From 131fbdd42cc70a19451d0080276cc7ae0de76077 Mon Sep 17 00:00:00 2001 From: Bertrand Marron Date: Tue, 3 Nov 2015 15:35:36 +0100 Subject: [PATCH 0001/2240] repro; #3521 --- test/schema.validation.test.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 36e19c49511..f9fadf03efc 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -757,6 +757,36 @@ describe('schema', function() { }); }); + it('should allow an array of subdocuments with enums (gh-3521)', function(done) { + var coolSchema = new Schema({ + votes: [{ + vote: { type: String, enum: ['cool', 'not-cool'] } + }] + }); + var Cool = mongoose.model('gh-3521', coolSchema, 'gh-3521'); + + var cool = new Cool(); + cool.votes.push(cool.votes.create({ + vote: 'cool' + })); + cool.validate(function(error) { + assert.ifError(error); + + var terrible = new Cool(); + terrible.votes.push(terrible.votes.create({ + vote: 'terrible' + })); + terrible.validate(function(error) { + assert.ok(error); + assert.ok(error.errors['votes.0.vote']); + assert.equal(error.errors['votes.0.vote'].message, + '`terrible` is not a valid enum value for path `vote`.'); + + done(); + }); + }); + }); + it('doesnt do double validation on document arrays (gh-2618)', function(done) { var A = new Schema({str: String}); var B = new Schema({a: [A]}); From 644c4826f8414a038d6e566deb31b64f46e3f203 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Nov 2015 10:12:57 -0500 Subject: [PATCH 0002/2240] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ad3238ab418..e78724fb621 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.4", + "version": "4.2.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 56671103800449f8012a68e34e04cefe178f51c0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Nov 2015 10:24:47 -0500 Subject: [PATCH 0003/2240] upgrade; node-mongodb-native -> 2.0.47 (Fix #3493) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e78724fb621..16d6689dd94 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.18", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.0.46", + "mongodb": "2.0.47", "mpath": "0.1.1", "mpromise": "0.5.4", "mquery": "1.6.3", From 78abaed1d0fe225a228dab22520e9d10d9802e4c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Nov 2015 11:05:07 -0500 Subject: [PATCH 0004/2240] repro; #3507 --- test/model.populate.test.js | 51 ++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index bfb706a3962..170d6fe5307 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -93,7 +93,7 @@ describe('model: populate:', function() { }); }); - it('deep population', function(done) { + it('deep population (gh-3103)', function(done) { var db = start() , BlogPost = db.model('RefBlogPost', posts) , User = db.model('RefUser', users); @@ -152,6 +152,55 @@ describe('model: populate:', function() { }); }); + it('deep population with refs (gh-3507)', function(done) { + var db = start(); + // handler schema + var handlerSchema = new Schema({ + name: String + }); + + // task schema + var taskSchema = new Schema({ + name: String, + handler: { type: Schema.Types.ObjectId, ref: 'gh3507_0' } + }); + + // application schema + var applicationSchema = new Schema({ + name: String, + tasks: [{ type: Schema.Types.ObjectId, ref: 'gh3507_1' }] + }); + + var Handler = db.model('gh3507_0', handlerSchema); + var Task = db.model('gh3507_1', taskSchema); + var Application = db.model('gh3507_2', applicationSchema); + + Handler.create({ name: 'test' }, function(error, doc) { + assert.ifError(error); + Task.create({ name: 'test2', handler: doc._id }, function(error, doc) { + assert.ifError(error); + var obj = { name: 'test3', tasks: [doc._id] }; + Application.create(obj, function(error, doc) { + assert.ifError(error); + test(doc._id); + }); + }); + }); + + function test(id) { + Application. + findById(id). + populate([ + { path: 'tasks', populate: { path: 'handler' } }, + ]). + exec(function(error, doc) { + assert.ifError(error); + assert.ok(doc.tasks[0].handler._id); + db.close(done); + }); + } + }); + it('populating a single ref', function(done) { var db = start() , BlogPost = db.model('RefBlogPost', posts) From 64fc228eb8504504b1db8112ec892871033efebd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Nov 2015 11:05:31 -0500 Subject: [PATCH 0005/2240] fix; get ref for deep populate (Fix #3507) --- lib/model.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/model.js b/lib/model.js index 7bb047fa989..d03a9612175 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2397,8 +2397,17 @@ function subPopulate(docs, options, cb) { subOptions._originalPath = subOptions.path; subOptions.path = prefix + subOptions.path; } + + var schema = model.schema._getSchema(prefix); if (typeof subOptions.model === 'string') { subOptions.model = model.model(subOptions.model); + } else if (schema && schema.caster && schema.caster.options && + schema.caster.options.ref) { + var subSchema = model.model(schema.caster.options.ref).schema. + _getSchema(subOptions._originalPath); + if (subSchema && subSchema.options && subSchema.options.ref) { + subOptions.model = model.model(subSchema.options.ref); + } } Model.populate.call(subOptions.model || model, docs, subOptions, next); }); From f3b837ca9d7ad9bec55f972d4f807617cb934c54 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Nov 2015 11:28:29 -0500 Subject: [PATCH 0006/2240] fix; handle embedded document markModified with no parent array (Fix #3521) --- lib/types/embedded.js | 2 +- test/schema.validation.test.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 4629bd85b3d..df694cf189f 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -57,9 +57,9 @@ EmbeddedDocument.prototype.constructor = EmbeddedDocument; */ EmbeddedDocument.prototype.markModified = function(path) { + this.$__.activePaths.modify(path); if (!this.__parentArray) return; - this.$__.activePaths.modify(path); if (this.isNew) { // Mark the WHOLE parent array as modified // if this is a new document (i.e., we are initializing diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index f9fadf03efc..3fbac7e8418 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -776,6 +776,7 @@ describe('schema', function() { terrible.votes.push(terrible.votes.create({ vote: 'terrible' })); + terrible.validate(function(error) { assert.ok(error); assert.ok(error.errors['votes.0.vote']); From 51c14f6e964a1af7908f8b8e1b85ab071e0f0a8c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Nov 2015 11:43:33 -0500 Subject: [PATCH 0007/2240] fix; ability to customize _id field for discriminators (Re: #3482) --- lib/model.js | 12 +++++++++--- test/model.discriminator.test.js | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/model.js b/lib/model.js index d03a9612175..109f510f8d1 100644 --- a/lib/model.js +++ b/lib/model.js @@ -811,19 +811,25 @@ Model.discriminator = function discriminator(name, schema) { delete a.toObject; delete b.toJSON; delete b.toObject; + delete a._id; + delete b._id; if (!utils.deepEqual(a, b)) { throw new Error("Discriminator options are not customizable " + - "(except toJSON & toObject)"); + "(except toJSON, toObject, _id)"); } })(schema.options, baseSchema.options); - var toJSON = schema.options.toJSON, - toObject = schema.options.toObject; + var toJSON = schema.options.toJSON; + var toObject = schema.options.toObject; + var _id = schema.options._id; schema.options = utils.clone(baseSchema.options); if (toJSON) schema.options.toJSON = toJSON; if (toObject) schema.options.toObject = toObject; + if (typeof _id !== 'undefined') { + schema.options._id = _id; + } schema.callQueue = baseSchema.callQueue.concat(schema.callQueue.slice(schema._defaultMiddleware.length)); schema._requiredpaths = undefined; // reset just in case Schema#requiredPaths() was called on either schema diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index e6930235cba..3b8ae9b6ed8 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -254,7 +254,7 @@ describe('model', function() { errorMessage = e.message; } - assert.equal(errorMessage, 'Discriminator options are not customizable (except toJSON & toObject)'); + assert.equal(errorMessage, 'Discriminator options are not customizable (except toJSON, toObject, _id)'); done(); }); }); From 802df912e18d59641d854aaf20c80df08227602c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Nov 2015 11:44:34 -0500 Subject: [PATCH 0008/2240] docs; add guide clarifying discriminator _id weirdness (Fix #3482) --- test/docs/discriminators.test.js | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index 942da175be6..ab82c29e39a 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -195,4 +195,45 @@ describe('discriminator docs', function() { }); }); }); + + /** + * A discriminator's fields are the union of the base schema's fields and + * the discriminator schema's fields, and the discriminator schema's fields + * take precedence. This behavior gets quirky when you have a custom `_id` + * field. A schema gets an `_id` field by default, so the base schema's + * `_id` field will get overridden by the discriminator schema's default + * `_id` field. + * + * You can work around this by setting the `_id` option to false in the + * discriminator schema as shown below. + */ + it('Handling custom _id fields', function(done) { + var options = { discriminatorKey: 'kind' }; + + // Base schema has a String _id... + var eventSchema = new mongoose.Schema({ _id: String, time: Date }, + options); + var Event = mongoose.model('BaseEvent', eventSchema); + + var clickedLinkSchema = new mongoose.Schema({ url: String }, options); + var ClickedLinkEvent = Event.discriminator('ChildEventBad', + clickedLinkSchema); + + var event1 = new ClickedLinkEvent(); + // Woops, clickedLinkSchema overwrote the custom _id + assert.ok(event1._id instanceof mongoose.Types.ObjectId); + + // But if you set `_id` option to false... + clickedLinkSchema = new mongoose.Schema({ url: String }, + { discriminatorKey: 'kind', _id: false }); + ClickedLinkEvent = Event.discriminator('ChildEventGood', + clickedLinkSchema); + + // The custom _id from the base schema comes through + var event2 = new ClickedLinkEvent({ _id: 'test' }); + assert.ok(event2._id.toString() === event2._id); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); }); From 8ae08b9c3ddd4acfc30254f10db6e38b40e032df Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Nov 2015 11:58:41 -0500 Subject: [PATCH 0009/2240] docs; basic docs covering single embedded subdocs (Fix #3495) --- docs/subdocs.jade | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/subdocs.jade b/docs/subdocs.jade index 5b54e2092eb..fbcd347e5f5 100644 --- a/docs/subdocs.jade +++ b/docs/subdocs.jade @@ -84,12 +84,36 @@ block content h4#altsyntax Alternate declaration syntax :markdown - _New in v3_ If you don't need access to the sub-document schema instance, + If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal: :js var parentSchema = new Schema({ children: [{ name: 'string' }] }) + + h4#single-embedded Single Embedded Subdocs + :markdown + **New in 4.2.0** + + You can also embed schemas without using arrays. + :js + var childSchema = new Schema({ name: 'string' }); + + var parentSchema = new Schema({ + child: childSchema + }); + :markdown + A single embedded sub-document behaves similarly to an embedded array. + It only gets saved when the parent document gets saved, and its pre/post + document middleware get executed. + :js + childSchema.pre('save', function(next) { + console.log(this.name); // prints 'Leia' + }); + var Parent = mongoose.model('Parent', parentSchema); + var parent = new Parent({ child: { name: 'Luke' } }) + parent.child.name = 'Leia'; + parent.save(callback); // Triggers the pre middleware. h3#next Next Up :markdown From 63ed80b1cd0874bfd36ae4e88a6991c5916b9c59 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 4 Nov 2015 10:48:02 -0500 Subject: [PATCH 0010/2240] repro; #3534 --- test/document.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index ec57dfcb77a..9e3b1a356ec 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2045,4 +2045,19 @@ describe('document', function() { }); }); }); + + it('single embedded schemas with methods (gh-3534)', function(done) { + var db = start(); + var personSchema = new Schema({ name: String }); + personSchema.methods.firstName = function() { + return this.name.substr(0, this.name.indexOf(' ')); + }; + + var bandSchema = new Schema({ leadSinger: personSchema }); + var Band = db.model('gh3534', bandSchema); + + var gnr = new Band({ leadSinger: { name: 'Axl Rose' } }); + assert.equal(gnr.leadSinger.firstName(), 'Axl'); + done(); + }); }); From b3472acb78550b5b8e916fe48b13a689c236614f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 4 Nov 2015 10:48:22 -0500 Subject: [PATCH 0011/2240] fix; apply methods to single embedded schemas (Fix #3534) --- lib/schema/embedded.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 283d79a8abf..7fda177e6f0 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -23,6 +23,16 @@ function Embedded(schema, path, options) { _embedded.$isSingleNested = true; _embedded.prototype.$basePath = path; + // apply methods + for (var i in schema.methods) { + _embedded.prototype[i] = schema.methods[i]; + } + + // apply statics + for (i in schema.statics) { + _embedded[i] = schema.statics[i]; + } + this.caster = _embedded; this.schema = schema; this.$isSingleNested = true; From ce11be0170956efe3bfd61f2ecf7863a2a642297 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 4 Nov 2015 11:14:32 -0500 Subject: [PATCH 0012/2240] repro; #3535 --- test/document.test.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/document.test.js b/test/document.test.js index 9e3b1a356ec..b032a0b4fb5 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2058,6 +2058,24 @@ describe('document', function() { var gnr = new Band({ leadSinger: { name: 'Axl Rose' } }); assert.equal(gnr.leadSinger.firstName(), 'Axl'); - done(); + db.close(done); + }); + + it('single embedded schemas with models (gh-3535)', function(done) { + var db = start(); + var personSchema = new Schema({ name: String }); + var Person = db.model('gh3535_0', personSchema); + + var bandSchema = new Schema({ leadSinger: personSchema }); + var Band = db.model('gh3535', bandSchema); + + var axl = new Person({ name: 'Axl Rose' }); + var gnr = new Band({ leadSinger: axl }); + + gnr.save(function(error, doc) { + assert.ifError(error); + assert.equal(gnr.leadSinger.name, 'Axl Rose'); + db.close(done); + }); }); }); From 0922d781259e03fdd9e4b9d930baad7350828643 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 4 Nov 2015 11:14:42 -0500 Subject: [PATCH 0013/2240] fix; call toObject() when setting single embedded schema to doc (Fix #3535) --- lib/document.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/document.js b/lib/document.js index 03372be3d42..ca0dfad6856 100644 --- a/lib/document.js +++ b/lib/document.js @@ -503,6 +503,11 @@ Document.prototype.set = function(path, val, type, options) { this.set(path[key], prefix + key, constructing); } else if (strict) { if ('real' === pathtype || 'virtual' === pathtype) { + // Check for setting single embedded schema to document (gh-3535) + if (this.schema.paths[pathName] && + this.schema.paths[pathName].$isSingleNested) { + path[key] = path[key].toObject({ virtuals: false }); + } this.set(prefix + key, path[key], constructing); } else if (pathtype === 'nested' && path[key] instanceof Document) { this.set(prefix + key, From 171e6945a4b498f89eeb82453cd71c916fddb689 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 4 Nov 2015 11:47:46 -0500 Subject: [PATCH 0014/2240] docs; deep populate docs (Fix #3528) --- docs/populate.jade | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/docs/populate.jade b/docs/populate.jade index f7140c6c191..8f031d8b545 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -190,11 +190,38 @@ block content h3#populate_an_existing_mongoose_document Populating an existing document :markdown - If we have an existing mongoose document and want to populate some of its paths, **mongoose >= 3.6** supports the [document#populate()](./api.html#document_Document-populate) method. + If we have an existing mongoose document and want to populate some of its + paths, **mongoose >= 3.6** supports the + [document#populate()](./api.html#document_Document-populate) method. h3#populate_multiple_documents Populating multiple existing documents :markdown - If we have one or many mongoose documents or even plain objects (_like [mapReduce](./api.html#model_Model.mapReduce) output_), we may populate them using the [Model.populate()](./api.html#model_Model.populate) method available in **mongoose >= 3.6**. This is what `document#populate()` and `query#populate()` use to populate documents. + If we have one or many mongoose documents or even plain objects + (_like [mapReduce](./api.html#model_Model.mapReduce) output_), we may + populate them using the [Model.populate()](./api.html#model_Model.populate) + method available in **mongoose >= 3.6**. This is what `document#populate()` + and `query#populate()` use to populate documents. + + h3#deep-populate Populating across multiple levels + :markdown + Say you have a user schema which keeps track of the user's friends. + :js + var userSchema = new Schema({ + name: String, + friends: [{ type: ObjectId, ref: 'User' }] + }); + :markdown + Populate lets you get a list of a user's friends, but what if you also + wanted a user's friends of friends? Specify the `populate` option to tell + mongoose to populate the `friends` array of all the user's friends: + :js + User. + findOne({ name: 'Val' }). + populate({ + path: 'friends', + // Get friends of friends - populate the 'friends' array for every friend + populate: { path: 'friends' } + }); h3#next Next Up :markdown From a2a3b8b337e954c06b62b6f7006ad4c7eea9e374 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Nov 2015 10:58:20 -0500 Subject: [PATCH 0015/2240] fix; issue with fix for #3535 --- lib/document.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index ca0dfad6856..674cc305cf8 100644 --- a/lib/document.js +++ b/lib/document.js @@ -505,7 +505,8 @@ Document.prototype.set = function(path, val, type, options) { if ('real' === pathtype || 'virtual' === pathtype) { // Check for setting single embedded schema to document (gh-3535) if (this.schema.paths[pathName] && - this.schema.paths[pathName].$isSingleNested) { + this.schema.paths[pathName].$isSingleNested && + path[key] instanceof Document) { path[key] = path[key].toObject({ virtuals: false }); } this.set(prefix + key, path[key], constructing); From cfc31945b3d2b1848e52d8c6e58925565e792060 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Nov 2015 10:59:28 -0500 Subject: [PATCH 0016/2240] repro; #3539 --- test/schema.validation.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 3fbac7e8418..6c1b341d3f1 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -1013,5 +1013,18 @@ describe('schema', function() { done(); }); }); + + it('skips conditional required (gh-3539)', function(done) { + var s = mongoose.Schema({ + n: { type: Number, required: function() { return false; }, min: 0 } + }); + var M = mongoose.model('gh3539', s); + + var m = new M(); + m.validate(function(error) { + assert.ifError(error); + done(); + }); + }); }); }); From a55fba7303c3196a60f9891f845ae7243b187e3c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Nov 2015 10:59:38 -0500 Subject: [PATCH 0017/2240] fix; allow undefined for min/max validators (Fix #3539) --- lib/schema/number.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/schema/number.js b/lib/schema/number.js index b9a65dcf948..7c427cfa37e 100644 --- a/lib/schema/number.js +++ b/lib/schema/number.js @@ -92,7 +92,7 @@ SchemaNumber.prototype.min = function(value, message) { msg = msg.replace(/{MIN}/, value); this.validators.push({ validator: this.minValidator = function(v) { - return v === null || v >= value; + return v == null || v >= value; }, message: msg, type: 'min', @@ -146,7 +146,7 @@ SchemaNumber.prototype.max = function(value, message) { msg = msg.replace(/{MAX}/, value); this.validators.push({ validator: this.maxValidator = function(v) { - return v === null || v <= value; + return v == null || v <= value; }, message: msg, type: 'max', From 4023f12f9a541e846bf98cac68f92368c4d6c95e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Nov 2015 11:37:26 -0500 Subject: [PATCH 0018/2240] docs; fix bad connection string example --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index b3b219c0812..1f7a654c12b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -199,7 +199,7 @@ Mongoose.prototype.createConnection = function(uri, options) { * mongoose.connect('mongodb://user:pass@localhost:port/database'); * * // replica sets - * var uri = 'mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port'; + * var uri = 'mongodb://user:pass@localhost:port,anotherhost:port,yetanother:port/mydatabase'; * mongoose.connect(uri); * * // with options From 043c9585944935be07f4859ca62b88882c716c10 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 6 Nov 2015 13:38:20 -0500 Subject: [PATCH 0019/2240] repro; #3537 --- test/connection.test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/connection.test.js b/test/connection.test.js index 3129c199843..cb5f3bf35f0 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -871,6 +871,12 @@ describe('connections:', function() { }); }); + it('connecting to single mongos (gh-3537)', function(done) { + var db = mongoose.createConnection('localhost:27017', { mongos: true }); + assert.ok(db.db.serverConfig instanceof mongoose.mongo.Mongos); + db.close(done); + }); + describe('connecting to multiple mongos nodes (gh-1037)', function() { var mongos = process.env.MONGOOSE_MULTI_MONGOS_TEST_URI; if (!mongos) return console.log('Not testing multi-mongos support'); From 352d80d1901db08f94796a7daec4a27a38110fa7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 6 Nov 2015 13:38:42 -0500 Subject: [PATCH 0020/2240] fix; ability to use mongos for standalones (Fix #3537) --- lib/drivers/node-mongodb-native/connection.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 617045543ec..215146b67aa 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -45,7 +45,13 @@ NativeConnection.prototype.__proto__ = MongooseConnection.prototype; NativeConnection.prototype.doOpen = function(fn) { var server = new Server(this.host, this.port, this.options.server); - this.db = new Db(this.name, server, this.options.db); + + if (this.options && this.options.mongos) { + var mongos = new Mongos([server], this.options.mongos); + this.db = new Db(this.name, mongos, this.options.db); + } else { + this.db = new Db(this.name, server, this.options.db); + } var self = this; this.db.open(function(err) { From aac346a37bff59fbf174d32394fcf3932b44363c Mon Sep 17 00:00:00 2001 From: Christian Murphy Date: Sat, 7 Nov 2015 08:58:53 -0700 Subject: [PATCH 0021/2240] Update README examples to comma last style alphabetize lint rules resolve new lint warnings --- .eslintrc | 17 ++++++------ README.md | 42 ++++++++++++++--------------- test/docs/promises.test.js | 1 - test/document.test.js | 2 +- test/model.findOneAndUpdate.test.js | 14 +++++----- test/model.populate.test.js | 2 +- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/.eslintrc b/.eslintrc index b48ed430078..99f448b31b9 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,15 +5,21 @@ env: mocha: true rules: + comma-style: 2 + consistent-this: + - 1 + - _this indent: - 2 - 2 - SwitchCase: 1 VariableDeclarator: 2 - no-trailing-spaces: 2 - comma-style: 2 - no-spaced-func: 2 + key-spacing: 1 + no-console: 0 no-multi-spaces: 1 + no-spaced-func: 2 + no-trailing-spaces: 2 + semi: 2 space-after-keywords: 2 space-before-blocks: 2 space-before-function-paren: @@ -23,8 +29,3 @@ rules: space-infix-ops: 2 space-return-throw-case: 2 space-unary-ops: 1 - no-console: 0 - consistent-this: - - 1 - - _this - semi: 2 diff --git a/README.md b/README.md index 0e9a7512a98..fd8077d4630 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/my_database'); ``` -Once connected, the `open` event is fired on the `Connection` instance. If you're using `mongoose.connect`, the `Connection` is `mongoose.connection`. Otherwise, `mongoose.createConnection` return value is a `Connection`. +Once connected, the `open` event is fired on the `Connection` instance. If you're using `mongoose.connect`, the `Connection` is `mongoose.connection`. Otherwise, `mongoose.createConnection` return value is a `Connection`. **Note:** _If the local connection fails then try using 127.0.0.1 instead of localhost. Sometimes issues may arise when the local hostname has been changed._ @@ -68,14 +68,14 @@ Once connected, the `open` event is fired on the `Connection` instance. If you'r Models are defined through the `Schema` interface. ```js -var Schema = mongoose.Schema - , ObjectId = Schema.ObjectId; +var Schema = mongoose.Schema, + ObjectId = Schema.ObjectId; var BlogPost = new Schema({ - author : ObjectId - , title : String - , body : String - , date : Date + author : ObjectId, + title : String, + body : String, + date : Date }); ``` @@ -96,11 +96,11 @@ The following example shows some of these features: ```js var Comment = new Schema({ - name : { type: String, default: 'hahaha' } - , age : { type: Number, min: 18, index: true } - , bio : { type: String, match: /[a-z]/ } - , date : { type: Date, default: Date.now } - , buff : Buffer + name : { type: String, default: 'hahaha' }, + age : { type: Number, min: 18, index: true }, + bio : { type: String, match: /[a-z]/ }, + date : { type: Date, default: Date.now }, + buff : Buffer }); // a setter @@ -269,19 +269,19 @@ Moreover, you can mutate the incoming `method` arguments so that subsequent midd ```js new Schema({ - broken: { type: Boolean } - , asset : { - name: String - , type: String // uh oh, it broke. asset will be interpreted as String + broken: { type: Boolean }, + asset : { + name: String, + type: String // uh oh, it broke. asset will be interpreted as String } }); new Schema({ - works: { type: Boolean } - , asset : { - name: String - , type: { type: String } // works. asset is an object with a type property - } + works: { type: Boolean }, + asset : { + name: String, + type: { type: String } // works. asset is an object with a type property + } }); ``` diff --git a/test/docs/promises.test.js b/test/docs/promises.test.js index b7031dae2b0..3497c07337d 100644 --- a/test/docs/promises.test.js +++ b/test/docs/promises.test.js @@ -1,6 +1,5 @@ var PromiseProvider = require('../../lib/promise_provider'); var assert = require('assert'); -var async = require('async'); var mongoose = require('../../'); describe('promises docs', function() { diff --git a/test/document.test.js b/test/document.test.js index b032a0b4fb5..7088ea7c1ac 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2072,7 +2072,7 @@ describe('document', function() { var axl = new Person({ name: 'Axl Rose' }); var gnr = new Band({ leadSinger: axl }); - gnr.save(function(error, doc) { + gnr.save(function(error) { assert.ifError(error); assert.equal(gnr.leadSinger.name, 'Axl Rose'); db.close(done); diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index fdc25295b23..e78d9fe9325 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1481,9 +1481,9 @@ describe('model: findByIdAndUpdate:', function() { var db = start(); var recordSchema = new mongoose.Schema({ kind: String, - amount: Number, + amount: Number }, { - _id: false, + _id: false }); var shiftSchema = new mongoose.Schema({ @@ -1495,14 +1495,14 @@ describe('model: findByIdAndUpdate:', function() { Shift.create({ userId: 'tom', - records: [], - }, function(error, shift) { + records: [] + }, function(error) { assert.ifError(error); Shift.findOneAndUpdate({userId: 'tom'}, { - records: [{kind: 'kind1', amount: NaN}], + records: [{kind: 'kind1', amount: NaN}] }, { - 'new': true, - }, function(error, shift) { + 'new': true + }, function(error) { assert.ok(error); assert.ok(error instanceof CastError); db.close(done); diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 170d6fe5307..58fc1ec5282 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -191,7 +191,7 @@ describe('model: populate:', function() { Application. findById(id). populate([ - { path: 'tasks', populate: { path: 'handler' } }, + { path: 'tasks', populate: { path: 'handler' } } ]). exec(function(error, doc) { assert.ifError(error); From fc3f645bfeac6e72667d34dffbe33f68db8f69a0 Mon Sep 17 00:00:00 2001 From: Christian Murphy Date: Sat, 7 Nov 2015 09:04:59 -0700 Subject: [PATCH 0022/2240] update ESLint and add a lint script to the package.json add npm-debug.log to the list of ignored files --- .gitignore | 1 + package.json | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6386a6bf953..c9eae254b4c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ test/triage/*.js /inspections bin/mongoose.min.js coverage +npm-debug.log # Visual Studio # ========= diff --git a/package.json b/package.json index 16d6689dd94..619cfa263a5 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "bluebird": "2.9.34", "co": "3.1.0", "dox": "0.3.1", - "eslint": "1.7.3", + "eslint": "1.9.0", "highlight.js": "7.0.1", "istanbul": "^0.3.13", "jade": "0.26.3", @@ -67,7 +67,8 @@ "scripts": { "install-browser": "npm install `node format_deps.js`", "test": "mocha --async-only test/*.test.js test/**/*.test.js", - "test-cov": "istanbul cover _mocha --async-only test/*.test.js" + "test-cov": "istanbul cover _mocha --async-only test/*.test.js", + "lint": "eslint . --quiet" }, "main": "./index.js", "engines": { From 6d0df2f7ae5dabb1843e2026fd4181f203d7a8fc Mon Sep 17 00:00:00 2001 From: Christian Murphy Date: Sat, 7 Nov 2015 09:18:40 -0700 Subject: [PATCH 0023/2240] Test against Node 4 LTS and Node 5 Stable --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a8086538480..dcdb2c7d4db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: node_js sudo: false node_js: - - "4.0" + - "5" + - "4" - "0.12" - "0.10" - "iojs" From 6ff39efaa9d1f0a1ba0c11f1e3092ec4c6ca107a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 Nov 2015 18:05:23 -0500 Subject: [PATCH 0024/2240] fix; unhandled rejection using Query.then() (Fix #3543) --- lib/query.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/query.js b/lib/query.js index 591f75bfe0f..97ac7090c1b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2134,6 +2134,20 @@ Query.prototype.exec = function exec(op, callback) { }); }; +/** + * Executes the query returning a `Promise` which will be + * resolved with either the doc(s) or rejected with the error. + * + * @param {Function} [resolve] + * @param {Function} [reject] + * @return {Promise} + * @api public + */ + +Query.prototype.then = function(resolve, reject) { + return this.exec().then(resolve, reject); +} + /** * Finds the schema for `path`. This is different than * calling `schema.path` as it also resolves paths with From 932cdbe1ef31c3befb10417bd060276d5fa3c0f5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Nov 2015 10:41:43 -0500 Subject: [PATCH 0025/2240] upgrade; node driver -> 2.0.48 (re: #3544) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 619cfa263a5..cce61bc378e 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.18", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.0.47", + "mongodb": "2.0.48", "mpath": "0.1.1", "mpromise": "0.5.4", "mquery": "1.6.3", From b5329a17998668878e74ba8ec4295d605a2cdc57 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Nov 2015 13:14:59 -0500 Subject: [PATCH 0026/2240] repro; #3221 --- test/model.update.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 8adae58b7a3..073d3b21936 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1608,4 +1608,19 @@ describe('model: update:', function() { db.close(done); }); }); + + it('.update(doc) (gh-3221)', function(done) { + var db = start(); + + var Schema = mongoose.Schema({ name: String }); + var Model = db.model('gh3412', Schema); + + var query = Model.update({ name: 'Val' }); + assert.equal(query.getUpdate().$set.name, 'Val'); + + query = Model.find().update({ name: 'Val' }); + assert.equal(query.getUpdate().$set.name, 'Val'); + + db.close(done); + }); }); From 73de49ca8e9066996335bbeda84cca9a5d7dfd15 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Nov 2015 13:17:03 -0500 Subject: [PATCH 0027/2240] fix; proper support for .update(doc) (Fix #3221) --- lib/query.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index 97ac7090c1b..0fb038b1ec7 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1989,20 +1989,27 @@ Query.prototype._execUpdate = function(castedQuery, castedDoc, options, callback Query.prototype.update = function(conditions, doc, options, callback) { if ('function' === typeof options) { - // Scenario: update(conditions, doc, callback) + // .update(conditions, doc, callback) callback = options; options = null; } else if ('function' === typeof doc) { - // Scenario: update(doc, callback); + // .update(doc, callback); callback = doc; doc = conditions; conditions = {}; options = null; } else if ('function' === typeof conditions) { + // .update(callback) callback = conditions; conditions = undefined; doc = undefined; options = undefined; + } else if (typeof conditions === 'object' && !doc && !options && !callback) { + // .update(doc) + doc = conditions; + conditions = undefined; + options = undefined; + callback = undefined; } // make sure we don't send in the whole Document to merge() From f0b0f6161a2ad9676c71a92bb0f5f69f010ab01b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Nov 2015 13:32:23 -0500 Subject: [PATCH 0028/2240] repro; #3554 --- test/updateValidators.unit.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/updateValidators.unit.test.js b/test/updateValidators.unit.test.js index e1424e1cb60..db547c075d1 100644 --- a/test/updateValidators.unit.test.js +++ b/test/updateValidators.unit.test.js @@ -53,5 +53,20 @@ describe('updateValidators', function() { done(); }); }); + + it('doesnt flatten empty arrays (gh-3554)', function(done) { + var fn = updateValidators({}, schema, { test: [] }, {}); + schema.doValidate.emitter.on('called', function(args) { + args.cb(); + }); + fn(function(err) { + assert.ifError(err); + assert.equal(schema._getSchema.calls.length, 1); + assert.equal(schema.doValidate.calls.length, 1); + assert.equal('test', schema._getSchema.calls[0]); + assert.deepEqual(schema.doValidate.calls[0].v, []); + done(); + }); + }); }); }); From 68e394d9c1bbd4374552746269d0dc1bb5cf397e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Nov 2015 13:32:42 -0500 Subject: [PATCH 0029/2240] fix; dont flatten empty arrays in updateValidators (Fix #3554) --- lib/services/updateValidators.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 5b0b5d2cf1c..5d6347e06e6 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -159,7 +159,6 @@ function modifiedPaths(update, path, result) { var val = update[key]; result[path + key] = true; - if (shouldFlatten(val)) { modifiedPaths(val, path + key, result); } @@ -194,5 +193,6 @@ function shouldFlatten(val) { return val && typeof val === 'object' && !(val instanceof Date) && - !(val instanceof ObjectId); + !(val instanceof ObjectId) && + (!Array.isArray(val) || val.length > 0); } From 5e58d8305456453021e3e7b71974a3e7e39fc9d5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Nov 2015 15:10:01 -0500 Subject: [PATCH 0030/2240] repro; #3549 --- test/model.update.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 073d3b21936..f5b02368b65 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1623,4 +1623,29 @@ describe('model: update:', function() { db.close(done); }); + + it('middleware update with exec (gh-3549)', function(done) { + var db = start(); + + var Schema = mongoose.Schema({ name: String }); + + Schema.pre('update', function(next) { + this.update({ name: 'Val' }); + next(); + }); + + var Model = db.model('gh3549', Schema); + + Model.create({}, function(error, doc) { + assert.ifError(error); + Model.update({ _id: doc._id }, { name: 'test' }).exec(function(error) { + assert.ifError(error); + Model.findOne({ _id: doc._id }, function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Val'); + db.close(done); + }); + }); + }); + }); }); From fae7c94b9835a102c1c2fc29f0054967212d191e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Nov 2015 15:10:22 -0500 Subject: [PATCH 0031/2240] fix; correctly handle changes in update hook (Fix #3549) --- lib/query.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/query.js b/lib/query.js index 0fb038b1ec7..f9618746633 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1875,21 +1875,21 @@ function convertSortToArray(opts) { } /** - * Internal helper for update + * Internal thunk for .update() * - * @param {Object} castedQuery - * @param {Object} castedDoc the update command - * @param {Object} options * @param {Function} callback - * @return {Query} this * @see Model.update #model_Model.update * @api private */ -Query.prototype._execUpdate = function(castedQuery, castedDoc, options, callback) { +Query.prototype._execUpdate = function(callback) { var schema = this.model.schema; var doValidate; var _this; + var castedQuery = this._conditions; + var castedDoc = this._update; + var options = this.options; + if (this._castError) { callback(this._castError); return this; @@ -2088,7 +2088,7 @@ Query.prototype.update = function(conditions, doc, options, callback) { // Hooks if (callback) { - return this._execUpdate(castedQuery, castedDoc, options, callback); + return this._execUpdate(callback); } return Query.base.update.call(this, castedQuery, castedDoc, options, callback); From de88912969017e20cda78a3b98dac27caa781bf1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Nov 2015 15:21:42 -0500 Subject: [PATCH 0032/2240] release 4.2.5 --- History.md | 16 ++++++++++++++++ bin/mongoose.js | 22 +++++++++++++++++++--- package.json | 2 +- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index c683bc258d4..6804dadba7c 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,19 @@ +4.2.5 / 2015-11-09 +================== + * fixed; handle setting fields in pre update hooks with exec #3549 + * upgraded; ESLint #3547 [ChristianMurphy](https://github.com/ChristianMurphy) + * fixed; bluebird unhandled rejections with cast errors and .exec #3543 + * fixed; min/max validators handling undefined #3539 + * fixed; standalone mongos connections #3537 + * fixed; call `.toObject()` when setting a single nested doc #3535 + * fixed; single nested docs now have methods #3534 + * fixed; single nested docs with .create() #3533 #3521 [tusbar](https://github.com/tusbar) + * docs; deep populate docs #3528 + * fixed; deep populate schema ref handling #3507 + * upgraded; mongodb driver -> 2.0.48 for sort overflow issue #3493 + * docs; clarify default ids for discriminators #3482 + * fixed; properly support .update(doc) #3221 + 4.2.4 / 2015-11-02 ================== * fixed; upgraded `ms` package for security vulnerability #3254 [fhemberger](https://github.com/fhemberger) diff --git a/bin/mongoose.js b/bin/mongoose.js index dde322039e0..97ba711e029 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -956,6 +956,12 @@ Document.prototype.set = function(path, val, type, options) { this.set(path[key], prefix + key, constructing); } else if (strict) { if ('real' === pathtype || 'virtual' === pathtype) { + // Check for setting single embedded schema to document (gh-3535) + if (this.schema.paths[pathName] && + this.schema.paths[pathName].$isSingleNested && + path[key] instanceof Document) { + path[key] = path[key].toObject({ virtuals: false }); + } this.set(prefix + key, path[key], constructing); } else if (pathtype === 'nested' && path[key] instanceof Document) { this.set(prefix + key, @@ -6122,6 +6128,16 @@ function Embedded(schema, path, options) { _embedded.$isSingleNested = true; _embedded.prototype.$basePath = path; + // apply methods + for (var i in schema.methods) { + _embedded.prototype[i] = schema.methods[i]; + } + + // apply statics + for (i in schema.statics) { + _embedded[i] = schema.statics[i]; + } + this.caster = _embedded; this.schema = schema; this.$isSingleNested = true; @@ -6396,7 +6412,7 @@ SchemaNumber.prototype.min = function(value, message) { msg = msg.replace(/{MIN}/, value); this.validators.push({ validator: this.minValidator = function(v) { - return v === null || v >= value; + return v == null || v >= value; }, message: msg, type: 'min', @@ -6450,7 +6466,7 @@ SchemaNumber.prototype.max = function(value, message) { msg = msg.replace(/{MAX}/, value); this.validators.push({ validator: this.maxValidator = function(v) { - return v === null || v <= value; + return v == null || v <= value; }, message: msg, type: 'max', @@ -9639,9 +9655,9 @@ EmbeddedDocument.prototype.constructor = EmbeddedDocument; */ EmbeddedDocument.prototype.markModified = function(path) { + this.$__.activePaths.modify(path); if (!this.__parentArray) return; - this.$__.activePaths.modify(path); if (this.isNew) { // Mark the WHOLE parent array as modified // if this is a new document (i.e., we are initializing diff --git a/package.json b/package.json index cce61bc378e..d3c080e53e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.5-pre", + "version": "4.2.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 9c048d2466117c4e0f047f848c044ccbf6c643c0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 Nov 2015 09:46:18 -0500 Subject: [PATCH 0033/2240] now working on 4.2.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d3c080e53e8..8bc69b8efae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.5", + "version": "4.2.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e863c100354f47a27ffdff64758ac62d081c3482 Mon Sep 17 00:00:00 2001 From: Amaury Date: Tue, 10 Nov 2015 11:57:48 -0300 Subject: [PATCH 0034/2240] Minor grammar fix in populate documentation --- docs/populate.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/populate.jade b/docs/populate.jade index 8f031d8b545..115def52e59 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -26,7 +26,7 @@ block content var Story = mongoose.model('Story', storySchema); var Person = mongoose.model('Person', personSchema); :markdown - So far we've created two [Models](./models.html). Our `Person` model has it's `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose which model to use during population, in our case the `Story` model. All `_id`s we store here must be document `_id`s from the `Story` model. We also declared the `Story` `_creator` property as a `Number`, the same type as the `_id` used in the `personSchema`. It is important to match the type of `_id` to the type of ref. + So far we've created two [Models](./models.html). Our `Person` model has its `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose which model to use during population, in our case the `Story` model. All `_id`s we store here must be document `_id`s from the `Story` model. We also declared the `Story` `_creator` property as a `Number`, the same type as the `_id` used in the `personSchema`. It is important to match the type of `_id` to the type of ref. .important :markdown **Note**: `ObjectId`, `Number`, `String`, and `Buffer` are valid for use as refs. From d76fe3d5f7a063798b11e562ceb9d57019da073e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 Nov 2015 14:45:55 -0500 Subject: [PATCH 0035/2240] repro; #3560 --- test/schema.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 50db2a42084..d5ba87754c4 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1453,6 +1453,22 @@ describe('schema', function() { done(); }); + it('custom typeKey in doc arrays (gh-3560)', function(done) { + var schema = Schema({ + test: [{ + name: { $type: String } + }] + }, { typeKey: '$type' }); + + schema.path('test').schema.path('name').required(true); + var M = mongoose.model('gh3560', schema); + var m = new M({ test: [{ name: 'Val' }] }); + + assert.ifError(m.validateSync()); + assert.equal(m.test[0].name, 'Val'); + done(); + }); + describe('remove()', function() { before(function() { From 6a431625339c2d9ee30425201f65c474e7aa6653 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 Nov 2015 14:46:30 -0500 Subject: [PATCH 0036/2240] fix; inline doc arrays inherit parents typeKey (Fix #3560) --- lib/schema.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index fddc66ff8a4..fb7ede29fd0 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -543,8 +543,16 @@ Schema.interpretAsType = function(path, obj, options) { } else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type)) && 'Object' == utils.getFunctionName(cast.constructor) && Object.keys(cast).length) { - var opts = { minimize: options.minimize }; - return new MongooseTypes.DocumentArray(path, new Schema(cast, opts), obj); + + // The `minimize` and `typeKey` options propagate to child schemas + // declared inline, like `{ arr: [{ val: { $type: String } }] }`. + // See gh-3560 + var childSchemaOptions = { minimize: options.minimize }; + if (options.typeKey) { + childSchemaOptions.typeKey = options.typeKey; + } + var childSchema = new Schema(cast, childSchemaOptions); + return new MongooseTypes.DocumentArray(path, childSchema, obj); } return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj); From 79797da7e728345ba3f4e18548050102ebf2e4d5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 Nov 2015 15:01:42 -0500 Subject: [PATCH 0037/2240] repro; #3562 --- test/schema.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index d5ba87754c4..0b80be8ccde 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1469,6 +1469,27 @@ describe('schema', function() { done(); }); + it('required for single nested schemas (gh-3562)', function(done) { + var personSchema = Schema({ + name: { type: String, required: true } + }); + + var bandSchema = Schema({ + name: String, + guitarist: { type: personSchema, required: true } + }); + + var Band = mongoose.model('gh3562', bandSchema); + var band = new Band({ name: "Guns N' Roses" }); + + assert.ok(band.validateSync()); + assert.ok(band.validateSync().errors['guitarist']); + band.guitarist = { name: 'Slash' }; + assert.ifError(band.validateSync()); + + done(); + }); + describe('remove()', function() { before(function() { From edd28b4e511c92e5429e4d91752962c343ff26be Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 Nov 2015 15:02:43 -0500 Subject: [PATCH 0038/2240] fix; validation for single nested schemas (Fix #3562) --- lib/schema/embedded.js | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 7fda177e6f0..699b81a1378 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -78,10 +78,41 @@ Embedded.prototype.castForQuery = function($conditional, val) { } }; +/** + * Async validation on this single nested doc. + * + * @api private + */ + Embedded.prototype.doValidate = function(value, fn) { - value.validate(fn, { __noPromise: true }); + SchemaType.prototype.doValidate.call(this, value, function(error) { + if (error) { + return fn(error); + } + value.validate(fn, { __noPromise: true }); + }); }; +/** + * Synchronously validate this single nested doc + * + * @api private + */ + Embedded.prototype.doValidateSync = function(value) { + var schemaTypeError = SchemaType.prototype.doValidateSync.call(this, value); + if (schemaTypeError) { + return schemaTypeError; + } return value.validateSync(); }; + +/** + * Required validator for single nested docs + * + * @api private + */ + +Embedded.prototype.checkRequired = function(value) { + return !!value && value.$isSingleNested; +}; From 36f21356f57c49c0db882a3c9d6b10d9dc37e315 Mon Sep 17 00:00:00 2001 From: John Peberdy Date: Tue, 10 Nov 2015 18:37:56 -0500 Subject: [PATCH 0039/2240] Fix issue encountered with custom id type that contains a buffer modifiedPaths() walks the object structure, encounters the Buffer, then encounters the parent of the buffer, which hangs the server for up to 30 seconds. --- lib/services/updateValidators.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 698aaabf445..e415ea3d8d0 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -174,5 +174,6 @@ function shouldFlatten(val) { return val && typeof val === 'object' && !(val instanceof Date) && - !(val instanceof ObjectId); + !(val instanceof ObjectId) && + !(val instanceof Buffer); } From 5151c83ad15af2abb102d61da26f0db4584b182a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 11 Nov 2015 10:00:15 -0500 Subject: [PATCH 0040/2240] repro; #3564 --- test/model.update.test.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index f5b02368b65..fbbd0231370 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1648,4 +1648,39 @@ describe('model: update:', function() { }); }); }); + + it('casting $push with overwrite (gh-3564)', function(done) { + var db = start(); + + var schema = mongoose.Schema({ + topicId: Number, + name: String, + followers: [Number] + }); + + var doc = { + topicId: 100, + name: 'name', + followers: [500] + }; + + var M = db.model('gh-3564', schema); + + M.create(doc, function(err, topic) { + assert.ifError(err); + + var update = { $push: { followers: 200 } }; + var opts = { overwrite: true, new: true, safe: true, upsert: false, multi: false}; + + M.update({ topicId: doc.topicId }, update, opts, function(err) { + assert.ifError(err); + M.findOne({ topicId: doc.topicId }, function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'name'); + assert.deepEqual(doc.followers.toObject(), [500, 200]); + db.close(done); + }); + }) + }); + }); }); From 4b15d39a3902d5366c1e6ab988afcdc44a3429f9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 11 Nov 2015 10:00:56 -0500 Subject: [PATCH 0041/2240] fix; update casting for $ keys (Fix #3564) re: #3546 --- lib/query.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/query.js b/lib/query.js index f9618746633..96810c13ad5 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2200,13 +2200,16 @@ var numberOps = { */ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) { - if (!obj) return undefined; + if (!obj) { + return undefined; + } - var ops = Object.keys(obj), - i = ops.length, - ret = {}, - hasKeys, - val; + var ops = Object.keys(obj); + var i = ops.length; + var ret = {}; + var hasKeys; + var val; + var hasDollarKey = false; while (i--) { var op = ops[i]; @@ -2244,7 +2247,10 @@ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) { while (i--) { op = ops[i]; val = ret[op]; - if (val && 'Object' === val.constructor.name && !overwrite) { + hasDollarKey = hasDollarKey || op.charAt(0) === '$'; + if (val && + val.constructor.name === 'Object' && + (!overwrite || hasDollarKey)) { hasKeys |= this._walkUpdatePath(val, op); } else if (overwrite && 'Object' === ret.constructor.name) { // if we are just using overwrite, cast the query and then we will @@ -2253,7 +2259,7 @@ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) { // user passes {} and wants to clobber the whole document // Also, _walkUpdatePath expects an operation, so give it $set since that // is basically what we're doing - this._walkUpdatePath(ret.$set || ret, '$set'); + this._walkUpdatePath(ret, '$set'); } else { var msg = 'Invalid atomic update value for ' + op + '. ' + 'Expected an object, received ' + typeof val; From 0fe9864ee0ce109db8ebae316d3b8ca71f7b5c0b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Nov 2015 12:32:38 -0500 Subject: [PATCH 0042/2240] docs; add ids to middleware guide headers --- docs/middleware.jade | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/middleware.jade b/docs/middleware.jade index bb8567083fc..7cbc02dd902 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -31,10 +31,10 @@ block content If you set a 'remove' hook, it will be fired when you call `myDoc.remove()`, not when you call `MyModel.remove()`. - h3 Pre + h3#pre Pre :markdown There are two types of `pre` hooks, serial and parallel. - h4 Serial + h4#serial Serial :markdown Serial middleware are executed one after another, when each middleware calls `next`. :js @@ -43,7 +43,7 @@ block content // do stuff next(); }); - h4 Parallel + h4#parallel Parallel p | Parallel middleware offer more fine-grained flow control. :js @@ -55,7 +55,7 @@ block content }); :markdown The hooked method, in this case `save`, will not be executed until `done` is called by each middleware. - h4 Use Cases + h4#use-cases Use Cases p | Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas: ul @@ -69,7 +69,7 @@ block content ul li triggering custom events li notifications - h4 Error handling + h4#error-handling Error handling :markdown If any middleware calls `next` or `done` with an error, the flow is interrupted, and the error is passed to the callback. From a57b1f168c21a7196cad40b14458ee91b4cd25f0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Nov 2015 14:48:37 -0500 Subject: [PATCH 0043/2240] fix; use captureStackTrace when possible (Fix #3571) --- lib/error/cast.js | 6 +++++- lib/error/validation.js | 6 +++++- lib/error/validator.js | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/error/cast.js b/lib/error/cast.js index 65da189232a..266858c5d1c 100644 --- a/lib/error/cast.js +++ b/lib/error/cast.js @@ -15,7 +15,11 @@ var MongooseError = require('../error.js'); function CastError(type, value, path, reason) { MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '" at path "' + path + '"'); - this.stack = new Error().stack; + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack + } this.name = 'CastError'; this.kind = type; this.value = value; diff --git a/lib/error/validation.js b/lib/error/validation.js index b574455ac95..41b11439ad3 100644 --- a/lib/error/validation.js +++ b/lib/error/validation.js @@ -19,7 +19,11 @@ function ValidationError(instance) { } else { MongooseError.call(this, "Validation failed"); } - this.stack = new Error().stack; + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack + } this.name = 'ValidationError'; this.errors = {}; if (instance) { diff --git a/lib/error/validator.js b/lib/error/validator.js index 3f1c67f9126..ca605b8c3e3 100644 --- a/lib/error/validator.js +++ b/lib/error/validator.js @@ -22,7 +22,11 @@ function ValidatorError(properties) { this.properties = properties; var message = this.formatMessage(msg, properties); MongooseError.call(this, message); - this.stack = new Error().stack; + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack + } this.name = 'ValidatorError'; this.kind = properties.type; this.path = properties.path; From f78e398e1c8305f75946f1db59b22981a74e4a88 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Nov 2015 14:58:57 -0500 Subject: [PATCH 0044/2240] fix; missed fix for #3571 in one place --- lib/error.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/error.js b/lib/error.js index d08980eab19..ace45653ab3 100644 --- a/lib/error.js +++ b/lib/error.js @@ -8,7 +8,11 @@ function MongooseError(msg) { Error.call(this); - this.stack = new Error().stack; + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack + } this.message = msg; this.name = 'MongooseError'; } From 23ff015d9e33b68b1046bdc638772dca9ac61f49 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Nov 2015 15:26:38 -0500 Subject: [PATCH 0045/2240] repro; #2321 --- test/model.populate.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 58fc1ec5282..be27a9c9621 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3051,4 +3051,31 @@ describe('model: populate:', function() { }); }); }); + + it('populate option (gh-2321)', function(done) { + var db = start(); + + var User = db.model('User', { name: String }); + var Group = db.model('Group', { + users: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }], + name: String + }); + + User.create({ name: 'Val' }, function(error, user) { + assert.ifError(error); + Group.create({ users: [user._id], name: 'test' }, function(error, group) { + assert.ifError(error); + test(group._id); + }); + }); + + var test = function(id) { + var options = { populate: { path: 'users', model: 'User' } }; + Group.find({ _id: id }, '-name', options, function(error, group) { + assert.ifError(error); + assert.ok(group[0].users[0]._id); + db.close(done); + }); + }; + }); }); From 168f516902bf142006581479d58d19867fb844e8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Nov 2015 15:27:19 -0500 Subject: [PATCH 0046/2240] fix; use setOption for find and findOne (Fix #2321) --- lib/model.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index 109f510f8d1..f8d9b08cf4e 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1128,8 +1128,9 @@ Model.find = function find(conditions, projection, options, callback) { } // get the raw mongodb collection object - var mq = new Query({}, options, this, this.collection); + var mq = new Query({}, {}, this, this.collection); mq.select(projection); + mq.setOptions(options); if (this.schema.discriminatorMapping && mq.selectedInclusively()) { mq.select(this.schema.options.discriminatorKey); } @@ -1243,8 +1244,9 @@ Model.findOne = function findOne(conditions, projection, options, callback) { } // get the mongodb collection object - var mq = new Query({}, options, this, this.collection); + var mq = new Query({}, {}, this, this.collection); mq.select(projection); + mq.setOptions(options); if (this.schema.discriminatorMapping && mq.selectedInclusively()) { mq.select(this.schema.options.discriminatorKey); } From 19c801f39d1ffbec9a82935391ca8b4f11084c97 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Nov 2015 15:33:38 -0500 Subject: [PATCH 0047/2240] now working on 3.8.37 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b99d2b5ad8..c82f1af2aa0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose" , "description": "Mongoose MongoDB ODM" - , "version": "3.8.36" + , "version": "3.8.37-pre" , "author": "Guillermo Rauch " , "keywords": ["mongodb", "document", "model", "schema", "database", "odm", "data", "datastore", "query", "nosql", "orm", "db"] , "dependencies": { From a787cc16b863c59cbce76464876850c8a3c1cf59 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Nov 2015 15:33:52 -0500 Subject: [PATCH 0048/2240] fix; use retainKeyOrder for castedDoc in 3.8 (Fix #3572) --- lib/query.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 6ec4b6fbbd2..415cd86eb20 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1757,7 +1757,7 @@ Query.prototype.update = function (conditions, doc, options, callback) { // validate the update part of the query var castedDoc; try { - castedDoc = this._castUpdate(utils.clone(doc), + castedDoc = this._castUpdate(utils.clone(doc, { retainKeyOrder: true }), options && options.overwrite); } catch (err) { if (callback) { From 6e1815550bec1c970f294c175a8ad1dab4c5398a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Nov 2015 12:10:49 -0500 Subject: [PATCH 0049/2240] repro; #3575 --- test/document.modified.test.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/document.modified.test.js b/test/document.modified.test.js index 669831ed026..8e942356c61 100644 --- a/test/document.modified.test.js +++ b/test/document.modified.test.js @@ -369,7 +369,7 @@ describe('document modified', function() { var parentSchema = new Schema({ name: String, - child: { type: Schema.Types.ObjectId, ref: 'Child'} + child: { type: Schema.Types.ObjectId, ref: 'Child' } }); var Parent = db.model('Parent', parentSchema, 'parents'); @@ -382,6 +382,25 @@ describe('document modified', function() { db.close(done); }); + it('gh-1530 for arrays (gh-3575)', function(done) { + var db = start(); + + var parentSchema = new Schema({ + name: String, + children: [{ type: Schema.Types.ObjectId, ref: 'Child' }] + }); + + var Parent = db.model('Parent', parentSchema, 'parents'); + var Child = db.model('Child', parentSchema, 'children'); + + var child = new Child({ name: 'Luke' }); + var p = new Parent({ name: 'Anakin', children: [child] }); + + assert.equal(p.children[0].name, 'Luke'); + assert.ok(p.populated('children')); + db.close(done); + }); + it('should support setting mixed paths by string (gh-1418)', function(done) { var db = start(); var BlogPost = db.model('1418', new Schema({ mixed: {} })); From 47f6806918babea58fc6f8c2d4bb5029040b3ad3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Nov 2015 12:17:25 -0500 Subject: [PATCH 0050/2240] fix; handle #1530 when overwriting arrays (Fix #3575) --- lib/document.js | 13 +++++++++++++ lib/model.js | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/lib/document.js b/lib/document.js index 674cc305cf8..10f9578e53a 100644 --- a/lib/document.js +++ b/lib/document.js @@ -616,6 +616,19 @@ Document.prototype.set = function(path, val, type, options) { this.populated(path, val._id); didPopulate = true; } + + if (schema.options && + Array.isArray(schema.options.type) && + schema.options.type.length && + schema.options.type[0].ref && + Array.isArray(val) && + val.length > 0 && + val[0] instanceof Document && + val[0].constructor.modelName && + schema.options.type[0].ref === val[0].constructor.modelName) { + this.populated(path, val.map(function(v) { return v._id })); + didPopulate = true; + } val = schema.applySetters(val, this, false, priorVal); if (!didPopulate && this.$__.populated) { diff --git a/lib/model.js b/lib/model.js index f8d9b08cf4e..4b9019ba424 100644 --- a/lib/model.js +++ b/lib/model.js @@ -538,6 +538,10 @@ function checkDivergentArray(doc, path, array) { if (!(pop && array && array.isMongooseArray)) return; + if (!pop.options) { + return; + } + // If the array was populated using options that prevented all // documents from being returned (match, skip, limit) or they // deselected the _id field, $pop and $set of the array are From f6ba7708e0ee45feb2c47ac960709bbd2127b601 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Nov 2015 12:25:33 -0500 Subject: [PATCH 0051/2240] docs; clarify second param to .pre() (Fix #3573) --- docs/middleware.jade | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/middleware.jade b/docs/middleware.jade index 7cbc02dd902..1f1faa9bd6d 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -48,6 +48,9 @@ block content | Parallel middleware offer more fine-grained flow control. :js var schema = new Schema(..); + + // `true` means this is a parallel middleware. You **must** specify `true` + // as the second parameter if you want to use parallel middleware. schema.pre('save', true, function(next, done) { // calling next kicks off the next middleware in parallel next(); From 2bb356c7bde9b0492d648324602df2925b6109d3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Nov 2015 15:19:25 -0500 Subject: [PATCH 0052/2240] release 3.8.37 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index aea3e68f06f..83ef532316b 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +3.8.37 / 2015-11-16 +=================== + * fixed; use retainKeyOrder for cloning update op #3572 + 3.8.36 / 2015-10-18 =================== * fixed; Make array props non-enumerable #3461 [boblauer](https://github.com/boblauer) diff --git a/package.json b/package.json index c82f1af2aa0..d6a35e10383 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose" , "description": "Mongoose MongoDB ODM" - , "version": "3.8.37-pre" + , "version": "3.8.37" , "author": "Guillermo Rauch " , "keywords": ["mongodb", "document", "model", "schema", "database", "odm", "data", "datastore", "query", "nosql", "orm", "db"] , "dependencies": { From cefe6623f841c7f678ec6f463505fc6af9c797ab Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Nov 2015 15:37:16 -0500 Subject: [PATCH 0053/2240] release 4.2.6 --- History.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 9c64e641cd1..3463892c16c 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,15 @@ +4.2.6 / 2015-11-16 +================== + * fixed; ability to manually populate an array #3575 + * docs; clarify `isAsync` parameter to hooks #3573 + * fixed; use captureStackTrace if possible instead #3571 + * fixed; crash with buffer and update validators #3565 [johnpeb](https://github.com/johnpeb) + * fixed; update casting with operators overwrite: true #3564 + * fixed; validation with single embedded docs #3562 + * fixed; inline docs inherit parents $type key #3560 + * docs; bad grammar in populate docs #3559 [amaurymedeiros](https://github.com/amaurymedeiros) + * fixed; properly handle populate option for find() #2321 + 3.8.37 / 2015-11-16 =================== * fixed; use retainKeyOrder for cloning update op #3572 diff --git a/package.json b/package.json index 8bc69b8efae..ea3f7ae1b77 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.6-pre", + "version": "4.2.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4eec954b531b2d988cb0ec833d1ac0efe8490ed3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 17 Nov 2015 10:41:51 -0500 Subject: [PATCH 0054/2240] now working on 4.2.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea3f7ae1b77..6d4dcc4988b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.6", + "version": "4.2.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 3ec1911a136a72b6696d80e0d485008cfc0c6399 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 17 Nov 2015 10:54:13 -0500 Subject: [PATCH 0055/2240] repro; #3579 --- test/document.populate.test.js | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/test/document.populate.test.js b/test/document.populate.test.js index e5efcc16b69..abec505f2dc 100644 --- a/test/document.populate.test.js +++ b/test/document.populate.test.js @@ -608,10 +608,41 @@ describe('document.populate', function() { band.depopulate('lead'); assert.ok(!band.lead.name); assert.equal(band.lead.toString(), docs[0]._id.toString()); - done(); + db.close(done); }); }); }); }); }); + + it('handles pulling from populated array (gh-3579)', function(done) { + var db = start(); + var barSchema = new Schema({ name: String }); + + var Bar = db.model('gh3579', barSchema); + + var fooSchema = new Schema({ + bars: [{ + type: Schema.Types.ObjectId, + ref: 'gh3579' + }] + }); + + var Foo = db.model('gh3579_0', fooSchema); + + Bar.create([{ name: 'bar1' }, { name: 'bar2' }], function(error, docs) { + assert.ifError(error); + var foo = new Foo({ bars: [docs[0], docs[1]] }); + foo.bars.pull(docs[0]._id); + foo.save(function(error) { + assert.ifError(error); + Foo.findById(foo._id, function(error, foo) { + assert.ifError(error); + assert.equal(foo.bars.length, 1); + assert.equal(foo.bars[0].toString(), docs[1]._id.toString()); + db.close(done); + }); + }); + }); + }); }); From 78fa27ff83a9783ba2c2f67b637b3e97adc82f85 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 17 Nov 2015 11:12:15 -0500 Subject: [PATCH 0056/2240] fix; properly handle pulling manually populated arrays (Fix #3579) --- lib/document.js | 5 +++-- lib/model.js | 4 ---- lib/types/array.js | 5 +++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/document.js b/lib/document.js index 10f9578e53a..54d905f6b1b 100644 --- a/lib/document.js +++ b/lib/document.js @@ -613,7 +613,7 @@ Document.prototype.set = function(path, val, type, options) { schema.options.ref && val instanceof Document && schema.options.ref === val.constructor.modelName) { - this.populated(path, val._id); + this.populated(path, val._id, { model: val.constructor }); didPopulate = true; } @@ -626,7 +626,8 @@ Document.prototype.set = function(path, val, type, options) { val[0] instanceof Document && val[0].constructor.modelName && schema.options.type[0].ref === val[0].constructor.modelName) { - this.populated(path, val.map(function(v) { return v._id })); + this.populated(path, val.map(function(v) { return v._id }), + { model: val[0].constructor }); didPopulate = true; } val = schema.applySetters(val, this, false, priorVal); diff --git a/lib/model.js b/lib/model.js index 4b9019ba424..f8d9b08cf4e 100644 --- a/lib/model.js +++ b/lib/model.js @@ -538,10 +538,6 @@ function checkDivergentArray(doc, path, array) { if (!(pop && array && array.isMongooseArray)) return; - if (!pop.options) { - return; - } - // If the array was populated using options that prevented all // documents from being returned (match, skip, limit) or they // deselected the _id field, $pop and $set of the array are diff --git a/lib/types/array.js b/lib/types/array.js index 542d69bbbc7..97612788eb4 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -510,7 +510,7 @@ MongooseArray.mixin = { while (i--) { mem = cur[i]; - if (mem instanceof EmbeddedDocument) { + if (mem instanceof Document) { if (values.some(function(v) { return v.equals(mem); } )) { [].splice.call(cur, i, 1); } @@ -736,8 +736,9 @@ MongooseArray.mixin = { indexOf: function indexOf(obj) { if (obj instanceof ObjectId) obj = obj.toString(); for (var i = 0, len = this.length; i < len; ++i) { - if (obj == this[i]) + if (obj == this[i]) { return i; + } } return -1; } From 62a8fee5ea92dc10e1ade16dda44488d3928245b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Nov 2015 11:44:33 -0500 Subject: [PATCH 0057/2240] repro; #3580 part 1 --- test/model.findOneAndUpdate.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index e78d9fe9325..12f9df6879a 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1509,5 +1509,20 @@ describe('model: findByIdAndUpdate:', function() { }); }); }); + + it('cast errors with nested schemas (gh-3580)', function(done) { + var db = start(); + + var nested = new Schema({ num: Number }); + var s = new Schema({ nested: nested }); + + var MyModel = db.model('gh3580', s); + + var update = { nested: { num: 'Not a Number' } }; + MyModel.findOneAndUpdate({}, update, function(error) { + assert.ok(error); + db.close(done); + }); + }); }); }); From 1e6047b4f0b02e5846ffec89262de88c97e44158 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Nov 2015 11:44:47 -0500 Subject: [PATCH 0058/2240] fix; throw casterrors for queries re: #3580 --- lib/schema/embedded.js | 2 +- lib/types/subdocument.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 699b81a1378..d6c45025fba 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -50,8 +50,8 @@ Embedded.prototype = Object.create(SchemaType.prototype); Embedded.prototype.cast = function(val, doc) { var subdoc = new this.caster(); - subdoc = subdoc.init(val); subdoc.$parent = doc; + subdoc = subdoc.init(val); return subdoc; }; diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 1a345b9e044..9526e2cc3e2 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -58,5 +58,7 @@ Subdocument.prototype.$markValid = function(path) { Subdocument.prototype.invalidate = function(path, err, val) { if (this.$parent) { this.$parent.invalidate([this.$basePath, path].join('.'), err, val); + } else if (err.kind === 'cast') { + throw err; } }; From da20549f18784c204687116e472366b99eee64dd Mon Sep 17 00:00:00 2001 From: "Gunar C. Gessner" Date: Thu, 19 Nov 2015 14:50:20 -0200 Subject: [PATCH 0059/2240] docs; clarify param projection in findOne 1. Short link removed because it's a duplicate of `@see findOne`. 2. `@see Query.select` added because of its relation to the `projection` argument. Thank you! --- lib/query.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 96810c13ad5..29548a44d7f 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1192,10 +1192,11 @@ Query.prototype._findOne = function(callback) { * }); * * @param {Object|Query} [criteria] mongodb selector - * @param {Object} [projection] optional fields to return (http://bit.ly/1HotzBo) + * @param {Object} [projection] optional fields to return * @param {Function} [callback] * @return {Query} this * @see findOne http://docs.mongodb.org/manual/reference/method/db.collection.findOne/ + * @see Query.select #query_Query-select * @api public */ From a66a8ce5a64ded37f34bbd7c30c490216107eae3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 19 Nov 2015 12:43:17 -0500 Subject: [PATCH 0060/2240] repro; #3594 --- test/document.test.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 7088ea7c1ac..0c557effbad 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2078,4 +2078,16 @@ describe('document', function() { db.close(done); }); }); + + it('single embedded schemas with indexes (gh-3594)', function(done) { + var personSchema = new Schema({ name: { type: String, unique: true } }); + + var bandSchema = new Schema({ leadSinger: personSchema }); + + assert.equal(bandSchema.indexes().length, 1); + var index = bandSchema.indexes()[0]; + assert.deepEqual(index[0], { 'leadSinger.name': 1 }); + assert.ok(index[1].unique); + done(); + }); }); From 2c9199c90205976a0c64942879ee0265ef135bd6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 19 Nov 2015 12:44:14 -0500 Subject: [PATCH 0061/2240] fix; get indexes from single embedded schemas (Fix #3594) --- lib/schema.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index fb7ede29fd0..e20b0fa00ed 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1043,6 +1043,8 @@ Schema.prototype.indexes = function() { if (path instanceof MongooseTypes.DocumentArray) { collectIndexes(path.schema, key + '.'); + } else if (path.$isSingleNested) { + collectIndexes(path.schema, key + '.'); } else { index = path._index; From 3f413c8eb327a1d8d5206395f7710ee7b1385fd8 Mon Sep 17 00:00:00 2001 From: Steven Cruy Date: Thu, 19 Nov 2015 20:30:50 +0100 Subject: [PATCH 0062/2240] Add FAQ entry: OverwriteModelError --- docs/faq.jade | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/faq.jade b/docs/faq.jade index 1300fc9bf2d..5c6b1341d72 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -66,6 +66,23 @@ block content **Q**. Should I create/destroy a new connection for each database operation? **A**. No. Open your connection when your application starts up and leave it open until the application shuts down. + hr#overwritemodelerror + :markdown + **Q**. Why do I get "OverwriteModelError: Cannot overwrite .. model once compiled" when I use nodemon / a testing framework? + It always works when the code loads the first time, but then throws this error from the second load onwards. + + **A**. Use `connection.model(..)` instead of `mongoose.model(..)` to create your models. + See [this issue](https://github.com/Automattic/mongoose/issues/1251#issuecomment-11697477) and below: + "it works b/c a new connection is created for each of your tests and the model is cached locally within the connection for each. the other way fails b/c models were getting compiled at the mongoose module level for each test, hence the conflicts." + :js + var mongoose = require('mongoose'); + var connection = mongoose.createConnection(..); + + // use mongoose.Schema + var kittySchema = mongoose.Schema({ name: String }); + + // use connection.model + var Kitten = connection.model('Kitten', kittySchema); hr :markdown From 1f67c74c373e001aac95426ebf1f11781d09807c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 19 Nov 2015 16:55:36 -0500 Subject: [PATCH 0063/2240] docs; clarify #3597 --- docs/faq.jade | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/docs/faq.jade b/docs/faq.jade index 5c6b1341d72..b607104034e 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -25,20 +25,6 @@ block content doc.array[3] = 'changed'; doc.markModified('array'); doc.save(); - hr#assign_schemas_to_paths - :markdown - **Q**. Why doesn't mongoose allow me to directly assign schemas to paths? - :js - var userSchema = new Schema({ name: String }); - new Schema({ user: userSchema }) - :markdown - **A**. Schemas have a one-to-one mapping with documents. Documents have `save` and `remove` methods along with their own `pre` and `post` hooks which would lead to code like the following: - :js - doc.user.save(); // ? - doc.user.remove();// ? - doc.save() - :markdown - We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling `save` on a sub-document is a no-op and exists only to support `pre` save hooks). In the future this is likely to be revisited. hr#enable_debugging :markdown **Q**. How can I enable debugging? @@ -66,14 +52,19 @@ block content **Q**. Should I create/destroy a new connection for each database operation? **A**. No. Open your connection when your application starts up and leave it open until the application shuts down. - hr#overwritemodelerror + hr#overwrite-model-error :markdown - **Q**. Why do I get "OverwriteModelError: Cannot overwrite .. model once compiled" when I use nodemon / a testing framework? - It always works when the code loads the first time, but then throws this error from the second load onwards. + **Q**. Why do I get "OverwriteModelError: Cannot overwrite .. model once + compiled" when I use nodemon / a testing framework? - **A**. Use `connection.model(..)` instead of `mongoose.model(..)` to create your models. - See [this issue](https://github.com/Automattic/mongoose/issues/1251#issuecomment-11697477) and below: - "it works b/c a new connection is created for each of your tests and the model is cached locally within the connection for each. the other way fails b/c models were getting compiled at the mongoose module level for each test, hence the conflicts." + **A**. `mongoose.model('ModelName', schema)` requires 'ModelName' to be + unique, so you can access the model by using `mongoose.model('ModelName')`. + If you put `mongoose.model('ModelName', schema);` in a + [mocha `beforeEach()` hook](https://mochajs.org/#hooks), this code will + attempt to create a new model named 'ModelName' before **every** test, + and so you will get an error. Make sure you only create a new model with + a given name **once**. If you need to create multiple models with the + same name, create a new connection and bind the model to the connection. :js var mongoose = require('mongoose'); var connection = mongoose.createConnection(..); @@ -90,4 +81,3 @@ block content If you'd like to contribute to this page, please [visit it](https://github.com/Automattic/mongoose/tree/master/docs/faq.jade) on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request. br - From 6c98eb41d1f3dbcf922636efa05861c95d18d20d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Nov 2015 11:38:50 -0500 Subject: [PATCH 0064/2240] upgrade; mongodb -> 2.0.49 (Fix #3589) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6d4dcc4988b..ab5927ce18f 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.18", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.0.48", + "mongodb": "2.0.49", "mpath": "0.1.1", "mpromise": "0.5.4", "mquery": "1.6.3", From a26d188e4d7db3f88b32e50011184b65a0dffb16 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Nov 2015 11:56:58 -0500 Subject: [PATCH 0065/2240] repro; #3589 --- test/document.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 0c557effbad..2390a70ec58 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2090,4 +2090,22 @@ describe('document', function() { assert.ok(index[1].unique); done(); }); + + it('single embedded docs have an ownerDocument function (gh-3589)', function(done) { + var db = start(); + var personSchema = new Schema({ name: String }); + personSchema.methods.display = function() { + return this.name + ' of ' + this.ownerDocument().name; + }; + + var bandSchema = new Schema({ leadSinger: personSchema, name: String }); + var Band = db.model('gh3589', bandSchema); + + var gnr = new Band({ + name: "Guns N' Roses", + leadSinger: { name: 'Axl Rose' } + }); + assert.equal(gnr.leadSinger.display(), "Axl Rose of Guns N' Roses"); + db.close(done); + }); }); From df7a5dc5a230075021bbf2b91efe7bf8adb30962 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Nov 2015 11:57:19 -0500 Subject: [PATCH 0066/2240] fix; single embedded docs ownerDocument() func (Fix #3589) --- lib/types/subdocument.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 9526e2cc3e2..73597d0e0a4 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -62,3 +62,26 @@ Subdocument.prototype.invalidate = function(path, err, val) { throw err; } }; + +/** + * Returns the top level document of this sub-document. + * + * @return {Document} + */ + +Subdocument.prototype.ownerDocument = function() { + if (this.$__.ownerDocument) { + return this.$__.ownerDocument; + } + + var parent = this.$parent; + if (!parent) { + return this; + } + + while (parent.$parent) { + parent = parent.$parent; + } + + return this.$__.ownerDocument = parent; +}; From bf30909f7b370306b527bc66c250f7370afa3296 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Nov 2015 17:02:07 -0500 Subject: [PATCH 0067/2240] fix; readPreference option in connection.js --- lib/drivers/node-mongodb-native/connection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 215146b67aa..a22e6174eef 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -304,8 +304,8 @@ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { } break; case 'readPreference': - if ('undefined' == typeof o.db.read_preference) { - o.db.read_preference = opts[name]; + if ('undefined' == typeof o.db.readPreference) { + o.db.readPreference = opts[name]; } break; case 'readPreferenceTags': From 279c36f2eb3a4d1a1cf088c39d47ff759ded8d66 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Nov 2015 17:04:55 -0500 Subject: [PATCH 0068/2240] fix; tests from readPref fixes re: #3600 --- lib/drivers/node-mongodb-native/connection.js | 5 ----- test/connection.test.js | 6 ++---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index a22e6174eef..f13d5b2c214 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -320,11 +320,6 @@ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { o.server.auto_reconnect = true; } - if (!o.db.read_preference) { - // read from primaries by default - o.db.read_preference = 'primary'; - } - // mongoose creates its own ObjectIds o.db.forceServerObjectId = false; diff --git a/test/connection.test.js b/test/connection.test.js index cb5f3bf35f0..371d3e255ab 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -29,7 +29,6 @@ describe('connections:', function() { assert.equal(true, db.options.server.auto_reconnect); assert.equal('object', typeof db.options.db); assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('primary', db.options.db.read_preference); assert.equal(undefined, db.pass); assert.equal(undefined, db.user); assert.equal('fake', db.name); @@ -46,7 +45,6 @@ describe('connections:', function() { assert.equal(true, db.options.server.auto_reconnect); assert.equal('object', typeof db.options.db); assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('primary', db.options.db.read_preference); assert.equal(undefined, db.pass); assert.equal(undefined, db.user); assert.equal('fake', db.name); @@ -387,7 +385,7 @@ describe('connections:', function() { assert.equal(true, db.options.db.fsync); assert.equal(true, db.options.db.journal); assert.equal(80, db.options.db.wtimeoutMS); - assert.equal('nearest', db.options.db.read_preference); + assert.equal('nearest', db.options.db.readPreference); assert.deepEqual([{ dc: 'ny', rack: 1 }, { dc: 'sf' }], db.options.db.read_preference_tags); assert.equal(false, db.options.db.forceServerObjectId); done(); @@ -428,7 +426,7 @@ describe('connections:', function() { assert.equal(true, db.options.db.fsync); assert.equal(true, db.options.db.journal); assert.equal(80, db.options.db.wtimeoutMS); - assert.equal('nearest', db.options.db.read_preference); + assert.equal('nearest', db.options.db.readPreference); assert.deepEqual([{ dc: 'ny', rack: 1 }, { dc: 'sf' }], db.options.db.read_preference_tags); assert.equal(false, db.options.db.forceServerObjectId); From 8f14b01e5af5b523d18218f9b554ed4483336dbf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Nov 2015 17:13:48 -0500 Subject: [PATCH 0069/2240] repro; #3596 --- test/document.test.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 2390a70ec58..c0188185be8 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2108,4 +2108,26 @@ describe('document', function() { assert.equal(gnr.leadSinger.display(), "Axl Rose of Guns N' Roses"); db.close(done); }); + + it('removing single embedded docs (gh-3596)', function(done) { + var db = start(); + var personSchema = new Schema({ name: String }); + + var bandSchema = new Schema({ guitarist: personSchema, name: String }); + var Band = db.model('gh3596', bandSchema); + + var gnr = new Band({ + name: "Guns N' Roses", + guitarist: { name: 'Slash' } + }); + gnr.save(function(error, gnr) { + assert.ifError(error); + gnr.guitarist = undefined; + gnr.save(function(error, gnr) { + assert.ifError(error); + assert.ok(!gnr.guitarist); + db.close(done); + }); + }); + }); }); From 3f2ebba624b7b560af6bee845081fbf9497c8002 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Nov 2015 17:14:43 -0500 Subject: [PATCH 0070/2240] fix; dont try to validate falsy subdocs (Fix #3596) --- lib/schema/embedded.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index d6c45025fba..1dede23d4fe 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -89,6 +89,9 @@ Embedded.prototype.doValidate = function(value, fn) { if (error) { return fn(error); } + if (!value) { + return fn(null); + } value.validate(fn, { __noPromise: true }); }); }; @@ -104,6 +107,9 @@ Embedded.prototype.doValidateSync = function(value) { if (schemaTypeError) { return schemaTypeError; } + if (!value) { + return; + } return value.validateSync(); }; From f7080914bc472f24542f6a0e4c8ba5fd6d080949 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Nov 2015 17:24:50 -0500 Subject: [PATCH 0071/2240] release 4.2.7 --- History.md | 12 +++++ bin/mongoose.js | 125 +++++++++++++++++++++++++++++++++++++++++++----- package.json | 2 +- 3 files changed, 127 insertions(+), 12 deletions(-) diff --git a/History.md b/History.md index 3463892c16c..da01fefd342 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,15 @@ +4.2.7 / 2015-11-20 +================== + * fixed; readPreference connection string option #3600 + * fixed; pulling from manually populated arrays #3598 #3579 + * docs; FAQ about OverwriteModelError #3597 [stcruy](https://github.com/stcruy) + * fixed; setting single embedded schemas to null #3596 + * fixed; indexes for single embedded schemas #3594 + * docs; clarify projection for `findOne()` #3593 [gunar](https://github.com/gunar) + * fixed; .ownerDocument() method on single embedded schemas #3589 + * fixed; properly throw casterror for query on single embedded schema #3580 + * upgraded; mongodb driver -> 2.0.49 for reconnect issue fix #3481 + 4.2.6 / 2015-11-16 ================== * fixed; ability to manually populate an array #3575 diff --git a/bin/mongoose.js b/bin/mongoose.js index 97ba711e029..ba89c4063f5 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -1066,7 +1066,21 @@ Document.prototype.set = function(path, val, type, options) { schema.options.ref && val instanceof Document && schema.options.ref === val.constructor.modelName) { - this.populated(path, val._id); + this.populated(path, val._id, { model: val.constructor }); + didPopulate = true; + } + + if (schema.options && + Array.isArray(schema.options.type) && + schema.options.type.length && + schema.options.type[0].ref && + Array.isArray(val) && + val.length > 0 && + val[0] instanceof Document && + val[0].constructor.modelName && + schema.options.type[0].ref === val[0].constructor.modelName) { + this.populated(path, val.map(function(v) { return v._id }), + { model: val[0].constructor }); didPopulate = true; } val = schema.applySetters(val, this, false, priorVal); @@ -2853,7 +2867,11 @@ module.exports = driver; function MongooseError(msg) { Error.call(this); - this.stack = new Error().stack; + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack + } this.message = msg; this.name = 'MongooseError'; } @@ -2913,7 +2931,11 @@ var MongooseError = require('../error.js'); function CastError(type, value, path, reason) { MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '" at path "' + path + '"'); - this.stack = new Error().stack; + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack + } this.name = 'CastError'; this.kind = type; this.value = value; @@ -3114,7 +3136,11 @@ function ValidationError(instance) { } else { MongooseError.call(this, "Validation failed"); } - this.stack = new Error().stack; + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack + } this.name = 'ValidationError'; this.errors = {}; if (instance) { @@ -3177,7 +3203,11 @@ function ValidatorError(properties) { this.properties = properties; var message = this.formatMessage(msg, properties); MongooseError.call(this, message); - this.stack = new Error().stack; + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack + } this.name = 'ValidatorError'; this.kind = properties.type; this.path = properties.path; @@ -4181,8 +4211,16 @@ Schema.interpretAsType = function(path, obj, options) { } else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type)) && 'Object' == utils.getFunctionName(cast.constructor) && Object.keys(cast).length) { - var opts = { minimize: options.minimize }; - return new MongooseTypes.DocumentArray(path, new Schema(cast, opts), obj); + + // The `minimize` and `typeKey` options propagate to child schemas + // declared inline, like `{ arr: [{ val: { $type: String } }] }`. + // See gh-3560 + var childSchemaOptions = { minimize: options.minimize }; + if (options.typeKey) { + childSchemaOptions.typeKey = options.typeKey; + } + var childSchema = new Schema(cast, childSchemaOptions); + return new MongooseTypes.DocumentArray(path, childSchema, obj); } return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj); @@ -4673,6 +4711,8 @@ Schema.prototype.indexes = function() { if (path instanceof MongooseTypes.DocumentArray) { collectIndexes(path.schema, key + '.'); + } else if (path.$isSingleNested) { + collectIndexes(path.schema, key + '.'); } else { index = path._index; @@ -6155,8 +6195,8 @@ Embedded.prototype = Object.create(SchemaType.prototype); Embedded.prototype.cast = function(val, doc) { var subdoc = new this.caster(); - subdoc = subdoc.init(val); subdoc.$parent = doc; + subdoc = subdoc.init(val); return subdoc; }; @@ -6183,14 +6223,51 @@ Embedded.prototype.castForQuery = function($conditional, val) { } }; +/** + * Async validation on this single nested doc. + * + * @api private + */ + Embedded.prototype.doValidate = function(value, fn) { - value.validate(fn, { __noPromise: true }); + SchemaType.prototype.doValidate.call(this, value, function(error) { + if (error) { + return fn(error); + } + if (!value) { + return fn(null); + } + value.validate(fn, { __noPromise: true }); + }); }; +/** + * Synchronously validate this single nested doc + * + * @api private + */ + Embedded.prototype.doValidateSync = function(value) { + var schemaTypeError = SchemaType.prototype.doValidateSync.call(this, value); + if (schemaTypeError) { + return schemaTypeError; + } + if (!value) { + return; + } return value.validateSync(); }; +/** + * Required validator for single nested docs + * + * @api private + */ + +Embedded.prototype.checkRequired = function(value) { + return !!value && value.$isSingleNested; +}; + },{"../schematype":36,"../types/subdocument":44}],31:[function(require,module,exports){ /*! @@ -8843,7 +8920,7 @@ MongooseArray.mixin = { while (i--) { mem = cur[i]; - if (mem instanceof EmbeddedDocument) { + if (mem instanceof Document) { if (values.some(function(v) { return v.equals(mem); } )) { [].splice.call(cur, i, 1); } @@ -9069,8 +9146,9 @@ MongooseArray.mixin = { indexOf: function indexOf(obj) { if (obj instanceof ObjectId) obj = obj.toString(); for (var i = 0, len = this.length; i < len; ++i) { - if (obj == this[i]) + if (obj == this[i]) { return i; + } } return -1; } @@ -10002,7 +10080,32 @@ Subdocument.prototype.$markValid = function(path) { Subdocument.prototype.invalidate = function(path, err, val) { if (this.$parent) { this.$parent.invalidate([this.$basePath, path].join('.'), err, val); + } else if (err.kind === 'cast') { + throw err; + } +}; + +/** + * Returns the top level document of this sub-document. + * + * @return {Document} + */ + +Subdocument.prototype.ownerDocument = function() { + if (this.$__.ownerDocument) { + return this.$__.ownerDocument; + } + + var parent = this.$parent; + if (!parent) { + return this; } + + while (parent.$parent) { + parent = parent.$parent; + } + + return this.$__.ownerDocument = parent; }; },{"../document":5,"../promise_provider":23}],45:[function(require,module,exports){ diff --git a/package.json b/package.json index ab5927ce18f..380320de99a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.7-pre", + "version": "4.2.7", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 3fa4cd35e55e1376696482aa5ceffef1e2c20a69 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Nov 2015 11:11:25 -0500 Subject: [PATCH 0072/2240] Now working on 4.2.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 380320de99a..4ab2b27812b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.7", + "version": "4.2.8-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 7c60ca454600c219e8cb07695d669b25abcdb4ad Mon Sep 17 00:00:00 2001 From: Christian Murphy Date: Sat, 21 Nov 2015 10:13:44 -0700 Subject: [PATCH 0073/2240] lint Update Eslint Rename .eslintrc to .eslintrc.yml Update code style in README.md Update lint warnings --- .eslintrc => .eslintrc.yml | 0 README.md | 24 +++++++++++------------ lib/document.js | 2 +- lib/error.js | 2 +- lib/error/cast.js | 2 +- lib/error/validation.js | 2 +- lib/error/validator.js | 2 +- lib/query.js | 2 +- package.json | 2 +- test/browser/{.eslintrc => .eslintrc.yml} | 0 test/harmony/{.eslintrc => .eslintrc.yml} | 0 test/model.update.test.js | 6 +++--- 12 files changed, 22 insertions(+), 22 deletions(-) rename .eslintrc => .eslintrc.yml (100%) rename test/browser/{.eslintrc => .eslintrc.yml} (100%) rename test/harmony/{.eslintrc => .eslintrc.yml} (100%) diff --git a/.eslintrc b/.eslintrc.yml similarity index 100% rename from .eslintrc rename to .eslintrc.yml diff --git a/README.md b/README.md index fd8077d4630..852bcab6c80 100644 --- a/README.md +++ b/README.md @@ -96,11 +96,11 @@ The following example shows some of these features: ```js var Comment = new Schema({ - name : { type: String, default: 'hahaha' }, - age : { type: Number, min: 18, index: true }, - bio : { type: String, match: /[a-z]/ }, - date : { type: Date, default: Date.now }, - buff : Buffer + name: { type: String, default: 'hahaha' }, + age: { type: Number, min: 18, index: true }, + bio: { type: String, match: /[a-z]/ }, + date: { type: Date, default: Date.now }, + buff: Buffer }); // a setter @@ -162,18 +162,18 @@ You can also `findOne`, `findById`, `update`, etc. For more details check out [t **Important!** If you opened a separate connection using `mongoose.createConnection()` but attempt to access the model through `mongoose.model('ModelName')` it will not work as expected since it is not hooked up to an active db connection. In this case access your model through the connection you created: ```js -var conn = mongoose.createConnection('your connection string') - , MyModel = conn.model('ModelName', schema) - , m = new MyModel; +var conn = mongoose.createConnection('your connection string'), + MyModel = conn.model('ModelName', schema), + m = new MyModel; m.save(); // works ``` vs ```js -var conn = mongoose.createConnection('your connection string') - , MyModel = mongoose.model('ModelName', schema) - , m = new MyModel; +var conn = mongoose.createConnection('your connection string'), + MyModel = mongoose.model('ModelName', schema), + m = new MyModel; m.save(); // does not work b/c the default connection object was never connected ``` @@ -278,7 +278,7 @@ new Schema({ new Schema({ works: { type: Boolean }, - asset : { + asset: { name: String, type: { type: String } // works. asset is an object with a type property } diff --git a/lib/document.js b/lib/document.js index 54d905f6b1b..d8803196094 100644 --- a/lib/document.js +++ b/lib/document.js @@ -626,7 +626,7 @@ Document.prototype.set = function(path, val, type, options) { val[0] instanceof Document && val[0].constructor.modelName && schema.options.type[0].ref === val[0].constructor.modelName) { - this.populated(path, val.map(function(v) { return v._id }), + this.populated(path, val.map(function(v) { return v._id; }), { model: val[0].constructor }); didPopulate = true; } diff --git a/lib/error.js b/lib/error.js index ace45653ab3..b084e764c95 100644 --- a/lib/error.js +++ b/lib/error.js @@ -11,7 +11,7 @@ function MongooseError(msg) { if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { - this.stack = new Error().stack + this.stack = new Error().stack; } this.message = msg; this.name = 'MongooseError'; diff --git a/lib/error/cast.js b/lib/error/cast.js index 266858c5d1c..fcace73ee01 100644 --- a/lib/error/cast.js +++ b/lib/error/cast.js @@ -18,7 +18,7 @@ function CastError(type, value, path, reason) { if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { - this.stack = new Error().stack + this.stack = new Error().stack; } this.name = 'CastError'; this.kind = type; diff --git a/lib/error/validation.js b/lib/error/validation.js index 41b11439ad3..ecbf73a914e 100644 --- a/lib/error/validation.js +++ b/lib/error/validation.js @@ -22,7 +22,7 @@ function ValidationError(instance) { if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { - this.stack = new Error().stack + this.stack = new Error().stack; } this.name = 'ValidationError'; this.errors = {}; diff --git a/lib/error/validator.js b/lib/error/validator.js index ca605b8c3e3..959073bc86e 100644 --- a/lib/error/validator.js +++ b/lib/error/validator.js @@ -25,7 +25,7 @@ function ValidatorError(properties) { if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { - this.stack = new Error().stack + this.stack = new Error().stack; } this.name = 'ValidatorError'; this.kind = properties.type; diff --git a/lib/query.js b/lib/query.js index 29548a44d7f..b74586d58f2 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2154,7 +2154,7 @@ Query.prototype.exec = function exec(op, callback) { Query.prototype.then = function(resolve, reject) { return this.exec().then(resolve, reject); -} +}; /** * Finds the schema for `path`. This is different than diff --git a/package.json b/package.json index 4ab2b27812b..2230620fa16 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "bluebird": "2.9.34", "co": "3.1.0", "dox": "0.3.1", - "eslint": "1.9.0", + "eslint": "1.10.1", "highlight.js": "7.0.1", "istanbul": "^0.3.13", "jade": "0.26.3", diff --git a/test/browser/.eslintrc b/test/browser/.eslintrc.yml similarity index 100% rename from test/browser/.eslintrc rename to test/browser/.eslintrc.yml diff --git a/test/harmony/.eslintrc b/test/harmony/.eslintrc.yml similarity index 100% rename from test/harmony/.eslintrc rename to test/harmony/.eslintrc.yml diff --git a/test/model.update.test.js b/test/model.update.test.js index fbbd0231370..608033b0cbc 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1666,11 +1666,11 @@ describe('model: update:', function() { var M = db.model('gh-3564', schema); - M.create(doc, function(err, topic) { + M.create(doc, function(err) { assert.ifError(err); var update = { $push: { followers: 200 } }; - var opts = { overwrite: true, new: true, safe: true, upsert: false, multi: false}; + var opts = { overwrite: true, new: true, safe: true, upsert: false, multi: false}; M.update({ topicId: doc.topicId }, update, opts, function(err) { assert.ifError(err); @@ -1680,7 +1680,7 @@ describe('model: update:', function() { assert.deepEqual(doc.followers.toObject(), [500, 200]); db.close(done); }); - }) + }); }); }); }); From 66b085be9ab4db4b3819c5037bc939e950bcae71 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Nov 2015 15:19:53 -0500 Subject: [PATCH 0074/2240] repro; #3601 --- test/document.test.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index c0188185be8..b69832e6860 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2130,4 +2130,26 @@ describe('document', function() { }); }); }); + + it('setting single embedded docs (gh-3601)', function(done) { + var db = start(); + var personSchema = new Schema({ name: String }); + + var bandSchema = new Schema({ guitarist: personSchema, name: String }); + var Band = db.model('gh3601', bandSchema); + + var gnr = new Band({ + name: "Guns N' Roses", + guitarist: { name: 'Slash' } + }); + var velvetRevolver = new Band({ + name: 'Velvet Revolver' + }); + velvetRevolver.guitarist = gnr.guitarist; + velvetRevolver.save(function(error) { + assert.ifError(error); + assert.equal(velvetRevolver.guitarist, gnr.guitarist); + db.close(done); + }); + }); }); From 99828ce5030b20cfc0048ec5e17319f820c0cc5f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Nov 2015 15:25:41 -0500 Subject: [PATCH 0075/2240] fix; casting issue with single nested (Fix #3601) --- lib/schema/embedded.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 1dede23d4fe..e6abec2d03b 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -49,6 +49,9 @@ Embedded.prototype = Object.create(SchemaType.prototype); */ Embedded.prototype.cast = function(val, doc) { + if (val && val.$isSingleNested) { + return val; + } var subdoc = new this.caster(); subdoc.$parent = doc; subdoc = subdoc.init(val); From c9c4e5d33a44009565f4037d41bb0d97401299a7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 22 Nov 2015 19:06:13 -0500 Subject: [PATCH 0076/2240] chore: remove --async-only from tests --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2230620fa16..f6b9105a99b 100644 --- a/package.json +++ b/package.json @@ -66,8 +66,8 @@ }, "scripts": { "install-browser": "npm install `node format_deps.js`", - "test": "mocha --async-only test/*.test.js test/**/*.test.js", - "test-cov": "istanbul cover _mocha --async-only test/*.test.js", + "test": "mocha test/*.test.js test/**/*.test.js", + "test-cov": "istanbul cover _mocha test/*.test.js", "lint": "eslint . --quiet" }, "main": "./index.js", From d1dd3ba1b39c0aa2c6a69f962922997e533d9369 Mon Sep 17 00:00:00 2001 From: ReadmeCritic Date: Mon, 23 Nov 2015 09:20:15 -0800 Subject: [PATCH 0077/2240] Update README URLs based on HTTP redirects --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 852bcab6c80..235c9ab8de8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Mongoose -Mongoose is a [MongoDB](http://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. +Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. [![Build Status](https://api.travis-ci.org/Automattic/mongoose.png?branch=master)](https://travis-ci.org/Automattic/mongoose) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Automattic/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -15,7 +15,7 @@ Mongoose is a [MongoDB](http://www.mongodb.org/) object modeling tool designed t - [Stack Overflow](http://stackoverflow.com/questions/tagged/mongoose) - [bug reports](https://github.com/Automattic/mongoose/issues/) - [help forum](http://groups.google.com/group/mongoose-orm) - - [MongoDB support](http://www.mongodb.org/display/DOCS/Technical+Support) + - [MongoDB support](https://docs.mongodb.org/manual/support/) - (irc) #mongoosejs on freenode ## Plugins @@ -29,11 +29,11 @@ Build your own Mongoose plugin through [generator-mongoose-plugin](https://githu View all 100+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors). Stand up and be counted as a [contributor](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md) too! ## Live Examples - + ## Installation -First install [node.js](http://nodejs.org/) and [mongodb](http://www.mongodb.org/downloads). Then: +First install [node.js](http://nodejs.org/) and [mongodb](https://www.mongodb.org/downloads). Then: ```sh $ npm install mongoose @@ -291,8 +291,8 @@ The driver being used defaults to [node-mongodb-native](https://github.com/mongo ## API Docs -Find the API docs [here](http://mongoosejs.com/docs/api.html), generated using [dox](http://github.com/visionmedia/dox) -and [acquit](http://github.com/vkarpov15/acquit). +Find the API docs [here](http://mongoosejs.com/docs/api.html), generated using [dox](https://github.com/tj/dox) +and [acquit](https://github.com/vkarpov15/acquit). ## License From 9acc598e7897c0456f4375935ba1364f2c2aae64 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 24 Nov 2015 14:12:16 -0500 Subject: [PATCH 0078/2240] docs; coverage for debug logging functions (Fix #3557) --- lib/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 1f7a654c12b..fd6e63a81ad 100644 --- a/lib/index.js +++ b/lib/index.js @@ -58,8 +58,10 @@ Mongoose.prototype.STATES = STATES; * * mongoose.set('debug', true) // enable logging collection methods + arguments to the console * + * mongoose.set('debug', function(collectionName, methodName, arg1, arg2...) {}); // use custom function to log collection methods + arguments + * * @param {String} key - * @param {String} value + * @param {String|Function} value * @api public */ From 79c17e00794dd29f4f7c74f1a2469abcbd753496 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 25 Nov 2015 14:03:50 -0500 Subject: [PATCH 0079/2240] release 4.2.8 --- History.md | 7 +++++++ bin/mongoose.js | 13 ++++++++----- package.json | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index da01fefd342..3e324e297ad 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.2.8 / 2015-11-25 +================== + * docs; clean up README links #3612 [ReadmeCritic](https://github.com/ReadmeCritic) + * fix; ESLint improvements #3605 [ChristianMurphy](https://github.com/ChristianMurphy) + * fix; assigning single nested subdocs #3601 + * docs; describe custom logging functions in `mongoose.set()` docs #3557 + 4.2.7 / 2015-11-20 ================== * fixed; readPreference connection string option #3600 diff --git a/bin/mongoose.js b/bin/mongoose.js index ba89c4063f5..fbecc9a1943 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -1079,7 +1079,7 @@ Document.prototype.set = function(path, val, type, options) { val[0] instanceof Document && val[0].constructor.modelName && schema.options.type[0].ref === val[0].constructor.modelName) { - this.populated(path, val.map(function(v) { return v._id }), + this.populated(path, val.map(function(v) { return v._id; }), { model: val[0].constructor }); didPopulate = true; } @@ -2870,7 +2870,7 @@ function MongooseError(msg) { if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { - this.stack = new Error().stack + this.stack = new Error().stack; } this.message = msg; this.name = 'MongooseError'; @@ -2934,7 +2934,7 @@ function CastError(type, value, path, reason) { if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { - this.stack = new Error().stack + this.stack = new Error().stack; } this.name = 'CastError'; this.kind = type; @@ -3139,7 +3139,7 @@ function ValidationError(instance) { if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { - this.stack = new Error().stack + this.stack = new Error().stack; } this.name = 'ValidationError'; this.errors = {}; @@ -3206,7 +3206,7 @@ function ValidatorError(properties) { if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { - this.stack = new Error().stack + this.stack = new Error().stack; } this.name = 'ValidatorError'; this.kind = properties.type; @@ -6194,6 +6194,9 @@ Embedded.prototype = Object.create(SchemaType.prototype); */ Embedded.prototype.cast = function(val, doc) { + if (val && val.$isSingleNested) { + return val; + } var subdoc = new this.caster(); subdoc.$parent = doc; subdoc = subdoc.init(val); diff --git a/package.json b/package.json index f6b9105a99b..400ca9b10e1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.8-pre", + "version": "4.2.8", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 6b83639b43050e1eb18c4f00d6da5367d3aa3547 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 26 Nov 2015 08:29:03 -0500 Subject: [PATCH 0080/2240] Now working on 4.2.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 400ca9b10e1..dfd16ad392a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.8", + "version": "4.2.9-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 5c3c9be549382b09d2f6526fbd56791ca523c979 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 Nov 2015 12:24:10 -0500 Subject: [PATCH 0081/2240] Upgrade node driver to 2.0.50 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dfd16ad392a..27397f71507 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.18", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.0.49", + "mongodb": "2.0.50", "mpath": "0.1.1", "mpromise": "0.5.4", "mquery": "1.6.3", From 7d18476c385da3441564bc5bb505da2533e39767 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Nov 2015 16:32:54 -0500 Subject: [PATCH 0082/2240] repro; #3616 --- test/model.findOneAndUpdate.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 12f9df6879a..b157ded2d75 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1524,5 +1524,25 @@ describe('model: findByIdAndUpdate:', function() { db.close(done); }); }); + + it('pull with nested schemas (gh-3616)', function(done) { + var db = start(); + + var nested = new Schema({ arr: [{ num: Number }] }); + var s = new Schema({ nested: nested }); + + var MyModel = db.model('gh3616', s); + + MyModel.create({ nested: { arr: [{ num: 5 }] } }, function(error, doc) { + assert.ifError(error); + var update = { $pull: { 'nested.arr': { num: 5 } } }; + var options = { 'new': true }; + MyModel.findOneAndUpdate({}, update, options, function(error, doc) { + assert.ifError(error); + assert.equal(doc.nested.arr.length, 0); + db.close(done); + }); + }); + }); }); }); From d24d0e791c85dcee4d61c6fc317b7a8387ba6796 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Nov 2015 17:05:31 -0500 Subject: [PATCH 0083/2240] fix; get single nested paths properly (Fix #3616) --- lib/schema.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index e20b0fa00ed..9b9f2f0abae 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -69,6 +69,7 @@ function Schema(obj, options) { this.paths = {}; this.subpaths = {}; this.virtuals = {}; + this.singleNestedPaths = {}; this.nested = {}; this.inherits = {}; this.callQueue = []; @@ -496,6 +497,12 @@ Schema.prototype.path = function(path, obj) { branch[last] = utils.clone(obj); this.paths[path] = Schema.interpretAsType(path, obj, this.options); + if (this.paths[path].$isSingleNested) { + for (var key in this.paths[path].schema.paths) { + this.singleNestedPaths[path + '.' + key] = + this.paths[path].schema.paths[key]; + } + } return this; }; @@ -658,6 +665,9 @@ Schema.prototype.pathType = function(path) { if (path in this.virtuals) return 'virtual'; if (path in this.nested) return 'nested'; if (path in this.subpaths) return 'real'; + if (path in this.singleNestedPaths) { + return 'real'; + } if (/\.\d+\.|\.\d+$/.test(path)) { return getPositionalPathType(this, path); From a37cf702154489b038501a0eee5e54dfedd48e3f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 Nov 2015 18:20:16 -0500 Subject: [PATCH 0084/2240] repro; #3618 --- test/document.test.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index b69832e6860..040f24a72f4 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2152,4 +2152,27 @@ describe('document', function() { db.close(done); }); }); + + it('handles virtuals with dots correctly (gh-3618)', function(done) { + var db = start(); + var testSchema = new Schema({ nested: { type: Object, default: {} } }); + testSchema.virtual('nested.test').get(function() { + return true; + }); + + var Test = db.model('gh3618', testSchema); + + var test = new Test(); + + var doc = test.toObject({ getters: true, virtuals: true }); + delete doc._id; + delete doc.id; + assert.deepEqual(doc, { 'nested.test': true }); + + doc = test.toObject({ getters: false, virtuals: true }); + delete doc._id; + delete doc.id; + assert.deepEqual(doc, { 'nested.test': true }); + db.close(done); + }); }); From b839f1e8639b0f3b5c959aa538f2d6a1f3ad9b17 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 Nov 2015 18:20:38 -0500 Subject: [PATCH 0085/2240] fix; properly handle dots in virtual path names in toObject() (Fix #3618) --- lib/document.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/document.js b/lib/document.js index d8803196094..d7d476ac20e 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2036,6 +2036,12 @@ function applyGetters(self, json, type, options) { branch = json, part; + // Special case: virtuals never get nested (See gh-3618) + if (type === 'virtuals') { + branch[path] = clone(self.get(path), options); + continue; + } + for (var ii = 0; ii < plen; ++ii) { part = parts[ii]; if (ii === last) { From 717470a94b4881fa66b0d592daaba15e39bb88b5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Nov 2015 18:09:53 -0500 Subject: [PATCH 0086/2240] Peg exact BSON version re: #3631 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 27397f71507..948b4150370 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "license": "MIT", "dependencies": { "async": "0.9.0", - "bson": "~0.4.18", + "bson": "0.4.19", "hooks-fixed": "1.1.0", "kareem": "1.0.1", "mongodb": "2.0.50", From 27b97f40431e8321ac8f89ebb3285833a7f32627 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Nov 2015 18:13:53 -0500 Subject: [PATCH 0087/2240] go back to mongodb driver 2.0.49 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 948b4150370..d32609ae6ed 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "0.4.19", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.0.50", + "mongodb": "2.0.49", "mpath": "0.1.1", "mpromise": "0.5.4", "mquery": "1.6.3", From 12ee5a30afb3da02637698f8554500cea59c933b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 1 Dec 2015 14:21:37 -0500 Subject: [PATCH 0088/2240] Revert "fix; properly handle dots in virtual path names in toObject() (Fix #3618)" This reverts commit b839f1e8639b0f3b5c959aa538f2d6a1f3ad9b17. --- lib/document.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/document.js b/lib/document.js index d7d476ac20e..d8803196094 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2036,12 +2036,6 @@ function applyGetters(self, json, type, options) { branch = json, part; - // Special case: virtuals never get nested (See gh-3618) - if (type === 'virtuals') { - branch[path] = clone(self.get(path), options); - continue; - } - for (var ii = 0; ii < plen; ++ii) { part = parts[ii]; if (ii === last) { From 7b9cdf9b90dca54df4f54a36eefc7d93539fdb90 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 1 Dec 2015 14:24:52 -0500 Subject: [PATCH 0089/2240] fix(document): apply path getters before virtual getters #3618 --- lib/document.js | 8 ++++---- test/document.test.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/document.js b/lib/document.js index d8803196094..b9e2227faa2 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1814,10 +1814,6 @@ Document.prototype.$toObject = function(options, json) { var ret = clone(this._doc, options) || {}; - if (options.virtuals || options.getters && false !== options.virtuals) { - applyGetters(this, ret, 'virtuals', options); - } - if (options.getters) { applyGetters(this, ret, 'paths', options); // applyGetters for paths will add nested empty objects; @@ -1827,6 +1823,10 @@ Document.prototype.$toObject = function(options, json) { } } + if (options.virtuals || options.getters && false !== options.virtuals) { + applyGetters(this, ret, 'virtuals', options); + } + if (options.versionKey === false && this.schema.options.versionKey) { delete ret[this.schema.options.versionKey]; } diff --git a/test/document.test.js b/test/document.test.js index 040f24a72f4..5bc4c305cf8 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2167,12 +2167,12 @@ describe('document', function() { var doc = test.toObject({ getters: true, virtuals: true }); delete doc._id; delete doc.id; - assert.deepEqual(doc, { 'nested.test': true }); + assert.deepEqual(doc, { nested: { test: true } }); doc = test.toObject({ getters: false, virtuals: true }); delete doc._id; delete doc.id; - assert.deepEqual(doc, { 'nested.test': true }); + assert.deepEqual(doc, { nested: { test: true } }); db.close(done); }); }); From de52384c4756df0794bb61eacbffef4328149651 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 1 Dec 2015 14:34:39 -0500 Subject: [PATCH 0090/2240] repro; #3623 --- test/document.test.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 5bc4c305cf8..ff2fc07221f 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2175,4 +2175,37 @@ describe('document', function() { assert.deepEqual(doc, { nested: { test: true } }); db.close(done); }); + + it('handles pushing with numeric keys (gh-3623)', function(done) { + var db = start(); + var schema = new Schema({ + array: [{ + 1: { + date: Date + }, + 2: { + date: Date + }, + 3: { + date: Date + } + }] + }); + + var MyModel = db.model('gh3623', schema); + + var doc = { array: [{ 2: {} }] }; + MyModel.collection.insertOne(doc, function(error) { + assert.ifError(error); + + MyModel.findOne({ _id: doc._id }, function(error, doc) { + assert.ifError(error); + doc.array.push({ 2: {} }); + doc.save(function(error) { + assert.ifError(error); + db.close(done); + }); + }); + }); + }); }); From 0817b4a25969c7487ea773409025e2216b0fa2a0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 1 Dec 2015 14:35:52 -0500 Subject: [PATCH 0091/2240] fix(document): prevent setting nested toObject (Fix #3623) --- lib/document.js | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/document.js b/lib/document.js index b9e2227faa2..dc1045ac1b9 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1524,13 +1524,30 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { }); } - nested.toObject = function() { - return _self.get(path); - }; - - nested.toJSON = nested.toObject; - - nested.$__isNested = true; + Object.defineProperty(nested, 'toObject', { + enumerable: true, + configurable: true, + writable: false, + value: function() { + return _self.get(path); + } + }); + + Object.defineProperty(nested, 'toJSON', { + enumerable: true, + configurable: true, + writable: false, + value: function() { + return _self.get(path); + } + }); + + Object.defineProperty(nested, '$__isNested', { + enumerable: true, + configurable: true, + writable: false, + value: true + }); compile(subprops, nested, path, options); this.$__.getters[path] = nested; From 3a4eb65e45a454304e525eb35512d7cccfe891ab Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 2 Dec 2015 10:57:39 -0500 Subject: [PATCH 0092/2240] docs; setDefaultsOnInsert docs --- docs/includes/nav.jade | 3 ++ docs/source/acquit.js | 5 ++ test/docs/defaults.test.js | 93 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 test/docs/defaults.test.js diff --git a/docs/includes/nav.jade b/docs/includes/nav.jade index 2047d2a6eb9..80d5a1cfe0a 100644 --- a/docs/includes/nav.jade +++ b/docs/includes/nav.jade @@ -32,6 +32,9 @@ ul li.subdocs a(href="./subdocs.html") | sub docs + li.defaults + a(href="./defaults.html") + | defaults li a(href="./queries.html") | queries diff --git a/docs/source/acquit.js b/docs/source/acquit.js index e260fcefabf..066643dc102 100644 --- a/docs/source/acquit.js +++ b/docs/source/acquit.js @@ -5,6 +5,11 @@ var marked = require('marked'); require('acquit-ignore')(); var files = [ + { + input: 'test/docs/defaults.test.js', + output: 'defaults.html', + title: 'Defaults' + }, { input: 'test/docs/discriminators.test.js', output: 'discriminators.html', diff --git a/test/docs/defaults.test.js b/test/docs/defaults.test.js new file mode 100644 index 00000000000..258848f34e5 --- /dev/null +++ b/test/docs/defaults.test.js @@ -0,0 +1,93 @@ +var assert = require('assert'); +var async = require('async'); +var mongoose = require('../../'); + +describe('defaults docs', function() { + var db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test'); + var Schema = mongoose.Schema; + + /** + * Your schemas can define default values for certain paths. If you create + * a new document without that path set, the default will kick in. + */ + it('Declaring defaults in your schema', function() { + var schema = new Schema({ + name: String, + role: { type: String, default: 'guitarist' } + }); + + var Person = db.model('Person', schema); + + var axl = new Person({ name: 'Axl Rose', role: 'singer' }); + assert.equal(axl.role, 'singer'); + + var slash = new Person({ name: 'Slash' }); + assert.equal(slash.role, 'guitarist'); + }); + + /** + * You can also set the `default` schema option to a function. Mongoose will + * execute that function and use the return value as the default. + */ + it('Default functions', function() { + var schema = new Schema({ + title: String, + date: { + type: Date, + // `Date.now()` returns the current unix timestamp as a number + default: Date.now + } + }); + + var BlogPost = db.model('BlogPost', schema); + + var post = new BlogPost({ title: '5 Best Arnold Schwarzenegger Movies' }); + + // The post has a default Date set to now + assert.ok(post.date.getTime() >= Date.now() - 1000); + assert.ok(post.date.getTime() <= Date.now()); + }); + + /** + * By default, mongoose only applies defaults when you create a new document. + * It will **not** set defaults if you use `update()` and + * `findOneAndUpdate()`. However, mongoose 4.x lets you opt-in to this + * behavior using the `setDefaultsOnInsert` option. + * + * ## Important + * + * The `setDefaultsOnInsert` option relies on the + * [MongoDB `$setOnInsert` operator](https://docs.mongodb.org/manual/reference/operator/update/setOnInsert/). + * The `$setOnInsert` operator was introduced in MongoDB 2.4. If you're + * using MongoDB server < 2.4.0, do **not** use `setDefaultsOnInsert`. + */ + it('The `setDefaultsOnInsert` option', function(done) { + var schema = new Schema({ + title: String, + genre: { type: String, default: 'Action' } + }); + + var Movie = db.model('Movie', schema); + + var query = {}; + var update = { title: 'The Terminator' }; + var options = { + // Return the document after updates are applied + 'new': true, + // Create a document if one isn't found. Required + // for `setDefaultsOnInsert` + upsert: true, + setDefaultsOnInsert: true + }; + + Movie. + findOneAndUpdate(query, update, options, function(error, doc) { + assert.ifError(error); + assert.equal(doc.title, 'The Terminator'); + assert.equal(doc.genre, 'Action'); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); +}); From 299ece85afb11062fcf7be2084e7769e20977dca Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 2 Dec 2015 14:28:43 -0500 Subject: [PATCH 0093/2240] release 4.2.9 --- History.md | 7 +++++++ bin/mongoose.js | 45 ++++++++++++++++++++++++++++++++++++--------- package.json | 2 +- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/History.md b/History.md index 3e324e297ad..73d514c854d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.2.9 / 2015-12-02 +================== + * docs; defaults docs #3625 + * fix; nested numeric keys causing an embedded document crash #3623 + * fix; apply path getters before virtual getters #3618 + * fix; casting for arrays in single nested schemas #3616 + 4.2.8 / 2015-11-25 ================== * docs; clean up README links #3612 [ReadmeCritic](https://github.com/ReadmeCritic) diff --git a/bin/mongoose.js b/bin/mongoose.js index fbecc9a1943..efc06f81318 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -1977,13 +1977,30 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { }); } - nested.toObject = function() { - return _self.get(path); - }; + Object.defineProperty(nested, 'toObject', { + enumerable: true, + configurable: true, + writable: false, + value: function() { + return _self.get(path); + } + }); - nested.toJSON = nested.toObject; + Object.defineProperty(nested, 'toJSON', { + enumerable: true, + configurable: true, + writable: false, + value: function() { + return _self.get(path); + } + }); - nested.$__isNested = true; + Object.defineProperty(nested, '$__isNested', { + enumerable: true, + configurable: true, + writable: false, + value: true + }); compile(subprops, nested, path, options); this.$__.getters[path] = nested; @@ -2267,10 +2284,6 @@ Document.prototype.$toObject = function(options, json) { var ret = clone(this._doc, options) || {}; - if (options.virtuals || options.getters && false !== options.virtuals) { - applyGetters(this, ret, 'virtuals', options); - } - if (options.getters) { applyGetters(this, ret, 'paths', options); // applyGetters for paths will add nested empty objects; @@ -2280,6 +2293,10 @@ Document.prototype.$toObject = function(options, json) { } } + if (options.virtuals || options.getters && false !== options.virtuals) { + applyGetters(this, ret, 'virtuals', options); + } + if (options.versionKey === false && this.schema.options.versionKey) { delete ret[this.schema.options.versionKey]; } @@ -3737,6 +3754,7 @@ function Schema(obj, options) { this.paths = {}; this.subpaths = {}; this.virtuals = {}; + this.singleNestedPaths = {}; this.nested = {}; this.inherits = {}; this.callQueue = []; @@ -4164,6 +4182,12 @@ Schema.prototype.path = function(path, obj) { branch[last] = utils.clone(obj); this.paths[path] = Schema.interpretAsType(path, obj, this.options); + if (this.paths[path].$isSingleNested) { + for (var key in this.paths[path].schema.paths) { + this.singleNestedPaths[path + '.' + key] = + this.paths[path].schema.paths[key]; + } + } return this; }; @@ -4326,6 +4350,9 @@ Schema.prototype.pathType = function(path) { if (path in this.virtuals) return 'virtual'; if (path in this.nested) return 'nested'; if (path in this.subpaths) return 'real'; + if (path in this.singleNestedPaths) { + return 'real'; + } if (/\.\d+\.|\.\d+$/.test(path)) { return getPositionalPathType(this, path); diff --git a/package.json b/package.json index d32609ae6ed..f127ee08c16 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.2.9-pre", + "version": "4.2.9", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 49b917fe60c0b1bd778f5cd03026db06882a5482 Mon Sep 17 00:00:00 2001 From: Pranu Sarna Date: Thu, 3 Dec 2015 20:51:18 +0530 Subject: [PATCH 0094/2240] Update virtuals.html I think the grammar here is not entirely correct. made suitable changes --- docs/2.7.x/docs/virtuals.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/2.7.x/docs/virtuals.html b/docs/2.7.x/docs/virtuals.html index 37c98a4e04a..ac7678ad2b5 100644 --- a/docs/2.7.x/docs/virtuals.html +++ b/docs/2.7.x/docs/virtuals.html @@ -224,7 +224,7 @@

Example

} }); -If you want virtual field should be display on client side, then +If you want the virtual field to be displayed on client side, then set {virtuals: true} for toObject and toJSON in schema options as below:
var PersonSchema = new Schema({

From 88d6884aeeed9accb48d9f4df070b23b53441954 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 3 Dec 2015 13:48:33 -0500
Subject: [PATCH 0095/2240] now working on 4.2.10

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index f127ee08c16..33f4f10efd6 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.2.9",
+  "version": "4.2.10-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From a3b363a39d81b4028e38f3b9f23b3878c139bad5 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 3 Dec 2015 15:26:15 -0500
Subject: [PATCH 0096/2240] repro: #3642

---
 test/document.test.js | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/test/document.test.js b/test/document.test.js
index ff2fc07221f..c6b732b87e2 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -2153,6 +2153,29 @@ describe('document', function() {
     });
   });
 
+  it('single embedded docs init obeys strict mode (gh-3642)', function(done) {
+    var db = start();
+    var personSchema = new Schema({ name: String });
+
+    var bandSchema = new Schema({ guitarist: personSchema, name: String });
+    var Band = db.model('gh3642', bandSchema);
+
+    var velvetRevolver = new Band({
+      name: 'Velvet Revolver',
+      guitarist: { name: 'Slash', realName: 'Saul Hudson' }
+    });
+
+    velvetRevolver.save(function(error) {
+      assert.ifError(error);
+      var query = { name: 'Velvet Revolver' };
+      Band.collection.findOne(query, function(error, band) {
+        assert.ifError(error);
+        assert.ok(!band.guitarist.realName);
+        db.close(done);
+      });
+    });
+  });
+
   it('handles virtuals with dots correctly (gh-3618)', function(done) {
     var db = start();
     var testSchema = new Schema({ nested: { type: Object, default: {} } });

From 80e190850bcae147ef82db9125df097a87310e84 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 3 Dec 2015 15:33:34 -0500
Subject: [PATCH 0097/2240] fix(embedded): single nested subdocs init properly

---
 lib/schema/embedded.js   | 8 ++++++--
 lib/types/subdocument.js | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js
index e6abec2d03b..9c32484148e 100644
--- a/lib/schema/embedded.js
+++ b/lib/schema/embedded.js
@@ -48,13 +48,17 @@ Embedded.prototype = Object.create(SchemaType.prototype);
  * @api private
  */
 
-Embedded.prototype.cast = function(val, doc) {
+Embedded.prototype.cast = function(val, doc, init) {
   if (val && val.$isSingleNested) {
     return val;
   }
   var subdoc = new this.caster();
   subdoc.$parent = doc;
-  subdoc = subdoc.init(val);
+  if (init) {
+    subdoc.init(val);
+  } else {
+    subdoc.set(val, undefined, true);
+  }
   return subdoc;
 };
 
diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js
index 73597d0e0a4..b5097f91339 100644
--- a/lib/types/subdocument.js
+++ b/lib/types/subdocument.js
@@ -58,7 +58,7 @@ Subdocument.prototype.$markValid = function(path) {
 Subdocument.prototype.invalidate = function(path, err, val) {
   if (this.$parent) {
     this.$parent.invalidate([this.$basePath, path].join('.'), err, val);
-  } else if (err.kind === 'cast') {
+  } else if (err.kind === 'cast' || err.name === 'CastError') {
     throw err;
   }
 };

From c7e5fc049ddb1ba87bf9cdef91ad3cd0b6177af4 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 3 Dec 2015 15:52:22 -0500
Subject: [PATCH 0098/2240] refactor(driver): pass callback to db.close (Fix
 #3645)

---
 lib/drivers/node-mongodb-native/connection.js | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js
index f13d5b2c214..7f3dd76ebc5 100644
--- a/lib/drivers/node-mongodb-native/connection.js
+++ b/lib/drivers/node-mongodb-native/connection.js
@@ -213,8 +213,7 @@ NativeConnection.prototype.doOpenSet = function(fn) {
  */
 
 NativeConnection.prototype.doClose = function(fn) {
-  this.db.close();
-  if (fn) fn();
+  this.db.close(fn);
   return this;
 };
 

From 79108046ad0c63ddd49a72f7e7fb76d1a4b3f6dd Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 3 Dec 2015 16:14:22 -0500
Subject: [PATCH 0099/2240] docs: Fix #3640

---
 docs/validation.jade | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/docs/validation.jade b/docs/validation.jade
index 180e986bec9..ef299325542 100644
--- a/docs/validation.jade
+++ b/docs/validation.jade
@@ -56,10 +56,9 @@ block content
   h3#validation-errors Validation errors
   :markdown
     Errors returned after failed validation contain an `errors` object
-    holding the actual `ValidatorError`s. Each
-    [ValidatorError](./api.html#error-validation-js) has a `type`, `path`,
-    and `value` property providing us with a little more error handling
-    flexibility.
+    holding the actual `ValidatorError` objects. Each
+    [ValidatorError](./api.html#error-validation-js) has `kind`, `path`,
+    `value`, and `message` properties.
   :js
     var toySchema = new Schema({
       color: String,
@@ -80,7 +79,7 @@ block content
 
       console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color with value `grease`'
       console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color with value `grease`'
-      console.log(err.errors.color.type)  // prints "Invalid color"
+      console.log(err.errors.color.kind)  // prints "Invalid color"
       console.log(err.errors.color.path)  // prints "color"
       console.log(err.errors.color.value) // prints "grease"
       console.log(err.name) // prints "ValidationError"

From f4657db62547e1fc7cf94828f6adcf4217095e3c Mon Sep 17 00:00:00 2001
From: Ujjwal Ojha 
Date: Fri, 4 Dec 2015 09:31:13 +0545
Subject: [PATCH 0100/2240] Update mocha website

---
 CONTRIBUTING.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 514657e448c..b3386ba83fd 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -37,7 +37,7 @@ If you have a question about Mongoose (not a bug report) please post it to eithe
 ### Running the tests
 - Open a terminal and navigate to the root of the project
 - execute `npm install` to install the necessary dependencies
-- execute `make test` to run the tests (we're using [mocha](http://visionmedia.github.com/mocha/))
+- execute `make test` to run the tests (we're using [mocha](http://mochajs.org/))
   - or to execute a single test `T="-g 'some regexp that matches the test description'" make test`
   - any mocha flags can be specified with `T="..."`
 

From 13600b7434b413c4d7e9bc6fbdf839e8ac46fa7f Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 4 Dec 2015 13:38:21 -0500
Subject: [PATCH 0101/2240] docs(query): clarify model parameter to .populate()
 re: #3639

---
 lib/query.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/query.js b/lib/query.js
index b74586d58f2..b57a3ceab91 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -2488,7 +2488,7 @@ function castDoc(query, overwrite) {
  *
  * @param {Object|String} path either the path to populate or an object specifying all parameters
  * @param {Object|String} [select] Field selection for the population query
- * @param {Model} [model] The name of the model you wish to use for population. If not specified, the name is looked up from the Schema ref.
+ * @param {Model} [model] The model you wish to use for population. If not specified, populate will look up the model by the name in the Schema's `ref` field.
  * @param {Object} [match] Conditions for the population query
  * @param {Object} [options] Options for the population query (sort, etc)
  * @see population ./populate.html

From c6626bf7d2d31a223414816c55629c25c75330cc Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sun, 6 Dec 2015 12:49:31 -0500
Subject: [PATCH 0102/2240] docs(populate): cross-db populate

---
 docs/populate.jade | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/docs/populate.jade b/docs/populate.jade
index 115def52e59..dba890e98eb 100644
--- a/docs/populate.jade
+++ b/docs/populate.jade
@@ -222,6 +222,43 @@ block content
         // Get friends of friends - populate the 'friends' array for every friend
         populate: { path: 'friends' }
       });
+  
+  h3#cross-db-populate Populating across Databases
+  :markdown
+    Let's say you have a schema representing events, and a schema representing
+    conversations. Each event has a corresponding conversation thread.
+  :js
+    var eventSchema = new Schema({
+      name: String,
+      // The id of the corresponding conversation
+      // Notice there's no ref here!
+      conversation: ObjectId
+    });
+    var conversationSchema = new Schema({
+      numMessages: Number
+    });
+  :markdown
+    Also, suppose that events and conversations are stored in separate MongoDB
+    instances.
+  :js
+    var db1 = mongoose.createConnection('localhost:27000/db1');
+    var db2 = mongoose.createConnection('localhost:27001/db2');
+    
+    var Event = db1.model('Event', eventSchema);
+    var Conversation = db2.model('Conversation', conversationSchema);
+  :markdown
+    In this situation, you will **not** be able to `populate()` normally.
+    The `conversation` field will always be null, because `populate()` doesn't
+    know which model to use. However,
+    [you can specify the model explicitly](http://mongoosejs.com/docs/api.html#model_Model.populate).
+  :js
+    Event.
+      find().
+      populate({ path: 'conversation', model: Conversation }).
+      exec(function(error, docs) { /* ... */ });
+  :markdown
+    This is known as a "cross-database populate," because it enables you to
+    populate across MongoDB databases and even acrosss MongoDB instances.
 
   h3#next Next Up
   :markdown

From 17e30be40a92526ba83adc291d999c6e867f3ba8 Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Mon, 7 Dec 2015 16:28:33 -0700
Subject: [PATCH 0103/2240] update marked

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 33f4f10efd6..0a60e4ea78e 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,7 @@
     "istanbul": "^0.3.13",
     "jade": "0.26.3",
     "markdown": "0.3.1",
-    "marked": "0.3.2",
+    "marked": "0.3.5",
     "mocha": "1.20.0",
     "node-static": "0.5.9",
     "open": "0.0.3",

From 668d1fdec71d9d4b18f8631e5ee3cab1b115b70a Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 8 Dec 2015 13:55:26 -0500
Subject: [PATCH 0104/2240] release 4.2.10

---
 History.md      | 10 ++++++++++
 bin/mongoose.js | 10 +++++++---
 package.json    |  2 +-
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/History.md b/History.md
index 73d514c854d..6fb61fc586a 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,13 @@
+4.2.10 /2015-12-08
+==================
+ * fixed; upgraded marked #3653 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * docs; cross-db populate #3648
+ * docs; update mocha URL #3646 [ojhaujjwal](https://github.com/ojhaujjwal)
+ * fixed; call close callback asynchronously #3645
+ * docs; virtuals.html issue #3644 [Psarna94](https://github.com/Psarna94)
+ * fixed; single embedded doc casting on init #3642
+ * docs; validation docs improvements #3640
+
 4.2.9 / 2015-12-02
 ==================
  * docs; defaults docs #3625
diff --git a/bin/mongoose.js b/bin/mongoose.js
index efc06f81318..e2249e82264 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -6220,13 +6220,17 @@ Embedded.prototype = Object.create(SchemaType.prototype);
  * @api private
  */
 
-Embedded.prototype.cast = function(val, doc) {
+Embedded.prototype.cast = function(val, doc, init) {
   if (val && val.$isSingleNested) {
     return val;
   }
   var subdoc = new this.caster();
   subdoc.$parent = doc;
-  subdoc = subdoc.init(val);
+  if (init) {
+    subdoc.init(val);
+  } else {
+    subdoc.set(val, undefined, true);
+  }
   return subdoc;
 };
 
@@ -10110,7 +10114,7 @@ Subdocument.prototype.$markValid = function(path) {
 Subdocument.prototype.invalidate = function(path, err, val) {
   if (this.$parent) {
     this.$parent.invalidate([this.$basePath, path].join('.'), err, val);
-  } else if (err.kind === 'cast') {
+  } else if (err.kind === 'cast' || err.name === 'CastError') {
     throw err;
   }
 };
diff --git a/package.json b/package.json
index 0a60e4ea78e..7080a4f236d 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.2.10-pre",
+  "version": "4.2.10",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From a986f4366e40e090c697b152c323c6dc41191610 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 8 Dec 2015 14:01:16 -0500
Subject: [PATCH 0105/2240] now working on 4.3.0

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 7080a4f236d..f7773ab6875 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.2.10",
+  "version": "4.3.0-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From cc522d2e152f83c3431d7ff919101dd92818b781 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 8 Dec 2015 16:03:24 -0500
Subject: [PATCH 0106/2240] chore: upgrade to node driver 2.1.0

---
 package.json                        |  2 +-
 test/collection.capped.test.js      | 16 ++++++---
 test/common.js                      |  4 ++-
 test/connection.auth.test.js        |  4 +--
 test/docs/defaults.test.js          | 10 +++++-
 test/docs/discriminators.test.js    |  8 ++++-
 test/docs/promises.test.js          |  7 ++--
 test/document.hooks.test.js         |  2 +-
 test/document.populate.test.js      |  2 +-
 test/document.test.js               |  2 +-
 test/model.field.selection.test.js  |  4 +--
 test/model.findOneAndUpdate.test.js |  8 ++---
 test/model.query.casting.test.js    |  2 +-
 test/model.querying.test.js         |  6 ++--
 test/model.test.js                  |  6 ++--
 test/model.update.test.js           | 12 +++----
 test/promise_provider.test.js       |  9 +++--
 test/query.test.js                  | 31 ++++++++---------
 test/schema.timestamps.test.js      |  4 ++-
 test/schema.validation.test.js      |  4 +--
 test/types.array.test.js            | 52 ++++++++++++++++++++---------
 test/utils.test.js                  | 14 ++++----
 test/versioning.test.js             | 43 +++++++++++-------------
 23 files changed, 148 insertions(+), 104 deletions(-)

diff --git a/package.json b/package.json
index f7773ab6875..9cb0b24364e 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
     "bson": "0.4.19",
     "hooks-fixed": "1.1.0",
     "kareem": "1.0.1",
-    "mongodb": "2.0.49",
+    "mongodb": "2.1.0",
     "mpath": "0.1.1",
     "mpromise": "0.5.4",
     "mquery": "1.6.3",
diff --git a/test/collection.capped.test.js b/test/collection.capped.test.js
index 454eb32d7a4..81460945a3d 100644
--- a/test/collection.capped.test.js
+++ b/test/collection.capped.test.js
@@ -21,13 +21,22 @@ var coll = 'capped_' + random();
  */
 
 describe('collections: capped:', function() {
+  var db;
+
+  before(function() {
+    db = start();
+  });
+
+  after(function(done) {
+    db.close(done);
+  });
+
   it('schemas should have option size', function(done) {
     assert.ok(capped.options.capped);
     assert.equal(1000, capped.options.capped.size);
     done();
   });
   it('creation', function(done) {
-    var db = start();
     var Capped = db.model('Capped', capped, coll);
     Capped.collection.isCapped(function(err, isCapped) {
       assert.ifError(err);
@@ -39,19 +48,18 @@ describe('collections: capped:', function() {
         assert.ifError(err);
         assert.ok(isCapped, 'should reuse the capped collection in the db');
         assert.equal(Capped.collection.name, Capped2.collection.name);
-        db.close(done);
+        done();
       });
     });
   });
   it('creation using a number', function(done) {
-    var db = start();
     var schema = new Schema({ key: 'string' }, { capped: 8192 });
     var Capped = db.model('Capped3', schema);
     Capped.collection.options(function(err, options) {
       assert.ifError(err);
       assert.ok(options.capped, 'should create a capped collection');
       assert.equal(8192, options.size);
-      db.close(done);
+      done();
     });
   });
   it('attempting to use existing non-capped collection as capped emits error', function(done) {
diff --git a/test/common.js b/test/common.js
index 03403a9e419..36698f55b53 100644
--- a/test/common.js
+++ b/test/common.js
@@ -119,7 +119,9 @@ module.exports.mongodVersion = function(cb) {
     admin.serverStatus(function(err, info) {
       if (err) return cb(err);
       var version = info.version.split('.').map(function(n) { return parseInt(n, 10); });
-      cb(null, version);
+      db.close(function() {
+        cb(null, version);
+      });
     });
   });
 };
diff --git a/test/connection.auth.test.js b/test/connection.auth.test.js
index e43ff7d8fe5..20bef230c16 100644
--- a/test/connection.auth.test.js
+++ b/test/connection.auth.test.js
@@ -12,7 +12,7 @@ describe('connection:', function() {
         assert.ok(conn.options);
         assert.ok(conn.options.auth);
         assert.equal('users', conn.options.auth.authSource);
-        done();
+        conn.close(done);
       };
       conn.open(start.uri + '?authSource=users');
     });
@@ -23,7 +23,7 @@ describe('connection:', function() {
         assert.ok(conn.options);
         assert.ok(conn.options.auth);
         assert.equal('users', conn.options.auth.authSource);
-        done();
+        conn.close(done);
       };
       conn.open(start.uri, { auth: { authSource: 'users' }});
     });
diff --git a/test/docs/defaults.test.js b/test/docs/defaults.test.js
index 258848f34e5..5eecf24fea6 100644
--- a/test/docs/defaults.test.js
+++ b/test/docs/defaults.test.js
@@ -3,9 +3,17 @@ var async = require('async');
 var mongoose = require('../../');
 
 describe('defaults docs', function() {
-  var db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
+  var db;
   var Schema = mongoose.Schema;
 
+  before(function() {
+    db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
+  });
+
+  after(function(done) {
+    db.close(done);
+  });
+
   /**
    * Your schemas can define default values for certain paths. If you create
    * a new document without that path set, the default will kick in.
diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js
index ab82c29e39a..74b14514f6e 100644
--- a/test/docs/discriminators.test.js
+++ b/test/docs/discriminators.test.js
@@ -6,9 +6,11 @@ describe('discriminator docs', function() {
   var Event;
   var ClickedLinkEvent;
   var SignedUpEvent;
-  var db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
+  var db;
 
   before(function(done) {
+    db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
+
     var options = { discriminatorKey: 'kind' };
 
     var eventSchema = new mongoose.Schema({ time: Date }, options);
@@ -23,6 +25,10 @@ describe('discriminator docs', function() {
     done();
   });
 
+  after(function(done) {
+    db.close(done);
+  });
+
   beforeEach(function(done) {
     Event.remove({}, done);
   });
diff --git a/test/docs/promises.test.js b/test/docs/promises.test.js
index 3497c07337d..748b4b7df36 100644
--- a/test/docs/promises.test.js
+++ b/test/docs/promises.test.js
@@ -4,9 +4,11 @@ var mongoose = require('../../');
 
 describe('promises docs', function() {
   var Band;
-  var db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
+  var db;
 
   before(function(done) {
+    db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
+
     Band = db.model('band-promises', { name: String, members: [String] });
 
     done();
@@ -16,8 +18,9 @@ describe('promises docs', function() {
     Band.remove({}, done);
   });
 
-  after(function() {
+  after(function(done) {
     PromiseProvider.reset();
+    db.close(done);
   });
 
   /**
diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index 0ad70da64f5..487cab7857a 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -809,7 +809,7 @@ describe('document: hooks:', function() {
     L1.create(data, function(error) {
       assert.ifError(error);
       assert.equal(calls, 1);
-      done();
+      db.close(done);
     });
   });
 });
diff --git a/test/document.populate.test.js b/test/document.populate.test.js
index abec505f2dc..520ff277d25 100644
--- a/test/document.populate.test.js
+++ b/test/document.populate.test.js
@@ -522,7 +522,7 @@ describe('document.populate', function() {
     gnr.guitarist = buckethead._id;
     assert.ok(!gnr.populated('guitarist'));
 
-    done();
+    db.close(done);
   });
 
   describe('gh-2214', function() {
diff --git a/test/document.test.js b/test/document.test.js
index c6b732b87e2..caebdc7e217 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -1928,7 +1928,7 @@ describe('document', function() {
     assert.ok(error.errors['user.email']);
     assert.equal(error.errors['user.email'].kind, 'regexp');
 
-    done();
+    db.close(done);
   });
 
   it('single embedded schemas with markmodified (gh-2689)', function(done) {
diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js
index eaad22e7bfb..2a33aeaf7f2 100644
--- a/test/model.field.selection.test.js
+++ b/test/model.field.selection.test.js
@@ -151,7 +151,7 @@ describe('model field selection', function() {
       MyModel.findOne({}, { _id: 1 }, function(error, doc) {
         assert.ifError(error);
         assert.ok(!doc.test);
-        done();
+        db.close(done);
       });
     });
   });
@@ -298,7 +298,7 @@ describe('model field selection', function() {
             assert.equal(found.id, doc.id);
             assert.equal(1, found.ids.length);
             assert.equal(_id2.toString(), found.ids[0].toString());
-            done();
+            db.close(done);
           });
         });
       });
diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index b157ded2d75..4f849bfa104 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -1022,7 +1022,7 @@ describe('model: findByIdAndUpdate:', function() {
     q.lean();
     q.exec(function(error, doc) {
       assert.ok(!doc.notInSchema);
-      done();
+      db.close(done);
     });
   });
 
@@ -1359,7 +1359,7 @@ describe('model: findByIdAndUpdate:', function() {
           },
           function(error) {
             assert.ifError(error);
-            done();
+            db.close(done);
           });
       });
     });
@@ -1385,7 +1385,7 @@ describe('model: findByIdAndUpdate:', function() {
           },
             function(error) {
               assert.ifError(error);
-              done();
+              db.close(done);
             });
       });
     });
@@ -1473,7 +1473,7 @@ describe('model: findByIdAndUpdate:', function() {
           assert.ifError(error);
           assert.ok(res);
           assert.ok(res.ok);
-          done();
+          db.close(done);
         });
     });
 
diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js
index 5150843ac98..cf69ace6e29 100644
--- a/test/model.query.casting.test.js
+++ b/test/model.query.casting.test.js
@@ -824,7 +824,7 @@ describe('model query casting', function() {
       MyModel.findOne({ tags: { $all: doc.tags } }, function(error, doc) {
         assert.ifError(error);
         assert.ok(doc);
-        done();
+        db.close(done);
       });
     });
   });
diff --git a/test/model.querying.test.js b/test/model.querying.test.js
index ff9a61771d2..cae4b71f45d 100644
--- a/test/model.querying.test.js
+++ b/test/model.querying.test.js
@@ -315,7 +315,7 @@ describe('model: querying:', function() {
 
       assert.ok(!query._update.$set.mixed);
 
-      done();
+      db.close(done);
     });
   });
 
@@ -679,7 +679,7 @@ describe('model: querying:', function() {
         BlogPostB.findById(undefined, function(err, doc) {
           assert.ifError(err);
           assert.equal(null, doc);
-          done();
+          db.close(done);
         });
       });
     });
@@ -2592,7 +2592,7 @@ describe('lean option:', function() {
         assert.equal(doc.dates.length, 1);
         assert.equal(doc.dates[0].getTime(),
           new Date('2014-07-01T04:00:00.000Z').getTime());
-        done();
+        db.close(done);
       });
     });
   });
diff --git a/test/model.test.js b/test/model.test.js
index 7532d55bece..214e008c51c 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -4417,7 +4417,7 @@ describe('Model', function() {
             B.findById(post, function(err, doc) {
               assert.ifError(err);
               assert.equal('changed', doc.title);
-              done();
+              db.close(done);
             });
           });
         });
@@ -4482,7 +4482,7 @@ describe('Model', function() {
                   assert.equal(2, b.numbers.length);
                   assert.equal(4, b.numbers[0]);
                   assert.equal(5, b.numbers[1]);
-                  done();
+                  db.close(done);
                 });
               });
             });
@@ -4755,7 +4755,7 @@ describe('Model', function() {
           assert.ifError(err);
           m.s = m.n = m.a = undefined;
           assert.equal(undefined, m.$__delta());
-          done();
+          db.close(done);
         });
       });
     });
diff --git a/test/model.update.test.js b/test/model.update.test.js
index 608033b0cbc..aef9cf6fcc7 100644
--- a/test/model.update.test.js
+++ b/test/model.update.test.js
@@ -1406,7 +1406,7 @@ describe('model: update:', function() {
         { runValidators: true },
         function(err) {
           assert.ok(err);
-          done();
+          db.close(done);
         });
     });
   });
@@ -1440,7 +1440,7 @@ describe('model: update:', function() {
           assert.equal(book.chapters.length, 2);
           assert.ok(book.chapters[0]._id);
           assert.ok(book.chapters[1]._id);
-          done();
+          db.close(done);
         });
       });
   });
@@ -1455,7 +1455,7 @@ describe('model: update:', function() {
 
     assert.doesNotThrow(function() {
       D.update({}, { d: undefined }, function() {
-        done();
+        db.close(done);
       });
     });
   });
@@ -1507,7 +1507,7 @@ describe('model: update:', function() {
     var update = { $set: { values: 2, value: 2 } };
     Model.update({ key: 1 }, update, function() {
       assert.equal(update.$set.values, 2);
-      done();
+      db.close(done);
     });
   });
 
@@ -1554,7 +1554,7 @@ describe('model: update:', function() {
         exec(function(error, res) {
           assert.ifError(error);
           assert.equal(res.n, 1);
-          done();
+          db.close(done);
         });
     });
   });
@@ -1576,7 +1576,7 @@ describe('model: update:', function() {
           Model.findById(m._id, function(error, doc) {
             assert.ifError(error);
             assert.equal(doc.attributes.scores.bar.length, 1);
-            done();
+            db.close(done);
           });
         });
     });
diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js
index baff19046ca..eb15958bfae 100644
--- a/test/promise_provider.test.js
+++ b/test/promise_provider.test.js
@@ -51,8 +51,9 @@ describe('ES6 promises: ', function() {
       MyModel = db.model('es6promise', testSchema);
     });
 
-    after(function() {
+    after(function(done) {
       PromiseProvider.reset();
+      db.close(done);
     });
 
     afterEach(function(done) {
@@ -186,8 +187,9 @@ describe('ES6 promises: ', function() {
       MyModel = db.model('es6promise_bluebird', testSchema);
     });
 
-    after(function() {
+    after(function(done) {
       PromiseProvider.reset();
+      db.close(done);
     });
 
     afterEach(function(done) {
@@ -326,8 +328,9 @@ describe('ES6 promises: ', function() {
       MyModel = db.model('es6promise_q', testSchema);
     });
 
-    after(function() {
+    after(function(done) {
       PromiseProvider.reset();
+      db.close(done);
     });
 
     afterEach(function(done) {
diff --git a/test/query.test.js b/test/query.test.js
index b9a960ac259..00a04d79b55 100644
--- a/test/query.test.js
+++ b/test/query.test.js
@@ -847,11 +847,19 @@ describe('Query', function() {
   });
 
   describe('casting', function() {
+    var db;
+
+    before(function() {
+      db = start();
+    });
+
+    after(function(done) {
+      db.close(done);
+    });
+
     it('to an array of mixed', function(done) {
       var query = new Query({}, {}, null, p1.collection);
-      var db = start();
       var Product = db.model('Product');
-      db.close();
       var params = { _id: new DocumentObjectId, tags: { $in: [ 4, 8, 15, 16 ] }};
       query.cast(Product, params);
       assert.deepEqual(params.tags.$in, [4,8,15,16]);
@@ -860,10 +868,8 @@ describe('Query', function() {
 
     it('find $ne should not cast single value to array for schematype of Array', function(done) {
       var query = new Query({}, {}, null, p1.collection);
-      var db = start();
       var Product = db.model('Product');
       var Comment = db.model('Comment');
-      db.close();
 
       var id = new DocumentObjectId;
       var castedComment = { _id: id, text: 'hello there' };
@@ -906,9 +912,7 @@ describe('Query', function() {
 
     it('subdocument array with $ne: null should not throw', function(done) {
       var query = new Query({}, {}, null, p1.collection);
-      var db = start();
       var Product = db.model('Product');
-      db.close();
 
       var params = {
         comments: { $ne: null }
@@ -921,10 +925,8 @@ describe('Query', function() {
 
     it('find should not cast single value to array for schematype of Array', function(done) {
       var query = new Query({}, {}, null, p1.collection);
-      var db = start();
       var Product = db.model('Product');
       var Comment = db.model('Comment');
-      db.close();
 
       var id = new DocumentObjectId;
       var castedComment = { _id: id, text: 'hello there' };
@@ -967,9 +969,7 @@ describe('Query', function() {
 
     it('an $elemMatch with $in works (gh-1100)', function(done) {
       var query = new Query({}, {}, null, p1.collection);
-      var db = start();
       var Product = db.model('Product');
-      db.close();
       var ids = [String(new DocumentObjectId), String(new DocumentObjectId)];
       var params = { ids: { $elemMatch: { $in: ids }}};
       query.cast(Product, params);
@@ -982,10 +982,8 @@ describe('Query', function() {
 
     it('inequality operators for an array', function(done) {
       var query = new Query({}, {}, null, p1.collection);
-      var db = start();
       var Product = db.model('Product');
       var Comment = db.model('Comment');
-      db.close();
 
       var id = new DocumentObjectId;
       var castedComment = { _id: id, text: 'hello there' };
@@ -1014,9 +1012,8 @@ describe('Query', function() {
       var prod = new Product({});
       var q = new Query({}, {}, Product, prod.collection).distinct('blah', function() {
         assert.equal(q.op,'distinct');
-        db.close();
+        db.close(done);
       });
-      done();
     });
   });
 
@@ -1073,7 +1070,7 @@ describe('Query', function() {
       var promise = Product.findOne();
 
       promise.then(function() {
-        done();
+        db.close(done);
       }, function(err) {
         assert.ifError(err);
       });
@@ -1533,7 +1530,7 @@ describe('Query', function() {
 
     assert.deepEqual(Object.keys(q.getUpdate().$push.arr.$sort),
      ['value', 'date']);
-    done();
+    db.close(done);
   });
 
   it('handles nested $ (gh-3265)', function(done) {
@@ -1556,7 +1553,7 @@ describe('Query', function() {
 
     assert.deepEqual(q.getUpdate().$set['answers.$'].stats,
       { votes: 1, count: 3 });
-    done();
+    db.close(done);
   });
 
   describe('handles falsy and object projections with defaults (gh-3256)', function() {
diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js
index 3107b24b83e..9f68a61416f 100644
--- a/test/schema.timestamps.test.js
+++ b/test/schema.timestamps.test.js
@@ -119,7 +119,9 @@ describe('schema options.timestamps', function() {
     });
 
     after(function(done) {
-      Cat.remove({}, done);
+      Cat.remove({}, function() {
+        conn.close(done);
+      });
     });
   });
 
diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js
index 6c1b341d3f1..7bc2d73bd77 100644
--- a/test/schema.validation.test.js
+++ b/test/schema.validation.test.js
@@ -158,8 +158,8 @@ describe('schema', function() {
           Person = db.model('person-schema-validation-test', PersonSchema);
         });
 
-        after(function() {
-          db.close();
+        after(function(done) {
+          db.close(done);
         });
 
         it('and can be set to "undefined" (gh-1594)', function(done) {
diff --git a/test/types.array.test.js b/test/types.array.test.js
index 3eed1259c15..2624ac2d66c 100644
--- a/test/types.array.test.js
+++ b/test/types.array.test.js
@@ -96,7 +96,6 @@ describe('types array', function() {
           tj.save(function(err) {
             assert.ifError(err);
             User.findOne({ name: 'tj' }, function(err, user) {
-              db.close();
               assert.ifError(err);
               assert.equal(user.pets.length, 3);
               assert.equal(user.pets.indexOf(tobi.id),0);
@@ -105,7 +104,7 @@ describe('types array', function() {
               assert.equal(user.pets.indexOf(tobi._id),0);
               assert.equal(user.pets.indexOf(loki._id),1);
               assert.equal(user.pets.indexOf(jane._id),2);
-              done();
+              db.close(done);
             });
           });
         });
@@ -307,10 +306,19 @@ describe('types array', function() {
   });
 
   describe('splice()', function() {
+    var db;
+
+    before(function() {
+      db = start();
+    });
+
+    after(function(done) {
+      db.close(done);
+    });
+
     it('works', function(done) {
       var collection = 'splicetest-number' + random();
-      var db = start()
-        , schema = new Schema({ numbers: [Number] })
+      var schema = new Schema({ numbers: [Number] })
         , A = db.model('splicetestNumber', schema, collection);
 
       var a = new A({ numbers: [4,5,6,7] });
@@ -329,7 +337,6 @@ describe('types array', function() {
               assert.deepEqual(doc.numbers.toObject(), [4,10,6,7]);
 
               A.collection.drop(function(err) {
-                db.close();
                 assert.ifError(err);
                 done();
               });
@@ -341,8 +348,7 @@ describe('types array', function() {
 
     it('on embedded docs', function(done) {
       var collection = 'splicetest-embeddeddocs' + random();
-      var db = start()
-        , schema = new Schema({ types: [new Schema({ type: String }) ]})
+      var schema = new Schema({ types: [new Schema({ type: String }) ]})
         , A = db.model('splicetestEmbeddedDoc', schema, collection);
 
       var a = new A({ types: [{type:'bird'},{type:'boy'},{type:'frog'},{type:'cloud'}] });
@@ -364,7 +370,6 @@ describe('types array', function() {
           doc.save(function(err) {
             assert.ifError(err);
             A.findById(a._id, function(err, doc) {
-              db.close();
               assert.ifError(err);
 
               var obj = doc.types.toObject();
@@ -379,9 +384,18 @@ describe('types array', function() {
   });
 
   describe('unshift()', function() {
+    var db;
+
+    before(function() {
+      db = start();
+    });
+
+    after(function(done) {
+      db.close(done);
+    });
+
     it('works', function(done) {
-      var db = start()
-        , schema = new Schema({
+      var schema = new Schema({
           types: [new Schema({ type: String })]
             , nums: [Number]
             , strs: [String]
@@ -431,7 +445,6 @@ describe('types array', function() {
           doc.save(function(err) {
             assert.ifError(err);
             A.findById(a._id, function(err, doc) {
-              db.close();
               assert.ifError(err);
 
               var obj = doc.types.toObject();
@@ -461,7 +474,6 @@ describe('types array', function() {
     });
 
     it('applies setters (gh-3032)', function(done) {
-      var db = start();
       var ST = db.model('setterArray', Schema({ arr: [{
         type: String,
         lowercase: true
@@ -482,16 +494,24 @@ describe('types array', function() {
           assert.strictEqual('one', doc.arr[1]);
           assert.strictEqual('two', doc.arr[2]);
 
-          db.close(done);
+          done();
         });
       });
     });
   });
 
   describe('shift()', function() {
+    var db;
+    before(function() {
+      db = start();
+    });
+
+    after(function(done) {
+      db.close(done);
+    });
+
     it('works', function(done) {
-      var db = start()
-        , schema = new Schema({
+      var schema = new Schema({
           types: [new Schema({ type: String })]
             , nums: [Number]
             , strs: [String]
@@ -744,7 +764,7 @@ describe('types array', function() {
             assert.equal(gnr.members[1].name, 'Izzy');
             assert.equal(gnr.members[2].name, 'Duff');
             assert.equal(gnr.members[3].name, 'Adler');
-            done();
+            db.close(done);
           });
         });
       });
diff --git a/test/utils.test.js b/test/utils.test.js
index 98bdf4c113d..b00e41a43a6 100644
--- a/test/utils.test.js
+++ b/test/utils.test.js
@@ -310,11 +310,11 @@ describe('utils', function() {
   describe('pluralize', function() {
     var db;
 
-    beforeEach(function() {
+    before(function() {
       db = start();
     });
 
-    afterEach(function(done) {
+    after(function(done) {
       db.close(done);
     });
 
@@ -353,7 +353,7 @@ describe('utils', function() {
 
         var ASchema = new Schema({value: String});
 
-        var collectionName = 'singular';
+        var collectionName = 'one';
         var A = db.model(collectionName, ASchema);
         assert.equal(A.collection.name, collectionName + 's');
         done();
@@ -363,7 +363,7 @@ describe('utils', function() {
 
         var ASchema = new Schema({value: String});
 
-        var collectionName = 'singular';
+        var collectionName = 'two';
         var A = db.model(collectionName, ASchema);
         assert.equal(A.collection.name, collectionName);
         done();
@@ -374,7 +374,7 @@ describe('utils', function() {
         // override
         var ASchema = new Schema({value: String}, {pluralization: true});
 
-        var collectionName = 'singular';
+        var collectionName = 'three';
         var A = db.model(collectionName, ASchema);
         assert.equal(A.collection.name, collectionName + 's');
         done();
@@ -384,7 +384,7 @@ describe('utils', function() {
 
         var ASchema = new Schema({value: String}, {pluralization: false});
 
-        var collectionName = 'singular';
+        var collectionName = 'four';
         var A = db.model(collectionName, ASchema);
         assert.equal(A.collection.name, collectionName);
         done();
@@ -392,7 +392,7 @@ describe('utils', function() {
       it('should not pluralize when local option set to false and global not set', function(done) {
         var ASchema = new Schema({value: String}, {pluralization: false});
 
-        var collectionName = 'singular';
+        var collectionName = 'five';
         var A = db.model(collectionName, ASchema);
         assert.equal(A.collection.name, collectionName);
         done();
diff --git a/test/versioning.test.js b/test/versioning.test.js
index f8601a44892..6a777add548 100644
--- a/test/versioning.test.js
+++ b/test/versioning.test.js
@@ -49,6 +49,16 @@ var BlogPost = new Schema({
 mongoose.model('Versioning', BlogPost);
 
 describe('versioning', function() {
+  var db;
+
+  before(function() {
+    db = start();
+  });
+
+  after(function(done) {
+    db.close(done);
+  });
+
   it('is only added to parent schema (gh-1265)', function(done) {
     assert.ok(BlogPost.path('__v'));
     assert.ok(!BlogPost.path('comments').__v);
@@ -57,8 +67,7 @@ describe('versioning', function() {
   });
 
   it('works', function(done) {
-    var db = start()
-      , V = db.model('Versioning');
+    var V = db.model('Versioning');
 
     var doc = new V;
     doc.title = 'testing versioning';
@@ -270,7 +279,6 @@ describe('versioning', function() {
 
     function test15(err, a) {
       assert.equal(a._doc.__v, 13, 'version should not be incremented for non-versioned sub-document fields');
-      db.close();
       done();
     }
 
@@ -302,8 +310,7 @@ describe('versioning', function() {
   });
 
   it('versioning without version key', function(done) {
-    var db = start()
-      , V = db.model('Versioning');
+    var V = db.model('Versioning');
 
     var doc = new V;
     doc.numbers = [3,4,5,6,7];
@@ -320,7 +327,6 @@ describe('versioning', function() {
       assert.ifError(err);
       // test getting docs back from db missing version key
       V.findById(doc).select('numbers comments').exec(function(err, doc) {
-        db.close();
         assert.ifError(err);
         doc.comments[0].title = 'no version was included';
         var d = doc.$__delta();
@@ -331,7 +337,6 @@ describe('versioning', function() {
   });
 
   it('version works with strict docs', function(done) {
-    var db = start();
     var schema = new Schema({ str: ['string'] }, { strict: true, collection: 'versionstrict_' + random() });
     var M = db.model('VersionStrict', schema);
     var m = new M({ str: ['death', 'to', 'smootchy'] });
@@ -346,7 +351,6 @@ describe('versioning', function() {
         m.save(function(err) {
           assert.ifError(err);
           M.findById(m, function(err, m) {
-            db.close();
             assert.ifError(err);
             assert.equal(1, m._doc.__v);
             assert.equal(2, m.str.length);
@@ -359,8 +363,7 @@ describe('versioning', function() {
   });
 
   it('version works with existing unversioned docs', function(done) {
-    var db = start()
-      , V = db.model('Versioning');
+    var V = db.model('Versioning');
 
     V.collection.insert({ title: 'unversioned', numbers: [1,2,3] }, {safe:true}, function(err) {
       assert.ifError(err);
@@ -376,7 +379,6 @@ describe('versioning', function() {
           assert.ifError(err);
           assert.equal(1, d._doc.__v);
           V.findById(d, function(err, d) {
-            db.close();
             assert.ifError(err);
             assert.ok(d);
             done();
@@ -387,7 +389,6 @@ describe('versioning', function() {
   });
 
   it('versionKey is configurable', function(done) {
-    var db = start();
     var schema = new Schema(
         { configured: 'bool' }
       , { versionKey: 'lolwat', collection: 'configuredversion' + random() });
@@ -396,7 +397,6 @@ describe('versioning', function() {
     v.save(function(err) {
       assert.ifError(err);
       V.findById(v, function(err, v) {
-        db.close();
         assert.ifError(err);
         assert.equal(0, v._doc.lolwat);
         done();
@@ -405,7 +405,6 @@ describe('versioning', function() {
   });
 
   it('can be disabled', function(done) {
-    var db = start();
     var schema = Schema({ x: ['string'] }, { versionKey: false });
     var M = db.model('disabledVersioning', schema, 's' + random());
     M.create({ x: ['hi'] }, function(err, doc) {
@@ -422,28 +421,26 @@ describe('versioning', function() {
 
         M.collection.findOne({ _id: doc._id }, function(err, doc) {
           assert.equal(false, '__v' in doc);
-          db.close(done);
+          done();
         });
       });
     });
   });
 
   it('works with numbericAlpha paths', function(done) {
-    var db = start();
     var M = db.model('Versioning');
     var m = new M({ mixed: {} });
     var path = 'mixed.4a';
     m.set(path, 2);
     m.save(function(err) {
       assert.ifError(err);
-      db.close(done);
+      done();
     });
   });
 
   describe('doc.increment()', function() {
     it('works without any other changes (gh-1475)', function(done) {
-      var db = start()
-        , V = db.model('Versioning');
+      var V = db.model('Versioning');
 
       var doc = new V;
       doc.save(function(err) {
@@ -460,7 +457,7 @@ describe('versioning', function() {
           V.findById(doc, function(err, doc) {
             assert.ifError(err);
             assert.equal(1, doc.__v);
-            db.close(done);
+            done();
           });
         });
       });
@@ -481,7 +478,6 @@ describe('versioning', function() {
   });
 
   it('gh-1898', function(done) {
-    var db = start();
     var schema = new Schema({ tags: [String], name: String });
 
     var M = db.model('gh-1898', schema, 'gh-1898');
@@ -498,12 +494,11 @@ describe('versioning', function() {
 
       assert.equal(m.$__where(m.$__delta()[0]).__v, 0);
       assert.equal(m.$__delta()[1].$inc.__v, 1);
-      db.close(done);
+      done();
     });
   });
 
   it('can remove version key from toObject() (gh-2675)', function(done) {
-    var db = start();
     var schema = new Schema({ name: String });
     var M = db.model('gh2675', schema, 'gh2675');
 
@@ -514,7 +509,7 @@ describe('versioning', function() {
       assert.equal(0, obj.__v);
       obj = m.toObject({ versionKey: false });
       assert.equal(undefined, obj.__v);
-      db.close(done);
+      done();
     });
   });
 });

From 6ce343fb9b83b96fe9082aafd51c6b8c40aa6e55 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 8 Dec 2015 16:09:37 -0500
Subject: [PATCH 0107/2240] chore: account for slow dropDBs

---
 test/common.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/test/common.js b/test/common.js
index 36698f55b53..857037f8ff0 100644
--- a/test/common.js
+++ b/test/common.js
@@ -152,6 +152,7 @@ before(function(done) {
   dropDBs(done);
 });
 after(function(done) {
-  this.timeout(10 * 1000);
+  // DropDBs can be extraordinarily slow on 3.2
+  this.timeout(120 * 1000);
   dropDBs(done);
 });

From a74f7533c744dc59ef3730cb9f72b62707b791e9 Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Tue, 8 Dec 2015 16:26:16 -0700
Subject: [PATCH 0108/2240] comma last style in tests

---
 test/aggregate.test.js                    |  48 +++---
 test/browser/document.test_.js            |   4 +-
 test/browser/schema.test_.js              | 172 +++++++++++-----------
 test/browser/schema.validation.test_.js   |  32 ++--
 test/collection.capped.test.js            |  10 +-
 test/collection.test.js                   |  22 +--
 test/common.js                            |  37 ++---
 test/connection.test.js                   |  10 +-
 test/crash.test.js                        |   6 +-
 test/docs/defaults.test.js                |   1 -
 test/document.hooks.test.js               |  89 ++++++-----
 test/document.isselected.test.js          | 144 +++++++++---------
 test/document.modified.test.js            | 148 +++++++++----------
 test/document.populate.test.js            | 124 ++++++++--------
 test/document.strict.test.js              |  44 +++---
 test/document.test.js                     |  28 ++--
 test/errors.validation.test.js            |  56 +++----
 test/gh-1408.test.js                      |   8 +-
 test/index.test.js                        |  74 +++++-----
 test/model.aggregate.test.js              |  16 +-
 test/model.create.test.js                 |  27 ++--
 test/model.discriminator.querying.test.js |  72 ++++-----
 test/model.discriminator.test.js          |  32 ++--
 test/model.field.selection.test.js        | 148 +++++++++----------
 24 files changed, 673 insertions(+), 679 deletions(-)

diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index 11be81327ef..b1b27678b96 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -2,11 +2,11 @@
  * Module dependencies
  */
 
-var start = require('./common')
-  , Aggregate = require('../lib/aggregate')
-  , mongoose = start.mongoose
-  , Schema = mongoose.Schema
-  , assert = require('assert');
+var start = require('./common'),
+    Aggregate = require('../lib/aggregate'),
+    mongoose = start.mongoose,
+    Schema = mongoose.Schema,
+    assert = require('assert');
 
 /**
  * Test data
@@ -22,15 +22,15 @@ var EmployeeSchema = new Schema({
 mongoose.model('Employee', EmployeeSchema);
 
 function setupData(callback) {
-  var saved = 0
-    , emps = [
-        { name: "Alice", sal: 18000, dept: "sales", customers: [ 'Eve', 'Fred' ] }
-    , { name: "Bob", sal: 15000, dept: "sales", customers: [ 'Gary', 'Herbert', 'Isaac' ] }
-    , { name: "Carol", sal: 14000, dept: "r&d" }
-    , { name: "Dave", sal: 14500, dept: "r&d" }
-    ]
-    , db = start()
-    , Employee = db.model('Employee');
+  var saved = 0,
+      emps = [
+        { name: "Alice", sal: 18000, dept: "sales", customers: [ 'Eve', 'Fred' ] },
+        { name: "Bob", sal: 15000, dept: "sales", customers: [ 'Gary', 'Herbert', 'Isaac' ] },
+        { name: "Carol", sal: 14000, dept: "r&d" },
+        { name: "Dave", sal: 14500, dept: "r&d" }
+      ],
+      db = start(),
+      Employee = db.model('Employee');
 
   emps.forEach(function(data) {
     var emp = new Employee(data);
@@ -68,8 +68,8 @@ describe('aggregate: ', function() {
     });
 
     it('throws if non-operator parameter is passed', function(done) {
-      var aggregate = new Aggregate()
-        , regexp = /Arguments must be aggregate pipeline operators/;
+      var aggregate = new Aggregate(),
+          regexp = /Arguments must be aggregate pipeline operators/;
 
       assert.throws(function() {
         aggregate.append({ $a: 1 }, "string");
@@ -198,10 +198,10 @@ describe('aggregate: ', function() {
 
       aggregate.unwind("a", "b", "c");
       assert.deepEqual(aggregate._pipeline, [
-        { $unwind: "$field" }
-      , { $unwind: "$a" }
-      , { $unwind: "$b" }
-      , { $unwind: "$c" }
+        { $unwind: "$field" },
+        { $unwind: "$a" },
+        { $unwind: "$b" },
+        { $unwind: "$c" }
       ]);
 
       done();
@@ -317,8 +317,8 @@ describe('aggregate: ', function() {
 
   describe('bind', function() {
     it('works', function(done) {
-      var aggregate = new Aggregate()
-        , model = { foo: 42 };
+      var aggregate = new Aggregate(),
+          model = { foo: 42 };
 
       assert.equal(aggregate.model(model), aggregate);
       assert.equal(aggregate._model, model);
@@ -513,8 +513,8 @@ describe('aggregate: ', function() {
       });
 
       it('with a callback', function(done) {
-        var aggregate = new Aggregate()
-          , callback;
+        var aggregate = new Aggregate(),
+            callback;
 
         setupData(function(db) {
           aggregate.model(db.model('Employee'));
diff --git a/test/browser/document.test_.js b/test/browser/document.test_.js
index 5f2a57d1977..2d659145547 100644
--- a/test/browser/document.test_.js
+++ b/test/browser/document.test_.js
@@ -1,5 +1,5 @@
-var Schema = mongoose.Schema
-  , ObjectId = mongoose.Schema.Types.ObjectId;
+var Schema = mongoose.Schema,
+    ObjectId = mongoose.Schema.Types.ObjectId;
 
 var em = new mongoose.Schema({ title: String, body: String });
 em.virtual('works').get(function() {
diff --git a/test/browser/schema.test_.js b/test/browser/schema.test_.js
index 8247543adf8..45402842e6f 100644
--- a/test/browser/schema.test_.js
+++ b/test/browser/schema.test_.js
@@ -1,13 +1,13 @@
 var underlyingBuffer = Buffer;
 
-var Schema = mongoose.Schema
-  , Document = mongoose.Document
-  , VirtualType = mongoose.VirtualType
-  , SchemaTypes = Schema.Types
-  , ObjectId = SchemaTypes.ObjectId
-  , Mixed = SchemaTypes.Mixed
-  , Buffer = SchemaTypes.Buffer
-  , DocumentObjectId = mongoose.Types.ObjectId;
+var Schema = mongoose.Schema,
+    Document = mongoose.Document,
+    VirtualType = mongoose.VirtualType,
+    SchemaTypes = Schema.Types,
+    ObjectId = SchemaTypes.ObjectId,
+    Mixed = SchemaTypes.Mixed,
+    Buffer = SchemaTypes.Buffer,
+    DocumentObjectId = mongoose.Types.ObjectId;
 
 /**
  * Test Document constructor.
@@ -35,24 +35,24 @@ describe('schema', function() {
 
   it('supports different schematypes', function(done) {
     var Checkin = new mongoose.Schema({
-      date      : Date
-      , location  : {
-        lat: Number
-          , lng: Number
+      date: Date,
+      location: {
+        lat: Number,
+        lng: Number
       }
     });
 
     var Ferret = new mongoose.Schema({
-      name      : String
-      , owner     : mongoose.Schema.Types.ObjectId
-      , fur       : String
-      , color     : { type: String }
-      , age       : Number
-      , checkins  : [Checkin]
-      , friends   : [mongoose.Schema.Types.ObjectId]
-      , likes     : Array
-      , alive     : Boolean
-      , extra     : mongoose.Schema.Types.Mixed
+      name: String,
+      owner: mongoose.Schema.Types.ObjectId,
+      fur: String,
+      color: { type: String },
+      age: Number,
+      checkins: [Checkin],
+      friends: [mongoose.Schema.Types.ObjectId],
+      likes: Array,
+      alive: Boolean,
+      extra: mongoose.Schema.Types.Mixed
     });
 
     assert.ok(Ferret.path('name') instanceof mongoose.Schema.Types.String);
@@ -72,10 +72,10 @@ describe('schema', function() {
 
     // check strings
     var Checkin1 = new mongoose.Schema({
-      date      : 'date'
-      , location  : {
-        lat: 'number'
-          , lng: 'Number'
+      date: 'date',
+      location: {
+        lat: 'number',
+        lng: 'Number'
       }
     });
 
@@ -84,20 +84,20 @@ describe('schema', function() {
     assert.ok(Checkin1.path('location.lng') instanceof mongoose.Schema.Types.Number);
 
     var Ferret1 = new mongoose.Schema({
-      name      : "string"
-      , owner     : "oid"
-      , fur       : { type: "string" }
-      , color     : { type: "String" }
-      , checkins  : [Checkin]
-      , friends   : Array
-      , likes     : "array"
-      , alive     : "Bool"
-      , alive1    : "bool"
-      , alive2    : "boolean"
-      , extra     : "mixed"
-      , obj       : "object"
-      , buf       : "buffer"
-      , Buf       : "Buffer"
+      name: "string",
+      owner: "oid",
+      fur: { type: "string" },
+      color: { type: "String" },
+      checkins: [Checkin],
+      friends: Array,
+      likes: "array",
+      alive: "Bool",
+      alive1: "bool",
+      alive2: "boolean",
+      extra: "mixed",
+      obj: "object",
+      buf: "buffer",
+      Buf: "Buffer"
     });
 
     assert.ok(Ferret1.path('name') instanceof mongoose.Schema.Types.String);
@@ -119,19 +119,19 @@ describe('schema', function() {
 
   it('supports dot notation for path accessors', function(done) {
     var Racoon = new Schema({
-      name  : { type: String, enum: ['Edwald', 'Tobi'] }
-      , age   : Number
+      name: { type: String, enum: ['Edwald', 'Tobi'] },
+      age: Number
     });
 
     // check for global variable leak
     assert.equal('undefined', typeof errorMessage);
 
     var Person = new Schema({
-      name      : String
-      , raccoons  : [Racoon]
-      , location  : {
-        city  : String
-        , state : String
+      name: String,
+      raccoons: [Racoon],
+      location: {
+        city: String,
+        state: String
       }
     });
 
@@ -158,14 +158,14 @@ describe('schema', function() {
 
   it('default definition', function(done) {
     var Test = new Schema({
-      simple    : { type: String, default: 'a' }
-      , array     : { type: Array, default: [1,2,3,4,5] }
-      , arrayX    : { type: Array, default: 9 }
-      , arrayFn   : { type: Array, default: function() { return [8]; } }
-      , callback  : { type: Number, default: function() {
-          assert.equal('b', this.a);
-          return '3';
-        }}
+      simple: { type: String, default: 'a' },
+      array: { type: Array, default: [1,2,3,4,5] },
+      arrayX: { type: Array, default: 9 },
+      arrayFn: { type: Array, default: function() { return [8]; } },
+      callback: { type: Number, default: function() {
+        assert.equal('b', this.a);
+        return '3';
+      }}
     });
 
     assert.equal(Test.path('simple').defaultValue, 'a');
@@ -183,8 +183,8 @@ describe('schema', function() {
 
   it('Mixed defaults can be empty arrays', function(done) {
     var Test = new Schema({
-      mixed1    : { type: Mixed, default: [] }
-      , mixed2    : { type: Mixed, default: Array }
+      mixed1: { type: Mixed, default: [] },
+      mixed2: { type: Mixed, default: Array }
     });
 
     assert.ok(Test.path('mixed1').getDefault() instanceof Array);
@@ -256,8 +256,8 @@ describe('schema', function() {
         owner: { type: ObjectId }
       });
 
-      var doc = new TestDocument
-        , id = doc._id.toString();
+      var doc = new TestDocument,
+          id = doc._id.toString();
 
       assert.ok(Loki.path('owner').cast('4c54f3453e688c000000001a')
         instanceof DocumentObjectId);
@@ -274,13 +274,13 @@ describe('schema', function() {
 
     it('array', function(done) {
       var Loki = new Schema({
-        oids        : [ObjectId]
-        , dates       : [Date]
-        , numbers     : [Number]
-        , strings     : [String]
-        , buffers     : [Buffer]
-        , nocast      : []
-        , mixed       : [Mixed]
+        oids: [ObjectId],
+        dates: [Date],
+        numbers: [Number],
+        strings: [String],
+        buffers: [Buffer],
+        nocast: [],
+        mixed: [Mixed]
       });
 
       var oids = Loki.path('oids').cast(['4c54f3453e688c000000001a', new DocumentObjectId]);
@@ -354,8 +354,8 @@ describe('schema', function() {
     var a = new Schema;
     a.method('test', function() {});
     a.method({
-      a: function() {}
-      , b: function() {}
+      a: function() {},
+      b: function() {}
     });
     assert.equal(3, Object.keys(a.methods).length);
     done();
@@ -365,9 +365,9 @@ describe('schema', function() {
     var a = new Schema;
     a.static('test', function() {});
     a.static({
-      a: function() {}
-      , b: function() {}
-      , c: function() {}
+      a: function() {},
+      b: function() {},
+      c: function() {}
     });
 
     assert.equal(Object.keys(a.statics).length, 4);
@@ -407,9 +407,9 @@ describe('schema', function() {
         name: { type: Schema.ObjectId, set: extract }
       });
 
-      var id = new DocumentObjectId
-        , sid = id.toString()
-        , _id = { _id: id };
+      var id = new DocumentObjectId,
+          sid = id.toString(),
+          _id = { _id: id };
 
       assert.equal(Tobi.path('name').applySetters(sid, { a: 'b' }).toString(),sid);
       assert.equal(Tobi.path('name').applySetters(_id, { a: 'b' }).toString(),sid);
@@ -680,8 +680,8 @@ describe('schema', function() {
 
   describe('plugins', function() {
     it('work', function(done) {
-      var Tobi = new Schema
-        , called = false;
+      var Tobi = new Schema,
+          called = false;
 
       Tobi.plugin(function(schema) {
         assert.equal(schema, Tobi);
@@ -727,8 +727,8 @@ describe('schema', function() {
   describe('virtuals', function() {
     it('works', function(done) {
       var Contact = new Schema({
-        firstName: String
-        , lastName: String
+        firstName: String,
+        lastName: String
       });
 
       Contact
@@ -839,8 +839,8 @@ describe('schema', function() {
     });
 
     it('of nested schemas should throw (gh-700)', function(done) {
-      var a = new Schema({ title: String })
-        , err;
+      var a = new Schema({ title: String }),
+          err;
 
       try {
         new Schema({ blah: Boolean, a: a });
@@ -855,12 +855,12 @@ describe('schema', function() {
 
     it('does not alter original argument (gh-1364)', function(done) {
       var schema = {
-        ids: [{ type: Schema.ObjectId, ref: 'something' }]
-        , a: { type: Array }
-        , b: Array
-        , c: [Date]
-        , d: { type: 'Boolean' }
-        , e: [{ a: String, b: [{ /*type: { type: Buffer },*/ x: Number }] }]
+        ids: [{ type: Schema.ObjectId, ref: 'something' }],
+        a: { type: Array },
+        b: Array,
+        c: [Date],
+        d: { type: 'Boolean' },
+        e: [{ a: String, b: [{ /*type: { type: Buffer },*/ x: Number }] }]
       };
 
       new Schema(schema);
diff --git a/test/browser/schema.validation.test_.js b/test/browser/schema.validation.test_.js
index cbf529bfc1b..f10c59cccb0 100644
--- a/test/browser/schema.validation.test_.js
+++ b/test/browser/schema.validation.test_.js
@@ -2,12 +2,12 @@
  * Module dependencies.
  */
 
-var Schema = mongoose.Schema
-  , ValidatorError = mongoose.Error.ValidatorError
-  , SchemaTypes = Schema.Types
-  , ObjectId = SchemaTypes.ObjectId
-  , Mixed = SchemaTypes.Mixed
-  , DocumentObjectId = mongoose.Types.ObjectId;
+var Schema = mongoose.Schema,
+    ValidatorError = mongoose.Error.ValidatorError,
+    SchemaTypes = Schema.Types,
+    ObjectId = SchemaTypes.ObjectId,
+    Mixed = SchemaTypes.Mixed,
+    DocumentObjectId = mongoose.Types.ObjectId;
 
 describe('schema', function() {
   describe('validation', function() {
@@ -456,16 +456,16 @@ describe('schema', function() {
       describe('are customizable', function() {
         it('within schema definitions', function(done) {
           var schema = new Schema({
-            name: { type: String, enum: ['one', 'two'] }
-            , myenum: { type: String, enum: { values: ['x'], message: 'enum validator failed for path: {PATH} with {VALUE}' }}
-            , requiredString1: { type: String, required: true }
-            , requiredString2: { type: String, required: 'oops, {PATH} is missing. {TYPE}' }
-            , matchString0: { type: String, match: /bryancranston/ }
-            , matchString1: { type: String, match: [/bryancranston/, 'invalid string for {PATH} with value: {VALUE}'] }
-            , numMin0: { type: Number, min: 10 }
-            , numMin1: { type: Number, min: [10, 'hey, {PATH} is too small']}
-            , numMax0: { type: Number, max: 20 }
-            , numMax1: { type: Number, max: [20, 'hey, {PATH} ({VALUE}) is greater than {MAX}'] }
+            name: { type: String, enum: ['one', 'two'] },
+            myenum: { type: String, enum: { values: ['x'], message: 'enum validator failed for path: {PATH} with {VALUE}' }},
+            requiredString1: { type: String, required: true },
+            requiredString2: { type: String, required: 'oops, {PATH} is missing. {TYPE}' },
+            matchString0: { type: String, match: /bryancranston/ },
+            matchString1: { type: String, match: [/bryancranston/, 'invalid string for {PATH} with value: {VALUE}'] },
+            numMin0: { type: Number, min: 10 },
+            numMin1: { type: Number, min: [10, 'hey, {PATH} is too small']},
+            numMax0: { type: Number, max: 20 },
+            numMax1: { type: Number, max: [20, 'hey, {PATH} ({VALUE}) is greater than {MAX}'] }
           });
 
           var a = new mongoose.Document({}, schema);
diff --git a/test/collection.capped.test.js b/test/collection.capped.test.js
index 454eb32d7a4..8128aa9cf1f 100644
--- a/test/collection.capped.test.js
+++ b/test/collection.capped.test.js
@@ -3,11 +3,11 @@
  * Module dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , assert = require('assert')
-  , Schema = mongoose.Schema
-  , random = require('../lib/utils').random;
+var start = require('./common'),
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    Schema = mongoose.Schema,
+    random = require('../lib/utils').random;
 
 /**
  * setup
diff --git a/test/collection.test.js b/test/collection.test.js
index eb846bbf91d..37363406aa9 100644
--- a/test/collection.test.js
+++ b/test/collection.test.js
@@ -1,16 +1,16 @@
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , assert = require('assert')
-  , Collection = require('../lib/collection');
+var start = require('./common'),
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    Collection = require('../lib/collection');
 
 describe('collections:', function() {
   it('should buffer commands until connection is established', function(done) {
-    var db = mongoose.createConnection()
-      , collection = db.collection('test-buffering-collection')
-      , connected = false
-      , inserted = false
-      , pending = 2;
+    var db = mongoose.createConnection(),
+        collection = db.collection('test-buffering-collection'),
+        connected = false,
+        inserted = false,
+        pending = 2;
 
     function finish() {
       if (--pending) return;
@@ -34,8 +34,8 @@ describe('collections:', function() {
   });
 
   it('methods should that throw (unimplemented)', function(done) {
-    var collection = new Collection('test', mongoose.connection)
-      , thrown = false;
+    var collection = new Collection('test', mongoose.connection),
+        thrown = false;
 
     try {
       collection.getIndexes();
diff --git a/test/common.js b/test/common.js
index 03403a9e419..b8b0b928ac1 100644
--- a/test/common.js
+++ b/test/common.js
@@ -3,12 +3,12 @@
  * Module dependencies.
  */
 
-var mongoose = require('../')
-  , Collection = mongoose.Collection
-  , assert = require('assert')
-  , queryCount = 0
-  , opened = 0
-  , closed = 0;
+var mongoose = require('../'),
+    Collection = mongoose.Collection,
+    assert = require('assert'),
+    queryCount = 0,
+    opened = 0,
+    closed = 0;
 
 if (process.env.D === '1')
   mongoose.set('debug', true);
@@ -17,18 +17,19 @@ if (process.env.D === '1')
  * Override all Collection related queries to keep count
  */
 
-[ 'ensureIndex'
-  , 'findAndModify'
-  , 'findOne'
-  , 'find'
-  , 'insert'
-  , 'save'
-  , 'update'
-  , 'remove'
-  , 'count'
-  , 'distinct'
-  , 'isCapped'
-  , 'options'
+[
+  'ensureIndex',
+  'findAndModify',
+  'findOne',
+  'find',
+  'insert',
+  'save',
+  'update',
+  'remove',
+  'count',
+  'distinct',
+  'isCapped',
+  'options'
 ].forEach(function(method) {
 
   var oldMethod = Collection.prototype[method];
diff --git a/test/connection.test.js b/test/connection.test.js
index 371d3e255ab..b747c316c42 100644
--- a/test/connection.test.js
+++ b/test/connection.test.js
@@ -3,11 +3,11 @@
  * Module dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , Schema = mongoose.Schema
-  , random = require('../lib/utils').random;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    Schema = mongoose.Schema,
+    random = require('../lib/utils').random;
 
 /**
  * Test.
diff --git a/test/crash.test.js b/test/crash.test.js
index 6a5a758c8c3..6067d11c6c0 100644
--- a/test/crash.test.js
+++ b/test/crash.test.js
@@ -1,9 +1,9 @@
 
 // GH-407
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose;
 
 describe('crash: (gh-407)', function() {
   it('test mongodb crash with invalid objectid string', function(done) {
diff --git a/test/docs/defaults.test.js b/test/docs/defaults.test.js
index 258848f34e5..a665762d11f 100644
--- a/test/docs/defaults.test.js
+++ b/test/docs/defaults.test.js
@@ -1,5 +1,4 @@
 var assert = require('assert');
-var async = require('async');
 var mongoose = require('../../');
 
 describe('defaults docs', function() {
diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index 0ad70da64f5..46ffda155f6 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -3,13 +3,13 @@
  * Module dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , assert = require('assert')
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.ObjectId
-  , Document = require('../lib/document')
-  , EmbeddedDocument = require('../lib/types/embedded');
+var start = require('./common'),
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    Schema = mongoose.Schema,
+    ObjectId = Schema.ObjectId,
+    Document = require('../lib/document'),
+    EmbeddedDocument = require('../lib/types/embedded');
 
 /**
  * Test Document constructor.
@@ -34,25 +34,25 @@ em.virtual('works').get(function() {
   return 'em virtual works';
 });
 var schema = new Schema({
-  test    : String
-  , oids    : [ObjectId]
-  , numbers : [Number]
-  , nested  : {
-    age   : Number
-      , cool  : ObjectId
-      , deep  : { x: String }
-      , path  : String
-      , setr  : String
-  }
-  , nested2 : {
-    nested: String
-      , yup   : {
-        nested  : Boolean
-          , yup     : String
-          , age     : Number
-      }
-  }
-  , em: [em]
+  test: String,
+  oids: [ObjectId],
+  numbers: [Number],
+  nested: {
+    age: Number,
+    cool: ObjectId,
+    deep: { x: String },
+    path: String,
+    setr: String
+  },
+  nested2: {
+    nested: String,
+    yup: {
+      nested: Boolean,
+      yup: String,
+      age: Number
+    }
+  },
+  em: [em]
 });
 TestDocument.prototype.$__setSchema(schema);
 
@@ -80,8 +80,8 @@ TestDocument.prototype.hooksTest = function(fn) {
 
 describe('document: hooks:', function() {
   it('step order', function(done) {
-    var doc = new TestDocument()
-      , steps = 0;
+    var doc = new TestDocument(),
+        steps = 0;
 
     // serial
     doc.pre('hooksTest', function(next) {
@@ -133,8 +133,8 @@ describe('document: hooks:', function() {
   });
 
   it('calling next twice does not break', function(done) {
-    var doc = new TestDocument()
-      , steps = 0;
+    var doc = new TestDocument(),
+        steps = 0;
 
     doc.pre('hooksTest', function(next) {
       steps++;
@@ -155,8 +155,8 @@ describe('document: hooks:', function() {
   });
 
   it('calling done twice does not break', function(done) {
-    var doc = new TestDocument()
-      , steps = 0;
+    var doc = new TestDocument(),
+        steps = 0;
 
     doc.pre('hooksTest', true, function(next, done) {
       steps++;
@@ -180,8 +180,8 @@ describe('document: hooks:', function() {
   });
 
   it('errors from a serial hook', function(done) {
-    var doc = new TestDocument()
-      , steps = 0;
+    var doc = new TestDocument(),
+        steps = 0;
 
     doc.pre('hooksTest', function(next) {
       steps++;
@@ -230,8 +230,8 @@ describe('document: hooks:', function() {
   });
 
   it('test hooks system errors from a parallel hook', function(done) {
-    var doc = new TestDocument()
-      , steps = 0;
+    var doc = new TestDocument(),
+        steps = 0;
 
     doc.pre('hooksTest', true, function(next, done) {
       steps++;
@@ -282,8 +282,8 @@ describe('document: hooks:', function() {
     });
 
     var schema = new Schema({
-      name: String
-      , e: [child]
+      name: String,
+      e: [child]
     });
 
     var S = db.model('docArrayWithHookedSet', schema);
@@ -323,8 +323,8 @@ describe('document: hooks:', function() {
     });
 
     var schema = new Schema({
-      name: String
-      , e: [child]
+      name: String,
+      e: [child]
     });
 
     var S = db.model('docArrayWithHookedSave', schema);
@@ -511,16 +511,13 @@ describe('document: hooks:', function() {
       subs: [
           {
             preference: "xx"
-          }
-        ,
+          },
           {
             preference: "yy"
-          }
-        ,
+          },
           {
             preference: "1"
-          }
-        ,
+          },
           {
             preference: "2"
           }
diff --git a/test/document.isselected.test.js b/test/document.isselected.test.js
index 2fdb4aed055..5718fdecc08 100644
--- a/test/document.isselected.test.js
+++ b/test/document.isselected.test.js
@@ -3,13 +3,13 @@
  * Module dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , assert = require('assert')
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.ObjectId
-  , Document = require('../lib/document')
-  , DocumentObjectId = mongoose.Types.ObjectId;
+var start = require('./common'),
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    Schema = mongoose.Schema,
+    ObjectId = Schema.ObjectId,
+    Document = require('../lib/document'),
+    DocumentObjectId = mongoose.Types.ObjectId;
 
 /**
  * Test Document constructor.
@@ -34,26 +34,26 @@ em.virtual('works').get(function() {
   return 'em virtual works';
 });
 var schema = new Schema({
-  test    : String
-  , oids    : [ObjectId]
-  , numbers : [Number]
-  , nested  : {
-    age   : Number
-      , cool  : ObjectId
-      , deep  : { x: String }
-      , path  : String
-      , setr  : String
-  }
-  , nested2 : {
-    nested: String
-      , yup   : {
-        nested  : Boolean
-          , yup     : String
-          , age     : Number
-      }
-  }
-  , em: [em]
-  , date: Date
+  test: String,
+  oids: [ObjectId],
+  numbers: [Number],
+  nested: {
+    age: Number,
+    cool: ObjectId,
+    deep: { x: String },
+    path: String,
+    setr: String
+  },
+  nested2: {
+    nested: String,
+    yup: {
+      nested: Boolean,
+      yup: String,
+      age: Number
+    }
+  },
+  em: [em],
+  date: Date
 });
 TestDocument.prototype.$__setSchema(schema);
 
@@ -93,16 +93,16 @@ describe('document', function() {
     var doc = new TestDocument();
 
     doc.init({
-      test    : 'test'
-      , numbers : [4,5,6,7]
-      , nested  : {
-        age   : 5
-          , cool  : DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c')
-          , path  : 'my path'
-          , deep  : { x: 'a string' }
-      }
-      , notapath: 'i am not in the schema'
-      , em: [{ title: 'gocars' }]
+      test: 'test',
+      numbers: [4,5,6,7],
+      nested: {
+        age: 5,
+        cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
+        path: 'my path',
+        deep: { x: 'a string' }
+      },
+      notapath: 'i am not in the schema',
+      em: [{ title: 'gocars' }]
     });
 
     assert.ok(doc.isSelected('_id'));
@@ -126,19 +126,19 @@ describe('document', function() {
     assert.ok(doc.isSelected('em.nonpath')); // not a path
 
     var selection = {
-      'test': 1
-      , 'numbers': 1
-      , 'nested.deep': 1
-      , 'oids': 1
+      'test': 1,
+      'numbers': 1,
+      'nested.deep': 1,
+      'oids': 1
     };
 
     doc = new TestDocument(undefined, selection);
 
     doc.init({
-      test    : 'test'
-      , numbers : [4,5,6,7]
-      , nested  : {
-        deep  : { x: 'a string' }
+      test: 'test',
+      numbers: [4,5,6,7],
+      nested: {
+        deep: { x: 'a string' }
       }
     });
 
@@ -198,15 +198,15 @@ describe('document', function() {
 
     doc = new TestDocument(undefined, selection);
     doc.init({
-      test    : 'test'
-      , numbers : [4,5,6,7]
-      , nested  : {
-        age   : 5
-          , cool  : DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c')
-          , path  : 'my path'
-          , deep  : { x: 'a string' }
-      }
-      , notapath: 'i am not in the schema'
+      test: 'test',
+      numbers: [4,5,6,7],
+      nested: {
+        age: 5,
+        cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
+        path: 'my path',
+        deep: { x: 'a string' }
+      },
+      notapath: 'i am not in the schema'
     });
 
     assert.ok(doc.isSelected('_id'));
@@ -235,15 +235,15 @@ describe('document', function() {
 
     doc = new TestDocument(undefined, selection);
     doc.init({
-      test    : 'test'
-      , numbers : [4,5,6,7]
-      , nested  : {
-        age   : 5
-          , cool  : DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c')
-          , path  : 'my path'
-          , deep  : { x: 'a string' }
-      }
-      , notapath: 'i am not in the schema'
+      test: 'test',
+      numbers: [4,5,6,7],
+      nested: {
+        age: 5,
+        cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
+        path: 'my path',
+        deep: { x: 'a string' }
+      },
+      notapath: 'i am not in the schema'
     });
 
     assert.ok(!doc.isSelected('_id'));
@@ -308,15 +308,15 @@ describe('document', function() {
 
     doc = new TestDocument(undefined, selection);
     doc.init({
-      test    : 'test'
-      , numbers : [4,5,6,7]
-      , nested  : {
-        age   : 5
-          , cool  : DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c')
-          , path  : 'my path'
-          , deep  : { x: 'a string' }
-      }
-      , notapath: 'i am not in the schema'
+      test: 'test',
+      numbers: [4,5,6,7],
+      nested: {
+        age: 5,
+        cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
+        path: 'my path',
+        deep: { x: 'a string' }
+      },
+      notapath: 'i am not in the schema'
     });
 
     assert.ok(doc.isSelected('_id'));
diff --git a/test/document.modified.test.js b/test/document.modified.test.js
index 8e942356c61..ba4f5d12a39 100644
--- a/test/document.modified.test.js
+++ b/test/document.modified.test.js
@@ -3,13 +3,13 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.ObjectId
-  , DocumentObjectId = mongoose.Types.ObjectId;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema,
+    ObjectId = Schema.ObjectId,
+    DocumentObjectId = mongoose.Types.ObjectId;
 
 /**
  * Setup.
@@ -18,27 +18,27 @@ var start = require('./common')
 var Comments = new Schema;
 
 Comments.add({
-  title     : String
-  , date      : Date
-  , body      : String
-  , comments  : [Comments]
+  title: String,
+  date: Date,
+  body: String,
+  comments: [Comments]
 });
 
 var BlogPost = new Schema({
-  title     : String
-  , author    : String
-  , slug      : String
-  , date      : Date
-  , meta      : {
-    date      : Date
-      , visitors  : Number
-  }
-  , published : Boolean
-  , mixed     : {}
-  , numbers   : [Number]
-  , owners    : [ObjectId]
-  , comments  : [Comments]
-  , nested    : { array: [Number] }
+  title: String,
+  author: String,
+  slug: String,
+  date: Date,
+  meta: {
+    date: Date,
+    visitors: Number
+  },
+  published: Boolean,
+  mixed: {},
+  numbers: [Number],
+  owners: [ObjectId],
+  comments: [Comments],
+  nested: { array: [Number] }
 });
 
 BlogPost
@@ -74,8 +74,8 @@ var collection = 'blogposts_' + random();
 describe('document modified', function() {
   describe('modified states', function() {
     it('reset after save', function(done) {
-      var db = start()
-        , B = db.model(modelName, collection);
+      var db = start(),
+          B = db.model(modelName, collection);
 
       var b = new B;
 
@@ -99,8 +99,8 @@ describe('document modified', function() {
     });
 
     it('of embedded docs reset after save', function(done) {
-      var db = start()
-        , BlogPost = db.model(modelName, collection);
+      var db = start(),
+          BlogPost = db.model(modelName, collection);
 
       var post = new BlogPost({ title: 'hocus pocus' });
       post.comments.push({ title: 'Humpty Dumpty', comments: [{title: 'nested'}] });
@@ -146,15 +146,15 @@ describe('document modified', function() {
     });
 
     it('when modifying keys', function(done) {
-      var db = start()
-        , BlogPost = db.model(modelName, collection);
+      var db = start(),
+          BlogPost = db.model(modelName, collection);
 
       db.close();
       var post = new BlogPost;
       post.init({
-        title       : 'Test'
-        , slug        : 'test'
-        , date        : new Date
+        title: 'Test',
+        slug: 'test',
+        date: new Date
       });
 
       assert.equal(false, post.isModified('title'));
@@ -170,15 +170,15 @@ describe('document modified', function() {
     });
 
     it('setting a key identically to its current value should not dirty the key', function(done) {
-      var db = start()
-        , BlogPost = db.model(modelName, collection);
+      var db = start(),
+          BlogPost = db.model(modelName, collection);
 
       db.close();
       var post = new BlogPost;
       post.init({
-        title       : 'Test'
-        , slug        : 'test'
-        , date        : new Date
+        title: 'Test',
+        slug: 'test',
+        date: new Date
       });
 
       assert.equal(false, post.isModified('title'));
@@ -189,14 +189,14 @@ describe('document modified', function() {
 
     describe('on DocumentArray', function() {
       it('work', function(done) {
-        var db = start()
-          , BlogPost = db.model(modelName, collection);
+        var db = start(),
+            BlogPost = db.model(modelName, collection);
 
         var post = new BlogPost();
         post.init({
-          title       : 'Test'
-          , slug        : 'test'
-          , comments    : [ { title: 'Test', date: new Date, body: 'Test' } ]
+          title: 'Test',
+          slug: 'test',
+          comments: [ { title: 'Test', date: new Date, body: 'Test' } ]
         });
 
         assert.equal(false, post.isModified('comments.0.title'));
@@ -209,14 +209,14 @@ describe('document modified', function() {
         db.close(done);
       });
       it('with accessors', function(done) {
-        var db = start()
-          , BlogPost = db.model(modelName, collection);
+        var db = start(),
+            BlogPost = db.model(modelName, collection);
 
         var post = new BlogPost();
         post.init({
-          title       : 'Test'
-          , slug        : 'test'
-          , comments    : [ { title: 'Test', date: new Date, body: 'Test' } ]
+          title: 'Test',
+          slug: 'test',
+          comments: [ { title: 'Test', date: new Date, body: 'Test' } ]
         });
 
         assert.equal(false, post.isModified('comments.0.body'));
@@ -234,8 +234,8 @@ describe('document modified', function() {
     describe('on MongooseArray', function() {
       it('atomic methods', function(done) {
         // COMPLETEME
-        var db = start()
-          , BlogPost = db.model(modelName, collection);
+        var db = start(),
+            BlogPost = db.model(modelName, collection);
 
         db.close();
         var post = new BlogPost();
@@ -246,8 +246,8 @@ describe('document modified', function() {
       });
       it('native methods', function(done) {
         // COMPLETEME
-        var db = start()
-          , BlogPost = db.model(modelName, collection);
+        var db = start(),
+            BlogPost = db.model(modelName, collection);
 
         db.close();
         var post = new BlogPost;
@@ -257,24 +257,24 @@ describe('document modified', function() {
     });
 
     it('on entire document', function(done) {
-      var db = start()
-        , BlogPost = db.model(modelName, collection);
+      var db = start(),
+          BlogPost = db.model(modelName, collection);
 
       var doc = {
-        title       : 'Test'
-        , slug        : 'test'
-        , date        : new Date
-        , meta        : {
-          date      : new Date
-            , visitors  : 5
-        }
-        , published   : true
-        , mixed       : { x: [ { y: [1,'yes', 2] } ] }
-        , numbers     : []
-        , owners      : [new DocumentObjectId, new DocumentObjectId]
-        , comments    : [
-            { title: 'Test', date: new Date, body: 'Test' }
-          , { title: 'Super', date: new Date, body: 'Cool' }
+        title: 'Test',
+        slug: 'test',
+        date: new Date,
+        meta: {
+          date: new Date,
+          visitors: 5
+        },
+        published: true,
+        mixed: { x: [ { y: [1,'yes', 2] } ] },
+        numbers: [],
+        owners: [new DocumentObjectId, new DocumentObjectId],
+        comments: [
+          { title: 'Test', date: new Date, body: 'Test' },
+          { title: 'Super', date: new Date, body: 'Cool' }
         ]
       };
 
@@ -445,17 +445,17 @@ describe('document modified', function() {
       var db = start();
 
       var grandChildSchema = Schema({
-        name : String
+        name: String
       });
 
       var childSchema = Schema({
-        name : String,
-        grandChild : [grandChildSchema]
+        name: String,
+        grandChild: [grandChildSchema]
       });
 
       var parentSchema = Schema({
-        name : String,
-        child : [childSchema]
+        name: String,
+        child: [childSchema]
       });
 
       var Parent = db.model('gh-1754', parentSchema);
diff --git a/test/document.populate.test.js b/test/document.populate.test.js
index abec505f2dc..8a106b2f80c 100644
--- a/test/document.populate.test.js
+++ b/test/document.populate.test.js
@@ -3,14 +3,14 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , utils = require('../lib/utils')
-  , random = utils.random
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.ObjectId
-  , Document = require('../lib/document');
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    utils = require('../lib/utils'),
+    random = utils.random,
+    Schema = mongoose.Schema,
+    ObjectId = Schema.ObjectId,
+    Document = require('../lib/document');
 
 /**
  * Setup.
@@ -39,26 +39,26 @@ em.virtual('works').get(function() {
   return 'em virtual works';
 });
 var schema = new Schema({
-  test    : String
-  , oids    : [ObjectId]
-  , numbers : [Number]
-  , nested  : {
-    age   : Number
-      , cool  : ObjectId
-      , deep  : { x: String }
-      , path  : String
-      , setr  : String
-  }
-  , nested2 : {
-    nested: String
-      , yup   : {
-        nested  : Boolean
-          , yup     : String
-          , age     : Number
-      }
-  }
-  , em: [em]
-  , date: Date
+  test: String,
+  oids: [ObjectId],
+  numbers: [Number],
+  nested: {
+    age: Number,
+    cool: ObjectId,
+    deep: { x: String },
+    path: String,
+    setr: String
+  },
+  nested2: {
+    nested: String,
+    yup: {
+      nested: Boolean,
+      yup: String,
+      age: Number
+    }
+  },
+  em: [em],
+  date: Date
 });
 TestDocument.prototype.$__setSchema(schema);
 
@@ -67,11 +67,11 @@ TestDocument.prototype.$__setSchema(schema);
  */
 
 var User = new Schema({
-  name      : String
-  , email     : String
-  , gender    : { type: String, enum: ['male', 'female'], default: 'male' }
-  , age       : { type: Number, default: 21 }
-  , blogposts : [{ type: ObjectId, ref: 'doc.populate.b' }]
+  name: String,
+  email: String,
+  gender: { type: String, enum: ['male', 'female'], default: 'male' },
+  age: { type: Number, default: 21 },
+  blogposts: [{ type: ObjectId, ref: 'doc.populate.b' }]
 }, { collection: 'doc.populate.us' });
 
 /**
@@ -79,9 +79,9 @@ var User = new Schema({
  */
 
 var Comment = new Schema({
-  asers   : [{ type: ObjectId, ref: 'doc.populate.u' }]
-  , _creator : { type: ObjectId, ref: 'doc.populate.u' }
-  , content  : String
+  asers: [{ type: ObjectId, ref: 'doc.populate.u' }],
+  _creator: { type: ObjectId, ref: 'doc.populate.u' },
+  content: String
 });
 
 /**
@@ -89,10 +89,10 @@ var Comment = new Schema({
  */
 
 var BlogPost = new Schema({
-  _creator      : { type: ObjectId, ref: 'doc.populate.u' }
-  , title         : String
-  , comments      : [Comment]
-  , fans          : [{ type: ObjectId, ref: 'doc.populate.u' }]
+  _creator: { type: ObjectId, ref: 'doc.populate.u' },
+  title: String,
+  comments: [Comment],
+  fans: [{ type: ObjectId, ref: 'doc.populate.u' }]
 });
 
 mongoose.model('doc.populate.b', BlogPost);
@@ -111,13 +111,13 @@ describe('document.populate', function() {
     _id = new mongoose.Types.ObjectId;
 
     User.create({
-      name  : 'Phoenix'
-      , email : 'phx@az.com'
-      , blogposts: [_id]
+      name: 'Phoenix',
+      email: 'phx@az.com',
+      blogposts: [_id]
     }, {
-      name  : 'Newark'
-      , email : 'ewr@nj.com'
-      , blogposts: [_id]
+      name: 'Newark',
+      email: 'ewr@nj.com',
+      blogposts: [_id]
     }, function(err, u1, u2) {
       assert.ifError(err);
 
@@ -125,10 +125,10 @@ describe('document.populate', function() {
       user2 = u2;
 
       B.create({
-        title     : 'the how and why'
-        , _creator  : user1
-        , fans: [user1, user2]
-        , comments: [{ _creator: user2, content: 'user2' }, { _creator: user1, content: 'user1' }]
+        title: 'the how and why',
+        _creator: user1,
+        fans: [user1, user2],
+        comments: [{ _creator: user2, content: 'user2' }, { _creator: user1, content: 'user1' }]
       }, function(err, p) {
         assert.ifError(err);
         post = p;
@@ -363,13 +363,13 @@ describe('document.populate', function() {
     var db = start();
 
     var UserSchema = new Schema({
-      _id: String
-      , name: String
+      _id: String,
+      name: String
     });
 
     var NoteSchema = new Schema({
-      author: { type: String, ref: 'UserWithStringId' }
-      , body: String
+      author: { type: String, ref: 'UserWithStringId' },
+      body: String
     });
 
     var User = db.model('UserWithStringId', UserSchema, random());
@@ -396,13 +396,13 @@ describe('document.populate', function() {
     var db = start();
 
     var UserSchema = new Schema({
-      _id: Buffer
-      , name: String
+      _id: Buffer,
+      name: String
     });
 
     var NoteSchema = new Schema({
-      author: { type: Buffer, ref: 'UserWithBufferId' }
-      , body: String
+      author: { type: Buffer, ref: 'UserWithBufferId' },
+      body: String
     });
 
     var User = db.model('UserWithBufferId', UserSchema, random());
@@ -437,13 +437,13 @@ describe('document.populate', function() {
     var db = start();
 
     var UserSchema = new Schema({
-      _id: Number
-      , name: String
+      _id: Number,
+      name: String
     });
 
     var NoteSchema = new Schema({
-      author: { type: Number, ref: 'UserWithNumberId' }
-      , body: String
+      author: { type: Number, ref: 'UserWithNumberId' },
+      body: String
     });
 
     var User = db.model('UserWithNumberId', UserSchema, random());
diff --git a/test/document.strict.test.js b/test/document.strict.test.js
index f76648de480..c41fc4094f1 100644
--- a/test/document.strict.test.js
+++ b/test/document.strict.test.js
@@ -3,11 +3,11 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , assert = require('assert')
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema;
+var start = require('./common'),
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema;
 
 describe('document: strict mode:', function() {
   describe('should work', function() {
@@ -17,11 +17,11 @@ describe('document: strict mode:', function() {
       db = start();
 
       var raw = {
-        ts  : { type: Date, default: Date.now }
-        , content: String
-        , mixed: {}
-        , deepMixed: { '4a': {}}
-        , arrayMixed: []
+        ts: { type: Date, default: Date.now },
+        content: String,
+        mixed: {},
+        deepMixed: { '4a': {}},
+        arrayMixed: []
       };
 
       var lax = new Schema(raw, { strict: false });
@@ -150,13 +150,13 @@ describe('document: strict mode:', function() {
     var db = start();
 
     var lax = new Schema({
-      ts  : { type: Date, default: Date.now }
-      , content: String
+      ts: { type: Date, default: Date.now },
+      content: String
     }, { strict: false });
 
     var strict = new Schema({
-      ts  : { type: Date, default: Date.now }
-      , content: String
+      ts: { type: Date, default: Date.now },
+      content: String
     });
 
     var Lax = db.model('EmbeddedLax', new Schema({ dox: [lax] }, { strict: false }), 'embdoc' + random());
@@ -186,7 +186,7 @@ describe('document: strict mode:', function() {
     assert.ok(!s3.dox[0].rouge);
 
     // strict on create
-    Strict.create({dox:[{content: 'sample2', rouge: 'data'}]}, function(err, doc) {
+    Strict.create({dox: [{content: 'sample2', rouge: 'data'}]}, function(err, doc) {
       assert.equal('sample2', doc.dox[0].content);
       assert.ok(!('rouge' in doc.dox[0]));
       assert.ok(!doc.dox[0].rouge);
@@ -197,12 +197,12 @@ describe('document: strict mode:', function() {
   it('virtuals', function(done) {
     var db = start();
 
-    var getCount = 0
-      , setCount = 0;
+    var getCount = 0,
+        setCount = 0;
 
     var strictSchema = new Schema({
-      email: String
-      , prop: String
+      email: String,
+      prop: String
     });
 
     strictSchema
@@ -219,8 +219,8 @@ describe('document: strict mode:', function() {
     var StrictModel = db.model('StrictVirtual', strictSchema);
 
     var strictInstance = new StrictModel({
-      email: 'hunter@skookum.com'
-      , myvirtual: 'test'
+      email: 'hunter@skookum.com',
+      myvirtual: 'test'
     });
 
     assert.equal(0, getCount);
@@ -357,7 +357,7 @@ describe('document: strict mode:', function() {
 
   describe('"throws" mode', function() {
     it('throws on set() of unknown property', function(done) {
-      var schema = Schema({ n: String, docs:[{x:[{y:String}]}] });
+      var schema = Schema({ n: String, docs: [{x: [{y: String}]}] });
       schema.set('strict', 'throw');
       var M = mongoose.model('throwStrictSet', schema, 'tss_' + random());
       var m = new M;
diff --git a/test/document.test.js b/test/document.test.js
index ff2fc07221f..83e276cb4ea 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -3,20 +3,20 @@
  * Module dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , assert = require('assert')
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.ObjectId
-  , Document = require('../lib/document')
-  , DocumentObjectId = mongoose.Types.ObjectId
-  , SchemaType = mongoose.SchemaType
-  , ValidatorError = SchemaType.ValidatorError
-  , ValidationError = mongoose.Document.ValidationError
-  , MongooseError = mongoose.Error
-  , EmbeddedDocument = require('../lib/types/embedded')
-  , Query = require('../lib/query');
+var start = require('./common'),
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema,
+    ObjectId = Schema.ObjectId,
+    Document = require('../lib/document'),
+    DocumentObjectId = mongoose.Types.ObjectId,
+    SchemaType = mongoose.SchemaType,
+    ValidatorError = SchemaType.ValidatorError,
+    ValidationError = mongoose.Document.ValidationError,
+    MongooseError = mongoose.Error,
+    EmbeddedDocument = require('../lib/types/embedded'),
+    Query = require('../lib/query');
 
 /**
  * Test Document constructor.
diff --git a/test/errors.validation.test.js b/test/errors.validation.test.js
index 1230e529541..b69e4f606d0 100644
--- a/test/errors.validation.test.js
+++ b/test/errors.validation.test.js
@@ -3,24 +3,24 @@
  * Module dependencies.
  */
 
-var assert = require('assert')
-  , start = require('./common')
-  , mongoose = start.mongoose
-  , Schema = mongoose.Schema
-  , SchemaType = mongoose.SchemaType
-  , ValidatorError = SchemaType.ValidatorError;
+var assert = require('assert'),
+    start = require('./common'),
+    mongoose = start.mongoose,
+    Schema = mongoose.Schema,
+    SchemaType = mongoose.SchemaType,
+    ValidatorError = SchemaType.ValidatorError;
 
 describe('ValidationError', function() {
   describe('#infiniteRecursion', function() {
     it('does not cause RangeError (gh-1834)', function(done) {
-      var SubSchema
-        , M
-        , model;
+      var SubSchema,
+          M,
+          model;
 
       SubSchema = new Schema({
         name: {type: String, required: true},
         contents: [new Schema({
-          key:   {type: String, required: true},
+          key: {type: String, required: true},
           value: {type: String, required: true}
         }, {_id: false})]
       });
@@ -45,12 +45,12 @@ describe('ValidationError', function() {
 
   describe('#minDate', function() {
     it('causes a validation error', function(done) {
-      var MinSchema
-        , M
-        , model;
+      var MinSchema,
+          M,
+          model;
 
       MinSchema = new Schema({
-        appointmentDate : { type: Date, min: Date.now }
+        appointmentDate: { type: Date, min: Date.now }
       });
 
       M = mongoose.model('MinSchema', MinSchema);
@@ -75,12 +75,12 @@ describe('ValidationError', function() {
 
   describe('#maxDate', function() {
     it('causes a validation error', function(done) {
-      var MaxSchema
-        , M
-        , model;
+      var MaxSchema,
+          M,
+          model;
 
       MaxSchema = new Schema({
-        birthdate : { type: Date, max: Date.now }
+        birthdate: { type: Date, max: Date.now }
       });
 
       M = mongoose.model('MaxSchema', MaxSchema);
@@ -105,12 +105,12 @@ describe('ValidationError', function() {
 
   describe('#minlength', function() {
     it('causes a validation error', function(done) {
-      var AddressSchema
-        , Address
-        , model;
+      var AddressSchema,
+          Address,
+          model;
 
       AddressSchema = new Schema({
-        postalCode : { type: String, minlength: 5 }
+        postalCode: { type: String, minlength: 5 }
       });
 
       Address = mongoose.model('MinLengthAddress', AddressSchema);
@@ -135,12 +135,12 @@ describe('ValidationError', function() {
 
   describe('#maxlength', function() {
     it('causes a validation error', function(done) {
-      var AddressSchema
-        , Address
-        , model;
+      var AddressSchema,
+          Address,
+          model;
 
       AddressSchema = new Schema({
-        postalCode : { type: String, maxlength: 10 }
+        postalCode: { type: String, maxlength: 10 }
       });
 
       Address = mongoose.model('MaxLengthAddress', AddressSchema);
@@ -166,8 +166,8 @@ describe('ValidationError', function() {
   describe('#toString', function() {
     it('does not cause RangeError (gh-1296)', function(done) {
       var ASchema = new Schema({
-        key: {type: String, required: true}
-        , value: {type:String, required: true}
+        key: {type: String, required: true},
+        value: {type: String, required: true}
       });
 
       var BSchema = new Schema({
diff --git a/test/gh-1408.test.js b/test/gh-1408.test.js
index 8f4dcfdf50a..5405b512720 100644
--- a/test/gh-1408.test.js
+++ b/test/gh-1408.test.js
@@ -3,10 +3,10 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , Schema = mongoose.Schema;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    Schema = mongoose.Schema;
 
 describe('documents should not be converted to _id (gh-1408)', function() {
   it('if an embedded doc', function(done) {
diff --git a/test/index.test.js b/test/index.test.js
index 56f40831edb..2b2e50ede41 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -1,19 +1,19 @@
 
-var url = require('url')
-  , start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , Mongoose = mongoose.Mongoose
-  , Schema = mongoose.Schema
-  , random = require('../lib/utils').random
-  , collection = 'blogposts_' + random();
+var url = require('url'),
+    start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    Mongoose = mongoose.Mongoose,
+    Schema = mongoose.Schema,
+    random = require('../lib/utils').random,
+    collection = 'blogposts_' + random();
 
 describe('mongoose module:', function() {
   describe('default connection works', function() {
     it('without options', function(done) {
       var goose = new Mongoose;
-      var db = goose.connection
-        , uri = 'mongodb://localhost/mongoose_test';
+      var db = goose.connection,
+          uri = 'mongodb://localhost/mongoose_test';
 
       goose.connect(process.env.MONGOOSE_TEST_URI || uri);
 
@@ -26,10 +26,10 @@ describe('mongoose module:', function() {
 
     it('with options', function(done) {
       var goose = new Mongoose;
-      var db = goose.connection
-        , uri = 'mongodb://localhost/mongoose_test';
+      var db = goose.connection,
+          uri = 'mongodb://localhost/mongoose_test';
 
-      goose.connect(process.env.MONGOOSE_TEST_URI || uri, {db:{safe:false}});
+      goose.connect(process.env.MONGOOSE_TEST_URI || uri, {db: {safe: false}});
 
       db.on('open', function() {
         db.close(function() {
@@ -52,9 +52,9 @@ describe('mongoose module:', function() {
   });
 
   it('declaring global plugins', function(done) {
-    var mong = new Mongoose()
-      , schema = new Schema()
-      , called = 0;
+    var mong = new Mongoose(),
+        schema = new Schema(),
+        called = 0;
 
     mong.plugin(function(s) {
       assert.equal(s, schema);
@@ -75,11 +75,11 @@ describe('mongoose module:', function() {
   describe('disconnection of all connections', function() {
     describe('no callback', function() {
       it('works', function(done) {
-        var mong = new Mongoose()
-          , uri = 'mongodb://localhost/mongoose_test'
-          , connections = 0
-          , disconnections = 0
-          , pending = 4;
+        var mong = new Mongoose(),
+            uri = 'mongodb://localhost/mongoose_test',
+            connections = 0,
+            disconnections = 0,
+            pending = 4;
 
         mong.connect(process.env.MONGOOSE_TEST_URI || uri);
         var db = mong.connection;
@@ -117,8 +117,8 @@ describe('mongoose module:', function() {
       });
 
       it('properly handles errors', function(done) {
-        var mong = new Mongoose()
-          , uri = 'mongodb://localhost/mongoose_test';
+        var mong = new Mongoose(),
+            uri = 'mongodb://localhost/mongoose_test';
 
         mong.connect(process.env.MONGOOSE_TEST_URI || uri);
         var db = mong.connection;
@@ -140,8 +140,8 @@ describe('mongoose module:', function() {
     });
 
     it('with callback', function(done) {
-      var mong = new Mongoose()
-        , uri = 'mongodb://localhost/mongoose_test';
+      var mong = new Mongoose(),
+          uri = 'mongodb://localhost/mongoose_test';
 
       mong.connect(process.env.MONGOOSE_TEST_URI || uri);
 
@@ -155,8 +155,8 @@ describe('mongoose module:', function() {
 
   describe('model()', function() {
     it('accessing a model that hasn\'t been defined', function(done) {
-      var mong = new Mongoose()
-        , thrown = false;
+      var mong = new Mongoose(),
+          thrown = false;
 
       try {
         mong.model('Test');
@@ -244,8 +244,8 @@ describe('mongoose module:', function() {
   });
 
   it('connecting with a signature of host, database, function', function(done) {
-    var mong = new Mongoose()
-      , uri = process.env.MONGOOSE_TEST_URI || 'mongodb://localhost/mongoose_test';
+    var mong = new Mongoose(),
+        uri = process.env.MONGOOSE_TEST_URI || 'mongodb://localhost/mongoose_test';
 
     uri = url.parse(uri);
 
@@ -258,8 +258,8 @@ describe('mongoose module:', function() {
 
   describe('connecting with a signature of uri, options, function', function() {
     it('with single mongod', function(done) {
-      var mong = new Mongoose()
-        , uri = process.env.MONGOOSE_TEST_URI || 'mongodb://localhost/mongoose_test';
+      var mong = new Mongoose(),
+          uri = process.env.MONGOOSE_TEST_URI || 'mongodb://localhost/mongoose_test';
 
       mong.connect(uri, { db: { safe: false }}, function(err) {
         assert.ifError(err);
@@ -269,8 +269,8 @@ describe('mongoose module:', function() {
     });
 
     it('with replica set', function(done) {
-      var mong = new Mongoose()
-        , uri = process.env.MONGOOSE_SET_TEST_URI;
+      var mong = new Mongoose(),
+          uri = process.env.MONGOOSE_SET_TEST_URI;
 
       if (!uri) return done();
 
@@ -302,8 +302,8 @@ describe('mongoose module:', function() {
         test: String
       }));
 
-      var Test = mong.model('Test')
-        , test = new Test();
+      var Test = mong.model('Test'),
+          test = new Test();
 
       test.test = 'aa';
       test.save(function(err) {
@@ -341,8 +341,8 @@ describe('mongoose module:', function() {
         test: String
       }));
 
-      var Test = conn.model('ReplSetTwo')
-        , test = new Test();
+      var Test = conn.model('ReplSetTwo'),
+          test = new Test();
 
       test.test = 'aa';
       test.save(function(err) {
diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js
index d77f5709013..42f6f085a9c 100644
--- a/test/model.aggregate.test.js
+++ b/test/model.aggregate.test.js
@@ -3,20 +3,20 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , assert = require('assert')
-  , random = require('../lib/utils').random
-  , Aggregate = require('../lib/aggregate')
-  , Schema = mongoose.Schema;
+var start = require('./common'),
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    random = require('../lib/utils').random,
+    Aggregate = require('../lib/aggregate'),
+    Schema = mongoose.Schema;
 
 /**
  * Setup.
  */
 
 var userSchema = new Schema({
-  name: String
-  , age: Number
+  name: String,
+  age: Number
 });
 
 var collection = 'aggregate_' + random();
diff --git a/test/model.create.test.js b/test/model.create.test.js
index 3a96825bd7b..5a08cb3d6c1 100644
--- a/test/model.create.test.js
+++ b/test/model.create.test.js
@@ -2,12 +2,12 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema
-  , DocumentObjectId = mongoose.Types.ObjectId;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema,
+    DocumentObjectId = mongoose.Types.ObjectId;
 
 /**
  * Setup
@@ -76,9 +76,9 @@ describe('model', function() {
     it('creates in parallel', function(done) {
       // we set the time out to be double that of the validator - 1 (so that running in serial will be greater then that)
       this.timeout(1000);
-      var db = start()
-        , countPre = 0
-        , countPost = 0;
+      var db = start(),
+          countPre = 0,
+          countPost = 0;
 
       var SchemaWithPreSaveHook = new Schema({
         preference: String
@@ -95,12 +95,9 @@ describe('model', function() {
       });
       var MWPSH = db.model('mwpsh', SchemaWithPreSaveHook);
       MWPSH.create([
-        {preference: "xx"}
-        ,
-        {preference: "yy"}
-        ,
-        {preference: "1"}
-        ,
+        {preference: "xx"},
+        {preference: "yy"},
+        {preference: "1"},
         {preference: "2"}
       ], function(err, docs) {
         assert.ifError(err);
diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js
index 190d11aebcb..e3cdceedd39 100644
--- a/test/model.discriminator.querying.test.js
+++ b/test/model.discriminator.querying.test.js
@@ -2,13 +2,13 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , Schema = mongoose.Schema
-  , assert = require('assert')
-  , random = require('../lib/utils').random
-  , util = require('util')
-  , async = require('async');
+var start = require('./common'),
+    mongoose = start.mongoose,
+    Schema = mongoose.Schema,
+    assert = require('assert'),
+    random = require('../lib/utils').random,
+    util = require('util'),
+    async = require('async');
 
 
 /**
@@ -653,15 +653,15 @@ describe('model', function() {
         var busSchema = new Schema({ speed: Number });
 
         var userSchema = new Schema({
-          vehicles: [{ type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationVehicle' }]
-          , favoriteVehicle: { type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationVehicle' }
-          , favoriteBus: { type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationBus' }
+          vehicles: [{ type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationVehicle' }],
+          favoriteVehicle: { type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationVehicle' },
+          favoriteBus: { type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationBus' }
         });
 
-        var Vehicle = db.model('ModelDiscriminatorPopulationVehicle', vehicleSchema)
-          , Car = Vehicle.discriminator('ModelDiscriminatorPopulationCar', carSchema)
-          , Bus = Vehicle.discriminator('ModelDiscriminatorPopulationBus', busSchema)
-          , User = db.model('ModelDiscriminatorPopulationUser', userSchema);
+        var Vehicle = db.model('ModelDiscriminatorPopulationVehicle', vehicleSchema),
+            Car = Vehicle.discriminator('ModelDiscriminatorPopulationCar', carSchema),
+            Bus = Vehicle.discriminator('ModelDiscriminatorPopulationBus', busSchema),
+            User = db.model('ModelDiscriminatorPopulationUser', userSchema);
 
         Vehicle.create({}, function(err, vehicle) {
           assert.ifError(err);
@@ -674,15 +674,15 @@ describe('model', function() {
                   assert.ifError(err);
 
                   var expected = {
-                    __v: 0
-                    , _id: user._id
-                    , vehicles: [
-                        { _id: vehicle._id, __v: 0 }
-                      , { _id: car._id, speed: 160, __v: 0, __t: 'ModelDiscriminatorPopulationCar' }
-                      , { _id: bus._id, speed: 80, __v: 0, __t: 'ModelDiscriminatorPopulationBus' }
-                    ]
-                    , favoriteVehicle: { _id: car._id, speed: 160, __v: 0, __t: 'ModelDiscriminatorPopulationCar' }
-                    , favoriteBus: { _id: bus._id, speed: 80, __v: 0, __t: 'ModelDiscriminatorPopulationBus' }
+                    __v: 0,
+                    _id: user._id,
+                    vehicles: [
+                      { _id: vehicle._id, __v: 0 },
+                      { _id: car._id, speed: 160, __v: 0, __t: 'ModelDiscriminatorPopulationCar' },
+                      { _id: bus._id, speed: 80, __v: 0, __t: 'ModelDiscriminatorPopulationBus' }
+                    ],
+                    favoriteVehicle: { _id: car._id, speed: 160, __v: 0, __t: 'ModelDiscriminatorPopulationCar' },
+                    favoriteBus: { _id: bus._id, speed: 80, __v: 0, __t: 'ModelDiscriminatorPopulationBus' }
                   };
 
                   assert.deepEqual(user.toJSON(), expected);
@@ -722,10 +722,10 @@ describe('model', function() {
           num_of_places: Number
         });
 
-        var Vehicle = db.model('gh2719PopulationVehicle', vehicleSchema)
-          , Car = Vehicle.discriminator('gh2719PopulationCar', carSchema)
-          , Bus = Vehicle.discriminator('gh2719PopulationBus', busSchema)
-          , Garage = db.model('gh2719PopulationGarage', garageSchema);
+        var Vehicle = db.model('gh2719PopulationVehicle', vehicleSchema),
+            Car = Vehicle.discriminator('gh2719PopulationCar', carSchema),
+            Bus = Vehicle.discriminator('gh2719PopulationBus', busSchema),
+            Garage = db.model('gh2719PopulationGarage', garageSchema);
 
         Garage.create({name: 'My', num_of_places: 3}, function(err, garage) {
           assert.ifError(err);
@@ -754,10 +754,10 @@ describe('model', function() {
           Schema.apply(this, arguments);
 
           this.add({
-            name     : { type: String, required: true },
-            date     : { type: Date, required: true },
-            period   : { start : { type: String, required: true },
-              end   : { type: String, required: true }
+            name: { type: String, required: true },
+            date: { type: Date, required: true },
+            period: { start: { type: String, required: true },
+              end: { type: String, required: true }
             }
           });
         }
@@ -768,11 +768,11 @@ describe('model', function() {
         Event = db.model('Event', EventSchema);
 
         TalkSchema = new BaseSchema({
-          pin            : { type: String, required: true, index: { unique: true } },
-          totalAttendees : { type: Number },
-          speakers       : [{ type: Schema.Types.ObjectId, ref: 'Speaker' }],
-          surveys        : [{ type: Schema.Types.ObjectId, ref: 'Survey' }],
-          questions      : [{ type: Schema.Types.ObjectId, ref: 'Question' }]
+          pin: { type: String, required: true, index: { unique: true } },
+          totalAttendees: { type: Number },
+          speakers: [{ type: Schema.Types.ObjectId, ref: 'Speaker' }],
+          surveys: [{ type: Schema.Types.ObjectId, ref: 'Survey' }],
+          questions: [{ type: Schema.Types.ObjectId, ref: 'Question' }]
         });
 
         Talk = Event.discriminator('Talk', TalkSchema);
diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js
index 3b8ae9b6ed8..b3acdb10980 100644
--- a/test/model.discriminator.test.js
+++ b/test/model.discriminator.test.js
@@ -2,20 +2,20 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , Schema = mongoose.Schema
-  , assert = require('assert')
-  , util = require('util')
-  , clone = require('../lib/utils').clone
-  , random = require('../lib/utils').random;
+var start = require('./common'),
+    mongoose = start.mongoose,
+    Schema = mongoose.Schema,
+    assert = require('assert'),
+    util = require('util'),
+    clone = require('../lib/utils').clone,
+    random = require('../lib/utils').random;
 
 /**
  * Setup
  */
 var PersonSchema = new Schema({
-  name: { first: String, last: String }
-  , gender: String
+  name: { first: String, last: String },
+  gender: String
 }, { collection: 'model-discriminator-' + random() });
 PersonSchema.index({ name: 1 });
 PersonSchema.methods.getFullName = function() {
@@ -111,7 +111,7 @@ describe('model', function() {
       var Person = db.model('Person', PersonSchema);
       var Boss = Person.discriminator('Boss', BossSchema);
 
-      var boss = new Boss({name:'Bernenke'});
+      var boss = new Boss({name: 'Bernenke'});
       assert.equal(boss.myName(), 'Bernenke');
       assert.equal(boss.notInstanceMethod, undefined);
       assert.equal(Boss.currentPresident(), 'obama');
@@ -246,8 +246,8 @@ describe('model', function() {
       });
 
       it('is not customizable', function(done) {
-        var errorMessage
-            , CustomizedSchema = new Schema({}, { capped: true });
+        var errorMessage,
+            CustomizedSchema = new Schema({}, { capped: true });
         try {
           Person.discriminator('model-discriminator-custom', CustomizedSchema);
         } catch (e) {
@@ -274,8 +274,8 @@ describe('model', function() {
       });
 
       it('does not inherit and override fields that exist', function(done) {
-        var FemaleSchema = new Schema({ gender: { type: String, default: 'F' }})
-          , Female = Person.discriminator('model-discriminator-female', FemaleSchema);
+        var FemaleSchema = new Schema({ gender: { type: String, default: 'F' }}),
+            Female = Person.discriminator('model-discriminator-female', FemaleSchema);
 
         var gender = Female.schema.paths.gender;
 
@@ -327,8 +327,8 @@ describe('model', function() {
       });
 
       it('gets options overridden by root options except toJSON and toObject', function(done) {
-        var personOptions = clone(Person.schema.options)
-          , employeeOptions = clone(Employee.schema.options);
+        var personOptions = clone(Person.schema.options),
+            employeeOptions = clone(Employee.schema.options);
 
         delete personOptions.toJSON;
         delete personOptions.toObject;
diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js
index eaad22e7bfb..8a7cbcd2d49 100644
--- a/test/model.field.selection.test.js
+++ b/test/model.field.selection.test.js
@@ -2,13 +2,13 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.Types.ObjectId
-  , DocumentObjectId = mongoose.Types.ObjectId;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema,
+    ObjectId = Schema.Types.ObjectId,
+    DocumentObjectId = mongoose.Types.ObjectId;
 
 /**
  * Setup.
@@ -17,29 +17,29 @@ var start = require('./common')
 var Comments = new Schema;
 
 Comments.add({
-  title     : String
-  , date      : Date
-  , body      : String
-  , comments  : [Comments]
+  title: String,
+  date: Date,
+  body: String,
+  comments: [Comments]
 });
 
 var BlogPostB = new Schema({
-  title     : String
-  , author    : String
-  , slug      : String
-  , date      : Date
-  , meta      : {
-    date      : Date
-      , visitors  : Number
-  }
-  , published : Boolean
-  , mixed     : {}
-  , numbers   : [Number]
-  , tags      : [String]
-  , sigs      : [Buffer]
-  , owners    : [ObjectId]
-  , comments  : [Comments]
-  , def       : { type: String, default: 'kandinsky' }
+  title: String,
+  author: String,
+  slug: String,
+  date: Date,
+  meta: {
+    date: Date,
+    visitors: Number
+  },
+  published: Boolean,
+  mixed: {},
+  numbers: [Number],
+  tags: [String],
+  sigs: [Buffer],
+  owners: [ObjectId],
+  comments: [Comments],
+  def: { type: String, default: 'kandinsky' }
 });
 
 var modelName = 'model.select.blogpost';
@@ -48,15 +48,15 @@ var collection = 'blogposts_' + random();
 
 describe('model field selection', function() {
   it('excluded fields should be undefined', function(done) {
-    var db = start()
-      , BlogPostB = db.model(modelName, collection)
-      , date = new Date;
+    var db = start(),
+        BlogPostB = db.model(modelName, collection),
+        date = new Date;
 
     var doc = {
-      title: 'subset 1'
-      , author: 'me'
-      , comments: [{ title: 'first comment', date: new Date }, { title: '2nd', date: new Date }]
-      , meta: { date: date }
+      title: 'subset 1',
+      author: 'me',
+      comments: [{ title: 'first comment', date: new Date }, { title: '2nd', date: new Date }],
+      meta: { date: date }
     };
 
     BlogPostB.create(doc, function(err, created) {
@@ -85,10 +85,10 @@ describe('model field selection', function() {
   });
 
   it('excluded fields should be undefined and defaults applied to other fields', function(done) {
-    var db = start()
-      , BlogPostB = db.model(modelName, collection)
-      , id = new DocumentObjectId
-      , date = new Date;
+    var db = start(),
+        BlogPostB = db.model(modelName, collection),
+        id = new DocumentObjectId,
+        date = new Date;
 
     BlogPostB.collection.insert({ _id: id, title: 'hahaha1', meta: { date: date }}, function(err) {
       assert.ifError(err);
@@ -109,8 +109,8 @@ describe('model field selection', function() {
   });
 
   it('where subset of fields excludes _id', function(done) {
-    var db = start()
-      , BlogPostB = db.model(modelName, collection);
+    var db = start(),
+        BlogPostB = db.model(modelName, collection);
     BlogPostB.create({title: 'subset 1'}, function(err) {
       assert.ifError(err);
       BlogPostB.findOne({title: 'subset 1'}, {title: 1, _id: 0}, function(err, found) {
@@ -124,8 +124,8 @@ describe('model field selection', function() {
   });
 
   it('works with subset of fields, excluding _id', function(done) {
-    var db = start()
-      , BlogPostB = db.model(modelName, collection);
+    var db = start(),
+        BlogPostB = db.model(modelName, collection);
     BlogPostB.create({title: 'subset 1', author: 'me'}, function(err) {
       assert.ifError(err);
       BlogPostB.find({title: 'subset 1'}, {title: 1, _id: 0}, function(err, found) {
@@ -157,8 +157,8 @@ describe('model field selection', function() {
   });
 
   it('works with subset of fields excluding emebedded doc _id (gh-541)', function(done) {
-    var db = start()
-      , BlogPostB = db.model(modelName, collection);
+    var db = start(),
+        BlogPostB = db.model(modelName, collection);
 
     BlogPostB.create({title: 'LOTR', comments: [{ title: ':)' }]}, function(err, created) {
       assert.ifError(err);
@@ -181,9 +181,9 @@ describe('model field selection', function() {
   });
 
   it('included fields should have defaults applied when no value exists in db (gh-870)', function(done) {
-    var db = start()
-      , BlogPostB = db.model(modelName, collection)
-      , id = new DocumentObjectId;
+    var db = start(),
+        BlogPostB = db.model(modelName, collection),
+        id = new DocumentObjectId;
 
     BlogPostB.collection.insert(
         { _id: id, title: 'issue 870'}, { safe: true }, function(err) {
@@ -205,10 +205,10 @@ describe('model field selection', function() {
   });
 
   it('including subdoc field excludes other subdoc fields (gh-1027)', function(done) {
-    var db = start()
-      , BlogPostB = db.model(modelName, collection);
+    var db = start(),
+        BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.create({ comments: [{title: 'a'}, {title:'b'}] }, function(err, doc) {
+    BlogPostB.create({ comments: [{title: 'a'}, {title: 'b'}] }, function(err, doc) {
       assert.ifError(err);
 
       BlogPostB.findById(doc._id).select('_id comments.title').exec(function(err, found) {
@@ -230,10 +230,10 @@ describe('model field selection', function() {
   });
 
   it('excluding nested subdoc fields (gh-1027)', function(done) {
-    var db = start()
-      , BlogPostB = db.model(modelName, collection);
+    var db = start(),
+        BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.create({ title: 'top', comments: [{title: 'a',body:'body'}, {title:'b', body:'body',comments: [{title:'c'}]}] }, function(err, doc) {
+    BlogPostB.create({ title: 'top', comments: [{title: 'a',body: 'body'}, {title: 'b', body: 'body',comments: [{title: 'c'}]}] }, function(err, doc) {
       assert.ifError(err);
 
       BlogPostB.findById(doc._id).select('-_id -comments.title -comments.comments.comments -numbers').exec(function(err, found) {
@@ -308,8 +308,8 @@ describe('model field selection', function() {
       var db = start();
 
       var postSchema = new Schema({
-        ids:  [{type: Schema.ObjectId}]
-         , ids2: [{type: Schema.ObjectId}]
+        ids: [{type: Schema.ObjectId}],
+        ids2: [{type: Schema.ObjectId}]
       });
 
       var B = db.model('gh-1334', postSchema);
@@ -321,7 +321,7 @@ describe('model field selection', function() {
 
         B
         .findById(doc._id)
-        .select({ ids: { $elemMatch:  { $in: [_id2.toString()] }}})
+        .select({ ids: { $elemMatch: { $in: [_id2.toString()] }}})
         .select({ ids2: { $elemMatch: { $in: [_id1.toString()] }}})
         .exec(function(err, found) {
           assert.ifError(err);
@@ -363,10 +363,10 @@ describe('model field selection', function() {
   });
 
   it('selecting an array of docs applies defaults properly (gh-1108)', function(done) {
-    var db = start()
-      , M = db.model(modelName, collection);
+    var db = start(),
+        M = db.model(modelName, collection);
 
-    var m = new M({ title: '1108', comments: [{body:'yay'}] });
+    var m = new M({ title: '1108', comments: [{body: 'yay'}] });
     m.comments[0].comments = undefined;
     m.save(function(err, doc) {
       assert.ifError(err);
@@ -383,19 +383,19 @@ describe('model field selection', function() {
   it('appropriately filters subdocuments based on properties (gh-1280)', function(done) {
     var db = start();
     var RouteSchema = new Schema({
-      stations:   {
+      stations: {
         start: {
-          name:   { type: String },
-          loc:    { type: [Number], index: '2d' }
+          name: { type: String },
+          loc: { type: [Number], index: '2d' }
         },
         end: {
-          name:   { type: String },
-          loc:    { type: [Number], index: '2d' }
+          name: { type: String },
+          loc: { type: [Number], index: '2d' }
         },
         points: [
             {
-              name:   { type: String },
-              loc:    { type: [Number], index: '2d' }
+              name: { type: String },
+              loc: { type: [Number], index: '2d' }
             }
         ]
       }
@@ -404,16 +404,16 @@ describe('model field selection', function() {
     var Route = db.model('Route' + random(), RouteSchema);
 
     var item = {
-      stations : {
-        start : {
-          name : "thing",
-          loc : [1,2]
+      stations: {
+        start: {
+          name: "thing",
+          loc: [1,2]
         },
-        end : {
-          name : "thingend",
-          loc : [2,3]
+        end: {
+          name: "thingend",
+          loc: [2,3]
         },
-        points : [ { name : "rawr" }]
+        points: [ { name: "rawr" }]
       }
     };
 

From ffa5d50fc34ae65bd04ba752c064f0d9ee114791 Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Tue, 8 Dec 2015 16:38:02 -0700
Subject: [PATCH 0109/2240] general linting

---
 test/model.findOneAndUpdate.test.js |  2 +-
 test/types.array.test.js            | 18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index 4f849bfa104..e9c5a72d228 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -1533,7 +1533,7 @@ describe('model: findByIdAndUpdate:', function() {
 
       var MyModel = db.model('gh3616', s);
 
-      MyModel.create({ nested: { arr: [{ num: 5 }] } }, function(error, doc) {
+      MyModel.create({ nested: { arr: [{ num: 5 }] } }, function(error) {
         assert.ifError(error);
         var update = { $pull: { 'nested.arr': { num: 5 } } };
         var options = { 'new': true };
diff --git a/test/types.array.test.js b/test/types.array.test.js
index 2624ac2d66c..2473d0cde29 100644
--- a/test/types.array.test.js
+++ b/test/types.array.test.js
@@ -396,11 +396,11 @@ describe('types array', function() {
 
     it('works', function(done) {
       var schema = new Schema({
-          types: [new Schema({ type: String })]
-            , nums: [Number]
-            , strs: [String]
-        })
-        , A = db.model('unshift', schema, 'unshift' + random());
+            types: [new Schema({ type: String })],
+            nums: [Number],
+            strs: [String]
+          }),
+          A = db.model('unshift', schema, 'unshift' + random());
 
       var a = new A({
         types: [{type:'bird'},{type:'boy'},{type:'frog'},{type:'cloud'}]
@@ -512,10 +512,10 @@ describe('types array', function() {
 
     it('works', function(done) {
       var schema = new Schema({
-          types: [new Schema({ type: String })]
-            , nums: [Number]
-            , strs: [String]
-        });
+        types: [new Schema({ type: String })],
+        nums: [Number],
+        strs: [String]
+      });
 
       var A = db.model('shift', schema, 'unshift' + random());
 

From 1ef43b3f5d26933719c98544ca714e6255a45b02 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 9 Dec 2015 11:14:29 -0500
Subject: [PATCH 0110/2240] feat(aggregate): $lookup operator

---
 lib/aggregate.js       | 17 +++++++++++++++++
 test/aggregate.test.js | 18 ++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/lib/aggregate.js b/lib/aggregate.js
index 3686941a3f2..efc7b52d078 100644
--- a/lib/aggregate.js
+++ b/lib/aggregate.js
@@ -277,6 +277,23 @@ Aggregate.prototype.unwind = function() {
   }));
 };
 
+/**
+ * Appends new custom $lookup operator(s) to this aggregate pipeline.
+ *
+ * ####Examples:
+ *
+ *     aggregate.lookup({ from: 'users', localField: 'userId', foreignField: '_id', as: 'users' });
+ *
+ * @see $lookup https://docs.mongodb.org/manual/reference/operator/aggregation/lookup/#pipe._S_lookup
+ * @param {Object} options to $lookup as described in the above link
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.lookup = function(options) {
+  return this.append({ $lookup: options });
+};
+
 /**
  * Appends a new $sort operator to this aggregate pipeline.
  *
diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index 11be81327ef..c29e63139f6 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -315,6 +315,24 @@ describe('aggregate: ', function() {
     });
   });
 
+  describe('lookup', function() {
+    it('works', function(done) {
+      var aggregate = new Aggregate();
+      var obj = {
+        from: 'users',
+        localField: 'userId',
+        foreignField: '_id',
+        as: 'users'
+      };
+
+      aggregate.lookup(obj);
+
+      assert.equal(aggregate._pipeline.length, 1);
+      assert.deepEqual(aggregate._pipeline[0].$lookup, obj);
+      done();
+    });
+  });
+
   describe('bind', function() {
     it('works', function(done) {
       var aggregate = new Aggregate()

From c003d315c4f7ba9f14b5eb393b4cda24d4d7912a Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 9 Dec 2015 13:01:39 -0500
Subject: [PATCH 0111/2240] feat(query): bitwise query operators

---
 lib/schema/number.js | 16 ++++++++++++++++
 test/cast.test.js    | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)
 create mode 100644 test/cast.test.js

diff --git a/lib/schema/number.js b/lib/schema/number.js
index 7c427cfa37e..32c8ee9f56a 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -239,8 +239,24 @@ function handleArray(val) {
   });
 }
 
+function handleBitwiseOperator(val) {
+  var _this = this;
+  if (Array.isArray(val)) {
+    return val.map(function(v) { return _this.cast(v); });
+  } else if (Buffer.isBuffer(val)) {
+    return val;
+  } else {
+    // Assume trying to cast to number
+    return this.cast(val);
+  }
+}
+
 SchemaNumber.prototype.$conditionalHandlers =
   utils.options(SchemaType.prototype.$conditionalHandlers, {
+    '$bitsAllClear': handleBitwiseOperator,
+    '$bitsAnyClear': handleBitwiseOperator,
+    '$bitsAllSet': handleBitwiseOperator,
+    '$bitsAnySet': handleBitwiseOperator,
     '$gt' : handleSingle,
     '$gte': handleSingle,
     '$lt' : handleSingle,
diff --git a/test/cast.test.js b/test/cast.test.js
new file mode 100644
index 00000000000..0fd69e99c3e
--- /dev/null
+++ b/test/cast.test.js
@@ -0,0 +1,36 @@
+/**
+ * Module dependencies.
+ */
+
+var Schema = require('../lib/schema');
+var assert = require('assert');
+var cast = require('../lib/cast');
+
+describe('cast: ', function() {
+  describe('bitwise query operators: ', function() {
+    it('with a number', function() {
+      var schema = new Schema({ x: Number });
+      assert.deepEqual(cast(schema, { x: { $bitsAllClear: 3 } }),
+        { x: { $bitsAllClear: 3 } });
+    });
+
+    it('with an array', function() {
+      var schema = new Schema({ x: Number });
+      assert.deepEqual(cast(schema, { x: { $bitsAllSet: [2, '3'] } }),
+        { x: { $bitsAllSet: [2, 3] } });
+    });
+
+    it('with a buffer', function() {
+      var schema = new Schema({ x: Number });
+      assert.deepEqual(cast(schema, { x: { $bitsAnyClear: new Buffer([3]) } }),
+        { x: { $bitsAnyClear: new Buffer([3]) } });
+    });
+
+    it('throws when invalid', function() {
+      var schema = new Schema({ x: Number });
+      assert.throws(function() {
+        cast(schema, { x: { $bitsAnySet: 'Not a number' } });
+      }, /Cast to number failed/);
+    });
+  });
+});

From 2ee009a8f3fa55e53b3bc5f68f2166b192a0f57a Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 9 Dec 2015 13:13:45 -0500
Subject: [PATCH 0112/2240] release 4.3.0

---
 History.md      |  9 ++++++++-
 bin/mongoose.js | 16 ++++++++++++++++
 package.json    |  2 +-
 3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/History.md b/History.md
index 6fb61fc586a..ac38d6a9a6f 100644
--- a/History.md
+++ b/History.md
@@ -1,5 +1,12 @@
-4.2.10 /2015-12-08
+4.3.0 / 2015-12-09
 ==================
+ * feat(query): support for mongodb 3.2 bitwise query operators #3660
+ * style: use comma-last style consistently #3657 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * feat: upgrade mongodb driver to 2.1.0 for full MongoDB 3.2 support #3656
+ * feat(aggregate): `.lookup()` helper #3532
+
+4.2.10 / 2015-12-08
+===================
  * fixed; upgraded marked #3653 [ChristianMurphy](https://github.com/ChristianMurphy)
  * docs; cross-db populate #3648
  * docs; update mocha URL #3646 [ojhaujjwal](https://github.com/ojhaujjwal)
diff --git a/bin/mongoose.js b/bin/mongoose.js
index e2249e82264..157890e2ab3 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -6670,8 +6670,24 @@ function handleArray(val) {
   });
 }
 
+function handleBitwiseOperator(val) {
+  var _this = this;
+  if (Array.isArray(val)) {
+    return val.map(function(v) { return _this.cast(v); });
+  } else if (Buffer.isBuffer(val)) {
+    return val;
+  } else {
+    // Assume trying to cast to number
+    return this.cast(val);
+  }
+}
+
 SchemaNumber.prototype.$conditionalHandlers =
   utils.options(SchemaType.prototype.$conditionalHandlers, {
+    '$bitsAllClear': handleBitwiseOperator,
+    '$bitsAnyClear': handleBitwiseOperator,
+    '$bitsAllSet': handleBitwiseOperator,
+    '$bitsAnySet': handleBitwiseOperator,
     '$gt' : handleSingle,
     '$gte': handleSingle,
     '$lt' : handleSingle,
diff --git a/package.json b/package.json
index 9cb0b24364e..9be0e79f963 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.0-pre",
+  "version": "4.3.0",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From d5a08ad695c5503bd297d094637f29b77e25d5fa Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 10 Dec 2015 15:19:38 -0500
Subject: [PATCH 0113/2240] now working on 4.3.1

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 9be0e79f963..e1897ad438e 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.0",
+  "version": "4.3.1-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From 92630c35dd18be911986aa191a0e9c8d7d5d066a Mon Sep 17 00:00:00 2001
From: Doug Molineux 
Date: Thu, 10 Dec 2015 14:21:03 -0700
Subject: [PATCH 0114/2240] #3628 Mapreduce should return es6 promise

---
 lib/model.js                 | 41 ++++++++++++++++++------------------
 test/model.mapreduce.test.js | 19 +++++++++--------
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/lib/model.js b/lib/model.js
index f8d9b08cf4e..5200933ea66 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -1962,7 +1962,7 @@ Model.update = function update(conditions, doc, options, callback) {
  */
 
 Model.mapReduce = function mapReduce(o, callback) {
-  var promise = new Promise(callback);
+  var promise = PromiseProvider.get();
   var self = this;
 
   if (!Model.mapReduce.schema) {
@@ -1983,27 +1983,26 @@ Model.mapReduce = function mapReduce(o, callback) {
     q = undefined;
   }
 
-  this.collection.mapReduce(null, null, o, function(err, ret, stats) {
-    if (err) return promise.error(err);
-
-    if (ret.findOne && ret.mapReduce) {
-      // returned a collection, convert to Model
-      var model = Model.compile(
-          '_mapreduce_' + ret.collectionName
-        , Model.mapReduce.schema
-        , ret.collectionName
-        , self.db
-        , self.base);
-
-      model._mapreduce = true;
-
-      return promise.fulfill(model, stats);
-    }
-
-    promise.fulfill(ret, stats);
+  return new Promise.ES6(function(resolve, reject) {
+    self.collection.mapReduce(null, null, o, function(err, ret, stats) {
+      if (err) {
+        return reject(err);
+      }
+      if (ret.findOne && ret.mapReduce) {
+        // returned a collection, convert to Model
+        var model = Model.compile(
+            '_mapreduce_' + ret.collectionName
+          , Model.mapReduce.schema
+          , ret.collectionName
+          , self.db
+          , self.base);
+
+        model._mapreduce = true;
+        return resolve(model, stats);
+      }
+      return resolve(ret, stats);
+    });
   });
-
-  return promise;
 };
 
 /**
diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 2f82ad29883..314b4dee38b 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -68,8 +68,7 @@ describe('model: mapreduce:', function() {
         , reduce: function(k, vals) { return vals.length; }
       };
 
-      MR.mapReduce(o, function(err, ret, stats) {
-        assert.ifError(err);
+      MR.mapReduce(o).then(function(ret, stats) {
         assert.ok(Array.isArray(ret));
         assert.ok(stats);
         ret.forEach(function(res) {
@@ -85,17 +84,16 @@ describe('model: mapreduce:', function() {
           , query: { author: 'aaron', published: 1, owners: id }
         };
 
-        MR.mapReduce(o, function(err, ret, stats) {
-          assert.ifError(err);
-
+        MR.mapReduce(o).then(function(ret, stats) {
           assert.ok(Array.isArray(ret));
           assert.equal(1, ret.length);
           assert.equal('aaron', ret[0]._id);
           assert.equal(3, ret[0].value);
           assert.ok(stats);
-
           modeling();
         });
+      }).catch(function(err) {
+        assert.ifError(err);
       });
 
       function modeling() {
@@ -106,8 +104,7 @@ describe('model: mapreduce:', function() {
           , out: { replace: '_mapreduce_test_' + random() }
         };
 
-        MR.mapReduce(o, function(err, ret) {
-          assert.ifError(err);
+        MR.mapReduce(o).then(function(ret) {
 
           // ret is a model
           assert.ok(!Array.isArray(ret));
@@ -141,6 +138,9 @@ describe('model: mapreduce:', function() {
               });
             });
           });
+        }).catch(function(err) {
+          assert.ifError(err);
+          done();
         });
       }
     });
@@ -156,10 +156,11 @@ describe('model: mapreduce:', function() {
       , verbose: false
     };
 
-    MR.mapReduce(o, function(err, results, stats) {
+    MR.mapReduce(o).then(function(results, stats) {
       assert.equal('undefined', typeof stats);
       db.close(done);
     });
+
   });
 
   describe('promises (gh-1628)', function() {

From d04e9efba61228ab960da46389064d4075d5f9d9 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 10 Dec 2015 17:19:56 -0500
Subject: [PATCH 0115/2240] feat(query): buffers support bitwise (Fix #3663)

---
 lib/schema/buffer.js            |  5 +++++
 lib/schema/number.js            | 11 +++++-----
 lib/schema/operators/bitwise.js | 37 +++++++++++++++++++++++++++++++++
 test/cast.test.js               |  4 ++--
 4 files changed, 50 insertions(+), 7 deletions(-)
 create mode 100644 lib/schema/operators/bitwise.js

diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js
index 159a28ab9d2..c46da0494d9 100644
--- a/lib/schema/buffer.js
+++ b/lib/schema/buffer.js
@@ -2,6 +2,7 @@
  * Module dependencies.
  */
 
+var handleBitwiseOperator = require('./operators/bitwise');
 var utils = require('../utils');
 
 var MongooseBuffer = require('../types').Buffer;
@@ -140,6 +141,10 @@ function handleSingle(val) {
 
 SchemaBuffer.prototype.$conditionalHandlers =
   utils.options(SchemaType.prototype.$conditionalHandlers, {
+    '$bitsAllClear': handleBitwiseOperator,
+    '$bitsAnyClear': handleBitwiseOperator,
+    '$bitsAllSet': handleBitwiseOperator,
+    '$bitsAnySet': handleBitwiseOperator,
     '$gt' : handleSingle,
     '$gte': handleSingle,
     '$lt' : handleSingle,
diff --git a/lib/schema/number.js b/lib/schema/number.js
index 32c8ee9f56a..24f07468357 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -2,11 +2,12 @@
  * Module requirements.
  */
 
-var SchemaType = require('../schematype'),
-    CastError = SchemaType.CastError,
-    errorMessages = require('../error').messages,
-    utils = require('../utils'),
-    Document;
+var SchemaType = require('../schematype');
+var CastError = SchemaType.CastError;
+var handleBitwiseOperator = require('./operators/bitwise');
+var errorMessages = require('../error').messages;
+var utils = require('../utils');
+var Document;
 
 /**
  * Number SchemaType constructor.
diff --git a/lib/schema/operators/bitwise.js b/lib/schema/operators/bitwise.js
new file mode 100644
index 00000000000..e3932481449
--- /dev/null
+++ b/lib/schema/operators/bitwise.js
@@ -0,0 +1,37 @@
+/*!
+ * Module requirements.
+ */
+
+var CastError = require('../../error/cast');
+
+/*!
+ * ignore
+ */
+
+function handleBitwiseOperator(val) {
+  var _this = this;
+  if (Array.isArray(val)) {
+    return val.map(function(v) {
+      return _castNumber(_this, v);
+    });
+  } else if (Buffer.isBuffer(val)) {
+    return val;
+  } else {
+    // Assume trying to cast to number
+    return _castNumber(_this, val);
+  }
+}
+
+/*!
+ * ignore
+ */
+
+function _castNumber(_this, num) {
+  var v = Number(num);
+  if (isNaN(v)) {
+    throw new CastError('number', num, _this.path);
+  }
+  return v;
+}
+
+module.exports = handleBitwiseOperator;
diff --git a/test/cast.test.js b/test/cast.test.js
index 0fd69e99c3e..9ebc6ef5648 100644
--- a/test/cast.test.js
+++ b/test/cast.test.js
@@ -9,13 +9,13 @@ var cast = require('../lib/cast');
 describe('cast: ', function() {
   describe('bitwise query operators: ', function() {
     it('with a number', function() {
-      var schema = new Schema({ x: Number });
+      var schema = new Schema({ x: Buffer });
       assert.deepEqual(cast(schema, { x: { $bitsAllClear: 3 } }),
         { x: { $bitsAllClear: 3 } });
     });
 
     it('with an array', function() {
-      var schema = new Schema({ x: Number });
+      var schema = new Schema({ x: Buffer });
       assert.deepEqual(cast(schema, { x: { $bitsAllSet: [2, '3'] } }),
         { x: { $bitsAllSet: [2, 3] } });
     });

From 6c5d6463332643b7877d1d939fcefe0161a84f7e Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 10 Dec 2015 17:23:01 -0500
Subject: [PATCH 0116/2240] docs(migration): clarify findAndModify change for
 findByIdAndUpdate (Fix #3661)

---
 docs/migration.jade | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/docs/migration.jade b/docs/migration.jade
index 0dae65916ba..7172f1f7b50 100644
--- a/docs/migration.jade
+++ b/docs/migration.jade
@@ -11,12 +11,19 @@ block content
   :markdown
     There are several [backwards-breaking changes](https://github.com/Automattic/mongoose/wiki/4.0-Release-Notes) to be aware of when migrating from Mongoose 3 to Mongoose 4.
 
-  h3 findOneAndUpdate() new field is now `false` by default
+  h3#findandmodify-new
+    | `findOneAndUpdate()` new field is now `false` by default
   :markdown
-    Mongoose's `findOneAndUpdate()` and `findOneAndRemove()` functions are just wrappers around MongoDB's [`findAndModify` command](http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/).
-    Both the MongoDB server and the MongoDB NodeJS driver set the `new` option to false by default, but mongoose 3 overwrote this default.
-    In order to be more consistent with the MongoDB server's documentation, mongoose will use false by default.
-    That is, `findOneAndUpdate({}, { $set: { test: 1 } }, callback);` will return the document as it was *before* the `$set` operation was applied.
+    Mongoose's `findOneAndUpdate()`, `findOneAndRemove()`,
+    `findByIdAndUpdate()`, and `findByIdAndRemove()` functions are just
+    wrappers around MongoDB's
+    [`findAndModify` command](http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/).
+    Both the MongoDB server and the MongoDB NodeJS driver set the `new` option
+    to false by default, but mongoose 3 overwrote this default. In order to be
+    more consistent with the MongoDB server's documentation, mongoose will
+    use false by default. That is,
+    `findOneAndUpdate({}, { $set: { test: 1 } }, callback);` will return the
+    document as it was *before* the `$set` operation was applied.
 
     To return the document with modifications made on the update, use the `new: true` option.
 

From 9fb1933b4a3ef3feb865fdb257bc71ce3867217f Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 10 Dec 2015 17:26:32 -0500
Subject: [PATCH 0117/2240] feat(aggregate): .sample() helper (Fix #3665)

---
 lib/aggregate.js       | 17 +++++++++++++++++
 test/aggregate.test.js | 12 ++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/lib/aggregate.js b/lib/aggregate.js
index efc7b52d078..2e6dd85f3c7 100644
--- a/lib/aggregate.js
+++ b/lib/aggregate.js
@@ -294,6 +294,23 @@ Aggregate.prototype.lookup = function(options) {
   return this.append({ $lookup: options });
 };
 
+/**
+ * Appends new custom $sample operator(s) to this aggregate pipeline.
+ *
+ * ####Examples:
+ *
+ *     aggregate.sample(3); // Add a pipeline that picks 3 random documents
+ *
+ * @see $sample https://docs.mongodb.org/manual/reference/operator/aggregation/sample/#pipe._S_sample
+ * @param {Number} size number of random documents to pick
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.sample = function(size) {
+  return this.append({ $sample: { size: size } });
+};
+
 /**
  * Appends a new $sort operator to this aggregate pipeline.
  *
diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index 5c4df4aec4d..38209e13238 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -333,6 +333,18 @@ describe('aggregate: ', function() {
     });
   });
 
+  describe('sample', function() {
+    it('works', function(done) {
+      var aggregate = new Aggregate();
+
+      aggregate.sample(3);
+
+      assert.equal(aggregate._pipeline.length, 1);
+      assert.deepEqual(aggregate._pipeline[0].$sample, { size: 3 });
+      done();
+    });
+  });
+
   describe('bind', function() {
     it('works', function(done) {
       var aggregate = new Aggregate(),

From 73ced54bfc9866b471a1c54a43abad9300bf9817 Mon Sep 17 00:00:00 2001
From: Doug Molineux 
Date: Thu, 10 Dec 2015 15:37:05 -0700
Subject: [PATCH 0118/2240] #3628 Made sure to call the callback function as
 well

---
 lib/model.js                 | 21 ++++++++++-----------
 test/model.mapreduce.test.js |  5 +++--
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/lib/model.js b/lib/model.js
index 5200933ea66..98f9ae441ea 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -1938,13 +1938,6 @@ Model.update = function update(conditions, doc, options, callback) {
  *     o.out = { replace: 'createdCollectionNameForResults' }
  *     o.verbose = true;
  *
- *     User.mapReduce(o, function (err, model, stats) {
- *       console.log('map reduce took %d ms', stats.processtime)
- *       model.find().where('value').gt(10).exec(function (err, docs) {
- *         console.log(docs);
- *       });
- *     })
- *
  *     // a promise is returned so you may instead write
  *     var promise = User.mapReduce(o);
  *     promise.then(function (model, stats) {
@@ -1962,7 +1955,7 @@ Model.update = function update(conditions, doc, options, callback) {
  */
 
 Model.mapReduce = function mapReduce(o, callback) {
-  var promise = PromiseProvider.get();
+  var Promise = PromiseProvider.get();
   var self = this;
 
   if (!Model.mapReduce.schema) {
@@ -1986,7 +1979,9 @@ Model.mapReduce = function mapReduce(o, callback) {
   return new Promise.ES6(function(resolve, reject) {
     self.collection.mapReduce(null, null, o, function(err, ret, stats) {
       if (err) {
-        return reject(err);
+        reject(err);
+        callback && callback(err);
+        return;
       }
       if (ret.findOne && ret.mapReduce) {
         // returned a collection, convert to Model
@@ -1998,9 +1993,13 @@ Model.mapReduce = function mapReduce(o, callback) {
           , self.base);
 
         model._mapreduce = true;
-        return resolve(model, stats);
+        resolve(model, stats);
+        callback && callback(null, model, stats);
+        return;
       }
-      return resolve(ret, stats);
+      resolve(ret, stats);
+      callback && callback(null, ret, stats);
+      return;
     });
   });
 };
diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 314b4dee38b..27c82e05d14 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -91,9 +91,10 @@ describe('model: mapreduce:', function() {
           assert.equal(3, ret[0].value);
           assert.ok(stats);
           modeling();
+        }).catch(function(err) {
+          assert.ifError(err);
         });
-      }).catch(function(err) {
-        assert.ifError(err);
+
       });
 
       function modeling() {

From caae826f15e2d88f8a78bdfbb72542231cb9e404 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 11 Dec 2015 10:41:54 -0500
Subject: [PATCH 0119/2240] release 4.3.1

---
 History.md      |   6 ++
 bin/mongoose.js | 215 +++++++++++++++++++++++++++++-------------------
 package.json    |   2 +-
 3 files changed, 138 insertions(+), 85 deletions(-)

diff --git a/History.md b/History.md
index ac38d6a9a6f..46b42f5ccc2 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,9 @@
+4.3.1 / 2015-12-11
+==================
+ * feat(aggregate): `.sample()` helper #3665
+ * fix(query): bitwise query operators with buffers #3663
+ * docs(migration): clarify `new` option and findByIdAndUpdate #3661
+
 4.3.0 / 2015-12-09
 ==================
  * feat(query): support for mongodb 3.2 bitwise query operators #3660
diff --git a/bin/mongoose.js b/bin/mongoose.js
index 157890e2ab3..bd69531e5a2 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -129,7 +129,7 @@ if (typeof window !== 'undefined') {
 }
 
 }).call(this,require("buffer").Buffer)
-},{"./document_provider.js":6,"./error":12,"./schema":24,"./schematype.js":36,"./types":42,"./utils.js":45,"./virtualtype":46,"buffer":49}],3:[function(require,module,exports){
+},{"./document_provider.js":6,"./error":12,"./schema":24,"./schematype.js":37,"./types":43,"./utils.js":46,"./virtualtype":47,"buffer":50}],3:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -236,7 +236,7 @@ Document.prototype.constructor = Document;
 Document.ValidationError = ValidationError;
 module.exports = exports = Document;
 
-},{"./document":5,"./error":12,"./internal":21,"./schema":24,"./types/objectid":43,"./utils":45,"events":53}],4:[function(require,module,exports){
+},{"./document":5,"./error":12,"./internal":21,"./schema":24,"./types/objectid":44,"./utils":46,"events":54}],4:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -449,7 +449,7 @@ var cast = module.exports = function(schema, obj) {
   return obj;
 };
 
-},{"./schema/index":31,"./utils":45}],5:[function(require,module,exports){
+},{"./schema/index":31,"./utils":46}],5:[function(require,module,exports){
 (function (process,Buffer){
 /* eslint no-unused-vars: 1 */
 
@@ -2785,7 +2785,7 @@ Document.ValidationError = ValidationError;
 module.exports = exports = Document;
 
 }).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"./error":12,"./internal":21,"./promise_provider":23,"./schema":24,"./schema/mixed":32,"./schematype":36,"./types/array":38,"./types/documentarray":40,"./types/embedded":41,"./utils":45,"FWaASH":55,"buffer":49,"events":53,"hooks-fixed":76,"util":57}],6:[function(require,module,exports){
+},{"./error":12,"./internal":21,"./promise_provider":23,"./schema":24,"./schema/mixed":32,"./schematype":37,"./types/array":39,"./types/documentarray":41,"./types/embedded":42,"./utils":46,"FWaASH":56,"buffer":50,"events":54,"hooks-fixed":77,"util":58}],6:[function(require,module,exports){
 'use strict';
 
 /*!
@@ -2827,7 +2827,7 @@ var Binary = require('bson').Binary;
 
 module.exports = exports = Binary;
 
-},{"bson":60}],9:[function(require,module,exports){
+},{"bson":61}],9:[function(require,module,exports){
 /*!
  * Module exports.
  */
@@ -2852,7 +2852,7 @@ var ObjectId = require('bson').ObjectID;
 
 module.exports = exports = ObjectId;
 
-},{"bson":60}],11:[function(require,module,exports){
+},{"bson":61}],11:[function(require,module,exports){
 (function (global){
 /*!
  * ignore
@@ -3335,7 +3335,7 @@ function InternalCache() {
   this.fullPath = undefined;
 }
 
-},{"./statemachine":37}],22:[function(require,module,exports){
+},{"./statemachine":38}],22:[function(require,module,exports){
 /*!
  * Module dependencies
  */
@@ -3628,7 +3628,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject;
 
 module.exports = Promise;
 
-},{"mpromise":80,"util":57}],23:[function(require,module,exports){
+},{"mpromise":81,"util":58}],23:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -3681,7 +3681,7 @@ Promise.reset = function() {
 
 module.exports = Promise;
 
-},{"./ES6Promise":1,"./promise":22,"mquery":85}],24:[function(require,module,exports){
+},{"./ES6Promise":1,"./promise":22,"mquery":86}],24:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -4960,7 +4960,7 @@ Schema.Types = MongooseTypes = require('./schema/index');
 exports.ObjectId = MongooseTypes.ObjectId;
 
 }).call(this,require("buffer").Buffer)
-},{"./drivers":11,"./promise_provider":23,"./schema/index":31,"./utils":45,"./virtualtype":46,"async":47,"buffer":49,"events":53,"kareem":77}],25:[function(require,module,exports){
+},{"./drivers":11,"./promise_provider":23,"./schema/index":31,"./utils":46,"./virtualtype":47,"async":48,"buffer":50,"events":54,"kareem":78}],25:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -5356,7 +5356,7 @@ handle.$regex = SchemaArray.prototype.castForQuery;
 
 module.exports = SchemaArray;
 
-},{"../cast":4,"../schematype":36,"../types":42,"../utils":45,"./boolean":26,"./buffer":27,"./date":28,"./mixed":32,"./number":33,"./objectid":34,"./string":35}],26:[function(require,module,exports){
+},{"../cast":4,"../schematype":37,"../types":43,"../utils":46,"./boolean":26,"./buffer":27,"./date":28,"./mixed":32,"./number":33,"./objectid":34,"./string":36}],26:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -5449,12 +5449,13 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val) {
 
 module.exports = SchemaBoolean;
 
-},{"../schematype":36,"../utils":45}],27:[function(require,module,exports){
+},{"../schematype":37,"../utils":46}],27:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
  */
 
+var handleBitwiseOperator = require('./operators/bitwise');
 var utils = require('../utils');
 
 var MongooseBuffer = require('../types').Buffer;
@@ -5593,6 +5594,10 @@ function handleSingle(val) {
 
 SchemaBuffer.prototype.$conditionalHandlers =
   utils.options(SchemaType.prototype.$conditionalHandlers, {
+    '$bitsAllClear': handleBitwiseOperator,
+    '$bitsAnyClear': handleBitwiseOperator,
+    '$bitsAllSet': handleBitwiseOperator,
+    '$bitsAnySet': handleBitwiseOperator,
     '$gt' : handleSingle,
     '$gte': handleSingle,
     '$lt' : handleSingle,
@@ -5627,7 +5632,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaBuffer;
 
 }).call(this,require("buffer").Buffer)
-},{"../schematype":36,"../types":42,"../utils":45,"./../document":5,"buffer":49}],28:[function(require,module,exports){
+},{"../schematype":37,"../types":43,"../utils":46,"./../document":5,"./operators/bitwise":35,"buffer":50}],28:[function(require,module,exports){
 /*!
  * Module requirements.
  */
@@ -5913,7 +5918,7 @@ SchemaDate.prototype.castForQuery = function($conditional, val) {
 
 module.exports = SchemaDate;
 
-},{"../error":12,"../schematype":36,"../utils":45}],29:[function(require,module,exports){
+},{"../error":12,"../schematype":37,"../utils":46}],29:[function(require,module,exports){
 /* eslint no-empty: 1 */
 
 /*!
@@ -6169,7 +6174,7 @@ function scopePaths(array, fields, init) {
 
 module.exports = DocumentArray;
 
-},{"../error/cast":13,"../schematype":36,"../types/documentarray":40,"../types/embedded":41,"./array":25}],30:[function(require,module,exports){
+},{"../error/cast":13,"../schematype":37,"../types/documentarray":41,"../types/embedded":42,"./array":25}],30:[function(require,module,exports){
 var SchemaType = require('../schematype');
 var Subdocument = require('../types/subdocument');
 
@@ -6302,7 +6307,7 @@ Embedded.prototype.checkRequired = function(value) {
   return !!value && value.$isSingleNested;
 };
 
-},{"../schematype":36,"../types/subdocument":44}],31:[function(require,module,exports){
+},{"../schematype":37,"../types/subdocument":45}],31:[function(require,module,exports){
 
 /*!
  * Module exports.
@@ -6334,7 +6339,7 @@ exports.Oid = exports.ObjectId;
 exports.Object = exports.Mixed;
 exports.Bool = exports.Boolean;
 
-},{"./array":25,"./boolean":26,"./buffer":27,"./date":28,"./documentarray":29,"./embedded":30,"./mixed":32,"./number":33,"./objectid":34,"./string":35}],32:[function(require,module,exports){
+},{"./array":25,"./boolean":26,"./buffer":27,"./date":28,"./documentarray":29,"./embedded":30,"./mixed":32,"./number":33,"./objectid":34,"./string":36}],32:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -6427,17 +6432,18 @@ Mixed.prototype.castForQuery = function($cond, val) {
 
 module.exports = Mixed;
 
-},{"../schematype":36,"../utils":45}],33:[function(require,module,exports){
+},{"../schematype":37,"../utils":46}],33:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module requirements.
  */
 
-var SchemaType = require('../schematype'),
-    CastError = SchemaType.CastError,
-    errorMessages = require('../error').messages,
-    utils = require('../utils'),
-    Document;
+var SchemaType = require('../schematype');
+var CastError = SchemaType.CastError;
+var handleBitwiseOperator = require('./operators/bitwise');
+var errorMessages = require('../error').messages;
+var utils = require('../utils');
+var Document;
 
 /**
  * Number SchemaType constructor.
@@ -6723,7 +6729,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaNumber;
 
 }).call(this,require("buffer").Buffer)
-},{"../error":12,"../schematype":36,"../utils":45,"./../document":5,"buffer":49}],34:[function(require,module,exports){
+},{"../error":12,"../schematype":37,"../utils":46,"./../document":5,"./operators/bitwise":35,"buffer":50}],34:[function(require,module,exports){
 (function (Buffer){
 /* eslint no-empty: 1 */
 
@@ -6921,7 +6927,48 @@ function resetId(v) {
 module.exports = ObjectId;
 
 }).call(this,require("buffer").Buffer)
-},{"../schematype":36,"../types/objectid":43,"../utils":45,"./../document":5,"buffer":49}],35:[function(require,module,exports){
+},{"../schematype":37,"../types/objectid":44,"../utils":46,"./../document":5,"buffer":50}],35:[function(require,module,exports){
+(function (Buffer){
+/*!
+ * Module requirements.
+ */
+
+var CastError = require('../../error/cast');
+
+/*!
+ * ignore
+ */
+
+function handleBitwiseOperator(val) {
+  var _this = this;
+  if (Array.isArray(val)) {
+    return val.map(function(v) {
+      return _castNumber(_this, v);
+    });
+  } else if (Buffer.isBuffer(val)) {
+    return val;
+  } else {
+    // Assume trying to cast to number
+    return _castNumber(_this, val);
+  }
+}
+
+/*!
+ * ignore
+ */
+
+function _castNumber(_this, num) {
+  var v = Number(num);
+  if (isNaN(v)) {
+    throw new CastError('number', num, _this.path);
+  }
+  return v;
+}
+
+module.exports = handleBitwiseOperator;
+
+}).call(this,require("buffer").Buffer)
+},{"../../error/cast":13,"buffer":50}],36:[function(require,module,exports){
 (function (Buffer){
 
 /*!
@@ -7417,7 +7464,7 @@ SchemaString.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaString;
 
 }).call(this,require("buffer").Buffer)
-},{"../error":12,"../schematype":36,"../utils":45,"./../document":5,"buffer":49}],36:[function(require,module,exports){
+},{"../error":12,"../schematype":37,"../utils":46,"./../document":5,"buffer":50}],37:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -8276,7 +8323,7 @@ exports.CastError = CastError;
 exports.ValidatorError = ValidatorError;
 
 }).call(this,require("buffer").Buffer)
-},{"./error":12,"./utils":45,"buffer":49}],37:[function(require,module,exports){
+},{"./error":12,"./utils":46,"buffer":50}],38:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -8456,7 +8503,7 @@ StateMachine.prototype.map = function map() {
   return this.map.apply(this, arguments);
 };
 
-},{"./utils":45}],38:[function(require,module,exports){
+},{"./utils":46}],39:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9223,7 +9270,7 @@ MongooseArray.mixin.remove = MongooseArray.mixin.pull;
 module.exports = exports = MongooseArray;
 
 }).call(this,require("buffer").Buffer)
-},{"../document":5,"../utils":45,"./embedded":41,"./objectid":43,"buffer":49}],39:[function(require,module,exports){
+},{"../document":5,"../utils":46,"./embedded":42,"./objectid":44,"buffer":50}],40:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9496,7 +9543,7 @@ MongooseBuffer.Binary = Binary;
 module.exports = MongooseBuffer;
 
 }).call(this,require("buffer").Buffer)
-},{"../drivers":11,"../utils":45,"buffer":49}],40:[function(require,module,exports){
+},{"../drivers":11,"../utils":46,"buffer":50}],41:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9723,7 +9770,7 @@ MongooseDocumentArray.mixin.notify = function notify(event) {
 module.exports = MongooseDocumentArray;
 
 }).call(this,require("buffer").Buffer)
-},{"../document":5,"../schema/objectid":34,"../utils":45,"./array":38,"./objectid":43,"buffer":49,"util":57}],41:[function(require,module,exports){
+},{"../document":5,"../schema/objectid":34,"../utils":46,"./array":39,"./objectid":44,"buffer":50,"util":58}],42:[function(require,module,exports){
 /* eslint no-func-assign: 1 */
 
 /*!
@@ -10037,7 +10084,7 @@ EmbeddedDocument.prototype.parentArray = function() {
 
 module.exports = EmbeddedDocument;
 
-},{"../document_provider":6,"../promise_provider":23,"util":57}],42:[function(require,module,exports){
+},{"../document_provider":6,"../promise_provider":23,"util":58}],43:[function(require,module,exports){
 
 /*!
  * Module exports.
@@ -10054,7 +10101,7 @@ exports.ObjectId = require('./objectid');
 
 exports.Subdocument = require('./subdocument');
 
-},{"./array":38,"./buffer":39,"./documentarray":40,"./embedded":41,"./objectid":43,"./subdocument":44}],43:[function(require,module,exports){
+},{"./array":39,"./buffer":40,"./documentarray":41,"./embedded":42,"./objectid":44,"./subdocument":45}],44:[function(require,module,exports){
 /**
  * ObjectId type constructor
  *
@@ -10069,7 +10116,7 @@ var ObjectId = require('../drivers').ObjectId;
 
 module.exports = ObjectId;
 
-},{"../drivers":11}],44:[function(require,module,exports){
+},{"../drivers":11}],45:[function(require,module,exports){
 var Document = require('../document');
 var PromiseProvider = require('../promise_provider');
 
@@ -10158,7 +10205,7 @@ Subdocument.prototype.ownerDocument = function() {
   return this.$__.ownerDocument = parent;
 };
 
-},{"../document":5,"../promise_provider":23}],45:[function(require,module,exports){
+},{"../document":5,"../promise_provider":23}],46:[function(require,module,exports){
 (function (process,Buffer){
 /*!
  * Module dependencies.
@@ -10959,7 +11006,7 @@ exports.each = function(arr, fn) {
 };
 
 }).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"./document":5,"./types":42,"./types/objectid":43,"FWaASH":55,"buffer":49,"mpath":78,"ms":91,"regexp-clone":92,"sliced":93}],46:[function(require,module,exports){
+},{"./document":5,"./types":43,"./types/objectid":44,"FWaASH":56,"buffer":50,"mpath":79,"ms":92,"regexp-clone":93,"sliced":94}],47:[function(require,module,exports){
 
 /**
  * VirtualType constructor
@@ -11064,7 +11111,7 @@ VirtualType.prototype.applySetters = function(value, scope) {
 
 module.exports = VirtualType;
 
-},{}],47:[function(require,module,exports){
+},{}],48:[function(require,module,exports){
 (function (process){
 /*!
  * async
@@ -12191,7 +12238,7 @@ module.exports = VirtualType;
 }());
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":55}],48:[function(require,module,exports){
+},{"FWaASH":56}],49:[function(require,module,exports){
 // http://wiki.commonjs.org/wiki/Unit_Testing/1.0
 //
 // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
@@ -12553,7 +12600,7 @@ var objectKeys = Object.keys || function (obj) {
   return keys;
 };
 
-},{"util/":57}],49:[function(require,module,exports){
+},{"util/":58}],50:[function(require,module,exports){
 /*!
  * The buffer module from node.js, for the browser.
  *
@@ -13607,7 +13654,7 @@ function decodeUtf8Char (str) {
   }
 }
 
-},{"base64-js":50,"ieee754":51,"is-array":52}],50:[function(require,module,exports){
+},{"base64-js":51,"ieee754":52,"is-array":53}],51:[function(require,module,exports){
 var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 
 ;(function (exports) {
@@ -13729,7 +13776,7 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 	exports.fromByteArray = uint8ToBase64
 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
 
-},{}],51:[function(require,module,exports){
+},{}],52:[function(require,module,exports){
 exports.read = function (buffer, offset, isLE, mLen, nBytes) {
   var e, m
   var eLen = nBytes * 8 - mLen - 1
@@ -13815,7 +13862,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
   buffer[offset + i - d] |= s * 128
 }
 
-},{}],52:[function(require,module,exports){
+},{}],53:[function(require,module,exports){
 
 /**
  * isArray
@@ -13850,7 +13897,7 @@ module.exports = isArray || function (val) {
   return !! val && '[object Array]' == str.call(val);
 };
 
-},{}],53:[function(require,module,exports){
+},{}],54:[function(require,module,exports){
 // Copyright Joyent, Inc. and other Node contributors.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
@@ -14153,7 +14200,7 @@ function isUndefined(arg) {
   return arg === void 0;
 }
 
-},{}],54:[function(require,module,exports){
+},{}],55:[function(require,module,exports){
 if (typeof Object.create === 'function') {
   // implementation from standard node.js 'util' module
   module.exports = function inherits(ctor, superCtor) {
@@ -14178,7 +14225,7 @@ if (typeof Object.create === 'function') {
   }
 }
 
-},{}],55:[function(require,module,exports){
+},{}],56:[function(require,module,exports){
 // shim for using process in browser
 
 var process = module.exports = {};
@@ -14243,14 +14290,14 @@ process.chdir = function (dir) {
     throw new Error('process.chdir is not supported');
 };
 
-},{}],56:[function(require,module,exports){
+},{}],57:[function(require,module,exports){
 module.exports = function isBuffer(arg) {
   return arg && typeof arg === 'object'
     && typeof arg.copy === 'function'
     && typeof arg.fill === 'function'
     && typeof arg.readUInt8 === 'function';
 }
-},{}],57:[function(require,module,exports){
+},{}],58:[function(require,module,exports){
 (function (process,global){
 // Copyright Joyent, Inc. and other Node contributors.
 //
@@ -14840,7 +14887,7 @@ function hasOwnProperty(obj, prop) {
 }
 
 }).call(this,require("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./support/isBuffer":56,"FWaASH":55,"inherits":54}],58:[function(require,module,exports){
+},{"./support/isBuffer":57,"FWaASH":56,"inherits":55}],59:[function(require,module,exports){
 /**
  * Module dependencies.
  * @ignore
@@ -15186,7 +15233,7 @@ Binary.SUBTYPE_USER_DEFINED = 128;
 module.exports = Binary;
 module.exports.Binary = Binary;
 
-},{"buffer":49}],59:[function(require,module,exports){
+},{"buffer":50}],60:[function(require,module,exports){
 (function (process){
 /**
  * Binary Parser.
@@ -15575,7 +15622,7 @@ BinaryParser.Buffer = BinaryParserBuffer;
 exports.BinaryParser = BinaryParser;
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":55,"util":57}],60:[function(require,module,exports){
+},{"FWaASH":56,"util":58}],61:[function(require,module,exports){
 (function (Buffer){
 // "use strict"
 
@@ -15902,7 +15949,7 @@ module.exports.MaxKey = MaxKey;
 module.exports.BSONRegExp = BSONRegExp;
 
 }).call(this,require("buffer").Buffer)
-},{"./binary":58,"./code":61,"./db_ref":62,"./double":63,"./float_parser":64,"./long":65,"./map":66,"./max_key":67,"./min_key":68,"./objectid":69,"./parser/calculate_size":70,"./parser/deserializer":71,"./parser/serializer":72,"./regexp":73,"./symbol":74,"./timestamp":75,"buffer":49}],61:[function(require,module,exports){
+},{"./binary":59,"./code":62,"./db_ref":63,"./double":64,"./float_parser":65,"./long":66,"./map":67,"./max_key":68,"./min_key":69,"./objectid":70,"./parser/calculate_size":71,"./parser/deserializer":72,"./parser/serializer":73,"./regexp":74,"./symbol":75,"./timestamp":76,"buffer":50}],62:[function(require,module,exports){
 /**
  * A class representation of the BSON Code type.
  *
@@ -15927,7 +15974,7 @@ Code.prototype.toJSON = function() {
 
 module.exports = Code;
 module.exports.Code = Code;
-},{}],62:[function(require,module,exports){
+},{}],63:[function(require,module,exports){
 /**
  * A class representation of the BSON DBRef type.
  *
@@ -15960,7 +16007,7 @@ DBRef.prototype.toJSON = function() {
 
 module.exports = DBRef;
 module.exports.DBRef = DBRef;
-},{}],63:[function(require,module,exports){
+},{}],64:[function(require,module,exports){
 /**
  * A class representation of the BSON Double type.
  *
@@ -15994,7 +16041,7 @@ Double.prototype.toJSON = function() {
 
 module.exports = Double;
 module.exports.Double = Double;
-},{}],64:[function(require,module,exports){
+},{}],65:[function(require,module,exports){
 // Copyright (c) 2008, Fair Oaks Labs, Inc.
 // All rights reserved.
 // 
@@ -16116,7 +16163,7 @@ var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) {
 
 exports.readIEEE754 = readIEEE754;
 exports.writeIEEE754 = writeIEEE754;
-},{}],65:[function(require,module,exports){
+},{}],66:[function(require,module,exports){
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
@@ -16973,7 +17020,7 @@ Long.TWO_PWR_24_ = Long.fromInt(1 << 24);
  */
 module.exports = Long;
 module.exports.Long = Long;
-},{}],66:[function(require,module,exports){
+},{}],67:[function(require,module,exports){
 (function (global){
 "use strict"
 
@@ -17102,7 +17149,7 @@ if(typeof global.Map !== 'undefined') {
   module.exports.Map = Map;
 }
 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],67:[function(require,module,exports){
+},{}],68:[function(require,module,exports){
 /**
  * A class representation of the BSON MaxKey type.
  *
@@ -17117,7 +17164,7 @@ function MaxKey() {
 
 module.exports = MaxKey;
 module.exports.MaxKey = MaxKey;
-},{}],68:[function(require,module,exports){
+},{}],69:[function(require,module,exports){
 /**
  * A class representation of the BSON MinKey type.
  *
@@ -17132,7 +17179,7 @@ function MinKey() {
 
 module.exports = MinKey;
 module.exports.MinKey = MinKey;
-},{}],69:[function(require,module,exports){
+},{}],70:[function(require,module,exports){
 (function (process){
 /**
  * Module dependencies.
@@ -17414,7 +17461,7 @@ module.exports.ObjectID = ObjectID;
 module.exports.ObjectId = ObjectID;
 
 }).call(this,require("FWaASH"))
-},{"./binary_parser":59,"FWaASH":55}],70:[function(require,module,exports){
+},{"./binary_parser":60,"FWaASH":56}],71:[function(require,module,exports){
 (function (Buffer){
 "use strict"
 
@@ -17728,7 +17775,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 module.exports = calculateObjectSize;
 
 }).call(this,require("buffer").Buffer)
-},{"../binary":58,"../code":61,"../db_ref":62,"../double":63,"../float_parser":64,"../long":65,"../max_key":67,"../min_key":68,"../objectid":69,"../regexp":73,"../symbol":74,"../timestamp":75,"buffer":49}],71:[function(require,module,exports){
+},{"../binary":59,"../code":62,"../db_ref":63,"../double":64,"../float_parser":65,"../long":66,"../max_key":68,"../min_key":69,"../objectid":70,"../regexp":74,"../symbol":75,"../timestamp":76,"buffer":50}],72:[function(require,module,exports){
 "use strict"
 
 var writeIEEE754 = require('../float_parser').writeIEEE754,
@@ -18285,7 +18332,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 
 module.exports = deserialize
 
-},{"../binary":58,"../code":61,"../db_ref":62,"../double":63,"../float_parser":64,"../long":65,"../max_key":67,"../min_key":68,"../objectid":69,"../regexp":73,"../symbol":74,"../timestamp":75,"util":57}],72:[function(require,module,exports){
+},{"../binary":59,"../code":62,"../db_ref":63,"../double":64,"../float_parser":65,"../long":66,"../max_key":68,"../min_key":69,"../objectid":70,"../regexp":74,"../symbol":75,"../timestamp":76,"util":58}],73:[function(require,module,exports){
 (function (Buffer){
 "use strict"
 
@@ -19201,7 +19248,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 module.exports = serializeInto;
 
 }).call(this,require("buffer").Buffer)
-},{"../binary":58,"../code":61,"../db_ref":62,"../double":63,"../float_parser":64,"../long":65,"../map":66,"../max_key":67,"../min_key":68,"../objectid":69,"../regexp":73,"../symbol":74,"../timestamp":75,"buffer":49}],73:[function(require,module,exports){
+},{"../binary":59,"../code":62,"../db_ref":63,"../double":64,"../float_parser":65,"../long":66,"../map":67,"../max_key":68,"../min_key":69,"../objectid":70,"../regexp":74,"../symbol":75,"../timestamp":76,"buffer":50}],74:[function(require,module,exports){
 /**
  * A class representation of the BSON RegExp type.
  *
@@ -19232,7 +19279,7 @@ function BSONRegExp(pattern, options) {
 
 module.exports = BSONRegExp;
 module.exports.BSONRegExp = BSONRegExp;
-},{}],74:[function(require,module,exports){
+},{}],75:[function(require,module,exports){
 /**
  * A class representation of the BSON Symbol type.
  *
@@ -19280,7 +19327,7 @@ Symbol.prototype.toJSON = function() {
 
 module.exports = Symbol;
 module.exports.Symbol = Symbol;
-},{}],75:[function(require,module,exports){
+},{}],76:[function(require,module,exports){
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
@@ -20137,7 +20184,7 @@ Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24);
  */
 module.exports = Timestamp;
 module.exports.Timestamp = Timestamp;
-},{}],76:[function(require,module,exports){
+},{}],77:[function(require,module,exports){
 // TODO Add in pre and post skipping options
 module.exports = {
   /**
@@ -20330,7 +20377,7 @@ function once (fn, scope) {
   };
 }
 
-},{}],77:[function(require,module,exports){
+},{}],78:[function(require,module,exports){
 (function (process){
 'use strict';
 
@@ -20563,10 +20610,10 @@ Kareem.prototype.clone = function() {
 module.exports = Kareem;
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":55}],78:[function(require,module,exports){
+},{"FWaASH":56}],79:[function(require,module,exports){
 module.exports = exports = require('./lib');
 
-},{"./lib":79}],79:[function(require,module,exports){
+},{"./lib":80}],80:[function(require,module,exports){
 
 /**
  * Returns the value of object `o` at the given `path`.
@@ -20751,7 +20798,7 @@ function K (v) {
   return v;
 }
 
-},{}],80:[function(require,module,exports){
+},{}],81:[function(require,module,exports){
 (function (process){
 'use strict';
 var util = require('util');
@@ -21195,7 +21242,7 @@ Promise.deferred = function deferred() {
 
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":55,"events":53,"util":57}],81:[function(require,module,exports){
+},{"FWaASH":56,"events":54,"util":58}],82:[function(require,module,exports){
 'use strict';
 
 /**
@@ -21239,7 +21286,7 @@ function notImplemented (method) {
 }
 
 
-},{}],82:[function(require,module,exports){
+},{}],83:[function(require,module,exports){
 'use strict';
 
 var env = require('../env')
@@ -21254,7 +21301,7 @@ module.exports =
   require('./collection');
 
 
-},{"../env":84,"./collection":81,"./node":83}],83:[function(require,module,exports){
+},{"../env":85,"./collection":82,"./node":84}],84:[function(require,module,exports){
 'use strict';
 
 /**
@@ -21356,7 +21403,7 @@ NodeCollection.prototype.findStream = function(match, findOptions, streamOptions
 module.exports = exports = NodeCollection;
 
 
-},{"../utils":87,"./collection":81}],84:[function(require,module,exports){
+},{"../utils":88,"./collection":82}],85:[function(require,module,exports){
 (function (process,global,Buffer){
 'use strict';
 
@@ -21382,7 +21429,7 @@ exports.type = exports.isNode ? 'node'
   : 'unknown'
 
 }).call(this,require("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
-},{"FWaASH":55,"buffer":49}],85:[function(require,module,exports){
+},{"FWaASH":56,"buffer":50}],86:[function(require,module,exports){
 'use strict';
 
 /**
@@ -23996,7 +24043,7 @@ module.exports = exports = Query;
 // TODO
 // test utils
 
-},{"./collection":82,"./collection/collection":81,"./env":84,"./permissions":86,"./utils":87,"assert":48,"bluebird":88,"debug":89,"sliced":93,"util":57}],86:[function(require,module,exports){
+},{"./collection":83,"./collection/collection":82,"./env":85,"./permissions":87,"./utils":88,"assert":49,"bluebird":89,"debug":90,"sliced":94,"util":58}],87:[function(require,module,exports){
 'use strict';
 
 var denied = exports;
@@ -24088,7 +24135,7 @@ denied.count.maxScan =
 denied.count.snapshot =
 denied.count.tailable = true;
 
-},{}],87:[function(require,module,exports){
+},{}],88:[function(require,module,exports){
 (function (process,Buffer){
 'use strict';
 
@@ -24423,7 +24470,7 @@ exports.cloneBuffer = function (buff) {
 };
 
 }).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"FWaASH":55,"buffer":49,"regexp-clone":92}],88:[function(require,module,exports){
+},{"FWaASH":56,"buffer":50,"regexp-clone":93}],89:[function(require,module,exports){
 (function (process,global){
 /* @preserve
  * The MIT License (MIT)
@@ -29531,7 +29578,7 @@ function isUndefined(arg) {
 },{}]},{},[4])(4)
 });                    ;if (typeof window !== 'undefined' && window !== null) {                               window.P = window.Promise;                                                     } else if (typeof self !== 'undefined' && self !== null) {                             self.P = self.Promise;                                                         }
 }).call(this,require("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"FWaASH":55}],89:[function(require,module,exports){
+},{"FWaASH":56}],90:[function(require,module,exports){
 
 /**
  * This is the web browser implementation of `debug()`.
@@ -29701,7 +29748,7 @@ function localstorage(){
   } catch (e) {}
 }
 
-},{"./debug":90}],90:[function(require,module,exports){
+},{"./debug":91}],91:[function(require,module,exports){
 
 /**
  * This is the common logic for both the Node.js and web browser
@@ -29900,7 +29947,7 @@ function coerce(val) {
   return val;
 }
 
-},{"ms":91}],91:[function(require,module,exports){
+},{"ms":92}],92:[function(require,module,exports){
 /**
  * Helpers.
  */
@@ -30027,7 +30074,7 @@ function plural(ms, n, name) {
   return Math.ceil(ms / n) + ' ' + name + 's';
 }
 
-},{}],92:[function(require,module,exports){
+},{}],93:[function(require,module,exports){
 
 var toString = Object.prototype.toString;
 
@@ -30049,10 +30096,10 @@ module.exports = exports = function (regexp) {
 }
 
 
-},{}],93:[function(require,module,exports){
+},{}],94:[function(require,module,exports){
 module.exports = exports = require('./lib/sliced');
 
-},{"./lib/sliced":94}],94:[function(require,module,exports){
+},{"./lib/sliced":95}],95:[function(require,module,exports){
 
 /**
  * An Array.prototype.slice.call(arguments) alternative
diff --git a/package.json b/package.json
index e1897ad438e..4f84b5dd0a2 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.1-pre",
+  "version": "4.3.1",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From 52de96af55d0abdd2c33a195b7422517682c6cdf Mon Sep 17 00:00:00 2001
From: Doug Molineux 
Date: Fri, 11 Dec 2015 13:29:54 -0700
Subject: [PATCH 0120/2240] #3628 Took out some catches and added some more
 tests

---
 test/model.mapreduce.test.js | 220 ++++++++++++++++++++++++++---------
 1 file changed, 167 insertions(+), 53 deletions(-)

diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 27c82e05d14..fb26b5939e7 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -45,7 +45,7 @@ var collection = 'mapreduce_' + random();
 mongoose.model('MapReduce', BlogPost);
 
 describe('model: mapreduce:', function() {
-  it('works', function(done) {
+  it('works', function(done){
     var db = start()
       , MR = db.model('MapReduce', collection);
 
@@ -54,24 +54,26 @@ describe('model: mapreduce:', function() {
     var authors = 'aaron guillermo brian nathan'.split(' ');
     var num = 10;
     var docs = [];
-    for (var i = 0; i < num; ++i)
-      docs.push({ author: authors[i % authors.length], owners: [id], published: true });
+    for (var i = 0; i< num; ++i)
+      docs.push({ author: authors[i%authors.length], owners: [id], published: true });
 
-    MR.create(docs, function(err, insertedDocs) {
+    MR.create(docs, function (err, insertedDocs) {
       assert.ifError(err);
 
+      var a = insertedDocs[0];
       var b = insertedDocs[1];
       magicID = b._id;
 
       var o = {
-        map: function() { emit(this.author, 1); }
-        , reduce: function(k, vals) { return vals.length; }
-      };
+          map: function () { emit(this.author, 1) }
+        , reduce: function (k, vals) { return vals.length }
+      }
 
-      MR.mapReduce(o).then(function(ret, stats) {
+      MR.mapReduce(o, function (err, ret, stats) {
+        assert.ifError(err);
         assert.ok(Array.isArray(ret));
         assert.ok(stats);
-        ret.forEach(function(res) {
+        ret.forEach(function (res) {
           if ('aaron' == res._id) assert.equal(3, res.value);
           if ('guillermo' == res._id) assert.equal(3, res.value);
           if ('brian' == res._id) assert.equal(2, res.value);
@@ -79,33 +81,34 @@ describe('model: mapreduce:', function() {
         });
 
         var o = {
-          map: function() { emit(this.author, 1); }
-          , reduce: function(k, vals) { return vals.length; }
+            map: function () { emit(this.author, 1) }
+          , reduce: function (k, vals) { return vals.length }
           , query: { author: 'aaron', published: 1, owners: id }
-        };
+        }
+
+        MR.mapReduce(o, function (err, ret, stats) {
+          assert.ifError(err);
 
-        MR.mapReduce(o).then(function(ret, stats) {
           assert.ok(Array.isArray(ret));
           assert.equal(1, ret.length);
           assert.equal('aaron', ret[0]._id);
           assert.equal(3, ret[0].value);
           assert.ok(stats);
+
           modeling();
-        }).catch(function(err) {
-          assert.ifError(err);
         });
-
       });
 
-      function modeling() {
+      function modeling () {
         var o = {
-          map: function() { emit(this.author, { own: magicID }); }
+            map: function () { emit(this.author, { own: magicID }) }
           , scope: { magicID: magicID }
-          , reduce: function(k, vals) { return { own: vals[0].own, count: vals.length };}
+          , reduce: function (k, vals) { return { own: vals[0].own, count: vals.length }}
           , out: { replace: '_mapreduce_test_' + random() }
-        };
+        }
 
-        MR.mapReduce(o).then(function(ret) {
+        MR.mapReduce(o, function (err, ret, stats) {
+          assert.ifError(err);
 
           // ret is a model
           assert.ok(!Array.isArray(ret));
@@ -113,7 +116,7 @@ describe('model: mapreduce:', function() {
           assert.equal('function', typeof ret.mapReduce);
 
           // queries work
-          ret.where('value.count').gt(1).sort({_id: 1}).exec(function(err, docs) {
+          ret.where('value.count').gt(1).sort({_id: 1}).exec(function (err, docs) {
             assert.ifError(err);
             assert.equal('aaron', docs[0]._id);
             assert.equal('brian', docs[1]._id);
@@ -121,7 +124,7 @@ describe('model: mapreduce:', function() {
             assert.equal('nathan', docs[3]._id);
 
             // update casting works
-            ret.findOneAndUpdate({ _id: 'aaron' }, { published: true }, { 'new': true }, function(err, doc) {
+            ret.findOneAndUpdate({ _id: 'aaron' }, { published: true }, { 'new': true }, function (err, doc) {
               assert.ifError(err);
               assert.ok(doc);
               assert.equal('aaron', doc._id);
@@ -131,85 +134,196 @@ describe('model: mapreduce:', function() {
               ret
               .findOne({ _id: 'aaron' })
               .populate({ path: 'value.own', model: 'MapReduce' })
-              .exec(function(err, doc) {
+              .exec(function (err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal('guillermo', doc.value.own.author);
                 done();
-              });
+              })
             });
           });
-        }).catch(function(err) {
-          assert.ifError(err);
-          done();
         });
       }
     });
-  });
+  })
 
-  it('withholds stats with false verbosity', function(done) {
+  it('withholds stats with false verbosity', function(done){
     var db = start()
-      , MR = db.model('MapReduce', collection);
+      , MR = db.model('MapReduce', collection)
 
     var o = {
-      map: function() {}
-      , reduce: function() { return 'test'; }
+        map: function () {}
+      , reduce: function () { return 'test' }
       , verbose: false
-    };
+    }
 
-    MR.mapReduce(o).then(function(results, stats) {
+    MR.mapReduce(o, function (err, results, stats){
       assert.equal('undefined', typeof stats);
       db.close(done);
     });
-
   });
 
-  describe('promises (gh-1628)', function() {
-    it('are returned', function(done) {
+  describe('promises (gh-1628)', function () {
+    it('are returned', function(done){
       var db = start()
-        , MR = db.model('MapReduce', collection);
+        , MR = db.model('MapReduce', collection)
 
       var o = {
-        map: function() {}
-        , reduce: function() { return 'test'; }
-      };
+          map: function () {}
+        , reduce: function () { return 'test' }
+      }
 
-      var promise = MR.mapReduce(o, function() {});
+      var promise = MR.mapReduce(o, function(){});
       assert.ok(promise instanceof mongoose.Promise);
 
       db.close(done);
     });
 
-    it('allow not passing a callback', function(done) {
+    it('allow not passing a callback', function(done){
       var db = start()
-        , MR = db.model('MapReduce', collection);
+        , MR = db.model('MapReduce', collection)
 
       var o = {
-        map: function() { emit(this.author, 1); }
-        , reduce: function(k, vals) { return vals.length; }
+          map: function () { emit(this.author, 1) }
+        , reduce: function (k, vals) { return vals.length }
         , query: { author: 'aaron', published: 1 }
-      };
+      }
 
-      function validate(ret, stats) {
+      function validate (ret, stats) {
         assert.ok(Array.isArray(ret));
         assert.equal(1, ret.length);
         assert.equal('aaron', ret[0]._id);
-        assert.equal(3, ret[0].value);
+        assert.equal(6, ret[0].value);
         assert.ok(stats);
       }
 
-      function finish() {
+      function finish () {
         db.close(done);
       }
 
       var promise;
 
-      assert.doesNotThrow(function() {
+      assert.doesNotThrow(function(){
         promise = MR.mapReduce(o);
-      });
+      })
 
       promise.then(validate, assert.ifError).then(finish).end();
+    })
+
+  });
+
+  it('works using then', function(done) {
+    var db = start()
+      , MR = db.model('MapReduce', collection);
+
+    var magicID;
+    var id = new mongoose.Types.ObjectId;
+    var authors = 'aaron guillermo brian nathan'.split(' ');
+    var num = 10;
+    var docs = [];
+    for (var i = 0; i < num; ++i)
+      docs.push({ author: authors[i % authors.length], owners: [id], published: true });
+
+    MR.create(docs, function(err, insertedDocs) {
+      assert.ifError(err);
+
+      var b = insertedDocs[1];
+      magicID = b._id;
+
+      var o = {
+        map: function() { emit(this.author, 1); }
+        , reduce: function(k, vals) { return vals.length; }
+      };
+
+      MR.mapReduce(o).then(function(ret, stats) {
+        assert.ok(Array.isArray(ret));
+        assert.ok(stats);
+        ret.forEach(function(res) {
+          if ('aaron' == res._id) assert.equal(6, res.value);
+          if ('guillermo' == res._id) assert.equal(6, res.value);
+          if ('brian' == res._id) assert.equal(4, res.value);
+          if ('nathan' == res._id) assert.equal(4, res.value);
+        });
+
+        var o = {
+          map: function() { emit(this.author, 1); }
+          , reduce: function(k, vals) { return vals.length; }
+          , query: { author: 'aaron', published: 1, owners: id }
+        };
+
+        MR.mapReduce(o).then(function(ret, stats) {
+          assert.ok(Array.isArray(ret));
+          assert.equal(1, ret.length);
+          assert.equal('aaron', ret[0]._id);
+          assert.equal(3, ret[0].value);
+          assert.ok(stats);
+          modeling();
+        });
+
+      });
+
+      function modeling() {
+        var o = {
+          map: function() { emit(this.author, { own: magicID }); }
+          , scope: { magicID: magicID }
+          , reduce: function(k, vals) { return { own: vals[0].own, count: vals.length };}
+          , out: { replace: '_mapreduce_test_' + random() }
+        };
+
+        MR.mapReduce(o).then(function(ret) {
+
+          // ret is a model
+          assert.ok(!Array.isArray(ret));
+          assert.equal('function', typeof ret.findOne);
+          assert.equal('function', typeof ret.mapReduce);
+
+          // queries work
+          ret.where('value.count').gt(1).sort({_id: 1}).exec(function(err, docs) {
+            assert.ifError(err);
+            assert.equal('aaron', docs[0]._id);
+            assert.equal('brian', docs[1]._id);
+            assert.equal('guillermo', docs[2]._id);
+            assert.equal('nathan', docs[3]._id);
+
+            // update casting works
+            ret.findOneAndUpdate({ _id: 'aaron' }, { published: true }, { 'new': true }, function(err, doc) {
+              assert.ifError(err);
+              assert.ok(doc);
+              assert.equal('aaron', doc._id);
+              assert.equal(true, doc.published);
+
+              // ad-hoc population works
+              ret
+              .findOne({ _id: 'aaron' })
+              .populate({ path: 'value.own', model: 'MapReduce' })
+              .exec(function(err, doc) {
+                db.close();
+                assert.ifError(err);
+                assert.equal('guillermo', doc.value.own.author);
+                done();
+              });
+            });
+          });
+        })
+      }
+    });
+  });
+
+  it('withholds stats with false verbosity using then', function(done) {
+    var db = start()
+      , MR = db.model('MapReduce', collection);
+
+    var o = {
+      map: function() {}
+      , reduce: function() { return 'test'; }
+      , verbose: false
+    };
+
+    MR.mapReduce(o).then(function(results, stats) {
+      assert.equal('undefined', typeof stats);
+      db.close(done);
     });
 
   });
+
 });

From 9d94b18d3e9e2ced280e66076d18e016361c593b Mon Sep 17 00:00:00 2001
From: Doug Molineux 
Date: Fri, 11 Dec 2015 13:44:25 -0700
Subject: [PATCH 0121/2240] #3628 Adding the callback function back into the
 doc

---
 lib/model.js | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/lib/model.js b/lib/model.js
index 98f9ae441ea..7080dd2ab5b 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -1938,6 +1938,13 @@ Model.update = function update(conditions, doc, options, callback) {
  *     o.out = { replace: 'createdCollectionNameForResults' }
  *     o.verbose = true;
  *
+ *     User.mapReduce(o, function (err, model, stats) {
+ *       console.log('map reduce took %d ms', stats.processtime)
+ *       model.find().where('value').gt(10).exec(function (err, docs) {
+ *         console.log(docs);
+ *       });
+ *     })
+ *
  *     // a promise is returned so you may instead write
  *     var promise = User.mapReduce(o);
  *     promise.then(function (model, stats) {

From 9d98b3244e8ec876bc3fe154ac2fa2f1f84893d4 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 11 Dec 2015 15:45:33 -0500
Subject: [PATCH 0122/2240] now working on 4.3.2

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 4f84b5dd0a2..551d4d9b3e0 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.1",
+  "version": "4.3.2-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From da490a3a7cf4016c330c8160b3307a1a57e34d68 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 11 Dec 2015 15:47:54 -0500
Subject: [PATCH 0123/2240] docs(query): fix stale maxScan link

---
 lib/query.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/query.js b/lib/query.js
index b57a3ceab91..6032b64fd96 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -847,7 +847,7 @@ Query.prototype.read = function read(pref, tags) {
  * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D) *
  * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D) *
  * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D) *
- * - [maxscan](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan) *
+ * - [maxscan](https://docs.mongodb.org/v3.2/reference/operator/meta/maxScan/#metaOp._S_maxScan) *
  * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D) *
  * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment) *
  * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D) *

From 104a1255fd5178d3290cc9495e00d9fc01a9fc00 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sat, 12 Dec 2015 10:30:11 -0500
Subject: [PATCH 0124/2240] Remove unused file

---
 contRun.sh | 10 ----------
 1 file changed, 10 deletions(-)
 delete mode 100755 contRun.sh

diff --git a/contRun.sh b/contRun.sh
deleted file mode 100755
index cd5610d9bd3..00000000000
--- a/contRun.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-make test
-
-ret=$?
-
-while [ $ret == 0 ]; do
-  make test
-  ret=$?
-done

From 72f6eb6debf25ae9219fb09c36ce7143a7a18b3f Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sat, 12 Dec 2015 13:59:03 -0500
Subject: [PATCH 0125/2240] fix: strict throw throws a mongoose error (Fix
 #3662)

---
 lib/document.js     |  5 +++--
 lib/error/strict.js | 35 +++++++++++++++++++++++++++++++++++
 lib/query.js        |  7 ++++---
 3 files changed, 42 insertions(+), 5 deletions(-)
 create mode 100644 lib/error/strict.js

diff --git a/lib/document.js b/lib/document.js
index dc1045ac1b9..f6e92286d21 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -8,6 +8,7 @@ var EventEmitter = require('events').EventEmitter,
     MongooseError = require('./error'),
     MixedSchema = require('./schema/mixed'),
     Schema = require('./schema'),
+    StrictModeError = require('./error/strict'),
     ValidatorError = require('./schematype').ValidatorError,
     utils = require('./utils'),
     clone = utils.clone,
@@ -514,7 +515,7 @@ Document.prototype.set = function(path, val, type, options) {
             this.set(prefix + key,
               path[key].toObject({ virtuals: false }), constructing);
           } else if ('throw' == strict) {
-            throw new Error('Field `' + key + '` is not in schema.');
+            throw new StrictModeError(key);
           }
         } else if (undefined !== path[key]) {
           this.set(prefix + key, path[key], constructing);
@@ -560,7 +561,7 @@ Document.prototype.set = function(path, val, type, options) {
 
     if (!mixed) {
       if ('throw' == strict) {
-        throw new Error("Field `" + path + "` is not in schema.");
+        throw new StrictModeError(path);
       }
       return this;
     }
diff --git a/lib/error/strict.js b/lib/error/strict.js
new file mode 100644
index 00000000000..6e3443135a9
--- /dev/null
+++ b/lib/error/strict.js
@@ -0,0 +1,35 @@
+/*!
+ * Module dependencies.
+ */
+
+var MongooseError = require('../error.js');
+
+/**
+ * Strict mode error constructor
+ *
+ * @param {String} type
+ * @param {String} value
+ * @inherits MongooseError
+ * @api private
+ */
+
+function StrictModeError(path) {
+  MongooseError.call(this, 'Field `' + path + '` is not in schema and strict ' +
+    'mode is set to throw.');
+  if (Error.captureStackTrace) {
+    Error.captureStackTrace(this);
+  } else {
+    this.stack = new Error().stack;
+  }
+  this.name = 'StrictModeError';
+  this.path = path;
+}
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+StrictModeError.prototype = Object.create(MongooseError.prototype);
+StrictModeError.prototype.constructor = MongooseError;
+
+module.exports = StrictModeError;
diff --git a/lib/query.js b/lib/query.js
index 6032b64fd96..730f432a825 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -13,6 +13,7 @@ var utils = require('./utils');
 var helpers = require('./queryhelpers');
 var Document = require('./document');
 var QueryStream = require('./querystream');
+var StrictModeError = require('./error/strict');
 var cast = require('./cast');
 
 /**
@@ -2342,7 +2343,7 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) {
             this.model.schema.pathType(positionalPath) === 'adhocOrUndefined' &&
             !this.model.schema.hasMixedParent(positionalPath)) {
           if (strict === 'throw') {
-            throw new Error('Field `' + pathToCheck + '` is not in schema.');
+            throw new StrictModeError(pathToCheck);
           } else if (strict) {
             delete obj[key];
             continue;
@@ -2365,8 +2366,8 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) {
                  !/real|nested/.test(this.model.schema.pathType(prefix + key));
 
       if (skip) {
-        if ('throw' == strict) {
-          throw new Error('Field `' + prefix + key + '` is not in schema.');
+        if (strict === 'throw') {
+          throw new StrictModeError(prefix + key);
         } else {
           delete obj[key];
         }

From 119f98a62498f77fe5bb702186d04971eb800d2e Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sat, 12 Dec 2015 14:01:55 -0500
Subject: [PATCH 0126/2240] now working on 4.4.0

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 551d4d9b3e0..ee764407dd8 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.2-pre",
+  "version": "4.4.0-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From 175057e949d7a91f319b5c6f069aad1a35a1a655 Mon Sep 17 00:00:00 2001
From: Chris Zieba 
Date: Sat, 12 Dec 2015 12:38:31 -0800
Subject: [PATCH 0127/2240] Update keepAlive info

The current docs make it seem like this is a Boolean. According to the [native driver](https://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html), the keepAlive is a number of seconds.
---
 docs/connections.jade | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/connections.jade b/docs/connections.jade
index ee1984488ee..512b47c086a 100644
--- a/docs/connections.jade
+++ b/docs/connections.jade
@@ -56,10 +56,10 @@ block content
   h4#keepAlive A note about keepAlive
   .important
     :markdown
-      For long running applictions it is often prudent to enable `keepAlive`. Without it, after some period of time you may start to see `"connection closed"` errors for what seems like no reason. If so, after [reading this](http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html), you may decide to enable `keepAlive`:
+      For long running applictions it is often prudent to enable `keepAlive` with a number of seconds. Without it, after some period of time you may start to see `"connection closed"` errors for what seems like no reason. If so, after [reading this](http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html), you may decide to enable `keepAlive`:
 
   :js
-    options.server.socketOptions = options.replset.socketOptions = { keepAlive: 1 };
+    options.server.socketOptions = options.replset.socketOptions = { keepAlive: 120 };
     mongoose.connect(uri, options);
 
   h3#replicaset_connections ReplicaSet Connections

From effe2a0a540542edd4697c3f897da771cfc8f725 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sun, 13 Dec 2015 14:26:59 -0500
Subject: [PATCH 0128/2240] docs: keepAlive docs clarification re #3667

---
 docs/connections.jade | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/docs/connections.jade b/docs/connections.jade
index 512b47c086a..1ba6b01580d 100644
--- a/docs/connections.jade
+++ b/docs/connections.jade
@@ -56,7 +56,12 @@ block content
   h4#keepAlive A note about keepAlive
   .important
     :markdown
-      For long running applictions it is often prudent to enable `keepAlive` with a number of seconds. Without it, after some period of time you may start to see `"connection closed"` errors for what seems like no reason. If so, after [reading this](http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html), you may decide to enable `keepAlive`:
+      For long running applictions it is often prudent to enable `keepAlive`
+      with a number of milliseconds. Without it, after some period of time
+      you may start to see `"connection closed"` errors for what seems like
+      no reason. If so, after
+      [reading this](http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html),
+      you may decide to enable `keepAlive`:
 
   :js
     options.server.socketOptions = options.replset.socketOptions = { keepAlive: 120 };

From 45b6818b278fb3e8aa97260f473871810b53b9bc Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 14 Dec 2015 12:07:40 -0500
Subject: [PATCH 0129/2240] fix(query): more robust check for regexp (Fix
 #2969)

---
 lib/schema/string.js | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/lib/schema/string.js b/lib/schema/string.js
index 799fcc5808d..1d9b609b743 100644
--- a/lib/schema/string.js
+++ b/lib/schema/string.js
@@ -3,11 +3,12 @@
  * Module dependencies.
  */
 
-var SchemaType = require('../schematype'),
-    CastError = SchemaType.CastError,
-    errorMessages = require('../error').messages,
-    utils = require('../utils'),
-    Document;
+var SchemaType = require('../schematype');
+var CastError = SchemaType.CastError;
+var errorMessages = require('../error').messages;
+var utils = require('../utils');
+var Document;
+var type = require('type-component');
 
 /**
  * String SchemaType constructor.
@@ -480,7 +481,9 @@ SchemaString.prototype.castForQuery = function($conditional, val) {
     return handler.call(this, val);
   } else {
     val = $conditional;
-    if (val instanceof RegExp) return val;
+    if (Object.prototype.toString.call(val) === '[object RegExp]') {
+      return val;
+    }
     return this.cast(val);
   }
 };

From 9ccdc69de11e664578dc632fa11c0ab299b7b4ba Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 14 Dec 2015 12:34:17 -0500
Subject: [PATCH 0130/2240] fix: flakey test (Fix #3332)

---
 test/document.hooks.test.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index d453f043534..63cadb104b2 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -529,7 +529,7 @@ describe('document: hooks:', function() {
 
       try {
         assert.equal(err.message, "gaga");
-        assert.equal(count, 4);
+        assert.ok(count >= 3);
         done();
       } catch (e) {
         done(e);

From f422e9a85bd76123c67c241aff955371d0f2e5e8 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 14 Dec 2015 12:36:11 -0500
Subject: [PATCH 0131/2240] docs: clarification re: #3672

---
 docs/middleware.jade | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/middleware.jade b/docs/middleware.jade
index 1f1faa9bd6d..9b13867b268 100644
--- a/docs/middleware.jade
+++ b/docs/middleware.jade
@@ -74,10 +74,12 @@ block content
           li notifications
   h4#error-handling Error handling
   :markdown
-    If any middleware calls `next` or `done` with an error, the flow
-    is interrupted, and the error is passed to the callback.
+    If any middleware calls `next` or `done` with a parameter of type `Error`,
+    the flow is interrupted, and the error is passed to the callback.
   :js
     schema.pre('save', function(next) {
+      // You **must** do `new Error()`. `next('something went wrong')` will
+      // **not** work
       var err = new Error('something went wrong');
       next(err);
     });

From dcc75c86ba377a517fbace8f8dfb5a09a2ab7f5c Mon Sep 17 00:00:00 2001
From: Vivek Gounder 
Date: Tue, 15 Dec 2015 13:58:14 +0530
Subject: [PATCH 0132/2240] fix; remove unused npm library (Fix #3673)

This was breaking make test on a fresh clone of the repo
---
 lib/schema/string.js | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/schema/string.js b/lib/schema/string.js
index 1d9b609b743..33210dbbdc4 100644
--- a/lib/schema/string.js
+++ b/lib/schema/string.js
@@ -8,7 +8,6 @@ var CastError = SchemaType.CastError;
 var errorMessages = require('../error').messages;
 var utils = require('../utils');
 var Document;
-var type = require('type-component');
 
 /**
  * String SchemaType constructor.

From 13b3816142c6a199433f01f0dda1c886a739e847 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 15 Dec 2015 13:19:20 -0500
Subject: [PATCH 0133/2240] fix(schema): dont use promises in defaultMiddleware
 (Fix #3671)

---
 lib/schema.js | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/lib/schema.js b/lib/schema.js
index 9b9f2f0abae..1ba5843c118 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -252,26 +252,22 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
         return;
       }
 
-      new Promise.ES6(function(resolve, reject) {
-        async.each(subdocs, function(subdoc, cb) {
-          subdoc.$__preSavingFromParent = true;
-          subdoc.save(function(err) {
-            cb(err);
-          });
-        }, function(error) {
-          for (var i = 0; i < subdocs.length; ++i) {
-            delete subdocs[i].$__preSavingFromParent;
-          }
-          if (error) {
-            reject(error);
-            return;
-          }
-          resolve();
+      async.each(subdocs, function(subdoc, cb) {
+        subdoc.$__preSavingFromParent = true;
+        subdoc.save(function(err) {
+          cb(err);
         });
-      }).then(function() {
+      }, function(error) {
+        for (var i = 0; i < subdocs.length; ++i) {
+          delete subdocs[i].$__preSavingFromParent;
+        }
+        if (error) {
+          done(error);
+          return;
+        }
         next();
         done();
-      }, done);
+      });
     }
   }]
 });

From 97001475feb5afb23e3adfdcb817a1dce3a0f663 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 16 Dec 2015 13:47:18 -0500
Subject: [PATCH 0134/2240] test: repro #3679

---
 test/document.test.js | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/test/document.test.js b/test/document.test.js
index 669072de4d8..3fff7aadb59 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -2176,6 +2176,28 @@ describe('document', function() {
     });
   });
 
+  it('single embedded docs post hooks (gh-3679)', function(done) {
+    var db = start();
+    var postHookCalls = [];
+    var personSchema = new Schema({ name: String });
+    personSchema.post('save', function() {
+      postHookCalls.push(this);
+    });
+
+    var bandSchema = new Schema({ guitarist: personSchema, name: String });
+    var Band = db.model('gh3679', bandSchema);
+    var obj = { name: "Guns N' Roses", guitarist: { name: 'Slash' } };
+
+    Band.create(obj, function(error) {
+      assert.ifError(error);
+      setTimeout(function() {
+        assert.equal(postHookCalls.length, 1);
+        assert.equal(postHookCalls[0].name, 'Slash');
+        db.close(done);
+      });
+    });
+  });
+
   it('handles virtuals with dots correctly (gh-3618)', function(done) {
     var db = start();
     var testSchema = new Schema({ nested: { type: Object, default: {} } });

From b60759e7474b499aeccd07bf9827af178b16004f Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 16 Dec 2015 13:54:07 -0500
Subject: [PATCH 0135/2240] fix(schematype): single nested subscribes to parent
 save (Fix #3679)

---
 lib/schema/embedded.js | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js
index 9c32484148e..bd42df74f9a 100644
--- a/lib/schema/embedded.js
+++ b/lib/schema/embedded.js
@@ -14,8 +14,15 @@ module.exports = Embedded;
  */
 
 function Embedded(schema, path, options) {
-  var _embedded = function() {
+  var _embedded = function(value, path, parent) {
+    var _this = this;
     Subdocument.apply(this, arguments);
+    this.$parent = parent;
+    if (parent) {
+      parent.on('save', function() {
+        _this.emit('save', _this);
+      });
+    }
   };
   _embedded.prototype = Object.create(Subdocument.prototype);
   _embedded.prototype.$__setSchema(schema);
@@ -52,8 +59,7 @@ Embedded.prototype.cast = function(val, doc, init) {
   if (val && val.$isSingleNested) {
     return val;
   }
-  var subdoc = new this.caster();
-  subdoc.$parent = doc;
+  var subdoc = new this.caster(undefined, undefined, doc);
   if (init) {
     subdoc.init(val);
   } else {

From 0e4ed94d72555eff0259f8e46748ae904c6da489 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 16 Dec 2015 14:06:22 -0500
Subject: [PATCH 0136/2240] test: repro #3681

---
 test/promise_provider.test.js | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js
index eb15958bfae..57303a63033 100644
--- a/test/promise_provider.test.js
+++ b/test/promise_provider.test.js
@@ -315,6 +315,16 @@ describe('ES6 promises: ', function() {
         });
       });
     });
+
+    it('subdocument validation (gh-3681)', function(done) {
+      var subSchema = new Schema({ name: { type: String, required: true } });
+      var parentSchema = new Schema({ sub: [subSchema] });
+      var Parent = db.model('gh3681', parentSchema);
+
+      Parent.create({ sub: [{}] }).catch(function() {
+        done();
+      });
+    });
   });
 
   describe('q: ', function() {

From 1c872b3d60b4014a6fa752bf763a4245718b29b1 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 16 Dec 2015 14:09:43 -0500
Subject: [PATCH 0137/2240] fix: unhandled rejection in documentarray (Fix
 #3681)

---
 lib/schema/documentarray.js | 2 +-
 test/document.hooks.test.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js
index d51b6de5244..34c31c128f6 100644
--- a/lib/schema/documentarray.js
+++ b/lib/schema/documentarray.js
@@ -97,7 +97,7 @@ DocumentArray.prototype.doValidate = function(array, fn, scope) {
         continue;
       }
 
-      doc.validate(function(err) {
+      doc.validate({ __noPromise: true }, function(err) {
         if (err) {
           error = err;
         }
diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index 63cadb104b2..d557860daa6 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -709,7 +709,7 @@ describe('document: hooks:', function() {
       });
 
       ['init', 'save', 'validate'].forEach(function(type) {
-        childSchema.pre(type, function(obj, next) {
+        childSchema.pre(type, function(next) {
           self['pre' + type + 'Called'] = true;
           next();
         });

From 03a7a2d86465aec33ba34b4c9c577b0228fcccd9 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 17 Dec 2015 12:17:42 -0500
Subject: [PATCH 0138/2240] tests: repro #3686

---
 test/document.test.js | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/test/document.test.js b/test/document.test.js
index 3fff7aadb59..aad4990e367 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -2198,6 +2198,32 @@ describe('document', function() {
     });
   });
 
+  it('single embedded docs .set() (gh-3686)', function(done) {
+    var db = start();
+    var postHookCalls = [];
+    var personSchema = new Schema({ name: String, realName: String });
+
+    var bandSchema = new Schema({
+      guitarist: personSchema,
+      name: String
+    });
+    var Band = db.model('gh3686', bandSchema);
+    var obj = {
+      name: "Guns N' Roses",
+      guitarist: { name: 'Slash', realName: 'Saul Hudson' }
+    };
+
+    Band.create(obj, function(error, gnr) {
+      gnr.set('guitarist.name', 'Buckethead');
+      gnr.save(function(error) {
+        assert.ifError(error);
+        assert.equal(gnr.guitarist.name, 'Buckethead');
+        assert.equal(gnr.guitarist.realName, 'Saul Hudson');
+        done();
+      });
+    });
+  });
+
   it('handles virtuals with dots correctly (gh-3618)', function(done) {
     var db = start();
     var testSchema = new Schema({ nested: { type: Object, default: {} } });

From e66dfedf8a85dedccf40ebf5a400ac0ea950efff Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 17 Dec 2015 12:17:51 -0500
Subject: [PATCH 0139/2240] fix: handle .set() to single nested docs Fix #3686

---
 lib/document.js | 2 ++
 lib/schema.js   | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/lib/document.js b/lib/document.js
index f6e92286d21..d866c2064ad 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -743,6 +743,8 @@ Document.prototype.$__set = function(
         obj = obj[parts[i]];
       } else if (obj[parts[i]] && obj[parts[i]] instanceof Embedded) {
         obj = obj[parts[i]];
+      } else if (obj[parts[i]] && obj[parts[i]].$isSingleNested) {
+        obj = obj[parts[i]];
       } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
         obj = obj[parts[i]];
       } else {
diff --git a/lib/schema.js b/lib/schema.js
index 1ba5843c118..af476d77c02 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -456,6 +456,9 @@ Schema.prototype.path = function(path, obj) {
   if (obj == undefined) {
     if (this.paths[path]) return this.paths[path];
     if (this.subpaths[path]) return this.subpaths[path];
+    if (this.singleNestedPaths[path]) {
+      return this.singleNestedPaths[path];
+    }
 
     // subpaths?
     return /\.\d+\.?.*$/.test(path)

From e1a758a9c83c44b5f7360666817ce5513eaff693 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 17 Dec 2015 12:38:08 -0500
Subject: [PATCH 0140/2240] test(document): repro #3680

---
 test/document.test.js | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/test/document.test.js b/test/document.test.js
index aad4990e367..443af72c03b 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -2219,11 +2219,38 @@ describe('document', function() {
         assert.ifError(error);
         assert.equal(gnr.guitarist.name, 'Buckethead');
         assert.equal(gnr.guitarist.realName, 'Saul Hudson');
-        done();
+        db.close(done);
       });
     });
   });
 
+  it('single embedded docs with arrays pre hooks (gh-3680)', function(done) {
+    var db = start();
+    var childSchema = Schema({ count: Number });
+
+    var preCalls = 0;
+    childSchema.pre('save', function(next) {
+      ++preCalls;
+      next();
+    });
+
+    var SingleNestedSchema = new Schema({
+      children: [childSchema]
+    });
+
+    var ParentSchema = new Schema({
+      singleNested: SingleNestedSchema
+    });
+
+    var Parent = db.model('gh3680', ParentSchema);
+    var obj = { singleNested: { children: [{ count: 0 }] } };
+    Parent.create(obj, function(error) {
+      assert.ifError(error);
+      assert.equal(preCalls, 1);
+      db.close(done);
+    });
+  });
+
   it('handles virtuals with dots correctly (gh-3618)', function(done) {
     var db = start();
     var testSchema = new Schema({ nested: { type: Object, default: {} } });

From 919fc0a5bff168b28ca71dca26b8247c63eb0ca2 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 17 Dec 2015 12:38:48 -0500
Subject: [PATCH 0141/2240] fix(document): pre save for nested within single
 nested Fix #3680

---
 lib/document.js | 1 +
 lib/schema.js   | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index d866c2064ad..943fe53dd5a 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -1632,6 +1632,7 @@ Document.prototype.$__getAllSubdocs = function() {
     if (val instanceof Embedded) seed.push(val);
     if (val && val.$isSingleNested) {
       seed.push(val);
+      seed = Object.keys(val._doc).reduce(docReducer.bind(val._doc), seed);
     }
     if (val && val.isMongooseDocumentArray) {
       val.forEach(function _docReduce(doc) {
diff --git a/lib/schema.js b/lib/schema.js
index af476d77c02..a0a41504849 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -243,8 +243,8 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
     hook: 'save',
     isAsync: true,
     fn: function(next, done) {
-      var Promise = PromiseProvider.get(),
-          subdocs = this.$__getAllSubdocs();
+      var Promise = PromiseProvider.get();
+      var subdocs = this.$__getAllSubdocs();
 
       if (!subdocs.length || this.$__preSavingFromParent) {
         done();

From 14fd8fbfbeb4c1efa7d05d7e7cec94f1e281c586 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 17 Dec 2015 12:40:56 -0500
Subject: [PATCH 0142/2240] fix(connection): support options.replSet (Fix
 #3685)

---
 lib/drivers/node-mongodb-native/connection.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js
index 7f3dd76ebc5..c6c9517603b 100644
--- a/lib/drivers/node-mongodb-native/connection.js
+++ b/lib/drivers/node-mongodb-native/connection.js
@@ -188,7 +188,7 @@ NativeConnection.prototype.doOpenSet = function(fn) {
 
   var server = this.options.mongos
     ? new Mongos(servers, this.options.mongos)
-    : new ReplSetServers(servers, this.options.replset);
+    : new ReplSetServers(servers, this.options.replset || this.options.replSet);
   this.db = new Db(this.name, server, this.options.db);
 
   this.db.on('fullsetup', function() {

From 2623362a9171dd28479f525c32e23bff2c990c10 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 17 Dec 2015 13:01:10 -0500
Subject: [PATCH 0143/2240] chore: release 4.3.2

---
 History.md      |  14 +++
 bin/mongoose.js | 278 ++++++++++++++++++++++++++++--------------------
 package.json    |   2 +-
 3 files changed, 178 insertions(+), 116 deletions(-)

diff --git a/History.md b/History.md
index 46b42f5ccc2..fc9e97b4b78 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,17 @@
+4.3.2 / 2015-12-17
+==================
+ * fix(document): .set() into single nested schemas #3686
+ * fix(connection): support 'replSet' as well as 'replset' option #3685
+ * fix(document): bluebird unhandled rejection when validating doc arrays #3681
+ * fix(document): hooks for doc arrays in single nested schemas #3680
+ * fix(document): post hooks for single nested schemas #3679
+ * fix: remove unused npm module #3674 [sybarite](https://github.com/sybarite)
+ * fix(model): don't swallow exceptions in nested doc save callback #3671
+ * docs: update keepAlive info #3667 [ChrisZieba](https://github.com/ChrisZieba)
+ * fix(document): strict 'throw' throws a specific mongoose error #3662
+ * fix: flakey test #3332
+ * fix(query): more robust check for RegExp #2969
+
 4.3.1 / 2015-12-11
 ==================
  * feat(aggregate): `.sample()` helper #3665
diff --git a/bin/mongoose.js b/bin/mongoose.js
index bd69531e5a2..88ca4c00d0d 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -129,7 +129,7 @@ if (typeof window !== 'undefined') {
 }
 
 }).call(this,require("buffer").Buffer)
-},{"./document_provider.js":6,"./error":12,"./schema":24,"./schematype.js":37,"./types":43,"./utils.js":46,"./virtualtype":47,"buffer":50}],3:[function(require,module,exports){
+},{"./document_provider.js":6,"./error":12,"./schema":25,"./schematype.js":38,"./types":44,"./utils.js":47,"./virtualtype":48,"buffer":51}],3:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -236,7 +236,7 @@ Document.prototype.constructor = Document;
 Document.ValidationError = ValidationError;
 module.exports = exports = Document;
 
-},{"./document":5,"./error":12,"./internal":21,"./schema":24,"./types/objectid":44,"./utils":46,"events":54}],4:[function(require,module,exports){
+},{"./document":5,"./error":12,"./internal":22,"./schema":25,"./types/objectid":45,"./utils":47,"events":55}],4:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -449,7 +449,7 @@ var cast = module.exports = function(schema, obj) {
   return obj;
 };
 
-},{"./schema/index":31,"./utils":46}],5:[function(require,module,exports){
+},{"./schema/index":32,"./utils":47}],5:[function(require,module,exports){
 (function (process,Buffer){
 /* eslint no-unused-vars: 1 */
 
@@ -461,6 +461,7 @@ var EventEmitter = require('events').EventEmitter,
     MongooseError = require('./error'),
     MixedSchema = require('./schema/mixed'),
     Schema = require('./schema'),
+    StrictModeError = require('./error/strict'),
     ValidatorError = require('./schematype').ValidatorError,
     utils = require('./utils'),
     clone = utils.clone,
@@ -967,7 +968,7 @@ Document.prototype.set = function(path, val, type, options) {
             this.set(prefix + key,
               path[key].toObject({ virtuals: false }), constructing);
           } else if ('throw' == strict) {
-            throw new Error('Field `' + key + '` is not in schema.');
+            throw new StrictModeError(key);
           }
         } else if (undefined !== path[key]) {
           this.set(prefix + key, path[key], constructing);
@@ -1013,7 +1014,7 @@ Document.prototype.set = function(path, val, type, options) {
 
     if (!mixed) {
       if ('throw' == strict) {
-        throw new Error("Field `" + path + "` is not in schema.");
+        throw new StrictModeError(path);
       }
       return this;
     }
@@ -1195,6 +1196,8 @@ Document.prototype.$__set = function(
         obj = obj[parts[i]];
       } else if (obj[parts[i]] && obj[parts[i]] instanceof Embedded) {
         obj = obj[parts[i]];
+      } else if (obj[parts[i]] && obj[parts[i]].$isSingleNested) {
+        obj = obj[parts[i]];
       } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
         obj = obj[parts[i]];
       } else {
@@ -2082,6 +2085,7 @@ Document.prototype.$__getAllSubdocs = function() {
     if (val instanceof Embedded) seed.push(val);
     if (val && val.$isSingleNested) {
       seed.push(val);
+      seed = Object.keys(val._doc).reduce(docReducer.bind(val._doc), seed);
     }
     if (val && val.isMongooseDocumentArray) {
       val.forEach(function _docReduce(doc) {
@@ -2785,7 +2789,7 @@ Document.ValidationError = ValidationError;
 module.exports = exports = Document;
 
 }).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"./error":12,"./internal":21,"./promise_provider":23,"./schema":24,"./schema/mixed":32,"./schematype":37,"./types/array":39,"./types/documentarray":41,"./types/embedded":42,"./utils":46,"FWaASH":56,"buffer":50,"events":54,"hooks-fixed":77,"util":58}],6:[function(require,module,exports){
+},{"./error":12,"./error/strict":18,"./internal":22,"./promise_provider":24,"./schema":25,"./schema/mixed":33,"./schematype":38,"./types/array":40,"./types/documentarray":42,"./types/embedded":43,"./utils":47,"FWaASH":57,"buffer":51,"events":55,"hooks-fixed":78,"util":59}],6:[function(require,module,exports){
 'use strict';
 
 /*!
@@ -2827,7 +2831,7 @@ var Binary = require('bson').Binary;
 
 module.exports = exports = Binary;
 
-},{"bson":61}],9:[function(require,module,exports){
+},{"bson":62}],9:[function(require,module,exports){
 /*!
  * Module exports.
  */
@@ -2852,7 +2856,7 @@ var ObjectId = require('bson').ObjectID;
 
 module.exports = exports = ObjectId;
 
-},{"bson":61}],11:[function(require,module,exports){
+},{"bson":62}],11:[function(require,module,exports){
 (function (global){
 /*!
  * ignore
@@ -2930,7 +2934,7 @@ MongooseError.OverwriteModelError = require('./error/overwriteModel');
 MongooseError.MissingSchemaError = require('./error/missingSchema');
 MongooseError.DivergentArrayError = require('./error/divergentArray');
 
-},{"./error/cast":13,"./error/divergentArray":14,"./error/messages":15,"./error/missingSchema":16,"./error/overwriteModel":17,"./error/validation":18,"./error/validator":19,"./error/version":20}],13:[function(require,module,exports){
+},{"./error/cast":13,"./error/divergentArray":14,"./error/messages":15,"./error/missingSchema":16,"./error/overwriteModel":17,"./error/validation":19,"./error/validator":20,"./error/version":21}],13:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -3132,6 +3136,43 @@ OverwriteModelError.prototype.constructor = MongooseError;
 module.exports = OverwriteModelError;
 
 },{"../error.js":12}],18:[function(require,module,exports){
+/*!
+ * Module dependencies.
+ */
+
+var MongooseError = require('../error.js');
+
+/**
+ * Strict mode error constructor
+ *
+ * @param {String} type
+ * @param {String} value
+ * @inherits MongooseError
+ * @api private
+ */
+
+function StrictModeError(path) {
+  MongooseError.call(this, 'Field `' + path + '` is not in schema and strict ' +
+    'mode is set to throw.');
+  if (Error.captureStackTrace) {
+    Error.captureStackTrace(this);
+  } else {
+    this.stack = new Error().stack;
+  }
+  this.name = 'StrictModeError';
+  this.path = path;
+}
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+StrictModeError.prototype = Object.create(MongooseError.prototype);
+StrictModeError.prototype.constructor = MongooseError;
+
+module.exports = StrictModeError;
+
+},{"../error.js":12}],19:[function(require,module,exports){
 
 /*!
  * Module requirements
@@ -3195,7 +3236,7 @@ ValidationError.prototype.toString = function() {
 
 module.exports = exports = ValidationError;
 
-},{"../error.js":12}],19:[function(require,module,exports){
+},{"../error.js":12}],20:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -3268,7 +3309,7 @@ ValidatorError.prototype.toString = function() {
 
 module.exports = ValidatorError;
 
-},{"../error.js":12}],20:[function(require,module,exports){
+},{"../error.js":12}],21:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -3302,7 +3343,7 @@ VersionError.prototype.constructor = MongooseError;
 
 module.exports = VersionError;
 
-},{"../error.js":12}],21:[function(require,module,exports){
+},{"../error.js":12}],22:[function(require,module,exports){
 /*!
  * Dependencies
  */
@@ -3335,7 +3376,7 @@ function InternalCache() {
   this.fullPath = undefined;
 }
 
-},{"./statemachine":38}],22:[function(require,module,exports){
+},{"./statemachine":39}],23:[function(require,module,exports){
 /*!
  * Module dependencies
  */
@@ -3628,7 +3669,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject;
 
 module.exports = Promise;
 
-},{"mpromise":81,"util":58}],23:[function(require,module,exports){
+},{"mpromise":82,"util":59}],24:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -3681,7 +3722,7 @@ Promise.reset = function() {
 
 module.exports = Promise;
 
-},{"./ES6Promise":1,"./promise":22,"mquery":86}],24:[function(require,module,exports){
+},{"./ES6Promise":1,"./promise":23,"mquery":87}],25:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -3928,8 +3969,8 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
     hook: 'save',
     isAsync: true,
     fn: function(next, done) {
-      var Promise = PromiseProvider.get(),
-          subdocs = this.$__getAllSubdocs();
+      var Promise = PromiseProvider.get();
+      var subdocs = this.$__getAllSubdocs();
 
       if (!subdocs.length || this.$__preSavingFromParent) {
         done();
@@ -3937,26 +3978,22 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
         return;
       }
 
-      new Promise.ES6(function(resolve, reject) {
-        async.each(subdocs, function(subdoc, cb) {
-          subdoc.$__preSavingFromParent = true;
-          subdoc.save(function(err) {
-            cb(err);
-          });
-        }, function(error) {
-          for (var i = 0; i < subdocs.length; ++i) {
-            delete subdocs[i].$__preSavingFromParent;
-          }
-          if (error) {
-            reject(error);
-            return;
-          }
-          resolve();
+      async.each(subdocs, function(subdoc, cb) {
+        subdoc.$__preSavingFromParent = true;
+        subdoc.save(function(err) {
+          cb(err);
         });
-      }).then(function() {
+      }, function(error) {
+        for (var i = 0; i < subdocs.length; ++i) {
+          delete subdocs[i].$__preSavingFromParent;
+        }
+        if (error) {
+          done(error);
+          return;
+        }
         next();
         done();
-      }, done);
+      });
     }
   }]
 });
@@ -4145,6 +4182,9 @@ Schema.prototype.path = function(path, obj) {
   if (obj == undefined) {
     if (this.paths[path]) return this.paths[path];
     if (this.subpaths[path]) return this.subpaths[path];
+    if (this.singleNestedPaths[path]) {
+      return this.singleNestedPaths[path];
+    }
 
     // subpaths?
     return /\.\d+\.?.*$/.test(path)
@@ -4960,7 +5000,7 @@ Schema.Types = MongooseTypes = require('./schema/index');
 exports.ObjectId = MongooseTypes.ObjectId;
 
 }).call(this,require("buffer").Buffer)
-},{"./drivers":11,"./promise_provider":23,"./schema/index":31,"./utils":46,"./virtualtype":47,"async":48,"buffer":50,"events":54,"kareem":78}],25:[function(require,module,exports){
+},{"./drivers":11,"./promise_provider":24,"./schema/index":32,"./utils":47,"./virtualtype":48,"async":49,"buffer":51,"events":55,"kareem":79}],26:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -5356,7 +5396,7 @@ handle.$regex = SchemaArray.prototype.castForQuery;
 
 module.exports = SchemaArray;
 
-},{"../cast":4,"../schematype":37,"../types":43,"../utils":46,"./boolean":26,"./buffer":27,"./date":28,"./mixed":32,"./number":33,"./objectid":34,"./string":36}],26:[function(require,module,exports){
+},{"../cast":4,"../schematype":38,"../types":44,"../utils":47,"./boolean":27,"./buffer":28,"./date":29,"./mixed":33,"./number":34,"./objectid":35,"./string":37}],27:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -5449,7 +5489,7 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val) {
 
 module.exports = SchemaBoolean;
 
-},{"../schematype":37,"../utils":46}],27:[function(require,module,exports){
+},{"../schematype":38,"../utils":47}],28:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -5632,7 +5672,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaBuffer;
 
 }).call(this,require("buffer").Buffer)
-},{"../schematype":37,"../types":43,"../utils":46,"./../document":5,"./operators/bitwise":35,"buffer":50}],28:[function(require,module,exports){
+},{"../schematype":38,"../types":44,"../utils":47,"./../document":5,"./operators/bitwise":36,"buffer":51}],29:[function(require,module,exports){
 /*!
  * Module requirements.
  */
@@ -5918,7 +5958,7 @@ SchemaDate.prototype.castForQuery = function($conditional, val) {
 
 module.exports = SchemaDate;
 
-},{"../error":12,"../schematype":37,"../utils":46}],29:[function(require,module,exports){
+},{"../error":12,"../schematype":38,"../utils":47}],30:[function(require,module,exports){
 /* eslint no-empty: 1 */
 
 /*!
@@ -6018,7 +6058,7 @@ DocumentArray.prototype.doValidate = function(array, fn, scope) {
         continue;
       }
 
-      doc.validate(function(err) {
+      doc.validate({ __noPromise: true }, function(err) {
         if (err) {
           error = err;
         }
@@ -6174,7 +6214,7 @@ function scopePaths(array, fields, init) {
 
 module.exports = DocumentArray;
 
-},{"../error/cast":13,"../schematype":37,"../types/documentarray":41,"../types/embedded":42,"./array":25}],30:[function(require,module,exports){
+},{"../error/cast":13,"../schematype":38,"../types/documentarray":42,"../types/embedded":43,"./array":26}],31:[function(require,module,exports){
 var SchemaType = require('../schematype');
 var Subdocument = require('../types/subdocument');
 
@@ -6191,8 +6231,15 @@ module.exports = Embedded;
  */
 
 function Embedded(schema, path, options) {
-  var _embedded = function() {
+  var _embedded = function(value, path, parent) {
+    var _this = this;
     Subdocument.apply(this, arguments);
+    this.$parent = parent;
+    if (parent) {
+      parent.on('save', function() {
+        _this.emit('save', _this);
+      });
+    }
   };
   _embedded.prototype = Object.create(Subdocument.prototype);
   _embedded.prototype.$__setSchema(schema);
@@ -6229,8 +6276,7 @@ Embedded.prototype.cast = function(val, doc, init) {
   if (val && val.$isSingleNested) {
     return val;
   }
-  var subdoc = new this.caster();
-  subdoc.$parent = doc;
+  var subdoc = new this.caster(undefined, undefined, doc);
   if (init) {
     subdoc.init(val);
   } else {
@@ -6307,7 +6353,7 @@ Embedded.prototype.checkRequired = function(value) {
   return !!value && value.$isSingleNested;
 };
 
-},{"../schematype":37,"../types/subdocument":45}],31:[function(require,module,exports){
+},{"../schematype":38,"../types/subdocument":46}],32:[function(require,module,exports){
 
 /*!
  * Module exports.
@@ -6339,7 +6385,7 @@ exports.Oid = exports.ObjectId;
 exports.Object = exports.Mixed;
 exports.Bool = exports.Boolean;
 
-},{"./array":25,"./boolean":26,"./buffer":27,"./date":28,"./documentarray":29,"./embedded":30,"./mixed":32,"./number":33,"./objectid":34,"./string":36}],32:[function(require,module,exports){
+},{"./array":26,"./boolean":27,"./buffer":28,"./date":29,"./documentarray":30,"./embedded":31,"./mixed":33,"./number":34,"./objectid":35,"./string":37}],33:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -6432,7 +6478,7 @@ Mixed.prototype.castForQuery = function($cond, val) {
 
 module.exports = Mixed;
 
-},{"../schematype":37,"../utils":46}],33:[function(require,module,exports){
+},{"../schematype":38,"../utils":47}],34:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module requirements.
@@ -6729,7 +6775,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaNumber;
 
 }).call(this,require("buffer").Buffer)
-},{"../error":12,"../schematype":37,"../utils":46,"./../document":5,"./operators/bitwise":35,"buffer":50}],34:[function(require,module,exports){
+},{"../error":12,"../schematype":38,"../utils":47,"./../document":5,"./operators/bitwise":36,"buffer":51}],35:[function(require,module,exports){
 (function (Buffer){
 /* eslint no-empty: 1 */
 
@@ -6927,7 +6973,7 @@ function resetId(v) {
 module.exports = ObjectId;
 
 }).call(this,require("buffer").Buffer)
-},{"../schematype":37,"../types/objectid":44,"../utils":46,"./../document":5,"buffer":50}],35:[function(require,module,exports){
+},{"../schematype":38,"../types/objectid":45,"../utils":47,"./../document":5,"buffer":51}],36:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module requirements.
@@ -6968,18 +7014,18 @@ function _castNumber(_this, num) {
 module.exports = handleBitwiseOperator;
 
 }).call(this,require("buffer").Buffer)
-},{"../../error/cast":13,"buffer":50}],36:[function(require,module,exports){
+},{"../../error/cast":13,"buffer":51}],37:[function(require,module,exports){
 (function (Buffer){
 
 /*!
  * Module dependencies.
  */
 
-var SchemaType = require('../schematype'),
-    CastError = SchemaType.CastError,
-    errorMessages = require('../error').messages,
-    utils = require('../utils'),
-    Document;
+var SchemaType = require('../schematype');
+var CastError = SchemaType.CastError;
+var errorMessages = require('../error').messages;
+var utils = require('../utils');
+var Document;
 
 /**
  * String SchemaType constructor.
@@ -7452,7 +7498,9 @@ SchemaString.prototype.castForQuery = function($conditional, val) {
     return handler.call(this, val);
   } else {
     val = $conditional;
-    if (val instanceof RegExp) return val;
+    if (Object.prototype.toString.call(val) === '[object RegExp]') {
+      return val;
+    }
     return this.cast(val);
   }
 };
@@ -7464,7 +7512,7 @@ SchemaString.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaString;
 
 }).call(this,require("buffer").Buffer)
-},{"../error":12,"../schematype":37,"../utils":46,"./../document":5,"buffer":50}],37:[function(require,module,exports){
+},{"../error":12,"../schematype":38,"../utils":47,"./../document":5,"buffer":51}],38:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -8323,7 +8371,7 @@ exports.CastError = CastError;
 exports.ValidatorError = ValidatorError;
 
 }).call(this,require("buffer").Buffer)
-},{"./error":12,"./utils":46,"buffer":50}],38:[function(require,module,exports){
+},{"./error":12,"./utils":47,"buffer":51}],39:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -8503,7 +8551,7 @@ StateMachine.prototype.map = function map() {
   return this.map.apply(this, arguments);
 };
 
-},{"./utils":46}],39:[function(require,module,exports){
+},{"./utils":47}],40:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9270,7 +9318,7 @@ MongooseArray.mixin.remove = MongooseArray.mixin.pull;
 module.exports = exports = MongooseArray;
 
 }).call(this,require("buffer").Buffer)
-},{"../document":5,"../utils":46,"./embedded":42,"./objectid":44,"buffer":50}],40:[function(require,module,exports){
+},{"../document":5,"../utils":47,"./embedded":43,"./objectid":45,"buffer":51}],41:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9543,7 +9591,7 @@ MongooseBuffer.Binary = Binary;
 module.exports = MongooseBuffer;
 
 }).call(this,require("buffer").Buffer)
-},{"../drivers":11,"../utils":46,"buffer":50}],41:[function(require,module,exports){
+},{"../drivers":11,"../utils":47,"buffer":51}],42:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9770,7 +9818,7 @@ MongooseDocumentArray.mixin.notify = function notify(event) {
 module.exports = MongooseDocumentArray;
 
 }).call(this,require("buffer").Buffer)
-},{"../document":5,"../schema/objectid":34,"../utils":46,"./array":39,"./objectid":44,"buffer":50,"util":58}],42:[function(require,module,exports){
+},{"../document":5,"../schema/objectid":35,"../utils":47,"./array":40,"./objectid":45,"buffer":51,"util":59}],43:[function(require,module,exports){
 /* eslint no-func-assign: 1 */
 
 /*!
@@ -10084,7 +10132,7 @@ EmbeddedDocument.prototype.parentArray = function() {
 
 module.exports = EmbeddedDocument;
 
-},{"../document_provider":6,"../promise_provider":23,"util":58}],43:[function(require,module,exports){
+},{"../document_provider":6,"../promise_provider":24,"util":59}],44:[function(require,module,exports){
 
 /*!
  * Module exports.
@@ -10101,7 +10149,7 @@ exports.ObjectId = require('./objectid');
 
 exports.Subdocument = require('./subdocument');
 
-},{"./array":39,"./buffer":40,"./documentarray":41,"./embedded":42,"./objectid":44,"./subdocument":45}],44:[function(require,module,exports){
+},{"./array":40,"./buffer":41,"./documentarray":42,"./embedded":43,"./objectid":45,"./subdocument":46}],45:[function(require,module,exports){
 /**
  * ObjectId type constructor
  *
@@ -10116,7 +10164,7 @@ var ObjectId = require('../drivers').ObjectId;
 
 module.exports = ObjectId;
 
-},{"../drivers":11}],45:[function(require,module,exports){
+},{"../drivers":11}],46:[function(require,module,exports){
 var Document = require('../document');
 var PromiseProvider = require('../promise_provider');
 
@@ -10205,7 +10253,7 @@ Subdocument.prototype.ownerDocument = function() {
   return this.$__.ownerDocument = parent;
 };
 
-},{"../document":5,"../promise_provider":23}],46:[function(require,module,exports){
+},{"../document":5,"../promise_provider":24}],47:[function(require,module,exports){
 (function (process,Buffer){
 /*!
  * Module dependencies.
@@ -11006,7 +11054,7 @@ exports.each = function(arr, fn) {
 };
 
 }).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"./document":5,"./types":43,"./types/objectid":44,"FWaASH":56,"buffer":50,"mpath":79,"ms":92,"regexp-clone":93,"sliced":94}],47:[function(require,module,exports){
+},{"./document":5,"./types":44,"./types/objectid":45,"FWaASH":57,"buffer":51,"mpath":80,"ms":93,"regexp-clone":94,"sliced":95}],48:[function(require,module,exports){
 
 /**
  * VirtualType constructor
@@ -11111,7 +11159,7 @@ VirtualType.prototype.applySetters = function(value, scope) {
 
 module.exports = VirtualType;
 
-},{}],48:[function(require,module,exports){
+},{}],49:[function(require,module,exports){
 (function (process){
 /*!
  * async
@@ -12238,7 +12286,7 @@ module.exports = VirtualType;
 }());
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":56}],49:[function(require,module,exports){
+},{"FWaASH":57}],50:[function(require,module,exports){
 // http://wiki.commonjs.org/wiki/Unit_Testing/1.0
 //
 // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
@@ -12600,7 +12648,7 @@ var objectKeys = Object.keys || function (obj) {
   return keys;
 };
 
-},{"util/":58}],50:[function(require,module,exports){
+},{"util/":59}],51:[function(require,module,exports){
 /*!
  * The buffer module from node.js, for the browser.
  *
@@ -13654,7 +13702,7 @@ function decodeUtf8Char (str) {
   }
 }
 
-},{"base64-js":51,"ieee754":52,"is-array":53}],51:[function(require,module,exports){
+},{"base64-js":52,"ieee754":53,"is-array":54}],52:[function(require,module,exports){
 var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 
 ;(function (exports) {
@@ -13776,7 +13824,7 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 	exports.fromByteArray = uint8ToBase64
 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
 
-},{}],52:[function(require,module,exports){
+},{}],53:[function(require,module,exports){
 exports.read = function (buffer, offset, isLE, mLen, nBytes) {
   var e, m
   var eLen = nBytes * 8 - mLen - 1
@@ -13862,7 +13910,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
   buffer[offset + i - d] |= s * 128
 }
 
-},{}],53:[function(require,module,exports){
+},{}],54:[function(require,module,exports){
 
 /**
  * isArray
@@ -13897,7 +13945,7 @@ module.exports = isArray || function (val) {
   return !! val && '[object Array]' == str.call(val);
 };
 
-},{}],54:[function(require,module,exports){
+},{}],55:[function(require,module,exports){
 // Copyright Joyent, Inc. and other Node contributors.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
@@ -14200,7 +14248,7 @@ function isUndefined(arg) {
   return arg === void 0;
 }
 
-},{}],55:[function(require,module,exports){
+},{}],56:[function(require,module,exports){
 if (typeof Object.create === 'function') {
   // implementation from standard node.js 'util' module
   module.exports = function inherits(ctor, superCtor) {
@@ -14225,7 +14273,7 @@ if (typeof Object.create === 'function') {
   }
 }
 
-},{}],56:[function(require,module,exports){
+},{}],57:[function(require,module,exports){
 // shim for using process in browser
 
 var process = module.exports = {};
@@ -14290,14 +14338,14 @@ process.chdir = function (dir) {
     throw new Error('process.chdir is not supported');
 };
 
-},{}],57:[function(require,module,exports){
+},{}],58:[function(require,module,exports){
 module.exports = function isBuffer(arg) {
   return arg && typeof arg === 'object'
     && typeof arg.copy === 'function'
     && typeof arg.fill === 'function'
     && typeof arg.readUInt8 === 'function';
 }
-},{}],58:[function(require,module,exports){
+},{}],59:[function(require,module,exports){
 (function (process,global){
 // Copyright Joyent, Inc. and other Node contributors.
 //
@@ -14887,7 +14935,7 @@ function hasOwnProperty(obj, prop) {
 }
 
 }).call(this,require("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./support/isBuffer":57,"FWaASH":56,"inherits":55}],59:[function(require,module,exports){
+},{"./support/isBuffer":58,"FWaASH":57,"inherits":56}],60:[function(require,module,exports){
 /**
  * Module dependencies.
  * @ignore
@@ -15233,7 +15281,7 @@ Binary.SUBTYPE_USER_DEFINED = 128;
 module.exports = Binary;
 module.exports.Binary = Binary;
 
-},{"buffer":50}],60:[function(require,module,exports){
+},{"buffer":51}],61:[function(require,module,exports){
 (function (process){
 /**
  * Binary Parser.
@@ -15622,7 +15670,7 @@ BinaryParser.Buffer = BinaryParserBuffer;
 exports.BinaryParser = BinaryParser;
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":56,"util":58}],61:[function(require,module,exports){
+},{"FWaASH":57,"util":59}],62:[function(require,module,exports){
 (function (Buffer){
 // "use strict"
 
@@ -15949,7 +15997,7 @@ module.exports.MaxKey = MaxKey;
 module.exports.BSONRegExp = BSONRegExp;
 
 }).call(this,require("buffer").Buffer)
-},{"./binary":59,"./code":62,"./db_ref":63,"./double":64,"./float_parser":65,"./long":66,"./map":67,"./max_key":68,"./min_key":69,"./objectid":70,"./parser/calculate_size":71,"./parser/deserializer":72,"./parser/serializer":73,"./regexp":74,"./symbol":75,"./timestamp":76,"buffer":50}],62:[function(require,module,exports){
+},{"./binary":60,"./code":63,"./db_ref":64,"./double":65,"./float_parser":66,"./long":67,"./map":68,"./max_key":69,"./min_key":70,"./objectid":71,"./parser/calculate_size":72,"./parser/deserializer":73,"./parser/serializer":74,"./regexp":75,"./symbol":76,"./timestamp":77,"buffer":51}],63:[function(require,module,exports){
 /**
  * A class representation of the BSON Code type.
  *
@@ -15974,7 +16022,7 @@ Code.prototype.toJSON = function() {
 
 module.exports = Code;
 module.exports.Code = Code;
-},{}],63:[function(require,module,exports){
+},{}],64:[function(require,module,exports){
 /**
  * A class representation of the BSON DBRef type.
  *
@@ -16007,7 +16055,7 @@ DBRef.prototype.toJSON = function() {
 
 module.exports = DBRef;
 module.exports.DBRef = DBRef;
-},{}],64:[function(require,module,exports){
+},{}],65:[function(require,module,exports){
 /**
  * A class representation of the BSON Double type.
  *
@@ -16041,7 +16089,7 @@ Double.prototype.toJSON = function() {
 
 module.exports = Double;
 module.exports.Double = Double;
-},{}],65:[function(require,module,exports){
+},{}],66:[function(require,module,exports){
 // Copyright (c) 2008, Fair Oaks Labs, Inc.
 // All rights reserved.
 // 
@@ -16163,7 +16211,7 @@ var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) {
 
 exports.readIEEE754 = readIEEE754;
 exports.writeIEEE754 = writeIEEE754;
-},{}],66:[function(require,module,exports){
+},{}],67:[function(require,module,exports){
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
@@ -17020,7 +17068,7 @@ Long.TWO_PWR_24_ = Long.fromInt(1 << 24);
  */
 module.exports = Long;
 module.exports.Long = Long;
-},{}],67:[function(require,module,exports){
+},{}],68:[function(require,module,exports){
 (function (global){
 "use strict"
 
@@ -17149,7 +17197,7 @@ if(typeof global.Map !== 'undefined') {
   module.exports.Map = Map;
 }
 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],68:[function(require,module,exports){
+},{}],69:[function(require,module,exports){
 /**
  * A class representation of the BSON MaxKey type.
  *
@@ -17164,7 +17212,7 @@ function MaxKey() {
 
 module.exports = MaxKey;
 module.exports.MaxKey = MaxKey;
-},{}],69:[function(require,module,exports){
+},{}],70:[function(require,module,exports){
 /**
  * A class representation of the BSON MinKey type.
  *
@@ -17179,7 +17227,7 @@ function MinKey() {
 
 module.exports = MinKey;
 module.exports.MinKey = MinKey;
-},{}],70:[function(require,module,exports){
+},{}],71:[function(require,module,exports){
 (function (process){
 /**
  * Module dependencies.
@@ -17461,7 +17509,7 @@ module.exports.ObjectID = ObjectID;
 module.exports.ObjectId = ObjectID;
 
 }).call(this,require("FWaASH"))
-},{"./binary_parser":60,"FWaASH":56}],71:[function(require,module,exports){
+},{"./binary_parser":61,"FWaASH":57}],72:[function(require,module,exports){
 (function (Buffer){
 "use strict"
 
@@ -17775,7 +17823,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 module.exports = calculateObjectSize;
 
 }).call(this,require("buffer").Buffer)
-},{"../binary":59,"../code":62,"../db_ref":63,"../double":64,"../float_parser":65,"../long":66,"../max_key":68,"../min_key":69,"../objectid":70,"../regexp":74,"../symbol":75,"../timestamp":76,"buffer":50}],72:[function(require,module,exports){
+},{"../binary":60,"../code":63,"../db_ref":64,"../double":65,"../float_parser":66,"../long":67,"../max_key":69,"../min_key":70,"../objectid":71,"../regexp":75,"../symbol":76,"../timestamp":77,"buffer":51}],73:[function(require,module,exports){
 "use strict"
 
 var writeIEEE754 = require('../float_parser').writeIEEE754,
@@ -18332,7 +18380,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 
 module.exports = deserialize
 
-},{"../binary":59,"../code":62,"../db_ref":63,"../double":64,"../float_parser":65,"../long":66,"../max_key":68,"../min_key":69,"../objectid":70,"../regexp":74,"../symbol":75,"../timestamp":76,"util":58}],73:[function(require,module,exports){
+},{"../binary":60,"../code":63,"../db_ref":64,"../double":65,"../float_parser":66,"../long":67,"../max_key":69,"../min_key":70,"../objectid":71,"../regexp":75,"../symbol":76,"../timestamp":77,"util":59}],74:[function(require,module,exports){
 (function (Buffer){
 "use strict"
 
@@ -19248,7 +19296,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 module.exports = serializeInto;
 
 }).call(this,require("buffer").Buffer)
-},{"../binary":59,"../code":62,"../db_ref":63,"../double":64,"../float_parser":65,"../long":66,"../map":67,"../max_key":68,"../min_key":69,"../objectid":70,"../regexp":74,"../symbol":75,"../timestamp":76,"buffer":50}],74:[function(require,module,exports){
+},{"../binary":60,"../code":63,"../db_ref":64,"../double":65,"../float_parser":66,"../long":67,"../map":68,"../max_key":69,"../min_key":70,"../objectid":71,"../regexp":75,"../symbol":76,"../timestamp":77,"buffer":51}],75:[function(require,module,exports){
 /**
  * A class representation of the BSON RegExp type.
  *
@@ -19279,7 +19327,7 @@ function BSONRegExp(pattern, options) {
 
 module.exports = BSONRegExp;
 module.exports.BSONRegExp = BSONRegExp;
-},{}],75:[function(require,module,exports){
+},{}],76:[function(require,module,exports){
 /**
  * A class representation of the BSON Symbol type.
  *
@@ -19327,7 +19375,7 @@ Symbol.prototype.toJSON = function() {
 
 module.exports = Symbol;
 module.exports.Symbol = Symbol;
-},{}],76:[function(require,module,exports){
+},{}],77:[function(require,module,exports){
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
@@ -20184,7 +20232,7 @@ Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24);
  */
 module.exports = Timestamp;
 module.exports.Timestamp = Timestamp;
-},{}],77:[function(require,module,exports){
+},{}],78:[function(require,module,exports){
 // TODO Add in pre and post skipping options
 module.exports = {
   /**
@@ -20377,7 +20425,7 @@ function once (fn, scope) {
   };
 }
 
-},{}],78:[function(require,module,exports){
+},{}],79:[function(require,module,exports){
 (function (process){
 'use strict';
 
@@ -20610,10 +20658,10 @@ Kareem.prototype.clone = function() {
 module.exports = Kareem;
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":56}],79:[function(require,module,exports){
+},{"FWaASH":57}],80:[function(require,module,exports){
 module.exports = exports = require('./lib');
 
-},{"./lib":80}],80:[function(require,module,exports){
+},{"./lib":81}],81:[function(require,module,exports){
 
 /**
  * Returns the value of object `o` at the given `path`.
@@ -20798,7 +20846,7 @@ function K (v) {
   return v;
 }
 
-},{}],81:[function(require,module,exports){
+},{}],82:[function(require,module,exports){
 (function (process){
 'use strict';
 var util = require('util');
@@ -21242,7 +21290,7 @@ Promise.deferred = function deferred() {
 
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":56,"events":54,"util":58}],82:[function(require,module,exports){
+},{"FWaASH":57,"events":55,"util":59}],83:[function(require,module,exports){
 'use strict';
 
 /**
@@ -21286,7 +21334,7 @@ function notImplemented (method) {
 }
 
 
-},{}],83:[function(require,module,exports){
+},{}],84:[function(require,module,exports){
 'use strict';
 
 var env = require('../env')
@@ -21301,7 +21349,7 @@ module.exports =
   require('./collection');
 
 
-},{"../env":85,"./collection":82,"./node":84}],84:[function(require,module,exports){
+},{"../env":86,"./collection":83,"./node":85}],85:[function(require,module,exports){
 'use strict';
 
 /**
@@ -21403,7 +21451,7 @@ NodeCollection.prototype.findStream = function(match, findOptions, streamOptions
 module.exports = exports = NodeCollection;
 
 
-},{"../utils":88,"./collection":82}],85:[function(require,module,exports){
+},{"../utils":89,"./collection":83}],86:[function(require,module,exports){
 (function (process,global,Buffer){
 'use strict';
 
@@ -21429,7 +21477,7 @@ exports.type = exports.isNode ? 'node'
   : 'unknown'
 
 }).call(this,require("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
-},{"FWaASH":56,"buffer":50}],86:[function(require,module,exports){
+},{"FWaASH":57,"buffer":51}],87:[function(require,module,exports){
 'use strict';
 
 /**
@@ -24043,7 +24091,7 @@ module.exports = exports = Query;
 // TODO
 // test utils
 
-},{"./collection":83,"./collection/collection":82,"./env":85,"./permissions":87,"./utils":88,"assert":49,"bluebird":89,"debug":90,"sliced":94,"util":58}],87:[function(require,module,exports){
+},{"./collection":84,"./collection/collection":83,"./env":86,"./permissions":88,"./utils":89,"assert":50,"bluebird":90,"debug":91,"sliced":95,"util":59}],88:[function(require,module,exports){
 'use strict';
 
 var denied = exports;
@@ -24135,7 +24183,7 @@ denied.count.maxScan =
 denied.count.snapshot =
 denied.count.tailable = true;
 
-},{}],88:[function(require,module,exports){
+},{}],89:[function(require,module,exports){
 (function (process,Buffer){
 'use strict';
 
@@ -24470,7 +24518,7 @@ exports.cloneBuffer = function (buff) {
 };
 
 }).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"FWaASH":56,"buffer":50,"regexp-clone":93}],89:[function(require,module,exports){
+},{"FWaASH":57,"buffer":51,"regexp-clone":94}],90:[function(require,module,exports){
 (function (process,global){
 /* @preserve
  * The MIT License (MIT)
@@ -29578,7 +29626,7 @@ function isUndefined(arg) {
 },{}]},{},[4])(4)
 });                    ;if (typeof window !== 'undefined' && window !== null) {                               window.P = window.Promise;                                                     } else if (typeof self !== 'undefined' && self !== null) {                             self.P = self.Promise;                                                         }
 }).call(this,require("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"FWaASH":56}],90:[function(require,module,exports){
+},{"FWaASH":57}],91:[function(require,module,exports){
 
 /**
  * This is the web browser implementation of `debug()`.
@@ -29748,7 +29796,7 @@ function localstorage(){
   } catch (e) {}
 }
 
-},{"./debug":91}],91:[function(require,module,exports){
+},{"./debug":92}],92:[function(require,module,exports){
 
 /**
  * This is the common logic for both the Node.js and web browser
@@ -29947,7 +29995,7 @@ function coerce(val) {
   return val;
 }
 
-},{"ms":92}],92:[function(require,module,exports){
+},{"ms":93}],93:[function(require,module,exports){
 /**
  * Helpers.
  */
@@ -30074,7 +30122,7 @@ function plural(ms, n, name) {
   return Math.ceil(ms / n) + ' ' + name + 's';
 }
 
-},{}],93:[function(require,module,exports){
+},{}],94:[function(require,module,exports){
 
 var toString = Object.prototype.toString;
 
@@ -30096,10 +30144,10 @@ module.exports = exports = function (regexp) {
 }
 
 
-},{}],94:[function(require,module,exports){
+},{}],95:[function(require,module,exports){
 module.exports = exports = require('./lib/sliced');
 
-},{"./lib/sliced":95}],95:[function(require,module,exports){
+},{"./lib/sliced":96}],96:[function(require,module,exports){
 
 /**
  * An Array.prototype.slice.call(arguments) alternative
diff --git a/package.json b/package.json
index 551d4d9b3e0..b20bbf61242 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.2-pre",
+  "version": "4.3.2",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From 8b3c4ec73fcf207e8db091ec5a115aaf5b1a5ae6 Mon Sep 17 00:00:00 2001
From: Anthony Liatsis 
Date: Thu, 17 Dec 2015 15:00:41 -0800
Subject: [PATCH 0144/2240] add subdocs of single nested first for proper hook
 order

---
 lib/document.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/document.js b/lib/document.js
index 943fe53dd5a..88c602e5e9a 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -1631,8 +1631,8 @@ Document.prototype.$__getAllSubdocs = function() {
 
     if (val instanceof Embedded) seed.push(val);
     if (val && val.$isSingleNested) {
-      seed.push(val);
       seed = Object.keys(val._doc).reduce(docReducer.bind(val._doc), seed);
+      seed.push(val);
     }
     if (val && val.isMongooseDocumentArray) {
       val.forEach(function _docReduce(doc) {

From daa7ab70fb8817b8b811fe2b092462874a74344a Mon Sep 17 00:00:00 2001
From: Richard Bateman 
Date: Thu, 17 Dec 2015 18:39:27 -0700
Subject: [PATCH 0145/2240] Finish fixing #3685 - support 'replSet' as well as
 'replset' for connect options

---
 lib/drivers/node-mongodb-native/connection.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js
index c6c9517603b..188d6b61988 100644
--- a/lib/drivers/node-mongodb-native/connection.js
+++ b/lib/drivers/node-mongodb-native/connection.js
@@ -232,7 +232,7 @@ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) {
   o.db || (o.db = {});
   o.auth || (o.auth = {});
   o.server || (o.server = {});
-  o.replset || (o.replset = {});
+  o.replset || (o.replset = o.replSet) || (o.replset = {});
   o.server.socketOptions || (o.server.socketOptions = {});
   o.replset.socketOptions || (o.replset.socketOptions = {});
 

From 144ebc736aaf107b7a3d9a23ec191cccb7fd07d9 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 17 Dec 2015 21:59:15 -0500
Subject: [PATCH 0146/2240] now working on 4.3.3

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index b20bbf61242..4195c71039d 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.2",
+  "version": "4.3.3-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From 82dd4db4dbe50f7530aab9d37c7b01232d169d73 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 18 Dec 2015 11:44:55 -0500
Subject: [PATCH 0147/2240] chore: release 4.3.3

---
 History.md      | 5 +++++
 bin/mongoose.js | 2 +-
 package.json    | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/History.md b/History.md
index fc9e97b4b78..d134a1cfb5a 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,8 @@
+4.3.3 / 2015-12-18
+==================
+ * fix(connection): properly support 'replSet' as well as 'replset' #3688 [taxilian](https://github.com/taxilian)
+ * fix(document): single nested doc pre hooks called before nested doc array #3687 [aliatsis](https://github.com/aliatsis)
+
 4.3.2 / 2015-12-17
 ==================
  * fix(document): .set() into single nested schemas #3686
diff --git a/bin/mongoose.js b/bin/mongoose.js
index 88ca4c00d0d..fb852a714b8 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -2084,8 +2084,8 @@ Document.prototype.$__getAllSubdocs = function() {
 
     if (val instanceof Embedded) seed.push(val);
     if (val && val.$isSingleNested) {
-      seed.push(val);
       seed = Object.keys(val._doc).reduce(docReducer.bind(val._doc), seed);
+      seed.push(val);
     }
     if (val && val.isMongooseDocumentArray) {
       val.forEach(function _docReduce(doc) {
diff --git a/package.json b/package.json
index 4195c71039d..8cccd8d340a 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.3-pre",
+  "version": "4.3.3",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From e1320dac5b15b30fd63235541806e7ffb81b2597 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 18 Dec 2015 11:48:39 -0500
Subject: [PATCH 0148/2240] chore: now working on 4.3.4

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 8cccd8d340a..ae4df75bc58 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.3",
+  "version": "4.3.4-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From c65d0a9d7afcfeec84e6ae5f7c38f2edb31ca1f5 Mon Sep 17 00:00:00 2001
From: Olivier Louvignes 
Date: Sat, 19 Dec 2015 19:20:32 +0100
Subject: [PATCH 0149/2240] fix(schema): add duck-typing to support
 cross-modules schema definitions (fixes #3690)

---
 lib/browserDocument.js | 2 +-
 lib/connection.js      | 6 +++---
 lib/index.js           | 4 ++--
 lib/model.js           | 2 +-
 lib/schema.js          | 1 +
 test/schema.test.js    | 6 ++++++
 6 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/lib/browserDocument.js b/lib/browserDocument.js
index ed23af3c40c..09bc5857098 100644
--- a/lib/browserDocument.js
+++ b/lib/browserDocument.js
@@ -28,7 +28,7 @@ function Document(obj, schema, fields, skipId, skipInit) {
     return new Document( obj, schema, fields, skipId, skipInit );
 
 
-  if (utils.isObject(schema) && !(schema instanceof Schema)) {
+  if (utils.isObject(schema) && !schema.instanceOfSchema) {
     schema = new Schema(schema);
   }
 
diff --git a/lib/connection.js b/lib/connection.js
index b10293deeb0..60bce2c0883 100644
--- a/lib/connection.js
+++ b/lib/connection.js
@@ -619,13 +619,13 @@ Connection.prototype.model = function(name, schema, collection) {
     schema = false;
   }
 
-  if (utils.isObject(schema) && !(schema instanceof Schema)) {
+  if (utils.isObject(schema) && !schema.instanceOfSchema) {
     schema = new Schema(schema);
   }
 
   if (this.models[name] && !collection) {
     // model exists but we are not subclassing with custom collection
-    if (schema instanceof Schema && schema != this.models[name].schema) {
+    if (schema && schema.instanceOfSchema && schema != this.models[name].schema) {
       throw new MongooseError.OverwriteModelError(name);
     }
     return this.models[name];
@@ -634,7 +634,7 @@ Connection.prototype.model = function(name, schema, collection) {
   var opts = { cache: false, connection: this };
   var model;
 
-  if (schema instanceof Schema) {
+  if (schema && schema.instanceOfSchema) {
     // compile a model
     model = this.base.model(name, schema, collection, opts);
 
diff --git a/lib/index.js b/lib/index.js
index fd6e63a81ad..5f714bd1df1 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -307,7 +307,7 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
     schema = false;
   }
 
-  if (utils.isObject(schema) && !(schema instanceof Schema)) {
+  if (utils.isObject(schema) && !(schema.instanceOfSchema)) {
     schema = new Schema(schema);
   }
 
@@ -342,7 +342,7 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
   // connection.model() may be passing a different schema for
   // an existing model name. in this case don't read from cache.
   if (this.models[name] && false !== options.cache) {
-    if (schema instanceof Schema && schema != this.models[name].schema) {
+    if (schema && schema.instanceOfSchema && schema != this.models[name].schema) {
       throw new mongoose.Error.OverwriteModelError(name);
     }
 
diff --git a/lib/model.js b/lib/model.js
index f8d9b08cf4e..04f090b23b4 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -775,7 +775,7 @@ Model.prototype.model = function model(name) {
  */
 
 Model.discriminator = function discriminator(name, schema) {
-  if (!(schema instanceof Schema)) {
+  if (!(schema && schema.instanceOfSchema)) {
     throw new Error("You must pass a valid discriminator Schema");
   }
 
diff --git a/lib/schema.js b/lib/schema.js
index a0a41504849..d229f07a37e 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -186,6 +186,7 @@ function idGetter() {
  */
 Schema.prototype = Object.create( EventEmitter.prototype );
 Schema.prototype.constructor = Schema;
+Schema.prototype.instanceOfSchema = true;
 
 /**
  * Default middleware attached to a schema. Cannot be changed.
diff --git a/test/schema.test.js b/test/schema.test.js
index 0b80be8ccde..261646c3c98 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -98,6 +98,12 @@ describe('schema', function() {
     done();
   });
 
+  it('does expose a property for duck-typing instanceof', function(done) {
+    var schema = Schema({ name: String });
+    assert.ok(schema.instanceOfSchema);
+    done();
+  });
+
   it('supports different schematypes', function(done) {
     var Checkin = new Schema({
       date      : Date

From 99c3c642fd7f540090f04436b0e47828c73aa95b Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sat, 19 Dec 2015 14:42:37 -0500
Subject: [PATCH 0150/2240] docs: clarify that 3.8.x is no longer being
 developed

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 235c9ab8de8..384b7f06539 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ $ npm install mongoose
 
 ## Stability
 
-The current stable branch is [master](https://github.com/Automattic/mongoose/tree/master). The [3.8.x](https://github.com/Automattic/mongoose/tree/3.8.x) branch contains legacy support for the 3.x release series, which will continue to be actively maintained until September 1, 2015.
+The current stable branch is [master](https://github.com/Automattic/mongoose/tree/master). The [3.8.x](https://github.com/Automattic/mongoose/tree/3.8.x) branch contains legacy support for the 3.x release series, which is no longer under active development as of September 2015. The [3.8.x docs](http://mongoosejs.com/docs/3.8.x/) are still available.
 
 ## Overview
 

From 0998caa9da6ca728e81d4d8c44e00ee6d5fdb0e1 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sun, 20 Dec 2015 11:39:54 -0500
Subject: [PATCH 0151/2240] docs: fix #3697

---
 docs/index.jade | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/index.jade b/docs/index.jade
index c306bc442f2..2898cbb9d6f 100644
--- a/docs/index.jade
+++ b/docs/index.jade
@@ -38,8 +38,8 @@ html(lang='en')
         :js
           var db = mongoose.connection;
           db.on('error', console.error.bind(console, 'connection error:'));
-          db.once('open', function (callback) {
-            // yay!
+          db.once('open', function() {
+            // we're connected!
           });
         :markdown
           Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

From eeb7470e8313243c1875945b11ad5d244eac7c48 Mon Sep 17 00:00:00 2001
From: Olivier Louvignes 
Date: Mon, 21 Dec 2015 16:36:16 +0100
Subject: [PATCH 0152/2240] fix(schema): more duck-typing (fixes #3690)

---
 lib/schema.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/schema.js b/lib/schema.js
index d229f07a37e..5feec22016f 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -541,7 +541,7 @@ Schema.interpretAsType = function(path, obj, options) {
       ? obj.cast
       : type[0];
 
-    if (cast instanceof Schema) {
+    if (cast && cast.instanceOfSchema) {
       return new MongooseTypes.DocumentArray(path, cast, obj);
     }
 
@@ -565,7 +565,7 @@ Schema.interpretAsType = function(path, obj, options) {
     return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj);
   }
 
-  if (type instanceof Schema) {
+  if (type && type.instanceOfSchema) {
     return new MongooseTypes.Embedded(type, path, obj);
   }
 

From 69ee16fdb54055b8bb9e000895c62d9943f2696c Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 21 Dec 2015 11:16:12 -0500
Subject: [PATCH 0153/2240] docs: clarify _id schema option (Fix #3638)

---
 docs/guide.jade | 39 ++++++++++++++++-----------------------
 1 file changed, 16 insertions(+), 23 deletions(-)

diff --git a/docs/guide.jade b/docs/guide.jade
index da5a8a36515..d3de6564737 100644
--- a/docs/guide.jade
+++ b/docs/guide.jade
@@ -331,9 +331,15 @@ block content
 
   h4#_id option: _id
   :markdown
-    Mongoose assigns each of your schemas an `_id` field by default if one is not passed into the [Schema](/docs/api.html#schema-js) constructor. The type assigned is an [ObjectId](/docs/api.html#schema_Schema.Types) to coincide with MongoDBs default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option.
-
-    Pass this option *during schema construction* to prevent documents from getting an `_id` created by Mongoose (parent documents will still have an `_id` created by MongoDB when inserted). _Passing the option later using `Schema.set('_id', false)` will not work. See issue [#1512](https://github.com/Automattic/mongoose/issues/1512)._
+    Mongoose assigns each of your schemas an `_id` field by default if one
+    is not passed into the [Schema](/docs/api.html#schema-js) constructor.
+    The type assigned is an [ObjectId](/docs/api.html#schema_Schema.Types)
+    to coincide with MongoDB's default behavior. If you don't want an `_id`
+    added to your schema at all, you may disable it using this option.
+    
+    You can **only** use this option on sub-documents. Mongoose can't
+    save a document without knowing its id, so you will get an error if
+    you try to save a document without an `_id`.
   :js
     // default behavior
     var schema = new Schema({ name: String });
@@ -342,27 +348,14 @@ block content
     console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
 
     // disabled _id
-    var schema = new Schema({ name: String }, { _id: false });
-
-    // Don't set _id to false after schema construction as in
-    // var schema = new Schema({ name: String });
-    // schema.set('_id', false);
-
-    var Page = mongoose.model('Page', schema);
-    var p = new Page({ name: 'mongodb.org' });
-    console.log(p); // { name: 'mongodb.org' }
-
-    // MongoDB will create the _id when inserted
-    p.save(function (err) {
-      if (err) return handleError(err);
-      Page.findById(p, function (err, doc) {
-        if (err) return handleError(err);
-        console.log(doc); // { name: 'mongodb.org', _id: '50341373e894ad16347efe12' }
-      })
-    })
+    var childSchema = new Schema({ name: String }, { _id: false });
+    var parentSchema = new Schema({ children: [childSchema] });
 
-  :markdown
-    Note that currently you must disable the `_id` 
+    var Model = mongoose.model('Model', parentSchema);
+    
+    Model.create({ children: [{ name: 'Luke' }] }, function(error, doc) {
+      // doc.children[0]._id will be undefined
+    });
 
   h4#minimize option: minimize
   :markdown

From 370e11dd52e73d7df041262fdda7410c57f7bb39 Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Tue, 22 Dec 2015 08:42:22 -0700
Subject: [PATCH 0154/2240] general linting

---
 lib/schema.js         |  2 --
 lib/schema/number.js  | 12 ------------
 test/document.test.js |  1 -
 3 files changed, 15 deletions(-)

diff --git a/lib/schema.js b/lib/schema.js
index 5feec22016f..236665c0b5b 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -9,7 +9,6 @@ var utils = require('./utils');
 var MongooseTypes;
 var Kareem = require('kareem');
 var async = require('async');
-var PromiseProvider = require('./promise_provider');
 
 var IS_QUERY_HOOK = {
   count: true,
@@ -244,7 +243,6 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
     hook: 'save',
     isAsync: true,
     fn: function(next, done) {
-      var Promise = PromiseProvider.get();
       var subdocs = this.$__getAllSubdocs();
 
       if (!subdocs.length || this.$__preSavingFromParent) {
diff --git a/lib/schema/number.js b/lib/schema/number.js
index 24f07468357..ca7dedb2636 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -240,18 +240,6 @@ function handleArray(val) {
   });
 }
 
-function handleBitwiseOperator(val) {
-  var _this = this;
-  if (Array.isArray(val)) {
-    return val.map(function(v) { return _this.cast(v); });
-  } else if (Buffer.isBuffer(val)) {
-    return val;
-  } else {
-    // Assume trying to cast to number
-    return this.cast(val);
-  }
-}
-
 SchemaNumber.prototype.$conditionalHandlers =
   utils.options(SchemaType.prototype.$conditionalHandlers, {
     '$bitsAllClear': handleBitwiseOperator,
diff --git a/test/document.test.js b/test/document.test.js
index 443af72c03b..c6b1b37f486 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -2200,7 +2200,6 @@ describe('document', function() {
 
   it('single embedded docs .set() (gh-3686)', function(done) {
     var db = start();
-    var postHookCalls = [];
     var personSchema = new Schema({ name: String, realName: String });
 
     var bandSchema = new Schema({

From 08c12ad57cb86f4146880652ed0883bace5f40cd Mon Sep 17 00:00:00 2001
From: Ivan Maeder 
Date: Tue, 22 Dec 2015 17:18:31 +0100
Subject: [PATCH 0155/2240] Fix typo

Changed "suite your needs" to "suit your needs."
---
 docs/validation.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/validation.jade b/docs/validation.jade
index ef299325542..128e3f9c93f 100644
--- a/docs/validation.jade
+++ b/docs/validation.jade
@@ -23,7 +23,7 @@ block content
     Each of the validator links above provide more information about how to enable them as well as customize their associated error messages.
   h3#customized Custom validators
   :markdown
-    If the built-in validators aren't enough, validation can be completely tailored to suite your needs.
+    If the built-in validators aren't enough, validation can be completely tailored to suit your needs.
 
     Custom validation is declared by passing a validation function.
     You can find detailed instructions on how to do this in the

From 11114c2d94748ea4094e4eacea975b133fdca91a Mon Sep 17 00:00:00 2001
From: Bryant Chou 
Date: Wed, 23 Dec 2015 09:31:06 -0800
Subject: [PATCH 0156/2240] Update mongo driver to 2.1.2 - fixes No primary
 server available errors

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index ae4df75bc58..6e77ef5f95d 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
     "bson": "0.4.19",
     "hooks-fixed": "1.1.0",
     "kareem": "1.0.1",
-    "mongodb": "2.1.0",
+    "mongodb": "2.1.2",
     "mpath": "0.1.1",
     "mpromise": "0.5.4",
     "mquery": "1.6.3",

From d7c10cbac3dc5208661a12289b33d626321a502e Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 23 Dec 2015 16:58:19 -0500
Subject: [PATCH 0157/2240] chore: release 4.3.4

---
 History.md      | 10 ++++++++++
 bin/mongoose.js | 23 +++++------------------
 package.json    |  2 +-
 3 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/History.md b/History.md
index d134a1cfb5a..71126f9c4b4 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,13 @@
+4.3.4 / 2015-12-23
+==================
+ * fix: upgrade mongodb driver to 2.1.2 for repl set error #3712 [sansmischevia](https://github.com/sansmischevia)
+ * docs: validation docs typo #3709 [ivanmaeder](https://github.com/ivanmaeder)
+ * style: remove unused variables #3708 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix(schema): duck-typing for schemas #3703 [mgcrea](https://github.com/mgcrea)
+ * docs: connection sample code issue #3697
+ * fix(schema): duck-typing for schemas #3693 [mgcrea](https://github.com/mgcrea)
+ * docs: clarify id schema option #3638
+
 4.3.3 / 2015-12-18
 ==================
  * fix(connection): properly support 'replSet' as well as 'replset' #3688 [taxilian](https://github.com/taxilian)
diff --git a/bin/mongoose.js b/bin/mongoose.js
index fb852a714b8..ce22a81e740 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -160,7 +160,7 @@ function Document(obj, schema, fields, skipId, skipInit) {
     return new Document( obj, schema, fields, skipId, skipInit );
 
 
-  if (utils.isObject(schema) && !(schema instanceof Schema)) {
+  if (utils.isObject(schema) && !schema.instanceOfSchema) {
     schema = new Schema(schema);
   }
 
@@ -3735,7 +3735,6 @@ var utils = require('./utils');
 var MongooseTypes;
 var Kareem = require('kareem');
 var async = require('async');
-var PromiseProvider = require('./promise_provider');
 
 var IS_QUERY_HOOK = {
   count: true,
@@ -3912,6 +3911,7 @@ function idGetter() {
  */
 Schema.prototype = Object.create( EventEmitter.prototype );
 Schema.prototype.constructor = Schema;
+Schema.prototype.instanceOfSchema = true;
 
 /**
  * Default middleware attached to a schema. Cannot be changed.
@@ -3969,7 +3969,6 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
     hook: 'save',
     isAsync: true,
     fn: function(next, done) {
-      var Promise = PromiseProvider.get();
       var subdocs = this.$__getAllSubdocs();
 
       if (!subdocs.length || this.$__preSavingFromParent) {
@@ -4266,7 +4265,7 @@ Schema.interpretAsType = function(path, obj, options) {
       ? obj.cast
       : type[0];
 
-    if (cast instanceof Schema) {
+    if (cast && cast.instanceOfSchema) {
       return new MongooseTypes.DocumentArray(path, cast, obj);
     }
 
@@ -4290,7 +4289,7 @@ Schema.interpretAsType = function(path, obj, options) {
     return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj);
   }
 
-  if (type instanceof Schema) {
+  if (type && type.instanceOfSchema) {
     return new MongooseTypes.Embedded(type, path, obj);
   }
 
@@ -5000,7 +4999,7 @@ Schema.Types = MongooseTypes = require('./schema/index');
 exports.ObjectId = MongooseTypes.ObjectId;
 
 }).call(this,require("buffer").Buffer)
-},{"./drivers":11,"./promise_provider":24,"./schema/index":32,"./utils":47,"./virtualtype":48,"async":49,"buffer":51,"events":55,"kareem":79}],26:[function(require,module,exports){
+},{"./drivers":11,"./schema/index":32,"./utils":47,"./virtualtype":48,"async":49,"buffer":51,"events":55,"kareem":79}],26:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -6722,18 +6721,6 @@ function handleArray(val) {
   });
 }
 
-function handleBitwiseOperator(val) {
-  var _this = this;
-  if (Array.isArray(val)) {
-    return val.map(function(v) { return _this.cast(v); });
-  } else if (Buffer.isBuffer(val)) {
-    return val;
-  } else {
-    // Assume trying to cast to number
-    return this.cast(val);
-  }
-}
-
 SchemaNumber.prototype.$conditionalHandlers =
   utils.options(SchemaType.prototype.$conditionalHandlers, {
     '$bitsAllClear': handleBitwiseOperator,
diff --git a/package.json b/package.json
index 6e77ef5f95d..6707e1646a4 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.4-pre",
+  "version": "4.3.4",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From a49186b487f1bd310090ce0b5193ece3f9ad5362 Mon Sep 17 00:00:00 2001
From: dbkup 
Date: Mon, 28 Dec 2015 21:36:27 +0100
Subject: [PATCH 0158/2240] fix support for array pipeline with
 Aggregate#append

---
 lib/aggregate.js       |  4 +++-
 test/aggregate.test.js | 26 ++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/lib/aggregate.js b/lib/aggregate.js
index 2e6dd85f3c7..48df96470dd 100644
--- a/lib/aggregate.js
+++ b/lib/aggregate.js
@@ -83,7 +83,9 @@ Aggregate.prototype.model = function(model) {
  */
 
 Aggregate.prototype.append = function() {
-  var args = utils.args(arguments);
+  var args = (1 === arguments.length && util.isArray(arguments[0]))
+      ? arguments[0]
+      : utils.args(arguments);
 
   if (!args.every(isOperator)) {
     throw new Error("Arguments must be aggregate pipeline operators");
diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index 38209e13238..a04feb647b1 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -67,6 +67,18 @@ describe('aggregate: ', function() {
       done();
     });
 
+    it('supports array as single argument', function (done) {
+      var aggregate = new Aggregate();
+
+      assert.equal(aggregate.append([{$a: 1}, {$b: 2}, {$c: 3}]), aggregate);
+      assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}]);
+
+      aggregate.append([{$d: 4}, {$c: 5}]);
+      assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}, {$d: 4}, {$c: 5}]);
+
+      done();
+    });
+
     it('throws if non-operator parameter is passed', function(done) {
       var aggregate = new Aggregate(),
           regexp = /Arguments must be aggregate pipeline operators/;
@@ -83,6 +95,10 @@ describe('aggregate: ', function() {
         aggregate.append({ $a: 1 }, { a: 1 });
       }, regexp);
 
+      assert.throws(function () {
+        aggregate.append([{$a: 1}, {a: 1}]);
+      }, regexp);
+
       done();
     });
 
@@ -96,6 +112,16 @@ describe('aggregate: ', function() {
       done();
     });
 
+    it('does not throw when empty array is passed as single argument', function (done) {
+      var aggregate = new Aggregate();
+
+      assert.doesNotThrow(function () {
+        aggregate.append([]);
+      });
+
+      done();
+    });
+
     it('called from constructor', function(done) {
       var aggregate = new Aggregate({ $a: 1 }, { $b: 2 }, { $c: 3 });
       assert.deepEqual(aggregate._pipeline, [{ $a: 1 }, { $b: 2 }, { $c: 3 }]);

From cd411fb95caff8a3ce330b8dc255b7676b317d76 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sun, 3 Jan 2016 16:30:06 -0500
Subject: [PATCH 0159/2240] docs: Remove +1 comments from contributing.md

---
 CONTRIBUTING.md | 2 --
 1 file changed, 2 deletions(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b3386ba83fd..e930875e476 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,14 +8,12 @@ If you have a question about Mongoose (not a bug report) please post it to eithe
   - Please describe the issue you are experiencing, along with any associated stack trace.
   - Please post code that reproduces the issue, the version of mongoose, node version, and mongodb version.
   - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. 
-  - In general, adding a "+1" comment to an existing issue does little to help get it resolved. A better way is to submit a well documented pull request with clean code and passing tests.
 
 ### Requesting new features
 
 - Before opening a new issue, look for existing [issues](https://github.com/learnboost/mongoose/issues) to avoid duplication. If the issue does not yet exist, [create one](https://github.com/learnboost/mongoose/issues/new).
 - Please describe a use case for it
 - it would be ideal to include test cases as well
-- In general, adding a "+1" comment to an existing issue does little to help get it resolved. A better way is to submit a well documented pull request with clean code and passing tests.
 
 ### Fixing bugs / Adding features
 

From 71e8a1077622777aab8406cca8fe13379ab850f0 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 4 Jan 2016 10:28:09 -0500
Subject: [PATCH 0160/2240] docs(compatibility): clarify 3.2 support re: #3656

---
 docs/compatibility.jade | 1 +
 1 file changed, 1 insertion(+)

diff --git a/docs/compatibility.jade b/docs/compatibility.jade
index e8f0f775e4e..5953967a684 100644
--- a/docs/compatibility.jade
+++ b/docs/compatibility.jade
@@ -16,3 +16,4 @@ block content
     * MongoDB Server 2.4.x: mongoose `~3.8`, `4.x`
     * MongoDB Server 2.6.x: mongoose `~3.8.8`, `4.x`
     * MongoDB Server 3.0.x: mongoose `~3.8.22`, `4.x`
+    * MongoDB Server 3.2.x: mongoose `>=4.3.0`

From 79a16b06f1237bb6b466f50454176bde6a63103f Mon Sep 17 00:00:00 2001
From: dbkup 
Date: Mon, 4 Jan 2016 17:59:20 +0100
Subject: [PATCH 0161/2240] backport Aggregate#append fix for arrays from
 master

---
 lib/aggregate.js       |  4 +++-
 test/aggregate.test.js | 26 ++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/lib/aggregate.js b/lib/aggregate.js
index 4efd40f2be4..f1dfbd71f2a 100644
--- a/lib/aggregate.js
+++ b/lib/aggregate.js
@@ -265,7 +265,9 @@ Aggregate.prototype.near = function (arg) {
  */
 
 Aggregate.prototype.unwind = function () {
-  var args = utils.args(arguments);
+  var args = (1 === arguments.length && util.isArray(arguments[0]))
+      ? arguments[0]
+      : utils.args(arguments);
 
   return this.append.apply(this, args.map(function (arg) {
     return { $unwind: '$' + arg };
diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index 03f08477d2f..880ef90790c 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -65,6 +65,18 @@ describe('aggregate', function() {
       done();
     });
 
+    it('supports array as single argument', function (done) {
+      var aggregate = new Aggregate();
+
+      assert.equal(aggregate.append([{$a: 1}, {$b: 2}, {$c: 3}]), aggregate);
+      assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}]);
+
+      aggregate.append([{$d: 4}, {$c: 5}]);
+      assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}, {$d: 4}, {$c: 5}]);
+
+      done();
+    });
+
     it('throws if non-operator parameter is passed', function(done) {
       var aggregate = new Aggregate()
         , regexp = /Arguments must be aggregate pipeline operators/;
@@ -81,6 +93,10 @@ describe('aggregate', function() {
         aggregate.append({ $a: 1 }, { a: 1 });
       }, regexp);
 
+      assert.throws(function () {
+        aggregate.append([{$a: 1}, {a: 1}]);
+      }, regexp);
+
       done();
     });
 
@@ -94,6 +110,16 @@ describe('aggregate', function() {
       done();
     });
 
+    it('does not throw when empty array is passed as single argument', function (done) {
+      var aggregate = new Aggregate();
+
+      assert.doesNotThrow(function () {
+        aggregate.append([]);
+      });
+
+      done();
+    });
+
     it('called from constructor', function(done) {
       var aggregate = new Aggregate({ $a: 1 }, { $b: 2 }, { $c: 3 });
       assert.deepEqual(aggregate._pipeline, [{ $a: 1 }, { $b: 2 }, { $c: 3 }]);

From 78f727a74632e6e2af3d2563f8257b2a0919a1ab Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 4 Jan 2016 13:08:34 -0500
Subject: [PATCH 0162/2240] chore: now working on 4.3.5

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 6707e1646a4..144a4747ed8 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.4",
+  "version": "4.3.5-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From 1c3dcffcb52ef4a91f3c7cdc53dc13f37d14527e Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 4 Jan 2016 13:14:58 -0500
Subject: [PATCH 0163/2240] fix(drivers): debug prints 0 correctly (Fix #3689)

---
 lib/drivers/node-mongodb-native/collection.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js
index 815e8bd53b3..d65b805236f 100644
--- a/lib/drivers/node-mongodb-native/collection.js
+++ b/lib/drivers/node-mongodb-native/collection.js
@@ -174,7 +174,7 @@ NativeCollection.prototype.$format = function(arg) {
 function format(obj, sub) {
   var x = utils.clone(obj, { retainKeyOrder: 1 });
   var representation;
-  if (x) {
+  if (x != null) {
     if ('Binary' === x.constructor.name) {
       x = '[object Buffer]';
     } else if ('ObjectID' === x.constructor.name) {

From ede06fc6231ca5062c0bcd4e03021dc997604705 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 4 Jan 2016 13:28:53 -0500
Subject: [PATCH 0164/2240] docs(api): show schema constructors in docs (Fix
 #3700)

---
 lib/document.js             | 1 -
 lib/schema/array.js         | 4 ++--
 lib/schema/boolean.js       | 4 ++--
 lib/schema/buffer.js        | 4 ++--
 lib/schema/date.js          | 4 ++--
 lib/schema/documentarray.js | 4 ++--
 lib/schema/embedded.js      | 2 +-
 lib/schema/mixed.js         | 4 ++--
 lib/schema/number.js        | 4 ++--
 lib/schema/objectid.js      | 4 ++--
 lib/schema/string.js        | 4 ++--
 11 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index 88c602e5e9a..3305fcd6347 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -915,7 +915,6 @@ Document.prototype.isModified = function(path) {
  *
  * @param {String} [path]
  * @return {Boolean}
- * @method $isDefault
  * @api public
  */
 
diff --git a/lib/schema/array.js b/lib/schema/array.js
index 945fb2debb9..e78ac0300fd 100644
--- a/lib/schema/array.js
+++ b/lib/schema/array.js
@@ -26,7 +26,7 @@ var SchemaType = require('../schematype'),
  * @param {SchemaType} cast
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaArray(key, cast, options) {
@@ -81,7 +81,7 @@ function SchemaArray(key, cast, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaArray.schemaName = 'Array';
 
diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js
index 971ab157dc1..5a296ed1efa 100644
--- a/lib/schema/boolean.js
+++ b/lib/schema/boolean.js
@@ -12,7 +12,7 @@ var SchemaType = require('../schematype');
  * @param {String} path
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaBoolean(path, options) {
@@ -23,7 +23,7 @@ function SchemaBoolean(path, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaBoolean.schemaName = 'Boolean';
 
diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js
index c46da0494d9..d26cc339b7c 100644
--- a/lib/schema/buffer.js
+++ b/lib/schema/buffer.js
@@ -18,7 +18,7 @@ var Document;
  * @param {String} key
  * @param {SchemaType} cast
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaBuffer(key, options) {
@@ -29,7 +29,7 @@ function SchemaBuffer(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaBuffer.schemaName = 'Buffer';
 
diff --git a/lib/schema/date.js b/lib/schema/date.js
index 57d36e9ab16..6c0d4ff862e 100644
--- a/lib/schema/date.js
+++ b/lib/schema/date.js
@@ -15,7 +15,7 @@ var CastError = SchemaType.CastError;
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaDate(key, options) {
@@ -26,7 +26,7 @@ function SchemaDate(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaDate.schemaName = 'Date';
 
diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js
index 34c31c128f6..59ce05c7efb 100644
--- a/lib/schema/documentarray.js
+++ b/lib/schema/documentarray.js
@@ -17,7 +17,7 @@ var Subdocument = require('../types/embedded');
  * @param {Schema} schema
  * @param {Object} options
  * @inherits SchemaArray
- * @api private
+ * @api public
  */
 
 function DocumentArray(key, schema, options) {
@@ -58,7 +58,7 @@ function DocumentArray(key, schema, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 DocumentArray.schemaName = 'DocumentArray';
 
diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js
index bd42df74f9a..8ac808d8091 100644
--- a/lib/schema/embedded.js
+++ b/lib/schema/embedded.js
@@ -10,7 +10,7 @@ module.exports = Embedded;
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function Embedded(schema, path, options) {
diff --git a/lib/schema/mixed.js b/lib/schema/mixed.js
index ff2173a0675..0963a217b23 100644
--- a/lib/schema/mixed.js
+++ b/lib/schema/mixed.js
@@ -12,7 +12,7 @@ var utils = require('../utils');
  * @param {String} path
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function Mixed(path, options) {
@@ -38,7 +38,7 @@ function Mixed(path, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 Mixed.schemaName = 'Mixed';
 
diff --git a/lib/schema/number.js b/lib/schema/number.js
index ca7dedb2636..2ddb1a3d0b0 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -15,7 +15,7 @@ var Document;
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaNumber(key, options) {
@@ -26,7 +26,7 @@ function SchemaNumber(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaNumber.schemaName = 'Number';
 
diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js
index 26f6621c175..6907fc1dfbe 100644
--- a/lib/schema/objectid.js
+++ b/lib/schema/objectid.js
@@ -16,7 +16,7 @@ var SchemaType = require('../schematype'),
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function ObjectId(key, options) {
@@ -27,7 +27,7 @@ function ObjectId(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 ObjectId.schemaName = 'ObjectId';
 
diff --git a/lib/schema/string.js b/lib/schema/string.js
index 33210dbbdc4..210b27cc7d9 100644
--- a/lib/schema/string.js
+++ b/lib/schema/string.js
@@ -15,7 +15,7 @@ var Document;
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaString(key, options) {
@@ -28,7 +28,7 @@ function SchemaString(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaString.schemaName = 'String';
 

From c112f98a41fd09af245ef8511bf8c77c763b0b0f Mon Sep 17 00:00:00 2001
From: dbkup 
Date: Mon, 4 Jan 2016 22:45:57 +0100
Subject: [PATCH 0165/2240] fix erroneous change

---
 lib/aggregate.js | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/lib/aggregate.js b/lib/aggregate.js
index f1dfbd71f2a..306f7967462 100644
--- a/lib/aggregate.js
+++ b/lib/aggregate.js
@@ -80,8 +80,9 @@ Aggregate.prototype.bind = function (model) {
  */
 
 Aggregate.prototype.append = function () {
-  var args = utils.args(arguments)
-    , arg;
+  var args = (1 === arguments.length && util.isArray(arguments[0]))
+      ? arguments[0]
+      : utils.args(arguments);
 
   if (!args.every(isOperator)) {
     throw new Error("Arguments must be aggregate pipeline operators");
@@ -265,14 +266,12 @@ Aggregate.prototype.near = function (arg) {
  */
 
 Aggregate.prototype.unwind = function () {
-  var args = (1 === arguments.length && util.isArray(arguments[0]))
-      ? arguments[0]
-      : utils.args(arguments);
+  var args = utils.args(arguments);
 
   return this.append.apply(this, args.map(function (arg) {
     return { $unwind: '$' + arg };
   }));
-}
+};
 
 /**
  * Appends a new $sort operator to this aggregate pipeline.

From 8ba135555325d5e3cd42784a51465cc8346cc775 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 4 Jan 2016 18:02:41 -0500
Subject: [PATCH 0166/2240] tests(schema): repro #3701

---
 test/schema.documentarray.test.js | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/test/schema.documentarray.test.js b/test/schema.documentarray.test.js
index 37811fe8e80..6bbaf56846b 100644
--- a/test/schema.documentarray.test.js
+++ b/test/schema.documentarray.test.js
@@ -32,4 +32,22 @@ describe('schema.documentarray', function() {
     });
     done();
   });
+
+  it('only sets if document has same schema (gh-3701)', function(done) {
+    var schema1 = new Schema({
+      arr: [new Schema({ a: Number, b: Number }, { _id: false })]
+    });
+    var schema2 = new Schema({
+      arr: [new Schema({ a: Number }, { _id: false })]
+    });
+
+    var Model1 = mongoose.model('gh3701_0', schema1);
+    var Model2 = mongoose.model('gh3701_1', schema2);
+
+    var source = new Model1({ arr: [{ a: 1, b: 1 }, { a: 2, b: 2 }] });
+    var dest = new Model2({ arr: source.arr });
+
+    assert.deepEqual(dest.toObject().arr, [{ a: 1 }, { a: 2 }]);
+    done();
+  });
 });

From 525e6749fbd085ed68deb739429cbbfb5116fd7c Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 4 Jan 2016 18:04:16 -0500
Subject: [PATCH 0167/2240] fix: handle setting documentarray of wrong type
 (Fix #3701)

---
 lib/schema/documentarray.js | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js
index 59ce05c7efb..3cce0d4ea83 100644
--- a/lib/schema/documentarray.js
+++ b/lib/schema/documentarray.js
@@ -39,7 +39,6 @@ function DocumentArray(key, schema, options) {
     EmbeddedDocument[i] = schema.statics[i];
 
   EmbeddedDocument.options = options;
-  this.schema = schema;
 
   ArrayType.call(this, key, EmbeddedDocument, options);
 
@@ -182,6 +181,14 @@ DocumentArray.prototype.cast = function(value, doc, init, prev) {
   i = value.length;
 
   while (i--) {
+    if (!value[i]) {
+      continue;
+    }
+    // Check if the document has a different schema (re gh-3701)
+    if ((value[i] instanceof Subdocument) &&
+        value[i].schema !== this.casterConstructor.schema) {
+      value[i] = value[i].toObject({ virtuals: false });
+    }
     if (!(value[i] instanceof Subdocument) && value[i]) {
       if (init) {
         selected || (selected = scopePaths(this, doc.$__.selected, init));

From 4c022036db18b2c5c6454f8770c33e0f70e67c8f Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 5 Jan 2016 15:14:32 -0500
Subject: [PATCH 0168/2240] test: repro #3702

---
 test/document.test.js | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/test/document.test.js b/test/document.test.js
index c6b1b37f486..dad622ad0a1 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -2250,6 +2250,21 @@ describe('document', function() {
     });
   });
 
+  it('nested single embedded doc validation (gh-3702)', function(done) {
+    var db = start();
+    var childChildSchema = Schema({ count: { type: Number, min: 1 } });
+    var childSchema = new Schema({ child: childChildSchema });
+    var parentSchema = new Schema({ child: childSchema });
+
+    var Parent = db.model('gh3702', parentSchema);
+    var obj = { child: { child: { count: 0 } } };
+    Parent.create(obj, function(error) {
+      assert.ok(error);
+      assert.ok(/ValidationError/.test(error.toString()));
+      db.close(done);
+    });
+  });
+
   it('handles virtuals with dots correctly (gh-3618)', function(done) {
     var db = start();
     var testSchema = new Schema({ nested: { type: Object, default: {} } });

From f589e5f0bdb3237bc4c47f379cd2d27a1927777d Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 5 Jan 2016 15:15:04 -0500
Subject: [PATCH 0169/2240] fix(schema): pull singleNestedPaths up from subdocs
 (Fix #3702)

---
 lib/schema.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/schema.js b/lib/schema.js
index 236665c0b5b..ffed15c1a9e 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -500,6 +500,10 @@ Schema.prototype.path = function(path, obj) {
       this.singleNestedPaths[path + '.' + key] =
         this.paths[path].schema.paths[key];
     }
+    for (var key in this.paths[path].schema.singleNestedPaths) {
+      this.singleNestedPaths[path + '.' + key] =
+        this.paths[path].schema.singleNestedPaths[key];
+    }
   }
   return this;
 };

From 258091bdaeeeb9171cb82329d9bebe215440c58c Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 5 Jan 2016 15:22:52 -0500
Subject: [PATCH 0170/2240] docs(api): clarify callback for mongoose.connect()
 (Fix #3705)

---
 lib/index.js | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/lib/index.js b/lib/index.js
index 5f714bd1df1..9f2916c1a7f 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -192,7 +192,9 @@ Mongoose.prototype.createConnection = function(uri, options) {
 /**
  * Opens the default mongoose connection.
  *
- * If arguments are passed, they are proxied to either [Connection#open](#connection_Connection-open) or [Connection#openSet](#connection_Connection-openSet) appropriately.
+ * If arguments are passed, they are proxied to either
+ * [Connection#open](#connection_Connection-open) or
+ * [Connection#openSet](#connection_Connection-openSet) appropriately.
  *
  * _Options passed take precedence over options included in connection strings._
  *
@@ -212,6 +214,12 @@ Mongoose.prototype.createConnection = function(uri, options) {
  *     var opts = { mongos: true };
  *     mongoose.connect(uri, opts);
  *
+ *     // optional callback that gets fired when initial connection completed
+ *     var uri = 'mongodb://nonexistent.domain:27000';
+ *     mongoose.connect(uri, function(error) {
+ *       // if error is truthy, the initial connection failed.
+ *     })
+ *
  * @param {String} uri(s)
  * @param {Object} [options]
  * @param {Function} [callback]

From bcec765007ebc7bc50a9de32ba548ad7599c12e5 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 5 Jan 2016 19:11:57 -0500
Subject: [PATCH 0171/2240] test: repro #3721

---
 test/document.modified.test.js | 62 +++++++++++++++++++++++++++-------
 1 file changed, 50 insertions(+), 12 deletions(-)

diff --git a/test/document.modified.test.js b/test/document.modified.test.js
index ba4f5d12a39..98d2c0bcd3d 100644
--- a/test/document.modified.test.js
+++ b/test/document.modified.test.js
@@ -382,25 +382,63 @@ describe('document modified', function() {
       db.close(done);
     });
 
-    it('gh-1530 for arrays (gh-3575)', function(done) {
-      var db = start();
+    describe('manually populating arrays', function() {
+      var db;
 
-      var parentSchema = new Schema({
-        name: String,
-        children: [{ type: Schema.Types.ObjectId, ref: 'Child' }]
+      before(function() {
+        db = start();
       });
 
-      var Parent = db.model('Parent', parentSchema, 'parents');
-      var Child = db.model('Child', parentSchema, 'children');
+      after(function(done) {
+        db.close(done);
+      });
 
-      var child = new Child({ name: 'Luke' });
-      var p = new Parent({ name: 'Anakin', children: [child] });
+      it('gh-1530 for arrays (gh-3575)', function(done) {
+        var parentSchema = new Schema({
+          name: String,
+          children: [{ type: Schema.Types.ObjectId, ref: 'Child' }]
+        });
 
-      assert.equal(p.children[0].name, 'Luke');
-      assert.ok(p.populated('children'));
-      db.close(done);
+        var Parent = db.model('Parent', parentSchema, 'parents');
+        var Child = db.model('Child', parentSchema, 'children');
+
+        var child = new Child({ name: 'Luke' });
+        var p = new Parent({ name: 'Anakin', children: [child] });
+
+        assert.equal(p.children[0].name, 'Luke');
+        assert.ok(p.populated('children'));
+        done();
+      });
+
+      it('setting nested arrays (gh-3721)', function(done) {
+        var userSchema = new Schema({
+          name: { type: Schema.Types.String }
+        });
+        var User = db.model('User', userSchema);
+
+        var accountSchema = new Schema({
+          roles: [{
+            name: { type: Schema.Types.String },
+            users: [{ type: Schema.Types.ObjectId, ref: 'User'}]
+          }]
+        });
+
+        var Account = db.model('Account', accountSchema);
+
+        var user = new User({ name: 'Test' });
+        var account = new Account({
+          roles: [
+            { name: 'test group', users: [user] }
+          ]
+        });
+
+        assert.ok(account.roles[0].users[0].isModified);
+        done();
+      });
     });
 
+
+
     it('should support setting mixed paths by string (gh-1418)', function(done) {
       var db = start();
       var BlogPost = db.model('1418', new Schema({ mixed: {} }));

From 82c9152c7abc99b4d955676e69da6aa97a9af6fb Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 5 Jan 2016 19:13:09 -0500
Subject: [PATCH 0172/2240] fix(document): manually populating arrays marks
 full path as populated (Fix #3721)

---
 lib/document.js | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index 3305fcd6347..c8cf2c9844d 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -627,8 +627,14 @@ Document.prototype.set = function(path, val, type, options) {
         val[0] instanceof Document &&
         val[0].constructor.modelName &&
         schema.options.type[0].ref === val[0].constructor.modelName) {
-      this.populated(path, val.map(function(v) { return v._id; }),
-        { model: val[0].constructor });
+      if (this.ownerDocument) {
+        this.ownerDocument().populated(this.$__fullPath(path),
+          val.map(function(v) { return v._id; }),
+          { model: val[0].constructor });
+      } else {
+        this.populated(path, val.map(function(v) { return v._id; }),
+          { model: val[0].constructor });
+      }
       didPopulate = true;
     }
     val = schema.applySetters(val, this, false, priorVal);

From b969b694846c6f96fead1113f25a1cfef07c775c Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 6 Jan 2016 10:07:15 -0500
Subject: [PATCH 0173/2240] docs(faq): add clarification re in-place date ops
 (Fix #3722)

---
 docs/faq.jade | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/docs/faq.jade b/docs/faq.jade
index b607104034e..f3704d1d612 100644
--- a/docs/faq.jade
+++ b/docs/faq.jade
@@ -10,7 +10,8 @@ block append style
 block content
   h2 FAQ
   :markdown
-    **Q**. Why don't my changes to arrays get saved when I update an element directly?
+    **Q**. Why don't my changes to arrays get saved when I update an element
+    directly?
   :js
     doc.array[3] = 'changed';
     doc.save();
@@ -25,6 +26,26 @@ block content
     doc.array[3] = 'changed';
     doc.markModified('array');
     doc.save();
+  hr#date_changes
+  :markdown
+    **Q**. Why don't in-place modifications to date objects
+    (e.g. `date.setMonth(1);`) get saved?
+  :js
+    doc.createdAt.setDate(2011, 5, 1);
+    doc.save(); // createdAt changes won't get saved!
+  :markdown
+    **A**. Mongoose currently doesn't watch for in-place updates to date
+    objects. If you have need for this feature, feel free to discuss on
+    [this GitHub issue](https://github.com/Automattic/mongoose/issues/3738).
+    There are several workarounds:
+  :js
+    doc.createdAt.setDate(2011, 5, 1);
+    doc.markModified('createdAt');
+    doc.save(); // Works
+  :js
+    doc.createdAt = new Date(2011, 5, 1).setHours(4);
+    doc.save(); // Works
+  
   hr#enable_debugging
   :markdown
     **Q**. How can I enable debugging?

From 9c6cd3b16b3ea1053b0f82b3816194572d68a00b Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 6 Jan 2016 14:07:49 -0500
Subject: [PATCH 0174/2240] test(validation): repro #3724

---
 test/model.update.test.js | 94 +++++++++++++++++++++++++--------------
 1 file changed, 60 insertions(+), 34 deletions(-)

diff --git a/test/model.update.test.js b/test/model.update.test.js
index aef9cf6fcc7..a6ab10205e3 100644
--- a/test/model.update.test.js
+++ b/test/model.update.test.js
@@ -1365,49 +1365,75 @@ describe('model: update:', function() {
       });
     });
 
-    it('embedded objects (gh-2733)', function(done) {
-      var db = start();
+    describe('objects and arrays', function() {
+      var db;
 
-      var bandSchema = new Schema({
-        singer: {
-          firstName: { type: String, enum: ['Axl'] },
-          lastName: { type: String, enum: ['Rose'] }
-        }
-      });
-      bandSchema.pre('update', function() {
-        this.options.runValidators = true;
+      before(function() {
+        db = start();
       });
-      var Band = db.model('gh2706', bandSchema, 'gh2706');
 
-      Band.update({}, { $set: { singer: { firstName: 'Not', lastName: 'Axl' } } }, function(err) {
-        assert.ok(err);
+      after(function(done) {
         db.close(done);
       });
-    });
 
-    it('handles document array validation (gh-2733)', function(done) {
-      var db = start();
+      it('embedded objects (gh-2706)', function(done) {
+        var bandSchema = new Schema({
+          singer: {
+            firstName: { type: String, enum: ['Axl'] },
+            lastName: { type: String, enum: ['Rose'] }
+          }
+        });
+        bandSchema.pre('update', function() {
+          this.options.runValidators = true;
+        });
+        var Band = db.model('gh2706', bandSchema, 'gh2706');
 
-      var member = new Schema({
-        name: String,
-        role: { type: String, required: true, enum: ['singer', 'guitar', 'drums', 'bass'] }
-      });
-      var band = new Schema({ members: [member], name: String });
-      var Band = db.model('band', band, 'bands');
-      var members = [
-        { name: 'Axl Rose', role: 'singer' },
-        { name: 'Slash', role: 'guitar' },
-        { name: 'Christopher Walken', role: 'cowbell' }
-      ];
-
-      Band.findOneAndUpdate(
-        { name: "Guns N' Roses" },
-        { $set: { members: members } },
-        { runValidators: true },
-        function(err) {
+        Band.update({}, { $set: { singer: { firstName: 'Not', lastName: 'Axl' } } }, function(err) {
           assert.ok(err);
-          db.close(done);
+          done();
         });
+      });
+
+      it('handles document array validation (gh-2733)', function(done) {
+        var member = new Schema({
+          name: String,
+          role: { type: String, required: true, enum: ['singer', 'guitar', 'drums', 'bass'] }
+        });
+        var band = new Schema({ members: [member], name: String });
+        var Band = db.model('band', band, 'bands');
+        var members = [
+          { name: 'Axl Rose', role: 'singer' },
+          { name: 'Slash', role: 'guitar' },
+          { name: 'Christopher Walken', role: 'cowbell' }
+        ];
+
+        Band.findOneAndUpdate(
+          { name: "Guns N' Roses" },
+          { $set: { members: members } },
+          { runValidators: true },
+          function(err) {
+            assert.ok(err);
+            done();
+          });
+      });
+
+      it('validators on arrays (gh-3724)', function(done) {
+        var schema = new Schema({
+          arr: [String]
+        });
+
+        schema.path('arr').validate(function(v) {
+          return false;
+        });
+
+        var M = db.model('gh3724', schema);
+        var options = { runValidators: true };
+        M.findOneAndUpdate({}, { arr: ['test'] }, options, function(error) {
+          assert.ok(error);
+          assert.ok(/ValidationError/.test(error.toString()));
+          done();
+        });
+      });
     });
   });
 

From e89227ac8c234ccfd2430f1e1367dcee87c5a006 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 6 Jan 2016 14:09:04 -0500
Subject: [PATCH 0175/2240] fix(validation): update validators handle array
 validation (Fix #3724)

---
 lib/schema/documentarray.js      | 14 +++++++++++---
 lib/services/updateValidators.js |  6 +++++-
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js
index 3cce0d4ea83..06b5fe5751a 100644
--- a/lib/schema/documentarray.js
+++ b/lib/schema/documentarray.js
@@ -73,7 +73,8 @@ DocumentArray.prototype.constructor = DocumentArray;
  * @api private
  */
 
-DocumentArray.prototype.doValidate = function(array, fn, scope) {
+DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
+  var _this = this;
   SchemaType.prototype.doValidate.call(this, array, function(err) {
     if (err) {
       return fn(err);
@@ -82,7 +83,12 @@ DocumentArray.prototype.doValidate = function(array, fn, scope) {
     var count = array && array.length;
     var error;
 
-    if (!count) return fn();
+    if (!count) {
+      return fn();
+    }
+    if (options && options.updateValidator) {
+      return fn();
+    }
 
     // handle sparse arrays, do not use array.forEach which does not
     // iterate over sparse elements yet reports array.length including
@@ -124,7 +130,9 @@ DocumentArray.prototype.doValidateSync = function(array, scope) {
   var count = array && array.length,
       resultError = null;
 
-  if (!count) return;
+  if (!count) {
+    return;
+  }
 
   // handle sparse arrays, do not use array.forEach which does not
   // iterate over sparse elements yet reports array.length including
diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js
index d921190ffb4..10dd734a9c9 100644
--- a/lib/services/updateValidators.js
+++ b/lib/services/updateValidators.js
@@ -128,7 +128,8 @@ module.exports = function(query, schema, castedDoc, options) {
               }
               callback(null);
             },
-            options && options.context === 'query' ? query : null);
+            options && options.context === 'query' ? query : null,
+            { updateValidator: true });
         });
       }
     })(i);
@@ -181,6 +182,9 @@ function flatten(update, path) {
       for (var k in flat) {
         result[k] = flat[k];
       }
+      if (Array.isArray(val)) {
+        result[path + key] = val;
+      }
     } else {
       result[path + key] = val;
     }

From 09af924358799fba3810f089fe0e8da26c8a1179 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 7 Jan 2016 09:42:47 -0500
Subject: [PATCH 0176/2240] docs: fix dead links (Fix #3727)

---
 docs/faq.jade   | 6 +++++-
 lib/document.js | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/docs/faq.jade b/docs/faq.jade
index f3704d1d612..68ecac9839f 100644
--- a/docs/faq.jade
+++ b/docs/faq.jade
@@ -16,7 +16,11 @@ block content
     doc.array[3] = 'changed';
     doc.save();
   :markdown
-    **A**. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to use [MongooseArray#set](./api.html#types_array_MongooseArray-set) available in **Mongoose >= 3.2.0**.
+    **A**. Mongoose doesn't create getters/setters for array indexes; without
+    them mongoose never gets notified of the change and so doesn't know to
+    persist the new value. The work-around is to use
+    [MongooseArray#set](./api.html#types_array_MongooseArray.set) available
+    in **Mongoose >= 3.2.0**.
   :js
     // 3.2.0
     doc.array.set(3, 'changed');
diff --git a/lib/document.js b/lib/document.js
index c8cf2c9844d..01c5807ffc8 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -251,7 +251,7 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) {
  *
  * @param {Object} doc document returned by mongo
  * @param {Function} fn callback
- * @api private
+ * @api public
  */
 
 Document.prototype.init = function(doc, opts, fn) {

From d959367fdebbfc9f28b562d693276722adc30e83 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 7 Jan 2016 10:10:39 -0500
Subject: [PATCH 0177/2240] fix(drivers): re-register events when db changes
 (Fix #3729)

---
 lib/drivers/node-mongodb-native/connection.js | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js
index 188d6b61988..e67c3eeddb7 100644
--- a/lib/drivers/node-mongodb-native/connection.js
+++ b/lib/drivers/node-mongodb-native/connection.js
@@ -128,8 +128,10 @@ NativeConnection.prototype.useDb = function(name) {
  */
 
 function listen(conn) {
-  if (conn._listening) return;
-  conn._listening = true;
+  if (conn.db._listening) {
+    return;
+  }
+  conn.db._listening = true;
 
   conn.db.on('close', function() {
     if (conn._closeCalled) return;

From 4384555c123f869d5b726708e63526e642b855b6 Mon Sep 17 00:00:00 2001
From: kasselTrankos 
Date: Thu, 7 Jan 2016 16:50:14 +0100
Subject: [PATCH 0178/2240] solve, error when passed a callback in updata, and
 that is not a function

---
 lib/query.js | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/lib/query.js b/lib/query.js
index 730f432a825..fbad6a8e6ab 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -2019,9 +2019,14 @@ Query.prototype.update = function(conditions, doc, options, callback) {
 
   var oldCb = callback;
   if (oldCb) {
-    callback = function(error, result) {
-      oldCb(error, result ? result.result : { ok: 0, n: 0, nModified: 0 });
-    };
+	if('function' === typeof oldCb){
+	  callback = function(error, result) {
+		oldCb(error, result ? result.result : { ok: 0, n: 0, nModified: 0 });
+	  };  
+	}else{		
+	  throw new Error('Invalid callback() argument.');
+	}	  
+    
   }
 
   // strict is an option used in the update checking, make sure it gets set

From 1ecbe406861e514c6b745bb1662f21e2d9c506a3 Mon Sep 17 00:00:00 2001
From: Mike Kusold 
Date: Thu, 7 Jan 2016 10:36:25 -0700
Subject: [PATCH 0179/2240] check for `$__` before using its `adhocPaths`

---
 lib/document.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/document.js b/lib/document.js
index 46a9009d674..d9608875669 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -732,7 +732,8 @@ Document.prototype.get = function (path, type) {
  */
 
 Document.prototype.$__path = function (path) {
-  var adhocs = this.$__.adhocPaths
+  var base = this.$__
+    , adhocs = (base) ? base.adhocPaths : undefined
     , adhocType = adhocs && adhocs[path];
 
   if (adhocType) {

From 4b60369c476095ad874b043675b050c03805b712 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 7 Jan 2016 15:50:36 -0500
Subject: [PATCH 0180/2240] test: repro #3734

---
 test/promise_provider.test.js | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js
index 57303a63033..35d7b21c659 100644
--- a/test/promise_provider.test.js
+++ b/test/promise_provider.test.js
@@ -325,6 +325,13 @@ describe('ES6 promises: ', function() {
         done();
       });
     });
+
+    it('Model.populate (gh-3734)', function(done) {
+      var doc = new MyModel({});
+      var promise = MyModel.populate(doc, 'test');
+      assert.equal(promise.constructor, bluebird);
+      done();
+    });
   });
 
   describe('q: ', function() {

From bc8bdfce42de1e46953ba07c08a24f97f8edd014 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 7 Jan 2016 15:51:47 -0500
Subject: [PATCH 0181/2240] fix(model): .populate() returns ES6 promise (Fix
 #3734)

---
 lib/document.js    | 12 ++-------
 lib/model.js       | 61 ++++++++++++++++++++++++++++++++--------------
 lib/query.js       |  3 +++
 lib/querystream.js |  1 +
 4 files changed, 49 insertions(+), 28 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index 01c5807ffc8..0c00a9237dc 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -2201,6 +2201,7 @@ Document.prototype.populate = function populate() {
   if (fn) {
     var paths = utils.object.vals(pop);
     this.$__.populate = undefined;
+    paths.__noPromise = true;
     this.constructor.populate(this, paths, fn);
   }
 
@@ -2240,16 +2241,7 @@ Document.prototype.populate = function populate() {
  */
 
 Document.prototype.execPopulate = function() {
-  var Promise = PromiseProvider.get();
-  var _this = this;
-  return new Promise.ES6(function(resolve, reject) {
-    _this.populate(function(error) {
-      if (error) {
-        return reject(error);
-      }
-      resolve(_this);
-    });
-  });
+  return this.populate(function() {});
 };
 
 /**
diff --git a/lib/model.js b/lib/model.js
index 04f090b23b4..7dc88077fd3 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -2326,44 +2326,69 @@ Model.geoSearch = function(conditions, options, callback) {
  */
 
 Model.populate = function(docs, paths, cb) {
-  var promise = new Promise(cb);
+  var _this = this;
 
-  // always resolve on nextTick for consistent async behavior
-  function resolve() {
-    var args = utils.args(arguments);
+  // normalized paths
+  var noPromise = paths && !!paths.__noPromise;
+  paths = utils.populate(paths);
 
-    process.nextTick(function() {
-      promise.resolve.apply(promise, args);
+  if (noPromise) {
+    _populate(this, docs, paths, cb);
+  } else {
+    var Promise = PromiseProvider.get();
+    return new Promise.ES6(function(resolve, reject) {
+      _populate(_this, docs, paths, function(error, docs) {
+        if (error) {
+          cb && cb(error);
+          reject(error);
+        } else {
+          cb && cb(null, docs);
+          resolve(docs);
+        }
+      });
     });
   }
+};
 
-  // normalized paths
-  paths = utils.populate(paths);
+/*!
+ * Populate helper
+ *
+ * @param {Model} model the model to use
+ * @param {Document|Array} docs Either a single document or array of documents to populate.
+ * @param {Object} paths
+ * @param {Function} [cb(err,doc)] Optional callback, executed upon completion. Receives `err` and the `doc(s)`.
+ * @return {Function}
+ * @api private
+ */
+
+function _populate(model, docs, paths, cb) {
   var pending = paths.length;
 
   if (0 === pending) {
-    resolve(null, docs);
-    return promise;
+    return cb(null, docs);
   }
 
   // each path has its own query options and must be executed separately
   var i = pending;
   var path;
-  var model = this;
   while (i--) {
     path = paths[i];
-    if ('function' === typeof path.model) model = path.model;
+    if ('function' === typeof path.model) {
+      model = path.model;
+    }
     populate(model, docs, path, subPopulate.call(model, docs, path, next));
   }
 
-  return promise;
-
   function next(err) {
-    if (err) return resolve(err);
-    if (--pending) return;
-    resolve(null, docs);
+    if (err) {
+      return cb(err);
+    }
+    if (--pending) {
+      return;
+    }
+    cb(null, docs);
   }
-};
+}
 
 /*!
  * Populates deeply if `populate` option is present.
diff --git a/lib/query.js b/lib/query.js
index 730f432a825..991d29ee0f9 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -1045,6 +1045,7 @@ Query.prototype._find = function(callback) {
     }
 
     var pop = helpers.preparePopulationOptionsMQ(self, options);
+    pop.__noPromise = true;
     self.model.populate(docs, pop, function(err, docs) {
       if (err) return callback(err);
       return true === options.lean
@@ -1165,6 +1166,7 @@ Query.prototype._findOne = function(callback) {
     }
 
     var pop = helpers.preparePopulationOptionsMQ(self, options);
+    pop.__noPromise = true;
     self.model.populate(doc, pop, function(err, doc) {
       if (err) {
         return callback(err);
@@ -1810,6 +1812,7 @@ Query.prototype._findAndModify = function(type, callback) {
     }
 
     var pop = helpers.preparePopulationOptionsMQ(self, options);
+    pop.__noPromise = true;
     self.model.populate(doc, pop, function(err, doc) {
       if (err) {
         return callback(err);
diff --git a/lib/querystream.js b/lib/querystream.js
index 086a203622e..a2534998122 100644
--- a/lib/querystream.js
+++ b/lib/querystream.js
@@ -229,6 +229,7 @@ QueryStream.prototype._onNextObject = function _onNextObject(err, doc) {
     delete option.model;
   });
 
+  pop.__noPromise = true;
   self.query.model.populate(doc, pop, function(err, doc) {
     if (err) return self.destroy(err);
     return true === opts.lean ?

From 8077e9e3b03b088d1c023543e6f61f1a8457906f Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 7 Jan 2016 16:06:52 -0500
Subject: [PATCH 0182/2240] test: repro #3735

---
 test/document.strict.test.js | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/test/document.strict.test.js b/test/document.strict.test.js
index c41fc4094f1..639d3322d35 100644
--- a/test/document.strict.test.js
+++ b/test/document.strict.test.js
@@ -440,5 +440,19 @@ describe('document: strict mode:', function() {
 
       done();
     });
+
+    it('set nested to num throws ObjectExpectedError (gh-3735)', function() {
+      var schema = new Schema({
+        resolved: {
+          by: { type: String }
+        }
+      }, { strict: 'throw' });
+
+      var Test = mongoose.model('gh3735', schema);
+
+      assert.throws(function() {
+        var t = new Test({ resolved: 123 });
+      }, /ObjectExpectedError/);
+    });
   });
 });

From 1b335554420e3a209f9ce94348691feadc4cae9a Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 7 Jan 2016 16:07:29 -0500
Subject: [PATCH 0183/2240] fix(document): strict throw with setting nested to
 num (Fix #3735)

---
 lib/document.js             |  7 ++++++-
 lib/error/objectExpected.js | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)
 create mode 100644 lib/error/objectExpected.js

diff --git a/lib/document.js b/lib/document.js
index 0c00a9237dc..654774d23b4 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -8,6 +8,7 @@ var EventEmitter = require('events').EventEmitter,
     MongooseError = require('./error'),
     MixedSchema = require('./schema/mixed'),
     Schema = require('./schema'),
+    ObjectExpectedError = require('./error/objectExpected'),
     StrictModeError = require('./error/strict'),
     ValidatorError = require('./schematype').ValidatorError,
     utils = require('./utils'),
@@ -515,7 +516,11 @@ Document.prototype.set = function(path, val, type, options) {
             this.set(prefix + key,
               path[key].toObject({ virtuals: false }), constructing);
           } else if ('throw' == strict) {
-            throw new StrictModeError(key);
+            if (pathtype ==='nested') {
+              throw new ObjectExpectedError(key, path[key]);
+            } else {
+              throw new StrictModeError(key);
+            }
           }
         } else if (undefined !== path[key]) {
           this.set(prefix + key, path[key], constructing);
diff --git a/lib/error/objectExpected.js b/lib/error/objectExpected.js
new file mode 100644
index 00000000000..fa863bcb4a5
--- /dev/null
+++ b/lib/error/objectExpected.js
@@ -0,0 +1,35 @@
+/*!
+ * Module dependencies.
+ */
+
+var MongooseError = require('../error.js');
+
+/**
+ * Strict mode error constructor
+ *
+ * @param {String} type
+ * @param {String} value
+ * @inherits MongooseError
+ * @api private
+ */
+
+function ObjectExpectedError(path, val) {
+  MongooseError.call(this, 'Tried to set nested object field `' + path +
+    '` to primitive value `' + val + '` and strict mode is set to throw.');
+  if (Error.captureStackTrace) {
+    Error.captureStackTrace(this);
+  } else {
+    this.stack = new Error().stack;
+  }
+  this.name = 'ObjectExpectedError';
+  this.path = path;
+}
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+ObjectExpectedError.prototype = Object.create(MongooseError.prototype);
+ObjectExpectedError.prototype.constructor = MongooseError;
+
+module.exports = ObjectExpectedError;

From 49fa672305cf5154aa2334d46d7603a66dbe9193 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 7 Jan 2016 16:14:27 -0500
Subject: [PATCH 0184/2240] release 3.8.38

---
 History.md   | 4 ++++
 package.json | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/History.md b/History.md
index 83ef532316b..83b12bea09f 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,7 @@
+3.8.38 / 2016-01-07
+===================
+ * fixed; aggregate.append an array #3730 [dbkup](https://github.com/dbkup)
+
 3.8.37 / 2015-11-16
 ===================
  * fixed; use retainKeyOrder for cloning update op #3572
diff --git a/package.json b/package.json
index d6a35e10383..1e0a63a9c49 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
     "name": "mongoose"
   , "description": "Mongoose MongoDB ODM"
-  , "version": "3.8.37"
+  , "version": "3.8.38"
   , "author": "Guillermo Rauch "
   , "keywords": ["mongodb", "document", "model", "schema", "database", "odm", "data", "datastore", "query", "nosql", "orm", "db"]
   , "dependencies": {

From 25f4e15768096461263b62ce0432deb8f19ea1e3 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 7 Jan 2016 16:23:08 -0500
Subject: [PATCH 0185/2240] style(query): clean up #3741

---
 lib/query.js | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/lib/query.js b/lib/query.js
index 23d68441a7b..524f6a26894 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -2022,14 +2022,13 @@ Query.prototype.update = function(conditions, doc, options, callback) {
 
   var oldCb = callback;
   if (oldCb) {
-	if('function' === typeof oldCb){
-	  callback = function(error, result) {
-		oldCb(error, result ? result.result : { ok: 0, n: 0, nModified: 0 });
-	  };  
-	}else{		
-	  throw new Error('Invalid callback() argument.');
-	}	  
-    
+    if (typeof oldCb === 'function') {
+      callback = function(error, result) {
+        oldCb(error, result ? result.result : { ok: 0, n: 0, nModified: 0 });
+      };
+    } else {
+      throw new Error('Invalid callback() argument.');
+    }
   }
 
   // strict is an option used in the update checking, make sure it gets set

From 25ce44326310231fdf08b72d98a35f5be215d60f Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sat, 9 Jan 2016 11:13:02 -0500
Subject: [PATCH 0186/2240] chore: release 4.3.5

---
 History.md      |  17 +++
 bin/mongoose.js | 306 ++++++++++++++++++++++++++++--------------------
 package.json    |   2 +-
 3 files changed, 200 insertions(+), 125 deletions(-)

diff --git a/History.md b/History.md
index 30b8606bb7e..a24867f1a45 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,20 @@
+4.3.5 / 2016-01-09
+==================
+ * fix(query): throw when 4th parameter to update not a function #3741 [kasselTrankos](https://github.com/kasselTrankos)
+ * fix(document): separate error type for setting an object to a primitive #3735
+ * fix(populate): Model.populate returns ES6 promise #3734
+ * fix(drivers): re-register event handlers after manual reconnect #3729
+ * docs: broken links #3727
+ * fix(validation): update validators run array validation #3724
+ * docs: clarify the need to use markModified with in-place date ops #3722
+ * fix(document): mark correct path as populated when manually populating array #3721
+ * fix(aggregate): support for array pipeline argument to append #3718 [dbkup](https://github.com/dbkup)
+ * docs: clarify `.connect()` callback #3705
+ * fix(schema): properly validate nested single nested docs #3702
+ * fix(types): handle setting documentarray of wrong type #3701
+ * docs: broken links #3700
+ * fix(drivers): debug output properly displays '0' #3689
+
 3.8.38 / 2016-01-07
 ===================
  * fixed; aggregate.append an array #3730 [dbkup](https://github.com/dbkup)
diff --git a/bin/mongoose.js b/bin/mongoose.js
index ce22a81e740..bdb41766d44 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -129,7 +129,7 @@ if (typeof window !== 'undefined') {
 }
 
 }).call(this,require("buffer").Buffer)
-},{"./document_provider.js":6,"./error":12,"./schema":25,"./schematype.js":38,"./types":44,"./utils.js":47,"./virtualtype":48,"buffer":51}],3:[function(require,module,exports){
+},{"./document_provider.js":6,"./error":12,"./schema":26,"./schematype.js":39,"./types":45,"./utils.js":48,"./virtualtype":49,"buffer":52}],3:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -236,7 +236,7 @@ Document.prototype.constructor = Document;
 Document.ValidationError = ValidationError;
 module.exports = exports = Document;
 
-},{"./document":5,"./error":12,"./internal":22,"./schema":25,"./types/objectid":45,"./utils":47,"events":55}],4:[function(require,module,exports){
+},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":46,"./utils":48,"events":56}],4:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -449,7 +449,7 @@ var cast = module.exports = function(schema, obj) {
   return obj;
 };
 
-},{"./schema/index":32,"./utils":47}],5:[function(require,module,exports){
+},{"./schema/index":33,"./utils":48}],5:[function(require,module,exports){
 (function (process,Buffer){
 /* eslint no-unused-vars: 1 */
 
@@ -461,6 +461,7 @@ var EventEmitter = require('events').EventEmitter,
     MongooseError = require('./error'),
     MixedSchema = require('./schema/mixed'),
     Schema = require('./schema'),
+    ObjectExpectedError = require('./error/objectExpected'),
     StrictModeError = require('./error/strict'),
     ValidatorError = require('./schematype').ValidatorError,
     utils = require('./utils'),
@@ -704,7 +705,7 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) {
  *
  * @param {Object} doc document returned by mongo
  * @param {Function} fn callback
- * @api private
+ * @api public
  */
 
 Document.prototype.init = function(doc, opts, fn) {
@@ -968,7 +969,11 @@ Document.prototype.set = function(path, val, type, options) {
             this.set(prefix + key,
               path[key].toObject({ virtuals: false }), constructing);
           } else if ('throw' == strict) {
-            throw new StrictModeError(key);
+            if (pathtype ==='nested') {
+              throw new ObjectExpectedError(key, path[key]);
+            } else {
+              throw new StrictModeError(key);
+            }
           }
         } else if (undefined !== path[key]) {
           this.set(prefix + key, path[key], constructing);
@@ -1080,8 +1085,14 @@ Document.prototype.set = function(path, val, type, options) {
         val[0] instanceof Document &&
         val[0].constructor.modelName &&
         schema.options.type[0].ref === val[0].constructor.modelName) {
-      this.populated(path, val.map(function(v) { return v._id; }),
-        { model: val[0].constructor });
+      if (this.ownerDocument) {
+        this.ownerDocument().populated(this.$__fullPath(path),
+          val.map(function(v) { return v._id; }),
+          { model: val[0].constructor });
+      } else {
+        this.populated(path, val.map(function(v) { return v._id; }),
+          { model: val[0].constructor });
+      }
       didPopulate = true;
     }
     val = schema.applySetters(val, this, false, priorVal);
@@ -1368,7 +1379,6 @@ Document.prototype.isModified = function(path) {
  *
  * @param {String} [path]
  * @return {Boolean}
- * @method $isDefault
  * @api public
  */
 
@@ -2649,6 +2659,7 @@ Document.prototype.populate = function populate() {
   if (fn) {
     var paths = utils.object.vals(pop);
     this.$__.populate = undefined;
+    paths.__noPromise = true;
     this.constructor.populate(this, paths, fn);
   }
 
@@ -2688,16 +2699,7 @@ Document.prototype.populate = function populate() {
  */
 
 Document.prototype.execPopulate = function() {
-  var Promise = PromiseProvider.get();
-  var _this = this;
-  return new Promise.ES6(function(resolve, reject) {
-    _this.populate(function(error) {
-      if (error) {
-        return reject(error);
-      }
-      resolve(_this);
-    });
-  });
+  return this.populate(function() {});
 };
 
 /**
@@ -2789,7 +2791,7 @@ Document.ValidationError = ValidationError;
 module.exports = exports = Document;
 
 }).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"./error":12,"./error/strict":18,"./internal":22,"./promise_provider":24,"./schema":25,"./schema/mixed":33,"./schematype":38,"./types/array":40,"./types/documentarray":42,"./types/embedded":43,"./utils":47,"FWaASH":57,"buffer":51,"events":55,"hooks-fixed":78,"util":59}],6:[function(require,module,exports){
+},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":39,"./types/array":41,"./types/documentarray":43,"./types/embedded":44,"./utils":48,"FWaASH":58,"buffer":52,"events":56,"hooks-fixed":79,"util":60}],6:[function(require,module,exports){
 'use strict';
 
 /*!
@@ -2831,7 +2833,7 @@ var Binary = require('bson').Binary;
 
 module.exports = exports = Binary;
 
-},{"bson":62}],9:[function(require,module,exports){
+},{"bson":63}],9:[function(require,module,exports){
 /*!
  * Module exports.
  */
@@ -2856,7 +2858,7 @@ var ObjectId = require('bson').ObjectID;
 
 module.exports = exports = ObjectId;
 
-},{"bson":62}],11:[function(require,module,exports){
+},{"bson":63}],11:[function(require,module,exports){
 (function (global){
 /*!
  * ignore
@@ -2934,7 +2936,7 @@ MongooseError.OverwriteModelError = require('./error/overwriteModel');
 MongooseError.MissingSchemaError = require('./error/missingSchema');
 MongooseError.DivergentArrayError = require('./error/divergentArray');
 
-},{"./error/cast":13,"./error/divergentArray":14,"./error/messages":15,"./error/missingSchema":16,"./error/overwriteModel":17,"./error/validation":19,"./error/validator":20,"./error/version":21}],13:[function(require,module,exports){
+},{"./error/cast":13,"./error/divergentArray":14,"./error/messages":15,"./error/missingSchema":16,"./error/overwriteModel":18,"./error/validation":20,"./error/validator":21,"./error/version":22}],13:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -3103,6 +3105,43 @@ MissingSchemaError.prototype.constructor = MongooseError;
 module.exports = MissingSchemaError;
 
 },{"../error.js":12}],17:[function(require,module,exports){
+/*!
+ * Module dependencies.
+ */
+
+var MongooseError = require('../error.js');
+
+/**
+ * Strict mode error constructor
+ *
+ * @param {String} type
+ * @param {String} value
+ * @inherits MongooseError
+ * @api private
+ */
+
+function ObjectExpectedError(path, val) {
+  MongooseError.call(this, 'Tried to set nested object field `' + path +
+    '` to primitive value `' + val + '` and strict mode is set to throw.');
+  if (Error.captureStackTrace) {
+    Error.captureStackTrace(this);
+  } else {
+    this.stack = new Error().stack;
+  }
+  this.name = 'ObjectExpectedError';
+  this.path = path;
+}
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+ObjectExpectedError.prototype = Object.create(MongooseError.prototype);
+ObjectExpectedError.prototype.constructor = MongooseError;
+
+module.exports = ObjectExpectedError;
+
+},{"../error.js":12}],18:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -3135,7 +3174,7 @@ OverwriteModelError.prototype.constructor = MongooseError;
 
 module.exports = OverwriteModelError;
 
-},{"../error.js":12}],18:[function(require,module,exports){
+},{"../error.js":12}],19:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -3172,7 +3211,7 @@ StrictModeError.prototype.constructor = MongooseError;
 
 module.exports = StrictModeError;
 
-},{"../error.js":12}],19:[function(require,module,exports){
+},{"../error.js":12}],20:[function(require,module,exports){
 
 /*!
  * Module requirements
@@ -3236,7 +3275,7 @@ ValidationError.prototype.toString = function() {
 
 module.exports = exports = ValidationError;
 
-},{"../error.js":12}],20:[function(require,module,exports){
+},{"../error.js":12}],21:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -3309,7 +3348,7 @@ ValidatorError.prototype.toString = function() {
 
 module.exports = ValidatorError;
 
-},{"../error.js":12}],21:[function(require,module,exports){
+},{"../error.js":12}],22:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -3343,7 +3382,7 @@ VersionError.prototype.constructor = MongooseError;
 
 module.exports = VersionError;
 
-},{"../error.js":12}],22:[function(require,module,exports){
+},{"../error.js":12}],23:[function(require,module,exports){
 /*!
  * Dependencies
  */
@@ -3376,7 +3415,7 @@ function InternalCache() {
   this.fullPath = undefined;
 }
 
-},{"./statemachine":39}],23:[function(require,module,exports){
+},{"./statemachine":40}],24:[function(require,module,exports){
 /*!
  * Module dependencies
  */
@@ -3669,7 +3708,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject;
 
 module.exports = Promise;
 
-},{"mpromise":82,"util":59}],24:[function(require,module,exports){
+},{"mpromise":83,"util":60}],25:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -3722,7 +3761,7 @@ Promise.reset = function() {
 
 module.exports = Promise;
 
-},{"./ES6Promise":1,"./promise":23,"mquery":87}],25:[function(require,module,exports){
+},{"./ES6Promise":1,"./promise":24,"mquery":88}],26:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -4226,6 +4265,10 @@ Schema.prototype.path = function(path, obj) {
       this.singleNestedPaths[path + '.' + key] =
         this.paths[path].schema.paths[key];
     }
+    for (var key in this.paths[path].schema.singleNestedPaths) {
+      this.singleNestedPaths[path + '.' + key] =
+        this.paths[path].schema.singleNestedPaths[key];
+    }
   }
   return this;
 };
@@ -4999,7 +5042,7 @@ Schema.Types = MongooseTypes = require('./schema/index');
 exports.ObjectId = MongooseTypes.ObjectId;
 
 }).call(this,require("buffer").Buffer)
-},{"./drivers":11,"./schema/index":32,"./utils":47,"./virtualtype":48,"async":49,"buffer":51,"events":55,"kareem":79}],26:[function(require,module,exports){
+},{"./drivers":11,"./schema/index":33,"./utils":48,"./virtualtype":49,"async":50,"buffer":52,"events":56,"kareem":80}],27:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -5028,7 +5071,7 @@ var SchemaType = require('../schematype'),
  * @param {SchemaType} cast
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaArray(key, cast, options) {
@@ -5083,7 +5126,7 @@ function SchemaArray(key, cast, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaArray.schemaName = 'Array';
 
@@ -5395,7 +5438,7 @@ handle.$regex = SchemaArray.prototype.castForQuery;
 
 module.exports = SchemaArray;
 
-},{"../cast":4,"../schematype":38,"../types":44,"../utils":47,"./boolean":27,"./buffer":28,"./date":29,"./mixed":33,"./number":34,"./objectid":35,"./string":37}],27:[function(require,module,exports){
+},{"../cast":4,"../schematype":39,"../types":45,"../utils":48,"./boolean":28,"./buffer":29,"./date":30,"./mixed":34,"./number":35,"./objectid":36,"./string":38}],28:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -5410,7 +5453,7 @@ var SchemaType = require('../schematype');
  * @param {String} path
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaBoolean(path, options) {
@@ -5421,7 +5464,7 @@ function SchemaBoolean(path, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaBoolean.schemaName = 'Boolean';
 
@@ -5488,7 +5531,7 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val) {
 
 module.exports = SchemaBoolean;
 
-},{"../schematype":38,"../utils":47}],28:[function(require,module,exports){
+},{"../schematype":39,"../utils":48}],29:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -5510,7 +5553,7 @@ var Document;
  * @param {String} key
  * @param {SchemaType} cast
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaBuffer(key, options) {
@@ -5521,7 +5564,7 @@ function SchemaBuffer(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaBuffer.schemaName = 'Buffer';
 
@@ -5671,7 +5714,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaBuffer;
 
 }).call(this,require("buffer").Buffer)
-},{"../schematype":38,"../types":44,"../utils":47,"./../document":5,"./operators/bitwise":36,"buffer":51}],29:[function(require,module,exports){
+},{"../schematype":39,"../types":45,"../utils":48,"./../document":5,"./operators/bitwise":37,"buffer":52}],30:[function(require,module,exports){
 /*!
  * Module requirements.
  */
@@ -5689,7 +5732,7 @@ var CastError = SchemaType.CastError;
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaDate(key, options) {
@@ -5700,7 +5743,7 @@ function SchemaDate(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaDate.schemaName = 'Date';
 
@@ -5957,7 +6000,7 @@ SchemaDate.prototype.castForQuery = function($conditional, val) {
 
 module.exports = SchemaDate;
 
-},{"../error":12,"../schematype":38,"../utils":47}],30:[function(require,module,exports){
+},{"../error":12,"../schematype":39,"../utils":48}],31:[function(require,module,exports){
 /* eslint no-empty: 1 */
 
 /*!
@@ -5977,7 +6020,7 @@ var Subdocument = require('../types/embedded');
  * @param {Schema} schema
  * @param {Object} options
  * @inherits SchemaArray
- * @api private
+ * @api public
  */
 
 function DocumentArray(key, schema, options) {
@@ -5999,7 +6042,6 @@ function DocumentArray(key, schema, options) {
     EmbeddedDocument[i] = schema.statics[i];
 
   EmbeddedDocument.options = options;
-  this.schema = schema;
 
   ArrayType.call(this, key, EmbeddedDocument, options);
 
@@ -6018,7 +6060,7 @@ function DocumentArray(key, schema, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 DocumentArray.schemaName = 'DocumentArray';
 
@@ -6034,7 +6076,8 @@ DocumentArray.prototype.constructor = DocumentArray;
  * @api private
  */
 
-DocumentArray.prototype.doValidate = function(array, fn, scope) {
+DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
+  var _this = this;
   SchemaType.prototype.doValidate.call(this, array, function(err) {
     if (err) {
       return fn(err);
@@ -6043,7 +6086,12 @@ DocumentArray.prototype.doValidate = function(array, fn, scope) {
     var count = array && array.length;
     var error;
 
-    if (!count) return fn();
+    if (!count) {
+      return fn();
+    }
+    if (options && options.updateValidator) {
+      return fn();
+    }
 
     // handle sparse arrays, do not use array.forEach which does not
     // iterate over sparse elements yet reports array.length including
@@ -6085,7 +6133,9 @@ DocumentArray.prototype.doValidateSync = function(array, scope) {
   var count = array && array.length,
       resultError = null;
 
-  if (!count) return;
+  if (!count) {
+    return;
+  }
 
   // handle sparse arrays, do not use array.forEach which does not
   // iterate over sparse elements yet reports array.length including
@@ -6142,6 +6192,14 @@ DocumentArray.prototype.cast = function(value, doc, init, prev) {
   i = value.length;
 
   while (i--) {
+    if (!value[i]) {
+      continue;
+    }
+    // Check if the document has a different schema (re gh-3701)
+    if ((value[i] instanceof Subdocument) &&
+        value[i].schema !== this.casterConstructor.schema) {
+      value[i] = value[i].toObject({ virtuals: false });
+    }
     if (!(value[i] instanceof Subdocument) && value[i]) {
       if (init) {
         selected || (selected = scopePaths(this, doc.$__.selected, init));
@@ -6213,7 +6271,7 @@ function scopePaths(array, fields, init) {
 
 module.exports = DocumentArray;
 
-},{"../error/cast":13,"../schematype":38,"../types/documentarray":42,"../types/embedded":43,"./array":26}],31:[function(require,module,exports){
+},{"../error/cast":13,"../schematype":39,"../types/documentarray":43,"../types/embedded":44,"./array":27}],32:[function(require,module,exports){
 var SchemaType = require('../schematype');
 var Subdocument = require('../types/subdocument');
 
@@ -6226,7 +6284,7 @@ module.exports = Embedded;
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function Embedded(schema, path, options) {
@@ -6352,7 +6410,7 @@ Embedded.prototype.checkRequired = function(value) {
   return !!value && value.$isSingleNested;
 };
 
-},{"../schematype":38,"../types/subdocument":46}],32:[function(require,module,exports){
+},{"../schematype":39,"../types/subdocument":47}],33:[function(require,module,exports){
 
 /*!
  * Module exports.
@@ -6384,7 +6442,7 @@ exports.Oid = exports.ObjectId;
 exports.Object = exports.Mixed;
 exports.Bool = exports.Boolean;
 
-},{"./array":26,"./boolean":27,"./buffer":28,"./date":29,"./documentarray":30,"./embedded":31,"./mixed":33,"./number":34,"./objectid":35,"./string":37}],33:[function(require,module,exports){
+},{"./array":27,"./boolean":28,"./buffer":29,"./date":30,"./documentarray":31,"./embedded":32,"./mixed":34,"./number":35,"./objectid":36,"./string":38}],34:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -6399,7 +6457,7 @@ var utils = require('../utils');
  * @param {String} path
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function Mixed(path, options) {
@@ -6425,7 +6483,7 @@ function Mixed(path, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 Mixed.schemaName = 'Mixed';
 
@@ -6477,7 +6535,7 @@ Mixed.prototype.castForQuery = function($cond, val) {
 
 module.exports = Mixed;
 
-},{"../schematype":38,"../utils":47}],34:[function(require,module,exports){
+},{"../schematype":39,"../utils":48}],35:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module requirements.
@@ -6496,7 +6554,7 @@ var Document;
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaNumber(key, options) {
@@ -6507,7 +6565,7 @@ function SchemaNumber(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaNumber.schemaName = 'Number';
 
@@ -6762,7 +6820,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaNumber;
 
 }).call(this,require("buffer").Buffer)
-},{"../error":12,"../schematype":38,"../utils":47,"./../document":5,"./operators/bitwise":36,"buffer":51}],35:[function(require,module,exports){
+},{"../error":12,"../schematype":39,"../utils":48,"./../document":5,"./operators/bitwise":37,"buffer":52}],36:[function(require,module,exports){
 (function (Buffer){
 /* eslint no-empty: 1 */
 
@@ -6782,7 +6840,7 @@ var SchemaType = require('../schematype'),
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function ObjectId(key, options) {
@@ -6793,7 +6851,7 @@ function ObjectId(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 ObjectId.schemaName = 'ObjectId';
 
@@ -6960,7 +7018,7 @@ function resetId(v) {
 module.exports = ObjectId;
 
 }).call(this,require("buffer").Buffer)
-},{"../schematype":38,"../types/objectid":45,"../utils":47,"./../document":5,"buffer":51}],36:[function(require,module,exports){
+},{"../schematype":39,"../types/objectid":46,"../utils":48,"./../document":5,"buffer":52}],37:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module requirements.
@@ -7001,7 +7059,7 @@ function _castNumber(_this, num) {
 module.exports = handleBitwiseOperator;
 
 }).call(this,require("buffer").Buffer)
-},{"../../error/cast":13,"buffer":51}],37:[function(require,module,exports){
+},{"../../error/cast":13,"buffer":52}],38:[function(require,module,exports){
 (function (Buffer){
 
 /*!
@@ -7020,7 +7078,7 @@ var Document;
  * @param {String} key
  * @param {Object} options
  * @inherits SchemaType
- * @api private
+ * @api public
  */
 
 function SchemaString(key, options) {
@@ -7033,7 +7091,7 @@ function SchemaString(key, options) {
  * This schema type's name, to defend against minifiers that mangle
  * function names.
  *
- * @api private
+ * @api public
  */
 SchemaString.schemaName = 'String';
 
@@ -7499,7 +7557,7 @@ SchemaString.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaString;
 
 }).call(this,require("buffer").Buffer)
-},{"../error":12,"../schematype":38,"../utils":47,"./../document":5,"buffer":51}],38:[function(require,module,exports){
+},{"../error":12,"../schematype":39,"../utils":48,"./../document":5,"buffer":52}],39:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -8358,7 +8416,7 @@ exports.CastError = CastError;
 exports.ValidatorError = ValidatorError;
 
 }).call(this,require("buffer").Buffer)
-},{"./error":12,"./utils":47,"buffer":51}],39:[function(require,module,exports){
+},{"./error":12,"./utils":48,"buffer":52}],40:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -8538,7 +8596,7 @@ StateMachine.prototype.map = function map() {
   return this.map.apply(this, arguments);
 };
 
-},{"./utils":47}],40:[function(require,module,exports){
+},{"./utils":48}],41:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9305,7 +9363,7 @@ MongooseArray.mixin.remove = MongooseArray.mixin.pull;
 module.exports = exports = MongooseArray;
 
 }).call(this,require("buffer").Buffer)
-},{"../document":5,"../utils":47,"./embedded":43,"./objectid":45,"buffer":51}],41:[function(require,module,exports){
+},{"../document":5,"../utils":48,"./embedded":44,"./objectid":46,"buffer":52}],42:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9578,7 +9636,7 @@ MongooseBuffer.Binary = Binary;
 module.exports = MongooseBuffer;
 
 }).call(this,require("buffer").Buffer)
-},{"../drivers":11,"../utils":47,"buffer":51}],42:[function(require,module,exports){
+},{"../drivers":11,"../utils":48,"buffer":52}],43:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9805,7 +9863,7 @@ MongooseDocumentArray.mixin.notify = function notify(event) {
 module.exports = MongooseDocumentArray;
 
 }).call(this,require("buffer").Buffer)
-},{"../document":5,"../schema/objectid":35,"../utils":47,"./array":40,"./objectid":45,"buffer":51,"util":59}],43:[function(require,module,exports){
+},{"../document":5,"../schema/objectid":36,"../utils":48,"./array":41,"./objectid":46,"buffer":52,"util":60}],44:[function(require,module,exports){
 /* eslint no-func-assign: 1 */
 
 /*!
@@ -10119,7 +10177,7 @@ EmbeddedDocument.prototype.parentArray = function() {
 
 module.exports = EmbeddedDocument;
 
-},{"../document_provider":6,"../promise_provider":24,"util":59}],44:[function(require,module,exports){
+},{"../document_provider":6,"../promise_provider":25,"util":60}],45:[function(require,module,exports){
 
 /*!
  * Module exports.
@@ -10136,7 +10194,7 @@ exports.ObjectId = require('./objectid');
 
 exports.Subdocument = require('./subdocument');
 
-},{"./array":40,"./buffer":41,"./documentarray":42,"./embedded":43,"./objectid":45,"./subdocument":46}],45:[function(require,module,exports){
+},{"./array":41,"./buffer":42,"./documentarray":43,"./embedded":44,"./objectid":46,"./subdocument":47}],46:[function(require,module,exports){
 /**
  * ObjectId type constructor
  *
@@ -10151,7 +10209,7 @@ var ObjectId = require('../drivers').ObjectId;
 
 module.exports = ObjectId;
 
-},{"../drivers":11}],46:[function(require,module,exports){
+},{"../drivers":11}],47:[function(require,module,exports){
 var Document = require('../document');
 var PromiseProvider = require('../promise_provider');
 
@@ -10240,7 +10298,7 @@ Subdocument.prototype.ownerDocument = function() {
   return this.$__.ownerDocument = parent;
 };
 
-},{"../document":5,"../promise_provider":24}],47:[function(require,module,exports){
+},{"../document":5,"../promise_provider":25}],48:[function(require,module,exports){
 (function (process,Buffer){
 /*!
  * Module dependencies.
@@ -11041,7 +11099,7 @@ exports.each = function(arr, fn) {
 };
 
 }).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"./document":5,"./types":44,"./types/objectid":45,"FWaASH":57,"buffer":51,"mpath":80,"ms":93,"regexp-clone":94,"sliced":95}],48:[function(require,module,exports){
+},{"./document":5,"./types":45,"./types/objectid":46,"FWaASH":58,"buffer":52,"mpath":81,"ms":94,"regexp-clone":95,"sliced":96}],49:[function(require,module,exports){
 
 /**
  * VirtualType constructor
@@ -11146,7 +11204,7 @@ VirtualType.prototype.applySetters = function(value, scope) {
 
 module.exports = VirtualType;
 
-},{}],49:[function(require,module,exports){
+},{}],50:[function(require,module,exports){
 (function (process){
 /*!
  * async
@@ -12273,7 +12331,7 @@ module.exports = VirtualType;
 }());
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":57}],50:[function(require,module,exports){
+},{"FWaASH":58}],51:[function(require,module,exports){
 // http://wiki.commonjs.org/wiki/Unit_Testing/1.0
 //
 // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
@@ -12635,7 +12693,7 @@ var objectKeys = Object.keys || function (obj) {
   return keys;
 };
 
-},{"util/":59}],51:[function(require,module,exports){
+},{"util/":60}],52:[function(require,module,exports){
 /*!
  * The buffer module from node.js, for the browser.
  *
@@ -13689,7 +13747,7 @@ function decodeUtf8Char (str) {
   }
 }
 
-},{"base64-js":52,"ieee754":53,"is-array":54}],52:[function(require,module,exports){
+},{"base64-js":53,"ieee754":54,"is-array":55}],53:[function(require,module,exports){
 var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 
 ;(function (exports) {
@@ -13811,7 +13869,7 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 	exports.fromByteArray = uint8ToBase64
 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
 
-},{}],53:[function(require,module,exports){
+},{}],54:[function(require,module,exports){
 exports.read = function (buffer, offset, isLE, mLen, nBytes) {
   var e, m
   var eLen = nBytes * 8 - mLen - 1
@@ -13897,7 +13955,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
   buffer[offset + i - d] |= s * 128
 }
 
-},{}],54:[function(require,module,exports){
+},{}],55:[function(require,module,exports){
 
 /**
  * isArray
@@ -13932,7 +13990,7 @@ module.exports = isArray || function (val) {
   return !! val && '[object Array]' == str.call(val);
 };
 
-},{}],55:[function(require,module,exports){
+},{}],56:[function(require,module,exports){
 // Copyright Joyent, Inc. and other Node contributors.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
@@ -14235,7 +14293,7 @@ function isUndefined(arg) {
   return arg === void 0;
 }
 
-},{}],56:[function(require,module,exports){
+},{}],57:[function(require,module,exports){
 if (typeof Object.create === 'function') {
   // implementation from standard node.js 'util' module
   module.exports = function inherits(ctor, superCtor) {
@@ -14260,7 +14318,7 @@ if (typeof Object.create === 'function') {
   }
 }
 
-},{}],57:[function(require,module,exports){
+},{}],58:[function(require,module,exports){
 // shim for using process in browser
 
 var process = module.exports = {};
@@ -14325,14 +14383,14 @@ process.chdir = function (dir) {
     throw new Error('process.chdir is not supported');
 };
 
-},{}],58:[function(require,module,exports){
+},{}],59:[function(require,module,exports){
 module.exports = function isBuffer(arg) {
   return arg && typeof arg === 'object'
     && typeof arg.copy === 'function'
     && typeof arg.fill === 'function'
     && typeof arg.readUInt8 === 'function';
 }
-},{}],59:[function(require,module,exports){
+},{}],60:[function(require,module,exports){
 (function (process,global){
 // Copyright Joyent, Inc. and other Node contributors.
 //
@@ -14922,7 +14980,7 @@ function hasOwnProperty(obj, prop) {
 }
 
 }).call(this,require("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./support/isBuffer":58,"FWaASH":57,"inherits":56}],60:[function(require,module,exports){
+},{"./support/isBuffer":59,"FWaASH":58,"inherits":57}],61:[function(require,module,exports){
 /**
  * Module dependencies.
  * @ignore
@@ -15268,7 +15326,7 @@ Binary.SUBTYPE_USER_DEFINED = 128;
 module.exports = Binary;
 module.exports.Binary = Binary;
 
-},{"buffer":51}],61:[function(require,module,exports){
+},{"buffer":52}],62:[function(require,module,exports){
 (function (process){
 /**
  * Binary Parser.
@@ -15657,7 +15715,7 @@ BinaryParser.Buffer = BinaryParserBuffer;
 exports.BinaryParser = BinaryParser;
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":57,"util":59}],62:[function(require,module,exports){
+},{"FWaASH":58,"util":60}],63:[function(require,module,exports){
 (function (Buffer){
 // "use strict"
 
@@ -15984,7 +16042,7 @@ module.exports.MaxKey = MaxKey;
 module.exports.BSONRegExp = BSONRegExp;
 
 }).call(this,require("buffer").Buffer)
-},{"./binary":60,"./code":63,"./db_ref":64,"./double":65,"./float_parser":66,"./long":67,"./map":68,"./max_key":69,"./min_key":70,"./objectid":71,"./parser/calculate_size":72,"./parser/deserializer":73,"./parser/serializer":74,"./regexp":75,"./symbol":76,"./timestamp":77,"buffer":51}],63:[function(require,module,exports){
+},{"./binary":61,"./code":64,"./db_ref":65,"./double":66,"./float_parser":67,"./long":68,"./map":69,"./max_key":70,"./min_key":71,"./objectid":72,"./parser/calculate_size":73,"./parser/deserializer":74,"./parser/serializer":75,"./regexp":76,"./symbol":77,"./timestamp":78,"buffer":52}],64:[function(require,module,exports){
 /**
  * A class representation of the BSON Code type.
  *
@@ -16009,7 +16067,7 @@ Code.prototype.toJSON = function() {
 
 module.exports = Code;
 module.exports.Code = Code;
-},{}],64:[function(require,module,exports){
+},{}],65:[function(require,module,exports){
 /**
  * A class representation of the BSON DBRef type.
  *
@@ -16042,7 +16100,7 @@ DBRef.prototype.toJSON = function() {
 
 module.exports = DBRef;
 module.exports.DBRef = DBRef;
-},{}],65:[function(require,module,exports){
+},{}],66:[function(require,module,exports){
 /**
  * A class representation of the BSON Double type.
  *
@@ -16076,7 +16134,7 @@ Double.prototype.toJSON = function() {
 
 module.exports = Double;
 module.exports.Double = Double;
-},{}],66:[function(require,module,exports){
+},{}],67:[function(require,module,exports){
 // Copyright (c) 2008, Fair Oaks Labs, Inc.
 // All rights reserved.
 // 
@@ -16198,7 +16256,7 @@ var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) {
 
 exports.readIEEE754 = readIEEE754;
 exports.writeIEEE754 = writeIEEE754;
-},{}],67:[function(require,module,exports){
+},{}],68:[function(require,module,exports){
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
@@ -17055,7 +17113,7 @@ Long.TWO_PWR_24_ = Long.fromInt(1 << 24);
  */
 module.exports = Long;
 module.exports.Long = Long;
-},{}],68:[function(require,module,exports){
+},{}],69:[function(require,module,exports){
 (function (global){
 "use strict"
 
@@ -17184,7 +17242,7 @@ if(typeof global.Map !== 'undefined') {
   module.exports.Map = Map;
 }
 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],69:[function(require,module,exports){
+},{}],70:[function(require,module,exports){
 /**
  * A class representation of the BSON MaxKey type.
  *
@@ -17199,7 +17257,7 @@ function MaxKey() {
 
 module.exports = MaxKey;
 module.exports.MaxKey = MaxKey;
-},{}],70:[function(require,module,exports){
+},{}],71:[function(require,module,exports){
 /**
  * A class representation of the BSON MinKey type.
  *
@@ -17214,7 +17272,7 @@ function MinKey() {
 
 module.exports = MinKey;
 module.exports.MinKey = MinKey;
-},{}],71:[function(require,module,exports){
+},{}],72:[function(require,module,exports){
 (function (process){
 /**
  * Module dependencies.
@@ -17496,7 +17554,7 @@ module.exports.ObjectID = ObjectID;
 module.exports.ObjectId = ObjectID;
 
 }).call(this,require("FWaASH"))
-},{"./binary_parser":61,"FWaASH":57}],72:[function(require,module,exports){
+},{"./binary_parser":62,"FWaASH":58}],73:[function(require,module,exports){
 (function (Buffer){
 "use strict"
 
@@ -17810,7 +17868,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 module.exports = calculateObjectSize;
 
 }).call(this,require("buffer").Buffer)
-},{"../binary":60,"../code":63,"../db_ref":64,"../double":65,"../float_parser":66,"../long":67,"../max_key":69,"../min_key":70,"../objectid":71,"../regexp":75,"../symbol":76,"../timestamp":77,"buffer":51}],73:[function(require,module,exports){
+},{"../binary":61,"../code":64,"../db_ref":65,"../double":66,"../float_parser":67,"../long":68,"../max_key":70,"../min_key":71,"../objectid":72,"../regexp":76,"../symbol":77,"../timestamp":78,"buffer":52}],74:[function(require,module,exports){
 "use strict"
 
 var writeIEEE754 = require('../float_parser').writeIEEE754,
@@ -18367,7 +18425,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 
 module.exports = deserialize
 
-},{"../binary":60,"../code":63,"../db_ref":64,"../double":65,"../float_parser":66,"../long":67,"../max_key":69,"../min_key":70,"../objectid":71,"../regexp":75,"../symbol":76,"../timestamp":77,"util":59}],74:[function(require,module,exports){
+},{"../binary":61,"../code":64,"../db_ref":65,"../double":66,"../float_parser":67,"../long":68,"../max_key":70,"../min_key":71,"../objectid":72,"../regexp":76,"../symbol":77,"../timestamp":78,"util":60}],75:[function(require,module,exports){
 (function (Buffer){
 "use strict"
 
@@ -19283,7 +19341,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 module.exports = serializeInto;
 
 }).call(this,require("buffer").Buffer)
-},{"../binary":60,"../code":63,"../db_ref":64,"../double":65,"../float_parser":66,"../long":67,"../map":68,"../max_key":69,"../min_key":70,"../objectid":71,"../regexp":75,"../symbol":76,"../timestamp":77,"buffer":51}],75:[function(require,module,exports){
+},{"../binary":61,"../code":64,"../db_ref":65,"../double":66,"../float_parser":67,"../long":68,"../map":69,"../max_key":70,"../min_key":71,"../objectid":72,"../regexp":76,"../symbol":77,"../timestamp":78,"buffer":52}],76:[function(require,module,exports){
 /**
  * A class representation of the BSON RegExp type.
  *
@@ -19314,7 +19372,7 @@ function BSONRegExp(pattern, options) {
 
 module.exports = BSONRegExp;
 module.exports.BSONRegExp = BSONRegExp;
-},{}],76:[function(require,module,exports){
+},{}],77:[function(require,module,exports){
 /**
  * A class representation of the BSON Symbol type.
  *
@@ -19362,7 +19420,7 @@ Symbol.prototype.toJSON = function() {
 
 module.exports = Symbol;
 module.exports.Symbol = Symbol;
-},{}],77:[function(require,module,exports){
+},{}],78:[function(require,module,exports){
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
@@ -20219,7 +20277,7 @@ Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24);
  */
 module.exports = Timestamp;
 module.exports.Timestamp = Timestamp;
-},{}],78:[function(require,module,exports){
+},{}],79:[function(require,module,exports){
 // TODO Add in pre and post skipping options
 module.exports = {
   /**
@@ -20412,7 +20470,7 @@ function once (fn, scope) {
   };
 }
 
-},{}],79:[function(require,module,exports){
+},{}],80:[function(require,module,exports){
 (function (process){
 'use strict';
 
@@ -20645,10 +20703,10 @@ Kareem.prototype.clone = function() {
 module.exports = Kareem;
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":57}],80:[function(require,module,exports){
+},{"FWaASH":58}],81:[function(require,module,exports){
 module.exports = exports = require('./lib');
 
-},{"./lib":81}],81:[function(require,module,exports){
+},{"./lib":82}],82:[function(require,module,exports){
 
 /**
  * Returns the value of object `o` at the given `path`.
@@ -20833,7 +20891,7 @@ function K (v) {
   return v;
 }
 
-},{}],82:[function(require,module,exports){
+},{}],83:[function(require,module,exports){
 (function (process){
 'use strict';
 var util = require('util');
@@ -21277,7 +21335,7 @@ Promise.deferred = function deferred() {
 
 
 }).call(this,require("FWaASH"))
-},{"FWaASH":57,"events":55,"util":59}],83:[function(require,module,exports){
+},{"FWaASH":58,"events":56,"util":60}],84:[function(require,module,exports){
 'use strict';
 
 /**
@@ -21321,7 +21379,7 @@ function notImplemented (method) {
 }
 
 
-},{}],84:[function(require,module,exports){
+},{}],85:[function(require,module,exports){
 'use strict';
 
 var env = require('../env')
@@ -21336,7 +21394,7 @@ module.exports =
   require('./collection');
 
 
-},{"../env":86,"./collection":83,"./node":85}],85:[function(require,module,exports){
+},{"../env":87,"./collection":84,"./node":86}],86:[function(require,module,exports){
 'use strict';
 
 /**
@@ -21438,7 +21496,7 @@ NodeCollection.prototype.findStream = function(match, findOptions, streamOptions
 module.exports = exports = NodeCollection;
 
 
-},{"../utils":89,"./collection":83}],86:[function(require,module,exports){
+},{"../utils":90,"./collection":84}],87:[function(require,module,exports){
 (function (process,global,Buffer){
 'use strict';
 
@@ -21464,7 +21522,7 @@ exports.type = exports.isNode ? 'node'
   : 'unknown'
 
 }).call(this,require("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
-},{"FWaASH":57,"buffer":51}],87:[function(require,module,exports){
+},{"FWaASH":58,"buffer":52}],88:[function(require,module,exports){
 'use strict';
 
 /**
@@ -24078,7 +24136,7 @@ module.exports = exports = Query;
 // TODO
 // test utils
 
-},{"./collection":84,"./collection/collection":83,"./env":86,"./permissions":88,"./utils":89,"assert":50,"bluebird":90,"debug":91,"sliced":95,"util":59}],88:[function(require,module,exports){
+},{"./collection":85,"./collection/collection":84,"./env":87,"./permissions":89,"./utils":90,"assert":51,"bluebird":91,"debug":92,"sliced":96,"util":60}],89:[function(require,module,exports){
 'use strict';
 
 var denied = exports;
@@ -24170,7 +24228,7 @@ denied.count.maxScan =
 denied.count.snapshot =
 denied.count.tailable = true;
 
-},{}],89:[function(require,module,exports){
+},{}],90:[function(require,module,exports){
 (function (process,Buffer){
 'use strict';
 
@@ -24505,7 +24563,7 @@ exports.cloneBuffer = function (buff) {
 };
 
 }).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"FWaASH":57,"buffer":51,"regexp-clone":94}],90:[function(require,module,exports){
+},{"FWaASH":58,"buffer":52,"regexp-clone":95}],91:[function(require,module,exports){
 (function (process,global){
 /* @preserve
  * The MIT License (MIT)
@@ -29613,7 +29671,7 @@ function isUndefined(arg) {
 },{}]},{},[4])(4)
 });                    ;if (typeof window !== 'undefined' && window !== null) {                               window.P = window.Promise;                                                     } else if (typeof self !== 'undefined' && self !== null) {                             self.P = self.Promise;                                                         }
 }).call(this,require("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"FWaASH":57}],91:[function(require,module,exports){
+},{"FWaASH":58}],92:[function(require,module,exports){
 
 /**
  * This is the web browser implementation of `debug()`.
@@ -29783,7 +29841,7 @@ function localstorage(){
   } catch (e) {}
 }
 
-},{"./debug":92}],92:[function(require,module,exports){
+},{"./debug":93}],93:[function(require,module,exports){
 
 /**
  * This is the common logic for both the Node.js and web browser
@@ -29982,7 +30040,7 @@ function coerce(val) {
   return val;
 }
 
-},{"ms":93}],93:[function(require,module,exports){
+},{"ms":94}],94:[function(require,module,exports){
 /**
  * Helpers.
  */
@@ -30109,7 +30167,7 @@ function plural(ms, n, name) {
   return Math.ceil(ms / n) + ' ' + name + 's';
 }
 
-},{}],94:[function(require,module,exports){
+},{}],95:[function(require,module,exports){
 
 var toString = Object.prototype.toString;
 
@@ -30131,10 +30189,10 @@ module.exports = exports = function (regexp) {
 }
 
 
-},{}],95:[function(require,module,exports){
+},{}],96:[function(require,module,exports){
 module.exports = exports = require('./lib/sliced');
 
-},{"./lib/sliced":96}],96:[function(require,module,exports){
+},{"./lib/sliced":97}],97:[function(require,module,exports){
 
 /**
  * An Array.prototype.slice.call(arguments) alternative
diff --git a/package.json b/package.json
index 144a4747ed8..c3a6d92845e 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.5-pre",
+  "version": "4.3.5",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From 1e4a49cd03d330c001c0a21fd0a94cbe82f10919 Mon Sep 17 00:00:00 2001
From: CTAPbIuMABP 
Date: Sun, 10 Jan 2016 16:48:52 +0800
Subject: [PATCH 0187/2240] fixes colors in stdout

---
 .../population-across-three-collections.js    |   2 +-
 lib/document.js                               |   3 +-
 lib/types/documentarray.js                    |   9 +-
 lib/types/embedded.js                         |   2 +-
 test/colors.js                                | 133 ++++++++++++++++++
 5 files changed, 137 insertions(+), 12 deletions(-)
 create mode 100644 test/colors.js

diff --git a/examples/population/population-across-three-collections.js b/examples/population/population-across-three-collections.js
index 5edd01a68f7..4762a5d2ffc 100644
--- a/examples/population/population-across-three-collections.js
+++ b/examples/population/population-across-three-collections.js
@@ -118,7 +118,7 @@ mongoose.connection.on('open', function() {
         BlogPost.populate(docs, opts, function(err, docs) {
           assert.ifError(err);
           console.log('populated');
-          var s = require('util').inspect(docs, { depth: null });
+          var s = require('util').inspect(docs, { depth: null, colors: true });
           console.log(s);
           done();
         });
diff --git a/lib/document.js b/lib/document.js
index 654774d23b4..191b64e6465 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -14,7 +14,6 @@ var EventEmitter = require('events').EventEmitter,
     utils = require('./utils'),
     clone = utils.clone,
     isMongooseObject = utils.isMongooseObject,
-    inspect = require('util').inspect,
     ValidationError = MongooseError.ValidationError,
     InternalCache = require('./internal'),
     deepEqual = utils.deepEqual,
@@ -2109,7 +2108,7 @@ Document.prototype.inspect = function(options) {
   var opts = options && 'Object' == utils.getFunctionName(options.constructor) ? options : {};
   opts.minimize = false;
   opts.retainKeyOrder = true;
-  return inspect(this.toObject(opts));
+  return this.toObject(opts);
 };
 
 /**
diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js
index d3055ef67fd..5f78a8d07d4 100644
--- a/lib/types/documentarray.js
+++ b/lib/types/documentarray.js
@@ -161,14 +161,7 @@ MongooseDocumentArray.mixin.toObject = function(options) {
  */
 
 MongooseDocumentArray.mixin.inspect = function() {
-  return '[' + Array.prototype.map.call(this, function(doc) {
-    if (doc) {
-      return doc.inspect
-        ? doc.inspect()
-        : util.inspect(doc);
-    }
-    return 'null';
-  }).join('\n') + ']';
+  return Array.prototype.slice.call(this);
 };
 
 /**
diff --git a/lib/types/embedded.js b/lib/types/embedded.js
index df694cf189f..0d00ae810cf 100644
--- a/lib/types/embedded.js
+++ b/lib/types/embedded.js
@@ -156,7 +156,7 @@ EmbeddedDocument.prototype.update = function() {
  */
 
 EmbeddedDocument.prototype.inspect = function() {
-  return inspect(this.toObject());
+  return this.toObject();
 };
 
 /**
diff --git a/test/colors.js b/test/colors.js
new file mode 100644
index 00000000000..ab99d1bebb6
--- /dev/null
+++ b/test/colors.js
@@ -0,0 +1,133 @@
+/**
+ * Module dependencies.
+ */
+
+var start = require('./common'),
+	mongoose = start.mongoose,
+	assert = require('assert'),
+	Schema = mongoose.Schema,
+	MongooseDocumentArray = mongoose.Types.DocumentArray,
+	EmbeddedDocument = require('../lib/types/embedded'),
+	DocumentArray = require('../lib/types/documentarray');
+
+/**
+ * setup
+ */
+
+var test = Schema({
+	string: String,
+	number: Number,
+	date: {
+		type: Date,
+		default: Date.now
+	}
+});
+
+function TestDoc(schema) {
+	var Subdocument = function() {
+		EmbeddedDocument.call(this, {}, new DocumentArray);
+	};
+
+	/**
+	 * Inherits from EmbeddedDocument.
+	 */
+
+	Subdocument.prototype.__proto__ = EmbeddedDocument.prototype;
+
+	/**
+	 * Set schema.
+	 */
+
+	Subdocument.prototype.$__setSchema(schema || test);
+
+	return Subdocument;
+}
+
+/**
+ * Test.
+ */
+
+describe('debug: colors', function () {
+	var db;
+	var Test;
+
+	before(function () {
+		db = start();
+		Test = db.model('Test', test, 'TEST');
+	});
+
+	after(function (done) {
+		db.close(done);
+	});
+
+	it('Document', function (done) {
+
+		var date = new Date();
+
+		Test.create([{
+			string: 'qwerty',
+			number: 123,
+			date: date
+		}, {
+			string: 'asdfgh',
+			number: 456,
+			date: date
+		}, {
+			string: 'zxcvbn',
+			number: 789,
+			date: date
+		}], function (err) {
+			assert.ifError(err);
+			Test
+				.find()
+				.lean(false)
+				.exec(function (err, docs) {
+					assert.ifError(err);
+
+					var colorfull = require('util').inspect(docs, {
+						depth: null,
+						colors: true
+					});
+
+					var colorless = require('util').inspect(docs, {
+						depth: null,
+						colors: false
+					});
+
+					// console.log(colorfull, colorless);
+
+					assert.notEqual(colorfull, colorless);
+
+					done();
+				});
+		});
+	});
+
+	it('MongooseDocumentArray', function () {
+
+		var Subdocument = TestDoc();
+
+		var sub1 = new Subdocument();
+		sub1.string = 'string';
+		sub1.number = 12345;
+		sub1.date = new Date();
+
+		var docs = new MongooseDocumentArray([sub1]);
+
+		var colorfull = require('util').inspect(docs, {
+			depth: null,
+			colors: true
+		});
+
+		var colorless = require('util').inspect(docs, {
+			depth: null,
+			colors: false
+		});
+
+		// console.log(colorfull, colorless);
+
+		assert.notEqual(colorfull, colorless);
+
+	})
+
+});

From e9c69b596a00b74ca35a00d05a7d840a000c7d5a Mon Sep 17 00:00:00 2001
From: CTAPbIuMABP 
Date: Sun, 10 Jan 2016 16:50:34 +0800
Subject: [PATCH 0188/2240] Travis CI


From 0960d29ff9868bcf39ff0de6e2aac0d769d00dd3 Mon Sep 17 00:00:00 2001
From: CTAPbIuMABP 
Date: Sun, 10 Jan 2016 17:33:04 +0800
Subject: [PATCH 0189/2240] 2 failing tests fixed

---
 lib/document.js    |  5 ++++-
 test/model.test.js | 10 +++++-----
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index 191b64e6465..7efd8fa3178 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -14,6 +14,7 @@ var EventEmitter = require('events').EventEmitter,
     utils = require('./utils'),
     clone = utils.clone,
     isMongooseObject = utils.isMongooseObject,
+    inspect = require('util').inspect,
     ValidationError = MongooseError.ValidationError,
     InternalCache = require('./internal'),
     deepEqual = utils.deepEqual,
@@ -2118,7 +2119,9 @@ Document.prototype.inspect = function(options) {
  * @method toString
  */
 
-Document.prototype.toString = Document.prototype.inspect;
+Document.prototype.toString = function () {
+  return inspect(this.inspect());
+};
 
 /**
  * Returns true if the Document stores the same data as doc.
diff --git a/test/model.test.js b/test/model.test.js
index 214e008c51c..e5d4d7a00d7 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -4180,11 +4180,11 @@ describe('Model', function() {
       db.close();
 
       var out = post.inspect();
-      assert.ok(/meta: { visitors: 45 }/.test(out));
-      assert.ok(/numbers: \[ 5, 6, 7 \]/.test(out));
-      assert.ok(/Wed.+ 2011 \d\d:02:31 GMT/.test(out));
-      assert.ok(!/activePaths:/.test(out));
-      assert.ok(!/_atomics:/.test(out));
+      assert.equal(out.meta.visitors, post.meta.visitors);
+      assert.deepEqual(out.numbers, Array.prototype.slice.call(post.numbers));
+      assert.equal(out.date.valueOf(), post.date.valueOf());
+      assert.equal(out.activePaths, undefined);
+      assert.equal(out._atomics, undefined);
       done();
     });
   });

From bdb2248b53cbf5f07e4238e6d44a40d86d32c463 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sun, 10 Jan 2016 17:05:47 -0500
Subject: [PATCH 0190/2240] chore: now working on 4.3.6

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index c3a6d92845e..5ada2d389d4 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.5",
+  "version": "4.3.6-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From fd0f0981564955ea403ab52f047913354e93b8a9 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 11 Jan 2016 09:49:23 -0500
Subject: [PATCH 0191/2240] docs: clarify versionKey is a string (Fix #3747)

---
 docs/guide.jade | 11 +++++++++--
 lib/schema.js   |  2 +-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/docs/guide.jade b/docs/guide.jade
index d3de6564737..d38d10dd468 100644
--- a/docs/guide.jade
+++ b/docs/guide.jade
@@ -577,7 +577,12 @@ block content
 
   h4#versionKey option: versionKey
   :markdown
-    The `versionKey` is a property set on each document when first created by Mongoose. This keys value contains the internal [revision](http://aaronheckmann.tumblr.com/post/48943525537/mongoose-v3-part-1-versioning) of the document. The name of this document property is configurable. The default is `__v`. If this conflicts with your application you can configure as such:
+    The `versionKey` is a property set on each document when first created by
+    Mongoose. This keys value contains the internal
+    [revision](http://aaronheckmann.tumblr.com/post/48943525537/mongoose-v3-part-1-versioning)
+    of the document. The `versionKey` option is a string that represents the
+    path to use for versioning. The default is `__v`. If this conflicts with
+    your application you can configure as such:
   :js
     var schema = new Schema({ name: 'string' });
     var Thing = mongoose.model('Thing', schema);
@@ -591,7 +596,9 @@ block content
     thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
 
   :markdown
-    Document versioning can also be disabled by setting the `versionKey` to false. _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.tumblr.com/post/48943525537/mongoose-v3-part-1-versioning)._
+    Document versioning can also be disabled by setting the `versionKey` to
+    `false`.
+    _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.tumblr.com/post/48943525537/mongoose-v3-part-1-versioning)._
   :js
     new Schema({..}, { versionKey: false });
     var Thing = mongoose.model('Thing', schema);
diff --git a/lib/schema.js b/lib/schema.js
index ffed15c1a9e..a6bd8b38ece 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -49,7 +49,7 @@ var IS_QUERY_HOOK = {
  * - [toObject](/docs/guide.html#toObject) - object - no default
  * - [typeKey](/docs/guide.html#typeKey) - string - defaults to 'type'
  * - [validateBeforeSave](/docs/guide.html#validateBeforeSave) - bool - defaults to `true`
- * - [versionKey](/docs/guide.html#versionKey): bool - defaults to "__v"
+ * - [versionKey](/docs/guide.html#versionKey): string - defaults to "__v"
  *
  * ####Note:
  *

From a005927830ed53fa46a153bda123156fa7f21044 Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Mon, 11 Jan 2016 09:07:34 -0700
Subject: [PATCH 0192/2240] general linting

---
 lib/document.js              |   4 +-
 lib/schema.js                |   2 +-
 lib/schema/documentarray.js  |   1 -
 lib/types/documentarray.js   |   1 -
 lib/types/embedded.js        |   1 -
 package.json                 |   2 +-
 test/aggregate.test.js       |   8 +-
 test/colors.js               | 174 +++++++++++------------
 test/document.strict.test.js |   2 +-
 test/model.test.js           |   6 +-
 test/model.update.test.js    |   2 +-
 test/schema.test.js          |   6 +-
 test/types.buffer.test.js    | 262 +++++++++++++++++------------------
 13 files changed, 234 insertions(+), 237 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index 7efd8fa3178..b147c543a6e 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -516,7 +516,7 @@ Document.prototype.set = function(path, val, type, options) {
             this.set(prefix + key,
               path[key].toObject({ virtuals: false }), constructing);
           } else if ('throw' == strict) {
-            if (pathtype ==='nested') {
+            if (pathtype === 'nested') {
               throw new ObjectExpectedError(key, path[key]);
             } else {
               throw new StrictModeError(key);
@@ -2119,7 +2119,7 @@ Document.prototype.inspect = function(options) {
  * @method toString
  */
 
-Document.prototype.toString = function () {
+Document.prototype.toString = function() {
   return inspect(this.inspect());
 };
 
diff --git a/lib/schema.js b/lib/schema.js
index a6bd8b38ece..8b699be6ccf 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -500,7 +500,7 @@ Schema.prototype.path = function(path, obj) {
       this.singleNestedPaths[path + '.' + key] =
         this.paths[path].schema.paths[key];
     }
-    for (var key in this.paths[path].schema.singleNestedPaths) {
+    for (key in this.paths[path].schema.singleNestedPaths) {
       this.singleNestedPaths[path + '.' + key] =
         this.paths[path].schema.singleNestedPaths[key];
     }
diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js
index 06b5fe5751a..8fd2b6df332 100644
--- a/lib/schema/documentarray.js
+++ b/lib/schema/documentarray.js
@@ -74,7 +74,6 @@ DocumentArray.prototype.constructor = DocumentArray;
  */
 
 DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
-  var _this = this;
   SchemaType.prototype.doValidate.call(this, array, function(err) {
     if (err) {
       return fn(err);
diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js
index 5f78a8d07d4..ec8dddc8b37 100644
--- a/lib/types/documentarray.js
+++ b/lib/types/documentarray.js
@@ -6,7 +6,6 @@ var MongooseArray = require('./array'),
     ObjectId = require('./objectid'),
     ObjectIdSchema = require('../schema/objectid'),
     utils = require('../utils'),
-    util = require('util'),
     Document = require('../document');
 
 /**
diff --git a/lib/types/embedded.js b/lib/types/embedded.js
index 0d00ae810cf..cc7918d3440 100644
--- a/lib/types/embedded.js
+++ b/lib/types/embedded.js
@@ -5,7 +5,6 @@
  */
 
 var Document = require('../document_provider')();
-var inspect = require('util').inspect;
 var PromiseProvider = require('../promise_provider');
 
 /**
diff --git a/package.json b/package.json
index 5ada2d389d4..cc7a30eb476 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
     "bluebird": "2.9.34",
     "co": "3.1.0",
     "dox": "0.3.1",
-    "eslint": "1.10.1",
+    "eslint": "2.0.0-alpha-2",
     "highlight.js": "7.0.1",
     "istanbul": "^0.3.13",
     "jade": "0.26.3",
diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index a04feb647b1..eff4fabc4b7 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -67,7 +67,7 @@ describe('aggregate: ', function() {
       done();
     });
 
-    it('supports array as single argument', function (done) {
+    it('supports array as single argument', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.append([{$a: 1}, {$b: 2}, {$c: 3}]), aggregate);
@@ -95,7 +95,7 @@ describe('aggregate: ', function() {
         aggregate.append({ $a: 1 }, { a: 1 });
       }, regexp);
 
-      assert.throws(function () {
+      assert.throws(function() {
         aggregate.append([{$a: 1}, {a: 1}]);
       }, regexp);
 
@@ -112,10 +112,10 @@ describe('aggregate: ', function() {
       done();
     });
 
-    it('does not throw when empty array is passed as single argument', function (done) {
+    it('does not throw when empty array is passed as single argument', function(done) {
       var aggregate = new Aggregate();
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         aggregate.append([]);
       });
 
diff --git a/test/colors.js b/test/colors.js
index ab99d1bebb6..ce31c5c7f25 100644
--- a/test/colors.js
+++ b/test/colors.js
@@ -3,131 +3,131 @@
  */
 
 var start = require('./common'),
-	mongoose = start.mongoose,
-	assert = require('assert'),
-	Schema = mongoose.Schema,
-	MongooseDocumentArray = mongoose.Types.DocumentArray,
-	EmbeddedDocument = require('../lib/types/embedded'),
-	DocumentArray = require('../lib/types/documentarray');
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    Schema = mongoose.Schema,
+    MongooseDocumentArray = mongoose.Types.DocumentArray,
+    EmbeddedDocument = require('../lib/types/embedded'),
+    DocumentArray = require('../lib/types/documentarray');
 
 /**
  * setup
  */
 
 var test = Schema({
-	string: String,
-	number: Number,
-	date: {
-		type: Date,
-		default: Date.now
-	}
+  string: String,
+  number: Number,
+  date: {
+    type: Date,
+    default: Date.now
+  }
 });
 
 function TestDoc(schema) {
-	var Subdocument = function() {
-		EmbeddedDocument.call(this, {}, new DocumentArray);
-	};
+  var Subdocument = function() {
+    EmbeddedDocument.call(this, {}, new DocumentArray);
+  };
 
-	/**
-	 * Inherits from EmbeddedDocument.
-	 */
+  /**
+   * Inherits from EmbeddedDocument.
+   */
 
-	Subdocument.prototype.__proto__ = EmbeddedDocument.prototype;
+  Subdocument.prototype.__proto__ = EmbeddedDocument.prototype;
 
-	/**
-	 * Set schema.
-	 */
+  /**
+   * Set schema.
+   */
 
-	Subdocument.prototype.$__setSchema(schema || test);
+  Subdocument.prototype.$__setSchema(schema || test);
 
-	return Subdocument;
+  return Subdocument;
 }
 
 /**
  * Test.
  */
 
-describe('debug: colors', function () {
-	var db;
-	var Test;
+describe('debug: colors', function() {
+  var db;
+  var Test;
 
-	before(function () {
-		db = start();
-		Test = db.model('Test', test, 'TEST');
-	});
+  before(function() {
+    db = start();
+    Test = db.model('Test', test, 'TEST');
+  });
 
-	after(function (done) {
-		db.close(done);
-	});
+  after(function(done) {
+    db.close(done);
+  });
 
-	it('Document', function (done) {
+  it('Document', function(done) {
 
-		var date = new Date();
+    var date = new Date();
 
-		Test.create([{
-			string: 'qwerty',
-			number: 123,
-			date: date
-		}, {
-			string: 'asdfgh',
-			number: 456,
-			date: date
-		}, {
-			string: 'zxcvbn',
-			number: 789,
-			date: date
-		}], function (err) {
-			assert.ifError(err);
-			Test
-				.find()
-				.lean(false)
-				.exec(function (err, docs) {
-					assert.ifError(err);
+    Test.create([{
+      string: 'qwerty',
+      number: 123,
+      date: date
+    }, {
+      string: 'asdfgh',
+      number: 456,
+      date: date
+    }, {
+      string: 'zxcvbn',
+      number: 789,
+      date: date
+    }], function(err) {
+      assert.ifError(err);
+      Test
+        .find()
+        .lean(false)
+        .exec(function(err, docs) {
+          assert.ifError(err);
 
-					var colorfull = require('util').inspect(docs, {
-						depth: null,
-						colors: true
-					});
+          var colorfull = require('util').inspect(docs, {
+            depth: null,
+            colors: true
+          });
 
-					var colorless = require('util').inspect(docs, {
-						depth: null,
-						colors: false
-					});
+          var colorless = require('util').inspect(docs, {
+            depth: null,
+            colors: false
+          });
 
-					// console.log(colorfull, colorless);
+          // console.log(colorfull, colorless);
 
-					assert.notEqual(colorfull, colorless);
+          assert.notEqual(colorfull, colorless);
 
-					done();
-				});
-		});
-	});
+          done();
+        });
+    });
+  });
 
-	it('MongooseDocumentArray', function () {
+  it('MongooseDocumentArray', function() {
 
-		var Subdocument = TestDoc();
+    var Subdocument = TestDoc();
 
-		var sub1 = new Subdocument();
-		sub1.string = 'string';
-		sub1.number = 12345;
-		sub1.date = new Date();
+    var sub1 = new Subdocument();
+    sub1.string = 'string';
+    sub1.number = 12345;
+    sub1.date = new Date();
 
-		var docs = new MongooseDocumentArray([sub1]);
+    var docs = new MongooseDocumentArray([sub1]);
 
-		var colorfull = require('util').inspect(docs, {
-			depth: null,
-			colors: true
-		});
+    var colorfull = require('util').inspect(docs, {
+      depth: null,
+      colors: true
+    });
 
-		var colorless = require('util').inspect(docs, {
-			depth: null,
-			colors: false
-		});
+    var colorless = require('util').inspect(docs, {
+      depth: null,
+      colors: false
+    });
 
-		// console.log(colorfull, colorless);
+    // console.log(colorfull, colorless);
 
-		assert.notEqual(colorfull, colorless);
+    assert.notEqual(colorfull, colorless);
 
-	})
+  });
 
 });
diff --git a/test/document.strict.test.js b/test/document.strict.test.js
index 639d3322d35..cd7be7f865c 100644
--- a/test/document.strict.test.js
+++ b/test/document.strict.test.js
@@ -451,7 +451,7 @@ describe('document: strict mode:', function() {
       var Test = mongoose.model('gh3735', schema);
 
       assert.throws(function() {
-        var t = new Test({ resolved: 123 });
+        new Test({ resolved: 123 });
       }, /ObjectExpectedError/);
     });
   });
diff --git a/test/model.test.js b/test/model.test.js
index e5d4d7a00d7..33473ce8b9b 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -2109,9 +2109,9 @@ describe('Model', function() {
           type:Number
             , set: function(x) { return x / 2;}
             , get: function(x) {
-                called = true;
-                return x * 2;
-              }
+              called = true;
+              return x * 2;
+            }
         }
       });
 
diff --git a/test/model.update.test.js b/test/model.update.test.js
index a6ab10205e3..f707cbd0593 100644
--- a/test/model.update.test.js
+++ b/test/model.update.test.js
@@ -1422,7 +1422,7 @@ describe('model: update:', function() {
           arr: [String]
         });
 
-        schema.path('arr').validate(function(v) {
+        schema.path('arr').validate(function() {
           return false;
         });
 
diff --git a/test/schema.test.js b/test/schema.test.js
index 261646c3c98..2c2ff6fe72e 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -234,9 +234,9 @@ describe('schema', function() {
       , arrayX    : { $type: Array, default: 9 }
       , arrayFn   : { $type: Array, default: function() { return [8]; } }
       , callback  : { $type: Number, default: function() {
-          assert.equal('b', this.a);
-          return '3';
-        }}
+        assert.equal('b', this.a);
+        return '3';
+      }}
     }, { typeKey: '$type' });
 
     assert.equal(Test.path('simple').defaultValue, 'a');
diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js
index 8fbded796c3..74af5701885 100644
--- a/test/types.buffer.test.js
+++ b/test/types.buffer.test.js
@@ -185,157 +185,157 @@ describe('types.buffer', function() {
                 is(tj);
               }
               , 'writeUInt16': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeUInt16(0xbeef, 0, 'little');
-                  is(tj);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeUInt16(0xbeef, 0, 'little');
+                is(tj);
+              }
               , 'writeUInt16LE': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeUInt16LE(0xbeef, 0);
-                  is(tj);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeUInt16LE(0xbeef, 0);
+                is(tj);
+              }
               , 'writeUInt16BE': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeUInt16BE(0xbeef, 0);
-                  is(tj);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeUInt16BE(0xbeef, 0);
+                is(tj);
+              }
               , 'writeUInt32': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeUInt32(0xfeedface, 0, 'little');
-                  is(tj);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeUInt32(0xfeedface, 0, 'little');
+                is(tj);
+              }
               , 'writeUInt32LE': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeUInt32LE(0xfeedface, 0);
-                  is(tj);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeUInt32LE(0xfeedface, 0);
+                is(tj);
+              }
               , 'writeUInt32BE': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeUInt32BE(0xfeedface, 0);
-                  is(tj);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeUInt32BE(0xfeedface, 0);
+                is(tj);
+              }
               , 'writeInt8': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeInt8(-5, 0, 'big');
-                  is(tj);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeInt8(-5, 0, 'big');
+                is(tj);
+              }
               , 'writeInt16': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeInt16(0x0023, 2, 'little');
-                  is(tj);
-                  assert.equal(tj.required[2], 0x23);
-                  assert.equal(tj.required[3], 0x00);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeInt16(0x0023, 2, 'little');
+                is(tj);
+                assert.equal(tj.required[2], 0x23);
+                assert.equal(tj.required[3], 0x00);
+              }
               , 'writeInt16LE': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeInt16LE(0x0023, 2);
-                  is(tj);
-                  assert.equal(tj.required[2], 0x23);
-                  assert.equal(tj.required[3], 0x00);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeInt16LE(0x0023, 2);
+                is(tj);
+                assert.equal(tj.required[2], 0x23);
+                assert.equal(tj.required[3], 0x00);
+              }
               , 'writeInt16BE': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeInt16BE(0x0023, 2);
-                  is(tj);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeInt16BE(0x0023, 2);
+                is(tj);
+              }
               , 'writeInt32': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeInt32(0x23, 0, 'big');
-                  is(tj);
-                  assert.equal(tj.required[0], 0x00);
-                  assert.equal(tj.required[1], 0x00);
-                  assert.equal(tj.required[2], 0x00);
-                  assert.equal(tj.required[3], 0x23);
-                  tj.required = new Buffer(8);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.writeInt32(0x23, 0, 'big');
+                is(tj);
+                assert.equal(tj.required[0], 0x00);
+                assert.equal(tj.required[1], 0x00);
+                assert.equal(tj.required[2], 0x00);
+                assert.equal(tj.required[3], 0x23);
+                tj.required = new Buffer(8);
+              }
               , 'writeInt32LE': function() {
-                  tj.required = new Buffer(8);
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeInt32LE(0x23, 0);
-                  is(tj);
-                }
+                tj.required = new Buffer(8);
+                reset(tj);
+                not(tj);
+                tj.required.writeInt32LE(0x23, 0);
+                is(tj);
+              }
               , 'writeInt32BE': function() {
-                  tj.required = new Buffer(8);
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeInt32BE(0x23, 0);
-                  is(tj);
-                  assert.equal(tj.required[0], 0x00);
-                  assert.equal(tj.required[1], 0x00);
-                  assert.equal(tj.required[2], 0x00);
-                  assert.equal(tj.required[3], 0x23);
-                }
+                tj.required = new Buffer(8);
+                reset(tj);
+                not(tj);
+                tj.required.writeInt32BE(0x23, 0);
+                is(tj);
+                assert.equal(tj.required[0], 0x00);
+                assert.equal(tj.required[1], 0x00);
+                assert.equal(tj.required[2], 0x00);
+                assert.equal(tj.required[3], 0x23);
+              }
               , 'writeFloat': function() {
-                  tj.required = new Buffer(16);
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeFloat(2.225073858507201e-308, 0, 'big');
-                  is(tj);
-                  assert.equal(tj.required[0], 0x00);
-                  assert.equal(tj.required[1], 0x0f);
-                  assert.equal(tj.required[2], 0xff);
-                  assert.equal(tj.required[3], 0xff);
-                  assert.equal(tj.required[4], 0xff);
-                  assert.equal(tj.required[5], 0xff);
-                  assert.equal(tj.required[6], 0xff);
-                  assert.equal(tj.required[7], 0xff);
-                }
+                tj.required = new Buffer(16);
+                reset(tj);
+                not(tj);
+                tj.required.writeFloat(2.225073858507201e-308, 0, 'big');
+                is(tj);
+                assert.equal(tj.required[0], 0x00);
+                assert.equal(tj.required[1], 0x0f);
+                assert.equal(tj.required[2], 0xff);
+                assert.equal(tj.required[3], 0xff);
+                assert.equal(tj.required[4], 0xff);
+                assert.equal(tj.required[5], 0xff);
+                assert.equal(tj.required[6], 0xff);
+                assert.equal(tj.required[7], 0xff);
+              }
               , 'writeFloatLE': function() {
-                  tj.required = new Buffer(16);
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeFloatLE(2.225073858507201e-308, 0);
-                  is(tj);
-                }
+                tj.required = new Buffer(16);
+                reset(tj);
+                not(tj);
+                tj.required.writeFloatLE(2.225073858507201e-308, 0);
+                is(tj);
+              }
               , 'writeFloatBE': function() {
-                  tj.required = new Buffer(16);
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeFloatBE(2.225073858507201e-308, 0);
-                  is(tj);
-                }
+                tj.required = new Buffer(16);
+                reset(tj);
+                not(tj);
+                tj.required.writeFloatBE(2.225073858507201e-308, 0);
+                is(tj);
+              }
               , 'writeDoubleLE': function() {
-                  tj.required = new Buffer(8);
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeDoubleLE(0xdeadbeefcafebabe, 0);
-                  is(tj);
-                }
+                tj.required = new Buffer(8);
+                reset(tj);
+                not(tj);
+                tj.required.writeDoubleLE(0xdeadbeefcafebabe, 0);
+                is(tj);
+              }
               , 'writeDoubleBE': function() {
-                  tj.required = new Buffer(8);
-                  reset(tj);
-                  not(tj);
-                  tj.required.writeDoubleBE(0xdeadbeefcafebabe, 0);
-                  is(tj);
-                }
+                tj.required = new Buffer(8);
+                reset(tj);
+                not(tj);
+                tj.required.writeDoubleBE(0xdeadbeefcafebabe, 0);
+                is(tj);
+              }
               , 'fill': function() {
-                  tj.required = new Buffer(8);
-                  reset(tj);
-                  not(tj);
-                  tj.required.fill(0);
-                  is(tj);
-                  for (var i = 0; i < tj.required.length; i++) {
-                    assert.strictEqual(tj.required[i], 0);
-                  }
+                tj.required = new Buffer(8);
+                reset(tj);
+                not(tj);
+                tj.required.fill(0);
+                is(tj);
+                for (var i = 0; i < tj.required.length; i++) {
+                  assert.strictEqual(tj.required[i], 0);
                 }
+              }
               , 'set': function() {
-                  reset(tj);
-                  not(tj);
-                  tj.required.set(0, 1);
-                  is(tj);
-                }
+                reset(tj);
+                not(tj);
+                tj.required.set(0, 1);
+                is(tj);
+              }
             };
 
             var keys = Object.keys(fns)

From e3192b8bdf0c6a7f68c4d81c9d4e293b82ea9fb3 Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Mon, 11 Jan 2016 10:38:55 -0700
Subject: [PATCH 0193/2240] comma last test folder

---
 test/model.findAndRemoveOne.test.js   | 124 ++--
 test/model.findOneAndUpdate.test.js   | 254 ++++----
 test/model.geonear.test.js            | 124 ++--
 test/model.geosearch.test.js          |  52 +-
 test/model.hydrate.test.js            |  10 +-
 test/model.indexes.test.js            |  78 +--
 test/model.mapreduce.test.js          |  98 +--
 test/model.middleware.test.js         |  36 +-
 test/model.populate.divergent.test.js |  12 +-
 test/model.populate.setting.test.js   |  80 +--
 test/model.populate.test.js           | 844 +++++++++++++-------------
 11 files changed, 868 insertions(+), 844 deletions(-)

diff --git a/test/model.findAndRemoveOne.test.js b/test/model.findAndRemoveOne.test.js
index 4a882ff612e..a6e704c0ddb 100644
--- a/test/model.findAndRemoveOne.test.js
+++ b/test/model.findAndRemoveOne.test.js
@@ -3,13 +3,13 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , assert = require('assert')
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.Types.ObjectId
-  , DocumentObjectId = mongoose.Types.ObjectId;
+var start = require('./common'),
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema,
+    ObjectId = Schema.Types.ObjectId,
+    DocumentObjectId = mongoose.Types.ObjectId;
 
 /**
  * Setup.
@@ -18,26 +18,26 @@ var start = require('./common')
 var Comments = new Schema;
 
 Comments.add({
-  title     : String
-  , date      : Date
-  , body      : String
-  , comments  : [Comments]
+  title: String,
+  date: Date,
+  body: String,
+  comments: [Comments]
 });
 
 var BlogPost = new Schema({
-  title     : String
-  , author    : String
-  , slug      : String
-  , date      : Date
-  , meta      : {
-    date      : Date
-      , visitors  : Number
-  }
-  , published : Boolean
-  , mixed     : {}
-  , numbers   : [Number]
-  , owners    : [ObjectId]
-  , comments  : [Comments]
+  title: String,
+  author: String,
+  slug: String,
+  date: Date,
+  meta: {
+    date: Date,
+    visitors: Number
+  },
+  published: Boolean,
+  mixed: {},
+  numbers: [Number],
+  owners: [ObjectId],
+  comments: [Comments]
 });
 
 BlogPost.virtual('titleWithAuthor')
@@ -68,9 +68,9 @@ mongoose.model('RemoveOneStrictSchema', strictSchema);
 
 describe('model: findOneAndRemove:', function() {
   it('returns the original document', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , title = 'remove muah';
+    var db = start(),
+        M = db.model(modelname, collection),
+        title = 'remove muah';
 
     var post = new M({ title: title });
     post.save(function(err) {
@@ -89,13 +89,13 @@ describe('model: findOneAndRemove:', function() {
   });
 
   it('options/conditions/doc are merged when no callback is passed', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection);
+    var db = start(),
+        M = db.model(modelname, collection);
 
     db.close();
 
-    var now = new Date
-      , query;
+    var now = new Date,
+        query;
 
     // Model.findOneAndRemove
     query = M.findOneAndRemove({ author: 'aaron' }, { select: 'author' });
@@ -128,9 +128,9 @@ describe('model: findOneAndRemove:', function() {
   });
 
   it('executes when a callback is passed', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection + random())
-      , pending = 5;
+    var db = start(),
+        M = db.model(modelname, collection + random()),
+        pending = 5;
 
     M.findOneAndRemove({ name: 'aaron1' }, { select: 'name' }, cb);
     M.findOneAndRemove({ name: 'aaron1' }, cb);
@@ -148,9 +148,9 @@ describe('model: findOneAndRemove:', function() {
   });
 
   it('executed with only a callback throws', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , err;
+    var db = start(),
+        M = db.model(modelname, collection),
+        err;
 
     try {
       M.findOneAndRemove(function() {});
@@ -167,9 +167,9 @@ describe('model: findOneAndRemove:', function() {
 
 describe('model: findByIdAndRemove:', function() {
   it('executed with only a callback throws', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , err;
+    var db = start(),
+        M = db.model(modelname, collection),
+        err;
 
     try {
       M.findByIdAndRemove(function() {});
@@ -183,10 +183,10 @@ describe('model: findByIdAndRemove:', function() {
   });
 
   it('executes when a callback is passed', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection + random())
-      , _id = new DocumentObjectId
-      , pending = 2;
+    var db = start(),
+        M = db.model(modelname, collection + random()),
+        _id = new DocumentObjectId,
+        pending = 2;
 
     M.findByIdAndRemove(_id, { select: 'name' }, cb);
     M.findByIdAndRemove(_id, cb);
@@ -201,9 +201,9 @@ describe('model: findByIdAndRemove:', function() {
   });
 
   it('returns the original document', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , title = 'remove muah pleez';
+    var db = start(),
+        M = db.model(modelname, collection),
+        title = 'remove muah pleez';
 
     var post = new M({ title: title });
     post.save(function(err) {
@@ -222,9 +222,9 @@ describe('model: findByIdAndRemove:', function() {
   });
 
   it('options/conditions/doc are merged when no callback is passed', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , _id = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        _id = new DocumentObjectId;
 
     db.close();
 
@@ -247,9 +247,9 @@ describe('model: findByIdAndRemove:', function() {
   });
 
   it('supports v3 select string syntax', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , _id = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        _id = new DocumentObjectId;
 
     db.close();
 
@@ -266,9 +266,9 @@ describe('model: findByIdAndRemove:', function() {
   });
 
   it('supports v3 select object syntax', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , _id = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        _id = new DocumentObjectId;
 
     db.close();
 
@@ -285,9 +285,9 @@ describe('model: findByIdAndRemove:', function() {
   });
 
   it('supports v3 sort string syntax', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , _id = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        _id = new DocumentObjectId;
 
     db.close();
 
@@ -306,9 +306,9 @@ describe('model: findByIdAndRemove:', function() {
   });
 
   it('supports v3 sort object syntax', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , _id = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        _id = new DocumentObjectId;
 
     var query;
 
diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index e9c5a72d228..7d98d929c3a 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -21,26 +21,26 @@ var _ = require('underscore');
 var Comments = new Schema();
 
 Comments.add({
-  title     : String
-  , date      : Date
-  , body      : String
-  , comments  : [Comments]
+  title: String,
+  date: Date,
+  body: String,
+  comments: [Comments]
 });
 
 var BlogPost = new Schema({
-  title     : String
-  , author    : String
-  , slug      : String
-  , date      : Date
-  , meta      : {
-    date      : Date
-      , visitors  : Number
-  }
-  , published : Boolean
-  , mixed     : {}
-  , numbers   : [Number]
-  , owners    : [ObjectId]
-  , comments  : [Comments]
+  title: String,
+  author: String,
+  slug: String,
+  date: Date,
+  meta: {
+    date: Date,
+    visitors: Number
+  },
+  published: Boolean,
+  mixed: {},
+  numbers: [Number],
+  owners: [ObjectId],
+  comments: [Comments]
 });
 
 BlogPost.virtual('titleWithAuthor')
@@ -74,13 +74,13 @@ mongoose.model('UpdateOneStrictThrowSchema', strictThrowSchema);
 
 describe('model: findOneAndUpdate:', function() {
   it('WWW returns the edited document', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , title = 'Tobi ' + random()
-      , author = 'Brian ' + random()
-      , newTitle = 'Woot ' + random()
-      , id0 = new DocumentObjectId
-      , id1 = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        title = 'Tobi ' + random(),
+        author = 'Brian ' + random(),
+        newTitle = 'Woot ' + random(),
+        id0 = new DocumentObjectId,
+        id1 = new DocumentObjectId;
 
     var post = new M;
     post.set('title', title);
@@ -116,14 +116,14 @@ describe('model: findOneAndUpdate:', function() {
         assert.ok(cf.comments[1]._id instanceof DocumentObjectId);
 
         var update = {
-          title: newTitle // becomes $set
-          , $inc: { 'meta.visitors': 2 }
-          , $set: { date: new Date }
-          , published: false // becomes $set
-          , 'mixed': { x: 'ECKS', y: 'why' } // $set
-          , $pullAll: { 'numbers': [4, 6] }
-          , $pull: { 'owners': id0 }
-          , 'comments.1.body': 8 // $set
+          title: newTitle, // becomes $set
+          $inc: { 'meta.visitors': 2 },
+          $set: { date: new Date },
+          published: false, // becomes $set
+          'mixed': { x: 'ECKS', y: 'why' }, // $set
+          $pullAll: { 'numbers': [4, 6] },
+          $pull: { 'owners': id0 },
+          'comments.1.body': 8 // $set
         };
 
         M.findOneAndUpdate({ title: title }, update, { 'new': true }, function(err, up) {
@@ -219,13 +219,13 @@ describe('model: findOneAndUpdate:', function() {
   });
 
   it('returns the original document', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , title = 'Tobi ' + random()
-      , author = 'Brian ' + random()
-      , newTitle = 'Woot ' + random()
-      , id0 = new DocumentObjectId
-      , id1 = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        title = 'Tobi ' + random(),
+        author = 'Brian ' + random(),
+        newTitle = 'Woot ' + random(),
+        id0 = new DocumentObjectId,
+        id1 = new DocumentObjectId;
 
     var post = new M;
     post.set('title', title);
@@ -244,14 +244,14 @@ describe('model: findOneAndUpdate:', function() {
         assert.ifError(err);
 
         var update = {
-          title: newTitle // becomes $set
-          , $inc: { 'meta.visitors': 2 }
-          , $set: { date: new Date }
-          , published: false // becomes $set
-          , 'mixed': { x: 'ECKS', y: 'why' } // $set
-          , $pullAll: { 'numbers': [4, 6] }
-          , $pull: { 'owners': id0 }
-          , 'comments.1.body': 8 // $set
+          title: newTitle, // becomes $set
+          $inc: { 'meta.visitors': 2 },
+          $set: { date: new Date },
+          published: false, // becomes $set
+          'mixed': { x: 'ECKS', y: 'why' }, // $set
+          $pullAll: { 'numbers': [4, 6] },
+          $pull: { 'owners': id0 },
+          'comments.1.body': 8 // $set
         };
 
         M.findOneAndUpdate({ title: title }, update, { new: false }, function(err, up) {
@@ -281,13 +281,13 @@ describe('model: findOneAndUpdate:', function() {
   });
 
   it('allows upserting', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , title = 'Tobi ' + random()
-      , author = 'Brian ' + random()
-      , newTitle = 'Woot ' + random()
-      , id0 = new DocumentObjectId
-      , id1 = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        title = 'Tobi ' + random(),
+        author = 'Brian ' + random(),
+        newTitle = 'Woot ' + random(),
+        id0 = new DocumentObjectId,
+        id1 = new DocumentObjectId;
 
     var post = new M;
     post.set('title', title);
@@ -301,13 +301,13 @@ describe('model: findOneAndUpdate:', function() {
     post.comments = [{ body: 'been there' }, { body: 'done that' }];
 
     var update = {
-      title: newTitle // becomes $set
-      , $inc: { 'meta.visitors': 2 }
-      , $set: { date: new Date }
-      , published: false // becomes $set
-      , 'mixed': { x: 'ECKS', y: 'why' } // $set
-      , $pullAll: { 'numbers': [4, 6] }
-      , $pull: { 'owners': id0 }
+      title: newTitle, // becomes $set
+      $inc: { 'meta.visitors': 2 },
+      $set: { date: new Date },
+      published: false, // becomes $set
+      'mixed': { x: 'ECKS', y: 'why' }, // $set
+      $pullAll: { 'numbers': [4, 6] },
+      $pull: { 'owners': id0 }
     };
 
     M.findOneAndUpdate({ title: title }, update, { upsert: true, new: true }, function(err, up) {
@@ -329,13 +329,13 @@ describe('model: findOneAndUpdate:', function() {
   });
 
   it('options/conditions/doc are merged when no callback is passed', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection);
+    var db = start(),
+        M = db.model(modelname, collection);
 
     db.close();
 
-    var now = new Date
-      , query;
+    var now = new Date,
+        query;
 
     // Model.findOneAndUpdate
     query = M.findOneAndUpdate({ author: 'aaron' }, { $set: { date: now }}, { new: false, fields: 'author' });
@@ -383,9 +383,9 @@ describe('model: findOneAndUpdate:', function() {
   });
 
   it('executes when a callback is passed', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection + random())
-      , pending = 6;
+    var db = start(),
+        M = db.model(modelname, collection + random()),
+        pending = 6;
 
     M.findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron6'}}, { new: false }, cb);
     M.findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron4'}}, cb);
@@ -404,9 +404,9 @@ describe('model: findOneAndUpdate:', function() {
   });
 
   it('executes when a callback is passed to a succeeding function', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection + random())
-      , pending = 6;
+    var db = start(),
+        M = db.model(modelname, collection + random()),
+        pending = 6;
 
     M.findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron'}}, { new: false }).exec(cb);
     M.findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron'}}).exec(cb);
@@ -425,9 +425,9 @@ describe('model: findOneAndUpdate:', function() {
   });
 
   it('executing with only a callback throws', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , err;
+    var db = start(),
+        M = db.model(modelname, collection),
+        err;
 
     try {
       M.findOneAndUpdate(function() {});
@@ -441,9 +441,9 @@ describe('model: findOneAndUpdate:', function() {
   });
 
   it('updates numbers atomically', function(done) {
-    var db = start()
-      , BlogPost = db.model(modelname, collection)
-      , totalDocs = 4;
+    var db = start(),
+        BlogPost = db.model(modelname, collection),
+        totalDocs = 4;
 
     var post = new BlogPost();
     post.set('meta.visitors', 5);
@@ -531,9 +531,9 @@ describe('model: findOneAndUpdate:', function() {
 
 describe('model: findByIdAndUpdate:', function() {
   it('executing with just a callback throws', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , err;
+    var db = start(),
+        M = db.model(modelname, collection),
+        err;
 
     try {
       M.findByIdAndUpdate(function() {});
@@ -547,10 +547,10 @@ describe('model: findByIdAndUpdate:', function() {
   });
 
   it('executes when a callback is passed', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection + random())
-      , _id = new DocumentObjectId
-      , pending = 2;
+    var db = start(),
+        M = db.model(modelname, collection + random()),
+        _id = new DocumentObjectId,
+        pending = 2;
 
     M.findByIdAndUpdate(_id, { $set: { name: 'Aaron'}}, { new: false }, cb);
     M.findByIdAndUpdate(_id, { $set: { name: 'changed' }}, cb);
@@ -564,10 +564,10 @@ describe('model: findByIdAndUpdate:', function() {
   });
 
   it('executes when a callback is passed to a succeeding function', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection + random())
-      , _id = new DocumentObjectId
-      , pending = 2;
+    var db = start(),
+        M = db.model(modelname, collection + random()),
+        _id = new DocumentObjectId,
+        pending = 2;
 
     M.findByIdAndUpdate(_id, { $set: { name: 'Aaron'}}, { new: false }).exec(cb);
     M.findByIdAndUpdate(_id, { $set: { name: 'changed' }}).exec(cb);
@@ -581,13 +581,13 @@ describe('model: findByIdAndUpdate:', function() {
   });
 
   it('returns the original document', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , title = 'Tobi ' + random()
-      , author = 'Brian ' + random()
-      , newTitle = 'Woot ' + random()
-      , id0 = new DocumentObjectId
-      , id1 = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        title = 'Tobi ' + random(),
+        author = 'Brian ' + random(),
+        newTitle = 'Woot ' + random(),
+        id0 = new DocumentObjectId,
+        id1 = new DocumentObjectId;
 
     var post = new M;
     post.set('title', title);
@@ -606,14 +606,14 @@ describe('model: findByIdAndUpdate:', function() {
         assert.ifError(err);
 
         var update = {
-          title: newTitle // becomes $set
-          , $inc: { 'meta.visitors': 2 }
-          , $set: { date: new Date }
-          , published: false // becomes $set
-          , 'mixed': { x: 'ECKS', y: 'why' } // $set
-          , $pullAll: { 'numbers': [4, 6] }
-          , $pull: { 'owners': id0 }
-          , 'comments.1.body': 8 // $set
+          title: newTitle, // becomes $set
+          $inc: { 'meta.visitors': 2 },
+          $set: { date: new Date },
+          published: false, // becomes $set
+          'mixed': { x: 'ECKS', y: 'why' }, // $set
+          $pullAll: { 'numbers': [4, 6] },
+          $pull: { 'owners': id0 },
+          'comments.1.body': 8 // $set
         };
 
         M.findByIdAndUpdate(post.id, update, { new: false }, function(err, up) {
@@ -642,12 +642,12 @@ describe('model: findByIdAndUpdate:', function() {
   });
 
   it('options/conditions/doc are merged when no callback is passed', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , _id = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        _id = new DocumentObjectId;
 
-    var now = new Date
-      , query;
+    var now = new Date,
+        query;
 
     // Model.findByIdAndUpdate
     query = M.findByIdAndUpdate(_id, { $set: { date: now }}, { new: false, fields: 'author' });
@@ -673,12 +673,12 @@ describe('model: findByIdAndUpdate:', function() {
   });
 
   it('supports v3 select string syntax', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , _id = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        _id = new DocumentObjectId;
 
-    var now = new Date
-      , query;
+    var now = new Date,
+        query;
 
     query = M.findByIdAndUpdate(_id, { $set: { date: now }}, { select: 'author -title' });
     assert.strictEqual(1, query._fields.author);
@@ -691,12 +691,12 @@ describe('model: findByIdAndUpdate:', function() {
   });
 
   it('supports v3 select object syntax', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , _id = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        _id = new DocumentObjectId;
 
-    var now = new Date
-      , query;
+    var now = new Date,
+        query;
 
     query = M.findByIdAndUpdate(_id, { $set: { date: now }}, { select: { author: 1, title: 0 }});
     assert.strictEqual(1, query._fields.author);
@@ -709,8 +709,8 @@ describe('model: findByIdAndUpdate:', function() {
   });
 
   it('supports v3 sort string syntax', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection);
+    var db = start(),
+        M = db.model(modelname, collection);
 
     var now = new Date;
     var _id = new DocumentObjectId;
@@ -745,12 +745,12 @@ describe('model: findByIdAndUpdate:', function() {
   });
 
   it('supports v3 sort object syntax', function(done) {
-    var db = start()
-      , M = db.model(modelname, collection)
-      , _id = new DocumentObjectId;
+    var db = start(),
+        M = db.model(modelname, collection),
+        _id = new DocumentObjectId;
 
-    var now = new Date
-      , query;
+    var now = new Date,
+        query;
 
     query = M.findByIdAndUpdate(_id, { $set: { date: now }}, { sort: { author: 1, title: -1 }});
     assert.equal(2, Object.keys(query.options.sort).length);
@@ -769,8 +769,8 @@ describe('model: findByIdAndUpdate:', function() {
     var db = start();
 
     var postSchema = new Schema({
-      ids: [{type: Schema.ObjectId}]
-      , title: String
+      ids: [{type: Schema.ObjectId}],
+      title: String
     });
 
     var B = db.model('gh-1091+1100', postSchema);
diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js
index 8ddc2066b02..ad4659b9b75 100644
--- a/test/model.geonear.test.js
+++ b/test/model.geonear.test.js
@@ -1,16 +1,16 @@
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema;
 
 /**
  * Setup
  */
 
 var schema = new Schema({
-  coordinates : { type: [Number], index: '2dsphere' },
+  coordinates: { type: [Number], index: '2dsphere' },
   type: String
 });
 
@@ -19,11 +19,11 @@ function getModel(db) {
 }
 
 var testLocations = {
-  MONGODB_NYC_OFFICE :     [-73.987732, 40.757471]
-  , BRYANT_PART_NY :         [-73.983677, 40.753628]
-  , EAST_HARLEM_SHOP :       [-73.93831, 40.794963]
-  , CENTRAL_PARK_ZOO :       [-73.972299, 40.767732]
-  , PORT_AUTHORITY_STATION : [-73.990147, 40.757253]
+  MONGODB_NYC_OFFICE: [-73.987732, 40.757471],
+  BRYANT_PART_NY: [-73.983677, 40.753628],
+  EAST_HARLEM_SHOP: [-73.93831, 40.794963],
+  CENTRAL_PARK_ZOO: [-73.972299, 40.767732],
+  PORT_AUTHORITY_STATION: [-73.990147, 40.757253]
 };
 
 // convert meters to radians for use as legacy coordinates
@@ -53,14 +53,22 @@ describe('model', function() {
         assert.ifError(err);
 
         var geos = [];
-        geos[0] = new Geo({ coordinates : testLocations.MONGODB_NYC_OFFICE
-                            , type : "Point"});
-        geos[1] = new Geo({ coordinates : testLocations.BRYANT_PARK_NY
-                            , type : "Point"});
-        geos[2] = new Geo({ coordinates : testLocations.EAST_HARLEM_SHOP
-                            , type : "Point"});
-        geos[3] = new Geo({ coordinates : testLocations.CENTRAL_PARK_ZOO
-                            , type : "Point"});
+        geos[0] = new Geo({
+          coordinates: testLocations.MONGODB_NYC_OFFICE,
+          type: "Point"
+        });
+        geos[1] = new Geo({
+          coordinates: testLocations.BRYANT_PARK_NY,
+          type: "Point"
+        });
+        geos[2] = new Geo({
+          coordinates: testLocations.EAST_HARLEM_SHOP,
+          type: "Point"
+        });
+        geos[3] = new Geo({
+          coordinates: testLocations.CENTRAL_PARK_ZOO,
+          type: "Point"
+        });
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
@@ -98,14 +106,22 @@ describe('model', function() {
         assert.ifError(err);
 
         var geos = [];
-        geos[0] = new Geo({ coordinates : testLocations.MONGODB_NYC_OFFICE
-                            , type : "Point"});
-        geos[1] = new Geo({ coordinates : testLocations.BRANT_PARK_NY
-                            , type : "Point"});
-        geos[2] = new Geo({ coordinates : testLocations.EAST_HARLEM_SHOP
-                            , type : "Point"});
-        geos[3] = new Geo({ coordinates : testLocations.CENTRAL_PARK_ZOO
-                            , type : "Point"});
+        geos[0] = new Geo({
+          coordinates: testLocations.MONGODB_NYC_OFFICE,
+          type: "Point"
+        });
+        geos[1] = new Geo({
+          coordinates: testLocations.BRANT_PARK_NY,
+          type: "Point"
+        });
+        geos[2] = new Geo({
+          coordinates: testLocations.EAST_HARLEM_SHOP,
+          type: "Point"
+        });
+        geos[3] = new Geo({
+          coordinates: testLocations.CENTRAL_PARK_ZOO,
+          type: "Point"
+        });
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
@@ -115,8 +131,8 @@ describe('model', function() {
         }
 
         function next() {
-          var pnt = { type : "Point", coordinates : testLocations.PORT_AUTHORITY_STATION };
-          Geo.geoNear(pnt, { spherical : true, maxDistance : 300 }, function(err, results) {
+          var pnt = { type: "Point", coordinates: testLocations.PORT_AUTHORITY_STATION };
+          Geo.geoNear(pnt, { spherical: true, maxDistance: 300 }, function(err, results) {
             assert.ifError(err);
 
             assert.equal(1, results.length);
@@ -143,14 +159,22 @@ describe('model', function() {
         assert.ifError(err);
 
         var geos = [];
-        geos[0] = new Geo({ coordinates : testLocations.MONGODB_NYC_OFFICE
-                            , type : "Point"});
-        geos[1] = new Geo({ coordinates : testLocations.BRANT_PARK_NY
-                            , type : "Point"});
-        geos[2] = new Geo({ coordinates : testLocations.EAST_HARLEM_SHOP
-                            , type : "Point"});
-        geos[3] = new Geo({ coordinates : testLocations.CENTRAL_PARK_ZOO
-                            , type : "Point"});
+        geos[0] = new Geo({
+          coordinates: testLocations.MONGODB_NYC_OFFICE,
+          type: "Point"
+        });
+        geos[1] = new Geo({
+          coordinates: testLocations.BRANT_PARK_NY,
+          type: "Point"
+        });
+        geos[2] = new Geo({
+          coordinates: testLocations.EAST_HARLEM_SHOP,
+          type: "Point"
+        });
+        geos[3] = new Geo({
+          coordinates: testLocations.CENTRAL_PARK_ZOO,
+          type: "Point"
+        });
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
@@ -160,8 +184,8 @@ describe('model', function() {
         }
 
         function next() {
-          var pnt = { type : "Point", coordinates : testLocations.PORT_AUTHORITY_STATION };
-          Geo.geoNear(pnt, { spherical : true, maxDistance : 300, lean : true }, function(err, results) {
+          var pnt = { type: "Point", coordinates: testLocations.PORT_AUTHORITY_STATION };
+          Geo.geoNear(pnt, { spherical: true, maxDistance: 300, lean: true }, function(err, results) {
             assert.ifError(err);
 
             assert.equal(1, results.length);
@@ -187,7 +211,7 @@ describe('model', function() {
       Geo.on('index', function(err) {
         assert.ifError(err);
 
-        var g = new Geo({ coordinates : [10,10], type : "place"});
+        var g = new Geo({ coordinates: [10,10], type: "place"});
         g.save(function() {
           Geo.geoNear("1,2", {}, function(e) {
             assert.ok(e);
@@ -197,11 +221,11 @@ describe('model', function() {
               assert.ok(e);
               assert.equal(e.message, "If using legacy coordinates, must be an array of size 2 for geoNear");
 
-              Geo.geoNear({ type : "Square" }, {}, function(e) {
+              Geo.geoNear({ type: "Square" }, {}, function(e) {
                 assert.ok(e);
                 assert.equal(e.message, "Must pass either a legacy coordinate array or GeoJSON Point to geoNear");
 
-                Geo.geoNear({ type : "Point", coordinates : "1,2" }, {}, function(e) {
+                Geo.geoNear({ type: "Point", coordinates: "1,2" }, {}, function(e) {
                   assert.ok(e);
                   assert.equal(e.message, "Must pass either a legacy coordinate array or GeoJSON Point to geoNear");
 
@@ -218,9 +242,9 @@ describe('model', function() {
       var db = start();
       var Geo = getModel(db);
 
-      var pnt = { type : "Point", coordinates : testLocations.PORT_AUTHORITY_STATION };
+      var pnt = { type: "Point", coordinates: testLocations.PORT_AUTHORITY_STATION };
       // using GeoJSON point
-      var prom = Geo.geoNear(pnt, { spherical : true, maxDistance : 300 }, function() {});
+      var prom = Geo.geoNear(pnt, { spherical: true, maxDistance: 300 }, function() {});
       assert.ok(prom instanceof mongoose.Promise);
       db.close();
       done();
@@ -232,14 +256,14 @@ describe('model', function() {
       var Geo = getModel(db);
       Geo.on('index', function(err) {
         assert.ifError(err);
-        var g = new Geo({ coordinates : testLocations.MONGODB_NYC_OFFICE, type : "Point"});
+        var g = new Geo({ coordinates: testLocations.MONGODB_NYC_OFFICE, type: "Point"});
         g.save(function(err) {
           assert.ifError(err);
 
-          var pnt = { type : "Point", coordinates : testLocations.PORT_AUTHORITY_STATION };
+          var pnt = { type: "Point", coordinates: testLocations.PORT_AUTHORITY_STATION };
           var promise;
           assert.doesNotThrow(function() {
-            promise = Geo.geoNear(pnt, { spherical : true, maxDistance : 300 });
+            promise = Geo.geoNear(pnt, { spherical: true, maxDistance: 300 });
           });
 
           function validate(ret, stat) {
@@ -264,14 +288,14 @@ describe('model', function() {
       var Geo = getModel(db);
       Geo.on('index', function(err) {
         assert.ifError(err);
-        var g = new Geo({ coordinates : [1,1], type : "Point"});
+        var g = new Geo({ coordinates: [1,1], type: "Point"});
         g.save(function(err) {
           assert.ifError(err);
 
-          var pnt = { type : "Point", coordinates : [90, 45] };
+          var pnt = { type: "Point", coordinates: [90, 45] };
           var promise;
           assert.doesNotThrow(function() {
-            promise = Geo.geoNear(pnt, { spherical : true, maxDistance : 1000 });
+            promise = Geo.geoNear(pnt, { spherical: true, maxDistance: 1000 });
           });
 
           function finish() {
diff --git a/test/model.geosearch.test.js b/test/model.geosearch.test.js
index b03e1cb059c..2a017f101ad 100644
--- a/test/model.geosearch.test.js
+++ b/test/model.geosearch.test.js
@@ -1,20 +1,20 @@
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema;
 
 /**
  * Setup
  */
 
 var schema = new Schema({
-  pos : [Number],
-  complex : {},
+  pos: [Number],
+  complex: {},
   type: String
 });
-schema.index({ "pos" : "geoHaystack", type : 1},{ bucketSize : 1});
+schema.index({ "pos": "geoHaystack", type: 1},{ bucketSize: 1});
 
 function getModel(db) {
   return db.model('GeoSearch', schema, 'geosearch-' + random());
@@ -32,10 +32,10 @@ describe('model', function() {
         assert.ifError(err);
 
         var geos = [];
-        geos[0] = new Geo({ pos : [10,10], type : "place"});
-        geos[1] = new Geo({ pos : [15,5], type : "place"});
-        geos[2] = new Geo({ pos : [20,15], type : "house"});
-        geos[3] = new Geo({ pos : [1,-1], type : "house"});
+        geos[0] = new Geo({ pos: [10,10], type: "place"});
+        geos[1] = new Geo({ pos: [15,5], type: "place"});
+        geos[2] = new Geo({ pos: [20,15], type: "house"});
+        geos[3] = new Geo({ pos: [1,-1], type: "house"});
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
@@ -46,7 +46,7 @@ describe('model', function() {
         }
 
         function next() {
-          Geo.geoSearch({ type : "place" }, { near : [9,9], maxDistance : 5 }, function(err, results) {
+          Geo.geoSearch({ type: "place" }, { near: [9,9], maxDistance: 5 }, function(err, results) {
             assert.ifError(err);
             assert.equal(1, results.length);
 
@@ -57,7 +57,7 @@ describe('model', function() {
             assert.equal(results[0].id, geos[0].id);
             assert.ok(results[0] instanceof Geo);
 
-            Geo.geoSearch({ type : "place" }, { near : [40,40], maxDistance : 5 }, function(err, results) {
+            Geo.geoSearch({ type: "place" }, { near: [40,40], maxDistance: 5 }, function(err, results) {
               assert.ifError(err);
               assert.equal(0, results.length);
               db.close(done);
@@ -76,10 +76,10 @@ describe('model', function() {
         assert.ifError(err);
 
         var geos = [];
-        geos[0] = new Geo({ pos : [10,10], type : "place"});
-        geos[1] = new Geo({ pos : [15,5], type : "place"});
-        geos[2] = new Geo({ pos : [20,15], type : "house"});
-        geos[3] = new Geo({ pos : [1,-1], type : "house"});
+        geos[0] = new Geo({ pos: [10,10], type: "place"});
+        geos[1] = new Geo({ pos: [15,5], type: "place"});
+        geos[2] = new Geo({ pos: [20,15], type: "house"});
+        geos[3] = new Geo({ pos: [1,-1], type: "house"});
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
@@ -90,7 +90,7 @@ describe('model', function() {
         }
 
         function next() {
-          Geo.geoSearch({ type : "place" }, { near : [9,9], maxDistance : 5, lean : true }, function(err, results) {
+          Geo.geoSearch({ type: "place" }, { near: [9,9], maxDistance: 5, lean: true }, function(err, results) {
             assert.ifError(err);
             assert.equal(1, results.length);
 
@@ -115,21 +115,21 @@ describe('model', function() {
       Geo.on('index', function(err) {
         assert.ifError(err);
 
-        var g = new Geo({ pos : [10,10], type : "place"});
+        var g = new Geo({ pos: [10,10], type: "place"});
         g.save(function() {
           Geo.geoSearch([], {}, function(e) {
             assert.ok(e);
             assert.equal(e.message, "Must pass conditions to geoSearch");
 
-            Geo.geoSearch({ type : "test"}, {}, function(e) {
+            Geo.geoSearch({ type: "test"}, {}, function(e) {
               assert.ok(e);
               assert.equal(e.message, "Must specify the near option in geoSearch");
 
-              Geo.geoSearch({ type : "test" }, { near : "hello" }, function(e) {
+              Geo.geoSearch({ type: "test" }, { near: "hello" }, function(e) {
                 assert.ok(e);
                 assert.equal(e.message, "near option must be an array [x, y]");
 
-                Geo.geoSearch({ type : "test" }, { near : [1,2] }, function(err) {
+                Geo.geoSearch({ type: "test" }, { near: [1,2] }, function(err) {
                   assert.ok(err);
                   assert.ok(/maxDistance needs a number/.test(err));
                   db.close(done);
@@ -144,7 +144,7 @@ describe('model', function() {
       var db = start();
       var Geo = getModel(db);
 
-      var prom = Geo.geoSearch({ type : "place" }, { near : [9,9], maxDistance : 5 }, function() {});
+      var prom = Geo.geoSearch({ type: "place" }, { near: [9,9], maxDistance: 5 }, function() {});
       assert.ok(prom instanceof mongoose.Promise);
       db.close();
       done();
@@ -155,13 +155,13 @@ describe('model', function() {
       var Geo = getModel(db);
       Geo.on('index', function(err) {
         assert.ifError(err);
-        var g = new Geo({ pos : [10,10], type : "place"});
+        var g = new Geo({ pos: [10,10], type: "place"});
         g.save(function(err) {
           assert.ifError(err);
 
           var promise;
           assert.doesNotThrow(function() {
-            promise = Geo.geoSearch({ type : "place" }, { near : [9,9], maxDistance : 5 });
+            promise = Geo.geoSearch({ type: "place" }, { near: [9,9], maxDistance: 5 });
           });
           function validate(ret, stat) {
             assert.equal(1, ret.length);
diff --git a/test/model.hydrate.test.js b/test/model.hydrate.test.js
index de4ab11041d..031607318fc 100644
--- a/test/model.hydrate.test.js
+++ b/test/model.hydrate.test.js
@@ -2,11 +2,11 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , Schema = mongoose.Schema
-  , DocumentObjectId = mongoose.Types.ObjectId;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    Schema = mongoose.Schema,
+    DocumentObjectId = mongoose.Types.ObjectId;
 
 /**
  * Setup
diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js
index c8aca09274b..1d21d2db45e 100644
--- a/test/model.indexes.test.js
+++ b/test/model.indexes.test.js
@@ -3,32 +3,32 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.Types.ObjectId;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema,
+    ObjectId = Schema.Types.ObjectId;
 
 describe('model', function() {
   describe('indexes', function() {
     it('are created when model is compiled', function(done) {
       var Indexed = new Schema({
-        name  : { type: String, index: true }
-        , last  : String
-        , email : String
-        , date  : Date
+        name: { type: String, index: true },
+        last: String,
+        email: String,
+        date: Date
       });
 
       Indexed.index({ last: 1, email: 1 }, { unique: true });
       Indexed.index({ date: 1 }, { expires: 10 });
 
-      var db = start()
-        , IndexedModel = db.model('IndexedModel', Indexed, 'indexedmodel' + random())
-        , assertions = 0;
+      var db = start(),
+          IndexedModel = db.model('IndexedModel', Indexed, 'indexedmodel' + random()),
+          assertions = 0;
 
       IndexedModel.on('index', function() {
-        IndexedModel.collection.getIndexes({full:true}, function(err, indexes) {
+        IndexedModel.collection.getIndexes({full: true}, function(err, indexes) {
           assert.ifError(err);
 
           indexes.forEach(function(index) {
@@ -53,19 +53,19 @@ describe('model', function() {
 
     it('of embedded documents', function(done) {
       var BlogPosts = new Schema({
-        _id     : { type: ObjectId, index: true }
-        , title   : { type: String, index: true }
-        , desc    : String
+        _id: { type: ObjectId, index: true },
+        title: { type: String, index: true },
+        desc: String
       });
 
       var User = new Schema({
-        name        : { type: String, index: true }
-        , blogposts   : [BlogPosts]
+        name: { type: String, index: true },
+        blogposts: [BlogPosts]
       });
 
-      var db = start()
-        , UserModel = db.model('DeepIndexedModel', User, 'deepindexedmodel' + random())
-        , assertions = 0;
+      var db = start(),
+          UserModel = db.model('DeepIndexedModel', User, 'deepindexedmodel' + random()),
+          assertions = 0;
 
       UserModel.on('index', function() {
         UserModel.collection.getIndexes(function(err, indexes) {
@@ -137,20 +137,20 @@ describe('model', function() {
 
     it('compound: on embedded docs', function(done) {
       var BlogPosts = new Schema({
-        title   : String
-        , desc    : String
+        title: String,
+        desc: String
       });
 
       BlogPosts.index({ title: 1, desc: 1 });
 
       var User = new Schema({
-        name        : { type: String, index: true }
-        , blogposts   : [BlogPosts]
+        name: { type: String, index: true },
+        blogposts: [BlogPosts]
       });
 
-      var db = start()
-        , UserModel = db.model('DeepCompoundIndexModel', User, 'deepcompoundindexmodel' + random())
-        , found = 0;
+      var db = start(),
+          UserModel = db.model('DeepCompoundIndexModel', User, 'deepcompoundindexmodel' + random()),
+          found = 0;
 
       UserModel.on('index', function() {
         UserModel.collection.getIndexes(function(err, indexes) {
@@ -175,8 +175,8 @@ describe('model', function() {
     it('error should emit on the model', function(done) {
       var db = start();
 
-      var schema = new Schema({ name: { type: String } })
-        , Test = db.model('IndexError', schema, "x" + random());
+      var schema = new Schema({ name: { type: String } }),
+          Test = db.model('IndexError', schema, "x" + random());
 
       Test.on('index', function(err) {
         db.close();
@@ -221,7 +221,7 @@ describe('model', function() {
       describe('global autoIndexes (gh-1875)', function() {
         it('will create indexes as a default', function(done) {
           var db = start();
-          var schema = new Schema({name : { type: String, index: true } });
+          var schema = new Schema({name: { type: String, index: true } });
           var Test = db.model('GlobalAutoIndex', schema, 'gh-1875-1');
           Test.on('index', function(error) {
             assert.ifError(error);
@@ -235,8 +235,8 @@ describe('model', function() {
         });
 
         it('will not create indexes if the global auto index is false and schema option isnt set (gh-1875)', function(done) {
-          var db = start({config: {autoIndex : false}});
-          var schema = new Schema({name : {type: String, index: true}});
+          var db = start({config: {autoIndex: false}});
+          var schema = new Schema({name: {type: String, index: true}});
           var Test = db.model('GlobalAutoIndex', schema, "x" + random());
           Test.on('index', function() {
             assert.ok(false, 'Model.ensureIndexes() was called');
@@ -262,11 +262,11 @@ describe('model', function() {
       var db = start({ uri: 'mongodb://localhost/mongoose_test_indexing'});
 
       var schema = Schema({
-        name: { type:String, index: true }
-        , furryness: { type:Number, index: true }
+        name: { type: String, index: true },
+        furryness: { type: Number, index: true }
       }, { autoIndex: false });
 
-      schema.index({ name:1, furryness:1});
+      schema.index({ name: 1, furryness: 1});
 
       var K = db.model('Kitten', schema);
       K.on('index', function(err) {
@@ -318,8 +318,8 @@ describe('model', function() {
 
       it('creates indexes', function(done) {
         var db = start();
-        var schema = new Schema({ name: { type: String } })
-          , Test = db.model('ManualIndexing', schema, "x" + random());
+        var schema = new Schema({ name: { type: String } }),
+            Test = db.model('ManualIndexing', schema, "x" + random());
 
         Test.schema.index({ name: 1 }, { sparse: true });
 
diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 2f82ad29883..01e61a38947 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -1,15 +1,15 @@
-/* eslint unused-vars: 1 */
+/* eslint no-unused-vars: 1 */
 /* global emit */
 /**
  * Test dependencies.
  */
 
-var start = require('./common')
-  , mongoose = start.mongoose
-  , assert = require('assert')
-  , random = require('../lib/utils').random
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.Types.ObjectId;
+var start = require('./common'),
+    mongoose = start.mongoose,
+    assert = require('assert'),
+    random = require('../lib/utils').random,
+    Schema = mongoose.Schema,
+    ObjectId = Schema.Types.ObjectId;
 
 /**
  * Setup.
@@ -18,26 +18,26 @@ var start = require('./common')
 var Comments = new Schema();
 
 Comments.add({
-  title     : String
-  , date      : Date
-  , body      : String
-  , comments  : [Comments]
+  title: String,
+  date: Date,
+  body: String,
+  comments: [Comments]
 });
 
 var BlogPost = new Schema({
-  title     : String
-  , author    : String
-  , slug      : String
-  , date      : Date
-  , meta      : {
-    date      : Date
-      , visitors  : Number
-  }
-  , published : Boolean
-  , mixed     : {}
-  , numbers   : [Number]
-  , owners    : [ObjectId]
-  , comments  : [Comments]
+  title: String,
+  author: String,
+  slug: String,
+  date: Date,
+  meta: {
+    date: Date,
+    visitors: Number
+  },
+  published: Boolean,
+  mixed: {},
+  numbers: [Number],
+  owners: [ObjectId],
+  comments: [Comments]
 });
 
 
@@ -46,8 +46,8 @@ mongoose.model('MapReduce', BlogPost);
 
 describe('model: mapreduce:', function() {
   it('works', function(done) {
-    var db = start()
-      , MR = db.model('MapReduce', collection);
+    var db = start(),
+        MR = db.model('MapReduce', collection);
 
     var magicID;
     var id = new mongoose.Types.ObjectId;
@@ -64,8 +64,8 @@ describe('model: mapreduce:', function() {
       magicID = b._id;
 
       var o = {
-        map: function() { emit(this.author, 1); }
-        , reduce: function(k, vals) { return vals.length; }
+        map: function() { emit(this.author, 1); },
+        reduce: function(k, vals) { return vals.length; }
       };
 
       MR.mapReduce(o, function(err, ret, stats) {
@@ -80,9 +80,9 @@ describe('model: mapreduce:', function() {
         });
 
         var o = {
-          map: function() { emit(this.author, 1); }
-          , reduce: function(k, vals) { return vals.length; }
-          , query: { author: 'aaron', published: 1, owners: id }
+          map: function() { emit(this.author, 1); },
+          reduce: function(k, vals) { return vals.length; },
+          query: { author: 'aaron', published: 1, owners: id }
         };
 
         MR.mapReduce(o, function(err, ret, stats) {
@@ -100,10 +100,10 @@ describe('model: mapreduce:', function() {
 
       function modeling() {
         var o = {
-          map: function() { emit(this.author, { own: magicID }); }
-          , scope: { magicID: magicID }
-          , reduce: function(k, vals) { return { own: vals[0].own, count: vals.length };}
-          , out: { replace: '_mapreduce_test_' + random() }
+          map: function() { emit(this.author, { own: magicID }); },
+          scope: { magicID: magicID },
+          reduce: function(k, vals) { return { own: vals[0].own, count: vals.length };},
+          out: { replace: '_mapreduce_test_' + random() }
         };
 
         MR.mapReduce(o, function(err, ret) {
@@ -147,13 +147,13 @@ describe('model: mapreduce:', function() {
   });
 
   it('withholds stats with false verbosity', function(done) {
-    var db = start()
-      , MR = db.model('MapReduce', collection);
+    var db = start(),
+        MR = db.model('MapReduce', collection);
 
     var o = {
-      map: function() {}
-      , reduce: function() { return 'test'; }
-      , verbose: false
+      map: function() {},
+      reduce: function() { return 'test'; },
+      verbose: false
     };
 
     MR.mapReduce(o, function(err, results, stats) {
@@ -164,12 +164,12 @@ describe('model: mapreduce:', function() {
 
   describe('promises (gh-1628)', function() {
     it('are returned', function(done) {
-      var db = start()
-        , MR = db.model('MapReduce', collection);
+      var db = start(),
+          MR = db.model('MapReduce', collection);
 
       var o = {
-        map: function() {}
-        , reduce: function() { return 'test'; }
+        map: function() {},
+        reduce: function() { return 'test'; }
       };
 
       var promise = MR.mapReduce(o, function() {});
@@ -179,13 +179,13 @@ describe('model: mapreduce:', function() {
     });
 
     it('allow not passing a callback', function(done) {
-      var db = start()
-        , MR = db.model('MapReduce', collection);
+      var db = start(),
+          MR = db.model('MapReduce', collection);
 
       var o = {
-        map: function() { emit(this.author, 1); }
-        , reduce: function(k, vals) { return vals.length; }
-        , query: { author: 'aaron', published: 1 }
+        map: function() { emit(this.author, 1); },
+        reduce: function(k, vals) { return vals.length; },
+        query: { author: 'aaron', published: 1 }
       };
 
       function validate(ret, stats) {
diff --git a/test/model.middleware.test.js b/test/model.middleware.test.js
index 6271c5bd70c..fc6b82641e8 100644
--- a/test/model.middleware.test.js
+++ b/test/model.middleware.test.js
@@ -3,10 +3,10 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , Schema = mongoose.Schema;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    Schema = mongoose.Schema;
 
 describe('model middleware', function() {
   it('post save', function(done) {
@@ -37,8 +37,8 @@ describe('model middleware', function() {
       next();
     });
 
-    var db = start()
-      , TestMiddleware = db.model('TestPostSaveMiddleware', schema);
+    var db = start(),
+        TestMiddleware = db.model('TestPostSaveMiddleware', schema);
 
     var test = new TestMiddleware({ title: 'Little Green Running Hood'});
 
@@ -100,8 +100,8 @@ describe('model middleware', function() {
 
     mongoose.model('TestMiddleware', schema);
 
-    var db = start()
-      , TestMiddleware = db.model('TestMiddleware');
+    var db = start(),
+        TestMiddleware = db.model('TestMiddleware');
 
     var test = new TestMiddleware();
 
@@ -130,8 +130,8 @@ describe('model middleware', function() {
       title: String
     });
 
-    var preinit = 0
-      , postinit = 0;
+    var preinit = 0,
+        postinit = 0;
 
     schema.pre('init', function(next) {
       ++preinit;
@@ -145,8 +145,8 @@ describe('model middleware', function() {
 
     mongoose.model('TestPostInitMiddleware', schema);
 
-    var db = start()
-      , Test = db.model('TestPostInitMiddleware');
+    var db = start(),
+        Test = db.model('TestPostInitMiddleware');
 
     var test = new Test({ title: "banana" });
 
@@ -228,10 +228,10 @@ describe('model middleware', function() {
       title: String
     });
 
-    var preValidate = 0
-      , postValidate = 0
-      , preRemove = 0
-      , postRemove = 0;
+    var preValidate = 0,
+        postValidate = 0,
+        preRemove = 0,
+        postRemove = 0;
 
     schema.pre('validate', function(next) {
       ++preValidate;
@@ -253,8 +253,8 @@ describe('model middleware', function() {
       ++postRemove;
     });
 
-    var db = start()
-      , Test = db.model('TestPostValidateMiddleware', schema);
+    var db = start(),
+        Test = db.model('TestPostValidateMiddleware', schema);
 
     var test = new Test({ title: "banana" });
 
diff --git a/test/model.populate.divergent.test.js b/test/model.populate.divergent.test.js
index 02da3e742d4..b4ade1c6015 100644
--- a/test/model.populate.divergent.test.js
+++ b/test/model.populate.divergent.test.js
@@ -3,12 +3,12 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , DivergentArrayError = mongoose.Error.DivergentArrayError
-  , utils = require('../lib/utils')
-  , random = utils.random;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    DivergentArrayError = mongoose.Error.DivergentArrayError,
+    utils = require('../lib/utils'),
+    random = utils.random;
 
 /**
  * Tests.
diff --git a/test/model.populate.setting.test.js b/test/model.populate.setting.test.js
index f1d37950605..d19b90572c3 100644
--- a/test/model.populate.setting.test.js
+++ b/test/model.populate.setting.test.js
@@ -4,20 +4,20 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , utils = require('../lib/utils')
-  , random = utils.random
-  , Schema = mongoose.Schema
-  , DocObjectId = mongoose.Types.ObjectId;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    utils = require('../lib/utils'),
+    random = utils.random,
+    Schema = mongoose.Schema,
+    DocObjectId = mongoose.Types.ObjectId;
 
 /**
  * Setup.
  */
 
-var posts = 'blogposts_' + random()
-  , users = 'users_' + random();
+var posts = 'blogposts_' + random(),
+    users = 'users_' + random();
 
 /**
  * Tests.
@@ -26,10 +26,10 @@ var posts = 'blogposts_' + random()
 describe('model: populate:', function() {
   describe('setting populated paths (gh-570)', function() {
     var types = {
-      'ObjectId': DocObjectId
-      , 'String': String
-      , 'Number': Number
-      , 'Buffer': Buffer
+      'ObjectId': DocObjectId,
+      'String': String,
+      'Number': Number,
+      'Buffer': Buffer
     };
 
     var construct = {};
@@ -52,20 +52,20 @@ describe('model: populate:', function() {
           refuser = 'RefUser-' + id;
 
           var bSchema = Schema({
-            title: String
-            , fans: [{type: id, ref: refuser }]
-            , adhoc: [{ subdoc: id, subarray: [{ things: [id] }] }]
-            , _creator: { type: id, ref: refuser }
-            , embed: [{
-              other: { type: id, ref: refuser }
-                , array: [{ type: id, ref: refuser }]
+            title: String,
+            fans: [{type: id, ref: refuser }],
+            adhoc: [{ subdoc: id, subarray: [{ things: [id] }] }],
+            _creator: { type: id, ref: refuser },
+            embed: [{
+              other: { type: id, ref: refuser },
+              array: [{ type: id, ref: refuser }]
             }]
           });
 
           var uSchema = Schema({
-            _id: id
-            , name: String
-            , email: String
+            _id: id,
+            name: String,
+            email: String
           });
 
           db = start();
@@ -73,30 +73,30 @@ describe('model: populate:', function() {
           U = db.model(refuser, uSchema, users + random());
 
           U.create({
-            _id: construct[id]()
-            , name  : 'Fan 1'
-            , email : 'fan1@learnboost.com'
+            _id: construct[id](),
+            name: 'Fan 1',
+            email: 'fan1@learnboost.com'
           }, {
-            _id: construct[id]()
-            , name  : 'Fan 2'
-            , email : 'fan2@learnboost.com'
+            _id: construct[id](),
+            name: 'Fan 2',
+            email: 'fan2@learnboost.com'
           }, function(err, fan1, fan2) {
             assert.ifError(err);
             u1 = fan1;
 
             B.create({
-              title : 'Woot'
-              , fans  : [fan1, fan2]
-              , adhoc : [{ subdoc: fan2, subarray: [{ things: [fan1] }]}]
-              , _creator: fan1
-              , embed : [{ other: fan1, array: [fan1, fan2] }, { other: fan2, array: [fan2, fan1] }]
+              title: 'Woot',
+              fans: [fan1, fan2],
+              adhoc: [{ subdoc: fan2, subarray: [{ things: [fan1] }]}],
+              _creator: fan1,
+              embed: [{ other: fan1, array: [fan1, fan2] }, { other: fan2, array: [fan2, fan1] }]
             }, {
-              title : 'Woot2'
-              , fans  : [fan2, fan1]
-              , adhoc : [{ subdoc: fan1, subarray: [{ things: [fan2] }]}]
-              , _creator: fan1
-              , _creator: fan2
-              , embed : [{ other: fan2, array: [fan2, fan1] }, { other: fan1, array: [fan1, fan2] }]
+              title: 'Woot2',
+              fans: [fan2, fan1],
+              adhoc: [{ subdoc: fan1, subarray: [{ things: [fan2] }]}],
+              _creator: fan1,
+              _creator: fan2,
+              embed: [{ other: fan2, array: [fan2, fan1] }, { other: fan1, array: [fan1, fan2] }]
             }, function(err, post1, post2) {
               assert.ifError(err);
               b1 = post1;
diff --git a/test/model.populate.test.js b/test/model.populate.test.js
index be27a9c9621..1bf00862ec8 100644
--- a/test/model.populate.test.js
+++ b/test/model.populate.test.js
@@ -3,14 +3,14 @@
  * Test dependencies.
  */
 
-var start = require('./common')
-  , assert = require('assert')
-  , mongoose = start.mongoose
-  , utils = require('../lib/utils')
-  , random = utils.random
-  , Schema = mongoose.Schema
-  , ObjectId = Schema.ObjectId
-  , DocObjectId = mongoose.Types.ObjectId;
+var start = require('./common'),
+    assert = require('assert'),
+    mongoose = start.mongoose,
+    utils = require('../lib/utils'),
+    random = utils.random,
+    Schema = mongoose.Schema,
+    ObjectId = Schema.ObjectId,
+    DocObjectId = mongoose.Types.ObjectId;
 
 /**
  * Setup.
@@ -21,12 +21,12 @@ var start = require('./common')
  */
 
 var User = new Schema({
-  name      : String
-  , email     : String
-  , gender    : { type: String, enum: ['male', 'female'], default: 'male' }
-  , age       : { type: Number, default: 21 }
-  , blogposts : [{ type: ObjectId, ref: 'RefBlogPost' }]
-  , followers : [{ type: ObjectId, ref: 'RefUser' }]
+  name: String,
+  email: String,
+  gender: { type: String, enum: ['male', 'female'], default: 'male' },
+  age: { type: Number, default: 21 },
+  blogposts: [{ type: ObjectId, ref: 'RefBlogPost' }],
+  followers: [{ type: ObjectId, ref: 'RefUser' }]
 });
 
 /**
@@ -34,9 +34,9 @@ var User = new Schema({
  */
 
 var Comment = new Schema({
-  asers   : [{ type: ObjectId, ref: 'RefUser' }]
-  , _creator : { type: ObjectId, ref: 'RefUser' }
-  , content  : String
+  asers: [{ type: ObjectId, ref: 'RefUser' }],
+  _creator: { type: ObjectId, ref: 'RefUser' },
+  content: String
 });
 
 /**
@@ -44,14 +44,14 @@ var Comment = new Schema({
  */
 
 var BlogPost = new Schema({
-  _creator      : { type: ObjectId, ref: 'RefUser' }
-  , title         : String
-  , comments      : [Comment]
-  , fans          : [{ type: ObjectId, ref: 'RefUser' }]
+  _creator: { type: ObjectId, ref: 'RefUser' },
+  title: String,
+  comments: [Comment],
+  fans: [{ type: ObjectId, ref: 'RefUser' }]
 });
 
-var posts = 'blogposts_' + random()
-  , users = 'users_' + random();
+var posts = 'blogposts_' + random(),
+    users = 'users_' + random();
 
 mongoose.model('RefBlogPost', BlogPost);
 mongoose.model('RefUser', User);
@@ -64,9 +64,9 @@ mongoose.model('RefAlternateUser', User);
 
 describe('model: populate:', function() {
   it('populating array of object', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({ name: 'User 1' }, function(err, user1) {
       assert.ifError(err);
@@ -75,11 +75,11 @@ describe('model: populate:', function() {
         assert.ifError(err);
 
         BlogPost.create({
-          title: 'Woot'
-          , _creator: user1._id
-          , comments: [
-            { _creator: user1._id, content: 'Woot woot' }
-            , { _creator: user2._id, content: 'Wha wha' }
+          title: 'Woot',
+          _creator: user1._id,
+          comments: [
+            { _creator: user1._id, content: 'Woot woot' },
+            { _creator: user2._id, content: 'Wha wha' }
           ]
         }, function(err, post) {
           assert.ifError(err);
@@ -94,9 +94,9 @@ describe('model: populate:', function() {
   });
 
   it('deep population (gh-3103)', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({ name: 'User 01' }, function(err, user1) {
       assert.ifError(err);
@@ -108,8 +108,8 @@ describe('model: populate:', function() {
           assert.ifError(err);
 
           BlogPost.create({
-            title: 'w00tabulous'
-            , _creator: user3._id
+            title: 'w00tabulous',
+            _creator: user3._id
           }, function(err, post) {
             assert.ifError(err);
 
@@ -202,19 +202,19 @@ describe('model: populate:', function() {
   });
 
   it('populating a single ref', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Guillermo'
-      , email : 'rauchg@gmail.com'
+      name: 'Guillermo',
+      email: 'rauchg@gmail.com'
     }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
-        title     : 'woot'
-        , _creator  : creator
+        title: 'woot',
+        _creator: creator
       }, function(err, post) {
         assert.ifError(err);
 
@@ -234,12 +234,12 @@ describe('model: populate:', function() {
   });
 
   it('not failing on null as ref', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create({
-      title     : 'woot'
-      , _creator  : null
+      title: 'woot',
+      _creator: null
     }, function(err, post) {
       assert.ifError(err);
 
@@ -256,11 +256,11 @@ describe('model: populate:', function() {
   });
 
   it('not failing on empty object as ref', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create(
-      { title : 'woot' },
+      { title: 'woot' },
       function(err, post) {
         assert.ifError(err);
 
@@ -273,20 +273,20 @@ describe('model: populate:', function() {
   });
 
   it('across DBs', function(done) {
-    var db = start()
-      , db2 = db.useDb('mongoose_test2')
-      , BlogPost = db.model('RefBlogPost', posts + '2')
-      , User = db2.model('RefUser', users + '2');
+    var db = start(),
+        db2 = db.useDb('mongoose_test2'),
+        BlogPost = db.model('RefBlogPost', posts + '2'),
+        User = db2.model('RefUser', users + '2');
 
     User.create({
-      name: 'Guillermo'
-      , email: 'rauchg@gmail.com'
+      name: 'Guillermo',
+      email: 'rauchg@gmail.com'
     }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
-        title    : 'woot'
-        , _creator : creator._id
+        title: 'woot',
+        _creator: creator._id
       }, function(err, post) {
         assert.ifError(err);
         BlogPost
@@ -306,19 +306,19 @@ describe('model: populate:', function() {
   });
 
   it('an error in single ref population propagates', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts + '1')
-      , User = db.model('RefUser', users + '1');
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts + '1'),
+        User = db.model('RefUser', users + '1');
 
     User.create({
-      name: 'Guillermo'
-      , email: 'rauchg@gmail.com'
+      name: 'Guillermo',
+      email: 'rauchg@gmail.com'
     }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
-        title    : 'woot'
-        , _creator : creator
+        title: 'woot',
+        _creator: creator
       }, function(err, post) {
         assert.ifError(err);
 
@@ -348,19 +348,19 @@ describe('model: populate:', function() {
   });
 
   it('populating with partial fields selection', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Guillermo'
-      , email : 'rauchg@gmail.com'
+      name: 'Guillermo',
+      email: 'rauchg@gmail.com'
     }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
-        title     : 'woot'
-        , _creator  : creator
+        title: 'woot',
+        _creator: creator
       }, function(err, post) {
         assert.ifError(err);
 
@@ -381,19 +381,19 @@ describe('model: populate:', function() {
   });
 
   it('population of single oid with partial field selection and filter', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', 'blogposts_' + random())
-      , User = db.model('RefUser', 'users_' + random());
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', 'blogposts_' + random()),
+        User = db.model('RefUser', 'users_' + random());
 
     User.create({
-      name  : 'Banana'
-      , email : 'cats@example.com'
+      name: 'Banana',
+      email: 'cats@example.com'
     }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
-        title     : 'woot'
-        , _creator  : creator
+        title: 'woot',
+        _creator: creator
       }, function(err, post) {
         assert.ifError(err);
 
@@ -421,9 +421,9 @@ describe('model: populate:', function() {
   });
 
   it('population of undefined fields in a collection of docs', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', 'blogposts_' + random())
-      , User = db.model('RefUser', 'users_' + random());
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', 'blogposts_' + random()),
+        User = db.model('RefUser', 'users_' + random());
     User.create({
       name: 'Eloy',
       email: 'eloytoro@gmail.com'
@@ -457,19 +457,19 @@ describe('model: populate:', function() {
   });
 
   it('population and changing a reference', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Guillermo'
-      , email : 'rauchg@gmail.com'
+      name: 'Guillermo',
+      email: 'rauchg@gmail.com'
     }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
-        title     : 'woot'
-        , _creator  : creator
+        title: 'woot',
+        _creator: creator
       }, function(err, post) {
         assert.ifError(err);
 
@@ -484,8 +484,8 @@ describe('model: populate:', function() {
           assert.equal(post._creator.email,'rauchg@gmail.com');
 
           User.create({
-            name  : 'Aaron'
-            , email : 'aaron.heckmann@gmail.com'
+            name: 'Aaron',
+            email: 'aaron.heckmann@gmail.com'
           }, function(err, newCreator) {
             assert.ifError(err);
 
@@ -513,19 +513,19 @@ describe('model: populate:', function() {
   });
 
   it('populating with partial fields selection and changing ref', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Guillermo'
-      , email : 'rauchg@gmail.com'
+      name: 'Guillermo',
+      email: 'rauchg@gmail.com'
     }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
-        title     : 'woot'
-        , _creator  : creator
+        title: 'woot',
+        _creator: creator
       }, function(err, post) {
         assert.ifError(err);
 
@@ -539,8 +539,8 @@ describe('model: populate:', function() {
           assert.equal(post._creator.name,'Guillermo');
 
           User.create({
-            name  : 'Aaron'
-            , email : 'aaron@learnboost.com'
+            name: 'Aaron',
+            email: 'aaron@learnboost.com'
           }, function(err, newCreator) {
             assert.ifError(err);
 
@@ -567,31 +567,31 @@ describe('model: populate:', function() {
   });
 
   it('populating an array of refs and fetching many', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Fan 1'
-      , email : 'fan1@learnboost.com'
+      name: 'Fan 1',
+      email: 'fan1@learnboost.com'
     }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
-        name  : 'Fan 2'
-        , email : 'fan2@learnboost.com'
+        name: 'Fan 2',
+        email: 'fan2@learnboost.com'
       }, function(err, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
-          title : 'Woot'
-          , fans  : [fan1, fan2]
+          title: 'Woot',
+          fans: [fan1, fan2]
         }, function(err, post1) {
           assert.ifError(err);
 
           BlogPost.create({
-            title : 'Woot'
-            , fans  : [fan2, fan1]
+            title: 'Woot',
+            fans: [fan2, fan1]
           }, function(err, post2) {
             assert.ifError(err);
 
@@ -620,31 +620,31 @@ describe('model: populate:', function() {
   });
 
   it('an error in array reference population propagates', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts + '2')
-      , User = db.model('RefUser', users + '2');
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts + '2'),
+        User = db.model('RefUser', users + '2');
 
     User.create({
-      name  : 'Fan 1'
-      , email : 'fan1@learnboost.com'
+      name: 'Fan 1',
+      email: 'fan1@learnboost.com'
     }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
-        name  : 'Fan 2'
-        , email : 'fan2@learnboost.com'
+        name: 'Fan 2',
+        email: 'fan2@learnboost.com'
       }, function(err, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
-          title : 'Woot'
-          , fans  : [fan1, fan2]
+          title: 'Woot',
+          fans: [fan1, fan2]
         }, function(err, post1) {
           assert.ifError(err);
 
           BlogPost.create({
-            title : 'Woot'
-            , fans  : [fan2, fan1]
+            title: 'Woot',
+            fans: [fan2, fan1]
           }, function(err, post2) {
             assert.ifError(err);
 
@@ -676,31 +676,31 @@ describe('model: populate:', function() {
   });
 
   it('populating an array of references with fields selection', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Fan 1'
-      , email : 'fan1@learnboost.com'
+      name: 'Fan 1',
+      email: 'fan1@learnboost.com'
     }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
-        name  : 'Fan 2'
-        , email : 'fan2@learnboost.com'
+        name: 'Fan 2',
+        email: 'fan2@learnboost.com'
       }, function(err, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
-          title : 'Woot'
-          , fans  : [fan1, fan2]
+          title: 'Woot',
+          fans: [fan1, fan2]
         }, function(err, post1) {
           assert.ifError(err);
 
           BlogPost.create({
-            title : 'Woot'
-            , fans  : [fan2, fan1]
+            title: 'Woot',
+            fans: [fan2, fan1]
           }, function(err, post2) {
             assert.ifError(err);
 
@@ -731,39 +731,39 @@ describe('model: populate:', function() {
   });
 
   it('populating an array of references and filtering', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Fan 1'
-      , email : 'fan1@learnboost.com'
+      name: 'Fan 1',
+      email: 'fan1@learnboost.com'
     }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
-        name   : 'Fan 2'
-        , email  : 'fan2@learnboost.com'
-        , gender : 'female'
+        name: 'Fan 2',
+        email: 'fan2@learnboost.com',
+        gender: 'female'
       }, function(err, fan2) {
         assert.ifError(err);
 
         User.create({
-          name   : 'Fan 3'
-          , email  : 'fan3@learnboost.com'
-          , gender : 'female'
+          name: 'Fan 3',
+          email: 'fan3@learnboost.com',
+          gender: 'female'
         }, function(err, fan3) {
           assert.ifError(err);
 
           BlogPost.create({
-            title : 'Woot'
-            , fans  : [fan1, fan2, fan3]
+            title: 'Woot',
+            fans: [fan1, fan2, fan3]
           }, function(err, post1) {
             assert.ifError(err);
 
             BlogPost.create({
-              title : 'Woot'
-              , fans  : [fan3, fan2, fan1]
+              title: 'Woot',
+              fans: [fan3, fan2, fan1]
             }, function(err, post2) {
               assert.ifError(err);
 
@@ -818,40 +818,40 @@ describe('model: populate:', function() {
   });
 
   it('populating an array of references and multi-filtering', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Fan 1'
-      , email : 'fan1@learnboost.com'
+      name: 'Fan 1',
+      email: 'fan1@learnboost.com'
     }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
-        name   : 'Fan 2'
-        , email  : 'fan2@learnboost.com'
-        , gender : 'female'
+        name: 'Fan 2',
+        email: 'fan2@learnboost.com',
+        gender: 'female'
       }, function(err, fan2) {
         assert.ifError(err);
 
         User.create({
-          name   : 'Fan 3'
-          , email  : 'fan3@learnboost.com'
-          , gender : 'female'
-          , age    : 25
+          name: 'Fan 3',
+          email: 'fan3@learnboost.com',
+          gender: 'female',
+          age: 25
         }, function(err, fan3) {
           assert.ifError(err);
 
           BlogPost.create({
-            title : 'Woot'
-            , fans  : [fan1, fan2, fan3]
+            title: 'Woot',
+            fans: [fan1, fan2, fan3]
           }, function(err, post1) {
             assert.ifError(err);
 
             BlogPost.create({
-              title : 'Woot'
-              , fans  : [fan3, fan2, fan1]
+              title: 'Woot',
+              fans: [fan3, fan2, fan1]
             }, function(err, post2) {
               assert.ifError(err);
 
@@ -909,40 +909,40 @@ describe('model: populate:', function() {
   });
 
   it('populating an array of references and multi-filtering with field selection', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Fan 1'
-      , email : 'fan1@learnboost.com'
+      name: 'Fan 1',
+      email: 'fan1@learnboost.com'
     }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
-        name   : 'Fan 2'
-        , email  : 'fan2@learnboost.com'
-        , gender : 'female'
+        name: 'Fan 2',
+        email: 'fan2@learnboost.com',
+        gender: 'female'
       }, function(err, fan2) {
         assert.ifError(err);
 
         User.create({
-          name   : 'Fan 3'
-          , email  : 'fan3@learnboost.com'
-          , gender : 'female'
-          , age    : 25
+          name: 'Fan 3',
+          email: 'fan3@learnboost.com',
+          gender: 'female',
+          age: 25
         }, function(err, fan3) {
           assert.ifError(err);
 
           BlogPost.create({
-            title : 'Woot'
-            , fans  : [fan1, fan2, fan3]
+            title: 'Woot',
+            fans: [fan1, fan2, fan3]
           }, function(err, post1) {
             assert.ifError(err);
 
             BlogPost.create({
-              title : 'Woot'
-              , fans  : [fan3, fan2, fan1]
+              title: 'Woot',
+              fans: [fan3, fan2, fan1]
             }, function(err, post2) {
               assert.ifError(err);
 
@@ -977,31 +977,31 @@ describe('model: populate:', function() {
   });
 
   it('populating an array of refs changing one and removing one', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'Fan 1'
-      , email : 'fan1@learnboost.com'
+      name: 'Fan 1',
+      email: 'fan1@learnboost.com'
     }, {
-      name  : 'Fan 2'
-      , email : 'fan2@learnboost.com'
+      name: 'Fan 2',
+      email: 'fan2@learnboost.com'
     }, {
-      name  : 'Fan 3'
-      , email : 'fan3@learnboost.com'
+      name: 'Fan 3',
+      email: 'fan3@learnboost.com'
     }, {
-      name  : 'Fan 4'
-      , email : 'fan4@learnboost.com'
+      name: 'Fan 4',
+      email: 'fan4@learnboost.com'
     }, function(err, fan1, fan2, fan3, fan4) {
       assert.ifError(err);
 
       BlogPost.create({
-        title : 'Woot'
-        , fans  : [fan1, fan2]
+        title: 'Woot',
+        fans: [fan1, fan2]
       }, {
-        title : 'Woot'
-        , fans  : [fan2, fan1]
+        title: 'Woot',
+        fans: [fan2, fan1]
       }, function(err, post1, post2) {
         assert.ifError(err);
 
@@ -1058,9 +1058,9 @@ describe('model: populate:', function() {
 
   describe('populating sub docs', function() {
     it('works with findById', function(done) {
-      var db = start()
-        , BlogPost = db.model('RefBlogPost', posts)
-        , User = db.model('RefUser', users);
+      var db = start(),
+          BlogPost = db.model('RefBlogPost', posts),
+          User = db.model('RefUser', users);
 
       User.create({ name: 'User 1' }, function(err, user1) {
         assert.ifError(err);
@@ -1069,11 +1069,11 @@ describe('model: populate:', function() {
           assert.ifError(err);
 
           BlogPost.create({
-            title: 'Woot'
-            , _creator: user1._id
-            , comments: [
-                  { _creator: user1._id, content: 'Woot woot' }
-                , { _creator: user2._id, content: 'Wha wha' }
+            title: 'Woot',
+            _creator: user1._id,
+            comments: [
+              { _creator: user1._id, content: 'Woot woot' },
+              { _creator: user2._id, content: 'Wha wha' }
             ]
           }, function(err, post) {
             assert.ifError(err);
@@ -1096,23 +1096,23 @@ describe('model: populate:', function() {
     });
 
     it('works when first doc returned has empty array for populated path (gh-1055)', function(done) {
-      var db = start()
-        , BlogPost = db.model('RefBlogPost', posts)
-        , User = db.model('RefUser', users);
+      var db = start(),
+          BlogPost = db.model('RefBlogPost', posts),
+          User = db.model('RefUser', users);
 
       User.create({ name: 'gh-1055-1' }, { name: 'gh-1055-2' }, function(err, user1, user2) {
         assert.ifError(err);
 
         BlogPost.create({
-          title: 'gh-1055 post1'
-          , _creator: user1._id
-          , comments: []
+          title: 'gh-1055 post1',
+          _creator: user1._id,
+          comments: []
         },{
-          title: 'gh-1055 post2'
-          , _creator: user1._id
-          , comments: [
-                { _creator: user1._id, content: 'Woot woot', asers: [] }
-              , { _creator: user2._id, content: 'Wha wha', asers: [user1, user2] }
+          title: 'gh-1055 post2',
+          _creator: user1._id,
+          comments: [
+            { _creator: user1._id, content: 'Woot woot', asers: [] },
+            { _creator: user2._id, content: 'Wha wha', asers: [user1, user2] }
           ]
         }, function(err) {
           assert.ifError(err);
@@ -1178,27 +1178,27 @@ describe('model: populate:', function() {
   });
 
   it('populating subdocuments partially', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'User 1'
-      , email : 'user1@learnboost.com'
+      name: 'User 1',
+      email: 'user1@learnboost.com'
     }, function(err, user1) {
       assert.ifError(err);
 
       User.create({
-        name  : 'User 2'
-        , email : 'user2@learnboost.com'
+        name: 'User 2',
+        email: 'user2@learnboost.com'
       }, function(err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
-          title: 'Woot'
-          , comments: [
-                { _creator: user1, content: 'Woot woot' }
-              , { _creator: user2, content: 'Wha wha' }
+          title: 'Woot',
+          comments: [
+            { _creator: user1, content: 'Woot woot' },
+            { _creator: user2, content: 'Wha wha' }
           ]
         }, function(err, post) {
           assert.ifError(err);
@@ -1223,27 +1223,27 @@ describe('model: populate:', function() {
   });
 
   it('populating subdocuments partially with conditions', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'User 1'
-      , email : 'user1@learnboost.com'
+      name: 'User 1',
+      email: 'user1@learnboost.com'
     }, function(err, user1) {
       assert.ifError(err);
 
       User.create({
-        name  : 'User 2'
-        , email : 'user2@learnboost.com'
+        name: 'User 2',
+        email: 'user2@learnboost.com'
       }, function(err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
-          title: 'Woot'
-          , comments: [
-                { _creator: user1, content: 'Woot woot' }
-              , { _creator: user2, content: 'Wha wha' }
+          title: 'Woot',
+          comments: [
+            { _creator: user1, content: 'Woot woot' },
+            { _creator: user2, content: 'Wha wha' }
           ]
         }, function(err, post) {
           assert.ifError(err);
@@ -1268,27 +1268,27 @@ describe('model: populate:', function() {
   });
 
   it('populating subdocs with invalid/missing subproperties', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create({
-      name  : 'T-100'
-      , email : 'terminator100@learnboost.com'
+      name: 'T-100',
+      email: 'terminator100@learnboost.com'
     }, function(err) {
       assert.ifError(err);
 
       User.create({
-        name  : 'T-1000'
-        , email : 'terminator1000@learnboost.com'
+        name: 'T-1000',
+        email: 'terminator1000@learnboost.com'
       }, function(err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
-          title: 'Woot'
-          , comments: [
-                { _creator: null, content: 'Woot woot' }
-              , { _creator: user2, content: 'Wha wha' }
+          title: 'Woot',
+          comments: [
+            { _creator: null, content: 'Woot woot' },
+            { _creator: user2, content: 'Wha wha' }
           ]
         }, function(err, post) {
           assert.ifError(err);
@@ -1442,12 +1442,12 @@ describe('model: populate:', function() {
   });
 
   it('populating subdocuments partially with empty array (gh-481)', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create({
-      title: 'Woot'
-      , comments: [] // EMPTY ARRAY
+      title: 'Woot',
+      comments: [] // EMPTY ARRAY
     }, function(err, post) {
       assert.ifError(err);
 
@@ -1464,12 +1464,12 @@ describe('model: populate:', function() {
   });
 
   it('populating subdocuments partially with null array', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create({
-      title: 'Woot'
-      , comments: null
+      title: 'Woot',
+      comments: null
     }, function(err, post) {
       assert.ifError(err);
 
@@ -1486,17 +1486,17 @@ describe('model: populate:', function() {
   });
 
   it('populating subdocuments with array including nulls', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     var user = new User({ name: 'hans zimmer' });
     user.save(function(err) {
       assert.ifError(err);
 
       BlogPost.create({
-        title: 'Woot'
-        , fans: []
+        title: 'Woot',
+        fans: []
       }, function(err, post) {
         assert.ifError(err);
 
@@ -1520,38 +1520,38 @@ describe('model: populate:', function() {
   });
 
   it('populating more than one array at a time', function(done) {
-    var db = start()
-      , User = db.model('RefUser', users)
-      , M = db.model('PopMultiSubDocs', new Schema({
-        users: [{ type: ObjectId, ref: 'RefUser' }]
-          , fans:  [{ type: ObjectId, ref: 'RefUser' }]
-          , comments: [Comment]
-      }));
+    var db = start(),
+        User = db.model('RefUser', users),
+        M = db.model('PopMultiSubDocs', new Schema({
+          users: [{ type: ObjectId, ref: 'RefUser' }],
+          fans: [{ type: ObjectId, ref: 'RefUser' }],
+          comments: [Comment]
+        }));
 
     User.create({
-      email : 'fan1@learnboost.com'
+      email: 'fan1@learnboost.com'
     }, {
-      name   : 'Fan 2'
-      , email  : 'fan2@learnboost.com'
-      , gender : 'female'
+      name: 'Fan 2',
+      email: 'fan2@learnboost.com',
+      gender: 'female'
     }, {
       name: 'Fan 3'
     }, function(err, fan1, fan2, fan3) {
       assert.ifError(err);
 
       M.create({
-        users: [fan3]
-        , fans: [fan1]
-        , comments: [
-              { _creator: fan1, content: 'bejeah!' }
-            , { _creator: fan2, content: 'chickfila' }
+        users: [fan3],
+        fans: [fan1],
+        comments: [
+          { _creator: fan1, content: 'bejeah!' },
+          { _creator: fan2, content: 'chickfila' }
         ]
       }, {
-        users: [fan1]
-        , fans: [fan2]
-        , comments: [
-              { _creator: fan3, content: 'hello' }
-            , { _creator: fan1, content: 'world' }
+        users: [fan1],
+        fans: [fan2],
+        comments: [
+          { _creator: fan3, content: 'hello' },
+          { _creator: fan1, content: 'world' }
         ]
       }, function(err, post1, post2) {
         assert.ifError(err);
@@ -1595,13 +1595,13 @@ describe('model: populate:', function() {
   });
 
   it('populating multiple children of a sub-array at a time', function(done) {
-    var db = start()
-      , User = db.model('RefUser', users)
-      , BlogPost = db.model('RefBlogPost', posts)
-      , Inner = new Schema({
-        user: { type: ObjectId, ref: 'RefUser' }
-          , post: { type: ObjectId, ref: 'RefBlogPost' }
-      });
+    var db = start(),
+        User = db.model('RefUser', users),
+        BlogPost = db.model('RefBlogPost', posts),
+        Inner = new Schema({
+          user: { type: ObjectId, ref: 'RefUser' },
+          post: { type: ObjectId, ref: 'RefBlogPost' }
+        });
     db.model('PopMultiChildrenOfSubDocInner', Inner);
 
     var M = db.model('PopMultiChildrenOfSubDoc', new Schema({
@@ -1609,28 +1609,28 @@ describe('model: populate:', function() {
     }));
 
     User.create({
-      name   : 'Fan 1'
-      , email  : 'fan1@learnboost.com'
-      , gender : 'male'
+      name: 'Fan 1',
+      email: 'fan1@learnboost.com',
+      gender: 'male'
     }, {
-      name   : 'Fan 2'
-      , email  : 'fan2@learnboost.com'
-      , gender : 'female'
+      name: 'Fan 2',
+      email: 'fan2@learnboost.com',
+      gender: 'female'
     }, function(err, fan1, fan2) {
       assert.ifError(err);
 
       BlogPost.create({
-        title     : 'woot'
+        title: 'woot'
       }, {
-        title     : 'yay'
+        title: 'yay'
       }, function(err, post1, post2) {
         assert.ifError(err);
         M.create({
           kids: [
-              { user: fan1, post: post1, y: 5 }
-            , { user: fan2, post: post2, y: 8 }
-          ]
-        , x: 4
+            { user: fan1, post: post1, y: 5 },
+            { user: fan2, post: post2, y: 8 }
+          ],
+          x: 4
         }, function(err, m1) {
           assert.ifError(err);
 
@@ -1657,9 +1657,9 @@ describe('model: populate:', function() {
   });
 
   it('passing sort options to the populate method', function(done) {
-    var db = start()
-      , P = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        P = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.create(
       { name: 'aaron', age: 10 },
@@ -1684,7 +1684,7 @@ describe('model: populate:', function() {
             assert.equal(post.fans[3].name, 'aaron');
 
             P.findById(post)
-            .populate('fans', 'name', null, { sort: {'name':-1} })
+            .populate('fans', 'name', null, { sort: {'name': -1} })
             .exec(function(err, post) {
               assert.ifError(err);
 
@@ -1723,19 +1723,19 @@ describe('model: populate:', function() {
     });
     var name = 'b' + random();
     var sJ = new Schema({
-      b    : [{ type: Schema.Types.ObjectId, ref: name }]
+      b: [{ type: Schema.Types.ObjectId, ref: name }]
     });
     var B = db.model(name, sB);
     var J = db.model('j' + random(), sJ);
 
-    var b1 = new B({ name : 'thing1'});
-    var b2 = new B({ name : 'thing2'});
-    var b3 = new B({ name : 'thing3'});
-    var b4 = new B({ name : 'thing4'});
-    var b5 = new B({ name : 'thing5'});
+    var b1 = new B({ name: 'thing1'});
+    var b2 = new B({ name: 'thing2'});
+    var b3 = new B({ name: 'thing3'});
+    var b4 = new B({ name: 'thing4'});
+    var b5 = new B({ name: 'thing5'});
 
-    var j1 = new J({ b : [b1.id, b2.id, b5.id]});
-    var j2 = new J({ b : [b3.id, b4.id, b5.id]});
+    var j1 = new J({ b: [b1.id, b2.id, b5.id]});
+    var j2 = new J({ b: [b3.id, b4.id, b5.id]});
 
     var count = 7;
 
@@ -1753,7 +1753,7 @@ describe('model: populate:', function() {
     }
 
     function next() {
-      J.find().populate({ path: 'b', options : { limit : 2 } }).exec(function(err, j) {
+      J.find().populate({ path: 'b', options: { limit: 2 } }).exec(function(err, j) {
         assert.equal(j.length, 2);
         assert.equal(j[0].b.length, 2);
         assert.equal(j[1].b.length, 2);
@@ -1776,13 +1776,13 @@ describe('model: populate:', function() {
     var db = start();
 
     var UserSchema = new Schema({
-      _id: String
-      , name: String
+      _id: String,
+      name: String
     });
 
     var NoteSchema = new Schema({
-      author: { type: String, ref: 'UserWithStringId' }
-      , body: String
+      author: { type: String, ref: 'UserWithStringId' },
+      body: String
     });
 
     var User = db.model('UserWithStringId', UserSchema, random());
@@ -1813,13 +1813,13 @@ describe('model: populate:', function() {
     var db = start();
 
     var UserSchema = new Schema({
-      _id: Number
-      , name: String
+      _id: Number,
+      name: String
     });
 
     var NoteSchema = new Schema({
-      author: { type: Number, ref: 'UserWithNumberId' }
-      , body: String
+      author: { type: Number, ref: 'UserWithNumberId' },
+      body: String
     });
 
     var User = db.model('UserWithNumberId', UserSchema, random());
@@ -1861,10 +1861,10 @@ describe('model: populate:', function() {
     var Str = db.model('StringRefRequired', strSchema, random());
 
     var commentSchema = new Schema({
-      user: {type: ObjectId, ref: 'ObjectIdRefRequiredField', required: true}
-      , num: {type: Number, ref: 'NumberRefRequired', required: true}
-      , str: {type: String, ref: 'StringRefRequired', required: true}
-      , text: String
+      user: {type: ObjectId, ref: 'ObjectIdRefRequiredField', required: true},
+      num: {type: Number, ref: 'NumberRefRequired', required: true},
+      str: {type: String, ref: 'StringRefRequired', required: true},
+      text: String
     });
     var Comment = db.model('CommentWithRequiredField', commentSchema);
 
@@ -1924,9 +1924,9 @@ describe('model: populate:', function() {
   });
 
   it('populate works with schemas with both id and _id defined', function(done) {
-    var db = start()
-      , S1 = new Schema({ id: String })
-      , S2 = new Schema({ things: [{ type: ObjectId, ref: '_idAndid' }]});
+    var db = start(),
+        S1 = new Schema({ id: String }),
+        S2 = new Schema({ things: [{ type: ObjectId, ref: '_idAndid' }]});
 
     var M1 = db.model('_idAndid', S1);
     var M2 = db.model('populateWorksWith_idAndidSchemas', S2);
@@ -1953,16 +1953,16 @@ describe('model: populate:', function() {
   });
 
   it('Update works with populated arrays (gh-602)', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
-    User.create({name:'aphex'},{name:'twin'}, function(err, u1, u2) {
+    User.create({name: 'aphex'},{name: 'twin'}, function(err, u1, u2) {
       assert.ifError(err);
 
       BlogPost.create({
-        title: 'Woot'
-        , fans: []
+        title: 'Woot',
+        fans: []
       }, function(err, post) {
         assert.ifError(err);
 
@@ -1990,9 +1990,9 @@ describe('model: populate:', function() {
   });
 
   it('toJSON should also be called for refs (gh-675)', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefUser', users);
 
     User.prototype._toJSON = User.prototype.toJSON;
     User.prototype.toJSON = function() {
@@ -2009,14 +2009,14 @@ describe('model: populate:', function() {
     };
 
     User.create({
-      name  : 'Jerem'
-      , email : 'jerem@jolicloud.com'
+      name: 'Jerem',
+      email: 'jerem@jolicloud.com'
     }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
-        title     : 'Ping Pong'
-        , _creator  : creator
+        title: 'Ping Pong',
+        _creator: creator
       }, function(err, post) {
         assert.ifError(err);
 
@@ -2040,13 +2040,13 @@ describe('model: populate:', function() {
     var db = start();
 
     var UserSchema = new Schema({
-      _id: Buffer
-      , name: String
+      _id: Buffer,
+      name: String
     });
 
     var NoteSchema = new Schema({
-      author: { type: Buffer, ref: 'UserWithBufferId' }
-      , body: String
+      author: { type: Buffer, ref: 'UserWithBufferId' },
+      body: String
     });
 
     var User = db.model('UserWithBufferId', UserSchema, random());
@@ -2077,13 +2077,13 @@ describe('model: populate:', function() {
     var db = start();
 
     var UserSchema = new Schema({
-      _id: Buffer
-      , name: String
+      _id: Buffer,
+      name: String
     });
 
     var NoteSchema = new Schema({
-      author: { type: Buffer, ref: 'UserWithBufferId', required: true }
-      , body: String
+      author: { type: Buffer, ref: 'UserWithBufferId', required: true },
+      body: String
     });
 
     var User = db.model('UserWithBufferId', UserSchema, random());
@@ -2111,19 +2111,19 @@ describe('model: populate:', function() {
   });
 
   it('populating with custom model selection (gh-773)', function(done) {
-    var db = start()
-      , BlogPost = db.model('RefBlogPost', posts)
-      , User = db.model('RefAlternateUser', users);
+    var db = start(),
+        BlogPost = db.model('RefBlogPost', posts),
+        User = db.model('RefAlternateUser', users);
 
     User.create({
-      name  : 'Daniel'
-      , email : 'daniel.baulig@gmx.de'
+      name: 'Daniel',
+      email: 'daniel.baulig@gmx.de'
     }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
-        title     : 'woot'
-        , _creator  : creator
+        title: 'woot',
+        _creator: creator
       }, function(err, post) {
         assert.ifError(err);
 
@@ -2225,8 +2225,8 @@ describe('model: populate:', function() {
       User = db.model('RefAlternateUser');
 
       User.create({
-        name  : 'use an object'
-        , email : 'fo-real@objects.r.fun'
+        name: 'use an object',
+        email: 'fo-real@objects.r.fun'
       }
       , { name: 'yup' }
       , { name: 'not here' }
@@ -2234,8 +2234,8 @@ describe('model: populate:', function() {
         assert.ifError(err);
 
         B.create({
-          title: 'woot'
-          , fans: [fan1, fan2, fan3]
+          title: 'woot',
+          fans: [fan1, fan2, fan3]
         }, function(err, post_) {
           assert.ifError(err);
           post = post_;
@@ -2251,11 +2251,11 @@ describe('model: populate:', function() {
     it('works', function(done) {
       B.findById(post._id)
       .populate({
-        path: 'fans'
-        , select: 'name'
-        , model: 'RefAlternateUser'
-        , match: { name: /u/ }
-        , options: { sort: {'name': -1} }
+        path: 'fans',
+        select: 'name',
+        model: 'RefAlternateUser',
+        match: { name: /u/ },
+        options: { sort: {'name': -1} }
       })
       .exec(function(err, post) {
         assert.ifError(err);
@@ -2289,13 +2289,13 @@ describe('model: populate:', function() {
       _id = new mongoose.Types.ObjectId;
 
       User.create({
-        name  : 'Phoenix'
-        , email : 'phx@az.com'
-        , blogposts: [_id]
+        name: 'Phoenix',
+        email: 'phx@az.com',
+        blogposts: [_id]
       }, {
-        name  : 'Newark'
-        , email : 'ewr@nj.com'
-        , blogposts: [_id]
+        name: 'Newark',
+        email: 'ewr@nj.com',
+        blogposts: [_id]
       }, function(err, u1, u2) {
         assert.ifError(err);
 
@@ -2303,13 +2303,13 @@ describe('model: populate:', function() {
         user2 = u2;
 
         B.create({
-          title     : 'the how and why'
-          , _creator  : user1
-          , fans: [user1, user2]
+          title: 'the how and why',
+          _creator: user1,
+          fans: [user1, user2]
         }, {
-          title     : 'green eggs and ham'
-          , _creator  : user2
-          , fans: [user2, user1]
+          title: 'green eggs and ham',
+          _creator: user2,
+          fans: [user2, user1]
         }, function(err, p1, p2) {
           assert.ifError(err);
           post1 = p1;
@@ -2461,19 +2461,19 @@ describe('model: populate:', function() {
 
   describe('populating combined with lean (gh-1260)', function() {
     it('with findOne', function(done) {
-      var db = start()
-        , BlogPost = db.model('RefBlogPost', posts + random())
-        , User = db.model('RefUser', users + random());
+      var db = start(),
+          BlogPost = db.model('RefBlogPost', posts + random()),
+          User = db.model('RefUser', users + random());
 
       User.create({
-        name  : 'Guillermo'
-        , email : 'rauchg@gmail.com'
+        name: 'Guillermo',
+        email: 'rauchg@gmail.com'
       }, function(err, creator) {
         assert.ifError(err);
 
         BlogPost.create({
-          title     : 'woot'
-          , _creator  : creator
+          title: 'woot',
+          _creator: creator
         }, function(err, post) {
           assert.ifError(err);
 
@@ -2496,25 +2496,25 @@ describe('model: populate:', function() {
     });
 
     it('with find', function(done) {
-      var db = start()
-        , BlogPost = db.model('RefBlogPost', posts + random())
-        , User = db.model('RefUser', users + random());
+      var db = start(),
+          BlogPost = db.model('RefBlogPost', posts + random()),
+          User = db.model('RefUser', users + random());
 
       User.create({
-        name  : 'Fan 1'
-        , email : 'fan1@learnboost.com'
+        name: 'Fan 1',
+        email: 'fan1@learnboost.com'
       }, {
-        name  : 'Fan 2'
-        , email : 'fan2@learnboost.com'
+        name: 'Fan 2',
+        email: 'fan2@learnboost.com'
       }, function(err, fan1, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
-          title : 'Woot'
-          , fans  : [fan1, fan2]
+          title: 'Woot',
+          fans: [fan1, fan2]
         }, {
-          title : 'Woot2'
-          , fans  : [fan2, fan1]
+          title: 'Woot2',
+          fans: [fan2, fan1]
         }, function(err, post1, post2) {
           assert.ifError(err);
 
@@ -2558,24 +2558,24 @@ describe('model: populate:', function() {
       U = db.model('RefUser', users + random());
 
       U.create({
-        name  : 'Fan 1'
-        , email : 'fan1@learnboost.com'
+        name: 'Fan 1',
+        email: 'fan1@learnboost.com'
       }, {
-        name  : 'Fan 2'
-        , email : 'fan2@learnboost.com'
+        name: 'Fan 2',
+        email: 'fan2@learnboost.com'
       }, function(err, fan1, fan2) {
         assert.ifError(err);
         u1 = fan1;
         u2 = fan2;
 
         B.create({
-          title : 'Woot'
-          , fans  : [fan1, fan2]
-          , _creator: fan1
+          title: 'Woot',
+          fans: [fan1, fan2],
+          _creator: fan1
         }, {
-          title : 'Woot2'
-          , fans  : [fan2, fan1]
-          , _creator: fan2
+          title: 'Woot2',
+          fans: [fan2, fan1],
+          _creator: fan2
         }, function(err, post) {
           assert.ifError(err);
           b1 = post;
@@ -2635,9 +2635,9 @@ describe('model: populate:', function() {
       }), 'comments_' + random());
 
       U = db.model('User', Schema({
-        name: 'string'
-        , comments: [{ type: Schema.ObjectId, ref: 'Comment' }]
-        , comment: { type: Schema.ObjectId, ref: 'Comment' }
+        name: 'string',
+        comments: [{ type: Schema.ObjectId, ref: 'Comment' }],
+        comment: { type: Schema.ObjectId, ref: 'Comment' }
       }), 'users_' + random());
 
       C.create({ body: 'comment 1', title: '1' }, { body: 'comment 2', title: 2 }, function(err, c1_, c2_) {
@@ -2661,7 +2661,7 @@ describe('model: populate:', function() {
 
     describe('in a subdocument', function() {
       it('works', function(done) {
-        U.find({name:'u1'}).populate('comments', { _id: 0 }).exec(function(err, docs) {
+        U.find({name: 'u1'}).populate('comments', { _id: 0 }).exec(function(err, docs) {
           assert.ifError(err);
 
           var doc = docs[0];
@@ -2674,7 +2674,7 @@ describe('model: populate:', function() {
             assert.equal('number', typeof d._doc.__v);
           });
 
-          U.findOne({name:'u1'}).populate('comments', 'title -_id').exec(function(err, doc) {
+          U.findOne({name: 'u1'}).populate('comments', 'title -_id').exec(function(err, doc) {
             assert.ifError(err);
             assert.equal(2, doc.comments.length);
             doc.comments.forEach(function(d) {
@@ -2684,7 +2684,7 @@ describe('model: populate:', function() {
               assert.equal(undefined, d.body);
               assert.equal(typeof d._doc.__v, 'undefined');
             });
-            U.findOne({name:'u1'}).populate('comments', '-_id').exec(function(err, doc) {
+            U.findOne({name: 'u1'}).populate('comments', '-_id').exec(function(err, doc) {
               assert.ifError(err);
               assert.equal(2, doc.comments.length);
               doc.comments.forEach(function(d) {
@@ -2701,7 +2701,7 @@ describe('model: populate:', function() {
       });
 
       it('with lean', function(done) {
-        U.find({name:'u1'}).lean().populate({ path: 'comments', select: { _id: 0 }, options: { lean: true }}).exec(function(err, docs) {
+        U.find({name: 'u1'}).lean().populate({ path: 'comments', select: { _id: 0 }, options: { lean: true }}).exec(function(err, docs) {
           assert.ifError(err);
 
           var doc = docs[0];
@@ -2712,7 +2712,7 @@ describe('model: populate:', function() {
             assert.equal('number', typeof d.__v);
           });
 
-          U.findOne({name:'u1'}).lean().populate('comments', '-_id', null, { lean: true}).exec(function(err, doc) {
+          U.findOne({name: 'u1'}).lean().populate('comments', '-_id', null, { lean: true}).exec(function(err, doc) {
             assert.ifError(err);
             assert.equal(2, doc.comments.length);
             doc.comments.forEach(function(d) {
@@ -2756,7 +2756,7 @@ describe('model: populate:', function() {
 
     var articleSchema = new Schema({
       body: String,
-      mediaAttach: {type: Schema.ObjectId, ref : '1444-Media'},
+      mediaAttach: {type: Schema.ObjectId, ref: '1444-Media'},
       author: String
     });
     var Article = db.model('1444-Article', articleSchema);
@@ -2904,23 +2904,23 @@ describe('model: populate:', function() {
     });
 
     it('when saving new docs', function(done) {
-      Cat.create({name:'new1'},{name:'new2'},{name:'new3'}, function(err, a, b, c) {
+      Cat.create({name: 'new1'},{name: 'new2'},{name: 'new3'}, function(err, a, b, c) {
         if (err) return done(err);
 
         Litter.create({
-          name: 'new'
-          , cats:[a]
-          , o: b
-          , a: [c]
+          name: 'new',
+          cats: [a],
+          o: b,
+          a: [c]
         }, confirm(done));
       });
     });
 
     it('when saving existing docs 5T5', function(done) {
-      Cat.create({name:'ex1'},{name:'ex2'},{name:'ex3'}, function(err, a, b, c) {
+      Cat.create({name: 'ex1'},{name: 'ex2'},{name: 'ex3'}, function(err, a, b, c) {
         if (err) return done(err);
 
-        Litter.create({name:'existing'}, function(err, doc) {
+        Litter.create({name: 'existing'}, function(err, doc) {
           doc.cats = [a];
           doc.o = b;
           doc.a = [c];
@@ -3006,7 +3006,7 @@ describe('model: populate:', function() {
     var db = start();
 
     var teamSchema = new Schema({
-      members:[{
+      members: [{
         user: {type: ObjectId, ref: 'gh3279'},
         role: String
       }]

From 2b12b095fb50db69c82f1a140bc438f127d5cb15 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 12 Jan 2016 09:59:38 -0500
Subject: [PATCH 0194/2240] test(document): repro #3754

---
 test/document.hooks.test.js | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index d557860daa6..60844e6e9d1 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -809,4 +809,34 @@ describe('document: hooks:', function() {
       db.close(done);
     });
   });
+
+  it('remove hooks for single nested (gh-3754)', function(done) {
+    var db = start();
+    var postCount = 0;
+    var PhotoSchema = new mongoose.Schema({
+      bla: String
+    });
+
+    PhotoSchema.post('remove', function(photo) {
+      ++postCount;
+    });
+
+    var PersonSchema = new mongoose.Schema({
+      photo: PhotoSchema
+    });
+
+    var Person = db.model('Person', PersonSchema);
+
+    Person.create({ photo: { bla: 'test' } }, function(error, person) {
+      assert.ifError(error);
+      person.photo.remove();
+      person.save(function(error) {
+        assert.ifError(error);
+        setTimeout(function() {
+          assert.equal(postCount, 1);
+          done();
+        }, 0);
+      });
+    });
+  });
 });

From 8e29c5b8ce90d3d455224280f19c799c7bb0ef50 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 12 Jan 2016 10:00:21 -0500
Subject: [PATCH 0195/2240] fix(types): properly fire remove hooks on single
 nested (Fix #3754)

---
 lib/types/subdocument.js | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js
index b5097f91339..f9dd3d98aa2 100644
--- a/lib/types/subdocument.js
+++ b/lib/types/subdocument.js
@@ -85,3 +85,39 @@ Subdocument.prototype.ownerDocument = function() {
 
   return this.$__.ownerDocument = parent;
 };
+
+/**
+ * Null-out this subdoc
+ *
+ * @param {Function} [callback] optional callback for compatibility with Document.prototype.remove
+ */
+
+Subdocument.prototype.remove = function(callback) {
+  this.$parent.set(this.$basePath, null);
+  registerRemoveListener(this);
+  if (callback) {
+    callback(null);
+  }
+};
+
+/*!
+ * Registers remove event listeners for triggering
+ * on subdocuments.
+ *
+ * @param {EmbeddedDocument} sub
+ * @api private
+ */
+
+function registerRemoveListener(sub) {
+  var owner = sub.ownerDocument();
+
+  owner.on('save', emitRemove);
+  owner.on('remove', emitRemove);
+
+  function emitRemove() {
+    owner.removeListener('save', emitRemove);
+    owner.removeListener('remove', emitRemove);
+    sub.emit('remove', sub);
+    owner = sub = emitRemove = null;
+  }
+}

From b92c849810486c30b332af47fffd77e2bb446d0a Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Tue, 12 Jan 2016 09:11:09 -0700
Subject: [PATCH 0196/2240] update acquit

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index cc7a30eb476..062131ac375 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,7 @@
     "sliced": "0.0.5"
   },
   "devDependencies": {
-    "acquit": "0.3.0",
+    "acquit": "0.4.1",
     "acquit-ignore": "0.0.1",
     "benchmark": "1.0.0",
     "bluebird": "2.9.34",

From 53888dccdf5e8720ba5a4555f76ae3a694e7b090 Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Tue, 12 Jan 2016 09:31:36 -0700
Subject: [PATCH 0197/2240] update uglify-js

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index cc7a30eb476..eb88ab603ad 100644
--- a/package.json
+++ b/package.json
@@ -50,7 +50,7 @@
     "open": "0.0.3",
     "q": "1.4.1",
     "tbd": "0.6.4",
-    "uglify-js": "2.4.24",
+    "uglify-js": "2.6.1",
     "underscore": "1.5.2"
   },
   "browserDependencies": {

From c2106b5e5e1dd4b0b95514f6d3bb07afa4c6822d Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 13 Jan 2016 16:05:46 -0500
Subject: [PATCH 0198/2240] fix(schema): listeners and removeListener are now
 reserved words (Fix #3759)

---
 lib/schema.js | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/schema.js b/lib/schema.js
index 8b699be6ccf..42b5ddea6d7 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -410,6 +410,8 @@ var reserved = Schema.reserved;
 reserved.emit =
 reserved.on =
 reserved.once =
+reserved.listeners =
+reserved.removeListener =
 // document properties and functions
 reserved.collection =
 reserved.db =

From 61e8696946454b335f319f3808bcecd304ed7be4 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 13 Jan 2016 16:13:48 -0500
Subject: [PATCH 0199/2240] refactor(test): common connection for several tests

---
 test/document.test.js | 224 ++++++++++++++++++++++--------------------
 1 file changed, 115 insertions(+), 109 deletions(-)

diff --git a/test/document.test.js b/test/document.test.js
index dad622ad0a1..2824c324681 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -2176,146 +2176,152 @@ describe('document', function() {
     });
   });
 
-  it('single embedded docs post hooks (gh-3679)', function(done) {
-    var db = start();
-    var postHookCalls = [];
-    var personSchema = new Schema({ name: String });
-    personSchema.post('save', function() {
-      postHookCalls.push(this);
-    });
+  describe('bug fixes', function() {
+    var db;
 
-    var bandSchema = new Schema({ guitarist: personSchema, name: String });
-    var Band = db.model('gh3679', bandSchema);
-    var obj = { name: "Guns N' Roses", guitarist: { name: 'Slash' } };
+    before(function() {
+      db = start();
+    });
 
-    Band.create(obj, function(error) {
-      assert.ifError(error);
-      setTimeout(function() {
-        assert.equal(postHookCalls.length, 1);
-        assert.equal(postHookCalls[0].name, 'Slash');
-        db.close(done);
-      });
+    after(function(done) {
+      db.close(done);
     });
-  });
 
-  it('single embedded docs .set() (gh-3686)', function(done) {
-    var db = start();
-    var personSchema = new Schema({ name: String, realName: String });
+    it('single embedded docs post hooks (gh-3679)', function(done) {
+      var postHookCalls = [];
+      var personSchema = new Schema({ name: String });
+      personSchema.post('save', function() {
+        postHookCalls.push(this);
+      });
 
-    var bandSchema = new Schema({
-      guitarist: personSchema,
-      name: String
-    });
-    var Band = db.model('gh3686', bandSchema);
-    var obj = {
-      name: "Guns N' Roses",
-      guitarist: { name: 'Slash', realName: 'Saul Hudson' }
-    };
+      var bandSchema = new Schema({ guitarist: personSchema, name: String });
+      var Band = db.model('gh3679', bandSchema);
+      var obj = { name: "Guns N' Roses", guitarist: { name: 'Slash' } };
 
-    Band.create(obj, function(error, gnr) {
-      gnr.set('guitarist.name', 'Buckethead');
-      gnr.save(function(error) {
+      Band.create(obj, function(error) {
         assert.ifError(error);
-        assert.equal(gnr.guitarist.name, 'Buckethead');
-        assert.equal(gnr.guitarist.realName, 'Saul Hudson');
-        db.close(done);
+        setTimeout(function() {
+          assert.equal(postHookCalls.length, 1);
+          assert.equal(postHookCalls[0].name, 'Slash');
+          done();
+        });
       });
     });
-  });
 
-  it('single embedded docs with arrays pre hooks (gh-3680)', function(done) {
-    var db = start();
-    var childSchema = Schema({ count: Number });
+    it('single embedded docs .set() (gh-3686)', function(done) {
+      var personSchema = new Schema({ name: String, realName: String });
 
-    var preCalls = 0;
-    childSchema.pre('save', function(next) {
-      ++preCalls;
-      next();
-    });
+      var bandSchema = new Schema({
+        guitarist: personSchema,
+        name: String
+      });
+      var Band = db.model('gh3686', bandSchema);
+      var obj = {
+        name: "Guns N' Roses",
+        guitarist: { name: 'Slash', realName: 'Saul Hudson' }
+      };
 
-    var SingleNestedSchema = new Schema({
-      children: [childSchema]
+      Band.create(obj, function(error, gnr) {
+        gnr.set('guitarist.name', 'Buckethead');
+        gnr.save(function(error) {
+          assert.ifError(error);
+          assert.equal(gnr.guitarist.name, 'Buckethead');
+          assert.equal(gnr.guitarist.realName, 'Saul Hudson');
+          done();
+        });
+      });
     });
 
-    var ParentSchema = new Schema({
-      singleNested: SingleNestedSchema
-    });
+    it('single embedded docs with arrays pre hooks (gh-3680)', function(done) {
+      var childSchema = Schema({ count: Number });
 
-    var Parent = db.model('gh3680', ParentSchema);
-    var obj = { singleNested: { children: [{ count: 0 }] } };
-    Parent.create(obj, function(error) {
-      assert.ifError(error);
-      assert.equal(preCalls, 1);
-      db.close(done);
-    });
-  });
+      var preCalls = 0;
+      childSchema.pre('save', function(next) {
+        ++preCalls;
+        next();
+      });
 
-  it('nested single embedded doc validation (gh-3702)', function(done) {
-    var db = start();
-    var childChildSchema = Schema({ count: { type: Number, min: 1 } });
-    var childSchema = new Schema({ child: childChildSchema });
-    var parentSchema = new Schema({ child: childSchema });
+      var SingleNestedSchema = new Schema({
+        children: [childSchema]
+      });
 
-    var Parent = db.model('gh3702', parentSchema);
-    var obj = { child: { child: { count: 0 } } };
-    Parent.create(obj, function(error) {
-      assert.ok(error);
-      assert.ok(/ValidationError/.test(error.toString()));
-      db.close(done);
+      var ParentSchema = new Schema({
+        singleNested: SingleNestedSchema
+      });
+
+      var Parent = db.model('gh3680', ParentSchema);
+      var obj = { singleNested: { children: [{ count: 0 }] } };
+      Parent.create(obj, function(error) {
+        assert.ifError(error);
+        assert.equal(preCalls, 1);
+        done();
+      });
     });
-  });
 
-  it('handles virtuals with dots correctly (gh-3618)', function(done) {
-    var db = start();
-    var testSchema = new Schema({ nested: { type: Object, default: {} } });
-    testSchema.virtual('nested.test').get(function() {
-      return true;
+    it('nested single embedded doc validation (gh-3702)', function(done) {
+      var childChildSchema = Schema({ count: { type: Number, min: 1 } });
+      var childSchema = new Schema({ child: childChildSchema });
+      var parentSchema = new Schema({ child: childSchema });
+
+      var Parent = db.model('gh3702', parentSchema);
+      var obj = { child: { child: { count: 0 } } };
+      Parent.create(obj, function(error) {
+        assert.ok(error);
+        assert.ok(/ValidationError/.test(error.toString()));
+        done();
+      });
     });
 
-    var Test = db.model('gh3618', testSchema);
+    it('handles virtuals with dots correctly (gh-3618)', function(done) {
+      var testSchema = new Schema({ nested: { type: Object, default: {} } });
+      testSchema.virtual('nested.test').get(function() {
+        return true;
+      });
 
-    var test = new Test();
+      var Test = db.model('gh3618', testSchema);
 
-    var doc = test.toObject({ getters: true, virtuals: true });
-    delete doc._id;
-    delete doc.id;
-    assert.deepEqual(doc, { nested: { test: true } });
+      var test = new Test();
 
-    doc = test.toObject({ getters: false, virtuals: true });
-    delete doc._id;
-    delete doc.id;
-    assert.deepEqual(doc, { nested: { test: true } });
-    db.close(done);
-  });
+      var doc = test.toObject({ getters: true, virtuals: true });
+      delete doc._id;
+      delete doc.id;
+      assert.deepEqual(doc, { nested: { test: true } });
 
-  it('handles pushing with numeric keys (gh-3623)', function(done) {
-    var db = start();
-    var schema = new Schema({
-      array: [{
-        1: {
-          date: Date
-        },
-        2: {
-          date: Date
-        },
-        3: {
-          date: Date
-        }
-      }]
+      doc = test.toObject({ getters: false, virtuals: true });
+      delete doc._id;
+      delete doc.id;
+      assert.deepEqual(doc, { nested: { test: true } });
+      done();
     });
 
-    var MyModel = db.model('gh3623', schema);
+    it('handles pushing with numeric keys (gh-3623)', function(done) {
+      var schema = new Schema({
+        array: [{
+          1: {
+            date: Date
+          },
+          2: {
+            date: Date
+          },
+          3: {
+            date: Date
+          }
+        }]
+      });
 
-    var doc = { array: [{ 2: {} }] };
-    MyModel.collection.insertOne(doc, function(error) {
-      assert.ifError(error);
+      var MyModel = db.model('gh3623', schema);
 
-      MyModel.findOne({ _id: doc._id }, function(error, doc) {
+      var doc = { array: [{ 2: {} }] };
+      MyModel.collection.insertOne(doc, function(error) {
         assert.ifError(error);
-        doc.array.push({ 2: {} });
-        doc.save(function(error) {
+
+        MyModel.findOne({ _id: doc._id }, function(error, doc) {
           assert.ifError(error);
-          db.close(done);
+          doc.array.push({ 2: {} });
+          doc.save(function(error) {
+            assert.ifError(error);
+            done();
+          });
         });
       });
     });

From a1f575bc7bd6ec80e6da1edc3cee420206312750 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 13 Jan 2016 16:28:12 -0500
Subject: [PATCH 0200/2240] fix(document): execPopulate (Fix #3753 #3755)

---
 lib/document.js       | 18 +++++++++++-------
 test/document.test.js | 30 ++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index b147c543a6e..9fbbe69438c 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -2236,19 +2236,23 @@ Document.prototype.populate = function populate() {
  *     doc.execPopulate()
  *
  *
- * ####NOTE:
- *
- * Population does not occur unless a `callback` is passed.
- * Passing the same path a second time will overwrite the previous path options.
- * See [Model.populate()](#model_Model.populate) for explaination of options.
- *
  * @see Document.populate #Document_model.populate
  * @api public
  * @return {Promise} promise that resolves to the document when population is done
  */
 
 Document.prototype.execPopulate = function() {
-  return this.populate(function() {});
+  var Promise = PromiseProvider.get();
+  var _this = this;
+  return new Promise.ES6(function(resolve, reject) {
+    _this.populate(function(error, res) {
+      if (error) {
+        reject(error);
+      } else {
+        resolve(res);
+      }
+    });
+  });
 };
 
 /**
diff --git a/test/document.test.js b/test/document.test.js
index 2824c324681..f2283ae6aa7 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -2325,5 +2325,35 @@ describe('document', function() {
         });
       });
     });
+
+    it('execPopulate (gh-3753)', function(done) {
+      var childSchema = new Schema({
+        name: String
+      });
+
+      var parentSchema = new Schema({
+        name: String,
+        children: [{ type: ObjectId, ref: 'gh3753' }]
+      });
+
+      var Child = db.model('gh3753', childSchema);
+      var Parent = db.model('gh3753_0', parentSchema);
+
+      Child.create({ name: 'Luke Skywalker' }, function(error, child) {
+        assert.ifError(error);
+        var doc = { name: 'Darth Vader', children: [child._id] };
+        Parent.create(doc, function(error, doc) {
+          Parent.findOne({ _id: doc._id }, function(error, doc) {
+            assert.ifError(error);
+            assert.ok(doc);
+            doc.populate('children').execPopulate().then(function(doc) {
+              assert.equal(doc.children.length, 1);
+              assert.equal(doc.children[0].name, 'Luke Skywalker');
+              done();
+            });
+          });
+        });
+      });
+    });
   });
 });

From a07fffb83ba3107a9921112af3c3f729328b74cf Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 14 Jan 2016 09:18:18 -0500
Subject: [PATCH 0201/2240] fix: webpack by upgrading to mongodb@2.1.4 (Fix
 #3713)

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index f6a55db62c5..240c6251b8e 100644
--- a/package.json
+++ b/package.json
@@ -20,10 +20,10 @@
   "license": "MIT",
   "dependencies": {
     "async": "0.9.0",
-    "bson": "0.4.19",
+    "bson": "0.4.21",
     "hooks-fixed": "1.1.0",
     "kareem": "1.0.1",
-    "mongodb": "2.1.2",
+    "mongodb": "2.1.4",
     "mpath": "0.1.1",
     "mpromise": "0.5.4",
     "mquery": "1.6.3",

From 823d43a0ef742e51b3de27db978c805c76bdfe87 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 14 Jan 2016 12:50:18 -0500
Subject: [PATCH 0202/2240] chore: upgrade acquit-ignore to match peer

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 240c6251b8e..a1bdebacbfa 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
   },
   "devDependencies": {
     "acquit": "0.4.1",
-    "acquit-ignore": "0.0.1",
+    "acquit-ignore": "0.0.3",
     "benchmark": "1.0.0",
     "bluebird": "2.9.34",
     "co": "3.1.0",

From 42e7ba5144a47d0f2ae6ac2227a94b398691ede0 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 14 Jan 2016 12:55:54 -0500
Subject: [PATCH 0203/2240] docs: fix broken image in README

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 384b7f06539..e9a63fdf1ff 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ Build your own Mongoose plugin through [generator-mongoose-plugin](https://githu
 View all 100+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors). Stand up and be counted as a [contributor](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md) too!
 
 ## Live Examples
-
+
 
 ## Installation
 

From 95ce489a58fb5f51a547db77525680a0140cc3a3 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 14 Jan 2016 13:00:49 -0500
Subject: [PATCH 0204/2240] docs: fix broken image in README take 2

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index e9a63fdf1ff..5b8cce57f69 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ Build your own Mongoose plugin through [generator-mongoose-plugin](https://githu
 View all 100+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors). Stand up and be counted as a [contributor](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md) too!
 
 ## Live Examples
-
+
 
 ## Installation
 

From 7004584fc80c77270543b61e53cd8f0744af9805 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 14 Jan 2016 13:02:04 -0500
Subject: [PATCH 0205/2240] docs: runnable image top border removed

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 5b8cce57f69..863aeac08b2 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ Build your own Mongoose plugin through [generator-mongoose-plugin](https://githu
 View all 100+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors). Stand up and be counted as a [contributor](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md) too!
 
 ## Live Examples
-
+
 
 ## Installation
 

From 16839d74fedb81d6034fdbe396732f2dcad2dee2 Mon Sep 17 00:00:00 2001
From: Marcus Milton-Ellis 
Date: Fri, 15 Jan 2016 07:49:58 -0800
Subject: [PATCH 0206/2240] Update README.md

removing 'atomically' sentence because it doesnt fit with the rest of the readme
---
 README.md | 1 -
 1 file changed, 1 deletion(-)

diff --git a/README.md b/README.md
index 863aeac08b2..0f9e9580b4b 100644
--- a/README.md
+++ b/README.md
@@ -217,7 +217,6 @@ BlogPost.findById(myId, function (err, post) {
 
 Embedded documents enjoy all the same features as your models. Defaults, validators, middleware. Whenever an error occurs, it's bubbled to the `save()` error callback, so error handling is a snap!
 
-Mongoose interacts with your embedded documents in arrays _atomically_, out of the box.
 
 ### Middleware
 

From 8066b145c07984c8b7e56dbb51721c0a3d48e18a Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 15 Jan 2016 14:15:03 -0500
Subject: [PATCH 0207/2240] fix(types): smarter casting for buffer with number
 (Fix #3764)

---
 lib/schema/buffer.js      | 3 +++
 test/types.buffer.test.js | 9 +++++++++
 2 files changed, 12 insertions(+)

diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js
index d26cc339b7c..b64234fce89 100644
--- a/lib/schema/buffer.js
+++ b/lib/schema/buffer.js
@@ -125,6 +125,9 @@ SchemaBuffer.prototype.cast = function(value, doc, init) {
 
   var type = typeof value;
   if ('string' == type || 'number' == type || Array.isArray(value)) {
+    if (type === 'number') {
+      value = [value];
+    }
     ret = new MongooseBuffer(value, [this.path, doc]);
     return ret;
   }
diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js
index 74af5701885..b7081c387d3 100644
--- a/test/types.buffer.test.js
+++ b/test/types.buffer.test.js
@@ -450,5 +450,14 @@ describe('types.buffer', function() {
         });
       });
     });
+
+    it('cast from number (gh-3764)', function(done) {
+      var schema = new Schema({ buf: Buffer });
+      var MyModel = mongoose.model('gh3764', schema);
+
+      var doc = new MyModel({ buf: 9001 });
+      assert.equal(doc.buf.length, 1);
+      done();
+    });
   });
 });

From e17e233affcde0ec6564f62e65e06001a35b9d5e Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 15 Jan 2016 14:23:03 -0500
Subject: [PATCH 0208/2240] chore: release 4.3.6

---
 History.md      |    12 +
 bin/mongoose.js | 16593 +++++++++++++++++++++++-----------------------
 package.json    |     2 +-
 3 files changed, 8313 insertions(+), 8294 deletions(-)

diff --git a/History.md b/History.md
index a24867f1a45..faa859071ba 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,15 @@
+4.3.6 / 2016-01-15
+==================
+ * fix(types): casting a number to a buffer #3764
+ * fix: add "listener" to reserved keywords #3759
+ * chore: upgrade uglify #3757 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix: broken execPopulate() in 4.3.5 #3755 #3753
+ * fix: ability to remove() a single embedded doc #3754
+ * style: comma-last in test folder #3751 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * docs: clarify versionKey option #3747
+ * fix: improve colorization for arrays #3744 [TrejGun](https://github.com/TrejGun)
+ * fix: webpack build #3713
+
 4.3.5 / 2016-01-09
 ==================
  * fix(query): throw when 4th parameter to update not a function #3741 [kasselTrankos](https://github.com/kasselTrankos)
diff --git a/bin/mongoose.js b/bin/mongoose.js
index bdb41766d44..362dc02c446 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -129,7 +129,7 @@ if (typeof window !== 'undefined') {
 }
 
 }).call(this,require("buffer").Buffer)
-},{"./document_provider.js":6,"./error":12,"./schema":26,"./schematype.js":39,"./types":45,"./utils.js":48,"./virtualtype":49,"buffer":52}],3:[function(require,module,exports){
+},{"./document_provider.js":6,"./error":12,"./schema":26,"./schematype.js":39,"./types":45,"./utils.js":48,"./virtualtype":49,"buffer":71}],3:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -236,7 +236,7 @@ Document.prototype.constructor = Document;
 Document.ValidationError = ValidationError;
 module.exports = exports = Document;
 
-},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":46,"./utils":48,"events":56}],4:[function(require,module,exports){
+},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":46,"./utils":48,"events":74}],4:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -969,7 +969,7 @@ Document.prototype.set = function(path, val, type, options) {
             this.set(prefix + key,
               path[key].toObject({ virtuals: false }), constructing);
           } else if ('throw' == strict) {
-            if (pathtype ==='nested') {
+            if (pathtype === 'nested') {
               throw new ObjectExpectedError(key, path[key]);
             } else {
               throw new StrictModeError(key);
@@ -2562,7 +2562,7 @@ Document.prototype.inspect = function(options) {
   var opts = options && 'Object' == utils.getFunctionName(options.constructor) ? options : {};
   opts.minimize = false;
   opts.retainKeyOrder = true;
-  return inspect(this.toObject(opts));
+  return this.toObject(opts);
 };
 
 /**
@@ -2572,7 +2572,9 @@ Document.prototype.inspect = function(options) {
  * @method toString
  */
 
-Document.prototype.toString = Document.prototype.inspect;
+Document.prototype.toString = function() {
+  return inspect(this.inspect());
+};
 
 /**
  * Returns true if the Document stores the same data as doc.
@@ -2687,19 +2689,23 @@ Document.prototype.populate = function populate() {
  *     doc.execPopulate()
  *
  *
- * ####NOTE:
- *
- * Population does not occur unless a `callback` is passed.
- * Passing the same path a second time will overwrite the previous path options.
- * See [Model.populate()](#model_Model.populate) for explaination of options.
- *
  * @see Document.populate #Document_model.populate
  * @api public
  * @return {Promise} promise that resolves to the document when population is done
  */
 
 Document.prototype.execPopulate = function() {
-  return this.populate(function() {});
+  var Promise = PromiseProvider.get();
+  var _this = this;
+  return new Promise.ES6(function(resolve, reject) {
+    _this.populate(function(error, res) {
+      if (error) {
+        reject(error);
+      } else {
+        resolve(res);
+      }
+    });
+  });
 };
 
 /**
@@ -2790,8 +2796,8 @@ Document.prototype.$__fullPath = function(path) {
 Document.ValidationError = ValidationError;
 module.exports = exports = Document;
 
-}).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":39,"./types/array":41,"./types/documentarray":43,"./types/embedded":44,"./utils":48,"FWaASH":58,"buffer":52,"events":56,"hooks-fixed":79,"util":60}],6:[function(require,module,exports){
+}).call(this,require("g5I+bs"),require("buffer").Buffer)
+},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":39,"./types/array":41,"./types/documentarray":43,"./types/embedded":44,"./utils":48,"buffer":71,"events":74,"g5I+bs":92,"hooks-fixed":75,"util":97}],6:[function(require,module,exports){
 'use strict';
 
 /*!
@@ -2833,7 +2839,7 @@ var Binary = require('bson').Binary;
 
 module.exports = exports = Binary;
 
-},{"bson":63}],9:[function(require,module,exports){
+},{"bson":55}],9:[function(require,module,exports){
 /*!
  * Module exports.
  */
@@ -2858,7 +2864,7 @@ var ObjectId = require('bson').ObjectID;
 
 module.exports = exports = ObjectId;
 
-},{"bson":63}],11:[function(require,module,exports){
+},{"bson":55}],11:[function(require,module,exports){
 (function (global){
 /*!
  * ignore
@@ -3708,7 +3714,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject;
 
 module.exports = Promise;
 
-},{"mpromise":83,"util":60}],25:[function(require,module,exports){
+},{"mpromise":82,"util":97}],25:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -3761,7 +3767,7 @@ Promise.reset = function() {
 
 module.exports = Promise;
 
-},{"./ES6Promise":1,"./promise":24,"mquery":88}],26:[function(require,module,exports){
+},{"./ES6Promise":1,"./promise":24,"mquery":87}],26:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -3814,7 +3820,7 @@ var IS_QUERY_HOOK = {
  * - [toObject](/docs/guide.html#toObject) - object - no default
  * - [typeKey](/docs/guide.html#typeKey) - string - defaults to 'type'
  * - [validateBeforeSave](/docs/guide.html#validateBeforeSave) - bool - defaults to `true`
- * - [versionKey](/docs/guide.html#versionKey): bool - defaults to "__v"
+ * - [versionKey](/docs/guide.html#versionKey): string - defaults to "__v"
  *
  * ####Note:
  *
@@ -4175,6 +4181,8 @@ var reserved = Schema.reserved;
 reserved.emit =
 reserved.on =
 reserved.once =
+reserved.listeners =
+reserved.removeListener =
 // document properties and functions
 reserved.collection =
 reserved.db =
@@ -4265,7 +4273,7 @@ Schema.prototype.path = function(path, obj) {
       this.singleNestedPaths[path + '.' + key] =
         this.paths[path].schema.paths[key];
     }
-    for (var key in this.paths[path].schema.singleNestedPaths) {
+    for (key in this.paths[path].schema.singleNestedPaths) {
       this.singleNestedPaths[path + '.' + key] =
         this.paths[path].schema.singleNestedPaths[key];
     }
@@ -5042,7 +5050,7 @@ Schema.Types = MongooseTypes = require('./schema/index');
 exports.ObjectId = MongooseTypes.ObjectId;
 
 }).call(this,require("buffer").Buffer)
-},{"./drivers":11,"./schema/index":33,"./utils":48,"./virtualtype":49,"async":50,"buffer":52,"events":56,"kareem":80}],27:[function(require,module,exports){
+},{"./drivers":11,"./schema/index":33,"./utils":48,"./virtualtype":49,"async":51,"buffer":71,"events":74,"kareem":79}],27:[function(require,module,exports){
 /*!
  * Module dependencies.
  */
@@ -5660,6 +5668,9 @@ SchemaBuffer.prototype.cast = function(value, doc, init) {
 
   var type = typeof value;
   if ('string' == type || 'number' == type || Array.isArray(value)) {
+    if (type === 'number') {
+      value = [value];
+    }
     ret = new MongooseBuffer(value, [this.path, doc]);
     return ret;
   }
@@ -5714,7 +5725,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaBuffer;
 
 }).call(this,require("buffer").Buffer)
-},{"../schematype":39,"../types":45,"../utils":48,"./../document":5,"./operators/bitwise":37,"buffer":52}],30:[function(require,module,exports){
+},{"../schematype":39,"../types":45,"../utils":48,"./../document":5,"./operators/bitwise":37,"buffer":71}],30:[function(require,module,exports){
 /*!
  * Module requirements.
  */
@@ -6077,7 +6088,6 @@ DocumentArray.prototype.constructor = DocumentArray;
  */
 
 DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
-  var _this = this;
   SchemaType.prototype.doValidate.call(this, array, function(err) {
     if (err) {
       return fn(err);
@@ -6820,7 +6830,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaNumber;
 
 }).call(this,require("buffer").Buffer)
-},{"../error":12,"../schematype":39,"../utils":48,"./../document":5,"./operators/bitwise":37,"buffer":52}],36:[function(require,module,exports){
+},{"../error":12,"../schematype":39,"../utils":48,"./../document":5,"./operators/bitwise":37,"buffer":71}],36:[function(require,module,exports){
 (function (Buffer){
 /* eslint no-empty: 1 */
 
@@ -7018,7 +7028,7 @@ function resetId(v) {
 module.exports = ObjectId;
 
 }).call(this,require("buffer").Buffer)
-},{"../schematype":39,"../types/objectid":46,"../utils":48,"./../document":5,"buffer":52}],37:[function(require,module,exports){
+},{"../schematype":39,"../types/objectid":46,"../utils":48,"./../document":5,"buffer":71}],37:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module requirements.
@@ -7059,7 +7069,7 @@ function _castNumber(_this, num) {
 module.exports = handleBitwiseOperator;
 
 }).call(this,require("buffer").Buffer)
-},{"../../error/cast":13,"buffer":52}],38:[function(require,module,exports){
+},{"../../error/cast":13,"buffer":71}],38:[function(require,module,exports){
 (function (Buffer){
 
 /*!
@@ -7557,7 +7567,7 @@ SchemaString.prototype.castForQuery = function($conditional, val) {
 module.exports = SchemaString;
 
 }).call(this,require("buffer").Buffer)
-},{"../error":12,"../schematype":39,"../utils":48,"./../document":5,"buffer":52}],39:[function(require,module,exports){
+},{"../error":12,"../schematype":39,"../utils":48,"./../document":5,"buffer":71}],39:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -8416,7 +8426,7 @@ exports.CastError = CastError;
 exports.ValidatorError = ValidatorError;
 
 }).call(this,require("buffer").Buffer)
-},{"./error":12,"./utils":48,"buffer":52}],40:[function(require,module,exports){
+},{"./error":12,"./utils":48,"buffer":71}],40:[function(require,module,exports){
 
 /*!
  * Module dependencies.
@@ -9363,7 +9373,7 @@ MongooseArray.mixin.remove = MongooseArray.mixin.pull;
 module.exports = exports = MongooseArray;
 
 }).call(this,require("buffer").Buffer)
-},{"../document":5,"../utils":48,"./embedded":44,"./objectid":46,"buffer":52}],42:[function(require,module,exports){
+},{"../document":5,"../utils":48,"./embedded":44,"./objectid":46,"buffer":71}],42:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9636,7 +9646,7 @@ MongooseBuffer.Binary = Binary;
 module.exports = MongooseBuffer;
 
 }).call(this,require("buffer").Buffer)
-},{"../drivers":11,"../utils":48,"buffer":52}],43:[function(require,module,exports){
+},{"../drivers":11,"../utils":48,"buffer":71}],43:[function(require,module,exports){
 (function (Buffer){
 /*!
  * Module dependencies.
@@ -9646,7 +9656,6 @@ var MongooseArray = require('./array'),
     ObjectId = require('./objectid'),
     ObjectIdSchema = require('../schema/objectid'),
     utils = require('../utils'),
-    util = require('util'),
     Document = require('../document');
 
 /**
@@ -9801,14 +9810,7 @@ MongooseDocumentArray.mixin.toObject = function(options) {
  */
 
 MongooseDocumentArray.mixin.inspect = function() {
-  return '[' + Array.prototype.map.call(this, function(doc) {
-    if (doc) {
-      return doc.inspect
-        ? doc.inspect()
-        : util.inspect(doc);
-    }
-    return 'null';
-  }).join('\n') + ']';
+  return Array.prototype.slice.call(this);
 };
 
 /**
@@ -9863,7 +9865,7 @@ MongooseDocumentArray.mixin.notify = function notify(event) {
 module.exports = MongooseDocumentArray;
 
 }).call(this,require("buffer").Buffer)
-},{"../document":5,"../schema/objectid":36,"../utils":48,"./array":41,"./objectid":46,"buffer":52,"util":60}],44:[function(require,module,exports){
+},{"../document":5,"../schema/objectid":36,"../utils":48,"./array":41,"./objectid":46,"buffer":71}],44:[function(require,module,exports){
 /* eslint no-func-assign: 1 */
 
 /*!
@@ -9871,7 +9873,6 @@ module.exports = MongooseDocumentArray;
  */
 
 var Document = require('../document_provider')();
-var inspect = require('util').inspect;
 var PromiseProvider = require('../promise_provider');
 
 /**
@@ -10022,7 +10023,7 @@ EmbeddedDocument.prototype.update = function() {
  */
 
 EmbeddedDocument.prototype.inspect = function() {
-  return inspect(this.toObject());
+  return this.toObject();
 };
 
 /**
@@ -10177,7 +10178,7 @@ EmbeddedDocument.prototype.parentArray = function() {
 
 module.exports = EmbeddedDocument;
 
-},{"../document_provider":6,"../promise_provider":25,"util":60}],45:[function(require,module,exports){
+},{"../document_provider":6,"../promise_provider":25}],45:[function(require,module,exports){
 
 /*!
  * Module exports.
@@ -10298,6 +10299,42 @@ Subdocument.prototype.ownerDocument = function() {
   return this.$__.ownerDocument = parent;
 };
 
+/**
+ * Null-out this subdoc
+ *
+ * @param {Function} [callback] optional callback for compatibility with Document.prototype.remove
+ */
+
+Subdocument.prototype.remove = function(callback) {
+  this.$parent.set(this.$basePath, null);
+  registerRemoveListener(this);
+  if (callback) {
+    callback(null);
+  }
+};
+
+/*!
+ * Registers remove event listeners for triggering
+ * on subdocuments.
+ *
+ * @param {EmbeddedDocument} sub
+ * @api private
+ */
+
+function registerRemoveListener(sub) {
+  var owner = sub.ownerDocument();
+
+  owner.on('save', emitRemove);
+  owner.on('remove', emitRemove);
+
+  function emitRemove() {
+    owner.removeListener('save', emitRemove);
+    owner.removeListener('remove', emitRemove);
+    sub.emit('remove', sub);
+    owner = sub = emitRemove = null;
+  }
+}
+
 },{"../document":5,"../promise_provider":25}],48:[function(require,module,exports){
 (function (process,Buffer){
 /*!
@@ -11098,8 +11135,8 @@ exports.each = function(arr, fn) {
   }
 };
 
-}).call(this,require("FWaASH"),require("buffer").Buffer)
-},{"./document":5,"./types":45,"./types/objectid":46,"FWaASH":58,"buffer":52,"mpath":81,"ms":94,"regexp-clone":95,"sliced":96}],49:[function(require,module,exports){
+}).call(this,require("g5I+bs"),require("buffer").Buffer)
+},{"./document":5,"./types":45,"./types/objectid":46,"buffer":71,"g5I+bs":92,"mpath":80,"ms":91,"regexp-clone":93,"sliced":94}],49:[function(require,module,exports){
 
 /**
  * VirtualType constructor
@@ -11205,635 +11242,619 @@ VirtualType.prototype.applySetters = function(value, scope) {
 module.exports = VirtualType;
 
 },{}],50:[function(require,module,exports){
-(function (process){
-/*!
- * async
- * https://github.com/caolan/async
- *
- * Copyright 2010-2014 Caolan McMahon
- * Released under the MIT license
- */
-/*jshint onevar: false, indent:4 */
-/*global setImmediate: false, setTimeout: false, console: false */
-(function () {
+// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
+//
+// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
+//
+// Originally from narwhal.js (http://narwhaljs.org)
+// Copyright (c) 2009 Thomas Robinson <280north.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the 'Software'), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-    var async = {};
+// when used in node, this will actually load the util module we depend on
+// versus loading the builtin util module as happens otherwise
+// this is a bug in node module loading as far as I am concerned
+var util = require('util/');
 
-    // global on the server, window in the browser
-    var root, previous_async;
+var pSlice = Array.prototype.slice;
+var hasOwn = Object.prototype.hasOwnProperty;
 
-    root = this;
-    if (root != null) {
-      previous_async = root.async;
-    }
+// 1. The assert module provides functions that throw
+// AssertionError's when particular conditions are not met. The
+// assert module must conform to the following interface.
 
-    async.noConflict = function () {
-        root.async = previous_async;
-        return async;
-    };
+var assert = module.exports = ok;
 
-    function only_once(fn) {
-        var called = false;
-        return function() {
-            if (called) throw new Error("Callback was already called.");
-            called = true;
-            fn.apply(root, arguments);
-        }
-    }
+// 2. The AssertionError is defined in assert.
+// new assert.AssertionError({ message: message,
+//                             actual: actual,
+//                             expected: expected })
 
-    //// cross-browser compatiblity functions ////
+assert.AssertionError = function AssertionError(options) {
+  this.name = 'AssertionError';
+  this.actual = options.actual;
+  this.expected = options.expected;
+  this.operator = options.operator;
+  if (options.message) {
+    this.message = options.message;
+    this.generatedMessage = false;
+  } else {
+    this.message = getMessage(this);
+    this.generatedMessage = true;
+  }
+  var stackStartFunction = options.stackStartFunction || fail;
 
-    var _toString = Object.prototype.toString;
+  if (Error.captureStackTrace) {
+    Error.captureStackTrace(this, stackStartFunction);
+  }
+  else {
+    // non v8 browsers so we can have a stacktrace
+    var err = new Error();
+    if (err.stack) {
+      var out = err.stack;
 
-    var _isArray = Array.isArray || function (obj) {
-        return _toString.call(obj) === '[object Array]';
-    };
+      // try to strip useless frames
+      var fn_name = stackStartFunction.name;
+      var idx = out.indexOf('\n' + fn_name);
+      if (idx >= 0) {
+        // once we have located the function frame
+        // we need to strip out everything before it (and its line)
+        var next_line = out.indexOf('\n', idx + 1);
+        out = out.substring(next_line + 1);
+      }
 
-    var _each = function (arr, iterator) {
-        if (arr.forEach) {
-            return arr.forEach(iterator);
-        }
-        for (var i = 0; i < arr.length; i += 1) {
-            iterator(arr[i], i, arr);
-        }
-    };
+      this.stack = out;
+    }
+  }
+};
 
-    var _map = function (arr, iterator) {
-        if (arr.map) {
-            return arr.map(iterator);
-        }
-        var results = [];
-        _each(arr, function (x, i, a) {
-            results.push(iterator(x, i, a));
-        });
-        return results;
-    };
+// assert.AssertionError instanceof Error
+util.inherits(assert.AssertionError, Error);
 
-    var _reduce = function (arr, iterator, memo) {
-        if (arr.reduce) {
-            return arr.reduce(iterator, memo);
-        }
-        _each(arr, function (x, i, a) {
-            memo = iterator(memo, x, i, a);
-        });
-        return memo;
-    };
+function replacer(key, value) {
+  if (util.isUndefined(value)) {
+    return '' + value;
+  }
+  if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {
+    return value.toString();
+  }
+  if (util.isFunction(value) || util.isRegExp(value)) {
+    return value.toString();
+  }
+  return value;
+}
 
-    var _keys = function (obj) {
-        if (Object.keys) {
-            return Object.keys(obj);
-        }
-        var keys = [];
-        for (var k in obj) {
-            if (obj.hasOwnProperty(k)) {
-                keys.push(k);
-            }
-        }
-        return keys;
-    };
+function truncate(s, n) {
+  if (util.isString(s)) {
+    return s.length < n ? s : s.slice(0, n);
+  } else {
+    return s;
+  }
+}
 
-    //// exported async module functions ////
+function getMessage(self) {
+  return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
+         self.operator + ' ' +
+         truncate(JSON.stringify(self.expected, replacer), 128);
+}
 
-    //// nextTick implementation with browser-compatible fallback ////
-    if (typeof process === 'undefined' || !(process.nextTick)) {
-        if (typeof setImmediate === 'function') {
-            async.nextTick = function (fn) {
-                // not a direct alias for IE10 compatibility
-                setImmediate(fn);
-            };
-            async.setImmediate = async.nextTick;
-        }
-        else {
-            async.nextTick = function (fn) {
-                setTimeout(fn, 0);
-            };
-            async.setImmediate = async.nextTick;
-        }
-    }
-    else {
-        async.nextTick = process.nextTick;
-        if (typeof setImmediate !== 'undefined') {
-            async.setImmediate = function (fn) {
-              // not a direct alias for IE10 compatibility
-              setImmediate(fn);
-            };
-        }
-        else {
-            async.setImmediate = async.nextTick;
-        }
-    }
+// At present only the three keys mentioned above are used and
+// understood by the spec. Implementations or sub modules can pass
+// other keys to the AssertionError's constructor - they will be
+// ignored.
 
-    async.each = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
-        }
-        var completed = 0;
-        _each(arr, function (x) {
-            iterator(x, only_once(done) );
-        });
-        function done(err) {
-          if (err) {
-              callback(err);
-              callback = function () {};
-          }
-          else {
-              completed += 1;
-              if (completed >= arr.length) {
-                  callback();
-              }
-          }
-        }
-    };
-    async.forEach = async.each;
+// 3. All of the following functions must throw an AssertionError
+// when a corresponding condition is not met, with a message that
+// may be undefined if not provided.  All assertion methods provide
+// both the actual and expected values to the assertion error for
+// display purposes.
 
-    async.eachSeries = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
-        }
-        var completed = 0;
-        var iterate = function () {
-            iterator(arr[completed], function (err) {
-                if (err) {
-                    callback(err);
-                    callback = function () {};
-                }
-                else {
-                    completed += 1;
-                    if (completed >= arr.length) {
-                        callback();
-                    }
-                    else {
-                        iterate();
-                    }
-                }
-            });
-        };
-        iterate();
-    };
-    async.forEachSeries = async.eachSeries;
+function fail(actual, expected, message, operator, stackStartFunction) {
+  throw new assert.AssertionError({
+    message: message,
+    actual: actual,
+    expected: expected,
+    operator: operator,
+    stackStartFunction: stackStartFunction
+  });
+}
 
-    async.eachLimit = function (arr, limit, iterator, callback) {
-        var fn = _eachLimit(limit);
-        fn.apply(null, [arr, iterator, callback]);
-    };
-    async.forEachLimit = async.eachLimit;
+// EXTENSION! allows for well behaved errors defined elsewhere.
+assert.fail = fail;
 
-    var _eachLimit = function (limit) {
+// 4. Pure assertion tests whether a value is truthy, as determined
+// by !!guard.
+// assert.ok(guard, message_opt);
+// This statement is equivalent to assert.equal(true, !!guard,
+// message_opt);. To test strictly for the value true, use
+// assert.strictEqual(true, guard, message_opt);.
 
-        return function (arr, iterator, callback) {
-            callback = callback || function () {};
-            if (!arr.length || limit <= 0) {
-                return callback();
-            }
-            var completed = 0;
-            var started = 0;
-            var running = 0;
+function ok(value, message) {
+  if (!value) fail(value, true, message, '==', assert.ok);
+}
+assert.ok = ok;
 
-            (function replenish () {
-                if (completed >= arr.length) {
-                    return callback();
-                }
+// 5. The equality assertion tests shallow, coercive equality with
+// ==.
+// assert.equal(actual, expected, message_opt);
 
-                while (running < limit && started < arr.length) {
-                    started += 1;
-                    running += 1;
-                    iterator(arr[started - 1], function (err) {
-                        if (err) {
-                            callback(err);
-                            callback = function () {};
-                        }
-                        else {
-                            completed += 1;
-                            running -= 1;
-                            if (completed >= arr.length) {
-                                callback();
-                            }
-                            else {
-                                replenish();
-                            }
-                        }
-                    });
-                }
-            })();
-        };
-    };
+assert.equal = function equal(actual, expected, message) {
+  if (actual != expected) fail(actual, expected, message, '==', assert.equal);
+};
 
+// 6. The non-equality assertion tests for whether two objects are not equal
+// with != assert.notEqual(actual, expected, message_opt);
 
-    var doParallel = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.each].concat(args));
-        };
-    };
-    var doParallelLimit = function(limit, fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [_eachLimit(limit)].concat(args));
-        };
-    };
-    var doSeries = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.eachSeries].concat(args));
-        };
-    };
+assert.notEqual = function notEqual(actual, expected, message) {
+  if (actual == expected) {
+    fail(actual, expected, message, '!=', assert.notEqual);
+  }
+};
 
+// 7. The equivalence assertion tests a deep equality relation.
+// assert.deepEqual(actual, expected, message_opt);
 
-    var _asyncMap = function (eachfn, arr, iterator, callback) {
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        if (!callback) {
-            eachfn(arr, function (x, callback) {
-                iterator(x.value, function (err) {
-                    callback(err);
-                });
-            });
-        } else {
-            var results = [];
-            eachfn(arr, function (x, callback) {
-                iterator(x.value, function (err, v) {
-                    results[x.index] = v;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
-    async.map = doParallel(_asyncMap);
-    async.mapSeries = doSeries(_asyncMap);
-    async.mapLimit = function (arr, limit, iterator, callback) {
-        return _mapLimit(limit)(arr, iterator, callback);
-    };
+assert.deepEqual = function deepEqual(actual, expected, message) {
+  if (!_deepEqual(actual, expected)) {
+    fail(actual, expected, message, 'deepEqual', assert.deepEqual);
+  }
+};
 
-    var _mapLimit = function(limit) {
-        return doParallelLimit(limit, _asyncMap);
-    };
+function _deepEqual(actual, expected) {
+  // 7.1. All identical values are equivalent, as determined by ===.
+  if (actual === expected) {
+    return true;
 
-    // reduce only has a series version, as doing reduce in parallel won't
-    // work in many situations.
-    async.reduce = function (arr, memo, iterator, callback) {
-        async.eachSeries(arr, function (x, callback) {
-            iterator(memo, x, function (err, v) {
-                memo = v;
-                callback(err);
-            });
-        }, function (err) {
-            callback(err, memo);
-        });
-    };
-    // inject alias
-    async.inject = async.reduce;
-    // foldl alias
-    async.foldl = async.reduce;
+  } else if (util.isBuffer(actual) && util.isBuffer(expected)) {
+    if (actual.length != expected.length) return false;
 
-    async.reduceRight = function (arr, memo, iterator, callback) {
-        var reversed = _map(arr, function (x) {
-            return x;
-        }).reverse();
-        async.reduce(reversed, memo, iterator, callback);
-    };
-    // foldr alias
-    async.foldr = async.reduceRight;
+    for (var i = 0; i < actual.length; i++) {
+      if (actual[i] !== expected[i]) return false;
+    }
 
-    var _filter = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
-                if (v) {
-                    results.push(x);
-                }
-                callback();
-            });
-        }, function (err) {
-            callback(_map(results.sort(function (a, b) {
-                return a.index - b.index;
-            }), function (x) {
-                return x.value;
-            }));
-        });
-    };
-    async.filter = doParallel(_filter);
-    async.filterSeries = doSeries(_filter);
-    // select alias
-    async.select = async.filter;
-    async.selectSeries = async.filterSeries;
+    return true;
 
-    var _reject = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
-                if (!v) {
-                    results.push(x);
-                }
-                callback();
-            });
-        }, function (err) {
-            callback(_map(results.sort(function (a, b) {
-                return a.index - b.index;
-            }), function (x) {
-                return x.value;
-            }));
-        });
-    };
-    async.reject = doParallel(_reject);
-    async.rejectSeries = doSeries(_reject);
+  // 7.2. If the expected value is a Date object, the actual value is
+  // equivalent if it is also a Date object that refers to the same time.
+  } else if (util.isDate(actual) && util.isDate(expected)) {
+    return actual.getTime() === expected.getTime();
 
-    var _detect = function (eachfn, arr, iterator, main_callback) {
-        eachfn(arr, function (x, callback) {
-            iterator(x, function (result) {
-                if (result) {
-                    main_callback(x);
-                    main_callback = function () {};
-                }
-                else {
-                    callback();
-                }
-            });
-        }, function (err) {
-            main_callback();
-        });
-    };
-    async.detect = doParallel(_detect);
-    async.detectSeries = doSeries(_detect);
+  // 7.3 If the expected value is a RegExp object, the actual value is
+  // equivalent if it is also a RegExp object with the same source and
+  // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
+  } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
+    return actual.source === expected.source &&
+           actual.global === expected.global &&
+           actual.multiline === expected.multiline &&
+           actual.lastIndex === expected.lastIndex &&
+           actual.ignoreCase === expected.ignoreCase;
 
-    async.some = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (v) {
-                    main_callback(true);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(false);
-        });
-    };
-    // any alias
-    async.any = async.some;
+  // 7.4. Other pairs that do not both pass typeof value == 'object',
+  // equivalence is determined by ==.
+  } else if (!util.isObject(actual) && !util.isObject(expected)) {
+    return actual == expected;
 
-    async.every = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (!v) {
-                    main_callback(false);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(true);
-        });
-    };
-    // all alias
-    async.all = async.every;
+  // 7.5 For all other Object pairs, including Array objects, equivalence is
+  // determined by having the same number of owned properties (as verified
+  // with Object.prototype.hasOwnProperty.call), the same set of keys
+  // (although not necessarily the same order), equivalent values for every
+  // corresponding key, and an identical 'prototype' property. Note: this
+  // accounts for both named and indexed properties on Arrays.
+  } else {
+    return objEquiv(actual, expected);
+  }
+}
 
-    async.sortBy = function (arr, iterator, callback) {
-        async.map(arr, function (x, callback) {
-            iterator(x, function (err, criteria) {
-                if (err) {
-                    callback(err);
-                }
-                else {
-                    callback(null, {value: x, criteria: criteria});
-                }
-            });
-        }, function (err, results) {
-            if (err) {
-                return callback(err);
-            }
-            else {
-                var fn = function (left, right) {
-                    var a = left.criteria, b = right.criteria;
-                    return a < b ? -1 : a > b ? 1 : 0;
-                };
-                callback(null, _map(results.sort(fn), function (x) {
-                    return x.value;
-                }));
-            }
-        });
-    };
+function isArguments(object) {
+  return Object.prototype.toString.call(object) == '[object Arguments]';
+}
 
-    async.auto = function (tasks, callback) {
-        callback = callback || function () {};
-        var keys = _keys(tasks);
-        var remainingTasks = keys.length
-        if (!remainingTasks) {
-            return callback();
-        }
+function objEquiv(a, b) {
+  if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
+    return false;
+  // an identical 'prototype' property.
+  if (a.prototype !== b.prototype) return false;
+  //~~~I've managed to break Object.keys through screwy arguments passing.
+  //   Converting to array solves the problem.
+  if (isArguments(a)) {
+    if (!isArguments(b)) {
+      return false;
+    }
+    a = pSlice.call(a);
+    b = pSlice.call(b);
+    return _deepEqual(a, b);
+  }
+  try {
+    var ka = objectKeys(a),
+        kb = objectKeys(b),
+        key, i;
+  } catch (e) {//happens when one is a string literal and the other isn't
+    return false;
+  }
+  // having the same number of owned properties (keys incorporates
+  // hasOwnProperty)
+  if (ka.length != kb.length)
+    return false;
+  //the same set of keys (although not necessarily the same order),
+  ka.sort();
+  kb.sort();
+  //~~~cheap key test
+  for (i = ka.length - 1; i >= 0; i--) {
+    if (ka[i] != kb[i])
+      return false;
+  }
+  //equivalent values for every corresponding key, and
+  //~~~possibly expensive deep test
+  for (i = ka.length - 1; i >= 0; i--) {
+    key = ka[i];
+    if (!_deepEqual(a[key], b[key])) return false;
+  }
+  return true;
+}
 
-        var results = {};
+// 8. The non-equivalence assertion tests for any deep inequality.
+// assert.notDeepEqual(actual, expected, message_opt);
 
-        var listeners = [];
-        var addListener = function (fn) {
-            listeners.unshift(fn);
-        };
-        var removeListener = function (fn) {
-            for (var i = 0; i < listeners.length; i += 1) {
-                if (listeners[i] === fn) {
-                    listeners.splice(i, 1);
-                    return;
-                }
-            }
-        };
-        var taskComplete = function () {
-            remainingTasks--
-            _each(listeners.slice(0), function (fn) {
-                fn();
-            });
-        };
+assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
+  if (_deepEqual(actual, expected)) {
+    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
+  }
+};
 
-        addListener(function () {
-            if (!remainingTasks) {
-                var theCallback = callback;
-                // prevent final callback from calling itself if it errors
-                callback = function () {};
+// 9. The strict equality assertion tests strict equality, as determined by ===.
+// assert.strictEqual(actual, expected, message_opt);
 
-                theCallback(null, results);
-            }
-        });
+assert.strictEqual = function strictEqual(actual, expected, message) {
+  if (actual !== expected) {
+    fail(actual, expected, message, '===', assert.strictEqual);
+  }
+};
 
-        _each(keys, function (k) {
-            var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
-            var taskCallback = function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
-                if (args.length <= 1) {
-                    args = args[0];
-                }
-                if (err) {
-                    var safeResults = {};
-                    _each(_keys(results), function(rkey) {
-                        safeResults[rkey] = results[rkey];
-                    });
-                    safeResults[k] = args;
-                    callback(err, safeResults);
-                    // stop subsequent errors hitting callback multiple times
-                    callback = function () {};
-                }
-                else {
-                    results[k] = args;
-                    async.setImmediate(taskComplete);
-                }
-            };
-            var requires = task.slice(0, Math.abs(task.length - 1)) || [];
-            var ready = function () {
-                return _reduce(requires, function (a, x) {
-                    return (a && results.hasOwnProperty(x));
-                }, true) && !results.hasOwnProperty(k);
-            };
-            if (ready()) {
-                task[task.length - 1](taskCallback, results);
-            }
-            else {
-                var listener = function () {
-                    if (ready()) {
-                        removeListener(listener);
-                        task[task.length - 1](taskCallback, results);
-                    }
-                };
-                addListener(listener);
-            }
-        });
-    };
+// 10. The strict non-equality assertion tests for strict inequality, as
+// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);
 
-    async.retry = function(times, task, callback) {
-        var DEFAULT_TIMES = 5;
-        var attempts = [];
-        // Use defaults if times not passed
-        if (typeof times === 'function') {
-            callback = task;
-            task = times;
-            times = DEFAULT_TIMES;
-        }
-        // Make sure times is a number
-        times = parseInt(times, 10) || DEFAULT_TIMES;
-        var wrappedTask = function(wrappedCallback, wrappedResults) {
-            var retryAttempt = function(task, finalAttempt) {
-                return function(seriesCallback) {
-                    task(function(err, result){
-                        seriesCallback(!err || finalAttempt, {err: err, result: result});
-                    }, wrappedResults);
-                };
-            };
-            while (times) {
-                attempts.push(retryAttempt(task, !(times-=1)));
+assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
+  if (actual === expected) {
+    fail(actual, expected, message, '!==', assert.notStrictEqual);
+  }
+};
+
+function expectedException(actual, expected) {
+  if (!actual || !expected) {
+    return false;
+  }
+
+  if (Object.prototype.toString.call(expected) == '[object RegExp]') {
+    return expected.test(actual);
+  } else if (actual instanceof expected) {
+    return true;
+  } else if (expected.call({}, actual) === true) {
+    return true;
+  }
+
+  return false;
+}
+
+function _throws(shouldThrow, block, expected, message) {
+  var actual;
+
+  if (util.isString(expected)) {
+    message = expected;
+    expected = null;
+  }
+
+  try {
+    block();
+  } catch (e) {
+    actual = e;
+  }
+
+  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
+            (message ? ' ' + message : '.');
+
+  if (shouldThrow && !actual) {
+    fail(actual, expected, 'Missing expected exception' + message);
+  }
+
+  if (!shouldThrow && expectedException(actual, expected)) {
+    fail(actual, expected, 'Got unwanted exception' + message);
+  }
+
+  if ((shouldThrow && actual && expected &&
+      !expectedException(actual, expected)) || (!shouldThrow && actual)) {
+    throw actual;
+  }
+}
+
+// 11. Expected to throw an error:
+// assert.throws(block, Error_opt, message_opt);
+
+assert.throws = function(block, /*optional*/error, /*optional*/message) {
+  _throws.apply(this, [true].concat(pSlice.call(arguments)));
+};
+
+// EXTENSION! This is annoying to write outside this module.
+assert.doesNotThrow = function(block, /*optional*/message) {
+  _throws.apply(this, [false].concat(pSlice.call(arguments)));
+};
+
+assert.ifError = function(err) { if (err) {throw err;}};
+
+var objectKeys = Object.keys || function (obj) {
+  var keys = [];
+  for (var key in obj) {
+    if (hasOwn.call(obj, key)) keys.push(key);
+  }
+  return keys;
+};
+
+},{"util/":97}],51:[function(require,module,exports){
+(function (process){
+/*!
+ * async
+ * https://github.com/caolan/async
+ *
+ * Copyright 2010-2014 Caolan McMahon
+ * Released under the MIT license
+ */
+/*jshint onevar: false, indent:4 */
+/*global setImmediate: false, setTimeout: false, console: false */
+(function () {
+
+    var async = {};
+
+    // global on the server, window in the browser
+    var root, previous_async;
+
+    root = this;
+    if (root != null) {
+      previous_async = root.async;
+    }
+
+    async.noConflict = function () {
+        root.async = previous_async;
+        return async;
+    };
+
+    function only_once(fn) {
+        var called = false;
+        return function() {
+            if (called) throw new Error("Callback was already called.");
+            called = true;
+            fn.apply(root, arguments);
+        }
+    }
+
+    //// cross-browser compatiblity functions ////
+
+    var _toString = Object.prototype.toString;
+
+    var _isArray = Array.isArray || function (obj) {
+        return _toString.call(obj) === '[object Array]';
+    };
+
+    var _each = function (arr, iterator) {
+        if (arr.forEach) {
+            return arr.forEach(iterator);
+        }
+        for (var i = 0; i < arr.length; i += 1) {
+            iterator(arr[i], i, arr);
+        }
+    };
+
+    var _map = function (arr, iterator) {
+        if (arr.map) {
+            return arr.map(iterator);
+        }
+        var results = [];
+        _each(arr, function (x, i, a) {
+            results.push(iterator(x, i, a));
+        });
+        return results;
+    };
+
+    var _reduce = function (arr, iterator, memo) {
+        if (arr.reduce) {
+            return arr.reduce(iterator, memo);
+        }
+        _each(arr, function (x, i, a) {
+            memo = iterator(memo, x, i, a);
+        });
+        return memo;
+    };
+
+    var _keys = function (obj) {
+        if (Object.keys) {
+            return Object.keys(obj);
+        }
+        var keys = [];
+        for (var k in obj) {
+            if (obj.hasOwnProperty(k)) {
+                keys.push(k);
             }
-            async.series(attempts, function(done, data){
-                data = data[data.length - 1];
-                (wrappedCallback || callback)(data.err, data.result);
-            });
         }
-        // If a callback is passed, run this as a controll flow
-        return callback ? wrappedTask() : wrappedTask
+        return keys;
     };
 
-    async.waterfall = function (tasks, callback) {
+    //// exported async module functions ////
+
+    //// nextTick implementation with browser-compatible fallback ////
+    if (typeof process === 'undefined' || !(process.nextTick)) {
+        if (typeof setImmediate === 'function') {
+            async.nextTick = function (fn) {
+                // not a direct alias for IE10 compatibility
+                setImmediate(fn);
+            };
+            async.setImmediate = async.nextTick;
+        }
+        else {
+            async.nextTick = function (fn) {
+                setTimeout(fn, 0);
+            };
+            async.setImmediate = async.nextTick;
+        }
+    }
+    else {
+        async.nextTick = process.nextTick;
+        if (typeof setImmediate !== 'undefined') {
+            async.setImmediate = function (fn) {
+              // not a direct alias for IE10 compatibility
+              setImmediate(fn);
+            };
+        }
+        else {
+            async.setImmediate = async.nextTick;
+        }
+    }
+
+    async.each = function (arr, iterator, callback) {
         callback = callback || function () {};
-        if (!_isArray(tasks)) {
-          var err = new Error('First argument to waterfall must be an array of functions');
-          return callback(err);
+        if (!arr.length) {
+            return callback();
         }
-        if (!tasks.length) {
+        var completed = 0;
+        _each(arr, function (x) {
+            iterator(x, only_once(done) );
+        });
+        function done(err) {
+          if (err) {
+              callback(err);
+              callback = function () {};
+          }
+          else {
+              completed += 1;
+              if (completed >= arr.length) {
+                  callback();
+              }
+          }
+        }
+    };
+    async.forEach = async.each;
+
+    async.eachSeries = function (arr, iterator, callback) {
+        callback = callback || function () {};
+        if (!arr.length) {
             return callback();
         }
-        var wrapIterator = function (iterator) {
-            return function (err) {
+        var completed = 0;
+        var iterate = function () {
+            iterator(arr[completed], function (err) {
                 if (err) {
-                    callback.apply(null, arguments);
+                    callback(err);
                     callback = function () {};
                 }
                 else {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    var next = iterator.next();
-                    if (next) {
-                        args.push(wrapIterator(next));
+                    completed += 1;
+                    if (completed >= arr.length) {
+                        callback();
                     }
                     else {
-                        args.push(callback);
+                        iterate();
                     }
-                    async.setImmediate(function () {
-                        iterator.apply(null, args);
-                    });
                 }
-            };
+            });
         };
-        wrapIterator(async.iterator(tasks))();
+        iterate();
     };
+    async.forEachSeries = async.eachSeries;
 
-    var _parallel = function(eachfn, tasks, callback) {
-        callback = callback || function () {};
-        if (_isArray(tasks)) {
-            eachfn.map(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
+    async.eachLimit = function (arr, limit, iterator, callback) {
+        var fn = _eachLimit(limit);
+        fn.apply(null, [arr, iterator, callback]);
+    };
+    async.forEachLimit = async.eachLimit;
+
+    var _eachLimit = function (limit) {
+
+        return function (arr, iterator, callback) {
+            callback = callback || function () {};
+            if (!arr.length || limit <= 0) {
+                return callback();
+            }
+            var completed = 0;
+            var started = 0;
+            var running = 0;
+
+            (function replenish () {
+                if (completed >= arr.length) {
+                    return callback();
+                }
+
+                while (running < limit && started < arr.length) {
+                    started += 1;
+                    running += 1;
+                    iterator(arr[started - 1], function (err) {
+                        if (err) {
+                            callback(err);
+                            callback = function () {};
+                        }
+                        else {
+                            completed += 1;
+                            running -= 1;
+                            if (completed >= arr.length) {
+                                callback();
+                            }
+                            else {
+                                replenish();
+                            }
                         }
-                        callback.call(null, err, args);
                     });
                 }
-            }, callback);
-        }
-        else {
-            var results = {};
-            eachfn.each(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
+            })();
+        };
     };
 
-    async.parallel = function (tasks, callback) {
-        _parallel({ map: async.map, each: async.each }, tasks, callback);
-    };
 
-    async.parallelLimit = function(tasks, limit, callback) {
-        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
+    var doParallel = function (fn) {
+        return function () {
+            var args = Array.prototype.slice.call(arguments);
+            return fn.apply(null, [async.each].concat(args));
+        };
+    };
+    var doParallelLimit = function(limit, fn) {
+        return function () {
+            var args = Array.prototype.slice.call(arguments);
+            return fn.apply(null, [_eachLimit(limit)].concat(args));
+        };
+    };
+    var doSeries = function (fn) {
+        return function () {
+            var args = Array.prototype.slice.call(arguments);
+            return fn.apply(null, [async.eachSeries].concat(args));
+        };
     };
 
-    async.series = function (tasks, callback) {
-        callback = callback || function () {};
-        if (_isArray(tasks)) {
-            async.mapSeries(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
-                        }
-                        callback.call(null, err, args);
-                    });
-                }
-            }, callback);
-        }
-        else {
-            var results = {};
-            async.eachSeries(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
+
+    var _asyncMap = function (eachfn, arr, iterator, callback) {
+        arr = _map(arr, function (x, i) {
+            return {index: i, value: x};
+        });
+        if (!callback) {
+            eachfn(arr, function (x, callback) {
+                iterator(x.value, function (err) {
+                    callback(err);
+                });
+            });
+        } else {
+            var results = [];
+            eachfn(arr, function (x, callback) {
+                iterator(x.value, function (err, v) {
+                    results[x.index] = v;
                     callback(err);
                 });
             }, function (err) {
@@ -11841,4043 +11862,4247 @@ module.exports = VirtualType;
             });
         }
     };
-
-    async.iterator = function (tasks) {
-        var makeCallback = function (index) {
-            var fn = function () {
-                if (tasks.length) {
-                    tasks[index].apply(null, arguments);
-                }
-                return fn.next();
-            };
-            fn.next = function () {
-                return (index < tasks.length - 1) ? makeCallback(index + 1): null;
-            };
-            return fn;
-        };
-        return makeCallback(0);
+    async.map = doParallel(_asyncMap);
+    async.mapSeries = doSeries(_asyncMap);
+    async.mapLimit = function (arr, limit, iterator, callback) {
+        return _mapLimit(limit)(arr, iterator, callback);
     };
 
-    async.apply = function (fn) {
-        var args = Array.prototype.slice.call(arguments, 1);
-        return function () {
-            return fn.apply(
-                null, args.concat(Array.prototype.slice.call(arguments))
-            );
-        };
+    var _mapLimit = function(limit) {
+        return doParallelLimit(limit, _asyncMap);
     };
 
-    var _concat = function (eachfn, arr, fn, callback) {
-        var r = [];
-        eachfn(arr, function (x, cb) {
-            fn(x, function (err, y) {
-                r = r.concat(y || []);
-                cb(err);
+    // reduce only has a series version, as doing reduce in parallel won't
+    // work in many situations.
+    async.reduce = function (arr, memo, iterator, callback) {
+        async.eachSeries(arr, function (x, callback) {
+            iterator(memo, x, function (err, v) {
+                memo = v;
+                callback(err);
             });
         }, function (err) {
-            callback(err, r);
+            callback(err, memo);
         });
     };
-    async.concat = doParallel(_concat);
-    async.concatSeries = doSeries(_concat);
+    // inject alias
+    async.inject = async.reduce;
+    // foldl alias
+    async.foldl = async.reduce;
 
-    async.whilst = function (test, iterator, callback) {
-        if (test()) {
-            iterator(function (err) {
-                if (err) {
-                    return callback(err);
-                }
-                async.whilst(test, iterator, callback);
-            });
-        }
-        else {
-            callback();
-        }
+    async.reduceRight = function (arr, memo, iterator, callback) {
+        var reversed = _map(arr, function (x) {
+            return x;
+        }).reverse();
+        async.reduce(reversed, memo, iterator, callback);
     };
+    // foldr alias
+    async.foldr = async.reduceRight;
 
-    async.doWhilst = function (iterator, test, callback) {
-        iterator(function (err) {
-            if (err) {
-                return callback(err);
-            }
-            var args = Array.prototype.slice.call(arguments, 1);
-            if (test.apply(null, args)) {
-                async.doWhilst(iterator, test, callback);
-            }
-            else {
+    var _filter = function (eachfn, arr, iterator, callback) {
+        var results = [];
+        arr = _map(arr, function (x, i) {
+            return {index: i, value: x};
+        });
+        eachfn(arr, function (x, callback) {
+            iterator(x.value, function (v) {
+                if (v) {
+                    results.push(x);
+                }
                 callback();
-            }
+            });
+        }, function (err) {
+            callback(_map(results.sort(function (a, b) {
+                return a.index - b.index;
+            }), function (x) {
+                return x.value;
+            }));
         });
     };
+    async.filter = doParallel(_filter);
+    async.filterSeries = doSeries(_filter);
+    // select alias
+    async.select = async.filter;
+    async.selectSeries = async.filterSeries;
 
-    async.until = function (test, iterator, callback) {
-        if (!test()) {
-            iterator(function (err) {
-                if (err) {
-                    return callback(err);
+    var _reject = function (eachfn, arr, iterator, callback) {
+        var results = [];
+        arr = _map(arr, function (x, i) {
+            return {index: i, value: x};
+        });
+        eachfn(arr, function (x, callback) {
+            iterator(x.value, function (v) {
+                if (!v) {
+                    results.push(x);
                 }
-                async.until(test, iterator, callback);
+                callback();
             });
-        }
-        else {
-            callback();
-        }
+        }, function (err) {
+            callback(_map(results.sort(function (a, b) {
+                return a.index - b.index;
+            }), function (x) {
+                return x.value;
+            }));
+        });
     };
+    async.reject = doParallel(_reject);
+    async.rejectSeries = doSeries(_reject);
 
-    async.doUntil = function (iterator, test, callback) {
-        iterator(function (err) {
+    var _detect = function (eachfn, arr, iterator, main_callback) {
+        eachfn(arr, function (x, callback) {
+            iterator(x, function (result) {
+                if (result) {
+                    main_callback(x);
+                    main_callback = function () {};
+                }
+                else {
+                    callback();
+                }
+            });
+        }, function (err) {
+            main_callback();
+        });
+    };
+    async.detect = doParallel(_detect);
+    async.detectSeries = doSeries(_detect);
+
+    async.some = function (arr, iterator, main_callback) {
+        async.each(arr, function (x, callback) {
+            iterator(x, function (v) {
+                if (v) {
+                    main_callback(true);
+                    main_callback = function () {};
+                }
+                callback();
+            });
+        }, function (err) {
+            main_callback(false);
+        });
+    };
+    // any alias
+    async.any = async.some;
+
+    async.every = function (arr, iterator, main_callback) {
+        async.each(arr, function (x, callback) {
+            iterator(x, function (v) {
+                if (!v) {
+                    main_callback(false);
+                    main_callback = function () {};
+                }
+                callback();
+            });
+        }, function (err) {
+            main_callback(true);
+        });
+    };
+    // all alias
+    async.all = async.every;
+
+    async.sortBy = function (arr, iterator, callback) {
+        async.map(arr, function (x, callback) {
+            iterator(x, function (err, criteria) {
+                if (err) {
+                    callback(err);
+                }
+                else {
+                    callback(null, {value: x, criteria: criteria});
+                }
+            });
+        }, function (err, results) {
             if (err) {
                 return callback(err);
             }
-            var args = Array.prototype.slice.call(arguments, 1);
-            if (!test.apply(null, args)) {
-                async.doUntil(iterator, test, callback);
-            }
             else {
-                callback();
+                var fn = function (left, right) {
+                    var a = left.criteria, b = right.criteria;
+                    return a < b ? -1 : a > b ? 1 : 0;
+                };
+                callback(null, _map(results.sort(fn), function (x) {
+                    return x.value;
+                }));
             }
         });
     };
 
-    async.queue = function (worker, concurrency) {
-        if (concurrency === undefined) {
-            concurrency = 1;
+    async.auto = function (tasks, callback) {
+        callback = callback || function () {};
+        var keys = _keys(tasks);
+        var remainingTasks = keys.length
+        if (!remainingTasks) {
+            return callback();
         }
-        function _insert(q, data, pos, callback) {
-          if (!q.started){
-            q.started = true;
-          }
-          if (!_isArray(data)) {
-              data = [data];
-          }
-          if(data.length == 0) {
-             // call drain immediately if there are no tasks
-             return async.setImmediate(function() {
-                 if (q.drain) {
-                     q.drain();
-                 }
-             });
-          }
-          _each(data, function(task) {
-              var item = {
-                  data: task,
-                  callback: typeof callback === 'function' ? callback : null
-              };
-
-              if (pos) {
-                q.tasks.unshift(item);
-              } else {
-                q.tasks.push(item);
-              }
 
-              if (q.saturated && q.tasks.length === q.concurrency) {
-                  q.saturated();
-              }
-              async.setImmediate(q.process);
-          });
-        }
+        var results = {};
 
-        var workers = 0;
-        var q = {
-            tasks: [],
-            concurrency: concurrency,
-            saturated: null,
-            empty: null,
-            drain: null,
-            started: false,
-            paused: false,
-            push: function (data, callback) {
-              _insert(q, data, false, callback);
-            },
-            kill: function () {
-              q.drain = null;
-              q.tasks = [];
-            },
-            unshift: function (data, callback) {
-              _insert(q, data, true, callback);
-            },
-            process: function () {
-                if (!q.paused && workers < q.concurrency && q.tasks.length) {
-                    var task = q.tasks.shift();
-                    if (q.empty && q.tasks.length === 0) {
-                        q.empty();
-                    }
-                    workers += 1;
-                    var next = function () {
-                        workers -= 1;
-                        if (task.callback) {
-                            task.callback.apply(task, arguments);
-                        }
-                        if (q.drain && q.tasks.length + workers === 0) {
-                            q.drain();
-                        }
-                        q.process();
-                    };
-                    var cb = only_once(next);
-                    worker(task.data, cb);
+        var listeners = [];
+        var addListener = function (fn) {
+            listeners.unshift(fn);
+        };
+        var removeListener = function (fn) {
+            for (var i = 0; i < listeners.length; i += 1) {
+                if (listeners[i] === fn) {
+                    listeners.splice(i, 1);
+                    return;
                 }
-            },
-            length: function () {
-                return q.tasks.length;
-            },
-            running: function () {
-                return workers;
-            },
-            idle: function() {
-                return q.tasks.length + workers === 0;
-            },
-            pause: function () {
-                if (q.paused === true) { return; }
-                q.paused = true;
-                q.process();
-            },
-            resume: function () {
-                if (q.paused === false) { return; }
-                q.paused = false;
-                q.process();
             }
         };
-        return q;
-    };
-    
-    async.priorityQueue = function (worker, concurrency) {
-        
-        function _compareTasks(a, b){
-          return a.priority - b.priority;
+        var taskComplete = function () {
+            remainingTasks--
+            _each(listeners.slice(0), function (fn) {
+                fn();
+            });
         };
-        
-        function _binarySearch(sequence, item, compare) {
-          var beg = -1,
-              end = sequence.length - 1;
-          while (beg < end) {
-            var mid = beg + ((end - beg + 1) >>> 1);
-            if (compare(item, sequence[mid]) >= 0) {
-              beg = mid;
-            } else {
-              end = mid - 1;
+
+        addListener(function () {
+            if (!remainingTasks) {
+                var theCallback = callback;
+                // prevent final callback from calling itself if it errors
+                callback = function () {};
+
+                theCallback(null, results);
             }
-          }
-          return beg;
-        }
-        
-        function _insert(q, data, priority, callback) {
-          if (!q.started){
-            q.started = true;
-          }
-          if (!_isArray(data)) {
-              data = [data];
-          }
-          if(data.length == 0) {
-             // call drain immediately if there are no tasks
-             return async.setImmediate(function() {
-                 if (q.drain) {
-                     q.drain();
-                 }
-             });
-          }
-          _each(data, function(task) {
-              var item = {
-                  data: task,
-                  priority: priority,
-                  callback: typeof callback === 'function' ? callback : null
-              };
-              
-              q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
+        });
 
-              if (q.saturated && q.tasks.length === q.concurrency) {
-                  q.saturated();
-              }
-              async.setImmediate(q.process);
-          });
-        }
-        
-        // Start with a normal queue
-        var q = async.queue(worker, concurrency);
-        
-        // Override push to accept second parameter representing priority
-        q.push = function (data, priority, callback) {
-          _insert(q, data, priority, callback);
-        };
-        
-        // Remove unshift function
-        delete q.unshift;
-
-        return q;
-    };
-
-    async.cargo = function (worker, payload) {
-        var working     = false,
-            tasks       = [];
-
-        var cargo = {
-            tasks: tasks,
-            payload: payload,
-            saturated: null,
-            empty: null,
-            drain: null,
-            drained: true,
-            push: function (data, callback) {
-                if (!_isArray(data)) {
-                    data = [data];
+        _each(keys, function (k) {
+            var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
+            var taskCallback = function (err) {
+                var args = Array.prototype.slice.call(arguments, 1);
+                if (args.length <= 1) {
+                    args = args[0];
                 }
-                _each(data, function(task) {
-                    tasks.push({
-                        data: task,
-                        callback: typeof callback === 'function' ? callback : null
+                if (err) {
+                    var safeResults = {};
+                    _each(_keys(results), function(rkey) {
+                        safeResults[rkey] = results[rkey];
                     });
-                    cargo.drained = false;
-                    if (cargo.saturated && tasks.length === payload) {
-                        cargo.saturated();
-                    }
-                });
-                async.setImmediate(cargo.process);
-            },
-            process: function process() {
-                if (working) return;
-                if (tasks.length === 0) {
-                    if(cargo.drain && !cargo.drained) cargo.drain();
-                    cargo.drained = true;
-                    return;
+                    safeResults[k] = args;
+                    callback(err, safeResults);
+                    // stop subsequent errors hitting callback multiple times
+                    callback = function () {};
                 }
-
-                var ts = typeof payload === 'number'
-                            ? tasks.splice(0, payload)
-                            : tasks.splice(0, tasks.length);
-
-                var ds = _map(ts, function (task) {
-                    return task.data;
-                });
-
-                if(cargo.empty) cargo.empty();
-                working = true;
-                worker(ds, function () {
-                    working = false;
-
-                    var args = arguments;
-                    _each(ts, function (data) {
-                        if (data.callback) {
-                            data.callback.apply(null, args);
-                        }
-                    });
-
-                    process();
-                });
-            },
-            length: function () {
-                return tasks.length;
-            },
-            running: function () {
-                return working;
-            }
-        };
-        return cargo;
-    };
-
-    var _console_fn = function (name) {
-        return function (fn) {
-            var args = Array.prototype.slice.call(arguments, 1);
-            fn.apply(null, args.concat([function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
-                if (typeof console !== 'undefined') {
-                    if (err) {
-                        if (console.error) {
-                            console.error(err);
-                        }
-                    }
-                    else if (console[name]) {
-                        _each(args, function (x) {
-                            console[name](x);
-                        });
-                    }
+                else {
+                    results[k] = args;
+                    async.setImmediate(taskComplete);
                 }
-            }]));
-        };
-    };
-    async.log = _console_fn('log');
-    async.dir = _console_fn('dir');
-    /*async.info = _console_fn('info');
-    async.warn = _console_fn('warn');
-    async.error = _console_fn('error');*/
-
-    async.memoize = function (fn, hasher) {
-        var memo = {};
-        var queues = {};
-        hasher = hasher || function (x) {
-            return x;
-        };
-        var memoized = function () {
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            var key = hasher.apply(null, args);
-            if (key in memo) {
-                async.nextTick(function () {
-                    callback.apply(null, memo[key]);
-                });
-            }
-            else if (key in queues) {
-                queues[key].push(callback);
+            };
+            var requires = task.slice(0, Math.abs(task.length - 1)) || [];
+            var ready = function () {
+                return _reduce(requires, function (a, x) {
+                    return (a && results.hasOwnProperty(x));
+                }, true) && !results.hasOwnProperty(k);
+            };
+            if (ready()) {
+                task[task.length - 1](taskCallback, results);
             }
             else {
-                queues[key] = [callback];
-                fn.apply(null, args.concat([function () {
-                    memo[key] = arguments;
-                    var q = queues[key];
-                    delete queues[key];
-                    for (var i = 0, l = q.length; i < l; i++) {
-                      q[i].apply(null, arguments);
+                var listener = function () {
+                    if (ready()) {
+                        removeListener(listener);
+                        task[task.length - 1](taskCallback, results);
                     }
-                }]));
+                };
+                addListener(listener);
             }
-        };
-        memoized.memo = memo;
-        memoized.unmemoized = fn;
-        return memoized;
-    };
-
-    async.unmemoize = function (fn) {
-      return function () {
-        return (fn.unmemoized || fn).apply(null, arguments);
-      };
+        });
     };
 
-    async.times = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
+    async.retry = function(times, task, callback) {
+        var DEFAULT_TIMES = 5;
+        var attempts = [];
+        // Use defaults if times not passed
+        if (typeof times === 'function') {
+            callback = task;
+            task = times;
+            times = DEFAULT_TIMES;
         }
-        return async.map(counter, iterator, callback);
-    };
-
-    async.timesSeries = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
+        // Make sure times is a number
+        times = parseInt(times, 10) || DEFAULT_TIMES;
+        var wrappedTask = function(wrappedCallback, wrappedResults) {
+            var retryAttempt = function(task, finalAttempt) {
+                return function(seriesCallback) {
+                    task(function(err, result){
+                        seriesCallback(!err || finalAttempt, {err: err, result: result});
+                    }, wrappedResults);
+                };
+            };
+            while (times) {
+                attempts.push(retryAttempt(task, !(times-=1)));
+            }
+            async.series(attempts, function(done, data){
+                data = data[data.length - 1];
+                (wrappedCallback || callback)(data.err, data.result);
+            });
         }
-        return async.mapSeries(counter, iterator, callback);
+        // If a callback is passed, run this as a controll flow
+        return callback ? wrappedTask() : wrappedTask
     };
 
-    async.seq = function (/* functions... */) {
-        var fns = arguments;
-        return function () {
-            var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            async.reduce(fns, args, function (newargs, fn, cb) {
-                fn.apply(that, newargs.concat([function () {
-                    var err = arguments[0];
-                    var nextargs = Array.prototype.slice.call(arguments, 1);
-                    cb(err, nextargs);
-                }]))
-            },
-            function (err, results) {
-                callback.apply(that, [err].concat(results));
-            });
+    async.waterfall = function (tasks, callback) {
+        callback = callback || function () {};
+        if (!_isArray(tasks)) {
+          var err = new Error('First argument to waterfall must be an array of functions');
+          return callback(err);
+        }
+        if (!tasks.length) {
+            return callback();
+        }
+        var wrapIterator = function (iterator) {
+            return function (err) {
+                if (err) {
+                    callback.apply(null, arguments);
+                    callback = function () {};
+                }
+                else {
+                    var args = Array.prototype.slice.call(arguments, 1);
+                    var next = iterator.next();
+                    if (next) {
+                        args.push(wrapIterator(next));
+                    }
+                    else {
+                        args.push(callback);
+                    }
+                    async.setImmediate(function () {
+                        iterator.apply(null, args);
+                    });
+                }
+            };
         };
+        wrapIterator(async.iterator(tasks))();
     };
 
-    async.compose = function (/* functions... */) {
-      return async.seq.apply(null, Array.prototype.reverse.call(arguments));
-    };
-
-    var _applyEach = function (eachfn, fns /*args...*/) {
-        var go = function () {
-            var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            return eachfn(fns, function (fn, cb) {
-                fn.apply(that, args.concat([cb]));
-            },
-            callback);
-        };
-        if (arguments.length > 2) {
-            var args = Array.prototype.slice.call(arguments, 2);
-            return go.apply(this, args);
-        }
-        else {
-            return go;
-        }
-    };
-    async.applyEach = doParallel(_applyEach);
-    async.applyEachSeries = doSeries(_applyEach);
-
-    async.forever = function (fn, callback) {
-        function next(err) {
-            if (err) {
-                if (callback) {
-                    return callback(err);
+    var _parallel = function(eachfn, tasks, callback) {
+        callback = callback || function () {};
+        if (_isArray(tasks)) {
+            eachfn.map(tasks, function (fn, callback) {
+                if (fn) {
+                    fn(function (err) {
+                        var args = Array.prototype.slice.call(arguments, 1);
+                        if (args.length <= 1) {
+                            args = args[0];
+                        }
+                        callback.call(null, err, args);
+                    });
                 }
-                throw err;
-            }
-            fn(next);
+            }, callback);
         }
-        next();
-    };
-
-    // Node.js
-    if (typeof module !== 'undefined' && module.exports) {
-        module.exports = async;
-    }
-    // AMD / RequireJS
-    else if (typeof define !== 'undefined' && define.amd) {
-        define([], function () {
-            return async;
-        });
-    }
-    // included directly via 
  *  ```
  */
-describe('Mongoose in the browser', function() {
-
+describe('Mongoose in the browser', function () {
   /**
    *  When you include the `mongoose.js` file in a script tag, mongoose will
    *  attach a `mongoose` object to the global `window`. This object includes
@@ -26,12 +25,12 @@ describe('Mongoose in the browser', function() {
    *  browser. In particular, it will *not* work in Internet Explorer 8
    *  or Safari 5.
    */
-  describe('Declaring schemas in the browser', function() {
-    it('allows you to use mongoose types', function() {
-      var foodSchema = new mongoose.Schema({ name: String });
+  describe('Declaring schemas in the browser', function () {
+    it('allows you to use mongoose types', function () {
+      var foodSchema = new mongoose.Schema({name: String});
       var breakfastSchema = new mongoose.Schema({
         foods: [foodSchema],
-        date: { type: Date, default: Date.now }
+        date: {type: Date, default: Date.now}
       });
 
       assert.ok(foodSchema.path('name') instanceof mongoose.Schema.Types.String);
@@ -46,12 +45,12 @@ describe('Mongoose in the browser', function() {
    *  currently support any sort of querying, you're responsible for creating
    *  your own documents.
    */
-  describe('Validating documents in the browser', function() {
-    it('allows you to create a schema and use it to validate documents', function(done) {
+  describe('Validating documents in the browser', function () {
+    it('allows you to create a schema and use it to validate documents', function (done) {
       var schema = new mongoose.Schema({
-        name: { type: String, required: true },
-        quest: { type: String, match: /Holy Grail/i, required: true },
-        favoriteColor: { type: String, enum: ['Red', 'Blue'], required: true }
+        name: {type: String, required: true},
+        quest: {type: String, match: /Holy Grail/i, required: true},
+        favoriteColor: {type: String, enum: ['Red', 'Blue'], required: true}
       });
 
       /* `mongoose.Document` is different in the browser than in NodeJS.
@@ -59,7 +58,7 @@ describe('Mongoose in the browser', function() {
        * then modify the document and call `validate()` to make sure it
        * passes validation rules. */
       var doc = new mongoose.Document({}, schema);
-      doc.validate(function(error) {
+      doc.validate(function (error) {
         assert.ok(error);
         assert.equal('Path `name` is required.', error.errors['name'].message);
         assert.equal('Path `quest` is required.', error.errors['quest'].message);
@@ -69,13 +68,13 @@ describe('Mongoose in the browser', function() {
         doc.name = 'Sir Lancelot of Camelot';
         doc.quest = 'To seek the holy grail';
         doc.favoriteColor = 'Blue';
-        doc.validate(function(error) {
+        doc.validate(function (error) {
           assert.ifError(error);
 
           doc.name = 'Sir Galahad of Camelot';
           doc.quest = 'I seek the grail'; // Invalid, must contain 'holy grail'
           doc.favoriteColor = 'Yellow'; // Invalid, not 'Red' or 'Blue'
-          doc.validate(function(error) {
+          doc.validate(function (error) {
             assert.ok(error);
             assert.ok(!error.errors['name']);
             assert.equal('Path `quest` is invalid (I seek the grail).',
diff --git a/test/browser/schema.test_.js b/test/browser/schema.test_.js
index 45402842e6f..d0e9ae3bf7b 100644
--- a/test/browser/schema.test_.js
+++ b/test/browser/schema.test_.js
@@ -13,27 +13,27 @@ var Schema = mongoose.Schema,
  * Test Document constructor.
  */
 
-function TestDocument( obj ) {
+function TestDocument(obj) {
   mongoose.Document.call(this, obj || {}, new Schema({
     test: String
-  }) );
+  }));
 }
 
 /**
  * Inherits from Document.
  */
 
-TestDocument.prototype = Object.create( Document.prototype );
+TestDocument.prototype = Object.create(Document.prototype);
 TestDocument.prototype.constructor = TestDocument;
 
-describe('schema', function() {
-  it('can be created without the "new" keyword', function(done) {
-    var schema = mongoose.Schema({ name: String });
+describe('schema', function () {
+  it('can be created without the "new" keyword', function (done) {
+    var schema = mongoose.Schema({name: String});
     assert.ok(schema instanceof mongoose.Schema);
     done();
   });
 
-  it('supports different schematypes', function(done) {
+  it('supports different schematypes', function (done) {
     var Checkin = new mongoose.Schema({
       date: Date,
       location: {
@@ -46,7 +46,7 @@ describe('schema', function() {
       name: String,
       owner: mongoose.Schema.Types.ObjectId,
       fur: String,
-      color: { type: String },
+      color: {type: String},
       age: Number,
       checkins: [Checkin],
       friends: [mongoose.Schema.Types.ObjectId],
@@ -84,20 +84,20 @@ describe('schema', function() {
     assert.ok(Checkin1.path('location.lng') instanceof mongoose.Schema.Types.Number);
 
     var Ferret1 = new mongoose.Schema({
-      name: "string",
-      owner: "oid",
-      fur: { type: "string" },
-      color: { type: "String" },
+      name: 'string',
+      owner: 'oid',
+      fur: {type: 'string'},
+      color: {type: 'String'},
       checkins: [Checkin],
       friends: Array,
-      likes: "array",
-      alive: "Bool",
-      alive1: "bool",
-      alive2: "boolean",
-      extra: "mixed",
-      obj: "object",
-      buf: "buffer",
-      Buf: "Buffer"
+      likes: 'array',
+      alive: 'Bool',
+      alive1: 'bool',
+      alive2: 'boolean',
+      extra: 'mixed',
+      obj: 'object',
+      buf: 'buffer',
+      Buf: 'Buffer'
     });
 
     assert.ok(Ferret1.path('name') instanceof mongoose.Schema.Types.String);
@@ -105,7 +105,7 @@ describe('schema', function() {
     assert.ok(Ferret1.path('fur') instanceof mongoose.Schema.Types.String);
     assert.ok(Ferret1.path('color') instanceof mongoose.Schema.Types.String);
     assert.ok(Ferret1.path('checkins') instanceof mongoose.Schema.Types.DocumentArray);
-    assert.ok( Ferret1.path('friends') instanceof mongoose.Schema.Types.Array);
+    assert.ok(Ferret1.path('friends') instanceof mongoose.Schema.Types.Array);
     assert.ok(Ferret1.path('likes') instanceof mongoose.Schema.Types.Array);
     assert.ok(Ferret1.path('alive') instanceof mongoose.Schema.Types.Boolean);
     assert.ok(Ferret1.path('alive1') instanceof mongoose.Schema.Types.Boolean);
@@ -117,9 +117,9 @@ describe('schema', function() {
     done();
   });
 
-  it('supports dot notation for path accessors', function(done) {
+  it('supports dot notation for path accessors', function (done) {
     var Racoon = new Schema({
-      name: { type: String, enum: ['Edwald', 'Tobi'] },
+      name: {type: String, enum: ['Edwald', 'Tobi']},
       age: Number
     });
 
@@ -144,7 +144,7 @@ describe('schema', function() {
     done();
   });
 
-  it('allows paths nested > 2 levels', function(done) {
+  it('allows paths nested > 2 levels', function (done) {
     var Nested = new Schema({
       first: {
         second: {
@@ -156,23 +156,29 @@ describe('schema', function() {
     done();
   });
 
-  it('default definition', function(done) {
+  it('default definition', function (done) {
     var Test = new Schema({
-      simple: { type: String, default: 'a' },
-      array: { type: Array, default: [1,2,3,4,5] },
-      arrayX: { type: Array, default: 9 },
-      arrayFn: { type: Array, default: function() { return [8]; } },
-      callback: { type: Number, default: function() {
-        assert.equal('b', this.a);
-        return '3';
-      }}
+      simple: {type: String, default: 'a'},
+      array: {type: Array, default: [1, 2, 3, 4, 5]},
+      arrayX: {type: Array, default: 9},
+      arrayFn: {
+        type: Array, default: function () {
+          return [8];
+        }
+      },
+      callback: {
+        type: Number, default: function () {
+          assert.equal('b', this.a);
+          return '3';
+        }
+      }
     });
 
     assert.equal(Test.path('simple').defaultValue, 'a');
     assert.equal(typeof Test.path('callback').defaultValue, 'function');
 
     assert.equal(Test.path('simple').getDefault(), 'a');
-    assert.equal((+Test.path('callback').getDefault({ a: 'b' })), 3);
+    assert.equal((+Test.path('callback').getDefault({a: 'b'})), 3);
     assert.equal(typeof Test.path('array').defaultValue, 'function');
     assert.equal(Test.path('array').getDefault(new TestDocument)[3], 4);
     assert.equal(Test.path('arrayX').getDefault(new TestDocument)[0], 9);
@@ -181,10 +187,10 @@ describe('schema', function() {
     done();
   });
 
-  it('Mixed defaults can be empty arrays', function(done) {
+  it('Mixed defaults can be empty arrays', function (done) {
     var Test = new Schema({
-      mixed1: { type: Mixed, default: [] },
-      mixed2: { type: Mixed, default: Array }
+      mixed1: {type: Mixed, default: []},
+      mixed2: {type: Mixed, default: Array}
     });
 
     assert.ok(Test.path('mixed1').getDefault() instanceof Array);
@@ -194,8 +200,8 @@ describe('schema', function() {
     done();
   });
 
-  describe('casting', function() {
-    it('number', function(done) {
+  describe('casting', function () {
+    it('number', function (done) {
       var Tobi = new Schema({
         age: Number
       });
@@ -209,14 +215,16 @@ describe('schema', function() {
       done();
     });
 
-    describe('string', function() {
-      it('works', function(done) {
+    describe('string', function () {
+      it('works', function (done) {
         var Tobi = new Schema({
           nickname: String
         });
 
-        function Test() {}
-        Test.prototype.toString = function() {
+        function Test() {
+        }
+
+        Test.prototype.toString = function () {
           return 'woot';
         };
 
@@ -229,7 +237,7 @@ describe('schema', function() {
         assert.equal('woot', Tobi.path('nickname').cast(new Test));
         done();
       });
-      /*it('casts undefined to "undefined"', function(done){
+      /* it('casts undefined to "undefined"', function(done){
         var schema = new Schema({ arr: [String] });
         var M = db.model('castingStringArrayWithUndefined', schema);
         M.find({ arr: { $in: [undefined] }}, function (err) {
@@ -237,12 +245,12 @@ describe('schema', function() {
           assert.equal(err && err.message, 'Cast to string failed for value "undefined" at path "arr"');
           done();
         });
-      });*/
+      }); */
     });
 
-    it('date', function(done) {
+    it('date', function (done) {
       var Loki = new Schema({
-        birth_date: { type: Date }
+        birth_date: {type: Date}
       });
 
       assert.ok(Loki.path('birth_date').cast(1294525628301) instanceof Date);
@@ -251,28 +259,25 @@ describe('schema', function() {
       done();
     });
 
-    it('objectid', function(done) {
+    it('objectid', function (done) {
       var Loki = new Schema({
-        owner: { type: ObjectId }
+        owner: {type: ObjectId}
       });
 
       var doc = new TestDocument,
           id = doc._id.toString();
 
-      assert.ok(Loki.path('owner').cast('4c54f3453e688c000000001a')
-        instanceof DocumentObjectId);
+      assert.ok(Loki.path('owner').cast('4c54f3453e688c000000001a') instanceof DocumentObjectId);
 
-      assert.ok(Loki.path('owner').cast(new DocumentObjectId())
-        instanceof DocumentObjectId);
+      assert.ok(Loki.path('owner').cast(new DocumentObjectId()) instanceof DocumentObjectId);
 
-      assert.ok(Loki.path('owner').cast(doc)
-        instanceof DocumentObjectId);
+      assert.ok(Loki.path('owner').cast(doc) instanceof DocumentObjectId);
 
       assert.equal(id, Loki.path('owner').cast(doc).toString());
       done();
     });
 
-    it('array', function(done) {
+    it('array', function (done) {
       var Loki = new Schema({
         oids: [ObjectId],
         dates: [Date],
@@ -301,12 +306,12 @@ describe('schema', function() {
       var strings = Loki.path('strings').cast(['test', 123]);
 
       assert.equal(typeof strings[0], 'string');
-      assert.equal('test',strings[0]);
+      assert.equal('test', strings[0]);
 
       assert.equal(typeof strings[1], 'string');
       assert.equal('123', strings[1]);
 
-      var buffers = Loki.path('buffers').cast(['\0\0\0', new underlyingBuffer("abc")]);
+      var buffers = Loki.path('buffers').cast(['\0\0\0', new underlyingBuffer('abc')]);
 
       assert.ok(underlyingBuffer.isBuffer(buffers[0]));
       assert.ok(underlyingBuffer.isBuffer(buffers[1]));
@@ -330,9 +335,9 @@ describe('schema', function() {
       done();
     });
 
-    it('boolean', function(done) {
+    it('boolean', function (done) {
       var Animal = new Schema({
-        isFerret: { type: Boolean, required: true }
+        isFerret: {type: Boolean, required: true}
       });
 
       assert.strictEqual(Animal.path('isFerret').cast(null), null);
@@ -350,44 +355,51 @@ describe('schema', function() {
     });
   });
 
-  it('methods declaration', function(done) {
+  it('methods declaration', function (done) {
     var a = new Schema;
-    a.method('test', function() {});
+    a.method('test', function () {
+    });
     a.method({
-      a: function() {},
-      b: function() {}
+      a: function () {
+      },
+      b: function () {
+      }
     });
     assert.equal(3, Object.keys(a.methods).length);
     done();
   });
 
-  it('static declaration', function(done) {
+  it('static declaration', function (done) {
     var a = new Schema;
-    a.static('test', function() {});
+    a.static('test', function () {
+    });
     a.static({
-      a: function() {},
-      b: function() {},
-      c: function() {}
+      a: function () {
+      },
+      b: function () {
+      },
+      c: function () {
+      }
     });
 
     assert.equal(Object.keys(a.statics).length, 4);
     done();
   });
 
-  describe('setters', function() {
-    it('work', function(done) {
+  describe('setters', function () {
+    it('work', function (done) {
       function lowercase(v) {
         return v.toLowerCase();
       }
 
       var Tobi = new Schema({
-        name: { type: String, set: lowercase }
+        name: {type: String, set: lowercase}
       });
 
       assert.equal('woot', Tobi.path('name').applySetters('WOOT'));
       assert.equal(1, Tobi.path('name').setters.length);
 
-      Tobi.path('name').set(function(v) {
+      Tobi.path('name').set(function (v) {
         return v + 'WOOT';
       });
 
@@ -396,28 +408,28 @@ describe('schema', function() {
       done();
     });
 
-    it('order', function(done) {
+    it('order', function (done) {
       function extract(v) {
         return (v && v._id)
-          ? v._id
-          : v;
+            ? v._id
+            : v;
       }
 
       var Tobi = new Schema({
-        name: { type: Schema.ObjectId, set: extract }
+        name: {type: Schema.ObjectId, set: extract}
       });
 
       var id = new DocumentObjectId,
           sid = id.toString(),
-          _id = { _id: id };
+          _id = {_id: id};
 
-      assert.equal(Tobi.path('name').applySetters(sid, { a: 'b' }).toString(),sid);
-      assert.equal(Tobi.path('name').applySetters(_id, { a: 'b' }).toString(),sid);
-      assert.equal(Tobi.path('name').applySetters(id, { a: 'b' }).toString(),sid);
+      assert.equal(Tobi.path('name').applySetters(sid, {a: 'b'}).toString(), sid);
+      assert.equal(Tobi.path('name').applySetters(_id, {a: 'b'}).toString(), sid);
+      assert.equal(Tobi.path('name').applySetters(id, {a: 'b'}).toString(), sid);
       done();
     });
 
-    it('scope', function(done) {
+    it('scope', function (done) {
       function lowercase(v, self) {
         assert.equal('b', this.a);
         assert.equal('name', self.path);
@@ -425,14 +437,14 @@ describe('schema', function() {
       }
 
       var Tobi = new Schema({
-        name: { type: String, set: lowercase }
+        name: {type: String, set: lowercase}
       });
 
-      assert.equal('what', Tobi.path('name').applySetters('WHAT', { a: 'b' }));
+      assert.equal('what', Tobi.path('name').applySetters('WHAT', {a: 'b'}));
       done();
     });
 
-    it('casting', function(done) {
+    it('casting', function (done) {
       function last(v) {
         assert.equal('number', typeof v);
         assert.equal(0, v);
@@ -444,7 +456,7 @@ describe('schema', function() {
       }
 
       var Tobi = new Schema({
-        name: { type: String, set: last }
+        name: {type: String, set: last}
       });
 
       Tobi.path('name').set(first);
@@ -452,8 +464,8 @@ describe('schema', function() {
       done();
     });
 
-    describe('array', function() {
-      it('object setters will be applied for each object in array', function(done) {
+    describe('array', function () {
+      it('object setters will be applied for each object in array', function (done) {
         var Tobi = new Schema({
           names: [{type: String, lowercase: true, trim: true}]
         });
@@ -465,28 +477,28 @@ describe('schema', function() {
       });
     });
 
-    describe('string', function() {
-      it('lowercase', function(done) {
+    describe('string', function () {
+      it('lowercase', function (done) {
         var Tobi = new Schema({
-          name: { type: String, lowercase: true }
+          name: {type: String, lowercase: true}
         });
 
         assert.equal('what', Tobi.path('name').applySetters('WHAT'));
         assert.equal('1977', Tobi.path('name').applySetters(1977));
         done();
       });
-      it('uppercase', function(done) {
+      it('uppercase', function (done) {
         var Tobi = new Schema({
-          name: { type: String, uppercase: true }
+          name: {type: String, uppercase: true}
         });
 
         assert.equal('WHAT', Tobi.path('name').applySetters('what'));
         assert.equal('1977', Tobi.path('name').applySetters(1977));
         done();
       });
-      it('trim', function(done) {
+      it('trim', function (done) {
         var Tobi = new Schema({
-          name: { type: String, uppercase: true, trim: true }
+          name: {type: String, uppercase: true, trim: true}
         });
 
         assert.equal('WHAT', Tobi.path('name').applySetters('  what   '));
@@ -495,7 +507,7 @@ describe('schema', function() {
       });
     });
 
-    it('applying when none have been defined', function(done) {
+    it('applying when none have been defined', function (done) {
       var Tobi = new Schema({
         name: String
       });
@@ -504,8 +516,8 @@ describe('schema', function() {
       done();
     });
 
-    it('assignment of non-functions throw', function(done) {
-      var schema = new Schema({ fun: String });
+    it('assignment of non-functions throw', function (done) {
+      var schema = new Schema({fun: String});
       var g;
 
       try {
@@ -515,40 +527,40 @@ describe('schema', function() {
       }
 
       assert.ok(g);
-      assert.equal(g.message,'A setter must be a function.');
+      assert.equal(g.message, 'A setter must be a function.');
       done();
     });
   });
 
-  describe('getters', function() {
-    it('work', function(done) {
+  describe('getters', function () {
+    it('work', function (done) {
       function woot(v) {
         return v + ' woot';
       }
 
       var Tobi = new Schema({
-        name: { type: String, get: woot }
+        name: {type: String, get: woot}
       });
 
       assert.equal(1, Tobi.path('name').getters.length);
       assert.equal('test woot', Tobi.path('name').applyGetters('test'));
       done();
     });
-    it('order', function(done) {
+    it('order', function (done) {
       function format(v) {
         return v
-          ? '$' + v
-          : v;
+            ? '$' + v
+            : v;
       }
 
       var Tobi = new Schema({
-        name: { type: Number, get: format }
+        name: {type: Number, get: format}
       });
 
-      assert.equal('$30', Tobi.path('name').applyGetters(30, { a: 'b' }));
+      assert.equal('$30', Tobi.path('name').applyGetters(30, {a: 'b'}));
       done();
     });
-    it('scope', function(done) {
+    it('scope', function (done) {
       function woot(v, self) {
         assert.equal('b', this.a);
         assert.equal('name', self.path);
@@ -556,13 +568,13 @@ describe('schema', function() {
       }
 
       var Tobi = new Schema({
-        name: { type: String, get: woot }
+        name: {type: String, get: woot}
       });
 
-      assert.equal('yep', Tobi.path('name').applyGetters('YEP', { a: 'b' }));
+      assert.equal('yep', Tobi.path('name').applyGetters('YEP', {a: 'b'}));
       done();
     });
-    it('casting', function(done) {
+    it('casting', function (done) {
       function last(v) {
         assert.equal('number', typeof v);
         assert.equal(0, v);
@@ -574,14 +586,14 @@ describe('schema', function() {
       }
 
       var Tobi = new Schema({
-        name: { type: String, get: last }
+        name: {type: String, get: last}
       });
 
       Tobi.path('name').get(first);
       assert.equal('last', Tobi.path('name').applyGetters('woot'));
       done();
     });
-    it('applying when none have been defined', function(done) {
+    it('applying when none have been defined', function (done) {
       var Tobi = new Schema({
         name: String
       });
@@ -589,8 +601,8 @@ describe('schema', function() {
       assert.equal('woot', Tobi.path('name').applyGetters('woot'));
       done();
     });
-    it('assignment of non-functions throw', function(done) {
-      var schema = new Schema({ fun: String });
+    it('assignment of non-functions throw', function (done) {
+      var schema = new Schema({fun: String});
       var g;
 
       try {
@@ -600,10 +612,10 @@ describe('schema', function() {
       }
 
       assert.ok(g);
-      assert.equal(g.message,'A getter must be a function.');
+      assert.equal(g.message, 'A getter must be a function.');
       done();
     });
-    it('auto _id', function(done) {
+    it('auto _id', function (done) {
       var schema = new Schema({
         name: String
       });
@@ -611,28 +623,28 @@ describe('schema', function() {
 
       schema = new Schema({
         name: String
-      }, { _id: true });
+      }, {_id: true});
       assert.ok(schema.path('_id') instanceof Schema.ObjectId);
 
       schema = new Schema({
         name: String
-      }, { _id: false });
+      }, {_id: false});
       assert.equal(undefined, schema.path('_id'));
 
       // old options
       schema = new Schema({
         name: String
-      }, { noId: false });
+      }, {noId: false});
       assert.ok(schema.path('_id') instanceof Schema.ObjectId);
 
       schema = new Schema({
         name: String
-      }, { noId: true });
+      }, {noId: true});
       assert.equal(undefined, schema.path('_id'));
       done();
     });
 
-    it('auto id', function(done) {
+    it('auto id', function (done) {
       var schema = new Schema({
         name: String
       });
@@ -640,50 +652,53 @@ describe('schema', function() {
 
       schema = new Schema({
         name: String
-      }, { id: true });
+      }, {id: true});
       assert.ok(schema.virtualpath('id') instanceof mongoose.VirtualType);
 
       schema = new Schema({
         name: String
-      }, { id: false });
+      }, {id: false});
       assert.equal(undefined, schema.virtualpath('id'));
 
       // old options
       schema = new Schema({
         name: String
-      }, { noVirtualId: false });
+      }, {noVirtualId: false});
       assert.ok(schema.virtualpath('id') instanceof mongoose.VirtualType);
 
       schema = new Schema({
         name: String
-      }, { noVirtualId: true });
+      }, {noVirtualId: true});
       assert.equal(undefined, schema.virtualpath('id'));
       done();
     });
   });
 
-  describe('hooks', function() {
-    it('registration', function(done) {
+  describe('hooks', function () {
+    it('registration', function (done) {
       var Tobi = new Schema();
 
-      Tobi.pre('save', function() {});
+      Tobi.pre('save', function () {
+      });
       assert.equal(2, Tobi.callQueue.length);
 
-      Tobi.post('save', function() {});
+      Tobi.post('save', function () {
+      });
       assert.equal(3, Tobi.callQueue.length);
 
-      Tobi.pre('save', function() {});
+      Tobi.pre('save', function () {
+      });
       assert.equal(4, Tobi.callQueue.length);
       done();
     });
   });
 
-  describe('plugins', function() {
-    it('work', function(done) {
+  describe('plugins', function () {
+    it('work', function (done) {
       var Tobi = new Schema,
           called = false;
 
-      Tobi.plugin(function(schema) {
+      Tobi.plugin(function (schema) {
         assert.equal(schema, Tobi);
         called = true;
       });
@@ -693,8 +708,8 @@ describe('schema', function() {
     });
   });
 
-  describe('options', function() {
-    it('defaults are set', function(done) {
+  describe('options', function () {
+    it('defaults are set', function (done) {
       var Tobi = new Schema();
 
       assert.equal('object', typeof Tobi.options);
@@ -709,83 +724,83 @@ describe('schema', function() {
       done();
     });
 
-    it('setting', function(done) {
-      var Tobi = new Schema({}, { collection: 'users' });
+    it('setting', function (done) {
+      var Tobi = new Schema({}, {collection: 'users'});
 
       Tobi.set('a', 'b');
       Tobi.set('safe', false);
       assert.equal('users', Tobi.options.collection);
 
       assert.equal('b', Tobi.options.a);
-      assert.deepEqual(Tobi.options.safe, { w: 0 });
+      assert.deepEqual(Tobi.options.safe, {w: 0});
       assert.equal(null, Tobi.options.read);
 
       done();
     });
   });
 
-  describe('virtuals', function() {
-    it('works', function(done) {
+  describe('virtuals', function () {
+    it('works', function (done) {
       var Contact = new Schema({
         firstName: String,
         lastName: String
       });
 
       Contact
-        .virtual('fullName')
-        .get(function() {
-          return this.get('firstName') + ' ' + this.get('lastName');
-        })
-        .set(function(fullName) {
-          var split = fullName.split(' ');
-          this.set('firstName', split[0]);
-          this.set('lastName', split[1]);
-        });
+      .virtual('fullName')
+      .get(function () {
+        return this.get('firstName') + ' ' + this.get('lastName');
+      })
+      .set(function (fullName) {
+        var split = fullName.split(' ');
+        this.set('firstName', split[0]);
+        this.set('lastName', split[1]);
+      });
 
       assert.ok(Contact.virtualpath('fullName') instanceof VirtualType);
       done();
     });
 
-    describe('id', function() {
-      it('default creation of id can be overridden (gh-298)', function(done) {
-        assert.doesNotThrow(function() {
-          new Schema({ id: String });
+    describe('id', function () {
+      it('default creation of id can be overridden (gh-298)', function (done) {
+        assert.doesNotThrow(function () {
+          new Schema({id: String});
         });
         done();
       });
-      it('disabling', function(done) {
-        var schema = new Schema({ name: String }, { noVirtualId: true });
+      it('disabling', function (done) {
+        var schema = new Schema({name: String}, {noVirtualId: true});
         assert.strictEqual(undefined, schema.virtuals.id);
         done();
       });
     });
 
-    describe('getter', function() {
-      it('scope', function(done) {
+    describe('getter', function () {
+      it('scope', function (done) {
         var Tobi = new Schema;
 
-        Tobi.virtual('name').get(function(v, self) {
+        Tobi.virtual('name').get(function (v, self) {
           assert.equal('b', this.a);
           assert.equal('name', self.path);
           return v.toLowerCase();
         });
 
-        assert.equal('yep', Tobi.virtualpath('name').applyGetters('YEP', { a: 'b' }));
+        assert.equal('yep', Tobi.virtualpath('name').applyGetters('YEP', {a: 'b'}));
         done();
       });
     });
 
-    describe('setter', function() {
-      it('scope', function(done) {
+    describe('setter', function () {
+      it('scope', function (done) {
         var Tobi = new Schema;
 
-        Tobi.virtual('name').set(function(v, self) {
+        Tobi.virtual('name').set(function (v, self) {
           assert.equal('b', this.a);
           assert.equal('name', self.path);
           return v.toLowerCase();
         });
 
-        assert.equal('yep', Tobi.virtualpath('name').applySetters('YEP', { a: 'b' }));
+        assert.equal('yep', Tobi.virtualpath('name').applySetters('YEP', {a: 'b'}));
         done();
       });
     });
@@ -794,16 +809,16 @@ describe('schema', function() {
   // not other contexts
   // not #add()
 
-  it('debugging msgs', function(done) {
+  it('debugging msgs', function (done) {
     var err;
     try {
-      new Schema({ name: { first: null } });
+      new Schema({name: {first: null}});
     } catch (e) {
       err = e;
     }
-    assert.equal(err.message,'Invalid value for schema path `name.first`');
+    assert.equal(err.message, 'Invalid value for schema path `name.first`');
     try {
-      new Schema({ age: undefined });
+      new Schema({age: undefined});
     } catch (e) {
       err = e;
     }
@@ -811,39 +826,39 @@ describe('schema', function() {
     done();
   });
 
-  describe('construction', function() {
-    it('array of object literal missing a type is interpreted as DocumentArray', function(done) {
+  describe('construction', function () {
+    it('array of object literal missing a type is interpreted as DocumentArray', function (done) {
       var s = new Schema({
         arr: [
-          { something: { type: String } }
+          {something: {type: String}}
         ]
       });
       assert.ok(s.path('arr') instanceof SchemaTypes.DocumentArray);
-      var m = new mongoose.Document({ arr: [ { something: 'wicked this way comes' }] }, s);
+      var m = new mongoose.Document({arr: [{something: 'wicked this way comes'}]}, s);
       assert.equal('wicked this way comes', m.arr[0].something);
       assert.ok(m.arr[0]._id);
       done();
     });
 
-    it('array of object literal with type.type is interpreted as DocumentArray', function(done) {
+    it('array of object literal with type.type is interpreted as DocumentArray', function (done) {
       var s = new Schema({
         arr: [
-          { type: { type: String } }
+          {type: {type: String}}
         ]
       });
       assert.ok(s.path('arr') instanceof SchemaTypes.DocumentArray);
-      var m = new mongoose.Document({ arr: [ { type: 'works' }] }, s);
+      var m = new mongoose.Document({arr: [{type: 'works'}]}, s);
       assert.equal('works', m.arr[0].type);
       assert.ok(m.arr[0]._id);
       done();
     });
 
-    it('of nested schemas should throw (gh-700)', function(done) {
-      var a = new Schema({ title: String }),
+    it('of nested schemas should throw (gh-700)', function (done) {
+      var a = new Schema({title: String}),
           err;
 
       try {
-        new Schema({ blah: Boolean, a: a });
+        new Schema({blah: Boolean, a: a});
       } catch (err_) {
         err = err_;
       }
@@ -853,29 +868,29 @@ describe('schema', function() {
       done();
     });
 
-    it('does not alter original argument (gh-1364)', function(done) {
+    it('does not alter original argument (gh-1364)', function (done) {
       var schema = {
-        ids: [{ type: Schema.ObjectId, ref: 'something' }],
-        a: { type: Array },
+        ids: [{type: Schema.ObjectId, ref: 'something'}],
+        a: {type: Array},
         b: Array,
         c: [Date],
-        d: { type: 'Boolean' },
-        e: [{ a: String, b: [{ /*type: { type: Buffer },*/ x: Number }] }]
+        d: {type: 'Boolean'},
+        e: [{a: String, b: [{x: Number}]}]
       };
 
       new Schema(schema);
       assert.equal(6, Object.keys(schema).length);
-      assert.deepEqual([{ type: Schema.ObjectId, ref: 'something' }], schema.ids);
-      assert.deepEqual({ type: Array }, schema.a);
+      assert.deepEqual([{type: Schema.ObjectId, ref: 'something'}], schema.ids);
+      assert.deepEqual({type: Array}, schema.a);
       assert.deepEqual(Array, schema.b);
       assert.deepEqual([Date], schema.c);
-      assert.deepEqual({ type: 'Boolean' }, schema.d);
-      assert.deepEqual([{ a: String, b: [{ /*type: { type: Buffer },*/ x: Number }] }], schema.e);
+      assert.deepEqual({type: 'Boolean'}, schema.d);
+      assert.deepEqual([{a: String, b: [{x: Number}]}], schema.e);
 
       done();
     });
 
-    /*it('properly gets value of plain objects when dealing with refs (gh-1606)', function (done) {
+    /* it('properly gets value of plain objects when dealing with refs (gh-1606)', function (done) {
       var el = new Schema({ title : String });
       var so = new Schema({
         title : String,
@@ -899,6 +914,6 @@ describe('schema', function() {
           });
         });
       });
-    });*/
+    }); */
   });
 });
diff --git a/test/browser/schema.validation.test_.js b/test/browser/schema.validation.test_.js
index f10c59cccb0..99959a59087 100644
--- a/test/browser/schema.validation.test_.js
+++ b/test/browser/schema.validation.test_.js
@@ -9,44 +9,44 @@ var Schema = mongoose.Schema,
     Mixed = SchemaTypes.Mixed,
     DocumentObjectId = mongoose.Types.ObjectId;
 
-describe('schema', function() {
-  describe('validation', function() {
-    it('invalid arguments are rejected (1044)', function(done) {
-      assert.throws(function() {
+describe('schema', function () {
+  describe('validation', function () {
+    it('invalid arguments are rejected (1044)', function (done) {
+      assert.throws(function () {
         new Schema({
-          simple: { type: String, validate: 'nope' }
+          simple: {type: String, validate: 'nope'}
         });
       }, /Invalid validator/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
-          simple: { type: String, validate: ['nope'] }
+          simple: {type: String, validate: ['nope']}
         });
       }, /Invalid validator/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
-          simple: { type: String, validate: { nope: 1, msg: 'nope' } }
+          simple: {type: String, validate: {nope: 1, msg: 'nope'}}
         });
       }, /Invalid validator/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
-          simple: { type: String, validate: [{ nope: 1, msg: 'nope' }, 'nope'] }
+          simple: {type: String, validate: [{nope: 1, msg: 'nope'}, 'nope']}
         });
       }, /Invalid validator/);
 
       done();
     });
 
-    it('string enum', function(done) {
+    it('string enum', function (done) {
       var Test = new Schema({
-        complex: { type: String, enum: ['a', 'b', undefined, 'c', null] },
-        state: { type: String }
+        complex: {type: String, enum: ['a', 'b', undefined, 'c', null]},
+        state: {type: String}
       });
 
       assert.ok(Test.path('complex') instanceof SchemaTypes.String);
-      assert.deepEqual(Test.path('complex').enumValues,['a', 'b', 'c', null]);
+      assert.deepEqual(Test.path('complex').enumValues, ['a', 'b', 'c', null]);
       assert.equal(Test.path('complex').validators.length, 1);
 
       Test.path('complex').enum('d', 'e');
@@ -62,101 +62,101 @@ describe('schema', function() {
       assert.equal(Test.path('state').validators.length, 1);
       assert.deepEqual(Test.path('state').enumValues, ['opening', 'open', 'closing', 'closed']);
 
-      Test.path('complex').doValidate('x', function(err) {
+      Test.path('complex').doValidate('x', function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       // allow unsetting enums
-      Test.path('complex').doValidate(undefined, function(err) {
+      Test.path('complex').doValidate(undefined, function (err) {
         assert.ifError(err);
       });
 
-      Test.path('complex').doValidate(null, function(err) {
+      Test.path('complex').doValidate(null, function (err) {
         assert.ifError(err);
       });
 
-      Test.path('complex').doValidate('da', function(err) {
+      Test.path('complex').doValidate('da', function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('state').doValidate('x', function(err) {
+      Test.path('state').doValidate('x', function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('state').doValidate('opening', function(err) {
+      Test.path('state').doValidate('opening', function (err) {
         assert.ifError(err);
       });
 
-      Test.path('state').doValidate('open', function(err) {
+      Test.path('state').doValidate('open', function (err) {
         assert.ifError(err);
       });
 
       done();
     });
 
-    it('string regexp', function(done) {
+    it('string regexp', function (done) {
       var Test = new Schema({
-        simple: { type: String, match: /[a-z]/ }
+        simple: {type: String, match: /[a-z]/}
       });
 
       assert.equal(1, Test.path('simple').validators.length);
 
-      Test.path('simple').doValidate('az', function(err) {
+      Test.path('simple').doValidate('az', function (err) {
         assert.ifError(err);
       });
 
       Test.path('simple').match(/[0-9]/);
       assert.equal(2, Test.path('simple').validators.length);
 
-      Test.path('simple').doValidate('12', function(err) {
+      Test.path('simple').doValidate('12', function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('simple').doValidate('a12', function(err) {
+      Test.path('simple').doValidate('a12', function (err) {
         assert.ifError(err);
       });
 
-      Test.path('simple').doValidate('', function(err) {
+      Test.path('simple').doValidate('', function (err) {
         assert.ifError(err);
       });
-      Test.path('simple').doValidate(null, function(err) {
+      Test.path('simple').doValidate(null, function (err) {
         assert.ifError(err);
       });
-      Test.path('simple').doValidate(undefined, function(err) {
+      Test.path('simple').doValidate(undefined, function (err) {
         assert.ifError(err);
       });
       Test.path('simple').validators = [];
       Test.path('simple').match(/[1-9]/);
-      Test.path('simple').doValidate(0, function(err) {
+      Test.path('simple').doValidate(0, function (err) {
         assert.ok(err instanceof ValidatorError);
       });
       done();
     });
 
-    it('number min and max', function(done) {
+    it('number min and max', function (done) {
       var Tobi = new Schema({
-        friends: { type: Number, max: 15, min: 5 }
+        friends: {type: Number, max: 15, min: 5}
       });
 
       assert.equal(Tobi.path('friends').validators.length, 2);
 
-      Tobi.path('friends').doValidate(10, function(err) {
+      Tobi.path('friends').doValidate(10, function (err) {
         assert.ifError(err);
       });
 
-      Tobi.path('friends').doValidate(100, function(err) {
+      Tobi.path('friends').doValidate(100, function (err) {
         assert.ok(err instanceof ValidatorError);
         assert.equal('friends', err.path);
         assert.equal('max', err.kind);
         assert.equal(100, err.value);
       });
 
-      Tobi.path('friends').doValidate(1, function(err) {
+      Tobi.path('friends').doValidate(1, function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       // null is allowed
-      Tobi.path('friends').doValidate(null, function(err) {
+      Tobi.path('friends').doValidate(null, function (err) {
         assert.ifError(err);
       });
 
@@ -167,8 +167,8 @@ describe('schema', function() {
       done();
     });
 
-    describe('required', function() {
-      it('string required', function(done) {
+    describe('required', function () {
+      it('string required', function (done) {
         var Test = new Schema({
           simple: String
         });
@@ -176,300 +176,302 @@ describe('schema', function() {
         Test.path('simple').required(true);
         assert.equal(Test.path('simple').validators.length, 1);
 
-        Test.path('simple').doValidate(null, function(err) {
+        Test.path('simple').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate(undefined, function(err) {
+        Test.path('simple').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('', function(err) {
+        Test.path('simple').doValidate('', function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('woot', function(err) {
+        Test.path('simple').doValidate('woot', function (err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('string conditional required', function(done) {
+      it('string conditional required', function (done) {
         var Test = new Schema({
           simple: String
         });
 
         var required = true,
-            isRequired = function() {
+            isRequired = function () {
               return required;
             };
 
         Test.path('simple').required(isRequired);
         assert.equal(Test.path('simple').validators.length, 1);
 
-        Test.path('simple').doValidate(null, function(err) {
+        Test.path('simple').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate(undefined, function(err) {
+        Test.path('simple').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('', function(err) {
+        Test.path('simple').doValidate('', function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('woot', function(err) {
+        Test.path('simple').doValidate('woot', function (err) {
           assert.ifError(err);
         });
 
         required = false;
 
-        Test.path('simple').doValidate(null, function(err) {
+        Test.path('simple').doValidate(null, function (err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate(undefined, function(err) {
+        Test.path('simple').doValidate(undefined, function (err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate('', function(err) {
+        Test.path('simple').doValidate('', function (err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate('woot', function(err) {
+        Test.path('simple').doValidate('woot', function (err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('number required', function(done) {
+      it('number required', function (done) {
         var Edwald = new Schema({
-          friends: { type: Number, required: true }
+          friends: {type: Number, required: true}
         });
 
-        Edwald.path('friends').doValidate(null, function(err) {
+        Edwald.path('friends').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Edwald.path('friends').doValidate(undefined, function(err) {
+        Edwald.path('friends').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Edwald.path('friends').doValidate(0, function(err) {
+        Edwald.path('friends').doValidate(0, function (err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('date required', function(done) {
+      it('date required', function (done) {
         var Loki = new Schema({
-          birth_date: { type: Date, required: true }
+          birth_date: {type: Date, required: true}
         });
 
-        Loki.path('birth_date').doValidate(null, function(err) {
+        Loki.path('birth_date').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('birth_date').doValidate(undefined, function(err) {
+        Loki.path('birth_date').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('birth_date').doValidate(new Date(), function(err) {
+        Loki.path('birth_date').doValidate(new Date(), function (err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('objectid required', function(done) {
+      it('objectid required', function (done) {
         var Loki = new Schema({
-          owner: { type: ObjectId, required: true }
+          owner: {type: ObjectId, required: true}
         });
 
-        Loki.path('owner').doValidate(new DocumentObjectId(), function(err) {
+        Loki.path('owner').doValidate(new DocumentObjectId(), function (err) {
           assert.ifError(err);
         });
 
-        Loki.path('owner').doValidate(null, function(err) {
+        Loki.path('owner').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('owner').doValidate(undefined, function(err) {
+        Loki.path('owner').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
         done();
       });
 
-      it('array required', function(done) {
+      it('array required', function (done) {
         var Loki = new Schema({
-          likes: { type: Array, required: true }
+          likes: {type: Array, required: true}
         });
 
-        Loki.path('likes').doValidate(null, function(err) {
+        Loki.path('likes').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('likes').doValidate(undefined, function(err) {
+        Loki.path('likes').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('likes').doValidate([], function(err) {
+        Loki.path('likes').doValidate([], function (err) {
           assert.ok(err instanceof ValidatorError);
         });
         done();
       });
 
-      it('boolean required', function(done) {
+      it('boolean required', function (done) {
         var Animal = new Schema({
-          isFerret: { type: Boolean, required: true }
+          isFerret: {type: Boolean, required: true}
         });
 
-        Animal.path('isFerret').doValidate(null, function(err) {
+        Animal.path('isFerret').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('isFerret').doValidate(undefined, function(err) {
+        Animal.path('isFerret').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('isFerret').doValidate(true, function(err) {
+        Animal.path('isFerret').doValidate(true, function (err) {
           assert.ifError(err);
         });
 
-        Animal.path('isFerret').doValidate(false, function(err) {
+        Animal.path('isFerret').doValidate(false, function (err) {
           assert.ifError(err);
         });
         done();
       });
 
-      it('mixed required', function(done) {
+      it('mixed required', function (done) {
         var Animal = new Schema({
-          characteristics: { type: Mixed, required: true }
+          characteristics: {type: Mixed, required: true}
         });
 
-        Animal.path('characteristics').doValidate(null, function(err) {
+        Animal.path('characteristics').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('characteristics').doValidate(undefined, function(err) {
+        Animal.path('characteristics').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
         Animal.path('characteristics').doValidate({
           aggresive: true
-        }, function(err) {
+        }, function (err) {
           assert.ifError(err);
         });
 
-        Animal.path('characteristics').doValidate('none available', function(err) {
+        Animal.path('characteristics').doValidate('none available', function (err) {
           assert.ifError(err);
         });
         done();
       });
     });
 
-    describe('async', function() {
-      it('works', function(done) {
+    describe('async', function () {
+      it('works', function (done) {
         var executed = 0;
 
         function validator(value, fn) {
-          setTimeout(function() {
+          setTimeout(function () {
             executed++;
             fn(value === true);
-            if (2 === executed) done();
+            if (2 === executed) {
+              done();
+            }
           }, 5);
         }
 
         var Animal = new Schema({
-          ferret: { type: Boolean, validate: validator }
+          ferret: {type: Boolean, validate: validator}
         });
 
-        Animal.path('ferret').doValidate(true, function(err) {
+        Animal.path('ferret').doValidate(true, function (err) {
           assert.ifError(err);
         });
 
-        Animal.path('ferret').doValidate(false, function(err) {
+        Animal.path('ferret').doValidate(false, function (err) {
           assert.ok(err instanceof Error);
         });
       });
 
-      it('multiple', function(done) {
+      it('multiple', function (done) {
         var executed = 0;
 
         function validator(value, fn) {
-          setTimeout(function() {
+          setTimeout(function () {
             executed++;
             fn(value === true);
-            if (2 === executed) done();
+            if (2 === executed) {
+              done();
+            }
           }, 5);
         }
 
         var Animal = new Schema({
           ferret: {
             type: Boolean,
-            validate: [
-                {
-                  'validator': validator,
-                  'msg': 'validator1'
-                },
-                {
-                  'validator': validator,
-                  'msg': 'validator2'
-                }
-            ]
+            validate: [{
+              'validator': validator,
+              'msg': 'validator1'
+            }, {
+              'validator': validator,
+              'msg': 'validator2'
+            }]
           }
         });
 
-        Animal.path('ferret').doValidate(true, function(err) {
+        Animal.path('ferret').doValidate(true, function (err) {
           assert.ifError(err);
         });
       });
 
-      it('scope', function(done) {
+      it('scope', function (done) {
         var called = false;
+
         function validator(value, fn) {
           assert.equal('b', this.a);
 
-          setTimeout(function() {
+          setTimeout(function () {
             called = true;
             fn(true);
           }, 5);
         }
 
         var Animal = new Schema({
-          ferret: { type: Boolean, validate: validator }
+          ferret: {type: Boolean, validate: validator}
         });
 
-        Animal.path('ferret').doValidate(true, function(err) {
+        Animal.path('ferret').doValidate(true, function (err) {
           assert.ifError(err);
           assert.equal(true, called);
           done();
-        }, { a: 'b' });
+        }, {a: 'b'});
       });
     });
 
-    describe('messages', function() {
-      describe('are customizable', function() {
-        it('within schema definitions', function(done) {
+    describe('messages', function () {
+      describe('are customizable', function () {
+        it('within schema definitions', function (done) {
           var schema = new Schema({
-            name: { type: String, enum: ['one', 'two'] },
-            myenum: { type: String, enum: { values: ['x'], message: 'enum validator failed for path: {PATH} with {VALUE}' }},
-            requiredString1: { type: String, required: true },
-            requiredString2: { type: String, required: 'oops, {PATH} is missing. {TYPE}' },
-            matchString0: { type: String, match: /bryancranston/ },
-            matchString1: { type: String, match: [/bryancranston/, 'invalid string for {PATH} with value: {VALUE}'] },
-            numMin0: { type: Number, min: 10 },
-            numMin1: { type: Number, min: [10, 'hey, {PATH} is too small']},
-            numMax0: { type: Number, max: 20 },
-            numMax1: { type: Number, max: [20, 'hey, {PATH} ({VALUE}) is greater than {MAX}'] }
+            name: {type: String, enum: ['one', 'two']},
+            myenum: {type: String, enum: {values: ['x'], message: 'enum validator failed for path: {PATH} with {VALUE}'}},
+            requiredString1: {type: String, required: true},
+            requiredString2: {type: String, required: 'oops, {PATH} is missing. {TYPE}'},
+            matchString0: {type: String, match: /bryancranston/},
+            matchString1: {type: String, match: [/bryancranston/, 'invalid string for {PATH} with value: {VALUE}']},
+            numMin0: {type: Number, min: 10},
+            numMin1: {type: Number, min: [10, 'hey, {PATH} is too small']},
+            numMax0: {type: Number, max: 20},
+            numMax1: {type: Number, max: [20, 'hey, {PATH} ({VALUE}) is greater than {MAX}']}
           });
 
           var a = new mongoose.Document({}, schema);
-          a.validate(function(err) {
+          a.validate(function (err) {
             assert.equal('Path `requiredString1` is required.', err.errors.requiredString1);
             assert.equal('oops, requiredString2 is missing. required', err.errors.requiredString2);
 
@@ -480,7 +482,7 @@ describe('schema', function() {
             a.numMin0 = a.numMin1 = 2;
             a.numMax0 = a.numMax1 = 30;
 
-            a.validate(function(err) {
+            a.validate(function (err) {
               assert.equal('`three` is not a valid enum value for path `name`.', err.errors.name);
               assert.equal('enum validator failed for path: myenum with y', err.errors.myenum);
               assert.equal('Path `matchString0` is invalid (no match).', err.errors.matchString0);
@@ -500,17 +502,18 @@ describe('schema', function() {
           });
         });
 
-        it('for custom validators', function(done) {
+        it('for custom validators', function (done) {
           function validate() {
             return false;
           }
+
           var validator = [validate, '{PATH} failed validation ({VALUE})'];
 
-          var schema = new Schema({ x: { type: [], validate: validator }});
+          var schema = new Schema({x: {type: [], validate: validator}});
 
-          var doc = new mongoose.Document({ x: [3,4,5,6] }, schema);
+          var doc = new mongoose.Document({x: [3, 4, 5, 6]}, schema);
 
-          doc.validate(function(err) {
+          doc.validate(function (err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('user defined', err.errors.x.kind);
             done();
@@ -519,37 +522,39 @@ describe('schema', function() {
       });
     });
 
-    describe('types', function() {
-      describe('are customizable', function() {
-        it('for single custom validators', function(done) {
+    describe('types', function () {
+      describe('are customizable', function () {
+        it('for single custom validators', function (done) {
           function validate() {
             return false;
           }
+
           var validator = [validate, '{PATH} failed validation ({VALUE})', 'customType'];
 
-          var schema = new Schema({ x: { type: [], validate: validator }});
+          var schema = new Schema({x: {type: [], validate: validator}});
 
-          var doc = new mongoose.Document({ x: [3,4,5,6] }, schema);
+          var doc = new mongoose.Document({x: [3, 4, 5, 6]}, schema);
 
-          doc.validate(function(err) {
+          doc.validate(function (err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('customType', err.errors.x.kind);
             done();
           });
         });
 
-        it('for many custom validators', function(done) {
+        it('for many custom validators', function (done) {
           function validate() {
             return false;
           }
+
           var validator = [
-              { validator: validate, msg: '{PATH} failed validation ({VALUE})', type: 'customType'}
+            {validator: validate, msg: '{PATH} failed validation ({VALUE})', type: 'customType'}
           ];
-          var schema = new Schema({ x: { type: [], validate: validator }});
+          var schema = new Schema({x: {type: [], validate: validator}});
 
-          var doc = new mongoose.Document({ x: [3,4,5,6] }, schema);
+          var doc = new mongoose.Document({x: [3, 4, 5, 6]}, schema);
 
-          doc.validate(function(err) {
+          doc.validate(function (err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('customType', err.errors.x.kind);
             done();
@@ -558,8 +563,8 @@ describe('schema', function() {
       });
     });
 
-    describe('sync', function() {
-      it('works', function( done ) {
+    describe('sync', function () {
+      it('works', function (done) {
         var executed = 0;
 
         function validator(value) {
@@ -568,16 +573,18 @@ describe('schema', function() {
         }
 
         var Animal = new Schema({
-          ferret: { type: Boolean, validate: validator }
+          ferret: {type: Boolean, validate: validator}
         });
 
         assert.ifError(Animal.path('ferret').doValidateSync(true));
         assert.ok(Animal.path('ferret').doValidateSync(false) instanceof Error);
 
-        if (2 === executed) done();
+        if (2 === executed) {
+          done();
+        }
       });
 
-      it('multiple', function(done) {
+      it('multiple', function (done) {
         var executed = 0;
 
         function validator(value) {
@@ -588,26 +595,26 @@ describe('schema', function() {
         var Animal = new Schema({
           ferret: {
             type: Boolean,
-            validate: [
-                {
-                  'validator': validator,
-                  'msg': 'validator1'
-                },
-                {
-                  'validator': validator,
-                  'msg': 'validator2'
-                }
-            ]
+            validate: [{
+              'validator': validator,
+              'msg': 'validator1'
+            }, {
+              'validator': validator,
+              'msg': 'validator2'
+            }]
           }
         });
 
         assert.ifError(Animal.path('ferret').doValidateSync(true));
 
-        if (2 === executed) done();
+        if (2 === executed) {
+          done();
+        }
       });
 
-      it('scope', function(done) {
+      it('scope', function (done) {
         var called = false;
+
         function validator() {
           assert.equal('b', this.a);
 
@@ -616,10 +623,10 @@ describe('schema', function() {
         }
 
         var Animal = new Schema({
-          ferret: { type: Boolean, validate: validator }
+          ferret: {type: Boolean, validate: validator}
         });
 
-        var err = Animal.path('ferret').doValidateSync(true, { a: 'b' });
+        var err = Animal.path('ferret').doValidateSync(true, {a: 'b'});
 
         assert.ifError(err);
         assert.equal(true, called);
@@ -627,22 +634,23 @@ describe('schema', function() {
         done();
       });
 
-      it('ingore async', function(done) {
+      it('ingore async', function (done) {
         function syncValidator(val) {
           return val == 'sync';
         }
 
         var called = false;
+
         function asyncValidator(val, respond) {
           called = true;
-          setTimeout(function() {
-            respond( val == 'async' );
+          setTimeout(function () {
+            respond(val == 'async');
           }, 0);
         }
 
         var Animal = new Schema({
-          simple: { type: Boolean, validate: [ syncValidator, asyncValidator ] },
-          simpleAsync: { type: Boolean, validate: asyncValidator }
+          simple: {type: Boolean, validate: [syncValidator, asyncValidator]},
+          simpleAsync: {type: Boolean, validate: asyncValidator}
         });
 
         assert.ifError(Animal.path('simple').doValidateSync('sync'));
@@ -653,26 +661,27 @@ describe('schema', function() {
         done();
       });
 
-      it('subdoc', function(done) {
+      it('subdoc', function (done) {
         function syncValidator(val) {
           return val == 'sync';
         }
 
         var called = false;
+
         function asyncValidator(val, respond) {
           called = true;
-          setTimeout(function() {
-            respond( val == 'async' );
+          setTimeout(function () {
+            respond(val == 'async');
           }, 0);
         }
 
         var Sub = new mongoose.Schema({
-          title: { type: String, required: true },
-          sync: { type: String, validate: [ syncValidator, asyncValidator ] },
-          async: { type: String, validate: asyncValidator }
+          title: {type: String, required: true},
+          sync: {type: String, validate: [syncValidator, asyncValidator]},
+          async: {type: String, validate: asyncValidator}
         });
         var SubsSchema = new mongoose.Schema({
-          subs: [ Sub ]
+          subs: [Sub]
         });
 
         var doc = new mongoose.Document({
@@ -680,7 +689,7 @@ describe('schema', function() {
         }, SubsSchema);
 
         var err = doc.validateSync();
-        assert.ok( err instanceof mongoose.Error.ValidationError );
+        assert.ok(err instanceof mongoose.Error.ValidationError);
         assert.equal('title', err.errors['subs.0.title'].path);
 
 
@@ -691,7 +700,7 @@ describe('schema', function() {
         }, SubsSchema);
 
         var err1 = doc1.validateSync();
-        assert.ok( err1 instanceof mongoose.Error.ValidationError );
+        assert.ok(err1 instanceof mongoose.Error.ValidationError);
         assert.equal('title', err1.errors['subs.1.title'].path);
 
 
@@ -702,7 +711,7 @@ describe('schema', function() {
             title: 'title2'
           }]
         }, SubsSchema);
-        assert.ifError( doc2.validateSync() );
+        assert.ifError(doc2.validateSync());
 
 
         var doc3 = new mongoose.Document({
@@ -715,7 +724,7 @@ describe('schema', function() {
         }, SubsSchema);
 
         var err3 = doc3.validateSync();
-        assert.ok( err3 instanceof mongoose.Error.ValidationError );
+        assert.ok(err3 instanceof mongoose.Error.ValidationError);
         assert.equal('Validator failed for path `sync` with value `fail`', err3.errors['subs.0.sync'].message);
 
 
@@ -732,9 +741,9 @@ describe('schema', function() {
         }, SubsSchema);
 
         var err4 = doc4.validateSync();
-        assert.ok( err4 instanceof mongoose.Error.ValidationError );
-        assert.equal( err4.errors['subs.0.sync'], undefined );
-        assert.ok( err4.errors['subs.1.sync'] );
+        assert.ok(err4 instanceof mongoose.Error.ValidationError);
+        assert.equal(err4.errors['subs.0.sync'], undefined);
+        assert.ok(err4.errors['subs.1.sync']);
 
 
         assert.equal(false, called);
@@ -742,10 +751,10 @@ describe('schema', function() {
         done();
       });
 
-      it('string enum', function(done) {
+      it('string enum', function (done) {
         var Test = new Schema({
-          complex: { type: String, enum: ['a', 'b', undefined, 'c', null] },
-          state: { type: String }
+          complex: {type: String, enum: ['a', 'b', undefined, 'c', null]},
+          state: {type: String}
         });
 
         // with SchemaTypes validate method
@@ -767,9 +776,9 @@ describe('schema', function() {
         done();
       });
 
-      it('string regexp', function(done) {
+      it('string regexp', function (done) {
         var Test = new Schema({
-          simple: { type: String, match: /[a-z]/ }
+          simple: {type: String, match: /[a-z]/}
         });
 
         assert.ifError(Test.path('simple').doValidateSync('az'));
@@ -790,9 +799,9 @@ describe('schema', function() {
         done();
       });
 
-      it('number min and max', function(done) {
+      it('number min and max', function (done) {
         var Tobi = new Schema({
-          friends: { type: Number, max: 15, min: 5 }
+          friends: {type: Number, max: 15, min: 5}
         });
 
         assert.ifError(Tobi.path('friends').doValidateSync(10));
@@ -810,8 +819,8 @@ describe('schema', function() {
         done();
       });
 
-      describe('required', function() {
-        it('string required', function(done) {
+      describe('required', function () {
+        it('string required', function (done) {
           var Test = new Schema({
             simple: String
           });
@@ -826,13 +835,13 @@ describe('schema', function() {
           done();
         });
 
-        it('string conditional required', function(done) {
+        it('string conditional required', function (done) {
           var Test = new Schema({
             simple: String
           });
 
           var required = true,
-              isRequired = function() {
+              isRequired = function () {
                 return required;
               };
 
@@ -853,9 +862,9 @@ describe('schema', function() {
           done();
         });
 
-        it('number required', function(done) {
+        it('number required', function (done) {
           var Edwald = new Schema({
-            friends: { type: Number, required: true }
+            friends: {type: Number, required: true}
           });
 
           assert.ok(Edwald.path('friends').doValidateSync(null) instanceof ValidatorError);
@@ -865,9 +874,9 @@ describe('schema', function() {
           done();
         });
 
-        it('date required', function(done) {
+        it('date required', function (done) {
           var Loki = new Schema({
-            birth_date: { type: Date, required: true }
+            birth_date: {type: Date, required: true}
           });
 
           assert.ok(Loki.path('birth_date').doValidateSync(null) instanceof ValidatorError);
@@ -877,21 +886,21 @@ describe('schema', function() {
           done();
         });
 
-        it('objectid required', function(done) {
+        it('objectid required', function (done) {
           var Loki = new Schema({
-            owner: { type: ObjectId, required: true }
+            owner: {type: ObjectId, required: true}
           });
 
-          assert.ifError(Loki.path('owner').doValidateSync( new DocumentObjectId() ));
+          assert.ifError(Loki.path('owner').doValidateSync(new DocumentObjectId()));
           assert.ok(Loki.path('owner').doValidateSync(null) instanceof ValidatorError);
           assert.ok(Loki.path('owner').doValidateSync(undefined) instanceof ValidatorError);
 
           done();
         });
 
-        it('array required', function(done) {
+        it('array required', function (done) {
           var Loki = new Schema({
-            likes: { type: Array, required: true }
+            likes: {type: Array, required: true}
           });
 
           assert.ok(Loki.path('likes').doValidateSync(null) instanceof ValidatorError);
@@ -901,9 +910,9 @@ describe('schema', function() {
           done();
         });
 
-        it('boolean required', function(done) {
+        it('boolean required', function (done) {
           var Animal = new Schema({
-            isFerret: { type: Boolean, required: true }
+            isFerret: {type: Boolean, required: true}
           });
 
           assert.ok(Animal.path('isFerret').doValidateSync(null) instanceof ValidatorError);
@@ -914,14 +923,14 @@ describe('schema', function() {
           done();
         });
 
-        it('mixed required', function(done) {
+        it('mixed required', function (done) {
           var Animal = new Schema({
-            characteristics: { type: Mixed, required: true }
+            characteristics: {type: Mixed, required: true}
           });
 
           assert.ok(Animal.path('characteristics').doValidateSync(null) instanceof ValidatorError);
           assert.ok(Animal.path('characteristics').doValidateSync(undefined) instanceof ValidatorError);
-          assert.ifError(Animal.path('characteristics').doValidateSync( { aggresive: true } ));
+          assert.ifError(Animal.path('characteristics').doValidateSync({aggresive: true}));
           assert.ifError(Animal.path('characteristics').doValidateSync('none available'));
 
           done();
diff --git a/test/browser/types.buffer.test_.js b/test/browser/types.buffer.test_.js
index cc83386f768..e82714da886 100644
--- a/test/browser/types.buffer.test_.js
+++ b/test/browser/types.buffer.test_.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -9,16 +8,15 @@ var MongooseBuffer = mongoose.Types.Buffer;
  * Test.
  */
 
-describe('types.buffer', function() {
-
-  it('test that a mongoose buffer behaves and quacks like a buffer', function(done) {
+describe('types.buffer', function () {
+  it('test that a mongoose buffer behaves and quacks like a buffer', function (done) {
     var a = new MongooseBuffer;
 
     assert.ok(a.isMongooseBuffer);
     assert.equal(true, a.equals(a));
 
     a = new MongooseBuffer([195, 188, 98, 101, 114]);
-    var b = new MongooseBuffer("buffer shtuffs are neat");
+    var b = new MongooseBuffer('buffer shtuffs are neat');
     var c = new MongooseBuffer('aGVsbG8gd29ybGQ=', 'base64');
     var d = new MongooseBuffer(0);
 
@@ -29,8 +27,8 @@ describe('types.buffer', function() {
     done();
   });
 
-  describe('#toObject', function() {
-    it('retains custom subtypes', function(done) {
+  describe('#toObject', function () {
+    it('retains custom subtypes', function (done) {
       var buf = new MongooseBuffer(0);
       var out = buf.toObject(2);
       // validate the drivers Binary type output retains the option
diff --git a/test/browser/types.number.test_.js b/test/browser/types.number.test_.js
index d343f5a10ce..e7854629a9b 100644
--- a/test/browser/types.number.test_.js
+++ b/test/browser/types.number.test_.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -9,21 +8,20 @@ var SchemaNumber = mongoose.Schema.Types.Number;
  * Test.
  */
 
-describe('types.number', function() {
-
-  it('an empty string casts to null', function(done) {
+describe('types.number', function () {
+  it('an empty string casts to null', function (done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.cast(''), null);
     done();
   });
 
-  it('a null number should castForQuery to null', function(done) {
+  it('a null number should castForQuery to null', function (done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.castForQuery(null), null);
     done();
   });
 
-  it('undefined throws number cast error', function(done) {
+  it('undefined throws number cast error', function (done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -35,7 +33,7 @@ describe('types.number', function() {
     done();
   });
 
-  it('array throws cast number error', function(done) {
+  it('array throws cast number error', function (done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -47,7 +45,7 @@ describe('types.number', function() {
     done();
   });
 
-  it('three throws cast number error', function(done) {
+  it('three throws cast number error', function (done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -59,7 +57,7 @@ describe('types.number', function() {
     done();
   });
 
-  it('{} throws cast number error', function(done) {
+  it('{} throws cast number error', function (done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -71,7 +69,7 @@ describe('types.number', function() {
     done();
   });
 
-  it('does not throw number cast error', function(done) {
+  it('does not throw number cast error', function (done) {
     var n = new SchemaNumber();
     var items = [1, '2', '0', null, '', new String('47'), new Number(5), Number(47), Number('09'), 0x12];
     var err;
@@ -85,5 +83,4 @@ describe('types.number', function() {
     assert.strictEqual(false, !!err, err);
     done();
   });
-
 });
diff --git a/test/browser/types.objectid.test_.js b/test/browser/types.objectid.test_.js
index 342b3720cc4..41b284ff529 100644
--- a/test/browser/types.objectid.test_.js
+++ b/test/browser/types.objectid.test_.js
@@ -1,21 +1,20 @@
-/* eslint no-empty: 1 */
-(function() {
+(function () {
   var ObjectId = mongoose.Types.ObjectId;
 
-  describe('types.objectid', function() {
-    it('Should Correctly convert ObjectId to itself', function(done) {
+  describe('types.objectid', function () {
+    it('Should Correctly convert ObjectId to itself', function (done) {
       var myObject, newObject;
-      var selfConvertion = (function() {
+      var selfConvertion = function () {
         myObject = new ObjectId();
         newObject = ObjectId(myObject);
-      });
+      };
 
       assert.doesNotThrow(selfConvertion);
       assert.equal(myObject, newObject);
       done();
     });
 
-    it('ObjectId should correctly create objects', function(done) {
+    it('ObjectId should correctly create objects', function (done) {
       try {
         ObjectId.createFromHexString('000000000000000000000001');
         ObjectId.createFromHexString('00000000000000000000001');
@@ -27,7 +26,7 @@
       done();
     });
 
-    it('ObjectId should correctly retrieve timestamp', function(done) {
+    it('ObjectId should correctly retrieve timestamp', function (done) {
       var testDate = new Date();
       var object1 = new ObjectId();
       assert.equal(Math.floor(testDate.getTime() / 1000), Math.floor(object1.getTimestamp().getTime() / 1000));
@@ -35,7 +34,7 @@
       done();
     });
 
-    it('ObjectId should have a correct cached representation of the hexString', function(done) {
+    it('ObjectId should have a correct cached representation of the hexString', function (done) {
       ObjectId.cacheHexString = true;
       var a = new ObjectId;
       var __id = a.__id;
@@ -70,25 +69,25 @@
       done();
     });
 
-    it('Should fail to create ObjectId due to illegal hex code', function(done) {
-      try {
-        new ObjectId("zzzzzzzzzzzzzzzzzzzzzzzz");
-        assert.ok(false);
-      } catch (err) {
-      }
+    it('Should fail to create ObjectId due to illegal hex code', function (done) {
+      assert.throws(function () {
+        new ObjectId('zzzzzzzzzzzzzzzzzzzzzzzz');
+      });
+      done();
+    });
 
+    it('Should validate ObjectId', function (done) {
       assert.equal(false, ObjectId.isValid(null));
       assert.equal(false, ObjectId.isValid({}));
       assert.equal(false, ObjectId.isValid([]));
       assert.equal(false, ObjectId.isValid(true));
       assert.equal(true, ObjectId.isValid(0));
-      assert.equal(false, ObjectId.isValid("invalid"));
-      assert.equal(true, ObjectId.isValid("zzzzzzzzzzzz"));
-      assert.equal(false, ObjectId.isValid("zzzzzzzzzzzzzzzzzzzzzzzz"));
-      assert.equal(true, ObjectId.isValid("000000000000000000000000"));
+      assert.equal(false, ObjectId.isValid('invalid'));
+      assert.equal(true, ObjectId.isValid('zzzzzzzzzzzz'));
+      assert.equal(false, ObjectId.isValid('zzzzzzzzzzzzzzzzzzzzzzzz'));
+      assert.equal(true, ObjectId.isValid('000000000000000000000000'));
 
       done();
     });
   });
-
 })();
diff --git a/test/cast.test.js b/test/cast.test.js
index cfa3b1d0e5d..80ffb18338d 100644
--- a/test/cast.test.js
+++ b/test/cast.test.js
@@ -6,33 +6,33 @@ var Schema = require('../lib/schema');
 var assert = require('assert');
 var cast = require('../lib/cast');
 
-describe('cast: ', function() {
-  describe('bitwise query operators: ', function() {
-    it('with a number', function(done) {
-      var schema = new Schema({ x: Buffer });
-      assert.deepEqual(cast(schema, { x: { $bitsAllClear: 3 } }),
-        { x: { $bitsAllClear: 3 } });
+describe('cast: ', function () {
+  describe('bitwise query operators: ', function () {
+    it('with a number', function (done) {
+      var schema = new Schema({x: Buffer});
+      assert.deepEqual(cast(schema, {x: {$bitsAllClear: 3}}),
+        {x: {$bitsAllClear: 3}});
       done();
     });
 
-    it('with an array', function(done) {
-      var schema = new Schema({ x: Buffer });
-      assert.deepEqual(cast(schema, { x: { $bitsAllSet: [2, '3'] } }),
-        { x: { $bitsAllSet: [2, 3] } });
+    it('with an array', function (done) {
+      var schema = new Schema({x: Buffer});
+      assert.deepEqual(cast(schema, {x: {$bitsAllSet: [2, '3']}}),
+        {x: {$bitsAllSet: [2, 3]}});
       done();
     });
 
-    it('with a buffer', function(done) {
-      var schema = new Schema({ x: Number });
-      assert.deepEqual(cast(schema, { x: { $bitsAnyClear: new Buffer([3]) } }),
-        { x: { $bitsAnyClear: new Buffer([3]) } });
+    it('with a buffer', function (done) {
+      var schema = new Schema({x: Number});
+      assert.deepEqual(cast(schema, {x: {$bitsAnyClear: new Buffer([3])}}),
+        {x: {$bitsAnyClear: new Buffer([3])}});
       done();
     });
 
-    it('throws when invalid', function(done) {
-      var schema = new Schema({ x: Number });
-      assert.throws(function() {
-        cast(schema, { x: { $bitsAnySet: 'Not a number' } });
+    it('throws when invalid', function (done) {
+      var schema = new Schema({x: Number});
+      assert.throws(function () {
+        cast(schema, {x: {$bitsAnySet: 'Not a number'}});
       }, /Cast to number failed/);
       done();
     });
diff --git a/test/collection.capped.test.js b/test/collection.capped.test.js
index 2697f4ba72d..30b2c677641 100644
--- a/test/collection.capped.test.js
+++ b/test/collection.capped.test.js
@@ -12,39 +12,39 @@ var start = require('./common'),
 /**
  * setup
  */
-var capped = new Schema({ key: 'string', val: 'number' });
-capped.set('capped', { size: 1000 });
+var capped = new Schema({key: 'string', val: 'number'});
+capped.set('capped', {size: 1000});
 var coll = 'capped_' + random();
 
 /**
  * Test.
  */
 
-describe('collections: capped:', function() {
+describe('collections: capped:', function () {
   var db;
 
-  before(function() {
+  before(function () {
     db = start();
   });
 
-  after(function(done) {
+  after(function (done) {
     db.close(done);
   });
 
-  it('schemas should have option size', function(done) {
+  it('schemas should have option size', function (done) {
     assert.ok(capped.options.capped);
     assert.equal(1000, capped.options.capped.size);
     done();
   });
-  it('creation', function(done) {
+  it('creation', function (done) {
     var Capped = db.model('Capped', capped, coll);
-    Capped.collection.isCapped(function(err, isCapped) {
+    Capped.collection.isCapped(function (err, isCapped) {
       assert.ifError(err);
       assert.ok(isCapped, 'should create a capped collection');
 
       // use the existing capped collection in the db (no coll creation)
       var Capped2 = db.model('Capped2', capped, coll);
-      Capped2.collection.isCapped(function(err, isCapped) {
+      Capped2.collection.isCapped(function (err, isCapped) {
         assert.ifError(err);
         assert.ok(isCapped, 'should reuse the capped collection in the db');
         assert.equal(Capped.collection.name, Capped2.collection.name);
@@ -52,29 +52,29 @@ describe('collections: capped:', function() {
       });
     });
   });
-  it('creation using a number', function(done) {
-    var schema = new Schema({ key: 'string' }, { capped: 8192 });
+  it('creation using a number', function (done) {
+    var schema = new Schema({key: 'string'}, {capped: 8192});
     var Capped = db.model('Capped3', schema);
-    Capped.collection.options(function(err, options) {
+    Capped.collection.options(function (err, options) {
       assert.ifError(err);
       assert.ok(options.capped, 'should create a capped collection');
       assert.equal(8192, options.size);
       done();
     });
   });
-  it('attempting to use existing non-capped collection as capped emits error', function(done) {
+  it('attempting to use existing non-capped collection as capped emits error', function (done) {
     var db = start();
-    var opts = { safe: true };
+    var opts = {safe: true};
     var conn = 'capped_existing_' + random();
 
-    db.on('open', function() {
-      db.db.createCollection(conn, opts, function(err) {
+    db.on('open', function () {
+      db.db.createCollection(conn, opts, function (err) {
         if (err) db.close();
         assert.ifError(err);
 
         var timer;
 
-        db.on('error', function(err) {
+        db.on('error', function (err) {
           clearTimeout(timer);
           db.close();
           assert.ok(/non-capped collection exists/.test(err));
@@ -82,7 +82,7 @@ describe('collections: capped:', function() {
         });
 
         db.model('CappedExisting', capped, conn);
-        timer = setTimeout(function() {
+        timer = setTimeout(function () {
           db.close();
           throw new Error('capped test timeout');
         }, 900);
diff --git a/test/collection.test.js b/test/collection.test.js
index 37363406aa9..e392fbbc026 100644
--- a/test/collection.test.js
+++ b/test/collection.test.js
@@ -4,8 +4,8 @@ var start = require('./common'),
     assert = require('assert'),
     Collection = require('../lib/collection');
 
-describe('collections:', function() {
-  it('should buffer commands until connection is established', function(done) {
+describe('collections:', function () {
+  it('should buffer commands until connection is established', function (done) {
     var db = mongoose.createConnection(),
         collection = db.collection('test-buffering-collection'),
         connected = false,
@@ -19,7 +19,7 @@ describe('collections:', function() {
       done();
     }
 
-    collection.insert({ }, { safe: true }, function() {
+    collection.insert({ }, {safe: true}, function () {
       assert.ok(connected);
       inserted = true;
       db.close();
@@ -27,13 +27,13 @@ describe('collections:', function() {
     });
 
     var uri = 'mongodb://localhost/mongoose_test';
-    db.open(process.env.MONGOOSE_TEST_URI || uri, function(err) {
+    db.open(process.env.MONGOOSE_TEST_URI || uri, function (err) {
       connected = !err;
       finish();
     });
   });
 
-  it('methods should that throw (unimplemented)', function(done) {
+  it('methods should that throw (unimplemented)', function (done) {
     var collection = new Collection('test', mongoose.connection),
         thrown = false;
 
diff --git a/test/colors.js b/test/colors.js
index ce31c5c7f25..07502ac2d1c 100644
--- a/test/colors.js
+++ b/test/colors.js
@@ -24,7 +24,7 @@ var test = Schema({
 });
 
 function TestDoc(schema) {
-  var Subdocument = function() {
+  var Subdocument = function () {
     EmbeddedDocument.call(this, {}, new DocumentArray);
   };
 
@@ -47,21 +47,20 @@ function TestDoc(schema) {
  * Test.
  */
 
-describe('debug: colors', function() {
+describe('debug: colors', function () {
   var db;
   var Test;
 
-  before(function() {
+  before(function () {
     db = start();
     Test = db.model('Test', test, 'TEST');
   });
 
-  after(function(done) {
+  after(function (done) {
     db.close(done);
   });
 
-  it('Document', function(done) {
-
+  it('Document', function (done) {
     var date = new Date();
 
     Test.create([{
@@ -76,12 +75,12 @@ describe('debug: colors', function() {
       string: 'zxcvbn',
       number: 789,
       date: date
-    }], function(err) {
+    }], function (err) {
       assert.ifError(err);
       Test
         .find()
         .lean(false)
-        .exec(function(err, docs) {
+        .exec(function (err, docs) {
           assert.ifError(err);
 
           var colorfull = require('util').inspect(docs, {
@@ -103,8 +102,7 @@ describe('debug: colors', function() {
     });
   });
 
-  it('MongooseDocumentArray', function() {
-
+  it('MongooseDocumentArray', function () {
     var Subdocument = TestDoc();
 
     var sub1 = new Subdocument();
@@ -127,7 +125,5 @@ describe('debug: colors', function() {
     // console.log(colorfull, colorless);
 
     assert.notEqual(colorfull, colorless);
-
   });
-
 });
diff --git a/test/common.js b/test/common.js
index 6da92ff937d..28eeea522fd 100644
--- a/test/common.js
+++ b/test/common.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -10,8 +9,9 @@ var mongoose = require('../'),
     opened = 0,
     closed = 0;
 
-if (process.env.D === '1')
+if (process.env.D === '1') {
   mongoose.set('debug', true);
+}
 
 /**
  * Override all Collection related queries to keep count
@@ -30,15 +30,13 @@ if (process.env.D === '1')
   'distinct',
   'isCapped',
   'options'
-].forEach(function(method) {
-
+].forEach(function (method) {
   var oldMethod = Collection.prototype[method];
 
-  Collection.prototype[method] = function() {
+  Collection.prototype[method] = function () {
     queryCount++;
     return oldMethod.apply(this, arguments);
   };
-
 });
 
 /**
@@ -47,7 +45,7 @@ if (process.env.D === '1')
 
 var oldOnOpen = Collection.prototype.onOpen;
 
-Collection.prototype.onOpen = function() {
+Collection.prototype.onOpen = function () {
   opened++;
   return oldOnOpen.apply(this, arguments);
 };
@@ -58,7 +56,7 @@ Collection.prototype.onOpen = function() {
 
 var oldOnClose = Collection.prototype.onClose;
 
-Collection.prototype.onClose = function() {
+Collection.prototype.onClose = function () {
   closed++;
   return oldOnClose.apply(this, arguments);
 };
@@ -70,7 +68,7 @@ Collection.prototype.onClose = function() {
  * @api private
  */
 
-module.exports = function(options) {
+module.exports = function (options) {
   options || (options = {});
   var uri;
 
@@ -86,9 +84,11 @@ module.exports = function(options) {
 
   var conn = mongoose.createConnection(uri, options);
 
-  if (noErrorListener) return conn;
+  if (noErrorListener) {
+    return conn;
+  }
 
-  conn.on('error', function(err) {
+  conn.on('error', function (err) {
     assert.ok(err);
   });
 
@@ -111,16 +111,20 @@ module.exports.mongoose = mongoose;
  * expose mongod version helper
  */
 
-module.exports.mongodVersion = function(cb) {
+module.exports.mongodVersion = function (cb) {
   var db = module.exports();
   db.on('error', cb);
 
-  db.on('open', function() {
+  db.on('open', function () {
     var admin = db.db.admin();
-    admin.serverStatus(function(err, info) {
-      if (err) return cb(err);
-      var version = info.version.split('.').map(function(n) { return parseInt(n, 10); });
-      db.close(function() {
+    admin.serverStatus(function (err, info) {
+      if (err) {
+        return cb(err);
+      }
+      var version = info.version.split('.').map(function (n) {
+        return parseInt(n, 10);
+      });
+      db.close(function () {
         cb(null, version);
       });
     });
@@ -129,18 +133,20 @@ module.exports.mongodVersion = function(cb) {
 
 function dropDBs(done) {
   var db = module.exports();
-  db.once('open', function() {
+  db.once('open', function () {
     // drop the default test database
-    db.db.dropDatabase(function() {
+    db.db.dropDatabase(function () {
       var db2 = db.useDb('mongoose-test-2');
-      db2.db.dropDatabase(function() {
+      db2.db.dropDatabase(function () {
         // drop mongos test db if exists
         var mongos = process.env.MONGOOSE_MULTI_MONGOS_TEST_URI;
-        if (!mongos) return done();
+        if (!mongos) {
+          return done();
+        }
 
 
-        var db = mongoose.connect(mongos, {mongos: true });
-        db.once('open', function() {
+        var db = mongoose.connect(mongos, {mongos: true});
+        db.once('open', function () {
           db.db.dropDatabase(done);
         });
       });
@@ -148,11 +154,11 @@ function dropDBs(done) {
   });
 }
 
-before(function(done) {
+before(function (done) {
   this.timeout(10 * 1000);
   dropDBs(done);
 });
-after(function(done) {
+after(function (done) {
   // DropDBs can be extraordinarily slow on 3.2
   this.timeout(120 * 1000);
   dropDBs(done);
diff --git a/test/connection.auth.test.js b/test/connection.auth.test.js
index 20bef230c16..154fcc86f7b 100644
--- a/test/connection.auth.test.js
+++ b/test/connection.auth.test.js
@@ -3,12 +3,11 @@ var start = require('./common');
 var mongoose = start.mongoose;
 var assert = require('assert');
 
-describe('connection:', function() {
-  describe('supports authSource', function() {
-
-    it('in querystring', function(done) {
+describe('connection:', function () {
+  describe('supports authSource', function () {
+    it('in querystring', function (done) {
       var conn = mongoose.createConnection();
-      conn._open = function() {
+      conn._open = function () {
         assert.ok(conn.options);
         assert.ok(conn.options.auth);
         assert.equal('users', conn.options.auth.authSource);
@@ -17,15 +16,15 @@ describe('connection:', function() {
       conn.open(start.uri + '?authSource=users');
     });
 
-    it('passed as an option', function(done) {
+    it('passed as an option', function (done) {
       var conn = mongoose.createConnection();
-      conn._open = function() {
+      conn._open = function () {
         assert.ok(conn.options);
         assert.ok(conn.options.auth);
         assert.equal('users', conn.options.auth.authSource);
         conn.close(done);
       };
-      conn.open(start.uri, { auth: { authSource: 'users' }});
+      conn.open(start.uri, {auth: {authSource: 'users'}});
     });
   });
 });
diff --git a/test/connection.reconnect.test.js b/test/connection.reconnect.test.js
index c60b5e09e86..b8aaec8ad24 100644
--- a/test/connection.reconnect.test.js
+++ b/test/connection.reconnect.test.js
@@ -2,8 +2,8 @@
 var start = require('./common');
 var mongoose = start.mongoose;
 
-describe('connection: manual reconnect with authReconnect: false', function() {
-  it('should continue processing queries/writes', function(done) {
+describe('connection: manual reconnect with authReconnect: false', function () {
+  it('should continue processing queries/writes', function (done) {
     // connect to mongod
     // perform writes/queries
     // take mongod down
@@ -13,31 +13,31 @@ describe('connection: manual reconnect with authReconnect: false', function() {
 
     var db = mongoose.createConnection();
 
-    db.open(start.uri, { server: { auto_reconnect: false }});
+    db.open(start.uri, {server: {auto_reconnect: false}});
 
-    var M = db.model('autoReconnect', { name: String });
+    var M = db.model('autoReconnect', {name: String});
 
     var open = false;
     var times = 0;
 
-    db.on('open', function() {
+    db.on('open', function () {
       ++times;
       open = true;
       hit();
     });
 
-    db.on('disconnected', function() {
+    db.on('disconnected', function () {
       open = false;
-      setTimeout(function() {
-        db.open(start.uri, { server: { auto_reconnect: false }});
+      setTimeout(function () {
+        db.open(start.uri, {server: {auto_reconnect: false}});
       }, 30);
     });
 
     function hit() {
       if (!open) return;
-      M.create({ name: times }, function(err, doc) {
+      M.create({name: times}, function (err, doc) {
         if (err) return complete(err);
-        M.findOne({ _id: doc._id }, function(err) {
+        M.findOne({_id: doc._id}, function (err) {
           if (err) return complete(err);
           if (times > 1) {
             return complete();
@@ -52,7 +52,7 @@ describe('connection: manual reconnect with authReconnect: false', function() {
     }
 
     function complete(err) {
-      if (complete.ran) return ;
+      if (complete.ran) return;
       complete.ran = 1;
       done(err);
     }
diff --git a/test/connection.test.js b/test/connection.test.js
index b747c316c42..b619e7269fa 100644
--- a/test/connection.test.js
+++ b/test/connection.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -13,17 +12,18 @@ var start = require('./common'),
  * Test.
  */
 
-describe('connections:', function() {
-  it('should allow closing a closed connection', function(done) {
+describe('connections:', function () {
+  it('should allow closing a closed connection', function (done) {
     var db = mongoose.createConnection();
 
     assert.equal(0, db.readyState);
     db.close(done);
   });
 
-  it('should accept mongodb://localhost/fake', function(done) {
+  it('should accept mongodb://localhost/fake', function (done) {
     var db = mongoose.createConnection('mongodb://localhost/fake');
-    db.on('error', function() {});
+    db.on('error', function () {
+    });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
     assert.equal(true, db.options.server.auto_reconnect);
@@ -37,9 +37,10 @@ describe('connections:', function() {
     db.close(done);
   });
 
-  it('should accept replicaSet query param', function(done) {
+  it('should accept replicaSet query param', function (done) {
     var db = mongoose.createConnection('mongodb://localhost/fake?replicaSet=rs0');
-    db.on('error', function() {});
+    db.on('error', function () {
+    });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
     assert.equal(true, db.options.server.auto_reconnect);
@@ -48,7 +49,7 @@ describe('connections:', function() {
     assert.equal(undefined, db.pass);
     assert.equal(undefined, db.user);
     assert.equal('fake', db.name);
-    assert.deepEqual([{ host: 'localhost', port: 27017 }], db.hosts);
+    assert.deepEqual([{host: 'localhost', port: 27017}], db.hosts);
 
     // Should be a replica set
     assert.ok(db.replica);
@@ -56,9 +57,10 @@ describe('connections:', function() {
     done();
   });
 
-  it('should accept mongodb://localhost:27000/fake', function(done) {
+  it('should accept mongodb://localhost:27000/fake', function (done) {
     var db = mongoose.createConnection('mongodb://localhost:27000/fake');
-    db.on('error', function() {});
+    db.on('error', function () {
+    });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
     assert.equal(true, db.options.server.auto_reconnect);
@@ -68,9 +70,10 @@ describe('connections:', function() {
     done();
   });
 
-  it('should accept mongodb://aaron:psw@localhost:27000/fake', function(done) {
+  it('should accept mongodb://aaron:psw@localhost:27000/fake', function (done) {
     var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake');
-    db.on('error', function() {});
+    db.on('error', function () {
+    });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
     assert.equal(true, db.options.server.auto_reconnect);
@@ -85,9 +88,10 @@ describe('connections:', function() {
     done();
   });
 
-  it('should accept mongodb://aaron:psw@localhost:27000/fake with db options', function(done) {
-    var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', { db: { forceServerObjectId: true }});
-    db.on('error', function() {});
+  it('should accept mongodb://aaron:psw@localhost:27000/fake with db options', function (done) {
+    var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {db: {forceServerObjectId: true}});
+    db.on('error', function () {
+    });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
     assert.equal(true, db.options.server.auto_reconnect);
@@ -97,9 +101,10 @@ describe('connections:', function() {
     done();
   });
 
-  it('should accept mongodb://aaron:psw@localhost:27000/fake with server options', function(done) {
-    var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', { server: { auto_reconnect: false }});
-    db.on('error', function() {});
+  it('should accept mongodb://aaron:psw@localhost:27000/fake with server options', function (done) {
+    var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {server: {auto_reconnect: false}});
+    db.on('error', function () {
+    });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
     assert.equal(false, db.options.server.auto_reconnect);
@@ -109,9 +114,10 @@ describe('connections:', function() {
     done();
   });
 
-  it('should accept unix domain sockets', function(done) {
-    var db = mongoose.createConnection('mongodb://aaron:psw@/tmp/mongodb-27017.sock/fake', { server: { auto_reconnect: false }});
-    db.on('error', function() {});
+  it('should accept unix domain sockets', function (done) {
+    var db = mongoose.createConnection('mongodb://aaron:psw@/tmp/mongodb-27017.sock/fake', {server: {auto_reconnect: false}});
+    db.on('error', function () {
+    });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
     assert.equal(false, db.options.server.auto_reconnect);
@@ -125,32 +131,40 @@ describe('connections:', function() {
     done();
   });
 
-  describe('re-opening a closed connection', function() {
+  describe('re-opening a closed connection', function () {
     var mongos = process.env.MONGOOSE_SHARD_TEST_URI;
-    if (!mongos) return;
+    if (!mongos) {
+      return;
+    }
 
     var mongod = 'mongodb://localhost:27017';
 
     var repl1 = process.env.MONGOOSE_SET_TEST_URI;
-    var repl2 = repl1.replace("mongodb://", "").split(',');
+    var repl2 = repl1.replace('mongodb://', '').split(',');
     repl2.push(repl2.shift());
-    repl2 = "mongodb://" + repl2.join(',');
+    repl2 = 'mongodb://' + repl2.join(',');
 
-    describe('with different host/port', function() {
-      it('non-replica set', function(done) {
+    describe('with different host/port', function () {
+      it('non-replica set', function (done) {
         var db = mongoose.createConnection();
 
-        db.open(mongod, function(err) {
-          if (err) return done(err);
+        db.open(mongod, function (err) {
+          if (err) {
+            return done(err);
+          }
 
           var port1 = db.port;
           var db1 = db.db;
 
-          db.close(function(err) {
-            if (err) return done(err);
+          db.close(function (err) {
+            if (err) {
+              return done(err);
+            }
 
-            db.open(mongos, function(err) {
-              if (err) return done(err);
+            db.open(mongos, function (err) {
+              if (err) {
+                return done(err);
+              }
 
               assert.notEqual(port1, db.port);
               assert.ok(db1 !== db.db);
@@ -159,10 +173,14 @@ describe('connections:', function() {
               var port2 = db.port;
               var db2 = db.db;
 
-              db.close(function(err) {
-                if (err) return done(err);
-                db.open(mongod, function(err) {
-                  if (err) return done(err);
+              db.close(function (err) {
+                if (err) {
+                  return done(err);
+                }
+                db.open(mongod, function (err) {
+                  if (err) {
+                    return done(err);
+                  }
 
                   assert.notEqual(port2, db.port);
                   assert.ok(db2 !== db.db);
@@ -176,22 +194,28 @@ describe('connections:', function() {
         });
       });
 
-      it('replica set', function(done) {
+      it('replica set', function (done) {
         var db = mongoose.createConnection();
 
-        db.openSet(repl1, function(err) {
-          if (err) return done(err);
+        db.openSet(repl1, function (err) {
+          if (err) {
+            return done(err);
+          }
 
           var hosts = db.hosts.slice();
           var db1 = db.db;
 
-          db.close(function(err) {
-            if (err) return done(err);
+          db.close(function (err) {
+            if (err) {
+              return done(err);
+            }
 
-            db.openSet(repl2, function(err) {
-              if (err) return done(err);
+            db.openSet(repl2, function (err) {
+              if (err) {
+                return done(err);
+              }
 
-              db.hosts.forEach(function(host, i) {
+              db.hosts.forEach(function (host, i) {
                 assert.notEqual(host.port, hosts[i].port);
               });
               assert.ok(db1 !== db.db);
@@ -199,13 +223,17 @@ describe('connections:', function() {
               hosts = db.hosts.slice();
               var db2 = db.db;
 
-              db.close(function(err) {
-                if (err) return done(err);
+              db.close(function (err) {
+                if (err) {
+                  return done(err);
+                }
 
-                db.openSet(repl1, function(err) {
-                  if (err) return done(err);
+                db.openSet(repl1, function (err) {
+                  if (err) {
+                    return done(err);
+                  }
 
-                  db.hosts.forEach(function(host, i) {
+                  db.hosts.forEach(function (host, i) {
                     assert.notEqual(host.port, hosts[i].port);
                   });
                   assert.ok(db2 !== db.db);
@@ -221,10 +249,11 @@ describe('connections:', function() {
     });
   });
 
-  describe('should accept separated args with options', function() {
-    it('works', function(done) {
-      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, { server: { auto_reconnect: true }});
-      db.on('error', function() {});
+  describe('should accept separated args with options', function () {
+    it('works', function (done) {
+      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, {server: {auto_reconnect: true}});
+      db.on('error', function () {
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -235,8 +264,9 @@ describe('connections:', function() {
       assert.equal(28000, db.port);
       db.close();
 
-      db = mongoose.createConnection('127.0.0.1', 'faker', { blah: 1 });
-      db.on('error', function() {});
+      db = mongoose.createConnection('127.0.0.1', 'faker', {blah: 1});
+      db.on('error', function () {
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -250,9 +280,10 @@ describe('connections:', function() {
       done();
     });
 
-    it('including user/pass', function(done) {
+    it('including user/pass', function (done) {
       var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'aaron', pass: 'psw'});
-      db.on('error', function() {});
+      db.on('error', function () {
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -267,9 +298,10 @@ describe('connections:', function() {
       done();
     });
 
-    it('but fails when passing user and no pass with standard authentication', function(done) {
+    it('but fails when passing user and no pass with standard authentication', function (done) {
       var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'no_pass'});
-      db.on('error', function() {});
+      db.on('error', function () {
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -284,9 +316,10 @@ describe('connections:', function() {
       done();
     });
 
-    it('but passes when passing user and no pass with the MONGODB-X509 authMechanism', function(done) {
+    it('but passes when passing user and no pass with the MONGODB-X509 authMechanism', function (done) {
       var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'no_pass', auth: {authMechanism: 'MONGODB-X509'}});
-      db.on('error', function() {});
+      db.on('error', function () {
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -302,10 +335,11 @@ describe('connections:', function() {
     });
   });
 
-  describe('should accept separated args without options', function() {
-    it('works', function(done) {
+  describe('should accept separated args without options', function () {
+    it('works', function (done) {
       var db = mongoose.createConnection('127.0.0.1', 'faker', 28001);
-      db.on('error', function() {});
+      db.on('error', function () {
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -317,7 +351,8 @@ describe('connections:', function() {
       db.close();
 
       db = mongoose.createConnection('127.0.0.1', 'faker');
-      db.on('error', function() {});
+      db.on('error', function () {
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -329,9 +364,10 @@ describe('connections:', function() {
       db.close();
       done();
     });
-    it('and accept user/pass in hostname', function(done) {
+    it('and accept user/pass in hostname', function (done) {
       var db = mongoose.createConnection('aaron:psw@localhost', 'fake', 27000);
-      db.on('error', function() {});
+      db.on('error', function () {
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -347,18 +383,19 @@ describe('connections:', function() {
     });
   });
 
-  describe('querystring options', function() {
-    describe('for replica sets', function() {
-      it('work', function(done) {
+  describe('querystring options', function () {
+    describe('for replica sets', function () {
+      it('work', function (done) {
         var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2'
-                 + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
-                 + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true'
-                 + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true'
-                 + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags='
-                 + 'dc:ny,rack:1&readPreferenceTags=dc:sf';
+            + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
+            + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true'
+            + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true'
+            + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags='
+            + 'dc:ny,rack:1&readPreferenceTags=dc:sf';
 
         var db = mongoose.createConnection(conn);
-        db.on('error', function() {});
+        db.on('error', function () {
+        });
         db.close();
         assert.equal('object', typeof db.options);
         assert.equal('object', typeof db.options.server);
@@ -386,20 +423,21 @@ describe('connections:', function() {
         assert.equal(true, db.options.db.journal);
         assert.equal(80, db.options.db.wtimeoutMS);
         assert.equal('nearest', db.options.db.readPreference);
-        assert.deepEqual([{ dc: 'ny', rack: 1 }, { dc: 'sf' }], db.options.db.read_preference_tags);
+        assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags);
         assert.equal(false, db.options.db.forceServerObjectId);
         done();
       });
-      it('mixed with passed options', function(done) {
+      it('mixed with passed options', function (done) {
         var conn = 'mongodb://localhost/fake?poolSize=2'
-                 + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
-                 + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true'
-                 + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true'
-                 + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags='
-                 + 'dc:ny,rack:1&readPreferenceTags=dc:sf';
-
-        var db = mongoose.createConnection(conn, { server: { poolSize: 3, auto_reconnect: false }});
-        db.on('error', function() {});
+            + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
+            + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true'
+            + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true'
+            + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags='
+            + 'dc:ny,rack:1&readPreferenceTags=dc:sf';
+
+        var db = mongoose.createConnection(conn, {server: {poolSize: 3, auto_reconnect: false}});
+        db.on('error', function () {
+        });
         db.close();
         assert.equal('object', typeof db.options);
         assert.equal('object', typeof db.options.server);
@@ -427,22 +465,23 @@ describe('connections:', function() {
         assert.equal(true, db.options.db.journal);
         assert.equal(80, db.options.db.wtimeoutMS);
         assert.equal('nearest', db.options.db.readPreference);
-        assert.deepEqual([{ dc: 'ny', rack: 1 }, { dc: 'sf' }], db.options.db.read_preference_tags);
+        assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags);
         assert.equal(false, db.options.db.forceServerObjectId);
 
         done();
       });
     });
-    describe('for non replica sets', function() {
-      it('work', function(done) {
+    describe('for non replica sets', function () {
+      it('work', function (done) {
         var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2'
-                 + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
-                 + '&retries=10&reconnectWait=5&readSecondary=true'
-                 + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true'
-                 + '&wtimeoutMS=80&';
+            + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
+            + '&retries=10&reconnectWait=5&readSecondary=true'
+            + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true'
+            + '&wtimeoutMS=80&';
 
         var db = mongoose.createConnection(conn);
-        db.on('error', function() {});
+        db.on('error', function () {
+        });
         db.close();
         assert.equal('object', typeof db.options);
         assert.equal('object', typeof db.options.server);
@@ -471,14 +510,15 @@ describe('connections:', function() {
         assert.equal(false, db.options.db.forceServerObjectId);
         done();
       });
-      it('mixed with passed options', function(done) {
+      it('mixed with passed options', function (done) {
         var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2'
-                 + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
-                 + '&retries=10&reconnectWait=5&readSecondary=true'
-                 + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true';
+            + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
+            + '&retries=10&reconnectWait=5&readSecondary=true'
+            + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true';
 
-        var db = mongoose.createConnection(conn, { db: { w: 3, wtimeoutMS: 80 }});
-        db.on('error', function() {});
+        var db = mongoose.createConnection(conn, {db: {w: 3, wtimeoutMS: 80}});
+        db.on('error', function () {
+        });
         db.close();
         assert.equal('object', typeof db.options);
         assert.equal('object', typeof db.options.server);
@@ -510,21 +550,22 @@ describe('connections:', function() {
     });
   });
 
-  describe('missing protocols', function() {
-    it('are allowed with replsets', function(done) {
-      var conn = mongoose.createConnection('localhost:12345,127.0.0.1:14326?replicaSet=bacon', function(err) {
+  describe('missing protocols', function () {
+    it('are allowed with replsets', function (done) {
+      var conn = mongoose.createConnection('localhost:12345,127.0.0.1:14326?replicaSet=bacon', function (err) {
         // force missing db error so we don't actually connect.
         assert.ok(err);
       });
-      assert.deepEqual([{host:'localhost', port:12345},{host:'127.0.0.1',port:14326}], conn.hosts);
+      assert.deepEqual([{host: 'localhost', port: 12345}, {host: '127.0.0.1', port: 14326}], conn.hosts);
       assert.deepEqual(null, conn.host);
       assert.deepEqual(null, conn.port);
       setTimeout(done, 10);
     });
 
-    it('are allowed with single connections', function(done) {
+    it('are allowed with single connections', function (done) {
       var conn = mongoose.createConnection();
-      conn.doOpen = function() {};
+      conn.doOpen = function () {
+      };
       conn.open('localhost:12345/woot');
       assert.deepEqual('localhost', conn.host);
       assert.deepEqual(12345, conn.port);
@@ -532,12 +573,14 @@ describe('connections:', function() {
     });
   });
 
-  describe('connect callbacks', function() {
-    it('execute with user:pwd connection strings', function(done) {
-      var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', { server: { auto_reconnect: true }}, function() {
+  describe('connect callbacks', function () {
+    it('execute with user:pwd connection strings', function (done) {
+      var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {server: {auto_reconnect: true}}, function () {
         done();
       });
-      db.on('error', function(err) { assert.ok(err); });
+      db.on('error', function (err) {
+        assert.ok(err);
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -545,9 +588,12 @@ describe('connections:', function() {
       assert.equal(false, db.options.db.forceServerObjectId);
       db.close();
     });
-    it('execute without user:pwd connection strings', function(done) {
-      var db = mongoose.createConnection('mongodb://localhost/fake', function() {});
-      db.on('error', function(err) { assert.ok(err); });
+    it('execute without user:pwd connection strings', function (done) {
+      var db = mongoose.createConnection('mongodb://localhost/fake', function () {
+      });
+      db.on('error', function (err) {
+        assert.ok(err);
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(true, db.options.server.auto_reconnect);
@@ -558,18 +604,18 @@ describe('connections:', function() {
       assert.equal('localhost', db.host);
       assert.equal(27017, db.port);
       db.close();
-      setTimeout(done,10);
+      setTimeout(done, 10);
     });
-    it('should return an error if malformed uri passed', function(done) {
-      var db = mongoose.createConnection('mongodb:///fake', function(err) {
+    it('should return an error if malformed uri passed', function (done) {
+      var db = mongoose.createConnection('mongodb:///fake', function (err) {
         assert.ok(/Missing hostname/.test(err.message));
         done();
       });
       db.close();
       assert.ok(!db.options);
     });
-    it('should use admin db if not specified and user/pass specified', function(done) {
-      var db = mongoose.createConnection('mongodb://u:p@localhost', function() {
+    it('should use admin db if not specified and user/pass specified', function (done) {
+      var db = mongoose.createConnection('mongodb://u:p@localhost', function () {
         done();
       });
       assert.equal('object', typeof db.options);
@@ -582,8 +628,8 @@ describe('connections:', function() {
       assert.equal(27017, db.port);
       db.close();
     });
-    it('should fire when individual args are passed', function(done) {
-      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, { server: { auto_reconnect: false }}, function() {
+    it('should fire when individual args are passed', function (done) {
+      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, {server: {auto_reconnect: false}}, function () {
         done();
       });
       assert.equal('object', typeof db.options);
@@ -596,8 +642,8 @@ describe('connections:', function() {
       assert.equal(28000, db.port);
       db.close();
     });
-    it('should fire when no options are passed', function(done) {
-      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, function() {
+    it('should fire when no options are passed', function (done) {
+      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, function () {
         done();
       });
       assert.equal('object', typeof db.options);
@@ -610,7 +656,7 @@ describe('connections:', function() {
       assert.equal(28000, db.port);
       db.close();
     });
-    it('should fire when default port utilized', function(done) {
+    it('should fire when default port utilized', function (done) {
       var db = mongoose.createConnection('127.0.0.1', 'faker', done);
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -624,20 +670,20 @@ describe('connections:', function() {
     });
   });
 
-  describe('errors', function() {
-    it('event fires with one listener', function(done) {
+  describe('errors', function () {
+    it('event fires with one listener', function (done) {
       this.timeout(1000);
-      var db = start({ uri: 'mongodb://whatever23939.localhost/fakeeee?connectTimeoutMS=500', noErrorListener: 1 });
-      db.on('error', function() {
+      var db = start({uri: 'mongodb://whatever23939.localhost/fakeeee?connectTimeoutMS=500', noErrorListener: 1});
+      db.on('error', function () {
         // this callback has no params which triggered the bug #759
         db.close();
         done();
       });
     });
 
-    it('should occur without hanging when password with special chars is used (gh-460)', function(done) {
+    it('should occur without hanging when password with special chars is used (gh-460)', function (done) {
       this.timeout(1000);
-      var db = mongoose.createConnection('mongodb://aaron:ps#w@localhost/fake?connectTimeoutMS=500', function(err) {
+      var db = mongoose.createConnection('mongodb://aaron:ps#w@localhost/fake?connectTimeoutMS=500', function (err) {
         assert.ok(err);
         db.close();
         done();
@@ -645,8 +691,8 @@ describe('connections:', function() {
     });
   });
 
-  describe('.model()', function() {
-    it('allows passing a schema', function(done) {
+  describe('.model()', function () {
+    it('allows passing a schema', function (done) {
       var db = start();
       var MyModel = db.model('MyModelasdf', new Schema({
         name: String
@@ -656,25 +702,25 @@ describe('connections:', function() {
       assert.ok(MyModel.schema instanceof Schema);
       assert.ok(MyModel.prototype.schema instanceof Schema);
 
-      var m = new MyModel({name:'aaron'});
+      var m = new MyModel({name: 'aaron'});
       assert.equal('aaron', m.name);
       done();
     });
 
-    it('should properly assign the db', function(done) {
-      var A = mongoose.model('testing853a', new Schema({x:String}), 'testing853-1');
-      var B = mongoose.model('testing853b', new Schema({x:String}), 'testing853-2');
+    it('should properly assign the db', function (done) {
+      var A = mongoose.model('testing853a', new Schema({x: String}), 'testing853-1');
+      var B = mongoose.model('testing853b', new Schema({x: String}), 'testing853-2');
       var C = B.model('testing853a');
       assert.ok(C == A);
       done();
     });
 
-    it('prevents overwriting pre-existing models', function(done) {
+    it('prevents overwriting pre-existing models', function (done) {
       var db = start();
       var name = 'gh-1209-a';
       db.model(name, new Schema);
 
-      assert.throws(function() {
+      assert.throws(function () {
         db.model(name, new Schema);
       }, /Cannot overwrite `gh-1209-a` model/);
 
@@ -682,13 +728,13 @@ describe('connections:', function() {
       done();
     });
 
-    it('allows passing identical name + schema args', function(done) {
+    it('allows passing identical name + schema args', function (done) {
       var db = start();
       var name = 'gh-1209-b';
       var schema = new Schema;
 
       db.model(name, schema);
-      assert.doesNotThrow(function() {
+      assert.doesNotThrow(function () {
         db.model(name, schema);
       });
 
@@ -696,9 +742,9 @@ describe('connections:', function() {
       done();
     });
 
-    it('throws on unknown model name', function(done) {
+    it('throws on unknown model name', function (done) {
       var db = start();
-      assert.throws(function() {
+      assert.throws(function () {
         db.model('iDoNotExist!');
       }, /Schema hasn't been registered/);
 
@@ -706,9 +752,9 @@ describe('connections:', function() {
       done();
     });
 
-    it('uses the passed schema when global model exists with same name (gh-1209)', function(done) {
-      var s1 = new Schema({ one: String });
-      var s2 = new Schema({ two: Number });
+    it('uses the passed schema when global model exists with same name (gh-1209)', function (done) {
+      var s1 = new Schema({one: String});
+      var s2 = new Schema({two: Number});
 
       var db = start();
 
@@ -730,9 +776,9 @@ describe('connections:', function() {
       done();
     });
 
-    describe('get existing model with not existing collection in db', function() {
-      it('must return exiting collection with all collection options', function(done) {
-        mongoose.model('some-th-1458', new Schema({test:String},{capped:{size:1000, max:10}}));
+    describe('get existing model with not existing collection in db', function () {
+      it('must return exiting collection with all collection options', function (done) {
+        mongoose.model('some-th-1458', new Schema({test: String}, {capped: {size: 1000, max: 10}}));
         var db = start();
         var m = db.model('some-th-1458');
         assert.equal(m.collection.opts.capped.size, 1000);
@@ -742,11 +788,11 @@ describe('connections:', function() {
       });
     });
 
-    describe('passing collection name', function() {
-      describe('when model name already exists', function() {
-        it('returns a new uncached model', function(done) {
+    describe('passing collection name', function () {
+      describe('when model name already exists', function () {
+        it('returns a new uncached model', function (done) {
           var db = start();
-          var s1 = new Schema({ a: [] });
+          var s1 = new Schema({a: []});
           var name = 'non-cached-collection-name';
           var A = db.model(name, s1);
           var B = db.model(name);
@@ -761,15 +807,15 @@ describe('connections:', function() {
       });
     });
 
-    describe('passing object literal schemas', function() {
-      it('works', function(done) {
+    describe('passing object literal schemas', function () {
+      it('works', function (done) {
         var db = start();
-        var A = db.model('A', { n: [{ age: 'number' }]});
-        var a = new A({ n: [{ age: '47' }] });
+        var A = db.model('A', {n: [{age: 'number'}]});
+        var a = new A({n: [{age: '47'}]});
         assert.strictEqual(47, a.n[0].age);
-        a.save(function(err) {
+        a.save(function (err) {
           assert.ifError(err);
-          A.findById(a, function(err) {
+          A.findById(a, function (err) {
             db.close();
             assert.ifError(err);
             assert.strictEqual(47, a.n[0].age);
@@ -780,43 +826,51 @@ describe('connections:', function() {
     });
   });
 
-  describe('openSet', function() {
-    it('accepts uris, dbname, options', function(done) {
+  describe('openSet', function () {
+    it('accepts uris, dbname, options', function (done) {
       var m = new mongoose.Mongoose;
       var uris = process.env.MONGOOSE_SET_TEST_URI;
-      if (!uris) return done();
+      if (!uris) {
+        return done();
+      }
 
       m.connection.on('error', done);
-      m.connection.on('open', function() {
+      m.connection.on('open', function () {
         m.connection.close(done);
       });
 
       try {
-        m.connect(uris, 'mongoose_test', { server: { auto_reconnect: true }});
+        m.connect(uris, 'mongoose_test', {server: {auto_reconnect: true}});
       } catch (err) {
         done(err);
       }
     });
-    describe('auth', function() {
-      it('from uri', function(done) {
+    describe('auth', function () {
+      it('from uri', function (done) {
         var uris = process.env.MONGOOSE_SET_TEST_URI;
-        if (!uris) return done();
+        if (!uris) {
+          return done();
+        }
 
         var db = mongoose.createConnection();
-        db.openSet('mongodb://aaron:psw@localhost:27000,b,c', { server: { auto_reconnect: false }});
-        db.on('error', function() {});
+        db.openSet('mongodb://aaron:psw@localhost:27000,b,c', {server: {auto_reconnect: false}});
+        db.on('error', function () {
+        });
         assert.equal('aaron', db.user);
         assert.equal('psw', db.pass);
         db.close();
         done();
       });
-      it('form options', function(done) {
+      it('form options', function (done) {
         var uris = process.env.MONGOOSE_SET_TEST_URI;
-        if (!uris) return done();
+        if (!uris) {
+          return done();
+        }
 
         var db = mongoose.createConnection();
-        db.openSet('mongodb://aaron:psw@localhost:27000,b,c', { user: 'tester', pass: 'testpsw' });
-        db.on('error', function() {});
+        db.openSet('mongodb://aaron:psw@localhost:27000,b,c', {user: 'tester', pass: 'testpsw'});
+        db.on('error', function () {
+        });
         assert.equal('tester', db.user);
         assert.equal('testpsw', db.pass);
         db.close();
@@ -824,10 +878,11 @@ describe('connections:', function() {
       });
     });
 
-    it('handles unix domain sockets', function(done) {
+    it('handles unix domain sockets', function (done) {
       var url = 'mongodb://aaron:psw@/tmp/mongodb-27018.sock,/tmp/mongodb-27019.sock/fake?replicaSet=bacon';
-      var db = mongoose.createConnection(url, { server: { auto_reconnect: false }});
-      db.on('error', function() {});
+      var db = mongoose.createConnection(url, {server: {auto_reconnect: false}});
+      db.on('error', function () {
+      });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
       assert.equal(false, db.options.server.auto_reconnect);
@@ -843,22 +898,28 @@ describe('connections:', function() {
       done();
     });
 
-    it('can reopen a disconnected replica set (gh-1263)', function(done) {
+    it('can reopen a disconnected replica set (gh-1263)', function (done) {
       var uris = process.env.MONGOOSE_SET_TEST_URI;
-      if (!uris) return done();
+      if (!uris) {
+        return done();
+      }
 
       var conn = mongoose.createConnection();
 
       conn.on('error', done);
 
       try {
-        conn.openSet(uris, 'mongoose_test', {}, function(err) {
-          if (err) return done(err);
+        conn.openSet(uris, 'mongoose_test', {}, function (err) {
+          if (err) {
+            return done(err);
+          }
 
-          conn.close(function(err) {
-            if (err) return done(err);
+          conn.close(function (err) {
+            if (err) {
+              return done(err);
+            }
 
-            conn.openSet(uris, 'mongoose_test', {}, function() {
+            conn.openSet(uris, 'mongoose_test', {}, function () {
               conn.close(done);
             });
           });
@@ -869,32 +930,34 @@ describe('connections:', function() {
     });
   });
 
-  it('connecting to single mongos (gh-3537)', function(done) {
-    var db = mongoose.createConnection('localhost:27017', { mongos: true });
+  it('connecting to single mongos (gh-3537)', function (done) {
+    var db = mongoose.createConnection('localhost:27017', {mongos: true});
     assert.ok(db.db.serverConfig instanceof mongoose.mongo.Mongos);
     db.close(done);
   });
 
-  describe('connecting to multiple mongos nodes (gh-1037)', function() {
+  describe('connecting to multiple mongos nodes (gh-1037)', function () {
     var mongos = process.env.MONGOOSE_MULTI_MONGOS_TEST_URI;
-    if (!mongos) return console.log('Not testing multi-mongos support');
+    if (!mongos) {
+      return console.log('Not testing multi-mongos support');
+    }
 
-    it('works', function(done) {
+    it('works', function (done) {
       this.timeout(3000);
 
       var m = new mongoose.Mongoose;
-      m.connect(mongos, { mongos: true }, function(err) {
+      m.connect(mongos, {mongos: true}, function (err) {
         assert.ifError(err);
 
         var s = m.connection.db.serverConfig;
         assert.ok(s instanceof mongoose.mongo.Mongos);
         assert.equal(2, s.servers.length);
 
-        var M = m.model('TestMultipleMongos', { name: String }, 'test-multi-mongos-' + random());
-        M.create({ name: 'works' }, function(err, d) {
+        var M = m.model('TestMultipleMongos', {name: String}, 'test-multi-mongos-' + random());
+        M.create({name: 'works'}, function (err, d) {
           assert.ifError(err);
 
-          M.findOne({ name: 'works' }, function(err, doc) {
+          M.findOne({name: 'works'}, function (err, doc) {
             assert.ifError(err);
             assert.equal(doc.id, d.id);
             m.disconnect(done);
@@ -904,15 +967,15 @@ describe('connections:', function() {
     });
   });
 
-  describe('modelNames()', function() {
-    it('returns names of all models registered on it', function(done) {
+  describe('modelNames()', function () {
+    it('returns names of all models registered on it', function (done) {
       var m = new mongoose.Mongoose;
-      m.model('root', { x: String });
-      var another = m.model('another', { x: String });
-      another.discriminator('discriminated', new Schema({ x: String }));
+      m.model('root', {x: String});
+      var another = m.model('another', {x: String});
+      another.discriminator('discriminated', new Schema({x: String}));
 
       var db = m.createConnection();
-      db.model('something', { x: String });
+      db.model('something', {x: String});
 
       var names = db.modelNames();
       assert.ok(Array.isArray(names));
@@ -930,8 +993,8 @@ describe('connections:', function() {
     });
   });
 
-  describe('connection pool sharing: ', function() {
-    it('works', function(done) {
+  describe('connection pool sharing: ', function () {
+    it('works', function (done) {
       var db = mongoose.createConnection('mongodb://localhost/mongoose1');
 
       var db2 = db.useDb('mongoose2');
@@ -951,39 +1014,39 @@ describe('connections:', function() {
       db2.close(done);
     });
 
-    it('saves correctly', function(done) {
+    it('saves correctly', function (done) {
       var db = start();
       var db2 = db.useDb('mongoose-test-2');
 
       var schema = new Schema({
-        body : String,
-        thing : Number
+        body: String,
+        thing: Number
       });
 
       var m1 = db.model('testMod', schema);
       var m2 = db2.model('testMod', schema);
 
-      m1.create({ body : 'this is some text', thing : 1 }, function(err, i1) {
+      m1.create({body: 'this is some text', thing: 1}, function (err, i1) {
         assert.ifError(err);
-        m2.create({ body : 'this is another body', thing : 2 }, function(err, i2) {
+        m2.create({body: 'this is another body', thing: 2}, function (err, i2) {
           assert.ifError(err);
 
-          m1.findById(i1.id, function(err, item1) {
+          m1.findById(i1.id, function (err, item1) {
             assert.ifError(err);
             assert.equal(item1.body, 'this is some text');
             assert.equal(item1.thing, 1);
 
-            m2.findById(i2.id, function(err, item2) {
+            m2.findById(i2.id, function (err, item2) {
               assert.ifError(err);
               assert.equal(item2.body, 'this is another body');
               assert.equal(item2.thing, 2);
 
               // validate the doc doesn't exist in the other db
-              m1.findById(i2.id, function(err, nothing) {
+              m1.findById(i2.id, function (err, nothing) {
                 assert.ifError(err);
                 assert.strictEqual(null, nothing);
 
-                m2.findById(i1.id, function(err, nothing) {
+                m2.findById(i1.id, function (err, nothing) {
                   assert.ifError(err);
                   assert.strictEqual(null, nothing);
 
@@ -996,17 +1059,17 @@ describe('connections:', function() {
       });
     });
 
-    it('emits connecting events on both', function(done) {
+    it('emits connecting events on both', function (done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
 
-      db2.on('connecting', function() {
+      db2.on('connecting', function () {
         hit && close();
         hit = true;
       });
 
-      db.on('connecting', function() {
+      db.on('connecting', function () {
         hit && close();
         hit = true;
       });
@@ -1018,16 +1081,16 @@ describe('connections:', function() {
       }
     });
 
-    it('emits connected events on both', function(done) {
+    it('emits connected events on both', function (done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
 
-      db2.on('connected', function() {
+      db2.on('connected', function () {
         hit && close();
         hit = true;
       });
-      db.on('connected', function() {
+      db.on('connected', function () {
         hit && close();
         hit = true;
       });
@@ -1037,18 +1100,17 @@ describe('connections:', function() {
       function close() {
         db.close(done);
       }
-
     });
 
-    it('emits open events on both', function(done) {
+    it('emits open events on both', function (done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('open', function() {
+      db2.on('open', function () {
         hit && close();
         hit = true;
       });
-      db.on('open', function() {
+      db.on('open', function () {
         hit && close();
         hit = true;
       });
@@ -1060,107 +1122,106 @@ describe('connections:', function() {
       }
     });
 
-    it('emits disconnecting events on both, closing initial db', function(done) {
+    it('emits disconnecting events on both, closing initial db', function (done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('disconnecting', function() {
+      db2.on('disconnecting', function () {
         hit && done();
         hit = true;
       });
-      db.on('disconnecting', function() {
+      db.on('disconnecting', function () {
         hit && done();
         hit = true;
       });
-      db.on('open', function() {
+      db.on('open', function () {
         db.close();
       });
       db.open(start.uri);
     });
 
-    it('emits disconnecting events on both, closing secondary db', function(done) {
+    it('emits disconnecting events on both, closing secondary db', function (done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('disconnecting', function() {
+      db2.on('disconnecting', function () {
         hit && done();
         hit = true;
       });
-      db.on('disconnecting', function() {
+      db.on('disconnecting', function () {
         hit && done();
         hit = true;
       });
-      db.on('open', function() {
+      db.on('open', function () {
         db2.close();
       });
       db.open(start.uri);
     });
 
-    it('emits disconnected events on both, closing initial db', function(done) {
+    it('emits disconnected events on both, closing initial db', function (done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('disconnected', function() {
+      db2.on('disconnected', function () {
         hit && done();
         hit = true;
       });
-      db.on('disconnected', function() {
+      db.on('disconnected', function () {
         hit && done();
         hit = true;
       });
-      db.on('open', function() {
+      db.on('open', function () {
         db.close();
       });
       db.open(start.uri);
     });
 
-    it('emits disconnected events on both, closing secondary db', function(done) {
+    it('emits disconnected events on both, closing secondary db', function (done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('disconnected', function() {
+      db2.on('disconnected', function () {
         hit && done();
         hit = true;
       });
-      db.on('disconnected', function() {
+      db.on('disconnected', function () {
         hit && done();
         hit = true;
       });
-      db.on('open', function() {
+      db.on('open', function () {
         db2.close();
       });
       db.open(start.uri);
     });
 
-    it('closes correctly for all dbs, closing initial db', function(done) {
+    it('closes correctly for all dbs, closing initial db', function (done) {
       var db = start();
       var db2 = db.useDb('mongoose-test-2');
 
-      db2.on('close', function() {
+      db2.on('close', function () {
         done();
       });
       db.close();
-
     });
 
-    it('closes correctly for all dbs, closing secondary db', function(done) {
+    it('closes correctly for all dbs, closing secondary db', function (done) {
       var db = start();
       var db2 = db.useDb('mongoose-test-2');
 
-      db.on('close', function() {
+      db.on('close', function () {
         done();
       });
       db2.close();
-
     });
   });
 
-  describe('shouldAuthenticate()', function() {
-    describe('when using standard authentication', function() {
-      describe('when username and password are undefined', function() {
-        it('should return false', function(done) {
+  describe('shouldAuthenticate()', function () {
+    describe('when using standard authentication', function () {
+      describe('when username and password are undefined', function () {
+        it('should return false', function (done) {
           var db = mongoose.createConnection('localhost', 'fake', 27000, {});
-          db.on('error', function() {});
+          db.on('error', function () {
+          });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
           assert.equal(true, db.options.server.auto_reconnect);
@@ -1178,10 +1239,11 @@ describe('connections:', function() {
           done();
         });
       });
-      describe('when username and password are empty strings', function() {
-        it('should return false', function(done) {
-          var db = mongoose.createConnection('localhost', 'fake', 27000, { user: '', pass: ''});
-          db.on('error', function() {});
+      describe('when username and password are empty strings', function () {
+        it('should return false', function (done) {
+          var db = mongoose.createConnection('localhost', 'fake', 27000, {user: '', pass: ''});
+          db.on('error', function () {
+          });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
           assert.equal(true, db.options.server.auto_reconnect);
@@ -1199,10 +1261,11 @@ describe('connections:', function() {
           done();
         });
       });
-      describe('when only username is defined', function() {
-        it('should return false', function(done) {
-          var db = mongoose.createConnection('localhost', 'fake', 27000, { user: 'user' });
-          db.on('error', function() {});
+      describe('when only username is defined', function () {
+        it('should return false', function (done) {
+          var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user'});
+          db.on('error', function () {
+          });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
           assert.equal(true, db.options.server.auto_reconnect);
@@ -1220,10 +1283,11 @@ describe('connections:', function() {
           done();
         });
       });
-      describe('when both username and password are defined', function() {
-        it('should return false', function(done) {
-          var db = mongoose.createConnection('localhost', 'fake', 27000, { user: 'user', pass: 'pass' });
-          db.on('error', function() {});
+      describe('when both username and password are defined', function () {
+        it('should return false', function (done) {
+          var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user', pass: 'pass'});
+          db.on('error', function () {
+          });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
           assert.equal(true, db.options.server.auto_reconnect);
@@ -1242,11 +1306,12 @@ describe('connections:', function() {
         });
       });
     });
-    describe('when using MONGODB-X509 authentication', function() {
-      describe('when username and password are undefined', function() {
-        it('should return false', function(done) {
+    describe('when using MONGODB-X509 authentication', function () {
+      describe('when username and password are undefined', function () {
+        it('should return false', function (done) {
           var db = mongoose.createConnection('localhost', 'fake', 27000, {});
-          db.on('error', function() {});
+          db.on('error', function () {
+          });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
           assert.equal(true, db.options.server.auto_reconnect);
@@ -1264,10 +1329,11 @@ describe('connections:', function() {
           done();
         });
       });
-      describe('when only username is defined', function() {
-        it('should return false', function(done) {
-          var db = mongoose.createConnection('localhost', 'fake', 27000, { user: 'user', auth: { authMechanism: 'MONGODB-X509' } });
-          db.on('error', function() {});
+      describe('when only username is defined', function () {
+        it('should return false', function (done) {
+          var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user', auth: {authMechanism: 'MONGODB-X509'}});
+          db.on('error', function () {
+          });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
           assert.equal(true, db.options.server.auto_reconnect);
@@ -1285,10 +1351,11 @@ describe('connections:', function() {
           done();
         });
       });
-      describe('when both username and password are defined', function() {
-        it('should return false', function(done) {
-          var db = mongoose.createConnection('localhost', 'fake', 27000, { user: 'user', pass: 'pass', auth: { authMechanism: 'MONGODB-X509' } });
-          db.on('error', function() {});
+      describe('when both username and password are defined', function () {
+        it('should return false', function (done) {
+          var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user', pass: 'pass', auth: {authMechanism: 'MONGODB-X509'}});
+          db.on('error', function () {
+          });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
           assert.equal(true, db.options.server.auto_reconnect);
diff --git a/test/crash.test.js b/test/crash.test.js
index 6067d11c6c0..7d9c415f177 100644
--- a/test/crash.test.js
+++ b/test/crash.test.js
@@ -5,12 +5,12 @@ var start = require('./common'),
     assert = require('assert'),
     mongoose = start.mongoose;
 
-describe('crash: (gh-407)', function() {
-  it('test mongodb crash with invalid objectid string', function(done) {
-    var db = mongoose.createConnection("mongodb://localhost/test-crash");
+describe('crash: (gh-407)', function () {
+  it('test mongodb crash with invalid objectid string', function (done) {
+    var db = mongoose.createConnection('mongodb://localhost/test-crash');
 
     var IndexedGuy = new mongoose.Schema({
-      name: { type: String }
+      name: {type: String}
     });
 
     var Guy = db.model('Guy', IndexedGuy);
@@ -22,7 +22,7 @@ describe('crash: (gh-407)', function() {
           '',
           '4e0e2ca0795666368603d974']
       }
-    }, function(err) {
+    }, function (err) {
       db.close(done);
 
       try {
@@ -32,6 +32,5 @@ describe('crash: (gh-407)', function() {
         throw er;
       }
     });
-
   });
 });
diff --git a/test/docs/defaults.test.js b/test/docs/defaults.test.js
index 6256caeae2d..419a1330ab4 100644
--- a/test/docs/defaults.test.js
+++ b/test/docs/defaults.test.js
@@ -1,15 +1,15 @@
 var assert = require('assert');
 var mongoose = require('../../');
 
-describe('defaults docs', function() {
+describe('defaults docs', function () {
   var db;
   var Schema = mongoose.Schema;
 
-  before(function() {
+  before(function () {
     db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
   });
 
-  after(function(done) {
+  after(function (done) {
     db.close(done);
   });
 
@@ -17,18 +17,18 @@ describe('defaults docs', function() {
    * Your schemas can define default values for certain paths. If you create
    * a new document without that path set, the default will kick in.
    */
-  it('Declaring defaults in your schema', function() {
+  it('Declaring defaults in your schema', function () {
     var schema = new Schema({
       name: String,
-      role: { type: String, default: 'guitarist' }
+      role: {type: String, default: 'guitarist'}
     });
 
     var Person = db.model('Person', schema);
 
-    var axl = new Person({ name: 'Axl Rose', role: 'singer' });
+    var axl = new Person({name: 'Axl Rose', role: 'singer'});
     assert.equal(axl.role, 'singer');
 
-    var slash = new Person({ name: 'Slash' });
+    var slash = new Person({name: 'Slash'});
     assert.equal(slash.role, 'guitarist');
   });
 
@@ -36,7 +36,7 @@ describe('defaults docs', function() {
    * You can also set the `default` schema option to a function. Mongoose will
    * execute that function and use the return value as the default.
    */
-  it('Default functions', function() {
+  it('Default functions', function () {
     var schema = new Schema({
       title: String,
       date: {
@@ -48,7 +48,7 @@ describe('defaults docs', function() {
 
     var BlogPost = db.model('BlogPost', schema);
 
-    var post = new BlogPost({ title: '5 Best Arnold Schwarzenegger Movies' });
+    var post = new BlogPost({title: '5 Best Arnold Schwarzenegger Movies'});
 
     // The post has a default Date set to now
     assert.ok(post.date.getTime() >= Date.now() - 1000);
@@ -68,16 +68,16 @@ describe('defaults docs', function() {
    * The `$setOnInsert` operator was introduced in MongoDB 2.4. If you're
    * using MongoDB server < 2.4.0, do **not** use `setDefaultsOnInsert`.
    */
-  it('The `setDefaultsOnInsert` option', function(done) {
+  it('The `setDefaultsOnInsert` option', function (done) {
     var schema = new Schema({
       title: String,
-      genre: { type: String, default: 'Action' }
+      genre: {type: String, default: 'Action'}
     });
 
     var Movie = db.model('Movie', schema);
 
     var query = {};
-    var update = { title: 'The Terminator' };
+    var update = {title: 'The Terminator'};
     var options = {
       // Return the document after updates are applied
       'new': true,
@@ -88,7 +88,7 @@ describe('defaults docs', function() {
     };
 
     Movie.
-      findOneAndUpdate(query, update, options, function(error, doc) {
+      findOneAndUpdate(query, update, options, function (error, doc) {
         assert.ifError(error);
         assert.equal(doc.title, 'The Terminator');
         assert.equal(doc.genre, 'Action');
diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js
index 74b14514f6e..1b7306b6c66 100644
--- a/test/docs/discriminators.test.js
+++ b/test/docs/discriminators.test.js
@@ -2,34 +2,34 @@ var assert = require('assert');
 var async = require('async');
 var mongoose = require('../../');
 
-describe('discriminator docs', function() {
+describe('discriminator docs', function () {
   var Event;
   var ClickedLinkEvent;
   var SignedUpEvent;
   var db;
 
-  before(function(done) {
+  before(function (done) {
     db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
 
-    var options = { discriminatorKey: 'kind' };
+    var options = {discriminatorKey: 'kind'};
 
-    var eventSchema = new mongoose.Schema({ time: Date }, options);
+    var eventSchema = new mongoose.Schema({time: Date}, options);
     Event = db.model('_event', eventSchema);
 
     ClickedLinkEvent = Event.discriminator('ClickedLink',
-      new mongoose.Schema({ url: String }, options));
+      new mongoose.Schema({url: String}, options));
 
     SignedUpEvent = Event.discriminator('SignedUp',
-      new mongoose.Schema({ username: String }, options));
+      new mongoose.Schema({username: String}, options));
 
     done();
   });
 
-  after(function(done) {
+  after(function (done) {
     db.close(done);
   });
 
-  beforeEach(function(done) {
+  beforeEach(function (done) {
     Event.remove({}, done);
   });
 
@@ -46,24 +46,24 @@ describe('discriminator docs', function() {
    * model whose schema is the union of the base schema and the
    * discriminator schema.
    */
-  it('The `model.discriminator()` function', function(done) {
-    var options = { discriminatorKey: 'kind' };
+  it('The `model.discriminator()` function', function (done) {
+    var options = {discriminatorKey: 'kind'};
 
-    var eventSchema = new mongoose.Schema({ time: Date }, options);
+    var eventSchema = new mongoose.Schema({time: Date}, options);
     var Event = mongoose.model('Event', eventSchema);
 
     // ClickedLinkEvent is a special type of Event that has
     // a URL.
     var ClickedLinkEvent = Event.discriminator('ClickedLink',
-      new mongoose.Schema({ url: String }, options));
+      new mongoose.Schema({url: String}, options));
 
     // When you create a generic event, it can't have a URL field...
-    var genericEvent = new Event({ time: Date.now(), url: 'google.com' });
+    var genericEvent = new Event({time: Date.now(), url: 'google.com'});
     assert.ok(!genericEvent.url);
 
     // But a ClickedLinkEvent can
     var clickedEvent =
-      new ClickedLinkEvent({ time: Date.now(), url: 'google.com' });
+      new ClickedLinkEvent({time: Date.now(), url: 'google.com'});
     assert.ok(clickedEvent.url);
 
     // acquit:ignore:start
@@ -77,23 +77,23 @@ describe('discriminator docs', function() {
    * stored in the same collection as generic events and `ClickedLinkEvent`
    * instances.
    */
-  it('Discriminators save to the Event model\'s collection', function(done) {
-    var event1 = new Event({ time: Date.now() });
-    var event2 = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' });
-    var event3 = new SignedUpEvent({ time: Date.now(), user: 'testuser' });
+  it('Discriminators save to the Event model\'s collection', function (done) {
+    var event1 = new Event({time: Date.now()});
+    var event2 = new ClickedLinkEvent({time: Date.now(), url: 'google.com'});
+    var event3 = new SignedUpEvent({time: Date.now(), user: 'testuser'});
 
-    var save = function(doc, callback) {
-      doc.save(function(error, doc) {
+    var save = function (doc, callback) {
+      doc.save(function (error, doc) {
         callback(error, doc);
       });
     };
 
-    async.map([event1, event2, event3], save, function(error) {
+    async.map([event1, event2, event3], save, function (error) {
       // acquit:ignore:start
       assert.ifError(error);
       // acquit:ignore:end
 
-      Event.count({}, function(error, count) {
+      Event.count({}, function (error, count) {
         // acquit:ignore:start
         assert.ifError(error);
         // acquit:ignore:end
@@ -112,10 +112,10 @@ describe('discriminator docs', function() {
    * to your schemas that it uses to track which discriminator
    * this document is an instance of.
    */
-  it('Discriminator keys', function(done) {
-    var event1 = new Event({ time: Date.now() });
-    var event2 = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' });
-    var event3 = new SignedUpEvent({ time: Date.now(), user: 'testuser' });
+  it('Discriminator keys', function (done) {
+    var event1 = new Event({time: Date.now()});
+    var event2 = new ClickedLinkEvent({time: Date.now(), url: 'google.com'});
+    var event3 = new SignedUpEvent({time: Date.now(), user: 'testuser'});
 
     assert.ok(!event1.kind);
     assert.equal(event2.kind, 'ClickedLink');
@@ -131,23 +131,23 @@ describe('discriminator docs', function() {
    * to queries. In other words, `find()`, `count()`, `aggregate()`, etc.
    * are smart enough to account for discriminators.
    */
-  it('Discriminators add the discriminator key to queries', function(done) {
-    var event1 = new Event({ time: Date.now() });
-    var event2 = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' });
-    var event3 = new SignedUpEvent({ time: Date.now(), user: 'testuser' });
+  it('Discriminators add the discriminator key to queries', function (done) {
+    var event1 = new Event({time: Date.now()});
+    var event2 = new ClickedLinkEvent({time: Date.now(), url: 'google.com'});
+    var event3 = new SignedUpEvent({time: Date.now(), user: 'testuser'});
 
-    var save = function(doc, callback) {
-      doc.save(function(error, doc) {
+    var save = function (doc, callback) {
+      doc.save(function (error, doc) {
         callback(error, doc);
       });
     };
 
-    async.map([event1, event2, event3], save, function(error) {
+    async.map([event1, event2, event3], save, function (error) {
       // acquit:ignore:start
       assert.ifError(error);
       // acquit:ignore:end
 
-      ClickedLinkEvent.find({}, function(error, docs) {
+      ClickedLinkEvent.find({}, function (error, docs) {
         // acquit:ignore:start
         assert.ifError(error);
         // acquit:ignore:end
@@ -166,20 +166,20 @@ describe('discriminator docs', function() {
    * However, you can also attach middleware to the discriminator schema
    * without affecting the base schema.
    */
-  it('Discriminators copy pre and post hooks', function(done) {
-    var options = { discriminatorKey: 'kind' };
+  it('Discriminators copy pre and post hooks', function (done) {
+    var options = {discriminatorKey: 'kind'};
 
-    var eventSchema = new mongoose.Schema({ time: Date }, options);
+    var eventSchema = new mongoose.Schema({time: Date}, options);
     var eventSchemaCalls = 0;
-    eventSchema.pre('validate', function(next) {
+    eventSchema.pre('validate', function (next) {
       ++eventSchemaCalls;
       next();
     });
     var Event = mongoose.model('GenericEvent', eventSchema);
 
-    var clickedLinkSchema = new mongoose.Schema({ url: String }, options);
+    var clickedLinkSchema = new mongoose.Schema({url: String}, options);
     var clickedSchemaCalls = 0;
-    clickedLinkSchema.pre('validate', function(next) {
+    clickedLinkSchema.pre('validate', function (next) {
       ++clickedSchemaCalls;
       next();
     });
@@ -187,12 +187,12 @@ describe('discriminator docs', function() {
       clickedLinkSchema);
 
     var event1 = new ClickedLinkEvent();
-    event1.validate(function() {
+    event1.validate(function () {
       assert.equal(eventSchemaCalls, 1);
       assert.equal(clickedSchemaCalls, 1);
 
       var generic = new Event();
-      generic.validate(function() {
+      generic.validate(function () {
         assert.equal(eventSchemaCalls, 2);
         assert.equal(clickedSchemaCalls, 1);
         // acquit:ignore:start
@@ -213,15 +213,15 @@ describe('discriminator docs', function() {
    * You can work around this by setting the `_id` option to false in the
    * discriminator schema as shown below.
    */
-  it('Handling custom _id fields', function(done) {
-    var options = { discriminatorKey: 'kind' };
+  it('Handling custom _id fields', function (done) {
+    var options = {discriminatorKey: 'kind'};
 
     // Base schema has a String _id...
-    var eventSchema = new mongoose.Schema({ _id: String, time: Date },
+    var eventSchema = new mongoose.Schema({_id: String, time: Date},
       options);
     var Event = mongoose.model('BaseEvent', eventSchema);
 
-    var clickedLinkSchema = new mongoose.Schema({ url: String }, options);
+    var clickedLinkSchema = new mongoose.Schema({url: String}, options);
     var ClickedLinkEvent = Event.discriminator('ChildEventBad',
       clickedLinkSchema);
 
@@ -230,13 +230,13 @@ describe('discriminator docs', function() {
     assert.ok(event1._id instanceof mongoose.Types.ObjectId);
 
     // But if you set `_id` option to false...
-    clickedLinkSchema = new mongoose.Schema({ url: String },
-      { discriminatorKey: 'kind', _id: false });
+    clickedLinkSchema = new mongoose.Schema({url: String},
+      {discriminatorKey: 'kind', _id: false});
     ClickedLinkEvent = Event.discriminator('ChildEventGood',
       clickedLinkSchema);
 
     // The custom _id from the base schema comes through
-    var event2 = new ClickedLinkEvent({ _id: 'test' });
+    var event2 = new ClickedLinkEvent({_id: 'test'});
     assert.ok(event2._id.toString() === event2._id);
     // acquit:ignore:start
     done();
diff --git a/test/docs/promises.test.js b/test/docs/promises.test.js
index 748b4b7df36..3b5243b285e 100644
--- a/test/docs/promises.test.js
+++ b/test/docs/promises.test.js
@@ -2,23 +2,23 @@ var PromiseProvider = require('../../lib/promise_provider');
 var assert = require('assert');
 var mongoose = require('../../');
 
-describe('promises docs', function() {
+describe('promises docs', function () {
   var Band;
   var db;
 
-  before(function(done) {
+  before(function (done) {
     db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
 
-    Band = db.model('band-promises', { name: String, members: [String] });
+    Band = db.model('band-promises', {name: String, members: [String]});
 
     done();
   });
 
-  beforeEach(function(done) {
+  beforeEach(function (done) {
     Band.remove({}, done);
   });
 
-  after(function(done) {
+  after(function (done) {
     PromiseProvider.reset();
     db.close(done);
   });
@@ -32,7 +32,7 @@ describe('promises docs', function() {
    * For backwards compatibility, Mongoose 4 returns [mpromise](https://www.npmjs.com/package/mpromise)
    * promises by default.
    */
-  it('Built-in Promises', function(done) {
+  it('Built-in Promises', function (done) {
     var gnr = new Band({
       name: "Guns N' Roses",
       members: ['Axl', 'Slash']
@@ -41,7 +41,7 @@ describe('promises docs', function() {
     var promise = gnr.save();
     assert.ok(promise instanceof require('mpromise'));
 
-    promise.then(function(doc) {
+    promise.then(function (doc) {
       assert.equal(doc.name, "Guns N' Roses");
       // acquit:ignore:start
       done();
@@ -54,8 +54,8 @@ describe('promises docs', function() {
    * function for `yield` and async/await. If you need
    * a fully-fledged promise, use the `.exec()` function.
    */
-  it('Queries are not promises', function(done) {
-    var query = Band.findOne({ name: "Guns N' Roses" });
+  it('Queries are not promises', function (done) {
+    var query = Band.findOne({name: "Guns N' Roses"});
     assert.ok(!(query instanceof require('mpromise')));
 
     // acquit:ignore:start
@@ -63,7 +63,7 @@ describe('promises docs', function() {
     // acquit:ignore:end
 
     // A query is not a fully-fledged promise, but it does have a `.then()`.
-    query.then(function(doc) {
+    query.then(function (doc) {
       // use doc
       // acquit:ignore:start
       assert.ok(!doc);
@@ -75,7 +75,7 @@ describe('promises docs', function() {
     var promise = query.exec();
     assert.ok(promise instanceof require('mpromise'));
 
-    promise.then(function(doc) {
+    promise.then(function (doc) {
       // use doc
       // acquit:ignore:start
       assert.ok(!doc);
@@ -101,13 +101,13 @@ describe('promises docs', function() {
    * often differs from practice. If you find a bug, open
    * [an issue on GitHub](https://github.com/Automattic/mongoose/issues)
    */
-  it('Plugging in your own Promises Library', function(done) {
+  it('Plugging in your own Promises Library', function (done) {
     // acquit:ignore:start
     if (!global.Promise) {
       return done();
     }
     // acquit:ignore:end
-    var query = Band.findOne({ name: "Guns N' Roses" });
+    var query = Band.findOne({name: "Guns N' Roses"});
 
     // Use native promises
     mongoose.Promise = global.Promise;
diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index 65b7a10a441..f287e116942 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -29,8 +29,8 @@ TestDocument.prototype.__proto__ = Document.prototype;
  * Set a dummy schema to simulate compilation.
  */
 
-var em = new Schema({ title: String, body: String });
-em.virtual('works').get(function() {
+var em = new Schema({title: String, body: String});
+em.virtual('works').get(function () {
   return 'em virtual works';
 });
 var schema = new Schema({
@@ -40,7 +40,7 @@ var schema = new Schema({
   nested: {
     age: Number,
     cool: ObjectId,
-    deep: { x: String },
+    deep: {x: String},
     path: String,
     setr: String
   },
@@ -56,16 +56,16 @@ var schema = new Schema({
 });
 TestDocument.prototype.$__setSchema(schema);
 
-schema.virtual('nested.agePlus2').get(function() {
+schema.virtual('nested.agePlus2').get(function () {
   return this.nested.age + 2;
 });
-schema.virtual('nested.setAge').set(function(v) {
+schema.virtual('nested.setAge').set(function (v) {
   this.nested.age = v;
 });
-schema.path('nested.path').get(function(v) {
+schema.path('nested.path').get(function (v) {
   return this.nested.age + (v ? v : '');
 });
-schema.path('nested.setr').set(function(v) {
+schema.path('nested.setr').set(function (v) {
   return v + ' setter';
 });
 
@@ -74,153 +74,152 @@ schema.path('nested.setr').set(function(v) {
  * executed.
  */
 
-TestDocument.prototype.hooksTest = function(fn) {
+TestDocument.prototype.hooksTest = function (fn) {
   fn(null, arguments);
 };
 
-describe('document: hooks:', function() {
-  it('step order', function(done) {
+describe('document: hooks:', function () {
+  it('step order', function (done) {
     var doc = new TestDocument(),
         steps = 0;
 
     // serial
-    doc.pre('hooksTest', function(next) {
+    doc.pre('hooksTest', function (next) {
       steps++;
-      setTimeout(function() {
+      setTimeout(function () {
         // make sure next step hasn't executed yet
         assert.equal(1, steps);
         next();
       }, 50);
     });
 
-    doc.pre('hooksTest', function(next) {
+    doc.pre('hooksTest', function (next) {
       steps++;
       next();
     });
 
     // parallel
-    doc.pre('hooksTest', true, function(next, done) {
+    doc.pre('hooksTest', true, function (next, done) {
       steps++;
       assert.equal(3, steps);
-      setTimeout(function() {
+      setTimeout(function () {
         assert.equal(4, steps);
       }, 10);
-      setTimeout(function() {
+      setTimeout(function () {
         steps++;
         done();
       }, 110);
       next();
     });
 
-    doc.pre('hooksTest', true, function(next, done) {
+    doc.pre('hooksTest', true, function (next, done) {
       steps++;
-      setTimeout(function() {
+      setTimeout(function () {
         assert.equal(4, steps);
       }, 10);
-      setTimeout(function() {
+      setTimeout(function () {
         steps++;
         done();
       }, 110);
       next();
     });
 
-    doc.hooksTest(function(err) {
+    doc.hooksTest(function (err) {
       assert.ifError(err);
       assert.equal(6, steps);
       done();
     });
-
   });
 
-  it('calling next twice does not break', function(done) {
+  it('calling next twice does not break', function (done) {
     var doc = new TestDocument(),
         steps = 0;
 
-    doc.pre('hooksTest', function(next) {
+    doc.pre('hooksTest', function (next) {
       steps++;
       next();
       next();
     });
 
-    doc.pre('hooksTest', function(next) {
+    doc.pre('hooksTest', function (next) {
       steps++;
       next();
     });
 
-    doc.hooksTest(function(err) {
+    doc.hooksTest(function (err) {
       assert.ifError(err);
       assert.equal(2, steps);
       done();
     });
   });
 
-  it('calling done twice does not break', function(done) {
+  it('calling done twice does not break', function (done) {
     var doc = new TestDocument(),
         steps = 0;
 
-    doc.pre('hooksTest', true, function(next, done) {
+    doc.pre('hooksTest', true, function (next, done) {
       steps++;
       next();
       done();
       done();
     });
 
-    doc.pre('hooksTest', true, function(next, done) {
+    doc.pre('hooksTest', true, function (next, done) {
       steps++;
       next();
       done();
       done();
     });
 
-    doc.hooksTest(function(err) {
+    doc.hooksTest(function (err) {
       assert.ifError(err);
       assert.equal(2, steps);
       done();
     });
   });
 
-  it('errors from a serial hook', function(done) {
+  it('errors from a serial hook', function (done) {
     var doc = new TestDocument(),
         steps = 0;
 
-    doc.pre('hooksTest', function(next) {
+    doc.pre('hooksTest', function (next) {
       steps++;
       next();
     });
 
-    doc.pre('hooksTest', function(next) {
+    doc.pre('hooksTest', function (next) {
       steps++;
       next(new Error);
     });
 
-    doc.pre('hooksTest', function() {
+    doc.pre('hooksTest', function () {
       steps++;
     });
 
-    doc.hooksTest(function(err) {
+    doc.hooksTest(function (err) {
       assert.ok(err instanceof Error);
       assert.equal(2, steps);
       done();
     });
   });
 
-  it('errors from last serial hook', function(done) {
+  it('errors from last serial hook', function (done) {
     var doc = new TestDocument();
 
-    doc.pre('hooksTest', function(next) {
+    doc.pre('hooksTest', function (next) {
       next(new Error);
     });
 
-    doc.hooksTest(function(err) {
+    doc.hooksTest(function (err) {
       assert.ok(err instanceof Error);
       done();
     });
   });
 
-  it('mutating incoming args via middleware', function(done) {
+  it('mutating incoming args via middleware', function (done) {
     var doc = new TestDocument();
 
-    doc.pre('set', function(next, path, val) {
+    doc.pre('set', function (next, path, val) {
       next(path, 'altered-' + val);
     });
 
@@ -229,55 +228,55 @@ describe('document: hooks:', function() {
     done();
   });
 
-  it('test hooks system errors from a parallel hook', function(done) {
+  it('test hooks system errors from a parallel hook', function (done) {
     var doc = new TestDocument(),
         steps = 0;
 
-    doc.pre('hooksTest', true, function(next, done) {
+    doc.pre('hooksTest', true, function (next, done) {
       steps++;
       next();
       done();
     });
 
-    doc.pre('hooksTest', true, function(next, done) {
+    doc.pre('hooksTest', true, function (next, done) {
       steps++;
       next();
       done();
     });
 
-    doc.pre('hooksTest', true, function(next, done) {
+    doc.pre('hooksTest', true, function (next, done) {
       steps++;
       next();
       done(new Error);
     });
 
-    doc.hooksTest(function(err) {
+    doc.hooksTest(function (err) {
       assert.ok(err instanceof Error);
       assert.equal(3, steps);
       done();
     });
   });
 
-  it('passing two arguments to a method subject to hooks and return value', function(done) {
+  it('passing two arguments to a method subject to hooks and return value', function (done) {
     var doc = new TestDocument();
 
-    doc.pre('hooksTest', function(next) {
+    doc.pre('hooksTest', function (next) {
       next();
     });
 
-    doc.hooksTest(function(err, args) {
+    doc.hooksTest(function (err, args) {
       assert.equal(2, args.length);
       assert.equal(args[1], 'test');
       done();
     }, 'test');
   });
 
-  it('hooking set works with document arrays (gh-746)', function(done) {
+  it('hooking set works with document arrays (gh-746)', function (done) {
     var db = start();
 
-    var child = new Schema({ text: String });
+    var child = new Schema({text: String});
 
-    child.pre('set', function(next, path, value, type) {
+    child.pre('set', function (next, path, value, type) {
       next(path, value, type);
     });
 
@@ -288,19 +287,19 @@ describe('document: hooks:', function() {
 
     var S = db.model('docArrayWithHookedSet', schema);
 
-    var s = new S({ name: "test" });
-    s.e = [{ text: 'hi' }];
-    s.save(function(err) {
+    var s = new S({name: 'test'});
+    s.e = [{text: 'hi'}];
+    s.save(function (err) {
       assert.ifError(err);
 
-      S.findById(s.id, function(err ,s) {
+      S.findById(s.id, function (err, s) {
         assert.ifError(err);
 
-        s.e = [{ text: 'bye' }];
-        s.save(function(err) {
+        s.e = [{text: 'bye'}];
+        s.save(function (err) {
           assert.ifError(err);
 
-          S.findById(s.id, function(err, s) {
+          S.findById(s.id, function (err, s) {
             db.close();
             assert.ifError(err);
             assert.equal('bye', s.e[0].text);
@@ -311,13 +310,13 @@ describe('document: hooks:', function() {
     });
   });
 
-  it('pre save hooks on sub-docs should not exec after validation errors', function(done) {
+  it('pre save hooks on sub-docs should not exec after validation errors', function (done) {
     var db = start();
     var presave = false;
 
-    var child = new Schema({ text: { type: String, required: true }});
+    var child = new Schema({text: {type: String, required: true}});
 
-    child.pre('save', function(next) {
+    child.pre('save', function (next) {
       presave = true;
       next();
     });
@@ -328,8 +327,8 @@ describe('document: hooks:', function() {
     });
 
     var S = db.model('docArrayWithHookedSave', schema);
-    var s = new S({ name: 'hi', e: [{}] });
-    s.save(function(err) {
+    var s = new S({name: 'hi', e: [{}]});
+    s.save(function (err) {
       db.close();
 
       try {
@@ -343,54 +342,54 @@ describe('document: hooks:', function() {
     });
   });
 
-  it('post remove hooks on subdocuments work', function(done) {
+  it('post remove hooks on subdocuments work', function (done) {
     var db = start();
-    var sub = Schema({ _id: Number });
-    var called = { pre: 0, post: 0 };
+    var sub = Schema({_id: Number});
+    var called = {pre: 0, post: 0};
 
-    sub.pre('remove', function(next) {
+    sub.pre('remove', function (next) {
       called.pre++;
       next();
     });
 
-    sub.post('remove', function(doc) {
+    sub.post('remove', function (doc) {
       called.post++;
       assert.ok(doc instanceof Document);
     });
 
-    var par = Schema({ sub: [sub], name: String });
+    var par = Schema({sub: [sub], name: String});
     var M = db.model('post-remove-hooks-sub', par);
 
-    var m = new M({ sub: [{ _id: 1 }, { _id: 2 }] });
-    m.save(function(err) {
+    var m = new M({sub: [{_id: 1}, {_id: 2}]});
+    m.save(function (err) {
       assert.ifError(err);
       assert.equal(0, called.pre);
       assert.equal(0, called.post);
 
-      M.findById(m, function(err, doc) {
+      M.findById(m, function (err, doc) {
         assert.ifError(err);
 
         doc.sub.id(1).remove();
-        doc.save(function(err) {
+        doc.save(function (err) {
           assert.ifError(err);
           assert.equal(1, called.pre);
           assert.equal(1, called.post);
 
           // does not get called when not removed
           doc.name = 'changed1';
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
             assert.equal(1, called.pre);
             assert.equal(1, called.post);
 
             doc.sub.id(2).remove();
-            doc.remove(function(err) {
+            doc.remove(function (err) {
               assert.ifError(err);
               assert.equal(2, called.pre);
               assert.equal(2, called.post);
 
               // does not get called twice
-              doc.remove(function(err) {
+              doc.remove(function (err) {
                 assert.ifError(err);
                 assert.equal(2, called.pre);
                 assert.equal(2, called.post);
@@ -403,7 +402,7 @@ describe('document: hooks:', function() {
     });
   });
 
-  it('can set nested schema to undefined in pre save (gh-1335)', function(done) {
+  it('can set nested schema to undefined in pre save (gh-1335)', function (done) {
     var db = start();
     var FooSchema = new Schema({});
     db.model('gh-1335-1', FooSchema);
@@ -413,14 +412,14 @@ describe('document: hooks:', function() {
     var Bar = db.model('gh-1335-2', BarSchema);
 
     var b = new Bar();
-    b.pre('save', function(next) {
+    b.pre('save', function (next) {
       if (this.isNew && 0 === this.foos.length) {
         this.foos = undefined;
       }
       next();
     });
 
-    b.save(function(error, dbBar) {
+    b.save(function (error, dbBar) {
       assert.ifError(error);
       assert.ok(!dbBar.foos);
       assert.equal(typeof dbBar.foos, 'undefined');
@@ -430,28 +429,26 @@ describe('document: hooks:', function() {
     });
   });
 
-  it('post save hooks on subdocuments work (gh-915) (gh-3780)', function(done) {
-
+  it('post save hooks on subdocuments work (gh-915) (gh-3780)', function (done) {
     var doneCalled = false;
-    var _done = function(e) {
+    var _done = function (e) {
       if (!doneCalled) {
         doneCalled = true;
         done(e);
       }
     };
     var db = start();
-    var called = { post: 0 };
+    var called = {post: 0};
 
     var subSchema = new Schema({
       name: String
     });
 
-    subSchema.post('save', function(doc) {
+    subSchema.post('save', function (doc) {
       called.post++;
       try {
         assert.ok(doc instanceof EmbeddedDocument);
-      }
-      catch (e) {
+      } catch (e) {
         _done(e);
       }
     });
@@ -462,20 +459,20 @@ describe('document: hooks:', function() {
 
     var M = db.model('post-save-hooks-sub', postSaveHooks);
 
-    var m = new M({ subs: [
-      { name: 'mee' },
-      { name: 'moo' }
-    ] });
+    var m = new M({subs: [
+      {name: 'mee'},
+      {name: 'moo'}
+    ]});
 
-    m.save(function(err) {
+    m.save(function (err) {
       assert.ifError(err);
       assert.equal(2, called.post);
       called.post = 0;
 
-      M.findById(m, function(err, doc) {
+      M.findById(m, function (err, doc) {
         assert.ifError(err);
-        doc.subs.push({ name: 'maa' });
-        doc.save(function(err) {
+        doc.subs.push({name: 'maa'});
+        doc.save(function (err) {
           assert.ifError(err);
           assert.equal(called.post, 3);
 
@@ -485,7 +482,7 @@ describe('document: hooks:', function() {
     });
   });
 
-  it("pre save hooks should run in parallel", function(done) {
+  it('pre save hooks should run in parallel', function (done) {
     // we set the time out to be double that of the validator - 1 (so that running in serial will be greater then that)
     this.timeout(1000);
     var db = start(),
@@ -495,11 +492,11 @@ describe('document: hooks:', function() {
       preference: String
     });
     SchemaWithPreSaveHook.pre('save', true, function hook(next, done) {
-      setTimeout(function() {
+      setTimeout(function () {
         count++;
         next();
         if (count === 3) {
-          done(new Error("gaga"));
+          done(new Error('gaga'));
         } else {
           done();
         }
@@ -510,25 +507,25 @@ describe('document: hooks:', function() {
     var m = new MWPSH({
       subs: [
           {
-            preference: "xx"
+            preference: 'xx'
           },
           {
-            preference: "yy"
+            preference: 'yy'
           },
           {
-            preference: "1"
+            preference: '1'
           },
           {
-            preference: "2"
+            preference: '2'
           }
       ]
     });
 
-    m.save(function(err) {
+    m.save(function (err) {
       db.close();
 
       try {
-        assert.equal(err.message, "gaga");
+        assert.equal(err.message, 'gaga');
         assert.ok(count >= 3);
         done();
       } catch (e) {
@@ -537,18 +534,18 @@ describe('document: hooks:', function() {
     });
   });
 
-  it('parallel followed by serial (gh-2521)', function(done) {
-    var schema = Schema({ name: String });
+  it('parallel followed by serial (gh-2521)', function (done) {
+    var schema = Schema({name: String});
 
-    schema.pre('save', true, function(next, done) {
-      process.nextTick(function() {
+    schema.pre('save', true, function (next, done) {
+      process.nextTick(function () {
         done();
       });
       next();
     });
 
-    schema.pre('save', function(done) {
-      process.nextTick(function() {
+    schema.pre('save', function (done) {
+      process.nextTick(function () {
         done();
       });
     });
@@ -556,18 +553,18 @@ describe('document: hooks:', function() {
     var db = start();
     var People = db.model('gh-2521', schema, 'gh-2521');
 
-    var p = new People({ name: 'Val' });
-    p.save(function(error) {
+    var p = new People({name: 'Val'});
+    p.save(function (error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('runs post hooks after function (gh-2949)', function(done) {
-    var schema = Schema({ name: String });
+  it('runs post hooks after function (gh-2949)', function (done) {
+    var schema = Schema({name: String});
 
     var postCount = 0;
-    schema.post('init', function(doc) {
+    schema.post('init', function (doc) {
       assert.equal(doc.name, 'Val');
       ++postCount;
     });
@@ -575,18 +572,18 @@ describe('document: hooks:', function() {
     var db = start();
     var People = db.model('gh-2949', schema, 'gh-2949');
 
-    People.create({ name: 'Val' }, function(err, doc) {
-      People.findOne({ _id: doc._id }, function() {
+    People.create({name: 'Val'}, function (err, doc) {
+      People.findOne({_id: doc._id}, function () {
         assert.equal(postCount, 1);
         db.close(done);
       });
     });
   });
 
-  it('pre-init hooks work', function(done) {
-    var schema = Schema({ text: String });
+  it('pre-init hooks work', function (done) {
+    var schema = Schema({text: String});
 
-    schema.pre('init', function(next, data) {
+    schema.pre('init', function (next, data) {
       data.text = "pre init'd";
       next();
     });
@@ -596,9 +593,8 @@ describe('document: hooks:', function() {
 
     Parent.create({
       text: "not init'd"
-    }, function(err, doc) {
-
-      Parent.findOne({ _id: doc._id }, function(err, doc) {
+    }, function (err, doc) {
+      Parent.findOne({_id: doc._id}, function (err, doc) {
         db.close();
 
         assert.strictEqual(doc.text, "pre init'd");
@@ -608,10 +604,10 @@ describe('document: hooks:', function() {
     });
   });
 
-  it('post save handles multiple args (gh-3155)', function(done) {
+  it('post save handles multiple args (gh-3155)', function (done) {
     var schema = Schema({});
 
-    schema.post('save', function(item, next) {
+    schema.post('save', function (item, next) {
       next();
     });
 
@@ -619,33 +615,32 @@ describe('document: hooks:', function() {
     var Test = db.model('gh3155', schema);
 
     var t = new Test();
-    t.save(function(error, doc, numAffected) {
+    t.save(function (error, doc, numAffected) {
       assert.strictEqual(numAffected, 1);
 
       db.close(done);
     });
   });
 
-  it('pre-init hooks on subdocuments work', function(done) {
-    var childSchema = Schema({ age: Number });
+  it('pre-init hooks on subdocuments work', function (done) {
+    var childSchema = Schema({age: Number});
 
-    childSchema.pre('init', function(next, data) {
+    childSchema.pre('init', function (next, data) {
       ++data.age;
       next();
       // On subdocuments, you have to return `this`
       return this;
     });
 
-    var parentSchema = Schema({ name: String, children: [childSchema] });
+    var parentSchema = Schema({name: String, children: [childSchema]});
     var db = start(),
         Parent = db.model('ParentWithChildren', parentSchema);
 
     Parent.create({
       name: 'Bob',
-      children: [{ age: 8 }, { age: 5 }]
-    }, function(err, doc) {
-
-      Parent.findOne({ _id: doc._id }, function(err, doc) {
+      children: [{age: 8}, {age: 5}]
+    }, function (err, doc) {
+      Parent.findOne({_id: doc._id}, function (err, doc) {
         db.close();
 
         assert.strictEqual(doc.children.length, 2);
@@ -659,10 +654,10 @@ describe('document: hooks:', function() {
     });
   });
 
-  it('pre-save hooks fire on subdocs before their parent doc', function(done) {
-    var childSchema = Schema({ name: String, count: Number });
+  it('pre-save hooks fire on subdocs before their parent doc', function (done) {
+    var childSchema = Schema({name: String, count: Number});
 
-    childSchema.pre('save', function(next) {
+    childSchema.pre('save', function (next) {
       ++this.count;
       next();
       // On subdocuments, you have to return `this`
@@ -674,18 +669,19 @@ describe('document: hooks:', function() {
       children: [childSchema]
     });
 
-    parentSchema.pre('save', function(next) {
-      this.cumulativeCount = this.children.reduce(function(seed, child) {
-        return seed += child.count;
+    parentSchema.pre('save', function (next) {
+      this.cumulativeCount = this.children.reduce(function (seed, child) {
+        seed += child.count;
+        return seed;
       }, 0);
       next();
     });
 
     var db = start(),
         Parent = db.model('ParentWithChildren', parentSchema),
-        doc = new Parent({ children: [{ count: 0, name: 'a' }, { count: 1, name: 'b' }] });
+        doc = new Parent({children: [{count: 0, name: 'a'}, {count: 1, name: 'b'}]});
 
-    doc.save(function(err, doc) {
+    doc.save(function (err, doc) {
       db.close();
 
       try {
@@ -700,16 +696,16 @@ describe('document: hooks:', function() {
     });
   });
 
-  describe('gh-3284', function() {
-    it('should call pre hooks on nested subdoc', function(done) {
+  describe('gh-3284', function () {
+    it('should call pre hooks on nested subdoc', function (done) {
       var self = this;
 
       var childSchema = new Schema({
         title: String
       });
 
-      ['init', 'save', 'validate'].forEach(function(type) {
-        childSchema.pre(type, function(next) {
+      ['init', 'save', 'validate'].forEach(function (type) {
+        childSchema.pre(type, function (next) {
           self['pre' + type + 'Called'] = true;
           next();
         });
@@ -734,9 +730,9 @@ describe('document: hooks:', function() {
         }
       });
 
-      parent.save().then(function() {
+      parent.save().then(function () {
         return Parent.findById(parent._id);
-      }).then(function() {
+      }).then(function () {
         db.close();
         assert.ok(self.preinitCalled);
         assert.ok(self.prevalidateCalled);
@@ -746,14 +742,14 @@ describe('document: hooks:', function() {
     });
   });
 
-  it('pre set hooks on real documents (gh-3479)', function(done) {
+  it('pre set hooks on real documents (gh-3479)', function (done) {
     var bookSchema = new Schema({
       title: String
     });
 
     var preCalls = [];
-    bookSchema.pre('set', function(next, path, val) {
-      preCalls.push({ path: path, val: val });
+    bookSchema.pre('set', function (next, path, val) {
+      preCalls.push({path: path, val: val});
       next();
     });
 
@@ -769,7 +765,7 @@ describe('document: hooks:', function() {
     done();
   });
 
-  it('nested subdocs only fire once (gh-3281)', function(done) {
+  it('nested subdocs only fire once (gh-3281)', function (done) {
     var L3Schema = new Schema({
       title: String
     });
@@ -783,7 +779,7 @@ describe('document: hooks:', function() {
     });
 
     var calls = 0;
-    L3Schema.pre('save', function(next) {
+    L3Schema.pre('save', function (next) {
       ++calls;
       return next();
     });
@@ -803,21 +799,21 @@ describe('document: hooks:', function() {
       ]
     };
 
-    L1.create(data, function(error) {
+    L1.create(data, function (error) {
       assert.ifError(error);
       assert.equal(calls, 1);
       db.close(done);
     });
   });
 
-  it('remove hooks for single nested (gh-3754)', function(done) {
+  it('remove hooks for single nested (gh-3754)', function (done) {
     var db = start();
     var postCount = 0;
     var PhotoSchema = new mongoose.Schema({
       bla: String
     });
 
-    PhotoSchema.post('remove', function(photo) {
+    PhotoSchema.post('remove', function () {
       ++postCount;
     });
 
@@ -827,12 +823,12 @@ describe('document: hooks:', function() {
 
     var Person = db.model('Person', PersonSchema);
 
-    Person.create({ photo: { bla: 'test' } }, function(error, person) {
+    Person.create({photo: {bla: 'test'}}, function (error, person) {
       assert.ifError(error);
       person.photo.remove();
-      person.save(function(error) {
+      person.save(function (error) {
         assert.ifError(error);
-        setTimeout(function() {
+        setTimeout(function () {
           assert.equal(postCount, 1);
           done();
         }, 0);
diff --git a/test/document.isselected.test.js b/test/document.isselected.test.js
index 5718fdecc08..ed859dea607 100644
--- a/test/document.isselected.test.js
+++ b/test/document.isselected.test.js
@@ -29,8 +29,8 @@ TestDocument.prototype.__proto__ = Document.prototype;
  * Set a dummy schema to simulate compilation.
  */
 
-var em = new Schema({ title: String, body: String });
-em.virtual('works').get(function() {
+var em = new Schema({title: String, body: String});
+em.virtual('works').get(function () {
   return 'em virtual works';
 });
 var schema = new Schema({
@@ -40,7 +40,7 @@ var schema = new Schema({
   nested: {
     age: Number,
     cool: ObjectId,
-    deep: { x: String },
+    deep: {x: String},
     path: String,
     setr: String
   },
@@ -57,20 +57,20 @@ var schema = new Schema({
 });
 TestDocument.prototype.$__setSchema(schema);
 
-schema.virtual('nested.agePlus2').get(function() {
+schema.virtual('nested.agePlus2').get(function () {
   return this.nested.age + 2;
 });
-schema.virtual('nested.setAge').set(function(v) {
+schema.virtual('nested.setAge').set(function (v) {
   this.nested.age = v;
 });
-schema.path('nested.path').get(function(v) {
+schema.path('nested.path').get(function (v) {
   return (this.nested.age || '') + (v ? v : '');
 });
-schema.path('nested.setr').set(function(v) {
+schema.path('nested.setr').set(function (v) {
   return v + ' setter';
 });
 
-schema.path('date').set(function(v) {
+schema.path('date').set(function (v) {
   // should not have been cast to a Date yet
   assert.equal('string', typeof v);
   return v;
@@ -81,28 +81,28 @@ schema.path('date').set(function(v) {
  * executed.
  */
 
-TestDocument.prototype.hooksTest = function(fn) {
+TestDocument.prototype.hooksTest = function (fn) {
   fn(null, arguments);
 };
 
 /**
  * Test.
  */
-describe('document', function() {
-  it('isSelected()', function(done) {
+describe('document', function () {
+  it('isSelected()', function (done) {
     var doc = new TestDocument();
 
     doc.init({
       test: 'test',
-      numbers: [4,5,6,7],
+      numbers: [4, 5, 6, 7],
       nested: {
         age: 5,
         cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
         path: 'my path',
-        deep: { x: 'a string' }
+        deep: {x: 'a string'}
       },
       notapath: 'i am not in the schema',
-      em: [{ title: 'gocars' }]
+      em: [{title: 'gocars'}]
     });
 
     assert.ok(doc.isSelected('_id'));
@@ -136,9 +136,9 @@ describe('document', function() {
 
     doc.init({
       test: 'test',
-      numbers: [4,5,6,7],
+      numbers: [4, 5, 6, 7],
       nested: {
-        deep: { x: 'a string' }
+        deep: {x: 'a string'}
       }
     });
 
@@ -169,7 +169,7 @@ describe('document', function() {
     doc = new TestDocument(undefined, selection);
 
     doc.init({
-      em: [{ title: 'one' }]
+      em: [{title: 'one'}]
     });
 
     assert.ok(doc.isSelected('_id'));
@@ -199,12 +199,12 @@ describe('document', function() {
     doc = new TestDocument(undefined, selection);
     doc.init({
       test: 'test',
-      numbers: [4,5,6,7],
+      numbers: [4, 5, 6, 7],
       nested: {
         age: 5,
         cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
         path: 'my path',
-        deep: { x: 'a string' }
+        deep: {x: 'a string'}
       },
       notapath: 'i am not in the schema'
     });
@@ -236,12 +236,12 @@ describe('document', function() {
     doc = new TestDocument(undefined, selection);
     doc.init({
       test: 'test',
-      numbers: [4,5,6,7],
+      numbers: [4, 5, 6, 7],
       nested: {
         age: 5,
         cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
         path: 'my path',
-        deep: { x: 'a string' }
+        deep: {x: 'a string'}
       },
       notapath: 'i am not in the schema'
     });
@@ -249,7 +249,7 @@ describe('document', function() {
     assert.ok(!doc.isSelected('_id'));
     assert.ok(doc.isSelected('nested.deep.x.no'));
 
-    doc = new TestDocument({ test: 'boom' });
+    doc = new TestDocument({test: 'boom'});
     assert.ok(doc.isSelected('_id'));
     assert.ok(doc.isSelected('test'));
     assert.ok(doc.isSelected('numbers'));
@@ -275,12 +275,12 @@ describe('document', function() {
     };
 
     doc = new TestDocument(undefined, selection);
-    doc.init({ _id: 'test' });
+    doc.init({_id: 'test'});
 
     assert.ok(doc.isSelected('_id'));
     assert.ok(!doc.isSelected('test'));
 
-    doc = new TestDocument({ test: 'boom' }, true);
+    doc = new TestDocument({test: 'boom'}, true);
     assert.ok(doc.isSelected('_id'));
     assert.ok(doc.isSelected('test'));
     assert.ok(doc.isSelected('numbers'));
@@ -309,12 +309,12 @@ describe('document', function() {
     doc = new TestDocument(undefined, selection);
     doc.init({
       test: 'test',
-      numbers: [4,5,6,7],
+      numbers: [4, 5, 6, 7],
       nested: {
         age: 5,
         cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
         path: 'my path',
-        deep: { x: 'a string' }
+        deep: {x: 'a string'}
       },
       notapath: 'i am not in the schema'
     });
diff --git a/test/document.modified.test.js b/test/document.modified.test.js
index 98d2c0bcd3d..2a967ef4707 100644
--- a/test/document.modified.test.js
+++ b/test/document.modified.test.js
@@ -38,31 +38,31 @@ var BlogPost = new Schema({
   numbers: [Number],
   owners: [ObjectId],
   comments: [Comments],
-  nested: { array: [Number] }
+  nested: {array: [Number]}
 });
 
 BlogPost
 .path('title')
-.get(function(v) {
+.get(function (v) {
   if (v) return v.toUpperCase();
 });
 
 BlogPost
 .virtual('titleWithAuthor')
-.get(function() {
+.get(function () {
   return this.get('title') + ' by ' + this.get('author');
 })
-.set(function(val) {
+.set(function (val) {
   var split = val.split(' by ');
   this.set('title', split[0]);
   this.set('author', split[1]);
 });
 
-BlogPost.method('cool', function() {
+BlogPost.method('cool', function () {
   return this;
 });
 
-BlogPost.static('woot', function() {
+BlogPost.static('woot', function () {
   return this;
 });
 
@@ -71,23 +71,23 @@ mongoose.model(modelName, BlogPost);
 
 var collection = 'blogposts_' + random();
 
-describe('document modified', function() {
-  describe('modified states', function() {
-    it('reset after save', function(done) {
+describe('document modified', function () {
+  describe('modified states', function () {
+    it('reset after save', function (done) {
       var db = start(),
           B = db.model(modelName, collection);
 
       var b = new B;
 
       b.numbers.push(3);
-      b.save(function(err) {
+      b.save(function (err) {
         assert.strictEqual(null, err);
 
         b.numbers.push(3);
-        b.save(function(err) {
+        b.save(function (err) {
           assert.strictEqual(null, err);
 
-          B.findById(b, function(err, b) {
+          B.findById(b, function (err, b) {
             assert.strictEqual(null, err);
             assert.equal(2, b.numbers.length);
 
@@ -98,13 +98,13 @@ describe('document modified', function() {
       });
     });
 
-    it('of embedded docs reset after save', function(done) {
+    it('of embedded docs reset after save', function (done) {
       var db = start(),
           BlogPost = db.model(modelName, collection);
 
-      var post = new BlogPost({ title: 'hocus pocus' });
-      post.comments.push({ title: 'Humpty Dumpty', comments: [{title: 'nested'}] });
-      post.save(function(err) {
+      var post = new BlogPost({title: 'hocus pocus'});
+      post.comments.push({title: 'Humpty Dumpty', comments: [{title: 'nested'}]});
+      post.save(function (err) {
         db.close();
         assert.strictEqual(null, err);
         var mFlag = post.comments[0].isModified('title');
@@ -115,20 +115,20 @@ describe('document modified', function() {
     });
   });
 
-  describe('isDefault', function() {
-    it('works', function(done) {
+  describe('isDefault', function () {
+    it('works', function (done) {
       var db = start();
 
       var MyModel = db.model('test',
-        { name: { type: String, default: 'Val '} });
+        {name: {type: String, default: 'Val '}});
       var m = new MyModel();
       assert.ok(m.$isDefault('name'));
       db.close(done);
     });
   });
 
-  describe('isModified', function() {
-    it('should not throw with no argument', function(done) {
+  describe('isModified', function () {
+    it('should not throw with no argument', function (done) {
       var db = start();
       var BlogPost = db.model(modelName, collection);
       var post = new BlogPost;
@@ -145,7 +145,7 @@ describe('document modified', function() {
       done();
     });
 
-    it('when modifying keys', function(done) {
+    it('when modifying keys', function (done) {
       var db = start(),
           BlogPost = db.model(modelName, collection);
 
@@ -169,7 +169,7 @@ describe('document modified', function() {
       done();
     });
 
-    it('setting a key identically to its current value should not dirty the key', function(done) {
+    it('setting a key identically to its current value should not dirty the key', function (done) {
       var db = start(),
           BlogPost = db.model(modelName, collection);
 
@@ -187,8 +187,8 @@ describe('document modified', function() {
       done();
     });
 
-    describe('on DocumentArray', function() {
-      it('work', function(done) {
+    describe('on DocumentArray', function () {
+      it('work', function (done) {
         var db = start(),
             BlogPost = db.model(modelName, collection);
 
@@ -196,7 +196,7 @@ describe('document modified', function() {
         post.init({
           title: 'Test',
           slug: 'test',
-          comments: [ { title: 'Test', date: new Date, body: 'Test' } ]
+          comments: [{title: 'Test', date: new Date, body: 'Test'}]
         });
 
         assert.equal(false, post.isModified('comments.0.title'));
@@ -208,7 +208,7 @@ describe('document modified', function() {
 
         db.close(done);
       });
-      it('with accessors', function(done) {
+      it('with accessors', function (done) {
         var db = start(),
             BlogPost = db.model(modelName, collection);
 
@@ -216,7 +216,7 @@ describe('document modified', function() {
         post.init({
           title: 'Test',
           slug: 'test',
-          comments: [ { title: 'Test', date: new Date, body: 'Test' } ]
+          comments: [{title: 'Test', date: new Date, body: 'Test'}]
         });
 
         assert.equal(false, post.isModified('comments.0.body'));
@@ -231,8 +231,8 @@ describe('document modified', function() {
       });
     });
 
-    describe('on MongooseArray', function() {
-      it('atomic methods', function(done) {
+    describe('on MongooseArray', function () {
+      it('atomic methods', function (done) {
         // COMPLETEME
         var db = start(),
             BlogPost = db.model(modelName, collection);
@@ -244,7 +244,7 @@ describe('document modified', function() {
         assert.equal(true, post.isModified('owners'));
         done();
       });
-      it('native methods', function(done) {
+      it('native methods', function (done) {
         // COMPLETEME
         var db = start(),
             BlogPost = db.model(modelName, collection);
@@ -256,7 +256,7 @@ describe('document modified', function() {
       });
     });
 
-    it('on entire document', function(done) {
+    it('on entire document', function (done) {
       var db = start(),
           BlogPost = db.model(modelName, collection);
 
@@ -269,22 +269,22 @@ describe('document modified', function() {
           visitors: 5
         },
         published: true,
-        mixed: { x: [ { y: [1,'yes', 2] } ] },
+        mixed: {x: [{y: [1, 'yes', 2]}]},
         numbers: [],
         owners: [new DocumentObjectId, new DocumentObjectId],
         comments: [
-          { title: 'Test', date: new Date, body: 'Test' },
-          { title: 'Super', date: new Date, body: 'Cool' }
+          {title: 'Test', date: new Date, body: 'Test'},
+          {title: 'Super', date: new Date, body: 'Cool'}
         ]
       };
 
-      BlogPost.create(doc, function(err, post) {
+      BlogPost.create(doc, function (err, post) {
         assert.ifError(err);
-        BlogPost.findById(post.id, function(err, postRead) {
+        BlogPost.findById(post.id, function (err, postRead) {
           db.close();
           assert.ifError(err);
-          //set the same data again back to the document.
-          //expected result, nothing should be set to modified
+          // set the same data again back to the document.
+          // expected result, nothing should be set to modified
           assert.equal(false, postRead.isModified('comments'));
           assert.equal(false, postRead.isNew);
           postRead.set(postRead.toObject());
@@ -300,7 +300,7 @@ describe('document modified', function() {
           assert.equal(false, postRead.isModified('owners'));
           assert.equal(false, postRead.isModified('comments'));
           var arr = postRead.comments.slice();
-          arr[2] = postRead.comments.create({ title: 'index' });
+          arr[2] = postRead.comments.create({title: 'index'});
           postRead.comments = arr;
           assert.equal(true, postRead.isModified('comments'));
           done();
@@ -308,11 +308,11 @@ describe('document modified', function() {
       });
     });
 
-    it('should let you set ref paths (gh-1530)', function(done) {
+    it('should let you set ref paths (gh-1530)', function (done) {
       var db = start();
 
       var parentSchema = new Schema({
-        child: { type: Schema.Types.ObjectId, ref: 'gh-1530-2' }
+        child: {type: Schema.Types.ObjectId, ref: 'gh-1530-2'}
       });
       var Parent = db.model('gh-1530-1', parentSchema);
       var childSchema = new Schema({
@@ -320,39 +320,39 @@ describe('document modified', function() {
       });
 
       var preCalls = 0;
-      childSchema.pre('save', function(next) {
+      childSchema.pre('save', function (next) {
         ++preCalls;
         next();
       });
 
       var postCalls = 0;
-      childSchema.post('save', function(doc, next) {
+      childSchema.post('save', function (doc, next) {
         ++postCalls;
         next();
       });
       var Child = db.model('gh-1530-2', childSchema);
 
       var p = new Parent();
-      var c = new Child({ name: 'Luke' });
+      var c = new Child({name: 'Luke'});
       p.child = c;
       assert.equal(p.child.name, 'Luke');
 
-      p.save(function(error) {
+      p.save(function (error) {
         assert.ifError(error);
         assert.equal(p.child.name, 'Luke');
         var originalParent = p;
-        Parent.findOne({}, function(error, p) {
+        Parent.findOne({}, function (error, p) {
           assert.ifError(error);
           assert.ok(p.child);
           assert.ok(typeof p.child.name === 'undefined');
           assert.equal(0, preCalls);
           assert.equal(0, postCalls);
-          Child.findOne({ name: 'Luke' }, function(error, child) {
+          Child.findOne({name: 'Luke'}, function (error, child) {
             assert.ifError(error);
             assert.ok(!child);
-            originalParent.child.save(function(error) {
+            originalParent.child.save(function (error) {
               assert.ifError(error);
-              Child.findOne({ name: 'Luke' }, function(error, child) {
+              Child.findOne({name: 'Luke'}, function (error, child) {
                 assert.ifError(error);
                 assert.ok(child);
                 assert.equal(child._id.toString(), p.child.toString());
@@ -364,71 +364,71 @@ describe('document modified', function() {
       });
     });
 
-    it('properly sets populated for gh-1530 (gh-2678)', function(done) {
+    it('properly sets populated for gh-1530 (gh-2678)', function (done) {
       var db = start();
 
       var parentSchema = new Schema({
         name: String,
-        child: { type: Schema.Types.ObjectId, ref: 'Child' }
+        child: {type: Schema.Types.ObjectId, ref: 'Child'}
       });
 
       var Parent = db.model('Parent', parentSchema, 'parents');
       var Child = db.model('Child', parentSchema, 'children');
 
-      var child = new Child({ name: 'Mary' });
-      var p = new Parent({ name: 'Alex', child: child });
+      var child = new Child({name: 'Mary'});
+      var p = new Parent({name: 'Alex', child: child});
 
       assert.equal(p.populated('child').toString(), child._id.toString());
       db.close(done);
     });
 
-    describe('manually populating arrays', function() {
+    describe('manually populating arrays', function () {
       var db;
 
-      before(function() {
+      before(function () {
         db = start();
       });
 
-      after(function(done) {
+      after(function (done) {
         db.close(done);
       });
 
-      it('gh-1530 for arrays (gh-3575)', function(done) {
+      it('gh-1530 for arrays (gh-3575)', function (done) {
         var parentSchema = new Schema({
           name: String,
-          children: [{ type: Schema.Types.ObjectId, ref: 'Child' }]
+          children: [{type: Schema.Types.ObjectId, ref: 'Child'}]
         });
 
         var Parent = db.model('Parent', parentSchema, 'parents');
         var Child = db.model('Child', parentSchema, 'children');
 
-        var child = new Child({ name: 'Luke' });
-        var p = new Parent({ name: 'Anakin', children: [child] });
+        var child = new Child({name: 'Luke'});
+        var p = new Parent({name: 'Anakin', children: [child]});
 
         assert.equal(p.children[0].name, 'Luke');
         assert.ok(p.populated('children'));
         done();
       });
 
-      it('setting nested arrays (gh-3721)', function(done) {
+      it('setting nested arrays (gh-3721)', function (done) {
         var userSchema = new Schema({
-          name: { type: Schema.Types.String }
+          name: {type: Schema.Types.String}
         });
         var User = db.model('User', userSchema);
 
         var accountSchema = new Schema({
           roles: [{
-            name: { type: Schema.Types.String },
-            users: [{ type: Schema.Types.ObjectId, ref: 'User'}]
+            name: {type: Schema.Types.String},
+            users: [{type: Schema.Types.ObjectId, ref: 'User'}]
           }]
         });
 
         var Account = db.model('Account', accountSchema);
 
-        var user = new User({ name: 'Test' });
+        var user = new User({name: 'Test'});
         var account = new Account({
           roles: [
-            { name: 'test group', users: [user] }
+            {name: 'test group', users: [user]}
           ]
         });
 
@@ -437,13 +437,11 @@ describe('document modified', function() {
       });
     });
 
-
-
-    it('should support setting mixed paths by string (gh-1418)', function(done) {
+    it('should support setting mixed paths by string (gh-1418)', function (done) {
       var db = start();
-      var BlogPost = db.model('1418', new Schema({ mixed: {} }));
+      var BlogPost = db.model('1418', new Schema({mixed: {}}));
       var b = new BlogPost;
-      b.init({ mixed: {} });
+      b.init({mixed: {}});
 
       var path = 'mixed.path';
       assert.ok(!b.isModified(path));
@@ -453,14 +451,14 @@ describe('document modified', function() {
       assert.equal(3, b.get(path));
 
       b = new BlogPost;
-      b.init({ mixed: {} });
+      b.init({mixed: {}});
       path = 'mixed.9a';
       b.set(path, 4);
       assert.ok(b.isModified(path));
       assert.equal(4, b.get(path));
 
-      b = new BlogPost({ mixed: {} });
-      b.save(function(err) {
+      b = new BlogPost({mixed: {}});
+      b.save(function (err) {
         assert.ifError(err);
 
         path = 'mixed.9a.x';
@@ -468,9 +466,9 @@ describe('document modified', function() {
         assert.ok(b.isModified(path));
         assert.equal(8, b.get(path));
 
-        b.save(function(err) {
+        b.save(function (err) {
           assert.ifError(err);
-          BlogPost.findById(b, function(err, doc) {
+          BlogPost.findById(b, function (err, doc) {
             assert.ifError(err);
             assert.equal(8, doc.get(path));
             db.close(done);
@@ -479,7 +477,7 @@ describe('document modified', function() {
       });
     });
 
-    it('should mark multi-level nested schemas as modified (gh-1754)', function(done) {
+    it('should mark multi-level nested schemas as modified (gh-1754)', function (done) {
       var db = start();
 
       var grandChildSchema = Schema({
@@ -498,15 +496,15 @@ describe('document modified', function() {
 
       var Parent = db.model('gh-1754', parentSchema);
       Parent.create(
-        { child: [{ name: 'Brian', grandChild: [{ name: 'Jake' }] }] },
-        function(error, p) {
+        {child: [{name: 'Brian', grandChild: [{name: 'Jake'}]}]},
+        function (error, p) {
           assert.ifError(error);
           assert.ok(p);
           assert.equal(1, p.child.length);
           assert.equal(1, p.child[0].grandChild.length);
           p.child[0].grandChild[0].name = 'Jason';
           assert.ok(p.isModified('child.0.grandChild.0.name'));
-          p.save(function(error, inDb) {
+          p.save(function (error, inDb) {
             assert.ifError(error);
             assert.equal('Jason', inDb.child[0].grandChild[0].name);
             db.close(done);
diff --git a/test/document.populate.test.js b/test/document.populate.test.js
index 5ae004136fd..82e7422c585 100644
--- a/test/document.populate.test.js
+++ b/test/document.populate.test.js
@@ -34,8 +34,8 @@ TestDocument.prototype.__proto__ = Document.prototype;
  * Set a dummy schema to simulate compilation.
  */
 
-var em = new Schema({ title: String, body: String });
-em.virtual('works').get(function() {
+var em = new Schema({title: String, body: String});
+em.virtual('works').get(function () {
   return 'em virtual works';
 });
 var schema = new Schema({
@@ -45,7 +45,7 @@ var schema = new Schema({
   nested: {
     age: Number,
     cool: ObjectId,
-    deep: { x: String },
+    deep: {x: String},
     path: String,
     setr: String
   },
@@ -69,18 +69,18 @@ TestDocument.prototype.$__setSchema(schema);
 var User = new Schema({
   name: String,
   email: String,
-  gender: { type: String, enum: ['male', 'female'], default: 'male' },
-  age: { type: Number, default: 21 },
-  blogposts: [{ type: ObjectId, ref: 'doc.populate.b' }]
-}, { collection: 'doc.populate.us' });
+  gender: {type: String, enum: ['male', 'female'], default: 'male'},
+  age: {type: Number, default: 21},
+  blogposts: [{type: ObjectId, ref: 'doc.populate.b'}]
+}, {collection: 'doc.populate.us'});
 
 /**
  * Comment subdocument schema.
  */
 
 var Comment = new Schema({
-  asers: [{ type: ObjectId, ref: 'doc.populate.u' }],
-  _creator: { type: ObjectId, ref: 'doc.populate.u' },
+  asers: [{type: ObjectId, ref: 'doc.populate.u'}],
+  _creator: {type: ObjectId, ref: 'doc.populate.u'},
   content: String
 });
 
@@ -89,21 +89,21 @@ var Comment = new Schema({
  */
 
 var BlogPost = new Schema({
-  _creator: { type: ObjectId, ref: 'doc.populate.u' },
+  _creator: {type: ObjectId, ref: 'doc.populate.u'},
   title: String,
   comments: [Comment],
-  fans: [{ type: ObjectId, ref: 'doc.populate.u' }]
+  fans: [{type: ObjectId, ref: 'doc.populate.u'}]
 });
 
 mongoose.model('doc.populate.b', BlogPost);
 mongoose.model('doc.populate.u', User);
 mongoose.model('doc.populate.u2', User);
 
-describe('document.populate', function() {
+describe('document.populate', function () {
   var db, B, User;
   var user1, user2, post, _id;
 
-  before(function(done) {
+  before(function (done) {
     db = start();
     B = db.model('doc.populate.b');
     User = db.model('doc.populate.u');
@@ -118,7 +118,7 @@ describe('document.populate', function() {
       name: 'Newark',
       email: 'ewr@nj.com',
       blogposts: [_id]
-    }, function(err, u1, u2) {
+    }, function (err, u1, u2) {
       assert.ifError(err);
 
       user1 = u1;
@@ -128,8 +128,8 @@ describe('document.populate', function() {
         title: 'the how and why',
         _creator: user1,
         fans: [user1, user2],
-        comments: [{ _creator: user2, content: 'user2' }, { _creator: user1, content: 'user1' }]
-      }, function(err, p) {
+        comments: [{_creator: user2, content: 'user2'}, {_creator: user1, content: 'user1'}]
+      }, function (err, p) {
         assert.ifError(err);
         post = p;
         done();
@@ -137,14 +137,14 @@ describe('document.populate', function() {
     });
   });
 
-  after(function(done) {
+  after(function (done) {
     db.close(done);
   });
 
-  describe('argument processing', function() {
-    describe('duplicates', function() {
-      it('are removed', function(done) {
-        B.findById(post, function(err, post) {
+  describe('argument processing', function () {
+    describe('duplicates', function () {
+      it('are removed', function (done) {
+        B.findById(post, function (err, post) {
           assert.ifError(err);
           post.populate('_creator');
           assert.equal(1, Object.keys(post.$__.populate).length);
@@ -156,20 +156,20 @@ describe('document.populate', function() {
           assert.equal(2, Object.keys(post.$__.populate).length);
           assert.ok('_creator' in post.$__.populate);
           assert.ok('fans' in post.$__.populate);
-          post.populate({ path: '_creator' });
+          post.populate({path: '_creator'});
           assert.equal(2, Object.keys(post.$__.populate).length);
           assert.ok('_creator' in post.$__.populate);
           assert.ok('fans' in post.$__.populate);
           done();
         });
       });
-      it('overwrite previous', function(done) {
-        B.findById(post, function(err, post) {
+      it('overwrite previous', function (done) {
+        B.findById(post, function (err, post) {
           assert.ifError(err);
           post.populate('_creator');
           assert.equal(1, Object.keys(post.$__.populate).length);
           assert.equal(undefined, post.$__.populate._creator.select);
-          post.populate({ path: '_creator', select: 'name' });
+          post.populate({path: '_creator', select: 'name'});
           assert.equal(1, Object.keys(post.$__.populate).length);
           assert.ok('_creator' in post.$__.populate);
           assert.equal('name', post.$__.populate._creator.select);
@@ -179,11 +179,11 @@ describe('document.populate', function() {
     });
   });
 
-  describe('options', function() {
-    it('resets populate options after execution', function(done) {
-      B.findById(post, function(err, post) {
+  describe('options', function () {
+    it('resets populate options after execution', function (done) {
+      B.findById(post, function (err, post) {
         var creator_id = post._creator;
-        post.populate('_creator', function(err) {
+        post.populate('_creator', function (err) {
           assert.ifError(err);
           assert.ok(!post.$__.populate);
           assert.ok(post._creator);
@@ -193,7 +193,7 @@ describe('document.populate', function() {
       });
     });
 
-    it('are not modified when no arguments are passed', function(done) {
+    it('are not modified when no arguments are passed', function (done) {
       var d = new TestDocument();
       var o = utils.clone(d.options);
       assert.deepEqual(o, d.populate().options);
@@ -201,12 +201,12 @@ describe('document.populate', function() {
     });
   });
 
-  describe('populating two paths', function() {
-    it('with space delmited string works', function(done) {
-      B.findById(post, function(err, post) {
+  describe('populating two paths', function () {
+    it('with space delmited string works', function (done) {
+      B.findById(post, function (err, post) {
         var creator_id = post._creator;
         var alt_id = post.fans[1];
-        post.populate('_creator fans', function(err) {
+        post.populate('_creator fans', function (err) {
           assert.ifError(err);
           assert.ok(post._creator);
           assert.equal(String(creator_id), String(post._creator._id));
@@ -218,11 +218,11 @@ describe('document.populate', function() {
     });
   });
 
-  it('works with just a callback', function(done) {
-    B.findById(post, function(err, post) {
+  it('works with just a callback', function (done) {
+    B.findById(post, function (err, post) {
       var creator_id = post._creator;
       var alt_id = post.fans[1];
-      post.populate('_creator').populate(function(err) {
+      post.populate('_creator').populate(function (err) {
         assert.ifError(err);
         assert.ok(post._creator);
         assert.equal(String(creator_id), String(post._creator._id));
@@ -232,16 +232,16 @@ describe('document.populate', function() {
     });
   });
 
-  it('populating using space delimited paths with options', function(done) {
-    B.findById(post, function(err, post) {
+  it('populating using space delimited paths with options', function (done) {
+    B.findById(post, function (err, post) {
       var param = {};
       param.select = '-email';
-      param.options = { sort: 'name' };
+      param.options = {sort: 'name'};
       param.path = '_creator fans'; // 2 paths
 
       var creator_id = post._creator;
       var alt_id = post.fans[1];
-      post.populate(param, function(err, post) {
+      post.populate(param, function (err, post) {
         assert.ifError(err);
         assert.equal(2, post.fans.length);
         assert.equal(String(creator_id), String(post._creator._id));
@@ -256,19 +256,19 @@ describe('document.populate', function() {
     });
   });
 
-  it('using multiple populate calls', function(done) {
-    B.findById(post, function(err, post) {
+  it('using multiple populate calls', function (done) {
+    B.findById(post, function (err, post) {
       var creator_id = post._creator;
       var alt_id = post.fans[1];
 
       var param = {};
       param.select = '-email';
-      param.options = { sort: 'name' };
+      param.options = {sort: 'name'};
       param.path = '_creator';
       post.populate(param);
       param.path = 'fans';
 
-      post.populate(param, function(err, post) {
+      post.populate(param, function (err, post) {
         assert.ifError(err);
         assert.equal(2, post.fans.length);
         assert.equal(String(creator_id), String(post._creator._id));
@@ -283,17 +283,17 @@ describe('document.populate', function() {
     });
   });
 
-  it('with custom model selection', function(done) {
-    B.findById(post, function(err, post) {
+  it('with custom model selection', function (done) {
+    B.findById(post, function (err, post) {
       var param = {};
       param.select = '-email';
-      param.options = { sort: 'name' };
+      param.options = {sort: 'name'};
       param.path = '_creator fans';
       param.model = 'doc.populate.u2';
 
       var creator_id = post._creator;
       var alt_id = post.fans[1];
-      post.populate(param, function(err, post) {
+      post.populate(param, function (err, post) {
         assert.ifError(err);
         assert.equal(2, post.fans.length);
         assert.equal(String(creator_id), String(post._creator._id));
@@ -308,17 +308,17 @@ describe('document.populate', function() {
     });
   });
 
-  it('a property not in schema', function(done) {
-    B.findById(post, function(err, post) {
+  it('a property not in schema', function (done) {
+    B.findById(post, function (err, post) {
       assert.ifError(err);
-      post.populate('idontexist', function(err) {
+      post.populate('idontexist', function (err) {
         assert.ifError(err);
 
         // stuff an ad-hoc value in
         post.setValue('idontexist', user1._id);
 
         // populate the non-schema value by passing an explicit model
-        post.populate({ path: 'idontexist', model: 'doc.populate.u' }, function(err, post) {
+        post.populate({path: 'idontexist', model: 'doc.populate.u'}, function (err, post) {
           assert.ifError(err);
           assert.ok(post);
           assert.equal(post.get('idontexist')._id, user1._id.toString());
@@ -329,37 +329,37 @@ describe('document.populate', function() {
     });
   });
 
-  it('of empty array', function(done) {
-    B.findById(post, function(err, post) {
+  it('of empty array', function (done) {
+    B.findById(post, function (err, post) {
       post.fans = [];
-      post.populate('fans', function(err) {
+      post.populate('fans', function (err) {
         assert.ifError(err);
         done();
       });
     });
   });
 
-  it('of array of null/undefined', function(done) {
-    B.findById(post, function(err, post) {
+  it('of array of null/undefined', function (done) {
+    B.findById(post, function (err, post) {
       post.fans = [null, undefined];
-      post.populate('fans', function(err) {
+      post.populate('fans', function (err) {
         assert.ifError(err);
         done();
       });
     });
   });
 
-  it('of null property', function(done) {
-    B.findById(post, function(err, post) {
+  it('of null property', function (done) {
+    B.findById(post, function (err, post) {
       post._creator = null;
-      post.populate('_creator', function(err) {
+      post.populate('_creator', function (err) {
         assert.ifError(err);
         done();
       });
     });
   });
 
-  it('String _ids', function(done) {
+  it('String _ids', function (done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -368,20 +368,20 @@ describe('document.populate', function() {
     });
 
     var NoteSchema = new Schema({
-      author: { type: String, ref: 'UserWithStringId' },
+      author: {type: String, ref: 'UserWithStringId'},
       body: String
     });
 
     var User = db.model('UserWithStringId', UserSchema, random());
     var Note = db.model('NoteWithStringId', NoteSchema, random());
 
-    var alice = new User({_id: 'alice', name: "Alice In Wonderland"});
+    var alice = new User({_id: 'alice', name: 'Alice In Wonderland'});
 
-    alice.save(function(err) {
+    alice.save(function (err) {
       assert.ifError(err);
 
-      var note = new Note({ author: 'alice', body: "Buy Milk" });
-      note.populate('author', function(err) {
+      var note = new Note({author: 'alice', body: 'Buy Milk'});
+      note.populate('author', function (err) {
         db.close();
         assert.ifError(err);
         assert.ok(note.author);
@@ -392,7 +392,7 @@ describe('document.populate', function() {
     });
   });
 
-  it('Buffer _ids', function(done) {
+  it('Buffer _ids', function (done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -401,31 +401,31 @@ describe('document.populate', function() {
     });
 
     var NoteSchema = new Schema({
-      author: { type: Buffer, ref: 'UserWithBufferId' },
+      author: {type: Buffer, ref: 'UserWithBufferId'},
       body: String
     });
 
     var User = db.model('UserWithBufferId', UserSchema, random());
     var Note = db.model('NoteWithBufferId', NoteSchema, random());
 
-    var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: "Alice"});
+    var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: 'Alice'});
 
-    alice.save(function(err) {
+    alice.save(function (err) {
       assert.ifError(err);
 
-      var note = new Note({author: 'alice', body: "Buy Milk"});
-      note.save(function(err) {
+      var note = new Note({author: 'alice', body: 'Buy Milk'});
+      note.save(function (err) {
         assert.ifError(err);
 
-        Note.findById(note.id, function(err, note) {
+        Note.findById(note.id, function (err, note) {
           assert.ifError(err);
           assert.equal('alice', note.author);
-          note.populate('author', function(err, note) {
+          note.populate('author', function (err, note) {
             db.close();
             assert.ifError(err);
-            assert.equal(note.body,'Buy Milk');
+            assert.equal(note.body, 'Buy Milk');
             assert.ok(note.author);
-            assert.equal(note.author.name,'Alice');
+            assert.equal(note.author.name, 'Alice');
             done();
           });
         });
@@ -433,7 +433,7 @@ describe('document.populate', function() {
     });
   });
 
-  it('Number _ids', function(done) {
+  it('Number _ids', function (done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -442,36 +442,36 @@ describe('document.populate', function() {
     });
 
     var NoteSchema = new Schema({
-      author: { type: Number, ref: 'UserWithNumberId' },
+      author: {type: Number, ref: 'UserWithNumberId'},
       body: String
     });
 
     var User = db.model('UserWithNumberId', UserSchema, random());
     var Note = db.model('NoteWithNumberId', NoteSchema, random());
 
-    var alice = new User({_id: 2359, name: "Alice"});
+    var alice = new User({_id: 2359, name: 'Alice'});
 
-    alice.save(function(err) {
+    alice.save(function (err) {
       assert.ifError(err);
 
-      var note = new Note({author: 2359, body: "Buy Milk"});
-      note.populate('author').populate(function(err, note) {
+      var note = new Note({author: 2359, body: 'Buy Milk'});
+      note.populate('author').populate(function (err, note) {
         db.close();
         assert.ifError(err);
         assert.ok(note.author);
         assert.equal(2359, note.author._id);
-        assert.equal(note.author.name,'Alice');
+        assert.equal(note.author.name, 'Alice');
         done();
       });
     });
   });
 
-  describe('sub-level properties', function() {
-    it('with string arg', function(done) {
-      B.findById(post, function(err, post) {
+  describe('sub-level properties', function () {
+    it('with string arg', function (done) {
+      B.findById(post, function (err, post) {
         var id0 = post.comments[0]._creator;
         var id1 = post.comments[1]._creator;
-        post.populate('comments._creator', function(err, post) {
+        post.populate('comments._creator', function (err, post) {
           assert.ifError(err);
           assert.equal(2, post.comments.length);
           assert.equal(id0, post.comments[0]._creator.id);
@@ -482,15 +482,15 @@ describe('document.populate', function() {
     });
   });
 
-  describe('of new document', function() {
-    it('should save just the populated _id (gh-1442)', function(done) {
-      var b = new B({ _creator: user1 });
-      b.populate('_creator', function(err, b) {
+  describe('of new document', function () {
+    it('should save just the populated _id (gh-1442)', function (done) {
+      var b = new B({_creator: user1});
+      b.populate('_creator', function (err, b) {
         if (err) return done(err);
         assert.equal('Phoenix', b._creator.name);
-        b.save(function(err) {
+        b.save(function (err) {
           assert.ifError(err);
-          B.collection.findOne({ _id: b._id }, function(err, b) {
+          B.collection.findOne({_id: b._id}, function (err, b) {
             assert.ifError(err);
             assert.equal(b._creator, String(user1._id));
             done();
@@ -500,7 +500,7 @@ describe('document.populate', function() {
     });
   });
 
-  it('gh-3308', function(done) {
+  it('gh-3308', function (done) {
     var db = start();
 
     var Person = db.model('gh3308', {
@@ -508,25 +508,25 @@ describe('document.populate', function() {
     });
 
     var Band = db.model('gh3308_0', {
-      guitarist: { type: Schema.Types.ObjectId, ref: 'gh3308' }
+      guitarist: {type: Schema.Types.ObjectId, ref: 'gh3308'}
     });
 
-    var slash = new Person({ name: 'Slash' });
-    var gnr = new Band({ guitarist: slash._id });
+    var slash = new Person({name: 'Slash'});
+    var gnr = new Band({guitarist: slash._id});
 
     gnr.guitarist = slash;
     assert.equal(gnr.guitarist.name, 'Slash');
     assert.ok(gnr.populated('guitarist'));
 
-    var buckethead = new Person({ name: 'Buckethead' });
+    var buckethead = new Person({name: 'Buckethead'});
     gnr.guitarist = buckethead._id;
     assert.ok(!gnr.populated('guitarist'));
 
     db.close(done);
   });
 
-  describe('gh-2214', function() {
-    it('should return a real document array when populating', function(done) {
+  describe('gh-2214', function () {
+    it('should return a real document array when populating', function (done) {
       var db = start();
 
       var Car = db.model('gh-2214-1', {
@@ -546,21 +546,21 @@ describe('document.populate', function() {
 
       var car, joe;
       joe = new Person({
-        name: "Joe"
+        name: 'Joe'
       });
       car = new Car({
-        model: "BMW",
-        color: "red"
+        model: 'BMW',
+        color: 'red'
       });
       joe.cars.push(car);
 
-      return joe.save(function() {
-        return car.save(function() {
-          return Person.findById(joe.id, function(err, joe) {
-            return joe.populate("cars", function() {
+      return joe.save(function () {
+        return car.save(function () {
+          return Person.findById(joe.id, function (err, joe) {
+            return joe.populate('cars', function () {
               car = new Car({
-                model: "BMW",
-                color: "black"
+                model: 'BMW',
+                color: 'black'
               });
               joe.cars.push(car);
               assert.ok(joe.isModified('cars'));
@@ -573,7 +573,7 @@ describe('document.populate', function() {
     });
   });
 
-  it('can depopulate (gh-2509)', function(done) {
+  it('can depopulate (gh-2509)', function (done) {
     var db = start();
 
     var Person = db.model('gh2509_1', {
@@ -582,20 +582,20 @@ describe('document.populate', function() {
 
     var Band = db.model('gh2509_2', {
       name: String,
-      members: [{ type: Schema.Types.ObjectId, ref: 'gh2509_1' }],
-      lead: { type: Schema.Types.ObjectId, ref: 'gh2509_1' }
+      members: [{type: Schema.Types.ObjectId, ref: 'gh2509_1'}],
+      lead: {type: Schema.Types.ObjectId, ref: 'gh2509_1'}
     });
 
-    var people = [{ name: 'Axl Rose' }, { name: 'Slash' }];
-    Person.create(people, function(error, docs) {
+    var people = [{name: 'Axl Rose'}, {name: 'Slash'}];
+    Person.create(people, function (error, docs) {
       assert.ifError(error);
       var band = {
         name: "Guns N' Roses",
         members: [docs[0]._id, docs[1]],
         lead: docs[0]._id
       };
-      Band.create(band, function(error, band) {
-        band.populate('members', function() {
+      Band.create(band, function (error, band) {
+        band.populate('members', function () {
           assert.equal(band.members[0].name, 'Axl Rose');
           band.depopulate('members');
           assert.ok(!band.members[0].name);
@@ -603,7 +603,7 @@ describe('document.populate', function() {
           assert.equal(band.members[1].toString(), docs[1]._id.toString());
           assert.ok(!band.populated('members'));
           assert.ok(!band.populated('lead'));
-          band.populate('lead', function() {
+          band.populate('lead', function () {
             assert.equal(band.lead.name, 'Axl Rose');
             band.depopulate('lead');
             assert.ok(!band.lead.name);
@@ -615,9 +615,9 @@ describe('document.populate', function() {
     });
   });
 
-  it('handles pulling from populated array (gh-3579)', function(done) {
+  it('handles pulling from populated array (gh-3579)', function (done) {
     var db = start();
-    var barSchema = new Schema({ name: String });
+    var barSchema = new Schema({name: String});
 
     var Bar = db.model('gh3579', barSchema);
 
@@ -630,13 +630,13 @@ describe('document.populate', function() {
 
     var Foo = db.model('gh3579_0', fooSchema);
 
-    Bar.create([{ name: 'bar1' }, { name: 'bar2' }], function(error, docs) {
+    Bar.create([{name: 'bar1'}, {name: 'bar2'}], function (error, docs) {
       assert.ifError(error);
-      var foo = new Foo({ bars: [docs[0], docs[1]] });
+      var foo = new Foo({bars: [docs[0], docs[1]]});
       foo.bars.pull(docs[0]._id);
-      foo.save(function(error) {
+      foo.save(function (error) {
         assert.ifError(error);
-        Foo.findById(foo._id, function(error, foo) {
+        Foo.findById(foo._id, function (error, foo) {
           assert.ifError(error);
           assert.equal(foo.bars.length, 1);
           assert.equal(foo.bars[0].toString(), docs[1]._id.toString());
diff --git a/test/document.strict.test.js b/test/document.strict.test.js
index 21b7c13e6e7..3b85231e55d 100644
--- a/test/document.strict.test.js
+++ b/test/document.strict.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Test dependencies.
  */
@@ -9,33 +8,33 @@ var start = require('./common'),
     random = require('../lib/utils').random,
     Schema = mongoose.Schema;
 
-describe('document: strict mode:', function() {
-  describe('should work', function() {
+describe('document: strict mode:', function () {
+  describe('should work', function () {
     var db, Lax, Strict;
 
-    before(function() {
+    before(function () {
       db = start();
 
       var raw = {
-        ts: { type: Date, default: Date.now },
+        ts: {type: Date, default: Date.now},
         content: String,
         mixed: {},
-        deepMixed: { '4a': {}},
+        deepMixed: {'4a': {}},
         arrayMixed: []
       };
 
-      var lax = new Schema(raw, { strict: false });
+      var lax = new Schema(raw, {strict: false});
       var strict = new Schema(raw);
 
       Lax = db.model('Lax', lax);
       Strict = db.model('Strict', strict);
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('when creating models with non-strict schemas', function(done) {
+    it('when creating models with non-strict schemas', function (done) {
       var l = new Lax({content: 'sample', rouge: 'data'});
       assert.equal(false, l.$__.strictMode);
 
@@ -49,7 +48,7 @@ describe('document: strict mode:', function() {
       done();
     });
 
-    it('when creating models with strict schemas', function(done) {
+    it('when creating models with strict schemas', function (done) {
       var s = new Strict({content: 'sample', rouge: 'data'});
       assert.equal(true, s.$__.strictMode);
 
@@ -65,7 +64,7 @@ describe('document: strict mode:', function() {
       done();
     });
 
-    it('when overriding strictness', function(done) {
+    it('when overriding strictness', function (done) {
       // instance override
       var instance = new Lax({content: 'sample', rouge: 'data'}, true);
       assert.ok(instance.$__.strictMode);
@@ -93,9 +92,9 @@ describe('document: strict mode:', function() {
       done();
     });
 
-    it('when using Model#create', function(done) {
+    it('when using Model#create', function (done) {
       // strict on create
-      Strict.create({content: 'sample2', rouge: 'data'}, function(err, doc) {
+      Strict.create({content: 'sample2', rouge: 'data'}, function (err, doc) {
         assert.equal('sample2', doc.content);
         assert.ok(!('rouge' in doc));
         assert.ok(!doc.rouge);
@@ -103,40 +102,40 @@ describe('document: strict mode:', function() {
       });
     });
 
-    after(function() {
+    after(function () {
       db.close();
     });
   });
 
-  it('nested doc', function(done) {
+  it('nested doc', function (done) {
     var db = start();
 
     var lax = new Schema({
-      name: { last: String }
-    }, { strict: false });
+      name: {last: String}
+    }, {strict: false});
 
     var strict = new Schema({
-      name: { last: String }
+      name: {last: String}
     });
 
     var Lax = db.model('NestedLax', lax, 'nestdoc' + random());
     var Strict = db.model('NestedStrict', strict, 'nestdoc' + random());
 
     var l = new Lax;
-    l.set('name', { last: 'goose', hack: 'xx' });
+    l.set('name', {last: 'goose', hack: 'xx'});
     l = l.toObject();
     assert.equal('goose', l.name.last);
     assert.equal('xx', l.name.hack);
 
     var s = new Strict;
-    s.set({ name: { last: 'goose', hack: 'xx' }});
+    s.set({name: {last: 'goose', hack: 'xx'}});
     s = s.toObject();
     assert.equal('goose', s.name.last);
     assert.ok(!('hack' in s.name));
     assert.ok(!s.name.hack);
 
     s = new Strict;
-    s.set('name', { last: 'goose', hack: 'xx' });
+    s.set('name', {last: 'goose', hack: 'xx'});
     s.set('shouldnt.exist', ':(');
     s = s.toObject();
     assert.equal('goose', s.name.last);
@@ -146,30 +145,30 @@ describe('document: strict mode:', function() {
     db.close(done);
   });
 
-  it('sub doc', function(done) {
+  it('sub doc', function (done) {
     var db = start();
 
     var lax = new Schema({
-      ts: { type: Date, default: Date.now },
+      ts: {type: Date, default: Date.now},
       content: String
-    }, { strict: false });
+    }, {strict: false});
 
     var strict = new Schema({
-      ts: { type: Date, default: Date.now },
+      ts: {type: Date, default: Date.now},
       content: String
     });
 
-    var Lax = db.model('EmbeddedLax', new Schema({ dox: [lax] }, { strict: false }), 'embdoc' + random());
-    var Strict = db.model('EmbeddedStrict', new Schema({ dox: [strict] }, { strict: false }), 'embdoc' + random());
+    var Lax = db.model('EmbeddedLax', new Schema({dox: [lax]}, {strict: false}), 'embdoc' + random());
+    var Strict = db.model('EmbeddedStrict', new Schema({dox: [strict]}, {strict: false}), 'embdoc' + random());
 
-    var l = new Lax({ dox: [{content: 'sample', rouge: 'data'}] });
+    var l = new Lax({dox: [{content: 'sample', rouge: 'data'}]});
     assert.equal(false, l.dox[0].$__.strictMode);
     l = l.dox[0].toObject();
     assert.equal('sample', l.content);
     assert.equal('data', l.rouge);
     assert.ok(l.rouge);
 
-    var s = new Strict({ dox: [{content: 'sample', rouge: 'data'}] });
+    var s = new Strict({dox: [{content: 'sample', rouge: 'data'}]});
     assert.equal(true, s.dox[0].$__.strictMode);
     s = s.dox[0].toObject();
     assert.ok('ts' in s);
@@ -186,7 +185,7 @@ describe('document: strict mode:', function() {
     assert.ok(!s3.dox[0].rouge);
 
     // strict on create
-    Strict.create({dox: [{content: 'sample2', rouge: 'data'}]}, function(err, doc) {
+    Strict.create({dox: [{content: 'sample2', rouge: 'data'}]}, function (err, doc) {
       assert.equal('sample2', doc.dox[0].content);
       assert.ok(!('rouge' in doc.dox[0]));
       assert.ok(!doc.dox[0].rouge);
@@ -194,7 +193,7 @@ describe('document: strict mode:', function() {
     });
   });
 
-  it('virtuals', function(done) {
+  it('virtuals', function (done) {
     var db = start();
 
     var getCount = 0,
@@ -207,11 +206,11 @@ describe('document: strict mode:', function() {
 
     strictSchema
     .virtual('myvirtual')
-    .get(function() {
+    .get(function () {
       getCount++;
       return 'ok';
     })
-    .set(function(v) {
+    .set(function (v) {
       setCount++;
       this.prop = v;
     });
@@ -238,7 +237,7 @@ describe('document: strict mode:', function() {
     db.close(done);
   });
 
-  it('can be overridden during set()', function(done) {
+  it('can be overridden during set()', function (done) {
     var db = start();
 
     var strict = new Schema({
@@ -246,22 +245,22 @@ describe('document: strict mode:', function() {
     });
 
     var Strict = db.model('Strict', strict);
-    var s = new Strict({ bool: true });
+    var s = new Strict({bool: true});
 
     // insert non-schema property
     var doc = s.toObject();
     doc.notInSchema = true;
 
-    Strict.collection.insert(doc, { w: 1 }, function(err) {
+    Strict.collection.insert(doc, {w: 1}, function (err) {
       assert.ifError(err);
-      Strict.findById(doc._id, function(err, doc) {
+      Strict.findById(doc._id, function (err, doc) {
         assert.ifError(err);
         assert.equal(true, doc._doc.bool);
         assert.equal(true, doc._doc.notInSchema);
         doc.bool = undefined;
-        doc.set('notInSchema', undefined, { strict: false });
-        doc.save(function() {
-          Strict.findById(doc._id, function(err, doc) {
+        doc.set('notInSchema', undefined, {strict: false});
+        doc.save(function () {
+          Strict.findById(doc._id, function (err, doc) {
             assert.ifError(err);
             assert.equal(undefined, doc._doc.bool);
             assert.equal(undefined, doc._doc.notInSchema);
@@ -272,7 +271,7 @@ describe('document: strict mode:', function() {
     });
   });
 
-  it('can be overridden during update()', function(done) {
+  it('can be overridden during update()', function (done) {
     var db = start();
 
     var strict = new Schema({
@@ -280,41 +279,37 @@ describe('document: strict mode:', function() {
     });
 
     var Strict = db.model('Strict', strict);
-    var s = new Strict({ bool: true });
+    var s = new Strict({bool: true});
 
     // insert non-schema property
     var doc = s.toObject();
     doc.notInSchema = true;
 
-    Strict.collection.insert(doc, { w: 1 }, function(err) {
+    Strict.collection.insert(doc, {w: 1}, function (err) {
       assert.ifError(err);
 
-      Strict.findById(doc._id, function(err, doc) {
+      Strict.findById(doc._id, function (err, doc) {
         assert.ifError(err);
         assert.equal(true, doc._doc.bool);
         assert.equal(true, doc._doc.notInSchema);
 
-        Strict.update(
-            { _id: doc._id }
-          , { $unset: { bool: 1, notInSchema: 1 }}
-          , { strict: false, w: 1 }
-          , function(err) {
-
-            assert.ifError(err);
-
-            Strict.findById(doc._id, function(err, doc) {
-              db.close();
+        Strict.update({_id: doc._id}, {$unset: {bool: 1, notInSchema: 1}}, {strict: false, w: 1},
+            function (err) {
               assert.ifError(err);
-              assert.equal(undefined, doc._doc.bool);
-              assert.equal(undefined, doc._doc.notInSchema);
-              done();
+
+              Strict.findById(doc._id, function (err, doc) {
+                db.close();
+                assert.ifError(err);
+                assert.equal(undefined, doc._doc.bool);
+                assert.equal(undefined, doc._doc.notInSchema);
+                done();
+              });
             });
-          });
       });
     });
   });
 
-  it('can be overwritten with findOneAndUpdate (gh-1967)', function(done) {
+  it('can be overwritten with findOneAndUpdate (gh-1967)', function (done) {
     var db = start();
 
     var strict = new Schema({
@@ -322,101 +317,97 @@ describe('document: strict mode:', function() {
     });
 
     var Strict = db.model('Strict', strict);
-    var s = new Strict({ bool: true });
+    var s = new Strict({bool: true});
 
     // insert non-schema property
     var doc = s.toObject();
     doc.notInSchema = true;
 
-    Strict.collection.insert(doc, { w: 1 }, function(err) {
+    Strict.collection.insert(doc, {w: 1}, function (err) {
       assert.ifError(err);
 
-      Strict.findById(doc._id, function(err, doc) {
+      Strict.findById(doc._id, function (err, doc) {
         assert.ifError(err);
         assert.equal(true, doc._doc.bool);
         assert.equal(true, doc._doc.notInSchema);
 
-        Strict.findOneAndUpdate(
-            { _id: doc._id }
-          , { $unset: { bool: 1, notInSchema: 1 }}
-          , { strict: false, w: 1 }
-          , function(err) {
-
-            assert.ifError(err);
-
-            Strict.findById(doc._id, function(err, doc) {
+        Strict.findOneAndUpdate({_id: doc._id}, {$unset: {bool: 1, notInSchema: 1}}, {strict: false, w: 1},
+            function (err) {
               assert.ifError(err);
-              assert.equal(undefined, doc._doc.bool);
-              assert.equal(undefined, doc._doc.notInSchema);
-              db.close(done);
+
+              Strict.findById(doc._id, function (err, doc) {
+                assert.ifError(err);
+                assert.equal(undefined, doc._doc.bool);
+                assert.equal(undefined, doc._doc.notInSchema);
+                db.close(done);
+              });
             });
-          });
       });
     });
   });
 
-  describe('"throws" mode', function() {
-    it('throws on set() of unknown property', function(done) {
-      var schema = Schema({ n: String, docs: [{x: [{y: String}]}] });
+  describe('"throws" mode', function () {
+    it('throws on set() of unknown property', function (done) {
+      var schema = Schema({n: String, docs: [{x: [{y: String}]}]});
       schema.set('strict', 'throw');
       var M = mongoose.model('throwStrictSet', schema, 'tss_' + random());
       var m = new M;
 
       var badField = /Field `[\w\.]+` is not in schema/;
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.set('unknown.stuff.is.here', 3);
       }, badField);
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.set('n.something', 3);
       }, badField);
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.set('n.3', 3);
       }, badField);
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.set('z', 3);
       }, badField);
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.set('docs.z', 3);
       }, badField);
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.set('docs.0.z', 3);
       }, badField);
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.set('docs.0.x.z', 3);
       }, badField);
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.set('docs.0.x.4.z', 3);
       }, badField);
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.set('docs.0.x.4.y.z', 3);
       }, badField);
 
       done();
     });
 
-    it('fails with extra fields', function(done) {
+    it('fails with extra fields', function (done) {
       // Simple schema with throws option
       var FooSchema = new mongoose.Schema({
-        name: { type: String }
-      }, {strict: "throw"});
+        name: {type: String}
+      }, {strict: 'throw'});
 
       // Create the model
       var Foo = mongoose.model('Foo1234', FooSchema);
 
-      assert.doesNotThrow(function() {
+      assert.doesNotThrow(function () {
         new Foo({name: 'bar'});
       });
 
-      assert.throws(function() {
+      assert.throws(function () {
         // The extra baz field should throw
         new Foo({name: 'bar', baz: 'bam'});
       }, /Field `baz` is not in schema/);
@@ -424,34 +415,34 @@ describe('document: strict mode:', function() {
       done();
     });
 
-    it('doesnt throw with refs (gh-2665)', function(done) {
+    it('doesnt throw with refs (gh-2665)', function (done) {
       // Simple schema with throws option
       var FooSchema = new mongoose.Schema({
-        name: { type: mongoose.Schema.Types.ObjectId, ref: 'test', required: false, default: null },
-        father: { name: { full: String } }
-      }, {strict: "throw"});
+        name: {type: mongoose.Schema.Types.ObjectId, ref: 'test', required: false, default: null},
+        father: {name: {full: String}}
+      }, {strict: 'throw'});
 
       // Create the model
       var Foo = mongoose.model('Foo', FooSchema);
 
-      assert.doesNotThrow(function() {
-        new Foo({name: mongoose.Types.ObjectId(), father: { name: { full: 'bacon' } } });
+      assert.doesNotThrow(function () {
+        new Foo({name: mongoose.Types.ObjectId(), father: {name: {full: 'bacon'}}});
       });
 
       done();
     });
 
-    it('set nested to num throws ObjectExpectedError (gh-3735)', function(done) {
+    it('set nested to num throws ObjectExpectedError (gh-3735)', function (done) {
       var schema = new Schema({
         resolved: {
-          by: { type: String }
+          by: {type: String}
         }
-      }, { strict: 'throw' });
+      }, {strict: 'throw'});
 
       var Test = mongoose.model('gh3735', schema);
 
-      assert.throws(function() {
-        new Test({ resolved: 123 });
+      assert.throws(function () {
+        new Test({resolved: 123});
       }, /ObjectExpectedError/);
       done();
     });
diff --git a/test/document.test.js b/test/document.test.js
index 7da2fee5c42..cd7f0fd923f 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -36,27 +35,27 @@ TestDocument.prototype.__proto__ = Document.prototype;
  * Set a dummy schema to simulate compilation.
  */
 
-var em = new Schema({ title: String, body: String });
-em.virtual('works').get(function() {
+var em = new Schema({title: String, body: String});
+em.virtual('works').get(function () {
   return 'em virtual works';
 });
 var schema = new Schema({
-  test    : String,
-  oids    : [ObjectId],
-  numbers : [Number],
-  nested  : {
-    age   : Number,
-    cool  : ObjectId,
-    deep  : { x: String },
-    path  : String,
-    setr  : String
+  test: String,
+  oids: [ObjectId],
+  numbers: [Number],
+  nested: {
+    age: Number,
+    cool: ObjectId,
+    deep: {x: String},
+    path: String,
+    setr: String
   },
-  nested2 : {
+  nested2: {
     nested: String,
-    yup   : {
-      nested  : Boolean,
-      yup     : String,
-      age     : Number
+    yup: {
+      nested: Boolean,
+      yup: String,
+      age: Number
     }
   },
   em: [em],
@@ -64,21 +63,21 @@ var schema = new Schema({
 });
 TestDocument.prototype.$__setSchema(schema);
 
-schema.virtual('nested.agePlus2').get(function() {
+schema.virtual('nested.agePlus2').get(function () {
   return this.nested.age + 2;
 });
-schema.virtual('nested.setAge').set(function(v) {
+schema.virtual('nested.setAge').set(function (v) {
   this.nested.age = v;
 });
-schema.path('nested.path').get(function(v) {
+schema.path('nested.path').get(function (v) {
   return (this.nested.age || '') + (v ? v : '');
 });
-schema.path('nested.setr').set(function(v) {
+schema.path('nested.setr').set(function (v) {
   return v + ' setter';
 });
 
 var dateSetterCalled = false;
-schema.path('date').set(function(v) {
+schema.path('date').set(function (v) {
   // should not have been cast to a Date yet
   if (v !== undefined) {
     assert.equal('string', typeof v);
@@ -92,11 +91,11 @@ schema.path('date').set(function(v) {
  * executed.
  */
 
-TestDocument.prototype.hooksTest = function(fn) {
+TestDocument.prototype.hooksTest = function (fn) {
   fn(null, arguments);
 };
 
-var childSchema = new Schema({ counter: Number });
+var childSchema = new Schema({counter: Number});
 
 var parentSchema = new Schema({
   name: String,
@@ -107,25 +106,24 @@ var parentSchema = new Schema({
  * Test.
  */
 
-describe('document', function() {
-
-  describe('shortcut getters', function() {
-    it('return undefined for properties with a null/undefined parent object (gh-1326)', function(done) {
+describe('document', function () {
+  describe('shortcut getters', function () {
+    it('return undefined for properties with a null/undefined parent object (gh-1326)', function (done) {
       var doc = new TestDocument;
-      doc.init({ nested: null });
+      doc.init({nested: null});
       assert.strictEqual(undefined, doc.nested.age);
       done();
     });
 
-    it('work', function(done) {
+    it('work', function (done) {
       var doc = new TestDocument();
       doc.init({
-        test    : 'test',
-        oids    : [],
-        nested  : {
-          age   : 5,
-          cool  : DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
-          path  : 'my path'
+        test: 'test',
+        oids: [],
+        nested: {
+          age: 5,
+          cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
+          path: 'my path'
         }
       });
 
@@ -142,12 +140,12 @@ describe('document', function() {
 
       var doc2 = new TestDocument();
       doc2.init({
-        test    : 'toop',
-        oids    : [],
-        nested  : {
-          age   : 2,
-          cool  : DocumentObjectId.createFromHexString('4cf70857337498f95900001c'),
-          deep  : { x: 'yay' }
+        test: 'toop',
+        oids: [],
+        nested: {
+          age: 2,
+          cool: DocumentObjectId.createFromHexString('4cf70857337498f95900001c'),
+          deep: {x: 'yay'}
         }
       });
 
@@ -173,18 +171,18 @@ describe('document', function() {
 
       doc2.nested2.yup = {
         age: 150,
-        yup: "Yesiree",
+        yup: 'Yesiree',
         nested: true
       };
 
       assert.equal(doc2.nested2.nested, undefined);
       assert.equal(doc2.nested2.yup.nested, true);
-      assert.equal(doc2.nested2.yup.yup, "Yesiree");
+      assert.equal(doc2.nested2.yup.yup, 'Yesiree');
       assert.equal(doc2.nested2.yup.age, 150);
-      doc2.nested2.nested = "y";
-      assert.equal(doc2.nested2.nested, "y");
+      doc2.nested2.nested = 'y';
+      assert.equal(doc2.nested2.nested, 'y');
       assert.equal(doc2.nested2.yup.nested, true);
-      assert.equal(doc2.nested2.yup.yup, "Yesiree");
+      assert.equal(doc2.nested2.yup.yup, 'Yesiree');
       assert.equal(150, doc2.nested2.yup.age);
 
       assert.equal(String(doc2.nested.cool), '4cf70857337498f95900001c');
@@ -194,13 +192,13 @@ describe('document', function() {
     });
   });
 
-  it('test shortcut setters', function(done) {
+  it('test shortcut setters', function (done) {
     var doc = new TestDocument();
 
     doc.init({
-      test    : 'Test',
-      nested  : {
-        age   : 5
+      test: 'Test',
+      nested: {
+        age: 5
       }
     });
 
@@ -209,12 +207,12 @@ describe('document', function() {
     assert.equal('Woot', doc.test);
     assert.equal(true, doc.isModified('test'));
 
-    assert.equal(doc.isModified('nested.age'),false);
+    assert.equal(doc.isModified('nested.age'), false);
     doc.nested.age = 2;
-    assert.equal(2,doc.nested.age);
+    assert.equal(2, doc.nested.age);
     assert.ok(doc.isModified('nested.age'));
 
-    doc.nested = { path: 'overwrite the entire nested object' };
+    doc.nested = {path: 'overwrite the entire nested object'};
     assert.equal(undefined, doc.nested.age);
     assert.equal(1, Object.keys(doc._doc.nested).length);
     assert.equal('overwrite the entire nested object', doc.nested.path);
@@ -222,26 +220,26 @@ describe('document', function() {
     done();
   });
 
-  it('test accessor of id', function(done) {
+  it('test accessor of id', function (done) {
     var doc = new TestDocument();
     assert.ok(doc._id instanceof DocumentObjectId);
     done();
   });
 
-  it('test shortcut of id hexString', function(done) {
+  it('test shortcut of id hexString', function (done) {
     var doc = new TestDocument();
     assert.equal('string', typeof doc.id);
     done();
   });
 
-  it('test toObject clone', function(done) {
+  it('test toObject clone', function (done) {
     var doc = new TestDocument();
     doc.init({
-      test    : 'test',
-      oids    : [],
-      nested  : {
-        age   : 5,
-        cool  : new DocumentObjectId
+      test: 'test',
+      oids: [],
+      nested: {
+        age: 5,
+        cool: new DocumentObjectId
       }
     });
 
@@ -259,23 +257,23 @@ describe('document', function() {
     done();
   });
 
-  it('toObject options', function( done ) {
+  it('toObject options', function (done) {
     var doc = new TestDocument();
 
     doc.init({
-      test    : 'test',
-      oids    : [],
-      em: [{title:'asdf'}],
-      nested  : {
-        age   : 5,
-        cool  : DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
-        path  : 'my path'
+      test: 'test',
+      oids: [],
+      em: [{title: 'asdf'}],
+      nested: {
+        age: 5,
+        cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
+        path: 'my path'
       },
       nested2: {},
       date: new Date
     });
 
-    var clone = doc.toObject({ getters: true, virtuals: false });
+    var clone = doc.toObject({getters: true, virtuals: false});
 
     assert.equal(clone.test, 'test');
     assert.ok(clone.oids instanceof Array);
@@ -286,7 +284,7 @@ describe('document', function() {
     assert.equal(undefined, clone.em[0].works);
     assert.ok(clone.date instanceof Date);
 
-    clone = doc.toObject({ virtuals: true });
+    clone = doc.toObject({virtuals: true});
 
     assert.equal('test', clone.test);
     assert.ok(clone.oids instanceof Array);
@@ -296,23 +294,23 @@ describe('document', function() {
     assert.equal(7, clone.nested.agePlus2);
     assert.equal(clone.em[0].works, 'em virtual works');
 
-    clone = doc.toObject({ getters: true });
+    clone = doc.toObject({getters: true});
 
     assert.equal('test', clone.test);
     assert.ok(clone.oids instanceof Array);
     assert.equal(5, clone.nested.age);
-    assert.equal(clone.nested.cool.toString(),'4c6c2d6240ced95d0e00003c');
+    assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c');
     assert.equal('5my path', clone.nested.path);
     assert.equal(7, clone.nested.agePlus2);
     assert.equal('em virtual works', clone.em[0].works);
 
     // test toObject options
-    doc.schema.options.toObject = { virtuals: true };
-    clone = doc.toObject({ transform: false, virtuals: true });
+    doc.schema.options.toObject = {virtuals: true};
+    clone = doc.toObject({transform: false, virtuals: true});
     assert.equal('test', clone.test);
     assert.ok(clone.oids instanceof Array);
     assert.equal(5, clone.nested.age);
-    assert.equal(clone.nested.cool.toString(),'4c6c2d6240ced95d0e00003c');
+    assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c');
 
     assert.equal('my path', clone.nested.path);
     assert.equal(7, clone.nested.agePlus2);
@@ -320,18 +318,18 @@ describe('document', function() {
     delete doc.schema.options.toObject;
 
     // minimize
-    clone = doc.toObject({ minimize: true });
+    clone = doc.toObject({minimize: true});
     assert.equal(undefined, clone.nested2);
-    clone = doc.toObject({ minimize: true, getters: true });
+    clone = doc.toObject({minimize: true, getters: true});
     assert.equal(undefined, clone.nested2);
-    clone = doc.toObject({ minimize: false });
+    clone = doc.toObject({minimize: false});
     assert.equal('Object', clone.nested2.constructor.name);
     assert.equal(1, Object.keys(clone.nested2).length);
     clone = doc.toObject('2');
     assert.equal(undefined, clone.nested2);
 
-    doc.schema.options.toObject = { minimize: false };
-    clone = doc.toObject({ transform: false, minimize: false });
+    doc.schema.options.toObject = {minimize: false};
+    clone = doc.toObject({transform: false, minimize: false});
     assert.equal('Object', clone.nested2.constructor.name);
     assert.equal(1, Object.keys(clone.nested2).length);
     delete doc.schema.options.toObject;
@@ -347,10 +345,10 @@ describe('document', function() {
     // transform
     doc.schema.options.toObject = {};
     doc.schema.options.toObject.transform = function xform(doc, ret) {
-
-      if ('function' == typeof doc.ownerDocument)
-        // ignore embedded docs
+      // ignore embedded docs
+      if ('function' == typeof doc.ownerDocument) {
         return;
+      }
 
       delete ret.em;
       delete ret.numbers;
@@ -367,38 +365,40 @@ describe('document', function() {
     assert.equal(5, clone.nested.age);
 
     // transform with return value
-    var out = { myid: doc._id.toString() };
-    doc.schema.options.toObject.transform = function(doc, ret) {
-      if ('function' == typeof doc.ownerDocument)
-        // ignore embedded docs
+    var out = {myid: doc._id.toString()};
+    doc.schema.options.toObject.transform = function (doc, ret) {
+      // ignore embedded docs
+      if ('function' == typeof doc.ownerDocument) {
         return;
+      }
 
-      return { myid: ret._id.toString() };
+      return {myid: ret._id.toString()};
     };
 
     clone = doc.toObject();
     assert.deepEqual(out, clone);
 
     // ignored transform with inline options
-    clone = doc.toObject({ x: 1, transform: false });
+    clone = doc.toObject({x: 1, transform: false});
     assert.ok(!('myid' in clone));
     assert.equal('test', clone.test);
     assert.ok(clone.oids instanceof Array);
     assert.equal(5, clone.nested.age);
-    assert.equal(clone.nested.cool.toString(),'4c6c2d6240ced95d0e00003c');
+    assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c');
     assert.equal('my path', clone.nested.path);
     assert.equal('Object', clone.em[0].constructor.name);
 
     // applied transform when inline transform is true
-    clone = doc.toObject({ x: 1 });
+    clone = doc.toObject({x: 1});
     assert.deepEqual(out, clone);
 
     // transform passed inline
     function xform(self, doc, opts) {
-      opts.fields.split(' ').forEach(function(field) {
+      opts.fields.split(' ').forEach(function (field) {
         delete doc[field];
       });
     }
+
     clone = doc.toObject({
       transform: xform,
       fields: '_id em numbers oids nested'
@@ -415,7 +415,7 @@ describe('document', function() {
     done();
   });
 
-  it('toObject transform', function( done ) {
+  it('toObject transform', function (done) {
     var schema = new Schema({
       name: String,
       places: [{type: ObjectId, ref: 'toObject-transform-places'}]
@@ -426,11 +426,9 @@ describe('document', function() {
     });
 
     schemaPlaces.set('toObject', {
-      transform: function(doc, ret) {
-
+      transform: function (doc, ret) {
         // here should be only toObject-transform-places documents
         assert.equal(doc.constructor.modelName, 'toObject-transform-places');
-
         return ret;
       }
     });
@@ -439,10 +437,10 @@ describe('document', function() {
         Test = db.model('toObject-transform', schema),
         Places = db.model('toObject-transform-places', schemaPlaces);
 
-    Places.create({ identity: 'a' },{ identity: 'b' },{ identity: 'c' }, function(err, a, b, c) {
-      Test.create({ name: 'chetverikov', places: [a, b, c]}, function( err ) {
+    Places.create({identity: 'a'}, {identity: 'b'}, {identity: 'c'}, function (err, a, b, c) {
+      Test.create({name: 'chetverikov', places: [a, b, c]}, function (err) {
         assert.ifError(err);
-        Test.findOne({}).populate('places').exec(function( err, docs ) {
+        Test.findOne({}).populate('places').exec(function (err, docs) {
           assert.ifError(err);
 
           docs.toObject({transform: true});
@@ -453,20 +451,20 @@ describe('document', function() {
     });
   });
 
-  it('allows you to skip validation on save (gh-2981)', function(done) {
+  it('allows you to skip validation on save (gh-2981)', function (done) {
     var db = start();
 
     var MyModel = db.model('gh2981',
-      { name: { type: String, required: true } });
+        {name: {type: String, required: true}});
 
     var doc = new MyModel();
-    doc.save({ validateBeforeSave: false }, function(error) {
+    doc.save({validateBeforeSave: false}, function (error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('doesnt use custom toObject options on save', function( done ) {
+  it('doesnt use custom toObject options on save', function (done) {
     var schema = new Schema({
       name: String,
       iWillNotBeDelete: Boolean,
@@ -476,7 +474,7 @@ describe('document', function() {
     });
 
     schema.set('toObject', {
-      transform: function(doc, ret) {
+      transform: function (doc, ret) {
         delete ret.iWillNotBeDelete;
         delete ret.nested.iWillNotBeDeleteToo;
 
@@ -486,28 +484,27 @@ describe('document', function() {
     var db = start(),
         Test = db.model('TestToObject', schema);
 
-    Test.create({ name: 'chetverikov', iWillNotBeDelete: true, 'nested.iWillNotBeDeleteToo': true}, function( err ) {
+    Test.create({name: 'chetverikov', iWillNotBeDelete: true, 'nested.iWillNotBeDeleteToo': true}, function (err) {
       assert.ifError(err);
-      Test.findOne({}, function( err, doc ) {
+      Test.findOne({}, function (err, doc) {
         assert.ifError(err);
 
-        assert.equal( doc._doc.iWillNotBeDelete, true );
-        assert.equal( doc._doc.nested.iWillNotBeDeleteToo, true );
+        assert.equal(doc._doc.iWillNotBeDelete, true);
+        assert.equal(doc._doc.nested.iWillNotBeDeleteToo, true);
 
         db.close(done);
       });
     });
   });
 
-  it('does not apply toObject functions of subdocuments to root document', function( done ) {
-
+  it('does not apply toObject functions of subdocuments to root document', function (done) {
     var subdocSchema = new Schema({
       test: String,
       wow: String
     });
 
     subdocSchema.options.toObject = {};
-    subdocSchema.options.toObject.transform = function(doc, ret) {
+    subdocSchema.options.toObject.transform = function (doc, ret) {
       delete ret.wow;
     };
 
@@ -527,10 +524,9 @@ describe('document', function() {
         test: 'someOtherString',
         wow: 'thisIsAString'
       }]
-    }, function( err, doc ) {
-
+    }, function (err, doc) {
       var obj = doc.toObject({
-        transform: function(doc, ret) {
+        transform: function (doc, ret) {
           ret.phew = 'new';
         }
       });
@@ -542,7 +538,7 @@ describe('document', function() {
     });
   });
 
-  it('handles child schema transforms', function(done) {
+  it('handles child schema transforms', function (done) {
     var db = start();
     var userSchema = new Schema({
       name: String,
@@ -555,13 +551,13 @@ describe('document', function() {
     });
 
     userSchema.options.toObject = {
-      transform: function(doc, ret) {
+      transform: function (doc, ret) {
         delete ret.email;
       }
     };
 
     topicSchema.options.toObject = {
-      transform: function(doc, ret) {
+      transform: function (doc, ret) {
         ret.title = ret.title.toLowerCase();
       }
     };
@@ -571,10 +567,10 @@ describe('document', function() {
     var topic = new Topic({
       title: 'Favorite Foods',
       email: 'a@b.co',
-      followers: [{ name: 'Val', email: 'val@test.co' }]
+      followers: [{name: 'Val', email: 'val@test.co'}]
     });
 
-    var output = topic.toObject({ transform: true });
+    var output = topic.toObject({transform: true});
     assert.equal('favorite foods', output.title);
     assert.equal('a@b.co', output.email);
     assert.equal('Val', output.followers[0].name);
@@ -582,7 +578,7 @@ describe('document', function() {
     db.close(done);
   });
 
-  it('doesnt clobber child schema options when called with no params (gh-2035)', function(done) {
+  it('doesnt clobber child schema options when called with no params (gh-2035)', function (done) {
     var db = start();
     var userSchema = new Schema({
       firstName: String,
@@ -590,33 +586,33 @@ describe('document', function() {
       password: String
     });
 
-    userSchema.virtual('fullName').get(function() {
+    userSchema.virtual('fullName').get(function () {
       return this.firstName + ' ' + this.lastName;
     });
 
-    userSchema.set('toObject', { virtuals: false });
+    userSchema.set('toObject', {virtuals: false});
 
     var postSchema = new Schema({
-      owner: { type: Schema.Types.ObjectId, ref: 'gh-2035-user' },
+      owner: {type: Schema.Types.ObjectId, ref: 'gh-2035-user'},
       content: String
     });
 
-    postSchema.virtual('capContent').get(function() {
+    postSchema.virtual('capContent').get(function () {
       return this.content.toUpperCase();
     });
 
-    postSchema.set('toObject', { virtuals: true });
+    postSchema.set('toObject', {virtuals: true});
     var User = db.model('gh-2035-user', userSchema, 'gh-2035-user');
     var Post = db.model('gh-2035-post', postSchema, 'gh-2035-post');
 
-    var user = new User({ firstName: 'Joe', lastName: 'Smith', password: 'password' });
+    var user = new User({firstName: 'Joe', lastName: 'Smith', password: 'password'});
 
-    user.save(function(err, savedUser) {
+    user.save(function (err, savedUser) {
       assert.ifError(err);
-      var post = new Post({ owner: savedUser._id, content: 'lorem ipsum' });
-      post.save(function(err, savedPost) {
+      var post = new Post({owner: savedUser._id, content: 'lorem ipsum'});
+      post.save(function (err, savedPost) {
         assert.ifError(err);
-        Post.findById(savedPost._id).populate('owner').exec(function(err, newPost) {
+        Post.findById(savedPost._id).populate('owner').exec(function (err, newPost) {
           assert.ifError(err);
           var obj = newPost.toObject();
           assert.equal(obj.owner.fullName, undefined);
@@ -626,33 +622,33 @@ describe('document', function() {
     });
   });
 
-  it('toJSON options', function(done) {
+  it('toJSON options', function (done) {
     var doc = new TestDocument();
 
     doc.init({
-      test    : 'test',
-      oids    : [],
-      em: [{title:'asdf'}],
-      nested  : {
-        age   : 5,
-        cool  : DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
-        path  : 'my path'
+      test: 'test',
+      oids: [],
+      em: [{title: 'asdf'}],
+      nested: {
+        age: 5,
+        cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'),
+        path: 'my path'
       },
       nested2: {}
     });
 
     // override to check if toJSON gets fired
     var path = TestDocument.prototype.schema.path('em');
-    path.casterConstructor.prototype.toJSON = function() {
+    path.casterConstructor.prototype.toJSON = function () {
       return {};
     };
 
-    doc.schema.options.toJSON = { virtuals: true };
+    doc.schema.options.toJSON = {virtuals: true};
     var clone = doc.toJSON();
     assert.equal('test', clone.test);
     assert.ok(clone.oids instanceof Array);
     assert.equal(5, clone.nested.age);
-    assert.equal(clone.nested.cool.toString(),'4c6c2d6240ced95d0e00003c');
+    assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c');
     assert.equal('my path', clone.nested.path);
     assert.equal(7, clone.nested.agePlus2);
     assert.equal('Object', clone.em[0].constructor.name);
@@ -660,7 +656,7 @@ describe('document', function() {
     delete doc.schema.options.toJSON;
     delete path.casterConstructor.prototype.toJSON;
 
-    doc.schema.options.toJSON = { minimize: false };
+    doc.schema.options.toJSON = {minimize: false};
     clone = doc.toJSON();
     assert.equal('Object', clone.nested2.constructor.name);
     assert.equal(1, Object.keys(clone.nested2).length);
@@ -674,7 +670,9 @@ describe('document', function() {
         str;
     try {
       str = JSON.stringify(arr);
-    } catch (_) { err = true; }
+    } catch (_) {
+      err = true;
+    }
     assert.equal(false, err);
     assert.ok(/nested2/.test(str));
     assert.equal('Object', clone.nested2.constructor.name);
@@ -683,9 +681,10 @@ describe('document', function() {
     // transform
     doc.schema.options.toJSON = {};
     doc.schema.options.toJSON.transform = function xform(doc, ret) {
-      if ('function' == typeof doc.ownerDocument)
-        // ignore embedded docs
+      // ignore embedded docs
+      if ('function' == typeof doc.ownerDocument) {
         return;
+      }
 
       delete ret.em;
       delete ret.numbers;
@@ -702,38 +701,40 @@ describe('document', function() {
     assert.equal(5, clone.nested.age);
 
     // transform with return value
-    var out = { myid: doc._id.toString() };
-    doc.schema.options.toJSON.transform = function(doc, ret) {
-      if ('function' == typeof doc.ownerDocument)
-        // ignore embedded docs
+    var out = {myid: doc._id.toString()};
+    doc.schema.options.toJSON.transform = function (doc, ret) {
+      // ignore embedded docs
+      if ('function' == typeof doc.ownerDocument) {
         return;
+      }
 
-      return { myid: ret._id.toString() };
+      return {myid: ret._id.toString()};
     };
 
     clone = doc.toJSON();
     assert.deepEqual(out, clone);
 
     // ignored transform with inline options
-    clone = doc.toJSON({ x: 1, transform: false });
+    clone = doc.toJSON({x: 1, transform: false});
     assert.ok(!('myid' in clone));
     assert.equal('test', clone.test);
     assert.ok(clone.oids instanceof Array);
     assert.equal(5, clone.nested.age);
-    assert.equal(clone.nested.cool.toString(),'4c6c2d6240ced95d0e00003c');
+    assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c');
     assert.equal('my path', clone.nested.path);
     assert.equal('Object', clone.em[0].constructor.name);
 
     // applied transform when inline transform is true
-    clone = doc.toJSON({ x: 1 });
+    clone = doc.toJSON({x: 1});
     assert.deepEqual(out, clone);
 
     // transform passed inline
     function xform(self, doc, opts) {
-      opts.fields.split(' ').forEach(function(field) {
+      opts.fields.split(' ').forEach(function (field) {
         delete doc[field];
       });
     }
+
     clone = doc.toJSON({
       transform: xform,
       fields: '_id em numbers oids nested'
@@ -750,8 +751,8 @@ describe('document', function() {
     done();
   });
 
-  it('jsonifying an object', function(done) {
-    var doc = new TestDocument({ test: 'woot' }),
+  it('jsonifying an object', function (done) {
+    var doc = new TestDocument({test: 'woot'}),
         oidString = doc._id.toString();
     // convert to json string
     var json = JSON.stringify(doc);
@@ -762,14 +763,14 @@ describe('document', function() {
     assert.equal(obj._id, oidString);
     done();
   });
-  it('jsonifying an object\'s populated items works (gh-1376)', function(done) {
+  it('jsonifying an object\'s populated items works (gh-1376)', function (done) {
     var db = start();
     var userSchema, User, groupSchema, Group;
 
     userSchema = Schema({name: String});
     // includes virtual path when 'toJSON'
     userSchema.set('toJSON', {getters: true});
-    userSchema.virtual('hello').get(function() {
+    userSchema.virtual('hello').get(function () {
       return 'Hello, ' + this.name;
     });
     User = db.model('User', userSchema);
@@ -781,11 +782,11 @@ describe('document', function() {
 
     Group = db.model('Group', groupSchema);
 
-    User.create({name: 'Alice'}, {name: 'Bob'}, function(err, alice, bob) {
+    User.create({name: 'Alice'}, {name: 'Bob'}, function (err, alice, bob) {
       assert.ifError(err);
 
-      new Group({name: 'mongoose', _users: [alice, bob]}).save(function(err, group) {
-        Group.findById(group).populate('_users').exec(function(err, group) {
+      new Group({name: 'mongoose', _users: [alice, bob]}).save(function (err, group) {
+        Group.findById(group).populate('_users').exec(function (err, group) {
           assert.ifError(err);
           assert.ok(group.toJSON()._users[0].hello);
           db.close(done);
@@ -794,23 +795,23 @@ describe('document', function() {
     });
   });
 
-  describe('#update', function() {
-    it('returns a Query', function(done) {
+  describe('#update', function () {
+    it('returns a Query', function (done) {
       var mg = new mongoose.Mongoose;
-      var M = mg.model('doc#update', { s: String });
+      var M = mg.model('doc#update', {s: String});
       var doc = new M;
       assert.ok(doc.update() instanceof Query);
       done();
     });
-    it('calling update on document should relay to its model (gh-794)', function(done) {
+    it('calling update on document should relay to its model (gh-794)', function (done) {
       var db = start();
-      var Docs = new Schema({text:String});
+      var Docs = new Schema({text: String});
       var docs = db.model('docRelayUpdate', Docs);
-      var d = new docs({text:'A doc'});
+      var d = new docs({text: 'A doc'});
       var called = false;
-      d.save(function() {
+      d.save(function () {
         var oldUpdate = docs.update;
-        docs.update = function(query, operation) {
+        docs.update = function (query, operation) {
           assert.equal(1, Object.keys(query).length);
           assert.equal(query._id, d._id);
           assert.equal(1, Object.keys(operation).length);
@@ -820,33 +821,32 @@ describe('document', function() {
           docs.update = oldUpdate;
           oldUpdate.apply(docs, arguments);
         };
-        d.update({$set :{text: 'A changed doc'}}, function(err) {
+        d.update({$set: {text: 'A changed doc'}}, function (err) {
           assert.ifError(err);
           assert.equal(true, called);
           db.close(done);
         });
       });
-
     });
   });
 
-  it('toObject should not set undefined values to null', function(done) {
+  it('toObject should not set undefined values to null', function (done) {
     var doc = new TestDocument(),
         obj = doc.toObject();
 
     delete obj._id;
-    assert.deepEqual(obj, { numbers: [], oids: [], em: [] });
+    assert.deepEqual(obj, {numbers: [], oids: [], em: []});
     done();
   });
 
-  describe('Errors', function() {
-    it('MongooseErrors should be instances of Error (gh-209)', function(done) {
+  describe('Errors', function () {
+    it('MongooseErrors should be instances of Error (gh-209)', function (done) {
       var MongooseError = require('../lib/error'),
-          err = new MongooseError("Some message");
+          err = new MongooseError('Some message');
       assert.ok(err instanceof Error);
       done();
     });
-    it('ValidationErrors should be instances of Error', function(done) {
+    it('ValidationErrors should be instances of Error', function (done) {
       var ValidationError = Document.ValidationError,
           err = new ValidationError(new TestDocument);
       assert.ok(err instanceof Error);
@@ -854,23 +854,23 @@ describe('document', function() {
     });
   });
 
-  it('methods on embedded docs should work', function(done) {
+  it('methods on embedded docs should work', function (done) {
     var db = start(),
-        ESchema = new Schema({ name: String });
+        ESchema = new Schema({name: String});
 
-    ESchema.methods.test = function() {
+    ESchema.methods.test = function () {
       return this.name + ' butter';
     };
-    ESchema.statics.ten = function() {
+    ESchema.statics.ten = function () {
       return 10;
     };
 
     var E = db.model('EmbeddedMethodsAndStaticsE', ESchema);
-    var PSchema = new Schema({ embed: [ESchema] });
+    var PSchema = new Schema({embed: [ESchema]});
     var P = db.model('EmbeddedMethodsAndStaticsP', PSchema);
     db.close();
 
-    var p = new P({ embed: [{name: 'peanut'}] });
+    var p = new P({embed: [{name: 'peanut'}]});
     assert.equal('function', typeof p.embed[0].test);
     assert.equal('function', typeof E.ten);
     assert.equal('peanut butter', p.embed[0].test());
@@ -885,9 +885,9 @@ describe('document', function() {
     done();
   });
 
-  it('setting a positional path does not cast value to array', function(done) {
+  it('setting a positional path does not cast value to array', function (done) {
     var doc = new TestDocument;
-    doc.init({ numbers: [1,3] });
+    doc.init({numbers: [1, 3]});
     assert.equal(1, doc.numbers[0]);
     assert.equal(3, doc.numbers[1]);
     doc.set('numbers.1', 2);
@@ -896,69 +896,69 @@ describe('document', function() {
     done();
   });
 
-  it('no maxListeners warning should occur', function(done) {
+  it('no maxListeners warning should occur', function (done) {
     var db = start();
 
     var traced = false;
     var trace = console.trace;
 
-    console.trace = function() {
+    console.trace = function () {
       traced = true;
       console.trace = trace;
     };
 
     var schema = new Schema({
       title: String,
-      embed1: [new Schema({name:String})],
-      embed2: [new Schema({name:String})],
-      embed3: [new Schema({name:String})],
-      embed4: [new Schema({name:String})],
-      embed5: [new Schema({name:String})],
-      embed6: [new Schema({name:String})],
-      embed7: [new Schema({name:String})],
-      embed8: [new Schema({name:String})],
-      embed9: [new Schema({name:String})],
-      embed10: [new Schema({name:String})],
-      embed11: [new Schema({name:String})]
+      embed1: [new Schema({name: String})],
+      embed2: [new Schema({name: String})],
+      embed3: [new Schema({name: String})],
+      embed4: [new Schema({name: String})],
+      embed5: [new Schema({name: String})],
+      embed6: [new Schema({name: String})],
+      embed7: [new Schema({name: String})],
+      embed8: [new Schema({name: String})],
+      embed9: [new Schema({name: String})],
+      embed10: [new Schema({name: String})],
+      embed11: [new Schema({name: String})]
     });
 
     var S = db.model('noMaxListeners', schema);
 
-    new S({ title: "test" });
+    new S({title: 'test'});
     db.close();
     assert.equal(false, traced);
     done();
   });
 
-  it('unselected required fields should pass validation', function(done) {
+  it('unselected required fields should pass validation', function (done) {
     var db = start(),
-        Tschema = new Schema({ name: String, req: { type: String, required: true }}),
+        Tschema = new Schema({name: String, req: {type: String, required: true}}),
         T = db.model('unselectedRequiredFieldValidation', Tschema);
 
-    var t = new T({ name: 'teeee', req: 'i am required' });
-    t.save(function(err) {
+    var t = new T({name: 'teeee', req: 'i am required'});
+    t.save(function (err) {
       assert.ifError(err);
-      T.findById(t).select('name').exec(function(err, t) {
+      T.findById(t).select('name').exec(function (err, t) {
         assert.ifError(err);
         assert.equal(undefined, t.req);
         t.name = 'wooo';
-        t.save(function(err) {
+        t.save(function (err) {
           assert.ifError(err);
 
-          T.findById(t).select('name').exec(function(err, t) {
+          T.findById(t).select('name').exec(function (err, t) {
             assert.ifError(err);
             t.req = undefined;
-            t.save(function(err) {
+            t.save(function (err) {
               err = String(err);
               var invalid = /Path `req` is required./.test(err);
               assert.ok(invalid);
               t.req = 'it works again';
-              t.save(function(err) {
+              t.save(function (err) {
                 assert.ifError(err);
 
-                T.findById(t).select('_id').exec(function(err, t) {
+                T.findById(t).select('_id').exec(function (err, t) {
                   assert.ifError(err);
-                  t.save(function(err) {
+                  t.save(function (err) {
                     assert.ifError(err);
                     db.close(done);
                   });
@@ -971,32 +971,35 @@ describe('document', function() {
     });
   });
 
-  describe('#validate', function() {
+  describe('#validate', function () {
     var collection = 'validateschema_' + random();
 
-    it('works (gh-891)', function(done) {
+    it('works (gh-891)', function (done) {
       var db = start();
       var schema = null;
       var called = false;
 
-      var validate = [ function() { called = true; return true; }, 'BAM'];
+      var validate = [function () {
+        called = true;
+        return true;
+      }, 'BAM'];
 
       schema = new Schema({
-        prop: { type: String, required: true, validate: validate },
-        nick: { type: String, required: true }
+        prop: {type: String, required: true, validate: validate},
+        nick: {type: String, required: true}
       });
 
       var M = db.model('validateSchema', schema, collection);
-      var m = new M({ prop: 'gh891', nick: 'validation test' });
-      m.save(function(err) {
+      var m = new M({prop: 'gh891', nick: 'validation test'});
+      m.save(function (err) {
         assert.ifError(err);
         assert.equal(true, called);
         called = false;
-        M.findById(m, 'nick', function(err, m) {
+        M.findById(m, 'nick', function (err, m) {
           assert.equal(false, called);
           assert.ifError(err);
           m.nick = 'gh-891';
-          m.save(function(err) {
+          m.save(function (err) {
             assert.equal(false, called);
             assert.ifError(err);
             db.close(done);
@@ -1005,66 +1008,68 @@ describe('document', function() {
       });
     });
 
-    it('can return a promise', function(done) {
+    it('can return a promise', function (done) {
       var db = start();
       var schema = null;
 
-      var validate = [ function() { return true; }, 'BAM'];
+      var validate = [function () {
+        return true;
+      }, 'BAM'];
 
       schema = new Schema({
-        prop: { type: String, required: true, validate: validate },
-        nick: { type: String, required: true }
+        prop: {type: String, required: true, validate: validate},
+        nick: {type: String, required: true}
       });
 
       var M = db.model('validateSchemaPromise', schema, collection);
-      var m = new M({ prop: 'gh891', nick: 'validation test' });
-      var mBad = new M({ prop: 'other' });
+      var m = new M({prop: 'gh891', nick: 'validation test'});
+      var mBad = new M({prop: 'other'});
 
       var promise = m.validate();
-      promise.then(function() {
+      promise.then(function () {
         var promise2 = mBad.validate();
-        promise2.onReject(function(err) {
+        promise2.onReject(function (err) {
           assert.ok(!!err);
           clearTimeout(timeout);
           db.close(done);
         });
       });
 
-      var timeout = setTimeout(function() {
+      var timeout = setTimeout(function () {
         db.close();
-        throw new Error("Promise not fulfilled!");
+        throw new Error('Promise not fulfilled!');
       }, 500);
     });
 
-    it('doesnt have stale cast errors (gh-2766)', function(done) {
+    it('doesnt have stale cast errors (gh-2766)', function (done) {
       var db = start();
-      var testSchema = new Schema({ name: String });
+      var testSchema = new Schema({name: String});
       var M = db.model('gh2766', testSchema);
 
-      var m = new M({ _id: 'this is not a valid _id' });
+      var m = new M({_id: 'this is not a valid _id'});
       assert.ok(!m.$isValid('_id'));
       assert.ok(m.validateSync().errors['_id'].name, 'CastError');
 
       m._id = '000000000000000000000001';
       assert.ok(m.$isValid('_id'));
       assert.ifError(m.validateSync());
-      m.validate(function(error) {
+      m.validate(function (error) {
         assert.ifError(error);
         db.close(done);
       });
     });
 
-    it('cast errors persist across validate() calls (gh-2766)', function(done) {
+    it('cast errors persist across validate() calls (gh-2766)', function (done) {
       var db = start();
-      var testSchema = new Schema({ name: String });
+      var testSchema = new Schema({name: String});
       var M = db.model('gh2766', testSchema);
 
-      var m = new M({ _id: 'this is not a valid _id' });
+      var m = new M({_id: 'this is not a valid _id'});
       assert.ok(!m.$isValid('_id'));
-      m.validate(function(error) {
+      m.validate(function (error) {
         assert.ok(error);
         assert.equal(error.errors['_id'].name, 'CastError');
-        m.validate(function(error) {
+        m.validate(function (error) {
           assert.ok(error);
           assert.equal(error.errors['_id'].name, 'CastError');
 
@@ -1077,54 +1082,54 @@ describe('document', function() {
       });
     });
 
-    it('returns a promise when there are no validators', function(done) {
+    it('returns a promise when there are no validators', function (done) {
       var db = start();
       var schema = null;
 
-      schema = new Schema({ _id : String });
+      schema = new Schema({_id: String});
 
       var M = db.model('validateSchemaPromise2', schema, collection);
       var m = new M();
 
       var promise = m.validate();
-      promise.then(function() {
+      promise.then(function () {
         clearTimeout(timeout);
         db.close();
         done();
       });
 
-      var timeout = setTimeout(function() {
+      var timeout = setTimeout(function () {
         db.close();
-        throw new Error("Promise not fulfilled!");
+        throw new Error('Promise not fulfilled!');
       }, 500);
     });
 
-    describe('works on arrays', function() {
+    describe('works on arrays', function () {
       var db;
 
-      before(function(done) {
+      before(function (done) {
         db = start();
         done();
       });
 
-      after(function(done) {
+      after(function (done) {
         db.close(done);
       });
 
-      it('with required', function(done) {
+      it('with required', function (done) {
         var schema = new Schema({
           name: String,
-          arr : { type: [], required: true }
+          arr: {type: [], required: true}
         });
         var M = db.model('validateSchema-array1', schema, collection);
-        var m = new M({ name: 'gh1109-1' });
-        m.save(function(err) {
+        var m = new M({name: 'gh1109-1'});
+        m.save(function (err) {
           assert.ok(/Path `arr` is required/.test(err));
           m.arr = [];
-          m.save(function(err) {
+          m.save(function (err) {
             assert.ok(/Path `arr` is required/.test(err));
             m.arr.push('works');
-            m.save(function(err) {
+            m.save(function (err) {
               assert.ifError(err);
               done();
             });
@@ -1132,7 +1137,7 @@ describe('document', function() {
         });
       });
 
-      it('with custom validator', function(done) {
+      it('with custom validator', function (done) {
         var called = false;
 
         function validator(val) {
@@ -1143,18 +1148,18 @@ describe('document', function() {
         var validate = [validator, 'BAM'];
 
         var schema = new Schema({
-          arr : { type: [], validate: validate }
+          arr: {type: [], validate: validate}
         });
 
         var M = db.model('validateSchema-array2', schema, collection);
-        var m = new M({ name: 'gh1109-2', arr: [1] });
+        var m = new M({name: 'gh1109-2', arr: [1]});
         assert.equal(false, called);
-        m.save(function(err) {
+        m.save(function (err) {
           assert.equal('ValidationError: BAM', String(err));
           assert.equal(true, called);
           m.arr.push(2);
           called = false;
-          m.save(function(err) {
+          m.save(function (err) {
             assert.equal(true, called);
             assert.ifError(err);
             done();
@@ -1162,7 +1167,7 @@ describe('document', function() {
         });
       });
 
-      it('with both required + custom validator', function(done) {
+      it('with both required + custom validator', function (done) {
         function validator(val) {
           return val && val.length > 1;
         }
@@ -1170,18 +1175,18 @@ describe('document', function() {
         var validate = [validator, 'BAM'];
 
         var schema = new Schema({
-          arr : { type: [], required: true, validate: validate }
+          arr: {type: [], required: true, validate: validate}
         });
 
         var M = db.model('validateSchema-array3', schema, collection);
-        var m = new M({ name: 'gh1109-3' });
-        m.save(function(err) {
+        var m = new M({name: 'gh1109-3'});
+        m.save(function (err) {
           assert.equal(err.errors.arr.message, 'Path `arr` is required.');
           m.arr.push({nice: true});
-          m.save(function(err) {
+          m.save(function (err) {
             assert.equal(String(err), 'ValidationError: BAM');
             m.arr.push(95);
-            m.save(function(err) {
+            m.save(function (err) {
               assert.ifError(err);
               done();
             });
@@ -1190,14 +1195,14 @@ describe('document', function() {
       });
     });
 
-    it("validator should run only once gh-1743", function(done) {
+    it('validator should run only once gh-1743', function (done) {
       var count = 0;
       var db = start();
 
       var Control = new Schema({
         test: {
           type: String,
-          validate: function(value, done) {
+          validate: function (value, done) {
             count++;
             return done(true);
           }
@@ -1211,24 +1216,24 @@ describe('document', function() {
 
       var post = new Post({
         controls: [{
-          test: "xx"
+          test: 'xx'
         }]
       });
 
-      post.save(function() {
+      post.save(function () {
         assert.equal(count, 1);
         db.close(done);
       });
     });
 
-    it("validator should run only once per sub-doc gh-1743", function(done) {
+    it('validator should run only once per sub-doc gh-1743', function (done) {
       var count = 0;
       var db = start();
 
       var Control = new Schema({
         test: {
           type: String,
-          validate: function(value, done) {
+          validate: function (value, done) {
             count++;
             return done(true);
           }
@@ -1241,24 +1246,21 @@ describe('document', function() {
       var Post = db.model('post', PostSchema);
 
       var post = new Post({
-        controls: [
-            {
-              test: "xx"
-            },
-            {
-              test: "yy"
-            }
-        ]
+        controls: [{
+          test: 'xx'
+        }, {
+          test: 'yy'
+        }]
       });
 
-      post.save(function() {
+      post.save(function () {
         assert.equal(count, post.controls.length);
         db.close(done);
       });
     });
 
 
-    it("validator should run in parallel", function(done) {
+    it('validator should run in parallel', function (done) {
       // we set the time out to be double that of the validator - 1 (so that running in serial will be greater then that)
       this.timeout(1000);
       var db = start();
@@ -1277,39 +1279,33 @@ describe('document', function() {
 
       var MWSV = db.model('mwv', new Schema({subs: [SchemaWithValidator]}));
       var m = new MWSV({
-        subs: [
-            {
-              preference: "xx"
-            },
-            {
-              preference: "yy"
-            },
-            {
-              preference: "1"
-            },
-            {
-              preference: "2"
-            }
-        ]
+        subs: [{
+          preference: 'xx'
+        }, {
+          preference: 'yy'
+        }, {
+          preference: '1'
+        }, {
+          preference: '2'
+        }]
       });
 
-      m.save(function(err) {
+      m.save(function (err) {
         assert.ifError(err);
         assert.equal(count, 4);
         db.close(done);
       });
     });
-
   });
 
-  it('#invalidate', function(done) {
+  it('#invalidate', function (done) {
     var db = start();
     var InvalidateSchema = null;
     var Post = null;
     var post = null;
 
-    InvalidateSchema = new Schema({ prop: { type: String } },
-      { strict: false });
+    InvalidateSchema = new Schema({prop: {type: String}},
+        {strict: false});
 
     mongoose.model('InvalidateSchema', InvalidateSchema);
 
@@ -1318,15 +1314,15 @@ describe('document', function() {
     post.set({baz: 'val'});
     post.invalidate('baz', 'validation failed for path {PATH}');
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ok(err instanceof MongooseError);
       assert.ok(err instanceof ValidationError);
       assert.ok(err.errors.baz instanceof ValidatorError);
-      assert.equal(err.errors.baz.message,'validation failed for path baz');
-      assert.equal(err.errors.baz.kind,'user defined');
-      assert.equal(err.errors.baz.path,'baz');
+      assert.equal(err.errors.baz.message, 'validation failed for path baz');
+      assert.equal(err.errors.baz.kind, 'user defined');
+      assert.equal(err.errors.baz.path, 'baz');
 
-      post.save(function(err) {
+      post.save(function (err) {
         db.close();
         assert.strictEqual(err, null);
         done();
@@ -1334,8 +1330,8 @@ describe('document', function() {
     });
   });
 
-  describe('#equals', function() {
-    describe('should work', function() {
+  describe('#equals', function () {
+    describe('should work', function () {
       var db;
       var S;
       var N;
@@ -1343,53 +1339,53 @@ describe('document', function() {
       var B;
       var M;
 
-      before(function() {
+      before(function () {
         db = start();
-        S = db.model('equals-S', new Schema({ _id: String }));
-        N = db.model('equals-N', new Schema({ _id: Number }));
-        O = db.model('equals-O', new Schema({ _id: Schema.ObjectId }));
-        B = db.model('equals-B', new Schema({ _id: Buffer }));
-        M = db.model('equals-I', new Schema({ name: String }, { _id: false }));
+        S = db.model('equals-S', new Schema({_id: String}));
+        N = db.model('equals-N', new Schema({_id: Number}));
+        O = db.model('equals-O', new Schema({_id: Schema.ObjectId}));
+        B = db.model('equals-B', new Schema({_id: Buffer}));
+        M = db.model('equals-I', new Schema({name: String}, {_id: false}));
       });
 
-      after(function(done) {
+      after(function (done) {
         db.close(done);
       });
 
-      it('with string _ids', function(done) {
-        var s1 = new S({ _id: 'one' });
-        var s2 = new S({ _id: 'one' });
+      it('with string _ids', function (done) {
+        var s1 = new S({_id: 'one'});
+        var s2 = new S({_id: 'one'});
         assert.ok(s1.equals(s2));
         done();
       });
-      it('with number _ids', function(done) {
-        var n1 = new N({ _id: 0 });
-        var n2 = new N({ _id: 0 });
+      it('with number _ids', function (done) {
+        var n1 = new N({_id: 0});
+        var n2 = new N({_id: 0});
         assert.ok(n1.equals(n2));
         done();
       });
-      it('with ObjectId _ids', function(done) {
+      it('with ObjectId _ids', function (done) {
         var id = new mongoose.Types.ObjectId;
-        var o1 = new O({ _id: id });
-        var o2 = new O({ _id: id });
+        var o1 = new O({_id: id});
+        var o2 = new O({_id: id});
         assert.ok(o1.equals(o2));
 
         id = String(new mongoose.Types.ObjectId);
-        o1 = new O({ _id: id });
-        o2 = new O({ _id: id });
+        o1 = new O({_id: id});
+        o2 = new O({_id: id});
         assert.ok(o1.equals(o2));
         done();
       });
-      it('with Buffer _ids', function(done) {
-        var n1 = new B({ _id: 0 });
-        var n2 = new B({ _id: 0 });
+      it('with Buffer _ids', function (done) {
+        var n1 = new B({_id: 0});
+        var n2 = new B({_id: 0});
         assert.ok(n1.equals(n2));
         done();
       });
-      it('with _id disabled (gh-1687)', function(done) {
+      it('with _id disabled (gh-1687)', function (done) {
         var m1 = new M;
         var m2 = new M;
-        assert.doesNotThrow(function() {
+        assert.doesNotThrow(function () {
           m1.equals(m2);
         });
         done();
@@ -1397,9 +1393,9 @@ describe('document', function() {
     });
   });
 
-  describe('setter', function() {
-    describe('order', function() {
-      it('is applied correctly', function(done) {
+  describe('setter', function () {
+    describe('order', function () {
+      it('is applied correctly', function (done) {
         var date = 'Thu Aug 16 2012 09:45:59 GMT-0700';
         var d = new TestDocument();
         dateSetterCalled = false;
@@ -1413,39 +1409,39 @@ describe('document', function() {
       });
     });
 
-    it('works with undefined (gh-1892)', function(done) {
+    it('works with undefined (gh-1892)', function (done) {
       var d = new TestDocument();
       d.nested.setr = undefined;
       assert.equal('undefined setter', d.nested.setr);
       dateSetterCalled = false;
       d.date = undefined;
-      d.validate(function(err) {
+      d.validate(function (err) {
         assert.ifError(err);
         assert.ok(dateSetterCalled);
         done();
       });
     });
 
-    describe('on nested paths', function() {
-      describe('using set(path, object)', function() {
-        it('overwrites the entire object', function(done) {
+    describe('on nested paths', function () {
+      describe('using set(path, object)', function () {
+        it('overwrites the entire object', function (done) {
           var doc = new TestDocument();
 
           doc.init({
-            test    : 'Test',
-            nested  : {
-              age   : 5
+            test: 'Test',
+            nested: {
+              age: 5
             }
           });
 
-          doc.set('nested', { path: 'overwrite the entire nested object' });
+          doc.set('nested', {path: 'overwrite the entire nested object'});
           assert.equal(undefined, doc.nested.age);
           assert.equal(1, Object.keys(doc._doc.nested).length);
           assert.equal('overwrite the entire nested object', doc.nested.path);
           assert.ok(doc.isModified('nested'));
 
           // vs merging using doc.set(object)
-          doc.set({ test: 'Test', nested: { age: 4 }});
+          doc.set({test: 'Test', nested: {age: 4}});
           assert.equal('4overwrite the entire nested object', doc.nested.path);
           assert.equal(4, doc.nested.age);
           assert.equal(2, Object.keys(doc._doc.nested).length);
@@ -1453,14 +1449,14 @@ describe('document', function() {
 
           doc = new TestDocument();
           doc.init({
-            test    : 'Test',
-            nested  : {
-              age   : 5
+            test: 'Test',
+            nested: {
+              age: 5
             }
           });
 
           // vs merging using doc.set(path, object, {merge: true})
-          doc.set('nested', { path: 'did not overwrite the nested object' }, {merge: true});
+          doc.set('nested', {path: 'did not overwrite the nested object'}, {merge: true});
           assert.equal('5did not overwrite the nested object', doc.nested.path);
           assert.equal(5, doc.nested.age);
           assert.equal(3, Object.keys(doc._doc.nested).length);
@@ -1468,25 +1464,25 @@ describe('document', function() {
 
           doc = new TestDocument();
           doc.init({
-            test    : 'Test',
-            nested  : {
-              age   : 5
+            test: 'Test',
+            nested: {
+              age: 5
             }
           });
 
-          doc.set({ test: 'Test', nested: { age: 5 }});
+          doc.set({test: 'Test', nested: {age: 5}});
           assert.ok(!doc.isModified());
           assert.ok(!doc.isModified('test'));
           assert.ok(!doc.isModified('nested'));
           assert.ok(!doc.isModified('nested.age'));
 
-          doc.nested = { path: 'overwrite the entire nested object', age: 5 };
+          doc.nested = {path: 'overwrite the entire nested object', age: 5};
           assert.equal(5, doc.nested.age);
           assert.equal(2, Object.keys(doc._doc.nested).length);
           assert.equal('5overwrite the entire nested object', doc.nested.path);
           assert.ok(doc.isModified('nested'));
 
-          doc.nested.deep = { x: 'Hank and Marie' };
+          doc.nested.deep = {x: 'Hank and Marie'};
           assert.equal(3, Object.keys(doc._doc.nested).length);
           assert.equal('5overwrite the entire nested object', doc.nested.path);
           assert.ok(doc.isModified('nested'));
@@ -1494,13 +1490,13 @@ describe('document', function() {
 
           doc = new TestDocument();
           doc.init({
-            test    : 'Test',
-            nested  : {
-              age   : 5
+            test: 'Test',
+            nested: {
+              age: 5
             }
           });
 
-          doc.set('nested.deep', { x: 'Hank and Marie' });
+          doc.set('nested.deep', {x: 'Hank and Marie'});
           assert.equal(2, Object.keys(doc._doc.nested).length);
           assert.equal(1, Object.keys(doc._doc.nested.deep).length);
           assert.ok(doc.isModified('nested'));
@@ -1512,9 +1508,9 @@ describe('document', function() {
           done();
         });
 
-        it('gh-1954', function(done) {
+        it('gh-1954', function (done) {
           var schema = new Schema({
-            schedule: [ new Schema({open: Number, close: Number}) ]
+            schedule: [new Schema({open: Number, close: Number})]
           });
 
           var M = mongoose.model('Blog', schema);
@@ -1538,28 +1534,27 @@ describe('document', function() {
         });
       });
 
-      describe('when overwriting with a document instance', function() {
-        it('does not cause StackOverflows (gh-1234)', function(done) {
-          var doc = new TestDocument({ nested: { age: 35 }});
+      describe('when overwriting with a document instance', function () {
+        it('does not cause StackOverflows (gh-1234)', function (done) {
+          var doc = new TestDocument({nested: {age: 35}});
           doc.nested = doc.nested;
-          assert.doesNotThrow(function() {
+          assert.doesNotThrow(function () {
             doc.nested.age;
           });
           done();
         });
       });
     });
-
   });
 
-  describe('virtual', function() {
-    describe('setter', function() {
+  describe('virtual', function () {
+    describe('setter', function () {
       var val;
       var M;
 
-      before(function(done) {
-        var schema = new mongoose.Schema({ v: Number });
-        schema.virtual('thang').set(function(v) {
+      before(function (done) {
+        var schema = new mongoose.Schema({v: Number});
+        schema.virtual('thang').set(function (v) {
           val = v;
         });
 
@@ -1569,47 +1564,47 @@ describe('document', function() {
         done();
       });
 
-      it('works with objects', function(done) {
-        new M({ thang: {}});
+      it('works with objects', function (done) {
+        new M({thang: {}});
         assert.deepEqual({}, val);
         done();
       });
-      it('works with arrays', function(done) {
-        new M({ thang: []});
+      it('works with arrays', function (done) {
+        new M({thang: []});
         assert.deepEqual([], val);
         done();
       });
-      it('works with numbers', function(done) {
-        new M({ thang: 4});
+      it('works with numbers', function (done) {
+        new M({thang: 4});
         assert.deepEqual(4, val);
         done();
       });
-      it('works with strings', function(done) {
-        new M({ thang: '3'});
+      it('works with strings', function (done) {
+        new M({thang: '3'});
         assert.deepEqual('3', val);
         done();
       });
     });
   });
 
-  describe('gh-2082', function() {
-    it('works', function(done) {
+  describe('gh-2082', function () {
+    it('works', function (done) {
       var db = start();
       var Parent = db.model('gh2082', parentSchema, 'gh2082');
 
       var parent = new Parent({name: 'Hello'});
-      parent.save(function(err, parent) {
+      parent.save(function (err, parent) {
         assert.ifError(err);
-        parent.children.push( {counter: 0} );
-        parent.save(function(err, parent) {
+        parent.children.push({counter: 0});
+        parent.save(function (err, parent) {
           assert.ifError(err);
           parent.children[0].counter += 1;
-          parent.save(function(err, parent) {
+          parent.save(function (err, parent) {
             assert.ifError(err);
             parent.children[0].counter += 1;
-            parent.save(function(err) {
+            parent.save(function (err) {
               assert.ifError(err);
-              Parent.findOne({}, function(error, parent) {
+              Parent.findOne({}, function (error, parent) {
                 assert.ifError(error);
                 assert.equal(2, parent.children[0].counter);
                 db.close(done);
@@ -1621,18 +1616,18 @@ describe('document', function() {
     });
   });
 
-  describe('gh-1933', function() {
-    it('works', function(done) {
+  describe('gh-1933', function () {
+    it('works', function (done) {
       var db = start();
-      var M = db.model('gh1933', new Schema({ id: String, field: Number }), 'gh1933');
+      var M = db.model('gh1933', new Schema({id: String, field: Number}), 'gh1933');
 
-      M.create({}, function(error) {
+      M.create({}, function (error) {
         assert.ifError(error);
-        M.findOne({}, function(error, doc) {
+        M.findOne({}, function (error, doc) {
           assert.ifError(error);
           doc.__v = 123;
-          doc.field = 5;//.push({ _id: '123', type: '456' });
-          doc.save(function(error) {
+          doc.field = 5; // .push({ _id: '123', type: '456' });
+          doc.save(function (error) {
             assert.ifError(error);
             db.close(done);
           });
@@ -1641,10 +1636,10 @@ describe('document', function() {
     });
   });
 
-  describe('gh-1638', function() {
-    it('works', function(done) {
+  describe('gh-1638', function () {
+    it('works', function (done) {
       var ItemChildSchema = new mongoose.Schema({
-        name: { type: String, required: true, default: "hello" }
+        name: {type: String, required: true, default: 'hello'}
       });
 
       var ItemParentSchema = new mongoose.Schema({
@@ -1655,19 +1650,19 @@ describe('document', function() {
       var ItemParent = db.model('gh-1638-1', ItemParentSchema, 'gh-1638-1');
       var ItemChild = db.model('gh-1638-2', ItemChildSchema, 'gh-1638-2');
 
-      var c1 = new ItemChild({ name: 'first child' });
-      var c2 = new ItemChild({ name: 'second child' });
+      var c1 = new ItemChild({name: 'first child'});
+      var c2 = new ItemChild({name: 'second child'});
 
       var p = new ItemParent({
         children: [c1, c2]
       });
 
-      p.save(function(error) {
+      p.save(function (error) {
         assert.ifError(error);
 
         c2.name = 'updated 2';
         p.children = [c2];
-        p.save(function(error, doc) {
+        p.save(function (error, doc) {
           assert.ifError(error);
           assert.equal(1, doc.children.length);
           db.close(done);
@@ -1676,8 +1671,8 @@ describe('document', function() {
     });
   });
 
-  describe('gh-2434', function() {
-    it('will save the new value', function(done) {
+  describe('gh-2434', function () {
+    it('will save the new value', function (done) {
       var ItemSchema = new mongoose.Schema({
         st: Number,
         s: []
@@ -1686,16 +1681,16 @@ describe('document', function() {
       var db = start();
       var Item = db.model('gh-2434', ItemSchema, 'gh-2434');
 
-      var item = new Item({ st: 1 });
+      var item = new Item({st: 1});
 
-      item.save(function(error) {
+      item.save(function (error) {
         assert.ifError(error);
         item.st = 3;
         item.s = [];
-        item.save(function(error) {
+        item.save(function (error) {
           assert.ifError(error);
           // item.st is 3 but may not be saved to DB
-          Item.findById(item._id, function(error, doc) {
+          Item.findById(item._id, function (error, doc) {
             assert.ifError(error);
             assert.equal(3, doc.st);
             db.close(done);
@@ -1705,33 +1700,33 @@ describe('document', function() {
     });
   });
 
-  it('properly calls queue functions (gh-2856)', function(done) {
+  it('properly calls queue functions (gh-2856)', function (done) {
     var personSchema = new mongoose.Schema({
       name: String
     });
 
     var db = start();
     var calledName;
-    personSchema.methods.fn = function() {
+    personSchema.methods.fn = function () {
       calledName = this.name;
     };
     personSchema.queue('fn');
 
     var Person = db.model('gh2856', personSchema, 'gh2856');
-    new Person({ name: 'Val' });
+    new Person({name: 'Val'});
     assert.equal(calledName, 'Val');
     db.close(done);
   });
 
-  it('applies toJSON transform correctly for populated docs (gh-2910) (gh-2990)', function(done) {
+  it('applies toJSON transform correctly for populated docs (gh-2910) (gh-2990)', function (done) {
     var db = start();
     var parentSchema = mongoose.Schema({
-      c: { type: mongoose.Schema.Types.ObjectId, ref: 'gh-2910-1' }
+      c: {type: mongoose.Schema.Types.ObjectId, ref: 'gh-2910-1'}
     });
 
     var called = [];
     parentSchema.options.toJSON = {
-      transform: function(doc, ret) {
+      transform: function (doc, ret) {
         called.push(ret);
         return ret;
       }
@@ -1743,7 +1738,7 @@ describe('document', function() {
 
     var childCalled = [];
     childSchema.options.toJSON = {
-      transform: function(doc, ret) {
+      transform: function (doc, ret) {
         childCalled.push(ret);
         return ret;
       }
@@ -1752,9 +1747,9 @@ describe('document', function() {
     var Child = db.model('gh-2910-1', childSchema);
     var Parent = db.model('gh-2910-0', parentSchema);
 
-    Child.create({ name: 'test' }, function(error, c) {
-      Parent.create({ c: c._id }, function(error, p) {
-        Parent.findOne({ _id: p._id }).populate('c').exec(function(error, p) {
+    Child.create({name: 'test'}, function (error, c) {
+      Parent.create({c: c._id}, function (error, p) {
+        Parent.findOne({_id: p._id}).populate('c').exec(function (error, p) {
           var doc = p.toJSON();
           assert.equal(called.length, 1);
           assert.equal(called[0]._id.toString(), p._id.toString());
@@ -1767,7 +1762,7 @@ describe('document', function() {
 
           // JSON.stringify() passes field name, so make sure we don't treat
           // that as a param to toJSON (gh-2990)
-          doc = JSON.parse(JSON.stringify({ parent: p })).parent;
+          doc = JSON.parse(JSON.stringify({parent: p})).parent;
           assert.equal(called.length, 1);
           assert.equal(called[0]._id.toString(), p._id.toString());
           assert.equal(doc._id.toString(), p._id.toString());
@@ -1780,25 +1775,27 @@ describe('document', function() {
     });
   });
 
-  it('setters firing with objects on real paths (gh-2943)', function(done) {
+  it('setters firing with objects on real paths (gh-2943)', function (done) {
     var M = mongoose.model('gh2943', {
       myStr: {
-        type: String, set: function(v) { return v.value; }
+        type: String, set: function (v) {
+          return v.value;
+        }
       },
       otherStr: String
     });
 
-    var t = new M({ myStr: { value: 'test' } });
+    var t = new M({myStr: {value: 'test'}});
     assert.equal(t.myStr, 'test');
 
-    new M({ otherStr: { value: 'test' } });
+    new M({otherStr: {value: 'test'}});
     assert.ok(!t.otherStr);
 
     done();
   });
 
-  describe('gh-2782', function() {
-    it('should set data from a sub doc', function(done) {
+  describe('gh-2782', function () {
+    it('should set data from a sub doc', function (done) {
       var schema1 = new mongoose.Schema({
         data: {
           email: String
@@ -1810,7 +1807,7 @@ describe('document', function() {
       var Model1 = mongoose.model('gh-2782-1', schema1);
       var Model2 = mongoose.model('gh-2782-2', schema2);
 
-      var doc1 = new Model1({ 'data.email': 'some@example.com' });
+      var doc1 = new Model1({'data.email': 'some@example.com'});
       assert.equal(doc1.data.email, 'some@example.com');
       var doc2 = new Model2();
       doc2.set(doc1.data);
@@ -1819,7 +1816,7 @@ describe('document', function() {
     });
   });
 
-  it('set data from subdoc keys (gh-3346)', function(done) {
+  it('set data from subdoc keys (gh-3346)', function (done) {
     var schema1 = new mongoose.Schema({
       data: {
         email: String
@@ -1827,38 +1824,38 @@ describe('document', function() {
     });
     var Model1 = mongoose.model('gh3346', schema1);
 
-    var doc1 = new Model1({ 'data.email': 'some@example.com' });
+    var doc1 = new Model1({'data.email': 'some@example.com'});
     assert.equal(doc1.data.email, 'some@example.com');
-    var doc2 = new Model1({ data: doc1.data });
+    var doc2 = new Model1({data: doc1.data});
     assert.equal(doc2.data.email, 'some@example.com');
     done();
   });
 
-  it('doesnt attempt to cast generic objects as strings (gh-3030)', function(done) {
+  it('doesnt attempt to cast generic objects as strings (gh-3030)', function (done) {
     var M = mongoose.model('gh3030', {
       myStr: {
         type: String
       }
     });
 
-    var t = new M({ myStr: { thisIs: 'anObject' } });
+    var t = new M({myStr: {thisIs: 'anObject'}});
     assert.ok(!t.myStr);
-    t.validate(function(error) {
+    t.validate(function (error) {
       assert.ok(error);
       done();
     });
   });
 
-  it('single embedded schemas (gh-2689)', function(done) {
+  it('single embedded schemas (gh-2689)', function (done) {
     var db = start();
 
     var userSchema = new mongoose.Schema({
       name: String,
       email: String
-    }, { _id: false, id: false });
+    }, {_id: false, id: false});
 
     var userHookCount = 0;
-    userSchema.pre('save', function(next) {
+    userSchema.pre('save', function (next) {
       ++userHookCount;
       next();
     });
@@ -1869,44 +1866,44 @@ describe('document', function() {
     });
 
     var eventHookCount = 0;
-    eventSchema.pre('save', function(next) {
+    eventSchema.pre('save', function (next) {
       ++eventHookCount;
       next();
     });
 
     var Event = db.model('gh2689', eventSchema);
 
-    var e = new Event({ name: 'test', user: { name: 123, email: 'val' } });
-    e.save(function(error) {
+    var e = new Event({name: 'test', user: {name: 123, email: 'val'}});
+    e.save(function (error) {
       assert.ifError(error);
       assert.strictEqual(e.user.name, '123');
       assert.equal(eventHookCount, 1);
       assert.equal(userHookCount, 1);
 
       Event.findOne(
-        { user: { name: '123', email: 'val' } },
-        function(error, doc) {
-          assert.ifError(error);
-          assert.ok(doc);
-
-          Event.findOne(
-            { user: { $in: [{ name: '123', email: 'val' }] } },
-            function(error, doc) {
-              assert.ifError(error);
-              assert.ok(doc);
-              db.close(done);
-            });
-        });
+          {user: {name: '123', email: 'val'}},
+          function (error, doc) {
+            assert.ifError(error);
+            assert.ok(doc);
+
+            Event.findOne(
+                {user: {$in: [{name: '123', email: 'val'}]}},
+                function (error, doc) {
+                  assert.ifError(error);
+                  assert.ok(doc);
+                  db.close(done);
+                });
+          });
     });
   });
 
-  it('single embedded schemas with validation (gh-2689)', function(done) {
+  it('single embedded schemas with validation (gh-2689)', function (done) {
     var db = start();
 
     var userSchema = new mongoose.Schema({
       name: String,
-      email: { type: String, required: true, match: /.+@.+/ }
-    }, { _id: false, id: false });
+      email: {type: String, required: true, match: /.+@.+/}
+    }, {_id: false, id: false});
 
     var eventSchema = new mongoose.Schema({
       user: userSchema,
@@ -1915,7 +1912,7 @@ describe('document', function() {
 
     var Event = db.model('gh2689_1', eventSchema);
 
-    var e = new Event({ name: 'test', user: {} });
+    var e = new Event({name: 'test', user: {}});
     var error = e.validateSync();
     assert.ok(error);
     assert.ok(error.errors['user.email']);
@@ -1931,13 +1928,13 @@ describe('document', function() {
     db.close(done);
   });
 
-  it('single embedded schemas with markmodified (gh-2689)', function(done) {
+  it('single embedded schemas with markmodified (gh-2689)', function (done) {
     var db = start();
 
     var userSchema = new mongoose.Schema({
       name: String,
-      email: { type: String, required: true, match: /.+@.+/ }
-    }, { _id: false, id: false });
+      email: {type: String, required: true, match: /.+@.+/}
+    }, {_id: false, id: false});
 
     var eventSchema = new mongoose.Schema({
       user: userSchema,
@@ -1946,8 +1943,8 @@ describe('document', function() {
 
     var Event = db.model('gh2689_2', eventSchema);
 
-    var e = new Event({ name: 'test', user: { email: 'a@b' } });
-    e.save(function(error, doc) {
+    var e = new Event({name: 'test', user: {email: 'a@b'}});
+    e.save(function (error, doc) {
       assert.ifError(error);
       assert.ok(doc);
       assert.ok(!doc.isModified('user'));
@@ -1960,27 +1957,27 @@ describe('document', function() {
 
       var delta = doc.$__delta()[1];
       assert.deepEqual(delta, {
-        $set: { 'user.name': 'Val' }
+        $set: {'user.name': 'Val'}
       });
 
-      doc.save(function(error) {
+      doc.save(function (error) {
         assert.ifError(error);
-        Event.findOne({ _id: doc._id }, function(error, doc) {
+        Event.findOne({_id: doc._id}, function (error, doc) {
           assert.ifError(error);
-          assert.deepEqual(doc.user.toObject(), { email: 'a@b', name: 'Val' });
+          assert.deepEqual(doc.user.toObject(), {email: 'a@b', name: 'Val'});
           db.close(done);
         });
       });
     });
   });
 
-  it('single embedded schemas + update validators (gh-2689)', function(done) {
+  it('single embedded schemas + update validators (gh-2689)', function (done) {
     var db = start();
 
     var userSchema = new mongoose.Schema({
-      name: { type: String, default: 'Val' },
-      email: { type: String, required: true, match: /.+@.+/ }
-    }, { _id: false, id: false });
+      name: {type: String, default: 'Val'},
+      email: {type: String, required: true, match: /.+@.+/}
+    }, {_id: false, id: false});
 
     var eventSchema = new mongoose.Schema({
       user: userSchema,
@@ -1989,17 +1986,17 @@ describe('document', function() {
 
     var Event = db.model('gh2689_3', eventSchema);
 
-    var badUpdate = { $set: { 'user.email': 'a' } };
-    var options = { runValidators: true };
-    Event.update({}, badUpdate, options, function(error) {
+    var badUpdate = {$set: {'user.email': 'a'}};
+    var options = {runValidators: true};
+    Event.update({}, badUpdate, options, function (error) {
       assert.ok(error);
       assert.equal(error.errors['user.email'].kind, 'regexp');
 
-      var nestedUpdate = { name: 'test' };
-      var options = { upsert: true, setDefaultsOnInsert: true };
-      Event.update({}, nestedUpdate, options, function(error) {
+      var nestedUpdate = {name: 'test'};
+      var options = {upsert: true, setDefaultsOnInsert: true};
+      Event.update({}, nestedUpdate, options, function (error) {
         assert.ifError(error);
-        Event.findOne({ name: 'test' }, function(error, ev) {
+        Event.findOne({name: 'test'}, function (error, ev) {
           assert.ifError(error);
           assert.equal(ev.user.name, 'Val');
           db.close(done);
@@ -2008,10 +2005,9 @@ describe('document', function() {
     });
   });
 
-  it('single embedded schemas with populate (gh-3501)', function(done) {
+  it('single embedded schemas with populate (gh-3501)', function (done) {
     var db = start();
-    var PopulateMeSchema = new Schema({
-    });
+    var PopulateMeSchema = new Schema({});
 
     var Child = db.model('gh3501', PopulateMeSchema);
 
@@ -2028,102 +2024,102 @@ describe('document', function() {
 
     var P = db.model('gh3501_1', parentSchema);
 
-    Child.create([{}, {}], function(error, docs) {
+    Child.create([{}, {}], function (error, docs) {
       assert.ifError(error);
       var obj = {
-        singleNested: { populateMeArray: [docs[0]._id, docs[1]._id] }
+        singleNested: {populateMeArray: [docs[0]._id, docs[1]._id]}
       };
-      P.create(obj, function(error, doc) {
+      P.create(obj, function (error, doc) {
         assert.ifError(error);
         P.
-          findById(doc._id).
-          populate('singleNested.populateMeArray').
-          exec(function(error, doc) {
-            assert.ok(doc.singleNested.populateMeArray[0]._id);
-            db.close(done);
-          });
+        findById(doc._id).
+        populate('singleNested.populateMeArray').
+        exec(function (error, doc) {
+          assert.ok(doc.singleNested.populateMeArray[0]._id);
+          db.close(done);
+        });
       });
     });
   });
 
-  it('single embedded schemas with methods (gh-3534)', function(done) {
+  it('single embedded schemas with methods (gh-3534)', function (done) {
     var db = start();
-    var personSchema = new Schema({ name: String });
-    personSchema.methods.firstName = function() {
+    var personSchema = new Schema({name: String});
+    personSchema.methods.firstName = function () {
       return this.name.substr(0, this.name.indexOf(' '));
     };
 
-    var bandSchema = new Schema({ leadSinger: personSchema });
+    var bandSchema = new Schema({leadSinger: personSchema});
     var Band = db.model('gh3534', bandSchema);
 
-    var gnr = new Band({ leadSinger: { name: 'Axl Rose' } });
+    var gnr = new Band({leadSinger: {name: 'Axl Rose'}});
     assert.equal(gnr.leadSinger.firstName(), 'Axl');
     db.close(done);
   });
 
-  it('single embedded schemas with models (gh-3535)', function(done) {
+  it('single embedded schemas with models (gh-3535)', function (done) {
     var db = start();
-    var personSchema = new Schema({ name: String });
+    var personSchema = new Schema({name: String});
     var Person = db.model('gh3535_0', personSchema);
 
-    var bandSchema = new Schema({ leadSinger: personSchema });
+    var bandSchema = new Schema({leadSinger: personSchema});
     var Band = db.model('gh3535', bandSchema);
 
-    var axl = new Person({ name: 'Axl Rose' });
-    var gnr = new Band({ leadSinger: axl });
+    var axl = new Person({name: 'Axl Rose'});
+    var gnr = new Band({leadSinger: axl});
 
-    gnr.save(function(error) {
+    gnr.save(function (error) {
       assert.ifError(error);
       assert.equal(gnr.leadSinger.name, 'Axl Rose');
       db.close(done);
     });
   });
 
-  it('single embedded schemas with indexes (gh-3594)', function(done) {
-    var personSchema = new Schema({ name: { type: String, unique: true } });
+  it('single embedded schemas with indexes (gh-3594)', function (done) {
+    var personSchema = new Schema({name: {type: String, unique: true}});
 
-    var bandSchema = new Schema({ leadSinger: personSchema });
+    var bandSchema = new Schema({leadSinger: personSchema});
 
     assert.equal(bandSchema.indexes().length, 1);
     var index = bandSchema.indexes()[0];
-    assert.deepEqual(index[0], { 'leadSinger.name': 1 });
+    assert.deepEqual(index[0], {'leadSinger.name': 1});
     assert.ok(index[1].unique);
     done();
   });
 
-  it('single embedded docs have an ownerDocument function (gh-3589)', function(done) {
+  it('single embedded docs have an ownerDocument function (gh-3589)', function (done) {
     var db = start();
-    var personSchema = new Schema({ name: String });
-    personSchema.methods.display = function() {
+    var personSchema = new Schema({name: String});
+    personSchema.methods.display = function () {
       return this.name + ' of ' + this.ownerDocument().name;
     };
 
-    var bandSchema = new Schema({ leadSinger: personSchema, name: String });
+    var bandSchema = new Schema({leadSinger: personSchema, name: String});
     var Band = db.model('gh3589', bandSchema);
 
     var gnr = new Band({
       name: "Guns N' Roses",
-      leadSinger: { name: 'Axl Rose' }
+      leadSinger: {name: 'Axl Rose'}
     });
     assert.equal(gnr.leadSinger.display(), "Axl Rose of Guns N' Roses");
     db.close(done);
   });
 
-  it('removing single embedded docs (gh-3596)', function(done) {
+  it('removing single embedded docs (gh-3596)', function (done) {
     var db = start();
-    var personSchema = new Schema({ name: String });
+    var personSchema = new Schema({name: String});
 
-    var bandSchema = new Schema({ guitarist: personSchema, name: String });
+    var bandSchema = new Schema({guitarist: personSchema, name: String});
     var Band = db.model('gh3596', bandSchema);
 
     var gnr = new Band({
       name: "Guns N' Roses",
-      guitarist: { name: 'Slash' }
+      guitarist: {name: 'Slash'}
     });
-    gnr.save(function(error, gnr) {
+    gnr.save(function (error, gnr) {
       assert.ifError(error);
       gnr.guitarist = undefined;
-      gnr.save(function(error, gnr) {
+      gnr.save(function (error, gnr) {
         assert.ifError(error);
         assert.ok(!gnr.guitarist);
         db.close(done);
@@ -2131,44 +2127,44 @@ describe('document', function() {
     });
   });
 
-  it('setting single embedded docs (gh-3601)', function(done) {
+  it('setting single embedded docs (gh-3601)', function (done) {
     var db = start();
-    var personSchema = new Schema({ name: String });
+    var personSchema = new Schema({name: String});
 
-    var bandSchema = new Schema({ guitarist: personSchema, name: String });
+    var bandSchema = new Schema({guitarist: personSchema, name: String});
     var Band = db.model('gh3601', bandSchema);
 
     var gnr = new Band({
       name: "Guns N' Roses",
-      guitarist: { name: 'Slash' }
+      guitarist: {name: 'Slash'}
     });
     var velvetRevolver = new Band({
       name: 'Velvet Revolver'
     });
     velvetRevolver.guitarist = gnr.guitarist;
-    velvetRevolver.save(function(error) {
+    velvetRevolver.save(function (error) {
       assert.ifError(error);
       assert.equal(velvetRevolver.guitarist, gnr.guitarist);
       db.close(done);
     });
   });
 
-  it('single embedded docs init obeys strict mode (gh-3642)', function(done) {
+  it('single embedded docs init obeys strict mode (gh-3642)', function (done) {
     var db = start();
-    var personSchema = new Schema({ name: String });
+    var personSchema = new Schema({name: String});
 
-    var bandSchema = new Schema({ guitarist: personSchema, name: String });
+    var bandSchema = new Schema({guitarist: personSchema, name: String});
     var Band = db.model('gh3642', bandSchema);
 
     var velvetRevolver = new Band({
       name: 'Velvet Revolver',
-      guitarist: { name: 'Slash', realName: 'Saul Hudson' }
+      guitarist: {name: 'Slash', realName: 'Saul Hudson'}
     });
 
-    velvetRevolver.save(function(error) {
+    velvetRevolver.save(function (error) {
       assert.ifError(error);
-      var query = { name: 'Velvet Revolver' };
-      Band.collection.findOne(query, function(error, band) {
+      var query = {name: 'Velvet Revolver'};
+      Band.collection.findOne(query, function (error, band) {
         assert.ifError(error);
         assert.ok(!band.guitarist.realName);
         db.close(done);
@@ -2176,31 +2172,31 @@ describe('document', function() {
     });
   });
 
-  describe('bug fixes', function() {
+  describe('bug fixes', function () {
     var db;
 
-    before(function() {
+    before(function () {
       db = start();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('single embedded docs post hooks (gh-3679)', function(done) {
+    it('single embedded docs post hooks (gh-3679)', function (done) {
       var postHookCalls = [];
-      var personSchema = new Schema({ name: String });
-      personSchema.post('save', function() {
+      var personSchema = new Schema({name: String});
+      personSchema.post('save', function () {
         postHookCalls.push(this);
       });
 
-      var bandSchema = new Schema({ guitarist: personSchema, name: String });
+      var bandSchema = new Schema({guitarist: personSchema, name: String});
       var Band = db.model('gh3679', bandSchema);
-      var obj = { name: "Guns N' Roses", guitarist: { name: 'Slash' } };
+      var obj = {name: "Guns N' Roses", guitarist: {name: 'Slash'}};
 
-      Band.create(obj, function(error) {
+      Band.create(obj, function (error) {
         assert.ifError(error);
-        setTimeout(function() {
+        setTimeout(function () {
           assert.equal(postHookCalls.length, 1);
           assert.equal(postHookCalls[0].name, 'Slash');
           done();
@@ -2208,8 +2204,8 @@ describe('document', function() {
       });
     });
 
-    it('single embedded docs .set() (gh-3686)', function(done) {
-      var personSchema = new Schema({ name: String, realName: String });
+    it('single embedded docs .set() (gh-3686)', function (done) {
+      var personSchema = new Schema({name: String, realName: String});
 
       var bandSchema = new Schema({
         guitarist: personSchema,
@@ -2218,12 +2214,12 @@ describe('document', function() {
       var Band = db.model('gh3686', bandSchema);
       var obj = {
         name: "Guns N' Roses",
-        guitarist: { name: 'Slash', realName: 'Saul Hudson' }
+        guitarist: {name: 'Slash', realName: 'Saul Hudson'}
       };
 
-      Band.create(obj, function(error, gnr) {
+      Band.create(obj, function (error, gnr) {
         gnr.set('guitarist.name', 'Buckethead');
-        gnr.save(function(error) {
+        gnr.save(function (error) {
           assert.ifError(error);
           assert.equal(gnr.guitarist.name, 'Buckethead');
           assert.equal(gnr.guitarist.realName, 'Saul Hudson');
@@ -2232,11 +2228,11 @@ describe('document', function() {
       });
     });
 
-    it('single embedded docs with arrays pre hooks (gh-3680)', function(done) {
-      var childSchema = Schema({ count: Number });
+    it('single embedded docs with arrays pre hooks (gh-3680)', function (done) {
+      var childSchema = Schema({count: Number});
 
       var preCalls = 0;
-      childSchema.pre('save', function(next) {
+      childSchema.pre('save', function (next) {
         ++preCalls;
         next();
       });
@@ -2250,31 +2246,31 @@ describe('document', function() {
       });
 
       var Parent = db.model('gh3680', ParentSchema);
-      var obj = { singleNested: { children: [{ count: 0 }] } };
-      Parent.create(obj, function(error) {
+      var obj = {singleNested: {children: [{count: 0}]}};
+      Parent.create(obj, function (error) {
         assert.ifError(error);
         assert.equal(preCalls, 1);
         done();
       });
     });
 
-    it('nested single embedded doc validation (gh-3702)', function(done) {
-      var childChildSchema = Schema({ count: { type: Number, min: 1 } });
-      var childSchema = new Schema({ child: childChildSchema });
-      var parentSchema = new Schema({ child: childSchema });
+    it('nested single embedded doc validation (gh-3702)', function (done) {
+      var childChildSchema = Schema({count: {type: Number, min: 1}});
+      var childSchema = new Schema({child: childChildSchema});
+      var parentSchema = new Schema({child: childSchema});
 
       var Parent = db.model('gh3702', parentSchema);
-      var obj = { child: { child: { count: 0 } } };
-      Parent.create(obj, function(error) {
+      var obj = {child: {child: {count: 0}}};
+      Parent.create(obj, function (error) {
         assert.ok(error);
         assert.ok(/ValidationError/.test(error.toString()));
         done();
       });
     });
 
-    it('handles virtuals with dots correctly (gh-3618)', function(done) {
-      var testSchema = new Schema({ nested: { type: Object, default: {} } });
-      testSchema.virtual('nested.test').get(function() {
+    it('handles virtuals with dots correctly (gh-3618)', function (done) {
+      var testSchema = new Schema({nested: {type: Object, default: {}}});
+      testSchema.virtual('nested.test').get(function () {
         return true;
       });
 
@@ -2282,19 +2278,19 @@ describe('document', function() {
 
       var test = new Test();
 
-      var doc = test.toObject({ getters: true, virtuals: true });
+      var doc = test.toObject({getters: true, virtuals: true});
       delete doc._id;
       delete doc.id;
-      assert.deepEqual(doc, { nested: { test: true } });
+      assert.deepEqual(doc, {nested: {test: true}});
 
-      doc = test.toObject({ getters: false, virtuals: true });
+      doc = test.toObject({getters: false, virtuals: true});
       delete doc._id;
       delete doc.id;
-      assert.deepEqual(doc, { nested: { test: true } });
+      assert.deepEqual(doc, {nested: {test: true}});
       done();
     });
 
-    it('handles pushing with numeric keys (gh-3623)', function(done) {
+    it('handles pushing with numeric keys (gh-3623)', function (done) {
       var schema = new Schema({
         array: [{
           1: {
@@ -2311,14 +2307,14 @@ describe('document', function() {
 
       var MyModel = db.model('gh3623', schema);
 
-      var doc = { array: [{ 2: {} }] };
-      MyModel.collection.insertOne(doc, function(error) {
+      var doc = {array: [{2: {}}]};
+      MyModel.collection.insertOne(doc, function (error) {
         assert.ifError(error);
 
-        MyModel.findOne({ _id: doc._id }, function(error, doc) {
+        MyModel.findOne({_id: doc._id}, function (error, doc) {
           assert.ifError(error);
-          doc.array.push({ 2: {} });
-          doc.save(function(error) {
+          doc.array.push({2: {}});
+          doc.save(function (error) {
             assert.ifError(error);
             done();
           });
@@ -2326,27 +2322,27 @@ describe('document', function() {
       });
     });
 
-    it('execPopulate (gh-3753)', function(done) {
+    it('execPopulate (gh-3753)', function (done) {
       var childSchema = new Schema({
         name: String
       });
 
       var parentSchema = new Schema({
         name: String,
-        children: [{ type: ObjectId, ref: 'gh3753' }]
+        children: [{type: ObjectId, ref: 'gh3753'}]
       });
 
       var Child = db.model('gh3753', childSchema);
       var Parent = db.model('gh3753_0', parentSchema);
 
-      Child.create({ name: 'Luke Skywalker' }, function(error, child) {
+      Child.create({name: 'Luke Skywalker'}, function (error, child) {
         assert.ifError(error);
-        var doc = { name: 'Darth Vader', children: [child._id] };
-        Parent.create(doc, function(error, doc) {
-          Parent.findOne({ _id: doc._id }, function(error, doc) {
+        var doc = {name: 'Darth Vader', children: [child._id]};
+        Parent.create(doc, function (error, doc) {
+          Parent.findOne({_id: doc._id}, function (error, doc) {
             assert.ifError(error);
             assert.ok(doc);
-            doc.populate('children').execPopulate().then(function(doc) {
+            doc.populate('children').execPopulate().then(function (doc) {
               assert.equal(doc.children.length, 1);
               assert.equal(doc.children[0].name, 'Luke Skywalker');
               done();
@@ -2356,26 +2352,26 @@ describe('document', function() {
       });
     });
 
-    it('handles 0 for numeric subdoc ids (gh-3776)', function(done) {
+    it('handles 0 for numeric subdoc ids (gh-3776)', function (done) {
       var personSchema = Schema({
         _id: Number,
         name: String,
         age: Number,
-        friends: [{ type: Number, ref: 'gh3776' }]
+        friends: [{type: Number, ref: 'gh3776'}]
       });
 
       var Person = db.model('gh3776', personSchema);
 
       var people = [
-        { _id: 0, name: 'Alice' },
-        { _id: 1, name: 'Bob' }
+        {_id: 0, name: 'Alice'},
+        {_id: 1, name: 'Bob'}
       ];
 
-      Person.create(people, function(error, people) {
+      Person.create(people, function (error, people) {
         assert.ifError(error);
         var alice = people[0];
         alice.friends.push(people[1]);
-        alice.save(function(error) {
+        alice.save(function (error) {
           assert.ifError(error);
           done();
         });
diff --git a/test/document.unit.test.js b/test/document.unit.test.js
index 2e87f421ef2..fb1c4abfb13 100644
--- a/test/document.unit.test.js
+++ b/test/document.unit.test.js
@@ -6,21 +6,21 @@ var start = require('./common');
 var assert = require('assert');
 var mongoose = start.mongoose;
 
-describe('sharding', function() {
-  it('should handle shard keys properly (gh-2127)', function(done) {
+describe('sharding', function () {
+  it('should handle shard keys properly (gh-2127)', function (done) {
     var mockSchema = {
       options: {
-        shardKey: { date: 1 }
+        shardKey: {date: 1}
       }
     };
-    var Stub = function() {
+    var Stub = function () {
       this.schema = mockSchema;
       this.$__ = {};
     };
     Stub.prototype.__proto__ = mongoose.Document.prototype;
     var d = new Stub();
     var currentTime = new Date();
-    d._doc = { date: currentTime };
+    d._doc = {date: currentTime};
 
     d.$__storeShard();
     assert.equal(currentTime, d.$__.shardval.date);
@@ -28,38 +28,38 @@ describe('sharding', function() {
   });
 });
 
-describe('toObject()', function() {
+describe('toObject()', function () {
   var Stub;
 
-  beforeEach(function() {
-    Stub = function() {
+  beforeEach(function () {
+    Stub = function () {
       var schema = this.schema = {
-        options: { toObject: { minimize: false, virtuals: true } },
-        virtuals: { virtual: 'test' }
+        options: {toObject: {minimize: false, virtuals: true}},
+        virtuals: {virtual: 'test'}
       };
-      this._doc = { empty: {} };
-      this.get = function(path) { return schema.virtuals[path]; };
+      this._doc = {empty: {}};
+      this.get = function (path) { return schema.virtuals[path]; };
       this.$__ = {};
     };
     Stub.prototype = Object.create(mongoose.Document.prototype);
   });
 
-  it('should inherit options from schema', function(done) {
+  it('should inherit options from schema', function (done) {
     var d = new Stub();
-    assert.deepEqual(d.toObject(), { empty: {}, virtual: 'test' });
+    assert.deepEqual(d.toObject(), {empty: {}, virtual: 'test'});
     done();
   });
 
-  it('can overwrite by passing an option', function(done) {
+  it('can overwrite by passing an option', function (done) {
     var d = new Stub();
-    assert.deepEqual(d.toObject({ minimize: true }), {});
+    assert.deepEqual(d.toObject({minimize: true}), {});
     done();
   });
 
-  it('doesnt crash with empty object (gh-3130)', function(done) {
+  it('doesnt crash with empty object (gh-3130)', function (done) {
     var d = new Stub();
     d._doc = undefined;
-    assert.doesNotThrow(function() {
+    assert.doesNotThrow(function () {
       d.toObject();
     });
     done();
diff --git a/test/errors.validation.test.js b/test/errors.validation.test.js
index b69e4f606d0..eec2e6646ca 100644
--- a/test/errors.validation.test.js
+++ b/test/errors.validation.test.js
@@ -10,9 +10,9 @@ var assert = require('assert'),
     SchemaType = mongoose.SchemaType,
     ValidatorError = SchemaType.ValidatorError;
 
-describe('ValidationError', function() {
-  describe('#infiniteRecursion', function() {
-    it('does not cause RangeError (gh-1834)', function(done) {
+describe('ValidationError', function () {
+  describe('#infiniteRecursion', function () {
+    it('does not cause RangeError (gh-1834)', function (done) {
       var SubSchema,
           M,
           model;
@@ -30,12 +30,12 @@ describe('ValidationError', function() {
       model = new M({
         name: 'Model',
         contents: [
-          { key: 'foo' }
+          {key: 'foo'}
         ]
       });
 
-      model.validate(function(err) {
-        assert.doesNotThrow(function() {
+      model.validate(function (err) {
+        assert.doesNotThrow(function () {
           JSON.stringify(err);
         });
         done();
@@ -43,14 +43,14 @@ describe('ValidationError', function() {
     });
   });
 
-  describe('#minDate', function() {
-    it('causes a validation error', function(done) {
+  describe('#minDate', function () {
+    it('causes a validation error', function (done) {
       var MinSchema,
           M,
           model;
 
       MinSchema = new Schema({
-        appointmentDate: { type: Date, min: Date.now }
+        appointmentDate: {type: Date, min: Date.now}
       });
 
       M = mongoose.model('MinSchema', MinSchema);
@@ -59,13 +59,13 @@ describe('ValidationError', function() {
         appointmentDate: new Date(Date.now().valueOf() - 10000)
       });
 
-      //should fail validation
-      model.validate(function(err) {
+      // should fail validation
+      model.validate(function (err) {
         assert.notEqual(err, null, 'min Date validation failed.');
         model.appointmentDate = new Date(Date.now().valueOf() + 10000);
 
-        //should pass validation
-        model.validate(function(err) {
+        // should pass validation
+        model.validate(function (err) {
           assert.equal(err, null);
           done();
         });
@@ -73,14 +73,14 @@ describe('ValidationError', function() {
     });
   });
 
-  describe('#maxDate', function() {
-    it('causes a validation error', function(done) {
+  describe('#maxDate', function () {
+    it('causes a validation error', function (done) {
       var MaxSchema,
           M,
           model;
 
       MaxSchema = new Schema({
-        birthdate: { type: Date, max: Date.now }
+        birthdate: {type: Date, max: Date.now}
       });
 
       M = mongoose.model('MaxSchema', MaxSchema);
@@ -89,13 +89,13 @@ describe('ValidationError', function() {
         birthdate: new Date(Date.now().valueOf() + 2000)
       });
 
-      //should fail validation
-      model.validate(function(err) {
+      // should fail validation
+      model.validate(function (err) {
         assert.notEqual(err, null, 'max Date validation failed');
         model.birthdate = Date.now();
 
-        //should pass validation
-        model.validate(function(err) {
+        // should pass validation
+        model.validate(function (err) {
           assert.equal(err, null, 'max Date validation failed');
           done();
         });
@@ -103,14 +103,14 @@ describe('ValidationError', function() {
     });
   });
 
-  describe('#minlength', function() {
-    it('causes a validation error', function(done) {
+  describe('#minlength', function () {
+    it('causes a validation error', function (done) {
       var AddressSchema,
           Address,
           model;
 
       AddressSchema = new Schema({
-        postalCode: { type: String, minlength: 5 }
+        postalCode: {type: String, minlength: 5}
       });
 
       Address = mongoose.model('MinLengthAddress', AddressSchema);
@@ -119,13 +119,13 @@ describe('ValidationError', function() {
         postalCode: '9512'
       });
 
-      //should fail validation
-      model.validate(function(err) {
+      // should fail validation
+      model.validate(function (err) {
         assert.notEqual(err, null, 'String minlegth validation failed.');
         model.postalCode = '95125';
 
-        //should pass validation
-        model.validate(function(err) {
+        // should pass validation
+        model.validate(function (err) {
           assert.equal(err, null);
           done();
         });
@@ -133,14 +133,14 @@ describe('ValidationError', function() {
     });
   });
 
-  describe('#maxlength', function() {
-    it('causes a validation error', function(done) {
+  describe('#maxlength', function () {
+    it('causes a validation error', function (done) {
       var AddressSchema,
           Address,
           model;
 
       AddressSchema = new Schema({
-        postalCode: { type: String, maxlength: 10 }
+        postalCode: {type: String, maxlength: 10}
       });
 
       Address = mongoose.model('MaxLengthAddress', AddressSchema);
@@ -149,13 +149,13 @@ describe('ValidationError', function() {
         postalCode: '95125012345'
       });
 
-      //should fail validation
-      model.validate(function(err) {
+      // should fail validation
+      model.validate(function (err) {
         assert.notEqual(err, null, 'String maxlegth validation failed.');
         model.postalCode = '95125';
 
-        //should pass validation
-        model.validate(function(err) {
+        // should pass validation
+        model.validate(function (err) {
           assert.equal(err, null);
           done();
         });
@@ -163,8 +163,8 @@ describe('ValidationError', function() {
     });
   });
 
-  describe('#toString', function() {
-    it('does not cause RangeError (gh-1296)', function(done) {
+  describe('#toString', function () {
+    it('does not cause RangeError (gh-1296)', function (done) {
       var ASchema = new Schema({
         key: {type: String, required: true},
         value: {type: String, required: true}
@@ -176,9 +176,9 @@ describe('ValidationError', function() {
 
       var M = mongoose.model('A', BSchema);
       var m = new M;
-      m.contents.push({ key: 'asdf' });
-      m.validate(function(err) {
-        assert.doesNotThrow(function() {
+      m.contents.push({key: 'asdf'});
+      m.validate(function (err) {
+        assert.doesNotThrow(function () {
           String(err);
         });
         done();
@@ -186,9 +186,9 @@ describe('ValidationError', function() {
     });
   });
 
-  describe('formatMessage', function() {
-    it('replaces properties in a message', function(done) {
-      var props = { base: 'eggs', topping: 'bacon' };
+  describe('formatMessage', function () {
+    it('replaces properties in a message', function (done) {
+      var props = {base: 'eggs', topping: 'bacon'};
       var message = 'I had {BASE} and {TOPPING} for breakfast';
 
       var result = ValidatorError.prototype.formatMessage(message, props);
diff --git a/test/gh-1408.test.js b/test/gh-1408.test.js
index 5405b512720..993cb5eddf3 100644
--- a/test/gh-1408.test.js
+++ b/test/gh-1408.test.js
@@ -8,15 +8,15 @@ var start = require('./common'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema;
 
-describe('documents should not be converted to _id (gh-1408)', function() {
-  it('if an embedded doc', function(done) {
+describe('documents should not be converted to _id (gh-1408)', function () {
+  it('if an embedded doc', function (done) {
     var db = start();
 
     var PreferenceSchema = new Schema({
       _id: {type: Schema.ObjectId, auto: true},
-      preference: { type: String, required: true },
-      value: { type: Schema.Types.Mixed }
-    }, { versionKey: false });
+      preference: {type: String, required: true},
+      value: {type: Schema.Types.Mixed}
+    }, {versionKey: false});
 
     var BrandSchema = new Schema({
       settings: {
@@ -29,43 +29,43 @@ describe('documents should not be converted to _id (gh-1408)', function() {
     var a = new A({
       settings: {
         preferences:
-         [ { preference: 'group_colors', value: false },
-           { preference: 'can_force_orders', value: true },
-           { preference: 'hide_from_buyers', value: true },
-           { preference: 'no_orders', value: '' }
+         [{preference: 'group_colors', value: false},
+           {preference: 'can_force_orders', value: true},
+           {preference: 'hide_from_buyers', value: true},
+           {preference: 'no_orders', value: ''}
          ]
       }
     });
 
-    a.save(function(err, a) {
+    a.save(function (err, a) {
       if (err) return done(err);
 
-      A.findById(a, function(err, doc) {
+      A.findById(a, function (err, doc) {
         if (err) return done(err);
 
         var newData = {
           settings: {
             preferences:
-             [ { preference: 'group_colors', value: true },
-               { preference: 'can_force_orders', value: true },
-               { preference: 'custom_csv', value: '' },
-               { preference: 'hide_from_buyers', value: false },
-               { preference: 'nozoom', value: false },
-               { preference: 'no_orders', value: false }
+             [{preference: 'group_colors', value: true},
+               {preference: 'can_force_orders', value: true},
+               {preference: 'custom_csv', value: ''},
+               {preference: 'hide_from_buyers', value: false},
+               {preference: 'nozoom', value: false},
+               {preference: 'no_orders', value: false}
             ]
           }
         };
 
-        doc.set('settings', newData.settings, { merge: true });
+        doc.set('settings', newData.settings, {merge: true});
         doc.markModified('settings'); // <== this caused the bug
 
-        doc.save(function(err) {
+        doc.save(function (err) {
           if (err) return done(err);
 
-          A.findById(doc, function(err, doc) {
+          A.findById(doc, function (err, doc) {
             if (err) return done(err);
 
-            doc.settings.preferences.forEach(function(pref, i) {
+            doc.settings.preferences.forEach(function (pref, i) {
               assert.equal(pref.preference, newData.settings.preferences[i].preference);
               assert.equal(pref.value, newData.settings.preferences[i].value);
             });
diff --git a/test/harmony/document.test_.js b/test/harmony/document.test_.js
index 51df9096e4d..e54a4ffa168 100644
--- a/test/harmony/document.test_.js
+++ b/test/harmony/document.test_.js
@@ -14,23 +14,23 @@ var assert = require('assert');
  *  Note that the `yield` keyword is currently only supported in NodeJS 0.11.x
  *  with the `--harmony` flag.
  */
-describe('Documents in ES6', function() {
+describe('Documents in ES6', function () {
   var db;
   var collectionNameCounter = 0;
 
-  var getCollectionName = function() {
+  var getCollectionName = function () {
     return 'harmony-documents-validate-' + (++collectionNameCounter);
   };
 
-  beforeEach(function() {
-    db = start({ noErrorListener: 1 });
+  beforeEach(function () {
+    db = start({noErrorListener: 1});
   });
 
-  afterEach(function(done) {
+  afterEach(function (done) {
     db.close(done);
   });
 
-  it('validate() integrates with co and the yield keyword', function(done) {
+  it('validate() integrates with co and the yield keyword', function (done) {
     co(function*() {
       var schema = null;
       var called = false;
@@ -38,7 +38,7 @@ describe('Documents in ES6', function() {
       var error;
 
       var validate = {
-        validator: function() {
+        validator: function () {
           called = true;
           return shouldSucceed;
         },
@@ -46,12 +46,12 @@ describe('Documents in ES6', function() {
       };
 
       schema = new Schema({
-        eggs: { type: String, required: true, validate: validate },
-        bacon: { type: Boolean, required: true }
+        eggs: {type: String, required: true, validate: validate},
+        bacon: {type: Boolean, required: true}
       });
 
       var M = db.model('validateSchema', schema, getCollectionName());
-      var m = new M({ eggs: 'Sunny side up', bacon: false });
+      var m = new M({eggs: 'Sunny side up', bacon: false});
 
       try {
         yield m.validate();
@@ -78,16 +78,16 @@ describe('Documents in ES6', function() {
     })();
   });
 
-  it('save() integrates with co and the yield keyword', function(done) {
+  it('save() integrates with co and the yield keyword', function (done) {
     co(function*() {
       var error;
       var schema = new Schema({
-        description: { type: String, required: true }
+        description: {type: String, required: true}
       });
 
       var Breakfast = db.model('breakfast', schema, getCollectionName());
 
-      var goodBreakfast = new Breakfast({ description: 'eggs & bacon' });
+      var goodBreakfast = new Breakfast({description: 'eggs & bacon'});
 
       try {
         yield goodBreakfast.save();
@@ -120,7 +120,7 @@ describe('Documents in ES6', function() {
     })();
   });
 
-  it('populate() *requires* execPopulate() to work with the yield keyword', function(done) {
+  it('populate() *requires* execPopulate() to work with the yield keyword', function (done) {
     /**
      *  Because the `populate()` function supports chaining, it's difficult
      *  to determine when the chain is 'done'. Therefore, you need to call
@@ -131,7 +131,7 @@ describe('Documents in ES6', function() {
       var breakfastCollectionName = getCollectionName();
       var foodCollectionName = getCollectionName();
       var breakfastSchema = new Schema({
-        foods: [{ type: mongoose.Schema.ObjectId, ref: foodCollectionName }]
+        foods: [{type: mongoose.Schema.ObjectId, ref: foodCollectionName}]
       });
 
       var foodSchema = new Schema({
@@ -141,9 +141,9 @@ describe('Documents in ES6', function() {
       var Food = db.model(foodCollectionName, foodSchema, foodCollectionName);
       var Breakfast = db.model(breakfastCollectionName, breakfastSchema, breakfastCollectionName);
 
-      var bacon = new Food({ name: 'bacon' });
-      var eggs = new Food({ name: 'eggs' });
-      var goodBreakfast = new Breakfast({ foods: [bacon, eggs] });
+      var bacon = new Food({name: 'bacon'});
+      var eggs = new Food({name: 'eggs'});
+      var goodBreakfast = new Breakfast({foods: [bacon, eggs]});
 
       try {
         yield [bacon.save(), eggs.save(), goodBreakfast.save()];
@@ -174,7 +174,7 @@ describe('Documents in ES6', function() {
     })();
   });
 
-  it('update() works with co and yield', function(done) {
+  it('update() works with co and yield', function (done) {
     co(function*() {
       var schema = new Schema({
         steak: String,
@@ -187,7 +187,7 @@ describe('Documents in ES6', function() {
       var error;
 
       try {
-        yield breakfast.update({ steak: 'Ribeye', eggs: 'Scrambled' }, { upsert: true }).exec();
+        yield breakfast.update({steak: 'Ribeye', eggs: 'Scrambled'}, {upsert: true}).exec();
       } catch (e) {
         error = e;
       }
diff --git a/test/harmony/model.test_.js b/test/harmony/model.test_.js
index a289f0ca571..aac5f689001 100644
--- a/test/harmony/model.test_.js
+++ b/test/harmony/model.test_.js
@@ -18,27 +18,27 @@ var assert = require('assert');
  *  `yield` as described above.
  *
  */
-describe('Models in ES6', function() {
+describe('Models in ES6', function () {
   var db;
   var collectionNameCounter = 0;
 
-  var getCollectionName = function() {
+  var getCollectionName = function () {
     return 'harmony-models-validate-' + (++collectionNameCounter);
   };
 
-  beforeEach(function() {
+  beforeEach(function () {
     db = start();
   });
 
-  afterEach(function(done) {
+  afterEach(function (done) {
     db.close(done);
   });
 
-  it('`create()` integrates with co and the yield keyword', function(done) {
+  it('`create()` integrates with co and the yield keyword', function (done) {
     co(function * () {
       var schema = new Schema({
-        eggs: { type: String, required: true },
-        bacon: { type: Boolean, required: true }
+        eggs: {type: String, required: true},
+        bacon: {type: Boolean, required: true}
       });
 
       var M = db.model('harmonyCreate', schema, getCollectionName());
@@ -46,8 +46,8 @@ describe('Models in ES6', function() {
       var results;
       try {
         results = yield M.create([
-          { eggs: 'sunny-side up', bacon: false },
-          { eggs: 'scrambled', bacon: true }]);
+          {eggs: 'sunny-side up', bacon: false},
+          {eggs: 'scrambled', bacon: true}]);
       } catch (e) {
         return done(e);
       }
@@ -60,19 +60,19 @@ describe('Models in ES6', function() {
     })();
   });
 
-  it('`aggregate()` integrates with co and the yield keyword', function(done) {
+  it('`aggregate()` integrates with co and the yield keyword', function (done) {
     co(function*() {
       var schema = new Schema({
-        eggs: { type: String, required: true },
-        bacon: { type: Boolean, required: true }
+        eggs: {type: String, required: true},
+        bacon: {type: Boolean, required: true}
       });
 
       var M = db.model('harmonyAggregate', schema, getCollectionName());
 
       try {
         yield M.create([
-          { eggs: 'sunny-side up', bacon: false },
-          { eggs: 'scrambled', bacon: true }]);
+          {eggs: 'sunny-side up', bacon: false},
+          {eggs: 'scrambled', bacon: true}]);
       } catch (e) {
         return done(e);
       }
@@ -80,8 +80,8 @@ describe('Models in ES6', function() {
       var results;
       try {
         results = yield M.aggregate([
-          { $group: { _id: '$bacon', eggs: { $first: '$eggs' } } },
-          { $sort: { _id: 1 } }
+          {$group: {_id: '$bacon', eggs: {$first: '$eggs'}}},
+          {$sort: {_id: 1}}
         ]).exec();
       } catch (e) {
         return done(e);
@@ -97,20 +97,20 @@ describe('Models in ES6', function() {
     })();
   });
 
-  it('`mapReduce()` can also be used with co and yield', function(done) {
+  it('`mapReduce()` can also be used with co and yield', function (done) {
     co(function*() {
       var schema = new Schema({
-        eggs: { type: String, required: true },
-        bacon: { type: Boolean, required: true }
+        eggs: {type: String, required: true},
+        bacon: {type: Boolean, required: true}
       });
 
       var M = db.model('harmonyMapreduce', schema, getCollectionName());
 
       try {
         yield M.create([
-          { eggs: 'sunny-side up', bacon: false },
-          { eggs: 'sunny-side up', bacon: true },
-          { eggs: 'scrambled', bacon: true }]);
+          {eggs: 'sunny-side up', bacon: false},
+          {eggs: 'sunny-side up', bacon: true},
+          {eggs: 'scrambled', bacon: true}]);
       } catch (e) {
         return done(e);
       }
@@ -118,8 +118,8 @@ describe('Models in ES6', function() {
       var results;
       try {
         results = yield M.mapReduce({
-          map: function() { emit(this.eggs, 1); },
-          reduce: function(k, vals) { return vals.length; }
+          map: function () { emit(this.eggs, 1); },
+          reduce: function (k, vals) { return vals.length; }
         });
       } catch (e) {
         return done(e);
diff --git a/test/harmony/query.test_.js b/test/harmony/query.test_.js
index d5f9899fe3b..b662a538c8c 100644
--- a/test/harmony/query.test_.js
+++ b/test/harmony/query.test_.js
@@ -13,43 +13,43 @@ var assert = require('assert');
  *  Note that the `yield` keyword is currently only supported in NodeJS 0.11.x
  *  with the `--harmony` flag.
  */
-describe('Queries in ES6', function() {
+describe('Queries in ES6', function () {
   var db;
   var collectionNameCounter = 0;
 
-  var getCollectionName = function() {
+  var getCollectionName = function () {
     return 'harmony-queries' + (++collectionNameCounter);
   };
 
-  beforeEach(function() {
+  beforeEach(function () {
     db = start();
   });
 
-  afterEach(function(done) {
+  afterEach(function (done) {
     db.close(done);
   });
 
-  it('`exec()` integrates with co and the yield keyword', function(done) {
+  it('`exec()` integrates with co and the yield keyword', function (done) {
     co(function*() {
       var schema = new Schema({
-        eggs: { type: Number, required: true },
-        bacon: { type: Number, required: true }
+        eggs: {type: Number, required: true},
+        bacon: {type: Number, required: true}
       });
 
       var Breakfast = db.model('BreakfastHarmony', schema, getCollectionName());
 
       try {
         yield Breakfast.create(
-          { eggs: 4, bacon: 2 },
-          { eggs: 3, bacon: 3 },
-          { eggs: 2, bacon: 4 });
+          {eggs: 4, bacon: 2},
+          {eggs: 3, bacon: 3},
+          {eggs: 2, bacon: 4});
       } catch (e) {
         return done(e);
       }
 
       var result;
       try {
-        result = yield Breakfast.findOne({ eggs: 4 }).exec();
+        result = yield Breakfast.findOne({eggs: 4}).exec();
       } catch (e) {
         return done(e);
       }
@@ -58,7 +58,7 @@ describe('Queries in ES6', function() {
 
       var results;
       try {
-        results = yield Breakfast.find({ eggs: { $gt: 2 } }).sort({ bacon: 1 }).exec();
+        results = yield Breakfast.find({eggs: {$gt: 2}}).sort({bacon: 1}).exec();
       } catch (e) {
         return done(e);
       }
@@ -69,7 +69,7 @@ describe('Queries in ES6', function() {
 
       var count;
       try {
-        count = yield Breakfast.count({ eggs: { $gt: 2 } }).exec();
+        count = yield Breakfast.count({eggs: {$gt: 2}}).exec();
       } catch (e) {
         return done(e);
       }
@@ -80,10 +80,10 @@ describe('Queries in ES6', function() {
     })();
   });
 
-  it('can call `populate()` with `exec()`', function(done) {
+  it('can call `populate()` with `exec()`', function (done) {
     co(function*() {
       var bookSchema = new Schema({
-        author: { type: mongoose.Schema.ObjectId, ref: 'AuthorHarmony' },
+        author: {type: mongoose.Schema.ObjectId, ref: 'AuthorHarmony'},
         title: String
       });
 
@@ -95,15 +95,15 @@ describe('Queries in ES6', function() {
       var Author = db.model('AuthorHarmony', authorSchema, getCollectionName());
 
       try {
-        var hugo = yield Author.create({ name: 'Victor Hugo' });
-        yield Book.create({ author: hugo._id, title: 'Les Miserables' });
+        var hugo = yield Author.create({name: 'Victor Hugo'});
+        yield Book.create({author: hugo._id, title: 'Les Miserables'});
       } catch (e) {
         return done(e);
       }
 
       var result;
       try {
-        result = yield Book.findOne({ title: 'Les Miserables' }).populate('author').exec();
+        result = yield Book.findOne({title: 'Les Miserables'}).populate('author').exec();
       } catch (e) {
         return done(e);
       }
diff --git a/test/index.test.js b/test/index.test.js
index e30b01db451..d6bcd971dc6 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -8,38 +8,38 @@ var url = require('url'),
     random = require('../lib/utils').random,
     collection = 'blogposts_' + random();
 
-describe('mongoose module:', function() {
-  describe('default connection works', function() {
-    it('without options', function(done) {
+describe('mongoose module:', function () {
+  describe('default connection works', function () {
+    it('without options', function (done) {
       var goose = new Mongoose;
       var db = goose.connection,
           uri = 'mongodb://localhost/mongoose_test';
 
       goose.connect(process.env.MONGOOSE_TEST_URI || uri);
 
-      db.on('open', function() {
-        db.close(function() {
+      db.on('open', function () {
+        db.close(function () {
           done();
         });
       });
     });
 
-    it('with options', function(done) {
+    it('with options', function (done) {
       var goose = new Mongoose;
       var db = goose.connection,
           uri = 'mongodb://localhost/mongoose_test';
 
       goose.connect(process.env.MONGOOSE_TEST_URI || uri, {db: {safe: false}});
 
-      db.on('open', function() {
-        db.close(function() {
+      db.on('open', function () {
+        db.close(function () {
           done();
         });
       });
     });
   });
 
-  it('{g,s}etting options', function(done) {
+  it('{g,s}etting options', function (done) {
     var mongoose = new Mongoose();
 
     mongoose.set('a', 'b');
@@ -51,17 +51,17 @@ describe('mongoose module:', function() {
     done();
   });
 
-  it('declaring global plugins', function(done) {
+  it('declaring global plugins', function (done) {
     var mong = new Mongoose(),
         schema = new Schema(),
         called = 0;
 
-    mong.plugin(function(s) {
+    mong.plugin(function (s) {
       assert.equal(s, schema);
       called++;
     });
 
-    schema.plugin(function(s) {
+    schema.plugin(function (s) {
       assert.equal(s, schema);
       called++;
     });
@@ -72,9 +72,9 @@ describe('mongoose module:', function() {
     done();
   });
 
-  describe('disconnection of all connections', function() {
-    describe('no callback', function() {
-      it('works', function(done) {
+  describe('disconnection of all connections', function () {
+    describe('no callback', function () {
+      it('works', function (done) {
         var mong = new Mongoose(),
             uri = 'mongodb://localhost/mongoose_test',
             connections = 0,
@@ -91,24 +91,24 @@ describe('mongoose module:', function() {
           done();
         }
 
-        db.on('open', function() {
+        db.on('open', function () {
           connections++;
           cb();
         });
 
-        db.on('close', function() {
+        db.on('close', function () {
           disconnections++;
           cb();
         });
 
         var db2 = mong.createConnection(process.env.MONGOOSE_TEST_URI || uri);
 
-        db2.on('open', function() {
+        db2.on('open', function () {
           connections++;
           cb();
         });
 
-        db2.on('close', function() {
+        db2.on('close', function () {
           disconnections++;
           cb();
         });
@@ -116,7 +116,7 @@ describe('mongoose module:', function() {
         mong.disconnect();
       });
 
-      it('properly handles errors', function(done) {
+      it('properly handles errors', function (done) {
         var mong = new Mongoose(),
             uri = 'mongodb://localhost/mongoose_test';
 
@@ -124,12 +124,12 @@ describe('mongoose module:', function() {
         var db = mong.connection;
 
         // forced failure
-        db.close = function(cb) {
+        db.close = function (cb) {
           cb(new Error('bam'));
         };
 
         mong.disconnect()
-          .on('error', function(error) {
+          .on('error', function (error) {
             assert.equal('bam', error.message);
           });
 
@@ -137,22 +137,22 @@ describe('mongoose module:', function() {
       });
     });
 
-    it('with callback', function(done) {
+    it('with callback', function (done) {
       var mong = new Mongoose(),
           uri = 'mongodb://localhost/mongoose_test';
 
       mong.connect(process.env.MONGOOSE_TEST_URI || uri);
 
-      mong.connection.on('open', function() {
-        mong.disconnect(function() {
+      mong.connection.on('open', function () {
+        mong.disconnect(function () {
           done();
         });
       });
     });
   });
 
-  describe('model()', function() {
-    it('accessing a model that hasn\'t been defined', function(done) {
+  describe('model()', function () {
+    it('accessing a model that hasn\'t been defined', function (done) {
       var mong = new Mongoose(),
           thrown = false;
 
@@ -167,56 +167,56 @@ describe('mongoose module:', function() {
       done();
     });
 
-    it('returns the model at creation', function(done) {
-      var Named = mongoose.model('Named', new Schema({ name: String }));
+    it('returns the model at creation', function (done) {
+      var Named = mongoose.model('Named', new Schema({name: String}));
       var n1 = new Named();
       assert.equal(n1.name, null);
-      var n2 = new Named({ name: 'Peter Bjorn' });
+      var n2 = new Named({name: 'Peter Bjorn'});
       assert.equal(n2.name, 'Peter Bjorn');
 
-      var schema = new Schema({ number: Number });
+      var schema = new Schema({number: Number});
       var Numbered = mongoose.model('Numbered', schema, collection);
-      var n3 = new Numbered({ number: 1234 });
+      var n3 = new Numbered({number: 1234});
       assert.equal(1234, n3.number.valueOf());
       done();
     });
 
-    it('prevents overwriting pre-existing models', function(done) {
+    it('prevents overwriting pre-existing models', function (done) {
       var m = new Mongoose;
       m.model('A', new Schema);
 
-      assert.throws(function() {
+      assert.throws(function () {
         m.model('A', new Schema);
       }, /Cannot overwrite `A` model/);
 
       done();
     });
 
-    it('allows passing identical name + schema args', function(done) {
+    it('allows passing identical name + schema args', function (done) {
       var m = new Mongoose;
       var schema = new Schema;
       m.model('A', schema);
 
-      assert.doesNotThrow(function() {
+      assert.doesNotThrow(function () {
         m.model('A', schema);
       });
 
       done();
     });
 
-    it('throws on unknown model name', function(done) {
-      assert.throws(function() {
+    it('throws on unknown model name', function (done) {
+      assert.throws(function () {
         mongoose.model('iDoNotExist!');
       }, /Schema hasn't been registered/);
 
       done();
     });
 
-    describe('passing collection name', function() {
-      describe('when model name already exists', function() {
-        it('returns a new uncached model', function(done) {
+    describe('passing collection name', function () {
+      describe('when model name already exists', function () {
+        it('returns a new uncached model', function (done) {
           var m = new Mongoose;
-          var s1 = new Schema({ a: [] });
+          var s1 = new Schema({a: []});
           var name = 'non-cached-collection-name';
           var A = m.model(name, s1);
           var B = m.model(name);
@@ -230,49 +230,49 @@ describe('mongoose module:', function() {
       });
     });
 
-    describe('passing object literal schemas', function() {
-      it('works', function(done) {
+    describe('passing object literal schemas', function () {
+      it('works', function (done) {
         var m = new Mongoose;
-        var A = m.model('A', { n: [{ age: 'number' }]});
-        var a = new A({ n: [{ age: '47' }] });
+        var A = m.model('A', {n: [{age: 'number'}]});
+        var a = new A({n: [{age: '47'}]});
         assert.strictEqual(47, a.n[0].age);
         done();
       });
     });
   });
 
-  it('connecting with a signature of host, database, function', function(done) {
+  it('connecting with a signature of host, database, function', function (done) {
     var mong = new Mongoose(),
         uri = process.env.MONGOOSE_TEST_URI || 'mongodb://localhost/mongoose_test';
 
     uri = url.parse(uri);
 
-    mong.connect(uri.hostname, uri.pathname.substr(1), function(err) {
+    mong.connect(uri.hostname, uri.pathname.substr(1), function (err) {
       assert.ifError(err);
       mong.connection.close();
       done();
     });
   });
 
-  describe('connecting with a signature of uri, options, function', function() {
-    it('with single mongod', function(done) {
+  describe('connecting with a signature of uri, options, function', function () {
+    it('with single mongod', function (done) {
       var mong = new Mongoose(),
           uri = process.env.MONGOOSE_TEST_URI || 'mongodb://localhost/mongoose_test';
 
-      mong.connect(uri, { db: { safe: false }}, function(err) {
+      mong.connect(uri, {db: {safe: false}}, function (err) {
         assert.ifError(err);
         mong.connection.close();
         done();
       });
     });
 
-    it('with replica set', function(done) {
+    it('with replica set', function (done) {
       var mong = new Mongoose(),
           uri = process.env.MONGOOSE_SET_TEST_URI;
 
       if (!uri) return done();
 
-      mong.connect(uri, { db: { safe: false }}, function(err) {
+      mong.connect(uri, {db: {safe: false}}, function (err) {
         assert.ifError(err);
         mong.connection.close();
         done();
@@ -280,7 +280,7 @@ describe('mongoose module:', function() {
     });
   });
 
-  it('goose.connect() to a replica set', function(done) {
+  it('goose.connect() to a replica set', function (done) {
     var uri = process.env.MONGOOSE_SET_TEST_URI;
 
     if (!uri) {
@@ -293,7 +293,7 @@ describe('mongoose module:', function() {
 
     var mong = new Mongoose();
 
-    mong.connect(uri, function(err) {
+    mong.connect(uri, function (err) {
       assert.ifError(err);
 
       mong.model('Test', new mongoose.Schema({
@@ -304,10 +304,10 @@ describe('mongoose module:', function() {
           test = new Test();
 
       test.test = 'aa';
-      test.save(function(err) {
+      test.save(function (err) {
         assert.ifError(err);
 
-        Test.findById(test._id, function(err, doc) {
+        Test.findById(test._id, function (err, doc) {
           assert.ifError(err);
           assert.equal('aa', doc.test);
           mong.connection.close();
@@ -325,14 +325,14 @@ describe('mongoose module:', function() {
     }
   });
 
-  it('goose.createConnection() to a replica set', function(done) {
+  it('goose.createConnection() to a replica set', function (done) {
     var uri = process.env.MONGOOSE_SET_TEST_URI;
 
     if (!uri) return done();
 
     var mong = new Mongoose();
 
-    var conn = mong.createConnection(uri, function(err) {
+    var conn = mong.createConnection(uri, function (err) {
       assert.ifError(err);
 
       mong.model('ReplSetTwo', new mongoose.Schema({
@@ -343,10 +343,10 @@ describe('mongoose module:', function() {
           test = new Test();
 
       test.test = 'aa';
-      test.save(function(err) {
+      test.save(function (err) {
         assert.ifError(err);
 
-        Test.findById(test._id, function(err, doc) {
+        Test.findById(test._id, function (err, doc) {
           assert.ifError(err);
           assert.equal('aa', doc.test);
           conn.close();
@@ -364,7 +364,7 @@ describe('mongoose module:', function() {
     }
   });
 
-  describe('exports', function() {
+  describe('exports', function () {
     function test(mongoose) {
       assert.equal('string', typeof mongoose.version);
       assert.equal('function', typeof mongoose.Mongoose);
@@ -383,14 +383,14 @@ describe('mongoose module:', function() {
       assert.equal('function', typeof mongoose.Error.VersionError);
     }
 
-    it('of module', function(done) {
+    it('of module', function (done) {
       test(mongoose);
       done();
     });
-    it('of new Mongoose instances', function(done) {
+
+    it('of new Mongoose instances', function (done) {
       test(new mongoose.Mongoose);
       done();
     });
   });
-
 });
diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js
index 42f6f085a9c..ec907413dfe 100644
--- a/test/model.aggregate.test.js
+++ b/test/model.aggregate.test.js
@@ -22,14 +22,14 @@ var userSchema = new Schema({
 var collection = 'aggregate_' + random();
 mongoose.model('Aggregate', userSchema);
 
-describe('model aggregate', function() {
-  var group = { $group: { _id: null, maxAge: { $max: '$age' } }};
-  var project = { $project: { maxAge: 1, _id: 0 }};
+describe('model aggregate', function () {
+  var group = {$group: {_id: null, maxAge: {$max: '$age'}}};
+  var project = {$project: {maxAge: 1, _id: 0}};
   var db, A, maxAge;
 
   var mongo26_or_greater = false;
 
-  before(function(done) {
+  before(function (done) {
     db = start();
     A = db.model('Aggregate', collection);
 
@@ -41,12 +41,12 @@ describe('model aggregate', function() {
     for (var i = 0; i < num; ++i) {
       var age = Math.random() * 100 | 0;
       maxAge = Math.max(maxAge, age);
-      docs.push({ author: authors[i % authors.length], age: age });
+      docs.push({author: authors[i % authors.length], age: age});
     }
 
-    A.create(docs, function(err) {
+    A.create(docs, function (err) {
       assert.ifError(err);
-      start.mongodVersion(function(err, version) {
+      start.mongodVersion(function (err, version) {
         if (err) throw err;
         mongo26_or_greater = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
         if (!mongo26_or_greater) console.log('not testing mongodb 2.6 features');
@@ -55,15 +55,15 @@ describe('model aggregate', function() {
     });
   });
 
-  after(function(done) {
+  after(function (done) {
     db.close(done);
   });
 
-  describe('works', function() {
-    it('with argument lists', function(done) {
+  describe('works', function () {
+    it('with argument lists', function (done) {
       this.timeout(4000);
 
-      A.aggregate(group, project, function(err, res) {
+      A.aggregate(group, project, function (err, res) {
         assert.ifError(err);
         assert.ok(res);
         assert.equal(1, res.length);
@@ -73,10 +73,10 @@ describe('model aggregate', function() {
       });
     });
 
-    it('with arrays', function(done) {
+    it('with arrays', function (done) {
       this.timeout(4000);
 
-      A.aggregate([group, project], function(err, res) {
+      A.aggregate([group, project], function (err, res) {
         assert.ifError(err);
         assert.ok(res);
         assert.equal(1, res.length);
@@ -86,13 +86,13 @@ describe('model aggregate', function() {
       });
     });
 
-    it('with Aggregate syntax', function(done) {
+    it('with Aggregate syntax', function (done) {
       this.timeout(4000);
 
       var promise = A.aggregate()
         .group(group.$group)
         .project(project.$project)
-        .exec(function(err, res) {
+        .exec(function (err, res) {
           assert.ifError(err);
           assert.ok(promise instanceof mongoose.Promise);
           assert.ok(res);
@@ -103,7 +103,7 @@ describe('model aggregate', function() {
         });
     });
 
-    it('with Aggregate syntax if callback not provided', function(done) {
+    it('with Aggregate syntax if callback not provided', function (done) {
       this.timeout(4000);
 
       var promise = A.aggregate()
@@ -111,7 +111,7 @@ describe('model aggregate', function() {
         .project(project.$project)
         .exec();
 
-      promise.then(function(res) {
+      promise.then(function (res) {
         assert.ok(promise instanceof mongoose.Promise);
         assert.ok(res);
         assert.equal(1, res.length);
@@ -121,12 +121,12 @@ describe('model aggregate', function() {
       }).end();
     });
 
-    it('when returning Aggregate', function(done) {
+    it('when returning Aggregate', function (done) {
       assert(A.aggregate(project) instanceof Aggregate);
       done();
     });
 
-    it('can use helper for $out', function(done) {
+    it('can use helper for $out', function (done) {
       if (!mongo26_or_greater) {
         return done();
       }
@@ -138,9 +138,9 @@ describe('model aggregate', function() {
         .group(group.$group)
         .project(project.$project)
         .out(outputCollection)
-        .exec(function(error) {
+        .exec(function (error) {
           assert.ifError(error);
-          A.db.collection(outputCollection).find().toArray(function(error, documents) {
+          A.db.collection(outputCollection).find().toArray(function (error, documents) {
             assert.ifError(error);
             assert.equal(1, documents.length);
             assert.ok('maxAge' in documents[0]);
diff --git a/test/model.create.test.js b/test/model.create.test.js
index 5a08cb3d6c1..36e4148590c 100644
--- a/test/model.create.test.js
+++ b/test/model.create.test.js
@@ -18,22 +18,22 @@ var schema = Schema({
 });
 
 
-describe('model', function() {
-  describe('create()', function() {
+describe('model', function () {
+  describe('create()', function () {
     var db;
     var B;
 
-    before(function() {
+    before(function () {
       db = start();
       B = db.model('model-create', schema, 'model-create-' + random());
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('accepts an array and returns an array', function(done) {
-      B.create([{ title: 'hi'}, { title: 'bye'}], function(err, posts) {
+    it('accepts an array and returns an array', function (done) {
+      B.create([{title: 'hi'}, {title: 'bye'}], function (err, posts) {
         assert.ifError(err);
 
         assert.ok(posts instanceof Array);
@@ -41,39 +41,39 @@ describe('model', function() {
         var post1 = posts[0];
         var post2 = posts[1];
         assert.ok(post1.get('_id') instanceof DocumentObjectId);
-        assert.equal(post1.title,'hi');
+        assert.equal(post1.title, 'hi');
 
         assert.ok(post2.get('_id') instanceof DocumentObjectId);
-        assert.equal(post2.title,'bye');
+        assert.equal(post2.title, 'bye');
 
         done();
       });
     });
 
-    it('fires callback when passed 0 docs', function(done) {
-      B.create(function(err, a) {
+    it('fires callback when passed 0 docs', function (done) {
+      B.create(function (err, a) {
         assert.ifError(err);
         assert.ok(!a);
         done();
       });
     });
 
-    it('fires callback when empty array passed', function(done) {
-      B.create([], function(err, a) {
+    it('fires callback when empty array passed', function (done) {
+      B.create([], function (err, a) {
         assert.ifError(err);
         assert.ok(!a);
         done();
       });
     });
 
-    it('returns a promise', function(done) {
-      var p = B.create({ title: 'returns promise' }, function() {
+    it('returns a promise', function (done) {
+      var p = B.create({title: 'returns promise'}, function () {
         assert.ok(p instanceof mongoose.Promise);
         done();
       });
     });
 
-    it('creates in parallel', function(done) {
+    it('creates in parallel', function (done) {
       // we set the time out to be double that of the validator - 1 (so that running in serial will be greater then that)
       this.timeout(1000);
       var db = start(),
@@ -84,22 +84,22 @@ describe('model', function() {
         preference: String
       });
       SchemaWithPreSaveHook.pre('save', true, function hook(next, done) {
-        setTimeout(function() {
+        setTimeout(function () {
           countPre++;
           next();
           done();
         }, 500);
       });
-      SchemaWithPreSaveHook.post('save', function() {
+      SchemaWithPreSaveHook.post('save', function () {
         countPost++;
       });
       var MWPSH = db.model('mwpsh', SchemaWithPreSaveHook);
       MWPSH.create([
-        {preference: "xx"},
-        {preference: "yy"},
-        {preference: "1"},
-        {preference: "2"}
-      ], function(err, docs) {
+        {preference: 'xx'},
+        {preference: 'yy'},
+        {preference: '1'},
+        {preference: '2'}
+      ], function (err, docs) {
         assert.ifError(err);
 
         assert.ok(docs instanceof Array);
@@ -119,27 +119,27 @@ describe('model', function() {
     });
 
 
-    describe('callback is optional', function() {
-      it('with one doc', function(done) {
-        var p = B.create({ title: 'optional callback' });
-        p.then(function(doc) {
+    describe('callback is optional', function () {
+      it('with one doc', function (done) {
+        var p = B.create({title: 'optional callback'});
+        p.then(function (doc) {
           assert.equal('optional callback', doc.title);
           done();
         }, done).end();
       });
 
-      it('with more than one doc', function(done) {
-        var p = B.create({ title: 'optional callback 2' }, { title: 'orient expressions' });
-        p.then(function(doc1, doc2) {
+      it('with more than one doc', function (done) {
+        var p = B.create({title: 'optional callback 2'}, {title: 'orient expressions'});
+        p.then(function (doc1, doc2) {
           assert.equal('optional callback 2', doc1.title);
           assert.equal('orient expressions', doc2.title);
           done();
         }, done).end();
       });
 
-      it('with array of docs', function(done) {
-        var p = B.create([{ title: 'optional callback3' }, { title: '3' }]);
-        p.then(function(docs) {
+      it('with array of docs', function (done) {
+        var p = B.create([{title: 'optional callback3'}, {title: '3'}]);
+        p.then(function (docs) {
           assert.ok(docs instanceof Array);
           assert.equal(docs.length, 2);
           var doc1 = docs[0];
@@ -150,13 +150,13 @@ describe('model', function() {
         }, done).end();
       });
 
-      it('and should reject promise on error', function(done) {
-        var p = B.create({ title: 'optional callback 4' });
-        p.then(function(doc) {
-          var p2 = B.create({ _id: doc._id });
-          p2.then(function() {
+      it('and should reject promise on error', function (done) {
+        var p = B.create({title: 'optional callback 4'});
+        p.then(function (doc) {
+          var p2 = B.create({_id: doc._id});
+          p2.then(function () {
             assert(false);
-          }, function(err) {
+          }, function (err) {
             assert(err);
             done();
           }).end();
diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js
index e3cdceedd39..0998081fb90 100644
--- a/test/model.discriminator.querying.test.js
+++ b/test/model.discriminator.querying.test.js
@@ -19,27 +19,27 @@ function BaseSchema() {
 
   this.add({
     name: String,
-    createdAt: { type: Date, default: Date.now }
+    createdAt: {type: Date, default: Date.now}
   });
 }
 util.inherits(BaseSchema, Schema);
 
 var EventSchema = new BaseSchema();
 var ImpressionEventSchema = new BaseSchema();
-var ConversionEventSchema = new BaseSchema({ revenue: Number });
+var ConversionEventSchema = new BaseSchema({revenue: Number});
 
-describe('model', function() {
-  describe('discriminator()', function() {
+describe('model', function () {
+  describe('discriminator()', function () {
     var db, BaseEvent, ImpressionEvent, ConversionEvent;
 
-    before(function() {
+    before(function () {
       db = start();
       BaseEvent = db.model('model-discriminator-querying-event', EventSchema, 'model-discriminator-querying-' + random());
       ImpressionEvent = BaseEvent.discriminator('model-discriminator-querying-impression', ImpressionEventSchema);
       ConversionEvent = BaseEvent.discriminator('model-discriminator-querying-conversion', ConversionEventSchema);
     });
 
-    afterEach(function(done) {
+    afterEach(function (done) {
       async.series(
         [
           function removeBaseEvent(next) {
@@ -56,13 +56,13 @@ describe('model', function() {
       );
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    describe('pushing discriminated objects', function() {
+    describe('pushing discriminated objects', function () {
       var ContainerModel, BaseCustomEvent, DiscCustomEvent;
-      before(function() {
+      before(function () {
         var BaseCustomEventSchema = new BaseSchema();
         var DiscCustomEventSchema = new BaseSchema({
           personName: Number
@@ -78,9 +78,9 @@ describe('model', function() {
         ContainerModel = db.model('container-event-model', ContainerSchema);
       });
 
-      it('into non-discriminated arrays works', function(done) {
+      it('into non-discriminated arrays works', function (done) {
         var c = new ContainerModel({
-          title: "events-group-1"
+          title: 'events-group-1'
         });
         var d1 = new BaseCustomEvent();
         var d2 = new BaseCustomEvent();
@@ -89,19 +89,19 @@ describe('model', function() {
         c.events.push(d2);
         async.series(
           [
-            function(next) { d1.save(next); },
-            function(next) { d2.save(next); },
-            function(next) { d3.save(next); },
-            function(next) { c.save(next); },
-            function(next) {
-              ContainerModel.findOne({}).populate('events').exec(function(err, doc) {
+            function (next) { d1.save(next); },
+            function (next) { d2.save(next); },
+            function (next) { d3.save(next); },
+            function (next) { c.save(next); },
+            function (next) {
+              ContainerModel.findOne({}).populate('events').exec(function (err, doc) {
                 assert.ifError(err);
                 assert.ok(doc.events && doc.events.length);
                 assert.equal(doc.events.length, 2);
                 doc.events.push(d3);
                 var hasDisc = false;
                 var discKey = DiscCustomEvent.schema.discriminatorMapping.key;
-                doc.events.forEach(function(subDoc) {
+                doc.events.forEach(function (subDoc) {
                   if (discKey in subDoc) {
                     hasDisc = true;
                   }
@@ -116,19 +116,19 @@ describe('model', function() {
       });
     });
 
-    describe('find', function() {
-      it('hydrates correct models', function(done) {
-        var baseEvent = new BaseEvent({ name: 'Base event' });
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 1.337 });
+    describe('find', function () {
+      it('hydrates correct models', function (done) {
+        var baseEvent = new BaseEvent({name: 'Base event'});
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function(err) {
+        baseEvent.save(function (err) {
           assert.ifError(err);
-          impressionEvent.save(function(err) {
+          impressionEvent.save(function (err) {
             assert.ifError(err);
-            conversionEvent.save(function(err) {
+            conversionEvent.save(function (err) {
               assert.ifError(err);
-              BaseEvent.find({}).sort('name').exec(function(err, docs) {
+              BaseEvent.find({}).sort('name').exec(function (err, docs) {
                 assert.ifError(err);
                 assert.ok(docs[0] instanceof BaseEvent);
                 assert.equal(docs[0].name, 'Base event');
@@ -148,18 +148,18 @@ describe('model', function() {
         });
       });
 
-      var checkHydratesCorrectModels = function(fields, done) {
-        var baseEvent = new BaseEvent({ name: 'Base event' });
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 1.337 });
+      var checkHydratesCorrectModels = function (fields, done) {
+        var baseEvent = new BaseEvent({name: 'Base event'});
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function(err) {
+        baseEvent.save(function (err) {
           assert.ifError(err);
-          impressionEvent.save(function(err) {
+          impressionEvent.save(function (err) {
             assert.ifError(err);
-            conversionEvent.save(function(err) {
+            conversionEvent.save(function (err) {
               assert.ifError(err);
-              BaseEvent.find({}, fields).sort('name').exec(function(err, docs) {
+              BaseEvent.find({}, fields).sort('name').exec(function (err, docs) {
                 assert.ifError(err);
                 assert.ok(docs[0] instanceof BaseEvent);
                 assert.equal(docs[0].name, 'Base event');
@@ -179,42 +179,42 @@ describe('model', function() {
         });
       };
 
-      it('hydrates correct models when fields selection set as string', function(done) {
+      it('hydrates correct models when fields selection set as string', function (done) {
         checkHydratesCorrectModels('name', done);
       });
 
-      it('hydrates correct models when fields selection set as object', function(done) {
+      it('hydrates correct models when fields selection set as object', function (done) {
         checkHydratesCorrectModels({name: 1}, done);
       });
 
-      describe('discriminator model only finds documents of its type', function() {
+      describe('discriminator model only finds documents of its type', function () {
         var impressionEvent, conversionEvent1, conversionEvent2;
 
-        before(function() {
-          impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-          conversionEvent1 = new ConversionEvent({ name: 'Conversion event 1', revenue: 1 });
-          conversionEvent2 = new ConversionEvent({ name: 'Conversion event 2', revenue: 2 });
+        before(function () {
+          impressionEvent = new ImpressionEvent({name: 'Impression event'});
+          conversionEvent1 = new ConversionEvent({name: 'Conversion event 1', revenue: 1});
+          conversionEvent2 = new ConversionEvent({name: 'Conversion event 2', revenue: 2});
         });
 
-        describe('using "ModelDiscriminator#findById"', function() {
-          it('to find a document of the appropriate discriminator', function(done) {
-            impressionEvent.save(function(err) {
+        describe('using "ModelDiscriminator#findById"', function () {
+          it('to find a document of the appropriate discriminator', function (done) {
+            impressionEvent.save(function (err) {
               assert.ifError(err);
 
               // via BaseEvent model
-              BaseEvent.findById(impressionEvent._id, function(err, doc) {
+              BaseEvent.findById(impressionEvent._id, function (err, doc) {
                 assert.ifError(err);
                 assert.ok(doc);
                 assert.equal(impressionEvent.__t, doc.__t);
 
                 // via ImpressionEvent model discriminator -- should be present
-                ImpressionEvent.findById(impressionEvent._id, function(err, doc) {
+                ImpressionEvent.findById(impressionEvent._id, function (err, doc) {
                   assert.ifError(err);
                   assert.ok(doc);
                   assert.equal(impressionEvent.__t, doc.__t);
 
                   // via ConversionEvent model discriminator -- should not be present
-                  ConversionEvent.findById(impressionEvent._id, function(err, doc) {
+                  ConversionEvent.findById(impressionEvent._id, function (err, doc) {
                     assert.ifError(err);
                     assert.ok(!doc);
 
@@ -226,27 +226,27 @@ describe('model', function() {
           });
         });
 
-        describe('using "ModelDiscriminator#find"', function() {
-          it('to find documents of the appropriate discriminator', function(done) {
-            impressionEvent.save(function(err) {
+        describe('using "ModelDiscriminator#find"', function () {
+          it('to find documents of the appropriate discriminator', function (done) {
+            impressionEvent.save(function (err) {
               assert.ifError(err);
-              conversionEvent1.save(function(err) {
+              conversionEvent1.save(function (err) {
                 assert.ifError(err);
-                conversionEvent2.save(function(err) {
+                conversionEvent2.save(function (err) {
                   assert.ifError(err);
                   // doesn't find anything since we're querying for an impression id
-                  var query = ConversionEvent.find({ _id: impressionEvent._id });
+                  var query = ConversionEvent.find({_id: impressionEvent._id});
                   assert.equal(query.op, 'find');
-                  assert.deepEqual(query._conditions, { _id: impressionEvent._id, __t: 'model-discriminator-querying-conversion' });
-                  query.exec(function(err, documents) {
+                  assert.deepEqual(query._conditions, {_id: impressionEvent._id, __t: 'model-discriminator-querying-conversion'});
+                  query.exec(function (err, documents) {
                     assert.ifError(err);
                     assert.equal(documents.length, 0);
 
                     // now find one with no criteria given and ensure it gets added to _conditions
                     var query = ConversionEvent.find();
-                    assert.deepEqual(query._conditions, { __t: 'model-discriminator-querying-conversion' });
+                    assert.deepEqual(query._conditions, {__t: 'model-discriminator-querying-conversion'});
                     assert.equal(query.op, 'find');
-                    query.exec(function(err, documents) {
+                    query.exec(function (err, documents) {
                       assert.ifError(err);
                       assert.equal(documents.length, 2);
 
@@ -266,30 +266,30 @@ describe('model', function() {
         });
       });
 
-      var checkDiscriminatorModelsFindDocumentsOfItsType = function(fields, done) {
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent1 = new ConversionEvent({ name: 'Conversion event 1', revenue: 1 });
-        var conversionEvent2 = new ConversionEvent({ name: 'Conversion event 2', revenue: 2 });
+      var checkDiscriminatorModelsFindDocumentsOfItsType = function (fields, done) {
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent1 = new ConversionEvent({name: 'Conversion event 1', revenue: 1});
+        var conversionEvent2 = new ConversionEvent({name: 'Conversion event 2', revenue: 2});
 
-        impressionEvent.save(function(err) {
+        impressionEvent.save(function (err) {
           assert.ifError(err);
-          conversionEvent1.save(function(err) {
+          conversionEvent1.save(function (err) {
             assert.ifError(err);
-            conversionEvent2.save(function(err) {
+            conversionEvent2.save(function (err) {
               assert.ifError(err);
               // doesn't find anything since we're querying for an impression id
-              var query = ConversionEvent.find({ _id: impressionEvent._id }, fields);
+              var query = ConversionEvent.find({_id: impressionEvent._id}, fields);
               assert.equal(query.op, 'find');
-              assert.deepEqual(query._conditions, { _id: impressionEvent._id, __t: 'model-discriminator-querying-conversion' });
-              query.exec(function(err, documents) {
+              assert.deepEqual(query._conditions, {_id: impressionEvent._id, __t: 'model-discriminator-querying-conversion'});
+              query.exec(function (err, documents) {
                 assert.ifError(err);
                 assert.equal(documents.length, 0);
 
                 // now find one with no criteria given and ensure it gets added to _conditions
                 var query = ConversionEvent.find({}, fields);
-                assert.deepEqual(query._conditions, { __t: 'model-discriminator-querying-conversion' });
+                assert.deepEqual(query._conditions, {__t: 'model-discriminator-querying-conversion'});
                 assert.equal(query.op, 'find');
-                query.exec(function(err, documents) {
+                query.exec(function (err, documents) {
                   assert.ifError(err);
                   assert.equal(documents.length, 2);
 
@@ -306,44 +306,44 @@ describe('model', function() {
         });
       };
 
-      it('discriminator model only finds documents of its type when fields selection set as string inclusive', function(done) {
+      it('discriminator model only finds documents of its type when fields selection set as string inclusive', function (done) {
         checkDiscriminatorModelsFindDocumentsOfItsType('name', done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as string exclusive', function(done) {
+      it('discriminator model only finds documents of its type when fields selection set as string exclusive', function (done) {
         checkDiscriminatorModelsFindDocumentsOfItsType('-revenue', done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as empty string', function(done) {
+      it('discriminator model only finds documents of its type when fields selection set as empty string', function (done) {
         checkDiscriminatorModelsFindDocumentsOfItsType('', done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as object inclusive', function(done) {
+      it('discriminator model only finds documents of its type when fields selection set as object inclusive', function (done) {
         checkDiscriminatorModelsFindDocumentsOfItsType({name: 1}, done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as object exclusive', function(done) {
+      it('discriminator model only finds documents of its type when fields selection set as object exclusive', function (done) {
         checkDiscriminatorModelsFindDocumentsOfItsType({revenue: 0}, done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as empty object', function(done) {
+      it('discriminator model only finds documents of its type when fields selection set as empty object', function (done) {
         checkDiscriminatorModelsFindDocumentsOfItsType({}, done);
       });
 
-      it('hydrates streams', function(done) {
-        var baseEvent = new BaseEvent({ name: 'Base event' });
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 1.337 });
+      it('hydrates streams', function (done) {
+        var baseEvent = new BaseEvent({name: 'Base event'});
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function(err) {
+        baseEvent.save(function (err) {
           assert.ifError(err);
-          impressionEvent.save(function(err) {
+          impressionEvent.save(function (err) {
             assert.ifError(err);
-            conversionEvent.save(function(err) {
+            conversionEvent.save(function (err) {
               assert.ifError(err);
               var stream = BaseEvent.find({}).sort('name').stream();
 
-              stream.on('data', function(doc) {
+              stream.on('data', function (doc) {
                 switch (doc.name) {
                   case 'Base event':
                     assert.ok(doc instanceof BaseEvent);
@@ -361,11 +361,11 @@ describe('model', function() {
                 }
               });
 
-              stream.on('error', function(err) {
+              stream.on('error', function (err) {
                 assert.ifError(err);
               });
 
-              stream.on('close', function() {
+              stream.on('close', function () {
                 done();
               });
             });
@@ -374,33 +374,33 @@ describe('model', function() {
       });
     });
 
-    describe('findOne', function() {
-      it('hydrates correct model', function(done) {
-        var baseEvent = new BaseEvent({ name: 'Base event' });
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 1.337 });
+    describe('findOne', function () {
+      it('hydrates correct model', function (done) {
+        var baseEvent = new BaseEvent({name: 'Base event'});
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function(err) {
+        baseEvent.save(function (err) {
           assert.ifError(err);
-          impressionEvent.save(function(err) {
+          impressionEvent.save(function (err) {
             assert.ifError(err);
-            conversionEvent.save(function(err) {
+            conversionEvent.save(function (err) {
               assert.ifError(err);
               // finds & hydrates BaseEvent
-              BaseEvent.findOne({ _id: baseEvent._id }, function(err, event) {
+              BaseEvent.findOne({_id: baseEvent._id}, function (err, event) {
                 assert.ifError(err);
                 assert.ok(event instanceof BaseEvent);
                 assert.equal(event.name, 'Base event');
 
                 // finds & hydrates ImpressionEvent
-                BaseEvent.findOne({ _id: impressionEvent._id }, function(err, event) {
+                BaseEvent.findOne({_id: impressionEvent._id}, function (err, event) {
                   assert.ifError(err);
                   assert.ok(event instanceof ImpressionEvent);
                   assert.equal(event.schema, ImpressionEventSchema);
                   assert.equal(event.name, 'Impression event');
 
                   // finds & hydrates ConversionEvent
-                  BaseEvent.findOne({ _id: conversionEvent._id }, function(err, event) {
+                  BaseEvent.findOne({_id: conversionEvent._id}, function (err, event) {
                     assert.ifError(err);
                     assert.ok(event instanceof ConversionEvent);
                     assert.equal(event.schema, ConversionEventSchema);
@@ -414,32 +414,32 @@ describe('model', function() {
         });
       });
 
-      var checkHydratesCorrectModels = function(fields, done, checkUndefinedRevenue) {
-        var baseEvent = new BaseEvent({ name: 'Base event' });
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 1.337 });
+      var checkHydratesCorrectModels = function (fields, done, checkUndefinedRevenue) {
+        var baseEvent = new BaseEvent({name: 'Base event'});
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function(err) {
+        baseEvent.save(function (err) {
           assert.ifError(err);
-          impressionEvent.save(function(err) {
+          impressionEvent.save(function (err) {
             assert.ifError(err);
-            conversionEvent.save(function(err) {
+            conversionEvent.save(function (err) {
               assert.ifError(err);
               // finds & hydrates BaseEvent
-              BaseEvent.findOne({ _id: baseEvent._id }, fields, function(err, event) {
+              BaseEvent.findOne({_id: baseEvent._id}, fields, function (err, event) {
                 assert.ifError(err);
                 assert.ok(event instanceof BaseEvent);
                 assert.equal(event.name, 'Base event');
 
                 // finds & hydrates ImpressionEvent
-                BaseEvent.findOne({ _id: impressionEvent._id }, fields, function(err, event) {
+                BaseEvent.findOne({_id: impressionEvent._id}, fields, function (err, event) {
                   assert.ifError(err);
                   assert.ok(event instanceof ImpressionEvent);
                   assert.equal(event.schema, ImpressionEventSchema);
                   assert.equal(event.name, 'Impression event');
 
                   // finds & hydrates ConversionEvent
-                  BaseEvent.findOne({ _id: conversionEvent._id }, fields, function(err, event) {
+                  BaseEvent.findOne({_id: conversionEvent._id}, fields, function (err, event) {
                     assert.ifError(err);
                     assert.ok(event instanceof ConversionEvent);
                     assert.equal(event.schema, ConversionEventSchema);
@@ -456,53 +456,53 @@ describe('model', function() {
         });
       };
 
-      it('hydrates correct model when fields selection set as string inclusive', function(done) {
+      it('hydrates correct model when fields selection set as string inclusive', function (done) {
         checkHydratesCorrectModels('name', done, true);
       });
 
-      it('hydrates correct model when fields selection set as string exclusive', function(done) {
+      it('hydrates correct model when fields selection set as string exclusive', function (done) {
         checkHydratesCorrectModels('-revenue', done, true);
       });
 
-      it('hydrates correct model when fields selection set as empty string', function(done) {
+      it('hydrates correct model when fields selection set as empty string', function (done) {
         checkHydratesCorrectModels('', done);
       });
 
-      it('hydrates correct model when fields selection set as object inclusive', function(done) {
+      it('hydrates correct model when fields selection set as object inclusive', function (done) {
         checkHydratesCorrectModels({name: 1}, done, true);
       });
 
-      it('hydrates correct model when fields selection set as object exclusive', function(done) {
+      it('hydrates correct model when fields selection set as object exclusive', function (done) {
         checkHydratesCorrectModels({revenue: 0}, done, true);
       });
 
-      it('hydrates correct model when fields selection set as empty object', function(done) {
+      it('hydrates correct model when fields selection set as empty object', function (done) {
         checkHydratesCorrectModels({}, done);
       });
 
-      it('discriminator model only finds a document of its type', function(done) {
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 2 });
+      it('discriminator model only finds a document of its type', function (done) {
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 2});
 
-        impressionEvent.save(function(err) {
+        impressionEvent.save(function (err) {
           assert.ifError(err);
-          conversionEvent.save(function(err) {
+          conversionEvent.save(function (err) {
             assert.ifError(err);
             // doesn't find anything since we're querying for an impression id
-            var query = ConversionEvent.findOne({ _id: impressionEvent._id });
+            var query = ConversionEvent.findOne({_id: impressionEvent._id});
             assert.equal(query.op, 'findOne');
-            assert.deepEqual(query._conditions, { _id: impressionEvent._id, __t: 'model-discriminator-querying-conversion' });
+            assert.deepEqual(query._conditions, {_id: impressionEvent._id, __t: 'model-discriminator-querying-conversion'});
 
-            query.exec(function(err, document) {
+            query.exec(function (err, document) {
               assert.ifError(err);
               assert.equal(document, null);
 
               // now find one with no criteria given and ensure it gets added to _conditions
               var query = ConversionEvent.findOne();
               assert.equal(query.op, 'findOne');
-              assert.deepEqual(query._conditions, { __t: 'model-discriminator-querying-conversion' });
+              assert.deepEqual(query._conditions, {__t: 'model-discriminator-querying-conversion'});
 
-              query.exec(function(err, document) {
+              query.exec(function (err, document) {
                 assert.ifError(err);
                 assert.ok(document instanceof ConversionEvent);
                 assert.equal(document.__t, 'model-discriminator-querying-conversion');
@@ -513,29 +513,29 @@ describe('model', function() {
         });
       });
 
-      var checkDiscriminatorModelsFindOneDocumentOfItsType = function(fields, done) {
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 2 });
+      var checkDiscriminatorModelsFindOneDocumentOfItsType = function (fields, done) {
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 2});
 
-        impressionEvent.save(function(err) {
+        impressionEvent.save(function (err) {
           assert.ifError(err);
-          conversionEvent.save(function(err) {
+          conversionEvent.save(function (err) {
             assert.ifError(err);
             // doesn't find anything since we're querying for an impression id
-            var query = ConversionEvent.findOne({ _id: impressionEvent._id }, fields);
+            var query = ConversionEvent.findOne({_id: impressionEvent._id}, fields);
             assert.equal(query.op, 'findOne');
-            assert.deepEqual(query._conditions, { _id: impressionEvent._id, __t: 'model-discriminator-querying-conversion' });
+            assert.deepEqual(query._conditions, {_id: impressionEvent._id, __t: 'model-discriminator-querying-conversion'});
 
-            query.exec(function(err, document) {
+            query.exec(function (err, document) {
               assert.ifError(err);
               assert.equal(document, null);
 
               // now find one with no criteria given and ensure it gets added to _conditions
               var query = ConversionEvent.findOne({}, fields);
               assert.equal(query.op, 'findOne');
-              assert.deepEqual(query._conditions, { __t: 'model-discriminator-querying-conversion' });
+              assert.deepEqual(query._conditions, {__t: 'model-discriminator-querying-conversion'});
 
-              query.exec(function(err, document) {
+              query.exec(function (err, document) {
                 assert.ifError(err);
                 assert.ok(document instanceof ConversionEvent);
                 assert.equal(document.__t, 'model-discriminator-querying-conversion');
@@ -546,46 +546,46 @@ describe('model', function() {
         });
       };
 
-      it('discriminator model only finds a document of its type when fields selection set as string inclusive', function(done) {
+      it('discriminator model only finds a document of its type when fields selection set as string inclusive', function (done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType('name', done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as string exclusive', function(done) {
+      it('discriminator model only finds a document of its type when fields selection set as string exclusive', function (done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType('-revenue', done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as empty string', function(done) {
+      it('discriminator model only finds a document of its type when fields selection set as empty string', function (done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType('', done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as object inclusive', function(done) {
+      it('discriminator model only finds a document of its type when fields selection set as object inclusive', function (done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType({name: 1}, done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as object exclusive', function(done) {
+      it('discriminator model only finds a document of its type when fields selection set as object exclusive', function (done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType({revenue: 0}, done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as empty object', function(done) {
+      it('discriminator model only finds a document of its type when fields selection set as empty object', function (done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType({}, done);
       });
     });
 
-    describe('findOneAndUpdate', function() {
-      it('does not update models of other types', function(done) {
-        var baseEvent = new BaseEvent({ name: 'Base event' });
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 1.337 });
+    describe('findOneAndUpdate', function () {
+      it('does not update models of other types', function (done) {
+        var baseEvent = new BaseEvent({name: 'Base event'});
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function(err) {
+        baseEvent.save(function (err) {
           assert.ifError(err);
-          impressionEvent.save(function(err) {
+          impressionEvent.save(function (err) {
             assert.ifError(err);
-            conversionEvent.save(function(err) {
+            conversionEvent.save(function (err) {
               assert.ifError(err);
-              var query = ConversionEvent.findOneAndUpdate({ name: 'Impression event' }, { $set: { name: 'Impression event - updated'}});
-              assert.deepEqual(query._conditions, { name: 'Impression event', __t: 'model-discriminator-querying-conversion' });
-              query.exec(function(err, document) {
+              var query = ConversionEvent.findOneAndUpdate({name: 'Impression event'}, {$set: {name: 'Impression event - updated'}});
+              assert.deepEqual(query._conditions, {name: 'Impression event', __t: 'model-discriminator-querying-conversion'});
+              query.exec(function (err, document) {
                 assert.ifError(err);
                 assert.equal(document, null);
                 done();
@@ -595,20 +595,20 @@ describe('model', function() {
         });
       });
 
-      it('updates models of its own type', function(done) {
-        var baseEvent = new BaseEvent({ name: 'Base event' });
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 1.337 });
+      it('updates models of its own type', function (done) {
+        var baseEvent = new BaseEvent({name: 'Base event'});
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function(err) {
+        baseEvent.save(function (err) {
           assert.ifError(err);
-          impressionEvent.save(function(err) {
+          impressionEvent.save(function (err) {
             assert.ifError(err);
-            conversionEvent.save(function(err) {
+            conversionEvent.save(function (err) {
               assert.ifError(err);
-              var query = ConversionEvent.findOneAndUpdate({ name: 'Conversion event' }, { $set: { name: 'Conversion event - updated'}}, { 'new': true });
-              assert.deepEqual(query._conditions, { name: 'Conversion event', __t: 'model-discriminator-querying-conversion' });
-              query.exec(function(err, document) {
+              var query = ConversionEvent.findOneAndUpdate({name: 'Conversion event'}, {$set: {name: 'Conversion event - updated'}}, {'new': true});
+              assert.deepEqual(query._conditions, {name: 'Conversion event', __t: 'model-discriminator-querying-conversion'});
+              query.exec(function (err, document) {
                 assert.ifError(err);
                 var expected = conversionEvent.toJSON();
                 expected.name = 'Conversion event - updated';
@@ -620,20 +620,20 @@ describe('model', function() {
         });
       });
 
-      it('base model modifies any event type', function(done) {
-        var baseEvent = new BaseEvent({ name: 'Base event' });
-        var impressionEvent = new ImpressionEvent({ name: 'Impression event' });
-        var conversionEvent = new ConversionEvent({ name: 'Conversion event', revenue: 1.337 });
+      it('base model modifies any event type', function (done) {
+        var baseEvent = new BaseEvent({name: 'Base event'});
+        var impressionEvent = new ImpressionEvent({name: 'Impression event'});
+        var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function(err) {
+        baseEvent.save(function (err) {
           assert.ifError(err);
-          impressionEvent.save(function(err) {
+          impressionEvent.save(function (err) {
             assert.ifError(err);
-            conversionEvent.save(function(err) {
+            conversionEvent.save(function (err) {
               assert.ifError(err);
-              var query = BaseEvent.findOneAndUpdate({ name: 'Conversion event' }, { $set: { name: 'Conversion event - updated'}}, { 'new': true });
-              assert.deepEqual(query._conditions, { name: 'Conversion event' });
-              query.exec(function(err, document) {
+              var query = BaseEvent.findOneAndUpdate({name: 'Conversion event'}, {$set: {name: 'Conversion event - updated'}}, {'new': true});
+              assert.deepEqual(query._conditions, {name: 'Conversion event'});
+              query.exec(function (err, document) {
                 assert.ifError(err);
                 var expected = conversionEvent.toJSON();
                 expected.name = 'Conversion event - updated';
@@ -646,16 +646,16 @@ describe('model', function() {
       });
     });
 
-    describe('population/reference mapping', function() {
-      it('populates and hydrates correct models', function(done) {
+    describe('population/reference mapping', function () {
+      it('populates and hydrates correct models', function (done) {
         var vehicleSchema = new Schema();
-        var carSchema = new Schema({ speed: Number });
-        var busSchema = new Schema({ speed: Number });
+        var carSchema = new Schema({speed: Number});
+        var busSchema = new Schema({speed: Number});
 
         var userSchema = new Schema({
-          vehicles: [{ type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationVehicle' }],
-          favoriteVehicle: { type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationVehicle' },
-          favoriteBus: { type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationBus' }
+          vehicles: [{type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationVehicle'}],
+          favoriteVehicle: {type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationVehicle'},
+          favoriteBus: {type: Schema.Types.ObjectId, ref: 'ModelDiscriminatorPopulationBus'}
         });
 
         var Vehicle = db.model('ModelDiscriminatorPopulationVehicle', vehicleSchema),
@@ -663,26 +663,26 @@ describe('model', function() {
             Bus = Vehicle.discriminator('ModelDiscriminatorPopulationBus', busSchema),
             User = db.model('ModelDiscriminatorPopulationUser', userSchema);
 
-        Vehicle.create({}, function(err, vehicle) {
+        Vehicle.create({}, function (err, vehicle) {
           assert.ifError(err);
-          Car.create({ speed: 160 }, function(err, car) {
-            Bus.create({ speed: 80 }, function(err, bus) {
+          Car.create({speed: 160}, function (err, car) {
+            Bus.create({speed: 80}, function (err, bus) {
               assert.ifError(err);
-              User.create({ vehicles: [vehicle._id, car._id, bus._id], favoriteVehicle: car._id, favoriteBus: bus._id }, function(err) {
+              User.create({vehicles: [vehicle._id, car._id, bus._id], favoriteVehicle: car._id, favoriteBus: bus._id}, function (err) {
                 assert.ifError(err);
-                User.findOne({}).populate('vehicles favoriteVehicle favoriteBus').exec(function(err, user) {
+                User.findOne({}).populate('vehicles favoriteVehicle favoriteBus').exec(function (err, user) {
                   assert.ifError(err);
 
                   var expected = {
                     __v: 0,
                     _id: user._id,
                     vehicles: [
-                      { _id: vehicle._id, __v: 0 },
-                      { _id: car._id, speed: 160, __v: 0, __t: 'ModelDiscriminatorPopulationCar' },
-                      { _id: bus._id, speed: 80, __v: 0, __t: 'ModelDiscriminatorPopulationBus' }
+                      {_id: vehicle._id, __v: 0},
+                      {_id: car._id, speed: 160, __v: 0, __t: 'ModelDiscriminatorPopulationCar'},
+                      {_id: bus._id, speed: 80, __v: 0, __t: 'ModelDiscriminatorPopulationBus'}
                     ],
-                    favoriteVehicle: { _id: car._id, speed: 160, __v: 0, __t: 'ModelDiscriminatorPopulationCar' },
-                    favoriteBus: { _id: bus._id, speed: 80, __v: 0, __t: 'ModelDiscriminatorPopulationBus' }
+                    favoriteVehicle: {_id: car._id, speed: 160, __v: 0, __t: 'ModelDiscriminatorPopulationCar'},
+                    favoriteBus: {_id: bus._id, speed: 80, __v: 0, __t: 'ModelDiscriminatorPopulationBus'}
                   };
 
                   assert.deepEqual(user.toJSON(), expected);
@@ -706,7 +706,7 @@ describe('model', function() {
         });
       });
 
-      it('reference in child schemas (gh-2719)', function(done) {
+      it('reference in child schemas (gh-2719)', function (done) {
         var vehicleSchema = new Schema({});
         var carSchema = new Schema({
           speed: Number,
@@ -727,16 +727,16 @@ describe('model', function() {
             Bus = Vehicle.discriminator('gh2719PopulationBus', busSchema),
             Garage = db.model('gh2719PopulationGarage', garageSchema);
 
-        Garage.create({name: 'My', num_of_places: 3}, function(err, garage) {
+        Garage.create({name: 'My', num_of_places: 3}, function (err, garage) {
           assert.ifError(err);
-          Car.create({ speed: 160, garage: garage }, function(err) {
+          Car.create({speed: 160, garage: garage}, function (err) {
             assert.ifError(err);
-            Bus.create({ speed: 80, garage: garage }, function(err) {
+            Bus.create({speed: 80, garage: garage}, function (err) {
               assert.ifError(err);
-              Vehicle.find({}).populate('garage').exec(function(err, vehicles) {
+              Vehicle.find({}).populate('garage').exec(function (err, vehicles) {
                 assert.ifError(err);
 
-                vehicles.forEach(function(v) {
+                vehicles.forEach(function (v) {
                   assert.ok(v.garage instanceof Garage);
                 });
 
@@ -747,17 +747,17 @@ describe('model', function() {
         });
       });
 
-      it('reference in child schemas (gh-2719-2)', function(done) {
+      it('reference in child schemas (gh-2719-2)', function (done) {
         var EventSchema, Event, TalkSchema, Talk, Survey;
 
         function BaseSchema() {
           Schema.apply(this, arguments);
 
           this.add({
-            name: { type: String, required: true },
-            date: { type: Date, required: true },
-            period: { start: { type: String, required: true },
-              end: { type: String, required: true }
+            name: {type: String, required: true},
+            date: {type: Date, required: true},
+            period: {start: {type: String, required: true},
+              end: {type: String, required: true}
             }
           });
         }
@@ -768,11 +768,11 @@ describe('model', function() {
         Event = db.model('Event', EventSchema);
 
         TalkSchema = new BaseSchema({
-          pin: { type: String, required: true, index: { unique: true } },
-          totalAttendees: { type: Number },
-          speakers: [{ type: Schema.Types.ObjectId, ref: 'Speaker' }],
-          surveys: [{ type: Schema.Types.ObjectId, ref: 'Survey' }],
-          questions: [{ type: Schema.Types.ObjectId, ref: 'Question' }]
+          pin: {type: String, required: true, index: {unique: true}},
+          totalAttendees: {type: Number},
+          speakers: [{type: Schema.Types.ObjectId, ref: 'Speaker'}],
+          surveys: [{type: Schema.Types.ObjectId, ref: 'Survey'}],
+          questions: [{type: Schema.Types.ObjectId, ref: 'Question'}]
         });
 
         Talk = Event.discriminator('Talk', TalkSchema);
@@ -783,21 +783,21 @@ describe('model', function() {
         }));
 
         Survey.create({
-          name: "That you see?",
+          name: 'That you see?',
           date: Date.now()
-        }, function(err, survey) {
+        }, function (err, survey) {
           assert.ifError(err);
 
           Talk.create({
-            name: "Meetup rails",
-            date: new Date("2015-04-01T00:00:00Z"),
-            pin: "0004",
-            period: { start: "11:00", end: "12:00" },
-            surveys: [ survey ]
-          }, function(err) {
+            name: 'Meetup rails',
+            date: new Date('2015-04-01T00:00:00Z'),
+            pin: '0004',
+            period: {start: '11:00', end: '12:00'},
+            surveys: [survey]
+          }, function (err) {
             assert.ifError(err);
 
-            Event.find({}).populate('surveys').exec(function(err, events) {
+            Event.find({}).populate('surveys').exec(function (err, events) {
               assert.ifError(err);
 
               assert.ok(events[0].surveys[0] instanceof Survey);
@@ -809,33 +809,33 @@ describe('model', function() {
       });
     });
 
-    describe('aggregate', function() {
+    describe('aggregate', function () {
       var impressionEvent, conversionEvent, ignoredImpressionEvent;
 
-      beforeEach(function(done) {
-        impressionEvent = new ImpressionEvent({ name: 'Test Event' });
-        conversionEvent = new ConversionEvent({ name: 'Test Event', revenue: 10 });
-        ignoredImpressionEvent = new ImpressionEvent({ name: 'Ignored Event' });
+      beforeEach(function (done) {
+        impressionEvent = new ImpressionEvent({name: 'Test Event'});
+        conversionEvent = new ConversionEvent({name: 'Test Event', revenue: 10});
+        ignoredImpressionEvent = new ImpressionEvent({name: 'Ignored Event'});
 
         async.forEach(
           [impressionEvent, conversionEvent, ignoredImpressionEvent],
-          function(doc, cb) {
+          function (doc, cb) {
             doc.save(cb);
           },
           done
         );
       });
 
-      describe('using "RootModel#aggregate"', function() {
-        it('to aggregate documents of all discriminators', function(done) {
+      describe('using "RootModel#aggregate"', function () {
+        it('to aggregate documents of all discriminators', function (done) {
           var aggregate = BaseEvent.aggregate([
-            { $match: { name: 'Test Event' } }
+            {$match: {name: 'Test Event'}}
           ]);
 
-          aggregate.exec(function(err, docs) {
+          aggregate.exec(function (err, docs) {
             assert.ifError(err);
             assert.deepEqual(aggregate._pipeline, [
-              { $match: { name: 'Test Event' } }
+              {$match: {name: 'Test Event'}}
             ]);
             assert.equal(docs.length, 2);
             done();
@@ -843,13 +843,13 @@ describe('model', function() {
         });
       });
 
-      describe('using "ModelDiscriminator#aggregate"', function() {
-        it('only aggregates documents of the appropriate discriminator', function(done) {
+      describe('using "ModelDiscriminator#aggregate"', function () {
+        it('only aggregates documents of the appropriate discriminator', function (done) {
           var aggregate = ImpressionEvent.aggregate([
-            { $group: { _id: '$__t', count: { $sum: 1 } } }
+            {$group: {_id: '$__t', count: {$sum: 1}}}
           ]);
 
-          aggregate.exec(function(err, result) {
+          aggregate.exec(function (err, result) {
             assert.ifError(err);
 
             // Discriminator `$match` pipeline step was added on the
@@ -857,24 +857,24 @@ describe('model', function() {
             // aggregations with empty pipelines, but that are over
             // discriminators be executed
             assert.deepEqual(aggregate._pipeline, [
-              { $match: { __t: 'model-discriminator-querying-impression' } },
-              { $group: { _id: '$__t', count: { $sum: 1 } } }
+              {$match: {__t: 'model-discriminator-querying-impression'}},
+              {$group: {_id: '$__t', count: {$sum: 1}}}
             ]);
 
             assert.equal(result.length, 1);
             assert.deepEqual(result, [
-              { _id: 'model-discriminator-querying-impression', count: 2 }
+              {_id: 'model-discriminator-querying-impression', count: 2}
             ]);
             done();
           });
         });
 
-        it('merges the first pipeline stages if applicable', function(done) {
+        it('merges the first pipeline stages if applicable', function (done) {
           var aggregate = ImpressionEvent.aggregate([
-            { $match: { name: 'Test Event' } }
+            {$match: {name: 'Test Event'}}
           ]);
 
-          aggregate.exec(function(err, result) {
+          aggregate.exec(function (err, result) {
             assert.ifError(err);
 
             // Discriminator `$match` pipeline step was added on the
@@ -882,7 +882,7 @@ describe('model', function() {
             // aggregations with empty pipelines, but that are over
             // discriminators be executed
             assert.deepEqual(aggregate._pipeline, [
-              { $match: { __t: 'model-discriminator-querying-impression', name: 'Test Event' } }
+              {$match: {__t: 'model-discriminator-querying-impression', name: 'Test Event'}}
             ]);
 
             assert.equal(result.length, 1);
diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js
index b3acdb10980..9cc7e0c62df 100644
--- a/test/model.discriminator.test.js
+++ b/test/model.discriminator.test.js
@@ -14,72 +14,74 @@ var start = require('./common'),
  * Setup
  */
 var PersonSchema = new Schema({
-  name: { first: String, last: String },
+  name: {first: String, last: String},
   gender: String
-}, { collection: 'model-discriminator-' + random() });
-PersonSchema.index({ name: 1 });
-PersonSchema.methods.getFullName = function() {
+}, {collection: 'model-discriminator-' + random()});
+PersonSchema.index({name: 1});
+PersonSchema.methods.getFullName = function () {
   return this.name.first + ' ' + this.name.last;
 };
 PersonSchema.methods.toJSonConfig = {
   include: ['prop1', 'prop2'],
   exclude: ['prop3', 'prop4']
 };
-PersonSchema.statics.findByGender = function() {};
-PersonSchema.virtual('name.full').get(function() {
+PersonSchema.statics.findByGender = function () {
+};
+PersonSchema.virtual('name.full').get(function () {
   return this.name.first + ' ' + this.name.last;
 });
-PersonSchema.virtual('name.full').set(function(name) {
+PersonSchema.virtual('name.full').set(function (name) {
   var split = name.split(' ');
   this.name.first = split[0];
   this.name.last = split[1];
 });
-PersonSchema.path('gender').validate(function(value) {
+PersonSchema.path('gender').validate(function (value) {
   return /[A-Z]/.test(value);
 }, 'Invalid name');
-PersonSchema.post('save', function(next) {
+PersonSchema.post('save', function (next) {
   next();
 });
-PersonSchema.set('toObject', { getters: true, virtuals: true });
-PersonSchema.set('toJSON', { getters: true, virtuals: true });
+PersonSchema.set('toObject', {getters: true, virtuals: true});
+PersonSchema.set('toJSON', {getters: true, virtuals: true});
 
-var EmployeeSchema = new Schema({ department: String });
-EmployeeSchema.index({ department: 1 });
-EmployeeSchema.methods.getDepartment = function() {
+var EmployeeSchema = new Schema({department: String});
+EmployeeSchema.index({department: 1});
+EmployeeSchema.methods.getDepartment = function () {
   return this.department;
 };
-EmployeeSchema.statics.findByDepartment = function() {};
-EmployeeSchema.path('department').validate(function(value) {
+EmployeeSchema.statics.findByDepartment = function () {
+};
+EmployeeSchema.path('department').validate(function (value) {
   return /[a-zA-Z]/.test(value);
 }, 'Invalid name');
-var employeeSchemaPreSaveFn = function(next) {
+var employeeSchemaPreSaveFn = function (next) {
   next();
 };
 EmployeeSchema.pre('save', employeeSchemaPreSaveFn);
-EmployeeSchema.set('toObject', { getters: true, virtuals: false });
-EmployeeSchema.set('toJSON', { getters: false, virtuals: true });
+EmployeeSchema.set('toObject', {getters: true, virtuals: false});
+EmployeeSchema.set('toJSON', {getters: false, virtuals: true});
 
-describe('model', function() {
-  describe('discriminator()', function() {
+describe('model', function () {
+  describe('discriminator()', function () {
     var db, Person, Employee;
 
-    before(function() {
+    before(function () {
       db = start();
       Person = db.model('model-discriminator-person', PersonSchema);
       Employee = Person.discriminator('model-discriminator-employee', EmployeeSchema);
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('model defaults without discriminator', function(done) {
+    it('model defaults without discriminator', function (done) {
       var Model = db.model('model-discriminator-defaults', new Schema(), 'model-discriminator-' + random());
       assert.equal(Model.discriminators, undefined);
       done();
     });
 
-    it('is instance of root', function(done) {
+    it('is instance of root', function (done) {
       assert.equal(Employee.baseModelName, 'model-discriminator-person');
       var employee = new Employee();
       assert.ok(employee instanceof Person);
@@ -89,7 +91,7 @@ describe('model', function() {
       done();
     });
 
-    it('can define static and instance methods', function(done) {
+    it('can define static and instance methods', function (done) {
       function BossBaseSchema() {
         Schema.apply(this, arguments);
 
@@ -98,14 +100,15 @@ describe('model', function() {
           createdAt: Date
         });
       }
+
       util.inherits(BossBaseSchema, Schema);
 
       var PersonSchema = new BossBaseSchema();
-      var BossSchema = new BossBaseSchema({ department: String });
-      BossSchema.methods.myName = function() {
+      var BossSchema = new BossBaseSchema({department: String});
+      BossSchema.methods.myName = function () {
         return this.name;
       };
-      BossSchema.statics.currentPresident = function() {
+      BossSchema.statics.currentPresident = function () {
         return 'obama';
       };
       var Person = db.model('Person', PersonSchema);
@@ -119,24 +122,24 @@ describe('model', function() {
       done();
     });
 
-    it('sets schema root discriminator mapping', function(done) {
-      assert.deepEqual(PersonSchema.discriminatorMapping, { key: '__t', value: null, isRoot: true });
+    it('sets schema root discriminator mapping', function (done) {
+      assert.deepEqual(PersonSchema.discriminatorMapping, {key: '__t', value: null, isRoot: true});
       done();
     });
 
-    it('sets schema discriminator type mapping', function(done) {
-      assert.deepEqual(EmployeeSchema.discriminatorMapping, { key: '__t', value: 'model-discriminator-employee', isRoot: false });
+    it('sets schema discriminator type mapping', function (done) {
+      assert.deepEqual(EmployeeSchema.discriminatorMapping, {key: '__t', value: 'model-discriminator-employee', isRoot: false});
       done();
     });
 
-    it('adds discriminatorKey to schema with default as name', function(done) {
+    it('adds discriminatorKey to schema with default as name', function (done) {
       var type = EmployeeSchema.paths.__t;
       assert.equal(type.options.type, String);
       assert.equal(type.options.default, 'model-discriminator-employee');
       done();
     });
 
-    it('adds discriminator to Model.discriminators object', function(done) {
+    it('adds discriminator to Model.discriminators object', function (done) {
       assert.equal(Object.keys(Person.discriminators).length, 1);
       assert.equal(Person.discriminators['model-discriminator-employee'], Employee);
       var newName = 'model-discriminator-' + random();
@@ -146,61 +149,61 @@ describe('model', function() {
       done();
     });
 
-    it('throws error on invalid schema', function(done) {
+    it('throws error on invalid schema', function (done) {
       assert.throws(
-        function() {
-          Person.discriminator('Foo');
-        },
-        /You must pass a valid discriminator Schema/
+          function () {
+            Person.discriminator('Foo');
+          },
+          /You must pass a valid discriminator Schema/
       );
       done();
     });
 
-    it('throws error when attempting to nest discriminators', function(done) {
+    it('throws error when attempting to nest discriminators', function (done) {
       assert.throws(
-        function() {
-          Employee.discriminator('model-discriminator-foo', new Schema());
-        },
-        /Discriminator "model-discriminator-foo" can only be a discriminator of the root model/
+          function () {
+            Employee.discriminator('model-discriminator-foo', new Schema());
+          },
+          /Discriminator "model-discriminator-foo" can only be a discriminator of the root model/
       );
       done();
     });
 
-    it('throws error when discriminator has mapped discriminator key in schema', function(done) {
+    it('throws error when discriminator has mapped discriminator key in schema', function (done) {
       assert.throws(
-        function() {
-          Person.discriminator('model-discriminator-foo', new Schema({ __t: String }));
-        },
-        /Discriminator "model-discriminator-foo" cannot have field with name "__t"/
+          function () {
+            Person.discriminator('model-discriminator-foo', new Schema({__t: String}));
+          },
+          /Discriminator "model-discriminator-foo" cannot have field with name "__t"/
       );
       done();
     });
 
-    it('throws error when discriminator has mapped discriminator key in schema with discriminatorKey option set', function(done) {
+    it('throws error when discriminator has mapped discriminator key in schema with discriminatorKey option set', function (done) {
       assert.throws(
-        function() {
-          var Foo = db.model('model-discriminator-foo', new Schema({}, { discriminatorKey: '_type' }), 'model-discriminator-' + random());
-          Foo.discriminator('model-discriminator-bar', new Schema({ _type: String }));
-        },
-        /Discriminator "model-discriminator-bar" cannot have field with name "_type"/
+          function () {
+            var Foo = db.model('model-discriminator-foo', new Schema({}, {discriminatorKey: '_type'}), 'model-discriminator-' + random());
+            Foo.discriminator('model-discriminator-bar', new Schema({_type: String}));
+          },
+          /Discriminator "model-discriminator-bar" cannot have field with name "_type"/
       );
       done();
     });
 
-    it('throws error when discriminator with taken name is added', function(done) {
+    it('throws error when discriminator with taken name is added', function (done) {
       var Foo = db.model('model-discriminator-foo', new Schema({}), 'model-discriminator-' + random());
       Foo.discriminator('model-discriminator-taken', new Schema());
       assert.throws(
-        function() {
-          Foo.discriminator('model-discriminator-taken', new Schema());
-        },
-        /Discriminator with name "model-discriminator-taken" already exists/
+          function () {
+            Foo.discriminator('model-discriminator-taken', new Schema());
+          },
+          /Discriminator with name "model-discriminator-taken" already exists/
       );
       done();
     });
 
-    it('works with nested schemas (gh-2821)', function(done) {
-      var MinionSchema = function() {
+    it('works with nested schemas (gh-2821)', function (done) {
+      var MinionSchema = function () {
         mongoose.Schema.apply(this, arguments);
 
         this.add({
@@ -209,13 +212,13 @@ describe('model', function() {
       };
       util.inherits(MinionSchema, mongoose.Schema);
 
-      var BaseSchema = function() {
-        mongoose.Schema.apply( this, arguments );
+      var BaseSchema = function () {
+        mongoose.Schema.apply(this, arguments);
 
         this.add({
           name: String,
           created_at: Date,
-          minions: [ new MinionSchema() ]
+          minions: [new MinionSchema()]
         });
       };
       util.inherits(BaseSchema, mongoose.Schema);
@@ -225,29 +228,29 @@ describe('model', function() {
         department: String
       });
 
-      assert.doesNotThrow(function() {
+      assert.doesNotThrow(function () {
         var Person = db.model('gh2821', PersonSchema);
         Person.discriminator('Boss', BossSchema);
       });
       done();
     });
 
-    describe('options', function() {
-      it('allows toObject to be overridden', function(done) {
+    describe('options', function () {
+      it('allows toObject to be overridden', function (done) {
         assert.notDeepEqual(Employee.schema.get('toObject'), Person.schema.get('toObject'));
-        assert.deepEqual(Employee.schema.get('toObject'), { getters: true, virtuals: false });
+        assert.deepEqual(Employee.schema.get('toObject'), {getters: true, virtuals: false});
         done();
       });
 
-      it('allows toJSON to be overridden', function(done) {
+      it('allows toJSON to be overridden', function (done) {
         assert.notDeepEqual(Employee.schema.get('toJSON'), Person.schema.get('toJSON'));
-        assert.deepEqual(Employee.schema.get('toJSON'), { getters: false, virtuals: true });
+        assert.deepEqual(Employee.schema.get('toJSON'), {getters: false, virtuals: true});
         done();
       });
 
-      it('is not customizable', function(done) {
+      it('is not customizable', function (done) {
         var errorMessage,
-            CustomizedSchema = new Schema({}, { capped: true });
+            CustomizedSchema = new Schema({}, {capped: true});
         try {
           Person.discriminator('model-discriminator-custom', CustomizedSchema);
         } catch (e) {
@@ -259,22 +262,22 @@ describe('model', function() {
       });
     });
 
-    describe('root schema inheritance', function() {
-      it('inherits field mappings', function(done) {
+    describe('root schema inheritance', function () {
+      it('inherits field mappings', function (done) {
         assert.strictEqual(Employee.schema.path('name'), Person.schema.path('name'));
         assert.strictEqual(Employee.schema.path('gender'), Person.schema.path('gender'));
         assert.equal(Person.schema.paths.department, undefined);
         done();
       });
 
-      it('inherits validators', function(done) {
+      it('inherits validators', function (done) {
         assert.strictEqual(Employee.schema.path('gender').validators, PersonSchema.path('gender').validators);
         assert.strictEqual(Employee.schema.path('department').validators, EmployeeSchema.path('department').validators);
         done();
       });
 
-      it('does not inherit and override fields that exist', function(done) {
-        var FemaleSchema = new Schema({ gender: { type: String, default: 'F' }}),
+      it('does not inherit and override fields that exist', function (done) {
+        var FemaleSchema = new Schema({gender: {type: String, default: 'F'}}),
             Female = Person.discriminator('model-discriminator-female', FemaleSchema);
 
         var gender = Female.schema.paths.gender;
@@ -285,7 +288,7 @@ describe('model', function() {
         done();
       });
 
-      it('inherits methods', function(done) {
+      it('inherits methods', function (done) {
         var employee = new Employee();
         assert.strictEqual(employee.getFullName, PersonSchema.methods.getFullName);
         assert.strictEqual(employee.getDepartment, EmployeeSchema.methods.getDepartment);
@@ -293,21 +296,21 @@ describe('model', function() {
         done();
       });
 
-      it('inherits statics', function(done) {
+      it('inherits statics', function (done) {
         assert.strictEqual(Employee.findByGender, EmployeeSchema.statics.findByGender);
         assert.strictEqual(Employee.findByDepartment, EmployeeSchema.statics.findByDepartment);
         assert.equal(Person.findByDepartment, undefined);
         done();
       });
 
-      it('inherits virtual (g.s)etters', function(done) {
+      it('inherits virtual (g.s)etters', function (done) {
         var employee = new Employee();
         employee.name.full = 'John Doe';
         assert.equal(employee.name.full, 'John Doe');
         done();
       });
 
-      it('merges callQueue with base queue defined before discriminator types callQueue', function(done) {
+      it('merges callQueue with base queue defined before discriminator types callQueue', function (done) {
         assert.equal(Employee.schema.callQueue.length, 4);
         // PersonSchema.post('save')
         assert.strictEqual(Employee.schema.callQueue[0], Person.schema.callQueue[0]);
@@ -320,13 +323,13 @@ describe('model', function() {
         done();
       });
 
-      it('does not inherit indexes', function(done) {
-        assert.deepEqual(Person.schema.indexes(), [[{ name: 1 }, { background: true }]]);
-        assert.deepEqual(Employee.schema.indexes(), [[{ department: 1 }, { background: true }]]);
+      it('does not inherit indexes', function (done) {
+        assert.deepEqual(Person.schema.indexes(), [[{name: 1}, {background: true}]]);
+        assert.deepEqual(Employee.schema.indexes(), [[{department: 1}, {background: true}]]);
         done();
       });
 
-      it('gets options overridden by root options except toJSON and toObject', function(done) {
+      it('gets options overridden by root options except toJSON and toObject', function (done) {
         var personOptions = clone(Person.schema.options),
             employeeOptions = clone(Employee.schema.options);
 
diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js
index 7ae41e57bce..765e100e054 100644
--- a/test/model.field.selection.test.js
+++ b/test/model.field.selection.test.js
@@ -39,15 +39,15 @@ var BlogPostB = new Schema({
   sigs: [Buffer],
   owners: [ObjectId],
   comments: [Comments],
-  def: { type: String, default: 'kandinsky' }
+  def: {type: String, default: 'kandinsky'}
 });
 
 var modelName = 'model.select.blogpost';
 mongoose.model(modelName, BlogPostB);
 var collection = 'blogposts_' + random();
 
-describe('model field selection', function() {
-  it('excluded fields should be undefined', function(done) {
+describe('model field selection', function () {
+  it('excluded fields should be undefined', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         date = new Date;
@@ -55,15 +55,15 @@ describe('model field selection', function() {
     var doc = {
       title: 'subset 1',
       author: 'me',
-      comments: [{ title: 'first comment', date: new Date }, { title: '2nd', date: new Date }],
-      meta: { date: date }
+      comments: [{title: 'first comment', date: new Date}, {title: '2nd', date: new Date}],
+      meta: {date: date}
     };
 
-    BlogPostB.create(doc, function(err, created) {
+    BlogPostB.create(doc, function (err, created) {
       assert.ifError(err);
 
       var id = created.id;
-      BlogPostB.findById(id, {title: 0, 'meta.date': 0, owners: 0, 'comments.user': 0}, function(err, found) {
+      BlogPostB.findById(id, {title: 0, 'meta.date': 0, owners: 0, 'comments.user': 0}, function (err, found) {
         db.close();
         assert.ifError(err);
         assert.equal(found._id.toString(), created._id);
@@ -76,7 +76,7 @@ describe('model field selection', function() {
         assert.equal(undefined, found.owners);
         assert.strictEqual(true, Array.isArray(found.comments));
         assert.equal(found.comments.length, 2);
-        found.comments.forEach(function(comment) {
+        found.comments.forEach(function (comment) {
           assert.equal(undefined, comment.user);
         });
         done();
@@ -84,16 +84,16 @@ describe('model field selection', function() {
     });
   });
 
-  it('excluded fields should be undefined and defaults applied to other fields', function(done) {
+  it('excluded fields should be undefined and defaults applied to other fields', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         id = new DocumentObjectId,
         date = new Date;
 
-    BlogPostB.collection.insert({ _id: id, title: 'hahaha1', meta: { date: date }}, function(err) {
+    BlogPostB.collection.insert({_id: id, title: 'hahaha1', meta: {date: date}}, function (err) {
       assert.ifError(err);
 
-      BlogPostB.findById(id, {title: 0}, function(err, found) {
+      BlogPostB.findById(id, {title: 0}, function (err, found) {
         db.close();
         assert.ifError(err);
         assert.equal(found._id.toString(), id);
@@ -108,31 +108,31 @@ describe('model field selection', function() {
     });
   });
 
-  it('where subset of fields excludes _id', function(done) {
+  it('where subset of fields excludes _id', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
-    BlogPostB.create({title: 'subset 1'}, function(err) {
+    BlogPostB.create({title: 'subset 1'}, function (err) {
       assert.ifError(err);
-      BlogPostB.findOne({title: 'subset 1'}, {title: 1, _id: 0}, function(err, found) {
+      BlogPostB.findOne({title: 'subset 1'}, {title: 1, _id: 0}, function (err, found) {
         db.close();
         assert.ifError(err);
         assert.strictEqual(undefined, found._id);
-        assert.equal(found.title,'subset 1');
+        assert.equal(found.title, 'subset 1');
         done();
       });
     });
   });
 
-  it('works with subset of fields, excluding _id', function(done) {
+  it('works with subset of fields, excluding _id', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
-    BlogPostB.create({title: 'subset 1', author: 'me'}, function(err) {
+    BlogPostB.create({title: 'subset 1', author: 'me'}, function (err) {
       assert.ifError(err);
-      BlogPostB.find({title: 'subset 1'}, {title: 1, _id: 0}, function(err, found) {
+      BlogPostB.find({title: 'subset 1'}, {title: 1, _id: 0}, function (err, found) {
         db.close();
         assert.ifError(err);
         assert.strictEqual(undefined, found[0]._id);
-        assert.equal(found[0].title,'subset 1');
+        assert.equal(found[0].title, 'subset 1');
         assert.strictEqual(undefined, found[0].def);
         assert.strictEqual(undefined, found[0].author);
         assert.strictEqual(false, Array.isArray(found[0].comments));
@@ -141,14 +141,14 @@ describe('model field selection', function() {
     });
   });
 
-  it('works with just _id and findOneAndUpdate (gh-3407)', function(done) {
+  it('works with just _id and findOneAndUpdate (gh-3407)', function (done) {
     var db = start();
 
-    var MyModel = db.model('gh3407', { test: { type: Number, default: 1 } });
+    var MyModel = db.model('gh3407', {test: {type: Number, default: 1}});
 
-    MyModel.collection.insert({}, function(error) {
+    MyModel.collection.insert({}, function (error) {
       assert.ifError(error);
-      MyModel.findOne({}, { _id: 1 }, function(error, doc) {
+      MyModel.findOne({}, {_id: 1}, function (error, doc) {
         assert.ifError(error);
         assert.ok(!doc.test);
         db.close(done);
@@ -156,21 +156,21 @@ describe('model field selection', function() {
     });
   });
 
-  it('works with subset of fields excluding emebedded doc _id (gh-541)', function(done) {
+  it('works with subset of fields excluding emebedded doc _id (gh-541)', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.create({title: 'LOTR', comments: [{ title: ':)' }]}, function(err, created) {
+    BlogPostB.create({title: 'LOTR', comments: [{title: ':)'}]}, function (err, created) {
       assert.ifError(err);
-      BlogPostB.find({_id: created}, { _id: 0, 'comments._id': 0 }, function(err, found) {
+      BlogPostB.find({_id: created}, {_id: 0, 'comments._id': 0}, function (err, found) {
         db.close();
         assert.ifError(err);
         assert.strictEqual(undefined, found[0]._id);
-        assert.equal(found[0].title,'LOTR');
+        assert.equal(found[0].title, 'LOTR');
         assert.strictEqual('kandinsky', found[0].def);
         assert.strictEqual(undefined, found[0].author);
         assert.strictEqual(true, Array.isArray(found[0].comments));
-        assert.equal(found[0].comments.length,1);
+        assert.equal(found[0].comments.length, 1);
         assert.equal(found[0].comments[0].title, ':)');
         assert.strictEqual(undefined, found[0].comments[0]._id);
         // gh-590
@@ -180,16 +180,16 @@ describe('model field selection', function() {
     });
   });
 
-  it('included fields should have defaults applied when no value exists in db (gh-870)', function(done) {
+  it('included fields should have defaults applied when no value exists in db (gh-870)', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         id = new DocumentObjectId;
 
     BlogPostB.collection.insert(
-        { _id: id, title: 'issue 870'}, { safe: true }, function(err) {
+        {_id: id, title: 'issue 870'}, {safe: true}, function (err) {
           assert.ifError(err);
 
-          BlogPostB.findById(id, 'def comments', function(err, found) {
+          BlogPostB.findById(id, 'def comments', function (err, found) {
             db.close();
             assert.ifError(err);
             assert.ok(found);
@@ -204,21 +204,21 @@ describe('model field selection', function() {
         });
   });
 
-  it('including subdoc field excludes other subdoc fields (gh-1027)', function(done) {
+  it('including subdoc field excludes other subdoc fields (gh-1027)', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.create({ comments: [{title: 'a'}, {title: 'b'}] }, function(err, doc) {
+    BlogPostB.create({comments: [{title: 'a'}, {title: 'b'}]}, function (err, doc) {
       assert.ifError(err);
 
-      BlogPostB.findById(doc._id).select('_id comments.title').exec(function(err, found) {
+      BlogPostB.findById(doc._id).select('_id comments.title').exec(function (err, found) {
         db.close();
         assert.ifError(err);
         assert.ok(found);
         assert.equal(found._id.toString(), doc._id.toString());
         assert.strictEqual(undefined, found.title);
         assert.strictEqual(true, Array.isArray(found.comments));
-        found.comments.forEach(function(comment) {
+        found.comments.forEach(function (comment) {
           assert.equal(undefined, comment.body);
           assert.equal(undefined, comment.comments);
           assert.equal(undefined, comment._id);
@@ -229,14 +229,14 @@ describe('model field selection', function() {
     });
   });
 
-  it('excluding nested subdoc fields (gh-1027)', function(done) {
+  it('excluding nested subdoc fields (gh-1027)', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.create({ title: 'top', comments: [{title: 'a',body: 'body'}, {title: 'b', body: 'body',comments: [{title: 'c'}]}] }, function(err, doc) {
+    BlogPostB.create({title: 'top', comments: [{title: 'a', body: 'body'}, {title: 'b', body: 'body', comments: [{title: 'c'}]}]}, function (err, doc) {
       assert.ifError(err);
 
-      BlogPostB.findById(doc._id).select('-_id -comments.title -comments.comments.comments -numbers').exec(function(err, found) {
+      BlogPostB.findById(doc._id).select('-_id -comments.title -comments.comments.comments -numbers').exec(function (err, found) {
         db.close();
         assert.ifError(err);
         assert.ok(found);
@@ -244,12 +244,12 @@ describe('model field selection', function() {
         assert.strictEqual('top', found.title);
         assert.equal(undefined, found.numbers);
         assert.strictEqual(true, Array.isArray(found.comments));
-        found.comments.forEach(function(comment) {
+        found.comments.forEach(function (comment) {
           assert.equal(undefined, comment.title);
           assert.equal('body', comment.body);
           assert.strictEqual(true, Array.isArray(comment.comments));
           assert.ok(comment._id);
-          comment.comments.forEach(function(comment) {
+          comment.comments.forEach(function (comment) {
             assert.equal('c', comment.title);
             assert.equal(undefined, comment.body);
             assert.equal(undefined, comment.comments);
@@ -261,10 +261,10 @@ describe('model field selection', function() {
     });
   });
 
-  describe('with $elemMatch projection', function() {
+  describe('with $elemMatch projection', function () {
     // mongodb 2.2 support
 
-    it('casts elemMatch args (gh-1091)', function(done) {
+    it('casts elemMatch args (gh-1091)', function (done) {
       var db = start();
 
       var postSchema = new Schema({
@@ -275,13 +275,13 @@ describe('model field selection', function() {
       var _id1 = new mongoose.Types.ObjectId;
       var _id2 = new mongoose.Types.ObjectId;
 
-      B.create({ ids: [_id1, _id2] }, function(err, doc) {
+      B.create({ids: [_id1, _id2]}, function (err, doc) {
         assert.ifError(err);
 
         B
         .findById(doc._id)
-        .select({ ids: { $elemMatch: { $in: [_id2.toString()] }}})
-        .exec(function(err, found) {
+        .select({ids: {$elemMatch: {$in: [_id2.toString()]}}})
+        .exec(function (err, found) {
           assert.ifError(err);
           assert.ok(found);
           assert.equal(found.id, doc.id);
@@ -289,9 +289,9 @@ describe('model field selection', function() {
           assert.equal(_id2.toString(), found.ids[0].toString());
 
           B
-          .find({ _id: doc._id })
-          .select({ ids: { $elemMatch: { $in: [_id2.toString()] }}})
-          .exec(function(err, found) {
+          .find({_id: doc._id})
+          .select({ids: {$elemMatch: {$in: [_id2.toString()]}}})
+          .exec(function (err, found) {
             assert.ifError(err);
             assert.ok(found.length);
             found = found[0];
@@ -304,7 +304,7 @@ describe('model field selection', function() {
       });
     });
 
-    it('disallows saving modified elemMatch paths (gh-1334)', function(done) {
+    it('disallows saving modified elemMatch paths (gh-1334)', function (done) {
       var db = start();
 
       var postSchema = new Schema({
@@ -316,20 +316,20 @@ describe('model field selection', function() {
       var _id1 = new mongoose.Types.ObjectId;
       var _id2 = new mongoose.Types.ObjectId;
 
-      B.create({ ids: [_id1, _id2], ids2: [_id2, _id1] }, function(err, doc) {
+      B.create({ids: [_id1, _id2], ids2: [_id2, _id1]}, function (err, doc) {
         assert.ifError(err);
 
         B
         .findById(doc._id)
-        .select({ ids: { $elemMatch: { $in: [_id2.toString()] }}})
-        .select({ ids2: { $elemMatch: { $in: [_id1.toString()] }}})
-        .exec(function(err, found) {
+        .select({ids: {$elemMatch: {$in: [_id2.toString()]}}})
+        .select({ids2: {$elemMatch: {$in: [_id1.toString()]}}})
+        .exec(function (err, found) {
           assert.ifError(err);
           assert.equal(1, found.ids.length);
           assert.equal(1, found.ids2.length);
           found.ids = [];
           found.ids2.set(0, _id2);
-          found.save(function(err) {
+          found.save(function (err) {
             db.close();
             assert.ok(/\$elemMatch projection/.test(err));
             assert.ok(/ ids/.test(err));
@@ -340,20 +340,20 @@ describe('model field selection', function() {
       });
     });
 
-    it('works with $ positional in select (gh-2031)', function(done) {
+    it('works with $ positional in select (gh-2031)', function (done) {
       var db = start();
 
       var postSchema = new Schema({
-        tags: [{ tag: String, count: 0 }]
+        tags: [{tag: String, count: 0}]
       });
 
       var Post = db.model('gh-2031', postSchema, 'gh-2031');
-      Post.create({ tags: [{ tag: 'bacon', count: 2 }, { tag: 'eggs', count: 3 }] }, function(error) {
+      Post.create({tags: [{tag: 'bacon', count: 2}, {tag: 'eggs', count: 3}]}, function (error) {
         assert.ifError(error);
-        Post.findOne({ 'tags.tag': 'eggs' }, { 'tags.$': 1 }, function(error, post) {
+        Post.findOne({'tags.tag': 'eggs'}, {'tags.$': 1}, function (error, post) {
           assert.ifError(error);
           post.tags[0].count = 1;
-          post.save(function(error) {
+          post.save(function (error) {
             assert.ok(error);
             db.close(done);
           });
@@ -362,15 +362,15 @@ describe('model field selection', function() {
     });
   });
 
-  it('selecting an array of docs applies defaults properly (gh-1108)', function(done) {
+  it('selecting an array of docs applies defaults properly (gh-1108)', function (done) {
     var db = start(),
         M = db.model(modelName, collection);
 
-    var m = new M({ title: '1108', comments: [{body: 'yay'}] });
+    var m = new M({title: '1108', comments: [{body: 'yay'}]});
     m.comments[0].comments = undefined;
-    m.save(function(err, doc) {
+    m.save(function (err, doc) {
       assert.ifError(err);
-      M.findById(doc._id).select('comments').exec(function(err, found) {
+      M.findById(doc._id).select('comments').exec(function (err, found) {
         assert.ifError(err);
         assert.ok(Array.isArray(found.comments));
         assert.equal(1, found.comments.length);
@@ -380,22 +380,22 @@ describe('model field selection', function() {
     });
   });
 
-  it('appropriately filters subdocuments based on properties (gh-1280)', function(done) {
+  it('appropriately filters subdocuments based on properties (gh-1280)', function (done) {
     var db = start();
     var RouteSchema = new Schema({
       stations: {
         start: {
-          name: { type: String },
-          loc: { type: [Number], index: '2d' }
+          name: {type: String},
+          loc: {type: [Number], index: '2d'}
         },
         end: {
-          name: { type: String },
-          loc: { type: [Number], index: '2d' }
+          name: {type: String},
+          loc: {type: [Number], index: '2d'}
         },
         points: [
             {
-              name: { type: String },
-              loc: { type: [Number], index: '2d' }
+              name: {type: String},
+              loc: {type: [Number], index: '2d'}
             }
         ]
       }
@@ -406,28 +406,28 @@ describe('model field selection', function() {
     var item = {
       stations: {
         start: {
-          name: "thing",
-          loc: [1,2]
+          name: 'thing',
+          loc: [1, 2]
         },
         end: {
-          name: "thingend",
-          loc: [2,3]
+          name: 'thingend',
+          loc: [2, 3]
         },
-        points: [ { name: "rawr" }]
+        points: [{name: 'rawr'}]
       }
     };
 
-    Route.create(item, function(err, i) {
+    Route.create(item, function (err, i) {
       assert.ifError(err);
 
-      Route.findById(i.id).select('-stations').exec(function(err, res) {
+      Route.findById(i.id).select('-stations').exec(function (err, res) {
         assert.ifError(err);
-        assert.ok(res.stations.toString() === "undefined");
+        assert.ok(res.stations.toString() === 'undefined');
 
-        Route.findById(i.id).select('-stations.start -stations.end').exec(function(err, res) {
+        Route.findById(i.id).select('-stations.start -stations.end').exec(function (err, res) {
           assert.ifError(err);
-          assert.equal(res.stations.start.toString(), "undefined");
-          assert.equal(res.stations.end.toString(), "undefined");
+          assert.equal(res.stations.start.toString(), 'undefined');
+          assert.equal(res.stations.end.toString(), 'undefined');
           assert.ok(Array.isArray(res.stations.points));
           db.close(done);
         });
diff --git a/test/model.findAndRemoveOne.test.js b/test/model.findAndRemoveOne.test.js
index a6e704c0ddb..19780ed6b9e 100644
--- a/test/model.findAndRemoveOne.test.js
+++ b/test/model.findAndRemoveOne.test.js
@@ -41,20 +41,20 @@ var BlogPost = new Schema({
 });
 
 BlogPost.virtual('titleWithAuthor')
-  .get(function() {
+  .get(function () {
     return this.get('title') + ' by ' + this.get('author');
   })
-  .set(function(val) {
+  .set(function (val) {
     var split = val.split(' by ');
     this.set('title', split[0]);
     this.set('author', split[1]);
   });
 
-BlogPost.method('cool', function() {
+BlogPost.method('cool', function () {
   return this;
 });
 
-BlogPost.static('woot', function() {
+BlogPost.static('woot', function () {
   return this;
 });
 
@@ -63,22 +63,22 @@ mongoose.model(modelname, BlogPost);
 
 var collection = 'removeoneblogposts_' + random();
 
-var strictSchema = new Schema({ name: String }, { strict: true });
+var strictSchema = new Schema({name: String}, {strict: true});
 mongoose.model('RemoveOneStrictSchema', strictSchema);
 
-describe('model: findOneAndRemove:', function() {
-  it('returns the original document', function(done) {
+describe('model: findOneAndRemove:', function () {
+  it('returns the original document', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'remove muah';
 
-    var post = new M({ title: title });
-    post.save(function(err) {
+    var post = new M({title: title});
+    post.save(function (err) {
       assert.ifError(err);
-      M.findOneAndRemove({ title: title }, function(err, doc) {
+      M.findOneAndRemove({title: title}, function (err, doc) {
         assert.ifError(err);
         assert.equal(doc.id, post.id);
-        M.findById(post.id, function(err, gone) {
+        M.findById(post.id, function (err, gone) {
           db.close();
           assert.ifError(err);
           assert.equal(null, gone);
@@ -88,7 +88,7 @@ describe('model: findOneAndRemove:', function() {
     });
   });
 
-  it('options/conditions/doc are merged when no callback is passed', function(done) {
+  it('options/conditions/doc are merged when no callback is passed', function (done) {
     var db = start(),
         M = db.model(modelname, collection);
 
@@ -98,11 +98,11 @@ describe('model: findOneAndRemove:', function() {
         query;
 
     // Model.findOneAndRemove
-    query = M.findOneAndRemove({ author: 'aaron' }, { select: 'author' });
+    query = M.findOneAndRemove({author: 'aaron'}, {select: 'author'});
     assert.equal(1, query._fields.author);
     assert.equal('aaron', query._conditions.author);
 
-    query = M.findOneAndRemove({ author: 'aaron' });
+    query = M.findOneAndRemove({author: 'aaron'});
     assert.equal(undefined, query._fields);
     assert.equal('aaron', query._conditions.author);
 
@@ -112,12 +112,12 @@ describe('model: findOneAndRemove:', function() {
     assert.equal(undefined, query._conditions.author);
 
     // Query.findOneAndRemove
-    query = M.where('author', 'aaron').findOneAndRemove({ date: now });
+    query = M.where('author', 'aaron').findOneAndRemove({date: now});
     assert.equal(undefined, query._fields);
     assert.equal(now, query._conditions.date);
     assert.equal('aaron', query._conditions.author);
 
-    query = M.find().findOneAndRemove({ author: 'aaron' }, { select: 'author' });
+    query = M.find().findOneAndRemove({author: 'aaron'}, {select: 'author'});
     assert.equal(1, query._fields.author);
     assert.equal('aaron', query._conditions.author);
 
@@ -127,15 +127,15 @@ describe('model: findOneAndRemove:', function() {
     done();
   });
 
-  it('executes when a callback is passed', function(done) {
+  it('executes when a callback is passed', function (done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         pending = 5;
 
-    M.findOneAndRemove({ name: 'aaron1' }, { select: 'name' }, cb);
-    M.findOneAndRemove({ name: 'aaron1' }, cb);
-    M.where().findOneAndRemove({ name: 'aaron1' }, { select: 'name' }, cb);
-    M.where().findOneAndRemove({ name: 'aaron1' }, cb);
+    M.findOneAndRemove({name: 'aaron1'}, {select: 'name'}, cb);
+    M.findOneAndRemove({name: 'aaron1'}, cb);
+    M.where().findOneAndRemove({name: 'aaron1'}, {select: 'name'}, cb);
+    M.where().findOneAndRemove({name: 'aaron1'}, cb);
     M.where('name', 'aaron1').findOneAndRemove(cb);
 
     function cb(err, doc) {
@@ -147,13 +147,13 @@ describe('model: findOneAndRemove:', function() {
     }
   });
 
-  it('executed with only a callback throws', function(done) {
+  it('executed with only a callback throws', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         err;
 
     try {
-      M.findOneAndRemove(function() {});
+      M.findOneAndRemove(function () {});
     } catch (e) {
       err = e;
     }
@@ -162,17 +162,16 @@ describe('model: findOneAndRemove:', function() {
     assert.ok(/First argument must not be a function/.test(err));
     done();
   });
-
 });
 
-describe('model: findByIdAndRemove:', function() {
-  it('executed with only a callback throws', function(done) {
+describe('model: findByIdAndRemove:', function () {
+  it('executed with only a callback throws', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         err;
 
     try {
-      M.findByIdAndRemove(function() {});
+      M.findByIdAndRemove(function () {});
     } catch (e) {
       err = e;
     }
@@ -182,13 +181,13 @@ describe('model: findByIdAndRemove:', function() {
     done();
   });
 
-  it('executes when a callback is passed', function(done) {
+  it('executes when a callback is passed', function (done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         _id = new DocumentObjectId,
         pending = 2;
 
-    M.findByIdAndRemove(_id, { select: 'name' }, cb);
+    M.findByIdAndRemove(_id, {select: 'name'}, cb);
     M.findByIdAndRemove(_id, cb);
 
     function cb(err, doc) {
@@ -200,18 +199,18 @@ describe('model: findByIdAndRemove:', function() {
     }
   });
 
-  it('returns the original document', function(done) {
+  it('returns the original document', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'remove muah pleez';
 
-    var post = new M({ title: title });
-    post.save(function(err) {
+    var post = new M({title: title});
+    post.save(function (err) {
       assert.ifError(err);
-      M.findByIdAndRemove(post.id, function(err, doc) {
+      M.findByIdAndRemove(post.id, function (err, doc) {
         assert.ifError(err);
         assert.equal(doc.id, post.id);
-        M.findById(post.id, function(err, gone) {
+        M.findById(post.id, function (err, gone) {
           db.close();
           assert.ifError(err);
           assert.equal(null, gone);
@@ -221,7 +220,7 @@ describe('model: findByIdAndRemove:', function() {
     });
   });
 
-  it('options/conditions/doc are merged when no callback is passed', function(done) {
+  it('options/conditions/doc are merged when no callback is passed', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -231,7 +230,7 @@ describe('model: findByIdAndRemove:', function() {
     var query;
 
     // Model.findByIdAndRemove
-    query = M.findByIdAndRemove(_id, { select: 'author' });
+    query = M.findByIdAndRemove(_id, {select: 'author'});
     assert.equal(1, query._fields.author);
     assert.equal(_id.toString(), query._conditions._id.toString());
 
@@ -246,7 +245,7 @@ describe('model: findByIdAndRemove:', function() {
     done();
   });
 
-  it('supports v3 select string syntax', function(done) {
+  it('supports v3 select string syntax', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -255,17 +254,17 @@ describe('model: findByIdAndRemove:', function() {
 
     var query;
 
-    query = M.findByIdAndRemove(_id, { select: 'author -title' });
+    query = M.findByIdAndRemove(_id, {select: 'author -title'});
     assert.strictEqual(1, query._fields.author);
     assert.strictEqual(0, query._fields.title);
 
-    query = M.findOneAndRemove({}, { select: 'author -title' });
+    query = M.findOneAndRemove({}, {select: 'author -title'});
     assert.strictEqual(1, query._fields.author);
     assert.strictEqual(0, query._fields.title);
     done();
   });
 
-  it('supports v3 select object syntax', function(done) {
+  it('supports v3 select object syntax', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -274,17 +273,17 @@ describe('model: findByIdAndRemove:', function() {
 
     var query;
 
-    query = M.findByIdAndRemove(_id, { select: { author: 1, title: 0 }});
+    query = M.findByIdAndRemove(_id, {select: {author: 1, title: 0}});
     assert.strictEqual(1, query._fields.author);
     assert.strictEqual(0, query._fields.title);
 
-    query = M.findOneAndRemove({}, { select: { author: 1, title: 0 }});
+    query = M.findOneAndRemove({}, {select: {author: 1, title: 0}});
     assert.strictEqual(1, query._fields.author);
     assert.strictEqual(0, query._fields.title);
     done();
   });
 
-  it('supports v3 sort string syntax', function(done) {
+  it('supports v3 sort string syntax', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -293,50 +292,50 @@ describe('model: findByIdAndRemove:', function() {
 
     var query;
 
-    query = M.findByIdAndRemove(_id, { sort: 'author -title' });
+    query = M.findByIdAndRemove(_id, {sort: 'author -title'});
     assert.equal(2, Object.keys(query.options.sort).length);
     assert.equal(1, query.options.sort.author);
     assert.equal(-1, query.options.sort.title);
 
-    query = M.findOneAndRemove({}, { sort: 'author -title' });
+    query = M.findOneAndRemove({}, {sort: 'author -title'});
     assert.equal(2, Object.keys(query.options.sort).length);
     assert.equal(1, query.options.sort.author);
     assert.equal(-1, query.options.sort.title);
     done();
   });
 
-  it('supports v3 sort object syntax', function(done) {
+  it('supports v3 sort object syntax', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
 
     var query;
 
-    query = M.findByIdAndRemove(_id, { sort: { author: 1, title: -1 }});
+    query = M.findByIdAndRemove(_id, {sort: {author: 1, title: -1}});
     assert.equal(2, Object.keys(query.options.sort).length);
     assert.equal(1, query.options.sort.author);
     assert.equal(-1, query.options.sort.title);
 
-    query = M.findOneAndRemove(_id, { sort: { author: 1, title: -1 }});
+    query = M.findOneAndRemove(_id, {sort: {author: 1, title: -1}});
     assert.equal(2, Object.keys(query.options.sort).length);
     assert.equal(1, query.options.sort.author);
     assert.equal(-1, query.options.sort.title);
     db.close(done);
   });
 
-  it('supports population (gh-1395)', function(done) {
+  it('supports population (gh-1395)', function (done) {
     var db = start();
-    var M = db.model('A', { name: String });
-    var N = db.model('B', { a: { type: Schema.ObjectId, ref: 'A' }, i: Number});
+    var M = db.model('A', {name: String});
+    var N = db.model('B', {a: {type: Schema.ObjectId, ref: 'A'}, i: Number});
 
-    M.create({ name: 'i am an A' }, function(err, a) {
+    M.create({name: 'i am an A'}, function (err, a) {
       if (err) return done(err);
-      N.create({ a: a._id, i: 10 }, function(err, b) {
+      N.create({a: a._id, i: 10}, function (err, b) {
         if (err) return done(err);
 
-        N.findOneAndRemove({ _id: b._id }, { select: 'a -_id' })
+        N.findOneAndRemove({_id: b._id}, {select: 'a -_id'})
         .populate('a')
-        .exec(function(err, doc) {
+        .exec(function (err, doc) {
           if (err) return done(err);
           assert.ok(doc);
           assert.equal(undefined, doc._id);
@@ -348,30 +347,30 @@ describe('model: findByIdAndRemove:', function() {
     });
   });
 
-  describe('middleware', function() {
+  describe('middleware', function () {
     var db;
 
-    beforeEach(function() {
+    beforeEach(function () {
       db = start();
     });
 
-    afterEach(function(done) {
+    afterEach(function (done) {
       db.close(done);
     });
 
-    it('works', function(done) {
+    it('works', function (done) {
       var s = new Schema({
-        topping: { type: String, default: 'bacon' },
+        topping: {type: String, default: 'bacon'},
         base: String
       });
 
       var preCount = 0;
-      s.pre('findOneAndRemove', function() {
+      s.pre('findOneAndRemove', function () {
         ++preCount;
       });
 
       var postCount = 0;
-      s.post('findOneAndRemove', function() {
+      s.post('findOneAndRemove', function () {
         ++postCount;
       });
 
@@ -380,13 +379,13 @@ describe('model: findByIdAndRemove:', function() {
         base: 'eggs'
       });
 
-      breakfast.save(function(error) {
+      breakfast.save(function (error) {
         assert.ifError(error);
 
         Breakfast.findOneAndRemove(
-          { base: 'eggs' },
+          {base: 'eggs'},
           {},
-          function(error, breakfast) {
+          function (error, breakfast) {
             assert.ifError(error);
             assert.equal('eggs', breakfast.base);
             assert.equal(1, preCount);
@@ -396,19 +395,19 @@ describe('model: findByIdAndRemove:', function() {
       });
     });
 
-    it('works with exec()', function(done) {
+    it('works with exec()', function (done) {
       var s = new Schema({
-        topping: { type: String, default: 'bacon' },
+        topping: {type: String, default: 'bacon'},
         base: String
       });
 
       var preCount = 0;
-      s.pre('findOneAndRemove', function() {
+      s.pre('findOneAndRemove', function () {
         ++preCount;
       });
 
       var postCount = 0;
-      s.post('findOneAndRemove', function() {
+      s.post('findOneAndRemove', function () {
         ++postCount;
       });
 
@@ -417,12 +416,12 @@ describe('model: findByIdAndRemove:', function() {
         base: 'eggs'
       });
 
-      breakfast.save(function(error) {
+      breakfast.save(function (error) {
         assert.ifError(error);
 
         Breakfast.
-          findOneAndRemove({ base: 'eggs' }, {}).
-          exec(function(error, breakfast) {
+          findOneAndRemove({base: 'eggs'}, {}).
+          exec(function (error, breakfast) {
             assert.ifError(error);
             assert.equal('eggs', breakfast.base);
             assert.equal(1, preCount);
diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index 7d98d929c3a..a256fd9c87c 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Test dependencies.
  */
@@ -44,20 +43,20 @@ var BlogPost = new Schema({
 });
 
 BlogPost.virtual('titleWithAuthor')
-  .get(function() {
-    return this.get('title') + ' by ' + this.get('author');
-  })
-  .set(function(val) {
-    var split = val.split(' by ');
-    this.set('title', split[0]);
-    this.set('author', split[1]);
-  });
+.get(function () {
+  return this.get('title') + ' by ' + this.get('author');
+})
+.set(function (val) {
+  var split = val.split(' by ');
+  this.set('title', split[0]);
+  this.set('author', split[1]);
+});
 
-BlogPost.method('cool', function() {
+BlogPost.method('cool', function () {
   return this;
 });
 
-BlogPost.static('woot', function() {
+BlogPost.static('woot', function () {
   return this;
 });
 
@@ -66,14 +65,14 @@ mongoose.model(modelname, BlogPost);
 
 var collection = 'updateoneblogposts_' + random();
 
-var strictSchema = new Schema({ name: String }, { strict: true });
+var strictSchema = new Schema({name: String}, {strict: true});
 mongoose.model('UpdateOneStrictSchema', strictSchema);
 
-var strictThrowSchema = new Schema({ name: String }, { strict: 'throw'});
+var strictThrowSchema = new Schema({name: String}, {strict: 'throw'});
 mongoose.model('UpdateOneStrictThrowSchema', strictThrowSchema);
 
-describe('model: findOneAndUpdate:', function() {
-  it('WWW returns the edited document', function(done) {
+describe('model: findOneAndUpdate:', function () {
+  it('WWW returns the edited document', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'Tobi ' + random(),
@@ -88,14 +87,14 @@ describe('model: findOneAndUpdate:', function() {
     post.meta.visitors = 0;
     post.date = new Date;
     post.published = true;
-    post.mixed = { x: 'ex' };
-    post.numbers = [4,5,6,7];
+    post.mixed = {x: 'ex'};
+    post.numbers = [4, 5, 6, 7];
     post.owners = [id0, id1];
-    post.comments = [{ body: 'been there' }, { body: 'done that' }];
+    post.comments = [{body: 'been there'}, {body: 'done that'}];
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
-      M.findById(post._id, function(err, cf) {
+      M.findById(post._id, function (err, cf) {
         assert.ifError(err);
         assert.equal(title, cf.title);
         assert.equal(author, cf.author);
@@ -103,10 +102,10 @@ describe('model: findOneAndUpdate:', function() {
         assert.equal(post.date.toString(), cf.date);
         assert.equal(true, cf.published);
         assert.equal('ex', cf.mixed.x);
-        assert.deepEqual([4,5,6,7], cf.numbers.toObject());
+        assert.deepEqual([4, 5, 6, 7], cf.numbers.toObject());
         assert.equal(2, cf.owners.length);
-        assert.equal(id0.toString(),cf.owners[0].toString() );
-        assert.equal(id1.toString(),cf.owners[1].toString() );
+        assert.equal(id0.toString(), cf.owners[0].toString());
+        assert.equal(id1.toString(), cf.owners[1].toString());
         assert.equal(2, cf.comments.length);
         assert.equal('been there', cf.comments[0].body);
         assert.equal('done that', cf.comments[1].body);
@@ -117,29 +116,29 @@ describe('model: findOneAndUpdate:', function() {
 
         var update = {
           title: newTitle, // becomes $set
-          $inc: { 'meta.visitors': 2 },
-          $set: { date: new Date },
+          $inc: {'meta.visitors': 2},
+          $set: {date: new Date},
           published: false, // becomes $set
-          'mixed': { x: 'ECKS', y: 'why' }, // $set
-          $pullAll: { 'numbers': [4, 6] },
-          $pull: { 'owners': id0 },
+          mixed: {x: 'ECKS', y: 'why'}, // $set
+          $pullAll: {numbers: [4, 6]},
+          $pull: {'owners': id0},
           'comments.1.body': 8 // $set
         };
 
-        M.findOneAndUpdate({ title: title }, update, { 'new': true }, function(err, up) {
+        M.findOneAndUpdate({title: title}, update, {'new': true}, function (err, up) {
           db.close();
           assert.equal(err, null, err && err.stack);
 
           assert.equal(newTitle, up.title);
           assert.equal(author, up.author);
           assert.equal(2, up.meta.visitors.valueOf());
-          assert.equal(update.$set.date.toString(),up.date.toString());
+          assert.equal(update.$set.date.toString(), up.date.toString());
           assert.equal(false, up.published);
           assert.equal('ECKS', up.mixed.x);
           assert.equal('why', up.mixed.y);
-          assert.deepEqual([5,7], up.numbers.toObject());
+          assert.deepEqual([5, 7], up.numbers.toObject());
           assert.equal(1, up.owners.length);
-          assert.equal(id1.toString(),up.owners[0].toString());
+          assert.equal(id1.toString(), up.owners[0].toString());
           assert.equal('been there', up.comments[0].body);
           assert.equal('8', up.comments[1].body);
           assert.ok(up.comments[0]._id);
@@ -152,14 +151,16 @@ describe('model: findOneAndUpdate:', function() {
     });
   });
 
-  describe('will correctly', function() {
+  describe('will correctly', function () {
     var db, ItemParentModel, ItemChildModel;
 
-    before(function() {
+    before(function () {
       db = start();
       var itemSpec = new Schema({
         item_id: {
-          type: ObjectId, required: true, default: function() { return new DocumentObjectId();}
+          type: ObjectId, required: true, default: function () {
+            return new DocumentObjectId();
+          }
         },
         address: {
           street: String,
@@ -174,51 +175,51 @@ describe('model: findOneAndUpdate:', function() {
       ItemChildModel = db.model('ItemChildModel', itemSpec);
     });
 
-    after(function() {
+    after(function () {
       db.close();
     });
 
-    it('update subdocument in array item', function(done) {
+    it('update subdocument in array item', function (done) {
       var item1 = new ItemChildModel({
         address: {
-          street: "times square",
-          zipcode: "10036"
+          street: 'times square',
+          zipcode: '10036'
         }
       });
       var item2 = new ItemChildModel({
         address: {
-          street: "bryant park",
-          zipcode: "10030"
+          street: 'bryant park',
+          zipcode: '10030'
         }
       });
       var item3 = new ItemChildModel({
         address: {
-          street: "queens",
-          zipcode: "1002?"
+          street: 'queens',
+          zipcode: '1002?'
         }
       });
-      var itemParent = new ItemParentModel({items:[item1, item2, item3]});
-      itemParent.save(function(err) {
+      var itemParent = new ItemParentModel({items: [item1, item2, item3]});
+      itemParent.save(function (err) {
         assert.ifError(err);
         ItemParentModel.findOneAndUpdate(
-          {"_id": itemParent._id, "items.item_id": item1.item_id},
-          {"$set":{ "items.$.address":{}}},
-          {new: true},
-          function(err, updatedDoc) {
-            assert.ifError(err);
-            assert.ok(updatedDoc.items);
-            assert.ok(updatedDoc.items instanceof Array);
-            assert.ok(updatedDoc.items.length, 3);
-            assert.ok(Utils.isObject(updatedDoc.items[0].address));
-            assert.ok(Object.keys(updatedDoc.items[0].address).length, 0);
-            done();
-          }
+            {_id: itemParent._id, 'items.item_id': item1.item_id},
+            {$set: {'items.$.address': {}}},
+            {new: true},
+            function (err, updatedDoc) {
+              assert.ifError(err);
+              assert.ok(updatedDoc.items);
+              assert.ok(updatedDoc.items instanceof Array);
+              assert.ok(updatedDoc.items.length, 3);
+              assert.ok(Utils.isObject(updatedDoc.items[0].address));
+              assert.ok(Object.keys(updatedDoc.items[0].address).length, 0);
+              done();
+            }
         );
       });
     });
   });
 
-  it('returns the original document', function(done) {
+  it('returns the original document', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'Tobi ' + random(),
@@ -233,37 +234,37 @@ describe('model: findOneAndUpdate:', function() {
     post.meta.visitors = 0;
     post.date = new Date;
     post.published = true;
-    post.mixed = { x: 'ex' };
-    post.numbers = [4,5,6,7];
+    post.mixed = {x: 'ex'};
+    post.numbers = [4, 5, 6, 7];
     post.owners = [id0, id1];
-    post.comments = [{ body: 'been there' }, { body: 'done that' }];
+    post.comments = [{body: 'been there'}, {body: 'done that'}];
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
-      M.findById(post._id, function(err) {
+      M.findById(post._id, function (err) {
         assert.ifError(err);
 
         var update = {
           title: newTitle, // becomes $set
-          $inc: { 'meta.visitors': 2 },
-          $set: { date: new Date },
+          $inc: {'meta.visitors': 2},
+          $set: {date: new Date},
           published: false, // becomes $set
-          'mixed': { x: 'ECKS', y: 'why' }, // $set
-          $pullAll: { 'numbers': [4, 6] },
-          $pull: { 'owners': id0 },
+          mixed: {x: 'ECKS', y: 'why'}, // $set
+          $pullAll: {numbers: [4, 6]},
+          $pull: {owners: id0},
           'comments.1.body': 8 // $set
         };
 
-        M.findOneAndUpdate({ title: title }, update, { new: false }, function(err, up) {
+        M.findOneAndUpdate({title: title}, update, {new: false}, function (err, up) {
           db.close();
           assert.ifError(err);
 
           assert.equal(post.title, up.title);
           assert.equal(post.author, up.author);
           assert.equal(post.meta.visitors, up.meta.visitors.valueOf());
-          assert.equal(up.date.toString(),post.date.toString());
-          assert.equal(up.published,post.published);
-          assert.equal(up.mixed.x,post.mixed.x);
+          assert.equal(up.date.toString(), post.date.toString());
+          assert.equal(up.published, post.published);
+          assert.equal(up.mixed.x, post.mixed.x);
           assert.equal(up.mixed.y, post.mixed.y);
           assert.deepEqual(up.numbers.toObject(), post.numbers.toObject());
           assert.equal(up.owners.length, post.owners.length);
@@ -280,7 +281,7 @@ describe('model: findOneAndUpdate:', function() {
     });
   });
 
-  it('allows upserting', function(done) {
+  it('allows upserting', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'Tobi ' + random(),
@@ -295,28 +296,28 @@ describe('model: findOneAndUpdate:', function() {
     post.meta.visitors = 0;
     post.date = new Date;
     post.published = true;
-    post.mixed = { x: 'ex' };
-    post.numbers = [4,5,6,7];
+    post.mixed = {x: 'ex'};
+    post.numbers = [4, 5, 6, 7];
     post.owners = [id0, id1];
-    post.comments = [{ body: 'been there' }, { body: 'done that' }];
+    post.comments = [{body: 'been there'}, {body: 'done that'}];
 
     var update = {
       title: newTitle, // becomes $set
-      $inc: { 'meta.visitors': 2 },
-      $set: { date: new Date },
+      $inc: {'meta.visitors': 2},
+      $set: {date: new Date},
       published: false, // becomes $set
-      'mixed': { x: 'ECKS', y: 'why' }, // $set
-      $pullAll: { 'numbers': [4, 6] },
-      $pull: { 'owners': id0 }
+      mixed: {x: 'ECKS', y: 'why'}, // $set
+      $pullAll: {numbers: [4, 6]},
+      $pull: {owners: id0}
     };
 
-    M.findOneAndUpdate({ title: title }, update, { upsert: true, new: true }, function(err, up) {
+    M.findOneAndUpdate({title: title}, update, {upsert: true, new: true}, function (err, up) {
       db.close();
       assert.ifError(err);
 
       assert.equal(newTitle, up.title);
       assert.equal(2, up.meta.visitors.valueOf());
-      assert.equal(up.date.toString(),update.$set.date.toString());
+      assert.equal(up.date.toString(), update.$set.date.toString());
       assert.equal(update.published, up.published);
       assert.deepEqual(update.mixed.x, up.mixed.x);
       assert.strictEqual(up.mixed.y, update.mixed.y);
@@ -328,7 +329,7 @@ describe('model: findOneAndUpdate:', function() {
     });
   });
 
-  it('options/conditions/doc are merged when no callback is passed', function(done) {
+  it('options/conditions/doc are merged when no callback is passed', function (done) {
     var db = start(),
         M = db.model(modelname, collection);
 
@@ -338,18 +339,18 @@ describe('model: findOneAndUpdate:', function() {
         query;
 
     // Model.findOneAndUpdate
-    query = M.findOneAndUpdate({ author: 'aaron' }, { $set: { date: now }}, { new: false, fields: 'author' });
+    query = M.findOneAndUpdate({author: 'aaron'}, {$set: {date: now}}, {new: false, fields: 'author'});
     assert.strictEqual(false, query.options.new);
     assert.strictEqual(1, query._fields.author);
     assert.equal(now.toString(), query._update.$set.date.toString());
     assert.strictEqual('aaron', query._conditions.author);
 
-    query = M.findOneAndUpdate({ author: 'aaron' }, { $set: { date: now }});
+    query = M.findOneAndUpdate({author: 'aaron'}, {$set: {date: now}});
     assert.strictEqual(undefined, query.options.new);
     assert.equal(now.toString(), query._update.$set.date.toString());
     assert.strictEqual('aaron', query._conditions.author);
 
-    query = M.findOneAndUpdate({ $set: { date: now }});
+    query = M.findOneAndUpdate({$set: {date: now}});
     assert.strictEqual(undefined, query.options.new);
     assert.equal(now.toString(), query._update.$set.date.toString());
     assert.strictEqual(undefined, query._conditions.author);
@@ -360,17 +361,17 @@ describe('model: findOneAndUpdate:', function() {
     assert.strictEqual(undefined, query._conditions.author);
 
     // Query.findOneAndUpdate
-    query = M.where('author', 'aaron').findOneAndUpdate({ date: now });
+    query = M.where('author', 'aaron').findOneAndUpdate({date: now});
     assert.strictEqual(undefined, query.options.new);
     assert.equal(now.toString(), query._update.date.toString());
     assert.strictEqual('aaron', query._conditions.author);
 
-    query = M.find().findOneAndUpdate({ author: 'aaron' }, { date: now });
+    query = M.find().findOneAndUpdate({author: 'aaron'}, {date: now});
     assert.strictEqual(undefined, query.options.new);
     assert.equal(now.toString(), query._update.date.toString());
     assert.strictEqual('aaron', query._conditions.author);
 
-    query = M.find().findOneAndUpdate({ date: now });
+    query = M.find().findOneAndUpdate({date: now});
     assert.strictEqual(undefined, query.options.new);
     assert.equal(now.toString(), query._update.date.toString());
     assert.strictEqual(undefined, query._conditions.author);
@@ -382,55 +383,60 @@ describe('model: findOneAndUpdate:', function() {
     done();
   });
 
-  it('executes when a callback is passed', function(done) {
+  it('executes when a callback is passed', function (done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         pending = 6;
 
-    M.findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron6'}}, { new: false }, cb);
-    M.findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron4'}}, cb);
-    M.where().findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron1'}}, { new: false }, cb);
-    M.where().findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron2'}}, cb);
-    M.where().findOneAndUpdate({ $set: { name: 'Aaron6'}}, cb);
-    M.where('name', 'aaron').findOneAndUpdate({ $set: { name: 'Aaron'}}).findOneAndUpdate(cb);
+    M.findOneAndUpdate({name: 'aaron'}, {$set: {name: 'Aaron6'}}, {new: false}, cb);
+    M.findOneAndUpdate({name: 'aaron'}, {$set: {name: 'Aaron4'}}, cb);
+    M.where().findOneAndUpdate({name: 'aaron'}, {$set: {name: 'Aaron1'}}, {new: false}, cb);
+    M.where().findOneAndUpdate({name: 'aaron'}, {$set: {name: 'Aaron2'}}, cb);
+    M.where().findOneAndUpdate({$set: {name: 'Aaron6'}}, cb);
+    M.where('name', 'aaron').findOneAndUpdate({$set: {name: 'Aaron'}}).findOneAndUpdate(cb);
 
     function cb(err, doc) {
       assert.ifError(err);
       assert.strictEqual(null, doc); // not an upsert, no previously existing doc
-      if (--pending) return;
+      if (--pending) {
+        return;
+      }
       db.close();
       done();
     }
   });
 
-  it('executes when a callback is passed to a succeeding function', function(done) {
+  it('executes when a callback is passed to a succeeding function', function (done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         pending = 6;
 
-    M.findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron'}}, { new: false }).exec(cb);
-    M.findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron'}}).exec(cb);
-    M.where().findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron'}}, { new: false }).exec(cb);
-    M.where().findOneAndUpdate({ name: 'aaron' }, { $set: { name: 'Aaron'}}).exec(cb);
-    M.where().findOneAndUpdate({ $set: { name: 'Aaron'}}).exec(cb);
-    M.where('name', 'aaron').findOneAndUpdate({ $set: { name: 'Aaron'}}).exec(cb);
+    M.findOneAndUpdate({name: 'aaron'}, {$set: {name: 'Aaron'}}, {new: false}).exec(cb);
+    M.findOneAndUpdate({name: 'aaron'}, {$set: {name: 'Aaron'}}).exec(cb);
+    M.where().findOneAndUpdate({name: 'aaron'}, {$set: {name: 'Aaron'}}, {new: false}).exec(cb);
+    M.where().findOneAndUpdate({name: 'aaron'}, {$set: {name: 'Aaron'}}).exec(cb);
+    M.where().findOneAndUpdate({$set: {name: 'Aaron'}}).exec(cb);
+    M.where('name', 'aaron').findOneAndUpdate({$set: {name: 'Aaron'}}).exec(cb);
 
     function cb(err, doc) {
       assert.ifError(err);
       assert.strictEqual(null, doc); // not an upsert, no previously existing doc
-      if (--pending) return;
+      if (--pending) {
+        return;
+      }
       db.close();
       done();
     }
   });
 
-  it('executing with only a callback throws', function(done) {
+  it('executing with only a callback throws', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         err;
 
     try {
-      M.findOneAndUpdate(function() {});
+      M.findOneAndUpdate(function () {
+      });
     } catch (e) {
       err = e;
     }
@@ -440,7 +446,7 @@ describe('model: findOneAndUpdate:', function() {
     done();
   });
 
-  it('updates numbers atomically', function(done) {
+  it('updates numbers atomically', function (done) {
     var db = start(),
         BlogPost = db.model(modelname, collection),
         totalDocs = 4;
@@ -448,19 +454,19 @@ describe('model: findOneAndUpdate:', function() {
     var post = new BlogPost();
     post.set('meta.visitors', 5);
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
       for (var i = 0; i < 4; ++i) {
         BlogPost
-        .findOneAndUpdate({ _id: post._id }, { $inc: { 'meta.visitors': 1 }}, function(err) {
+        .findOneAndUpdate({_id: post._id}, {$inc: {'meta.visitors': 1}}, function (err) {
           assert.ifError(err);
           --totalDocs || complete();
         });
       }
 
       function complete() {
-        BlogPost.findOne({ _id: post.get('_id') }, function(err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
           db.close();
           assert.ifError(err);
           assert.equal(9, doc.get('meta.visitors'));
@@ -470,27 +476,27 @@ describe('model: findOneAndUpdate:', function() {
     });
   });
 
-  it('honors strict schemas', function(done) {
+  it('honors strict schemas', function (done) {
     var db = start();
     var S = db.model('UpdateOneStrictSchema');
-    var s = new S({ name: 'orange crush' });
+    var s = new S({name: 'orange crush'});
 
-    s.save(function(err) {
+    s.save(function (err) {
       assert.ifError(err);
       var name = Date.now();
-      S.findOneAndUpdate({ name: name }, { ignore: true }, { upsert: true, 'new': true }, function(err, doc) {
+      S.findOneAndUpdate({name: name}, {ignore: true}, {upsert: true, 'new': true}, function (err, doc) {
         assert.ifError(err);
         assert.ok(doc);
         assert.ok(doc._id);
         assert.equal(undefined, doc.ignore);
         assert.equal(undefined, doc._doc.ignore);
         assert.equal(name, doc.name);
-        S.findOneAndUpdate({ name: 'orange crush' }, { ignore: true }, { upsert: true }, function(err, doc) {
+        S.findOneAndUpdate({name: 'orange crush'}, {ignore: true}, {upsert: true}, function (err, doc) {
           assert.ifError(err);
           assert.ok(!doc.ignore);
           assert.ok(!doc._doc.ignore);
           assert.equal('orange crush', doc.name);
-          S.findOneAndUpdate({ name: 'orange crush' }, { ignore: true }, function(err, doc) {
+          S.findOneAndUpdate({name: 'orange crush'}, {ignore: true}, function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.ok(!doc.ignore);
@@ -503,21 +509,21 @@ describe('model: findOneAndUpdate:', function() {
     });
   });
 
-  it('returns errors with strict:throw schemas', function(done) {
+  it('returns errors with strict:throw schemas', function (done) {
     var db = start();
     var S = db.model('UpdateOneStrictThrowSchema');
-    var s = new S({ name: 'orange crush' });
+    var s = new S({name: 'orange crush'});
 
-    s.save(function(err) {
+    s.save(function (err) {
       assert.ifError(err);
 
       var name = Date.now();
-      S.findOneAndUpdate({ name: name }, { ignore: true }, { upsert: true }, function(err, doc) {
+      S.findOneAndUpdate({name: name}, {ignore: true}, {upsert: true}, function (err, doc) {
         assert.ok(err);
         assert.ok(/not in schema/.test(err));
         assert.ok(!doc);
 
-        S.findOneAndUpdate({ _id: s._id }, { ignore: true }, function(err, doc) {
+        S.findOneAndUpdate({_id: s._id}, {ignore: true}, function (err, doc) {
           db.close();
           assert.ok(err);
           assert.ok(/not in schema/.test(err));
@@ -529,14 +535,15 @@ describe('model: findOneAndUpdate:', function() {
   });
 });
 
-describe('model: findByIdAndUpdate:', function() {
-  it('executing with just a callback throws', function(done) {
+describe('model: findByIdAndUpdate:', function () {
+  it('executing with just a callback throws', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         err;
 
     try {
-      M.findByIdAndUpdate(function() {});
+      M.findByIdAndUpdate(function () {
+      });
     } catch (e) {
       err = e;
     }
@@ -546,41 +553,45 @@ describe('model: findByIdAndUpdate:', function() {
     done();
   });
 
-  it('executes when a callback is passed', function(done) {
+  it('executes when a callback is passed', function (done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         _id = new DocumentObjectId,
         pending = 2;
 
-    M.findByIdAndUpdate(_id, { $set: { name: 'Aaron'}}, { new: false }, cb);
-    M.findByIdAndUpdate(_id, { $set: { name: 'changed' }}, cb);
+    M.findByIdAndUpdate(_id, {$set: {name: 'Aaron'}}, {new: false}, cb);
+    M.findByIdAndUpdate(_id, {$set: {name: 'changed'}}, cb);
 
     function cb(err, doc) {
       assert.ifError(err);
       assert.strictEqual(null, doc); // no previously existing doc
-      if (--pending) return;
+      if (--pending) {
+        return;
+      }
       db.close(done);
     }
   });
 
-  it('executes when a callback is passed to a succeeding function', function(done) {
+  it('executes when a callback is passed to a succeeding function', function (done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         _id = new DocumentObjectId,
         pending = 2;
 
-    M.findByIdAndUpdate(_id, { $set: { name: 'Aaron'}}, { new: false }).exec(cb);
-    M.findByIdAndUpdate(_id, { $set: { name: 'changed' }}).exec(cb);
+    M.findByIdAndUpdate(_id, {$set: {name: 'Aaron'}}, {new: false}).exec(cb);
+    M.findByIdAndUpdate(_id, {$set: {name: 'changed'}}).exec(cb);
 
     function cb(err, doc) {
       assert.ifError(err);
       assert.strictEqual(null, doc); // no previously existing doc
-      if (--pending) return;
+      if (--pending) {
+        return;
+      }
       db.close(done);
     }
   });
 
-  it('returns the original document', function(done) {
+  it('returns the original document', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'Tobi ' + random(),
@@ -595,32 +606,32 @@ describe('model: findByIdAndUpdate:', function() {
     post.meta.visitors = 0;
     post.date = new Date;
     post.published = true;
-    post.mixed = { x: 'ex' };
-    post.numbers = [4,5,6,7];
+    post.mixed = {x: 'ex'};
+    post.numbers = [4, 5, 6, 7];
     post.owners = [id0, id1];
-    post.comments = [{ body: 'been there' }, { body: 'done that' }];
+    post.comments = [{body: 'been there'}, {body: 'done that'}];
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
-      M.findById(post._id, function(err) {
+      M.findById(post._id, function (err) {
         assert.ifError(err);
 
         var update = {
           title: newTitle, // becomes $set
-          $inc: { 'meta.visitors': 2 },
-          $set: { date: new Date },
+          $inc: {'meta.visitors': 2},
+          $set: {date: new Date},
           published: false, // becomes $set
-          'mixed': { x: 'ECKS', y: 'why' }, // $set
-          $pullAll: { 'numbers': [4, 6] },
-          $pull: { 'owners': id0 },
+          mixed: {x: 'ECKS', y: 'why'}, // $set
+          $pullAll: {numbers: [4, 6]},
+          $pull: {owners: id0},
           'comments.1.body': 8 // $set
         };
 
-        M.findByIdAndUpdate(post.id, update, { new: false }, function(err, up) {
+        M.findByIdAndUpdate(post.id, update, {new: false}, function (err, up) {
           assert.ifError(err);
 
-          assert.equal(up.title,post.title);
-          assert.equal(up.author,post.author);
+          assert.equal(up.title, post.title);
+          assert.equal(up.author, post.author);
           assert.equal(up.meta.visitors.valueOf(), post.meta.visitors);
           assert.equal(up.date.toString(), post.date.toString());
           assert.equal(up.published, post.published);
@@ -641,7 +652,7 @@ describe('model: findByIdAndUpdate:', function() {
     });
   });
 
-  it('options/conditions/doc are merged when no callback is passed', function(done) {
+  it('options/conditions/doc are merged when no callback is passed', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -650,13 +661,13 @@ describe('model: findByIdAndUpdate:', function() {
         query;
 
     // Model.findByIdAndUpdate
-    query = M.findByIdAndUpdate(_id, { $set: { date: now }}, { new: false, fields: 'author' });
+    query = M.findByIdAndUpdate(_id, {$set: {date: now}}, {new: false, fields: 'author'});
     assert.strictEqual(false, query.options.new);
     assert.strictEqual(1, query._fields.author);
     assert.equal(now.toString(), query._update.$set.date.toString());
     assert.strictEqual(_id.toString(), query._conditions._id.toString());
 
-    query = M.findByIdAndUpdate(_id, { $set: { date: now }});
+    query = M.findByIdAndUpdate(_id, {$set: {date: now}});
     assert.strictEqual(undefined, query.options.new);
     assert.equal(now.toString(), query._update.$set.date.toString());
     assert.strictEqual(_id.toString(), query._conditions._id.toString());
@@ -672,7 +683,7 @@ describe('model: findByIdAndUpdate:', function() {
     db.close(done);
   });
 
-  it('supports v3 select string syntax', function(done) {
+  it('supports v3 select string syntax', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -680,17 +691,17 @@ describe('model: findByIdAndUpdate:', function() {
     var now = new Date,
         query;
 
-    query = M.findByIdAndUpdate(_id, { $set: { date: now }}, { select: 'author -title' });
+    query = M.findByIdAndUpdate(_id, {$set: {date: now}}, {select: 'author -title'});
     assert.strictEqual(1, query._fields.author);
     assert.strictEqual(0, query._fields.title);
 
-    query = M.findOneAndUpdate({}, { $set: { date: now }}, { select: 'author -title' });
+    query = M.findOneAndUpdate({}, {$set: {date: now}}, {select: 'author -title'});
     assert.strictEqual(1, query._fields.author);
     assert.strictEqual(0, query._fields.title);
     db.close(done);
   });
 
-  it('supports v3 select object syntax', function(done) {
+  it('supports v3 select object syntax', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -698,17 +709,17 @@ describe('model: findByIdAndUpdate:', function() {
     var now = new Date,
         query;
 
-    query = M.findByIdAndUpdate(_id, { $set: { date: now }}, { select: { author: 1, title: 0 }});
+    query = M.findByIdAndUpdate(_id, {$set: {date: now}}, {select: {author: 1, title: 0}});
     assert.strictEqual(1, query._fields.author);
     assert.strictEqual(0, query._fields.title);
 
-    query = M.findOneAndUpdate({}, { $set: { date: now }}, { select: { author: 1, title: 0 }});
+    query = M.findOneAndUpdate({}, {$set: {date: now}}, {select: {author: 1, title: 0}});
     assert.strictEqual(1, query._fields.author);
     assert.strictEqual(0, query._fields.title);
     db.close(done);
   });
 
-  it('supports v3 sort string syntax', function(done) {
+  it('supports v3 sort string syntax', function (done) {
     var db = start(),
         M = db.model(modelname, collection);
 
@@ -716,35 +727,39 @@ describe('model: findByIdAndUpdate:', function() {
     var _id = new DocumentObjectId;
     var query;
 
-    query = M.findByIdAndUpdate(_id, { $set: { date: now }}, { sort: 'author -title' });
+    query = M.findByIdAndUpdate(_id, {$set: {date: now}}, {sort: 'author -title'});
     assert.equal(2, Object.keys(query.options.sort).length);
     assert.equal(1, query.options.sort.author);
     assert.equal(-1, query.options.sort.title);
 
-    query = M.findOneAndUpdate({}, { $set: { date: now }}, { sort: 'author -title' });
+    query = M.findOneAndUpdate({}, {$set: {date: now}}, {sort: 'author -title'});
     assert.equal(2, Object.keys(query.options.sort).length);
     assert.equal(1, query.options.sort.author);
     assert.equal(-1, query.options.sort.title);
 
     // gh-1887
     M.create(
-        { title: 1, meta: {visitors: 0}}
-      , { title: 2, meta: {visitors: 10}}
-      , { title: 3, meta: {visitors: 5}}
-      , function(err) {
-        if (err) return done(err);
-
-        M.findOneAndUpdate({}, { title: 'changed' })
-      .sort({ 'meta.visitors': -1 })
-      .exec(function(err, doc) {
-        if (err) return done(err);
-        assert.equal(10, doc.meta.visitors);
-        db.close(done);
-      });
-      });
+        {title: 1, meta: {visitors: 0}}
+        , {title: 2, meta: {visitors: 10}}
+        , {title: 3, meta: {visitors: 5}}
+        , function (err) {
+          if (err) {
+            return done(err);
+          }
+
+          M.findOneAndUpdate({}, {title: 'changed'})
+          .sort({'meta.visitors': -1})
+          .exec(function (err, doc) {
+            if (err) {
+              return done(err);
+            }
+            assert.equal(10, doc.meta.visitors);
+            db.close(done);
+          });
+        });
   });
 
-  it('supports v3 sort object syntax', function(done) {
+  it('supports v3 sort object syntax', function (done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -752,12 +767,12 @@ describe('model: findByIdAndUpdate:', function() {
     var now = new Date,
         query;
 
-    query = M.findByIdAndUpdate(_id, { $set: { date: now }}, { sort: { author: 1, title: -1 }});
+    query = M.findByIdAndUpdate(_id, {$set: {date: now}}, {sort: {author: 1, title: -1}});
     assert.equal(2, Object.keys(query.options.sort).length);
     assert.equal(1, query.options.sort.author);
     assert.equal(-1, query.options.sort.title);
 
-    query = M.findOneAndUpdate(_id, { $set: { date: now }}, { sort: { author: 1, title: -1 }});
+    query = M.findOneAndUpdate(_id, {$set: {date: now}}, {sort: {author: 1, title: -1}});
     assert.equal(2, Object.keys(query.options.sort).length);
     assert.equal(1, query.options.sort.author);
     assert.equal(-1, query.options.sort.title);
@@ -765,7 +780,7 @@ describe('model: findByIdAndUpdate:', function() {
     db.close(done);
   });
 
-  it('supports $elemMatch with $in (gh-1091 gh-1100)', function(done) {
+  it('supports $elemMatch with $in (gh-1091 gh-1100)', function (done) {
     var db = start();
 
     var postSchema = new Schema({
@@ -777,13 +792,13 @@ describe('model: findByIdAndUpdate:', function() {
     var _id1 = new mongoose.Types.ObjectId;
     var _id2 = new mongoose.Types.ObjectId;
 
-    B.create({ ids: [_id1, _id2] }, function(err, doc) {
+    B.create({ids: [_id1, _id2]}, function (err, doc) {
       assert.ifError(err);
 
       B
-      .findByIdAndUpdate(doc._id, { title: 'woot' }, { 'new': true })
-      .select({ title: 1, ids: { $elemMatch: { $in: [_id2.toString()] }}})
-      .exec(function(err, found) {
+      .findByIdAndUpdate(doc._id, {title: 'woot'}, {'new': true})
+      .select({title: 1, ids: {$elemMatch: {$in: [_id2.toString()]}}})
+      .exec(function (err, found) {
         assert.ifError(err);
         assert.ok(found);
         assert.equal(found.id, doc.id);
@@ -795,20 +810,26 @@ describe('model: findByIdAndUpdate:', function() {
     });
   });
 
-  it('supports population (gh-1395)', function(done) {
+  it('supports population (gh-1395)', function (done) {
     var db = start();
-    var M = db.model('A', { name: String });
-    var N = db.model('B', { a: { type: Schema.ObjectId, ref: 'A' }, i: Number});
+    var M = db.model('A', {name: String});
+    var N = db.model('B', {a: {type: Schema.ObjectId, ref: 'A'}, i: Number});
 
-    M.create({ name: 'i am an A' }, function(err, a) {
-      if (err) return done(err);
-      N.create({ a: a._id, i: 10 }, function(err, b) {
-        if (err) return done(err);
+    M.create({name: 'i am an A'}, function (err, a) {
+      if (err) {
+        return done(err);
+      }
+      N.create({a: a._id, i: 10}, function (err, b) {
+        if (err) {
+          return done(err);
+        }
 
-        N.findOneAndUpdate({ _id: b._id }, { $inc: { i: 1 }})
+        N.findOneAndUpdate({_id: b._id}, {$inc: {i: 1}})
         .populate('a')
-        .exec(function(err, doc) {
-          if (err) return done(err);
+        .exec(function (err, doc) {
+          if (err) {
+            return done(err);
+          }
           assert.ok(doc);
           assert.ok(doc.a);
           assert.equal(doc.a.name, 'i am an A');
@@ -817,24 +838,24 @@ describe('model: findByIdAndUpdate:', function() {
       });
     });
   });
-  it('returns null when doing an upsert & new=false gh-1533', function(done) {
+  it('returns null when doing an upsert & new=false gh-1533', function (done) {
     var db = start();
 
     var thingSchema = new Schema({
       _id: String,
       flag: {
         type: Boolean,
-        "default": false
+        'default': false
       }
     });
 
     var Thing = db.model('Thing', thingSchema);
     var key = 'some-id';
 
-    Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, "new": false}).exec(function(err, thing) {
+    Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, 'new': false}).exec(function (err, thing) {
       assert.ifError(err);
       assert.equal(null, thing);
-      Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, "new": false}).exec(function(err, thing2) {
+      Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, 'new': false}).exec(function (err, thing2) {
         assert.ifError(err);
         assert.equal(key, thing2.id);
         assert.equal(false, thing2.flag);
@@ -843,34 +864,42 @@ describe('model: findByIdAndUpdate:', function() {
     });
   });
 
-  it('allows properties to be set to null gh-1643', function(done) {
+  it('allows properties to be set to null gh-1643', function (done) {
     var db = start();
 
     var thingSchema = new Schema({
-      name:[String]
+      name: [String]
     });
 
     var Thing = db.model('Thing', thingSchema);
 
-    Thing.create({name:["Test"]}, function(err, thing) {
-      if (err) return done(err);
-      Thing.findOneAndUpdate({ _id: thing._id }, {name:null}, { 'new': true })
-        .exec(function(err, doc) {
-          if (err) return done(err);
-          assert.ok(doc);
-          assert.equal(doc.name, null);
-          db.close(done);
-        });
+    Thing.create({name: ['Test']}, function (err, thing) {
+      if (err) {
+        return done(err);
+      }
+      Thing.findOneAndUpdate({_id: thing._id}, {name: null}, {'new': true})
+      .exec(function (err, doc) {
+        if (err) {
+          return done(err);
+        }
+        assert.ok(doc);
+        assert.equal(doc.name, null);
+        db.close(done);
+      });
     });
   });
 
-  it('honors the overwrite option (gh-1809)', function(done) {
+  it('honors the overwrite option (gh-1809)', function (done) {
     var db = start();
-    var M = db.model('1809', { name: String, change: Boolean });
-    M.create({ name: 'first' }, function(err, doc) {
-      if (err) return done(err);
-      M.findByIdAndUpdate(doc._id, { change: true }, { overwrite: true, 'new': true }, function(err, doc) {
-        if (err) return done(err);
+    var M = db.model('1809', {name: String, change: Boolean});
+    M.create({name: 'first'}, function (err, doc) {
+      if (err) {
+        return done(err);
+      }
+      M.findByIdAndUpdate(doc._id, {change: true}, {overwrite: true, 'new': true}, function (err, doc) {
+        if (err) {
+          return done(err);
+        }
         assert.ok(doc.change);
         assert.equal(undefined, doc.name);
         db.close(done);
@@ -878,47 +907,47 @@ describe('model: findByIdAndUpdate:', function() {
     });
   });
 
-  it('can do deep equals on object id after findOneAndUpdate (gh-2070)', function(done) {
+  it('can do deep equals on object id after findOneAndUpdate (gh-2070)', function (done) {
     var db = start();
 
     var accountSchema = Schema({
       name: String,
       contacts: [{
-        account: { type: Schema.Types.ObjectId, ref: 'Account'},
+        account: {type: Schema.Types.ObjectId, ref: 'Account'},
         name: String
       }]
     });
 
     var Account = db.model('2070', accountSchema);
 
-    var a1 = new Account({ name: 'parent' });
-    var a2 = new Account({ name: 'child' });
+    var a1 = new Account({name: 'parent'});
+    var a2 = new Account({name: 'child'});
 
-    a1.save(function(error) {
+    a1.save(function (error) {
       assert.ifError(error);
-      a2.save(function(error, a2) {
+      a2.save(function (error, a2) {
         assert.ifError(error);
         Account.findOneAndUpdate(
-          { name: 'parent' },
-          { $push: { contacts: { account: a2._id, name: 'child' } } },
-          { 'new': true },
-          function(error, doc) {
-            assert.ifError(error);
-            assert.ok(Utils.deepEqual(doc.contacts[0].account, a2._id));
-            assert.ok(_.isEqual(doc.contacts[0].account, a2._id));
-
-            Account.findOne({ name : 'parent' }, function(error, doc) {
+            {name: 'parent'},
+            {$push: {contacts: {account: a2._id, name: 'child'}}},
+            {'new': true},
+            function (error, doc) {
               assert.ifError(error);
               assert.ok(Utils.deepEqual(doc.contacts[0].account, a2._id));
               assert.ok(_.isEqual(doc.contacts[0].account, a2._id));
-              db.close(done);
+
+              Account.findOne({name: 'parent'}, function (error, doc) {
+                assert.ifError(error);
+                assert.ok(Utils.deepEqual(doc.contacts[0].account, a2._id));
+                assert.ok(_.isEqual(doc.contacts[0].account, a2._id));
+                db.close(done);
+              });
             });
-          });
       });
     });
   });
 
-  it('adds __v on upsert (gh-2122)', function(done) {
+  it('adds __v on upsert (gh-2122)', function (done) {
     var db = start();
 
     var accountSchema = Schema({
@@ -928,51 +957,40 @@ describe('model: findByIdAndUpdate:', function() {
     var Account = db.model('2122', accountSchema);
 
     Account.findOneAndUpdate(
-      { name: 'account' },
-      { },
-      { upsert: true, new: true },
-      function(error, doc) {
-        assert.ifError(error);
-        assert.equal(0, doc.__v);
-        db.close(done);
-      });
+        {name: 'account'},
+        {},
+        {upsert: true, new: true},
+        function (error, doc) {
+          assert.ifError(error);
+          assert.equal(0, doc.__v);
+          db.close(done);
+        });
   });
 
-  it('works with nested schemas and $pull+$or (gh-1932)', function(done) {
+  it('works with nested schemas and $pull+$or (gh-1932)', function (done) {
     var db = start();
 
-    var TickSchema = Schema({ name: String });
-    var TestSchema = Schema({ a: Number, b: Number, ticks: [TickSchema] });
+    var TickSchema = Schema({name: String});
+    var TestSchema = Schema({a: Number, b: Number, ticks: [TickSchema]});
 
     var TestModel = db.model('gh-1932', TestSchema, 'gh-1932');
 
-    TestModel.create({ a: 1, b: 0, ticks: [{ name: 'eggs' }, { name: 'bacon' }, { name: 'coffee' }] }, function(error) {
+    TestModel.create({a: 1, b: 0, ticks: [{name: 'eggs'}, {name: 'bacon'}, {name: 'coffee'}]}, function (error) {
       assert.ifError(error);
-      TestModel.findOneAndUpdate(
-        { a: 1 },
-        {
-          $pull: {
-            ticks: {
-              $or: [
-                { name: 'eggs' },
-                { name: 'bacon' }
-              ]
-            }
-          }
-        },
-        function(error) {
-          assert.ifError(error);
-          TestModel.findOne({}, function(error, doc) {
+      TestModel.findOneAndUpdate({a: 1}, {$pull: {ticks: {$or: [{name: 'eggs'}, {name: 'bacon'}]}}},
+          function (error) {
             assert.ifError(error);
-            assert.equal(1, doc.ticks.length);
-            assert.equal('coffee', doc.ticks[0].name);
-            db.close(done);
+            TestModel.findOne({}, function (error, doc) {
+              assert.ifError(error);
+              assert.equal(1, doc.ticks.length);
+              assert.equal('coffee', doc.ticks[0].name);
+              db.close(done);
+            });
           });
-        });
     });
   });
 
-  it('accepts undefined', function(done) {
+  it('accepts undefined', function (done) {
     var db = start();
 
     var s = new Schema({
@@ -983,14 +1001,14 @@ describe('model: findByIdAndUpdate:', function() {
     var Breakfast = db.model('gh-2272', s);
 
     Breakfast.
-      findOneAndUpdate({}, { time: undefined, base: undefined }, {}).
-      exec(function(error) {
-        assert.ifError(error);
-        db.close(done);
-      });
+    findOneAndUpdate({}, {time: undefined, base: undefined}, {}).
+    exec(function (error) {
+      assert.ifError(error);
+      db.close(done);
+    });
   });
 
-  it('cast errors for empty objects as object ids (gh-2732)', function(done) {
+  it('cast errors for empty objects as object ids (gh-2732)', function (done) {
     var db = start();
 
     var s = new Schema({
@@ -1000,184 +1018,192 @@ describe('model: findByIdAndUpdate:', function() {
     var Breakfast = db.model('gh2732', s);
 
     Breakfast.
-      findOneAndUpdate({}, { base: {} }, {}).
-      exec(function(error) {
-        assert.ok(error);
-        db.close(done);
-      });
+    findOneAndUpdate({}, {base: {}}, {}).
+    exec(function (error) {
+      assert.ok(error);
+      db.close(done);
+    });
   });
 
-  it('strict mode with objects (gh-2947)', function(done) {
+  it('strict mode with objects (gh-2947)', function (done) {
     var db = start();
 
     var s = new Schema({
       test: String
-    }, { strict: true });
+    }, {strict: true});
 
     var Breakfast = db.model('gh2947', s);
     var q = Breakfast.findOneAndUpdate({},
-      { notInSchema: { a: 1 }, test: 'abc' },
-      { 'new': true, strict: true, upsert: true });
+        {notInSchema: {a: 1}, test: 'abc'},
+        {'new': true, strict: true, upsert: true});
 
     q.lean();
-    q.exec(function(error, doc) {
+    q.exec(function (error, doc) {
       assert.ok(!doc.notInSchema);
       db.close(done);
     });
   });
 
-  describe('middleware', function() {
+  describe('middleware', function () {
     var db;
 
-    beforeEach(function() {
+    beforeEach(function () {
       db = start();
     });
 
-    afterEach(function(done) {
+    afterEach(function (done) {
       db.close(done);
     });
 
-    it('works', function(done) {
+    it('works', function (done) {
       var s = new Schema({
-        topping: { type: String, default: 'bacon' },
+        topping: {type: String, default: 'bacon'},
         base: String
       });
 
       var preCount = 0;
-      s.pre('findOneAndUpdate', function() {
+      s.pre('findOneAndUpdate', function () {
         ++preCount;
       });
 
       var postCount = 0;
-      s.post('findOneAndUpdate', function() {
+      s.post('findOneAndUpdate', function () {
         ++postCount;
       });
 
       var Breakfast = db.model('gh-964', s);
 
       Breakfast.findOneAndUpdate(
-        {},
-        { base: 'eggs' },
-        {},
-        function(error) {
-          assert.ifError(error);
-          assert.equal(1, preCount);
-          assert.equal(1, postCount);
-          done();
-        });
+          {},
+          {base: 'eggs'},
+          {},
+          function (error) {
+            assert.ifError(error);
+            assert.equal(1, preCount);
+            assert.equal(1, postCount);
+            done();
+          });
     });
 
-    it('works with exec()', function(done) {
+    it('works with exec()', function (done) {
       var s = new Schema({
-        topping: { type: String, default: 'bacon' },
+        topping: {type: String, default: 'bacon'},
         base: String
       });
 
       var preCount = 0;
-      s.pre('findOneAndUpdate', function() {
+      s.pre('findOneAndUpdate', function () {
         ++preCount;
       });
 
       var postCount = 0;
-      s.post('findOneAndUpdate', function() {
+      s.post('findOneAndUpdate', function () {
         ++postCount;
       });
 
       var Breakfast = db.model('gh-964-2', s);
 
       Breakfast.
-        findOneAndUpdate({}, { base: 'eggs' }, {}).
-        exec(function(error) {
-          assert.ifError(error);
-          assert.equal(1, preCount);
-          assert.equal(1, postCount);
-          done();
-        });
+      findOneAndUpdate({}, {base: 'eggs'}, {}).
+      exec(function (error) {
+        assert.ifError(error);
+        assert.equal(1, preCount);
+        assert.equal(1, postCount);
+        done();
+      });
     });
   });
 
-  describe('validators (gh-860)', function() {
-    it('applies defaults on upsert', function(done) {
+  describe('validators (gh-860)', function () {
+    it('applies defaults on upsert', function (done) {
       var db = start();
 
       var s = new Schema({
-        topping: { type: String, default: 'bacon' },
+        topping: {type: String, default: 'bacon'},
         base: String
       });
       var Breakfast = db.model('fam-gh-860-0', s);
 
-      var updateOptions = { upsert: true, setDefaultsOnInsert: true, 'new': true };
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true, 'new': true};
       Breakfast.findOneAndUpdate(
-        {},
-        { base: 'eggs' },
-        updateOptions,
-        function(error, breakfast) {
-          assert.ifError(error);
-          assert.equal('eggs', breakfast.base);
-          assert.equal('bacon', breakfast.topping);
-          Breakfast.count({ topping: 'bacon' }, function(error, count) {
+          {},
+          {base: 'eggs'},
+          updateOptions,
+          function (error, breakfast) {
             assert.ifError(error);
-            assert.equal(count, 1);
-            db.close(done);
+            assert.equal('eggs', breakfast.base);
+            assert.equal('bacon', breakfast.topping);
+            Breakfast.count({topping: 'bacon'}, function (error, count) {
+              assert.ifError(error);
+              assert.equal(count, 1);
+              db.close(done);
+            });
           });
-        });
     });
 
-    it('doesnt set default on upsert if query sets it', function(done) {
+    it('doesnt set default on upsert if query sets it', function (done) {
       var db = start();
 
       var s = new Schema({
-        topping: { type: String, default: 'bacon' },
+        topping: {type: String, default: 'bacon'},
         base: String
       });
       var Breakfast = db.model('fam-gh-860-1', s);
 
-      var updateOptions = { upsert: true, setDefaultsOnInsert: true, 'new': true };
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true, 'new': true};
       Breakfast.findOneAndUpdate(
-        { topping: 'sausage' },
-        { base: 'eggs' },
-        updateOptions,
-        function(error, breakfast) {
-          assert.ifError(error);
-          assert.equal('eggs', breakfast.base);
-          assert.equal('sausage', breakfast.topping);
-          db.close();
-          done();
-        });
+          {topping: 'sausage'},
+          {base: 'eggs'},
+          updateOptions,
+          function (error, breakfast) {
+            assert.ifError(error);
+            assert.equal('eggs', breakfast.base);
+            assert.equal('sausage', breakfast.topping);
+            db.close();
+            done();
+          });
     });
 
-    it('properly sets default on upsert if query wont set it', function(done) {
+    it('properly sets default on upsert if query wont set it', function (done) {
       var db = start();
 
       var s = new Schema({
-        topping: { type: String, default: 'bacon' },
+        topping: {type: String, default: 'bacon'},
         base: String
       });
       var Breakfast = db.model('fam-gh-860-2', s);
 
-      var updateOptions = { upsert: true, setDefaultsOnInsert: true, 'new': true };
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true, 'new': true};
       Breakfast.findOneAndUpdate(
-        { topping: { $ne: 'sausage' } },
-        { base: 'eggs' },
-        updateOptions,
-        function(error, breakfast) {
-          assert.ifError(error);
-          assert.equal('eggs', breakfast.base);
-          assert.equal('bacon', breakfast.topping);
-          Breakfast.count({ topping: 'bacon' }, function(error, count) {
+          {topping: {$ne: 'sausage'}},
+          {base: 'eggs'},
+          updateOptions,
+          function (error, breakfast) {
             assert.ifError(error);
-            assert.equal(count, 1);
-            db.close(done);
+            assert.equal('eggs', breakfast.base);
+            assert.equal('bacon', breakfast.topping);
+            Breakfast.count({topping: 'bacon'}, function (error, count) {
+              assert.ifError(error);
+              assert.equal(count, 1);
+              db.close(done);
+            });
           });
-        });
     });
 
-    it('runs validators if theyre set', function(done) {
+    it('runs validators if theyre set', function (done) {
       var db = start();
 
       var s = new Schema({
-        topping: { type: String, validate: function() { return false; } },
-        base: { type: String, validate: function() { return true; } }
+        topping: {
+          type: String, validate: function () {
+            return false;
+          }
+        },
+        base: {
+          type: String, validate: function () {
+            return true;
+          }
+        }
       });
       var Breakfast = db.model('fam-gh-860-3', s);
 
@@ -1188,153 +1214,157 @@ describe('model: findByIdAndUpdate:', function() {
         'new': true
       };
       Breakfast.findOneAndUpdate(
-        {},
-        { topping: 'bacon', base: 'eggs' },
-        updateOptions,
-        function(error, breakfast) {
-          assert.ok(!!error);
-          assert.ok(!breakfast);
-          assert.equal(1, Object.keys(error.errors).length);
-          assert.equal('topping', Object.keys(error.errors)[0]);
-          assert.equal('Validator failed for path `topping` with value `bacon`',
-            error.errors['topping'].message);
-
-          assert.ok(!breakfast);
-          db.close();
-          done();
-        });
+          {},
+          {topping: 'bacon', base: 'eggs'},
+          updateOptions,
+          function (error, breakfast) {
+            assert.ok(!!error);
+            assert.ok(!breakfast);
+            assert.equal(1, Object.keys(error.errors).length);
+            assert.equal('topping', Object.keys(error.errors)[0]);
+            assert.equal('Validator failed for path `topping` with value `bacon`',
+                error.errors['topping'].message);
+
+            assert.ok(!breakfast);
+            db.close();
+            done();
+          });
     });
 
-    it('validators handle $unset and $setOnInsert', function(done) {
+    it('validators handle $unset and $setOnInsert', function (done) {
       var db = start();
 
       var s = new Schema({
-        steak: { type: String, required: true },
-        eggs: { type: String, validate: function() { return false; } }
+        steak: {type: String, required: true},
+        eggs: {
+          type: String, validate: function () {
+            return false;
+          }
+        }
       });
       var Breakfast = db.model('fam-gh-860-4', s);
 
-      var updateOptions = { runValidators: true, 'new': true };
+      var updateOptions = {runValidators: true, 'new': true};
       Breakfast.findOneAndUpdate(
-        {},
-        { $unset: { steak: '' }, $setOnInsert: { eggs: 'softboiled' } },
-        updateOptions,
-        function(error, breakfast) {
-          assert.ok(!!error);
-          assert.ok(!breakfast);
-          assert.equal(2, Object.keys(error.errors).length);
-          assert.ok(Object.keys(error.errors).indexOf('eggs') != -1);
-          assert.ok(Object.keys(error.errors).indexOf('steak') != -1);
-          assert.equal('Validator failed for path `eggs` with value `softboiled`',
-            error.errors['eggs'].message);
-          assert.equal('Path `steak` is required.',
-            error.errors['steak'].message);
-          db.close();
-          done();
-        });
+          {},
+          {$unset: {steak: ''}, $setOnInsert: {eggs: 'softboiled'}},
+          updateOptions,
+          function (error, breakfast) {
+            assert.ok(!!error);
+            assert.ok(!breakfast);
+            assert.equal(2, Object.keys(error.errors).length);
+            assert.ok(Object.keys(error.errors).indexOf('eggs') != -1);
+            assert.ok(Object.keys(error.errors).indexOf('steak') != -1);
+            assert.equal('Validator failed for path `eggs` with value `softboiled`',
+                error.errors['eggs'].message);
+            assert.equal('Path `steak` is required.',
+                error.errors['steak'].message);
+            db.close();
+            done();
+          });
     });
 
-    it('min/max, enum, and regex built-in validators work', function(done) {
+    it('min/max, enum, and regex built-in validators work', function (done) {
       var db = start();
 
       var s = new Schema({
-        steak: { type: String, enum: ['ribeye', 'sirloin'] },
-        eggs: { type: Number, min: 4, max: 6 },
-        bacon: { type: String, match: /strips/ }
+        steak: {type: String, enum: ['ribeye', 'sirloin']},
+        eggs: {type: Number, min: 4, max: 6},
+        bacon: {type: String, match: /strips/}
       });
       var Breakfast = db.model('fam-gh-860-5', s);
 
-      var updateOptions = { runValidators: true, 'new': true };
+      var updateOptions = {runValidators: true, 'new': true};
       Breakfast.findOneAndUpdate(
-        {},
-        { $set: { steak: 'ribeye', eggs: 3, bacon: '3 strips' } },
-        updateOptions,
-        function(error) {
-          assert.ok(!!error);
-          assert.equal(1, Object.keys(error.errors).length);
-          assert.equal('eggs', Object.keys(error.errors)[0]);
-          assert.equal('Path `eggs` (3) is less than minimum allowed value (4).',
-            error.errors['eggs'].message);
-
-          Breakfast.findOneAndUpdate(
-            {},
-            { $set: { steak: 'tofu', eggs: 5, bacon: '3 strips' } },
-            updateOptions,
-            function(error) {
-              assert.ok(!!error);
-              assert.equal(1, Object.keys(error.errors).length);
-              assert.equal('steak', Object.keys(error.errors)[0]);
-              assert.equal('`tofu` is not a valid enum value for path `steak`.',
-                error.errors['steak']);
-
-
-              Breakfast.findOneAndUpdate(
+          {},
+          {$set: {steak: 'ribeye', eggs: 3, bacon: '3 strips'}},
+          updateOptions,
+          function (error) {
+            assert.ok(!!error);
+            assert.equal(1, Object.keys(error.errors).length);
+            assert.equal('eggs', Object.keys(error.errors)[0]);
+            assert.equal('Path `eggs` (3) is less than minimum allowed value (4).',
+                error.errors['eggs'].message);
+
+            Breakfast.findOneAndUpdate(
                 {},
-                { $set: { steak: 'sirloin', eggs: 6, bacon: 'none' } },
+                {$set: {steak: 'tofu', eggs: 5, bacon: '3 strips'}},
                 updateOptions,
-                function(error) {
+                function (error) {
                   assert.ok(!!error);
                   assert.equal(1, Object.keys(error.errors).length);
-                  assert.equal('bacon', Object.keys(error.errors)[0]);
-                  assert.equal('Path `bacon` is invalid (none).',
-                    error.errors['bacon'].message);
-
-                  db.close();
-                  done();
+                  assert.equal('steak', Object.keys(error.errors)[0]);
+                  assert.equal('`tofu` is not a valid enum value for path `steak`.',
+                      error.errors['steak']);
+
+
+                  Breakfast.findOneAndUpdate(
+                      {},
+                      {$set: {steak: 'sirloin', eggs: 6, bacon: 'none'}},
+                      updateOptions,
+                      function (error) {
+                        assert.ok(!!error);
+                        assert.equal(1, Object.keys(error.errors).length);
+                        assert.equal('bacon', Object.keys(error.errors)[0]);
+                        assert.equal('Path `bacon` is invalid (none).',
+                            error.errors['bacon'].message);
+
+                        db.close();
+                        done();
+                      });
                 });
-            });
-        });
+          });
     });
 
-    it('multiple validation errors', function(done) {
+    it('multiple validation errors', function (done) {
       var db = start();
 
       var s = new Schema({
-        steak: { type: String, enum: ['ribeye', 'sirloin'] },
-        eggs: { type: Number, min: 4, max: 6 },
-        bacon: { type: String, match: /strips/ }
+        steak: {type: String, enum: ['ribeye', 'sirloin']},
+        eggs: {type: Number, min: 4, max: 6},
+        bacon: {type: String, match: /strips/}
       });
       var Breakfast = db.model('fam-gh-860-6', s);
 
-      var updateOptions = { runValidators: true, 'new': true };
+      var updateOptions = {runValidators: true, 'new': true};
       Breakfast.findOneAndUpdate(
-        {},
-        { $set: { steak: 'tofu', eggs: 2, bacon: '3 strips' } },
-        updateOptions,
-        function(error, breakfast) {
-          assert.ok(!!error);
-          assert.equal(2, Object.keys(error.errors).length);
-          assert.ok(Object.keys(error.errors).indexOf('steak') !== -1);
-          assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1);
-          assert.ok(!breakfast);
-          db.close();
-          done();
-        });
+          {},
+          {$set: {steak: 'tofu', eggs: 2, bacon: '3 strips'}},
+          updateOptions,
+          function (error, breakfast) {
+            assert.ok(!!error);
+            assert.equal(2, Object.keys(error.errors).length);
+            assert.ok(Object.keys(error.errors).indexOf('steak') !== -1);
+            assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1);
+            assert.ok(!breakfast);
+            db.close();
+            done();
+          });
     });
 
-    it('validators ignore $inc', function(done) {
+    it('validators ignore $inc', function (done) {
       var db = start();
 
       var s = new Schema({
-        steak: { type: String, required: true },
-        eggs: { type: Number, min: 4 }
+        steak: {type: String, required: true},
+        eggs: {type: Number, min: 4}
       });
       var Breakfast = db.model('fam-gh-860-7', s);
 
-      var updateOptions = { runValidators: true, upsert: true, 'new': true };
+      var updateOptions = {runValidators: true, upsert: true, 'new': true};
       Breakfast.findOneAndUpdate(
-        {},
-        { $inc: { eggs: 1 } },
-        updateOptions,
-        function(error, breakfast) {
-          assert.ifError(error);
-          assert.ok(!!breakfast);
-          assert.equal(1, breakfast.eggs);
-          db.close(done);
-        });
+          {},
+          {$inc: {eggs: 1}},
+          updateOptions,
+          function (error, breakfast) {
+            assert.ifError(error);
+            assert.ok(!!breakfast);
+            assert.equal(1, breakfast.eggs);
+            db.close(done);
+          });
     });
 
-    it('should work with arrays (gh-3035)', function(done) {
+    it('should work with arrays (gh-3035)', function (done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
@@ -1348,49 +1378,37 @@ describe('model: findByIdAndUpdate:', function() {
       });
 
       var TestModel = db.model('gh3035', testSchema);
-      TestModel.create({ id: '1' }, function(error) {
+      TestModel.create({id: '1'}, function (error) {
         assert.ifError(error);
-        TestModel.findOneAndUpdate(
-          { id: '1' },
-          { $set: { name: 'Joe' } },
-          {
-            upsert: true,
-            setDefaultsOnInsert: true
-          },
-          function(error) {
-            assert.ifError(error);
-            db.close(done);
-          });
+        TestModel.findOneAndUpdate({id: '1'}, {$set: {name: 'Joe'}}, {upsert: true, setDefaultsOnInsert: true},
+            function (error) {
+              assert.ifError(error);
+              db.close(done);
+            });
       });
     });
 
-    it('should allow null values in query (gh-3135)', function(done) {
+    it('should allow null values in query (gh-3135)', function (done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
-        id:      String,
-        blob:    ObjectId,
-        status:  String
+        id: String,
+        blob: ObjectId,
+        status: String
       });
 
       var TestModel = db.model('gh3135', testSchema);
-      TestModel.create({ blob: null, status: 'active' }, function(error) {
+      TestModel.create({blob: null, status: 'active'}, function (error) {
         assert.ifError(error);
-        TestModel.findOneAndUpdate(
-            { id: '1', blob: null },
-            { $set: { status: 'inactive' }},
-          {
-            upsert: true,
-            setDefaultsOnInsert: true
-          },
-            function(error) {
+        TestModel.findOneAndUpdate({id: '1', blob: null}, {$set: {status: 'inactive'}}, {upsert: true, setDefaultsOnInsert: true},
+            function (error) {
               assert.ifError(error);
               db.close(done);
             });
       });
     });
 
-    it('should work with array documents (gh-3034)', function(done) {
+    it('should work with array documents (gh-3034)', function (done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
@@ -1406,23 +1424,17 @@ describe('model: findByIdAndUpdate:', function() {
       });
 
       var TestModel = db.model('gh3034', testSchema);
-      TestModel.create({ id: '1' }, function(error) {
+      TestModel.create({id: '1'}, function (error) {
         assert.ifError(error);
-        TestModel.findOneAndUpdate(
-          { id: '1' },
-          { $set: { name: 'Joe' } },
-          {
-            upsert: true,
-            setDefaultsOnInsert: true
-          },
-          function(error) {
-            assert.ifError(error);
-            db.close(done);
-          });
+        TestModel.findOneAndUpdate({id: '1'}, {$set: {name: 'Joe'}}, {upsert: true, setDefaultsOnInsert: true},
+            function (error) {
+              assert.ifError(error);
+              db.close(done);
+            });
       });
     });
 
-    it('handles setting array (gh-3107)', function(done) {
+    it('handles setting array (gh-3107)', function (done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
@@ -1434,25 +1446,19 @@ describe('model: findByIdAndUpdate:', function() {
       });
 
       var TestModel = db.model('gh3107', testSchema);
-      TestModel.findOneAndUpdate(
-        { id: '1' },
-        { $setOnInsert: { a: [{ foo: 'bar' }], b: [2] } },
-        {
-          upsert: true,
-          'new': true,
-          setDefaultsOnInsert: true
-        },
-        function(error, doc) {
-          assert.ifError(error);
-          assert.equal(doc.a.length, 1);
-          assert.equal(doc.a[0].foo, 'bar');
-          assert.equal(doc.b.length, 1);
-          assert.equal(doc.b[0], 2);
-          db.close(done);
-        });
+      TestModel
+      .findOneAndUpdate({id: '1'}, {$setOnInsert: {a: [{foo: 'bar'}], b: [2]}}, {upsert: true, 'new': true, setDefaultsOnInsert: true},
+          function (error, doc) {
+            assert.ifError(error);
+            assert.equal(doc.a.length, 1);
+            assert.equal(doc.a[0].foo, 'bar');
+            assert.equal(doc.b.length, 1);
+            assert.equal(doc.b[0], 2);
+            db.close(done);
+          });
     });
 
-    it('passes raw result as 3rd param (gh-3173)', function(done) {
+    it('passes raw result as 3rd param (gh-3173)', function (done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
@@ -1461,23 +1467,16 @@ describe('model: findByIdAndUpdate:', function() {
 
       var TestModel = db.model('gh3173', testSchema);
 
-      TestModel.findOneAndUpdate(
-        {},
-        { $set: { test: 'abc' } },
-        {
-          upsert: true,
-          'new': true,
-          passRawResult: true
-        }).
-        exec(function(error, doc, res) {
-          assert.ifError(error);
-          assert.ok(res);
-          assert.ok(res.ok);
-          db.close(done);
-        });
+      TestModel.findOneAndUpdate({}, {$set: {test: 'abc'}}, {upsert: true, 'new': true, passRawResult: true}).
+      exec(function (error, doc, res) {
+        assert.ifError(error);
+        assert.ok(res);
+        assert.ok(res.ok);
+        db.close(done);
+      });
     });
 
-    it('handles nested cast errors (gh-3468)', function(done) {
+    it('handles nested cast errors (gh-3468)', function (done) {
       var db = start();
       var recordSchema = new mongoose.Schema({
         kind: String,
@@ -1496,13 +1495,13 @@ describe('model: findByIdAndUpdate:', function() {
       Shift.create({
         userId: 'tom',
         records: []
-      }, function(error) {
+      }, function (error) {
         assert.ifError(error);
         Shift.findOneAndUpdate({userId: 'tom'}, {
           records: [{kind: 'kind1', amount: NaN}]
         }, {
           'new': true
-        }, function(error) {
+        }, function (error) {
           assert.ok(error);
           assert.ok(error instanceof CastError);
           db.close(done);
@@ -1510,34 +1509,34 @@ describe('model: findByIdAndUpdate:', function() {
       });
     });
 
-    it('cast errors with nested schemas (gh-3580)', function(done) {
+    it('cast errors with nested schemas (gh-3580)', function (done) {
       var db = start();
 
-      var nested = new Schema({ num: Number });
-      var s = new Schema({ nested: nested });
+      var nested = new Schema({num: Number});
+      var s = new Schema({nested: nested});
 
       var MyModel = db.model('gh3580', s);
 
-      var update = { nested: { num: 'Not a Number' } };
-      MyModel.findOneAndUpdate({}, update, function(error) {
+      var update = {nested: {num: 'Not a Number'}};
+      MyModel.findOneAndUpdate({}, update, function (error) {
         assert.ok(error);
         db.close(done);
       });
     });
 
-    it('pull with nested schemas (gh-3616)', function(done) {
+    it('pull with nested schemas (gh-3616)', function (done) {
       var db = start();
 
-      var nested = new Schema({ arr: [{ num: Number }] });
-      var s = new Schema({ nested: nested });
+      var nested = new Schema({arr: [{num: Number}]});
+      var s = new Schema({nested: nested});
 
       var MyModel = db.model('gh3616', s);
 
-      MyModel.create({ nested: { arr: [{ num: 5 }] } }, function(error) {
+      MyModel.create({nested: {arr: [{num: 5}]}}, function (error) {
         assert.ifError(error);
-        var update = { $pull: { 'nested.arr': { num: 5 } } };
-        var options = { 'new': true };
-        MyModel.findOneAndUpdate({}, update, options, function(error, doc) {
+        var update = {$pull: {'nested.arr': {num: 5}}};
+        var options = {'new': true};
+        MyModel.findOneAndUpdate({}, update, options, function (error, doc) {
           assert.ifError(error);
           assert.equal(doc.nested.arr.length, 0);
           db.close(done);
diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js
index ad4659b9b75..d13c5444ecd 100644
--- a/test/model.geonear.test.js
+++ b/test/model.geonear.test.js
@@ -10,7 +10,7 @@ var start = require('./common'),
  */
 
 var schema = new Schema({
-  coordinates: { type: [Number], index: '2dsphere' },
+  coordinates: {type: [Number], index: '2dsphere'},
   type: String
 });
 
@@ -31,48 +31,47 @@ function metersToRadians(m) {
   return m / (6371 * 1000);
 }
 
-describe('model', function() {
+describe('model', function () {
   var mongo24_or_greater = false;
-  before(function(done) {
-    start.mongodVersion(function(err, version) {
+  before(function (done) {
+    start.mongodVersion(function (err, version) {
       if (err) throw err;
       mongo24_or_greater = 2 < version[0] || (2 == version[0] && 4 <= version[1]);
       if (!mongo24_or_greater) console.log('not testing mongodb 2.4 features');
       done();
     });
   });
-  describe('geoNear', function() {
-
-    it('works with legacy coordinate points', function(done) {
+  describe('geoNear', function () {
+    it('works with legacy coordinate points', function (done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoNear instanceof Function);
 
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
 
         var geos = [];
         geos[0] = new Geo({
           coordinates: testLocations.MONGODB_NYC_OFFICE,
-          type: "Point"
+          type: 'Point'
         });
         geos[1] = new Geo({
           coordinates: testLocations.BRYANT_PARK_NY,
-          type: "Point"
+          type: 'Point'
         });
         geos[2] = new Geo({
           coordinates: testLocations.EAST_HARLEM_SHOP,
-          type: "Point"
+          type: 'Point'
         });
         geos[3] = new Geo({
           coordinates: testLocations.CENTRAL_PARK_ZOO,
-          type: "Point"
+          type: 'Point'
         });
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function(err) {
+          geos[i].save(function (err) {
             assert.ifError(err);
             --count || next();
           });
@@ -80,8 +79,8 @@ describe('model', function() {
 
         function next() {
           // using legacy coordinates -- maxDistance units in radians
-          var options = { spherical: true, maxDistance: metersToRadians(300) };
-          Geo.geoNear(testLocations.PORT_AUTHORITY_STATION, options).then(function(results) {
+          var options = {spherical: true, maxDistance: metersToRadians(300)};
+          Geo.geoNear(testLocations.PORT_AUTHORITY_STATION, options).then(function (results) {
             assert.equal(1, results.length);
 
             assert.equal(results[0].obj.type, 'Point');
@@ -96,43 +95,43 @@ describe('model', function() {
       });
     });
 
-    it('works with GeoJSON coordinate points', function(done) {
+    it('works with GeoJSON coordinate points', function (done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoNear instanceof Function);
 
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
 
         var geos = [];
         geos[0] = new Geo({
           coordinates: testLocations.MONGODB_NYC_OFFICE,
-          type: "Point"
+          type: 'Point'
         });
         geos[1] = new Geo({
           coordinates: testLocations.BRANT_PARK_NY,
-          type: "Point"
+          type: 'Point'
         });
         geos[2] = new Geo({
           coordinates: testLocations.EAST_HARLEM_SHOP,
-          type: "Point"
+          type: 'Point'
         });
         geos[3] = new Geo({
           coordinates: testLocations.CENTRAL_PARK_ZOO,
-          type: "Point"
+          type: 'Point'
         });
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function() {
+          geos[i].save(function () {
             --count || next();
           });
         }
 
         function next() {
-          var pnt = { type: "Point", coordinates: testLocations.PORT_AUTHORITY_STATION };
-          Geo.geoNear(pnt, { spherical: true, maxDistance: 300 }, function(err, results) {
+          var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION};
+          Geo.geoNear(pnt, {spherical: true, maxDistance: 300}, function (err, results) {
             assert.ifError(err);
 
             assert.equal(1, results.length);
@@ -149,43 +148,43 @@ describe('model', function() {
       });
     });
 
-    it('works with lean', function(done) {
+    it('works with lean', function (done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoNear instanceof Function);
 
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
 
         var geos = [];
         geos[0] = new Geo({
           coordinates: testLocations.MONGODB_NYC_OFFICE,
-          type: "Point"
+          type: 'Point'
         });
         geos[1] = new Geo({
           coordinates: testLocations.BRANT_PARK_NY,
-          type: "Point"
+          type: 'Point'
         });
         geos[2] = new Geo({
           coordinates: testLocations.EAST_HARLEM_SHOP,
-          type: "Point"
+          type: 'Point'
         });
         geos[3] = new Geo({
           coordinates: testLocations.CENTRAL_PARK_ZOO,
-          type: "Point"
+          type: 'Point'
         });
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function() {
+          geos[i].save(function () {
             --count || next();
           });
         }
 
         function next() {
-          var pnt = { type: "Point", coordinates: testLocations.PORT_AUTHORITY_STATION };
-          Geo.geoNear(pnt, { spherical: true, maxDistance: 300, lean: true }, function(err, results) {
+          var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION};
+          Geo.geoNear(pnt, {spherical: true, maxDistance: 300, lean: true}, function (err, results) {
             assert.ifError(err);
 
             assert.equal(1, results.length);
@@ -202,32 +201,32 @@ describe('model', function() {
       });
     });
 
-    it('throws the correct error messages', function(done) {
+    it('throws the correct error messages', function (done) {
       if (!mongo24_or_greater) return done();
 
       var db = start();
       var Geo = getModel(db);
 
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
 
-        var g = new Geo({ coordinates: [10,10], type: "place"});
-        g.save(function() {
-          Geo.geoNear("1,2", {}, function(e) {
+        var g = new Geo({coordinates: [10, 10], type: 'place'});
+        g.save(function () {
+          Geo.geoNear('1,2', {}, function (e) {
             assert.ok(e);
-            assert.equal(e.message, "Must pass either a legacy coordinate array or GeoJSON Point to geoNear");
+            assert.equal(e.message, 'Must pass either a legacy coordinate array or GeoJSON Point to geoNear');
 
-            Geo.geoNear([1], {}, function(e) {
+            Geo.geoNear([1], {}, function (e) {
               assert.ok(e);
-              assert.equal(e.message, "If using legacy coordinates, must be an array of size 2 for geoNear");
+              assert.equal(e.message, 'If using legacy coordinates, must be an array of size 2 for geoNear');
 
-              Geo.geoNear({ type: "Square" }, {}, function(e) {
+              Geo.geoNear({type: 'Square'}, {}, function (e) {
                 assert.ok(e);
-                assert.equal(e.message, "Must pass either a legacy coordinate array or GeoJSON Point to geoNear");
+                assert.equal(e.message, 'Must pass either a legacy coordinate array or GeoJSON Point to geoNear');
 
-                Geo.geoNear({ type: "Point", coordinates: "1,2" }, {}, function(e) {
+                Geo.geoNear({type: 'Point', coordinates: '1,2'}, {}, function (e) {
                   assert.ok(e);
-                  assert.equal(e.message, "Must pass either a legacy coordinate array or GeoJSON Point to geoNear");
+                  assert.equal(e.message, 'Must pass either a legacy coordinate array or GeoJSON Point to geoNear');
 
                   db.close(done);
                 });
@@ -237,33 +236,33 @@ describe('model', function() {
         });
       });
     });
-    it('returns a promise (gh-1614)', function(done) {
+    it('returns a promise (gh-1614)', function (done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
 
-      var pnt = { type: "Point", coordinates: testLocations.PORT_AUTHORITY_STATION };
+      var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION};
       // using GeoJSON point
-      var prom = Geo.geoNear(pnt, { spherical: true, maxDistance: 300 }, function() {});
+      var prom = Geo.geoNear(pnt, {spherical: true, maxDistance: 300}, function () {});
       assert.ok(prom instanceof mongoose.Promise);
       db.close();
       done();
     });
 
-    it('allows not passing a callback (gh-1614)', function(done) {
+    it('allows not passing a callback (gh-1614)', function (done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
-        var g = new Geo({ coordinates: testLocations.MONGODB_NYC_OFFICE, type: "Point"});
-        g.save(function(err) {
+        var g = new Geo({coordinates: testLocations.MONGODB_NYC_OFFICE, type: 'Point'});
+        g.save(function (err) {
           assert.ifError(err);
 
-          var pnt = { type: "Point", coordinates: testLocations.PORT_AUTHORITY_STATION };
+          var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION};
           var promise;
-          assert.doesNotThrow(function() {
-            promise = Geo.geoNear(pnt, { spherical: true, maxDistance: 300 });
+          assert.doesNotThrow(function () {
+            promise = Geo.geoNear(pnt, {spherical: true, maxDistance: 300});
           });
 
           function validate(ret, stat) {
@@ -278,24 +277,23 @@ describe('model', function() {
           }
 
           promise.then(validate, assert.ifError).then(finish).end();
-
         });
       });
     });
-    it('promise fulfill even when no results returned', function(done) {
+    it('promise fulfill even when no results returned', function (done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
-        var g = new Geo({ coordinates: [1,1], type: "Point"});
-        g.save(function(err) {
+        var g = new Geo({coordinates: [1, 1], type: 'Point'});
+        g.save(function (err) {
           assert.ifError(err);
 
-          var pnt = { type: "Point", coordinates: [90, 45] };
+          var pnt = {type: 'Point', coordinates: [90, 45]};
           var promise;
-          assert.doesNotThrow(function() {
-            promise = Geo.geoNear(pnt, { spherical: true, maxDistance: 1000 });
+          assert.doesNotThrow(function () {
+            promise = Geo.geoNear(pnt, {spherical: true, maxDistance: 1000});
           });
 
           function finish() {
@@ -303,7 +301,6 @@ describe('model', function() {
           }
 
           promise.then(finish).end();
-
         });
       });
     });
diff --git a/test/model.geosearch.test.js b/test/model.geosearch.test.js
index 2a017f101ad..002e998e50b 100644
--- a/test/model.geosearch.test.js
+++ b/test/model.geosearch.test.js
@@ -14,39 +14,38 @@ var schema = new Schema({
   complex: {},
   type: String
 });
-schema.index({ "pos": "geoHaystack", type: 1},{ bucketSize: 1});
+schema.index({'pos': 'geoHaystack', type: 1}, {bucketSize: 1});
 
 function getModel(db) {
   return db.model('GeoSearch', schema, 'geosearch-' + random());
 }
 
-describe('model', function() {
-  describe('geoSearch', function() {
-    it('works', function(done) {
-
+describe('model', function () {
+  describe('geoSearch', function () {
+    it('works', function (done) {
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoSearch instanceof Function);
 
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
 
         var geos = [];
-        geos[0] = new Geo({ pos: [10,10], type: "place"});
-        geos[1] = new Geo({ pos: [15,5], type: "place"});
-        geos[2] = new Geo({ pos: [20,15], type: "house"});
-        geos[3] = new Geo({ pos: [1,-1], type: "house"});
+        geos[0] = new Geo({pos: [10, 10], type: 'place'});
+        geos[1] = new Geo({pos: [15, 5], type: 'place'});
+        geos[2] = new Geo({pos: [20, 15], type: 'house'});
+        geos[3] = new Geo({pos: [1, -1], type: 'house'});
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function(err) {
+          geos[i].save(function (err) {
             assert.ifError(err);
             --count || next();
           });
         }
 
         function next() {
-          Geo.geoSearch({ type: "place" }, { near: [9,9], maxDistance: 5 }, function(err, results) {
+          Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5}, function (err, results) {
             assert.ifError(err);
             assert.equal(1, results.length);
 
@@ -57,7 +56,7 @@ describe('model', function() {
             assert.equal(results[0].id, geos[0].id);
             assert.ok(results[0] instanceof Geo);
 
-            Geo.geoSearch({ type: "place" }, { near: [40,40], maxDistance: 5 }, function(err, results) {
+            Geo.geoSearch({type: 'place'}, {near: [40, 40], maxDistance: 5}, function (err, results) {
               assert.ifError(err);
               assert.equal(0, results.length);
               db.close(done);
@@ -66,31 +65,30 @@ describe('model', function() {
         }
       });
     });
-    it('works with lean', function(done) {
-
+    it('works with lean', function (done) {
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoSearch instanceof Function);
 
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
 
         var geos = [];
-        geos[0] = new Geo({ pos: [10,10], type: "place"});
-        geos[1] = new Geo({ pos: [15,5], type: "place"});
-        geos[2] = new Geo({ pos: [20,15], type: "house"});
-        geos[3] = new Geo({ pos: [1,-1], type: "house"});
+        geos[0] = new Geo({pos: [10, 10], type: 'place'});
+        geos[1] = new Geo({pos: [15, 5], type: 'place'});
+        geos[2] = new Geo({pos: [20, 15], type: 'house'});
+        geos[3] = new Geo({pos: [1, -1], type: 'house'});
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function(err) {
+          geos[i].save(function (err) {
             assert.ifError(err);
             --count || next();
           });
         }
 
         function next() {
-          Geo.geoSearch({ type: "place" }, { near: [9,9], maxDistance: 5, lean: true }, function(err, results) {
+          Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5, lean: true}, function (err, results) {
             assert.ifError(err);
             assert.equal(1, results.length);
 
@@ -106,30 +104,29 @@ describe('model', function() {
         }
       });
     });
-    it('throws the correct error messages', function(done) {
-
+    it('throws the correct error messages', function (done) {
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoSearch instanceof Function);
 
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
 
-        var g = new Geo({ pos: [10,10], type: "place"});
-        g.save(function() {
-          Geo.geoSearch([], {}, function(e) {
+        var g = new Geo({pos: [10, 10], type: 'place'});
+        g.save(function () {
+          Geo.geoSearch([], {}, function (e) {
             assert.ok(e);
-            assert.equal(e.message, "Must pass conditions to geoSearch");
+            assert.equal(e.message, 'Must pass conditions to geoSearch');
 
-            Geo.geoSearch({ type: "test"}, {}, function(e) {
+            Geo.geoSearch({type: 'test'}, {}, function (e) {
               assert.ok(e);
-              assert.equal(e.message, "Must specify the near option in geoSearch");
+              assert.equal(e.message, 'Must specify the near option in geoSearch');
 
-              Geo.geoSearch({ type: "test" }, { near: "hello" }, function(e) {
+              Geo.geoSearch({type: 'test'}, {near: 'hello'}, function (e) {
                 assert.ok(e);
-                assert.equal(e.message, "near option must be an array [x, y]");
+                assert.equal(e.message, 'near option must be an array [x, y]');
 
-                Geo.geoSearch({ type: "test" }, { near: [1,2] }, function(err) {
+                Geo.geoSearch({type: 'test'}, {near: [1, 2]}, function (err) {
                   assert.ok(err);
                   assert.ok(/maxDistance needs a number/.test(err));
                   db.close(done);
@@ -140,28 +137,28 @@ describe('model', function() {
         });
       });
     });
-    it('returns a promise (gh-1614)', function(done) {
+    it('returns a promise (gh-1614)', function (done) {
       var db = start();
       var Geo = getModel(db);
 
-      var prom = Geo.geoSearch({ type: "place" }, { near: [9,9], maxDistance: 5 }, function() {});
+      var prom = Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5}, function () {});
       assert.ok(prom instanceof mongoose.Promise);
       db.close();
       done();
     });
 
-    it('allows not passing a callback (gh-1614)', function(done) {
+    it('allows not passing a callback (gh-1614)', function (done) {
       var db = start();
       var Geo = getModel(db);
-      Geo.on('index', function(err) {
+      Geo.on('index', function (err) {
         assert.ifError(err);
-        var g = new Geo({ pos: [10,10], type: "place"});
-        g.save(function(err) {
+        var g = new Geo({pos: [10, 10], type: 'place'});
+        g.save(function (err) {
           assert.ifError(err);
 
           var promise;
-          assert.doesNotThrow(function() {
-            promise = Geo.geoSearch({ type: "place" }, { near: [9,9], maxDistance: 5 });
+          assert.doesNotThrow(function () {
+            promise = Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5});
           });
           function validate(ret, stat) {
             assert.equal(1, ret.length);
@@ -174,7 +171,6 @@ describe('model', function() {
             db.close(done);
           }
           promise.then(validate, assert.ifError).then(finish).end();
-
         });
       });
     });
diff --git a/test/model.hydrate.test.js b/test/model.hydrate.test.js
index 031607318fc..ae94a6d881a 100644
--- a/test/model.hydrate.test.js
+++ b/test/model.hydrate.test.js
@@ -25,29 +25,29 @@ var schemaC = Schema({
 }, {discriminatorKey: 'type'});
 
 
-describe('model', function() {
-  describe('hydrate()', function() {
+describe('model', function () {
+  describe('hydrate()', function () {
     var db;
     var B;
     var Breakfast;
 
     var breakfastSchema = Schema({
-      food: { type: String, enum: ['bacon', 'eggs'] }
+      food: {type: String, enum: ['bacon', 'eggs']}
     });
 
-    before(function() {
+    before(function () {
       db = start();
       B = db.model('model-create', schemaB, 'gh-2637-1');
       B.discriminator('C', schemaC);
       Breakfast = db.model('gh-2637-2', breakfastSchema, 'gh-2637-2');
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('hydrates documents with no modified paths', function(done) {
-      var hydrated = B.hydrate({ _id: '541085faedb2f28965d0e8e7', title: 'chair' });
+    it('hydrates documents with no modified paths', function (done) {
+      var hydrated = B.hydrate({_id: '541085faedb2f28965d0e8e7', title: 'chair'});
 
       assert.ok(hydrated.get('_id') instanceof DocumentObjectId);
       assert.equal(hydrated.title, 'chair');
@@ -59,13 +59,13 @@ describe('model', function() {
       done();
     });
 
-    it('runs validators', function(done) {
+    it('runs validators', function (done) {
       var hydrated = Breakfast.hydrate({
         _id: '000000000000000000000001',
         food: 'waffles'
       });
 
-      hydrated.validate(function(err) {
+      hydrated.validate(function (err) {
         assert.ok(err);
         assert.ok(err.errors['food']);
         assert.deepEqual(['food'], Object.keys(err.errors));
@@ -73,7 +73,7 @@ describe('model', function() {
       });
     });
 
-    it('works correctly with model discriminators', function(done) {
+    it('works correctly with model discriminators', function (done) {
       var hydrated = B.hydrate({_id: '541085faedb2f28965d0e8e8', title: 'chair', type: 'C'});
 
       assert.equal(hydrated.test, 'test');
diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js
index 1d21d2db45e..7db34644702 100644
--- a/test/model.indexes.test.js
+++ b/test/model.indexes.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Test dependencies.
  */
@@ -10,28 +9,28 @@ var start = require('./common'),
     Schema = mongoose.Schema,
     ObjectId = Schema.Types.ObjectId;
 
-describe('model', function() {
-  describe('indexes', function() {
-    it('are created when model is compiled', function(done) {
+describe('model', function () {
+  describe('indexes', function () {
+    it('are created when model is compiled', function (done) {
       var Indexed = new Schema({
-        name: { type: String, index: true },
+        name: {type: String, index: true},
         last: String,
         email: String,
         date: Date
       });
 
-      Indexed.index({ last: 1, email: 1 }, { unique: true });
-      Indexed.index({ date: 1 }, { expires: 10 });
+      Indexed.index({last: 1, email: 1}, {unique: true});
+      Indexed.index({date: 1}, {expires: 10});
 
       var db = start(),
           IndexedModel = db.model('IndexedModel', Indexed, 'indexedmodel' + random()),
           assertions = 0;
 
-      IndexedModel.on('index', function() {
-        IndexedModel.collection.getIndexes({full: true}, function(err, indexes) {
+      IndexedModel.on('index', function () {
+        IndexedModel.collection.getIndexes({full: true}, function (err, indexes) {
           assert.ifError(err);
 
-          indexes.forEach(function(index) {
+          indexes.forEach(function (index) {
             switch (index.name) {
               case '_id_':
               case 'name_1':
@@ -51,15 +50,15 @@ describe('model', function() {
       });
     });
 
-    it('of embedded documents', function(done) {
+    it('of embedded documents', function (done) {
       var BlogPosts = new Schema({
-        _id: { type: ObjectId, index: true },
-        title: { type: String, index: true },
+        _id: {type: ObjectId, index: true},
+        title: {type: String, index: true},
         desc: String
       });
 
       var User = new Schema({
-        name: { type: String, index: true },
+        name: {type: String, index: true},
         blogposts: [BlogPosts]
       });
 
@@ -67,18 +66,21 @@ describe('model', function() {
           UserModel = db.model('DeepIndexedModel', User, 'deepindexedmodel' + random()),
           assertions = 0;
 
-      UserModel.on('index', function() {
-        UserModel.collection.getIndexes(function(err, indexes) {
+      UserModel.on('index', function () {
+        UserModel.collection.getIndexes(function (err, indexes) {
           assert.ifError(err);
 
           for (var i in indexes) {
-            indexes[i].forEach(function(index) {
-              if (index[0] == 'name')
+            indexes[i].forEach(function (index) {
+              if (index[0] == 'name') {
                 assertions++;
-              if (index[0] == 'blogposts._id')
+              }
+              if (index[0] == 'blogposts._id') {
                 assertions++;
-              if (index[0] == 'blogposts.title')
+              }
+              if (index[0] == 'blogposts.title') {
                 assertions++;
+              }
             });
           }
 
@@ -88,15 +90,15 @@ describe('model', function() {
       });
     });
 
-    it('of multiple embedded documents with same schema', function(done) {
+    it('of multiple embedded documents with same schema', function (done) {
       var BlogPosts = new Schema({
-        _id: { type: ObjectId, index: true },
-        title: { type: String, index: true },
+        _id: {type: ObjectId, index: true},
+        title: {type: String, index: true},
         desc: String
       });
 
       var User = new Schema({
-        name: { type: String, index: true },
+        name: {type: String, index: true},
         blogposts: [BlogPosts],
         featured: [BlogPosts]
       });
@@ -105,12 +107,12 @@ describe('model', function() {
       var UserModel = db.model('DeepIndexedModel', User, 'gh-2322');
       var assertions = 0;
 
-      UserModel.on('index', function() {
-        UserModel.collection.getIndexes(function(err, indexes) {
+      UserModel.on('index', function () {
+        UserModel.collection.getIndexes(function (err, indexes) {
           assert.ifError(err);
 
           for (var i in indexes) {
-            indexes[i].forEach(function(index) {
+            indexes[i].forEach(function (index) {
               if (index[0] === 'name') {
                 ++assertions;
               }
@@ -135,16 +137,16 @@ describe('model', function() {
       });
     });
 
-    it('compound: on embedded docs', function(done) {
+    it('compound: on embedded docs', function (done) {
       var BlogPosts = new Schema({
         title: String,
         desc: String
       });
 
-      BlogPosts.index({ title: 1, desc: 1 });
+      BlogPosts.index({title: 1, desc: 1});
 
       var User = new Schema({
-        name: { type: String, index: true },
+        name: {type: String, index: true},
         blogposts: [BlogPosts]
       });
 
@@ -152,8 +154,8 @@ describe('model', function() {
           UserModel = db.model('DeepCompoundIndexModel', User, 'deepcompoundindexmodel' + random()),
           found = 0;
 
-      UserModel.on('index', function() {
-        UserModel.collection.getIndexes(function(err, indexes) {
+      UserModel.on('index', function () {
+        UserModel.collection.getIndexes(function (err, indexes) {
           assert.ifError(err);
 
           for (var index in indexes) {
@@ -172,43 +174,42 @@ describe('model', function() {
       });
     });
 
-    it('error should emit on the model', function(done) {
-      var db = start();
-
-      var schema = new Schema({ name: { type: String } }),
-          Test = db.model('IndexError', schema, "x" + random());
+    it('error should emit on the model', function (done) {
+      var db = start(),
+          schema = new Schema({name: {type: String}}),
+          Test = db.model('IndexError', schema, 'x' + random());
 
-      Test.on('index', function(err) {
+      Test.on('index', function (err) {
         db.close();
         assert.ok(/E11000 duplicate key error/.test(err.message), err);
         done();
       });
 
-      Test.create({ name: 'hi' }, { name: 'hi' }, function(err) {
+      Test.create({name: 'hi'}, {name: 'hi'}, function (err) {
         assert.strictEqual(err, null);
-        Test.schema.index({ name: 1 }, { unique: true });
-        Test.schema.index({ other: 1 });
+        Test.schema.index({name: 1}, {unique: true});
+        Test.schema.index({other: 1});
         Test.init();
       });
     });
 
-    describe('auto creation', function() {
-      it('can be disabled', function(done) {
+    describe('auto creation', function () {
+      it('can be disabled', function (done) {
         var db = start();
-        var schema = new Schema({ name: { type: String, index: true }});
+        var schema = new Schema({name: {type: String, index: true}});
         schema.set('autoIndex', false);
 
         var Test = db.model('AutoIndexing', schema, 'autoindexing-disable');
-        Test.on('index', function() {
+        Test.on('index', function () {
           assert.ok(false, 'Model.ensureIndexes() was called');
         });
 
         // Create a doc because mongodb 3.0 getIndexes errors if db doesn't
         // exist
-        Test.create({ name: 'Bacon' }, function(err) {
+        Test.create({name: 'Bacon'}, function (err) {
           assert.ifError(err);
-          setTimeout(function() {
-            Test.collection.getIndexes(function(err, indexes) {
+          setTimeout(function () {
+            Test.collection.getIndexes(function (err, indexes) {
               assert.ifError(err);
               // Only default _id index should exist
               assert.deepEqual(['_id_'], Object.keys(indexes));
@@ -218,15 +219,15 @@ describe('model', function() {
         });
       });
 
-      describe('global autoIndexes (gh-1875)', function() {
-        it('will create indexes as a default', function(done) {
+      describe('global autoIndexes (gh-1875)', function () {
+        it('will create indexes as a default', function (done) {
           var db = start();
-          var schema = new Schema({name: { type: String, index: true } });
+          var schema = new Schema({name: {type: String, index: true}});
           var Test = db.model('GlobalAutoIndex', schema, 'gh-1875-1');
-          Test.on('index', function(error) {
+          Test.on('index', function (error) {
             assert.ifError(error);
             assert.ok(true, 'Model.ensureIndexes() was called');
-            Test.collection.getIndexes(function(err, indexes) {
+            Test.collection.getIndexes(function (err, indexes) {
               assert.ifError(err);
               assert.equal(2, Object.keys(indexes).length);
               db.close(done);
@@ -234,18 +235,18 @@ describe('model', function() {
           });
         });
 
-        it('will not create indexes if the global auto index is false and schema option isnt set (gh-1875)', function(done) {
+        it('will not create indexes if the global auto index is false and schema option isnt set (gh-1875)', function (done) {
           var db = start({config: {autoIndex: false}});
           var schema = new Schema({name: {type: String, index: true}});
-          var Test = db.model('GlobalAutoIndex', schema, "x" + random());
-          Test.on('index', function() {
+          var Test = db.model('GlobalAutoIndex', schema, 'x' + random());
+          Test.on('index', function () {
             assert.ok(false, 'Model.ensureIndexes() was called');
           });
 
-          Test.create({ name: 'Bacon' }, function(err) {
+          Test.create({name: 'Bacon'}, function (err) {
             assert.ifError(err);
-            setTimeout(function() {
-              Test.collection.getIndexes(function(err, indexes) {
+            setTimeout(function () {
+              Test.collection.getIndexes(function (err, indexes) {
                 assert.ifError(err);
                 assert.deepEqual(['_id_'], Object.keys(indexes));
                 db.close(done);
@@ -256,42 +257,48 @@ describe('model', function() {
       });
     });
 
-    it('do not trigger "MongoError: cannot add index with a background operation in progress" (gh-1365) LONG', function(done) {
+    it('do not trigger "MongoError: cannot add index with a background operation in progress" (gh-1365) LONG', function (done) {
       this.timeout(45000);
 
-      var db = start({ uri: 'mongodb://localhost/mongoose_test_indexing'});
+      var db = start({uri: 'mongodb://localhost/mongoose_test_indexing'});
 
       var schema = Schema({
-        name: { type: String, index: true },
-        furryness: { type: Number, index: true }
-      }, { autoIndex: false });
+        name: {type: String, index: true},
+        furryness: {type: Number, index: true}
+      }, {autoIndex: false});
 
-      schema.index({ name: 1, furryness: 1});
+      schema.index({name: 1, furryness: 1});
 
       var K = db.model('Kitten', schema);
-      K.on('index', function(err) {
+      K.on('index', function (err) {
         assert.ifError(err);
         db.close(done);
       });
 
       var neededKittens = 30000;
 
-      db.on('open', function() {
-        K.count({}, function(err, n) {
+      db.on('open', function () {
+        K.count({}, function (err, n) {
           assert.ifError(err);
-          if (n >= neededKittens) return index();
+          if (n >= neededKittens) {
+            return index();
+          }
           var pending = neededKittens - n;
-          for (var i = n; i < neededKittens; ++i) (function(i) {
-            K.create({ name: 'kitten' + i, furryness: i }, function(err) {
-              assert.ifError(err);
-              if (--pending) return;
-              index();
-            });
-          })(i);
+          for (var i = n; i < neededKittens; ++i) {
+            (function (i) {
+              K.create({name: 'kitten' + i, furryness: i}, function (err) {
+                assert.ifError(err);
+                if (--pending) {
+                  return;
+                }
+                index();
+              });
+            })(i);
+          }
         });
 
         function index() {
-          K.collection.dropAllIndexes(function(err) {
+          K.collection.dropAllIndexes(function (err) {
             assert.ifError(err);
             K.ensureIndexes();
           });
@@ -300,35 +307,35 @@ describe('model', function() {
     });
 
 
-    describe('model.ensureIndexes()', function() {
-      it('is a function', function(done) {
-        var schema = mongoose.Schema({ x: 'string' });
+    describe('model.ensureIndexes()', function () {
+      it('is a function', function (done) {
+        var schema = mongoose.Schema({x: 'string'});
         var Test = mongoose.createConnection().model('ensureIndexes-' + random, schema);
         assert.equal('function', typeof Test.ensureIndexes);
         done();
       });
 
-      it('returns a Promise', function(done) {
-        var schema = mongoose.Schema({ x: 'string' });
+      it('returns a Promise', function (done) {
+        var schema = mongoose.Schema({x: 'string'});
         var Test = mongoose.createConnection().model('ensureIndexes-' + random, schema);
         var p = Test.ensureIndexes();
         assert.ok(p instanceof mongoose.Promise);
         done();
       });
 
-      it('creates indexes', function(done) {
+      it('creates indexes', function (done) {
         var db = start();
-        var schema = new Schema({ name: { type: String } }),
-            Test = db.model('ManualIndexing', schema, "x" + random());
+        var schema = new Schema({name: {type: String}}),
+            Test = db.model('ManualIndexing', schema, 'x' + random());
 
-        Test.schema.index({ name: 1 }, { sparse: true });
+        Test.schema.index({name: 1}, {sparse: true});
 
         var called = false;
-        Test.on('index', function() {
+        Test.on('index', function () {
           called = true;
         });
 
-        Test.ensureIndexes(function(err) {
+        Test.ensureIndexes(function (err) {
           assert.ifError(err);
           assert.ok(called);
           db.close(done);
diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 3a307c03bac..6b04f901e63 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -44,8 +44,8 @@ var BlogPost = new Schema({
 var collection = 'mapreduce_' + random();
 mongoose.model('MapReduce', BlogPost);
 
-describe('model: mapreduce:', function() {
-  it('works', function(done) {
+describe('model: mapreduce:', function () {
+  it('works', function (done) {
     var db = start(),
         MR = db.model('MapReduce', collection);
 
@@ -54,8 +54,9 @@ describe('model: mapreduce:', function() {
     var authors = 'aaron guillermo brian nathan'.split(' ');
     var num = 10;
     var docs = [];
-    for (var i = 0; i< num; ++i)
-      docs.push({ author: authors[i%authors.length], owners: [id], published: true });
+    for (var i = 0; i < num; ++i) {
+      docs.push({author: authors[i % authors.length], owners: [id], published: true});
+    }
 
     MR.create(docs, function (err, insertedDocs) {
       assert.ifError(err);
@@ -65,8 +66,12 @@ describe('model: mapreduce:', function() {
       magicID = b._id;
 
       var o = {
-        map: function() { emit(this.author, 1); },
-        reduce: function(k, vals) { return vals.length; }
+        map: function () {
+          emit(this.author, 1);
+        },
+        reduce: function (k, vals) {
+          return vals.length;
+        }
       };
 
       MR.mapReduce(o, function (err, ret, stats) {
@@ -74,16 +79,28 @@ describe('model: mapreduce:', function() {
         assert.ok(Array.isArray(ret));
         assert.ok(stats);
         ret.forEach(function (res) {
-          if ('aaron' == res._id) assert.equal(3, res.value);
-          if ('guillermo' == res._id) assert.equal(3, res.value);
-          if ('brian' == res._id) assert.equal(2, res.value);
-          if ('nathan' == res._id) assert.equal(2, res.value);
+          if ('aaron' == res._id) {
+            assert.equal(3, res.value);
+          }
+          if ('guillermo' == res._id) {
+            assert.equal(3, res.value);
+          }
+          if ('brian' == res._id) {
+            assert.equal(2, res.value);
+          }
+          if ('nathan' == res._id) {
+            assert.equal(2, res.value);
+          }
         });
 
         var o = {
-          map: function() { emit(this.author, 1); },
-          reduce: function(k, vals) { return vals.length; },
-          query: { author: 'aaron', published: 1, owners: id }
+          map: function () {
+            emit(this.author, 1);
+          },
+          reduce: function (k, vals) {
+            return vals.length;
+          },
+          query: {author: 'aaron', published: 1, owners: id}
         };
 
         MR.mapReduce(o, function (err, ret, stats) {
@@ -99,12 +116,16 @@ describe('model: mapreduce:', function() {
         });
       });
 
-      function modeling () {
+      function modeling() {
         var o = {
-          map: function() { emit(this.author, { own: magicID }); },
-          scope: { magicID: magicID },
-          reduce: function(k, vals) { return { own: vals[0].own, count: vals.length };},
-          out: { replace: '_mapreduce_test_' + random() }
+          map: function () {
+            emit(this.author, {own: magicID});
+          },
+          scope: {magicID: magicID},
+          reduce: function (k, vals) {
+            return {own: vals[0].own, count: vals.length};
+          },
+          out: {replace: '_mapreduce_test_' + random()}
         };
 
         MR.mapReduce(o, function (err, ret, stats) {
@@ -124,7 +145,7 @@ describe('model: mapreduce:', function() {
             assert.equal('nathan', docs[3]._id);
 
             // update casting works
-            ret.findOneAndUpdate({ _id: 'aaron' }, { published: true }, { 'new': true }, function (err, doc) {
+            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {'new': true}, function (err, doc) {
               assert.ifError(err);
               assert.ok(doc);
               assert.equal('aaron', doc._id);
@@ -132,14 +153,14 @@ describe('model: mapreduce:', function() {
 
               // ad-hoc population works
               ret
-              .findOne({ _id: 'aaron' })
-              .populate({ path: 'value.own', model: 'MapReduce' })
+              .findOne({_id: 'aaron'})
+              .populate({path: 'value.own', model: 'MapReduce'})
               .exec(function (err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal('guillermo', doc.value.own.author);
                 done();
-              })
+              });
             });
           });
         });
@@ -147,49 +168,60 @@ describe('model: mapreduce:', function() {
     });
   });
 
-  it('withholds stats with false verbosity', function(done) {
+  it('withholds stats with false verbosity', function (done) {
     var db = start(),
         MR = db.model('MapReduce', collection);
 
     var o = {
-      map: function() {},
-      reduce: function() { return 'test'; },
+      map: function () {
+      },
+      reduce: function () {
+        return 'test';
+      },
       verbose: false
     };
 
-    MR.mapReduce(o, function (err, results, stats){
+    MR.mapReduce(o, function (err, results, stats) {
       assert.equal('undefined', typeof stats);
       db.close(done);
     });
   });
 
-  describe('promises (gh-1628)', function() {
-    it('are returned', function(done) {
+  describe('promises (gh-1628)', function () {
+    it('are returned', function (done) {
       var db = start(),
           MR = db.model('MapReduce', collection);
 
       var o = {
-        map: function() {},
-        reduce: function() { return 'test'; }
+        map: function () {
+        },
+        reduce: function () {
+          return 'test';
+        }
       };
 
-      var promise = MR.mapReduce(o, function(){});
+      var promise = MR.mapReduce(o, function () {
+      });
       assert.ok(promise instanceof mongoose.Promise);
 
       db.close(done);
     });
 
-    it('allow not passing a callback', function(done) {
+    it('allow not passing a callback', function (done) {
       var db = start(),
           MR = db.model('MapReduce', collection);
 
       var o = {
-        map: function() { emit(this.author, 1); },
-        reduce: function(k, vals) { return vals.length; },
-        query: { author: 'aaron', published: 1 }
+        map: function () {
+          emit(this.author, 1);
+        },
+        reduce: function (k, vals) {
+          return vals.length;
+        },
+        query: {author: 'aaron', published: 1}
       };
 
-      function validate (ret, stats) {
+      function validate(ret, stats) {
         assert.ok(Array.isArray(ret));
         assert.equal(1, ret.length);
         assert.equal('aaron', ret[0]._id);
@@ -197,61 +229,77 @@ describe('model: mapreduce:', function() {
         assert.ok(stats);
       }
 
-      function finish () {
+      function finish() {
         db.close(done);
       }
 
       var promise;
 
-      assert.doesNotThrow(function(){
+      assert.doesNotThrow(function () {
         promise = MR.mapReduce(o);
-      })
+      });
 
       promise.then(validate, assert.ifError).then(finish).end();
-    })
-
+    });
   });
 
-  it('works using then', function(done) {
-    var db = start()
-      , MR = db.model('MapReduce', collection);
+  it('works using then', function (done) {
+    var db = start(),
+        MR = db.model('MapReduce', collection);
 
     var magicID;
     var id = new mongoose.Types.ObjectId;
     var authors = 'aaron guillermo brian nathan'.split(' ');
     var num = 10;
     var docs = [];
-    for (var i = 0; i < num; ++i)
-      docs.push({ author: authors[i % authors.length], owners: [id], published: true });
+    for (var i = 0; i < num; ++i) {
+      docs.push({author: authors[i % authors.length], owners: [id], published: true});
+    }
 
-    MR.create(docs, function(err, insertedDocs) {
+    MR.create(docs, function (err, insertedDocs) {
       assert.ifError(err);
 
       var b = insertedDocs[1];
       magicID = b._id;
 
       var o = {
-        map: function() { emit(this.author, 1); }
-        , reduce: function(k, vals) { return vals.length; }
+        map: function () {
+          emit(this.author, 1);
+        },
+        reduce: function (k, vals) {
+          return vals.length;
+        }
       };
 
-      MR.mapReduce(o).then(function(ret, stats) {
+      MR.mapReduce(o).then(function (ret, stats) {
         assert.ok(Array.isArray(ret));
         assert.ok(stats);
-        ret.forEach(function(res) {
-          if ('aaron' == res._id) assert.equal(6, res.value);
-          if ('guillermo' == res._id) assert.equal(6, res.value);
-          if ('brian' == res._id) assert.equal(4, res.value);
-          if ('nathan' == res._id) assert.equal(4, res.value);
+        ret.forEach(function (res) {
+          if ('aaron' == res._id) {
+            assert.equal(6, res.value);
+          }
+          if ('guillermo' == res._id) {
+            assert.equal(6, res.value);
+          }
+          if ('brian' == res._id) {
+            assert.equal(4, res.value);
+          }
+          if ('nathan' == res._id) {
+            assert.equal(4, res.value);
+          }
         });
 
         var o = {
-          map: function() { emit(this.author, 1); }
-          , reduce: function(k, vals) { return vals.length; }
-          , query: { author: 'aaron', published: 1, owners: id }
+          map: function () {
+            emit(this.author, 1);
+          },
+          reduce: function (k, vals) {
+            return vals.length;
+          },
+          query: {author: 'aaron', published: 1, owners: id}
         };
 
-        MR.mapReduce(o).then(function(ret, stats) {
+        MR.mapReduce(o).then(function (ret, stats) {
           assert.ok(Array.isArray(ret));
           assert.equal(1, ret.length);
           assert.equal('aaron', ret[0]._id);
@@ -259,26 +307,28 @@ describe('model: mapreduce:', function() {
           assert.ok(stats);
           modeling();
         });
-
       });
 
       function modeling() {
         var o = {
-          map: function() { emit(this.author, { own: magicID }); }
-          , scope: { magicID: magicID }
-          , reduce: function(k, vals) { return { own: vals[0].own, count: vals.length };}
-          , out: { replace: '_mapreduce_test_' + random() }
+          map: function () {
+            emit(this.author, {own: magicID});
+          },
+          scope: {magicID: magicID},
+          reduce: function (k, vals) {
+            return {own: vals[0].own, count: vals.length};
+          },
+          out: {replace: '_mapreduce_test_' + random()}
         };
 
-        MR.mapReduce(o).then(function(ret) {
-
+        MR.mapReduce(o).then(function (ret) {
           // ret is a model
           assert.ok(!Array.isArray(ret));
           assert.equal('function', typeof ret.findOne);
           assert.equal('function', typeof ret.mapReduce);
 
           // queries work
-          ret.where('value.count').gt(1).sort({_id: 1}).exec(function(err, docs) {
+          ret.where('value.count').gt(1).sort({_id: 1}).exec(function (err, docs) {
             assert.ifError(err);
             assert.equal('aaron', docs[0]._id);
             assert.equal('brian', docs[1]._id);
@@ -286,7 +336,7 @@ describe('model: mapreduce:', function() {
             assert.equal('nathan', docs[3]._id);
 
             // update casting works
-            ret.findOneAndUpdate({ _id: 'aaron' }, { published: true }, { 'new': true }, function(err, doc) {
+            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {'new': true}, function (err, doc) {
               assert.ifError(err);
               assert.ok(doc);
               assert.equal('aaron', doc._id);
@@ -294,9 +344,9 @@ describe('model: mapreduce:', function() {
 
               // ad-hoc population works
               ret
-              .findOne({ _id: 'aaron' })
-              .populate({ path: 'value.own', model: 'MapReduce' })
-              .exec(function(err, doc) {
+              .findOne({_id: 'aaron'})
+              .populate({path: 'value.own', model: 'MapReduce'})
+              .exec(function (err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal('guillermo', doc.value.own.author);
@@ -304,26 +354,27 @@ describe('model: mapreduce:', function() {
               });
             });
           });
-        })
+        });
       }
     });
   });
 
-  it('withholds stats with false verbosity using then', function(done) {
-    var db = start()
-      , MR = db.model('MapReduce', collection);
+  it('withholds stats with false verbosity using then', function (done) {
+    var db = start(),
+        MR = db.model('MapReduce', collection);
 
     var o = {
-      map: function() {}
-      , reduce: function() { return 'test'; }
-      , verbose: false
+      map: function () {
+      },
+      reduce: function () {
+        return 'test';
+      },
+      verbose: false
     };
 
-    MR.mapReduce(o).then(function(results, stats) {
+    MR.mapReduce(o).then(function (results, stats) {
       assert.equal('undefined', typeof stats);
       db.close(done);
     });
-
   });
-
 });
diff --git a/test/model.middleware.test.js b/test/model.middleware.test.js
index fc6b82641e8..fdbadd45ee6 100644
--- a/test/model.middleware.test.js
+++ b/test/model.middleware.test.js
@@ -8,29 +8,29 @@ var start = require('./common'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema;
 
-describe('model middleware', function() {
-  it('post save', function(done) {
+describe('model middleware', function () {
+  it('post save', function (done) {
     var schema = new Schema({
       title: String
     });
 
     var called = 0;
 
-    schema.post('save', function(obj) {
+    schema.post('save', function (obj) {
       assert.equal(obj.title, 'Little Green Running Hood');
       assert.equal(this.title, 'Little Green Running Hood');
       assert.equal(0, called);
       called++;
     });
 
-    schema.post('save', function(obj) {
+    schema.post('save', function (obj) {
       assert.equal(obj.title, 'Little Green Running Hood');
       assert.equal(this.title, 'Little Green Running Hood');
       assert.equal(1, called);
       called++;
     });
 
-    schema.post('save', function(obj, next) {
+    schema.post('save', function (obj, next) {
       assert.equal(obj.title, 'Little Green Running Hood');
       assert.equal(2, called);
       called++;
@@ -40,29 +40,29 @@ describe('model middleware', function() {
     var db = start(),
         TestMiddleware = db.model('TestPostSaveMiddleware', schema);
 
-    var test = new TestMiddleware({ title: 'Little Green Running Hood'});
+    var test = new TestMiddleware({title: 'Little Green Running Hood'});
 
-    test.save(function(err) {
+    test.save(function (err) {
       assert.ifError(err);
-      assert.equal(test.title,'Little Green Running Hood');
+      assert.equal(test.title, 'Little Green Running Hood');
       assert.equal(3, called);
       db.close();
       done();
     });
   });
 
-  it('validate middleware runs before save middleware (gh-2462)', function(done) {
+  it('validate middleware runs before save middleware (gh-2462)', function (done) {
     var schema = new Schema({
       title: String
     });
     var count = 0;
 
-    schema.pre('validate', function(next) {
+    schema.pre('validate', function (next) {
       assert.equal(0, count++);
       next();
     });
 
-    schema.pre('save', function(next) {
+    schema.pre('save', function (next) {
       assert.equal(1, count++);
       next();
     });
@@ -70,30 +70,30 @@ describe('model middleware', function() {
     var db = start();
     var Book = db.model('gh2462', schema);
 
-    Book.create({}, function() {
+    Book.create({}, function () {
       assert.equal(count, 2);
       db.close(done);
     });
   });
 
-  it('works', function(done) {
+  it('works', function (done) {
     var schema = new Schema({
       title: String
     });
 
     var called = 0;
 
-    schema.pre('init', function(next) {
+    schema.pre('init', function (next) {
       called++;
       next();
     });
 
-    schema.pre('save', function(next) {
+    schema.pre('save', function (next) {
       called++;
       next(new Error('Error 101'));
     });
 
-    schema.pre('remove', function(next) {
+    schema.pre('remove', function (next) {
       called++;
       next();
     });
@@ -111,12 +111,12 @@ describe('model middleware', function() {
 
     assert.equal(1, called);
 
-    test.save(function(err) {
+    test.save(function (err) {
       assert.ok(err instanceof Error);
-      assert.equal(err.message,'Error 101');
+      assert.equal(err.message, 'Error 101');
       assert.equal(2, called);
 
-      test.remove(function(err) {
+      test.remove(function (err) {
         db.close();
         assert.ifError(err);
         assert.equal(3, called);
@@ -125,7 +125,7 @@ describe('model middleware', function() {
     });
   });
 
-  it('post init', function(done) {
+  it('post init', function (done) {
     var schema = new Schema({
       title: String
     });
@@ -133,12 +133,12 @@ describe('model middleware', function() {
     var preinit = 0,
         postinit = 0;
 
-    schema.pre('init', function(next) {
+    schema.pre('init', function (next) {
       ++preinit;
       next();
     });
 
-    schema.post('init', function(doc) {
+    schema.post('init', function (doc) {
       assert.ok(doc instanceof mongoose.Document);
       ++postinit;
     });
@@ -148,16 +148,16 @@ describe('model middleware', function() {
     var db = start(),
         Test = db.model('TestPostInitMiddleware');
 
-    var test = new Test({ title: "banana" });
+    var test = new Test({title: 'banana'});
 
-    test.save(function(err) {
+    test.save(function (err) {
       assert.ifError(err);
 
-      Test.findById(test._id, function(err, test) {
+      Test.findById(test._id, function (err, test) {
         assert.ifError(err);
         assert.equal(1, preinit);
         assert.equal(1, postinit);
-        test.remove(function() {
+        test.remove(function () {
           db.close();
           done();
         });
@@ -165,7 +165,7 @@ describe('model middleware', function() {
     });
   });
 
-  it('gh-1829', function(done) {
+  it('gh-1829', function (done) {
     var childSchema = new mongoose.Schema({
       name: String
     });
@@ -174,7 +174,7 @@ describe('model middleware', function() {
     var childPreCallsByName = {};
     var parentPreCalls = 0;
 
-    childSchema.pre('save', function(next) {
+    childSchema.pre('save', function (next) {
       childPreCallsByName[this.name] = childPreCallsByName[this.name] || 0;
       ++childPreCallsByName[this.name];
       ++childPreCalls;
@@ -186,7 +186,7 @@ describe('model middleware', function() {
       children: [childSchema]
     });
 
-    parentSchema.pre('save', function(next) {
+    parentSchema.pre('save', function (next) {
       ++parentPreCalls;
       next();
     });
@@ -197,19 +197,19 @@ describe('model middleware', function() {
     var parent = new Parent({
       name: 'Han',
       children: [
-        { name: 'Jaina' },
-        { name: 'Jacen' }
+        {name: 'Jaina'},
+        {name: 'Jacen'}
       ]
     });
 
-    parent.save(function(error) {
+    parent.save(function (error) {
       assert.ifError(error);
       assert.equal(2, childPreCalls);
       assert.equal(1, childPreCallsByName['Jaina']);
       assert.equal(1, childPreCallsByName['Jacen']);
       assert.equal(1, parentPreCalls);
       parent.children[0].name = 'Anakin';
-      parent.save(function(error) {
+      parent.save(function (error) {
         assert.ifError(error);
         assert.equal(4, childPreCalls);
         assert.equal(1, childPreCallsByName['Anakin']);
@@ -223,7 +223,7 @@ describe('model middleware', function() {
     });
   });
 
-  it('validate + remove', function(done) {
+  it('validate + remove', function (done) {
     var schema = new Schema({
       title: String
     });
@@ -233,22 +233,22 @@ describe('model middleware', function() {
         preRemove = 0,
         postRemove = 0;
 
-    schema.pre('validate', function(next) {
+    schema.pre('validate', function (next) {
       ++preValidate;
       next();
     });
 
-    schema.pre('remove', function(next) {
+    schema.pre('remove', function (next) {
       ++preRemove;
       next();
     });
 
-    schema.post('validate', function(doc) {
+    schema.post('validate', function (doc) {
       assert.ok(doc instanceof mongoose.Document);
       ++postValidate;
     });
 
-    schema.post('remove', function(doc) {
+    schema.post('remove', function (doc) {
       assert.ok(doc instanceof mongoose.Document);
       ++postRemove;
     });
@@ -256,15 +256,15 @@ describe('model middleware', function() {
     var db = start(),
         Test = db.model('TestPostValidateMiddleware', schema);
 
-    var test = new Test({ title: "banana" });
+    var test = new Test({title: 'banana'});
 
-    test.save(function(err) {
+    test.save(function (err) {
       assert.ifError(err);
       assert.equal(1, preValidate);
       assert.equal(1, postValidate);
       assert.equal(0, preRemove);
       assert.equal(0, postRemove);
-      test.remove(function(err) {
+      test.remove(function (err) {
         db.close();
         assert.ifError(err);
         assert.equal(1, preValidate);
diff --git a/test/model.populate.divergent.test.js b/test/model.populate.divergent.test.js
index b4ade1c6015..ebacb4ddf8a 100644
--- a/test/model.populate.divergent.test.js
+++ b/test/model.populate.divergent.test.js
@@ -14,7 +14,7 @@ var start = require('./common'),
  * Tests.
  */
 
-describe('model: populate: divergent arrays', function() {
+describe('model: populate: divergent arrays', function () {
   // match
   // skip
   // limit
@@ -26,53 +26,53 @@ describe('model: populate: divergent arrays', function() {
 
   var db, C, M;
 
-  before(function(done) {
+  before(function (done) {
     db = start();
-    C = db.model("Child", { _id: Number, name: String }, 'child-' + random());
-    M = db.model("Parent", { array: { type: [{ type: Number, ref: 'Child' }] }}, 'parent-' + random());
+    C = db.model('Child', {_id: Number, name: String}, 'child-' + random());
+    M = db.model('Parent', {array: {type: [{type: Number, ref: 'Child'}]}}, 'parent-' + random());
 
     C.create(
-        { _id: 0, name: 'zero' }
-      , { _id: 1, name: 'one' }
-      , { _id: 2, name: 'two' }, function(err) {
+        {_id: 0, name: 'zero'}
+      , {_id: 1, name: 'one'}
+      , {_id: 2, name: 'two'}, function (err) {
         assert.ifError(err);
-        M.create({ array: [0, 1, 2] }, function(err) {
+        M.create({array: [0, 1, 2]}, function (err) {
           assert.ifError(err);
           done();
         });
       });
   });
 
-  after(function(done) {
+  after(function (done) {
     db.close(done);
   });
 
   function test(check, fn) {
-    it('using $set', function(done) {
-      fn(function(err, doc) {
+    it('using $set', function (done) {
+      fn(function (err, doc) {
         assert.ifError(err);
-        doc.array.unshift({ _id: 10, name: 'ten' });
-        doc.save(function(err) {
+        doc.array.unshift({_id: 10, name: 'ten'});
+        doc.save(function (err) {
           check(err);
           done();
         });
       });
     });
-    it('using $pop 1', function(done) {
-      fn(function(err, doc) {
+    it('using $pop 1', function (done) {
+      fn(function (err, doc) {
         assert.ifError(err);
         doc.array.$pop();
-        doc.save(function(err) {
+        doc.save(function (err) {
           check(err);
           done();
         });
       });
     });
-    it('using $pop -1', function(done) {
-      fn(function(err, doc) {
+    it('using $pop -1', function (done) {
+      fn(function (err, doc) {
         assert.ifError(err);
         doc.array.$shift();
-        doc.save(function(err) {
+        doc.save(function (err) {
           check(err);
           done();
         });
@@ -85,60 +85,60 @@ describe('model: populate: divergent arrays', function() {
   }
 
   function testFails(fn) {
-    test(function(err) {
+    test(function (err) {
       assert.ok(err instanceof DivergentArrayError, 'non-divergent error: ' + err);
       assert.ok(/\sarray/.test(err.message));
     }, fn);
   }
 
-  describe('from match', function() {
-    testFails(function(cb) {
-      M.findOne().populate({ path: 'array', match: { name: 'one' }}).exec(cb);
+  describe('from match', function () {
+    testFails(function (cb) {
+      M.findOne().populate({path: 'array', match: {name: 'one'}}).exec(cb);
     });
   });
-  describe('from skip', function() {
-    describe('2', function() {
-      testFails(function(cb) {
-        M.findOne().populate({ path: 'array', options: { skip: 2 }}).exec(cb);
+  describe('from skip', function () {
+    describe('2', function () {
+      testFails(function (cb) {
+        M.findOne().populate({path: 'array', options: {skip: 2}}).exec(cb);
       });
     });
-    describe('0', function() {
-      testOk(function(cb) {
-        M.findOne().populate({ path: 'array', options: { skip: 0 }}).exec(cb);
+    describe('0', function () {
+      testOk(function (cb) {
+        M.findOne().populate({path: 'array', options: {skip: 0}}).exec(cb);
       });
     });
   });
-  describe('from limit', function() {
-    describe('0', function() {
-      testFails(function(cb) {
-        M.findOne().populate({ path: 'array', options: { limit: 0 }}).exec(cb);
+  describe('from limit', function () {
+    describe('0', function () {
+      testFails(function (cb) {
+        M.findOne().populate({path: 'array', options: {limit: 0}}).exec(cb);
       });
     });
-    describe('1', function() {
-      testFails(function(cb) {
-        M.findOne().populate({ path: 'array', options: { limit: 1 }}).exec(cb);
+    describe('1', function () {
+      testFails(function (cb) {
+        M.findOne().populate({path: 'array', options: {limit: 1}}).exec(cb);
       });
     });
   });
-  describe('from deselected _id', function() {
-    describe('using string and only -_id', function() {
-      testFails(function(cb) {
-        M.findOne().populate({ path: 'array', select: '-_id'}).exec(cb);
+  describe('from deselected _id', function () {
+    describe('using string and only -_id', function () {
+      testFails(function (cb) {
+        M.findOne().populate({path: 'array', select: '-_id'}).exec(cb);
       });
     });
-    describe('using string', function() {
-      testFails(function(cb) {
-        M.findOne().populate({ path: 'array', select: 'name -_id'}).exec(cb);
+    describe('using string', function () {
+      testFails(function (cb) {
+        M.findOne().populate({path: 'array', select: 'name -_id'}).exec(cb);
       });
     });
-    describe('using object and only _id: 0', function() {
-      testFails(function(cb) {
-        M.findOne().populate({ path: 'array', select: { _id: 0 }}).exec(cb);
+    describe('using object and only _id: 0', function () {
+      testFails(function (cb) {
+        M.findOne().populate({path: 'array', select: {_id: 0}}).exec(cb);
       });
     });
-    describe('using object', function() {
-      testFails(function(cb) {
-        M.findOne().populate({ path: 'array', select: { _id: 0, name: 1 }}).exec(cb);
+    describe('using object', function () {
+      testFails(function (cb) {
+        M.findOne().populate({path: 'array', select: {_id: 0, name: 1}}).exec(cb);
       });
     });
   });
diff --git a/test/model.populate.setting.test.js b/test/model.populate.setting.test.js
index aefbecac57e..9890cc48f82 100644
--- a/test/model.populate.setting.test.js
+++ b/test/model.populate.setting.test.js
@@ -23,8 +23,8 @@ var posts = 'blogposts_' + random(),
  * Tests.
  */
 
-describe('model: populate:', function() {
-  describe('setting populated paths (gh-570)', function() {
+describe('model: populate:', function () {
+  describe('setting populated paths (gh-570)', function () {
     var types = {
       'ObjectId': DocObjectId,
       'String': String,
@@ -36,30 +36,30 @@ describe('model: populate:', function() {
     construct.String = random;
     construct.ObjectId = DocObjectId;
     construct.Number = random;
-    construct.Buffer = function() {
+    construct.Buffer = function () {
       return new Buffer(random());
     };
 
-    Object.keys(types).forEach(function(id) {
-      describe('should not cast to _id of type ' + id, function() {
+    Object.keys(types).forEach(function (id) {
+      describe('should not cast to _id of type ' + id, function () {
         var refuser;
         var db;
         var B, U;
         var u1;
         var b1, b2;
 
-        before(function(done) {
+        before(function (done) {
           refuser = 'RefUser-' + id;
 
           var bSchema = Schema({
             title: String,
-            fans: [{type: id, ref: refuser }],
-            adhoc: [{ subdoc: id, subarray: [{ things: [id] }] }],
-            _creator: { type: id, ref: refuser },
+            fans: [{type: id, ref: refuser}],
+            adhoc: [{subdoc: id, subarray: [{things: [id]}]}],
+            _creator: {type: id, ref: refuser},
             embed: [{
-              other: { type: id, ref: refuser },
-              array: [{ type: id, ref: refuser }],
-              nested: [{ subdoc: { type: id, ref: refuser }}]
+              other: {type: id, ref: refuser},
+              array: [{type: id, ref: refuser}],
+              nested: [{subdoc: {type: id, ref: refuser}}]
             }]
           });
 
@@ -81,24 +81,24 @@ describe('model: populate:', function() {
             _id: construct[id](),
             name: 'Fan 2',
             email: 'fan2@learnboost.com'
-          }, function(err, fan1, fan2) {
+          }, function (err, fan1, fan2) {
             assert.ifError(err);
             u1 = fan1;
 
             B.create({
               title: 'Woot',
               fans: [fan1, fan2],
-              adhoc: [{ subdoc: fan2, subarray: [{ things: [fan1] }]}],
+              adhoc: [{subdoc: fan2, subarray: [{things: [fan1]}]}],
               _creator: fan1,
-              embed: [{ other: fan1, array: [fan1, fan2] }, { other: fan2, array: [fan2, fan1] }]
+              embed: [{other: fan1, array: [fan1, fan2]}, {other: fan2, array: [fan2, fan1]}]
             }, {
               title: 'Woot2',
               fans: [fan2, fan1],
-              adhoc: [{ subdoc: fan1, subarray: [{ things: [fan2] }]}],
+              adhoc: [{subdoc: fan1, subarray: [{things: [fan2]}]}],
               _creator: fan1,
               _creator: fan2,
-              embed: [{ other: fan2, array: [fan2, fan1] }, { other: fan1, array: [fan1, fan2] }]
-            }, function(err, post1, post2) {
+              embed: [{other: fan2, array: [fan2, fan1]}, {other: fan1, array: [fan1, fan2]}]
+            }, function (err, post1, post2) {
               assert.ifError(err);
               b1 = post1;
               b2 = post2;
@@ -107,24 +107,24 @@ describe('model: populate:', function() {
           });
         });
 
-        after(function(done) {
+        after(function (done) {
           db.close(done);
         });
 
         function userLiteral(name) {
-          return { _id: construct[id](), name: name };
+          return {_id: construct[id](), name: name};
         }
 
         function user(name) {
           return new U(userLiteral(name));
         }
 
-        it('if a document', function(done) {
+        it('if a document', function (done) {
           B.findById(b1)
            .populate('fans _creator embed.other embed.array embed.nested.subdoc')
-           .populate({ path: 'adhoc.subdoc', model: refuser })
-           .populate({ path: 'adhoc.subarray.things', model: refuser })
-           .exec(function(err, doc) {
+           .populate({path: 'adhoc.subdoc', model: refuser})
+           .populate({path: 'adhoc.subarray.things', model: refuser})
+           .exec(function (err, doc) {
              assert.ifError(err);
 
              var user3 = user('user3');
@@ -147,7 +147,7 @@ describe('model: populate:', function() {
              doc.fans.addToSet(user7);
              assert.deepEqual(doc.fans[5].toObject(), user7.toObject());
 
-             doc.fans.forEach(function(doc) {
+             doc.fans.forEach(function (doc) {
                assert.ok(doc instanceof U);
              });
 
@@ -186,7 +186,7 @@ describe('model: populate:', function() {
              assert.deepEqual(doc.embed[0].other.toObject(), user1b.toObject());
 
              var user1c = user('user2c');
-             doc.embed[0].nested = [{ subdoc: user1c }];
+             doc.embed[0].nested = [{subdoc: user1c}];
              assert.deepEqual(doc.embed[0].nested[0].subdoc.toObject(), user1c.toObject());
 
             // embedded without declared ref in schema
@@ -198,9 +198,9 @@ describe('model: populate:', function() {
              doc.adhoc[0].subarray[0].things.push(user2b);
              assert.deepEqual(doc.adhoc[0].subarray[0].things[1].toObject(), user2b.toObject());
 
-             doc.save(function(err) {
+             doc.save(function (err) {
                assert.ifError(err);
-               B.findById(b1).exec(function(err, doc) {
+               B.findById(b1).exec(function (err, doc) {
                 // db is closed in after()
                  assert.ifError(err);
                  assert.equal(8, doc.fans.length);
@@ -220,12 +220,12 @@ describe('model: populate:', function() {
            });
         });
 
-        it('if an object', function(done) {
+        it('if an object', function (done) {
           B.findById(b2)
            .populate('fans _creator embed.other embed.array embed.nested.subdoc')
-           .populate({ path: 'adhoc.subdoc', model: refuser })
-           .populate({ path: 'adhoc.subarray.things', model: refuser })
-           .exec(function(err, doc) {
+           .populate({path: 'adhoc.subdoc', model: refuser})
+           .populate({path: 'adhoc.subarray.things', model: refuser})
+           .exec(function (err, doc) {
              assert.ifError(err);
 
              var name = 'fan1';
@@ -239,7 +239,7 @@ describe('model: populate:', function() {
              assert.equal(name, doc.fans[3].name);
 
              name = 'fan3';
-             doc.fans.splice(2,1,userLiteral(name));
+             doc.fans.splice(2, 1, userLiteral(name));
              assert.ok(doc.fans[2]._id);
              assert.equal(name, doc.fans[2].name);
 
@@ -258,7 +258,7 @@ describe('model: populate:', function() {
              assert.ok(doc.fans[0]._id);
              assert.equal(name, doc.fans[0].name);
 
-             doc.fans.forEach(function(doc) {
+             doc.fans.forEach(function (doc) {
                assert.ok(doc instanceof U);
              });
 
@@ -287,7 +287,7 @@ describe('model: populate:', function() {
 
              name = 'user1c';
              var user1c = userLiteral(name);
-             doc.embed[0].nested = [{ subdoc: user1c }];
+             doc.embed[0].nested = [{subdoc: user1c}];
              assert.equal(name, doc.embed[0].nested[0].subdoc.name);
              var user1cId = doc.embed[0].nested[0].subdoc._id;
 
@@ -304,9 +304,9 @@ describe('model: populate:', function() {
              assert.deepEqual(name, doc.adhoc[0].subarray[0].things[1].name);
              var user2bId = doc.adhoc[0].subarray[0].things[1]._id;
 
-             doc.save(function(err) {
+             doc.save(function (err) {
                assert.ifError(err);
-               B.findById(b2).exec(function(err, doc) {
+               B.findById(b2).exec(function (err, doc) {
                 // db is closed in after()
                  assert.ifError(err);
                  assert.equal(6, doc.fans.length);
@@ -323,7 +323,6 @@ describe('model: populate:', function() {
              });
            });
         });
-
       });
     });
   });
diff --git a/test/model.populate.test.js b/test/model.populate.test.js
index 1bf00862ec8..f10512fc9ac 100644
--- a/test/model.populate.test.js
+++ b/test/model.populate.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Test dependencies.
  */
@@ -23,10 +22,10 @@ var start = require('./common'),
 var User = new Schema({
   name: String,
   email: String,
-  gender: { type: String, enum: ['male', 'female'], default: 'male' },
-  age: { type: Number, default: 21 },
-  blogposts: [{ type: ObjectId, ref: 'RefBlogPost' }],
-  followers: [{ type: ObjectId, ref: 'RefUser' }]
+  gender: {type: String, enum: ['male', 'female'], default: 'male'},
+  age: {type: Number, default: 21},
+  blogposts: [{type: ObjectId, ref: 'RefBlogPost'}],
+  followers: [{type: ObjectId, ref: 'RefUser'}]
 });
 
 /**
@@ -34,8 +33,8 @@ var User = new Schema({
  */
 
 var Comment = new Schema({
-  asers: [{ type: ObjectId, ref: 'RefUser' }],
-  _creator: { type: ObjectId, ref: 'RefUser' },
+  asers: [{type: ObjectId, ref: 'RefUser'}],
+  _creator: {type: ObjectId, ref: 'RefUser'},
   content: String
 });
 
@@ -44,10 +43,10 @@ var Comment = new Schema({
  */
 
 var BlogPost = new Schema({
-  _creator: { type: ObjectId, ref: 'RefUser' },
+  _creator: {type: ObjectId, ref: 'RefUser'},
   title: String,
   comments: [Comment],
-  fans: [{ type: ObjectId, ref: 'RefUser' }]
+  fans: [{type: ObjectId, ref: 'RefUser'}]
 });
 
 var posts = 'blogposts_' + random(),
@@ -62,30 +61,31 @@ mongoose.model('RefAlternateUser', User);
  * Tests.
  */
 
-describe('model: populate:', function() {
-  it('populating array of object', function(done) {
+describe('model: populate:', function () {
+  it('populating array of object', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
-    User.create({ name: 'User 1' }, function(err, user1) {
+    User.create({name: 'User 1'}, function (err, user1) {
       assert.ifError(err);
 
-      User.create({ name: 'User 2' }, function(err, user2) {
+      User.create({name: 'User 2'}, function (err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           _creator: user1._id,
           comments: [
-            { _creator: user1._id, content: 'Woot woot' },
-            { _creator: user2._id, content: 'Wha wha' }
+            {_creator: user1._id, content: 'Woot woot'},
+            {_creator: user2._id, content: 'Wha wha'}
           ]
-        }, function(err, post) {
+        }, function (err, post) {
           assert.ifError(err);
 
-          assert.doesNotThrow(function() {
-            post.populate('comments', function() {});
+          assert.doesNotThrow(function () {
+            post.populate('comments', function () {
+            });
           });
           db.close(done);
         });
@@ -93,58 +93,58 @@ describe('model: populate:', function() {
     });
   });
 
-  it('deep population (gh-3103)', function(done) {
+  it('deep population (gh-3103)', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
-    User.create({ name: 'User 01' }, function(err, user1) {
+    User.create({name: 'User 01'}, function (err, user1) {
       assert.ifError(err);
 
-      User.create({ name: 'User 02', followers: [user1._id] }, function(err, user2) {
+      User.create({name: 'User 02', followers: [user1._id]}, function (err, user2) {
         assert.ifError(err);
 
-        User.create({ name: 'User 03', followers: [user2._id] }, function(err, user3) {
+        User.create({name: 'User 03', followers: [user2._id]}, function (err, user3) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'w00tabulous',
             _creator: user3._id
-          }, function(err, post) {
+          }, function (err, post) {
             assert.ifError(err);
 
-            assert.doesNotThrow(function() {
+            assert.doesNotThrow(function () {
               BlogPost
-                .findById(post._id)
-                .select('_creator')
-                .populate({
-                  path: '_creator',
-                  model: 'RefUser',
+              .findById(post._id)
+              .select('_creator')
+              .populate({
+                path: '_creator',
+                model: 'RefUser',
+                select: 'name followers',
+                populate: [{
+                  path: 'followers',
                   select: 'name followers',
-                  populate: [{
+                  options: {limit: 5},
+                  populate: {  // can also use a single object instead of array of objects
                     path: 'followers',
-                    select: 'name followers',
-                    options: { limit: 5 },
-                    populate: {  // can also use a single object instead of array of objects
-                      path: 'followers',
-                      select: 'name',
-                      options: { limit: 2 }
-                    }
-                  }]
-                })
-                .exec(function(err, post) {
-                  db.close();
-                  assert.ifError(err);
-                  assert.ok(post._creator);
-                  assert.equal(post._creator.name,'User 03');
-                  assert.ok(post._creator.followers);
-                  assert.ok(post._creator.followers[0]);
-                  assert.equal(post._creator.followers[0].name,'User 02');
-                  assert.ok(post._creator.followers[0].followers);
-                  assert.ok(post._creator.followers[0].followers[0]);
-                  assert.equal(post._creator.followers[0].followers[0].name,'User 01');
-                  done();
-                });
+                    select: 'name',
+                    options: {limit: 2}
+                  }
+                }]
+              })
+              .exec(function (err, post) {
+                db.close();
+                assert.ifError(err);
+                assert.ok(post._creator);
+                assert.equal(post._creator.name, 'User 03');
+                assert.ok(post._creator.followers);
+                assert.ok(post._creator.followers[0]);
+                assert.equal(post._creator.followers[0].name, 'User 02');
+                assert.ok(post._creator.followers[0].followers);
+                assert.ok(post._creator.followers[0].followers[0]);
+                assert.equal(post._creator.followers[0].followers[0].name, 'User 01');
+                done();
+              });
             });
           });
         });
@@ -152,7 +152,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('deep population with refs (gh-3507)', function(done) {
+  it('deep population with refs (gh-3507)', function (done) {
     var db = start();
     // handler schema
     var handlerSchema = new Schema({
@@ -162,25 +162,25 @@ describe('model: populate:', function() {
     // task schema
     var taskSchema = new Schema({
       name: String,
-      handler: { type: Schema.Types.ObjectId, ref: 'gh3507_0' }
+      handler: {type: Schema.Types.ObjectId, ref: 'gh3507_0'}
     });
 
     // application schema
     var applicationSchema = new Schema({
       name: String,
-      tasks: [{ type: Schema.Types.ObjectId, ref: 'gh3507_1' }]
+      tasks: [{type: Schema.Types.ObjectId, ref: 'gh3507_1'}]
     });
 
     var Handler = db.model('gh3507_0', handlerSchema);
     var Task = db.model('gh3507_1', taskSchema);
     var Application = db.model('gh3507_2', applicationSchema);
 
-    Handler.create({ name: 'test' }, function(error, doc) {
+    Handler.create({name: 'test'}, function (error, doc) {
       assert.ifError(error);
-      Task.create({ name: 'test2', handler: doc._id }, function(error, doc) {
+      Task.create({name: 'test2', handler: doc._id}, function (error, doc) {
         assert.ifError(error);
-        var obj = { name: 'test3', tasks: [doc._id] };
-        Application.create(obj, function(error, doc) {
+        var obj = {name: 'test3', tasks: [doc._id]};
+        Application.create(obj, function (error, doc) {
           assert.ifError(error);
           test(doc._id);
         });
@@ -189,19 +189,19 @@ describe('model: populate:', function() {
 
     function test(id) {
       Application.
-        findById(id).
-        populate([
-          { path: 'tasks', populate: { path: 'handler' } }
-        ]).
-        exec(function(error, doc) {
-          assert.ifError(error);
-          assert.ok(doc.tasks[0].handler._id);
-          db.close(done);
-        });
+      findById(id).
+      populate([
+        {path: 'tasks', populate: {path: 'handler'}}
+      ]).
+      exec(function (error, doc) {
+        assert.ifError(error);
+        assert.ok(doc.tasks[0].handler._id);
+        db.close(done);
+      });
     }
   });
 
-  it('populating a single ref', function(done) {
+  it('populating a single ref', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -209,19 +209,19 @@ describe('model: populate:', function() {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function(err, creator) {
+    }, function (err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator')
-        .exec(function(err, post) {
+        .exec(function (err, post) {
           assert.ifError(err);
 
           assert.ok(post._creator instanceof User);
@@ -233,20 +233,20 @@ describe('model: populate:', function() {
     });
   });
 
-  it('not failing on null as ref', function(done) {
+  it('not failing on null as ref', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create({
       title: 'woot',
       _creator: null
-    }, function(err, post) {
+    }, function (err, post) {
       assert.ifError(err);
 
       BlogPost
       .findById(post._id)
       .populate('_creator')
-      .exec(function(err, post) {
+      .exec(function (err, post) {
         assert.ifError(err);
 
         assert.equal(post._creator, null);
@@ -255,24 +255,24 @@ describe('model: populate:', function() {
     });
   });
 
-  it('not failing on empty object as ref', function(done) {
+  it('not failing on empty object as ref', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create(
-      { title: 'woot' },
-      function(err, post) {
-        assert.ifError(err);
+        {title: 'woot'},
+        function (err, post) {
+          assert.ifError(err);
 
-        BlogPost.
-         findByIdAndUpdate(post._id, { $set: { _creator: {} } }, function(err) {
-           assert.ok(err);
-           db.close(done);
-         });
-      });
+          BlogPost.
+          findByIdAndUpdate(post._id, {$set: {_creator: {}}}, function (err) {
+            assert.ok(err);
+            db.close(done);
+          });
+        });
   });
 
-  it('across DBs', function(done) {
+  it('across DBs', function (done) {
     var db = start(),
         db2 = db.useDb('mongoose_test2'),
         BlogPost = db.model('RefBlogPost', posts + '2'),
@@ -281,19 +281,19 @@ describe('model: populate:', function() {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function(err, creator) {
+    }, function (err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator._id
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
         BlogPost
         .findById(post._id)
         .populate('_creator', 'name', User)
-        .exec(function(err, post) {
-          db2.db.dropDatabase(function() {
+        .exec(function (err, post) {
+          db2.db.dropDatabase(function () {
             db.close();
             db2.close();
             assert.ifError(err);
@@ -305,7 +305,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('an error in single ref population propagates', function(done) {
+  it('an error in single ref population propagates', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts + '1'),
         User = db.model('RefUser', users + '1');
@@ -313,21 +313,21 @@ describe('model: populate:', function() {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function(err, creator) {
+    }, function (err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
         var origFind = User.find;
 
         // mock an error
-        User.find = function() {
-          var args = Array.prototype.map.call(arguments, function(arg) {
-            return 'function' == typeof arg ? function() {
+        User.find = function () {
+          var args = Array.prototype.map.call(arguments, function (arg) {
+            return 'function' == typeof arg ? function () {
               arg(new Error('woot'));
             } : arg;
           });
@@ -337,7 +337,7 @@ describe('model: populate:', function() {
         BlogPost
         .findById(post._id)
         .populate('_creator')
-        .exec(function(err) {
+        .exec(function (err) {
           db.close();
           assert.ok(err instanceof Error);
           assert.equal('woot', err.message);
@@ -347,7 +347,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating with partial fields selection', function(done) {
+  it('populating with partial fields selection', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -355,32 +355,32 @@ describe('model: populate:', function() {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function(err, creator) {
+    }, function (err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator', 'email')
-        .exec(function(err, post) {
+        .exec(function (err, post) {
           db.close();
           assert.ifError(err);
 
           assert.ok(post._creator instanceof User);
           assert.equal(false, post._creator.isInit('name'));
-          assert.equal(post._creator.email,'rauchg@gmail.com');
+          assert.equal(post._creator.email, 'rauchg@gmail.com');
           done();
         });
       });
     });
   });
 
-  it('population of single oid with partial field selection and filter', function(done) {
+  it('population of single oid with partial field selection and filter', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', 'blogposts_' + random()),
         User = db.model('RefUser', 'users_' + random());
@@ -388,26 +388,26 @@ describe('model: populate:', function() {
     User.create({
       name: 'Banana',
       email: 'cats@example.com'
-    }, function(err, creator) {
+    }, function (err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
-        .populate('_creator', 'email', { name: 'Peanut' })
-        .exec(function(err, post) {
+        .populate('_creator', 'email', {name: 'Peanut'})
+        .exec(function (err, post) {
           assert.ifError(err);
           assert.strictEqual(post._creator, null);
 
           BlogPost
           .findById(post._id)
-          .populate('_creator', 'email', { name: 'Banana' })
-          .exec(function(err, post) {
+          .populate('_creator', 'email', {name: 'Banana'})
+          .exec(function (err, post) {
             db.close();
             assert.ifError(err);
             assert.ok(post._creator instanceof User);
@@ -420,34 +420,35 @@ describe('model: populate:', function() {
     });
   });
 
-  it('population of undefined fields in a collection of docs', function(done) {
+  it('population of undefined fields in a collection of docs', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', 'blogposts_' + random()),
         User = db.model('RefUser', 'users_' + random());
     User.create({
       name: 'Eloy',
       email: 'eloytoro@gmail.com'
-    }, function(err, user) {
+    }, function (err, user) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'I have a user ref',
         _creator: user
-      }, function(err) {
+      }, function (err) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'I don\'t'
-        }, function(err) {
+        }, function (err) {
           assert.ifError(err);
           BlogPost
           .find()
           .populate('_creator')
-          .exec(function(err, posts) {
+          .exec(function (err, posts) {
             db.close();
-            posts.forEach(function(post) {
-              if ('_creator' in post)
+            posts.forEach(function (post) {
+              if ('_creator' in post) {
                 assert.ok(post._creator !== null);
+              }
             });
             done();
           });
@@ -456,7 +457,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('population and changing a reference', function(done) {
+  it('population and changing a reference', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -464,45 +465,45 @@ describe('model: populate:', function() {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function(err, creator) {
+    }, function (err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator')
-        .exec(function(err, post) {
+        .exec(function (err, post) {
           assert.ifError(err);
 
           assert.ok(post._creator instanceof User);
-          assert.equal(post._creator.name,'Guillermo');
-          assert.equal(post._creator.email,'rauchg@gmail.com');
+          assert.equal(post._creator.name, 'Guillermo');
+          assert.equal(post._creator.email, 'rauchg@gmail.com');
 
           User.create({
             name: 'Aaron',
             email: 'aaron.heckmann@gmail.com'
-          }, function(err, newCreator) {
+          }, function (err, newCreator) {
             assert.ifError(err);
 
             post._creator = newCreator._id;
             assert.equal(newCreator._id, String(post._creator));
 
-            post.save(function(err) {
+            post.save(function (err) {
               assert.ifError(err);
 
               BlogPost
               .findById(post._id)
               .populate('_creator')
-              .exec(function(err, post) {
+              .exec(function (err, post) {
                 db.close();
                 assert.ifError(err);
-                assert.equal(post._creator.name,'Aaron');
-                assert.equal(post._creator.email,'aaron.heckmann@gmail.com');
+                assert.equal(post._creator.name, 'Aaron');
+                assert.equal(post._creator.email, 'aaron.heckmann@gmail.com');
                 done();
               });
             });
@@ -512,7 +513,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating with partial fields selection and changing ref', function(done) {
+  it('populating with partial fields selection and changing ref', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -520,42 +521,42 @@ describe('model: populate:', function() {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function(err, creator) {
+    }, function (err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator', {'name': 1})
-        .exec(function(err, post) {
+        .exec(function (err, post) {
           assert.ifError(err);
 
           assert.ok(post._creator instanceof User);
-          assert.equal(post._creator.name,'Guillermo');
+          assert.equal(post._creator.name, 'Guillermo');
 
           User.create({
             name: 'Aaron',
             email: 'aaron@learnboost.com'
-          }, function(err, newCreator) {
+          }, function (err, newCreator) {
             assert.ifError(err);
 
             post._creator = newCreator._id;
-            post.save(function(err) {
+            post.save(function (err) {
               assert.ifError(err);
 
               BlogPost
               .findById(post._id)
               .populate('_creator', '-email')
-              .exec(function(err, post) {
+              .exec(function (err, post) {
                 db.close();
                 assert.ifError(err);
 
-                assert.equal(post._creator.name,'Aaron');
+                assert.equal(post._creator.name, 'Aaron');
                 assert.ok(!post._creator.email);
                 done();
               });
@@ -566,7 +567,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating an array of refs and fetching many', function(done) {
+  it('populating an array of refs and fetching many', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -574,43 +575,43 @@ describe('model: populate:', function() {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function(err, fan1) {
+    }, function (err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function(err, fan2) {
+      }, function (err, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           fans: [fan1, fan2]
-        }, function(err, post1) {
+        }, function (err, post1) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan2, fan1]
-          }, function(err, post2) {
+          }, function (err, post2) {
             assert.ifError(err);
 
             BlogPost
-            .find({ _id: { $in: [post1._id, post2._id ] } })
+            .find({_id: {$in: [post1._id, post2._id]}})
             .populate('fans')
-            .exec(function(err, blogposts) {
+            .exec(function (err, blogposts) {
               db.close();
               assert.ifError(err);
 
-              assert.equal(blogposts[0].fans[0].name,'Fan 1');
-              assert.equal(blogposts[0].fans[0].email,'fan1@learnboost.com');
-              assert.equal(blogposts[0].fans[1].name,'Fan 2');
-              assert.equal(blogposts[0].fans[1].email,'fan2@learnboost.com');
+              assert.equal(blogposts[0].fans[0].name, 'Fan 1');
+              assert.equal(blogposts[0].fans[0].email, 'fan1@learnboost.com');
+              assert.equal(blogposts[0].fans[1].name, 'Fan 2');
+              assert.equal(blogposts[0].fans[1].email, 'fan2@learnboost.com');
 
-              assert.equal(blogposts[1].fans[0].name,'Fan 2');
-              assert.equal(blogposts[1].fans[0].email,'fan2@learnboost.com');
-              assert.equal(blogposts[1].fans[1].name,'Fan 1');
-              assert.equal(blogposts[1].fans[1].email,'fan1@learnboost.com');
+              assert.equal(blogposts[1].fans[0].name, 'Fan 2');
+              assert.equal(blogposts[1].fans[0].email, 'fan2@learnboost.com');
+              assert.equal(blogposts[1].fans[1].name, 'Fan 1');
+              assert.equal(blogposts[1].fans[1].email, 'fan1@learnboost.com');
               done();
             });
           });
@@ -619,7 +620,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('an error in array reference population propagates', function(done) {
+  it('an error in array reference population propagates', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts + '2'),
         User = db.model('RefUser', users + '2');
@@ -627,32 +628,32 @@ describe('model: populate:', function() {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function(err, fan1) {
+    }, function (err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function(err, fan2) {
+      }, function (err, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           fans: [fan1, fan2]
-        }, function(err, post1) {
+        }, function (err, post1) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan2, fan1]
-          }, function(err, post2) {
+          }, function (err, post2) {
             assert.ifError(err);
 
             // mock an error
             var origFind = User.find;
-            User.find = function() {
-              var args = Array.prototype.map.call(arguments, function(arg) {
-                return 'function' == typeof arg ? function() {
+            User.find = function () {
+              var args = Array.prototype.map.call(arguments, function (arg) {
+                return 'function' == typeof arg ? function () {
                   arg(new Error('woot 2'));
                 } : arg;
               });
@@ -660,13 +661,13 @@ describe('model: populate:', function() {
             };
 
             BlogPost
-            .find({ $or: [{ _id: post1._id }, { _id: post2._id }] })
+            .find({$or: [{_id: post1._id}, {_id: post2._id}]})
             .populate('fans')
-            .exec(function(err) {
+            .exec(function (err) {
               db.close();
 
               assert.ok(err instanceof Error);
-              assert.equal(err.message,'woot 2');
+              assert.equal(err.message, 'woot 2');
               done();
             });
           });
@@ -675,7 +676,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating an array of references with fields selection', function(done) {
+  it('populating an array of references with fields selection', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -683,35 +684,35 @@ describe('model: populate:', function() {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function(err, fan1) {
+    }, function (err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function(err, fan2) {
+      }, function (err, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           fans: [fan1, fan2]
-        }, function(err, post1) {
+        }, function (err, post1) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan2, fan1]
-          }, function(err, post2) {
+          }, function (err, post2) {
             assert.ifError(err);
 
             BlogPost
-            .find({ _id: { $in: [post1._id, post2._id ] } })
+            .find({_id: {$in: [post1._id, post2._id]}})
             .populate('fans', 'name')
-            .exec(function(err, blogposts) {
+            .exec(function (err, blogposts) {
               db.close();
               assert.ifError(err);
 
-              assert.equal(blogposts[0].fans[0].name,'Fan 1');
+              assert.equal(blogposts[0].fans[0].name, 'Fan 1');
               assert.equal(blogposts[0].fans[0].isInit('email'), false);
               assert.equal(blogposts[0].fans[1].name, 'Fan 2');
               assert.equal(blogposts[0].fans[1].isInit('email'), false);
@@ -730,7 +731,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating an array of references and filtering', function(done) {
+  it('populating an array of references and filtering', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -738,77 +739,76 @@ describe('model: populate:', function() {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function(err, fan1) {
+    }, function (err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com',
         gender: 'female'
-      }, function(err, fan2) {
+      }, function (err, fan2) {
         assert.ifError(err);
 
         User.create({
           name: 'Fan 3',
           email: 'fan3@learnboost.com',
           gender: 'female'
-        }, function(err, fan3) {
+        }, function (err, fan3) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan1, fan2, fan3]
-          }, function(err, post1) {
+          }, function (err, post1) {
             assert.ifError(err);
 
             BlogPost.create({
               title: 'Woot',
               fans: [fan3, fan2, fan1]
-            }, function(err, post2) {
+            }, function (err, post2) {
               assert.ifError(err);
 
               BlogPost
-              .find({ _id: { $in: [post1._id, post2._id ] } })
-              .populate('fans', '', { gender: 'female', _id: { $in: [fan2] }})
-              .exec(function(err, blogposts) {
+              .find({_id: {$in: [post1._id, post2._id]}})
+              .populate('fans', '', {gender: 'female', _id: {$in: [fan2]}})
+              .exec(function (err, blogposts) {
                 assert.ifError(err);
 
                 assert.equal(blogposts[0].fans.length, 1);
                 assert.equal(blogposts[0].fans[0].gender, 'female');
-                assert.equal(blogposts[0].fans[0].name,'Fan 2');
-                assert.equal(blogposts[0].fans[0].email,'fan2@learnboost.com');
+                assert.equal(blogposts[0].fans[0].name, 'Fan 2');
+                assert.equal(blogposts[0].fans[0].email, 'fan2@learnboost.com');
 
                 assert.equal(blogposts[1].fans.length, 1);
-                assert.equal(blogposts[1].fans[0].gender,'female');
-                assert.equal(blogposts[1].fans[0].name,'Fan 2');
-                assert.equal(blogposts[1].fans[0].email,'fan2@learnboost.com');
+                assert.equal(blogposts[1].fans[0].gender, 'female');
+                assert.equal(blogposts[1].fans[0].name, 'Fan 2');
+                assert.equal(blogposts[1].fans[0].email, 'fan2@learnboost.com');
 
                 BlogPost
-                .find({ _id: { $in: [post1._id, post2._id ] } })
-                .populate('fans', false, { gender: 'female' })
-                .exec(function(err, blogposts) {
+                .find({_id: {$in: [post1._id, post2._id]}})
+                .populate('fans', false, {gender: 'female'})
+                .exec(function (err, blogposts) {
                   db.close();
                   assert.ifError(err);
 
                   assert.strictEqual(blogposts[0].fans.length, 2);
-                  assert.equal(blogposts[0].fans[0].gender,'female');
-                  assert.equal(blogposts[0].fans[0].name,'Fan 2');
-                  assert.equal(blogposts[0].fans[0].email,'fan2@learnboost.com');
-                  assert.equal(blogposts[0].fans[1].gender,'female');
-                  assert.equal(blogposts[0].fans[1].name,'Fan 3');
-                  assert.equal(blogposts[0].fans[1].email,'fan3@learnboost.com');
+                  assert.equal(blogposts[0].fans[0].gender, 'female');
+                  assert.equal(blogposts[0].fans[0].name, 'Fan 2');
+                  assert.equal(blogposts[0].fans[0].email, 'fan2@learnboost.com');
+                  assert.equal(blogposts[0].fans[1].gender, 'female');
+                  assert.equal(blogposts[0].fans[1].name, 'Fan 3');
+                  assert.equal(blogposts[0].fans[1].email, 'fan3@learnboost.com');
 
                   assert.strictEqual(blogposts[1].fans.length, 2);
-                  assert.equal(blogposts[1].fans[0].gender,'female');
-                  assert.equal(blogposts[1].fans[0].name,'Fan 3');
-                  assert.equal(blogposts[1].fans[0].email,'fan3@learnboost.com');
-                  assert.equal(blogposts[1].fans[1].gender,'female');
-                  assert.equal(blogposts[1].fans[1].name,'Fan 2');
-                  assert.equal(blogposts[1].fans[1].email,'fan2@learnboost.com');
+                  assert.equal(blogposts[1].fans[0].gender, 'female');
+                  assert.equal(blogposts[1].fans[0].name, 'Fan 3');
+                  assert.equal(blogposts[1].fans[0].email, 'fan3@learnboost.com');
+                  assert.equal(blogposts[1].fans[1].gender, 'female');
+                  assert.equal(blogposts[1].fans[1].name, 'Fan 2');
+                  assert.equal(blogposts[1].fans[1].email, 'fan2@learnboost.com');
 
                   done();
                 });
-
               });
             });
           });
@@ -817,7 +817,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating an array of references and multi-filtering', function(done) {
+  it('populating an array of references and multi-filtering', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -825,14 +825,14 @@ describe('model: populate:', function() {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function(err, fan1) {
+    }, function (err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com',
         gender: 'female'
-      }, function(err, fan2) {
+      }, function (err, fan2) {
         assert.ifError(err);
 
         User.create({
@@ -840,49 +840,49 @@ describe('model: populate:', function() {
           email: 'fan3@learnboost.com',
           gender: 'female',
           age: 25
-        }, function(err, fan3) {
+        }, function (err, fan3) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan1, fan2, fan3]
-          }, function(err, post1) {
+          }, function (err, post1) {
             assert.ifError(err);
 
             BlogPost.create({
               title: 'Woot',
               fans: [fan3, fan2, fan1]
-            }, function(err, post2) {
+            }, function (err, post2) {
               assert.ifError(err);
 
               BlogPost
-              .find({ _id: { $in: [post1._id, post2._id ] } })
-              .populate('fans', undefined, { _id: fan3 })
-              .exec(function(err, blogposts) {
+              .find({_id: {$in: [post1._id, post2._id]}})
+              .populate('fans', undefined, {_id: fan3})
+              .exec(function (err, blogposts) {
                 assert.ifError(err);
 
                 assert.equal(blogposts[0].fans.length, 1);
-                assert.equal(blogposts[0].fans[0].gender,'female');
-                assert.equal(blogposts[0].fans[0].name,'Fan 3');
-                assert.equal(blogposts[0].fans[0].email,'fan3@learnboost.com');
+                assert.equal(blogposts[0].fans[0].gender, 'female');
+                assert.equal(blogposts[0].fans[0].name, 'Fan 3');
+                assert.equal(blogposts[0].fans[0].email, 'fan3@learnboost.com');
                 assert.equal(blogposts[0].fans[0].age, 25);
 
-                assert.equal(blogposts[1].fans.length,1);
-                assert.equal(blogposts[1].fans[0].gender,'female');
-                assert.equal(blogposts[1].fans[0].name,'Fan 3');
-                assert.equal(blogposts[1].fans[0].email,'fan3@learnboost.com');
+                assert.equal(blogposts[1].fans.length, 1);
+                assert.equal(blogposts[1].fans[0].gender, 'female');
+                assert.equal(blogposts[1].fans[0].name, 'Fan 3');
+                assert.equal(blogposts[1].fans[0].email, 'fan3@learnboost.com');
                 assert.equal(blogposts[1].fans[0].age, 25);
 
                 BlogPost
-                .find({ _id: { $in: [post1._id, post2._id ] } })
-                .populate('fans', 0, { gender: 'female' })
-                .exec(function(err, blogposts) {
+                .find({_id: {$in: [post1._id, post2._id]}})
+                .populate('fans', 0, {gender: 'female'})
+                .exec(function (err, blogposts) {
                   db.close();
                   assert.ifError(err);
 
                   assert.equal(blogposts[0].fans.length, 2);
-                  assert.equal(blogposts[0].fans[0].gender,'female');
-                  assert.equal(blogposts[0].fans[0].name,'Fan 2');
+                  assert.equal(blogposts[0].fans[0].gender, 'female');
+                  assert.equal(blogposts[0].fans[0].name, 'Fan 2');
                   assert.equal(blogposts[0].fans[0].email, 'fan2@learnboost.com');
                   assert.equal(blogposts[0].fans[1].gender, 'female');
                   assert.equal(blogposts[0].fans[1].name, 'Fan 3');
@@ -908,7 +908,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating an array of references and multi-filtering with field selection', function(done) {
+  it('populating an array of references and multi-filtering with field selection', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -916,14 +916,14 @@ describe('model: populate:', function() {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function(err, fan1) {
+    }, function (err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com',
         gender: 'female'
-      }, function(err, fan2) {
+      }, function (err, fan2) {
         assert.ifError(err);
 
         User.create({
@@ -931,38 +931,38 @@ describe('model: populate:', function() {
           email: 'fan3@learnboost.com',
           gender: 'female',
           age: 25
-        }, function(err, fan3) {
+        }, function (err, fan3) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan1, fan2, fan3]
-          }, function(err, post1) {
+          }, function (err, post1) {
             assert.ifError(err);
 
             BlogPost.create({
               title: 'Woot',
               fans: [fan3, fan2, fan1]
-            }, function(err, post2) {
+            }, function (err, post2) {
               assert.ifError(err);
 
               BlogPost
-              .find({ _id: { $in: [post1._id, post2._id ] } })
-              .populate('fans', 'name email', { gender: 'female', age: 25 })
-              .exec(function(err, blogposts) {
+              .find({_id: {$in: [post1._id, post2._id]}})
+              .populate('fans', 'name email', {gender: 'female', age: 25})
+              .exec(function (err, blogposts) {
                 db.close();
                 assert.ifError(err);
 
                 assert.strictEqual(blogposts[0].fans.length, 1);
-                assert.equal(blogposts[0].fans[0].name,'Fan 3');
-                assert.equal(blogposts[0].fans[0].email,'fan3@learnboost.com');
+                assert.equal(blogposts[0].fans[0].name, 'Fan 3');
+                assert.equal(blogposts[0].fans[0].email, 'fan3@learnboost.com');
                 assert.equal(blogposts[0].fans[0].isInit('email'), true);
                 assert.equal(blogposts[0].fans[0].isInit('gender'), false);
                 assert.equal(blogposts[0].fans[0].isInit('age'), false);
 
                 assert.strictEqual(blogposts[1].fans.length, 1);
-                assert.equal(blogposts[1].fans[0].name,'Fan 3');
-                assert.equal(blogposts[1].fans[0].email,'fan3@learnboost.com');
+                assert.equal(blogposts[1].fans[0].name, 'Fan 3');
+                assert.equal(blogposts[1].fans[0].email, 'fan3@learnboost.com');
                 assert.equal(blogposts[1].fans[0].isInit('email'), true);
                 assert.equal(blogposts[1].fans[0].isInit('gender'), false);
                 assert.equal(blogposts[1].fans[0].isInit('age'), false);
@@ -976,7 +976,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating an array of refs changing one and removing one', function(done) {
+  it('populating an array of refs changing one and removing one', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -993,7 +993,7 @@ describe('model: populate:', function() {
     }, {
       name: 'Fan 4',
       email: 'fan4@learnboost.com'
-    }, function(err, fan1, fan2, fan3, fan4) {
+    }, function (err, fan1, fan2, fan3, fan4) {
       assert.ifError(err);
 
       BlogPost.create({
@@ -1002,50 +1002,50 @@ describe('model: populate:', function() {
       }, {
         title: 'Woot',
         fans: [fan2, fan1]
-      }, function(err, post1, post2) {
+      }, function (err, post1, post2) {
         assert.ifError(err);
 
         BlogPost
-        .find({ _id: { $in: [post1._id, post2._id ] } })
+        .find({_id: {$in: [post1._id, post2._id]}})
         .populate('fans', 'name')
-        .exec(function(err, blogposts) {
+        .exec(function (err, blogposts) {
           assert.ifError(err);
 
-          assert.equal(blogposts[0].fans[0].name,'Fan 1');
+          assert.equal(blogposts[0].fans[0].name, 'Fan 1');
           assert.equal(blogposts[0].fans[0].isInit('email'), false);
-          assert.equal(blogposts[0].fans[1].name,'Fan 2');
+          assert.equal(blogposts[0].fans[1].name, 'Fan 2');
           assert.equal(blogposts[0].fans[1].isInit('email'), false);
 
-          assert.equal(blogposts[1].fans[0].name,'Fan 2');
+          assert.equal(blogposts[1].fans[0].name, 'Fan 2');
           assert.equal(blogposts[1].fans[0].isInit('email'), false);
-          assert.equal(blogposts[1].fans[1].name,'Fan 1');
-          assert.equal(blogposts[1].fans[1].isInit('email'),false);
+          assert.equal(blogposts[1].fans[1].name, 'Fan 1');
+          assert.equal(blogposts[1].fans[1].isInit('email'), false);
 
           blogposts[1].fans = [fan3, fan4];
 
-          blogposts[1].save(function(err) {
+          blogposts[1].save(function (err) {
             assert.ifError(err);
 
             BlogPost
-            .findById(blogposts[1]._id, '', { populate: ['fans'] })
-            .exec(function(err, post) {
+            .findById(blogposts[1]._id, '', {populate: ['fans']})
+            .exec(function (err, post) {
               assert.ifError(err);
 
-              assert.equal(post.fans[0].name,'Fan 3');
-              assert.equal(post.fans[1].name,'Fan 4');
+              assert.equal(post.fans[0].name, 'Fan 3');
+              assert.equal(post.fans[1].name, 'Fan 4');
 
               post.fans.splice(0, 1);
-              post.save(function(err) {
+              post.save(function (err) {
                 assert.ifError(err);
 
                 BlogPost
                 .findById(post._id)
                 .populate('fans')
-                .exec(function(err, post) {
+                .exec(function (err, post) {
                   db.close();
                   assert.ifError(err);
-                  assert.equal(post.fans.length,1);
-                  assert.equal(post.fans[0].name,'Fan 4');
+                  assert.equal(post.fans.length, 1);
+                  assert.equal(post.fans[0].name, 'Fan 4');
                   done();
                 });
               });
@@ -1056,38 +1056,38 @@ describe('model: populate:', function() {
     });
   });
 
-  describe('populating sub docs', function() {
-    it('works with findById', function(done) {
+  describe('populating sub docs', function () {
+    it('works with findById', function (done) {
       var db = start(),
           BlogPost = db.model('RefBlogPost', posts),
           User = db.model('RefUser', users);
 
-      User.create({ name: 'User 1' }, function(err, user1) {
+      User.create({name: 'User 1'}, function (err, user1) {
         assert.ifError(err);
 
-        User.create({ name: 'User 2' }, function(err, user2) {
+        User.create({name: 'User 2'}, function (err, user2) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             _creator: user1._id,
             comments: [
-              { _creator: user1._id, content: 'Woot woot' },
-              { _creator: user2._id, content: 'Wha wha' }
+              {_creator: user1._id, content: 'Woot woot'},
+              {_creator: user2._id, content: 'Wha wha'}
             ]
-          }, function(err, post) {
+          }, function (err, post) {
             assert.ifError(err);
 
             BlogPost
             .findById(post._id)
             .populate('_creator')
             .populate('comments._creator')
-            .exec(function(err, post) {
+            .exec(function (err, post) {
               assert.ifError(err);
 
-              assert.equal(post._creator.name,'User 1');
-              assert.equal(post.comments[0]._creator.name,'User 1');
-              assert.equal(post.comments[1]._creator.name,'User 2');
+              assert.equal(post._creator.name, 'User 1');
+              assert.equal(post.comments[0]._creator.name, 'User 1');
+              assert.equal(post.comments[1]._creator.name, 'User 2');
               db.close(done);
             });
           });
@@ -1095,36 +1095,36 @@ describe('model: populate:', function() {
       });
     });
 
-    it('works when first doc returned has empty array for populated path (gh-1055)', function(done) {
+    it('works when first doc returned has empty array for populated path (gh-1055)', function (done) {
       var db = start(),
           BlogPost = db.model('RefBlogPost', posts),
           User = db.model('RefUser', users);
 
-      User.create({ name: 'gh-1055-1' }, { name: 'gh-1055-2' }, function(err, user1, user2) {
+      User.create({name: 'gh-1055-1'}, {name: 'gh-1055-2'}, function (err, user1, user2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'gh-1055 post1',
           _creator: user1._id,
           comments: []
-        },{
+        }, {
           title: 'gh-1055 post2',
           _creator: user1._id,
           comments: [
-            { _creator: user1._id, content: 'Woot woot', asers: [] },
-            { _creator: user2._id, content: 'Wha wha', asers: [user1, user2] }
+            {_creator: user1._id, content: 'Woot woot', asers: []},
+            {_creator: user2._id, content: 'Wha wha', asers: [user1, user2]}
           ]
-        }, function(err) {
+        }, function (err) {
           assert.ifError(err);
 
           var ran = false;
           BlogPost
-          .find({ title: /gh-1055/ })
+          .find({title: /gh-1055/})
           .sort('title')
           .select('comments')
           .populate('comments._creator')
           .populate('comments.asers')
-          .exec(function(err, posts) {
+          .exec(function (err, posts) {
             assert.equal(false, ran);
             ran = true;
             assert.ifError(err);
@@ -1138,12 +1138,12 @@ describe('model: populate:', function() {
     });
   });
 
-  it('clears cache when array has been re-assigned (gh-2176)', function(done) {
+  it('clears cache when array has been re-assigned (gh-2176)', function (done) {
     var db = start();
     var BlogPost = db.model('RefBlogPost', posts, 'gh-2176-1');
     var User = db.model('RefUser', users, 'gh-2176-2');
 
-    User.create({ name: 'aaron' }, { name: 'val' }, function(err, user1, user2) {
+    User.create({name: 'aaron'}, {name: 'val'}, function (err, user1, user2) {
       assert.ifError(err);
 
       BlogPost.create(
@@ -1152,32 +1152,32 @@ describe('model: populate:', function() {
           _creator: user1._id,
           comments: []
         },
-        function(err) {
-          assert.ifError(err);
-          BlogPost.
-            find({ title: 'gh-2176' }).
+          function (err) {
+            assert.ifError(err);
+            BlogPost.
+            find({title: 'gh-2176'}).
             populate('_creator').
-            exec(function(error, posts) {
+            exec(function (error, posts) {
               assert.ifError(error);
               assert.equal(1, posts.length);
               assert.equal('aaron', posts[0]._creator.name);
               posts[0]._creator = user2;
               assert.equal('val', posts[0]._creator.name);
-              posts[0].save(function(error, post) {
+              posts[0].save(function (error, post) {
                 assert.ifError(error);
                 assert.equal('val', post._creator.name);
-                posts[0].populate('_creator', function(error, doc) {
+                posts[0].populate('_creator', function (error, doc) {
                   assert.ifError(error);
                   assert.equal('val', doc._creator.name);
                   db.close(done);
                 });
               });
             });
-        });
+          });
     });
   });
 
-  it('populating subdocuments partially', function(done) {
+  it('populating subdocuments partially', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -1185,34 +1185,34 @@ describe('model: populate:', function() {
     User.create({
       name: 'User 1',
       email: 'user1@learnboost.com'
-    }, function(err, user1) {
+    }, function (err, user1) {
       assert.ifError(err);
 
       User.create({
         name: 'User 2',
         email: 'user2@learnboost.com'
-      }, function(err, user2) {
+      }, function (err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           comments: [
-            { _creator: user1, content: 'Woot woot' },
-            { _creator: user2, content: 'Wha wha' }
+            {_creator: user1, content: 'Woot woot'},
+            {_creator: user2, content: 'Wha wha'}
           ]
-        }, function(err, post) {
+        }, function (err, post) {
           assert.ifError(err);
 
           BlogPost
           .findById(post._id)
           .populate('comments._creator', 'email')
-          .exec(function(err, post) {
+          .exec(function (err, post) {
             db.close();
             assert.ifError(err);
 
-            assert.equal(post.comments[0]._creator.email,'user1@learnboost.com');
+            assert.equal(post.comments[0]._creator.email, 'user1@learnboost.com');
             assert.equal(post.comments[0]._creator.isInit('name'), false);
-            assert.equal(post.comments[1]._creator.email,'user2@learnboost.com');
+            assert.equal(post.comments[1]._creator.email, 'user2@learnboost.com');
             assert.equal(post.comments[1]._creator.isInit('name'), false);
 
             done();
@@ -1222,7 +1222,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating subdocuments partially with conditions', function(done) {
+  it('populating subdocuments partially with conditions', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -1230,34 +1230,34 @@ describe('model: populate:', function() {
     User.create({
       name: 'User 1',
       email: 'user1@learnboost.com'
-    }, function(err, user1) {
+    }, function (err, user1) {
       assert.ifError(err);
 
       User.create({
         name: 'User 2',
         email: 'user2@learnboost.com'
-      }, function(err, user2) {
+      }, function (err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           comments: [
-            { _creator: user1, content: 'Woot woot' },
-            { _creator: user2, content: 'Wha wha' }
+            {_creator: user1, content: 'Woot woot'},
+            {_creator: user2, content: 'Wha wha'}
           ]
-        }, function(err, post) {
+        }, function (err, post) {
           assert.ifError(err);
 
           BlogPost
           .findById(post._id)
-          .populate('comments._creator', {'email': 1}, { name: /User/ })
-          .exec(function(err, post) {
+          .populate('comments._creator', {'email': 1}, {name: /User/})
+          .exec(function (err, post) {
             db.close();
             assert.ifError(err);
 
-            assert.equal(post.comments[0]._creator.email,'user1@learnboost.com');
-            assert.equal(post.comments[0]._creator.isInit('name'),false);
-            assert.equal(post.comments[1]._creator.email,'user2@learnboost.com');
+            assert.equal(post.comments[0]._creator.email, 'user1@learnboost.com');
+            assert.equal(post.comments[0]._creator.isInit('name'), false);
+            assert.equal(post.comments[1]._creator.email, 'user2@learnboost.com');
             assert.equal(post.comments[1]._creator.isInit('name'), false);
 
             done();
@@ -1267,7 +1267,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating subdocs with invalid/missing subproperties', function(done) {
+  it('populating subdocs with invalid/missing subproperties', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -1275,79 +1275,79 @@ describe('model: populate:', function() {
     User.create({
       name: 'T-100',
       email: 'terminator100@learnboost.com'
-    }, function(err) {
+    }, function (err) {
       assert.ifError(err);
 
       User.create({
         name: 'T-1000',
         email: 'terminator1000@learnboost.com'
-      }, function(err, user2) {
+      }, function (err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           comments: [
-            { _creator: null, content: 'Woot woot' },
-            { _creator: user2, content: 'Wha wha' }
+            {_creator: null, content: 'Woot woot'},
+            {_creator: user2, content: 'Wha wha'}
           ]
-        }, function(err, post) {
+        }, function (err, post) {
           assert.ifError(err);
 
           // non-existant subprop
           BlogPost
           .findById(post._id)
           .populate('comments._idontexist', 'email')
-          .exec(function(err) {
+          .exec(function (err) {
             assert.ifError(err);
 
             // add a non-schema property to the document.
             BlogPost.collection.update(
-                { _id: post._id }
-              , { $set: { 'comments.0._idontexist': user2._id }}, function(err) {
-                assert.ifError(err);
-
-              // allow population of unknown property by passing model name.
-              // helpful when populating mapReduce results too.
-                BlogPost
-              .findById(post._id)
-              .populate('comments._idontexist', 'email', 'RefUser')
-              .exec(function(err, post) {
-                assert.ifError(err);
-                assert.ok(post);
-                assert.equal(post.comments.length, 2);
-                assert.ok(post.comments[0].get('_idontexist'));
-                assert.equal(String(post.comments[0].get('_idontexist')._id), user2.id);
-                assert.equal(post.comments[0].get('_idontexist').email, 'terminator1000@learnboost.com');
-                assert.equal(post.comments[0].get('_idontexist').isInit('name'), false);
-                assert.strictEqual(post.comments[0]._creator, null);
-                assert.equal(post.comments[1]._creator.toString(),user2.id);
-
-                // subprop is null in a doc
-                BlogPost
-                .findById(post._id)
-                .populate('comments._creator', 'email')
-                .exec(function(err, post) {
+                {_id: post._id}
+                , {$set: {'comments.0._idontexist': user2._id}}, function (err) {
                   assert.ifError(err);
 
-                  assert.ok(post.comments);
-                  assert.equal(post.comments.length,2);
-                  assert.strictEqual(post.comments[0]._creator, null);
-                  assert.strictEqual(post.comments[0].content, 'Woot woot');
-                  assert.equal(post.comments[1]._creator.email,'terminator1000@learnboost.com');
-                  assert.equal(post.comments[1]._creator.isInit('name'), false);
-                  assert.equal(post.comments[1].content,'Wha wha');
-
-                  db.close(done);
+                  // allow population of unknown property by passing model name.
+                  // helpful when populating mapReduce results too.
+                  BlogPost
+                  .findById(post._id)
+                  .populate('comments._idontexist', 'email', 'RefUser')
+                  .exec(function (err, post) {
+                    assert.ifError(err);
+                    assert.ok(post);
+                    assert.equal(post.comments.length, 2);
+                    assert.ok(post.comments[0].get('_idontexist'));
+                    assert.equal(String(post.comments[0].get('_idontexist')._id), user2.id);
+                    assert.equal(post.comments[0].get('_idontexist').email, 'terminator1000@learnboost.com');
+                    assert.equal(post.comments[0].get('_idontexist').isInit('name'), false);
+                    assert.strictEqual(post.comments[0]._creator, null);
+                    assert.equal(post.comments[1]._creator.toString(), user2.id);
+
+                    // subprop is null in a doc
+                    BlogPost
+                    .findById(post._id)
+                    .populate('comments._creator', 'email')
+                    .exec(function (err, post) {
+                      assert.ifError(err);
+
+                      assert.ok(post.comments);
+                      assert.equal(post.comments.length, 2);
+                      assert.strictEqual(post.comments[0]._creator, null);
+                      assert.strictEqual(post.comments[0].content, 'Woot woot');
+                      assert.equal(post.comments[1]._creator.email, 'terminator1000@learnboost.com');
+                      assert.equal(post.comments[1]._creator.isInit('name'), false);
+                      assert.equal(post.comments[1].content, 'Wha wha');
+
+                      db.close(done);
+                    });
+                  });
                 });
-              });
-              });
           });
         });
       });
     });
   });
 
-  it('properly handles limit per document (gh-2151)', function(done) {
+  it('properly handles limit per document (gh-2151)', function (done) {
     var db = start();
     var ObjectId = mongoose.Types.ObjectId;
 
@@ -1394,7 +1394,7 @@ describe('model: populate:', function() {
       friends: [userIds[0], userIds[1], userIds[2]]
     });
 
-    User.create(users, function(err) {
+    User.create(users, function (err) {
       assert.ifError(err);
 
       var blogposts = [];
@@ -1414,69 +1414,69 @@ describe('model: populate:', function() {
         author: userIds[2]
       });
 
-      BlogPost.create(blogposts, function(err) {
+      BlogPost.create(blogposts, function (err) {
         assert.ifError(err);
 
         BlogPost.
-          find({ tags: 'fun' }).
-          lean().
-          populate('author').
-          exec(function(err, docs) {
-            assert.ifError(err);
-            var opts = {
-              path: 'author.friends',
-              select: 'name',
-              options: { limit: 1 }
-            };
+        find({tags: 'fun'}).
+        lean().
+        populate('author').
+        exec(function (err, docs) {
+          assert.ifError(err);
+          var opts = {
+            path: 'author.friends',
+            select: 'name',
+            options: {limit: 1}
+          };
 
-            BlogPost.populate(docs, opts, function(err, docs) {
-              assert.ifError(err);
-              assert.equal(2, docs.length);
-              assert.equal(1, docs[0].author.friends.length);
-              assert.equal(1, docs[1].author.friends.length);
-              db.close(done);
-            });
+          BlogPost.populate(docs, opts, function (err, docs) {
+            assert.ifError(err);
+            assert.equal(2, docs.length);
+            assert.equal(1, docs[0].author.friends.length);
+            assert.equal(1, docs[1].author.friends.length);
+            db.close(done);
           });
+        });
       });
     });
   });
 
-  it('populating subdocuments partially with empty array (gh-481)', function(done) {
+  it('populating subdocuments partially with empty array (gh-481)', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create({
       title: 'Woot',
       comments: [] // EMPTY ARRAY
-    }, function(err, post) {
+    }, function (err, post) {
       assert.ifError(err);
 
       BlogPost
       .findById(post._id)
       .populate('comments._creator', 'email')
-      .exec(function(err, returned) {
+      .exec(function (err, returned) {
         db.close();
         assert.ifError(err);
-        assert.equal(returned.id,post.id);
+        assert.equal(returned.id, post.id);
         done();
       });
     });
   });
 
-  it('populating subdocuments partially with null array', function(done) {
+  it('populating subdocuments partially with null array', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create({
       title: 'Woot',
       comments: null
-    }, function(err, post) {
+    }, function (err, post) {
       assert.ifError(err);
 
       BlogPost
       .findById(post._id)
       .populate('comments._creator')
-      .exec(function(err, returned) {
+      .exec(function (err, returned) {
         db.close();
         assert.ifError(err);
         assert.equal(returned.id, post.id);
@@ -1485,32 +1485,32 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating subdocuments with array including nulls', function(done) {
+  it('populating subdocuments with array including nulls', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
-    var user = new User({ name: 'hans zimmer' });
-    user.save(function(err) {
+    var user = new User({name: 'hans zimmer'});
+    user.save(function (err) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'Woot',
         fans: []
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
         // shove some uncasted vals
-        BlogPost.collection.update({ _id: post._id }, { $set: { fans: [null, undefined, user.id, null] } }, function(err) {
+        BlogPost.collection.update({_id: post._id}, {$set: {fans: [null, undefined, user.id, null]}}, function (err) {
           assert.ifError(err);
 
           BlogPost
           .findById(post._id)
           .populate('fans', 'name')
-          .exec(function(err, returned) {
+          .exec(function (err, returned) {
             db.close();
             assert.ifError(err);
-            assert.equal(returned.id,post.id);
+            assert.equal(returned.id, post.id);
             assert.equal(returned.fans.length, 1);
             done();
           });
@@ -1519,12 +1519,12 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating more than one array at a time', function(done) {
+  it('populating more than one array at a time', function (done) {
     var db = start(),
         User = db.model('RefUser', users),
         M = db.model('PopMultiSubDocs', new Schema({
-          users: [{ type: ObjectId, ref: 'RefUser' }],
-          fans: [{ type: ObjectId, ref: 'RefUser' }],
+          users: [{type: ObjectId, ref: 'RefUser'}],
+          fans: [{type: ObjectId, ref: 'RefUser'}],
           comments: [Comment]
         }));
 
@@ -1536,57 +1536,57 @@ describe('model: populate:', function() {
       gender: 'female'
     }, {
       name: 'Fan 3'
-    }, function(err, fan1, fan2, fan3) {
+    }, function (err, fan1, fan2, fan3) {
       assert.ifError(err);
 
       M.create({
         users: [fan3],
         fans: [fan1],
         comments: [
-          { _creator: fan1, content: 'bejeah!' },
-          { _creator: fan2, content: 'chickfila' }
+          {_creator: fan1, content: 'bejeah!'},
+          {_creator: fan2, content: 'chickfila'}
         ]
       }, {
         users: [fan1],
         fans: [fan2],
         comments: [
-          { _creator: fan3, content: 'hello' },
-          { _creator: fan1, content: 'world' }
+          {_creator: fan3, content: 'hello'},
+          {_creator: fan1, content: 'world'}
         ]
-      }, function(err, post1, post2) {
+      }, function (err, post1, post2) {
         assert.ifError(err);
 
         M.where('_id').in([post1, post2])
-        .populate('fans', 'name', { gender: 'female' })
-        .populate('users', 'name', { gender: 'male' })
-        .populate('comments._creator', 'email', { name: null })
-        .exec(function(err, posts) {
+        .populate('fans', 'name', {gender: 'female'})
+        .populate('users', 'name', {gender: 'male'})
+        .populate('comments._creator', 'email', {name: null})
+        .exec(function (err, posts) {
           db.close();
           assert.ifError(err);
 
           assert.ok(posts);
-          assert.equal(posts.length,2);
+          assert.equal(posts.length, 2);
           var p1 = posts[0];
           var p2 = posts[1];
           assert.strictEqual(p1.fans.length, 0);
           assert.strictEqual(p2.fans.length, 1);
-          assert.equal(p2.fans[0].name,'Fan 2');
+          assert.equal(p2.fans[0].name, 'Fan 2');
           assert.equal(p2.fans[0].isInit('email'), false);
           assert.equal(p2.fans[0].isInit('gender'), false);
-          assert.equal(p1.comments.length,2);
-          assert.equal(p2.comments.length,2);
+          assert.equal(p1.comments.length, 2);
+          assert.equal(p2.comments.length, 2);
           assert.ok(p1.comments[0]._creator.email);
           assert.ok(!p2.comments[0]._creator);
-          assert.equal(p1.comments[0]._creator.email,'fan1@learnboost.com');
-          assert.equal(p2.comments[1]._creator.email,'fan1@learnboost.com');
+          assert.equal(p1.comments[0]._creator.email, 'fan1@learnboost.com');
+          assert.equal(p2.comments[1]._creator.email, 'fan1@learnboost.com');
           assert.equal(p1.comments[0]._creator.isInit('name'), false);
           assert.equal(p2.comments[1]._creator.isInit('name'), false);
-          assert.equal(p1.comments[0].content,'bejeah!');
-          assert.equal(p2.comments[1].content,'world');
+          assert.equal(p1.comments[0].content, 'bejeah!');
+          assert.equal(p2.comments[1].content, 'world');
           assert.ok(!p1.comments[1]._creator);
           assert.ok(!p2.comments[0]._creator);
-          assert.equal(p1.comments[1].content,'chickfila');
-          assert.equal(p2.comments[0].content,'hello');
+          assert.equal(p1.comments[1].content, 'chickfila');
+          assert.equal(p2.comments[0].content, 'hello');
 
           done();
         });
@@ -1594,13 +1594,13 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating multiple children of a sub-array at a time', function(done) {
+  it('populating multiple children of a sub-array at a time', function (done) {
     var db = start(),
         User = db.model('RefUser', users),
         BlogPost = db.model('RefBlogPost', posts),
         Inner = new Schema({
-          user: { type: ObjectId, ref: 'RefUser' },
-          post: { type: ObjectId, ref: 'RefBlogPost' }
+          user: {type: ObjectId, ref: 'RefUser'},
+          post: {type: ObjectId, ref: 'RefBlogPost'}
         });
     db.model('PopMultiChildrenOfSubDocInner', Inner);
 
@@ -1616,38 +1616,38 @@ describe('model: populate:', function() {
       name: 'Fan 2',
       email: 'fan2@learnboost.com',
       gender: 'female'
-    }, function(err, fan1, fan2) {
+    }, function (err, fan1, fan2) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot'
       }, {
         title: 'yay'
-      }, function(err, post1, post2) {
+      }, function (err, post1, post2) {
         assert.ifError(err);
         M.create({
           kids: [
-            { user: fan1, post: post1, y: 5 },
-            { user: fan2, post: post2, y: 8 }
+            {user: fan1, post: post1, y: 5},
+            {user: fan2, post: post2, y: 8}
           ],
           x: 4
-        }, function(err, m1) {
+        }, function (err, m1) {
           assert.ifError(err);
 
           M.findById(m1)
-          .populate('kids.user', "name")
-          .populate('kids.post', "title", { title: "woot" })
-          .exec(function(err, o) {
+          .populate('kids.user', 'name')
+          .populate('kids.post', 'title', {title: 'woot'})
+          .exec(function (err, o) {
             db.close();
             assert.ifError(err);
             assert.strictEqual(o.kids.length, 2);
             var k1 = o.kids[0];
             var k2 = o.kids[1];
             assert.strictEqual(true, !k2.post);
-            assert.strictEqual(k1.user.name, "Fan 1");
+            assert.strictEqual(k1.user.name, 'Fan 1');
             assert.strictEqual(k1.user.email, undefined);
-            assert.strictEqual(k1.post.title, "woot");
-            assert.strictEqual(k2.user.name, "Fan 2");
+            assert.strictEqual(k1.post.title, 'woot');
+            assert.strictEqual(k2.user.name, 'Fan 2');
 
             done();
           });
@@ -1656,86 +1656,86 @@ describe('model: populate:', function() {
     });
   });
 
-  it('passing sort options to the populate method', function(done) {
+  it('passing sort options to the populate method', function (done) {
     var db = start(),
         P = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
     User.create(
-      { name: 'aaron', age: 10 },
-      { name: 'fan2', age: 8 },
-      { name: 'someone else', age: 3 },
-      { name: 'val', age: 3 },
-      function(err, fan1, fan2, fan3, fan4) {
-        assert.ifError(err);
-
-        P.create({ fans: [fan4, fan2, fan3, fan1] }, function(err, post) {
+        {name: 'aaron', age: 10},
+        {name: 'fan2', age: 8},
+        {name: 'someone else', age: 3},
+        {name: 'val', age: 3},
+        function (err, fan1, fan2, fan3, fan4) {
           assert.ifError(err);
 
-          P.findById(post)
-          .populate('fans', null, null, { sort: { age: 1, name: 1 } })
-          .exec(function(err, post) {
+          P.create({fans: [fan4, fan2, fan3, fan1]}, function (err, post) {
             assert.ifError(err);
 
-            assert.equal(post.fans.length, 4);
-            assert.equal(post.fans[0].name, 'someone else');
-            assert.equal(post.fans[1].name, 'val');
-            assert.equal(post.fans[2].name, 'fan2');
-            assert.equal(post.fans[3].name, 'aaron');
-
             P.findById(post)
-            .populate('fans', 'name', null, { sort: {'name': -1} })
-            .exec(function(err, post) {
+            .populate('fans', null, null, {sort: {age: 1, name: 1}})
+            .exec(function (err, post) {
               assert.ifError(err);
 
               assert.equal(post.fans.length, 4);
-              assert.equal(post.fans[3].name,'aaron');
-              assert.strictEqual(undefined, post.fans[3].age);
-              assert.equal(post.fans[2].name,'fan2');
-              assert.strictEqual(undefined, post.fans[2].age);
-              assert.equal(post.fans[1].name,'someone else');
-              assert.strictEqual(undefined, post.fans[1].age);
-              assert.equal(post.fans[0].name, 'val');
-              assert.strictEqual(undefined, post.fans[0].age);
+              assert.equal(post.fans[0].name, 'someone else');
+              assert.equal(post.fans[1].name, 'val');
+              assert.equal(post.fans[2].name, 'fan2');
+              assert.equal(post.fans[3].name, 'aaron');
 
               P.findById(post)
-              .populate('fans', 'age', { age: { $gt: 3 }}, { sort: {'name': 'desc'} })
-              .exec(function(err, post) {
-                db.close();
+              .populate('fans', 'name', null, {sort: {'name': -1}})
+              .exec(function (err, post) {
                 assert.ifError(err);
 
-                assert.equal(post.fans.length,2);
-                assert.equal(post.fans[1].age.valueOf(),10);
-                assert.equal(post.fans[0].age.valueOf(),8);
+                assert.equal(post.fans.length, 4);
+                assert.equal(post.fans[3].name, 'aaron');
+                assert.strictEqual(undefined, post.fans[3].age);
+                assert.equal(post.fans[2].name, 'fan2');
+                assert.strictEqual(undefined, post.fans[2].age);
+                assert.equal(post.fans[1].name, 'someone else');
+                assert.strictEqual(undefined, post.fans[1].age);
+                assert.equal(post.fans[0].name, 'val');
+                assert.strictEqual(undefined, post.fans[0].age);
+
+                P.findById(post)
+                .populate('fans', 'age', {age: {$gt: 3}}, {sort: {'name': 'desc'}})
+                .exec(function (err, post) {
+                  db.close();
+                  assert.ifError(err);
 
-                done();
+                  assert.equal(post.fans.length, 2);
+                  assert.equal(post.fans[1].age.valueOf(), 10);
+                  assert.equal(post.fans[0].age.valueOf(), 8);
+
+                  done();
+                });
               });
             });
           });
         });
-      });
   });
 
-  it('limit should apply to each returned doc, not in aggregate (gh-1490)', function(done) {
+  it('limit should apply to each returned doc, not in aggregate (gh-1490)', function (done) {
     var db = start();
     var sB = new Schema({
       name: String
     });
     var name = 'b' + random();
     var sJ = new Schema({
-      b: [{ type: Schema.Types.ObjectId, ref: name }]
+      b: [{type: Schema.Types.ObjectId, ref: name}]
     });
     var B = db.model(name, sB);
     var J = db.model('j' + random(), sJ);
 
-    var b1 = new B({ name: 'thing1'});
-    var b2 = new B({ name: 'thing2'});
-    var b3 = new B({ name: 'thing3'});
-    var b4 = new B({ name: 'thing4'});
-    var b5 = new B({ name: 'thing5'});
+    var b1 = new B({name: 'thing1'});
+    var b2 = new B({name: 'thing2'});
+    var b3 = new B({name: 'thing3'});
+    var b4 = new B({name: 'thing4'});
+    var b5 = new B({name: 'thing5'});
 
-    var j1 = new J({ b: [b1.id, b2.id, b5.id]});
-    var j2 = new J({ b: [b3.id, b4.id, b5.id]});
+    var j1 = new J({b: [b1.id, b2.id, b5.id]});
+    var j2 = new J({b: [b3.id, b4.id, b5.id]});
 
     var count = 7;
 
@@ -1748,12 +1748,14 @@ describe('model: populate:', function() {
     j2.save(cb);
 
     function cb(err) {
-      if (err) throw err;
+      if (err) {
+        throw err;
+      }
       --count || next();
     }
 
     function next() {
-      J.find().populate({ path: 'b', options: { limit: 2 } }).exec(function(err, j) {
+      J.find().populate({path: 'b', options: {limit: 2}}).exec(function (err, j) {
         assert.equal(j.length, 2);
         assert.equal(j[0].b.length, 2);
         assert.equal(j[1].b.length, 2);
@@ -1762,7 +1764,7 @@ describe('model: populate:', function() {
     }
   });
 
-  it('refs should cast to ObjectId from hexstrings', function(done) {
+  it('refs should cast to ObjectId from hexstrings', function (done) {
     var BP = mongoose.model('RefBlogPost', BlogPost);
     var bp = new BP;
     bp._creator = new DocObjectId().toString();
@@ -1772,7 +1774,7 @@ describe('model: populate:', function() {
     done();
   });
 
-  it('populate should work on String _ids', function(done) {
+  it('populate should work on String _ids', function (done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -1781,35 +1783,35 @@ describe('model: populate:', function() {
     });
 
     var NoteSchema = new Schema({
-      author: { type: String, ref: 'UserWithStringId' },
+      author: {type: String, ref: 'UserWithStringId'},
       body: String
     });
 
     var User = db.model('UserWithStringId', UserSchema, random());
     var Note = db.model('NoteWithStringId', NoteSchema, random());
 
-    var alice = new User({_id: 'alice', name: "Alice"});
+    var alice = new User({_id: 'alice', name: 'Alice'});
 
-    alice.save(function(err) {
+    alice.save(function (err) {
       assert.ifError(err);
 
-      var note = new Note({author: 'alice', body: "Buy Milk"});
-      note.save(function(err) {
+      var note = new Note({author: 'alice', body: 'Buy Milk'});
+      note.save(function (err) {
         assert.ifError(err);
 
-        Note.findById(note.id).populate('author').exec(function(err, note) {
+        Note.findById(note.id).populate('author').exec(function (err, note) {
           db.close();
           assert.ifError(err);
-          assert.equal(note.body,'Buy Milk');
+          assert.equal(note.body, 'Buy Milk');
           assert.ok(note.author);
-          assert.equal(note.author.name,'Alice');
+          assert.equal(note.author.name, 'Alice');
           done();
         });
       });
     });
   });
 
-  it('populate should work on Number _ids', function(done) {
+  it('populate should work on Number _ids', function (done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -1818,35 +1820,35 @@ describe('model: populate:', function() {
     });
 
     var NoteSchema = new Schema({
-      author: { type: Number, ref: 'UserWithNumberId' },
+      author: {type: Number, ref: 'UserWithNumberId'},
       body: String
     });
 
     var User = db.model('UserWithNumberId', UserSchema, random());
     var Note = db.model('NoteWithNumberId', NoteSchema, random());
 
-    var alice = new User({_id: 2359, name: "Alice"});
+    var alice = new User({_id: 2359, name: 'Alice'});
 
-    alice.save(function(err) {
+    alice.save(function (err) {
       assert.ifError(err);
 
-      var note = new Note({author: 2359, body: "Buy Milk"});
-      note.save(function(err) {
+      var note = new Note({author: 2359, body: 'Buy Milk'});
+      note.save(function (err) {
         assert.ifError(err);
 
-        Note.findById(note.id).populate('author').exec(function(err, note) {
+        Note.findById(note.id).populate('author').exec(function (err, note) {
           db.close();
           assert.ifError(err);
-          assert.equal(note.body,'Buy Milk');
+          assert.equal(note.body, 'Buy Milk');
           assert.ok(note.author);
-          assert.equal(note.author.name,'Alice');
+          assert.equal(note.author.name, 'Alice');
           done();
         });
       });
     });
   });
 
-  it('required works on ref fields (gh-577)', function(done) {
+  it('required works on ref fields (gh-577)', function (done) {
     var db = start();
 
     var userSchema = new Schema({
@@ -1854,10 +1856,10 @@ describe('model: populate:', function() {
     });
     var User = db.model('ObjectIdRefRequiredField', userSchema, random());
 
-    var numSchema = new Schema({ _id: Number, val: Number });
+    var numSchema = new Schema({_id: Number, val: Number});
     var Num = db.model('NumberRefRequired', numSchema, random());
 
-    var strSchema = new Schema({ _id: String, val: String });
+    var strSchema = new Schema({_id: String, val: String});
     var Str = db.model('StringRefRequired', strSchema, random());
 
     var commentSchema = new Schema({
@@ -1870,9 +1872,9 @@ describe('model: populate:', function() {
 
     var pending = 3;
 
-    var string = new Str({ _id: 'my string', val: 'hello' });
-    var number = new Num({ _id: 1995, val: 234 });
-    var user = new User({ email: 'test' });
+    var string = new Str({_id: 'my string', val: 'hello'});
+    var number = new Num({_id: 1995, val: 234});
+    var user = new User({email: 'test'});
 
     string.save(next);
     number.save(next);
@@ -1880,26 +1882,28 @@ describe('model: populate:', function() {
 
     function next(err) {
       assert.strictEqual(null, err);
-      if (--pending) return;
+      if (--pending) {
+        return;
+      }
 
       var comment = new Comment({
         text: 'test'
       });
 
-      comment.save(function(err) {
+      comment.save(function (err) {
         assert.equal('CommentWithRequiredField validation failed', err && err.message);
         assert.ok('num' in err.errors);
         assert.ok('str' in err.errors);
         assert.ok('user' in err.errors);
-        assert.equal(err.errors.num.kind,'required');
-        assert.equal(err.errors.str.kind,'required');
-        assert.equal(err.errors.user.kind,'required');
+        assert.equal(err.errors.num.kind, 'required');
+        assert.equal(err.errors.str.kind, 'required');
+        assert.equal(err.errors.user.kind, 'required');
 
         comment.user = user;
         comment.num = 1995;
         comment.str = 'my string';
 
-        comment.save(function(err, comment) {
+        comment.save(function (err, comment) {
           assert.strictEqual(null, err);
 
           Comment
@@ -1907,12 +1911,12 @@ describe('model: populate:', function() {
           .populate('user')
           .populate('num')
           .populate('str')
-          .exec(function(err, comment) {
+          .exec(function (err, comment) {
             assert.ifError(err);
 
             comment.set({text: 'test2'});
 
-            comment.save(function(err) {
+            comment.save(function (err) {
               db.close();
               assert.ifError(err);
               done();
@@ -1923,51 +1927,51 @@ describe('model: populate:', function() {
     }
   });
 
-  it('populate works with schemas with both id and _id defined', function(done) {
+  it('populate works with schemas with both id and _id defined', function (done) {
     var db = start(),
-        S1 = new Schema({ id: String }),
-        S2 = new Schema({ things: [{ type: ObjectId, ref: '_idAndid' }]});
+        S1 = new Schema({id: String}),
+        S2 = new Schema({things: [{type: ObjectId, ref: '_idAndid'}]});
 
     var M1 = db.model('_idAndid', S1);
     var M2 = db.model('populateWorksWith_idAndidSchemas', S2);
 
     M1.create(
-        { id: "The Tiger That Isn't" }
-      , { id: "Users Guide To The Universe" }
-      , function(err, a, b) {
-        assert.ifError(err);
-
-        var m2 = new M2({ things: [a, b]});
-        m2.save(function(err) {
+        {id: "The Tiger That Isn't"}
+        , {id: 'Users Guide To The Universe'}
+        , function (err, a, b) {
           assert.ifError(err);
-          M2.findById(m2).populate('things').exec(function(err, doc) {
-            db.close();
+
+          var m2 = new M2({things: [a, b]});
+          m2.save(function (err) {
             assert.ifError(err);
-            assert.equal(doc.things.length,2);
-            assert.equal(doc.things[0].id,"The Tiger That Isn't");
-            assert.equal(doc.things[1].id,"Users Guide To The Universe");
-            done();
+            M2.findById(m2).populate('things').exec(function (err, doc) {
+              db.close();
+              assert.ifError(err);
+              assert.equal(doc.things.length, 2);
+              assert.equal(doc.things[0].id, "The Tiger That Isn't");
+              assert.equal(doc.things[1].id, 'Users Guide To The Universe');
+              done();
+            });
           });
         });
-      });
   });
 
-  it('Update works with populated arrays (gh-602)', function(done) {
+  it('Update works with populated arrays (gh-602)', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
-    User.create({name: 'aphex'},{name: 'twin'}, function(err, u1, u2) {
+    User.create({name: 'aphex'}, {name: 'twin'}, function (err, u1, u2) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'Woot',
         fans: []
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
-        var update = { fans: [u1, u2] };
-        BlogPost.update({ _id: post }, update, function(err) {
+        var update = {fans: [u1, u2]};
+        BlogPost.update({_id: post}, update, function (err) {
           assert.ifError(err);
 
           // the original update doc should not be modified
@@ -1976,10 +1980,10 @@ describe('model: populate:', function() {
           assert.ok(update.fans[0] instanceof mongoose.Document);
           assert.ok(update.fans[1] instanceof mongoose.Document);
 
-          BlogPost.findById(post, function(err, post) {
+          BlogPost.findById(post, function (err, post) {
             db.close();
             assert.ifError(err);
-            assert.equal(post.fans.length,2);
+            assert.equal(post.fans.length, 2);
             assert.ok(post.fans[0] instanceof DocObjectId);
             assert.ok(post.fans[1] instanceof DocObjectId);
             done();
@@ -1989,20 +1993,20 @@ describe('model: populate:', function() {
     });
   });
 
-  it('toJSON should also be called for refs (gh-675)', function(done) {
+  it('toJSON should also be called for refs (gh-675)', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
     User.prototype._toJSON = User.prototype.toJSON;
-    User.prototype.toJSON = function() {
+    User.prototype.toJSON = function () {
       var res = this._toJSON();
       res.was_in_to_json = true;
       return res;
     };
 
     BlogPost.prototype._toJSON = BlogPost.prototype.toJSON;
-    BlogPost.prototype.toJSON = function() {
+    BlogPost.prototype.toJSON = function () {
       var res = this._toJSON();
       res.was_in_to_json = true;
       return res;
@@ -2011,32 +2015,32 @@ describe('model: populate:', function() {
     User.create({
       name: 'Jerem',
       email: 'jerem@jolicloud.com'
-    }, function(err, creator) {
+    }, function (err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'Ping Pong',
         _creator: creator
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator')
-        .exec(function(err, post) {
+        .exec(function (err, post) {
           db.close();
           assert.ifError(err);
 
           var json = post.toJSON();
           assert.equal(true, json.was_in_to_json);
-          assert.equal(json._creator.was_in_to_json,true);
+          assert.equal(json._creator.was_in_to_json, true);
           done();
         });
       });
     });
   });
 
-  it('populate should work on Buffer _ids (gh-686)', function(done) {
+  it('populate should work on Buffer _ids (gh-686)', function (done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -2045,35 +2049,35 @@ describe('model: populate:', function() {
     });
 
     var NoteSchema = new Schema({
-      author: { type: Buffer, ref: 'UserWithBufferId' },
+      author: {type: Buffer, ref: 'UserWithBufferId'},
       body: String
     });
 
     var User = db.model('UserWithBufferId', UserSchema, random());
     var Note = db.model('NoteWithBufferId', NoteSchema, random());
 
-    var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: "Alice"});
+    var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: 'Alice'});
 
-    alice.save(function(err) {
+    alice.save(function (err) {
       assert.ifError(err);
 
-      var note = new Note({author: 'alice', body: "Buy Milk"});
-      note.save(function(err) {
+      var note = new Note({author: 'alice', body: 'Buy Milk'});
+      note.save(function (err) {
         assert.ifError(err);
 
-        Note.findById(note.id).populate('author').exec(function(err, note) {
+        Note.findById(note.id).populate('author').exec(function (err, note) {
           db.close();
           assert.ifError(err);
-          assert.equal(note.body,'Buy Milk');
+          assert.equal(note.body, 'Buy Milk');
           assert.ok(note.author);
-          assert.equal(note.author.name,'Alice');
+          assert.equal(note.author.name, 'Alice');
           done();
         });
       });
     });
   });
 
-  it('populated Buffer _ids should be requireable', function(done) {
+  it('populated Buffer _ids should be requireable', function (done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -2082,25 +2086,25 @@ describe('model: populate:', function() {
     });
 
     var NoteSchema = new Schema({
-      author: { type: Buffer, ref: 'UserWithBufferId', required: true },
+      author: {type: Buffer, ref: 'UserWithBufferId', required: true},
       body: String
     });
 
     var User = db.model('UserWithBufferId', UserSchema, random());
     var Note = db.model('NoteWithBufferId', NoteSchema, random());
 
-    var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: "Alice"});
+    var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: 'Alice'});
 
-    alice.save(function(err) {
+    alice.save(function (err) {
       assert.ifError(err);
 
-      var note = new Note({author: 'alice', body: "Buy Milk"});
-      note.save(function(err) {
+      var note = new Note({author: 'alice', body: 'Buy Milk'});
+      note.save(function (err) {
         assert.ifError(err);
 
-        Note.findById(note.id).populate('author').exec(function(err, note) {
+        Note.findById(note.id).populate('author').exec(function (err, note) {
           assert.ifError(err);
-          note.save(function(err) {
+          note.save(function (err) {
             db.close();
             assert.ifError(err);
             done();
@@ -2110,7 +2114,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populating with custom model selection (gh-773)', function(done) {
+  it('populating with custom model selection (gh-773)', function (done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefAlternateUser', users);
@@ -2118,25 +2122,25 @@ describe('model: populate:', function() {
     User.create({
       name: 'Daniel',
       email: 'daniel.baulig@gmx.de'
-    }, function(err, creator) {
+    }, function (err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator', 'email', 'RefAlternateUser')
-        .exec(function(err, post) {
+        .exec(function (err, post) {
           db.close();
           assert.ifError(err);
 
           assert.ok(post._creator instanceof User);
           assert.equal(post._creator.isInit('name'), false);
-          assert.equal(post._creator.email,'daniel.baulig@gmx.de');
+          assert.equal(post._creator.email, 'daniel.baulig@gmx.de');
 
           done();
         });
@@ -2144,69 +2148,93 @@ describe('model: populate:', function() {
     });
   });
 
-  describe('specifying a custom model without specifying a ref in schema', function() {
-    it('with String _id', function(done) {
+  describe('specifying a custom model without specifying a ref in schema', function () {
+    it('with String _id', function (done) {
       var db = start();
-      var A = db.model('A', { name: String, _id: String });
-      var B = db.model('B', { other: String });
-      A.create({ name: 'hello', _id: 'first' }, function(err, a) {
-        if (err) return done(err);
-        B.create({ other: a._id }, function(err, b) {
-          if (err) return done(err);
-          B.findById(b._id).populate({ path: 'other', model: 'A' }).exec(function(err, b) {
+      var A = db.model('A', {name: String, _id: String});
+      var B = db.model('B', {other: String});
+      A.create({name: 'hello', _id: 'first'}, function (err, a) {
+        if (err) {
+          return done(err);
+        }
+        B.create({other: a._id}, function (err, b) {
+          if (err) {
+            return done(err);
+          }
+          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function (err, b) {
             db.close();
-            if (err) return done(err);
+            if (err) {
+              return done(err);
+            }
             assert.equal('hello', b.other.name);
             done();
           });
         });
       });
     });
-    it('with Number _id', function(done) {
+    it('with Number _id', function (done) {
       var db = start();
-      var A = db.model('A', { name: String, _id: Number });
-      var B = db.model('B', { other: Number });
-      A.create({ name: 'hello', _id: 3 }, function(err, a) {
-        if (err) return done(err);
-        B.create({ other: a._id }, function(err, b) {
-          if (err) return done(err);
-          B.findById(b._id).populate({ path: 'other', model: 'A' }).exec(function(err, b) {
+      var A = db.model('A', {name: String, _id: Number});
+      var B = db.model('B', {other: Number});
+      A.create({name: 'hello', _id: 3}, function (err, a) {
+        if (err) {
+          return done(err);
+        }
+        B.create({other: a._id}, function (err, b) {
+          if (err) {
+            return done(err);
+          }
+          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function (err, b) {
             db.close();
-            if (err) return done(err);
+            if (err) {
+              return done(err);
+            }
             assert.equal('hello', b.other.name);
             done();
           });
         });
       });
     });
-    it('with Buffer _id', function(done) {
+    it('with Buffer _id', function (done) {
       var db = start();
-      var A = db.model('A', { name: String, _id: Buffer });
-      var B = db.model('B', { other: Buffer });
-      A.create({ name: 'hello', _id: new Buffer('x') }, function(err, a) {
-        if (err) return done(err);
-        B.create({ other: a._id }, function(err, b) {
-          if (err) return done(err);
-          B.findById(b._id).populate({ path: 'other', model: 'A' }).exec(function(err, b) {
+      var A = db.model('A', {name: String, _id: Buffer});
+      var B = db.model('B', {other: Buffer});
+      A.create({name: 'hello', _id: new Buffer('x')}, function (err, a) {
+        if (err) {
+          return done(err);
+        }
+        B.create({other: a._id}, function (err, b) {
+          if (err) {
+            return done(err);
+          }
+          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function (err, b) {
             db.close();
-            if (err) return done(err);
+            if (err) {
+              return done(err);
+            }
             assert.equal('hello', b.other.name);
             done();
           });
         });
       });
     });
-    it('with ObjectId _id', function(done) {
+    it('with ObjectId _id', function (done) {
       var db = start();
-      var A = db.model('A', { name: String });
-      var B = db.model('B', { other: Schema.ObjectId });
-      A.create({ name: 'hello' }, function(err, a) {
-        if (err) return done(err);
-        B.create({ other: a._id }, function(err, b) {
-          if (err) return done(err);
-          B.findById(b._id).populate({ path: 'other', model: 'A' }).exec(function(err, b) {
+      var A = db.model('A', {name: String});
+      var B = db.model('B', {other: Schema.ObjectId});
+      A.create({name: 'hello'}, function (err, a) {
+        if (err) {
+          return done(err);
+        }
+        B.create({other: a._id}, function (err, b) {
+          if (err) {
+            return done(err);
+          }
+          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function (err, b) {
             db.close();
-            if (err) return done(err);
+            if (err) {
+              return done(err);
+            }
             assert.equal('hello', b.other.name);
             done();
           });
@@ -2215,11 +2243,11 @@ describe('model: populate:', function() {
     });
   });
 
-  describe('specifying all params using an object', function() {
+  describe('specifying all params using an object', function () {
     var db, B, User;
     var post;
 
-    before(function(done) {
+    before(function (done) {
       db = start();
       B = db.model('RefBlogPost');
       User = db.model('RefAlternateUser');
@@ -2228,36 +2256,36 @@ describe('model: populate:', function() {
         name: 'use an object',
         email: 'fo-real@objects.r.fun'
       }
-      , { name: 'yup' }
-      , { name: 'not here' }
-      , function(err, fan1, fan2, fan3) {
-        assert.ifError(err);
+          , {name: 'yup'}
+          , {name: 'not here'}
+          , function (err, fan1, fan2, fan3) {
+            assert.ifError(err);
 
-        B.create({
-          title: 'woot',
-          fans: [fan1, fan2, fan3]
-        }, function(err, post_) {
-          assert.ifError(err);
-          post = post_;
-          done();
-        });
-      });
+            B.create({
+              title: 'woot',
+              fans: [fan1, fan2, fan3]
+            }, function (err, post_) {
+              assert.ifError(err);
+              post = post_;
+              done();
+            });
+          });
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('works', function(done) {
+    it('works', function (done) {
       B.findById(post._id)
       .populate({
         path: 'fans',
         select: 'name',
         model: 'RefAlternateUser',
-        match: { name: /u/ },
-        options: { sort: {'name': -1} }
+        match: {name: /u/},
+        options: {sort: {'name': -1}}
       })
-      .exec(function(err, post) {
+      .exec(function (err, post) {
         assert.ifError(err);
 
         assert.ok(Array.isArray(post.fans));
@@ -2268,20 +2296,19 @@ describe('model: populate:', function() {
         assert.equal(post.fans[1].isInit('name'), true);
         assert.equal(post.fans[0].isInit('email'), false);
         assert.equal(post.fans[1].isInit('email'), false);
-        assert.equal(post.fans[0].name,'yup');
-        assert.equal(post.fans[1].name,'use an object');
+        assert.equal(post.fans[0].name, 'yup');
+        assert.equal(post.fans[1].name, 'use an object');
 
         done();
       });
     });
-
   });
 
-  describe('Model.populate()', function() {
+  describe('Model.populate()', function () {
     var db, B, User;
     var user1, user2, post1, post2, _id;
 
-    before(function(done) {
+    before(function (done) {
       db = start();
       B = db.model('RefBlogPost', posts);
       User = db.model('RefAlternateUser', users);
@@ -2296,7 +2323,7 @@ describe('model: populate:', function() {
         name: 'Newark',
         email: 'ewr@nj.com',
         blogposts: [_id]
-      }, function(err, u1, u2) {
+      }, function (err, u1, u2) {
         assert.ifError(err);
 
         user1 = u1;
@@ -2310,7 +2337,7 @@ describe('model: populate:', function() {
           title: 'green eggs and ham',
           _creator: user2,
           fans: [user2, user1]
-        }, function(err, p1, p2) {
+        }, function (err, p1, p2) {
           assert.ifError(err);
           post1 = p1;
           post2 = p2;
@@ -2319,12 +2346,12 @@ describe('model: populate:', function() {
       });
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    describe('returns', function() {
-      it('a promise', function(done) {
+    describe('returns', function () {
+      it('a promise', function (done) {
         var p = B.populate(post1, '_creator');
         assert.ok(p instanceof mongoose.Promise);
         p.then(success, done).end();
@@ -2335,11 +2362,11 @@ describe('model: populate:', function() {
       });
     });
 
-    describe('of individual document', function() {
-      it('works', function(done) {
-        B.findById(post1._id, function(error, post1) {
-          var ret = utils.populate({ path: '_creator', model: 'RefAlternateUser' });
-          B.populate(post1, ret, function(err, post) {
+    describe('of individual document', function () {
+      it('works', function (done) {
+        B.findById(post1._id, function (error, post1) {
+          var ret = utils.populate({path: '_creator', model: 'RefAlternateUser'});
+          B.populate(post1, ret, function (err, post) {
             assert.ifError(err);
             assert.ok(post);
             assert.ok(post._creator instanceof User);
@@ -2350,12 +2377,12 @@ describe('model: populate:', function() {
       });
     });
 
-    describe('a document already populated', function() {
-      describe('when paths are not modified', function() {
-        it('works', function(done) {
-          B.findById(post1._id, function(err, doc) {
+    describe('a document already populated', function () {
+      describe('when paths are not modified', function () {
+        it('works', function (done) {
+          B.findById(post1._id, function (err, doc) {
             assert.ifError(err);
-            B.populate(doc, [{ path: '_creator', model: 'RefAlternateUser' }, { path: 'fans', model: 'RefAlternateUser' }], function(err, post) {
+            B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function (err, post) {
               assert.ifError(err);
               assert.ok(post);
               assert.ok(post._creator instanceof User);
@@ -2367,7 +2394,7 @@ describe('model: populate:', function() {
               assert.equal(String(post._creator._id), String(post.populated('_creator')));
               assert.ok(Array.isArray(post.populated('fans')));
 
-              B.populate(doc, [{ path: '_creator', model: 'RefAlternateUser' }, { path: 'fans', model: 'RefAlternateUser' }], function(err, post) {
+              B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function (err, post) {
                 assert.ifError(err);
                 assert.ok(post);
                 assert.ok(post._creator instanceof User);
@@ -2376,12 +2403,8 @@ describe('model: populate:', function() {
                 assert.equal(post.fans[0].name, user1.name);
                 assert.equal(post.fans[1].name, user2.name);
                 assert.ok(Array.isArray(post.populated('fans')));
-                assert.equal(
-                    String(post.fans[0]._id)
-                  , String(post.populated('fans')[0]));
-                assert.equal(
-                    String(post.fans[1]._id)
-                  , String(post.populated('fans')[1]));
+                assert.equal(String(post.fans[0]._id), String(post.populated('fans')[0]));
+                assert.equal(String(post.fans[1]._id), String(post.populated('fans')[1]));
 
                 done();
               });
@@ -2389,11 +2412,11 @@ describe('model: populate:', function() {
           });
         });
       });
-      describe('when paths are modified', function() {
-        it('works', function(done) {
-          B.findById(post1._id, function(err, doc) {
+      describe('when paths are modified', function () {
+        it('works', function (done) {
+          B.findById(post1._id, function (err, doc) {
             assert.ifError(err);
-            B.populate(doc, [{ path: '_creator', model: 'RefAlternateUser' }, { path: 'fans', model: 'RefAlternateUser' }], function(err, post) {
+            B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function (err, post) {
               assert.ifError(err);
               assert.ok(post);
               assert.ok(post._creator instanceof User);
@@ -2409,7 +2432,7 @@ describe('model: populate:', function() {
               doc.markModified('_creator');
               doc.markModified('fans');
 
-              B.populate(doc, [{ path: '_creator', model: 'RefAlternateUser' }, { path: 'fans', model: 'RefAlternateUser' }], function(err, post) {
+              B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function (err, post) {
                 assert.ifError(err);
                 assert.ok(post);
                 assert.ok(post._creator instanceof User);
@@ -2420,10 +2443,10 @@ describe('model: populate:', function() {
                 assert.ok(Array.isArray(post.populated('fans')));
                 assert.equal(
                     String(post.fans[0]._id)
-                  , String(post.populated('fans')[0]));
+                    , String(post.populated('fans')[0]));
                 assert.equal(
                     String(post.fans[1]._id)
-                  , String(post.populated('fans')[1]));
+                    , String(post.populated('fans')[1]));
 
                 done();
               });
@@ -2433,14 +2456,14 @@ describe('model: populate:', function() {
       });
     });
 
-    describe('of multiple documents', function() {
-      it('works', function(done) {
-        B.findById(post1._id, function(error, post1) {
+    describe('of multiple documents', function () {
+      it('works', function (done) {
+        B.findById(post1._id, function (error, post1) {
           assert.ifError(error);
-          B.findById(post2._id, function(error, post2) {
+          B.findById(post2._id, function (error, post2) {
             assert.ifError(error);
-            var ret = utils.populate({ path: '_creator', model: 'RefAlternateUser' });
-            B.populate([post1, post2], ret, function(err, posts) {
+            var ret = utils.populate({path: '_creator', model: 'RefAlternateUser'});
+            B.populate([post1, post2], ret, function (err, posts) {
               assert.ifError(err);
               assert.ok(posts);
               assert.equal(2, posts.length);
@@ -2456,11 +2479,10 @@ describe('model: populate:', function() {
         });
       });
     });
-
   });
 
-  describe('populating combined with lean (gh-1260)', function() {
-    it('with findOne', function(done) {
+  describe('populating combined with lean (gh-1260)', function () {
+    it('with findOne', function (done) {
       var db = start(),
           BlogPost = db.model('RefBlogPost', posts + random()),
           User = db.model('RefUser', users + random());
@@ -2468,20 +2490,20 @@ describe('model: populate:', function() {
       User.create({
         name: 'Guillermo',
         email: 'rauchg@gmail.com'
-      }, function(err, creator) {
+      }, function (err, creator) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'woot',
           _creator: creator
-        }, function(err, post) {
+        }, function (err, post) {
           assert.ifError(err);
 
           BlogPost
           .findById(post._id)
           .lean()
           .populate('_creator')
-          .exec(function(err, post) {
+          .exec(function (err, post) {
             db.close();
             assert.ifError(err);
 
@@ -2495,7 +2517,7 @@ describe('model: populate:', function() {
       });
     });
 
-    it('with find', function(done) {
+    it('with find', function (done) {
       var db = start(),
           BlogPost = db.model('RefBlogPost', posts + random()),
           User = db.model('RefUser', users + random());
@@ -2506,7 +2528,7 @@ describe('model: populate:', function() {
       }, {
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function(err, fan1, fan2) {
+      }, function (err, fan1, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
@@ -2515,28 +2537,28 @@ describe('model: populate:', function() {
         }, {
           title: 'Woot2',
           fans: [fan2, fan1]
-        }, function(err, post1, post2) {
+        }, function (err, post1, post2) {
           assert.ifError(err);
 
           BlogPost
-          .find({ _id: { $in: [post1._id, post2._id ] } })
+          .find({_id: {$in: [post1._id, post2._id]}})
           .populate('fans')
           .lean()
-          .exec(function(err, blogposts) {
+          .exec(function (err, blogposts) {
             assert.ifError(err);
 
-            assert.equal(blogposts[0].fans[0].name,'Fan 1');
-            assert.equal(blogposts[0].fans[0].email,'fan1@learnboost.com');
+            assert.equal(blogposts[0].fans[0].name, 'Fan 1');
+            assert.equal(blogposts[0].fans[0].email, 'fan1@learnboost.com');
             assert.equal('undefined', typeof blogposts[0].fans[0].update);
-            assert.equal(blogposts[0].fans[1].name,'Fan 2');
-            assert.equal(blogposts[0].fans[1].email,'fan2@learnboost.com');
+            assert.equal(blogposts[0].fans[1].name, 'Fan 2');
+            assert.equal(blogposts[0].fans[1].email, 'fan2@learnboost.com');
             assert.equal('undefined', typeof blogposts[0].fans[1].update);
 
-            assert.equal(blogposts[1].fans[0].name,'Fan 2');
-            assert.equal(blogposts[1].fans[0].email,'fan2@learnboost.com');
+            assert.equal(blogposts[1].fans[0].name, 'Fan 2');
+            assert.equal(blogposts[1].fans[0].email, 'fan2@learnboost.com');
             assert.equal('undefined', typeof blogposts[1].fans[0].update);
-            assert.equal(blogposts[1].fans[1].name,'Fan 1');
-            assert.equal(blogposts[1].fans[1].email,'fan1@learnboost.com');
+            assert.equal(blogposts[1].fans[1].name, 'Fan 1');
+            assert.equal(blogposts[1].fans[1].email, 'fan1@learnboost.com');
             assert.equal('undefined', typeof blogposts[1].fans[1].update);
             db.close(done);
           });
@@ -2545,14 +2567,14 @@ describe('model: populate:', function() {
     });
   });
 
-  describe('records paths and _ids used in population', function() {
+  describe('records paths and _ids used in population', function () {
     var db;
     var B;
     var U;
     var u1, u2;
     var b1;
 
-    before(function(done) {
+    before(function (done) {
       db = start();
       B = db.model('RefBlogPost', posts + random());
       U = db.model('RefUser', users + random());
@@ -2563,7 +2585,7 @@ describe('model: populate:', function() {
       }, {
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function(err, fan1, fan2) {
+      }, function (err, fan1, fan2) {
         assert.ifError(err);
         u1 = fan1;
         u2 = fan2;
@@ -2576,7 +2598,7 @@ describe('model: populate:', function() {
           title: 'Woot2',
           fans: [fan2, fan1],
           _creator: fan2
-        }, function(err, post) {
+        }, function (err, post) {
           assert.ifError(err);
           b1 = post;
           done();
@@ -2584,12 +2606,12 @@ describe('model: populate:', function() {
       });
     });
 
-    after(function() {
+    after(function () {
       db.close();
     });
 
-    it('with findOne', function(done) {
-      B.findById(b1).populate('fans _creator').exec(function(err, doc) {
+    it('with findOne', function (done) {
+      B.findById(b1).populate('fans _creator').exec(function (err, doc) {
         assert.ifError(err);
         assert.ok(Array.isArray(doc.populated('fans')));
         assert.equal(2, doc.populated('fans').length);
@@ -2600,8 +2622,8 @@ describe('model: populate:', function() {
       });
     });
 
-    it('with find', function(done) {
-      B.find().sort('title').populate('fans _creator').exec(function(err, docs) {
+    it('with find', function (done) {
+      B.find().sort('title').populate('fans _creator').exec(function (err, docs) {
         assert.ifError(err);
         assert.equal(2, docs.length);
 
@@ -2625,9 +2647,9 @@ describe('model: populate:', function() {
     });
   });
 
-  describe('deselecting _id', function() {
+  describe('deselecting _id', function () {
     var db, C, U, c1, c2;
-    before(function(done) {
+    before(function (done) {
       db = start();
 
       C = db.model('Comment', Schema({
@@ -2636,58 +2658,58 @@ describe('model: populate:', function() {
 
       U = db.model('User', Schema({
         name: 'string',
-        comments: [{ type: Schema.ObjectId, ref: 'Comment' }],
-        comment: { type: Schema.ObjectId, ref: 'Comment' }
+        comments: [{type: Schema.ObjectId, ref: 'Comment'}],
+        comment: {type: Schema.ObjectId, ref: 'Comment'}
       }), 'users_' + random());
 
-      C.create({ body: 'comment 1', title: '1' }, { body: 'comment 2', title: 2 }, function(err, c1_, c2_) {
+      C.create({body: 'comment 1', title: '1'}, {body: 'comment 2', title: 2}, function (err, c1_, c2_) {
         assert.ifError(err);
         c1 = c1_;
         c2 = c2_;
 
         U.create(
-            { name: 'u1', comments: [c1, c2], comment: c1 }
-          , { name: 'u2', comment: c2 }
-          , function(err) {
-            assert.ifError(err);
-            done();
-          });
+            {name: 'u1', comments: [c1, c2], comment: c1}
+            , {name: 'u2', comment: c2}
+            , function (err) {
+              assert.ifError(err);
+              done();
+            });
       });
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    describe('in a subdocument', function() {
-      it('works', function(done) {
-        U.find({name: 'u1'}).populate('comments', { _id: 0 }).exec(function(err, docs) {
+    describe('in a subdocument', function () {
+      it('works', function (done) {
+        U.find({name: 'u1'}).populate('comments', {_id: 0}).exec(function (err, docs) {
           assert.ifError(err);
 
           var doc = docs[0];
           assert.ok(Array.isArray(doc.comments), 'comments should be an array: ' + JSON.stringify(doc));
           assert.equal(2, doc.comments.length, 'invalid comments length for ' + JSON.stringify(doc));
-          doc.comments.forEach(function(d) {
+          doc.comments.forEach(function (d) {
             assert.equal(undefined, d._id);
             assert.equal(-1, Object.keys(d._doc).indexOf('_id'));
             assert.ok(d.body.length);
             assert.equal('number', typeof d._doc.__v);
           });
 
-          U.findOne({name: 'u1'}).populate('comments', 'title -_id').exec(function(err, doc) {
+          U.findOne({name: 'u1'}).populate('comments', 'title -_id').exec(function (err, doc) {
             assert.ifError(err);
             assert.equal(2, doc.comments.length);
-            doc.comments.forEach(function(d) {
+            doc.comments.forEach(function (d) {
               assert.equal(undefined, d._id);
               assert.equal(-1, Object.keys(d._doc).indexOf('_id'));
               assert.ok(d.title.length);
               assert.equal(undefined, d.body);
               assert.equal(typeof d._doc.__v, 'undefined');
             });
-            U.findOne({name: 'u1'}).populate('comments', '-_id').exec(function(err, doc) {
+            U.findOne({name: 'u1'}).populate('comments', '-_id').exec(function (err, doc) {
               assert.ifError(err);
               assert.equal(2, doc.comments.length);
-              doc.comments.forEach(function(d) {
+              doc.comments.forEach(function (d) {
                 assert.equal(undefined, d._id);
                 assert.equal(-1, Object.keys(d._doc).indexOf('_id'));
                 assert.ok(d.title.length);
@@ -2700,22 +2722,22 @@ describe('model: populate:', function() {
         });
       });
 
-      it('with lean', function(done) {
-        U.find({name: 'u1'}).lean().populate({ path: 'comments', select: { _id: 0 }, options: { lean: true }}).exec(function(err, docs) {
+      it('with lean', function (done) {
+        U.find({name: 'u1'}).lean().populate({path: 'comments', select: {_id: 0}, options: {lean: true}}).exec(function (err, docs) {
           assert.ifError(err);
 
           var doc = docs[0];
           assert.equal(2, doc.comments.length);
-          doc.comments.forEach(function(d) {
+          doc.comments.forEach(function (d) {
             assert.ok(!('_id' in d));
             assert.ok(d.body.length);
             assert.equal('number', typeof d.__v);
           });
 
-          U.findOne({name: 'u1'}).lean().populate('comments', '-_id', null, { lean: true}).exec(function(err, doc) {
+          U.findOne({name: 'u1'}).lean().populate('comments', '-_id', null, {lean: true}).exec(function (err, doc) {
             assert.ifError(err);
             assert.equal(2, doc.comments.length);
-            doc.comments.forEach(function(d) {
+            doc.comments.forEach(function (d) {
               assert.ok(!('_id' in d));
               assert.ok(d.body.length);
               assert.equal('number', typeof d.__v);
@@ -2726,32 +2748,30 @@ describe('model: populate:', function() {
       });
     });
 
-    describe('of documents being populated', function() {
-      it('still works (gh-1441)', function(done) {
-
+    describe('of documents being populated', function () {
+      it('still works (gh-1441)', function (done) {
         U.find()
-          .select('-_id comment name')
-          .populate('comment', { _id: 0 }).exec(function(err, docs) {
-
-            assert.ifError(err);
-            assert.equal(2, docs.length);
-
-            docs.forEach(function(doc) {
-              assert.ok(doc.comment && doc.comment.body);
-              if ('u1' == doc.name) {
-                assert.equal('comment 1', doc.comment.body);
-              } else {
-                assert.equal('comment 2', doc.comment.body);
-              }
-            });
-
-            done();
+        .select('-_id comment name')
+        .populate('comment', {_id: 0}).exec(function (err, docs) {
+          assert.ifError(err);
+          assert.equal(2, docs.length);
+
+          docs.forEach(function (doc) {
+            assert.ok(doc.comment && doc.comment.body);
+            if ('u1' == doc.name) {
+              assert.equal('comment 1', doc.comment.body);
+            } else {
+              assert.equal('comment 2', doc.comment.body);
+            }
           });
+
+          done();
+        });
       });
     });
   });
 
-  it('maps results back to correct document (gh-1444)', function(done) {
+  it('maps results back to correct document (gh-1444)', function (done) {
     var db = start();
 
     var articleSchema = new Schema({
@@ -2766,35 +2786,39 @@ describe('model: populate:', function() {
     });
     var Media = db.model('1444-Media', mediaSchema);
 
-    Media.create({ filename: 'one' }, function(err, media) {
+    Media.create({filename: 'one'}, function (err, media) {
       assert.ifError(err);
 
       Article.create(
           {body: 'body1', author: 'a'}
-        , {body: 'body2', author: 'a', mediaAttach: media._id}
-        , {body: 'body3', author: 'a'}, function(err) {
-          if (err) return done(err);
+          , {body: 'body2', author: 'a', mediaAttach: media._id}
+          , {body: 'body3', author: 'a'}, function (err) {
+            if (err) {
+              return done(err);
+            }
 
-          Article.find().populate('mediaAttach').exec(function(err, docs) {
-            db.close();
-            assert.ifError(err);
+            Article.find().populate('mediaAttach').exec(function (err, docs) {
+              db.close();
+              assert.ifError(err);
 
-            var a2 = docs.filter(function(d) { return 'body2' == d.body;})[0];
-            assert.equal(a2.mediaAttach.id, media.id);
+              var a2 = docs.filter(function (d) {
+                return 'body2' == d.body;
+              })[0];
+              assert.equal(a2.mediaAttach.id, media.id);
 
-            done();
+              done();
+            });
           });
-        });
     });
   });
 
-  describe('DynRef', function() {
+  describe('DynRef', function () {
     var db;
     var Review;
     var Item1;
     var Item2;
 
-    before(function(done) {
+    before(function (done) {
       db = start();
       var reviewSchema = new Schema({
         _id: Number,
@@ -2838,19 +2862,19 @@ describe('model: populate:', function() {
       var review = {
         _id: 0,
         text: 'Test',
-        item: { id: 1, type: 'dynrefItem1' },
-        items: [{ id: 1, type: 'dynrefItem1' }, { id: 2, type: 'dynrefItem2' }]
+        item: {id: 1, type: 'dynrefItem1'},
+        items: [{id: 1, type: 'dynrefItem1'}, {id: 2, type: 'dynrefItem2'}]
       };
 
-      Item1.create({ _id: 1, name: 'Val' }, function(err) {
+      Item1.create({_id: 1, name: 'Val'}, function (err) {
         if (err) {
           return done(err);
         }
-        Item2.create({ _id: 2, otherName: 'Val' }, function(err) {
+        Item2.create({_id: 2, otherName: 'Val'}, function (err) {
           if (err) {
             return done(err);
           }
-          Review.create(review, function(err) {
+          Review.create(review, function (err) {
             if (err) {
               return done(err);
             }
@@ -2860,12 +2884,12 @@ describe('model: populate:', function() {
       });
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('Simple populate', function(done) {
-      Review.find({}).populate('item.id').exec(function(err, results) {
+    it('Simple populate', function (done) {
+      Review.find({}).populate('item.id').exec(function (err, results) {
         assert.ifError(err);
         assert.equal(1, results.length);
         var result = results[0];
@@ -2874,8 +2898,8 @@ describe('model: populate:', function() {
       });
     });
 
-    it('Array populate', function(done) {
-      Review.find({}).populate('items.id').exec(function(err, results) {
+    it('Array populate', function (done) {
+      Review.find({}).populate('items.id').exec(function (err, results) {
         assert.ifError(err);
         assert.equal(1, results.length);
         var result = results[0];
@@ -2887,25 +2911,27 @@ describe('model: populate:', function() {
     });
   });
 
-  describe('leaves Documents within Mixed properties alone (gh-1471)', function() {
+  describe('leaves Documents within Mixed properties alone (gh-1471)', function () {
     var db;
     var Cat;
     var Litter;
 
-    before(function() {
+    before(function () {
       db = start();
-      Cat = db.model('cats', new Schema({ name: String }));
+      Cat = db.model('cats', new Schema({name: String}));
       var litterSchema = new Schema({name: String, cats: {}, o: {}, a: []});
       Litter = db.model('litters', litterSchema);
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('when saving new docs', function(done) {
-      Cat.create({name: 'new1'},{name: 'new2'},{name: 'new3'}, function(err, a, b, c) {
-        if (err) return done(err);
+    it('when saving new docs', function (done) {
+      Cat.create({name: 'new1'}, {name: 'new2'}, {name: 'new3'}, function (err, a, b, c) {
+        if (err) {
+          return done(err);
+        }
 
         Litter.create({
           name: 'new',
@@ -2916,11 +2942,13 @@ describe('model: populate:', function() {
       });
     });
 
-    it('when saving existing docs 5T5', function(done) {
-      Cat.create({name: 'ex1'},{name: 'ex2'},{name: 'ex3'}, function(err, a, b, c) {
-        if (err) return done(err);
+    it('when saving existing docs 5T5', function (done) {
+      Cat.create({name: 'ex1'}, {name: 'ex2'}, {name: 'ex3'}, function (err, a, b, c) {
+        if (err) {
+          return done(err);
+        }
 
-        Litter.create({name: 'existing'}, function(err, doc) {
+        Litter.create({name: 'existing'}, function (err, doc) {
           doc.cats = [a];
           doc.o = b;
           doc.a = [c];
@@ -2930,10 +2958,14 @@ describe('model: populate:', function() {
     });
 
     function confirm(done) {
-      return function(err, litter) {
-        if (err) return done(err);
-        Litter.findById(litter).lean().exec(function(err, doc) {
-          if (err) return done(err);
+      return function (err, litter) {
+        if (err) {
+          return done(err);
+        }
+        Litter.findById(litter).lean().exec(function (err, doc) {
+          if (err) {
+            return done(err);
+          }
           assert.ok(doc.o._id);
           assert.ok(doc.cats[0]);
           assert.ok(doc.cats[0]._id);
@@ -2945,24 +2977,24 @@ describe('model: populate:', function() {
     }
   });
 
-  describe('gh-2252', function() {
-    it('handles skip', function(done) {
+  describe('gh-2252', function () {
+    it('handles skip', function (done) {
       var db = start();
 
       var movieSchema = new Schema({});
-      var categorySchema = new Schema({ movies: [{ type: ObjectId, ref: 'gh-2252-1' }] });
+      var categorySchema = new Schema({movies: [{type: ObjectId, ref: 'gh-2252-1'}]});
 
       var Movie = db.model('gh-2252-1', movieSchema);
       var Category = db.model('gh-2252-2', categorySchema);
 
-      Movie.create({}, {}, {}, function(error) {
+      Movie.create({}, {}, {}, function (error) {
         assert.ifError(error);
-        Movie.find({}, function(error, docs) {
+        Movie.find({}, function (error, docs) {
           assert.ifError(error);
           assert.equal(docs.length, 3);
-          Category.create({ movies: [docs[0]._id, docs[1]._id, docs[2]._id] }, function(error) {
+          Category.create({movies: [docs[0]._id, docs[1]._id, docs[2]._id]}, function (error) {
             assert.ifError(error);
-            Category.findOne({}).populate({ path: 'movies', options: { limit: 2, skip: 1 } }).exec(function(error, category) {
+            Category.findOne({}).populate({path: 'movies', options: {limit: 2, skip: 1}}).exec(function (error, category) {
               assert.ifError(error);
               assert.equal(2, category.movies.length);
               db.close(done);
@@ -2973,24 +3005,24 @@ describe('model: populate:', function() {
     });
   });
 
-  it('handles slice (gh-1934)', function(done) {
+  it('handles slice (gh-1934)', function (done) {
     var db = start();
 
-    var movieSchema = new Schema({ title: String, actors: [String] });
-    var categorySchema = new Schema({ movies: [{ type: ObjectId, ref: 'gh-1934-1' }] });
+    var movieSchema = new Schema({title: String, actors: [String]});
+    var categorySchema = new Schema({movies: [{type: ObjectId, ref: 'gh-1934-1'}]});
 
     var Movie = db.model('gh-1934-1', movieSchema);
     var Category = db.model('gh-1934-2', categorySchema);
     var movies = [
-      { title: 'Rush', actors: ['Chris Hemsworth', 'Daniel Bruhl'] },
-      { title: 'Pacific Rim', actors: ['Charlie Hunnam', 'Idris Elba'] },
-      { title: 'Man of Steel', actors: ['Henry Cavill', 'Amy Adams'] }
+      {title: 'Rush', actors: ['Chris Hemsworth', 'Daniel Bruhl']},
+      {title: 'Pacific Rim', actors: ['Charlie Hunnam', 'Idris Elba']},
+      {title: 'Man of Steel', actors: ['Henry Cavill', 'Amy Adams']}
     ];
-    Movie.create(movies[0], movies[1], movies[2], function(error, m1, m2, m3) {
+    Movie.create(movies[0], movies[1], movies[2], function (error, m1, m2, m3) {
       assert.ifError(error);
-      Category.create({ movies: [m1._id, m2._id, m3._id] }, function(error) {
+      Category.create({movies: [m1._id, m2._id, m3._id]}, function (error) {
         assert.ifError(error);
-        Category.findOne({}).populate({ path: 'movies', options: { slice: { actors: 1 } } }).exec(function(error, category) {
+        Category.findOne({}).populate({path: 'movies', options: {slice: {actors: 1}}}).exec(function (error, category) {
           assert.ifError(error);
           assert.equal(category.movies.length, 3);
           assert.equal(category.movies[0].actors.length, 1);
@@ -3002,7 +3034,7 @@ describe('model: populate:', function() {
     });
   });
 
-  it('handles toObject() (gh-3279)', function(done) {
+  it('handles toObject() (gh-3279)', function (done) {
     var db = start();
 
     var teamSchema = new Schema({
@@ -3014,7 +3046,7 @@ describe('model: populate:', function() {
 
     var calls = 0;
     teamSchema.set('toJSON', {
-      transform: function(doc, ret) {
+      transform: function (doc, ret) {
         ++calls;
         return ret;
       }
@@ -3028,22 +3060,22 @@ describe('model: populate:', function() {
     });
 
     userSchema.set('toJSON', {
-      transform: function(doc, ret) {
+      transform: function (doc, ret) {
         return ret;
       }
     });
 
     var User = db.model('gh3279', userSchema);
 
-    var user = new User({ username: 'Test' });
+    var user = new User({username: 'Test'});
 
-    user.save(function(err) {
+    user.save(function (err) {
       assert.ifError(err);
-      var team = new Team({ members: [{ user: user }] });
+      var team = new Team({members: [{user: user}]});
 
-      team.save(function(err) {
+      team.save(function (err) {
         assert.ifError(err);
-        team.populate('members.user', function() {
+        team.populate('members.user', function () {
           team.toJSON();
           assert.equal(calls, 1);
           done();
@@ -3052,26 +3084,26 @@ describe('model: populate:', function() {
     });
   });
 
-  it('populate option (gh-2321)', function(done) {
+  it('populate option (gh-2321)', function (done) {
     var db = start();
 
-    var User = db.model('User', { name: String });
+    var User = db.model('User', {name: String});
     var Group = db.model('Group', {
-      users: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
+      users: [{type: mongoose.Schema.Types.ObjectId, ref: 'User'}],
       name: String
     });
 
-    User.create({ name: 'Val' }, function(error, user) {
+    User.create({name: 'Val'}, function (error, user) {
       assert.ifError(error);
-      Group.create({ users: [user._id], name: 'test' }, function(error, group) {
+      Group.create({users: [user._id], name: 'test'}, function (error, group) {
         assert.ifError(error);
         test(group._id);
       });
     });
 
-    var test = function(id) {
-      var options = { populate: { path: 'users', model: 'User' } };
-      Group.find({ _id: id }, '-name', options, function(error, group) {
+    var test = function (id) {
+      var options = {populate: {path: 'users', model: 'User'}};
+      Group.find({_id: id}, '-name', options, function (error, group) {
         assert.ifError(error);
         assert.ok(group[0].users[0]._id);
         db.close(done);
diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js
index 1cfbb0052ef..78523c9a12a 100644
--- a/test/model.query.casting.test.js
+++ b/test/model.query.casting.test.js
@@ -28,7 +28,7 @@ Comments.add({
 });
 
 var BlogPostB = new Schema({
-  title: { $type: String },
+  title: {$type: String},
   author: String,
   slug: String,
   date: Date,
@@ -38,25 +38,24 @@ var BlogPostB = new Schema({
   },
   published: Boolean,
   mixed: {},
-  numbers: [{ $type: Number }],
+  numbers: [{$type: Number}],
   tags: [String],
   sigs: [Buffer],
   owners: [ObjectId],
   comments: [Comments],
-  def: { $type: String, default: 'kandinsky' }
-}, { typeKey: '$type' });
+  def: {$type: String, default: 'kandinsky'}
+}, {typeKey: '$type'});
 
 var modelName = 'model.query.casting.blogpost';
 mongoose.model(modelName, BlogPostB);
 var collection = 'blogposts_' + random();
 
-var geoSchemaArray = new Schema({ loc: { type: [Number], index: '2d'}});
-var geoSchemaObject = new Schema({ loc: { long: Number, lat: Number }});
+var geoSchemaArray = new Schema({loc: {type: [Number], index: '2d'}});
+var geoSchemaObject = new Schema({loc: {long: Number, lat: Number}});
 geoSchemaObject.index({'loc': '2d'});
 
-describe('model query casting', function() {
-
-  it('works', function(done) {
+describe('model query casting', function () {
+  it('works', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         title = 'Loki ' + random();
@@ -66,10 +65,10 @@ describe('model query casting', function() {
 
     post.set('title', title);
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      BlogPostB.findOne({ _id: id }, function(err, doc) {
+      BlogPostB.findOne({_id: id}, function (err, doc) {
         assert.ifError(err);
         assert.equal(title, doc.get('title'));
         db.close(done);
@@ -77,18 +76,18 @@ describe('model query casting', function() {
     });
   });
 
-  it('returns cast errors', function(done) {
+  it('returns cast errors', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.find({ date: 'invalid date' }, function(err) {
+    BlogPostB.find({date: 'invalid date'}, function (err) {
       assert.ok(err instanceof Error);
       assert.ok(err instanceof CastError);
       db.close(done);
     });
   });
 
-  it('casts $modifiers', function(done) {
+  it('casts $modifiers', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         post = new BlogPostB({
@@ -97,33 +96,33 @@ describe('model query casting', function() {
           }
         });
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      BlogPostB.find({ 'meta.visitors': { $gt: '-100', $lt: -50 } },
-      function(err, found) {
-        assert.ifError(err);
+      BlogPostB.find({'meta.visitors': {$gt: '-100', $lt: -50}},
+          function (err, found) {
+            assert.ifError(err);
 
-        assert.ok(found);
-        assert.equal(1, found.length);
-        assert.equal(found[0].get('_id').toString(), post.get('_id'));
-        assert.equal(found[0].get('meta.visitors').valueOf(), post.get('meta.visitors').valueOf());
-        db.close(done);
-      });
+            assert.ok(found);
+            assert.equal(1, found.length);
+            assert.equal(found[0].get('_id').toString(), post.get('_id'));
+            assert.equal(found[0].get('meta.visitors').valueOf(), post.get('meta.visitors').valueOf());
+            db.close(done);
+          });
     });
   });
 
-  it('casts $in values of arrays (gh-199)', function(done) {
+  it('casts $in values of arrays (gh-199)', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
     var post = new BlogPostB(),
         id = post._id.toString();
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      BlogPostB.findOne({ _id: { $in: [id] } }, function(err, doc) {
+      BlogPostB.findOne({_id: {$in: [id]}}, function (err, doc) {
         assert.ifError(err);
 
         assert.equal(doc._id.toString(), id);
@@ -132,17 +131,17 @@ describe('model query casting', function() {
     });
   });
 
-  it('casts $in values of arrays with single item instead of array (jrl-3238)', function(done) {
+  it('casts $in values of arrays with single item instead of array (jrl-3238)', function (done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
     var post = new BlogPostB(),
         id = post._id.toString();
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      BlogPostB.findOne({ _id: { $in: id } }, function(err, doc) {
+      BlogPostB.findOne({_id: {$in: id}}, function (err, doc) {
         assert.ifError(err);
 
         assert.equal(doc._id.toString(), id);
@@ -152,7 +151,7 @@ describe('model query casting', function() {
     });
   });
 
-  it('casts $nin values of arrays (gh-232)', function(done) {
+  it('casts $nin values of arrays (gh-232)', function (done) {
     var db = start(),
         NinSchema = new Schema({
           num: Number
@@ -162,13 +161,13 @@ describe('model query casting', function() {
 
     var Nin = db.model('Nin', 'nins_' + random());
 
-    Nin.create({ num: 1 }, function(err) {
+    Nin.create({num: 1}, function (err) {
       assert.ifError(err);
-      Nin.create({ num: 2 }, function(err) {
+      Nin.create({num: 2}, function (err) {
         assert.ifError(err);
-        Nin.create({num: 3}, function(err) {
+        Nin.create({num: 3}, function (err) {
           assert.ifError(err);
-          Nin.find({ num: {$nin: [2]}}, function(err, found) {
+          Nin.find({num: {$nin: [2]}}, function (err, found) {
             assert.ifError(err);
             assert.equal(2, found.length);
             db.close(done);
@@ -178,7 +177,7 @@ describe('model query casting', function() {
     });
   });
 
-  it('works when finding by Date (gh-204)', function(done) {
+  it('works when finding by Date (gh-204)', function (done) {
     var db = start(),
         P = db.model(modelName, collection);
 
@@ -186,17 +185,17 @@ describe('model query casting', function() {
 
     post.meta.date = new Date();
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      P.findOne({ _id: post._id, 'meta.date': { $lte: Date.now() } }, function(err, doc) {
+      P.findOne({_id: post._id, 'meta.date': {$lte: Date.now()}}, function (err, doc) {
         assert.ifError(err);
 
         assert.equal(doc._id.toString(), post._id.toString());
         doc.meta.date = null;
-        doc.save(function(err) {
+        doc.save(function (err) {
           assert.ifError(err);
-          P.findById(doc._id, function(err, doc) {
+          P.findById(doc._id, function (err, doc) {
             assert.ifError(err);
             assert.strictEqual(doc.meta.date, null);
             db.close(done);
@@ -206,14 +205,14 @@ describe('model query casting', function() {
     });
   });
 
-  it('works with $type matching', function(done) {
+  it('works with $type matching', function (done) {
     var db = start(),
         B = db.model(modelName, collection);
 
-    B.find({ title: { $type: "asd" }}, function(err) {
-      assert.equal(err.message,"$type parameter must be Number");
+    B.find({title: {$type: 'asd'}}, function (err) {
+      assert.equal(err.message, '$type parameter must be Number');
 
-      B.find({ title: { $type: 2 }}, function(err, posts) {
+      B.find({title: {$type: 2}}, function (err, posts) {
         assert.ifError(err);
         assert.strictEqual(Array.isArray(posts), true);
         db.close(done);
@@ -221,14 +220,14 @@ describe('model query casting', function() {
     });
   });
 
-  it('works when finding Boolean with $in (gh-998)', function(done) {
+  it('works when finding Boolean with $in (gh-998)', function (done) {
     var db = start(),
         B = db.model(modelName, collection);
 
-    var b = new B({ published: true });
-    b.save(function(err) {
+    var b = new B({published: true});
+    b.save(function (err) {
       assert.ifError(err);
-      B.find({ _id: b._id, boolean: { $in: [null, true] }}, function(err, doc) {
+      B.find({_id: b._id, boolean: {$in: [null, true]}}, function (err, doc) {
         assert.ifError(err);
         assert.ok(doc);
         assert.equal(doc[0].id, b.id);
@@ -237,14 +236,14 @@ describe('model query casting', function() {
     });
   });
 
-  it('works when finding Boolean with $ne (gh-1093)', function(done) {
+  it('works when finding Boolean with $ne (gh-1093)', function (done) {
     var db = start(),
         B = db.model(modelName, collection + random());
 
-    var b = new B({ published: false });
-    b.save(function(err) {
+    var b = new B({published: false});
+    b.save(function (err) {
       assert.ifError(err);
-      B.find().ne('published', true).exec(function(err, doc) {
+      B.find().ne('published', true).exec(function (err, doc) {
         assert.ifError(err);
         assert.ok(doc);
         assert.equal(doc[0].id, b.id);
@@ -253,29 +252,31 @@ describe('model query casting', function() {
     });
   });
 
-  it('properly casts $and (gh-1180)', function(done) {
+  it('properly casts $and (gh-1180)', function (done) {
     var db = start(),
         B = db.model(modelName, collection + random()),
-        result = B.find({}).cast(B, {$and:[{date:'1987-03-17T20:00:00.000Z'}, {_id:'000000000000000000000000'}]});
+        result = B.find({}).cast(B, {$and: [{date: '1987-03-17T20:00:00.000Z'}, {_id: '000000000000000000000000'}]});
     assert.ok(result.$and[0].date instanceof Date);
     assert.ok(result.$and[1]._id instanceof DocumentObjectId);
     db.close(done);
   });
 
-  describe('$near', function() {
+  describe('$near', function () {
     this.slow(60);
 
-    it('with arrays', function(done) {
+    it('with arrays', function (done) {
       var db = start(),
-          Test = db.model('Geo4', geoSchemaArray, "y" + random());
+          Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
       Test.once('index', complete);
-      Test.create({ loc: [ 10, 20 ]}, { loc: [ 40, 90 ]}, complete);
+      Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
       var pending = 2;
 
       function complete(err) {
-        if (complete.ran) return;
+        if (complete.ran) {
+          return;
+        }
         if (err) {
           db.close();
           return done(complete.ran = err);
@@ -284,7 +285,7 @@ describe('model query casting', function() {
       }
 
       function test() {
-        Test.find({ loc: { $near: ['30', '40'] }}, function(err, docs) {
+        Test.find({loc: {$near: ['30', '40']}}, function (err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -293,14 +294,16 @@ describe('model query casting', function() {
       }
     });
 
-    it('with objects', function(done) {
+    it('with objects', function (done) {
       var db = start(),
-          Test = db.model('Geo5', geoSchemaObject, "y" + random());
+          Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
       var pending = 2;
 
       function complete(err) {
-        if (complete.ran) return;
+        if (complete.ran) {
+          return;
+        }
         if (err) {
           db.close();
           return done(complete.ran = err);
@@ -309,7 +312,7 @@ describe('model query casting', function() {
       }
 
       function test() {
-        Test.find({ loc: { $near: ['30', '40'], $maxDistance: 51 }}, function(err, docs) {
+        Test.find({loc: {$near: ['30', '40'], $maxDistance: 51}}, function (err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -317,21 +320,23 @@ describe('model query casting', function() {
         });
       }
 
-      Test.create({ loc: {long: 10, lat:20 }}, { loc: {long:40, lat:90 }}, complete);
+      Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
       Test.once('index', complete);
     });
 
-    it('with nested objects', function(done) {
+    it('with nested objects', function (done) {
       var db = start();
-      var geoSchemaObject = new Schema({ loc: { nested: { long: Number, lat: Number }}});
+      var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
       geoSchemaObject.index({'loc.nested': '2d'});
 
-      var Test = db.model('Geo52', geoSchemaObject, "y" + random());
+      var Test = db.model('Geo52', geoSchemaObject, 'y' + random());
 
       var pending = 2;
 
       function complete(err) {
-        if (complete.ran) return;
+        if (complete.ran) {
+          return;
+        }
         if (err) {
           db.close();
           return done(complete.ran = err);
@@ -340,7 +345,7 @@ describe('model query casting', function() {
       }
 
       function test() {
-        Test.find({ 'loc.nested': {$near: ['30', '40'], $maxDistance: '50' }}, function(err, docs) {
+        Test.find({'loc.nested': {$near: ['30', '40'], $maxDistance: '50'}}, function (err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(1, docs.length);
@@ -350,31 +355,36 @@ describe('model query casting', function() {
 
       Test.once('index', complete);
       Test.create(
-          { loc: {nested:{long:10, lat:20 }}},
-         { loc: {nested:{long:40, lat:90 }}},
-         complete);
+          {loc: {nested: {long: 10, lat: 20}}},
+          {loc: {nested: {long: 40, lat: 90}}},
+          complete);
     });
   });
 
-  describe('$nearSphere', function() {
+  describe('$nearSphere', function () {
     this.slow(70);
 
-    it('with arrays', function(done) {
+    it('with arrays', function (done) {
       var db = start(),
-          Test = db.model('Geo4', geoSchemaArray, "y" + random());
+          Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
       var pending = 2;
+
       function complete(err) {
-        if (complete.ran) return;
-        if (err) return done(complete.err = err);
+        if (complete.ran) {
+          return;
+        }
+        if (err) {
+          return done(complete.err = err);
+        }
         --pending || test();
       }
 
       Test.on('index', complete);
-      Test.create({ loc: [ 10, 20 ]}, { loc: [ 40, 90 ]}, complete);
+      Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
       function test() {
-        Test.find({ loc: { $nearSphere: ['30', '40'] }}, function(err, docs) {
+        Test.find({loc: {$nearSphere: ['30', '40']}}, function (err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -383,22 +393,27 @@ describe('model query casting', function() {
       }
     });
 
-    it('with objects', function(done) {
+    it('with objects', function (done) {
       var db = start(),
-          Test = db.model('Geo5', geoSchemaObject, "y" + random());
+          Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
       var pending = 2;
+
       function complete(err) {
-        if (complete.ran) return;
-        if (err) return done(complete.err = err);
+        if (complete.ran) {
+          return;
+        }
+        if (err) {
+          return done(complete.err = err);
+        }
         --pending || test();
       }
 
       Test.on('index', complete);
-      Test.create({ loc: {long: 10, lat:20 }}, { loc: {long:40, lat:90 }}, complete);
+      Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
       function test() {
-        Test.find({ loc: { $nearSphere: ['30', '40'], $maxDistance: 1 }}, function(err, docs) {
+        Test.find({loc: {$nearSphere: ['30', '40'], $maxDistance: 1}}, function (err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -407,25 +422,30 @@ describe('model query casting', function() {
       }
     });
 
-    it('with nested objects', function(done) {
+    it('with nested objects', function (done) {
       var db = start();
-      var geoSchemaObject = new Schema({ loc: { nested: { long: Number, lat: Number }}});
+      var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
       geoSchemaObject.index({'loc.nested': '2d'});
 
-      var Test = db.model('Geo52', geoSchemaObject, "y" + random());
+      var Test = db.model('Geo52', geoSchemaObject, 'y' + random());
 
       var pending = 2;
+
       function complete(err) {
-        if (complete.ran) return;
-        if (err) return done(complete.err = err);
+        if (complete.ran) {
+          return;
+        }
+        if (err) {
+          return done(complete.err = err);
+        }
         --pending || test();
       }
 
       Test.on('index', complete);
-      Test.create({ loc: {nested:{long:10, lat:20 }}}, { loc: {nested:{long:40, lat:90 }}}, complete);
+      Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
       function test() {
-        Test.find({ 'loc.nested': {$nearSphere: ['30', '40'], $maxDistance: 1 }}, function(err, docs) {
+        Test.find({'loc.nested': {$nearSphere: ['30', '40'], $maxDistance: 1}}, function (err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -435,26 +455,31 @@ describe('model query casting', function() {
     });
   });
 
-  describe('$within', function() {
+  describe('$within', function () {
     this.slow(60);
 
-    describe('$centerSphere', function() {
-      it('with arrays', function(done) {
+    describe('$centerSphere', function () {
+      it('with arrays', function (done) {
         var db = start(),
-            Test = db.model('Geo4', geoSchemaArray, "y" + random());
+            Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: [ 10, 20 ]}, { loc: [ 40, 90 ]}, complete);
+        Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
         function test() {
-          Test.find({ loc: { $within: { $centerSphere: [['11', '20'], '0.4'] }}}, function(err, docs) {
+          Test.find({loc: {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -463,22 +488,27 @@ describe('model query casting', function() {
         }
       });
 
-      it('with objects', function(done) {
+      it('with objects', function (done) {
         var db = start(),
-            Test = db.model('Geo5', geoSchemaObject, "y" + random());
+            Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: {long:10, lat:20 }}, { loc: {long:40, lat:90 }}, complete);
+        Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
         function test() {
-          Test.find({ loc: { $within: { $centerSphere: [['11', '20'], '0.4'] }}}, function(err, docs) {
+          Test.find({loc: {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -487,25 +517,30 @@ describe('model query casting', function() {
         }
       });
 
-      it('with nested objects', function(done) {
+      it('with nested objects', function (done) {
         var db = start();
-        var geoSchemaObject = new Schema({ loc: { nested: { long: Number, lat: Number }}});
+        var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
         geoSchemaObject.index({'loc.nested': '2d'});
 
-        var Test = db.model('Geo52', geoSchemaObject, "y" + random());
+        var Test = db.model('Geo52', geoSchemaObject, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: {nested:{long:10, lat:20 }}}, { loc: {nested:{long:40, lat:90 }}}, complete);
+        Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
         function test() {
-          Test.find({ 'loc.nested': { $within: { $centerSphere: [['11', '20'], '0.4'] }}}, function(err, docs) {
+          Test.find({'loc.nested': {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -515,23 +550,28 @@ describe('model query casting', function() {
       });
     });
 
-    describe('$center', function() {
-      it('with arrays', function(done) {
+    describe('$center', function () {
+      it('with arrays', function (done) {
         var db = start(),
-            Test = db.model('Geo4', geoSchemaArray, "y" + random());
+            Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: [ 10, 20 ]}, { loc: [ 40, 90 ]}, complete);
+        Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
         function test() {
-          Test.find({ loc: { $within: { $center: [['11', '20'], '1'] }}}, function(err, docs) {
+          Test.find({loc: {$within: {$center: [['11', '20'], '1']}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -540,22 +580,27 @@ describe('model query casting', function() {
         }
       });
 
-      it('with objects', function(done) {
+      it('with objects', function (done) {
         var db = start(),
-            Test = db.model('Geo5', geoSchemaObject, "y" + random());
+            Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: {long:10, lat:20 }}, { loc: {long:40, lat:90 }}, complete);
+        Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
         function test() {
-          Test.find({ loc: { $within: { $center: [['11', '20'], '1'] }}}, function(err, docs) {
+          Test.find({loc: {$within: {$center: [['11', '20'], '1']}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -564,25 +609,30 @@ describe('model query casting', function() {
         }
       });
 
-      it('with nested objects', function(done) {
+      it('with nested objects', function (done) {
         var db = start();
-        var geoSchemaObject = new Schema({ loc: { nested: { long: Number, lat: Number }}});
+        var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
         geoSchemaObject.index({'loc.nested': '2d'});
 
-        var Test = db.model('Geo52', geoSchemaObject, "y" + random());
+        var Test = db.model('Geo52', geoSchemaObject, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: {nested:{long:10, lat:20 }}}, { loc: {nested:{long:40, lat:90 }}}, complete);
+        Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
         function test() {
-          Test.find({ 'loc.nested': { $within: { $center: [['11', '20'], '1'] }}}, function(err, docs) {
+          Test.find({'loc.nested': {$within: {$center: [['11', '20'], '1']}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -592,23 +642,28 @@ describe('model query casting', function() {
       });
     });
 
-    describe('$polygon', function() {
-      it('with arrays', function(done) {
+    describe('$polygon', function () {
+      it('with arrays', function (done) {
         var db = start(),
-            Test = db.model('Geo4', geoSchemaArray, "y" + random());
+            Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: [ 10, 20 ]}, { loc: [ 40, 90 ]}, complete);
+        Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
         function test() {
-          Test.find({ loc: { $within: { $polygon: [['8', '1'], ['8', '100'],['50','100'],['50','1']] }}}, function(err, docs) {
+          Test.find({loc: {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -617,22 +672,27 @@ describe('model query casting', function() {
         }
       });
 
-      it('with objects', function(done) {
+      it('with objects', function (done) {
         var db = start(),
-            Test = db.model('Geo5', geoSchemaObject, "y" + random());
+            Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: {long:10, lat:20 }}, { loc: {long:40, lat:90 }}, complete);
+        Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
         function test() {
-          Test.find({ loc: { $within: { $polygon: [['8', '1'], ['8', '100'],['50','100'],['50','1']] }}}, function(err, docs) {
+          Test.find({loc: {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -641,25 +701,30 @@ describe('model query casting', function() {
         }
       });
 
-      it('with nested objects', function(done) {
+      it('with nested objects', function (done) {
         var db = start();
-        var geoSchemaObject = new Schema({ loc: { nested: { long: Number, lat: Number }}});
+        var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
         geoSchemaObject.index({'loc.nested': '2d'});
 
-        var Test = db.model('Geo52', geoSchemaObject, "y" + random());
+        var Test = db.model('Geo52', geoSchemaObject, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: {nested:{long:10, lat:20 }}}, { loc: {nested:{long:40, lat:90 }}}, complete);
+        Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
         function test() {
-          Test.find({ 'loc.nested': { $within: { $polygon: [['8', '1'], ['8', '100'],['50','100'],['50','1']] }}}, function(err, docs) {
+          Test.find({'loc.nested': {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -669,24 +734,28 @@ describe('model query casting', function() {
       });
     });
 
-    describe('$box', function() {
-      it('with arrays', function(done) {
-
+    describe('$box', function () {
+      it('with arrays', function (done) {
         var db = start(),
-            Test = db.model('Geo4', geoSchemaArray, "y" + random());
+            Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: [ 10, 20 ]}, { loc: [ 40, 90 ]}, complete);
+        Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
         function test() {
-          Test.find({ loc: { $within: { $box: [['8', '1'], ['50','100']] }}}, function(err, docs) {
+          Test.find({loc: {$within: {$box: [['8', '1'], ['50', '100']]}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -695,22 +764,27 @@ describe('model query casting', function() {
         }
       });
 
-      it('with objects', function(done) {
+      it('with objects', function (done) {
         var db = start(),
-            Test = db.model('Geo5', geoSchemaObject, "y" + random());
+            Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: {long:10, lat:20 }}, { loc: {long:40, lat:90 }}, complete);
+        Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
         function test() {
-          Test.find({ loc: { $within: { $box: [['8', '1'], ['50','100']] }}}, function(err, docs) {
+          Test.find({loc: {$within: {$box: [['8', '1'], ['50', '100']]}}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -719,25 +793,30 @@ describe('model query casting', function() {
         }
       });
 
-      it('with nested objects', function(done) {
+      it('with nested objects', function (done) {
         var db = start();
-        var geoSchemaObject = new Schema({ loc: { nested: { long: Number, lat: Number }}});
+        var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
         geoSchemaObject.index({'loc.nested': '2d'});
 
-        var Test = db.model('Geo52', geoSchemaObject, "y" + random());
+        var Test = db.model('Geo52', geoSchemaObject, 'y' + random());
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.err = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.err = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: {nested:{long:10, lat:20 }}}, { loc: {nested:{long:40, lat:90 }}}, complete);
+        Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
         function test() {
-          Test.find({ 'loc.nested': { $within: { $box: [['8', '1'], ['50','100']] }}}, function(err, docs) {
+          Test.find({'loc.nested': {$within: {$box: [['8', '1'], ['50', '100']]}}}, function (err, docs) {
             assert.ifError(err);
             assert.equal(2, docs.length);
             db.close(done);
@@ -747,37 +826,35 @@ describe('model query casting', function() {
     });
   });
 
-  describe('$options', function() {
-    it('works on arrays gh-1462', function(done) {
+  describe('$options', function () {
+    it('works on arrays gh-1462', function (done) {
       var opts = {};
-      opts.toString = function() {
+      opts.toString = function () {
         return 'img';
       };
 
       var db = start(),
           B = db.model(modelName, collection + random()),
-          result = B.find({}).cast(B, { tags: {$regex:/a/, $options: opts}});
+          result = B.find({}).cast(B, {tags: {$regex: /a/, $options: opts}});
 
       assert.equal('img', result.tags.$options);
       db.close(done);
     });
   });
 
-  describe('$elemMatch', function() {
-    it('should cast String to ObjectId in $elemMatch', function(done) {
+  describe('$elemMatch', function () {
+    it('should cast String to ObjectId in $elemMatch', function (done) {
       var db = start(),
           BlogPostB = db.model(modelName, collection);
 
       var commentId = mongoose.Types.ObjectId(111);
 
-      var post = new BlogPostB({
-            comments: [{ _id: commentId }]
-          }), id = post._id.toString();
+      var post = new BlogPostB({comments: [{_id: commentId}]}), id = post._id.toString();
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({ _id: id, comments: { $elemMatch: { _id: commentId.toString() } } }, function(err, doc) {
+        BlogPostB.findOne({_id: id, comments: {$elemMatch: {_id: commentId.toString()}}}, function (err, doc) {
           assert.ifError(err);
 
           assert.equal(doc._id.toString(), id);
@@ -786,20 +863,18 @@ describe('model query casting', function() {
       });
     });
 
-    it('should cast String to ObjectId in $elemMatch inside $not', function(done) {
+    it('should cast String to ObjectId in $elemMatch inside $not', function (done) {
       var db = start(),
           BlogPostB = db.model(modelName, collection);
 
       var commentId = mongoose.Types.ObjectId(111);
 
-      var post = new BlogPostB({
-            comments: [{ _id: commentId }]
-          }), id = post._id.toString();
+      var post = new BlogPostB({comments: [{_id: commentId}]}), id = post._id.toString();
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({ _id: id, comments: { $not: { $elemMatch: { _id: commentId.toString() } } } }, function(err, doc) {
+        BlogPostB.findOne({_id: id, comments: {$not: {$elemMatch: {_id: commentId.toString()}}}}, function (err, doc) {
           assert.ifError(err);
 
           assert.equal(doc, null);
@@ -809,19 +884,19 @@ describe('model query casting', function() {
     });
   });
 
-  it('works with $all (gh-3394)', function(done) {
+  it('works with $all (gh-3394)', function (done) {
     var db = start();
 
-    var MyModel = db.model('gh3394', { tags: [ObjectId] });
+    var MyModel = db.model('gh3394', {tags: [ObjectId]});
 
     var doc = {
       tags: ['00000000000000000000000a', '00000000000000000000000b']
     };
 
-    MyModel.create(doc, function(error, savedDoc) {
+    MyModel.create(doc, function (error, savedDoc) {
       assert.ifError(error);
       assert.equal(typeof savedDoc.tags[0], 'object');
-      MyModel.findOne({ tags: { $all: doc.tags } }, function(error, doc) {
+      MyModel.findOne({tags: {$all: doc.tags}}, function (error, doc) {
         assert.ifError(error);
         assert.ok(doc);
         db.close(done);
diff --git a/test/model.querying.test.js b/test/model.querying.test.js
index cc381179363..d97fcf97504 100644
--- a/test/model.querying.test.js
+++ b/test/model.querying.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Test dependencies.
  */
@@ -42,7 +41,7 @@ var BlogPostB = new Schema({
   sigs: [Buffer],
   owners: [ObjectId],
   comments: [Comments],
-  def: { type: String, default: 'kandinsky' }
+  def: {type: String, default: 'kandinsky'}
 });
 
 mongoose.model('BlogPostB', BlogPostB);
@@ -54,20 +53,24 @@ var ModSchema = new Schema({
 });
 mongoose.model('Mod', ModSchema);
 
-var geoSchema = new Schema({ loc: { type: [Number], index: '2d'}});
+var geoSchema = new Schema({loc: {type: [Number], index: '2d'}});
 
-describe('model: querying:', function() {
+describe('model: querying:', function () {
   var mongo26_or_greater = false;
-  before(function(done) {
-    start.mongodVersion(function(err, version) {
-      if (err) throw err;
+  before(function (done) {
+    start.mongodVersion(function (err, version) {
+      if (err) {
+        throw err;
+      }
       mongo26_or_greater = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
-      if (!mongo26_or_greater) console.log('not testing mongodb 2.6 features');
+      if (!mongo26_or_greater) {
+        console.log('not testing mongodb 2.6 features');
+      }
       done();
     });
   });
 
-  it('find returns a Query', function(done) {
+  it('find returns a Query', function (done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection);
 
@@ -89,7 +92,7 @@ describe('model: querying:', function() {
     db.close(done);
   });
 
-  it('findOne returns a Query', function(done) {
+  it('findOne returns a Query', function (done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection);
 
@@ -111,7 +114,7 @@ describe('model: querying:', function() {
     db.close(done);
   });
 
-  it('an empty find does not hang', function(done) {
+  it('an empty find does not hang', function (done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection);
 
@@ -122,14 +125,16 @@ describe('model: querying:', function() {
     BlogPostB.find({}, fn);
   });
 
-  it('a query is executed when a callback is passed', function(done) {
+  it('a query is executed when a callback is passed', function (done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         count = 5,
-        q = { _id: new DocumentObjectId }; // make sure the query is fast
+        q = {_id: new DocumentObjectId}; // make sure the query is fast
 
     function fn() {
-      if (--count) return;
+      if (--count) {
+        return;
+      }
       db.close(done);
     }
 
@@ -149,14 +154,16 @@ describe('model: querying:', function() {
     assert.ok(BlogPostB.find(q, '', {}, fn) instanceof Query);
   });
 
-  it('query is executed where a callback for findOne', function(done) {
+  it('query is executed where a callback for findOne', function (done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         count = 5,
-        q = { _id: new DocumentObjectId }; // make sure the query is fast
+        q = {_id: new DocumentObjectId}; // make sure the query is fast
 
     function fn() {
-      if (--count) return;
+      if (--count) {
+        return;
+      }
       db.close();
       done();
     }
@@ -177,8 +184,8 @@ describe('model: querying:', function() {
     assert.ok(BlogPostB.findOne(q, null, {}, fn) instanceof Query);
   });
 
-  describe('count', function() {
-    it('returns a Query', function(done) {
+  describe('count', function () {
+    it('returns a Query', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
       assert.ok(BlogPostB.count({}) instanceof Query);
@@ -186,13 +193,15 @@ describe('model: querying:', function() {
       done();
     });
 
-    it('Query executes when you pass a callback', function(done) {
+    it('Query executes when you pass a callback', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           pending = 2;
 
       function fn() {
-        if (--pending) return;
+        if (--pending) {
+          return;
+        }
         db.close();
         done();
       }
@@ -201,7 +210,7 @@ describe('model: querying:', function() {
       assert.ok(BlogPostB.count(fn) instanceof Query);
     });
 
-    it('counts documents', function(done) {
+    it('counts documents', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Wooooot ' + random();
@@ -209,16 +218,16 @@ describe('model: querying:', function() {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
         var post = new BlogPostB();
         post.set('title', title);
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ifError(err);
 
-          BlogPostB.count({ title: title }, function(err, count) {
+          BlogPostB.count({title: title}, function (err, count) {
             assert.ifError(err);
 
             assert.equal('number', typeof count);
@@ -232,8 +241,8 @@ describe('model: querying:', function() {
     });
   });
 
-  describe('distinct', function() {
-    it('returns a Query', function(done) {
+  describe('distinct', function () {
+    it('returns a Query', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -242,14 +251,14 @@ describe('model: querying:', function() {
       done();
     });
 
-    it('executes when you pass a callback', function(done) {
+    it('executes when you pass a callback', function (done) {
       var db = start();
-      var Address = new Schema({ zip: String });
+      var Address = new Schema({zip: String});
       Address = db.model('Address', Address, 'addresses_' + random());
 
-      Address.create({ zip: '10010'}, { zip: '10010'}, { zip: '99701'}, function(err) {
+      Address.create({zip: '10010'}, {zip: '10010'}, {zip: '99701'}, function (err) {
         assert.strictEqual(null, err);
-        var query = Address.distinct('zip', {}, function(err, results) {
+        var query = Address.distinct('zip', {}, function (err, results) {
           assert.ifError(err);
           assert.equal(2, results.length);
           assert.ok(results.indexOf('10010') > -1);
@@ -260,13 +269,13 @@ describe('model: querying:', function() {
       });
     });
 
-    it('permits excluding conditions gh-1541', function(done) {
+    it('permits excluding conditions gh-1541', function (done) {
       var db = start();
-      var Address = new Schema({ zip: String });
+      var Address = new Schema({zip: String});
       Address = db.model('Address', Address, 'addresses_' + random());
-      Address.create({ zip: '10010'}, { zip: '10010'}, { zip: '99701'}, function(err) {
+      Address.create({zip: '10010'}, {zip: '10010'}, {zip: '99701'}, function (err) {
         assert.ifError(err);
-        Address.distinct('zip', function(err, results) {
+        Address.distinct('zip', function (err, results) {
           assert.ifError(err);
           assert.equal(2, results.length);
           assert.ok(results.indexOf('10010') > -1);
@@ -277,8 +286,8 @@ describe('model: querying:', function() {
     });
   });
 
-  describe('update', function() {
-    it('returns a Query', function(done) {
+  describe('update', function () {
+    it('returns a Query', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -288,13 +297,15 @@ describe('model: querying:', function() {
       done();
     });
 
-    it('Query executes when you pass a callback', function(done) {
+    it('Query executes when you pass a callback', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           count = 2;
 
       function fn() {
-        if (--count) return;
+        if (--count) {
+          return;
+        }
         db.close();
         done();
       }
@@ -303,15 +314,15 @@ describe('model: querying:', function() {
       assert.ok(BlogPostB.update({title: random()}, {}, {}, fn) instanceof Query);
     });
 
-    it('can handle minimize option (gh-3381)', function(done) {
+    it('can handle minimize option (gh-3381)', function (done) {
       var db = start();
       var Model = db.model('gh3381', {
         name: String,
         mixed: Schema.Types.Mixed
       });
 
-      var query = Model.update({}, { mixed: {}, name: 'abc' },
-        { minimize: true });
+      var query = Model.update({}, {mixed: {}, name: 'abc'},
+          {minimize: true});
 
       assert.ok(!query._update.$set.mixed);
 
@@ -319,8 +330,8 @@ describe('model: querying:', function() {
     });
   });
 
-  describe('findOne', function() {
-    it('works', function(done) {
+  describe('findOne', function () {
+    it('works', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Wooooot ' + random();
@@ -328,10 +339,10 @@ describe('model: querying:', function() {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({ title: title }, function(err, doc) {
+        BlogPostB.findOne({title: title}, function (err, doc) {
           assert.ifError(err);
           assert.equal(title, doc.get('title'));
           assert.equal(false, doc.isNew);
@@ -342,7 +353,7 @@ describe('model: querying:', function() {
       });
     });
 
-    it('casts $modifiers', function(done) {
+    it('casts $modifiers', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           post = new BlogPostB({
@@ -351,11 +362,11 @@ describe('model: querying:', function() {
             }
           });
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        var query = { 'meta.visitors': { $gt: '-20', $lt: -1 }};
-        BlogPostB.findOne(query, function(err, found) {
+        var query = {'meta.visitors': {$gt: '-20', $lt: -1}};
+        BlogPostB.findOne(query, function (err, found) {
           assert.ifError(err);
           assert.ok(found);
           assert.equal(found.get('meta.visitors').valueOf(), post.get('meta.visitors').valueOf());
@@ -367,7 +378,7 @@ describe('model: querying:', function() {
       });
     });
 
-    it('querying if an array contains one of multiple members $in a set', function(done) {
+    it('querying if an array contains one of multiple members $in a set', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -375,16 +386,16 @@ describe('model: querying:', function() {
 
       post.tags.push('football');
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({tags: {$in: ['football', 'baseball']}}, function(err, doc) {
+        BlogPostB.findOne({tags: {$in: ['football', 'baseball']}}, function (err, doc) {
           assert.ifError(err);
-          assert.equal(doc._id.toString(),post._id);
+          assert.equal(doc._id.toString(), post._id);
 
-          BlogPostB.findOne({ _id: post._id, tags: /otba/i }, function(err, doc) {
+          BlogPostB.findOne({_id: post._id, tags: /otba/i}, function (err, doc) {
             assert.ifError(err);
-            assert.equal(doc._id.toString(),post._id);
+            assert.equal(doc._id.toString(), post._id);
             db.close();
             done();
           });
@@ -392,18 +403,18 @@ describe('model: querying:', function() {
       });
     });
 
-    it('querying if an array contains one of multiple members $in a set 2', function(done) {
+    it('querying if an array contains one of multiple members $in a set 2', function (done) {
       var db = start(),
           BlogPostA = db.model('BlogPostB', collection);
 
-      var post = new BlogPostA({ tags: ['gooberOne'] });
+      var post = new BlogPostA({tags: ['gooberOne']});
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        var query = {tags: {$in: [ 'gooberOne' ]}};
+        var query = {tags: {$in: ['gooberOne']}};
 
-        BlogPostA.findOne(query, function(err, returned) {
+        BlogPostA.findOne(query, function (err, returned) {
           cb();
           assert.ifError(err);
           assert.ok(!!~returned.tags.indexOf('gooberOne'));
@@ -411,10 +422,10 @@ describe('model: querying:', function() {
         });
       });
 
-      post.collection.insert({ meta: { visitors: 9898, a: null } }, {}, function(err, b) {
+      post.collection.insert({meta: {visitors: 9898, a: null}}, {}, function (err, b) {
         assert.ifError(err);
 
-        BlogPostA.findOne({_id: b.ops[0]._id}, function(err, found) {
+        BlogPostA.findOne({_id: b.ops[0]._id}, function (err, found) {
           cb();
           assert.ifError(err);
           assert.equal(found.get('meta.visitors'), 9898);
@@ -422,40 +433,45 @@ describe('model: querying:', function() {
       });
 
       var pending = 2;
+
       function cb() {
-        if (--pending) return;
+        if (--pending) {
+          return;
+        }
         db.close();
         done();
       }
     });
 
-    it('querying via $where a string', function(done) {
+    it('querying via $where a string', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({ title: 'Steve Jobs', author: 'Steve Jobs'}, function(err, created) {
+      BlogPostB.create({title: 'Steve Jobs', author: 'Steve Jobs'}, function (err, created) {
         assert.ifError(err);
 
-        BlogPostB.findOne({ $where: "this.title && this.title === this.author" }, function(err, found) {
+        BlogPostB.findOne({$where: 'this.title && this.title === this.author'}, function (err, found) {
           assert.ifError(err);
 
-          assert.equal(found._id.toString(),created._id);
+          assert.equal(found._id.toString(), created._id);
           db.close();
           done();
         });
       });
     });
 
-    it('querying via $where a function', function(done) {
+    it('querying via $where a function', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({ author: 'Atari', slug: 'Atari'}, function(err, created) {
+      BlogPostB.create({author: 'Atari', slug: 'Atari'}, function (err, created) {
         assert.ifError(err);
 
-        BlogPostB.findOne({ $where: function() {
-          return (this.author && this.slug && this.author === this.slug);
-        } }, function(err, found) {
+        BlogPostB.findOne({
+          $where: function () {
+            return (this.author && this.slug && this.author === this.slug);
+          }
+        }, function (err, found) {
           assert.ifError(err);
 
           assert.equal(found._id.toString(), created._id);
@@ -465,7 +481,7 @@ describe('model: querying:', function() {
       });
     });
 
-    it('based on nested fields', function(done) {
+    it('based on nested fields', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           post = new BlogPostB({
@@ -474,13 +490,13 @@ describe('model: querying:', function() {
             }
           });
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({ 'meta.visitors': 5678 }, function(err, found) {
+        BlogPostB.findOne({'meta.visitors': 5678}, function (err, found) {
           assert.ifError(err);
           assert.equal(found.get('meta.visitors')
-            .valueOf(), post.get('meta.visitors').valueOf());
+          .valueOf(), post.get('meta.visitors').valueOf());
           assert.equal(found.get('_id').toString(), post.get('_id'));
           db.close();
           done();
@@ -488,26 +504,26 @@ describe('model: querying:', function() {
       });
     });
 
-    it('based on embedded doc fields (gh-242, gh-463)', function(done) {
+    it('based on embedded doc fields (gh-242, gh-463)', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({comments: [{title: 'i should be queryable'}], numbers: [1,2,33333], tags: ['yes', 'no']}, function(err, created) {
+      BlogPostB.create({comments: [{title: 'i should be queryable'}], numbers: [1, 2, 33333], tags: ['yes', 'no']}, function (err, created) {
         assert.ifError(err);
-        BlogPostB.findOne({'comments.title': 'i should be queryable'}, function(err, found) {
+        BlogPostB.findOne({'comments.title': 'i should be queryable'}, function (err, found) {
           assert.ifError(err);
           assert.equal(found._id.toString(), created._id);
 
-          BlogPostB.findOne({'comments.0.title': 'i should be queryable'}, function(err, found) {
+          BlogPostB.findOne({'comments.0.title': 'i should be queryable'}, function (err, found) {
             assert.ifError(err);
             assert.equal(found._id.toString(), created._id);
 
             // GH-463
-            BlogPostB.findOne({'numbers.2': 33333}, function(err, found) {
+            BlogPostB.findOne({'numbers.2': 33333}, function (err, found) {
               assert.ifError(err);
               assert.equal(found._id.toString(), created._id);
 
-              BlogPostB.findOne({'tags.1': 'no'}, function(err, found) {
+              BlogPostB.findOne({'tags.1': 'no'}, function (err, found) {
                 assert.ifError(err);
                 assert.equal(found._id.toString(), created._id);
                 db.close();
@@ -519,14 +535,14 @@ describe('model: querying:', function() {
       });
     });
 
-    it('works with nested docs and string ids (gh-389)', function(done) {
+    it('works with nested docs and string ids (gh-389)', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({comments: [{title: 'i should be queryable by _id'}, {title: 'me too me too!'}]}, function(err, created) {
+      BlogPostB.create({comments: [{title: 'i should be queryable by _id'}, {title: 'me too me too!'}]}, function (err, created) {
         assert.ifError(err);
         var id = created.comments[1]._id.toString();
-        BlogPostB.findOne({'comments._id': id}, function(err, found) {
+        BlogPostB.findOne({'comments._id': id}, function (err, found) {
           db.close();
           assert.ifError(err);
           assert.strictEqual(!!found, true, 'Find by nested doc id hex string fails');
@@ -536,23 +552,23 @@ describe('model: querying:', function() {
       });
     });
 
-    it('using #all with nested #elemMatch', function(done) {
+    it('using #all with nested #elemMatch', function (done) {
       var db = start(),
           P = db.model('BlogPostB', collection + '_nestedElemMatch');
 
-      var post = new P({ title: "nested elemMatch" });
-      post.comments.push({ title: 'comment A' }, { title: 'comment B' }, { title: 'comment C' });
+      var post = new P({title: 'nested elemMatch'});
+      post.comments.push({title: 'comment A'}, {title: 'comment B'}, {title: 'comment C'});
 
       var id1 = post.comments[1]._id;
       var id2 = post.comments[2]._id;
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        var query0 = { $elemMatch: { _id: id1, title: 'comment B' }};
-        var query1 = { $elemMatch: { _id: id2.toString(), title: 'comment C' }};
+        var query0 = {$elemMatch: {_id: id1, title: 'comment B'}};
+        var query1 = {$elemMatch: {_id: id2.toString(), title: 'comment C'}};
 
-        P.findOne({ comments: { $all: [query0, query1] }}, function(err, p) {
+        P.findOne({comments: {$all: [query0, query1]}}, function (err, p) {
           db.close();
           assert.ifError(err);
           assert.equal(p.id, post.id);
@@ -561,22 +577,22 @@ describe('model: querying:', function() {
       });
     });
 
-    it('using #or with nested #elemMatch', function(done) {
+    it('using #or with nested #elemMatch', function (done) {
       var db = start(),
           P = db.model('BlogPostB', collection);
 
-      var post = new P({ title: "nested elemMatch" });
-      post.comments.push({ title: 'comment D' }, { title: 'comment E' }, { title: 'comment F' });
+      var post = new P({title: 'nested elemMatch'});
+      post.comments.push({title: 'comment D'}, {title: 'comment E'}, {title: 'comment F'});
 
       var id1 = post.comments[1]._id;
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        var query0 = { comments: { $elemMatch: { title: 'comment Z' }}};
-        var query1 = { comments: { $elemMatch: { _id: id1.toString(), title: 'comment E' }}};
+        var query0 = {comments: {$elemMatch: {title: 'comment Z'}}};
+        var query1 = {comments: {$elemMatch: {_id: id1.toString(), title: 'comment E'}}};
 
-        P.findOne({ $or: [query0, query1] }, function(err, p) {
+        P.findOne({$or: [query0, query1]}, function (err, p) {
           db.close();
           assert.ifError(err);
           assert.equal(p.id, post.id);
@@ -585,20 +601,22 @@ describe('model: querying:', function() {
       });
     });
 
-    it('buffer $in array', function(done) {
+    it('buffer $in array', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({sigs: [new Buffer([1, 2, 3]),
-                               new Buffer([4, 5, 6]),
-                               new Buffer([7, 8, 9])]}, function(err, created) {
+      BlogPostB.create({
+        sigs: [new Buffer([1, 2, 3]),
+          new Buffer([4, 5, 6]),
+          new Buffer([7, 8, 9])]
+      }, function (err, created) {
         assert.ifError(err);
-        BlogPostB.findOne({sigs: new Buffer([1, 2, 3])}, function(err, found) {
+        BlogPostB.findOne({sigs: new Buffer([1, 2, 3])}, function (err, found) {
           assert.ifError(err);
           found.id;
           assert.equal(found._id.toString(), created._id);
-          var query = { sigs: { "$in" : [new Buffer([3, 3, 3]), new Buffer([4, 5, 6])] } };
-          BlogPostB.findOne(query, function(err) {
+          var query = {sigs: {'$in': [new Buffer([3, 3, 3]), new Buffer([4, 5, 6])]}};
+          BlogPostB.findOne(query, function (err) {
             assert.ifError(err);
             db.close();
             done();
@@ -607,18 +625,18 @@ describe('model: querying:', function() {
       });
     });
 
-    it('regex with Array (gh-599)', function(done) {
+    it('regex with Array (gh-599)', function (done) {
       var db = start(),
           B = db.model('BlogPostB', random());
 
-      B.create({ tags: 'wooof baaaark meeeeow'.split(' ') }, function(err) {
+      B.create({tags: 'wooof baaaark meeeeow'.split(' ')}, function (err) {
         assert.ifError(err);
-        B.findOne({ tags: /ooof$/ }, function(err, doc) {
+        B.findOne({tags: /ooof$/}, function (err, doc) {
           assert.ifError(err);
           assert.strictEqual(true, !!doc);
           assert.ok(!!~doc.tags.indexOf('meeeeow'));
 
-          B.findOne({ tags: {$regex: 'eow$' } }, function(err, doc) {
+          B.findOne({tags: {$regex: 'eow$'}}, function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.strictEqual(true, !!doc);
@@ -629,14 +647,14 @@ describe('model: querying:', function() {
       });
     });
 
-    it('regex with options', function(done) {
+    it('regex with options', function (done) {
       var db = start(),
           B = db.model('BlogPostB', collection);
 
-      var post = new B({ title: '$option queries' });
-      post.save(function(err) {
+      var post = new B({title: '$option queries'});
+      post.save(function (err) {
         assert.ifError(err);
-        B.findOne({ title: { $regex: ' QUERIES$', $options: 'i' }}, function(err, doc) {
+        B.findOne({title: {$regex: ' QUERIES$', $options: 'i'}}, function (err, doc) {
           db.close();
           assert.strictEqual(null, err, err && err.stack);
           assert.equal(doc.id, post.id);
@@ -645,15 +663,15 @@ describe('model: querying:', function() {
       });
     });
 
-    it('works with $elemMatch and $in combo (gh-1100)', function(done) {
+    it('works with $elemMatch and $in combo (gh-1100)', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           id1 = new DocumentObjectId,
           id2 = new DocumentObjectId;
 
-      BlogPostB.create({owners: [id1, id2]}, function(err, created) {
+      BlogPostB.create({owners: [id1, id2]}, function (err, created) {
         assert.ifError(err);
-        BlogPostB.findOne({owners: {'$elemMatch': { $in: [id2.toString()] }}}, function(err, found) {
+        BlogPostB.findOne({owners: {'$elemMatch': {$in: [id2.toString()]}}}, function (err, found) {
           db.close();
           assert.ifError(err);
           assert.ok(found);
@@ -664,8 +682,8 @@ describe('model: querying:', function() {
     });
   });
 
-  describe('findById', function() {
-    it('handles undefined', function(done) {
+  describe('findById', function () {
+    it('handles undefined', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Edwald ' + random();
@@ -673,10 +691,10 @@ describe('model: querying:', function() {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.findById(undefined, function(err, doc) {
+        BlogPostB.findById(undefined, function (err, doc) {
           assert.ifError(err);
           assert.equal(null, doc);
           db.close(done);
@@ -684,7 +702,7 @@ describe('model: querying:', function() {
       });
     });
 
-    it('works', function(done) {
+    it('works', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Edwald ' + random();
@@ -692,32 +710,36 @@ describe('model: querying:', function() {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
         var pending = 2;
 
-        BlogPostB.findById(post.get('_id'), function(err, doc) {
+        BlogPostB.findById(post.get('_id'), function (err, doc) {
           assert.ifError(err);
           assert.ok(doc instanceof BlogPostB);
           assert.equal(title, doc.get('title'));
-          if (--pending) return;
+          if (--pending) {
+            return;
+          }
           db.close();
           done();
         });
 
-        BlogPostB.findById(post.get('_id').toHexString(), function(err, doc) {
+        BlogPostB.findById(post.get('_id').toHexString(), function (err, doc) {
           assert.ifError(err);
           assert.ok(doc instanceof BlogPostB);
           assert.equal(title, doc.get('title'));
-          if (--pending) return;
+          if (--pending) {
+            return;
+          }
           db.close();
           done();
         });
       });
     });
 
-    it('works with partial initialization', function(done) {
+    it('works with partial initialization', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           queries = 5;
@@ -729,10 +751,10 @@ describe('model: querying:', function() {
       post.meta.visitors = 53;
       post.tags = ['humidity', 'soggy'];
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.findById(post.get('_id'), function(err, doc) {
+        BlogPostB.findById(post.get('_id'), function (err, doc) {
           assert.ifError(err);
 
           assert.equal(true, doc.isInit('title'));
@@ -741,12 +763,14 @@ describe('model: querying:', function() {
           assert.equal(true, doc.isInit('meta.visitors'));
           assert.equal(53, doc.meta.visitors.valueOf());
           assert.equal(2, doc.tags.length);
-          if (--queries) return;
+          if (--queries) {
+            return;
+          }
           db.close();
           done();
         });
 
-        BlogPostB.findById(post.get('_id'), 'title', function(err, doc) {
+        BlogPostB.findById(post.get('_id'), 'title', function (err, doc) {
           assert.ifError(err);
           assert.equal(true, doc.isInit('title'));
           assert.equal(false, doc.isInit('slug'));
@@ -754,12 +778,14 @@ describe('model: querying:', function() {
           assert.equal(false, doc.isInit('meta.visitors'));
           assert.equal(undefined, doc.meta.visitors);
           assert.equal(undefined, doc.tags);
-          if (--queries) return;
+          if (--queries) {
+            return;
+          }
           db.close();
           done();
         });
 
-        BlogPostB.findById(post.get('_id'), '-slug', function(err, doc) {
+        BlogPostB.findById(post.get('_id'), '-slug', function (err, doc) {
           assert.ifError(err);
           assert.equal(true, doc.isInit('title'));
           assert.equal(false, doc.isInit('slug'));
@@ -767,12 +793,14 @@ describe('model: querying:', function() {
           assert.equal(true, doc.isInit('meta.visitors'));
           assert.equal(53, doc.meta.visitors);
           assert.equal(2, doc.tags.length);
-          if (--queries) return;
+          if (--queries) {
+            return;
+          }
           db.close();
           done();
         });
 
-        BlogPostB.findById(post.get('_id'), { title: 1 }, function(err, doc) {
+        BlogPostB.findById(post.get('_id'), {title: 1}, function (err, doc) {
           assert.ifError(err);
           assert.equal(true, doc.isInit('title'));
           assert.equal(false, doc.isInit('slug'));
@@ -780,12 +808,14 @@ describe('model: querying:', function() {
           assert.equal(false, doc.isInit('meta.visitors'));
           assert.equal(undefined, doc.meta.visitors);
           assert.equal(undefined, doc.tags);
-          if (--queries) return;
+          if (--queries) {
+            return;
+          }
           db.close();
           done();
         });
 
-        BlogPostB.findById(post.get('_id'), 'slug', function(err, doc) {
+        BlogPostB.findById(post.get('_id'), 'slug', function (err, doc) {
           assert.ifError(err);
           assert.equal(false, doc.isInit('title'));
           assert.equal(true, doc.isInit('slug'));
@@ -793,14 +823,16 @@ describe('model: querying:', function() {
           assert.equal(false, doc.isInit('meta.visitors'));
           assert.equal(undefined, doc.meta.visitors);
           assert.equal(undefined, doc.tags);
-          if (--queries) return;
+          if (--queries) {
+            return;
+          }
           db.close();
           done();
         });
       });
     });
 
-    it('querying if an array contains at least a certain single member (gh-220)', function(done) {
+    it('querying if an array contains at least a certain single member (gh-220)', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -808,12 +840,12 @@ describe('model: querying:', function() {
 
       post.tags.push('cat');
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({tags: 'cat'}, function(err, doc) {
+        BlogPostB.findOne({tags: 'cat'}, function (err, doc) {
           assert.ifError(err);
-          assert.equal(doc._id.toString(),post._id);
+          assert.equal(doc._id.toString(), post._id);
           db.close();
           done();
         });
@@ -821,25 +853,25 @@ describe('model: querying:', function() {
     });
 
 
-    it('where an array where the $slice operator', function(done) {
+    it('where an array where the $slice operator', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({numbers: [500,600,700,800]}, function(err, created) {
+      BlogPostB.create({numbers: [500, 600, 700, 800]}, function (err, created) {
         assert.ifError(err);
-        BlogPostB.findById(created._id, {numbers: {$slice: 2}}, function(err, found) {
+        BlogPostB.findById(created._id, {numbers: {$slice: 2}}, function (err, found) {
           assert.ifError(err);
           assert.equal(found._id.toString(), created._id);
           assert.equal(2, found.numbers.length);
           assert.equal(500, found.numbers[0]);
           assert.equal(600, found.numbers[1]);
-          BlogPostB.findById(created._id, {numbers: {$slice: -2}}, function(err, found) {
+          BlogPostB.findById(created._id, {numbers: {$slice: -2}}, function (err, found) {
             assert.ifError(err);
             assert.equal(found._id.toString(), created._id);
             assert.equal(2, found.numbers.length);
             assert.equal(700, found.numbers[0]);
             assert.equal(800, found.numbers[1]);
-            BlogPostB.findById(created._id, {numbers: {$slice: [1, 2]}}, function(err, found) {
+            BlogPostB.findById(created._id, {numbers: {$slice: [1, 2]}}, function (err, found) {
               assert.ifError(err);
               assert.equal(found._id.toString(), created._id);
               assert.equal(2, found.numbers.length);
@@ -852,11 +884,10 @@ describe('model: querying:', function() {
         });
       });
     });
-
   });
 
-  describe('find', function() {
-    it('works', function(done) {
+  describe('find', function () {
+    it('works', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Wooooot ' + random();
@@ -864,16 +895,16 @@ describe('model: querying:', function() {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
         var post = new BlogPostB();
         post.set('title', title);
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ifError(err);
 
-          BlogPostB.find({ title: title }, function(err, docs) {
+          BlogPostB.find({title: title}, function (err, docs) {
             assert.ifError(err);
             assert.equal(2, docs.length);
 
@@ -890,12 +921,12 @@ describe('model: querying:', function() {
       });
     });
 
-    it('returns docs where an array that contains one specific member', function(done) {
+    it('returns docs where an array that contains one specific member', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
-      BlogPostB.create({numbers: [100, 101, 102]}, function(err, created) {
+      BlogPostB.create({numbers: [100, 101, 102]}, function (err, created) {
         assert.ifError(err);
-        BlogPostB.find({numbers: 100}, function(err, found) {
+        BlogPostB.find({numbers: 100}, function (err, found) {
           assert.ifError(err);
           assert.equal(1, found.length);
           assert.equal(found[0]._id.toString(), created._id);
@@ -905,7 +936,7 @@ describe('model: querying:', function() {
       });
     });
 
-    it('works when comparing $ne with single value against an array', function(done) {
+    it('works when comparing $ne with single value against an array', function (done) {
       var db = start();
       var schema = new Schema({
         ids: [Schema.ObjectId],
@@ -919,23 +950,23 @@ describe('model: querying:', function() {
       var id3 = new DocumentObjectId;
       var id4 = new DocumentObjectId;
 
-      NE.create({ ids: [id1, id4], b: id3 }, function(err) {
+      NE.create({ids: [id1, id4], b: id3}, function (err) {
         assert.ifError(err);
-        NE.create({ ids: [id2, id4], b: id3 }, function(err) {
+        NE.create({ids: [id2, id4], b: id3}, function (err) {
           assert.ifError(err);
 
-          var query = NE.find({ 'b': id3.toString(), 'ids': { $ne: id1 }});
-          query.exec(function(err, nes1) {
+          var query = NE.find({'b': id3.toString(), 'ids': {$ne: id1}});
+          query.exec(function (err, nes1) {
             assert.ifError(err);
             assert.equal(1, nes1.length);
 
-            NE.find({ b: { $ne: [1] }}, function(err) {
-              assert.equal("Cast to ObjectId failed for value \"1\" at path \"b\"", err.message);
+            NE.find({b: {$ne: [1]}}, function (err) {
+              assert.equal('Cast to ObjectId failed for value "1" at path "b"', err.message);
 
-              NE.find({ b: { $ne: 4 }}, function(err) {
-                assert.equal("Cast to ObjectId failed for value \"4\" at path \"b\"", err.message);
+              NE.find({b: {$ne: 4}}, function (err) {
+                assert.equal('Cast to ObjectId failed for value "4" at path "b"', err.message);
 
-                NE.find({ b: id3, ids: { $ne: id4 }}, function(err, nes4) {
+                NE.find({b: id3, ids: {$ne: id4}}, function (err, nes4) {
                   db.close();
                   assert.ifError(err);
                   assert.equal(0, nes4.length);
@@ -944,12 +975,11 @@ describe('model: querying:', function() {
               });
             });
           });
-
         });
       });
     });
 
-    it('with partial initialization', function(done) {
+    it('with partial initialization', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           queries = 4;
@@ -959,56 +989,64 @@ describe('model: querying:', function() {
       post.title = 'hahaha';
       post.slug = 'woot';
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.find({ _id: post.get('_id') }, function(err, docs) {
+        BlogPostB.find({_id: post.get('_id')}, function (err, docs) {
           assert.ifError(err);
           assert.equal(true, docs[0].isInit('title'));
           assert.equal(true, docs[0].isInit('slug'));
           assert.equal(false, docs[0].isInit('date'));
           assert.strictEqual('kandinsky', docs[0].def);
-          if (--queries) return;
+          if (--queries) {
+            return;
+          }
           db.close();
           done();
         });
 
-        BlogPostB.find({ _id: post.get('_id') }, 'title', function(err, docs) {
+        BlogPostB.find({_id: post.get('_id')}, 'title', function (err, docs) {
           assert.ifError(err);
           assert.equal(true, docs[0].isInit('title'));
           assert.equal(false, docs[0].isInit('slug'));
           assert.equal(false, docs[0].isInit('date'));
           assert.strictEqual(undefined, docs[0].def);
-          if (--queries) return;
+          if (--queries) {
+            return;
+          }
           db.close();
           done();
         });
 
-        BlogPostB.find({ _id: post.get('_id') }, { slug: 0, def: 0 }, function(err, docs) {
+        BlogPostB.find({_id: post.get('_id')}, {slug: 0, def: 0}, function (err, docs) {
           assert.ifError(err);
           assert.equal(true, docs[0].isInit('title'));
           assert.equal(false, docs[0].isInit('slug'));
           assert.equal(false, docs[0].isInit('date'));
           assert.strictEqual(undefined, docs[0].def);
-          if (--queries) return;
+          if (--queries) {
+            return;
+          }
           db.close();
           done();
         });
 
-        BlogPostB.find({ _id: post.get('_id') }, 'slug', function(err, docs) {
+        BlogPostB.find({_id: post.get('_id')}, 'slug', function (err, docs) {
           assert.ifError(err);
           assert.equal(false, docs[0].isInit('title'));
           assert.equal(true, docs[0].isInit('slug'));
           assert.equal(false, docs[0].isInit('date'));
           assert.strictEqual(undefined, docs[0].def);
-          if (--queries) return;
+          if (--queries) {
+            return;
+          }
           db.close();
           done();
         });
       });
     });
 
-    it('where $exists', function(done) {
+    it('where $exists', function (done) {
       var db = start(),
           ExistsSchema = new Schema({
             a: Number,
@@ -1016,11 +1054,11 @@ describe('model: querying:', function() {
           });
       mongoose.model('Exists', ExistsSchema);
       var Exists = db.model('Exists', 'exists_' + random());
-      Exists.create({ a: 1}, function(err) {
+      Exists.create({a: 1}, function (err) {
         assert.ifError(err);
-        Exists.create({b: 'hi'}, function(err) {
+        Exists.create({b: 'hi'}, function (err) {
           assert.ifError(err);
-          Exists.find({b: {$exists: true}}, function(err, docs) {
+          Exists.find({b: {$exists: true}}, function (err, docs) {
             assert.ifError(err);
             db.close();
             assert.equal(1, docs.length);
@@ -1030,15 +1068,15 @@ describe('model: querying:', function() {
       });
     });
 
-    it('works with $elemMatch (gh-1100)', function(done) {
+    it('works with $elemMatch (gh-1100)', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           id1 = new DocumentObjectId,
           id2 = new DocumentObjectId;
 
-      BlogPostB.create({owners: [id1, id2]}, function(err) {
+      BlogPostB.create({owners: [id1, id2]}, function (err) {
         assert.ifError(err);
-        BlogPostB.find({owners: {'$elemMatch': { $in: [id2.toString()] }}}, function(err, found) {
+        BlogPostB.find({owners: {'$elemMatch': {$in: [id2.toString()]}}}, function (err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(1, found.length);
@@ -1047,14 +1085,14 @@ describe('model: querying:', function() {
       });
     });
 
-    it('where $mod', function(done) {
+    it('where $mod', function (done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
-      Mod.create({num: 1}, function(err, one) {
+      Mod.create({num: 1}, function (err, one) {
         assert.ifError(err);
-        Mod.create({num: 2}, function(err) {
+        Mod.create({num: 2}, function (err) {
           assert.ifError(err);
-          Mod.find({num: {$mod: [2, 1]}}, function(err, found) {
+          Mod.find({num: {$mod: [2, 1]}}, function (err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
             assert.equal(found[0]._id.toString(), one._id);
@@ -1065,17 +1103,17 @@ describe('model: querying:', function() {
       });
     });
 
-    it('where $not', function(done) {
+    it('where $not', function (done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
-      Mod.create({num: 1}, function(err) {
+      Mod.create({num: 1}, function (err) {
         assert.ifError(err);
-        Mod.create({num: 2}, function(err, two) {
+        Mod.create({num: 2}, function (err, two) {
           assert.ifError(err);
-          Mod.find({num: {$not: {$mod: [2, 1]}}}, function(err, found) {
+          Mod.find({num: {$not: {$mod: [2, 1]}}}, function (err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
-            assert.equal(found[0]._id.toString(),two._id);
+            assert.equal(found[0]._id.toString(), two._id);
             db.close();
             done();
           });
@@ -1083,11 +1121,11 @@ describe('model: querying:', function() {
       });
     });
 
-    it('where or()', function(done) {
+    it('where or()', function (done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
 
-      Mod.create({num: 1}, {num: 2, str: 'two'}, function(err, one, two) {
+      Mod.create({num: 1}, {num: 2, str: 'two'}, function (err, one, two) {
         assert.ifError(err);
 
         var pending = 3;
@@ -1096,7 +1134,7 @@ describe('model: querying:', function() {
         test3();
 
         function test1() {
-          Mod.find({$or: [{num: 1}, {num: 2}]}, function(err, found) {
+          Mod.find({$or: [{num: 1}, {num: 2}]}, function (err, found) {
             cb();
             assert.ifError(err);
             assert.equal(2, found.length);
@@ -1104,9 +1142,12 @@ describe('model: querying:', function() {
             var found1 = false;
             var found2 = false;
 
-            found.forEach(function(doc) {
-              if (doc.id == one.id) found1 = true;
-              else if (doc.id == two.id) found2 = true;
+            found.forEach(function (doc) {
+              if (doc.id == one.id) {
+                found1 = true;
+              } else if (doc.id == two.id) {
+                found2 = true;
+              }
             });
 
             assert.ok(found1);
@@ -1115,16 +1156,16 @@ describe('model: querying:', function() {
         }
 
         function test2() {
-          Mod.find({ $or: [{ str: 'two'}, {str:'three'}] }, function(err, found) {
+          Mod.find({$or: [{str: 'two'}, {str: 'three'}]}, function (err, found) {
             cb();
             assert.ifError(err);
             assert.equal(1, found.length);
-            assert.equal(found[0]._id.toString(),two._id);
+            assert.equal(found[0]._id.toString(), two._id);
           });
         }
 
         function test3() {
-          Mod.find({$or: [{num: 1}]}).or([{ str: 'two' }]).exec(function(err, found) {
+          Mod.find({$or: [{num: 1}]}).or([{str: 'two'}]).exec(function (err, found) {
             cb();
             assert.ifError(err);
             assert.equal(2, found.length);
@@ -1132,9 +1173,12 @@ describe('model: querying:', function() {
             var found1 = false;
             var found2 = false;
 
-            found.forEach(function(doc) {
-              if (doc.id == one.id) found1 = true;
-              else if (doc.id == two.id) found2 = true;
+            found.forEach(function (doc) {
+              if (doc.id == one.id) {
+                found1 = true;
+              } else if (doc.id == two.id) {
+                found2 = true;
+              }
             });
 
             assert.ok(found1);
@@ -1143,22 +1187,24 @@ describe('model: querying:', function() {
         }
 
         function cb() {
-          if (--pending) return;
+          if (--pending) {
+            return;
+          }
           db.close();
           done();
         }
       });
     });
 
-    it('using $or with array of Document', function(done) {
+    it('using $or with array of Document', function (done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
 
-      Mod.create({num: 1}, function(err, one) {
+      Mod.create({num: 1}, function (err, one) {
         assert.ifError(err);
-        Mod.find({num: 1}, function(err, found) {
+        Mod.find({num: 1}, function (err, found) {
           assert.ifError(err);
-          Mod.find({$or: found}, function(err, found) {
+          Mod.find({$or: found}, function (err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
             assert.equal(found[0]._id.toString(), one._id);
@@ -1169,21 +1215,21 @@ describe('model: querying:', function() {
       });
     });
 
-    it('where $ne', function(done) {
+    it('where $ne', function (done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
-      Mod.create({num: 1}, function(err) {
+      Mod.create({num: 1}, function (err) {
         assert.ifError(err);
-        Mod.create({num: 2}, function(err, two) {
+        Mod.create({num: 2}, function (err, two) {
           assert.ifError(err);
-          Mod.create({num: 3}, function(err, three) {
+          Mod.create({num: 3}, function (err, three) {
             assert.ifError(err);
-            Mod.find({num: {$ne: 1}}, function(err, found) {
+            Mod.find({num: {$ne: 1}}, function (err, found) {
               assert.ifError(err);
 
               assert.equal(found.length, 2);
-              assert.equal(found[0]._id.toString(),two._id);
-              assert.equal(found[1]._id.toString(),three._id);
+              assert.equal(found[0]._id.toString(), two._id);
+              assert.equal(found[1]._id.toString(), three._id);
               db.close();
               done();
             });
@@ -1192,11 +1238,11 @@ describe('model: querying:', function() {
       });
     });
 
-    it('where $nor', function(done) {
+    it('where $nor', function (done) {
       var db = start(),
           Mod = db.model('Mod', 'nor_' + random());
 
-      Mod.create({num: 1}, {num: 2, str: 'two'}, function(err, one, two) {
+      Mod.create({num: 1}, {num: 2, str: 'two'}, function (err, one, two) {
         assert.ifError(err);
 
         var pending = 3;
@@ -1205,16 +1251,16 @@ describe('model: querying:', function() {
         test3();
 
         function test1() {
-          Mod.find({$nor: [{num: 1}, {num: 3}]}, function(err, found) {
+          Mod.find({$nor: [{num: 1}, {num: 3}]}, function (err, found) {
             cb();
             assert.ifError(err);
             assert.equal(1, found.length);
-            assert.equal(found[0]._id.toString(),two._id);
+            assert.equal(found[0]._id.toString(), two._id);
           });
         }
 
         function test2() {
-          Mod.find({ $nor: [{ str: 'two'}, {str:'three'}] }, function(err, found) {
+          Mod.find({$nor: [{str: 'two'}, {str: 'three'}]}, function (err, found) {
             cb();
             assert.ifError(err);
             assert.equal(1, found.length);
@@ -1223,7 +1269,7 @@ describe('model: querying:', function() {
         }
 
         function test3() {
-          Mod.find({$nor: [{num: 2}]}).nor([{ str: 'two' }]).exec(function(err, found) {
+          Mod.find({$nor: [{num: 2}]}).nor([{str: 'two'}]).exec(function (err, found) {
             cb();
             assert.ifError(err);
             assert.equal(1, found.length);
@@ -1232,22 +1278,24 @@ describe('model: querying:', function() {
         }
 
         function cb() {
-          if (--pending) return;
+          if (--pending) {
+            return;
+          }
           db.close();
           done();
         }
       });
     });
 
-    it('STRICT null matches', function(done) {
+    it('STRICT null matches', function (done) {
       var db = start();
       var BlogPostB = db.model('BlogPostB', collection + random());
 
-      var a = { title: 'A', author: null};
-      var b = { title: 'B' };
-      BlogPostB.create(a, b, function(err, createdA) {
+      var a = {title: 'A', author: null};
+      var b = {title: 'B'};
+      BlogPostB.create(a, b, function (err, createdA) {
         assert.ifError(err);
-        BlogPostB.find({author: {$in: [null], $exists: true}}, function(err, found) {
+        BlogPostB.find({author: {$in: [null], $exists: true}}, function (err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(1, found.length);
@@ -1257,56 +1305,56 @@ describe('model: querying:', function() {
       });
     });
 
-    it('null matches null and undefined', function(done) {
+    it('null matches null and undefined', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection + random());
 
       BlogPostB.create(
-          { title: 'A', author: null },
-         { title: 'B' }, function(err) {
-           assert.ifError(err);
-           BlogPostB.find({author: null}, function(err, found) {
-             db.close();
-             assert.ifError(err);
-             assert.equal(2, found.length);
-             done();
-           });
-         });
-    });
-
-    it('a document whose arrays contain at least $all string values', function(done) {
+          {title: 'A', author: null},
+          {title: 'B'}, function (err) {
+            assert.ifError(err);
+            BlogPostB.find({author: null}, function (err, found) {
+              db.close();
+              assert.ifError(err);
+              assert.equal(2, found.length);
+              done();
+            });
+          });
+    });
+
+    it('a document whose arrays contain at least $all string values', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      var post = new BlogPostB({ title: "Aristocats" });
+      var post = new BlogPostB({title: 'Aristocats'});
 
       post.tags.push('onex');
       post.tags.push('twox');
       post.tags.push('threex');
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPostB.findById(post._id, function(err, post) {
+        BlogPostB.findById(post._id, function (err, post) {
           assert.ifError(err);
 
-          BlogPostB.find({ title: { '$all': ['Aristocats']}}, function(err, docs) {
+          BlogPostB.find({title: {'$all': ['Aristocats']}}, function (err, docs) {
             assert.ifError(err);
             assert.equal(1, docs.length);
 
-            BlogPostB.find({ title: { '$all': [/^Aristocats/]}}, function(err, docs) {
+            BlogPostB.find({title: {'$all': [/^Aristocats/]}}, function (err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
 
-              BlogPostB.find({tags: { '$all': ['onex','twox','threex']}}, function(err, docs) {
+              BlogPostB.find({tags: {'$all': ['onex', 'twox', 'threex']}}, function (err, docs) {
                 assert.ifError(err);
                 assert.equal(1, docs.length);
 
-                BlogPostB.find({tags: { '$all': [/^onex/i]}}, function(err, docs) {
+                BlogPostB.find({tags: {'$all': [/^onex/i]}}, function (err, docs) {
                   assert.ifError(err);
                   assert.equal(1, docs.length);
 
-                  BlogPostB.findOne({tags: { '$all': /^two/ }}, function(err, doc) {
+                  BlogPostB.findOne({tags: {'$all': /^two/}}, function (err, doc) {
                     db.close();
                     assert.ifError(err);
                     assert.equal(post.id, doc.id);
@@ -1317,28 +1365,27 @@ describe('model: querying:', function() {
             });
           });
         });
-
       });
     });
 
-    it('using #nor with nested #elemMatch', function(done) {
+    it('using #nor with nested #elemMatch', function (done) {
       var db = start(),
           P = db.model('BlogPostB', collection + '_norWithNestedElemMatch');
 
-      var p0 = { title: "nested $nor elemMatch1", comments: [] };
+      var p0 = {title: 'nested $nor elemMatch1', comments: []};
 
-      var p1 = { title: "nested $nor elemMatch0", comments: [] };
-      p1.comments.push({ title: 'comment X' }, { title: 'comment Y' }, { title: 'comment W' });
+      var p1 = {title: 'nested $nor elemMatch0', comments: []};
+      p1.comments.push({title: 'comment X'}, {title: 'comment Y'}, {title: 'comment W'});
 
-      P.create(p0, p1, function(err, post0, post1) {
+      P.create(p0, p1, function (err, post0, post1) {
         assert.ifError(err);
 
         var id = post1.comments[1]._id;
 
-        var query0 = { comments: { $elemMatch: { title: 'comment Z' }}};
-        var query1 = { comments: { $elemMatch: { _id: id.toString(), title: 'comment Y' }}};
+        var query0 = {comments: {$elemMatch: {title: 'comment Z'}}};
+        var query1 = {comments: {$elemMatch: {_id: id.toString(), title: 'comment Y'}}};
 
-        P.find({ $nor: [query0, query1] }, function(err, posts) {
+        P.find({$nor: [query0, query1]}, function (err, posts) {
           db.close();
           assert.ifError(err);
           assert.equal(1, posts.length);
@@ -1348,32 +1395,32 @@ describe('model: querying:', function() {
       });
     });
 
-    it('strings via regexp', function(done) {
+    it('strings via regexp', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({title: 'Next to Normal'}, function(err, created) {
+      BlogPostB.create({title: 'Next to Normal'}, function (err, created) {
         assert.ifError(err);
-        BlogPostB.findOne({title: /^Next/}, function(err, found) {
+        BlogPostB.findOne({title: /^Next/}, function (err, found) {
           assert.ifError(err);
           assert.equal(found._id.toString(), created._id);
 
           var reg = '^Next to Normal$';
 
-          BlogPostB.find({ title: { $regex: reg }}, function(err, found) {
+          BlogPostB.find({title: {$regex: reg}}, function (err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
             assert.equal(found[0]._id.toString(), created._id);
 
-            BlogPostB.findOne({ title: { $regex: reg }}, function(err, found) {
+            BlogPostB.findOne({title: {$regex: reg}}, function (err, found) {
               assert.ifError(err);
               assert.equal(found._id.toString(), created._id);
 
-              BlogPostB.where('title').regex(reg).findOne(function(err, found) {
+              BlogPostB.where('title').regex(reg).findOne(function (err, found) {
                 assert.ifError(err);
                 assert.equal(found._id.toString(), created._id);
 
-                BlogPostB.where('title').regex(/^Next/).findOne(function(err, found) {
+                BlogPostB.where('title').regex(/^Next/).findOne(function (err, found) {
                   db.close();
                   assert.ifError(err);
                   assert.equal(found._id.toString(), created._id);
@@ -1386,22 +1433,22 @@ describe('model: querying:', function() {
       });
     });
 
-    it('a document whose arrays contain at least $all values', function(done) {
+    it('a document whose arrays contain at least $all values', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
-      var a1 = {numbers: [-1,-2,-3,-4], meta: { visitors: 4 }};
-      var a2 = {numbers: [0,-1,-2,-3,-4]};
-      BlogPostB.create(a1, a2, function(err, whereoutZero, whereZero) {
+      var a1 = {numbers: [-1, -2, -3, -4], meta: {visitors: 4}};
+      var a2 = {numbers: [0, -1, -2, -3, -4]};
+      BlogPostB.create(a1, a2, function (err, whereoutZero, whereZero) {
         assert.ifError(err);
 
-        BlogPostB.find({numbers: {$all: [-1, -2, -3, -4]}}, function(err, found) {
+        BlogPostB.find({numbers: {$all: [-1, -2, -3, -4]}}, function (err, found) {
           assert.ifError(err);
           assert.equal(2, found.length);
-          BlogPostB.find({'meta.visitors': {$all: [4] }}, function(err, found) {
+          BlogPostB.find({'meta.visitors': {$all: [4]}}, function (err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
             assert.equal(found[0]._id.toString(), whereoutZero._id);
-            BlogPostB.find({numbers: {$all: [0, -1]}}, function(err, found) {
+            BlogPostB.find({numbers: {$all: [0, -1]}}, function (err, found) {
               db.close();
               assert.ifError(err);
               assert.equal(1, found.length);
@@ -1413,20 +1460,20 @@ describe('model: querying:', function() {
       });
     });
 
-    it('where $size', function(done) {
+    it('where $size', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({numbers: [1,2,3,4,5,6,7,8,9,10]}, function(err) {
+      BlogPostB.create({numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}, function (err) {
         assert.ifError(err);
-        BlogPostB.create({numbers: [11,12,13,14,15,16,17,18,19,20]}, function(err) {
+        BlogPostB.create({numbers: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]}, function (err) {
           assert.ifError(err);
-          BlogPostB.create({numbers: [1,2,3,4,5,6,7,8,9,10,11]}, function(err) {
+          BlogPostB.create({numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]}, function (err) {
             assert.ifError(err);
-            BlogPostB.find({numbers: {$size: 10}}, function(err, found) {
+            BlogPostB.find({numbers: {$size: 10}}, function (err, found) {
               assert.ifError(err);
               assert.equal(2, found.length);
-              BlogPostB.find({numbers: {$size: 11}}, function(err, found) {
+              BlogPostB.find({numbers: {$size: 11}}, function (err, found) {
                 assert.ifError(err);
                 assert.equal(1, found.length);
                 db.close();
@@ -1438,25 +1485,30 @@ describe('model: querying:', function() {
       });
     });
 
-    it('$gt, $lt, $lte, $gte work on strings', function(done) {
+    it('$gt, $lt, $lte, $gte work on strings', function (done) {
       var db = start();
       var D = db.model('D', new Schema({dt: String}), collection);
 
-      D.create({ dt: '2011-03-30' }, cb);
-      D.create({ dt: '2011-03-31' }, cb);
-      D.create({ dt: '2011-04-01' }, cb);
-      D.create({ dt: '2011-04-02' }, cb);
+      D.create({dt: '2011-03-30'}, cb);
+      D.create({dt: '2011-03-31'}, cb);
+      D.create({dt: '2011-04-01'}, cb);
+      D.create({dt: '2011-04-02'}, cb);
 
       var pending = 4;
+
       function cb(err) {
-        if (err) db.close();
+        if (err) {
+          db.close();
+        }
         assert.ifError(err);
 
-        if (--pending) return;
+        if (--pending) {
+          return;
+        }
 
         pending = 2;
 
-        D.find({ 'dt': { $gte: '2011-03-30', $lte: '2011-04-01' }}).sort('dt').exec(function(err, docs) {
+        D.find({'dt': {$gte: '2011-03-30', $lte: '2011-04-01'}}).sort('dt').exec(function (err, docs) {
           if (!--pending) {
             db.close();
             done();
@@ -1466,10 +1518,12 @@ describe('model: querying:', function() {
           assert.equal(docs[0].dt, '2011-03-30');
           assert.equal(docs[1].dt, '2011-03-31');
           assert.equal(docs[2].dt, '2011-04-01');
-          assert.equal(false, docs.some(function(d) { return '2011-04-02' === d.dt; }));
+          assert.equal(false, docs.some(function (d) {
+            return '2011-04-02' === d.dt;
+          }));
         });
 
-        D.find({ 'dt': { $gt: '2011-03-30', $lt: '2011-04-02' }}).sort('dt').exec(function(err, docs) {
+        D.find({'dt': {$gt: '2011-03-30', $lt: '2011-04-02'}}).sort('dt').exec(function (err, docs) {
           if (!--pending) {
             db.close();
             done();
@@ -1478,15 +1532,18 @@ describe('model: querying:', function() {
           assert.equal(2, docs.length);
           assert.equal(docs[0].dt, '2011-03-31');
           assert.equal(docs[1].dt, '2011-04-01');
-          assert.equal(false, docs.some(function(d) { return '2011-03-30' === d.dt; }));
-          assert.equal(false, docs.some(function(d) { return '2011-04-02' === d.dt; }));
+          assert.equal(false, docs.some(function (d) {
+            return '2011-03-30' === d.dt;
+          }));
+          assert.equal(false, docs.some(function (d) {
+            return '2011-04-02' === d.dt;
+          }));
         });
       }
-
     });
 
-    describe('text search indexes', function() {
-      it('works with text search ensure indexes ', function(done) {
+    describe('text search indexes', function () {
+      it('works with text search ensure indexes ', function (done) {
         if (!mongo26_or_greater) {
           return done();
         }
@@ -1494,40 +1551,40 @@ describe('model: querying:', function() {
         var db = start(),
             blogPost = db.model('BlogPostB', collection);
 
-        blogPost.collection.ensureIndex({ title: 'text' }, function(error) {
+        blogPost.collection.ensureIndex({title: 'text'}, function (error) {
           assert.ifError(error);
-          var a = new blogPost({ title : 'querying in mongoose' });
-          var b = new blogPost({ title : 'text search in mongoose' });
-          a.save(function(error) {
+          var a = new blogPost({title: 'querying in mongoose'});
+          var b = new blogPost({title: 'text search in mongoose'});
+          a.save(function (error) {
             assert.ifError(error);
-            b.save(function(error) {
+            b.save(function (error) {
               assert.ifError(error);
               blogPost.
-                find({ $text: { $search : 'text search' } }, { score: { $meta: "textScore" } }).
-                limit(2).
-                exec(function(error, documents) {
+              find({$text: {$search: 'text search'}}, {score: {$meta: 'textScore'}}).
+              limit(2).
+              exec(function (error, documents) {
+                assert.ifError(error);
+                assert.equal(1, documents.length);
+                assert.equal('text search in mongoose', documents[0].title);
+                a.remove(function (error) {
                   assert.ifError(error);
-                  assert.equal(1, documents.length);
-                  assert.equal('text search in mongoose', documents[0].title);
-                  a.remove(function(error) {
+                  b.remove(function (error) {
                     assert.ifError(error);
-                    b.remove(function(error) {
-                      assert.ifError(error);
-                      db.close(done);
-                    });
+                    db.close(done);
                   });
                 });
+              });
             });
           });
         });
       });
 
-      it('works when text search is called by a schema', function(done) {
+      it('works when text search is called by a schema', function (done) {
         var db = start();
 
         var exampleSchema = new Schema({
           title: String,
-          name: {type: String, text: true },
+          name: {type: String, text: true},
           large_text: String
         });
 
@@ -1538,18 +1595,18 @@ describe('model: querying:', function() {
     });
   });
 
-  describe('limit', function() {
-    it('works', function(done) {
+  describe('limit', function () {
+    it('works', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({title: 'first limit'}, function(err, first) {
+      BlogPostB.create({title: 'first limit'}, function (err, first) {
         assert.ifError(err);
-        BlogPostB.create({title: 'second limit'}, function(err, second) {
+        BlogPostB.create({title: 'second limit'}, function (err, second) {
           assert.ifError(err);
-          BlogPostB.create({title: 'third limit'}, function(err) {
+          BlogPostB.create({title: 'third limit'}, function (err) {
             assert.ifError(err);
-            BlogPostB.find({title: /limit$/}).limit(2).find( function(err, found) {
+            BlogPostB.find({title: /limit$/}).limit(2).find(function (err, found) {
               db.close();
               assert.ifError(err);
               assert.equal(2, found.length);
@@ -1563,20 +1620,20 @@ describe('model: querying:', function() {
     });
   });
 
-  describe('skip', function() {
-    it('works', function(done) {
+  describe('skip', function () {
+    it('works', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({title: '1 skip'}, function(err) {
+      BlogPostB.create({title: '1 skip'}, function (err) {
         assert.ifError(err);
-        BlogPostB.create({title: '2 skip'}, function(err, second) {
+        BlogPostB.create({title: '2 skip'}, function (err, second) {
           assert.ifError(err);
-          BlogPostB.create({title: '3 skip'}, function(err, third) {
+          BlogPostB.create({title: '3 skip'}, function (err, third) {
             assert.ifError(err);
-            BlogPostB.find({title: /skip$/}).sort({ title: 1 }).skip(1).limit(2).find( function(err, found) {
+            BlogPostB.find({title: /skip$/}).sort({title: 1}).skip(1).limit(2).find(function (err, found) {
               assert.ifError(err);
-              assert.equal(2,found.length);
+              assert.equal(2, found.length);
               assert.equal(found[0].id, second._id);
               assert.equal(found[1].id, third._id);
               db.close();
@@ -1588,21 +1645,21 @@ describe('model: querying:', function() {
     });
   });
 
-  describe('sort', function() {
-    it('works', function(done) {
+  describe('sort', function () {
+    it('works', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({meta: {visitors: 100}}, function(err, least) {
+      BlogPostB.create({meta: {visitors: 100}}, function (err, least) {
         assert.ifError(err);
-        BlogPostB.create({meta: {visitors: 300}}, function(err, largest) {
+        BlogPostB.create({meta: {visitors: 300}}, function (err, largest) {
           assert.ifError(err);
-          BlogPostB.create({meta: {visitors: 200}}, function(err, middle) {
+          BlogPostB.create({meta: {visitors: 200}}, function (err, middle) {
             assert.ifError(err);
             BlogPostB
             .where('meta.visitors').gt(99).lt(301)
             .sort('-meta.visitors')
-            .find( function(err, found) {
+            .find(function (err, found) {
               assert.ifError(err);
               assert.equal(3, found.length);
               assert.equal(found[0].id, largest._id);
@@ -1615,7 +1672,7 @@ describe('model: querying:', function() {
         });
       });
     });
-    it('handles sorting by text score', function(done) {
+    it('handles sorting by text score', function (done) {
       if (!mongo26_or_greater) {
         return done();
       }
@@ -1623,38 +1680,38 @@ describe('model: querying:', function() {
       var db = start(),
           blogPost = db.model('BlogPostB', collection);
 
-      blogPost.collection.ensureIndex({ title: 'text' }, function(error) {
+      blogPost.collection.ensureIndex({title: 'text'}, function (error) {
         assert.ifError(error);
-        var a = new blogPost({ title : 'searching in mongoose' });
-        var b = new blogPost({ title : 'text search in mongoose' });
-        a.save(function(error) {
+        var a = new blogPost({title: 'searching in mongoose'});
+        var b = new blogPost({title: 'text search in mongoose'});
+        a.save(function (error) {
           assert.ifError(error);
-          b.save(function(error) {
+          b.save(function (error) {
             assert.ifError(error);
             blogPost.
-              find({ $text: { $search : 'text search' } }, { score: { $meta: "textScore" } }).
-              sort({ score: { $meta: 'textScore' } }).
-              limit(2).
-              exec(function(error, documents) {
-                assert.ifError(error);
-                assert.equal(2, documents.length);
-                assert.equal('text search in mongoose', documents[0].title);
-                assert.equal('searching in mongoose', documents[1].title);
-                db.close();
-                done();
-              });
+            find({$text: {$search: 'text search'}}, {score: {$meta: 'textScore'}}).
+            sort({score: {$meta: 'textScore'}}).
+            limit(2).
+            exec(function (error, documents) {
+              assert.ifError(error);
+              assert.equal(2, documents.length);
+              assert.equal('text search in mongoose', documents[0].title);
+              assert.equal('searching in mongoose', documents[1].title);
+              db.close();
+              done();
+            });
           });
         });
       });
     });
   });
 
-  describe('nested mixed "x.y.z"', function() {
-    it('works', function(done) {
+  describe('nested mixed "x.y.z"', function () {
+    it('works', function (done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.find({ 'mixed.nested.stuff': 'skynet' }, function(err) {
+      BlogPostB.find({'mixed.nested.stuff': 'skynet'}, function (err) {
         db.close();
         assert.ifError(err);
         done();
@@ -1662,15 +1719,15 @@ describe('model: querying:', function() {
     });
   });
 
-  it('by Date (gh-336)', function(done) {
+  it('by Date (gh-336)', function (done) {
     // GH-336
     var db = start(),
-        Test = db.model('TestDateQuery', new Schema({ date: Date }), 'datetest_' + random()),
+        Test = db.model('TestDateQuery', new Schema({date: Date}), 'datetest_' + random()),
         now = new Date;
 
-    Test.create({ date: now }, { date: new Date(now - 10000) }, function(err) {
+    Test.create({date: now}, {date: new Date(now - 10000)}, function (err) {
       assert.ifError(err);
-      Test.find({ date: now }, function(err, docs) {
+      Test.find({date: now}, function (err, docs) {
         db.close();
         assert.ifError(err);
         assert.equal(1, docs.length);
@@ -1679,30 +1736,30 @@ describe('model: querying:', function() {
     });
   });
 
-  it('mixed types with $elemMatch (gh-591)', function(done) {
+  it('mixed types with $elemMatch (gh-591)', function (done) {
     var db = start(),
-        S = new Schema({ a: [{}], b: Number }),
+        S = new Schema({a: [{}], b: Number}),
         M = db.model('QueryingMixedArrays', S, random());
 
     var m = new M;
-    m.a = [1,2,{ name: 'Frodo' },'IDK', {name: 100}];
+    m.a = [1, 2, {name: 'Frodo'}, 'IDK', {name: 100}];
     m.b = 10;
 
-    m.save(function(err) {
+    m.save(function (err) {
       assert.ifError(err);
 
-      M.find({ a: { name: 'Frodo' }, b: '10' }, function(err, docs) {
+      M.find({a: {name: 'Frodo'}, b: '10'}, function (err, docs) {
         assert.ifError(err);
         assert.equal(5, docs[0].a.length);
         assert.equal(10, docs[0].b.valueOf());
 
         var query = {
           a: {
-            $elemMatch: { name: 100 }
+            $elemMatch: {name: 100}
           }
         };
 
-        M.find(query, function(err, docs) {
+        M.find(query, function (err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(5, docs[0].a.length);
@@ -1712,32 +1769,32 @@ describe('model: querying:', function() {
     });
   });
 
-  describe('$all', function() {
-    it('with ObjectIds (gh-690)', function(done) {
+  describe('$all', function () {
+    it('with ObjectIds (gh-690)', function (done) {
       var db = start();
 
-      var SSchema = new Schema({ name: String });
-      var PSchema = new Schema({ sub: [SSchema] });
+      var SSchema = new Schema({name: String});
+      var PSchema = new Schema({sub: [SSchema]});
 
       var P = db.model('usingAllWithObjectIds', PSchema);
-      var sub = [{ name: 'one' }, { name: 'two' }, { name: 'three' }];
+      var sub = [{name: 'one'}, {name: 'two'}, {name: 'three'}];
 
-      P.create({ sub: sub }, function(err, p) {
+      P.create({sub: sub}, function (err, p) {
         assert.ifError(err);
 
         var o0 = p.sub[0]._id;
         var o1 = p.sub[1]._id;
         var o2 = p.sub[2]._id;
 
-        P.findOne({ 'sub._id': { $all: [o1, o2.toString()] }}, function(err, doc) {
+        P.findOne({'sub._id': {$all: [o1, o2.toString()]}}, function (err, doc) {
           assert.ifError(err);
           assert.equal(doc.id, p.id);
 
-          P.findOne({ 'sub._id': { $all: [o0, new DocumentObjectId] }}, function(err, doc) {
+          P.findOne({'sub._id': {$all: [o0, new DocumentObjectId]}}, function (err, doc) {
             assert.ifError(err);
             assert.equal(false, !!doc);
 
-            P.findOne({ 'sub._id': { $all: [o2] }}, function(err, doc) {
+            P.findOne({'sub._id': {$all: [o2]}}, function (err, doc) {
               db.close();
               assert.ifError(err);
               assert.equal(doc.id, p.id);
@@ -1748,36 +1805,36 @@ describe('model: querying:', function() {
       });
     });
 
-    it('with Dates', function(done) {
+    it('with Dates', function (done) {
       this.timeout(3000);
       var db = start();
 
-      var SSchema = new Schema({ d: Date });
-      var PSchema = new Schema({ sub: [SSchema] });
+      var SSchema = new Schema({d: Date});
+      var PSchema = new Schema({sub: [SSchema]});
 
       var P = db.model('usingAllWithDates', PSchema);
       var sub = [
-          { d: new Date },
-         { d: new Date(Date.now() - 10000) },
-         { d: new Date(Date.now() - 30000) }
+        {d: new Date},
+        {d: new Date(Date.now() - 10000)},
+        {d: new Date(Date.now() - 30000)}
       ];
 
-      P.create({ sub: sub }, function(err, p) {
+      P.create({sub: sub}, function (err, p) {
         assert.ifError(err);
 
         var o0 = p.sub[0].d;
         var o1 = p.sub[1].d;
         var o2 = p.sub[2].d;
 
-        P.findOne({ 'sub.d': { $all: [o1, o2] }}, function(err, doc) {
+        P.findOne({'sub.d': {$all: [o1, o2]}}, function (err, doc) {
           assert.ifError(err);
-          assert.equal(doc.id,p.id);
+          assert.equal(doc.id, p.id);
 
-          P.findOne({ 'sub.d': { $all: [o0, new Date] }}, function(err, doc) {
+          P.findOne({'sub.d': {$all: [o0, new Date]}}, function (err, doc) {
             assert.ifError(err);
             assert.equal(false, !!doc);
 
-            P.findOne({ 'sub.d': { $all: [o2] }}, function(err, doc) {
+            P.findOne({'sub.d': {$all: [o2]}}, function (err, doc) {
               assert.ifError(err);
               assert.equal(doc.id, p.id);
               db.close(done);
@@ -1787,10 +1844,10 @@ describe('model: querying:', function() {
       });
     });
 
-    it('with $elemMatch (gh-3163)', function(done) {
+    it('with $elemMatch (gh-3163)', function (done) {
       var db = start();
 
-      start.mongodVersion(function(err, version) {
+      start.mongodVersion(function (err, version) {
         if (err) {
           throw err;
         }
@@ -1802,14 +1859,14 @@ describe('model: querying:', function() {
         next();
       });
 
-      var next = function() {
-        var schema = new Schema({ test: [String] });
+      var next = function () {
+        var schema = new Schema({test: [String]});
         var MyModel = db.model('gh3163', schema);
 
-        MyModel.create({ test: ['log1', 'log2'] }, function(error) {
+        MyModel.create({test: ['log1', 'log2']}, function (error) {
           assert.ifError(error);
-          var query = { test: { $all: [{ $elemMatch: { $regex: /log/g } }] } };
-          MyModel.find(query, function(error, docs) {
+          var query = {test: {$all: [{$elemMatch: {$regex: /log/g}}]}};
+          MyModel.find(query, function (error, docs) {
             assert.ifError(error);
             assert.equal(docs.length, 1);
             db.close(done);
@@ -1819,41 +1876,41 @@ describe('model: querying:', function() {
     });
   });
 
-  describe('and', function() {
-    it('works with queries gh-1188', function(done) {
+  describe('and', function () {
+    it('works with queries gh-1188', function (done) {
       var db = start();
       var B = db.model('BlogPostB');
 
-      B.create({ title: 'and operator', published: false, author: 'Me' }, function(err) {
+      B.create({title: 'and operator', published: false, author: 'Me'}, function (err) {
         assert.ifError(err);
 
-        B.find({ $and: [{ title: 'and operator' }] }, function(err, docs) {
+        B.find({$and: [{title: 'and operator'}]}, function (err, docs) {
           assert.ifError(err);
           assert.equal(1, docs.length);
 
-          B.find({ $and: [{ title: 'and operator' }, { published: true }] }, function(err, docs) {
+          B.find({$and: [{title: 'and operator'}, {published: true}]}, function (err, docs) {
             assert.ifError(err);
             assert.equal(0, docs.length);
 
-            B.find({ $and: [{ title: 'and operator' }, { published: false }] }, function(err, docs) {
+            B.find({$and: [{title: 'and operator'}, {published: false}]}, function (err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
 
               var query = B.find();
               query.and([
-                { title: 'and operator', published: false },
-                { author: 'Me' }
+                {title: 'and operator', published: false},
+                {author: 'Me'}
               ]);
-              query.exec(function(err, docs) {
+              query.exec(function (err, docs) {
                 assert.ifError(err);
                 assert.equal(1, docs.length);
 
                 var query = B.find();
                 query.and([
-                  { title: 'and operator', published: false },
-                  { author: 'You' }
+                  {title: 'and operator', published: false},
+                  {author: 'You'}
                 ]);
-                query.exec(function(err, docs) {
+                query.exec(function (err, docs) {
                   assert.ifError(err);
                   assert.equal(0, docs.length);
                   db.close(done);
@@ -1865,11 +1922,11 @@ describe('model: querying:', function() {
       });
     });
 
-    it('works with nested query selectors gh-1884', function(done) {
+    it('works with nested query selectors gh-1884', function (done) {
       var db = start();
-      var B = db.model('gh1884', { a: String, b: String }, 'gh1884');
+      var B = db.model('gh1884', {a: String, b: String}, 'gh1884');
 
-      B.remove({ $and: [{ a: 'coffee' }, { b: { $in: ['bacon', 'eggs'] } }] }, function(error) {
+      B.remove({$and: [{a: 'coffee'}, {b: {$in: ['bacon', 'eggs']}}]}, function (error) {
         assert.ifError(error);
         db.close(done);
       });
@@ -1877,49 +1934,49 @@ describe('model: querying:', function() {
   });
 });
 
-describe('buffers', function() {
-  it('works with different methods and query types', function(done) {
+describe('buffers', function () {
+  it('works with different methods and query types', function (done) {
     var db = start(),
-        BufSchema = new Schema({ name: String, block: Buffer }),
-        Test = db.model('Buffer', BufSchema, "buffers");
+        BufSchema = new Schema({name: String, block: Buffer}),
+        Test = db.model('Buffer', BufSchema, 'buffers');
 
-    var docA = { name: 'A', block: new Buffer('über') };
-    var docB = { name: 'B', block: new Buffer("buffer shtuffs are neat") };
-    var docC = { name: 'C', block: 'hello world' };
+    var docA = {name: 'A', block: new Buffer('über')};
+    var docB = {name: 'B', block: new Buffer('buffer shtuffs are neat')};
+    var docC = {name: 'C', block: 'hello world'};
 
-    Test.create(docA, docB, docC, function(err, a, b, c) {
+    Test.create(docA, docB, docC, function (err, a, b, c) {
       assert.ifError(err);
-      assert.equal(b.block.toString('utf8'),'buffer shtuffs are neat');
-      assert.equal(a.block.toString('utf8'),'über');
-      assert.equal(c.block.toString('utf8'),'hello world');
+      assert.equal(b.block.toString('utf8'), 'buffer shtuffs are neat');
+      assert.equal(a.block.toString('utf8'), 'über');
+      assert.equal(c.block.toString('utf8'), 'hello world');
 
-      Test.findById(a._id, function(err, a) {
+      Test.findById(a._id, function (err, a) {
         assert.ifError(err);
-        assert.equal(a.block.toString('utf8'),'über');
+        assert.equal(a.block.toString('utf8'), 'über');
 
-        Test.findOne({ block: 'buffer shtuffs are neat' }, function(err, rb) {
+        Test.findOne({block: 'buffer shtuffs are neat'}, function (err, rb) {
           assert.ifError(err);
-          assert.equal(rb.block.toString('utf8'),'buffer shtuffs are neat');
+          assert.equal(rb.block.toString('utf8'), 'buffer shtuffs are neat');
 
-          Test.findOne({ block: /buffer/i }, function(err) {
+          Test.findOne({block: /buffer/i}, function (err) {
             assert.equal(err.message, 'Cast to buffer failed for value "/buffer/i" at path "block"');
-            Test.findOne({ block: [195, 188, 98, 101, 114] }, function(err, rb) {
+            Test.findOne({block: [195, 188, 98, 101, 114]}, function (err, rb) {
               assert.ifError(err);
-              assert.equal(rb.block.toString('utf8'),'über');
+              assert.equal(rb.block.toString('utf8'), 'über');
 
-              Test.findOne({ block: 'aGVsbG8gd29ybGQ=' }, function(err, rb) {
+              Test.findOne({block: 'aGVsbG8gd29ybGQ='}, function (err, rb) {
                 assert.ifError(err);
                 assert.strictEqual(rb, null);
 
-                Test.findOne({ block: new Buffer('aGVsbG8gd29ybGQ=', 'base64') }, function(err, rb) {
+                Test.findOne({block: new Buffer('aGVsbG8gd29ybGQ=', 'base64')}, function (err, rb) {
                   assert.ifError(err);
-                  assert.equal(rb.block.toString('utf8'),'hello world');
+                  assert.equal(rb.block.toString('utf8'), 'hello world');
 
-                  Test.findOne({ block: new MongooseBuffer('aGVsbG8gd29ybGQ=', 'base64') }, function(err, rb) {
+                  Test.findOne({block: new MongooseBuffer('aGVsbG8gd29ybGQ=', 'base64')}, function (err, rb) {
                     assert.ifError(err);
-                    assert.equal(rb.block.toString('utf8'),'hello world');
+                    assert.equal(rb.block.toString('utf8'), 'hello world');
 
-                    Test.remove({}, function(err) {
+                    Test.remove({}, function (err) {
                       db.close();
                       assert.ifError(err);
                       done();
@@ -1931,77 +1988,76 @@ describe('buffers', function() {
           });
         });
       });
-
     });
   });
 
-  it('with conditionals', function(done) {
+  it('with conditionals', function (done) {
     // $in $nin etc
     var db = start(),
-        BufSchema = new Schema({ name: String, block: Buffer }),
-        Test = db.model('Buffer2', BufSchema, "buffer_" + random());
+        BufSchema = new Schema({name: String, block: Buffer}),
+        Test = db.model('Buffer2', BufSchema, 'buffer_' + random());
 
-    var docA = { name: 'A', block: new MongooseBuffer([195, 188, 98, 101, 114]) }; //über
-    var docB = { name: 'B', block: new MongooseBuffer("buffer shtuffs are neat") };
-    var docC = { name: 'C', block: new MongooseBuffer('aGVsbG8gd29ybGQ=', 'base64') };
+    var docA = {name: 'A', block: new MongooseBuffer([195, 188, 98, 101, 114])}; // über
+    var docB = {name: 'B', block: new MongooseBuffer('buffer shtuffs are neat')};
+    var docC = {name: 'C', block: new MongooseBuffer('aGVsbG8gd29ybGQ=', 'base64')};
 
-    Test.create(docA, docB, docC, function(err, a, b, c) {
+    Test.create(docA, docB, docC, function (err, a, b, c) {
       assert.ifError(err);
-      assert.equal(a.block.toString('utf8'),'über');
-      assert.equal(b.block.toString('utf8'),'buffer shtuffs are neat');
-      assert.equal(c.block.toString('utf8'),'hello world');
+      assert.equal(a.block.toString('utf8'), 'über');
+      assert.equal(b.block.toString('utf8'), 'buffer shtuffs are neat');
+      assert.equal(c.block.toString('utf8'), 'hello world');
 
-      Test.find({ block: { $in: [[195, 188, 98, 101, 114], "buffer shtuffs are neat", new Buffer('aGVsbG8gd29ybGQ=', 'base64')] }}, function(err, tests) {
+      Test.find({block: {$in: [[195, 188, 98, 101, 114], 'buffer shtuffs are neat', new Buffer('aGVsbG8gd29ybGQ=', 'base64')]}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(3, tests.length);
       });
 
-      Test.find({ block: { $in: ['über', 'hello world'] }}, function(err, tests) {
+      Test.find({block: {$in: ['über', 'hello world']}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
       });
 
-      Test.find({ block: { $in: ['über'] }}, function(err, tests) {
+      Test.find({block: {$in: ['über']}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(1, tests.length);
-        assert.equal(tests[0].block.toString('utf8'),'über');
+        assert.equal(tests[0].block.toString('utf8'), 'über');
       });
 
-      Test.find({ block: { $nin: ['über'] }}, function(err, tests) {
+      Test.find({block: {$nin: ['über']}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
       });
 
-      Test.find({ block: { $nin: [[195, 188, 98, 101, 114], new Buffer('aGVsbG8gd29ybGQ=', 'base64')] }}, function(err, tests) {
+      Test.find({block: {$nin: [[195, 188, 98, 101, 114], new Buffer('aGVsbG8gd29ybGQ=', 'base64')]}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(1, tests.length);
-        assert.equal(tests[0].block.toString('utf8'),'buffer shtuffs are neat');
+        assert.equal(tests[0].block.toString('utf8'), 'buffer shtuffs are neat');
       });
 
-      Test.find({ block: { $ne: 'über' }}, function(err, tests) {
+      Test.find({block: {$ne: 'über'}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
       });
 
-      Test.find({ block: { $gt: 'über' }}, function(err, tests) {
+      Test.find({block: {$gt: 'über'}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
       });
 
-      Test.find({ block: { $gte: 'über' }}, function(err, tests) {
+      Test.find({block: {$gte: 'über'}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(3, tests.length);
       });
 
-      Test.find({ block: { $lt: new Buffer('buffer shtuffs are neat') }}, function(err, tests) {
+      Test.find({block: {$lt: new Buffer('buffer shtuffs are neat')}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
@@ -2012,16 +2068,19 @@ describe('buffers', function() {
         assert.ok(ret['über'] !== undefined);
       });
 
-      Test.find({ block: { $lte: 'buffer shtuffs are neat' }}, function(err, tests) {
+      Test.find({block: {$lte: 'buffer shtuffs are neat'}}, function (err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(3, tests.length);
       });
 
       var pending = 9;
+
       function cb() {
-        if (--pending) return;
-        Test.remove({}, function(err) {
+        if (--pending) {
+          return;
+        }
+        Test.remove({}, function (err) {
           db.close();
           assert.ifError(err);
           done();
@@ -2031,16 +2090,16 @@ describe('buffers', function() {
   });
 });
 
-describe('backwards compatibility', function() {
-  it('with previously existing null values in the db', function(done) {
+describe('backwards compatibility', function () {
+  it('with previously existing null values in the db', function (done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         post = new BlogPostB();
 
-    post.collection.insert({ meta: { visitors: 9898, a: null } }, {}, function(err, b) {
+    post.collection.insert({meta: {visitors: 9898, a: null}}, {}, function (err, b) {
       assert.ifError(err);
 
-      BlogPostB.findOne({_id: b.ops[0]._id}, function(err, found) {
+      BlogPostB.findOne({_id: b.ops[0]._id}, function (err, found) {
         assert.ifError(err);
         assert.equal(9898, found.get('meta.visitors').valueOf());
         db.close();
@@ -2049,18 +2108,18 @@ describe('backwards compatibility', function() {
     });
   });
 
-  it('with unused values in the db', function(done) {
+  it('with unused values in the db', function (done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         post = new BlogPostB();
 
-    post.collection.insert({ meta: { visitors: 9898, color: 'blue'}}, {}, function(err, b) {
+    post.collection.insert({meta: {visitors: 9898, color: 'blue'}}, {}, function (err, b) {
       assert.ifError(err);
 
-      BlogPostB.findOne({_id: b.ops[0]._id}, function(err, found) {
+      BlogPostB.findOne({_id: b.ops[0]._id}, function (err, found) {
         assert.ifError(err);
         assert.equal(9898, found.get('meta.visitors').valueOf());
-        found.save(function(err) {
+        found.save(function (err) {
           assert.ifError(err);
           db.close();
           done();
@@ -2070,24 +2129,29 @@ describe('backwards compatibility', function() {
   });
 });
 
-describe('geo-spatial', function() {
-  describe('2d', function() {
-    it('$near (gh-309)', function(done) {
+describe('geo-spatial', function () {
+  describe('2d', function () {
+    it('$near (gh-309)', function (done) {
       var db = start(),
           Test = db.model('Geo1', geoSchema, 'geospatial' + random());
 
       var pending = 2;
+
       function complete(err) {
-        if (complete.ran) return;
-        if (err) return done(complete.ran = err);
+        if (complete.ran) {
+          return;
+        }
+        if (err) {
+          return done(complete.ran = err);
+        }
         --pending || test();
       }
 
       Test.on('index', complete);
-      Test.create({ loc: [ 10, 20 ]}, { loc: [ 40, 90 ]}, complete);
+      Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
       function test() {
-        Test.find({ loc: { $near: [30, 40] }}, function(err, docs) {
+        Test.find({loc: {$near: [30, 40]}}, function (err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -2096,22 +2160,27 @@ describe('geo-spatial', function() {
       }
     });
 
-    it('$within arrays (gh-586)', function(done) {
+    it('$within arrays (gh-586)', function (done) {
       var db = start(),
           Test = db.model('Geo2', geoSchema, collection + 'geospatial');
 
       var pending = 2;
+
       function complete(err) {
-        if (complete.ran) return;
-        if (err) return done(complete.ran = err);
+        if (complete.ran) {
+          return;
+        }
+        if (err) {
+          return done(complete.ran = err);
+        }
         --pending || test();
       }
 
       Test.on('index', complete);
-      Test.create({ loc: [ 35, 50 ]}, { loc: [ -40, -90 ]}, complete);
+      Test.create({loc: [35, 50]}, {loc: [-40, -90]}, complete);
 
       function test() {
-        Test.find({ loc: { '$within': { '$box': [[30,40], [40,60]] }}}, function(err, docs) {
+        Test.find({loc: {'$within': {'$box': [[30, 40], [40, 60]]}}}, function (err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(1, docs.length);
@@ -2120,22 +2189,27 @@ describe('geo-spatial', function() {
       }
     });
 
-    it('$nearSphere with arrays (gh-610)', function(done) {
+    it('$nearSphere with arrays (gh-610)', function (done) {
       var db = start(),
-          Test = db.model('Geo3', geoSchema, "y" + random());
+          Test = db.model('Geo3', geoSchema, 'y' + random());
 
       var pending = 2;
+
       function complete(err) {
-        if (complete.ran) return;
-        if (err) return done(complete.ran = err);
+        if (complete.ran) {
+          return;
+        }
+        if (err) {
+          return done(complete.ran = err);
+        }
         --pending || test();
       }
 
       Test.on('index', complete);
-      Test.create({ loc: [ 10, 20 ]}, { loc: [ 40, 90 ]}, complete);
+      Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
       function test() {
-        Test.find({ loc: { $nearSphere: [30, 40] }}, function(err, docs) {
+        Test.find({loc: {$nearSphere: [30, 40]}}, function (err, docs) {
           assert.ifError(err);
           assert.equal(2, docs.length);
           db.close(done);
@@ -2143,41 +2217,45 @@ describe('geo-spatial', function() {
       }
     });
 
-    it('$nearSphere with invalid coordinate does not crash (gh-1874)', function(done) {
+    it('$nearSphere with invalid coordinate does not crash (gh-1874)', function (done) {
       var geoSchema = new Schema({
         loc: {
-          type: { type: String },
-          coordinates: { type: [Number], index: '2dsphere' }
+          type: {type: String},
+          coordinates: {type: [Number], index: '2dsphere'}
         }
       });
       var db = start(),
           Test = db.model('gh1874', geoSchema, 'gh1874');
 
       var pending = 2;
-      var complete = function(err) {
-        if (complete.ran) return;
-        if (err) return done(complete.ran = err);
+      var complete = function (err) {
+        if (complete.ran) {
+          return;
+        }
+        if (err) {
+          return done(complete.ran = err);
+        }
         --pending || test();
       };
 
       Test.on('index', complete);
       Test.create(
-        { loc: { coordinates: [ 30, 41 ] } },
-        { loc: { coordinates: [ 31, 40 ] } },
-        complete);
+          {loc: {coordinates: [30, 41]}},
+          {loc: {coordinates: [31, 40]}},
+          complete);
 
-      var test = function() {
+      var test = function () {
         var q = new Query({}, {}, null, Test.collection);
         q.find({
           'loc': {
             $nearSphere: {
-              $geometry: { type: 'Point', coordinates: [30, 40] },
+              $geometry: {type: 'Point', coordinates: [30, 40]},
               $maxDistance: 10000000
             }
           }
         });
 
-        assert.doesNotThrow(function() {
+        assert.doesNotThrow(function () {
           q.cast(Test);
         });
 
@@ -2185,25 +2263,30 @@ describe('geo-spatial', function() {
       };
     });
 
-    it('$maxDistance with arrays', function(done) {
+    it('$maxDistance with arrays', function (done) {
       var db = start(),
-          Test = db.model('Geo4', geoSchema, "x" + random());
+          Test = db.model('Geo4', geoSchema, 'x' + random());
 
       var pending = 2;
+
       function complete(err) {
-        if (complete.ran) return;
-        if (err) return done(complete.ran = err);
+        if (complete.ran) {
+          return;
+        }
+        if (err) {
+          return done(complete.ran = err);
+        }
         --pending || test();
       }
 
       Test.on('index', complete);
-      Test.create({ loc: [ 20, 80 ]}, { loc: [ 25, 30 ]}, complete);
+      Test.create({loc: [20, 80]}, {loc: [25, 30]}, complete);
 
       function test() {
-        Test.find({ loc: { $near: [25, 31], $maxDistance: 1 }}, function(err, docs) {
+        Test.find({loc: {$near: [25, 31], $maxDistance: 1}}, function (err, docs) {
           assert.ifError(err);
           assert.equal(1, docs.length);
-          Test.find({ loc: { $near: [25, 32], $maxDistance: 1 }}, function(err, docs) {
+          Test.find({loc: {$near: [25, 32], $maxDistance: 1}}, function (err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(0, docs.length);
@@ -2214,60 +2297,68 @@ describe('geo-spatial', function() {
     });
   });
 
-  describe('2dsphere', function() {
+  describe('2dsphere', function () {
     // mongodb 2.4
 
-    var schema2dsphere = new Schema({ loc: { type: [Number], index: '2dsphere'}});
+    var schema2dsphere = new Schema({loc: {type: [Number], index: '2dsphere'}});
 
-    var geoSchema = new Schema({ line: { type: { type: String }, coordinates: []}});
-    geoSchema.index({ line: '2dsphere' });
+    var geoSchema = new Schema({line: {type: {type: String}, coordinates: []}});
+    geoSchema.index({line: '2dsphere'});
 
-    var geoMultiSchema = new Schema({ geom: [{ type: { type: String }, coordinates: []}]});
+    var geoMultiSchema = new Schema({geom: [{type: {type: String}, coordinates: []}]});
     // see mongodb issue SERVER-8907
     // geoMultiSchema.index({ geom: '2dsphere' });
 
     var mongo24_or_greater = false;
-    before(function(done) {
-      start.mongodVersion(function(err, version) {
-        if (err) throw err;
+    before(function (done) {
+      start.mongodVersion(function (err, version) {
+        if (err) {
+          throw err;
+        }
 
         mongo24_or_greater = 2 < version[0] || (2 == version[0] && 4 <= version[1]);
-        if (!mongo24_or_greater) console.log('not testing mongodb 2.4 features');
+        if (!mongo24_or_greater) {
+          console.log('not testing mongodb 2.4 features');
+        }
         done();
       });
     });
 
-    it('index is allowed in schema', function(done) {
-      if (!mongo24_or_greater) return done();
+    it('index is allowed in schema', function (done) {
+      if (!mongo24_or_greater) {
+        return done();
+      }
 
-      var ok = schema2dsphere.indexes().some(function(index) {
+      var ok = schema2dsphere.indexes().some(function (index) {
         return '2dsphere' == index[0].loc;
       });
       assert.ok(ok);
       done();
     });
 
-    describe('$geometry', function() {
-      it('Polygon', function(done) {
-        if (!mongo24_or_greater) return done();
+    describe('$geometry', function () {
+      it('Polygon', function (done) {
+        if (!mongo24_or_greater) {
+          return done();
+        }
 
         var db = start(),
             Test = db.model('2dsphere-polygon', schema2dsphere, 'geospatial' + random());
 
-        Test.on('index', function(err) {
+        Test.on('index', function (err) {
           assert.ifError(err);
 
-          Test.create({ loc: [ 0, 0 ]}, function(err, created) {
+          Test.create({loc: [0, 0]}, function (err, created) {
             assert.ifError(err);
 
-            var geojsonPoly = { type: 'Polygon', coordinates: [[[-5,-5], ['-5',5], [5,5], [5,-5],[-5,'-5']]] };
+            var geojsonPoly = {type: 'Polygon', coordinates: [[[-5, -5], ['-5', 5], [5, 5], [5, -5], [-5, '-5']]]};
 
-            Test.find({ loc: { $within: { $geometry: geojsonPoly }}}, function(err, docs) {
+            Test.find({loc: {$within: {$geometry: geojsonPoly}}}, function (err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
               assert.equal(created.id, docs[0].id);
 
-              Test.where('loc').within().geometry(geojsonPoly).exec(function(err, docs) {
+              Test.where('loc').within().geometry(geojsonPoly).exec(function (err, docs) {
                 assert.ifError(err);
                 assert.equal(1, docs.length);
                 assert.equal(created.id, docs[0].id);
@@ -2279,55 +2370,60 @@ describe('geo-spatial', function() {
       });
     });
 
-    describe('$geoIntersects', function() {
-      it('LineString', function(done) {
-        if (!mongo24_or_greater) return done();
+    describe('$geoIntersects', function () {
+      it('LineString', function (done) {
+        if (!mongo24_or_greater) {
+          return done();
+        }
 
         var db = start(),
             Test = db.model('2dsphere-geo', geoSchema, 'geospatial' + random());
 
-        Test.on('index', function(err) {
+        Test.on('index', function (err) {
           assert.ifError(err);
 
-          Test.create({ line: { type:'LineString', coordinates: [[-178.0, 10.0],[178.0,10.0]] }}, function(err, created) {
+          Test.create({line: {type: 'LineString', coordinates: [[-178.0, 10.0], [178.0, 10.0]]}}, function (err, created) {
             assert.ifError(err);
 
-            var geojsonLine = { type: 'LineString', coordinates: [[180.0, 11.0], [180.0, '9.00']] };
+            var geojsonLine = {type: 'LineString', coordinates: [[180.0, 11.0], [180.0, '9.00']]};
 
-            Test.find({ line: { $geoIntersects: { $geometry: geojsonLine }}}, function(err, docs) {
+            Test.find({line: {$geoIntersects: {$geometry: geojsonLine}}}, function (err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
               assert.equal(created.id, docs[0].id);
 
-              Test.where('line').intersects().geometry(geojsonLine).findOne(function(err, doc) {
+              Test.where('line').intersects().geometry(geojsonLine).findOne(function (err, doc) {
                 assert.ifError(err);
                 assert.equal(created.id, doc.id);
                 db.close(done);
               });
             });
           });
-
         });
       });
 
-      it('MultiLineString', function(done) {
-        if (!mongo24_or_greater) return done();
+      it('MultiLineString', function (done) {
+        if (!mongo24_or_greater) {
+          return done();
+        }
 
         var db = start(),
             Test = db.model('2dsphere-geo-multi1', geoMultiSchema, 'geospatial' + random());
 
-        Test.create({ geom: [{ type:'LineString', coordinates: [[-178.0, 10.0],[178.0,10.0]] },
-                             { type:'LineString', coordinates: [[-178.0, 5.0],[178.0,5.0]] } ]}, function(err, created) {
+        Test.create({
+          geom: [{type: 'LineString', coordinates: [[-178.0, 10.0], [178.0, 10.0]]},
+            {type: 'LineString', coordinates: [[-178.0, 5.0], [178.0, 5.0]]}]
+        }, function (err, created) {
           assert.ifError(err);
 
-          var geojsonLine = { type: 'LineString', coordinates: [[180.0, 11.0], [180.0, '9.00']] };
+          var geojsonLine = {type: 'LineString', coordinates: [[180.0, 11.0], [180.0, '9.00']]};
 
-          Test.find({ geom: { $geoIntersects: { $geometry: geojsonLine }}}, function(err, docs) {
+          Test.find({geom: {$geoIntersects: {$geometry: geojsonLine}}}, function (err, docs) {
             assert.ifError(err);
             assert.equal(1, docs.length);
             assert.equal(created.id, docs[0].id);
 
-            Test.where('geom').intersects().geometry(geojsonLine).findOne(function(err, doc) {
+            Test.where('geom').intersects().geometry(geojsonLine).findOne(function (err, doc) {
               assert.ifError(err);
               assert.equal(created.id, doc.id);
               db.close(done);
@@ -2336,24 +2432,28 @@ describe('geo-spatial', function() {
         });
       });
 
-      it('MultiPolygon', function(done) {
-        if (!mongo24_or_greater) return done();
+      it('MultiPolygon', function (done) {
+        if (!mongo24_or_greater) {
+          return done();
+        }
 
         var db = start(),
             Test = db.model('2dsphere-geo-multi2', geoMultiSchema, 'geospatial' + random());
 
-        Test.create({ geom: [{ type: "Polygon", coordinates: [[ [28.7,41],[29.2,40.9],[29.1,41.3],[28.7,41] ]] },
-                             { type: "Polygon", coordinates: [[ [-1,-1],[1,-1],[1,1],[-1,1],[-1,-1] ]] }]}, function(err, created) {
+        Test.create({
+          geom: [{type: 'Polygon', coordinates: [[[28.7, 41], [29.2, 40.9], [29.1, 41.3], [28.7, 41]]]},
+            {type: 'Polygon', coordinates: [[[-1, -1], [1, -1], [1, 1], [-1, 1], [-1, -1]]]}]
+        }, function (err, created) {
           assert.ifError(err);
 
-          var geojsonPolygon = { type: 'Polygon', coordinates: [[ [26,36],[45,36],[45,42],[26,42],[26,36] ]] };
+          var geojsonPolygon = {type: 'Polygon', coordinates: [[[26, 36], [45, 36], [45, 42], [26, 42], [26, 36]]]};
 
-          Test.find({ geom: { $geoIntersects: { $geometry: geojsonPolygon }}}, function(err, docs) {
+          Test.find({geom: {$geoIntersects: {$geometry: geojsonPolygon}}}, function (err, docs) {
             assert.ifError(err);
             assert.equal(1, docs.length);
             assert.equal(created.id, docs[0].id);
 
-            Test.where('geom').intersects().geometry(geojsonPolygon).findOne(function(err, doc) {
+            Test.where('geom').intersects().geometry(geojsonPolygon).findOne(function (err, doc) {
               assert.ifError(err);
               assert.equal(created.id, doc.id);
               db.close(done);
@@ -2363,27 +2463,29 @@ describe('geo-spatial', function() {
       });
     });
 
-    describe('$near', function() {
-      it('Point', function(done) {
-        if (!mongo24_or_greater) return done();
+    describe('$near', function () {
+      it('Point', function (done) {
+        if (!mongo24_or_greater) {
+          return done();
+        }
 
         var db = start(),
             Test = db.model('2dsphere-geo', geoSchema, 'geospatial' + random());
 
-        Test.on('index', function(err) {
+        Test.on('index', function (err) {
           assert.ifError(err);
 
-          Test.create({ line: { type:'Point', coordinates: [-179.0, 0.0] }}, function(err, created) {
+          Test.create({line: {type: 'Point', coordinates: [-179.0, 0.0]}}, function (err, created) {
             assert.ifError(err);
 
-            var geojsonPoint = { type: 'Point', coordinates: [-179.0, 0.0] };
+            var geojsonPoint = {type: 'Point', coordinates: [-179.0, 0.0]};
 
-            Test.find({ line: { $near: geojsonPoint }}, function(err, docs) {
+            Test.find({line: {$near: geojsonPoint}}, function (err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
               assert.equal(created.id, docs[0].id);
 
-              Test.find({ line: { $near: { $geometry: geojsonPoint, $maxDistance: 50 } } }, function(err, docs) {
+              Test.find({line: {$near: {$geometry: geojsonPoint, $maxDistance: 50}}}, function (err, docs) {
                 assert.ifError(err);
                 assert.equal(1, docs.length);
                 assert.equal(created.id, docs[0].id);
@@ -2394,77 +2496,95 @@ describe('geo-spatial', function() {
         });
       });
 
-      it('works with GeoJSON (gh-1482)', function(done) {
-        if (!mongo24_or_greater) return done();
+      it('works with GeoJSON (gh-1482)', function (done) {
+        if (!mongo24_or_greater) {
+          return done();
+        }
 
-        var geoJSONSchema = new Schema({ loc: { type: { type: String }, coordinates: [Number] } });
-        geoJSONSchema.index({ loc: '2dsphere' });
+        var geoJSONSchema = new Schema({loc: {type: {type: String}, coordinates: [Number]}});
+        geoJSONSchema.index({loc: '2dsphere'});
         var name = 'geospatial' + random();
         var db = start(),
             Test = db.model('Geo1', geoJSONSchema, name);
 
         var pending = 2;
+
         function complete(err) {
-          if (complete.ran) return;
-          if (err) return done(complete.ran = err);
+          if (complete.ran) {
+            return;
+          }
+          if (err) {
+            return done(complete.ran = err);
+          }
           --pending || test();
         }
 
         Test.on('index', complete);
-        Test.create({ loc: { type: 'Point', coordinates :[ 10, 20 ]}}, { loc: {
-          type: 'Point', coordinates: [ 40, 90 ]}}, complete);
+        Test.create({loc: {type: 'Point', coordinates: [10, 20]}}, {
+          loc: {
+            type: 'Point', coordinates: [40, 90]
+          }
+        }, complete);
 
         function test() {
           // $maxDistance is in meters... so even though they aren't that far off
           // in lat/long, need an incredibly high number here
-          Test.where('loc').near({ center: { type: 'Point', coordinates :
-            [11,20]}, maxDistance: 1000000 }).exec(function(err, docs) {
-              db.close();
-              assert.ifError(err);
-              assert.equal(1, docs.length);
-              done();
-            });
+          Test.where('loc').near({
+            center: {
+              type: 'Point', coordinates: [11, 20]
+            }, maxDistance: 1000000
+          }).exec(function (err, docs) {
+            db.close();
+            assert.ifError(err);
+            assert.equal(1, docs.length);
+            done();
+          });
         }
       });
-
     });
   });
 
-  describe('hashed indexes', function() {
+  describe('hashed indexes', function () {
     var mongo24_or_greater = false;
 
-    before(function(done) {
-      start.mongodVersion(function(err, version) {
-        if (err) return done(err);
+    before(function (done) {
+      start.mongodVersion(function (err, version) {
+        if (err) {
+          return done(err);
+        }
         mongo24_or_greater = 2 < version[0] || (2 == version[0] && 4 <= version[1]);
-        if (!mongo24_or_greater) console.log('not testing mongodb 2.4 features');
+        if (!mongo24_or_greater) {
+          console.log('not testing mongodb 2.4 features');
+        }
         done();
       });
     });
 
-    it('work', function(done) {
-      if (!mongo24_or_greater) return done();
+    it('work', function (done) {
+      if (!mongo24_or_greater) {
+        return done();
+      }
       var db = start();
       var schemas = [];
-      schemas[0] = new Schema({ t: { type: String, index: 'hashed' }});
-      schemas[1] = new Schema({ t: { type: String, index: 'hashed', sparse: true }});
-      schemas[2] = new Schema({ t: { type: String, index: { type: 'hashed', sparse: true }}});
+      schemas[0] = new Schema({t: {type: String, index: 'hashed'}});
+      schemas[1] = new Schema({t: {type: String, index: 'hashed', sparse: true}});
+      schemas[2] = new Schema({t: {type: String, index: {type: 'hashed', sparse: true}}});
 
       var pending = schemas.length;
 
-      schemas.forEach(function(schema, i) {
+      schemas.forEach(function (schema, i) {
         var H = db.model('Hashed' + i, schema);
-        H.on('index', function(err) {
+        H.on('index', function (err) {
           assert.ifError(err);
-          H.collection.getIndexes({ full: true }, function(err, indexes) {
+          H.collection.getIndexes({full: true}, function (err, indexes) {
             assert.ifError(err);
 
-            var found = indexes.some(function(index) {
+            var found = indexes.some(function (index) {
               return 'hashed' === index.key.t;
             });
             assert.ok(found);
 
-            H.create({ t: 'hashing' }, { }, function(err, doc1, doc2) {
+            H.create({t: 'hashing'}, {}, function (err, doc1, doc2) {
               assert.ifError(err);
               assert.ok(doc1);
               assert.ok(doc2);
@@ -2483,8 +2603,8 @@ describe('geo-spatial', function() {
   });
 });
 
-describe('lean option:', function() {
-  it('find', function(done) {
+describe('lean option:', function () {
+  it('find', function (done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         title = 'Wooooot ' + random();
@@ -2492,13 +2612,13 @@ describe('lean option:', function() {
     var post = new BlogPostB();
     post.set('title', title);
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
-      BlogPostB.find({title: title}).lean().exec(function(err, docs) {
+      BlogPostB.find({title: title}).lean().exec(function (err, docs) {
         assert.ifError(err);
         assert.equal(docs.length, 1);
         assert.strictEqual(docs[0] instanceof mongoose.Document, false);
-        BlogPostB.find({title: title}, null, { lean: true }, function(err, docs) {
+        BlogPostB.find({title: title}, null, {lean: true}, function (err, docs) {
           assert.ifError(err);
           assert.equal(docs.length, 1);
           assert.strictEqual(docs[0] instanceof mongoose.Document, false);
@@ -2509,7 +2629,7 @@ describe('lean option:', function() {
     });
   });
 
-  it('findOne', function(done) {
+  it('findOne', function (done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         title = 'Wooooot ' + random();
@@ -2517,9 +2637,9 @@ describe('lean option:', function() {
     var post = new BlogPostB();
     post.set('title', title);
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
-      BlogPostB.findOne({title: title}, null, { lean: true }, function(err, doc) {
+      BlogPostB.findOne({title: title}, null, {lean: true}, function (err, doc) {
         db.close();
         assert.ifError(err);
         assert.ok(doc);
@@ -2528,18 +2648,18 @@ describe('lean option:', function() {
       });
     });
   });
-  it('properly casts nested and/or queries (gh-676)', function(done) {
+  it('properly casts nested and/or queries (gh-676)', function (done) {
     var sch = new Schema({
       num: Number,
-      subdoc: { title: String, num: Number }
+      subdoc: {title: String, num: Number}
     });
 
     var M = mongoose.model('andor' + random(), sch);
 
     var cond = {
       $and: [
-        { $or: [ { num: '23' }, { 'subdoc.num' : '45' } ] },
-        { $and: [ { 'subdoc.title' : 233 }, { num: '345' } ] }
+        {$or: [{num: '23'}, {'subdoc.num': '45'}]},
+        {$and: [{'subdoc.title': 233}, {num: '345'}]}
       ]
     };
     var q = M.find(cond);
@@ -2549,28 +2669,16 @@ describe('lean option:', function() {
     assert.equal('number', typeof q._conditions.$and[1].$and[1].num);
     done();
   });
-  it('properly casts deeply nested and/or queries (gh-676)', function(done) {
+  it('properly casts deeply nested and/or queries (gh-676)', function (done) {
     var sch = new Schema({
       num: Number,
-      subdoc: { title: String, num: Number }
+      subdoc: {title: String, num: Number}
     });
 
     var M = mongoose.model('andor' + random(), sch);
 
     var cond = {
-      $and: [
-        { $or: [
-            { $and: [
-                { $or: [
-                    { num: '12345' },
-                    { 'subdoc.num' : '56789' }
-                ]
-                }
-            ]
-            }
-        ]
-        }
-      ]
+      $and: [{$or: [{$and: [{$or: [{num: '12345'}, {'subdoc.num': '56789'}]}]}]}]
     };
     var q = M.find(cond);
     assert.equal('number', typeof q._conditions.$and[0].$or[0].$and[0].$or[0].num);
@@ -2578,52 +2686,54 @@ describe('lean option:', function() {
     done();
   });
 
-  it('casts $elemMatch (gh-2199)', function(done) {
+  it('casts $elemMatch (gh-2199)', function (done) {
     var db = start();
-    var schema = new Schema({ dates: [Date] });
+    var schema = new Schema({dates: [Date]});
     var Dates = db.model('Date', schema, 'dates');
 
     var array = ['2014-07-01T02:00:00.000Z', '2014-07-01T04:00:00.000Z'];
-    Dates.create({ dates: array }, function(err) {
+    Dates.create({dates: array}, function (err) {
       assert.ifError(err);
-      var elemMatch = { $gte: '2014-07-01T03:00:00.000Z' };
-      Dates.findOne({}, { dates: { $elemMatch: elemMatch } }, function(err, doc) {
+      var elemMatch = {$gte: '2014-07-01T03:00:00.000Z'};
+      Dates.findOne({}, {dates: {$elemMatch: elemMatch}}, function (err, doc) {
         assert.ifError(err);
         assert.equal(doc.dates.length, 1);
         assert.equal(doc.dates[0].getTime(),
-          new Date('2014-07-01T04:00:00.000Z').getTime());
+            new Date('2014-07-01T04:00:00.000Z').getTime());
         db.close(done);
       });
     });
   });
 
-  describe('$eq', function() {
+  describe('$eq', function () {
     var mongo26 = false;
 
-    before(function(done) {
-      start.mongodVersion(function(err, version) {
-        if (err) return done(err);
+    before(function (done) {
+      start.mongodVersion(function (err, version) {
+        if (err) {
+          return done(err);
+        }
         mongo26 = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
         done();
       });
     });
 
-    it('casts $eq (gh-2752)', function(done) {
+    it('casts $eq (gh-2752)', function (done) {
       var db = start();
       var BlogPostB = db.model('BlogPostB', collection);
 
       BlogPostB.findOne(
-        { _id: { $eq: '000000000000000000000001' }, numbers: { $eq: [1, 2] } },
-        function(err, doc) {
-          if (mongo26) {
-            assert.ifError(err);
-          } else {
-            assert.ok(err.toString().indexOf('MongoError') !== -1);
-          }
+          {_id: {$eq: '000000000000000000000001'}, numbers: {$eq: [1, 2]}},
+          function (err, doc) {
+            if (mongo26) {
+              assert.ifError(err);
+            } else {
+              assert.ok(err.toString().indexOf('MongoError') !== -1);
+            }
 
-          assert.ok(!doc);
-          db.close(done);
-        });
+            assert.ok(!doc);
+            db.close(done);
+          });
     });
   });
 });
diff --git a/test/model.stream.test.js b/test/model.stream.test.js
index 6da0981e323..aa2780630ba 100644
--- a/test/model.stream.test.js
+++ b/test/model.stream.test.js
@@ -24,23 +24,23 @@ var Person = new Schema({
 mongoose.model('PersonForStream', Person);
 var collection = 'personforstream_' + random();
 
-describe('query stream:', function() {
-  before(function(done) {
+describe('query stream:', function () {
+  before(function (done) {
     var db = start(),
         P = db.model('PersonForStream', collection);
 
-    var people = names.map(function(name) {
-      return { name: name };
+    var people = names.map(function (name) {
+      return {name: name};
     });
 
-    P.create(people, function(err) {
+    P.create(people, function (err) {
       assert.ifError(err);
       db.close();
       done();
     });
   });
 
-  it('works', function(done) {
+  it('works', function (done) {
     var db = start(),
         P = db.model('PersonForStream', collection),
         i = 0,
@@ -52,7 +52,7 @@ describe('query stream:', function() {
 
     var stream = P.find().batchSize(3).stream();
 
-    stream.on('data', function(doc) {
+    stream.on('data', function (doc) {
       assert.strictEqual(true, !!doc.name);
       assert.strictEqual(true, !!doc._id);
 
@@ -73,7 +73,7 @@ describe('query stream:', function() {
         assert.equal(true, stream.paused);
         paused++;
 
-        setTimeout(function() {
+        setTimeout(function () {
           assert.equal(true, stream.paused);
           resumed++;
           stream.resume();
@@ -87,12 +87,12 @@ describe('query stream:', function() {
       }
     });
 
-    stream.on('error', function(er) {
+    stream.on('error', function (er) {
       err = er;
       cb();
     });
 
-    stream.on('close', function() {
+    stream.on('close', function () {
       closed++;
       cb();
     });
@@ -109,14 +109,14 @@ describe('query stream:', function() {
     }
   });
 
-  it('immediately destroying a stream prevents the query from executing', function(done) {
+  it('immediately destroying a stream prevents the query from executing', function (done) {
     var db = start(),
         P = db.model('PersonForStream', collection),
         i = 0;
 
     var stream = P.where('name', 'Jonah').select('name').findOne().stream();
 
-    stream.on('data', function() {
+    stream.on('data', function () {
       i++;
     });
     stream.on('close', cb);
@@ -127,7 +127,7 @@ describe('query stream:', function() {
     function cb(err) {
       assert.ifError(err);
       assert.equal(0, i);
-      process.nextTick(function() {
+      process.nextTick(function () {
         db.close();
         assert.strictEqual(null, stream._fields);
         done();
@@ -135,7 +135,7 @@ describe('query stream:', function() {
     }
   });
 
-  it('destroying a stream stops it', function(done) {
+  it('destroying a stream stops it', function (done) {
     this.slow(300);
 
     var db = start(),
@@ -148,7 +148,7 @@ describe('query stream:', function() {
     assert.strictEqual(null, stream._destroyed);
     assert.equal(true, stream.readable);
 
-    stream.on('data', function(doc) {
+    stream.on('data', function (doc) {
       assert.strictEqual(undefined, doc.name);
       if (++i === 5) {
         stream.destroy();
@@ -161,7 +161,7 @@ describe('query stream:', function() {
 
     function cb(err) {
       ++finished;
-      setTimeout(function() {
+      setTimeout(function () {
         db.close();
         assert.strictEqual(undefined, err);
         assert.equal(5, i);
@@ -174,10 +174,10 @@ describe('query stream:', function() {
     }
   });
 
-  it('errors', function(done) {
+  it('errors', function (done) {
     this.slow(300);
 
-    var db = start({ server: { auto_reconnect: false }}),
+    var db = start({server: {auto_reconnect: false}}),
         P = db.model('PersonForStream', collection),
         finished = 0,
         closed = 0,
@@ -185,13 +185,13 @@ describe('query stream:', function() {
 
     var stream = P.find().batchSize(5).stream();
 
-    stream.on('data', function() {
+    stream.on('data', function () {
       if (++i === 5) {
         db.close();
       }
     });
 
-    stream.on('close', function() {
+    stream.on('close', function () {
       closed++;
     });
 
@@ -199,12 +199,12 @@ describe('query stream:', function() {
 
     function cb(err) {
       ++finished;
-      setTimeout(function() {
+      setTimeout(function () {
         assert.ok(/destroyed/.test(err.message), err.message);
         assert.equal(i, 5);
         assert.equal(1, closed);
         assert.equal(1, finished);
-        assert.equal(stream._destroyed,true);
+        assert.equal(stream._destroyed, true);
         assert.equal(stream.readable, false);
         assert.equal(stream._cursor.isClosed(), true);
         done();
@@ -212,17 +212,17 @@ describe('query stream:', function() {
     }
   });
 
-  it('pipe', function(done) {
+  it('pipe', function (done) {
     var db = start(),
         P = db.model('PersonForStream', collection),
         filename = '/tmp/_mongoose_stream_out.txt',
         out = fs.createWriteStream(filename);
 
-    var opts = { transform: JSON.stringify };
+    var opts = {transform: JSON.stringify};
     var stream = P.find().sort('name').limit(20).stream(opts);
     stream.pipe(out);
 
-    var cb = function(err) {
+    var cb = function (err) {
       db.close();
       assert.ifError(err);
       var contents = fs.readFileSync(filename, 'utf8');
@@ -239,7 +239,7 @@ describe('query stream:', function() {
     out.on('close', cb);
   });
 
-  it('lean', function(done) {
+  it('lean', function (done) {
     var db = start(),
         P = db.model('PersonForStream', collection),
         i = 0,
@@ -248,7 +248,7 @@ describe('query stream:', function() {
 
     var stream = P.find({}).lean().stream();
 
-    stream.on('data', function(doc) {
+    stream.on('data', function (doc) {
       assert.strictEqual(false, doc instanceof mongoose.Document);
       i++;
 
@@ -260,7 +260,7 @@ describe('query stream:', function() {
       } else if (2 === i) {
         stream.pause();
         assert.equal(true, stream.paused);
-        process.nextTick(function() {
+        process.nextTick(function () {
           assert.equal(true, stream.paused);
           stream.resume();
           assert.equal(false, stream.paused);
@@ -268,17 +268,17 @@ describe('query stream:', function() {
       }
     });
 
-    stream.on('error', function(er) {
+    stream.on('error', function (er) {
       err = er;
       cb();
     });
 
-    stream.on('close', function() {
+    stream.on('close', function () {
       closed++;
       cb();
     });
 
-    var cb = function() {
+    var cb = function () {
       db.close();
       assert.strictEqual(undefined, err);
       assert.equal(i, names.length);
@@ -288,7 +288,7 @@ describe('query stream:', function() {
     };
   });
 
-  it('supports $elemMatch with $in (gh-1091)', function(done) {
+  it('supports $elemMatch with $in (gh-1091)', function (done) {
     this.timeout(3000);
 
     var db = start();
@@ -302,32 +302,32 @@ describe('query stream:', function() {
     var _id1 = new mongoose.Types.ObjectId;
     var _id2 = new mongoose.Types.ObjectId;
 
-    B.create({ ids: [_id1, _id2] }, function(err, doc) {
+    B.create({ids: [_id1, _id2]}, function (err, doc) {
       assert.ifError(err);
 
       var error;
 
-      var stream = B.find({ _id: doc._id })
-        .select({ title: 1, ids: { $elemMatch: { $in: [_id2.toString()] }}})
+      var stream = B.find({_id: doc._id})
+        .select({title: 1, ids: {$elemMatch: {$in: [_id2.toString()]}}})
         .stream();
 
       stream.
-        on('data', function(found) {
+        on('data', function (found) {
           assert.equal(found.id, doc.id);
           assert.equal(1, found.ids.length);
           assert.equal(_id2.toString(), found.ids[0].toString());
         }).
-        on('error', function(err) {
+        on('error', function (err) {
           error = err;
         }).
-        on('close', function() {
+        on('close', function () {
           db.close();
           done(error);
         });
     });
   });
 
-  it('supports population (gh-1411)', function(done) {
+  it('supports population (gh-1411)', function (done) {
     var db = start();
 
     var barSchema = Schema({
@@ -335,24 +335,24 @@ describe('query stream:', function() {
     });
 
     var fooSchema = Schema({
-      bar: { type: "ObjectId", ref: "Bar" }
+      bar: {type: 'ObjectId', ref: 'Bar'}
     });
 
     var Foo = db.model('Foo', fooSchema);
     var Bar = db.model('Bar', barSchema);
     var found = [];
 
-    Bar.create({ value: 2 }, { value: 3 }, function(err, bar1, bar2) {
+    Bar.create({value: 2}, {value: 3}, function (err, bar1, bar2) {
       if (err) return complete(err);
 
-      Foo.create({ bar: bar1 }, { bar: bar2 }, function(err) {
+      Foo.create({bar: bar1}, {bar: bar2}, function (err) {
         if (err) return complete(err);
 
         Foo.
           find().
           populate('bar').
           stream().
-          on('data', function(foo) {
+          on('data', function (foo) {
             found.push(foo.bar.value);
           }).
           on('end', complete).
@@ -360,7 +360,7 @@ describe('query stream:', function() {
       });
     });
 
-    var complete = function(err) {
+    var complete = function (err) {
       if (!err) {
         assert.ok(~found.indexOf(2));
         assert.ok(~found.indexOf(3));
@@ -369,45 +369,45 @@ describe('query stream:', function() {
     };
   });
 
-  it('respects schema options (gh-1862)', function(done) {
+  it('respects schema options (gh-1862)', function (done) {
     var db = start();
 
     var schema = Schema({
-      fullname: { type: String },
-      password: { type: String, select: false }
+      fullname: {type: String},
+      password: {type: String, select: false}
     });
 
     var User = db.model('gh-1862', schema, 'gh-1862');
-    User.create({ fullname: 'val', password: 'taco' }, function(error) {
+    User.create({fullname: 'val', password: 'taco'}, function (error) {
       assert.ifError(error);
-      User.find().stream().on('data', function(doc) {
+      User.find().stream().on('data', function (doc) {
         assert.equal(undefined, doc.password);
         db.close(done);
       });
     });
   });
 
-  it('works with populate + lean (gh-2841)', function(done) {
+  it('works with populate + lean (gh-2841)', function (done) {
     var db = start();
 
     var Sku = db.model('Sku', {}, 'gh2841_0');
     var Item = db.model('Item', {
-      sku: { ref: 'Sku', type: Schema.Types.ObjectId }
+      sku: {ref: 'Sku', type: Schema.Types.ObjectId}
     }, 'gh2841_1');
 
-    Sku.create({}, function(error, sku) {
+    Sku.create({}, function (error, sku) {
       assert.ifError(error);
-      Item.create({ sku: sku._id }, function(error) {
+      Item.create({sku: sku._id}, function (error) {
         assert.ifError(error);
 
         var found = 0;
-        var popOpts = { path: 'sku', options: { lean: true } };
+        var popOpts = {path: 'sku', options: {lean: true}};
         var stream = Item.find().populate(popOpts).stream();
-        stream.on('data', function(doc) {
+        stream.on('data', function (doc) {
           ++found;
           assert.equal(doc.sku._id.toString(), sku._id.toString());
         });
-        stream.on('end', function() {
+        stream.on('end', function () {
           assert.equal(found, 1);
           db.close(done);
         });
@@ -415,7 +415,7 @@ describe('query stream:', function() {
     });
   });
 
-  it('works with populate + dynref (gh-3108)', function(done) {
+  it('works with populate + dynref (gh-3108)', function (done) {
     var db = start();
 
     var reviewSchema = new Schema({
@@ -459,21 +459,21 @@ describe('query stream:', function() {
 
     var c = 0;
 
-    var create = function(cb) {
-      Item1.create({ _id: ++c, name: 'Val' }, function(error) {
+    var create = function (cb) {
+      Item1.create({_id: ++c, name: 'Val'}, function (error) {
         assert.ifError(error);
-        Item2.create({ _id: ++c, otherName: 'Val' }, function(error) {
+        Item2.create({_id: ++c, otherName: 'Val'}, function (error) {
           assert.ifError(error);
           var review = {
             _id: c,
             text: 'Test',
-            item: { id: c - 1, type: 'dynrefItem1' },
+            item: {id: c - 1, type: 'dynrefItem1'},
             items: [
-              { id: c - 1, type: 'dynrefItem1' },
-              { id: c, type: 'dynrefItem2' }
+              {id: c - 1, type: 'dynrefItem1'},
+              {id: c, type: 'dynrefItem2'}
             ]
           };
-          Review.create(review, function(error) {
+          Review.create(review, function (error) {
             assert.ifError(error);
             cb();
           });
@@ -481,24 +481,24 @@ describe('query stream:', function() {
       });
     };
 
-    var test = function() {
+    var test = function () {
       var stream = Review.find({}).populate('items.id').stream();
       var count = 0;
 
-      stream.on('data', function(doc) {
+      stream.on('data', function (doc) {
         ++count;
         assert.equal('Val', doc.items[0].id.name);
         assert.equal('Val', doc.items[1].id.otherName);
       });
 
-      stream.on('close', function() {
+      stream.on('close', function () {
         assert.equal(count, 2);
         db.close(done);
       });
     };
 
-    create(function() {
-      create(function() {
+    create(function () {
+      create(function () {
         test();
       });
     });
diff --git a/test/model.test.js b/test/model.test.js
index 9b876c4c14b..b7ab7ebd05f 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -42,25 +42,25 @@ var BlogPost = new Schema({
   numbers: [Number],
   owners: [ObjectId],
   comments: [Comments],
-  nested: { array: [Number] }
+  nested: {array: [Number]}
 });
 
 BlogPost
 .virtual('titleWithAuthor')
-.get(function() {
+.get(function () {
   return this.get('title') + ' by ' + this.get('author');
 })
-.set(function(val) {
+.set(function (val) {
   var split = val.split(' by ');
   this.set('title', split[0]);
   this.set('author', split[1]);
 });
 
-BlogPost.method('cool', function() {
+BlogPost.method('cool', function () {
   return this;
 });
 
-BlogPost.static('woot', function() {
+BlogPost.static('woot', function () {
   return this;
 });
 
@@ -69,10 +69,10 @@ var bpSchema = BlogPost;
 
 var collection = 'blogposts_' + random();
 
-describe('Model', function() {
+describe('Model', function () {
   var db, Test;
 
-  before(function() {
+  before(function () {
     db = start();
     var testSchema = new Schema({
       _id: {
@@ -88,46 +88,46 @@ describe('Model', function() {
     Test = db.model('test-schema', testSchema);
   });
 
-  after(function() {
+  after(function () {
     db.close();
   });
 
-  it('can be created using _id as embedded document', function(done) {
+  it('can be created using _id as embedded document', function (done) {
     var t = new Test({
       _id: {
-        first_name: "Daniel",
+        first_name: 'Daniel',
         age: 21
       },
-      last_name: "Alabi",
+      last_name: 'Alabi',
       doc_embed: {
-        some: "a"
+        some: 'a'
       }
     });
 
-    t.save(function(err) {
+    t.save(function (err) {
       assert.ifError(err);
-      Test.findOne({}, function(err, doc) {
+      Test.findOne({}, function (err, doc) {
         assert.ifError(err);
 
         assert.ok('last_name' in doc);
         assert.ok('_id' in doc);
         assert.ok('first_name' in doc._id);
-        assert.equal("Daniel", doc._id.first_name);
+        assert.equal('Daniel', doc._id.first_name);
         assert.ok('age' in doc._id);
         assert.equal(21, doc._id.age);
 
         assert.ok('doc_embed' in doc);
         assert.ok('some' in doc.doc_embed);
-        assert.equal("a", doc.doc_embed.some);
+        assert.equal('a', doc.doc_embed.some);
         done();
       });
     });
   });
 });
 
-describe('Model', function() {
-  describe('constructor', function() {
-    it('works without "new" keyword', function(done) {
+describe('Model', function () {
+  describe('constructor', function () {
+    it('works without "new" keyword', function (done) {
       var B = mongoose.model('BlogPost');
       var b = B();
       assert.ok(b instanceof B);
@@ -138,7 +138,7 @@ describe('Model', function() {
       assert.ok(b instanceof B);
       done();
     });
-    it('works "new" keyword', function(done) {
+    it('works "new" keyword', function (done) {
       var B = mongoose.model('BlogPost');
       var b = new B();
       assert.ok(b instanceof B);
@@ -150,8 +150,8 @@ describe('Model', function() {
       done();
     });
   });
-  describe('isNew', function() {
-    it('is true on instantiation', function(done) {
+  describe('isNew', function () {
+    it('is true on instantiation', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -161,24 +161,24 @@ describe('Model', function() {
       done();
     });
 
-    it('on parent and subdocs on failed inserts', function(done) {
+    it('on parent and subdocs on failed inserts', function (done) {
       var db = start();
 
       var schema = new Schema({
-        name: { type: String, unique: true },
-        em: [new Schema({ x: Number })]
-      }, { collection: 'testisnewonfail_' + random() });
+        name: {type: String, unique: true},
+        em: [new Schema({x: Number})]
+      }, {collection: 'testisnewonfail_' + random()});
 
       var A = db.model('isNewOnFail', schema);
 
-      A.on('index', function() {
-        var a = new A({ name: 'i am new', em: [{ x: 1 }] });
-        a.save(function(err) {
+      A.on('index', function () {
+        var a = new A({name: 'i am new', em: [{x: 1}]});
+        a.save(function (err) {
           assert.ifError(err);
           assert.equal(a.isNew, false);
           assert.equal(a.em[0].isNew, false);
-          var b = new A({ name: 'i am new', em: [{x:2}] });
-          b.save(function(err) {
+          var b = new A({name: 'i am new', em: [{x: 2}]});
+          b.save(function (err) {
             db.close();
             assert.ok(err);
             assert.equal(b.isNew, true);
@@ -190,7 +190,7 @@ describe('Model', function() {
     });
   });
 
-  it('gh-2140', function(done) {
+  it('gh-2140', function (done) {
     var db = start();
     var S = new Schema({
       field: [{text: String}]
@@ -205,8 +205,8 @@ describe('Model', function() {
     db.close(done);
   });
 
-  describe('schema', function() {
-    it('should exist', function(done) {
+  describe('schema', function () {
+    it('should exist', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -215,31 +215,31 @@ describe('Model', function() {
       assert.ok(BlogPost.prototype.schema instanceof Schema);
       done();
     });
-    it('emits init event', function(done) {
+    it('emits init event', function (done) {
       var db = start(),
-          schema = new Schema({ name: String }),
+          schema = new Schema({name: String}),
           model;
 
-      schema.on('init', function(model_) {
+      schema.on('init', function (model_) {
         model = model_;
       });
 
       var Named = db.model('EmitInitOnSchema', schema);
       db.close();
-      assert.equal(model,Named);
+      assert.equal(model, Named);
       done();
     });
   });
 
-  describe('structure', function() {
-    it('default when instantiated', function(done) {
+  describe('structure', function () {
+    it('default when instantiated', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       db.close();
       var post = new BlogPost;
-      assert.equal(post.db.model('BlogPost').modelName,'BlogPost');
-      assert.equal(post.constructor.modelName,'BlogPost');
+      assert.equal(post.db.model('BlogPost').modelName, 'BlogPost');
+      assert.equal(post.constructor.modelName, 'BlogPost');
 
       assert.ok(post.get('_id') instanceof DocumentObjectId);
 
@@ -262,9 +262,9 @@ describe('Model', function() {
       done();
     });
 
-    describe('array', function() {
-      describe('defaults', function() {
-        it('to a non-empty array', function(done) {
+    describe('array', function () {
+      describe('defaults', function () {
+        it('to a non-empty array', function (done) {
           var db = start(),
               DefaultArraySchema = new Schema({
                 arr: {type: Array, cast: String, default: ['a', 'b', 'c']},
@@ -275,15 +275,15 @@ describe('Model', function() {
           var arr = new DefaultArray;
           db.close();
           assert.equal(arr.get('arr').length, 3);
-          assert.equal(arr.get('arr')[0],'a');
-          assert.equal(arr.get('arr')[1],'b');
-          assert.equal(arr.get('arr')[2],'c');
+          assert.equal(arr.get('arr')[0], 'a');
+          assert.equal(arr.get('arr')[1], 'b');
+          assert.equal(arr.get('arr')[2], 'c');
           assert.equal(arr.get('single').length, 1);
-          assert.equal(arr.get('single')[0],'a');
+          assert.equal(arr.get('single')[0], 'a');
           done();
         });
 
-        it('empty', function(done) {
+        it('empty', function (done) {
           var db = start(),
               DefaultZeroCardArraySchema = new Schema({
                 arr: {type: Array, cast: String, default: []},
@@ -301,7 +301,7 @@ describe('Model', function() {
       });
     });
 
-    it('a hash with one null value', function(done) {
+    it('a hash with one null value', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -313,19 +313,21 @@ describe('Model', function() {
       done();
     });
 
-    it('when saved', function(done) {
+    it('when saved', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           pending = 2;
 
       function cb() {
-        if (--pending) return;
+        if (--pending) {
+          return;
+        }
         db.close();
         done();
       }
 
       var post = new BlogPost();
-      post.on('save', function(post) {
+      post.on('save', function (post) {
         assert.ok(post.get('_id') instanceof DocumentObjectId);
 
         assert.equal(undefined, post.get('title'));
@@ -343,7 +345,7 @@ describe('Model', function() {
         cb();
       });
 
-      post.save(function(err, post) {
+      post.save(function (err, post) {
         assert.ifError(err);
         assert.ok(post.get('_id') instanceof DocumentObjectId);
 
@@ -353,7 +355,7 @@ describe('Model', function() {
         assert.equal(undefined, post.get('published'));
 
         assert.equal(typeof post.get('meta'), 'object');
-        assert.deepEqual(post.get('meta'),{});
+        assert.deepEqual(post.get('meta'), {});
         assert.equal(undefined, post.get('meta.date'));
         assert.equal(undefined, post.get('meta.visitors'));
 
@@ -364,13 +366,13 @@ describe('Model', function() {
     });
 
 
-    it('when saved using the promise not the callback', function(done) {
+    it('when saved using the promise not the callback', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost();
       var p = post.save();
-      p.onResolve(function(err, post) {
+      p.onResolve(function (err, post) {
         assert.ifError(err);
         assert.ok(post.get('_id') instanceof DocumentObjectId);
 
@@ -380,7 +382,7 @@ describe('Model', function() {
         assert.equal(undefined, post.get('published'));
 
         assert.equal(typeof post.get('meta'), 'object');
-        assert.deepEqual(post.get('meta'),{});
+        assert.deepEqual(post.get('meta'), {});
         assert.equal(undefined, post.get('meta.date'));
         assert.equal(undefined, post.get('meta.visitors'));
 
@@ -391,8 +393,8 @@ describe('Model', function() {
     });
 
 
-    describe('init', function() {
-      it('works', function(done) {
+    describe('init', function () {
+      it('works', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -410,25 +412,25 @@ describe('Model', function() {
           published: true,
           owners: [new DocumentObjectId, new DocumentObjectId],
           comments: [
-                              { title: 'Test', date: new Date, body: 'Test' },
-                             { title: 'Super', date: new Date, body: 'Cool' }
+            {title: 'Test', date: new Date, body: 'Test'},
+            {title: 'Super', date: new Date, body: 'Cool'}
           ]
         });
 
-        assert.equal(post.get('title'),'Test');
-        assert.equal(post.get('slug'),'test');
+        assert.equal(post.get('title'), 'Test');
+        assert.equal(post.get('slug'), 'test');
         assert.ok(post.get('date') instanceof Date);
         assert.equal('object', typeof post.get('meta'));
         assert.ok(post.get('meta').date instanceof Date);
         assert.equal(typeof post.get('meta').visitors, 'number');
         assert.equal(post.get('published'), true);
 
-        assert.equal(post.title,'Test');
-        assert.equal(post.slug,'test');
+        assert.equal(post.title, 'Test');
+        assert.equal(post.slug, 'test');
         assert.ok(post.date instanceof Date);
-        assert.equal(typeof post.meta,'object');
+        assert.equal(typeof post.meta, 'object');
         assert.ok(post.meta.date instanceof Date);
-        assert.equal(typeof post.meta.visitors,'number');
+        assert.equal(typeof post.meta.visitors, 'number');
         assert.equal(post.published, true);
 
         assert.ok(post.get('owners').isMongooseArray);
@@ -449,7 +451,7 @@ describe('Model', function() {
         done();
       });
 
-      it('partially', function(done) {
+      it('partially', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -461,12 +463,12 @@ describe('Model', function() {
           date: new Date
         });
 
-        assert.equal(post.get('title'),'Test');
-        assert.equal(post.get('slug'),'test');
+        assert.equal(post.get('title'), 'Test');
+        assert.equal(post.get('slug'), 'test');
         assert.ok(post.get('date') instanceof Date);
         assert.equal('object', typeof post.get('meta'));
 
-        assert.deepEqual(post.get('meta'),{});
+        assert.deepEqual(post.get('meta'), {});
         assert.equal(undefined, post.get('meta.date'));
         assert.equal(undefined, post.get('meta.visitors'));
         assert.equal(undefined, post.get('published'));
@@ -476,7 +478,7 @@ describe('Model', function() {
         done();
       });
 
-      it('with partial hash', function(done) {
+      it('with partial hash', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -492,7 +494,7 @@ describe('Model', function() {
         done();
       });
 
-      it('isNew on embedded documents', function(done) {
+      it('isNew on embedded documents', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -501,27 +503,27 @@ describe('Model', function() {
         post.init({
           title: 'Test',
           slug: 'test',
-          comments: [ { title: 'Test', date: new Date, body: 'Test' } ]
+          comments: [{title: 'Test', date: new Date, body: 'Test'}]
         });
 
         assert.equal(false, post.get('comments')[0].isNew);
         done();
       });
 
-      it('isNew on embedded documents after saving', function(done) {
+      it('isNew on embedded documents after saving', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
-        var post = new BlogPost({ title: 'hocus pocus' });
-        post.comments.push({ title: 'Humpty Dumpty', comments: [{title: 'nested'}] });
+        var post = new BlogPost({title: 'hocus pocus'});
+        post.comments.push({title: 'Humpty Dumpty', comments: [{title: 'nested'}]});
         assert.equal(true, post.get('comments')[0].isNew);
         assert.equal(true, post.get('comments')[0].comments[0].isNew);
         post.invalidate('title'); // force error
-        post.save(function() {
+        post.save(function () {
           assert.equal(true, post.isNew);
           assert.equal(true, post.get('comments')[0].isNew);
           assert.equal(true, post.get('comments')[0].comments[0].isNew);
-          post.save(function(err) {
+          post.save(function (err) {
             db.close();
             assert.strictEqual(null, err);
             assert.equal(false, post.isNew);
@@ -534,20 +536,20 @@ describe('Model', function() {
     });
   });
 
-  it('collection name can be specified through schema', function(done) {
-    var schema = new Schema({ name: String }, { collection: 'users1' });
+  it('collection name can be specified through schema', function (done) {
+    var schema = new Schema({name: String}, {collection: 'users1'});
     var Named = mongoose.model('CollectionNamedInSchema1', schema);
-    assert.equal(Named.prototype.collection.name,'users1');
+    assert.equal(Named.prototype.collection.name, 'users1');
 
     var db = start();
-    var users2schema = new Schema({ name: String }, { collection: 'users2' });
+    var users2schema = new Schema({name: String}, {collection: 'users2'});
     var Named2 = db.model('CollectionNamedInSchema2', users2schema);
     db.close();
-    assert.equal(Named2.prototype.collection.name,'users2');
+    assert.equal(Named2.prototype.collection.name, 'users2');
     done();
   });
 
-  it('saving a model with a null value should perpetuate that null value to the db', function(done) {
+  it('saving a model with a null value should perpetuate that null value to the db', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -555,9 +557,9 @@ describe('Model', function() {
       title: null
     });
     assert.strictEqual(null, post.title);
-    post.save( function(err) {
+    post.save(function (err) {
       assert.strictEqual(err, null);
-      BlogPost.findById(post.id, function(err, found) {
+      BlogPost.findById(post.id, function (err, found) {
         db.close();
         assert.strictEqual(err, null);
         assert.strictEqual(found.title, null);
@@ -566,7 +568,7 @@ describe('Model', function() {
     });
   });
 
-  it('saves subdocuments middleware correctly', function(done) {
+  it('saves subdocuments middleware correctly', function (done) {
     var db = start();
 
     var child_hook;
@@ -575,7 +577,7 @@ describe('Model', function() {
       name: String
     });
 
-    childSchema.pre('save', function(next) {
+    childSchema.pre('save', function (next) {
       child_hook = this.name;
       next();
     });
@@ -585,7 +587,7 @@ describe('Model', function() {
       children: [childSchema]
     });
 
-    parentSchema.pre('save', function(next) {
+    parentSchema.pre('save', function (next) {
       parent_hook = this.name;
       next();
     });
@@ -599,22 +601,20 @@ describe('Model', function() {
       }]
     });
 
-    parent.save(function(err, parent) {
-      assert.equal(parent_hook, "Bob");
-      assert.equal(child_hook, "Mary");
+    parent.save(function (err, parent) {
+      assert.equal(parent_hook, 'Bob');
+      assert.equal(child_hook, 'Mary');
       assert.ifError(err);
       parent.children[0].name = 'Jane';
-      parent.save(function(err) {
-        assert.equal(child_hook, "Jane");
+      parent.save(function (err) {
+        assert.equal(child_hook, 'Jane');
         assert.ifError(err);
         done();
       });
-
     });
-
   });
 
-  it('instantiating a model with a hash that maps to at least 1 undefined value', function(done) {
+  it('instantiating a model with a hash that maps to at least 1 undefined value', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -622,9 +622,9 @@ describe('Model', function() {
       title: undefined
     });
     assert.strictEqual(undefined, post.title);
-    post.save( function(err) {
+    post.save(function (err) {
       assert.strictEqual(null, err);
-      BlogPost.findById(post.id, function(err, found) {
+      BlogPost.findById(post.id, function (err, found) {
         db.close();
         assert.strictEqual(err, null);
         assert.strictEqual(found.title, undefined);
@@ -633,7 +633,7 @@ describe('Model', function() {
     });
   });
 
-  it('modified nested objects which contain MongoseNumbers should not cause a RangeError on save (gh-714)', function(done) {
+  it('modified nested objects which contain MongoseNumbers should not cause a RangeError on save (gh-714)', function (done) {
     var db = start();
 
     var schema = new Schema({
@@ -645,13 +645,13 @@ describe('Model', function() {
     var M = db.model('NestedObjectWithMongooseNumber', schema);
     var m = new M;
     m.nested = null;
-    m.save(function(err) {
+    m.save(function (err) {
       assert.ifError(err);
 
-      M.findById(m, function(err, m) {
+      M.findById(m, function (err, m) {
         assert.ifError(err);
         m.nested.num = 5;
-        m.save(function(err) {
+        m.save(function (err) {
           db.close();
           assert.ifError(err);
           done();
@@ -660,11 +660,11 @@ describe('Model', function() {
     });
   });
 
-  it('no RangeError on remove() of a doc with Number _id (gh-714)', function(done) {
+  it('no RangeError on remove() of a doc with Number _id (gh-714)', function (done) {
     var db = start();
 
     var MySchema = new Schema({
-      _id: { type: Number },
+      _id: {type: Number},
       name: String
     });
 
@@ -674,13 +674,13 @@ describe('Model', function() {
       name: 'test',
       _id: 35
     });
-    instance.save(function(err) {
+    instance.save(function (err) {
       assert.ifError(err);
 
-      MyModel.findById(35, function(err, doc) {
+      MyModel.findById(35, function (err, doc) {
         assert.ifError(err);
 
-        doc.remove(function(err) {
+        doc.remove(function (err) {
           db.close();
           assert.ifError(err);
           done();
@@ -689,7 +689,7 @@ describe('Model', function() {
     });
   });
 
-  it('over-writing a number should persist to the db (gh-342)', function(done) {
+  it('over-writing a number should persist to the db (gh-342)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -700,12 +700,12 @@ describe('Model', function() {
       }
     });
 
-    post.save( function(err) {
+    post.save(function (err) {
       assert.ifError(err);
       post.set('meta.visitors', 20);
-      post.save( function(err) {
+      post.save(function (err) {
         assert.ifError(err);
-        BlogPost.findById(post.id, function(err, found) {
+        BlogPost.findById(post.id, function (err, found) {
           assert.ifError(err);
           assert.equal(20, found.get('meta.visitors').valueOf());
           db.close();
@@ -715,8 +715,8 @@ describe('Model', function() {
     });
   });
 
-  describe('methods', function() {
-    it('can be defined', function(done) {
+  describe('methods', function () {
+    it('can be defined', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -726,10 +726,10 @@ describe('Model', function() {
       done();
     });
 
-    it('can be defined on embedded documents', function(done) {
+    it('can be defined on embedded documents', function (done) {
       var db = start();
-      var ChildSchema = new Schema({ name: String });
-      ChildSchema.method('talk', function() {
+      var ChildSchema = new Schema({name: String});
+      ChildSchema.method('talk', function () {
         return 'gaga';
       });
 
@@ -750,11 +750,11 @@ describe('Model', function() {
       done();
     });
 
-    it('can be defined with nested key', function(done) {
+    it('can be defined with nested key', function (done) {
       var db = start();
       var NestedKeySchema = new Schema({});
       NestedKeySchema.method('foo', {
-        bar: function() {
+        bar: function () {
           return this;
         }
       });
@@ -765,8 +765,8 @@ describe('Model', function() {
     });
   });
 
-  describe('statics', function() {
-    it('can be defined', function(done) {
+  describe('statics', function () {
+    it('can be defined', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -776,14 +776,14 @@ describe('Model', function() {
     });
   });
 
-  describe('casting as validation errors', function() {
-    it('error', function(done) {
+  describe('casting as validation errors', function () {
+    it('error', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           threw = false;
 
       try {
-        var post = new BlogPost({ date: 'Test', meta: { date: 'Test' } });
+        var post = new BlogPost({date: 'Test', meta: {date: 'Test'}});
       } catch (e) {
         threw = true;
       }
@@ -798,20 +798,20 @@ describe('Model', function() {
 
       assert.equal(false, threw);
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         assert.equal(2, Object.keys(err.errors).length);
         post.date = new Date;
         post.meta.date = new Date;
-        post.save(function(err) {
+        post.save(function (err) {
           db.close();
           assert.ifError(err);
           done();
         });
       });
     });
-    it('nested error', function(done) {
+    it('nested error', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           threw = false;
@@ -838,7 +838,7 @@ describe('Model', function() {
 
       assert.equal(false, threw);
 
-      post.save(function(err) {
+      post.save(function (err) {
         db.close();
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
@@ -847,19 +847,19 @@ describe('Model', function() {
     });
 
 
-    it('subdocument cast error', function(done) {
+    it('subdocument cast error', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost({
         title: 'Test',
         slug: 'test',
-        comments: [ { title: 'Test', date: new Date, body: 'Test' } ]
+        comments: [{title: 'Test', date: new Date, body: 'Test'}]
       });
 
       post.get('comments')[0].set('date', 'invalid');
 
-      post.save(function(err) {
+      post.save(function (err) {
         db.close();
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
@@ -868,7 +868,7 @@ describe('Model', function() {
     });
 
 
-    it('subdocument validation error', function(done) {
+    it('subdocument validation error', function (done) {
       function failingvalidator() {
         return false;
       }
@@ -883,10 +883,10 @@ describe('Model', function() {
 
       var post = new BlogPost();
       post.init({
-        subs: [ { str: 'gaga' } ]
+        subs: [{str: 'gaga'}]
       });
 
-      post.save(function(err) {
+      post.save(function (err) {
         db.close();
         assert.ok(err instanceof ValidationError);
         done();
@@ -894,7 +894,7 @@ describe('Model', function() {
     });
 
 
-    it('subdocument error when adding a subdoc', function(done) {
+    it('subdocument error when adding a subdoc', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           threw = false;
@@ -911,7 +911,7 @@ describe('Model', function() {
 
       assert.equal(false, threw);
 
-      post.save(function(err) {
+      post.save(function (err) {
         db.close();
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
@@ -920,7 +920,7 @@ describe('Model', function() {
     });
 
 
-    it('updates', function(done) {
+    it('updates', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -929,13 +929,13 @@ describe('Model', function() {
 
       var id = post.get('_id');
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPost.update({ title: 1, _id: id }, { title: 2 }, function(err) {
+        BlogPost.update({title: 1, _id: id}, {title: 2}, function (err) {
           assert.ifError(err);
 
-          BlogPost.findOne({ _id: post.get('_id') }, function(err, doc) {
+          BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(doc.get('title'), '2');
@@ -945,7 +945,7 @@ describe('Model', function() {
       });
     });
 
-    it('$pull', function(done) {
+    it('$pull', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost();
@@ -956,21 +956,21 @@ describe('Model', function() {
       done();
     });
 
-    it('$push', function(done) {
+    it('$push', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost();
 
       post.get('numbers').push(1, 2, 3, 4);
-      post.save( function() {
-        BlogPost.findById( post.get('_id'), function(err, found) {
-          assert.equal(found.get('numbers').length,4);
+      post.save(function () {
+        BlogPost.findById(post.get('_id'), function (err, found) {
+          assert.equal(found.get('numbers').length, 4);
           found.get('numbers').pull('3');
-          found.save( function() {
-            BlogPost.findById(found.get('_id'), function(err, found2) {
+          found.save(function () {
+            BlogPost.findById(found.get('_id'), function (err, found2) {
               db.close();
               assert.ifError(err);
-              assert.equal(found2.get('numbers').length,3);
+              assert.equal(found2.get('numbers').length, 3);
               done();
             });
           });
@@ -978,17 +978,17 @@ describe('Model', function() {
       });
     });
 
-    it('Number arrays', function(done) {
+    it('Number arrays', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost();
       post.numbers.push(1, '2', 3);
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.strictEqual(err, null);
 
-        BlogPost.findById(post._id, function(err, doc) {
+        BlogPost.findById(post._id, function (err, doc) {
           assert.ifError(err);
 
           assert.ok(~doc.numbers.indexOf(1));
@@ -1001,10 +1001,10 @@ describe('Model', function() {
       });
     });
 
-    it('date casting compat with datejs (gh-502)', function(done) {
+    it('date casting compat with datejs (gh-502)', function (done) {
       var db = start();
 
-      Date.prototype.toObject = function() {
+      Date.prototype.toObject = function () {
         return {
           millisecond: 86,
           second: 42,
@@ -1027,20 +1027,20 @@ describe('Model', function() {
           curr: String,
           rateName: String
         },
-        created: { type: Date, default: Date.now },
-        valid: { type: Boolean, default: true }
+        created: {type: Date, default: Date.now},
+        valid: {type: Boolean, default: true}
       });
 
       var M = db.model('gh502', S);
 
       var m = new M;
-      m.save(function(err) {
+      m.save(function (err) {
         assert.ifError(err);
-        M.findById(m._id, function(err, m) {
+        M.findById(m._id, function (err, m) {
           assert.ifError(err);
-          m.save(function(err) {
+          m.save(function (err) {
             assert.ifError(err);
-            M.remove(function(err) {
+            M.remove(function (err) {
               db.close();
               delete Date.prototype.toObject;
               assert.ifError(err);
@@ -1052,8 +1052,8 @@ describe('Model', function() {
     });
   });
 
-  describe('validation', function() {
-    it('works', function(done) {
+  describe('validation', function () {
+    it('works', function (done) {
       function dovalidate() {
         assert.equal('correct', this.asyncScope);
         return true;
@@ -1061,15 +1061,15 @@ describe('Model', function() {
 
       function dovalidateAsync(val, callback) {
         assert.equal('correct', this.scope);
-        process.nextTick(function() {
+        process.nextTick(function () {
           callback(true);
         });
       }
 
       mongoose.model('TestValidation', new Schema({
-        simple: { type: String, required: true },
-        scope: { type: String, validate: [dovalidate, 'scope failed'], required: true },
-        asyncScope: { type: String, validate: [dovalidateAsync, 'async scope failed'], required: true }
+        simple: {type: String, required: true},
+        scope: {type: String, validate: [dovalidate, 'scope failed'], required: true},
+        asyncScope: {type: String, validate: [dovalidateAsync, 'async scope failed'], required: true}
       }));
 
       var db = start(),
@@ -1080,12 +1080,12 @@ describe('Model', function() {
       post.set('scope', 'correct');
       post.set('asyncScope', 'correct');
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
 
         post.set('simple', 'here');
-        post.save(function(err) {
+        post.save(function (err) {
           db.close();
           assert.ifError(err);
           done();
@@ -1093,12 +1093,13 @@ describe('Model', function() {
       });
     });
 
-    it('custom messaging', function(done) {
+    it('custom messaging', function (done) {
       function validate(val) {
         return val === 'abc';
       }
+
       mongoose.model('TestValidationMessage', new Schema({
-        simple: { type: String, validate: [validate, 'must be abc'] }
+        simple: {type: String, validate: [validate, 'must be abc']}
       }));
 
       var db = start(),
@@ -1107,15 +1108,15 @@ describe('Model', function() {
       var post = new TestValidationMessage();
       post.set('simple', '');
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         assert.ok(err.errors.simple instanceof ValidatorError);
-        assert.equal(err.errors.simple.message,'must be abc');
-        assert.equal(post.errors.simple.message,'must be abc');
+        assert.equal(err.errors.simple.message, 'must be abc');
+        assert.equal(post.errors.simple.message, 'must be abc');
 
         post.set('simple', 'abc');
-        post.save(function(err) {
+        post.save(function (err) {
           db.close();
           assert.ifError(err);
           done();
@@ -1123,28 +1124,28 @@ describe('Model', function() {
       });
     });
 
-    it('with Model.schema.path introspection (gh-272)', function(done) {
+    it('with Model.schema.path introspection (gh-272)', function (done) {
       var db = start();
       var IntrospectionValidationSchema = new Schema({
         name: String
       });
       var IntrospectionValidation = db.model('IntrospectionValidation', IntrospectionValidationSchema, 'introspections_' + random());
-      IntrospectionValidation.schema.path('name').validate(function(value) {
+      IntrospectionValidation.schema.path('name').validate(function (value) {
         return value.length < 2;
       }, 'Name cannot be greater than 1 character for path "{PATH}" with value `{VALUE}`');
       var doc = new IntrospectionValidation({name: 'hi'});
-      doc.save( function(err) {
+      doc.save(function (err) {
         db.close();
         assert.equal(err.errors.name.message, 'Name cannot be greater than 1 character for path "name" with value `hi`');
-        assert.equal(err.name,"ValidationError");
-        assert.equal(err.message,"IntrospectionValidation validation failed");
+        assert.equal(err.name, 'ValidationError');
+        assert.equal(err.message, 'IntrospectionValidation validation failed');
         done();
       });
     });
 
-    it('of required undefined values', function(done) {
+    it('of required undefined values', function (done) {
       mongoose.model('TestUndefinedValidation', new Schema({
-        simple: { type: String, required: true }
+        simple: {type: String, required: true}
       }));
 
       var db = start(),
@@ -1152,12 +1153,12 @@ describe('Model', function() {
 
       var post = new TestUndefinedValidation;
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
 
         post.set('simple', 'here');
-        post.save(function(err) {
+        post.save(function (err) {
           db.close();
           assert.ifError(err);
           done();
@@ -1165,24 +1166,24 @@ describe('Model', function() {
       });
     });
 
-    it('save callback should only execute once (gh-319)', function(done) {
+    it('save callback should only execute once (gh-319)', function (done) {
       var db = start();
 
       var D = db.model('CallbackFiresOnceValidation', new Schema({
-        username: { type: String, validate: /^[a-z]{6}$/i },
-        email: { type: String, validate: /^[a-z]{6}$/i },
-        password: { type: String, validate: /^[a-z]{6}$/i }
+        username: {type: String, validate: /^[a-z]{6}$/i},
+        email: {type: String, validate: /^[a-z]{6}$/i},
+        password: {type: String, validate: /^[a-z]{6}$/i}
       }));
 
       var post = new D({
-        username: "nope",
-        email: "too",
-        password: "short"
+        username: 'nope',
+        email: 'too',
+        password: 'short'
       });
 
       var timesCalled = 0;
 
-      post.save(function(err) {
+      post.save(function (err) {
         db.close();
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
@@ -1193,24 +1194,24 @@ describe('Model', function() {
         assert.ok(err.errors.password instanceof ValidatorError);
         assert.ok(err.errors.email instanceof ValidatorError);
         assert.ok(err.errors.username instanceof ValidatorError);
-        assert.equal(err.errors.password.message,'Validator failed for path `password` with value `short`');
-        assert.equal(err.errors.email.message,'Validator failed for path `email` with value `too`');
-        assert.equal(err.errors.username.message,'Validator failed for path `username` with value `nope`');
+        assert.equal(err.errors.password.message, 'Validator failed for path `password` with value `short`');
+        assert.equal(err.errors.email.message, 'Validator failed for path `email` with value `too`');
+        assert.equal(err.errors.username.message, 'Validator failed for path `username` with value `nope`');
 
         assert.equal(Object.keys(post.errors).length, 3);
         assert.ok(post.errors.password instanceof ValidatorError);
         assert.ok(post.errors.email instanceof ValidatorError);
         assert.ok(post.errors.username instanceof ValidatorError);
-        assert.equal(post.errors.password.message,'Validator failed for path `password` with value `short`');
-        assert.equal(post.errors.email.message,'Validator failed for path `email` with value `too`');
-        assert.equal(post.errors.username.message,'Validator failed for path `username` with value `nope`');
+        assert.equal(post.errors.password.message, 'Validator failed for path `password` with value `short`');
+        assert.equal(post.errors.email.message, 'Validator failed for path `email` with value `too`');
+        assert.equal(post.errors.username.message, 'Validator failed for path `username` with value `nope`');
         done();
       });
     });
 
-    it('query result', function(done) {
+    it('query result', function (done) {
       mongoose.model('TestValidationOnResult', new Schema({
-        resultv: { type: String, required: true }
+        resultv: {type: String, required: true}
       }));
 
       var db = start(),
@@ -1218,17 +1219,17 @@ describe('Model', function() {
 
       var post = new TestV;
 
-      post.validate(function(err) {
+      post.validate(function (err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
 
         post.resultv = 'yeah';
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ifError(err);
-          TestV.findOne({ _id: post.id }, function(err, found) {
+          TestV.findOne({_id: post.id}, function (err, found) {
             assert.ifError(err);
-            assert.equal(found.resultv,'yeah');
-            found.save(function(err) {
+            assert.equal(found.resultv, 'yeah');
+            found.save(function (err) {
               db.close();
               assert.ifError(err);
               done();
@@ -1238,28 +1239,28 @@ describe('Model', function() {
       });
     });
 
-    it('of required previously existing null values', function(done) {
+    it('of required previously existing null values', function (done) {
       mongoose.model('TestPreviousNullValidation', new Schema({
-        previous: { type: String, required: true },
+        previous: {type: String, required: true},
         a: String
       }));
 
       var db = start(),
           TestP = db.model('TestPreviousNullValidation');
 
-      TestP.collection.insert({ a: null, previous: null}, {}, function(err, f) {
+      TestP.collection.insert({a: null, previous: null}, {}, function (err, f) {
         assert.ifError(err);
-        TestP.findOne({_id: f.ops[0]._id}, function(err, found) {
+        TestP.findOne({_id: f.ops[0]._id}, function (err, found) {
           assert.ifError(err);
           assert.equal(false, found.isNew);
           assert.strictEqual(found.get('previous'), null);
 
-          found.validate(function(err) {
+          found.validate(function (err) {
             assert.ok(err instanceof MongooseError);
             assert.ok(err instanceof ValidationError);
 
             found.set('previous', 'yoyo');
-            found.save(function(err) {
+            found.save(function (err) {
               assert.strictEqual(err, null);
               db.close();
               done();
@@ -1269,10 +1270,10 @@ describe('Model', function() {
       });
     });
 
-    it('nested', function(done) {
+    it('nested', function (done) {
       mongoose.model('TestNestedValidation', new Schema({
         nested: {
-          required: { type: String, required: true }
+          required: {type: String, required: true}
         }
       }));
 
@@ -1282,12 +1283,12 @@ describe('Model', function() {
       var post = new TestNestedValidation();
       post.set('nested.required', null);
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
 
         post.set('nested.required', 'here');
-        post.save(function(err) {
+        post.save(function (err) {
           db.close();
           assert.ifError(err);
           done();
@@ -1295,11 +1296,11 @@ describe('Model', function() {
       });
     });
 
-    it('of nested subdocuments', function(done) {
-      var Subsubdocs = new Schema({ required: { type: String, required: true }});
+    it('of nested subdocuments', function (done) {
+      var Subsubdocs = new Schema({required: {type: String, required: true}});
 
       var Subdocs = new Schema({
-        required: { type: String, required: true },
+        required: {type: String, required: true},
         subs: [Subsubdocs]
       });
 
@@ -1312,15 +1313,15 @@ describe('Model', function() {
 
       var post = new TestSubdocumentsValidation();
 
-      post.get('items').push({ required: '', subs: [{required: ''}] });
+      post.get('items').push({required: '', subs: [{required: ''}]});
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         assert.ok(err.errors['items.0.subs.0.required'] instanceof ValidatorError);
-        assert.equal(err.errors['items.0.subs.0.required'].message,'Path `required` is required.');
+        assert.equal(err.errors['items.0.subs.0.required'].message, 'Path `required` is required.');
         assert.ok(post.errors['items.0.subs.0.required'] instanceof ValidatorError);
-        assert.equal(post.errors['items.0.subs.0.required'].message,'Path `required` is required.');
+        assert.equal(post.errors['items.0.subs.0.required'].message, 'Path `required` is required.');
 
         assert.ok(err.errors['items.0.required']);
         assert.ok(post.errors['items.0.required']);
@@ -1328,11 +1329,11 @@ describe('Model', function() {
         post.items[0].subs[0].set('required', true);
         assert.equal(undefined, post.$__.validationError);
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ok(err);
           assert.ok(err.errors);
           assert.ok(err.errors['items.0.required'] instanceof ValidatorError);
-          assert.equal(err.errors['items.0.required'].message,'Path `required` is required.');
+          assert.equal(err.errors['items.0.required'].message, 'Path `required` is required.');
 
           assert.ok(!err.errors['items.0.subs.0.required']);
           assert.ok(!err.errors['items.0.subs.0.required']);
@@ -1340,7 +1341,7 @@ describe('Model', function() {
           assert.ok(!post.errors['items.0.subs.0.required']);
 
           post.get('items')[0].set('required', true);
-          post.save(function(err) {
+          post.save(function (err) {
             db.close();
             assert.ok(!post.errors);
             assert.ifError(err);
@@ -1350,18 +1351,19 @@ describe('Model', function() {
       });
     });
 
-    describe('async', function() {
-      it('works', function(done) {
+    describe('async', function () {
+      it('works', function (done) {
         var executed = false;
 
         function validator(v, fn) {
-          setTimeout(function() {
+          setTimeout(function () {
             executed = true;
             fn(v !== 'test');
           }, 5);
         }
+
         mongoose.model('TestAsyncValidation', new Schema({
-          async: { type: String, validate: [validator, 'async validator failed for `{PATH}`'] }
+          async: {type: String, validate: [validator, 'async validator failed for `{PATH}`']}
         }));
 
         var db = start(),
@@ -1370,16 +1372,16 @@ describe('Model', function() {
         var post = new TestAsyncValidation();
         post.set('async', 'test');
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.ok(err.errors.async instanceof ValidatorError);
-          assert.equal(err.errors.async.message,'async validator failed for `async`');
+          assert.equal(err.errors.async.message, 'async validator failed for `async`');
           assert.equal(true, executed);
           executed = false;
 
           post.set('async', 'woot');
-          post.save(function(err) {
+          post.save(function (err) {
             db.close();
             assert.equal(true, executed);
             assert.strictEqual(err, null);
@@ -1388,11 +1390,11 @@ describe('Model', function() {
         });
       });
 
-      it('nested', function(done) {
+      it('nested', function (done) {
         var executed = false;
 
         function validator(v, fn) {
-          setTimeout(function() {
+          setTimeout(function () {
             executed = true;
             fn(v !== 'test');
           }, 5);
@@ -1400,7 +1402,7 @@ describe('Model', function() {
 
         mongoose.model('TestNestedAsyncValidation', new Schema({
           nested: {
-            async: { type: String, validate: [validator, 'async validator'] }
+            async: {type: String, validate: [validator, 'async validator']}
           }
         }));
 
@@ -1410,25 +1412,25 @@ describe('Model', function() {
         var post = new TestNestedAsyncValidation();
         post.set('nested.async', 'test');
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.ok(executed);
           executed = false;
 
-          post.validate(function(err) {
+          post.validate(function (err) {
             assert.ok(err instanceof MongooseError);
             assert.ok(err instanceof ValidationError);
             assert.ok(executed);
             executed = false;
 
             post.set('nested.async', 'woot');
-            post.validate(function(err) {
+            post.validate(function (err) {
               assert.ok(executed);
               assert.equal(err, null);
               executed = false;
 
-              post.save(function(err) {
+              post.save(function (err) {
                 db.close();
                 assert.ok(executed);
                 assert.strictEqual(err, null);
@@ -1439,18 +1441,18 @@ describe('Model', function() {
         });
       });
 
-      it('subdocuments', function(done) {
+      it('subdocuments', function (done) {
         var executed = false;
 
         function validator(v, fn) {
-          setTimeout(function() {
+          setTimeout(function () {
             executed = true;
             fn(v !== '');
           }, 5);
         }
 
         var Subdocs = new Schema({
-          required: { type: String, validate: [validator, 'async in subdocs'] }
+          required: {type: String, validate: [validator, 'async in subdocs']}
         });
 
         mongoose.model('TestSubdocumentsAsyncValidation', new Schema({
@@ -1462,16 +1464,16 @@ describe('Model', function() {
 
         var post = new Test();
 
-        post.get('items').push({ required: '' });
+        post.get('items').push({required: ''});
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.ok(executed);
           executed = false;
 
-          post.get('items')[0].set({ required: 'here' });
-          post.save(function(err) {
+          post.get('items')[0].set({required: 'here'});
+          post.save(function (err) {
             db.close();
             assert.ok(executed);
             assert.strictEqual(err, null);
@@ -1479,12 +1481,11 @@ describe('Model', function() {
           });
         });
       });
-
     });
 
-    it('without saving', function(done) {
+    it('without saving', function (done) {
       mongoose.model('TestCallingValidation', new Schema({
-        item: { type: String, required: true }
+        item: {type: String, required: true}
       }));
 
       var db = start(),
@@ -1495,13 +1496,13 @@ describe('Model', function() {
       assert.equal(true, post.schema.path('item').isRequired);
       assert.strictEqual(post.isNew, true);
 
-      post.validate(function(err) {
+      post.validate(function (err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         assert.strictEqual(post.isNew, true);
 
         post.item = 'yo';
-        post.validate(function(err) {
+        post.validate(function (err) {
           db.close();
           assert.equal(err, null);
           assert.strictEqual(post.isNew, true);
@@ -1510,13 +1511,13 @@ describe('Model', function() {
       });
     });
 
-    it('when required is set to false', function(done) {
+    it('when required is set to false', function (done) {
       function validator() {
         return true;
       }
 
       mongoose.model('TestRequiredFalse', new Schema({
-        result: { type: String, validate: [validator, 'chump validator'], required: false }
+        result: {type: String, validate: [validator, 'chump validator'], required: false}
       }));
 
       var db = start(),
@@ -1529,18 +1530,18 @@ describe('Model', function() {
       done();
     });
 
-    describe('middleware', function() {
-      it('works', function(done) {
+    describe('middleware', function () {
+      it('works', function (done) {
         var db = start(),
             ValidationMiddlewareSchema = null,
             Post = null,
             post = null;
 
         ValidationMiddlewareSchema = new Schema({
-          baz: { type: String }
+          baz: {type: String}
         });
 
-        ValidationMiddlewareSchema.pre('validate', function(next) {
+        ValidationMiddlewareSchema.pre('validate', function (next) {
           if (this.get('baz') == 'bad') {
             this.invalidate('baz', 'bad');
           }
@@ -1553,14 +1554,14 @@ describe('Model', function() {
         post = new Post();
         post.set({baz: 'bad'});
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
-          assert.equal(err.errors.baz.kind,'user defined');
-          assert.equal(err.errors.baz.path,'baz');
+          assert.equal(err.errors.baz.kind, 'user defined');
+          assert.equal(err.errors.baz.path, 'baz');
 
           post.set('baz', 'good');
-          post.save(function(err) {
+          post.save(function (err) {
             assert.ifError(err);
             db.close();
             done();
@@ -1568,19 +1569,19 @@ describe('Model', function() {
         });
       });
 
-      it('async', function(done) {
+      it('async', function (done) {
         var db = start(),
             AsyncValidationMiddlewareSchema = null,
             Post = null,
             post = null;
 
         AsyncValidationMiddlewareSchema = new Schema({
-          prop: { type: String }
+          prop: {type: String}
         });
 
-        AsyncValidationMiddlewareSchema.pre('validate', true, function(next, done) {
+        AsyncValidationMiddlewareSchema.pre('validate', true, function (next, done) {
           var self = this;
-          setTimeout(function() {
+          setTimeout(function () {
             if (self.get('prop') == 'bad') {
               self.invalidate('prop', 'bad');
             }
@@ -1595,14 +1596,14 @@ describe('Model', function() {
         post = new Post();
         post.set({prop: 'bad'});
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
-          assert.equal(err.errors.prop.kind,'user defined');
-          assert.equal(err.errors.prop.path,'prop');
+          assert.equal(err.errors.prop.kind, 'user defined');
+          assert.equal(err.errors.prop.path, 'prop');
 
           post.set('prop', 'good');
-          post.save(function(err) {
+          post.save(function (err) {
             assert.ifError(err);
             db.close();
             done();
@@ -1610,25 +1611,25 @@ describe('Model', function() {
         });
       });
 
-      it('complex', function(done) {
+      it('complex', function (done) {
         var db = start(),
             ComplexValidationMiddlewareSchema = null,
             Post = null,
             post = null,
-            abc = function(v) {
+            abc = function (v) {
               return v === 'abc';
             };
 
         ComplexValidationMiddlewareSchema = new Schema({
-          baz: { type: String },
-          abc: { type: String, validate: [abc, 'must be abc'] },
-          test: { type: String, validate: [/test/, 'must also be abc'] },
-          required: { type: String, required: true }
+          baz: {type: String},
+          abc: {type: String, validate: [abc, 'must be abc']},
+          test: {type: String, validate: [/test/, 'must also be abc']},
+          required: {type: String, required: true}
         });
 
-        ComplexValidationMiddlewareSchema.pre('validate', true, function(next, done) {
+        ComplexValidationMiddlewareSchema.pre('validate', true, function (next, done) {
           var self = this;
-          setTimeout(function() {
+          setTimeout(function () {
             if (self.get('baz') == 'bad') {
               self.invalidate('baz', 'bad');
             }
@@ -1647,24 +1648,24 @@ describe('Model', function() {
           test: 'fail'
         });
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.equal(4, Object.keys(err.errors).length);
           assert.ok(err.errors.baz instanceof ValidatorError);
-          assert.equal(err.errors.baz.kind,'user defined');
-          assert.equal(err.errors.baz.path,'baz');
+          assert.equal(err.errors.baz.kind, 'user defined');
+          assert.equal(err.errors.baz.path, 'baz');
           assert.ok(err.errors.abc instanceof ValidatorError);
-          assert.equal(err.errors.abc.kind,'user defined');
-          assert.equal(err.errors.abc.message,'must be abc');
-          assert.equal(err.errors.abc.path,'abc');
+          assert.equal(err.errors.abc.kind, 'user defined');
+          assert.equal(err.errors.abc.message, 'must be abc');
+          assert.equal(err.errors.abc.path, 'abc');
           assert.ok(err.errors.test instanceof ValidatorError);
-          assert.equal(err.errors.test.message,'must also be abc');
-          assert.equal(err.errors.test.kind,'user defined');
-          assert.equal(err.errors.test.path,'test');
+          assert.equal(err.errors.test.message, 'must also be abc');
+          assert.equal(err.errors.test.kind, 'user defined');
+          assert.equal(err.errors.test.path, 'test');
           assert.ok(err.errors.required instanceof ValidatorError);
-          assert.equal(err.errors.required.kind,'required');
-          assert.equal(err.errors.required.path,'required');
+          assert.equal(err.errors.required.kind, 'required');
+          assert.equal(err.errors.required.path, 'required');
 
           post.set({
             baz: 'good',
@@ -1673,7 +1674,7 @@ describe('Model', function() {
             required: 'here'
           });
 
-          post.save(function(err) {
+          post.save(function (err) {
             assert.ifError(err);
             db.close();
             done();
@@ -1683,12 +1684,12 @@ describe('Model', function() {
     });
   });
 
-  describe('defaults application', function() {
-    it('works', function(done) {
+  describe('defaults application', function () {
+    it('works', function (done) {
       var now = Date.now();
 
       mongoose.model('TestDefaults', new Schema({
-        date: { type: Date, default: now }
+        date: {type: Date, default: now}
       }));
 
       var db = start(),
@@ -1701,12 +1702,12 @@ describe('Model', function() {
       done();
     });
 
-    it('nested', function(done) {
+    it('nested', function (done) {
       var now = Date.now();
 
       mongoose.model('TestNestedDefaults', new Schema({
         nested: {
-          date: { type: Date, default: now }
+          date: {type: Date, default: now}
         }
       }));
 
@@ -1720,11 +1721,11 @@ describe('Model', function() {
       done();
     });
 
-    it('subdocument', function(done) {
+    it('subdocument', function (done) {
       var now = Date.now();
 
       var Items = new Schema({
-        date: { type: Date, default: now }
+        date: {type: Date, default: now}
       });
 
       mongoose.model('TestSubdocumentsDefaults', new Schema({
@@ -1742,17 +1743,17 @@ describe('Model', function() {
       done();
     });
 
-    it('allows nulls', function(done) {
+    it('allows nulls', function (done) {
       var db = start();
-      var T = db.model('NullDefault', new Schema({ name: { type: String, default: null }}), collection);
+      var T = db.model('NullDefault', new Schema({name: {type: String, default: null}}), collection);
       var t = new T();
 
       assert.strictEqual(null, t.name);
 
-      t.save(function(err) {
+      t.save(function (err) {
         assert.ifError(err);
 
-        T.findById(t._id, function(err, t) {
+        T.findById(t._id, function (err, t) {
           db.close();
           assert.ifError(err);
           assert.strictEqual(null, t.name);
@@ -1761,16 +1762,16 @@ describe('Model', function() {
       });
     });
 
-    it('do not cause the document to stay dirty after save', function(done) {
+    it('do not cause the document to stay dirty after save', function (done) {
       var db = start(),
-          Model = db.model('SavingDefault', new Schema({ name: { type: String, default: 'saving' }}), collection),
+          Model = db.model('SavingDefault', new Schema({name: {type: String, default: 'saving'}}), collection),
           doc = new Model();
 
-      doc.save(function(err, doc, numberAffected) {
+      doc.save(function (err, doc, numberAffected) {
         assert.ifError(err);
         assert.strictEqual(1, numberAffected);
 
-        doc.save(function(err, doc, numberAffected) {
+        doc.save(function (err, doc, numberAffected) {
           db.close();
           assert.ifError(err);
           // should not have saved a second time
@@ -1781,8 +1782,8 @@ describe('Model', function() {
     });
   });
 
-  describe('virtuals', function() {
-    it('getters', function(done) {
+  describe('virtuals', function () {
+    it('getters', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost({
@@ -1792,37 +1793,37 @@ describe('Model', function() {
 
       db.close();
       assert.equal(post.get('titleWithAuthor'), 'Letters from Earth by Mark Twain');
-      assert.equal(post.titleWithAuthor,'Letters from Earth by Mark Twain');
+      assert.equal(post.titleWithAuthor, 'Letters from Earth by Mark Twain');
       done();
     });
 
-    it('set()', function(done) {
+    it('set()', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost();
 
       db.close();
       post.set('titleWithAuthor', 'Huckleberry Finn by Mark Twain');
-      assert.equal(post.get('title'),'Huckleberry Finn');
-      assert.equal(post.get('author'),'Mark Twain');
+      assert.equal(post.get('title'), 'Huckleberry Finn');
+      assert.equal(post.get('author'), 'Mark Twain');
       done();
     });
 
-    it('should not be saved to the db', function(done) {
+    it('should not be saved to the db', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost();
 
       post.set('titleWithAuthor', 'Huckleberry Finn by Mark Twain');
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPost.findById(post.get('_id'), function(err, found) {
+        BlogPost.findById(post.get('_id'), function (err, found) {
           assert.ifError(err);
 
-          assert.equal(found.get('title'),'Huckleberry Finn');
-          assert.equal(found.get('author'),'Mark Twain');
+          assert.equal(found.get('title'), 'Huckleberry Finn');
+          assert.equal(found.get('author'), 'Mark Twain');
           assert.ok(!('titleWithAuthor' in found.toObject()));
           db.close();
           done();
@@ -1830,7 +1831,7 @@ describe('Model', function() {
       });
     });
 
-    it('nested', function(done) {
+    it('nested', function (done) {
       var db = start(),
           PersonSchema = new Schema({
             name: {
@@ -1841,10 +1842,10 @@ describe('Model', function() {
 
       PersonSchema
       .virtual('name.full')
-      .get(function() {
+      .get(function () {
         return this.get('name.first') + ' ' + this.get('name.last');
       })
-      .set(function(fullName) {
+      .set(function (fullName) {
         var split = fullName.split(' ');
         this.set('name.first', split[0]);
         this.set('name.last', split[1]);
@@ -1862,32 +1863,32 @@ describe('Model', function() {
 
       db.close();
 
-      assert.equal(person.get('name.full'),'Michael Sorrentino');
+      assert.equal(person.get('name.full'), 'Michael Sorrentino');
       person.set('name.full', 'The Situation');
-      assert.equal(person.get('name.first'),'The');
-      assert.equal(person.get('name.last'),'Situation');
+      assert.equal(person.get('name.first'), 'The');
+      assert.equal(person.get('name.last'), 'Situation');
 
-      assert.equal(person.name.full,'The Situation');
+      assert.equal(person.name.full, 'The Situation');
       person.name.full = 'Michael Sorrentino';
-      assert.equal(person.name.first,'Michael');
-      assert.equal(person.name.last,'Sorrentino');
+      assert.equal(person.name.first, 'Michael');
+      assert.equal(person.name.last, 'Sorrentino');
       done();
     });
   });
 
-  describe('.remove()', function() {
-    it('works', function(done) {
+  describe('.remove()', function () {
+    it('works', function (done) {
       var db = start(),
           collection = 'blogposts_' + random(),
           BlogPost = db.model('BlogPost', collection);
 
-      BlogPost.create({ title: 1 }, { title: 2 }, function(err) {
+      BlogPost.create({title: 1}, {title: 2}, function (err) {
         assert.ifError(err);
 
-        BlogPost.remove({ title: 1 }, function(err) {
+        BlogPost.remove({title: 1}, function (err) {
           assert.ifError(err);
 
-          BlogPost.find({}, function(err, found) {
+          BlogPost.find({}, function (err, found) {
             db.close();
             assert.ifError(err);
             assert.equal(1, found.length);
@@ -1898,16 +1899,16 @@ describe('Model', function() {
       });
     });
 
-    it('errors when id deselected (gh-3118)', function(done) {
+    it('errors when id deselected (gh-3118)', function (done) {
       var db = start(),
           collection = 'blogposts_' + random(),
           BlogPost = db.model('BlogPost', collection);
 
-      BlogPost.create({ title: 1 }, { title: 2 }, function(err) {
+      BlogPost.create({title: 1}, {title: 2}, function (err) {
         assert.ifError(err);
-        BlogPost.findOne({ title: 1 }, { _id: 0 }, function(error, doc) {
+        BlogPost.findOne({title: 1}, {_id: 0}, function (error, doc) {
           assert.ifError(error);
-          doc.remove(function(err) {
+          doc.remove(function (err) {
             assert.ok(err);
             assert.equal(err.toString(), 'Error: No _id found on document!');
             db.close(done);
@@ -1916,16 +1917,16 @@ describe('Model', function() {
       });
     });
 
-    it('should not remove any records when deleting by id undefined', function(done) {
+    it('should not remove any records when deleting by id undefined', function (done) {
       var db = start();
       var collection = 'blogposts_' + random();
       var BlogPost = db.model('BlogPost', collection);
-      BlogPost.create({ title: 1 }, { title: 2 }, function(err) {
+      BlogPost.create({title: 1}, {title: 2}, function (err) {
         assert.ifError(err);
 
-        BlogPost.remove({ _id: undefined }, function(err) {
+        BlogPost.remove({_id: undefined}, function (err) {
           assert.ifError(err);
-          BlogPost.find({}, function(err, found) {
+          BlogPost.find({}, function (err, found) {
             assert.equal(found.length, 2, 'Should not remove any records');
             done();
           });
@@ -1933,18 +1934,18 @@ describe('Model', function() {
       });
     });
 
-    it('should not remove all documents in the collection (gh-3326)', function(done) {
+    it('should not remove all documents in the collection (gh-3326)', function (done) {
       var db = start(),
           collection = 'blogposts_' + random(),
           BlogPost = db.model('BlogPost', collection);
 
-      BlogPost.create({ title: 1 }, { title: 2 }, function(err) {
+      BlogPost.create({title: 1}, {title: 2}, function (err) {
         assert.ifError(err);
-        BlogPost.findOne({ title: 1 }, function(error, doc) {
+        BlogPost.findOne({title: 1}, function (error, doc) {
           assert.ifError(error);
-          doc.remove(function(err) {
+          doc.remove(function (err) {
             assert.ifError(err);
-            BlogPost.find(function(err, found) {
+            BlogPost.find(function (err, found) {
               db.close();
               assert.ifError(err);
               assert.equal(1, found.length);
@@ -1957,25 +1958,25 @@ describe('Model', function() {
     });
   });
 
-  describe('#remove()', function() {
+  describe('#remove()', function () {
     var db, B;
 
-    before(function() {
+    before(function () {
       db = start();
       B = db.model('BlogPost', 'blogposts_' + random());
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('passes the removed document (gh-1419)', function(done) {
-      B.create({}, function(err, post) {
+    it('passes the removed document (gh-1419)', function (done) {
+      B.create({}, function (err, post) {
         assert.ifError(err);
-        B.findById(post, function(err, found) {
+        B.findById(post, function (err, found) {
           assert.ifError(err);
 
-          found.remove(function(err, doc) {
+          found.remove(function (err, doc) {
             assert.ifError(err);
             assert.ok(doc);
             assert.ok(doc.equals(found));
@@ -1985,13 +1986,13 @@ describe('Model', function() {
       });
     });
 
-    it('works as a promise', function(done) {
-      B.create({}, function(err, post) {
+    it('works as a promise', function (done) {
+      B.create({}, function (err, post) {
         assert.ifError(err);
-        B.findById(post, function(err, found) {
+        B.findById(post, function (err, found) {
           assert.ifError(err);
 
-          found.remove().onResolve(function(err, doc) {
+          found.remove().onResolve(function (err, doc) {
             assert.ifError(err);
             assert.ok(doc);
             assert.ok(doc.equals(found));
@@ -2001,26 +2002,26 @@ describe('Model', function() {
       });
     });
 
-    it('works as a promise with a hook', function(done) {
+    it('works as a promise with a hook', function (done) {
       var called = 0;
       var RHS = new Schema({
         name: String
       });
-      RHS.pre('remove', function(next) {
+      RHS.pre('remove', function (next) {
         called++;
         return next();
       });
 
       var RH = db.model('RH', RHS, 'RH_' + random());
 
-      RH.create({name: 'to be removed'}, function(err, post) {
+      RH.create({name: 'to be removed'}, function (err, post) {
         assert.ifError(err);
         assert.ok(post);
-        RH.findById(post, function(err, found) {
+        RH.findById(post, function (err, found) {
           assert.ifError(err);
           assert.ok(found);
 
-          found.remove().onResolve(function(err, doc) {
+          found.remove().onResolve(function (err, doc) {
             assert.ifError(err);
             assert.equal(called, 1);
             assert.ok(doc);
@@ -2031,13 +2032,13 @@ describe('Model', function() {
       });
     });
 
-    it('passes the removed document (gh-1419)', function(done) {
-      B.create({}, function(err, post) {
+    it('passes the removed document (gh-1419)', function (done) {
+      B.create({}, function (err, post) {
         assert.ifError(err);
-        B.findById(post, function(err, found) {
+        B.findById(post, function (err, found) {
           assert.ifError(err);
 
-          found.remove(function(err, doc) {
+          found.remove(function (err, doc) {
             assert.ifError(err);
             assert.ok(doc);
             assert.ok(doc.equals(found));
@@ -2047,24 +2048,28 @@ describe('Model', function() {
       });
     });
 
-    describe('when called multiple times', function() {
-      it('always executes the passed callback gh-1210', function(done) {
+    describe('when called multiple times', function () {
+      it('always executes the passed callback gh-1210', function (done) {
         var db = start(),
             collection = 'blogposts_' + random(),
             BlogPost = db.model('BlogPost', collection),
             post = new BlogPost();
 
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ifError(err);
 
           var pending = 2;
 
-          post.remove(function() {
-            if (--pending) return;
+          post.remove(function () {
+            if (--pending) {
+              return;
+            }
             done();
           });
-          post.remove(function() {
-            if (--pending) return;
+          post.remove(function () {
+            if (--pending) {
+              return;
+            }
             done();
           });
         });
@@ -2072,12 +2077,12 @@ describe('Model', function() {
     });
   });
 
-  describe('getters', function() {
-    it('with same name on embedded docs do not class', function(done) {
+  describe('getters', function () {
+    it('with same name on embedded docs do not class', function (done) {
       var Post = new Schema({
         title: String,
-        author: { name: String },
-        subject: { name: String }
+        author: {name: String},
+        subject: {name: String}
       });
 
       mongoose.model('PostWithClashGetters', Post);
@@ -2087,18 +2092,18 @@ describe('Model', function() {
 
       var post = new PostModel({
         title: 'Test',
-        author: { name: 'A' },
-        subject: { name: 'B' }
+        author: {name: 'A'},
+        subject: {name: 'B'}
       });
 
       db.close();
-      assert.equal(post.author.name,'A');
-      assert.equal(post.subject.name,'B');
-      assert.equal(post.author.name,'A');
+      assert.equal(post.author.name, 'A');
+      assert.equal(post.subject.name, 'B');
+      assert.equal(post.author.name, 'A');
       done();
     });
 
-    it('should not be triggered at construction (gh-685)', function(done) {
+    it('should not be triggered at construction (gh-685)', function (done) {
       var db = start(),
           called = false;
 
@@ -2106,9 +2111,11 @@ describe('Model', function() {
 
       var schema = new mongoose.Schema({
         number: {
-          type:Number,
-          set: function(x) { return x / 2;},
-          get: function(x) {
+          type: Number,
+          set: function (x) {
+            return x / 2;
+          },
+          get: function (x) {
             called = true;
             return x * 2;
           }
@@ -2117,7 +2124,7 @@ describe('Model', function() {
 
       var A = mongoose.model('gettersShouldNotBeTriggeredAtConstruction', schema);
 
-      var a = new A({ number: 100 });
+      var a = new A({number: 100});
       assert.equal(false, called);
       var num = a.number;
       assert.equal(true, called);
@@ -2126,7 +2133,7 @@ describe('Model', function() {
 
       called = false;
       var b = new A;
-      b.init({ number: 50 });
+      b.init({number: 50});
       assert.equal(false, called);
       num = b.number;
       assert.equal(true, called);
@@ -2135,9 +2142,9 @@ describe('Model', function() {
       done();
     });
 
-    it('with type defined with { type: Native } (gh-190)', function(done) {
+    it('with type defined with { type: Native } (gh-190)', function (done) {
       var schema = new Schema({
-        date: { type: Date }
+        date: {type: Date}
       });
 
       mongoose.model('ShortcutGetterObject', schema);
@@ -2152,8 +2159,8 @@ describe('Model', function() {
       done();
     });
 
-    describe('nested', function() {
-      it('works', function(done) {
+    describe('nested', function () {
+      it('works', function (done) {
         var schema = new Schema({
           first: {
             second: [Number]
@@ -2171,7 +2178,7 @@ describe('Model', function() {
         done();
       });
 
-      it('works with object literals', function(done) {
+      it('works with object literals', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -2228,10 +2235,10 @@ describe('Model', function() {
         assert.ok(post.get('meta').date instanceof Date);
         assert.equal('number', typeof post.meta.visitors);
         assert.equal('number', typeof post.get('meta').visitors);
-        assert.equal((+post.meta.date),date - 2000);
-        assert.equal((+post.get('meta').date),date - 2000);
-        assert.equal((+post.meta.visitors),234);
-        assert.equal((+post.get('meta').visitors),234);
+        assert.equal((+post.meta.date), date - 2000);
+        assert.equal((+post.get('meta').date), date - 2000);
+        assert.equal((+post.meta.visitors), 234);
+        assert.equal((+post.get('meta').visitors), 234);
 
         // set object directly
         post.meta = {
@@ -2243,14 +2250,14 @@ describe('Model', function() {
         assert.ok(post.get('meta').date instanceof Date);
         assert.equal('number', typeof post.meta.visitors);
         assert.equal('number', typeof post.get('meta').visitors);
-        assert.equal((+post.meta.date),date - 3000);
-        assert.equal((+post.get('meta').date),date - 3000);
-        assert.equal((+post.meta.visitors),4815162342);
-        assert.equal((+post.get('meta').visitors),4815162342);
+        assert.equal((+post.meta.date), date - 3000);
+        assert.equal((+post.get('meta').date), date - 3000);
+        assert.equal((+post.meta.visitors), 4815162342);
+        assert.equal((+post.get('meta').visitors), 4815162342);
         done();
       });
 
-      it('object property access works when root initd with null', function(done) {
+      it('object property access works when root initd with null', function (done) {
         var db = start();
 
         var schema = new Schema({
@@ -2262,21 +2269,21 @@ describe('Model', function() {
         mongoose.model('NestedStringA', schema);
         var T = db.model('NestedStringA', collection);
 
-        var t = new T({ nest: null });
+        var t = new T({nest: null});
 
         assert.strictEqual(t.nest.st, undefined);
-        t.nest = { st: "jsconf rules" };
-        assert.deepEqual(t.nest.toObject(),{ st: "jsconf rules" });
-        assert.equal(t.nest.st,"jsconf rules");
+        t.nest = {st: 'jsconf rules'};
+        assert.deepEqual(t.nest.toObject(), {st: 'jsconf rules'});
+        assert.equal(t.nest.st, 'jsconf rules');
 
-        t.save(function(err) {
+        t.save(function (err) {
           db.close();
           assert.ifError(err);
           done();
         });
       });
 
-      it('object property access works when root initd with undefined', function(done) {
+      it('object property access works when root initd with undefined', function (done) {
         var db = start();
 
         var schema = new Schema({
@@ -2288,21 +2295,21 @@ describe('Model', function() {
         mongoose.model('NestedStringB', schema);
         var T = db.model('NestedStringB', collection);
 
-        var t = new T({ nest: undefined });
+        var t = new T({nest: undefined});
 
         assert.strictEqual(t.nest.st, undefined);
-        t.nest = { st: "jsconf rules" };
-        assert.deepEqual(t.nest.toObject(),{ st: "jsconf rules" });
-        assert.equal(t.nest.st,"jsconf rules");
+        t.nest = {st: 'jsconf rules'};
+        assert.deepEqual(t.nest.toObject(), {st: 'jsconf rules'});
+        assert.equal(t.nest.st, 'jsconf rules');
 
-        t.save(function(err) {
+        t.save(function (err) {
           db.close();
           assert.ifError(err);
           done();
         });
       });
 
-      it('pre-existing null object re-save', function(done) {
+      it('pre-existing null object re-save', function (done) {
         var db = start();
 
         var schema = new Schema({
@@ -2315,12 +2322,12 @@ describe('Model', function() {
         mongoose.model('NestedStringC', schema);
         var T = db.model('NestedStringC', collection);
 
-        var t = new T({ nest: null });
+        var t = new T({nest: null});
 
-        t.save(function(err) {
+        t.save(function (err) {
           assert.ifError(err);
 
-          t.nest = { st: "jsconf rules", yep: "it does" };
+          t.nest = {st: 'jsconf rules', yep: 'it does'};
 
           // check that entire `nest` object is being $set
           var u = t.$__delta()[1];
@@ -2330,16 +2337,16 @@ describe('Model', function() {
           assert.ok(u.$set.nest.yep);
           assert.ok(u.$set.nest.st);
 
-          t.save(function(err) {
+          t.save(function (err) {
             assert.ifError(err);
 
-            T.findById(t.id, function(err, t) {
+            T.findById(t.id, function (err, t) {
               assert.ifError(err);
-              assert.equal(t.nest.st,"jsconf rules");
-              assert.equal(t.nest.yep,"it does");
+              assert.equal(t.nest.st, 'jsconf rules');
+              assert.equal(t.nest.yep, 'it does');
 
               t.nest = null;
-              t.save(function(err) {
+              t.save(function (err) {
                 db.close();
                 assert.ifError(err);
                 assert.strictEqual(t._doc.nest, null);
@@ -2350,7 +2357,7 @@ describe('Model', function() {
         });
       });
 
-      it('array of Mixed on existing doc can be pushed to', function(done) {
+      it('array of Mixed on existing doc can be pushed to', function (done) {
         var db = start();
 
         mongoose.model('MySchema', new Schema({
@@ -2360,28 +2367,28 @@ describe('Model', function() {
         }));
 
         var DooDad = db.model('MySchema'),
-            doodad = new DooDad({ nested: { arrays: [] } }),
+            doodad = new DooDad({nested: {arrays: []}}),
             date = 1234567890;
 
-        doodad.nested.arrays.push(["+10", "yup", date]);
+        doodad.nested.arrays.push(['+10', 'yup', date]);
 
-        doodad.save(function(err) {
+        doodad.save(function (err) {
           assert.ifError(err);
 
-          DooDad.findById(doodad._id, function(err, doodad) {
+          DooDad.findById(doodad._id, function (err, doodad) {
             assert.ifError(err);
 
-            assert.deepEqual(doodad.nested.arrays.toObject(), [['+10','yup',date]]);
+            assert.deepEqual(doodad.nested.arrays.toObject(), [['+10', 'yup', date]]);
 
-            doodad.nested.arrays.push(["another", 1]);
+            doodad.nested.arrays.push(['another', 1]);
 
-            doodad.save(function(err) {
+            doodad.save(function (err) {
               assert.ifError(err);
 
-              DooDad.findById(doodad._id, function(err, doodad) {
+              DooDad.findById(doodad._id, function (err, doodad) {
                 db.close();
                 assert.ifError(err);
-                assert.deepEqual(doodad.nested.arrays.toObject(), [['+10','yup',date], ["another", 1]]);
+                assert.deepEqual(doodad.nested.arrays.toObject(), [['+10', 'yup', date], ['another', 1]]);
                 done();
               });
             });
@@ -2389,16 +2396,16 @@ describe('Model', function() {
         });
       });
 
-      it('props can be set directly when property was named "type"', function(done) {
+      it('props can be set directly when property was named "type"', function (done) {
         var db = start();
 
         function def() {
-          return [{ x: 1 }, { x: 2 }, { x:3 }];
+          return [{x: 1}, {x: 2}, {x: 3}];
         }
 
         mongoose.model('MySchema2', new Schema({
           nested: {
-            type: { type: String, default: 'yep' },
+            type: {type: String, default: 'yep'},
             array: {
               type: Array, default: def
             }
@@ -2408,52 +2415,52 @@ describe('Model', function() {
         var DooDad = db.model('MySchema2', collection),
             doodad = new DooDad();
 
-        doodad.save(function(err) {
+        doodad.save(function (err) {
           assert.ifError(err);
 
-          DooDad.findById(doodad._id, function(err, doodad) {
+          DooDad.findById(doodad._id, function (err, doodad) {
             assert.ifError(err);
 
-            assert.equal(doodad.nested.type,"yep");
-            assert.deepEqual(doodad.nested.array.toObject(), [{x:1},{x:2},{x:3}]);
+            assert.equal(doodad.nested.type, 'yep');
+            assert.deepEqual(doodad.nested.array.toObject(), [{x: 1}, {x: 2}, {x: 3}]);
 
-            doodad.nested.type = "nope";
-            doodad.nested.array = ["some", "new", "stuff"];
+            doodad.nested.type = 'nope';
+            doodad.nested.array = ['some', 'new', 'stuff'];
 
-            doodad.save(function(err) {
+            doodad.save(function (err) {
               assert.ifError(err);
 
-              DooDad.findById(doodad._id, function(err, doodad) {
+              DooDad.findById(doodad._id, function (err, doodad) {
                 db.close();
                 assert.ifError(err);
-                assert.equal(doodad.nested.type,"nope");
-                assert.deepEqual(doodad.nested.array.toObject(), ["some", "new", "stuff"]);
+                assert.equal(doodad.nested.type, 'nope');
+                assert.deepEqual(doodad.nested.array.toObject(), ['some', 'new', 'stuff']);
                 done();
               });
             });
           });
         });
       });
-
     });
   });
 
-  describe('setters', function() {
-    it('are used on embedded docs (gh-365 gh-390 gh-422)', function(done) {
+  describe('setters', function () {
+    it('are used on embedded docs (gh-365 gh-390 gh-422)', function (done) {
       var db = start();
 
       function setLat(val) {
-        return parseInt(val);
+        return parseInt(val, 10);
       }
 
       var tick = 0;
+
       function uptick() {
         return ++tick;
       }
 
       var Location = new Schema({
-        lat:  { type: Number, default: 0, set: setLat},
-        long: { type: Number, set: uptick }
+        lat: {type: Number, default: 0, set: setLat},
+        long: {type: Number, set: uptick}
       });
 
       var Deal = new Schema({
@@ -2465,28 +2472,28 @@ describe('Model', function() {
       Deal = db.model('Deal', Deal, 'deals_' + random());
 
       var location = new Location({lat: 1.2, long: 10});
-      assert.equal(location.lat.valueOf(),1);
-      assert.equal(location.long.valueOf(),1);
+      assert.equal(location.lat.valueOf(), 1);
+      assert.equal(location.long.valueOf(), 1);
 
-      var deal = new Deal({title: "My deal", locations: [{lat: 1.2, long: 33}]});
-      assert.equal(deal.locations[0].lat.valueOf(),1);
-      assert.equal(deal.locations[0].long.valueOf(),2);
+      var deal = new Deal({title: 'My deal', locations: [{lat: 1.2, long: 33}]});
+      assert.equal(deal.locations[0].lat.valueOf(), 1);
+      assert.equal(deal.locations[0].long.valueOf(), 2);
 
-      deal.save(function(err) {
+      deal.save(function (err) {
         assert.ifError(err);
-        Deal.findById(deal._id, function(err, deal) {
+        Deal.findById(deal._id, function (err, deal) {
           db.close();
           assert.ifError(err);
-          assert.equal(deal.locations[0].lat.valueOf(),1);
+          assert.equal(deal.locations[0].lat.valueOf(), 1);
           // GH-422
-          assert.equal(deal.locations[0].long.valueOf(),2);
+          assert.equal(deal.locations[0].long.valueOf(), 2);
           done();
         });
       });
     });
   });
 
-  it('changing a number non-atomically (gh-203)', function(done) {
+  it('changing a number non-atomically (gh-203)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -2494,18 +2501,18 @@ describe('Model', function() {
 
     post.meta.visitors = 5;
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      BlogPost.findById(post._id, function(err, doc) {
+      BlogPost.findById(post._id, function (err, doc) {
         assert.ifError(err);
 
         doc.meta.visitors -= 2;
 
-        doc.save(function(err) {
+        doc.save(function (err) {
           assert.ifError(err);
 
-          BlogPost.findById(post._id, function(err, doc) {
+          BlogPost.findById(post._id, function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(3, +doc.meta.visitors);
@@ -2516,8 +2523,8 @@ describe('Model', function() {
     });
   });
 
-  describe('atomic subdocument', function() {
-    it('saving', function(done) {
+  describe('atomic subdocument', function () {
+    it('saving', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           totalDocs = 4,
@@ -2525,38 +2532,38 @@ describe('Model', function() {
 
       var post = new BlogPost;
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPost.findOne({ _id: post.get('_id') }, function(err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
           assert.ifError(err);
-          doc.get('comments').push({ title: '1' });
+          doc.get('comments').push({title: '1'});
           save(doc);
         });
 
-        BlogPost.findOne({ _id: post.get('_id') }, function(err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
           assert.ifError(err);
-          doc.get('comments').push({ title: '2' });
+          doc.get('comments').push({title: '2'});
           save(doc);
         });
 
-        BlogPost.findOne({ _id: post.get('_id') }, function(err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
           assert.ifError(err);
-          doc.get('comments').push({ title: '3' });
+          doc.get('comments').push({title: '3'});
           save(doc);
         });
 
-        BlogPost.findOne({ _id: post.get('_id') }, function(err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
           assert.ifError(err);
-          doc.get('comments').push({ title: '4' }, { title: '5' });
+          doc.get('comments').push({title: '4'}, {title: '5'});
           save(doc);
         });
 
         function save(doc) {
           saveQueue.push(doc);
           if (saveQueue.length == 4) {
-            saveQueue.forEach(function(doc) {
-              doc.save(function(err) {
+            saveQueue.forEach(function (doc) {
+              doc.save(function (err) {
                 assert.ifError(err);
                 --totalDocs || complete();
               });
@@ -2565,37 +2572,37 @@ describe('Model', function() {
         }
 
         function complete() {
-          BlogPost.findOne({ _id: post.get('_id') }, function(err, doc) {
+          BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
             db.close();
 
             assert.ifError(err);
-            assert.equal(doc.get('comments').length,5);
+            assert.equal(doc.get('comments').length, 5);
 
-            var v = doc.get('comments').some(function(comment) {
+            var v = doc.get('comments').some(function (comment) {
               return comment.get('title') == '1';
             });
 
             assert.ok(v);
 
-            v = doc.get('comments').some(function(comment) {
+            v = doc.get('comments').some(function (comment) {
               return comment.get('title') == '2';
             });
 
             assert.ok(v);
 
-            v = doc.get('comments').some(function(comment) {
+            v = doc.get('comments').some(function (comment) {
               return comment.get('title') == '3';
             });
 
             assert.ok(v);
 
-            v = doc.get('comments').some(function(comment) {
+            v = doc.get('comments').some(function (comment) {
               return comment.get('title') == '4';
             });
 
             assert.ok(v);
 
-            v = doc.get('comments').some(function(comment) {
+            v = doc.get('comments').some(function (comment) {
               return comment.get('title') == '5';
             });
 
@@ -2606,30 +2613,30 @@ describe('Model', function() {
       });
     });
 
-    it('setting (gh-310)', function(done) {
+    it('setting (gh-310)', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       BlogPost.create({
-        comments: [{ title: 'first-title', body: 'first-body'}]
-      }, function(err, blog) {
+        comments: [{title: 'first-title', body: 'first-body'}]
+      }, function (err, blog) {
         assert.ifError(err);
-        BlogPost.findById(blog.id, function(err, agent1blog) {
+        BlogPost.findById(blog.id, function (err, agent1blog) {
           assert.ifError(err);
-          BlogPost.findById(blog.id, function(err, agent2blog) {
+          BlogPost.findById(blog.id, function (err, agent2blog) {
             assert.ifError(err);
             agent1blog.get('comments')[0].title = 'second-title';
-            agent1blog.save( function(err) {
+            agent1blog.save(function (err) {
               assert.ifError(err);
               agent2blog.get('comments')[0].body = 'second-body';
-              agent2blog.save( function(err) {
+              agent2blog.save(function (err) {
                 assert.ifError(err);
-                BlogPost.findById(blog.id, function(err, foundBlog) {
+                BlogPost.findById(blog.id, function (err, foundBlog) {
                   assert.ifError(err);
                   db.close();
                   var comment = foundBlog.get('comments')[0];
-                  assert.equal(comment.title,'second-title');
-                  assert.equal(comment.body,'second-body');
+                  assert.equal(comment.title, 'second-title');
+                  assert.equal(comment.body, 'second-body');
                   done();
                 });
               });
@@ -2640,7 +2647,7 @@ describe('Model', function() {
     });
   });
 
-  it('doubly nested array saving and loading', function(done) {
+  it('doubly nested array saving and loading', function (done) {
     var Inner = new Schema({
       arr: [Number]
     });
@@ -2655,18 +2662,18 @@ describe('Model', function() {
 
     var outer = new Outer();
     outer.inner.push({});
-    outer.save(function(err) {
+    outer.save(function (err) {
       assert.ifError(err);
       assert.ok(outer.get('_id') instanceof DocumentObjectId);
 
-      Outer.findById(outer.get('_id'), function(err, found) {
+      Outer.findById(outer.get('_id'), function (err, found) {
         assert.ifError(err);
         assert.equal(1, found.inner.length);
         found.inner[0].arr.push(5);
-        found.save(function(err) {
+        found.save(function (err) {
           assert.ifError(err);
           assert.ok(found.get('_id') instanceof DocumentObjectId);
-          Outer.findById(found.get('_id'), function(err, found2) {
+          Outer.findById(found.get('_id'), function (err, found2) {
             db.close();
             assert.ifError(err);
             assert.equal(1, found2.inner.length);
@@ -2679,7 +2686,7 @@ describe('Model', function() {
     });
   });
 
-  it('updating multiple Number $pushes as a single $pushAll', function(done) {
+  it('updating multiple Number $pushes as a single $pushAll', function (done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2690,27 +2697,27 @@ describe('Model', function() {
     mongoose.model('NestedPushes', schema);
     var Temp = db.model('NestedPushes', collection);
 
-    Temp.create({}, function(err, t) {
+    Temp.create({}, function (err, t) {
       assert.ifError(err);
       t.nested.nums.push(1);
       t.nested.nums.push(2);
 
-      assert.equal(t.nested.nums.length,2);
+      assert.equal(t.nested.nums.length, 2);
 
-      t.save(function(err) {
+      t.save(function (err) {
         assert.ifError(err);
-        assert.equal(t.nested.nums.length,2);
-        Temp.findById(t._id, function(err) {
+        assert.equal(t.nested.nums.length, 2);
+        Temp.findById(t._id, function (err) {
           db.close();
           assert.ifError(err);
-          assert.equal(t.nested.nums.length,2);
+          assert.equal(t.nested.nums.length, 2);
           done();
         });
       });
     });
   });
 
-  it('updating at least a single $push and $pushAll as a single $pushAll', function(done) {
+  it('updating at least a single $push and $pushAll as a single $pushAll', function (done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2720,16 +2727,16 @@ describe('Model', function() {
 
     var Temp = db.model('NestedPushes', schema, collection);
 
-    Temp.create({}, function(err, t) {
+    Temp.create({}, function (err, t) {
       assert.ifError(err);
       t.nested.nums.push(1);
       t.nested.nums.push(2, 3);
       assert.equal(3, t.nested.nums.length);
 
-      t.save(function(err) {
+      t.save(function (err) {
         assert.ifError(err);
         assert.equal(t.nested.nums.length, 3);
-        Temp.findById(t._id, function(err, found) {
+        Temp.findById(t._id, function (err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(found.nested.nums.length, 3);
@@ -2739,7 +2746,7 @@ describe('Model', function() {
     });
   });
 
-  it('activePaths should be updated for nested modifieds', function(done) {
+  it('activePaths should be updated for nested modifieds', function (done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2749,18 +2756,18 @@ describe('Model', function() {
 
     var Temp = db.model('NestedPushes', schema, collection);
 
-    Temp.create({nested: {nums: [1, 2, 3, 4, 5]}}, function(err, t) {
+    Temp.create({nested: {nums: [1, 2, 3, 4, 5]}}, function (err, t) {
       assert.ifError(err);
       t.nested.nums.pull(1);
       t.nested.nums.pull(2);
-      assert.equal(t.$__.activePaths.paths['nested.nums'],'modify');
+      assert.equal(t.$__.activePaths.paths['nested.nums'], 'modify');
       db.close();
       done();
     });
   });
 
 
-  it('activePaths should be updated for nested modifieds as promise', function(done) {
+  it('activePaths should be updated for nested modifieds as promise', function (done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2771,19 +2778,17 @@ describe('Model', function() {
     var Temp = db.model('NestedPushes', schema, collection);
 
     var p1 = Temp.create({nested: {nums: [1, 2, 3, 4, 5]}});
-    p1.onResolve(function(err, t) {
+    p1.onResolve(function (err, t) {
       assert.ifError(err);
       t.nested.nums.pull(1);
       t.nested.nums.pull(2);
-      assert.equal(t.$__.activePaths.paths['nested.nums'],'modify');
+      assert.equal(t.$__.activePaths.paths['nested.nums'], 'modify');
       db.close();
       done();
     });
   });
 
-
-
-  it('$pull should affect what you see in an array before a save', function(done) {
+  it('$pull should affect what you see in an array before a save', function (done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2793,7 +2798,7 @@ describe('Model', function() {
 
     var Temp = db.model('NestedPushes', schema, collection);
 
-    Temp.create({nested: {nums: [1, 2, 3, 4, 5]}}, function(err, t) {
+    Temp.create({nested: {nums: [1, 2, 3, 4, 5]}}, function (err, t) {
       assert.ifError(err);
       t.nested.nums.pull(1);
       assert.equal(4, t.nested.nums.length);
@@ -2802,7 +2807,7 @@ describe('Model', function() {
     });
   });
 
-  it('$shift', function(done) {
+  it('$shift', function (done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2813,35 +2818,35 @@ describe('Model', function() {
     mongoose.model('TestingShift', schema);
     var Temp = db.model('TestingShift', collection);
 
-    Temp.create({ nested: { nums: [1,2,3] }}, function(err, t) {
+    Temp.create({nested: {nums: [1, 2, 3]}}, function (err, t) {
       assert.ifError(err);
 
-      Temp.findById(t._id, function(err, found) {
+      Temp.findById(t._id, function (err, found) {
         assert.ifError(err);
         assert.equal(found.nested.nums.length, 3);
         found.nested.nums.$pop();
         assert.equal(found.nested.nums.length, 2);
-        assert.equal(found.nested.nums[0],1);
-        assert.equal(found.nested.nums[1],2);
+        assert.equal(found.nested.nums[0], 1);
+        assert.equal(found.nested.nums[1], 2);
 
-        found.save(function(err) {
+        found.save(function (err) {
           assert.ifError(err);
-          Temp.findById(t._id, function(err, found) {
+          Temp.findById(t._id, function (err, found) {
             assert.ifError(err);
             assert.equal(2, found.nested.nums.length);
-            assert.equal(1, found.nested.nums[0],1);
-            assert.equal(2, found.nested.nums[1],2);
+            assert.equal(1, found.nested.nums[0], 1);
+            assert.equal(2, found.nested.nums[1], 2);
             found.nested.nums.$shift();
             assert.equal(1, found.nested.nums.length);
-            assert.equal(found.nested.nums[0],2);
+            assert.equal(found.nested.nums[0], 2);
 
-            found.save(function(err) {
+            found.save(function (err) {
               assert.ifError(err);
-              Temp.findById(t._id, function(err, found) {
+              Temp.findById(t._id, function (err, found) {
                 db.close();
                 assert.ifError(err);
-                assert.equal(found.nested.nums.length,1);
-                assert.equal(found.nested.nums[0],2);
+                assert.equal(found.nested.nums.length, 1);
+                assert.equal(found.nested.nums[0], 2);
                 done();
               });
             });
@@ -2851,8 +2856,8 @@ describe('Model', function() {
     });
   });
 
-  describe('saving embedded arrays', function() {
-    it('of Numbers atomically', function(done) {
+  describe('saving embedded arrays', function () {
+    it('of Numbers atomically', function (done) {
       var db = start(),
           TempSchema = new Schema({
             nums: [Number]
@@ -2865,16 +2870,16 @@ describe('Model', function() {
 
       var t = new Temp();
 
-      t.save(function(err) {
+      t.save(function (err) {
         assert.ifError(err);
 
-        Temp.findOne({ _id: t.get('_id') }, function(err, doc) {
+        Temp.findOne({_id: t.get('_id')}, function (err, doc) {
           assert.ifError(err);
           doc.get('nums').push(1);
           save(doc);
         });
 
-        Temp.findOne({ _id: t.get('_id') }, function(err, doc) {
+        Temp.findOne({_id: t.get('_id')}, function (err, doc) {
           assert.ifError(err);
           doc.get('nums').push(2, 3);
           save(doc);
@@ -2883,8 +2888,8 @@ describe('Model', function() {
         function save(doc) {
           saveQueue.push(doc);
           if (saveQueue.length == totalDocs) {
-            saveQueue.forEach(function(doc) {
-              doc.save(function(err) {
+            saveQueue.forEach(function (doc) {
+              doc.save(function (err) {
                 assert.ifError(err);
                 --totalDocs || complete();
               });
@@ -2893,21 +2898,21 @@ describe('Model', function() {
         }
 
         function complete() {
-          Temp.findOne({ _id: t.get('_id') }, function(err, doc) {
+          Temp.findOne({_id: t.get('_id')}, function (err, doc) {
             assert.ifError(err);
             assert.equal(3, doc.get('nums').length);
 
-            var v = doc.get('nums').some(function(num) {
+            var v = doc.get('nums').some(function (num) {
               return num.valueOf() == '1';
             });
             assert.ok(v);
 
-            v = doc.get('nums').some(function(num) {
+            v = doc.get('nums').some(function (num) {
               return num.valueOf() == '2';
             });
             assert.ok(v);
 
-            v = doc.get('nums').some(function(num) {
+            v = doc.get('nums').some(function (num) {
               return num.valueOf() == '3';
             });
             assert.ok(v);
@@ -2917,7 +2922,7 @@ describe('Model', function() {
       });
     });
 
-    it('of Strings atomically', function(done) {
+    it('of Strings atomically', function (done) {
       var db = start(),
           StrListSchema = new Schema({
             strings: [String]
@@ -2930,16 +2935,16 @@ describe('Model', function() {
 
       var t = new StrList();
 
-      t.save(function(err) {
+      t.save(function (err) {
         assert.ifError(err);
 
-        StrList.findOne({ _id: t.get('_id') }, function(err, doc) {
+        StrList.findOne({_id: t.get('_id')}, function (err, doc) {
           assert.ifError(err);
           doc.get('strings').push('a');
           save(doc);
         });
 
-        StrList.findOne({ _id: t.get('_id') }, function(err, doc) {
+        StrList.findOne({_id: t.get('_id')}, function (err, doc) {
           assert.ifError(err);
           doc.get('strings').push('b', 'c');
           save(doc);
@@ -2949,8 +2954,8 @@ describe('Model', function() {
         function save(doc) {
           saveQueue.push(doc);
           if (saveQueue.length == totalDocs) {
-            saveQueue.forEach(function(doc) {
-              doc.save(function(err) {
+            saveQueue.forEach(function (doc) {
+              doc.save(function (err) {
                 assert.ifError(err);
                 --totalDocs || complete();
               });
@@ -2959,23 +2964,23 @@ describe('Model', function() {
         }
 
         function complete() {
-          StrList.findOne({ _id: t.get('_id') }, function(err, doc) {
+          StrList.findOne({_id: t.get('_id')}, function (err, doc) {
             db.close();
             assert.ifError(err);
 
             assert.equal(3, doc.get('strings').length);
 
-            var v = doc.get('strings').some(function(str) {
+            var v = doc.get('strings').some(function (str) {
               return str == 'a';
             });
             assert.ok(v);
 
-            v = doc.get('strings').some(function(str) {
+            v = doc.get('strings').some(function (str) {
               return str == 'b';
             });
             assert.ok(v);
 
-            v = doc.get('strings').some(function(str) {
+            v = doc.get('strings').some(function (str) {
               return str == 'c';
             });
             assert.ok(v);
@@ -2985,7 +2990,7 @@ describe('Model', function() {
       });
     });
 
-    it('of Buffers atomically', function(done) {
+    it('of Buffers atomically', function (done) {
       var db = start(),
           BufListSchema = new Schema({
             buffers: [Buffer]
@@ -2998,16 +3003,16 @@ describe('Model', function() {
 
       var t = new BufList();
 
-      t.save(function(err) {
+      t.save(function (err) {
         assert.ifError(err);
 
-        BufList.findOne({ _id: t.get('_id') }, function(err, doc) {
+        BufList.findOne({_id: t.get('_id')}, function (err, doc) {
           assert.ifError(err);
           doc.get('buffers').push(new Buffer([140]));
           save(doc);
         });
 
-        BufList.findOne({ _id: t.get('_id') }, function(err, doc) {
+        BufList.findOne({_id: t.get('_id')}, function (err, doc) {
           assert.ifError(err);
           doc.get('buffers').push(new Buffer([141]), new Buffer([142]));
           save(doc);
@@ -3016,8 +3021,8 @@ describe('Model', function() {
         function save(doc) {
           saveQueue.push(doc);
           if (saveQueue.length == totalDocs) {
-            saveQueue.forEach(function(doc) {
-              doc.save(function(err) {
+            saveQueue.forEach(function (doc) {
+              doc.save(function (err) {
                 assert.ifError(err);
                 --totalDocs || complete();
               });
@@ -3026,23 +3031,23 @@ describe('Model', function() {
         }
 
         function complete() {
-          BufList.findOne({ _id: t.get('_id') }, function(err, doc) {
+          BufList.findOne({_id: t.get('_id')}, function (err, doc) {
             db.close();
             assert.ifError(err);
 
             assert.equal(3, doc.get('buffers').length);
 
-            var v = doc.get('buffers').some(function(buf) {
+            var v = doc.get('buffers').some(function (buf) {
               return buf[0] == 140;
             });
             assert.ok(v);
 
-            v = doc.get('buffers').some(function(buf) {
+            v = doc.get('buffers').some(function (buf) {
               return buf[0] == 141;
             });
             assert.ok(v);
 
-            v = doc.get('buffers').some(function(buf) {
+            v = doc.get('buffers').some(function (buf) {
               return buf[0] == 142;
             });
             assert.ok(v);
@@ -3053,29 +3058,29 @@ describe('Model', function() {
       });
     });
 
-    it('works with modified element properties + doc removal (gh-975)', function(done) {
+    it('works with modified element properties + doc removal (gh-975)', function (done) {
       var db = start(),
           B = db.model('BlogPost', collection),
-          b = new B({ comments: [{ title: 'gh-975' }] });
+          b = new B({comments: [{title: 'gh-975'}]});
 
-      b.save(function(err) {
+      b.save(function (err) {
         assert.ifError(err);
 
         b.comments[0].title = 'changed';
-        b.save(function(err) {
+        b.save(function (err) {
           assert.ifError(err);
 
           b.comments[0].remove();
-          b.save(function(err) {
+          b.save(function (err) {
             assert.ifError(err);
 
-            B.findByIdAndUpdate({ _id: b._id }, { $set: { comments: [{ title: 'a' }] }}, { 'new': true }, function(err, doc) {
+            B.findByIdAndUpdate({_id: b._id}, {$set: {comments: [{title: 'a'}]}}, {'new': true}, function (err, doc) {
               assert.ifError(err);
               doc.comments[0].title = 'differ';
               doc.comments[0].remove();
-              doc.save(function(err) {
+              doc.save(function (err) {
                 assert.ifError(err);
-                B.findById(doc._id, function(err, doc) {
+                B.findById(doc._id, function (err, doc) {
                   db.close();
                   assert.ifError(err);
                   assert.equal(0, doc.comments.length);
@@ -3088,7 +3093,7 @@ describe('Model', function() {
       });
     });
 
-    it('updating an embedded document in an embedded array with set call', function(done) {
+    it('updating an embedded document in an embedded array with set call', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -3096,9 +3101,9 @@ describe('Model', function() {
         comments: [{
           title: 'before-change'
         }]
-      }, function(err, post) {
+      }, function (err, post) {
         assert.ifError(err);
-        BlogPost.findById(post._id, function(err, found) {
+        BlogPost.findById(post._id, function (err, found) {
           assert.ifError(err);
           assert.equal('before-change', found.comments[0].title);
           var subDoc = [{
@@ -3107,9 +3112,9 @@ describe('Model', function() {
           }];
           found.set('comments', subDoc);
 
-          found.save(function(err) {
+          found.save(function (err) {
             assert.ifError(err);
-            BlogPost.findById(found._id, function(err, updated) {
+            BlogPost.findById(found._id, function (err, updated) {
               db.close();
               assert.ifError(err);
               assert.equal('after-change', updated.comments[0].title);
@@ -3121,19 +3126,19 @@ describe('Model', function() {
     });
   });
 
-  it('updating an embedded document in an embedded array (gh-255)', function(done) {
+  it('updating an embedded document in an embedded array (gh-255)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
-    BlogPost.create({comments: [{title: 'woot'}]}, function(err, post) {
+    BlogPost.create({comments: [{title: 'woot'}]}, function (err, post) {
       assert.ifError(err);
-      BlogPost.findById(post._id, function(err, found) {
+      BlogPost.findById(post._id, function (err, found) {
         assert.ifError(err);
         assert.equal('woot', found.comments[0].title);
         found.comments[0].title = 'notwoot';
-        found.save( function(err) {
+        found.save(function (err) {
           assert.ifError(err);
-          BlogPost.findById(found._id, function(err, updated) {
+          BlogPost.findById(found._id, function (err, updated) {
             db.close();
             assert.ifError(err);
             assert.equal('notwoot', updated.comments[0].title);
@@ -3144,30 +3149,30 @@ describe('Model', function() {
     });
   });
 
-  it('updating an embedded array document to an Object value (gh-334)', function(done) {
+  it('updating an embedded array document to an Object value (gh-334)', function (done) {
     var db = start(),
         SubSchema = new Schema({
           name: String,
-          subObj: { subName: String }
+          subObj: {subName: String}
         });
-    var GH334Schema = new Schema({ name: String, arrData: [ SubSchema] });
+    var GH334Schema = new Schema({name: String, arrData: [SubSchema]});
 
     mongoose.model('GH334', GH334Schema);
     var AModel = db.model('GH334');
     var instance = new AModel();
 
-    instance.set( { name : 'name-value', arrData: [ { name: 'arrName1', subObj: { subName: 'subName1' } } ] });
-    instance.save(function(err) {
+    instance.set({name: 'name-value', arrData: [{name: 'arrName1', subObj: {subName: 'subName1'}}]});
+    instance.save(function (err) {
       assert.ifError(err);
-      AModel.findById(instance.id, function(err, doc) {
+      AModel.findById(instance.id, function (err, doc) {
         assert.ifError(err);
-        doc.arrData[0].set('subObj', { subName : 'modified subName' });
-        doc.save(function(err) {
+        doc.arrData[0].set('subObj', {subName: 'modified subName'});
+        doc.save(function (err) {
           assert.ifError(err);
-          AModel.findById(instance.id, function(err, doc) {
+          AModel.findById(instance.id, function (err, doc) {
             db.close();
             assert.ifError(err);
-            assert.equal(doc.arrData[0].subObj.subName,'modified subName');
+            assert.equal(doc.arrData[0].subObj.subName, 'modified subName');
             done();
           });
         });
@@ -3175,22 +3180,22 @@ describe('Model', function() {
     });
   });
 
-  it('saving an embedded document twice should not push that doc onto the parent doc twice (gh-267)', function(done) {
+  it('saving an embedded document twice should not push that doc onto the parent doc twice (gh-267)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection),
         post = new BlogPost();
 
     post.comments.push({title: 'woot'});
-    post.save( function(err) {
+    post.save(function (err) {
       assert.ifError(err);
       assert.equal(1, post.comments.length);
-      BlogPost.findById(post.id, function(err, found) {
+      BlogPost.findById(post.id, function (err, found) {
         assert.ifError(err);
         assert.equal(1, found.comments.length);
-        post.save( function(err) {
+        post.save(function (err) {
           assert.ifError(err);
           assert.equal(1, post.comments.length);
-          BlogPost.findById(post.id, function(err, found) {
+          BlogPost.findById(post.id, function (err, found) {
             db.close();
             assert.ifError(err);
             assert.equal(1, found.comments.length);
@@ -3201,47 +3206,47 @@ describe('Model', function() {
     });
   });
 
-  describe('embedded array filtering', function() {
-    it('by the id shortcut function', function(done) {
+  describe('embedded array filtering', function () {
+    it('by the id shortcut function', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost();
 
-      post.comments.push({ title: 'woot' });
-      post.comments.push({ title: 'aaaa' });
+      post.comments.push({title: 'woot'});
+      post.comments.push({title: 'aaaa'});
 
       var subdoc1 = post.comments[0];
       var subdoc2 = post.comments[1];
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPost.findById(post.get('_id'), function(err, doc) {
+        BlogPost.findById(post.get('_id'), function (err, doc) {
           db.close();
           assert.ifError(err);
 
           // test with an objectid
-          assert.equal(doc.comments.id(subdoc1.get('_id')).title,'woot');
+          assert.equal(doc.comments.id(subdoc1.get('_id')).title, 'woot');
 
           // test with a string
           var id = subdoc2._id.toString();
-          assert.equal(doc.comments.id(id).title,'aaaa');
+          assert.equal(doc.comments.id(id).title, 'aaaa');
           done();
         });
       });
     });
 
-    it('by the id with cast error', function(done) {
+    it('by the id with cast error', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost();
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPost.findById(post.get('_id'), function(err, doc) {
+        BlogPost.findById(post.get('_id'), function (err, doc) {
           db.close();
           assert.ifError(err);
           assert.strictEqual(doc.comments.id(null), null);
@@ -3250,16 +3255,16 @@ describe('Model', function() {
       });
     });
 
-    it('by the id shortcut with no match', function(done) {
+    it('by the id shortcut with no match', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost();
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        BlogPost.findById(post.get('_id'), function(err, doc) {
+        BlogPost.findById(post.get('_id'), function (err, doc) {
           db.close();
           assert.ifError(err);
           assert.strictEqual(doc.comments.id(new DocumentObjectId), null);
@@ -3269,30 +3274,30 @@ describe('Model', function() {
     });
   });
 
-  it('removing a subdocument atomically', function(done) {
+  it('removing a subdocument atomically', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
     var post = new BlogPost();
     post.title = 'hahaha';
-    post.comments.push({ title: 'woot' });
-    post.comments.push({ title: 'aaaa' });
+    post.comments.push({title: 'woot'});
+    post.comments.push({title: 'aaaa'});
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      BlogPost.findById(post.get('_id'), function(err, doc) {
+      BlogPost.findById(post.get('_id'), function (err, doc) {
         assert.ifError(err);
 
         doc.comments[0].remove();
-        doc.save(function(err) {
+        doc.save(function (err) {
           assert.ifError(err);
 
-          BlogPost.findById(post.get('_id'), function(err, doc) {
+          BlogPost.findById(post.get('_id'), function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(1, doc.comments.length);
-            assert.equal(doc.comments[0].title,'aaaa');
+            assert.equal(doc.comments[0].title, 'aaaa');
             done();
           });
         });
@@ -3300,27 +3305,27 @@ describe('Model', function() {
     });
   });
 
-  it('single pull embedded doc', function(done) {
+  it('single pull embedded doc', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
     var post = new BlogPost();
     post.title = 'hahaha';
-    post.comments.push({ title: 'woot' });
-    post.comments.push({ title: 'aaaa' });
+    post.comments.push({title: 'woot'});
+    post.comments.push({title: 'aaaa'});
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      BlogPost.findById(post.get('_id'), function(err, doc) {
+      BlogPost.findById(post.get('_id'), function (err, doc) {
         assert.ifError(err);
 
         doc.comments.pull(doc.comments[0]);
         doc.comments.pull(doc.comments[0]);
-        doc.save(function(err) {
+        doc.save(function (err) {
           assert.ifError(err);
 
-          BlogPost.findById(post.get('_id'), function(err, doc) {
+          BlogPost.findById(post.get('_id'), function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(0, doc.comments.length);
@@ -3331,7 +3336,7 @@ describe('Model', function() {
     });
   });
 
-  it('saving mixed data', function(done) {
+  it('saving mixed data', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection),
         count = 3;
@@ -3339,12 +3344,14 @@ describe('Model', function() {
     // string
     var post = new BlogPost();
     post.mixed = 'woot';
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      BlogPost.findById(post._id, function(err) {
+      BlogPost.findById(post._id, function (err) {
         assert.ifError(err);
-        if (--count) return;
+        if (--count) {
+          return;
+        }
         db.close();
         done();
       });
@@ -3352,37 +3359,39 @@ describe('Model', function() {
 
     // array
     var post2 = new BlogPost();
-    post2.mixed = { name: "mr bungle", arr: [] };
-    post2.save(function(err) {
+    post2.mixed = {name: 'mr bungle', arr: []};
+    post2.save(function (err) {
       assert.ifError(err);
 
-      BlogPost.findById(post2._id, function(err, doc) {
+      BlogPost.findById(post2._id, function (err, doc) {
         assert.ifError(err);
 
         assert.equal(true, Array.isArray(doc.mixed.arr));
 
         doc.mixed = [{foo: 'bar'}];
-        doc.save(function(err) {
+        doc.save(function (err) {
           assert.ifError(err);
 
-          BlogPost.findById(doc._id, function(err, doc) {
+          BlogPost.findById(doc._id, function (err, doc) {
             assert.ifError(err);
 
             assert.equal(true, Array.isArray(doc.mixed));
-            doc.mixed.push({ hello: 'world' });
-            doc.mixed.push([ 'foo', 'bar' ]);
+            doc.mixed.push({hello: 'world'});
+            doc.mixed.push(['foo', 'bar']);
             doc.markModified('mixed');
 
-            doc.save(function(err) {
+            doc.save(function (err) {
               assert.ifError(err);
 
-              BlogPost.findById(post2._id, function(err, doc) {
+              BlogPost.findById(post2._id, function (err, doc) {
                 assert.ifError(err);
 
-                assert.deepEqual(doc.mixed[0],{ foo: 'bar' });
-                assert.deepEqual(doc.mixed[1],{ hello: 'world' });
-                assert.deepEqual(doc.mixed[2],['foo','bar']);
-                if (--count) return;
+                assert.deepEqual(doc.mixed[0], {foo: 'bar'});
+                assert.deepEqual(doc.mixed[1], {hello: 'world'});
+                assert.deepEqual(doc.mixed[2], ['foo', 'bar']);
+                if (--count) {
+                  return;
+                }
                 db.close();
                 done();
               });
@@ -3392,13 +3401,15 @@ describe('Model', function() {
           // date
           var post3 = new BlogPost();
           post3.mixed = new Date;
-          post3.save(function(err) {
+          post3.save(function (err) {
             assert.ifError(err);
 
-            BlogPost.findById(post3._id, function(err, doc) {
+            BlogPost.findById(post3._id, function (err, doc) {
               assert.ifError(err);
               assert.ok(doc.mixed instanceof Date);
-              if (--count) return;
+              if (--count) {
+                return;
+              }
               db.close();
               done();
             });
@@ -3408,7 +3419,7 @@ describe('Model', function() {
     });
   });
 
-  it('populating mixed data from the constructor (gh-200)', function(done) {
+  it('populating mixed data from the constructor (gh-200)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost');
 
@@ -3429,53 +3440,53 @@ describe('Model', function() {
     done();
   });
 
-  it('"type" is allowed as a key', function(done) {
+  it('"type" is allowed as a key', function (done) {
     mongoose.model('TestTypeDefaults', new Schema({
-      type: { type: String, default: 'YES!' }
+      type: {type: String, default: 'YES!'}
     }));
 
     var db = start(),
         TestDefaults = db.model('TestTypeDefaults');
 
     var post = new TestDefaults();
-    assert.equal(typeof post.get('type'),'string');
-    assert.equal(post.get('type'),'YES!');
+    assert.equal(typeof post.get('type'), 'string');
+    assert.equal(post.get('type'), 'YES!');
 
     // GH-402
     var TestDefaults2 = db.model('TestTypeDefaults2', new Schema({
-      x: { y: { type: { type: String }, owner: String } }
+      x: {y: {type: {type: String}, owner: String}}
     }));
 
     post = new TestDefaults2;
-    post.x.y.type = "#402";
-    post.x.y.owner = "me";
-    post.save(function(err) {
+    post.x.y.type = '#402';
+    post.x.y.owner = 'me';
+    post.save(function (err) {
       db.close();
       assert.ifError(err);
       done();
     });
   });
 
-  it('unaltered model does not clear the doc (gh-195)', function(done) {
+  it('unaltered model does not clear the doc (gh-195)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
     var post = new BlogPost();
     post.title = 'woot';
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
-      BlogPost.findById(post._id, function(err, doc) {
+      BlogPost.findById(post._id, function (err, doc) {
         assert.ifError(err);
 
         // we deliberately make no alterations
-        doc.save(function(err) {
+        doc.save(function (err) {
           assert.ifError(err);
 
-          BlogPost.findById(doc._id, function(err, doc) {
+          BlogPost.findById(doc._id, function (err, doc) {
             db.close();
             assert.ifError(err);
-            assert.equal(doc.title,'woot');
+            assert.equal(doc.title, 'woot');
             done();
           });
         });
@@ -3483,11 +3494,11 @@ describe('Model', function() {
     });
   });
 
-  describe('safe mode', function() {
-    it('works', function(done) {
+  describe('safe mode', function () {
+    it('works', function (done) {
       var Human = new Schema({
         name: String,
-        email: { type: String, index: { unique: true, background: false }}
+        email: {type: String, index: {unique: true, background: false}}
       });
 
       mongoose.model('SafeHuman', Human, true);
@@ -3495,26 +3506,26 @@ describe('Model', function() {
       var db = start();
       Human = db.model('SafeHuman', 'safehuman' + random());
 
-      Human.on('index', function(err) {
+      Human.on('index', function (err) {
         assert.ifError(err);
         var me = new Human({
-          name  : 'Guillermo Rauch',
-          email : 'rauchg@gmail.com'
+          name: 'Guillermo Rauch',
+          email: 'rauchg@gmail.com'
         });
 
-        me.save(function(err) {
+        me.save(function (err) {
           assert.ifError(err);
 
-          Human.findById(me._id, function(err, doc) {
+          Human.findById(me._id, function (err, doc) {
             assert.ifError(err);
-            assert.equal(doc.email,'rauchg@gmail.com');
+            assert.equal(doc.email, 'rauchg@gmail.com');
 
             var copycat = new Human({
-              name  : 'Lionel Messi',
-              email : 'rauchg@gmail.com'
+              name: 'Lionel Messi',
+              email: 'rauchg@gmail.com'
             });
 
-            copycat.save(function(err) {
+            copycat.save(function (err) {
               db.close();
               assert.ok(/duplicate/.test(err.message));
               assert.ok(err instanceof Error);
@@ -3523,13 +3534,12 @@ describe('Model', function() {
           });
         });
       });
-
     });
 
-    it('can be disabled', function(done) {
+    it('can be disabled', function (done) {
       var Human = new Schema({
         name: String,
-        email: { type: String, index: { unique: true, background: false }}
+        email: {type: String, index: {unique: true, background: false}}
       });
 
       // turn it off
@@ -3540,31 +3550,31 @@ describe('Model', function() {
       var db = start();
       Human = db.model('UnsafeHuman', 'unsafehuman' + random());
 
-      Human.on('index', function(err) {
+      Human.on('index', function (err) {
         assert.ifError(err);
       });
 
       var me = new Human({
-        name  : 'Guillermo Rauch',
-        email : 'rauchg@gmail.com'
+        name: 'Guillermo Rauch',
+        email: 'rauchg@gmail.com'
       });
 
-      me.save(function(err) {
+      me.save(function (err) {
         assert.ifError(err);
 
         // no confirmation the write occured b/c we disabled safe.
         // wait a little bit to ensure the doc exists in the db
-        setTimeout(function() {
-          Human.findById(me._id, function(err, doc) {
+        setTimeout(function () {
+          Human.findById(me._id, function (err, doc) {
             assert.ifError(err);
-            assert.equal(doc.email,'rauchg@gmail.com');
+            assert.equal(doc.email, 'rauchg@gmail.com');
 
             var copycat = new Human({
-              name  : 'Lionel Messi',
-              email : 'rauchg@gmail.com'
+              name: 'Lionel Messi',
+              email: 'rauchg@gmail.com'
             });
 
-            copycat.save(function(err) {
+            copycat.save(function (err) {
               db.close();
               assert.ifError(err);
               done();
@@ -3575,30 +3585,30 @@ describe('Model', function() {
     });
   });
 
-  describe('hooks', function() {
-    describe('pre', function() {
-      it('can pass non-error values to the next middleware', function(done) {
+  describe('hooks', function () {
+    describe('pre', function () {
+      it('can pass non-error values to the next middleware', function (done) {
         var db = start();
-        var schema = new Schema({ name: String });
+        var schema = new Schema({name: String});
 
-        schema.pre('save', function(next) {
+        schema.pre('save', function (next) {
           next('hey there');
-        }).pre('save', function(next, message) {
+        }).pre('save', function (next, message) {
           assert.ok(message);
           assert.equal(message, 'hey there');
           next();
-        }).pre('save', function(next) {
+        }).pre('save', function (next) {
           // just throw error
           next(new Error('error string'));
-        }).pre('save', function(next) {
+        }).pre('save', function (next) {
           // don't call since error thrown in previous save
           assert.ok(false);
           next('don\'t call me');
         });
         var S = db.model('S', schema, collection);
-        var s = new S({ name: 'angelina' });
+        var s = new S({name: 'angelina'});
 
-        s.save(function(err) {
+        s.save(function (err) {
           db.close();
           assert.ok(err);
           assert.equal(err.message, 'error string');
@@ -3606,17 +3616,17 @@ describe('Model', function() {
         });
       });
 
-      it('with undefined and null', function(done) {
+      it('with undefined and null', function (done) {
         var db = start();
-        var schema = new Schema({ name: String });
+        var schema = new Schema({name: String});
         var called = 0;
 
-        schema.pre('save', function(next) {
+        schema.pre('save', function (next) {
           called++;
           next(undefined);
         });
 
-        schema.pre('save', function(next) {
+        schema.pre('save', function (next) {
           called++;
           next(null);
         });
@@ -3624,7 +3634,7 @@ describe('Model', function() {
         var S = db.model('S', schema, collection);
         var s = new S({name: 'zupa'});
 
-        s.save(function(err) {
+        s.save(function (err) {
           db.close();
           assert.ifError(err);
           assert.equal(2, called);
@@ -3633,20 +3643,20 @@ describe('Model', function() {
       });
 
 
-      it('with an async waterfall', function(done) {
+      it('with an async waterfall', function (done) {
         var db = start();
-        var schema = new Schema({ name: String });
+        var schema = new Schema({name: String});
         var called = 0;
 
-        schema.pre('save', true, function(next, done) {
+        schema.pre('save', true, function (next, done) {
           called++;
-          process.nextTick(function() {
+          process.nextTick(function () {
             next();
             done();
           });
         });
 
-        schema.pre('save', function(next) {
+        schema.pre('save', function (next) {
           called++;
           return next();
         });
@@ -3655,7 +3665,7 @@ describe('Model', function() {
         var s = new S({name: 'zupa'});
 
         var p = s.save();
-        p.onResolve(function(err) {
+        p.onResolve(function (err) {
           db.close();
           assert.ifError(err);
           assert.equal(2, called);
@@ -3664,80 +3674,80 @@ describe('Model', function() {
       });
 
 
-      it('called on all sub levels', function(done) {
+      it('called on all sub levels', function (done) {
         var db = start();
 
-        var grandSchema = new Schema({ name: String });
-        grandSchema.pre('save', function(next) {
+        var grandSchema = new Schema({name: String});
+        grandSchema.pre('save', function (next) {
           this.name = 'grand';
           next();
         });
 
-        var childSchema = new Schema({ name: String, grand: [grandSchema]});
-        childSchema.pre('save', function(next) {
+        var childSchema = new Schema({name: String, grand: [grandSchema]});
+        childSchema.pre('save', function (next) {
           this.name = 'child';
           next();
         });
 
-        var schema = new Schema({ name: String, child: [childSchema] });
+        var schema = new Schema({name: String, child: [childSchema]});
 
-        schema.pre('save', function(next) {
+        schema.pre('save', function (next) {
           this.name = 'parent';
           next();
         });
 
         var S = db.model('presave_hook', schema, 'presave_hook');
-        var s = new S({ name: 'a', child: [ { name: 'b', grand: [{ name: 'c'}] } ]});
+        var s = new S({name: 'a', child: [{name: 'b', grand: [{name: 'c'}]}]});
 
-        s.save(function(err, doc) {
+        s.save(function (err, doc) {
           db.close();
           assert.ifError(err);
-          assert.equal(doc.name,'parent');
-          assert.equal(doc.child[0].name,'child');
-          assert.equal(doc.child[0].grand[0].name,'grand');
+          assert.equal(doc.name, 'parent');
+          assert.equal(doc.child[0].name, 'child');
+          assert.equal(doc.child[0].grand[0].name, 'grand');
           done();
         });
       });
 
 
-      it('error on any sub level', function(done) {
+      it('error on any sub level', function (done) {
         var db = start();
 
-        var grandSchema = new Schema({ name: String });
-        grandSchema.pre('save', function(next) {
+        var grandSchema = new Schema({name: String});
+        grandSchema.pre('save', function (next) {
           next(new Error('Error 101'));
         });
 
-        var childSchema = new Schema({ name: String, grand: [grandSchema]});
-        childSchema.pre('save', function(next) {
+        var childSchema = new Schema({name: String, grand: [grandSchema]});
+        childSchema.pre('save', function (next) {
           this.name = 'child';
           next();
         });
 
-        var schema = new Schema({ name: String, child: [childSchema] });
-        schema.pre('save', function(next) {
+        var schema = new Schema({name: String, child: [childSchema]});
+        schema.pre('save', function (next) {
           this.name = 'parent';
           next();
         });
 
         var S = db.model('presave_hook_error', schema, 'presave_hook_error');
-        var s = new S({ name: 'a', child: [ { name: 'b', grand: [{ name: 'c'}] } ]});
+        var s = new S({name: 'a', child: [{name: 'b', grand: [{name: 'c'}]}]});
 
-        s.save(function(err) {
+        s.save(function (err) {
           db.close();
           assert.ok(err instanceof Error);
-          assert.equal(err.message,'Error 101');
+          assert.equal(err.message, 'Error 101');
           done();
         });
       });
 
-      describe('init', function() {
-        it('has access to the true ObjectId when used with querying (gh-289)', function(done) {
+      describe('init', function () {
+        it('has access to the true ObjectId when used with querying (gh-289)', function (done) {
           var db = start(),
               PreInitSchema = new Schema({}),
               preId = null;
 
-          PreInitSchema.pre('init', function(next) {
+          PreInitSchema.pre('init', function (next) {
             preId = this._id;
             next();
           });
@@ -3745,9 +3755,9 @@ describe('Model', function() {
           var PreInit = db.model('PreInit', PreInitSchema, 'pre_inits' + random());
 
           var doc = new PreInit();
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
-            PreInit.findById(doc._id, function(err) {
+            PreInit.findById(doc._id, function (err) {
               db.close();
               assert.ifError(err);
               assert.strictEqual(undefined, preId);
@@ -3757,15 +3767,15 @@ describe('Model', function() {
         });
       });
 
-      it('should not work when calling next() after a thrown error', function(done) {
+      it('should not work when calling next() after a thrown error', function (done) {
         var db = start();
 
         var s = new Schema({});
-        s.methods.funky = function() {
+        s.methods.funky = function () {
           assert.strictEqual(false, true, 'reached unreachable code');
         };
 
-        s.pre('funky', function(next) {
+        s.pre('funky', function (next) {
           db.close();
           try {
             next(new Error);
@@ -3779,11 +3789,10 @@ describe('Model', function() {
         new Kaboom().funky();
         done();
       });
-
     });
 
-    describe('post', function() {
-      it('works', function(done) {
+    describe('post', function () {
+      it('works', function (done) {
         var schema = new Schema({
               title: String
             }),
@@ -3792,17 +3801,17 @@ describe('Model', function() {
             init = false,
             post = undefined;
 
-        schema.post('save', function(arg) {
+        schema.post('save', function (arg) {
           assert.equal(arg.id, post.id);
           save = true;
         });
 
-        schema.post('init', function() {
+        schema.post('init', function () {
           init = true;
         });
 
-        schema.post('remove', function(arg) {
-          assert.equal(arg.id,post.id);
+        schema.post('remove', function (arg) {
+          assert.equal(arg.id, post.id);
           remove = true;
         });
 
@@ -3813,17 +3822,17 @@ describe('Model', function() {
 
         post = new BlogPost();
 
-        post.save(function(err) {
-          process.nextTick(function() {
+        post.save(function (err) {
+          process.nextTick(function () {
             assert.ifError(err);
             assert.ok(save);
-            BlogPost.findById(post._id, function(err, doc) {
-              process.nextTick(function() {
+            BlogPost.findById(post._id, function (err, doc) {
+              process.nextTick(function () {
                 assert.ifError(err);
                 assert.ok(init);
 
-                doc.remove(function(err) {
-                  process.nextTick(function() {
+                doc.remove(function (err) {
+                  process.nextTick(function () {
                     db.close();
                     assert.ifError(err);
                     assert.ok(remove);
@@ -3833,12 +3842,10 @@ describe('Model', function() {
               });
             });
           });
-
         });
-
       });
 
-      it('on embedded docs', function(done) {
+      it('on embedded docs', function (done) {
         var save = false;
 
         var EmbeddedSchema = new Schema({
@@ -3849,18 +3856,18 @@ describe('Model', function() {
           embeds: [EmbeddedSchema]
         });
 
-        EmbeddedSchema.post('save', function() {
+        EmbeddedSchema.post('save', function () {
           save = true;
         });
 
         // Don't know how to test those on a embedded document.
-        //EmbeddedSchema.post('init', function () {
-          //init = true;
-        //});
+        // EmbeddedSchema.post('init', function () {
+        // init = true;
+        // });
 
-        //EmbeddedSchema.post('remove', function () {
-          //remove = true;
-        //});
+        // EmbeddedSchema.post('remove', function () {
+        // remove = true;
+        // });
 
         mongoose.model('Parent', ParentSchema);
 
@@ -3871,7 +3878,7 @@ describe('Model', function() {
 
         parent.embeds.push({title: 'Testing post hooks for embedded docs'});
 
-        parent.save(function(err) {
+        parent.save(function (err) {
           db.close();
           assert.ifError(err);
           assert.ok(save);
@@ -3879,18 +3886,17 @@ describe('Model', function() {
         });
       });
     });
-
   });
 
-  describe('#exec()', function() {
-    it('count()', function(done) {
+  describe('#exec()', function () {
+    it('count()', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-      BlogPost.create({title: 'interoperable count as promise'}, function(err) {
+      BlogPost.create({title: 'interoperable count as promise'}, function (err) {
         assert.ifError(err);
         var query = BlogPost.count({title: 'interoperable count as promise'});
-        query.exec(function(err, count) {
+        query.exec(function (err, count) {
           db.close();
           assert.ifError(err);
           assert.equal(1, count);
@@ -3899,17 +3905,17 @@ describe('Model', function() {
       });
     });
 
-    it('update()', function(done) {
+    it('update()', function (done) {
       var col = 'BlogPost' + random();
       var db = start(),
           BlogPost = db.model(col, bpSchema);
 
-      BlogPost.create({title: 'interoperable update as promise'}, function(err) {
+      BlogPost.create({title: 'interoperable update as promise'}, function (err) {
         assert.ifError(err);
         var query = BlogPost.update({title: 'interoperable update as promise'}, {title: 'interoperable update as promise delta'});
-        query.exec(function(err) {
+        query.exec(function (err) {
           assert.ifError(err);
-          BlogPost.count({title: 'interoperable update as promise delta'}, function(err, count) {
+          BlogPost.count({title: 'interoperable update as promise delta'}, function (err, count) {
             db.close();
             assert.ifError(err);
             assert.equal(1, count);
@@ -3919,93 +3925,93 @@ describe('Model', function() {
       });
     });
 
-    it('findOne()', function(done) {
+    it('findOne()', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-      BlogPost.create({title: 'interoperable findOne as promise'}, function(err, created) {
+      BlogPost.create({title: 'interoperable findOne as promise'}, function (err, created) {
         assert.ifError(err);
         var query = BlogPost.findOne({title: 'interoperable findOne as promise'});
-        query.exec(function(err, found) {
+        query.exec(function (err, found) {
           db.close();
           assert.ifError(err);
-          assert.equal(found.id,created.id);
+          assert.equal(found.id, created.id);
           done();
         });
       });
     });
 
-    it('find()', function(done) {
+    it('find()', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema);
 
       BlogPost.create(
           {title: 'interoperable find as promise'},
-         {title: 'interoperable find as promise'},
-         function(err, createdOne, createdTwo) {
-           assert.ifError(err);
-           var query = BlogPost.find({title: 'interoperable find as promise'}).sort('_id');
-           query.exec(function(err, found) {
-             db.close();
-             assert.ifError(err);
-             assert.equal(found.length, 2);
-             var ids = {};
-             ids[String(found[0]._id)] = 1;
-             ids[String(found[1]._id)] = 1;
-             assert.ok(String(createdOne._id) in ids);
-             assert.ok(String(createdTwo._id) in ids);
-             done();
-           });
-         });
-    });
-
-    it('remove()', function(done) {
+          {title: 'interoperable find as promise'},
+          function (err, createdOne, createdTwo) {
+            assert.ifError(err);
+            var query = BlogPost.find({title: 'interoperable find as promise'}).sort('_id');
+            query.exec(function (err, found) {
+              db.close();
+              assert.ifError(err);
+              assert.equal(found.length, 2);
+              var ids = {};
+              ids[String(found[0]._id)] = 1;
+              ids[String(found[1]._id)] = 1;
+              assert.ok(String(createdOne._id) in ids);
+              assert.ok(String(createdTwo._id) in ids);
+              done();
+            });
+          });
+    });
+
+    it('remove()', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema);
 
       BlogPost.create(
           {title: 'interoperable remove as promise'},
-         function(err) {
-           assert.ifError(err);
-           var query = BlogPost.remove({title: 'interoperable remove as promise'});
-           query.exec(function(err) {
-             assert.ifError(err);
-             BlogPost.count({title: 'interoperable remove as promise'}, function(err, count) {
-               db.close();
-               assert.equal(count, 0);
-               done();
-             });
-           });
-         });
-    });
-
-    it('op can be changed', function(done) {
+          function (err) {
+            assert.ifError(err);
+            var query = BlogPost.remove({title: 'interoperable remove as promise'});
+            query.exec(function (err) {
+              assert.ifError(err);
+              BlogPost.count({title: 'interoperable remove as promise'}, function (err, count) {
+                db.close();
+                assert.equal(count, 0);
+                done();
+              });
+            });
+          });
+    });
+
+    it('op can be changed', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema),
           title = 'interop ad-hoc as promise';
 
-      BlogPost.create({title: title }, function(err, created) {
+      BlogPost.create({title: title}, function (err, created) {
         assert.ifError(err);
-        var query = BlogPost.count({title: title });
-        query.exec('findOne', function(err, found) {
+        var query = BlogPost.count({title: title});
+        query.exec('findOne', function (err, found) {
           db.close();
           assert.ifError(err);
-          assert.equal(found.id,created.id);
+          assert.equal(found.id, created.id);
           done();
         });
       });
     });
 
-    describe('promises', function() {
-      it('count()', function(done) {
+    describe('promises', function () {
+      it('count()', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-        BlogPost.create({title: 'interoperable count as promise 2'}, function(err) {
+        BlogPost.create({title: 'interoperable count as promise 2'}, function (err) {
           assert.ifError(err);
           var query = BlogPost.count({title: 'interoperable count as promise 2'});
           var promise = query.exec();
-          promise.onResolve(function(err, count) {
+          promise.onResolve(function (err, count) {
             db.close();
             assert.ifError(err);
             assert.equal(1, count);
@@ -4014,18 +4020,18 @@ describe('Model', function() {
         });
       });
 
-      it('update()', function(done) {
+      it('update()', function (done) {
         var col = 'BlogPost' + random();
         var db = start(),
             BlogPost = db.model(col, bpSchema);
 
-        BlogPost.create({title: 'interoperable update as promise 2'}, function(err) {
+        BlogPost.create({title: 'interoperable update as promise 2'}, function (err) {
           assert.ifError(err);
           var query = BlogPost.update({title: 'interoperable update as promise 2'}, {title: 'interoperable update as promise delta 2'});
           var promise = query.exec();
-          promise.onResolve(function(err) {
+          promise.onResolve(function (err) {
             assert.ifError(err);
-            BlogPost.count({title: 'interoperable update as promise delta 2'}, function(err, count) {
+            BlogPost.count({title: 'interoperable update as promise delta 2'}, function (err, count) {
               db.close();
               assert.ifError(err);
               assert.equal(1, count);
@@ -4035,127 +4041,127 @@ describe('Model', function() {
         });
       });
 
-      it('findOne()', function(done) {
+      it('findOne()', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-        BlogPost.create({title: 'interoperable findOne as promise 2'}, function(err, created) {
+        BlogPost.create({title: 'interoperable findOne as promise 2'}, function (err, created) {
           assert.ifError(err);
           var query = BlogPost.findOne({title: 'interoperable findOne as promise 2'});
           var promise = query.exec();
-          promise.onResolve(function(err, found) {
+          promise.onResolve(function (err, found) {
             db.close();
             assert.ifError(err);
-            assert.equal(found.id,created.id);
+            assert.equal(found.id, created.id);
             done();
           });
         });
       });
 
-      it('find()', function(done) {
+      it('find()', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
         BlogPost.create(
             {title: 'interoperable find as promise 2'},
-           {title: 'interoperable find as promise 2'},
-           function(err, createdOne, createdTwo) {
-             assert.ifError(err);
-             var query = BlogPost.find({title: 'interoperable find as promise 2'}).sort('_id');
-             var promise = query.exec();
-             promise.onResolve(function(err, found) {
-               db.close();
-               assert.ifError(err);
-               assert.equal(found.length,2);
-               assert.equal(found[0].id,createdOne.id);
-               assert.equal(found[1].id,createdTwo.id);
-               done();
-             });
-           });
-      });
-
-      it('remove()', function(done) {
+            {title: 'interoperable find as promise 2'},
+            function (err, createdOne, createdTwo) {
+              assert.ifError(err);
+              var query = BlogPost.find({title: 'interoperable find as promise 2'}).sort('_id');
+              var promise = query.exec();
+              promise.onResolve(function (err, found) {
+                db.close();
+                assert.ifError(err);
+                assert.equal(found.length, 2);
+                assert.equal(found[0].id, createdOne.id);
+                assert.equal(found[1].id, createdTwo.id);
+                done();
+              });
+            });
+      });
+
+      it('remove()', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
         BlogPost.create(
             {title: 'interoperable remove as promise 2'},
-           function(err) {
-             assert.ifError(err);
-             var query = BlogPost.remove({title: 'interoperable remove as promise 2'});
-             var promise = query.exec();
-             promise.onResolve(function(err) {
-               assert.ifError(err);
-               BlogPost.count({title: 'interoperable remove as promise 2'}, function(err, count) {
-                 db.close();
-                 assert.equal(count,0);
-                 done();
-               });
-             });
-           });
-      });
-
-      it('are compatible with op modification on the fly', function(done) {
+            function (err) {
+              assert.ifError(err);
+              var query = BlogPost.remove({title: 'interoperable remove as promise 2'});
+              var promise = query.exec();
+              promise.onResolve(function (err) {
+                assert.ifError(err);
+                BlogPost.count({title: 'interoperable remove as promise 2'}, function (err, count) {
+                  db.close();
+                  assert.equal(count, 0);
+                  done();
+                });
+              });
+            });
+      });
+
+      it('are compatible with op modification on the fly', function (done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-        BlogPost.create({title: 'interoperable ad-hoc as promise 2'}, function(err, created) {
+        BlogPost.create({title: 'interoperable ad-hoc as promise 2'}, function (err, created) {
           assert.ifError(err);
           var query = BlogPost.count({title: 'interoperable ad-hoc as promise 2'});
           var promise = query.exec('findOne');
-          promise.onResolve(function(err, found) {
+          promise.onResolve(function (err, found) {
             db.close();
             assert.ifError(err);
-            assert.equal(found._id.id,created._id.id);
+            assert.equal(found._id.id, created._id.id);
             done();
           });
         });
       });
 
-      it('are thenable', function(done) {
+      it('are thenable', function (done) {
         var db = start(),
             B = db.model('BlogPost' + random(), bpSchema);
 
-        var peopleSchema = Schema({ name: String, likes: ['ObjectId'] });
+        var peopleSchema = Schema({name: String, likes: ['ObjectId']});
         var P = db.model('promise-BP-people', peopleSchema, random());
         B.create(
-            { title: 'then promise 1' },
-           { title: 'then promise 2' },
-           { title: 'then promise 3' },
-           function(err, d1, d2, d3) {
-             assert.ifError(err);
-
-             P.create(
-              { name: 'brandon', likes: [d1] },
-             { name: 'ben', likes: [d2] },
-             { name: 'bernie', likes: [d3] },
-             function(err) {
-               assert.ifError(err);
-
-               var promise = B.find({ title: /^then promise/ }).select('_id').exec();
-               promise.then(function(blogs) {
-                 var ids = blogs.map(function(m) {
-                   return m._id;
-                 });
-                 return P.where('likes').in(ids).exec();
-               }).then(function(people) {
-                 assert.equal(3, people.length);
-                 return people;
-               }).then(function() {
-                 db.close();
-                 done();
-               }, function(err) {
-                 db.close();
-                 done(new Error(err));
-               });
-             });
-           });
+            {title: 'then promise 1'},
+            {title: 'then promise 2'},
+            {title: 'then promise 3'},
+            function (err, d1, d2, d3) {
+              assert.ifError(err);
+
+              P.create(
+                  {name: 'brandon', likes: [d1]},
+                  {name: 'ben', likes: [d2]},
+                  {name: 'bernie', likes: [d3]},
+                  function (err) {
+                    assert.ifError(err);
+
+                    var promise = B.find({title: /^then promise/}).select('_id').exec();
+                    promise.then(function (blogs) {
+                      var ids = blogs.map(function (m) {
+                        return m._id;
+                      });
+                      return P.where('likes').in(ids).exec();
+                    }).then(function (people) {
+                      assert.equal(3, people.length);
+                      return people;
+                    }).then(function () {
+                      db.close();
+                      done();
+                    }, function (err) {
+                      db.close();
+                      done(new Error(err));
+                    });
+                  });
+            });
       });
     });
   });
 
-  describe('console.log', function() {
-    it('hides private props', function(done) {
+  describe('console.log', function () {
+    it('hides private props', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -4169,12 +4175,12 @@ describe('Model', function() {
         title: 'Test',
         _id: id0,
         date: date,
-        numbers: [5,6,7],
+        numbers: [5, 6, 7],
         owners: [id1],
-        meta: { visitors: 45 },
+        meta: {visitors: 45},
         comments: [
-            { _id: id2, title: 'my comment', date: date, body: 'this is a comment' },
-            { _id: id3, title: 'the next thang', date: date, body: 'this is a comment too!' }]
+          {_id: id2, title: 'my comment', date: date, body: 'this is a comment'},
+          {_id: id3, title: 'the next thang', date: date, body: 'this is a comment too!'}]
       });
 
       db.close();
@@ -4189,15 +4195,15 @@ describe('Model', function() {
     });
   });
 
-  describe('pathnames', function() {
-    it('named path can be used', function(done) {
+  describe('pathnames', function () {
+    it('named path can be used', function (done) {
       var db = start(),
-          P = db.model('pathnametest', new Schema({ path: String }));
+          P = db.model('pathnametest', new Schema({path: String}));
       db.close();
 
       var threw = false;
       try {
-        new P({ path: 'i should not throw' });
+        new P({path: 'i should not throw'});
       } catch (err) {
         threw = true;
       }
@@ -4207,25 +4213,25 @@ describe('Model', function() {
     });
   });
 
-  describe('auto_reconnect', function() {
-    describe('if disabled', function() {
-      describe('with mongo down', function() {
-        it('and no command buffering should pass an error', function(done) {
-          var db = start({ db: { bufferMaxEntries: 0 } });
-          var schema = Schema({ type: String }, { bufferCommands: false });
+  describe('auto_reconnect', function () {
+    describe('if disabled', function () {
+      describe('with mongo down', function () {
+        it('and no command buffering should pass an error', function (done) {
+          var db = start({db: {bufferMaxEntries: 0}});
+          var schema = Schema({type: String}, {bufferCommands: false});
           var T = db.model('Thing', schema);
-          db.on('open', function() {
-            var t = new T({ type: "monster" });
+          db.on('open', function () {
+            var t = new T({type: 'monster'});
             var worked = false;
 
-            t.save(function(err) {
+            t.save(function (err) {
               assert.ok(/(operation|destroyed)/.test(err.message));
               worked = true;
             });
 
             db.db.close();
 
-            setTimeout(function() {
+            setTimeout(function () {
               assert.ok(worked);
               done();
             }, 100);
@@ -4235,51 +4241,51 @@ describe('Model', function() {
     });
   });
 
-  it('subdocuments with changed values should persist the values', function(done) {
+  it('subdocuments with changed values should persist the values', function (done) {
     var db = start();
-    var Subdoc = new Schema({ name: String, mixed: Schema.Types.Mixed });
-    var T = db.model('SubDocMixed', new Schema({ subs: [Subdoc] }));
+    var Subdoc = new Schema({name: String, mixed: Schema.Types.Mixed});
+    var T = db.model('SubDocMixed', new Schema({subs: [Subdoc]}));
 
-    var t = new T({ subs: [{ name: "Hubot", mixed: { w: 1, x: 2 }}] });
-    assert.equal(t.subs[0].name,"Hubot");
-    assert.equal(t.subs[0].mixed.w,1);
-    assert.equal(t.subs[0].mixed.x,2);
+    var t = new T({subs: [{name: 'Hubot', mixed: {w: 1, x: 2}}]});
+    assert.equal(t.subs[0].name, 'Hubot');
+    assert.equal(t.subs[0].mixed.w, 1);
+    assert.equal(t.subs[0].mixed.x, 2);
 
-    t.save(function(err) {
+    t.save(function (err) {
       assert.ifError(err);
 
-      T.findById(t._id, function(err, t) {
+      T.findById(t._id, function (err, t) {
         assert.ifError(err);
-        assert.equal(t.subs[0].name,"Hubot");
-        assert.equal(t.subs[0].mixed.w,1);
-        assert.equal(t.subs[0].mixed.x,2);
+        assert.equal(t.subs[0].name, 'Hubot');
+        assert.equal(t.subs[0].mixed.w, 1);
+        assert.equal(t.subs[0].mixed.x, 2);
 
         var sub = t.subs[0];
-        sub.name = "Hubot1";
-        assert.equal(sub.name,"Hubot1");
+        sub.name = 'Hubot1';
+        assert.equal(sub.name, 'Hubot1');
         assert.ok(sub.isModified('name'));
         assert.ok(t.isModified());
 
-        t.save(function(err) {
+        t.save(function (err) {
           assert.ifError(err);
 
-          T.findById(t._id, function(err, t) {
+          T.findById(t._id, function (err, t) {
             assert.ifError(err);
-            assert.strictEqual(t.subs[0].name, "Hubot1");
+            assert.strictEqual(t.subs[0].name, 'Hubot1');
 
             var sub = t.subs[0];
             sub.mixed.w = 5;
-            assert.equal(sub.mixed.w,5);
+            assert.equal(sub.mixed.w, 5);
             assert.ok(!sub.isModified('mixed'));
             sub.markModified('mixed');
             assert.ok(sub.isModified('mixed'));
             assert.ok(sub.isModified());
             assert.ok(t.isModified());
 
-            t.save(function(err) {
+            t.save(function (err) {
               assert.ifError(err);
 
-              T.findById(t._id, function(err, t) {
+              T.findById(t._id, function (err, t) {
                 db.close();
                 assert.ifError(err);
                 assert.strictEqual(t.subs[0].mixed.w, 5);
@@ -4292,21 +4298,21 @@ describe('Model', function() {
     });
   });
 
-  describe('RegExps', function() {
-    it('can be saved', function(done) {
+  describe('RegExps', function () {
+    it('can be saved', function (done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
-      var post = new BlogPost({ mixed: { rgx: /^asdf$/ } });
+      var post = new BlogPost({mixed: {rgx: /^asdf$/}});
       assert.ok(post.mixed.rgx instanceof RegExp);
-      assert.equal(post.mixed.rgx.source,'^asdf$');
-      post.save(function(err) {
+      assert.equal(post.mixed.rgx.source, '^asdf$');
+      post.save(function (err) {
         assert.ifError(err);
-        BlogPost.findById(post._id, function(err, post) {
+        BlogPost.findById(post._id, function (err, post) {
           db.close();
           assert.ifError(err);
           assert.ok(post.mixed.rgx instanceof RegExp);
-          assert.equal(post.mixed.rgx.source,'^asdf$');
+          assert.equal(post.mixed.rgx.source, '^asdf$');
           done();
         });
       });
@@ -4314,42 +4320,42 @@ describe('Model', function() {
   });
 
   // Demonstration showing why GH-261 is a misunderstanding
-  it('a single instantiated document should be able to update its embedded documents more than once', function(done) {
+  it('a single instantiated document should be able to update its embedded documents more than once', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
     var post = new BlogPost();
     post.comments.push({title: 'one'});
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
-      assert.equal(post.comments[0].title,'one');
+      assert.equal(post.comments[0].title, 'one');
       post.comments[0].title = 'two';
-      assert.equal(post.comments[0].title,'two');
-      post.save(function(err) {
+      assert.equal(post.comments[0].title, 'two');
+      post.save(function (err) {
         assert.ifError(err);
-        BlogPost.findById(post._id, function(err, found) {
+        BlogPost.findById(post._id, function (err, found) {
           db.close();
           assert.ifError(err);
-          assert.equal(found.comments[0].title,'two');
+          assert.equal(found.comments[0].title, 'two');
           done();
         });
       });
     });
   });
 
-  describe('save()', function() {
-    describe('when no callback is passed', function() {
-      it('should emit error on its Model when there are listeners', function(done) {
+  describe('save()', function () {
+    describe('when no callback is passed', function () {
+      it('should emit error on its Model when there are listeners', function (done) {
         var db = start();
 
         var DefaultErrSchema = new Schema({});
-        DefaultErrSchema.pre('save', function(next) {
+        DefaultErrSchema.pre('save', function (next) {
           next(new Error);
         });
 
         var DefaultErr = db.model('DefaultErr3', DefaultErrSchema, 'default_err_' + random());
 
-        DefaultErr.on('error', function(err) {
+        DefaultErr.on('error', function (err) {
           db.close();
           assert.ok(err instanceof Error);
           done();
@@ -4359,16 +4365,16 @@ describe('Model', function() {
       });
     });
 
-    it('returns number of affected docs', function(done) {
+    it('returns number of affected docs', function (done) {
       var db = start();
-      var schema = new Schema({ name: String });
+      var schema = new Schema({name: String});
       var S = db.model('AffectedDocsAreReturned', schema);
-      var s = new S({ name: 'aaron' });
-      s.save(function(err, doc, affected) {
+      var s = new S({name: 'aaron'});
+      s.save(function (err, doc, affected) {
         assert.ifError(err);
         assert.equal(1, affected);
         s.name = 'heckmanananananana';
-        s.save(function(err, doc, affected) {
+        s.save(function (err, doc, affected) {
           db.close();
           assert.ifError(err);
           assert.equal(1, affected);
@@ -4377,18 +4383,18 @@ describe('Model', function() {
       });
     });
 
-    it('returns 0 as the number of affected docs if doc was not modified', function(done) {
+    it('returns 0 as the number of affected docs if doc was not modified', function (done) {
       var db = start(),
-          schema = new Schema({ name: String }),
+          schema = new Schema({name: String}),
           Model = db.model('AffectedDocsAreReturned', schema),
-          doc = new Model({ name: 'aaron' });
+          doc = new Model({name: 'aaron'});
 
-      doc.save(function(err, doc, affected) {
+      doc.save(function (err, doc, affected) {
         assert.ifError(err);
         assert.equal(1, affected);
 
-        Model.findById(doc.id).then(function(doc) {
-          doc.save(function(err, doc, affected) {
+        Model.findById(doc.id).then(function (doc) {
+          doc.save(function (err, doc, affected) {
             db.close();
             assert.ifError(err);
             assert.equal(0, affected);
@@ -4398,23 +4404,23 @@ describe('Model', function() {
       });
     });
 
-    it('saved changes made within callback of a previous no-op save gh-1139', function(done) {
+    it('saved changes made within callback of a previous no-op save gh-1139', function (done) {
       var db = start(),
           B = db.model('BlogPost', collection);
 
-      var post = new B({ title: 'first' });
-      post.save(function(err) {
+      var post = new B({title: 'first'});
+      post.save(function (err) {
         assert.ifError(err);
 
         // no op
-        post.save(function(err) {
+        post.save(function (err) {
           assert.ifError(err);
 
           post.title = 'changed';
-          post.save(function(err) {
+          post.save(function (err) {
             assert.ifError(err);
 
-            B.findById(post, function(err, doc) {
+            B.findById(post, function (err, doc) {
               assert.ifError(err);
               assert.equal('changed', doc.title);
               db.close(done);
@@ -4424,12 +4430,12 @@ describe('Model', function() {
       });
     });
 
-    it('rejects new documents that have no _id set (1595)', function(done) {
+    it('rejects new documents that have no _id set (1595)', function (done) {
       var db = start();
-      var s = new Schema({ _id: { type: String }});
+      var s = new Schema({_id: {type: String}});
       var B = db.model('1595', s);
       var b = new B;
-      b.save(function(err) {
+      b.save(function (err) {
         db.close();
         assert.ok(err);
         assert.ok(/must have an _id/.test(err));
@@ -4439,16 +4445,16 @@ describe('Model', function() {
   });
 
 
-  describe('_delta()', function() {
-    it('should overwrite arrays when directly set (gh-1126)', function(done) {
+  describe('_delta()', function () {
+    it('should overwrite arrays when directly set (gh-1126)', function (done) {
       var db = start(),
           B = db.model('BlogPost', collection);
 
-      B.create({ title: 'gh-1126', numbers: [1,2] }, function(err, b) {
+      B.create({title: 'gh-1126', numbers: [1, 2]}, function (err, b) {
         assert.ifError(err);
-        B.findById(b._id, function(err, b) {
+        B.findById(b._id, function (err, b) {
           assert.ifError(err);
-          assert.deepEqual([1,2].join(), b.numbers.join());
+          assert.deepEqual([1, 2].join(), b.numbers.join());
 
           b.numbers = [];
           b.numbers.push(3);
@@ -4459,10 +4465,10 @@ describe('Model', function() {
           assert.equal(d.$set.numbers.length, 1);
           assert.equal(d.$set.numbers[0], 3);
 
-          b.save(function(err) {
+          b.save(function (err) {
             assert.ifError(err);
 
-            B.findById(b._id, function(err, b) {
+            B.findById(b._id, function (err, b) {
               assert.ifError(err);
               assert.ok(Array.isArray(b.numbers));
               assert.equal(1, b.numbers.length);
@@ -4474,9 +4480,9 @@ describe('Model', function() {
 
               b.numbers = [4];
               b.numbers.push(5);
-              b.save(function(err) {
+              b.save(function (err) {
                 assert.ifError(err);
-                B.findById(b._id, function(err, b) {
+                B.findById(b._id, function (err, b) {
                   assert.ifError(err);
                   assert.ok(Array.isArray(b.numbers));
                   assert.equal(2, b.numbers.length);
@@ -4491,55 +4497,54 @@ describe('Model', function() {
       });
     });
 
-    it('should use $set when subdoc changed before pulling (gh-1303)', function(done) {
+    it('should use $set when subdoc changed before pulling (gh-1303)', function (done) {
       var db = start(),
           B = db.model('BlogPost', 'gh-1303-' + random());
 
       B.create(
-          { title: 'gh-1303', comments: [{body:'a'},{body:'b'},{body:'c'}] },
-         function(err, b) {
-
-           assert.ifError(err);
-           B.findById(b._id, function(err, b) {
-             assert.ifError(err);
-
-             b.comments[2].body = 'changed';
-             b.comments.pull(b.comments[1]);
-
-             assert.equal(2, b.comments.length);
-             assert.equal('a', b.comments[0].body);
-             assert.equal('changed', b.comments[1].body);
-
-             var d = b.$__delta()[1];
-             assert.ok('$set' in d, 'invalid delta ' + JSON.stringify(d));
-             assert.ok(Array.isArray(d.$set.comments));
-             assert.equal(d.$set.comments.length, 2);
-
-             b.save(function(err) {
-               assert.ifError(err);
-
-               B.findById(b._id, function(err, b) {
-                 db.close();
-                 assert.ifError(err);
-                 assert.ok(Array.isArray(b.comments));
-                 assert.equal(2, b.comments.length);
-                 assert.equal('a', b.comments[0].body);
-                 assert.equal('changed', b.comments[1].body);
-                 done();
-               });
-             });
-           });
-         });
+          {title: 'gh-1303', comments: [{body: 'a'}, {body: 'b'}, {body: 'c'}]},
+          function (err, b) {
+            assert.ifError(err);
+            B.findById(b._id, function (err, b) {
+              assert.ifError(err);
+
+              b.comments[2].body = 'changed';
+              b.comments.pull(b.comments[1]);
+
+              assert.equal(2, b.comments.length);
+              assert.equal('a', b.comments[0].body);
+              assert.equal('changed', b.comments[1].body);
+
+              var d = b.$__delta()[1];
+              assert.ok('$set' in d, 'invalid delta ' + JSON.stringify(d));
+              assert.ok(Array.isArray(d.$set.comments));
+              assert.equal(d.$set.comments.length, 2);
+
+              b.save(function (err) {
+                assert.ifError(err);
+
+                B.findById(b._id, function (err, b) {
+                  db.close();
+                  assert.ifError(err);
+                  assert.ok(Array.isArray(b.comments));
+                  assert.equal(2, b.comments.length);
+                  assert.equal('a', b.comments[0].body);
+                  assert.equal('changed', b.comments[1].body);
+                  done();
+                });
+              });
+            });
+          });
     });
   });
 
-  describe('backward compatibility', function() {
-    it('with conflicted data in db', function(done) {
+  describe('backward compatibility', function () {
+    it('with conflicted data in db', function (done) {
       var db = start();
-      var M = db.model('backwardDataConflict', new Schema({ namey: { first: String, last: String }}));
-      var m = new M({ namey: "[object Object]" });
-      m.namey = { first: 'GI', last: 'Joe' };// <-- should overwrite the string
-      m.save(function(err) {
+      var M = db.model('backwardDataConflict', new Schema({namey: {first: String, last: String}}));
+      var m = new M({namey: '[object Object]'});
+      m.namey = {first: 'GI', last: 'Joe'};// <-- should overwrite the string
+      m.save(function (err) {
         db.close();
         assert.strictEqual(err, null);
         assert.strictEqual('GI', m.namey.first);
@@ -4548,23 +4553,23 @@ describe('Model', function() {
       });
     });
 
-    it('with positional notation on path not existing in schema (gh-1048)', function(done) {
+    it('with positional notation on path not existing in schema (gh-1048)', function (done) {
       var db = start();
 
-      var M = db.model('backwardCompat-gh-1048', Schema({ name: 'string' }));
-      db.on('open', function() {
+      var M = db.model('backwardCompat-gh-1048', Schema({name: 'string'}));
+      db.on('open', function () {
         var o = {
           name: 'gh-1048',
           _id: new mongoose.Types.ObjectId,
           databases: {
-            0: { keys: 100, expires: 0},
-            15: {keys:1,expires:0}
+            0: {keys: 100, expires: 0},
+            15: {keys: 1, expires: 0}
           }
         };
 
-        M.collection.insert(o, { safe: true }, function(err) {
+        M.collection.insert(o, {safe: true}, function (err) {
           assert.ifError(err);
-          M.findById(o._id, function(err, doc) {
+          M.findById(o._id, function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.ok(doc);
@@ -4579,16 +4584,16 @@ describe('Model', function() {
     });
   });
 
-  describe('non-schema adhoc property assignments', function() {
-    it('are not saved', function(done) {
+  describe('non-schema adhoc property assignments', function () {
+    it('are not saved', function (done) {
       var db = start(),
           B = db.model('BlogPost', collection);
 
       var b = new B;
       b.whateveriwant = 10;
-      b.save(function(err) {
+      b.save(function (err) {
         assert.ifError(err);
-        B.collection.findOne({ _id: b._id }, function(err, doc) {
+        B.collection.findOne({_id: b._id}, function (err, doc) {
           db.close();
           assert.ifError(err);
           assert.ok(!('whateveriwant' in doc));
@@ -4598,19 +4603,19 @@ describe('Model', function() {
     });
   });
 
-  it('should not throw range error when using Number _id and saving existing doc (gh-691)', function(done) {
+  it('should not throw range error when using Number _id and saving existing doc (gh-691)', function (done) {
     var db = start();
-    var T = new Schema({ _id: Number, a: String });
+    var T = new Schema({_id: Number, a: String});
     var D = db.model('Testing691', T, 'asdf' + random());
-    var d = new D({ _id: 1 });
-    d.save(function(err) {
+    var d = new D({_id: 1});
+    d.save(function (err) {
       assert.ifError(err);
 
-      D.findById(d._id, function(err, d) {
+      D.findById(d._id, function (err, d) {
         assert.ifError(err);
 
         d.a = 'yo';
-        d.save(function(err) {
+        d.save(function (err) {
           db.close();
           assert.ifError(err);
           done();
@@ -4619,34 +4624,34 @@ describe('Model', function() {
     });
   });
 
-  describe('setting an unset value', function() {
-    it('is saved (gh-742)', function(done) {
+  describe('setting an unset value', function () {
+    it('is saved (gh-742)', function (done) {
       var db = start();
 
-      var DefaultTestObject = db.model("defaultTestObject",
-        new Schema({
-          score:{type:Number, "default":55}
-        })
+      var DefaultTestObject = db.model('defaultTestObject',
+          new Schema({
+            score: {type: Number, 'default': 55}
+          })
       );
 
       var myTest = new DefaultTestObject();
 
-      myTest.save(function(err, doc) {
+      myTest.save(function (err, doc) {
         assert.ifError(err);
         assert.equal(doc.score, 55);
 
-        DefaultTestObject.findById(doc._id, function(err, doc) {
+        DefaultTestObject.findById(doc._id, function (err, doc) {
           assert.ifError(err);
 
           doc.score = undefined; // unset
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
 
-            DefaultTestObject.findById(doc._id, function(err, doc) {
+            DefaultTestObject.findById(doc._id, function (err, doc) {
               assert.ifError(err);
 
               doc.score = 55;
-              doc.save(function(err, doc, count) {
+              doc.save(function (err, doc, count) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(doc.score, 55);
@@ -4660,13 +4665,13 @@ describe('Model', function() {
     });
   });
 
-  it('path is cast to correct value when retreived from db', function(done) {
+  it('path is cast to correct value when retreived from db', function (done) {
     var db = start();
-    var schema = new Schema({ title: { type: 'string', index: true }});
+    var schema = new Schema({title: {type: 'string', index: true}});
     var T = db.model('T', schema);
-    T.collection.insert({ title: 234 }, {safe:true}, function(err) {
+    T.collection.insert({title: 234}, {safe: true}, function (err) {
       assert.ifError(err);
-      T.findOne(function(err, doc) {
+      T.findOne(function (err, doc) {
         db.close();
         assert.ifError(err);
         assert.equal('234', doc.title);
@@ -4675,47 +4680,47 @@ describe('Model', function() {
     });
   });
 
-  it('setting a path to undefined should retain the value as undefined', function(done) {
+  it('setting a path to undefined should retain the value as undefined', function (done) {
     var db = start(),
         B = db.model('BlogPost', collection + random());
 
     var doc = new B;
     doc.title = 'css3';
-    assert.equal(doc.$__delta()[1].$set.title,'css3');
+    assert.equal(doc.$__delta()[1].$set.title, 'css3');
     doc.title = undefined;
-    assert.equal(doc.$__delta()[1].$unset.title,1);
+    assert.equal(doc.$__delta()[1].$unset.title, 1);
     assert.strictEqual(undefined, doc.$__delta()[1].$set.title);
 
     doc.title = 'css3';
     doc.author = 'aaron';
-    doc.numbers = [3,4,5];
+    doc.numbers = [3, 4, 5];
     doc.meta.date = new Date;
     doc.meta.visitors = 89;
-    doc.comments = [{ title: 'thanksgiving', body: 'yuuuumm' }];
-    doc.comments.push({ title: 'turkey', body: 'cranberries' });
+    doc.comments = [{title: 'thanksgiving', body: 'yuuuumm'}];
+    doc.comments.push({title: 'turkey', body: 'cranberries'});
 
-    doc.save(function(err) {
+    doc.save(function (err) {
       assert.ifError(err);
-      B.findById(doc._id, function(err, b) {
+      B.findById(doc._id, function (err, b) {
         assert.ifError(err);
-        assert.equal(b.title,'css3');
-        assert.equal(b.author,'aaron');
+        assert.equal(b.title, 'css3');
+        assert.equal(b.author, 'aaron');
         assert.equal(b.meta.date.toString(), doc.meta.date.toString());
         assert.equal(b.meta.visitors.valueOf(), doc.meta.visitors.valueOf());
         assert.equal(2, b.comments.length);
         assert.equal(b.comments[0].title, 'thanksgiving');
         assert.equal(b.comments[0].body, 'yuuuumm');
-        assert.equal(b.comments[1].title,'turkey');
-        assert.equal(b.comments[1].body,'cranberries');
+        assert.equal(b.comments[1].title, 'turkey');
+        assert.equal(b.comments[1].body, 'cranberries');
         b.title = undefined;
         b.author = null;
         b.meta.date = undefined;
         b.meta.visitors = null;
         b.comments[0].title = null;
         b.comments[0].body = undefined;
-        b.save(function(err) {
+        b.save(function (err) {
           assert.ifError(err);
-          B.findById(b._id, function(err, b) {
+          B.findById(b._id, function (err, b) {
             assert.ifError(err);
             assert.strictEqual(undefined, b.title);
             assert.strictEqual(null, b.author);
@@ -4724,14 +4729,14 @@ describe('Model', function() {
             assert.strictEqual(null, b.meta.visitors);
             assert.strictEqual(null, b.comments[0].title);
             assert.strictEqual(undefined, b.comments[0].body);
-            assert.equal(b.comments[1].title,'turkey');
-            assert.equal(b.comments[1].body,'cranberries');
+            assert.equal(b.comments[1].title, 'turkey');
+            assert.equal(b.comments[1].body, 'cranberries');
 
             b.meta = undefined;
             b.comments = undefined;
-            b.save(function(err) {
+            b.save(function (err) {
               assert.ifError(err);
-              B.collection.findOne({ _id: b._id}, function(err, b) {
+              B.collection.findOne({_id: b._id}, function (err, b) {
                 db.close();
                 assert.ifError(err);
                 assert.strictEqual(undefined, b.meta);
@@ -4745,13 +4750,13 @@ describe('Model', function() {
     });
   });
 
-  describe('unsetting a default value', function() {
-    it('should be ignored (gh-758)', function(done) {
+  describe('unsetting a default value', function () {
+    it('should be ignored (gh-758)', function (done) {
       var db = start();
-      var M = db.model('758', new Schema({ s: String, n: Number, a: Array }));
-      M.collection.insert({ }, { safe: true }, function(err) {
+      var M = db.model('758', new Schema({s: String, n: Number, a: Array}));
+      M.collection.insert({}, {safe: true}, function (err) {
         assert.ifError(err);
-        M.findOne(function(err, m) {
+        M.findOne(function (err, m) {
           assert.ifError(err);
           m.s = m.n = m.a = undefined;
           assert.equal(undefined, m.$__delta());
@@ -4761,20 +4766,20 @@ describe('Model', function() {
     });
   });
 
-  it('allow for object passing to ref paths (gh-1606)', function(done) {
+  it('allow for object passing to ref paths (gh-1606)', function (done) {
     var db = start();
-    var schA = new Schema({ title: String });
+    var schA = new Schema({title: String});
     var schma = new Schema({
-      thing: { type: Schema.Types.ObjectId, ref: 'A' },
+      thing: {type: Schema.Types.ObjectId, ref: 'A'},
       subdoc: {
         some: String,
-        thing: [{ type: Schema.Types.ObjectId, ref: 'A' }]
+        thing: [{type: Schema.Types.ObjectId, ref: 'A'}]
       }
     });
 
     var M1 = db.model('A', schA);
     var M2 = db.model('A2', schma);
-    var a = new M1({ title: 'hihihih' }).toObject();
+    var a = new M1({title: 'hihihih'}).toObject();
     var thing = new M2({
       thing: a,
       subdoc: {
@@ -4789,7 +4794,7 @@ describe('Model', function() {
     db.close(done);
   });
 
-  it('setters trigger on null values (gh-1445)', function(done) {
+  it('setters trigger on null values (gh-1445)', function (done) {
     var db = start();
     db.close();
 
@@ -4797,7 +4802,7 @@ describe('Model', function() {
       total: {
         type: Number,
         default: 0,
-        set: function(value) {
+        set: function (value) {
           assert.strictEqual(null, value);
           return 10;
         }
@@ -4805,14 +4810,13 @@ describe('Model', function() {
     });
 
     var Order = db.model('order' + random(), OrderSchema);
-    var o = new Order({ total: null });
+    var o = new Order({total: null});
     assert.equal(o.total, 10);
     done();
   });
 
-  describe('Skip setting default value for Geospatial-indexed fields (gh-1668)', function() {
-
-    it('2dsphere indexed field with value is saved', function(done) {
+  describe('Skip setting default value for Geospatial-indexed fields (gh-1668)', function () {
+    it('2dsphere indexed field with value is saved', function (done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -4823,16 +4827,16 @@ describe('Model', function() {
       });
 
       var Person = db.model('Person_1', PersonSchema);
-      var loc = [ 0.3, 51.4 ];
+      var loc = [0.3, 51.4];
       var p = new Person({
         name: 'Jimmy Page',
         loc: loc
       });
 
-      p.save(function(err) {
+      p.save(function (err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function(err, personDoc) {
+        Person.findById(p._id, function (err, personDoc) {
           assert.ifError(err);
 
           assert.equal(personDoc.loc[0], loc[0]);
@@ -4843,7 +4847,7 @@ describe('Model', function() {
       });
     });
 
-    it('2dsphere indexed field without value is saved (gh-1668)', function(done) {
+    it('2dsphere indexed field without value is saved (gh-1668)', function (done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -4858,10 +4862,10 @@ describe('Model', function() {
         name: 'Jimmy Page'
       });
 
-      p.save(function(err) {
+      p.save(function (err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function(err, personDoc) {
+        Person.findById(p._id, function (err, personDoc) {
           assert.ifError(err);
 
           assert.equal(personDoc.name, 'Jimmy Page');
@@ -4872,10 +4876,10 @@ describe('Model', function() {
       });
     });
 
-    it('2dsphere indexed field in subdoc without value is saved', function(done) {
+    it('2dsphere indexed field in subdoc without value is saved', function (done) {
       var db = start();
       var PersonSchema = new Schema({
-        name: { type: String, required: true },
+        name: {type: String, required: true},
         nested: {
           tag: String,
           loc: {
@@ -4884,7 +4888,7 @@ describe('Model', function() {
         }
       });
 
-      PersonSchema.index({ 'nested.loc': '2dsphere' });
+      PersonSchema.index({'nested.loc': '2dsphere'});
 
       var Person = db.model('Person_3', PersonSchema);
       var p = new Person({
@@ -4893,10 +4897,10 @@ describe('Model', function() {
 
       p.nested.tag = 'guitarist';
 
-      p.save(function(err) {
+      p.save(function (err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function(err, personDoc) {
+        Person.findById(p._id, function (err, personDoc) {
           assert.ifError(err);
 
           assert.equal(personDoc.name, 'Jimmy Page');
@@ -4908,7 +4912,7 @@ describe('Model', function() {
       });
     });
 
-    it('Doc with 2dsphere indexed field without initial value can be updated', function(done) {
+    it('Doc with 2dsphere indexed field without initial value can be updated', function (done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -4923,16 +4927,16 @@ describe('Model', function() {
         name: 'Jimmy Page'
       });
 
-      p.save(function(err) {
+      p.save(function (err) {
         assert.ifError(err);
 
         var updates = {
           $set: {
-            loc: [ 0.3, 51.4 ]
+            loc: [0.3, 51.4]
           }
         };
 
-        Person.findByIdAndUpdate(p._id, updates, { 'new': true }, function(err, personDoc) {
+        Person.findByIdAndUpdate(p._id, updates, {'new': true}, function (err, personDoc) {
           assert.ifError(err);
 
           assert.equal(personDoc.loc[0], updates.$set.loc[0]);
@@ -4943,7 +4947,7 @@ describe('Model', function() {
       });
     });
 
-    it('2dsphere indexed required field without value is rejected', function(done) {
+    it('2dsphere indexed required field without value is rejected', function (done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -4959,7 +4963,7 @@ describe('Model', function() {
         name: 'Jimmy Page'
       });
 
-      p.save(function(err) {
+      p.save(function (err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         db.close();
@@ -4967,9 +4971,9 @@ describe('Model', function() {
       });
     });
 
-    it('2dsphere field without value but with schema default is saved', function(done) {
+    it('2dsphere field without value but with schema default is saved', function (done) {
       var db = start();
-      var loc = [ 0, 1 ];
+      var loc = [0, 1];
       var PersonSchema = new Schema({
         name: String,
         loc: {
@@ -4984,10 +4988,10 @@ describe('Model', function() {
         name: 'Jimmy Page'
       });
 
-      p.save(function(err) {
+      p.save(function (err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function(err, personDoc) {
+        Person.findById(p._id, function (err, personDoc) {
           assert.ifError(err);
 
           assert.equal(loc[0], personDoc.loc[0]);
@@ -4998,7 +5002,7 @@ describe('Model', function() {
       });
     });
 
-    it('2d indexed field without value is saved', function(done) {
+    it('2d indexed field without value is saved', function (done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -5013,10 +5017,10 @@ describe('Model', function() {
         name: 'Jimmy Page'
       });
 
-      p.save(function(err) {
+      p.save(function (err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function(err, personDoc) {
+        Person.findById(p._id, function (err, personDoc) {
           assert.ifError(err);
 
           assert.equal(undefined, personDoc.loc);
@@ -5026,30 +5030,30 @@ describe('Model', function() {
       });
     });
 
-    it('Compound index with 2dsphere field without value is saved', function(done) {
+    it('Compound index with 2dsphere field without value is saved', function (done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
         type: String,
-        slug: { type: String, index: { unique: true } },
-        loc:  { type: [Number] },
-        tags: { type: [String], index: true }
+        slug: {type: String, index: {unique: true}},
+        loc: {type: [Number]},
+        tags: {type: [String], index: true}
       });
 
-      PersonSchema.index({ name: 1, loc: '2dsphere' });
+      PersonSchema.index({name: 1, loc: '2dsphere'});
 
       var Person = db.model('Person_8', PersonSchema);
       var p = new Person({
         name: 'Jimmy Page',
         type: 'musician',
         slug: 'ledzep-1',
-        tags: [ 'guitarist' ]
+        tags: ['guitarist']
       });
 
-      p.save(function(err) {
+      p.save(function (err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function(err, personDoc) {
+        Person.findById(p._id, function (err, personDoc) {
           assert.ifError(err);
 
           assert.equal('Jimmy Page', personDoc.name);
@@ -5061,31 +5065,31 @@ describe('Model', function() {
     });
 
 
-    it('Compound index on field earlier declared with 2dsphere index is saved', function(done) {
+    it('Compound index on field earlier declared with 2dsphere index is saved', function (done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
         type: String,
-        slug: { type: String, index: { unique: true } },
-        loc:  { type: [Number] },
-        tags: { type: [String], index: true }
+        slug: {type: String, index: {unique: true}},
+        loc: {type: [Number]},
+        tags: {type: [String], index: true}
       });
 
-      PersonSchema.index({ loc: '2dsphere' });
-      PersonSchema.index({ name: 1, loc: -1 });
+      PersonSchema.index({loc: '2dsphere'});
+      PersonSchema.index({name: 1, loc: -1});
 
       var Person = db.model('Person_9', PersonSchema);
       var p = new Person({
         name: 'Jimmy Page',
         type: 'musician',
         slug: 'ledzep-1',
-        tags: [ 'guitarist' ]
+        tags: ['guitarist']
       });
 
-      p.save(function(err) {
+      p.save(function (err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function(err, personDoc) {
+        Person.findById(p._id, function (err, personDoc) {
           assert.ifError(err);
 
           assert.equal('Jimmy Page', personDoc.name);
@@ -5097,8 +5101,8 @@ describe('Model', function() {
     });
   });
 
-  describe('gh-1920', function() {
-    it('doesnt crash', function(done) {
+  describe('gh-1920', function () {
+    it('doesnt crash', function (done) {
       var db = start();
 
       var parentSchema = new Schema({
@@ -5111,10 +5115,10 @@ describe('Model', function() {
 
       var parent = new Parent();
       parent.children.push({name: 'child name'});
-      parent.save(function(err, it) {
+      parent.save(function (err, it) {
         assert.ifError(err);
         parent.children.push({name: 'another child'});
-        Parent.findByIdAndUpdate(it._id, { $set: { children: parent.children } }, function(err) {
+        Parent.findByIdAndUpdate(it._id, {$set: {children: parent.children}}, function (err) {
           assert.ifError(err);
           db.close(done);
         });
@@ -5122,8 +5126,8 @@ describe('Model', function() {
     });
   });
 
-  describe('save failure', function() {
-    it('doesnt reset "modified" status for fields', function(done) {
+  describe('save failure', function () {
+    it('doesnt reset "modified" status for fields', function (done) {
       var db = start();
 
       var UniqueSchema = new Schema({
@@ -5138,25 +5142,25 @@ describe('Model', function() {
 
       var u1 = new Unique({
         changer: 'a',
-        unique:  5
+        unique: 5
       });
 
       var u2 = new Unique({
         changer: 'a',
-        unique:  6
+        unique: 6
       });
 
-      Unique.on('index', function() {
-        u1.save(function(err) {
+      Unique.on('index', function () {
+        u1.save(function (err) {
           assert.ifError(err);
           assert.ok(!u1.isModified('changer'));
-          u2.save(function(err) {
+          u2.save(function (err) {
             assert.ifError(err);
             assert.ok(!u2.isModified('changer'));
             u2.changer = 'b';
             u2.unique = 5;
             assert.ok(u2.isModified('changer'));
-            u2.save(function(err) {
+            u2.save(function (err) {
               assert.ok(err);
               assert.ok(u2.isModified('changer'));
               db.close(done);
@@ -5167,16 +5171,16 @@ describe('Model', function() {
     });
   });
 
-  it('insertMany() (gh-723)', function(done) {
+  it('insertMany() (gh-723)', function (done) {
     var db = start();
-    var schema = new Schema({ name: String });
+    var schema = new Schema({name: String});
     var Movie = db.model('gh723', schema);
 
-    var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }];
-    Movie.insertMany(arr, function(error, docs) {
+    var arr = [{name: 'Star Wars'}, {name: 'The Empire Strikes Back'}];
+    Movie.insertMany(arr, function (error, docs) {
       assert.ifError(error);
       assert.equal(docs.length, 2);
-      Movie.find({}, function(error, docs) {
+      Movie.find({}, function (error, docs) {
         assert.ifError(error);
         assert.equal(docs.length, 2);
         done();
@@ -5184,13 +5188,13 @@ describe('Model', function() {
     });
   });
 
-  describe('gh-2442', function() {
-    it('marks array as modified when initializing non-array from db', function(done) {
+  describe('gh-2442', function () {
+    it('marks array as modified when initializing non-array from db', function (done) {
       var db = start();
 
       var s1 = new Schema({
         array: mongoose.Schema.Types.Mixed
-      }, { minimize: false });
+      }, {minimize: false});
 
       var s2 = new Schema({
         array: {
@@ -5208,16 +5212,16 @@ describe('Model', function() {
       var M1 = db.model('gh-2442-1', s1, 'gh-2442');
       var M2 = db.model('gh-2442-2', s2, 'gh-2442');
 
-      M1.create({ array: {} }, function(err, doc) {
+      M1.create({array: {}}, function (err, doc) {
         assert.ifError(err);
         assert.ok(doc.array);
-        M2.findOne({ _id: doc._id }, function(err, doc) {
+        M2.findOne({_id: doc._id}, function (err, doc) {
           assert.ifError(err);
           assert.equal(doc.array[0].value, 0);
           doc.array[0].value = 1;
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
-            M2.findOne({ _id: doc._id }, function(err, doc) {
+            M2.findOne({_id: doc._id}, function (err, doc) {
               assert.ifError(err);
               assert.ok(!doc.isModified('array'));
               assert.deepEqual(doc.array[0].value, 1);
diff --git a/test/model.update.test.js b/test/model.update.test.js
index f3005943487..61a2fdead47 100644
--- a/test/model.update.test.js
+++ b/test/model.update.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Test dependencies.
  */
@@ -38,23 +37,23 @@ var BlogPost = new Schema({
   numbers: [Number],
   owners: [ObjectId],
   comments: [Comments]
-}, { strict: false });
+}, {strict: false});
 
 BlogPost.virtual('titleWithAuthor')
-  .get(function() {
-    return this.get('title') + ' by ' + this.get('author');
-  })
-  .set(function(val) {
-    var split = val.split(' by ');
-    this.set('title', split[0]);
-    this.set('author', split[1]);
-  });
+.get(function () {
+  return this.get('title') + ' by ' + this.get('author');
+})
+.set(function (val) {
+  var split = val.split(' by ');
+  this.set('title', split[0]);
+  this.set('author', split[1]);
+});
 
-BlogPost.method('cool', function() {
+BlogPost.method('cool', function () {
   return this;
 });
 
-BlogPost.static('woot', function() {
+BlogPost.static('woot', function () {
   return this;
 });
 
@@ -62,14 +61,14 @@ mongoose.model('BlogPostForUpdates', BlogPost);
 
 var collection = 'blogposts_' + random();
 
-var strictSchema = new Schema({ name: String, x: { nested: String }});
-strictSchema.virtual('foo').get(function() {
+var strictSchema = new Schema({name: String, x: {nested: String}});
+strictSchema.virtual('foo').get(function () {
   return 'i am a virtual FOO!';
 });
 mongoose.model('UpdateStrictSchema', strictSchema);
 
 
-describe('model: update:', function() {
+describe('model: update:', function () {
   var post,
       title = 'Tobi ' + random(),
       author = 'Brian ' + random(),
@@ -77,7 +76,7 @@ describe('model: update:', function() {
       id0,
       id1;
 
-  before(function(done) {
+  before(function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -90,30 +89,30 @@ describe('model: update:', function() {
     post.meta.visitors = 0;
     post.date = new Date;
     post.published = true;
-    post.mixed = { x: 'ex' };
-    post.numbers = [4,5,6,7];
+    post.mixed = {x: 'ex'};
+    post.numbers = [4, 5, 6, 7];
     post.owners = [id0, id1];
-    post.comments = [{ body: 'been there' }, { body: 'done that' }];
+    post.comments = [{body: 'been there'}, {body: 'done that'}];
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
       db.close(done);
     });
   });
 
-  it('works', function(done) {
+  it('works', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    BlogPost.findById(post._id, function(err, cf) {
+    BlogPost.findById(post._id, function (err, cf) {
       assert.ifError(err);
       assert.equal(title, cf.title);
-      assert.equal(cf.author,author);
-      assert.equal(cf.meta.visitors.valueOf(),0);
+      assert.equal(cf.author, author);
+      assert.equal(cf.meta.visitors.valueOf(), 0);
       assert.equal(cf.date.toString(), post.date.toString());
       assert.equal(true, cf.published);
       assert.equal('ex', cf.mixed.x);
-      assert.deepEqual(cf.numbers.toObject(), [4,5,6,7]);
+      assert.deepEqual(cf.numbers.toObject(), [4, 5, 6, 7]);
       assert.equal(cf.owners.length, 2);
       assert.equal(cf.owners[0].toString(), id0.toString());
       assert.equal(cf.owners[1].toString(), id1.toString());
@@ -127,32 +126,32 @@ describe('model: update:', function() {
 
       var update = {
         title: newTitle, // becomes $set
-        $inc: { 'meta.visitors': 2 },
-        $set: { date: new Date },
+        $inc: {'meta.visitors': 2},
+        $set: {date: new Date},
         published: false, // becomes $set
-        'mixed': { x: 'ECKS', y: 'why' }, // $set
-        $pullAll: { 'numbers': [4, 6] },
-        $pull: { 'owners': id0 },
+        'mixed': {x: 'ECKS', y: 'why'}, // $set
+        $pullAll: {'numbers': [4, 6]},
+        $pull: {'owners': id0},
         'comments.1.body': 8 // $set
       };
 
-      BlogPost.update({ title: title }, update, function(err) {
+      BlogPost.update({title: title}, update, function (err) {
         assert.ifError(err);
 
-        BlogPost.findById(post._id, function(err, up) {
+        BlogPost.findById(post._id, function (err, up) {
           assert.ifError(err);
-          assert.equal(up.title,newTitle);
-          assert.equal(up.author,author);
+          assert.equal(up.title, newTitle);
+          assert.equal(up.author, author);
           assert.equal(up.meta.visitors.valueOf(), 2);
-          assert.equal(up.date.toString(),update.$set.date.toString());
+          assert.equal(up.date.toString(), update.$set.date.toString());
           assert.equal(up.published, false);
           assert.equal(up.mixed.x, 'ECKS');
-          assert.equal(up.mixed.y,'why');
-          assert.deepEqual(up.numbers.toObject(), [5,7]);
+          assert.equal(up.mixed.y, 'why');
+          assert.deepEqual(up.numbers.toObject(), [5, 7]);
           assert.equal(up.owners.length, 1);
           assert.equal(up.owners[0].toString(), id1.toString());
-          assert.equal(up.comments[0].body,'been there');
-          assert.equal(up.comments[1].body,'8');
+          assert.equal(up.comments[0].body, 'been there');
+          assert.equal(up.comments[1].body, '8');
           assert.ok(up.comments[0]._id);
           assert.ok(up.comments[1]._id);
           assert.ok(up.comments[0]._id instanceof DocumentObjectId);
@@ -162,40 +161,40 @@ describe('model: update:', function() {
             'comments.body': 'fail'
           };
 
-          BlogPost.update({ _id: post._id }, update2, function(err) {
+          BlogPost.update({_id: post._id}, update2, function (err) {
             assert.ok(err);
             assert.ok(err.message.length > 0);
-            BlogPost.findById(post, function(err) {
+            BlogPost.findById(post, function (err) {
               assert.ifError(err);
 
               var update3 = {
                 $pull: 'fail'
               };
 
-              BlogPost.update({ _id: post._id }, update3, function(err) {
+              BlogPost.update({_id: post._id}, update3, function (err) {
                 assert.ok(err);
 
                 assert.ok(/Invalid atomic update value for \$pull\. Expected an object, received string/.test(err.message));
 
                 var update4 = {
-                  $inc: { idontexist: 1 }
+                  $inc: {idontexist: 1}
                 };
 
                 // should not overwrite doc when no valid paths are submitted
-                BlogPost.update({ _id: post._id }, update4, function(err) {
+                BlogPost.update({_id: post._id}, update4, function (err) {
                   assert.ifError(err);
 
-                  BlogPost.findById(post._id, function(err, up) {
+                  BlogPost.findById(post._id, function (err, up) {
                     assert.ifError(err);
 
-                    assert.equal(up.title,newTitle);
-                    assert.equal(up.author,author);
-                    assert.equal(up.meta.visitors.valueOf(),2);
-                    assert.equal(up.date.toString(),update.$set.date.toString());
-                    assert.equal(up.published,false);
-                    assert.equal(up.mixed.x,'ECKS');
-                    assert.equal(up.mixed.y,'why');
-                    assert.deepEqual(up.numbers.toObject(),[5,7]);
+                    assert.equal(up.title, newTitle);
+                    assert.equal(up.author, author);
+                    assert.equal(up.meta.visitors.valueOf(), 2);
+                    assert.equal(up.date.toString(), update.$set.date.toString());
+                    assert.equal(up.published, false);
+                    assert.equal(up.mixed.x, 'ECKS');
+                    assert.equal(up.mixed.y, 'why');
+                    assert.deepEqual(up.numbers.toObject(), [5, 7]);
                     assert.equal(up.owners.length, 1);
                     assert.equal(up.owners[0].toString(), id1.toString());
                     assert.equal(up.comments[0].body, 'been there');
@@ -214,21 +213,21 @@ describe('model: update:', function() {
     });
   });
 
-  it('casts doc arrays', function(done) {
+  it('casts doc arrays', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
     var update = {
-      comments: [{ body: 'worked great' }],
+      comments: [{body: 'worked great'}],
       $set: {'numbers.1': 100},
-      $inc: { idontexist: 1 }
+      $inc: {idontexist: 1}
     };
 
-    BlogPost.update({ _id: post._id }, update, function(err) {
+    BlogPost.update({_id: post._id}, update, function (err) {
       assert.ifError(err);
 
       // get the underlying doc
-      BlogPost.collection.findOne({ _id: post._id }, function(err, doc) {
+      BlogPost.collection.findOne({_id: post._id}, function (err, doc) {
         assert.ifError(err);
 
         var up = new BlogPost;
@@ -236,10 +235,10 @@ describe('model: update:', function() {
         assert.equal(up.comments.length, 1);
         assert.equal(up.comments[0].body, 'worked great');
         assert.strictEqual(true, !!doc.comments[0]._id);
-        assert.equal(2,up.meta.visitors.valueOf());
-        assert.equal(up.mixed.x,'ECKS');
-        assert.deepEqual(up.numbers.toObject(),[5,100]);
-        assert.strictEqual(up.numbers[1].valueOf(),100);
+        assert.equal(2, up.meta.visitors.valueOf());
+        assert.equal(up.mixed.x, 'ECKS');
+        assert.deepEqual(up.numbers.toObject(), [5, 100]);
+        assert.strictEqual(up.numbers[1].valueOf(), 100);
 
         assert.equal(2, doc.idontexist);
         assert.equal(100, doc.numbers[1]);
@@ -249,23 +248,23 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $pushAll array of docs', function(done) {
+  it('handles $pushAll array of docs', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
     var update = {
-      $pushAll: { comments: [{ body: 'i am number 2' }, { body: 'i am number 3' }] }
+      $pushAll: {comments: [{body: 'i am number 2'}, {body: 'i am number 3'}]}
     };
 
-    BlogPost.update({ _id: post._id }, update, function(err) {
+    BlogPost.update({_id: post._id}, update, function (err) {
       assert.ifError(err);
-      BlogPost.findById(post, function(err, ret) {
+      BlogPost.findById(post, function (err, ret) {
         assert.ifError(err);
         assert.equal(3, ret.comments.length);
-        assert.equal(ret.comments[1].body,'i am number 2');
+        assert.equal(ret.comments[1].body, 'i am number 2');
         assert.strictEqual(true, !!ret.comments[1]._id);
         assert.ok(ret.comments[1]._id instanceof DocumentObjectId);
-        assert.equal(ret.comments[2].body,'i am number 3');
+        assert.equal(ret.comments[2].body, 'i am number 3');
         assert.strictEqual(true, !!ret.comments[2]._id);
         assert.ok(ret.comments[2]._id instanceof DocumentObjectId);
         db.close(done);
@@ -273,67 +272,71 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $pull of object literal array of docs (gh-542)', function(done) {
+  it('handles $pull of object literal array of docs (gh-542)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
     var update = {
-      $pull: { comments: { body: 'i am number 2' } }
+      $pull: {comments: {body: 'i am number 2'}}
     };
 
-    BlogPost.update({ _id: post._id }, update, function(err) {
+    BlogPost.update({_id: post._id}, update, function (err) {
       assert.ifError(err);
-      BlogPost.findById(post, function(err, ret) {
+      BlogPost.findById(post, function (err, ret) {
         assert.ifError(err);
         assert.equal(2, ret.comments.length);
-        assert.equal(ret.comments[0].body,'worked great');
+        assert.equal(ret.comments[0].body, 'worked great');
         assert.ok(ret.comments[0]._id instanceof DocumentObjectId);
-        assert.equal(ret.comments[1].body,'i am number 3');
+        assert.equal(ret.comments[1].body, 'i am number 3');
         assert.ok(ret.comments[1]._id instanceof DocumentObjectId);
         db.close(done);
       });
     });
   });
 
-  it('makes copy of conditions and update options', function(done) {
+  it('makes copy of conditions and update options', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    var conditions = { '_id': post._id.toString() };
-    var update = {'$set':{'some_attrib':post._id.toString()}};
-    BlogPost.update(conditions, update, function(err) {
+    var conditions = {'_id': post._id.toString()};
+    var update = {'$set': {'some_attrib': post._id.toString()}};
+    BlogPost.update(conditions, update, function (err) {
       assert.ifError(err);
       assert.equal('string', typeof conditions._id);
       db.close(done);
     });
   });
 
-  it('handles weird casting (gh-479)', function(done) {
+  it('handles weird casting (gh-479)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    function a() {}
-    a.prototype.toString = function() { return 'MongoDB++'; };
+    function a() {
+    }
+
+    a.prototype.toString = function () {
+      return 'MongoDB++';
+    };
     var crazy = new a;
 
     var update = {
-      $addToSet: { 'comments.$.comments': { body: 'The Ring Of Power' } },
-      $set: { 'comments.$.title': crazy }
+      $addToSet: {'comments.$.comments': {body: 'The Ring Of Power'}},
+      $set: {'comments.$.title': crazy}
     };
 
-    BlogPost.update({ _id: post._id, 'comments.body': 'worked great' }, update, function(err) {
+    BlogPost.update({_id: post._id, 'comments.body': 'worked great'}, update, function (err) {
       assert.ifError(err);
-      BlogPost.findById(post, function(err, ret) {
+      BlogPost.findById(post, function (err, ret) {
         assert.ifError(err);
         assert.equal(2, ret.comments.length);
         assert.equal(ret.comments[0].body, 'worked great');
-        assert.equal(ret.comments[0].title,'MongoDB++');
+        assert.equal(ret.comments[0].title, 'MongoDB++');
         assert.strictEqual(true, !!ret.comments[0].comments);
         assert.equal(ret.comments[0].comments.length, 1);
         assert.strictEqual(ret.comments[0].comments[0].body, 'The Ring Of Power');
         assert.ok(ret.comments[0]._id instanceof DocumentObjectId);
         assert.ok(ret.comments[0].comments[0]._id instanceof DocumentObjectId);
-        assert.equal(ret.comments[1].body,'i am number 3');
+        assert.equal(ret.comments[1].body, 'i am number 3');
         assert.strictEqual(undefined, ret.comments[1].title);
         assert.ok(ret.comments[1]._id instanceof DocumentObjectId);
         db.close(done);
@@ -342,18 +345,18 @@ describe('model: update:', function() {
   });
 
   var last;
-  it('handles date casting (gh-479)', function(done) {
+  it('handles date casting (gh-479)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
     var update = {
-      $inc: { 'comments.$.newprop': '1' },
-      $set: { date: (new Date).getTime() } // check for single val casting
+      $inc: {'comments.$.newprop': '1'},
+      $set: {date: (new Date).getTime()} // check for single val casting
     };
 
-    BlogPost.update({ _id: post._id, 'comments.body': 'worked great' }, update, function(err) {
+    BlogPost.update({_id: post._id, 'comments.body': 'worked great'}, update, function (err) {
       assert.ifError(err);
-      BlogPost.findById(post, function(err, ret) {
+      BlogPost.findById(post, function (err, ret) {
         assert.ifError(err);
         assert.equal(1, ret._doc.comments[0]._doc.newprop);
         assert.strictEqual(undefined, ret._doc.comments[1]._doc.newprop);
@@ -366,19 +369,19 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $addToSet (gh-545)', function(done) {
+  it('handles $addToSet (gh-545)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
     var owner = last.owners[0];
 
     var update = {
-      $addToSet: { 'owners': owner }
+      $addToSet: {'owners': owner}
     };
 
-    BlogPost.update({ _id: post._id }, update, function(err) {
+    BlogPost.update({_id: post._id}, update, function (err) {
       assert.ifError(err);
-      BlogPost.findById(post, function(err, ret) {
+      BlogPost.findById(post, function (err, ret) {
         assert.ifError(err);
         assert.equal(1, ret.owners.length);
         assert.equal(ret.owners[0].toString(), owner.toString());
@@ -389,7 +392,7 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $addToSet with $each (gh-545)', function(done) {
+  it('handles $addToSet with $each (gh-545)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -397,12 +400,12 @@ describe('model: update:', function() {
         newowner = new DocumentObjectId;
 
     var update = {
-      $addToSet: { 'owners': { $each: [owner, newowner] }}
+      $addToSet: {'owners': {$each: [owner, newowner]}}
     };
 
-    BlogPost.update({ _id: post._id }, update, function(err) {
+    BlogPost.update({_id: post._id}, update, function (err) {
       assert.ifError(err);
-      BlogPost.findById(post, function(err, ret) {
+      BlogPost.findById(post, function (err, ret) {
         assert.ifError(err);
         assert.equal(2, ret.owners.length);
         assert.equal(ret.owners[0].toString(), owner.toString());
@@ -414,19 +417,19 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $pop and $unset (gh-574)', function(done) {
+  it('handles $pop and $unset (gh-574)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
     var update = {
-      $pop: { 'owners': -1 },
-      $unset: { title: 1 }
+      $pop: {'owners': -1},
+      $unset: {title: 1}
     };
 
 
-    BlogPost.update({ _id: post._id }, update, function(err) {
+    BlogPost.update({_id: post._id}, update, function (err) {
       assert.ifError(err);
-      BlogPost.findById(post, function(err, ret) {
+      BlogPost.findById(post, function (err, ret) {
         assert.ifError(err);
         assert.equal(1, ret.owners.length);
         assert.equal(ret.owners[0].toString(), last.toString());
@@ -436,7 +439,7 @@ describe('model: update:', function() {
     });
   });
 
-  it('works with nested positional notation', function(done) {
+  it('works with nested positional notation', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -447,9 +450,9 @@ describe('model: update:', function() {
       }
     };
 
-    BlogPost.update({ _id: post._id }, update, function(err) {
+    BlogPost.update({_id: post._id}, update, function (err) {
       assert.ifError(err);
-      BlogPost.findById(post, function(err, ret) {
+      BlogPost.findById(post, function (err, ret) {
         assert.ifError(err);
         assert.equal(2, ret.comments.length, 2);
         assert.equal(ret.comments[0].body, 'worked great');
@@ -461,20 +464,20 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $pull with obj literal (gh-542)', function(done) {
+  it('handles $pull with obj literal (gh-542)', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    BlogPost.findById(post, function(err, last) {
+    BlogPost.findById(post, function (err, last) {
       assert.ifError(err);
 
       var update = {
-        $pull: { comments: { _id: last.comments[0].id } }
+        $pull: {comments: {_id: last.comments[0].id}}
       };
 
-      BlogPost.update({ _id: post._id }, update, function(err) {
+      BlogPost.update({_id: post._id}, update, function (err) {
         assert.ifError(err);
-        BlogPost.findById(post, function(err, ret) {
+        BlogPost.findById(post, function (err, ret) {
           assert.ifError(err);
           assert.equal(1, ret.comments.length);
           assert.equal(ret.comments[0].body, '9000');
@@ -484,19 +487,19 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $pull of obj literal and nested $in', function(done) {
+  it('handles $pull of obj literal and nested $in', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    BlogPost.findById(post, function(err, last) {
+    BlogPost.findById(post, function (err, last) {
       assert.ifError(err);
       var update = {
-        $pull: { comments: { body: { $in: [last.comments[0].body] }} }
+        $pull: {comments: {body: {$in: [last.comments[0].body]}}}
       };
 
-      BlogPost.update({ _id: post._id }, update, function(err) {
+      BlogPost.update({_id: post._id}, update, function (err) {
         assert.ifError(err);
-        BlogPost.findById(post, function(err, ret) {
+        BlogPost.findById(post, function (err, ret) {
           assert.ifError(err);
           assert.equal(0, ret.comments.length);
 
@@ -507,27 +510,27 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $pull and nested $nin', function(done) {
+  it('handles $pull and nested $nin', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    BlogPost.findById(post, function(err, last) {
+    BlogPost.findById(post, function (err, last) {
       assert.ifError(err);
 
-      last.comments.push({body: 'hi'}, {body:'there'});
-      last.save(function(err) {
+      last.comments.push({body: 'hi'}, {body: 'there'});
+      last.save(function (err) {
         assert.ifError(err);
-        BlogPost.findById(post, function(err, ret) {
+        BlogPost.findById(post, function (err, ret) {
           assert.ifError(err);
           assert.equal(2, ret.comments.length);
 
           var update = {
-            $pull: { comments: { body: { $nin: ['there'] }} }
+            $pull: {comments: {body: {$nin: ['there']}}}
           };
 
-          BlogPost.update({ _id: ret._id }, update, function(err) {
+          BlogPost.update({_id: ret._id}, update, function (err) {
             assert.ifError(err);
-            BlogPost.findById(post, function(err, ret) {
+            BlogPost.findById(post, function (err, ret) {
               assert.ifError(err);
               assert.equal(1, ret.comments.length);
               db.close(done);
@@ -538,7 +541,7 @@ describe('model: update:', function() {
     });
   });
 
-  it('updates numbers atomically', function(done) {
+  it('updates numbers atomically', function (done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection),
         totalDocs = 4;
@@ -546,19 +549,19 @@ describe('model: update:', function() {
     var post = new BlogPost;
     post.set('meta.visitors', 5);
 
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
 
       for (var i = 0; i < 4; ++i) {
         BlogPost
-        .update({ _id: post._id }, { $inc: { 'meta.visitors': 1 }}, function(err) {
+        .update({_id: post._id}, {$inc: {'meta.visitors': 1}}, function (err) {
           assert.ifError(err);
           --totalDocs || complete();
         });
       }
 
       function complete() {
-        BlogPost.findOne({ _id: post.get('_id') }, function(err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
           db.close();
           assert.ifError(err);
           assert.equal(9, doc.get('meta.visitors'));
@@ -568,40 +571,40 @@ describe('model: update:', function() {
     });
   });
 
-  describe('honors strict schemas', function() {
-    it('(gh-699)', function(done) {
+  describe('honors strict schemas', function () {
+    it('(gh-699)', function (done) {
       var db = start();
       var S = db.model('UpdateStrictSchema');
 
-      var doc = S.find()._castUpdate({ ignore: true });
+      var doc = S.find()._castUpdate({ignore: true});
       assert.equal(false, doc);
-      doc = S.find()._castUpdate({ $unset: {x: 1}});
+      doc = S.find()._castUpdate({$unset: {x: 1}});
       assert.equal(1, Object.keys(doc.$unset).length);
       db.close(done);
     });
 
-    it('works', function(done) {
+    it('works', function (done) {
       var db = start();
       var S = db.model('UpdateStrictSchema');
-      var s = new S({ name: 'orange crush' });
+      var s = new S({name: 'orange crush'});
 
-      s.save(function(err) {
+      s.save(function (err) {
         assert.ifError(err);
 
-        S.update({ _id: s._id }, { ignore: true }, function(err, affected) {
+        S.update({_id: s._id}, {ignore: true}, function (err, affected) {
           assert.ifError(err);
           assert.equal(0, affected.n);
 
-          S.findById(s._id, function(err, doc) {
+          S.findById(s._id, function (err, doc) {
             assert.ifError(err);
             assert.ok(!doc.ignore);
             assert.ok(!doc._doc.ignore);
 
-            S.update({ _id: s._id }, { name: 'Drukqs', foo: 'fooey' }, function(err, affected) {
+            S.update({_id: s._id}, {name: 'Drukqs', foo: 'fooey'}, function (err, affected) {
               assert.ifError(err);
               assert.equal(1, affected.n);
 
-              S.findById(s._id, function(err, doc) {
+              S.findById(s._id, function (err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.ok(!doc._doc.foo);
@@ -614,13 +617,13 @@ describe('model: update:', function() {
     });
   });
 
-  it('passes number of affected docs', function(done) {
+  it('passes number of affected docs', function (done) {
     var db = start(),
         B = db.model('BlogPostForUpdates', 'wwwwowowo' + random());
 
-    B.create({ title: 'one'},{title:'two'},{title:'three'}, function(err) {
+    B.create({title: 'one'}, {title: 'two'}, {title: 'three'}, function (err) {
       assert.ifError(err);
-      B.update({}, { title: 'newtitle' }, { multi: true }, function(err, affected) {
+      B.update({}, {title: 'newtitle'}, {multi: true}, function (err, affected) {
         db.close();
         assert.ifError(err);
         assert.equal(3, affected.n);
@@ -629,17 +632,17 @@ describe('model: update:', function() {
     });
   });
 
-  it('updates a number to null (gh-640)', function(done) {
+  it('updates a number to null (gh-640)', function (done) {
     var db = start();
     var B = db.model('BlogPostForUpdates', 'wwwwowowo' + random());
-    var b = new B({ meta: { visitors: null }});
-    b.save(function(err) {
+    var b = new B({meta: {visitors: null}});
+    b.save(function (err) {
       assert.ifError(err);
-      B.findById(b, function(err, b) {
+      B.findById(b, function (err, b) {
         assert.ifError(err);
         assert.strictEqual(b.meta.visitors, null);
 
-        B.update({ _id: b._id }, { meta: { visitors: null }}, function(err) {
+        B.update({_id: b._id}, {meta: {visitors: null}}, function (err) {
           db.close();
           assert.strictEqual(null, err);
           done();
@@ -648,13 +651,13 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $pull from Mixed arrays (gh-735)', function(done) {
+  it('handles $pull from Mixed arrays (gh-735)', function (done) {
     var db = start();
-    var schema = new Schema({ comments: [] });
+    var schema = new Schema({comments: []});
     var M = db.model('gh-735', schema, 'gh-735_' + random());
-    M.create({ comments: [{ name: 'node 0.8' }] }, function(err, doc) {
+    M.create({comments: [{name: 'node 0.8'}]}, function (err, doc) {
       assert.ifError(err);
-      M.update({ _id: doc._id }, { $pull: { comments: { name: 'node 0.8' }}}, function(err, affected) {
+      M.update({_id: doc._id}, {$pull: {comments: {name: 'node 0.8'}}}, function (err, affected) {
         assert.ifError(err);
         assert.equal(1, affected.n);
         db.close();
@@ -663,7 +666,7 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles $push with $ positionals (gh-1057)', function(done) {
+  it('handles $push with $ positionals (gh-1057)', function (done) {
     var db = start();
 
     var taskSchema = new Schema({
@@ -682,16 +685,16 @@ describe('model: update:', function() {
 
     var Project = db.model('1057-project', projectSchema, '1057-' + random());
 
-    Project.create({ name: 'my project' }, function(err, project) {
+    Project.create({name: 'my project'}, function (err, project) {
       assert.ifError(err);
       var pid = project.id;
-      var comp = project.components.create({ name: 'component' });
-      Project.update({ _id: pid }, { $push: { components: comp }}, function(err) {
+      var comp = project.components.create({name: 'component'});
+      Project.update({_id: pid}, {$push: {components: comp}}, function (err) {
         assert.ifError(err);
-        var task = comp.tasks.create({ name: 'my task' });
-        Project.update({ _id: pid, 'components._id': comp._id }, { $push : { 'components.$.tasks': task }}, function(err) {
+        var task = comp.tasks.create({name: 'my task'});
+        Project.update({_id: pid, 'components._id': comp._id}, {$push: {'components.$.tasks': task}}, function (err) {
           assert.ifError(err);
-          Project.findById(pid, function(err, proj) {
+          Project.findById(pid, function (err, proj) {
             assert.ifError(err);
             assert.ok(proj);
             assert.equal(1, proj.components.length);
@@ -705,18 +708,17 @@ describe('model: update:', function() {
         });
       });
     });
-
   });
 
-  it('handles nested paths starting with numbers (gh-1062)', function(done) {
+  it('handles nested paths starting with numbers (gh-1062)', function (done) {
     var db = start();
-    var schema = Schema({ counts: Schema.Types.Mixed });
+    var schema = Schema({counts: Schema.Types.Mixed});
     var M = db.model('gh-1062', schema, '1062-' + random());
-    M.create({ counts: {} }, function(err, m) {
+    M.create({counts: {}}, function (err, m) {
       assert.ifError(err);
-      M.update({}, { $inc: { 'counts.1': 1, 'counts.1a': 10 }}, function(err) {
+      M.update({}, {$inc: {'counts.1': 1, 'counts.1a': 10}}, function (err) {
         assert.ifError(err);
-        M.findById(m, function(err, doc) {
+        M.findById(m, function (err, doc) {
           assert.ifError(err);
           assert.equal(1, doc.counts['1']);
           assert.equal(10, doc.counts['1a']);
@@ -726,19 +728,19 @@ describe('model: update:', function() {
     });
   });
 
-  it('handles positional operators with referenced docs (gh-1572)', function(done) {
+  it('handles positional operators with referenced docs (gh-1572)', function (done) {
     var db = start();
 
-    var so = new Schema({ title: String, obj: [String] });
+    var so = new Schema({title: String, obj: [String]});
     var Some = db.model('Some' + random(), so);
 
-    Some.create({ obj: ['a','b','c'] }, function(err, s) {
+    Some.create({obj: ['a', 'b', 'c']}, function (err, s) {
       assert.ifError(err);
 
-      Some.update({ _id: s._id, obj: 'b' }, { $set: { "obj.$" : 2 }}, function(err) {
+      Some.update({_id: s._id, obj: 'b'}, {$set: {'obj.$': 2}}, function (err) {
         assert.ifError(err);
 
-        Some.findById(s._id, function(err, ss) {
+        Some.findById(s._id, function (err, ss) {
           assert.ifError(err);
 
           assert.strictEqual(ss.obj[1], '2');
@@ -748,25 +750,25 @@ describe('model: update:', function() {
     });
   });
 
-  it('use .where for update condition (gh-2170)', function(done) {
+  it('use .where for update condition (gh-2170)', function (done) {
     var db = start();
-    var so = new Schema({ num: Number });
+    var so = new Schema({num: Number});
     var Some = db.model('gh-2170' + random(), so);
 
-    Some.create([ {num: 1}, {num: 1} ], function(err, docs) {
+    Some.create([{num: 1}, {num: 1}], function (err, docs) {
       assert.ifError(err);
       assert.equal(docs.length, 2);
       var doc0 = docs[0];
       var doc1 = docs[1];
       var sId0 = doc0._id;
       var sId1 = doc1._id;
-      Some.where({_id: sId0}).update({}, {$set: {num: '99'}}, {multi: true}, function(err, cnt) {
+      Some.where({_id: sId0}).update({}, {$set: {num: '99'}}, {multi: true}, function (err, cnt) {
         assert.ifError(err);
         assert.equal(1, cnt.n);
-        Some.findById(sId0, function(err, doc0_1) {
+        Some.findById(sId0, function (err, doc0_1) {
           assert.ifError(err);
           assert.equal(99, doc0_1.num);
-          Some.findById(sId1, function(err, doc1_1) {
+          Some.findById(sId1, function (err, doc1_1) {
             assert.ifError(err);
             assert.equal(1, doc1_1.num);
             db.close(done);
@@ -776,42 +778,42 @@ describe('model: update:', function() {
     });
   });
 
-  describe('mongodb 2.4 features', function() {
+  describe('mongodb 2.4 features', function () {
     var mongo24_or_greater = false;
 
-    before(function(done) {
-      start.mongodVersion(function(err, version) {
+    before(function (done) {
+      start.mongodVersion(function (err, version) {
         assert.ifError(err);
         mongo24_or_greater = 2 < version[0] || (2 == version[0] && 4 <= version[1]);
         done();
       });
     });
 
-    it('$setOnInsert operator', function(done) {
+    it('$setOnInsert operator', function (done) {
       if (!mongo24_or_greater) {
         console.log('not testing mongodb 2.4 $setOnInsert feature');
         return done();
       }
 
       var db = start();
-      var schema = Schema({ name: String, age: Number, x: String });
+      var schema = Schema({name: String, age: Number, x: String});
       var M = db.model('setoninsert-' + random(), schema);
 
-      var match = { name: 'set on insert' };
-      var op = { $setOnInsert: { age: '47' }, x: 'inserted' };
-      M.update(match, op, { upsert: true }, function(err) {
+      var match = {name: 'set on insert'};
+      var op = {$setOnInsert: {age: '47'}, x: 'inserted'};
+      M.update(match, op, {upsert: true}, function (err) {
         assert.ifError(err);
-        M.findOne(function(err, doc) {
+        M.findOne(function (err, doc) {
           assert.ifError(err);
           assert.equal(47, doc.age);
           assert.equal('set on insert', doc.name);
 
-          var match = { name: 'set on insert' };
-          var op = { $setOnInsert: { age: 108 }, name: 'changed' };
-          M.update(match, op, { upsert: true }, function(err) {
+          var match = {name: 'set on insert'};
+          var op = {$setOnInsert: {age: 108}, name: 'changed'};
+          M.update(match, op, {upsert: true}, function (err) {
             assert.ifError(err);
 
-            M.findOne(function(err, doc) {
+            M.findOne(function (err, doc) {
               assert.equal(47, doc.age);
               assert.equal('changed', doc.name);
               db.close(done);
@@ -821,28 +823,32 @@ describe('model: update:', function() {
       });
     });
 
-    it('push with $slice', function(done) {
+    it('push with $slice', function (done) {
       if (!mongo24_or_greater) {
         console.log('not testing mongodb 2.4 $push with $slice feature');
         return done();
       }
 
       var db = start();
-      var schema = Schema({ name: String, n: [{ x: Number }] });
+      var schema = Schema({name: String, n: [{x: Number}]});
       var M = db.model('setoninsert-' + random(), schema);
 
-      M.create({ name: '2.4' }, function(err, created) {
+      M.create({name: '2.4'}, function (err, created) {
         assert.ifError(err);
 
-        var op = { $push: { n: {
-          $each: [{x:10},{x:4}, {x:1}],
-          $slice: '-1',
-          $sort: { x:1 }
-        }}};
+        var op = {
+          $push: {
+            n: {
+              $each: [{x: 10}, {x: 4}, {x: 1}],
+              $slice: '-1',
+              $sort: {x: 1}
+            }
+          }
+        };
 
-        M.update({ _id: created._id }, op, function(err) {
+        M.update({_id: created._id}, op, function (err) {
           assert.ifError(err);
-          M.findById(created._id, function(err, doc) {
+          M.findById(created._id, function (err, doc) {
             assert.ifError(err);
             assert.equal(created.id, doc.id);
             assert.equal(1, doc.n.length);
@@ -856,9 +862,9 @@ describe('model: update:', function() {
                 }
               }
             };
-            M.update({ _id: created._id }, op, function(err) {
+            M.update({_id: created._id}, op, function (err) {
               assert.ifError(err);
-              M.findById(created._id, function(error, doc) {
+              M.findById(created._id, function (error, doc) {
                 assert.ifError(error);
                 assert.equal(doc.n.length, 0);
                 db.close(done);
@@ -870,89 +876,89 @@ describe('model: update:', function() {
     });
   });
 
-  describe('mongodb 2.6 features', function() {
+  describe('mongodb 2.6 features', function () {
     var mongo26_or_greater = false;
 
-    before(function(done) {
-      start.mongodVersion(function(err, version) {
+    before(function (done) {
+      start.mongodVersion(function (err, version) {
         assert.ifError(err);
         mongo26_or_greater = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
         done();
       });
     });
 
-    it('supports $position', function(done) {
+    it('supports $position', function (done) {
       if (!mongo26_or_greater) {
         return done();
       }
 
       var db = start();
-      var schema = Schema({ name: String, n: [{ x: Number }] });
+      var schema = Schema({name: String, n: [{x: Number}]});
       var M = db.model('setoninsert-' + random(), schema);
 
-      var m = new M({ name: '2.6', n: [{ x: 0 }] });
-      m.save(function(error, m) {
+      var m = new M({name: '2.6', n: [{x: 0}]});
+      m.save(function (error, m) {
         assert.ifError(error);
         assert.equal(1, m.n.length);
         M.update(
-           { name: '2.6' },
-           { $push: { n: { $each: [{x: 2}, {x: 1}], $position: 0 } } },
-           function(error) {
-             assert.ifError(error);
-             M.findOne({ name: '2.6' }, function(error, m) {
-               assert.ifError(error);
-               assert.equal(3, m.n.length);
-               assert.equal(2, m.n[0].x);
-               assert.equal(1, m.n[1].x);
-               assert.equal(0, m.n[2].x);
-               db.close(done);
-             });
-           });
+            {name: '2.6'},
+            {$push: {n: {$each: [{x: 2}, {x: 1}], $position: 0}}},
+            function (error) {
+              assert.ifError(error);
+              M.findOne({name: '2.6'}, function (error, m) {
+                assert.ifError(error);
+                assert.equal(3, m.n.length);
+                assert.equal(2, m.n[0].x);
+                assert.equal(1, m.n[1].x);
+                assert.equal(0, m.n[2].x);
+                db.close(done);
+              });
+            });
       });
     });
 
-    it('supports $currentDate', function(done) {
+    it('supports $currentDate', function (done) {
       if (!mongo26_or_greater) {
         return done();
       }
 
       var db = start();
-      var schema = Schema({ name: String, lastModified: Date, lastModifiedTS: Date });
+      var schema = Schema({name: String, lastModified: Date, lastModifiedTS: Date});
       var M = db.model('gh-2019', schema);
 
-      var m = new M({ name: '2.6' });
-      m.save(function(error) {
+      var m = new M({name: '2.6'});
+      m.save(function (error) {
         assert.ifError(error);
         var before = Date.now();
         M.update(
-           { name: '2.6' },
-           { $currentDate: { lastModified: true, lastModifiedTS: { $type: 'timestamp' } } },
-           function(error) {
-             assert.ifError(error);
-             M.findOne({ name: '2.6' }, function(error, m) {
-               var after = Date.now();
-               assert.ifError(error);
-               assert.ok(m.lastModified.getTime() >= before);
-               assert.ok(m.lastModified.getTime() <= after);
-               db.close(done);
-             });
-           });
+            {name: '2.6'},
+            {$currentDate: {lastModified: true, lastModifiedTS: {$type: 'timestamp'}}},
+            function (error) {
+              assert.ifError(error);
+              M.findOne({name: '2.6'}, function (error, m) {
+                var after = Date.now();
+                assert.ifError(error);
+                assert.ok(m.lastModified.getTime() >= before);
+                assert.ok(m.lastModified.getTime() <= after);
+                db.close(done);
+              });
+            });
       });
     });
   });
 
-  describe('{overwrite: true}', function() {
-    it('overwrite works', function(done) {
+  describe('{overwrite: true}', function () {
+    it('overwrite works', function (done) {
       var db = start();
-      var schema = new Schema({ mixed: {} });
+      var schema = new Schema({mixed: {}});
       var M = db.model('updatesmixed-' + random(), schema);
 
-      M.create({ mixed: 'something' }, function(err, created) {
+      M.create({mixed: 'something'}, function (err, created) {
         assert.ifError(err);
 
-        M.update({ _id: created._id }, { mixed: {} }, { overwrite: true }, function(err) {
+        M.update({_id: created._id}, {mixed: {}}, {overwrite: true}, function (err) {
           assert.ifError(err);
-          M.findById(created._id, function(err, doc) {
+          M.findById(created._id, function (err, doc) {
             assert.ifError(err);
             assert.equal(created.id, doc.id);
             assert.equal(typeof doc.mixed, 'object');
@@ -963,18 +969,18 @@ describe('model: update:', function() {
       });
     });
 
-    it('overwrites all properties', function(done) {
+    it('overwrites all properties', function (done) {
       var db = start();
-      var sch = new Schema({ title: String, subdoc : { name: String, num: Number }});
+      var sch = new Schema({title: String, subdoc: {name: String, num: Number}});
 
       var M = db.model('updateover' + random(), sch);
 
-      M.create({ subdoc : { name : 'that', num: 1 } }, function(err, doc) {
+      M.create({subdoc: {name: 'that', num: 1}}, function (err, doc) {
         assert.ifError(err);
 
-        M.update({ _id: doc.id }, { title : 'something!' }, { overwrite: true }, function(err) {
+        M.update({_id: doc.id}, {title: 'something!'}, {overwrite: true}, function (err) {
           assert.ifError(err);
-          M.findById(doc.id, function(err, doc) {
+          M.findById(doc.id, function (err, doc) {
             assert.ifError(err);
             assert.equal(doc.title, 'something!');
             assert.equal(doc.subdoc.name, undefined);
@@ -985,18 +991,18 @@ describe('model: update:', function() {
       });
     });
 
-    it('allows users to blow it up', function(done) {
+    it('allows users to blow it up', function (done) {
       var db = start();
-      var sch = new Schema({ title: String, subdoc : { name: String, num: Number }});
+      var sch = new Schema({title: String, subdoc: {name: String, num: Number}});
 
       var M = db.model('updateover' + random(), sch);
 
-      M.create({ subdoc : { name : 'that', num: 1, title : 'hello' } }, function(err, doc) {
+      M.create({subdoc: {name: 'that', num: 1, title: 'hello'}}, function (err, doc) {
         assert.ifError(err);
 
-        M.update({ _id: doc.id }, {}, { overwrite: true }, function(err) {
+        M.update({_id: doc.id}, {}, {overwrite: true}, function (err) {
           assert.ifError(err);
-          M.findById(doc.id, function(err, doc) {
+          M.findById(doc.id, function (err, doc) {
             assert.ifError(err);
             assert.equal(doc.title, undefined);
             assert.equal(doc.subdoc.name, undefined);
@@ -1008,19 +1014,25 @@ describe('model: update:', function() {
     });
   });
 
-  it('casts empty arrays', function(done) {
+  it('casts empty arrays', function (done) {
     var db = start();
 
-    var so = new Schema({ arr: [] });
+    var so = new Schema({arr: []});
     var Some = db.model('1838-' + random(), so);
 
-    Some.create({ arr: ['a'] }, function(err, s) {
-      if (err) return done(err);
+    Some.create({arr: ['a']}, function (err, s) {
+      if (err) {
+        return done(err);
+      }
 
-      Some.update({ _id: s._id }, { arr: [] }, function(err) {
-        if (err) return done(err);
-        Some.findById(s._id, function(err, doc) {
-          if (err) return done(err);
+      Some.update({_id: s._id}, {arr: []}, function (err) {
+        if (err) {
+          return done(err);
+        }
+        Some.findById(s._id, function (err, doc) {
+          if (err) {
+            return done(err);
+          }
           assert.ok(Array.isArray(doc.arr));
           assert.strictEqual(0, doc.arr.length);
           db.close(done);
@@ -1029,16 +1041,16 @@ describe('model: update:', function() {
     });
   });
 
-  describe('defaults and validators (gh-860)', function() {
-    it('applies defaults on upsert', function(done) {
+  describe('defaults and validators (gh-860)', function () {
+    it('applies defaults on upsert', function (done) {
       var db = start();
 
-      var s = new Schema({ topping: { type: String, default: 'bacon' }, base: String });
+      var s = new Schema({topping: {type: String, default: 'bacon'}, base: String});
       var Breakfast = db.model('gh-860-0', s);
-      var updateOptions = { upsert: true, setDefaultsOnInsert: true };
-      Breakfast.update({}, { base: 'eggs' }, updateOptions, function(error) {
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true};
+      Breakfast.update({}, {base: 'eggs'}, updateOptions, function (error) {
         assert.ifError(error);
-        Breakfast.findOne({}).lean().exec(function(error, breakfast) {
+        Breakfast.findOne({}).lean().exec(function (error, breakfast) {
           assert.ifError(error);
           assert.equal('eggs', breakfast.base);
           assert.equal('bacon', breakfast.topping);
@@ -1047,16 +1059,16 @@ describe('model: update:', function() {
       });
     });
 
-    it('doesnt set default on upsert if query sets it', function(done) {
+    it('doesnt set default on upsert if query sets it', function (done) {
       var db = start();
 
-      var s = new Schema({ topping: { type: String, default: 'bacon' }, base: String });
+      var s = new Schema({topping: {type: String, default: 'bacon'}, base: String});
       var Breakfast = db.model('gh-860-1', s);
 
-      var updateOptions = { upsert: true, setDefaultsOnInsert: true };
-      Breakfast.update({ topping: 'sausage' }, { base: 'eggs' }, updateOptions, function(error) {
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true};
+      Breakfast.update({topping: 'sausage'}, {base: 'eggs'}, updateOptions, function (error) {
         assert.ifError(error);
-        Breakfast.findOne({}, function(error, breakfast) {
+        Breakfast.findOne({}, function (error, breakfast) {
           assert.ifError(error);
           assert.equal('eggs', breakfast.base);
           assert.equal('sausage', breakfast.topping);
@@ -1066,16 +1078,16 @@ describe('model: update:', function() {
       });
     });
 
-    it('properly sets default on upsert if query wont set it', function(done) {
+    it('properly sets default on upsert if query wont set it', function (done) {
       var db = start();
 
-      var s = new Schema({ topping: { type: String, default: 'bacon' }, base: String });
+      var s = new Schema({topping: {type: String, default: 'bacon'}, base: String});
       var Breakfast = db.model('gh-860-2', s);
 
-      var updateOptions = { upsert: true, setDefaultsOnInsert: true };
-      Breakfast.update({ topping: { $ne: 'sausage' } }, { base: 'eggs' }, updateOptions, function(error) {
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true};
+      Breakfast.update({topping: {$ne: 'sausage'}}, {base: 'eggs'}, updateOptions, function (error) {
         assert.ifError(error);
-        Breakfast.findOne({}, function(error, breakfast) {
+        Breakfast.findOne({}, function (error, breakfast) {
           assert.ifError(error);
           assert.equal('eggs', breakfast.base);
           assert.equal('bacon', breakfast.topping);
@@ -1085,24 +1097,32 @@ describe('model: update:', function() {
       });
     });
 
-    it('runs validators if theyre set', function(done) {
+    it('runs validators if theyre set', function (done) {
       var db = start();
 
       var s = new Schema({
-        topping: { type: String, validate: function() { return false; } },
-        base: { type: String, validate: function() { return true; } }
+        topping: {
+          type: String, validate: function () {
+            return false;
+          }
+        },
+        base: {
+          type: String, validate: function () {
+            return true;
+          }
+        }
       });
       var Breakfast = db.model('gh-860-3', s);
 
-      var updateOptions = { upsert: true, setDefaultsOnInsert: true, runValidators: true };
-      Breakfast.update({}, { topping: 'bacon', base: 'eggs' }, updateOptions, function(error) {
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true, runValidators: true};
+      Breakfast.update({}, {topping: 'bacon', base: 'eggs'}, updateOptions, function (error) {
         assert.ok(!!error);
         assert.equal(1, Object.keys(error.errors).length);
         assert.equal('topping', Object.keys(error.errors)[0]);
         assert.equal('Validator failed for path `topping` with value `bacon`',
-          error.errors['topping'].message);
+            error.errors['topping'].message);
 
-        Breakfast.findOne({}, function(error, breakfast) {
+        Breakfast.findOne({}, function (error, breakfast) {
           assert.ifError(error);
           assert.ok(!breakfast);
           db.close();
@@ -1111,14 +1131,14 @@ describe('model: update:', function() {
       });
     });
 
-    it('validators handle $unset and $setOnInsert', function(done) {
+    it('validators handle $unset and $setOnInsert', function (done) {
       var db = start();
 
       var s = new Schema({
-        steak: { type: String, required: true },
+        steak: {type: String, required: true},
         eggs: {
           type: String,
-          validate: function() {
+          validate: function () {
             assert.ok(this instanceof require('../').Query);
             return false;
           }
@@ -1126,53 +1146,53 @@ describe('model: update:', function() {
       });
       var Breakfast = db.model('gh-860-4', s);
 
-      var updateOptions = { runValidators: true, context: 'query' };
-      Breakfast.update({}, { $unset: { steak: '' }, $setOnInsert: { eggs: 'softboiled' } }, updateOptions, function(error) {
+      var updateOptions = {runValidators: true, context: 'query'};
+      Breakfast.update({}, {$unset: {steak: ''}, $setOnInsert: {eggs: 'softboiled'}}, updateOptions, function (error) {
         assert.ok(!!error);
         assert.equal(2, Object.keys(error.errors).length);
         assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1);
         assert.ok(Object.keys(error.errors).indexOf('steak') !== -1);
         assert.equal('Validator failed for path `eggs` with value `softboiled`',
-          error.errors['eggs'].message);
+            error.errors['eggs'].message);
         assert.equal('Path `steak` is required.',
-          error.errors['steak'].message);
+            error.errors['steak'].message);
         db.close();
         done();
       });
     });
 
-    it('min/max, enum, and regex built-in validators work', function(done) {
+    it('min/max, enum, and regex built-in validators work', function (done) {
       var db = start();
 
       var s = new Schema({
-        steak: { type: String, enum: ['ribeye', 'sirloin'] },
-        eggs: { type: Number, min: 4, max: 6 },
-        bacon: { type: String, match: /strips/ }
+        steak: {type: String, enum: ['ribeye', 'sirloin']},
+        eggs: {type: Number, min: 4, max: 6},
+        bacon: {type: String, match: /strips/}
       });
       var Breakfast = db.model('gh-860-5', s);
 
-      var updateOptions = { runValidators: true };
-      Breakfast.update({}, { $set: { steak: 'ribeye', eggs: 3, bacon: '3 strips' } }, updateOptions, function(error) {
+      var updateOptions = {runValidators: true};
+      Breakfast.update({}, {$set: {steak: 'ribeye', eggs: 3, bacon: '3 strips'}}, updateOptions, function (error) {
         assert.ok(!!error);
         assert.equal(1, Object.keys(error.errors).length);
         assert.equal('eggs', Object.keys(error.errors)[0]);
         assert.equal('Path `eggs` (3) is less than minimum allowed value (4).',
-          error.errors['eggs'].message);
+            error.errors['eggs'].message);
 
-        Breakfast.update({}, { $set: { steak: 'tofu', eggs: 5, bacon: '3 strips' } }, updateOptions, function(error) {
+        Breakfast.update({}, {$set: {steak: 'tofu', eggs: 5, bacon: '3 strips'}}, updateOptions, function (error) {
           assert.ok(!!error);
           assert.equal(1, Object.keys(error.errors).length);
           assert.equal('steak', Object.keys(error.errors)[0]);
           assert.equal('`tofu` is not a valid enum value for path `steak`.',
-            error.errors['steak']);
+              error.errors['steak']);
 
 
-          Breakfast.update({}, { $set: { steak: 'sirloin', eggs: 6, bacon: 'none' } }, updateOptions, function(error) {
+          Breakfast.update({}, {$set: {steak: 'sirloin', eggs: 6, bacon: 'none'}}, updateOptions, function (error) {
             assert.ok(!!error);
             assert.equal(1, Object.keys(error.errors).length);
             assert.equal('bacon', Object.keys(error.errors)[0]);
             assert.equal('Path `bacon` is invalid (none).',
-              error.errors['bacon'].message);
+                error.errors['bacon'].message);
 
             db.close();
             done();
@@ -1181,18 +1201,18 @@ describe('model: update:', function() {
       });
     });
 
-    it('multiple validation errors', function(done) {
+    it('multiple validation errors', function (done) {
       var db = start();
 
       var s = new Schema({
-        steak: { type: String, enum: ['ribeye', 'sirloin'] },
-        eggs: { type: Number, min: 4, max: 6 },
-        bacon: { type: String, match: /strips/ }
+        steak: {type: String, enum: ['ribeye', 'sirloin']},
+        eggs: {type: Number, min: 4, max: 6},
+        bacon: {type: String, match: /strips/}
       });
       var Breakfast = db.model('gh-860-6', s);
 
-      var updateOptions = { runValidators: true };
-      Breakfast.update({}, { $set: { steak: 'tofu', eggs: 2, bacon: '3 strips' } }, updateOptions, function(error) {
+      var updateOptions = {runValidators: true};
+      Breakfast.update({}, {$set: {steak: 'tofu', eggs: 2, bacon: '3 strips'}}, updateOptions, function (error) {
         assert.ok(!!error);
         assert.equal(2, Object.keys(error.errors).length);
         assert.ok(Object.keys(error.errors).indexOf('steak') !== -1);
@@ -1202,233 +1222,233 @@ describe('model: update:', function() {
       });
     });
 
-    it('validators ignore $inc', function(done) {
+    it('validators ignore $inc', function (done) {
       var db = start();
 
       var s = new Schema({
-        steak: { type: String, required: true },
-        eggs: { type: Number, min: 4 }
+        steak: {type: String, required: true},
+        eggs: {type: Number, min: 4}
       });
       var Breakfast = db.model('gh-860-7', s);
 
-      var updateOptions = { runValidators: true };
-      Breakfast.update({}, { $inc: { eggs: 1 } }, updateOptions, function(error) {
+      var updateOptions = {runValidators: true};
+      Breakfast.update({}, {$inc: {eggs: 1}}, updateOptions, function (error) {
         assert.ifError(error);
         db.close();
         done();
       });
     });
 
-    it('validators handle positional operator (gh-3167)', function(done) {
+    it('validators handle positional operator (gh-3167)', function (done) {
       var db = start();
 
       var s = new Schema({
-        toppings: [{ name: { type: String, enum: ['bacon', 'cheese'] } }]
+        toppings: [{name: {type: String, enum: ['bacon', 'cheese']}}]
       });
       var Breakfast = db.model('gh-860-8', s);
 
-      var updateOptions = { runValidators: true };
+      var updateOptions = {runValidators: true};
       Breakfast.update(
-        { 'toppings.name': 'bacon' },
-        { 'toppings.$.name': 'tofu' },
-        updateOptions,
-        function(error) {
-          assert.ok(error);
-          assert.ok(error.errors['toppings.0.name']);
-          db.close(done);
-        });
+          {'toppings.name': 'bacon'},
+          {'toppings.$.name': 'tofu'},
+          updateOptions,
+          function (error) {
+            assert.ok(error);
+            assert.ok(error.errors['toppings.0.name']);
+            db.close(done);
+          });
     });
   });
 
-  it('works with $set and overwrite (gh-2515)', function(done) {
+  it('works with $set and overwrite (gh-2515)', function (done) {
     var db = start();
 
-    var schema = new Schema({ breakfast: String });
+    var schema = new Schema({breakfast: String});
     var M = db.model('gh-2515', schema);
 
-    M.create({ breakfast: 'bacon' }, function(error, doc) {
+    M.create({breakfast: 'bacon'}, function (error, doc) {
       assert.ifError(error);
       M.update(
-        { _id: doc._id },
-        { $set: { breakfast: 'eggs' } },
-        { overwrite: true },
-        function(error) {
-          assert.ifError(error);
-          M.findOne({ _id: doc._id }, function(error, doc) {
+          {_id: doc._id},
+          {$set: {breakfast: 'eggs'}},
+          {overwrite: true},
+          function (error) {
             assert.ifError(error);
-            assert.equal(doc.breakfast, 'eggs');
-            db.close(done);
+            M.findOne({_id: doc._id}, function (error, doc) {
+              assert.ifError(error);
+              assert.equal(doc.breakfast, 'eggs');
+              db.close(done);
+            });
           });
-        });
     });
   });
 
-  it('successfully casts set with nested mixed objects (gh-2796)', function(done) {
+  it('successfully casts set with nested mixed objects (gh-2796)', function (done) {
     var db = start();
 
-    var schema = new Schema({ breakfast: {} });
+    var schema = new Schema({breakfast: {}});
     var M = db.model('gh-2796', schema);
 
-    M.create({}, function(error, doc) {
+    M.create({}, function (error, doc) {
       assert.ifError(error);
       M.update(
-        { _id: doc._id },
-        { breakfast: { eggs: 2, bacon: 3 } },
-        function(error, result) {
-          assert.ifError(error);
-          assert.ok(result.ok);
-          assert.equal(result.n, 1);
-          M.findOne({ _id: doc._id }, function(error, doc) {
+          {_id: doc._id},
+          {breakfast: {eggs: 2, bacon: 3}},
+          function (error, result) {
             assert.ifError(error);
-            assert.equal(doc.breakfast.eggs, 2);
-            db.close(done);
+            assert.ok(result.ok);
+            assert.equal(result.n, 1);
+            M.findOne({_id: doc._id}, function (error, doc) {
+              assert.ifError(error);
+              assert.equal(doc.breakfast.eggs, 2);
+              db.close(done);
+            });
           });
-        });
     });
   });
 
-  it('handles empty update with promises (gh-2796)', function(done) {
+  it('handles empty update with promises (gh-2796)', function (done) {
     var db = start();
 
-    var schema = new Schema({ eggs: Number });
+    var schema = new Schema({eggs: Number});
     var M = db.model('gh-2796', schema);
 
-    M.create({}, function(error, doc) {
+    M.create({}, function (error, doc) {
       assert.ifError(error);
       M.update(
-        { _id: doc._id },
-        { notInSchema: 1 }).
-        exec().
-        then(function(data) {
-          assert.equal(data.ok, 0);
-          assert.equal(data.n, 0);
-          db.close(done);
-        }).
-        onReject(function(error) {
-          return done(error);
-        });
+          {_id: doc._id},
+          {notInSchema: 1}).
+      exec().
+      then(function (data) {
+        assert.equal(data.ok, 0);
+        assert.equal(data.n, 0);
+        db.close(done);
+      }).
+      onReject(function (error) {
+        return done(error);
+      });
     });
   });
 
-  describe('middleware', function() {
-    it('can specify pre and post hooks', function(done) {
+  describe('middleware', function () {
+    it('can specify pre and post hooks', function (done) {
       var db = start();
 
       var numPres = 0;
       var numPosts = 0;
-      var band = new Schema({ members: [String] });
-      band.pre('update', function(next) {
+      var band = new Schema({members: [String]});
+      band.pre('update', function (next) {
         ++numPres;
         next();
       });
-      band.post('update', function() {
+      band.post('update', function () {
         ++numPosts;
       });
       var Band = db.model('gh-964', band);
 
-      var gnr = new Band({ members: ['Axl', 'Slash', 'Izzy', 'Duff', 'Adler' ] });
-      gnr.save(function(error) {
+      var gnr = new Band({members: ['Axl', 'Slash', 'Izzy', 'Duff', 'Adler']});
+      gnr.save(function (error) {
         assert.ifError(error);
         assert.equal(0, numPres);
         assert.equal(0, numPosts);
         Band.update(
-          { _id: gnr._id },
-          { $pull: { members: 'Adler' } },
-          function(error) {
-            assert.ifError(error);
-            assert.equal(1, numPres);
-            assert.equal(1, numPosts);
-            Band.findOne({ _id: gnr._id }, function(error, doc) {
+            {_id: gnr._id},
+            {$pull: {members: 'Adler'}},
+            function (error) {
               assert.ifError(error);
-              assert.deepEqual(['Axl', 'Slash', 'Izzy', 'Duff'],
-                doc.toObject().members);
-              db.close(done);
+              assert.equal(1, numPres);
+              assert.equal(1, numPosts);
+              Band.findOne({_id: gnr._id}, function (error, doc) {
+                assert.ifError(error);
+                assert.deepEqual(['Axl', 'Slash', 'Izzy', 'Duff'],
+                    doc.toObject().members);
+                db.close(done);
+              });
             });
-          });
       });
     });
 
-    it('runs before validators (gh-2706)', function(done) {
+    it('runs before validators (gh-2706)', function (done) {
       var db = start();
 
       var bandSchema = new Schema({
-        lead: { type: String, enum: ['Axl Rose'] }
+        lead: {type: String, enum: ['Axl Rose']}
       });
-      bandSchema.pre('update', function() {
+      bandSchema.pre('update', function () {
         this.options.runValidators = true;
       });
       var Band = db.model('gh2706', bandSchema, 'gh2706');
 
-      Band.update({}, { $set: { lead: 'Not Axl' } }, function(err) {
+      Band.update({}, {$set: {lead: 'Not Axl'}}, function (err) {
         assert.ok(err);
         db.close(done);
       });
     });
 
-    describe('objects and arrays', function() {
+    describe('objects and arrays', function () {
       var db;
 
-      before(function() {
+      before(function () {
         db = start();
       });
 
-      after(function(done) {
+      after(function (done) {
         db.close(done);
       });
 
-      it('embedded objects (gh-2706)', function(done) {
+      it('embedded objects (gh-2706)', function (done) {
         var bandSchema = new Schema({
           singer: {
-            firstName: { type: String, enum: ['Axl'] },
-            lastName: { type: String, enum: ['Rose'] }
+            firstName: {type: String, enum: ['Axl']},
+            lastName: {type: String, enum: ['Rose']}
           }
         });
-        bandSchema.pre('update', function() {
+        bandSchema.pre('update', function () {
           this.options.runValidators = true;
         });
         var Band = db.model('gh2706', bandSchema, 'gh2706');
 
-        Band.update({}, { $set: { singer: { firstName: 'Not', lastName: 'Axl' } } }, function(err) {
+        Band.update({}, {$set: {singer: {firstName: 'Not', lastName: 'Axl'}}}, function (err) {
           assert.ok(err);
           done();
         });
       });
 
-      it('handles document array validation (gh-2733)', function(done) {
+      it('handles document array validation (gh-2733)', function (done) {
         var member = new Schema({
           name: String,
-          role: { type: String, required: true, enum: ['singer', 'guitar', 'drums', 'bass'] }
+          role: {type: String, required: true, enum: ['singer', 'guitar', 'drums', 'bass']}
         });
-        var band = new Schema({ members: [member], name: String });
+        var band = new Schema({members: [member], name: String});
         var Band = db.model('band', band, 'bands');
         var members = [
-          { name: 'Axl Rose', role: 'singer' },
-          { name: 'Slash', role: 'guitar' },
-          { name: 'Christopher Walken', role: 'cowbell' }
+          {name: 'Axl Rose', role: 'singer'},
+          {name: 'Slash', role: 'guitar'},
+          {name: 'Christopher Walken', role: 'cowbell'}
         ];
 
         Band.findOneAndUpdate(
-          { name: "Guns N' Roses" },
-          { $set: { members: members } },
-          { runValidators: true },
-          function(err) {
-            assert.ok(err);
-            done();
-          });
+            {name: "Guns N' Roses"},
+            {$set: {members: members}},
+            {runValidators: true},
+            function (err) {
+              assert.ok(err);
+              done();
+            });
       });
 
-      it('validators on arrays (gh-3724)', function(done) {
+      it('validators on arrays (gh-3724)', function (done) {
         var schema = new Schema({
           arr: [String]
         });
 
-        schema.path('arr').validate(function() {
+        schema.path('arr').validate(function () {
           return false;
         });
 
         var M = db.model('gh3724', schema);
-        var options = { runValidators: true };
-        M.findOneAndUpdate({}, { arr: ['test'] }, options, function(error) {
+        var options = {runValidators: true};
+        M.findOneAndUpdate({}, {arr: ['test']}, options, function (error) {
           assert.ok(error);
           assert.ok(/ValidationError/.test(error.toString()));
           done();
@@ -1437,7 +1457,7 @@ describe('model: update:', function() {
     });
   });
 
-  it('works with overwrite but no $set (gh-2568)', function(done) {
+  it('works with overwrite but no $set (gh-2568)', function (done) {
     var db = start();
 
     var chapterSchema = {
@@ -1458,20 +1478,20 @@ describe('model: update:', function() {
       id: 0
     };
 
-    Book.update({}, jsonObject, { upsert: true, overwrite: true },
-      function(error) {
-        assert.ifError(error);
-        Book.findOne({ id: 0 }, function(error, book) {
+    Book.update({}, jsonObject, {upsert: true, overwrite: true},
+        function (error) {
           assert.ifError(error);
-          assert.equal(book.chapters.length, 2);
-          assert.ok(book.chapters[0]._id);
-          assert.ok(book.chapters[1]._id);
-          db.close(done);
+          Book.findOne({id: 0}, function (error, book) {
+            assert.ifError(error);
+            assert.equal(book.chapters.length, 2);
+            assert.ok(book.chapters[0]._id);
+            assert.ok(book.chapters[1]._id);
+            db.close(done);
+          });
         });
-      });
   });
 
-  it('works with undefined date (gh-2833)', function(done) {
+  it('works with undefined date (gh-2833)', function (done) {
     var db = start();
 
     var dateSchema = {
@@ -1479,29 +1499,31 @@ describe('model: update:', function() {
     };
     var D = db.model('gh2833', dateSchema);
 
-    assert.doesNotThrow(function() {
-      D.update({}, { d: undefined }, function() {
+    assert.doesNotThrow(function () {
+      D.update({}, {d: undefined}, function () {
         db.close(done);
       });
     });
   });
 
-  it('does not add virtuals to update (gh-2046)', function(done) {
+  it('does not add virtuals to update (gh-2046)', function (done) {
     var db = start();
 
-    var childSchema = Schema({ foo: String }, { toObject: { getters: true } });
-    var parentSchema = Schema({ children: [childSchema] });
+    var childSchema = Schema({foo: String}, {toObject: {getters: true}});
+    var parentSchema = Schema({children: [childSchema]});
 
-    childSchema.virtual('bar').get(function() { return 'bar'; });
+    childSchema.virtual('bar').get(function () {
+      return 'bar';
+    });
 
     var Parent = db.model('gh2046', parentSchema, 'gh2046');
 
-    var update = Parent.update({}, { $push: { children: { foo: 'foo' } } }, { upsert: true });
+    var update = Parent.update({}, {$push: {children: {foo: 'foo'}}}, {upsert: true});
     assert.equal(update._update.$push.children.bar, undefined);
 
-    update.exec(function(error) {
+    update.exec(function (error) {
       assert.ifError(error);
-      Parent.findOne({}, function(error, doc) {
+      Parent.findOne({}, function (error, doc) {
         assert.ifError(error);
         assert.equal(doc.children.length, 1);
         assert.ok(!doc.children[0].bar);
@@ -1510,19 +1532,19 @@ describe('model: update:', function() {
     });
   });
 
-  it('can $rename (gh-1845)', function(done) {
+  it('can $rename (gh-1845)', function (done) {
     var db = start();
 
-    var schema = Schema({ foo: Date, bar: Date });
+    var schema = Schema({foo: Date, bar: Date});
     var Model = db.model('gh1845', schema, 'gh1845');
 
-    Model.update({}, { $rename: { foo: 'bar' } }, function(error) {
+    Model.update({}, {$rename: {foo: 'bar'}}, function (error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('doesnt modify original argument doc (gh-3008)', function(done) {
+  it('doesnt modify original argument doc (gh-3008)', function (done) {
     var db = start();
     var FooSchema = new mongoose.Schema({
       key: Number,
@@ -1530,143 +1552,143 @@ describe('model: update:', function() {
     });
     var Model = db.model('gh3008', FooSchema);
 
-    var update = { $set: { values: 2, value: 2 } };
-    Model.update({ key: 1 }, update, function() {
+    var update = {$set: {values: 2, value: 2}};
+    Model.update({key: 1}, update, function () {
       assert.equal(update.$set.values, 2);
       db.close(done);
     });
   });
 
-  it('can $rename (gh-1845)', function(done) {
+  it('can $rename (gh-1845)', function (done) {
     var db = start();
-    var schema = Schema({ foo: Date, bar: Date });
+    var schema = Schema({foo: Date, bar: Date});
     var Model = db.model('gh1845', schema, 'gh1845');
 
-    Model.update({}, { $rename: { foo: 'bar' } }, function(error) {
+    Model.update({}, {$rename: {foo: 'bar'}}, function (error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('allows objects with positional operator (gh-3185)', function(done) {
+  it('allows objects with positional operator (gh-3185)', function (done) {
     var db = start();
-    var schema = Schema({ children: [{ _id: Number }] });
+    var schema = Schema({children: [{_id: Number}]});
     var MyModel = db.model('gh3185', schema, 'gh3185');
 
-    MyModel.create({ children: [{ _id: 1 }] }, function(error, doc) {
+    MyModel.create({children: [{_id: 1}]}, function (error, doc) {
       assert.ifError(error);
       MyModel.findOneAndUpdate(
-        { _id: doc._id, 'children._id': 1 },
-        { $set: { 'children.$': { _id: 2 } } },
-        { 'new': true },
-        function(error, doc) {
-          assert.ifError(error);
-          assert.equal(doc.children[0]._id, 2);
-          db.close(done);
-        });
+          {_id: doc._id, 'children._id': 1},
+          {$set: {'children.$': {_id: 2}}},
+          {'new': true},
+          function (error, doc) {
+            assert.ifError(error);
+            assert.equal(doc.children[0]._id, 2);
+            db.close(done);
+          });
     });
   });
 
-  it('mixed type casting (gh-3305)', function(done) {
+  it('mixed type casting (gh-3305)', function (done) {
     var db = start();
 
-    var Schema = mongoose.Schema({}, { strict: false });
+    var Schema = mongoose.Schema({}, {strict: false});
     var Model = db.model('gh3305', Schema);
 
-    Model.create({}, function(error, m) {
+    Model.create({}, function (error, m) {
       assert.ifError(error);
       Model.
-        update({ _id: m._id }, { '$push': { 'myArr': { 'key': 'Value' } } }).
-        exec(function(error, res) {
-          assert.ifError(error);
-          assert.equal(res.n, 1);
-          db.close(done);
-        });
+      update({_id: m._id}, {'$push': {'myArr': {'key': 'Value'}}}).
+      exec(function (error, res) {
+        assert.ifError(error);
+        assert.equal(res.n, 1);
+        db.close(done);
+      });
     });
   });
 
-  it('mixed nested type casting (gh-3337)', function(done) {
+  it('mixed nested type casting (gh-3337)', function (done) {
     var db = start();
 
-    var Schema = mongoose.Schema({ attributes: {} }, { strict: true });
+    var Schema = mongoose.Schema({attributes: {}}, {strict: true});
     var Model = db.model('gh3337', Schema);
 
-    Model.create({}, function(error, m) {
+    Model.create({}, function (error, m) {
       assert.ifError(error);
-      var update = { '$push': { 'attributes.scores.bar': { a: 1 } } };
+      var update = {'$push': {'attributes.scores.bar': {a: 1}}};
       Model.
-        update({ _id: m._id }, update).
-        exec(function(error, res) {
+      update({_id: m._id}, update).
+      exec(function (error, res) {
+        assert.ifError(error);
+        assert.equal(res.n, 1);
+        Model.findById(m._id, function (error, doc) {
           assert.ifError(error);
-          assert.equal(res.n, 1);
-          Model.findById(m._id, function(error, doc) {
-            assert.ifError(error);
-            assert.equal(doc.attributes.scores.bar.length, 1);
-            db.close(done);
-          });
+          assert.equal(doc.attributes.scores.bar.length, 1);
+          db.close(done);
         });
+      });
     });
   });
 
-  it('works with buffers (gh-3496)', function(done) {
+  it('works with buffers (gh-3496)', function (done) {
     var db = start();
 
-    var Schema = mongoose.Schema({ myBufferField: Buffer });
+    var Schema = mongoose.Schema({myBufferField: Buffer});
     var Model = db.model('gh3496', Schema);
 
-    Model.update({}, { myBufferField: new Buffer(1) }, function(error) {
+    Model.update({}, {myBufferField: new Buffer(1)}, function (error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('dontThrowCastError option (gh-3512)', function(done) {
+  it('dontThrowCastError option (gh-3512)', function (done) {
     var db = start();
 
-    var Schema = mongoose.Schema({ name: String });
+    var Schema = mongoose.Schema({name: String});
     var Model = db.model('gh3412', Schema);
 
-    var badQuery = { _id: 'foo' };
-    var update = { name: 'test' };
-    var options = { dontThrowCastError: true };
-    Model.update(badQuery, update, options).then(null, function(error) {
+    var badQuery = {_id: 'foo'};
+    var update = {name: 'test'};
+    var options = {dontThrowCastError: true};
+    Model.update(badQuery, update, options).then(null, function (error) {
       assert.ok(error);
       db.close(done);
     });
   });
 
-  it('.update(doc) (gh-3221)', function(done) {
+  it('.update(doc) (gh-3221)', function (done) {
     var db = start();
 
-    var Schema = mongoose.Schema({ name: String });
+    var Schema = mongoose.Schema({name: String});
     var Model = db.model('gh3412', Schema);
 
-    var query = Model.update({ name: 'Val' });
+    var query = Model.update({name: 'Val'});
     assert.equal(query.getUpdate().$set.name, 'Val');
 
-    query = Model.find().update({ name: 'Val' });
+    query = Model.find().update({name: 'Val'});
     assert.equal(query.getUpdate().$set.name, 'Val');
 
     db.close(done);
   });
 
-  it('middleware update with exec (gh-3549)', function(done) {
+  it('middleware update with exec (gh-3549)', function (done) {
     var db = start();
 
-    var Schema = mongoose.Schema({ name: String });
+    var Schema = mongoose.Schema({name: String});
 
-    Schema.pre('update', function(next) {
-      this.update({ name: 'Val' });
+    Schema.pre('update', function (next) {
+      this.update({name: 'Val'});
       next();
     });
 
     var Model = db.model('gh3549', Schema);
 
-    Model.create({}, function(error, doc) {
+    Model.create({}, function (error, doc) {
       assert.ifError(error);
-      Model.update({ _id: doc._id }, { name: 'test' }).exec(function(error) {
+      Model.update({_id: doc._id}, {name: 'test'}).exec(function (error) {
         assert.ifError(error);
-        Model.findOne({ _id: doc._id }, function(error, doc) {
+        Model.findOne({_id: doc._id}, function (error, doc) {
           assert.ifError(error);
           assert.equal(doc.name, 'Val');
           db.close(done);
@@ -1675,7 +1697,7 @@ describe('model: update:', function() {
     });
   });
 
-  it('casting $push with overwrite (gh-3564)', function(done) {
+  it('casting $push with overwrite (gh-3564)', function (done) {
     var db = start();
 
     var schema = mongoose.Schema({
@@ -1692,15 +1714,15 @@ describe('model: update:', function() {
 
     var M = db.model('gh-3564', schema);
 
-    M.create(doc, function(err) {
+    M.create(doc, function (err) {
       assert.ifError(err);
 
-      var update = { $push: { followers: 200 } };
-      var opts = { overwrite: true, new: true, safe: true, upsert: false, multi: false};
+      var update = {$push: {followers: 200}};
+      var opts = {overwrite: true, new: true, safe: true, upsert: false, multi: false};
 
-      M.update({ topicId: doc.topicId }, update, opts, function(err) {
+      M.update({topicId: doc.topicId}, update, opts, function (err) {
         assert.ifError(err);
-        M.findOne({ topicId: doc.topicId }, function(error, doc) {
+        M.findOne({topicId: doc.topicId}, function (error, doc) {
           assert.ifError(error);
           assert.equal(doc.name, 'name');
           assert.deepEqual(doc.followers.toObject(), [500, 200]);
diff --git a/test/object.create.null.test.js b/test/object.create.null.test.js
index 8313fa0fb86..325ee46334a 100644
--- a/test/object.create.null.test.js
+++ b/test/object.create.null.test.js
@@ -13,37 +13,37 @@ var schema = new Schema({
   a: String,
   b: {
     c: Number,
-    d: [{ e: String }]
+    d: [{e: String}]
   },
-  f: { g: Date },
+  f: {g: Date},
   h: {}
 });
 
-describe('is compatible with object created using Object.create(null) (gh-1484)', function() {
+describe('is compatible with object created using Object.create(null) (gh-1484)', function () {
   var db;
   var M;
 
-  before(function() {
+  before(function () {
     db = start();
     M = db.model('1484', schema);
   });
 
-  after(function(done) {
+  after(function (done) {
     db.close(done);
   });
 
-  it('during construction', function(done) {
-    assert.doesNotThrow(function() {
+  it('during construction', function (done) {
+    assert.doesNotThrow(function () {
       new M(Object.create(null));
     });
 
-    assert.doesNotThrow(function() {
+    assert.doesNotThrow(function () {
       var o = Object.create(null);
       o.b = Object.create(null);
       new M(o);
     });
 
-    assert.doesNotThrow(function() {
+    assert.doesNotThrow(function () {
       var o = Object.create(null);
 
       o.b = Object.create(null);
@@ -71,13 +71,13 @@ describe('is compatible with object created using Object.create(null) (gh-1484)'
       assert.equal(date, m.f.g);
       assert.equal(1, m.h.ad);
       assert.equal(2, m.h.hoc);
-      assert.deepEqual({},m.h.obj);
+      assert.deepEqual({}, m.h.obj);
     });
 
     done();
   });
 
-  it('with .set(path, obj)', function(done) {
+  it('with .set(path, obj)', function (done) {
     var m = new M;
 
     var b = Object.create(null);
@@ -105,30 +105,30 @@ describe('is compatible with object created using Object.create(null) (gh-1484)'
     done();
   });
 
-  it('with schema', function(done) {
+  it('with schema', function (done) {
     var o = Object.create(null);
     o.name = String;
     o.created = Date;
     o.nested = Object.create(null);
     o.nested.n = Number;
 
-    assert.doesNotThrow(function() {
+    assert.doesNotThrow(function () {
       new Schema(o);
     });
 
-    assert.doesNotThrow(function() {
+    assert.doesNotThrow(function () {
       var s = new Schema;
       var o = Object.create(null);
       o.yay = Number;
       s.path('works', o);
     });
 
-    assert.doesNotThrow(function() {
+    assert.doesNotThrow(function () {
       var s = new Schema;
       var o = Object.create(null);
       o = {};
       o.name = String;
-      var x = { type: [o] };
+      var x = {type: [o]};
       s.path('works', x);
     });
 
diff --git a/test/promise.test.js b/test/promise.test.js
index 281eb9276c4..2e7130714bc 100644
--- a/test/promise.test.js
+++ b/test/promise.test.js
@@ -11,12 +11,12 @@ var Promise = require('../lib/promise');
  * Test.
  */
 
-describe('Promise', function() {
-  it('events fire right after complete()', function(done) {
+describe('Promise', function () {
+  it('events fire right after complete()', function (done) {
     var promise = new Promise(),
         called = 0;
 
-    promise.on('fulfill', function(a, b) {
+    promise.on('fulfill', function (a, b) {
       assert.equal(a, '1');
       assert.equal(b, '2');
       called++;
@@ -24,7 +24,7 @@ describe('Promise', function() {
 
     promise.complete('1', '2');
 
-    promise.on('fulfill', function(a, b) {
+    promise.on('fulfill', function (a, b) {
       assert.equal(a, '1');
       assert.equal(b, '2');
       called++;
@@ -34,18 +34,18 @@ describe('Promise', function() {
     done();
   });
 
-  it('events fire right after error()', function(done) {
+  it('events fire right after error()', function (done) {
     var promise = new Promise(),
         called = 0;
 
-    promise.on('reject', function(err) {
+    promise.on('reject', function (err) {
       assert.ok(err instanceof Error);
       called++;
     });
 
     promise.error('booyah');
 
-    promise.on('reject', function(err) {
+    promise.on('reject', function (err) {
       assert.ok(err instanceof Error);
       called++;
     });
@@ -54,18 +54,18 @@ describe('Promise', function() {
     done();
   });
 
-  it('events fire right after reject()', function(done) {
+  it('events fire right after reject()', function (done) {
     var promise = new Promise(),
         called = 0;
 
-    promise.on('reject', function(err) {
+    promise.on('reject', function (err) {
       assert.equal(9, err);
       called++;
     });
 
     promise.reject(9);
 
-    promise.on('reject', function(err) {
+    promise.on('reject', function (err) {
       assert.equal(9, err);
       called++;
     });
@@ -74,11 +74,11 @@ describe('Promise', function() {
     done();
   });
 
-  describe('onResolve()', function() {
-    it('from constructor works', function(done) {
+  describe('onResolve()', function () {
+    it('from constructor works', function (done) {
       var called = 0;
 
-      var promise = new Promise(function(err) {
+      var promise = new Promise(function (err) {
         assert.ok(err instanceof Error);
         called++;
       });
@@ -89,18 +89,18 @@ describe('Promise', function() {
       done();
     });
 
-    it('after fulfill()', function(done) {
+    it('after fulfill()', function (done) {
       var promise = new Promise(),
           called = 0;
 
       promise.fulfill('woot');
 
-      promise.onResolve(function(err, data) {
-        assert.equal(data,'woot');
+      promise.onResolve(function (err, data) {
+        assert.equal(data, 'woot');
         called++;
       });
 
-      promise.onResolve(function(err) {
+      promise.onResolve(function (err) {
         assert.strictEqual(err, null);
         called++;
       });
@@ -109,18 +109,18 @@ describe('Promise', function() {
       done();
     });
 
-    it('after error()', function(done) {
+    it('after error()', function (done) {
       var promise = new Promise(),
           called = 0;
 
       promise.error(new Error('woot'));
 
-      promise.onResolve(function(err) {
+      promise.onResolve(function (err) {
         assert.ok(err instanceof Error);
         called++;
       });
 
-      promise.onResolve(function(err) {
+      promise.onResolve(function (err) {
         assert.ok(err instanceof Error);
         called++;
       });
@@ -129,12 +129,12 @@ describe('Promise', function() {
     });
   });
 
-  describe('onFulfill() shortcut', function() {
-    it('works', function(done) {
+  describe('onFulfill() shortcut', function () {
+    it('works', function (done) {
       var promise = new Promise(),
           called = 0;
 
-      promise.onFulfill(function(woot) {
+      promise.onFulfill(function (woot) {
         assert.strictEqual(woot, undefined);
         called++;
       });
@@ -146,12 +146,12 @@ describe('Promise', function() {
     });
   });
 
-  describe('onReject shortcut', function() {
-    it('works', function(done) {
+  describe('onReject shortcut', function () {
+    it('works', function (done) {
       var promise = new Promise(),
           called = 0;
 
-      promise.onReject(function(err) {
+      promise.onReject(function (err) {
         assert.ok(err instanceof Error);
         called++;
       });
@@ -162,34 +162,34 @@ describe('Promise', function() {
     });
   });
 
-  describe('return values', function() {
-    it('on()', function(done) {
+  describe('return values', function () {
+    it('on()', function (done) {
       var promise = new Promise();
-      assert.ok(promise.on('jump', function() {}) instanceof Promise);
+      assert.ok(promise.on('jump', function () {}) instanceof Promise);
       done();
     });
 
-    it('onFulfill()', function(done) {
+    it('onFulfill()', function (done) {
       var promise = new Promise();
-      assert.ok(promise.onFulfill(function() {}) instanceof Promise);
+      assert.ok(promise.onFulfill(function () {}) instanceof Promise);
       done();
     });
-    it('onReject()', function(done) {
+    it('onReject()', function (done) {
       var promise = new Promise();
-      assert.ok(promise.onReject(function() {}) instanceof Promise);
+      assert.ok(promise.onReject(function () {}) instanceof Promise);
       done();
     });
-    it('onResolve()', function(done) {
+    it('onResolve()', function (done) {
       var promise = new Promise();
-      assert.ok(promise.onResolve(function() {}) instanceof Promise);
+      assert.ok(promise.onResolve(function () {}) instanceof Promise);
       done();
     });
   });
 
-  describe('casting errors', function() {
-    describe('error()', function() {
-      it('casts arguments to Error', function(done) {
-        var p = new Promise(function(err) {
+  describe('casting errors', function () {
+    describe('error()', function () {
+      it('casts arguments to Error', function (done) {
+        var p = new Promise(function (err) {
           assert.ok(err instanceof Error);
           assert.equal('3', err.message);
           done();
@@ -199,9 +199,9 @@ describe('Promise', function() {
       });
     });
 
-    describe('reject()', function() {
-      it('does not cast arguments to Error', function(done) {
-        var p = new Promise(function(err) {
+    describe('reject()', function () {
+      it('does not cast arguments to Error', function (done) {
+        var p = new Promise(function (err) {
           assert.equal(3, err);
           done();
         });
@@ -211,9 +211,9 @@ describe('Promise', function() {
     });
   });
 
-  it('doesnt swallow exceptions (gh-3222)', function(done) {
-    assert.throws(function() {
-      new Promise.ES6(function() {
+  it('doesnt swallow exceptions (gh-3222)', function (done) {
+    assert.throws(function () {
+      new Promise.ES6(function () {
         throw 'bacon';
       });
     });
diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js
index 48be6344b40..7ac9ccde3cb 100644
--- a/test/promise_provider.test.js
+++ b/test/promise_provider.test.js
@@ -14,20 +14,20 @@ var Schema = require('../lib/schema');
 
 var Promise;
 var db;
-var testSchema = new Schema({ test: { type: String, required: true } });
-testSchema.pre('save', function(next) {
+var testSchema = new Schema({test: {type: String, required: true}});
+testSchema.pre('save', function (next) {
   if (this.$__saveSucceeds === false) {
     return next(new Error('fail'));
   }
   next();
 });
-testSchema.pre('validate', function(next) {
+testSchema.pre('validate', function (next) {
   if (this.$__validateSucceeds === false) {
     return next(new Error('validation failed'));
   }
   next();
 });
-testSchema.pre('findOne', function(next) {
+testSchema.pre('findOne', function (next) {
   if (this.$__findOneSucceeds === false) {
     return next(new Error('findOne failed'));
   }
@@ -35,131 +35,131 @@ testSchema.pre('findOne', function(next) {
 });
 var MyModel;
 
-describe('ES6 promises: ', function() {
-  describe('native: ', function() {
+describe('ES6 promises: ', function () {
+  describe('native: ', function () {
     if (!global.Promise) {
       return;
     }
 
-    before(function() {
+    before(function () {
       PromiseProvider.set(global.Promise);
       Promise = PromiseProvider.get();
     });
 
-    before(function() {
+    before(function () {
       db = start();
       MyModel = db.model('es6promise', testSchema);
     });
 
-    after(function(done) {
+    after(function (done) {
       PromiseProvider.reset();
       db.close(done);
     });
 
-    afterEach(function(done) {
+    afterEach(function (done) {
       MyModel.remove({}, done);
     });
 
-    it('save()', function(done) {
-      var m = new MyModel({ test: '123' });
+    it('save()', function (done) {
+      var m = new MyModel({test: '123'});
       var promise = m.save();
       assert.equal(promise.constructor, global.Promise);
-      promise.then(function(doc) {
+      promise.then(function (doc) {
         assert.equal(m, doc);
         done();
       });
     });
 
-    it('save() with validation error', function(done) {
+    it('save() with validation error', function (done) {
       var m = new MyModel({});
       var promise = m.save();
       assert.equal(promise.constructor, global.Promise);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.ok(err.errors['test']);
           done();
         });
     });
 
-    it('save() with middleware error', function(done) {
-      var m = new MyModel({ test: '123' });
+    it('save() with middleware error', function (done) {
+      var m = new MyModel({test: '123'});
       m.$__saveSucceeds = false;
       var promise = m.save();
       assert.equal(promise.constructor, global.Promise);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: fail');
           done();
         });
     });
 
-    it('save() with validation middleware error', function(done) {
-      var m = new MyModel({ test: '123' });
+    it('save() with validation middleware error', function (done) {
+      var m = new MyModel({test: '123'});
       m.$__validateSucceeds = false;
       var promise = m.save();
       assert.equal(promise.constructor, global.Promise);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: validation failed');
           done();
         });
     });
 
-    it('validate()', function(done) {
+    it('validate()', function (done) {
       var m = new MyModel({});
       var promise = m.validate();
       assert.equal(promise.constructor, global.Promise);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.ok(err.errors['test']);
           done();
         });
     });
 
-    it('queries', function(done) {
-      MyModel.create({ test: '123' }, function(error) {
+    it('queries', function (done) {
+      MyModel.create({test: '123'}, function (error) {
         assert.ifError(error);
 
-        var promise = MyModel.findOne({ test: '123' }).exec();
+        var promise = MyModel.findOne({test: '123'}).exec();
         assert.equal(promise.constructor, global.Promise);
 
-        promise.then(function(doc) {
+        promise.then(function (doc) {
           assert.equal(doc.test, '123');
           done();
         });
       });
     });
 
-    it('queries with errors', function(done) {
-      MyModel.create({ test: '123' }, function(error) {
+    it('queries with errors', function (done) {
+      MyModel.create({test: '123'}, function (error) {
         assert.ifError(error);
 
-        var query = MyModel.findOne({ test: '123' });
+        var query = MyModel.findOne({test: '123'});
         query.$__findOneSucceeds = false;
         var promise = query.exec();
         assert.equal(promise.constructor, global.Promise);
 
         promise.
-          then(function() {
+          then(function () {
             assert.ok(false);
           }).
-          catch(function(err) {
+          catch(function (err) {
             assert.ok(err);
             assert.equal(err.toString(), 'Error: findOne failed');
             done();
@@ -167,135 +167,135 @@ describe('ES6 promises: ', function() {
       });
     });
 
-    it('create', function(done) {
-      var promise = MyModel.create({ test: '123' });
+    it('create', function (done) {
+      var promise = MyModel.create({test: '123'});
       assert.equal(promise.constructor, global.Promise);
-      promise.then(function() {
+      promise.then(function () {
         done();
       });
     });
   });
 
-  describe('bluebird: ', function() {
-    before(function() {
+  describe('bluebird: ', function () {
+    before(function () {
       PromiseProvider.set(bluebird);
       Promise = PromiseProvider.get();
     });
 
-    before(function() {
+    before(function () {
       db = start();
       MyModel = db.model('es6promise_bluebird', testSchema);
     });
 
-    after(function(done) {
+    after(function (done) {
       PromiseProvider.reset();
       db.close(done);
     });
 
-    afterEach(function(done) {
+    afterEach(function (done) {
       MyModel.remove({}, done);
     });
 
-    it('save()', function(done) {
-      var m = new MyModel({ test: '123' });
+    it('save()', function (done) {
+      var m = new MyModel({test: '123'});
       var promise = m.save();
       assert.equal(promise.constructor, bluebird);
-      promise.then(function(doc) {
+      promise.then(function (doc) {
         assert.equal(m, doc);
         done();
       });
     });
 
-    it('save() with validation error', function(done) {
+    it('save() with validation error', function (done) {
       var m = new MyModel({});
       var promise = m.save();
       assert.equal(promise.constructor, bluebird);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.ok(err.errors['test']);
           done();
         });
     });
 
-    it('save() with middleware error', function(done) {
-      var m = new MyModel({ test: '123' });
+    it('save() with middleware error', function (done) {
+      var m = new MyModel({test: '123'});
       m.$__saveSucceeds = false;
       var promise = m.save();
       assert.equal(promise.constructor, bluebird);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: fail');
           done();
         });
     });
 
-    it('save() with validation middleware error', function(done) {
-      var m = new MyModel({ test: '123' });
+    it('save() with validation middleware error', function (done) {
+      var m = new MyModel({test: '123'});
       m.$__validateSucceeds = false;
       var promise = m.save();
       assert.equal(promise.constructor, bluebird);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: validation failed');
           done();
         });
     });
 
-    it('validate()', function(done) {
+    it('validate()', function (done) {
       var m = new MyModel({});
       var promise = m.validate();
       assert.equal(promise.constructor, bluebird);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.ok(err.errors['test']);
           done();
         });
     });
 
-    it('queries', function(done) {
-      MyModel.create({ test: '123' }, function(error) {
+    it('queries', function (done) {
+      MyModel.create({test: '123'}, function (error) {
         assert.ifError(error);
 
-        var promise = MyModel.findOne({ test: '123' }).exec();
+        var promise = MyModel.findOne({test: '123'}).exec();
         assert.equal(promise.constructor, bluebird);
 
-        promise.then(function(doc) {
+        promise.then(function (doc) {
           assert.equal(doc.test, '123');
           done();
         });
       });
     });
 
-    it('queries with errors', function(done) {
-      MyModel.create({ test: '123' }, function(error) {
+    it('queries with errors', function (done) {
+      MyModel.create({test: '123'}, function (error) {
         assert.ifError(error);
 
-        var query = MyModel.findOne({ test: '123' });
+        var query = MyModel.findOne({test: '123'});
         query.$__findOneSucceeds = false;
         var promise = query.exec();
         assert.equal(promise.constructor, bluebird);
 
         promise.
-          then(function() {
+          then(function () {
             assert.ok(false);
           }).
-          catch(function(err) {
+          catch(function (err) {
             assert.ok(err);
             assert.equal(err.toString(), 'Error: findOne failed');
             done();
@@ -303,42 +303,41 @@ describe('ES6 promises: ', function() {
       });
     });
 
-    it('create', function(done) {
-      var promise = MyModel.create({ test: '123' });
+    it('create', function (done) {
+      var promise = MyModel.create({test: '123'});
       assert.equal(promise.constructor, bluebird);
-      promise.then(function() {
-
+      promise.then(function () {
         var p = MyModel.create({});
-        p.catch(function(error) {
+        p.catch(function (error) {
           assert.ok(error);
           done();
         });
       });
     });
 
-    it('subdocument validation (gh-3681)', function(done) {
-      var subSchema = new Schema({ name: { type: String, required: true } });
-      var parentSchema = new Schema({ sub: [subSchema] });
+    it('subdocument validation (gh-3681)', function (done) {
+      var subSchema = new Schema({name: {type: String, required: true}});
+      var parentSchema = new Schema({sub: [subSchema]});
       var Parent = db.model('gh3681', parentSchema);
 
-      Parent.create({ sub: [{}] }).catch(function() {
+      Parent.create({sub: [{}]}).catch(function () {
         done();
       });
     });
 
-    it('Model.populate (gh-3734)', function(done) {
+    it('Model.populate (gh-3734)', function (done) {
       var doc = new MyModel({});
       var promise = MyModel.populate(doc, 'test');
       assert.equal(promise.constructor, bluebird);
       done();
     });
 
-    it('subdoc pre doesnt cause unhandled rejection (gh-3669)', function(done) {
+    it('subdoc pre doesnt cause unhandled rejection (gh-3669)', function (done) {
       var nestedSchema = new Schema({
-        name: { type: String, required: true }
+        name: {type: String, required: true}
       });
 
-      nestedSchema.pre('validate', function(next) {
+      nestedSchema.pre('validate', function (next) {
         next();
       });
 
@@ -348,133 +347,133 @@ describe('ES6 promises: ', function() {
 
       var MyModel = db.model('gh3669', schema);
 
-      MyModel.create({ items: [{ name: null}] }).catch(function(error) {
+      MyModel.create({items: [{name: null}]}).catch(function (error) {
         assert.ok(error);
         done();
       });
     });
   });
 
-  describe('q: ', function() {
-    before(function() {
+  describe('q: ', function () {
+    before(function () {
       PromiseProvider.set(q.Promise);
       Promise = PromiseProvider.get();
     });
 
-    before(function() {
+    before(function () {
       db = start();
       MyModel = db.model('es6promise_q', testSchema);
     });
 
-    after(function(done) {
+    after(function (done) {
       PromiseProvider.reset();
       db.close(done);
     });
 
-    afterEach(function(done) {
+    afterEach(function (done) {
       MyModel.remove({}, done);
     });
 
-    it('save()', function(done) {
-      var m = new MyModel({ test: '123' });
+    it('save()', function (done) {
+      var m = new MyModel({test: '123'});
       var promise = m.save();
       assert.ok(promise instanceof q.makePromise);
-      promise.then(function(doc) {
+      promise.then(function (doc) {
         assert.equal(m, doc);
         done();
       });
     });
 
-    it('save() with validation error', function(done) {
+    it('save() with validation error', function (done) {
       var m = new MyModel({});
       var promise = m.save();
       assert.ok(promise instanceof q.makePromise);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.ok(err.errors['test']);
           done();
         });
     });
 
-    it('save() with middleware error', function(done) {
-      var m = new MyModel({ test: '123' });
+    it('save() with middleware error', function (done) {
+      var m = new MyModel({test: '123'});
       m.$__saveSucceeds = false;
       var promise = m.save();
       assert.ok(promise instanceof q.makePromise);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: fail');
           done();
         });
     });
 
-    it('save() with validation middleware error', function(done) {
-      var m = new MyModel({ test: '123' });
+    it('save() with validation middleware error', function (done) {
+      var m = new MyModel({test: '123'});
       m.$__validateSucceeds = false;
       var promise = m.save();
       assert.ok(promise instanceof q.makePromise);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: validation failed');
           done();
         });
     });
 
-    it('validate()', function(done) {
+    it('validate()', function (done) {
       var m = new MyModel({});
       var promise = m.validate();
       assert.ok(promise instanceof q.makePromise);
       promise.
-        then(function() {
+        then(function () {
           assert.ok(false);
         }).
-        catch(function(err) {
+        catch(function (err) {
           assert.ok(err);
           assert.ok(err.errors['test']);
           done();
         });
     });
 
-    it('queries', function(done) {
-      MyModel.create({ test: '123' }, function(error) {
+    it('queries', function (done) {
+      MyModel.create({test: '123'}, function (error) {
         assert.ifError(error);
 
-        var promise = MyModel.findOne({ test: '123' }).exec();
+        var promise = MyModel.findOne({test: '123'}).exec();
         assert.ok(promise instanceof q.makePromise);
 
-        promise.then(function(doc) {
+        promise.then(function (doc) {
           assert.equal(doc.test, '123');
           done();
         });
       });
     });
 
-    it('queries with errors', function(done) {
-      MyModel.create({ test: '123' }, function(error) {
+    it('queries with errors', function (done) {
+      MyModel.create({test: '123'}, function (error) {
         assert.ifError(error);
 
-        var query = MyModel.findOne({ test: '123' });
+        var query = MyModel.findOne({test: '123'});
         query.$__findOneSucceeds = false;
         var promise = query.exec();
         assert.ok(promise instanceof q.makePromise);
 
         promise.
-          then(function() {
+          then(function () {
             assert.ok(false);
           }).
-          catch(function(err) {
+          catch(function (err) {
             assert.ok(err);
             assert.equal(err.toString(), 'Error: findOne failed');
             done();
@@ -482,10 +481,10 @@ describe('ES6 promises: ', function() {
       });
     });
 
-    it('create', function(done) {
-      var promise = MyModel.create({ test: '123' });
+    it('create', function (done) {
+      var promise = MyModel.create({test: '123'});
       assert.ok(promise instanceof q.makePromise);
-      promise.then(function() {
+      promise.then(function () {
         done();
       });
     });
diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js
index e7a46db7b96..10e18add18f 100644
--- a/test/query.middleware.test.js
+++ b/test/query.middleware.test.js
@@ -3,27 +3,27 @@ var assert = require('assert');
 var mongoose = start.mongoose;
 var Schema = mongoose.Schema;
 
-describe('query middleware', function() {
+describe('query middleware', function () {
   var db;
   var schema;
   var publisherSchema;
   var Author;
   var Publisher;
 
-  var initializeData = function(done) {
+  var initializeData = function (done) {
     Author = db.model('gh-2138', schema, 'gh-2138');
     Publisher = db.model('gh-2138-1', publisherSchema, 'gh-2138-1');
 
-    Author.remove({}, function(error) {
+    Author.remove({}, function (error) {
       if (error) {
         return done(error);
       }
 
-      Publisher.remove({}, function(error) {
+      Publisher.remove({}, function (error) {
         if (error) {
           return done(error);
         }
-        Publisher.create({ name: 'Wiley' }, function(error, publisher) {
+        Publisher.create({name: 'Wiley'}, function (error, publisher) {
           if (error) {
             return done(error);
           }
@@ -35,7 +35,7 @@ describe('query middleware', function() {
             options: 'bacon'
           };
 
-          Author.create(doc, function(error) {
+          Author.create(doc, function (error) {
             done(error);
           });
         });
@@ -43,11 +43,11 @@ describe('query middleware', function() {
     });
   };
 
-  beforeEach(function(done) {
+  beforeEach(function (done) {
     schema = new Schema({
       title: String,
       author: String,
-      publisher: { type: Schema.ObjectId, ref: 'gh-2138-1' },
+      publisher: {type: Schema.ObjectId, ref: 'gh-2138-1'},
       options: String
     });
 
@@ -60,22 +60,22 @@ describe('query middleware', function() {
     done();
   });
 
-  afterEach(function(done) {
+  afterEach(function (done) {
     db.close(done);
   });
 
-  it('has a pre find hook', function(done) {
+  it('has a pre find hook', function (done) {
     var count = 0;
-    schema.pre('find', function(next) {
+    schema.pre('find', function (next) {
       ++count;
       next();
     });
 
     start();
 
-    initializeData(function(error) {
+    initializeData(function (error) {
       assert.ifError(error);
-      Author.find({ x: 1 }, function(error) {
+      Author.find({x: 1}, function (error) {
         assert.ifError(error);
         assert.equal(1, count);
         done();
@@ -83,9 +83,9 @@ describe('query middleware', function() {
     });
   });
 
-  it('has post find hooks', function(done) {
+  it('has post find hooks', function (done) {
     var postCount = 0;
-    schema.post('find', function(results, next) {
+    schema.post('find', function (results, next) {
       assert.equal(1, results.length);
       assert.equal('Val', results[0].author);
       assert.equal('bacon', results[0].options);
@@ -93,9 +93,9 @@ describe('query middleware', function() {
       next();
     });
 
-    initializeData(function(error) {
+    initializeData(function (error) {
       assert.ifError(error);
-      Author.find({ title: 'Professional AngularJS' }, function(error, docs) {
+      Author.find({title: 'Professional AngularJS'}, function (error, docs) {
         assert.ifError(error);
         assert.equal(1, postCount);
         assert.equal(1, docs.length);
@@ -104,23 +104,23 @@ describe('query middleware', function() {
     });
   });
 
-  it('works when using a chained query builder', function(done) {
+  it('works when using a chained query builder', function (done) {
     var count = 0;
-    schema.pre('find', function(next) {
+    schema.pre('find', function (next) {
       ++count;
       next();
     });
 
     var postCount = 0;
-    schema.post('find', function(results, next) {
+    schema.post('find', function (results, next) {
       assert.equal(1, results.length);
       assert.equal('Val', results[0].author);
       ++postCount;
       next();
     });
 
-    initializeData(function() {
-      Author.find({ title: 'Professional AngularJS' }).exec(function(error, docs) {
+    initializeData(function () {
+      Author.find({title: 'Professional AngularJS'}).exec(function (error, docs) {
         assert.ifError(error);
         assert.equal(1, count);
         assert.equal(1, postCount);
@@ -130,22 +130,22 @@ describe('query middleware', function() {
     });
   });
 
-  it('has separate pre-findOne() and post-findOne() hooks', function(done) {
+  it('has separate pre-findOne() and post-findOne() hooks', function (done) {
     var count = 0;
-    schema.pre('findOne', function(next) {
+    schema.pre('findOne', function (next) {
       ++count;
       next();
     });
 
     var postCount = 0;
-    schema.post('findOne', function(result, next) {
+    schema.post('findOne', function (result, next) {
       assert.equal('Val', result.author);
       ++postCount;
       next();
     });
 
-    initializeData(function() {
-      Author.findOne({ title: 'Professional AngularJS' }).exec(function(error, doc) {
+    initializeData(function () {
+      Author.findOne({title: 'Professional AngularJS'}).exec(function (error, doc) {
         assert.ifError(error);
         assert.equal(1, count);
         assert.equal(1, postCount);
@@ -155,14 +155,14 @@ describe('query middleware', function() {
     });
   });
 
-  it('can populate in pre hook', function(done) {
-    schema.pre('findOne', function(next) {
+  it('can populate in pre hook', function (done) {
+    schema.pre('findOne', function (next) {
       this.populate('publisher');
       next();
     });
 
-    initializeData(function() {
-      Author.findOne({ title: 'Professional AngularJS' }).exec(function(error, doc) {
+    initializeData(function () {
+      Author.findOne({title: 'Professional AngularJS'}).exec(function (error, doc) {
         assert.ifError(error);
         assert.equal('Val', doc.author);
         assert.equal('Wiley', doc.publisher.name);
@@ -171,15 +171,15 @@ describe('query middleware', function() {
     });
   });
 
-  it('can populate in post hook', function(done) {
-    schema.post('findOne', function(doc, next) {
-      doc.populate('publisher', function(error) {
+  it('can populate in post hook', function (done) {
+    schema.post('findOne', function (doc, next) {
+      doc.populate('publisher', function (error) {
         next(error);
       });
     });
 
-    initializeData(function() {
-      Author.findOne({ title: 'Professional AngularJS' }).exec(function(error, doc) {
+    initializeData(function () {
+      Author.findOne({title: 'Professional AngularJS'}).exec(function (error, doc) {
         assert.ifError(error);
         assert.equal('Val', doc.author);
         assert.equal('Wiley', doc.publisher.name);
@@ -188,21 +188,21 @@ describe('query middleware', function() {
     });
   });
 
-  it('has hooks for count()', function(done) {
+  it('has hooks for count()', function (done) {
     var preCount = 0;
     var postCount = 0;
 
-    schema.pre('count', function() {
+    schema.pre('count', function () {
       ++preCount;
     });
 
-    schema.post('count', function() {
+    schema.post('count', function () {
       ++postCount;
     });
 
-    initializeData(function(error) {
+    initializeData(function (error) {
       assert.ifError(error);
-      Author.find({ title: 'Professional AngularJS' }).count(function(error, count) {
+      Author.find({title: 'Professional AngularJS'}).count(function (error, count) {
         assert.ifError(error);
         assert.equal(1, count);
         assert.equal(1, preCount);
diff --git a/test/query.test.js b/test/query.test.js
index ee796837b7d..b67595ef1e4 100644
--- a/test/query.test.js
+++ b/test/query.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -32,13 +31,13 @@ var p1;
  * Test.
  */
 
-describe('Query', function() {
-  before(function() {
+describe('Query', function () {
+  before(function () {
     var Prod = mongoose.model('Product');
     p1 = new Prod();
   });
-  describe('constructor', function() {
-    it('should not corrupt options', function(done) {
+  describe('constructor', function () {
+    it('should not corrupt options', function (done) {
       var opts = {};
       var query = new Query({}, opts, null, p1.collection);
       assert.notEqual(opts, query._mongooseOptions);
@@ -46,53 +45,53 @@ describe('Query', function() {
     });
   });
 
-  describe('select', function() {
-    it('(object)', function(done) {
+  describe('select', function () {
+    it('(object)', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.select({a: 1, b: 1, c: 0});
-      assert.deepEqual(query._fields,{a: 1, b: 1, c: 0});
+      assert.deepEqual(query._fields, {a: 1, b: 1, c: 0});
       done();
     });
 
-    it('(string)', function(done) {
+    it('(string)', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.select(" a  b -c ");
-      assert.deepEqual(query._fields,{a: 1, b: 1, c: 0});
+      query.select(' a  b -c ');
+      assert.deepEqual(query._fields, {a: 1, b: 1, c: 0});
       done();
     });
 
-    it('("a","b","c")', function(done) {
-      assert.throws(function() {
+    it('("a","b","c")', function (done) {
+      assert.throws(function () {
         var query = new Query({}, {}, null, p1.collection);
         query.select('a', 'b', 'c');
       }, /Invalid select/);
       done();
     });
 
-    it('["a","b","c"]', function(done) {
-      assert.throws(function() {
+    it('["a","b","c"]', function (done) {
+      assert.throws(function () {
         var query = new Query({}, {}, null, p1.collection);
         query.select(['a', 'b', 'c']);
       }, /Invalid select/);
       done();
     });
 
-    it('should not overwrite fields set in prior calls', function(done) {
+    it('should not overwrite fields set in prior calls', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.select('a');
-      assert.deepEqual(query._fields,{a: 1});
+      assert.deepEqual(query._fields, {a: 1});
       query.select('b');
-      assert.deepEqual(query._fields,{a: 1, b: 1});
-      query.select({ c: 0 });
-      assert.deepEqual(query._fields,{a: 1, b: 1, c: 0});
+      assert.deepEqual(query._fields, {a: 1, b: 1});
+      query.select({c: 0});
+      assert.deepEqual(query._fields, {a: 1, b: 1, c: 0});
       query.select('-d');
-      assert.deepEqual(query._fields,{a: 1, b: 1, c: 0, d: 0});
+      assert.deepEqual(query._fields, {a: 1, b: 1, c: 0, d: 0});
       done();
     });
   });
 
-  describe('where', function() {
-    it('works', function(done) {
+  describe('where', function () {
+    it('works', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('name', 'guillermo');
       assert.deepEqual(query._conditions, {name: 'guillermo'});
@@ -101,27 +100,27 @@ describe('Query', function() {
       assert.deepEqual(query._conditions, {name: 'guillermo', a: 'b'});
       done();
     });
-    it('throws if non-string or non-object path is passed', function(done) {
+    it('throws if non-string or non-object path is passed', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      assert.throws(function() {
+      assert.throws(function () {
         query.where(50);
       });
-      assert.throws(function() {
+      assert.throws(function () {
         query.where([]);
       });
       done();
     });
-    it('does not throw when 0 args passed', function(done) {
+    it('does not throw when 0 args passed', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      assert.doesNotThrow(function() {
+      assert.doesNotThrow(function () {
         query.where();
       });
       done();
     });
   });
 
-  describe('equals', function() {
-    it('works', function(done) {
+  describe('equals', function () {
+    it('works', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('name').equals('guillermo');
       assert.deepEqual(query._conditions, {name: 'guillermo'});
@@ -129,29 +128,29 @@ describe('Query', function() {
     });
   });
 
-  describe('gte', function() {
-    it('with 2 args', function(done) {
+  describe('gte', function () {
+    it('with 2 args', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.gte('age', 18);
       assert.deepEqual(query._conditions, {age: {$gte: 18}});
       done();
     });
-    it('with 1 arg', function(done) {
+    it('with 1 arg', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("age").gte(18);
+      query.where('age').gte(18);
       assert.deepEqual(query._conditions, {age: {$gte: 18}});
       done();
     });
   });
 
-  describe('gt', function() {
-    it('with 1 arg', function(done) {
+  describe('gt', function () {
+    it('with 1 arg', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("age").gt(17);
+      query.where('age').gt(17);
       assert.deepEqual(query._conditions, {age: {$gt: 17}});
       done();
     });
-    it('with 2 args', function(done) {
+    it('with 2 args', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.gt('age', 17);
       assert.deepEqual(query._conditions, {age: {$gt: 17}});
@@ -159,14 +158,14 @@ describe('Query', function() {
     });
   });
 
-  describe('lte', function() {
-    it('with 1 arg', function(done) {
+  describe('lte', function () {
+    it('with 1 arg', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("age").lte(65);
+      query.where('age').lte(65);
       assert.deepEqual(query._conditions, {age: {$lte: 65}});
       done();
     });
-    it('with 2 args', function(done) {
+    it('with 2 args', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.lte('age', 65);
       assert.deepEqual(query._conditions, {age: {$lte: 65}});
@@ -174,14 +173,14 @@ describe('Query', function() {
     });
   });
 
-  describe('lt', function() {
-    it('with 1 arg', function(done) {
+  describe('lt', function () {
+    it('with 1 arg', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("age").lt(66);
+      query.where('age').lt(66);
       assert.deepEqual(query._conditions, {age: {$lt: 66}});
       done();
     });
-    it('with 2 args', function(done) {
+    it('with 2 args', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.lt('age', 66);
       assert.deepEqual(query._conditions, {age: {$lt: 66}});
@@ -189,36 +188,36 @@ describe('Query', function() {
     });
   });
 
-  describe('combined', function() {
-    describe('lt and gt', function() {
-      it('works', function(done) {
+  describe('combined', function () {
+    describe('lt and gt', function () {
+      it('works', function (done) {
         var query = new Query({}, {}, null, p1.collection);
-        query.where("age").lt(66).gt(17);
+        query.where('age').lt(66).gt(17);
         assert.deepEqual(query._conditions, {age: {$lt: 66, $gt: 17}});
         done();
       });
     });
   });
 
-  describe('tl on one path and gt on another', function() {
-    it('works', function(done) {
+  describe('tl on one path and gt on another', function () {
+    it('works', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query
-        .where("age").lt(66)
-        .where("height").gt(5);
+      .where('age').lt(66)
+      .where('height').gt(5);
       assert.deepEqual(query._conditions, {age: {$lt: 66}, height: {$gt: 5}});
       done();
     });
   });
 
-  describe('ne', function() {
-    it('with 1 arg', function(done) {
+  describe('ne', function () {
+    it('with 1 arg', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("age").ne(21);
+      query.where('age').ne(21);
       assert.deepEqual(query._conditions, {age: {$ne: 21}});
       done();
     });
-    it('with 2 args', function(done) {
+    it('with 2 args', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.ne('age', 21);
       assert.deepEqual(query._conditions, {age: {$ne: 21}});
@@ -226,26 +225,26 @@ describe('Query', function() {
     });
   });
 
-  describe('in', function() {
-    it('with 1 arg', function(done) {
+  describe('in', function () {
+    it('with 1 arg', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("age").in([21, 25, 30]);
+      query.where('age').in([21, 25, 30]);
       assert.deepEqual(query._conditions, {age: {$in: [21, 25, 30]}});
       done();
     });
-    it('with 2 args', function(done) {
+    it('with 2 args', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.in('age', [21, 25, 30]);
       assert.deepEqual(query._conditions, {age: {$in: [21, 25, 30]}});
       done();
     });
-    it('where a non-array value no via where', function(done) {
+    it('where a non-array value no via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.in('age', 21);
       assert.deepEqual(query._conditions, {age: {$in: 21}});
       done();
     });
-    it('where a non-array value via where', function(done) {
+    it('where a non-array value via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').in(21);
       assert.deepEqual(query._conditions, {age: {$in: 21}});
@@ -253,26 +252,26 @@ describe('Query', function() {
     });
   });
 
-  describe('nin', function() {
-    it('with 1 arg', function(done) {
+  describe('nin', function () {
+    it('with 1 arg', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("age").nin([21, 25, 30]);
+      query.where('age').nin([21, 25, 30]);
       assert.deepEqual(query._conditions, {age: {$nin: [21, 25, 30]}});
       done();
     });
-    it('with 2 args', function(done) {
+    it('with 2 args', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.nin('age', [21, 25, 30]);
       assert.deepEqual(query._conditions, {age: {$nin: [21, 25, 30]}});
       done();
     });
-    it('with a non-array value not via where', function(done) {
+    it('with a non-array value not via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.nin('age', 21);
       assert.deepEqual(query._conditions, {age: {$nin: 21}});
       done();
     });
-    it('with a non-array value via where', function(done) {
+    it('with a non-array value via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').nin(21);
       assert.deepEqual(query._conditions, {age: {$nin: 21}});
@@ -280,137 +279,137 @@ describe('Query', function() {
     });
   });
 
-  describe('mod', function() {
-    it('not via where, where [a, b] param', function(done) {
+  describe('mod', function () {
+    it('not via where, where [a, b] param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.mod('age', [5, 2]);
       assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
       done();
     });
-    it('not via where, where a and b params', function(done) {
+    it('not via where, where a and b params', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.mod('age', 5, 2);
       assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
       done();
     });
-    it('via where, where [a, b] param', function(done) {
+    it('via where, where [a, b] param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("age").mod([5, 2]);
+      query.where('age').mod([5, 2]);
       assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
       done();
     });
-    it('via where, where a and b params', function(done) {
+    it('via where, where a and b params', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("age").mod(5, 2);
+      query.where('age').mod(5, 2);
       assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
       done();
     });
   });
 
-  describe('near', function() {
-    it('via where, where { center :[lat, long]} param', function(done) {
+  describe('near', function () {
+    it('via where, where { center :[lat, long]} param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where('checkin').near({ center: [40, -72]});
+      query.where('checkin').near({center: [40, -72]});
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('via where, where [lat, long] param', function(done) {
+    it('via where, where [lat, long] param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').near([40, -72]);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('via where, where lat and long params', function(done) {
+    it('via where, where lat and long params', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').near(40, -72);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('not via where, where [lat, long] param', function(done) {
+    it('not via where, where [lat, long] param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.near('checkin', [40, -72]);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('not via where, where lat and long params', function(done) {
+    it('not via where, where lat and long params', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.near('checkin', 40, -72);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('via where, where GeoJSON param', function(done) {
+    it('via where, where GeoJSON param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where('numbers').near({ center: { type: 'Point', coordinates: [40, -72 ]}});
-      assert.deepEqual(query._conditions, {numbers: {$near: { $geometry: { type: 'Point', coordinates: [40, -72] }}}});
-      assert.doesNotThrow(function() {
+      query.where('numbers').near({center: {type: 'Point', coordinates: [40, -72]}});
+      assert.deepEqual(query._conditions, {numbers: {$near: {$geometry: {type: 'Point', coordinates: [40, -72]}}}});
+      assert.doesNotThrow(function () {
         query.cast(p1.constructor);
       });
       done();
     });
-    it('with path, where GeoJSON param', function(done) {
+    it('with path, where GeoJSON param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.near('loc', { center: { type: 'Point', coordinates: [40, -72 ]}});
-      assert.deepEqual(query._conditions, {loc: {$near: { $geometry: { type: 'Point', coordinates: [40, -72] }}}});
+      query.near('loc', {center: {type: 'Point', coordinates: [40, -72]}});
+      assert.deepEqual(query._conditions, {loc: {$near: {$geometry: {type: 'Point', coordinates: [40, -72]}}}});
       done();
     });
   });
 
-  describe('nearSphere', function() {
-    it('via where, where [lat, long] param', function(done) {
+  describe('nearSphere', function () {
+    it('via where, where [lat, long] param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').nearSphere([40, -72]);
       assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
       done();
     });
-    it('via where, where lat and long params', function(done) {
+    it('via where, where lat and long params', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').nearSphere(40, -72);
       assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
       done();
     });
-    it('not via where, where [lat, long] param', function(done) {
+    it('not via where, where [lat, long] param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.nearSphere('checkin', [40, -72]);
       assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
       done();
     });
-    it('not via where, where lat and long params', function(done) {
+    it('not via where, where lat and long params', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.nearSphere('checkin', 40, -72);
       assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
       done();
     });
 
-    it('via where, with object', function(done) {
+    it('via where, with object', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where('checkin').nearSphere({ center: [20,23], maxDistance: 2 });
-      assert.deepEqual(query._conditions, {checkin: {$nearSphere: [20,23],$maxDistance:2}});
+      query.where('checkin').nearSphere({center: [20, 23], maxDistance: 2});
+      assert.deepEqual(query._conditions, {checkin: {$nearSphere: [20, 23], $maxDistance: 2}});
       done();
     });
 
-    it('via where, where GeoJSON param', function(done) {
+    it('via where, where GeoJSON param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where('numbers').nearSphere({ center: { type: 'Point', coordinates: [40, -72 ]}});
-      assert.deepEqual(query._conditions, {numbers: {$nearSphere: { $geometry: { type: 'Point', coordinates: [40, -72] }}}});
-      assert.doesNotThrow(function() {
+      query.where('numbers').nearSphere({center: {type: 'Point', coordinates: [40, -72]}});
+      assert.deepEqual(query._conditions, {numbers: {$nearSphere: {$geometry: {type: 'Point', coordinates: [40, -72]}}}});
+      assert.doesNotThrow(function () {
         query.cast(p1.constructor);
       });
       done();
     });
 
-    it('with path, with GeoJSON', function(done) {
+    it('with path, with GeoJSON', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.nearSphere('numbers', { center: { type: 'Point', coordinates: [40, -72 ]}});
-      assert.deepEqual(query._conditions, {numbers: {$nearSphere: { $geometry: { type: 'Point', coordinates: [40, -72] }}}});
-      assert.doesNotThrow(function() {
+      query.nearSphere('numbers', {center: {type: 'Point', coordinates: [40, -72]}});
+      assert.deepEqual(query._conditions, {numbers: {$nearSphere: {$geometry: {type: 'Point', coordinates: [40, -72]}}}});
+      assert.doesNotThrow(function () {
         query.cast(p1.constructor);
       });
       done();
     });
   });
 
-  describe('maxDistance', function() {
-    it('via where', function(done) {
+  describe('maxDistance', function () {
+    it('via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').near([40, -72]).maxDistance(1);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72], $maxDistance: 1}});
@@ -418,68 +417,68 @@ describe('Query', function() {
     });
   });
 
-  describe('within', function() {
-    describe('box', function() {
-      it('via where', function(done) {
+  describe('within', function () {
+    describe('box', function () {
+      it('via where', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('gps').within().box({ll: [5, 25], ur: [10, 30]});
         var match = {gps: {$within: {$box: [[5, 25], [10, 30]]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps["$within"];
+          delete match.gps['$within'];
         }
         assert.deepEqual(query._conditions, match);
         done();
       });
-      it('via where, no object', function(done) {
+      it('via where, no object', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('gps').within().box([5, 25], [10, 30]);
         var match = {gps: {$within: {$box: [[5, 25], [10, 30]]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps["$within"];
+          delete match.gps['$within'];
         }
         assert.deepEqual(query._conditions, match);
         done();
       });
     });
 
-    describe('center', function() {
-      it('via where', function(done) {
+    describe('center', function () {
+      it('via where', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('gps').within().center({center: [5, 25], radius: 5});
         var match = {gps: {$within: {$center: [[5, 25], 5]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps["$within"];
+          delete match.gps['$within'];
         }
         assert.deepEqual(query._conditions, match);
         done();
       });
     });
 
-    describe('centerSphere', function() {
-      it('via where', function(done) {
+    describe('centerSphere', function () {
+      it('via where', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('gps').within().centerSphere({center: [5, 25], radius: 5});
         var match = {gps: {$within: {$centerSphere: [[5, 25], 5]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps["$within"];
+          delete match.gps['$within'];
         }
         assert.deepEqual(query._conditions, match);
         done();
       });
     });
 
-    describe('polygon', function() {
-      it('via where', function(done) {
+    describe('polygon', function () {
+      it('via where', function (done) {
         var query = new Query({}, {}, null, p1.collection);
-        query.where('gps').within().polygon({ a: { x: 10, y: 20 }, b: { x: 15, y: 25 }, c: { x: 20, y: 20 }});
-        var match = {gps: {$within: {$polygon: [{ a: { x: 10, y: 20 }, b: { x: 15, y: 25 }, c: { x: 20, y: 20 }}] }}};
+        query.where('gps').within().polygon({a: {x: 10, y: 20}, b: {x: 15, y: 25}, c: {x: 20, y: 20}});
+        var match = {gps: {$within: {$polygon: [{a: {x: 10, y: 20}, b: {x: 15, y: 25}, c: {x: 20, y: 20}}]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps["$within"];
+          delete match.gps['$within'];
         }
         assert.deepEqual(query._conditions, match);
         done();
@@ -487,42 +486,42 @@ describe('Query', function() {
     });
   });
 
-  describe('exists', function() {
-    it('0 args via where', function(done) {
+  describe('exists', function () {
+    it('0 args via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("username").exists();
+      query.where('username').exists();
       assert.deepEqual(query._conditions, {username: {$exists: true}});
       done();
     });
-    it('1 arg via where', function(done) {
+    it('1 arg via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.where("username").exists(false);
+      query.where('username').exists(false);
       assert.deepEqual(query._conditions, {username: {$exists: false}});
       done();
     });
-    it('where 1 argument not via where', function(done) {
+    it('where 1 argument not via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.exists('username');
       assert.deepEqual(query._conditions, {username: {$exists: true}});
       done();
     });
 
-    it('where 2 args not via where', function(done) {
+    it('where 2 args not via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.exists("username", false);
+      query.exists('username', false);
       assert.deepEqual(query._conditions, {username: {$exists: false}});
       done();
     });
   });
 
-  describe('all', function() {
-    it('via where', function(done) {
+  describe('all', function () {
+    it('via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('pets').all(['dog', 'cat', 'ferret']);
       assert.deepEqual(query._conditions, {pets: {$all: ['dog', 'cat', 'ferret']}});
       done();
     });
-    it('not via where', function(done) {
+    it('not via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.all('pets', ['dog', 'cat', 'ferret']);
       assert.deepEqual(query._conditions, {pets: {$all: ['dog', 'cat', 'ferret']}});
@@ -530,14 +529,14 @@ describe('Query', function() {
     });
   });
 
-  describe('find', function() {
-    it('strict array equivalence condition v', function(done) {
+  describe('find', function () {
+    it('strict array equivalence condition v', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.find({'pets': ['dog', 'cat', 'ferret']});
       assert.deepEqual(query._conditions, {pets: ['dog', 'cat', 'ferret']});
       done();
     });
-    it('with no args', function(done) {
+    it('with no args', function (done) {
       var threw = false;
       var q = new Query({}, {}, null, p1.collection);
 
@@ -550,25 +549,25 @@ describe('Query', function() {
       assert.ok(!threw);
       done();
     });
-    it('works with overwriting previous object args (1176)', function(done) {
+    it('works with overwriting previous object args (1176)', function (done) {
       var q = new Query({}, {}, null, p1.collection);
-      assert.doesNotThrow(function() {
-        q.find({ age: { $lt: 30 }});
-        q.find({ age: 20 }); // overwrite
+      assert.doesNotThrow(function () {
+        q.find({age: {$lt: 30}});
+        q.find({age: 20}); // overwrite
       });
-      assert.deepEqual({ age: 20 }, q._conditions);
+      assert.deepEqual({age: 20}, q._conditions);
       done();
     });
   });
 
-  describe('size', function() {
-    it('via where', function(done) {
+  describe('size', function () {
+    it('via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').size(5);
       assert.deepEqual(query._conditions, {collection: {$size: 5}});
       done();
     });
-    it('not via where', function(done) {
+    it('not via where', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.size('collection', 5);
       assert.deepEqual(query._conditions, {collection: {$size: 5}});
@@ -576,74 +575,74 @@ describe('Query', function() {
     });
   });
 
-  describe('slice', function() {
-    it('where and positive limit param', function(done) {
+  describe('slice', function () {
+    it('where and positive limit param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(5);
       assert.deepEqual(query._fields, {collection: {$slice: 5}});
       done();
     });
-    it('where just negative limit param', function(done) {
+    it('where just negative limit param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(-5);
       assert.deepEqual(query._fields, {collection: {$slice: -5}});
       done();
     });
-    it('where [skip, limit] param', function(done) {
+    it('where [skip, limit] param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice([14, 10]); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('where skip and limit params', function(done) {
+    it('where skip and limit params', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(14, 10); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('where just positive limit param', function(done) {
+    it('where just positive limit param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(5);
       assert.deepEqual(query._fields, {collection: {$slice: 5}});
       done();
     });
-    it('where just negative limit param', function(done) {
+    it('where just negative limit param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(-5);
       assert.deepEqual(query._fields, {collection: {$slice: -5}});
       done();
     });
-    it('where the [skip, limit] param', function(done) {
+    it('where the [skip, limit] param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice([14, 10]); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('where the skip and limit params', function(done) {
+    it('where the skip and limit params', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(14, 10); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('not via where, with just positive limit param', function(done) {
+    it('not via where, with just positive limit param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.slice('collection', 5);
       assert.deepEqual(query._fields, {collection: {$slice: 5}});
       done();
     });
-    it('not via where, where just negative limit param', function(done) {
+    it('not via where, where just negative limit param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.slice('collection', -5);
       assert.deepEqual(query._fields, {collection: {$slice: -5}});
       done();
     });
-    it('not via where, where [skip, limit] param', function(done) {
+    it('not via where, where [skip, limit] param', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.slice('collection', [14, 10]); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('not via where, where skip and limit params', function(done) {
+    it('not via where, where skip and limit params', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.slice('collection', 14, 10); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
@@ -651,17 +650,17 @@ describe('Query', function() {
     });
   });
 
-  describe('elemMatch', function() {
-    describe('not via where', function() {
-      it('works', function(done) {
+  describe('elemMatch', function () {
+    describe('not via where', function () {
+      it('works', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.elemMatch('comments', {author: 'bnoguchi', votes: {$gte: 5}});
         assert.deepEqual(query._conditions, {comments: {$elemMatch: {author: 'bnoguchi', votes: {$gte: 5}}}});
         done();
       });
-      it('where block notation', function(done) {
+      it('where block notation', function (done) {
         var query = new Query({}, {}, null, p1.collection);
-        query.elemMatch('comments', function(elem) {
+        query.elemMatch('comments', function (elem) {
           elem.where('author', 'bnoguchi');
           elem.where('votes').gte(5);
         });
@@ -669,16 +668,16 @@ describe('Query', function() {
         done();
       });
     });
-    describe('via where', function() {
-      it('works', function(done) {
+    describe('via where', function () {
+      it('works', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('comments').elemMatch({author: 'bnoguchi', votes: {$gte: 5}});
         assert.deepEqual(query._conditions, {comments: {$elemMatch: {author: 'bnoguchi', votes: {$gte: 5}}}});
         done();
       });
-      it('where block notation', function(done) {
+      it('where block notation', function (done) {
         var query = new Query({}, {}, null, p1.collection);
-        query.where('comments').elemMatch(function(elem) {
+        query.where('comments').elemMatch(function (elem) {
           elem.where('author', 'bnoguchi');
           elem.where('votes').gte(5);
         });
@@ -688,17 +687,19 @@ describe('Query', function() {
     });
   });
 
-  describe('$where', function() {
-    it('function arg', function(done) {
+  describe('$where', function () {
+    it('function arg', function (done) {
       var query = new Query({}, {}, null, p1.collection);
+
       function filter() {
         return this.lastName === this.firstName;
       }
+
       query.$where(filter);
       assert.deepEqual(query._conditions, {$where: filter});
       done();
     });
-    it('string arg', function(done) {
+    it('string arg', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.$where('this.lastName === this.firstName');
       assert.deepEqual(query._conditions, {$where: 'this.lastName === this.firstName'});
@@ -706,29 +707,29 @@ describe('Query', function() {
     });
   });
 
-  describe('limit', function() {
-    it('works', function(done) {
+  describe('limit', function () {
+    it('works', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.limit(5);
-      assert.equal(query.options.limit,5);
+      assert.equal(query.options.limit, 5);
       done();
     });
   });
 
-  describe('skip', function() {
-    it('works', function(done) {
+  describe('skip', function () {
+    it('works', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.skip(9);
-      assert.equal(query.options.skip,9);
+      assert.equal(query.options.skip, 9);
       done();
     });
   });
 
-  describe('sort', function() {
-    it('works', function(done) {
+  describe('sort', function () {
+    it('works', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.sort('a -c b');
-      assert.deepEqual(query.options.sort, {'a': 1, 'c': -1,'b': 1});
+      assert.deepEqual(query.options.sort, {'a': 1, 'c': -1, 'b': 1});
       query = new Query({}, {}, null, p1.collection);
       query.sort({'a': 1, 'c': -1, 'b': 'asc', e: 'descending', f: 'ascending'});
       assert.deepEqual(query.options.sort, {'a': 1, 'c': -1, 'b': 1, 'e': -1, 'f': 1});
@@ -736,7 +737,7 @@ describe('Query', function() {
       var e;
 
       try {
-        query.sort(['a',1]);
+        query.sort(['a', 1]);
       } catch (err) {
         e = err;
       }
@@ -756,47 +757,47 @@ describe('Query', function() {
     });
   });
 
-  describe('or', function() {
-    it('works', function(done) {
+  describe('or', function () {
+    it('works', function (done) {
       var query = new Query;
-      query.find({ $or: [{x:1},{x:2}] });
+      query.find({$or: [{x: 1}, {x: 2}]});
       assert.equal(query._conditions.$or.length, 2);
-      query.or([{y:"We're under attack"}, {z:47}]);
+      query.or([{y: "We're under attack"}, {z: 47}]);
       assert.equal(query._conditions.$or.length, 4);
       assert.equal(query._conditions.$or[3].z, 47);
-      query.or({z:"phew"});
+      query.or({z: 'phew'});
       assert.equal(query._conditions.$or.length, 5);
       assert.equal(query._conditions.$or[3].z, 47);
-      assert.equal(query._conditions.$or[4].z, "phew");
+      assert.equal(query._conditions.$or[4].z, 'phew');
       done();
     });
   });
 
-  describe('and', function() {
-    it('works', function(done) {
+  describe('and', function () {
+    it('works', function (done) {
       var query = new Query;
-      query.find({ $and: [{x:1},{y:2}] });
+      query.find({$and: [{x: 1}, {y: 2}]});
       assert.equal(query._conditions.$and.length, 2);
-      query.and([{z:"We're under attack"}, {w:47}]);
+      query.and([{z: "We're under attack"}, {w: 47}]);
       assert.equal(query._conditions.$and.length, 4);
       assert.equal(query._conditions.$and[3].w, 47);
-      query.and({a:"phew"});
+      query.and({a: 'phew'});
       assert.equal(query._conditions.$and.length, 5);
       assert.equal(query._conditions.$and[0].x, 1);
       assert.equal(query._conditions.$and[1].y, 2);
       assert.equal(query._conditions.$and[2].z, "We're under attack");
       assert.equal(query._conditions.$and[3].w, 47);
-      assert.equal(query._conditions.$and[4].a, "phew");
+      assert.equal(query._conditions.$and[4].a, 'phew');
       done();
     });
   });
 
-  describe('populate', function() {
-    it('converts to PopulateOptions objects', function(done) {
+  describe('populate', function () {
+    it('converts to PopulateOptions objects', function (done) {
       var q = new Query({}, {}, null, p1.collection);
       var o = {
         path: 'yellow.brick',
-        match: { bricks: { $lt: 1000 }},
+        match: {bricks: {$lt: 1000}},
         select: undefined,
         model: undefined,
         options: undefined,
@@ -807,11 +808,11 @@ describe('Query', function() {
       done();
     });
 
-    it('overwrites duplicate paths', function(done) {
+    it('overwrites duplicate paths', function (done) {
       var q = new Query({}, {}, null, p1.collection);
       var o = {
         path: 'yellow.brick',
-        match: { bricks: { $lt: 1000 }},
+        match: {bricks: {$lt: 1000}},
         select: undefined,
         model: undefined,
         options: undefined,
@@ -827,7 +828,7 @@ describe('Query', function() {
       done();
     });
 
-    it('accepts space delimited strings', function(done) {
+    it('accepts space delimited strings', function (done) {
       var q = new Query({}, {}, null, p1.collection);
       q.populate('yellow.brick dirt');
       var o = {
@@ -846,45 +847,45 @@ describe('Query', function() {
     });
   });
 
-  describe('casting', function() {
+  describe('casting', function () {
     var db;
 
-    before(function() {
+    before(function () {
       db = start();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('to an array of mixed', function(done) {
+    it('to an array of mixed', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
-      var params = { _id: new DocumentObjectId, tags: { $in: [ 4, 8, 15, 16 ] }};
+      var params = {_id: new DocumentObjectId, tags: {$in: [4, 8, 15, 16]}};
       query.cast(Product, params);
-      assert.deepEqual(params.tags.$in, [4,8,15,16]);
+      assert.deepEqual(params.tags.$in, [4, 8, 15, 16]);
       done();
     });
 
-    it('find $ne should not cast single value to array for schematype of Array', function(done) {
+    it('find $ne should not cast single value to array for schematype of Array', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
       var Comment = db.model('Comment');
 
       var id = new DocumentObjectId;
-      var castedComment = { _id: id, text: 'hello there' };
+      var castedComment = {_id: id, text: 'hello there'};
       var comment = new Comment(castedComment);
 
       var params = {
-        array: { $ne: 5 },
-        ids: { $ne: id },
-        comments: { $ne: comment },
-        strings: { $ne: 'Hi there' },
-        numbers: { $ne: 10000 }
+        array: {$ne: 5},
+        ids: {$ne: id},
+        comments: {$ne: comment},
+        strings: {$ne: 'Hi there'},
+        numbers: {$ne: 10000}
       };
 
       query.cast(Product, params);
-      assert.equal(params.array.$ne,5);
+      assert.equal(params.array.$ne, 5);
       assert.equal(params.ids.$ne, id);
       params.comments.$ne._id.toHexString();
       assert.deepEqual(params.comments.$ne, castedComment);
@@ -910,12 +911,12 @@ describe('Query', function() {
       done();
     });
 
-    it('subdocument array with $ne: null should not throw', function(done) {
+    it('subdocument array with $ne: null should not throw', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
 
       var params = {
-        comments: { $ne: null }
+        comments: {$ne: null}
       };
 
       query.cast(Product, params);
@@ -923,13 +924,13 @@ describe('Query', function() {
       done();
     });
 
-    it('find should not cast single value to array for schematype of Array', function(done) {
+    it('find should not cast single value to array for schematype of Array', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
       var Comment = db.model('Comment');
 
       var id = new DocumentObjectId;
-      var castedComment = { _id: id, text: 'hello there' };
+      var castedComment = {_id: id, text: 'hello there'};
       var comment = new Comment(castedComment);
 
       var params = {
@@ -941,7 +942,7 @@ describe('Query', function() {
       };
 
       query.cast(Product, params);
-      assert.equal(params.array,5);
+      assert.equal(params.array, 5);
       assert.equal(params.ids, id);
       params.comments._id.toHexString();
       assert.deepEqual(params.comments, castedComment);
@@ -967,11 +968,11 @@ describe('Query', function() {
       done();
     });
 
-    it('an $elemMatch with $in works (gh-1100)', function(done) {
+    it('an $elemMatch with $in works (gh-1100)', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
       var ids = [String(new DocumentObjectId), String(new DocumentObjectId)];
-      var params = { ids: { $elemMatch: { $in: ids }}};
+      var params = {ids: {$elemMatch: {$in: ids}}};
       query.cast(Product, params);
       assert.ok(params.ids.$elemMatch.$in[0] instanceof DocumentObjectId);
       assert.ok(params.ids.$elemMatch.$in[1] instanceof DocumentObjectId);
@@ -980,20 +981,20 @@ describe('Query', function() {
       done();
     });
 
-    it('inequality operators for an array', function(done) {
+    it('inequality operators for an array', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
       var Comment = db.model('Comment');
 
       var id = new DocumentObjectId;
-      var castedComment = { _id: id, text: 'hello there' };
+      var castedComment = {_id: id, text: 'hello there'};
       var comment = new Comment(castedComment);
 
       var params = {
-        ids: { $gt: id },
-        comments: { $gt: comment },
-        strings: { $gt: 'Hi there' },
-        numbers: { $gt: 10000 }
+        ids: {$gt: id},
+        comments: {$gt: comment},
+        strings: {$gt: 'Hi there'},
+        numbers: {$gt: 10000}
       };
 
       query.cast(Product, params);
@@ -1005,36 +1006,36 @@ describe('Query', function() {
     });
   });
 
-  describe('distinct', function() {
-    it('op', function(done) {
+  describe('distinct', function () {
+    it('op', function (done) {
       var db = start();
       var Product = db.model('Product');
       var prod = new Product({});
-      var q = new Query({}, {}, Product, prod.collection).distinct('blah', function() {
-        assert.equal(q.op,'distinct');
+      var q = new Query({}, {}, Product, prod.collection).distinct('blah', function () {
+        assert.equal(q.op, 'distinct');
         db.close(done);
       });
     });
   });
 
-  describe('without a callback', function() {
-    it('count, update, remove works', function(done) {
+  describe('without a callback', function () {
+    it('count, update, remove works', function (done) {
       var db = start();
       var Product = db.model('Product', 'update_products_' + random());
       new Query(p1.collection, {}, Product).count();
-      Product.create({ tags: 12345 }, function(err) {
+      Product.create({tags: 12345}, function (err) {
         assert.ifError(err);
         var time = 20;
-        Product.find({ tags: 12345 }).update({ $set: { tags: 123456 }});
+        Product.find({tags: 12345}).update({$set: {tags: 123456}});
 
-        setTimeout(function() {
-          Product.find({ tags: 12345 }, function(err, p) {
+        setTimeout(function () {
+          Product.find({tags: 12345}, function (err, p) {
             assert.ifError(err);
             assert.equal(1, p.length);
 
-            Product.find({ tags: 123456 }).remove();
-            setTimeout(function() {
-              Product.find({ tags: 123456 }, function(err, p) {
+            Product.find({tags: 123456}).remove();
+            setTimeout(function () {
+              Product.find({tags: 123456}, function (err, p) {
                 assert.ifError(err);
                 assert.equal(0, p.length);
                 db.close();
@@ -1047,43 +1048,43 @@ describe('Query', function() {
     });
   });
 
-  describe('findOne', function() {
-    it('sets the op', function(done) {
+  describe('findOne', function () {
+    it('sets the op', function (done) {
       var db = start();
       var Product = db.model('Product');
       var prod = new Product({});
       var q = new Query(prod.collection, {}, Product).distinct();
       // use a timeout here because we have to wait for the connection to start
       // before any ops will get set
-      setTimeout(function() {
-        assert.equal(q.op,'distinct');
+      setTimeout(function () {
+        assert.equal(q.op, 'distinct');
         q.findOne();
-        assert.equal(q.op,'findOne');
+        assert.equal(q.op, 'findOne');
         db.close();
         done();
       }, 50);
     });
 
-    it('works as a promise', function(done) {
+    it('works as a promise', function (done) {
       var db = start();
       var Product = db.model('Product');
       var promise = Product.findOne();
 
-      promise.then(function() {
+      promise.then(function () {
         db.close(done);
-      }, function(err) {
+      }, function (err) {
         assert.ifError(err);
       });
     });
   });
 
-  describe('remove', function() {
-    it('handles cast errors async', function(done) {
+  describe('remove', function () {
+    it('handles cast errors async', function (done) {
       var db = start();
       var Product = db.model('Product');
 
-      assert.doesNotThrow(function() {
-        Product.where({ numbers: [[[]]] }).remove(function(err) {
+      assert.doesNotThrow(function () {
+        Product.where({numbers: [[[]]]}).remove(function (err) {
           db.close();
           assert.ok(err);
           done();
@@ -1091,27 +1092,27 @@ describe('Query', function() {
       });
     });
 
-    it('supports a single conditions arg', function(done) {
+    it('supports a single conditions arg', function (done) {
       var db = start();
       var Product = db.model('Product');
 
-      Product.create({ strings: ['remove-single-condition'] }).then(function() {
+      Product.create({strings: ['remove-single-condition']}).then(function () {
         db.close();
-        var q = Product.where().remove({ strings: 'remove-single-condition' });
+        var q = Product.where().remove({strings: 'remove-single-condition'});
         assert.ok(q instanceof mongoose.Query);
         done();
       }, done).end();
     });
 
-    it('supports a single callback arg', function(done) {
+    it('supports a single callback arg', function (done) {
       var db = start();
       var Product = db.model('Product');
       var val = 'remove-single-callback';
 
-      Product.create({ strings: [val] }).then(function() {
-        Product.where({ strings: val }).remove(function(err) {
+      Product.create({strings: [val]}).then(function () {
+        Product.where({strings: val}).remove(function (err) {
           assert.ifError(err);
-          Product.findOne({ strings: val }, function(err, doc) {
+          Product.findOne({strings: val}, function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.ok(!doc);
@@ -1121,15 +1122,15 @@ describe('Query', function() {
       }, done).end();
     });
 
-    it('supports conditions and callback args', function(done) {
+    it('supports conditions and callback args', function (done) {
       var db = start();
       var Product = db.model('Product');
       var val = 'remove-cond-and-callback';
 
-      Product.create({ strings: [val] }).then(function() {
-        Product.where().remove({ strings: val }, function(err) {
+      Product.create({strings: [val]}).then(function () {
+        Product.where().remove({strings: val}, function (err) {
           assert.ifError(err);
-          Product.findOne({ strings: val }, function(err, doc) {
+          Product.findOne({strings: val}, function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.ok(!doc);
@@ -1140,32 +1141,32 @@ describe('Query', function() {
     });
   });
 
-  describe('querying/updating with model instance containing embedded docs should work (#454)', function() {
-    it('works', function(done) {
+  describe('querying/updating with model instance containing embedded docs should work (#454)', function () {
+    it('works', function (done) {
       var db = start();
       var Product = db.model('Product');
 
-      var proddoc = { comments: [{ text: 'hello' }] };
-      var prod2doc = { comments: [{ text: 'goodbye' }] };
+      var proddoc = {comments: [{text: 'hello'}]};
+      var prod2doc = {comments: [{text: 'goodbye'}]};
 
       var prod = new Product(proddoc);
-      prod.save(function(err) {
+      prod.save(function (err) {
         assert.ifError(err);
 
-        Product.findOne(prod, function(err, product) {
+        Product.findOne(prod, function (err, product) {
           assert.ifError(err);
           assert.equal(product.comments.length, 1);
           assert.equal(product.comments[0].text, 'hello');
 
-          Product.update(product, prod2doc, function(err) {
+          Product.update(product, prod2doc, function (err) {
             assert.ifError(err);
 
-            Product.collection.findOne({ _id: product._id }, function(err, doc) {
+            Product.collection.findOne({_id: product._id}, function (err, doc) {
               assert.ifError(err);
               assert.equal(doc.comments.length, 1);
               // ensure hidden private props were not saved to db
-              assert.ok(!doc.comments[0].hasOwnProperty('parentArry') );
-              assert.equal(doc.comments[0].text,'goodbye');
+              assert.ok(!doc.comments[0].hasOwnProperty('parentArry'));
+              assert.equal(doc.comments[0].text, 'goodbye');
               db.close(done);
             });
           });
@@ -1174,35 +1175,35 @@ describe('Query', function() {
     });
   });
 
-  describe('optionsForExecute', function() {
-    it('should retain key order', function(done) {
+  describe('optionsForExecute', function () {
+    it('should retain key order', function (done) {
       // this is important for query hints
-      var hint = { x: 1, y: 1, z: 1 };
-      var a = JSON.stringify({ hint: hint, safe: true});
+      var hint = {x: 1, y: 1, z: 1};
+      var a = JSON.stringify({hint: hint, safe: true});
 
       var q = new Query;
       q.hint(hint);
 
-      var options = q._optionsForExec({ schema: { options: { safe: true } }});
-      assert.equal(a,JSON.stringify(options));
+      var options = q._optionsForExec({schema: {options: {safe: true}}});
+      assert.equal(a, JSON.stringify(options));
       done();
     });
   });
 
   // Advanced Query options
 
-  describe('options', function() {
-    describe('maxscan', function() {
-      it('works', function(done) {
+  describe('options', function () {
+    describe('maxscan', function () {
+      it('works', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.maxscan(100);
-        assert.equal(query.options.maxScan,100);
+        assert.equal(query.options.maxScan, 100);
         done();
       });
     });
 
-    describe('slaveOk', function() {
-      it('works', function(done) {
+    describe('slaveOk', function () {
+      it('works', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.slaveOk();
         assert.equal(true, query.options.slaveOk);
@@ -1218,8 +1219,8 @@ describe('Query', function() {
       });
     });
 
-    describe('tailable', function() {
-      it('works', function(done) {
+    describe('tailable', function () {
+      it('works', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.tailable();
         assert.equal(true, query.options.tailable);
@@ -1233,32 +1234,32 @@ describe('Query', function() {
         assert.equal(false, query.options.tailable);
         done();
       });
-      it('supports passing the `await` option', function(done) {
+      it('supports passing the `await` option', function (done) {
         var query = new Query({}, {}, null, p1.collection);
-        query.tailable({ awaitdata: true });
+        query.tailable({awaitdata: true});
         assert.equal(true, query.options.tailable);
         assert.equal(true, query.options.awaitdata);
         done();
       });
     });
 
-    describe('comment', function() {
-      it('works', function(done) {
+    describe('comment', function () {
+      it('works', function (done) {
         var query = new Query;
-        assert.equal('function',typeof query.comment);
-        assert.equal(query.comment('Lowpass is more fun'),query);
-        assert.equal(query.options.comment,'Lowpass is more fun');
+        assert.equal('function', typeof query.comment);
+        assert.equal(query.comment('Lowpass is more fun'), query);
+        assert.equal(query.options.comment, 'Lowpass is more fun');
         done();
       });
     });
 
-    describe('hint', function() {
-      it('works', function(done) {
+    describe('hint', function () {
+      it('works', function (done) {
         var query2 = new Query({}, {}, null, p1.collection);
         query2.hint({'indexAttributeA': 1, 'indexAttributeB': -1});
         assert.deepEqual(query2.options.hint, {'indexAttributeA': 1, 'indexAttributeB': -1});
 
-        assert.throws(function() {
+        assert.throws(function () {
           var query3 = new Query({}, {}, null, p1.collection);
           query3.hint('indexAttributeA');
         }, /Invalid hint./);
@@ -1267,8 +1268,8 @@ describe('Query', function() {
       });
     });
 
-    describe('snapshot', function() {
-      it('works', function(done) {
+    describe('snapshot', function () {
+      it('works', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.snapshot(true);
         assert.equal(true, query.options.snapshot);
@@ -1276,20 +1277,20 @@ describe('Query', function() {
       });
     });
 
-    describe('batchSize', function() {
-      it('works', function(done) {
+    describe('batchSize', function () {
+      it('works', function (done) {
         var query = new Query({}, {}, null, p1.collection);
         query.batchSize(10);
-        assert.equal(query.options.batchSize,10);
+        assert.equal(query.options.batchSize, 10);
         done();
       });
     });
 
-    describe('read', function() {
+    describe('read', function () {
       var P = mongoose.mongo.ReadPreference;
 
-      describe('without tags', function() {
-        it('works', function(done) {
+      describe('without tags', function () {
+        it('works', function (done) {
           var query = new Query({}, {}, null, p1.collection);
           query.read('primary');
           assert.ok(query.options.readPreference instanceof P);
@@ -1345,10 +1346,10 @@ describe('Query', function() {
         });
       });
 
-      describe('with tags', function() {
-        it('works', function(done) {
+      describe('with tags', function () {
+        it('works', function (done) {
           var query = new Query({}, {}, null, p1.collection);
-          var tags = [{ dc: 'sf', s: 1}, { dc: 'jp', s: 2 }];
+          var tags = [{dc: 'sf', s: 1}, {dc: 'jp', s: 2}];
 
           query.read('pp', tags);
           assert.ok(query.options.readPreference instanceof P);
@@ -1363,75 +1364,76 @@ describe('Query', function() {
         });
       });
 
-      describe('inherits its models schema read option', function() {
+      describe('inherits its models schema read option', function () {
         var schema, M, called;
-        before(function() {
-          schema = new Schema({}, { read: 'p' });
+        before(function () {
+          schema = new Schema({}, {read: 'p'});
           M = mongoose.model('schemaOptionReadPrefWithQuery', schema);
         });
 
-        it('if not set in query', function(done) {
+        it('if not set in query', function (done) {
           var options = M.where()._optionsForExec(M);
           assert.ok(options.readPreference instanceof P);
           assert.equal(options.readPreference.mode, 'primary');
           done();
         });
 
-        it('if set in query', function(done) {
+        it('if set in query', function (done) {
           var options = M.where().read('s')._optionsForExec(M);
           assert.ok(options.readPreference instanceof P);
           assert.equal(options.readPreference.mode, 'secondary');
           done();
         });
 
-        it('and sends it though the driver', function(done) {
+        it('and sends it though the driver', function (done) {
           var db = start();
-          var options = { read: 'secondary', safe: { w: 'majority' }};
-          var schema = Schema({ name: String }, options);
+          var options = {read: 'secondary', safe: {w: 'majority'}};
+          var schema = Schema({name: String}, options);
           var M = db.model(random(), schema);
           var q = M.find();
 
           // stub the internal query options call
           var getopts = q._optionsForExec;
-          q._optionsForExec = function(model) {
+          q._optionsForExec = function (model) {
             q._optionsForExec = getopts;
 
             var ret = getopts.call(this, model);
 
             assert.ok(ret.readPreference);
             assert.equal('secondary', ret.readPreference.mode);
-            assert.deepEqual({ w: 'majority' }, ret.safe);
+            assert.deepEqual({w: 'majority'}, ret.safe);
             called = true;
 
             return ret;
           };
 
-          q.exec(function(err) {
-            if (err) return done(err);
+          q.exec(function (err) {
+            if (err) {
+              return done(err);
+            }
             assert.ok(called);
             db.close(done);
           });
         });
-
       });
     });
   });
 
-  describe('setOptions', function() {
-    it('works', function(done) {
+  describe('setOptions', function () {
+    it('works', function (done) {
       var q = new Query;
-      q.setOptions({ thing: "cat" });
-      q.setOptions({ populate: ['fans'] });
-      q.setOptions({ batchSize: 10 });
-      q.setOptions({ limit: 4 });
-      q.setOptions({ skip: 3 });
-      q.setOptions({ sort: '-blah' });
-      q.setOptions({ sort: {'woot': -1} });
-      q.setOptions({ hint: { index1: 1, index2: -1 }});
-      q.setOptions({ read: ['s', [{dc:'eu'}]]});
+      q.setOptions({thing: 'cat'});
+      q.setOptions({populate: ['fans']});
+      q.setOptions({batchSize: 10});
+      q.setOptions({limit: 4});
+      q.setOptions({skip: 3});
+      q.setOptions({sort: '-blah'});
+      q.setOptions({sort: {'woot': -1}});
+      q.setOptions({hint: {index1: 1, index2: -1}});
+      q.setOptions({read: ['s', [{dc: 'eu'}]]});
 
       assert.equal(q.options.thing, 'cat');
-      assert.deepEqual(q._mongooseOptions.populate.fans, { path: 'fans', select: undefined, match: undefined, options: undefined, model: undefined, _docs: {} });
+      assert.deepEqual(q._mongooseOptions.populate.fans, {path: 'fans', select: undefined, match: undefined, options: undefined, model: undefined, _docs: {}});
       assert.equal(q.options.batchSize, 10);
       assert.equal(q.options.limit, 4);
       assert.equal(q.options.skip, 3);
@@ -1446,51 +1448,49 @@ describe('Query', function() {
       var db = start();
       var Product = db.model('Product', 'Product_setOptions_test');
       Product.create(
-        { numbers: [3,4,5] },
-        { strings: 'hi there'.split(' ') }, function(err, doc1, doc2) {
-
-          assert.ifError(err);
-
-          Product.find().setOptions({ limit: 1, sort: {_id: -1}, read: 'n' }).exec(function(err, docs) {
-            db.close();
+          {numbers: [3, 4, 5]},
+          {strings: 'hi there'.split(' ')}, function (err, doc1, doc2) {
             assert.ifError(err);
-            assert.equal(docs.length, 1);
-            assert.equal(docs[0].id, doc2.id);
-            done();
+            Product.find().setOptions({limit: 1, sort: {_id: -1}, read: 'n'}).exec(function (err, docs) {
+              db.close();
+              assert.ifError(err);
+              assert.equal(docs.length, 1);
+              assert.equal(docs[0].id, doc2.id);
+              done();
+            });
           });
-        });
     });
   });
 
-  describe('update', function() {
-    it('when empty, nothing is run', function(done) {
+  describe('update', function () {
+    it('when empty, nothing is run', function (done) {
       var q = new Query;
       assert.equal(false, !!q._castUpdate({}));
       done();
     });
   });
 
-  describe('gh-1950', function() {
-    it('ignores sort when passed to count', function(done) {
+  describe('gh-1950', function () {
+    it('ignores sort when passed to count', function (done) {
       var db = start();
       var Product = db.model('Product', 'Product_setOptions_test');
-      Product.find().sort({ _id: 1 }).count({}).exec(function(error) {
+      Product.find().sort({_id: 1}).count({}).exec(function (error) {
         assert.ifError(error);
         db.close(done);
       });
     });
 
-    it('ignores count when passed to sort', function(done) {
+    it('ignores count when passed to sort', function (done) {
       var db = start();
       var Product = db.model('Product', 'Product_setOptions_test');
-      Product.find().count({}).sort({ _id: 1 }).exec(function(error) {
+      Product.find().count({}).sort({_id: 1}).exec(function (error) {
         assert.ifError(error);
         db.close(done);
       });
     });
   });
 
-  it('excludes _id when select false and inclusive mode (gh-3010)', function(done) {
+  it('excludes _id when select false and inclusive mode (gh-3010)', function (done) {
     var db = start();
     var User = db.model('gh3010', {
       _id: {
@@ -1501,9 +1501,9 @@ describe('Query', function() {
       username: String
     });
 
-    User.create({ username: 'Val' }, function(error, user) {
+    User.create({username: 'Val'}, function (error, user) {
       assert.ifError(error);
-      User.find({ _id: user._id }).select('username').exec(function(error, users) {
+      User.find({_id: user._id}).select('username').exec(function (error, users) {
         assert.ifError(error);
         assert.equal(users.length, 1);
         assert.ok(!users[0]._id);
@@ -1513,27 +1513,27 @@ describe('Query', function() {
     });
   });
 
-  it('doesnt reverse key order for update docs (gh-3215)', function(done) {
+  it('doesnt reverse key order for update docs (gh-3215)', function (done) {
     var db = start();
     var Test = db.model('gh3215', {
-      arr: [{ date: Date, value: Number }]
+      arr: [{date: Date, value: Number}]
     });
 
     var q = Test.update({}, {
       $push: {
         arr: {
-          $each: [{ date: new Date(), value: 1 }],
-          $sort: { value: -1, date: -1 }
+          $each: [{date: new Date(), value: 1}],
+          $sort: {value: -1, date: -1}
         }
       }
     });
 
     assert.deepEqual(Object.keys(q.getUpdate().$push.arr.$sort),
-     ['value', 'date']);
+        ['value', 'date']);
     db.close(done);
   });
 
-  it('handles nested $ (gh-3265)', function(done) {
+  it('handles nested $ (gh-3265)', function (done) {
     var db = start();
     var Post = db.model('gh3265', {
       title: String,
@@ -1546,21 +1546,21 @@ describe('Query', function() {
       }]
     });
 
-    var answersUpdate = { details: 'blah', stats: { votes: 1, count: '3' } };
+    var answersUpdate = {details: 'blah', stats: {votes: 1, count: '3'}};
     var q = Post.update(
-      { 'answers._id': '507f1f77bcf86cd799439011' },
-      { $set: { 'answers.$': answersUpdate } });
+        {'answers._id': '507f1f77bcf86cd799439011'},
+        {$set: {'answers.$': answersUpdate}});
 
     assert.deepEqual(q.getUpdate().$set['answers.$'].stats,
-      { votes: 1, count: 3 });
+        {votes: 1, count: 3});
     db.close(done);
   });
 
-  describe('handles falsy and object projections with defaults (gh-3256)', function() {
+  describe('handles falsy and object projections with defaults (gh-3256)', function () {
     var db = start();
     var MyModel;
 
-    before(function(done) {
+    before(function (done) {
       db = start();
 
       var PersonSchema = new Schema({
@@ -1576,7 +1576,7 @@ describe('Query', function() {
         lastName: 'Doe',
         dependents: ['Jake', 'Jill', 'Jane']
       };
-      m.create(obj, function(error) {
+      m.create(obj, function (error) {
         assert.ifError(error);
 
         var PersonSchema = new Schema({
@@ -1592,35 +1592,35 @@ describe('Query', function() {
       });
     });
 
-    after(function() {
+    after(function () {
       db.close();
     });
 
-    it('falsy projection', function(done) {
-      MyModel.findOne({ name: 'John' }, { lastName: false }).
-        exec(function(error, person) {
-          assert.ifError(error);
-          assert.equal(person.salary, 25000);
-          done();
-        });
+    it('falsy projection', function (done) {
+      MyModel.findOne({name: 'John'}, {lastName: false}).
+      exec(function (error, person) {
+        assert.ifError(error);
+        assert.equal(person.salary, 25000);
+        done();
+      });
     });
 
-    it('slice projection', function(done) {
-      MyModel.findOne({ name: 'John' }, { dependents: { $slice: 1 } }).
-        exec(function(error, person) {
-          assert.ifError(error);
-          assert.equal(person.salary, 25000);
-          done();
-        });
+    it('slice projection', function (done) {
+      MyModel.findOne({name: 'John'}, {dependents: {$slice: 1}}).
+      exec(function (error, person) {
+        assert.ifError(error);
+        assert.equal(person.salary, 25000);
+        done();
+      });
     });
 
-    it('empty projection', function(done) {
-      MyModel.findOne({ name: 'John' }, {}).
-        exec(function(error, person) {
-          assert.ifError(error);
-          assert.equal(person.salary, 25000);
-          done();
-        });
+    it('empty projection', function (done) {
+      MyModel.findOne({name: 'John'}, {}).
+      exec(function (error, person) {
+        assert.ifError(error);
+        assert.equal(person.salary, 25000);
+        done();
+      });
     });
   });
 });
diff --git a/test/query.toconstructor.test.js b/test/query.toconstructor.test.js
index 226ab08ca53..89e725ebc01 100644
--- a/test/query.toconstructor.test.js
+++ b/test/query.toconstructor.test.js
@@ -1,4 +1,3 @@
-
 var start = require('./common'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema,
@@ -25,23 +24,23 @@ var cName = 'Comment' + random();
 mongoose.model(prodName, Product);
 mongoose.model(cName, Comment);
 
-describe('Query:', function() {
-  describe('toConstructor', function() {
-    it('creates a query', function(done) {
+describe('Query:', function () {
+  describe('toConstructor', function () {
+    it('creates a query', function (done) {
       var db = start();
       var Product = db.model(prodName);
-      var prodQ = Product.find({ title : /test/ }).toConstructor();
+      var prodQ = Product.find({title: /test/}).toConstructor();
 
       assert.ok(prodQ() instanceof Query);
 
       db.close(done);
     });
 
-    it('copies all the right values', function(done) {
+    it('copies all the right values', function (done) {
       var db = start();
       var Product = db.model(prodName);
 
-      var prodQ = Product.update({ title: /test/ }, { title: 'blah' });
+      var prodQ = Product.update({title: /test/}, {title: 'blah'});
 
       var prodC = prodQ.toConstructor();
 
@@ -58,14 +57,14 @@ describe('Query:', function() {
       db.close(done);
     });
 
-    it('gets expected results', function(done) {
+    it('gets expected results', function (done) {
       var db = start();
       var Product = db.model(prodName);
-      Product.create({ title : 'this is a test' }, function(err, p) {
+      Product.create({title: 'this is a test'}, function (err, p) {
         assert.ifError(err);
-        var prodC = Product.find({ title : /test/ }).toConstructor();
+        var prodC = Product.find({title: /test/}).toConstructor();
 
-        prodC().exec(function(err, results) {
+        prodC().exec(function (err, results) {
           db.close();
           assert.ifError(err);
           assert.equal(results.length, 1);
@@ -75,25 +74,25 @@ describe('Query:', function() {
       });
     });
 
-    it('can be re-used multiple times', function(done) {
+    it('can be re-used multiple times', function (done) {
       var db = start();
       var Product = db.model(prodName);
 
-      Product.create([{ title : 'moar thing' }, {title : 'second thing' }], function(err, prods) {
+      Product.create([{title: 'moar thing'}, {title: 'second thing'}], function (err, prods) {
         assert.ifError(err);
         assert.equal(prods.length, 2);
         var prod = prods[0];
-        var prodC = Product.find({ title : /thing/ }).toConstructor();
+        var prodC = Product.find({title: /thing/}).toConstructor();
 
-        prodC().exec(function(err, results) {
+        prodC().exec(function (err, results) {
           assert.ifError(err);
 
           assert.equal(results.length, 2);
-          prodC().find({ _id: prod.id }).exec(function(err, res) {
+          prodC().find({_id: prod.id}).exec(function (err, res) {
             assert.ifError(err);
             assert.equal(res.length, 1);
 
-            prodC().exec(function(err, res) {
+            prodC().exec(function (err, res) {
               db.close();
               assert.ifError(err);
               assert.equal(res.length, 2);
@@ -104,46 +103,46 @@ describe('Query:', function() {
       });
     });
 
-    it('options get merged properly', function(done) {
+    it('options get merged properly', function (done) {
       var db = start();
       var Product = db.model(prodName);
       db.close();
 
-      var prodC = Product.find({ title : /blah/ }).setOptions({ sort: 'title', lean: true });
+      var prodC = Product.find({title: /blah/}).setOptions({sort: 'title', lean: true});
       prodC = prodC.toConstructor();
 
-      var nq = prodC(null, { limit: 3 });
-      assert.deepEqual(nq._mongooseOptions, { lean: true, limit: 3 });
-      assert.deepEqual(nq.options, { sort: { 'title': 1 }, limit: 3 });
+      var nq = prodC(null, {limit: 3});
+      assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3});
+      assert.deepEqual(nq.options, {sort: {'title': 1}, limit: 3});
       done();
     });
 
-    it('options get cloned (gh-3176)', function(done) {
+    it('options get cloned (gh-3176)', function (done) {
       var db = start();
       var Product = db.model(prodName);
       db.close();
 
-      var prodC = Product.find({ title : /blah/ }).setOptions({ sort: 'title', lean: true });
+      var prodC = Product.find({title: /blah/}).setOptions({sort: 'title', lean: true});
       prodC = prodC.toConstructor();
 
-      var nq = prodC(null, { limit: 3 });
-      assert.deepEqual(nq._mongooseOptions, { lean: true, limit: 3 });
-      assert.deepEqual(nq.options, { sort: { 'title': 1 }, limit: 3 });
-      var nq2 = prodC(null, { limit: 5 });
-      assert.deepEqual(nq._mongooseOptions, { lean: true, limit: 3 });
-      assert.deepEqual(nq2._mongooseOptions, { lean: true, limit: 5 });
+      var nq = prodC(null, {limit: 3});
+      assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3});
+      assert.deepEqual(nq.options, {sort: {'title': 1}, limit: 3});
+      var nq2 = prodC(null, {limit: 5});
+      assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3});
+      assert.deepEqual(nq2._mongooseOptions, {lean: true, limit: 5});
       done();
     });
 
-    it('creates subclasses of mquery', function(done) {
+    it('creates subclasses of mquery', function (done) {
       var db = start();
       var Product = db.model(prodName);
       db.close();
 
-      var opts = { safe: { w: 'majority' }, readPreference: 'p' };
-      var match = { title: 'test', count: { $gt: 101 }};
-      var select = { name: 1, count: 0 };
-      var update = { $set: { title: 'thing' }};
+      var opts = {safe: {w: 'majority'}, readPreference: 'p'};
+      var match = {title: 'test', count: {$gt: 101}};
+      var select = {name: 1, count: 0};
+      var update = {$set: {title: 'thing'}};
       var path = 'title';
 
       var q = Product.update(match, update);
diff --git a/test/schema.boolean.test.js b/test/schema.boolean.test.js
index 0ef2ce88ae5..d60e2f6507e 100644
--- a/test/schema.boolean.test.js
+++ b/test/schema.boolean.test.js
@@ -8,15 +8,15 @@ var start = require('./common'),
     assert = require('assert'),
     Schema = mongoose.Schema;
 
-describe('schematype', function() {
-  describe('boolean', function() {
-    it('null default is permitted (gh-523)', function(done) {
+describe('schematype', function () {
+  describe('boolean', function () {
+    it('null default is permitted (gh-523)', function (done) {
       var db = start(),
-          s1 = new Schema({ b: { type: Boolean, default: null }}),
+          s1 = new Schema({b: {type: Boolean, default: null}}),
           M1 = db.model('NullDateDefaultIsAllowed1', s1),
-          s2 = new Schema({ b: { type: Boolean, default: false }}),
+          s2 = new Schema({b: {type: Boolean, default: false}}),
           M2 = db.model('NullDateDefaultIsAllowed2', s2),
-          s3 = new Schema({ b: { type: Boolean, default: true }}),
+          s3 = new Schema({b: {type: Boolean, default: true}}),
           M3 = db.model('NullDateDefaultIsAllowed3', s3);
 
       db.close();
diff --git a/test/schema.documentarray.test.js b/test/schema.documentarray.test.js
index 1df91b7ae60..f332a2e9d14 100644
--- a/test/schema.documentarray.test.js
+++ b/test/schema.documentarray.test.js
@@ -12,19 +12,19 @@ var start = require('./common'),
  * Test.
  */
 
-describe('schema.documentarray', function() {
-  it('defaults should be preserved', function(done) {
-    var child = new Schema({ title: String });
+describe('schema.documentarray', function () {
+  it('defaults should be preserved', function (done) {
+    var child = new Schema({title: String});
 
-    var schema1 = new Schema({ x: { type: [child], default: [{ title: 'Prometheus'}] }});
-    var schema2 = new Schema({ x: { type: [child], default: { title: 'Prometheus'} }});
-    var schema3 = new Schema({ x: { type: [child], default: function() { return [{ title: 'Prometheus'}];} }});
+    var schema1 = new Schema({x: {type: [child], default: [{title: 'Prometheus'}]}});
+    var schema2 = new Schema({x: {type: [child], default: {title: 'Prometheus'}}});
+    var schema3 = new Schema({x: {type: [child], default: function () { return [{title: 'Prometheus'}];}}});
 
     var M = mongoose.model('DefaultDocArrays1', schema1);
     var N = mongoose.model('DefaultDocArrays2', schema2);
     var O = mongoose.model('DefaultDocArrays3', schema3);
 
-    [M,N,O].forEach(function(M) {
+    [M, N, O].forEach(function (M) {
       var m = new M;
       assert.ok(Array.isArray(m.x));
       assert.equal(1, m.x.length);
@@ -33,21 +33,21 @@ describe('schema.documentarray', function() {
     done();
   });
 
-  it('only sets if document has same schema (gh-3701)', function(done) {
+  it('only sets if document has same schema (gh-3701)', function (done) {
     var schema1 = new Schema({
-      arr: [new Schema({ a: Number, b: Number }, { _id: false })]
+      arr: [new Schema({a: Number, b: Number}, {_id: false})]
     });
     var schema2 = new Schema({
-      arr: [new Schema({ a: Number }, { _id: false })]
+      arr: [new Schema({a: Number}, {_id: false})]
     });
 
     var Model1 = mongoose.model('gh3701_0', schema1);
     var Model2 = mongoose.model('gh3701_1', schema2);
 
-    var source = new Model1({ arr: [{ a: 1, b: 1 }, { a: 2, b: 2 }] });
-    var dest = new Model2({ arr: source.arr });
+    var source = new Model1({arr: [{a: 1, b: 1}, {a: 2, b: 2}]});
+    var dest = new Model2({arr: source.arr});
 
-    assert.deepEqual(dest.toObject().arr, [{ a: 1 }, { a: 2 }]);
+    assert.deepEqual(dest.toObject().arr, [{a: 1}, {a: 2}]);
     done();
   });
 });
diff --git a/test/schema.mixed.test.js b/test/schema.mixed.test.js
index 79bc52b2bfa..44764a8b470 100644
--- a/test/schema.mixed.test.js
+++ b/test/schema.mixed.test.js
@@ -8,10 +8,10 @@ var start = require('./common'),
     assert = require('assert'),
     Schema = mongoose.Schema;
 
-describe('schematype mixed', function() {
-  describe('empty object defaults (gh-1380)', function() {
-    it('are interpreted as fns that return new empty objects', function(done) {
-      var s = Schema({ mix: { type: Schema.Types.Mixed, default: {} }});
+describe('schematype mixed', function () {
+  describe('empty object defaults (gh-1380)', function () {
+    it('are interpreted as fns that return new empty objects', function (done) {
+      var s = Schema({mix: {type: Schema.Types.Mixed, default: {}}});
       var M = mongoose.model('M1', s);
       var m1 = new M;
       var m2 = new M;
@@ -20,9 +20,9 @@ describe('schematype mixed', function() {
       assert.equal(undefined, m2.mix.val);
       done();
     });
-    it('can be forced to share the object between documents', function(done) {
+    it('can be forced to share the object between documents', function (done) {
       // silly but necessary for backwards compatibility
-      var s = Schema({ mix: { type: Schema.Types.Mixed, default: {}, shared: true }});
+      var s = Schema({mix: {type: Schema.Types.Mixed, default: {}, shared: true}});
       var M = mongoose.model('M2', s);
       var m1 = new M;
       var m2 = new M;
diff --git a/test/schema.onthefly.test.js b/test/schema.onthefly.test.js
index 94ff318ab6b..c59a08b41f9 100644
--- a/test/schema.onthefly.test.js
+++ b/test/schema.onthefly.test.js
@@ -11,14 +11,14 @@ var start = require('./common'),
 
 var DecoratedSchema = new Schema({
   title: String
-}, { strict: false });
+}, {strict: false});
 
 mongoose.model('Decorated', DecoratedSchema);
 
 var collection = 'decorated_' + random();
 
-describe('schema.onthefly', function() {
-  it('setting should cache the schema type and cast values appropriately', function(done) {
+describe('schema.onthefly', function () {
+  it('setting should cache the schema type and cast values appropriately', function (done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
@@ -29,22 +29,22 @@ describe('schema.onthefly', function() {
     done();
   });
 
-  it('should be local to the particular document', function(done) {
+  it('should be local to the particular document', function (done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
     db.close();
     var postOne = new Decorated();
     postOne.set('adhoc', '9', Number);
-    assert.notStrictEqual(postOne.$__path('adhoc'),undefined);
+    assert.notStrictEqual(postOne.$__path('adhoc'), undefined);
 
     var postTwo = new Decorated();
-    assert.notStrictEqual(postTwo.$__path('title'),undefined);
+    assert.notStrictEqual(postTwo.$__path('title'), undefined);
     assert.strictEqual(undefined, postTwo.$__path('adhoc'));
     done();
   });
 
-  it('querying a document that had an on the fly schema should work', function(done) {
+  it('querying a document that had an on the fly schema should work', function (done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
@@ -52,10 +52,10 @@ describe('schema.onthefly', function() {
     // Interpret adhoc as a Number
     post.set('adhoc', '9', Number);
     assert.equal(9, post.get('adhoc').valueOf());
-    post.save(function(err) {
+    post.save(function (err) {
       assert.ifError(err);
       assert.strictEqual(null, err);
-      Decorated.findById(post.id, function(err, found) {
+      Decorated.findById(post.id, function (err, found) {
         db.close();
         assert.strictEqual(null, err);
         assert.equal(9, found.get('adhoc'));
@@ -83,28 +83,28 @@ describe('schema.onthefly', function() {
     });
   });
 
-  it('on the fly Embedded Array schemas should cast properly', function(done) {
+  it('on the fly Embedded Array schemas should cast properly', function (done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
     db.close();
     var post = new Decorated();
     post.set('moderators', [{name: 'alex trebek'}], [new Schema({name: String})]);
-    assert.equal(post.get('moderators')[0].name,'alex trebek');
+    assert.equal(post.get('moderators')[0].name, 'alex trebek');
     done();
   });
 
-  it('on the fly Embedded Array schemas should get from a fresh queried document properly', function(done) {
+  it('on the fly Embedded Array schemas should get from a fresh queried document properly', function (done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
     var post = new Decorated(),
         ModeratorSchema = new Schema({name: String, ranking: Number});
     post.set('moderators', [{name: 'alex trebek', ranking: '1'}], [ModeratorSchema]);
-    assert.equal(post.get('moderators')[0].name,'alex trebek');
-    post.save(function(err) {
+    assert.equal(post.get('moderators')[0].name, 'alex trebek');
+    post.save(function (err) {
       assert.ifError(err);
-      Decorated.findById(post.id, function(err, found) {
+      Decorated.findById(post.id, function (err, found) {
         db.close();
         assert.ifError(err);
         var rankingPreCast = found.get('moderators')[0].ranking;
@@ -113,7 +113,7 @@ describe('schema.onthefly', function() {
         var rankingPostCast = found.get('moderators', [ModeratorSchema])[0].ranking;
         assert.equal(1, rankingPostCast);
 
-        var NewModeratorSchema = new Schema({ name: String, ranking: String});
+        var NewModeratorSchema = new Schema({name: String, ranking: String});
         rankingPostCast = found.get('moderators', [NewModeratorSchema])[0].ranking;
         assert.equal(1, rankingPostCast);
         done();
@@ -121,11 +121,11 @@ describe('schema.onthefly', function() {
     });
   });
 
-  it('casts on get() (gh-2360)', function(done) {
+  it('casts on get() (gh-2360)', function (done) {
     var db = start();
     var Decorated = db.model('gh2360', DecoratedSchema, 'gh2360');
 
-    var d = new Decorated({ title: '1' });
+    var d = new Decorated({title: '1'});
     assert.equal('number', typeof d.get('title', 'Number'));
 
     d.title = '000000000000000000000001';
diff --git a/test/schema.select.test.js b/test/schema.select.test.js
index 944df7ca2e9..e2a532e0b03 100644
--- a/test/schema.select.test.js
+++ b/test/schema.select.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Test dependencies.
  */
@@ -9,38 +8,40 @@ var start = require('./common'),
     random = require('../lib/utils').random,
     Schema = mongoose.Schema;
 
-describe('schema select option', function() {
-
-  it('excluding paths through schematype', function(done) {
+describe('schema select option', function () {
+  it('excluding paths through schematype', function (done) {
     var db = start();
 
     var schema = new Schema({
       thin: Boolean,
-      name: { type: String, select: false},
-      docs: [new Schema({ bool: Boolean, name: { type: String, select: false }})]
+      name: {type: String, select: false},
+      docs: [new Schema({bool: Boolean, name: {type: String, select: false}})]
     });
 
     var S = db.model('ExcludingBySchemaType', schema);
-    S.create({ thin: true, name: 'the excluded', docs:[{bool:true, name: 'test'}] }, function(err, s) {
+    S.create({thin: true, name: 'the excluded', docs: [{bool: true, name: 'test'}]}, function (err, s) {
       assert.ifError(err);
       assert.equal(s.name, 'the excluded');
       assert.equal(s.docs[0].name, 'test');
 
       var pending = 5;
       var item = s;
+
       function cb(err, s) {
         if (!--pending) {
           db.close();
         }
 
-        if (Array.isArray(s)) s = s[0];
+        if (Array.isArray(s)) {
+          s = s[0];
+        }
         assert.strictEqual(null, err);
         assert.equal(false, s.isSelected('name'));
         assert.equal(false, s.isSelected('docs.name'));
         assert.strictEqual(undefined, s.name);
         // we need to make sure this executes absolutely last.
         if (pending === 1) {
-          S.findOneAndRemove({ _id: item._id }, cb);
+          S.findOneAndRemove({_id: item._id}, cb);
         }
         if (0 === pending) {
           done();
@@ -48,33 +49,36 @@ describe('schema select option', function() {
       }
 
       S.findById(s).select('-thin -docs.bool').exec(cb);
-      S.find({ _id: s._id }).select('thin docs.bool').exec(cb);
+      S.find({_id: s._id}).select('thin docs.bool').exec(cb);
       S.findById(s, cb);
-      S.findOneAndUpdate({ _id: s._id }, { name: 'changed' }, cb);
+      S.findOneAndUpdate({_id: s._id}, {name: 'changed'}, cb);
     });
   });
 
-  it('including paths through schematype', function(done) {
+  it('including paths through schematype', function (done) {
     var db = start();
 
     var schema = new Schema({
       thin: Boolean,
-      name: { type: String, select: true },
-      docs: [new Schema({ bool: Boolean, name: { type: String, select: true }})]
+      name: {type: String, select: true},
+      docs: [new Schema({bool: Boolean, name: {type: String, select: true}})]
     });
 
     var S = db.model('IncludingBySchemaType', schema);
-    S.create({ thin: true, name: 'the included', docs:[{bool:true, name: 'test'}] }, function(err, s) {
+    S.create({thin: true, name: 'the included', docs: [{bool: true, name: 'test'}]}, function (err, s) {
       assert.ifError(err);
       assert.equal(s.name, 'the included');
       assert.equal(s.docs[0].name, 'test');
 
       var pending = 4;
+
       function cb(err, s) {
         if (!--pending) {
           db.close();
         }
-        if (Array.isArray(s)) s = s[0];
+        if (Array.isArray(s)) {
+          s = s[0];
+        }
         assert.strictEqual(null, err);
         assert.strictEqual(true, s.isSelected('name'));
         assert.strictEqual(true, s.isSelected('docs.name'));
@@ -85,49 +89,49 @@ describe('schema select option', function() {
         }
       }
 
-      S.findById(s).select('-thin -docs.bool').exec(function(err, res) {
+      S.findById(s).select('-thin -docs.bool').exec(function (err, res) {
         cb(err, res);
-        S.find({ _id: s._id }).select('thin docs.bool').exec(function(err, res) {
+        S.find({_id: s._id}).select('thin docs.bool').exec(function (err, res) {
           cb(err, res);
-          S.findOneAndUpdate({ _id: s._id }, { thin: false }, function(err, s) {
+          S.findOneAndUpdate({_id: s._id}, {thin: false}, function (err, s) {
             cb(err, s);
-            S.findOneAndRemove({ _id: s._id }, cb);
+            S.findOneAndRemove({_id: s._id}, cb);
           });
         });
       });
     });
   });
 
-  describe('overriding schematype select options', function() {
+  describe('overriding schematype select options', function () {
     var db, selected, excluded, S, E;
 
-    before(function() {
+    before(function () {
       db = start();
 
       selected = new Schema({
         thin: Boolean,
-        name: { type: String, select: true },
-        docs: [new Schema({ name: { type: String, select: true }, bool: Boolean })]
+        name: {type: String, select: true},
+        docs: [new Schema({name: {type: String, select: true}, bool: Boolean})]
       });
       excluded = new Schema({
         thin: Boolean,
-        name: { type: String, select: false },
-        docs: [new Schema({ name: { type: String, select: false }, bool: Boolean})]
+        name: {type: String, select: false},
+        docs: [new Schema({name: {type: String, select: false}, bool: Boolean})]
       });
 
       S = db.model('OverriddingSelectedBySchemaType', selected);
       E = db.model('OverriddingExcludedBySchemaType', excluded);
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    describe('works', function() {
-      describe('for inclusions', function() {
+    describe('works', function () {
+      describe('for inclusions', function () {
         var s;
-        before(function(done) {
-          S.create({ thin: true, name: 'the included', docs: [{name:'test',bool: true}] }, function(err, s_) {
+        before(function (done) {
+          S.create({thin: true, name: 'the included', docs: [{name: 'test', bool: true}]}, function (err, s_) {
             assert.ifError(err);
             s = s_;
             assert.equal(s.name, 'the included');
@@ -135,8 +139,8 @@ describe('schema select option', function() {
             done();
           });
         });
-        it('with find', function(done) {
-          S.find({ _id: s._id }).select('thin name docs.bool docs.name').exec(function(err, s) {
+        it('with find', function (done) {
+          S.find({_id: s._id}).select('thin name docs.bool docs.name').exec(function (err, s) {
             assert.ifError(err);
             assert.ok(s && s.length > 0, 'no document found');
             s = s[0];
@@ -151,8 +155,8 @@ describe('schema select option', function() {
             done();
           });
         });
-        it('for findById', function(done) {
-          S.findById(s).select('-name -docs.name').exec(function(err, s) {
+        it('for findById', function (done) {
+          S.findById(s).select('-name -docs.name').exec(function (err, s) {
             assert.strictEqual(null, err);
             assert.equal(false, s.isSelected('name'));
             assert.equal(true, s.isSelected('thin'));
@@ -165,8 +169,8 @@ describe('schema select option', function() {
             done();
           });
         });
-        it('with findOneAndUpdate', function(done) {
-          S.findOneAndUpdate({ _id: s._id }, { name: 'changed' }, { 'new': true }).select('thin name docs.bool docs.name').exec(function(err, s) {
+        it('with findOneAndUpdate', function (done) {
+          S.findOneAndUpdate({_id: s._id}, {name: 'changed'}, {'new': true}).select('thin name docs.bool docs.name').exec(function (err, s) {
             assert.ifError(err);
             assert.strictEqual(true, s.isSelected('name'));
             assert.strictEqual(true, s.isSelected('thin'));
@@ -179,8 +183,8 @@ describe('schema select option', function() {
             done();
           });
         });
-        it('for findByIdAndUpdate', function(done) {
-          S.findByIdAndUpdate(s, { thin: false }, { 'new': true }).select('-name -docs.name').exec(function(err, s) {
+        it('for findByIdAndUpdate', function (done) {
+          S.findByIdAndUpdate(s, {thin: false}, {'new': true}).select('-name -docs.name').exec(function (err, s) {
             assert.strictEqual(null, err);
             assert.equal(false, s.isSelected('name'));
             assert.equal(true, s.isSelected('thin'));
@@ -195,10 +199,10 @@ describe('schema select option', function() {
         });
       });
 
-      describe('for exclusions', function() {
+      describe('for exclusions', function () {
         var e;
-        before(function(done) {
-          E.create({ thin: true, name: 'the excluded',docs:[{name:'test',bool:true}] }, function(err, e_) {
+        before(function (done) {
+          E.create({thin: true, name: 'the excluded', docs: [{name: 'test', bool: true}]}, function (err, e_) {
             e = e_;
             assert.ifError(err);
             assert.equal(e.name, 'the excluded');
@@ -206,8 +210,8 @@ describe('schema select option', function() {
             done();
           });
         });
-        it('with find', function(done) {
-          E.find({ _id: e._id }).select('thin name docs.name docs.bool').exec(function(err, e) {
+        it('with find', function (done) {
+          E.find({_id: e._id}).select('thin name docs.name docs.bool').exec(function (err, e) {
             e = e[0];
             assert.strictEqual(null, err);
             assert.equal(true, e.isSelected('name'));
@@ -221,12 +225,12 @@ describe('schema select option', function() {
             done();
           });
         });
-        it('with findById', function(done) {
-          E.findById(e).select('-name -docs.name').exec(function(err, e) {
+        it('with findById', function (done) {
+          E.findById(e).select('-name -docs.name').exec(function (err, e) {
             assert.strictEqual(null, err);
-            assert.equal(e.isSelected('name'),false);
+            assert.equal(e.isSelected('name'), false);
             assert.equal(e.isSelected('thin'), true);
-            assert.equal(e.isSelected('docs.name'),false);
+            assert.equal(e.isSelected('docs.name'), false);
             assert.equal(e.isSelected('docs.bool'), true);
             assert.strictEqual(undefined, e.name);
             assert.strictEqual(undefined, e.docs[0].name);
@@ -235,8 +239,8 @@ describe('schema select option', function() {
             done();
           });
         });
-        it('with findOneAndUpdate', function(done) {
-          E.findOneAndUpdate({ _id: e._id }, { name: 'changed' }, { 'new': true }).select('thin name docs.name docs.bool').exec(function(err, e) {
+        it('with findOneAndUpdate', function (done) {
+          E.findOneAndUpdate({_id: e._id}, {name: 'changed'}, {'new': true}).select('thin name docs.name docs.bool').exec(function (err, e) {
             assert.strictEqual(null, err);
             assert.equal(true, e.isSelected('name'));
             assert.equal(true, e.isSelected('thin'));
@@ -249,12 +253,12 @@ describe('schema select option', function() {
             done();
           });
         });
-        it('with findOneAndRemove', function(done) {
-          E.findOneAndRemove({ _id: e._id }).select('-name -docs.name').exec(function(err, e) {
+        it('with findOneAndRemove', function (done) {
+          E.findOneAndRemove({_id: e._id}).select('-name -docs.name').exec(function (err, e) {
             assert.strictEqual(null, err);
-            assert.equal(e.isSelected('name'),false);
+            assert.equal(e.isSelected('name'), false);
             assert.equal(e.isSelected('thin'), true);
-            assert.equal(e.isSelected('docs.name'),false);
+            assert.equal(e.isSelected('docs.name'), false);
             assert.equal(e.isSelected('docs.bool'), true);
             assert.strictEqual(undefined, e.name);
             assert.strictEqual(undefined, e.docs[0].name);
@@ -267,15 +271,15 @@ describe('schema select option', function() {
     });
   });
 
-  describe('exclusion in root schema should override child schema', function() {
-    it('works (gh-1333)', function(done) {
+  describe('exclusion in root schema should override child schema', function () {
+    it('works (gh-1333)', function (done) {
       var m = new mongoose.Mongoose();
       var child = new Schema({
-        name1: {type:String, select: false},
-        name2: {type:String, select: true}
+        name1: {type: String, select: false},
+        name2: {type: String, select: true}
       });
       var selected = new Schema({
-        docs: { type: [child], select: false }
+        docs: {type: [child], select: false}
       });
       var M = m.model('gh-1333-deselect', selected);
 
@@ -289,22 +293,22 @@ describe('schema select option', function() {
     });
   });
 
-  describe('forcing inclusion of a deselected schema path', function() {
-    it('works', function(done) {
+  describe('forcing inclusion of a deselected schema path', function () {
+    it('works', function (done) {
       var db = start();
       var excluded = new Schema({
         thin: Boolean,
-        name: { type: String, select: false },
-        docs: [new Schema({ name: { type: String, select: false }, bool: Boolean })]
+        name: {type: String, select: false},
+        docs: [new Schema({name: {type: String, select: false}, bool: Boolean})]
       });
 
       var M = db.model('ForcedInclusionOfPath', excluded);
-      M.create({ thin: false, name: '1 meter', docs:[{name:'test', bool:false}] }, function(err, d) {
+      M.create({thin: false, name: '1 meter', docs: [{name: 'test', bool: false}]}, function (err, d) {
         assert.ifError(err);
 
         M.findById(d)
         .select('+name +docs.name')
-        .exec(function(err, doc) {
+        .exec(function (err, doc) {
           assert.ifError(err);
           assert.equal(false, doc.thin);
           assert.equal('1 meter', doc.name);
@@ -314,7 +318,7 @@ describe('schema select option', function() {
 
           M.findById(d)
           .select('+name -thin +docs.name -docs.bool')
-          .exec(function(err, doc) {
+          .exec(function (err, doc) {
             assert.ifError(err);
             assert.equal(undefined, doc.thin);
             assert.equal('1 meter', doc.name);
@@ -324,7 +328,7 @@ describe('schema select option', function() {
 
             M.findById(d)
             .select('-thin +name -docs.bool +docs.name')
-            .exec(function(err, doc) {
+            .exec(function (err, doc) {
               assert.ifError(err);
               assert.equal(undefined, doc.thin);
               assert.equal('1 meter', doc.name);
@@ -334,7 +338,7 @@ describe('schema select option', function() {
 
               M.findById(d)
               .select('-thin -docs.bool')
-              .exec(function(err, doc) {
+              .exec(function (err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(undefined, doc.thin);
@@ -350,17 +354,21 @@ describe('schema select option', function() {
       });
     });
 
-    it('works with query.slice (gh-1370)', function(done) {
+    it('works with query.slice (gh-1370)', function (done) {
       var db = start();
-      var M = db.model("1370", new Schema({ many: { type: [String], select: false }}));
+      var M = db.model('1370', new Schema({many: {type: [String], select: false}}));
 
-      M.create({ many: ["1", "2", "3", "4", "5"] }, function(err) {
-        if (err) return done(err);
+      M.create({many: ['1', '2', '3', '4', '5']}, function (err) {
+        if (err) {
+          return done(err);
+        }
 
-        var query = M.findOne().select("+many").where("many").slice(2);
+        var query = M.findOne().select('+many').where('many').slice(2);
 
-        query.exec(function(err, doc) {
-          if (err) return done(err);
+        query.exec(function (err, doc) {
+          if (err) {
+            return done(err);
+          }
           assert.equal(2, doc.many.length);
           db.close(done);
         });
@@ -368,49 +376,52 @@ describe('schema select option', function() {
     });
   });
 
-  it('conflicting schematype path selection should not error', function(done) {
+  it('conflicting schematype path selection should not error', function (done) {
     var db = start();
 
     var schema = new Schema({
       thin: Boolean,
-      name: { type: String, select: true },
-      conflict: { type: String, select: false}
+      name: {type: String, select: true},
+      conflict: {type: String, select: false}
     });
 
     var S = db.model('ConflictingBySchemaType', schema);
-    S.create({ thin: true, name: 'bing', conflict: 'crosby' }, function(err, s) {
+    S.create({thin: true, name: 'bing', conflict: 'crosby'}, function (err, s) {
       assert.strictEqual(null, err);
       assert.equal(s.name, 'bing');
       assert.equal(s.conflict, 'crosby');
 
       var pending = 2;
+
       function cb(err, s) {
         if (!--pending) {
           db.close(done);
         }
-        if (Array.isArray(s)) s = s[0];
+        if (Array.isArray(s)) {
+          s = s[0];
+        }
         assert.ifError(err);
         assert.equal(s.name, 'bing');
         assert.equal(undefined, s.conflict);
       }
 
       S.findById(s).exec(cb);
-      S.find({ _id: s._id }).exec(cb);
+      S.find({_id: s._id}).exec(cb);
     });
   });
 
-  it('selecting _id works with excluded schematype path', function(done) {
+  it('selecting _id works with excluded schematype path', function (done) {
     var db = start();
 
     var schema = new Schema({
-      name: { type: String, select: false}
+      name: {type: String, select: false}
     });
 
     var M = db.model('SelectingOnly_idWithExcludedSchemaType', schema);
-    M.find().select('_id -name').exec(function(err) {
+    M.find().select('_id -name').exec(function (err) {
       assert.ok(err instanceof Error, 'conflicting path selection error should be instance of Error');
 
-      M.find().select('_id').exec(function(err) {
+      M.find().select('_id').exec(function (err) {
         db.close();
         assert.ifError(err, err && err.stack);
         done();
@@ -418,18 +429,18 @@ describe('schema select option', function() {
     });
   });
 
-  it('selecting _id works with excluded schematype path on sub doc', function(done) {
+  it('selecting _id works with excluded schematype path on sub doc', function (done) {
     var db = start();
 
     var schema = new Schema({
-      docs: [new Schema({name: { type: String, select: false}})]
+      docs: [new Schema({name: {type: String, select: false}})]
     });
 
     var M = db.model('SelectingOnly_idWithExcludedSchemaType', schema);
-    M.find().select('_id -docs.name').exec(function(err) {
+    M.find().select('_id -docs.name').exec(function (err) {
       assert.ok(err instanceof Error, 'conflicting path selection error should be instance of Error');
 
-      M.find().select('_id').exec(function(err) {
+      M.find().select('_id').exec(function (err) {
         db.close();
         assert.ifError(err, err && err.stack);
         done();
@@ -437,44 +448,44 @@ describe('schema select option', function() {
     });
   });
 
-  it('all inclusive/exclusive combos work', function(done) {
+  it('all inclusive/exclusive combos work', function (done) {
     var db = start();
     var coll = 'inclusiveexclusivecomboswork_' + random();
 
     var schema = new Schema({
-      name: { type: String },
+      name: {type: String},
       age: Number
-    }, { collection: coll });
+    }, {collection: coll});
     var M = db.model('InclusiveExclusiveCombosWork', schema);
 
     var schema1 = new Schema({
-      name: { type: String, select: false },
+      name: {type: String, select: false},
       age: Number
-    }, { collection: coll });
+    }, {collection: coll});
     var S = db.model('InclusiveExclusiveCombosWorkWithSchemaSelectionFalse', schema1);
 
     var schema2 = new Schema({
-      name: { type: String, select: true },
+      name: {type: String, select: true},
       age: Number
-    }, { collection: coll });
+    }, {collection: coll});
     var T = db.model('InclusiveExclusiveCombosWorkWithSchemaSelectionTrue', schema2);
 
     function useId(M, id, cb) {
-      M.findOne().select('_id -name').exec(function(err, d) {
+      M.findOne().select('_id -name').exec(function (err, d) {
         assert.ok(err);
         assert.ok(!d);
-        M.findOne().select('-_id name').exec(function(err, d) {
+        M.findOne().select('-_id name').exec(function (err, d) {
           // mongo special case for exclude _id + include path
           assert.ifError(err);
           assert.equal(undefined, d.id);
           assert.equal('ssd', d.name);
           assert.equal(undefined, d.age);
-          M.findOne().select('-_id -name').exec(function(err, d) {
+          M.findOne().select('-_id -name').exec(function (err, d) {
             assert.ifError(err);
             assert.equal(undefined, d.id);
             assert.equal(undefined, d.name);
             assert.equal(0, d.age);
-            M.findOne().select('_id name').exec(function(err, d) {
+            M.findOne().select('_id name').exec(function (err, d) {
               assert.ifError(err);
               assert.equal(id, d.id);
               assert.equal('ssd', d.name);
@@ -487,18 +498,18 @@ describe('schema select option', function() {
     }
 
     function nonId(M, id, cb) {
-      M.findOne().select('age -name').exec(function(err, d) {
+      M.findOne().select('age -name').exec(function (err, d) {
         assert.ok(err);
         assert.ok(!d);
-        M.findOne().select('-age name').exec(function(err, d) {
+        M.findOne().select('-age name').exec(function (err, d) {
           assert.ok(err);
           assert.ok(!d);
-          M.findOne().select('-age -name').exec(function(err, d) {
+          M.findOne().select('-age -name').exec(function (err, d) {
             assert.ifError(err);
             assert.equal(id, d.id);
             assert.equal(undefined, d.name);
             assert.equal(undefined, d.age);
-            M.findOne().select('age name').exec(function(err, d) {
+            M.findOne().select('age name').exec(function (err, d) {
               assert.ifError(err);
               assert.equal(id, d.id);
               assert.equal('ssd', d.name);
@@ -510,15 +521,15 @@ describe('schema select option', function() {
       });
     }
 
-    M.create({ name: 'ssd', age: 0 }, function(err, d) {
+    M.create({name: 'ssd', age: 0}, function (err, d) {
       assert.ifError(err);
       var id = d.id;
-      useId(M, id, function() {
-        nonId(M, id, function() {
-          useId(S, id, function() {
-            nonId(S, id, function() {
-              useId(T, id, function() {
-                nonId(T, id, function() {
+      useId(M, id, function () {
+        nonId(M, id, function () {
+          useId(S, id, function () {
+            nonId(S, id, function () {
+              useId(T, id, function () {
+                nonId(T, id, function () {
                   db.close();
                   done();
                 });
@@ -530,10 +541,10 @@ describe('schema select option', function() {
     });
   });
 
-  it('initializes nested defaults with selected objects (gh-2629)', function(done) {
+  it('initializes nested defaults with selected objects (gh-2629)', function (done) {
     var NestedSchema = new mongoose.Schema({
       nested: {
-        name: { type: String, default: 'val' }
+        name: {type: String, default: 'val'}
       }
     });
 
@@ -542,9 +553,9 @@ describe('schema select option', function() {
 
     var doc = new Model();
     doc.nested.name = undefined;
-    doc.save(function(error) {
+    doc.save(function (error) {
       assert.ifError(error);
-      Model.findOne({}, { nested: 1 }, function(error, doc) {
+      Model.findOne({}, {nested: 1}, function (error, doc) {
         assert.ifError(error);
         assert.equal('val', doc.nested.name);
         db.close(done);
diff --git a/test/schema.test.js b/test/schema.test.js
index b2881a06566..dbd50a355ff 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -41,11 +41,11 @@ TestDocument.prototype.$__setSchema(new Schema({
  * Test.
  */
 
-describe('schema', function() {
-  describe('nested fields with same name', function() {
+describe('schema', function () {
+  describe('nested fields with same name', function () {
     var db, NestedModel;
 
-    before(function() {
+    before(function () {
       db = start();
       var NestedSchema = new Schema({
         a: {
@@ -55,26 +55,27 @@ describe('schema', function() {
           }
         },
         b: {$type: String}
-      }, { typeKey: '$type' });
+      }, {typeKey: '$type'});
       NestedModel = db.model('Nested', NestedSchema);
     });
 
-    after(function() {
+    after(function () {
       db.close();
     });
 
-    it('don\'t disappear', function(done) {
+    it('don\'t disappear', function (done) {
       var n = new NestedModel({
         a: {
           b: {
-            c:'foo',
-            d:'bar'}
-        }, b:'foobar'
+            c: 'foo',
+            d: 'bar'
+          }
+        }, b: 'foobar'
       });
 
-      n.save(function(err) {
+      n.save(function (err) {
         assert.ifError(err);
-        NestedModel.findOne({_id :n._id}, function(err, nm) {
+        NestedModel.findOne({_id: n._id}, function (err, nm) {
           assert.ifError(err);
 
           // make sure no field has disappeared
@@ -92,19 +93,19 @@ describe('schema', function() {
   });
 
 
-  it('can be created without the "new" keyword', function(done) {
-    var schema = Schema({ name: String });
+  it('can be created without the "new" keyword', function (done) {
+    var schema = Schema({name: String});
     assert.ok(schema instanceof Schema);
     done();
   });
 
-  it('does expose a property for duck-typing instanceof', function(done) {
-    var schema = Schema({ name: String });
+  it('does expose a property for duck-typing instanceof', function (done) {
+    var schema = Schema({name: String});
     assert.ok(schema.instanceOfSchema);
     done();
   });
 
-  it('supports different schematypes', function(done) {
+  it('supports different schematypes', function (done) {
     var Checkin = new Schema({
       date: Date,
       location: {
@@ -117,7 +118,7 @@ describe('schema', function() {
       name: String,
       owner: ObjectId,
       fur: String,
-      color: { type: String },
+      color: {type: String},
       age: Number,
       checkins: [Checkin],
       friends: [ObjectId],
@@ -155,20 +156,20 @@ describe('schema', function() {
     assert.ok(Checkin1.path('location.lng') instanceof SchemaTypes.Number);
 
     var Ferret1 = new Schema({
-      name      : "string",
-      owner     : "oid",
-      fur: { type: "string" },
-      color: { type: "String" },
+      name: 'string',
+      owner: 'oid',
+      fur: {type: 'string'},
+      color: {type: 'String'},
       checkins: [Checkin],
       friends: Array,
-      likes     : "array",
-      alive     : "Bool",
-      alive1    : "bool",
-      alive2    : "boolean",
-      extra     : "mixed",
-      obj       : "object",
-      buf       : "buffer",
-      Buf       : "Buffer"
+      likes: 'array',
+      alive: 'Bool',
+      alive1: 'bool',
+      alive2: 'boolean',
+      extra: 'mixed',
+      obj: 'object',
+      buf: 'buffer',
+      Buf: 'Buffer'
     });
 
     assert.ok(Ferret1.path('name') instanceof SchemaTypes.String);
@@ -176,7 +177,7 @@ describe('schema', function() {
     assert.ok(Ferret1.path('fur') instanceof SchemaTypes.String);
     assert.ok(Ferret1.path('color') instanceof SchemaTypes.String);
     assert.ok(Ferret1.path('checkins') instanceof SchemaTypes.DocumentArray);
-    assert.ok( Ferret1.path('friends') instanceof SchemaTypes.Array);
+    assert.ok(Ferret1.path('friends') instanceof SchemaTypes.Array);
     assert.ok(Ferret1.path('likes') instanceof SchemaTypes.Array);
     assert.ok(Ferret1.path('alive') instanceof SchemaTypes.Boolean);
     assert.ok(Ferret1.path('alive1') instanceof SchemaTypes.Boolean);
@@ -188,9 +189,9 @@ describe('schema', function() {
     done();
   });
 
-  it('supports dot notation for path accessors', function(done) {
+  it('supports dot notation for path accessors', function (done) {
     var Racoon = new Schema({
-      name: { type: String, enum: ['Edwald', 'Tobi'] },
+      name: {type: String, enum: ['Edwald', 'Tobi']},
       age: Number
     });
 
@@ -215,7 +216,7 @@ describe('schema', function() {
     done();
   });
 
-  it('allows paths nested > 2 levels', function(done) {
+  it('allows paths nested > 2 levels', function (done) {
     var Nested = new Schema({
       first: {
         second: {
@@ -227,23 +228,29 @@ describe('schema', function() {
     done();
   });
 
-  it('default definition', function(done) {
+  it('default definition', function (done) {
     var Test = new Schema({
-      simple: { $type: String, default: 'a' },
-      array: { $type: Array, default: [1,2,3,4,5] },
-      arrayX: { $type: Array, default: 9 },
-      arrayFn: { $type: Array, default: function() { return [8]; } },
-      callback: { $type: Number, default: function() {
-        assert.equal('b', this.a);
-        return '3';
-      }}
-    }, { typeKey: '$type' });
+      simple: {$type: String, default: 'a'},
+      array: {$type: Array, default: [1, 2, 3, 4, 5]},
+      arrayX: {$type: Array, default: 9},
+      arrayFn: {
+        $type: Array, default: function () {
+          return [8];
+        }
+      },
+      callback: {
+        $type: Number, default: function () {
+          assert.equal('b', this.a);
+          return '3';
+        }
+      }
+    }, {typeKey: '$type'});
 
     assert.equal(Test.path('simple').defaultValue, 'a');
     assert.equal(typeof Test.path('callback').defaultValue, 'function');
 
     assert.equal(Test.path('simple').getDefault(), 'a');
-    assert.equal((+Test.path('callback').getDefault({ a: 'b' })), 3);
+    assert.equal((+Test.path('callback').getDefault({a: 'b'})), 3);
     assert.equal(typeof Test.path('array').defaultValue, 'function');
     assert.equal(Test.path('array').getDefault(new TestDocument)[3], 4);
     assert.equal(Test.path('arrayX').getDefault(new TestDocument)[0], 9);
@@ -254,10 +261,10 @@ describe('schema', function() {
     done();
   });
 
-  it('Mixed defaults can be empty arrays', function(done) {
+  it('Mixed defaults can be empty arrays', function (done) {
     var Test = new Schema({
-      mixed1: { type: Mixed, default: [] },
-      mixed2: { type: Mixed, default: Array }
+      mixed1: {type: Mixed, default: []},
+      mixed2: {type: Mixed, default: Array}
     });
 
     assert.ok(Test.path('mixed1').getDefault() instanceof Array);
@@ -267,8 +274,8 @@ describe('schema', function() {
     done();
   });
 
-  describe('casting', function() {
-    it('number', function(done) {
+  describe('casting', function () {
+    it('number', function (done) {
       var Tobi = new Schema({
         age: Number
       });
@@ -282,14 +289,16 @@ describe('schema', function() {
       done();
     });
 
-    describe('string', function() {
-      it('works', function(done) {
+    describe('string', function () {
+      it('works', function (done) {
         var Tobi = new Schema({
           nickname: String
         });
 
-        function Test() {}
-        Test.prototype.toString = function() {
+        function Test() {
+        }
+
+        Test.prototype.toString = function () {
           return 'woot';
         };
 
@@ -304,9 +313,9 @@ describe('schema', function() {
       });
     });
 
-    it('date', function(done) {
+    it('date', function (done) {
       var Loki = new Schema({
-        birth_date: { type: Date }
+        birth_date: {type: Date}
       });
 
       assert.ok(Loki.path('birth_date').cast(1294525628301) instanceof Date);
@@ -317,28 +326,25 @@ describe('schema', function() {
       done();
     });
 
-    it('objectid', function(done) {
+    it('objectid', function (done) {
       var Loki = new Schema({
-        owner: { type: ObjectId }
+        owner: {type: ObjectId}
       });
 
       var doc = new TestDocument(),
           id = doc._id.toString();
 
-      assert.ok(Loki.path('owner').cast('4c54f3453e688c000000001a')
-                        instanceof DocumentObjectId);
+      assert.ok(Loki.path('owner').cast('4c54f3453e688c000000001a') instanceof DocumentObjectId);
 
-      assert.ok(Loki.path('owner').cast(new DocumentObjectId())
-                        instanceof DocumentObjectId);
+      assert.ok(Loki.path('owner').cast(new DocumentObjectId()) instanceof DocumentObjectId);
 
-      assert.ok(Loki.path('owner').cast(doc)
-                        instanceof DocumentObjectId);
+      assert.ok(Loki.path('owner').cast(doc) instanceof DocumentObjectId);
 
       assert.equal(id, Loki.path('owner').cast(doc).toString());
       done();
     });
 
-    it('array', function(done) {
+    it('array', function (done) {
       var Loki = new Schema({
         oids: [ObjectId],
         dates: [Date],
@@ -367,12 +373,12 @@ describe('schema', function() {
       var strings = Loki.path('strings').cast(['test', 123]);
 
       assert.equal(typeof strings[0], 'string');
-      assert.equal('test',strings[0]);
+      assert.equal('test', strings[0]);
 
       assert.equal(typeof strings[1], 'string');
       assert.equal('123', strings[1]);
 
-      var buffers = Loki.path('buffers').cast(['\0\0\0', new Buffer("abc")]);
+      var buffers = Loki.path('buffers').cast(['\0\0\0', new Buffer('abc')]);
 
       assert.ok(buffers[0] instanceof Buffer);
       assert.ok(buffers[1] instanceof Buffer);
@@ -396,9 +402,9 @@ describe('schema', function() {
       done();
     });
 
-    it('boolean', function(done) {
+    it('boolean', function (done) {
       var Animal = new Schema({
-        isFerret: { type: Boolean, required: true }
+        isFerret: {type: Boolean, required: true}
       });
 
       assert.strictEqual(Animal.path('isFerret').cast(null), null);
@@ -416,44 +422,51 @@ describe('schema', function() {
     });
   });
 
-  it('methods declaration', function(done) {
+  it('methods declaration', function (done) {
     var a = new Schema;
-    a.method('test', function() {});
+    a.method('test', function () {
+    });
     a.method({
-      a: function() {},
-      b: function() {}
+      a: function () {
+      },
+      b: function () {
+      }
     });
     assert.equal(3, Object.keys(a.methods).length);
     done();
   });
 
-  it('static declaration', function(done) {
+  it('static declaration', function (done) {
     var a = new Schema;
-    a.static('test', function() {});
+    a.static('test', function () {
+    });
     a.static({
-      a: function() {},
-      b: function() {},
-      c: function() {}
+      a: function () {
+      },
+      b: function () {
+      },
+      c: function () {
+      }
     });
 
     assert.equal(Object.keys(a.statics).length, 4);
     done();
   });
 
-  describe('setters', function() {
-    it('work', function(done) {
+  describe('setters', function () {
+    it('work', function (done) {
       function lowercase(v) {
         return v.toLowerCase();
       }
 
       var Tobi = new Schema({
-        name: { type: String, set: lowercase }
+        name: {type: String, set: lowercase}
       });
 
       assert.equal('woot', Tobi.path('name').applySetters('WOOT'));
       assert.equal(1, Tobi.path('name').setters.length);
 
-      Tobi.path('name').set(function(v) {
+      Tobi.path('name').set(function (v) {
         return v + 'WOOT';
       });
 
@@ -462,28 +475,28 @@ describe('schema', function() {
       done();
     });
 
-    it('order', function(done) {
+    it('order', function (done) {
       function extract(v) {
         return (v && v._id)
-          ? v._id
-          : v;
+            ? v._id
+            : v;
       }
 
       var Tobi = new Schema({
-        name: { type: Schema.ObjectId, set: extract }
+        name: {type: Schema.ObjectId, set: extract}
       });
 
       var id = new DocumentObjectId,
           sid = id.toString(),
-          _id = { _id: id };
+          _id = {_id: id};
 
-      assert.equal(Tobi.path('name').applySetters(sid, { a: 'b' }).toString(),sid);
-      assert.equal(Tobi.path('name').applySetters(_id, { a: 'b' }).toString(),sid);
-      assert.equal(Tobi.path('name').applySetters(id, { a: 'b' }).toString(),sid);
+      assert.equal(Tobi.path('name').applySetters(sid, {a: 'b'}).toString(), sid);
+      assert.equal(Tobi.path('name').applySetters(_id, {a: 'b'}).toString(), sid);
+      assert.equal(Tobi.path('name').applySetters(id, {a: 'b'}).toString(), sid);
       done();
     });
 
-    it('scope', function(done) {
+    it('scope', function (done) {
       function lowercase(v, self) {
         assert.equal('b', this.a);
         assert.equal('name', self.path);
@@ -491,14 +504,14 @@ describe('schema', function() {
       }
 
       var Tobi = new Schema({
-        name: { type: String, set: lowercase }
+        name: {type: String, set: lowercase}
       });
 
-      assert.equal('what', Tobi.path('name').applySetters('WHAT', { a: 'b' }));
+      assert.equal('what', Tobi.path('name').applySetters('WHAT', {a: 'b'}));
       done();
     });
 
-    it('casting', function(done) {
+    it('casting', function (done) {
       function last(v) {
         assert.equal('number', typeof v);
         assert.equal(0, v);
@@ -510,7 +523,7 @@ describe('schema', function() {
       }
 
       var Tobi = new Schema({
-        name: { type: String, set: last }
+        name: {type: String, set: last}
       });
 
       Tobi.path('name').set(first);
@@ -518,8 +531,8 @@ describe('schema', function() {
       done();
     });
 
-    describe('array', function() {
-      it('object setters will be applied for each object in array', function(done) {
+    describe('array', function () {
+      it('object setters will be applied for each object in array', function (done) {
         var Tobi = new Schema({
           names: [{type: String, lowercase: true, trim: true}]
         });
@@ -531,28 +544,28 @@ describe('schema', function() {
       });
     });
 
-    describe('string', function() {
-      it('lowercase', function(done) {
+    describe('string', function () {
+      it('lowercase', function (done) {
         var Tobi = new Schema({
-          name: { type: String, lowercase: true }
+          name: {type: String, lowercase: true}
         });
 
         assert.equal('what', Tobi.path('name').applySetters('WHAT'));
         assert.equal('1977', Tobi.path('name').applySetters(1977));
         done();
       });
-      it('uppercase', function(done) {
+      it('uppercase', function (done) {
         var Tobi = new Schema({
-          name: { type: String, uppercase: true }
+          name: {type: String, uppercase: true}
         });
 
         assert.equal('WHAT', Tobi.path('name').applySetters('what'));
         assert.equal('1977', Tobi.path('name').applySetters(1977));
         done();
       });
-      it('trim', function(done) {
+      it('trim', function (done) {
         var Tobi = new Schema({
-          name: { type: String, uppercase: true, trim: true }
+          name: {type: String, uppercase: true, trim: true}
         });
 
         assert.equal('WHAT', Tobi.path('name').applySetters('  what   '));
@@ -561,7 +574,7 @@ describe('schema', function() {
       });
     });
 
-    it('applying when none have been defined', function(done) {
+    it('applying when none have been defined', function (done) {
       var Tobi = new Schema({
         name: String
       });
@@ -570,8 +583,8 @@ describe('schema', function() {
       done();
     });
 
-    it('assignment of non-functions throw', function(done) {
-      var schema = new Schema({ fun: String });
+    it('assignment of non-functions throw', function (done) {
+      var schema = new Schema({fun: String});
       var g;
 
       try {
@@ -581,40 +594,40 @@ describe('schema', function() {
       }
 
       assert.ok(g);
-      assert.equal(g.message,'A setter must be a function.');
+      assert.equal(g.message, 'A setter must be a function.');
       done();
     });
   });
 
-  describe('getters', function() {
-    it('work', function(done) {
+  describe('getters', function () {
+    it('work', function (done) {
       function woot(v) {
         return v + ' woot';
       }
 
       var Tobi = new Schema({
-        name: { type: String, get: woot }
+        name: {type: String, get: woot}
       });
 
       assert.equal(1, Tobi.path('name').getters.length);
       assert.equal('test woot', Tobi.path('name').applyGetters('test'));
       done();
     });
-    it('order', function(done) {
+    it('order', function (done) {
       function format(v) {
         return v
-          ? '$' + v
-          : v;
+            ? '$' + v
+            : v;
       }
 
       var Tobi = new Schema({
-        name: { type: Number, get: format }
+        name: {type: Number, get: format}
       });
 
-      assert.equal('$30', Tobi.path('name').applyGetters(30, { a: 'b' }));
+      assert.equal('$30', Tobi.path('name').applyGetters(30, {a: 'b'}));
       done();
     });
-    it('scope', function(done) {
+    it('scope', function (done) {
       function woot(v, self) {
         assert.equal('b', this.a);
         assert.equal('name', self.path);
@@ -622,13 +635,13 @@ describe('schema', function() {
       }
 
       var Tobi = new Schema({
-        name: { type: String, get: woot }
+        name: {type: String, get: woot}
       });
 
-      assert.equal('yep', Tobi.path('name').applyGetters('YEP', { a: 'b' }));
+      assert.equal('yep', Tobi.path('name').applyGetters('YEP', {a: 'b'}));
       done();
     });
-    it('casting', function(done) {
+    it('casting', function (done) {
       function last(v) {
         assert.equal('number', typeof v);
         assert.equal(0, v);
@@ -640,14 +653,14 @@ describe('schema', function() {
       }
 
       var Tobi = new Schema({
-        name: { type: String, get: last }
+        name: {type: String, get: last}
       });
 
       Tobi.path('name').get(first);
       assert.equal('last', Tobi.path('name').applyGetters('woot'));
       done();
     });
-    it('applying when none have been defined', function(done) {
+    it('applying when none have been defined', function (done) {
       var Tobi = new Schema({
         name: String
       });
@@ -655,8 +668,8 @@ describe('schema', function() {
       assert.equal('woot', Tobi.path('name').applyGetters('woot'));
       done();
     });
-    it('assignment of non-functions throw', function(done) {
-      var schema = new Schema({ fun: String });
+    it('assignment of non-functions throw', function (done) {
+      var schema = new Schema({fun: String});
       var g;
 
       try {
@@ -666,10 +679,10 @@ describe('schema', function() {
       }
 
       assert.ok(g);
-      assert.equal(g.message,'A getter must be a function.');
+      assert.equal(g.message, 'A getter must be a function.');
       done();
     });
-    it('auto _id', function(done) {
+    it('auto _id', function (done) {
       var schema = new Schema({
         name: String
       });
@@ -677,28 +690,28 @@ describe('schema', function() {
 
       schema = new Schema({
         name: String
-      }, { _id: true });
+      }, {_id: true});
       assert.ok(schema.path('_id') instanceof Schema.ObjectId);
 
       schema = new Schema({
         name: String
-      }, { _id: false });
+      }, {_id: false});
       assert.equal(undefined, schema.path('_id'));
 
       // old options
       schema = new Schema({
         name: String
-      }, { noId: false });
+      }, {noId: false});
       assert.ok(schema.path('_id') instanceof Schema.ObjectId);
 
       schema = new Schema({
         name: String
-      }, { noId: true });
+      }, {noId: true});
       assert.equal(undefined, schema.path('_id'));
       done();
     });
 
-    it('auto id', function(done) {
+    it('auto id', function (done) {
       var schema = new Schema({
         name: String
       });
@@ -706,93 +719,96 @@ describe('schema', function() {
 
       schema = new Schema({
         name: String
-      }, { id: true });
+      }, {id: true});
       assert.ok(schema.virtualpath('id') instanceof mongoose.VirtualType);
 
       schema = new Schema({
         name: String
-      }, { id: false });
+      }, {id: false});
       assert.equal(undefined, schema.virtualpath('id'));
 
       // old options
       schema = new Schema({
         name: String
-      }, { noVirtualId: false });
+      }, {noVirtualId: false});
       assert.ok(schema.virtualpath('id') instanceof mongoose.VirtualType);
 
       schema = new Schema({
         name: String
-      }, { noVirtualId: true });
+      }, {noVirtualId: true});
       assert.equal(undefined, schema.virtualpath('id'));
       done();
     });
   });
 
-  describe('hooks', function() {
-    it('registration', function(done) {
+  describe('hooks', function () {
+    it('registration', function (done) {
       var Tobi = new Schema();
 
-      Tobi.pre('save', function() {});
+      Tobi.pre('save', function () {
+      });
       assert.equal(Tobi.callQueue.length, 3);
 
-      Tobi.post('save', function() {});
+      Tobi.post('save', function () {
+      });
       assert.equal(Tobi.callQueue.length, 4);
 
-      Tobi.pre('save', function() {});
+      Tobi.pre('save', function () {
+      });
       assert.equal(Tobi.callQueue.length, 5);
       done();
     });
   });
 
-  describe('indexes', function() {
-    describe('definition', function() {
-      it('basic', function(done) {
+  describe('indexes', function () {
+    describe('definition', function () {
+      it('basic', function (done) {
         var Tobi = new Schema({
-          name: { type: String, index: true }
+          name: {type: String, index: true}
         });
 
         assert.equal(true, Tobi.path('name')._index);
-        Tobi.path('name').index({ unique: true });
-        assert.deepEqual(Tobi.path('name')._index, { unique: true });
+        Tobi.path('name').index({unique: true});
+        assert.deepEqual(Tobi.path('name')._index, {unique: true});
         Tobi.path('name').unique(false);
-        assert.deepEqual(Tobi.path('name')._index, { unique: false });
+        assert.deepEqual(Tobi.path('name')._index, {unique: false});
 
         var T, i;
 
         T = new Schema({
-          name: { type: String, sparse: true }
+          name: {type: String, sparse: true}
         });
-        assert.deepEqual(T.path('name')._index, { sparse: true });
+        assert.deepEqual(T.path('name')._index, {sparse: true});
 
         T = new Schema({
-          name: { type: String, unique: true }
+          name: {type: String, unique: true}
         });
-        assert.deepEqual(T.path('name')._index, { unique: true });
+        assert.deepEqual(T.path('name')._index, {unique: true});
 
         T = new Schema({
-          name: { type: Date, expires:  '1.5m' }
+          name: {type: Date, expires: '1.5m'}
         });
-        assert.deepEqual(T.path('name')._index, { expireAfterSeconds: 90 });
+        assert.deepEqual(T.path('name')._index, {expireAfterSeconds: 90});
 
         T = new Schema({
-          name: { type: Date, expires:  200 }
+          name: {type: Date, expires: 200}
         });
-        assert.deepEqual(T.path('name')._index, { expireAfterSeconds: 200 });
+        assert.deepEqual(T.path('name')._index, {expireAfterSeconds: 200});
 
         T = new Schema({
-          name: { type: String, sparse: true, unique: true }
+          name: {type: String, sparse: true, unique: true}
         });
-        assert.deepEqual(T.path('name')._index, { sparse: true, unique: true });
+        assert.deepEqual(T.path('name')._index, {sparse: true, unique: true});
 
         T = new Schema({
-          name: { type: String, unique: true, sparse: true }
+          name: {type: String, unique: true, sparse: true}
         });
         i = T.path('name')._index;
         assert.equal(true, i.unique);
         assert.equal(true, i.sparse);
 
         T = new Schema({
-          name: { type: String, index: { sparse: true, unique: true, expireAfterSeconds: 65 }}
+          name: {type: String, index: {sparse: true, unique: true, expireAfterSeconds: 65}}
         });
         i = T.path('name')._index;
         assert.equal(true, i.unique);
@@ -800,7 +816,7 @@ describe('schema', function() {
         assert.equal(65, i.expireAfterSeconds);
 
         T = new Schema({
-          name: { type: Date, index: { sparse: true, unique: true, expires: '24h' }}
+          name: {type: Date, index: {sparse: true, unique: true, expires: '24h'}}
         });
         i = T.path('name')._index;
         assert.equal(true, i.unique);
@@ -809,22 +825,22 @@ describe('schema', function() {
 
         done();
       });
-      it('compound', function(done) {
+      it('compound', function (done) {
         var Tobi = new Schema({
-          name: { type: String, index: true },
-          last: { type: Number, sparse: true },
-          nope: { type: String, index: { background: false }}
+          name: {type: String, index: true},
+          last: {type: Number, sparse: true},
+          nope: {type: String, index: {background: false}}
         });
 
-        Tobi.index({ firstname: 1, last: 1 }, { unique: true, expires: '1h' });
-        Tobi.index({ firstname: 1, nope: 1 }, { unique: true, background: false });
+        Tobi.index({firstname: 1, last: 1}, {unique: true, expires: '1h'});
+        Tobi.index({firstname: 1, nope: 1}, {unique: true, background: false});
 
         assert.deepEqual(Tobi.indexes(), [
-          [{ name: 1 }, { background: true }],
-          [{ last: 1 }, { sparse: true, background :true }],
-          [{ nope: 1 }, { background: false}],
-          [{ firstname: 1, last: 1}, {unique: true, expireAfterSeconds: 60 * 60, background: true }],
-          [{ firstname: 1, nope: 1 }, { unique: true, background: false }]
+          [{name: 1}, {background: true}],
+          [{last: 1}, {sparse: true, background: true}],
+          [{nope: 1}, {background: false}],
+          [{firstname: 1, last: 1}, {unique: true, expireAfterSeconds: 60 * 60, background: true}],
+          [{firstname: 1, nope: 1}, {unique: true, background: false}]
         ]);
 
         done();
@@ -832,12 +848,12 @@ describe('schema', function() {
     });
   });
 
-  describe('plugins', function() {
-    it('work', function(done) {
+  describe('plugins', function () {
+    it('work', function (done) {
       var Tobi = new Schema,
           called = false;
 
-      Tobi.plugin(function(schema) {
+      Tobi.plugin(function (schema) {
         assert.equal(schema, Tobi);
         called = true;
       });
@@ -847,8 +863,8 @@ describe('schema', function() {
     });
   });
 
-  describe('options', function() {
-    it('defaults are set', function(done) {
+  describe('options', function () {
+    it('defaults are set', function (done) {
       var Tobi = new Schema();
 
       assert.equal('object', typeof Tobi.options);
@@ -863,18 +879,18 @@ describe('schema', function() {
       done();
     });
 
-    it('setting', function(done) {
-      var Tobi = new Schema({}, { collection: 'users' });
+    it('setting', function (done) {
+      var Tobi = new Schema({}, {collection: 'users'});
 
       Tobi.set('a', 'b');
       Tobi.set('safe', false);
       assert.equal('users', Tobi.options.collection);
 
       assert.equal('b', Tobi.options.a);
-      assert.deepEqual(Tobi.options.safe, { w: 0 });
+      assert.deepEqual(Tobi.options.safe, {w: 0});
       assert.equal(null, Tobi.options.read);
 
-      var tags = [{ x: 1 }];
+      var tags = [{x: 1}];
 
       Tobi.set('read', 'n');
       assert.ok(Tobi.options.read instanceof ReadPref);
@@ -892,56 +908,56 @@ describe('schema', function() {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 'p' });
+      Tobi = Schema({}, {read: 'p'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('primary', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['p', tags] });
+      Tobi = Schema({}, {read: ['p', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('primary', Tobi.options.read.mode);
       assert.ok(Array.isArray(Tobi.options.read.tags));
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 'primary' });
+      Tobi = Schema({}, {read: 'primary'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('primary', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['primary', tags] });
+      Tobi = Schema({}, {read: ['primary', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('primary', Tobi.options.read.mode);
       assert.ok(Array.isArray(Tobi.options.read.tags));
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 's' });
+      Tobi = Schema({}, {read: 's'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('secondary', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['s', tags] });
+      Tobi = Schema({}, {read: ['s', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('secondary', Tobi.options.read.mode);
       assert.ok(Array.isArray(Tobi.options.read.tags));
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 'secondary' });
+      Tobi = Schema({}, {read: 'secondary'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('secondary', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['secondary', tags] });
+      Tobi = Schema({}, {read: ['secondary', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('secondary', Tobi.options.read.mode);
       assert.ok(Array.isArray(Tobi.options.read.tags));
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 'pp' });
+      Tobi = Schema({}, {read: 'pp'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('primaryPreferred', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['pp', tags] });
+      Tobi = Schema({}, {read: ['pp', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('primaryPreferred', Tobi.options.read.mode);
@@ -949,12 +965,12 @@ describe('schema', function() {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 'primaryPreferred'});
+      Tobi = Schema({}, {read: 'primaryPreferred'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('primaryPreferred', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['primaryPreferred', tags]});
+      Tobi = Schema({}, {read: ['primaryPreferred', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('primaryPreferred', Tobi.options.read.mode);
@@ -962,12 +978,12 @@ describe('schema', function() {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 'sp' });
+      Tobi = Schema({}, {read: 'sp'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('secondaryPreferred', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['sp', tags] });
+      Tobi = Schema({}, {read: ['sp', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('secondaryPreferred', Tobi.options.read.mode);
@@ -975,12 +991,12 @@ describe('schema', function() {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 'secondaryPreferred'});
+      Tobi = Schema({}, {read: 'secondaryPreferred'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('secondaryPreferred', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['secondaryPreferred', tags]});
+      Tobi = Schema({}, {read: ['secondaryPreferred', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('secondaryPreferred', Tobi.options.read.mode);
@@ -988,12 +1004,12 @@ describe('schema', function() {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 'n'});
+      Tobi = Schema({}, {read: 'n'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('nearest', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['n', tags]});
+      Tobi = Schema({}, {read: ['n', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('nearest', Tobi.options.read.mode);
@@ -1001,12 +1017,12 @@ describe('schema', function() {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, { read: 'nearest'});
+      Tobi = Schema({}, {read: 'nearest'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('nearest', Tobi.options.read.mode);
 
-      Tobi = Schema({}, { read: ['nearest', tags]});
+      Tobi = Schema({}, {read: ['nearest', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('nearest', Tobi.options.read.mode);
@@ -1018,8 +1034,8 @@ describe('schema', function() {
     });
   });
 
-  describe('virtuals', function() {
-    it('works', function(done) {
+  describe('virtuals', function () {
+    it('works', function (done) {
       var Contact = new Schema({
         firstName: String,
         lastName: String
@@ -1027,10 +1043,10 @@ describe('schema', function() {
 
       Contact
       .virtual('fullName')
-      .get(function() {
+      .get(function () {
         return this.get('firstName') + ' ' + this.get('lastName');
       })
-      .set(function(fullName) {
+      .set(function (fullName) {
         var split = fullName.split(' ');
         this.set('firstName', split[0]);
         this.set('lastName', split[1]);
@@ -1040,65 +1056,65 @@ describe('schema', function() {
       done();
     });
 
-    describe('id', function() {
-      it('default creation of id can be overridden (gh-298)', function(done) {
-        assert.doesNotThrow(function() {
-          new Schema({ id: String });
+    describe('id', function () {
+      it('default creation of id can be overridden (gh-298)', function (done) {
+        assert.doesNotThrow(function () {
+          new Schema({id: String});
         });
         done();
       });
-      it('disabling', function(done) {
-        var schema = new Schema({ name: String }, { noVirtualId: true });
+      it('disabling', function (done) {
+        var schema = new Schema({name: String}, {noVirtualId: true});
         assert.strictEqual(undefined, schema.virtuals.id);
         done();
       });
     });
 
-    describe('getter', function() {
-      it('scope', function(done) {
+    describe('getter', function () {
+      it('scope', function (done) {
         var Tobi = new Schema;
 
-        Tobi.virtual('name').get(function(v, self) {
+        Tobi.virtual('name').get(function (v, self) {
           assert.equal('b', this.a);
           assert.equal('name', self.path);
           return v.toLowerCase();
         });
 
-        assert.equal('yep', Tobi.virtualpath('name').applyGetters('YEP', { a: 'b' }));
+        assert.equal('yep', Tobi.virtualpath('name').applyGetters('YEP', {a: 'b'}));
         done();
       });
     });
 
-    describe('setter', function() {
-      it('scope', function(done) {
+    describe('setter', function () {
+      it('scope', function (done) {
         var Tobi = new Schema;
 
-        Tobi.virtual('name').set(function(v, self) {
+        Tobi.virtual('name').set(function (v, self) {
           assert.equal('b', this.a);
           assert.equal('name', self.path);
           return v.toLowerCase();
         });
 
-        assert.equal('yep', Tobi.virtualpath('name').applySetters('YEP', { a: 'b' }));
+        assert.equal('yep', Tobi.virtualpath('name').applySetters('YEP', {a: 'b'}));
         done();
       });
     });
   });
 
-  describe('other contexts', function() {
-    it('work', function(done) {
+  describe('other contexts', function () {
+    it('work', function (done) {
       var str = 'code = {' +
-        '  name: String' +
-        ', arr1: Array ' +
-        ', arr2: { type: [] }' +
-        ', date: Date  ' +
-        ', num: { type: Number }' +
-        ', bool: Boolean' +
-        ', nest: { sub: { type: {}, required: true }}' +
-        '}';
+          '  name: String' +
+          ', arr1: Array ' +
+          ', arr2: { type: [] }' +
+          ', date: Date  ' +
+          ', num: { type: Number }' +
+          ', bool: Boolean' +
+          ', nest: { sub: { type: {}, required: true }}' +
+          '}';
 
       var script = vm.createScript(str, 'testSchema.vm');
-      var sandbox = { code: null };
+      var sandbox = {code: null};
       script.runInNewContext(sandbox);
 
       var Ferret = new Schema(sandbox.code);
@@ -1113,36 +1129,36 @@ describe('schema', function() {
     });
   });
 
-  describe('#add()', function() {
-    it('does not polute existing paths', function(done) {
-      var o = { name: String };
+  describe('#add()', function () {
+    it('does not polute existing paths', function (done) {
+      var o = {name: String};
       var s = new Schema(o);
 
-      assert.throws(function() {
-        s.add({ age: Number }, 'name.');
+      assert.throws(function () {
+        s.add({age: Number}, 'name.');
       }, /Cannot set nested path/);
 
-      assert.throws(function() {
-        s.add({ age: { x: Number }}, 'name.');
+      assert.throws(function () {
+        s.add({age: {x: Number}}, 'name.');
       }, /Cannot set nested path/);
       assert.equal(false, ('age' in o.name));
 
-      o = { name: 'string' };
+      o = {name: 'string'};
       s = new Schema(o);
 
-      assert.throws(function() {
-        s.add({ age: Number }, 'name.');
+      assert.throws(function () {
+        s.add({age: Number}, 'name.');
       }, /Cannot set nested path/);
 
-      assert.throws(function() {
-        s.add({ age: { x: Number }}, 'name.');
+      assert.throws(function () {
+        s.add({age: {x: Number}}, 'name.');
       }, /Cannot set nested path/);
 
       assert.equal('string', o.name);
       done();
     });
 
-    it('merging nested objects (gh-662)', function(done) {
+    it('merging nested objects (gh-662)', function (done) {
       var db = start();
 
       var MergedSchema = new Schema({
@@ -1172,29 +1188,29 @@ describe('schema', function() {
         }
       });
 
-      merged.save(function(err) {
+      merged.save(function (err) {
         assert.ifError(err);
-        Merged.findById(merged.id, function(err, found) {
+        Merged.findById(merged.id, function (err, found) {
           db.close();
           assert.ifError(err);
-          assert.equal(found.a.foo,'baz');
-          assert.equal(found.a.b.bar,'qux');
+          assert.equal(found.a.foo, 'baz');
+          assert.equal(found.a.b.bar, 'qux');
           done();
         });
       });
     });
   });
 
-  it('debugging msgs', function(done) {
+  it('debugging msgs', function (done) {
     var err;
     try {
-      new Schema({ name: { first: null } });
+      new Schema({name: {first: null}});
     } catch (e) {
       err = e;
     }
-    assert.equal(err.message,'Invalid value for schema path `name.first`');
+    assert.equal(err.message, 'Invalid value for schema path `name.first`');
     try {
-      new Schema({ age: undefined });
+      new Schema({age: undefined});
     } catch (e) {
       err = e;
     }
@@ -1202,78 +1218,78 @@ describe('schema', function() {
     done();
   });
 
-  describe('construction', function() {
-    it('array of object literal missing a type is interpreted as DocumentArray', function(done) {
+  describe('construction', function () {
+    it('array of object literal missing a type is interpreted as DocumentArray', function (done) {
       var goose = new mongoose.Mongoose;
       var s = new Schema({
         arr: [
-            { something: { type: String } }
+          {something: {type: String}}
         ]
       });
       assert.ok(s.path('arr') instanceof SchemaTypes.DocumentArray);
       var M = goose.model('objectliteralschema', s);
-      var m = new M({ arr: [ { something: 'wicked this way comes' }] });
+      var m = new M({arr: [{something: 'wicked this way comes'}]});
       assert.equal('wicked this way comes', m.arr[0].something);
       assert.ok(m.arr[0]._id);
       done();
     });
 
-    it('array of object literal with type.type is interpreted as DocumentArray', function(done) {
+    it('array of object literal with type.type is interpreted as DocumentArray', function (done) {
       var goose = new mongoose.Mongoose;
       var s = new Schema({
         arr: [
-            { type: { type: String } }
+          {type: {type: String}}
         ]
       });
       assert.ok(s.path('arr') instanceof SchemaTypes.DocumentArray);
       var M = goose.model('objectliteralschema2', s);
-      var m = new M({ arr: [ { type: 'works' }] });
+      var m = new M({arr: [{type: 'works'}]});
       assert.equal('works', m.arr[0].type);
       assert.ok(m.arr[0]._id);
       done();
     });
 
-    it('does not alter original argument (gh-1364)', function(done) {
+    it('does not alter original argument (gh-1364)', function (done) {
       var schema = {
-        ids: [{ type: Schema.ObjectId, ref: 'something' }],
-        a: { type: Array },
+        ids: [{type: Schema.ObjectId, ref: 'something'}],
+        a: {type: Array},
         b: Array,
         c: [Date],
-        d: { type: 'Boolean' },
-        e: [{ a: String, b: [{ type: { type: Buffer }, x: Number }] }]
+        d: {type: 'Boolean'},
+        e: [{a: String, b: [{type: {type: Buffer}, x: Number}]}]
       };
 
       new Schema(schema);
       assert.equal(6, Object.keys(schema).length);
-      assert.deepEqual([{ type: Schema.ObjectId, ref: 'something' }], schema.ids);
-      assert.deepEqual({ type: Array }, schema.a);
+      assert.deepEqual([{type: Schema.ObjectId, ref: 'something'}], schema.ids);
+      assert.deepEqual({type: Array}, schema.a);
       assert.deepEqual(Array, schema.b);
       assert.deepEqual([Date], schema.c);
-      assert.deepEqual({ type: 'Boolean' }, schema.d);
-      assert.deepEqual([{ a: String, b: [{ type: { type: Buffer }, x: Number }] }], schema.e);
+      assert.deepEqual({type: 'Boolean'}, schema.d);
+      assert.deepEqual([{a: String, b: [{type: {type: Buffer}, x: Number}]}], schema.e);
 
       done();
     });
 
-    it('properly gets value of plain objects when dealing with refs (gh-1606)', function(done) {
+    it('properly gets value of plain objects when dealing with refs (gh-1606)', function (done) {
       var db = start();
-      var el = new Schema({ title: String });
+      var el = new Schema({title: String});
       var so = new Schema({
         title: String,
-        obj: { type: Schema.Types.ObjectId, ref: 'Element' }
+        obj: {type: Schema.Types.ObjectId, ref: 'Element'}
       });
 
       var Element = db.model('Element', el);
       var Some = db.model('Some', so);
 
-      var ele = new Element({ title: 'thing' });
+      var ele = new Element({title: 'thing'});
 
-      ele.save(function(err) {
+      ele.save(function (err) {
         assert.ifError(err);
-        var s = new Some({ obj: ele.toObject() });
-        s.save(function(err) {
+        var s = new Some({obj: ele.toObject()});
+        s.save(function (err) {
           assert.ifError(err);
-          Some.findOne({ _id: s.id }, function(err, ss) {
+          Some.findOne({_id: s.id}, function (err, ss) {
             assert.ifError(err);
             assert.equal(ss.obj, ele.id);
             db.close(done);
@@ -1283,54 +1299,54 @@ describe('schema', function() {
     });
   });
 
-  describe('property names', function() {
-    it('that conflict throw', function(done) {
-      var child = new Schema({ name: String });
+  describe('property names', function () {
+    it('that conflict throw', function (done) {
+      var child = new Schema({name: String});
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
           on: String,
           child: [child]
         });
       }, /`on` may not be used as a schema pathname/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
           collection: String
         });
       }, /`collection` may not be used as a schema pathname/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
           schema: String
         });
       }, /`schema` may not be used as a schema pathname/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
           db: String
         });
       }, /`db` may not be used as a schema pathname/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
           modelName: String
         });
       }, /`modelName` may not be used as a schema pathname/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
           isNew: String
         });
       }, /`isNew` may not be used as a schema pathname/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
           errors: String
         });
       }, /`errors` may not be used as a schema pathname/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
           init: String
         });
@@ -1339,42 +1355,42 @@ describe('schema', function() {
       done();
     });
 
-    it('that do not conflict do not throw', function(done) {
-      assert.doesNotThrow(function() {
+    it('that do not conflict do not throw', function (done) {
+      assert.doesNotThrow(function () {
         new Schema({
           model: String
         });
       });
 
-      assert.doesNotThrow(function() {
-        Schema({ child: [{parent: String}] });
+      assert.doesNotThrow(function () {
+        Schema({child: [{parent: String}]});
       });
 
-      assert.doesNotThrow(function() {
-        Schema({ child: [{parentArray: String}] });
+      assert.doesNotThrow(function () {
+        Schema({child: [{parentArray: String}]});
       });
 
-      assert.doesNotThrow(function() {
-        var s = Schema({ docs: [{ path: String }] });
+      assert.doesNotThrow(function () {
+        var s = Schema({docs: [{path: String}]});
         var M = mongoose.model('gh-1245', s);
-        new M({ docs: [{ path: 'works' }] });
+        new M({docs: [{path: 'works'}]});
       });
 
-      assert.doesNotThrow(function() {
-        var s = Schema({ setMaxListeners: String });
+      assert.doesNotThrow(function () {
+        var s = Schema({setMaxListeners: String});
         var M = mongoose.model('setMaxListeners-as-property-name', s);
-        new M({ setMaxListeners: 'works' });
+        new M({setMaxListeners: 'works'});
       });
 
       done();
     });
 
-    it('permit _scope to be used (gh-1184)', function(done) {
+    it('permit _scope to be used (gh-1184)', function (done) {
       var db = start();
-      var child = new Schema({ _scope: Schema.ObjectId });
+      var child = new Schema({_scope: Schema.ObjectId});
       var C = db.model('scope', child);
       var c = new C;
-      c.save(function(err) {
+      c.save(function (err) {
         db.close();
         assert.ifError(err);
         try {
@@ -1388,20 +1404,20 @@ describe('schema', function() {
     });
   });
 
-  describe('pathType()', function() {
+  describe('pathType()', function () {
     var schema;
 
-    before(function() {
+    before(function () {
       schema = Schema({
         n: String,
-        nest: { thing: { nests: Boolean }},
-        docs:[{ x: [{ y:String }] }],
+        nest: {thing: {nests: Boolean}},
+        docs: [{x: [{y: String}]}],
         mixed: {}
       });
     });
 
-    describe('when called on an explicit real path', function() {
-      it('returns "real"', function(done) {
+    describe('when called on an explicit real path', function () {
+      it('returns "real"', function (done) {
         assert.equal('real', schema.pathType('n'));
         assert.equal('real', schema.pathType('nest.thing.nests'));
         assert.equal('real', schema.pathType('docs'));
@@ -1411,21 +1427,21 @@ describe('schema', function() {
         done();
       });
     });
-    describe('when called on a virtual', function() {
-      it('returns virtual', function(done) {
+    describe('when called on a virtual', function () {
+      it('returns virtual', function (done) {
         assert.equal('virtual', schema.pathType('id'));
         done();
       });
     });
-    describe('when called on nested structure', function() {
-      it('returns nested', function(done) {
+    describe('when called on nested structure', function () {
+      it('returns nested', function (done) {
         assert.equal('nested', schema.pathType('nest'));
         assert.equal('nested', schema.pathType('nest.thing'));
         done();
       });
     });
-    describe('when called on undefined path', function() {
-      it('returns adHocOrUndefined', function(done) {
+    describe('when called on undefined path', function () {
+      it('returns adHocOrUndefined', function (done) {
         assert.equal('adhocOrUndefined', schema.pathType('mixed.what'));
         assert.equal('adhocOrUndefined', schema.pathType('mixed.4'));
         assert.equal('adhocOrUndefined', schema.pathType('mixed.4.thing'));
@@ -1446,59 +1462,58 @@ describe('schema', function() {
     });
   });
 
-  it('required() with doc arrays (gh-3199)', function(done) {
+  it('required() with doc arrays (gh-3199)', function (done) {
     var schema = Schema({
-      test: [{ x: String }]
+      test: [{x: String}]
     });
 
     schema.path('test').schema.path('x').required(true);
     var M = mongoose.model('gh3199', schema);
-    var m = new M({ test: [{}] });
+    var m = new M({test: [{}]});
 
     assert.equal(m.validateSync().errors['test.0.x'].kind, 'required');
     done();
   });
 
-  it('custom typeKey in doc arrays (gh-3560)', function(done) {
+  it('custom typeKey in doc arrays (gh-3560)', function (done) {
     var schema = Schema({
       test: [{
-        name: { $type: String }
+        name: {$type: String}
       }]
-    }, { typeKey: '$type' });
+    }, {typeKey: '$type'});
 
     schema.path('test').schema.path('name').required(true);
     var M = mongoose.model('gh3560', schema);
-    var m = new M({ test: [{ name: 'Val' }] });
+    var m = new M({test: [{name: 'Val'}]});
 
     assert.ifError(m.validateSync());
     assert.equal(m.test[0].name, 'Val');
     done();
   });
 
-  it('required for single nested schemas (gh-3562)', function(done) {
+  it('required for single nested schemas (gh-3562)', function (done) {
     var personSchema = Schema({
-      name: { type: String, required: true }
+      name: {type: String, required: true}
     });
 
     var bandSchema = Schema({
       name: String,
-      guitarist: { type: personSchema, required: true }
+      guitarist: {type: personSchema, required: true}
     });
 
     var Band = mongoose.model('gh3562', bandSchema);
-    var band = new Band({ name: "Guns N' Roses" });
+    var band = new Band({name: "Guns N' Roses"});
 
     assert.ok(band.validateSync());
     assert.ok(band.validateSync().errors['guitarist']);
-    band.guitarist = { name: 'Slash' };
+    band.guitarist = {name: 'Slash'};
     assert.ifError(band.validateSync());
 
     done();
   });
 
-  describe('remove()', function() {
-
-    before(function() {
+  describe('remove()', function () {
+    before(function () {
       this.schema = Schema({
         a: String,
         b: {
@@ -1512,13 +1527,13 @@ describe('schema', function() {
       });
     });
 
-    it('removes a single path', function(done) {
+    it('removes a single path', function (done) {
       this.schema.remove('a');
       assert.strictEqual(this.schema.path('a'), undefined);
       done();
     });
 
-    it('removes a nested path', function(done) {
+    it('removes a nested path', function (done) {
       this.schema.remove('b.c.d');
       assert.strictEqual(this.schema.path('b'), undefined);
       assert.strictEqual(this.schema.path('b.c'), undefined);
@@ -1526,7 +1541,7 @@ describe('schema', function() {
       done();
     });
 
-    it('removes an array of paths', function(done) {
+    it('removes an array of paths', function (done) {
       this.schema.remove(['e', 'f', 'g']);
       assert.strictEqual(this.schema.path('e'), undefined);
       assert.strictEqual(this.schema.path('f'), undefined);
diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js
index b033de8bf44..eeb5fcd01a4 100644
--- a/test/schema.timestamps.test.js
+++ b/test/schema.timestamps.test.js
@@ -8,9 +8,9 @@ var start = require('./common'),
     assert = require('assert'),
     Schema = mongoose.Schema;
 
-describe('schema options.timestamps', function() {
-  describe('create schema with options.timestamps', function() {
-    it('should have createdAt and updatedAt fields', function(done) {
+describe('schema options.timestamps', function () {
+  describe('create schema with options.timestamps', function () {
+    it('should have createdAt and updatedAt fields', function (done) {
       var TestSchema = new Schema({
         name: String
       }, {
@@ -22,7 +22,7 @@ describe('schema options.timestamps', function() {
       done();
     });
 
-    it('should have created and updatedAt fields', function(done) {
+    it('should have created and updatedAt fields', function (done) {
       var TestSchema = new Schema({
         name: String
       }, {
@@ -36,7 +36,7 @@ describe('schema options.timestamps', function() {
       done();
     });
 
-    it('should have created and updated fields', function(done) {
+    it('should have created and updated fields', function (done) {
       var TestSchema = new Schema({
         name: String
       }, {
@@ -52,7 +52,7 @@ describe('schema options.timestamps', function() {
     });
   });
 
-  describe('auto update createdAt and updatedAt when create/save/update document', function() {
+  describe('auto update createdAt and updatedAt when create/save/update document', function () {
     var CatSchema = new Schema({
       name: String,
       hobby: String
@@ -61,13 +61,13 @@ describe('schema options.timestamps', function() {
     var conn = start();
     var Cat = conn.model('Cat', CatSchema);
 
-    before(function(done) {
+    before(function (done) {
       Cat.remove({}, done);
     });
 
-    it('should have fields when create', function(done) {
+    it('should have fields when create', function (done) {
       var cat = new Cat({name: 'newcat'});
-      cat.save(function(err, doc) {
+      cat.save(function (err, doc) {
         assert.ok(doc.createdAt);
         assert.ok(doc.updatedAt);
         assert.ok(doc.createdAt.getTime() == doc.updatedAt.getTime());
@@ -75,8 +75,8 @@ describe('schema options.timestamps', function() {
       });
     });
 
-    it('should have fields when create with findOneAndUpdate', function(done) {
-      Cat.findOneAndUpdate({name: 'notexistname'}, {$set: {}}, {upsert: true, 'new': true}, function(err, doc) {
+    it('should have fields when create with findOneAndUpdate', function (done) {
+      Cat.findOneAndUpdate({name: 'notexistname'}, {$set: {}}, {upsert: true, 'new': true}, function (err, doc) {
         assert.ok(doc.createdAt);
         assert.ok(doc.updatedAt);
         assert.ok(doc.createdAt.getTime() == doc.updatedAt.getTime());
@@ -84,32 +84,32 @@ describe('schema options.timestamps', function() {
       });
     });
 
-    it('should change updatedAt when save', function(done) {
-      Cat.findOne({name: 'newcat'}, function(err, doc) {
+    it('should change updatedAt when save', function (done) {
+      Cat.findOne({name: 'newcat'}, function (err, doc) {
         var old = doc.updatedAt;
 
-        doc.save(function(err, doc) {
+        doc.save(function (err, doc) {
           assert.ok(doc.updatedAt.getTime() > old.getTime());
           done();
         });
       });
     });
 
-    it('should change updatedAt when findOneAndUpdate', function(done) {
-      Cat.findOne({name: 'newcat'}, function(err, doc) {
+    it('should change updatedAt when findOneAndUpdate', function (done) {
+      Cat.findOne({name: 'newcat'}, function (err, doc) {
         var old = doc.updatedAt;
-        Cat.findOneAndUpdate({name: 'newcat'}, {$set: {hobby: 'fish'}}, {'new': true}, function(err, doc) {
+        Cat.findOneAndUpdate({name: 'newcat'}, {$set: {hobby: 'fish'}}, {'new': true}, function (err, doc) {
           assert.ok(doc.updatedAt.getTime() > old.getTime());
           done();
         });
       });
     });
 
-    it('should have fields when update', function(done) {
-      Cat.findOne({name: 'newcat'}, function(err, doc) {
+    it('should have fields when update', function (done) {
+      Cat.findOne({name: 'newcat'}, function (err, doc) {
         var old = doc.updatedAt;
-        Cat.update({name: 'newcat'}, {$set: {hobby: 'fish'}}, function() {
-          Cat.findOne({name: 'newcat'}, function(err, doc) {
+        Cat.update({name: 'newcat'}, {$set: {hobby: 'fish'}}, function () {
+          Cat.findOne({name: 'newcat'}, function (err, doc) {
             assert.ok(doc.updatedAt.getTime() > old.getTime());
             done();
           });
@@ -117,11 +117,10 @@ describe('schema options.timestamps', function() {
       });
     });
 
-    after(function(done) {
-      Cat.remove({}, function() {
+    after(function (done) {
+      Cat.remove({}, function () {
         conn.close(done);
       });
     });
   });
-
 });
diff --git a/test/schema.type.test.js b/test/schema.type.test.js
index 0514a6e1895..a282c69c4df 100644
--- a/test/schema.type.test.js
+++ b/test/schema.type.test.js
@@ -7,25 +7,25 @@ var mongoose = require('./common').mongoose,
     assert = require('assert'),
     Schema = mongoose.Schema;
 
-describe('schematype', function() {
-  it('honors the selected option', function(done) {
-    var s = new Schema({ thought: { type: String, select: false }});
+describe('schematype', function () {
+  it('honors the selected option', function (done) {
+    var s = new Schema({thought: {type: String, select: false}});
     assert.equal(false, s.path('thought').selected);
 
-    var a = new Schema({ thought: { type: String, select: true }});
+    var a = new Schema({thought: {type: String, select: true}});
     assert.equal(true, a.path('thought').selected);
     done();
   });
 
-  it('properly handles specifying index in combination with unique or sparse', function(done) {
-    var s = new Schema({ name: { type: String, index: true, unique: true }});
-    assert.deepEqual(s.path('name')._index, { unique: true });
-    s = new Schema({ name: { type: String, unique: true, index: true }});
-    assert.deepEqual(s.path('name')._index, { unique: true });
-    s = new Schema({ name: { type: String, index: true, sparse: true }});
-    assert.deepEqual(s.path('name')._index, { sparse: true });
-    s = new Schema({ name: { type: String, sparse: true, index: true }});
-    assert.deepEqual(s.path('name')._index, { sparse: true });
+  it('properly handles specifying index in combination with unique or sparse', function (done) {
+    var s = new Schema({name: {type: String, index: true, unique: true}});
+    assert.deepEqual(s.path('name')._index, {unique: true});
+    s = new Schema({name: {type: String, unique: true, index: true}});
+    assert.deepEqual(s.path('name')._index, {unique: true});
+    s = new Schema({name: {type: String, index: true, sparse: true}});
+    assert.deepEqual(s.path('name')._index, {sparse: true});
+    s = new Schema({name: {type: String, sparse: true, index: true}});
+    assert.deepEqual(s.path('name')._index, {sparse: true});
     done();
   });
 });
diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js
index bb30cdb0a59..b8334605a56 100644
--- a/test/schema.validation.test.js
+++ b/test/schema.validation.test.js
@@ -13,44 +13,44 @@ var start = require('./common'),
     DocumentObjectId = mongoose.Types.ObjectId,
     random = require('../lib/utils').random;
 
-describe('schema', function() {
-  describe('validation', function() {
-    it('invalid arguments are rejected (1044)', function(done) {
-      assert.throws(function() {
+describe('schema', function () {
+  describe('validation', function () {
+    it('invalid arguments are rejected (1044)', function (done) {
+      assert.throws(function () {
         new Schema({
-          simple: { type: String, validate: 'nope' }
+          simple: {type: String, validate: 'nope'}
         });
       }, /Invalid validator/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
-          simple: { type: String, validate: ['nope'] }
+          simple: {type: String, validate: ['nope']}
         });
       }, /Invalid validator/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
-          simple: { type: String, validate: { nope: 1, msg: 'nope' } }
+          simple: {type: String, validate: {nope: 1, msg: 'nope'}}
         });
       }, /Invalid validator/);
 
-      assert.throws(function() {
+      assert.throws(function () {
         new Schema({
-          simple: { type: String, validate: [{ nope: 1, msg: 'nope' }, 'nope'] }
+          simple: {type: String, validate: [{nope: 1, msg: 'nope'}, 'nope']}
         });
       }, /Invalid validator/);
 
       done();
     });
 
-    it('string enum', function(done) {
+    it('string enum', function (done) {
       var Test = new Schema({
-        complex: { type: String, enum: ['a', 'b', undefined, 'c', null] },
-        state: { type: String }
+        complex: {type: String, enum: ['a', 'b', undefined, 'c', null]},
+        state: {type: String}
       });
 
       assert.ok(Test.path('complex') instanceof SchemaTypes.String);
-      assert.deepEqual(Test.path('complex').enumValues,['a', 'b', 'c', null]);
+      assert.deepEqual(Test.path('complex').enumValues, ['a', 'b', 'c', null]);
       assert.equal(Test.path('complex').validators.length, 1);
 
       Test.path('complex').enum('d', 'e');
@@ -66,117 +66,117 @@ describe('schema', function() {
       assert.equal(Test.path('state').validators.length, 1);
       assert.deepEqual(Test.path('state').enumValues, ['opening', 'open', 'closing', 'closed']);
 
-      Test.path('complex').doValidate('x', function(err) {
+      Test.path('complex').doValidate('x', function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       // allow unsetting enums
-      Test.path('complex').doValidate(undefined, function(err) {
+      Test.path('complex').doValidate(undefined, function (err) {
         assert.ifError(err);
       });
 
-      Test.path('complex').doValidate(null, function(err) {
+      Test.path('complex').doValidate(null, function (err) {
         assert.ifError(err);
       });
 
-      Test.path('complex').doValidate('da', function(err) {
+      Test.path('complex').doValidate('da', function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('state').doValidate('x', function(err) {
+      Test.path('state').doValidate('x', function (err) {
         assert.ok(err instanceof ValidatorError);
         assert.equal(err.message,
           'enum validator failed for path `state`: test');
       });
 
-      Test.path('state').doValidate('opening', function(err) {
+      Test.path('state').doValidate('opening', function (err) {
         assert.ifError(err);
       });
 
-      Test.path('state').doValidate('open', function(err) {
+      Test.path('state').doValidate('open', function (err) {
         assert.ifError(err);
       });
 
       done();
     });
 
-    it('string regexp', function(done) {
+    it('string regexp', function (done) {
       var Test = new Schema({
-        simple: { type: String, match: /[a-z]/ }
+        simple: {type: String, match: /[a-z]/}
       });
 
       assert.equal(1, Test.path('simple').validators.length);
 
-      Test.path('simple').doValidate('az', function(err) {
+      Test.path('simple').doValidate('az', function (err) {
         assert.ifError(err);
       });
 
       Test.path('simple').match(/[0-9]/);
       assert.equal(2, Test.path('simple').validators.length);
 
-      Test.path('simple').doValidate('12', function(err) {
+      Test.path('simple').doValidate('12', function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('simple').doValidate('a12', function(err) {
+      Test.path('simple').doValidate('a12', function (err) {
         assert.ifError(err);
       });
 
-      Test.path('simple').doValidate('', function(err) {
+      Test.path('simple').doValidate('', function (err) {
         assert.ifError(err);
       });
-      Test.path('simple').doValidate(null, function(err) {
+      Test.path('simple').doValidate(null, function (err) {
         assert.ifError(err);
       });
-      Test.path('simple').doValidate(undefined, function(err) {
+      Test.path('simple').doValidate(undefined, function (err) {
         assert.ifError(err);
       });
       Test.path('simple').validators = [];
       Test.path('simple').match(/[1-9]/);
-      Test.path('simple').doValidate(0, function(err) {
+      Test.path('simple').doValidate(0, function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       Test.path('simple').match(null);
-      Test.path('simple').doValidate(0, function(err) {
+      Test.path('simple').doValidate(0, function (err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       done();
     });
 
-    describe('non-required fields', function() {
-      describe('are validated correctly', function() {
+    describe('non-required fields', function () {
+      describe('are validated correctly', function () {
         var db, Person;
 
-        before(function() {
+        before(function () {
           db = start();
           var PersonSchema = new Schema({
-            name: { type: String },
+            name: {type: String},
             num_cars: {type: Number, min: 20}
           });
           Person = db.model('person-schema-validation-test', PersonSchema);
         });
 
-        after(function(done) {
+        after(function (done) {
           db.close(done);
         });
 
-        it('and can be set to "undefined" (gh-1594)', function(done) {
+        it('and can be set to "undefined" (gh-1594)', function (done) {
           var p = new Person({name: 'Daniel'});
           p.num_cars = 25;
 
-          p.save(function(err) {
+          p.save(function (err) {
             assert.ifError(err);
             assert.equal(p.num_cars, 25);
             p.num_cars = undefined;
 
-            p.save(function(err) {
+            p.save(function (err) {
               assert.ifError(err);
               assert.equal(p.num_cars, undefined);
               p.num_cars = 5;
 
-              p.save(function(err) {
+              p.save(function (err) {
                 // validation should still work for non-undefined values
                 assert.ok(err);
                 done();
@@ -186,32 +186,32 @@ describe('schema', function() {
         });
       });
 
-      it('number min and max', function(done) {
+      it('number min and max', function (done) {
         var Tobi = new Schema({
-          friends: { type: Number, max: 15, min: 5 }
+          friends: {type: Number, max: 15, min: 5}
         });
 
         assert.equal(Tobi.path('friends').validators.length, 2);
 
-        Tobi.path('friends').doValidate(10, function(err) {
+        Tobi.path('friends').doValidate(10, function (err) {
           assert.ifError(err);
         });
 
-        Tobi.path('friends').doValidate(100, function(err) {
+        Tobi.path('friends').doValidate(100, function (err) {
           assert.ok(err instanceof ValidatorError);
           assert.equal('friends', err.path);
           assert.equal('max', err.kind);
           assert.equal(100, err.value);
         });
 
-        Tobi.path('friends').doValidate(1, function(err) {
+        Tobi.path('friends').doValidate(1, function (err) {
           assert.ok(err instanceof ValidatorError);
           assert.equal('friends', err.path);
           assert.equal('min', err.kind);
         });
 
         // null is allowed
-        Tobi.path('friends').doValidate(null, function(err) {
+        Tobi.path('friends').doValidate(null, function (err) {
           assert.ifError(err);
         });
 
@@ -223,8 +223,8 @@ describe('schema', function() {
       });
     });
 
-    describe('required', function() {
-      it('string required', function(done) {
+    describe('required', function () {
+      it('string required', function (done) {
         var Test = new Schema({
           simple: String
         });
@@ -232,219 +232,219 @@ describe('schema', function() {
         Test.path('simple').required(true);
         assert.equal(Test.path('simple').validators.length, 1);
 
-        Test.path('simple').doValidate(null, function(err) {
+        Test.path('simple').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate(undefined, function(err) {
+        Test.path('simple').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('', function(err) {
+        Test.path('simple').doValidate('', function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('woot', function(err) {
+        Test.path('simple').doValidate('woot', function (err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('string conditional required', function(done) {
+      it('string conditional required', function (done) {
         var Test = new Schema({
           simple: String
         });
 
         var required = true,
-            isRequired = function() {
+            isRequired = function () {
               return required;
             };
 
         Test.path('simple').required(isRequired);
         assert.equal(Test.path('simple').validators.length, 1);
 
-        Test.path('simple').doValidate(null, function(err) {
+        Test.path('simple').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate(undefined, function(err) {
+        Test.path('simple').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('', function(err) {
+        Test.path('simple').doValidate('', function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('woot', function(err) {
+        Test.path('simple').doValidate('woot', function (err) {
           assert.ifError(err);
         });
 
         required = false;
 
-        Test.path('simple').doValidate(null, function(err) {
+        Test.path('simple').doValidate(null, function (err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate(undefined, function(err) {
+        Test.path('simple').doValidate(undefined, function (err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate('', function(err) {
+        Test.path('simple').doValidate('', function (err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate('woot', function(err) {
+        Test.path('simple').doValidate('woot', function (err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('number required', function(done) {
+      it('number required', function (done) {
         var Edwald = new Schema({
-          friends: { type: Number, required: true }
+          friends: {type: Number, required: true}
         });
 
-        Edwald.path('friends').doValidate(null, function(err) {
+        Edwald.path('friends').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Edwald.path('friends').doValidate(undefined, function(err) {
+        Edwald.path('friends').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Edwald.path('friends').doValidate(0, function(err) {
+        Edwald.path('friends').doValidate(0, function (err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('date required', function(done) {
+      it('date required', function (done) {
         var Loki = new Schema({
-          birth_date: { type: Date, required: true }
+          birth_date: {type: Date, required: true}
         });
 
-        Loki.path('birth_date').doValidate(null, function(err) {
+        Loki.path('birth_date').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('birth_date').doValidate(undefined, function(err) {
+        Loki.path('birth_date').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('birth_date').doValidate(new Date(), function(err) {
+        Loki.path('birth_date').doValidate(new Date(), function (err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('date not empty string (gh-3132)', function(done) {
+      it('date not empty string (gh-3132)', function (done) {
         var HappyBirthday = new Schema({
-          date: { type: Date, required: true }
+          date: {type: Date, required: true}
         });
 
-        HappyBirthday.path('date').doValidate('', function(err) {
+        HappyBirthday.path('date').doValidate('', function (err) {
           assert.ok(err instanceof ValidatorError);
           done();
         });
       });
 
-      it('objectid required', function(done) {
+      it('objectid required', function (done) {
         var Loki = new Schema({
-          owner: { type: ObjectId, required: true }
+          owner: {type: ObjectId, required: true}
         });
 
-        Loki.path('owner').doValidate(new DocumentObjectId(), function(err) {
+        Loki.path('owner').doValidate(new DocumentObjectId(), function (err) {
           assert.ifError(err);
         });
 
-        Loki.path('owner').doValidate(null, function(err) {
+        Loki.path('owner').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('owner').doValidate(undefined, function(err) {
+        Loki.path('owner').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
         done();
       });
 
-      it('array required', function(done) {
+      it('array required', function (done) {
         var Loki = new Schema({
-          likes: { type: Array, required: true }
+          likes: {type: Array, required: true}
         });
 
-        Loki.path('likes').doValidate(null, function(err) {
+        Loki.path('likes').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('likes').doValidate(undefined, function(err) {
+        Loki.path('likes').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('likes').doValidate([], function(err) {
+        Loki.path('likes').doValidate([], function (err) {
           assert.ok(err instanceof ValidatorError);
         });
         done();
       });
 
-      it('boolean required', function(done) {
+      it('boolean required', function (done) {
         var Animal = new Schema({
-          isFerret: { type: Boolean, required: true }
+          isFerret: {type: Boolean, required: true}
         });
 
-        Animal.path('isFerret').doValidate(null, function(err) {
+        Animal.path('isFerret').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('isFerret').doValidate(undefined, function(err) {
+        Animal.path('isFerret').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('isFerret').doValidate(true, function(err) {
+        Animal.path('isFerret').doValidate(true, function (err) {
           assert.ifError(err);
         });
 
-        Animal.path('isFerret').doValidate(false, function(err) {
+        Animal.path('isFerret').doValidate(false, function (err) {
           assert.ifError(err);
         });
         done();
       });
 
-      it('mixed required', function(done) {
+      it('mixed required', function (done) {
         var Animal = new Schema({
-          characteristics: { type: Mixed, required: true }
+          characteristics: {type: Mixed, required: true}
         });
 
-        Animal.path('characteristics').doValidate(null, function(err) {
+        Animal.path('characteristics').doValidate(null, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('characteristics').doValidate(undefined, function(err) {
+        Animal.path('characteristics').doValidate(undefined, function (err) {
           assert.ok(err instanceof ValidatorError);
         });
 
         Animal.path('characteristics').doValidate({
           aggresive: true
-        }, function(err) {
+        }, function (err) {
           assert.ifError(err);
         });
 
-        Animal.path('characteristics').doValidate('none available', function(err) {
+        Animal.path('characteristics').doValidate('none available', function (err) {
           assert.ifError(err);
         });
         done();
       });
     });
 
-    describe('async', function() {
-      it('works', function(done) {
+    describe('async', function () {
+      it('works', function (done) {
         var executed = 0;
 
         function validator(value, fn) {
-          setTimeout(function() {
+          setTimeout(function () {
             executed++;
             fn(value === true);
             if (2 === executed) done();
@@ -452,23 +452,23 @@ describe('schema', function() {
         }
 
         var Animal = new Schema({
-          ferret: { type: Boolean, validate: validator }
+          ferret: {type: Boolean, validate: validator}
         });
 
-        Animal.path('ferret').doValidate(true, function(err) {
+        Animal.path('ferret').doValidate(true, function (err) {
           assert.ifError(err);
         });
 
-        Animal.path('ferret').doValidate(false, function(err) {
+        Animal.path('ferret').doValidate(false, function (err) {
           assert.ok(err instanceof Error);
         });
       });
 
-      it('multiple', function(done) {
+      it('multiple', function (done) {
         var executed = 0;
 
         function validator(value, fn) {
-          setTimeout(function() {
+          setTimeout(function () {
             executed++;
             fn(value === true);
             if (2 === executed) done();
@@ -491,17 +491,17 @@ describe('schema', function() {
           }
         });
 
-        Animal.path('ferret').doValidate(true, function(err) {
+        Animal.path('ferret').doValidate(true, function (err) {
           assert.ifError(err);
         });
       });
 
-      it('multiple sequence', function(done) {
+      it('multiple sequence', function (done) {
         var validator1Executed = false,
             validator2Executed = false;
 
         function validator1(value, fn) {
-          setTimeout(function() {
+          setTimeout(function () {
             validator1Executed = true;
             assert.ok(!validator2Executed);
             fn(value === true);
@@ -509,7 +509,7 @@ describe('schema', function() {
         }
 
         function validator2(value, fn) {
-          setTimeout(function() {
+          setTimeout(function () {
             validator2Executed = true;
             assert.ok(validator1Executed);
             fn(value === true);
@@ -533,54 +533,54 @@ describe('schema', function() {
           }
         });
 
-        Animal.path('ferret').doValidate(true, function(err) {
+        Animal.path('ferret').doValidate(true, function (err) {
           assert.ifError(err);
         });
       });
 
-      it('scope', function(done) {
+      it('scope', function (done) {
         var called = false;
         function validator(value, fn) {
           assert.equal('b', this.a);
 
-          setTimeout(function() {
+          setTimeout(function () {
             called = true;
             fn(true);
           }, 5);
         }
 
         var Animal = new Schema({
-          ferret: { type: Boolean, validate: validator }
+          ferret: {type: Boolean, validate: validator}
         });
 
-        Animal.path('ferret').doValidate(true, function(err) {
+        Animal.path('ferret').doValidate(true, function (err) {
           assert.ifError(err);
           assert.equal(true, called);
           done();
-        }, { a: 'b' });
+        }, {a: 'b'});
       });
     });
 
-    describe('messages', function() {
-      describe('are customizable', function() {
-        it('within schema definitions', function(done) {
+    describe('messages', function () {
+      describe('are customizable', function () {
+        it('within schema definitions', function (done) {
           var schema = new Schema({
-            name: { type: String, enum: ['one', 'two'] },
-            myenum: { type: String, enum: { values: ['x'], message: 'enum validator failed for path: {PATH} with {VALUE}' }},
-            requiredString1: { type: String, required: true },
-            requiredString2: { type: String, required: 'oops, {PATH} is missing. {TYPE}' },
-            matchString0: { type: String, match: /bryancranston/ },
-            matchString1: { type: String, match: [/bryancranston/, 'invalid string for {PATH} with value: {VALUE}'] },
-            numMin0: { type: Number, min: 10 },
-            numMin1: { type: Number, min: [10, 'hey, {PATH} is too small']},
-            numMax0: { type: Number, max: 20 },
-            numMax1: { type: Number, max: [20, 'hey, {PATH} ({VALUE}) is greater than {MAX}'] }
+            name: {type: String, enum: ['one', 'two']},
+            myenum: {type: String, enum: {values: ['x'], message: 'enum validator failed for path: {PATH} with {VALUE}'}},
+            requiredString1: {type: String, required: true},
+            requiredString2: {type: String, required: 'oops, {PATH} is missing. {TYPE}'},
+            matchString0: {type: String, match: /bryancranston/},
+            matchString1: {type: String, match: [/bryancranston/, 'invalid string for {PATH} with value: {VALUE}']},
+            numMin0: {type: Number, min: 10},
+            numMin1: {type: Number, min: [10, 'hey, {PATH} is too small']},
+            numMax0: {type: Number, max: 20},
+            numMax1: {type: Number, max: [20, 'hey, {PATH} ({VALUE}) is greater than {MAX}']}
           });
 
           var A = mongoose.model('schema-validation-messages-' + random(), schema);
 
           var a = new A;
-          a.validate(function(err) {
+          a.validate(function (err) {
             assert.equal('Path `requiredString1` is required.', err.errors.requiredString1);
             assert.equal('oops, requiredString2 is missing. required', err.errors.requiredString2);
 
@@ -591,7 +591,7 @@ describe('schema', function() {
             a.numMin0 = a.numMin1 = 2;
             a.numMax0 = a.numMax1 = 30;
 
-            a.validate(function(err) {
+            a.validate(function (err) {
               assert.equal('`three` is not a valid enum value for path `name`.', err.errors.name);
               assert.equal('enum validator failed for path: myenum with y', err.errors.myenum);
               assert.equal('Path `matchString0` is invalid (no match).', err.errors.matchString0);
@@ -611,30 +611,30 @@ describe('schema', function() {
           });
         });
 
-        it('for custom validators', function(done) {
-          var validate = function() {
+        it('for custom validators', function (done) {
+          var validate = function () {
             return false;
           };
           var validator = [validate, '{PATH} failed validation ({VALUE})'];
 
-          var schema = new Schema({ x: { type: [], validate: validator }});
+          var schema = new Schema({x: {type: [], validate: validator}});
           var M = mongoose.model('custom-validator-' + random(), schema);
 
-          var m = new M({ x: [3,4,5,6] });
+          var m = new M({x: [3, 4, 5, 6]});
 
-          m.validate(function(err) {
+          m.validate(function (err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('user defined', err.errors.x.kind);
             done();
           });
         });
 
-        it('supports custom properties (gh-2132)', function(done) {
+        it('supports custom properties (gh-2132)', function (done) {
           var schema = new Schema({
             x: {
               type: String,
               validate: [{
-                validator: function() { return false; },
+                validator: function () { return false; },
                 msg: 'Error code {ERRORCODE}',
                 errorCode: 25
               }]
@@ -642,28 +642,28 @@ describe('schema', function() {
           });
           var M = mongoose.model('gh-2132', schema, 'gh-2132');
 
-          var m = new M({ x: 'a' });
-          m.validate(function(err) {
+          var m = new M({x: 'a'});
+          m.validate(function (err) {
             assert.equal('Error code 25', err.errors.x.toString());
             assert.equal(25, err.errors.x.properties.errorCode);
             done();
           });
         });
 
-        it('supports dynamic message for validators with callback (gh-1936)', function(done) {
+        it('supports dynamic message for validators with callback (gh-1936)', function (done) {
           var schema = new Schema({
             x: {
               type: String,
               validate: [{
-                validator: function(value, fn) { fn(false, 'Custom message'); },
+                validator: function (value, fn) { fn(false, 'Custom message'); },
                 msg: 'Does not matter'
               }]
             }
           });
           var M = mongoose.model('gh-1936', schema, 'gh-1936');
 
-          var m = new M({ x: 'whatever' });
-          m.validate(function(err) {
+          var m = new M({x: 'whatever'});
+          m.validate(function (err) {
             assert.equal('Custom message', err.errors.x.toString());
             done();
           });
@@ -671,39 +671,39 @@ describe('schema', function() {
       });
     });
 
-    describe('types', function() {
-      describe('are customizable', function() {
-        it('for single custom validators', function(done) {
+    describe('types', function () {
+      describe('are customizable', function () {
+        it('for single custom validators', function (done) {
           function validate() {
             return false;
           }
           var validator = [validate, '{PATH} failed validation ({VALUE})', 'customType'];
 
-          var schema = new Schema({ x: { type: [], validate: validator }});
+          var schema = new Schema({x: {type: [], validate: validator}});
           var M = mongoose.model('custom-validator-' + random(), schema);
 
-          var m = new M({ x: [3,4,5,6] });
+          var m = new M({x: [3, 4, 5, 6]});
 
-          m.validate(function(err) {
+          m.validate(function (err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('customType', err.errors.x.kind);
             done();
           });
         });
 
-        it('for many custom validators', function(done) {
+        it('for many custom validators', function (done) {
           function validate() {
             return false;
           }
           var validator = [
-              { validator: validate, msg: '{PATH} failed validation ({VALUE})', type: 'customType'}
+              {validator: validate, msg: '{PATH} failed validation ({VALUE})', type: 'customType'}
           ];
-          var schema = new Schema({ x: { type: [], validate: validator }});
+          var schema = new Schema({x: {type: [], validate: validator}});
           var M = mongoose.model('custom-validator-' + random(), schema);
 
-          var m = new M({ x: [3,4,5,6] });
+          var m = new M({x: [3, 4, 5, 6]});
 
-          m.validate(function(err) {
+          m.validate(function (err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('customType', err.errors.x.kind);
             done();
@@ -712,17 +712,17 @@ describe('schema', function() {
       });
     });
 
-    it('should clear validator errors (gh-2302)', function(done) {
-      var userSchema = new Schema({ name: { type: String, required: true } });
+    it('should clear validator errors (gh-2302)', function (done) {
+      var userSchema = new Schema({name: {type: String, required: true}});
       var User = mongoose.model('gh-2302', userSchema, 'gh-2302');
 
       var user = new User();
-      user.validate(function(err) {
+      user.validate(function (err) {
         assert.ok(err);
         assert.ok(user.errors);
         assert.ok(user.errors['name']);
         user.name = 'bacon';
-        user.validate(function(err) {
+        user.validate(function (err) {
           assert.ok(!err);
           assert.ok(!user.$__.validationError);
           done();
@@ -730,19 +730,19 @@ describe('schema', function() {
       });
     });
 
-    it('should allow an array of enums (gh-661)', function(done) {
+    it('should allow an array of enums (gh-661)', function (done) {
       var validBreakfastFoods = ['bacon', 'eggs', 'steak', 'coffee', 'butter'];
       var breakfastSchema = new Schema({
-        foods: [{ type: String, enum: validBreakfastFoods }]
+        foods: [{type: String, enum: validBreakfastFoods}]
       });
       var Breakfast = mongoose.model('gh-661', breakfastSchema, 'gh-661');
 
-      var goodBreakfast = new Breakfast({ foods: ['eggs', 'bacon'] });
-      goodBreakfast.validate(function(error) {
+      var goodBreakfast = new Breakfast({foods: ['eggs', 'bacon']});
+      goodBreakfast.validate(function (error) {
         assert.ifError(error);
 
-        var badBreakfast = new Breakfast({ foods: ['tofu', 'waffles', 'coffee'] });
-        badBreakfast.validate(function(error) {
+        var badBreakfast = new Breakfast({foods: ['tofu', 'waffles', 'coffee']});
+        badBreakfast.validate(function (error) {
           assert.ok(error);
           assert.ok(error.errors['foods.0']);
           assert.equal(error.errors['foods.0'].message,
@@ -757,10 +757,10 @@ describe('schema', function() {
       });
     });
 
-    it('should allow an array of subdocuments with enums (gh-3521)', function(done) {
+    it('should allow an array of subdocuments with enums (gh-3521)', function (done) {
       var coolSchema = new Schema({
         votes: [{
-          vote: { type: String, enum: ['cool', 'not-cool'] }
+          vote: {type: String, enum: ['cool', 'not-cool']}
         }]
       });
       var Cool = mongoose.model('gh-3521', coolSchema, 'gh-3521');
@@ -769,7 +769,7 @@ describe('schema', function() {
       cool.votes.push(cool.votes.create({
         vote: 'cool'
       }));
-      cool.validate(function(error) {
+      cool.validate(function (error) {
         assert.ifError(error);
 
         var terrible = new Cool();
@@ -777,7 +777,7 @@ describe('schema', function() {
           vote: 'terrible'
         }));
 
-        terrible.validate(function(error) {
+        terrible.validate(function (error) {
           assert.ok(error);
           assert.ok(error.errors['votes.0.vote']);
           assert.equal(error.errors['votes.0.vote'].message,
@@ -788,11 +788,11 @@ describe('schema', function() {
       });
     });
 
-    it('doesnt do double validation on document arrays (gh-2618)', function(done) {
+    it('doesnt do double validation on document arrays (gh-2618)', function (done) {
       var A = new Schema({str: String});
       var B = new Schema({a: [A]});
       var validateCalls = 0;
-      B.path('a').validate(function(val, next) {
+      B.path('a').validate(function (val, next) {
         ++validateCalls;
         next();
       });
@@ -800,62 +800,62 @@ describe('schema', function() {
       B = mongoose.model('b', B);
 
       var p = new B();
-      p.a.push({ str: 'asdf' });
-      p.validate(function(err) {
+      p.a.push({str: 'asdf'});
+      p.validate(function (err) {
         assert.ifError(err);
         assert.equal(1, validateCalls);
         done();
       });
     });
 
-    it('returns cast errors', function(done) {
+    it('returns cast errors', function (done) {
       var breakfastSchema = new Schema({
         eggs: Number
       });
       var Breakfast = mongoose.model('gh-2611', breakfastSchema, 'gh-2611');
 
-      var bad = new Breakfast({ eggs: 'none' });
-      bad.validate(function(error) {
+      var bad = new Breakfast({eggs: 'none'});
+      bad.validate(function (error) {
         assert.ok(error);
         done();
       });
     });
 
-    it('handles multiple subdocument errors (gh-2589)', function(done) {
-      var foodSchema = new Schema({ name: { type: String, required: true, enum: ['bacon', 'eggs'] } });
-      var breakfast = new Schema({ foods: [foodSchema], id: Number });
+    it('handles multiple subdocument errors (gh-2589)', function (done) {
+      var foodSchema = new Schema({name: {type: String, required: true, enum: ['bacon', 'eggs']}});
+      var breakfast = new Schema({foods: [foodSchema], id: Number});
 
       var Breakfast = mongoose.model('gh-2589', breakfast, 'gh-2589');
-      var bad = new Breakfast({ foods: [{ name: 'tofu' }, { name: 'waffles' }], id: 'Not a number' });
-      bad.validate(function(error) {
+      var bad = new Breakfast({foods: [{name: 'tofu'}, {name: 'waffles'}], id: 'Not a number'});
+      bad.validate(function (error) {
         assert.ok(error);
         assert.deepEqual(['id', 'foods.0.name', 'foods.1.name'], Object.keys(error.errors));
         done();
       });
     });
 
-    it('handles subdocument cast errors (gh-2819)', function(done) {
-      var foodSchema = new Schema({ eggs: { type: Number, required: true } });
-      var breakfast = new Schema({ foods: [foodSchema], id: Number });
+    it('handles subdocument cast errors (gh-2819)', function (done) {
+      var foodSchema = new Schema({eggs: {type: Number, required: true}});
+      var breakfast = new Schema({foods: [foodSchema], id: Number});
 
       var Breakfast = mongoose.model('gh-2819', breakfast, 'gh-2819');
 
       // Initially creating subdocs with cast errors
-      var bad = new Breakfast({ foods: [{ eggs: 'Not a number' }], id: 'Not a number' });
-      bad.validate(function(error) {
+      var bad = new Breakfast({foods: [{eggs: 'Not a number'}], id: 'Not a number'});
+      bad.validate(function (error) {
         assert.ok(error);
         assert.deepEqual(['id', 'foods.0.eggs'], Object.keys(error.errors));
         assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError);
 
         // Pushing docs with cast errors
-        bad.foods.push({ eggs: 'Also not a number' });
-        bad.validate(function(error) {
+        bad.foods.push({eggs: 'Also not a number'});
+        bad.validate(function (error) {
           assert.deepEqual(['id', 'foods.0.eggs', 'foods.1.eggs'], Object.keys(error.errors));
           assert.ok(error.errors['foods.1.eggs'] instanceof mongoose.Error.CastError);
 
           // Splicing docs with cast errors
-          bad.foods.splice(1, 1, { eggs: 'fail1' }, { eggs: 'fail2' });
-          bad.validate(function(error) {
+          bad.foods.splice(1, 1, {eggs: 'fail1'}, {eggs: 'fail2'});
+          bad.validate(function (error) {
             assert.deepEqual(['id', 'foods.0.eggs', 'foods.1.eggs', 'foods.2.eggs'], Object.keys(error.errors));
             assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError);
             assert.ok(error.errors['foods.1.eggs'] instanceof mongoose.Error.CastError);
@@ -863,14 +863,14 @@ describe('schema', function() {
 
             // Remove the cast error by setting field
             bad.foods[2].eggs = 3;
-            bad.validate(function(error) {
+            bad.validate(function (error) {
               assert.deepEqual(['id', 'foods.0.eggs', 'foods.1.eggs'], Object.keys(error.errors));
               assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError);
               assert.ok(error.errors['foods.1.eggs'] instanceof mongoose.Error.CastError);
 
               // Remove the cast error using array.set()
-              bad.foods.set(1, { eggs: 1 });
-              bad.validate(function(error) {
+              bad.foods.set(1, {eggs: 1});
+              bad.validate(function (error) {
                 assert.deepEqual(['id', 'foods.0.eggs'], Object.keys(error.errors));
                 assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError);
 
@@ -882,13 +882,13 @@ describe('schema', function() {
       });
     });
 
-    it('fails when you try to set a nested path to a primitive (gh-2592)', function(done) {
-      var breakfast = new Schema({ foods: { bacon: Number, eggs: Number } });
+    it('fails when you try to set a nested path to a primitive (gh-2592)', function (done) {
+      var breakfast = new Schema({foods: {bacon: Number, eggs: Number}});
 
       var Breakfast = mongoose.model('gh-2592', breakfast, 'gh-2592');
       var bad = new Breakfast();
       bad.foods = 'waffles';
-      bad.validate(function(error) {
+      bad.validate(function (error) {
         assert.ok(error);
         var errorMessage = 'CastError: Cast to Object failed for value ' +
           '"waffles" at path "foods"';
@@ -897,12 +897,12 @@ describe('schema', function() {
       });
     });
 
-    it('doesnt execute other validators if required fails (gh-2725)', function(done) {
-      var breakfast = new Schema({ description: { type: String, required: true, maxlength: 50 } });
+    it('doesnt execute other validators if required fails (gh-2725)', function (done) {
+      var breakfast = new Schema({description: {type: String, required: true, maxlength: 50}});
 
       var Breakfast = mongoose.model('gh2725', breakfast, 'gh2725');
       var bad = new Breakfast({});
-      bad.validate(function(error) {
+      bad.validate(function (error) {
         assert.ok(error);
         var errorMessage = 'ValidationError: Path `description` is required.';
         assert.equal(errorMessage, error.toString());
@@ -910,8 +910,8 @@ describe('schema', function() {
       });
     });
 
-    it('doesnt execute other validators if required fails (gh-3025)', function(done) {
-      var breakfast = new Schema({ description: { type: String, required: true, maxlength: 50 } });
+    it('doesnt execute other validators if required fails (gh-3025)', function (done) {
+      var breakfast = new Schema({description: {type: String, required: true, maxlength: 50}});
 
       var Breakfast = mongoose.model('gh3025', breakfast, 'gh3025');
       var bad = new Breakfast({});
@@ -923,10 +923,10 @@ describe('schema', function() {
       done();
     });
 
-    it('validateSync allows you to filter paths (gh-3153)', function(done) {
+    it('validateSync allows you to filter paths (gh-3153)', function (done) {
       var breakfast = new Schema({
-        description: { type: String, required: true, maxlength: 50 },
-        other: { type: String, required: true }
+        description: {type: String, required: true, maxlength: 50},
+        other: {type: String, required: true}
       });
 
       var Breakfast = mongoose.model('gh3153', breakfast, 'gh3153');
@@ -940,12 +940,12 @@ describe('schema', function() {
       done();
     });
 
-    it('adds required validators to the front of the list (gh-2843)', function(done) {
-      var breakfast = new Schema({ description: { type: String, maxlength: 50, required: true } });
+    it('adds required validators to the front of the list (gh-2843)', function (done) {
+      var breakfast = new Schema({description: {type: String, maxlength: 50, required: true}});
 
       var Breakfast = mongoose.model('gh2843', breakfast, 'gh2843');
       var bad = new Breakfast({});
-      bad.validate(function(error) {
+      bad.validate(function (error) {
         assert.ok(error);
         var errorMessage = 'ValidationError: Path `description` is required.';
         assert.equal(errorMessage, error.toString());
@@ -953,13 +953,13 @@ describe('schema', function() {
       });
     });
 
-    it('sets path correctly when setter throws exception (gh-2832)', function(done) {
+    it('sets path correctly when setter throws exception (gh-2832)', function (done) {
       var breakfast = new Schema({
-        description: { type: String, set: function() { throw new Error('oops'); } }
+        description: {type: String, set: function () { throw new Error('oops'); }}
       });
 
       var Breakfast = mongoose.model('gh2832', breakfast, 'gh2832');
-      Breakfast.create({ description: undefined }, function(error) {
+      Breakfast.create({description: undefined}, function (error) {
         assert.ok(error);
         var errorMessage = 'ValidationError: CastError: Cast to String failed for value "undefined" at path "description"';
         assert.equal(errorMessage, error.toString());
@@ -969,20 +969,20 @@ describe('schema', function() {
       });
     });
 
-    it('allows you to validate embedded doc that was .create()-ed (gh-2902) (gh-2929)', function(done) {
+    it('allows you to validate embedded doc that was .create()-ed (gh-2902) (gh-2929)', function (done) {
       var parentSchema = mongoose.Schema({
-        children: [{ name: { type: String, required: true } }]
+        children: [{name: {type: String, required: true}}]
       });
 
       var Parent = mongoose.model('gh2902', parentSchema);
 
       var p = new Parent();
-      var n = p.children.create({ name: '2' });
-      n.validate(function(error) {
+      var n = p.children.create({name: '2'});
+      n.validate(function (error) {
         assert.ifError(error);
         var bad = p.children.create({});
         p.children.push(bad);
-        bad.validate(function(error) {
+        bad.validate(function (error) {
           assert.ok(error);
           assert.ok(error.errors['children.0.name']);
           done();
@@ -990,38 +990,38 @@ describe('schema', function() {
       });
     });
 
-    it('returns correct kind for user defined custom validators (gh-2885)', function(done) {
-      var s = mongoose.Schema({ n: { type: String, validate: { validator: function() { return false; } }, msg: 'fail' } });
+    it('returns correct kind for user defined custom validators (gh-2885)', function (done) {
+      var s = mongoose.Schema({n: {type: String, validate: {validator: function () { return false; }}, msg: 'fail'}});
       var M = mongoose.model('gh2885', s);
 
-      var m = new M({ n: 'test' });
-      m.validate(function(error) {
+      var m = new M({n: 'test'});
+      m.validate(function (error) {
         assert.ok(error);
         assert.equal(error.errors['n'].kind, 'user defined');
         done();
       });
     });
 
-    it('enums report kind (gh-3009)', function(done) {
-      var s = mongoose.Schema({ n: { type: String, enum: ['a', 'b'] } });
+    it('enums report kind (gh-3009)', function (done) {
+      var s = mongoose.Schema({n: {type: String, enum: ['a', 'b']}});
       var M = mongoose.model('gh3009', s);
 
-      var m = new M({ n: 'test' });
-      m.validate(function(error) {
+      var m = new M({n: 'test'});
+      m.validate(function (error) {
         assert.ok(error);
         assert.equal(error.errors['n'].kind, 'enum');
         done();
       });
     });
 
-    it('skips conditional required (gh-3539)', function(done) {
+    it('skips conditional required (gh-3539)', function (done) {
       var s = mongoose.Schema({
-        n: { type: Number, required: function() { return false; }, min: 0 }
+        n: {type: Number, required: function () { return false; }, min: 0}
       });
       var M = mongoose.model('gh3539', s);
 
       var m = new M();
-      m.validate(function(error) {
+      m.validate(function (error) {
         assert.ifError(error);
         done();
       });
diff --git a/test/shard.test.js b/test/shard.test.js
index ca98c3b2641..64be3c20a24 100644
--- a/test/shard.test.js
+++ b/test/shard.test.js
@@ -1,4 +1,3 @@
-
 var start = require('./common'),
     assert = require('assert'),
     random = require('../lib/utils').random,
@@ -9,15 +8,16 @@ var uri = process.env.MONGOOSE_SHARD_TEST_URI;
 
 if (!uri) {
   console.log(
-    '\033[31m', '\n', 'You\'re not testing shards!',
-    '\n', 'Please set the MONGOOSE_SHARD_TEST_URI env variable.', '\n',
-    'e.g: `mongodb://localhost:27017/database', '\n',
-    'Sharding must already be enabled on your database',
-    '\033[39m'
+      '\033[31m', '\n', 'You\'re not testing shards!',
+      '\n', 'Please set the MONGOOSE_SHARD_TEST_URI env variable.', '\n',
+      'e.g: `mongodb://localhost:27017/database', '\n',
+      'Sharding must already be enabled on your database',
+      '\033[39m'
   );
 
   // let expresso shut down this test
-  exports.r = function expressoHack() {};
+  exports.r = function expressoHack() {
+  };
   return;
 }
 
@@ -25,11 +25,11 @@ var schema = new Schema({
   name: String,
   age: Number,
   likes: [String]
-}, { shardkey: { name: 1, age: 1 }});
+}, {shardkey: {name: 1, age: 1}});
 
 // to keep mongodb happy when sharding the collection
 // we add a matching index
-schema.index({ name: 1, age: 1 });
+schema.index({name: 1, age: 1});
 
 var collection = 'shardperson_' + random();
 mongoose.model('ShardPerson', schema, collection);
@@ -37,33 +37,32 @@ mongoose.model('ShardPerson', schema, collection);
 var version;
 var greaterThan20x;
 var db;
-describe('shard', function() {
-  before(function(done) {
-    db = start({ uri: uri });
-    db.on('error', function(err) {
+describe('shard', function () {
+  before(function (done) {
+    db = start({uri: uri});
+    db.on('error', function (err) {
       if (/failed to connect/.test(err)) {
         err.message = 'Shard test error: '
-          + err.message
-          + '\n'
-          + '    Are you sure there is a db running at '
-          + uri + ' ?'
-          + '\n';
+            + err.message
+            + '\n'
+            + '    Are you sure there is a db running at '
+            + uri + ' ?'
+            + '\n';
       }
       return done(err);
     });
-    db.on('open', function() {
+    db.on('open', function () {
       // set up a sharded test collection
       var P = db.model('ShardPerson', collection);
 
       // an existing index on shard key is required before sharding
-      P.on('index', function() {
-
+      P.on('index', function () {
         // enable sharding on our collection
         var cmd = {};
         cmd.shardcollection = db.name + '.' + collection;
         cmd.key = P.schema.options.shardkey;
 
-        P.db.db.executeDbAdminCommand(cmd, function(err, res) {
+        P.db.db.executeDbAdminCommand(cmd, function (err, res) {
           assert.ifError(err);
 
           if (!(res && res.documents && res.documents[0] && res.documents[0].ok)) {
@@ -71,16 +70,18 @@ describe('shard', function() {
                 + collection + '\n'
                 + res.documents[0].errmsg + '\n'
                 + 'Make sure to use a different database than what '
-                + 'is used for the MULTI_MONGOS_TEST' );
+                + 'is used for the MULTI_MONGOS_TEST');
             return done(err);
           }
 
-          db.db.admin(function(err, admin) {
+          db.db.admin(function (err, admin) {
             assert.ifError(err);
-            admin.serverStatus(function(err, info) {
+            admin.serverStatus(function (err, info) {
               db.close();
               assert.ifError(err);
-              version = info.version.split('.').map(function(n) { return parseInt(n, 10); });
+              version = info.version.split('.').map(function (n) {
+                return parseInt(n, 10);
+              });
               greaterThan20x = 2 < version[0] || 2 == version[0] && 0 < version[0];
               done();
             });
@@ -90,51 +91,51 @@ describe('shard', function() {
     });
   });
 
-  it('can read and write to a shard', function(done) {
-    var db = start({ uri:  uri });
+  it('can read and write to a shard', function (done) {
+    var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
-    P.create({ name: 'ryu', age: 25, likes: ['street fighting']}, function(err, ryu) {
+    P.create({name: 'ryu', age: 25, likes: ['street fighting']}, function (err, ryu) {
       assert.ifError(err);
-      P.findById(ryu._id, function(err, doc) {
+      P.findById(ryu._id, function (err, doc) {
         db.close();
         assert.ifError(err);
-        assert.equal(doc.id,ryu.id);
+        assert.equal(doc.id, ryu.id);
         done();
       });
     });
   });
 
-  it('save() and remove() works with shard keys transparently', function(done) {
-    var db = start({ uri:  uri });
+  it('save() and remove() works with shard keys transparently', function (done) {
+    var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
-    var zangief = new P({ name: 'Zangief', age: 33 });
-    zangief.save(function(err) {
+    var zangief = new P({name: 'Zangief', age: 33});
+    zangief.save(function (err) {
       assert.ifError(err);
 
       assert.equal(zangief.$__.shardval.name, 'Zangief');
       assert.equal(zangief.$__.shardval.age, 33);
 
-      P.findById(zangief._id, function(err, zang) {
+      P.findById(zangief._id, function (err, zang) {
         assert.ifError(err);
 
         assert.equal(zang.$__.shardval.name, 'Zangief');
         assert.equal(zang.$__.shardval.age, 33);
 
         zang.likes = ['spinning', 'laughing'];
-        zang.save(function(err) {
+        zang.save(function (err) {
           assert.ifError(err);
 
           assert.equal(zang.$__.shardval.name, 'Zangief');
           assert.equal(zang.$__.shardval.age, 33);
 
           zang.likes.addToSet('winning');
-          zang.save(function(err) {
+          zang.save(function (err) {
             assert.ifError(err);
             assert.equal(zang.$__.shardval.name, 'Zangief');
             assert.equal(zang.$__.shardval.age, 33);
-            zang.remove(function(err) {
+            zang.remove(function (err) {
               db.close();
               assert.ifError(err);
               done();
@@ -145,13 +146,13 @@ describe('shard', function() {
     });
   });
 
-  it('inserting to a sharded collection without the full shard key fails', function(done) {
-    var db = start({ uri:  uri });
+  it('inserting to a sharded collection without the full shard key fails', function (done) {
+    var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
     var pending = 6;
 
-    P.create({ name: 'ryu', likes: ['street fighting']}, function(err) {
+    P.create({name: 'ryu', likes: ['street fighting']}, function (err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -160,7 +161,7 @@ describe('shard', function() {
       }
     });
 
-    P.create({ likes: ['street fighting']}, function(err) {
+    P.create({likes: ['street fighting']}, function (err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -169,7 +170,7 @@ describe('shard', function() {
       }
     });
 
-    P.create({ name: 'ryu' }, function(err) {
+    P.create({name: 'ryu'}, function (err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -178,7 +179,7 @@ describe('shard', function() {
       }
     });
 
-    P.create({ age: 49 }, function(err) {
+    P.create({age: 49}, function (err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -187,7 +188,7 @@ describe('shard', function() {
       }
     });
 
-    P.create({ likes: ['street fighting'], age: 8 }, function(err) {
+    P.create({likes: ['street fighting'], age: 8}, function (err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -197,7 +198,7 @@ describe('shard', function() {
     });
 
     var p = new P;
-    p.save(function(err) {
+    p.save(function (err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -207,17 +208,17 @@ describe('shard', function() {
     });
   });
 
-  it('updating a sharded collection without the full shard key fails', function(done) {
-    var db = start({ uri:  uri });
+  it('updating a sharded collection without the full shard key fails', function (done) {
+    var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
-    P.create({ name: 'ken', age: 27 }, function(err, ken) {
+    P.create({name: 'ken', age: 27}, function (err, ken) {
       assert.ifError(err);
 
-      P.update({ name: 'ken' }, { likes: ['kicking', 'punching'] }, function(err) {
+      P.update({name: 'ken'}, {likes: ['kicking', 'punching']}, function (err) {
         assert.ok(/shard key/.test(err.message));
 
-        P.update({ _id: ken._id, name: 'ken' }, { likes: ['kicking', 'punching'] }, function(err) {
+        P.update({_id: ken._id, name: 'ken'}, {likes: ['kicking', 'punching']}, function (err) {
           // mongo 2.0.x returns: can't do non-multi update with query that doesn't have a valid shard key
           if (greaterThan20x) {
             assert.ok(!err, err);
@@ -225,7 +226,7 @@ describe('shard', function() {
             assert.ok(/shard key/.test(err.message));
           }
 
-          P.update({ _id: ken._id, age: 27 }, { likes: ['kicking', 'punching'] }, function(err) {
+          P.update({_id: ken._id, age: 27}, {likes: ['kicking', 'punching']}, function (err) {
             // mongo 2.0.x returns: can't do non-multi update with query that doesn't have a valid shard key
             if (greaterThan20x) {
               assert.ok(!err, err);
@@ -233,7 +234,7 @@ describe('shard', function() {
               assert.ok(/shard key/.test(err.message));
             }
 
-            P.update({ age: 27 }, { likes: ['kicking', 'punching'] }, function(err) {
+            P.update({age: 27}, {likes: ['kicking', 'punching']}, function (err) {
               db.close();
               assert.ok(err);
               done();
@@ -244,30 +245,30 @@ describe('shard', function() {
     });
   });
 
-  it('updating shard key values fails', function(done) {
-    var db = start({ uri:  uri });
+  it('updating shard key values fails', function (done) {
+    var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
-    P.create({ name: 'chun li', age: 19, likes: ['street fighting']}, function(err, chunli) {
+    P.create({name: 'chun li', age: 19, likes: ['street fighting']}, function (err, chunli) {
       assert.ifError(err);
 
       assert.equal(chunli.$__.shardval.name, 'chun li');
       assert.equal(chunli.$__.shardval.age, 19);
 
       chunli.age = 20;
-      chunli.save(function(err) {
+      chunli.save(function (err) {
         assert.ok(/^After applying the update to the document/.test(err.message));
 
         assert.equal(chunli.$__.shardval.name, 'chun li');
         assert.equal(chunli.$__.shardval.age, 19);
 
-        P.findById(chunli._id, function(err, chunli) {
+        P.findById(chunli._id, function (err, chunli) {
           assert.ifError(err);
 
           assert.equal(chunli.$__.shardval.name, 'chun li');
           assert.equal(chunli.$__.shardval.age, 19);
 
           chunli.name = 'chuuuun liiiii';
-          chunli.save(function(err) {
+          chunli.save(function (err) {
             db.close();
             assert.ok(/^After applying the update to the document/.test(err.message));
             done();
@@ -277,26 +278,25 @@ describe('shard', function() {
     });
   });
 
-  it('allows null shard key values', function(done) {
-    var db = start({ uri:  uri });
+  it('allows null shard key values', function (done) {
+    var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
-    P.create({ name: null, age: 27 }, function(err, ken) {
+    P.create({name: null, age: 27}, function (err, ken) {
       assert.ifError(err);
-      P.findById(ken, function(err) {
+      P.findById(ken, function (err) {
         assert.ifError(err);
         done();
       });
     });
   });
 
-  after(function(done) {
-    var db = start({ uri:  uri });
+  after(function (done) {
+    var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
-    P.collection.drop(function() {
+    P.collection.drop(function () {
       db.close();
       done();
     });
   });
-
 });
diff --git a/test/types.array.test.js b/test/types.array.test.js
index c0a4ca54ca5..d70af124394 100644
--- a/test/types.array.test.js
+++ b/test/types.array.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -28,8 +27,8 @@ mongoose.model('Pet', Pet);
  * Test.
  */
 
-describe('types array', function() {
-  it('behaves and quacks like an Array', function(done) {
+describe('types array', function () {
+  it('behaves and quacks like an Array', function (done) {
     var a = new MongooseArray;
 
     assert.ok(a instanceof Array);
@@ -41,9 +40,9 @@ describe('types array', function() {
     done();
   });
 
-  describe('hasAtomics', function() {
-    it('does not throw', function(done) {
-      var b = new MongooseArray([12,3,4,5]).filter(Boolean);
+  describe('hasAtomics', function () {
+    it('does not throw', function (done) {
+      var b = new MongooseArray([12, 3, 4, 5]).filter(Boolean);
       var threw = false;
 
       try {
@@ -54,9 +53,9 @@ describe('types array', function() {
 
       assert.ok(!threw);
 
-      var a = new MongooseArray([67,8]).filter(Boolean);
+      var a = new MongooseArray([67, 8]).filter(Boolean);
       try {
-        a.push(3,4);
+        a.push(3, 4);
       } catch (_) {
         console.error(_);
         threw = true;
@@ -65,19 +64,18 @@ describe('types array', function() {
       assert.ok(!threw);
       done();
     });
-
   });
 
-  describe('indexOf()', function() {
-    it('works', function(done) {
+  describe('indexOf()', function () {
+    it('works', function (done) {
       var db = start(),
           User = db.model('User', 'users_' + random()),
           Pet = db.model('Pet', 'pets' + random());
 
-      var tj = new User({ name: 'tj' }),
-          tobi = new Pet({ name: 'tobi' }),
-          loki = new Pet({ name: 'loki' }),
-          jane = new Pet({ name: 'jane' });
+      var tj = new User({name: 'tj'}),
+          tobi = new Pet({name: 'tobi'}),
+          loki = new Pet({name: 'loki'}),
+          jane = new Pet({name: 'jane'});
 
       tj.pets.push(tobi);
       tj.pets.push(loki);
@@ -85,73 +83,76 @@ describe('types array', function() {
 
       var pending = 3;
 
-      [tobi, loki, jane].forEach(function(pet) {
-        pet.save(function() {
+      [tobi, loki, jane].forEach(function (pet) {
+        pet.save(function () {
           --pending || cb();
         });
       });
 
       function cb() {
-        Pet.find({}, function(err) {
+        Pet.find({}, function (err) {
           assert.ifError(err);
-          tj.save(function(err) {
+          tj.save(function (err) {
             assert.ifError(err);
-            User.findOne({ name: 'tj' }, function(err, user) {
+            User.findOne({name: 'tj'}, function (err, user) {
               assert.ifError(err);
               assert.equal(user.pets.length, 3);
-              assert.equal(user.pets.indexOf(tobi.id),0);
-              assert.equal(user.pets.indexOf(loki.id),1);
-              assert.equal(user.pets.indexOf(jane.id),2);
-              assert.equal(user.pets.indexOf(tobi._id),0);
-              assert.equal(user.pets.indexOf(loki._id),1);
-              assert.equal(user.pets.indexOf(jane._id),2);
+              assert.equal(user.pets.indexOf(tobi.id), 0);
+              assert.equal(user.pets.indexOf(loki.id), 1);
+              assert.equal(user.pets.indexOf(jane.id), 2);
+              assert.equal(user.pets.indexOf(tobi._id), 0);
+              assert.equal(user.pets.indexOf(loki._id), 1);
+              assert.equal(user.pets.indexOf(jane._id), 2);
               db.close(done);
             });
           });
         });
       }
-
     });
   });
 
-  describe('push()', function() {
+  describe('push()', function () {
     var db, N, S, B, M, D, ST;
 
     function save(doc, cb) {
-      doc.save(function(err) {
-        if (err) return cb(err);
+      doc.save(function (err) {
+        if (err) {
+          return cb(err);
+        }
         doc.constructor.findById(doc._id, cb);
       });
     }
 
-    before(function(done) {
+    before(function (done) {
       db = start();
-      N = db.model('arraySet', Schema({ arr: [Number] }));
-      S = db.model('arraySetString', Schema({ arr: [String] }));
-      B = db.model('arraySetBuffer', Schema({ arr: [Buffer] }));
-      M = db.model('arraySetMixed', Schema({ arr: [] }));
-      D = db.model('arraySetSubDocs', Schema({ arr: [{ name: String}] }));
-      ST = db.model('arrayWithSetters', Schema({ arr: [{
-        type: String,
-        lowercase: true
-      }] }));
+      N = db.model('arraySet', Schema({arr: [Number]}));
+      S = db.model('arraySetString', Schema({arr: [String]}));
+      B = db.model('arraySetBuffer', Schema({arr: [Buffer]}));
+      M = db.model('arraySetMixed', Schema({arr: []}));
+      D = db.model('arraySetSubDocs', Schema({arr: [{name: String}]}));
+      ST = db.model('arrayWithSetters', Schema({
+        arr: [{
+          type: String,
+          lowercase: true
+        }]
+      }));
       done();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('works with numbers', function(done) {
-      var m = new N({ arr: [3,4,5,6] });
-      save(m, function(err, doc) {
+    it('works with numbers', function (done) {
+      var m = new N({arr: [3, 4, 5, 6]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.push(8);
         assert.strictEqual(8, doc.arr[doc.arr.length - 1]);
         assert.strictEqual(8, doc.arr[4]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.strictEqual(3, doc.arr[0]);
@@ -165,16 +166,16 @@ describe('types array', function() {
       });
     });
 
-    it('works with strings', function(done) {
-      var m = new S({ arr: [3,4,5,6] });
-      save(m, function(err, doc) {
+    it('works with strings', function (done) {
+      var m = new S({arr: [3, 4, 5, 6]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.push(8);
         assert.strictEqual('8', doc.arr[doc.arr.length - 1]);
         assert.strictEqual('8', doc.arr[4]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.strictEqual('3', doc.arr[0]);
@@ -188,41 +189,41 @@ describe('types array', function() {
       });
     });
 
-    it('works with buffers', function(done) {
-      var m = new B({ arr: [[0], new Buffer(1)] });
-      save(m, function(err, doc) {
+    it('works with buffers', function (done) {
+      var m = new B({arr: [[0], new Buffer(1)]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         assert.ok(doc.arr[0].isMongooseBuffer);
         assert.ok(doc.arr[1].isMongooseBuffer);
-        doc.arr.push("nice");
+        doc.arr.push('nice');
         assert.equal(3, doc.arr.length);
         assert.ok(doc.arr[2].isMongooseBuffer);
-        assert.strictEqual("nice", doc.arr[2].toString('utf8'));
+        assert.strictEqual('nice', doc.arr[2].toString('utf8'));
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.ok(doc.arr[0].isMongooseBuffer);
           assert.ok(doc.arr[1].isMongooseBuffer);
           assert.ok(doc.arr[2].isMongooseBuffer);
           assert.strictEqual('\u0000', doc.arr[0].toString());
-          assert.strictEqual("nice", doc.arr[2].toString());
+          assert.strictEqual('nice', doc.arr[2].toString());
           done();
         });
       });
     });
 
-    it('works with mixed', function(done) {
-      var m = new M({ arr: [3,{x:1},'yes', [5]] });
-      save(m, function(err, doc) {
+    it('works with mixed', function (done) {
+      var m = new M({arr: [3, {x: 1}, 'yes', [5]]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.push(null);
         assert.equal(5, doc.arr.length);
         assert.strictEqual(null, doc.arr[4]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
 
           assert.equal(5, doc.arr.length);
@@ -241,7 +242,7 @@ describe('types array', function() {
           assert.equal(7, doc.arr.length);
           assert.strictEqual('', doc.arr[6].toString());
 
-          save(doc, function(err, doc) {
+          save(doc, function (err, doc) {
             assert.ifError(err);
 
             assert.equal(7, doc.arr.length);
@@ -260,40 +261,40 @@ describe('types array', function() {
       });
     });
 
-    it('works with sub-docs', function(done) {
-      var m = new D({ arr: [{name:'aaron'}, {name:'moombahton '}] });
-      save(m, function(err, doc) {
+    it('works with sub-docs', function (done) {
+      var m = new D({arr: [{name: 'aaron'}, {name: 'moombahton '}]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
-        doc.arr.push({name:"Restrepo"});
+        doc.arr.push({name: 'Restrepo'});
         assert.equal(3, doc.arr.length);
-        assert.equal("Restrepo", doc.arr[2].name);
+        assert.equal('Restrepo', doc.arr[2].name);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
 
           // validate
           assert.equal(3, doc.arr.length);
           assert.equal('aaron', doc.arr[0].name);
-          assert.equal("moombahton ", doc.arr[1].name);
-          assert.equal("Restrepo", doc.arr[2].name);
+          assert.equal('moombahton ', doc.arr[1].name);
+          assert.equal('Restrepo', doc.arr[2].name);
 
           done();
         });
       });
     });
 
-    it('applies setters (gh-3032)', function(done) {
-      var m = new ST({ arr: ["ONE", "TWO"] });
-      save(m, function(err, doc) {
+    it('applies setters (gh-3032)', function (done) {
+      var m = new ST({arr: ['ONE', 'TWO']});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
-        doc.arr.push("THREE");
+        doc.arr.push('THREE');
         assert.strictEqual('one', doc.arr[0]);
         assert.strictEqual('two', doc.arr[1]);
         assert.strictEqual('three', doc.arr[2]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.strictEqual('one', doc.arr[0]);
@@ -306,38 +307,38 @@ describe('types array', function() {
     });
   });
 
-  describe('splice()', function() {
+  describe('splice()', function () {
     var db;
 
-    before(function() {
+    before(function () {
       db = start();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('works', function(done) {
+    it('works', function (done) {
       var collection = 'splicetest-number' + random();
-      var schema = new Schema({ numbers: [Number] }),
+      var schema = new Schema({numbers: [Number]}),
           A = db.model('splicetestNumber', schema, collection);
 
-      var a = new A({ numbers: [4,5,6,7] });
-      a.save(function(err) {
+      var a = new A({numbers: [4, 5, 6, 7]});
+      a.save(function (err) {
         assert.ifError(err);
-        A.findById(a._id, function(err, doc) {
+        A.findById(a._id, function (err, doc) {
           assert.ifError(err);
-          var removed = doc.numbers.splice(1, 1, "10");
+          var removed = doc.numbers.splice(1, 1, '10');
           assert.deepEqual(removed, [5]);
           assert.equal('number', typeof doc.numbers[1]);
-          assert.deepEqual(doc.numbers.toObject(),[4,10,6,7]);
-          doc.save(function(err) {
+          assert.deepEqual(doc.numbers.toObject(), [4, 10, 6, 7]);
+          doc.save(function (err) {
             assert.ifError(err);
-            A.findById(a._id, function(err, doc) {
+            A.findById(a._id, function (err, doc) {
               assert.ifError(err);
-              assert.deepEqual(doc.numbers.toObject(), [4,10,6,7]);
+              assert.deepEqual(doc.numbers.toObject(), [4, 10, 6, 7]);
 
-              A.collection.drop(function(err) {
+              A.collection.drop(function (err) {
                 assert.ifError(err);
                 done();
               });
@@ -347,35 +348,35 @@ describe('types array', function() {
       });
     });
 
-    it('on embedded docs', function(done) {
+    it('on embedded docs', function (done) {
       var collection = 'splicetest-embeddeddocs' + random();
-      var schema = new Schema({ types: [new Schema({ type: String }) ]}),
+      var schema = new Schema({types: [new Schema({type: String})]}),
           A = db.model('splicetestEmbeddedDoc', schema, collection);
 
-      var a = new A({ types: [{type:'bird'},{type:'boy'},{type:'frog'},{type:'cloud'}] });
-      a.save(function(err) {
+      var a = new A({types: [{type: 'bird'}, {type: 'boy'}, {type: 'frog'}, {type: 'cloud'}]});
+      a.save(function (err) {
         assert.ifError(err);
-        A.findById(a._id, function(err, doc) {
+        A.findById(a._id, function (err, doc) {
           assert.ifError(err);
 
           doc.types.$pop();
 
           var removed = doc.types.splice(1, 1);
-          assert.equal(removed.length,1);
-          assert.equal(removed[0].type,'boy');
+          assert.equal(removed.length, 1);
+          assert.equal(removed[0].type, 'boy');
 
           var obj = doc.types.toObject();
-          assert.equal(obj[0].type,'bird');
-          assert.equal(obj[1].type,'frog');
+          assert.equal(obj[0].type, 'bird');
+          assert.equal(obj[1].type, 'frog');
 
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
-            A.findById(a._id, function(err, doc) {
+            A.findById(a._id, function (err, doc) {
               assert.ifError(err);
 
               var obj = doc.types.toObject();
-              assert.equal(obj[0].type,'bird');
-              assert.equal(obj[1].type,'frog');
+              assert.equal(obj[0].type, 'bird');
+              assert.equal(obj[1].type, 'frog');
               done();
             });
           });
@@ -384,89 +385,89 @@ describe('types array', function() {
     });
   });
 
-  describe('unshift()', function() {
+  describe('unshift()', function () {
     var db;
 
-    before(function() {
+    before(function () {
       db = start();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('works', function(done) {
+    it('works', function (done) {
       var schema = new Schema({
-            types: [new Schema({ type: String })],
+            types: [new Schema({type: String})],
             nums: [Number],
             strs: [String]
           }),
           A = db.model('unshift', schema, 'unshift' + random());
 
       var a = new A({
-        types: [{type:'bird'},{type:'boy'},{type:'frog'},{type:'cloud'}],
-        nums: [1,2,3],
+        types: [{type: 'bird'}, {type: 'boy'}, {type: 'frog'}, {type: 'cloud'}],
+        nums: [1, 2, 3],
         strs: 'one two three'.split(' ')
       });
 
-      a.save(function(err) {
+      a.save(function (err) {
         assert.ifError(err);
-        A.findById(a._id, function(err, doc) {
+        A.findById(a._id, function (err, doc) {
           assert.ifError(err);
 
-          var tlen = doc.types.unshift({type:'tree'});
+          var tlen = doc.types.unshift({type: 'tree'});
           var nlen = doc.nums.unshift(0);
           var slen = doc.strs.unshift('zero');
 
-          assert.equal(tlen,5);
-          assert.equal(nlen,4);
-          assert.equal(slen,4);
+          assert.equal(tlen, 5);
+          assert.equal(nlen, 4);
+          assert.equal(slen, 4);
 
-          doc.types.push({type:'worm'});
+          doc.types.push({type: 'worm'});
           var obj = doc.types.toObject();
-          assert.equal(obj[0].type,'tree');
-          assert.equal(obj[1].type,'bird');
-          assert.equal(obj[2].type,'boy');
-          assert.equal(obj[3].type,'frog');
-          assert.equal(obj[4].type,'cloud');
-          assert.equal(obj[5].type,'worm');
+          assert.equal(obj[0].type, 'tree');
+          assert.equal(obj[1].type, 'bird');
+          assert.equal(obj[2].type, 'boy');
+          assert.equal(obj[3].type, 'frog');
+          assert.equal(obj[4].type, 'cloud');
+          assert.equal(obj[5].type, 'worm');
 
           obj = doc.nums.toObject();
-          assert.equal(obj[0].valueOf(),0);
-          assert.equal(obj[1].valueOf(),1);
-          assert.equal(obj[2].valueOf(),2);
-          assert.equal(obj[3].valueOf(),3);
+          assert.equal(obj[0].valueOf(), 0);
+          assert.equal(obj[1].valueOf(), 1);
+          assert.equal(obj[2].valueOf(), 2);
+          assert.equal(obj[3].valueOf(), 3);
 
           obj = doc.strs.toObject();
-          assert.equal(obj[0],'zero');
-          assert.equal(obj[1],'one');
-          assert.equal(obj[2],'two');
-          assert.equal(obj[3],'three');
+          assert.equal(obj[0], 'zero');
+          assert.equal(obj[1], 'one');
+          assert.equal(obj[2], 'two');
+          assert.equal(obj[3], 'three');
 
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
-            A.findById(a._id, function(err, doc) {
+            A.findById(a._id, function (err, doc) {
               assert.ifError(err);
 
               var obj = doc.types.toObject();
-              assert.equal(obj[0].type,'tree');
-              assert.equal(obj[1].type,'bird');
-              assert.equal(obj[2].type,'boy');
-              assert.equal(obj[3].type,'frog');
-              assert.equal(obj[4].type,'cloud');
-              assert.equal(obj[5].type,'worm');
+              assert.equal(obj[0].type, 'tree');
+              assert.equal(obj[1].type, 'bird');
+              assert.equal(obj[2].type, 'boy');
+              assert.equal(obj[3].type, 'frog');
+              assert.equal(obj[4].type, 'cloud');
+              assert.equal(obj[5].type, 'worm');
 
               obj = doc.nums.toObject();
-              assert.equal(obj[0].valueOf(),0);
-              assert.equal(obj[1].valueOf(),1);
-              assert.equal(obj[2].valueOf(),2);
-              assert.equal(obj[3].valueOf(),3);
+              assert.equal(obj[0].valueOf(), 0);
+              assert.equal(obj[1].valueOf(), 1);
+              assert.equal(obj[2].valueOf(), 2);
+              assert.equal(obj[3].valueOf(), 3);
 
               obj = doc.strs.toObject();
-              assert.equal(obj[0],'zero');
-              assert.equal(obj[1],'one');
-              assert.equal(obj[2],'two');
-              assert.equal(obj[3],'three');
+              assert.equal(obj[0], 'zero');
+              assert.equal(obj[1], 'one');
+              assert.equal(obj[2], 'two');
+              assert.equal(obj[3], 'three');
               done();
             });
           });
@@ -474,21 +475,23 @@ describe('types array', function() {
       });
     });
 
-    it('applies setters (gh-3032)', function(done) {
-      var ST = db.model('setterArray', Schema({ arr: [{
-        type: String,
-        lowercase: true
-      }] }));
-      var m = new ST({ arr: ["ONE", "TWO"] });
-      m.save(function(err, doc) {
+    it('applies setters (gh-3032)', function (done) {
+      var ST = db.model('setterArray', Schema({
+        arr: [{
+          type: String,
+          lowercase: true
+        }]
+      }));
+      var m = new ST({arr: ['ONE', 'TWO']});
+      m.save(function (err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
-        doc.arr.unshift("THREE");
+        doc.arr.unshift('THREE');
         assert.strictEqual('three', doc.arr[0]);
         assert.strictEqual('one', doc.arr[1]);
         assert.strictEqual('two', doc.arr[2]);
 
-        doc.save(function(err, doc) {
+        doc.save(function (err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.strictEqual('three', doc.arr[0]);
@@ -501,19 +504,19 @@ describe('types array', function() {
     });
   });
 
-  describe('shift()', function() {
+  describe('shift()', function () {
     var db;
-    before(function() {
+    before(function () {
       db = start();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('works', function(done) {
+    it('works', function (done) {
       var schema = new Schema({
-        types: [new Schema({ type: String })],
+        types: [new Schema({type: String})],
         nums: [Number],
         strs: [String]
       });
@@ -521,58 +524,58 @@ describe('types array', function() {
       var A = db.model('shift', schema, 'unshift' + random());
 
       var a = new A({
-        types: [{type:'bird'},{type:'boy'},{type:'frog'},{type:'cloud'}],
-        nums: [1,2,3],
+        types: [{type: 'bird'}, {type: 'boy'}, {type: 'frog'}, {type: 'cloud'}],
+        nums: [1, 2, 3],
         strs: 'one two three'.split(' ')
       });
 
-      a.save(function(err) {
+      a.save(function (err) {
         assert.ifError(err);
-        A.findById(a._id, function(err, doc) {
+        A.findById(a._id, function (err, doc) {
           assert.ifError(err);
 
           var t = doc.types.shift();
           var n = doc.nums.shift();
           var s = doc.strs.shift();
 
-          assert.equal(t.type,'bird');
-          assert.equal(n,1);
-          assert.equal(s,'one');
+          assert.equal(t.type, 'bird');
+          assert.equal(n, 1);
+          assert.equal(s, 'one');
 
           var obj = doc.types.toObject();
-          assert.equal(obj[0].type,'boy');
-          assert.equal(obj[1].type,'frog');
-          assert.equal(obj[2].type,'cloud');
+          assert.equal(obj[0].type, 'boy');
+          assert.equal(obj[1].type, 'frog');
+          assert.equal(obj[2].type, 'cloud');
 
           doc.nums.push(4);
           obj = doc.nums.toObject();
           assert.equal(2, obj[0].valueOf());
-          assert.equal(obj[1].valueOf(),3);
-          assert.equal(obj[2].valueOf(),4);
+          assert.equal(obj[1].valueOf(), 3);
+          assert.equal(obj[2].valueOf(), 4);
 
           obj = doc.strs.toObject();
-          assert.equal(obj[0],'two');
-          assert.equal(obj[1],'three');
+          assert.equal(obj[0], 'two');
+          assert.equal(obj[1], 'three');
 
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
-            A.findById(a._id, function(err, doc) {
+            A.findById(a._id, function (err, doc) {
               db.close();
               assert.ifError(err);
 
               var obj = doc.types.toObject();
-              assert.equal(obj[0].type,'boy');
-              assert.equal(obj[1].type,'frog');
-              assert.equal(obj[2].type,'cloud');
+              assert.equal(obj[0].type, 'boy');
+              assert.equal(obj[1].type, 'frog');
+              assert.equal(obj[2].type, 'cloud');
 
               obj = doc.nums.toObject();
-              assert.equal(obj[0].valueOf(),2);
-              assert.equal(obj[1].valueOf(),3);
-              assert.equal(obj[2].valueOf(),4);
+              assert.equal(obj[0].valueOf(), 2);
+              assert.equal(obj[1].valueOf(), 3);
+              assert.equal(obj[2].valueOf(), 4);
 
               obj = doc.strs.toObject();
-              assert.equal(obj[0],'two');
-              assert.equal(obj[1],'three');
+              assert.equal(obj[0], 'two');
+              assert.equal(obj[1], 'three');
               done();
             });
           });
@@ -581,17 +584,17 @@ describe('types array', function() {
     });
   });
 
-  describe('$shift', function() {
-    it('works', function(done) {
+  describe('$shift', function () {
+    it('works', function (done) {
       // atomic shift uses $pop -1
       var db = start();
-      var painting = new Schema({ colors: [] });
+      var painting = new Schema({colors: []});
       var Painting = db.model('Painting', painting);
-      var p = new Painting({ colors: ['blue', 'green', 'yellow'] });
-      p.save(function(err) {
+      var p = new Painting({colors: ['blue', 'green', 'yellow']});
+      p.save(function (err) {
         assert.ifError(err);
 
-        Painting.findById(p, function(err, doc) {
+        Painting.findById(p, function (err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.colors.length);
           var color = doc.colors.$shift();
@@ -602,14 +605,14 @@ describe('types array', function() {
           color = doc.colors.$shift();
           assert.equal(color, undefined);
           assert.equal(2, doc.colors.length);
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.equal(null, err);
             var color = doc.colors.$shift();
             assert.equal(1, doc.colors.length);
             assert.equal(color, 'green');
-            doc.save(function(err) {
+            doc.save(function (err) {
               assert.equal(null, err);
-              Painting.findById(doc, function(err, doc) {
+              Painting.findById(doc, function (err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(1, doc.colors.length);
@@ -623,11 +626,11 @@ describe('types array', function() {
     });
   });
 
-  describe('pop()', function() {
-    it('works', function(done) {
+  describe('pop()', function () {
+    it('works', function (done) {
       var db = start(),
           schema = new Schema({
-            types: [new Schema({ type: String })],
+            types: [new Schema({type: String})],
             nums: [Number],
             strs: [String]
           });
@@ -635,58 +638,58 @@ describe('types array', function() {
       var A = db.model('pop', schema, 'pop' + random());
 
       var a = new A({
-        types: [{type:'bird'},{type:'boy'},{type:'frog'},{type:'cloud'}],
-        nums: [1,2,3],
+        types: [{type: 'bird'}, {type: 'boy'}, {type: 'frog'}, {type: 'cloud'}],
+        nums: [1, 2, 3],
         strs: 'one two three'.split(' ')
       });
 
-      a.save(function(err) {
+      a.save(function (err) {
         assert.ifError(err);
-        A.findById(a._id, function(err, doc) {
+        A.findById(a._id, function (err, doc) {
           assert.ifError(err);
 
           var t = doc.types.pop();
           var n = doc.nums.pop();
           var s = doc.strs.pop();
 
-          assert.equal(t.type,'cloud');
-          assert.equal(n,3);
-          assert.equal(s,'three');
+          assert.equal(t.type, 'cloud');
+          assert.equal(n, 3);
+          assert.equal(s, 'three');
 
           var obj = doc.types.toObject();
-          assert.equal(obj[0].type,'bird');
-          assert.equal(obj[1].type,'boy');
-          assert.equal(obj[2].type,'frog');
+          assert.equal(obj[0].type, 'bird');
+          assert.equal(obj[1].type, 'boy');
+          assert.equal(obj[2].type, 'frog');
 
           doc.nums.push(4);
           obj = doc.nums.toObject();
-          assert.equal(obj[0].valueOf(),1);
-          assert.equal(obj[1].valueOf(),2);
-          assert.equal(obj[2].valueOf(),4);
+          assert.equal(obj[0].valueOf(), 1);
+          assert.equal(obj[1].valueOf(), 2);
+          assert.equal(obj[2].valueOf(), 4);
 
           obj = doc.strs.toObject();
-          assert.equal(obj[0],'one');
-          assert.equal(obj[1],'two');
+          assert.equal(obj[0], 'one');
+          assert.equal(obj[1], 'two');
 
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
-            A.findById(a._id, function(err, doc) {
+            A.findById(a._id, function (err, doc) {
               db.close();
               assert.ifError(err);
 
               var obj = doc.types.toObject();
-              assert.equal(obj[0].type,'bird');
-              assert.equal(obj[1].type,'boy');
-              assert.equal(obj[2].type,'frog');
+              assert.equal(obj[0].type, 'bird');
+              assert.equal(obj[1].type, 'boy');
+              assert.equal(obj[2].type, 'frog');
 
               obj = doc.nums.toObject();
-              assert.equal(obj[0].valueOf(),1);
-              assert.equal(obj[1].valueOf(),2);
-              assert.equal(obj[2].valueOf(),4);
+              assert.equal(obj[0].valueOf(), 1);
+              assert.equal(obj[1].valueOf(), 2);
+              assert.equal(obj[2].valueOf(), 4);
 
               obj = doc.strs.toObject();
-              assert.equal(obj[0],'one');
-              assert.equal(obj[1],'two');
+              assert.equal(obj[0], 'one');
+              assert.equal(obj[1], 'two');
               done();
             });
           });
@@ -695,41 +698,41 @@ describe('types array', function() {
     });
   });
 
-  describe('pull()', function() {
-    it('works', function(done) {
+  describe('pull()', function () {
+    it('works', function (done) {
       var db = start();
-      var catschema = new Schema({ name: String });
+      var catschema = new Schema({name: String});
       var Cat = db.model('Cat', catschema);
       var schema = new Schema({
-        a: [{ type: Schema.ObjectId, ref: 'Cat' }]
+        a: [{type: Schema.ObjectId, ref: 'Cat'}]
       });
       var A = db.model('TestPull', schema);
-      var cat = new Cat({ name: 'peanut' });
-      cat.save(function(err) {
+      var cat = new Cat({name: 'peanut'});
+      cat.save(function (err) {
         assert.ifError(err);
 
-        var a = new A({ a: [cat._id] });
-        a.save(function(err) {
+        var a = new A({a: [cat._id]});
+        a.save(function (err) {
           assert.ifError(err);
 
-          A.findById(a, function(err, doc) {
+          A.findById(a, function (err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(1, doc.a.length);
             doc.a.pull(cat.id);
-            assert.equal(doc.a.length,0);
+            assert.equal(doc.a.length, 0);
             done();
           });
         });
       });
     });
 
-    it('handles pulling with no _id (gh-3341)', function(done) {
+    it('handles pulling with no _id (gh-3341)', function (done) {
       var db = start();
       var personSchema = new Schema({
         name: String,
         role: String
-      }, { _id: false });
+      }, {_id: false});
       var bandSchema = new Schema({
         name: String,
         members: [personSchema]
@@ -740,25 +743,25 @@ describe('types array', function() {
       var gnr = new Band({
         name: "Guns N' Roses",
         members: [
-          { name: 'Axl', role: 'Lead Singer' },
-          { name: 'Slash', role: 'Guitar' },
-          { name: 'Izzy', role: 'Guitar' },
-          { name: 'Duff', role: 'Bass' },
-          { name: 'Adler', role: 'Drums' }
+          {name: 'Axl', role: 'Lead Singer'},
+          {name: 'Slash', role: 'Guitar'},
+          {name: 'Izzy', role: 'Guitar'},
+          {name: 'Duff', role: 'Bass'},
+          {name: 'Adler', role: 'Drums'}
         ]
       });
 
-      gnr.save(function(error) {
+      gnr.save(function (error) {
         assert.ifError(error);
-        gnr.members.pull({ name: 'Slash', role: 'Guitar' });
-        gnr.save(function(error) {
+        gnr.members.pull({name: 'Slash', role: 'Guitar'});
+        gnr.save(function (error) {
           assert.ifError(error);
           assert.equal(gnr.members.length, 4);
           assert.equal(gnr.members[0].name, 'Axl');
           assert.equal(gnr.members[1].name, 'Izzy');
           assert.equal(gnr.members[2].name, 'Duff');
           assert.equal(gnr.members[3].name, 'Adler');
-          Band.findById(gnr._id, function(error, gnr) {
+          Band.findById(gnr._id, function (error, gnr) {
             assert.ifError(error);
             assert.equal(gnr.members.length, 4);
             assert.equal(gnr.members[0].name, 'Axl');
@@ -772,16 +775,16 @@ describe('types array', function() {
     });
   });
 
-  describe('$pop()', function() {
-    it('works', function(done) {
+  describe('$pop()', function () {
+    it('works', function (done) {
       var db = start();
-      var painting = new Schema({ colors: [] });
+      var painting = new Schema({colors: []});
       var Painting = db.model('Painting', painting);
-      var p = new Painting({ colors: ['blue', 'green', 'yellow'] });
-      p.save(function(err) {
+      var p = new Painting({colors: ['blue', 'green', 'yellow']});
+      p.save(function (err) {
         assert.ifError(err);
 
-        Painting.findById(p, function(err, doc) {
+        Painting.findById(p, function (err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.colors.length);
           var color = doc.colors.$pop();
@@ -793,14 +796,14 @@ describe('types array', function() {
           assert.equal(color, undefined);
           assert.equal(2, doc.colors.length);
           assert.equal(false, '$set' in doc.colors._atomics, 'invalid $atomic op used');
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.equal(null, err);
             var color = doc.colors.$pop();
             assert.equal(1, doc.colors.length);
             assert.equal(color, 'green');
-            doc.save(function(err) {
+            doc.save(function (err) {
               assert.equal(null, err);
-              Painting.findById(doc, function(err, doc) {
+              Painting.findById(doc, function (err, doc) {
                 db.close();
                 assert.strictEqual(null, err);
                 assert.equal(1, doc.colors.length);
@@ -814,31 +817,31 @@ describe('types array', function() {
     });
   });
 
-  describe('addToSet()', function() {
-    it('works', function(done) {
+  describe('addToSet()', function () {
+    it('works', function (done) {
       var db = start(),
-          e = new Schema({ name: String, arr: [] }),
+          e = new Schema({name: String, arr: []}),
           schema = new Schema({
             num: [Number],
             str: [String],
             doc: [e],
             date: [Date],
-            id:  [Schema.ObjectId]
+            id: [Schema.ObjectId]
           });
 
       var M = db.model('testAddToSet', schema);
       var m = new M;
 
-      m.num.push(1,2,3);
-      m.str.push('one','two','tres');
-      m.doc.push({ name: 'Dubstep', arr: [1] }, { name: 'Polka', arr: [{ x: 3 }]});
+      m.num.push(1, 2, 3);
+      m.str.push('one', 'two', 'tres');
+      m.doc.push({name: 'Dubstep', arr: [1]}, {name: 'Polka', arr: [{x: 3}]});
 
       var d1 = new Date;
-      var d2 = new Date( +d1 + 60000);
-      var d3 = new Date( +d1 + 30000);
-      var d4 = new Date( +d1 + 20000);
-      var d5 = new Date( +d1 + 90000);
-      var d6 = new Date( +d1 + 10000);
+      var d2 = new Date(+d1 + 60000);
+      var d3 = new Date(+d1 + 30000);
+      var d4 = new Date(+d1 + 20000);
+      var d5 = new Date(+d1 + 90000);
+      var d6 = new Date(+d1 + 10000);
       m.date.push(d1, d2);
 
       var id1 = new mongoose.Types.ObjectId;
@@ -850,77 +853,83 @@ describe('types array', function() {
 
       m.id.push(id1, id2);
 
-      m.num.addToSet(3,4,5);
+      m.num.addToSet(3, 4, 5);
       assert.equal(5, m.num.length);
       m.str.addToSet('four', 'five', 'two');
-      assert.equal(m.str.length,5);
+      assert.equal(m.str.length, 5);
       m.id.addToSet(id2, id3);
-      assert.equal(m.id.length,3);
+      assert.equal(m.id.length, 3);
       m.doc.addToSet(m.doc[0]);
-      assert.equal(m.doc.length,2);
-      m.doc.addToSet({ name: 'Waltz', arr: [1] }, m.doc[0]);
-      assert.equal(m.doc.length,3);
-      assert.equal(m.date.length,2);
+      assert.equal(m.doc.length, 2);
+      m.doc.addToSet({name: 'Waltz', arr: [1]}, m.doc[0]);
+      assert.equal(m.doc.length, 3);
+      assert.equal(m.date.length, 2);
       m.date.addToSet(d1);
-      assert.equal(m.date.length,2);
+      assert.equal(m.date.length, 2);
       m.date.addToSet(d3);
-      assert.equal(m.date.length,3);
+      assert.equal(m.date.length, 3);
 
-      m.save(function(err) {
+      m.save(function (err) {
         assert.ifError(err);
-        M.findById(m, function(err, m) {
+        M.findById(m, function (err, m) {
           assert.ifError(err);
 
-          assert.equal(m.num.length,5);
+          assert.equal(m.num.length, 5);
           assert.ok(~m.num.indexOf(1));
           assert.ok(~m.num.indexOf(2));
           assert.ok(~m.num.indexOf(3));
           assert.ok(~m.num.indexOf(4));
           assert.ok(~m.num.indexOf(5));
 
-          assert.equal(m.str.length,5);
+          assert.equal(m.str.length, 5);
           assert.ok(~m.str.indexOf('one'));
           assert.ok(~m.str.indexOf('two'));
           assert.ok(~m.str.indexOf('tres'));
           assert.ok(~m.str.indexOf('four'));
           assert.ok(~m.str.indexOf('five'));
 
-          assert.equal(m.id.length,3);
+          assert.equal(m.id.length, 3);
           assert.ok(~m.id.indexOf(id1));
           assert.ok(~m.id.indexOf(id2));
           assert.ok(~m.id.indexOf(id3));
 
-          assert.equal(m.date.length,3);
+          assert.equal(m.date.length, 3);
           assert.ok(~m.date.indexOf(d1.toString()));
           assert.ok(~m.date.indexOf(d2.toString()));
           assert.ok(~m.date.indexOf(d3.toString()));
 
-          assert.equal(m.doc.length,3);
-          assert.ok(m.doc.some(function(v) { return v.name === 'Waltz';}));
-          assert.ok(m.doc.some(function(v) { return v.name === 'Dubstep';}));
-          assert.ok(m.doc.some(function(v) { return v.name === 'Polka';}));
+          assert.equal(m.doc.length, 3);
+          assert.ok(m.doc.some(function (v) {
+            return v.name === 'Waltz';
+          }));
+          assert.ok(m.doc.some(function (v) {
+            return v.name === 'Dubstep';
+          }));
+          assert.ok(m.doc.some(function (v) {
+            return v.name === 'Polka';
+          }));
 
           // test single $addToSet
-          m.num.addToSet(3,4,5,6);
-          assert.equal(m.num.length,6);
+          m.num.addToSet(3, 4, 5, 6);
+          assert.equal(m.num.length, 6);
           m.str.addToSet('four', 'five', 'two', 'six');
-          assert.equal(m.str.length,6);
+          assert.equal(m.str.length, 6);
           m.id.addToSet(id2, id3, id4);
-          assert.equal(m.id.length,4);
+          assert.equal(m.id.length, 4);
 
           m.date.addToSet(d1, d3, d4);
-          assert.equal(m.date.length,4);
+          assert.equal(m.date.length, 4);
 
-          m.doc.addToSet(m.doc[0], { name: '8bit' });
-          assert.equal(m.doc.length,4);
+          m.doc.addToSet(m.doc[0], {name: '8bit'});
+          assert.equal(m.doc.length, 4);
 
-          m.save(function(err) {
+          m.save(function (err) {
             assert.ifError(err);
 
-            M.findById(m, function(err, m) {
+            M.findById(m, function (err, m) {
               assert.ifError(err);
 
-              assert.equal(m.num.length,6);
+              assert.equal(m.num.length, 6);
               assert.ok(~m.num.indexOf(1));
               assert.ok(~m.num.indexOf(2));
               assert.ok(~m.num.indexOf(3));
@@ -928,7 +937,7 @@ describe('types array', function() {
               assert.ok(~m.num.indexOf(5));
               assert.ok(~m.num.indexOf(6));
 
-              assert.equal(m.str.length,6);
+              assert.equal(m.str.length, 6);
               assert.ok(~m.str.indexOf('one'));
               assert.ok(~m.str.indexOf('two'));
               assert.ok(~m.str.indexOf('tres'));
@@ -936,46 +945,54 @@ describe('types array', function() {
               assert.ok(~m.str.indexOf('five'));
               assert.ok(~m.str.indexOf('six'));
 
-              assert.equal(m.id.length,4);
+              assert.equal(m.id.length, 4);
               assert.ok(~m.id.indexOf(id1));
               assert.ok(~m.id.indexOf(id2));
               assert.ok(~m.id.indexOf(id3));
               assert.ok(~m.id.indexOf(id4));
 
-              assert.equal(m.date.length,4);
+              assert.equal(m.date.length, 4);
               assert.ok(~m.date.indexOf(d1.toString()));
               assert.ok(~m.date.indexOf(d2.toString()));
               assert.ok(~m.date.indexOf(d3.toString()));
               assert.ok(~m.date.indexOf(d4.toString()));
 
-              assert.equal(m.doc.length,4);
-              assert.ok(m.doc.some(function(v) { return v.name === 'Waltz';}));
-              assert.ok(m.doc.some(function(v) { return v.name === 'Dubstep';}));
-              assert.ok(m.doc.some(function(v) { return v.name === 'Polka';}));
-              assert.ok(m.doc.some(function(v) { return v.name === '8bit';}));
+              assert.equal(m.doc.length, 4);
+              assert.ok(m.doc.some(function (v) {
+                return v.name === 'Waltz';
+              }));
+              assert.ok(m.doc.some(function (v) {
+                return v.name === 'Dubstep';
+              }));
+              assert.ok(m.doc.some(function (v) {
+                return v.name === 'Polka';
+              }));
+              assert.ok(m.doc.some(function (v) {
+                return v.name === '8bit';
+              }));
 
               // test multiple $addToSet
-              m.num.addToSet(7,8);
-              assert.equal(m.num.length,8);
+              m.num.addToSet(7, 8);
+              assert.equal(m.num.length, 8);
               m.str.addToSet('seven', 'eight');
-              assert.equal(m.str.length,8);
+              assert.equal(m.str.length, 8);
               m.id.addToSet(id5, id6);
-              assert.equal(m.id.length,6);
+              assert.equal(m.id.length, 6);
 
               m.date.addToSet(d5, d6);
-              assert.equal(m.date.length,6);
+              assert.equal(m.date.length, 6);
 
-              m.doc.addToSet(m.doc[1], { name: 'BigBeat' }, { name: 'Funk' });
-              assert.equal(m.doc.length,6);
+              m.doc.addToSet(m.doc[1], {name: 'BigBeat'}, {name: 'Funk'});
+              assert.equal(m.doc.length, 6);
 
-              m.save(function(err) {
+              m.save(function (err) {
                 assert.ifError(err);
 
-                M.findById(m, function(err, m) {
+                M.findById(m, function (err, m) {
                   db.close();
                   assert.ifError(err);
 
-                  assert.equal(m.num.length,8);
+                  assert.equal(m.num.length, 8);
                   assert.ok(~m.num.indexOf(1));
                   assert.ok(~m.num.indexOf(2));
                   assert.ok(~m.num.indexOf(3));
@@ -985,7 +1002,7 @@ describe('types array', function() {
                   assert.ok(~m.num.indexOf(7));
                   assert.ok(~m.num.indexOf(8));
 
-                  assert.equal(m.str.length,8);
+                  assert.equal(m.str.length, 8);
                   assert.ok(~m.str.indexOf('one'));
                   assert.ok(~m.str.indexOf('two'));
                   assert.ok(~m.str.indexOf('tres'));
@@ -995,7 +1012,7 @@ describe('types array', function() {
                   assert.ok(~m.str.indexOf('seven'));
                   assert.ok(~m.str.indexOf('eight'));
 
-                  assert.equal(m.id.length,6);
+                  assert.equal(m.id.length, 6);
                   assert.ok(~m.id.indexOf(id1));
                   assert.ok(~m.id.indexOf(id2));
                   assert.ok(~m.id.indexOf(id3));
@@ -1003,7 +1020,7 @@ describe('types array', function() {
                   assert.ok(~m.id.indexOf(id5));
                   assert.ok(~m.id.indexOf(id6));
 
-                  assert.equal(m.date.length,6);
+                  assert.equal(m.date.length, 6);
                   assert.ok(~m.date.indexOf(d1.toString()));
                   assert.ok(~m.date.indexOf(d2.toString()));
                   assert.ok(~m.date.indexOf(d3.toString()));
@@ -1011,13 +1028,25 @@ describe('types array', function() {
                   assert.ok(~m.date.indexOf(d5.toString()));
                   assert.ok(~m.date.indexOf(d6.toString()));
 
-                  assert.equal(m.doc.length,6);
-                  assert.ok(m.doc.some(function(v) { return v.name === 'Waltz';}));
-                  assert.ok(m.doc.some(function(v) { return v.name === 'Dubstep';}));
-                  assert.ok(m.doc.some(function(v) { return v.name === 'Polka';}));
-                  assert.ok(m.doc.some(function(v) { return v.name === '8bit';}));
-                  assert.ok(m.doc.some(function(v) { return v.name === 'BigBeat';}));
-                  assert.ok(m.doc.some(function(v) { return v.name === 'Funk';}));
+                  assert.equal(m.doc.length, 6);
+                  assert.ok(m.doc.some(function (v) {
+                    return v.name === 'Waltz';
+                  }));
+                  assert.ok(m.doc.some(function (v) {
+                    return v.name === 'Dubstep';
+                  }));
+                  assert.ok(m.doc.some(function (v) {
+                    return v.name === 'Polka';
+                  }));
+                  assert.ok(m.doc.some(function (v) {
+                    return v.name === '8bit';
+                  }));
+                  assert.ok(m.doc.some(function (v) {
+                    return v.name === 'BigBeat';
+                  }));
+                  assert.ok(m.doc.some(function (v) {
+                    return v.name === 'Funk';
+                  }));
                   done();
                 });
               });
@@ -1027,9 +1056,9 @@ describe('types array', function() {
       });
     });
 
-    it('handles sub-documents that do not have an _id gh-1973', function(done) {
+    it('handles sub-documents that do not have an _id gh-1973', function (done) {
       var db = start(),
-          e = new Schema({ name: String, arr: [] }, { _id: false }),
+          e = new Schema({name: String, arr: []}, {_id: false}),
           schema = new Schema({
             doc: [e]
           });
@@ -1037,39 +1066,45 @@ describe('types array', function() {
       var M = db.model('gh1973', schema);
       var m = new M;
 
-      m.doc.addToSet({ name: 'Rap' });
-      m.save(function(error, m) {
+      m.doc.addToSet({name: 'Rap'});
+      m.save(function (error, m) {
         assert.ifError(error);
         assert.equal(1, m.doc.length);
         assert.equal('Rap', m.doc[0].name);
-        m.doc.addToSet({ name: 'House' });
+        m.doc.addToSet({name: 'House'});
         assert.equal(2, m.doc.length);
-        m.save(function(error, m) {
+        m.save(function (error, m) {
           assert.ifError(error);
           assert.equal(2, m.doc.length);
-          assert.ok(m.doc.some(function(v) { return v.name === 'Rap'; }));
-          assert.ok(m.doc.some(function(v) { return v.name === 'House'; }));
+          assert.ok(m.doc.some(function (v) {
+            return v.name === 'Rap';
+          }));
+          assert.ok(m.doc.some(function (v) {
+            return v.name === 'House';
+          }));
           db.close(done);
         });
       });
     });
 
-    it('applies setters (gh-3032)', function(done) {
+    it('applies setters (gh-3032)', function (done) {
       var db = start();
-      var ST = db.model('setterArray', Schema({ arr: [{
-        type: String,
-        lowercase: true
-      }] }));
-      var m = new ST({ arr: ["ONE", "TWO"] });
-      m.save(function(err, doc) {
+      var ST = db.model('setterArray', Schema({
+        arr: [{
+          type: String,
+          lowercase: true
+        }]
+      }));
+      var m = new ST({arr: ['ONE', 'TWO']});
+      m.save(function (err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
-        doc.arr.addToSet("THREE");
+        doc.arr.addToSet('THREE');
         assert.strictEqual('one', doc.arr[0]);
         assert.strictEqual('two', doc.arr[1]);
         assert.strictEqual('three', doc.arr[2]);
 
-        doc.save(function(err, doc) {
+        doc.save(function (err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.strictEqual('one', doc.arr[0]);
@@ -1082,37 +1117,37 @@ describe('types array', function() {
     });
   });
 
-  describe('nonAtomicPush()', function() {
-    it('works', function(done) {
+  describe('nonAtomicPush()', function () {
+    it('works', function (done) {
       var db = start();
       var U = db.model('User');
       var ID = mongoose.Types.ObjectId;
 
-      var u = new U({ name: 'banana', pets: [new ID] });
-      assert.equal(u.pets.length,1);
+      var u = new U({name: 'banana', pets: [new ID]});
+      assert.equal(u.pets.length, 1);
       u.pets.nonAtomicPush(new ID);
-      assert.equal(u.pets.length,2);
-      u.save(function(err) {
+      assert.equal(u.pets.length, 2);
+      u.save(function (err) {
         assert.ifError(err);
-        U.findById(u._id, function(err) {
+        U.findById(u._id, function (err) {
           assert.ifError(err);
-          assert.equal(u.pets.length,2);
+          assert.equal(u.pets.length, 2);
           var id0 = u.pets[0];
           var id1 = u.pets[1];
           var id2 = new ID;
           u.pets.pull(id0);
           u.pets.nonAtomicPush(id2);
-          assert.equal(u.pets.length,2);
-          assert.equal(u.pets[0].toString(),id1.toString());
-          assert.equal(u.pets[1].toString(),id2.toString());
-          u.save(function(err) {
+          assert.equal(u.pets.length, 2);
+          assert.equal(u.pets[0].toString(), id1.toString());
+          assert.equal(u.pets[1].toString(), id2.toString());
+          u.save(function (err) {
             assert.ifError(err);
-            U.findById(u._id, function(err) {
+            U.findById(u._id, function (err) {
               db.close();
               assert.ifError(err);
-              assert.equal(u.pets.length,2);
-              assert.equal(u.pets[0].toString(),id1.toString());
-              assert.equal(u.pets[1].toString(),id2.toString());
+              assert.equal(u.pets.length, 2);
+              assert.equal(u.pets[0].toString(), id1.toString());
+              assert.equal(u.pets[1].toString(), id2.toString());
               done();
             });
           });
@@ -1121,14 +1156,14 @@ describe('types array', function() {
     });
   });
 
-  describe('sort()', function() {
-    it('order should be saved', function(done) {
+  describe('sort()', function () {
+    it('order should be saved', function (done) {
       var db = start();
-      var M = db.model('ArraySortOrder', new Schema({ x: [Number] }));
-      var m = new M({ x: [1,4,3,2] });
-      m.save(function(err) {
+      var M = db.model('ArraySortOrder', new Schema({x: [Number]}));
+      var m = new M({x: [1, 4, 3, 2]});
+      m.save(function (err) {
         assert.ifError(err);
-        M.findById(m, function(err, m) {
+        M.findById(m, function (err, m) {
           assert.ifError(err);
 
           assert.equal(1, m.x[0]);
@@ -1138,9 +1173,9 @@ describe('types array', function() {
 
           m.x.sort();
 
-          m.save(function(err) {
+          m.save(function (err) {
             assert.ifError(err);
-            M.findById(m, function(err, m) {
+            M.findById(m, function (err, m) {
               assert.ifError(err);
 
               assert.equal(1, m.x[0]);
@@ -1148,13 +1183,13 @@ describe('types array', function() {
               assert.equal(3, m.x[2]);
               assert.equal(4, m.x[3]);
 
-              m.x.sort(function(a,b) {
+              m.x.sort(function (a, b) {
                 return b > a;
               });
 
-              m.save(function(err) {
+              m.save(function (err) {
                 assert.ifError(err);
-                M.findById(m, function(err, m) {
+                M.findById(m, function (err, m) {
                   assert.ifError(err);
 
                   assert.equal(4, m.x[0]);
@@ -1171,37 +1206,41 @@ describe('types array', function() {
     });
   });
 
-  describe('set()', function() {
+  describe('set()', function () {
     var db, N, S, B, M, D, ST;
 
     function save(doc, cb) {
-      doc.save(function(err) {
-        if (err) return cb(err);
+      doc.save(function (err) {
+        if (err) {
+          return cb(err);
+        }
         doc.constructor.findById(doc._id, cb);
       });
     }
 
-    before(function(done) {
+    before(function (done) {
       db = start();
-      N = db.model('arraySet', Schema({ arr: [Number] }));
-      S = db.model('arraySetString', Schema({ arr: [String] }));
-      B = db.model('arraySetBuffer', Schema({ arr: [Buffer] }));
-      M = db.model('arraySetMixed', Schema({ arr: [] }));
-      D = db.model('arraySetSubDocs', Schema({ arr: [{ name: String}] }));
-      ST = db.model('arrayWithSetters', Schema({ arr: [{
-        type: String,
-        lowercase: true
-      }] }));
+      N = db.model('arraySet', Schema({arr: [Number]}));
+      S = db.model('arraySetString', Schema({arr: [String]}));
+      B = db.model('arraySetBuffer', Schema({arr: [Buffer]}));
+      M = db.model('arraySetMixed', Schema({arr: []}));
+      D = db.model('arraySetSubDocs', Schema({arr: [{name: String}]}));
+      ST = db.model('arrayWithSetters', Schema({
+        arr: [{
+          type: String,
+          lowercase: true
+        }]
+      }));
       done();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('works combined with other ops', function(done) {
-      var m = new N({ arr: [3,4,5,6] });
-      save(m, function(err, doc) {
+    it('works combined with other ops', function (done) {
+      var m = new N({arr: [3, 4, 5, 6]});
+      save(m, function (err, doc) {
         assert.ifError(err);
 
         assert.equal(4, doc.arr.length);
@@ -1211,7 +1250,7 @@ describe('types array', function() {
         assert.equal(10, doc.arr[2]);
         assert.equal(20, doc.arr[4]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.equal(3, doc.arr[0]);
@@ -1232,7 +1271,7 @@ describe('types array', function() {
           assert.equal(6, doc.arr[2]);
           assert.equal(99, doc.arr[3]);
 
-          save(doc, function(err, doc) {
+          save(doc, function (err, doc) {
             assert.ifError(err);
             assert.equal(4, doc.arr.length);
             assert.equal(3, doc.arr[0]);
@@ -1247,9 +1286,9 @@ describe('types array', function() {
       // after this works go back to finishing doc.populate() branch
     });
 
-    it('works with numbers', function(done) {
-      var m = new N({ arr: [3,4,5,6] });
-      save(m, function(err, doc) {
+    it('works with numbers', function (done) {
+      var m = new N({arr: [3, 4, 5, 6]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.set(2, 10);
@@ -1259,7 +1298,7 @@ describe('types array', function() {
         assert.equal(5, doc.arr.length);
         assert.equal(11, doc.arr[4]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.equal(3, doc.arr[0]);
@@ -1269,12 +1308,12 @@ describe('types array', function() {
           assert.equal(11, doc.arr[4]);
 
           // casting + setting beyond current array length
-          doc.arr.set(8, "1");
+          doc.arr.set(8, '1');
           assert.equal(9, doc.arr.length);
           assert.strictEqual(1, doc.arr[8]);
           assert.equal(undefined, doc.arr[7]);
 
-          save(doc, function(err, doc) {
+          save(doc, function (err, doc) {
             assert.ifError(err);
 
             assert.equal(9, doc.arr.length);
@@ -1293,9 +1332,9 @@ describe('types array', function() {
       });
     });
 
-    it('works with strings', function(done) {
-      var m = new S({ arr: [3,4,5,6] });
-      save(m, function(err, doc) {
+    it('works with strings', function (done) {
+      var m = new S({arr: [3, 4, 5, 6]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal('4', doc.arr.length);
         doc.arr.set(2, 10);
@@ -1305,7 +1344,7 @@ describe('types array', function() {
         assert.equal(5, doc.arr.length);
         assert.equal('11', doc.arr[4]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.equal('3', doc.arr[0]);
@@ -1315,12 +1354,12 @@ describe('types array', function() {
           assert.equal('11', doc.arr[4]);
 
           // casting + setting beyond current array length
-          doc.arr.set(8, "yo");
+          doc.arr.set(8, 'yo');
           assert.equal(9, doc.arr.length);
-          assert.strictEqual("yo", doc.arr[8]);
+          assert.strictEqual('yo', doc.arr[8]);
           assert.equal(undefined, doc.arr[7]);
 
-          save(doc, function(err, doc) {
+          save(doc, function (err, doc) {
             assert.ifError(err);
 
             assert.equal('9', doc.arr.length);
@@ -1339,48 +1378,48 @@ describe('types array', function() {
       });
     });
 
-    it('works with buffers', function(done) {
-      var m = new B({ arr: [[0], new Buffer(1)] });
-      save(m, function(err, doc) {
+    it('works with buffers', function (done) {
+      var m = new B({arr: [[0], new Buffer(1)]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         assert.ok(doc.arr[0].isMongooseBuffer);
         assert.ok(doc.arr[1].isMongooseBuffer);
-        doc.arr.set(1, "nice");
+        doc.arr.set(1, 'nice');
         assert.equal(2, doc.arr.length);
         assert.ok(doc.arr[1].isMongooseBuffer);
-        assert.equal("nice", doc.arr[1].toString('utf8'));
+        assert.equal('nice', doc.arr[1].toString('utf8'));
         doc.arr.set(doc.arr.length, [11]);
         assert.equal(3, doc.arr.length);
         assert.equal(11, doc.arr[2][0]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.ok(doc.arr[0].isMongooseBuffer);
           assert.ok(doc.arr[1].isMongooseBuffer);
           assert.ok(doc.arr[2].isMongooseBuffer);
           assert.equal('\u0000', doc.arr[0].toString());
-          assert.equal("nice", doc.arr[1].toString());
+          assert.equal('nice', doc.arr[1].toString());
           assert.equal(11, doc.arr[2][0]);
           done();
         });
       });
     });
 
-    it('works with mixed', function(done) {
-      var m = new M({ arr: [3,{x:1},'yes', [5]] });
-      save(m, function(err, doc) {
+    it('works with mixed', function (done) {
+      var m = new M({arr: [3, {x: 1}, 'yes', [5]]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.set(2, null);
         assert.equal(4, doc.arr.length);
         assert.equal(null, doc.arr[2]);
-        doc.arr.set(doc.arr.length, "last");
+        doc.arr.set(doc.arr.length, 'last');
         assert.equal(5, doc.arr.length);
-        assert.equal("last", doc.arr[4]);
+        assert.equal('last', doc.arr[4]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
 
           assert.equal(5, doc.arr.length);
@@ -1389,7 +1428,7 @@ describe('types array', function() {
           assert.equal(null, doc.arr[2]);
           assert.ok(Array.isArray(doc.arr[3]));
           assert.equal(5, doc.arr[3][0]);
-          assert.equal("last", doc.arr[4]);
+          assert.equal('last', doc.arr[4]);
 
           doc.arr.set(8, Infinity);
           assert.equal(9, doc.arr.length);
@@ -1400,7 +1439,7 @@ describe('types array', function() {
           assert.equal('', doc.arr[9].toString());
           assert.equal(10, doc.arr.length);
 
-          save(doc, function(err, doc) {
+          save(doc, function (err, doc) {
             assert.ifError(err);
 
             assert.equal(10, doc.arr.length);
@@ -1409,7 +1448,7 @@ describe('types array', function() {
             assert.equal(null, doc.arr[2]);
             assert.ok(Array.isArray(doc.arr[3]));
             assert.equal(5, doc.arr[3][0]);
-            assert.equal("last", doc.arr[4]);
+            assert.equal('last', doc.arr[4]);
             assert.strictEqual(null, doc.arr[5]);
             assert.strictEqual(null, doc.arr[6]);
             assert.strictEqual(null, doc.arr[7]);
@@ -1423,84 +1462,82 @@ describe('types array', function() {
       });
     });
 
-    it('works with sub-docs', function(done) {
-      var m = new D({ arr: [{name:'aaron'}, {name:'moombahton '}] });
-      save(m, function(err, doc) {
+    it('works with sub-docs', function (done) {
+      var m = new D({arr: [{name: 'aaron'}, {name: 'moombahton '}]});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
-        doc.arr.set(0, {name:'vdrums'});
+        doc.arr.set(0, {name: 'vdrums'});
         assert.equal(2, doc.arr.length);
         assert.equal('vdrums', doc.arr[0].name);
-        doc.arr.set(doc.arr.length, {name:"Restrepo"});
+        doc.arr.set(doc.arr.length, {name: 'Restrepo'});
         assert.equal(3, doc.arr.length);
-        assert.equal("Restrepo", doc.arr[2].name);
+        assert.equal('Restrepo', doc.arr[2].name);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
 
           // validate
           assert.equal(3, doc.arr.length);
           assert.equal('vdrums', doc.arr[0].name);
-          assert.equal("moombahton ", doc.arr[1].name);
-          assert.equal("Restrepo", doc.arr[2].name);
+          assert.equal('moombahton ', doc.arr[1].name);
+          assert.equal('Restrepo', doc.arr[2].name);
 
-          doc.arr.set(10, { name: 'temple of doom' });
+          doc.arr.set(10, {name: 'temple of doom'});
           assert.equal(11, doc.arr.length);
           assert.equal('temple of doom', doc.arr[10].name);
           assert.equal(null, doc.arr[9]);
 
-          save(doc, function(err, doc) {
+          save(doc, function (err, doc) {
             assert.ifError(err);
 
             // validate
             assert.equal(11, doc.arr.length);
             assert.equal('vdrums', doc.arr[0].name);
-            assert.equal("moombahton ", doc.arr[1].name);
-            assert.equal("Restrepo", doc.arr[2].name);
+            assert.equal('moombahton ', doc.arr[1].name);
+            assert.equal('Restrepo', doc.arr[2].name);
             assert.equal(null, doc.arr[3]);
             assert.equal(null, doc.arr[9]);
             assert.equal('temple of doom', doc.arr[10].name);
 
             doc.arr.remove(doc.arr[0]);
-            doc.arr.set(7, { name: 7 });
-            assert.strictEqual("7", doc.arr[7].name);
+            doc.arr.set(7, {name: 7});
+            assert.strictEqual('7', doc.arr[7].name);
             assert.equal(10, doc.arr.length);
 
-            save(doc, function(err, doc) {
+            save(doc, function (err, doc) {
               assert.ifError(err);
 
               assert.equal(10, doc.arr.length);
-              assert.equal("moombahton ", doc.arr[0].name);
-              assert.equal("Restrepo", doc.arr[1].name);
+              assert.equal('moombahton ', doc.arr[0].name);
+              assert.equal('Restrepo', doc.arr[1].name);
               assert.equal(null, doc.arr[2]);
               assert.ok(doc.arr[7]);
-              assert.strictEqual("7", doc.arr[7].name);
+              assert.strictEqual('7', doc.arr[7].name);
               assert.equal(null, doc.arr[8]);
               assert.equal('temple of doom', doc.arr[9].name);
 
               done();
-
             });
           });
-
         });
       });
     });
 
-    it('applies setters (gh-3032)', function(done) {
-      var m = new ST({ arr: ["ONE", "TWO"] });
-      save(m, function(err, doc) {
+    it('applies setters (gh-3032)', function (done) {
+      var m = new ST({arr: ['ONE', 'TWO']});
+      save(m, function (err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
-        doc.arr.set(0, "THREE");
+        doc.arr.set(0, 'THREE');
         assert.strictEqual('three', doc.arr[0]);
         assert.strictEqual('two', doc.arr[1]);
-        doc.arr.set(doc.arr.length, "FOUR");
+        doc.arr.set(doc.arr.length, 'FOUR');
         assert.strictEqual('three', doc.arr[0]);
         assert.strictEqual('two', doc.arr[1]);
         assert.strictEqual('four', doc.arr[2]);
 
-        save(doc, function(err, doc) {
+        save(doc, function (err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.strictEqual('three', doc.arr[0]);
@@ -1513,25 +1550,25 @@ describe('types array', function() {
     });
   });
 
-  describe('setting a doc array', function() {
-    it('should adjust path positions', function(done) {
+  describe('setting a doc array', function () {
+    it('should adjust path positions', function (done) {
       var db = start();
 
       var D = db.model('subDocPositions', new Schema({
-        em1: [new Schema({ name: String })]
+        em1: [new Schema({name: String})]
       }));
 
       var d = new D({
         em1: [
-              { name: 'pos0' },
-             { name: 'pos1' },
-             { name: 'pos2' }
+          {name: 'pos0'},
+          {name: 'pos1'},
+          {name: 'pos2'}
         ]
       });
 
-      d.save(function(err) {
+      d.save(function (err) {
         assert.ifError(err);
-        D.findById(d, function(err, d) {
+        D.findById(d, function (err, d) {
           assert.ifError(err);
 
           var n = d.em1.slice();
@@ -1542,13 +1579,13 @@ describe('types array', function() {
           x = x.filter(Boolean);
           d.em1 = x;
 
-          d.save(function(err) {
+          d.save(function (err) {
             assert.ifError(err);
-            D.findById(d, function(err, d) {
+            D.findById(d, function (err, d) {
               db.close();
               assert.ifError(err);
-              assert.equal(d.em1[0].name,'position two');
-              assert.equal(d.em1[1].name,'pos1');
+              assert.equal(d.em1[0].name, 'position two');
+              assert.equal(d.em1[1].name, 'pos1');
               done();
             });
           });
@@ -1557,8 +1594,8 @@ describe('types array', function() {
     });
   });
 
-  describe('paths with similar names', function() {
-    it('should be saved', function(done) {
+  describe('paths with similar names', function () {
+    it('should be saved', function (done) {
       var db = start();
 
       var D = db.model('similarPathNames', new Schema({
@@ -1566,30 +1603,30 @@ describe('types array', function() {
           role: String,
           roles: [String]
         },
-        em: [new Schema({ name: String })]
+        em: [new Schema({name: String})]
       }));
 
       var d = new D({
-        account: { role: 'teacher', roles: ['teacher', 'admin'] },
-        em: [{ name: 'bob' }]
+        account: {role: 'teacher', roles: ['teacher', 'admin']},
+        em: [{name: 'bob'}]
       });
 
-      d.save(function(err) {
+      d.save(function (err) {
         assert.ifError(err);
-        D.findById(d, function(err, d) {
+        D.findById(d, function (err, d) {
           assert.ifError(err);
 
           d.account.role = 'president';
           d.account.roles = ['president', 'janitor'];
           d.em[0].name = 'memorable';
-          d.em = [{ name: 'frida' }];
+          d.em = [{name: 'frida'}];
 
-          d.save(function(err) {
+          d.save(function (err) {
             assert.ifError(err);
-            D.findById(d, function(err, d) {
+            D.findById(d, function (err, d) {
               db.close();
               assert.ifError(err);
-              assert.equal(d.account.role,'president');
+              assert.equal(d.account.role, 'president');
               assert.equal(d.account.roles.length, 2);
               assert.equal(d.account.roles[0], 'president');
               assert.equal(d.account.roles[1], 'janitor');
@@ -1603,20 +1640,20 @@ describe('types array', function() {
     });
   });
 
-  describe('of number', function() {
-    it('allows nulls', function(done) {
+  describe('of number', function () {
+    it('allows nulls', function (done) {
       var db = start();
-      var schema = new Schema({ x: [Number] }, { collection: 'nullsareallowed' + random() });
+      var schema = new Schema({x: [Number]}, {collection: 'nullsareallowed' + random()});
       var M = db.model('nullsareallowed', schema);
       var m;
 
-      m = new M({ x: [1, null, 3] });
-      m.save(function(err) {
+      m = new M({x: [1, null, 3]});
+      m.save(function (err) {
         assert.ifError(err);
 
         // undefined is not allowed
-        m = new M({ x: [1, undefined, 3] });
-        m.save(function(err) {
+        m = new M({x: [1, undefined, 3]});
+        m.save(function (err) {
           db.close();
           assert.ok(err);
           done();
@@ -1625,24 +1662,24 @@ describe('types array', function() {
     });
   });
 
-  it('modifying subdoc props and manipulating the array works (gh-842)', function(done) {
+  it('modifying subdoc props and manipulating the array works (gh-842)', function (done) {
     var db = start();
-    var schema = new Schema({ em: [new Schema({ username: String })]});
+    var schema = new Schema({em: [new Schema({username: String})]});
     var M = db.model('modifyingSubDocAndPushing', schema);
-    var m = new M({ em: [ { username: 'Arrietty' }]});
+    var m = new M({em: [{username: 'Arrietty'}]});
 
-    m.save(function(err) {
+    m.save(function (err) {
       assert.ifError(err);
-      M.findById(m, function(err, m) {
+      M.findById(m, function (err, m) {
         assert.ifError(err);
         assert.equal(m.em[0].username, 'Arrietty');
 
         m.em[0].username = 'Shawn';
-        m.em.push({ username: 'Homily' });
-        m.save(function(err) {
+        m.em.push({username: 'Homily'});
+        m.save(function (err) {
           assert.ifError(err);
 
-          M.findById(m, function(err, m) {
+          M.findById(m, function (err, m) {
             assert.ifError(err);
             assert.equal(m.em.length, 2);
             assert.equal(m.em[0].username, 'Shawn');
@@ -1650,10 +1687,10 @@ describe('types array', function() {
 
             m.em[0].username = 'Arrietty';
             m.em[1].remove();
-            m.save(function(err) {
+            m.save(function (err) {
               assert.ifError(err);
 
-              M.findById(m, function(err, m) {
+              M.findById(m, function (err, m) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(m.em.length, 1);
@@ -1667,25 +1704,25 @@ describe('types array', function() {
     });
   });
 
-  it('pushing top level arrays and subarrays works (gh-1073)', function(done) {
+  it('pushing top level arrays and subarrays works (gh-1073)', function (done) {
     var db = start();
-    var schema = new Schema({ em: [new Schema({ sub: [String] })]});
+    var schema = new Schema({em: [new Schema({sub: [String]})]});
     var M = db.model('gh1073', schema);
-    var m = new M({ em: [ { sub: [] }]});
-    m.save(function() {
-      M.findById(m, function(err, m) {
+    var m = new M({em: [{sub: []}]});
+    m.save(function () {
+      M.findById(m, function (err, m) {
         assert.ifError(err);
 
-        m.em[m.em.length - 1].sub.push("a");
-        m.em.push({ sub: [] });
+        m.em[m.em.length - 1].sub.push('a');
+        m.em.push({sub: []});
 
         assert.equal(2, m.em.length);
         assert.equal(1, m.em[0].sub.length);
 
-        m.save(function(err) {
+        m.save(function (err) {
           assert.ifError(err);
 
-          M.findById(m, function(err, m) {
+          M.findById(m, function (err, m) {
             assert.ifError(err);
             assert.equal(2, m.em.length);
             assert.equal(1, m.em[0].sub.length);
@@ -1697,8 +1734,8 @@ describe('types array', function() {
     });
   });
 
-  describe('default type', function() {
-    it('casts to Mixed', function(done) {
+  describe('default type', function () {
+    it('casts to Mixed', function (done) {
       var db = start(),
           DefaultArraySchema = new Schema({
             num1: Array,
@@ -1717,9 +1754,9 @@ describe('types array', function() {
           threw2 = false;
 
       try {
-        arr.num1.push({ x: 1 });
+        arr.num1.push({x: 1});
         arr.num1.push(9);
-        arr.num1.push("woah");
+        arr.num1.push('woah');
       } catch (err) {
         threw1 = true;
       }
@@ -1727,9 +1764,9 @@ describe('types array', function() {
       assert.equal(threw1, false);
 
       try {
-        arr.num2.push({ x: 1 });
+        arr.num2.push({x: 1});
         arr.num2.push(9);
-        arr.num2.push("woah");
+        arr.num2.push('woah');
       } catch (err) {
         threw2 = true;
       }
@@ -1739,17 +1776,17 @@ describe('types array', function() {
     });
   });
 
-  describe('removing from an array atomically using MongooseArray#remove', function() {
+  describe('removing from an array atomically using MongooseArray#remove', function () {
     var db;
     var B;
 
-    before(function(done) {
+    before(function (done) {
       var schema = Schema({
         numbers: ['number'],
-        numberIds: [{ _id: 'number', name: 'string' }],
-        stringIds: [{ _id: 'string', name: 'string' }],
-        bufferIds: [{ _id: 'buffer', name: 'string' }],
-        oidIds:    [{ name: 'string' }]
+        numberIds: [{_id: 'number', name: 'string'}],
+        stringIds: [{_id: 'string', name: 'string'}],
+        bufferIds: [{_id: 'buffer', name: 'string'}],
+        oidIds: [{name: 'string'}]
       });
 
       db = start();
@@ -1757,34 +1794,34 @@ describe('types array', function() {
       done();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('works', function(done) {
+    it('works', function (done) {
       var post = new B;
       post.numbers.push(1, 2, 3);
 
-      post.save(function(err) {
+      post.save(function (err) {
         assert.ifError(err);
 
-        B.findById(post._id, function(err, doc) {
+        B.findById(post._id, function (err, doc) {
           assert.ifError(err);
 
           doc.numbers.remove('1');
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
 
-            B.findById(post.get('_id'), function(err, doc) {
+            B.findById(post.get('_id'), function (err, doc) {
               assert.ifError(err);
 
               assert.equal(doc.numbers.length, 2);
               doc.numbers.remove('2', '3');
 
-              doc.save(function(err) {
+              doc.save(function (err) {
                 assert.ifError(err);
 
-                B.findById(post._id, function(err, doc) {
+                B.findById(post._id, function (err, doc) {
                   assert.ifError(err);
                   assert.equal(0, doc.numbers.length);
                   done();
@@ -1796,23 +1833,23 @@ describe('types array', function() {
       });
     });
 
-    describe('with subdocs', function() {
+    describe('with subdocs', function () {
       function docs(arr) {
-        return arr.map(function(val) {
-          return { _id: val };
+        return arr.map(function (val) {
+          return {_id: val};
         });
       }
 
-      it('supports passing strings', function(done) {
-        var post = new B({ stringIds: docs('a b c d'.split(' ')) });
-        post.save(function(err) {
+      it('supports passing strings', function (done) {
+        var post = new B({stringIds: docs('a b c d'.split(' '))});
+        post.save(function (err) {
           assert.ifError(err);
-          B.findById(post, function(err, post) {
+          B.findById(post, function (err, post) {
             assert.ifError(err);
             post.stringIds.remove('b');
-            post.save(function(err) {
+            post.save(function (err) {
               assert.ifError(err);
-              B.findById(post, function(err, post) {
+              B.findById(post, function (err, post) {
                 assert.ifError(err);
                 assert.equal(3, post.stringIds.length);
                 assert.ok(!post.stringIds.id('b'));
@@ -1822,16 +1859,16 @@ describe('types array', function() {
           });
         });
       });
-      it('supports passing numbers', function(done) {
-        var post = new B({ numberIds: docs([1,2,3,4]) });
-        post.save(function(err) {
+      it('supports passing numbers', function (done) {
+        var post = new B({numberIds: docs([1, 2, 3, 4])});
+        post.save(function (err) {
           assert.ifError(err);
-          B.findById(post, function(err, post) {
+          B.findById(post, function (err, post) {
             assert.ifError(err);
-            post.numberIds.remove(2,4);
-            post.save(function(err) {
+            post.numberIds.remove(2, 4);
+            post.save(function (err) {
               assert.ifError(err);
-              B.findById(post, function(err, post) {
+              B.findById(post, function (err, post) {
                 assert.ifError(err);
                 assert.equal(2, post.numberIds.length);
                 assert.ok(!post.numberIds.id(2));
@@ -1842,20 +1879,20 @@ describe('types array', function() {
           });
         });
       });
-      it('supports passing objectids', function(done) {
+      it('supports passing objectids', function (done) {
         var OID = mongoose.Types.ObjectId;
         var a = new OID;
         var b = new OID;
         var c = new OID;
-        var post = new B({ oidIds: docs([a,b,c]) });
-        post.save(function(err) {
+        var post = new B({oidIds: docs([a, b, c])});
+        post.save(function (err) {
           assert.ifError(err);
-          B.findById(post, function(err, post) {
+          B.findById(post, function (err, post) {
             assert.ifError(err);
-            post.oidIds.remove(a,c);
-            post.save(function(err) {
+            post.oidIds.remove(a, c);
+            post.save(function (err) {
               assert.ifError(err);
-              B.findById(post, function(err, post) {
+              B.findById(post, function (err, post) {
                 assert.ifError(err);
                 assert.equal(1, post.oidIds.length);
                 assert.ok(!post.oidIds.id(a));
@@ -1866,16 +1903,16 @@ describe('types array', function() {
           });
         });
       });
-      it('supports passing buffers', function(done) {
-        var post = new B({ bufferIds: docs(['a','b','c','d']) });
-        post.save(function(err) {
+      it('supports passing buffers', function (done) {
+        var post = new B({bufferIds: docs(['a', 'b', 'c', 'd'])});
+        post.save(function (err) {
           assert.ifError(err);
-          B.findById(post, function(err, post) {
+          B.findById(post, function (err, post) {
             assert.ifError(err);
             post.bufferIds.remove(new Buffer('a'));
-            post.save(function(err) {
+            post.save(function (err) {
               assert.ifError(err);
-              B.findById(post, function(err, post) {
+              B.findById(post, function (err, post) {
                 assert.ifError(err);
                 assert.equal(3, post.bufferIds.length);
                 assert.ok(!post.bufferIds.id(new Buffer('a')));
diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js
index b2ac66d0e02..faca4d4b60f 100644
--- a/test/types.buffer.test.js
+++ b/test/types.buffer.test.js
@@ -16,14 +16,14 @@ function valid(v) {
 
 var subBuf = new Schema({
   name: String,
-  buf: { type: Buffer, validate: [valid, 'valid failed'], required: true }
+  buf: {type: Buffer, validate: [valid, 'valid failed'], required: true}
 });
 
 var UserBuffer = new Schema({
   name: String,
   serial: Buffer,
   array: [Buffer],
-  required: { type: Buffer, required: true, index: true },
+  required: {type: Buffer, required: true, index: true},
   sub: [subBuf]
 });
 
@@ -35,9 +35,8 @@ var UserBuffer = new Schema({
  * Test.
  */
 
-describe('types.buffer', function() {
-
-  it('test that a mongoose buffer behaves and quacks like a buffer', function(done) {
+describe('types.buffer', function () {
+  it('test that a mongoose buffer behaves and quacks like a buffer', function (done) {
     var a = new MongooseBuffer;
 
     assert.ok(a instanceof Buffer);
@@ -45,7 +44,7 @@ describe('types.buffer', function() {
     assert.equal(true, Buffer.isBuffer(a));
 
     a = new MongooseBuffer([195, 188, 98, 101, 114]);
-    var b = new MongooseBuffer("buffer shtuffs are neat");
+    var b = new MongooseBuffer('buffer shtuffs are neat');
     var c = new MongooseBuffer('aGVsbG8gd29ybGQ=', 'base64');
     var d = new MongooseBuffer(0);
 
@@ -56,40 +55,40 @@ describe('types.buffer', function() {
     done();
   });
 
-  it('buffer validation', function(done) {
+  it('buffer validation', function (done) {
     var db = start(),
         User = db.model('UserBuffer', UserBuffer, 'usersbuffer_' + random());
 
-    User.on('index', function() {
+    User.on('index', function () {
       var t = new User({
         name: 'test validation'
       });
 
-      t.validate(function(err) {
-        assert.equal(err.message,'UserBuffer validation failed');
-        assert.equal(err.errors.required.kind,'required');
-        t.required = {x:[20]};
-        t.save(function(err) {
+      t.validate(function (err) {
+        assert.equal(err.message, 'UserBuffer validation failed');
+        assert.equal(err.errors.required.kind, 'required');
+        t.required = {x: [20]};
+        t.save(function (err) {
           assert.ok(err);
           assert.equal(err.name, 'ValidationError');
           assert.equal(err.errors.required.name, 'CastError');
           assert.equal(err.errors.required.kind, 'Buffer');
           assert.equal(err.errors.required.message, 'Cast to Buffer failed for value "[object Object]" at path "required"');
-          assert.deepEqual(err.errors.required.value, {x:[20]});
-          t.required = new Buffer("hello");
-
-          t.sub.push({ name: 'Friday Friday' });
-          t.save(function(err) {
-            assert.equal(err.message,'UserBuffer validation failed');
-            assert.equal(err.errors['sub.0.buf'].kind,'required');
-            t.sub[0].buf = new Buffer("well well");
-            t.save(function(err) {
-              assert.equal(err.message,'UserBuffer validation failed');
-              assert.equal(err.errors['sub.0.buf'].kind,'user defined');
-              assert.equal(err.errors['sub.0.buf'].message,'valid failed');
-
-              t.sub[0].buf = new Buffer("well well well");
-              t.validate(function(err) {
+          assert.deepEqual(err.errors.required.value, {x: [20]});
+          t.required = new Buffer('hello');
+
+          t.sub.push({name: 'Friday Friday'});
+          t.save(function (err) {
+            assert.equal(err.message, 'UserBuffer validation failed');
+            assert.equal(err.errors['sub.0.buf'].kind, 'required');
+            t.sub[0].buf = new Buffer('well well');
+            t.save(function (err) {
+              assert.equal(err.message, 'UserBuffer validation failed');
+              assert.equal(err.errors['sub.0.buf'].kind, 'user defined');
+              assert.equal(err.errors['sub.0.buf'].message, 'valid failed');
+
+              t.sub[0].buf = new Buffer('well well well');
+              t.validate(function (err) {
                 db.close();
                 assert.ifError(err);
                 done();
@@ -101,11 +100,11 @@ describe('types.buffer', function() {
     });
   });
 
-  it('buffer storage', function(done) {
+  it('buffer storage', function (done) {
     var db = start(),
         User = db.model('UserBuffer', UserBuffer, 'usersbuffer_' + random());
 
-    User.on('index', function() {
+    User.on('index', function () {
       var sampleBuffer = new Buffer([123, 223, 23, 42, 11]);
 
       var tj = new User({
@@ -114,9 +113,9 @@ describe('types.buffer', function() {
         required: new Buffer(sampleBuffer)
       });
 
-      tj.save(function(err) {
+      tj.save(function (err) {
         assert.ifError(err);
-        User.find({}, function(err, users) {
+        User.find({}, function (err, users) {
           db.close();
           assert.ifError(err);
           assert.equal(users.length, 1);
@@ -132,11 +131,11 @@ describe('types.buffer', function() {
     });
   });
 
-  it('test write markModified', function(done) {
+  it('test write markModified', function (done) {
     var db = start(),
         User = db.model('UserBuffer', UserBuffer, 'usersbuffer_' + random());
 
-    User.on('index', function() {
+    User.on('index', function () {
       var sampleBuffer = new Buffer([123, 223, 23, 42, 11]);
 
       var tj = new User({
@@ -145,16 +144,16 @@ describe('types.buffer', function() {
         required: sampleBuffer
       });
 
-      tj.save(function(err) {
+      tj.save(function (err) {
         assert.ifError(err);
 
         tj.serial.write('aa', 1, 'ascii');
         assert.equal(true, tj.isModified('serial'));
 
-        tj.save(function(err) {
+        tj.save(function (err) {
           assert.ifError(err);
 
-          User.findById(tj._id, function(err, user) {
+          User.findById(tj._id, function (err, user) {
             db.close();
             assert.ifError(err);
 
@@ -178,55 +177,55 @@ describe('types.buffer', function() {
 
             // buffer method tests
             var fns = {
-              'writeUInt8': function() {
+              writeUInt8: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt8(0x3, 0, 'big');
                 is(tj);
               },
-              'writeUInt16': function() {
+              writeUInt16: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt16(0xbeef, 0, 'little');
                 is(tj);
               },
-              'writeUInt16LE': function() {
+              writeUInt16LE: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt16LE(0xbeef, 0);
                 is(tj);
               },
-              'writeUInt16BE': function() {
+              writeUInt16BE: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt16BE(0xbeef, 0);
                 is(tj);
               },
-              'writeUInt32': function() {
+              writeUInt32: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt32(0xfeedface, 0, 'little');
                 is(tj);
               },
-              'writeUInt32LE': function() {
+              writeUInt32LE: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt32LE(0xfeedface, 0);
                 is(tj);
               },
-              'writeUInt32BE': function() {
+              writeUInt32BE: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt32BE(0xfeedface, 0);
                 is(tj);
               },
-              'writeInt8': function() {
+              writeInt8: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt8(-5, 0, 'big');
                 is(tj);
               },
-              'writeInt16': function() {
+              writeInt16: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt16(0x0023, 2, 'little');
@@ -234,7 +233,7 @@ describe('types.buffer', function() {
                 assert.equal(tj.required[2], 0x23);
                 assert.equal(tj.required[3], 0x00);
               },
-              'writeInt16LE': function() {
+              writeInt16LE: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt16LE(0x0023, 2);
@@ -242,13 +241,13 @@ describe('types.buffer', function() {
                 assert.equal(tj.required[2], 0x23);
                 assert.equal(tj.required[3], 0x00);
               },
-              'writeInt16BE': function() {
+              writeInt16BE: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt16BE(0x0023, 2);
                 is(tj);
               },
-              'writeInt32': function() {
+              writeInt32: function () {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt32(0x23, 0, 'big');
@@ -259,14 +258,14 @@ describe('types.buffer', function() {
                 assert.equal(tj.required[3], 0x23);
                 tj.required = new Buffer(8);
               },
-              'writeInt32LE': function() {
+              writeInt32LE: function () {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
                 tj.required.writeInt32LE(0x23, 0);
                 is(tj);
               },
-              'writeInt32BE': function() {
+              writeInt32BE: function () {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
@@ -277,7 +276,7 @@ describe('types.buffer', function() {
                 assert.equal(tj.required[2], 0x00);
                 assert.equal(tj.required[3], 0x23);
               },
-              'writeFloat': function() {
+              writeFloat: function () {
                 tj.required = new Buffer(16);
                 reset(tj);
                 not(tj);
@@ -292,35 +291,35 @@ describe('types.buffer', function() {
                 assert.equal(tj.required[6], 0xff);
                 assert.equal(tj.required[7], 0xff);
               },
-              'writeFloatLE': function() {
+              writeFloatLE: function () {
                 tj.required = new Buffer(16);
                 reset(tj);
                 not(tj);
                 tj.required.writeFloatLE(2.225073858507201e-308, 0);
                 is(tj);
               },
-              'writeFloatBE': function() {
+              writeFloatBE: function () {
                 tj.required = new Buffer(16);
                 reset(tj);
                 not(tj);
                 tj.required.writeFloatBE(2.225073858507201e-308, 0);
                 is(tj);
               },
-              'writeDoubleLE': function() {
+              writeDoubleLE: function () {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
                 tj.required.writeDoubleLE(0xdeadbeefcafebabe, 0);
                 is(tj);
               },
-              'writeDoubleBE': function() {
+              writeDoubleBE: function () {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
                 tj.required.writeDoubleBE(0xdeadbeefcafebabe, 0);
                 is(tj);
               },
-              'fill': function() {
+              fill: function () {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
@@ -330,7 +329,7 @@ describe('types.buffer', function() {
                   assert.strictEqual(tj.required[i], 0);
                 }
               },
-              'set': function() {
+              set: function () {
                 reset(tj);
                 not(tj);
                 tj.required.set(0, 1);
@@ -357,19 +356,19 @@ describe('types.buffer', function() {
     function reset(model) {
       // internal
       model.$__.activePaths.clear('modify');
-      model.schema.requiredPaths().forEach(function(path) {
+      model.schema.requiredPaths().forEach(function (path) {
         model.$__.activePaths.require(path);
       });
     }
   });
 
-  it('can be set to null', function(done) {
+  it('can be set to null', function (done) {
     var db = start(),
         User = db.model('UserBuffer', UserBuffer, 'usersbuffer_' + random());
-    var user = new User({ array: [null], required: new Buffer(1) });
-    user.save(function(err, doc) {
+    var user = new User({array: [null], required: new Buffer(1)});
+    user.save(function (err, doc) {
       assert.ifError(err);
-      User.findById(doc, function(err, doc) {
+      User.findById(doc, function (err, doc) {
         db.close();
         assert.ifError(err);
         assert.equal(1, doc.array.length);
@@ -377,11 +376,10 @@ describe('types.buffer', function() {
         done();
       });
     });
-
   });
 
-  describe('#toObject', function() {
-    it('retains custom subtypes', function(done) {
+  describe('#toObject', function () {
+    it('retains custom subtypes', function (done) {
       var buf = new MongooseBuffer(0);
       var out = buf.toObject(2);
       // validate the drivers Binary type output retains the option
@@ -390,39 +388,39 @@ describe('types.buffer', function() {
     });
   });
 
-  describe('subtype', function() {
+  describe('subtype', function () {
     var db, bufferSchema, B;
 
-    before(function(done) {
+    before(function (done) {
       db = start();
-      bufferSchema = new Schema({ buf: Buffer });
+      bufferSchema = new Schema({buf: Buffer});
       B = db.model('1571', bufferSchema);
       done();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('default value', function(done) {
-      var b = new B({ buf: new Buffer('hi') });
+    it('default value', function (done) {
+      var b = new B({buf: new Buffer('hi')});
       assert.strictEqual(0, b.buf._subtype);
       done();
     });
 
-    it('method works', function(done) {
-      var b = new B({ buf: new Buffer('hi') });
+    it('method works', function (done) {
+      var b = new B({buf: new Buffer('hi')});
       b.buf.subtype(128);
       assert.strictEqual(128, b.buf._subtype);
       done();
     });
 
-    it('is stored', function(done) {
-      var b = new B({ buf: new Buffer('hi') });
+    it('is stored', function (done) {
+      var b = new B({buf: new Buffer('hi')});
       b.buf.subtype(128);
-      b.save(function(err) {
+      b.save(function (err) {
         if (err) return done(err);
-        B.findById(b, function(err, doc) {
+        B.findById(b, function (err, doc) {
           if (err) return done(err);
           assert.equal(128, doc.buf._subtype);
           done();
@@ -430,18 +428,18 @@ describe('types.buffer', function() {
       });
     });
 
-    it('changes are retained', function(done) {
-      var b = new B({ buf: new Buffer('hi') });
+    it('changes are retained', function (done) {
+      var b = new B({buf: new Buffer('hi')});
       b.buf.subtype(128);
-      b.save(function(err) {
+      b.save(function (err) {
         if (err) return done(err);
-        B.findById(b, function(err, doc) {
+        B.findById(b, function (err, doc) {
           if (err) return done(err);
           assert.equal(128, doc.buf._subtype);
           doc.buf.subtype(0);
-          doc.save(function(err) {
+          doc.save(function (err) {
             if (err) return done(err);
-            B.findById(b, function(err, doc) {
+            B.findById(b, function (err, doc) {
               if (err) return done(err);
               assert.strictEqual(0, doc.buf._subtype);
               done();
@@ -451,11 +449,11 @@ describe('types.buffer', function() {
       });
     });
 
-    it('cast from number (gh-3764)', function(done) {
-      var schema = new Schema({ buf: Buffer });
+    it('cast from number (gh-3764)', function (done) {
+      var schema = new Schema({buf: Buffer});
       var MyModel = mongoose.model('gh3764', schema);
 
-      var doc = new MyModel({ buf: 9001 });
+      var doc = new MyModel({buf: 9001});
       assert.equal(doc.buf.length, 1);
       done();
     });
diff --git a/test/types.document.test.js b/test/types.document.test.js
index 22464673c21..b78da80f8e2 100644
--- a/test/types.document.test.js
+++ b/test/types.document.test.js
@@ -40,8 +40,8 @@ Subdocument.prototype.__proto__ = EmbeddedDocument.prototype;
  */
 
 Subdocument.prototype.$__setSchema(new Schema({
-  test: { type: String, required: true },
-  work: { type: String, validate: /^good/ }
+  test: {type: String, required: true},
+  work: {type: String, validate: /^good/}
 }));
 
 /**
@@ -50,7 +50,7 @@ Subdocument.prototype.$__setSchema(new Schema({
 
 var RatingSchema = new Schema({
   stars: Number,
-  description: { source: { url: String, time: Date }}
+  description: {source: {url: String, time: Date}}
 });
 
 var MovieSchema = new Schema({
@@ -64,15 +64,14 @@ mongoose.model('Movie', MovieSchema);
  * Test.
  */
 
-describe('types.document', function() {
-
-  it('test that validate sets errors', function(done) {
+describe('types.document', function () {
+  it('test that validate sets errors', function (done) {
     var a = new Subdocument();
     a.set('test', '');
     a.set('work', 'nope');
     a.__index = 0;
 
-    a.validate(function() {
+    a.validate(function () {
       assert.ok(a.__parent.$__.validationError instanceof ValidationError);
       assert.equal(a.__parent.errors['jsconf.ar.0.work'].name, 'ValidatorError');
       assert.equal(a.__parent.$__.validationError.toString(), 'ValidationError: Path `test` is required., Validator failed for path `work` with value `nope`');
@@ -80,17 +79,17 @@ describe('types.document', function() {
     });
   });
 
-  it('objects can be passed to #set', function(done) {
+  it('objects can be passed to #set', function (done) {
     var a = new Subdocument();
-    a.set({ test: 'paradiddle', work: 'good flam'});
+    a.set({test: 'paradiddle', work: 'good flam'});
     assert.equal(a.test, 'paradiddle');
     assert.equal(a.work, 'good flam');
     done();
   });
 
-  it('Subdocuments can be passed to #set', function(done) {
+  it('Subdocuments can be passed to #set', function (done) {
     var a = new Subdocument();
-    a.set({ test: 'paradiddle', work: 'good flam'});
+    a.set({test: 'paradiddle', work: 'good flam'});
     assert.equal(a.test, 'paradiddle');
     assert.equal(a.work, 'good flam');
     var b = new Subdocument();
@@ -100,7 +99,7 @@ describe('types.document', function() {
     done();
   });
 
-  it('cached _ids', function(done) {
+  it('cached _ids', function (done) {
     var db = start();
     var Movie = db.model('Movie');
     var m = new Movie;
@@ -113,7 +112,7 @@ describe('types.document', function() {
 
     var m2 = new Movie;
     delete m2._doc._id;
-    m2.init({ _id: new mongoose.Types.ObjectId });
+    m2.init({_id: new mongoose.Types.ObjectId});
     assert.equal(m2.id, m2.$__._id);
     assert.strictEqual(true, m.$__._id !== m2.$__._id);
     assert.strictEqual(true, m.id !== m2.id);
@@ -121,23 +120,23 @@ describe('types.document', function() {
     db.close(done);
   });
 
-  it('Subdocument#remove (gh-531)', function(done) {
+  it('Subdocument#remove (gh-531)', function (done) {
     var db = start();
     var Movie = db.model('Movie');
 
-    var super8 = new Movie({ title: 'Super 8' });
+    var super8 = new Movie({title: 'Super 8'});
 
     var id1 = '4e3d5fc7da5d7eb635063c96';
     var id2 = '4e3d5fc7da5d7eb635063c97';
     var id3 = '4e3d5fc7da5d7eb635063c98';
     var id4 = '4e3d5fc7da5d7eb635063c99';
 
-    super8.ratings.push({ stars: 9, _id: id1 });
-    super8.ratings.push({ stars: 8, _id: id2 });
-    super8.ratings.push({ stars: 7, _id: id3 });
-    super8.ratings.push({ stars: 6, _id: id4 });
+    super8.ratings.push({stars: 9, _id: id1});
+    super8.ratings.push({stars: 8, _id: id2});
+    super8.ratings.push({stars: 7, _id: id3});
+    super8.ratings.push({stars: 6, _id: id4});
 
-    super8.save(function(err) {
+    super8.save(function (err) {
       assert.ifError(err);
 
       assert.equal(super8.title, 'Super 8');
@@ -151,14 +150,14 @@ describe('types.document', function() {
       super8.ratings.id(id3).stars = 4;
       super8.ratings.id(id4).stars = 3;
 
-      super8.save(function(err) {
+      super8.save(function (err) {
         assert.ifError(err);
 
-        Movie.findById(super8._id, function(err, movie) {
+        Movie.findById(super8._id, function (err, movie) {
           assert.ifError(err);
 
           assert.equal(movie.title, 'Super 8');
-          assert.equal(movie.ratings.length,3);
+          assert.equal(movie.ratings.length, 3);
           assert.equal(movie.ratings.id(id1).stars.valueOf(), 5);
           assert.equal(movie.ratings.id(id3).stars.valueOf(), 4);
           assert.equal(movie.ratings.id(id4).stars.valueOf(), 3);
@@ -167,20 +166,20 @@ describe('types.document', function() {
           movie.ratings.id(id3).remove();
           movie.ratings.id(id4).stars = 1;
 
-          movie.save(function(err) {
+          movie.save(function (err) {
             assert.ifError(err);
 
-            Movie.findById(super8._id, function(err, movie) {
+            Movie.findById(super8._id, function (err, movie) {
               assert.ifError(err);
-              assert.equal(movie.ratings.length,2);
+              assert.equal(movie.ratings.length, 2);
               assert.equal(movie.ratings.id(id1).stars.valueOf(), 2);
               assert.equal(movie.ratings.id(id4).stars.valueOf(), 1);
 
               // gh-531
               movie.ratings[0].remove();
               movie.ratings[0].remove();
-              movie.save(function() {
-                Movie.findById(super8._id, function(err, movie) {
+              movie.save(function () {
+                Movie.findById(super8._id, function (err, movie) {
                   assert.ifError(err);
                   assert.equal(0, movie.ratings.length);
                   db.close(done);
@@ -193,8 +192,8 @@ describe('types.document', function() {
     });
   });
 
-  describe('setting nested objects', function() {
-    it('works (gh-1394)', function(done) {
+  describe('setting nested objects', function () {
+    it('works (gh-1394)', function (done) {
       var db = start();
       var Movie = db.model('Movie');
 
@@ -208,19 +207,19 @@ describe('types.document', function() {
             }
           }
         }]
-      }, function(err, movie) {
+      }, function (err, movie) {
         assert.ifError(err);
 
-        Movie.findById(movie, function(err, movie) {
+        Movie.findById(movie, function (err, movie) {
           assert.ifError(err);
 
           assert.ok(movie.ratings[0].description.source.time instanceof Date);
-          movie.ratings[0].description.source = { url: 'http://www.lifeofpimovie.com/' };
+          movie.ratings[0].description.source = {url: 'http://www.lifeofpimovie.com/'};
 
-          movie.save(function(err) {
+          movie.save(function (err) {
             assert.ifError(err);
 
-            Movie.findById(movie, function(err, movie) {
+            Movie.findById(movie, function (err, movie) {
               assert.ifError(err);
 
               assert.equal('http://www.lifeofpimovie.com/', movie.ratings[0].description.source.url);
@@ -229,11 +228,11 @@ describe('types.document', function() {
               assert.equal(undefined, movie.ratings[0].description.source.time);
 
               var newDate = new Date;
-              movie.ratings[0].set('description.source.time', newDate, { merge: true });
-              movie.save(function(err) {
+              movie.ratings[0].set('description.source.time', newDate, {merge: true});
+              movie.save(function (err) {
                 assert.ifError(err);
 
-                Movie.findById(movie, function(err, movie) {
+                Movie.findById(movie, function (err, movie) {
                   assert.ifError(err);
                   assert.equal(String(newDate), movie.ratings[0].description.source.time);
                   // url not overwritten using merge
@@ -247,5 +246,4 @@ describe('types.document', function() {
       });
     });
   });
-
 });
diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js
index e3e65841932..ada0a50f42d 100644
--- a/test/types.documentarray.test.js
+++ b/test/types.documentarray.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -19,7 +18,7 @@ var start = require('./common'),
  */
 
 function TestDoc(schema) {
-  var Subdocument = function() {
+  var Subdocument = function () {
     EmbeddedDocument.call(this, {}, new DocumentArray);
   };
 
@@ -34,7 +33,7 @@ function TestDoc(schema) {
    */
 
   var SubSchema = new Schema({
-    title: { type: String }
+    title: {type: String}
   });
 
   Subdocument.prototype.$__setSchema(schema || SubSchema);
@@ -46,8 +45,8 @@ function TestDoc(schema) {
  * Test.
  */
 
-describe('types.documentarray', function() {
-  it('behaves and quacks like an array', function(done) {
+describe('types.documentarray', function () {
+  it('behaves and quacks like an array', function (done) {
     var a = new MongooseDocumentArray();
 
     assert.ok(a instanceof Array);
@@ -61,7 +60,7 @@ describe('types.documentarray', function() {
     done();
   });
 
-  it('#id', function(done) {
+  it('#id', function (done) {
     var Subdocument = TestDoc();
 
     var sub1 = new Subdocument();
@@ -74,8 +73,8 @@ describe('types.documentarray', function() {
 
     // test with custom string _id
     var Custom = new Schema({
-      title: { type: String },
-      _id:   { type: String, required: true }
+      title: {type: String},
+      _id: {type: String, required: true}
     });
 
     Subdocument = TestDoc(Custom);
@@ -91,8 +90,8 @@ describe('types.documentarray', function() {
 
     // test with custom number _id
     var CustNumber = new Schema({
-      title: { type: String },
-      _id:   { type: Number, required: true }
+      title: {type: String},
+      _id: {type: Number, required: true}
     });
 
     Subdocument = TestDoc(CustNumber);
@@ -108,8 +107,8 @@ describe('types.documentarray', function() {
 
     // test with object as _id
     Custom = new Schema({
-      title: { type: String },
-      _id:   { one: { type: String }, two: { type: String } }
+      title: {type: String},
+      _id: {one: {type: String}, two: {type: String}}
     });
 
     Subdocument = TestDoc(Custom);
@@ -122,14 +121,14 @@ describe('types.documentarray', function() {
     sub2._id = {one: 'rock', two: 'roll'};
     sub2.title = 'rock-n-roll';
 
-    a = new MongooseDocumentArray([sub1,sub2]);
+    a = new MongooseDocumentArray([sub1, sub2]);
     assert.notEqual(a.id({one: 'rolling', two: 'rock'}).title, 'rock-n-roll');
     assert.equal(a.id({one: 'rock', two: 'roll'}).title, 'rock-n-roll');
 
     // test with no _id
     var NoId = new Schema({
-      title: { type: String }
-    }, { noId: true });
+      title: {type: String}
+    }, {noId: true});
 
     Subdocument = TestDoc(NoId);
 
@@ -147,8 +146,8 @@ describe('types.documentarray', function() {
 
     // test the _id option, noId is deprecated
     NoId = new Schema({
-      title: { type: String }
-    }, { _id: false });
+      title: {type: String}
+    }, {_id: false});
 
     Subdocument = TestDoc(NoId);
 
@@ -156,7 +155,7 @@ describe('types.documentarray', function() {
     sub4.title = 'rock-n-roll';
 
     a = new MongooseDocumentArray([sub4]),
-       threw = false;
+        threw = false;
     try {
       a.id('i better not throw');
     } catch (err) {
@@ -169,10 +168,10 @@ describe('types.documentarray', function() {
 
     // test when _id is a populated document
     Custom = new Schema({
-      title: { type: String }
+      title: {type: String}
     });
 
-    var Custom1 = new Schema({}, { id: false });
+    var Custom1 = new Schema({}, {id: false});
 
     Subdocument = TestDoc(Custom);
     var Subdocument1 = TestDoc(Custom1);
@@ -189,8 +188,8 @@ describe('types.documentarray', function() {
     done();
   });
 
-  describe('inspect', function() {
-    it('works with bad data', function(done) {
+  describe('inspect', function () {
+    it('works with bad data', function (done) {
       var threw = false;
       var a = new MongooseDocumentArray([null]);
       try {
@@ -204,8 +203,8 @@ describe('types.documentarray', function() {
     });
   });
 
-  describe('toObject', function() {
-    it('works with bad data', function(done) {
+  describe('toObject', function () {
+    it('works with bad data', function (done) {
       var threw = false;
       var a = new MongooseDocumentArray([null]);
       try {
@@ -217,13 +216,13 @@ describe('types.documentarray', function() {
       assert.ok(!threw);
       done();
     });
-    it('passes options to its documents (gh-1415)', function(done) {
+    it('passes options to its documents (gh-1415)', function (done) {
       var subSchema = new Schema({
-        title: { type: String }
+        title: {type: String}
       });
 
       subSchema.set('toObject', {
-        transform: function(doc, ret) {
+        transform: function (doc, ret) {
           // this should not be called because custom options are
           // passed during MongooseArray#toObject() calls
           ret.changed = 123;
@@ -232,14 +231,14 @@ describe('types.documentarray', function() {
       });
 
       var db = mongoose.createConnection();
-      var M = db.model('gh-1415', { docs: [subSchema] });
+      var M = db.model('gh-1415', {docs: [subSchema]});
       var m = new M;
-      m.docs.push({ docs: [{ title: 'hello' }] });
+      m.docs.push({docs: [{title: 'hello'}]});
       var delta = m.$__delta()[1];
       assert.equal(undefined, delta.$pushAll.docs[0].changed);
       done();
     });
-    it('uses the correct transform (gh-1412)', function(done) {
+    it('uses the correct transform (gh-1412)', function (done) {
       var db = start();
       var SecondSchema = new Schema({});
 
@@ -264,8 +263,7 @@ describe('types.documentarray', function() {
       var First = db.model('first', FirstSchema);
       var Second = db.model('second', SecondSchema);
 
-      var first = new First({
-      });
+      var first = new First({});
 
       first.second.push(new Second());
       first.second.push(new Second());
@@ -280,16 +278,16 @@ describe('types.documentarray', function() {
     });
   });
 
-  describe('create()', function() {
-    it('works', function(done) {
+  describe('create()', function () {
+    it('works', function (done) {
       var a = new MongooseDocumentArray([]);
       assert.equal('function', typeof a.create);
 
-      var schema = new Schema({ docs: [new Schema({ name: 'string' })] });
+      var schema = new Schema({docs: [new Schema({name: 'string'})]});
       var T = mongoose.model('embeddedDocument#create_test', schema, 'asdfasdfa' + random());
       var t = new T;
       assert.equal('function', typeof t.docs.create);
-      var subdoc = t.docs.create({ name: 100 });
+      var subdoc = t.docs.create({name: 100});
       assert.ok(subdoc._id);
       assert.equal(subdoc.name, '100');
       assert.ok(subdoc instanceof EmbeddedDocument);
@@ -297,27 +295,27 @@ describe('types.documentarray', function() {
     });
   });
 
-  describe('push()', function() {
-    it('does not re-cast instances of its embedded doc', function(done) {
+  describe('push()', function () {
+    it('does not re-cast instances of its embedded doc', function (done) {
       var db = start();
 
-      var child = new Schema({ name: String, date: Date });
-      child.pre('save', function(next) {
+      var child = new Schema({name: String, date: Date});
+      child.pre('save', function (next) {
         this.date = new Date;
         next();
       });
-      var schema = Schema({ children: [child] });
+      var schema = Schema({children: [child]});
       var M = db.model('embeddedDocArray-push-re-cast', schema, 'edarecast-' + random());
       var m = new M;
-      m.save(function(err) {
+      m.save(function (err) {
         assert.ifError(err);
-        M.findById(m._id, function(err, doc) {
+        M.findById(m._id, function (err, doc) {
           assert.ifError(err);
-          var c = doc.children.create({ name: 'first' });
+          var c = doc.children.create({name: 'first'});
           assert.equal(undefined, c.date);
           doc.children.push(c);
           assert.equal(undefined, c.date);
-          doc.save(function(err) {
+          doc.save(function (err) {
             assert.ifError(err);
             assert.ok(doc.children[doc.children.length - 1].date);
             assert.equal(c.date, doc.children[doc.children.length - 1].date);
@@ -325,12 +323,12 @@ describe('types.documentarray', function() {
             doc.children.push(c);
             doc.children.push(c);
 
-            doc.save(function(err) {
+            doc.save(function (err) {
               assert.ifError(err);
-              M.findById(m._id, function(err, doc) {
+              M.findById(m._id, function (err, doc) {
                 assert.ifError(err);
                 assert.equal(3, doc.children.length);
-                doc.children.forEach(function(child) {
+                doc.children.forEach(function (child) {
                   assert.equal(doc.children[0].id, child.id);
                 });
                 db.close(done);
@@ -340,11 +338,11 @@ describe('types.documentarray', function() {
         });
       });
     });
-    it('corrects #ownerDocument() if value was created with array.create() (gh-1385)', function(done) {
+    it('corrects #ownerDocument() if value was created with array.create() (gh-1385)', function (done) {
       var mg = new mongoose.Mongoose;
-      var M = mg.model('1385', { docs: [{ name: String }] });
+      var M = mg.model('1385', {docs: [{name: String}]});
       var m = new M;
-      var doc = m.docs.create({ name: 'test 1385' });
+      var doc = m.docs.create({name: 'test 1385'});
       assert.notEqual(String(doc.ownerDocument()._id), String(m._id));
       m.docs.push(doc);
       assert.equal(doc.ownerDocument()._id, String(m._id));
@@ -352,7 +350,7 @@ describe('types.documentarray', function() {
     });
   });
 
-  it('#push should work on EmbeddedDocuments more than 2 levels deep', function(done) {
+  it('#push should work on EmbeddedDocuments more than 2 levels deep', function (done) {
     var Comments = new Schema;
     Comments.add({
       title: String,
@@ -366,27 +364,27 @@ describe('types.documentarray', function() {
     var db = start(),
         Post = db.model('docarray-BlogPost', BlogPost, collection);
 
-    var p = new Post({ title: "comment nesting" });
-    var c1 = p.comments.create({ title: "c1" });
-    var c2 = p.comments.create({ title: "c2" });
-    var c3 = p.comments.create({ title: "c3" });
+    var p = new Post({title: 'comment nesting'});
+    var c1 = p.comments.create({title: 'c1'});
+    var c2 = p.comments.create({title: 'c2'});
+    var c3 = p.comments.create({title: 'c3'});
 
     p.comments.push(c1);
     c1.comments.push(c2);
     c2.comments.push(c3);
 
-    p.save(function(err) {
+    p.save(function (err) {
       assert.ifError(err);
 
-      Post.findById(p._id, function(err, p) {
+      Post.findById(p._id, function (err, p) {
         assert.ifError(err);
 
-        var c4 = p.comments.create({ title: "c4" });
+        var c4 = p.comments.create({title: 'c4'});
         p.comments[0].comments[0].comments[0].comments.push(c4);
-        p.save(function(err) {
+        p.save(function (err) {
           assert.ifError(err);
 
-          Post.findById(p._id, function(err, p) {
+          Post.findById(p._id, function (err, p) {
             assert.ifError(err);
             assert.equal(p.comments[0].comments[0].comments[0].comments[0].title, 'c4');
             db.close(done);
@@ -396,24 +394,24 @@ describe('types.documentarray', function() {
     });
   });
 
-  describe('invalidate()', function() {
-    it('works', function(done) {
-      var schema = Schema({ docs: [{ name: 'string' }] });
-      schema.pre('validate', function(next) {
+  describe('invalidate()', function () {
+    it('works', function (done) {
+      var schema = Schema({docs: [{name: 'string'}]});
+      schema.pre('validate', function (next) {
         var subdoc = this.docs[this.docs.length - 1];
         subdoc.invalidate('name', 'boo boo', '%');
         next();
       });
       var T = mongoose.model('embeddedDocument#invalidate_test', schema, 'asdfasdfa' + random());
       var t = new T;
-      t.docs.push({ name: 100 });
+      t.docs.push({name: 100});
 
-      var subdoc = t.docs.create({ name: 'yep' });
-      assert.throws(function() {
+      var subdoc = t.docs.create({name: 'yep'});
+      assert.throws(function () {
         // has no parent array
         subdoc.invalidate('name', 'junk', 47);
       }, /^Error: Unable to invalidate a subdocument/);
-      t.validate(function() {
+      t.validate(function () {
         var e = t.errors['docs.0.name'];
         assert.ok(e);
         assert.equal(e.path, 'docs.0.name');
@@ -424,34 +422,34 @@ describe('types.documentarray', function() {
       });
     });
 
-    it('handles validation failures', function(done) {
+    it('handles validation failures', function (done) {
       var db = start();
-      var nested = Schema({ v: { type: Number, max: 30 }});
+      var nested = Schema({v: {type: Number, max: 30}});
       var schema = Schema({
         docs: [nested]
-      }, { collection: 'embedded-invalidate-' + random() });
+      }, {collection: 'embedded-invalidate-' + random()});
       var M = db.model('embedded-invalidate', schema);
-      var m = new M({ docs: [{ v: 900 }] });
-      m.save(function(err) {
+      var m = new M({docs: [{v: 900}]});
+      m.save(function (err) {
         assert.equal(900, err.errors['docs.0.v'].value);
         db.close(done);
       });
     });
 
-    it('removes attached event listeners when creating new doc array', function(done) {
+    it('removes attached event listeners when creating new doc array', function (done) {
       var db = start();
-      var nested = Schema({ v: { type: Number }});
+      var nested = Schema({v: {type: Number}});
       var schema = Schema({
         docs: [nested]
-      }, { collection: 'gh-2159' });
+      }, {collection: 'gh-2159'});
       var M = db.model('gh-2159', schema);
-      M.create({ docs: [{v: 900}] }, function(error, m) {
+      M.create({docs: [{v: 900}]}, function (error, m) {
         m.shouldPrint = true;
         assert.ifError(error);
         var numListeners = m.listeners('save').length;
         assert.ok(numListeners > 0);
-        m.docs = [{ v: 9000 }];
-        m.save(function(error, m) {
+        m.docs = [{v: 9000}];
+        m.save(function (error, m) {
           assert.ifError(error);
           assert.equal(numListeners, m.listeners('save').length);
           db.close(done);
diff --git a/test/types.number.test.js b/test/types.number.test.js
index 534e5fe8f6f..e8ce2749c61 100644
--- a/test/types.number.test.js
+++ b/test/types.number.test.js
@@ -11,21 +11,20 @@ var mongoose = require('./common').mongoose,
  * Test.
  */
 
-describe('types.number', function() {
-
-  it('an empty string casts to null', function(done) {
+describe('types.number', function () {
+  it('an empty string casts to null', function (done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.cast(''), null);
     done();
   });
 
-  it('a null number should castForQuery to null', function(done) {
+  it('a null number should castForQuery to null', function (done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.castForQuery(null), null);
     done();
   });
 
-  it('undefined throws number cast error', function(done) {
+  it('undefined throws number cast error', function (done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -37,7 +36,7 @@ describe('types.number', function() {
     done();
   });
 
-  it('array throws cast number error', function(done) {
+  it('array throws cast number error', function (done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -49,7 +48,7 @@ describe('types.number', function() {
     done();
   });
 
-  it('three throws cast number error', function(done) {
+  it('three throws cast number error', function (done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -61,7 +60,7 @@ describe('types.number', function() {
     done();
   });
 
-  it('{} throws cast number error', function(done) {
+  it('{} throws cast number error', function (done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -73,7 +72,7 @@ describe('types.number', function() {
     done();
   });
 
-  it('does not throw number cast error', function(done) {
+  it('does not throw number cast error', function (done) {
     var n = new SchemaNumber();
     var items = [1, '2', '0', null, '', new String('47'), new Number(5), Number(47), Number('09'), 0x12];
     var err;
@@ -88,7 +87,7 @@ describe('types.number', function() {
     done();
   });
 
-  it('boolean casts to 0/1 (gh-3475)', function(done) {
+  it('boolean casts to 0/1 (gh-3475)', function (done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.cast(true), 1);
     assert.strictEqual(n.cast(false), 0);
diff --git a/test/updateValidators.unit.test.js b/test/updateValidators.unit.test.js
index db547c075d1..99bdc46872f 100644
--- a/test/updateValidators.unit.test.js
+++ b/test/updateValidators.unit.test.js
@@ -2,31 +2,31 @@ var assert = require('assert');
 var updateValidators = require('../lib/services/updateValidators');
 var emitter = require('events').EventEmitter;
 
-describe('updateValidators', function() {
+describe('updateValidators', function () {
   var schema;
 
-  beforeEach(function() {
+  beforeEach(function () {
     schema = {};
-    schema._getSchema = function(p) {
+    schema._getSchema = function (p) {
       schema._getSchema.calls.push(p);
       return schema;
     };
     schema._getSchema.calls = [];
-    schema.doValidate = function(v, cb) {
-      schema.doValidate.calls.push({ v: v, cb: cb });
-      schema.doValidate.emitter.emit('called', { v: v, cb: cb });
+    schema.doValidate = function (v, cb) {
+      schema.doValidate.calls.push({v: v, cb: cb});
+      schema.doValidate.emitter.emit('called', {v: v, cb: cb});
     };
     schema.doValidate.calls = [];
     schema.doValidate.emitter = new emitter();
   });
 
-  describe('validators', function() {
-    it('flattens paths', function(done) {
-      var fn = updateValidators({}, schema, { test: { a: 1, b: null } }, {});
-      schema.doValidate.emitter.on('called', function(args) {
+  describe('validators', function () {
+    it('flattens paths', function (done) {
+      var fn = updateValidators({}, schema, {test: {a: 1, b: null}}, {});
+      schema.doValidate.emitter.on('called', function (args) {
         args.cb();
       });
-      fn(function(err) {
+      fn(function (err) {
         assert.ifError(err);
         assert.equal(schema._getSchema.calls.length, 2);
         assert.equal(schema.doValidate.calls.length, 2);
@@ -38,13 +38,13 @@ describe('updateValidators', function() {
       });
     });
 
-    it('doesnt flatten dates (gh-3194)', function(done) {
+    it('doesnt flatten dates (gh-3194)', function (done) {
       var dt = new Date();
-      var fn = updateValidators({}, schema, { test: dt }, {});
-      schema.doValidate.emitter.on('called', function(args) {
+      var fn = updateValidators({}, schema, {test: dt}, {});
+      schema.doValidate.emitter.on('called', function (args) {
         args.cb();
       });
-      fn(function(err) {
+      fn(function (err) {
         assert.ifError(err);
         assert.equal(schema._getSchema.calls.length, 1);
         assert.equal(schema.doValidate.calls.length, 1);
@@ -54,12 +54,12 @@ describe('updateValidators', function() {
       });
     });
 
-    it('doesnt flatten empty arrays (gh-3554)', function(done) {
-      var fn = updateValidators({}, schema, { test: [] }, {});
-      schema.doValidate.emitter.on('called', function(args) {
+    it('doesnt flatten empty arrays (gh-3554)', function (done) {
+      var fn = updateValidators({}, schema, {test: []}, {});
+      schema.doValidate.emitter.on('called', function (args) {
         args.cb();
       });
-      fn(function(err) {
+      fn(function (err) {
         assert.ifError(err);
         assert.equal(schema._getSchema.calls.length, 1);
         assert.equal(schema.doValidate.calls.length, 1);
diff --git a/test/utils.test.js b/test/utils.test.js
index 4307cf4caf8..647b88dd45e 100644
--- a/test/utils.test.js
+++ b/test/utils.test.js
@@ -22,38 +22,38 @@ var ActiveRoster = StateMachine.ctor('require', 'init', 'modify');
  * Test.
  */
 
-describe('utils', function() {
-  describe('toCollectionName', function() {
-    it('works (gh-3490)', function(done) {
+describe('utils', function () {
+  describe('toCollectionName', function () {
+    it('works (gh-3490)', function (done) {
       assert.equal(utils.toCollectionName('stations'), 'stations');
       assert.equal(utils.toCollectionName('category'), 'categories');
       done();
     });
   });
 
-  describe('ActiveRoster', function() {
-    it('should detect a path as required if it has been required', function(done) {
+  describe('ActiveRoster', function () {
+    it('should detect a path as required if it has been required', function (done) {
       var ar = new ActiveRoster();
       ar.require('hello');
-      assert.equal(ar.paths['hello'],'require');
+      assert.equal(ar.paths['hello'], 'require');
       done();
     });
 
-    it('should detect a path as inited if it has been inited', function(done) {
+    it('should detect a path as inited if it has been inited', function (done) {
       var ar = new ActiveRoster();
       ar.init('hello');
-      assert.equal(ar.paths['hello'],'init');
+      assert.equal(ar.paths['hello'], 'init');
       done();
     });
 
-    it('should detect a path as modified', function(done) {
+    it('should detect a path as modified', function (done) {
       var ar = new ActiveRoster();
       ar.modify('hello');
-      assert.equal(ar.paths['hello'],'modify');
+      assert.equal(ar.paths['hello'], 'modify');
       done();
     });
 
-    it('should remove a path from an old state upon a state change', function(done) {
+    it('should remove a path from an old state upon a state change', function (done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.modify('hello');
@@ -62,43 +62,43 @@ describe('utils', function() {
       done();
     });
 
-    it('forEach should be able to iterate through the paths belonging to one state', function(done) {
+    it('forEach should be able to iterate through the paths belonging to one state', function (done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.init('goodbye');
       ar.modify('world');
       ar.require('foo');
-      ar.forEach('init', function(path) {
+      ar.forEach('init', function (path) {
         assert.ok(~['hello', 'goodbye'].indexOf(path));
       });
       done();
     });
 
-    it('forEach should be able to iterate through the paths in the union of two or more states', function(done) {
+    it('forEach should be able to iterate through the paths in the union of two or more states', function (done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.init('goodbye');
       ar.modify('world');
       ar.require('foo');
-      ar.forEach('modify', 'require', function(path) {
+      ar.forEach('modify', 'require', function (path) {
         assert.ok(~['world', 'foo'].indexOf(path));
       });
       done();
     });
 
-    it('forEach should iterate through all paths that have any state if given no state arguments', function(done) {
+    it('forEach should iterate through all paths that have any state if given no state arguments', function (done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.init('goodbye');
       ar.modify('world');
       ar.require('foo');
-      ar.forEach(function(path) {
-        assert.ok(~['hello', 'goodbye','world', 'foo'].indexOf(path));
+      ar.forEach(function (path) {
+        assert.ok(~['hello', 'goodbye', 'world', 'foo'].indexOf(path));
       });
       done();
     });
 
-    it('should be able to detect if at least one path exists in a set of states', function(done) {
+    it('should be able to detect if at least one path exists in a set of states', function (done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.modify('world');
@@ -111,42 +111,41 @@ describe('utils', function() {
       done();
     });
 
-    it('should be able to `map` over the set of paths in a given state', function(done) {
+    it('should be able to `map` over the set of paths in a given state', function (done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.modify('world');
       ar.require('iAmTheWalrus');
-      var suffixedPaths = ar.map('init', 'modify', function(path) {
+      var suffixedPaths = ar.map('init', 'modify', function (path) {
         return path + '-suffix';
       });
-      assert.deepEqual(suffixedPaths,['hello-suffix', 'world-suffix']);
+      assert.deepEqual(suffixedPaths, ['hello-suffix', 'world-suffix']);
       done();
     });
 
-    it("should `map` over all states' paths if no states are specified in a `map` invocation", function(done) {
+    it("should `map` over all states' paths if no states are specified in a `map` invocation", function (done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.modify('world');
       ar.require('iAmTheWalrus');
-      var suffixedPaths = ar.map(function(path) {
+      var suffixedPaths = ar.map(function (path) {
         return path + '-suffix';
       });
-      assert.deepEqual(suffixedPaths,['iAmTheWalrus-suffix', 'hello-suffix', 'world-suffix']);
+      assert.deepEqual(suffixedPaths, ['iAmTheWalrus-suffix', 'hello-suffix', 'world-suffix']);
       done();
     });
-
   });
 
-  it('utils.options', function(done) {
-    var o = { a: 1, b: 2, c: 3, 0: 'zero1' };
-    var defaults = { b: 10, d: 20, 0: 'zero2' };
+  it('utils.options', function (done) {
+    var o = {a: 1, b: 2, c: 3, 0: 'zero1'};
+    var defaults = {b: 10, d: 20, 0: 'zero2'};
     var result = utils.options(defaults, o);
     assert.equal(1, result.a);
-    assert.equal(result.b,2);
-    assert.equal(result.c,3);
-    assert.equal(result.d,20);
-    assert.deepEqual(o.d,result.d);
-    assert.equal(result['0'],'zero1');
+    assert.equal(result.b, 2);
+    assert.equal(result.c, 3);
+    assert.equal(result.d, 20);
+    assert.deepEqual(o.d, result.d);
+    assert.equal(result['0'], 'zero1');
 
     var result2 = utils.options(defaults);
     assert.equal(result2.b, 10);
@@ -161,7 +160,7 @@ describe('utils', function() {
     done();
   });
 
-  it('deepEquals on ObjectIds', function(done) {
+  it('deepEquals on ObjectIds', function (done) {
     var s = (new ObjectId).toString();
 
     var a = new ObjectId(s),
@@ -173,9 +172,9 @@ describe('utils', function() {
     done();
   });
 
-  it('deepEquals on MongooseDocumentArray works', function(done) {
+  it('deepEquals on MongooseDocumentArray works', function (done) {
     var db = start(),
-        A = new Schema({ a: String }),
+        A = new Schema({a: String}),
         M = db.model('deepEqualsOnMongooseDocArray', new Schema({
           a1: [A],
           a2: [A]
@@ -201,13 +200,13 @@ describe('utils', function() {
   });
 
   // gh-688
-  it('deepEquals with MongooseBuffer', function(done) {
-    var str = "this is the day";
+  it('deepEquals with MongooseBuffer', function (done) {
+    var str = 'this is the day';
     var a = new MongooseBuffer(str);
     var b = new MongooseBuffer(str);
     var c = new Buffer(str);
-    var d = new Buffer("this is the way");
-    var e = new Buffer("other length");
+    var d = new Buffer('this is the way');
+    var e = new Buffer('other length');
 
     assert.ok(utils.deepEqual(a, b));
     assert.ok(utils.deepEqual(a, c));
@@ -218,8 +217,8 @@ describe('utils', function() {
     done();
   });
 
-  describe('clone', function() {
-    it('retains RegExp options gh-1355', function(done) {
+  describe('clone', function () {
+    it('retains RegExp options gh-1355', function (done) {
       var a = new RegExp('hello', 'igm');
       assert.ok(a.global);
       assert.ok(a.ignoreCase);
@@ -233,7 +232,7 @@ describe('utils', function() {
       done();
     });
 
-    it('clones objects created with Object.create(null)', function(done) {
+    it('clones objects created with Object.create(null)', function (done) {
       var o = Object.create(null);
       o.a = 0;
       o.b = '0';
@@ -251,13 +250,13 @@ describe('utils', function() {
     });
   });
 
-  it('array.flatten', function(done) {
-    var orig = [0,[1,2,[3,4,[5,[6]],7],8],9];
-    assert.deepEqual([0,1,2,3,4,5,6,7,8,9], utils.array.flatten(orig));
+  it('array.flatten', function (done) {
+    var orig = [0, [1, 2, [3, 4, [5, [6]], 7], 8], 9];
+    assert.deepEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], utils.array.flatten(orig));
     done();
   });
 
-  it('array.unique', function(done) {
+  it('array.unique', function (done) {
     var case1 = [1, 2, 3, 3, 5, 'a', 6, 'a'];
     assert.deepEqual(utils.array.unique(case1), [1, 2, 3, 5, 'a', 6]);
     var objId = new ObjectId('000000000000000000000001');
@@ -275,21 +274,21 @@ describe('utils', function() {
     done();
   });
 
-  describe('merge', function() {
-    it('merges two objects together without overriding properties & methods', function(done) {
+  describe('merge', function () {
+    it('merges two objects together without overriding properties & methods', function (done) {
       function To() {
         this.name = 'to';
         this.toProperty = true;
       }
-      To.prototype.getName = function() {};
-      To.prototype.toMethod = function() {};
+      To.prototype.getName = function () {};
+      To.prototype.toMethod = function () {};
 
       function From() {
         this.name = 'from';
         this.fromProperty = true;
       }
-      From.prototype.getName = function() {};
-      From.prototype.fromMethod = function() {};
+      From.prototype.getName = function () {};
+      From.prototype.fromMethod = function () {};
 
       var to = new To();
       var from = new From();
@@ -307,20 +306,20 @@ describe('utils', function() {
     });
   });
 
-  describe('pluralize', function() {
+  describe('pluralize', function () {
     var db;
 
-    before(function() {
+    before(function () {
       db = start();
     });
 
-    after(function(done) {
+    after(function (done) {
       db.close(done);
     });
 
-    it('should not pluralize _temp_ (gh-1703)', function(done) {
+    it('should not pluralize _temp_ (gh-1703)', function (done) {
       var ASchema = new Schema({
-        value: { type: Schema.Types.Mixed }
+        value: {type: Schema.Types.Mixed}
       });
 
       var collectionName = '_temp_';
@@ -328,10 +327,9 @@ describe('utils', function() {
       assert.equal(A.collection.name, collectionName);
       done();
     });
-    it('should pluralize _temp (gh-1703)', function(done) {
-
+    it('should pluralize _temp (gh-1703)', function (done) {
       var ASchema = new Schema({
-        value: { type: Schema.Types.Mixed }
+        value: {type: Schema.Types.Mixed}
       });
 
       var collectionName = '_temp';
@@ -339,8 +337,8 @@ describe('utils', function() {
       assert.equal(A.collection.name, collectionName + 's');
       done();
     });
-    describe('option (gh-1707)', function() {
-      it('should pluralize by default', function(done) {
+    describe('option (gh-1707)', function () {
+      it('should pluralize by default', function (done) {
         var ASchema = new Schema({value: String});
 
         var collectionName = 'singular';
@@ -348,7 +346,7 @@ describe('utils', function() {
         assert.equal(A.collection.name, collectionName + 's');
         done();
       });
-      it('should pluralize when global option set to true', function(done) {
+      it('should pluralize when global option set to true', function (done) {
         db.base.set('pluralization', true);
 
         var ASchema = new Schema({value: String});
@@ -358,7 +356,7 @@ describe('utils', function() {
         assert.equal(A.collection.name, collectionName + 's');
         done();
       });
-      it('should not pluralize when global option set to false', function(done) {
+      it('should not pluralize when global option set to false', function (done) {
         db.base.set('pluralization', false);
 
         var ASchema = new Schema({value: String});
@@ -368,7 +366,7 @@ describe('utils', function() {
         assert.equal(A.collection.name, collectionName);
         done();
       });
-      it('should pluralize when local option set to true', function(done) {
+      it('should pluralize when local option set to true', function (done) {
         db.base.set('pluralization', false);
 
         // override
@@ -379,7 +377,7 @@ describe('utils', function() {
         assert.equal(A.collection.name, collectionName + 's');
         done();
       });
-      it('should not pluralize when local option set to false and global is true', function(done) {
+      it('should not pluralize when local option set to false and global is true', function (done) {
         db.base.set('pluralization', true);
 
         var ASchema = new Schema({value: String}, {pluralization: false});
@@ -389,7 +387,7 @@ describe('utils', function() {
         assert.equal(A.collection.name, collectionName);
         done();
       });
-      it('should not pluralize when local option set to false and global not set', function(done) {
+      it('should not pluralize when local option set to false and global not set', function (done) {
         var ASchema = new Schema({value: String}, {pluralization: false});
 
         var collectionName = 'five';
diff --git a/test/versioning.test.js b/test/versioning.test.js
index 1da297de1ae..7f26b07157f 100644
--- a/test/versioning.test.js
+++ b/test/versioning.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Test dependencies.
  */
@@ -49,25 +48,25 @@ var BlogPost = new Schema(
 
 mongoose.model('Versioning', BlogPost);
 
-describe('versioning', function() {
+describe('versioning', function () {
   var db;
 
-  before(function() {
+  before(function () {
     db = start();
   });
 
-  after(function(done) {
+  after(function (done) {
     db.close(done);
   });
 
-  it('is only added to parent schema (gh-1265)', function(done) {
+  it('is only added to parent schema (gh-1265)', function (done) {
     assert.ok(BlogPost.path('__v'));
     assert.ok(!BlogPost.path('comments').__v);
     assert.ok(!BlogPost.path('meta.nested').__v);
     done();
   });
 
-  it('works', function(done) {
+  it('works', function (done) {
     var V = db.model('Versioning');
 
     var doc = new V;
@@ -75,36 +74,40 @@ describe('versioning', function() {
     doc.date = new Date;
     doc.meta.date = new Date;
     doc.meta.visitors = 34;
-    doc.meta.numbers = [12,11,10];
+    doc.meta.numbers = [12, 11, 10];
     doc.meta.nested = [
-      { title: 'does it work?', date: new Date },
-      { title: '1', comments: [{ title: 'this is sub #1'},{ title: 'this is sub #2'}] },
-      { title: '2', comments: [{ title: 'this is sub #3'},{ title: 'this is sub #4'}] },
-      { title: 'hi', date: new Date }
+      {title: 'does it work?', date: new Date},
+      {title: '1', comments: [{title: 'this is sub #1'}, {title: 'this is sub #2'}]},
+      {title: '2', comments: [{title: 'this is sub #3'}, {title: 'this is sub #4'}]},
+      {title: 'hi', date: new Date}
     ];
-    doc.mixed = { arr: [12,11,10] };
-    doc.numbers = [3,4,5,6,7];
+    doc.mixed = {arr: [12, 11, 10]};
+    doc.numbers = [3, 4, 5, 6, 7];
     doc.comments = [
-        { title: 'comments 0', date: new Date },
-       { title: 'comments 1', comments: [{ title: 'comments.1.comments.1'},{ title: 'comments.1.comments.2'}] },
-       { title: 'coments 2', comments: [{ title: 'comments.2.comments.1'},{ title: 'comments.2.comments.2'}] },
-       { title: 'comments 3', date: new Date }
+      {title: 'comments 0', date: new Date},
+      {title: 'comments 1', comments: [{title: 'comments.1.comments.1'}, {title: 'comments.1.comments.2'}]},
+      {title: 'coments 2', comments: [{title: 'comments.2.comments.1'}, {title: 'comments.2.comments.2'}]},
+      {title: 'comments 3', date: new Date}
     ];
     doc.arr = [['2d']];
 
-    doc.save(function(err) {
+    doc.save(function (err) {
       var a, b;
       assert.ifError(err);
       // test 2 concurrent ops
-      V.findById(doc, function(err, _a) {
+      V.findById(doc, function (err, _a) {
         assert.ifError(err);
         a = _a;
-        a && b && test1(a, b);
+        if (a && b) {
+          test1(a, b);
+        }
       });
-      V.findById(doc, function(err, _b) {
+      V.findById(doc, function (err, _b) {
         assert.ifError(err);
         b = _b;
-        a && b && test1(a, b);
+        if (a && b) {
+          test1(a, b);
+        }
       });
     });
 
@@ -145,7 +148,7 @@ describe('versioning', function() {
       var d = a.$__delta();
       assert.equal(a._doc.__v, d[0].__v, 'version should be added to where clause');
       assert.ok(!('$inc' in d[1]));
-      save(a,b,test5);
+      save(a, b, test5);
     }
 
     function test5(err, a, b) {
@@ -174,7 +177,7 @@ describe('versioning', function() {
       save(a, b, test7);
     }
 
-    function test7(err,a,b) {
+    function test7(err, a, b) {
       assert.ok(/No matching document/.test(err), 'changes to b should not be applied');
       assert.equal(a.arr.length, 2);
       assert.equal('updated', a.arr[0][0]);
@@ -189,9 +192,9 @@ describe('versioning', function() {
       assert.ok(/No matching document/.test(err), 'changes to b should not be applied');
       assert.equal(a.meta.nested.length, 3);
       assert.equal(a._doc.__v, 8);
-      a.meta.nested.push({ title: 'the' });
-      a.meta.nested.push({ title: 'killing' });
-      b.meta.nested.push({ title: 'biutiful' });
+      a.meta.nested.push({title: 'the'});
+      a.meta.nested.push({title: 'killing'});
+      b.meta.nested.push({title: 'biutiful'});
       save(a, b, test9);
     }
 
@@ -203,7 +206,7 @@ describe('versioning', function() {
       a.meta.nested[2].title = 'two';
       b.meta.nested[0].title = 'zero';
       b.meta.nested[1].comments[0].title = 'sub one';
-      save(a,b, function(err, _a, _b) {
+      save(a, b, function (err, _a, _b) {
         assert.ifError(err);
         assert.equal(a._doc.__v, 10);
         assert.equal(b._doc.__v, 10);
@@ -218,7 +221,7 @@ describe('versioning', function() {
       assert.equal('sub one', b.meta.nested[1].comments[0].title);
       assert.equal(a._doc.__v, 10);
       assert.equal(3, a.mixed.arr.length);
-      a.mixed.arr.push([10],{x: 1},'woot');
+      a.mixed.arr.push([10], {x: 1}, 'woot');
       a.markModified('mixed.arr');
       save(a, b, test11);
     }
@@ -231,7 +234,7 @@ describe('versioning', function() {
       assert.equal('woot', a.mixed.arr[5]);
       assert.equal(10, a.mixed.arr[3][0]);
 
-      a.comments.addToSet({ title: 'monkey' });
+      a.comments.addToSet({title: 'monkey'});
       b.markModified('comments');
 
       var d = b.$__delta();
@@ -245,8 +248,8 @@ describe('versioning', function() {
       assert.ok(/No matching document/.test(err), 'changes to b should not be applied');
       assert.equal(5, a.comments.length);
 
-      a.comments.addToSet({ title: 'aven' });
-      a.comments.addToSet({ title: 'avengers' });
+      a.comments.addToSet({title: 'aven'});
+      a.comments.addToSet({title: 'avengers'});
       var d = a.$__delta();
 
       assert.equal(undefined, d[0].__v, 'version should not be included in where clause');
@@ -286,40 +289,51 @@ describe('versioning', function() {
     function save(a, b, cb) {
       var e;
       // make sure that a saves before b
-      a.save(function(err) {
-        if (err) e = err;
-        b.save(function(err) {
-          if (err) e = err;
+      a.save(function (err) {
+        if (err) {
+          e = err;
+        }
+        b.save(function (err) {
+          if (err) {
+            e = err;
+          }
           lookup();
         });
       });
       function lookup() {
         var a1, b1;
-        V.findById(a, function(err, a_) {
-          if (err && !e) e = err;
+        V.findById(a, function (err, a_) {
+          if (err && !e) {
+            e = err;
+          }
           a1 = a_;
-          a1 && b1 && cb(e, a1, b1);
+          if (a1 && b1) {
+            cb(e, a1, b1);
+          }
         });
-        V.findById(b, function(err, b_) {
-          if (err && !e) e = err;
+        V.findById(b, function (err, b_) {
+          if (err && !e) {
+            e = err;
+          }
           b1 = b_;
-          a1 && b1 && cb(e, a1, b1);
+          if (a1 && b1) {
+            cb(e, a1, b1);
+          }
         });
       }
     }
-
   });
 
-  it('versioning without version key', function(done) {
+  it('versioning without version key', function (done) {
     var V = db.model('Versioning');
 
     var doc = new V;
-    doc.numbers = [3,4,5,6,7];
+    doc.numbers = [3, 4, 5, 6, 7];
     doc.comments = [
-        { title: 'does it work?', date: new Date },
-       { title: '1', comments: [{ title: 'this is sub #1'},{ title: 'this is sub #2'}] },
-       { title: '2', comments: [{ title: 'this is sub #3'},{ title: 'this is sub #4'}] },
-       { title: 'hi', date: new Date }
+      {title: 'does it work?', date: new Date},
+      {title: '1', comments: [{title: 'this is sub #1'}, {title: 'this is sub #2'}]},
+      {title: '2', comments: [{title: 'this is sub #3'}, {title: 'this is sub #4'}]},
+      {title: 'hi', date: new Date}
     ];
 
     doc.save(test);
@@ -327,7 +341,7 @@ describe('versioning', function() {
     function test(err) {
       assert.ifError(err);
       // test getting docs back from db missing version key
-      V.findById(doc).select('numbers comments').exec(function(err, doc) {
+      V.findById(doc).select('numbers comments').exec(function (err, doc) {
         assert.ifError(err);
         doc.comments[0].title = 'no version was included';
         var d = doc.$__delta();
@@ -337,21 +351,21 @@ describe('versioning', function() {
     }
   });
 
-  it('version works with strict docs', function(done) {
-    var schema = new Schema({ str: ['string'] }, { strict: true, collection: 'versionstrict_' + random() });
+  it('version works with strict docs', function (done) {
+    var schema = new Schema({str: ['string']}, {strict: true, collection: 'versionstrict_' + random()});
     var M = db.model('VersionStrict', schema);
-    var m = new M({ str: ['death', 'to', 'smootchy'] });
-    m.save(function(err) {
+    var m = new M({str: ['death', 'to', 'smootchy']});
+    m.save(function (err) {
       assert.ifError(err);
-      M.find(m, function(err, m) {
+      M.find(m, function (err, m) {
         assert.ifError(err);
         assert.equal(1, m.length);
         m = m[0];
         assert.equal(0, m._doc.__v);
         m.str.pull('death');
-        m.save(function(err) {
+        m.save(function (err) {
           assert.ifError(err);
-          M.findById(m, function(err, m) {
+          M.findById(m, function (err, m) {
             assert.ifError(err);
             assert.equal(1, m._doc.__v);
             assert.equal(2, m.str.length);
@@ -363,12 +377,12 @@ describe('versioning', function() {
     });
   });
 
-  it('version works with existing unversioned docs', function(done) {
+  it('version works with existing unversioned docs', function (done) {
     var V = db.model('Versioning');
 
-    V.collection.insert({ title: 'unversioned', numbers: [1,2,3] }, {safe: true}, function(err) {
+    V.collection.insert({title: 'unversioned', numbers: [1, 2, 3]}, {safe: true}, function (err) {
       assert.ifError(err);
-      V.findOne({ title: 'unversioned' }, function(err, d) {
+      V.findOne({title: 'unversioned'}, function (err, d) {
         assert.ifError(err);
         assert.ok(!d._doc.__v);
         d.numbers.splice(1, 1, 10);
@@ -376,10 +390,10 @@ describe('versioning', function() {
         assert.equal(undefined, o[0].__v);
         assert.ok(o[1].$inc);
         assert.equal(1, o[1].$inc.__v);
-        d.save(function(err, d) {
+        d.save(function (err, d) {
           assert.ifError(err);
           assert.equal(1, d._doc.__v);
-          V.findById(d, function(err, d) {
+          V.findById(d, function (err, d) {
             assert.ifError(err);
             assert.ok(d);
             done();
@@ -389,15 +403,15 @@ describe('versioning', function() {
     });
   });
 
-  it('versionKey is configurable', function(done) {
+  it('versionKey is configurable', function (done) {
     var schema = new Schema(
-        { configured: 'bool' },
-       { versionKey: 'lolwat', collection: 'configuredversion' + random() });
+        {configured: 'bool'},
+        {versionKey: 'lolwat', collection: 'configuredversion' + random()});
     var V = db.model('ConfiguredVersionKey', schema);
-    var v = new V({ configured: true });
-    v.save(function(err) {
+    var v = new V({configured: true});
+    v.save(function (err) {
       assert.ifError(err);
-      V.findById(v, function(err, v) {
+      V.findById(v, function (err, v) {
         assert.ifError(err);
         assert.equal(0, v._doc.lolwat);
         done();
@@ -405,14 +419,14 @@ describe('versioning', function() {
     });
   });
 
-  it('can be disabled', function(done) {
-    var schema = Schema({ x: ['string'] }, { versionKey: false });
+  it('can be disabled', function (done) {
+    var schema = Schema({x: ['string']}, {versionKey: false});
     var M = db.model('disabledVersioning', schema, 's' + random());
-    M.create({ x: ['hi'] }, function(err, doc) {
+    M.create({x: ['hi']}, function (err, doc) {
       assert.ifError(err);
       assert.equal(false, '__v' in doc._doc);
       doc.x.pull('hi');
-      doc.save(function(err) {
+      doc.save(function (err) {
         assert.ifError(err);
         assert.equal(false, '__v' in doc._doc);
 
@@ -420,7 +434,7 @@ describe('versioning', function() {
         var d = doc.$__delta()[0];
         assert.equal(undefined, d.__v, 'version should not be added to where clause');
 
-        M.collection.findOne({ _id: doc._id }, function(err, doc) {
+        M.collection.findOne({_id: doc._id}, function (err, doc) {
           assert.equal(false, '__v' in doc);
           done();
         });
@@ -428,34 +442,34 @@ describe('versioning', function() {
     });
   });
 
-  it('works with numbericAlpha paths', function(done) {
+  it('works with numbericAlpha paths', function (done) {
     var M = db.model('Versioning');
-    var m = new M({ mixed: {} });
+    var m = new M({mixed: {}});
     var path = 'mixed.4a';
     m.set(path, 2);
-    m.save(function(err) {
+    m.save(function (err) {
       assert.ifError(err);
       done();
     });
   });
 
-  describe('doc.increment()', function() {
-    it('works without any other changes (gh-1475)', function(done) {
+  describe('doc.increment()', function () {
+    it('works without any other changes (gh-1475)', function (done) {
       var V = db.model('Versioning');
 
       var doc = new V;
-      doc.save(function(err) {
+      doc.save(function (err) {
         assert.ifError(err);
         assert.equal(0, doc.__v);
 
         doc.increment();
 
-        doc.save(function(err) {
+        doc.save(function (err) {
           assert.ifError(err);
 
           assert.equal(1, doc.__v);
 
-          V.findById(doc, function(err, doc) {
+          V.findById(doc, function (err, doc) {
             assert.ifError(err);
             assert.equal(1, doc.__v);
             done();
@@ -465,27 +479,27 @@ describe('versioning', function() {
     });
   });
 
-  describe('versioning is off', function() {
-    it('when { safe: false } is set (gh-1520)', function(done) {
-      var schema1 = new Schema({ title: String}, { safe: false });
+  describe('versioning is off', function () {
+    it('when { safe: false } is set (gh-1520)', function (done) {
+      var schema1 = new Schema({title: String}, {safe: false});
       assert.equal(schema1.options.versionKey, false);
       done();
     });
-    it('when { safe: { w: 0 }} is set (gh-1520)', function(done) {
-      var schema1 = new Schema({ title: String}, { safe: { w: 0 } });
+    it('when { safe: { w: 0 }} is set (gh-1520)', function (done) {
+      var schema1 = new Schema({title: String}, {safe: {w: 0}});
       assert.equal(schema1.options.versionKey, false);
       done();
     });
   });
 
-  it('gh-1898', function(done) {
-    var schema = new Schema({ tags: [String], name: String });
+  it('gh-1898', function (done) {
+    var schema = new Schema({tags: [String], name: String});
 
     var M = db.model('gh-1898', schema, 'gh-1898');
 
-    var m = new M({ tags: ['eggs'] });
+    var m = new M({tags: ['eggs']});
 
-    m.save(function(err) {
+    m.save(function (err) {
       assert.ifError(err);
 
       m.tags.push('bacon');
@@ -499,16 +513,16 @@ describe('versioning', function() {
     });
   });
 
-  it('can remove version key from toObject() (gh-2675)', function(done) {
-    var schema = new Schema({ name: String });
+  it('can remove version key from toObject() (gh-2675)', function (done) {
+    var schema = new Schema({name: String});
     var M = db.model('gh2675', schema, 'gh2675');
 
     var m = new M();
-    m.save(function(err, m) {
+    m.save(function (err, m) {
       assert.ifError(err);
       var obj = m.toObject();
       assert.equal(0, obj.__v);
-      obj = m.toObject({ versionKey: false });
+      obj = m.toObject({versionKey: false});
       assert.equal(undefined, obj.__v);
       done();
     });
diff --git a/website.js b/website.js
index c8f2ee3e86f..76f4cace21f 100644
--- a/website.js
+++ b/website.js
@@ -1,4 +1,3 @@
-
 var fs = require('fs');
 var jade = require('jade');
 var package = require('./package');
@@ -17,12 +16,12 @@ package.unstable = getUnstable(package.version);
 var filemap = require('./docs/source');
 var files = Object.keys(filemap);
 
-files.forEach(function(file) {
+files.forEach(function (file) {
   var filename = __dirname + '/' + file;
   jadeify(filename, filemap[file]);
 
   if ('--watch' == process.argv[2]) {
-    fs.watchFile(filename, { interval: 1000 }, function(cur, prev) {
+    fs.watchFile(filename, {interval: 1000}, function (cur, prev) {
       if (cur.mtime > prev.mtime) {
         jadeify(filename, filemap[file]);
       }
@@ -32,48 +31,55 @@ files.forEach(function(file) {
 
 var acquit = require('./docs/source/acquit');
 var acquitFiles = Object.keys(acquit);
-acquitFiles.forEach(function(file) {
+acquitFiles.forEach(function (file) {
   var filename = __dirname + '/docs/acquit.jade';
   jadeify(filename, acquit[file], __dirname + '/docs/' + file);
 });
 
 function jadeify(filename, options, newfile) {
-  options || (options = {});
+  options = options || {};
   options.package = package;
   options.hl = hl;
   options.linktype = linktype;
   options.href = href;
   options.klass = klass;
-  jade.renderFile(filename, options, function(err, str) {
-    if (err) return console.error(err.stack);
+  jade.renderFile(filename, options, function (err, str) {
+    if (err) {
+      return console.error(err.stack);
+    }
 
     newfile = newfile || filename.replace('.jade', '.html');
-    fs.writeFile(newfile, str, function(err) {
-      if (err) return console.error('could not write', err.stack);
+    fs.writeFile(newfile, str, function (err) {
+      if (err) {
+        return console.error('could not write', err.stack);
+      }
       console.log('%s : rendered ', new Date, newfile);
     });
   });
 }
 
 function getVersion() {
-  var hist = fs.readFileSync('./History.md','utf8').replace(/\r/g, '\n').split('\n');
+  var hist = fs.readFileSync('./History.md', 'utf8').replace(/\r/g, '\n').split('\n');
   for (var i = 0; i < hist.length; ++i) {
     var line = (hist[i] || '').trim();
-    if (!line) continue;
+    if (!line) {
+      continue;
+    }
     var match = /^\s*([^\s]+)\s/.exec(line);
-    if (match && match[1])
+    if (match && match[1]) {
       return match[1];
+    }
   }
   throw new Error('no match found');
 }
 
 function getUnstable(ver) {
-  ver = ver.replace("-pre");
+  ver = ver.replace('-pre');
   var spl = ver.split('.');
-  spl = spl.map(function(i) {
-    return parseInt(i);
+  spl = spl.map(function (i) {
+    return parseInt(i, 10);
   });
   spl[1]++;
-  spl[2] = "x";
+  spl[2] = 'x';
   return spl.join('.');
 }

From 7b5288852650c11c20fab885ede5ebcb2c76f036 Mon Sep 17 00:00:00 2001
From: CTAPbIuMABP 
Date: Sun, 31 Jan 2016 16:54:52 +0800
Subject: [PATCH 0237/2240] even more strict

---
 benchmarks/benchjs/delete.js                  |   4 +-
 benchmarks/benchjs/multiop.js                 |  20 +-
 bin/mongoose.debug.js                         |  28 +-
 bin/mongoose.js                               |  34 +-
 docs/helpers/href.js                          |   2 +-
 docs/helpers/linktype.js                      |   2 +-
 docs/includes/googleanalytics.jade            |   2 +-
 docs/includes/googlesearch.jade               |   2 +-
 docs/source/api.js                            |   8 +-
 examples/schema/schema.js                     |   2 +-
 index.html                                    |   2 +-
 lib/ES6Promise.js                             |   2 +-
 lib/aggregate.js                              |  14 +-
 lib/browserDocument.js                        |   2 +-
 lib/cast.js                                   |  18 +-
 lib/collection.js                             |   7 +-
 lib/connection.js                             |  80 ++--
 lib/document.js                               | 166 ++++----
 lib/drivers/node-mongodb-native/collection.js |  42 +--
 lib/drivers/node-mongodb-native/connection.js |  42 +--
 lib/error/validation.js                       |   5 +-
 lib/index.js                                  |   8 +-
 lib/model.js                                  | 144 +++----
 lib/query.js                                  | 111 +++---
 lib/querystream.js                            |  32 +-
 lib/schema.js                                 |  40 +-
 lib/schema/array.js                           |  16 +-
 lib/schema/boolean.js                         |   6 +-
 lib/schema/buffer.js                          |   6 +-
 lib/schema/date.js                            |  16 +-
 lib/schema/number.js                          |  22 +-
 lib/schema/objectid.js                        |   6 +-
 lib/schema/operators/bitwise.js               |   8 +-
 lib/schema/string.js                          |  34 +-
 lib/schematype.js                             |  52 +--
 lib/statemachine.js                           |   8 +-
 lib/types/array.js                            |  14 +-
 lib/types/buffer.js                           |   8 +-
 lib/types/documentarray.js                    |  10 +-
 lib/types/embedded.js                         |   6 +-
 lib/utils.js                                  |  34 +-
 static.js                                     |   2 +-
 test/aggregate.test.js                        |   4 +-
 test/browser/schema.validation.test_.js       |   8 +-
 test/browser/types.objectid.test_.js          |   2 +-
 test/connection.test.js                       |  18 +-
 test/document.hooks.test.js                   |  10 +-
 test/document.test.js                         |   8 +-
 test/index.test.js                            |   8 +-
 test/model.aggregate.test.js                  |   2 +-
 test/model.findOneAndUpdate.test.js           |  29 +-
 test/model.geonear.test.js                    |   2 +-
 test/model.hydrate.test.js                    |   2 +-
 test/model.indexes.test.js                    |   6 +-
 test/model.mapreduce.test.js                  |  16 +-
 test/model.middleware.test.js                 |  10 +-
 test/model.populate.test.js                   |  10 +-
 test/model.querying.test.js                   |  30 +-
 test/model.stream.test.js                     | 122 +++---
 test/model.test.js                            | 342 ++++++++---------
 test/model.update.test.js                     |  48 ++-
 test/promise.test.js                          |   2 +-
 test/promise_provider.test.js                 |  12 +-
 test/query.test.js                            |  12 +-
 test/schema.select.test.js                    |   4 +-
 test/schema.test.js                           |   2 +-
 test/schema.timestamps.test.js                |   4 +-
 test/schema.validation.test.js                | 101 +++--
 test/shard.test.js                            |   2 +-
 test/types.array.test.js                      |  12 +-
 test/types.documentarray.test.js              |   4 +-
 test/utils.test.js                            |   6 +-
 test/versioning.test.js                       | 354 +++++++++---------
 website.js                                    |  94 ++---
 74 files changed, 1184 insertions(+), 1169 deletions(-)

diff --git a/benchmarks/benchjs/delete.js b/benchmarks/benchjs/delete.js
index f5015a7cace..62287084602 100644
--- a/benchmarks/benchjs/delete.js
+++ b/benchmarks/benchjs/delete.js
@@ -68,13 +68,13 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
 
     function closeDB() {
       User.count(function (err, res) {
-        if (res != 0) {
+        if (res !== 0) {
           console.log('Still mongoose entries left...');
         }
         mongoose.disconnect();
       });
       user.count({}, function (err, res) {
-        if (res != 0) {
+        if (res !== 0) {
           console.log('Still driver entries left...');
         }
         if (err) {
diff --git a/benchmarks/benchjs/multiop.js b/benchmarks/benchjs/multiop.js
index 3423525a890..13da718b9f4 100644
--- a/benchmarks/benchjs/multiop.js
+++ b/benchmarks/benchjs/multiop.js
@@ -190,7 +190,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
             }
             --count || deferred.resolve();
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             var nData = utils.clone(data);
             User.create(nData, function (err) {
               if (err) {
@@ -212,7 +212,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
             }
             --count || deferred.resolve();
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             var nData = utils.clone(data);
             user.insert(nData, function (err) {
               if (err) {
@@ -234,7 +234,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
             }
             --count || deferred.resolve();
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             var nData = utils.clone(blogData);
             BlogPost.create(nData, function (err) {
               if (err) {
@@ -256,7 +256,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
             }
             --count || deferred.resolve();
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             var nData = utils.clone(blogData);
             blogpost.insert(nData, function (err) {
               if (err) {
@@ -280,7 +280,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
             }
             --count || deferred.resolve();
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             User.findOne({_id: getNextmId()}, function (err) {
               if (err) {
                 throw err;
@@ -303,7 +303,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
             }
             --count || deferred.resolve();
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             user.findOne({_id: getNextdId()}, function (err) {
               if (err) {
                 throw err;
@@ -326,7 +326,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
             }
             --count || deferred.resolve();
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             BlogPost.findOne({_id: getNextbmId()}, function (err) {
               if (err) {
                 throw err;
@@ -349,7 +349,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
             }
             --count || deferred.resolve();
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             blogpost.findOne({_id: getNextbdId()}, function (err) {
               if (err) {
                 throw err;
@@ -384,7 +384,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
               --count || deferred.resolve();
             }
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             var nData = utils.clone(blogData);
             BlogPost.create(nData, function (err) {
               if (err) {
@@ -420,7 +420,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
               --count || deferred.resolve();
             }
           });
-          if (i % 15 == 0) {
+          if (i % 15 === 0) {
             var nData = utils.clone(blogData);
             blogpost.insert(nData, function (err) {
               if (err) {
diff --git a/bin/mongoose.debug.js b/bin/mongoose.debug.js
index c7d0253b309..0db5f07b756 100644
--- a/bin/mongoose.debug.js
+++ b/bin/mongoose.debug.js
@@ -263,7 +263,7 @@ var cast = module.exports = function(schema, obj) {
         throw new Error("Must have a string or function for $where");
       }
 
-      if ('function' === type) {
+      if (type === 'function') {
         obj[path] = val.toString();
       }
 
@@ -379,7 +379,7 @@ var cast = module.exports = function(schema, obj) {
 
       } else if (val === null || val === undefined) {
         continue;
-      } else if ('Object' === val.constructor.name) {
+      } else if (val.constructor.name === 'Object') {
 
         any$conditionals = Object.keys(val).some(function (k) {
           return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
@@ -577,7 +577,7 @@ Document.prototype.$__buildDoc = function (obj, fields, skipId) {
 
   // determine if this doc is a result of a query with
   // excluded fields
-  if (fields && 'Object' === utils.getFunctionName(fields.constructor)) {
+  if (fields && utils.getFunctionName(fields.constructor) === 'Object') {
     keys = Object.keys(fields);
     ki = keys.length;
 
@@ -895,7 +895,7 @@ Document.prototype.set = function (path, val, type, options) {
           ) {
           this.set(path[key], prefix + key, constructing);
         } else if (strict) {
-          if ('real' === pathtype || 'virtual' === pathtype) {
+          if ('real' === pathtype || pathtype === 'virtual') {
             this.set(prefix + key, path[key], constructing);
           } else if ('throw' == strict) {
             throw new Error("Field `" + key + "` is not in schema.");
@@ -1088,7 +1088,7 @@ Document.prototype.$__set = function (
     if (last) {
       obj[parts[i]] = val;
     } else {
-      if (obj[parts[i]] && 'Object' === utils.getFunctionName(obj[parts[i]].constructor)) {
+      if (obj[parts[i]] && utils.getFunctionName(obj[parts[i]].constructor) === 'Object') {
         obj = obj[parts[i]];
       } else if (obj[parts[i]] && obj[parts[i]] instanceof Embedded) {  
         obj = obj[parts[i]];
@@ -1658,7 +1658,7 @@ function compile (tree, proto, prefix) {
     limb = tree[key];
 
     define(key
-        , (('Object' === utils.getFunctionName(limb.constructor)
+        , ((utils.getFunctionName(limb.constructor === 'Object')
                && Object.keys(limb).length)
                && (!limb.type || limb.type.type)
                ? limb
@@ -4204,7 +4204,7 @@ function SchemaArray (key, cast, options) {
   if (cast) {
     var castOptions = {};
 
-    if ('Object' === utils.getFunctionName(cast.constructor)) {
+    if (utils.getFunctionName(cast.constructor) === 'Object') {
       if (cast.type) {
         // support { type: Woot }
         castOptions = utils.clone(cast); // do not alter user arguments
@@ -4307,7 +4307,7 @@ SchemaArray.prototype.cast = function (value, doc, init) {
 
       for (var i = 0, l = indexes.length; i < l; ++i) {
         var pathIndex = indexes[i][0][this.path];
-        if ('2dsphere' === pathIndex || '2d' === pathIndex) {
+        if ('2dsphere' === pathIndex || pathIndex === '2d') {
           return;
         }
       }
@@ -4602,9 +4602,9 @@ SchemaBoolean.prototype.checkRequired = function (value) {
 
 SchemaBoolean.prototype.cast = function (value) {
   if (null === value) return value;
-  if ('0' === value) return false;
-  if ('true' === value) return true;
-  if ('false' === value) return false;
+  if (value === '0') return false;
+  if (value === 'true') return true;
+  if (value === 'false') return false;
   return !! value;
 }
 
@@ -6647,7 +6647,7 @@ SchemaType.prototype.get = function (fn) {
  */
 
 SchemaType.prototype.validate = function (obj, message, type) {
-  if ('function' == typeof obj || obj && 'RegExp' === utils.getFunctionName(obj.constructor)) {
+  if ('function' == typeof obj || obj && utils.getFunctionName(obj.constructor) === 'RegExp') {
     var properties;
     if (message instanceof Object && !type) {
       properties = utils.clone(message);
@@ -6670,7 +6670,7 @@ SchemaType.prototype.validate = function (obj, message, type) {
 
   for (i=0, length=arguments.length; i' + type + '';
   }
   return '' + type + '';
diff --git a/docs/includes/googleanalytics.jade b/docs/includes/googleanalytics.jade
index aaafe24e32d..f589283902c 100644
--- a/docs/includes/googleanalytics.jade
+++ b/docs/includes/googleanalytics.jade
@@ -5,6 +5,6 @@ script.
 
   (function() {
     var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
-    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+    ga.src = ('https:' === document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
     var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
   })();
diff --git a/docs/includes/googlesearch.jade b/docs/includes/googlesearch.jade
index 3a285f28c8e..04596e9cfd2 100644
--- a/docs/includes/googlesearch.jade
+++ b/docs/includes/googlesearch.jade
@@ -4,7 +4,7 @@ script
     var gcse = document.createElement('script');
     gcse.type = 'text/javascript';
     gcse.async = true;
-    gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+    gcse.src = (document.location.protocol === 'https:' ? 'https:' : 'http:') +
         '//www.google.com/cse/cse.js?cx=' + cx;
     var s = document.getElementsByTagName('script')[0];
     s.parentNode.insertBefore(gcse, s);
diff --git a/docs/source/api.js b/docs/source/api.js
index f1e01d1dcb9..998a59cf77f 100644
--- a/docs/source/api.js
+++ b/docs/source/api.js
@@ -147,7 +147,7 @@ function parse (docs) {
 
     // add constructor to properties too
     methods.some(function (method) {
-      if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) {
+      if (method.ctx && 'method' === method.ctx.type && method.ctx.hasOwnProperty('constructor')) {
         props.forEach(function (prop) {
           prop.ctx.constructor = method.ctx.constructor;
         });
@@ -201,7 +201,7 @@ function fix (str) {
     // parse out the ```language
     var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
 
-    if ('js' == code[1] || !code[1]) {
+    if ('js' === code[1] || !code[1]) {
       code[1] = 'javascript';
     }
 
@@ -226,9 +226,9 @@ function order (docs) {
   for (var i = 0; i < docs.length; ++i) {
     var doc = docs[i];
 
-    if ('index.js' == doc.title) {
+    if ('index.js' === doc.title) {
       docs.unshift(docs.splice(i, 1)[0]);
-    } else if ('collection.js' == doc.title) {
+    } else if ('collection.js' === doc.title) {
       docs.push(docs.splice(i, 1)[0]);
     }
 
diff --git a/examples/schema/schema.js b/examples/schema/schema.js
index 66ce872cd7c..489dcaaea3d 100644
--- a/examples/schema/schema.js
+++ b/examples/schema/schema.js
@@ -64,7 +64,7 @@ BlogPost.path('date')
   return new Date();
 })
 .set(function (v) {
-  return v == 'now' ? new Date() : v;
+  return v === 'now' ? new Date() : v;
 });
 
 /**
diff --git a/index.html b/index.html
index eeb3de3af24..a7b481e8bcb 100644
--- a/index.html
+++ b/index.html
@@ -14,6 +14,6 @@
 
 (function() {
   var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
-  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+  ga.src = ('https:' === document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
   var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
 })();
diff --git a/lib/ES6Promise.js b/lib/ES6Promise.js
index 4c112386285..a513d95e27b 100644
--- a/lib/ES6Promise.js
+++ b/lib/ES6Promise.js
@@ -18,7 +18,7 @@
  */
 
 function ES6Promise(fn) {
-  throw 'Can\'t use ES6 promise with mpromise style constructor';
+  throw new Error('Can\'t use ES6 promise with mpromise style constructor');
 }
 
 ES6Promise.use = function (Promise) {
diff --git a/lib/aggregate.js b/lib/aggregate.js
index fa38b377805..753f0b7b32a 100644
--- a/lib/aggregate.js
+++ b/lib/aggregate.js
@@ -131,14 +131,14 @@ Aggregate.prototype.append = function () {
 Aggregate.prototype.project = function (arg) {
   var fields = {};
 
-  if ('object' === typeof arg && !util.isArray(arg)) {
+  if (typeof arg === 'object' && !util.isArray(arg)) {
     Object.keys(arg).forEach(function (field) {
       fields[field] = arg[field];
     });
-  } else if (1 === arguments.length && 'string' === typeof arg) {
+  } else if (1 === arguments.length && typeof arg === 'string') {
     arg.split(/\s+/).forEach(function (field) {
       if (!field) return;
-      var include = '-' == field[0] ? 0 : 1;
+      var include = '-' === field[0] ? 0 : 1;
       if (include === 0) field = field.substring(1);
       fields[field] = include;
     });
@@ -337,15 +337,15 @@ Aggregate.prototype.sort = function (arg) {
 
   var sort = {};
 
-  if ('Object' === arg.constructor.name) {
+  if (arg.constructor.name === 'Object') {
     var desc = ['desc', 'descending', -1];
     Object.keys(arg).forEach(function (field) {
       sort[field] = desc.indexOf(arg[field]) === -1 ? 1 : -1;
     });
-  } else if (1 === arguments.length && 'string' == typeof arg) {
+  } else if (1 === arguments.length && typeof arg === 'string') {
     arg.split(/\s+/).forEach(function (field) {
       if (!field) return;
-      var ascend = '-' == field[0] ? -1 : 1;
+      var ascend = '-' === field[0] ? -1 : 1;
       if (ascend === -1) field = field.substring(1);
       sort[field] = ascend;
     });
@@ -555,7 +555,7 @@ Aggregate.prototype.exec = function (callback) {
 function isOperator(obj) {
   var k;
 
-  if ('object' !== typeof obj) {
+  if (typeof obj !== 'object') {
     return false;
   }
 
diff --git a/lib/browserDocument.js b/lib/browserDocument.js
index 196b31eb6c5..6c87d199629 100644
--- a/lib/browserDocument.js
+++ b/lib/browserDocument.js
@@ -58,7 +58,7 @@ function Document(obj, schema, fields, skipId, skipInit) {
 
   // var schema = this.schema;
 
-  if ('boolean' === typeof fields) {
+  if (typeof fields === 'boolean') {
     this.$__.strictMode = fields;
     fields = undefined;
   } else {
diff --git a/lib/cast.js b/lib/cast.js
index 57b52226569..728638ee246 100644
--- a/lib/cast.js
+++ b/lib/cast.js
@@ -40,7 +40,7 @@ var cast = module.exports = function (schema, obj) {
         throw new Error('Must have a string or function for $where');
       }
 
-      if ('function' === type) {
+      if (type === 'function') {
         obj[path] = val.toString();
       }
 
@@ -104,7 +104,7 @@ var cast = module.exports = function (schema, obj) {
             val.$maxDistance = numbertype.castForQuery(val.$maxDistance);
           }
 
-          if ('$within' == geo) {
+          if ('$within' === geo) {
             var withinType = value.$center
                           || value.$centerSphere
                           || value.$box
@@ -115,12 +115,12 @@ var cast = module.exports = function (schema, obj) {
             }
 
             value = withinType;
-          } else if ('$near' == geo &&
-              'string' == typeof value.type && Array.isArray(value.coordinates)) {
+          } else if ('$near' === geo &&
+              typeof value.type === 'string' && Array.isArray(value.coordinates)) {
             // geojson; cast the coordinates
             value = value.coordinates;
-          } else if (('$near' == geo || '$nearSphere' == geo || '$geoIntersects' == geo) &&
-              value.$geometry && 'string' == typeof value.$geometry.type &&
+          } else if (('$near' === geo || '$nearSphere' === geo || '$geoIntersects' === geo) &&
+              value.$geometry && typeof value.$geometry.type === 'string' &&
               Array.isArray(value.$geometry.coordinates)) {
             // geojson; cast the coordinates
             value = value.$geometry.coordinates;
@@ -153,7 +153,7 @@ var cast = module.exports = function (schema, obj) {
       } else if (val === null || val === undefined) {
         obj[path] = null;
         continue;
-      } else if ('Object' === val.constructor.name) {
+      } else if (val.constructor.name === 'Object') {
         any$conditionals = Object.keys(val).some(function (k) {
           return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
         });
@@ -171,14 +171,14 @@ var cast = module.exports = function (schema, obj) {
             nested = val[$cond];
 
             if ('$exists' === $cond) {
-              if ('boolean' !== typeof nested) {
+              if (typeof nested !== 'boolean') {
                 throw new Error('$exists parameter must be Boolean');
               }
               continue;
             }
 
             if ('$type' === $cond) {
-              if ('number' !== typeof nested) {
+              if (typeof nested !== 'number') {
                 throw new Error('$type parameter must be Number');
               }
               continue;
diff --git a/lib/collection.js b/lib/collection.js
index 2d30673e64f..f44d211adc6 100644
--- a/lib/collection.js
+++ b/lib/collection.js
@@ -25,7 +25,7 @@ function Collection(name, conn, opts) {
     ? true
     : opts.bufferCommands;
 
-  if ('number' == typeof opts.capped) {
+  if (typeof opts.capped === 'number') {
     opts.capped = {size: opts.capped};
   }
 
@@ -37,7 +37,7 @@ function Collection(name, conn, opts) {
   this.buffer = this.opts.bufferCommands;
   this.emitter = new EventEmitter();
 
-  if (STATES.connected == this.conn.readyState) {
+  if (STATES.connected === this.conn.readyState) {
     this.onOpen();
   }
 }
@@ -76,9 +76,8 @@ Collection.prototype.conn;
  */
 
 Collection.prototype.onOpen = function () {
-  var self = this;
   this.buffer = false;
-  self.doQueue();
+  this.doQueue();
 };
 
 /**
diff --git a/lib/connection.js b/lib/connection.js
index d1df9202f2f..cda8429bbe3 100644
--- a/lib/connection.js
+++ b/lib/connection.js
@@ -176,7 +176,7 @@ Connection.prototype.config;
 Connection.prototype.open = function (host, database, port, options, callback) {
   var parsed;
 
-  if ('string' === typeof database) {
+  if (typeof database === 'string') {
     switch (arguments.length) {
       case 2:
         port = 27017;
@@ -184,22 +184,26 @@ Connection.prototype.open = function (host, database, port, options, callback) {
       case 3:
         switch (typeof port) {
           case 'function':
-            callback = port, port = 27017;
+            callback = port;
+            port = 27017;
             break;
           case 'object':
-            options = port, port = 27017;
+            options = port;
+            port = 27017;
             break;
         }
         break;
       case 4:
-        if ('function' === typeof options) {
-          callback = options, options = {};
+        if (typeof options === 'function') {
+          callback = options;
+          options = {};
         }
     }
   } else {
     switch (typeof database) {
       case 'function':
-        callback = database, database = undefined;
+        callback = database;
+        database = undefined;
         break;
       case 'object':
         options = database;
@@ -272,10 +276,10 @@ Connection.prototype.open = function (host, database, port, options, callback) {
   this.host = host;
   this.port = port;
 
-  var self = this;
+  var _this = this;
   var Promise = PromiseProvider.get();
   return new Promise.ES6(function (resolve, reject) {
-    self._open(!!callback, function (error) {
+    _this._open(!!callback, function (error) {
       callback && callback(error);
       if (error) {
         reject(error);
@@ -348,7 +352,7 @@ Connection.prototype.openSet = function (uris, database, options, callback) {
           break;
       }
 
-      if ('function' === typeof options) {
+      if (typeof options === 'function') {
         callback = options;
         options = {};
       }
@@ -359,10 +363,12 @@ Connection.prototype.openSet = function (uris, database, options, callback) {
           this.name = database;
           break;
         case 'function':
-          callback = database, database = null;
+          callback = database;
+          database = null;
           break;
         case 'object':
-          options = database, database = null;
+          options = database;
+          database = null;
           break;
       }
   }
@@ -404,10 +410,10 @@ Connection.prototype.openSet = function (uris, database, options, callback) {
     this.config.autoIndex = options.config.autoIndex !== false;
   }
 
-  var self = this;
+  var _this = this;
   var Promise = PromiseProvider.get();
   return new Promise.ES6(function (resolve, reject) {
-    self._open(!!callback, function (error) {
+    _this._open(!!callback, function (error) {
       callback && callback(error);
       if (error) {
         reject(error);
@@ -445,7 +451,7 @@ Connection.prototype._open = function (emit, callback) {
   this.readyState = STATES.connecting;
   this._closeCalled = false;
 
-  var self = this;
+  var _this = this;
 
   var method = this.replica
     ? 'doOpenSet'
@@ -454,16 +460,16 @@ Connection.prototype._open = function (emit, callback) {
   // open connection
   this[method](function (err) {
     if (err) {
-      self.readyState = STATES.disconnected;
-      if (self._hasOpened) {
+      _this.readyState = STATES.disconnected;
+      if (_this._hasOpened) {
         if (callback) callback(err);
       } else {
-        self.error(err, emit && callback);
+        _this.error(err, emit && callback);
       }
       return;
     }
 
-    self.onOpen(callback);
+    _this.onOpen(callback);
   });
 };
 
@@ -474,36 +480,36 @@ Connection.prototype._open = function (emit, callback) {
  */
 
 Connection.prototype.onOpen = function (callback) {
-  var self = this;
+  var _this = this;
 
   function open(err, isAuth) {
     if (err) {
-      self.readyState = isAuth ? STATES.unauthorized : STATES.disconnected;
-      if (self._hasOpened) {
+      _this.readyState = isAuth ? STATES.unauthorized : STATES.disconnected;
+      if (_this._hasOpened) {
         if (callback) {
           callback(err);
         }
       } else {
-        self.error(err, callback);
+        _this.error(err, callback);
       }
       return;
     }
 
-    self.readyState = STATES.connected;
+    _this.readyState = STATES.connected;
 
     // avoid having the collection subscribe to our event emitter
     // to prevent 0.3 warning
-    for (var i in self.collections) {
-      self.collections[i].onOpen();
+    for (var i in _this.collections) {
+      _this.collections[i].onOpen();
     }
 
     callback && callback();
-    self.emit('open');
+    _this.emit('open');
   }
 
   // re-authenticate
   if (this.shouldAuthenticate()) {
-    self.db.authenticate(self.user, self.pass, self.options.auth, function (err) {
+    _this.db.authenticate(_this.user, _this.pass, _this.options.auth, function (err) {
       open(err, true);
     });
   } else {
@@ -520,10 +526,10 @@ Connection.prototype.onOpen = function (callback) {
  */
 
 Connection.prototype.close = function (callback) {
-  var self = this;
+  var _this = this;
   var Promise = PromiseProvider.get();
   return new Promise.ES6(function (resolve, reject) {
-    self._close(function (error) {
+    _this._close(function (error) {
       callback && callback(error);
       if (error) {
         reject(error);
@@ -541,7 +547,7 @@ Connection.prototype.close = function (callback) {
  * @api private
  */
 Connection.prototype._close = function (callback) {
-  var self = this;
+  var _this = this;
   this._closeCalled = true;
 
   switch (this.readyState) {
@@ -554,9 +560,9 @@ Connection.prototype._close = function (callback) {
       this.readyState = STATES.disconnecting;
       this.doClose(function (err) {
         if (err) {
-          self.error(err, callback);
+          _this.error(err, callback);
         } else {
-          self.onClose();
+          _this.onClose();
           callback && callback();
         }
       });
@@ -564,7 +570,7 @@ Connection.prototype._close = function (callback) {
 
     case 2: // connecting
       this.once('open', function () {
-        self.close(callback);
+        _this.close(callback);
       });
       break;
 
@@ -649,7 +655,7 @@ Connection.prototype.collection = function (name, options) {
 
 Connection.prototype.model = function (name, schema, collection) {
   // collection name discovery
-  if ('string' == typeof schema) {
+  if (typeof schema === 'string') {
     collection = schema;
     schema = false;
   }
@@ -660,7 +666,7 @@ Connection.prototype.model = function (name, schema, collection) {
 
   if (this.models[name] && !collection) {
     // model exists but we are not subclassing with custom collection
-    if (schema && schema.instanceOfSchema && schema != this.models[name].schema) {
+    if (schema && schema.instanceOfSchema && schema !== this.models[name].schema) {
       throw new MongooseError.OverwriteModelError(name);
     }
     return this.models[name];
@@ -699,8 +705,8 @@ Connection.prototype.model = function (name, schema, collection) {
     throw new MongooseError.MissingSchemaError(name);
   }
 
-  if (this == model.prototype.db
-      && (!collection || collection == model.collection.name)) {
+  if (this === model.prototype.db
+      && (!collection || collection === model.collection.name)) {
     // model already uses this connection.
 
     // only the first model with this name is cached to allow
diff --git a/lib/document.js b/lib/document.js
index aa51044ed02..bc955920dbc 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -44,7 +44,7 @@ function Document(obj, fields, skipId) {
 
   var schema = this.schema;
 
-  if ('boolean' === typeof fields) {
+  if (typeof fields === 'boolean') {
     this.$__.strictMode = fields;
     fields = undefined;
   } else {
@@ -65,12 +65,12 @@ function Document(obj, fields, skipId) {
   }
 
   if (!schema.options.strict && obj) {
-    var self = this,
+    var _this = this,
         keys = Object.keys(this._doc);
 
     keys.forEach(function (key) {
       if (!(key in schema.tree)) {
-        defineKey(key, null, self);
+        defineKey(key, null, _this);
       }
     });
   }
@@ -153,7 +153,7 @@ Document.prototype.$__buildDoc = function (obj, fields, skipId) {
   var exclude = null;
   var keys;
   var ki;
-  var self = this;
+  var _this = this;
 
   // determine if this doc is a result of a query with
   // excluded fields
@@ -181,7 +181,7 @@ Document.prototype.$__buildDoc = function (obj, fields, skipId) {
   for (; ii < plen; ++ii) {
     var p = paths[ii];
 
-    if ('_id' == p) {
+    if (p === '_id') {
       if (skipId) {
         continue;
       }
@@ -222,24 +222,24 @@ Document.prototype.$__buildDoc = function (obj, fields, skipId) {
               continue;
             }
 
-            def = type.getDefault(self, true);
-            if ('undefined' !== typeof def) {
+            def = type.getDefault(_this, true);
+            if (typeof def !== 'undefined') {
               doc_[piece] = def;
-              self.$__.activePaths.default(p);
+              _this.$__.activePaths.default(p);
             }
           } else if (included) {
             // selected field
-            def = type.getDefault(self, true);
-            if ('undefined' !== typeof def) {
+            def = type.getDefault(_this, true);
+            if (typeof def !== 'undefined') {
               doc_[piece] = def;
-              self.$__.activePaths.default(p);
+              _this.$__.activePaths.default(p);
             }
           }
         } else {
-          def = type.getDefault(self, true);
-          if ('undefined' !== typeof def) {
+          def = type.getDefault(_this, true);
+          if (typeof def !== 'undefined') {
             doc_[piece] = def;
-            self.$__.activePaths.default(p);
+            _this.$__.activePaths.default(p);
           }
         }
       } else {
@@ -266,7 +266,7 @@ Document.prototype.init = function (doc, opts, fn) {
   // do not prefix this method with $__ since its
   // used by public hooks
 
-  if ('function' == typeof opts) {
+  if (typeof opts === 'function') {
     fn = opts;
     opts = null;
   }
@@ -275,7 +275,7 @@ Document.prototype.init = function (doc, opts, fn) {
 
   // handle docs with populated paths
   // If doc._id is not null or undefined
-  if (doc._id != null && opts && opts.populated && opts.populated.length) {
+  if (doc._id !== null && opts && opts.populated && opts.populated.length) {
     var id = String(doc._id);
     for (var i = 0; i < opts.populated.length; ++i) {
       var item = opts.populated[i];
@@ -317,7 +317,7 @@ function init(self, obj, doc, prefix) {
     schema = self.schema.path(path);
 
     if (!schema && utils.isObject(obj[i]) &&
-        (!obj[i].constructor || 'Object' == utils.getFunctionName(obj[i].constructor))) {
+        (!obj[i].constructor || 'Object' === utils.getFunctionName(obj[i].constructor))) {
       // assume nested object
       if (!doc[i]) {
         doc[i] = {};
@@ -365,7 +365,7 @@ function init(self, obj, doc, prefix) {
 Document.prototype.$__storeShard = function () {
   // backwards compat
   var key = this.schema.options.shardKey || this.schema.options.shardkey;
-  if (!(key && 'Object' == utils.getFunctionName(key.constructor))) {
+  if (!(key && 'Object' === utils.getFunctionName(key.constructor))) {
     return;
   }
 
@@ -378,7 +378,7 @@ Document.prototype.$__storeShard = function () {
     val = this.getValue(paths[i]);
     if (isMongooseObject(val)) {
       orig[paths[i]] = val.toObject({depopulate: true});
-    } else if (null != val &&
+    } else if (null !== val &&
         val.valueOf &&
           // Explicitly don't take value of dates
         (!val.constructor || utils.getFunctionName(val.constructor) !== 'Date')) {
@@ -455,7 +455,7 @@ Document.prototype.update = function update() {
  */
 
 Document.prototype.set = function (path, val, type, options) {
-  if (type && 'Object' == utils.getFunctionName(type.constructor)) {
+  if (type && 'Object' === utils.getFunctionName(type.constructor)) {
     options = type;
     type = undefined;
   }
@@ -504,10 +504,10 @@ Document.prototype.set = function (path, val, type, options) {
         var pathName = prefix + key;
         pathtype = this.schema.pathType(pathName);
 
-        if (null != path[key]
+        if (null !== path[key]
               // need to know if plain object - no Buffer, ObjectId, ref, etc
             && utils.isObject(path[key])
-            && (!path[key].constructor || 'Object' == utils.getFunctionName(path[key].constructor))
+            && (!path[key].constructor || 'Object' === utils.getFunctionName(path[key].constructor))
             && 'virtual' !== pathtype
             && 'real' !== pathtype
             && !(this.$__path(pathName) instanceof MixedSchema)
@@ -516,7 +516,7 @@ Document.prototype.set = function (path, val, type, options) {
             this.schema.paths[pathName].options.ref)) {
           this.set(path[key], prefix + key, constructing);
         } else if (strict) {
-          if ('real' === pathtype || 'virtual' === pathtype) {
+          if ('real' === pathtype || pathtype === 'virtual') {
             // Check for setting single embedded schema to document (gh-3535)
             if (this.schema.paths[pathName] &&
                 this.schema.paths[pathName].$isSingleNested &&
@@ -527,7 +527,7 @@ Document.prototype.set = function (path, val, type, options) {
           } else if (pathtype === 'nested' && path[key] instanceof Document) {
             this.set(prefix + key,
                 path[key].toObject({virtuals: false}), constructing);
-          } else if ('throw' == strict) {
+          } else if (strict === 'throw') {
             if (pathtype === 'nested') {
               throw new ObjectExpectedError(key, path[key]);
             } else {
@@ -547,9 +547,9 @@ Document.prototype.set = function (path, val, type, options) {
   // docschema = new Schema({ path: { nest: 'string' }})
   // doc.set('path', obj);
   var pathType = this.schema.pathType(path);
-  if ('nested' == pathType && val) {
+  if ('nested' === pathType && val) {
     if (utils.isObject(val) &&
-        (!val.constructor || 'Object' == utils.getFunctionName(val.constructor))) {
+        (!val.constructor || 'Object' === utils.getFunctionName(val.constructor))) {
       if (!merge) {
         this.setValue(path, null);
       }
@@ -563,7 +563,7 @@ Document.prototype.set = function (path, val, type, options) {
   var schema;
   var parts = path.split('.');
 
-  if ('adhocOrUndefined' == pathType && strict) {
+  if ('adhocOrUndefined' === pathType && strict) {
     // check for roots that are Mixed types
     var mixed;
 
@@ -578,12 +578,12 @@ Document.prototype.set = function (path, val, type, options) {
     }
 
     if (!mixed) {
-      if ('throw' == strict) {
+      if (strict === 'throw') {
         throw new StrictModeError(path);
       }
       return this;
     }
-  } else if ('virtual' == pathType) {
+  } else if (pathType === 'virtual') {
     schema = this.schema.virtualpath(path);
     schema.applySetters(val, this);
     return this;
@@ -719,7 +719,7 @@ Document.prototype.$__shouldModify = function (pathToMark, path, constructing, p
   }
 
   if (!constructing &&
-      null != val &&
+      null !== val &&
       path in this.$__.activePaths.states.default &&
       deepEqual(val, schema.getDefault(this, constructing))) {
     // a path with a default was $unset on the server
@@ -1001,7 +1001,7 @@ Document.prototype.isInit = function (path) {
 
 Document.prototype.isSelected = function isSelected(path) {
   if (this.$__.selected) {
-    if ('_id' === path) {
+    if (path === '_id') {
       return 0 !== this.$__.selected._id;
     }
 
@@ -1017,7 +1017,7 @@ Document.prototype.isSelected = function isSelected(path) {
 
     while (i--) {
       cur = paths[i];
-      if ('_id' == cur) {
+      if (cur === '_id') {
         continue;
       }
       inclusive = !!this.$__.selected[cur];
@@ -1033,7 +1033,7 @@ Document.prototype.isSelected = function isSelected(path) {
 
     while (i--) {
       cur = paths[i];
-      if ('_id' == cur) {
+      if (cur === '_id') {
         continue;
       }
 
@@ -1222,7 +1222,7 @@ Document.prototype.$__validate = function (callback) {
  */
 
 Document.prototype.validateSync = function (pathsToValidate) {
-  var self = this;
+  var _this = this;
 
   if (typeof pathsToValidate === 'string') {
     pathsToValidate = pathsToValidate.split(' ');
@@ -1230,7 +1230,7 @@ Document.prototype.validateSync = function (pathsToValidate) {
 
   // only validate required fields when necessary
   var paths = Object.keys(this.$__.activePaths.states.require).filter(function (path) {
-    if (!self.isSelected(path) && !self.isModified(path)) {
+    if (!_this.isSelected(path) && !_this.isModified(path)) {
       return false;
     }
     return true;
@@ -1259,30 +1259,30 @@ Document.prototype.validateSync = function (pathsToValidate) {
 
     validating[path] = true;
 
-    var p = self.schema.path(path);
+    var p = _this.schema.path(path);
     if (!p) {
       return;
     }
-    if (!self.$isValid(path)) {
+    if (!_this.$isValid(path)) {
       return;
     }
 
-    var val = self.getValue(path);
-    var err = p.doValidateSync(val, self);
+    var val = _this.getValue(path);
+    var err = p.doValidateSync(val, _this);
     if (err) {
-      self.invalidate(path, err, undefined, true);
+      _this.invalidate(path, err, undefined, true);
     }
   });
 
-  var err = self.$__.validationError;
-  self.$__.validationError = undefined;
-  self.emit('validate', self);
+  var err = _this.$__.validationError;
+  _this.$__.validationError = undefined;
+  _this.emit('validate', _this);
 
   if (err) {
     for (var key in err.errors) {
       // Make sure cast errors persist
       if (err.errors[key] instanceof MongooseError.CastError) {
-        self.invalidate(key, err.errors[key]);
+        _this.invalidate(key, err.errors[key]);
       }
     }
   }
@@ -1328,7 +1328,7 @@ Document.prototype.invalidate = function (path, err, val) {
     return;
   }
 
-  if (!err || 'string' === typeof err) {
+  if (!err || typeof err === 'string') {
     err = new ValidatorError({
       path: path,
       message: err,
@@ -1337,7 +1337,7 @@ Document.prototype.invalidate = function (path, err, val) {
     });
   }
 
-  if (this.$__.validationError == err) {
+  if (this.$__.validationError === err) {
     return;
   }
 
@@ -1387,12 +1387,12 @@ Document.prototype.$isValid = function (path) {
  */
 
 Document.prototype.$__reset = function reset() {
-  var self = this;
+  var _this = this;
   DocumentArray || (DocumentArray = require('./types/documentarray'));
 
   this.$__.activePaths
   .map('init', 'modify', function (i) {
-    return self.getValue(i);
+    return _this.getValue(i);
   })
   .filter(function (val) {
     return val && val instanceof Array && val.isMongooseDocumentArray && val.length;
@@ -1421,9 +1421,9 @@ Document.prototype.$__reset = function reset() {
   this.$__.activePaths.clear('default');
   this.$__.validationError = undefined;
   this.errors = undefined;
-  self = this;
+  _this = this;
   this.schema.requiredPaths().forEach(function (path) {
-    self.$__.activePaths.require(path);
+    _this.$__.activePaths.require(path);
   });
 
   return this;
@@ -1438,26 +1438,26 @@ Document.prototype.$__reset = function reset() {
  */
 
 Document.prototype.$__dirty = function () {
-  var self = this;
+  var _this = this;
 
   var all = this.$__.activePaths.map('modify', function (path) {
     return {
       path: path,
-      value: self.getValue(path),
-      schema: self.$__path(path)
+      value: _this.getValue(path),
+      schema: _this.$__path(path)
     };
   });
 
   // gh-2558: if we had to set a default and the value is not undefined,
   // we have to save as well
   all = all.concat(this.$__.activePaths.map('default', function (path) {
-    if (path === '_id' || !self.getValue(path)) {
+    if (path === '_id' || !_this.getValue(path)) {
       return;
     }
     return {
       path: path,
-      value: self.getValue(path),
-      schema: self.$__path(path)
+      value: _this.getValue(path),
+      schema: _this.$__path(path)
     };
   }));
 
@@ -1548,7 +1548,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
       enumerable: true,
       configurable: true,
       get: function () {
-        var _self = this;
+        var _this = this;
         if (!this.$__.getters) {
           this.$__.getters = {};
         }
@@ -1581,7 +1581,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
             configurable: true,
             writable: false,
             value: function () {
-              return _self.get(path);
+              return _this.get(path);
             }
           });
 
@@ -1590,7 +1590,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
             configurable: true,
             writable: false,
             value: function () {
-              return _self.get(path);
+              return _this.get(path);
             }
           });
 
@@ -1728,16 +1728,16 @@ Document.prototype.$__registerHooksFromSchema = function () {
   Embedded = Embedded || require('./types/embedded');
   var Promise = PromiseProvider.get();
 
-  var self = this;
-  var q = self.schema && self.schema.callQueue;
+  var _this = this;
+  var q = _this.schema && _this.schema.callQueue;
   if (!q.length) {
-    return self;
+    return _this;
   }
 
   // we are only interested in 'pre' hooks, and group by point-cut
   var toWrap = q.reduce(function (seed, pair) {
     if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') {
-      self[pair[0]].apply(self, pair[1]);
+      _this[pair[0]].apply(_this, pair[1]);
       return seed;
     }
     var args = [].slice.call(pair[1]);
@@ -1757,20 +1757,20 @@ Document.prototype.$__registerHooksFromSchema = function () {
 
   // 'post' hooks are simpler
   toWrap.post.forEach(function (args) {
-    self.on.apply(self, args);
+    _this.on.apply(_this, args);
   });
   delete toWrap.post;
 
   // 'init' should be synchronous on subdocuments
-  if (toWrap.init && self instanceof Embedded) {
+  if (toWrap.init && _this instanceof Embedded) {
     if (toWrap.init.pre) {
       toWrap.init.pre.forEach(function (args) {
-        self.pre.apply(self, args);
+        _this.pre.apply(_this, args);
       });
     }
     if (toWrap.init.post) {
       toWrap.init.post.forEach(function (args) {
-        self.post.apply(self, args);
+        _this.post.apply(_this, args);
       });
     }
     delete toWrap.init;
@@ -1778,12 +1778,12 @@ Document.prototype.$__registerHooksFromSchema = function () {
     // Set hooks also need to be sync re: gh-3479
     if (toWrap.set.pre) {
       toWrap.set.pre.forEach(function (args) {
-        self.pre.apply(self, args);
+        _this.pre.apply(_this, args);
       });
     }
     if (toWrap.set.post) {
       toWrap.set.post.forEach(function (args) {
-        self.post.apply(self, args);
+        _this.post.apply(_this, args);
       });
     }
     delete toWrap.set;
@@ -1792,11 +1792,11 @@ Document.prototype.$__registerHooksFromSchema = function () {
   Object.keys(toWrap).forEach(function (pointCut) {
     // this is so we can wrap everything into a promise;
     var newName = ('$__original_' + pointCut);
-    if (!self[pointCut]) {
+    if (!_this[pointCut]) {
       return;
     }
-    self[newName] = self[pointCut];
-    self[pointCut] = function wrappedPointCut() {
+    _this[newName] = _this[pointCut];
+    _this[pointCut] = function wrappedPointCut() {
       var args = [].slice.call(arguments);
       var lastArg = args.pop();
       var fn;
@@ -1809,7 +1809,7 @@ Document.prototype.$__registerHooksFromSchema = function () {
         }
         args.push(function (error, result) {
           if (error) {
-            self.$__handleReject(error);
+            _this.$__handleReject(error);
             fn && fn(error);
             reject(error);
             return;
@@ -1819,20 +1819,20 @@ Document.prototype.$__registerHooksFromSchema = function () {
           resolve(result);
         });
 
-        self[newName].apply(self, args);
+        _this[newName].apply(_this, args);
       });
     };
 
     toWrap[pointCut].pre.forEach(function (args) {
       args[0] = newName;
-      self.pre.apply(self, args);
+      _this.pre.apply(_this, args);
     });
     toWrap[pointCut].post.forEach(function (args) {
       args[0] = newName;
-      self.post.apply(self, args);
+      _this.post.apply(_this, args);
     });
   });
-  return self;
+  return _this;
 };
 
 Document.prototype.$__handleReject = function handleReject(err) {
@@ -1870,7 +1870,7 @@ Document.prototype.$toObject = function (options, json) {
 
   // When internally saving this document we always pass options,
   // bypassing the custom schema options.
-  if (!(options && 'Object' == utils.getFunctionName(options.constructor)) ||
+  if (!(options && 'Object' === utils.getFunctionName(options.constructor)) ||
       (options && options._useSchemaOptions)) {
     if (json) {
       options = this.schema.options.toJSON ?
@@ -1936,9 +1936,9 @@ Document.prototype.$toObject = function (options, json) {
     options.transform = originalTransform;
   }
 
-  if ('function' == typeof transform) {
+  if (typeof transform === 'function') {
     var xformed = transform(this, ret, options);
-    if ('undefined' != typeof xformed) {
+    if ('undefined' !== typeof xformed) {
       ret = xformed;
     }
   }
@@ -2163,7 +2163,7 @@ Document.prototype.toJSON = function (options) {
  */
 
 Document.prototype.inspect = function (options) {
-  var opts = options && 'Object' == utils.getFunctionName(options.constructor) ? options : {};
+  var opts = options && 'Object' === utils.getFunctionName(options.constructor) ? options : {};
   opts.minimize = false;
   opts.retainKeyOrder = true;
   return this.toObject(opts);
@@ -2217,7 +2217,7 @@ Document.prototype.equals = function (doc) {
  *       model: 'modelName'
  *       options: opts
  *     }, function (err, user) {
- *       assert(doc._id == user._id) // the document itself is passed
+ *       assert(doc._id === user._id) // the document itself is passed
  *     })
  *
  *     // summary
@@ -2334,7 +2334,7 @@ Document.prototype.execPopulate = function () {
 Document.prototype.populated = function (path, val, options) {
   // val and options are internal
 
-  if (val == null) {
+  if (val === null || val === void 0) {
     if (!this.$__.populated) {
       return undefined;
     }
diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js
index 6dcc39f1d28..b6b5f65f3c7 100644
--- a/lib/drivers/node-mongodb-native/collection.js
+++ b/lib/drivers/node-mongodb-native/collection.js
@@ -34,22 +34,22 @@ NativeCollection.prototype.__proto__ = MongooseCollection.prototype;
  */
 
 NativeCollection.prototype.onOpen = function () {
-  var self = this;
+  var _this = this;
 
   // always get a new collection in case the user changed host:port
   // of parent db instance when re-opening the connection.
 
-  if (!self.opts.capped.size) {
+  if (!_this.opts.capped.size) {
     // non-capped
-    return self.conn.db.collection(self.name, callback);
+    return _this.conn.db.collection(_this.name, callback);
   }
 
   // capped
-  return self.conn.db.collection(self.name, function (err, c) {
+  return _this.conn.db.collection(_this.name, function (err, c) {
     if (err) return callback(err);
 
     // discover if this collection exists and if it is capped
-    self.conn.db.listCollections({name: self.name}).toArray(function (err, docs) {
+    _this.conn.db.listCollections({name: _this.name}).toArray(function (err, docs) {
       if (err) {
         return callback(err);
       }
@@ -60,7 +60,7 @@ NativeCollection.prototype.onOpen = function () {
         if (doc.options && doc.options.capped) {
           callback(null, c);
         } else {
-          var msg = 'A non-capped collection exists with the name: ' + self.name + '\n\n'
+          var msg = 'A non-capped collection exists with the name: ' + _this.name + '\n\n'
                   + ' To use this collection as a capped collection, please '
                   + 'first convert it.\n'
                   + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped';
@@ -69,9 +69,9 @@ NativeCollection.prototype.onOpen = function () {
         }
       } else {
         // create
-        var opts = utils.clone(self.opts.capped);
+        var opts = utils.clone(_this.opts.capped);
         opts.capped = true;
-        self.conn.db.createCollection(self.name, opts, callback);
+        _this.conn.db.createCollection(_this.name, opts, callback);
       }
     });
   });
@@ -79,10 +79,10 @@ NativeCollection.prototype.onOpen = function () {
   function callback(err, collection) {
     if (err) {
       // likely a strict mode error
-      self.conn.emit('error', err);
+      _this.conn.emit('error', err);
     } else {
-      self.collection = collection;
-      MongooseCollection.prototype.onOpen.call(self);
+      _this.collection = collection;
+      MongooseCollection.prototype.onOpen.call(_this);
     }
   }
 };
@@ -121,15 +121,15 @@ for (var i in Collection.prototype) {
 
       var collection = this.collection,
           args = arguments,
-          self = this,
-          debug = self.conn.base.options.debug;
+          _this = this,
+          debug = _this.conn.base.options.debug;
 
       if (debug) {
-        if ('function' === typeof debug) {
+        if (typeof debug === 'function') {
           debug.apply(debug
-            , [self.name, i].concat(utils.args(args, 0, args.length - 1)));
+            , [_this.name, i].concat(utils.args(args, 0, args.length - 1)));
         } else {
-          this.$print(self.name, i, args);
+          this.$print(_this.name, i, args);
         }
       }
 
@@ -163,7 +163,7 @@ NativeCollection.prototype.$print = function (name, i, args) {
 
 NativeCollection.prototype.$format = function (arg) {
   var type = typeof arg;
-  if ('function' === type || 'undefined' === type) return '';
+  if (type === 'function' || type === 'undefined') return '';
   return format(arg);
 };
 
@@ -175,15 +175,15 @@ function format(obj, sub) {
   var x = utils.clone(obj, {retainKeyOrder: 1});
   var representation;
   if (x != null) {
-    if ('Binary' === x.constructor.name) {
+    if (x.constructor.name === 'Binary') {
       x = '[object Buffer]';
-    } else if ('ObjectID' === x.constructor.name) {
+    } else if (x.constructor.name === 'ObjectID') {
       representation = 'ObjectId("' + x.toHexString() + '")';
       x = {inspect: function () { return representation; }};
-    } else if ('Date' === x.constructor.name) {
+    } else if (x.constructor.name === 'Date') {
       representation = 'new Date("' + x.toUTCString() + '")';
       x = {inspect: function () { return representation; }};
-    } else if ('Object' === x.constructor.name) {
+    } else if (x.constructor.name === 'Object') {
       var keys = Object.keys(x);
       var numKeys = keys.length;
       var key;
diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js
index 037e09b972f..c9045042a0f 100644
--- a/lib/drivers/node-mongodb-native/connection.js
+++ b/lib/drivers/node-mongodb-native/connection.js
@@ -53,10 +53,10 @@ NativeConnection.prototype.doOpen = function (fn) {
     this.db = new Db(this.name, server, this.options.db);
   }
 
-  var self = this;
+  var _this = this;
   this.db.open(function (err) {
     if (err) return fn(err);
-    listen(self);
+    listen(_this);
     fn();
   });
 
@@ -99,7 +99,7 @@ NativeConnection.prototype.useDb = function (name) {
   // the 'open' event of the connection before doing the rest of the setup
   // the 'connected' event is the first time we'll have access to the db object
 
-  var self = this;
+  var _this = this;
 
   if (this.db && this._readyState === STATES.connected) {
     wireup();
@@ -108,7 +108,7 @@ NativeConnection.prototype.useDb = function (name) {
   }
 
   function wireup() {
-    newConn.db = self.db.db(name);
+    newConn.db = _this.db.db(name);
     newConn.onOpen();
     // setup the events appropriately
     listen(newConn);
@@ -180,12 +180,12 @@ function listen(conn) {
 
 NativeConnection.prototype.doOpenSet = function (fn) {
   var servers = [],
-      self = this;
+      _this = this;
 
   this.hosts.forEach(function (server) {
     var host = server.host || server.ipc;
     var port = server.port || 27017;
-    servers.push(new Server(host, port, self.options.server));
+    servers.push(new Server(host, port, _this.options.server));
   });
 
   var server = this.options.mongos
@@ -194,13 +194,13 @@ NativeConnection.prototype.doOpenSet = function (fn) {
   this.db = new Db(this.name, server, this.options.db);
 
   this.db.on('fullsetup', function () {
-    self.emit('fullsetup');
+    _this.emit('fullsetup');
   });
 
   this.db.open(function (err) {
     if (err) return fn(err);
     fn();
-    listen(self);
+    listen(_this);
   });
 
   return this;
@@ -243,55 +243,55 @@ NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {
     switch (name) {
       case 'ssl':
       case 'poolSize':
-        if ('undefined' == typeof o.server[name]) {
+        if (typeof o.server[name] === 'undefined') {
           o.server[name] = o.replset[name] = opts[name];
         }
         break;
       case 'slaveOk':
-        if ('undefined' == typeof o.server.slave_ok) {
+        if (typeof o.server.slave_ok === 'undefined') {
           o.server.slave_ok = opts[name];
         }
         break;
       case 'autoReconnect':
-        if ('undefined' == typeof o.server.auto_reconnect) {
+        if (typeof o.server.auto_reconnect === 'undefined') {
           o.server.auto_reconnect = opts[name];
         }
         break;
       case 'socketTimeoutMS':
       case 'connectTimeoutMS':
-        if ('undefined' == typeof o.server.socketOptions[name]) {
+        if (typeof o.server.socketOptions[name] === 'undefined') {
           o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];
         }
         break;
       case 'authdb':
-        if ('undefined' == typeof o.auth.authdb) {
+        if (typeof o.auth.authdb === 'undefined') {
           o.auth.authdb = opts[name];
         }
         break;
       case 'authSource':
-        if ('undefined' == typeof o.auth.authSource) {
+        if (typeof o.auth.authSource === 'undefined') {
           o.auth.authSource = opts[name];
         }
         break;
       case 'retries':
       case 'reconnectWait':
       case 'rs_name':
-        if ('undefined' == typeof o.replset[name]) {
+        if (typeof o.replset[name] === 'undefined') {
           o.replset[name] = opts[name];
         }
         break;
       case 'replicaSet':
-        if ('undefined' == typeof o.replset.rs_name) {
+        if (typeof o.replset.rs_name === 'undefined') {
           o.replset.rs_name = opts[name];
         }
         break;
       case 'readSecondary':
-        if ('undefined' == typeof o.replset.read_secondary) {
+        if (typeof o.replset.read_secondary === 'undefined') {
           o.replset.read_secondary = opts[name];
         }
         break;
       case 'nativeParser':
-        if ('undefined' == typeof o.db.native_parser) {
+        if (typeof o.db.native_parser === 'undefined') {
           o.db.native_parser = opts[name];
         }
         break;
@@ -300,17 +300,17 @@ NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {
       case 'fsync':
       case 'journal':
       case 'wtimeoutMS':
-        if ('undefined' == typeof o.db[name]) {
+        if (typeof o.db[name] === 'undefined') {
           o.db[name] = opts[name];
         }
         break;
       case 'readPreference':
-        if ('undefined' == typeof o.db.readPreference) {
+        if (typeof o.db.readPreference === 'undefined') {
           o.db.readPreference = opts[name];
         }
         break;
       case 'readPreferenceTags':
-        if ('undefined' == typeof o.db.read_preference_tags) {
+        if (typeof o.db.read_preference_tags === 'undefined') {
           o.db.read_preference_tags = opts[name];
         }
         break;
diff --git a/lib/error/validation.js b/lib/error/validation.js
index 81dc219cb21..7e9d01127b4 100644
--- a/lib/error/validation.js
+++ b/lib/error/validation.js
@@ -1,4 +1,3 @@
-
 /*!
  * Module requirements
  */
@@ -48,7 +47,9 @@ ValidationError.prototype.toString = function () {
   var msgs = [];
 
   Object.keys(this.errors).forEach(function (key) {
-    if (this == this.errors[key]) return;
+    if (this === this.errors[key]) {
+      return;
+    }
     msgs.push(String(this.errors[key]));
   }, this);
 
diff --git a/lib/index.js b/lib/index.js
index 5554327b840..acef70a8fe3 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -66,7 +66,7 @@ Mongoose.prototype.STATES = STATES;
  */
 
 Mongoose.prototype.set = function (key, value) {
-  if (arguments.length == 1) {
+  if (arguments.length === 1) {
     return this.options[key];
   }
 
@@ -312,7 +312,7 @@ Mongoose.prototype.disconnect = function (fn) {
  */
 
 Mongoose.prototype.model = function (name, schema, collection, skipInit) {
-  if ('string' == typeof schema) {
+  if (typeof schema === 'string') {
     collection = schema;
     schema = false;
   }
@@ -321,7 +321,7 @@ Mongoose.prototype.model = function (name, schema, collection, skipInit) {
     schema = new Schema(schema);
   }
 
-  if ('boolean' === typeof collection) {
+  if (typeof collection === 'boolean') {
     skipInit = collection;
     collection = null;
   }
@@ -352,7 +352,7 @@ Mongoose.prototype.model = function (name, schema, collection, skipInit) {
   // connection.model() may be passing a different schema for
   // an existing model name. in this case don't read from cache.
   if (this.models[name] && false !== options.cache) {
-    if (schema && schema.instanceOfSchema && schema != this.models[name].schema) {
+    if (schema && schema.instanceOfSchema && schema !== this.models[name].schema) {
       throw new mongoose.Error.OverwriteModelError(name);
     }
 
diff --git a/lib/model.js b/lib/model.js
index 678b23d61ad..1d074e61a90 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -269,7 +269,7 @@ Model.prototype.$__save = function (options, callback) {
  */
 
 Model.prototype.save = function (options, fn) {
-  if ('function' == typeof options) {
+  if (typeof options === 'function') {
     fn = options;
     options = undefined;
   }
@@ -362,7 +362,7 @@ function operand(self, where, delta, data, val, op) {
   // only increment the version if an array position changes.
   // modifying elements of an array is ok if position does not change.
 
-  if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {
+  if ('$push' === op || '$pushAll' === op || '$addToSet' === op) {
     self.$__.version = VERSION_INC;
   } else if (/^\$p/.test(op)) {
     // potentially changing array positions
@@ -393,7 +393,7 @@ function handleAtomics(self, where, delta, data, value) {
     return;
   }
 
-  if ('function' == typeof value.$__getAtomics) {
+  if (typeof value.$__getAtomics === 'function') {
     value.$__getAtomics().forEach(function (atomic) {
       var op = atomic[0];
       var val = atomic[1];
@@ -456,7 +456,7 @@ function handleAtomics(self, where, delta, data, value) {
 
 Model.prototype.$__delta = function () {
   var dirty = this.$__dirty();
-  if (!dirty.length && VERSION_ALL != this.$__.version) return;
+  if (!dirty.length && VERSION_ALL !== this.$__.version) return;
 
   var where = {},
       delta = {},
@@ -676,7 +676,7 @@ Model.prototype.$__where = function _where(where) {
  */
 
 Model.prototype.remove = function remove(options, fn) {
-  if ('function' == typeof options) {
+  if (typeof options === 'function') {
     fn = options;
     options = undefined;
   }
@@ -908,10 +908,10 @@ Model.init = function init() {
  */
 
 Model.ensureIndexes = function ensureIndexes(cb) {
-  var self = this;
+  var _this = this;
   var Promise = PromiseProvider.get();
   return new Promise.ES6(function (resolve, reject) {
-    var indexes = self.schema.indexes();
+    var indexes = _this.schema.indexes();
     if (!indexes.length) {
       process.nextTick(function () {
         cb && cb();
@@ -923,19 +923,19 @@ Model.ensureIndexes = function ensureIndexes(cb) {
     // with background indexes.
 
     var done = function (err) {
-      if (err && self.schema.options.emitIndexErrors) {
-        self.emit('error', err);
+      if (err && _this.schema.options.emitIndexErrors) {
+        _this.emit('error', err);
       }
-      self.emit('index', err);
+      _this.emit('index', err);
       cb && cb(err);
       err ? reject(err) : resolve();
     };
 
     var indexSingleDone = function (err, fields, options, name) {
-      self.emit('index-single-done', err, fields, options, name);
+      _this.emit('index-single-done', err, fields, options, name);
     };
     var indexSingleStart = function (fields, options) {
-      self.emit('index-single-start', fields, options);
+      _this.emit('index-single-start', fields, options);
     };
 
     var create = function () {
@@ -948,7 +948,7 @@ Model.ensureIndexes = function ensureIndexes(cb) {
 
       indexSingleStart(indexFields, options);
 
-      self.collection.ensureIndex(indexFields, options, tick(function (err, name) {
+      _this.collection.ensureIndex(indexFields, options, tick(function (err, name) {
         indexSingleDone(err, indexFields, options, name);
         if (err) {
           return done(err);
@@ -1053,7 +1053,7 @@ Model.discriminators;
  */
 
 Model.remove = function remove(conditions, callback) {
-  if ('function' === typeof conditions) {
+  if (typeof conditions === 'function') {
     callback = conditions;
     conditions = {};
   }
@@ -1106,16 +1106,16 @@ Model.remove = function remove(conditions, callback) {
  */
 
 Model.find = function find(conditions, projection, options, callback) {
-  if ('function' == typeof conditions) {
+  if (typeof conditions === 'function') {
     callback = conditions;
     conditions = {};
     projection = null;
     options = null;
-  } else if ('function' == typeof projection) {
+  } else if (typeof projection === 'function') {
     callback = projection;
     projection = null;
     options = null;
-  } else if ('function' == typeof options) {
+  } else if (typeof options === 'function') {
     callback = options;
     options = null;
   }
@@ -1222,14 +1222,14 @@ Model.findById = function findById(id, projection, options, callback) {
  */
 
 Model.findOne = function findOne(conditions, projection, options, callback) {
-  if ('function' == typeof options) {
+  if (typeof options === 'function') {
     callback = options;
     options = null;
-  } else if ('function' == typeof projection) {
+  } else if (typeof projection === 'function') {
     callback = projection;
     projection = null;
     options = null;
-  } else if ('function' == typeof conditions) {
+  } else if (typeof conditions === 'function') {
     callback = conditions;
     conditions = {};
     projection = null;
@@ -1264,8 +1264,9 @@ Model.findOne = function findOne(conditions, projection, options, callback) {
  */
 
 Model.count = function count(conditions, callback) {
-  if ('function' === typeof conditions) {
-    callback = conditions, conditions = {};
+  if (typeof conditions === 'function') {
+    callback = conditions;
+    conditions = {};
   }
 
   // get the mongodb collection object
@@ -1302,7 +1303,7 @@ Model.distinct = function distinct(field, conditions, callback) {
   // get the mongodb collection object
   var mq = new Query({}, {}, this, this.collection);
 
-  if ('function' == typeof conditions) {
+  if (typeof conditions === 'function') {
     callback = conditions;
     conditions = {};
   }
@@ -1425,11 +1426,11 @@ Model.$where = function $where() {
  */
 
 Model.findOneAndUpdate = function (conditions, update, options, callback) {
-  if ('function' == typeof options) {
+  if (typeof options === 'function') {
     callback = options;
     options = null;
   } else if (1 === arguments.length) {
-    if ('function' == typeof conditions) {
+    if (typeof conditions === 'function') {
       var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\n\n'
               + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\n'
               + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\n'
@@ -1535,7 +1536,7 @@ Model.findOneAndUpdate = function (conditions, update, options, callback) {
 Model.findByIdAndUpdate = function (id, update, options, callback) {
   var args;
   if (1 === arguments.length) {
-    if ('function' == typeof id) {
+    if (typeof id === 'function') {
       var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
                 + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
                 + '  ' + this.modelName + '.findByIdAndUpdate(id)\n'
@@ -1605,7 +1606,7 @@ Model.findByIdAndUpdate = function (id, update, options, callback) {
  */
 
 Model.findOneAndRemove = function (conditions, options, callback) {
-  if (1 === arguments.length && 'function' == typeof conditions) {
+  if (1 === arguments.length && typeof conditions === 'function') {
     var msg = 'Model.findOneAndRemove(): First argument must not be a function.\n\n'
               + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)\n'
               + '  ' + this.modelName + '.findOneAndRemove(conditions)\n'
@@ -1613,7 +1614,7 @@ Model.findOneAndRemove = function (conditions, options, callback) {
     throw new TypeError(msg);
   }
 
-  if ('function' == typeof options) {
+  if (typeof options === 'function') {
     callback = options;
     options = undefined;
   }
@@ -1659,7 +1660,7 @@ Model.findOneAndRemove = function (conditions, options, callback) {
  */
 
 Model.findByIdAndRemove = function (id, options, callback) {
-  if (1 === arguments.length && 'function' == typeof id) {
+  if (1 === arguments.length && typeof id === 'function') {
     var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\n\n'
               + '  ' + this.modelName + '.findByIdAndRemove(id, callback)\n'
               + '  ' + this.modelName + '.findByIdAndRemove(id)\n'
@@ -1712,7 +1713,7 @@ Model.create = function create(doc, callback) {
     cb = callback;
   } else {
     var last = arguments[arguments.length - 1];
-    if ('function' == typeof last) {
+    if (typeof last === 'function') {
       cb = last;
       args = utils.args(arguments, 0, arguments.length - 1);
     } else {
@@ -1721,7 +1722,7 @@ Model.create = function create(doc, callback) {
   }
 
   var Promise = PromiseProvider.get();
-  var ModelConstructor = this;
+  var _this = this;
 
   var promise = new Promise.ES6(function (resolve, reject) {
     if (args.length === 0) {
@@ -1735,7 +1736,7 @@ Model.create = function create(doc, callback) {
     var toExecute = [];
     args.forEach(function (doc) {
       toExecute.push(function (callback) {
-        var toSave = new ModelConstructor(doc);
+        var toSave = new _this(doc);
         var callbackWrapper = function (error, doc) {
           if (error) {
             return callback(error);
@@ -1762,12 +1763,12 @@ Model.create = function create(doc, callback) {
 
       if (doc instanceof Array) {
         resolve(savedDocs);
-        cb && cb.call(ModelConstructor, null, savedDocs);
+        cb && cb.call(_this, null, savedDocs);
       } else {
         resolve.apply(promise, savedDocs);
         if (cb) {
           savedDocs.unshift(null);
-          cb.apply(ModelConstructor, savedDocs);
+          cb.apply(_this, savedDocs);
         }
       }
     });
@@ -2015,7 +2016,7 @@ Model.update = function update(conditions, doc, options, callback) {
  */
 
 Model.mapReduce = function mapReduce(o, callback) {
-  var self = this;
+  var _this = this;
   var Promise = PromiseProvider.get();
   return new Promise.ES6(function (resolve, reject) {
     if (!Model.mapReduce.schema) {
@@ -2031,12 +2032,12 @@ Model.mapReduce = function mapReduce(o, callback) {
 
     if (o.query) {
       var q = new Query(o.query);
-      q.cast(self);
+      q.cast(_this);
       o.query = q._conditions;
       q = undefined;
     }
 
-    self.collection.mapReduce(null, null, o, function (err, ret, stats) {
+    _this.collection.mapReduce(null, null, o, function (err, ret, stats) {
       if (err) {
         callback && callback(err);
         reject(err);
@@ -2049,8 +2050,8 @@ Model.mapReduce = function mapReduce(o, callback) {
             '_mapreduce_' + ret.collectionName
           , Model.mapReduce.schema
           , ret.collectionName
-          , self.db
-          , self.base);
+          , _this.db
+          , _this.base);
 
         model._mapreduce = true;
 
@@ -2094,12 +2095,12 @@ Model.mapReduce = function mapReduce(o, callback) {
  */
 
 Model.geoNear = function (near, options, callback) {
-  if ('function' == typeof options) {
+  if (typeof options === 'function') {
     callback = options;
     options = {};
   }
 
-  var self = this;
+  var _this = this;
   var Promise = PromiseProvider.get();
   if (!near) {
     return new Promise.ES6(function (resolve, reject) {
@@ -2110,7 +2111,6 @@ Model.geoNear = function (near, options, callback) {
   }
 
   var x, y;
-  var _this = this;
 
   return new Promise.ES6(function (resolve, reject) {
     var handler = function (err, res) {
@@ -2127,7 +2127,7 @@ Model.geoNear = function (near, options, callback) {
 
       var count = res.results.length;
       // if there are no results, fulfill the promise now
-      if (count == 0) {
+      if (count === 0) {
         resolve(res.results, res.stats);
         callback && callback(null, res.results, res.stats);
         return;
@@ -2136,7 +2136,7 @@ Model.geoNear = function (near, options, callback) {
       var errSeen = false;
       for (var i = 0; i < res.results.length; i++) {
         var temp = res.results[i].obj;
-        res.results[i].obj = new self();
+        res.results[i].obj = new _this();
         res.results[i].obj.init(temp, function (err) {
           if (err && !errSeen) {
             errSeen = true;
@@ -2164,7 +2164,7 @@ Model.geoNear = function (near, options, callback) {
       y = near[1];
       _this.collection.geoNear(x, y, options, handler);
     } else {
-      if (near.type != 'Point' || !Array.isArray(near.coordinates)) {
+      if (near.type !== 'Point' || !Array.isArray(near.coordinates)) {
         error = new Error('Must pass either a legacy coordinate array or ' +
           'GeoJSON Point to geoNear');
         reject(error);
@@ -2221,7 +2221,7 @@ Model.aggregate = function aggregate() {
       aggregate,
       callback;
 
-  if ('function' === typeof args[args.length - 1]) {
+  if (typeof args[args.length - 1] === 'function') {
     callback = args.pop();
   }
 
@@ -2233,7 +2233,7 @@ Model.aggregate = function aggregate() {
 
   aggregate.model(this);
 
-  if ('undefined' === typeof callback) {
+  if (typeof callback === 'undefined') {
     return aggregate;
   }
 
@@ -2266,16 +2266,16 @@ Model.aggregate = function aggregate() {
  */
 
 Model.geoSearch = function (conditions, options, callback) {
-  if ('function' == typeof options) {
+  if (typeof options === 'function') {
     callback = options;
     options = {};
   }
 
-  var self = this;
+  var _this = this;
   var Promise = PromiseProvider.get();
   return new Promise.ES6(function (resolve, reject) {
     var error;
-    if (conditions == undefined || !utils.isObject(conditions)) {
+    if (conditions === undefined || !utils.isObject(conditions)) {
       error = new Error('Must pass conditions to geoSearch');
     } else if (!options.near) {
       error = new Error('Must specify the near option in geoSearch');
@@ -2292,7 +2292,7 @@ Model.geoSearch = function (conditions, options, callback) {
     // send the conditions in the options object
     options.search = conditions;
 
-    self.collection.geoHaystackSearch(options.near[0], options.near[1], options, function (err, res) {
+    _this.collection.geoHaystackSearch(options.near[0], options.near[1], options, function (err, res) {
       // have to deal with driver problem. Should be fixed in a soon-ish release
       // (7/8/2013)
       if (err) {
@@ -2311,7 +2311,7 @@ Model.geoSearch = function (conditions, options, callback) {
       var errSeen = false;
       for (var i = 0; i < res.results.length; i++) {
         var temp = res.results[i];
-        res.results[i] = new self();
+        res.results[i] = new _this();
         res.results[i].init(temp, {}, function (err) {
           if (err && !errSeen) {
             callback && callback(err);
@@ -2439,7 +2439,7 @@ function _populate(model, docs, paths, cb) {
   var path;
   while (i--) {
     path = paths[i];
-    if ('function' === typeof path.model) {
+    if (typeof path.model === 'function') {
       model = path.model;
     }
     populate(model, docs, path, subPopulate.call(model, docs, path, next));
@@ -2466,7 +2466,7 @@ function _populate(model, docs, paths, cb) {
  * @api private
  */
 function subPopulate(docs, options, cb) {
-  var model = this;
+  var _this = this;
   var prefix = options.path + '.';
   var pop = options.populate;
 
@@ -2497,18 +2497,18 @@ function subPopulate(docs, options, cb) {
         subOptions.path = prefix + subOptions.path;
       }
 
-      var schema = model.schema._getSchema(prefix);
+      var schema = _this.schema._getSchema(prefix);
       if (typeof subOptions.model === 'string') {
-        subOptions.model = model.model(subOptions.model);
+        subOptions.model = _this.model(subOptions.model);
       } else if (schema && schema.caster && schema.caster.options &&
         schema.caster.options.ref) {
-        var subSchema = model.model(schema.caster.options.ref).schema.
+        var subSchema = _this.model(schema.caster.options.ref).schema.
           _getSchema(subOptions._originalPath);
         if (subSchema && subSchema.options && subSchema.options.ref) {
-          subOptions.model = model.model(subSchema.options.ref);
+          subOptions.model = _this.model(subSchema.options.ref);
         }
       }
-      Model.populate.call(subOptions.model || model, docs, subOptions, next);
+      Model.populate.call(subOptions.model || _this, docs, subOptions, next);
     });
   };
 }
@@ -2602,7 +2602,7 @@ function populate(model, docs, options, cb) {
       // override the exclusion from the query so we can use the _id
       // for document matching during assignment. we'll delete the
       // _id back off before returning the result.
-      if ('string' == typeof select) {
+      if (typeof select === 'string') {
         select = select.replace(excludeIdRegGlobal, ' ');
       } else {
         // preserve original select conditions by copying
@@ -2869,7 +2869,7 @@ function valueFilter(val, assignmentOpts) {
 
 function maybeRemoveId(subdoc, assignmentOpts) {
   if (assignmentOpts.excludeId) {
-    if ('function' == typeof subdoc.setValue) {
+    if ('function' === typeof subdoc.setValue) {
       delete subdoc._doc._id;
     } else {
       delete subdoc._id;
@@ -2888,11 +2888,11 @@ function isDoc(doc) {
   }
 
   var type = typeof doc;
-  if ('string' == type) {
+  if (type === 'string') {
     return false;
   }
 
-  if ('number' == type) {
+  if (type === 'number') {
     return false;
   }
 
@@ -2900,7 +2900,7 @@ function isDoc(doc) {
     return false;
   }
 
-  if ('ObjectID' == doc.constructor.name) {
+  if (doc.constructor.name === 'ObjectID') {
     return false;
   }
 
@@ -3110,28 +3110,28 @@ var applyStatics = function (model, schema) {
 
 Model.__subclass = function subclass(conn, schema, collection) {
   // subclass model using this connection and collection name
-  var model = this;
+  var _this = this;
 
   var Model = function Model(doc, fields, skipId) {
     if (!(this instanceof Model)) {
       return new Model(doc, fields, skipId);
     }
-    model.call(this, doc, fields, skipId);
+    _this.call(this, doc, fields, skipId);
   };
 
-  Model.__proto__ = model;
-  Model.prototype.__proto__ = model.prototype;
+  Model.__proto__ = _this;
+  Model.prototype.__proto__ = _this.prototype;
   Model.db = Model.prototype.db = conn;
 
-  var s = schema && 'string' != typeof schema
+  var s = schema && typeof schema !== 'string'
     ? schema
-    : model.prototype.schema;
+    : _this.prototype.schema;
 
   var options = s.options || {};
 
   if (!collection) {
-    collection = model.prototype.schema.get('collection')
-              || utils.toCollectionName(model.modelName, options);
+    collection = _this.prototype.schema.get('collection')
+              || utils.toCollectionName(_this.modelName, options);
   }
 
   var collectionOptions = {
diff --git a/lib/query.js b/lib/query.js
index b171e45dc30..ac601b74adb 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -877,7 +877,7 @@ Query.prototype.setOptions = function (options, overwrite) {
     return this;
   }
 
-  if (!(options && 'Object' == options.constructor.name)) {
+  if (!(options && options.constructor.name === 'Object')) {
     return this;
   }
 
@@ -1027,7 +1027,7 @@ Query.prototype._find = function (callback) {
 
   var fields = this._fieldsForExec();
   var options = this._mongooseOptions;
-  var self = this;
+  var _this = this;
 
   var cb = function (err, docs) {
     if (err) {
@@ -1041,16 +1041,16 @@ Query.prototype._find = function (callback) {
     if (!options.populate) {
       return true === options.lean
         ? callback(null, docs)
-        : completeMany(self.model, docs, fields, self, null, callback);
+        : completeMany(_this.model, docs, fields, _this, null, callback);
     }
 
-    var pop = helpers.preparePopulationOptionsMQ(self, options);
+    var pop = helpers.preparePopulationOptionsMQ(_this, options);
     pop.__noPromise = true;
-    self.model.populate(docs, pop, function (err, docs) {
+    _this.model.populate(docs, pop, function (err, docs) {
       if (err) return callback(err);
       return true === options.lean
         ? callback(null, docs)
-        : completeMany(self.model, docs, fields, self, pop, callback);
+        : completeMany(_this.model, docs, fields, _this, pop, callback);
     });
   };
 
@@ -1073,7 +1073,7 @@ Query.prototype._find = function (callback) {
  */
 
 Query.prototype.find = function (conditions, callback) {
-  if ('function' == typeof conditions) {
+  if (typeof conditions === 'function') {
     callback = conditions;
     conditions = {};
   }
@@ -1148,10 +1148,10 @@ Query.prototype._findOne = function (callback) {
 
   var options = this._mongooseOptions;
   var projection = this._fieldsForExec();
-  var self = this;
+  var _this = this;
 
   // don't pass in the conditions because we already merged them in
-  Query.base.findOne.call(self, {}, function (err, doc) {
+  Query.base.findOne.call(_this, {}, function (err, doc) {
     if (err) {
       return callback(err);
     }
@@ -1162,19 +1162,19 @@ Query.prototype._findOne = function (callback) {
     if (!options.populate) {
       return true === options.lean
         ? callback(null, doc)
-        : completeOne(self.model, doc, null, projection, self, null, callback);
+        : completeOne(_this.model, doc, null, projection, _this, null, callback);
     }
 
-    var pop = helpers.preparePopulationOptionsMQ(self, options);
+    var pop = helpers.preparePopulationOptionsMQ(_this, options);
     pop.__noPromise = true;
-    self.model.populate(doc, pop, function (err, doc) {
+    _this.model.populate(doc, pop, function (err, doc) {
       if (err) {
         return callback(err);
       }
 
       return true === options.lean
         ? callback(null, doc)
-        : completeOne(self.model, doc, null, projection, self, pop, callback);
+        : completeOne(_this.model, doc, null, projection, _this, pop, callback);
     });
   });
 };
@@ -1204,16 +1204,16 @@ Query.prototype._findOne = function (callback) {
  */
 
 Query.prototype.findOne = function (conditions, projection, options, callback) {
-  if ('function' == typeof conditions) {
+  if (typeof conditions === 'function') {
     callback = conditions;
     conditions = null;
     projection = null;
     options = null;
-  } else if ('function' == typeof projection) {
+  } else if (typeof projection === 'function') {
     callback = projection;
     options = null;
     projection = null;
-  } else if ('function' == typeof options) {
+  } else if (typeof options === 'function') {
     callback = options;
     options = null;
   }
@@ -1304,7 +1304,7 @@ Query.prototype._count = function (callback) {
  */
 
 Query.prototype.count = function (conditions, callback) {
-  if ('function' == typeof conditions) {
+  if (typeof conditions === 'function') {
     callback = conditions;
     conditions = undefined;
   }
@@ -1347,10 +1347,10 @@ Query.prototype.count = function (conditions, callback) {
 
 Query.prototype.distinct = function (field, conditions, callback) {
   if (!callback) {
-    if ('function' === typeof conditions) {
+    if (typeof conditions === 'function') {
       callback = conditions;
       conditions = undefined;
-    } else if ('function' === typeof field) {
+    } else if (typeof field === 'function') {
       callback = field;
       field = undefined;
       conditions = undefined;
@@ -1422,7 +1422,7 @@ Query.prototype.sort = function (arg) {
 
   // workaround for gh-2374 when sort is called after count
   // if previous operation is count, we ignore
-  if (this.op == 'count') {
+  if (this.op === 'count') {
     delete this.op;
   }
   return Query.base.sort.call(this, nArg);
@@ -1463,12 +1463,12 @@ Query.prototype.sort = function (arg) {
  */
 
 Query.prototype.remove = function (cond, callback) {
-  if ('function' == typeof cond) {
+  if (typeof cond === 'function') {
     callback = cond;
     cond = null;
   }
 
-  var cb = 'function' == typeof callback;
+  var cb = typeof callback === 'function';
 
   try {
     this.cast(this.model);
@@ -1571,13 +1571,13 @@ Query.prototype.findOneAndUpdate = function (criteria, doc, options, callback) {
 
   switch (arguments.length) {
     case 3:
-      if ('function' == typeof options) {
+      if (typeof options === 'function') {
         callback = options;
         options = {};
       }
       break;
     case 2:
-      if ('function' == typeof doc) {
+      if (typeof doc === 'function') {
         callback = doc;
         doc = criteria;
         criteria = undefined;
@@ -1585,7 +1585,7 @@ Query.prototype.findOneAndUpdate = function (criteria, doc, options, callback) {
       options = undefined;
       break;
     case 1:
-      if ('function' == typeof criteria) {
+      if (typeof criteria === 'function') {
         callback = criteria;
         criteria = options = doc = undefined;
       } else {
@@ -1666,13 +1666,13 @@ Query.prototype.findOneAndRemove = function (conditions, options, callback) {
 
   switch (arguments.length) {
     case 2:
-      if ('function' == typeof options) {
+      if (typeof options === 'function') {
         callback = options;
         options = {};
       }
       break;
     case 1:
-      if ('function' == typeof conditions) {
+      if (typeof conditions === 'function') {
         callback = conditions;
         conditions = undefined;
         options = undefined;
@@ -1715,13 +1715,13 @@ Query.prototype._findOneAndRemove = function (callback) {
  */
 
 Query.prototype._findAndModify = function (type, callback) {
-  if ('function' != typeof callback) {
+  if (typeof callback !== 'function') {
     throw new Error('Expected callback in _findAndModify');
   }
 
   var model = this.model;
   var schema = model.schema;
-  var self = this;
+  var _this = this;
   var castedQuery;
   var castedDoc;
   var fields;
@@ -1739,7 +1739,7 @@ Query.prototype._findAndModify = function (type, callback) {
     this._mongooseOptions.strict = opts.strict;
   }
 
-  if ('remove' == type) {
+  if (type === 'remove') {
     opts.remove = true;
   } else {
     if (!('new' in opts)) {
@@ -1778,7 +1778,6 @@ Query.prototype._findAndModify = function (type, callback) {
 
   this._applyPaths();
 
-  self = this;
   var options = this._mongooseOptions;
 
   if (this._fields) {
@@ -1807,19 +1806,19 @@ Query.prototype._findAndModify = function (type, callback) {
     if (!options.populate) {
       return true === options.lean
         ? callback(null, doc)
-        : completeOne(self.model, doc, res, fields, self, null, callback);
+        : completeOne(_this.model, doc, res, fields, _this, null, callback);
     }
 
-    var pop = helpers.preparePopulationOptionsMQ(self, options);
+    var pop = helpers.preparePopulationOptionsMQ(_this, options);
     pop.__noPromise = true;
-    self.model.populate(doc, pop, function (err, doc) {
+    _this.model.populate(doc, pop, function (err, doc) {
       if (err) {
         return callback(err);
       }
 
       return true === options.lean
         ? callback(null, doc)
-        : completeOne(self.model, doc, res, fields, self, pop, callback);
+        : completeOne(_this.model, doc, res, fields, _this, pop, callback);
     });
   };
 
@@ -1828,7 +1827,7 @@ Query.prototype._findAndModify = function (type, callback) {
       if (error) {
         return callback(error);
       }
-      self._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function (error, res) {
+      _this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function (error, res) {
         return cb(error, res ? res.value : res, res);
       }));
     });
@@ -1998,17 +1997,17 @@ Query.prototype._execUpdate = function (callback) {
  */
 
 Query.prototype.update = function (conditions, doc, options, callback) {
-  if ('function' === typeof options) {
+  if (typeof options === 'function') {
     // .update(conditions, doc, callback)
     callback = options;
     options = null;
-  } else if ('function' === typeof doc) {
+  } else if (typeof doc === 'function') {
     // .update(doc, callback);
     callback = doc;
     doc = conditions;
     conditions = {};
     options = null;
-  } else if ('function' === typeof conditions) {
+  } else if (typeof conditions === 'function') {
     // .update(callback)
     callback = conditions;
     conditions = undefined;
@@ -2129,10 +2128,10 @@ Query.prototype.exec = function exec(op, callback) {
   var Promise = PromiseProvider.get();
   var _this = this;
 
-  if ('function' == typeof op) {
+  if (typeof op === 'function') {
     callback = op;
     op = null;
-  } else if ('string' == typeof op) {
+  } else if (typeof op === 'string') {
     this.op = op;
   }
 
@@ -2266,7 +2265,7 @@ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) {
         val.constructor.name === 'Object' &&
         (!overwrite || hasDollarKey)) {
       hasKeys |= this._walkUpdatePath(val, op);
-    } else if (overwrite && 'Object' === ret.constructor.name) {
+    } else if (overwrite && ret.constructor.name === 'Object') {
       // if we are just using overwrite, cast the query and then we will
       // *always* return the value, even if it is an empty object. We need to
       // set hasKeys above because we need to account for the case where the
@@ -2312,7 +2311,7 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) {
     key = keys[i];
     val = obj[key];
 
-    if (val && 'Object' === val.constructor.name) {
+    if (val && val.constructor.name === 'Object') {
       // watch for embedded doc schemas
       schema = this._getSchema(prefix + key);
       if (schema && schema.caster && op in castOps) {
@@ -2617,7 +2616,7 @@ Query.prototype._applyPaths = function applyPaths() {
     ki = keys.length;
 
     while (ki--) {
-      if ('+' == keys[ki][0]) continue;
+      if ('+' === keys[ki][0]) continue;
       exclude = 0 === fields[keys[ki]];
       break;
     }
@@ -2631,7 +2630,7 @@ Query.prototype._applyPaths = function applyPaths() {
       seen = [];
 
   var analyzePath = function (path, type) {
-    if ('boolean' != typeof type.selected) return;
+    if (typeof type.selected !== 'boolean') return;
 
     var plusPath = '+' + path;
     if (fields && plusPath in fields) {
@@ -2770,7 +2769,7 @@ Query.prototype.maxscan = Query.base.maxScan;
 Query.prototype.tailable = function (val, opts) {
   // we need to support the tailable({ awaitdata : true }) as well as the
   // tailable(true, {awaitdata :true}) syntax that mquery does not support
-  if (val && val.constructor.name == 'Object') {
+  if (val && val.constructor.name === 'Object') {
     opts = val;
     val = true;
   }
@@ -2907,11 +2906,11 @@ Query.prototype.near = function () {
   if (arguments.length === 1) {
     if (Array.isArray(arguments[0])) {
       params.push({center: arguments[0], spherical: sphere});
-    } else if ('string' == typeof arguments[0]) {
+    } else if (typeof arguments[0] === 'string') {
       // just passing a path
       params.push(arguments[0]);
     } else if (utils.isObject(arguments[0])) {
-      if ('boolean' != typeof arguments[0].spherical) {
+      if (typeof arguments[0].spherical !== 'boolean') {
         arguments[0].spherical = sphere;
       }
       params.push(arguments[0]);
@@ -2919,14 +2918,14 @@ Query.prototype.near = function () {
       throw new TypeError('invalid argument');
     }
   } else if (arguments.length === 2) {
-    if ('number' == typeof arguments[0] && 'number' == typeof arguments[1]) {
+    if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
       params.push({center: [arguments[0], arguments[1]], spherical: sphere});
-    } else if ('string' == typeof arguments[0] && Array.isArray(arguments[1])) {
+    } else if (typeof arguments[0] === 'string' && Array.isArray(arguments[1])) {
       params.push(arguments[0]);
       params.push({center: arguments[1], spherical: sphere});
-    } else if ('string' == typeof arguments[0] && utils.isObject(arguments[1])) {
+    } else if (typeof arguments[0] === 'string' && utils.isObject(arguments[1])) {
       params.push(arguments[0]);
-      if ('boolean' != typeof arguments[1].spherical) {
+      if (typeof arguments[1].spherical !== 'boolean') {
         arguments[1].spherical = sphere;
       }
       params.push(arguments[1]);
@@ -2934,8 +2933,8 @@ Query.prototype.near = function () {
       throw new TypeError('invalid argument');
     }
   } else if (arguments.length === 3) {
-    if ('string' == typeof arguments[0] && 'number' == typeof arguments[1]
-        && 'number' == typeof arguments[2]) {
+    if (typeof arguments[0] === 'string' && typeof arguments[1] === 'number'
+        && typeof arguments[2] === 'number') {
       params.push(arguments[0]);
       params.push({center: [arguments[1], arguments[2]], spherical: sphere});
     } else {
@@ -3091,11 +3090,11 @@ Query.prototype.center = Query.base.circle;
  */
 
 Query.prototype.centerSphere = function () {
-  if (arguments[0] && arguments[0].constructor.name == 'Object') {
+  if (arguments[0] && arguments[0].constructor.name === 'Object') {
     arguments[0].spherical = true;
   }
 
-  if (arguments[1] && arguments[1].constructor.name == 'Object') {
+  if (arguments[1] && arguments[1].constructor.name === 'Object') {
     arguments[1].spherical = true;
   }
 
diff --git a/lib/querystream.js b/lib/querystream.js
index 4355ee9fea8..ca62194e4a9 100644
--- a/lib/querystream.js
+++ b/lib/querystream.js
@@ -64,14 +64,14 @@ function QueryStream(query, options) {
   this._buffer = null;
   this._inline = T_INIT;
   this._running = false;
-  this._transform = options && 'function' == typeof options.transform
+  this._transform = options && typeof options.transform === 'function'
       ? options.transform
       : K;
 
   // give time to hook up events
-  var self = this;
+  var _this = this;
   process.nextTick(function () {
-    self._init();
+    _this._init();
   });
 }
 
@@ -118,23 +118,23 @@ QueryStream.prototype._init = function () {
   var query = this.query,
       model = query.model,
       options = query._optionsForExec(model),
-      self = this;
+      _this = this;
 
   try {
     query.cast(model);
   } catch (err) {
-    return self.destroy(err);
+    return _this.destroy(err);
   }
 
-  self._fields = utils.clone(query._fields);
-  options.fields = query._castFields(self._fields);
+  _this._fields = utils.clone(query._fields);
+  options.fields = query._castFields(_this._fields);
 
   model.collection.find(query._conditions, options, function (err, cursor) {
     if (err) {
-      return self.destroy(err);
+      return _this.destroy(err);
     }
-    self._cursor = cursor;
-    self._next();
+    _this._cursor = cursor;
+    _this._next();
   });
 };
 
@@ -235,8 +235,8 @@ QueryStream.prototype._onNextObject = function _onNextObject(err, doc) {
         createAndEmit(this, null, doc);
   }
 
-  var self = this;
-  var pop = helpers.preparePopulationOptionsMQ(self.query, self.query._mongooseOptions);
+  var _this = this;
+  var pop = helpers.preparePopulationOptionsMQ(_this.query, _this.query._mongooseOptions);
 
   // Hack to work around gh-3108
   pop.forEach(function (option) {
@@ -244,13 +244,13 @@ QueryStream.prototype._onNextObject = function _onNextObject(err, doc) {
   });
 
   pop.__noPromise = true;
-  self.query.model.populate(doc, pop, function (err, doc) {
+  _this.query.model.populate(doc, pop, function (err, doc) {
     if (err) {
-      return self.destroy(err);
+      return _this.destroy(err);
     }
     return true === opts.lean ?
-        emit(self, doc) :
-        createAndEmit(self, pop, doc);
+        emit(_this, doc) :
+        createAndEmit(_this, pop, doc);
   });
 };
 
diff --git a/lib/schema.js b/lib/schema.js
index 3bdea04983a..9c88b7f49ce 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -377,7 +377,7 @@ Schema.prototype.add = function add(obj, prefix) {
     }
 
     if (utils.isObject(obj[key]) &&
-        (!obj[key].constructor || 'Object' == utils.getFunctionName(obj[key].constructor)) &&
+        (!obj[key].constructor || 'Object' === utils.getFunctionName(obj[key].constructor)) &&
         (!obj[key][this.options.typeKey] || (this.options.typeKey === 'type' && obj[key].type.type))) {
       if (Object.keys(obj[key]).length) {
         // nested object { last: { name: String }}
@@ -455,7 +455,7 @@ warnings.increment = '`increment` should not be used as a schema path name ' +
  */
 
 Schema.prototype.path = function (path, obj) {
-  if (obj == undefined) {
+  if (obj === undefined) {
     if (this.paths[path]) {
       return this.paths[path];
     }
@@ -490,7 +490,7 @@ Schema.prototype.path = function (path, obj) {
     if (!branch[sub]) {
       branch[sub] = {};
     }
-    if ('object' != typeof branch[sub]) {
+    if (typeof branch[sub] !== 'object') {
       var msg = 'Cannot set nested path `' + path + '`. '
           + 'Parent path `'
           + subpaths.slice(0, i).concat([sub]).join('.')
@@ -528,7 +528,7 @@ Schema.prototype.path = function (path, obj) {
 Schema.interpretAsType = function (path, obj, options) {
   if (obj.constructor) {
     var constructorName = utils.getFunctionName(obj.constructor);
-    if (constructorName != 'Object') {
+    if (constructorName !== 'Object') {
       var oldObj = obj;
       obj = {};
       obj[options.typeKey] = oldObj;
@@ -542,13 +542,13 @@ Schema.interpretAsType = function (path, obj, options) {
       ? obj[options.typeKey]
       : {};
 
-  if ('Object' == utils.getFunctionName(type.constructor) || 'mixed' == type) {
+  if ('Object' === utils.getFunctionName(type.constructor) || type === 'mixed') {
     return new MongooseTypes.Mixed(path, obj);
   }
 
-  if (Array.isArray(type) || Array == type || 'array' == type) {
+  if (Array.isArray(type) || Array === type || type === 'array') {
     // if it was specified through { type } look for `cast`
-    var cast = (Array == type || 'array' == type)
+    var cast = (Array === type || type === 'array')
         ? obj.cast
         : type[0];
 
@@ -556,10 +556,10 @@ Schema.interpretAsType = function (path, obj, options) {
       return new MongooseTypes.DocumentArray(path, cast, obj);
     }
 
-    if ('string' == typeof cast) {
+    if (typeof cast === 'string') {
       cast = MongooseTypes[cast.charAt(0).toUpperCase() + cast.substring(1)];
     } else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type))
-        && 'Object' == utils.getFunctionName(cast.constructor)
+        && 'Object' === utils.getFunctionName(cast.constructor)
         && Object.keys(cast).length) {
       // The `minimize` and `typeKey` options propagate to child schemas
       // declared inline, like `{ arr: [{ val: { $type: String } }] }`.
@@ -583,7 +583,7 @@ Schema.interpretAsType = function (path, obj, options) {
   if (Buffer.isBuffer(type)) {
     name = 'Buffer';
   } else {
-    name = 'string' == typeof type
+    name = typeof type === 'string'
         ? type
       // If not string, `type` is a function. Outside of IE, function.name
       // gives you the function name. In IE, you need to compute it
@@ -816,7 +816,7 @@ Schema.prototype.queue = function (name, args) {
  *     })
  *
  *     toySchema.pre('validate', function (next) {
- *       if (this.name != 'Woody') this.name = 'Woody';
+ *       if (this.name !== 'Woody') this.name = 'Woody';
  *       next();
  *     })
  *
@@ -873,10 +873,10 @@ Schema.prototype.post = function (method, fn) {
   return this.queue('post', [arguments[0], function (next) {
     // wrap original function so that the callback goes last,
     // for compatibility with old code that is using synchronous post hooks
-    var self = this;
+    var _this = this;
     var args = Array.prototype.slice.call(arguments, 1);
     fn.call(this, this, function (err) {
-      return next.apply(self, [err].concat(args));
+      return next.apply(_this, [err].concat(args));
     });
   }]);
 };
@@ -928,7 +928,7 @@ Schema.prototype.plugin = function (fn, opts) {
  */
 
 Schema.prototype.method = function (name, fn) {
-  if ('string' != typeof name) {
+  if (typeof name !== 'string') {
     for (var i in name) {
       this.methods[i] = name[i];
     }
@@ -961,7 +961,7 @@ Schema.prototype.method = function (name, fn) {
  */
 
 Schema.prototype.static = function (name, fn) {
-  if ('string' != typeof name) {
+  if (typeof name !== 'string') {
     for (var i in name) {
       this.statics[i] = name[i];
     }
@@ -1092,11 +1092,11 @@ Schema.prototype.indexes = function () {
       } else {
         index = path._index;
 
-        if (false !== index && null != index) {
+        if (false !== index && null !== index) {
           field = {};
           isObject = utils.isObject(index);
           options = isObject ? index : {};
-          type = 'string' == typeof index ? index :
+          type = typeof index === 'string' ? index :
               isObject ? index.type :
                   false;
 
@@ -1222,8 +1222,8 @@ Schema.prototype.remove = function (path) {
  */
 
 Schema.prototype._getSchema = function (path) {
-  var schema = this;
-  var pathschema = schema.path(path);
+  var _this = this;
+  var pathschema = _this.path(path);
 
   if (pathschema) {
     return pathschema;
@@ -1263,7 +1263,7 @@ Schema.prototype._getSchema = function (path) {
         return foundschema;
       }
     }
-  })(path.split('.'), schema);
+  })(path.split('.'), _this);
 };
 
 /*!
diff --git a/lib/schema/array.js b/lib/schema/array.js
index 3bdefa7528b..b33bea42416 100644
--- a/lib/schema/array.js
+++ b/lib/schema/array.js
@@ -45,7 +45,7 @@ function SchemaArray(key, cast, options) {
     }
 
     // support { type: 'String' }
-    var name = 'string' == typeof cast
+    var name = typeof cast === 'string'
         ? cast
         : utils.getFunctionName(cast);
 
@@ -62,18 +62,18 @@ function SchemaArray(key, cast, options) {
 
   SchemaType.call(this, key, options, 'Array');
 
-  var self = this,
+  var _this = this,
       defaultArr,
       fn;
 
   if (this.defaultValue) {
     defaultArr = this.defaultValue;
-    fn = 'function' == typeof defaultArr;
+    fn = typeof defaultArr === 'function';
   }
 
   this.default(function () {
     var arr = fn ? defaultArr() : defaultArr || [];
-    return new MongooseArray(arr, self.path, this);
+    return new MongooseArray(arr, _this.path, this);
   });
 }
 
@@ -135,7 +135,7 @@ SchemaArray.prototype.cast = function (value, doc, init) {
 
       for (var i = 0, l = indexes.length; i < l; ++i) {
         var pathIndex = indexes[i][0][this.path];
-        if ('2dsphere' === pathIndex || '2d' === pathIndex) {
+        if ('2dsphere' === pathIndex || pathIndex === '2d') {
           return;
         }
       }
@@ -225,8 +225,6 @@ function castToNumber(val) {
 }
 
 function castArraysOfNumbers(arr, self) {
-  self || (self = this);
-
   arr.forEach(function (v, i) {
     if (Array.isArray(v)) {
       castArraysOfNumbers(v, self);
@@ -269,10 +267,10 @@ function cast$geometry(val, self) {
 }
 
 function cast$within(val) {
-  var self = this;
+  var _this = this;
 
   if (val.$maxDistance) {
-    val.$maxDistance = castToNumber.call(self, val.$maxDistance);
+    val.$maxDistance = castToNumber.call(_this, val.$maxDistance);
   }
 
   if (val.$box || val.$polygon) {
diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js
index 6692facfde6..30d83a2ddb5 100644
--- a/lib/schema/boolean.js
+++ b/lib/schema/boolean.js
@@ -54,13 +54,13 @@ SchemaBoolean.prototype.cast = function (value) {
   if (null === value) {
     return value;
   }
-  if ('0' === value) {
+  if (value === '0') {
     return false;
   }
-  if ('true' === value) {
+  if (value === 'true') {
     return true;
   }
-  if ('false' === value) {
+  if (value === 'false') {
     return false;
   }
   return !!value;
diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js
index c7b46ea9fd9..ce83728b485 100644
--- a/lib/schema/buffer.js
+++ b/lib/schema/buffer.js
@@ -47,7 +47,7 @@ SchemaBuffer.prototype.constructor = SchemaBuffer;
 
 SchemaBuffer.prototype.checkRequired = function (value, doc) {
   if (SchemaType._isRef(this, value, doc, true)) {
-    return null != value;
+    return !!value;
   }
   return !!(value && value.length);
 };
@@ -66,7 +66,7 @@ SchemaBuffer.prototype.cast = function (value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (null == value) {
+    if (value === null || value === void 0) {
       return value;
     }
 
@@ -125,7 +125,7 @@ SchemaBuffer.prototype.cast = function (value, doc, init) {
   }
 
   var type = typeof value;
-  if ('string' == type || 'number' == type || Array.isArray(value)) {
+  if ('string' === type || 'number' === type || Array.isArray(value)) {
     if (type === 'number') {
       value = [value];
     }
diff --git a/lib/schema/date.js b/lib/schema/date.js
index 48ebe51993c..158afbd8383 100644
--- a/lib/schema/date.js
+++ b/lib/schema/date.js
@@ -121,17 +121,17 @@ SchemaDate.prototype.checkRequired = function (value) {
 SchemaDate.prototype.min = function (value, message) {
   if (this.minValidator) {
     this.validators = this.validators.filter(function (v) {
-      return v.validator != this.minValidator;
+      return v.validator !== this.minValidator;
     }, this);
   }
 
   if (value) {
     var msg = message || errorMessages.Date.min;
     msg = msg.replace(/{MIN}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
-    var self = this;
+    var _this = this;
     this.validators.push({
       validator: this.minValidator = function (val) {
-        var min = (value === Date.now ? value() : self.cast(value));
+        var min = (value === Date.now ? value() : _this.cast(value));
         return val === null || val.valueOf() >= min.valueOf();
       },
       message: msg,
@@ -177,17 +177,17 @@ SchemaDate.prototype.min = function (value, message) {
 SchemaDate.prototype.max = function (value, message) {
   if (this.maxValidator) {
     this.validators = this.validators.filter(function (v) {
-      return v.validator != this.maxValidator;
+      return v.validator !== this.maxValidator;
     }, this);
   }
 
   if (value) {
     var msg = message || errorMessages.Date.max;
     msg = msg.replace(/{MAX}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
-    var self = this;
+    var _this = this;
     this.validators.push({
       validator: this.maxValidator = function (val) {
-        var max = (value === Date.now ? value() : self.cast(value));
+        var max = (value === Date.now ? value() : _this.cast(value));
         return val === null || val.valueOf() <= max.valueOf();
       },
       message: msg,
@@ -208,7 +208,7 @@ SchemaDate.prototype.max = function (value, message) {
 
 SchemaDate.prototype.cast = function (value) {
   // If null or undefined
-  if (value == null || value === '') {
+  if (value === null || value === void 0 || value === '') {
     return null;
   }
 
@@ -218,7 +218,7 @@ SchemaDate.prototype.cast = function (value) {
 
   var date;
 
-  if (value instanceof Number || 'number' == typeof value
+  if (value instanceof Number || typeof value === 'number'
       || String(value) == Number(value)) {
     // support for timestamps
     date = new Date(Number(value));
diff --git a/lib/schema/number.js b/lib/schema/number.js
index e7daeee85de..d4f6276a8e4 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -44,9 +44,9 @@ SchemaNumber.prototype.constructor = SchemaNumber;
 
 SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
   if (SchemaType._isRef(this, value, doc, true)) {
-    return null != value;
+    return !!value;
   }
-  return typeof value == 'number' || value instanceof Number;
+  return typeof value === 'number' || value instanceof Number;
 };
 
 /**
@@ -83,7 +83,7 @@ SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
 SchemaNumber.prototype.min = function (value, message) {
   if (this.minValidator) {
     this.validators = this.validators.filter(function (v) {
-      return v.validator != this.minValidator;
+      return v.validator !== this.minValidator;
     }, this);
   }
 
@@ -137,11 +137,11 @@ SchemaNumber.prototype.min = function (value, message) {
 SchemaNumber.prototype.max = function (value, message) {
   if (this.maxValidator) {
     this.validators = this.validators.filter(function (v) {
-      return v.validator != this.maxValidator;
+      return v.validator !== this.maxValidator;
     }, this);
   }
 
-  if (null != value) {
+  if (value != null) {
     var msg = message || errorMessages.Number.max;
     msg = msg.replace(/{MAX}/, value);
     this.validators.push({
@@ -170,7 +170,7 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (null == value) {
+    if (value === null || value === void 0) {
       return value;
     }
 
@@ -183,7 +183,7 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
     }
 
     // setting a populated path
-    if ('number' == typeof value) {
+    if (typeof value === 'number') {
       return value;
     } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
       throw new CastError('number', value, this.path);
@@ -217,7 +217,7 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
     if (val instanceof Number) {
       return val;
     }
-    if ('number' == typeof val) {
+    if (typeof val === 'number') {
       return val;
     }
     if (val.toString && !Array.isArray(val) &&
@@ -238,12 +238,12 @@ function handleSingle(val) {
 }
 
 function handleArray(val) {
-  var self = this;
+  var _this = this;
   if (!Array.isArray(val)) {
     return [this.cast(val)];
   }
   return val.map(function (m) {
-    return self.cast(m);
+    return _this.cast(m);
   });
 }
 
@@ -278,7 +278,7 @@ SchemaNumber.prototype.castForQuery = function ($conditional, val) {
     return handler.call(this, val);
   }
   val = this.cast($conditional);
-  return val == null ? val : val;
+  return val;
 };
 
 /*!
diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js
index 22c5fbda7f7..e5b14f0b7e0 100644
--- a/lib/schema/objectid.js
+++ b/lib/schema/objectid.js
@@ -61,7 +61,7 @@ ObjectId.prototype.auto = function (turnOn) {
 
 ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
   if (SchemaType._isRef(this, value, doc, true)) {
-    return null != value;
+    return !!value;
   }
   return value instanceof oid;
 };
@@ -79,7 +79,7 @@ ObjectId.prototype.cast = function (value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (null == value) {
+    if (value === null || value === void 0) {
       return value;
     }
 
@@ -110,7 +110,7 @@ ObjectId.prototype.cast = function (value, doc, init) {
   }
 
   // If null or undefined
-  if (value == null) {
+  if (value === null || value === void 0) {
     return value;
   }
 
diff --git a/lib/schema/operators/bitwise.js b/lib/schema/operators/bitwise.js
index 0818f84d196..e0f535ae641 100644
--- a/lib/schema/operators/bitwise.js
+++ b/lib/schema/operators/bitwise.js
@@ -12,23 +12,23 @@ function handleBitwiseOperator(val) {
   var _this = this;
   if (Array.isArray(val)) {
     return val.map(function (v) {
-      return _castNumber(_this, v);
+      return _castNumber(_this.path, v);
     });
   } else if (Buffer.isBuffer(val)) {
     return val;
   }
   // Assume trying to cast to number
-  return _castNumber(_this, val);
+  return _castNumber(_this.path, val);
 }
 
 /*!
  * ignore
  */
 
-function _castNumber(_this, num) {
+function _castNumber(path, num) {
   var v = Number(num);
   if (isNaN(v)) {
-    throw new CastError('number', num, _this.path);
+    throw new CastError('number', num, path);
   }
   return v;
 }
diff --git a/lib/schema/string.js b/lib/schema/string.js
index 6abbd9e6813..696885ff67c 100644
--- a/lib/schema/string.js
+++ b/lib/schema/string.js
@@ -75,7 +75,7 @@ SchemaString.prototype.constructor = SchemaString;
 SchemaString.prototype.enum = function () {
   if (this.enumValidator) {
     this.validators = this.validators.filter(function (v) {
-      return v.validator != this.enumValidator;
+      return v.validator !== this.enumValidator;
     }, this);
     this.enumValidator = false;
   }
@@ -131,7 +131,7 @@ SchemaString.prototype.enum = function () {
 
 SchemaString.prototype.lowercase = function () {
   return this.set(function (v, self) {
-    if ('string' != typeof v) {
+    if (typeof v !== 'string') {
       v = self.cast(v);
     }
     if (v) {
@@ -157,7 +157,7 @@ SchemaString.prototype.lowercase = function () {
 
 SchemaString.prototype.uppercase = function () {
   return this.set(function (v, self) {
-    if ('string' != typeof v) {
+    if (typeof v !== 'string') {
       v = self.cast(v);
     }
     if (v) {
@@ -187,7 +187,7 @@ SchemaString.prototype.uppercase = function () {
 
 SchemaString.prototype.trim = function () {
   return this.set(function (v, self) {
-    if ('string' != typeof v) {
+    if (typeof v !== 'string') {
       v = self.cast(v);
     }
     if (v) {
@@ -231,11 +231,11 @@ SchemaString.prototype.trim = function () {
 SchemaString.prototype.minlength = function (value, message) {
   if (this.minlengthValidator) {
     this.validators = this.validators.filter(function (v) {
-      return v.validator != this.minlengthValidator;
+      return v.validator !== this.minlengthValidator;
     }, this);
   }
 
-  if (null != value) {
+  if (null !== value) {
     var msg = message || errorMessages.String.minlength;
     msg = msg.replace(/{MINLENGTH}/, value);
     this.validators.push({
@@ -285,11 +285,11 @@ SchemaString.prototype.minlength = function (value, message) {
 SchemaString.prototype.maxlength = function (value, message) {
   if (this.maxlengthValidator) {
     this.validators = this.validators.filter(function (v) {
-      return v.validator != this.maxlengthValidator;
+      return v.validator !== this.maxlengthValidator;
     }, this);
   }
 
-  if (null != value) {
+  if (value != null) {
     var msg = message || errorMessages.String.maxlength;
     msg = msg.replace(/{MAXLENGTH}/, value);
     this.validators.push({
@@ -377,9 +377,9 @@ SchemaString.prototype.match = function match(regExp, message) {
 
 SchemaString.prototype.checkRequired = function checkRequired(value, doc) {
   if (SchemaType._isRef(this, value, doc, true)) {
-    return null != value;
+    return !!value;
   }
-  return (value instanceof String || typeof value == 'string') && value.length;
+  return (value instanceof String || typeof value === 'string') && value.length;
 };
 
 /**
@@ -392,7 +392,7 @@ SchemaString.prototype.cast = function (value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (null == value) {
+    if (value === null) {
       return value;
     }
 
@@ -405,7 +405,7 @@ SchemaString.prototype.cast = function (value, doc, init) {
     }
 
     // setting a populated path
-    if ('string' == typeof value) {
+    if (typeof value === 'string') {
       return value;
     } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
       throw new CastError('string', value, this.path);
@@ -423,13 +423,13 @@ SchemaString.prototype.cast = function (value, doc, init) {
   }
 
   // If null or undefined
-  if (value == null) {
+  if (value === null || value === void 0) {
     return value;
   }
 
-  if ('undefined' !== typeof value) {
+  if (typeof value !== 'undefined') {
     // handle documents being passed
-    if (value._id && 'string' == typeof value._id) {
+    if (value._id && typeof value._id === 'string') {
       return value._id;
     }
 
@@ -453,12 +453,12 @@ function handleSingle(val) {
 }
 
 function handleArray(val) {
-  var self = this;
+  var _this = this;
   if (!Array.isArray(val)) {
     return [this.castForQuery(val)];
   }
   return val.map(function (m) {
-    return self.castForQuery(m);
+    return _this.castForQuery(m);
   });
 }
 
diff --git a/lib/schematype.js b/lib/schematype.js
index 7ed37e2b610..71a32eab11a 100644
--- a/lib/schematype.js
+++ b/lib/schematype.js
@@ -28,9 +28,9 @@ function SchemaType(path, options, instance) {
   this.selected;
 
   for (var i in options) {
-    if (this[i] && 'function' == typeof this[i]) {
+    if (this[i] && typeof this[i] === 'function') {
       // { unique: true, index: true }
-      if ('index' == i && this._index) {
+      if ('index' === i && this._index) {
         continue;
       }
 
@@ -145,9 +145,9 @@ SchemaType.prototype.index = function (options) {
  */
 
 SchemaType.prototype.unique = function (bool) {
-  if (null == this._index || 'boolean' == typeof this._index) {
+  if (null === this._index || typeof this._index === 'boolean') {
     this._index = {};
-  } else if ('string' == typeof this._index) {
+  } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
   }
 
@@ -168,9 +168,9 @@ SchemaType.prototype.unique = function (bool) {
  */
 
 SchemaType.prototype.text = function (bool) {
-  if (null == this._index || 'boolean' == typeof this._index) {
+  if (null === this._index || typeof this._index === 'boolean') {
     this._index = {};
-  } else if ('string' == typeof this._index) {
+  } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
   }
 
@@ -192,9 +192,9 @@ SchemaType.prototype.text = function (bool) {
  */
 
 SchemaType.prototype.sparse = function (bool) {
-  if (null == this._index || 'boolean' == typeof this._index) {
+  if (null === this._index || typeof this._index === 'boolean') {
     this._index = {};
-  } else if ('string' == typeof this._index) {
+  } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
   }
 
@@ -208,7 +208,7 @@ SchemaType.prototype.sparse = function (bool) {
  * ####Example:
  *
  *     function capitalize (val) {
- *       if ('string' != typeof val) val = '';
+ *       if (typeof val !== 'string') val = '';
  *       return val.charAt(0).toUpperCase() + val.substring(1);
  *     }
  *
@@ -276,7 +276,7 @@ SchemaType.prototype.sparse = function (bool) {
  */
 
 SchemaType.prototype.set = function (fn) {
-  if ('function' != typeof fn) {
+  if (typeof fn !== 'function') {
     throw new TypeError('A setter must be a function.');
   }
   this.setters.push(fn);
@@ -346,7 +346,7 @@ SchemaType.prototype.set = function (fn) {
  */
 
 SchemaType.prototype.get = function (fn) {
-  if ('function' != typeof fn) {
+  if (typeof fn !== 'function') {
     throw new TypeError('A getter must be a function.');
   }
   this.getters.push(fn);
@@ -436,7 +436,7 @@ SchemaType.prototype.get = function (fn) {
  */
 
 SchemaType.prototype.validate = function (obj, message, type) {
-  if ('function' == typeof obj || obj && 'RegExp' === utils.getFunctionName(obj.constructor)) {
+  if (typeof obj === 'function' || obj && 'RegExp' === utils.getFunctionName(obj.constructor)) {
     var properties;
     if (message instanceof Object && !type) {
       properties = utils.clone(message);
@@ -508,28 +508,28 @@ SchemaType.prototype.validate = function (obj, message, type) {
 SchemaType.prototype.required = function (required, message) {
   if (false === required) {
     this.validators = this.validators.filter(function (v) {
-      return v.validator != this.requiredValidator;
+      return v.validator !== this.requiredValidator;
     }, this);
 
     this.isRequired = false;
     return this;
   }
 
-  var self = this;
+  var _this = this;
   this.isRequired = true;
 
   this.requiredValidator = function (v) {
     // in here, `this` refers to the validating document.
     // no validation when this path wasn't selected in the query.
-    if ('isSelected' in this && !this.isSelected(self.path) && !this.isModified(self.path)) {
+    if ('isSelected' in this && !this.isSelected(_this.path) && !this.isModified(_this.path)) {
       return true;
     }
 
-    return (('function' === typeof required) && !required.apply(this)) ||
-        self.checkRequired(v, this);
+    return ((typeof required === 'function') && !required.apply(this)) ||
+        _this.checkRequired(v, this);
   };
 
-  if ('string' == typeof required) {
+  if (typeof required === 'string') {
     message = required;
     required = undefined;
   }
@@ -553,7 +553,7 @@ SchemaType.prototype.required = function (required, message) {
  */
 
 SchemaType.prototype.getDefault = function (scope, init) {
-  var ret = 'function' === typeof this.defaultValue
+  var ret = typeof this.defaultValue === 'function'
       ? this.defaultValue.call(scope)
       : this.defaultValue;
 
@@ -676,7 +676,7 @@ SchemaType.prototype.doValidate = function (value, fn, scope) {
     }
   };
 
-  var self = this;
+  var _this = this;
   this.validators.forEach(function (v) {
     if (err) {
       return;
@@ -690,8 +690,8 @@ SchemaType.prototype.doValidate = function (value, fn, scope) {
 
     if (validator instanceof RegExp) {
       validate(validator.test(value), validatorProperties);
-    } else if ('function' === typeof validator) {
-      if (value === undefined && !self.isRequired) {
+    } else if (typeof validator === 'function') {
+      if (value === undefined && !_this.isRequired) {
         validate(true, validatorProperties);
         return;
       }
@@ -740,8 +740,8 @@ SchemaType.prototype.doValidateSync = function (value, scope) {
     }
   };
 
-  var self = this;
-  if (value === undefined && !self.isRequired) {
+  var _this = this;
+  if (value === undefined && !_this.isRequired) {
     return null;
   }
 
@@ -757,7 +757,7 @@ SchemaType.prototype.doValidateSync = function (value, scope) {
 
     if (validator instanceof RegExp) {
       validate(validator.test(value), validatorProperties);
-    } else if ('function' === typeof validator) {
+    } else if (typeof validator === 'function') {
       // if not async validators
       if (2 !== validator.length) {
         validate(validator.call(scope, value), validatorProperties);
@@ -797,7 +797,7 @@ SchemaType._isRef = function (self, value, doc, init) {
       return true;
     }
     if (!Buffer.isBuffer(value) &&  // buffers are objects too
-        'Binary' != value._bsontype // raw binary value from the db
+        'Binary' !== value._bsontype // raw binary value from the db
         && utils.isObject(value)    // might have deselected _id in population query
     ) {
       return true;
diff --git a/lib/statemachine.js b/lib/statemachine.js
index 217bca4bd37..4bf081b9b3b 100644
--- a/lib/statemachine.js
+++ b/lib/statemachine.js
@@ -102,10 +102,10 @@ StateMachine.prototype.clear = function clear(state) {
  */
 
 StateMachine.prototype.some = function some() {
-  var self = this;
+  var _this = this;
   var what = arguments.length ? arguments : this.stateNames;
   return Array.prototype.some.call(what, function (state) {
-    return Object.keys(self.states[state]).length;
+    return Object.keys(_this.states[state]).length;
   });
 };
 
@@ -126,10 +126,10 @@ StateMachine.prototype._iter = function _iter(iterMethod) {
 
     if (!states.length) states = this.stateNames;
 
-    var self = this;
+    var _this = this;
 
     var paths = states.reduce(function (paths, state) {
-      return paths.concat(Object.keys(self.states[state]));
+      return paths.concat(Object.keys(_this.states[state]));
     }, []);
 
     return paths[iterMethod](function (path, i, paths) {
diff --git a/lib/types/array.js b/lib/types/array.js
index 21f3e0c1242..cea257cae95 100644
--- a/lib/types/array.js
+++ b/lib/types/array.js
@@ -106,7 +106,7 @@ MongooseArray.mixin = {
       populated = owner.populated(this._path, true);
     }
 
-    if (populated && null != value) {
+    if (populated && null !== value) {
       // cast to the populated Models schema
       Model = populated.options.model;
 
@@ -176,7 +176,7 @@ MongooseArray.mixin = {
    */
 
   _registerAtomic: function (op, val) {
-    if ('$set' == op) {
+    if ('$set' === op) {
       // $set takes precedence over all other ops.
       // mark entire array modified.
       this._atomics = {$set: val};
@@ -186,10 +186,10 @@ MongooseArray.mixin = {
     var atomics = this._atomics;
 
     // reset pop/shift after save
-    if ('$pop' == op && !('$pop' in atomics)) {
-      var self = this;
+    if ('$pop' === op && !('$pop' in atomics)) {
+      var _this = this;
       this._parent.once('save', function () {
-        self._popped = self._shifted = null;
+        _this._popped = _this._shifted = null;
       });
     }
 
@@ -262,7 +262,7 @@ MongooseArray.mixin = {
         val = val.valueOf();
       }
 
-      if ('$addToSet' == op) {
+      if ('$addToSet' === op) {
         val = {$each: val};
       }
 
@@ -282,7 +282,7 @@ MongooseArray.mixin = {
    */
 
   hasAtomics: function hasAtomics() {
-    if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
+    if (!(this._atomics && this._atomics.constructor.name === 'Object')) {
       return 0;
     }
 
diff --git a/lib/types/buffer.js b/lib/types/buffer.js
index 8bc6e92b23a..b9f518bf07b 100644
--- a/lib/types/buffer.js
+++ b/lib/types/buffer.js
@@ -51,7 +51,7 @@ function MongooseBuffer(value, encode, offset) {
     _parent: {value: doc}
   });
 
-  if (doc && 'string' === typeof path) {
+  if (doc && typeof path === 'string') {
     Object.defineProperty(buf, '_schema', {
       value: doc.schema.path(path)
     });
@@ -197,7 +197,7 @@ MongooseBuffer.mixin = {
  */
 
 MongooseBuffer.mixin.toObject = function (options) {
-  var subtype = 'number' == typeof options
+  var subtype = typeof options === 'number'
       ? options
       : (this._subtype || 0);
   return new Binary(this, subtype);
@@ -253,11 +253,11 @@ MongooseBuffer.mixin.equals = function (other) {
  */
 
 MongooseBuffer.mixin.subtype = function (subtype) {
-  if ('number' != typeof subtype) {
+  if (typeof subtype !== 'number') {
     throw new TypeError('Invalid subtype. Expected a number');
   }
 
-  if (this._subtype != subtype) {
+  if (this._subtype !== subtype) {
     this._markModified();
   }
 
diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js
index f040a4b7c67..8579a87636d 100644
--- a/lib/types/documentarray.js
+++ b/lib/types/documentarray.js
@@ -209,21 +209,21 @@ MongooseDocumentArray.mixin = {
    */
 
   notify: function notify(event) {
-    var self = this;
+    var _this = this;
     return function notify(val) {
-      var i = self.length;
+      var i = _this.length;
       while (i--) {
-        if (!self[i]) continue;
+        if (!_this[i]) continue;
         switch (event) {
           // only swap for save event for now, we may change this to all event types later
           case 'save':
-            val = self[i];
+            val = _this[i];
             break;
           default:
             // NO-OP
             break;
         }
-        self[i].emit(event, val);
+        _this[i].emit(event, val);
       }
     };
   }
diff --git a/lib/types/embedded.js b/lib/types/embedded.js
index c0c4f3b4cc0..a243971a91b 100644
--- a/lib/types/embedded.js
+++ b/lib/types/embedded.js
@@ -29,9 +29,9 @@ function EmbeddedDocument(obj, parentArr, skipId, fields, index) {
 
   Document.call(this, obj, fields, skipId);
 
-  var self = this;
+  var _this = this;
   this.on('isNew', function (val) {
-    self.isNew = val;
+    _this.isNew = val;
   });
 }
 
@@ -268,7 +268,7 @@ EmbeddedDocument.prototype.ownerDocument = function () {
 
 EmbeddedDocument.prototype.$__fullPath = function (path) {
   if (!this.$__.fullPath) {
-    var parent = this;
+    var parent = this; // eslint-disable-line consistent-this
     if (!parent.__parent) {
       return path;
     }
diff --git a/lib/utils.js b/lib/utils.js
index 3911723e68a..8ff81acba56 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -151,10 +151,10 @@ exports.deepEqual = function deepEqual(a, b) {
   }
 
   if (a instanceof RegExp && b instanceof RegExp) {
-    return a.source == b.source &&
-        a.ignoreCase == b.ignoreCase &&
-        a.multiline == b.multiline &&
-        a.global == b.global;
+    return a.source === b.source &&
+        a.ignoreCase === b.ignoreCase &&
+        a.multiline === b.multiline &&
+        a.global === b.global;
   }
 
   if (typeof a !== 'object' && typeof b !== 'object') {
@@ -196,7 +196,7 @@ exports.deepEqual = function deepEqual(a, b) {
 
   // having the same number of owned properties (keys incorporates
   // hasOwnProperty)
-  if (ka.length != kb.length) {
+  if (ka.length !== kb.length) {
     return false;
   }
 
@@ -206,7 +206,7 @@ exports.deepEqual = function deepEqual(a, b) {
 
   // ~~~cheap key test
   for (i = ka.length - 1; i >= 0; i--) {
-    if (ka[i] != kb[i]) {
+    if (ka[i] !== kb[i]) {
       return false;
     }
   }
@@ -246,7 +246,7 @@ exports.clone = function clone(obj, options) {
   }
 
   if (isMongooseObject(obj)) {
-    if (options && options.json && 'function' === typeof obj.toJSON) {
+    if (options && options.json && typeof obj.toJSON === 'function') {
       return obj.toJSON(options);
     }
     return obj.toObject(options);
@@ -299,7 +299,7 @@ function cloneObject(obj, options) {
     for (k in obj) {
       val = clone(obj[k], options);
 
-      if (!minimize || ('undefined' !== typeof val)) {
+      if (!minimize || (typeof val !== 'undefined')) {
         hasKeys || (hasKeys = true);
         ret[k] = val;
       }
@@ -314,7 +314,7 @@ function cloneObject(obj, options) {
       k = keys[i];
       val = clone(obj[k], options);
 
-      if (!minimize || ('undefined' !== typeof val)) {
+      if (!minimize || (typeof val !== 'undefined')) {
         if (!hasKeys) {
           hasKeys = true;
         }
@@ -387,7 +387,7 @@ exports.merge = function merge(to, from) {
 
   while (i--) {
     key = keys[i];
-    if ('undefined' === typeof to[key]) {
+    if (typeof to[key] === 'undefined') {
       to[key] = from[key];
     } else if (exports.isObject(from[key])) {
       merge(to[key], from[key]);
@@ -456,7 +456,7 @@ exports.isObject = function (arg) {
   if (Buffer.isBuffer(arg)) {
     return true;
   }
-  return '[object Object]' == toString.call(arg);
+  return '[object Object]' === toString.call(arg);
 };
 
 /*!
@@ -478,7 +478,7 @@ exports.args = sliced;
  */
 
 exports.tick = function tick(callback) {
-  if ('function' !== typeof callback) {
+  if (typeof callback !== 'function') {
     return;
   }
   return function () {
@@ -522,7 +522,7 @@ var isMongooseObject = exports.isMongooseObject;
  */
 
 exports.expires = function expires(object) {
-  if (!(object && 'Object' == object.constructor.name)) {
+  if (!(object && object.constructor.name === 'Object')) {
     return;
   }
   if (!('expires' in object)) {
@@ -530,7 +530,7 @@ exports.expires = function expires(object) {
   }
 
   var when;
-  if ('string' != typeof object.expires) {
+  if (typeof object.expires !== 'string') {
     when = object.expires;
   } else {
     when = Math.round(ms(object.expires) / 1000);
@@ -590,13 +590,13 @@ exports.populate = function populate(path, select, model, match, options, subPop
       subPopulate = path.populate;
       path = path.path;
     }
-  } else if ('string' !== typeof model && 'function' !== typeof model) {
+  } else if (typeof model !== 'string' && typeof model !== 'function') {
     options = match;
     match = model;
     model = undefined;
   }
 
-  if ('string' != typeof path) {
+  if (typeof path !== 'string') {
     throw new TypeError('utils.populate: invalid path. Expected string. Got typeof `' + typeof path + '`');
   }
 
@@ -810,7 +810,7 @@ exports.mergeClone = function (to, from) {
 
   while (i--) {
     key = keys[i];
-    if ('undefined' === typeof to[key]) {
+    if (typeof to[key] === 'undefined') {
       // make sure to retain key order here because of a bug handling the $each
       // operator in mongodb 2.4.4
       to[key] = exports.clone(from[key], {retainKeyOrder: 1});
diff --git a/static.js b/static.js
index ade4f661003..f99bf857ec1 100644
--- a/static.js
+++ b/static.js
@@ -4,7 +4,7 @@ var server = new static.Server('.', {cache: 0});
 var open = require('open');
 
 require('http').createServer(function (req, res) {
-  if ('/favicon.ico' == req.url) {
+  if ('/favicon.ico' === req.url) {
     req.destroy();
     res.statusCode = 204;
     return res.end();
diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index d252c9f04b0..bb55362b94f 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -532,7 +532,7 @@ describe('aggregate: ', function () {
         if (err) {
           return done(err);
         }
-        var mongo26 = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
+        var mongo26 = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
         if (!mongo26) {
           return done();
         }
@@ -602,7 +602,7 @@ describe('aggregate: ', function () {
       setupData(function (db) {
         start.mongodVersion(function (err, version) {
           if (err) throw err;
-          var mongo26_or_greater = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
+          var mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
 
           var m = db.model('Employee');
           var match = {$match: {sal: {$gt: 15000}}};
diff --git a/test/browser/schema.validation.test_.js b/test/browser/schema.validation.test_.js
index 99959a59087..9fde9b2b956 100644
--- a/test/browser/schema.validation.test_.js
+++ b/test/browser/schema.validation.test_.js
@@ -636,7 +636,7 @@ describe('schema', function () {
 
       it('ingore async', function (done) {
         function syncValidator(val) {
-          return val == 'sync';
+          return val''sync';
         }
 
         var called = false;
@@ -644,7 +644,7 @@ describe('schema', function () {
         function asyncValidator(val, respond) {
           called = true;
           setTimeout(function () {
-            respond(val == 'async');
+            respond(val''async');
           }, 0);
         }
 
@@ -663,7 +663,7 @@ describe('schema', function () {
 
       it('subdoc', function (done) {
         function syncValidator(val) {
-          return val == 'sync';
+          return val === 'sync';
         }
 
         var called = false;
@@ -671,7 +671,7 @@ describe('schema', function () {
         function asyncValidator(val, respond) {
           called = true;
           setTimeout(function () {
-            respond(val == 'async');
+            respond(val === 'async');
           }, 0);
         }
 
diff --git a/test/browser/types.objectid.test_.js b/test/browser/types.objectid.test_.js
index 41b284ff529..0fbb1f5b68f 100644
--- a/test/browser/types.objectid.test_.js
+++ b/test/browser/types.objectid.test_.js
@@ -20,7 +20,7 @@
         ObjectId.createFromHexString('00000000000000000000001');
         assert.ok(false);
       } catch (err) {
-        assert.ok(err != null);
+        assert.ok(err !== null);
       }
 
       done();
diff --git a/test/connection.test.js b/test/connection.test.js
index b619e7269fa..cbdfcead4fd 100644
--- a/test/connection.test.js
+++ b/test/connection.test.js
@@ -168,7 +168,7 @@ describe('connections:', function () {
 
               assert.notEqual(port1, db.port);
               assert.ok(db1 !== db.db);
-              assert.ok(db1.serverConfig.port != db.db.serverConfig.port);
+              assert.ok(db1.serverConfig.port !== db.db.serverConfig.port);
 
               var port2 = db.port;
               var db2 = db.db;
@@ -184,7 +184,7 @@ describe('connections:', function () {
 
                   assert.notEqual(port2, db.port);
                   assert.ok(db2 !== db.db);
-                  assert.ok(db2.serverConfig.port != db.db.serverConfig.port);
+                  assert.ok(db2.serverConfig.port !== db.db.serverConfig.port);
 
                   db.close(done);
                 });
@@ -711,7 +711,7 @@ describe('connections:', function () {
       var A = mongoose.model('testing853a', new Schema({x: String}), 'testing853-1');
       var B = mongoose.model('testing853b', new Schema({x: String}), 'testing853-2');
       var C = B.model('testing853a');
-      assert.ok(C == A);
+      assert.ok(C === A);
       done();
     });
 
@@ -761,7 +761,7 @@ describe('connections:', function () {
       var A = mongoose.model('gh-1209-a', s1);
       var B = db.model('gh-1209-a', s2);
 
-      assert.ok(A.schema != B.schema);
+      assert.ok(A.schema !== B.schema);
       assert.ok(A.schema.paths.one);
       assert.ok(B.schema.paths.two);
       assert.ok(!B.schema.paths.one);
@@ -770,7 +770,7 @@ describe('connections:', function () {
       // reset
       delete db.models['gh-1209-a'];
       var C = db.model('gh-1209-a');
-      assert.ok(C.schema == A.schema);
+      assert.ok(C.schema === A.schema);
 
       db.close();
       done();
@@ -797,10 +797,10 @@ describe('connections:', function () {
           var A = db.model(name, s1);
           var B = db.model(name);
           var C = db.model(name, 'alternate');
-          assert.ok(A.collection.name == B.collection.name);
-          assert.ok(A.collection.name != C.collection.name);
-          assert.ok(db.models[name].collection.name != C.collection.name);
-          assert.ok(db.models[name].collection.name == A.collection.name);
+          assert.ok(A.collection.name === B.collection.name);
+          assert.ok(A.collection.name !== C.collection.name);
+          assert.ok(db.models[name].collection.name !== C.collection.name);
+          assert.ok(db.models[name].collection.name === A.collection.name);
           db.close();
           done();
         });
diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index f287e116942..b27d47a1d6e 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -698,7 +698,7 @@ describe('document: hooks:', function () {
 
   describe('gh-3284', function () {
     it('should call pre hooks on nested subdoc', function (done) {
-      var self = this;
+      var _this = this;
 
       var childSchema = new Schema({
         title: String
@@ -706,7 +706,7 @@ describe('document: hooks:', function () {
 
       ['init', 'save', 'validate'].forEach(function (type) {
         childSchema.pre(type, function (next) {
-          self['pre' + type + 'Called'] = true;
+          _this['pre' + type + 'Called'] = true;
           next();
         });
       });
@@ -734,9 +734,9 @@ describe('document: hooks:', function () {
         return Parent.findById(parent._id);
       }).then(function () {
         db.close();
-        assert.ok(self.preinitCalled);
-        assert.ok(self.prevalidateCalled);
-        assert.ok(self.presaveCalled);
+        assert.ok(_this.preinitCalled);
+        assert.ok(_this.prevalidateCalled);
+        assert.ok(_this.presaveCalled);
         done();
       });
     });
diff --git a/test/document.test.js b/test/document.test.js
index cd7f0fd923f..98252dbd6be 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -346,7 +346,7 @@ describe('document', function () {
     doc.schema.options.toObject = {};
     doc.schema.options.toObject.transform = function xform(doc, ret) {
       // ignore embedded docs
-      if ('function' == typeof doc.ownerDocument) {
+      if ('function' === typeof doc.ownerDocument) {
         return;
       }
 
@@ -368,7 +368,7 @@ describe('document', function () {
     var out = {myid: doc._id.toString()};
     doc.schema.options.toObject.transform = function (doc, ret) {
       // ignore embedded docs
-      if ('function' == typeof doc.ownerDocument) {
+      if ('function' === typeof doc.ownerDocument) {
         return;
       }
 
@@ -682,7 +682,7 @@ describe('document', function () {
     doc.schema.options.toJSON = {};
     doc.schema.options.toJSON.transform = function xform(doc, ret) {
       // ignore embedded docs
-      if ('function' == typeof doc.ownerDocument) {
+      if ('function' === typeof doc.ownerDocument) {
         return;
       }
 
@@ -704,7 +704,7 @@ describe('document', function () {
     var out = {myid: doc._id.toString()};
     doc.schema.options.toJSON.transform = function (doc, ret) {
       // ignore embedded docs
-      if ('function' == typeof doc.ownerDocument) {
+      if ('function' === typeof doc.ownerDocument) {
         return;
       }
 
diff --git a/test/index.test.js b/test/index.test.js
index d6bcd971dc6..eac4d5e1950 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -221,10 +221,10 @@ describe('mongoose module:', function () {
           var A = m.model(name, s1);
           var B = m.model(name);
           var C = m.model(name, 'alternate');
-          assert.ok(A.collection.name == B.collection.name);
-          assert.ok(A.collection.name != C.collection.name);
-          assert.ok(m.models[name].collection.name != C.collection.name);
-          assert.ok(m.models[name].collection.name == A.collection.name);
+          assert.ok(A.collection.name === B.collection.name);
+          assert.ok(A.collection.name !== C.collection.name);
+          assert.ok(m.models[name].collection.name !== C.collection.name);
+          assert.ok(m.models[name].collection.name === A.collection.name);
           done();
         });
       });
diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js
index ec907413dfe..c895ace9af3 100644
--- a/test/model.aggregate.test.js
+++ b/test/model.aggregate.test.js
@@ -48,7 +48,7 @@ describe('model aggregate', function () {
       assert.ifError(err);
       start.mongodVersion(function (err, version) {
         if (err) throw err;
-        mongo26_or_greater = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
+        mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
         if (!mongo26_or_greater) console.log('not testing mongodb 2.6 features');
         done();
       });
diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index a256fd9c87c..46bde1ac311 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -1195,12 +1195,14 @@ describe('model: findByIdAndUpdate:', function () {
 
       var s = new Schema({
         topping: {
-          type: String, validate: function () {
+          type: String,
+          validate: function () {
             return false;
           }
         },
         base: {
-          type: String, validate: function () {
+          type: String,
+          validate: function () {
             return true;
           }
         }
@@ -1222,8 +1224,7 @@ describe('model: findByIdAndUpdate:', function () {
             assert.ok(!breakfast);
             assert.equal(1, Object.keys(error.errors).length);
             assert.equal('topping', Object.keys(error.errors)[0]);
-            assert.equal('Validator failed for path `topping` with value `bacon`',
-                error.errors['topping'].message);
+            assert.equal('Validator failed for path `topping` with value `bacon`', error.errors.topping.message);
 
             assert.ok(!breakfast);
             db.close();
@@ -1253,12 +1254,10 @@ describe('model: findByIdAndUpdate:', function () {
             assert.ok(!!error);
             assert.ok(!breakfast);
             assert.equal(2, Object.keys(error.errors).length);
-            assert.ok(Object.keys(error.errors).indexOf('eggs') != -1);
-            assert.ok(Object.keys(error.errors).indexOf('steak') != -1);
-            assert.equal('Validator failed for path `eggs` with value `softboiled`',
-                error.errors['eggs'].message);
-            assert.equal('Path `steak` is required.',
-                error.errors['steak'].message);
+            assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1);
+            assert.ok(Object.keys(error.errors).indexOf('steak') !== -1);
+            assert.equal('Validator failed for path `eggs` with value `softboiled`', error.errors.eggs.message);
+            assert.equal('Path `steak` is required.', error.errors.steak.message);
             db.close();
             done();
           });
@@ -1283,8 +1282,7 @@ describe('model: findByIdAndUpdate:', function () {
             assert.ok(!!error);
             assert.equal(1, Object.keys(error.errors).length);
             assert.equal('eggs', Object.keys(error.errors)[0]);
-            assert.equal('Path `eggs` (3) is less than minimum allowed value (4).',
-                error.errors['eggs'].message);
+            assert.equal('Path `eggs` (3) is less than minimum allowed value (4).', error.errors.eggs.message);
 
             Breakfast.findOneAndUpdate(
                 {},
@@ -1294,9 +1292,7 @@ describe('model: findByIdAndUpdate:', function () {
                   assert.ok(!!error);
                   assert.equal(1, Object.keys(error.errors).length);
                   assert.equal('steak', Object.keys(error.errors)[0]);
-                  assert.equal('`tofu` is not a valid enum value for path `steak`.',
-                      error.errors['steak']);
-
+                  assert.equal('`tofu` is not a valid enum value for path `steak`.', error.errors.steak);
 
                   Breakfast.findOneAndUpdate(
                       {},
@@ -1306,8 +1302,7 @@ describe('model: findByIdAndUpdate:', function () {
                         assert.ok(!!error);
                         assert.equal(1, Object.keys(error.errors).length);
                         assert.equal('bacon', Object.keys(error.errors)[0]);
-                        assert.equal('Path `bacon` is invalid (none).',
-                            error.errors['bacon'].message);
+                        assert.equal('Path `bacon` is invalid (none).', error.errors.bacon.message);
 
                         db.close();
                         done();
diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js
index d13c5444ecd..0c286b58f16 100644
--- a/test/model.geonear.test.js
+++ b/test/model.geonear.test.js
@@ -36,7 +36,7 @@ describe('model', function () {
   before(function (done) {
     start.mongodVersion(function (err, version) {
       if (err) throw err;
-      mongo24_or_greater = 2 < version[0] || (2 == version[0] && 4 <= version[1]);
+      mongo24_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 4);
       if (!mongo24_or_greater) console.log('not testing mongodb 2.4 features');
       done();
     });
diff --git a/test/model.hydrate.test.js b/test/model.hydrate.test.js
index ae94a6d881a..6d62657fb1e 100644
--- a/test/model.hydrate.test.js
+++ b/test/model.hydrate.test.js
@@ -67,7 +67,7 @@ describe('model', function () {
 
       hydrated.validate(function (err) {
         assert.ok(err);
-        assert.ok(err.errors['food']);
+        assert.ok(err.errors.food);
         assert.deepEqual(['food'], Object.keys(err.errors));
         done();
       });
diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js
index 7db34644702..4fbca37788b 100644
--- a/test/model.indexes.test.js
+++ b/test/model.indexes.test.js
@@ -72,13 +72,13 @@ describe('model', function () {
 
           for (var i in indexes) {
             indexes[i].forEach(function (index) {
-              if (index[0] == 'name') {
+              if (index[0] === 'name') {
                 assertions++;
               }
-              if (index[0] == 'blogposts._id') {
+              if (index[0] === 'blogposts._id') {
                 assertions++;
               }
-              if (index[0] == 'blogposts.title') {
+              if (index[0] === 'blogposts.title') {
                 assertions++;
               }
             });
diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 6b04f901e63..9dcd240c7bb 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -79,16 +79,16 @@ describe('model: mapreduce:', function () {
         assert.ok(Array.isArray(ret));
         assert.ok(stats);
         ret.forEach(function (res) {
-          if ('aaron' == res._id) {
+          if (res._id === 'aaron') {
             assert.equal(3, res.value);
           }
-          if ('guillermo' == res._id) {
+          if (res._id === 'guillermo') {
             assert.equal(3, res.value);
           }
-          if ('brian' == res._id) {
+          if (res._id === 'brian') {
             assert.equal(2, res.value);
           }
-          if ('nathan' == res._id) {
+          if (res._id === 'nathan') {
             assert.equal(2, res.value);
           }
         });
@@ -275,16 +275,16 @@ describe('model: mapreduce:', function () {
         assert.ok(Array.isArray(ret));
         assert.ok(stats);
         ret.forEach(function (res) {
-          if ('aaron' == res._id) {
+          if (res._id === 'aaron') {
             assert.equal(6, res.value);
           }
-          if ('guillermo' == res._id) {
+          if (res._id === 'guillermo') {
             assert.equal(6, res.value);
           }
-          if ('brian' == res._id) {
+          if (res._id === 'brian') {
             assert.equal(4, res.value);
           }
-          if ('nathan' == res._id) {
+          if (res._id === 'nathan') {
             assert.equal(4, res.value);
           }
         });
diff --git a/test/model.middleware.test.js b/test/model.middleware.test.js
index fdbadd45ee6..c949554f619 100644
--- a/test/model.middleware.test.js
+++ b/test/model.middleware.test.js
@@ -205,16 +205,16 @@ describe('model middleware', function () {
     parent.save(function (error) {
       assert.ifError(error);
       assert.equal(2, childPreCalls);
-      assert.equal(1, childPreCallsByName['Jaina']);
-      assert.equal(1, childPreCallsByName['Jacen']);
+      assert.equal(1, childPreCallsByName.Jaina);
+      assert.equal(1, childPreCallsByName.Jacen);
       assert.equal(1, parentPreCalls);
       parent.children[0].name = 'Anakin';
       parent.save(function (error) {
         assert.ifError(error);
         assert.equal(4, childPreCalls);
-        assert.equal(1, childPreCallsByName['Anakin']);
-        assert.equal(1, childPreCallsByName['Jaina']);
-        assert.equal(2, childPreCallsByName['Jacen']);
+        assert.equal(1, childPreCallsByName.Anakin);
+        assert.equal(1, childPreCallsByName.Jaina);
+        assert.equal(2, childPreCallsByName.Jacen);
 
         assert.equal(2, parentPreCalls);
         db.close();
diff --git a/test/model.populate.test.js b/test/model.populate.test.js
index f10512fc9ac..a911b83051c 100644
--- a/test/model.populate.test.js
+++ b/test/model.populate.test.js
@@ -297,7 +297,7 @@ describe('model: populate:', function () {
             db.close();
             db2.close();
             assert.ifError(err);
-            assert.ok(post._creator.name == 'Guillermo');
+            assert.ok(post._creator.name === 'Guillermo');
             done();
           });
         });
@@ -327,7 +327,7 @@ describe('model: populate:', function () {
         // mock an error
         User.find = function () {
           var args = Array.prototype.map.call(arguments, function (arg) {
-            return 'function' == typeof arg ? function () {
+            return 'function' === typeof arg ? function () {
               arg(new Error('woot'));
             } : arg;
           });
@@ -653,7 +653,7 @@ describe('model: populate:', function () {
             var origFind = User.find;
             User.find = function () {
               var args = Array.prototype.map.call(arguments, function (arg) {
-                return 'function' == typeof arg ? function () {
+                return 'function' === typeof arg ? function () {
                   arg(new Error('woot 2'));
                 } : arg;
               });
@@ -2758,7 +2758,7 @@ describe('model: populate:', function () {
 
           docs.forEach(function (doc) {
             assert.ok(doc.comment && doc.comment.body);
-            if ('u1' == doc.name) {
+            if (doc.name === 'u1') {
               assert.equal('comment 1', doc.comment.body);
             } else {
               assert.equal('comment 2', doc.comment.body);
@@ -2802,7 +2802,7 @@ describe('model: populate:', function () {
               assert.ifError(err);
 
               var a2 = docs.filter(function (d) {
-                return 'body2' == d.body;
+                return d.body === 'body2';
               })[0];
               assert.equal(a2.mediaAttach.id, media.id);
 
diff --git a/test/model.querying.test.js b/test/model.querying.test.js
index d97fcf97504..8e85d25949a 100644
--- a/test/model.querying.test.js
+++ b/test/model.querying.test.js
@@ -62,7 +62,7 @@ describe('model: querying:', function () {
       if (err) {
         throw err;
       }
-      mongo26_or_greater = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
+      mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
       if (!mongo26_or_greater) {
         console.log('not testing mongodb 2.6 features');
       }
@@ -1143,9 +1143,9 @@ describe('model: querying:', function () {
             var found2 = false;
 
             found.forEach(function (doc) {
-              if (doc.id == one.id) {
+              if (doc.id === one.id) {
                 found1 = true;
-              } else if (doc.id == two.id) {
+              } else if (doc.id === two.id) {
                 found2 = true;
               }
             });
@@ -1174,9 +1174,9 @@ describe('model: querying:', function () {
             var found2 = false;
 
             found.forEach(function (doc) {
-              if (doc.id == one.id) {
+              if (doc.id === one.id) {
                 found1 = true;
-              } else if (doc.id == two.id) {
+              } else if (doc.id === two.id) {
                 found2 = true;
               }
             });
@@ -1519,7 +1519,7 @@ describe('model: querying:', function () {
           assert.equal(docs[1].dt, '2011-03-31');
           assert.equal(docs[2].dt, '2011-04-01');
           assert.equal(false, docs.some(function (d) {
-            return '2011-04-02' === d.dt;
+            return d.dt === '2011-04-02';
           }));
         });
 
@@ -1533,10 +1533,10 @@ describe('model: querying:', function () {
           assert.equal(docs[0].dt, '2011-03-31');
           assert.equal(docs[1].dt, '2011-04-01');
           assert.equal(false, docs.some(function (d) {
-            return '2011-03-30' === d.dt;
+            return d.dt === '2011-03-30';
           }));
           assert.equal(false, docs.some(function (d) {
-            return '2011-04-02' === d.dt;
+            return d.dt === '2011-04-02';
           }));
         });
       }
@@ -1851,7 +1851,7 @@ describe('model: querying:', function () {
         if (err) {
           throw err;
         }
-        var mongo26_or_greater = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
+        var mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
         if (!mongo26_or_greater) {
           return done();
         }
@@ -2316,7 +2316,7 @@ describe('geo-spatial', function () {
           throw err;
         }
 
-        mongo24_or_greater = 2 < version[0] || (2 == version[0] && 4 <= version[1]);
+        mongo24_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 4);
         if (!mongo24_or_greater) {
           console.log('not testing mongodb 2.4 features');
         }
@@ -2330,7 +2330,7 @@ describe('geo-spatial', function () {
       }
 
       var ok = schema2dsphere.indexes().some(function (index) {
-        return '2dsphere' == index[0].loc;
+        return index[0].loc === '2dsphere';
       });
       assert.ok(ok);
       done();
@@ -2552,7 +2552,7 @@ describe('geo-spatial', function () {
         if (err) {
           return done(err);
         }
-        mongo24_or_greater = 2 < version[0] || (2 == version[0] && 4 <= version[1]);
+        mongo24_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 4);
         if (!mongo24_or_greater) {
           console.log('not testing mongodb 2.4 features');
         }
@@ -2580,7 +2580,7 @@ describe('geo-spatial', function () {
             assert.ifError(err);
 
             var found = indexes.some(function (index) {
-              return 'hashed' === index.key.t;
+              return index.key.t === 'hashed';
             });
             assert.ok(found);
 
@@ -2595,7 +2595,7 @@ describe('geo-spatial', function () {
       });
 
       function complete() {
-        if (0 === --pending) {
+        if (--pending === 0) {
           db.close(done);
         }
       }
@@ -2713,7 +2713,7 @@ describe('lean option:', function () {
         if (err) {
           return done(err);
         }
-        mongo26 = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
+        mongo26 = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
         done();
       });
     });
diff --git a/test/model.stream.test.js b/test/model.stream.test.js
index aa2780630ba..a407bef2e5b 100644
--- a/test/model.stream.test.js
+++ b/test/model.stream.test.js
@@ -52,6 +52,17 @@ describe('query stream:', function () {
 
     var stream = P.find().batchSize(3).stream();
 
+    function cb() {
+      db.close();
+      assert.strictEqual(undefined, err);
+      assert.equal(i, names.length);
+      assert.equal(1, closed);
+      assert.equal(1, paused);
+      assert.equal(1, resumed);
+      assert.equal(true, stream._cursor.isClosed());
+      done();
+    }
+
     stream.on('data', function (doc) {
       assert.strictEqual(true, !!doc.name);
       assert.strictEqual(true, !!doc._id);
@@ -96,17 +107,6 @@ describe('query stream:', function () {
       closed++;
       cb();
     });
-
-    function cb() {
-      db.close();
-      assert.strictEqual(undefined, err);
-      assert.equal(i, names.length);
-      assert.equal(1, closed);
-      assert.equal(1, paused);
-      assert.equal(1, resumed);
-      assert.equal(true, stream._cursor.isClosed());
-      done();
-    }
   });
 
   it('immediately destroying a stream prevents the query from executing', function (done) {
@@ -116,14 +116,6 @@ describe('query stream:', function () {
 
     var stream = P.where('name', 'Jonah').select('name').findOne().stream();
 
-    stream.on('data', function () {
-      i++;
-    });
-    stream.on('close', cb);
-    stream.on('error', cb);
-
-    stream.destroy();
-
     function cb(err) {
       assert.ifError(err);
       assert.equal(0, i);
@@ -133,6 +125,14 @@ describe('query stream:', function () {
         done();
       });
     }
+
+    stream.on('data', function () {
+      i++;
+    });
+    stream.on('close', cb);
+    stream.on('error', cb);
+
+    stream.destroy();
   });
 
   it('destroying a stream stops it', function (done) {
@@ -148,17 +148,6 @@ describe('query stream:', function () {
     assert.strictEqual(null, stream._destroyed);
     assert.equal(true, stream.readable);
 
-    stream.on('data', function (doc) {
-      assert.strictEqual(undefined, doc.name);
-      if (++i === 5) {
-        stream.destroy();
-        assert.equal(false, stream.readable);
-      }
-    });
-
-    stream.on('close', cb);
-    stream.on('error', cb);
-
     function cb(err) {
       ++finished;
       setTimeout(function () {
@@ -172,6 +161,17 @@ describe('query stream:', function () {
         done();
       }, 100);
     }
+
+    stream.on('data', function (doc) {
+      assert.strictEqual(undefined, doc.name);
+      if (++i === 5) {
+        stream.destroy();
+        assert.equal(false, stream.readable);
+      }
+    });
+
+    stream.on('close', cb);
+    stream.on('error', cb);
   });
 
   it('errors', function (done) {
@@ -185,18 +185,6 @@ describe('query stream:', function () {
 
     var stream = P.find().batchSize(5).stream();
 
-    stream.on('data', function () {
-      if (++i === 5) {
-        db.close();
-      }
-    });
-
-    stream.on('close', function () {
-      closed++;
-    });
-
-    stream.on('error', cb);
-
     function cb(err) {
       ++finished;
       setTimeout(function () {
@@ -210,6 +198,18 @@ describe('query stream:', function () {
         done();
       }, 100);
     }
+
+    stream.on('data', function () {
+      if (++i === 5) {
+        db.close();
+      }
+    });
+
+    stream.on('close', function () {
+      closed++;
+    });
+
+    stream.on('error', cb);
   });
 
   it('pipe', function (done) {
@@ -222,7 +222,7 @@ describe('query stream:', function () {
     var stream = P.find().sort('name').limit(20).stream(opts);
     stream.pipe(out);
 
-    var cb = function (err) {
+    function cb(err) {
       db.close();
       assert.ifError(err);
       var contents = fs.readFileSync(filename, 'utf8');
@@ -233,7 +233,7 @@ describe('query stream:', function () {
       assert.ok(/Agustin/.test(contents));
       fs.unlink(filename);
       done();
-    };
+    }
 
     stream.on('error', cb);
     out.on('close', cb);
@@ -248,6 +248,15 @@ describe('query stream:', function () {
 
     var stream = P.find({}).lean().stream();
 
+    function cb() {
+      db.close();
+      assert.strictEqual(undefined, err);
+      assert.equal(i, names.length);
+      assert.equal(1, closed);
+      assert.equal(true, stream._cursor.isClosed());
+      done();
+    }
+
     stream.on('data', function (doc) {
       assert.strictEqual(false, doc instanceof mongoose.Document);
       i++;
@@ -277,15 +286,6 @@ describe('query stream:', function () {
       closed++;
       cb();
     });
-
-    var cb = function () {
-      db.close();
-      assert.strictEqual(undefined, err);
-      assert.equal(i, names.length);
-      assert.equal(1, closed);
-      assert.equal(true, stream._cursor.isClosed());
-      done();
-    };
   });
 
   it('supports $elemMatch with $in (gh-1091)', function (done) {
@@ -342,6 +342,14 @@ describe('query stream:', function () {
     var Bar = db.model('Bar', barSchema);
     var found = [];
 
+    function complete(err) {
+      if (!err) {
+        assert.ok(~found.indexOf(2));
+        assert.ok(~found.indexOf(3));
+      }
+      db.close(done);
+    }
+
     Bar.create({value: 2}, {value: 3}, function (err, bar1, bar2) {
       if (err) return complete(err);
 
@@ -359,14 +367,6 @@ describe('query stream:', function () {
           on('error', complete);
       });
     });
-
-    var complete = function (err) {
-      if (!err) {
-        assert.ok(~found.indexOf(2));
-        assert.ok(~found.indexOf(3));
-      }
-      db.close(done);
-    };
   });
 
   it('respects schema options (gh-1862)', function (done) {
diff --git a/test/model.test.js b/test/model.test.js
index b7ab7ebd05f..a4f6c3df5da 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -782,8 +782,9 @@ describe('Model', function () {
           BlogPost = db.model('BlogPost', collection),
           threw = false;
 
+      var post;
       try {
-        var post = new BlogPost({date: 'Test', meta: {date: 'Test'}});
+        post = new BlogPost({date: 'Test', meta: {date: 'Test'}});
       } catch (e) {
         threw = true;
       }
@@ -1542,7 +1543,7 @@ describe('Model', function () {
         });
 
         ValidationMiddlewareSchema.pre('validate', function (next) {
-          if (this.get('baz') == 'bad') {
+          if (this.get('baz') === 'bad') {
             this.invalidate('baz', 'bad');
           }
           next();
@@ -1580,10 +1581,10 @@ describe('Model', function () {
         });
 
         AsyncValidationMiddlewareSchema.pre('validate', true, function (next, done) {
-          var self = this;
+          var _this = this;
           setTimeout(function () {
-            if (self.get('prop') == 'bad') {
-              self.invalidate('prop', 'bad');
+            if (_this.get('prop') === 'bad') {
+              _this.invalidate('prop', 'bad');
             }
             done();
           }, 5);
@@ -1628,10 +1629,10 @@ describe('Model', function () {
         });
 
         ComplexValidationMiddlewareSchema.pre('validate', true, function (next, done) {
-          var self = this;
+          var _this = this;
           setTimeout(function () {
-            if (self.get('baz') == 'bad') {
-              self.invalidate('baz', 'bad');
+            if (_this.get('baz') === 'bad') {
+              _this.invalidate('baz', 'bad');
             }
             done();
           }, 5);
@@ -2532,6 +2533,58 @@ describe('Model', function () {
 
       var post = new BlogPost;
 
+      function complete() {
+        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+          db.close();
+
+          assert.ifError(err);
+          assert.equal(doc.get('comments').length, 5);
+
+          var v = doc.get('comments').some(function (comment) {
+            return comment.get('title') === '1';
+          });
+
+          assert.ok(v);
+
+          v = doc.get('comments').some(function (comment) {
+            return comment.get('title') === '2';
+          });
+
+          assert.ok(v);
+
+          v = doc.get('comments').some(function (comment) {
+            return comment.get('title') === '3';
+          });
+
+          assert.ok(v);
+
+          v = doc.get('comments').some(function (comment) {
+            return comment.get('title') === '4';
+          });
+
+          assert.ok(v);
+
+          v = doc.get('comments').some(function (comment) {
+            return comment.get('title') === '5';
+          });
+
+          assert.ok(v);
+          done();
+        });
+      }
+
+      function save(doc) {
+        saveQueue.push(doc);
+        if (saveQueue.length === 4) {
+          saveQueue.forEach(function (doc) {
+            doc.save(function (err) {
+              assert.ifError(err);
+              --totalDocs || complete();
+            });
+          });
+        }
+      }
+
       post.save(function (err) {
         assert.ifError(err);
 
@@ -2558,58 +2611,6 @@ describe('Model', function () {
           doc.get('comments').push({title: '4'}, {title: '5'});
           save(doc);
         });
-
-        function save(doc) {
-          saveQueue.push(doc);
-          if (saveQueue.length == 4) {
-            saveQueue.forEach(function (doc) {
-              doc.save(function (err) {
-                assert.ifError(err);
-                --totalDocs || complete();
-              });
-            });
-          }
-        }
-
-        function complete() {
-          BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
-            db.close();
-
-            assert.ifError(err);
-            assert.equal(doc.get('comments').length, 5);
-
-            var v = doc.get('comments').some(function (comment) {
-              return comment.get('title') == '1';
-            });
-
-            assert.ok(v);
-
-            v = doc.get('comments').some(function (comment) {
-              return comment.get('title') == '2';
-            });
-
-            assert.ok(v);
-
-            v = doc.get('comments').some(function (comment) {
-              return comment.get('title') == '3';
-            });
-
-            assert.ok(v);
-
-            v = doc.get('comments').some(function (comment) {
-              return comment.get('title') == '4';
-            });
-
-            assert.ok(v);
-
-            v = doc.get('comments').some(function (comment) {
-              return comment.get('title') == '5';
-            });
-
-            assert.ok(v);
-            done();
-          });
-        }
       });
     });
 
@@ -2870,6 +2871,41 @@ describe('Model', function () {
 
       var t = new Temp();
 
+      function complete() {
+        Temp.findOne({_id: t.get('_id')}, function (err, doc) {
+          assert.ifError(err);
+          assert.equal(3, doc.get('nums').length);
+
+          var v = doc.get('nums').some(function (num) {
+            return num.valueOf() === 1;
+          });
+          assert.ok(v);
+
+          v = doc.get('nums').some(function (num) {
+            return num.valueOf() === 2;
+          });
+          assert.ok(v);
+
+          v = doc.get('nums').some(function (num) {
+            return num.valueOf() === 3;
+          });
+          assert.ok(v);
+          db.close(done);
+        });
+      }
+
+      function save(doc) {
+        saveQueue.push(doc);
+        if (saveQueue.length === totalDocs) {
+          saveQueue.forEach(function (doc) {
+            doc.save(function (err) {
+              assert.ifError(err);
+              --totalDocs || complete();
+            });
+          });
+        }
+      }
+
       t.save(function (err) {
         assert.ifError(err);
 
@@ -2884,41 +2920,6 @@ describe('Model', function () {
           doc.get('nums').push(2, 3);
           save(doc);
         });
-
-        function save(doc) {
-          saveQueue.push(doc);
-          if (saveQueue.length == totalDocs) {
-            saveQueue.forEach(function (doc) {
-              doc.save(function (err) {
-                assert.ifError(err);
-                --totalDocs || complete();
-              });
-            });
-          }
-        }
-
-        function complete() {
-          Temp.findOne({_id: t.get('_id')}, function (err, doc) {
-            assert.ifError(err);
-            assert.equal(3, doc.get('nums').length);
-
-            var v = doc.get('nums').some(function (num) {
-              return num.valueOf() == '1';
-            });
-            assert.ok(v);
-
-            v = doc.get('nums').some(function (num) {
-              return num.valueOf() == '2';
-            });
-            assert.ok(v);
-
-            v = doc.get('nums').some(function (num) {
-              return num.valueOf() == '3';
-            });
-            assert.ok(v);
-            db.close(done);
-          });
-        }
       });
     });
 
@@ -2935,6 +2936,43 @@ describe('Model', function () {
 
       var t = new StrList();
 
+      function complete() {
+        StrList.findOne({_id: t.get('_id')}, function (err, doc) {
+          db.close();
+          assert.ifError(err);
+
+          assert.equal(3, doc.get('strings').length);
+
+          var v = doc.get('strings').some(function (str) {
+            return str === 'a';
+          });
+          assert.ok(v);
+
+          v = doc.get('strings').some(function (str) {
+            return str === 'b';
+          });
+          assert.ok(v);
+
+          v = doc.get('strings').some(function (str) {
+            return str === 'c';
+          });
+          assert.ok(v);
+          done();
+        });
+      }
+
+      function save(doc) {
+        saveQueue.push(doc);
+        if (saveQueue.length === totalDocs) {
+          saveQueue.forEach(function (doc) {
+            doc.save(function (err) {
+              assert.ifError(err);
+              --totalDocs || complete();
+            });
+          });
+        }
+      }
+
       t.save(function (err) {
         assert.ifError(err);
 
@@ -2949,44 +2987,6 @@ describe('Model', function () {
           doc.get('strings').push('b', 'c');
           save(doc);
         });
-
-
-        function save(doc) {
-          saveQueue.push(doc);
-          if (saveQueue.length == totalDocs) {
-            saveQueue.forEach(function (doc) {
-              doc.save(function (err) {
-                assert.ifError(err);
-                --totalDocs || complete();
-              });
-            });
-          }
-        }
-
-        function complete() {
-          StrList.findOne({_id: t.get('_id')}, function (err, doc) {
-            db.close();
-            assert.ifError(err);
-
-            assert.equal(3, doc.get('strings').length);
-
-            var v = doc.get('strings').some(function (str) {
-              return str == 'a';
-            });
-            assert.ok(v);
-
-            v = doc.get('strings').some(function (str) {
-              return str == 'b';
-            });
-            assert.ok(v);
-
-            v = doc.get('strings').some(function (str) {
-              return str == 'c';
-            });
-            assert.ok(v);
-            done();
-          });
-        }
       });
     });
 
@@ -3003,6 +3003,44 @@ describe('Model', function () {
 
       var t = new BufList();
 
+      function complete() {
+        BufList.findOne({_id: t.get('_id')}, function (err, doc) {
+          db.close();
+          assert.ifError(err);
+
+          assert.equal(3, doc.get('buffers').length);
+
+          var v = doc.get('buffers').some(function (buf) {
+            return buf[0] === 140;
+          });
+          assert.ok(v);
+
+          v = doc.get('buffers').some(function (buf) {
+            return buf[0] === 141;
+          });
+          assert.ok(v);
+
+          v = doc.get('buffers').some(function (buf) {
+            return buf[0] === 142;
+          });
+          assert.ok(v);
+
+          done();
+        });
+      }
+
+      function save(doc) {
+        saveQueue.push(doc);
+        if (saveQueue.length === totalDocs) {
+          saveQueue.forEach(function (doc) {
+            doc.save(function (err) {
+              assert.ifError(err);
+              --totalDocs || complete();
+            });
+          });
+        }
+      }
+
       t.save(function (err) {
         assert.ifError(err);
 
@@ -3017,44 +3055,6 @@ describe('Model', function () {
           doc.get('buffers').push(new Buffer([141]), new Buffer([142]));
           save(doc);
         });
-
-        function save(doc) {
-          saveQueue.push(doc);
-          if (saveQueue.length == totalDocs) {
-            saveQueue.forEach(function (doc) {
-              doc.save(function (err) {
-                assert.ifError(err);
-                --totalDocs || complete();
-              });
-            });
-          }
-        }
-
-        function complete() {
-          BufList.findOne({_id: t.get('_id')}, function (err, doc) {
-            db.close();
-            assert.ifError(err);
-
-            assert.equal(3, doc.get('buffers').length);
-
-            var v = doc.get('buffers').some(function (buf) {
-              return buf[0] == 140;
-            });
-            assert.ok(v);
-
-            v = doc.get('buffers').some(function (buf) {
-              return buf[0] == 141;
-            });
-            assert.ok(v);
-
-            v = doc.get('buffers').some(function (buf) {
-              return buf[0] == 142;
-            });
-            assert.ok(v);
-
-            done();
-          });
-        }
       });
     });
 
diff --git a/test/model.update.test.js b/test/model.update.test.js
index 61a2fdead47..e44cf15966e 100644
--- a/test/model.update.test.js
+++ b/test/model.update.test.js
@@ -549,9 +549,17 @@ describe('model: update:', function () {
     var post = new BlogPost;
     post.set('meta.visitors', 5);
 
+    function complete() {
+      BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+        db.close();
+        assert.ifError(err);
+        assert.equal(9, doc.get('meta.visitors'));
+        done();
+      });
+    }
+
     post.save(function (err) {
       assert.ifError(err);
-
       for (var i = 0; i < 4; ++i) {
         BlogPost
         .update({_id: post._id}, {$inc: {'meta.visitors': 1}}, function (err) {
@@ -559,15 +567,6 @@ describe('model: update:', function () {
           --totalDocs || complete();
         });
       }
-
-      function complete() {
-        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
-          db.close();
-          assert.ifError(err);
-          assert.equal(9, doc.get('meta.visitors'));
-          done();
-        });
-      }
     });
   });
 
@@ -784,7 +783,7 @@ describe('model: update:', function () {
     before(function (done) {
       start.mongodVersion(function (err, version) {
         assert.ifError(err);
-        mongo24_or_greater = 2 < version[0] || (2 == version[0] && 4 <= version[1]);
+        mongo24_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 4);
         done();
       });
     });
@@ -882,7 +881,7 @@ describe('model: update:', function () {
     before(function (done) {
       start.mongodVersion(function (err, version) {
         assert.ifError(err);
-        mongo26_or_greater = 2 < version[0] || (2 == version[0] && 6 <= version[1]);
+        mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
         done();
       });
     });
@@ -1102,12 +1101,14 @@ describe('model: update:', function () {
 
       var s = new Schema({
         topping: {
-          type: String, validate: function () {
+          type: String,
+          validate: function () {
             return false;
           }
         },
         base: {
-          type: String, validate: function () {
+          type: String,
+          validate: function () {
             return true;
           }
         }
@@ -1119,8 +1120,7 @@ describe('model: update:', function () {
         assert.ok(!!error);
         assert.equal(1, Object.keys(error.errors).length);
         assert.equal('topping', Object.keys(error.errors)[0]);
-        assert.equal('Validator failed for path `topping` with value `bacon`',
-            error.errors['topping'].message);
+        assert.equal('Validator failed for path `topping` with value `bacon`', error.errors.topping.message);
 
         Breakfast.findOne({}, function (error, breakfast) {
           assert.ifError(error);
@@ -1152,10 +1152,8 @@ describe('model: update:', function () {
         assert.equal(2, Object.keys(error.errors).length);
         assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1);
         assert.ok(Object.keys(error.errors).indexOf('steak') !== -1);
-        assert.equal('Validator failed for path `eggs` with value `softboiled`',
-            error.errors['eggs'].message);
-        assert.equal('Path `steak` is required.',
-            error.errors['steak'].message);
+        assert.equal('Validator failed for path `eggs` with value `softboiled`', error.errors.eggs.message);
+        assert.equal('Path `steak` is required.', error.errors.steak.message);
         db.close();
         done();
       });
@@ -1176,23 +1174,19 @@ describe('model: update:', function () {
         assert.ok(!!error);
         assert.equal(1, Object.keys(error.errors).length);
         assert.equal('eggs', Object.keys(error.errors)[0]);
-        assert.equal('Path `eggs` (3) is less than minimum allowed value (4).',
-            error.errors['eggs'].message);
+        assert.equal('Path `eggs` (3) is less than minimum allowed value (4).', error.errors.eggs.message);
 
         Breakfast.update({}, {$set: {steak: 'tofu', eggs: 5, bacon: '3 strips'}}, updateOptions, function (error) {
           assert.ok(!!error);
           assert.equal(1, Object.keys(error.errors).length);
           assert.equal('steak', Object.keys(error.errors)[0]);
-          assert.equal('`tofu` is not a valid enum value for path `steak`.',
-              error.errors['steak']);
-
+          assert.equal('`tofu` is not a valid enum value for path `steak`.', error.errors.steak);
 
           Breakfast.update({}, {$set: {steak: 'sirloin', eggs: 6, bacon: 'none'}}, updateOptions, function (error) {
             assert.ok(!!error);
             assert.equal(1, Object.keys(error.errors).length);
             assert.equal('bacon', Object.keys(error.errors)[0]);
-            assert.equal('Path `bacon` is invalid (none).',
-                error.errors['bacon'].message);
+            assert.equal('Path `bacon` is invalid (none).', error.errors.bacon.message);
 
             db.close();
             done();
diff --git a/test/promise.test.js b/test/promise.test.js
index 2e7130714bc..7e9a2e3e36e 100644
--- a/test/promise.test.js
+++ b/test/promise.test.js
@@ -214,7 +214,7 @@ describe('Promise', function () {
   it('doesnt swallow exceptions (gh-3222)', function (done) {
     assert.throws(function () {
       new Promise.ES6(function () {
-        throw 'bacon';
+        throw new Error('bacon');
       });
     });
     done();
diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js
index 7ac9ccde3cb..6469a724490 100644
--- a/test/promise_provider.test.js
+++ b/test/promise_provider.test.js
@@ -80,7 +80,7 @@ describe('ES6 promises: ', function () {
         }).
         catch(function (err) {
           assert.ok(err);
-          assert.ok(err.errors['test']);
+          assert.ok(err.errors.test);
           done();
         });
     });
@@ -127,7 +127,7 @@ describe('ES6 promises: ', function () {
         }).
         catch(function (err) {
           assert.ok(err);
-          assert.ok(err.errors['test']);
+          assert.ok(err.errors.test);
           done();
         });
     });
@@ -216,7 +216,7 @@ describe('ES6 promises: ', function () {
         }).
         catch(function (err) {
           assert.ok(err);
-          assert.ok(err.errors['test']);
+          assert.ok(err.errors.test);
           done();
         });
     });
@@ -263,7 +263,7 @@ describe('ES6 promises: ', function () {
         }).
         catch(function (err) {
           assert.ok(err);
-          assert.ok(err.errors['test']);
+          assert.ok(err.errors.test);
           done();
         });
     });
@@ -394,7 +394,7 @@ describe('ES6 promises: ', function () {
         }).
         catch(function (err) {
           assert.ok(err);
-          assert.ok(err.errors['test']);
+          assert.ok(err.errors.test);
           done();
         });
     });
@@ -441,7 +441,7 @@ describe('ES6 promises: ', function () {
         }).
         catch(function (err) {
           assert.ok(err);
-          assert.ok(err.errors['test']);
+          assert.ok(err.errors.test);
           done();
         });
     });
diff --git a/test/query.test.js b/test/query.test.js
index b67595ef1e4..4f82e63543d 100644
--- a/test/query.test.js
+++ b/test/query.test.js
@@ -425,7 +425,7 @@ describe('Query', function () {
         var match = {gps: {$within: {$box: [[5, 25], [10, 30]]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps['$within'];
+          delete match.gps.$within;
         }
         assert.deepEqual(query._conditions, match);
         done();
@@ -436,7 +436,7 @@ describe('Query', function () {
         var match = {gps: {$within: {$box: [[5, 25], [10, 30]]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps['$within'];
+          delete match.gps.$within;
         }
         assert.deepEqual(query._conditions, match);
         done();
@@ -450,7 +450,7 @@ describe('Query', function () {
         var match = {gps: {$within: {$center: [[5, 25], 5]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps['$within'];
+          delete match.gps.$within;
         }
         assert.deepEqual(query._conditions, match);
         done();
@@ -464,7 +464,7 @@ describe('Query', function () {
         var match = {gps: {$within: {$centerSphere: [[5, 25], 5]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps['$within'];
+          delete match.gps.$within;
         }
         assert.deepEqual(query._conditions, match);
         done();
@@ -478,7 +478,7 @@ describe('Query', function () {
         var match = {gps: {$within: {$polygon: [{a: {x: 10, y: 20}, b: {x: 15, y: 25}, c: {x: 20, y: 20}}]}}};
         if (Query.use$geoWithin) {
           match.gps.$geoWithin = match.gps.$within;
-          delete match.gps['$within'];
+          delete match.gps.$within;
         }
         assert.deepEqual(query._conditions, match);
         done();
@@ -842,7 +842,7 @@ describe('Query', function () {
       assert.equal(2, Object.keys(q._mongooseOptions.populate).length);
       assert.deepEqual(o, q._mongooseOptions.populate['yellow.brick']);
       o.path = 'dirt';
-      assert.deepEqual(o, q._mongooseOptions.populate['dirt']);
+      assert.deepEqual(o, q._mongooseOptions.populate.dirt);
       done();
     });
   });
diff --git a/test/schema.select.test.js b/test/schema.select.test.js
index e2a532e0b03..e6e44aff89c 100644
--- a/test/schema.select.test.js
+++ b/test/schema.select.test.js
@@ -43,7 +43,7 @@ describe('schema select option', function () {
         if (pending === 1) {
           S.findOneAndRemove({_id: item._id}, cb);
         }
-        if (0 === pending) {
+        if (pending === 0) {
           done();
         }
       }
@@ -84,7 +84,7 @@ describe('schema select option', function () {
         assert.strictEqual(true, s.isSelected('docs.name'));
         assert.equal(s.name, 'the included');
 
-        if (0 === pending) {
+        if (pending === 0) {
           done();
         }
       }
diff --git a/test/schema.test.js b/test/schema.test.js
index dbd50a355ff..48949d55fbc 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -1505,7 +1505,7 @@ describe('schema', function () {
     var band = new Band({name: "Guns N' Roses"});
 
     assert.ok(band.validateSync());
-    assert.ok(band.validateSync().errors['guitarist']);
+    assert.ok(band.validateSync().errors.guitarist);
     band.guitarist = {name: 'Slash'};
     assert.ifError(band.validateSync());
 
diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js
index eeb5fcd01a4..67f4176a8f1 100644
--- a/test/schema.timestamps.test.js
+++ b/test/schema.timestamps.test.js
@@ -70,7 +70,7 @@ describe('schema options.timestamps', function () {
       cat.save(function (err, doc) {
         assert.ok(doc.createdAt);
         assert.ok(doc.updatedAt);
-        assert.ok(doc.createdAt.getTime() == doc.updatedAt.getTime());
+        assert.ok(doc.createdAt.getTime() === doc.updatedAt.getTime());
         done();
       });
     });
@@ -79,7 +79,7 @@ describe('schema options.timestamps', function () {
       Cat.findOneAndUpdate({name: 'notexistname'}, {$set: {}}, {upsert: true, 'new': true}, function (err, doc) {
         assert.ok(doc.createdAt);
         assert.ok(doc.updatedAt);
-        assert.ok(doc.createdAt.getTime() == doc.updatedAt.getTime());
+        assert.ok(doc.createdAt.getTime() === doc.updatedAt.getTime());
         done();
       });
     });
diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js
index b8334605a56..589e4e84143 100644
--- a/test/schema.validation.test.js
+++ b/test/schema.validation.test.js
@@ -86,7 +86,7 @@ describe('schema', function () {
       Test.path('state').doValidate('x', function (err) {
         assert.ok(err instanceof ValidatorError);
         assert.equal(err.message,
-          'enum validator failed for path `state`: test');
+            'enum validator failed for path `state`: test');
       });
 
       Test.path('state').doValidate('opening', function (err) {
@@ -447,7 +447,9 @@ describe('schema', function () {
           setTimeout(function () {
             executed++;
             fn(value === true);
-            if (2 === executed) done();
+            if (executed == 2) {
+              done();
+            }
           }, 5);
         }
 
@@ -471,23 +473,22 @@ describe('schema', function () {
           setTimeout(function () {
             executed++;
             fn(value === true);
-            if (2 === executed) done();
+            if (executed === 2) {
+              done();
+            }
           }, 5);
         }
 
         var Animal = new Schema({
           ferret: {
             type: Boolean,
-            validate: [
-                {
-                  'validator': validator,
-                  'msg': 'validator1'
-                },
-                {
-                  'validator': validator,
-                  'msg': 'validator2'
-                }
-            ]
+            validate: [{
+              validator: validator,
+              msg: 'validator1'
+            }, {
+              validator: validator,
+              msg: 'validator2'
+            }]
           }
         });
 
@@ -520,16 +521,13 @@ describe('schema', function () {
         var Animal = new Schema({
           ferret: {
             type: Boolean,
-            validate: [
-                {
-                  'validator': validator1,
-                  'msg': 'validator1'
-                },
-                {
-                  'validator': validator2,
-                  'msg': 'validator2'
-                }
-            ]
+            validate: [{
+              validator: validator1,
+              msg: 'validator1'
+            }, {
+              validator: validator2,
+              msg: 'validator2'
+            }]
           }
         });
 
@@ -540,6 +538,7 @@ describe('schema', function () {
 
       it('scope', function (done) {
         var called = false;
+
         function validator(value, fn) {
           assert.equal('b', this.a);
 
@@ -634,7 +633,9 @@ describe('schema', function () {
             x: {
               type: String,
               validate: [{
-                validator: function () { return false; },
+                validator: function () {
+                  return false;
+                },
                 msg: 'Error code {ERRORCODE}',
                 errorCode: 25
               }]
@@ -655,7 +656,9 @@ describe('schema', function () {
             x: {
               type: String,
               validate: [{
-                validator: function (value, fn) { fn(false, 'Custom message'); },
+                validator: function (value, fn) {
+                  fn(false, 'Custom message');
+                },
                 msg: 'Does not matter'
               }]
             }
@@ -677,6 +680,7 @@ describe('schema', function () {
           function validate() {
             return false;
           }
+
           var validator = [validate, '{PATH} failed validation ({VALUE})', 'customType'];
 
           var schema = new Schema({x: {type: [], validate: validator}});
@@ -695,8 +699,9 @@ describe('schema', function () {
           function validate() {
             return false;
           }
+
           var validator = [
-              {validator: validate, msg: '{PATH} failed validation ({VALUE})', type: 'customType'}
+            {validator: validate, msg: '{PATH} failed validation ({VALUE})', type: 'customType'}
           ];
           var schema = new Schema({x: {type: [], validate: validator}});
           var M = mongoose.model('custom-validator-' + random(), schema);
@@ -720,7 +725,7 @@ describe('schema', function () {
       user.validate(function (err) {
         assert.ok(err);
         assert.ok(user.errors);
-        assert.ok(user.errors['name']);
+        assert.ok(user.errors.name);
         user.name = 'bacon';
         user.validate(function (err) {
           assert.ok(!err);
@@ -746,10 +751,10 @@ describe('schema', function () {
           assert.ok(error);
           assert.ok(error.errors['foods.0']);
           assert.equal(error.errors['foods.0'].message,
-            '`tofu` is not a valid enum value for path `foods`.');
+              '`tofu` is not a valid enum value for path `foods`.');
           assert.ok(error.errors['foods.1']);
           assert.equal(error.errors['foods.1'].message,
-            '`waffles` is not a valid enum value for path `foods`.');
+              '`waffles` is not a valid enum value for path `foods`.');
           assert.ok(!error.errors['foods.2']);
 
           done();
@@ -781,7 +786,7 @@ describe('schema', function () {
           assert.ok(error);
           assert.ok(error.errors['votes.0.vote']);
           assert.equal(error.errors['votes.0.vote'].message,
-            '`terrible` is not a valid enum value for path `vote`.');
+              '`terrible` is not a valid enum value for path `vote`.');
 
           done();
         });
@@ -891,7 +896,7 @@ describe('schema', function () {
       bad.validate(function (error) {
         assert.ok(error);
         var errorMessage = 'CastError: Cast to Object failed for value ' +
-          '"waffles" at path "foods"';
+            '"waffles" at path "foods"';
         assert.ok(error.toString().indexOf(errorMessage) !== -1, error.toString());
         done();
       });
@@ -935,8 +940,8 @@ describe('schema', function () {
 
       assert.ok(error);
       assert.equal(Object.keys(error.errors).length, 1);
-      assert.ok(error.errors['other']);
-      assert.ok(!error.errors['description']);
+      assert.ok(error.errors.other);
+      assert.ok(!error.errors.description);
       done();
     });
 
@@ -955,7 +960,11 @@ describe('schema', function () {
 
     it('sets path correctly when setter throws exception (gh-2832)', function (done) {
       var breakfast = new Schema({
-        description: {type: String, set: function () { throw new Error('oops'); }}
+        description: {
+          type: String, set: function () {
+            throw new Error('oops');
+          }
+        }
       });
 
       var Breakfast = mongoose.model('gh2832', breakfast, 'gh2832');
@@ -963,8 +972,8 @@ describe('schema', function () {
         assert.ok(error);
         var errorMessage = 'ValidationError: CastError: Cast to String failed for value "undefined" at path "description"';
         assert.equal(errorMessage, error.toString());
-        assert.ok(error.errors['description']);
-        assert.equal(error.errors['description'].reason.toString(), 'Error: oops');
+        assert.ok(error.errors.description);
+        assert.equal(error.errors.description.reason.toString(), 'Error: oops');
         done();
       });
     });
@@ -991,13 +1000,21 @@ describe('schema', function () {
     });
 
     it('returns correct kind for user defined custom validators (gh-2885)', function (done) {
-      var s = mongoose.Schema({n: {type: String, validate: {validator: function () { return false; }}, msg: 'fail'}});
+      var s = mongoose.Schema({
+        n: {
+          type: String, validate: {
+            validator: function () {
+              return false;
+            }
+          }, msg: 'fail'
+        }
+      });
       var M = mongoose.model('gh2885', s);
 
       var m = new M({n: 'test'});
       m.validate(function (error) {
         assert.ok(error);
-        assert.equal(error.errors['n'].kind, 'user defined');
+        assert.equal(error.errors.n.kind, 'user defined');
         done();
       });
     });
@@ -1009,14 +1026,18 @@ describe('schema', function () {
       var m = new M({n: 'test'});
       m.validate(function (error) {
         assert.ok(error);
-        assert.equal(error.errors['n'].kind, 'enum');
+        assert.equal(error.errors.n.kind, 'enum');
         done();
       });
     });
 
     it('skips conditional required (gh-3539)', function (done) {
       var s = mongoose.Schema({
-        n: {type: Number, required: function () { return false; }, min: 0}
+        n: {
+          type: Number, required: function () {
+            return false;
+          }, min: 0
+        }
       });
       var M = mongoose.model('gh3539', s);
 
diff --git a/test/shard.test.js b/test/shard.test.js
index 64be3c20a24..c9a3e404dcf 100644
--- a/test/shard.test.js
+++ b/test/shard.test.js
@@ -82,7 +82,7 @@ describe('shard', function () {
               version = info.version.split('.').map(function (n) {
                 return parseInt(n, 10);
               });
-              greaterThan20x = 2 < version[0] || 2 == version[0] && 0 < version[0];
+              greaterThan20x = version[0] > 2 || version[0] === 2 && version[0] > 0;
               done();
             });
           });
diff --git a/test/types.array.test.js b/test/types.array.test.js
index d70af124394..f6b72516d9d 100644
--- a/test/types.array.test.js
+++ b/test/types.array.test.js
@@ -83,12 +83,6 @@ describe('types array', function () {
 
       var pending = 3;
 
-      [tobi, loki, jane].forEach(function (pet) {
-        pet.save(function () {
-          --pending || cb();
-        });
-      });
-
       function cb() {
         Pet.find({}, function (err) {
           assert.ifError(err);
@@ -108,6 +102,12 @@ describe('types array', function () {
           });
         });
       }
+
+      [tobi, loki, jane].forEach(function (pet) {
+        pet.save(function () {
+          --pending || cb();
+        });
+      });
     });
   });
 
diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js
index ada0a50f42d..65a02d50c20 100644
--- a/test/types.documentarray.test.js
+++ b/test/types.documentarray.test.js
@@ -154,8 +154,8 @@ describe('types.documentarray', function () {
     sub4 = new Subdocument();
     sub4.title = 'rock-n-roll';
 
-    a = new MongooseDocumentArray([sub4]),
-        threw = false;
+    a = new MongooseDocumentArray([sub4]);
+    threw = false;
     try {
       a.id('i better not throw');
     } catch (err) {
diff --git a/test/utils.test.js b/test/utils.test.js
index 647b88dd45e..9b66a1d3b17 100644
--- a/test/utils.test.js
+++ b/test/utils.test.js
@@ -35,21 +35,21 @@ describe('utils', function () {
     it('should detect a path as required if it has been required', function (done) {
       var ar = new ActiveRoster();
       ar.require('hello');
-      assert.equal(ar.paths['hello'], 'require');
+      assert.equal(ar.paths.hello, 'require');
       done();
     });
 
     it('should detect a path as inited if it has been inited', function (done) {
       var ar = new ActiveRoster();
       ar.init('hello');
-      assert.equal(ar.paths['hello'], 'init');
+      assert.equal(ar.paths.hello, 'init');
       done();
     });
 
     it('should detect a path as modified', function (done) {
       var ar = new ActiveRoster();
       ar.modify('hello');
-      assert.equal(ar.paths['hello'], 'modify');
+      assert.equal(ar.paths.hello, 'modify');
       done();
     });
 
diff --git a/test/versioning.test.js b/test/versioning.test.js
index 7f26b07157f..bc76dfcd673 100644
--- a/test/versioning.test.js
+++ b/test/versioning.test.js
@@ -91,111 +91,113 @@ describe('versioning', function () {
     ];
     doc.arr = [['2d']];
 
-    doc.save(function (err) {
-      var a, b;
-      assert.ifError(err);
-      // test 2 concurrent ops
-      V.findById(doc, function (err, _a) {
-        assert.ifError(err);
-        a = _a;
-        if (a && b) {
-          test1(a, b);
-        }
-      });
-      V.findById(doc, function (err, _b) {
-        assert.ifError(err);
-        b = _b;
-        if (a && b) {
-          test1(a, b);
+    function save(a, b, cb) {
+      var e;
+      function lookup() {
+        var a1, b1;
+        V.findById(a, function (err, a_) {
+          if (err && !e) {
+            e = err;
+          }
+          a1 = a_;
+          if (a1 && b1) {
+            cb(e, a1, b1);
+          }
+        });
+        V.findById(b, function (err, b_) {
+          if (err && !e) {
+            e = err;
+          }
+          b1 = b_;
+          if (a1 && b1) {
+            cb(e, a1, b1);
+          }
+        });
+      }
+      // make sure that a saves before b
+      a.save(function (err) {
+        if (err) {
+          e = err;
         }
+        b.save(function (err) {
+          if (err) {
+            e = err;
+          }
+          lookup();
+        });
       });
-    });
+    }
 
-    function test1(a, b) {
-      a.meta.numbers.push(9);
-      b.meta.numbers.push(8);
-      save(a, b, test2);
+    function test15(err, a) {
+      assert.equal(a._doc.__v, 13, 'version should not be incremented for non-versioned sub-document fields');
+      done();
     }
 
-    function test2(err, a, b) {
+    function test14(err, a, b) {
       assert.ifError(err);
-      assert.equal(a.meta.numbers.length, 5);
-      assert.equal(a._doc.__v, 2);
-      a.meta.numbers.pull(10);
-      b.meta.numbers.push(20);
-      save(a, b, test3);
+      assert.equal(a._doc.__v, 13, 'version should not be incremented for non-versioned fields');
+      a.comments[0].dontVersionMeEither.push('value1');
+      b.comments[0].dontVersionMeEither.push('value2');
+      save(a, b, test15);
     }
 
-    function test3(err, a, b) {
+    function test13(err, a, b) {
       assert.ifError(err);
-      assert.equal(a.meta.numbers.length, 5);
-      assert.equal(b.meta.numbers.length, 5);
-      assert.equal(-1, a.meta.numbers.indexOf(10));
-      assert.ok(~a.meta.numbers.indexOf(20));
-      assert.equal(a._doc.__v, 4);
-
-      a.numbers.pull(3, 20);
-
-      // should fail
-      b.set('numbers.2', 100);
-      save(a, b, test4);
+      a.dontVersionMe.push('value1');
+      b.dontVersionMe.push('value2');
+      save(a, b, test14);
     }
 
-    function test4(err, a, b) {
-      assert.ok(/No matching document/.test(err), err);
-      assert.equal(a._doc.__v, 5);
-      a.set('arr.0.0', 'updated');
+    function test12(err, a, b) {
+      assert.ok(err instanceof VersionError);
+      assert.ok(/No matching document/.test(err), 'changes to b should not be applied');
+      assert.equal(5, a.comments.length);
+
+      a.comments.addToSet({title: 'aven'});
+      a.comments.addToSet({title: 'avengers'});
       var d = a.$__delta();
-      assert.equal(a._doc.__v, d[0].__v, 'version should be added to where clause');
-      assert.ok(!('$inc' in d[1]));
-      save(a, b, test5);
-    }
 
-    function test5(err, a, b) {
-      assert.ifError(err);
-      assert.equal('updated', a.arr[0][0]);
-      assert.equal(a._doc.__v, 5);
-      a.set('arr.0', 'not an array');
-      // should overwrite a's changes, last write wins
-      b.arr.pull(10);
-      b.arr.addToSet('using set');
-      save(a, b, test6);
+      assert.equal(undefined, d[0].__v, 'version should not be included in where clause');
+      assert.ok(!d[1].$set);
+      assert.ok(d[1].$addToSet);
+      assert.ok(d[1].$addToSet.comments);
+
+      a.comments.$shift();
+      d = a.$__delta();
+      assert.equal(12, d[0].__v, 'version should be included in where clause');
+      assert.ok(d[1].$set, 'two differing atomic ops on same path should create a $set');
+      assert.ok(d[1].$inc, 'a $set of an array should trigger versioning');
+      assert.ok(!d[1].$addToSet);
+      save(a, b, test13);
     }
 
-    function test6(err, a, b) {
+    function test11(err, a, b) {
       assert.ifError(err);
-      assert.equal(a.arr.length, 2);
-      assert.equal('updated', a.arr[0][0]);
-      assert.equal('using set', a.arr[1]);
-      assert.equal(a._doc.__v, 6);
-      b.set('arr.0', 'not an array');
-      // should overwrite b's changes, last write wins
-      // force a $set
-      a.arr.pull('using set');
-      a.arr.push('woot', 'woot2');
-      a.arr.$pop();
-      save(a, b, test7);
-    }
+      assert.equal(a._doc.__v, 11);
+      assert.equal(6, a.mixed.arr.length);
+      assert.equal(1, a.mixed.arr[4].x);
+      assert.equal('woot', a.mixed.arr[5]);
+      assert.equal(10, a.mixed.arr[3][0]);
 
-    function test7(err, a, b) {
-      assert.ok(/No matching document/.test(err), 'changes to b should not be applied');
-      assert.equal(a.arr.length, 2);
-      assert.equal('updated', a.arr[0][0]);
-      assert.equal('woot', a.arr[1]);
-      assert.equal(a._doc.__v, 7);
-      a.meta.nested.$pop();
-      b.meta.nested.$pop();
-      save(a, b, test8);
+      a.comments.addToSet({title: 'monkey'});
+      b.markModified('comments');
+
+      var d = b.$__delta();
+      assert.ok(d[1].$inc, 'a $set of an array should trigger versioning');
+
+      save(a, b, test12);
     }
 
-    function test8(err, a, b) {
-      assert.ok(/No matching document/.test(err), 'changes to b should not be applied');
-      assert.equal(a.meta.nested.length, 3);
-      assert.equal(a._doc.__v, 8);
-      a.meta.nested.push({title: 'the'});
-      a.meta.nested.push({title: 'killing'});
-      b.meta.nested.push({title: 'biutiful'});
-      save(a, b, test9);
+    function test10(err, a, b) {
+      assert.ifError(err);
+      assert.equal('two', b.meta.nested[2].title);
+      assert.equal('zero', b.meta.nested[0].title);
+      assert.equal('sub one', b.meta.nested[1].comments[0].title);
+      assert.equal(a._doc.__v, 10);
+      assert.equal(3, a.mixed.arr.length);
+      a.mixed.arr.push([10], {x: 1}, 'woot');
+      a.markModified('mixed.arr');
+      save(a, b, test11);
     }
 
     function test9(err, a, b) {
@@ -214,114 +216,112 @@ describe('versioning', function () {
       });
     }
 
-    function test10(err, a, b) {
-      assert.ifError(err);
-      assert.equal('two', b.meta.nested[2].title);
-      assert.equal('zero', b.meta.nested[0].title);
-      assert.equal('sub one', b.meta.nested[1].comments[0].title);
-      assert.equal(a._doc.__v, 10);
-      assert.equal(3, a.mixed.arr.length);
-      a.mixed.arr.push([10], {x: 1}, 'woot');
-      a.markModified('mixed.arr');
-      save(a, b, test11);
+    function test8(err, a, b) {
+      assert.ok(/No matching document/.test(err), 'changes to b should not be applied');
+      assert.equal(a.meta.nested.length, 3);
+      assert.equal(a._doc.__v, 8);
+      a.meta.nested.push({title: 'the'});
+      a.meta.nested.push({title: 'killing'});
+      b.meta.nested.push({title: 'biutiful'});
+      save(a, b, test9);
     }
 
-    function test11(err, a, b) {
-      assert.ifError(err);
-      assert.equal(a._doc.__v, 11);
-      assert.equal(6, a.mixed.arr.length);
-      assert.equal(1, a.mixed.arr[4].x);
-      assert.equal('woot', a.mixed.arr[5]);
-      assert.equal(10, a.mixed.arr[3][0]);
-
-      a.comments.addToSet({title: 'monkey'});
-      b.markModified('comments');
-
-      var d = b.$__delta();
-      assert.ok(d[1].$inc, 'a $set of an array should trigger versioning');
+    function test7(err, a, b) {
+      assert.ok(/No matching document/.test(err), 'changes to b should not be applied');
+      assert.equal(a.arr.length, 2);
+      assert.equal('updated', a.arr[0][0]);
+      assert.equal('woot', a.arr[1]);
+      assert.equal(a._doc.__v, 7);
+      a.meta.nested.$pop();
+      b.meta.nested.$pop();
+      save(a, b, test8);
+    }
 
-      save(a, b, test12);
+    function test6(err, a, b) {
+      assert.ifError(err);
+      assert.equal(a.arr.length, 2);
+      assert.equal('updated', a.arr[0][0]);
+      assert.equal('using set', a.arr[1]);
+      assert.equal(a._doc.__v, 6);
+      b.set('arr.0', 'not an array');
+      // should overwrite b's changes, last write wins
+      // force a $set
+      a.arr.pull('using set');
+      a.arr.push('woot', 'woot2');
+      a.arr.$pop();
+      save(a, b, test7);
     }
 
-    function test12(err, a, b) {
-      assert.ok(err instanceof VersionError);
-      assert.ok(/No matching document/.test(err), 'changes to b should not be applied');
-      assert.equal(5, a.comments.length);
+    function test5(err, a, b) {
+      assert.ifError(err);
+      assert.equal('updated', a.arr[0][0]);
+      assert.equal(a._doc.__v, 5);
+      a.set('arr.0', 'not an array');
+      // should overwrite a's changes, last write wins
+      b.arr.pull(10);
+      b.arr.addToSet('using set');
+      save(a, b, test6);
+    }
 
-      a.comments.addToSet({title: 'aven'});
-      a.comments.addToSet({title: 'avengers'});
+    function test4(err, a, b) {
+      assert.ok(/No matching document/.test(err), err);
+      assert.equal(a._doc.__v, 5);
+      a.set('arr.0.0', 'updated');
       var d = a.$__delta();
-
-      assert.equal(undefined, d[0].__v, 'version should not be included in where clause');
-      assert.ok(!d[1].$set);
-      assert.ok(d[1].$addToSet);
-      assert.ok(d[1].$addToSet.comments);
-
-      a.comments.$shift();
-      d = a.$__delta();
-      assert.equal(12, d[0].__v, 'version should be included in where clause');
-      assert.ok(d[1].$set, 'two differing atomic ops on same path should create a $set');
-      assert.ok(d[1].$inc, 'a $set of an array should trigger versioning');
-      assert.ok(!d[1].$addToSet);
-      save(a, b, test13);
+      assert.equal(a._doc.__v, d[0].__v, 'version should be added to where clause');
+      assert.ok(!('$inc' in d[1]));
+      save(a, b, test5);
     }
 
-    function test13(err, a, b) {
+    function test3(err, a, b) {
       assert.ifError(err);
-      a.dontVersionMe.push('value1');
-      b.dontVersionMe.push('value2');
-      save(a, b, test14);
+      assert.equal(a.meta.numbers.length, 5);
+      assert.equal(b.meta.numbers.length, 5);
+      assert.equal(-1, a.meta.numbers.indexOf(10));
+      assert.ok(~a.meta.numbers.indexOf(20));
+      assert.equal(a._doc.__v, 4);
+
+      a.numbers.pull(3, 20);
+
+      // should fail
+      b.set('numbers.2', 100);
+      save(a, b, test4);
     }
 
-    function test14(err, a, b) {
+    function test2(err, a, b) {
       assert.ifError(err);
-      assert.equal(a._doc.__v, 13, 'version should not be incremented for non-versioned fields');
-      a.comments[0].dontVersionMeEither.push('value1');
-      b.comments[0].dontVersionMeEither.push('value2');
-      save(a, b, test15);
+      assert.equal(a.meta.numbers.length, 5);
+      assert.equal(a._doc.__v, 2);
+      a.meta.numbers.pull(10);
+      b.meta.numbers.push(20);
+      save(a, b, test3);
     }
 
-    function test15(err, a) {
-      assert.equal(a._doc.__v, 13, 'version should not be incremented for non-versioned sub-document fields');
-      done();
+    function test1(a, b) {
+      a.meta.numbers.push(9);
+      b.meta.numbers.push(8);
+      save(a, b, test2);
     }
 
-    function save(a, b, cb) {
-      var e;
-      // make sure that a saves before b
-      a.save(function (err) {
-        if (err) {
-          e = err;
+    doc.save(function (err) {
+      var a, b;
+      assert.ifError(err);
+      // test 2 concurrent ops
+      V.findById(doc, function (err, _a) {
+        assert.ifError(err);
+        a = _a;
+        if (a && b) {
+          test1(a, b);
         }
-        b.save(function (err) {
-          if (err) {
-            e = err;
-          }
-          lookup();
-        });
       });
-      function lookup() {
-        var a1, b1;
-        V.findById(a, function (err, a_) {
-          if (err && !e) {
-            e = err;
-          }
-          a1 = a_;
-          if (a1 && b1) {
-            cb(e, a1, b1);
-          }
-        });
-        V.findById(b, function (err, b_) {
-          if (err && !e) {
-            e = err;
-          }
-          b1 = b_;
-          if (a1 && b1) {
-            cb(e, a1, b1);
-          }
-        });
-      }
-    }
+      V.findById(doc, function (err, _b) {
+        assert.ifError(err);
+        b = _b;
+        if (a && b) {
+          test1(a, b);
+        }
+      });
+    });
   });
 
   it('versioning without version key', function (done) {
@@ -336,8 +336,6 @@ describe('versioning', function () {
       {title: 'hi', date: new Date}
     ];
 
-    doc.save(test);
-
     function test(err) {
       assert.ifError(err);
       // test getting docs back from db missing version key
@@ -349,6 +347,8 @@ describe('versioning', function () {
         done();
       });
     }
+
+    doc.save(test);
   });
 
   it('version works with strict docs', function (done) {
diff --git a/website.js b/website.js
index 76f4cace21f..1ca646cbbb6 100644
--- a/website.js
+++ b/website.js
@@ -9,6 +9,32 @@ var klass = require('./docs/helpers/klass');
 // add custom jade filters
 require('./docs/helpers/filters')(jade);
 
+function getVersion() {
+  var hist = fs.readFileSync('./History.md', 'utf8').replace(/\r/g, '\n').split('\n');
+  for (var i = 0; i < hist.length; ++i) {
+    var line = (hist[i] || '').trim();
+    if (!line) {
+      continue;
+    }
+    var match = /^\s*([^\s]+)\s/.exec(line);
+    if (match && match[1]) {
+      return match[1];
+    }
+  }
+  throw new Error('no match found');
+}
+
+function getUnstable(ver) {
+  ver = ver.replace('-pre');
+  var spl = ver.split('.');
+  spl = spl.map(function (i) {
+    return parseInt(i, 10);
+  });
+  spl[1]++;
+  spl[2] = 'x';
+  return spl.join('.');
+}
+
 // use last release
 package.version = getVersion();
 package.unstable = getUnstable(package.version);
@@ -16,26 +42,6 @@ package.unstable = getUnstable(package.version);
 var filemap = require('./docs/source');
 var files = Object.keys(filemap);
 
-files.forEach(function (file) {
-  var filename = __dirname + '/' + file;
-  jadeify(filename, filemap[file]);
-
-  if ('--watch' == process.argv[2]) {
-    fs.watchFile(filename, {interval: 1000}, function (cur, prev) {
-      if (cur.mtime > prev.mtime) {
-        jadeify(filename, filemap[file]);
-      }
-    });
-  }
-});
-
-var acquit = require('./docs/source/acquit');
-var acquitFiles = Object.keys(acquit);
-acquitFiles.forEach(function (file) {
-  var filename = __dirname + '/docs/acquit.jade';
-  jadeify(filename, acquit[file], __dirname + '/docs/' + file);
-});
-
 function jadeify(filename, options, newfile) {
   options = options || {};
   options.package = package;
@@ -45,41 +51,37 @@ function jadeify(filename, options, newfile) {
   options.klass = klass;
   jade.renderFile(filename, options, function (err, str) {
     if (err) {
-      return console.error(err.stack);
+      console.error(err.stack);
+      return;
     }
 
     newfile = newfile || filename.replace('.jade', '.html');
     fs.writeFile(newfile, str, function (err) {
       if (err) {
-        return console.error('could not write', err.stack);
+        console.error('could not write', err.stack);
+      } else {
+        console.log('%s : rendered ', new Date, newfile);
       }
-      console.log('%s : rendered ', new Date, newfile);
     });
   });
 }
 
-function getVersion() {
-  var hist = fs.readFileSync('./History.md', 'utf8').replace(/\r/g, '\n').split('\n');
-  for (var i = 0; i < hist.length; ++i) {
-    var line = (hist[i] || '').trim();
-    if (!line) {
-      continue;
-    }
-    var match = /^\s*([^\s]+)\s/.exec(line);
-    if (match && match[1]) {
-      return match[1];
-    }
+files.forEach(function (file) {
+  var filename = __dirname + '/' + file;
+  jadeify(filename, filemap[file]);
+
+  if ('--watch' === process.argv[2]) {
+    fs.watchFile(filename, {interval: 1000}, function (cur, prev) {
+      if (cur.mtime > prev.mtime) {
+        jadeify(filename, filemap[file]);
+      }
+    });
   }
-  throw new Error('no match found');
-}
+});
 
-function getUnstable(ver) {
-  ver = ver.replace('-pre');
-  var spl = ver.split('.');
-  spl = spl.map(function (i) {
-    return parseInt(i, 10);
-  });
-  spl[1]++;
-  spl[2] = 'x';
-  return spl.join('.');
-}
+var acquit = require('./docs/source/acquit');
+var acquitFiles = Object.keys(acquit);
+acquitFiles.forEach(function (file) {
+  var filename = __dirname + '/docs/acquit.jade';
+  jadeify(filename, acquit[file], __dirname + '/docs/' + file);
+});

From e60b1a9bc84bd0e763e0dce17856e154568bb08b Mon Sep 17 00:00:00 2001
From: CTAPbIuMABP 
Date: Sun, 31 Jan 2016 21:58:34 +0800
Subject: [PATCH 0238/2240] more strict lint

---
 benchmarks/mem.js                             |   2 +-
 benchmarks/populate.js                        |  27 ++-
 benchmarks/populationHeavyLoad.js             |  49 ++--
 lib/ES6Promise.js                             |   4 +-
 lib/aggregate.js                              | 120 ++++-----
 lib/cast.js                                   |  26 +-
 lib/collection.js                             |  13 +-
 lib/connection.js                             |  26 +-
 lib/document.js                               |  81 +++----
 lib/drivers/node-mongodb-native/collection.js |  37 ++-
 lib/drivers/node-mongodb-native/connection.js |   2 +-
 lib/error/browserMissingSchema.js             |   3 +-
 lib/index.js                                  |   4 +-
 lib/model.js                                  | 134 +++++-----
 lib/query.js                                  |  97 ++++----
 lib/querystream.js                            |   4 +-
 lib/schema.js                                 |  24 +-
 lib/schema/array.js                           |   4 +-
 lib/schema/boolean.js                         |   4 +-
 lib/schema/buffer.js                          |   4 +-
 lib/schema/date.js                            |   4 +-
 lib/schema/documentarray.js                   |   2 +-
 lib/schema/mixed.js                           |   4 +-
 lib/schema/number.js                          |  11 +-
 lib/schema/string.js                          |   6 +-
 lib/schematype.js                             |  38 +--
 lib/types/array.js                            |  16 +-
 lib/types/buffer.js                           |   2 +-
 lib/types/documentarray.js                    |  18 +-
 lib/types/embedded.js                         |  44 ++--
 lib/utils.js                                  |  10 +-
 static.js                                     |   2 +-
 test/aggregate.test.js                        | 228 ++++++++++--------
 test/browser/schema.validation.test_.js       |  12 +-
 test/cast.test.js                             |   6 +-
 test/collection.capped.test.js                |  17 +-
 test/collection.test.js                       |   7 +-
 test/colors.js                                |  36 +--
 test/connection.auth.test.js                  |   1 -
 test/connection.reconnect.test.js             |  17 +-
 test/crash.test.js                            |   1 -
 test/document.hooks.test.js                   | 108 ++++-----
 test/document.isselected.test.js              |   1 -
 test/document.modified.test.js                |  70 +++---
 test/document.strict.test.js                  |   2 +-
 test/document.test.js                         |  18 +-
 test/model.create.test.js                     |   2 +-
 test/model.discriminator.querying.test.js     |   2 +-
 test/model.findOneAndUpdate.test.js           |   8 +-
 test/model.hydrate.test.js                    |   6 +-
 test/model.indexes.test.js                    |   2 +-
 test/model.mapreduce.test.js                  |   7 +-
 test/model.populate.setting.test.js           |   4 +-
 test/model.populate.test.js                   |   6 +-
 test/model.stream.test.js                     |  12 +-
 test/model.test.js                            |   4 +-
 test/model.update.test.js                     |  20 +-
 test/object.create.null.test.js               |   2 -
 test/promise.test.js                          |   1 -
 test/promise_provider.test.js                 |   6 -
 test/query.test.js                            |  16 +-
 test/query.toconstructor.test.js              |   4 +-
 test/schema.documentarray.test.js             |   9 +-
 test/schema.mixed.test.js                     |   4 +-
 test/schema.test.js                           |  60 ++---
 test/schema.validation.test.js                |   2 +-
 test/types.array.test.js                      |   2 +-
 test/types.documentarray.test.js              |  12 +-
 test/versioning.test.js                       |   6 +-
 website.js                                    |   2 +-
 70 files changed, 795 insertions(+), 750 deletions(-)

diff --git a/benchmarks/mem.js b/benchmarks/mem.js
index 12e20e56b03..87147c4a872 100644
--- a/benchmarks/mem.js
+++ b/benchmarks/mem.js
@@ -101,7 +101,7 @@ var i = total;
 mongoose.connection.on('open', function () {
   mongoose.connection.db.dropDatabase(function () {
     (function cycle() {
-      if (0 === i--) {
+      if (i-- === 0) {
         return done();
       }
       var a = new A({
diff --git a/benchmarks/populate.js b/benchmarks/populate.js
index 5ad8f49caf0..6dd3bb7499b 100644
--- a/benchmarks/populate.js
+++ b/benchmarks/populate.js
@@ -1,4 +1,3 @@
-
 var mongoose = require('../');
 var Schema = mongoose.Schema;
 var docs = process.argv[2] ? process.argv[2] | 0 : 100;
@@ -19,10 +18,14 @@ var start;
 var count = 0;
 
 mongoose.connect('localhost', 'benchmark-populate', function (err) {
-  if (err) return done(err);
+  if (err) {
+    return done(err);
+  }
 
   A.create({name: 'wooooooooooooooooooooooooooooooooooooooooot'}, function (err, a) {
-    if (err) return done(err);
+    if (err) {
+      return done(err);
+    }
 
     var pending = docs;
     for (var i = 0; i < pending; ++i) {
@@ -31,9 +34,11 @@ mongoose.connect('localhost', 'benchmark-populate', function (err) {
         a: a,
         nested: [{a: a}, {a: a}, {a: a}, {a: a}, {a: a}, {a: a}]
       }).save(function (err) {
-        if (err) return done(err);
+        if (err) {
+          return done(err);
+        }
         --pending;
-        if (0 === pending) {
+        if (pending === 0) {
           // console.log('inserted %d docs. beginning test ...', docs);
           start = Date.now();
           test();
@@ -50,20 +55,26 @@ function test() {
   B.findOne().populate('as').populate('a').populate('nested.a').exec(handle);
 
   function handle(err) {
-    if (err) throw err;
+    if (err) {
+      throw err;
+    }
     count++;
 
     if (Date.now() - start > 1000 * 20) {
       return done();
     }
 
-    if (0 === --pending) return test();
+    if (--pending === 0) {
+      return test();
+    }
   }
 }
 
 
 function done(err) {
-  if (err) console.error(err.stack);
+  if (err) {
+    console.error(err.stack);
+  }
 
   mongoose.connection.db.dropDatabase(function () {
     mongoose.disconnect();
diff --git a/benchmarks/populationHeavyLoad.js b/benchmarks/populationHeavyLoad.js
index d6630bcc641..cb05ba3e6b0 100644
--- a/benchmarks/populationHeavyLoad.js
+++ b/benchmarks/populationHeavyLoad.js
@@ -1,4 +1,3 @@
-/* eslint no-unused-vars: 1 */
 var tbd = require('tbd');
 var mongoose = require('../');
 var Schema = mongoose.Schema;
@@ -26,7 +25,7 @@ function createRandomWord(len) {
   return word;
 }
 
-var Medication = mongoose.model('Medication', Schema({
+mongoose.model('Medication', Schema({
   catCode: {type: String},
   concentration: {type: String},
   medicationName: {type: String, required: true},
@@ -42,7 +41,7 @@ load.Medication = tbd.from({
   qty: 10
 }).make(dicCnt);
 
-var Prescription = mongoose.model('Prescription', Schema({
+mongoose.model('Prescription', Schema({
   age: {type: Number},
   city: {type: String},
   clientID: {type: String, required: true},
@@ -86,7 +85,7 @@ load.Prescription = tbd.from({
   tel: '{ type: String }'
 }).make(dicCnt);
 
-var Observation = mongoose.model('Observation', Schema({
+mongoose.model('Observation', Schema({
   observationCode: {type: Number},
   observationDesc: {type: String},
   observationGroup: {
@@ -100,7 +99,7 @@ load.Observation = tbd.from({
   observationGroup: '{ type: String}'
 }).make(dicCnt);
 
-var Heart = mongoose.model('Heart', Schema({
+mongoose.model('Heart', Schema({
   abdominalAscites: {type: String},
   abdominalCondition: {type: String},
   abdominalLocation: {type: String},
@@ -126,7 +125,7 @@ load.Heart = tbd.from({
   sounds: '{ type: String }'
 }).make(dicCnt);
 
-var PereferialPulse = mongoose.model('PereferialPulse', Schema({
+mongoose.model('PereferialPulse', Schema({
   leftDP: {type: String},
   leftFemoral: {type: String},
   leftPopliteal: {type: String},
@@ -150,7 +149,7 @@ load.PereferialPulse = tbd.from({
   rigthPopliteal: '{ type: String}'
 }).make(dicCnt);
 
-var Treatment = mongoose.model('Treatment', Schema({
+mongoose.model('Treatment', Schema({
   notes: {type: String},
   treatmentCode: {type: String},
   treatmentName: {
@@ -164,7 +163,7 @@ load.Treatment = tbd.from({
   treatmentName: '{ type: String, required: true}'
 }).make(dicCnt);
 
-var VitalSign = mongoose.model('VitalSign', Schema({
+mongoose.model('VitalSign', Schema({
   O2: {type: String},
   diastole: {type: String},
   heartSounds: {type: String},
@@ -208,7 +207,7 @@ load.VitalSign = tbd.from({
   weight: '{ type: String}'
 }).make(dicCnt);
 
-var FluidsProgram = mongoose.model('FluidsProgram', Schema({
+mongoose.model('FluidsProgram', Schema({
   name: String
 }));
 
@@ -216,7 +215,7 @@ load.FluidsProgram = tbd.from({
   name: 'String'
 }).make(dicCnt);
 
-var Allergy = mongoose.model('Allergy', Schema({
+mongoose.model('Allergy', Schema({
   allergy: {type: String, required: true},
   notes: {
     type: String
@@ -228,7 +227,7 @@ load.Allergy = tbd.from({
   notes: '{ type: String }'
 }).make(dicCnt);
 
-var Head = mongoose.model('Head', Schema({
+mongoose.model('Head', Schema({
   ears: {type: String},
   neckMurmur: {type: String},
   normalEarRight: {type: Boolean},
@@ -268,7 +267,7 @@ load.Head = tbd.from({
   venousCongestion: false
 }).make(dicCnt);
 
-var Sckeletal = mongoose.model('Sckeletal', Schema({
+mongoose.model('Sckeletal', Schema({
   consiousness: {type: String},
   dvtSigns: {type: Boolean},
   edema: {type: String},
@@ -302,7 +301,7 @@ load.Sckeletal = tbd.from({
   reflexes: '{ type: String}'
 }).make(dicCnt);
 
-var Pulse = mongoose.model('Pulse', Schema({
+mongoose.model('Pulse', Schema({
   rate: String
 }));
 
@@ -310,7 +309,7 @@ load.Pulse = tbd.from({
   rate: 'String'
 }).make(dicCnt);
 
-var Supplier = mongoose.model('Supplier', Schema({
+mongoose.model('Supplier', Schema({
   supplierDescription: {type: String},
   supplierQty: {type: Number},
   supplierRemarks: {
@@ -324,7 +323,7 @@ load.Supplier = tbd.from({
   supplierRemarks: '{ type: String }'
 }).make(dicCnt);
 
-var Gastrointestinal = mongoose.model('Gastrointestinal', Schema({
+mongoose.model('Gastrointestinal', Schema({
   leftKidney: {type: String},
   liver: {type: String},
   rightKidney: {type: String},
@@ -340,7 +339,7 @@ load.Gastrointestinal = tbd.from({
   spleen: '{ type: String }'
 }).make(dicCnt);
 
-var Ecg = mongoose.model('Ecg', Schema({
+mongoose.model('Ecg', Schema({
   ecgAxis: {type: String},
   ecgConduction: {type: String},
   ecgIschemia: {type: String},
@@ -360,7 +359,7 @@ load.Ecg = tbd.from({
   generalCondition: ' { type: String }'
 }).make(dicCnt);
 
-var Diagnose = mongoose.model('Diagnose', Schema({
+mongoose.model('Diagnose', Schema({
   diagNotes: {type: String},
   diagnoseGroup: {type: String},
   diagnoseName: {type: String, required: true},
@@ -376,7 +375,7 @@ load.Diagnose = tbd.from({
   idDiagnose: '{ type: String }'
 }).make(dicCnt);
 
-var Conclusion = mongoose.model('Conclusion', Schema({
+mongoose.model('Conclusion', Schema({
   approver: {type: String},
   daysScheduleVisits: {type: String},
   doctorLicense: {type: String},
@@ -415,7 +414,7 @@ function getItem(list) {
   };
 }
 
-var MedicalCard = mongoose.model('MedicalCard', Schema({
+mongoose.model('MedicalCard', Schema({
   firstName: String,
   lastName: String,
   medication: [{type: ObjectId, ref: 'Medication'}],
@@ -447,7 +446,7 @@ for (i = 0; i < len; i++) {
 }
 
 
-var db = mongoose.createConnection('localhost', 'HeavyLoad', function (err) {
+var db = mongoose.createConnection('localhost', 'HeavyLoad', function () {
   function getItems(list) {
     if (!list) {
       done();
@@ -577,7 +576,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function (err) {
       }
     };
 
-    var nextRun = function (err, data) {
+    var nextRun = function (err) {
       if (err) {
         return nextQuery(err);
       }
@@ -598,7 +597,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function (err) {
     nextQuery();
   };
 
-  var createRelations = function (err) {
+  var createRelations = function () {
     var coll = db.db.collection('medicalcards');
     console.log('Main Collection prepare');
     coll.remove({}, function () {
@@ -629,7 +628,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function (err) {
       .prop('conclusion').use(getItem(load.Conclusion)).done()
       .make(mainCnt);
 
-      var saveAll = function (err, data) {
+      var saveAll = function (err) {
         if (err) {
           done();
         } else if (--res === 0) {
@@ -640,7 +639,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function (err) {
 
       var res = loadMedicalCard.length;
       var mc = db.model('MedicalCard');
-      var i, rec;
+      var i;
       var len = loadMedicalCard.length;
       for (i = 0; i < len; i++) {
         new mc(loadMedicalCard[i]).save(saveAll);
@@ -709,7 +708,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function (err) {
       var coll = db.db.collection(item.collection);
       console.log(item.model);
       coll.remove({}, function () {
-        coll.save(item.list, function (err, data) {
+        coll.save(item.list, function () {
           var mdl = db.model(item.model);
           mdl.find({}, next);
         });
diff --git a/lib/ES6Promise.js b/lib/ES6Promise.js
index a513d95e27b..2025e6b2bec 100644
--- a/lib/ES6Promise.js
+++ b/lib/ES6Promise.js
@@ -1,5 +1,3 @@
-/* eslint no-unused-vars: 1 */
-
 /**
  * ES6 Promise wrapper constructor.
  *
@@ -17,7 +15,7 @@
  * @api public
  */
 
-function ES6Promise(fn) {
+function ES6Promise() {
   throw new Error('Can\'t use ES6 promise with mpromise style constructor');
 }
 
diff --git a/lib/aggregate.js b/lib/aggregate.js
index 753f0b7b32a..5ea3c65e4af 100644
--- a/lib/aggregate.js
+++ b/lib/aggregate.js
@@ -1,5 +1,3 @@
-/* eslint no-unused-vars: 1 */
-
 /*!
  * Module dependencies
  */
@@ -46,7 +44,7 @@ function Aggregate() {
   this._model = undefined;
   this.options = undefined;
 
-  if (1 === arguments.length && util.isArray(arguments[0])) {
+  if (arguments.length === 1 && util.isArray(arguments[0])) {
     this.append.apply(this, arguments[0]);
   } else {
     this.append.apply(this, arguments);
@@ -83,7 +81,7 @@ Aggregate.prototype.model = function (model) {
  */
 
 Aggregate.prototype.append = function () {
-  var args = (1 === arguments.length && util.isArray(arguments[0]))
+  var args = (arguments.length === 1 && util.isArray(arguments[0]))
       ? arguments[0]
       : utils.args(arguments);
 
@@ -135,11 +133,15 @@ Aggregate.prototype.project = function (arg) {
     Object.keys(arg).forEach(function (field) {
       fields[field] = arg[field];
     });
-  } else if (1 === arguments.length && typeof arg === 'string') {
+  } else if (arguments.length === 1 && typeof arg === 'string') {
     arg.split(/\s+/).forEach(function (field) {
-      if (!field) return;
-      var include = '-' === field[0] ? 0 : 1;
-      if (include === 0) field = field.substring(1);
+      if (!field) {
+        return;
+      }
+      var include = field[0] === '-' ? 0 : 1;
+      if (include === 0) {
+        field = field.substring(1);
+      }
       fields[field] = include;
     });
   } else {
@@ -342,11 +344,15 @@ Aggregate.prototype.sort = function (arg) {
     Object.keys(arg).forEach(function (field) {
       sort[field] = desc.indexOf(arg[field]) === -1 ? 1 : -1;
     });
-  } else if (1 === arguments.length && typeof arg === 'string') {
+  } else if (arguments.length === 1 && typeof arg === 'string') {
     arg.split(/\s+/).forEach(function (field) {
-      if (!field) return;
-      var ascend = '-' === field[0] ? -1 : 1;
-      if (ascend === -1) field = field.substring(1);
+      if (!field) {
+        return;
+      }
+      var ascend = field[0] === '-' ? -1 : 1;
+      if (ascend === -1) {
+        field = field.substring(1);
+      }
       sort[field] = ascend;
     });
   } else {
@@ -369,9 +375,11 @@ Aggregate.prototype.sort = function (arg) {
  * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences
  */
 
-Aggregate.prototype.read = function (pref) {
-  if (!this.options) this.options = {};
-  read.apply(this, arguments);
+Aggregate.prototype.read = function (pref, tags) {
+  if (!this.options) {
+    this.options = {};
+  }
+  read.call(this, pref, tags);
   return this;
 };
 
@@ -402,22 +410,22 @@ Aggregate.prototype.explain = function (callback) {
     prepareDiscriminatorPipeline(_this);
 
     _this._model
-      .collection
-      .aggregate(_this._pipeline, _this.options || {})
-      .explain(function (error, result) {
-        if (error) {
-          if (callback) {
-            callback(error);
+        .collection
+        .aggregate(_this._pipeline, _this.options || {})
+        .explain(function (error, result) {
+          if (error) {
+            if (callback) {
+              callback(error);
+            }
+            reject(error);
+            return;
           }
-          reject(error);
-          return;
-        }
 
-        if (callback) {
-          callback(null, result);
-        }
-        resolve(result);
-      });
+          if (callback) {
+            callback(null, result);
+          }
+          resolve(result);
+        });
   });
 };
 
@@ -434,7 +442,9 @@ Aggregate.prototype.explain = function (callback) {
  */
 
 Aggregate.prototype.allowDiskUse = function (value) {
-  if (!this.options) this.options = {};
+  if (!this.options) {
+    this.options = {};
+  }
   this.options.allowDiskUse = value;
   return this;
 };
@@ -456,7 +466,9 @@ Aggregate.prototype.allowDiskUse = function (value) {
  */
 
 Aggregate.prototype.cursor = function (options) {
-  if (!this.options) this.options = {};
+  if (!this.options) {
+    this.options = {};
+  }
   this.options.cursor = options;
   return this;
 };
@@ -487,11 +499,11 @@ Aggregate.prototype.exec = function (callback) {
 
   if (this.options && this.options.cursor) {
     if (this.options.cursor.async) {
-      return new Promise.ES6(function (resolve, reject) {
+      return new Promise.ES6(function (resolve) {
         if (!_this._model.collection.buffer) {
           process.nextTick(function () {
             var cursor = _this._model.collection.
-              aggregate(_this._pipeline, _this.options || {});
+            aggregate(_this._pipeline, _this.options || {});
             resolve(cursor);
             callback && callback(cursor);
           });
@@ -499,14 +511,14 @@ Aggregate.prototype.exec = function (callback) {
         }
         _this._model.collection.emitter.once('queue', function () {
           var cursor = _this._model.collection.
-            aggregate(_this._pipeline, _this.options || {});
+          aggregate(_this._pipeline, _this.options || {});
           resolve(cursor);
           callback && callback(null, cursor);
         });
       });
     }
     return this._model.collection.
-      aggregate(this._pipeline, this.options || {});
+    aggregate(this._pipeline, this.options || {});
   }
 
   return new Promise.ES6(function (resolve, reject) {
@@ -522,21 +534,21 @@ Aggregate.prototype.exec = function (callback) {
     prepareDiscriminatorPipeline(_this);
 
     _this._model
-      .collection
-      .aggregate(_this._pipeline, _this.options || {}, function (error, result) {
-        if (error) {
-          if (callback) {
-            callback(error);
+        .collection
+        .aggregate(_this._pipeline, _this.options || {}, function (error, result) {
+          if (error) {
+            if (callback) {
+              callback(error);
+            }
+            reject(error);
+            return;
           }
-          reject(error);
-          return;
-        }
 
-        if (callback) {
-          callback(null, result);
-        }
-        resolve(result);
-      });
+          if (callback) {
+            callback(null, result);
+          }
+          resolve(result);
+        });
   });
 };
 
@@ -561,9 +573,10 @@ function isOperator(obj) {
 
   k = Object.keys(obj);
 
-  return 1 === k.length && k.some(function (key) {
-    return '$' === key[0];
-  });
+  return k.length === 1 && k
+          .some(function (key) {
+            return key[0] === '$';
+          });
 }
 
 /*!
@@ -586,14 +599,13 @@ function prepareDiscriminatorPipeline(aggregate) {
     // If the first pipeline stage is a match and it doesn't specify a `__t`
     // key, add the discriminator key to it. This allows for potential
     // aggregation query optimizations not to be disturbed by this feature.
-    if (originalPipeline[0] && originalPipeline[0].$match &&
-        !originalPipeline[0].$match[discriminatorKey]) {
+    if (originalPipeline[0] && originalPipeline[0].$match && !originalPipeline[0].$match[discriminatorKey]) {
       originalPipeline[0].$match[discriminatorKey] = discriminatorValue;
       // `originalPipeline` is a ref, so there's no need for
       // aggregate._pipeline = originalPipeline
     } else if (originalPipeline[0] && originalPipeline[0].$geoNear) {
       originalPipeline[0].$geoNear.query =
-        originalPipeline[0].$geoNear.query || {};
+          originalPipeline[0].$geoNear.query || {};
       originalPipeline[0].$geoNear.query[discriminatorKey] = discriminatorValue;
     } else {
       var match = {};
diff --git a/lib/cast.js b/lib/cast.js
index 728638ee246..ccb64751bfc 100644
--- a/lib/cast.js
+++ b/lib/cast.js
@@ -27,7 +27,7 @@ var cast = module.exports = function (schema, obj) {
     path = paths[i];
     val = obj[path];
 
-    if ('$or' === path || '$nor' === path || '$and' === path) {
+    if (path === '$or' || path === '$nor' || path === '$and') {
       var k = val.length;
 
       while (k--) {
@@ -36,7 +36,7 @@ var cast = module.exports = function (schema, obj) {
     } else if (path === '$where') {
       type = typeof val;
 
-      if ('string' !== type && 'function' !== type) {
+      if (type !== 'string' && type !== 'function') {
         throw new Error('Must have a string or function for $where');
       }
 
@@ -67,7 +67,9 @@ var cast = module.exports = function (schema, obj) {
         while (j--) {
           pathFirstHalf = split.slice(0, j).join('.');
           schematype = schema.path(pathFirstHalf);
-          if (schematype) break;
+          if (schematype) {
+            break;
+          }
         }
 
         // If a substring of the input path resolves to an actual real path...
@@ -104,22 +106,22 @@ var cast = module.exports = function (schema, obj) {
             val.$maxDistance = numbertype.castForQuery(val.$maxDistance);
           }
 
-          if ('$within' === geo) {
+          if (geo === '$within') {
             var withinType = value.$center
-                          || value.$centerSphere
-                          || value.$box
-                          || value.$polygon;
+                || value.$centerSphere
+                || value.$box
+                || value.$polygon;
 
             if (!withinType) {
               throw new Error('Bad $within paramater: ' + JSON.stringify(val));
             }
 
             value = withinType;
-          } else if ('$near' === geo &&
+          } else if (geo === '$near' &&
               typeof value.type === 'string' && Array.isArray(value.coordinates)) {
             // geojson; cast the coordinates
             value = value.coordinates;
-          } else if (('$near' === geo || '$nearSphere' === geo || '$geoIntersects' === geo) &&
+          } else if ((geo === '$near' || geo === '$nearSphere' || geo === '$geoIntersects') &&
               value.$geometry && typeof value.$geometry.type === 'string' &&
               Array.isArray(value.$geometry.coordinates)) {
             // geojson; cast the coordinates
@@ -170,21 +172,21 @@ var cast = module.exports = function (schema, obj) {
             $cond = ks[k];
             nested = val[$cond];
 
-            if ('$exists' === $cond) {
+            if ($cond === '$exists') {
               if (typeof nested !== 'boolean') {
                 throw new Error('$exists parameter must be Boolean');
               }
               continue;
             }
 
-            if ('$type' === $cond) {
+            if ($cond === '$type') {
               if (typeof nested !== 'number') {
                 throw new Error('$type parameter must be Number');
               }
               continue;
             }
 
-            if ('$not' === $cond) {
+            if ($cond === '$not') {
               cast(schema, nested);
             } else {
               val[$cond] = schematype.castForQuery($cond, nested);
diff --git a/lib/collection.js b/lib/collection.js
index f44d211adc6..bffc5fdd912 100644
--- a/lib/collection.js
+++ b/lib/collection.js
@@ -1,4 +1,3 @@
-
 /*!
  * Module dependencies.
  */
@@ -18,12 +17,16 @@ var STATES = require('./connectionstate');
  */
 
 function Collection(name, conn, opts) {
-  if (undefined === opts) opts = {};
-  if (undefined === opts.capped) opts.capped = {};
+  if (opts === void 0) {
+    opts = {};
+  }
+  if (opts.capped === void 0) {
+    opts.capped = {};
+  }
 
   opts.bufferCommands = undefined === opts.bufferCommands
-    ? true
-    : opts.bufferCommands;
+      ? true
+      : opts.bufferCommands;
 
   if (typeof opts.capped === 'number') {
     opts.capped = {size: opts.capped};
diff --git a/lib/connection.js b/lib/connection.js
index cda8429bbe3..9cfe32a7575 100644
--- a/lib/connection.js
+++ b/lib/connection.js
@@ -256,7 +256,7 @@ Connection.prototype.open = function (host, database, port, options, callback) {
     this.user = parsed.auth.user;
     this.pass = parsed.auth.pass;
 
-  // Check hostname for user/pass
+    // Check hostname for user/pass
   } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
     host = host.split('@');
     var auth = host.shift().split(':');
@@ -436,7 +436,9 @@ Connection.prototype.openSet = function (uris, database, options, callback) {
  */
 
 Connection.prototype.error = function (err, callback) {
-  if (callback) return callback(err);
+  if (callback) {
+    return callback(err);
+  }
   this.emit('error', err);
 };
 
@@ -454,15 +456,17 @@ Connection.prototype._open = function (emit, callback) {
   var _this = this;
 
   var method = this.replica
-    ? 'doOpenSet'
-    : 'doOpen';
+      ? 'doOpenSet'
+      : 'doOpen';
 
   // open connection
   this[method](function (err) {
     if (err) {
       _this.readyState = STATES.disconnected;
       if (_this._hasOpened) {
-        if (callback) callback(err);
+        if (callback) {
+          callback(err);
+        }
       } else {
         _this.error(err, emit && callback);
       }
@@ -575,7 +579,9 @@ Connection.prototype._close = function (callback) {
       break;
 
     case 3: // disconnecting
-      if (!callback) break;
+      if (!callback) {
+        break;
+      }
       this.once('close', function () {
         callback();
       });
@@ -739,8 +745,8 @@ Connection.prototype.modelNames = function () {
  * @return {Boolean} true if the connection should be authenticated after it is opened, otherwise false.
  */
 Connection.prototype.shouldAuthenticate = function () {
-  return (this.user != null) &&
-    ((this.pass != null) || this.authMechanismDoesNotRequirePassword());
+  return (this.user !== null && this.user !== void 0) &&
+      ((this.pass !== null || this.pass !== void 0) || this.authMechanismDoesNotRequirePassword());
 };
 
 /**
@@ -769,8 +775,8 @@ Connection.prototype.authMechanismDoesNotRequirePassword = function () {
  */
 Connection.prototype.optionsProvideAuthenticationData = function (options) {
   return (options) &&
-    (options.user) &&
-    ((options.pass) || this.authMechanismDoesNotRequirePassword());
+      (options.user) &&
+      ((options.pass) || this.authMechanismDoesNotRequirePassword());
 };
 
 /*!
diff --git a/lib/document.js b/lib/document.js
index bc955920dbc..896ab67c421 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -1,5 +1,3 @@
-/* eslint no-unused-vars: 1 */
-
 /*!
  * Module dependencies.
  */
@@ -157,7 +155,7 @@ Document.prototype.$__buildDoc = function (obj, fields, skipId) {
 
   // determine if this doc is a result of a query with
   // excluded fields
-  if (fields && 'Object' === utils.getFunctionName(fields.constructor)) {
+  if (fields && utils.getFunctionName(fields.constructor) === 'Object') {
     keys = Object.keys(fields);
     ki = keys.length;
 
@@ -317,7 +315,7 @@ function init(self, obj, doc, prefix) {
     schema = self.schema.path(path);
 
     if (!schema && utils.isObject(obj[i]) &&
-        (!obj[i].constructor || 'Object' === utils.getFunctionName(obj[i].constructor))) {
+        (!obj[i].constructor || utils.getFunctionName(obj[i].constructor) === 'Object')) {
       // assume nested object
       if (!doc[i]) {
         doc[i] = {};
@@ -365,7 +363,7 @@ function init(self, obj, doc, prefix) {
 Document.prototype.$__storeShard = function () {
   // backwards compat
   var key = this.schema.options.shardKey || this.schema.options.shardkey;
-  if (!(key && 'Object' === utils.getFunctionName(key.constructor))) {
+  if (!(key && utils.getFunctionName(key.constructor) === 'Object')) {
     return;
   }
 
@@ -378,7 +376,7 @@ Document.prototype.$__storeShard = function () {
     val = this.getValue(paths[i]);
     if (isMongooseObject(val)) {
       orig[paths[i]] = val.toObject({depopulate: true});
-    } else if (null !== val &&
+    } else if (val !== null &&
         val.valueOf &&
           // Explicitly don't take value of dates
         (!val.constructor || utils.getFunctionName(val.constructor) !== 'Date')) {
@@ -455,14 +453,14 @@ Document.prototype.update = function update() {
  */
 
 Document.prototype.set = function (path, val, type, options) {
-  if (type && 'Object' === utils.getFunctionName(type.constructor)) {
+  if (type && utils.getFunctionName(type.constructor) === 'Object') {
     options = type;
     type = undefined;
   }
 
   var merge = options && options.merge,
-      adhoc = type && true !== type,
-      constructing = true === type,
+      adhoc = type && type !== true,
+      constructing = type === true,
       adhocs;
 
   var strict = options && 'strict' in options
@@ -474,10 +472,10 @@ Document.prototype.set = function (path, val, type, options) {
     adhocs[path] = Schema.interpretAsType(path, type, this.schema.options);
   }
 
-  if ('string' !== typeof path) {
+  if (typeof path !== 'string') {
     // new Document({ key: val })
 
-    if (null === path || undefined === path) {
+    if (path === null || path === void 0) {
       var _ = path;
       path = val;
       val = _;
@@ -504,19 +502,19 @@ Document.prototype.set = function (path, val, type, options) {
         var pathName = prefix + key;
         pathtype = this.schema.pathType(pathName);
 
-        if (null !== path[key]
+        if (path[key] !== null
               // need to know if plain object - no Buffer, ObjectId, ref, etc
             && utils.isObject(path[key])
-            && (!path[key].constructor || 'Object' === utils.getFunctionName(path[key].constructor))
-            && 'virtual' !== pathtype
-            && 'real' !== pathtype
+            && (!path[key].constructor || utils.getFunctionName(path[key].constructor) === 'Object')
+            && pathtype !== 'virtual'
+            && pathtype !== 'real'
             && !(this.$__path(pathName) instanceof MixedSchema)
             && !(this.schema.paths[pathName] &&
             this.schema.paths[pathName].options &&
             this.schema.paths[pathName].options.ref)) {
           this.set(path[key], prefix + key, constructing);
         } else if (strict) {
-          if ('real' === pathtype || pathtype === 'virtual') {
+          if (pathtype === 'real' || pathtype === 'virtual') {
             // Check for setting single embedded schema to document (gh-3535)
             if (this.schema.paths[pathName] &&
                 this.schema.paths[pathName].$isSingleNested &&
@@ -547,9 +545,9 @@ Document.prototype.set = function (path, val, type, options) {
   // docschema = new Schema({ path: { nest: 'string' }})
   // doc.set('path', obj);
   var pathType = this.schema.pathType(path);
-  if ('nested' === pathType && val) {
+  if (pathType === 'nested' && val) {
     if (utils.isObject(val) &&
-        (!val.constructor || 'Object' === utils.getFunctionName(val.constructor))) {
+        (!val.constructor || utils.getFunctionName(val.constructor) === 'Object')) {
       if (!merge) {
         this.setValue(path, null);
       }
@@ -563,7 +561,7 @@ Document.prototype.set = function (path, val, type, options) {
   var schema;
   var parts = path.split('.');
 
-  if ('adhocOrUndefined' === pathType && strict) {
+  if (pathType === 'adhocOrUndefined' && strict) {
     // check for roots that are Mixed types
     var mixed;
 
@@ -658,7 +656,8 @@ Document.prototype.set = function (path, val, type, options) {
             }),
             {model: val[0].constructor});
       } else {
-        this.populated(path, val.map(function (v) {
+        this.populated(path, val
+        .map(function (v) {
           return v._id;
         }),
             {model: val[0].constructor});
@@ -719,7 +718,7 @@ Document.prototype.$__shouldModify = function (pathToMark, path, constructing, p
   }
 
   if (!constructing &&
-      null !== val &&
+      val !== null &&
       path in this.$__.activePaths.states.default &&
       deepEqual(val, schema.getDefault(this, constructing))) {
     // a path with a default was $unset on the server
@@ -737,7 +736,7 @@ Document.prototype.$__shouldModify = function (pathToMark, path, constructing, p
  * @memberOf Document
  */
 
-Document.prototype.$__set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {
+Document.prototype.$__set = function (pathToMark, path, constructing, parts, schema, val/* , priorVal */) {
   Embedded = Embedded || require('./types/embedded');
 
   var shouldModify = this.$__shouldModify.apply(this, arguments);
@@ -772,7 +771,7 @@ Document.prototype.$__set = function (pathToMark, path, constructing, parts, sch
     if (last) {
       obj[parts[i]] = val;
     } else {
-      if (obj[parts[i]] && 'Object' === utils.getFunctionName(obj[parts[i]].constructor)) {
+      if (obj[parts[i]] && utils.getFunctionName(obj[parts[i]].constructor) === 'Object') {
         obj = obj[parts[i]];
       } else if (obj[parts[i]] && obj[parts[i]] instanceof Embedded) {
         obj = obj[parts[i]];
@@ -838,7 +837,7 @@ Document.prototype.get = function (path, type) {
       obj = this._doc;
 
   for (var i = 0, l = pieces.length; i < l; i++) {
-    obj = undefined === obj || null === obj
+    obj = obj === null || obj === void 0
         ? undefined
         : obj[pieces[i]];
   }
@@ -1002,7 +1001,7 @@ Document.prototype.isInit = function (path) {
 Document.prototype.isSelected = function isSelected(path) {
   if (this.$__.selected) {
     if (path === '_id') {
-      return 0 !== this.$__.selected._id;
+      return this.$__.selected._id !== 0;
     }
 
     var paths = Object.keys(this.$__.selected),
@@ -1010,9 +1009,9 @@ Document.prototype.isSelected = function isSelected(path) {
         inclusive = false,
         cur;
 
-    if (1 === i && '_id' === paths[0]) {
+    if (i === 1 && paths[0] === '_id') {
       // only _id was selected.
-      return 0 === this.$__.selected._id;
+      return this.$__.selected._id === 0;
     }
 
     while (i--) {
@@ -1037,11 +1036,11 @@ Document.prototype.isSelected = function isSelected(path) {
         continue;
       }
 
-      if (0 === cur.indexOf(pathDot)) {
+      if (cur.indexOf(pathDot) === 0) {
         return inclusive;
       }
 
-      if (0 === pathDot.indexOf(cur + '.')) {
+      if (pathDot.indexOf(cur + '.') === 0) {
         return inclusive;
       }
     }
@@ -1131,7 +1130,7 @@ Document.prototype.$__validate = function (callback) {
   paths = paths.concat(Object.keys(this.$__.activePaths.states.modify));
   paths = paths.concat(Object.keys(this.$__.activePaths.states.default));
 
-  if (0 === paths.length) {
+  if (paths.length === 0) {
     process.nextTick(function () {
       var err = _complete();
       if (err) {
@@ -1471,7 +1470,7 @@ Document.prototype.$__dirty = function () {
       lastPath,
       top;
 
-  all.forEach(function (item, i) {
+  all.forEach(function (item) {
     if (!item) {
       return;
     }
@@ -1509,8 +1508,8 @@ function compile(tree, proto, prefix, options) {
     key = keys[i];
     limb = tree[key];
 
-    defineKey(key
-        , (('Object' === utils.getFunctionName(limb.constructor)
+    defineKey(key,
+        ((utils.getFunctionName(limb.constructor) === 'Object'
         && Object.keys(limb).length)
         && (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type))
             ? limb
@@ -1870,7 +1869,7 @@ Document.prototype.$toObject = function (options, json) {
 
   // When internally saving this document we always pass options,
   // bypassing the custom schema options.
-  if (!(options && 'Object' === utils.getFunctionName(options.constructor)) ||
+  if (!(options && utils.getFunctionName(options.constructor) === 'Object') ||
       (options && options._useSchemaOptions)) {
     if (json) {
       options = this.schema.options.toJSON ?
@@ -1910,7 +1909,7 @@ Document.prototype.$toObject = function (options, json) {
     }
   }
 
-  if (options.virtuals || options.getters && false !== options.virtuals) {
+  if (options.virtuals || options.getters && options.virtuals !== false) {
     applyGetters(this, ret, 'virtuals', options);
   }
 
@@ -1925,7 +1924,7 @@ Document.prototype.$toObject = function (options, json) {
   // child schema has a transform (this.schema.options.toObject) In this case,
   // we need to adjust options.transform to be the child schema's transform and
   // not the parent schema's
-  if (true === transform ||
+  if (transform === true ||
       (this.schema.options.toObject && transform)) {
     var opts = options.json ? this.schema.options.toJSON : this.schema.options.toObject;
 
@@ -1938,7 +1937,7 @@ Document.prototype.$toObject = function (options, json) {
 
   if (typeof transform === 'function') {
     var xformed = transform(this, ret, options);
-    if ('undefined' !== typeof xformed) {
+    if (typeof xformed !== 'undefined') {
       ret = xformed;
     }
   }
@@ -2163,7 +2162,7 @@ Document.prototype.toJSON = function (options) {
  */
 
 Document.prototype.inspect = function (options) {
-  var opts = options && 'Object' === utils.getFunctionName(options.constructor) ? options : {};
+  var opts = options && utils.getFunctionName(options.constructor) === 'Object' ? options : {};
   opts.minimize = false;
   opts.retainKeyOrder = true;
   return this.toObject(opts);
@@ -2243,7 +2242,7 @@ Document.prototype.equals = function (doc) {
  */
 
 Document.prototype.populate = function populate() {
-  if (0 === arguments.length) {
+  if (arguments.length === 0) {
     return this;
   }
 
@@ -2251,7 +2250,7 @@ Document.prototype.populate = function populate() {
   var args = utils.args(arguments);
   var fn;
 
-  if ('function' == typeof args[args.length - 1]) {
+  if (typeof args[args.length - 1] === 'function') {
     fn = args.pop();
   }
 
@@ -2347,7 +2346,7 @@ Document.prototype.populated = function (path, val, options) {
 
   // internal
 
-  if (true === val) {
+  if (val === true) {
     if (!this.$__.populated) {
       return undefined;
     }
diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js
index b6b5f65f3c7..7c2ea597cb1 100644
--- a/lib/drivers/node-mongodb-native/collection.js
+++ b/lib/drivers/node-mongodb-native/collection.js
@@ -1,4 +1,3 @@
-
 /*!
  * Module dependencies.
  */
@@ -61,9 +60,9 @@ NativeCollection.prototype.onOpen = function () {
           callback(null, c);
         } else {
           var msg = 'A non-capped collection exists with the name: ' + _this.name + '\n\n'
-                  + ' To use this collection as a capped collection, please '
-                  + 'first convert it.\n'
-                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped';
+              + ' To use this collection as a capped collection, please '
+              + 'first convert it.\n'
+              + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped';
           err = new Error(msg);
           callback(err);
         }
@@ -127,7 +126,7 @@ for (var i in Collection.prototype) {
       if (debug) {
         if (typeof debug === 'function') {
           debug.apply(debug
-            , [_this.name, i].concat(utils.args(args, 0, args.length - 1)));
+              , [_this.name, i].concat(utils.args(args, 0, args.length - 1)));
         } else {
           this.$print(_this.name, i, args);
         }
@@ -146,13 +145,13 @@ for (var i in Collection.prototype) {
 
 NativeCollection.prototype.$print = function (name, i, args) {
   console.error(
-    '\x1B[0;36mMongoose:\x1B[0m %s.%s(%s) %s %s %s',
-    name,
-    i,
-    this.$format(args[0]),
-    this.$format(args[1]),
-    this.$format(args[2]),
-    this.$format(args[3]));
+      '\x1B[0;36mMongoose:\x1B[0m %s.%s(%s) %s %s %s',
+      name,
+      i,
+      this.$format(args[0]),
+      this.$format(args[1]),
+      this.$format(args[2]),
+      this.$format(args[3]));
 };
 
 /**
@@ -190,16 +189,16 @@ function format(obj, sub) {
       for (var i = 0; i < numKeys; ++i) {
         key = keys[i];
         if (x[key]) {
-          if ('Binary' === x[key].constructor.name) {
+          if (x[key].constructor.name === 'Binary') {
             x[key] = '[object Buffer]';
-          } else if ('Object' === x[key].constructor.name) {
+          } else if (x[key].constructor.name === 'Object') {
             x[key] = format(x[key], true);
-          } else if ('ObjectID' === x[key].constructor.name) {
+          } else if (x[key].constructor.name === 'ObjectID') {
             (function (x) {
               var representation = 'ObjectId("' + x[key].toHexString() + '")';
               x[key] = {inspect: function () { return representation; }};
             })(x);
-          } else if ('Date' === x[key].constructor.name) {
+          } else if (x[key].constructor.name === 'Date') {
             (function (x) {
               var representation = 'new Date("' + x[key].toUTCString() + '")';
               x[key] = {inspect: function () { return representation; }};
@@ -216,9 +215,9 @@ function format(obj, sub) {
   }
 
   return require('util')
-    .inspect(x, false, 10, true)
-    .replace(/\n/g, '')
-    .replace(/\s{2,}/g, ' ');
+  .inspect(x, false, 10, true)
+  .replace(/\n/g, '')
+  .replace(/\s{2,}/g, ' ');
 }
 
 /**
diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js
index c9045042a0f..f88bd03e4d6 100644
--- a/lib/drivers/node-mongodb-native/connection.js
+++ b/lib/drivers/node-mongodb-native/connection.js
@@ -341,7 +341,7 @@ NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {
  */
 
 function validate(o) {
-  if (-1 === o.db.w || 0 === o.db.w) {
+  if (o.db.w === -1 || o.db.w === 0) {
     if (o.db.journal || o.db.fsync || o.db.safe) {
       throw new Error(
           'Invalid writeConcern: '
diff --git a/lib/error/browserMissingSchema.js b/lib/error/browserMissingSchema.js
index 8a67f1ae2ea..1c7892e1f5b 100644
--- a/lib/error/browserMissingSchema.js
+++ b/lib/error/browserMissingSchema.js
@@ -1,4 +1,3 @@
-/* eslint no-unused-vars: 1 */
 /*!
  * Module dependencies.
  */
@@ -11,7 +10,7 @@ var MongooseError = require('../error.js');
  * @inherits MongooseError
  */
 
-function MissingSchemaError(name) {
+function MissingSchemaError() {
   var msg = 'Schema hasn\'t been registered for document.\n'
           + 'Use mongoose.Document(name, schema)';
   MongooseError.call(this, msg);
diff --git a/lib/index.js b/lib/index.js
index acef70a8fe3..c5051eddc6d 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -351,7 +351,7 @@ Mongoose.prototype.model = function (name, schema, collection, skipInit) {
 
   // connection.model() may be passing a different schema for
   // an existing model name. in this case don't read from cache.
-  if (this.models[name] && false !== options.cache) {
+  if (this.models[name] && options.cache !== false) {
     if (schema && schema.instanceOfSchema && schema !== this.models[name].schema) {
       throw new mongoose.Error.OverwriteModelError(name);
     }
@@ -391,7 +391,7 @@ Mongoose.prototype.model = function (name, schema, collection, skipInit) {
     model.init();
   }
 
-  if (false === options.cache) {
+  if (options.cache === false) {
     return model;
   }
 
diff --git a/lib/model.js b/lib/model.js
index 1d074e61a90..05d604369b8 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -1,5 +1,3 @@
-/* eslint no-unused-vars: 1 */
-
 /*!
  * Module dependencies.
  */
@@ -11,7 +9,6 @@ var DivergentArrayError = MongooseError.DivergentArrayError;
 var Query = require('./query');
 var Aggregate = require('./aggregate');
 var Schema = require('./schema');
-var Types = require('./schema/index');
 var utils = require('./utils');
 var hasOwnProperty = utils.object.hasOwnProperty;
 var isMongooseObject = utils.isMongooseObject;
@@ -334,7 +331,7 @@ function operand(self, where, delta, data, val, op) {
   delta[op][data.path] = val;
 
   // disabled versioning?
-  if (false === self.schema.options.versionKey) return;
+  if (self.schema.options.versionKey === false) return;
 
   // path excluded from versioning?
   if (shouldSkipVersioning(self, data.path)) return;
@@ -362,7 +359,7 @@ function operand(self, where, delta, data, val, op) {
   // only increment the version if an array position changes.
   // modifying elements of an array is ok if position does not change.
 
-  if ('$push' === op || '$pushAll' === op || '$addToSet' === op) {
+  if (op === '$push' || op === '$pushAll' || op === '$addToSet') {
     self.$__.version = VERSION_INC;
   } else if (/^\$p/.test(op)) {
     // potentially changing array positions
@@ -410,7 +407,7 @@ function handleAtomics(self, where, delta, data, value) {
       val,
       op;
 
-  if (0 === i) {
+  if (i === 0) {
     // $set
 
     if (isMongooseObject(value)) {
@@ -431,14 +428,14 @@ function handleAtomics(self, where, delta, data, value) {
     } else if (Array.isArray(val)) {
       val = val.map(function (mem) {
         return isMongooseObject(mem)
-          ? mem.toObject({depopulate: 1})
-          : mem;
+            ? mem.toObject({depopulate: 1})
+            : mem;
       });
     } else if (val.valueOf) {
       val = val.valueOf();
     }
 
-    if ('$addToSet' === op) {
+    if (op === '$addToSet') {
       val = {$each: val};
     }
 
@@ -480,7 +477,7 @@ Model.prototype.$__delta = function () {
 
     if (undefined === value) {
       operand(this, where, delta, data, 1, '$unset');
-    } else if (null === value) {
+    } else if (value === null) {
       operand(this, where, delta, data, null);
     } else if (value._path && value._atomics) {
       // arrays and other custom types (support plugins etc)
@@ -542,15 +539,15 @@ function checkDivergentArray(doc, path, array) {
   // would be similarily destructive as we never received all
   // elements of the array and potentially would overwrite data.
   var check = pop.options.match ||
-              pop.options.options && hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted
-              pop.options.options && pop.options.options.skip || // 0 is permitted
-              pop.options.select && // deselected _id?
-                (0 === pop.options.select._id ||
-                /\s?-_id\s?/.test(pop.options.select));
+      pop.options.options && hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted
+      pop.options.options && pop.options.options.skip || // 0 is permitted
+      pop.options.select && // deselected _id?
+      (pop.options.select._id === 0 ||
+      /\s?-_id\s?/.test(pop.options.select));
 
   if (check) {
     var atomics = array._atomics;
-    if (0 === Object.keys(atomics).length || atomics.$set || atomics.$pop) {
+    if (Object.keys(atomics).length === 0 || atomics.$set || atomics.$pop) {
       return path;
     }
   }
@@ -567,7 +564,7 @@ function checkDivergentArray(doc, path, array) {
 Model.prototype.$__version = function (where, delta) {
   var key = this.schema.options.versionKey;
 
-  if (true === where) {
+  if (where === true) {
     // this is an insert
     if (key) this.setValue(key, delta[key] = 0);
     return;
@@ -688,8 +685,8 @@ Model.prototype.remove = function remove(options, fn) {
   if (this.$__.removing) {
     if (fn) {
       this.$__.removing.then(
-        function (res) { fn(null, res); },
-        function (err) { fn(err); });
+          function (res) { fn(null, res); },
+          function (err) { fn(err); });
     }
     return this;
   }
@@ -772,13 +769,13 @@ Model.discriminator = function discriminator(name, schema) {
 
   if (this.schema.discriminatorMapping && !this.schema.discriminatorMapping.isRoot) {
     throw new Error('Discriminator "' + name +
-      '" can only be a discriminator of the root model');
+        '" can only be a discriminator of the root model');
   }
 
   var key = this.schema.options.discriminatorKey;
   if (schema.path(key)) {
     throw new Error('Discriminator "' + name +
-      '" cannot have field with name "' + key + '"');
+        '" cannot have field with name "' + key + '"');
   }
 
   // merges base schema into new discriminator schema and sets new type field.
@@ -794,7 +791,7 @@ Model.discriminator = function discriminator(name, schema) {
       schema.options.collection = baseSchema.options.collection;
     }
 
-      // throws error if options are invalid
+    // throws error if options are invalid
     (function (a, b) {
       a = utils.clone(a);
       b = utils.clone(b);
@@ -807,7 +804,7 @@ Model.discriminator = function discriminator(name, schema) {
 
       if (!utils.deepEqual(a, b)) {
         throw new Error('Discriminator options are not customizable ' +
-          '(except toJSON, toObject, _id)');
+            '(except toJSON, toObject, _id)');
       }
     })(schema.options, baseSchema.options);
 
@@ -1429,14 +1426,14 @@ Model.findOneAndUpdate = function (conditions, update, options, callback) {
   if (typeof options === 'function') {
     callback = options;
     options = null;
-  } else if (1 === arguments.length) {
+  } else if (arguments.length === 1) {
     if (typeof conditions === 'function') {
       var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\n\n'
-              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\n'
-              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\n'
-              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)\n'
-              + '  ' + this.modelName + '.findOneAndUpdate(update)\n'
-              + '  ' + this.modelName + '.findOneAndUpdate()\n';
+          + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\n'
+          + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\n'
+          + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)\n'
+          + '  ' + this.modelName + '.findOneAndUpdate(update)\n'
+          + '  ' + this.modelName + '.findOneAndUpdate()\n';
       throw new TypeError(msg);
     }
     update = conditions;
@@ -1534,28 +1531,23 @@ Model.findOneAndUpdate = function (conditions, update, options, callback) {
  */
 
 Model.findByIdAndUpdate = function (id, update, options, callback) {
-  var args;
-  if (1 === arguments.length) {
+  if (arguments.length === 1) {
     if (typeof id === 'function') {
       var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
-                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
-                + '  ' + this.modelName + '.findByIdAndUpdate(id)\n'
-                + '  ' + this.modelName + '.findByIdAndUpdate()\n';
+          + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
+          + '  ' + this.modelName + '.findByIdAndUpdate(id)\n'
+          + '  ' + this.modelName + '.findByIdAndUpdate()\n';
       throw new TypeError(msg);
     }
     return this.findOneAndUpdate({_id: id}, undefined);
   }
 
-  args = utils.args(arguments, 1);
-
   // if a model is passed in instead of an id
   if (id instanceof Document) {
     id = id._id;
   }
-  if (id) {
-    args.unshift({_id: id});
-  }
-  return this.findOneAndUpdate.apply(this, args);
+
+  return this.findOneAndUpdate.call(this, {_id: id}, update, options, callback);
 };
 
 /**
@@ -1606,11 +1598,11 @@ Model.findByIdAndUpdate = function (id, update, options, callback) {
  */
 
 Model.findOneAndRemove = function (conditions, options, callback) {
-  if (1 === arguments.length && typeof conditions === 'function') {
+  if (arguments.length === 1 && typeof conditions === 'function') {
     var msg = 'Model.findOneAndRemove(): First argument must not be a function.\n\n'
-              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)\n'
-              + '  ' + this.modelName + '.findOneAndRemove(conditions)\n'
-              + '  ' + this.modelName + '.findOneAndRemove()\n';
+        + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)\n'
+        + '  ' + this.modelName + '.findOneAndRemove(conditions)\n'
+        + '  ' + this.modelName + '.findOneAndRemove()\n';
     throw new TypeError(msg);
   }
 
@@ -1660,11 +1652,11 @@ Model.findOneAndRemove = function (conditions, options, callback) {
  */
 
 Model.findByIdAndRemove = function (id, options, callback) {
-  if (1 === arguments.length && typeof id === 'function') {
+  if (arguments.length === 1 && typeof id === 'function') {
     var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\n\n'
-              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)\n'
-              + '  ' + this.modelName + '.findByIdAndRemove(id)\n'
-              + '  ' + this.modelName + '.findByIdAndRemove()\n';
+        + '  ' + this.modelName + '.findByIdAndRemove(id, callback)\n'
+        + '  ' + this.modelName + '.findByIdAndRemove(id)\n'
+        + '  ' + this.modelName + '.findByIdAndRemove()\n';
     throw new TypeError(msg);
   }
 
@@ -2025,7 +2017,7 @@ Model.mapReduce = function mapReduce(o, callback) {
     }
 
     if (!o.out) o.out = {inline: 1};
-    if (false !== o.verbose) o.verbose = true;
+    if (o.verbose !== false) o.verbose = true;
 
     o.map = String(o.map);
     o.reduce = String(o.reduce);
@@ -2048,10 +2040,10 @@ Model.mapReduce = function mapReduce(o, callback) {
         // returned a collection, convert to Model
         var model = Model.compile(
             '_mapreduce_' + ret.collectionName
-          , Model.mapReduce.schema
-          , ret.collectionName
-          , _this.db
-          , _this.base);
+            , Model.mapReduce.schema
+            , ret.collectionName
+            , _this.db
+            , _this.base);
 
         model._mapreduce = true;
 
@@ -2155,7 +2147,7 @@ Model.geoNear = function (near, options, callback) {
     if (Array.isArray(near)) {
       if (near.length !== 2) {
         var error = new Error('If using legacy coordinates, must be an array ' +
-          'of size 2 for geoNear');
+            'of size 2 for geoNear');
         reject(error);
         callback && callback(error);
         return;
@@ -2166,7 +2158,7 @@ Model.geoNear = function (near, options, callback) {
     } else {
       if (near.type !== 'Point' || !Array.isArray(near.coordinates)) {
         error = new Error('Must pass either a legacy coordinate array or ' +
-          'GeoJSON Point to geoNear');
+            'GeoJSON Point to geoNear');
         reject(error);
         callback && callback(error);
         return;
@@ -2225,7 +2217,7 @@ Model.aggregate = function aggregate() {
     callback = args.pop();
   }
 
-  if (1 === args.length && util.isArray(args[0])) {
+  if (args.length === 1 && util.isArray(args[0])) {
     aggregate = new Aggregate(args[0]);
   } else {
     aggregate = new Aggregate(args);
@@ -2430,7 +2422,7 @@ Model.populate = function (docs, paths, cb) {
 function _populate(model, docs, paths, cb) {
   var pending = paths.length;
 
-  if (0 === pending) {
+  if (pending === 0) {
     return cb(null, docs);
   }
 
@@ -2501,9 +2493,9 @@ function subPopulate(docs, options, cb) {
       if (typeof subOptions.model === 'string') {
         subOptions.model = _this.model(subOptions.model);
       } else if (schema && schema.caster && schema.caster.options &&
-        schema.caster.options.ref) {
+          schema.caster.options.ref) {
         var subSchema = _this.model(schema.caster.options.ref).schema.
-          _getSchema(subOptions._originalPath);
+        _getSchema(subOptions._originalPath);
         if (subSchema && subSchema.options && subSchema.options.ref) {
           subOptions.model = _this.model(subSchema.options.ref);
         }
@@ -2527,7 +2519,7 @@ function populate(model, docs, options, cb) {
     docs = [docs];
   }
 
-  if (0 === docs.length || docs.every(utils.isNullOrUndefined)) {
+  if (docs.length === 0 || docs.every(utils.isNullOrUndefined)) {
     return cb();
   }
 
@@ -2586,7 +2578,7 @@ function populate(model, docs, options, cb) {
 
     ids = utils.array.unique(ids);
 
-    if (0 === ids.length || ids.every(utils.isNullOrUndefined)) {
+    if (ids.length === 0 || ids.every(utils.isNullOrUndefined)) {
       return cb();
     }
 
@@ -2596,7 +2588,7 @@ function populate(model, docs, options, cb) {
 
     var assignmentOpts = {};
     assignmentOpts.sort = mod.options.options && mod.options.options.sort || undefined;
-    assignmentOpts.excludeId = excludeIdReg.test(select) || (select && 0 === select._id);
+    assignmentOpts.excludeId = excludeIdReg.test(select) || (select && select._id === 0);
 
     if (assignmentOpts.excludeId) {
       // override the exclusion from the query so we can use the _id
@@ -2735,7 +2727,7 @@ function getIdsForAndAddIdsInMapPopulate(modelsMap) {
       id = String(utils.getValue('_id', doc));
       isDocument = !!doc.$__;
 
-      if (!ret || Array.isArray(ret) && 0 === ret.length) {
+      if (!ret || Array.isArray(ret) && ret.length === 0) {
         ret = utils.getValue(path, doc);
       }
 
@@ -2869,7 +2861,7 @@ function valueFilter(val, assignmentOpts) {
 
 function maybeRemoveId(subdoc, assignmentOpts) {
   if (assignmentOpts.excludeId) {
-    if ('function' === typeof subdoc.setValue) {
+    if (typeof subdoc.setValue === 'function') {
       delete subdoc._doc._id;
     } else {
       delete subdoc._id;
@@ -2883,7 +2875,7 @@ function maybeRemoveId(subdoc, assignmentOpts) {
  */
 
 function isDoc(doc) {
-  if (null == doc) {
+  if (doc == null) {
     return false;
   }
 
@@ -2946,7 +2938,7 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
       continue;
     }
 
-    if (null === id && !sorting) {
+    if (id === null && !sorting) {
       // keep nulls for findOne unless sorting, which always
       // removes them (backward compat)
       newOrder.push(id);
@@ -3013,7 +3005,7 @@ Model._getSchema = function _getSchema(path) {
  */
 
 Model.compile = function compile(name, schema, collectionName, connection, base) {
-  var versioningEnabled = false !== schema.options.versionKey;
+  var versioningEnabled = schema.options.versionKey !== false;
 
   if (versioningEnabled && !schema.paths[schema.options.versionKey]) {
     // add versioning to top level documents only
@@ -3048,7 +3040,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
 
   model.prototype.collection = connection.collection(
       collectionName
-    , collectionOptions
+      , collectionOptions
   );
 
   // apply methods and statics
@@ -3124,14 +3116,14 @@ Model.__subclass = function subclass(conn, schema, collection) {
   Model.db = Model.prototype.db = conn;
 
   var s = schema && typeof schema !== 'string'
-    ? schema
-    : _this.prototype.schema;
+      ? schema
+      : _this.prototype.schema;
 
   var options = s.options || {};
 
   if (!collection) {
     collection = _this.prototype.schema.get('collection')
-              || utils.toCollectionName(_this.modelName, options);
+        || utils.toCollectionName(_this.modelName, options);
   }
 
   var collectionOptions = {
diff --git a/lib/query.js b/lib/query.js
index ac601b74adb..ffd4df806aa 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -1,5 +1,3 @@
-/* eslint no-unused-vars: 1 */
-
 /*!
  * Module dependencies.
  */
@@ -11,7 +9,6 @@ var PromiseProvider = require('./promise_provider');
 var updateValidators = require('./services/updateValidators');
 var utils = require('./utils');
 var helpers = require('./queryhelpers');
-var Document = require('./document');
 var QueryStream = require('./querystream');
 var StrictModeError = require('./error/strict');
 var cast = require('./cast');
@@ -73,17 +70,17 @@ function Query(conditions, options, model, collection) {
 
   if (this.schema) {
     this._count = this.model.hooks.createWrapper('count',
-      Query.prototype._count, this);
+        Query.prototype._count, this);
     this._execUpdate = this.model.hooks.createWrapper('update',
-      Query.prototype._execUpdate, this);
+        Query.prototype._execUpdate, this);
     this._find = this.model.hooks.createWrapper('find',
-      Query.prototype._find, this);
+        Query.prototype._find, this);
     this._findOne = this.model.hooks.createWrapper('findOne',
-      Query.prototype._findOne, this);
+        Query.prototype._findOne, this);
     this._findOneAndRemove = this.model.hooks.createWrapper('findOneAndRemove',
-      Query.prototype._findOneAndRemove, this);
+        Query.prototype._findOneAndRemove, this);
     this._findOneAndUpdate = this.model.hooks.createWrapper('findOneAndUpdate',
-      Query.prototype._findOneAndUpdate, this);
+        Query.prototype._findOneAndUpdate, this);
   }
 }
 
@@ -822,7 +819,7 @@ Query.prototype.toConstructor = function toConstructor() {
 
 Query.prototype.read = function read(pref, tags) {
   // first cast into a ReadPreference object to support tags
-  var read = readPref.apply(readPref, arguments);
+  var read = readPref.call(readPref, pref, tags);
   return Query.base.read.call(this, read);
 };
 
@@ -1039,18 +1036,18 @@ Query.prototype._find = function (callback) {
     }
 
     if (!options.populate) {
-      return true === options.lean
-        ? callback(null, docs)
-        : completeMany(_this.model, docs, fields, _this, null, callback);
+      return options.lean === true
+          ? callback(null, docs)
+          : completeMany(_this.model, docs, fields, _this, null, callback);
     }
 
     var pop = helpers.preparePopulationOptionsMQ(_this, options);
     pop.__noPromise = true;
     _this.model.populate(docs, pop, function (err, docs) {
       if (err) return callback(err);
-      return true === options.lean
-        ? callback(null, docs)
-        : completeMany(_this.model, docs, fields, _this, pop, callback);
+      return options.lean === true
+          ? callback(null, docs)
+          : completeMany(_this.model, docs, fields, _this, pop, callback);
     });
   };
 
@@ -1119,8 +1116,8 @@ function completeMany(model, docs, fields, self, pop, callback) {
   var count = docs.length;
   var len = count;
   var opts = pop ?
-    {populated: pop}
-    : undefined;
+  {populated: pop}
+      : undefined;
   for (var i = 0; i < len; ++i) {
     arr[i] = helpers.createModel(model, docs[i], fields);
     arr[i].init(docs[i], opts, function (err) {
@@ -1160,9 +1157,9 @@ Query.prototype._findOne = function (callback) {
     }
 
     if (!options.populate) {
-      return true === options.lean
-        ? callback(null, doc)
-        : completeOne(_this.model, doc, null, projection, _this, null, callback);
+      return options.lean === true
+          ? callback(null, doc)
+          : completeOne(_this.model, doc, null, projection, _this, null, callback);
     }
 
     var pop = helpers.preparePopulationOptionsMQ(_this, options);
@@ -1172,9 +1169,9 @@ Query.prototype._findOne = function (callback) {
         return callback(err);
       }
 
-      return true === options.lean
-        ? callback(null, doc)
-        : completeOne(_this.model, doc, null, projection, _this, pop, callback);
+      return options.lean === true
+          ? callback(null, doc)
+          : completeOne(_this.model, doc, null, projection, _this, pop, callback);
     });
   });
 };
@@ -1494,8 +1491,8 @@ Query.prototype.remove = function (cond, callback) {
 
 function completeOne(model, doc, res, fields, self, pop, callback) {
   var opts = pop ?
-    {populated: pop}
-    : undefined;
+  {populated: pop}
+      : undefined;
 
   var casted = helpers.createModel(model, doc, fields);
   casted.init(doc, opts, function (err) {
@@ -1804,9 +1801,9 @@ Query.prototype._findAndModify = function (type, callback) {
     }
 
     if (!options.populate) {
-      return true === options.lean
-        ? callback(null, doc)
-        : completeOne(_this.model, doc, res, fields, _this, null, callback);
+      return options.lean === true
+          ? callback(null, doc)
+          : completeOne(_this.model, doc, res, fields, _this, null, callback);
     }
 
     var pop = helpers.preparePopulationOptionsMQ(_this, options);
@@ -1816,9 +1813,9 @@ Query.prototype._findAndModify = function (type, callback) {
         return callback(err);
       }
 
-      return true === options.lean
-        ? callback(null, doc)
-        : completeOne(_this.model, doc, res, fields, _this, pop, callback);
+      return options.lean === true
+          ? callback(null, doc)
+          : completeOne(_this.model, doc, res, fields, _this, pop, callback);
     });
   };
 
@@ -2075,7 +2072,7 @@ Query.prototype.update = function (conditions, doc, options, callback) {
       $options.minimize = true;
     }
     castedDoc = this._castUpdate(utils.clone(doc, $options),
-      options && options.overwrite);
+        options && options.overwrite);
   } catch (err) {
     this._castError = castedQuery;
     if (callback) {
@@ -2227,7 +2224,7 @@ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) {
   while (i--) {
     var op = ops[i];
     // if overwrite is set, don't do any of the special $set stuff
-    if ('$' !== op[0] && !overwrite) {
+    if (op[0] !== '$' && !overwrite) {
       // fix up $set sugar
       if (!ret.$set) {
         if (obj.$set) {
@@ -2239,7 +2236,7 @@ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) {
       ret.$set[op] = obj[op];
       ops.splice(i, 1);
       if (!~ops.indexOf('$set')) ops.push('$set');
-    } else if ('$set' === op) {
+    } else if (op === '$set') {
       if (!ret.$set) {
         ret[op] = obj[op];
       }
@@ -2275,7 +2272,7 @@ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) {
       this._walkUpdatePath(ret, '$set');
     } else {
       var msg = 'Invalid atomic update value for ' + op + '. '
-              + 'Expected an object, received ' + typeof val;
+          + 'Expected an object, received ' + typeof val;
       throw new Error(msg);
     }
   }
@@ -2304,8 +2301,8 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) {
       val;
 
   var strict = 'strict' in this._mongooseOptions
-    ? this._mongooseOptions.strict
-    : this.model.schema.options.strict;
+      ? this._mongooseOptions.strict
+      : this.model.schema.options.strict;
 
   while (i--) {
     key = keys[i];
@@ -2365,16 +2362,16 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) {
         // we should be able to set a schema-less field
         // to an empty object literal
         hasKeys |= this._walkUpdatePath(val, op, prefix + key) ||
-                   (utils.isObject(val) && Object.keys(val).length === 0);
+            (utils.isObject(val) && Object.keys(val).length === 0);
       }
     } else {
-      schema = ('$each' === key || '$or' === key || '$and' === key)
-        ? this._getSchema(pref)
-        : this._getSchema(prefix + key);
+      schema = (key === '$each' || key === '$or' || key === '$and')
+          ? this._getSchema(pref)
+          : this._getSchema(prefix + key);
 
       var skip = strict &&
-                 !schema &&
-                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
+          !schema &&
+          !/real|nested/.test(this.model.schema.pathType(prefix + key));
 
       if (skip) {
         if (strict === 'throw') {
@@ -2412,12 +2409,12 @@ Query.prototype._castUpdateVal = function _castUpdateVal(schema, val, op, $condi
   if (!schema) {
     // non-existing schema path
     return op in numberOps
-      ? Number(val)
-      : val;
+        ? Number(val)
+        : val;
   }
 
   var cond = schema.caster && op in castOps &&
-    (utils.isObject(val) || Array.isArray(val));
+      (utils.isObject(val) || Array.isArray(val));
   if (cond) {
     // Cast values for ops that add data to MongoDB.
     // Ensures embedded documents get ObjectIds etc.
@@ -2616,8 +2613,8 @@ Query.prototype._applyPaths = function applyPaths() {
     ki = keys.length;
 
     while (ki--) {
-      if ('+' === keys[ki][0]) continue;
-      exclude = 0 === fields[keys[ki]];
+      if (keys[ki][0] === '+') continue;
+      exclude = fields[keys[ki]] === 0;
       break;
     }
   }
@@ -2639,7 +2636,7 @@ Query.prototype._applyPaths = function applyPaths() {
 
       // if there are other fields being included, add this one
       // if no other included fields, leave this out (implied inclusion)
-      if (false === exclude && keys.length > 1 && !~keys.indexOf(path)) {
+      if (exclude === false && keys.length > 1 && !~keys.indexOf(path)) {
         fields[path] = 1;
       }
 
diff --git a/lib/querystream.js b/lib/querystream.js
index ca62194e4a9..c7220d35705 100644
--- a/lib/querystream.js
+++ b/lib/querystream.js
@@ -230,7 +230,7 @@ QueryStream.prototype._onNextObject = function _onNextObject(err, doc) {
   var opts = this.query._mongooseOptions;
 
   if (!opts.populate) {
-    return true === opts.lean ?
+    return opts.lean === true ?
         emit(this, doc) :
         createAndEmit(this, null, doc);
   }
@@ -248,7 +248,7 @@ QueryStream.prototype._onNextObject = function _onNextObject(err, doc) {
     if (err) {
       return _this.destroy(err);
     }
-    return true === opts.lean ?
+    return opts.lean === true ?
         emit(_this, doc) :
         createAndEmit(_this, pop, doc);
   });
diff --git a/lib/schema.js b/lib/schema.js
index 9c88b7f49ce..60ff6f599cc 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -175,7 +175,7 @@ function idGetter() {
     return this.$__._id;
   }
 
-  this.$__._id = null == this._id
+  this.$__._id = this._id == null
       ? null
       : String(this._id);
   return this.$__._id;
@@ -313,11 +313,11 @@ Schema.prototype.tree;
  */
 
 Schema.prototype.defaultOptions = function (options) {
-  if (options && false === options.safe) {
+  if (options && options.safe === false) {
     options.safe = {w: 0};
   }
 
-  if (options && options.safe && 0 === options.safe.w) {
+  if (options && options.safe && options.safe.w === 0) {
     // if you turn off safe writes, then versioning goes off as well
     options.versionKey = false;
   }
@@ -368,16 +368,16 @@ Schema.prototype.add = function add(obj, prefix) {
   for (var i = 0; i < keys.length; ++i) {
     var key = keys[i];
 
-    if (null == obj[key]) {
+    if (obj[key] == null) {
       throw new TypeError('Invalid value for schema path `' + prefix + key + '`');
     }
 
-    if (Array.isArray(obj[key]) && obj[key].length === 1 && null == obj[key][0]) {
+    if (Array.isArray(obj[key]) && obj[key].length === 1 && obj[key][0] == null) {
       throw new TypeError('Invalid value for schema Array path `' + prefix + key + '`');
     }
 
     if (utils.isObject(obj[key]) &&
-        (!obj[key].constructor || 'Object' === utils.getFunctionName(obj[key].constructor)) &&
+        (!obj[key].constructor || utils.getFunctionName(obj[key].constructor) === 'Object') &&
         (!obj[key][this.options.typeKey] || (this.options.typeKey === 'type' && obj[key].type.type))) {
       if (Object.keys(obj[key]).length) {
         // nested object { last: { name: String }}
@@ -542,7 +542,7 @@ Schema.interpretAsType = function (path, obj, options) {
       ? obj[options.typeKey]
       : {};
 
-  if ('Object' === utils.getFunctionName(type.constructor) || type === 'mixed') {
+  if (utils.getFunctionName(type.constructor) === 'Object' || type === 'mixed') {
     return new MongooseTypes.Mixed(path, obj);
   }
 
@@ -559,7 +559,7 @@ Schema.interpretAsType = function (path, obj, options) {
     if (typeof cast === 'string') {
       cast = MongooseTypes[cast.charAt(0).toUpperCase() + cast.substring(1)];
     } else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type))
-        && 'Object' === utils.getFunctionName(cast.constructor)
+        && utils.getFunctionName(cast.constructor) === 'Object'
         && Object.keys(cast).length) {
       // The `minimize` and `typeKey` options propagate to child schemas
       // declared inline, like `{ arr: [{ val: { $type: String } }] }`.
@@ -1011,7 +1011,7 @@ Schema.prototype.index = function (fields, options) {
  */
 
 Schema.prototype.set = function (key, value, _tags) {
-  if (1 === arguments.length) {
+  if (arguments.length === 1) {
     return this.options[key];
   }
 
@@ -1020,7 +1020,7 @@ Schema.prototype.set = function (key, value, _tags) {
       this.options[key] = readPref(value, _tags);
       break;
     case 'safe':
-      this.options[key] = false === value
+      this.options[key] = value === false
           ? {w: 0}
           : value;
       break;
@@ -1092,7 +1092,7 @@ Schema.prototype.indexes = function () {
       } else {
         index = path._index;
 
-        if (false !== index && null !== index) {
+        if (index !== false && index !== null) {
           field = {};
           isObject = utils.isObject(index);
           options = isObject ? index : {};
@@ -1252,7 +1252,7 @@ Schema.prototype._getSchema = function (path) {
           // If there is no foundschema.schema we are dealing with
           // a path like array.$
           if (p !== parts.length && foundschema.schema) {
-            if ('$' === parts[p]) {
+            if (parts[p] === '$') {
               // comments.$.comments.$.title
               return search(parts.slice(p + 1), foundschema.schema);
             }
diff --git a/lib/schema/array.js b/lib/schema/array.js
index b33bea42416..99a043ba39e 100644
--- a/lib/schema/array.js
+++ b/lib/schema/array.js
@@ -33,7 +33,7 @@ function SchemaArray(key, cast, options) {
   if (cast) {
     var castOptions = {};
 
-    if ('Object' === utils.getFunctionName(cast.constructor)) {
+    if (utils.getFunctionName(cast.constructor) === 'Object') {
       if (cast.type) {
         // support { type: Woot }
         castOptions = utils.clone(cast); // do not alter user arguments
@@ -135,7 +135,7 @@ SchemaArray.prototype.cast = function (value, doc, init) {
 
       for (var i = 0, l = indexes.length; i < l; ++i) {
         var pathIndex = indexes[i][0][this.path];
-        if ('2dsphere' === pathIndex || pathIndex === '2d') {
+        if (pathIndex === '2dsphere' || pathIndex === '2d') {
           return;
         }
       }
diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js
index 30d83a2ddb5..fae2382da77 100644
--- a/lib/schema/boolean.js
+++ b/lib/schema/boolean.js
@@ -51,7 +51,7 @@ SchemaBoolean.prototype.checkRequired = function (value) {
  */
 
 SchemaBoolean.prototype.cast = function (value) {
-  if (null === value) {
+  if (value === null) {
     return value;
   }
   if (value === '0') {
@@ -79,7 +79,7 @@ SchemaBoolean.$conditionalHandlers =
 
 SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
   var handler;
-  if (2 === arguments.length) {
+  if (arguments.length === 2) {
     handler = SchemaBoolean.$conditionalHandlers[$conditional];
 
     if (handler) {
diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js
index ce83728b485..e976c5bb7e4 100644
--- a/lib/schema/buffer.js
+++ b/lib/schema/buffer.js
@@ -120,12 +120,12 @@ SchemaBuffer.prototype.cast = function (value, doc, init) {
     return ret;
   }
 
-  if (null === value) {
+  if (value === null) {
     return value;
   }
 
   var type = typeof value;
-  if ('string' === type || 'number' === type || Array.isArray(value)) {
+  if (type === 'string' || type === 'number' || Array.isArray(value)) {
     if (type === 'number') {
       value = [value];
     }
diff --git a/lib/schema/date.js b/lib/schema/date.js
index 158afbd8383..09fcb5b95d3 100644
--- a/lib/schema/date.js
+++ b/lib/schema/date.js
@@ -68,7 +68,7 @@ SchemaDate.prototype.constructor = SchemaDate;
  */
 
 SchemaDate.prototype.expires = function (when) {
-  if (!this._index || 'Object' !== this._index.constructor.name) {
+  if (!this._index || this._index.constructor.name !== 'Object') {
     this._index = {};
   }
 
@@ -264,7 +264,7 @@ SchemaDate.prototype.$conditionalHandlers =
 SchemaDate.prototype.castForQuery = function ($conditional, val) {
   var handler;
 
-  if (2 !== arguments.length) {
+  if (arguments.length !== 2) {
     return this.cast($conditional);
   }
 
diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js
index a984da69966..2d46993e032 100644
--- a/lib/schema/documentarray.js
+++ b/lib/schema/documentarray.js
@@ -277,7 +277,7 @@ function scopePaths(array, fields, init) {
 
   while (i--) {
     key = keys[i];
-    if (0 === key.indexOf(path)) {
+    if (key.indexOf(path) === 0) {
       hasKeys || (hasKeys = true);
       selected[key.substring(path.length)] = fields[key];
     }
diff --git a/lib/schema/mixed.js b/lib/schema/mixed.js
index f1949356851..6b2576af8e7 100644
--- a/lib/schema/mixed.js
+++ b/lib/schema/mixed.js
@@ -17,10 +17,10 @@ var utils = require('../utils');
 function Mixed(path, options) {
   if (options && options.default) {
     var def = options.default;
-    if (Array.isArray(def) && 0 === def.length) {
+    if (Array.isArray(def) && def.length === 0) {
       // make sure empty array defaults are handled
       options.default = Array;
-    } else if (!options.shared && utils.isObject(def) && 0 === Object.keys(def).length) {
+    } else if (!options.shared && utils.isObject(def) && Object.keys(def).length === 0) {
       // prevent odd "shared" objects between documents
       options.default = function () {
         return {};
diff --git a/lib/schema/number.js b/lib/schema/number.js
index d4f6276a8e4..8659da0170b 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -87,7 +87,7 @@ SchemaNumber.prototype.min = function (value, message) {
     }, this);
   }
 
-  if (null != value) {
+  if (value !== null && value !== void 0) {
     var msg = message || errorMessages.Number.min;
     msg = msg.replace(/{MIN}/, value);
     this.validators.push({
@@ -141,7 +141,7 @@ SchemaNumber.prototype.max = function (value, message) {
     }, this);
   }
 
-  if (value != null) {
+  if (value !== null && value !== void 0) {
     var msg = message || errorMessages.Number.max;
     msg = msg.replace(/{MAX}/, value);
     this.validators.push({
@@ -205,10 +205,10 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
       : value;
 
   if (!isNaN(val)) {
-    if (null === val) {
+    if (val === null) {
       return val;
     }
-    if ('' === val) {
+    if (val === '') {
       return null;
     }
     if (typeof val === 'string' || typeof val === 'boolean') {
@@ -220,8 +220,7 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
     if (typeof val === 'number') {
       return val;
     }
-    if (val.toString && !Array.isArray(val) &&
-        val.toString() == Number(val)) {
+    if (val.toString && !Array.isArray(val) && val.toString() == Number(val)) {
       return new Number(val);
     }
   }
diff --git a/lib/schema/string.js b/lib/schema/string.js
index 696885ff67c..84710717f78 100644
--- a/lib/schema/string.js
+++ b/lib/schema/string.js
@@ -80,7 +80,7 @@ SchemaString.prototype.enum = function () {
     this.enumValidator = false;
   }
 
-  if (undefined === arguments[0] || false === arguments[0]) {
+  if (arguments[0] === void 0 || arguments[0] === false) {
     return this;
   }
 
@@ -235,7 +235,7 @@ SchemaString.prototype.minlength = function (value, message) {
     }, this);
   }
 
-  if (null !== value) {
+  if (value !== null) {
     var msg = message || errorMessages.String.minlength;
     msg = msg.replace(/{MINLENGTH}/, value);
     this.validators.push({
@@ -353,7 +353,7 @@ SchemaString.prototype.match = function match(regExp, message) {
       return false;
     }
 
-    var ret = ((null != v && '' !== v)
+    var ret = ((v != null && v !== '')
         ? regExp.test(v)
         : true);
     return ret;
diff --git a/lib/schematype.js b/lib/schematype.js
index 71a32eab11a..76e78ebbd63 100644
--- a/lib/schematype.js
+++ b/lib/schematype.js
@@ -30,7 +30,7 @@ function SchemaType(path, options, instance) {
   for (var i in options) {
     if (this[i] && typeof this[i] === 'function') {
       // { unique: true, index: true }
-      if ('index' === i && this._index) {
+      if (i === 'index' && this._index) {
         continue;
       }
 
@@ -87,7 +87,7 @@ function SchemaType(path, options, instance) {
  */
 
 SchemaType.prototype.default = function (val) {
-  if (1 === arguments.length) {
+  if (arguments.length === 1) {
     this.defaultValue = typeof val === 'function'
         ? val
         : this.cast(val);
@@ -145,7 +145,7 @@ SchemaType.prototype.index = function (options) {
  */
 
 SchemaType.prototype.unique = function (bool) {
-  if (null === this._index || typeof this._index === 'boolean') {
+  if (this._index === null || typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
@@ -168,7 +168,7 @@ SchemaType.prototype.unique = function (bool) {
  */
 
 SchemaType.prototype.text = function (bool) {
-  if (null === this._index || typeof this._index === 'boolean') {
+  if (this._index === null || typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
@@ -192,7 +192,7 @@ SchemaType.prototype.text = function (bool) {
  */
 
 SchemaType.prototype.sparse = function (bool) {
-  if (null === this._index || typeof this._index === 'boolean') {
+  if (this._index === null || typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
@@ -436,7 +436,7 @@ SchemaType.prototype.get = function (fn) {
  */
 
 SchemaType.prototype.validate = function (obj, message, type) {
-  if (typeof obj === 'function' || obj && 'RegExp' === utils.getFunctionName(obj.constructor)) {
+  if (typeof obj === 'function' || obj && utils.getFunctionName(obj.constructor) === 'RegExp') {
     var properties;
     if (message instanceof Object && !type) {
       properties = utils.clone(message);
@@ -464,7 +464,7 @@ SchemaType.prototype.validate = function (obj, message, type) {
 
   for (i = 0, length = arguments.length; i < length; i++) {
     arg = arguments[i];
-    if (!(arg && 'Object' === utils.getFunctionName(arg.constructor))) {
+    if (!(arg && utils.getFunctionName(arg.constructor) === 'Object')) {
       var msg = 'Invalid validator. Received (' + typeof arg + ') '
           + arg
           + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
@@ -506,7 +506,7 @@ SchemaType.prototype.validate = function (obj, message, type) {
  */
 
 SchemaType.prototype.required = function (required, message) {
-  if (false === required) {
+  if (required === false) {
     this.validators = this.validators.filter(function (v) {
       return v.validator !== this.requiredValidator;
     }, this);
@@ -557,7 +557,7 @@ SchemaType.prototype.getDefault = function (scope, init) {
       ? this.defaultValue.call(scope)
       : this.defaultValue;
 
-  if (null !== ret && undefined !== ret) {
+  if (ret !== null && undefined !== ret) {
     return this.cast(ret, scope, init);
   }
   return ret;
@@ -590,7 +590,7 @@ SchemaType.prototype.applySetters = function (value, scope, init, priorVal, opti
     v = newVal;
   }
 
-  if (null === v || undefined === v) {
+  if (v === null || v === void 0) {
     return v;
   }
 
@@ -695,7 +695,7 @@ SchemaType.prototype.doValidate = function (value, fn, scope) {
         validate(true, validatorProperties);
         return;
       }
-      if (2 === validator.length) {
+      if (validator.length === 2) {
         validator.call(scope, value, function (ok, customMsg) {
           if (customMsg) {
             validatorProperties.message = customMsg;
@@ -759,7 +759,7 @@ SchemaType.prototype.doValidateSync = function (value, scope) {
       validate(validator.test(value), validatorProperties);
     } else if (typeof validator === 'function') {
       // if not async validators
-      if (2 !== validator.length) {
+      if (validator.length !== 2) {
         validate(validator.call(scope, value), validatorProperties);
       }
     }
@@ -793,11 +793,11 @@ SchemaType._isRef = function (self, value, doc, init) {
   }
 
   if (ref) {
-    if (null == value) {
+    if (value == null) {
       return true;
     }
     if (!Buffer.isBuffer(value) &&  // buffers are objects too
-        'Binary' !== value._bsontype // raw binary value from the db
+        value._bsontype !== 'Binary' // raw binary value from the db
         && utils.isObject(value)    // might have deselected _id in population query
     ) {
       return true;
@@ -834,11 +834,11 @@ function handleArray(val) {
  */
 
 SchemaType.prototype.$conditionalHandlers = {
-  '$all': handleArray,
-  '$eq': handleSingle,
-  '$in': handleArray,
-  '$ne': handleSingle,
-  '$nin': handleArray
+  $all: handleArray,
+  $eq: handleSingle,
+  $in: handleArray,
+  $ne: handleSingle,
+  $nin: handleArray
 };
 
 /**
diff --git a/lib/types/array.js b/lib/types/array.js
index cea257cae95..faa8a97699e 100644
--- a/lib/types/array.js
+++ b/lib/types/array.js
@@ -106,7 +106,7 @@ MongooseArray.mixin = {
       populated = owner.populated(this._path, true);
     }
 
-    if (populated && null !== value) {
+    if (populated && value !== null) {
       // cast to the populated Models schema
       Model = populated.options.model;
 
@@ -150,7 +150,7 @@ MongooseArray.mixin = {
       dirtyPath = this._path;
 
       if (arguments.length) {
-        if (null != embeddedPath) {
+        if (embeddedPath != null) {
           // an embedded doc bubbled up the change
           dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
         } else {
@@ -176,7 +176,7 @@ MongooseArray.mixin = {
    */
 
   _registerAtomic: function (op, val) {
-    if ('$set' === op) {
+    if (op === '$set') {
       // $set takes precedence over all other ops.
       // mark entire array modified.
       this._atomics = {$set: val};
@@ -186,7 +186,7 @@ MongooseArray.mixin = {
     var atomics = this._atomics;
 
     // reset pop/shift after save
-    if ('$pop' === op && !('$pop' in atomics)) {
+    if (op === '$pop' && !('$pop' in atomics)) {
       var _this = this;
       this._parent.once('save', function () {
         _this._popped = _this._shifted = null;
@@ -242,7 +242,7 @@ MongooseArray.mixin = {
     var keys = Object.keys(this._atomics);
     var i = keys.length;
 
-    if (0 === i) {
+    if (i === 0) {
       ret[0] = ['$set', this.toObject({depopulate: 1, transform: false})];
       return ret;
     }
@@ -262,7 +262,7 @@ MongooseArray.mixin = {
         val = val.valueOf();
       }
 
-      if ('$addToSet' === op) {
+      if (op === '$addToSet') {
         val = {$each: val};
       }
 
@@ -522,7 +522,9 @@ MongooseArray.mixin = {
     while (i--) {
       mem = cur[i];
       if (mem instanceof Document) {
-        if (values.some(function (v) {return v.equals(mem);})) {
+        if (values.some(function (v) {
+              return v.equals(mem);
+            })) {
           [].splice.call(cur, i, 1);
         }
       } else if (~cur.indexOf.call(values, mem)) {
diff --git a/lib/types/buffer.js b/lib/types/buffer.js
index b9f518bf07b..e8e81fe7fb7 100644
--- a/lib/types/buffer.js
+++ b/lib/types/buffer.js
@@ -22,7 +22,7 @@ function MongooseBuffer(value, encode, offset) {
   var length = arguments.length;
   var val;
 
-  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
+  if (length === 0 || arguments[0] === null || arguments[0] === void 0) {
     val = 0;
   } else {
     val = value;
diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js
index 8579a87636d..ae3de043167 100644
--- a/lib/types/documentarray.js
+++ b/lib/types/documentarray.js
@@ -100,7 +100,7 @@ MongooseDocumentArray.mixin = {
     // only objects are permitted so we can safely assume that
     // non-objects are to be interpreted as _id
     if (Buffer.isBuffer(value) ||
-      value instanceof ObjectId || !utils.isObject(value)) {
+        value instanceof ObjectId || !utils.isObject(value)) {
       value = {_id: value};
     }
     return new this._schema.casterConstructor(value, this, undefined, undefined, index);
@@ -128,7 +128,9 @@ MongooseDocumentArray.mixin = {
 
     try {
       var casted_ = ObjectIdSchema.prototype.cast.call({}, id);
-      if (casted_) casted = String(casted_);
+      if (casted_) {
+        casted = String(casted_);
+      }
     } catch (e) {
       casted = null;
     }
@@ -140,9 +142,13 @@ MongooseDocumentArray.mixin = {
         continue;
       } else if (_id instanceof Document) {
         sid || (sid = String(id));
-        if (sid == _id._id) return this[i];
+        if (sid == _id._id) {
+          return this[i];
+        }
       } else if (!(_id instanceof ObjectId)) {
-        if (utils.deepEqual(id, _id)) return this[i];
+        if (utils.deepEqual(id, _id)) {
+          return this[i];
+        }
       } else if (casted == _id) {
         return this[i];
       }
@@ -213,7 +219,9 @@ MongooseDocumentArray.mixin = {
     return function notify(val) {
       var i = _this.length;
       while (i--) {
-        if (!_this[i]) continue;
+        if (!_this[i]) {
+          continue;
+        }
         switch (event) {
           // only swap for save event for now, we may change this to all event types later
           case 'save':
diff --git a/lib/types/embedded.js b/lib/types/embedded.js
index a243971a91b..1a85874b3e3 100644
--- a/lib/types/embedded.js
+++ b/lib/types/embedded.js
@@ -91,6 +91,28 @@ EmbeddedDocument.prototype.save = function (fn) {
   });
 };
 
+/*!
+ * Registers remove event listeners for triggering
+ * on subdocuments.
+ *
+ * @param {EmbeddedDocument} sub
+ * @api private
+ */
+
+function registerRemoveListener(sub) {
+  var owner = sub.ownerDocument();
+
+  function emitRemove() {
+    owner.removeListener('save', emitRemove);
+    owner.removeListener('remove', emitRemove);
+    sub.emit('remove', sub);
+    owner = sub = null;
+  }
+
+  owner.on('save', emitRemove);
+  owner.on('remove', emitRemove);
+}
+
 /**
  * Removes the subdocument from its parent array.
  *
@@ -122,28 +144,6 @@ EmbeddedDocument.prototype.remove = function (fn) {
   return this;
 };
 
-/*!
- * Registers remove event listeners for triggering
- * on subdocuments.
- *
- * @param {EmbeddedDocument} sub
- * @api private
- */
-
-function registerRemoveListener(sub) {
-  var owner = sub.ownerDocument();
-
-  owner.on('save', emitRemove);
-  owner.on('remove', emitRemove);
-
-  function emitRemove() {
-    owner.removeListener('save', emitRemove);
-    owner.removeListener('remove', emitRemove);
-    sub.emit('remove', sub);
-    owner = sub = emitRemove = null;
-  }
-}
-
 /**
  * Override #update method of parent documents.
  * @api private
diff --git a/lib/utils.js b/lib/utils.js
index 8ff81acba56..a3224810b4f 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -21,10 +21,10 @@ var Document;
 
 exports.toCollectionName = function (name, options) {
   options = options || {};
-  if ('system.profile' === name) {
+  if (name === 'system.profile') {
     return name;
   }
-  if ('system.indexes' === name) {
+  if (name === 'system.indexes') {
     return name;
   }
   if (options.pluralization === false) {
@@ -456,7 +456,7 @@ exports.isObject = function (arg) {
   if (Buffer.isBuffer(arg)) {
     return true;
   }
-  return '[object Object]' === toString.call(arg);
+  return toString.call(arg) === '[object Object]';
 };
 
 /*!
@@ -571,7 +571,7 @@ exports.populate = function populate(path, select, model, match, options, subPop
   // an array, string, or object literal).
 
   // might have passed an object specifying all arguments
-  if (1 === arguments.length) {
+  if (arguments.length === 1) {
     if (path instanceof PopulateOptions) {
       return [path];
     }
@@ -682,7 +682,7 @@ exports.object.hasOwnProperty = function (obj, prop) {
  */
 
 exports.isNullOrUndefined = function (val) {
-  return null == val;
+  return val === null || val === void 0;
 };
 
 /*!
diff --git a/static.js b/static.js
index f99bf857ec1..596c4aa6dd0 100644
--- a/static.js
+++ b/static.js
@@ -4,7 +4,7 @@ var server = new static.Server('.', {cache: 0});
 var open = require('open');
 
 require('http').createServer(function (req, res) {
-  if ('/favicon.ico' === req.url) {
+  if (req.url === '/favicon.ico') {
     req.destroy();
     res.statusCode = 204;
     return res.end();
diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index bb55362b94f..4ec5e100d7f 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -80,8 +80,8 @@ describe('aggregate: ', function () {
     });
 
     it('throws if non-operator parameter is passed', function (done) {
-      var aggregate = new Aggregate(),
-          regexp = /Arguments must be aggregate pipeline operators/;
+      var aggregate = new Aggregate();
+      var regexp = /Arguments must be aggregate pipeline operators/;
 
       assert.throws(function () {
         aggregate.append({$a: 1}, 'string');
@@ -325,7 +325,7 @@ describe('aggregate: ', function () {
         aggregate.exec();
       }, /Cannot read property 'aggregate' of undefined|Cannot call method 'aggregate' of undefined/);
       assert.deepEqual(aggregate._pipeline,
-        [{$geoNear: {a: 1, query: {__t: 'subschema'}}}]);
+          [{$geoNear: {a: 1, query: {__t: 'subschema'}}}]);
 
       aggregate = new Aggregate();
       aggregate._model = stub;
@@ -335,7 +335,7 @@ describe('aggregate: ', function () {
         aggregate.exec();
       }, /Cannot read property 'aggregate' of undefined|Cannot call method 'aggregate' of undefined/);
       assert.deepEqual(aggregate._pipeline,
-        [{$geoNear: {b: 2, query: {x: 1, __t: 'subschema'}}}]);
+          [{$geoNear: {b: 2, query: {x: 1, __t: 'subschema'}}}]);
 
       done();
     });
@@ -373,8 +373,8 @@ describe('aggregate: ', function () {
 
   describe('bind', function () {
     it('works', function (done) {
-      var aggregate = new Aggregate(),
-          model = {foo: 42};
+      var aggregate = new Aggregate();
+      var model = {foo: 42};
 
       assert.equal(aggregate.model(model), aggregate);
       assert.equal(aggregate._model, model);
@@ -389,16 +389,18 @@ describe('aggregate: ', function () {
 
       setupData(function (db) {
         aggregate
-          .model(db.model('Employee'))
-          .project({sal: 1, sal_k: {$divide: ['$sal', 1000]}})
-          .exec(function (err, docs) {
-            assert.ifError(err);
-            docs.forEach(function (doc) {
-              assert.equal(doc.sal / 1000, doc.sal_k);
-            });
+            .model(db.model('Employee'))
+            .project({sal: 1, sal_k: {$divide: ['$sal', 1000]}})
+            .exec(function (err, docs) {
+              assert.ifError(err);
+              docs.forEach(function (doc) {
+                assert.equal(doc.sal / 1000, doc.sal_k);
+              });
 
-            clearData(db, function () { done(); });
-          });
+              clearData(db, function () {
+                done();
+              });
+            });
       });
     });
 
@@ -407,20 +409,24 @@ describe('aggregate: ', function () {
 
       setupData(function (db) {
         aggregate
-          .model(db.model('Employee'))
-          .group({_id: '$dept'})
-          .exec(function (err, docs) {
-            var depts;
+            .model(db.model('Employee'))
+            .group({_id: '$dept'})
+            .exec(function (err, docs) {
+              var depts;
 
-            assert.ifError(err);
-            assert.equal(docs.length, 2);
+              assert.ifError(err);
+              assert.equal(docs.length, 2);
 
-            depts = docs.map(function (doc) { return doc._id; });
-            assert.notEqual(depts.indexOf('sales'), -1);
-            assert.notEqual(depts.indexOf('r&d'), -1);
+              depts = docs.map(function (doc) {
+                return doc._id;
+              });
+              assert.notEqual(depts.indexOf('sales'), -1);
+              assert.notEqual(depts.indexOf('r&d'), -1);
 
-            clearData(db, function () { done(); });
-          });
+              clearData(db, function () {
+                done();
+              });
+            });
       });
     });
 
@@ -429,14 +435,16 @@ describe('aggregate: ', function () {
 
       setupData(function (db) {
         aggregate
-          .model(db.model('Employee'))
-          .skip(1)
-          .exec(function (err, docs) {
-            assert.ifError(err);
-            assert.equal(docs.length, 3);
+            .model(db.model('Employee'))
+            .skip(1)
+            .exec(function (err, docs) {
+              assert.ifError(err);
+              assert.equal(docs.length, 3);
 
-            clearData(db, function () { done(); });
-          });
+              clearData(db, function () {
+                done();
+              });
+            });
       });
     });
 
@@ -445,14 +453,16 @@ describe('aggregate: ', function () {
 
       setupData(function (db) {
         aggregate
-          .model(db.model('Employee'))
-          .limit(3)
-          .exec(function (err, docs) {
-            assert.ifError(err);
-            assert.equal(docs.length, 3);
+            .model(db.model('Employee'))
+            .limit(3)
+            .exec(function (err, docs) {
+              assert.ifError(err);
+              assert.equal(docs.length, 3);
 
-            clearData(db, function () { done(); });
-          });
+              clearData(db, function () {
+                done();
+              });
+            });
       });
     });
 
@@ -461,14 +471,16 @@ describe('aggregate: ', function () {
 
       setupData(function (db) {
         aggregate
-          .model(db.model('Employee'))
-          .unwind('customers')
-          .exec(function (err, docs) {
-            assert.ifError(err);
-            assert.equal(docs.length, 5);
+            .model(db.model('Employee'))
+            .unwind('customers')
+            .exec(function (err, docs) {
+              assert.ifError(err);
+              assert.equal(docs.length, 5);
 
-            clearData(db, function () { done(); });
-          });
+              clearData(db, function () {
+                done();
+              });
+            });
       });
     });
 
@@ -477,14 +489,16 @@ describe('aggregate: ', function () {
 
       setupData(function (db) {
         aggregate
-          .model(db.model('Employee'))
-          .match({sal: {$gt: 15000}})
-          .exec(function (err, docs) {
-            assert.ifError(err);
-            assert.equal(docs.length, 1);
+            .model(db.model('Employee'))
+            .match({sal: {$gt: 15000}})
+            .exec(function (err, docs) {
+              assert.ifError(err);
+              assert.equal(docs.length, 1);
 
-            clearData(db, function () { done(); });
-          });
+              clearData(db, function () {
+                done();
+              });
+            });
       });
     });
 
@@ -493,14 +507,16 @@ describe('aggregate: ', function () {
 
       setupData(function (db) {
         aggregate
-          .model(db.model('Employee'))
-          .sort('sal')
-          .exec(function (err, docs) {
-            assert.ifError(err);
-            assert.equal(docs[0].sal, 14000);
+            .model(db.model('Employee'))
+            .sort('sal')
+            .exec(function (err, docs) {
+              assert.ifError(err);
+              assert.equal(docs[0].sal, 14000);
 
-            clearData(db, function () { done(); });
-          });
+              clearData(db, function () {
+                done();
+              });
+            });
       });
     });
 
@@ -509,20 +525,22 @@ describe('aggregate: ', function () {
 
       setupData(function (db) {
         aggregate
-          .model(db.model('Employee'))
-          .match({sal: {$lt: 16000}})
-          .unwind('customers')
-          .project({emp: '$name', cust: '$customers'})
-          .sort('-cust')
-          .skip(2)
-          .exec(function (err, docs) {
-            assert.ifError(err);
-            assert.equal(docs.length, 1);
-            assert.equal(docs[0].cust, 'Gary');
-            assert.equal(docs[0].emp, 'Bob');
-
-            clearData(db, function () { done(); });
-          });
+            .model(db.model('Employee'))
+            .match({sal: {$lt: 16000}})
+            .unwind('customers')
+            .project({emp: '$name', cust: '$customers'})
+            .sort('-cust')
+            .skip(2)
+            .exec(function (err, docs) {
+              assert.ifError(err);
+              assert.equal(docs.length, 1);
+              assert.equal(docs[0].cust, 'Gary');
+              assert.equal(docs[0].emp, 'Bob');
+
+              clearData(db, function () {
+                done();
+              });
+            });
       });
     });
 
@@ -530,25 +548,29 @@ describe('aggregate: ', function () {
       var aggregate = new Aggregate();
       start.mongodVersion(function (err, version) {
         if (err) {
-          return done(err);
+          done(err);
+          return;
         }
         var mongo26 = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
         if (!mongo26) {
-          return done();
+          done();
+          return;
         }
 
         setupData(function (db) {
           aggregate.
-            model(db.model('Employee')).
-            match({sal: {$lt: 16000}}).
-            explain(function (err, output) {
-              assert.ifError(err);
-              assert.ok(output);
-              // make sure we got explain output
-              assert.ok(output.stages);
-
-              clearData(db, function () { done(); });
+          model(db.model('Employee')).
+          match({sal: {$lt: 16000}}).
+          explain(function (err1, output) {
+            assert.ifError(err1);
+            assert.ok(output);
+            // make sure we got explain output
+            assert.ok(output.stages);
+
+            clearData(db, function () {
+              done();
             });
+          });
         });
       });
     });
@@ -569,8 +591,8 @@ describe('aggregate: ', function () {
       });
 
       it('with a callback', function (done) {
-        var aggregate = new Aggregate(),
-            callback;
+        var aggregate = new Aggregate();
+        var callback;
 
         setupData(function (db) {
           aggregate.model(db.model('Employee'));
@@ -601,7 +623,9 @@ describe('aggregate: ', function () {
     it('handles aggregation options', function (done) {
       setupData(function (db) {
         start.mongodVersion(function (err, version) {
-          if (err) throw err;
+          if (err) {
+            throw err;
+          }
           var mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
 
           var m = db.model('Employee');
@@ -618,12 +642,12 @@ describe('aggregate: ', function () {
           }
 
           aggregate
-            .exec(function (err, docs) {
-              assert.ifError(err);
-              assert.equal(1, docs.length);
-              assert.equal(docs[0].sal, 18000);
-              clearData(db, done);
-            });
+              .exec(function (err, docs) {
+                assert.ifError(err);
+                assert.equal(1, docs.length);
+                assert.equal(docs[0].sal, 18000);
+                clearData(db, done);
+              });
         });
       });
     });
@@ -635,12 +659,12 @@ describe('aggregate: ', function () {
     var MyModel = db.model('gh3160', {name: String});
 
     MyModel.
-      aggregate([{$match: {name: 'test'}}]).
-      cursor({async: true}).
-      exec(function (error, cursor) {
-        assert.ifError(error);
-        assert.ok(cursor);
-        db.close(done);
-      });
+    aggregate([{$match: {name: 'test'}}]).
+    cursor({async: true}).
+    exec(function (error, cursor) {
+      assert.ifError(error);
+      assert.ok(cursor);
+      db.close(done);
+    });
   });
 });
diff --git a/test/browser/schema.validation.test_.js b/test/browser/schema.validation.test_.js
index 9fde9b2b956..057fb8b60d5 100644
--- a/test/browser/schema.validation.test_.js
+++ b/test/browser/schema.validation.test_.js
@@ -380,7 +380,7 @@ describe('schema', function () {
           setTimeout(function () {
             executed++;
             fn(value === true);
-            if (2 === executed) {
+            if (executed === 2) {
               done();
             }
           }, 5);
@@ -406,7 +406,7 @@ describe('schema', function () {
           setTimeout(function () {
             executed++;
             fn(value === true);
-            if (2 === executed) {
+            if (executed === 2) {
               done();
             }
           }, 5);
@@ -579,7 +579,7 @@ describe('schema', function () {
         assert.ifError(Animal.path('ferret').doValidateSync(true));
         assert.ok(Animal.path('ferret').doValidateSync(false) instanceof Error);
 
-        if (2 === executed) {
+        if (executed === 2) {
           done();
         }
       });
@@ -607,7 +607,7 @@ describe('schema', function () {
 
         assert.ifError(Animal.path('ferret').doValidateSync(true));
 
-        if (2 === executed) {
+        if (executed === 2) {
           done();
         }
       });
@@ -636,7 +636,7 @@ describe('schema', function () {
 
       it('ingore async', function (done) {
         function syncValidator(val) {
-          return val''sync';
+          return val === 'sync';
         }
 
         var called = false;
@@ -644,7 +644,7 @@ describe('schema', function () {
         function asyncValidator(val, respond) {
           called = true;
           setTimeout(function () {
-            respond(val''async');
+            respond(val === 'async');
           }, 0);
         }
 
diff --git a/test/cast.test.js b/test/cast.test.js
index 80ffb18338d..5873dff11b6 100644
--- a/test/cast.test.js
+++ b/test/cast.test.js
@@ -11,21 +11,21 @@ describe('cast: ', function () {
     it('with a number', function (done) {
       var schema = new Schema({x: Buffer});
       assert.deepEqual(cast(schema, {x: {$bitsAllClear: 3}}),
-        {x: {$bitsAllClear: 3}});
+          {x: {$bitsAllClear: 3}});
       done();
     });
 
     it('with an array', function (done) {
       var schema = new Schema({x: Buffer});
       assert.deepEqual(cast(schema, {x: {$bitsAllSet: [2, '3']}}),
-        {x: {$bitsAllSet: [2, 3]}});
+          {x: {$bitsAllSet: [2, 3]}});
       done();
     });
 
     it('with a buffer', function (done) {
       var schema = new Schema({x: Number});
       assert.deepEqual(cast(schema, {x: {$bitsAnyClear: new Buffer([3])}}),
-        {x: {$bitsAnyClear: new Buffer([3])}});
+          {x: {$bitsAnyClear: new Buffer([3])}});
       done();
     });
 
diff --git a/test/collection.capped.test.js b/test/collection.capped.test.js
index 30b2c677641..b61091af753 100644
--- a/test/collection.capped.test.js
+++ b/test/collection.capped.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -44,9 +43,9 @@ describe('collections: capped:', function () {
 
       // use the existing capped collection in the db (no coll creation)
       var Capped2 = db.model('Capped2', capped, coll);
-      Capped2.collection.isCapped(function (err, isCapped) {
-        assert.ifError(err);
-        assert.ok(isCapped, 'should reuse the capped collection in the db');
+      Capped2.collection.isCapped(function (err1, isCapped1) {
+        assert.ifError(err1);
+        assert.ok(isCapped1, 'should reuse the capped collection in the db');
         assert.equal(Capped.collection.name, Capped2.collection.name);
         done();
       });
@@ -63,21 +62,23 @@ describe('collections: capped:', function () {
     });
   });
   it('attempting to use existing non-capped collection as capped emits error', function (done) {
-    var db = start();
+    db = start();
     var opts = {safe: true};
     var conn = 'capped_existing_' + random();
 
     db.on('open', function () {
       db.db.createCollection(conn, opts, function (err) {
-        if (err) db.close();
+        if (err) {
+          db.close();
+        }
         assert.ifError(err);
 
         var timer;
 
-        db.on('error', function (err) {
+        db.on('error', function (err1) {
           clearTimeout(timer);
           db.close();
-          assert.ok(/non-capped collection exists/.test(err));
+          assert.ok(/non-capped collection exists/.test(err1));
           done();
         });
 
diff --git a/test/collection.test.js b/test/collection.test.js
index e392fbbc026..95f47d09de7 100644
--- a/test/collection.test.js
+++ b/test/collection.test.js
@@ -1,4 +1,3 @@
-
 var start = require('./common'),
     mongoose = start.mongoose,
     assert = require('assert'),
@@ -13,13 +12,15 @@ describe('collections:', function () {
         pending = 2;
 
     function finish() {
-      if (--pending) return;
+      if (--pending) {
+        return;
+      }
       assert.ok(connected);
       assert.ok(inserted);
       done();
     }
 
-    collection.insert({ }, {safe: true}, function () {
+    collection.insert({}, {safe: true}, function () {
       assert.ok(connected);
       inserted = true;
       db.close();
diff --git a/test/colors.js b/test/colors.js
index 07502ac2d1c..b2a2c40cc29 100644
--- a/test/colors.js
+++ b/test/colors.js
@@ -14,7 +14,7 @@ var start = require('./common'),
  * setup
  */
 
-var test = Schema({
+var test = new Schema({
   string: String,
   number: Number,
   date: {
@@ -78,27 +78,27 @@ describe('debug: colors', function () {
     }], function (err) {
       assert.ifError(err);
       Test
-        .find()
-        .lean(false)
-        .exec(function (err, docs) {
-          assert.ifError(err);
-
-          var colorfull = require('util').inspect(docs, {
-            depth: null,
-            colors: true
-          });
+          .find()
+          .lean(false)
+          .exec(function (err, docs) {
+            assert.ifError(err);
 
-          var colorless = require('util').inspect(docs, {
-            depth: null,
-            colors: false
-          });
+            var colorfull = require('util').inspect(docs, {
+              depth: null,
+              colors: true
+            });
 
-          // console.log(colorfull, colorless);
+            var colorless = require('util').inspect(docs, {
+              depth: null,
+              colors: false
+            });
 
-          assert.notEqual(colorfull, colorless);
+            // console.log(colorfull, colorless);
 
-          done();
-        });
+            assert.notEqual(colorfull, colorless);
+
+            done();
+          });
     });
   });
 
diff --git a/test/connection.auth.test.js b/test/connection.auth.test.js
index 154fcc86f7b..af3e8b8ec66 100644
--- a/test/connection.auth.test.js
+++ b/test/connection.auth.test.js
@@ -1,4 +1,3 @@
-
 var start = require('./common');
 var mongoose = start.mongoose;
 var assert = require('assert');
diff --git a/test/connection.reconnect.test.js b/test/connection.reconnect.test.js
index b8aaec8ad24..0c0292ac251 100644
--- a/test/connection.reconnect.test.js
+++ b/test/connection.reconnect.test.js
@@ -1,4 +1,3 @@
-
 var start = require('./common');
 var mongoose = start.mongoose;
 
@@ -34,11 +33,17 @@ describe('connection: manual reconnect with authReconnect: false', function () {
     });
 
     function hit() {
-      if (!open) return;
+      if (!open) {
+        return;
+      }
       M.create({name: times}, function (err, doc) {
-        if (err) return complete(err);
+        if (err) {
+          return complete(err);
+        }
         M.findOne({_id: doc._id}, function (err) {
-          if (err) return complete(err);
+          if (err) {
+            return complete(err);
+          }
           if (times > 1) {
             return complete();
           }
@@ -52,7 +57,9 @@ describe('connection: manual reconnect with authReconnect: false', function () {
     }
 
     function complete(err) {
-      if (complete.ran) return;
+      if (complete.ran) {
+        return;
+      }
       complete.ran = 1;
       done(err);
     }
diff --git a/test/crash.test.js b/test/crash.test.js
index 7d9c415f177..6ab0a0de5a2 100644
--- a/test/crash.test.js
+++ b/test/crash.test.js
@@ -1,4 +1,3 @@
-
 // GH-407
 
 var start = require('./common'),
diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index b27d47a1d6e..8b663a16b59 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -344,7 +343,7 @@ describe('document: hooks:', function () {
 
   it('post remove hooks on subdocuments work', function (done) {
     var db = start();
-    var sub = Schema({_id: Number});
+    var sub = new Schema({_id: Number});
     var called = {pre: 0, post: 0};
 
     sub.pre('remove', function (next) {
@@ -357,7 +356,7 @@ describe('document: hooks:', function () {
       assert.ok(doc instanceof Document);
     });
 
-    var par = Schema({sub: [sub], name: String});
+    var par = new Schema({sub: [sub], name: String});
     var M = db.model('post-remove-hooks-sub', par);
 
     var m = new M({sub: [{_id: 1}, {_id: 2}]});
@@ -366,31 +365,31 @@ describe('document: hooks:', function () {
       assert.equal(0, called.pre);
       assert.equal(0, called.post);
 
-      M.findById(m, function (err, doc) {
-        assert.ifError(err);
+      M.findById(m, function (err1, doc) {
+        assert.ifError(err1);
 
         doc.sub.id(1).remove();
-        doc.save(function (err) {
-          assert.ifError(err);
+        doc.save(function (err2) {
+          assert.ifError(err2);
           assert.equal(1, called.pre);
           assert.equal(1, called.post);
 
           // does not get called when not removed
           doc.name = 'changed1';
-          doc.save(function (err) {
-            assert.ifError(err);
+          doc.save(function (err3) {
+            assert.ifError(err3);
             assert.equal(1, called.pre);
             assert.equal(1, called.post);
 
             doc.sub.id(2).remove();
-            doc.remove(function (err) {
-              assert.ifError(err);
+            doc.remove(function (err4) {
+              assert.ifError(err4);
               assert.equal(2, called.pre);
               assert.equal(2, called.post);
 
               // does not get called twice
-              doc.remove(function (err) {
-                assert.ifError(err);
+              doc.remove(function (err5) {
+                assert.ifError(err5);
                 assert.equal(2, called.pre);
                 assert.equal(2, called.post);
                 db.close(done);
@@ -413,7 +412,7 @@ describe('document: hooks:', function () {
 
     var b = new Bar();
     b.pre('save', function (next) {
-      if (this.isNew && 0 === this.foos.length) {
+      if (this.isNew && this.foos.length === 0) {
         this.foos = undefined;
       }
       next();
@@ -459,10 +458,12 @@ describe('document: hooks:', function () {
 
     var M = db.model('post-save-hooks-sub', postSaveHooks);
 
-    var m = new M({subs: [
-      {name: 'mee'},
-      {name: 'moo'}
-    ]});
+    var m = new M({
+      subs: [
+        {name: 'mee'},
+        {name: 'moo'}
+      ]
+    });
 
     m.save(function (err) {
       assert.ifError(err);
@@ -483,7 +484,8 @@ describe('document: hooks:', function () {
   });
 
   it('pre save hooks should run in parallel', function (done) {
-    // we set the time out to be double that of the validator - 1 (so that running in serial will be greater then that)
+    // we set the time out to be double that of the validator - 1
+    // (so that running in serial will be greater then that)
     this.timeout(1000);
     var db = start(),
         count = 0;
@@ -505,20 +507,15 @@ describe('document: hooks:', function () {
 
     var MWPSH = db.model('mwpsh', new Schema({subs: [SchemaWithPreSaveHook]}));
     var m = new MWPSH({
-      subs: [
-          {
-            preference: 'xx'
-          },
-          {
-            preference: 'yy'
-          },
-          {
-            preference: '1'
-          },
-          {
-            preference: '2'
-          }
-      ]
+      subs: [{
+        preference: 'xx'
+      }, {
+        preference: 'yy'
+      }, {
+        preference: '1'
+      }, {
+        preference: '2'
+      }]
     });
 
     m.save(function (err) {
@@ -535,7 +532,7 @@ describe('document: hooks:', function () {
   });
 
   it('parallel followed by serial (gh-2521)', function (done) {
-    var schema = Schema({name: String});
+    var schema = new Schema({name: String});
 
     schema.pre('save', true, function (next, done) {
       process.nextTick(function () {
@@ -561,7 +558,7 @@ describe('document: hooks:', function () {
   });
 
   it('runs post hooks after function (gh-2949)', function (done) {
-    var schema = Schema({name: String});
+    var schema = new Schema({name: String});
 
     var postCount = 0;
     schema.post('init', function (doc) {
@@ -581,7 +578,7 @@ describe('document: hooks:', function () {
   });
 
   it('pre-init hooks work', function (done) {
-    var schema = Schema({text: String});
+    var schema = new Schema({text: String});
 
     schema.pre('init', function (next, data) {
       data.text = "pre init'd";
@@ -605,7 +602,7 @@ describe('document: hooks:', function () {
   });
 
   it('post save handles multiple args (gh-3155)', function (done) {
-    var schema = Schema({});
+    var schema = new Schema({});
 
     schema.post('save', function (item, next) {
       next();
@@ -623,7 +620,7 @@ describe('document: hooks:', function () {
   });
 
   it('pre-init hooks on subdocuments work', function (done) {
-    var childSchema = Schema({age: Number});
+    var childSchema = new Schema({age: Number});
 
     childSchema.pre('init', function (next, data) {
       ++data.age;
@@ -632,7 +629,7 @@ describe('document: hooks:', function () {
       return this;
     });
 
-    var parentSchema = Schema({name: String, children: [childSchema]});
+    var parentSchema = new Schema({name: String, children: [childSchema]});
     var db = start(),
         Parent = db.model('ParentWithChildren', parentSchema);
 
@@ -655,7 +652,7 @@ describe('document: hooks:', function () {
   });
 
   it('pre-save hooks fire on subdocs before their parent doc', function (done) {
-    var childSchema = Schema({name: String, count: Number});
+    var childSchema = new Schema({name: String, count: Number});
 
     childSchema.pre('save', function (next) {
       ++this.count;
@@ -664,7 +661,7 @@ describe('document: hooks:', function () {
       return this;
     });
 
-    var parentSchema = Schema({
+    var parentSchema = new Schema({
       cumulativeCount: Number,
       children: [childSchema]
     });
@@ -681,15 +678,16 @@ describe('document: hooks:', function () {
         Parent = db.model('ParentWithChildren', parentSchema),
         doc = new Parent({children: [{count: 0, name: 'a'}, {count: 1, name: 'b'}]});
 
-    doc.save(function (err, doc) {
+    doc.save(function (err, doc1) {
       db.close();
 
       try {
-        assert.strictEqual(doc.children[0].count, 1);
-        assert.strictEqual(doc.children[1].count, 2);
-        assert.strictEqual(doc.cumulativeCount, 3);
+        assert.strictEqual(doc1.children[0].count, 1);
+        assert.strictEqual(doc1.children[1].count, 2);
+        assert.strictEqual(doc1.cumulativeCount, 3);
       } catch (e) {
-        return done(e);
+        done(e);
+        return;
       }
 
       done();
@@ -788,15 +786,11 @@ describe('document: hooks:', function () {
     var L1 = db.model('gh3281', L1Schema);
 
     var data = {
-      items: [
-          {
-            items: [
-                {
-                  title: 'test'
-                }
-            ]
-          }
-      ]
+      items: [{
+        items: [{
+          title: 'test'
+        }]
+      }]
     };
 
     L1.create(data, function (error) {
@@ -826,8 +820,8 @@ describe('document: hooks:', function () {
     Person.create({photo: {bla: 'test'}}, function (error, person) {
       assert.ifError(error);
       person.photo.remove();
-      person.save(function (error) {
-        assert.ifError(error);
+      person.save(function (error1) {
+        assert.ifError(error1);
         setTimeout(function () {
           assert.equal(postCount, 1);
           done();
diff --git a/test/document.isselected.test.js b/test/document.isselected.test.js
index ed859dea607..9ea4997b196 100644
--- a/test/document.isselected.test.js
+++ b/test/document.isselected.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
diff --git a/test/document.modified.test.js b/test/document.modified.test.js
index 2a967ef4707..531222e594e 100644
--- a/test/document.modified.test.js
+++ b/test/document.modified.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Test dependencies.
  */
@@ -42,21 +41,24 @@ var BlogPost = new Schema({
 });
 
 BlogPost
-.path('title')
-.get(function (v) {
-  if (v) return v.toUpperCase();
-});
+    .path('title')
+    .get(function (v) {
+      if (v) {
+        return v.toUpperCase();
+      }
+      return v;
+    });
 
 BlogPost
-.virtual('titleWithAuthor')
-.get(function () {
-  return this.get('title') + ' by ' + this.get('author');
-})
-.set(function (val) {
-  var split = val.split(' by ');
-  this.set('title', split[0]);
-  this.set('author', split[1]);
-});
+    .virtual('titleWithAuthor')
+    .get(function () {
+      return this.get('title') + ' by ' + this.get('author');
+    })
+    .set(function (val) {
+      var split = val.split(' by ');
+      this.set('title', split[0]);
+      this.set('author', split[1]);
+    });
 
 BlogPost.method('cool', function () {
   return this;
@@ -84,11 +86,11 @@ describe('document modified', function () {
         assert.strictEqual(null, err);
 
         b.numbers.push(3);
-        b.save(function (err) {
-          assert.strictEqual(null, err);
+        b.save(function (err1) {
+          assert.strictEqual(null, err1);
 
-          B.findById(b, function (err, b) {
-            assert.strictEqual(null, err);
+          B.findById(b, function (err2, b) {
+            assert.strictEqual(null, err2);
             assert.equal(2, b.numbers.length);
 
             db.close();
@@ -120,7 +122,7 @@ describe('document modified', function () {
       var db = start();
 
       var MyModel = db.model('test',
-        {name: {type: String, default: 'Val '}});
+          {name: {type: String, default: 'Val '}});
       var m = new MyModel();
       assert.ok(m.$isDefault('name'));
       db.close(done);
@@ -480,36 +482,36 @@ describe('document modified', function () {
     it('should mark multi-level nested schemas as modified (gh-1754)', function (done) {
       var db = start();
 
-      var grandChildSchema = Schema({
+      var grandChildSchema = new Schema({
         name: String
       });
 
-      var childSchema = Schema({
+      var childSchema = new Schema({
         name: String,
         grandChild: [grandChildSchema]
       });
 
-      var parentSchema = Schema({
+      var parentSchema = new Schema({
         name: String,
         child: [childSchema]
       });
 
       var Parent = db.model('gh-1754', parentSchema);
       Parent.create(
-        {child: [{name: 'Brian', grandChild: [{name: 'Jake'}]}]},
-        function (error, p) {
-          assert.ifError(error);
-          assert.ok(p);
-          assert.equal(1, p.child.length);
-          assert.equal(1, p.child[0].grandChild.length);
-          p.child[0].grandChild[0].name = 'Jason';
-          assert.ok(p.isModified('child.0.grandChild.0.name'));
-          p.save(function (error, inDb) {
+          {child: [{name: 'Brian', grandChild: [{name: 'Jake'}]}]},
+          function (error, p) {
             assert.ifError(error);
-            assert.equal('Jason', inDb.child[0].grandChild[0].name);
-            db.close(done);
+            assert.ok(p);
+            assert.equal(1, p.child.length);
+            assert.equal(1, p.child[0].grandChild.length);
+            p.child[0].grandChild[0].name = 'Jason';
+            assert.ok(p.isModified('child.0.grandChild.0.name'));
+            p.save(function (error1, inDb) {
+              assert.ifError(error1);
+              assert.equal('Jason', inDb.child[0].grandChild[0].name);
+              db.close(done);
+            });
           });
-        });
     });
   });
 });
diff --git a/test/document.strict.test.js b/test/document.strict.test.js
index 3b85231e55d..0940be531cf 100644
--- a/test/document.strict.test.js
+++ b/test/document.strict.test.js
@@ -348,7 +348,7 @@ describe('document: strict mode:', function () {
 
   describe('"throws" mode', function () {
     it('throws on set() of unknown property', function (done) {
-      var schema = Schema({n: String, docs: [{x: [{y: String}]}]});
+      var schema = new Schema({n: String, docs: [{x: [{y: String}]}]});
       schema.set('strict', 'throw');
       var M = mongoose.model('throwStrictSet', schema, 'tss_' + random());
       var m = new M;
diff --git a/test/document.test.js b/test/document.test.js
index 98252dbd6be..e97400856d7 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -346,7 +346,7 @@ describe('document', function () {
     doc.schema.options.toObject = {};
     doc.schema.options.toObject.transform = function xform(doc, ret) {
       // ignore embedded docs
-      if ('function' === typeof doc.ownerDocument) {
+      if (typeof doc.ownerDocument === 'function') {
         return;
       }
 
@@ -368,7 +368,7 @@ describe('document', function () {
     var out = {myid: doc._id.toString()};
     doc.schema.options.toObject.transform = function (doc, ret) {
       // ignore embedded docs
-      if ('function' === typeof doc.ownerDocument) {
+      if (typeof doc.ownerDocument === 'function') {
         return;
       }
 
@@ -682,7 +682,7 @@ describe('document', function () {
     doc.schema.options.toJSON = {};
     doc.schema.options.toJSON.transform = function xform(doc, ret) {
       // ignore embedded docs
-      if ('function' === typeof doc.ownerDocument) {
+      if (typeof doc.ownerDocument === 'function') {
         return;
       }
 
@@ -704,7 +704,7 @@ describe('document', function () {
     var out = {myid: doc._id.toString()};
     doc.schema.options.toJSON.transform = function (doc, ret) {
       // ignore embedded docs
-      if ('function' === typeof doc.ownerDocument) {
+      if (typeof doc.ownerDocument === 'function') {
         return;
       }
 
@@ -767,7 +767,7 @@ describe('document', function () {
     var db = start();
     var userSchema, User, groupSchema, Group;
 
-    userSchema = Schema({name: String});
+    userSchema = new Schema({name: String});
     // includes virtual path when 'toJSON'
     userSchema.set('toJSON', {getters: true});
     userSchema.virtual('hello').get(function () {
@@ -775,7 +775,7 @@ describe('document', function () {
     });
     User = db.model('User', userSchema);
 
-    groupSchema = Schema({
+    groupSchema = new Schema({
       name: String,
       _users: [{type: Schema.ObjectId, ref: 'User'}]
     });
@@ -2229,7 +2229,7 @@ describe('document', function () {
     });
 
     it('single embedded docs with arrays pre hooks (gh-3680)', function (done) {
-      var childSchema = Schema({count: Number});
+      var childSchema = new Schema({count: Number});
 
       var preCalls = 0;
       childSchema.pre('save', function (next) {
@@ -2255,7 +2255,7 @@ describe('document', function () {
     });
 
     it('nested single embedded doc validation (gh-3702)', function (done) {
-      var childChildSchema = Schema({count: {type: Number, min: 1}});
+      var childChildSchema = new Schema({count: {type: Number, min: 1}});
       var childSchema = new Schema({child: childChildSchema});
       var parentSchema = new Schema({child: childSchema});
 
@@ -2353,7 +2353,7 @@ describe('document', function () {
     });
 
     it('handles 0 for numeric subdoc ids (gh-3776)', function (done) {
-      var personSchema = Schema({
+      var personSchema = new Schema({
         _id: Number,
         name: String,
         age: Number,
diff --git a/test/model.create.test.js b/test/model.create.test.js
index 36e4148590c..6e5d8a98210 100644
--- a/test/model.create.test.js
+++ b/test/model.create.test.js
@@ -13,7 +13,7 @@ var start = require('./common'),
  * Setup
  */
 
-var schema = Schema({
+var schema = new Schema({
   title: String
 });
 
diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js
index 0998081fb90..30169f8daab 100644
--- a/test/model.discriminator.querying.test.js
+++ b/test/model.discriminator.querying.test.js
@@ -71,7 +71,7 @@ describe('model', function () {
                                    BaseCustomEventSchema);
         DiscCustomEvent = BaseCustomEvent.discriminator('disc-custom-event',
                                                         DiscCustomEventSchema);
-        var ContainerSchema = Schema({
+        var ContainerSchema = new Schema({
           title: String,
           events: [{type: Schema.Types.ObjectId, ref: 'base-custom-event'}]
         });
diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index 46bde1ac311..afd4112ad90 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -910,7 +910,7 @@ describe('model: findByIdAndUpdate:', function () {
   it('can do deep equals on object id after findOneAndUpdate (gh-2070)', function (done) {
     var db = start();
 
-    var accountSchema = Schema({
+    var accountSchema = new Schema({
       name: String,
       contacts: [{
         account: {type: Schema.Types.ObjectId, ref: 'Account'},
@@ -950,7 +950,7 @@ describe('model: findByIdAndUpdate:', function () {
   it('adds __v on upsert (gh-2122)', function (done) {
     var db = start();
 
-    var accountSchema = Schema({
+    var accountSchema = new Schema({
       name: String
     });
 
@@ -970,8 +970,8 @@ describe('model: findByIdAndUpdate:', function () {
   it('works with nested schemas and $pull+$or (gh-1932)', function (done) {
     var db = start();
 
-    var TickSchema = Schema({name: String});
-    var TestSchema = Schema({a: Number, b: Number, ticks: [TickSchema]});
+    var TickSchema = new Schema({name: String});
+    var TestSchema = new Schema({a: Number, b: Number, ticks: [TickSchema]});
 
     var TestModel = db.model('gh-1932', TestSchema, 'gh-1932');
 
diff --git a/test/model.hydrate.test.js b/test/model.hydrate.test.js
index 6d62657fb1e..acedf4f6795 100644
--- a/test/model.hydrate.test.js
+++ b/test/model.hydrate.test.js
@@ -12,12 +12,12 @@ var start = require('./common'),
  * Setup
  */
 
-var schemaB = Schema({
+var schemaB = new Schema({
   title: String,
   type: String
 }, {discriminatorKey: 'type'});
 
-var schemaC = Schema({
+var schemaC = new Schema({
   test: {
     type: String,
     default: 'test'
@@ -31,7 +31,7 @@ describe('model', function () {
     var B;
     var Breakfast;
 
-    var breakfastSchema = Schema({
+    var breakfastSchema = new Schema({
       food: {type: String, enum: ['bacon', 'eggs']}
     });
 
diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js
index 4fbca37788b..5956f20f369 100644
--- a/test/model.indexes.test.js
+++ b/test/model.indexes.test.js
@@ -262,7 +262,7 @@ describe('model', function () {
 
       var db = start({uri: 'mongodb://localhost/mongoose_test_indexing'});
 
-      var schema = Schema({
+      var schema = new Schema({
         name: {type: String, index: true},
         furryness: {type: Number, index: true}
       }, {autoIndex: false});
diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 9dcd240c7bb..6ff7acf0a10 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -1,4 +1,3 @@
-/* eslint no-unused-vars: 1 */
 /* global emit */
 /**
  * Test dependencies.
@@ -61,9 +60,7 @@ describe('model: mapreduce:', function () {
     MR.create(docs, function (err, insertedDocs) {
       assert.ifError(err);
 
-      var a = insertedDocs[0];
-      var b = insertedDocs[1];
-      magicID = b._id;
+      magicID = insertedDocs[1]._id;
 
       var o = {
         map: function () {
@@ -128,7 +125,7 @@ describe('model: mapreduce:', function () {
           out: {replace: '_mapreduce_test_' + random()}
         };
 
-        MR.mapReduce(o, function (err, ret, stats) {
+        MR.mapReduce(o, function (err, ret) {
           assert.ifError(err);
 
           // ret is a model
diff --git a/test/model.populate.setting.test.js b/test/model.populate.setting.test.js
index 9890cc48f82..02a7d1a444f 100644
--- a/test/model.populate.setting.test.js
+++ b/test/model.populate.setting.test.js
@@ -51,7 +51,7 @@ describe('model: populate:', function () {
         before(function (done) {
           refuser = 'RefUser-' + id;
 
-          var bSchema = Schema({
+          var bSchema = new Schema({
             title: String,
             fans: [{type: id, ref: refuser}],
             adhoc: [{subdoc: id, subarray: [{things: [id]}]}],
@@ -63,7 +63,7 @@ describe('model: populate:', function () {
             }]
           });
 
-          var uSchema = Schema({
+          var uSchema = new Schema({
             _id: id,
             name: String,
             email: String
diff --git a/test/model.populate.test.js b/test/model.populate.test.js
index a911b83051c..e02b85c513f 100644
--- a/test/model.populate.test.js
+++ b/test/model.populate.test.js
@@ -327,7 +327,7 @@ describe('model: populate:', function () {
         // mock an error
         User.find = function () {
           var args = Array.prototype.map.call(arguments, function (arg) {
-            return 'function' === typeof arg ? function () {
+            return typeof arg === 'function' ? function () {
               arg(new Error('woot'));
             } : arg;
           });
@@ -653,7 +653,7 @@ describe('model: populate:', function () {
             var origFind = User.find;
             User.find = function () {
               var args = Array.prototype.map.call(arguments, function (arg) {
-                return 'function' === typeof arg ? function () {
+                return typeof arg === 'function' ? function () {
                   arg(new Error('woot 2'));
                 } : arg;
               });
@@ -1360,7 +1360,7 @@ describe('model: populate:', function () {
     });
     var User = db.model('gh-2151-1', user, 'gh-2151-1');
 
-    var blogpost = Schema({
+    var blogpost = new Schema({
       title: String,
       tags: [String],
       author: {
diff --git a/test/model.stream.test.js b/test/model.stream.test.js
index a407bef2e5b..6990fe103cc 100644
--- a/test/model.stream.test.js
+++ b/test/model.stream.test.js
@@ -71,7 +71,7 @@ describe('query stream:', function () {
       assert.ok(!seen[doc.id]);
       seen[doc.id] = 1;
 
-      if (paused > 0 && 0 === resumed) {
+      if (paused > 0 && resumed === 0) {
         err = new Error('data emitted during pause');
         return cb();
       }
@@ -261,12 +261,12 @@ describe('query stream:', function () {
       assert.strictEqual(false, doc instanceof mongoose.Document);
       i++;
 
-      if (1 === i) {
+      if (i === 1) {
         stream.pause();
         assert.equal(true, stream.paused);
         stream.resume();
         assert.equal(false, stream.paused);
-      } else if (2 === i) {
+      } else if (i === 2) {
         stream.pause();
         assert.equal(true, stream.paused);
         process.nextTick(function () {
@@ -330,11 +330,11 @@ describe('query stream:', function () {
   it('supports population (gh-1411)', function (done) {
     var db = start();
 
-    var barSchema = Schema({
+    var barSchema = new Schema({
       value: Number
     });
 
-    var fooSchema = Schema({
+    var fooSchema = new Schema({
       bar: {type: 'ObjectId', ref: 'Bar'}
     });
 
@@ -372,7 +372,7 @@ describe('query stream:', function () {
   it('respects schema options (gh-1862)', function (done) {
     var db = start();
 
-    var schema = Schema({
+    var schema = new Schema({
       fullname: {type: String},
       password: {type: String, select: false}
     });
diff --git a/test/model.test.js b/test/model.test.js
index a4f6c3df5da..7d6069ec28e 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -4122,7 +4122,7 @@ describe('Model', function () {
         var db = start(),
             B = db.model('BlogPost' + random(), bpSchema);
 
-        var peopleSchema = Schema({name: String, likes: ['ObjectId']});
+        var peopleSchema = new Schema({name: String, likes: ['ObjectId']});
         var P = db.model('promise-BP-people', peopleSchema, random());
         B.create(
             {title: 'then promise 1'},
@@ -4218,7 +4218,7 @@ describe('Model', function () {
       describe('with mongo down', function () {
         it('and no command buffering should pass an error', function (done) {
           var db = start({db: {bufferMaxEntries: 0}});
-          var schema = Schema({type: String}, {bufferCommands: false});
+          var schema = new Schema({type: String}, {bufferCommands: false});
           var T = db.model('Thing', schema);
           db.on('open', function () {
             var t = new T({type: 'monster'});
diff --git a/test/model.update.test.js b/test/model.update.test.js
index e44cf15966e..949f9a4b06b 100644
--- a/test/model.update.test.js
+++ b/test/model.update.test.js
@@ -711,7 +711,7 @@ describe('model: update:', function () {
 
   it('handles nested paths starting with numbers (gh-1062)', function (done) {
     var db = start();
-    var schema = Schema({counts: Schema.Types.Mixed});
+    var schema = new Schema({counts: Schema.Types.Mixed});
     var M = db.model('gh-1062', schema, '1062-' + random());
     M.create({counts: {}}, function (err, m) {
       assert.ifError(err);
@@ -795,7 +795,7 @@ describe('model: update:', function () {
       }
 
       var db = start();
-      var schema = Schema({name: String, age: Number, x: String});
+      var schema = new Schema({name: String, age: Number, x: String});
       var M = db.model('setoninsert-' + random(), schema);
 
       var match = {name: 'set on insert'};
@@ -829,7 +829,7 @@ describe('model: update:', function () {
       }
 
       var db = start();
-      var schema = Schema({name: String, n: [{x: Number}]});
+      var schema = new Schema({name: String, n: [{x: Number}]});
       var M = db.model('setoninsert-' + random(), schema);
 
       M.create({name: '2.4'}, function (err, created) {
@@ -892,7 +892,7 @@ describe('model: update:', function () {
       }
 
       var db = start();
-      var schema = Schema({name: String, n: [{x: Number}]});
+      var schema = new Schema({name: String, n: [{x: Number}]});
       var M = db.model('setoninsert-' + random(), schema);
 
       var m = new M({name: '2.6', n: [{x: 0}]});
@@ -922,7 +922,7 @@ describe('model: update:', function () {
       }
 
       var db = start();
-      var schema = Schema({name: String, lastModified: Date, lastModifiedTS: Date});
+      var schema = new Schema({name: String, lastModified: Date, lastModifiedTS: Date});
       var M = db.model('gh-2019', schema);
 
       var m = new M({name: '2.6'});
@@ -1503,8 +1503,8 @@ describe('model: update:', function () {
   it('does not add virtuals to update (gh-2046)', function (done) {
     var db = start();
 
-    var childSchema = Schema({foo: String}, {toObject: {getters: true}});
-    var parentSchema = Schema({children: [childSchema]});
+    var childSchema = new Schema({foo: String}, {toObject: {getters: true}});
+    var parentSchema = new Schema({children: [childSchema]});
 
     childSchema.virtual('bar').get(function () {
       return 'bar';
@@ -1529,7 +1529,7 @@ describe('model: update:', function () {
   it('can $rename (gh-1845)', function (done) {
     var db = start();
 
-    var schema = Schema({foo: Date, bar: Date});
+    var schema = new Schema({foo: Date, bar: Date});
     var Model = db.model('gh1845', schema, 'gh1845');
 
     Model.update({}, {$rename: {foo: 'bar'}}, function (error) {
@@ -1555,7 +1555,7 @@ describe('model: update:', function () {
 
   it('can $rename (gh-1845)', function (done) {
     var db = start();
-    var schema = Schema({foo: Date, bar: Date});
+    var schema = new Schema({foo: Date, bar: Date});
     var Model = db.model('gh1845', schema, 'gh1845');
 
     Model.update({}, {$rename: {foo: 'bar'}}, function (error) {
@@ -1566,7 +1566,7 @@ describe('model: update:', function () {
 
   it('allows objects with positional operator (gh-3185)', function (done) {
     var db = start();
-    var schema = Schema({children: [{_id: Number}]});
+    var schema = new Schema({children: [{_id: Number}]});
     var MyModel = db.model('gh3185', schema, 'gh3185');
 
     MyModel.create({children: [{_id: 1}]}, function (error, doc) {
diff --git a/test/object.create.null.test.js b/test/object.create.null.test.js
index 325ee46334a..72c0b17b0a4 100644
--- a/test/object.create.null.test.js
+++ b/test/object.create.null.test.js
@@ -1,5 +1,3 @@
-
-
 /**
  * Test dependencies.
  */
diff --git a/test/promise.test.js b/test/promise.test.js
index 7e9a2e3e36e..665470a4e6c 100644
--- a/test/promise.test.js
+++ b/test/promise.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js
index 6469a724490..14d485388cb 100644
--- a/test/promise_provider.test.js
+++ b/test/promise_provider.test.js
@@ -1,5 +1,3 @@
-/* eslint no-unused-vars: 1 */
-
 /**
  * Module dependencies.
  */
@@ -12,7 +10,6 @@ var start = require('./common');
 var PromiseProvider = require('../lib/promise_provider');
 var Schema = require('../lib/schema');
 
-var Promise;
 var db;
 var testSchema = new Schema({test: {type: String, required: true}});
 testSchema.pre('save', function (next) {
@@ -43,7 +40,6 @@ describe('ES6 promises: ', function () {
 
     before(function () {
       PromiseProvider.set(global.Promise);
-      Promise = PromiseProvider.get();
     });
 
     before(function () {
@@ -179,7 +175,6 @@ describe('ES6 promises: ', function () {
   describe('bluebird: ', function () {
     before(function () {
       PromiseProvider.set(bluebird);
-      Promise = PromiseProvider.get();
     });
 
     before(function () {
@@ -357,7 +352,6 @@ describe('ES6 promises: ', function () {
   describe('q: ', function () {
     before(function () {
       PromiseProvider.set(q.Promise);
-      Promise = PromiseProvider.get();
     });
 
     before(function () {
diff --git a/test/query.test.js b/test/query.test.js
index 4f82e63543d..b516a36bfe7 100644
--- a/test/query.test.js
+++ b/test/query.test.js
@@ -532,7 +532,7 @@ describe('Query', function () {
   describe('find', function () {
     it('strict array equivalence condition v', function (done) {
       var query = new Query({}, {}, null, p1.collection);
-      query.find({'pets': ['dog', 'cat', 'ferret']});
+      query.find({pets: ['dog', 'cat', 'ferret']});
       assert.deepEqual(query._conditions, {pets: ['dog', 'cat', 'ferret']});
       done();
     });
@@ -729,10 +729,10 @@ describe('Query', function () {
     it('works', function (done) {
       var query = new Query({}, {}, null, p1.collection);
       query.sort('a -c b');
-      assert.deepEqual(query.options.sort, {'a': 1, 'c': -1, 'b': 1});
+      assert.deepEqual(query.options.sort, {a: 1, c: -1, b: 1});
       query = new Query({}, {}, null, p1.collection);
-      query.sort({'a': 1, 'c': -1, 'b': 'asc', e: 'descending', f: 'ascending'});
-      assert.deepEqual(query.options.sort, {'a': 1, 'c': -1, 'b': 1, 'e': -1, 'f': 1});
+      query.sort({a: 1, c: -1, b: 'asc', e: 'descending', f: 'ascending'});
+      assert.deepEqual(query.options.sort, {a: 1, c: -1, b: 1, e: -1, f: 1});
       query = new Query({}, {}, null, p1.collection);
       var e;
 
@@ -1256,8 +1256,8 @@ describe('Query', function () {
     describe('hint', function () {
       it('works', function (done) {
         var query2 = new Query({}, {}, null, p1.collection);
-        query2.hint({'indexAttributeA': 1, 'indexAttributeB': -1});
-        assert.deepEqual(query2.options.hint, {'indexAttributeA': 1, 'indexAttributeB': -1});
+        query2.hint({indexAttributeA: 1, indexAttributeB: -1});
+        assert.deepEqual(query2.options.hint, {indexAttributeA: 1, indexAttributeB: -1});
 
         assert.throws(function () {
           var query3 = new Query({}, {}, null, p1.collection);
@@ -1388,7 +1388,7 @@ describe('Query', function () {
         it('and sends it though the driver', function (done) {
           var db = start();
           var options = {read: 'secondary', safe: {w: 'majority'}};
-          var schema = Schema({name: String}, options);
+          var schema = new Schema({name: String}, options);
           var M = db.model(random(), schema);
           var q = M.find();
 
@@ -1428,7 +1428,7 @@ describe('Query', function () {
       q.setOptions({limit: 4});
       q.setOptions({skip: 3});
       q.setOptions({sort: '-blah'});
-      q.setOptions({sort: {'woot': -1}});
+      q.setOptions({sort: {woot: -1}});
       q.setOptions({hint: {index1: 1, index2: -1}});
       q.setOptions({read: ['s', [{dc: 'eu'}]]});
 
diff --git a/test/query.toconstructor.test.js b/test/query.toconstructor.test.js
index 89e725ebc01..23d6d52c190 100644
--- a/test/query.toconstructor.test.js
+++ b/test/query.toconstructor.test.js
@@ -113,7 +113,7 @@ describe('Query:', function () {
 
       var nq = prodC(null, {limit: 3});
       assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3});
-      assert.deepEqual(nq.options, {sort: {'title': 1}, limit: 3});
+      assert.deepEqual(nq.options, {sort: {title: 1}, limit: 3});
       done();
     });
 
@@ -127,7 +127,7 @@ describe('Query:', function () {
 
       var nq = prodC(null, {limit: 3});
       assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3});
-      assert.deepEqual(nq.options, {sort: {'title': 1}, limit: 3});
+      assert.deepEqual(nq.options, {sort: {title: 1}, limit: 3});
       var nq2 = prodC(null, {limit: 5});
       assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3});
       assert.deepEqual(nq2._mongooseOptions, {lean: true, limit: 5});
diff --git a/test/schema.documentarray.test.js b/test/schema.documentarray.test.js
index f332a2e9d14..9b49db4e4d1 100644
--- a/test/schema.documentarray.test.js
+++ b/test/schema.documentarray.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -18,7 +17,13 @@ describe('schema.documentarray', function () {
 
     var schema1 = new Schema({x: {type: [child], default: [{title: 'Prometheus'}]}});
     var schema2 = new Schema({x: {type: [child], default: {title: 'Prometheus'}}});
-    var schema3 = new Schema({x: {type: [child], default: function () { return [{title: 'Prometheus'}];}}});
+    var schema3 = new Schema({
+      x: {
+        type: [child], default: function () {
+          return [{title: 'Prometheus'}];
+        }
+      }
+    });
 
     var M = mongoose.model('DefaultDocArrays1', schema1);
     var N = mongoose.model('DefaultDocArrays2', schema2);
diff --git a/test/schema.mixed.test.js b/test/schema.mixed.test.js
index 44764a8b470..cfd25ba4c93 100644
--- a/test/schema.mixed.test.js
+++ b/test/schema.mixed.test.js
@@ -11,7 +11,7 @@ var start = require('./common'),
 describe('schematype mixed', function () {
   describe('empty object defaults (gh-1380)', function () {
     it('are interpreted as fns that return new empty objects', function (done) {
-      var s = Schema({mix: {type: Schema.Types.Mixed, default: {}}});
+      var s = new Schema({mix: {type: Schema.Types.Mixed, default: {}}});
       var M = mongoose.model('M1', s);
       var m1 = new M;
       var m2 = new M;
@@ -22,7 +22,7 @@ describe('schematype mixed', function () {
     });
     it('can be forced to share the object between documents', function (done) {
       // silly but necessary for backwards compatibility
-      var s = Schema({mix: {type: Schema.Types.Mixed, default: {}, shared: true}});
+      var s = new Schema({mix: {type: Schema.Types.Mixed, default: {}, shared: true}});
       var M = mongoose.model('M2', s);
       var m1 = new M;
       var m2 = new M;
diff --git a/test/schema.test.js b/test/schema.test.js
index 48949d55fbc..66ca25ca9f4 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -94,13 +94,13 @@ describe('schema', function () {
 
 
   it('can be created without the "new" keyword', function (done) {
-    var schema = Schema({name: String});
+    var schema = new Schema({name: String});
     assert.ok(schema instanceof Schema);
     done();
   });
 
   it('does expose a property for duck-typing instanceof', function (done) {
-    var schema = Schema({name: String});
+    var schema = new Schema({name: String});
     assert.ok(schema.instanceOfSchema);
     done();
   });
@@ -908,56 +908,56 @@ describe('schema', function () {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 'p'});
+      Tobi = new Schema({}, {read: 'p'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('primary', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['p', tags]});
+      Tobi = new Schema({}, {read: ['p', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('primary', Tobi.options.read.mode);
       assert.ok(Array.isArray(Tobi.options.read.tags));
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 'primary'});
+      Tobi = new Schema({}, {read: 'primary'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('primary', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['primary', tags]});
+      Tobi = new Schema({}, {read: ['primary', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('primary', Tobi.options.read.mode);
       assert.ok(Array.isArray(Tobi.options.read.tags));
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 's'});
+      Tobi = new Schema({}, {read: 's'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('secondary', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['s', tags]});
+      Tobi = new Schema({}, {read: ['s', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('secondary', Tobi.options.read.mode);
       assert.ok(Array.isArray(Tobi.options.read.tags));
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 'secondary'});
+      Tobi = new Schema({}, {read: 'secondary'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('secondary', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['secondary', tags]});
+      Tobi = new Schema({}, {read: ['secondary', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.equal('secondary', Tobi.options.read.mode);
       assert.ok(Array.isArray(Tobi.options.read.tags));
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 'pp'});
+      Tobi = new Schema({}, {read: 'pp'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('primaryPreferred', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['pp', tags]});
+      Tobi = new Schema({}, {read: ['pp', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('primaryPreferred', Tobi.options.read.mode);
@@ -965,12 +965,12 @@ describe('schema', function () {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 'primaryPreferred'});
+      Tobi = new Schema({}, {read: 'primaryPreferred'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('primaryPreferred', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['primaryPreferred', tags]});
+      Tobi = new Schema({}, {read: ['primaryPreferred', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('primaryPreferred', Tobi.options.read.mode);
@@ -978,12 +978,12 @@ describe('schema', function () {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 'sp'});
+      Tobi = new Schema({}, {read: 'sp'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('secondaryPreferred', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['sp', tags]});
+      Tobi = new Schema({}, {read: ['sp', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('secondaryPreferred', Tobi.options.read.mode);
@@ -991,12 +991,12 @@ describe('schema', function () {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 'secondaryPreferred'});
+      Tobi = new Schema({}, {read: 'secondaryPreferred'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('secondaryPreferred', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['secondaryPreferred', tags]});
+      Tobi = new Schema({}, {read: ['secondaryPreferred', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('secondaryPreferred', Tobi.options.read.mode);
@@ -1004,12 +1004,12 @@ describe('schema', function () {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 'n'});
+      Tobi = new Schema({}, {read: 'n'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('nearest', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['n', tags]});
+      Tobi = new Schema({}, {read: ['n', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('nearest', Tobi.options.read.mode);
@@ -1017,12 +1017,12 @@ describe('schema', function () {
       assert.equal(1, Tobi.options.read.tags.length);
       assert.equal(1, Tobi.options.read.tags[0].x);
 
-      Tobi = Schema({}, {read: 'nearest'});
+      Tobi = new Schema({}, {read: 'nearest'});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('nearest', Tobi.options.read.mode);
 
-      Tobi = Schema({}, {read: ['nearest', tags]});
+      Tobi = new Schema({}, {read: ['nearest', tags]});
       assert.ok(Tobi.options.read instanceof ReadPref);
       assert.ok(Tobi.options.read.isValid());
       assert.equal('nearest', Tobi.options.read.mode);
@@ -1371,13 +1371,13 @@ describe('schema', function () {
       });
 
       assert.doesNotThrow(function () {
-        var s = Schema({docs: [{path: String}]});
+        var s = new Schema({docs: [{path: String}]});
         var M = mongoose.model('gh-1245', s);
         new M({docs: [{path: 'works'}]});
       });
 
       assert.doesNotThrow(function () {
-        var s = Schema({setMaxListeners: String});
+        var s = new Schema({setMaxListeners: String});
         var M = mongoose.model('setMaxListeners-as-property-name', s);
         new M({setMaxListeners: 'works'});
       });
@@ -1408,7 +1408,7 @@ describe('schema', function () {
     var schema;
 
     before(function () {
-      schema = Schema({
+      schema = new Schema({
         n: String,
         nest: {thing: {nests: Boolean}},
         docs: [{x: [{y: String}]}],
@@ -1463,7 +1463,7 @@ describe('schema', function () {
   });
 
   it('required() with doc arrays (gh-3199)', function (done) {
-    var schema = Schema({
+    var schema = new Schema({
       test: [{x: String}]
     });
 
@@ -1476,7 +1476,7 @@ describe('schema', function () {
   });
 
   it('custom typeKey in doc arrays (gh-3560)', function (done) {
-    var schema = Schema({
+    var schema = new Schema({
       test: [{
         name: {$type: String}
       }]
@@ -1492,11 +1492,11 @@ describe('schema', function () {
   });
 
   it('required for single nested schemas (gh-3562)', function (done) {
-    var personSchema = Schema({
+    var personSchema = new Schema({
       name: {type: String, required: true}
     });
 
-    var bandSchema = Schema({
+    var bandSchema = new Schema({
       name: String,
       guitarist: {type: personSchema, required: true}
     });
@@ -1514,7 +1514,7 @@ describe('schema', function () {
 
   describe('remove()', function () {
     before(function () {
-      this.schema = Schema({
+      this.schema = new Schema({
         a: String,
         b: {
           c: {
diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js
index 589e4e84143..2ff101fdd77 100644
--- a/test/schema.validation.test.js
+++ b/test/schema.validation.test.js
@@ -447,7 +447,7 @@ describe('schema', function () {
           setTimeout(function () {
             executed++;
             fn(value === true);
-            if (executed == 2) {
+            if (executed === 2) {
               done();
             }
           }, 5);
diff --git a/test/types.array.test.js b/test/types.array.test.js
index f6b72516d9d..3d8252c9591 100644
--- a/test/types.array.test.js
+++ b/test/types.array.test.js
@@ -1781,7 +1781,7 @@ describe('types array', function () {
     var B;
 
     before(function (done) {
-      var schema = Schema({
+      var schema = new Schema({
         numbers: ['number'],
         numberIds: [{_id: 'number', name: 'string'}],
         stringIds: [{_id: 'string', name: 'string'}],
diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js
index 65a02d50c20..4be76934d15 100644
--- a/test/types.documentarray.test.js
+++ b/test/types.documentarray.test.js
@@ -304,7 +304,7 @@ describe('types.documentarray', function () {
         this.date = new Date;
         next();
       });
-      var schema = Schema({children: [child]});
+      var schema = new Schema({children: [child]});
       var M = db.model('embeddedDocArray-push-re-cast', schema, 'edarecast-' + random());
       var m = new M;
       m.save(function (err) {
@@ -396,7 +396,7 @@ describe('types.documentarray', function () {
 
   describe('invalidate()', function () {
     it('works', function (done) {
-      var schema = Schema({docs: [{name: 'string'}]});
+      var schema = new Schema({docs: [{name: 'string'}]});
       schema.pre('validate', function (next) {
         var subdoc = this.docs[this.docs.length - 1];
         subdoc.invalidate('name', 'boo boo', '%');
@@ -424,8 +424,8 @@ describe('types.documentarray', function () {
 
     it('handles validation failures', function (done) {
       var db = start();
-      var nested = Schema({v: {type: Number, max: 30}});
-      var schema = Schema({
+      var nested = new Schema({v: {type: Number, max: 30}});
+      var schema = new Schema({
         docs: [nested]
       }, {collection: 'embedded-invalidate-' + random()});
       var M = db.model('embedded-invalidate', schema);
@@ -438,8 +438,8 @@ describe('types.documentarray', function () {
 
     it('removes attached event listeners when creating new doc array', function (done) {
       var db = start();
-      var nested = Schema({v: {type: Number}});
-      var schema = Schema({
+      var nested = new Schema({v: {type: Number}});
+      var schema = new Schema({
         docs: [nested]
       }, {collection: 'gh-2159'});
       var M = db.model('gh-2159', schema);
diff --git a/test/versioning.test.js b/test/versioning.test.js
index bc76dfcd673..a954e2df1c3 100644
--- a/test/versioning.test.js
+++ b/test/versioning.test.js
@@ -411,8 +411,8 @@ describe('versioning', function () {
     var v = new V({configured: true});
     v.save(function (err) {
       assert.ifError(err);
-      V.findById(v, function (err, v) {
-        assert.ifError(err);
+      V.findById(v, function (err1, v) {
+        assert.ifError(err1);
         assert.equal(0, v._doc.lolwat);
         done();
       });
@@ -420,7 +420,7 @@ describe('versioning', function () {
   });
 
   it('can be disabled', function (done) {
-    var schema = Schema({x: ['string']}, {versionKey: false});
+    var schema = new Schema({x: ['string']}, {versionKey: false});
     var M = db.model('disabledVersioning', schema, 's' + random());
     M.create({x: ['hi']}, function (err, doc) {
       assert.ifError(err);
diff --git a/website.js b/website.js
index 1ca646cbbb6..ca057816f36 100644
--- a/website.js
+++ b/website.js
@@ -70,7 +70,7 @@ files.forEach(function (file) {
   var filename = __dirname + '/' + file;
   jadeify(filename, filemap[file]);
 
-  if ('--watch' === process.argv[2]) {
+  if (process.argv[2] === '--watch') {
     fs.watchFile(filename, {interval: 1000}, function (cur, prev) {
       if (cur.mtime > prev.mtime) {
         jadeify(filename, filemap[file]);

From cefea6cf5bf0ac90e2ebbe943a6d56a3fc64987d Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Mon, 1 Feb 2016 08:38:01 -0700
Subject: [PATCH 0239/2240] run lint after tests, update lint rules

---
 .eslintrc.yml | 12 ++++++------
 package.json  |  5 +++--
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/.eslintrc.yml b/.eslintrc.yml
index 99f448b31b9..419fce4eedb 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -14,18 +14,18 @@ rules:
     - 2
     - SwitchCase: 1
       VariableDeclarator: 2
-  key-spacing: 1
+  keyword-spacing: 2
   no-console: 0
-  no-multi-spaces: 1
+  no-multi-spaces: 2
   no-spaced-func: 2
   no-trailing-spaces: 2
+  quotes:
+    - 2
+    - single
   semi: 2
-  space-after-keywords: 2
   space-before-blocks: 2
   space-before-function-paren:
     - 2
     - never
-  space-before-keywords: 2
   space-infix-ops: 2
-  space-return-throw-case: 2
-  space-unary-ops: 1
+  space-unary-ops: 2
diff --git a/package.json b/package.json
index d6bc906de76..4bbab751f24 100644
--- a/package.json
+++ b/package.json
@@ -65,10 +65,11 @@
     "lib": "./lib/mongoose"
   },
   "scripts": {
+    "fix-lint": "eslint . --fix",
     "install-browser": "npm install `node format_deps.js`",
     "test": "mocha test/*.test.js test/**/*.test.js",
-    "test-cov": "istanbul cover --report text --report html _mocha test/*.test.js",
-    "lint": "eslint . --quiet"
+    "postlint": "eslint . --quiet",
+    "test-cov": "istanbul cover --report text --report html _mocha test/*.test.js"
   },
   "main": "./index.js",
   "engines": {

From 9890109c12b3ba80e9e7824fa988857f7788ee2c Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Mon, 1 Feb 2016 08:39:34 -0700
Subject: [PATCH 0240/2240] run `fix-lint` across project

---
 benchmarks/benchjs/casting.js                 |   16 +-
 benchmarks/benchjs/delete.js                  |   26 +-
 benchmarks/benchjs/insert.js                  |   28 +-
 benchmarks/benchjs/multiop.js                 |   84 +-
 benchmarks/benchjs/population.js              |   62 +-
 benchmarks/benchjs/read.js                    |   62 +-
 benchmarks/benchjs/update.js                  |   70 +-
 benchmarks/clone.js                           |    2 +-
 benchmarks/index.js                           |   28 +-
 benchmarks/mem.js                             |   36 +-
 benchmarks/populate.js                        |    8 +-
 benchmarks/populationHeavyLoad.js             |   28 +-
 examples/aggregate/aggregate.js               |   10 +-
 examples/aggregate/person.js                  |    2 +-
 examples/doc-methods.js                       |    8 +-
 examples/express/connection-sharing/app.js    |    2 +-
 examples/express/connection-sharing/routes.js |   10 +-
 examples/geospatial/geoJSONSchema.js          |    2 +-
 examples/geospatial/geoJSONexample.js         |   12 +-
 examples/geospatial/geospatial.js             |   14 +-
 examples/geospatial/person.js                 |    4 +-
 examples/globalschemas/gs_example.js          |   12 +-
 examples/globalschemas/person.js              |    2 +-
 examples/lean/lean.js                         |   10 +-
 examples/lean/person.js                       |    2 +-
 examples/mapreduce/mapreduce.js               |   14 +-
 examples/mapreduce/person.js                  |    2 +-
 .../population-across-three-collections.js    |   14 +-
 examples/population/population-basic.js       |   12 +-
 .../population/population-of-existing-doc.js  |   14 +-
 .../population-of-multiple-existing-docs.js   |   16 +-
 examples/population/population-options.js     |   14 +-
 .../population/population-plain-objects.js    |   12 +-
 examples/promises/person.js                   |    2 +-
 examples/promises/promise.js                  |   20 +-
 examples/querybuilder/person.js               |    2 +-
 examples/querybuilder/querybuilder.js         |   10 +-
 examples/replicasets/person.js                |    2 +-
 examples/replicasets/replica-sets.js          |   10 +-
 examples/schema/schema.js                     |   14 +-
 examples/statics/person.js                    |    4 +-
 examples/statics/statics.js                   |    8 +-
 format_deps.js                                |    2 +-
 karma.local.conf.js                           |    2 +-
 karma.sauce.conf.js                           |    2 +-
 lib/ES6Promise.js                             |    2 +-
 lib/aggregate.js                              |   56 +-
 lib/cast.js                                   |    6 +-
 lib/collection.js                             |   28 +-
 lib/connection.js                             |   54 +-
 lib/document.js                               |  178 +--
 lib/document_provider.js                      |    2 +-
 lib/drivers/browser/ReadPreference.js         |    2 +-
 lib/drivers/node-mongodb-native/collection.js |   30 +-
 lib/drivers/node-mongodb-native/connection.js |   32 +-
 lib/error/validation.js                       |    4 +-
 lib/error/validator.js                        |    4 +-
 lib/index.js                                  |   30 +-
 lib/model.js                                  |  138 +-
 lib/promise.js                                |   10 +-
 lib/promise_provider.js                       |    6 +-
 lib/query.js                                  |  100 +-
 lib/querystream.js                            |   22 +-
 lib/schema.js                                 |   82 +-
 lib/schema/array.js                           |   28 +-
 lib/schema/boolean.js                         |    6 +-
 lib/schema/buffer.js                          |    8 +-
 lib/schema/date.js                            |   22 +-
 lib/schema/documentarray.js                   |   14 +-
 lib/schema/embedded.js                        |   16 +-
 lib/schema/mixed.js                           |    8 +-
 lib/schema/number.js                          |   20 +-
 lib/schema/objectid.js                        |    8 +-
 lib/schema/operators/bitwise.js               |    2 +-
 lib/schema/string.js                          |   40 +-
 lib/schematype.js                             |   48 +-
 lib/services/updateValidators.js              |   16 +-
 lib/statemachine.js                           |   16 +-
 lib/types/array.js                            |   50 +-
 lib/types/buffer.js                           |   16 +-
 lib/types/documentarray.js                    |   12 +-
 lib/types/embedded.js                         |   28 +-
 lib/types/subdocument.js                      |   16 +-
 lib/utils.js                                  |   40 +-
 lib/virtualtype.js                            |    8 +-
 package.json                                  |    2 +-
 static.js                                     |    6 +-
 test/aggregate.test.js                        |  216 +--
 test/browser/document.test_.js                |   40 +-
 test/browser/example.test_.js                 |   16 +-
 test/browser/schema.test_.js                  |  162 +-
 test/browser/schema.validation.test_.js       |  230 +--
 test/browser/types.buffer.test_.js            |    8 +-
 test/browser/types.number.test_.js            |   16 +-
 test/browser/types.objectid.test_.js          |   20 +-
 test/cast.test.js                             |   14 +-
 test/collection.capped.test.js                |   28 +-
 test/collection.test.js                       |   10 +-
 test/colors.js                                |   16 +-
 test/common.js                                |   34 +-
 test/connection.auth.test.js                  |   12 +-
 test/connection.reconnect.test.js             |   14 +-
 test/connection.test.js                       |  376 ++---
 test/crash.test.js                            |    6 +-
 test/document.hooks.test.js                   |  238 +--
 test/document.isselected.test.js              |   18 +-
 test/document.modified.test.js                |   98 +-
 test/document.populate.test.js                |  166 +-
 test/document.strict.test.js                  |   98 +-
 test/document.test.js                         |  512 +++----
 test/document.unit.test.js                    |   22 +-
 test/errors.validation.test.js                |   54 +-
 test/gh-1408.test.js                          |   14 +-
 test/harmony/document.test_.js                |   18 +-
 test/harmony/model.test_.js                   |   18 +-
 test/harmony/query.test_.js                   |   12 +-
 test/index.test.js                            |  114 +-
 test/model.aggregate.test.js                  |   36 +-
 test/model.create.test.js                     |   54 +-
 test/model.discriminator.querying.test.js     |  286 ++--
 test/model.discriminator.test.js              |  102 +-
 test/model.field.selection.test.js            |  104 +-
 test/model.findAndRemoveOne.test.js           |   86 +-
 test/model.findOneAndUpdate.test.js           |  290 ++--
 test/model.geonear.test.js                    |   66 +-
 test/model.geosearch.test.js                  |   48 +-
 test/model.hydrate.test.js                    |   16 +-
 test/model.indexes.test.js                    |   96 +-
 test/model.mapreduce.test.js                  |   96 +-
 test/model.middleware.test.js                 |   68 +-
 test/model.populate.divergent.test.js         |   72 +-
 test/model.populate.setting.test.js           |   38 +-
 test/model.populate.test.js                   |  740 ++++-----
 test/model.query.casting.test.js              |  182 +--
 test/model.querying.test.js                   |  756 ++++-----
 test/model.stream.test.js                     |  104 +-
 test/model.test.js                            | 1348 ++++++++---------
 test/model.update.test.js                     |  490 +++---
 test/object.create.null.test.js               |   24 +-
 test/promise.test.js                          |   88 +-
 test/promise_provider.test.js                 |  190 +--
 test/query.middleware.test.js                 |   80 +-
 test/query.test.js                            |  494 +++---
 test/query.toconstructor.test.js              |   30 +-
 test/schema.boolean.test.js                   |    6 +-
 test/schema.documentarray.test.js             |   10 +-
 test/schema.mixed.test.js                     |    8 +-
 test/schema.onthefly.test.js                  |   22 +-
 test/schema.select.test.js                    |  146 +-
 test/schema.test.js                           |  286 ++--
 test/schema.timestamps.test.js                |   46 +-
 test/schema.type.test.js                      |    6 +-
 test/schema.validation.test.js                |  320 ++--
 test/shard.test.js                            |   82 +-
 test/types.array.test.js                      |  468 +++---
 test/types.buffer.test.js                     |  118 +-
 test/types.document.test.js                   |   44 +-
 test/types.documentarray.test.js              |   76 +-
 test/types.number.test.js                     |   18 +-
 test/updateValidators.unit.test.js            |   28 +-
 test/utils.test.js                            |   92 +-
 test/versioning.test.js                       |   92 +-
 website.js                                    |   12 +-
 163 files changed, 6198 insertions(+), 6198 deletions(-)

diff --git a/benchmarks/benchjs/casting.js b/benchmarks/benchjs/casting.js
index bed7f285f83..d5ca05d0141 100644
--- a/benchmarks/benchjs/casting.js
+++ b/benchmarks/benchjs/casting.js
@@ -92,44 +92,44 @@ var commentData = {
 BlogPost = mongoose.model('BlogPost', BlogPost);
 
 suite.add('Casting - Embedded Docs - 0 Docs', {
-  fn: function () {
+  fn: function() {
     var BlogPost = mongoose.model('BlogPost');
     var bp = new BlogPost();
     bp.init(blogData);
   }
 }).add('Casting - Embedded Docs - 10 Docs', {
-  fn: function () {
+  fn: function() {
     var BlogPost = mongoose.model('BlogPost');
     var bp = new BlogPost();
     bp.init(blogData10);
   }
 }).add('Casting - Embedded Docs - 100 Docs', {
-  fn: function () {
+  fn: function() {
     var BlogPost = mongoose.model('BlogPost');
     var bp = new BlogPost();
     bp.init(blogData100);
   }
 }).add('Casting - Embedded Docs - 1000 Docs', {
-  fn: function () {
+  fn: function() {
     var BlogPost = mongoose.model('BlogPost');
     var bp = new BlogPost();
     bp.init(blogData1000);
   }
 }).add('Casting - Embedded Docs - 10000 Docs', {
-  fn: function () {
+  fn: function() {
     var BlogPost = mongoose.model('BlogPost');
     var bp = new BlogPost();
     bp.init(blogData10000);
   }
 })
-.on('cycle', function (evt) {
+.on('cycle', function(evt) {
   if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) {
     console.log(String(evt.target));
   }
-}).on('complete', function () {
+}).on('complete', function() {
   if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) {
     var outObj = {};
-    this.forEach(function (item) {
+    this.forEach(function(item) {
       var out = {};
       out.stats = item.stats;
       delete out.stats.sample;
diff --git a/benchmarks/benchjs/delete.js b/benchmarks/benchjs/delete.js
index 62287084602..028ac6b34e7 100644
--- a/benchmarks/benchjs/delete.js
+++ b/benchmarks/benchjs/delete.js
@@ -17,11 +17,11 @@ var mongo = require('mongodb');
  */
 
 
-mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
+mongoose.connect('mongodb://localhost/mongoose-bench', function(err) {
   if (err) {
     throw err;
   }
-  mongo.connect('mongodb://localhost/mongoose-bench', function (err, db) {
+  mongo.connect('mongodb://localhost/mongoose-bench', function(err, db) {
     if (err) {
       throw err;
     }
@@ -48,7 +48,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
     // insert all of the data here
     var count = 1000;
     for (var i = 0; i < 500; i++) {
-      User.create(data, function (err, u) {
+      User.create(data, function(err, u) {
         if (err) {
           throw err;
         }
@@ -60,20 +60,20 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       nData.age = data.age;
       nData.likes = data.likes;
       nData.address = data.address;
-      user.insert(nData, function (err, res) {
+      user.insert(nData, function(err, res) {
         dIds.push(res[0]._id);
         --count || next();
       });
     }
 
     function closeDB() {
-      User.count(function (err, res) {
+      User.count(function(err, res) {
         if (res !== 0) {
           console.log('Still mongoose entries left...');
         }
         mongoose.disconnect();
       });
-      user.count({}, function (err, res) {
+      user.count({}, function(err, res) {
         if (res !== 0) {
           console.log('Still driver entries left...');
         }
@@ -86,8 +86,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
 
     suite.add('Delete - Mongoose', {
       defer: true,
-      fn: function (deferred) {
-        User.remove({_id: mIds.pop()}, function (err) {
+      fn: function(deferred) {
+        User.remove({_id: mIds.pop()}, function(err) {
           if (err) {
             throw err;
           }
@@ -96,8 +96,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Delete - Driver', {
       defer: true,
-      fn: function (deferred) {
-        user.remove({_id: dIds.pop()}, function (err) {
+      fn: function(deferred) {
+        user.remove({_id: dIds.pop()}, function(err) {
           if (err) {
             throw err;
           }
@@ -105,15 +105,15 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
         });
       }
     })
-    .on('cycle', function (evt) {
+    .on('cycle', function(evt) {
       if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) {
         console.log(String(evt.target));
       }
-    }).on('complete', function () {
+    }).on('complete', function() {
       closeDB();
       if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) {
         var outObj = {};
-        this.forEach(function (item) {
+        this.forEach(function(item) {
           var out = {};
           out.stats = item.stats;
           delete out.stats.sample;
diff --git a/benchmarks/benchjs/insert.js b/benchmarks/benchjs/insert.js
index e694348403e..b2d257880b0 100644
--- a/benchmarks/benchjs/insert.js
+++ b/benchmarks/benchjs/insert.js
@@ -19,11 +19,11 @@ var ObjectId = Schema.Types.ObjectId;
  */
 
 
-mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
+mongoose.connect('mongodb://localhost/mongoose-bench', function(err) {
   if (err) {
     throw err;
   }
-  mongo.connect('mongodb://localhost/mongoose-bench', function (err, db) {
+  mongo.connect('mongodb://localhost/mongoose-bench', function(err, db) {
     if (err) {
       throw err;
     }
@@ -103,7 +103,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
     var blogpost = db.collection('blogpost');
 
     function closeDB() {
-      mongoose.connection.db.dropDatabase(function () {
+      mongoose.connection.db.dropDatabase(function() {
         mongoose.disconnect();
         process.exit();
       });
@@ -111,9 +111,9 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
 
     suite.add('Insert - Mongoose - Basic', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var nData = utils.clone(data);
-        User.create(nData, function (err) {
+        User.create(nData, function(err) {
           if (err) {
             throw err;
           }
@@ -122,9 +122,9 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Insert - Driver - Basic', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var nData = utils.clone(data);
-        user.insert(nData, function (err) {
+        user.insert(nData, function(err) {
           if (err) {
             throw err;
           }
@@ -133,9 +133,9 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Insert - Mongoose - Embedded Docs', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var bp = utils.clone(blogData);
-        BlogPost.create(bp, function (err) {
+        BlogPost.create(bp, function(err) {
           if (err) {
             throw err;
           }
@@ -144,9 +144,9 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Insert - Driver - Embedded Docs', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var bp = utils.clone(blogData);
-        blogpost.insert(bp, function (err) {
+        blogpost.insert(bp, function(err) {
           if (err) {
             throw err;
           }
@@ -154,15 +154,15 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
         });
       }
     })
-    .on('cycle', function (evt) {
+    .on('cycle', function(evt) {
       if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) {
         console.log(String(evt.target));
       }
-    }).on('complete', function () {
+    }).on('complete', function() {
       closeDB();
       if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) {
         var outObj = {};
-        this.forEach(function (item) {
+        this.forEach(function(item) {
           var out = {};
           out.stats = item.stats;
           delete out.stats.sample;
diff --git a/benchmarks/benchjs/multiop.js b/benchmarks/benchjs/multiop.js
index 13da718b9f4..8b121a19391 100644
--- a/benchmarks/benchjs/multiop.js
+++ b/benchmarks/benchjs/multiop.js
@@ -19,11 +19,11 @@ var utils = require('../../lib/utils.js');
  */
 
 
-mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
+mongoose.connect('mongodb://localhost/mongoose-bench', function(err) {
   if (err) {
     throw err;
   }
-  mongo.connect('mongodb://localhost/mongoose-bench', function (err, db) {
+  mongo.connect('mongodb://localhost/mongoose-bench', function(err, db) {
     if (err) {
       throw err;
     }
@@ -114,7 +114,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
     var count = 4000;
     for (i = 0; i < 1000; i++) {
       data.age = Math.floor(Math.random() * 50);
-      User.create(data, function (err, u) {
+      User.create(data, function(err, u) {
         if (err) {
           throw err;
         }
@@ -122,14 +122,14 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
         --count || next();
       });
       var nData = utils.clone(data);
-      user.insert(nData, function (err, res) {
+      user.insert(nData, function(err, res) {
         if (err) {
           throw err;
         }
         dIds.push(res[0]._id);
         --count || next();
       });
-      BlogPost.create(blogData, function (err, bp) {
+      BlogPost.create(blogData, function(err, bp) {
         if (err) {
           throw err;
         }
@@ -138,7 +138,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       });
 
       var bpData = utils.clone(blogData);
-      blogpost.insert(bpData, function (err, res) {
+      blogpost.insert(bpData, function(err, res) {
         if (err) {
           throw err;
         }
@@ -173,7 +173,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
     }
 
     function closeDB() {
-      mongoose.connection.db.dropDatabase(function () {
+      mongoose.connection.db.dropDatabase(function() {
         mongoose.disconnect();
         process.exit();
       });
@@ -181,10 +181,10 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
 
     suite.add('Multi-Op - Mongoose - Heavy Read, low write', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
         for (var i = 0; i < 150; i++) {
-          User.findOne({_id: getNextmId()}, function (err) {
+          User.findOne({_id: getNextmId()}, function(err) {
             if (err) {
               throw err;
             }
@@ -192,7 +192,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
           });
           if (i % 15 === 0) {
             var nData = utils.clone(data);
-            User.create(nData, function (err) {
+            User.create(nData, function(err) {
               if (err) {
                 throw err;
               }
@@ -203,10 +203,10 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Multi-Op - Driver - Heavy Read, low write', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
         for (var i = 0; i < 150; i++) {
-          user.findOne({_id: getNextdId()}, function (err) {
+          user.findOne({_id: getNextdId()}, function(err) {
             if (err) {
               throw err;
             }
@@ -214,7 +214,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
           });
           if (i % 15 === 0) {
             var nData = utils.clone(data);
-            user.insert(nData, function (err) {
+            user.insert(nData, function(err) {
               if (err) {
                 throw err;
               }
@@ -225,10 +225,10 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Multi-Op - Mongoose - Embedded Docs - Heavy Read, low write', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
         for (var i = 0; i < 150; i++) {
-          BlogPost.findOne({_id: getNextbmId()}, function (err) {
+          BlogPost.findOne({_id: getNextbmId()}, function(err) {
             if (err) {
               throw err;
             }
@@ -236,7 +236,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
           });
           if (i % 15 === 0) {
             var nData = utils.clone(blogData);
-            BlogPost.create(nData, function (err) {
+            BlogPost.create(nData, function(err) {
               if (err) {
                 throw err;
               }
@@ -247,10 +247,10 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Multi-Op - Driver - Embedded Docs - Heavy Read, low write', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
         for (var i = 0; i < 150; i++) {
-          blogpost.findOne({_id: getNextbdId()}, function (err) {
+          blogpost.findOne({_id: getNextbdId()}, function(err) {
             if (err) {
               throw err;
             }
@@ -258,7 +258,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
           });
           if (i % 15 === 0) {
             var nData = utils.clone(blogData);
-            blogpost.insert(nData, function (err) {
+            blogpost.insert(nData, function(err) {
               if (err) {
                 throw err;
               }
@@ -269,19 +269,19 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Multi-Op - Mongoose - Heavy Write, low read', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
 
         for (var i = 0; i < 150; i++) {
           var nData = utils.clone(data);
-          User.create(nData, function (err) {
+          User.create(nData, function(err) {
             if (err) {
               throw err;
             }
             --count || deferred.resolve();
           });
           if (i % 15 === 0) {
-            User.findOne({_id: getNextmId()}, function (err) {
+            User.findOne({_id: getNextmId()}, function(err) {
               if (err) {
                 throw err;
               }
@@ -292,19 +292,19 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Multi-Op - Driver - Heavy Write, low read', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
 
         for (var i = 0; i < 150; i++) {
           var nData = utils.clone(data);
-          user.insert(nData, function (err) {
+          user.insert(nData, function(err) {
             if (err) {
               throw err;
             }
             --count || deferred.resolve();
           });
           if (i % 15 === 0) {
-            user.findOne({_id: getNextdId()}, function (err) {
+            user.findOne({_id: getNextdId()}, function(err) {
               if (err) {
                 throw err;
               }
@@ -315,19 +315,19 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Multi-Op - Mongoose - Embedded Docs - Heavy Write, low read', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
 
         for (var i = 0; i < 150; i++) {
           var nData = utils.clone(blogData);
-          BlogPost.create(nData, function (err) {
+          BlogPost.create(nData, function(err) {
             if (err) {
               throw err;
             }
             --count || deferred.resolve();
           });
           if (i % 15 === 0) {
-            BlogPost.findOne({_id: getNextbmId()}, function (err) {
+            BlogPost.findOne({_id: getNextbmId()}, function(err) {
               if (err) {
                 throw err;
               }
@@ -338,19 +338,19 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Multi-Op - Driver - Embedded Docs - Heavy Write, low read', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
 
         for (var i = 0; i < 150; i++) {
           var nData = utils.clone(blogData);
-          blogpost.insert(nData, function (err) {
+          blogpost.insert(nData, function(err) {
             if (err) {
               throw err;
             }
             --count || deferred.resolve();
           });
           if (i % 15 === 0) {
-            blogpost.findOne({_id: getNextbdId()}, function (err) {
+            blogpost.findOne({_id: getNextbdId()}, function(err) {
               if (err) {
                 throw err;
               }
@@ -361,11 +361,11 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Multi-Op - Mongoose - Embedded Docs - Read-write-update', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
         var updates = 0;
         for (var i = 0; i < 150; i++) {
-          BlogPost.findOne({_id: getNextbmId()}, function (err, res) {
+          BlogPost.findOne({_id: getNextbmId()}, function(err, res) {
             if (err) {
               throw err;
             }
@@ -374,7 +374,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
               res.author = 'soemthing new';
               res.comments.push(commentData);
               res.title = 'something newerrrr';
-              res.save(function (err) {
+              res.save(function(err) {
                 if (err) {
                   throw err;
                 }
@@ -386,7 +386,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
           });
           if (i % 15 === 0) {
             var nData = utils.clone(blogData);
-            BlogPost.create(nData, function (err) {
+            BlogPost.create(nData, function(err) {
               if (err) {
                 throw err;
               }
@@ -397,11 +397,11 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Multi-Op - Driver - Embedded Docs - Read-write-update', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var count = 150;
         var updates = 0;
         for (var i = 0; i < 150; i++) {
-          blogpost.findOne({_id: getNextbdId()}, function (err, bp) {
+          blogpost.findOne({_id: getNextbdId()}, function(err, bp) {
             if (err) {
               throw err;
             }
@@ -410,7 +410,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
               bp.author = 'soemthing new';
               bp.comments.push(commentData);
               bp.title = 'something newerrrr';
-              blogpost.save(bp, function (err) {
+              blogpost.save(bp, function(err) {
                 if (err) {
                   throw err;
                 }
@@ -422,7 +422,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
           });
           if (i % 15 === 0) {
             var nData = utils.clone(blogData);
-            blogpost.insert(nData, function (err) {
+            blogpost.insert(nData, function(err) {
               if (err) {
                 throw err;
               }
@@ -432,15 +432,15 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
         }
       }
     })
-    .on('cycle', function (evt) {
+    .on('cycle', function(evt) {
       if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) {
         console.log(String(evt.target));
       }
-    }).on('complete', function () {
+    }).on('complete', function() {
       closeDB();
       if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) {
         var outObj = {};
-        this.forEach(function (item) {
+        this.forEach(function(item) {
           var out = {};
           out.stats = item.stats;
           delete out.stats.sample;
diff --git a/benchmarks/benchjs/population.js b/benchmarks/benchjs/population.js
index 5ffe7ce7224..0a966d45c3a 100644
--- a/benchmarks/benchjs/population.js
+++ b/benchmarks/benchjs/population.js
@@ -18,7 +18,7 @@ var utils = require('../../lib/utils.js');
  */
 
 
-mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
+mongoose.connect('mongodb://localhost/mongoose-bench-pop', function(err) {
   if (err) {
     throw err;
   }
@@ -142,67 +142,67 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
 
   var cn = 5000;
   for (i = 0; i < 500; i++) {
-    Comments.create(commentData, function (err, com) {
+    Comments.create(commentData, function(err, com) {
       cIds.push(com.id);
       --cn || cont();
     });
-    Dummy1.create(dummyData, function (err, d) {
+    Dummy1.create(dummyData, function(err, d) {
       if (err) {
         throw err;
       }
       dIds[0].push(d.id);
       --cn || cont();
     });
-    Dummy2.create(dummyData, function (err, d) {
+    Dummy2.create(dummyData, function(err, d) {
       if (err) {
         throw err;
       }
       dIds[1].push(d.id);
       --cn || cont();
     });
-    Dummy3.create(dummyData, function (err, d) {
+    Dummy3.create(dummyData, function(err, d) {
       if (err) {
         throw err;
       }
       dIds[2].push(d.id);
       --cn || cont();
     });
-    Dummy4.create(dummyData, function (err, d) {
+    Dummy4.create(dummyData, function(err, d) {
       if (err) {
         throw err;
       }
       dIds[3].push(d.id);
       --cn || cont();
     });
-    Dummy5.create(dummyData, function (err, d) {
+    Dummy5.create(dummyData, function(err, d) {
       if (err) {
         throw err;
       }
       dIds[4].push(d.id);
       --cn || cont();
     });
-    Dummy6.create(dummyData, function (err, d) {
+    Dummy6.create(dummyData, function(err, d) {
       if (err) {
         throw err;
       }
       dIds[5].push(d.id);
       --cn || cont();
     });
-    Dummy7.create(dummyData, function (err, d) {
+    Dummy7.create(dummyData, function(err, d) {
       if (err) {
         throw err;
       }
       dIds[6].push(d.id);
       --cn || cont();
     });
-    Dummy8.create(dummyData, function (err, d) {
+    Dummy8.create(dummyData, function(err, d) {
       if (err) {
         throw err;
       }
       dIds[7].push(d.id);
       --cn || cont();
     });
-    Dummy9.create(dummyData, function (err, d) {
+    Dummy9.create(dummyData, function(err, d) {
       if (err) {
         throw err;
       }
@@ -260,8 +260,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
     var count = 7;
     for (i = 0; i < blog.length; i++) {
       // use some closure magic to make sure we retain the index
-      (function (c) {
-        BlogPost.create(blog[c], function (err, bl) {
+      (function(c) {
+        BlogPost.create(blog[c], function(err, bl) {
           if (err) {
             throw err;
           }
@@ -291,7 +291,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
 
   function closeDB() {
     // just a bit simpler...
-    mongoose.connection.db.dropDatabase(function () {
+    mongoose.connection.db.dropDatabase(function() {
       mongoose.disconnect();
       process.exit();
     });
@@ -299,8 +299,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
 
   suite.add('Populate - 1 value', {
     defer: true,
-    fn: function (deferred) {
-      blog[4].populate('comments', function (err) {
+    fn: function(deferred) {
+      blog[4].populate('comments', function(err) {
         if (err) {
           throw err;
         }
@@ -309,8 +309,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
     }
   }).add('Populate - 10 values', {
     defer: true,
-    fn: function (deferred) {
-      blog[0].populate('comments', function (err) {
+    fn: function(deferred) {
+      blog[0].populate('comments', function(err) {
         if (err) {
           throw err;
         }
@@ -319,8 +319,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
     }
   }).add('Populate - 100 values', {
     defer: true,
-    fn: function (deferred) {
-      blog[1].populate('comments', function (err) {
+    fn: function(deferred) {
+      blog[1].populate('comments', function(err) {
         if (err) {
           throw err;
         }
@@ -329,8 +329,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
     }
   }).add('Populate - 1000 values', {
     defer: true,
-    fn: function (deferred) {
-      blog[2].populate('comments', function (err) {
+    fn: function(deferred) {
+      blog[2].populate('comments', function(err) {
         if (err) {
           throw err;
         }
@@ -339,8 +339,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
     }
   }).add('Populate - 10000 values', {
     defer: true,
-    fn: function (deferred) {
-      blog[3].populate('comments', function (err) {
+    fn: function(deferred) {
+      blog[3].populate('comments', function(err) {
         if (err) {
           throw err;
         }
@@ -349,8 +349,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
     }
   }).add('Populate - 5 properties', {
     defer: true,
-    fn: function (deferred) {
-      blog[5].populate('comments dummy1 dummy2 dummy3 dummy4', function (err) {
+    fn: function(deferred) {
+      blog[5].populate('comments dummy1 dummy2 dummy3 dummy4', function(err) {
         if (err) {
           throw err;
         }
@@ -359,8 +359,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
     }
   }).add('Populate - 10 properties', {
     defer: true,
-    fn: function (deferred) {
-      blog[6].populate('comments dummy1 dummy2 dummy3 dummy4 dummy5 dummy6 dummy7 dummy8 dummy9', function (err) {
+    fn: function(deferred) {
+      blog[6].populate('comments dummy1 dummy2 dummy3 dummy4 dummy5 dummy6 dummy7 dummy8 dummy9', function(err) {
         if (err) {
           throw err;
         }
@@ -369,15 +369,15 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function (err) {
     }
   })
 
-  .on('cycle', function (evt) {
+  .on('cycle', function(evt) {
     if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) {
       console.log(String(evt.target));
     }
-  }).on('complete', function () {
+  }).on('complete', function() {
     closeDB();
     if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) {
       var outObj = {};
-      this.forEach(function (item) {
+      this.forEach(function(item) {
         var out = {};
         out.stats = item.stats;
         delete out.stats.sample;
diff --git a/benchmarks/benchjs/read.js b/benchmarks/benchjs/read.js
index 20de5631e2e..652191de73a 100644
--- a/benchmarks/benchjs/read.js
+++ b/benchmarks/benchjs/read.js
@@ -19,11 +19,11 @@ var utils = require('../../lib/utils.js');
  */
 
 
-mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
+mongoose.connect('mongodb://localhost/mongoose-bench', function(err) {
   if (err) {
     throw err;
   }
-  mongo.connect('mongodb://localhost/mongoose-bench', function (err, db) {
+  mongo.connect('mongodb://localhost/mongoose-bench', function(err, db) {
     if (err) {
       throw err;
     }
@@ -108,7 +108,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
     var count = 4000;
     for (i = 0; i < 1000; i++) {
       data.age = Math.floor(Math.random() * 50);
-      User.create(data, function (err, u) {
+      User.create(data, function(err, u) {
         if (err) {
           throw err;
         }
@@ -116,14 +116,14 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
         --count || next();
       });
       var nData = utils.clone(data);
-      user.insert(nData, function (err, res) {
+      user.insert(nData, function(err, res) {
         if (err) {
           throw err;
         }
         dIds.push(res[0]._id);
         --count || next();
       });
-      BlogPost.create(blogData, function (err, bp) {
+      BlogPost.create(blogData, function(err, bp) {
         if (err) {
           throw err;
         }
@@ -132,7 +132,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       });
 
       var bpData = utils.clone(blogData);
-      blogpost.insert(bpData, function (err, res) {
+      blogpost.insert(bpData, function(err, res) {
         if (err) {
           throw err;
         }
@@ -167,7 +167,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
     }
 
     function closeDB() {
-      mongoose.connection.db.dropDatabase(function () {
+      mongoose.connection.db.dropDatabase(function() {
         mongoose.disconnect();
         process.exit();
       });
@@ -175,8 +175,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
 
     suite.add('Read - Mongoose - Basic', {
       defer: true,
-      fn: function (deferred) {
-        User.findOne({_id: getNextmId()}, function (err) {
+      fn: function(deferred) {
+        User.findOne({_id: getNextmId()}, function(err) {
           if (err) {
             throw err;
           }
@@ -185,8 +185,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Read - Driver - Basic', {
       defer: true,
-      fn: function (deferred) {
-        user.findOne({_id: getNextdId()}, function (err) {
+      fn: function(deferred) {
+        user.findOne({_id: getNextdId()}, function(err) {
           if (err) {
             throw err;
           }
@@ -195,8 +195,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Read - Mongoose - With lean', {
       defer: true,
-      fn: function (deferred) {
-        User.findOne({_id: getNextmId()}, {}, {lean: true}, function (err) {
+      fn: function(deferred) {
+        User.findOne({_id: getNextmId()}, {}, {lean: true}, function(err) {
           if (err) {
             throw err;
           }
@@ -205,12 +205,12 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Read - Mongoose - Multiple Items', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var ids = [];
         for (var i = 0; i < 25; i++) {
           ids.push(getNextmId());
         }
-        User.find({_id: {$in: ids}}, function (err) {
+        User.find({_id: {$in: ids}}, function(err) {
           if (err) {
             throw err;
           }
@@ -219,16 +219,16 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Read - Driver - Multiple Items', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var ids = [];
         for (var i = 0; i < 25; i++) {
           ids.push(getNextdId());
         }
-        user.find({_id: {$in: ids}}, function (err, cursor) {
+        user.find({_id: {$in: ids}}, function(err, cursor) {
           if (err) {
             throw err;
           }
-          cursor.toArray(function (err) {
+          cursor.toArray(function(err) {
             if (err) {
               throw err;
             }
@@ -238,10 +238,10 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Read - Mongoose - Non-index', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var age = Math.floor(Math.random() * 50);
 
-        User.find({age: age}, function (err) {
+        User.find({age: age}, function(err) {
           if (err) {
             throw err;
           }
@@ -250,14 +250,14 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Read - Driver - Non-index', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var age = Math.floor(Math.random() * 50);
 
-        user.find({age: age}, function (err, cursor) {
+        user.find({age: age}, function(err, cursor) {
           if (err) {
             throw err;
           }
-          cursor.toArray(function (err) {
+          cursor.toArray(function(err) {
             if (err) {
               throw err;
             }
@@ -267,8 +267,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Read - Mongoose - Embedded Docs', {
       defer: true,
-      fn: function (deferred) {
-        BlogPost.find({_id: getNextbmId()}, function (err) {
+      fn: function(deferred) {
+        BlogPost.find({_id: getNextbmId()}, function(err) {
           if (err) {
             throw err;
           }
@@ -277,12 +277,12 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Read - Driver - Embedded Docs', {
       defer: true,
-      fn: function (deferred) {
-        blogpost.find({_id: getNextbdId()}, function (err, cursor) {
+      fn: function(deferred) {
+        blogpost.find({_id: getNextbdId()}, function(err, cursor) {
           if (err) {
             throw err;
           }
-          cursor.toArray(function (err) {
+          cursor.toArray(function(err) {
             if (err) {
               throw err;
             }
@@ -291,15 +291,15 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
         });
       }
     })
-    .on('cycle', function (evt) {
+    .on('cycle', function(evt) {
       if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) {
         console.log(String(evt.target));
       }
-    }).on('complete', function () {
+    }).on('complete', function() {
       closeDB();
       if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) {
         var outObj = {};
-        this.forEach(function (item) {
+        this.forEach(function(item) {
           var out = {};
           out.stats = item.stats;
           delete out.stats.sample;
diff --git a/benchmarks/benchjs/update.js b/benchmarks/benchjs/update.js
index f04a360a93e..62bd971226b 100644
--- a/benchmarks/benchjs/update.js
+++ b/benchmarks/benchjs/update.js
@@ -19,11 +19,11 @@ var utils = require('../../lib/utils.js');
  */
 
 
-mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
+mongoose.connect('mongodb://localhost/mongoose-bench', function(err) {
   if (err) {
     throw err;
   }
-  mongo.connect('mongodb://localhost/mongoose-bench', function (err, db) {
+  mongo.connect('mongodb://localhost/mongoose-bench', function(err, db) {
     if (err) {
       throw err;
     }
@@ -106,7 +106,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
     // insert all of the data here
     var count = 4000;
     for (i = 0; i < 1000; i++) {
-      User.create(data, function (err, u) {
+      User.create(data, function(err, u) {
         if (err) {
           throw err;
         }
@@ -114,11 +114,11 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
         --count || next();
       });
       var nData = utils.clone(data);
-      user.insert(nData, function (err, res) {
+      user.insert(nData, function(err, res) {
         dIds.push(res[0]._id);
         --count || next();
       });
-      BlogPost.create(blogData, function (err, bp) {
+      BlogPost.create(blogData, function(err, bp) {
         if (err) {
           throw err;
         }
@@ -128,7 +128,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       });
 
       var bpData = utils.clone(blogData);
-      blogpost.insert(bpData, function (err, res) {
+      blogpost.insert(bpData, function(err, res) {
         if (err) {
           throw err;
         }
@@ -163,7 +163,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
     }
 
     function closeDB() {
-      mongoose.connection.db.dropDatabase(function () {
+      mongoose.connection.db.dropDatabase(function() {
         mongoose.disconnect();
         process.exit();
       });
@@ -171,8 +171,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
 
     suite.add('Update - Mongoose - Basic', {
       defer: true,
-      fn: function (deferred) {
-        User.update({_id: getNextmId()}, {$set: {age: 2}, $push: {likes: 'metal'}}, function (err) {
+      fn: function(deferred) {
+        User.update({_id: getNextmId()}, {$set: {age: 2}, $push: {likes: 'metal'}}, function(err) {
           if (err) {
             throw err;
           }
@@ -181,8 +181,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Update - Driver - Basic', {
       defer: true,
-      fn: function (deferred) {
-        user.update({_id: getNextdId()}, {$set: {age: 2}, $push: {likes: 'metal'}}, function (err) {
+      fn: function(deferred) {
+        user.update({_id: getNextdId()}, {$set: {age: 2}, $push: {likes: 'metal'}}, function(err) {
           if (err) {
             throw err;
           }
@@ -191,8 +191,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Update - Mongoose - Embedded Docs', {
       defer: true,
-      fn: function (deferred) {
-        BlogPost.findOne({_id: getNextbmId()}, function (err, bp) {
+      fn: function(deferred) {
+        BlogPost.findOne({_id: getNextbmId()}, function(err, bp) {
           if (err) {
             throw err;
           }
@@ -203,7 +203,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
           // The driver will send the full document, while mongoose will check
           // and only update fields that have been changed. This is meant to
           // illustrate that difference between the two
-          bp.save(function (err) {
+          bp.save(function(err) {
             if (err) {
               throw err;
             }
@@ -213,15 +213,15 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Update - Driver - Embdedded Docs', {
       defer: true,
-      fn: function (deferred) {
-        blogpost.findOne({_id: getNextbdId()}, function (err, bp) {
+      fn: function(deferred) {
+        blogpost.findOne({_id: getNextbdId()}, function(err, bp) {
           if (err) {
             throw err;
           }
           bp.comments[3].title = 'this is a new title';
           bp.comments[0].date = new Date();
           bp.comments.push(commentData);
-          blogpost.save(bp, function (err) {
+          blogpost.save(bp, function(err) {
             if (err) {
               throw err;
             }
@@ -231,12 +231,12 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Update - Mongoose - Multiple Documents', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var ids = [];
         for (var i = 0; i < 50; i++) {
           ids.push(getNextmId());
         }
-        User.update({_id: {$in: ids}}, {$set: {age: 2}, $push: {likes: 'metal'}}, function (err) {
+        User.update({_id: {$in: ids}}, {$set: {age: 2}, $push: {likes: 'metal'}}, function(err) {
           if (err) {
             throw err;
           }
@@ -245,12 +245,12 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Update - Driver - Multiple Documents', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var ids = [];
         for (var i = 0; i < 50; i++) {
           ids.push(getNextdId());
         }
-        user.update({_id: {$in: ids}}, {$set: {age: 2}, $push: {likes: 'metal'}}, function (err) {
+        user.update({_id: {$in: ids}}, {$set: {age: 2}, $push: {likes: 'metal'}}, function(err) {
           if (err) {
             throw err;
           }
@@ -259,10 +259,10 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Update - Mongoose - pop and push', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         testBp.comments.push(commentData);
         testBp.comments.$shift();
-        testBp.save(function (err) {
+        testBp.save(function(err) {
           if (err) {
             throw err;
           }
@@ -271,16 +271,16 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Update - Mongoose - Array Manipulation, parallel ops', {
       defer: true,
-      fn: function (deferred) {
+      fn: function(deferred) {
         var done = false;
-        BlogPost.update({_id: testBp.id}, {$pop: {comments: -1}}, function (err) {
+        BlogPost.update({_id: testBp.id}, {$pop: {comments: -1}}, function(err) {
           if (err) {
             throw err;
           }
           done && deferred.resolve();
           done = true;
         });
-        BlogPost.update({_id: testBp.id}, {$push: {comments: commentData}}, function (err) {
+        BlogPost.update({_id: testBp.id}, {$push: {comments: commentData}}, function(err) {
           if (err) {
             throw err;
           }
@@ -290,8 +290,8 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Update - Mongoose - findOneAndModify', {
       defer: true,
-      fn: function (deferred) {
-        BlogPost.findOneAndUpdate({_id: getNextbmId()}, {$set: {age: 2}, $push: {likes: 'metal'}}, function (err) {
+      fn: function(deferred) {
+        BlogPost.findOneAndUpdate({_id: getNextbmId()}, {$set: {age: 2}, $push: {likes: 'metal'}}, function(err) {
           if (err) {
             throw err;
           }
@@ -300,12 +300,12 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       }
     }).add('Update - Mongoose - find and update, separate ops', {
       defer: true,
-      fn: function (deferred) {
-        BlogPost.findOne({_id: getNextbmId()}, function (err, bp) {
+      fn: function(deferred) {
+        BlogPost.findOne({_id: getNextbmId()}, function(err, bp) {
           if (err) {
             throw err;
           }
-          bp.update({$set: {age: 2}, $push: {likes: 'metal'}}, function (err) {
+          bp.update({$set: {age: 2}, $push: {likes: 'metal'}}, function(err) {
             if (err) {
               throw err;
             }
@@ -314,15 +314,15 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
         });
       }
     })
-    .on('cycle', function (evt) {
+    .on('cycle', function(evt) {
       if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) {
         console.log(String(evt.target));
       }
-    }).on('complete', function () {
+    }).on('complete', function() {
       closeDB();
       if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) {
         var outObj = {};
-        this.forEach(function (item) {
+        this.forEach(function(item) {
           var out = {};
           out.stats = item.stats;
           delete out.stats.sample;
@@ -336,7 +336,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function (err) {
       for (var i = 0; i < 100; i++) {
         testBp.comments.push(commentData);
       }
-      testBp.save(function (err) {
+      testBp.save(function(err) {
         if (err) {
           throw err;
         }
diff --git a/benchmarks/clone.js b/benchmarks/clone.js
index 02565e72342..1c84e2ebb6a 100644
--- a/benchmarks/clone.js
+++ b/benchmarks/clone.js
@@ -20,7 +20,7 @@ var AllSchema = new Schema({
   buffers: [Buffer],
   objectids: [Schema.ObjectId],
   docs: {
-    type: [DocSchema], validate: function () {
+    type: [DocSchema], validate: function() {
       return true;
     }
   },
diff --git a/benchmarks/index.js b/benchmarks/index.js
index 03a9f070caf..32a978e719c 100644
--- a/benchmarks/index.js
+++ b/benchmarks/index.js
@@ -76,72 +76,72 @@ function run(label, fn) {
   // console.error(((used.vsize - started.vsize) / 1048576)+' MB');
 }
 
-run('string', function () {
+run('string', function() {
   return new A({
     string: 'hello world'
   });
 });
-run('number', function () {
+run('number', function() {
   return new A({
     number: 444848484
   });
 });
-run('date', function () {
+run('date', function() {
   return new A({
     date: new Date
   });
 });
-run('bool', function () {
+run('bool', function() {
   return new A({
     bool: true
   });
 });
-run('buffer', function () {
+run('buffer', function() {
   return new A({
     buffer: new Buffer(0)
   });
 });
-run('objectid', function () {
+run('objectid', function() {
   return new A({
     objectid: new mongoose.Types.ObjectId()
   });
 });
-run('array of mixed', function () {
+run('array of mixed', function() {
   return new A({
     array: [4, {}, [], 'asdfa']
   });
 });
-run('array of strings', function () {
+run('array of strings', function() {
   return new A({
     strings: ['one', 'two', 'three', 'four']
   });
 });
-run('array of numbers', function () {
+run('array of numbers', function() {
   return new A({
     numbers: [72, 6493, 83984643, 348282.55]
   });
 });
-run('array of dates', function () {
+run('array of dates', function() {
   return new A({
     dates: [new Date, new Date, new Date]
   });
 });
-run('array of bools', function () {
+run('array of bools', function() {
   return new A({
     bools: [true, false, false, true, true]
   });
 });
-run('array of buffers', function () {
+run('array of buffers', function() {
   return new A({
     buffers: [new Buffer([33]), new Buffer([12])]
   });
 });
-run('array of objectids', function () {
+run('array of objectids', function() {
   return new A({
     objectids: [new mongoose.Types.ObjectId]
   });
 });
-run('array of docs', function () {
+run('array of docs', function() {
   return new A({
     docs: [{title: 'yo'}, {title: 'nowafasdi0fas asjkdfla fa'}]
   });
diff --git a/benchmarks/mem.js b/benchmarks/mem.js
index 87147c4a872..d3449d7e96e 100644
--- a/benchmarks/mem.js
+++ b/benchmarks/mem.js
@@ -22,7 +22,7 @@ var AllSchema = new Schema({
   buffers: [Buffer],
   objectids: [Schema.ObjectId],
   docs: {
-    type: [DocSchema], validate: function () {
+    type: [DocSchema], validate: function() {
       return true;
     }
   },
@@ -32,40 +32,40 @@ var AllSchema = new Schema({
 var A = mongoose.model('A', AllSchema);
 
 var methods = [];
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.findOne({_id: a._id}, cb);
 }); // 2 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.find({_id: a._id, bool: a.bool}, cb);
 }); // 3.8 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.findById(a._id, cb);
 }); // 4.6 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.where('number', a.number).limit(10).exec(cb);
 }); // 4.8 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.where('date', a.date).select('string').limit(10).exec(cb);
 }); // 3.5 mb
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.where('date', a.date).select('string bool').limit(10).exec(cb);
 }); // 3.5 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.where('date', a.date).where('array').in(3).limit(10).exec(cb);
 }); // 1.82 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.update({_id: a._id}, {$addToset: {array: 'heeeeello'}}, cb);
 }); // 3.32 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.remove({_id: a._id}, cb);
 }); // 3.32 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.find().where('objectids').exists().select('dates').limit(10).exec(cb);
 }); // 3.32 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   A.count({strings: a.strings[2], number: a.number}, cb);
 }); // 3.32 MB
-methods.push(function (a, cb) {
+methods.push(function(a, cb) {
   a.string = 'asdfaf';
   a.number = 38383838;
   a.date = new Date;
@@ -98,8 +98,8 @@ var start = new Date;
 var total = 10000;
 var i = total;
 
-mongoose.connection.on('open', function () {
-  mongoose.connection.db.dropDatabase(function () {
+mongoose.connection.on('open', function() {
+  mongoose.connection.db.dropDatabase(function() {
     (function cycle() {
       if (i-- === 0) {
         return done();
@@ -121,8 +121,8 @@ mongoose.connection.on('open', function () {
         docs: [{title: 'yo'}, {title: 'nowafasdi0fas asjkdfla fa'}]
       });
 
-      a.save(function () {
-        methods[Math.random() * methods.length | 0](a, function () {
+      a.save(function() {
+        methods[Math.random() * methods.length | 0](a, function() {
           a = null;
           process.nextTick(cycle);
         });
@@ -151,7 +151,7 @@ mongoose.connection.on('open', function () {
 
       console.error('took %d ms for %d docs (%d dps)', time, total, total / (time / 1000), 'change: ', res);
 
-      mongoose.connection.db.dropDatabase(function () {
+      mongoose.connection.db.dropDatabase(function() {
         mongoose.connection.close();
       });
     }
diff --git a/benchmarks/populate.js b/benchmarks/populate.js
index 6dd3bb7499b..5dedecbb9ac 100644
--- a/benchmarks/populate.js
+++ b/benchmarks/populate.js
@@ -17,12 +17,12 @@ var B = mongoose.model('B', Schema({
 var start;
 var count = 0;
 
-mongoose.connect('localhost', 'benchmark-populate', function (err) {
+mongoose.connect('localhost', 'benchmark-populate', function(err) {
   if (err) {
     return done(err);
   }
 
-  A.create({name: 'wooooooooooooooooooooooooooooooooooooooooot'}, function (err, a) {
+  A.create({name: 'wooooooooooooooooooooooooooooooooooooooooot'}, function(err, a) {
     if (err) {
       return done(err);
     }
@@ -33,7 +33,7 @@ mongoose.connect('localhost', 'benchmark-populate', function (err) {
         as: [a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a],
         a: a,
         nested: [{a: a}, {a: a}, {a: a}, {a: a}, {a: a}, {a: a}]
-      }).save(function (err) {
+      }).save(function(err) {
         if (err) {
           return done(err);
         }
@@ -76,7 +76,7 @@ function done(err) {
     console.error(err.stack);
   }
 
-  mongoose.connection.db.dropDatabase(function () {
+  mongoose.connection.db.dropDatabase(function() {
     mongoose.disconnect();
     console.log('%d completed queries on mongoose version %s', count, mongoose.version);
   });
diff --git a/benchmarks/populationHeavyLoad.js b/benchmarks/populationHeavyLoad.js
index cb05ba3e6b0..25f82d0bb4e 100644
--- a/benchmarks/populationHeavyLoad.js
+++ b/benchmarks/populationHeavyLoad.js
@@ -408,7 +408,7 @@ load.Conclusion = tbd.from({
 }).make(dicCnt);
 
 function getItem(list) {
-  return function () {
+  return function() {
     var cnt = Math.floor(Math.random() * dicCnt);
     return list[cnt];
   };
@@ -446,12 +446,12 @@ for (i = 0; i < len; i++) {
 }
 
 
-var db = mongoose.createConnection('localhost', 'HeavyLoad', function () {
+var db = mongoose.createConnection('localhost', 'HeavyLoad', function() {
   function getItems(list) {
     if (!list) {
       done();
     }
-    return function () {
+    return function() {
       var cnt = Math.floor(Math.random() * dicCnt);
       var i, res = [];
       for (i = 0; i < cnt; i++) {
@@ -465,7 +465,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function () {
   var length = cnt;
   var runResults = {};
   var finalResults = {};
-  var doBenchmark = function () {
+  var doBenchmark = function() {
     var mc = db.model('MedicalCard');
     var run = [];
 
@@ -562,7 +562,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function () {
     var gcnt = run.length;
     var qryName;
     var turn = turns;
-    var nextQuery = function (err) {
+    var nextQuery = function(err) {
       if (err) {
         done();
       } else if (--gcnt >= 0) {
@@ -576,7 +576,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function () {
       }
     };
 
-    var nextRun = function (err) {
+    var nextRun = function(err) {
       if (err) {
         return nextQuery(err);
       }
@@ -597,16 +597,16 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function () {
     nextQuery();
   };
 
-  var createRelations = function () {
+  var createRelations = function() {
     var coll = db.db.collection('medicalcards');
     console.log('Main Collection prepare');
-    coll.remove({}, function () {
+    coll.remove({}, function() {
       console.log('clean collection done');
       var loadMedicalCard = tbd.from({})
-      .prop('firstName').use(function () {
+      .prop('firstName').use(function() {
         return createRandomWord(10);
       }).done()
-      .prop('lastName').use(function () {
+      .prop('lastName').use(function() {
         return createRandomWord(10);
       }).done()
       .prop('medication').use(getItems(load.Medication)).done()
@@ -628,7 +628,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function () {
       .prop('conclusion').use(getItem(load.Conclusion)).done()
       .make(mainCnt);
 
-      var saveAll = function (err) {
+      var saveAll = function(err) {
         if (err) {
           done();
         } else if (--res === 0) {
@@ -690,7 +690,7 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function () {
   }
 
   var updated = {};
-  var next = function (err, data) {
+  var next = function(err, data) {
     if (cnt < length && Array.isArray(data)) {
       // debugger
       var modelName = creatList[cnt].model;
@@ -707,8 +707,8 @@ var db = mongoose.createConnection('localhost', 'HeavyLoad', function () {
       var item = creatList[cnt];
       var coll = db.db.collection(item.collection);
       console.log(item.model);
-      coll.remove({}, function () {
-        coll.save(item.list, function () {
+      coll.remove({}, function() {
+        coll.save(item.list, function() {
           var mdl = db.model(item.model);
           mdl.find({}, next);
         });
diff --git a/examples/aggregate/aggregate.js b/examples/aggregate/aggregate.js
index 122abafd8d8..ccafd493c26 100644
--- a/examples/aggregate/aggregate.js
+++ b/examples/aggregate/aggregate.js
@@ -49,13 +49,13 @@ var data = [
 ];
 
 
-mongoose.connect('mongodb://localhost/persons', function (err) {
+mongoose.connect('mongodb://localhost/persons', function(err) {
   if (err) throw err;
 
   // create all of the dummy people
-  async.each(data, function (item, cb) {
+  async.each(data, function(item, cb) {
     Person.create(item, cb);
-  }, function (err) {
+  }, function(err) {
     if (err) {
       // handle error
     }
@@ -74,7 +74,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
         _id: {likes: '$likes'},
         likers: {$addToSet: '$name'}
       }},
-      function (err, result) {
+      function(err, result) {
         if (err) throw err;
         console.log(result);
          /* [
@@ -97,7 +97,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
 });
 
 function cleanup() {
-  Person.remove(function () {
+  Person.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/aggregate/person.js b/examples/aggregate/person.js
index 6c09bd525ab..607bb0781b0 100644
--- a/examples/aggregate/person.js
+++ b/examples/aggregate/person.js
@@ -4,7 +4,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   var PersonSchema = new Schema({
     name: String,
diff --git a/examples/doc-methods.js b/examples/doc-methods.js
index 74e21ff96c9..1f648b9c002 100644
--- a/examples/doc-methods.js
+++ b/examples/doc-methods.js
@@ -24,7 +24,7 @@ var CharacterSchema = Schema({
  * Methods
  */
 
-CharacterSchema.methods.attack = function () {
+CharacterSchema.methods.attack = function() {
   console.log('%s is attacking', this.name);
 };
 
@@ -44,7 +44,7 @@ var uri = 'mongodb://localhost/' + dbname;
 
 console.log('connecting to %s', uri);
 
-mongoose.connect(uri, function (err) {
+mongoose.connect(uri, function(err) {
   // if we failed to connect, abort
   if (err) throw err;
 
@@ -57,7 +57,7 @@ mongoose.connect(uri, function (err) {
  */
 
 function example() {
-  Character.create({name: 'Link', health: 100}, function (err, link) {
+  Character.create({name: 'Link', health: 100}, function(err, link) {
     if (err) return done(err);
     console.log('found', link);
     link.attack(); // 'Link is attacking'
@@ -71,7 +71,7 @@ function example() {
 
 function done(err) {
   if (err) console.error(err);
-  mongoose.connection.db.dropDatabase(function () {
+  mongoose.connection.db.dropDatabase(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/express/connection-sharing/app.js b/examples/express/connection-sharing/app.js
index 9187ec7dc15..8fb2fee96bd 100644
--- a/examples/express/connection-sharing/app.js
+++ b/examples/express/connection-sharing/app.js
@@ -12,6 +12,6 @@ app.get('/', routes.home);
 app.get('/insert', routes.insert);
 app.get('/name', routes.modelName);
 
-app.listen(8000, function () {
+app.listen(8000, function() {
   console.log('listening on http://localhost:8000');
 });
diff --git a/examples/express/connection-sharing/routes.js b/examples/express/connection-sharing/routes.js
index e9106a6bed8..35e4f8f6efb 100644
--- a/examples/express/connection-sharing/routes.js
+++ b/examples/express/connection-sharing/routes.js
@@ -1,19 +1,19 @@
 
 var model = require('./modelA');
 
-exports.home = function (req, res, next) {
-  model.find(function (err, docs) {
+exports.home = function(req, res, next) {
+  model.find(function(err, docs) {
     if (err) return next(err);
     res.send(docs);
   });
 };
 
-exports.modelName = function (req, res) {
+exports.modelName = function(req, res) {
   res.send('my model name is ' + model.modelName);
 };
 
-exports.insert = function (req, res, next) {
-  model.create({name: 'inserting ' + Date.now()}, function (err, doc) {
+exports.insert = function(req, res, next) {
+  model.create({name: 'inserting ' + Date.now()}, function(err, doc) {
     if (err) return next(err);
     res.send(doc);
   });
diff --git a/examples/geospatial/geoJSONSchema.js b/examples/geospatial/geoJSONSchema.js
index 893751f9b19..f950dea27fc 100644
--- a/examples/geospatial/geoJSONSchema.js
+++ b/examples/geospatial/geoJSONSchema.js
@@ -4,7 +4,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   // NOTE : This object must conform *precisely* to the geoJSON specification
   // you cannot embed a geoJSON doc inside a model or anything like that- IT
diff --git a/examples/geospatial/geoJSONexample.js b/examples/geospatial/geoJSONexample.js
index ab683637517..8e5dd2b5081 100644
--- a/examples/geospatial/geoJSONexample.js
+++ b/examples/geospatial/geoJSONexample.js
@@ -19,26 +19,26 @@ var data = [
 ];
 
 
-mongoose.connect('mongodb://localhost/locations', function (err) {
+mongoose.connect('mongodb://localhost/locations', function(err) {
   if (err) {
     throw err;
   }
 
-  Location.on('index', function (err) {
+  Location.on('index', function(err) {
     if (err) {
       throw err;
     }
     // create all of the dummy locations
-    async.each(data, function (item, cb) {
+    async.each(data, function(item, cb) {
       Location.create(item, cb);
-    }, function (err) {
+    }, function(err) {
       if (err) {
         throw err;
       }
       // create the location we want to search for
       var coords = {type: 'Point', coordinates: [-5, 5]};
       // search for it
-      Location.find({loc: {$near: coords}}).limit(1).exec(function (err, res) {
+      Location.find({loc: {$near: coords}}).limit(1).exec(function(err, res) {
         if (err) {
           throw err;
         }
@@ -50,7 +50,7 @@ mongoose.connect('mongodb://localhost/locations', function (err) {
 });
 
 function cleanup() {
-  Location.remove(function () {
+  Location.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/geospatial/geospatial.js b/examples/geospatial/geospatial.js
index 847c27ea971..6e4b439cbf3 100644
--- a/examples/geospatial/geospatial.js
+++ b/examples/geospatial/geospatial.js
@@ -53,26 +53,26 @@ var data = [
 ];
 
 
-mongoose.connect('mongodb://localhost/persons', function (err) {
+mongoose.connect('mongodb://localhost/persons', function(err) {
   if (err) {
     throw err;
   }
 
   // create all of the dummy people
-  async.each(data, function (item, cb) {
+  async.each(data, function(item, cb) {
     Person.create(item, cb);
-  }, function (err) {
+  }, function(err) {
     if (err) {
       // handler error
     }
 
     // let's find the closest person to bob
-    Person.find({name: 'bob'}, function (err, res) {
+    Person.find({name: 'bob'}, function(err, res) {
       if (err) {
         throw err;
       }
 
-      res[0].findClosest(function (err, closest) {
+      res[0].findClosest(function(err, closest) {
         if (err) {
           throw err;
         }
@@ -84,7 +84,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
         // information about geospatial queries and indexes, see
         // http://docs.mongodb.org/manual/applications/geospatial-indexes/
         var coords = [7, 7];
-        Person.find({loc: {$nearSphere: coords}}).limit(1).exec(function (err, res) {
+        Person.find({loc: {$nearSphere: coords}}).limit(1).exec(function(err, res) {
           console.log('Closest to %s is %s', coords, res);
           cleanup();
         });
@@ -94,7 +94,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
 });
 
 function cleanup() {
-  Person.remove(function () {
+  Person.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/geospatial/person.js b/examples/geospatial/person.js
index ae6362db8b0..e816637167b 100644
--- a/examples/geospatial/person.js
+++ b/examples/geospatial/person.js
@@ -3,7 +3,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   var PersonSchema = new Schema({
     name: String,
@@ -16,7 +16,7 @@ module.exports = function () {
   });
 
   // define a method to find the closest person
-  PersonSchema.methods.findClosest = function (cb) {
+  PersonSchema.methods.findClosest = function(cb) {
     return this.model('Person').find({
       loc: {$nearSphere: this.loc},
       name: {$ne: this.name}
diff --git a/examples/globalschemas/gs_example.js b/examples/globalschemas/gs_example.js
index a835f26f7c1..af9ff11f230 100644
--- a/examples/globalschemas/gs_example.js
+++ b/examples/globalschemas/gs_example.js
@@ -9,7 +9,7 @@ var Person = mongoose.model('Person');
 
 // connect to a server to do a quick write / read example
 
-mongoose.connect('mongodb://localhost/persons', function (err) {
+mongoose.connect('mongodb://localhost/persons', function(err) {
   if (err) {
     throw err;
   }
@@ -18,22 +18,22 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
     name: 'bill',
     age: 25,
     birthday: new Date().setFullYear((new Date().getFullYear() - 25))
-  }, function (err, bill) {
+  }, function(err, bill) {
     if (err) {
       throw err;
     }
     console.log('People added to db: %s', bill.toString());
-    Person.find({}, function (err, people) {
+    Person.find({}, function(err, people) {
       if (err) {
         throw err;
       }
 
-      people.forEach(function (person) {
+      people.forEach(function(person) {
         console.log('People in the db: %s', person.toString());
       });
 
       // make sure to clean things up after we're done
-      setTimeout(function () {
+      setTimeout(function() {
         cleanup();
       }, 2000);
     });
@@ -41,7 +41,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
 });
 
 function cleanup() {
-  Person.remove(function () {
+  Person.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/globalschemas/person.js b/examples/globalschemas/person.js
index c6804c2094b..39ae725dece 100644
--- a/examples/globalschemas/person.js
+++ b/examples/globalschemas/person.js
@@ -3,7 +3,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   var PersonSchema = new Schema({
     name: String,
diff --git a/examples/lean/lean.js b/examples/lean/lean.js
index 4c738ca7606..c3e682e32f2 100644
--- a/examples/lean/lean.js
+++ b/examples/lean/lean.js
@@ -49,13 +49,13 @@ var data = [
 ];
 
 
-mongoose.connect('mongodb://localhost/persons', function (err) {
+mongoose.connect('mongodb://localhost/persons', function(err) {
   if (err) throw err;
 
   // create all of the dummy people
-  async.each(data, function (item, cb) {
+  async.each(data, function(item, cb) {
     Person.create(item, cb);
-  }, function (err) {
+  }, function(err) {
     if (err) {
       // handle error
     }
@@ -67,7 +67,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
     // when using .lean() the default is true, but you can explicitly set the
     // value by passing in a boolean value. IE. .lean(false)
     var q = Person.find({age: {$lt: 1000}}).sort('age').limit(2).lean();
-    q.exec(function (err, results) {
+    q.exec(function(err, results) {
       if (err) throw err;
       console.log('Are the results MongooseDocuments?: %s', results[0] instanceof mongoose.Document);
 
@@ -78,7 +78,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
 });
 
 function cleanup() {
-  Person.remove(function () {
+  Person.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/lean/person.js b/examples/lean/person.js
index 4de787cb076..b0bd2ed1f30 100644
--- a/examples/lean/person.js
+++ b/examples/lean/person.js
@@ -3,7 +3,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   var PersonSchema = new Schema({
     name: String,
diff --git a/examples/mapreduce/mapreduce.js b/examples/mapreduce/mapreduce.js
index de2a660b098..593d73a568e 100644
--- a/examples/mapreduce/mapreduce.js
+++ b/examples/mapreduce/mapreduce.js
@@ -43,13 +43,13 @@ var data = [
 ];
 
 
-mongoose.connect('mongodb://localhost/persons', function (err) {
+mongoose.connect('mongodb://localhost/persons', function(err) {
   if (err) throw err;
 
   // create all of the dummy people
-  async.each(data, function (item, cb) {
+  async.each(data, function(item, cb) {
     Person.create(item, cb);
-  }, function (err) {
+  }, function(err) {
     if (err) {
       // handle error
     }
@@ -60,7 +60,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
     // create the options object
     var o = {};
 
-    o.map = function () {
+    o.map = function() {
       // in this function, 'this' refers to the current document being
       // processed. Return the (gender, age) tuple using
       /* global emit */
@@ -69,7 +69,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
 
     // the reduce function receives the array of ages that are grouped by the
     // id, which in this case is the gender
-    o.reduce = function (id, ages) {
+    o.reduce = function(id, ages) {
       return Array.sum(ages);
     };
 
@@ -85,7 +85,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
     // o.out = {}; // objects to specify where output goes, by default is
                    // returned, but can also be stored in a new collection
                    // see: http://mongoosejs.com/docs/api.html#model_Model.mapReduce
-    Person.mapReduce(o, function (err, results, stats) {
+    Person.mapReduce(o, function(err, results, stats) {
       console.log('map reduce took %d ms', stats.processtime);
       console.log(results);
       cleanup();
@@ -94,7 +94,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
 });
 
 function cleanup() {
-  Person.remove(function () {
+  Person.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/mapreduce/person.js b/examples/mapreduce/person.js
index f072f9f70fa..9e2f084236e 100644
--- a/examples/mapreduce/person.js
+++ b/examples/mapreduce/person.js
@@ -4,7 +4,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   var PersonSchema = new Schema({
     name: String,
diff --git a/examples/population/population-across-three-collections.js b/examples/population/population-across-three-collections.js
index 23b699d1ba6..fe6de72dbee 100644
--- a/examples/population/population-across-three-collections.js
+++ b/examples/population/population-across-three-collections.js
@@ -10,7 +10,7 @@ var ObjectId = mongoose.Types.ObjectId;
 
 var dbname = 'testing_populateAdInfinitum_' + require('../../lib/utils').random();
 mongoose.connect('localhost', dbname);
-mongoose.connection.on('error', function () {
+mongoose.connection.on('error', function() {
   console.error('connection error', arguments);
 });
 
@@ -41,7 +41,7 @@ var BlogPost = mongoose.model('BlogPost', blogpost);
  * example
  */
 
-mongoose.connection.on('open', function () {
+mongoose.connection.on('open', function() {
   /**
    * Generate data
    */
@@ -70,7 +70,7 @@ mongoose.connection.on('open', function () {
     friends: [userIds[0], userIds[1], userIds[2]]
   });
 
-  User.create(users, function (err) {
+  User.create(users, function(err) {
     assert.ifError(err);
 
     var blogposts = [];
@@ -90,7 +90,7 @@ mongoose.connection.on('open', function () {
       author: userIds[2]
     });
 
-    BlogPost.create(blogposts, function (err) {
+    BlogPost.create(blogposts, function(err) {
       assert.ifError(err);
 
       /**
@@ -101,7 +101,7 @@ mongoose.connection.on('open', function () {
       .find({tags: 'fun'})
       .lean()
       .populate('author')
-      .exec(function (err, docs) {
+      .exec(function(err, docs) {
         assert.ifError(err);
 
         /**
@@ -114,7 +114,7 @@ mongoose.connection.on('open', function () {
           options: {limit: 2}
         };
 
-        BlogPost.populate(docs, opts, function (err, docs) {
+        BlogPost.populate(docs, opts, function(err, docs) {
           assert.ifError(err);
           console.log('populated');
           var s = require('util').inspect(docs, {depth: null, colors: true});
@@ -128,7 +128,7 @@ mongoose.connection.on('open', function () {
 
 function done(err) {
   if (err) console.error(err.stack);
-  mongoose.connection.db.dropDatabase(function () {
+  mongoose.connection.db.dropDatabase(function() {
     mongoose.connection.close();
   });
 }
diff --git a/examples/population/population-basic.js b/examples/population/population-basic.js
index abb0a57904e..252cc5374d0 100644
--- a/examples/population/population-basic.js
+++ b/examples/population/population-basic.js
@@ -35,7 +35,7 @@ var Game = mongoose.model('Game', gameSchema);
  * the default port (27017)
  */
 
-mongoose.connect('mongodb://localhost/console', function (err) {
+mongoose.connect('mongodb://localhost/console', function(err) {
   // if we failed to connect, abort
   if (err) throw err;
 
@@ -54,7 +54,7 @@ function createData() {
       manufacturer: 'Nintendo',
       released: 'September 29, 1996'
     },
-    function (err, nintendo64) {
+    function(err, nintendo64) {
       if (err) return done(err);
 
       Game.create({
@@ -63,7 +63,7 @@ function createData() {
         released: new Date('November 21, 1998'),
         consoles: [nintendo64]
       },
-      function (err) {
+      function(err) {
         if (err) return done(err);
         example();
       });
@@ -79,7 +79,7 @@ function example() {
   Game
   .findOne({name: /^Legend of Zelda/})
   .populate('consoles')
-  .exec(function (err, ocinara) {
+  .exec(function(err, ocinara) {
     if (err) return done(err);
 
     console.log(
@@ -95,8 +95,8 @@ function example() {
 
 function done(err) {
   if (err) console.error(err);
-  Console.remove(function () {
-    Game.remove(function () {
+  Console.remove(function() {
+    Game.remove(function() {
       mongoose.disconnect();
     });
   });
diff --git a/examples/population/population-of-existing-doc.js b/examples/population/population-of-existing-doc.js
index a2d6588bbf7..c7eadfee79f 100644
--- a/examples/population/population-of-existing-doc.js
+++ b/examples/population/population-of-existing-doc.js
@@ -35,7 +35,7 @@ var Game = mongoose.model('Game', gameSchema);
  * the default port (27017)
  */
 
-mongoose.connect('mongodb://localhost/console', function (err) {
+mongoose.connect('mongodb://localhost/console', function(err) {
   // if we failed to connect, abort
   if (err) throw err;
 
@@ -54,7 +54,7 @@ function createData() {
       manufacturer: 'Nintendo',
       released: 'September 29, 1996'
     },
-    function (err, nintendo64) {
+    function(err, nintendo64) {
       if (err) return done(err);
 
       Game.create({
@@ -63,7 +63,7 @@ function createData() {
         released: new Date('November 21, 1998'),
         consoles: [nintendo64]
       },
-      function (err) {
+      function(err) {
         if (err) return done(err);
         example();
       });
@@ -78,13 +78,13 @@ function createData() {
 function example() {
   Game
   .findOne({name: /^Legend of Zelda/})
-  .exec(function (err, ocinara) {
+  .exec(function(err, ocinara) {
     if (err) return done(err);
 
     console.log('"%s" console _id: %s', ocinara.name, ocinara.consoles[0]);
 
     // population of existing document
-    ocinara.populate('consoles', function (err) {
+    ocinara.populate('consoles', function(err) {
       if (err) return done(err);
 
       console.log(
@@ -101,8 +101,8 @@ function example() {
 
 function done(err) {
   if (err) console.error(err);
-  Console.remove(function () {
-    Game.remove(function () {
+  Console.remove(function() {
+    Game.remove(function() {
       mongoose.disconnect();
     });
   });
diff --git a/examples/population/population-of-multiple-existing-docs.js b/examples/population/population-of-multiple-existing-docs.js
index d95b6d91406..61b4e85de6f 100644
--- a/examples/population/population-of-multiple-existing-docs.js
+++ b/examples/population/population-of-multiple-existing-docs.js
@@ -35,7 +35,7 @@ var Game = mongoose.model('Game', gameSchema);
  * the default port (27017)
  */
 
-mongoose.connect('mongodb://localhost/console', function (err) {
+mongoose.connect('mongodb://localhost/console', function(err) {
   // if we failed to connect, abort
   if (err) throw err;
 
@@ -59,7 +59,7 @@ function createData() {
       manufacturer: 'Nintendo',
       released: 'August 23, 1991'
     },
-    function (err, nintendo64, superNintendo) {
+    function(err, nintendo64, superNintendo) {
       if (err) return done(err);
 
       Game.create(
@@ -75,7 +75,7 @@ function createData() {
           released: 'September 1, 1992',
           consoles: [superNintendo]
         },
-        function (err) {
+        function(err) {
           if (err) return done(err);
           example();
         }
@@ -91,16 +91,16 @@ function createData() {
 function example() {
   Game
   .find({})
-  .exec(function (err, games) {
+  .exec(function(err, games) {
     if (err) return done(err);
 
     console.log('found %d games', games.length);
 
     var options = {path: 'consoles', select: 'name released -_id'};
-    Game.populate(games, options, function (err, games) {
+    Game.populate(games, options, function(err, games) {
       if (err) return done(err);
 
-      games.forEach(function (game) {
+      games.forEach(function(game) {
         console.log(
           '"%s" was released for the %s on %s',
           game.name,
@@ -116,8 +116,8 @@ function example() {
 
 function done(err) {
   if (err) console.error(err);
-  Console.remove(function () {
-    Game.remove(function () {
+  Console.remove(function() {
+    Game.remove(function() {
       mongoose.disconnect();
     });
   });
diff --git a/examples/population/population-options.js b/examples/population/population-options.js
index ed825080709..59cfd1e8702 100644
--- a/examples/population/population-options.js
+++ b/examples/population/population-options.js
@@ -35,7 +35,7 @@ var Game = mongoose.model('Game', gameSchema);
  * the default port (27017)
  */
 
-mongoose.connect('mongodb://localhost/console', function (err) {
+mongoose.connect('mongodb://localhost/console', function(err) {
   // if we failed to connect, abort
   if (err) throw err;
 
@@ -64,7 +64,7 @@ function createData() {
       manufacturer: 'Microsoft',
       released: 'November 22, 2005'
     },
-    function (err, nintendo64, superNintendo, xbox360) {
+    function(err, nintendo64, superNintendo, xbox360) {
       if (err) return done(err);
 
       Game.create(
@@ -86,7 +86,7 @@ function createData() {
           released: 'November 17, 2005',
           consoles: [xbox360]
         },
-        function (err) {
+        function(err) {
           if (err) return done(err);
           example();
         }
@@ -108,10 +108,10 @@ function example() {
     select: 'name',
     options: {comment: 'population'}
   })
-  .exec(function (err, games) {
+  .exec(function(err, games) {
     if (err) return done(err);
 
-    games.forEach(function (game) {
+    games.forEach(function(game) {
       console.log(
         '"%s" was released for the %s on %s',
         game.name,
@@ -130,8 +130,8 @@ function example() {
 
 function done(err) {
   if (err) console.error(err);
-  Console.remove(function () {
-    Game.remove(function () {
+  Console.remove(function() {
+    Game.remove(function() {
       mongoose.disconnect();
     });
   });
diff --git a/examples/population/population-plain-objects.js b/examples/population/population-plain-objects.js
index 981357a8a5d..ba849dc38be 100644
--- a/examples/population/population-plain-objects.js
+++ b/examples/population/population-plain-objects.js
@@ -35,7 +35,7 @@ var Game = mongoose.model('Game', gameSchema);
  * the default port (27017)
  */
 
-mongoose.connect('mongodb://localhost/console', function (err) {
+mongoose.connect('mongodb://localhost/console', function(err) {
   // if we failed to connect, abort
   if (err) throw err;
 
@@ -54,7 +54,7 @@ function createData() {
       manufacturer: 'Nintendo',
       released: 'September 29, 1996'
     },
-    function (err, nintendo64) {
+    function(err, nintendo64) {
       if (err) return done(err);
 
       Game.create(
@@ -64,7 +64,7 @@ function createData() {
           released: new Date('November 21, 1998'),
           consoles: [nintendo64]
         },
-        function (err) {
+        function(err) {
           if (err) return done(err);
           example();
         }
@@ -82,7 +82,7 @@ function example() {
   .findOne({name: /^Legend of Zelda/})
   .populate('consoles')
   .lean() // just return plain objects, not documents wrapped by mongoose
-  .exec(function (err, ocinara) {
+  .exec(function(err, ocinara) {
     if (err) return done(err);
 
     console.log(
@@ -98,8 +98,8 @@ function example() {
 
 function done(err) {
   if (err) console.error(err);
-  Console.remove(function () {
-    Game.remove(function () {
+  Console.remove(function() {
+    Game.remove(function() {
       mongoose.disconnect();
     });
   });
diff --git a/examples/promises/person.js b/examples/promises/person.js
index 779e1f7587a..40e2bf17caa 100644
--- a/examples/promises/person.js
+++ b/examples/promises/person.js
@@ -4,7 +4,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   var PersonSchema = new Schema({
     name: String,
diff --git a/examples/promises/promise.js b/examples/promises/promise.js
index 86ee0deb569..fd1ff7a8149 100644
--- a/examples/promises/promise.js
+++ b/examples/promises/promise.js
@@ -38,15 +38,15 @@ var data = [
 ];
 
 
-mongoose.connect('mongodb://localhost/persons', function (err) {
+mongoose.connect('mongodb://localhost/persons', function(err) {
   if (err) {
     throw err;
   }
 
   // create all of the dummy people
-  async.each(data, function (item, cb) {
+  async.each(data, function(item, cb) {
     Person.create(item, cb);
-  }, function (err) {
+  }, function(err) {
     if (err) {
       // handle error
     }
@@ -56,39 +56,39 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
 
     // add a callback on the promise. This will be called on both error and
     // complete
-    prom.addBack(function () {
+    prom.addBack(function() {
       console.log('completed');
     });
 
     // add a callback that is only called on complete (success) events
-    prom.addCallback(function () {
+    prom.addCallback(function() {
       console.log('Successful Completion!');
     });
 
     // add a callback that is only called on err (rejected) events
-    prom.addErrback(function () {
+    prom.addErrback(function() {
       console.log('Fail Boat');
     });
 
     // you can chain things just like in the promise/A+ spec
     // note: each then() is returning a new promise, so the above methods
     // that we defined will all fire after the initial promise is fulfilled
-    prom.then(function (people) {
+    prom.then(function(people) {
       // just getting the stuff for the next query
-      var ids = people.map(function (p) {
+      var ids = people.map(function(p) {
         return p._id;
       });
 
       // return the next promise
       return Person.find({_id: {$nin: ids}}).exec();
-    }).then(function (oldest) {
+    }).then(function(oldest) {
       console.log('Oldest person is: %s', oldest);
     }).then(cleanup);
   });
 });
 
 function cleanup() {
-  Person.remove(function () {
+  Person.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/querybuilder/person.js b/examples/querybuilder/person.js
index 779e1f7587a..40e2bf17caa 100644
--- a/examples/querybuilder/person.js
+++ b/examples/querybuilder/person.js
@@ -4,7 +4,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   var PersonSchema = new Schema({
     name: String,
diff --git a/examples/querybuilder/querybuilder.js b/examples/querybuilder/querybuilder.js
index fbfca9343b6..723a357f4e3 100644
--- a/examples/querybuilder/querybuilder.js
+++ b/examples/querybuilder/querybuilder.js
@@ -39,13 +39,13 @@ var data = [
 ];
 
 
-mongoose.connect('mongodb://localhost/persons', function (err) {
+mongoose.connect('mongodb://localhost/persons', function(err) {
   if (err) throw err;
 
   // create all of the dummy people
-  async.each(data, function (item, cb) {
+  async.each(data, function(item, cb) {
     Person.create(item, cb);
-  }, function (err) {
+  }, function(err) {
     if (err) throw err;
 
     // when querying data, instead of providing a callback, you can instead
@@ -62,7 +62,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
     query.where('age').gt(21);
 
     // finally, when ready to execute the query, call the exec() function
-    query.exec(function (err, results) {
+    query.exec(function(err, results) {
       if (err) throw err;
 
       console.log(results);
@@ -73,7 +73,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
 });
 
 function cleanup() {
-  Person.remove(function () {
+  Person.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/replicasets/person.js b/examples/replicasets/person.js
index 779e1f7587a..40e2bf17caa 100644
--- a/examples/replicasets/person.js
+++ b/examples/replicasets/person.js
@@ -4,7 +4,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   var PersonSchema = new Schema({
     name: String,
diff --git a/examples/replicasets/replica-sets.js b/examples/replicasets/replica-sets.js
index e22bb53d19b..6aa27b5cbda 100644
--- a/examples/replicasets/replica-sets.js
+++ b/examples/replicasets/replica-sets.js
@@ -44,13 +44,13 @@ var data = [
 var opts = {
   replSet: {rs_name: 'rs0'}
 };
-mongoose.connect('mongodb://localhost:27018/persons,localhost:27019,localhost:27020', opts, function (err) {
+mongoose.connect('mongodb://localhost:27018/persons,localhost:27019,localhost:27020', opts, function(err) {
   if (err) throw err;
 
   // create all of the dummy people
-  async.each(data, function (item, cb) {
+  async.each(data, function(item, cb) {
     Person.create(item, cb);
-  }, function (err) {
+  }, function(err) {
     if (err) {
         // handle error
     }
@@ -58,14 +58,14 @@ mongoose.connect('mongodb://localhost:27018/persons,localhost:27019,localhost:27
       // create and delete some data
     var prom = Person.find({age: {$lt: 1000}}).exec();
 
-    prom.then(function (people) {
+    prom.then(function(people) {
       console.log('young people: %s', people);
     }).then(cleanup);
   });
 });
 
 function cleanup() {
-  Person.remove(function () {
+  Person.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/examples/schema/schema.js b/examples/schema/schema.js
index 489dcaaea3d..5bc99ae7635 100644
--- a/examples/schema/schema.js
+++ b/examples/schema/schema.js
@@ -60,10 +60,10 @@ var Person = new Schema({
  */
 
 BlogPost.path('date')
-.default(function () {
+.default(function() {
   return new Date();
 })
-.set(function (v) {
+.set(function(v) {
   return v === 'now' ? new Date() : v;
 });
 
@@ -71,7 +71,7 @@ BlogPost.path('date')
  * Pre hook.
  */
 
-BlogPost.pre('save', function (next, done) {
+BlogPost.pre('save', function(next, done) {
   /* global emailAuthor */
   emailAuthor(done); // some async function
   next();
@@ -81,15 +81,15 @@ BlogPost.pre('save', function (next, done) {
  * Methods
  */
 
-BlogPost.methods.findCreator = function (callback) {
+BlogPost.methods.findCreator = function(callback) {
   return this.db.model('Person').findById(this.creator, callback);
 };
 
-BlogPost.statics.findByTitle = function (title, callback) {
+BlogPost.statics.findByTitle = function(title, callback) {
   return this.find({title: title}, callback);
 };
 
-BlogPost.methods.expressiveQuery = function (creator, date, callback) {
+BlogPost.methods.expressiveQuery = function(creator, date, callback) {
   return this.find('creator', creator).where('date').gte(date).run(callback);
 };
 
@@ -102,7 +102,7 @@ function slugGenerator(options) {
   var key = options.key || 'title';
 
   return function slugGenerator(schema) {
-    schema.path(key).set(function (v) {
+    schema.path(key).set(function(v) {
       this.slug = v.toLowerCase().replace(/[^a-z0-9]/g, '').replace(/-+/g, '');
       return v;
     });
diff --git a/examples/statics/person.js b/examples/statics/person.js
index f50fb4a1ccb..a93b8c66cdb 100644
--- a/examples/statics/person.js
+++ b/examples/statics/person.js
@@ -3,7 +3,7 @@ var mongoose = require('../../lib');
 var Schema = mongoose.Schema;
 
 // create an export function to encapsulate the model creation
-module.exports = function () {
+module.exports = function() {
   // define schema
   var PersonSchema = new Schema({
     name: String,
@@ -12,7 +12,7 @@ module.exports = function () {
   });
 
   // define a static
-  PersonSchema.statics.findPersonByName = function (name, cb) {
+  PersonSchema.statics.findPersonByName = function(name, cb) {
     this.find({name: new RegExp(name, 'i')}, cb);
   };
 
diff --git a/examples/statics/statics.js b/examples/statics/statics.js
index b951b855c9e..610b2aa4d3c 100644
--- a/examples/statics/statics.js
+++ b/examples/statics/statics.js
@@ -9,20 +9,20 @@ var Person = mongoose.model('Person');
 
 // connect to a server to do a quick write / read example
 
-mongoose.connect('mongodb://localhost/persons', function (err) {
+mongoose.connect('mongodb://localhost/persons', function(err) {
   if (err) {
     throw err;
   }
 
   Person.create({name: 'bill', age: 25, birthday: new Date().setFullYear((new Date().getFullYear() - 25))},
-      function (err, bill) {
+      function(err, bill) {
         if (err) {
           throw err;
         }
         console.log('People added to db: %s', bill.toString());
 
         // using the static
-        Person.findPersonByName('bill', function (err, result) {
+        Person.findPersonByName('bill', function(err, result) {
           if (err) {
             throw err;
           }
@@ -35,7 +35,7 @@ mongoose.connect('mongodb://localhost/persons', function (err) {
 });
 
 function cleanup() {
-  Person.remove(function () {
+  Person.remove(function() {
     mongoose.disconnect();
   });
 }
diff --git a/format_deps.js b/format_deps.js
index f5ebc997de7..39e5e74322e 100644
--- a/format_deps.js
+++ b/format_deps.js
@@ -1,7 +1,7 @@
 var p = require('./package.json');
 var _ = require('underscore');
 
-var result = _.map(p.browserDependencies, function (v, k) {
+var result = _.map(p.browserDependencies, function(v, k) {
   return k + '@' + v;
 });
 
diff --git a/karma.local.conf.js b/karma.local.conf.js
index 16c569bb5d7..4cbcdbee4a2 100644
--- a/karma.local.conf.js
+++ b/karma.local.conf.js
@@ -1,4 +1,4 @@
-module.exports = function (config) {
+module.exports = function(config) {
   config.set({
 
     // base path that will be used to resolve all patterns (eg. files, exclude)
diff --git a/karma.sauce.conf.js b/karma.sauce.conf.js
index f91a3f4e8be..8afa737969d 100644
--- a/karma.sauce.conf.js
+++ b/karma.sauce.conf.js
@@ -1,4 +1,4 @@
-module.exports = function (config) {
+module.exports = function(config) {
   var customLaunchers = {
     sl_chrome_35: {
       base: 'SauceLabs',
diff --git a/lib/ES6Promise.js b/lib/ES6Promise.js
index 2025e6b2bec..13371ac3aca 100644
--- a/lib/ES6Promise.js
+++ b/lib/ES6Promise.js
@@ -19,7 +19,7 @@ function ES6Promise() {
   throw new Error('Can\'t use ES6 promise with mpromise style constructor');
 }
 
-ES6Promise.use = function (Promise) {
+ES6Promise.use = function(Promise) {
   ES6Promise.ES6 = Promise;
 };
 
diff --git a/lib/aggregate.js b/lib/aggregate.js
index 5ea3c65e4af..7aa45f287e0 100644
--- a/lib/aggregate.js
+++ b/lib/aggregate.js
@@ -59,7 +59,7 @@ function Aggregate() {
  * @api public
  */
 
-Aggregate.prototype.model = function (model) {
+Aggregate.prototype.model = function(model) {
   this._model = model;
   return this;
 };
@@ -80,7 +80,7 @@ Aggregate.prototype.model = function (model) {
  * @api public
  */
 
-Aggregate.prototype.append = function () {
+Aggregate.prototype.append = function() {
   var args = (arguments.length === 1 && util.isArray(arguments[0]))
       ? arguments[0]
       : utils.args(arguments);
@@ -126,15 +126,15 @@ Aggregate.prototype.append = function () {
  * @api public
  */
 
-Aggregate.prototype.project = function (arg) {
+Aggregate.prototype.project = function(arg) {
   var fields = {};
 
   if (typeof arg === 'object' && !util.isArray(arg)) {
-    Object.keys(arg).forEach(function (field) {
+    Object.keys(arg).forEach(function(field) {
       fields[field] = arg[field];
     });
   } else if (arguments.length === 1 && typeof arg === 'string') {
-    arg.split(/\s+/).forEach(function (field) {
+    arg.split(/\s+/).forEach(function(field) {
       if (!field) {
         return;
       }
@@ -238,7 +238,7 @@ Aggregate.prototype.project = function (arg) {
  * @api public
  */
 
-Aggregate.prototype.near = function (arg) {
+Aggregate.prototype.near = function(arg) {
   var op = {};
   op.$geoNear = arg;
   return this.append(op);
@@ -248,8 +248,8 @@ Aggregate.prototype.near = function (arg) {
  * define methods
  */
 
-'group match skip limit out'.split(' ').forEach(function ($operator) {
-  Aggregate.prototype[$operator] = function (arg) {
+'group match skip limit out'.split(' ').forEach(function($operator) {
+  Aggregate.prototype[$operator] = function(arg) {
     var op = {};
     op['$' + $operator] = arg;
     return this.append(op);
@@ -273,10 +273,10 @@ Aggregate.prototype.near = function (arg) {
  * @api public
  */
 
-Aggregate.prototype.unwind = function () {
+Aggregate.prototype.unwind = function() {
   var args = utils.args(arguments);
 
-  return this.append.apply(this, args.map(function (arg) {
+  return this.append.apply(this, args.map(function(arg) {
     return {$unwind: (arg && arg.charAt(0) === '$') ? arg : '$' + arg};
   }));
 };
@@ -294,7 +294,7 @@ Aggregate.prototype.unwind = function () {
  * @api public
  */
 
-Aggregate.prototype.lookup = function (options) {
+Aggregate.prototype.lookup = function(options) {
   return this.append({$lookup: options});
 };
 
@@ -311,7 +311,7 @@ Aggregate.prototype.lookup = function (options) {
  * @api public
  */
 
-Aggregate.prototype.sample = function (size) {
+Aggregate.prototype.sample = function(size) {
   return this.append({$sample: {size: size}});
 };
 
@@ -334,18 +334,18 @@ Aggregate.prototype.sample = function (size) {
  * @api public
  */
 
-Aggregate.prototype.sort = function (arg) {
+Aggregate.prototype.sort = function(arg) {
   // TODO refactor to reuse the query builder logic
 
   var sort = {};
 
   if (arg.constructor.name === 'Object') {
     var desc = ['desc', 'descending', -1];
-    Object.keys(arg).forEach(function (field) {
+    Object.keys(arg).forEach(function(field) {
       sort[field] = desc.indexOf(arg[field]) === -1 ? 1 : -1;
     });
   } else if (arguments.length === 1 && typeof arg === 'string') {
-    arg.split(/\s+/).forEach(function (field) {
+    arg.split(/\s+/).forEach(function(field) {
       if (!field) {
         return;
       }
@@ -375,7 +375,7 @@ Aggregate.prototype.sort = function (arg) {
  * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences
  */
 
-Aggregate.prototype.read = function (pref, tags) {
+Aggregate.prototype.read = function(pref, tags) {
   if (!this.options) {
     this.options = {};
   }
@@ -394,10 +394,10 @@ Aggregate.prototype.read = function (pref, tags) {
  * @return {Promise}
  */
 
-Aggregate.prototype.explain = function (callback) {
+Aggregate.prototype.explain = function(callback) {
   var _this = this;
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve, reject) {
+  return new Promise.ES6(function(resolve, reject) {
     if (!_this._pipeline.length) {
       var err = new Error('Aggregate has empty pipeline');
       if (callback) {
@@ -412,7 +412,7 @@ Aggregate.prototype.explain = function (callback) {
     _this._model
         .collection
         .aggregate(_this._pipeline, _this.options || {})
-        .explain(function (error, result) {
+        .explain(function(error, result) {
           if (error) {
             if (callback) {
               callback(error);
@@ -441,7 +441,7 @@ Aggregate.prototype.explain = function (callback) {
  * @see mongodb http://docs.mongodb.org/manual/reference/command/aggregate/
  */
 
-Aggregate.prototype.allowDiskUse = function (value) {
+Aggregate.prototype.allowDiskUse = function(value) {
   if (!this.options) {
     this.options = {};
   }
@@ -465,7 +465,7 @@ Aggregate.prototype.allowDiskUse = function (value) {
  * @see mongodb http://mongodb.github.io/node-mongodb-native/2.0/api/AggregationCursor.html
  */
 
-Aggregate.prototype.cursor = function (options) {
+Aggregate.prototype.cursor = function(options) {
   if (!this.options) {
     this.options = {};
   }
@@ -490,7 +490,7 @@ Aggregate.prototype.cursor = function (options) {
  * @api public
  */
 
-Aggregate.prototype.exec = function (callback) {
+Aggregate.prototype.exec = function(callback) {
   if (!this._model) {
     throw new Error('Aggregate not bound to any Model');
   }
@@ -499,9 +499,9 @@ Aggregate.prototype.exec = function (callback) {
 
   if (this.options && this.options.cursor) {
     if (this.options.cursor.async) {
-      return new Promise.ES6(function (resolve) {
+      return new Promise.ES6(function(resolve) {
         if (!_this._model.collection.buffer) {
-          process.nextTick(function () {
+          process.nextTick(function() {
             var cursor = _this._model.collection.
             aggregate(_this._pipeline, _this.options || {});
             resolve(cursor);
@@ -509,7 +509,7 @@ Aggregate.prototype.exec = function (callback) {
           });
           return;
         }
-        _this._model.collection.emitter.once('queue', function () {
+        _this._model.collection.emitter.once('queue', function() {
           var cursor = _this._model.collection.
           aggregate(_this._pipeline, _this.options || {});
           resolve(cursor);
@@ -521,7 +521,7 @@ Aggregate.prototype.exec = function (callback) {
     aggregate(this._pipeline, this.options || {});
   }
 
-  return new Promise.ES6(function (resolve, reject) {
+  return new Promise.ES6(function(resolve, reject) {
     if (!_this._pipeline.length) {
       var err = new Error('Aggregate has empty pipeline');
       if (callback) {
@@ -535,7 +535,7 @@ Aggregate.prototype.exec = function (callback) {
 
     _this._model
         .collection
-        .aggregate(_this._pipeline, _this.options || {}, function (error, result) {
+        .aggregate(_this._pipeline, _this.options || {}, function(error, result) {
           if (error) {
             if (callback) {
               callback(error);
@@ -574,7 +574,7 @@ function isOperator(obj) {
   k = Object.keys(obj);
 
   return k.length === 1 && k
-          .some(function (key) {
+          .some(function(key) {
             return key[0] === '$';
           });
 }
diff --git a/lib/cast.js b/lib/cast.js
index ccb64751bfc..111c027f86a 100644
--- a/lib/cast.js
+++ b/lib/cast.js
@@ -13,7 +13,7 @@ var Types = require('./schema/index');
  * @api private
  */
 
-var cast = module.exports = function (schema, obj) {
+var cast = module.exports = function(schema, obj) {
   var paths = Object.keys(obj),
       i = paths.length,
       any$conditionals,
@@ -130,7 +130,7 @@ var cast = module.exports = function (schema, obj) {
 
           (function _cast(val) {
             if (Array.isArray(val)) {
-              val.forEach(function (item, i) {
+              val.forEach(function(item, i) {
                 if (Array.isArray(item) || utils.isObject(item)) {
                   return _cast(item);
                 }
@@ -156,7 +156,7 @@ var cast = module.exports = function (schema, obj) {
         obj[path] = null;
         continue;
       } else if (val.constructor.name === 'Object') {
-        any$conditionals = Object.keys(val).some(function (k) {
+        any$conditionals = Object.keys(val).some(function(k) {
           return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
         });
 
diff --git a/lib/collection.js b/lib/collection.js
index bffc5fdd912..3aee0aa5f2b 100644
--- a/lib/collection.js
+++ b/lib/collection.js
@@ -78,7 +78,7 @@ Collection.prototype.conn;
  * @api private
  */
 
-Collection.prototype.onOpen = function () {
+Collection.prototype.onOpen = function() {
   this.buffer = false;
   this.doQueue();
 };
@@ -89,7 +89,7 @@ Collection.prototype.onOpen = function () {
  * @api private
  */
 
-Collection.prototype.onClose = function () {
+Collection.prototype.onClose = function() {
   if (this.opts.bufferCommands) {
     this.buffer = true;
   }
@@ -104,7 +104,7 @@ Collection.prototype.onClose = function () {
  * @api private
  */
 
-Collection.prototype.addQueue = function (name, args) {
+Collection.prototype.addQueue = function(name, args) {
   this.queue.push([name, args]);
   return this;
 };
@@ -115,13 +115,13 @@ Collection.prototype.addQueue = function (name, args) {
  * @api private
  */
 
-Collection.prototype.doQueue = function () {
+Collection.prototype.doQueue = function() {
   for (var i = 0, l = this.queue.length; i < l; i++) {
     this[this.queue[i][0]].apply(this, this.queue[i][1]);
   }
   this.queue = [];
   var _this = this;
-  process.nextTick(function () {
+  process.nextTick(function() {
     _this.emitter.emit('queue');
   });
   return this;
@@ -131,7 +131,7 @@ Collection.prototype.doQueue = function () {
  * Abstract method that drivers must implement.
  */
 
-Collection.prototype.ensureIndex = function () {
+Collection.prototype.ensureIndex = function() {
   throw new Error('Collection#ensureIndex unimplemented by driver');
 };
 
@@ -139,7 +139,7 @@ Collection.prototype.ensureIndex = function () {
  * Abstract method that drivers must implement.
  */
 
-Collection.prototype.findAndModify = function () {
+Collection.prototype.findAndModify = function() {
   throw new Error('Collection#findAndModify unimplemented by driver');
 };
 
@@ -147,7 +147,7 @@ Collection.prototype.findAndModify = function () {
  * Abstract method that drivers must implement.
  */
 
-Collection.prototype.findOne = function () {
+Collection.prototype.findOne = function() {
   throw new Error('Collection#findOne unimplemented by driver');
 };
 
@@ -155,7 +155,7 @@ Collection.prototype.findOne = function () {
  * Abstract method that drivers must implement.
  */
 
-Collection.prototype.find = function () {
+Collection.prototype.find = function() {
   throw new Error('Collection#find unimplemented by driver');
 };
 
@@ -163,7 +163,7 @@ Collection.prototype.find = function () {
  * Abstract method that drivers must implement.
  */
 
-Collection.prototype.insert = function () {
+Collection.prototype.insert = function() {
   throw new Error('Collection#insert unimplemented by driver');
 };
 
@@ -171,7 +171,7 @@ Collection.prototype.insert = function () {
  * Abstract method that drivers must implement.
  */
 
-Collection.prototype.save = function () {
+Collection.prototype.save = function() {
   throw new Error('Collection#save unimplemented by driver');
 };
 
@@ -179,7 +179,7 @@ Collection.prototype.save = function () {
  * Abstract method that drivers must implement.
  */
 
-Collection.prototype.update = function () {
+Collection.prototype.update = function() {
   throw new Error('Collection#update unimplemented by driver');
 };
 
@@ -187,7 +187,7 @@ Collection.prototype.update = function () {
  * Abstract method that drivers must implement.
  */
 
-Collection.prototype.getIndexes = function () {
+Collection.prototype.getIndexes = function() {
   throw new Error('Collection#getIndexes unimplemented by driver');
 };
 
@@ -195,7 +195,7 @@ Collection.prototype.getIndexes = function () {
  * Abstract method that drivers must implement.
  */
 
-Collection.prototype.mapReduce = function () {
+Collection.prototype.mapReduce = function() {
   throw new Error('Collection#mapReduce unimplemented by driver');
 };
 
diff --git a/lib/connection.js b/lib/connection.js
index 9cfe32a7575..e2fa0037da0 100644
--- a/lib/connection.js
+++ b/lib/connection.js
@@ -94,10 +94,10 @@ Connection.prototype.__proto__ = EventEmitter.prototype;
  */
 
 Object.defineProperty(Connection.prototype, 'readyState', {
-  get: function () {
+  get: function() {
     return this._readyState;
   },
-  set: function (val) {
+  set: function(val) {
     if (!(val in STATES)) {
       throw new Error('Invalid connection state: ' + val);
     }
@@ -173,7 +173,7 @@ Connection.prototype.config;
  * @api public
  */
 
-Connection.prototype.open = function (host, database, port, options, callback) {
+Connection.prototype.open = function(host, database, port, options, callback) {
   var parsed;
 
   if (typeof database === 'string') {
@@ -278,8 +278,8 @@ Connection.prototype.open = function (host, database, port, options, callback) {
 
   var _this = this;
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve, reject) {
-    _this._open(!!callback, function (error) {
+  return new Promise.ES6(function(resolve, reject) {
+    _this._open(!!callback, function(error) {
       callback && callback(error);
       if (error) {
         reject(error);
@@ -334,7 +334,7 @@ Connection.prototype.open = function (host, database, port, options, callback) {
  * @api public
  */
 
-Connection.prototype.openSet = function (uris, database, options, callback) {
+Connection.prototype.openSet = function(uris, database, options, callback) {
   if (!rgxProtocol.test(uris)) {
     uris = 'mongodb://' + uris;
   }
@@ -412,8 +412,8 @@ Connection.prototype.openSet = function (uris, database, options, callback) {
 
   var _this = this;
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve, reject) {
-    _this._open(!!callback, function (error) {
+  return new Promise.ES6(function(resolve, reject) {
+    _this._open(!!callback, function(error) {
       callback && callback(error);
       if (error) {
         reject(error);
@@ -435,7 +435,7 @@ Connection.prototype.openSet = function (uris, database, options, callback) {
  * @api private
  */
 
-Connection.prototype.error = function (err, callback) {
+Connection.prototype.error = function(err, callback) {
   if (callback) {
     return callback(err);
   }
@@ -449,7 +449,7 @@ Connection.prototype.error = function (err, callback) {
  * @api private
  */
 
-Connection.prototype._open = function (emit, callback) {
+Connection.prototype._open = function(emit, callback) {
   this.readyState = STATES.connecting;
   this._closeCalled = false;
 
@@ -460,7 +460,7 @@ Connection.prototype._open = function (emit, callback) {
       : 'doOpen';
 
   // open connection
-  this[method](function (err) {
+  this[method](function(err) {
     if (err) {
       _this.readyState = STATES.disconnected;
       if (_this._hasOpened) {
@@ -483,7 +483,7 @@ Connection.prototype._open = function (emit, callback) {
  * @api private
  */
 
-Connection.prototype.onOpen = function (callback) {
+Connection.prototype.onOpen = function(callback) {
   var _this = this;
 
   function open(err, isAuth) {
@@ -513,7 +513,7 @@ Connection.prototype.onOpen = function (callback) {
 
   // re-authenticate
   if (this.shouldAuthenticate()) {
-    _this.db.authenticate(_this.user, _this.pass, _this.options.auth, function (err) {
+    _this.db.authenticate(_this.user, _this.pass, _this.options.auth, function(err) {
       open(err, true);
     });
   } else {
@@ -529,11 +529,11 @@ Connection.prototype.onOpen = function (callback) {
  * @api public
  */
 
-Connection.prototype.close = function (callback) {
+Connection.prototype.close = function(callback) {
   var _this = this;
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve, reject) {
-    _this._close(function (error) {
+  return new Promise.ES6(function(resolve, reject) {
+    _this._close(function(error) {
       callback && callback(error);
       if (error) {
         reject(error);
@@ -550,7 +550,7 @@ Connection.prototype.close = function (callback) {
  * @param {Function} callback
  * @api private
  */
-Connection.prototype._close = function (callback) {
+Connection.prototype._close = function(callback) {
   var _this = this;
   this._closeCalled = true;
 
@@ -562,7 +562,7 @@ Connection.prototype._close = function (callback) {
     case 1: // connected
     case 4: // unauthorized
       this.readyState = STATES.disconnecting;
-      this.doClose(function (err) {
+      this.doClose(function(err) {
         if (err) {
           _this.error(err, callback);
         } else {
@@ -573,7 +573,7 @@ Connection.prototype._close = function (callback) {
       break;
 
     case 2: // connecting
-      this.once('open', function () {
+      this.once('open', function() {
         _this.close(callback);
       });
       break;
@@ -582,7 +582,7 @@ Connection.prototype._close = function (callback) {
       if (!callback) {
         break;
       }
-      this.once('close', function () {
+      this.once('close', function() {
         callback();
       });
       break;
@@ -597,7 +597,7 @@ Connection.prototype._close = function (callback) {
  * @api private
  */
 
-Connection.prototype.onClose = function () {
+Connection.prototype.onClose = function() {
   this.readyState = STATES.disconnected;
 
   // avoid having the collection subscribe to our event emitter
@@ -620,7 +620,7 @@ Connection.prototype.onClose = function () {
  * @api public
  */
 
-Connection.prototype.collection = function (name, options) {
+Connection.prototype.collection = function(name, options) {
   if (!(name in this.collections)) {
     this.collections[name] = new Collection(name, this, options);
   }
@@ -659,7 +659,7 @@ Connection.prototype.collection = function (name, options) {
  * @api public
  */
 
-Connection.prototype.model = function (name, schema, collection) {
+Connection.prototype.model = function(name, schema, collection) {
   // collection name discovery
   if (typeof schema === 'string') {
     collection = schema;
@@ -733,7 +733,7 @@ Connection.prototype.model = function (name, schema, collection) {
  * @return {Array}
  */
 
-Connection.prototype.modelNames = function () {
+Connection.prototype.modelNames = function() {
   return Object.keys(this.models);
 };
 
@@ -744,7 +744,7 @@ Connection.prototype.modelNames = function () {
  * @api private
  * @return {Boolean} true if the connection should be authenticated after it is opened, otherwise false.
  */
-Connection.prototype.shouldAuthenticate = function () {
+Connection.prototype.shouldAuthenticate = function() {
   return (this.user !== null && this.user !== void 0) &&
       ((this.pass !== null || this.pass !== void 0) || this.authMechanismDoesNotRequirePassword());
 };
@@ -756,7 +756,7 @@ Connection.prototype.shouldAuthenticate = function () {
  * @return {Boolean} true if the authentication mechanism specified in the options object requires
  *  a password, otherwise false.
  */
-Connection.prototype.authMechanismDoesNotRequirePassword = function () {
+Connection.prototype.authMechanismDoesNotRequirePassword = function() {
   if (this.options && this.options.auth) {
     return authMechanismsWhichDontRequirePassword.indexOf(this.options.auth.authMechanism) >= 0;
   }
@@ -773,7 +773,7 @@ Connection.prototype.authMechanismDoesNotRequirePassword = function () {
  * @return {Boolean} true if the provided options object provides enough data to authenticate with,
  *   otherwise false.
  */
-Connection.prototype.optionsProvideAuthenticationData = function (options) {
+Connection.prototype.optionsProvideAuthenticationData = function(options) {
   return (options) &&
       (options.user) &&
       ((options.pass) || this.authMechanismDoesNotRequirePassword());
diff --git a/lib/document.js b/lib/document.js
index 896ab67c421..edd70125b37 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -66,7 +66,7 @@ function Document(obj, fields, skipId) {
     var _this = this,
         keys = Object.keys(this._doc);
 
-    keys.forEach(function (key) {
+    keys.forEach(function(key) {
       if (!(key in schema.tree)) {
         defineKey(key, null, _this);
       }
@@ -83,8 +83,8 @@ function Document(obj, fields, skipId) {
 utils.each(
     ['on', 'once', 'emit', 'listeners', 'removeListener', 'setMaxListeners',
       'removeAllListeners', 'addListener'],
-    function (emitterFn) {
-      Document.prototype[emitterFn] = function () {
+    function(emitterFn) {
+      Document.prototype[emitterFn] = function() {
         return this.$__.emitter[emitterFn].apply(this.$__.emitter, arguments);
       };
     });
@@ -146,7 +146,7 @@ Document.prototype.errors;
  * @memberOf Document
  */
 
-Document.prototype.$__buildDoc = function (obj, fields, skipId) {
+Document.prototype.$__buildDoc = function(obj, fields, skipId) {
   var doc = {};
   var exclude = null;
   var keys;
@@ -260,7 +260,7 @@ Document.prototype.$__buildDoc = function (obj, fields, skipId) {
  * @api public
  */
 
-Document.prototype.init = function (doc, opts, fn) {
+Document.prototype.init = function(doc, opts, fn) {
   // do not prefix this method with $__ since its
   // used by public hooks
 
@@ -360,7 +360,7 @@ function init(self, obj, doc, prefix) {
  * @memberOf Document
  */
 
-Document.prototype.$__storeShard = function () {
+Document.prototype.$__storeShard = function() {
   // backwards compat
   var key = this.schema.options.shardKey || this.schema.options.shardkey;
   if (!(key && utils.getFunctionName(key.constructor) === 'Object')) {
@@ -452,7 +452,7 @@ Document.prototype.update = function update() {
  * @api public
  */
 
-Document.prototype.set = function (path, val, type, options) {
+Document.prototype.set = function(path, val, type, options) {
   if (type && utils.getFunctionName(type.constructor) === 'Object') {
     options = type;
     type = undefined;
@@ -651,13 +651,13 @@ Document.prototype.set = function (path, val, type, options) {
         schema.options.type[0].ref === val[0].constructor.modelName) {
       if (this.ownerDocument) {
         this.ownerDocument().populated(this.$__fullPath(path),
-            val.map(function (v) {
+            val.map(function(v) {
               return v._id;
             }),
             {model: val[0].constructor});
       } else {
         this.populated(path, val
-        .map(function (v) {
+        .map(function(v) {
           return v._id;
         }),
             {model: val[0].constructor});
@@ -697,7 +697,7 @@ Document.prototype.set = function (path, val, type, options) {
  * @memberOf Document
  */
 
-Document.prototype.$__shouldModify = function (pathToMark, path, constructing, parts, schema, val, priorVal) {
+Document.prototype.$__shouldModify = function(pathToMark, path, constructing, parts, schema, val, priorVal) {
   if (this.isNew) {
     return true;
   }
@@ -736,7 +736,7 @@ Document.prototype.$__shouldModify = function (pathToMark, path, constructing, p
  * @memberOf Document
  */
 
-Document.prototype.$__set = function (pathToMark, path, constructing, parts, schema, val/* , priorVal */) {
+Document.prototype.$__set = function(pathToMark, path, constructing, parts, schema, val/* , priorVal */) {
   Embedded = Embedded || require('./types/embedded');
 
   var shouldModify = this.$__shouldModify.apply(this, arguments);
@@ -752,7 +752,7 @@ Document.prototype.$__set = function (pathToMark, path, constructing, parts, sch
 
       // Small hack for gh-1638: if we're overwriting the entire array, ignore
       // paths that were modified before the array overwrite
-      this.$__.activePaths.forEach(function (modifiedPath) {
+      this.$__.activePaths.forEach(function(modifiedPath) {
         if (modifiedPath.indexOf(path + '.') === 0) {
           _this.$__.activePaths.ignore(modifiedPath);
         }
@@ -793,7 +793,7 @@ Document.prototype.$__set = function (pathToMark, path, constructing, parts, sch
  * @api private
  */
 
-Document.prototype.getValue = function (path) {
+Document.prototype.getValue = function(path) {
   return utils.getValue(path, this._doc);
 };
 
@@ -805,7 +805,7 @@ Document.prototype.getValue = function (path) {
  * @api private
  */
 
-Document.prototype.setValue = function (path, val) {
+Document.prototype.setValue = function(path, val) {
   utils.setValue(path, val, this._doc);
   return this;
 };
@@ -826,7 +826,7 @@ Document.prototype.setValue = function (path, val) {
  * @api public
  */
 
-Document.prototype.get = function (path, type) {
+Document.prototype.get = function(path, type) {
   var adhoc;
   if (type) {
     adhoc = Schema.interpretAsType(path, type, this.schema.options);
@@ -864,7 +864,7 @@ Document.prototype.get = function (path, type) {
  * @memberOf Document
  */
 
-Document.prototype.$__path = function (path) {
+Document.prototype.$__path = function(path) {
   var adhocs = this.$__.adhocPaths,
       adhocType = adhocs && adhocs[path];
 
@@ -889,7 +889,7 @@ Document.prototype.$__path = function (path) {
  * @api public
  */
 
-Document.prototype.markModified = function (path) {
+Document.prototype.markModified = function(path) {
   this.$__.activePaths.modify(path);
 };
 
@@ -900,12 +900,12 @@ Document.prototype.markModified = function (path) {
  * @api public
  */
 
-Document.prototype.modifiedPaths = function () {
+Document.prototype.modifiedPaths = function() {
   var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
 
-  return directModifiedPaths.reduce(function (list, path) {
+  return directModifiedPaths.reduce(function(list, path) {
     var parts = path.split('.');
-    return list.concat(parts.reduce(function (chains, part, i) {
+    return list.concat(parts.reduce(function(chains, part, i) {
       return chains.concat(parts.slice(0, i).concat(part).join('.'));
     }, []));
   }, []);
@@ -929,7 +929,7 @@ Document.prototype.modifiedPaths = function () {
  * @api public
  */
 
-Document.prototype.isModified = function (path) {
+Document.prototype.isModified = function(path) {
   return path
       ? !!~this.modifiedPaths().indexOf(path)
       : this.$__.activePaths.some('modify');
@@ -949,7 +949,7 @@ Document.prototype.isModified = function (path) {
  * @api public
  */
 
-Document.prototype.$isDefault = function (path) {
+Document.prototype.$isDefault = function(path) {
   return (path in this.$__.activePaths.states.default);
 };
 
@@ -967,7 +967,7 @@ Document.prototype.$isDefault = function (path) {
  * @api public
  */
 
-Document.prototype.isDirectModified = function (path) {
+Document.prototype.isDirectModified = function(path) {
   return (path in this.$__.activePaths.states.modify);
 };
 
@@ -979,7 +979,7 @@ Document.prototype.isDirectModified = function (path) {
  * @api public
  */
 
-Document.prototype.isInit = function (path) {
+Document.prototype.isInit = function(path) {
   return (path in this.$__.activePaths.states.init);
 };
 
@@ -1071,7 +1071,7 @@ Document.prototype.isSelected = function isSelected(path) {
  * @api public
  */
 
-Document.prototype.validate = function (options, callback) {
+Document.prototype.validate = function(options, callback) {
   var _this = this;
   var Promise = PromiseProvider.get();
   if (typeof options === 'function') {
@@ -1084,8 +1084,8 @@ Document.prototype.validate = function (options, callback) {
     return;
   }
 
-  return new Promise.ES6(function (resolve, reject) {
-    _this.$__validate(function (error) {
+  return new Promise.ES6(function(resolve, reject) {
+    _this.$__validate(function(error) {
       callback && callback(error);
       if (error) {
         reject(error);
@@ -1100,9 +1100,9 @@ Document.prototype.validate = function (options, callback) {
  * ignore
  */
 
-Document.prototype.$__validate = function (callback) {
+Document.prototype.$__validate = function(callback) {
   var _this = this;
-  var _complete = function () {
+  var _complete = function() {
     var err = _this.$__.validationError;
     _this.$__.validationError = undefined;
     _this.emit('validate', _this);
@@ -1119,7 +1119,7 @@ Document.prototype.$__validate = function (callback) {
   };
 
   // only validate required fields when necessary
-  var paths = Object.keys(this.$__.activePaths.states.require).filter(function (path) {
+  var paths = Object.keys(this.$__.activePaths.states.require).filter(function(path) {
     if (!_this.isSelected(path) && !_this.isModified(path)) {
       return false;
     }
@@ -1131,7 +1131,7 @@ Document.prototype.$__validate = function (callback) {
   paths = paths.concat(Object.keys(this.$__.activePaths.states.default));
 
   if (paths.length === 0) {
-    process.nextTick(function () {
+    process.nextTick(function() {
       var err = _complete();
       if (err) {
         callback(err);
@@ -1157,7 +1157,7 @@ Document.prototype.$__validate = function (callback) {
     }
   }
 
-  var complete = function () {
+  var complete = function() {
     var err = _complete();
     if (err) {
       callback(err);
@@ -1166,7 +1166,7 @@ Document.prototype.$__validate = function (callback) {
     callback();
   };
 
-  var validatePath = function (path) {
+  var validatePath = function(path) {
     if (validating[path]) {
       return;
     }
@@ -1174,7 +1174,7 @@ Document.prototype.$__validate = function (callback) {
     validating[path] = true;
     total++;
 
-    process.nextTick(function () {
+    process.nextTick(function() {
       var p = _this.schema.path(path);
       if (!p) {
         return --total || complete();
@@ -1187,7 +1187,7 @@ Document.prototype.$__validate = function (callback) {
       }
 
       var val = _this.getValue(path);
-      p.doValidate(val, function (err) {
+      p.doValidate(val, function(err) {
         if (err) {
           _this.invalidate(path, err, undefined, true);
         }
@@ -1220,7 +1220,7 @@ Document.prototype.$__validate = function (callback) {
  * @api public
  */
 
-Document.prototype.validateSync = function (pathsToValidate) {
+Document.prototype.validateSync = function(pathsToValidate) {
   var _this = this;
 
   if (typeof pathsToValidate === 'string') {
@@ -1228,7 +1228,7 @@ Document.prototype.validateSync = function (pathsToValidate) {
   }
 
   // only validate required fields when necessary
-  var paths = Object.keys(this.$__.activePaths.states.require).filter(function (path) {
+  var paths = Object.keys(this.$__.activePaths.states.require).filter(function(path) {
     if (!_this.isSelected(path) && !_this.isModified(path)) {
       return false;
     }
@@ -1251,7 +1251,7 @@ Document.prototype.validateSync = function (pathsToValidate) {
 
   var validating = {};
 
-  paths.forEach(function (path) {
+  paths.forEach(function(path) {
     if (validating[path]) {
       return;
     }
@@ -1318,7 +1318,7 @@ Document.prototype.validateSync = function (pathsToValidate) {
  * @api public
  */
 
-Document.prototype.invalidate = function (path, err, val) {
+Document.prototype.invalidate = function(path, err, val) {
   if (!this.$__.validationError) {
     this.$__.validationError = new ValidationError(this);
   }
@@ -1352,7 +1352,7 @@ Document.prototype.invalidate = function (path, err, val) {
  * @receiver Document
  */
 
-Document.prototype.$markValid = function (path) {
+Document.prototype.$markValid = function(path) {
   if (!this.$__.validationError || !this.$__.validationError.errors[path]) {
     return;
   }
@@ -1372,7 +1372,7 @@ Document.prototype.$markValid = function (path) {
  * @receiver Document
  */
 
-Document.prototype.$isValid = function (path) {
+Document.prototype.$isValid = function(path) {
   return !this.$__.validationError || !this.$__.validationError.errors[path];
 };
 
@@ -1390,13 +1390,13 @@ Document.prototype.$__reset = function reset() {
   DocumentArray || (DocumentArray = require('./types/documentarray'));
 
   this.$__.activePaths
-  .map('init', 'modify', function (i) {
+  .map('init', 'modify', function(i) {
     return _this.getValue(i);
   })
-  .filter(function (val) {
+  .filter(function(val) {
     return val && val instanceof Array && val.isMongooseDocumentArray && val.length;
   })
-  .forEach(function (array) {
+  .forEach(function(array) {
     var i = array.length;
     while (i--) {
       var doc = array[i];
@@ -1408,7 +1408,7 @@ Document.prototype.$__reset = function reset() {
   });
 
   // clear atomics
-  this.$__dirty().forEach(function (dirt) {
+  this.$__dirty().forEach(function(dirt) {
     var type = dirt.value;
     if (type && type._atomics) {
       type._atomics = {};
@@ -1421,7 +1421,7 @@ Document.prototype.$__reset = function reset() {
   this.$__.validationError = undefined;
   this.errors = undefined;
   _this = this;
-  this.schema.requiredPaths().forEach(function (path) {
+  this.schema.requiredPaths().forEach(function(path) {
     _this.$__.activePaths.require(path);
   });
 
@@ -1436,10 +1436,10 @@ Document.prototype.$__reset = function reset() {
  * @memberOf Document
  */
 
-Document.prototype.$__dirty = function () {
+Document.prototype.$__dirty = function() {
   var _this = this;
 
-  var all = this.$__.activePaths.map('modify', function (path) {
+  var all = this.$__.activePaths.map('modify', function(path) {
     return {
       path: path,
       value: _this.getValue(path),
@@ -1449,7 +1449,7 @@ Document.prototype.$__dirty = function () {
 
   // gh-2558: if we had to set a default and the value is not undefined,
   // we have to save as well
-  all = all.concat(this.$__.activePaths.map('default', function (path) {
+  all = all.concat(this.$__.activePaths.map('default', function(path) {
     if (path === '_id' || !_this.getValue(path)) {
       return;
     }
@@ -1461,7 +1461,7 @@ Document.prototype.$__dirty = function () {
   }));
 
   // Sort dirty paths in a flat hierarchy.
-  all.sort(function (a, b) {
+  all.sort(function(a, b) {
     return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
   });
 
@@ -1470,7 +1470,7 @@ Document.prototype.$__dirty = function () {
       lastPath,
       top;
 
-  all.forEach(function (item) {
+  all.forEach(function(item) {
     if (!item) {
       return;
     }
@@ -1526,7 +1526,7 @@ function compile(tree, proto, prefix, options) {
 function getOwnPropertyDescriptors(object) {
   var result = {};
 
-  Object.getOwnPropertyNames(object).forEach(function (key) {
+  Object.getOwnPropertyNames(object).forEach(function(key) {
     result[key] = Object.getOwnPropertyDescriptor(object, key);
     result[key].enumerable = true;
   });
@@ -1546,7 +1546,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
     Object.defineProperty(prototype, prop, {
       enumerable: true,
       configurable: true,
-      get: function () {
+      get: function() {
         var _this = this;
         if (!this.$__.getters) {
           this.$__.getters = {};
@@ -1579,7 +1579,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
             enumerable: true,
             configurable: true,
             writable: false,
-            value: function () {
+            value: function() {
               return _this.get(path);
             }
           });
@@ -1588,7 +1588,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
             enumerable: true,
             configurable: true,
             writable: false,
-            value: function () {
+            value: function() {
               return _this.get(path);
             }
           });
@@ -1606,7 +1606,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
 
         return this.$__.getters[path];
       },
-      set: function (v) {
+      set: function(v) {
         if (v instanceof Document) {
           v = v.toObject();
         }
@@ -1617,10 +1617,10 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
     Object.defineProperty(prototype, prop, {
       enumerable: true,
       configurable: true,
-      get: function () {
+      get: function() {
         return this.get.call(this.$__.scope || this, path);
       },
-      set: function (v) {
+      set: function(v) {
         return this.set.call(this.$__.scope || this, path, v);
       }
     });
@@ -1636,7 +1636,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
  * @memberOf Document
  */
 
-Document.prototype.$__setSchema = function (schema) {
+Document.prototype.$__setSchema = function(schema) {
   compile(schema.tree, this, undefined, schema.options);
   this.schema = schema;
 };
@@ -1650,20 +1650,20 @@ Document.prototype.$__setSchema = function (schema) {
  * @memberOf Document
  */
 
-Document.prototype.$__getArrayPathsToValidate = function () {
+Document.prototype.$__getArrayPathsToValidate = function() {
   DocumentArray || (DocumentArray = require('./types/documentarray'));
 
   // validate all document arrays.
   return this.$__.activePaths
-  .map('init', 'modify', function (i) {
+  .map('init', 'modify', function(i) {
     return this.getValue(i);
   }.bind(this))
-  .filter(function (val) {
+  .filter(function(val) {
     return val && val instanceof Array && val.isMongooseDocumentArray && val.length;
-  }).reduce(function (seed, array) {
+  }).reduce(function(seed, array) {
     return seed.concat(array);
   }, [])
-  .filter(function (doc) {
+  .filter(function(doc) {
     return doc;
   });
 };
@@ -1677,7 +1677,7 @@ Document.prototype.$__getArrayPathsToValidate = function () {
  * @memberOf Document
  */
 
-Document.prototype.$__getAllSubdocs = function () {
+Document.prototype.$__getAllSubdocs = function() {
   DocumentArray || (DocumentArray = require('./types/documentarray'));
   Embedded = Embedded || require('./types/embedded');
 
@@ -1723,7 +1723,7 @@ Document.prototype.$__getAllSubdocs = function () {
  * @memberOf Document
  */
 
-Document.prototype.$__registerHooksFromSchema = function () {
+Document.prototype.$__registerHooksFromSchema = function() {
   Embedded = Embedded || require('./types/embedded');
   var Promise = PromiseProvider.get();
 
@@ -1734,7 +1734,7 @@ Document.prototype.$__registerHooksFromSchema = function () {
   }
 
   // we are only interested in 'pre' hooks, and group by point-cut
-  var toWrap = q.reduce(function (seed, pair) {
+  var toWrap = q.reduce(function(seed, pair) {
     if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') {
       _this[pair[0]].apply(_this, pair[1]);
       return seed;
@@ -1755,7 +1755,7 @@ Document.prototype.$__registerHooksFromSchema = function () {
   }, {post: []});
 
   // 'post' hooks are simpler
-  toWrap.post.forEach(function (args) {
+  toWrap.post.forEach(function(args) {
     _this.on.apply(_this, args);
   });
   delete toWrap.post;
@@ -1763,12 +1763,12 @@ Document.prototype.$__registerHooksFromSchema = function () {
   // 'init' should be synchronous on subdocuments
   if (toWrap.init && _this instanceof Embedded) {
     if (toWrap.init.pre) {
-      toWrap.init.pre.forEach(function (args) {
+      toWrap.init.pre.forEach(function(args) {
         _this.pre.apply(_this, args);
       });
     }
     if (toWrap.init.post) {
-      toWrap.init.post.forEach(function (args) {
+      toWrap.init.post.forEach(function(args) {
         _this.post.apply(_this, args);
       });
     }
@@ -1776,19 +1776,19 @@ Document.prototype.$__registerHooksFromSchema = function () {
   } else if (toWrap.set) {
     // Set hooks also need to be sync re: gh-3479
     if (toWrap.set.pre) {
-      toWrap.set.pre.forEach(function (args) {
+      toWrap.set.pre.forEach(function(args) {
         _this.pre.apply(_this, args);
       });
     }
     if (toWrap.set.post) {
-      toWrap.set.post.forEach(function (args) {
+      toWrap.set.post.forEach(function(args) {
         _this.post.apply(_this, args);
       });
     }
     delete toWrap.set;
   }
 
-  Object.keys(toWrap).forEach(function (pointCut) {
+  Object.keys(toWrap).forEach(function(pointCut) {
     // this is so we can wrap everything into a promise;
     var newName = ('$__original_' + pointCut);
     if (!_this[pointCut]) {
@@ -1800,13 +1800,13 @@ Document.prototype.$__registerHooksFromSchema = function () {
       var lastArg = args.pop();
       var fn;
 
-      return new Promise.ES6(function (resolve, reject) {
+      return new Promise.ES6(function(resolve, reject) {
         if (lastArg && typeof lastArg !== 'function') {
           args.push(lastArg);
         } else {
           fn = lastArg;
         }
-        args.push(function (error, result) {
+        args.push(function(error, result) {
           if (error) {
             _this.$__handleReject(error);
             fn && fn(error);
@@ -1822,11 +1822,11 @@ Document.prototype.$__registerHooksFromSchema = function () {
       });
     };
 
-    toWrap[pointCut].pre.forEach(function (args) {
+    toWrap[pointCut].pre.forEach(function(args) {
       args[0] = newName;
       _this.pre.apply(_this, args);
     });
-    toWrap[pointCut].post.forEach(function (args) {
+    toWrap[pointCut].post.forEach(function(args) {
       args[0] = newName;
       _this.post.apply(_this, args);
     });
@@ -1853,7 +1853,7 @@ Document.prototype.$__handleReject = function handleReject(err) {
  * @memberOf Document
  */
 
-Document.prototype.$toObject = function (options, json) {
+Document.prototype.$toObject = function(options, json) {
   var defaultOptions = {transform: true, json: json};
 
   if (options && options.depopulate && !options._skipDepopulateTopLevel && this.$__.wasPopulated) {
@@ -2060,7 +2060,7 @@ Document.prototype.$toObject = function (options, json) {
  * @api public
  */
 
-Document.prototype.toObject = function (options) {
+Document.prototype.toObject = function(options) {
   return this.$toObject(options);
 };
 
@@ -2151,7 +2151,7 @@ function applyGetters(self, json, type, options) {
  * @api public
  */
 
-Document.prototype.toJSON = function (options) {
+Document.prototype.toJSON = function(options) {
   return this.$toObject(options, true);
 };
 
@@ -2161,7 +2161,7 @@ Document.prototype.toJSON = function (options) {
  * @api public
  */
 
-Document.prototype.inspect = function (options) {
+Document.prototype.inspect = function(options) {
   var opts = options && utils.getFunctionName(options.constructor) === 'Object' ? options : {};
   opts.minimize = false;
   opts.retainKeyOrder = true;
@@ -2175,7 +2175,7 @@ Document.prototype.inspect = function (options) {
  * @method toString
  */
 
-Document.prototype.toString = function () {
+Document.prototype.toString = function() {
   return inspect(this.inspect());
 };
 
@@ -2191,7 +2191,7 @@ Document.prototype.toString = function () {
  * @api public
  */
 
-Document.prototype.equals = function (doc) {
+Document.prototype.equals = function(doc) {
   var tid = this.get('_id');
   var docid = doc.get ? doc.get('_id') : doc;
   if (!tid && !docid) {
@@ -2299,11 +2299,11 @@ Document.prototype.populate = function populate() {
  * @return {Promise} promise that resolves to the document when population is done
  */
 
-Document.prototype.execPopulate = function () {
+Document.prototype.execPopulate = function() {
   var Promise = PromiseProvider.get();
   var _this = this;
-  return new Promise.ES6(function (resolve, reject) {
-    _this.populate(function (error, res) {
+  return new Promise.ES6(function(resolve, reject) {
+    _this.populate(function(error, res) {
       if (error) {
         reject(error);
       } else {
@@ -2330,7 +2330,7 @@ Document.prototype.execPopulate = function () {
  * @api public
  */
 
-Document.prototype.populated = function (path, val, options) {
+Document.prototype.populated = function(path, val, options) {
   // val and options are internal
 
   if (val === null || val === void 0) {
@@ -2375,7 +2375,7 @@ Document.prototype.populated = function (path, val, options) {
  * @api public
  */
 
-Document.prototype.depopulate = function (path) {
+Document.prototype.depopulate = function(path) {
   var populatedIds = this.populated(path);
   if (!populatedIds) {
     return;
@@ -2395,7 +2395,7 @@ Document.prototype.depopulate = function (path) {
  * @memberOf Document
  */
 
-Document.prototype.$__fullPath = function (path) {
+Document.prototype.$__fullPath = function(path) {
   // overridden in SubDocuments
   return path || '';
 };
diff --git a/lib/document_provider.js b/lib/document_provider.js
index 6a8c514a32c..131a6096c1d 100644
--- a/lib/document_provider.js
+++ b/lib/document_provider.js
@@ -11,7 +11,7 @@ var BrowserDocument = require('./browserDocument.js');
  *
  * @api private
  */
-module.exports = function () {
+module.exports = function() {
   if (typeof window !== 'undefined' && typeof document !== 'undefined' && document === window.document) {
     return BrowserDocument;
   }
diff --git a/lib/drivers/browser/ReadPreference.js b/lib/drivers/browser/ReadPreference.js
index 8567ce079d5..f20cd6cc0d8 100644
--- a/lib/drivers/browser/ReadPreference.js
+++ b/lib/drivers/browser/ReadPreference.js
@@ -2,4 +2,4 @@
  * ignore
  */
 
-module.exports = function () {};
+module.exports = function() {};
diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js
index 7c2ea597cb1..9038f0e38f7 100644
--- a/lib/drivers/node-mongodb-native/collection.js
+++ b/lib/drivers/node-mongodb-native/collection.js
@@ -32,7 +32,7 @@ NativeCollection.prototype.__proto__ = MongooseCollection.prototype;
  * @api private
  */
 
-NativeCollection.prototype.onOpen = function () {
+NativeCollection.prototype.onOpen = function() {
   var _this = this;
 
   // always get a new collection in case the user changed host:port
@@ -44,11 +44,11 @@ NativeCollection.prototype.onOpen = function () {
   }
 
   // capped
-  return _this.conn.db.collection(_this.name, function (err, c) {
+  return _this.conn.db.collection(_this.name, function(err, c) {
     if (err) return callback(err);
 
     // discover if this collection exists and if it is capped
-    _this.conn.db.listCollections({name: _this.name}).toArray(function (err, docs) {
+    _this.conn.db.listCollections({name: _this.name}).toArray(function(err, docs) {
       if (err) {
         return callback(err);
       }
@@ -92,7 +92,7 @@ NativeCollection.prototype.onOpen = function () {
  * @api private
  */
 
-NativeCollection.prototype.onClose = function () {
+NativeCollection.prototype.onClose = function() {
   MongooseCollection.prototype.onClose.call(this);
 };
 
@@ -111,8 +111,8 @@ for (var i in Collection.prototype) {
     continue;
   }
 
-  (function (i) {
-    NativeCollection.prototype[i] = function () {
+  (function(i) {
+    NativeCollection.prototype[i] = function() {
       if (this.buffer) {
         this.addQueue(i, arguments);
         return;
@@ -143,7 +143,7 @@ for (var i in Collection.prototype) {
  * @api public
  */
 
-NativeCollection.prototype.$print = function (name, i, args) {
+NativeCollection.prototype.$print = function(name, i, args) {
   console.error(
       '\x1B[0;36mMongoose:\x1B[0m %s.%s(%s) %s %s %s',
       name,
@@ -160,7 +160,7 @@ NativeCollection.prototype.$print = function (name, i, args) {
  * @api public
  */
 
-NativeCollection.prototype.$format = function (arg) {
+NativeCollection.prototype.$format = function(arg) {
   var type = typeof arg;
   if (type === 'function' || type === 'undefined') return '';
   return format(arg);
@@ -178,10 +178,10 @@ function format(obj, sub) {
       x = '[object Buffer]';
     } else if (x.constructor.name === 'ObjectID') {
       representation = 'ObjectId("' + x.toHexString() + '")';
-      x = {inspect: function () { return representation; }};
+      x = {inspect: function() { return representation; }};
     } else if (x.constructor.name === 'Date') {
       representation = 'new Date("' + x.toUTCString() + '")';
-      x = {inspect: function () { return representation; }};
+      x = {inspect: function() { return representation; }};
     } else if (x.constructor.name === 'Object') {
       var keys = Object.keys(x);
       var numKeys = keys.length;
@@ -194,17 +194,17 @@ function format(obj, sub) {
           } else if (x[key].constructor.name === 'Object') {
             x[key] = format(x[key], true);
           } else if (x[key].constructor.name === 'ObjectID') {
-            (function (x) {
+            (function(x) {
               var representation = 'ObjectId("' + x[key].toHexString() + '")';
-              x[key] = {inspect: function () { return representation; }};
+              x[key] = {inspect: function() { return representation; }};
             })(x);
           } else if (x[key].constructor.name === 'Date') {
-            (function (x) {
+            (function(x) {
               var representation = 'new Date("' + x[key].toUTCString() + '")';
-              x[key] = {inspect: function () { return representation; }};
+              x[key] = {inspect: function() { return representation; }};
             })(x);
           } else if (Array.isArray(x[key])) {
-            x[key] = x[key].map(function (o) {
+            x[key] = x[key].map(function(o) {
               return format(o, true);
             });
           }
diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js
index f88bd03e4d6..0e417f7143f 100644
--- a/lib/drivers/node-mongodb-native/connection.js
+++ b/lib/drivers/node-mongodb-native/connection.js
@@ -43,7 +43,7 @@ NativeConnection.prototype.__proto__ = MongooseConnection.prototype;
  * @api private
  */
 
-NativeConnection.prototype.doOpen = function (fn) {
+NativeConnection.prototype.doOpen = function(fn) {
   var server = new Server(this.host, this.port, this.options.server);
 
   if (this.options && this.options.mongos) {
@@ -54,7 +54,7 @@ NativeConnection.prototype.doOpen = function (fn) {
   }
 
   var _this = this;
-  this.db.open(function (err) {
+  this.db.open(function(err) {
     if (err) return fn(err);
     listen(_this);
     fn();
@@ -73,7 +73,7 @@ NativeConnection.prototype.doOpen = function (fn) {
  * @api public
  */
 
-NativeConnection.prototype.useDb = function (name) {
+NativeConnection.prototype.useDb = function(name) {
   // we have to manually copy all of the attributes...
   var newConn = new this.constructor();
   newConn.name = name;
@@ -133,7 +133,7 @@ function listen(conn) {
   }
   conn.db._listening = true;
 
-  conn.db.on('close', function () {
+  conn.db.on('close', function() {
     if (conn._closeCalled) return;
 
     // the driver never emits an `open` event. auto_reconnect still
@@ -146,24 +146,24 @@ function listen(conn) {
     }
     conn.onClose();
   });
-  conn.db.on('error', function (err) {
+  conn.db.on('error', function(err) {
     conn.emit('error', err);
   });
-  conn.db.on('reconnect', function () {
+  conn.db.on('reconnect', function() {
     conn.readyState = STATES.connected;
     conn.emit('reconnected');
   });
-  conn.db.on('timeout', function (err) {
+  conn.db.on('timeout', function(err) {
     var error = new Error(err && err.err || 'connection timeout');
     conn.emit('error', error);
   });
-  conn.db.on('open', function (err, db) {
+  conn.db.on('open', function(err, db) {
     if (STATES.disconnected === conn.readyState && db && db.databaseName) {
       conn.readyState = STATES.connected;
       conn.emit('reconnected');
     }
   });
-  conn.db.on('parseError', function (err) {
+  conn.db.on('parseError', function(err) {
     conn.emit('parseError', err);
   });
 }
@@ -178,11 +178,11 @@ function listen(conn) {
  * @return {Connection} this
  */
 
-NativeConnection.prototype.doOpenSet = function (fn) {
+NativeConnection.prototype.doOpenSet = function(fn) {
   var servers = [],
       _this = this;
 
-  this.hosts.forEach(function (server) {
+  this.hosts.forEach(function(server) {
     var host = server.host || server.ipc;
     var port = server.port || 27017;
     servers.push(new Server(host, port, _this.options.server));
@@ -193,11 +193,11 @@ NativeConnection.prototype.doOpenSet = function (fn) {
     : new ReplSetServers(servers, this.options.replset || this.options.replSet);
   this.db = new Db(this.name, server, this.options.db);
 
-  this.db.on('fullsetup', function () {
+  this.db.on('fullsetup', function() {
     _this.emit('fullsetup');
   });
 
-  this.db.open(function (err) {
+  this.db.open(function(err) {
     if (err) return fn(err);
     fn();
     listen(_this);
@@ -214,7 +214,7 @@ NativeConnection.prototype.doOpenSet = function (fn) {
  * @api private
  */
 
-NativeConnection.prototype.doClose = function (fn) {
+NativeConnection.prototype.doClose = function(fn) {
   this.db.close(fn);
   return this;
 };
@@ -229,7 +229,7 @@ NativeConnection.prototype.doClose = function (fn) {
  * @api private
  */
 
-NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {
+NativeConnection.prototype.parseOptions = function(passed, connStrOpts) {
   var o = passed || {};
   o.db || (o.db = {});
   o.auth || (o.auth = {});
@@ -239,7 +239,7 @@ NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {
   o.replset.socketOptions || (o.replset.socketOptions = {});
 
   var opts = connStrOpts || {};
-  Object.keys(opts).forEach(function (name) {
+  Object.keys(opts).forEach(function(name) {
     switch (name) {
       case 'ssl':
       case 'poolSize':
diff --git a/lib/error/validation.js b/lib/error/validation.js
index 7e9d01127b4..bcbad610a38 100644
--- a/lib/error/validation.js
+++ b/lib/error/validation.js
@@ -42,11 +42,11 @@ ValidationError.prototype.constructor = MongooseError;
  * Console.log helper
  */
 
-ValidationError.prototype.toString = function () {
+ValidationError.prototype.toString = function() {
   var ret = this.name + ': ';
   var msgs = [];
 
-  Object.keys(this.errors).forEach(function (key) {
+  Object.keys(this.errors).forEach(function(key) {
     if (this === this.errors[key]) {
       return;
     }
diff --git a/lib/error/validator.js b/lib/error/validator.js
index fd7f0698edb..959073bc86e 100644
--- a/lib/error/validator.js
+++ b/lib/error/validator.js
@@ -44,7 +44,7 @@ ValidatorError.prototype.constructor = MongooseError;
  * Formats error messages
  */
 
-ValidatorError.prototype.formatMessage = function (msg, properties) {
+ValidatorError.prototype.formatMessage = function(msg, properties) {
   var propertyNames = Object.keys(properties);
   for (var i = 0; i < propertyNames.length; ++i) {
     var propertyName = propertyNames[i];
@@ -60,7 +60,7 @@ ValidatorError.prototype.formatMessage = function (msg, properties) {
  * toString helper
  */
 
-ValidatorError.prototype.toString = function () {
+ValidatorError.prototype.toString = function() {
   return this.message;
 };
 
diff --git a/lib/index.js b/lib/index.js
index c5051eddc6d..eaa2ca69ea5 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -65,7 +65,7 @@ Mongoose.prototype.STATES = STATES;
  * @api public
  */
 
-Mongoose.prototype.set = function (key, value) {
+Mongoose.prototype.set = function(key, value) {
   if (arguments.length === 1) {
     return this.options[key];
   }
@@ -106,7 +106,7 @@ var rgxReplSet = /^.+,.+$/;
  * @api private
  */
 
-var checkReplicaSetInUri = function (uri) {
+var checkReplicaSetInUri = function(uri) {
   if (!uri) {
     return false;
   }
@@ -171,7 +171,7 @@ var checkReplicaSetInUri = function (uri) {
  * @api public
  */
 
-Mongoose.prototype.createConnection = function (uri, options) {
+Mongoose.prototype.createConnection = function(uri, options) {
   var conn = new Connection(this);
   this.connections.push(conn);
 
@@ -228,7 +228,7 @@ Mongoose.prototype.createConnection = function (uri, options) {
  * @return {Mongoose} this
  */
 
-Mongoose.prototype.connect = function () {
+Mongoose.prototype.connect = function() {
   var conn = this.connection;
 
   if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) {
@@ -246,11 +246,11 @@ Mongoose.prototype.connect = function () {
  * @api public
  */
 
-Mongoose.prototype.disconnect = function (fn) {
+Mongoose.prototype.disconnect = function(fn) {
   var error;
 
-  this.connections.forEach(function (conn) {
-    conn.close(function (err) {
+  this.connections.forEach(function(conn) {
+    conn.close(function(err) {
       if (error) {
         return;
       }
@@ -261,7 +261,7 @@ Mongoose.prototype.disconnect = function (fn) {
   });
 
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve, reject) {
+  return new Promise.ES6(function(resolve, reject) {
     fn && fn(error);
     if (error) {
       reject(error);
@@ -311,7 +311,7 @@ Mongoose.prototype.disconnect = function (fn) {
  * @api public
  */
 
-Mongoose.prototype.model = function (name, schema, collection, skipInit) {
+Mongoose.prototype.model = function(name, schema, collection, skipInit) {
   if (typeof schema === 'string') {
     collection = schema;
     schema = false;
@@ -410,7 +410,7 @@ Mongoose.prototype.model = function (name, schema, collection, skipInit) {
  * @return {Array}
  */
 
-Mongoose.prototype.modelNames = function () {
+Mongoose.prototype.modelNames = function() {
   var names = Object.keys(this.models);
   return names;
 };
@@ -422,7 +422,7 @@ Mongoose.prototype.modelNames = function () {
  * @api private
  */
 
-Mongoose.prototype._applyPlugins = function (schema) {
+Mongoose.prototype._applyPlugins = function(schema) {
   for (var i = 0, l = this.plugins.length; i < l; i++) {
     schema.plugin(this.plugins[i][0], this.plugins[i][1]);
   }
@@ -440,7 +440,7 @@ Mongoose.prototype._applyPlugins = function (schema) {
  * @api public
  */
 
-Mongoose.prototype.plugin = function (fn, opts) {
+Mongoose.prototype.plugin = function(fn, opts) {
   this.plugins.push([fn, opts]);
   return this;
 };
@@ -461,7 +461,7 @@ Mongoose.prototype.plugin = function (fn, opts) {
  * @api public
  */
 
-Mongoose.prototype.__defineGetter__('connection', function () {
+Mongoose.prototype.__defineGetter__('connection', function() {
   return this.connections[0];
 });
 
@@ -626,10 +626,10 @@ Mongoose.prototype.Query = Query;
  */
 
 Object.defineProperty(Mongoose.prototype, 'Promise', {
-  get: function () {
+  get: function() {
     return PromiseProvider.get();
   },
-  set: function (lib) {
+  set: function(lib) {
     PromiseProvider.set(lib);
   }
 });
diff --git a/lib/model.js b/lib/model.js
index 05d604369b8..8d0e1c7fd18 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -88,7 +88,7 @@ Model.prototype.modelName;
 
 Model.prototype.baseModelName;
 
-Model.prototype.$__handleSave = function (options, callback) {
+Model.prototype.$__handleSave = function(options, callback) {
   var _this = this;
   if (!options.safe && this.schema.options.safe) {
     options.safe = this.schema.options.safe;
@@ -117,14 +117,14 @@ Model.prototype.$__handleSave = function (options, callback) {
       // wouldn't know what _id was generated by mongodb either
       // nor would the ObjectId generated my mongodb necessarily
       // match the schema definition.
-      setTimeout(function () {
+      setTimeout(function() {
         callback(new Error('document must have an _id before saving'));
       }, 0);
       return;
     }
 
     this.$__version(true, obj);
-    this.collection.insert(obj, options.safe, function (err, ret) {
+    this.collection.insert(obj, options.safe, function(err, ret) {
       if (err) {
         _this.isNew = true;
         _this.emit('isNew', true);
@@ -159,7 +159,7 @@ Model.prototype.$__handleSave = function (options, callback) {
         return;
       }
 
-      this.collection.update(where, delta[1], options.safe, function (err, ret) {
+      this.collection.update(where, delta[1], options.safe, function(err, ret) {
         if (err) {
           callback(err);
           return;
@@ -180,10 +180,10 @@ Model.prototype.$__handleSave = function (options, callback) {
  * ignore
  */
 
-Model.prototype.$__save = function (options, callback) {
+Model.prototype.$__save = function(options, callback) {
   var _this = this;
 
-  _this.$__handleSave(options, function (error, result) {
+  _this.$__handleSave(options, function(error, result) {
     if (error) {
       return callback(error);
     }
@@ -265,7 +265,7 @@ Model.prototype.$__save = function (options, callback) {
  * @see middleware http://mongoosejs.com/docs/middleware.html
  */
 
-Model.prototype.save = function (options, fn) {
+Model.prototype.save = function(options, fn) {
   if (typeof options === 'function') {
     fn = options;
     options = undefined;
@@ -281,8 +281,8 @@ Model.prototype.save = function (options, fn) {
 
   var _this = this;
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve, reject) {
-    _this.$__save(options, function (error, doc, numAffected) {
+  return new Promise.ES6(function(resolve, reject) {
+    _this.$__save(options, function(error, doc, numAffected) {
       if (error) {
         fn && fn(error);
         reject(error);
@@ -391,7 +391,7 @@ function handleAtomics(self, where, delta, data, value) {
   }
 
   if (typeof value.$__getAtomics === 'function') {
-    value.$__getAtomics().forEach(function (atomic) {
+    value.$__getAtomics().forEach(function(atomic) {
       var op = atomic[0];
       var val = atomic[1];
       operand(self, where, delta, data, val, op);
@@ -426,7 +426,7 @@ function handleAtomics(self, where, delta, data, value) {
     if (isMongooseObject(val)) {
       val = val.toObject({depopulate: 1});
     } else if (Array.isArray(val)) {
-      val = val.map(function (mem) {
+      val = val.map(function(mem) {
         return isMongooseObject(mem)
             ? mem.toObject({depopulate: 1})
             : mem;
@@ -451,7 +451,7 @@ function handleAtomics(self, where, delta, data, value) {
  * @memberOf Model
  */
 
-Model.prototype.$__delta = function () {
+Model.prototype.$__delta = function() {
   var dirty = this.$__dirty();
   if (!dirty.length && VERSION_ALL !== this.$__.version) return;
 
@@ -561,7 +561,7 @@ function checkDivergentArray(doc, path, array) {
  * @memberOf Model
  */
 
-Model.prototype.$__version = function (where, delta) {
+Model.prototype.$__version = function(where, delta) {
   var key = this.schema.options.versionKey;
 
   if (where === true) {
@@ -685,15 +685,15 @@ Model.prototype.remove = function remove(options, fn) {
   if (this.$__.removing) {
     if (fn) {
       this.$__.removing.then(
-          function (res) { fn(null, res); },
-          function (err) { fn(err); });
+          function(res) { fn(null, res); },
+          function(err) { fn(err); });
     }
     return this;
   }
 
   var _this = this;
   var Promise = PromiseProvider.get();
-  this.$__.removing = new Promise.ES6(function (resolve, reject) {
+  this.$__.removing = new Promise.ES6(function(resolve, reject) {
     var where = _this.$__where();
     if (where instanceof Error) {
       reject(where);
@@ -705,7 +705,7 @@ Model.prototype.remove = function remove(options, fn) {
       options.safe = _this.schema.options.safe;
     }
 
-    _this.collection.remove(where, options, function (err) {
+    _this.collection.remove(where, options, function(err) {
       if (!err) {
         _this.emit('remove', _this);
         resolve(_this);
@@ -779,7 +779,7 @@ Model.discriminator = function discriminator(name, schema) {
   }
 
   // merges base schema into new discriminator schema and sets new type field.
-  (function (schema, baseSchema) {
+  (function(schema, baseSchema) {
     utils.merge(schema, baseSchema);
 
     var obj = {};
@@ -792,7 +792,7 @@ Model.discriminator = function discriminator(name, schema) {
     }
 
     // throws error if options are invalid
-    (function (a, b) {
+    (function(a, b) {
       a = utils.clone(a);
       b = utils.clone(b);
       delete a.toJSON;
@@ -907,10 +907,10 @@ Model.init = function init() {
 Model.ensureIndexes = function ensureIndexes(cb) {
   var _this = this;
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve, reject) {
+  return new Promise.ES6(function(resolve, reject) {
     var indexes = _this.schema.indexes();
     if (!indexes.length) {
-      process.nextTick(function () {
+      process.nextTick(function() {
         cb && cb();
         resolve();
       });
@@ -919,7 +919,7 @@ Model.ensureIndexes = function ensureIndexes(cb) {
     // Indexes are created one-by-one to support how MongoDB < 2.4 deals
     // with background indexes.
 
-    var done = function (err) {
+    var done = function(err) {
       if (err && _this.schema.options.emitIndexErrors) {
         _this.emit('error', err);
       }
@@ -928,14 +928,14 @@ Model.ensureIndexes = function ensureIndexes(cb) {
       err ? reject(err) : resolve();
     };
 
-    var indexSingleDone = function (err, fields, options, name) {
+    var indexSingleDone = function(err, fields, options, name) {
       _this.emit('index-single-done', err, fields, options, name);
     };
-    var indexSingleStart = function (fields, options) {
+    var indexSingleStart = function(fields, options) {
       _this.emit('index-single-start', fields, options);
     };
 
-    var create = function () {
+    var create = function() {
       var index = indexes.shift();
       if (!index) return done();
 
@@ -945,7 +945,7 @@ Model.ensureIndexes = function ensureIndexes(cb) {
 
       indexSingleStart(indexFields, options);
 
-      _this.collection.ensureIndex(indexFields, options, tick(function (err, name) {
+      _this.collection.ensureIndex(indexFields, options, tick(function(err, name) {
         indexSingleDone(err, indexFields, options, name);
         if (err) {
           return done(err);
@@ -1422,7 +1422,7 @@ Model.$where = function $where() {
  * @api public
  */
 
-Model.findOneAndUpdate = function (conditions, update, options, callback) {
+Model.findOneAndUpdate = function(conditions, update, options, callback) {
   if (typeof options === 'function') {
     callback = options;
     options = null;
@@ -1530,7 +1530,7 @@ Model.findOneAndUpdate = function (conditions, update, options, callback) {
  * @api public
  */
 
-Model.findByIdAndUpdate = function (id, update, options, callback) {
+Model.findByIdAndUpdate = function(id, update, options, callback) {
   if (arguments.length === 1) {
     if (typeof id === 'function') {
       var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
@@ -1597,7 +1597,7 @@ Model.findByIdAndUpdate = function (id, update, options, callback) {
  * @api public
  */
 
-Model.findOneAndRemove = function (conditions, options, callback) {
+Model.findOneAndRemove = function(conditions, options, callback) {
   if (arguments.length === 1 && typeof conditions === 'function') {
     var msg = 'Model.findOneAndRemove(): First argument must not be a function.\n\n'
         + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)\n'
@@ -1651,7 +1651,7 @@ Model.findOneAndRemove = function (conditions, options, callback) {
  * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
  */
 
-Model.findByIdAndRemove = function (id, options, callback) {
+Model.findByIdAndRemove = function(id, options, callback) {
   if (arguments.length === 1 && typeof id === 'function') {
     var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\n\n'
         + '  ' + this.modelName + '.findByIdAndRemove(id, callback)\n'
@@ -1716,9 +1716,9 @@ Model.create = function create(doc, callback) {
   var Promise = PromiseProvider.get();
   var _this = this;
 
-  var promise = new Promise.ES6(function (resolve, reject) {
+  var promise = new Promise.ES6(function(resolve, reject) {
     if (args.length === 0) {
-      process.nextTick(function () {
+      process.nextTick(function() {
         cb && cb(null);
         resolve(null);
       });
@@ -1726,10 +1726,10 @@ Model.create = function create(doc, callback) {
     }
 
     var toExecute = [];
-    args.forEach(function (doc) {
-      toExecute.push(function (callback) {
+    args.forEach(function(doc) {
+      toExecute.push(function(callback) {
         var toSave = new _this(doc);
-        var callbackWrapper = function (error, doc) {
+        var callbackWrapper = function(error, doc) {
           if (error) {
             return callback(error);
           }
@@ -1746,7 +1746,7 @@ Model.create = function create(doc, callback) {
       });
     });
 
-    async.parallel(toExecute, function (error, savedDocs) {
+    async.parallel(toExecute, function(error, savedDocs) {
       if (error) {
         cb && cb(error);
         reject(error);
@@ -1788,16 +1788,16 @@ Model.create = function create(doc, callback) {
  * @api public
  */
 
-Model.insertMany = function (arr, callback) {
+Model.insertMany = function(arr, callback) {
   var _this = this;
   var Promise = PromiseProvider.get();
 
-  return new Promise.ES6(function (resolve, reject) {
+  return new Promise.ES6(function(resolve, reject) {
     var toExecute = [];
-    arr.forEach(function (doc) {
-      toExecute.push(function (callback) {
+    arr.forEach(function(doc) {
+      toExecute.push(function(callback) {
         doc = new _this(doc);
-        doc.validate({__noPromise: true}, function (error) {
+        doc.validate({__noPromise: true}, function(error) {
           if (error) {
             return callback(error);
           }
@@ -1806,16 +1806,16 @@ Model.insertMany = function (arr, callback) {
       });
     });
 
-    async.parallel(toExecute, function (error, docs) {
+    async.parallel(toExecute, function(error, docs) {
       if (error) {
         reject(error);
         callback && callback(error);
         return;
       }
-      var docObjects = docs.map(function (doc) {
+      var docObjects = docs.map(function(doc) {
         return doc.toObject({virtuals: false});
       });
-      _this.collection.insertMany(docObjects, function (error) {
+      _this.collection.insertMany(docObjects, function(error) {
         if (error) {
           reject(error);
           callback && callback(error);
@@ -1842,7 +1842,7 @@ Model.insertMany = function (arr, callback) {
  * @api public
  */
 
-Model.hydrate = function (obj) {
+Model.hydrate = function(obj) {
   var model = require('./queryhelpers').createModel(this, obj);
   model.init(obj);
   return model;
@@ -2010,7 +2010,7 @@ Model.update = function update(conditions, doc, options, callback) {
 Model.mapReduce = function mapReduce(o, callback) {
   var _this = this;
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve, reject) {
+  return new Promise.ES6(function(resolve, reject) {
     if (!Model.mapReduce.schema) {
       var opts = {noId: true, noVirtualId: true, strict: false};
       Model.mapReduce.schema = new Schema({}, opts);
@@ -2029,7 +2029,7 @@ Model.mapReduce = function mapReduce(o, callback) {
       q = undefined;
     }
 
-    _this.collection.mapReduce(null, null, o, function (err, ret, stats) {
+    _this.collection.mapReduce(null, null, o, function(err, ret, stats) {
       if (err) {
         callback && callback(err);
         reject(err);
@@ -2086,7 +2086,7 @@ Model.mapReduce = function mapReduce(o, callback) {
  * @api public
  */
 
-Model.geoNear = function (near, options, callback) {
+Model.geoNear = function(near, options, callback) {
   if (typeof options === 'function') {
     callback = options;
     options = {};
@@ -2095,7 +2095,7 @@ Model.geoNear = function (near, options, callback) {
   var _this = this;
   var Promise = PromiseProvider.get();
   if (!near) {
-    return new Promise.ES6(function (resolve, reject) {
+    return new Promise.ES6(function(resolve, reject) {
       var error = new Error('Must pass a near option to geoNear');
       reject(error);
       callback && callback(error);
@@ -2104,8 +2104,8 @@ Model.geoNear = function (near, options, callback) {
 
   var x, y;
 
-  return new Promise.ES6(function (resolve, reject) {
-    var handler = function (err, res) {
+  return new Promise.ES6(function(resolve, reject) {
+    var handler = function(err, res) {
       if (err) {
         reject(err);
         callback && callback(err);
@@ -2129,7 +2129,7 @@ Model.geoNear = function (near, options, callback) {
       for (var i = 0; i < res.results.length; i++) {
         var temp = res.results[i].obj;
         res.results[i].obj = new _this();
-        res.results[i].obj.init(temp, function (err) {
+        res.results[i].obj.init(temp, function(err) {
           if (err && !errSeen) {
             errSeen = true;
             reject(err);
@@ -2257,7 +2257,7 @@ Model.aggregate = function aggregate() {
  * @api public
  */
 
-Model.geoSearch = function (conditions, options, callback) {
+Model.geoSearch = function(conditions, options, callback) {
   if (typeof options === 'function') {
     callback = options;
     options = {};
@@ -2265,7 +2265,7 @@ Model.geoSearch = function (conditions, options, callback) {
 
   var _this = this;
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve, reject) {
+  return new Promise.ES6(function(resolve, reject) {
     var error;
     if (conditions === undefined || !utils.isObject(conditions)) {
       error = new Error('Must pass conditions to geoSearch');
@@ -2284,7 +2284,7 @@ Model.geoSearch = function (conditions, options, callback) {
     // send the conditions in the options object
     options.search = conditions;
 
-    _this.collection.geoHaystackSearch(options.near[0], options.near[1], options, function (err, res) {
+    _this.collection.geoHaystackSearch(options.near[0], options.near[1], options, function(err, res) {
       // have to deal with driver problem. Should be fixed in a soon-ish release
       // (7/8/2013)
       if (err) {
@@ -2304,7 +2304,7 @@ Model.geoSearch = function (conditions, options, callback) {
       for (var i = 0; i < res.results.length; i++) {
         var temp = res.results[i];
         res.results[i] = new _this();
-        res.results[i].init(temp, {}, function (err) {
+        res.results[i].init(temp, {}, function(err) {
           if (err && !errSeen) {
             callback && callback(err);
             reject(err);
@@ -2383,7 +2383,7 @@ Model.geoSearch = function (conditions, options, callback) {
  * @api public
  */
 
-Model.populate = function (docs, paths, cb) {
+Model.populate = function(docs, paths, cb) {
   var _this = this;
 
   // normalized paths
@@ -2394,8 +2394,8 @@ Model.populate = function (docs, paths, cb) {
     _populate(this, docs, paths, cb);
   } else {
     var Promise = PromiseProvider.get();
-    return new Promise.ES6(function (resolve, reject) {
-      _populate(_this, docs, paths, function (error, docs) {
+    return new Promise.ES6(function(resolve, reject) {
+      _populate(_this, docs, paths, function(error, docs) {
         if (error) {
           cb && cb(error);
           reject(error);
@@ -2471,7 +2471,7 @@ function subPopulate(docs, options, cb) {
     pop = [pop];
   }
 
-  return function (err) {
+  return function(err) {
     var pending = pop.length;
 
     function next(err) {
@@ -2482,7 +2482,7 @@ function subPopulate(docs, options, cb) {
 
     if (err || !pending) return cb(err);
 
-    pop.forEach(function (subOptions) {
+    pop.forEach(function(subOptions) {
       // path needs parent's path prefixed to it
       if (!subOptions._originalPath) {
         subOptions._originalPath = subOptions.path;
@@ -2529,7 +2529,7 @@ function populate(model, docs, options, cb) {
   var i, len = modelsMap.length,
       mod, match, select, promise, vals = [];
 
-  promise = new Promise(function (err, vals, options, assignmentOpts) {
+  promise = new Promise(function(err, vals, options, assignmentOpts) {
     if (err) return cb(err);
 
     var lean = options.options && options.options.lean,
@@ -2571,7 +2571,7 @@ function populate(model, docs, options, cb) {
       match = {};
     }
 
-    var ids = utils.array.flatten(mod.ids, function (item) {
+    var ids = utils.array.flatten(mod.ids, function(item) {
       // no need to include undefined values in our query
       return undefined !== item;
     });
@@ -2795,7 +2795,7 @@ function assignVals(o) {
     if (utils.getValue(path, docs[i]) == null) {
       continue;
     }
-    utils.setValue(path, rawIds[i], docs[i], function (val) {
+    utils.setValue(path, rawIds[i], docs[i], function(val) {
       return valueFilter(val, options);
     });
   }
@@ -2974,7 +2974,7 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
     // forEach skips over sparse entries in arrays so we
     // can safely use this to our advantage dealing with sorted
     // result sets too.
-    newOrder.forEach(function (doc, i) {
+    newOrder.forEach(function(doc, i) {
       rawIds[i] = doc;
     });
   }
@@ -3059,14 +3059,14 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
  * @param {Model} model
  * @param {Schema} schema
  */
-var applyMethods = function (model, schema) {
+var applyMethods = function(model, schema) {
   for (var i in schema.methods) {
     if (typeof schema.methods[i] === 'function') {
       model.prototype[i] = schema.methods[i];
     } else {
-      (function (_i) {
+      (function(_i) {
         Object.defineProperty(model.prototype, _i, {
-          get: function () {
+          get: function() {
             var h = {};
             for (var k in schema.methods[_i]) {
               h[k] = schema.methods[_i][k].bind(this);
@@ -3085,7 +3085,7 @@ var applyMethods = function (model, schema) {
  * @param {Model} model
  * @param {Schema} schema
  */
-var applyStatics = function (model, schema) {
+var applyStatics = function(model, schema) {
   for (var i in schema.statics) {
     model[i] = schema.statics[i];
   }
diff --git a/lib/promise.js b/lib/promise.js
index 76cc36f1c18..403eaa37b3d 100644
--- a/lib/promise.js
+++ b/lib/promise.js
@@ -38,15 +38,15 @@ function Promise(fn) {
  * @return {Promise} new promise
  * @api public
  */
-Promise.ES6 = function (resolver) {
+Promise.ES6 = function(resolver) {
   var promise = new Promise();
 
   // No try/catch for backwards compatibility
   resolver(
-    function () {
+    function() {
       promise.complete.apply(promise, arguments);
     },
-    function (e) {
+    function(e) {
       promise.error(e);
     });
 
@@ -112,7 +112,7 @@ Promise.FAILURE = 'err';
  * @return {Promise} this
  */
 
-Promise.prototype.error = function (err) {
+Promise.prototype.error = function(err) {
   if (!(err instanceof Error)) {
     if (err instanceof Object) {
       err = util.inspect(err);
@@ -137,7 +137,7 @@ Promise.prototype.error = function (err) {
  * @deprecated
  */
 
-Promise.prototype.resolve = function (err) {
+Promise.prototype.resolve = function(err) {
   if (err) return this.error(err);
   return this.fulfill.apply(this, Array.prototype.slice.call(arguments, 1));
 };
diff --git a/lib/promise_provider.js b/lib/promise_provider.js
index e1db744407a..368cf85ff52 100644
--- a/lib/promise_provider.js
+++ b/lib/promise_provider.js
@@ -19,7 +19,7 @@ var Promise = {
  *
  * @api private
  */
-Promise.get = function () {
+Promise.get = function() {
   return Promise._promise;
 };
 
@@ -29,7 +29,7 @@ Promise.get = function () {
  * @api private
  */
 
-Promise.set = function (lib) {
+Promise.set = function(lib) {
   if (lib === MPromise) {
     return Promise.reset();
   }
@@ -44,7 +44,7 @@ Promise.set = function (lib) {
  * @api private
  */
 
-Promise.reset = function () {
+Promise.reset = function() {
   Promise._promise = MPromise;
 };
 
diff --git a/lib/query.js b/lib/query.js
index ffd4df806aa..e8d39641c7b 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -150,7 +150,7 @@ Query.use$geoWithin = mquery.use$geoWithin;
  */
 
 Query.prototype.toConstructor = function toConstructor() {
-  var CustomQuery = function (criteria, options) {
+  var CustomQuery = function(criteria, options) {
     if (!(this instanceof CustomQuery)) {
       return new CustomQuery(criteria, options);
     }
@@ -861,7 +861,7 @@ Query.prototype.read = function read(pref, tags) {
  * @api public
  */
 
-Query.prototype.setOptions = function (options, overwrite) {
+Query.prototype.setOptions = function(options, overwrite) {
   // overwrite is only for internal use
   if (overwrite) {
     // ensure that _mongooseOptions & options are two different objects
@@ -894,7 +894,7 @@ Query.prototype.setOptions = function (options, overwrite) {
  * @api public
  */
 
-Query.prototype.getQuery = function () {
+Query.prototype.getQuery = function() {
   return this._conditions;
 };
 
@@ -911,7 +911,7 @@ Query.prototype.getQuery = function () {
  * @api public
  */
 
-Query.prototype.getUpdate = function () {
+Query.prototype.getUpdate = function() {
   return this._update;
 };
 
@@ -958,7 +958,7 @@ Query.prototype.getUpdate = function () {
  * @api private
  */
 
-Query.prototype._optionsForExec = function (model) {
+Query.prototype._optionsForExec = function(model) {
   var options = Query.base._optionsForExec.call(this);
 
   delete options.populate;
@@ -1001,7 +1001,7 @@ Query.prototype._optionsForExec = function (model) {
  * @api public
  */
 
-Query.prototype.lean = function (v) {
+Query.prototype.lean = function(v) {
   this._mongooseOptions.lean = arguments.length ? !!v : true;
   return this;
 };
@@ -1013,7 +1013,7 @@ Query.prototype.lean = function (v) {
  * @return {Query} this
  * @api private
  */
-Query.prototype._find = function (callback) {
+Query.prototype._find = function(callback) {
   if (this._castError) {
     callback(this._castError);
     return this;
@@ -1026,7 +1026,7 @@ Query.prototype._find = function (callback) {
   var options = this._mongooseOptions;
   var _this = this;
 
-  var cb = function (err, docs) {
+  var cb = function(err, docs) {
     if (err) {
       return callback(err);
     }
@@ -1043,7 +1043,7 @@ Query.prototype._find = function (callback) {
 
     var pop = helpers.preparePopulationOptionsMQ(_this, options);
     pop.__noPromise = true;
-    _this.model.populate(docs, pop, function (err, docs) {
+    _this.model.populate(docs, pop, function(err, docs) {
       if (err) return callback(err);
       return options.lean === true
           ? callback(null, docs)
@@ -1069,7 +1069,7 @@ Query.prototype._find = function (callback) {
  * @api public
  */
 
-Query.prototype.find = function (conditions, callback) {
+Query.prototype.find = function(conditions, callback) {
   if (typeof conditions === 'function') {
     callback = conditions;
     conditions = {};
@@ -1120,7 +1120,7 @@ function completeMany(model, docs, fields, self, pop, callback) {
       : undefined;
   for (var i = 0; i < len; ++i) {
     arr[i] = helpers.createModel(model, docs[i], fields);
-    arr[i].init(docs[i], opts, function (err) {
+    arr[i].init(docs[i], opts, function(err) {
       if (err) return callback(err);
       --count || callback(null, arr);
     });
@@ -1135,7 +1135,7 @@ function completeMany(model, docs, fields, self, pop, callback) {
  * @api private
  */
 
-Query.prototype._findOne = function (callback) {
+Query.prototype._findOne = function(callback) {
   if (this._castError) {
     return callback(this._castError);
   }
@@ -1148,7 +1148,7 @@ Query.prototype._findOne = function (callback) {
   var _this = this;
 
   // don't pass in the conditions because we already merged them in
-  Query.base.findOne.call(_this, {}, function (err, doc) {
+  Query.base.findOne.call(_this, {}, function(err, doc) {
     if (err) {
       return callback(err);
     }
@@ -1164,7 +1164,7 @@ Query.prototype._findOne = function (callback) {
 
     var pop = helpers.preparePopulationOptionsMQ(_this, options);
     pop.__noPromise = true;
-    _this.model.populate(doc, pop, function (err, doc) {
+    _this.model.populate(doc, pop, function(err, doc) {
       if (err) {
         return callback(err);
       }
@@ -1200,7 +1200,7 @@ Query.prototype._findOne = function (callback) {
  * @api public
  */
 
-Query.prototype.findOne = function (conditions, projection, options, callback) {
+Query.prototype.findOne = function(conditions, projection, options, callback) {
   if (typeof conditions === 'function') {
     callback = conditions;
     conditions = null;
@@ -1259,11 +1259,11 @@ Query.prototype.findOne = function (conditions, projection, options, callback) {
  * @api private
  */
 
-Query.prototype._count = function (callback) {
+Query.prototype._count = function(callback) {
   try {
     this.cast(this.model);
   } catch (err) {
-    process.nextTick(function () {
+    process.nextTick(function() {
       callback(err);
     });
     return this;
@@ -1300,7 +1300,7 @@ Query.prototype._count = function (callback) {
  * @api public
  */
 
-Query.prototype.count = function (conditions, callback) {
+Query.prototype.count = function(conditions, callback) {
   if (typeof conditions === 'function') {
     callback = conditions;
     conditions = undefined;
@@ -1342,7 +1342,7 @@ Query.prototype.count = function (conditions, callback) {
  * @api public
  */
 
-Query.prototype.distinct = function (field, conditions, callback) {
+Query.prototype.distinct = function(field, conditions, callback) {
   if (!callback) {
     if (typeof conditions === 'function') {
       callback = conditions;
@@ -1400,7 +1400,7 @@ Query.prototype.distinct = function (field, conditions, callback) {
  * @api public
  */
 
-Query.prototype.sort = function (arg) {
+Query.prototype.sort = function(arg) {
   var nArg = {};
 
   if (arguments.length > 1) {
@@ -1459,7 +1459,7 @@ Query.prototype.sort = function (arg) {
  * @api public
  */
 
-Query.prototype.remove = function (cond, callback) {
+Query.prototype.remove = function(cond, callback) {
   if (typeof cond === 'function') {
     callback = cond;
     cond = null;
@@ -1495,7 +1495,7 @@ function completeOne(model, doc, res, fields, self, pop, callback) {
       : undefined;
 
   var casted = helpers.createModel(model, doc, fields);
-  casted.init(doc, opts, function (err) {
+  casted.init(doc, opts, function(err) {
     if (err) {
       return callback(err);
     }
@@ -1562,7 +1562,7 @@ function prepareDiscriminatorCriteria(query) {
  * @api public
  */
 
-Query.prototype.findOneAndUpdate = function (criteria, doc, options, callback) {
+Query.prototype.findOneAndUpdate = function(criteria, doc, options, callback) {
   this.op = 'findOneAndUpdate';
   this._validate();
 
@@ -1616,7 +1616,7 @@ Query.prototype.findOneAndUpdate = function (criteria, doc, options, callback) {
  * @api private
  */
 
-Query.prototype._findOneAndUpdate = function (callback) {
+Query.prototype._findOneAndUpdate = function(callback) {
   this._findAndModify('update', callback);
   return this;
 };
@@ -1657,7 +1657,7 @@ Query.prototype._findOneAndUpdate = function (callback) {
  * @api public
  */
 
-Query.prototype.findOneAndRemove = function (conditions, options, callback) {
+Query.prototype.findOneAndRemove = function(conditions, options, callback) {
   this.op = 'findOneAndRemove';
   this._validate();
 
@@ -1699,7 +1699,7 @@ Query.prototype.findOneAndRemove = function (conditions, options, callback) {
  * @return {Query} this
  * @api private
  */
-Query.prototype._findOneAndRemove = function (callback) {
+Query.prototype._findOneAndRemove = function(callback) {
   Query.base.findOneAndRemove.call(this, callback);
 };
 
@@ -1711,7 +1711,7 @@ Query.prototype._findOneAndRemove = function (callback) {
  * @api private
  */
 
-Query.prototype._findAndModify = function (type, callback) {
+Query.prototype._findAndModify = function(type, callback) {
   if (typeof callback !== 'function') {
     throw new Error('Expected callback in _findAndModify');
   }
@@ -1787,7 +1787,7 @@ Query.prototype._findAndModify = function (type, callback) {
 
   if (opts.sort) convertSortToArray(opts);
 
-  var cb = function (err, doc, res) {
+  var cb = function(err, doc, res) {
     if (err) {
       return callback(err);
     }
@@ -1808,7 +1808,7 @@ Query.prototype._findAndModify = function (type, callback) {
 
     var pop = helpers.preparePopulationOptionsMQ(_this, options);
     pop.__noPromise = true;
-    _this.model.populate(doc, pop, function (err, doc) {
+    _this.model.populate(doc, pop, function(err, doc) {
       if (err) {
         return callback(err);
       }
@@ -1820,16 +1820,16 @@ Query.prototype._findAndModify = function (type, callback) {
   };
 
   if ((opts.runValidators || opts.setDefaultsOnInsert) && doValidate) {
-    doValidate(function (error) {
+    doValidate(function(error) {
       if (error) {
         return callback(error);
       }
-      _this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function (error, res) {
+      _this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) {
         return cb(error, res ? res.value : res, res);
       }));
     });
   } else {
-    this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function (error, res) {
+    this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) {
       return cb(error, res ? res.value : res, res);
     }));
   }
@@ -1845,7 +1845,7 @@ Query.prototype._findAndModify = function (type, callback) {
  * @api private
  */
 
-Query.prototype._mergeUpdate = function (doc) {
+Query.prototype._mergeUpdate = function(doc) {
   if (!this._update) this._update = {};
   if (doc instanceof Query) {
     if (doc._update) {
@@ -1887,7 +1887,7 @@ function convertSortToArray(opts) {
  * @see Model.update #model_Model.update
  * @api private
  */
-Query.prototype._execUpdate = function (callback) {
+Query.prototype._execUpdate = function(callback) {
   var schema = this.model.schema;
   var doValidate;
   var _this;
@@ -1904,7 +1904,7 @@ Query.prototype._execUpdate = function (callback) {
   if (this.options.runValidators || this.options.setDefaultsOnInsert) {
     _this = this;
     doValidate = updateValidators(this, schema, castedDoc, options);
-    doValidate(function (err) {
+    doValidate(function(err) {
       if (err) {
         return callback(err);
       }
@@ -1993,7 +1993,7 @@ Query.prototype._execUpdate = function (callback) {
  * @api public
  */
 
-Query.prototype.update = function (conditions, doc, options, callback) {
+Query.prototype.update = function(conditions, doc, options, callback) {
   if (typeof options === 'function') {
     // .update(conditions, doc, callback)
     callback = options;
@@ -2024,7 +2024,7 @@ Query.prototype.update = function (conditions, doc, options, callback) {
   var oldCb = callback;
   if (oldCb) {
     if (typeof oldCb === 'function') {
-      callback = function (error, result) {
+      callback = function(error, result) {
         oldCb(error, result ? result.result : {ok: 0, n: 0, nModified: 0});
       };
     } else {
@@ -2132,14 +2132,14 @@ Query.prototype.exec = function exec(op, callback) {
     this.op = op;
   }
 
-  return new Promise.ES6(function (resolve, reject) {
+  return new Promise.ES6(function(resolve, reject) {
     if (!_this.op) {
       callback && callback(null, undefined);
       resolve();
       return;
     }
 
-    _this[_this.op].call(_this, function (error, res) {
+    _this[_this.op].call(_this, function(error, res) {
       if (error) {
         callback && callback(error);
         reject(error);
@@ -2161,7 +2161,7 @@ Query.prototype.exec = function exec(op, callback) {
  * @api public
  */
 
-Query.prototype.then = function (resolve, reject) {
+Query.prototype.then = function(resolve, reject) {
   return this.exec().then(resolve, reject);
 };
 
@@ -2507,7 +2507,7 @@ function castDoc(query, overwrite) {
  * @api public
  */
 
-Query.prototype.populate = function () {
+Query.prototype.populate = function() {
   var res = utils.populate.apply(null, arguments);
   var opts = this._mongooseOptions;
 
@@ -2535,7 +2535,7 @@ Query.prototype.populate = function () {
  * @api public
  */
 
-Query.prototype.cast = function (model, obj) {
+Query.prototype.cast = function(model, obj) {
   obj || (obj = this._conditions);
 
   return cast(model.schema, obj);
@@ -2626,7 +2626,7 @@ Query.prototype._applyPaths = function applyPaths() {
       excluded = [],
       seen = [];
 
-  var analyzePath = function (path, type) {
+  var analyzePath = function(path, type) {
     if (typeof type.selected !== 'boolean') return;
 
     var plusPath = '+' + path;
@@ -2650,14 +2650,14 @@ Query.prototype._applyPaths = function applyPaths() {
     (type.selected ? selected : excluded).push(path);
   };
 
-  var analyzeSchema = function (schema, prefix) {
+  var analyzeSchema = function(schema, prefix) {
     prefix || (prefix = '');
 
     // avoid recursion
     if (~seen.indexOf(schema)) return;
     seen.push(schema);
 
-    schema.eachPath(function (path, type) {
+    schema.eachPath(function(path, type) {
       if (prefix) path = prefix + '.' + path;
 
       analyzePath(path, type);
@@ -2763,7 +2763,7 @@ Query.prototype.maxscan = Query.base.maxScan;
  * @api public
  */
 
-Query.prototype.tailable = function (val, opts) {
+Query.prototype.tailable = function(val, opts) {
   // we need to support the tailable({ awaitdata : true }) as well as the
   // tailable(true, {awaitdata :true}) syntax that mquery does not support
   if (val && val.constructor.name === 'Object') {
@@ -2894,7 +2894,7 @@ Query.prototype.tailable = function (val, opts) {
  * In addition to all of the normal forms supported by mquery
  */
 
-Query.prototype.near = function () {
+Query.prototype.near = function() {
   var params = [];
   var sphere = this._mongooseOptions.nearSphere;
 
@@ -2964,7 +2964,7 @@ Query.prototype.near = function () {
  * @see $maxDistance http://docs.mongodb.org/manual/reference/operator/maxDistance/
  */
 
-Query.prototype.nearSphere = function () {
+Query.prototype.nearSphere = function() {
   this._mongooseOptions.nearSphere = true;
   this.near.apply(this, arguments);
   return this;
@@ -3016,7 +3016,7 @@ Query.prototype.nearSphere = function () {
  * box({ ll : [x,y], ur : [x2,y2] })
  */
 
-Query.prototype.box = function (ll, ur) {
+Query.prototype.box = function(ll, ur) {
   if (!Array.isArray(ll) && utils.isObject(ll)) {
     ur = ll.ur;
     ll = ll.ll;
@@ -3086,7 +3086,7 @@ Query.prototype.center = Query.base.circle;
  * @api public
  */
 
-Query.prototype.centerSphere = function () {
+Query.prototype.centerSphere = function() {
   if (arguments[0] && arguments[0].constructor.name === 'Object') {
     arguments[0].spherical = true;
   }
diff --git a/lib/querystream.js b/lib/querystream.js
index c7220d35705..f62294ad9fa 100644
--- a/lib/querystream.js
+++ b/lib/querystream.js
@@ -7,7 +7,7 @@
 var Stream = require('stream').Stream;
 var utils = require('./utils');
 var helpers = require('./queryhelpers');
-var K = function (k) {
+var K = function(k) {
   return k;
 };
 
@@ -70,7 +70,7 @@ function QueryStream(query, options) {
 
   // give time to hook up events
   var _this = this;
-  process.nextTick(function () {
+  process.nextTick(function() {
     _this._init();
   });
 }
@@ -110,7 +110,7 @@ var T_CONT = 2;
  * @api private
  */
 
-QueryStream.prototype._init = function () {
+QueryStream.prototype._init = function() {
   if (this._destroyed) {
     return;
   }
@@ -129,7 +129,7 @@ QueryStream.prototype._init = function () {
   _this._fields = utils.clone(query._fields);
   options.fields = query._castFields(_this._fields);
 
-  model.collection.find(query._conditions, options, function (err, cursor) {
+  model.collection.find(query._conditions, options, function(err, cursor) {
     if (err) {
       return _this.destroy(err);
     }
@@ -173,7 +173,7 @@ QueryStream.prototype._next = function _next() {
  * @api private
  */
 
-QueryStream.prototype.__next = function () {
+QueryStream.prototype.__next = function() {
   if (this.paused || this._destroyed) {
     this._running = false;
     return this._running;
@@ -239,12 +239,12 @@ QueryStream.prototype._onNextObject = function _onNextObject(err, doc) {
   var pop = helpers.preparePopulationOptionsMQ(_this.query, _this.query._mongooseOptions);
 
   // Hack to work around gh-3108
-  pop.forEach(function (option) {
+  pop.forEach(function(option) {
     delete option.model;
   });
 
   pop.__noPromise = true;
-  _this.query.model.populate(doc, pop, function (err, doc) {
+  _this.query.model.populate(doc, pop, function(err, doc) {
     if (err) {
       return _this.destroy(err);
     }
@@ -260,7 +260,7 @@ function createAndEmit(self, populatedIds, doc) {
   {populated: populatedIds} :
       undefined;
 
-  instance.init(doc, opts, function (err) {
+  instance.init(doc, opts, function(err) {
     if (err) {
       return self.destroy(err);
     }
@@ -292,7 +292,7 @@ function emit(self, doc) {
  * @api public
  */
 
-QueryStream.prototype.pause = function () {
+QueryStream.prototype.pause = function() {
   this.paused = true;
 };
 
@@ -302,7 +302,7 @@ QueryStream.prototype.pause = function () {
  * @api public
  */
 
-QueryStream.prototype.resume = function () {
+QueryStream.prototype.resume = function() {
   this.paused = false;
 
   if (!this._cursor) {
@@ -328,7 +328,7 @@ QueryStream.prototype.resume = function () {
  * @api public
  */
 
-QueryStream.prototype.destroy = function (err) {
+QueryStream.prototype.destroy = function(err) {
   if (this._destroyed) {
     return;
   }
diff --git a/lib/schema.js b/lib/schema.js
index 60ff6f599cc..80d6793e326 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -133,7 +133,7 @@ function Schema(obj, options) {
 
     this.add(schemaAdditions);
 
-    this.pre('save', function (next) {
+    this.pre('save', function(next) {
       var defaultTimestamp = new Date();
 
       if (!this[createdAt]) {
@@ -145,7 +145,7 @@ function Schema(obj, options) {
       next();
     });
 
-    var genUpdates = function () {
+    var genUpdates = function() {
       var now = new Date();
       var updates = {$set: {}, $setOnInsert: {}};
       updates.$set[updatedAt] = now;
@@ -154,12 +154,12 @@ function Schema(obj, options) {
       return updates;
     };
 
-    this.pre('findOneAndUpdate', function (next) {
+    this.pre('findOneAndUpdate', function(next) {
       this.findOneAndUpdate({}, genUpdates());
       next();
     });
 
-    this.pre('update', function (next) {
+    this.pre('update', function(next) {
       this.update({}, genUpdates());
       next();
     });
@@ -205,7 +205,7 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
   value: [{
     kind: 'pre',
     hook: 'save',
-    fn: function (next, options) {
+    fn: function(next, options) {
       // Nested docs have their own presave
       if (this.ownerDocument) {
         return next();
@@ -227,11 +227,11 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
         // HACK: use $__original_validate to avoid promises so bluebird doesn't
         // complain
         if (this.$__original_validate) {
-          this.$__original_validate({__noPromise: true}, function (error) {
+          this.$__original_validate({__noPromise: true}, function(error) {
             next(error);
           });
         } else {
-          this.validate({__noPromise: true}, function (error) {
+          this.validate({__noPromise: true}, function(error) {
             next(error);
           });
         }
@@ -243,7 +243,7 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
     kind: 'pre',
     hook: 'save',
     isAsync: true,
-    fn: function (next, done) {
+    fn: function(next, done) {
       var subdocs = this.$__getAllSubdocs();
 
       if (!subdocs.length || this.$__preSavingFromParent) {
@@ -252,12 +252,12 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
         return;
       }
 
-      async.each(subdocs, function (subdoc, cb) {
+      async.each(subdocs, function(subdoc, cb) {
         subdoc.$__preSavingFromParent = true;
-        subdoc.save(function (err) {
+        subdoc.save(function(err) {
           cb(err);
         });
-      }, function (error) {
+      }, function(error) {
         for (var i = 0; i < subdocs.length; ++i) {
           delete subdocs[i].$__preSavingFromParent;
         }
@@ -312,7 +312,7 @@ Schema.prototype.tree;
  * @api private
  */
 
-Schema.prototype.defaultOptions = function (options) {
+Schema.prototype.defaultOptions = function(options) {
   if (options && options.safe === false) {
     options.safe = {w: 0};
   }
@@ -454,7 +454,7 @@ warnings.increment = '`increment` should not be used as a schema path name ' +
  * @api public
  */
 
-Schema.prototype.path = function (path, obj) {
+Schema.prototype.path = function(path, obj) {
   if (obj === undefined) {
     if (this.paths[path]) {
       return this.paths[path];
@@ -486,7 +486,7 @@ Schema.prototype.path = function (path, obj) {
       last = subpaths.pop(),
       branch = this.tree;
 
-  subpaths.forEach(function (sub, i) {
+  subpaths.forEach(function(sub, i) {
     if (!branch[sub]) {
       branch[sub] = {};
     }
@@ -525,7 +525,7 @@ Schema.prototype.path = function (path, obj) {
  * @api private
  */
 
-Schema.interpretAsType = function (path, obj, options) {
+Schema.interpretAsType = function(path, obj, options) {
   if (obj.constructor) {
     var constructorName = utils.getFunctionName(obj.constructor);
     if (constructorName !== 'Object') {
@@ -613,7 +613,7 @@ Schema.interpretAsType = function (path, obj, options) {
  * @api public
  */
 
-Schema.prototype.eachPath = function (fn) {
+Schema.prototype.eachPath = function(fn) {
   var keys = Object.keys(this.paths),
       len = keys.length;
 
@@ -676,7 +676,7 @@ Schema.prototype.indexedPaths = function indexedPaths() {
  * @api public
  */
 
-Schema.prototype.pathType = function (path) {
+Schema.prototype.pathType = function(path) {
   if (path in this.paths) {
     return 'real';
   }
@@ -707,7 +707,7 @@ Schema.prototype.pathType = function (path) {
  * @api private
  */
 
-Schema.prototype.hasMixedParent = function (path) {
+Schema.prototype.hasMixedParent = function(path) {
   var subpaths = path.split(/\./g);
   path = '';
   for (var i = 0; i < subpaths.length; ++i) {
@@ -798,7 +798,7 @@ function getPositionalPath(self, path) {
  * @api public
  */
 
-Schema.prototype.queue = function (name, args) {
+Schema.prototype.queue = function(name, args) {
   this.callQueue.push([name, args]);
   return this;
 };
@@ -826,7 +826,7 @@ Schema.prototype.queue = function (name, args) {
  * @api public
  */
 
-Schema.prototype.pre = function () {
+Schema.prototype.pre = function() {
   var name = arguments[0];
   if (IS_QUERY_HOOK[name]) {
     this.s.hooks.pre.apply(this.s.hooks, arguments);
@@ -858,24 +858,24 @@ Schema.prototype.pre = function () {
  * @api public
  */
 
-Schema.prototype.post = function (method, fn) {
+Schema.prototype.post = function(method, fn) {
   if (IS_QUERY_HOOK[method]) {
     this.s.hooks.post.apply(this.s.hooks, arguments);
     return this;
   }
   // assuming that all callbacks with arity < 2 are synchronous post hooks
   if (fn.length < 2) {
-    return this.queue('on', [arguments[0], function (doc) {
+    return this.queue('on', [arguments[0], function(doc) {
       return fn.call(doc, doc);
     }]);
   }
 
-  return this.queue('post', [arguments[0], function (next) {
+  return this.queue('post', [arguments[0], function(next) {
     // wrap original function so that the callback goes last,
     // for compatibility with old code that is using synchronous post hooks
     var _this = this;
     var args = Array.prototype.slice.call(arguments, 1);
-    fn.call(this, this, function (err) {
+    fn.call(this, this, function(err) {
       return next.apply(_this, [err].concat(args));
     });
   }]);
@@ -890,7 +890,7 @@ Schema.prototype.post = function (method, fn) {
  * @api public
  */
 
-Schema.prototype.plugin = function (fn, opts) {
+Schema.prototype.plugin = function(fn, opts) {
   fn(this, opts);
   return this;
 };
@@ -927,7 +927,7 @@ Schema.prototype.plugin = function (fn, opts) {
  * @api public
  */
 
-Schema.prototype.method = function (name, fn) {
+Schema.prototype.method = function(name, fn) {
   if (typeof name !== 'string') {
     for (var i in name) {
       this.methods[i] = name[i];
@@ -960,7 +960,7 @@ Schema.prototype.method = function (name, fn) {
  * @api public
  */
 
-Schema.prototype.static = function (name, fn) {
+Schema.prototype.static = function(name, fn) {
   if (typeof name !== 'string') {
     for (var i in name) {
       this.statics[i] = name[i];
@@ -984,7 +984,7 @@ Schema.prototype.static = function (name, fn) {
  * @api public
  */
 
-Schema.prototype.index = function (fields, options) {
+Schema.prototype.index = function(fields, options) {
   options || (options = {});
 
   if (options.expires) {
@@ -1010,7 +1010,7 @@ Schema.prototype.index = function (fields, options) {
  * @api public
  */
 
-Schema.prototype.set = function (key, value, _tags) {
+Schema.prototype.set = function(key, value, _tags) {
   if (arguments.length === 1) {
     return this.options[key];
   }
@@ -1038,7 +1038,7 @@ Schema.prototype.set = function (key, value, _tags) {
  * @api public
  */
 
-Schema.prototype.get = function (key) {
+Schema.prototype.get = function(key) {
   return this.options[key];
 };
 
@@ -1053,10 +1053,10 @@ Schema.prototype.get = function (key) {
 var indexTypes = '2d 2dsphere hashed text'.split(' ');
 
 Object.defineProperty(Schema, 'indexTypes', {
-  get: function () {
+  get: function() {
     return indexTypes;
   },
-  set: function () {
+  set: function() {
     throw new Error('Cannot overwrite Schema.indexTypes');
   }
 });
@@ -1067,13 +1067,13 @@ Object.defineProperty(Schema, 'indexTypes', {
  * @api public
  */
 
-Schema.prototype.indexes = function () {
+Schema.prototype.indexes = function() {
   'use strict';
 
   var indexes = [];
   var seenPrefix = {};
 
-  var collectIndexes = function (schema, prefix) {
+  var collectIndexes = function(schema, prefix) {
     if (seenPrefix[prefix]) {
       return;
     }
@@ -1119,7 +1119,7 @@ Schema.prototype.indexes = function () {
     if (prefix) {
       fixSubIndexPaths(schema, prefix);
     } else {
-      schema._indexes.forEach(function (index) {
+      schema._indexes.forEach(function(index) {
         if (!('background' in index[1])) {
           index[1].background = true;
         }
@@ -1174,10 +1174,10 @@ Schema.prototype.indexes = function () {
  * @return {VirtualType}
  */
 
-Schema.prototype.virtual = function (name, options) {
+Schema.prototype.virtual = function(name, options) {
   var virtuals = this.virtuals;
   var parts = name.split('.');
-  virtuals[name] = parts.reduce(function (mem, part, i) {
+  virtuals[name] = parts.reduce(function(mem, part, i) {
     mem[part] || (mem[part] = (i === parts.length - 1)
         ? new VirtualType(options, name)
         : {});
@@ -1193,7 +1193,7 @@ Schema.prototype.virtual = function (name, options) {
  * @return {VirtualType}
  */
 
-Schema.prototype.virtualpath = function (name) {
+Schema.prototype.virtualpath = function(name) {
   return this.virtuals[name];
 };
 
@@ -1204,12 +1204,12 @@ Schema.prototype.virtualpath = function (name) {
  *
  * @api public
  */
-Schema.prototype.remove = function (path) {
+Schema.prototype.remove = function(path) {
   if (typeof path === 'string') {
     path = [path];
   }
   if (Array.isArray(path)) {
-    path.forEach(function (name) {
+    path.forEach(function(name) {
       if (this.path(name)) {
         delete this.paths[name];
       }
@@ -1221,7 +1221,7 @@ Schema.prototype.remove = function (path) {
  * ignore
  */
 
-Schema.prototype._getSchema = function (path) {
+Schema.prototype._getSchema = function(path) {
   var _this = this;
   var pathschema = _this.path(path);
 
diff --git a/lib/schema/array.js b/lib/schema/array.js
index 99a043ba39e..7fec9e86077 100644
--- a/lib/schema/array.js
+++ b/lib/schema/array.js
@@ -71,7 +71,7 @@ function SchemaArray(key, cast, options) {
     fn = typeof defaultArr === 'function';
   }
 
-  this.default(function () {
+  this.default(function() {
     var arr = fn ? defaultArr() : defaultArr || [];
     return new MongooseArray(arr, _this.path, this);
   });
@@ -98,7 +98,7 @@ SchemaArray.prototype.constructor = SchemaArray;
  * @api private
  */
 
-SchemaArray.prototype.checkRequired = function (value) {
+SchemaArray.prototype.checkRequired = function(value) {
   return !!(value && value.length);
 };
 
@@ -110,7 +110,7 @@ SchemaArray.prototype.checkRequired = function (value) {
  * @api private
  */
 
-SchemaArray.prototype.applyGetters = function (value, scope) {
+SchemaArray.prototype.applyGetters = function(value, scope) {
   if (this.caster.options && this.caster.options.ref) {
     // means the object id was populated
     return value;
@@ -128,7 +128,7 @@ SchemaArray.prototype.applyGetters = function (value, scope) {
  * @api private
  */
 
-SchemaArray.prototype.cast = function (value, doc, init) {
+SchemaArray.prototype.cast = function(value, doc, init) {
   if (Array.isArray(value)) {
     if (!value.length && doc) {
       var indexes = doc.schema.indexedPaths();
@@ -174,7 +174,7 @@ SchemaArray.prototype.cast = function (value, doc, init) {
  * @api private
  */
 
-SchemaArray.prototype.castForQuery = function ($conditional, value) {
+SchemaArray.prototype.castForQuery = function($conditional, value) {
   var handler,
       val;
 
@@ -182,7 +182,7 @@ SchemaArray.prototype.castForQuery = function ($conditional, value) {
     handler = this.$conditionalHandlers[$conditional];
 
     if (!handler) {
-      throw new Error("Can't use " + $conditional + ' with Array.');
+      throw new Error('Can\'t use ' + $conditional + ' with Array.');
     }
 
     val = handler.call(this, value);
@@ -193,7 +193,7 @@ SchemaArray.prototype.castForQuery = function ($conditional, value) {
     var caster = this.caster;
 
     if (Array.isArray(val)) {
-      val = val.map(function (v) {
+      val = val.map(function(v) {
         if (utils.isObject(v) && v.$elemMatch) {
           return v;
         }
@@ -225,7 +225,7 @@ function castToNumber(val) {
 }
 
 function castArraysOfNumbers(arr, self) {
-  arr.forEach(function (v, i) {
+  arr.forEach(function(v, i) {
     if (Array.isArray(v)) {
       castArraysOfNumbers(v, self);
     } else {
@@ -275,21 +275,21 @@ function cast$within(val) {
 
   if (val.$box || val.$polygon) {
     var type = val.$box ? '$box' : '$polygon';
-    val[type].forEach(function (arr) {
+    val[type].forEach(function(arr) {
       if (!Array.isArray(arr)) {
         var msg = 'Invalid $within $box argument. '
             + 'Expected an array, received ' + arr;
         throw new TypeError(msg);
       }
-      arr.forEach(function (v, i) {
+      arr.forEach(function(v, i) {
         arr[i] = castToNumber.call(this, v);
       });
     });
   } else if (val.$center || val.$centerSphere) {
     type = val.$center ? '$center' : '$centerSphere';
-    val[type].forEach(function (item, i) {
+    val[type].forEach(function(item, i) {
       if (Array.isArray(item)) {
-        item.forEach(function (v, j) {
+        item.forEach(function(v, j) {
           item[j] = castToNumber.call(this, v);
         });
       } else {
@@ -308,7 +308,7 @@ function cast$all(val) {
     val = [val];
   }
 
-  val = val.map(function (v) {
+  val = val.map(function(v) {
     if (utils.isObject(v)) {
       var o = {};
       o[this.path] = v;
@@ -352,7 +352,7 @@ handle.$all = cast$all;
 handle.$options = String;
 handle.$elemMatch = cast$elemMatch;
 handle.$geoIntersects = cast$geoIntersects;
-handle.$or = handle.$and = function (val) {
+handle.$or = handle.$and = function(val) {
   if (!Array.isArray(val)) {
     throw new TypeError('conditional $or/$and require array');
   }
diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js
index fae2382da77..6ca03ec5196 100644
--- a/lib/schema/boolean.js
+++ b/lib/schema/boolean.js
@@ -39,7 +39,7 @@ SchemaBoolean.prototype.constructor = SchemaBoolean;
  * @api private
  */
 
-SchemaBoolean.prototype.checkRequired = function (value) {
+SchemaBoolean.prototype.checkRequired = function(value) {
   return value === true || value === false;
 };
 
@@ -50,7 +50,7 @@ SchemaBoolean.prototype.checkRequired = function (value) {
  * @api private
  */
 
-SchemaBoolean.prototype.cast = function (value) {
+SchemaBoolean.prototype.cast = function(value) {
   if (value === null) {
     return value;
   }
@@ -77,7 +77,7 @@ SchemaBoolean.$conditionalHandlers =
  * @api private
  */
 
-SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
+SchemaBoolean.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = SchemaBoolean.$conditionalHandlers[$conditional];
diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js
index e976c5bb7e4..2114b7331c3 100644
--- a/lib/schema/buffer.js
+++ b/lib/schema/buffer.js
@@ -45,7 +45,7 @@ SchemaBuffer.prototype.constructor = SchemaBuffer;
  * @api private
  */
 
-SchemaBuffer.prototype.checkRequired = function (value, doc) {
+SchemaBuffer.prototype.checkRequired = function(value, doc) {
   if (SchemaType._isRef(this, value, doc, true)) {
     return !!value;
   }
@@ -61,7 +61,7 @@ SchemaBuffer.prototype.checkRequired = function (value, doc) {
  * @api private
  */
 
-SchemaBuffer.prototype.cast = function (value, doc, init) {
+SchemaBuffer.prototype.cast = function(value, doc, init) {
   var ret;
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
@@ -163,12 +163,12 @@ SchemaBuffer.prototype.$conditionalHandlers =
  * @api private
  */
 
-SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
+SchemaBuffer.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = this.$conditionalHandlers[$conditional];
     if (!handler) {
-      throw new Error("Can't use " + $conditional + ' with Buffer.');
+      throw new Error('Can\'t use ' + $conditional + ' with Buffer.');
     }
     return handler.call(this, val);
   }
diff --git a/lib/schema/date.js b/lib/schema/date.js
index 09fcb5b95d3..eebdd93ae8d 100644
--- a/lib/schema/date.js
+++ b/lib/schema/date.js
@@ -67,7 +67,7 @@ SchemaDate.prototype.constructor = SchemaDate;
  * @api public
  */
 
-SchemaDate.prototype.expires = function (when) {
+SchemaDate.prototype.expires = function(when) {
   if (!this._index || this._index.constructor.name !== 'Object') {
     this._index = {};
   }
@@ -83,7 +83,7 @@ SchemaDate.prototype.expires = function (when) {
  * @api private
  */
 
-SchemaDate.prototype.checkRequired = function (value) {
+SchemaDate.prototype.checkRequired = function(value) {
   return value instanceof Date;
 };
 
@@ -118,9 +118,9 @@ SchemaDate.prototype.checkRequired = function (value) {
  * @api public
  */
 
-SchemaDate.prototype.min = function (value, message) {
+SchemaDate.prototype.min = function(value, message) {
   if (this.minValidator) {
-    this.validators = this.validators.filter(function (v) {
+    this.validators = this.validators.filter(function(v) {
       return v.validator !== this.minValidator;
     }, this);
   }
@@ -130,7 +130,7 @@ SchemaDate.prototype.min = function (value, message) {
     msg = msg.replace(/{MIN}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
     var _this = this;
     this.validators.push({
-      validator: this.minValidator = function (val) {
+      validator: this.minValidator = function(val) {
         var min = (value === Date.now ? value() : _this.cast(value));
         return val === null || val.valueOf() >= min.valueOf();
       },
@@ -174,9 +174,9 @@ SchemaDate.prototype.min = function (value, message) {
  * @api public
  */
 
-SchemaDate.prototype.max = function (value, message) {
+SchemaDate.prototype.max = function(value, message) {
   if (this.maxValidator) {
-    this.validators = this.validators.filter(function (v) {
+    this.validators = this.validators.filter(function(v) {
       return v.validator !== this.maxValidator;
     }, this);
   }
@@ -186,7 +186,7 @@ SchemaDate.prototype.max = function (value, message) {
     msg = msg.replace(/{MAX}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
     var _this = this;
     this.validators.push({
-      validator: this.maxValidator = function (val) {
+      validator: this.maxValidator = function(val) {
         var max = (value === Date.now ? value() : _this.cast(value));
         return val === null || val.valueOf() <= max.valueOf();
       },
@@ -206,7 +206,7 @@ SchemaDate.prototype.max = function (value, message) {
  * @api private
  */
 
-SchemaDate.prototype.cast = function (value) {
+SchemaDate.prototype.cast = function(value) {
   // If null or undefined
   if (value === null || value === void 0 || value === '') {
     return null;
@@ -261,7 +261,7 @@ SchemaDate.prototype.$conditionalHandlers =
  * @api private
  */
 
-SchemaDate.prototype.castForQuery = function ($conditional, val) {
+SchemaDate.prototype.castForQuery = function($conditional, val) {
   var handler;
 
   if (arguments.length !== 2) {
@@ -271,7 +271,7 @@ SchemaDate.prototype.castForQuery = function ($conditional, val) {
   handler = this.$conditionalHandlers[$conditional];
 
   if (!handler) {
-    throw new Error("Can't use " + $conditional + ' with Date.');
+    throw new Error('Can\'t use ' + $conditional + ' with Date.');
   }
 
   return handler.call(this, val);
diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js
index 2d46993e032..40b44e3565b 100644
--- a/lib/schema/documentarray.js
+++ b/lib/schema/documentarray.js
@@ -48,7 +48,7 @@ function DocumentArray(key, schema, options) {
   var path = this.path;
   var fn = this.defaultValue;
 
-  this.default(function () {
+  this.default(function() {
     var arr = fn.call(this);
     if (!Array.isArray(arr)) {
       arr = [arr];
@@ -77,8 +77,8 @@ DocumentArray.prototype.constructor = DocumentArray;
  * @api private
  */
 
-DocumentArray.prototype.doValidate = function (array, fn, scope, options) {
-  SchemaType.prototype.doValidate.call(this, array, function (err) {
+DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
+  SchemaType.prototype.doValidate.call(this, array, function(err) {
     if (err) {
       return fn(err);
     }
@@ -108,14 +108,14 @@ DocumentArray.prototype.doValidate = function (array, fn, scope, options) {
       // HACK: use $__original_validate to avoid promises so bluebird doesn't
       // complain
       if (doc.$__original_validate) {
-        doc.$__original_validate({__noPromise: true}, function (err) {
+        doc.$__original_validate({__noPromise: true}, function(err) {
           if (err) {
             error = err;
           }
           --count || fn(error);
         });
       } else {
-        doc.validate({__noPromise: true}, function (err) {
+        doc.validate({__noPromise: true}, function(err) {
           if (err) {
             error = err;
           }
@@ -137,7 +137,7 @@ DocumentArray.prototype.doValidate = function (array, fn, scope, options) {
  * @api private
  */
 
-DocumentArray.prototype.doValidateSync = function (array, scope) {
+DocumentArray.prototype.doValidateSync = function(array, scope) {
   var schemaTypeError = SchemaType.prototype.doValidateSync.call(this, array, scope);
   if (schemaTypeError) {
     return schemaTypeError;
@@ -183,7 +183,7 @@ DocumentArray.prototype.doValidateSync = function (array, scope) {
  * @api private
  */
 
-DocumentArray.prototype.cast = function (value, doc, init, prev, options) {
+DocumentArray.prototype.cast = function(value, doc, init, prev, options) {
   var selected,
       subdoc,
       i;
diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js
index 505860597ed..f0444f5eb28 100644
--- a/lib/schema/embedded.js
+++ b/lib/schema/embedded.js
@@ -14,12 +14,12 @@ module.exports = Embedded;
  */
 
 function Embedded(schema, path, options) {
-  var _embedded = function (value, path, parent) {
+  var _embedded = function(value, path, parent) {
     var _this = this;
     Subdocument.apply(this, arguments);
     this.$parent = parent;
     if (parent) {
-      parent.on('save', function () {
+      parent.on('save', function() {
         _this.emit('save', _this);
       });
     }
@@ -55,7 +55,7 @@ Embedded.prototype = Object.create(SchemaType.prototype);
  * @api private
  */
 
-Embedded.prototype.cast = function (val, doc, init) {
+Embedded.prototype.cast = function(val, doc, init) {
   if (val && val.$isSingleNested) {
     return val;
   }
@@ -76,7 +76,7 @@ Embedded.prototype.cast = function (val, doc, init) {
  * @api private
  */
 
-Embedded.prototype.castForQuery = function ($conditional, val) {
+Embedded.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = this.$conditionalHandlers[$conditional];
@@ -95,8 +95,8 @@ Embedded.prototype.castForQuery = function ($conditional, val) {
  * @api private
  */
 
-Embedded.prototype.doValidate = function (value, fn) {
-  SchemaType.prototype.doValidate.call(this, value, function (error) {
+Embedded.prototype.doValidate = function(value, fn) {
+  SchemaType.prototype.doValidate.call(this, value, function(error) {
     if (error) {
       return fn(error);
     }
@@ -113,7 +113,7 @@ Embedded.prototype.doValidate = function (value, fn) {
  * @api private
  */
 
-Embedded.prototype.doValidateSync = function (value) {
+Embedded.prototype.doValidateSync = function(value) {
   var schemaTypeError = SchemaType.prototype.doValidateSync.call(this, value);
   if (schemaTypeError) {
     return schemaTypeError;
@@ -130,6 +130,6 @@ Embedded.prototype.doValidateSync = function (value) {
  * @api private
  */
 
-Embedded.prototype.checkRequired = function (value) {
+Embedded.prototype.checkRequired = function(value) {
   return !!value && value.$isSingleNested;
 };
diff --git a/lib/schema/mixed.js b/lib/schema/mixed.js
index 6b2576af8e7..c1b4cab793d 100644
--- a/lib/schema/mixed.js
+++ b/lib/schema/mixed.js
@@ -22,7 +22,7 @@ function Mixed(path, options) {
       options.default = Array;
     } else if (!options.shared && utils.isObject(def) && Object.keys(def).length === 0) {
       // prevent odd "shared" objects between documents
-      options.default = function () {
+      options.default = function() {
         return {};
       };
     }
@@ -51,7 +51,7 @@ Mixed.prototype.constructor = Mixed;
  * @api private
  */
 
-Mixed.prototype.checkRequired = function (val) {
+Mixed.prototype.checkRequired = function(val) {
   return (val !== undefined) && (val !== null);
 };
 
@@ -64,7 +64,7 @@ Mixed.prototype.checkRequired = function (val) {
  * @api private
  */
 
-Mixed.prototype.cast = function (val) {
+Mixed.prototype.cast = function(val) {
   return val;
 };
 
@@ -76,7 +76,7 @@ Mixed.prototype.cast = function (val) {
  * @api private
  */
 
-Mixed.prototype.castForQuery = function ($cond, val) {
+Mixed.prototype.castForQuery = function($cond, val) {
   if (arguments.length === 2) {
     return val;
   }
diff --git a/lib/schema/number.js b/lib/schema/number.js
index 8659da0170b..3f182a48637 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -80,9 +80,9 @@ SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
  * @api public
  */
 
-SchemaNumber.prototype.min = function (value, message) {
+SchemaNumber.prototype.min = function(value, message) {
   if (this.minValidator) {
-    this.validators = this.validators.filter(function (v) {
+    this.validators = this.validators.filter(function(v) {
       return v.validator !== this.minValidator;
     }, this);
   }
@@ -91,7 +91,7 @@ SchemaNumber.prototype.min = function (value, message) {
     var msg = message || errorMessages.Number.min;
     msg = msg.replace(/{MIN}/, value);
     this.validators.push({
-      validator: this.minValidator = function (v) {
+      validator: this.minValidator = function(v) {
         return v == null || v >= value;
       },
       message: msg,
@@ -134,9 +134,9 @@ SchemaNumber.prototype.min = function (value, message) {
  * @api public
  */
 
-SchemaNumber.prototype.max = function (value, message) {
+SchemaNumber.prototype.max = function(value, message) {
   if (this.maxValidator) {
-    this.validators = this.validators.filter(function (v) {
+    this.validators = this.validators.filter(function(v) {
       return v.validator !== this.maxValidator;
     }, this);
   }
@@ -145,7 +145,7 @@ SchemaNumber.prototype.max = function (value, message) {
     var msg = message || errorMessages.Number.max;
     msg = msg.replace(/{MAX}/, value);
     this.validators.push({
-      validator: this.maxValidator = function (v) {
+      validator: this.maxValidator = function(v) {
         return v == null || v <= value;
       },
       message: msg,
@@ -166,7 +166,7 @@ SchemaNumber.prototype.max = function (value, message) {
  * @api private
  */
 
-SchemaNumber.prototype.cast = function (value, doc, init) {
+SchemaNumber.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
@@ -241,7 +241,7 @@ function handleArray(val) {
   if (!Array.isArray(val)) {
     return [this.cast(val)];
   }
-  return val.map(function (m) {
+  return val.map(function(m) {
     return _this.cast(m);
   });
 }
@@ -267,12 +267,12 @@ SchemaNumber.prototype.$conditionalHandlers =
  * @api private
  */
 
-SchemaNumber.prototype.castForQuery = function ($conditional, val) {
+SchemaNumber.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = this.$conditionalHandlers[$conditional];
     if (!handler) {
-      throw new Error("Can't use " + $conditional + ' with Number.');
+      throw new Error('Can\'t use ' + $conditional + ' with Number.');
     }
     return handler.call(this, val);
   }
diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js
index e5b14f0b7e0..0dc212aa750 100644
--- a/lib/schema/objectid.js
+++ b/lib/schema/objectid.js
@@ -44,7 +44,7 @@ ObjectId.prototype.constructor = ObjectId;
  * @return {SchemaType} this
  */
 
-ObjectId.prototype.auto = function (turnOn) {
+ObjectId.prototype.auto = function(turnOn) {
   if (turnOn) {
     this.default(defaultId);
     this.set(resetId);
@@ -75,7 +75,7 @@ ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
  * @api private
  */
 
-ObjectId.prototype.cast = function (value, doc, init) {
+ObjectId.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
@@ -165,12 +165,12 @@ ObjectId.prototype.$conditionalHandlers =
  * @api private
  */
 
-ObjectId.prototype.castForQuery = function ($conditional, val) {
+ObjectId.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = this.$conditionalHandlers[$conditional];
     if (!handler) {
-      throw new Error("Can't use " + $conditional + ' with ObjectId.');
+      throw new Error('Can\'t use ' + $conditional + ' with ObjectId.');
     }
     return handler.call(this, val);
   }
diff --git a/lib/schema/operators/bitwise.js b/lib/schema/operators/bitwise.js
index e0f535ae641..c1fdd34e5ab 100644
--- a/lib/schema/operators/bitwise.js
+++ b/lib/schema/operators/bitwise.js
@@ -11,7 +11,7 @@ var CastError = require('../../error/cast');
 function handleBitwiseOperator(val) {
   var _this = this;
   if (Array.isArray(val)) {
-    return val.map(function (v) {
+    return val.map(function(v) {
       return _castNumber(_this.path, v);
     });
   } else if (Buffer.isBuffer(val)) {
diff --git a/lib/schema/string.js b/lib/schema/string.js
index 84710717f78..6157051baea 100644
--- a/lib/schema/string.js
+++ b/lib/schema/string.js
@@ -72,9 +72,9 @@ SchemaString.prototype.constructor = SchemaString;
  * @api public
  */
 
-SchemaString.prototype.enum = function () {
+SchemaString.prototype.enum = function() {
   if (this.enumValidator) {
-    this.validators = this.validators.filter(function (v) {
+    this.validators = this.validators.filter(function(v) {
       return v.validator !== this.enumValidator;
     }, this);
     this.enumValidator = false;
@@ -102,7 +102,7 @@ SchemaString.prototype.enum = function () {
   }
 
   var vals = this.enumValues;
-  this.enumValidator = function (v) {
+  this.enumValidator = function(v) {
     return undefined === v || ~vals.indexOf(v);
   };
   this.validators.push({
@@ -129,8 +129,8 @@ SchemaString.prototype.enum = function () {
  * @return {SchemaType} this
  */
 
-SchemaString.prototype.lowercase = function () {
-  return this.set(function (v, self) {
+SchemaString.prototype.lowercase = function() {
+  return this.set(function(v, self) {
     if (typeof v !== 'string') {
       v = self.cast(v);
     }
@@ -155,8 +155,8 @@ SchemaString.prototype.lowercase = function () {
  * @return {SchemaType} this
  */
 
-SchemaString.prototype.uppercase = function () {
-  return this.set(function (v, self) {
+SchemaString.prototype.uppercase = function() {
+  return this.set(function(v, self) {
     if (typeof v !== 'string') {
       v = self.cast(v);
     }
@@ -185,8 +185,8 @@ SchemaString.prototype.uppercase = function () {
  * @return {SchemaType} this
  */
 
-SchemaString.prototype.trim = function () {
-  return this.set(function (v, self) {
+SchemaString.prototype.trim = function() {
+  return this.set(function(v, self) {
     if (typeof v !== 'string') {
       v = self.cast(v);
     }
@@ -228,9 +228,9 @@ SchemaString.prototype.trim = function () {
  * @api public
  */
 
-SchemaString.prototype.minlength = function (value, message) {
+SchemaString.prototype.minlength = function(value, message) {
   if (this.minlengthValidator) {
-    this.validators = this.validators.filter(function (v) {
+    this.validators = this.validators.filter(function(v) {
       return v.validator !== this.minlengthValidator;
     }, this);
   }
@@ -239,7 +239,7 @@ SchemaString.prototype.minlength = function (value, message) {
     var msg = message || errorMessages.String.minlength;
     msg = msg.replace(/{MINLENGTH}/, value);
     this.validators.push({
-      validator: this.minlengthValidator = function (v) {
+      validator: this.minlengthValidator = function(v) {
         return v === null || v.length >= value;
       },
       message: msg,
@@ -282,9 +282,9 @@ SchemaString.prototype.minlength = function (value, message) {
  * @api public
  */
 
-SchemaString.prototype.maxlength = function (value, message) {
+SchemaString.prototype.maxlength = function(value, message) {
   if (this.maxlengthValidator) {
-    this.validators = this.validators.filter(function (v) {
+    this.validators = this.validators.filter(function(v) {
       return v.validator !== this.maxlengthValidator;
     }, this);
   }
@@ -293,7 +293,7 @@ SchemaString.prototype.maxlength = function (value, message) {
     var msg = message || errorMessages.String.maxlength;
     msg = msg.replace(/{MAXLENGTH}/, value);
     this.validators.push({
-      validator: this.maxlengthValidator = function (v) {
+      validator: this.maxlengthValidator = function(v) {
         return v === null || v.length <= value;
       },
       message: msg,
@@ -348,7 +348,7 @@ SchemaString.prototype.match = function match(regExp, message) {
 
   var msg = message || errorMessages.String.match;
 
-  var matchValidator = function (v) {
+  var matchValidator = function(v) {
     if (!regExp) {
       return false;
     }
@@ -388,7 +388,7 @@ SchemaString.prototype.checkRequired = function checkRequired(value, doc) {
  * @api private
  */
 
-SchemaString.prototype.cast = function (value, doc, init) {
+SchemaString.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
@@ -457,7 +457,7 @@ function handleArray(val) {
   if (!Array.isArray(val)) {
     return [this.castForQuery(val)];
   }
-  return val.map(function (m) {
+  return val.map(function(m) {
     return _this.castForQuery(m);
   });
 }
@@ -481,12 +481,12 @@ SchemaString.prototype.$conditionalHandlers =
  * @api private
  */
 
-SchemaString.prototype.castForQuery = function ($conditional, val) {
+SchemaString.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = this.$conditionalHandlers[$conditional];
     if (!handler) {
-      throw new Error("Can't use " + $conditional + ' with String.');
+      throw new Error('Can\'t use ' + $conditional + ' with String.');
     }
     return handler.call(this, val);
   }
diff --git a/lib/schematype.js b/lib/schematype.js
index 76e78ebbd63..7bd25039fce 100644
--- a/lib/schematype.js
+++ b/lib/schematype.js
@@ -86,7 +86,7 @@ function SchemaType(path, options, instance) {
  * @api public
  */
 
-SchemaType.prototype.default = function (val) {
+SchemaType.prototype.default = function(val) {
   if (arguments.length === 1) {
     this.defaultValue = typeof val === 'function'
         ? val
@@ -123,7 +123,7 @@ SchemaType.prototype.default = function (val) {
  * @api public
  */
 
-SchemaType.prototype.index = function (options) {
+SchemaType.prototype.index = function(options) {
   this._index = options;
   utils.expires(this._index);
   return this;
@@ -144,7 +144,7 @@ SchemaType.prototype.index = function (options) {
  * @api public
  */
 
-SchemaType.prototype.unique = function (bool) {
+SchemaType.prototype.unique = function(bool) {
   if (this._index === null || typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
@@ -167,7 +167,7 @@ SchemaType.prototype.unique = function (bool) {
  * @api public
  */
 
-SchemaType.prototype.text = function (bool) {
+SchemaType.prototype.text = function(bool) {
   if (this._index === null || typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
@@ -191,7 +191,7 @@ SchemaType.prototype.text = function (bool) {
  * @api public
  */
 
-SchemaType.prototype.sparse = function (bool) {
+SchemaType.prototype.sparse = function(bool) {
   if (this._index === null || typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
@@ -275,7 +275,7 @@ SchemaType.prototype.sparse = function (bool) {
  * @api public
  */
 
-SchemaType.prototype.set = function (fn) {
+SchemaType.prototype.set = function(fn) {
   if (typeof fn !== 'function') {
     throw new TypeError('A setter must be a function.');
   }
@@ -345,7 +345,7 @@ SchemaType.prototype.set = function (fn) {
  * @api public
  */
 
-SchemaType.prototype.get = function (fn) {
+SchemaType.prototype.get = function(fn) {
   if (typeof fn !== 'function') {
     throw new TypeError('A getter must be a function.');
   }
@@ -435,7 +435,7 @@ SchemaType.prototype.get = function (fn) {
  * @api public
  */
 
-SchemaType.prototype.validate = function (obj, message, type) {
+SchemaType.prototype.validate = function(obj, message, type) {
   if (typeof obj === 'function' || obj && utils.getFunctionName(obj.constructor) === 'RegExp') {
     var properties;
     if (message instanceof Object && !type) {
@@ -505,9 +505,9 @@ SchemaType.prototype.validate = function (obj, message, type) {
  * @api public
  */
 
-SchemaType.prototype.required = function (required, message) {
+SchemaType.prototype.required = function(required, message) {
   if (required === false) {
-    this.validators = this.validators.filter(function (v) {
+    this.validators = this.validators.filter(function(v) {
       return v.validator !== this.requiredValidator;
     }, this);
 
@@ -518,7 +518,7 @@ SchemaType.prototype.required = function (required, message) {
   var _this = this;
   this.isRequired = true;
 
-  this.requiredValidator = function (v) {
+  this.requiredValidator = function(v) {
     // in here, `this` refers to the validating document.
     // no validation when this path wasn't selected in the query.
     if ('isSelected' in this && !this.isSelected(_this.path) && !this.isModified(_this.path)) {
@@ -552,7 +552,7 @@ SchemaType.prototype.required = function (required, message) {
  * @api private
  */
 
-SchemaType.prototype.getDefault = function (scope, init) {
+SchemaType.prototype.getDefault = function(scope, init) {
   var ret = typeof this.defaultValue === 'function'
       ? this.defaultValue.call(scope)
       : this.defaultValue;
@@ -572,7 +572,7 @@ SchemaType.prototype.getDefault = function (scope, init) {
  * @api private
  */
 
-SchemaType.prototype.applySetters = function (value, scope, init, priorVal, options) {
+SchemaType.prototype.applySetters = function(value, scope, init, priorVal, options) {
   var v = value,
       setters = this.setters,
       len = setters.length,
@@ -608,7 +608,7 @@ SchemaType.prototype.applySetters = function (value, scope, init, priorVal, opti
  * @api private
  */
 
-SchemaType.prototype.applyGetters = function (value, scope) {
+SchemaType.prototype.applyGetters = function(value, scope) {
   var v = value,
       getters = this.getters,
       len = getters.length;
@@ -655,7 +655,7 @@ SchemaType.prototype.select = function select(val) {
  * @api private
  */
 
-SchemaType.prototype.doValidate = function (value, fn, scope) {
+SchemaType.prototype.doValidate = function(value, fn, scope) {
   var err = false,
       path = this.path,
       count = this.validators.length;
@@ -664,7 +664,7 @@ SchemaType.prototype.doValidate = function (value, fn, scope) {
     return fn(null);
   }
 
-  var validate = function (ok, validatorProperties) {
+  var validate = function(ok, validatorProperties) {
     if (err) {
       return;
     }
@@ -677,7 +677,7 @@ SchemaType.prototype.doValidate = function (value, fn, scope) {
   };
 
   var _this = this;
-  this.validators.forEach(function (v) {
+  this.validators.forEach(function(v) {
     if (err) {
       return;
     }
@@ -696,7 +696,7 @@ SchemaType.prototype.doValidate = function (value, fn, scope) {
         return;
       }
       if (validator.length === 2) {
-        validator.call(scope, value, function (ok, customMsg) {
+        validator.call(scope, value, function(ok, customMsg) {
           if (customMsg) {
             validatorProperties.message = customMsg;
           }
@@ -722,7 +722,7 @@ SchemaType.prototype.doValidate = function (value, fn, scope) {
  * @api private
  */
 
-SchemaType.prototype.doValidateSync = function (value, scope) {
+SchemaType.prototype.doValidateSync = function(value, scope) {
   var err = null,
       path = this.path,
       count = this.validators.length;
@@ -731,7 +731,7 @@ SchemaType.prototype.doValidateSync = function (value, scope) {
     return null;
   }
 
-  var validate = function (ok, validatorProperties) {
+  var validate = function(ok, validatorProperties) {
     if (err) {
       return;
     }
@@ -745,7 +745,7 @@ SchemaType.prototype.doValidateSync = function (value, scope) {
     return null;
   }
 
-  this.validators.forEach(function (v) {
+  this.validators.forEach(function(v) {
     if (err) {
       return;
     }
@@ -779,7 +779,7 @@ SchemaType.prototype.doValidateSync = function (value, scope) {
  * @api private
  */
 
-SchemaType._isRef = function (self, value, doc, init) {
+SchemaType._isRef = function(self, value, doc, init) {
   // fast path
   var ref = init && self.options && self.options.ref;
 
@@ -824,7 +824,7 @@ function handleArray(val) {
   if (!Array.isArray(val)) {
     return [this.castForQuery(val)];
   }
-  return val.map(function (m) {
+  return val.map(function(m) {
     return _this.castForQuery(m);
   });
 }
@@ -849,7 +849,7 @@ SchemaType.prototype.$conditionalHandlers = {
  * @api private
  */
 
-SchemaType.prototype.castForQuery = function ($conditional, val) {
+SchemaType.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = this.$conditionalHandlers[$conditional];
diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js
index 2d2c4018a95..beb7c9bb543 100644
--- a/lib/services/updateValidators.js
+++ b/lib/services/updateValidators.js
@@ -18,7 +18,7 @@ var ObjectId = require('../types/objectid');
  * @api private
  */
 
-module.exports = function (query, schema, castedDoc, options) {
+module.exports = function(query, schema, castedDoc, options) {
   var keys = Object.keys(castedDoc || {});
   var updatedKeys = {};
   var updatedValues = {};
@@ -77,7 +77,7 @@ module.exports = function (query, schema, castedDoc, options) {
     }
 
     if (options.setDefaultsOnInsert) {
-      schema.eachPath(function (path, schemaType) {
+      schema.eachPath(function(path, schemaType) {
         if (path === '_id') {
           // Ignore _id for now because it causes bugs in 2.4
           return;
@@ -85,7 +85,7 @@ module.exports = function (query, schema, castedDoc, options) {
         if (schemaType.$isSingleNested) {
           // Only handle nested schemas 1-level deep to avoid infinite
           // recursion re: https://github.com/mongodb-js/mongoose-autopopulate/issues/11
-          schemaType.schema.eachPath(function (_path, _schemaType) {
+          schemaType.schema.eachPath(function(_path, _schemaType) {
             if (path === '_id') {
               // Ignore _id for now because it causes bugs in 2.4
               return;
@@ -115,13 +115,13 @@ module.exports = function (query, schema, castedDoc, options) {
   var validatorsToExecute = [];
   var validationErrors = [];
   for (i = 0; i < numUpdates; ++i) {
-    (function (i) {
+    (function(i) {
       var schemaPath = schema._getSchema(updates[i]);
       if (schemaPath) {
-        validatorsToExecute.push(function (callback) {
+        validatorsToExecute.push(function(callback) {
           schemaPath.doValidate(
             updatedValues[updates[i]],
-            function (err) {
+            function(err) {
               if (err) {
                 err.path = updates[i];
                 validationErrors.push(err);
@@ -135,8 +135,8 @@ module.exports = function (query, schema, castedDoc, options) {
     })(i);
   }
 
-  return function (callback) {
-    async.parallel(validatorsToExecute, function () {
+  return function(callback) {
+    async.parallel(validatorsToExecute, function() {
       if (validationErrors.length) {
         var err = new ValidationError(null);
         for (var i = 0; i < validationErrors.length; ++i) {
diff --git a/lib/statemachine.js b/lib/statemachine.js
index 4bf081b9b3b..3bba519f6e4 100644
--- a/lib/statemachine.js
+++ b/lib/statemachine.js
@@ -29,10 +29,10 @@ var StateMachine = module.exports = exports = function StateMachine() {
  * @private
  */
 
-StateMachine.ctor = function () {
+StateMachine.ctor = function() {
   var states = utils.args(arguments);
 
-  var ctor = function () {
+  var ctor = function() {
     StateMachine.apply(this, arguments);
     this.paths = {};
     this.states = {};
@@ -49,9 +49,9 @@ StateMachine.ctor = function () {
 
   ctor.prototype = new StateMachine();
 
-  states.forEach(function (state) {
+  states.forEach(function(state) {
     // Changes the `path`'s state to `state`.
-    ctor.prototype[state] = function (path) {
+    ctor.prototype[state] = function(path) {
       this._changeState(path, state);
     };
   });
@@ -104,7 +104,7 @@ StateMachine.prototype.clear = function clear(state) {
 StateMachine.prototype.some = function some() {
   var _this = this;
   var what = arguments.length ? arguments : this.stateNames;
-  return Array.prototype.some.call(what, function (state) {
+  return Array.prototype.some.call(what, function(state) {
     return Object.keys(_this.states[state]).length;
   });
 };
@@ -119,7 +119,7 @@ StateMachine.prototype.some = function some() {
  */
 
 StateMachine.prototype._iter = function _iter(iterMethod) {
-  return function () {
+  return function() {
     var numArgs = arguments.length,
         states = utils.args(arguments, 0, numArgs - 1),
         callback = arguments[numArgs - 1];
@@ -128,11 +128,11 @@ StateMachine.prototype._iter = function _iter(iterMethod) {
 
     var _this = this;
 
-    var paths = states.reduce(function (paths, state) {
+    var paths = states.reduce(function(paths, state) {
       return paths.concat(Object.keys(_this.states[state]));
     }, []);
 
-    return paths[iterMethod](function (path, i, paths) {
+    return paths[iterMethod](function(path, i, paths) {
       return callback(path, i, paths);
     });
   };
diff --git a/lib/types/array.js b/lib/types/array.js
index faa8a97699e..be1e40a2d97 100644
--- a/lib/types/array.js
+++ b/lib/types/array.js
@@ -89,7 +89,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  _cast: function (value) {
+  _cast: function(value) {
     var owner = this._owner;
     var populated = false;
     var Model;
@@ -142,7 +142,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  _markModified: function (elem, embeddedPath) {
+  _markModified: function(elem, embeddedPath) {
     var parent = this._parent,
         dirtyPath;
 
@@ -175,7 +175,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  _registerAtomic: function (op, val) {
+  _registerAtomic: function(op, val) {
     if (op === '$set') {
       // $set takes precedence over all other ops.
       // mark entire array modified.
@@ -188,7 +188,7 @@ MongooseArray.mixin = {
     // reset pop/shift after save
     if (op === '$pop' && !('$pop' in atomics)) {
       var _this = this;
-      this._parent.once('save', function () {
+      this._parent.once('save', function() {
         _this._popped = _this._shifted = null;
       });
     }
@@ -212,7 +212,7 @@ MongooseArray.mixin = {
       var pullOp = atomics['$pull'] || (atomics['$pull'] = {});
       if (val[0] instanceof EmbeddedDocument) {
         selector = pullOp['$or'] || (pullOp['$or'] = []);
-        Array.prototype.push.apply(selector, val.map(function (v) {
+        Array.prototype.push.apply(selector, val.map(function(v) {
           return v.toObject({virtuals: false});
         }));
       } else {
@@ -237,7 +237,7 @@ MongooseArray.mixin = {
    * @api private
    */
 
-  $__getAtomics: function () {
+  $__getAtomics: function() {
     var ret = [];
     var keys = Object.keys(this._atomics);
     var i = keys.length;
@@ -297,7 +297,7 @@ MongooseArray.mixin = {
    * @method _mapCast
    * @receiver MongooseArray
    */
-  _mapCast: function (val, index) {
+  _mapCast: function(val, index) {
     return this._cast(val, this.length + index);
   },
 
@@ -310,7 +310,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  push: function () {
+  push: function() {
     var values = [].map.call(arguments, this._mapCast, this);
     values = this._schema.applySetters(values, this._parent, undefined,
         undefined, {skipDocumentArrayCast: true});
@@ -336,7 +336,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  nonAtomicPush: function () {
+  nonAtomicPush: function() {
     var values = [].map.call(arguments, this._mapCast, this);
     var ret = [].push.apply(this, values);
     this._registerAtomic('$set', this);
@@ -379,7 +379,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  $pop: function () {
+  $pop: function() {
     this._registerAtomic('$pop', 1);
     this._markModified();
 
@@ -405,7 +405,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  pop: function () {
+  pop: function() {
     var ret = [].pop.call(this);
     this._registerAtomic('$set', this);
     this._markModified();
@@ -477,7 +477,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  shift: function () {
+  shift: function() {
     var ret = [].shift.call(this);
     this._registerAtomic('$set', this);
     this._markModified();
@@ -513,7 +513,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  pull: function () {
+  pull: function() {
     var values = [].map.call(arguments, this._cast, this),
         cur = this._parent.get(this._path),
         i = cur.length,
@@ -522,9 +522,9 @@ MongooseArray.mixin = {
     while (i--) {
       mem = cur[i];
       if (mem instanceof Document) {
-        if (values.some(function (v) {
-              return v.equals(mem);
-            })) {
+        if (values.some(function(v) {
+          return v.equals(mem);
+        })) {
           [].splice.call(cur, i, 1);
         }
       } else if (~cur.indexOf.call(values, mem)) {
@@ -533,7 +533,7 @@ MongooseArray.mixin = {
     }
 
     if (values[0] instanceof EmbeddedDocument) {
-      this._registerAtomic('$pullDocs', values.map(function (v) {
+      this._registerAtomic('$pullDocs', values.map(function(v) {
         return v._id || v;
       }));
     } else {
@@ -586,7 +586,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  unshift: function () {
+  unshift: function() {
     var values = [].map.call(arguments, this._cast, this);
     values = this._schema.applySetters(values, this._parent);
     [].unshift.apply(this, values);
@@ -607,7 +607,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  sort: function () {
+  sort: function() {
     var ret = [].sort.apply(this, arguments);
     this._registerAtomic('$set', this);
     this._markModified();
@@ -642,17 +642,17 @@ MongooseArray.mixin = {
       type = 'date';
     }
 
-    values.forEach(function (v) {
+    values.forEach(function(v) {
       var found;
       switch (type) {
         case 'doc':
-          found = this.some(function (doc) {
+          found = this.some(function(doc) {
             return doc.equals(v);
           });
           break;
         case 'date':
           var val = +v;
-          found = this.some(function (d) {
+          found = this.some(function(d) {
             return +d === val;
           });
           break;
@@ -719,9 +719,9 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  toObject: function (options) {
+  toObject: function(options) {
     if (options && options.depopulate) {
-      return this.map(function (doc) {
+      return this.map(function(doc) {
         return doc instanceof Document
             ? doc.toObject(options)
             : doc;
@@ -739,7 +739,7 @@ MongooseArray.mixin = {
    * @receiver MongooseArray
    */
 
-  inspect: function () {
+  inspect: function() {
     return JSON.stringify(this);
   },
 
diff --git a/lib/types/buffer.js b/lib/types/buffer.js
index e8e81fe7fb7..2cd66507a15 100644
--- a/lib/types/buffer.js
+++ b/lib/types/buffer.js
@@ -97,7 +97,7 @@ MongooseBuffer.mixin = {
    * @receiver MongooseBuffer
    */
 
-  _markModified: function () {
+  _markModified: function() {
     var parent = this._parent;
 
     if (parent) {
@@ -114,7 +114,7 @@ MongooseBuffer.mixin = {
    * @receiver MongooseBuffer
    */
 
-  write: function () {
+  write: function() {
     var written = Buffer.prototype.write.apply(this, arguments);
 
     if (written > 0) {
@@ -137,7 +137,7 @@ MongooseBuffer.mixin = {
    * @receiver MongooseBuffer
    */
 
-  copy: function (target) {
+  copy: function(target) {
     var ret = Buffer.prototype.copy.apply(this, arguments);
 
     if (target && target.isMongooseBuffer) {
@@ -162,11 +162,11 @@ MongooseBuffer.mixin = {
     'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +
     'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +
     'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'
-).split(' ').forEach(function (method) {
+).split(' ').forEach(function(method) {
   if (!Buffer.prototype[method]) {
     return;
   }
-  MongooseBuffer.mixin[method] = function () {
+  MongooseBuffer.mixin[method] = function() {
     var ret = Buffer.prototype[method].apply(this, arguments);
     this._markModified();
     return ret;
@@ -196,7 +196,7 @@ MongooseBuffer.mixin = {
  * @receiver MongooseBuffer
  */
 
-MongooseBuffer.mixin.toObject = function (options) {
+MongooseBuffer.mixin.toObject = function(options) {
   var subtype = typeof options === 'number'
       ? options
       : (this._subtype || 0);
@@ -212,7 +212,7 @@ MongooseBuffer.mixin.toObject = function (options) {
  * @receiver MongooseBuffer
  */
 
-MongooseBuffer.mixin.equals = function (other) {
+MongooseBuffer.mixin.equals = function(other) {
   if (!Buffer.isBuffer(other)) {
     return false;
   }
@@ -252,7 +252,7 @@ MongooseBuffer.mixin.equals = function (other) {
  * @receiver MongooseBuffer
  */
 
-MongooseBuffer.mixin.subtype = function (subtype) {
+MongooseBuffer.mixin.subtype = function(subtype) {
   if (typeof subtype !== 'number') {
     throw new TypeError('Invalid subtype. Expected a number');
   }
diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js
index ae3de043167..5382b350119 100644
--- a/lib/types/documentarray.js
+++ b/lib/types/documentarray.js
@@ -85,7 +85,7 @@ MongooseDocumentArray.mixin = {
    * @receiver MongooseDocumentArray
    */
 
-  _cast: function (value, index) {
+  _cast: function(value, index) {
     if (value instanceof this._schema.casterConstructor) {
       if (!(value.__parent && value.__parentArray)) {
         // value may have been created using array.create()
@@ -121,7 +121,7 @@ MongooseDocumentArray.mixin = {
    * @receiver MongooseDocumentArray
    */
 
-  id: function (id) {
+  id: function(id) {
     var casted,
         sid,
         _id;
@@ -171,8 +171,8 @@ MongooseDocumentArray.mixin = {
    * @receiver MongooseDocumentArray
    */
 
-  toObject: function (options) {
-    return this.map(function (doc) {
+  toObject: function(options) {
+    return this.map(function(doc) {
       return doc && doc.toObject(options) || null;
     });
   },
@@ -185,7 +185,7 @@ MongooseDocumentArray.mixin = {
    * @receiver MongooseDocumentArray
    */
 
-  inspect: function () {
+  inspect: function() {
     return Array.prototype.slice.call(this);
   },
 
@@ -200,7 +200,7 @@ MongooseDocumentArray.mixin = {
    * @receiver MongooseDocumentArray
    */
 
-  create: function (obj) {
+  create: function(obj) {
     return new this._schema.casterConstructor(obj);
   },
 
diff --git a/lib/types/embedded.js b/lib/types/embedded.js
index 1a85874b3e3..feecf12cd9d 100644
--- a/lib/types/embedded.js
+++ b/lib/types/embedded.js
@@ -30,7 +30,7 @@ function EmbeddedDocument(obj, parentArr, skipId, fields, index) {
   Document.call(this, obj, fields, skipId);
 
   var _this = this;
-  this.on('isNew', function (val) {
+  this.on('isNew', function(val) {
     _this.isNew = val;
   });
 }
@@ -55,7 +55,7 @@ EmbeddedDocument.prototype.constructor = EmbeddedDocument;
  * @receiver EmbeddedDocument
  */
 
-EmbeddedDocument.prototype.markModified = function (path) {
+EmbeddedDocument.prototype.markModified = function(path) {
   this.$__.activePaths.modify(path);
   if (!this.__parentArray) {
     return;
@@ -83,9 +83,9 @@ EmbeddedDocument.prototype.markModified = function (path) {
  * @api private
  */
 
-EmbeddedDocument.prototype.save = function (fn) {
+EmbeddedDocument.prototype.save = function(fn) {
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve) {
+  return new Promise.ES6(function(resolve) {
     fn && fn();
     resolve();
   });
@@ -120,7 +120,7 @@ function registerRemoveListener(sub) {
  * @api public
  */
 
-EmbeddedDocument.prototype.remove = function (fn) {
+EmbeddedDocument.prototype.remove = function(fn) {
   if (!this.__parentArray) {
     return this;
   }
@@ -149,7 +149,7 @@ EmbeddedDocument.prototype.remove = function (fn) {
  * @api private
  */
 
-EmbeddedDocument.prototype.update = function () {
+EmbeddedDocument.prototype.update = function() {
   throw new Error('The #update method is not available on EmbeddedDocuments');
 };
 
@@ -159,7 +159,7 @@ EmbeddedDocument.prototype.update = function () {
  * @api public
  */
 
-EmbeddedDocument.prototype.inspect = function () {
+EmbeddedDocument.prototype.inspect = function() {
   return this.toObject();
 };
 
@@ -172,7 +172,7 @@ EmbeddedDocument.prototype.inspect = function () {
  * @api public
  */
 
-EmbeddedDocument.prototype.invalidate = function (path, err, val, first) {
+EmbeddedDocument.prototype.invalidate = function(path, err, val, first) {
   if (!this.__parent) {
     var msg = 'Unable to invalidate a subdocument that has not been added to an array.';
     throw new Error(msg);
@@ -201,7 +201,7 @@ EmbeddedDocument.prototype.invalidate = function (path, err, val, first) {
  * @receiver EmbeddedDocument
  */
 
-EmbeddedDocument.prototype.$markValid = function (path) {
+EmbeddedDocument.prototype.$markValid = function(path) {
   if (!this.__parent) {
     return;
   }
@@ -223,7 +223,7 @@ EmbeddedDocument.prototype.$markValid = function (path) {
  * @receiver EmbeddedDocument
  */
 
-EmbeddedDocument.prototype.$isValid = function (path) {
+EmbeddedDocument.prototype.$isValid = function(path) {
   var index = this.__index;
   if (typeof index !== 'undefined') {
     return !this.__parent.$__.validationError || !this.__parent.$__.validationError.errors[path];
@@ -238,7 +238,7 @@ EmbeddedDocument.prototype.$isValid = function (path) {
  * @return {Document}
  */
 
-EmbeddedDocument.prototype.ownerDocument = function () {
+EmbeddedDocument.prototype.ownerDocument = function() {
   if (this.$__.ownerDocument) {
     return this.$__.ownerDocument;
   }
@@ -266,7 +266,7 @@ EmbeddedDocument.prototype.ownerDocument = function () {
  * @memberOf EmbeddedDocument
  */
 
-EmbeddedDocument.prototype.$__fullPath = function (path) {
+EmbeddedDocument.prototype.$__fullPath = function(path) {
   if (!this.$__.fullPath) {
     var parent = this; // eslint-disable-line consistent-this
     if (!parent.__parent) {
@@ -298,7 +298,7 @@ EmbeddedDocument.prototype.$__fullPath = function (path) {
  * @api public
  */
 
-EmbeddedDocument.prototype.parent = function () {
+EmbeddedDocument.prototype.parent = function() {
   return this.__parent;
 };
 
@@ -308,7 +308,7 @@ EmbeddedDocument.prototype.parent = function () {
  * @api public
  */
 
-EmbeddedDocument.prototype.parentArray = function () {
+EmbeddedDocument.prototype.parentArray = function() {
   return this.__parentArray;
 };
 
diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js
index 0c4697fc4f5..de127a5dae3 100644
--- a/lib/types/subdocument.js
+++ b/lib/types/subdocument.js
@@ -29,33 +29,33 @@ Subdocument.prototype = Object.create(Document.prototype);
  * @api private
  */
 
-Subdocument.prototype.save = function (fn) {
+Subdocument.prototype.save = function(fn) {
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function (resolve) {
+  return new Promise.ES6(function(resolve) {
     fn && fn();
     resolve();
   });
 };
 
-Subdocument.prototype.$isValid = function (path) {
+Subdocument.prototype.$isValid = function(path) {
   if (this.$parent) {
     return this.$parent.$isValid([this.$basePath, path].join('.'));
   }
 };
 
-Subdocument.prototype.markModified = function (path) {
+Subdocument.prototype.markModified = function(path) {
   if (this.$parent) {
     this.$parent.markModified([this.$basePath, path].join('.'));
   }
 };
 
-Subdocument.prototype.$markValid = function (path) {
+Subdocument.prototype.$markValid = function(path) {
   if (this.$parent) {
     this.$parent.$markValid([this.$basePath, path].join('.'));
   }
 };
 
-Subdocument.prototype.invalidate = function (path, err, val) {
+Subdocument.prototype.invalidate = function(path, err, val) {
   if (this.$parent) {
     this.$parent.invalidate([this.$basePath, path].join('.'), err, val);
   } else if (err.kind === 'cast' || err.name === 'CastError') {
@@ -69,7 +69,7 @@ Subdocument.prototype.invalidate = function (path, err, val) {
  * @return {Document}
  */
 
-Subdocument.prototype.ownerDocument = function () {
+Subdocument.prototype.ownerDocument = function() {
   if (this.$__.ownerDocument) {
     return this.$__.ownerDocument;
   }
@@ -92,7 +92,7 @@ Subdocument.prototype.ownerDocument = function () {
  * @param {Function} [callback] optional callback for compatibility with Document.prototype.remove
  */
 
-Subdocument.prototype.remove = function (callback) {
+Subdocument.prototype.remove = function(callback) {
   this.$parent.set(this.$basePath, null);
   registerRemoveListener(this);
   if (callback) {
diff --git a/lib/utils.js b/lib/utils.js
index a3224810b4f..295dd0ee1f2 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -19,7 +19,7 @@ var Document;
  * @api private
  */
 
-exports.toCollectionName = function (name, options) {
+exports.toCollectionName = function(name, options) {
   options = options || {};
   if (name === 'system.profile') {
     return name;
@@ -116,7 +116,7 @@ var uncountables = exports.uncountables;
 function pluralize(str) {
   var found;
   if (!~uncountables.indexOf(str.toLowerCase())) {
-    found = rules.filter(function (rule) {
+    found = rules.filter(function(rule) {
       return str.match(rule[0]);
     });
     if (found[0]) {
@@ -345,7 +345,7 @@ function cloneArray(arr, options) {
  * @api private
  */
 
-exports.options = function (defaults, options) {
+exports.options = function(defaults, options) {
   var keys = Object.keys(defaults),
       i = keys.length,
       k;
@@ -368,7 +368,7 @@ exports.options = function (defaults, options) {
  * @api private
  */
 
-exports.random = function () {
+exports.random = function() {
   return Math.random().toString().substr(3);
 };
 
@@ -452,7 +452,7 @@ exports.toObject = function toObject(obj) {
  * @return {Boolean}
  */
 
-exports.isObject = function (arg) {
+exports.isObject = function(arg) {
   if (Buffer.isBuffer(arg)) {
     return true;
   }
@@ -481,13 +481,13 @@ exports.tick = function tick(callback) {
   if (typeof callback !== 'function') {
     return;
   }
-  return function () {
+  return function() {
     try {
       callback.apply(this, arguments);
     } catch (err) {
       // only nextTick on err to get out of
       // the event loop and avoid state corruption.
-      process.nextTick(function () {
+      process.nextTick(function() {
         throw err;
       });
     }
@@ -503,7 +503,7 @@ exports.tick = function tick(callback) {
  * @api private
  */
 
-exports.isMongooseObject = function (v) {
+exports.isMongooseObject = function(v) {
   Document || (Document = require('./document'));
   MongooseArray || (MongooseArray = require('./types').Array);
   MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
@@ -577,7 +577,7 @@ exports.populate = function populate(path, select, model, match, options, subPop
     }
 
     if (Array.isArray(path)) {
-      return path.map(function (o) {
+      return path.map(function(o) {
         return exports.populate(o)[0];
       });
     }
@@ -620,7 +620,7 @@ exports.populate = function populate(path, select, model, match, options, subPop
  * @param {Object} obj
  */
 
-exports.getValue = function (path, obj, map) {
+exports.getValue = function(path, obj, map) {
   return mpath.get(path, obj, '_doc', map);
 };
 
@@ -632,7 +632,7 @@ exports.getValue = function (path, obj, map) {
  * @param {Object} obj
  */
 
-exports.setValue = function (path, val, obj, map) {
+exports.setValue = function(path, val, obj, map) {
   mpath.set(path, val, obj, '_doc', map);
 };
 
@@ -671,7 +671,7 @@ exports.object.shallowCopy = exports.options;
  */
 
 var hop = Object.prototype.hasOwnProperty;
-exports.object.hasOwnProperty = function (obj, prop) {
+exports.object.hasOwnProperty = function(obj, prop) {
   return hop.call(obj, prop);
 };
 
@@ -681,7 +681,7 @@ exports.object.hasOwnProperty = function (obj, prop) {
  * @return {Boolean}
  */
 
-exports.isNullOrUndefined = function (val) {
+exports.isNullOrUndefined = function(val) {
   return val === null || val === void 0;
 };
 
@@ -705,7 +705,7 @@ exports.array = {};
 exports.array.flatten = function flatten(arr, filter, ret) {
   ret || (ret = []);
 
-  arr.forEach(function (item) {
+  arr.forEach(function(item) {
     if (Array.isArray(item)) {
       flatten(item, filter, ret);
     } else {
@@ -730,7 +730,7 @@ exports.array.flatten = function flatten(arr, filter, ret) {
  * @private
  */
 
-exports.array.unique = function (arr) {
+exports.array.unique = function(arr) {
   var primitives = {};
   var ids = {};
   var ret = [];
@@ -764,7 +764,7 @@ exports.array.unique = function (arr) {
  */
 
 exports.buffer = {};
-exports.buffer.areEqual = function (a, b) {
+exports.buffer.areEqual = function(a, b) {
   if (!Buffer.isBuffer(a)) {
     return false;
   }
@@ -782,14 +782,14 @@ exports.buffer.areEqual = function (a, b) {
   return true;
 };
 
-exports.getFunctionName = function (fn) {
+exports.getFunctionName = function(fn) {
   if (fn.name) {
     return fn.name;
   }
   return (fn.toString().trim().match(/^function\s*([^\s(]+)/) || [])[1];
 };
 
-exports.decorate = function (destination, source) {
+exports.decorate = function(destination, source) {
   for (var key in source) {
     destination[key] = source[key];
   }
@@ -803,7 +803,7 @@ exports.decorate = function (destination, source) {
  * @api private
  */
 
-exports.mergeClone = function (to, from) {
+exports.mergeClone = function(to, from) {
   var keys = Object.keys(from),
       i = keys.length,
       key;
@@ -834,7 +834,7 @@ exports.mergeClone = function (to, from) {
  * @api private
  */
 
-exports.each = function (arr, fn) {
+exports.each = function(arr, fn) {
   for (var i = 0; i < arr.length; ++i) {
     fn(arr[i]);
   }
diff --git a/lib/virtualtype.js b/lib/virtualtype.js
index bfb2b40ca76..f43cbe2b9fe 100644
--- a/lib/virtualtype.js
+++ b/lib/virtualtype.js
@@ -35,7 +35,7 @@ function VirtualType(options, name) {
  * @api public
  */
 
-VirtualType.prototype.get = function (fn) {
+VirtualType.prototype.get = function(fn) {
   this.getters.push(fn);
   return this;
 };
@@ -57,7 +57,7 @@ VirtualType.prototype.get = function (fn) {
  * @api public
  */
 
-VirtualType.prototype.set = function (fn) {
+VirtualType.prototype.set = function(fn) {
   this.setters.push(fn);
   return this;
 };
@@ -71,7 +71,7 @@ VirtualType.prototype.set = function (fn) {
  * @api public
  */
 
-VirtualType.prototype.applyGetters = function (value, scope) {
+VirtualType.prototype.applyGetters = function(value, scope) {
   var v = value;
   for (var l = this.getters.length - 1; l >= 0; l--) {
     v = this.getters[l].call(scope, v, this);
@@ -88,7 +88,7 @@ VirtualType.prototype.applyGetters = function (value, scope) {
  * @api public
  */
 
-VirtualType.prototype.applySetters = function (value, scope) {
+VirtualType.prototype.applySetters = function(value, scope) {
   var v = value;
   for (var l = this.setters.length - 1; l >= 0; l--) {
     v = this.setters[l].call(scope, v, this);
diff --git a/package.json b/package.json
index 4bbab751f24..bf94c6906b2 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
     "bluebird": "3.1.4",
     "co": "4.6.0",
     "dox": "0.8.0",
-    "eslint": "2.0.0-beta.2",
+    "eslint": "2.0.0-beta.3",
     "highlight.js": "9.1.0",
     "istanbul": "0.4.2",
     "jade": "0.26.3",
diff --git a/static.js b/static.js
index 596c4aa6dd0..c701653c15e 100644
--- a/static.js
+++ b/static.js
@@ -3,15 +3,15 @@ var static = require('node-static');
 var server = new static.Server('.', {cache: 0});
 var open = require('open');
 
-require('http').createServer(function (req, res) {
+require('http').createServer(function(req, res) {
   if (req.url === '/favicon.ico') {
     req.destroy();
     res.statusCode = 204;
     return res.end();
   }
 
-  req.on('end', function () {
-    server.serve(req, res, function (err) {
+  req.on('end', function() {
+    server.serve(req, res, function(err) {
       if (err) {
         console.error(err, req.url);
         res.writeHead(err.status, err.headers);
diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index 4ec5e100d7f..06f1305869b 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -32,10 +32,10 @@ function setupData(callback) {
       db = start(),
       Employee = db.model('Employee');
 
-  emps.forEach(function (data) {
+  emps.forEach(function(data) {
     var emp = new Employee(data);
 
-    emp.save(function () {
+    emp.save(function() {
       if (++saved === emps.length) {
         callback(db);
       }
@@ -44,7 +44,7 @@ function setupData(callback) {
 }
 
 function clearData(db, callback) {
-  db.model('Employee').remove(function () {
+  db.model('Employee').remove(function() {
     db.close(callback);
   });
 }
@@ -53,9 +53,9 @@ function clearData(db, callback) {
  * Test.
  */
 
-describe('aggregate: ', function () {
-  describe('append', function () {
-    it('(pipeline)', function (done) {
+describe('aggregate: ', function() {
+  describe('append', function() {
+    it('(pipeline)', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.append({$a: 1}, {$b: 2}, {$c: 3}), aggregate);
@@ -67,7 +67,7 @@ describe('aggregate: ', function () {
       done();
     });
 
-    it('supports array as single argument', function (done) {
+    it('supports array as single argument', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.append([{$a: 1}, {$b: 2}, {$c: 3}]), aggregate);
@@ -79,58 +79,58 @@ describe('aggregate: ', function () {
       done();
     });
 
-    it('throws if non-operator parameter is passed', function (done) {
+    it('throws if non-operator parameter is passed', function(done) {
       var aggregate = new Aggregate();
       var regexp = /Arguments must be aggregate pipeline operators/;
 
-      assert.throws(function () {
+      assert.throws(function() {
         aggregate.append({$a: 1}, 'string');
       }, regexp);
 
-      assert.throws(function () {
+      assert.throws(function() {
         aggregate.append({$a: 1}, ['array']);
       }, regexp);
 
-      assert.throws(function () {
+      assert.throws(function() {
         aggregate.append({$a: 1}, {a: 1});
       }, regexp);
 
-      assert.throws(function () {
+      assert.throws(function() {
         aggregate.append([{$a: 1}, {a: 1}]);
       }, regexp);
 
       done();
     });
 
-    it('does not throw when 0 args passed', function (done) {
+    it('does not throw when 0 args passed', function(done) {
       var aggregate = new Aggregate();
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         aggregate.append();
       });
 
       done();
     });
 
-    it('does not throw when empty array is passed as single argument', function (done) {
+    it('does not throw when empty array is passed as single argument', function(done) {
       var aggregate = new Aggregate();
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         aggregate.append([]);
       });
 
       done();
     });
 
-    it('called from constructor', function (done) {
+    it('called from constructor', function(done) {
       var aggregate = new Aggregate({$a: 1}, {$b: 2}, {$c: 3});
       assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}]);
       done();
     });
   });
 
-  describe('project', function () {
-    it('(object)', function (done) {
+  describe('project', function() {
+    it('(object)', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.project({a: 1, b: 1, c: 0}), aggregate);
@@ -142,7 +142,7 @@ describe('aggregate: ', function () {
       done();
     });
 
-    it('(string)', function (done) {
+    it('(string)', function(done) {
       var aggregate = new Aggregate();
 
       aggregate.project(' a b   -c  ');
@@ -154,8 +154,8 @@ describe('aggregate: ', function () {
       done();
     });
 
-    it('("a","b","c")', function (done) {
-      assert.throws(function () {
+    it('("a","b","c")', function(done) {
+      assert.throws(function() {
         var aggregate = new Aggregate();
         aggregate.project('a', 'b', 'c');
       }, /Invalid project/);
@@ -163,8 +163,8 @@ describe('aggregate: ', function () {
       done();
     });
 
-    it('["a","b","c"]', function (done) {
-      assert.throws(function () {
+    it('["a","b","c"]', function(done) {
+      assert.throws(function() {
         var aggregate = new Aggregate();
         aggregate.project(['a', 'b', 'c']);
       }, /Invalid project/);
@@ -173,8 +173,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('group', function () {
-    it('works', function (done) {
+  describe('group', function() {
+    it('works', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.group({a: 1, b: 2}), aggregate);
@@ -187,8 +187,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('skip', function () {
-    it('works', function (done) {
+  describe('skip', function() {
+    it('works', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.skip(42), aggregate);
@@ -201,8 +201,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('limit', function () {
-    it('works', function (done) {
+  describe('limit', function() {
+    it('works', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.limit(42), aggregate);
@@ -215,8 +215,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('unwind', function () {
-    it('("field")', function (done) {
+  describe('unwind', function() {
+    it('("field")', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.unwind('field'), aggregate);
@@ -234,8 +234,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('match', function () {
-    it('works', function (done) {
+  describe('match', function() {
+    it('works', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.match({a: 1}), aggregate);
@@ -248,8 +248,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('sort', function () {
-    it('(object)', function (done) {
+  describe('sort', function() {
+    it('(object)', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.sort({a: 1, b: 'asc', c: 'descending'}), aggregate);
@@ -261,7 +261,7 @@ describe('aggregate: ', function () {
       done();
     });
 
-    it('(string)', function (done) {
+    it('(string)', function(done) {
       var aggregate = new Aggregate();
 
       aggregate.sort(' a b   -c  ');
@@ -273,8 +273,8 @@ describe('aggregate: ', function () {
       done();
     });
 
-    it('("a","b","c")', function (done) {
-      assert.throws(function () {
+    it('("a","b","c")', function(done) {
+      assert.throws(function() {
         var aggregate = new Aggregate();
         aggregate.sort('a', 'b', 'c');
       }, /Invalid sort/);
@@ -282,8 +282,8 @@ describe('aggregate: ', function () {
       done();
     });
 
-    it('["a","b","c"]', function (done) {
-      assert.throws(function () {
+    it('["a","b","c"]', function(done) {
+      assert.throws(function() {
         var aggregate = new Aggregate();
         aggregate.sort(['a', 'b', 'c']);
       }, /Invalid sort/);
@@ -292,8 +292,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('near', function () {
-    it('works', function (done) {
+  describe('near', function() {
+    it('works', function(done) {
       var aggregate = new Aggregate();
 
       assert.equal(aggregate.near({a: 1}), aggregate);
@@ -305,7 +305,7 @@ describe('aggregate: ', function () {
       done();
     });
 
-    it('works with discriminators (gh-3304)', function (done) {
+    it('works with discriminators (gh-3304)', function(done) {
       var aggregate = new Aggregate();
       var stub = {
         schema: {
@@ -321,7 +321,7 @@ describe('aggregate: ', function () {
 
       assert.equal(aggregate.near({a: 1}), aggregate);
       // Run exec so we apply discriminator pipeline
-      assert.throws(function () {
+      assert.throws(function() {
         aggregate.exec();
       }, /Cannot read property 'aggregate' of undefined|Cannot call method 'aggregate' of undefined/);
       assert.deepEqual(aggregate._pipeline,
@@ -331,7 +331,7 @@ describe('aggregate: ', function () {
       aggregate._model = stub;
 
       aggregate.near({b: 2, query: {x: 1}});
-      assert.throws(function () {
+      assert.throws(function() {
         aggregate.exec();
       }, /Cannot read property 'aggregate' of undefined|Cannot call method 'aggregate' of undefined/);
       assert.deepEqual(aggregate._pipeline,
@@ -341,8 +341,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('lookup', function () {
-    it('works', function (done) {
+  describe('lookup', function() {
+    it('works', function(done) {
       var aggregate = new Aggregate();
       var obj = {
         from: 'users',
@@ -359,8 +359,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('sample', function () {
-    it('works', function (done) {
+  describe('sample', function() {
+    it('works', function(done) {
       var aggregate = new Aggregate();
 
       aggregate.sample(3);
@@ -371,8 +371,8 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('bind', function () {
-    it('works', function (done) {
+  describe('bind', function() {
+    it('works', function(done) {
       var aggregate = new Aggregate();
       var model = {foo: 42};
 
@@ -383,147 +383,147 @@ describe('aggregate: ', function () {
     });
   });
 
-  describe('exec', function () {
-    it('project', function (done) {
+  describe('exec', function() {
+    it('project', function(done) {
       var aggregate = new Aggregate();
 
-      setupData(function (db) {
+      setupData(function(db) {
         aggregate
             .model(db.model('Employee'))
             .project({sal: 1, sal_k: {$divide: ['$sal', 1000]}})
-            .exec(function (err, docs) {
+            .exec(function(err, docs) {
               assert.ifError(err);
-              docs.forEach(function (doc) {
+              docs.forEach(function(doc) {
                 assert.equal(doc.sal / 1000, doc.sal_k);
               });
 
-              clearData(db, function () {
+              clearData(db, function() {
                 done();
               });
             });
       });
     });
 
-    it('group', function (done) {
+    it('group', function(done) {
       var aggregate = new Aggregate();
 
-      setupData(function (db) {
+      setupData(function(db) {
         aggregate
             .model(db.model('Employee'))
             .group({_id: '$dept'})
-            .exec(function (err, docs) {
+            .exec(function(err, docs) {
               var depts;
 
               assert.ifError(err);
               assert.equal(docs.length, 2);
 
-              depts = docs.map(function (doc) {
+              depts = docs.map(function(doc) {
                 return doc._id;
               });
               assert.notEqual(depts.indexOf('sales'), -1);
               assert.notEqual(depts.indexOf('r&d'), -1);
 
-              clearData(db, function () {
+              clearData(db, function() {
                 done();
               });
             });
       });
     });
 
-    it('skip', function (done) {
+    it('skip', function(done) {
       var aggregate = new Aggregate();
 
-      setupData(function (db) {
+      setupData(function(db) {
         aggregate
             .model(db.model('Employee'))
             .skip(1)
-            .exec(function (err, docs) {
+            .exec(function(err, docs) {
               assert.ifError(err);
               assert.equal(docs.length, 3);
 
-              clearData(db, function () {
+              clearData(db, function() {
                 done();
               });
             });
       });
     });
 
-    it('limit', function (done) {
+    it('limit', function(done) {
       var aggregate = new Aggregate();
 
-      setupData(function (db) {
+      setupData(function(db) {
         aggregate
             .model(db.model('Employee'))
             .limit(3)
-            .exec(function (err, docs) {
+            .exec(function(err, docs) {
               assert.ifError(err);
               assert.equal(docs.length, 3);
 
-              clearData(db, function () {
+              clearData(db, function() {
                 done();
               });
             });
       });
     });
 
-    it('unwind', function (done) {
+    it('unwind', function(done) {
       var aggregate = new Aggregate();
 
-      setupData(function (db) {
+      setupData(function(db) {
         aggregate
             .model(db.model('Employee'))
             .unwind('customers')
-            .exec(function (err, docs) {
+            .exec(function(err, docs) {
               assert.ifError(err);
               assert.equal(docs.length, 5);
 
-              clearData(db, function () {
+              clearData(db, function() {
                 done();
               });
             });
       });
     });
 
-    it('match', function (done) {
+    it('match', function(done) {
       var aggregate = new Aggregate();
 
-      setupData(function (db) {
+      setupData(function(db) {
         aggregate
             .model(db.model('Employee'))
             .match({sal: {$gt: 15000}})
-            .exec(function (err, docs) {
+            .exec(function(err, docs) {
               assert.ifError(err);
               assert.equal(docs.length, 1);
 
-              clearData(db, function () {
+              clearData(db, function() {
                 done();
               });
             });
       });
     });
 
-    it('sort', function (done) {
+    it('sort', function(done) {
       var aggregate = new Aggregate();
 
-      setupData(function (db) {
+      setupData(function(db) {
         aggregate
             .model(db.model('Employee'))
             .sort('sal')
-            .exec(function (err, docs) {
+            .exec(function(err, docs) {
               assert.ifError(err);
               assert.equal(docs[0].sal, 14000);
 
-              clearData(db, function () {
+              clearData(db, function() {
                 done();
               });
             });
       });
     });
 
-    it('complex pipeline', function (done) {
+    it('complex pipeline', function(done) {
       var aggregate = new Aggregate();
 
-      setupData(function (db) {
+      setupData(function(db) {
         aggregate
             .model(db.model('Employee'))
             .match({sal: {$lt: 16000}})
@@ -531,22 +531,22 @@ describe('aggregate: ', function () {
             .project({emp: '$name', cust: '$customers'})
             .sort('-cust')
             .skip(2)
-            .exec(function (err, docs) {
+            .exec(function(err, docs) {
               assert.ifError(err);
               assert.equal(docs.length, 1);
               assert.equal(docs[0].cust, 'Gary');
               assert.equal(docs[0].emp, 'Bob');
 
-              clearData(db, function () {
+              clearData(db, function() {
                 done();
               });
             });
       });
     });
 
-    it('explain()', function (done) {
+    it('explain()', function(done) {
       var aggregate = new Aggregate();
-      start.mongodVersion(function (err, version) {
+      start.mongodVersion(function(err, version) {
         if (err) {
           done(err);
           return;
@@ -557,17 +557,17 @@ describe('aggregate: ', function () {
           return;
         }
 
-        setupData(function (db) {
+        setupData(function(db) {
           aggregate.
           model(db.model('Employee')).
           match({sal: {$lt: 16000}}).
-          explain(function (err1, output) {
+          explain(function(err1, output) {
             assert.ifError(err1);
             assert.ok(output);
             // make sure we got explain output
             assert.ok(output.stages);
 
-            clearData(db, function () {
+            clearData(db, function() {
               done();
             });
           });
@@ -575,14 +575,14 @@ describe('aggregate: ', function () {
       });
     });
 
-    describe('error when empty pipeline', function () {
-      it('without a callback', function (done) {
+    describe('error when empty pipeline', function() {
+      it('without a callback', function(done) {
         var agg = new Aggregate;
-        setupData(function (db) {
+        setupData(function(db) {
           agg.model(db.model('Employee'));
           var promise = agg.exec();
           assert.ok(promise instanceof mongoose.Promise);
-          promise.onResolve(function (err) {
+          promise.onResolve(function(err) {
             assert.ok(err);
             assert.equal(err.message, 'Aggregate has empty pipeline');
             done();
@@ -590,13 +590,13 @@ describe('aggregate: ', function () {
         });
       });
 
-      it('with a callback', function (done) {
+      it('with a callback', function(done) {
         var aggregate = new Aggregate();
         var callback;
 
-        setupData(function (db) {
+        setupData(function(db) {
           aggregate.model(db.model('Employee'));
-          callback = function (err) {
+          callback = function(err) {
             assert.ok(err);
             assert.equal(err.message, 'Aggregate has empty pipeline');
             done();
@@ -607,12 +607,12 @@ describe('aggregate: ', function () {
       });
     });
 
-    describe('error when not bound to a model', function () {
-      it('with callback', function (done) {
+    describe('error when not bound to a model', function() {
+      it('with callback', function(done) {
         var aggregate = new Aggregate();
 
         aggregate.skip(0);
-        assert.throws(function () {
+        assert.throws(function() {
           aggregate.exec();
         }, 'Aggregate not bound to any Model');
 
@@ -620,9 +620,9 @@ describe('aggregate: ', function () {
       });
     });
 
-    it('handles aggregation options', function (done) {
-      setupData(function (db) {
-        start.mongodVersion(function (err, version) {
+    it('handles aggregation options', function(done) {
+      setupData(function(db) {
+        start.mongodVersion(function(err, version) {
           if (err) {
             throw err;
           }
@@ -642,7 +642,7 @@ describe('aggregate: ', function () {
           }
 
           aggregate
-              .exec(function (err, docs) {
+              .exec(function(err, docs) {
                 assert.ifError(err);
                 assert.equal(1, docs.length);
                 assert.equal(docs[0].sal, 18000);
@@ -653,7 +653,7 @@ describe('aggregate: ', function () {
     });
   });
 
-  it('cursor (gh-3160)', function (done) {
+  it('cursor (gh-3160)', function(done) {
     var db = start();
 
     var MyModel = db.model('gh3160', {name: String});
@@ -661,7 +661,7 @@ describe('aggregate: ', function () {
     MyModel.
     aggregate([{$match: {name: 'test'}}]).
     cursor({async: true}).
-    exec(function (error, cursor) {
+    exec(function(error, cursor) {
       assert.ifError(error);
       assert.ok(cursor);
       db.close(done);
diff --git a/test/browser/document.test_.js b/test/browser/document.test_.js
index b6212b40cb2..c0c4be7f3ae 100644
--- a/test/browser/document.test_.js
+++ b/test/browser/document.test_.js
@@ -2,7 +2,7 @@ var Schema = mongoose.Schema,
     ObjectId = mongoose.Schema.Types.ObjectId;
 
 var em = new mongoose.Schema({title: String, body: String});
-em.virtual('works').get(function () {
+em.virtual('works').get(function() {
   return 'em virtual works';
 });
 
@@ -29,21 +29,21 @@ var schema = new Schema({
   date: Date
 });
 
-schema.virtual('nested.agePlus2').get(function () {
+schema.virtual('nested.agePlus2').get(function() {
   return this.get('nested.age') + 2;
 });
-schema.virtual('nested.setAge').set(function (v) {
+schema.virtual('nested.setAge').set(function(v) {
   this.set('nested.age', v);
 });
-schema.path('nested.path').get(function (v) {
+schema.path('nested.path').get(function(v) {
   return (this.get('nested.age') || '') + (v ? v : '');
 });
-schema.path('nested.setr').set(function (v) {
+schema.path('nested.setr').set(function(v) {
   return v + ' setter';
 });
 
-describe('browser:document', function () {
-  it('work', function (done) {
+describe('browser:document', function() {
+  it('work', function(done) {
     var obj = {
       test: 'test',
       oids: [],
@@ -122,10 +122,10 @@ describe('browser:document', function () {
   });
 });
 
-describe('browser:validate', function () {
-  it('works', function (done) {
+describe('browser:validate', function() {
+  it('works', function(done) {
     var called = false;
-    var validate = [function () {
+    var validate = [function() {
       called = true;
       return true;
     }, 'BAM'];
@@ -136,14 +136,14 @@ describe('browser:validate', function () {
     });
 
     var doc = new mongoose.Document({}, schema);
-    doc.validate(function (error) {
+    doc.validate(function(error) {
       assert.ok(!!error);
       assert.ok(called);
       assert.equal('Path `prop` is required.', error.errors['prop'].message);
       assert.equal('Path `nick` is required.', error.errors['nick'].message);
 
       doc.prop = 'Bacon';
-      doc.validate(function (error) {
+      doc.validate(function(error) {
         assert.ok(!error.errors['prop']);
         assert.equal('Path `nick` is required.', error.errors['nick'].message);
         done();
@@ -152,27 +152,27 @@ describe('browser:validate', function () {
   });
 });
 
-describe('#equals', function () {
-  describe('should work', function () {
+describe('#equals', function() {
+  describe('should work', function() {
     var S = new Schema({_id: String});
     var N = new Schema({_id: Number});
     var O = new Schema({_id: Schema.ObjectId});
     var B = new Schema({_id: mongoose.Schema.Types.Buffer});
     var M = new Schema({name: String}, {_id: false});
 
-    it('with string _ids', function (done) {
+    it('with string _ids', function(done) {
       var s1 = new mongoose.Document({_id: 'one'}, S);
       var s2 = new mongoose.Document({_id: 'one'}, S);
       assert.ok(s1.equals(s2));
       done();
     });
-    it('with number _ids', function (done) {
+    it('with number _ids', function(done) {
       var n1 = new mongoose.Document({_id: 0}, N);
       var n2 = new mongoose.Document({_id: 0}, N);
       assert.ok(n1.equals(n2));
       done();
     });
-    it('with ObjectId _ids', function (done) {
+    it('with ObjectId _ids', function(done) {
       var id = new mongoose.Types.ObjectId;
       var o1 = new mongoose.Document({_id: id}, O);
       var o2 = new mongoose.Document({_id: id}, O);
@@ -184,16 +184,16 @@ describe('#equals', function () {
       assert.ok(o1.equals(o2));
       done();
     });
-    it('with Buffer _ids', function (done) {
+    it('with Buffer _ids', function(done) {
       var n1 = new mongoose.Document({_id: 0}, B);
       var n2 = new mongoose.Document({_id: 0}, B);
       assert.ok(n1.equals(n2));
       done();
     });
-    it('with _id disabled (gh-1687)', function (done) {
+    it('with _id disabled (gh-1687)', function(done) {
       var m1 = new mongoose.Document({}, M);
       var m2 = new mongoose.Document({}, M);
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         m1.equals(m2);
       });
       done();
diff --git a/test/browser/example.test_.js b/test/browser/example.test_.js
index 1fe2eb9b91e..b31e5f72dd6 100644
--- a/test/browser/example.test_.js
+++ b/test/browser/example.test_.js
@@ -14,7 +14,7 @@
  *  
  *  ```
  */
-describe('Mongoose in the browser', function () {
+describe('Mongoose in the browser', function() {
   /**
    *  When you include the `mongoose.js` file in a script tag, mongoose will
    *  attach a `mongoose` object to the global `window`. This object includes
@@ -25,8 +25,8 @@ describe('Mongoose in the browser', function () {
    *  browser. In particular, it will *not* work in Internet Explorer 8
    *  or Safari 5.
    */
-  describe('Declaring schemas in the browser', function () {
-    it('allows you to use mongoose types', function () {
+  describe('Declaring schemas in the browser', function() {
+    it('allows you to use mongoose types', function() {
       var foodSchema = new mongoose.Schema({name: String});
       var breakfastSchema = new mongoose.Schema({
         foods: [foodSchema],
@@ -45,8 +45,8 @@ describe('Mongoose in the browser', function () {
    *  currently support any sort of querying, you're responsible for creating
    *  your own documents.
    */
-  describe('Validating documents in the browser', function () {
-    it('allows you to create a schema and use it to validate documents', function (done) {
+  describe('Validating documents in the browser', function() {
+    it('allows you to create a schema and use it to validate documents', function(done) {
       var schema = new mongoose.Schema({
         name: {type: String, required: true},
         quest: {type: String, match: /Holy Grail/i, required: true},
@@ -58,7 +58,7 @@ describe('Mongoose in the browser', function () {
        * then modify the document and call `validate()` to make sure it
        * passes validation rules. */
       var doc = new mongoose.Document({}, schema);
-      doc.validate(function (error) {
+      doc.validate(function(error) {
         assert.ok(error);
         assert.equal('Path `name` is required.', error.errors['name'].message);
         assert.equal('Path `quest` is required.', error.errors['quest'].message);
@@ -68,13 +68,13 @@ describe('Mongoose in the browser', function () {
         doc.name = 'Sir Lancelot of Camelot';
         doc.quest = 'To seek the holy grail';
         doc.favoriteColor = 'Blue';
-        doc.validate(function (error) {
+        doc.validate(function(error) {
           assert.ifError(error);
 
           doc.name = 'Sir Galahad of Camelot';
           doc.quest = 'I seek the grail'; // Invalid, must contain 'holy grail'
           doc.favoriteColor = 'Yellow'; // Invalid, not 'Red' or 'Blue'
-          doc.validate(function (error) {
+          doc.validate(function(error) {
             assert.ok(error);
             assert.ok(!error.errors['name']);
             assert.equal('Path `quest` is invalid (I seek the grail).',
diff --git a/test/browser/schema.test_.js b/test/browser/schema.test_.js
index d0e9ae3bf7b..573e19c904a 100644
--- a/test/browser/schema.test_.js
+++ b/test/browser/schema.test_.js
@@ -26,14 +26,14 @@ function TestDocument(obj) {
 TestDocument.prototype = Object.create(Document.prototype);
 TestDocument.prototype.constructor = TestDocument;
 
-describe('schema', function () {
-  it('can be created without the "new" keyword', function (done) {
+describe('schema', function() {
+  it('can be created without the "new" keyword', function(done) {
     var schema = mongoose.Schema({name: String});
     assert.ok(schema instanceof mongoose.Schema);
     done();
   });
 
-  it('supports different schematypes', function (done) {
+  it('supports different schematypes', function(done) {
     var Checkin = new mongoose.Schema({
       date: Date,
       location: {
@@ -117,7 +117,7 @@ describe('schema', function () {
     done();
   });
 
-  it('supports dot notation for path accessors', function (done) {
+  it('supports dot notation for path accessors', function(done) {
     var Racoon = new Schema({
       name: {type: String, enum: ['Edwald', 'Tobi']},
       age: Number
@@ -144,7 +144,7 @@ describe('schema', function () {
     done();
   });
 
-  it('allows paths nested > 2 levels', function (done) {
+  it('allows paths nested > 2 levels', function(done) {
     var Nested = new Schema({
       first: {
         second: {
@@ -156,18 +156,18 @@ describe('schema', function () {
     done();
   });
 
-  it('default definition', function (done) {
+  it('default definition', function(done) {
     var Test = new Schema({
       simple: {type: String, default: 'a'},
       array: {type: Array, default: [1, 2, 3, 4, 5]},
       arrayX: {type: Array, default: 9},
       arrayFn: {
-        type: Array, default: function () {
+        type: Array, default: function() {
           return [8];
         }
       },
       callback: {
-        type: Number, default: function () {
+        type: Number, default: function() {
           assert.equal('b', this.a);
           return '3';
         }
@@ -187,7 +187,7 @@ describe('schema', function () {
     done();
   });
 
-  it('Mixed defaults can be empty arrays', function (done) {
+  it('Mixed defaults can be empty arrays', function(done) {
     var Test = new Schema({
       mixed1: {type: Mixed, default: []},
       mixed2: {type: Mixed, default: Array}
@@ -200,8 +200,8 @@ describe('schema', function () {
     done();
   });
 
-  describe('casting', function () {
-    it('number', function (done) {
+  describe('casting', function() {
+    it('number', function(done) {
       var Tobi = new Schema({
         age: Number
       });
@@ -215,8 +215,8 @@ describe('schema', function () {
       done();
     });
 
-    describe('string', function () {
-      it('works', function (done) {
+    describe('string', function() {
+      it('works', function(done) {
         var Tobi = new Schema({
           nickname: String
         });
@@ -224,7 +224,7 @@ describe('schema', function () {
         function Test() {
         }
 
-        Test.prototype.toString = function () {
+        Test.prototype.toString = function() {
           return 'woot';
         };
 
@@ -248,7 +248,7 @@ describe('schema', function () {
       }); */
     });
 
-    it('date', function (done) {
+    it('date', function(done) {
       var Loki = new Schema({
         birth_date: {type: Date}
       });
@@ -259,7 +259,7 @@ describe('schema', function () {
       done();
     });
 
-    it('objectid', function (done) {
+    it('objectid', function(done) {
       var Loki = new Schema({
         owner: {type: ObjectId}
       });
@@ -277,7 +277,7 @@ describe('schema', function () {
       done();
     });
 
-    it('array', function (done) {
+    it('array', function(done) {
       var Loki = new Schema({
         oids: [ObjectId],
         dates: [Date],
@@ -335,7 +335,7 @@ describe('schema', function () {
       done();
     });
 
-    it('boolean', function (done) {
+    it('boolean', function(done) {
       var Animal = new Schema({
         isFerret: {type: Boolean, required: true}
       });
@@ -355,30 +355,30 @@ describe('schema', function () {
     });
   });
 
-  it('methods declaration', function (done) {
+  it('methods declaration', function(done) {
     var a = new Schema;
-    a.method('test', function () {
+    a.method('test', function() {
     });
     a.method({
-      a: function () {
+      a: function() {
       },
-      b: function () {
+      b: function() {
       }
     });
     assert.equal(3, Object.keys(a.methods).length);
     done();
   });
 
-  it('static declaration', function (done) {
+  it('static declaration', function(done) {
     var a = new Schema;
-    a.static('test', function () {
+    a.static('test', function() {
     });
     a.static({
-      a: function () {
+      a: function() {
       },
-      b: function () {
+      b: function() {
       },
-      c: function () {
+      c: function() {
       }
     });
 
@@ -386,8 +386,8 @@ describe('schema', function () {
     done();
   });
 
-  describe('setters', function () {
-    it('work', function (done) {
+  describe('setters', function() {
+    it('work', function(done) {
       function lowercase(v) {
         return v.toLowerCase();
       }
@@ -399,7 +399,7 @@ describe('schema', function () {
       assert.equal('woot', Tobi.path('name').applySetters('WOOT'));
       assert.equal(1, Tobi.path('name').setters.length);
 
-      Tobi.path('name').set(function (v) {
+      Tobi.path('name').set(function(v) {
         return v + 'WOOT';
       });
 
@@ -408,7 +408,7 @@ describe('schema', function () {
       done();
     });
 
-    it('order', function (done) {
+    it('order', function(done) {
       function extract(v) {
         return (v && v._id)
             ? v._id
@@ -429,7 +429,7 @@ describe('schema', function () {
       done();
     });
 
-    it('scope', function (done) {
+    it('scope', function(done) {
       function lowercase(v, self) {
         assert.equal('b', this.a);
         assert.equal('name', self.path);
@@ -444,7 +444,7 @@ describe('schema', function () {
       done();
     });
 
-    it('casting', function (done) {
+    it('casting', function(done) {
       function last(v) {
         assert.equal('number', typeof v);
         assert.equal(0, v);
@@ -464,8 +464,8 @@ describe('schema', function () {
       done();
     });
 
-    describe('array', function () {
-      it('object setters will be applied for each object in array', function (done) {
+    describe('array', function() {
+      it('object setters will be applied for each object in array', function(done) {
         var Tobi = new Schema({
           names: [{type: String, lowercase: true, trim: true}]
         });
@@ -477,8 +477,8 @@ describe('schema', function () {
       });
     });
 
-    describe('string', function () {
-      it('lowercase', function (done) {
+    describe('string', function() {
+      it('lowercase', function(done) {
         var Tobi = new Schema({
           name: {type: String, lowercase: true}
         });
@@ -487,7 +487,7 @@ describe('schema', function () {
         assert.equal('1977', Tobi.path('name').applySetters(1977));
         done();
       });
-      it('uppercase', function (done) {
+      it('uppercase', function(done) {
         var Tobi = new Schema({
           name: {type: String, uppercase: true}
         });
@@ -496,7 +496,7 @@ describe('schema', function () {
         assert.equal('1977', Tobi.path('name').applySetters(1977));
         done();
       });
-      it('trim', function (done) {
+      it('trim', function(done) {
         var Tobi = new Schema({
           name: {type: String, uppercase: true, trim: true}
         });
@@ -507,7 +507,7 @@ describe('schema', function () {
       });
     });
 
-    it('applying when none have been defined', function (done) {
+    it('applying when none have been defined', function(done) {
       var Tobi = new Schema({
         name: String
       });
@@ -516,7 +516,7 @@ describe('schema', function () {
       done();
     });
 
-    it('assignment of non-functions throw', function (done) {
+    it('assignment of non-functions throw', function(done) {
       var schema = new Schema({fun: String});
       var g;
 
@@ -532,8 +532,8 @@ describe('schema', function () {
     });
   });
 
-  describe('getters', function () {
-    it('work', function (done) {
+  describe('getters', function() {
+    it('work', function(done) {
       function woot(v) {
         return v + ' woot';
       }
@@ -546,7 +546,7 @@ describe('schema', function () {
       assert.equal('test woot', Tobi.path('name').applyGetters('test'));
       done();
     });
-    it('order', function (done) {
+    it('order', function(done) {
       function format(v) {
         return v
             ? '$' + v
@@ -560,7 +560,7 @@ describe('schema', function () {
       assert.equal('$30', Tobi.path('name').applyGetters(30, {a: 'b'}));
       done();
     });
-    it('scope', function (done) {
+    it('scope', function(done) {
       function woot(v, self) {
         assert.equal('b', this.a);
         assert.equal('name', self.path);
@@ -574,7 +574,7 @@ describe('schema', function () {
       assert.equal('yep', Tobi.path('name').applyGetters('YEP', {a: 'b'}));
       done();
     });
-    it('casting', function (done) {
+    it('casting', function(done) {
       function last(v) {
         assert.equal('number', typeof v);
         assert.equal(0, v);
@@ -593,7 +593,7 @@ describe('schema', function () {
       assert.equal('last', Tobi.path('name').applyGetters('woot'));
       done();
     });
-    it('applying when none have been defined', function (done) {
+    it('applying when none have been defined', function(done) {
       var Tobi = new Schema({
         name: String
       });
@@ -601,7 +601,7 @@ describe('schema', function () {
       assert.equal('woot', Tobi.path('name').applyGetters('woot'));
       done();
     });
-    it('assignment of non-functions throw', function (done) {
+    it('assignment of non-functions throw', function(done) {
       var schema = new Schema({fun: String});
       var g;
 
@@ -615,7 +615,7 @@ describe('schema', function () {
       assert.equal(g.message, 'A getter must be a function.');
       done();
     });
-    it('auto _id', function (done) {
+    it('auto _id', function(done) {
       var schema = new Schema({
         name: String
       });
@@ -644,7 +644,7 @@ describe('schema', function () {
       done();
     });
 
-    it('auto id', function (done) {
+    it('auto id', function(done) {
       var schema = new Schema({
         name: String
       });
@@ -674,31 +674,31 @@ describe('schema', function () {
     });
   });
 
-  describe('hooks', function () {
-    it('registration', function (done) {
+  describe('hooks', function() {
+    it('registration', function(done) {
       var Tobi = new Schema();
 
-      Tobi.pre('save', function () {
+      Tobi.pre('save', function() {
       });
       assert.equal(2, Tobi.callQueue.length);
 
-      Tobi.post('save', function () {
+      Tobi.post('save', function() {
       });
       assert.equal(3, Tobi.callQueue.length);
 
-      Tobi.pre('save', function () {
+      Tobi.pre('save', function() {
       });
       assert.equal(4, Tobi.callQueue.length);
       done();
     });
   });
 
-  describe('plugins', function () {
-    it('work', function (done) {
+  describe('plugins', function() {
+    it('work', function(done) {
       var Tobi = new Schema,
           called = false;
 
-      Tobi.plugin(function (schema) {
+      Tobi.plugin(function(schema) {
         assert.equal(schema, Tobi);
         called = true;
       });
@@ -708,8 +708,8 @@ describe('schema', function () {
     });
   });
 
-  describe('options', function () {
-    it('defaults are set', function (done) {
+  describe('options', function() {
+    it('defaults are set', function(done) {
       var Tobi = new Schema();
 
       assert.equal('object', typeof Tobi.options);
@@ -724,7 +724,7 @@ describe('schema', function () {
       done();
     });
 
-    it('setting', function (done) {
+    it('setting', function(done) {
       var Tobi = new Schema({}, {collection: 'users'});
 
       Tobi.set('a', 'b');
@@ -739,8 +739,8 @@ describe('schema', function () {
     });
   });
 
-  describe('virtuals', function () {
-    it('works', function (done) {
+  describe('virtuals', function() {
+    it('works', function(done) {
       var Contact = new Schema({
         firstName: String,
         lastName: String
@@ -748,10 +748,10 @@ describe('schema', function () {
 
       Contact
       .virtual('fullName')
-      .get(function () {
+      .get(function() {
         return this.get('firstName') + ' ' + this.get('lastName');
       })
-      .set(function (fullName) {
+      .set(function(fullName) {
         var split = fullName.split(' ');
         this.set('firstName', split[0]);
         this.set('lastName', split[1]);
@@ -761,25 +761,25 @@ describe('schema', function () {
       done();
     });
 
-    describe('id', function () {
-      it('default creation of id can be overridden (gh-298)', function (done) {
-        assert.doesNotThrow(function () {
+    describe('id', function() {
+      it('default creation of id can be overridden (gh-298)', function(done) {
+        assert.doesNotThrow(function() {
           new Schema({id: String});
         });
         done();
       });
-      it('disabling', function (done) {
+      it('disabling', function(done) {
         var schema = new Schema({name: String}, {noVirtualId: true});
         assert.strictEqual(undefined, schema.virtuals.id);
         done();
       });
     });
 
-    describe('getter', function () {
-      it('scope', function (done) {
+    describe('getter', function() {
+      it('scope', function(done) {
         var Tobi = new Schema;
 
-        Tobi.virtual('name').get(function (v, self) {
+        Tobi.virtual('name').get(function(v, self) {
           assert.equal('b', this.a);
           assert.equal('name', self.path);
           return v.toLowerCase();
@@ -790,11 +790,11 @@ describe('schema', function () {
       });
     });
 
-    describe('setter', function () {
-      it('scope', function (done) {
+    describe('setter', function() {
+      it('scope', function(done) {
         var Tobi = new Schema;
 
-        Tobi.virtual('name').set(function (v, self) {
+        Tobi.virtual('name').set(function(v, self) {
           assert.equal('b', this.a);
           assert.equal('name', self.path);
           return v.toLowerCase();
@@ -809,7 +809,7 @@ describe('schema', function () {
   // not other contexts
   // not #add()
 
-  it('debugging msgs', function (done) {
+  it('debugging msgs', function(done) {
     var err;
     try {
       new Schema({name: {first: null}});
@@ -826,8 +826,8 @@ describe('schema', function () {
     done();
   });
 
-  describe('construction', function () {
-    it('array of object literal missing a type is interpreted as DocumentArray', function (done) {
+  describe('construction', function() {
+    it('array of object literal missing a type is interpreted as DocumentArray', function(done) {
       var s = new Schema({
         arr: [
           {something: {type: String}}
@@ -840,7 +840,7 @@ describe('schema', function () {
       done();
     });
 
-    it('array of object literal with type.type is interpreted as DocumentArray', function (done) {
+    it('array of object literal with type.type is interpreted as DocumentArray', function(done) {
       var s = new Schema({
         arr: [
           {type: {type: String}}
@@ -853,7 +853,7 @@ describe('schema', function () {
       done();
     });
 
-    it('of nested schemas should throw (gh-700)', function (done) {
+    it('of nested schemas should throw (gh-700)', function(done) {
       var a = new Schema({title: String}),
           err;
 
@@ -868,7 +868,7 @@ describe('schema', function () {
       done();
     });
 
-    it('does not alter original argument (gh-1364)', function (done) {
+    it('does not alter original argument (gh-1364)', function(done) {
       var schema = {
         ids: [{type: Schema.ObjectId, ref: 'something'}],
         a: {type: Array},
diff --git a/test/browser/schema.validation.test_.js b/test/browser/schema.validation.test_.js
index 057fb8b60d5..1d2d0616231 100644
--- a/test/browser/schema.validation.test_.js
+++ b/test/browser/schema.validation.test_.js
@@ -9,28 +9,28 @@ var Schema = mongoose.Schema,
     Mixed = SchemaTypes.Mixed,
     DocumentObjectId = mongoose.Types.ObjectId;
 
-describe('schema', function () {
-  describe('validation', function () {
-    it('invalid arguments are rejected (1044)', function (done) {
-      assert.throws(function () {
+describe('schema', function() {
+  describe('validation', function() {
+    it('invalid arguments are rejected (1044)', function(done) {
+      assert.throws(function() {
         new Schema({
           simple: {type: String, validate: 'nope'}
         });
       }, /Invalid validator/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           simple: {type: String, validate: ['nope']}
         });
       }, /Invalid validator/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           simple: {type: String, validate: {nope: 1, msg: 'nope'}}
         });
       }, /Invalid validator/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           simple: {type: String, validate: [{nope: 1, msg: 'nope'}, 'nope']}
         });
@@ -39,7 +39,7 @@ describe('schema', function () {
       done();
     });
 
-    it('string enum', function (done) {
+    it('string enum', function(done) {
       var Test = new Schema({
         complex: {type: String, enum: ['a', 'b', undefined, 'c', null]},
         state: {type: String}
@@ -62,101 +62,101 @@ describe('schema', function () {
       assert.equal(Test.path('state').validators.length, 1);
       assert.deepEqual(Test.path('state').enumValues, ['opening', 'open', 'closing', 'closed']);
 
-      Test.path('complex').doValidate('x', function (err) {
+      Test.path('complex').doValidate('x', function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       // allow unsetting enums
-      Test.path('complex').doValidate(undefined, function (err) {
+      Test.path('complex').doValidate(undefined, function(err) {
         assert.ifError(err);
       });
 
-      Test.path('complex').doValidate(null, function (err) {
+      Test.path('complex').doValidate(null, function(err) {
         assert.ifError(err);
       });
 
-      Test.path('complex').doValidate('da', function (err) {
+      Test.path('complex').doValidate('da', function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('state').doValidate('x', function (err) {
+      Test.path('state').doValidate('x', function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('state').doValidate('opening', function (err) {
+      Test.path('state').doValidate('opening', function(err) {
         assert.ifError(err);
       });
 
-      Test.path('state').doValidate('open', function (err) {
+      Test.path('state').doValidate('open', function(err) {
         assert.ifError(err);
       });
 
       done();
     });
 
-    it('string regexp', function (done) {
+    it('string regexp', function(done) {
       var Test = new Schema({
         simple: {type: String, match: /[a-z]/}
       });
 
       assert.equal(1, Test.path('simple').validators.length);
 
-      Test.path('simple').doValidate('az', function (err) {
+      Test.path('simple').doValidate('az', function(err) {
         assert.ifError(err);
       });
 
       Test.path('simple').match(/[0-9]/);
       assert.equal(2, Test.path('simple').validators.length);
 
-      Test.path('simple').doValidate('12', function (err) {
+      Test.path('simple').doValidate('12', function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('simple').doValidate('a12', function (err) {
+      Test.path('simple').doValidate('a12', function(err) {
         assert.ifError(err);
       });
 
-      Test.path('simple').doValidate('', function (err) {
+      Test.path('simple').doValidate('', function(err) {
         assert.ifError(err);
       });
-      Test.path('simple').doValidate(null, function (err) {
+      Test.path('simple').doValidate(null, function(err) {
         assert.ifError(err);
       });
-      Test.path('simple').doValidate(undefined, function (err) {
+      Test.path('simple').doValidate(undefined, function(err) {
         assert.ifError(err);
       });
       Test.path('simple').validators = [];
       Test.path('simple').match(/[1-9]/);
-      Test.path('simple').doValidate(0, function (err) {
+      Test.path('simple').doValidate(0, function(err) {
         assert.ok(err instanceof ValidatorError);
       });
       done();
     });
 
-    it('number min and max', function (done) {
+    it('number min and max', function(done) {
       var Tobi = new Schema({
         friends: {type: Number, max: 15, min: 5}
       });
 
       assert.equal(Tobi.path('friends').validators.length, 2);
 
-      Tobi.path('friends').doValidate(10, function (err) {
+      Tobi.path('friends').doValidate(10, function(err) {
         assert.ifError(err);
       });
 
-      Tobi.path('friends').doValidate(100, function (err) {
+      Tobi.path('friends').doValidate(100, function(err) {
         assert.ok(err instanceof ValidatorError);
         assert.equal('friends', err.path);
         assert.equal('max', err.kind);
         assert.equal(100, err.value);
       });
 
-      Tobi.path('friends').doValidate(1, function (err) {
+      Tobi.path('friends').doValidate(1, function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       // null is allowed
-      Tobi.path('friends').doValidate(null, function (err) {
+      Tobi.path('friends').doValidate(null, function(err) {
         assert.ifError(err);
       });
 
@@ -167,8 +167,8 @@ describe('schema', function () {
       done();
     });
 
-    describe('required', function () {
-      it('string required', function (done) {
+    describe('required', function() {
+      it('string required', function(done) {
         var Test = new Schema({
           simple: String
         });
@@ -176,208 +176,208 @@ describe('schema', function () {
         Test.path('simple').required(true);
         assert.equal(Test.path('simple').validators.length, 1);
 
-        Test.path('simple').doValidate(null, function (err) {
+        Test.path('simple').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate(undefined, function (err) {
+        Test.path('simple').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('', function (err) {
+        Test.path('simple').doValidate('', function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('woot', function (err) {
+        Test.path('simple').doValidate('woot', function(err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('string conditional required', function (done) {
+      it('string conditional required', function(done) {
         var Test = new Schema({
           simple: String
         });
 
         var required = true,
-            isRequired = function () {
+            isRequired = function() {
               return required;
             };
 
         Test.path('simple').required(isRequired);
         assert.equal(Test.path('simple').validators.length, 1);
 
-        Test.path('simple').doValidate(null, function (err) {
+        Test.path('simple').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate(undefined, function (err) {
+        Test.path('simple').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('', function (err) {
+        Test.path('simple').doValidate('', function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('woot', function (err) {
+        Test.path('simple').doValidate('woot', function(err) {
           assert.ifError(err);
         });
 
         required = false;
 
-        Test.path('simple').doValidate(null, function (err) {
+        Test.path('simple').doValidate(null, function(err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate(undefined, function (err) {
+        Test.path('simple').doValidate(undefined, function(err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate('', function (err) {
+        Test.path('simple').doValidate('', function(err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate('woot', function (err) {
+        Test.path('simple').doValidate('woot', function(err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('number required', function (done) {
+      it('number required', function(done) {
         var Edwald = new Schema({
           friends: {type: Number, required: true}
         });
 
-        Edwald.path('friends').doValidate(null, function (err) {
+        Edwald.path('friends').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Edwald.path('friends').doValidate(undefined, function (err) {
+        Edwald.path('friends').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Edwald.path('friends').doValidate(0, function (err) {
+        Edwald.path('friends').doValidate(0, function(err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('date required', function (done) {
+      it('date required', function(done) {
         var Loki = new Schema({
           birth_date: {type: Date, required: true}
         });
 
-        Loki.path('birth_date').doValidate(null, function (err) {
+        Loki.path('birth_date').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('birth_date').doValidate(undefined, function (err) {
+        Loki.path('birth_date').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('birth_date').doValidate(new Date(), function (err) {
+        Loki.path('birth_date').doValidate(new Date(), function(err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('objectid required', function (done) {
+      it('objectid required', function(done) {
         var Loki = new Schema({
           owner: {type: ObjectId, required: true}
         });
 
-        Loki.path('owner').doValidate(new DocumentObjectId(), function (err) {
+        Loki.path('owner').doValidate(new DocumentObjectId(), function(err) {
           assert.ifError(err);
         });
 
-        Loki.path('owner').doValidate(null, function (err) {
+        Loki.path('owner').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('owner').doValidate(undefined, function (err) {
+        Loki.path('owner').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
         done();
       });
 
-      it('array required', function (done) {
+      it('array required', function(done) {
         var Loki = new Schema({
           likes: {type: Array, required: true}
         });
 
-        Loki.path('likes').doValidate(null, function (err) {
+        Loki.path('likes').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('likes').doValidate(undefined, function (err) {
+        Loki.path('likes').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('likes').doValidate([], function (err) {
+        Loki.path('likes').doValidate([], function(err) {
           assert.ok(err instanceof ValidatorError);
         });
         done();
       });
 
-      it('boolean required', function (done) {
+      it('boolean required', function(done) {
         var Animal = new Schema({
           isFerret: {type: Boolean, required: true}
         });
 
-        Animal.path('isFerret').doValidate(null, function (err) {
+        Animal.path('isFerret').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('isFerret').doValidate(undefined, function (err) {
+        Animal.path('isFerret').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('isFerret').doValidate(true, function (err) {
+        Animal.path('isFerret').doValidate(true, function(err) {
           assert.ifError(err);
         });
 
-        Animal.path('isFerret').doValidate(false, function (err) {
+        Animal.path('isFerret').doValidate(false, function(err) {
           assert.ifError(err);
         });
         done();
       });
 
-      it('mixed required', function (done) {
+      it('mixed required', function(done) {
         var Animal = new Schema({
           characteristics: {type: Mixed, required: true}
         });
 
-        Animal.path('characteristics').doValidate(null, function (err) {
+        Animal.path('characteristics').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('characteristics').doValidate(undefined, function (err) {
+        Animal.path('characteristics').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
         Animal.path('characteristics').doValidate({
           aggresive: true
-        }, function (err) {
+        }, function(err) {
           assert.ifError(err);
         });
 
-        Animal.path('characteristics').doValidate('none available', function (err) {
+        Animal.path('characteristics').doValidate('none available', function(err) {
           assert.ifError(err);
         });
         done();
       });
     });
 
-    describe('async', function () {
-      it('works', function (done) {
+    describe('async', function() {
+      it('works', function(done) {
         var executed = 0;
 
         function validator(value, fn) {
-          setTimeout(function () {
+          setTimeout(function() {
             executed++;
             fn(value === true);
             if (executed === 2) {
@@ -390,20 +390,20 @@ describe('schema', function () {
           ferret: {type: Boolean, validate: validator}
         });
 
-        Animal.path('ferret').doValidate(true, function (err) {
+        Animal.path('ferret').doValidate(true, function(err) {
           assert.ifError(err);
         });
 
-        Animal.path('ferret').doValidate(false, function (err) {
+        Animal.path('ferret').doValidate(false, function(err) {
           assert.ok(err instanceof Error);
         });
       });
 
-      it('multiple', function (done) {
+      it('multiple', function(done) {
         var executed = 0;
 
         function validator(value, fn) {
-          setTimeout(function () {
+          setTimeout(function() {
             executed++;
             fn(value === true);
             if (executed === 2) {
@@ -425,18 +425,18 @@ describe('schema', function () {
           }
         });
 
-        Animal.path('ferret').doValidate(true, function (err) {
+        Animal.path('ferret').doValidate(true, function(err) {
           assert.ifError(err);
         });
       });
 
-      it('scope', function (done) {
+      it('scope', function(done) {
         var called = false;
 
         function validator(value, fn) {
           assert.equal('b', this.a);
 
-          setTimeout(function () {
+          setTimeout(function() {
             called = true;
             fn(true);
           }, 5);
@@ -446,7 +446,7 @@ describe('schema', function () {
           ferret: {type: Boolean, validate: validator}
         });
 
-        Animal.path('ferret').doValidate(true, function (err) {
+        Animal.path('ferret').doValidate(true, function(err) {
           assert.ifError(err);
           assert.equal(true, called);
           done();
@@ -454,9 +454,9 @@ describe('schema', function () {
       });
     });
 
-    describe('messages', function () {
-      describe('are customizable', function () {
-        it('within schema definitions', function (done) {
+    describe('messages', function() {
+      describe('are customizable', function() {
+        it('within schema definitions', function(done) {
           var schema = new Schema({
             name: {type: String, enum: ['one', 'two']},
             myenum: {type: String, enum: {values: ['x'], message: 'enum validator failed for path: {PATH} with {VALUE}'}},
@@ -471,7 +471,7 @@ describe('schema', function () {
           });
 
           var a = new mongoose.Document({}, schema);
-          a.validate(function (err) {
+          a.validate(function(err) {
             assert.equal('Path `requiredString1` is required.', err.errors.requiredString1);
             assert.equal('oops, requiredString2 is missing. required', err.errors.requiredString2);
 
@@ -482,7 +482,7 @@ describe('schema', function () {
             a.numMin0 = a.numMin1 = 2;
             a.numMax0 = a.numMax1 = 30;
 
-            a.validate(function (err) {
+            a.validate(function(err) {
               assert.equal('`three` is not a valid enum value for path `name`.', err.errors.name);
               assert.equal('enum validator failed for path: myenum with y', err.errors.myenum);
               assert.equal('Path `matchString0` is invalid (no match).', err.errors.matchString0);
@@ -502,7 +502,7 @@ describe('schema', function () {
           });
         });
 
-        it('for custom validators', function (done) {
+        it('for custom validators', function(done) {
           function validate() {
             return false;
           }
@@ -513,7 +513,7 @@ describe('schema', function () {
 
           var doc = new mongoose.Document({x: [3, 4, 5, 6]}, schema);
 
-          doc.validate(function (err) {
+          doc.validate(function(err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('user defined', err.errors.x.kind);
             done();
@@ -522,9 +522,9 @@ describe('schema', function () {
       });
     });
 
-    describe('types', function () {
-      describe('are customizable', function () {
-        it('for single custom validators', function (done) {
+    describe('types', function() {
+      describe('are customizable', function() {
+        it('for single custom validators', function(done) {
           function validate() {
             return false;
           }
@@ -535,14 +535,14 @@ describe('schema', function () {
 
           var doc = new mongoose.Document({x: [3, 4, 5, 6]}, schema);
 
-          doc.validate(function (err) {
+          doc.validate(function(err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('customType', err.errors.x.kind);
             done();
           });
         });
 
-        it('for many custom validators', function (done) {
+        it('for many custom validators', function(done) {
           function validate() {
             return false;
           }
@@ -554,7 +554,7 @@ describe('schema', function () {
 
           var doc = new mongoose.Document({x: [3, 4, 5, 6]}, schema);
 
-          doc.validate(function (err) {
+          doc.validate(function(err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('customType', err.errors.x.kind);
             done();
@@ -563,8 +563,8 @@ describe('schema', function () {
       });
     });
 
-    describe('sync', function () {
-      it('works', function (done) {
+    describe('sync', function() {
+      it('works', function(done) {
         var executed = 0;
 
         function validator(value) {
@@ -584,7 +584,7 @@ describe('schema', function () {
         }
       });
 
-      it('multiple', function (done) {
+      it('multiple', function(done) {
         var executed = 0;
 
         function validator(value) {
@@ -612,7 +612,7 @@ describe('schema', function () {
         }
       });
 
-      it('scope', function (done) {
+      it('scope', function(done) {
         var called = false;
 
         function validator() {
@@ -634,7 +634,7 @@ describe('schema', function () {
         done();
       });
 
-      it('ingore async', function (done) {
+      it('ingore async', function(done) {
         function syncValidator(val) {
           return val === 'sync';
         }
@@ -643,7 +643,7 @@ describe('schema', function () {
 
         function asyncValidator(val, respond) {
           called = true;
-          setTimeout(function () {
+          setTimeout(function() {
             respond(val === 'async');
           }, 0);
         }
@@ -661,7 +661,7 @@ describe('schema', function () {
         done();
       });
 
-      it('subdoc', function (done) {
+      it('subdoc', function(done) {
         function syncValidator(val) {
           return val === 'sync';
         }
@@ -670,7 +670,7 @@ describe('schema', function () {
 
         function asyncValidator(val, respond) {
           called = true;
-          setTimeout(function () {
+          setTimeout(function() {
             respond(val === 'async');
           }, 0);
         }
@@ -751,7 +751,7 @@ describe('schema', function () {
         done();
       });
 
-      it('string enum', function (done) {
+      it('string enum', function(done) {
         var Test = new Schema({
           complex: {type: String, enum: ['a', 'b', undefined, 'c', null]},
           state: {type: String}
@@ -776,7 +776,7 @@ describe('schema', function () {
         done();
       });
 
-      it('string regexp', function (done) {
+      it('string regexp', function(done) {
         var Test = new Schema({
           simple: {type: String, match: /[a-z]/}
         });
@@ -799,7 +799,7 @@ describe('schema', function () {
         done();
       });
 
-      it('number min and max', function (done) {
+      it('number min and max', function(done) {
         var Tobi = new Schema({
           friends: {type: Number, max: 15, min: 5}
         });
@@ -819,8 +819,8 @@ describe('schema', function () {
         done();
       });
 
-      describe('required', function () {
-        it('string required', function (done) {
+      describe('required', function() {
+        it('string required', function(done) {
           var Test = new Schema({
             simple: String
           });
@@ -835,13 +835,13 @@ describe('schema', function () {
           done();
         });
 
-        it('string conditional required', function (done) {
+        it('string conditional required', function(done) {
           var Test = new Schema({
             simple: String
           });
 
           var required = true,
-              isRequired = function () {
+              isRequired = function() {
                 return required;
               };
 
@@ -862,7 +862,7 @@ describe('schema', function () {
           done();
         });
 
-        it('number required', function (done) {
+        it('number required', function(done) {
           var Edwald = new Schema({
             friends: {type: Number, required: true}
           });
@@ -874,7 +874,7 @@ describe('schema', function () {
           done();
         });
 
-        it('date required', function (done) {
+        it('date required', function(done) {
           var Loki = new Schema({
             birth_date: {type: Date, required: true}
           });
@@ -886,7 +886,7 @@ describe('schema', function () {
           done();
         });
 
-        it('objectid required', function (done) {
+        it('objectid required', function(done) {
           var Loki = new Schema({
             owner: {type: ObjectId, required: true}
           });
@@ -898,7 +898,7 @@ describe('schema', function () {
           done();
         });
 
-        it('array required', function (done) {
+        it('array required', function(done) {
           var Loki = new Schema({
             likes: {type: Array, required: true}
           });
@@ -910,7 +910,7 @@ describe('schema', function () {
           done();
         });
 
-        it('boolean required', function (done) {
+        it('boolean required', function(done) {
           var Animal = new Schema({
             isFerret: {type: Boolean, required: true}
           });
@@ -923,7 +923,7 @@ describe('schema', function () {
           done();
         });
 
-        it('mixed required', function (done) {
+        it('mixed required', function(done) {
           var Animal = new Schema({
             characteristics: {type: Mixed, required: true}
           });
diff --git a/test/browser/types.buffer.test_.js b/test/browser/types.buffer.test_.js
index e82714da886..ceb77870f88 100644
--- a/test/browser/types.buffer.test_.js
+++ b/test/browser/types.buffer.test_.js
@@ -8,8 +8,8 @@ var MongooseBuffer = mongoose.Types.Buffer;
  * Test.
  */
 
-describe('types.buffer', function () {
-  it('test that a mongoose buffer behaves and quacks like a buffer', function (done) {
+describe('types.buffer', function() {
+  it('test that a mongoose buffer behaves and quacks like a buffer', function(done) {
     var a = new MongooseBuffer;
 
     assert.ok(a.isMongooseBuffer);
@@ -27,8 +27,8 @@ describe('types.buffer', function () {
     done();
   });
 
-  describe('#toObject', function () {
-    it('retains custom subtypes', function (done) {
+  describe('#toObject', function() {
+    it('retains custom subtypes', function(done) {
       var buf = new MongooseBuffer(0);
       var out = buf.toObject(2);
       // validate the drivers Binary type output retains the option
diff --git a/test/browser/types.number.test_.js b/test/browser/types.number.test_.js
index e7854629a9b..932f2894ac6 100644
--- a/test/browser/types.number.test_.js
+++ b/test/browser/types.number.test_.js
@@ -8,20 +8,20 @@ var SchemaNumber = mongoose.Schema.Types.Number;
  * Test.
  */
 
-describe('types.number', function () {
-  it('an empty string casts to null', function (done) {
+describe('types.number', function() {
+  it('an empty string casts to null', function(done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.cast(''), null);
     done();
   });
 
-  it('a null number should castForQuery to null', function (done) {
+  it('a null number should castForQuery to null', function(done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.castForQuery(null), null);
     done();
   });
 
-  it('undefined throws number cast error', function (done) {
+  it('undefined throws number cast error', function(done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -33,7 +33,7 @@ describe('types.number', function () {
     done();
   });
 
-  it('array throws cast number error', function (done) {
+  it('array throws cast number error', function(done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -45,7 +45,7 @@ describe('types.number', function () {
     done();
   });
 
-  it('three throws cast number error', function (done) {
+  it('three throws cast number error', function(done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -57,7 +57,7 @@ describe('types.number', function () {
     done();
   });
 
-  it('{} throws cast number error', function (done) {
+  it('{} throws cast number error', function(done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -69,7 +69,7 @@ describe('types.number', function () {
     done();
   });
 
-  it('does not throw number cast error', function (done) {
+  it('does not throw number cast error', function(done) {
     var n = new SchemaNumber();
     var items = [1, '2', '0', null, '', new String('47'), new Number(5), Number(47), Number('09'), 0x12];
     var err;
diff --git a/test/browser/types.objectid.test_.js b/test/browser/types.objectid.test_.js
index 0fbb1f5b68f..da13d2b1442 100644
--- a/test/browser/types.objectid.test_.js
+++ b/test/browser/types.objectid.test_.js
@@ -1,10 +1,10 @@
-(function () {
+(function() {
   var ObjectId = mongoose.Types.ObjectId;
 
-  describe('types.objectid', function () {
-    it('Should Correctly convert ObjectId to itself', function (done) {
+  describe('types.objectid', function() {
+    it('Should Correctly convert ObjectId to itself', function(done) {
       var myObject, newObject;
-      var selfConvertion = function () {
+      var selfConvertion = function() {
         myObject = new ObjectId();
         newObject = ObjectId(myObject);
       };
@@ -14,7 +14,7 @@
       done();
     });
 
-    it('ObjectId should correctly create objects', function (done) {
+    it('ObjectId should correctly create objects', function(done) {
       try {
         ObjectId.createFromHexString('000000000000000000000001');
         ObjectId.createFromHexString('00000000000000000000001');
@@ -26,7 +26,7 @@
       done();
     });
 
-    it('ObjectId should correctly retrieve timestamp', function (done) {
+    it('ObjectId should correctly retrieve timestamp', function(done) {
       var testDate = new Date();
       var object1 = new ObjectId();
       assert.equal(Math.floor(testDate.getTime() / 1000), Math.floor(object1.getTimestamp().getTime() / 1000));
@@ -34,7 +34,7 @@
       done();
     });
 
-    it('ObjectId should have a correct cached representation of the hexString', function (done) {
+    it('ObjectId should have a correct cached representation of the hexString', function(done) {
       ObjectId.cacheHexString = true;
       var a = new ObjectId;
       var __id = a.__id;
@@ -69,14 +69,14 @@
       done();
     });
 
-    it('Should fail to create ObjectId due to illegal hex code', function (done) {
-      assert.throws(function () {
+    it('Should fail to create ObjectId due to illegal hex code', function(done) {
+      assert.throws(function() {
         new ObjectId('zzzzzzzzzzzzzzzzzzzzzzzz');
       });
       done();
     });
 
-    it('Should validate ObjectId', function (done) {
+    it('Should validate ObjectId', function(done) {
       assert.equal(false, ObjectId.isValid(null));
       assert.equal(false, ObjectId.isValid({}));
       assert.equal(false, ObjectId.isValid([]));
diff --git a/test/cast.test.js b/test/cast.test.js
index 5873dff11b6..77f8d919c16 100644
--- a/test/cast.test.js
+++ b/test/cast.test.js
@@ -6,32 +6,32 @@ var Schema = require('../lib/schema');
 var assert = require('assert');
 var cast = require('../lib/cast');
 
-describe('cast: ', function () {
-  describe('bitwise query operators: ', function () {
-    it('with a number', function (done) {
+describe('cast: ', function() {
+  describe('bitwise query operators: ', function() {
+    it('with a number', function(done) {
       var schema = new Schema({x: Buffer});
       assert.deepEqual(cast(schema, {x: {$bitsAllClear: 3}}),
           {x: {$bitsAllClear: 3}});
       done();
     });
 
-    it('with an array', function (done) {
+    it('with an array', function(done) {
       var schema = new Schema({x: Buffer});
       assert.deepEqual(cast(schema, {x: {$bitsAllSet: [2, '3']}}),
           {x: {$bitsAllSet: [2, 3]}});
       done();
     });
 
-    it('with a buffer', function (done) {
+    it('with a buffer', function(done) {
       var schema = new Schema({x: Number});
       assert.deepEqual(cast(schema, {x: {$bitsAnyClear: new Buffer([3])}}),
           {x: {$bitsAnyClear: new Buffer([3])}});
       done();
     });
 
-    it('throws when invalid', function (done) {
+    it('throws when invalid', function(done) {
       var schema = new Schema({x: Number});
-      assert.throws(function () {
+      assert.throws(function() {
         cast(schema, {x: {$bitsAnySet: 'Not a number'}});
       }, /Cast to number failed/);
       done();
diff --git a/test/collection.capped.test.js b/test/collection.capped.test.js
index b61091af753..5ed11d3a3fe 100644
--- a/test/collection.capped.test.js
+++ b/test/collection.capped.test.js
@@ -19,31 +19,31 @@ var coll = 'capped_' + random();
  * Test.
  */
 
-describe('collections: capped:', function () {
+describe('collections: capped:', function() {
   var db;
 
-  before(function () {
+  before(function() {
     db = start();
   });
 
-  after(function (done) {
+  after(function(done) {
     db.close(done);
   });
 
-  it('schemas should have option size', function (done) {
+  it('schemas should have option size', function(done) {
     assert.ok(capped.options.capped);
     assert.equal(1000, capped.options.capped.size);
     done();
   });
-  it('creation', function (done) {
+  it('creation', function(done) {
     var Capped = db.model('Capped', capped, coll);
-    Capped.collection.isCapped(function (err, isCapped) {
+    Capped.collection.isCapped(function(err, isCapped) {
       assert.ifError(err);
       assert.ok(isCapped, 'should create a capped collection');
 
       // use the existing capped collection in the db (no coll creation)
       var Capped2 = db.model('Capped2', capped, coll);
-      Capped2.collection.isCapped(function (err1, isCapped1) {
+      Capped2.collection.isCapped(function(err1, isCapped1) {
         assert.ifError(err1);
         assert.ok(isCapped1, 'should reuse the capped collection in the db');
         assert.equal(Capped.collection.name, Capped2.collection.name);
@@ -51,23 +51,23 @@ describe('collections: capped:', function () {
       });
     });
   });
-  it('creation using a number', function (done) {
+  it('creation using a number', function(done) {
     var schema = new Schema({key: 'string'}, {capped: 8192});
     var Capped = db.model('Capped3', schema);
-    Capped.collection.options(function (err, options) {
+    Capped.collection.options(function(err, options) {
       assert.ifError(err);
       assert.ok(options.capped, 'should create a capped collection');
       assert.equal(8192, options.size);
       done();
     });
   });
-  it('attempting to use existing non-capped collection as capped emits error', function (done) {
+  it('attempting to use existing non-capped collection as capped emits error', function(done) {
     db = start();
     var opts = {safe: true};
     var conn = 'capped_existing_' + random();
 
-    db.on('open', function () {
-      db.db.createCollection(conn, opts, function (err) {
+    db.on('open', function() {
+      db.db.createCollection(conn, opts, function(err) {
         if (err) {
           db.close();
         }
@@ -75,7 +75,7 @@ describe('collections: capped:', function () {
 
         var timer;
 
-        db.on('error', function (err1) {
+        db.on('error', function(err1) {
           clearTimeout(timer);
           db.close();
           assert.ok(/non-capped collection exists/.test(err1));
@@ -83,7 +83,7 @@ describe('collections: capped:', function () {
         });
 
         db.model('CappedExisting', capped, conn);
-        timer = setTimeout(function () {
+        timer = setTimeout(function() {
           db.close();
           throw new Error('capped test timeout');
         }, 900);
diff --git a/test/collection.test.js b/test/collection.test.js
index 95f47d09de7..8cb1c947ed3 100644
--- a/test/collection.test.js
+++ b/test/collection.test.js
@@ -3,8 +3,8 @@ var start = require('./common'),
     assert = require('assert'),
     Collection = require('../lib/collection');
 
-describe('collections:', function () {
-  it('should buffer commands until connection is established', function (done) {
+describe('collections:', function() {
+  it('should buffer commands until connection is established', function(done) {
     var db = mongoose.createConnection(),
         collection = db.collection('test-buffering-collection'),
         connected = false,
@@ -20,7 +20,7 @@ describe('collections:', function () {
       done();
     }
 
-    collection.insert({}, {safe: true}, function () {
+    collection.insert({}, {safe: true}, function() {
       assert.ok(connected);
       inserted = true;
       db.close();
@@ -28,13 +28,13 @@ describe('collections:', function () {
     });
 
     var uri = 'mongodb://localhost/mongoose_test';
-    db.open(process.env.MONGOOSE_TEST_URI || uri, function (err) {
+    db.open(process.env.MONGOOSE_TEST_URI || uri, function(err) {
       connected = !err;
       finish();
     });
   });
 
-  it('methods should that throw (unimplemented)', function (done) {
+  it('methods should that throw (unimplemented)', function(done) {
     var collection = new Collection('test', mongoose.connection),
         thrown = false;
 
diff --git a/test/colors.js b/test/colors.js
index b2a2c40cc29..6821c198927 100644
--- a/test/colors.js
+++ b/test/colors.js
@@ -24,7 +24,7 @@ var test = new Schema({
 });
 
 function TestDoc(schema) {
-  var Subdocument = function () {
+  var Subdocument = function() {
     EmbeddedDocument.call(this, {}, new DocumentArray);
   };
 
@@ -47,20 +47,20 @@ function TestDoc(schema) {
  * Test.
  */
 
-describe('debug: colors', function () {
+describe('debug: colors', function() {
   var db;
   var Test;
 
-  before(function () {
+  before(function() {
     db = start();
     Test = db.model('Test', test, 'TEST');
   });
 
-  after(function (done) {
+  after(function(done) {
     db.close(done);
   });
 
-  it('Document', function (done) {
+  it('Document', function(done) {
     var date = new Date();
 
     Test.create([{
@@ -75,12 +75,12 @@ describe('debug: colors', function () {
       string: 'zxcvbn',
       number: 789,
       date: date
-    }], function (err) {
+    }], function(err) {
       assert.ifError(err);
       Test
           .find()
           .lean(false)
-          .exec(function (err, docs) {
+          .exec(function(err, docs) {
             assert.ifError(err);
 
             var colorfull = require('util').inspect(docs, {
@@ -102,7 +102,7 @@ describe('debug: colors', function () {
     });
   });
 
-  it('MongooseDocumentArray', function () {
+  it('MongooseDocumentArray', function() {
     var Subdocument = TestDoc();
 
     var sub1 = new Subdocument();
diff --git a/test/common.js b/test/common.js
index 28eeea522fd..e9eedf757a6 100644
--- a/test/common.js
+++ b/test/common.js
@@ -30,10 +30,10 @@ if (process.env.D === '1') {
   'distinct',
   'isCapped',
   'options'
-].forEach(function (method) {
+].forEach(function(method) {
   var oldMethod = Collection.prototype[method];
 
-  Collection.prototype[method] = function () {
+  Collection.prototype[method] = function() {
     queryCount++;
     return oldMethod.apply(this, arguments);
   };
@@ -45,7 +45,7 @@ if (process.env.D === '1') {
 
 var oldOnOpen = Collection.prototype.onOpen;
 
-Collection.prototype.onOpen = function () {
+Collection.prototype.onOpen = function() {
   opened++;
   return oldOnOpen.apply(this, arguments);
 };
@@ -56,7 +56,7 @@ Collection.prototype.onOpen = function () {
 
 var oldOnClose = Collection.prototype.onClose;
 
-Collection.prototype.onClose = function () {
+Collection.prototype.onClose = function() {
   closed++;
   return oldOnClose.apply(this, arguments);
 };
@@ -68,7 +68,7 @@ Collection.prototype.onClose = function () {
  * @api private
  */
 
-module.exports = function (options) {
+module.exports = function(options) {
   options || (options = {});
   var uri;
 
@@ -88,7 +88,7 @@ module.exports = function (options) {
     return conn;
   }
 
-  conn.on('error', function (err) {
+  conn.on('error', function(err) {
     assert.ok(err);
   });
 
@@ -111,20 +111,20 @@ module.exports.mongoose = mongoose;
  * expose mongod version helper
  */
 
-module.exports.mongodVersion = function (cb) {
+module.exports.mongodVersion = function(cb) {
   var db = module.exports();
   db.on('error', cb);
 
-  db.on('open', function () {
+  db.on('open', function() {
     var admin = db.db.admin();
-    admin.serverStatus(function (err, info) {
+    admin.serverStatus(function(err, info) {
       if (err) {
         return cb(err);
       }
-      var version = info.version.split('.').map(function (n) {
+      var version = info.version.split('.').map(function(n) {
         return parseInt(n, 10);
       });
-      db.close(function () {
+      db.close(function() {
         cb(null, version);
       });
     });
@@ -133,11 +133,11 @@ module.exports.mongodVersion = function (cb) {
 
 function dropDBs(done) {
   var db = module.exports();
-  db.once('open', function () {
+  db.once('open', function() {
     // drop the default test database
-    db.db.dropDatabase(function () {
+    db.db.dropDatabase(function() {
       var db2 = db.useDb('mongoose-test-2');
-      db2.db.dropDatabase(function () {
+      db2.db.dropDatabase(function() {
         // drop mongos test db if exists
         var mongos = process.env.MONGOOSE_MULTI_MONGOS_TEST_URI;
         if (!mongos) {
@@ -146,7 +146,7 @@ function dropDBs(done) {
 
 
         var db = mongoose.connect(mongos, {mongos: true});
-        db.once('open', function () {
+        db.once('open', function() {
           db.db.dropDatabase(done);
         });
       });
@@ -154,11 +154,11 @@ function dropDBs(done) {
   });
 }
 
-before(function (done) {
+before(function(done) {
   this.timeout(10 * 1000);
   dropDBs(done);
 });
-after(function (done) {
+after(function(done) {
   // DropDBs can be extraordinarily slow on 3.2
   this.timeout(120 * 1000);
   dropDBs(done);
diff --git a/test/connection.auth.test.js b/test/connection.auth.test.js
index af3e8b8ec66..ab4dbaa5778 100644
--- a/test/connection.auth.test.js
+++ b/test/connection.auth.test.js
@@ -2,11 +2,11 @@ var start = require('./common');
 var mongoose = start.mongoose;
 var assert = require('assert');
 
-describe('connection:', function () {
-  describe('supports authSource', function () {
-    it('in querystring', function (done) {
+describe('connection:', function() {
+  describe('supports authSource', function() {
+    it('in querystring', function(done) {
       var conn = mongoose.createConnection();
-      conn._open = function () {
+      conn._open = function() {
         assert.ok(conn.options);
         assert.ok(conn.options.auth);
         assert.equal('users', conn.options.auth.authSource);
@@ -15,9 +15,9 @@ describe('connection:', function () {
       conn.open(start.uri + '?authSource=users');
     });
 
-    it('passed as an option', function (done) {
+    it('passed as an option', function(done) {
       var conn = mongoose.createConnection();
-      conn._open = function () {
+      conn._open = function() {
         assert.ok(conn.options);
         assert.ok(conn.options.auth);
         assert.equal('users', conn.options.auth.authSource);
diff --git a/test/connection.reconnect.test.js b/test/connection.reconnect.test.js
index 0c0292ac251..124f6186c4d 100644
--- a/test/connection.reconnect.test.js
+++ b/test/connection.reconnect.test.js
@@ -1,8 +1,8 @@
 var start = require('./common');
 var mongoose = start.mongoose;
 
-describe('connection: manual reconnect with authReconnect: false', function () {
-  it('should continue processing queries/writes', function (done) {
+describe('connection: manual reconnect with authReconnect: false', function() {
+  it('should continue processing queries/writes', function(done) {
     // connect to mongod
     // perform writes/queries
     // take mongod down
@@ -19,15 +19,15 @@ describe('connection: manual reconnect with authReconnect: false', function () {
     var open = false;
     var times = 0;
 
-    db.on('open', function () {
+    db.on('open', function() {
       ++times;
       open = true;
       hit();
     });
 
-    db.on('disconnected', function () {
+    db.on('disconnected', function() {
       open = false;
-      setTimeout(function () {
+      setTimeout(function() {
         db.open(start.uri, {server: {auto_reconnect: false}});
       }, 30);
     });
@@ -36,11 +36,11 @@ describe('connection: manual reconnect with authReconnect: false', function () {
       if (!open) {
         return;
       }
-      M.create({name: times}, function (err, doc) {
+      M.create({name: times}, function(err, doc) {
         if (err) {
           return complete(err);
         }
-        M.findOne({_id: doc._id}, function (err) {
+        M.findOne({_id: doc._id}, function(err) {
           if (err) {
             return complete(err);
           }
diff --git a/test/connection.test.js b/test/connection.test.js
index cbdfcead4fd..cbaa75986e4 100644
--- a/test/connection.test.js
+++ b/test/connection.test.js
@@ -12,17 +12,17 @@ var start = require('./common'),
  * Test.
  */
 
-describe('connections:', function () {
-  it('should allow closing a closed connection', function (done) {
+describe('connections:', function() {
+  it('should allow closing a closed connection', function(done) {
     var db = mongoose.createConnection();
 
     assert.equal(0, db.readyState);
     db.close(done);
   });
 
-  it('should accept mongodb://localhost/fake', function (done) {
+  it('should accept mongodb://localhost/fake', function(done) {
     var db = mongoose.createConnection('mongodb://localhost/fake');
-    db.on('error', function () {
+    db.on('error', function() {
     });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
@@ -37,9 +37,9 @@ describe('connections:', function () {
     db.close(done);
   });
 
-  it('should accept replicaSet query param', function (done) {
+  it('should accept replicaSet query param', function(done) {
     var db = mongoose.createConnection('mongodb://localhost/fake?replicaSet=rs0');
-    db.on('error', function () {
+    db.on('error', function() {
     });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
@@ -57,9 +57,9 @@ describe('connections:', function () {
     done();
   });
 
-  it('should accept mongodb://localhost:27000/fake', function (done) {
+  it('should accept mongodb://localhost:27000/fake', function(done) {
     var db = mongoose.createConnection('mongodb://localhost:27000/fake');
-    db.on('error', function () {
+    db.on('error', function() {
     });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
@@ -70,9 +70,9 @@ describe('connections:', function () {
     done();
   });
 
-  it('should accept mongodb://aaron:psw@localhost:27000/fake', function (done) {
+  it('should accept mongodb://aaron:psw@localhost:27000/fake', function(done) {
     var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake');
-    db.on('error', function () {
+    db.on('error', function() {
     });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
@@ -88,9 +88,9 @@ describe('connections:', function () {
     done();
   });
 
-  it('should accept mongodb://aaron:psw@localhost:27000/fake with db options', function (done) {
+  it('should accept mongodb://aaron:psw@localhost:27000/fake with db options', function(done) {
     var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {db: {forceServerObjectId: true}});
-    db.on('error', function () {
+    db.on('error', function() {
     });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
@@ -101,9 +101,9 @@ describe('connections:', function () {
     done();
   });
 
-  it('should accept mongodb://aaron:psw@localhost:27000/fake with server options', function (done) {
+  it('should accept mongodb://aaron:psw@localhost:27000/fake with server options', function(done) {
     var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {server: {auto_reconnect: false}});
-    db.on('error', function () {
+    db.on('error', function() {
     });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
@@ -114,9 +114,9 @@ describe('connections:', function () {
     done();
   });
 
-  it('should accept unix domain sockets', function (done) {
+  it('should accept unix domain sockets', function(done) {
     var db = mongoose.createConnection('mongodb://aaron:psw@/tmp/mongodb-27017.sock/fake', {server: {auto_reconnect: false}});
-    db.on('error', function () {
+    db.on('error', function() {
     });
     assert.equal('object', typeof db.options);
     assert.equal('object', typeof db.options.server);
@@ -131,7 +131,7 @@ describe('connections:', function () {
     done();
   });
 
-  describe('re-opening a closed connection', function () {
+  describe('re-opening a closed connection', function() {
     var mongos = process.env.MONGOOSE_SHARD_TEST_URI;
     if (!mongos) {
       return;
@@ -144,11 +144,11 @@ describe('connections:', function () {
     repl2.push(repl2.shift());
     repl2 = 'mongodb://' + repl2.join(',');
 
-    describe('with different host/port', function () {
-      it('non-replica set', function (done) {
+    describe('with different host/port', function() {
+      it('non-replica set', function(done) {
         var db = mongoose.createConnection();
 
-        db.open(mongod, function (err) {
+        db.open(mongod, function(err) {
           if (err) {
             return done(err);
           }
@@ -156,12 +156,12 @@ describe('connections:', function () {
           var port1 = db.port;
           var db1 = db.db;
 
-          db.close(function (err) {
+          db.close(function(err) {
             if (err) {
               return done(err);
             }
 
-            db.open(mongos, function (err) {
+            db.open(mongos, function(err) {
               if (err) {
                 return done(err);
               }
@@ -173,11 +173,11 @@ describe('connections:', function () {
               var port2 = db.port;
               var db2 = db.db;
 
-              db.close(function (err) {
+              db.close(function(err) {
                 if (err) {
                   return done(err);
                 }
-                db.open(mongod, function (err) {
+                db.open(mongod, function(err) {
                   if (err) {
                     return done(err);
                   }
@@ -194,10 +194,10 @@ describe('connections:', function () {
         });
       });
 
-      it('replica set', function (done) {
+      it('replica set', function(done) {
         var db = mongoose.createConnection();
 
-        db.openSet(repl1, function (err) {
+        db.openSet(repl1, function(err) {
           if (err) {
             return done(err);
           }
@@ -205,17 +205,17 @@ describe('connections:', function () {
           var hosts = db.hosts.slice();
           var db1 = db.db;
 
-          db.close(function (err) {
+          db.close(function(err) {
             if (err) {
               return done(err);
             }
 
-            db.openSet(repl2, function (err) {
+            db.openSet(repl2, function(err) {
               if (err) {
                 return done(err);
               }
 
-              db.hosts.forEach(function (host, i) {
+              db.hosts.forEach(function(host, i) {
                 assert.notEqual(host.port, hosts[i].port);
               });
               assert.ok(db1 !== db.db);
@@ -223,17 +223,17 @@ describe('connections:', function () {
               hosts = db.hosts.slice();
               var db2 = db.db;
 
-              db.close(function (err) {
+              db.close(function(err) {
                 if (err) {
                   return done(err);
                 }
 
-                db.openSet(repl1, function (err) {
+                db.openSet(repl1, function(err) {
                   if (err) {
                     return done(err);
                   }
 
-                  db.hosts.forEach(function (host, i) {
+                  db.hosts.forEach(function(host, i) {
                     assert.notEqual(host.port, hosts[i].port);
                   });
                   assert.ok(db2 !== db.db);
@@ -249,10 +249,10 @@ describe('connections:', function () {
     });
   });
 
-  describe('should accept separated args with options', function () {
-    it('works', function (done) {
+  describe('should accept separated args with options', function() {
+    it('works', function(done) {
       var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, {server: {auto_reconnect: true}});
-      db.on('error', function () {
+      db.on('error', function() {
       });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -265,7 +265,7 @@ describe('connections:', function () {
       db.close();
 
       db = mongoose.createConnection('127.0.0.1', 'faker', {blah: 1});
-      db.on('error', function () {
+      db.on('error', function() {
       });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -280,9 +280,9 @@ describe('connections:', function () {
       done();
     });
 
-    it('including user/pass', function (done) {
+    it('including user/pass', function(done) {
       var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'aaron', pass: 'psw'});
-      db.on('error', function () {
+      db.on('error', function() {
       });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -298,9 +298,9 @@ describe('connections:', function () {
       done();
     });
 
-    it('but fails when passing user and no pass with standard authentication', function (done) {
+    it('but fails when passing user and no pass with standard authentication', function(done) {
       var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'no_pass'});
-      db.on('error', function () {
+      db.on('error', function() {
       });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -316,9 +316,9 @@ describe('connections:', function () {
       done();
     });
 
-    it('but passes when passing user and no pass with the MONGODB-X509 authMechanism', function (done) {
+    it('but passes when passing user and no pass with the MONGODB-X509 authMechanism', function(done) {
       var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'no_pass', auth: {authMechanism: 'MONGODB-X509'}});
-      db.on('error', function () {
+      db.on('error', function() {
       });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -335,10 +335,10 @@ describe('connections:', function () {
     });
   });
 
-  describe('should accept separated args without options', function () {
-    it('works', function (done) {
+  describe('should accept separated args without options', function() {
+    it('works', function(done) {
       var db = mongoose.createConnection('127.0.0.1', 'faker', 28001);
-      db.on('error', function () {
+      db.on('error', function() {
       });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -351,7 +351,7 @@ describe('connections:', function () {
       db.close();
 
       db = mongoose.createConnection('127.0.0.1', 'faker');
-      db.on('error', function () {
+      db.on('error', function() {
       });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -364,9 +364,9 @@ describe('connections:', function () {
       db.close();
       done();
     });
-    it('and accept user/pass in hostname', function (done) {
+    it('and accept user/pass in hostname', function(done) {
       var db = mongoose.createConnection('aaron:psw@localhost', 'fake', 27000);
-      db.on('error', function () {
+      db.on('error', function() {
       });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -383,9 +383,9 @@ describe('connections:', function () {
     });
   });
 
-  describe('querystring options', function () {
-    describe('for replica sets', function () {
-      it('work', function (done) {
+  describe('querystring options', function() {
+    describe('for replica sets', function() {
+      it('work', function(done) {
         var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2'
             + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
             + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true'
@@ -394,7 +394,7 @@ describe('connections:', function () {
             + 'dc:ny,rack:1&readPreferenceTags=dc:sf';
 
         var db = mongoose.createConnection(conn);
-        db.on('error', function () {
+        db.on('error', function() {
         });
         db.close();
         assert.equal('object', typeof db.options);
@@ -427,7 +427,7 @@ describe('connections:', function () {
         assert.equal(false, db.options.db.forceServerObjectId);
         done();
       });
-      it('mixed with passed options', function (done) {
+      it('mixed with passed options', function(done) {
         var conn = 'mongodb://localhost/fake?poolSize=2'
             + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
             + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true'
@@ -436,7 +436,7 @@ describe('connections:', function () {
             + 'dc:ny,rack:1&readPreferenceTags=dc:sf';
 
         var db = mongoose.createConnection(conn, {server: {poolSize: 3, auto_reconnect: false}});
-        db.on('error', function () {
+        db.on('error', function() {
         });
         db.close();
         assert.equal('object', typeof db.options);
@@ -471,8 +471,8 @@ describe('connections:', function () {
         done();
       });
     });
-    describe('for non replica sets', function () {
-      it('work', function (done) {
+    describe('for non replica sets', function() {
+      it('work', function(done) {
         var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2'
             + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
             + '&retries=10&reconnectWait=5&readSecondary=true'
@@ -480,7 +480,7 @@ describe('connections:', function () {
             + '&wtimeoutMS=80&';
 
         var db = mongoose.createConnection(conn);
-        db.on('error', function () {
+        db.on('error', function() {
         });
         db.close();
         assert.equal('object', typeof db.options);
@@ -510,14 +510,14 @@ describe('connections:', function () {
         assert.equal(false, db.options.db.forceServerObjectId);
         done();
       });
-      it('mixed with passed options', function (done) {
+      it('mixed with passed options', function(done) {
         var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2'
             + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12'
             + '&retries=10&reconnectWait=5&readSecondary=true'
             + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true';
 
         var db = mongoose.createConnection(conn, {db: {w: 3, wtimeoutMS: 80}});
-        db.on('error', function () {
+        db.on('error', function() {
         });
         db.close();
         assert.equal('object', typeof db.options);
@@ -550,9 +550,9 @@ describe('connections:', function () {
     });
   });
 
-  describe('missing protocols', function () {
-    it('are allowed with replsets', function (done) {
-      var conn = mongoose.createConnection('localhost:12345,127.0.0.1:14326?replicaSet=bacon', function (err) {
+  describe('missing protocols', function() {
+    it('are allowed with replsets', function(done) {
+      var conn = mongoose.createConnection('localhost:12345,127.0.0.1:14326?replicaSet=bacon', function(err) {
         // force missing db error so we don't actually connect.
         assert.ok(err);
       });
@@ -562,9 +562,9 @@ describe('connections:', function () {
       setTimeout(done, 10);
     });
 
-    it('are allowed with single connections', function (done) {
+    it('are allowed with single connections', function(done) {
       var conn = mongoose.createConnection();
-      conn.doOpen = function () {
+      conn.doOpen = function() {
       };
       conn.open('localhost:12345/woot');
       assert.deepEqual('localhost', conn.host);
@@ -573,12 +573,12 @@ describe('connections:', function () {
     });
   });
 
-  describe('connect callbacks', function () {
-    it('execute with user:pwd connection strings', function (done) {
-      var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {server: {auto_reconnect: true}}, function () {
+  describe('connect callbacks', function() {
+    it('execute with user:pwd connection strings', function(done) {
+      var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {server: {auto_reconnect: true}}, function() {
         done();
       });
-      db.on('error', function (err) {
+      db.on('error', function(err) {
         assert.ok(err);
       });
       assert.equal('object', typeof db.options);
@@ -588,10 +588,10 @@ describe('connections:', function () {
       assert.equal(false, db.options.db.forceServerObjectId);
       db.close();
     });
-    it('execute without user:pwd connection strings', function (done) {
-      var db = mongoose.createConnection('mongodb://localhost/fake', function () {
+    it('execute without user:pwd connection strings', function(done) {
+      var db = mongoose.createConnection('mongodb://localhost/fake', function() {
       });
-      db.on('error', function (err) {
+      db.on('error', function(err) {
         assert.ok(err);
       });
       assert.equal('object', typeof db.options);
@@ -606,16 +606,16 @@ describe('connections:', function () {
       db.close();
       setTimeout(done, 10);
     });
-    it('should return an error if malformed uri passed', function (done) {
-      var db = mongoose.createConnection('mongodb:///fake', function (err) {
+    it('should return an error if malformed uri passed', function(done) {
+      var db = mongoose.createConnection('mongodb:///fake', function(err) {
         assert.ok(/Missing hostname/.test(err.message));
         done();
       });
       db.close();
       assert.ok(!db.options);
     });
-    it('should use admin db if not specified and user/pass specified', function (done) {
-      var db = mongoose.createConnection('mongodb://u:p@localhost', function () {
+    it('should use admin db if not specified and user/pass specified', function(done) {
+      var db = mongoose.createConnection('mongodb://u:p@localhost', function() {
         done();
       });
       assert.equal('object', typeof db.options);
@@ -628,8 +628,8 @@ describe('connections:', function () {
       assert.equal(27017, db.port);
       db.close();
     });
-    it('should fire when individual args are passed', function (done) {
-      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, {server: {auto_reconnect: false}}, function () {
+    it('should fire when individual args are passed', function(done) {
+      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, {server: {auto_reconnect: false}}, function() {
         done();
       });
       assert.equal('object', typeof db.options);
@@ -642,8 +642,8 @@ describe('connections:', function () {
       assert.equal(28000, db.port);
       db.close();
     });
-    it('should fire when no options are passed', function (done) {
-      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, function () {
+    it('should fire when no options are passed', function(done) {
+      var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, function() {
         done();
       });
       assert.equal('object', typeof db.options);
@@ -656,7 +656,7 @@ describe('connections:', function () {
       assert.equal(28000, db.port);
       db.close();
     });
-    it('should fire when default port utilized', function (done) {
+    it('should fire when default port utilized', function(done) {
       var db = mongoose.createConnection('127.0.0.1', 'faker', done);
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -670,20 +670,20 @@ describe('connections:', function () {
     });
   });
 
-  describe('errors', function () {
-    it('event fires with one listener', function (done) {
+  describe('errors', function() {
+    it('event fires with one listener', function(done) {
       this.timeout(1000);
       var db = start({uri: 'mongodb://whatever23939.localhost/fakeeee?connectTimeoutMS=500', noErrorListener: 1});
-      db.on('error', function () {
+      db.on('error', function() {
         // this callback has no params which triggered the bug #759
         db.close();
         done();
       });
     });
 
-    it('should occur without hanging when password with special chars is used (gh-460)', function (done) {
+    it('should occur without hanging when password with special chars is used (gh-460)', function(done) {
       this.timeout(1000);
-      var db = mongoose.createConnection('mongodb://aaron:ps#w@localhost/fake?connectTimeoutMS=500', function (err) {
+      var db = mongoose.createConnection('mongodb://aaron:ps#w@localhost/fake?connectTimeoutMS=500', function(err) {
         assert.ok(err);
         db.close();
         done();
@@ -691,8 +691,8 @@ describe('connections:', function () {
     });
   });
 
-  describe('.model()', function () {
-    it('allows passing a schema', function (done) {
+  describe('.model()', function() {
+    it('allows passing a schema', function(done) {
       var db = start();
       var MyModel = db.model('MyModelasdf', new Schema({
         name: String
@@ -707,7 +707,7 @@ describe('connections:', function () {
       done();
     });
 
-    it('should properly assign the db', function (done) {
+    it('should properly assign the db', function(done) {
       var A = mongoose.model('testing853a', new Schema({x: String}), 'testing853-1');
       var B = mongoose.model('testing853b', new Schema({x: String}), 'testing853-2');
       var C = B.model('testing853a');
@@ -715,12 +715,12 @@ describe('connections:', function () {
       done();
     });
 
-    it('prevents overwriting pre-existing models', function (done) {
+    it('prevents overwriting pre-existing models', function(done) {
       var db = start();
       var name = 'gh-1209-a';
       db.model(name, new Schema);
 
-      assert.throws(function () {
+      assert.throws(function() {
         db.model(name, new Schema);
       }, /Cannot overwrite `gh-1209-a` model/);
 
@@ -728,13 +728,13 @@ describe('connections:', function () {
       done();
     });
 
-    it('allows passing identical name + schema args', function (done) {
+    it('allows passing identical name + schema args', function(done) {
       var db = start();
       var name = 'gh-1209-b';
       var schema = new Schema;
 
       db.model(name, schema);
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         db.model(name, schema);
       });
 
@@ -742,9 +742,9 @@ describe('connections:', function () {
       done();
     });
 
-    it('throws on unknown model name', function (done) {
+    it('throws on unknown model name', function(done) {
       var db = start();
-      assert.throws(function () {
+      assert.throws(function() {
         db.model('iDoNotExist!');
       }, /Schema hasn't been registered/);
 
@@ -752,7 +752,7 @@ describe('connections:', function () {
       done();
     });
 
-    it('uses the passed schema when global model exists with same name (gh-1209)', function (done) {
+    it('uses the passed schema when global model exists with same name (gh-1209)', function(done) {
       var s1 = new Schema({one: String});
       var s2 = new Schema({two: Number});
 
@@ -776,8 +776,8 @@ describe('connections:', function () {
       done();
     });
 
-    describe('get existing model with not existing collection in db', function () {
-      it('must return exiting collection with all collection options', function (done) {
+    describe('get existing model with not existing collection in db', function() {
+      it('must return exiting collection with all collection options', function(done) {
         mongoose.model('some-th-1458', new Schema({test: String}, {capped: {size: 1000, max: 10}}));
         var db = start();
         var m = db.model('some-th-1458');
@@ -788,9 +788,9 @@ describe('connections:', function () {
       });
     });
 
-    describe('passing collection name', function () {
-      describe('when model name already exists', function () {
-        it('returns a new uncached model', function (done) {
+    describe('passing collection name', function() {
+      describe('when model name already exists', function() {
+        it('returns a new uncached model', function(done) {
           var db = start();
           var s1 = new Schema({a: []});
           var name = 'non-cached-collection-name';
@@ -807,15 +807,15 @@ describe('connections:', function () {
       });
     });
 
-    describe('passing object literal schemas', function () {
-      it('works', function (done) {
+    describe('passing object literal schemas', function() {
+      it('works', function(done) {
         var db = start();
         var A = db.model('A', {n: [{age: 'number'}]});
         var a = new A({n: [{age: '47'}]});
         assert.strictEqual(47, a.n[0].age);
-        a.save(function (err) {
+        a.save(function(err) {
           assert.ifError(err);
-          A.findById(a, function (err) {
+          A.findById(a, function(err) {
             db.close();
             assert.ifError(err);
             assert.strictEqual(47, a.n[0].age);
@@ -826,8 +826,8 @@ describe('connections:', function () {
     });
   });
 
-  describe('openSet', function () {
-    it('accepts uris, dbname, options', function (done) {
+  describe('openSet', function() {
+    it('accepts uris, dbname, options', function(done) {
       var m = new mongoose.Mongoose;
       var uris = process.env.MONGOOSE_SET_TEST_URI;
       if (!uris) {
@@ -835,7 +835,7 @@ describe('connections:', function () {
       }
 
       m.connection.on('error', done);
-      m.connection.on('open', function () {
+      m.connection.on('open', function() {
         m.connection.close(done);
       });
 
@@ -845,8 +845,8 @@ describe('connections:', function () {
         done(err);
       }
     });
-    describe('auth', function () {
-      it('from uri', function (done) {
+    describe('auth', function() {
+      it('from uri', function(done) {
         var uris = process.env.MONGOOSE_SET_TEST_URI;
         if (!uris) {
           return done();
@@ -854,14 +854,14 @@ describe('connections:', function () {
 
         var db = mongoose.createConnection();
         db.openSet('mongodb://aaron:psw@localhost:27000,b,c', {server: {auto_reconnect: false}});
-        db.on('error', function () {
+        db.on('error', function() {
         });
         assert.equal('aaron', db.user);
         assert.equal('psw', db.pass);
         db.close();
         done();
       });
-      it('form options', function (done) {
+      it('form options', function(done) {
         var uris = process.env.MONGOOSE_SET_TEST_URI;
         if (!uris) {
           return done();
@@ -869,7 +869,7 @@ describe('connections:', function () {
 
         var db = mongoose.createConnection();
         db.openSet('mongodb://aaron:psw@localhost:27000,b,c', {user: 'tester', pass: 'testpsw'});
-        db.on('error', function () {
+        db.on('error', function() {
         });
         assert.equal('tester', db.user);
         assert.equal('testpsw', db.pass);
@@ -878,10 +878,10 @@ describe('connections:', function () {
       });
     });
 
-    it('handles unix domain sockets', function (done) {
+    it('handles unix domain sockets', function(done) {
       var url = 'mongodb://aaron:psw@/tmp/mongodb-27018.sock,/tmp/mongodb-27019.sock/fake?replicaSet=bacon';
       var db = mongoose.createConnection(url, {server: {auto_reconnect: false}});
-      db.on('error', function () {
+      db.on('error', function() {
       });
       assert.equal('object', typeof db.options);
       assert.equal('object', typeof db.options.server);
@@ -898,7 +898,7 @@ describe('connections:', function () {
       done();
     });
 
-    it('can reopen a disconnected replica set (gh-1263)', function (done) {
+    it('can reopen a disconnected replica set (gh-1263)', function(done) {
       var uris = process.env.MONGOOSE_SET_TEST_URI;
       if (!uris) {
         return done();
@@ -909,17 +909,17 @@ describe('connections:', function () {
       conn.on('error', done);
 
       try {
-        conn.openSet(uris, 'mongoose_test', {}, function (err) {
+        conn.openSet(uris, 'mongoose_test', {}, function(err) {
           if (err) {
             return done(err);
           }
 
-          conn.close(function (err) {
+          conn.close(function(err) {
             if (err) {
               return done(err);
             }
 
-            conn.openSet(uris, 'mongoose_test', {}, function () {
+            conn.openSet(uris, 'mongoose_test', {}, function() {
               conn.close(done);
             });
           });
@@ -930,23 +930,23 @@ describe('connections:', function () {
     });
   });
 
-  it('connecting to single mongos (gh-3537)', function (done) {
+  it('connecting to single mongos (gh-3537)', function(done) {
     var db = mongoose.createConnection('localhost:27017', {mongos: true});
     assert.ok(db.db.serverConfig instanceof mongoose.mongo.Mongos);
     db.close(done);
   });
 
-  describe('connecting to multiple mongos nodes (gh-1037)', function () {
+  describe('connecting to multiple mongos nodes (gh-1037)', function() {
     var mongos = process.env.MONGOOSE_MULTI_MONGOS_TEST_URI;
     if (!mongos) {
       return console.log('Not testing multi-mongos support');
     }
 
-    it('works', function (done) {
+    it('works', function(done) {
       this.timeout(3000);
 
       var m = new mongoose.Mongoose;
-      m.connect(mongos, {mongos: true}, function (err) {
+      m.connect(mongos, {mongos: true}, function(err) {
         assert.ifError(err);
 
         var s = m.connection.db.serverConfig;
@@ -954,10 +954,10 @@ describe('connections:', function () {
         assert.equal(2, s.servers.length);
 
         var M = m.model('TestMultipleMongos', {name: String}, 'test-multi-mongos-' + random());
-        M.create({name: 'works'}, function (err, d) {
+        M.create({name: 'works'}, function(err, d) {
           assert.ifError(err);
 
-          M.findOne({name: 'works'}, function (err, doc) {
+          M.findOne({name: 'works'}, function(err, doc) {
             assert.ifError(err);
             assert.equal(doc.id, d.id);
             m.disconnect(done);
@@ -967,8 +967,8 @@ describe('connections:', function () {
     });
   });
 
-  describe('modelNames()', function () {
-    it('returns names of all models registered on it', function (done) {
+  describe('modelNames()', function() {
+    it('returns names of all models registered on it', function(done) {
       var m = new mongoose.Mongoose;
       m.model('root', {x: String});
       var another = m.model('another', {x: String});
@@ -993,8 +993,8 @@ describe('connections:', function () {
     });
   });
 
-  describe('connection pool sharing: ', function () {
-    it('works', function (done) {
+  describe('connection pool sharing: ', function() {
+    it('works', function(done) {
       var db = mongoose.createConnection('mongodb://localhost/mongoose1');
 
       var db2 = db.useDb('mongoose2');
@@ -1014,7 +1014,7 @@ describe('connections:', function () {
       db2.close(done);
     });
 
-    it('saves correctly', function (done) {
+    it('saves correctly', function(done) {
       var db = start();
       var db2 = db.useDb('mongoose-test-2');
 
@@ -1026,27 +1026,27 @@ describe('connections:', function () {
       var m1 = db.model('testMod', schema);
       var m2 = db2.model('testMod', schema);
 
-      m1.create({body: 'this is some text', thing: 1}, function (err, i1) {
+      m1.create({body: 'this is some text', thing: 1}, function(err, i1) {
         assert.ifError(err);
-        m2.create({body: 'this is another body', thing: 2}, function (err, i2) {
+        m2.create({body: 'this is another body', thing: 2}, function(err, i2) {
           assert.ifError(err);
 
-          m1.findById(i1.id, function (err, item1) {
+          m1.findById(i1.id, function(err, item1) {
             assert.ifError(err);
             assert.equal(item1.body, 'this is some text');
             assert.equal(item1.thing, 1);
 
-            m2.findById(i2.id, function (err, item2) {
+            m2.findById(i2.id, function(err, item2) {
               assert.ifError(err);
               assert.equal(item2.body, 'this is another body');
               assert.equal(item2.thing, 2);
 
               // validate the doc doesn't exist in the other db
-              m1.findById(i2.id, function (err, nothing) {
+              m1.findById(i2.id, function(err, nothing) {
                 assert.ifError(err);
                 assert.strictEqual(null, nothing);
 
-                m2.findById(i1.id, function (err, nothing) {
+                m2.findById(i1.id, function(err, nothing) {
                   assert.ifError(err);
                   assert.strictEqual(null, nothing);
 
@@ -1059,17 +1059,17 @@ describe('connections:', function () {
       });
     });
 
-    it('emits connecting events on both', function (done) {
+    it('emits connecting events on both', function(done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
 
-      db2.on('connecting', function () {
+      db2.on('connecting', function() {
         hit && close();
         hit = true;
       });
 
-      db.on('connecting', function () {
+      db.on('connecting', function() {
         hit && close();
         hit = true;
       });
@@ -1081,16 +1081,16 @@ describe('connections:', function () {
       }
     });
 
-    it('emits connected events on both', function (done) {
+    it('emits connected events on both', function(done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
 
-      db2.on('connected', function () {
+      db2.on('connected', function() {
         hit && close();
         hit = true;
       });
-      db.on('connected', function () {
+      db.on('connected', function() {
         hit && close();
         hit = true;
       });
@@ -1102,15 +1102,15 @@ describe('connections:', function () {
       }
     });
 
-    it('emits open events on both', function (done) {
+    it('emits open events on both', function(done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('open', function () {
+      db2.on('open', function() {
         hit && close();
         hit = true;
       });
-      db.on('open', function () {
+      db.on('open', function() {
         hit && close();
         hit = true;
       });
@@ -1122,105 +1122,105 @@ describe('connections:', function () {
       }
     });
 
-    it('emits disconnecting events on both, closing initial db', function (done) {
+    it('emits disconnecting events on both, closing initial db', function(done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('disconnecting', function () {
+      db2.on('disconnecting', function() {
         hit && done();
         hit = true;
       });
-      db.on('disconnecting', function () {
+      db.on('disconnecting', function() {
         hit && done();
         hit = true;
       });
-      db.on('open', function () {
+      db.on('open', function() {
         db.close();
       });
       db.open(start.uri);
     });
 
-    it('emits disconnecting events on both, closing secondary db', function (done) {
+    it('emits disconnecting events on both, closing secondary db', function(done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('disconnecting', function () {
+      db2.on('disconnecting', function() {
         hit && done();
         hit = true;
       });
-      db.on('disconnecting', function () {
+      db.on('disconnecting', function() {
         hit && done();
         hit = true;
       });
-      db.on('open', function () {
+      db.on('open', function() {
         db2.close();
       });
       db.open(start.uri);
     });
 
-    it('emits disconnected events on both, closing initial db', function (done) {
+    it('emits disconnected events on both, closing initial db', function(done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('disconnected', function () {
+      db2.on('disconnected', function() {
         hit && done();
         hit = true;
       });
-      db.on('disconnected', function () {
+      db.on('disconnected', function() {
         hit && done();
         hit = true;
       });
-      db.on('open', function () {
+      db.on('open', function() {
         db.close();
       });
       db.open(start.uri);
     });
 
-    it('emits disconnected events on both, closing secondary db', function (done) {
+    it('emits disconnected events on both, closing secondary db', function(done) {
       var db = mongoose.createConnection();
       var db2 = db.useDb('mongoose-test-2');
       var hit = false;
-      db2.on('disconnected', function () {
+      db2.on('disconnected', function() {
         hit && done();
         hit = true;
       });
-      db.on('disconnected', function () {
+      db.on('disconnected', function() {
         hit && done();
         hit = true;
       });
-      db.on('open', function () {
+      db.on('open', function() {
         db2.close();
       });
       db.open(start.uri);
     });
 
-    it('closes correctly for all dbs, closing initial db', function (done) {
+    it('closes correctly for all dbs, closing initial db', function(done) {
       var db = start();
       var db2 = db.useDb('mongoose-test-2');
 
-      db2.on('close', function () {
+      db2.on('close', function() {
         done();
       });
       db.close();
     });
 
-    it('closes correctly for all dbs, closing secondary db', function (done) {
+    it('closes correctly for all dbs, closing secondary db', function(done) {
       var db = start();
       var db2 = db.useDb('mongoose-test-2');
 
-      db.on('close', function () {
+      db.on('close', function() {
         done();
       });
       db2.close();
     });
   });
 
-  describe('shouldAuthenticate()', function () {
-    describe('when using standard authentication', function () {
-      describe('when username and password are undefined', function () {
-        it('should return false', function (done) {
+  describe('shouldAuthenticate()', function() {
+    describe('when using standard authentication', function() {
+      describe('when username and password are undefined', function() {
+        it('should return false', function(done) {
           var db = mongoose.createConnection('localhost', 'fake', 27000, {});
-          db.on('error', function () {
+          db.on('error', function() {
           });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
@@ -1239,10 +1239,10 @@ describe('connections:', function () {
           done();
         });
       });
-      describe('when username and password are empty strings', function () {
-        it('should return false', function (done) {
+      describe('when username and password are empty strings', function() {
+        it('should return false', function(done) {
           var db = mongoose.createConnection('localhost', 'fake', 27000, {user: '', pass: ''});
-          db.on('error', function () {
+          db.on('error', function() {
           });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
@@ -1261,10 +1261,10 @@ describe('connections:', function () {
           done();
         });
       });
-      describe('when only username is defined', function () {
-        it('should return false', function (done) {
+      describe('when only username is defined', function() {
+        it('should return false', function(done) {
           var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user'});
-          db.on('error', function () {
+          db.on('error', function() {
           });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
@@ -1283,10 +1283,10 @@ describe('connections:', function () {
           done();
         });
       });
-      describe('when both username and password are defined', function () {
-        it('should return false', function (done) {
+      describe('when both username and password are defined', function() {
+        it('should return false', function(done) {
           var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user', pass: 'pass'});
-          db.on('error', function () {
+          db.on('error', function() {
           });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
@@ -1306,11 +1306,11 @@ describe('connections:', function () {
         });
       });
     });
-    describe('when using MONGODB-X509 authentication', function () {
-      describe('when username and password are undefined', function () {
-        it('should return false', function (done) {
+    describe('when using MONGODB-X509 authentication', function() {
+      describe('when username and password are undefined', function() {
+        it('should return false', function(done) {
           var db = mongoose.createConnection('localhost', 'fake', 27000, {});
-          db.on('error', function () {
+          db.on('error', function() {
           });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
@@ -1329,10 +1329,10 @@ describe('connections:', function () {
           done();
         });
       });
-      describe('when only username is defined', function () {
-        it('should return false', function (done) {
+      describe('when only username is defined', function() {
+        it('should return false', function(done) {
           var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user', auth: {authMechanism: 'MONGODB-X509'}});
-          db.on('error', function () {
+          db.on('error', function() {
           });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
@@ -1351,10 +1351,10 @@ describe('connections:', function () {
           done();
         });
       });
-      describe('when both username and password are defined', function () {
-        it('should return false', function (done) {
+      describe('when both username and password are defined', function() {
+        it('should return false', function(done) {
           var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user', pass: 'pass', auth: {authMechanism: 'MONGODB-X509'}});
-          db.on('error', function () {
+          db.on('error', function() {
           });
           assert.equal('object', typeof db.options);
           assert.equal('object', typeof db.options.server);
diff --git a/test/crash.test.js b/test/crash.test.js
index 6ab0a0de5a2..f4fb98adea1 100644
--- a/test/crash.test.js
+++ b/test/crash.test.js
@@ -4,8 +4,8 @@ var start = require('./common'),
     assert = require('assert'),
     mongoose = start.mongoose;
 
-describe('crash: (gh-407)', function () {
-  it('test mongodb crash with invalid objectid string', function (done) {
+describe('crash: (gh-407)', function() {
+  it('test mongodb crash with invalid objectid string', function(done) {
     var db = mongoose.createConnection('mongodb://localhost/test-crash');
 
     var IndexedGuy = new mongoose.Schema({
@@ -21,7 +21,7 @@ describe('crash: (gh-407)', function () {
           '',
           '4e0e2ca0795666368603d974']
       }
-    }, function (err) {
+    }, function(err) {
       db.close(done);
 
       try {
diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index 8b663a16b59..6aa8902aafb 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -29,7 +29,7 @@ TestDocument.prototype.__proto__ = Document.prototype;
  */
 
 var em = new Schema({title: String, body: String});
-em.virtual('works').get(function () {
+em.virtual('works').get(function() {
   return 'em virtual works';
 });
 var schema = new Schema({
@@ -55,16 +55,16 @@ var schema = new Schema({
 });
 TestDocument.prototype.$__setSchema(schema);
 
-schema.virtual('nested.agePlus2').get(function () {
+schema.virtual('nested.agePlus2').get(function() {
   return this.nested.age + 2;
 });
-schema.virtual('nested.setAge').set(function (v) {
+schema.virtual('nested.setAge').set(function(v) {
   this.nested.age = v;
 });
-schema.path('nested.path').get(function (v) {
+schema.path('nested.path').get(function(v) {
   return this.nested.age + (v ? v : '');
 });
-schema.path('nested.setr').set(function (v) {
+schema.path('nested.setr').set(function(v) {
   return v + ' setter';
 });
 
@@ -73,152 +73,152 @@ schema.path('nested.setr').set(function (v) {
  * executed.
  */
 
-TestDocument.prototype.hooksTest = function (fn) {
+TestDocument.prototype.hooksTest = function(fn) {
   fn(null, arguments);
 };
 
-describe('document: hooks:', function () {
-  it('step order', function (done) {
+describe('document: hooks:', function() {
+  it('step order', function(done) {
     var doc = new TestDocument(),
         steps = 0;
 
     // serial
-    doc.pre('hooksTest', function (next) {
+    doc.pre('hooksTest', function(next) {
       steps++;
-      setTimeout(function () {
+      setTimeout(function() {
         // make sure next step hasn't executed yet
         assert.equal(1, steps);
         next();
       }, 50);
     });
 
-    doc.pre('hooksTest', function (next) {
+    doc.pre('hooksTest', function(next) {
       steps++;
       next();
     });
 
     // parallel
-    doc.pre('hooksTest', true, function (next, done) {
+    doc.pre('hooksTest', true, function(next, done) {
       steps++;
       assert.equal(3, steps);
-      setTimeout(function () {
+      setTimeout(function() {
         assert.equal(4, steps);
       }, 10);
-      setTimeout(function () {
+      setTimeout(function() {
         steps++;
         done();
       }, 110);
       next();
     });
 
-    doc.pre('hooksTest', true, function (next, done) {
+    doc.pre('hooksTest', true, function(next, done) {
       steps++;
-      setTimeout(function () {
+      setTimeout(function() {
         assert.equal(4, steps);
       }, 10);
-      setTimeout(function () {
+      setTimeout(function() {
         steps++;
         done();
       }, 110);
       next();
     });
 
-    doc.hooksTest(function (err) {
+    doc.hooksTest(function(err) {
       assert.ifError(err);
       assert.equal(6, steps);
       done();
     });
   });
 
-  it('calling next twice does not break', function (done) {
+  it('calling next twice does not break', function(done) {
     var doc = new TestDocument(),
         steps = 0;
 
-    doc.pre('hooksTest', function (next) {
+    doc.pre('hooksTest', function(next) {
       steps++;
       next();
       next();
     });
 
-    doc.pre('hooksTest', function (next) {
+    doc.pre('hooksTest', function(next) {
       steps++;
       next();
     });
 
-    doc.hooksTest(function (err) {
+    doc.hooksTest(function(err) {
       assert.ifError(err);
       assert.equal(2, steps);
       done();
     });
   });
 
-  it('calling done twice does not break', function (done) {
+  it('calling done twice does not break', function(done) {
     var doc = new TestDocument(),
         steps = 0;
 
-    doc.pre('hooksTest', true, function (next, done) {
+    doc.pre('hooksTest', true, function(next, done) {
       steps++;
       next();
       done();
       done();
     });
 
-    doc.pre('hooksTest', true, function (next, done) {
+    doc.pre('hooksTest', true, function(next, done) {
       steps++;
       next();
       done();
       done();
     });
 
-    doc.hooksTest(function (err) {
+    doc.hooksTest(function(err) {
       assert.ifError(err);
       assert.equal(2, steps);
       done();
     });
   });
 
-  it('errors from a serial hook', function (done) {
+  it('errors from a serial hook', function(done) {
     var doc = new TestDocument(),
         steps = 0;
 
-    doc.pre('hooksTest', function (next) {
+    doc.pre('hooksTest', function(next) {
       steps++;
       next();
     });
 
-    doc.pre('hooksTest', function (next) {
+    doc.pre('hooksTest', function(next) {
       steps++;
       next(new Error);
     });
 
-    doc.pre('hooksTest', function () {
+    doc.pre('hooksTest', function() {
       steps++;
     });
 
-    doc.hooksTest(function (err) {
+    doc.hooksTest(function(err) {
       assert.ok(err instanceof Error);
       assert.equal(2, steps);
       done();
     });
   });
 
-  it('errors from last serial hook', function (done) {
+  it('errors from last serial hook', function(done) {
     var doc = new TestDocument();
 
-    doc.pre('hooksTest', function (next) {
+    doc.pre('hooksTest', function(next) {
       next(new Error);
     });
 
-    doc.hooksTest(function (err) {
+    doc.hooksTest(function(err) {
       assert.ok(err instanceof Error);
       done();
     });
   });
 
-  it('mutating incoming args via middleware', function (done) {
+  it('mutating incoming args via middleware', function(done) {
     var doc = new TestDocument();
 
-    doc.pre('set', function (next, path, val) {
+    doc.pre('set', function(next, path, val) {
       next(path, 'altered-' + val);
     });
 
@@ -227,55 +227,55 @@ describe('document: hooks:', function () {
     done();
   });
 
-  it('test hooks system errors from a parallel hook', function (done) {
+  it('test hooks system errors from a parallel hook', function(done) {
     var doc = new TestDocument(),
         steps = 0;
 
-    doc.pre('hooksTest', true, function (next, done) {
+    doc.pre('hooksTest', true, function(next, done) {
       steps++;
       next();
       done();
     });
 
-    doc.pre('hooksTest', true, function (next, done) {
+    doc.pre('hooksTest', true, function(next, done) {
       steps++;
       next();
       done();
     });
 
-    doc.pre('hooksTest', true, function (next, done) {
+    doc.pre('hooksTest', true, function(next, done) {
       steps++;
       next();
       done(new Error);
     });
 
-    doc.hooksTest(function (err) {
+    doc.hooksTest(function(err) {
       assert.ok(err instanceof Error);
       assert.equal(3, steps);
       done();
     });
   });
 
-  it('passing two arguments to a method subject to hooks and return value', function (done) {
+  it('passing two arguments to a method subject to hooks and return value', function(done) {
     var doc = new TestDocument();
 
-    doc.pre('hooksTest', function (next) {
+    doc.pre('hooksTest', function(next) {
       next();
     });
 
-    doc.hooksTest(function (err, args) {
+    doc.hooksTest(function(err, args) {
       assert.equal(2, args.length);
       assert.equal(args[1], 'test');
       done();
     }, 'test');
   });
 
-  it('hooking set works with document arrays (gh-746)', function (done) {
+  it('hooking set works with document arrays (gh-746)', function(done) {
     var db = start();
 
     var child = new Schema({text: String});
 
-    child.pre('set', function (next, path, value, type) {
+    child.pre('set', function(next, path, value, type) {
       next(path, value, type);
     });
 
@@ -288,17 +288,17 @@ describe('document: hooks:', function () {
 
     var s = new S({name: 'test'});
     s.e = [{text: 'hi'}];
-    s.save(function (err) {
+    s.save(function(err) {
       assert.ifError(err);
 
-      S.findById(s.id, function (err, s) {
+      S.findById(s.id, function(err, s) {
         assert.ifError(err);
 
         s.e = [{text: 'bye'}];
-        s.save(function (err) {
+        s.save(function(err) {
           assert.ifError(err);
 
-          S.findById(s.id, function (err, s) {
+          S.findById(s.id, function(err, s) {
             db.close();
             assert.ifError(err);
             assert.equal('bye', s.e[0].text);
@@ -309,13 +309,13 @@ describe('document: hooks:', function () {
     });
   });
 
-  it('pre save hooks on sub-docs should not exec after validation errors', function (done) {
+  it('pre save hooks on sub-docs should not exec after validation errors', function(done) {
     var db = start();
     var presave = false;
 
     var child = new Schema({text: {type: String, required: true}});
 
-    child.pre('save', function (next) {
+    child.pre('save', function(next) {
       presave = true;
       next();
     });
@@ -327,7 +327,7 @@ describe('document: hooks:', function () {
 
     var S = db.model('docArrayWithHookedSave', schema);
     var s = new S({name: 'hi', e: [{}]});
-    s.save(function (err) {
+    s.save(function(err) {
       db.close();
 
       try {
@@ -341,17 +341,17 @@ describe('document: hooks:', function () {
     });
   });
 
-  it('post remove hooks on subdocuments work', function (done) {
+  it('post remove hooks on subdocuments work', function(done) {
     var db = start();
     var sub = new Schema({_id: Number});
     var called = {pre: 0, post: 0};
 
-    sub.pre('remove', function (next) {
+    sub.pre('remove', function(next) {
       called.pre++;
       next();
     });
 
-    sub.post('remove', function (doc) {
+    sub.post('remove', function(doc) {
       called.post++;
       assert.ok(doc instanceof Document);
     });
@@ -360,35 +360,35 @@ describe('document: hooks:', function () {
     var M = db.model('post-remove-hooks-sub', par);
 
     var m = new M({sub: [{_id: 1}, {_id: 2}]});
-    m.save(function (err) {
+    m.save(function(err) {
       assert.ifError(err);
       assert.equal(0, called.pre);
       assert.equal(0, called.post);
 
-      M.findById(m, function (err1, doc) {
+      M.findById(m, function(err1, doc) {
         assert.ifError(err1);
 
         doc.sub.id(1).remove();
-        doc.save(function (err2) {
+        doc.save(function(err2) {
           assert.ifError(err2);
           assert.equal(1, called.pre);
           assert.equal(1, called.post);
 
           // does not get called when not removed
           doc.name = 'changed1';
-          doc.save(function (err3) {
+          doc.save(function(err3) {
             assert.ifError(err3);
             assert.equal(1, called.pre);
             assert.equal(1, called.post);
 
             doc.sub.id(2).remove();
-            doc.remove(function (err4) {
+            doc.remove(function(err4) {
               assert.ifError(err4);
               assert.equal(2, called.pre);
               assert.equal(2, called.post);
 
               // does not get called twice
-              doc.remove(function (err5) {
+              doc.remove(function(err5) {
                 assert.ifError(err5);
                 assert.equal(2, called.pre);
                 assert.equal(2, called.post);
@@ -401,7 +401,7 @@ describe('document: hooks:', function () {
     });
   });
 
-  it('can set nested schema to undefined in pre save (gh-1335)', function (done) {
+  it('can set nested schema to undefined in pre save (gh-1335)', function(done) {
     var db = start();
     var FooSchema = new Schema({});
     db.model('gh-1335-1', FooSchema);
@@ -411,14 +411,14 @@ describe('document: hooks:', function () {
     var Bar = db.model('gh-1335-2', BarSchema);
 
     var b = new Bar();
-    b.pre('save', function (next) {
+    b.pre('save', function(next) {
       if (this.isNew && this.foos.length === 0) {
         this.foos = undefined;
       }
       next();
     });
 
-    b.save(function (error, dbBar) {
+    b.save(function(error, dbBar) {
       assert.ifError(error);
       assert.ok(!dbBar.foos);
       assert.equal(typeof dbBar.foos, 'undefined');
@@ -428,9 +428,9 @@ describe('document: hooks:', function () {
     });
   });
 
-  it('post save hooks on subdocuments work (gh-915) (gh-3780)', function (done) {
+  it('post save hooks on subdocuments work (gh-915) (gh-3780)', function(done) {
     var doneCalled = false;
-    var _done = function (e) {
+    var _done = function(e) {
       if (!doneCalled) {
         doneCalled = true;
         done(e);
@@ -443,7 +443,7 @@ describe('document: hooks:', function () {
       name: String
     });
 
-    subSchema.post('save', function (doc) {
+    subSchema.post('save', function(doc) {
       called.post++;
       try {
         assert.ok(doc instanceof EmbeddedDocument);
@@ -465,15 +465,15 @@ describe('document: hooks:', function () {
       ]
     });
 
-    m.save(function (err) {
+    m.save(function(err) {
       assert.ifError(err);
       assert.equal(2, called.post);
       called.post = 0;
 
-      M.findById(m, function (err, doc) {
+      M.findById(m, function(err, doc) {
         assert.ifError(err);
         doc.subs.push({name: 'maa'});
-        doc.save(function (err) {
+        doc.save(function(err) {
           assert.ifError(err);
           assert.equal(called.post, 3);
 
@@ -483,7 +483,7 @@ describe('document: hooks:', function () {
     });
   });
 
-  it('pre save hooks should run in parallel', function (done) {
+  it('pre save hooks should run in parallel', function(done) {
     // we set the time out to be double that of the validator - 1
     // (so that running in serial will be greater then that)
     this.timeout(1000);
@@ -494,7 +494,7 @@ describe('document: hooks:', function () {
       preference: String
     });
     SchemaWithPreSaveHook.pre('save', true, function hook(next, done) {
-      setTimeout(function () {
+      setTimeout(function() {
         count++;
         next();
         if (count === 3) {
@@ -518,7 +518,7 @@ describe('document: hooks:', function () {
       }]
     });
 
-    m.save(function (err) {
+    m.save(function(err) {
       db.close();
 
       try {
@@ -531,18 +531,18 @@ describe('document: hooks:', function () {
     });
   });
 
-  it('parallel followed by serial (gh-2521)', function (done) {
+  it('parallel followed by serial (gh-2521)', function(done) {
     var schema = new Schema({name: String});
 
-    schema.pre('save', true, function (next, done) {
-      process.nextTick(function () {
+    schema.pre('save', true, function(next, done) {
+      process.nextTick(function() {
         done();
       });
       next();
     });
 
-    schema.pre('save', function (done) {
-      process.nextTick(function () {
+    schema.pre('save', function(done) {
+      process.nextTick(function() {
         done();
       });
     });
@@ -551,17 +551,17 @@ describe('document: hooks:', function () {
     var People = db.model('gh-2521', schema, 'gh-2521');
 
     var p = new People({name: 'Val'});
-    p.save(function (error) {
+    p.save(function(error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('runs post hooks after function (gh-2949)', function (done) {
+  it('runs post hooks after function (gh-2949)', function(done) {
     var schema = new Schema({name: String});
 
     var postCount = 0;
-    schema.post('init', function (doc) {
+    schema.post('init', function(doc) {
       assert.equal(doc.name, 'Val');
       ++postCount;
     });
@@ -569,19 +569,19 @@ describe('document: hooks:', function () {
     var db = start();
     var People = db.model('gh-2949', schema, 'gh-2949');
 
-    People.create({name: 'Val'}, function (err, doc) {
-      People.findOne({_id: doc._id}, function () {
+    People.create({name: 'Val'}, function(err, doc) {
+      People.findOne({_id: doc._id}, function() {
         assert.equal(postCount, 1);
         db.close(done);
       });
     });
   });
 
-  it('pre-init hooks work', function (done) {
+  it('pre-init hooks work', function(done) {
     var schema = new Schema({text: String});
 
-    schema.pre('init', function (next, data) {
-      data.text = "pre init'd";
+    schema.pre('init', function(next, data) {
+      data.text = 'pre init\'d';
       next();
     });
 
@@ -589,22 +589,22 @@ describe('document: hooks:', function () {
         Parent = db.model('Parent', schema);
 
     Parent.create({
-      text: "not init'd"
-    }, function (err, doc) {
-      Parent.findOne({_id: doc._id}, function (err, doc) {
+      text: 'not init\'d'
+    }, function(err, doc) {
+      Parent.findOne({_id: doc._id}, function(err, doc) {
         db.close();
 
-        assert.strictEqual(doc.text, "pre init'd");
+        assert.strictEqual(doc.text, 'pre init\'d');
 
         done();
       });
     });
   });
 
-  it('post save handles multiple args (gh-3155)', function (done) {
+  it('post save handles multiple args (gh-3155)', function(done) {
     var schema = new Schema({});
 
-    schema.post('save', function (item, next) {
+    schema.post('save', function(item, next) {
       next();
     });
 
@@ -612,17 +612,17 @@ describe('document: hooks:', function () {
     var Test = db.model('gh3155', schema);
 
     var t = new Test();
-    t.save(function (error, doc, numAffected) {
+    t.save(function(error, doc, numAffected) {
       assert.strictEqual(numAffected, 1);
 
       db.close(done);
     });
   });
 
-  it('pre-init hooks on subdocuments work', function (done) {
+  it('pre-init hooks on subdocuments work', function(done) {
     var childSchema = new Schema({age: Number});
 
-    childSchema.pre('init', function (next, data) {
+    childSchema.pre('init', function(next, data) {
       ++data.age;
       next();
       // On subdocuments, you have to return `this`
@@ -636,8 +636,8 @@ describe('document: hooks:', function () {
     Parent.create({
       name: 'Bob',
       children: [{age: 8}, {age: 5}]
-    }, function (err, doc) {
-      Parent.findOne({_id: doc._id}, function (err, doc) {
+    }, function(err, doc) {
+      Parent.findOne({_id: doc._id}, function(err, doc) {
         db.close();
 
         assert.strictEqual(doc.children.length, 2);
@@ -651,10 +651,10 @@ describe('document: hooks:', function () {
     });
   });
 
-  it('pre-save hooks fire on subdocs before their parent doc', function (done) {
+  it('pre-save hooks fire on subdocs before their parent doc', function(done) {
     var childSchema = new Schema({name: String, count: Number});
 
-    childSchema.pre('save', function (next) {
+    childSchema.pre('save', function(next) {
       ++this.count;
       next();
       // On subdocuments, you have to return `this`
@@ -666,8 +666,8 @@ describe('document: hooks:', function () {
       children: [childSchema]
     });
 
-    parentSchema.pre('save', function (next) {
-      this.cumulativeCount = this.children.reduce(function (seed, child) {
+    parentSchema.pre('save', function(next) {
+      this.cumulativeCount = this.children.reduce(function(seed, child) {
         seed += child.count;
         return seed;
       }, 0);
@@ -678,7 +678,7 @@ describe('document: hooks:', function () {
         Parent = db.model('ParentWithChildren', parentSchema),
         doc = new Parent({children: [{count: 0, name: 'a'}, {count: 1, name: 'b'}]});
 
-    doc.save(function (err, doc1) {
+    doc.save(function(err, doc1) {
       db.close();
 
       try {
@@ -694,16 +694,16 @@ describe('document: hooks:', function () {
     });
   });
 
-  describe('gh-3284', function () {
-    it('should call pre hooks on nested subdoc', function (done) {
+  describe('gh-3284', function() {
+    it('should call pre hooks on nested subdoc', function(done) {
       var _this = this;
 
       var childSchema = new Schema({
         title: String
       });
 
-      ['init', 'save', 'validate'].forEach(function (type) {
-        childSchema.pre(type, function (next) {
+      ['init', 'save', 'validate'].forEach(function(type) {
+        childSchema.pre(type, function(next) {
           _this['pre' + type + 'Called'] = true;
           next();
         });
@@ -728,9 +728,9 @@ describe('document: hooks:', function () {
         }
       });
 
-      parent.save().then(function () {
+      parent.save().then(function() {
         return Parent.findById(parent._id);
-      }).then(function () {
+      }).then(function() {
         db.close();
         assert.ok(_this.preinitCalled);
         assert.ok(_this.prevalidateCalled);
@@ -740,13 +740,13 @@ describe('document: hooks:', function () {
     });
   });
 
-  it('pre set hooks on real documents (gh-3479)', function (done) {
+  it('pre set hooks on real documents (gh-3479)', function(done) {
     var bookSchema = new Schema({
       title: String
     });
 
     var preCalls = [];
-    bookSchema.pre('set', function (next, path, val) {
+    bookSchema.pre('set', function(next, path, val) {
       preCalls.push({path: path, val: val});
       next();
     });
@@ -763,7 +763,7 @@ describe('document: hooks:', function () {
     done();
   });
 
-  it('nested subdocs only fire once (gh-3281)', function (done) {
+  it('nested subdocs only fire once (gh-3281)', function(done) {
     var L3Schema = new Schema({
       title: String
     });
@@ -777,7 +777,7 @@ describe('document: hooks:', function () {
     });
 
     var calls = 0;
-    L3Schema.pre('save', function (next) {
+    L3Schema.pre('save', function(next) {
       ++calls;
       return next();
     });
@@ -793,21 +793,21 @@ describe('document: hooks:', function () {
       }]
     };
 
-    L1.create(data, function (error) {
+    L1.create(data, function(error) {
       assert.ifError(error);
       assert.equal(calls, 1);
       db.close(done);
     });
   });
 
-  it('remove hooks for single nested (gh-3754)', function (done) {
+  it('remove hooks for single nested (gh-3754)', function(done) {
     var db = start();
     var postCount = 0;
     var PhotoSchema = new mongoose.Schema({
       bla: String
     });
 
-    PhotoSchema.post('remove', function () {
+    PhotoSchema.post('remove', function() {
       ++postCount;
     });
 
@@ -817,12 +817,12 @@ describe('document: hooks:', function () {
 
     var Person = db.model('Person', PersonSchema);
 
-    Person.create({photo: {bla: 'test'}}, function (error, person) {
+    Person.create({photo: {bla: 'test'}}, function(error, person) {
       assert.ifError(error);
       person.photo.remove();
-      person.save(function (error1) {
+      person.save(function(error1) {
         assert.ifError(error1);
-        setTimeout(function () {
+        setTimeout(function() {
           assert.equal(postCount, 1);
           done();
         }, 0);
diff --git a/test/document.isselected.test.js b/test/document.isselected.test.js
index 9ea4997b196..065142c4210 100644
--- a/test/document.isselected.test.js
+++ b/test/document.isselected.test.js
@@ -29,7 +29,7 @@ TestDocument.prototype.__proto__ = Document.prototype;
  */
 
 var em = new Schema({title: String, body: String});
-em.virtual('works').get(function () {
+em.virtual('works').get(function() {
   return 'em virtual works';
 });
 var schema = new Schema({
@@ -56,20 +56,20 @@ var schema = new Schema({
 });
 TestDocument.prototype.$__setSchema(schema);
 
-schema.virtual('nested.agePlus2').get(function () {
+schema.virtual('nested.agePlus2').get(function() {
   return this.nested.age + 2;
 });
-schema.virtual('nested.setAge').set(function (v) {
+schema.virtual('nested.setAge').set(function(v) {
   this.nested.age = v;
 });
-schema.path('nested.path').get(function (v) {
+schema.path('nested.path').get(function(v) {
   return (this.nested.age || '') + (v ? v : '');
 });
-schema.path('nested.setr').set(function (v) {
+schema.path('nested.setr').set(function(v) {
   return v + ' setter';
 });
 
-schema.path('date').set(function (v) {
+schema.path('date').set(function(v) {
   // should not have been cast to a Date yet
   assert.equal('string', typeof v);
   return v;
@@ -80,15 +80,15 @@ schema.path('date').set(function (v) {
  * executed.
  */
 
-TestDocument.prototype.hooksTest = function (fn) {
+TestDocument.prototype.hooksTest = function(fn) {
   fn(null, arguments);
 };
 
 /**
  * Test.
  */
-describe('document', function () {
-  it('isSelected()', function (done) {
+describe('document', function() {
+  it('isSelected()', function(done) {
     var doc = new TestDocument();
 
     doc.init({
diff --git a/test/document.modified.test.js b/test/document.modified.test.js
index 531222e594e..ccc1ba76b51 100644
--- a/test/document.modified.test.js
+++ b/test/document.modified.test.js
@@ -42,7 +42,7 @@ var BlogPost = new Schema({
 
 BlogPost
     .path('title')
-    .get(function (v) {
+    .get(function(v) {
       if (v) {
         return v.toUpperCase();
       }
@@ -51,20 +51,20 @@ BlogPost
 
 BlogPost
     .virtual('titleWithAuthor')
-    .get(function () {
+    .get(function() {
       return this.get('title') + ' by ' + this.get('author');
     })
-    .set(function (val) {
+    .set(function(val) {
       var split = val.split(' by ');
       this.set('title', split[0]);
       this.set('author', split[1]);
     });
 
-BlogPost.method('cool', function () {
+BlogPost.method('cool', function() {
   return this;
 });
 
-BlogPost.static('woot', function () {
+BlogPost.static('woot', function() {
   return this;
 });
 
@@ -73,23 +73,23 @@ mongoose.model(modelName, BlogPost);
 
 var collection = 'blogposts_' + random();
 
-describe('document modified', function () {
-  describe('modified states', function () {
-    it('reset after save', function (done) {
+describe('document modified', function() {
+  describe('modified states', function() {
+    it('reset after save', function(done) {
       var db = start(),
           B = db.model(modelName, collection);
 
       var b = new B;
 
       b.numbers.push(3);
-      b.save(function (err) {
+      b.save(function(err) {
         assert.strictEqual(null, err);
 
         b.numbers.push(3);
-        b.save(function (err1) {
+        b.save(function(err1) {
           assert.strictEqual(null, err1);
 
-          B.findById(b, function (err2, b) {
+          B.findById(b, function(err2, b) {
             assert.strictEqual(null, err2);
             assert.equal(2, b.numbers.length);
 
@@ -100,13 +100,13 @@ describe('document modified', function () {
       });
     });
 
-    it('of embedded docs reset after save', function (done) {
+    it('of embedded docs reset after save', function(done) {
       var db = start(),
           BlogPost = db.model(modelName, collection);
 
       var post = new BlogPost({title: 'hocus pocus'});
       post.comments.push({title: 'Humpty Dumpty', comments: [{title: 'nested'}]});
-      post.save(function (err) {
+      post.save(function(err) {
         db.close();
         assert.strictEqual(null, err);
         var mFlag = post.comments[0].isModified('title');
@@ -117,8 +117,8 @@ describe('document modified', function () {
     });
   });
 
-  describe('isDefault', function () {
-    it('works', function (done) {
+  describe('isDefault', function() {
+    it('works', function(done) {
       var db = start();
 
       var MyModel = db.model('test',
@@ -129,8 +129,8 @@ describe('document modified', function () {
     });
   });
 
-  describe('isModified', function () {
-    it('should not throw with no argument', function (done) {
+  describe('isModified', function() {
+    it('should not throw with no argument', function(done) {
       var db = start();
       var BlogPost = db.model(modelName, collection);
       var post = new BlogPost;
@@ -147,7 +147,7 @@ describe('document modified', function () {
       done();
     });
 
-    it('when modifying keys', function (done) {
+    it('when modifying keys', function(done) {
       var db = start(),
           BlogPost = db.model(modelName, collection);
 
@@ -171,7 +171,7 @@ describe('document modified', function () {
       done();
     });
 
-    it('setting a key identically to its current value should not dirty the key', function (done) {
+    it('setting a key identically to its current value should not dirty the key', function(done) {
       var db = start(),
           BlogPost = db.model(modelName, collection);
 
@@ -189,8 +189,8 @@ describe('document modified', function () {
       done();
     });
 
-    describe('on DocumentArray', function () {
-      it('work', function (done) {
+    describe('on DocumentArray', function() {
+      it('work', function(done) {
         var db = start(),
             BlogPost = db.model(modelName, collection);
 
@@ -210,7 +210,7 @@ describe('document modified', function () {
 
         db.close(done);
       });
-      it('with accessors', function (done) {
+      it('with accessors', function(done) {
         var db = start(),
             BlogPost = db.model(modelName, collection);
 
@@ -233,8 +233,8 @@ describe('document modified', function () {
       });
     });
 
-    describe('on MongooseArray', function () {
-      it('atomic methods', function (done) {
+    describe('on MongooseArray', function() {
+      it('atomic methods', function(done) {
         // COMPLETEME
         var db = start(),
             BlogPost = db.model(modelName, collection);
@@ -246,7 +246,7 @@ describe('document modified', function () {
         assert.equal(true, post.isModified('owners'));
         done();
       });
-      it('native methods', function (done) {
+      it('native methods', function(done) {
         // COMPLETEME
         var db = start(),
             BlogPost = db.model(modelName, collection);
@@ -258,7 +258,7 @@ describe('document modified', function () {
       });
     });
 
-    it('on entire document', function (done) {
+    it('on entire document', function(done) {
       var db = start(),
           BlogPost = db.model(modelName, collection);
 
@@ -280,9 +280,9 @@ describe('document modified', function () {
         ]
       };
 
-      BlogPost.create(doc, function (err, post) {
+      BlogPost.create(doc, function(err, post) {
         assert.ifError(err);
-        BlogPost.findById(post.id, function (err, postRead) {
+        BlogPost.findById(post.id, function(err, postRead) {
           db.close();
           assert.ifError(err);
           // set the same data again back to the document.
@@ -310,7 +310,7 @@ describe('document modified', function () {
       });
     });
 
-    it('should let you set ref paths (gh-1530)', function (done) {
+    it('should let you set ref paths (gh-1530)', function(done) {
       var db = start();
 
       var parentSchema = new Schema({
@@ -322,13 +322,13 @@ describe('document modified', function () {
       });
 
       var preCalls = 0;
-      childSchema.pre('save', function (next) {
+      childSchema.pre('save', function(next) {
         ++preCalls;
         next();
       });
 
       var postCalls = 0;
-      childSchema.post('save', function (doc, next) {
+      childSchema.post('save', function(doc, next) {
         ++postCalls;
         next();
       });
@@ -339,22 +339,22 @@ describe('document modified', function () {
       p.child = c;
       assert.equal(p.child.name, 'Luke');
 
-      p.save(function (error) {
+      p.save(function(error) {
         assert.ifError(error);
         assert.equal(p.child.name, 'Luke');
         var originalParent = p;
-        Parent.findOne({}, function (error, p) {
+        Parent.findOne({}, function(error, p) {
           assert.ifError(error);
           assert.ok(p.child);
           assert.ok(typeof p.child.name === 'undefined');
           assert.equal(0, preCalls);
           assert.equal(0, postCalls);
-          Child.findOne({name: 'Luke'}, function (error, child) {
+          Child.findOne({name: 'Luke'}, function(error, child) {
             assert.ifError(error);
             assert.ok(!child);
-            originalParent.child.save(function (error) {
+            originalParent.child.save(function(error) {
               assert.ifError(error);
-              Child.findOne({name: 'Luke'}, function (error, child) {
+              Child.findOne({name: 'Luke'}, function(error, child) {
                 assert.ifError(error);
                 assert.ok(child);
                 assert.equal(child._id.toString(), p.child.toString());
@@ -366,7 +366,7 @@ describe('document modified', function () {
       });
     });
 
-    it('properly sets populated for gh-1530 (gh-2678)', function (done) {
+    it('properly sets populated for gh-1530 (gh-2678)', function(done) {
       var db = start();
 
       var parentSchema = new Schema({
@@ -384,18 +384,18 @@ describe('document modified', function () {
       db.close(done);
     });
 
-    describe('manually populating arrays', function () {
+    describe('manually populating arrays', function() {
       var db;
 
-      before(function () {
+      before(function() {
         db = start();
       });
 
-      after(function (done) {
+      after(function(done) {
         db.close(done);
       });
 
-      it('gh-1530 for arrays (gh-3575)', function (done) {
+      it('gh-1530 for arrays (gh-3575)', function(done) {
         var parentSchema = new Schema({
           name: String,
           children: [{type: Schema.Types.ObjectId, ref: 'Child'}]
@@ -412,7 +412,7 @@ describe('document modified', function () {
         done();
       });
 
-      it('setting nested arrays (gh-3721)', function (done) {
+      it('setting nested arrays (gh-3721)', function(done) {
         var userSchema = new Schema({
           name: {type: Schema.Types.String}
         });
@@ -439,7 +439,7 @@ describe('document modified', function () {
       });
     });
 
-    it('should support setting mixed paths by string (gh-1418)', function (done) {
+    it('should support setting mixed paths by string (gh-1418)', function(done) {
       var db = start();
       var BlogPost = db.model('1418', new Schema({mixed: {}}));
       var b = new BlogPost;
@@ -460,7 +460,7 @@ describe('document modified', function () {
       assert.equal(4, b.get(path));
 
       b = new BlogPost({mixed: {}});
-      b.save(function (err) {
+      b.save(function(err) {
         assert.ifError(err);
 
         path = 'mixed.9a.x';
@@ -468,9 +468,9 @@ describe('document modified', function () {
         assert.ok(b.isModified(path));
         assert.equal(8, b.get(path));
 
-        b.save(function (err) {
+        b.save(function(err) {
           assert.ifError(err);
-          BlogPost.findById(b, function (err, doc) {
+          BlogPost.findById(b, function(err, doc) {
             assert.ifError(err);
             assert.equal(8, doc.get(path));
             db.close(done);
@@ -479,7 +479,7 @@ describe('document modified', function () {
       });
     });
 
-    it('should mark multi-level nested schemas as modified (gh-1754)', function (done) {
+    it('should mark multi-level nested schemas as modified (gh-1754)', function(done) {
       var db = start();
 
       var grandChildSchema = new Schema({
@@ -499,14 +499,14 @@ describe('document modified', function () {
       var Parent = db.model('gh-1754', parentSchema);
       Parent.create(
           {child: [{name: 'Brian', grandChild: [{name: 'Jake'}]}]},
-          function (error, p) {
+          function(error, p) {
             assert.ifError(error);
             assert.ok(p);
             assert.equal(1, p.child.length);
             assert.equal(1, p.child[0].grandChild.length);
             p.child[0].grandChild[0].name = 'Jason';
             assert.ok(p.isModified('child.0.grandChild.0.name'));
-            p.save(function (error1, inDb) {
+            p.save(function(error1, inDb) {
               assert.ifError(error1);
               assert.equal('Jason', inDb.child[0].grandChild[0].name);
               db.close(done);
diff --git a/test/document.populate.test.js b/test/document.populate.test.js
index 82e7422c585..95bf82a95f9 100644
--- a/test/document.populate.test.js
+++ b/test/document.populate.test.js
@@ -35,7 +35,7 @@ TestDocument.prototype.__proto__ = Document.prototype;
  */
 
 var em = new Schema({title: String, body: String});
-em.virtual('works').get(function () {
+em.virtual('works').get(function() {
   return 'em virtual works';
 });
 var schema = new Schema({
@@ -99,11 +99,11 @@ mongoose.model('doc.populate.b', BlogPost);
 mongoose.model('doc.populate.u', User);
 mongoose.model('doc.populate.u2', User);
 
-describe('document.populate', function () {
+describe('document.populate', function() {
   var db, B, User;
   var user1, user2, post, _id;
 
-  before(function (done) {
+  before(function(done) {
     db = start();
     B = db.model('doc.populate.b');
     User = db.model('doc.populate.u');
@@ -118,7 +118,7 @@ describe('document.populate', function () {
       name: 'Newark',
       email: 'ewr@nj.com',
       blogposts: [_id]
-    }, function (err, u1, u2) {
+    }, function(err, u1, u2) {
       assert.ifError(err);
 
       user1 = u1;
@@ -129,7 +129,7 @@ describe('document.populate', function () {
         _creator: user1,
         fans: [user1, user2],
         comments: [{_creator: user2, content: 'user2'}, {_creator: user1, content: 'user1'}]
-      }, function (err, p) {
+      }, function(err, p) {
         assert.ifError(err);
         post = p;
         done();
@@ -137,14 +137,14 @@ describe('document.populate', function () {
     });
   });
 
-  after(function (done) {
+  after(function(done) {
     db.close(done);
   });
 
-  describe('argument processing', function () {
-    describe('duplicates', function () {
-      it('are removed', function (done) {
-        B.findById(post, function (err, post) {
+  describe('argument processing', function() {
+    describe('duplicates', function() {
+      it('are removed', function(done) {
+        B.findById(post, function(err, post) {
           assert.ifError(err);
           post.populate('_creator');
           assert.equal(1, Object.keys(post.$__.populate).length);
@@ -163,8 +163,8 @@ describe('document.populate', function () {
           done();
         });
       });
-      it('overwrite previous', function (done) {
-        B.findById(post, function (err, post) {
+      it('overwrite previous', function(done) {
+        B.findById(post, function(err, post) {
           assert.ifError(err);
           post.populate('_creator');
           assert.equal(1, Object.keys(post.$__.populate).length);
@@ -179,11 +179,11 @@ describe('document.populate', function () {
     });
   });
 
-  describe('options', function () {
-    it('resets populate options after execution', function (done) {
-      B.findById(post, function (err, post) {
+  describe('options', function() {
+    it('resets populate options after execution', function(done) {
+      B.findById(post, function(err, post) {
         var creator_id = post._creator;
-        post.populate('_creator', function (err) {
+        post.populate('_creator', function(err) {
           assert.ifError(err);
           assert.ok(!post.$__.populate);
           assert.ok(post._creator);
@@ -193,7 +193,7 @@ describe('document.populate', function () {
       });
     });
 
-    it('are not modified when no arguments are passed', function (done) {
+    it('are not modified when no arguments are passed', function(done) {
       var d = new TestDocument();
       var o = utils.clone(d.options);
       assert.deepEqual(o, d.populate().options);
@@ -201,12 +201,12 @@ describe('document.populate', function () {
     });
   });
 
-  describe('populating two paths', function () {
-    it('with space delmited string works', function (done) {
-      B.findById(post, function (err, post) {
+  describe('populating two paths', function() {
+    it('with space delmited string works', function(done) {
+      B.findById(post, function(err, post) {
         var creator_id = post._creator;
         var alt_id = post.fans[1];
-        post.populate('_creator fans', function (err) {
+        post.populate('_creator fans', function(err) {
           assert.ifError(err);
           assert.ok(post._creator);
           assert.equal(String(creator_id), String(post._creator._id));
@@ -218,11 +218,11 @@ describe('document.populate', function () {
     });
   });
 
-  it('works with just a callback', function (done) {
-    B.findById(post, function (err, post) {
+  it('works with just a callback', function(done) {
+    B.findById(post, function(err, post) {
       var creator_id = post._creator;
       var alt_id = post.fans[1];
-      post.populate('_creator').populate(function (err) {
+      post.populate('_creator').populate(function(err) {
         assert.ifError(err);
         assert.ok(post._creator);
         assert.equal(String(creator_id), String(post._creator._id));
@@ -232,8 +232,8 @@ describe('document.populate', function () {
     });
   });
 
-  it('populating using space delimited paths with options', function (done) {
-    B.findById(post, function (err, post) {
+  it('populating using space delimited paths with options', function(done) {
+    B.findById(post, function(err, post) {
       var param = {};
       param.select = '-email';
       param.options = {sort: 'name'};
@@ -241,7 +241,7 @@ describe('document.populate', function () {
 
       var creator_id = post._creator;
       var alt_id = post.fans[1];
-      post.populate(param, function (err, post) {
+      post.populate(param, function(err, post) {
         assert.ifError(err);
         assert.equal(2, post.fans.length);
         assert.equal(String(creator_id), String(post._creator._id));
@@ -256,8 +256,8 @@ describe('document.populate', function () {
     });
   });
 
-  it('using multiple populate calls', function (done) {
-    B.findById(post, function (err, post) {
+  it('using multiple populate calls', function(done) {
+    B.findById(post, function(err, post) {
       var creator_id = post._creator;
       var alt_id = post.fans[1];
 
@@ -268,7 +268,7 @@ describe('document.populate', function () {
       post.populate(param);
       param.path = 'fans';
 
-      post.populate(param, function (err, post) {
+      post.populate(param, function(err, post) {
         assert.ifError(err);
         assert.equal(2, post.fans.length);
         assert.equal(String(creator_id), String(post._creator._id));
@@ -283,8 +283,8 @@ describe('document.populate', function () {
     });
   });
 
-  it('with custom model selection', function (done) {
-    B.findById(post, function (err, post) {
+  it('with custom model selection', function(done) {
+    B.findById(post, function(err, post) {
       var param = {};
       param.select = '-email';
       param.options = {sort: 'name'};
@@ -293,7 +293,7 @@ describe('document.populate', function () {
 
       var creator_id = post._creator;
       var alt_id = post.fans[1];
-      post.populate(param, function (err, post) {
+      post.populate(param, function(err, post) {
         assert.ifError(err);
         assert.equal(2, post.fans.length);
         assert.equal(String(creator_id), String(post._creator._id));
@@ -308,17 +308,17 @@ describe('document.populate', function () {
     });
   });
 
-  it('a property not in schema', function (done) {
-    B.findById(post, function (err, post) {
+  it('a property not in schema', function(done) {
+    B.findById(post, function(err, post) {
       assert.ifError(err);
-      post.populate('idontexist', function (err) {
+      post.populate('idontexist', function(err) {
         assert.ifError(err);
 
         // stuff an ad-hoc value in
         post.setValue('idontexist', user1._id);
 
         // populate the non-schema value by passing an explicit model
-        post.populate({path: 'idontexist', model: 'doc.populate.u'}, function (err, post) {
+        post.populate({path: 'idontexist', model: 'doc.populate.u'}, function(err, post) {
           assert.ifError(err);
           assert.ok(post);
           assert.equal(post.get('idontexist')._id, user1._id.toString());
@@ -329,37 +329,37 @@ describe('document.populate', function () {
     });
   });
 
-  it('of empty array', function (done) {
-    B.findById(post, function (err, post) {
+  it('of empty array', function(done) {
+    B.findById(post, function(err, post) {
       post.fans = [];
-      post.populate('fans', function (err) {
+      post.populate('fans', function(err) {
         assert.ifError(err);
         done();
       });
     });
   });
 
-  it('of array of null/undefined', function (done) {
-    B.findById(post, function (err, post) {
+  it('of array of null/undefined', function(done) {
+    B.findById(post, function(err, post) {
       post.fans = [null, undefined];
-      post.populate('fans', function (err) {
+      post.populate('fans', function(err) {
         assert.ifError(err);
         done();
       });
     });
   });
 
-  it('of null property', function (done) {
-    B.findById(post, function (err, post) {
+  it('of null property', function(done) {
+    B.findById(post, function(err, post) {
       post._creator = null;
-      post.populate('_creator', function (err) {
+      post.populate('_creator', function(err) {
         assert.ifError(err);
         done();
       });
     });
   });
 
-  it('String _ids', function (done) {
+  it('String _ids', function(done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -377,11 +377,11 @@ describe('document.populate', function () {
 
     var alice = new User({_id: 'alice', name: 'Alice In Wonderland'});
 
-    alice.save(function (err) {
+    alice.save(function(err) {
       assert.ifError(err);
 
       var note = new Note({author: 'alice', body: 'Buy Milk'});
-      note.populate('author', function (err) {
+      note.populate('author', function(err) {
         db.close();
         assert.ifError(err);
         assert.ok(note.author);
@@ -392,7 +392,7 @@ describe('document.populate', function () {
     });
   });
 
-  it('Buffer _ids', function (done) {
+  it('Buffer _ids', function(done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -410,17 +410,17 @@ describe('document.populate', function () {
 
     var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: 'Alice'});
 
-    alice.save(function (err) {
+    alice.save(function(err) {
       assert.ifError(err);
 
       var note = new Note({author: 'alice', body: 'Buy Milk'});
-      note.save(function (err) {
+      note.save(function(err) {
         assert.ifError(err);
 
-        Note.findById(note.id, function (err, note) {
+        Note.findById(note.id, function(err, note) {
           assert.ifError(err);
           assert.equal('alice', note.author);
-          note.populate('author', function (err, note) {
+          note.populate('author', function(err, note) {
             db.close();
             assert.ifError(err);
             assert.equal(note.body, 'Buy Milk');
@@ -433,7 +433,7 @@ describe('document.populate', function () {
     });
   });
 
-  it('Number _ids', function (done) {
+  it('Number _ids', function(done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -451,11 +451,11 @@ describe('document.populate', function () {
 
     var alice = new User({_id: 2359, name: 'Alice'});
 
-    alice.save(function (err) {
+    alice.save(function(err) {
       assert.ifError(err);
 
       var note = new Note({author: 2359, body: 'Buy Milk'});
-      note.populate('author').populate(function (err, note) {
+      note.populate('author').populate(function(err, note) {
         db.close();
         assert.ifError(err);
         assert.ok(note.author);
@@ -466,12 +466,12 @@ describe('document.populate', function () {
     });
   });
 
-  describe('sub-level properties', function () {
-    it('with string arg', function (done) {
-      B.findById(post, function (err, post) {
+  describe('sub-level properties', function() {
+    it('with string arg', function(done) {
+      B.findById(post, function(err, post) {
         var id0 = post.comments[0]._creator;
         var id1 = post.comments[1]._creator;
-        post.populate('comments._creator', function (err, post) {
+        post.populate('comments._creator', function(err, post) {
           assert.ifError(err);
           assert.equal(2, post.comments.length);
           assert.equal(id0, post.comments[0]._creator.id);
@@ -482,15 +482,15 @@ describe('document.populate', function () {
     });
   });
 
-  describe('of new document', function () {
-    it('should save just the populated _id (gh-1442)', function (done) {
+  describe('of new document', function() {
+    it('should save just the populated _id (gh-1442)', function(done) {
       var b = new B({_creator: user1});
-      b.populate('_creator', function (err, b) {
+      b.populate('_creator', function(err, b) {
         if (err) return done(err);
         assert.equal('Phoenix', b._creator.name);
-        b.save(function (err) {
+        b.save(function(err) {
           assert.ifError(err);
-          B.collection.findOne({_id: b._id}, function (err, b) {
+          B.collection.findOne({_id: b._id}, function(err, b) {
             assert.ifError(err);
             assert.equal(b._creator, String(user1._id));
             done();
@@ -500,7 +500,7 @@ describe('document.populate', function () {
     });
   });
 
-  it('gh-3308', function (done) {
+  it('gh-3308', function(done) {
     var db = start();
 
     var Person = db.model('gh3308', {
@@ -525,8 +525,8 @@ describe('document.populate', function () {
     db.close(done);
   });
 
-  describe('gh-2214', function () {
-    it('should return a real document array when populating', function (done) {
+  describe('gh-2214', function() {
+    it('should return a real document array when populating', function(done) {
       var db = start();
 
       var Car = db.model('gh-2214-1', {
@@ -554,10 +554,10 @@ describe('document.populate', function () {
       });
       joe.cars.push(car);
 
-      return joe.save(function () {
-        return car.save(function () {
-          return Person.findById(joe.id, function (err, joe) {
-            return joe.populate('cars', function () {
+      return joe.save(function() {
+        return car.save(function() {
+          return Person.findById(joe.id, function(err, joe) {
+            return joe.populate('cars', function() {
               car = new Car({
                 model: 'BMW',
                 color: 'black'
@@ -573,7 +573,7 @@ describe('document.populate', function () {
     });
   });
 
-  it('can depopulate (gh-2509)', function (done) {
+  it('can depopulate (gh-2509)', function(done) {
     var db = start();
 
     var Person = db.model('gh2509_1', {
@@ -587,15 +587,15 @@ describe('document.populate', function () {
     });
 
     var people = [{name: 'Axl Rose'}, {name: 'Slash'}];
-    Person.create(people, function (error, docs) {
+    Person.create(people, function(error, docs) {
       assert.ifError(error);
       var band = {
-        name: "Guns N' Roses",
+        name: 'Guns N\' Roses',
         members: [docs[0]._id, docs[1]],
         lead: docs[0]._id
       };
-      Band.create(band, function (error, band) {
-        band.populate('members', function () {
+      Band.create(band, function(error, band) {
+        band.populate('members', function() {
           assert.equal(band.members[0].name, 'Axl Rose');
           band.depopulate('members');
           assert.ok(!band.members[0].name);
@@ -603,7 +603,7 @@ describe('document.populate', function () {
           assert.equal(band.members[1].toString(), docs[1]._id.toString());
           assert.ok(!band.populated('members'));
           assert.ok(!band.populated('lead'));
-          band.populate('lead', function () {
+          band.populate('lead', function() {
             assert.equal(band.lead.name, 'Axl Rose');
             band.depopulate('lead');
             assert.ok(!band.lead.name);
@@ -615,7 +615,7 @@ describe('document.populate', function () {
     });
   });
 
-  it('handles pulling from populated array (gh-3579)', function (done) {
+  it('handles pulling from populated array (gh-3579)', function(done) {
     var db = start();
     var barSchema = new Schema({name: String});
 
@@ -630,13 +630,13 @@ describe('document.populate', function () {
 
     var Foo = db.model('gh3579_0', fooSchema);
 
-    Bar.create([{name: 'bar1'}, {name: 'bar2'}], function (error, docs) {
+    Bar.create([{name: 'bar1'}, {name: 'bar2'}], function(error, docs) {
       assert.ifError(error);
       var foo = new Foo({bars: [docs[0], docs[1]]});
       foo.bars.pull(docs[0]._id);
-      foo.save(function (error) {
+      foo.save(function(error) {
         assert.ifError(error);
-        Foo.findById(foo._id, function (error, foo) {
+        Foo.findById(foo._id, function(error, foo) {
           assert.ifError(error);
           assert.equal(foo.bars.length, 1);
           assert.equal(foo.bars[0].toString(), docs[1]._id.toString());
diff --git a/test/document.strict.test.js b/test/document.strict.test.js
index 0940be531cf..fc51d27f58d 100644
--- a/test/document.strict.test.js
+++ b/test/document.strict.test.js
@@ -8,11 +8,11 @@ var start = require('./common'),
     random = require('../lib/utils').random,
     Schema = mongoose.Schema;
 
-describe('document: strict mode:', function () {
-  describe('should work', function () {
+describe('document: strict mode:', function() {
+  describe('should work', function() {
     var db, Lax, Strict;
 
-    before(function () {
+    before(function() {
       db = start();
 
       var raw = {
@@ -30,11 +30,11 @@ describe('document: strict mode:', function () {
       Strict = db.model('Strict', strict);
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('when creating models with non-strict schemas', function (done) {
+    it('when creating models with non-strict schemas', function(done) {
       var l = new Lax({content: 'sample', rouge: 'data'});
       assert.equal(false, l.$__.strictMode);
 
@@ -48,7 +48,7 @@ describe('document: strict mode:', function () {
       done();
     });
 
-    it('when creating models with strict schemas', function (done) {
+    it('when creating models with strict schemas', function(done) {
       var s = new Strict({content: 'sample', rouge: 'data'});
       assert.equal(true, s.$__.strictMode);
 
@@ -64,7 +64,7 @@ describe('document: strict mode:', function () {
       done();
     });
 
-    it('when overriding strictness', function (done) {
+    it('when overriding strictness', function(done) {
       // instance override
       var instance = new Lax({content: 'sample', rouge: 'data'}, true);
       assert.ok(instance.$__.strictMode);
@@ -92,9 +92,9 @@ describe('document: strict mode:', function () {
       done();
     });
 
-    it('when using Model#create', function (done) {
+    it('when using Model#create', function(done) {
       // strict on create
-      Strict.create({content: 'sample2', rouge: 'data'}, function (err, doc) {
+      Strict.create({content: 'sample2', rouge: 'data'}, function(err, doc) {
         assert.equal('sample2', doc.content);
         assert.ok(!('rouge' in doc));
         assert.ok(!doc.rouge);
@@ -102,12 +102,12 @@ describe('document: strict mode:', function () {
       });
     });
 
-    after(function () {
+    after(function() {
       db.close();
     });
   });
 
-  it('nested doc', function (done) {
+  it('nested doc', function(done) {
     var db = start();
 
     var lax = new Schema({
@@ -145,7 +145,7 @@ describe('document: strict mode:', function () {
     db.close(done);
   });
 
-  it('sub doc', function (done) {
+  it('sub doc', function(done) {
     var db = start();
 
     var lax = new Schema({
@@ -185,7 +185,7 @@ describe('document: strict mode:', function () {
     assert.ok(!s3.dox[0].rouge);
 
     // strict on create
-    Strict.create({dox: [{content: 'sample2', rouge: 'data'}]}, function (err, doc) {
+    Strict.create({dox: [{content: 'sample2', rouge: 'data'}]}, function(err, doc) {
       assert.equal('sample2', doc.dox[0].content);
       assert.ok(!('rouge' in doc.dox[0]));
       assert.ok(!doc.dox[0].rouge);
@@ -193,7 +193,7 @@ describe('document: strict mode:', function () {
     });
   });
 
-  it('virtuals', function (done) {
+  it('virtuals', function(done) {
     var db = start();
 
     var getCount = 0,
@@ -206,11 +206,11 @@ describe('document: strict mode:', function () {
 
     strictSchema
     .virtual('myvirtual')
-    .get(function () {
+    .get(function() {
       getCount++;
       return 'ok';
     })
-    .set(function (v) {
+    .set(function(v) {
       setCount++;
       this.prop = v;
     });
@@ -237,7 +237,7 @@ describe('document: strict mode:', function () {
     db.close(done);
   });
 
-  it('can be overridden during set()', function (done) {
+  it('can be overridden during set()', function(done) {
     var db = start();
 
     var strict = new Schema({
@@ -251,16 +251,16 @@ describe('document: strict mode:', function () {
     var doc = s.toObject();
     doc.notInSchema = true;
 
-    Strict.collection.insert(doc, {w: 1}, function (err) {
+    Strict.collection.insert(doc, {w: 1}, function(err) {
       assert.ifError(err);
-      Strict.findById(doc._id, function (err, doc) {
+      Strict.findById(doc._id, function(err, doc) {
         assert.ifError(err);
         assert.equal(true, doc._doc.bool);
         assert.equal(true, doc._doc.notInSchema);
         doc.bool = undefined;
         doc.set('notInSchema', undefined, {strict: false});
-        doc.save(function () {
-          Strict.findById(doc._id, function (err, doc) {
+        doc.save(function() {
+          Strict.findById(doc._id, function(err, doc) {
             assert.ifError(err);
             assert.equal(undefined, doc._doc.bool);
             assert.equal(undefined, doc._doc.notInSchema);
@@ -271,7 +271,7 @@ describe('document: strict mode:', function () {
     });
   });
 
-  it('can be overridden during update()', function (done) {
+  it('can be overridden during update()', function(done) {
     var db = start();
 
     var strict = new Schema({
@@ -285,19 +285,19 @@ describe('document: strict mode:', function () {
     var doc = s.toObject();
     doc.notInSchema = true;
 
-    Strict.collection.insert(doc, {w: 1}, function (err) {
+    Strict.collection.insert(doc, {w: 1}, function(err) {
       assert.ifError(err);
 
-      Strict.findById(doc._id, function (err, doc) {
+      Strict.findById(doc._id, function(err, doc) {
         assert.ifError(err);
         assert.equal(true, doc._doc.bool);
         assert.equal(true, doc._doc.notInSchema);
 
         Strict.update({_id: doc._id}, {$unset: {bool: 1, notInSchema: 1}}, {strict: false, w: 1},
-            function (err) {
+            function(err) {
               assert.ifError(err);
 
-              Strict.findById(doc._id, function (err, doc) {
+              Strict.findById(doc._id, function(err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(undefined, doc._doc.bool);
@@ -309,7 +309,7 @@ describe('document: strict mode:', function () {
     });
   });
 
-  it('can be overwritten with findOneAndUpdate (gh-1967)', function (done) {
+  it('can be overwritten with findOneAndUpdate (gh-1967)', function(done) {
     var db = start();
 
     var strict = new Schema({
@@ -323,19 +323,19 @@ describe('document: strict mode:', function () {
     var doc = s.toObject();
     doc.notInSchema = true;
 
-    Strict.collection.insert(doc, {w: 1}, function (err) {
+    Strict.collection.insert(doc, {w: 1}, function(err) {
       assert.ifError(err);
 
-      Strict.findById(doc._id, function (err, doc) {
+      Strict.findById(doc._id, function(err, doc) {
         assert.ifError(err);
         assert.equal(true, doc._doc.bool);
         assert.equal(true, doc._doc.notInSchema);
 
         Strict.findOneAndUpdate({_id: doc._id}, {$unset: {bool: 1, notInSchema: 1}}, {strict: false, w: 1},
-            function (err) {
+            function(err) {
               assert.ifError(err);
 
-              Strict.findById(doc._id, function (err, doc) {
+              Strict.findById(doc._id, function(err, doc) {
                 assert.ifError(err);
                 assert.equal(undefined, doc._doc.bool);
                 assert.equal(undefined, doc._doc.notInSchema);
@@ -346,8 +346,8 @@ describe('document: strict mode:', function () {
     });
   });
 
-  describe('"throws" mode', function () {
-    it('throws on set() of unknown property', function (done) {
+  describe('"throws" mode', function() {
+    it('throws on set() of unknown property', function(done) {
       var schema = new Schema({n: String, docs: [{x: [{y: String}]}]});
       schema.set('strict', 'throw');
       var M = mongoose.model('throwStrictSet', schema, 'tss_' + random());
@@ -355,46 +355,46 @@ describe('document: strict mode:', function () {
 
       var badField = /Field `[\w\.]+` is not in schema/;
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.set('unknown.stuff.is.here', 3);
       }, badField);
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.set('n.something', 3);
       }, badField);
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.set('n.3', 3);
       }, badField);
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.set('z', 3);
       }, badField);
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.set('docs.z', 3);
       }, badField);
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.set('docs.0.z', 3);
       }, badField);
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.set('docs.0.x.z', 3);
       }, badField);
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.set('docs.0.x.4.z', 3);
       }, badField);
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.set('docs.0.x.4.y.z', 3);
       }, badField);
 
       done();
     });
 
-    it('fails with extra fields', function (done) {
+    it('fails with extra fields', function(done) {
       // Simple schema with throws option
       var FooSchema = new mongoose.Schema({
         name: {type: String}
@@ -403,11 +403,11 @@ describe('document: strict mode:', function () {
       // Create the model
       var Foo = mongoose.model('Foo1234', FooSchema);
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         new Foo({name: 'bar'});
       });
 
-      assert.throws(function () {
+      assert.throws(function() {
         // The extra baz field should throw
         new Foo({name: 'bar', baz: 'bam'});
       }, /Field `baz` is not in schema/);
@@ -415,7 +415,7 @@ describe('document: strict mode:', function () {
       done();
     });
 
-    it('doesnt throw with refs (gh-2665)', function (done) {
+    it('doesnt throw with refs (gh-2665)', function(done) {
       // Simple schema with throws option
       var FooSchema = new mongoose.Schema({
         name: {type: mongoose.Schema.Types.ObjectId, ref: 'test', required: false, default: null},
@@ -425,14 +425,14 @@ describe('document: strict mode:', function () {
       // Create the model
       var Foo = mongoose.model('Foo', FooSchema);
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         new Foo({name: mongoose.Types.ObjectId(), father: {name: {full: 'bacon'}}});
       });
 
       done();
     });
 
-    it('set nested to num throws ObjectExpectedError (gh-3735)', function (done) {
+    it('set nested to num throws ObjectExpectedError (gh-3735)', function(done) {
       var schema = new Schema({
         resolved: {
           by: {type: String}
@@ -441,7 +441,7 @@ describe('document: strict mode:', function () {
 
       var Test = mongoose.model('gh3735', schema);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Test({resolved: 123});
       }, /ObjectExpectedError/);
       done();
diff --git a/test/document.test.js b/test/document.test.js
index e97400856d7..b4768bc3c94 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -36,7 +36,7 @@ TestDocument.prototype.__proto__ = Document.prototype;
  */
 
 var em = new Schema({title: String, body: String});
-em.virtual('works').get(function () {
+em.virtual('works').get(function() {
   return 'em virtual works';
 });
 var schema = new Schema({
@@ -63,21 +63,21 @@ var schema = new Schema({
 });
 TestDocument.prototype.$__setSchema(schema);
 
-schema.virtual('nested.agePlus2').get(function () {
+schema.virtual('nested.agePlus2').get(function() {
   return this.nested.age + 2;
 });
-schema.virtual('nested.setAge').set(function (v) {
+schema.virtual('nested.setAge').set(function(v) {
   this.nested.age = v;
 });
-schema.path('nested.path').get(function (v) {
+schema.path('nested.path').get(function(v) {
   return (this.nested.age || '') + (v ? v : '');
 });
-schema.path('nested.setr').set(function (v) {
+schema.path('nested.setr').set(function(v) {
   return v + ' setter';
 });
 
 var dateSetterCalled = false;
-schema.path('date').set(function (v) {
+schema.path('date').set(function(v) {
   // should not have been cast to a Date yet
   if (v !== undefined) {
     assert.equal('string', typeof v);
@@ -91,7 +91,7 @@ schema.path('date').set(function (v) {
  * executed.
  */
 
-TestDocument.prototype.hooksTest = function (fn) {
+TestDocument.prototype.hooksTest = function(fn) {
   fn(null, arguments);
 };
 
@@ -106,16 +106,16 @@ var parentSchema = new Schema({
  * Test.
  */
 
-describe('document', function () {
-  describe('shortcut getters', function () {
-    it('return undefined for properties with a null/undefined parent object (gh-1326)', function (done) {
+describe('document', function() {
+  describe('shortcut getters', function() {
+    it('return undefined for properties with a null/undefined parent object (gh-1326)', function(done) {
       var doc = new TestDocument;
       doc.init({nested: null});
       assert.strictEqual(undefined, doc.nested.age);
       done();
     });
 
-    it('work', function (done) {
+    it('work', function(done) {
       var doc = new TestDocument();
       doc.init({
         test: 'test',
@@ -192,7 +192,7 @@ describe('document', function () {
     });
   });
 
-  it('test shortcut setters', function (done) {
+  it('test shortcut setters', function(done) {
     var doc = new TestDocument();
 
     doc.init({
@@ -220,19 +220,19 @@ describe('document', function () {
     done();
   });
 
-  it('test accessor of id', function (done) {
+  it('test accessor of id', function(done) {
     var doc = new TestDocument();
     assert.ok(doc._id instanceof DocumentObjectId);
     done();
   });
 
-  it('test shortcut of id hexString', function (done) {
+  it('test shortcut of id hexString', function(done) {
     var doc = new TestDocument();
     assert.equal('string', typeof doc.id);
     done();
   });
 
-  it('test toObject clone', function (done) {
+  it('test toObject clone', function(done) {
     var doc = new TestDocument();
     doc.init({
       test: 'test',
@@ -257,7 +257,7 @@ describe('document', function () {
     done();
   });
 
-  it('toObject options', function (done) {
+  it('toObject options', function(done) {
     var doc = new TestDocument();
 
     doc.init({
@@ -366,7 +366,7 @@ describe('document', function () {
 
     // transform with return value
     var out = {myid: doc._id.toString()};
-    doc.schema.options.toObject.transform = function (doc, ret) {
+    doc.schema.options.toObject.transform = function(doc, ret) {
       // ignore embedded docs
       if (typeof doc.ownerDocument === 'function') {
         return;
@@ -394,7 +394,7 @@ describe('document', function () {
 
     // transform passed inline
     function xform(self, doc, opts) {
-      opts.fields.split(' ').forEach(function (field) {
+      opts.fields.split(' ').forEach(function(field) {
         delete doc[field];
       });
     }
@@ -415,7 +415,7 @@ describe('document', function () {
     done();
   });
 
-  it('toObject transform', function (done) {
+  it('toObject transform', function(done) {
     var schema = new Schema({
       name: String,
       places: [{type: ObjectId, ref: 'toObject-transform-places'}]
@@ -426,7 +426,7 @@ describe('document', function () {
     });
 
     schemaPlaces.set('toObject', {
-      transform: function (doc, ret) {
+      transform: function(doc, ret) {
         // here should be only toObject-transform-places documents
         assert.equal(doc.constructor.modelName, 'toObject-transform-places');
         return ret;
@@ -437,10 +437,10 @@ describe('document', function () {
         Test = db.model('toObject-transform', schema),
         Places = db.model('toObject-transform-places', schemaPlaces);
 
-    Places.create({identity: 'a'}, {identity: 'b'}, {identity: 'c'}, function (err, a, b, c) {
-      Test.create({name: 'chetverikov', places: [a, b, c]}, function (err) {
+    Places.create({identity: 'a'}, {identity: 'b'}, {identity: 'c'}, function(err, a, b, c) {
+      Test.create({name: 'chetverikov', places: [a, b, c]}, function(err) {
         assert.ifError(err);
-        Test.findOne({}).populate('places').exec(function (err, docs) {
+        Test.findOne({}).populate('places').exec(function(err, docs) {
           assert.ifError(err);
 
           docs.toObject({transform: true});
@@ -451,20 +451,20 @@ describe('document', function () {
     });
   });
 
-  it('allows you to skip validation on save (gh-2981)', function (done) {
+  it('allows you to skip validation on save (gh-2981)', function(done) {
     var db = start();
 
     var MyModel = db.model('gh2981',
         {name: {type: String, required: true}});
 
     var doc = new MyModel();
-    doc.save({validateBeforeSave: false}, function (error) {
+    doc.save({validateBeforeSave: false}, function(error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('doesnt use custom toObject options on save', function (done) {
+  it('doesnt use custom toObject options on save', function(done) {
     var schema = new Schema({
       name: String,
       iWillNotBeDelete: Boolean,
@@ -474,7 +474,7 @@ describe('document', function () {
     });
 
     schema.set('toObject', {
-      transform: function (doc, ret) {
+      transform: function(doc, ret) {
         delete ret.iWillNotBeDelete;
         delete ret.nested.iWillNotBeDeleteToo;
 
@@ -484,9 +484,9 @@ describe('document', function () {
     var db = start(),
         Test = db.model('TestToObject', schema);
 
-    Test.create({name: 'chetverikov', iWillNotBeDelete: true, 'nested.iWillNotBeDeleteToo': true}, function (err) {
+    Test.create({name: 'chetverikov', iWillNotBeDelete: true, 'nested.iWillNotBeDeleteToo': true}, function(err) {
       assert.ifError(err);
-      Test.findOne({}, function (err, doc) {
+      Test.findOne({}, function(err, doc) {
         assert.ifError(err);
 
         assert.equal(doc._doc.iWillNotBeDelete, true);
@@ -497,14 +497,14 @@ describe('document', function () {
     });
   });
 
-  it('does not apply toObject functions of subdocuments to root document', function (done) {
+  it('does not apply toObject functions of subdocuments to root document', function(done) {
     var subdocSchema = new Schema({
       test: String,
       wow: String
     });
 
     subdocSchema.options.toObject = {};
-    subdocSchema.options.toObject.transform = function (doc, ret) {
+    subdocSchema.options.toObject.transform = function(doc, ret) {
       delete ret.wow;
     };
 
@@ -524,9 +524,9 @@ describe('document', function () {
         test: 'someOtherString',
         wow: 'thisIsAString'
       }]
-    }, function (err, doc) {
+    }, function(err, doc) {
       var obj = doc.toObject({
-        transform: function (doc, ret) {
+        transform: function(doc, ret) {
           ret.phew = 'new';
         }
       });
@@ -538,7 +538,7 @@ describe('document', function () {
     });
   });
 
-  it('handles child schema transforms', function (done) {
+  it('handles child schema transforms', function(done) {
     var db = start();
     var userSchema = new Schema({
       name: String,
@@ -551,13 +551,13 @@ describe('document', function () {
     });
 
     userSchema.options.toObject = {
-      transform: function (doc, ret) {
+      transform: function(doc, ret) {
         delete ret.email;
       }
     };
 
     topicSchema.options.toObject = {
-      transform: function (doc, ret) {
+      transform: function(doc, ret) {
         ret.title = ret.title.toLowerCase();
       }
     };
@@ -578,7 +578,7 @@ describe('document', function () {
     db.close(done);
   });
 
-  it('doesnt clobber child schema options when called with no params (gh-2035)', function (done) {
+  it('doesnt clobber child schema options when called with no params (gh-2035)', function(done) {
     var db = start();
     var userSchema = new Schema({
       firstName: String,
@@ -586,7 +586,7 @@ describe('document', function () {
       password: String
     });
 
-    userSchema.virtual('fullName').get(function () {
+    userSchema.virtual('fullName').get(function() {
       return this.firstName + ' ' + this.lastName;
     });
 
@@ -597,7 +597,7 @@ describe('document', function () {
       content: String
     });
 
-    postSchema.virtual('capContent').get(function () {
+    postSchema.virtual('capContent').get(function() {
       return this.content.toUpperCase();
     });
 
@@ -607,12 +607,12 @@ describe('document', function () {
 
     var user = new User({firstName: 'Joe', lastName: 'Smith', password: 'password'});
 
-    user.save(function (err, savedUser) {
+    user.save(function(err, savedUser) {
       assert.ifError(err);
       var post = new Post({owner: savedUser._id, content: 'lorem ipsum'});
-      post.save(function (err, savedPost) {
+      post.save(function(err, savedPost) {
         assert.ifError(err);
-        Post.findById(savedPost._id).populate('owner').exec(function (err, newPost) {
+        Post.findById(savedPost._id).populate('owner').exec(function(err, newPost) {
           assert.ifError(err);
           var obj = newPost.toObject();
           assert.equal(obj.owner.fullName, undefined);
@@ -622,7 +622,7 @@ describe('document', function () {
     });
   });
 
-  it('toJSON options', function (done) {
+  it('toJSON options', function(done) {
     var doc = new TestDocument();
 
     doc.init({
@@ -639,7 +639,7 @@ describe('document', function () {
 
     // override to check if toJSON gets fired
     var path = TestDocument.prototype.schema.path('em');
-    path.casterConstructor.prototype.toJSON = function () {
+    path.casterConstructor.prototype.toJSON = function() {
       return {};
     };
 
@@ -702,7 +702,7 @@ describe('document', function () {
 
     // transform with return value
     var out = {myid: doc._id.toString()};
-    doc.schema.options.toJSON.transform = function (doc, ret) {
+    doc.schema.options.toJSON.transform = function(doc, ret) {
       // ignore embedded docs
       if (typeof doc.ownerDocument === 'function') {
         return;
@@ -730,7 +730,7 @@ describe('document', function () {
 
     // transform passed inline
     function xform(self, doc, opts) {
-      opts.fields.split(' ').forEach(function (field) {
+      opts.fields.split(' ').forEach(function(field) {
         delete doc[field];
       });
     }
@@ -751,7 +751,7 @@ describe('document', function () {
     done();
   });
 
-  it('jsonifying an object', function (done) {
+  it('jsonifying an object', function(done) {
     var doc = new TestDocument({test: 'woot'}),
         oidString = doc._id.toString();
     // convert to json string
@@ -763,14 +763,14 @@ describe('document', function () {
     assert.equal(obj._id, oidString);
     done();
   });
-  it('jsonifying an object\'s populated items works (gh-1376)', function (done) {
+  it('jsonifying an object\'s populated items works (gh-1376)', function(done) {
     var db = start();
     var userSchema, User, groupSchema, Group;
 
     userSchema = new Schema({name: String});
     // includes virtual path when 'toJSON'
     userSchema.set('toJSON', {getters: true});
-    userSchema.virtual('hello').get(function () {
+    userSchema.virtual('hello').get(function() {
       return 'Hello, ' + this.name;
     });
     User = db.model('User', userSchema);
@@ -782,11 +782,11 @@ describe('document', function () {
 
     Group = db.model('Group', groupSchema);
 
-    User.create({name: 'Alice'}, {name: 'Bob'}, function (err, alice, bob) {
+    User.create({name: 'Alice'}, {name: 'Bob'}, function(err, alice, bob) {
       assert.ifError(err);
 
-      new Group({name: 'mongoose', _users: [alice, bob]}).save(function (err, group) {
-        Group.findById(group).populate('_users').exec(function (err, group) {
+      new Group({name: 'mongoose', _users: [alice, bob]}).save(function(err, group) {
+        Group.findById(group).populate('_users').exec(function(err, group) {
           assert.ifError(err);
           assert.ok(group.toJSON()._users[0].hello);
           db.close(done);
@@ -795,23 +795,23 @@ describe('document', function () {
     });
   });
 
-  describe('#update', function () {
-    it('returns a Query', function (done) {
+  describe('#update', function() {
+    it('returns a Query', function(done) {
       var mg = new mongoose.Mongoose;
       var M = mg.model('doc#update', {s: String});
       var doc = new M;
       assert.ok(doc.update() instanceof Query);
       done();
     });
-    it('calling update on document should relay to its model (gh-794)', function (done) {
+    it('calling update on document should relay to its model (gh-794)', function(done) {
       var db = start();
       var Docs = new Schema({text: String});
       var docs = db.model('docRelayUpdate', Docs);
       var d = new docs({text: 'A doc'});
       var called = false;
-      d.save(function () {
+      d.save(function() {
         var oldUpdate = docs.update;
-        docs.update = function (query, operation) {
+        docs.update = function(query, operation) {
           assert.equal(1, Object.keys(query).length);
           assert.equal(query._id, d._id);
           assert.equal(1, Object.keys(operation).length);
@@ -821,7 +821,7 @@ describe('document', function () {
           docs.update = oldUpdate;
           oldUpdate.apply(docs, arguments);
         };
-        d.update({$set: {text: 'A changed doc'}}, function (err) {
+        d.update({$set: {text: 'A changed doc'}}, function(err) {
           assert.ifError(err);
           assert.equal(true, called);
           db.close(done);
@@ -830,7 +830,7 @@ describe('document', function () {
     });
   });
 
-  it('toObject should not set undefined values to null', function (done) {
+  it('toObject should not set undefined values to null', function(done) {
     var doc = new TestDocument(),
         obj = doc.toObject();
 
@@ -839,14 +839,14 @@ describe('document', function () {
     done();
   });
 
-  describe('Errors', function () {
-    it('MongooseErrors should be instances of Error (gh-209)', function (done) {
+  describe('Errors', function() {
+    it('MongooseErrors should be instances of Error (gh-209)', function(done) {
       var MongooseError = require('../lib/error'),
           err = new MongooseError('Some message');
       assert.ok(err instanceof Error);
       done();
     });
-    it('ValidationErrors should be instances of Error', function (done) {
+    it('ValidationErrors should be instances of Error', function(done) {
       var ValidationError = Document.ValidationError,
           err = new ValidationError(new TestDocument);
       assert.ok(err instanceof Error);
@@ -854,14 +854,14 @@ describe('document', function () {
     });
   });
 
-  it('methods on embedded docs should work', function (done) {
+  it('methods on embedded docs should work', function(done) {
     var db = start(),
         ESchema = new Schema({name: String});
 
-    ESchema.methods.test = function () {
+    ESchema.methods.test = function() {
       return this.name + ' butter';
     };
-    ESchema.statics.ten = function () {
+    ESchema.statics.ten = function() {
       return 10;
     };
 
@@ -885,7 +885,7 @@ describe('document', function () {
     done();
   });
 
-  it('setting a positional path does not cast value to array', function (done) {
+  it('setting a positional path does not cast value to array', function(done) {
     var doc = new TestDocument;
     doc.init({numbers: [1, 3]});
     assert.equal(1, doc.numbers[0]);
@@ -896,13 +896,13 @@ describe('document', function () {
     done();
   });
 
-  it('no maxListeners warning should occur', function (done) {
+  it('no maxListeners warning should occur', function(done) {
     var db = start();
 
     var traced = false;
     var trace = console.trace;
 
-    console.trace = function () {
+    console.trace = function() {
       traced = true;
       console.trace = trace;
     };
@@ -930,35 +930,35 @@ describe('document', function () {
     done();
   });
 
-  it('unselected required fields should pass validation', function (done) {
+  it('unselected required fields should pass validation', function(done) {
     var db = start(),
         Tschema = new Schema({name: String, req: {type: String, required: true}}),
         T = db.model('unselectedRequiredFieldValidation', Tschema);
 
     var t = new T({name: 'teeee', req: 'i am required'});
-    t.save(function (err) {
+    t.save(function(err) {
       assert.ifError(err);
-      T.findById(t).select('name').exec(function (err, t) {
+      T.findById(t).select('name').exec(function(err, t) {
         assert.ifError(err);
         assert.equal(undefined, t.req);
         t.name = 'wooo';
-        t.save(function (err) {
+        t.save(function(err) {
           assert.ifError(err);
 
-          T.findById(t).select('name').exec(function (err, t) {
+          T.findById(t).select('name').exec(function(err, t) {
             assert.ifError(err);
             t.req = undefined;
-            t.save(function (err) {
+            t.save(function(err) {
               err = String(err);
               var invalid = /Path `req` is required./.test(err);
               assert.ok(invalid);
               t.req = 'it works again';
-              t.save(function (err) {
+              t.save(function(err) {
                 assert.ifError(err);
 
-                T.findById(t).select('_id').exec(function (err, t) {
+                T.findById(t).select('_id').exec(function(err, t) {
                   assert.ifError(err);
-                  t.save(function (err) {
+                  t.save(function(err) {
                     assert.ifError(err);
                     db.close(done);
                   });
@@ -971,15 +971,15 @@ describe('document', function () {
     });
   });
 
-  describe('#validate', function () {
+  describe('#validate', function() {
     var collection = 'validateschema_' + random();
 
-    it('works (gh-891)', function (done) {
+    it('works (gh-891)', function(done) {
       var db = start();
       var schema = null;
       var called = false;
 
-      var validate = [function () {
+      var validate = [function() {
         called = true;
         return true;
       }, 'BAM'];
@@ -991,15 +991,15 @@ describe('document', function () {
 
       var M = db.model('validateSchema', schema, collection);
       var m = new M({prop: 'gh891', nick: 'validation test'});
-      m.save(function (err) {
+      m.save(function(err) {
         assert.ifError(err);
         assert.equal(true, called);
         called = false;
-        M.findById(m, 'nick', function (err, m) {
+        M.findById(m, 'nick', function(err, m) {
           assert.equal(false, called);
           assert.ifError(err);
           m.nick = 'gh-891';
-          m.save(function (err) {
+          m.save(function(err) {
             assert.equal(false, called);
             assert.ifError(err);
             db.close(done);
@@ -1008,11 +1008,11 @@ describe('document', function () {
       });
     });
 
-    it('can return a promise', function (done) {
+    it('can return a promise', function(done) {
       var db = start();
       var schema = null;
 
-      var validate = [function () {
+      var validate = [function() {
         return true;
       }, 'BAM'];
 
@@ -1026,22 +1026,22 @@ describe('document', function () {
       var mBad = new M({prop: 'other'});
 
       var promise = m.validate();
-      promise.then(function () {
+      promise.then(function() {
         var promise2 = mBad.validate();
-        promise2.onReject(function (err) {
+        promise2.onReject(function(err) {
           assert.ok(!!err);
           clearTimeout(timeout);
           db.close(done);
         });
       });
 
-      var timeout = setTimeout(function () {
+      var timeout = setTimeout(function() {
         db.close();
         throw new Error('Promise not fulfilled!');
       }, 500);
     });
 
-    it('doesnt have stale cast errors (gh-2766)', function (done) {
+    it('doesnt have stale cast errors (gh-2766)', function(done) {
       var db = start();
       var testSchema = new Schema({name: String});
       var M = db.model('gh2766', testSchema);
@@ -1053,23 +1053,23 @@ describe('document', function () {
       m._id = '000000000000000000000001';
       assert.ok(m.$isValid('_id'));
       assert.ifError(m.validateSync());
-      m.validate(function (error) {
+      m.validate(function(error) {
         assert.ifError(error);
         db.close(done);
       });
     });
 
-    it('cast errors persist across validate() calls (gh-2766)', function (done) {
+    it('cast errors persist across validate() calls (gh-2766)', function(done) {
       var db = start();
       var testSchema = new Schema({name: String});
       var M = db.model('gh2766', testSchema);
 
       var m = new M({_id: 'this is not a valid _id'});
       assert.ok(!m.$isValid('_id'));
-      m.validate(function (error) {
+      m.validate(function(error) {
         assert.ok(error);
         assert.equal(error.errors['_id'].name, 'CastError');
-        m.validate(function (error) {
+        m.validate(function(error) {
           assert.ok(error);
           assert.equal(error.errors['_id'].name, 'CastError');
 
@@ -1082,7 +1082,7 @@ describe('document', function () {
       });
     });
 
-    it('returns a promise when there are no validators', function (done) {
+    it('returns a promise when there are no validators', function(done) {
       var db = start();
       var schema = null;
 
@@ -1092,44 +1092,44 @@ describe('document', function () {
       var m = new M();
 
       var promise = m.validate();
-      promise.then(function () {
+      promise.then(function() {
         clearTimeout(timeout);
         db.close();
         done();
       });
 
-      var timeout = setTimeout(function () {
+      var timeout = setTimeout(function() {
         db.close();
         throw new Error('Promise not fulfilled!');
       }, 500);
     });
 
-    describe('works on arrays', function () {
+    describe('works on arrays', function() {
       var db;
 
-      before(function (done) {
+      before(function(done) {
         db = start();
         done();
       });
 
-      after(function (done) {
+      after(function(done) {
         db.close(done);
       });
 
-      it('with required', function (done) {
+      it('with required', function(done) {
         var schema = new Schema({
           name: String,
           arr: {type: [], required: true}
         });
         var M = db.model('validateSchema-array1', schema, collection);
         var m = new M({name: 'gh1109-1'});
-        m.save(function (err) {
+        m.save(function(err) {
           assert.ok(/Path `arr` is required/.test(err));
           m.arr = [];
-          m.save(function (err) {
+          m.save(function(err) {
             assert.ok(/Path `arr` is required/.test(err));
             m.arr.push('works');
-            m.save(function (err) {
+            m.save(function(err) {
               assert.ifError(err);
               done();
             });
@@ -1137,7 +1137,7 @@ describe('document', function () {
         });
       });
 
-      it('with custom validator', function (done) {
+      it('with custom validator', function(done) {
         var called = false;
 
         function validator(val) {
@@ -1154,12 +1154,12 @@ describe('document', function () {
         var M = db.model('validateSchema-array2', schema, collection);
         var m = new M({name: 'gh1109-2', arr: [1]});
         assert.equal(false, called);
-        m.save(function (err) {
+        m.save(function(err) {
           assert.equal('ValidationError: BAM', String(err));
           assert.equal(true, called);
           m.arr.push(2);
           called = false;
-          m.save(function (err) {
+          m.save(function(err) {
             assert.equal(true, called);
             assert.ifError(err);
             done();
@@ -1167,7 +1167,7 @@ describe('document', function () {
         });
       });
 
-      it('with both required + custom validator', function (done) {
+      it('with both required + custom validator', function(done) {
         function validator(val) {
           return val && val.length > 1;
         }
@@ -1180,13 +1180,13 @@ describe('document', function () {
 
         var M = db.model('validateSchema-array3', schema, collection);
         var m = new M({name: 'gh1109-3'});
-        m.save(function (err) {
+        m.save(function(err) {
           assert.equal(err.errors.arr.message, 'Path `arr` is required.');
           m.arr.push({nice: true});
-          m.save(function (err) {
+          m.save(function(err) {
             assert.equal(String(err), 'ValidationError: BAM');
             m.arr.push(95);
-            m.save(function (err) {
+            m.save(function(err) {
               assert.ifError(err);
               done();
             });
@@ -1195,14 +1195,14 @@ describe('document', function () {
       });
     });
 
-    it('validator should run only once gh-1743', function (done) {
+    it('validator should run only once gh-1743', function(done) {
       var count = 0;
       var db = start();
 
       var Control = new Schema({
         test: {
           type: String,
-          validate: function (value, done) {
+          validate: function(value, done) {
             count++;
             return done(true);
           }
@@ -1220,20 +1220,20 @@ describe('document', function () {
         }]
       });
 
-      post.save(function () {
+      post.save(function() {
         assert.equal(count, 1);
         db.close(done);
       });
     });
 
-    it('validator should run only once per sub-doc gh-1743', function (done) {
+    it('validator should run only once per sub-doc gh-1743', function(done) {
       var count = 0;
       var db = start();
 
       var Control = new Schema({
         test: {
           type: String,
-          validate: function (value, done) {
+          validate: function(value, done) {
             count++;
             return done(true);
           }
@@ -1253,14 +1253,14 @@ describe('document', function () {
         }]
       });
 
-      post.save(function () {
+      post.save(function() {
         assert.equal(count, post.controls.length);
         db.close(done);
       });
     });
 
 
-    it('validator should run in parallel', function (done) {
+    it('validator should run in parallel', function(done) {
       // we set the time out to be double that of the validator - 1 (so that running in serial will be greater then that)
       this.timeout(1000);
       var db = start();
@@ -1290,7 +1290,7 @@ describe('document', function () {
         }]
       });
 
-      m.save(function (err) {
+      m.save(function(err) {
         assert.ifError(err);
         assert.equal(count, 4);
         db.close(done);
@@ -1298,7 +1298,7 @@ describe('document', function () {
     });
   });
 
-  it('#invalidate', function (done) {
+  it('#invalidate', function(done) {
     var db = start();
     var InvalidateSchema = null;
     var Post = null;
@@ -1314,7 +1314,7 @@ describe('document', function () {
     post.set({baz: 'val'});
     post.invalidate('baz', 'validation failed for path {PATH}');
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ok(err instanceof MongooseError);
       assert.ok(err instanceof ValidationError);
       assert.ok(err.errors.baz instanceof ValidatorError);
@@ -1322,7 +1322,7 @@ describe('document', function () {
       assert.equal(err.errors.baz.kind, 'user defined');
       assert.equal(err.errors.baz.path, 'baz');
 
-      post.save(function (err) {
+      post.save(function(err) {
         db.close();
         assert.strictEqual(err, null);
         done();
@@ -1330,8 +1330,8 @@ describe('document', function () {
     });
   });
 
-  describe('#equals', function () {
-    describe('should work', function () {
+  describe('#equals', function() {
+    describe('should work', function() {
       var db;
       var S;
       var N;
@@ -1339,7 +1339,7 @@ describe('document', function () {
       var B;
       var M;
 
-      before(function () {
+      before(function() {
         db = start();
         S = db.model('equals-S', new Schema({_id: String}));
         N = db.model('equals-N', new Schema({_id: Number}));
@@ -1348,23 +1348,23 @@ describe('document', function () {
         M = db.model('equals-I', new Schema({name: String}, {_id: false}));
       });
 
-      after(function (done) {
+      after(function(done) {
         db.close(done);
       });
 
-      it('with string _ids', function (done) {
+      it('with string _ids', function(done) {
         var s1 = new S({_id: 'one'});
         var s2 = new S({_id: 'one'});
         assert.ok(s1.equals(s2));
         done();
       });
-      it('with number _ids', function (done) {
+      it('with number _ids', function(done) {
         var n1 = new N({_id: 0});
         var n2 = new N({_id: 0});
         assert.ok(n1.equals(n2));
         done();
       });
-      it('with ObjectId _ids', function (done) {
+      it('with ObjectId _ids', function(done) {
         var id = new mongoose.Types.ObjectId;
         var o1 = new O({_id: id});
         var o2 = new O({_id: id});
@@ -1376,16 +1376,16 @@ describe('document', function () {
         assert.ok(o1.equals(o2));
         done();
       });
-      it('with Buffer _ids', function (done) {
+      it('with Buffer _ids', function(done) {
         var n1 = new B({_id: 0});
         var n2 = new B({_id: 0});
         assert.ok(n1.equals(n2));
         done();
       });
-      it('with _id disabled (gh-1687)', function (done) {
+      it('with _id disabled (gh-1687)', function(done) {
         var m1 = new M;
         var m2 = new M;
-        assert.doesNotThrow(function () {
+        assert.doesNotThrow(function() {
           m1.equals(m2);
         });
         done();
@@ -1393,9 +1393,9 @@ describe('document', function () {
     });
   });
 
-  describe('setter', function () {
-    describe('order', function () {
-      it('is applied correctly', function (done) {
+  describe('setter', function() {
+    describe('order', function() {
+      it('is applied correctly', function(done) {
         var date = 'Thu Aug 16 2012 09:45:59 GMT-0700';
         var d = new TestDocument();
         dateSetterCalled = false;
@@ -1409,22 +1409,22 @@ describe('document', function () {
       });
     });
 
-    it('works with undefined (gh-1892)', function (done) {
+    it('works with undefined (gh-1892)', function(done) {
       var d = new TestDocument();
       d.nested.setr = undefined;
       assert.equal('undefined setter', d.nested.setr);
       dateSetterCalled = false;
       d.date = undefined;
-      d.validate(function (err) {
+      d.validate(function(err) {
         assert.ifError(err);
         assert.ok(dateSetterCalled);
         done();
       });
     });
 
-    describe('on nested paths', function () {
-      describe('using set(path, object)', function () {
-        it('overwrites the entire object', function (done) {
+    describe('on nested paths', function() {
+      describe('using set(path, object)', function() {
+        it('overwrites the entire object', function(done) {
           var doc = new TestDocument();
 
           doc.init({
@@ -1508,7 +1508,7 @@ describe('document', function () {
           done();
         });
 
-        it('gh-1954', function (done) {
+        it('gh-1954', function(done) {
           var schema = new Schema({
             schedule: [new Schema({open: Number, close: Number})]
           });
@@ -1534,11 +1534,11 @@ describe('document', function () {
         });
       });
 
-      describe('when overwriting with a document instance', function () {
-        it('does not cause StackOverflows (gh-1234)', function (done) {
+      describe('when overwriting with a document instance', function() {
+        it('does not cause StackOverflows (gh-1234)', function(done) {
           var doc = new TestDocument({nested: {age: 35}});
           doc.nested = doc.nested;
-          assert.doesNotThrow(function () {
+          assert.doesNotThrow(function() {
             doc.nested.age;
           });
           done();
@@ -1547,14 +1547,14 @@ describe('document', function () {
     });
   });
 
-  describe('virtual', function () {
-    describe('setter', function () {
+  describe('virtual', function() {
+    describe('setter', function() {
       var val;
       var M;
 
-      before(function (done) {
+      before(function(done) {
         var schema = new mongoose.Schema({v: Number});
-        schema.virtual('thang').set(function (v) {
+        schema.virtual('thang').set(function(v) {
           val = v;
         });
 
@@ -1564,22 +1564,22 @@ describe('document', function () {
         done();
       });
 
-      it('works with objects', function (done) {
+      it('works with objects', function(done) {
         new M({thang: {}});
         assert.deepEqual({}, val);
         done();
       });
-      it('works with arrays', function (done) {
+      it('works with arrays', function(done) {
         new M({thang: []});
         assert.deepEqual([], val);
         done();
       });
-      it('works with numbers', function (done) {
+      it('works with numbers', function(done) {
         new M({thang: 4});
         assert.deepEqual(4, val);
         done();
       });
-      it('works with strings', function (done) {
+      it('works with strings', function(done) {
         new M({thang: '3'});
         assert.deepEqual('3', val);
         done();
@@ -1587,24 +1587,24 @@ describe('document', function () {
     });
   });
 
-  describe('gh-2082', function () {
-    it('works', function (done) {
+  describe('gh-2082', function() {
+    it('works', function(done) {
       var db = start();
       var Parent = db.model('gh2082', parentSchema, 'gh2082');
 
       var parent = new Parent({name: 'Hello'});
-      parent.save(function (err, parent) {
+      parent.save(function(err, parent) {
         assert.ifError(err);
         parent.children.push({counter: 0});
-        parent.save(function (err, parent) {
+        parent.save(function(err, parent) {
           assert.ifError(err);
           parent.children[0].counter += 1;
-          parent.save(function (err, parent) {
+          parent.save(function(err, parent) {
             assert.ifError(err);
             parent.children[0].counter += 1;
-            parent.save(function (err) {
+            parent.save(function(err) {
               assert.ifError(err);
-              Parent.findOne({}, function (error, parent) {
+              Parent.findOne({}, function(error, parent) {
                 assert.ifError(error);
                 assert.equal(2, parent.children[0].counter);
                 db.close(done);
@@ -1616,18 +1616,18 @@ describe('document', function () {
     });
   });
 
-  describe('gh-1933', function () {
-    it('works', function (done) {
+  describe('gh-1933', function() {
+    it('works', function(done) {
       var db = start();
       var M = db.model('gh1933', new Schema({id: String, field: Number}), 'gh1933');
 
-      M.create({}, function (error) {
+      M.create({}, function(error) {
         assert.ifError(error);
-        M.findOne({}, function (error, doc) {
+        M.findOne({}, function(error, doc) {
           assert.ifError(error);
           doc.__v = 123;
           doc.field = 5; // .push({ _id: '123', type: '456' });
-          doc.save(function (error) {
+          doc.save(function(error) {
             assert.ifError(error);
             db.close(done);
           });
@@ -1636,8 +1636,8 @@ describe('document', function () {
     });
   });
 
-  describe('gh-1638', function () {
-    it('works', function (done) {
+  describe('gh-1638', function() {
+    it('works', function(done) {
       var ItemChildSchema = new mongoose.Schema({
         name: {type: String, required: true, default: 'hello'}
       });
@@ -1657,12 +1657,12 @@ describe('document', function () {
         children: [c1, c2]
       });
 
-      p.save(function (error) {
+      p.save(function(error) {
         assert.ifError(error);
 
         c2.name = 'updated 2';
         p.children = [c2];
-        p.save(function (error, doc) {
+        p.save(function(error, doc) {
           assert.ifError(error);
           assert.equal(1, doc.children.length);
           db.close(done);
@@ -1671,8 +1671,8 @@ describe('document', function () {
     });
   });
 
-  describe('gh-2434', function () {
-    it('will save the new value', function (done) {
+  describe('gh-2434', function() {
+    it('will save the new value', function(done) {
       var ItemSchema = new mongoose.Schema({
         st: Number,
         s: []
@@ -1683,14 +1683,14 @@ describe('document', function () {
 
       var item = new Item({st: 1});
 
-      item.save(function (error) {
+      item.save(function(error) {
         assert.ifError(error);
         item.st = 3;
         item.s = [];
-        item.save(function (error) {
+        item.save(function(error) {
           assert.ifError(error);
           // item.st is 3 but may not be saved to DB
-          Item.findById(item._id, function (error, doc) {
+          Item.findById(item._id, function(error, doc) {
             assert.ifError(error);
             assert.equal(3, doc.st);
             db.close(done);
@@ -1700,14 +1700,14 @@ describe('document', function () {
     });
   });
 
-  it('properly calls queue functions (gh-2856)', function (done) {
+  it('properly calls queue functions (gh-2856)', function(done) {
     var personSchema = new mongoose.Schema({
       name: String
     });
 
     var db = start();
     var calledName;
-    personSchema.methods.fn = function () {
+    personSchema.methods.fn = function() {
       calledName = this.name;
     };
     personSchema.queue('fn');
@@ -1718,7 +1718,7 @@ describe('document', function () {
     db.close(done);
   });
 
-  it('applies toJSON transform correctly for populated docs (gh-2910) (gh-2990)', function (done) {
+  it('applies toJSON transform correctly for populated docs (gh-2910) (gh-2990)', function(done) {
     var db = start();
     var parentSchema = mongoose.Schema({
       c: {type: mongoose.Schema.Types.ObjectId, ref: 'gh-2910-1'}
@@ -1726,7 +1726,7 @@ describe('document', function () {
 
     var called = [];
     parentSchema.options.toJSON = {
-      transform: function (doc, ret) {
+      transform: function(doc, ret) {
         called.push(ret);
         return ret;
       }
@@ -1738,7 +1738,7 @@ describe('document', function () {
 
     var childCalled = [];
     childSchema.options.toJSON = {
-      transform: function (doc, ret) {
+      transform: function(doc, ret) {
         childCalled.push(ret);
         return ret;
       }
@@ -1747,9 +1747,9 @@ describe('document', function () {
     var Child = db.model('gh-2910-1', childSchema);
     var Parent = db.model('gh-2910-0', parentSchema);
 
-    Child.create({name: 'test'}, function (error, c) {
-      Parent.create({c: c._id}, function (error, p) {
-        Parent.findOne({_id: p._id}).populate('c').exec(function (error, p) {
+    Child.create({name: 'test'}, function(error, c) {
+      Parent.create({c: c._id}, function(error, p) {
+        Parent.findOne({_id: p._id}).populate('c').exec(function(error, p) {
           var doc = p.toJSON();
           assert.equal(called.length, 1);
           assert.equal(called[0]._id.toString(), p._id.toString());
@@ -1775,10 +1775,10 @@ describe('document', function () {
     });
   });
 
-  it('setters firing with objects on real paths (gh-2943)', function (done) {
+  it('setters firing with objects on real paths (gh-2943)', function(done) {
     var M = mongoose.model('gh2943', {
       myStr: {
-        type: String, set: function (v) {
+        type: String, set: function(v) {
           return v.value;
         }
       },
@@ -1794,8 +1794,8 @@ describe('document', function () {
     done();
   });
 
-  describe('gh-2782', function () {
-    it('should set data from a sub doc', function (done) {
+  describe('gh-2782', function() {
+    it('should set data from a sub doc', function(done) {
       var schema1 = new mongoose.Schema({
         data: {
           email: String
@@ -1816,7 +1816,7 @@ describe('document', function () {
     });
   });
 
-  it('set data from subdoc keys (gh-3346)', function (done) {
+  it('set data from subdoc keys (gh-3346)', function(done) {
     var schema1 = new mongoose.Schema({
       data: {
         email: String
@@ -1831,7 +1831,7 @@ describe('document', function () {
     done();
   });
 
-  it('doesnt attempt to cast generic objects as strings (gh-3030)', function (done) {
+  it('doesnt attempt to cast generic objects as strings (gh-3030)', function(done) {
     var M = mongoose.model('gh3030', {
       myStr: {
         type: String
@@ -1840,13 +1840,13 @@ describe('document', function () {
 
     var t = new M({myStr: {thisIs: 'anObject'}});
     assert.ok(!t.myStr);
-    t.validate(function (error) {
+    t.validate(function(error) {
       assert.ok(error);
       done();
     });
   });
 
-  it('single embedded schemas (gh-2689)', function (done) {
+  it('single embedded schemas (gh-2689)', function(done) {
     var db = start();
 
     var userSchema = new mongoose.Schema({
@@ -1855,7 +1855,7 @@ describe('document', function () {
     }, {_id: false, id: false});
 
     var userHookCount = 0;
-    userSchema.pre('save', function (next) {
+    userSchema.pre('save', function(next) {
       ++userHookCount;
       next();
     });
@@ -1866,7 +1866,7 @@ describe('document', function () {
     });
 
     var eventHookCount = 0;
-    eventSchema.pre('save', function (next) {
+    eventSchema.pre('save', function(next) {
       ++eventHookCount;
       next();
     });
@@ -1874,7 +1874,7 @@ describe('document', function () {
     var Event = db.model('gh2689', eventSchema);
 
     var e = new Event({name: 'test', user: {name: 123, email: 'val'}});
-    e.save(function (error) {
+    e.save(function(error) {
       assert.ifError(error);
       assert.strictEqual(e.user.name, '123');
       assert.equal(eventHookCount, 1);
@@ -1882,13 +1882,13 @@ describe('document', function () {
 
       Event.findOne(
           {user: {name: '123', email: 'val'}},
-          function (error, doc) {
+          function(error, doc) {
             assert.ifError(error);
             assert.ok(doc);
 
             Event.findOne(
                 {user: {$in: [{name: '123', email: 'val'}]}},
-                function (error, doc) {
+                function(error, doc) {
                   assert.ifError(error);
                   assert.ok(doc);
                   db.close(done);
@@ -1897,7 +1897,7 @@ describe('document', function () {
     });
   });
 
-  it('single embedded schemas with validation (gh-2689)', function (done) {
+  it('single embedded schemas with validation (gh-2689)', function(done) {
     var db = start();
 
     var userSchema = new mongoose.Schema({
@@ -1928,7 +1928,7 @@ describe('document', function () {
     db.close(done);
   });
 
-  it('single embedded schemas with markmodified (gh-2689)', function (done) {
+  it('single embedded schemas with markmodified (gh-2689)', function(done) {
     var db = start();
 
     var userSchema = new mongoose.Schema({
@@ -1944,7 +1944,7 @@ describe('document', function () {
     var Event = db.model('gh2689_2', eventSchema);
 
     var e = new Event({name: 'test', user: {email: 'a@b'}});
-    e.save(function (error, doc) {
+    e.save(function(error, doc) {
       assert.ifError(error);
       assert.ok(doc);
       assert.ok(!doc.isModified('user'));
@@ -1960,9 +1960,9 @@ describe('document', function () {
         $set: {'user.name': 'Val'}
       });
 
-      doc.save(function (error) {
+      doc.save(function(error) {
         assert.ifError(error);
-        Event.findOne({_id: doc._id}, function (error, doc) {
+        Event.findOne({_id: doc._id}, function(error, doc) {
           assert.ifError(error);
           assert.deepEqual(doc.user.toObject(), {email: 'a@b', name: 'Val'});
           db.close(done);
@@ -1971,7 +1971,7 @@ describe('document', function () {
     });
   });
 
-  it('single embedded schemas + update validators (gh-2689)', function (done) {
+  it('single embedded schemas + update validators (gh-2689)', function(done) {
     var db = start();
 
     var userSchema = new mongoose.Schema({
@@ -1988,15 +1988,15 @@ describe('document', function () {
 
     var badUpdate = {$set: {'user.email': 'a'}};
     var options = {runValidators: true};
-    Event.update({}, badUpdate, options, function (error) {
+    Event.update({}, badUpdate, options, function(error) {
       assert.ok(error);
       assert.equal(error.errors['user.email'].kind, 'regexp');
 
       var nestedUpdate = {name: 'test'};
       var options = {upsert: true, setDefaultsOnInsert: true};
-      Event.update({}, nestedUpdate, options, function (error) {
+      Event.update({}, nestedUpdate, options, function(error) {
         assert.ifError(error);
-        Event.findOne({name: 'test'}, function (error, ev) {
+        Event.findOne({name: 'test'}, function(error, ev) {
           assert.ifError(error);
           assert.equal(ev.user.name, 'Val');
           db.close(done);
@@ -2005,7 +2005,7 @@ describe('document', function () {
     });
   });
 
-  it('single embedded schemas with populate (gh-3501)', function (done) {
+  it('single embedded schemas with populate (gh-3501)', function(done) {
     var db = start();
     var PopulateMeSchema = new Schema({});
 
@@ -2024,17 +2024,17 @@ describe('document', function () {
 
     var P = db.model('gh3501_1', parentSchema);
 
-    Child.create([{}, {}], function (error, docs) {
+    Child.create([{}, {}], function(error, docs) {
       assert.ifError(error);
       var obj = {
         singleNested: {populateMeArray: [docs[0]._id, docs[1]._id]}
       };
-      P.create(obj, function (error, doc) {
+      P.create(obj, function(error, doc) {
         assert.ifError(error);
         P.
         findById(doc._id).
         populate('singleNested.populateMeArray').
-        exec(function (error, doc) {
+        exec(function(error, doc) {
           assert.ok(doc.singleNested.populateMeArray[0]._id);
           db.close(done);
         });
@@ -2042,10 +2042,10 @@ describe('document', function () {
     });
   });
 
-  it('single embedded schemas with methods (gh-3534)', function (done) {
+  it('single embedded schemas with methods (gh-3534)', function(done) {
     var db = start();
     var personSchema = new Schema({name: String});
-    personSchema.methods.firstName = function () {
+    personSchema.methods.firstName = function() {
       return this.name.substr(0, this.name.indexOf(' '));
     };
 
@@ -2057,7 +2057,7 @@ describe('document', function () {
     db.close(done);
   });
 
-  it('single embedded schemas with models (gh-3535)', function (done) {
+  it('single embedded schemas with models (gh-3535)', function(done) {
     var db = start();
     var personSchema = new Schema({name: String});
     var Person = db.model('gh3535_0', personSchema);
@@ -2068,14 +2068,14 @@ describe('document', function () {
     var axl = new Person({name: 'Axl Rose'});
     var gnr = new Band({leadSinger: axl});
 
-    gnr.save(function (error) {
+    gnr.save(function(error) {
       assert.ifError(error);
       assert.equal(gnr.leadSinger.name, 'Axl Rose');
       db.close(done);
     });
   });
 
-  it('single embedded schemas with indexes (gh-3594)', function (done) {
+  it('single embedded schemas with indexes (gh-3594)', function(done) {
     var personSchema = new Schema({name: {type: String, unique: true}});
 
     var bandSchema = new Schema({leadSinger: personSchema});
@@ -2087,10 +2087,10 @@ describe('document', function () {
     done();
   });
 
-  it('single embedded docs have an ownerDocument function (gh-3589)', function (done) {
+  it('single embedded docs have an ownerDocument function (gh-3589)', function(done) {
     var db = start();
     var personSchema = new Schema({name: String});
-    personSchema.methods.display = function () {
+    personSchema.methods.display = function() {
       return this.name + ' of ' + this.ownerDocument().name;
     };
 
@@ -2098,14 +2098,14 @@ describe('document', function () {
     var Band = db.model('gh3589', bandSchema);
 
     var gnr = new Band({
-      name: "Guns N' Roses",
+      name: 'Guns N\' Roses',
       leadSinger: {name: 'Axl Rose'}
     });
-    assert.equal(gnr.leadSinger.display(), "Axl Rose of Guns N' Roses");
+    assert.equal(gnr.leadSinger.display(), 'Axl Rose of Guns N\' Roses');
     db.close(done);
   });
 
-  it('removing single embedded docs (gh-3596)', function (done) {
+  it('removing single embedded docs (gh-3596)', function(done) {
     var db = start();
     var personSchema = new Schema({name: String});
 
@@ -2113,13 +2113,13 @@ describe('document', function () {
     var Band = db.model('gh3596', bandSchema);
 
     var gnr = new Band({
-      name: "Guns N' Roses",
+      name: 'Guns N\' Roses',
       guitarist: {name: 'Slash'}
     });
-    gnr.save(function (error, gnr) {
+    gnr.save(function(error, gnr) {
       assert.ifError(error);
       gnr.guitarist = undefined;
-      gnr.save(function (error, gnr) {
+      gnr.save(function(error, gnr) {
         assert.ifError(error);
         assert.ok(!gnr.guitarist);
         db.close(done);
@@ -2127,7 +2127,7 @@ describe('document', function () {
     });
   });
 
-  it('setting single embedded docs (gh-3601)', function (done) {
+  it('setting single embedded docs (gh-3601)', function(done) {
     var db = start();
     var personSchema = new Schema({name: String});
 
@@ -2135,21 +2135,21 @@ describe('document', function () {
     var Band = db.model('gh3601', bandSchema);
 
     var gnr = new Band({
-      name: "Guns N' Roses",
+      name: 'Guns N\' Roses',
       guitarist: {name: 'Slash'}
     });
     var velvetRevolver = new Band({
       name: 'Velvet Revolver'
     });
     velvetRevolver.guitarist = gnr.guitarist;
-    velvetRevolver.save(function (error) {
+    velvetRevolver.save(function(error) {
       assert.ifError(error);
       assert.equal(velvetRevolver.guitarist, gnr.guitarist);
       db.close(done);
     });
   });
 
-  it('single embedded docs init obeys strict mode (gh-3642)', function (done) {
+  it('single embedded docs init obeys strict mode (gh-3642)', function(done) {
     var db = start();
     var personSchema = new Schema({name: String});
 
@@ -2161,10 +2161,10 @@ describe('document', function () {
       guitarist: {name: 'Slash', realName: 'Saul Hudson'}
     });
 
-    velvetRevolver.save(function (error) {
+    velvetRevolver.save(function(error) {
       assert.ifError(error);
       var query = {name: 'Velvet Revolver'};
-      Band.collection.findOne(query, function (error, band) {
+      Band.collection.findOne(query, function(error, band) {
         assert.ifError(error);
         assert.ok(!band.guitarist.realName);
         db.close(done);
@@ -2172,31 +2172,31 @@ describe('document', function () {
     });
   });
 
-  describe('bug fixes', function () {
+  describe('bug fixes', function() {
     var db;
 
-    before(function () {
+    before(function() {
       db = start();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('single embedded docs post hooks (gh-3679)', function (done) {
+    it('single embedded docs post hooks (gh-3679)', function(done) {
       var postHookCalls = [];
       var personSchema = new Schema({name: String});
-      personSchema.post('save', function () {
+      personSchema.post('save', function() {
         postHookCalls.push(this);
       });
 
       var bandSchema = new Schema({guitarist: personSchema, name: String});
       var Band = db.model('gh3679', bandSchema);
-      var obj = {name: "Guns N' Roses", guitarist: {name: 'Slash'}};
+      var obj = {name: 'Guns N\' Roses', guitarist: {name: 'Slash'}};
 
-      Band.create(obj, function (error) {
+      Band.create(obj, function(error) {
         assert.ifError(error);
-        setTimeout(function () {
+        setTimeout(function() {
           assert.equal(postHookCalls.length, 1);
           assert.equal(postHookCalls[0].name, 'Slash');
           done();
@@ -2204,7 +2204,7 @@ describe('document', function () {
       });
     });
 
-    it('single embedded docs .set() (gh-3686)', function (done) {
+    it('single embedded docs .set() (gh-3686)', function(done) {
       var personSchema = new Schema({name: String, realName: String});
 
       var bandSchema = new Schema({
@@ -2213,13 +2213,13 @@ describe('document', function () {
       });
       var Band = db.model('gh3686', bandSchema);
       var obj = {
-        name: "Guns N' Roses",
+        name: 'Guns N\' Roses',
         guitarist: {name: 'Slash', realName: 'Saul Hudson'}
       };
 
-      Band.create(obj, function (error, gnr) {
+      Band.create(obj, function(error, gnr) {
         gnr.set('guitarist.name', 'Buckethead');
-        gnr.save(function (error) {
+        gnr.save(function(error) {
           assert.ifError(error);
           assert.equal(gnr.guitarist.name, 'Buckethead');
           assert.equal(gnr.guitarist.realName, 'Saul Hudson');
@@ -2228,11 +2228,11 @@ describe('document', function () {
       });
     });
 
-    it('single embedded docs with arrays pre hooks (gh-3680)', function (done) {
+    it('single embedded docs with arrays pre hooks (gh-3680)', function(done) {
       var childSchema = new Schema({count: Number});
 
       var preCalls = 0;
-      childSchema.pre('save', function (next) {
+      childSchema.pre('save', function(next) {
         ++preCalls;
         next();
       });
@@ -2247,30 +2247,30 @@ describe('document', function () {
 
       var Parent = db.model('gh3680', ParentSchema);
       var obj = {singleNested: {children: [{count: 0}]}};
-      Parent.create(obj, function (error) {
+      Parent.create(obj, function(error) {
         assert.ifError(error);
         assert.equal(preCalls, 1);
         done();
       });
     });
 
-    it('nested single embedded doc validation (gh-3702)', function (done) {
+    it('nested single embedded doc validation (gh-3702)', function(done) {
       var childChildSchema = new Schema({count: {type: Number, min: 1}});
       var childSchema = new Schema({child: childChildSchema});
       var parentSchema = new Schema({child: childSchema});
 
       var Parent = db.model('gh3702', parentSchema);
       var obj = {child: {child: {count: 0}}};
-      Parent.create(obj, function (error) {
+      Parent.create(obj, function(error) {
         assert.ok(error);
         assert.ok(/ValidationError/.test(error.toString()));
         done();
       });
     });
 
-    it('handles virtuals with dots correctly (gh-3618)', function (done) {
+    it('handles virtuals with dots correctly (gh-3618)', function(done) {
       var testSchema = new Schema({nested: {type: Object, default: {}}});
-      testSchema.virtual('nested.test').get(function () {
+      testSchema.virtual('nested.test').get(function() {
         return true;
       });
 
@@ -2290,7 +2290,7 @@ describe('document', function () {
       done();
     });
 
-    it('handles pushing with numeric keys (gh-3623)', function (done) {
+    it('handles pushing with numeric keys (gh-3623)', function(done) {
       var schema = new Schema({
         array: [{
           1: {
@@ -2308,13 +2308,13 @@ describe('document', function () {
       var MyModel = db.model('gh3623', schema);
 
       var doc = {array: [{2: {}}]};
-      MyModel.collection.insertOne(doc, function (error) {
+      MyModel.collection.insertOne(doc, function(error) {
         assert.ifError(error);
 
-        MyModel.findOne({_id: doc._id}, function (error, doc) {
+        MyModel.findOne({_id: doc._id}, function(error, doc) {
           assert.ifError(error);
           doc.array.push({2: {}});
-          doc.save(function (error) {
+          doc.save(function(error) {
             assert.ifError(error);
             done();
           });
@@ -2322,7 +2322,7 @@ describe('document', function () {
       });
     });
 
-    it('execPopulate (gh-3753)', function (done) {
+    it('execPopulate (gh-3753)', function(done) {
       var childSchema = new Schema({
         name: String
       });
@@ -2335,14 +2335,14 @@ describe('document', function () {
       var Child = db.model('gh3753', childSchema);
       var Parent = db.model('gh3753_0', parentSchema);
 
-      Child.create({name: 'Luke Skywalker'}, function (error, child) {
+      Child.create({name: 'Luke Skywalker'}, function(error, child) {
         assert.ifError(error);
         var doc = {name: 'Darth Vader', children: [child._id]};
-        Parent.create(doc, function (error, doc) {
-          Parent.findOne({_id: doc._id}, function (error, doc) {
+        Parent.create(doc, function(error, doc) {
+          Parent.findOne({_id: doc._id}, function(error, doc) {
             assert.ifError(error);
             assert.ok(doc);
-            doc.populate('children').execPopulate().then(function (doc) {
+            doc.populate('children').execPopulate().then(function(doc) {
               assert.equal(doc.children.length, 1);
               assert.equal(doc.children[0].name, 'Luke Skywalker');
               done();
@@ -2352,7 +2352,7 @@ describe('document', function () {
       });
     });
 
-    it('handles 0 for numeric subdoc ids (gh-3776)', function (done) {
+    it('handles 0 for numeric subdoc ids (gh-3776)', function(done) {
       var personSchema = new Schema({
         _id: Number,
         name: String,
@@ -2367,11 +2367,11 @@ describe('document', function () {
         {_id: 1, name: 'Bob'}
       ];
 
-      Person.create(people, function (error, people) {
+      Person.create(people, function(error, people) {
         assert.ifError(error);
         var alice = people[0];
         alice.friends.push(people[1]);
-        alice.save(function (error) {
+        alice.save(function(error) {
           assert.ifError(error);
           done();
         });
diff --git a/test/document.unit.test.js b/test/document.unit.test.js
index fb1c4abfb13..145c978167f 100644
--- a/test/document.unit.test.js
+++ b/test/document.unit.test.js
@@ -6,14 +6,14 @@ var start = require('./common');
 var assert = require('assert');
 var mongoose = start.mongoose;
 
-describe('sharding', function () {
-  it('should handle shard keys properly (gh-2127)', function (done) {
+describe('sharding', function() {
+  it('should handle shard keys properly (gh-2127)', function(done) {
     var mockSchema = {
       options: {
         shardKey: {date: 1}
       }
     };
-    var Stub = function () {
+    var Stub = function() {
       this.schema = mockSchema;
       this.$__ = {};
     };
@@ -28,38 +28,38 @@ describe('sharding', function () {
   });
 });
 
-describe('toObject()', function () {
+describe('toObject()', function() {
   var Stub;
 
-  beforeEach(function () {
-    Stub = function () {
+  beforeEach(function() {
+    Stub = function() {
       var schema = this.schema = {
         options: {toObject: {minimize: false, virtuals: true}},
         virtuals: {virtual: 'test'}
       };
       this._doc = {empty: {}};
-      this.get = function (path) { return schema.virtuals[path]; };
+      this.get = function(path) { return schema.virtuals[path]; };
       this.$__ = {};
     };
     Stub.prototype = Object.create(mongoose.Document.prototype);
   });
 
-  it('should inherit options from schema', function (done) {
+  it('should inherit options from schema', function(done) {
     var d = new Stub();
     assert.deepEqual(d.toObject(), {empty: {}, virtual: 'test'});
     done();
   });
 
-  it('can overwrite by passing an option', function (done) {
+  it('can overwrite by passing an option', function(done) {
     var d = new Stub();
     assert.deepEqual(d.toObject({minimize: true}), {});
     done();
   });
 
-  it('doesnt crash with empty object (gh-3130)', function (done) {
+  it('doesnt crash with empty object (gh-3130)', function(done) {
     var d = new Stub();
     d._doc = undefined;
-    assert.doesNotThrow(function () {
+    assert.doesNotThrow(function() {
       d.toObject();
     });
     done();
diff --git a/test/errors.validation.test.js b/test/errors.validation.test.js
index eec2e6646ca..8c08b05f333 100644
--- a/test/errors.validation.test.js
+++ b/test/errors.validation.test.js
@@ -10,9 +10,9 @@ var assert = require('assert'),
     SchemaType = mongoose.SchemaType,
     ValidatorError = SchemaType.ValidatorError;
 
-describe('ValidationError', function () {
-  describe('#infiniteRecursion', function () {
-    it('does not cause RangeError (gh-1834)', function (done) {
+describe('ValidationError', function() {
+  describe('#infiniteRecursion', function() {
+    it('does not cause RangeError (gh-1834)', function(done) {
       var SubSchema,
           M,
           model;
@@ -34,8 +34,8 @@ describe('ValidationError', function () {
         ]
       });
 
-      model.validate(function (err) {
-        assert.doesNotThrow(function () {
+      model.validate(function(err) {
+        assert.doesNotThrow(function() {
           JSON.stringify(err);
         });
         done();
@@ -43,8 +43,8 @@ describe('ValidationError', function () {
     });
   });
 
-  describe('#minDate', function () {
-    it('causes a validation error', function (done) {
+  describe('#minDate', function() {
+    it('causes a validation error', function(done) {
       var MinSchema,
           M,
           model;
@@ -60,12 +60,12 @@ describe('ValidationError', function () {
       });
 
       // should fail validation
-      model.validate(function (err) {
+      model.validate(function(err) {
         assert.notEqual(err, null, 'min Date validation failed.');
         model.appointmentDate = new Date(Date.now().valueOf() + 10000);
 
         // should pass validation
-        model.validate(function (err) {
+        model.validate(function(err) {
           assert.equal(err, null);
           done();
         });
@@ -73,8 +73,8 @@ describe('ValidationError', function () {
     });
   });
 
-  describe('#maxDate', function () {
-    it('causes a validation error', function (done) {
+  describe('#maxDate', function() {
+    it('causes a validation error', function(done) {
       var MaxSchema,
           M,
           model;
@@ -90,12 +90,12 @@ describe('ValidationError', function () {
       });
 
       // should fail validation
-      model.validate(function (err) {
+      model.validate(function(err) {
         assert.notEqual(err, null, 'max Date validation failed');
         model.birthdate = Date.now();
 
         // should pass validation
-        model.validate(function (err) {
+        model.validate(function(err) {
           assert.equal(err, null, 'max Date validation failed');
           done();
         });
@@ -103,8 +103,8 @@ describe('ValidationError', function () {
     });
   });
 
-  describe('#minlength', function () {
-    it('causes a validation error', function (done) {
+  describe('#minlength', function() {
+    it('causes a validation error', function(done) {
       var AddressSchema,
           Address,
           model;
@@ -120,12 +120,12 @@ describe('ValidationError', function () {
       });
 
       // should fail validation
-      model.validate(function (err) {
+      model.validate(function(err) {
         assert.notEqual(err, null, 'String minlegth validation failed.');
         model.postalCode = '95125';
 
         // should pass validation
-        model.validate(function (err) {
+        model.validate(function(err) {
           assert.equal(err, null);
           done();
         });
@@ -133,8 +133,8 @@ describe('ValidationError', function () {
     });
   });
 
-  describe('#maxlength', function () {
-    it('causes a validation error', function (done) {
+  describe('#maxlength', function() {
+    it('causes a validation error', function(done) {
       var AddressSchema,
           Address,
           model;
@@ -150,12 +150,12 @@ describe('ValidationError', function () {
       });
 
       // should fail validation
-      model.validate(function (err) {
+      model.validate(function(err) {
         assert.notEqual(err, null, 'String maxlegth validation failed.');
         model.postalCode = '95125';
 
         // should pass validation
-        model.validate(function (err) {
+        model.validate(function(err) {
           assert.equal(err, null);
           done();
         });
@@ -163,8 +163,8 @@ describe('ValidationError', function () {
     });
   });
 
-  describe('#toString', function () {
-    it('does not cause RangeError (gh-1296)', function (done) {
+  describe('#toString', function() {
+    it('does not cause RangeError (gh-1296)', function(done) {
       var ASchema = new Schema({
         key: {type: String, required: true},
         value: {type: String, required: true}
@@ -177,8 +177,8 @@ describe('ValidationError', function () {
       var M = mongoose.model('A', BSchema);
       var m = new M;
       m.contents.push({key: 'asdf'});
-      m.validate(function (err) {
-        assert.doesNotThrow(function () {
+      m.validate(function(err) {
+        assert.doesNotThrow(function() {
           String(err);
         });
         done();
@@ -186,8 +186,8 @@ describe('ValidationError', function () {
     });
   });
 
-  describe('formatMessage', function () {
-    it('replaces properties in a message', function (done) {
+  describe('formatMessage', function() {
+    it('replaces properties in a message', function(done) {
       var props = {base: 'eggs', topping: 'bacon'};
       var message = 'I had {BASE} and {TOPPING} for breakfast';
 
diff --git a/test/gh-1408.test.js b/test/gh-1408.test.js
index 993cb5eddf3..00fd435f9b0 100644
--- a/test/gh-1408.test.js
+++ b/test/gh-1408.test.js
@@ -8,8 +8,8 @@ var start = require('./common'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema;
 
-describe('documents should not be converted to _id (gh-1408)', function () {
-  it('if an embedded doc', function (done) {
+describe('documents should not be converted to _id (gh-1408)', function() {
+  it('if an embedded doc', function(done) {
     var db = start();
 
     var PreferenceSchema = new Schema({
@@ -37,10 +37,10 @@ describe('documents should not be converted to _id (gh-1408)', function () {
       }
     });
 
-    a.save(function (err, a) {
+    a.save(function(err, a) {
       if (err) return done(err);
 
-      A.findById(a, function (err, doc) {
+      A.findById(a, function(err, doc) {
         if (err) return done(err);
 
         var newData = {
@@ -59,13 +59,13 @@ describe('documents should not be converted to _id (gh-1408)', function () {
         doc.set('settings', newData.settings, {merge: true});
         doc.markModified('settings'); // <== this caused the bug
 
-        doc.save(function (err) {
+        doc.save(function(err) {
           if (err) return done(err);
 
-          A.findById(doc, function (err, doc) {
+          A.findById(doc, function(err, doc) {
             if (err) return done(err);
 
-            doc.settings.preferences.forEach(function (pref, i) {
+            doc.settings.preferences.forEach(function(pref, i) {
               assert.equal(pref.preference, newData.settings.preferences[i].preference);
               assert.equal(pref.value, newData.settings.preferences[i].value);
             });
diff --git a/test/harmony/document.test_.js b/test/harmony/document.test_.js
index e54a4ffa168..f9fb3549408 100644
--- a/test/harmony/document.test_.js
+++ b/test/harmony/document.test_.js
@@ -14,23 +14,23 @@ var assert = require('assert');
  *  Note that the `yield` keyword is currently only supported in NodeJS 0.11.x
  *  with the `--harmony` flag.
  */
-describe('Documents in ES6', function () {
+describe('Documents in ES6', function() {
   var db;
   var collectionNameCounter = 0;
 
-  var getCollectionName = function () {
+  var getCollectionName = function() {
     return 'harmony-documents-validate-' + (++collectionNameCounter);
   };
 
-  beforeEach(function () {
+  beforeEach(function() {
     db = start({noErrorListener: 1});
   });
 
-  afterEach(function (done) {
+  afterEach(function(done) {
     db.close(done);
   });
 
-  it('validate() integrates with co and the yield keyword', function (done) {
+  it('validate() integrates with co and the yield keyword', function(done) {
     co(function*() {
       var schema = null;
       var called = false;
@@ -38,7 +38,7 @@ describe('Documents in ES6', function () {
       var error;
 
       var validate = {
-        validator: function () {
+        validator: function() {
           called = true;
           return shouldSucceed;
         },
@@ -78,7 +78,7 @@ describe('Documents in ES6', function () {
     })();
   });
 
-  it('save() integrates with co and the yield keyword', function (done) {
+  it('save() integrates with co and the yield keyword', function(done) {
     co(function*() {
       var error;
       var schema = new Schema({
@@ -120,7 +120,7 @@ describe('Documents in ES6', function () {
     })();
   });
 
-  it('populate() *requires* execPopulate() to work with the yield keyword', function (done) {
+  it('populate() *requires* execPopulate() to work with the yield keyword', function(done) {
     /**
      *  Because the `populate()` function supports chaining, it's difficult
      *  to determine when the chain is 'done'. Therefore, you need to call
@@ -174,7 +174,7 @@ describe('Documents in ES6', function () {
     })();
   });
 
-  it('update() works with co and yield', function (done) {
+  it('update() works with co and yield', function(done) {
     co(function*() {
       var schema = new Schema({
         steak: String,
diff --git a/test/harmony/model.test_.js b/test/harmony/model.test_.js
index aac5f689001..0239d38d3e2 100644
--- a/test/harmony/model.test_.js
+++ b/test/harmony/model.test_.js
@@ -18,23 +18,23 @@ var assert = require('assert');
  *  `yield` as described above.
  *
  */
-describe('Models in ES6', function () {
+describe('Models in ES6', function() {
   var db;
   var collectionNameCounter = 0;
 
-  var getCollectionName = function () {
+  var getCollectionName = function() {
     return 'harmony-models-validate-' + (++collectionNameCounter);
   };
 
-  beforeEach(function () {
+  beforeEach(function() {
     db = start();
   });
 
-  afterEach(function (done) {
+  afterEach(function(done) {
     db.close(done);
   });
 
-  it('`create()` integrates with co and the yield keyword', function (done) {
+  it('`create()` integrates with co and the yield keyword', function(done) {
     co(function * () {
       var schema = new Schema({
         eggs: {type: String, required: true},
@@ -60,7 +60,7 @@ describe('Models in ES6', function () {
     })();
   });
 
-  it('`aggregate()` integrates with co and the yield keyword', function (done) {
+  it('`aggregate()` integrates with co and the yield keyword', function(done) {
     co(function*() {
       var schema = new Schema({
         eggs: {type: String, required: true},
@@ -97,7 +97,7 @@ describe('Models in ES6', function () {
     })();
   });
 
-  it('`mapReduce()` can also be used with co and yield', function (done) {
+  it('`mapReduce()` can also be used with co and yield', function(done) {
     co(function*() {
       var schema = new Schema({
         eggs: {type: String, required: true},
@@ -118,8 +118,8 @@ describe('Models in ES6', function () {
       var results;
       try {
         results = yield M.mapReduce({
-          map: function () { emit(this.eggs, 1); },
-          reduce: function (k, vals) { return vals.length; }
+          map: function() { emit(this.eggs, 1); },
+          reduce: function(k, vals) { return vals.length; }
         });
       } catch (e) {
         return done(e);
diff --git a/test/harmony/query.test_.js b/test/harmony/query.test_.js
index b662a538c8c..ce7620eeb8c 100644
--- a/test/harmony/query.test_.js
+++ b/test/harmony/query.test_.js
@@ -13,23 +13,23 @@ var assert = require('assert');
  *  Note that the `yield` keyword is currently only supported in NodeJS 0.11.x
  *  with the `--harmony` flag.
  */
-describe('Queries in ES6', function () {
+describe('Queries in ES6', function() {
   var db;
   var collectionNameCounter = 0;
 
-  var getCollectionName = function () {
+  var getCollectionName = function() {
     return 'harmony-queries' + (++collectionNameCounter);
   };
 
-  beforeEach(function () {
+  beforeEach(function() {
     db = start();
   });
 
-  afterEach(function (done) {
+  afterEach(function(done) {
     db.close(done);
   });
 
-  it('`exec()` integrates with co and the yield keyword', function (done) {
+  it('`exec()` integrates with co and the yield keyword', function(done) {
     co(function*() {
       var schema = new Schema({
         eggs: {type: Number, required: true},
@@ -80,7 +80,7 @@ describe('Queries in ES6', function () {
     })();
   });
 
-  it('can call `populate()` with `exec()`', function (done) {
+  it('can call `populate()` with `exec()`', function(done) {
     co(function*() {
       var bookSchema = new Schema({
         author: {type: mongoose.Schema.ObjectId, ref: 'AuthorHarmony'},
diff --git a/test/index.test.js b/test/index.test.js
index eac4d5e1950..e3a5dea7661 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -8,38 +8,38 @@ var url = require('url'),
     random = require('../lib/utils').random,
     collection = 'blogposts_' + random();
 
-describe('mongoose module:', function () {
-  describe('default connection works', function () {
-    it('without options', function (done) {
+describe('mongoose module:', function() {
+  describe('default connection works', function() {
+    it('without options', function(done) {
       var goose = new Mongoose;
       var db = goose.connection,
           uri = 'mongodb://localhost/mongoose_test';
 
       goose.connect(process.env.MONGOOSE_TEST_URI || uri);
 
-      db.on('open', function () {
-        db.close(function () {
+      db.on('open', function() {
+        db.close(function() {
           done();
         });
       });
     });
 
-    it('with options', function (done) {
+    it('with options', function(done) {
       var goose = new Mongoose;
       var db = goose.connection,
           uri = 'mongodb://localhost/mongoose_test';
 
       goose.connect(process.env.MONGOOSE_TEST_URI || uri, {db: {safe: false}});
 
-      db.on('open', function () {
-        db.close(function () {
+      db.on('open', function() {
+        db.close(function() {
           done();
         });
       });
     });
   });
 
-  it('{g,s}etting options', function (done) {
+  it('{g,s}etting options', function(done) {
     var mongoose = new Mongoose();
 
     mongoose.set('a', 'b');
@@ -51,17 +51,17 @@ describe('mongoose module:', function () {
     done();
   });
 
-  it('declaring global plugins', function (done) {
+  it('declaring global plugins', function(done) {
     var mong = new Mongoose(),
         schema = new Schema(),
         called = 0;
 
-    mong.plugin(function (s) {
+    mong.plugin(function(s) {
       assert.equal(s, schema);
       called++;
     });
 
-    schema.plugin(function (s) {
+    schema.plugin(function(s) {
       assert.equal(s, schema);
       called++;
     });
@@ -72,9 +72,9 @@ describe('mongoose module:', function () {
     done();
   });
 
-  describe('disconnection of all connections', function () {
-    describe('no callback', function () {
-      it('works', function (done) {
+  describe('disconnection of all connections', function() {
+    describe('no callback', function() {
+      it('works', function(done) {
         var mong = new Mongoose(),
             uri = 'mongodb://localhost/mongoose_test',
             connections = 0,
@@ -91,24 +91,24 @@ describe('mongoose module:', function () {
           done();
         }
 
-        db.on('open', function () {
+        db.on('open', function() {
           connections++;
           cb();
         });
 
-        db.on('close', function () {
+        db.on('close', function() {
           disconnections++;
           cb();
         });
 
         var db2 = mong.createConnection(process.env.MONGOOSE_TEST_URI || uri);
 
-        db2.on('open', function () {
+        db2.on('open', function() {
           connections++;
           cb();
         });
 
-        db2.on('close', function () {
+        db2.on('close', function() {
           disconnections++;
           cb();
         });
@@ -116,7 +116,7 @@ describe('mongoose module:', function () {
         mong.disconnect();
       });
 
-      it('properly handles errors', function (done) {
+      it('properly handles errors', function(done) {
         var mong = new Mongoose(),
             uri = 'mongodb://localhost/mongoose_test';
 
@@ -124,12 +124,12 @@ describe('mongoose module:', function () {
         var db = mong.connection;
 
         // forced failure
-        db.close = function (cb) {
+        db.close = function(cb) {
           cb(new Error('bam'));
         };
 
         mong.disconnect()
-          .on('error', function (error) {
+          .on('error', function(error) {
             assert.equal('bam', error.message);
           });
 
@@ -137,22 +137,22 @@ describe('mongoose module:', function () {
       });
     });
 
-    it('with callback', function (done) {
+    it('with callback', function(done) {
       var mong = new Mongoose(),
           uri = 'mongodb://localhost/mongoose_test';
 
       mong.connect(process.env.MONGOOSE_TEST_URI || uri);
 
-      mong.connection.on('open', function () {
-        mong.disconnect(function () {
+      mong.connection.on('open', function() {
+        mong.disconnect(function() {
           done();
         });
       });
     });
   });
 
-  describe('model()', function () {
-    it('accessing a model that hasn\'t been defined', function (done) {
+  describe('model()', function() {
+    it('accessing a model that hasn\'t been defined', function(done) {
       var mong = new Mongoose(),
           thrown = false;
 
@@ -167,7 +167,7 @@ describe('mongoose module:', function () {
       done();
     });
 
-    it('returns the model at creation', function (done) {
+    it('returns the model at creation', function(done) {
       var Named = mongoose.model('Named', new Schema({name: String}));
       var n1 = new Named();
       assert.equal(n1.name, null);
@@ -181,40 +181,40 @@ describe('mongoose module:', function () {
       done();
     });
 
-    it('prevents overwriting pre-existing models', function (done) {
+    it('prevents overwriting pre-existing models', function(done) {
       var m = new Mongoose;
       m.model('A', new Schema);
 
-      assert.throws(function () {
+      assert.throws(function() {
         m.model('A', new Schema);
       }, /Cannot overwrite `A` model/);
 
       done();
     });
 
-    it('allows passing identical name + schema args', function (done) {
+    it('allows passing identical name + schema args', function(done) {
       var m = new Mongoose;
       var schema = new Schema;
       m.model('A', schema);
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         m.model('A', schema);
       });
 
       done();
     });
 
-    it('throws on unknown model name', function (done) {
-      assert.throws(function () {
+    it('throws on unknown model name', function(done) {
+      assert.throws(function() {
         mongoose.model('iDoNotExist!');
       }, /Schema hasn't been registered/);
 
       done();
     });
 
-    describe('passing collection name', function () {
-      describe('when model name already exists', function () {
-        it('returns a new uncached model', function (done) {
+    describe('passing collection name', function() {
+      describe('when model name already exists', function() {
+        it('returns a new uncached model', function(done) {
           var m = new Mongoose;
           var s1 = new Schema({a: []});
           var name = 'non-cached-collection-name';
@@ -230,8 +230,8 @@ describe('mongoose module:', function () {
       });
     });
 
-    describe('passing object literal schemas', function () {
-      it('works', function (done) {
+    describe('passing object literal schemas', function() {
+      it('works', function(done) {
         var m = new Mongoose;
         var A = m.model('A', {n: [{age: 'number'}]});
         var a = new A({n: [{age: '47'}]});
@@ -241,38 +241,38 @@ describe('mongoose module:', function () {
     });
   });
 
-  it('connecting with a signature of host, database, function', function (done) {
+  it('connecting with a signature of host, database, function', function(done) {
     var mong = new Mongoose(),
         uri = process.env.MONGOOSE_TEST_URI || 'mongodb://localhost/mongoose_test';
 
     uri = url.parse(uri);
 
-    mong.connect(uri.hostname, uri.pathname.substr(1), function (err) {
+    mong.connect(uri.hostname, uri.pathname.substr(1), function(err) {
       assert.ifError(err);
       mong.connection.close();
       done();
     });
   });
 
-  describe('connecting with a signature of uri, options, function', function () {
-    it('with single mongod', function (done) {
+  describe('connecting with a signature of uri, options, function', function() {
+    it('with single mongod', function(done) {
       var mong = new Mongoose(),
           uri = process.env.MONGOOSE_TEST_URI || 'mongodb://localhost/mongoose_test';
 
-      mong.connect(uri, {db: {safe: false}}, function (err) {
+      mong.connect(uri, {db: {safe: false}}, function(err) {
         assert.ifError(err);
         mong.connection.close();
         done();
       });
     });
 
-    it('with replica set', function (done) {
+    it('with replica set', function(done) {
       var mong = new Mongoose(),
           uri = process.env.MONGOOSE_SET_TEST_URI;
 
       if (!uri) return done();
 
-      mong.connect(uri, {db: {safe: false}}, function (err) {
+      mong.connect(uri, {db: {safe: false}}, function(err) {
         assert.ifError(err);
         mong.connection.close();
         done();
@@ -280,7 +280,7 @@ describe('mongoose module:', function () {
     });
   });
 
-  it('goose.connect() to a replica set', function (done) {
+  it('goose.connect() to a replica set', function(done) {
     var uri = process.env.MONGOOSE_SET_TEST_URI;
 
     if (!uri) {
@@ -293,7 +293,7 @@ describe('mongoose module:', function () {
 
     var mong = new Mongoose();
 
-    mong.connect(uri, function (err) {
+    mong.connect(uri, function(err) {
       assert.ifError(err);
 
       mong.model('Test', new mongoose.Schema({
@@ -304,10 +304,10 @@ describe('mongoose module:', function () {
           test = new Test();
 
       test.test = 'aa';
-      test.save(function (err) {
+      test.save(function(err) {
         assert.ifError(err);
 
-        Test.findById(test._id, function (err, doc) {
+        Test.findById(test._id, function(err, doc) {
           assert.ifError(err);
           assert.equal('aa', doc.test);
           mong.connection.close();
@@ -325,14 +325,14 @@ describe('mongoose module:', function () {
     }
   });
 
-  it('goose.createConnection() to a replica set', function (done) {
+  it('goose.createConnection() to a replica set', function(done) {
     var uri = process.env.MONGOOSE_SET_TEST_URI;
 
     if (!uri) return done();
 
     var mong = new Mongoose();
 
-    var conn = mong.createConnection(uri, function (err) {
+    var conn = mong.createConnection(uri, function(err) {
       assert.ifError(err);
 
       mong.model('ReplSetTwo', new mongoose.Schema({
@@ -343,10 +343,10 @@ describe('mongoose module:', function () {
           test = new Test();
 
       test.test = 'aa';
-      test.save(function (err) {
+      test.save(function(err) {
         assert.ifError(err);
 
-        Test.findById(test._id, function (err, doc) {
+        Test.findById(test._id, function(err, doc) {
           assert.ifError(err);
           assert.equal('aa', doc.test);
           conn.close();
@@ -364,7 +364,7 @@ describe('mongoose module:', function () {
     }
   });
 
-  describe('exports', function () {
+  describe('exports', function() {
     function test(mongoose) {
       assert.equal('string', typeof mongoose.version);
       assert.equal('function', typeof mongoose.Mongoose);
@@ -383,12 +383,12 @@ describe('mongoose module:', function () {
       assert.equal('function', typeof mongoose.Error.VersionError);
     }
 
-    it('of module', function (done) {
+    it('of module', function(done) {
       test(mongoose);
       done();
     });
 
-    it('of new Mongoose instances', function (done) {
+    it('of new Mongoose instances', function(done) {
       test(new mongoose.Mongoose);
       done();
     });
diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js
index c895ace9af3..142fc1917ac 100644
--- a/test/model.aggregate.test.js
+++ b/test/model.aggregate.test.js
@@ -22,14 +22,14 @@ var userSchema = new Schema({
 var collection = 'aggregate_' + random();
 mongoose.model('Aggregate', userSchema);
 
-describe('model aggregate', function () {
+describe('model aggregate', function() {
   var group = {$group: {_id: null, maxAge: {$max: '$age'}}};
   var project = {$project: {maxAge: 1, _id: 0}};
   var db, A, maxAge;
 
   var mongo26_or_greater = false;
 
-  before(function (done) {
+  before(function(done) {
     db = start();
     A = db.model('Aggregate', collection);
 
@@ -44,9 +44,9 @@ describe('model aggregate', function () {
       docs.push({author: authors[i % authors.length], age: age});
     }
 
-    A.create(docs, function (err) {
+    A.create(docs, function(err) {
       assert.ifError(err);
-      start.mongodVersion(function (err, version) {
+      start.mongodVersion(function(err, version) {
         if (err) throw err;
         mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
         if (!mongo26_or_greater) console.log('not testing mongodb 2.6 features');
@@ -55,15 +55,15 @@ describe('model aggregate', function () {
     });
   });
 
-  after(function (done) {
+  after(function(done) {
     db.close(done);
   });
 
-  describe('works', function () {
-    it('with argument lists', function (done) {
+  describe('works', function() {
+    it('with argument lists', function(done) {
       this.timeout(4000);
 
-      A.aggregate(group, project, function (err, res) {
+      A.aggregate(group, project, function(err, res) {
         assert.ifError(err);
         assert.ok(res);
         assert.equal(1, res.length);
@@ -73,10 +73,10 @@ describe('model aggregate', function () {
       });
     });
 
-    it('with arrays', function (done) {
+    it('with arrays', function(done) {
       this.timeout(4000);
 
-      A.aggregate([group, project], function (err, res) {
+      A.aggregate([group, project], function(err, res) {
         assert.ifError(err);
         assert.ok(res);
         assert.equal(1, res.length);
@@ -86,13 +86,13 @@ describe('model aggregate', function () {
       });
     });
 
-    it('with Aggregate syntax', function (done) {
+    it('with Aggregate syntax', function(done) {
       this.timeout(4000);
 
       var promise = A.aggregate()
         .group(group.$group)
         .project(project.$project)
-        .exec(function (err, res) {
+        .exec(function(err, res) {
           assert.ifError(err);
           assert.ok(promise instanceof mongoose.Promise);
           assert.ok(res);
@@ -103,7 +103,7 @@ describe('model aggregate', function () {
         });
     });
 
-    it('with Aggregate syntax if callback not provided', function (done) {
+    it('with Aggregate syntax if callback not provided', function(done) {
       this.timeout(4000);
 
       var promise = A.aggregate()
@@ -111,7 +111,7 @@ describe('model aggregate', function () {
         .project(project.$project)
         .exec();
 
-      promise.then(function (res) {
+      promise.then(function(res) {
         assert.ok(promise instanceof mongoose.Promise);
         assert.ok(res);
         assert.equal(1, res.length);
@@ -121,12 +121,12 @@ describe('model aggregate', function () {
       }).end();
     });
 
-    it('when returning Aggregate', function (done) {
+    it('when returning Aggregate', function(done) {
       assert(A.aggregate(project) instanceof Aggregate);
       done();
     });
 
-    it('can use helper for $out', function (done) {
+    it('can use helper for $out', function(done) {
       if (!mongo26_or_greater) {
         return done();
       }
@@ -138,9 +138,9 @@ describe('model aggregate', function () {
         .group(group.$group)
         .project(project.$project)
         .out(outputCollection)
-        .exec(function (error) {
+        .exec(function(error) {
           assert.ifError(error);
-          A.db.collection(outputCollection).find().toArray(function (error, documents) {
+          A.db.collection(outputCollection).find().toArray(function(error, documents) {
             assert.ifError(error);
             assert.equal(1, documents.length);
             assert.ok('maxAge' in documents[0]);
diff --git a/test/model.create.test.js b/test/model.create.test.js
index 6e5d8a98210..569005e1539 100644
--- a/test/model.create.test.js
+++ b/test/model.create.test.js
@@ -18,22 +18,22 @@ var schema = new Schema({
 });
 
 
-describe('model', function () {
-  describe('create()', function () {
+describe('model', function() {
+  describe('create()', function() {
     var db;
     var B;
 
-    before(function () {
+    before(function() {
       db = start();
       B = db.model('model-create', schema, 'model-create-' + random());
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('accepts an array and returns an array', function (done) {
-      B.create([{title: 'hi'}, {title: 'bye'}], function (err, posts) {
+    it('accepts an array and returns an array', function(done) {
+      B.create([{title: 'hi'}, {title: 'bye'}], function(err, posts) {
         assert.ifError(err);
 
         assert.ok(posts instanceof Array);
@@ -50,30 +50,30 @@ describe('model', function () {
       });
     });
 
-    it('fires callback when passed 0 docs', function (done) {
-      B.create(function (err, a) {
+    it('fires callback when passed 0 docs', function(done) {
+      B.create(function(err, a) {
         assert.ifError(err);
         assert.ok(!a);
         done();
       });
     });
 
-    it('fires callback when empty array passed', function (done) {
-      B.create([], function (err, a) {
+    it('fires callback when empty array passed', function(done) {
+      B.create([], function(err, a) {
         assert.ifError(err);
         assert.ok(!a);
         done();
       });
     });
 
-    it('returns a promise', function (done) {
-      var p = B.create({title: 'returns promise'}, function () {
+    it('returns a promise', function(done) {
+      var p = B.create({title: 'returns promise'}, function() {
         assert.ok(p instanceof mongoose.Promise);
         done();
       });
     });
 
-    it('creates in parallel', function (done) {
+    it('creates in parallel', function(done) {
       // we set the time out to be double that of the validator - 1 (so that running in serial will be greater then that)
       this.timeout(1000);
       var db = start(),
@@ -84,13 +84,13 @@ describe('model', function () {
         preference: String
       });
       SchemaWithPreSaveHook.pre('save', true, function hook(next, done) {
-        setTimeout(function () {
+        setTimeout(function() {
           countPre++;
           next();
           done();
         }, 500);
       });
-      SchemaWithPreSaveHook.post('save', function () {
+      SchemaWithPreSaveHook.post('save', function() {
         countPost++;
       });
       var MWPSH = db.model('mwpsh', SchemaWithPreSaveHook);
@@ -99,7 +99,7 @@ describe('model', function () {
         {preference: 'yy'},
         {preference: '1'},
         {preference: '2'}
-      ], function (err, docs) {
+      ], function(err, docs) {
         assert.ifError(err);
 
         assert.ok(docs instanceof Array);
@@ -119,27 +119,27 @@ describe('model', function () {
     });
 
 
-    describe('callback is optional', function () {
-      it('with one doc', function (done) {
+    describe('callback is optional', function() {
+      it('with one doc', function(done) {
         var p = B.create({title: 'optional callback'});
-        p.then(function (doc) {
+        p.then(function(doc) {
           assert.equal('optional callback', doc.title);
           done();
         }, done).end();
       });
 
-      it('with more than one doc', function (done) {
+      it('with more than one doc', function(done) {
         var p = B.create({title: 'optional callback 2'}, {title: 'orient expressions'});
-        p.then(function (doc1, doc2) {
+        p.then(function(doc1, doc2) {
           assert.equal('optional callback 2', doc1.title);
           assert.equal('orient expressions', doc2.title);
           done();
         }, done).end();
       });
 
-      it('with array of docs', function (done) {
+      it('with array of docs', function(done) {
         var p = B.create([{title: 'optional callback3'}, {title: '3'}]);
-        p.then(function (docs) {
+        p.then(function(docs) {
           assert.ok(docs instanceof Array);
           assert.equal(docs.length, 2);
           var doc1 = docs[0];
@@ -150,13 +150,13 @@ describe('model', function () {
         }, done).end();
       });
 
-      it('and should reject promise on error', function (done) {
+      it('and should reject promise on error', function(done) {
         var p = B.create({title: 'optional callback 4'});
-        p.then(function (doc) {
+        p.then(function(doc) {
           var p2 = B.create({_id: doc._id});
-          p2.then(function () {
+          p2.then(function() {
             assert(false);
-          }, function (err) {
+          }, function(err) {
             assert(err);
             done();
           }).end();
diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js
index 30169f8daab..9e52e75293a 100644
--- a/test/model.discriminator.querying.test.js
+++ b/test/model.discriminator.querying.test.js
@@ -28,18 +28,18 @@ var EventSchema = new BaseSchema();
 var ImpressionEventSchema = new BaseSchema();
 var ConversionEventSchema = new BaseSchema({revenue: Number});
 
-describe('model', function () {
-  describe('discriminator()', function () {
+describe('model', function() {
+  describe('discriminator()', function() {
     var db, BaseEvent, ImpressionEvent, ConversionEvent;
 
-    before(function () {
+    before(function() {
       db = start();
       BaseEvent = db.model('model-discriminator-querying-event', EventSchema, 'model-discriminator-querying-' + random());
       ImpressionEvent = BaseEvent.discriminator('model-discriminator-querying-impression', ImpressionEventSchema);
       ConversionEvent = BaseEvent.discriminator('model-discriminator-querying-conversion', ConversionEventSchema);
     });
 
-    afterEach(function (done) {
+    afterEach(function(done) {
       async.series(
         [
           function removeBaseEvent(next) {
@@ -56,13 +56,13 @@ describe('model', function () {
       );
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    describe('pushing discriminated objects', function () {
+    describe('pushing discriminated objects', function() {
       var ContainerModel, BaseCustomEvent, DiscCustomEvent;
-      before(function () {
+      before(function() {
         var BaseCustomEventSchema = new BaseSchema();
         var DiscCustomEventSchema = new BaseSchema({
           personName: Number
@@ -78,7 +78,7 @@ describe('model', function () {
         ContainerModel = db.model('container-event-model', ContainerSchema);
       });
 
-      it('into non-discriminated arrays works', function (done) {
+      it('into non-discriminated arrays works', function(done) {
         var c = new ContainerModel({
           title: 'events-group-1'
         });
@@ -89,19 +89,19 @@ describe('model', function () {
         c.events.push(d2);
         async.series(
           [
-            function (next) { d1.save(next); },
-            function (next) { d2.save(next); },
-            function (next) { d3.save(next); },
-            function (next) { c.save(next); },
-            function (next) {
-              ContainerModel.findOne({}).populate('events').exec(function (err, doc) {
+            function(next) { d1.save(next); },
+            function(next) { d2.save(next); },
+            function(next) { d3.save(next); },
+            function(next) { c.save(next); },
+            function(next) {
+              ContainerModel.findOne({}).populate('events').exec(function(err, doc) {
                 assert.ifError(err);
                 assert.ok(doc.events && doc.events.length);
                 assert.equal(doc.events.length, 2);
                 doc.events.push(d3);
                 var hasDisc = false;
                 var discKey = DiscCustomEvent.schema.discriminatorMapping.key;
-                doc.events.forEach(function (subDoc) {
+                doc.events.forEach(function(subDoc) {
                   if (discKey in subDoc) {
                     hasDisc = true;
                   }
@@ -116,19 +116,19 @@ describe('model', function () {
       });
     });
 
-    describe('find', function () {
-      it('hydrates correct models', function (done) {
+    describe('find', function() {
+      it('hydrates correct models', function(done) {
         var baseEvent = new BaseEvent({name: 'Base event'});
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function (err) {
+        baseEvent.save(function(err) {
           assert.ifError(err);
-          impressionEvent.save(function (err) {
+          impressionEvent.save(function(err) {
             assert.ifError(err);
-            conversionEvent.save(function (err) {
+            conversionEvent.save(function(err) {
               assert.ifError(err);
-              BaseEvent.find({}).sort('name').exec(function (err, docs) {
+              BaseEvent.find({}).sort('name').exec(function(err, docs) {
                 assert.ifError(err);
                 assert.ok(docs[0] instanceof BaseEvent);
                 assert.equal(docs[0].name, 'Base event');
@@ -148,18 +148,18 @@ describe('model', function () {
         });
       });
 
-      var checkHydratesCorrectModels = function (fields, done) {
+      var checkHydratesCorrectModels = function(fields, done) {
         var baseEvent = new BaseEvent({name: 'Base event'});
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function (err) {
+        baseEvent.save(function(err) {
           assert.ifError(err);
-          impressionEvent.save(function (err) {
+          impressionEvent.save(function(err) {
             assert.ifError(err);
-            conversionEvent.save(function (err) {
+            conversionEvent.save(function(err) {
               assert.ifError(err);
-              BaseEvent.find({}, fields).sort('name').exec(function (err, docs) {
+              BaseEvent.find({}, fields).sort('name').exec(function(err, docs) {
                 assert.ifError(err);
                 assert.ok(docs[0] instanceof BaseEvent);
                 assert.equal(docs[0].name, 'Base event');
@@ -179,42 +179,42 @@ describe('model', function () {
         });
       };
 
-      it('hydrates correct models when fields selection set as string', function (done) {
+      it('hydrates correct models when fields selection set as string', function(done) {
         checkHydratesCorrectModels('name', done);
       });
 
-      it('hydrates correct models when fields selection set as object', function (done) {
+      it('hydrates correct models when fields selection set as object', function(done) {
         checkHydratesCorrectModels({name: 1}, done);
       });
 
-      describe('discriminator model only finds documents of its type', function () {
+      describe('discriminator model only finds documents of its type', function() {
         var impressionEvent, conversionEvent1, conversionEvent2;
 
-        before(function () {
+        before(function() {
           impressionEvent = new ImpressionEvent({name: 'Impression event'});
           conversionEvent1 = new ConversionEvent({name: 'Conversion event 1', revenue: 1});
           conversionEvent2 = new ConversionEvent({name: 'Conversion event 2', revenue: 2});
         });
 
-        describe('using "ModelDiscriminator#findById"', function () {
-          it('to find a document of the appropriate discriminator', function (done) {
-            impressionEvent.save(function (err) {
+        describe('using "ModelDiscriminator#findById"', function() {
+          it('to find a document of the appropriate discriminator', function(done) {
+            impressionEvent.save(function(err) {
               assert.ifError(err);
 
               // via BaseEvent model
-              BaseEvent.findById(impressionEvent._id, function (err, doc) {
+              BaseEvent.findById(impressionEvent._id, function(err, doc) {
                 assert.ifError(err);
                 assert.ok(doc);
                 assert.equal(impressionEvent.__t, doc.__t);
 
                 // via ImpressionEvent model discriminator -- should be present
-                ImpressionEvent.findById(impressionEvent._id, function (err, doc) {
+                ImpressionEvent.findById(impressionEvent._id, function(err, doc) {
                   assert.ifError(err);
                   assert.ok(doc);
                   assert.equal(impressionEvent.__t, doc.__t);
 
                   // via ConversionEvent model discriminator -- should not be present
-                  ConversionEvent.findById(impressionEvent._id, function (err, doc) {
+                  ConversionEvent.findById(impressionEvent._id, function(err, doc) {
                     assert.ifError(err);
                     assert.ok(!doc);
 
@@ -226,19 +226,19 @@ describe('model', function () {
           });
         });
 
-        describe('using "ModelDiscriminator#find"', function () {
-          it('to find documents of the appropriate discriminator', function (done) {
-            impressionEvent.save(function (err) {
+        describe('using "ModelDiscriminator#find"', function() {
+          it('to find documents of the appropriate discriminator', function(done) {
+            impressionEvent.save(function(err) {
               assert.ifError(err);
-              conversionEvent1.save(function (err) {
+              conversionEvent1.save(function(err) {
                 assert.ifError(err);
-                conversionEvent2.save(function (err) {
+                conversionEvent2.save(function(err) {
                   assert.ifError(err);
                   // doesn't find anything since we're querying for an impression id
                   var query = ConversionEvent.find({_id: impressionEvent._id});
                   assert.equal(query.op, 'find');
                   assert.deepEqual(query._conditions, {_id: impressionEvent._id, __t: 'model-discriminator-querying-conversion'});
-                  query.exec(function (err, documents) {
+                  query.exec(function(err, documents) {
                     assert.ifError(err);
                     assert.equal(documents.length, 0);
 
@@ -246,7 +246,7 @@ describe('model', function () {
                     var query = ConversionEvent.find();
                     assert.deepEqual(query._conditions, {__t: 'model-discriminator-querying-conversion'});
                     assert.equal(query.op, 'find');
-                    query.exec(function (err, documents) {
+                    query.exec(function(err, documents) {
                       assert.ifError(err);
                       assert.equal(documents.length, 2);
 
@@ -266,22 +266,22 @@ describe('model', function () {
         });
       });
 
-      var checkDiscriminatorModelsFindDocumentsOfItsType = function (fields, done) {
+      var checkDiscriminatorModelsFindDocumentsOfItsType = function(fields, done) {
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent1 = new ConversionEvent({name: 'Conversion event 1', revenue: 1});
         var conversionEvent2 = new ConversionEvent({name: 'Conversion event 2', revenue: 2});
 
-        impressionEvent.save(function (err) {
+        impressionEvent.save(function(err) {
           assert.ifError(err);
-          conversionEvent1.save(function (err) {
+          conversionEvent1.save(function(err) {
             assert.ifError(err);
-            conversionEvent2.save(function (err) {
+            conversionEvent2.save(function(err) {
               assert.ifError(err);
               // doesn't find anything since we're querying for an impression id
               var query = ConversionEvent.find({_id: impressionEvent._id}, fields);
               assert.equal(query.op, 'find');
               assert.deepEqual(query._conditions, {_id: impressionEvent._id, __t: 'model-discriminator-querying-conversion'});
-              query.exec(function (err, documents) {
+              query.exec(function(err, documents) {
                 assert.ifError(err);
                 assert.equal(documents.length, 0);
 
@@ -289,7 +289,7 @@ describe('model', function () {
                 var query = ConversionEvent.find({}, fields);
                 assert.deepEqual(query._conditions, {__t: 'model-discriminator-querying-conversion'});
                 assert.equal(query.op, 'find');
-                query.exec(function (err, documents) {
+                query.exec(function(err, documents) {
                   assert.ifError(err);
                   assert.equal(documents.length, 2);
 
@@ -306,44 +306,44 @@ describe('model', function () {
         });
       };
 
-      it('discriminator model only finds documents of its type when fields selection set as string inclusive', function (done) {
+      it('discriminator model only finds documents of its type when fields selection set as string inclusive', function(done) {
         checkDiscriminatorModelsFindDocumentsOfItsType('name', done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as string exclusive', function (done) {
+      it('discriminator model only finds documents of its type when fields selection set as string exclusive', function(done) {
         checkDiscriminatorModelsFindDocumentsOfItsType('-revenue', done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as empty string', function (done) {
+      it('discriminator model only finds documents of its type when fields selection set as empty string', function(done) {
         checkDiscriminatorModelsFindDocumentsOfItsType('', done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as object inclusive', function (done) {
+      it('discriminator model only finds documents of its type when fields selection set as object inclusive', function(done) {
         checkDiscriminatorModelsFindDocumentsOfItsType({name: 1}, done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as object exclusive', function (done) {
+      it('discriminator model only finds documents of its type when fields selection set as object exclusive', function(done) {
         checkDiscriminatorModelsFindDocumentsOfItsType({revenue: 0}, done);
       });
 
-      it('discriminator model only finds documents of its type when fields selection set as empty object', function (done) {
+      it('discriminator model only finds documents of its type when fields selection set as empty object', function(done) {
         checkDiscriminatorModelsFindDocumentsOfItsType({}, done);
       });
 
-      it('hydrates streams', function (done) {
+      it('hydrates streams', function(done) {
         var baseEvent = new BaseEvent({name: 'Base event'});
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function (err) {
+        baseEvent.save(function(err) {
           assert.ifError(err);
-          impressionEvent.save(function (err) {
+          impressionEvent.save(function(err) {
             assert.ifError(err);
-            conversionEvent.save(function (err) {
+            conversionEvent.save(function(err) {
               assert.ifError(err);
               var stream = BaseEvent.find({}).sort('name').stream();
 
-              stream.on('data', function (doc) {
+              stream.on('data', function(doc) {
                 switch (doc.name) {
                   case 'Base event':
                     assert.ok(doc instanceof BaseEvent);
@@ -361,11 +361,11 @@ describe('model', function () {
                 }
               });
 
-              stream.on('error', function (err) {
+              stream.on('error', function(err) {
                 assert.ifError(err);
               });
 
-              stream.on('close', function () {
+              stream.on('close', function() {
                 done();
               });
             });
@@ -374,33 +374,33 @@ describe('model', function () {
       });
     });
 
-    describe('findOne', function () {
-      it('hydrates correct model', function (done) {
+    describe('findOne', function() {
+      it('hydrates correct model', function(done) {
         var baseEvent = new BaseEvent({name: 'Base event'});
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function (err) {
+        baseEvent.save(function(err) {
           assert.ifError(err);
-          impressionEvent.save(function (err) {
+          impressionEvent.save(function(err) {
             assert.ifError(err);
-            conversionEvent.save(function (err) {
+            conversionEvent.save(function(err) {
               assert.ifError(err);
               // finds & hydrates BaseEvent
-              BaseEvent.findOne({_id: baseEvent._id}, function (err, event) {
+              BaseEvent.findOne({_id: baseEvent._id}, function(err, event) {
                 assert.ifError(err);
                 assert.ok(event instanceof BaseEvent);
                 assert.equal(event.name, 'Base event');
 
                 // finds & hydrates ImpressionEvent
-                BaseEvent.findOne({_id: impressionEvent._id}, function (err, event) {
+                BaseEvent.findOne({_id: impressionEvent._id}, function(err, event) {
                   assert.ifError(err);
                   assert.ok(event instanceof ImpressionEvent);
                   assert.equal(event.schema, ImpressionEventSchema);
                   assert.equal(event.name, 'Impression event');
 
                   // finds & hydrates ConversionEvent
-                  BaseEvent.findOne({_id: conversionEvent._id}, function (err, event) {
+                  BaseEvent.findOne({_id: conversionEvent._id}, function(err, event) {
                     assert.ifError(err);
                     assert.ok(event instanceof ConversionEvent);
                     assert.equal(event.schema, ConversionEventSchema);
@@ -414,32 +414,32 @@ describe('model', function () {
         });
       });
 
-      var checkHydratesCorrectModels = function (fields, done, checkUndefinedRevenue) {
+      var checkHydratesCorrectModels = function(fields, done, checkUndefinedRevenue) {
         var baseEvent = new BaseEvent({name: 'Base event'});
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function (err) {
+        baseEvent.save(function(err) {
           assert.ifError(err);
-          impressionEvent.save(function (err) {
+          impressionEvent.save(function(err) {
             assert.ifError(err);
-            conversionEvent.save(function (err) {
+            conversionEvent.save(function(err) {
               assert.ifError(err);
               // finds & hydrates BaseEvent
-              BaseEvent.findOne({_id: baseEvent._id}, fields, function (err, event) {
+              BaseEvent.findOne({_id: baseEvent._id}, fields, function(err, event) {
                 assert.ifError(err);
                 assert.ok(event instanceof BaseEvent);
                 assert.equal(event.name, 'Base event');
 
                 // finds & hydrates ImpressionEvent
-                BaseEvent.findOne({_id: impressionEvent._id}, fields, function (err, event) {
+                BaseEvent.findOne({_id: impressionEvent._id}, fields, function(err, event) {
                   assert.ifError(err);
                   assert.ok(event instanceof ImpressionEvent);
                   assert.equal(event.schema, ImpressionEventSchema);
                   assert.equal(event.name, 'Impression event');
 
                   // finds & hydrates ConversionEvent
-                  BaseEvent.findOne({_id: conversionEvent._id}, fields, function (err, event) {
+                  BaseEvent.findOne({_id: conversionEvent._id}, fields, function(err, event) {
                     assert.ifError(err);
                     assert.ok(event instanceof ConversionEvent);
                     assert.equal(event.schema, ConversionEventSchema);
@@ -456,44 +456,44 @@ describe('model', function () {
         });
       };
 
-      it('hydrates correct model when fields selection set as string inclusive', function (done) {
+      it('hydrates correct model when fields selection set as string inclusive', function(done) {
         checkHydratesCorrectModels('name', done, true);
       });
 
-      it('hydrates correct model when fields selection set as string exclusive', function (done) {
+      it('hydrates correct model when fields selection set as string exclusive', function(done) {
         checkHydratesCorrectModels('-revenue', done, true);
       });
 
-      it('hydrates correct model when fields selection set as empty string', function (done) {
+      it('hydrates correct model when fields selection set as empty string', function(done) {
         checkHydratesCorrectModels('', done);
       });
 
-      it('hydrates correct model when fields selection set as object inclusive', function (done) {
+      it('hydrates correct model when fields selection set as object inclusive', function(done) {
         checkHydratesCorrectModels({name: 1}, done, true);
       });
 
-      it('hydrates correct model when fields selection set as object exclusive', function (done) {
+      it('hydrates correct model when fields selection set as object exclusive', function(done) {
         checkHydratesCorrectModels({revenue: 0}, done, true);
       });
 
-      it('hydrates correct model when fields selection set as empty object', function (done) {
+      it('hydrates correct model when fields selection set as empty object', function(done) {
         checkHydratesCorrectModels({}, done);
       });
 
-      it('discriminator model only finds a document of its type', function (done) {
+      it('discriminator model only finds a document of its type', function(done) {
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 2});
 
-        impressionEvent.save(function (err) {
+        impressionEvent.save(function(err) {
           assert.ifError(err);
-          conversionEvent.save(function (err) {
+          conversionEvent.save(function(err) {
             assert.ifError(err);
             // doesn't find anything since we're querying for an impression id
             var query = ConversionEvent.findOne({_id: impressionEvent._id});
             assert.equal(query.op, 'findOne');
             assert.deepEqual(query._conditions, {_id: impressionEvent._id, __t: 'model-discriminator-querying-conversion'});
 
-            query.exec(function (err, document) {
+            query.exec(function(err, document) {
               assert.ifError(err);
               assert.equal(document, null);
 
@@ -502,7 +502,7 @@ describe('model', function () {
               assert.equal(query.op, 'findOne');
               assert.deepEqual(query._conditions, {__t: 'model-discriminator-querying-conversion'});
 
-              query.exec(function (err, document) {
+              query.exec(function(err, document) {
                 assert.ifError(err);
                 assert.ok(document instanceof ConversionEvent);
                 assert.equal(document.__t, 'model-discriminator-querying-conversion');
@@ -513,20 +513,20 @@ describe('model', function () {
         });
       });
 
-      var checkDiscriminatorModelsFindOneDocumentOfItsType = function (fields, done) {
+      var checkDiscriminatorModelsFindOneDocumentOfItsType = function(fields, done) {
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 2});
 
-        impressionEvent.save(function (err) {
+        impressionEvent.save(function(err) {
           assert.ifError(err);
-          conversionEvent.save(function (err) {
+          conversionEvent.save(function(err) {
             assert.ifError(err);
             // doesn't find anything since we're querying for an impression id
             var query = ConversionEvent.findOne({_id: impressionEvent._id}, fields);
             assert.equal(query.op, 'findOne');
             assert.deepEqual(query._conditions, {_id: impressionEvent._id, __t: 'model-discriminator-querying-conversion'});
 
-            query.exec(function (err, document) {
+            query.exec(function(err, document) {
               assert.ifError(err);
               assert.equal(document, null);
 
@@ -535,7 +535,7 @@ describe('model', function () {
               assert.equal(query.op, 'findOne');
               assert.deepEqual(query._conditions, {__t: 'model-discriminator-querying-conversion'});
 
-              query.exec(function (err, document) {
+              query.exec(function(err, document) {
                 assert.ifError(err);
                 assert.ok(document instanceof ConversionEvent);
                 assert.equal(document.__t, 'model-discriminator-querying-conversion');
@@ -546,46 +546,46 @@ describe('model', function () {
         });
       };
 
-      it('discriminator model only finds a document of its type when fields selection set as string inclusive', function (done) {
+      it('discriminator model only finds a document of its type when fields selection set as string inclusive', function(done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType('name', done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as string exclusive', function (done) {
+      it('discriminator model only finds a document of its type when fields selection set as string exclusive', function(done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType('-revenue', done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as empty string', function (done) {
+      it('discriminator model only finds a document of its type when fields selection set as empty string', function(done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType('', done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as object inclusive', function (done) {
+      it('discriminator model only finds a document of its type when fields selection set as object inclusive', function(done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType({name: 1}, done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as object exclusive', function (done) {
+      it('discriminator model only finds a document of its type when fields selection set as object exclusive', function(done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType({revenue: 0}, done);
       });
 
-      it('discriminator model only finds a document of its type when fields selection set as empty object', function (done) {
+      it('discriminator model only finds a document of its type when fields selection set as empty object', function(done) {
         checkDiscriminatorModelsFindOneDocumentOfItsType({}, done);
       });
     });
 
-    describe('findOneAndUpdate', function () {
-      it('does not update models of other types', function (done) {
+    describe('findOneAndUpdate', function() {
+      it('does not update models of other types', function(done) {
         var baseEvent = new BaseEvent({name: 'Base event'});
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function (err) {
+        baseEvent.save(function(err) {
           assert.ifError(err);
-          impressionEvent.save(function (err) {
+          impressionEvent.save(function(err) {
             assert.ifError(err);
-            conversionEvent.save(function (err) {
+            conversionEvent.save(function(err) {
               assert.ifError(err);
               var query = ConversionEvent.findOneAndUpdate({name: 'Impression event'}, {$set: {name: 'Impression event - updated'}});
               assert.deepEqual(query._conditions, {name: 'Impression event', __t: 'model-discriminator-querying-conversion'});
-              query.exec(function (err, document) {
+              query.exec(function(err, document) {
                 assert.ifError(err);
                 assert.equal(document, null);
                 done();
@@ -595,20 +595,20 @@ describe('model', function () {
         });
       });
 
-      it('updates models of its own type', function (done) {
+      it('updates models of its own type', function(done) {
         var baseEvent = new BaseEvent({name: 'Base event'});
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function (err) {
+        baseEvent.save(function(err) {
           assert.ifError(err);
-          impressionEvent.save(function (err) {
+          impressionEvent.save(function(err) {
             assert.ifError(err);
-            conversionEvent.save(function (err) {
+            conversionEvent.save(function(err) {
               assert.ifError(err);
               var query = ConversionEvent.findOneAndUpdate({name: 'Conversion event'}, {$set: {name: 'Conversion event - updated'}}, {'new': true});
               assert.deepEqual(query._conditions, {name: 'Conversion event', __t: 'model-discriminator-querying-conversion'});
-              query.exec(function (err, document) {
+              query.exec(function(err, document) {
                 assert.ifError(err);
                 var expected = conversionEvent.toJSON();
                 expected.name = 'Conversion event - updated';
@@ -620,20 +620,20 @@ describe('model', function () {
         });
       });
 
-      it('base model modifies any event type', function (done) {
+      it('base model modifies any event type', function(done) {
         var baseEvent = new BaseEvent({name: 'Base event'});
         var impressionEvent = new ImpressionEvent({name: 'Impression event'});
         var conversionEvent = new ConversionEvent({name: 'Conversion event', revenue: 1.337});
 
-        baseEvent.save(function (err) {
+        baseEvent.save(function(err) {
           assert.ifError(err);
-          impressionEvent.save(function (err) {
+          impressionEvent.save(function(err) {
             assert.ifError(err);
-            conversionEvent.save(function (err) {
+            conversionEvent.save(function(err) {
               assert.ifError(err);
               var query = BaseEvent.findOneAndUpdate({name: 'Conversion event'}, {$set: {name: 'Conversion event - updated'}}, {'new': true});
               assert.deepEqual(query._conditions, {name: 'Conversion event'});
-              query.exec(function (err, document) {
+              query.exec(function(err, document) {
                 assert.ifError(err);
                 var expected = conversionEvent.toJSON();
                 expected.name = 'Conversion event - updated';
@@ -646,8 +646,8 @@ describe('model', function () {
       });
     });
 
-    describe('population/reference mapping', function () {
-      it('populates and hydrates correct models', function (done) {
+    describe('population/reference mapping', function() {
+      it('populates and hydrates correct models', function(done) {
         var vehicleSchema = new Schema();
         var carSchema = new Schema({speed: Number});
         var busSchema = new Schema({speed: Number});
@@ -663,14 +663,14 @@ describe('model', function () {
             Bus = Vehicle.discriminator('ModelDiscriminatorPopulationBus', busSchema),
             User = db.model('ModelDiscriminatorPopulationUser', userSchema);
 
-        Vehicle.create({}, function (err, vehicle) {
+        Vehicle.create({}, function(err, vehicle) {
           assert.ifError(err);
-          Car.create({speed: 160}, function (err, car) {
-            Bus.create({speed: 80}, function (err, bus) {
+          Car.create({speed: 160}, function(err, car) {
+            Bus.create({speed: 80}, function(err, bus) {
               assert.ifError(err);
-              User.create({vehicles: [vehicle._id, car._id, bus._id], favoriteVehicle: car._id, favoriteBus: bus._id}, function (err) {
+              User.create({vehicles: [vehicle._id, car._id, bus._id], favoriteVehicle: car._id, favoriteBus: bus._id}, function(err) {
                 assert.ifError(err);
-                User.findOne({}).populate('vehicles favoriteVehicle favoriteBus').exec(function (err, user) {
+                User.findOne({}).populate('vehicles favoriteVehicle favoriteBus').exec(function(err, user) {
                   assert.ifError(err);
 
                   var expected = {
@@ -706,7 +706,7 @@ describe('model', function () {
         });
       });
 
-      it('reference in child schemas (gh-2719)', function (done) {
+      it('reference in child schemas (gh-2719)', function(done) {
         var vehicleSchema = new Schema({});
         var carSchema = new Schema({
           speed: Number,
@@ -727,16 +727,16 @@ describe('model', function () {
             Bus = Vehicle.discriminator('gh2719PopulationBus', busSchema),
             Garage = db.model('gh2719PopulationGarage', garageSchema);
 
-        Garage.create({name: 'My', num_of_places: 3}, function (err, garage) {
+        Garage.create({name: 'My', num_of_places: 3}, function(err, garage) {
           assert.ifError(err);
-          Car.create({speed: 160, garage: garage}, function (err) {
+          Car.create({speed: 160, garage: garage}, function(err) {
             assert.ifError(err);
-            Bus.create({speed: 80, garage: garage}, function (err) {
+            Bus.create({speed: 80, garage: garage}, function(err) {
               assert.ifError(err);
-              Vehicle.find({}).populate('garage').exec(function (err, vehicles) {
+              Vehicle.find({}).populate('garage').exec(function(err, vehicles) {
                 assert.ifError(err);
 
-                vehicles.forEach(function (v) {
+                vehicles.forEach(function(v) {
                   assert.ok(v.garage instanceof Garage);
                 });
 
@@ -747,7 +747,7 @@ describe('model', function () {
         });
       });
 
-      it('reference in child schemas (gh-2719-2)', function (done) {
+      it('reference in child schemas (gh-2719-2)', function(done) {
         var EventSchema, Event, TalkSchema, Talk, Survey;
 
         function BaseSchema() {
@@ -785,7 +785,7 @@ describe('model', function () {
         Survey.create({
           name: 'That you see?',
           date: Date.now()
-        }, function (err, survey) {
+        }, function(err, survey) {
           assert.ifError(err);
 
           Talk.create({
@@ -794,10 +794,10 @@ describe('model', function () {
             pin: '0004',
             period: {start: '11:00', end: '12:00'},
             surveys: [survey]
-          }, function (err) {
+          }, function(err) {
             assert.ifError(err);
 
-            Event.find({}).populate('surveys').exec(function (err, events) {
+            Event.find({}).populate('surveys').exec(function(err, events) {
               assert.ifError(err);
 
               assert.ok(events[0].surveys[0] instanceof Survey);
@@ -809,30 +809,30 @@ describe('model', function () {
       });
     });
 
-    describe('aggregate', function () {
+    describe('aggregate', function() {
       var impressionEvent, conversionEvent, ignoredImpressionEvent;
 
-      beforeEach(function (done) {
+      beforeEach(function(done) {
         impressionEvent = new ImpressionEvent({name: 'Test Event'});
         conversionEvent = new ConversionEvent({name: 'Test Event', revenue: 10});
         ignoredImpressionEvent = new ImpressionEvent({name: 'Ignored Event'});
 
         async.forEach(
           [impressionEvent, conversionEvent, ignoredImpressionEvent],
-          function (doc, cb) {
+          function(doc, cb) {
             doc.save(cb);
           },
           done
         );
       });
 
-      describe('using "RootModel#aggregate"', function () {
-        it('to aggregate documents of all discriminators', function (done) {
+      describe('using "RootModel#aggregate"', function() {
+        it('to aggregate documents of all discriminators', function(done) {
           var aggregate = BaseEvent.aggregate([
             {$match: {name: 'Test Event'}}
           ]);
 
-          aggregate.exec(function (err, docs) {
+          aggregate.exec(function(err, docs) {
             assert.ifError(err);
             assert.deepEqual(aggregate._pipeline, [
               {$match: {name: 'Test Event'}}
@@ -843,13 +843,13 @@ describe('model', function () {
         });
       });
 
-      describe('using "ModelDiscriminator#aggregate"', function () {
-        it('only aggregates documents of the appropriate discriminator', function (done) {
+      describe('using "ModelDiscriminator#aggregate"', function() {
+        it('only aggregates documents of the appropriate discriminator', function(done) {
           var aggregate = ImpressionEvent.aggregate([
             {$group: {_id: '$__t', count: {$sum: 1}}}
           ]);
 
-          aggregate.exec(function (err, result) {
+          aggregate.exec(function(err, result) {
             assert.ifError(err);
 
             // Discriminator `$match` pipeline step was added on the
@@ -869,12 +869,12 @@ describe('model', function () {
           });
         });
 
-        it('merges the first pipeline stages if applicable', function (done) {
+        it('merges the first pipeline stages if applicable', function(done) {
           var aggregate = ImpressionEvent.aggregate([
             {$match: {name: 'Test Event'}}
           ]);
 
-          aggregate.exec(function (err, result) {
+          aggregate.exec(function(err, result) {
             assert.ifError(err);
 
             // Discriminator `$match` pipeline step was added on the
diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js
index 9cc7e0c62df..9344d7ddf06 100644
--- a/test/model.discriminator.test.js
+++ b/test/model.discriminator.test.js
@@ -18,27 +18,27 @@ var PersonSchema = new Schema({
   gender: String
 }, {collection: 'model-discriminator-' + random()});
 PersonSchema.index({name: 1});
-PersonSchema.methods.getFullName = function () {
+PersonSchema.methods.getFullName = function() {
   return this.name.first + ' ' + this.name.last;
 };
 PersonSchema.methods.toJSonConfig = {
   include: ['prop1', 'prop2'],
   exclude: ['prop3', 'prop4']
 };
-PersonSchema.statics.findByGender = function () {
+PersonSchema.statics.findByGender = function() {
 };
-PersonSchema.virtual('name.full').get(function () {
+PersonSchema.virtual('name.full').get(function() {
   return this.name.first + ' ' + this.name.last;
 });
-PersonSchema.virtual('name.full').set(function (name) {
+PersonSchema.virtual('name.full').set(function(name) {
   var split = name.split(' ');
   this.name.first = split[0];
   this.name.last = split[1];
 });
-PersonSchema.path('gender').validate(function (value) {
+PersonSchema.path('gender').validate(function(value) {
   return /[A-Z]/.test(value);
 }, 'Invalid name');
-PersonSchema.post('save', function (next) {
+PersonSchema.post('save', function(next) {
   next();
 });
 PersonSchema.set('toObject', {getters: true, virtuals: true});
@@ -46,42 +46,42 @@ PersonSchema.set('toJSON', {getters: true, virtuals: true});
 
 var EmployeeSchema = new Schema({department: String});
 EmployeeSchema.index({department: 1});
-EmployeeSchema.methods.getDepartment = function () {
+EmployeeSchema.methods.getDepartment = function() {
   return this.department;
 };
-EmployeeSchema.statics.findByDepartment = function () {
+EmployeeSchema.statics.findByDepartment = function() {
 };
-EmployeeSchema.path('department').validate(function (value) {
+EmployeeSchema.path('department').validate(function(value) {
   return /[a-zA-Z]/.test(value);
 }, 'Invalid name');
-var employeeSchemaPreSaveFn = function (next) {
+var employeeSchemaPreSaveFn = function(next) {
   next();
 };
 EmployeeSchema.pre('save', employeeSchemaPreSaveFn);
 EmployeeSchema.set('toObject', {getters: true, virtuals: false});
 EmployeeSchema.set('toJSON', {getters: false, virtuals: true});
 
-describe('model', function () {
-  describe('discriminator()', function () {
+describe('model', function() {
+  describe('discriminator()', function() {
     var db, Person, Employee;
 
-    before(function () {
+    before(function() {
       db = start();
       Person = db.model('model-discriminator-person', PersonSchema);
       Employee = Person.discriminator('model-discriminator-employee', EmployeeSchema);
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('model defaults without discriminator', function (done) {
+    it('model defaults without discriminator', function(done) {
       var Model = db.model('model-discriminator-defaults', new Schema(), 'model-discriminator-' + random());
       assert.equal(Model.discriminators, undefined);
       done();
     });
 
-    it('is instance of root', function (done) {
+    it('is instance of root', function(done) {
       assert.equal(Employee.baseModelName, 'model-discriminator-person');
       var employee = new Employee();
       assert.ok(employee instanceof Person);
@@ -91,7 +91,7 @@ describe('model', function () {
       done();
     });
 
-    it('can define static and instance methods', function (done) {
+    it('can define static and instance methods', function(done) {
       function BossBaseSchema() {
         Schema.apply(this, arguments);
 
@@ -105,10 +105,10 @@ describe('model', function () {
 
       var PersonSchema = new BossBaseSchema();
       var BossSchema = new BossBaseSchema({department: String});
-      BossSchema.methods.myName = function () {
+      BossSchema.methods.myName = function() {
         return this.name;
       };
-      BossSchema.statics.currentPresident = function () {
+      BossSchema.statics.currentPresident = function() {
         return 'obama';
       };
       var Person = db.model('Person', PersonSchema);
@@ -122,24 +122,24 @@ describe('model', function () {
       done();
     });
 
-    it('sets schema root discriminator mapping', function (done) {
+    it('sets schema root discriminator mapping', function(done) {
       assert.deepEqual(PersonSchema.discriminatorMapping, {key: '__t', value: null, isRoot: true});
       done();
     });
 
-    it('sets schema discriminator type mapping', function (done) {
+    it('sets schema discriminator type mapping', function(done) {
       assert.deepEqual(EmployeeSchema.discriminatorMapping, {key: '__t', value: 'model-discriminator-employee', isRoot: false});
       done();
     });
 
-    it('adds discriminatorKey to schema with default as name', function (done) {
+    it('adds discriminatorKey to schema with default as name', function(done) {
       var type = EmployeeSchema.paths.__t;
       assert.equal(type.options.type, String);
       assert.equal(type.options.default, 'model-discriminator-employee');
       done();
     });
 
-    it('adds discriminator to Model.discriminators object', function (done) {
+    it('adds discriminator to Model.discriminators object', function(done) {
       assert.equal(Object.keys(Person.discriminators).length, 1);
       assert.equal(Person.discriminators['model-discriminator-employee'], Employee);
       var newName = 'model-discriminator-' + random();
@@ -149,9 +149,9 @@ describe('model', function () {
       done();
     });
 
-    it('throws error on invalid schema', function (done) {
+    it('throws error on invalid schema', function(done) {
       assert.throws(
-          function () {
+          function() {
             Person.discriminator('Foo');
           },
           /You must pass a valid discriminator Schema/
@@ -159,9 +159,9 @@ describe('model', function () {
       done();
     });
 
-    it('throws error when attempting to nest discriminators', function (done) {
+    it('throws error when attempting to nest discriminators', function(done) {
       assert.throws(
-          function () {
+          function() {
             Employee.discriminator('model-discriminator-foo', new Schema());
           },
           /Discriminator "model-discriminator-foo" can only be a discriminator of the root model/
@@ -169,9 +169,9 @@ describe('model', function () {
       done();
     });
 
-    it('throws error when discriminator has mapped discriminator key in schema', function (done) {
+    it('throws error when discriminator has mapped discriminator key in schema', function(done) {
       assert.throws(
-          function () {
+          function() {
             Person.discriminator('model-discriminator-foo', new Schema({__t: String}));
           },
           /Discriminator "model-discriminator-foo" cannot have field with name "__t"/
@@ -179,9 +179,9 @@ describe('model', function () {
       done();
     });
 
-    it('throws error when discriminator has mapped discriminator key in schema with discriminatorKey option set', function (done) {
+    it('throws error when discriminator has mapped discriminator key in schema with discriminatorKey option set', function(done) {
       assert.throws(
-          function () {
+          function() {
             var Foo = db.model('model-discriminator-foo', new Schema({}, {discriminatorKey: '_type'}), 'model-discriminator-' + random());
             Foo.discriminator('model-discriminator-bar', new Schema({_type: String}));
           },
@@ -190,11 +190,11 @@ describe('model', function () {
       done();
     });
 
-    it('throws error when discriminator with taken name is added', function (done) {
+    it('throws error when discriminator with taken name is added', function(done) {
       var Foo = db.model('model-discriminator-foo', new Schema({}), 'model-discriminator-' + random());
       Foo.discriminator('model-discriminator-taken', new Schema());
       assert.throws(
-          function () {
+          function() {
             Foo.discriminator('model-discriminator-taken', new Schema());
           },
           /Discriminator with name "model-discriminator-taken" already exists/
@@ -202,8 +202,8 @@ describe('model', function () {
       done();
     });
 
-    it('works with nested schemas (gh-2821)', function (done) {
-      var MinionSchema = function () {
+    it('works with nested schemas (gh-2821)', function(done) {
+      var MinionSchema = function() {
         mongoose.Schema.apply(this, arguments);
 
         this.add({
@@ -212,7 +212,7 @@ describe('model', function () {
       };
       util.inherits(MinionSchema, mongoose.Schema);
 
-      var BaseSchema = function () {
+      var BaseSchema = function() {
         mongoose.Schema.apply(this, arguments);
 
         this.add({
@@ -228,27 +228,27 @@ describe('model', function () {
         department: String
       });
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         var Person = db.model('gh2821', PersonSchema);
         Person.discriminator('Boss', BossSchema);
       });
       done();
     });
 
-    describe('options', function () {
-      it('allows toObject to be overridden', function (done) {
+    describe('options', function() {
+      it('allows toObject to be overridden', function(done) {
         assert.notDeepEqual(Employee.schema.get('toObject'), Person.schema.get('toObject'));
         assert.deepEqual(Employee.schema.get('toObject'), {getters: true, virtuals: false});
         done();
       });
 
-      it('allows toJSON to be overridden', function (done) {
+      it('allows toJSON to be overridden', function(done) {
         assert.notDeepEqual(Employee.schema.get('toJSON'), Person.schema.get('toJSON'));
         assert.deepEqual(Employee.schema.get('toJSON'), {getters: false, virtuals: true});
         done();
       });
 
-      it('is not customizable', function (done) {
+      it('is not customizable', function(done) {
         var errorMessage,
             CustomizedSchema = new Schema({}, {capped: true});
         try {
@@ -262,21 +262,21 @@ describe('model', function () {
       });
     });
 
-    describe('root schema inheritance', function () {
-      it('inherits field mappings', function (done) {
+    describe('root schema inheritance', function() {
+      it('inherits field mappings', function(done) {
         assert.strictEqual(Employee.schema.path('name'), Person.schema.path('name'));
         assert.strictEqual(Employee.schema.path('gender'), Person.schema.path('gender'));
         assert.equal(Person.schema.paths.department, undefined);
         done();
       });
 
-      it('inherits validators', function (done) {
+      it('inherits validators', function(done) {
         assert.strictEqual(Employee.schema.path('gender').validators, PersonSchema.path('gender').validators);
         assert.strictEqual(Employee.schema.path('department').validators, EmployeeSchema.path('department').validators);
         done();
       });
 
-      it('does not inherit and override fields that exist', function (done) {
+      it('does not inherit and override fields that exist', function(done) {
         var FemaleSchema = new Schema({gender: {type: String, default: 'F'}}),
             Female = Person.discriminator('model-discriminator-female', FemaleSchema);
 
@@ -288,7 +288,7 @@ describe('model', function () {
         done();
       });
 
-      it('inherits methods', function (done) {
+      it('inherits methods', function(done) {
         var employee = new Employee();
         assert.strictEqual(employee.getFullName, PersonSchema.methods.getFullName);
         assert.strictEqual(employee.getDepartment, EmployeeSchema.methods.getDepartment);
@@ -296,21 +296,21 @@ describe('model', function () {
         done();
       });
 
-      it('inherits statics', function (done) {
+      it('inherits statics', function(done) {
         assert.strictEqual(Employee.findByGender, EmployeeSchema.statics.findByGender);
         assert.strictEqual(Employee.findByDepartment, EmployeeSchema.statics.findByDepartment);
         assert.equal(Person.findByDepartment, undefined);
         done();
       });
 
-      it('inherits virtual (g.s)etters', function (done) {
+      it('inherits virtual (g.s)etters', function(done) {
         var employee = new Employee();
         employee.name.full = 'John Doe';
         assert.equal(employee.name.full, 'John Doe');
         done();
       });
 
-      it('merges callQueue with base queue defined before discriminator types callQueue', function (done) {
+      it('merges callQueue with base queue defined before discriminator types callQueue', function(done) {
         assert.equal(Employee.schema.callQueue.length, 4);
         // PersonSchema.post('save')
         assert.strictEqual(Employee.schema.callQueue[0], Person.schema.callQueue[0]);
@@ -323,13 +323,13 @@ describe('model', function () {
         done();
       });
 
-      it('does not inherit indexes', function (done) {
+      it('does not inherit indexes', function(done) {
         assert.deepEqual(Person.schema.indexes(), [[{name: 1}, {background: true}]]);
         assert.deepEqual(Employee.schema.indexes(), [[{department: 1}, {background: true}]]);
         done();
       });
 
-      it('gets options overridden by root options except toJSON and toObject', function (done) {
+      it('gets options overridden by root options except toJSON and toObject', function(done) {
         var personOptions = clone(Person.schema.options),
             employeeOptions = clone(Employee.schema.options);
 
diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js
index 765e100e054..f2997f9890b 100644
--- a/test/model.field.selection.test.js
+++ b/test/model.field.selection.test.js
@@ -46,8 +46,8 @@ var modelName = 'model.select.blogpost';
 mongoose.model(modelName, BlogPostB);
 var collection = 'blogposts_' + random();
 
-describe('model field selection', function () {
-  it('excluded fields should be undefined', function (done) {
+describe('model field selection', function() {
+  it('excluded fields should be undefined', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         date = new Date;
@@ -59,11 +59,11 @@ describe('model field selection', function () {
       meta: {date: date}
     };
 
-    BlogPostB.create(doc, function (err, created) {
+    BlogPostB.create(doc, function(err, created) {
       assert.ifError(err);
 
       var id = created.id;
-      BlogPostB.findById(id, {title: 0, 'meta.date': 0, owners: 0, 'comments.user': 0}, function (err, found) {
+      BlogPostB.findById(id, {title: 0, 'meta.date': 0, owners: 0, 'comments.user': 0}, function(err, found) {
         db.close();
         assert.ifError(err);
         assert.equal(found._id.toString(), created._id);
@@ -76,7 +76,7 @@ describe('model field selection', function () {
         assert.equal(undefined, found.owners);
         assert.strictEqual(true, Array.isArray(found.comments));
         assert.equal(found.comments.length, 2);
-        found.comments.forEach(function (comment) {
+        found.comments.forEach(function(comment) {
           assert.equal(undefined, comment.user);
         });
         done();
@@ -84,16 +84,16 @@ describe('model field selection', function () {
     });
   });
 
-  it('excluded fields should be undefined and defaults applied to other fields', function (done) {
+  it('excluded fields should be undefined and defaults applied to other fields', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         id = new DocumentObjectId,
         date = new Date;
 
-    BlogPostB.collection.insert({_id: id, title: 'hahaha1', meta: {date: date}}, function (err) {
+    BlogPostB.collection.insert({_id: id, title: 'hahaha1', meta: {date: date}}, function(err) {
       assert.ifError(err);
 
-      BlogPostB.findById(id, {title: 0}, function (err, found) {
+      BlogPostB.findById(id, {title: 0}, function(err, found) {
         db.close();
         assert.ifError(err);
         assert.equal(found._id.toString(), id);
@@ -108,12 +108,12 @@ describe('model field selection', function () {
     });
   });
 
-  it('where subset of fields excludes _id', function (done) {
+  it('where subset of fields excludes _id', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
-    BlogPostB.create({title: 'subset 1'}, function (err) {
+    BlogPostB.create({title: 'subset 1'}, function(err) {
       assert.ifError(err);
-      BlogPostB.findOne({title: 'subset 1'}, {title: 1, _id: 0}, function (err, found) {
+      BlogPostB.findOne({title: 'subset 1'}, {title: 1, _id: 0}, function(err, found) {
         db.close();
         assert.ifError(err);
         assert.strictEqual(undefined, found._id);
@@ -123,12 +123,12 @@ describe('model field selection', function () {
     });
   });
 
-  it('works with subset of fields, excluding _id', function (done) {
+  it('works with subset of fields, excluding _id', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
-    BlogPostB.create({title: 'subset 1', author: 'me'}, function (err) {
+    BlogPostB.create({title: 'subset 1', author: 'me'}, function(err) {
       assert.ifError(err);
-      BlogPostB.find({title: 'subset 1'}, {title: 1, _id: 0}, function (err, found) {
+      BlogPostB.find({title: 'subset 1'}, {title: 1, _id: 0}, function(err, found) {
         db.close();
         assert.ifError(err);
         assert.strictEqual(undefined, found[0]._id);
@@ -141,14 +141,14 @@ describe('model field selection', function () {
     });
   });
 
-  it('works with just _id and findOneAndUpdate (gh-3407)', function (done) {
+  it('works with just _id and findOneAndUpdate (gh-3407)', function(done) {
     var db = start();
 
     var MyModel = db.model('gh3407', {test: {type: Number, default: 1}});
 
-    MyModel.collection.insert({}, function (error) {
+    MyModel.collection.insert({}, function(error) {
       assert.ifError(error);
-      MyModel.findOne({}, {_id: 1}, function (error, doc) {
+      MyModel.findOne({}, {_id: 1}, function(error, doc) {
         assert.ifError(error);
         assert.ok(!doc.test);
         db.close(done);
@@ -156,13 +156,13 @@ describe('model field selection', function () {
     });
   });
 
-  it('works with subset of fields excluding emebedded doc _id (gh-541)', function (done) {
+  it('works with subset of fields excluding emebedded doc _id (gh-541)', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.create({title: 'LOTR', comments: [{title: ':)'}]}, function (err, created) {
+    BlogPostB.create({title: 'LOTR', comments: [{title: ':)'}]}, function(err, created) {
       assert.ifError(err);
-      BlogPostB.find({_id: created}, {_id: 0, 'comments._id': 0}, function (err, found) {
+      BlogPostB.find({_id: created}, {_id: 0, 'comments._id': 0}, function(err, found) {
         db.close();
         assert.ifError(err);
         assert.strictEqual(undefined, found[0]._id);
@@ -180,16 +180,16 @@ describe('model field selection', function () {
     });
   });
 
-  it('included fields should have defaults applied when no value exists in db (gh-870)', function (done) {
+  it('included fields should have defaults applied when no value exists in db (gh-870)', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         id = new DocumentObjectId;
 
     BlogPostB.collection.insert(
-        {_id: id, title: 'issue 870'}, {safe: true}, function (err) {
+        {_id: id, title: 'issue 870'}, {safe: true}, function(err) {
           assert.ifError(err);
 
-          BlogPostB.findById(id, 'def comments', function (err, found) {
+          BlogPostB.findById(id, 'def comments', function(err, found) {
             db.close();
             assert.ifError(err);
             assert.ok(found);
@@ -204,21 +204,21 @@ describe('model field selection', function () {
         });
   });
 
-  it('including subdoc field excludes other subdoc fields (gh-1027)', function (done) {
+  it('including subdoc field excludes other subdoc fields (gh-1027)', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.create({comments: [{title: 'a'}, {title: 'b'}]}, function (err, doc) {
+    BlogPostB.create({comments: [{title: 'a'}, {title: 'b'}]}, function(err, doc) {
       assert.ifError(err);
 
-      BlogPostB.findById(doc._id).select('_id comments.title').exec(function (err, found) {
+      BlogPostB.findById(doc._id).select('_id comments.title').exec(function(err, found) {
         db.close();
         assert.ifError(err);
         assert.ok(found);
         assert.equal(found._id.toString(), doc._id.toString());
         assert.strictEqual(undefined, found.title);
         assert.strictEqual(true, Array.isArray(found.comments));
-        found.comments.forEach(function (comment) {
+        found.comments.forEach(function(comment) {
           assert.equal(undefined, comment.body);
           assert.equal(undefined, comment.comments);
           assert.equal(undefined, comment._id);
@@ -229,14 +229,14 @@ describe('model field selection', function () {
     });
   });
 
-  it('excluding nested subdoc fields (gh-1027)', function (done) {
+  it('excluding nested subdoc fields (gh-1027)', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.create({title: 'top', comments: [{title: 'a', body: 'body'}, {title: 'b', body: 'body', comments: [{title: 'c'}]}]}, function (err, doc) {
+    BlogPostB.create({title: 'top', comments: [{title: 'a', body: 'body'}, {title: 'b', body: 'body', comments: [{title: 'c'}]}]}, function(err, doc) {
       assert.ifError(err);
 
-      BlogPostB.findById(doc._id).select('-_id -comments.title -comments.comments.comments -numbers').exec(function (err, found) {
+      BlogPostB.findById(doc._id).select('-_id -comments.title -comments.comments.comments -numbers').exec(function(err, found) {
         db.close();
         assert.ifError(err);
         assert.ok(found);
@@ -244,12 +244,12 @@ describe('model field selection', function () {
         assert.strictEqual('top', found.title);
         assert.equal(undefined, found.numbers);
         assert.strictEqual(true, Array.isArray(found.comments));
-        found.comments.forEach(function (comment) {
+        found.comments.forEach(function(comment) {
           assert.equal(undefined, comment.title);
           assert.equal('body', comment.body);
           assert.strictEqual(true, Array.isArray(comment.comments));
           assert.ok(comment._id);
-          comment.comments.forEach(function (comment) {
+          comment.comments.forEach(function(comment) {
             assert.equal('c', comment.title);
             assert.equal(undefined, comment.body);
             assert.equal(undefined, comment.comments);
@@ -261,10 +261,10 @@ describe('model field selection', function () {
     });
   });
 
-  describe('with $elemMatch projection', function () {
+  describe('with $elemMatch projection', function() {
     // mongodb 2.2 support
 
-    it('casts elemMatch args (gh-1091)', function (done) {
+    it('casts elemMatch args (gh-1091)', function(done) {
       var db = start();
 
       var postSchema = new Schema({
@@ -275,13 +275,13 @@ describe('model field selection', function () {
       var _id1 = new mongoose.Types.ObjectId;
       var _id2 = new mongoose.Types.ObjectId;
 
-      B.create({ids: [_id1, _id2]}, function (err, doc) {
+      B.create({ids: [_id1, _id2]}, function(err, doc) {
         assert.ifError(err);
 
         B
         .findById(doc._id)
         .select({ids: {$elemMatch: {$in: [_id2.toString()]}}})
-        .exec(function (err, found) {
+        .exec(function(err, found) {
           assert.ifError(err);
           assert.ok(found);
           assert.equal(found.id, doc.id);
@@ -291,7 +291,7 @@ describe('model field selection', function () {
           B
           .find({_id: doc._id})
           .select({ids: {$elemMatch: {$in: [_id2.toString()]}}})
-          .exec(function (err, found) {
+          .exec(function(err, found) {
             assert.ifError(err);
             assert.ok(found.length);
             found = found[0];
@@ -304,7 +304,7 @@ describe('model field selection', function () {
       });
     });
 
-    it('disallows saving modified elemMatch paths (gh-1334)', function (done) {
+    it('disallows saving modified elemMatch paths (gh-1334)', function(done) {
       var db = start();
 
       var postSchema = new Schema({
@@ -316,20 +316,20 @@ describe('model field selection', function () {
       var _id1 = new mongoose.Types.ObjectId;
       var _id2 = new mongoose.Types.ObjectId;
 
-      B.create({ids: [_id1, _id2], ids2: [_id2, _id1]}, function (err, doc) {
+      B.create({ids: [_id1, _id2], ids2: [_id2, _id1]}, function(err, doc) {
         assert.ifError(err);
 
         B
         .findById(doc._id)
         .select({ids: {$elemMatch: {$in: [_id2.toString()]}}})
         .select({ids2: {$elemMatch: {$in: [_id1.toString()]}}})
-        .exec(function (err, found) {
+        .exec(function(err, found) {
           assert.ifError(err);
           assert.equal(1, found.ids.length);
           assert.equal(1, found.ids2.length);
           found.ids = [];
           found.ids2.set(0, _id2);
-          found.save(function (err) {
+          found.save(function(err) {
             db.close();
             assert.ok(/\$elemMatch projection/.test(err));
             assert.ok(/ ids/.test(err));
@@ -340,7 +340,7 @@ describe('model field selection', function () {
       });
     });
 
-    it('works with $ positional in select (gh-2031)', function (done) {
+    it('works with $ positional in select (gh-2031)', function(done) {
       var db = start();
 
       var postSchema = new Schema({
@@ -348,12 +348,12 @@ describe('model field selection', function () {
       });
 
       var Post = db.model('gh-2031', postSchema, 'gh-2031');
-      Post.create({tags: [{tag: 'bacon', count: 2}, {tag: 'eggs', count: 3}]}, function (error) {
+      Post.create({tags: [{tag: 'bacon', count: 2}, {tag: 'eggs', count: 3}]}, function(error) {
         assert.ifError(error);
-        Post.findOne({'tags.tag': 'eggs'}, {'tags.$': 1}, function (error, post) {
+        Post.findOne({'tags.tag': 'eggs'}, {'tags.$': 1}, function(error, post) {
           assert.ifError(error);
           post.tags[0].count = 1;
-          post.save(function (error) {
+          post.save(function(error) {
             assert.ok(error);
             db.close(done);
           });
@@ -362,15 +362,15 @@ describe('model field selection', function () {
     });
   });
 
-  it('selecting an array of docs applies defaults properly (gh-1108)', function (done) {
+  it('selecting an array of docs applies defaults properly (gh-1108)', function(done) {
     var db = start(),
         M = db.model(modelName, collection);
 
     var m = new M({title: '1108', comments: [{body: 'yay'}]});
     m.comments[0].comments = undefined;
-    m.save(function (err, doc) {
+    m.save(function(err, doc) {
       assert.ifError(err);
-      M.findById(doc._id).select('comments').exec(function (err, found) {
+      M.findById(doc._id).select('comments').exec(function(err, found) {
         assert.ifError(err);
         assert.ok(Array.isArray(found.comments));
         assert.equal(1, found.comments.length);
@@ -380,7 +380,7 @@ describe('model field selection', function () {
     });
   });
 
-  it('appropriately filters subdocuments based on properties (gh-1280)', function (done) {
+  it('appropriately filters subdocuments based on properties (gh-1280)', function(done) {
     var db = start();
     var RouteSchema = new Schema({
       stations: {
@@ -417,14 +417,14 @@ describe('model field selection', function () {
       }
     };
 
-    Route.create(item, function (err, i) {
+    Route.create(item, function(err, i) {
       assert.ifError(err);
 
-      Route.findById(i.id).select('-stations').exec(function (err, res) {
+      Route.findById(i.id).select('-stations').exec(function(err, res) {
         assert.ifError(err);
         assert.ok(res.stations.toString() === 'undefined');
 
-        Route.findById(i.id).select('-stations.start -stations.end').exec(function (err, res) {
+        Route.findById(i.id).select('-stations.start -stations.end').exec(function(err, res) {
           assert.ifError(err);
           assert.equal(res.stations.start.toString(), 'undefined');
           assert.equal(res.stations.end.toString(), 'undefined');
diff --git a/test/model.findAndRemoveOne.test.js b/test/model.findAndRemoveOne.test.js
index 19780ed6b9e..6ae6b53c196 100644
--- a/test/model.findAndRemoveOne.test.js
+++ b/test/model.findAndRemoveOne.test.js
@@ -41,20 +41,20 @@ var BlogPost = new Schema({
 });
 
 BlogPost.virtual('titleWithAuthor')
-  .get(function () {
+  .get(function() {
     return this.get('title') + ' by ' + this.get('author');
   })
-  .set(function (val) {
+  .set(function(val) {
     var split = val.split(' by ');
     this.set('title', split[0]);
     this.set('author', split[1]);
   });
 
-BlogPost.method('cool', function () {
+BlogPost.method('cool', function() {
   return this;
 });
 
-BlogPost.static('woot', function () {
+BlogPost.static('woot', function() {
   return this;
 });
 
@@ -66,19 +66,19 @@ var collection = 'removeoneblogposts_' + random();
 var strictSchema = new Schema({name: String}, {strict: true});
 mongoose.model('RemoveOneStrictSchema', strictSchema);
 
-describe('model: findOneAndRemove:', function () {
-  it('returns the original document', function (done) {
+describe('model: findOneAndRemove:', function() {
+  it('returns the original document', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'remove muah';
 
     var post = new M({title: title});
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
-      M.findOneAndRemove({title: title}, function (err, doc) {
+      M.findOneAndRemove({title: title}, function(err, doc) {
         assert.ifError(err);
         assert.equal(doc.id, post.id);
-        M.findById(post.id, function (err, gone) {
+        M.findById(post.id, function(err, gone) {
           db.close();
           assert.ifError(err);
           assert.equal(null, gone);
@@ -88,7 +88,7 @@ describe('model: findOneAndRemove:', function () {
     });
   });
 
-  it('options/conditions/doc are merged when no callback is passed', function (done) {
+  it('options/conditions/doc are merged when no callback is passed', function(done) {
     var db = start(),
         M = db.model(modelname, collection);
 
@@ -127,7 +127,7 @@ describe('model: findOneAndRemove:', function () {
     done();
   });
 
-  it('executes when a callback is passed', function (done) {
+  it('executes when a callback is passed', function(done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         pending = 5;
@@ -147,13 +147,13 @@ describe('model: findOneAndRemove:', function () {
     }
   });
 
-  it('executed with only a callback throws', function (done) {
+  it('executed with only a callback throws', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         err;
 
     try {
-      M.findOneAndRemove(function () {});
+      M.findOneAndRemove(function() {});
     } catch (e) {
       err = e;
     }
@@ -164,14 +164,14 @@ describe('model: findOneAndRemove:', function () {
   });
 });
 
-describe('model: findByIdAndRemove:', function () {
-  it('executed with only a callback throws', function (done) {
+describe('model: findByIdAndRemove:', function() {
+  it('executed with only a callback throws', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         err;
 
     try {
-      M.findByIdAndRemove(function () {});
+      M.findByIdAndRemove(function() {});
     } catch (e) {
       err = e;
     }
@@ -181,7 +181,7 @@ describe('model: findByIdAndRemove:', function () {
     done();
   });
 
-  it('executes when a callback is passed', function (done) {
+  it('executes when a callback is passed', function(done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         _id = new DocumentObjectId,
@@ -199,18 +199,18 @@ describe('model: findByIdAndRemove:', function () {
     }
   });
 
-  it('returns the original document', function (done) {
+  it('returns the original document', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'remove muah pleez';
 
     var post = new M({title: title});
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
-      M.findByIdAndRemove(post.id, function (err, doc) {
+      M.findByIdAndRemove(post.id, function(err, doc) {
         assert.ifError(err);
         assert.equal(doc.id, post.id);
-        M.findById(post.id, function (err, gone) {
+        M.findById(post.id, function(err, gone) {
           db.close();
           assert.ifError(err);
           assert.equal(null, gone);
@@ -220,7 +220,7 @@ describe('model: findByIdAndRemove:', function () {
     });
   });
 
-  it('options/conditions/doc are merged when no callback is passed', function (done) {
+  it('options/conditions/doc are merged when no callback is passed', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -245,7 +245,7 @@ describe('model: findByIdAndRemove:', function () {
     done();
   });
 
-  it('supports v3 select string syntax', function (done) {
+  it('supports v3 select string syntax', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -264,7 +264,7 @@ describe('model: findByIdAndRemove:', function () {
     done();
   });
 
-  it('supports v3 select object syntax', function (done) {
+  it('supports v3 select object syntax', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -283,7 +283,7 @@ describe('model: findByIdAndRemove:', function () {
     done();
   });
 
-  it('supports v3 sort string syntax', function (done) {
+  it('supports v3 sort string syntax', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -304,7 +304,7 @@ describe('model: findByIdAndRemove:', function () {
     done();
   });
 
-  it('supports v3 sort object syntax', function (done) {
+  it('supports v3 sort object syntax', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -323,19 +323,19 @@ describe('model: findByIdAndRemove:', function () {
     db.close(done);
   });
 
-  it('supports population (gh-1395)', function (done) {
+  it('supports population (gh-1395)', function(done) {
     var db = start();
     var M = db.model('A', {name: String});
     var N = db.model('B', {a: {type: Schema.ObjectId, ref: 'A'}, i: Number});
 
-    M.create({name: 'i am an A'}, function (err, a) {
+    M.create({name: 'i am an A'}, function(err, a) {
       if (err) return done(err);
-      N.create({a: a._id, i: 10}, function (err, b) {
+      N.create({a: a._id, i: 10}, function(err, b) {
         if (err) return done(err);
 
         N.findOneAndRemove({_id: b._id}, {select: 'a -_id'})
         .populate('a')
-        .exec(function (err, doc) {
+        .exec(function(err, doc) {
           if (err) return done(err);
           assert.ok(doc);
           assert.equal(undefined, doc._id);
@@ -347,30 +347,30 @@ describe('model: findByIdAndRemove:', function () {
     });
   });
 
-  describe('middleware', function () {
+  describe('middleware', function() {
     var db;
 
-    beforeEach(function () {
+    beforeEach(function() {
       db = start();
     });
 
-    afterEach(function (done) {
+    afterEach(function(done) {
       db.close(done);
     });
 
-    it('works', function (done) {
+    it('works', function(done) {
       var s = new Schema({
         topping: {type: String, default: 'bacon'},
         base: String
       });
 
       var preCount = 0;
-      s.pre('findOneAndRemove', function () {
+      s.pre('findOneAndRemove', function() {
         ++preCount;
       });
 
       var postCount = 0;
-      s.post('findOneAndRemove', function () {
+      s.post('findOneAndRemove', function() {
         ++postCount;
       });
 
@@ -379,13 +379,13 @@ describe('model: findByIdAndRemove:', function () {
         base: 'eggs'
       });
 
-      breakfast.save(function (error) {
+      breakfast.save(function(error) {
         assert.ifError(error);
 
         Breakfast.findOneAndRemove(
           {base: 'eggs'},
           {},
-          function (error, breakfast) {
+          function(error, breakfast) {
             assert.ifError(error);
             assert.equal('eggs', breakfast.base);
             assert.equal(1, preCount);
@@ -395,19 +395,19 @@ describe('model: findByIdAndRemove:', function () {
       });
     });
 
-    it('works with exec()', function (done) {
+    it('works with exec()', function(done) {
       var s = new Schema({
         topping: {type: String, default: 'bacon'},
         base: String
       });
 
       var preCount = 0;
-      s.pre('findOneAndRemove', function () {
+      s.pre('findOneAndRemove', function() {
         ++preCount;
       });
 
       var postCount = 0;
-      s.post('findOneAndRemove', function () {
+      s.post('findOneAndRemove', function() {
         ++postCount;
       });
 
@@ -416,12 +416,12 @@ describe('model: findByIdAndRemove:', function () {
         base: 'eggs'
       });
 
-      breakfast.save(function (error) {
+      breakfast.save(function(error) {
         assert.ifError(error);
 
         Breakfast.
           findOneAndRemove({base: 'eggs'}, {}).
-          exec(function (error, breakfast) {
+          exec(function(error, breakfast) {
             assert.ifError(error);
             assert.equal('eggs', breakfast.base);
             assert.equal(1, preCount);
diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index afd4112ad90..439267b15dc 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -43,20 +43,20 @@ var BlogPost = new Schema({
 });
 
 BlogPost.virtual('titleWithAuthor')
-.get(function () {
+.get(function() {
   return this.get('title') + ' by ' + this.get('author');
 })
-.set(function (val) {
+.set(function(val) {
   var split = val.split(' by ');
   this.set('title', split[0]);
   this.set('author', split[1]);
 });
 
-BlogPost.method('cool', function () {
+BlogPost.method('cool', function() {
   return this;
 });
 
-BlogPost.static('woot', function () {
+BlogPost.static('woot', function() {
   return this;
 });
 
@@ -71,8 +71,8 @@ mongoose.model('UpdateOneStrictSchema', strictSchema);
 var strictThrowSchema = new Schema({name: String}, {strict: 'throw'});
 mongoose.model('UpdateOneStrictThrowSchema', strictThrowSchema);
 
-describe('model: findOneAndUpdate:', function () {
-  it('WWW returns the edited document', function (done) {
+describe('model: findOneAndUpdate:', function() {
+  it('WWW returns the edited document', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'Tobi ' + random(),
@@ -92,9 +92,9 @@ describe('model: findOneAndUpdate:', function () {
     post.owners = [id0, id1];
     post.comments = [{body: 'been there'}, {body: 'done that'}];
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
-      M.findById(post._id, function (err, cf) {
+      M.findById(post._id, function(err, cf) {
         assert.ifError(err);
         assert.equal(title, cf.title);
         assert.equal(author, cf.author);
@@ -125,7 +125,7 @@ describe('model: findOneAndUpdate:', function () {
           'comments.1.body': 8 // $set
         };
 
-        M.findOneAndUpdate({title: title}, update, {'new': true}, function (err, up) {
+        M.findOneAndUpdate({title: title}, update, {'new': true}, function(err, up) {
           db.close();
           assert.equal(err, null, err && err.stack);
 
@@ -151,14 +151,14 @@ describe('model: findOneAndUpdate:', function () {
     });
   });
 
-  describe('will correctly', function () {
+  describe('will correctly', function() {
     var db, ItemParentModel, ItemChildModel;
 
-    before(function () {
+    before(function() {
       db = start();
       var itemSpec = new Schema({
         item_id: {
-          type: ObjectId, required: true, default: function () {
+          type: ObjectId, required: true, default: function() {
             return new DocumentObjectId();
           }
         },
@@ -175,11 +175,11 @@ describe('model: findOneAndUpdate:', function () {
       ItemChildModel = db.model('ItemChildModel', itemSpec);
     });
 
-    after(function () {
+    after(function() {
       db.close();
     });
 
-    it('update subdocument in array item', function (done) {
+    it('update subdocument in array item', function(done) {
       var item1 = new ItemChildModel({
         address: {
           street: 'times square',
@@ -199,13 +199,13 @@ describe('model: findOneAndUpdate:', function () {
         }
       });
       var itemParent = new ItemParentModel({items: [item1, item2, item3]});
-      itemParent.save(function (err) {
+      itemParent.save(function(err) {
         assert.ifError(err);
         ItemParentModel.findOneAndUpdate(
             {_id: itemParent._id, 'items.item_id': item1.item_id},
             {$set: {'items.$.address': {}}},
             {new: true},
-            function (err, updatedDoc) {
+            function(err, updatedDoc) {
               assert.ifError(err);
               assert.ok(updatedDoc.items);
               assert.ok(updatedDoc.items instanceof Array);
@@ -219,7 +219,7 @@ describe('model: findOneAndUpdate:', function () {
     });
   });
 
-  it('returns the original document', function (done) {
+  it('returns the original document', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'Tobi ' + random(),
@@ -239,9 +239,9 @@ describe('model: findOneAndUpdate:', function () {
     post.owners = [id0, id1];
     post.comments = [{body: 'been there'}, {body: 'done that'}];
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
-      M.findById(post._id, function (err) {
+      M.findById(post._id, function(err) {
         assert.ifError(err);
 
         var update = {
@@ -255,7 +255,7 @@ describe('model: findOneAndUpdate:', function () {
           'comments.1.body': 8 // $set
         };
 
-        M.findOneAndUpdate({title: title}, update, {new: false}, function (err, up) {
+        M.findOneAndUpdate({title: title}, update, {new: false}, function(err, up) {
           db.close();
           assert.ifError(err);
 
@@ -281,7 +281,7 @@ describe('model: findOneAndUpdate:', function () {
     });
   });
 
-  it('allows upserting', function (done) {
+  it('allows upserting', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'Tobi ' + random(),
@@ -311,7 +311,7 @@ describe('model: findOneAndUpdate:', function () {
       $pull: {owners: id0}
     };
 
-    M.findOneAndUpdate({title: title}, update, {upsert: true, new: true}, function (err, up) {
+    M.findOneAndUpdate({title: title}, update, {upsert: true, new: true}, function(err, up) {
       db.close();
       assert.ifError(err);
 
@@ -329,7 +329,7 @@ describe('model: findOneAndUpdate:', function () {
     });
   });
 
-  it('options/conditions/doc are merged when no callback is passed', function (done) {
+  it('options/conditions/doc are merged when no callback is passed', function(done) {
     var db = start(),
         M = db.model(modelname, collection);
 
@@ -383,7 +383,7 @@ describe('model: findOneAndUpdate:', function () {
     done();
   });
 
-  it('executes when a callback is passed', function (done) {
+  it('executes when a callback is passed', function(done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         pending = 6;
@@ -406,7 +406,7 @@ describe('model: findOneAndUpdate:', function () {
     }
   });
 
-  it('executes when a callback is passed to a succeeding function', function (done) {
+  it('executes when a callback is passed to a succeeding function', function(done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         pending = 6;
@@ -429,13 +429,13 @@ describe('model: findOneAndUpdate:', function () {
     }
   });
 
-  it('executing with only a callback throws', function (done) {
+  it('executing with only a callback throws', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         err;
 
     try {
-      M.findOneAndUpdate(function () {
+      M.findOneAndUpdate(function() {
       });
     } catch (e) {
       err = e;
@@ -446,7 +446,7 @@ describe('model: findOneAndUpdate:', function () {
     done();
   });
 
-  it('updates numbers atomically', function (done) {
+  it('updates numbers atomically', function(done) {
     var db = start(),
         BlogPost = db.model(modelname, collection),
         totalDocs = 4;
@@ -454,19 +454,19 @@ describe('model: findOneAndUpdate:', function () {
     var post = new BlogPost();
     post.set('meta.visitors', 5);
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
       for (var i = 0; i < 4; ++i) {
         BlogPost
-        .findOneAndUpdate({_id: post._id}, {$inc: {'meta.visitors': 1}}, function (err) {
+        .findOneAndUpdate({_id: post._id}, {$inc: {'meta.visitors': 1}}, function(err) {
           assert.ifError(err);
           --totalDocs || complete();
         });
       }
 
       function complete() {
-        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function(err, doc) {
           db.close();
           assert.ifError(err);
           assert.equal(9, doc.get('meta.visitors'));
@@ -476,27 +476,27 @@ describe('model: findOneAndUpdate:', function () {
     });
   });
 
-  it('honors strict schemas', function (done) {
+  it('honors strict schemas', function(done) {
     var db = start();
     var S = db.model('UpdateOneStrictSchema');
     var s = new S({name: 'orange crush'});
 
-    s.save(function (err) {
+    s.save(function(err) {
       assert.ifError(err);
       var name = Date.now();
-      S.findOneAndUpdate({name: name}, {ignore: true}, {upsert: true, 'new': true}, function (err, doc) {
+      S.findOneAndUpdate({name: name}, {ignore: true}, {upsert: true, 'new': true}, function(err, doc) {
         assert.ifError(err);
         assert.ok(doc);
         assert.ok(doc._id);
         assert.equal(undefined, doc.ignore);
         assert.equal(undefined, doc._doc.ignore);
         assert.equal(name, doc.name);
-        S.findOneAndUpdate({name: 'orange crush'}, {ignore: true}, {upsert: true}, function (err, doc) {
+        S.findOneAndUpdate({name: 'orange crush'}, {ignore: true}, {upsert: true}, function(err, doc) {
           assert.ifError(err);
           assert.ok(!doc.ignore);
           assert.ok(!doc._doc.ignore);
           assert.equal('orange crush', doc.name);
-          S.findOneAndUpdate({name: 'orange crush'}, {ignore: true}, function (err, doc) {
+          S.findOneAndUpdate({name: 'orange crush'}, {ignore: true}, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.ok(!doc.ignore);
@@ -509,21 +509,21 @@ describe('model: findOneAndUpdate:', function () {
     });
   });
 
-  it('returns errors with strict:throw schemas', function (done) {
+  it('returns errors with strict:throw schemas', function(done) {
     var db = start();
     var S = db.model('UpdateOneStrictThrowSchema');
     var s = new S({name: 'orange crush'});
 
-    s.save(function (err) {
+    s.save(function(err) {
       assert.ifError(err);
 
       var name = Date.now();
-      S.findOneAndUpdate({name: name}, {ignore: true}, {upsert: true}, function (err, doc) {
+      S.findOneAndUpdate({name: name}, {ignore: true}, {upsert: true}, function(err, doc) {
         assert.ok(err);
         assert.ok(/not in schema/.test(err));
         assert.ok(!doc);
 
-        S.findOneAndUpdate({_id: s._id}, {ignore: true}, function (err, doc) {
+        S.findOneAndUpdate({_id: s._id}, {ignore: true}, function(err, doc) {
           db.close();
           assert.ok(err);
           assert.ok(/not in schema/.test(err));
@@ -535,14 +535,14 @@ describe('model: findOneAndUpdate:', function () {
   });
 });
 
-describe('model: findByIdAndUpdate:', function () {
-  it('executing with just a callback throws', function (done) {
+describe('model: findByIdAndUpdate:', function() {
+  it('executing with just a callback throws', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         err;
 
     try {
-      M.findByIdAndUpdate(function () {
+      M.findByIdAndUpdate(function() {
       });
     } catch (e) {
       err = e;
@@ -553,7 +553,7 @@ describe('model: findByIdAndUpdate:', function () {
     done();
   });
 
-  it('executes when a callback is passed', function (done) {
+  it('executes when a callback is passed', function(done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         _id = new DocumentObjectId,
@@ -572,7 +572,7 @@ describe('model: findByIdAndUpdate:', function () {
     }
   });
 
-  it('executes when a callback is passed to a succeeding function', function (done) {
+  it('executes when a callback is passed to a succeeding function', function(done) {
     var db = start(),
         M = db.model(modelname, collection + random()),
         _id = new DocumentObjectId,
@@ -591,7 +591,7 @@ describe('model: findByIdAndUpdate:', function () {
     }
   });
 
-  it('returns the original document', function (done) {
+  it('returns the original document', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         title = 'Tobi ' + random(),
@@ -611,9 +611,9 @@ describe('model: findByIdAndUpdate:', function () {
     post.owners = [id0, id1];
     post.comments = [{body: 'been there'}, {body: 'done that'}];
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
-      M.findById(post._id, function (err) {
+      M.findById(post._id, function(err) {
         assert.ifError(err);
 
         var update = {
@@ -627,7 +627,7 @@ describe('model: findByIdAndUpdate:', function () {
           'comments.1.body': 8 // $set
         };
 
-        M.findByIdAndUpdate(post.id, update, {new: false}, function (err, up) {
+        M.findByIdAndUpdate(post.id, update, {new: false}, function(err, up) {
           assert.ifError(err);
 
           assert.equal(up.title, post.title);
@@ -652,7 +652,7 @@ describe('model: findByIdAndUpdate:', function () {
     });
   });
 
-  it('options/conditions/doc are merged when no callback is passed', function (done) {
+  it('options/conditions/doc are merged when no callback is passed', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -683,7 +683,7 @@ describe('model: findByIdAndUpdate:', function () {
     db.close(done);
   });
 
-  it('supports v3 select string syntax', function (done) {
+  it('supports v3 select string syntax', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -701,7 +701,7 @@ describe('model: findByIdAndUpdate:', function () {
     db.close(done);
   });
 
-  it('supports v3 select object syntax', function (done) {
+  it('supports v3 select object syntax', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -719,7 +719,7 @@ describe('model: findByIdAndUpdate:', function () {
     db.close(done);
   });
 
-  it('supports v3 sort string syntax', function (done) {
+  it('supports v3 sort string syntax', function(done) {
     var db = start(),
         M = db.model(modelname, collection);
 
@@ -742,14 +742,14 @@ describe('model: findByIdAndUpdate:', function () {
         {title: 1, meta: {visitors: 0}}
         , {title: 2, meta: {visitors: 10}}
         , {title: 3, meta: {visitors: 5}}
-        , function (err) {
+        , function(err) {
           if (err) {
             return done(err);
           }
 
           M.findOneAndUpdate({}, {title: 'changed'})
           .sort({'meta.visitors': -1})
-          .exec(function (err, doc) {
+          .exec(function(err, doc) {
             if (err) {
               return done(err);
             }
@@ -759,7 +759,7 @@ describe('model: findByIdAndUpdate:', function () {
         });
   });
 
-  it('supports v3 sort object syntax', function (done) {
+  it('supports v3 sort object syntax', function(done) {
     var db = start(),
         M = db.model(modelname, collection),
         _id = new DocumentObjectId;
@@ -780,7 +780,7 @@ describe('model: findByIdAndUpdate:', function () {
     db.close(done);
   });
 
-  it('supports $elemMatch with $in (gh-1091 gh-1100)', function (done) {
+  it('supports $elemMatch with $in (gh-1091 gh-1100)', function(done) {
     var db = start();
 
     var postSchema = new Schema({
@@ -792,13 +792,13 @@ describe('model: findByIdAndUpdate:', function () {
     var _id1 = new mongoose.Types.ObjectId;
     var _id2 = new mongoose.Types.ObjectId;
 
-    B.create({ids: [_id1, _id2]}, function (err, doc) {
+    B.create({ids: [_id1, _id2]}, function(err, doc) {
       assert.ifError(err);
 
       B
       .findByIdAndUpdate(doc._id, {title: 'woot'}, {'new': true})
       .select({title: 1, ids: {$elemMatch: {$in: [_id2.toString()]}}})
-      .exec(function (err, found) {
+      .exec(function(err, found) {
         assert.ifError(err);
         assert.ok(found);
         assert.equal(found.id, doc.id);
@@ -810,23 +810,23 @@ describe('model: findByIdAndUpdate:', function () {
     });
   });
 
-  it('supports population (gh-1395)', function (done) {
+  it('supports population (gh-1395)', function(done) {
     var db = start();
     var M = db.model('A', {name: String});
     var N = db.model('B', {a: {type: Schema.ObjectId, ref: 'A'}, i: Number});
 
-    M.create({name: 'i am an A'}, function (err, a) {
+    M.create({name: 'i am an A'}, function(err, a) {
       if (err) {
         return done(err);
       }
-      N.create({a: a._id, i: 10}, function (err, b) {
+      N.create({a: a._id, i: 10}, function(err, b) {
         if (err) {
           return done(err);
         }
 
         N.findOneAndUpdate({_id: b._id}, {$inc: {i: 1}})
         .populate('a')
-        .exec(function (err, doc) {
+        .exec(function(err, doc) {
           if (err) {
             return done(err);
           }
@@ -838,7 +838,7 @@ describe('model: findByIdAndUpdate:', function () {
       });
     });
   });
-  it('returns null when doing an upsert & new=false gh-1533', function (done) {
+  it('returns null when doing an upsert & new=false gh-1533', function(done) {
     var db = start();
 
     var thingSchema = new Schema({
@@ -852,10 +852,10 @@ describe('model: findByIdAndUpdate:', function () {
     var Thing = db.model('Thing', thingSchema);
     var key = 'some-id';
 
-    Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, 'new': false}).exec(function (err, thing) {
+    Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, 'new': false}).exec(function(err, thing) {
       assert.ifError(err);
       assert.equal(null, thing);
-      Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, 'new': false}).exec(function (err, thing2) {
+      Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, 'new': false}).exec(function(err, thing2) {
         assert.ifError(err);
         assert.equal(key, thing2.id);
         assert.equal(false, thing2.flag);
@@ -864,7 +864,7 @@ describe('model: findByIdAndUpdate:', function () {
     });
   });
 
-  it('allows properties to be set to null gh-1643', function (done) {
+  it('allows properties to be set to null gh-1643', function(done) {
     var db = start();
 
     var thingSchema = new Schema({
@@ -873,12 +873,12 @@ describe('model: findByIdAndUpdate:', function () {
 
     var Thing = db.model('Thing', thingSchema);
 
-    Thing.create({name: ['Test']}, function (err, thing) {
+    Thing.create({name: ['Test']}, function(err, thing) {
       if (err) {
         return done(err);
       }
       Thing.findOneAndUpdate({_id: thing._id}, {name: null}, {'new': true})
-      .exec(function (err, doc) {
+      .exec(function(err, doc) {
         if (err) {
           return done(err);
         }
@@ -889,14 +889,14 @@ describe('model: findByIdAndUpdate:', function () {
     });
   });
 
-  it('honors the overwrite option (gh-1809)', function (done) {
+  it('honors the overwrite option (gh-1809)', function(done) {
     var db = start();
     var M = db.model('1809', {name: String, change: Boolean});
-    M.create({name: 'first'}, function (err, doc) {
+    M.create({name: 'first'}, function(err, doc) {
       if (err) {
         return done(err);
       }
-      M.findByIdAndUpdate(doc._id, {change: true}, {overwrite: true, 'new': true}, function (err, doc) {
+      M.findByIdAndUpdate(doc._id, {change: true}, {overwrite: true, 'new': true}, function(err, doc) {
         if (err) {
           return done(err);
         }
@@ -907,7 +907,7 @@ describe('model: findByIdAndUpdate:', function () {
     });
   });
 
-  it('can do deep equals on object id after findOneAndUpdate (gh-2070)', function (done) {
+  it('can do deep equals on object id after findOneAndUpdate (gh-2070)', function(done) {
     var db = start();
 
     var accountSchema = new Schema({
@@ -923,20 +923,20 @@ describe('model: findByIdAndUpdate:', function () {
     var a1 = new Account({name: 'parent'});
     var a2 = new Account({name: 'child'});
 
-    a1.save(function (error) {
+    a1.save(function(error) {
       assert.ifError(error);
-      a2.save(function (error, a2) {
+      a2.save(function(error, a2) {
         assert.ifError(error);
         Account.findOneAndUpdate(
             {name: 'parent'},
             {$push: {contacts: {account: a2._id, name: 'child'}}},
             {'new': true},
-            function (error, doc) {
+            function(error, doc) {
               assert.ifError(error);
               assert.ok(Utils.deepEqual(doc.contacts[0].account, a2._id));
               assert.ok(_.isEqual(doc.contacts[0].account, a2._id));
 
-              Account.findOne({name: 'parent'}, function (error, doc) {
+              Account.findOne({name: 'parent'}, function(error, doc) {
                 assert.ifError(error);
                 assert.ok(Utils.deepEqual(doc.contacts[0].account, a2._id));
                 assert.ok(_.isEqual(doc.contacts[0].account, a2._id));
@@ -947,7 +947,7 @@ describe('model: findByIdAndUpdate:', function () {
     });
   });
 
-  it('adds __v on upsert (gh-2122)', function (done) {
+  it('adds __v on upsert (gh-2122)', function(done) {
     var db = start();
 
     var accountSchema = new Schema({
@@ -960,14 +960,14 @@ describe('model: findByIdAndUpdate:', function () {
         {name: 'account'},
         {},
         {upsert: true, new: true},
-        function (error, doc) {
+        function(error, doc) {
           assert.ifError(error);
           assert.equal(0, doc.__v);
           db.close(done);
         });
   });
 
-  it('works with nested schemas and $pull+$or (gh-1932)', function (done) {
+  it('works with nested schemas and $pull+$or (gh-1932)', function(done) {
     var db = start();
 
     var TickSchema = new Schema({name: String});
@@ -975,12 +975,12 @@ describe('model: findByIdAndUpdate:', function () {
 
     var TestModel = db.model('gh-1932', TestSchema, 'gh-1932');
 
-    TestModel.create({a: 1, b: 0, ticks: [{name: 'eggs'}, {name: 'bacon'}, {name: 'coffee'}]}, function (error) {
+    TestModel.create({a: 1, b: 0, ticks: [{name: 'eggs'}, {name: 'bacon'}, {name: 'coffee'}]}, function(error) {
       assert.ifError(error);
       TestModel.findOneAndUpdate({a: 1}, {$pull: {ticks: {$or: [{name: 'eggs'}, {name: 'bacon'}]}}},
-          function (error) {
+          function(error) {
             assert.ifError(error);
-            TestModel.findOne({}, function (error, doc) {
+            TestModel.findOne({}, function(error, doc) {
               assert.ifError(error);
               assert.equal(1, doc.ticks.length);
               assert.equal('coffee', doc.ticks[0].name);
@@ -990,7 +990,7 @@ describe('model: findByIdAndUpdate:', function () {
     });
   });
 
-  it('accepts undefined', function (done) {
+  it('accepts undefined', function(done) {
     var db = start();
 
     var s = new Schema({
@@ -1002,13 +1002,13 @@ describe('model: findByIdAndUpdate:', function () {
 
     Breakfast.
     findOneAndUpdate({}, {time: undefined, base: undefined}, {}).
-    exec(function (error) {
+    exec(function(error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('cast errors for empty objects as object ids (gh-2732)', function (done) {
+  it('cast errors for empty objects as object ids (gh-2732)', function(done) {
     var db = start();
 
     var s = new Schema({
@@ -1019,13 +1019,13 @@ describe('model: findByIdAndUpdate:', function () {
 
     Breakfast.
     findOneAndUpdate({}, {base: {}}, {}).
-    exec(function (error) {
+    exec(function(error) {
       assert.ok(error);
       db.close(done);
     });
   });
 
-  it('strict mode with objects (gh-2947)', function (done) {
+  it('strict mode with objects (gh-2947)', function(done) {
     var db = start();
 
     var s = new Schema({
@@ -1038,36 +1038,36 @@ describe('model: findByIdAndUpdate:', function () {
         {'new': true, strict: true, upsert: true});
 
     q.lean();
-    q.exec(function (error, doc) {
+    q.exec(function(error, doc) {
       assert.ok(!doc.notInSchema);
       db.close(done);
     });
   });
 
-  describe('middleware', function () {
+  describe('middleware', function() {
     var db;
 
-    beforeEach(function () {
+    beforeEach(function() {
       db = start();
     });
 
-    afterEach(function (done) {
+    afterEach(function(done) {
       db.close(done);
     });
 
-    it('works', function (done) {
+    it('works', function(done) {
       var s = new Schema({
         topping: {type: String, default: 'bacon'},
         base: String
       });
 
       var preCount = 0;
-      s.pre('findOneAndUpdate', function () {
+      s.pre('findOneAndUpdate', function() {
         ++preCount;
       });
 
       var postCount = 0;
-      s.post('findOneAndUpdate', function () {
+      s.post('findOneAndUpdate', function() {
         ++postCount;
       });
 
@@ -1077,7 +1077,7 @@ describe('model: findByIdAndUpdate:', function () {
           {},
           {base: 'eggs'},
           {},
-          function (error) {
+          function(error) {
             assert.ifError(error);
             assert.equal(1, preCount);
             assert.equal(1, postCount);
@@ -1085,19 +1085,19 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('works with exec()', function (done) {
+    it('works with exec()', function(done) {
       var s = new Schema({
         topping: {type: String, default: 'bacon'},
         base: String
       });
 
       var preCount = 0;
-      s.pre('findOneAndUpdate', function () {
+      s.pre('findOneAndUpdate', function() {
         ++preCount;
       });
 
       var postCount = 0;
-      s.post('findOneAndUpdate', function () {
+      s.post('findOneAndUpdate', function() {
         ++postCount;
       });
 
@@ -1105,7 +1105,7 @@ describe('model: findByIdAndUpdate:', function () {
 
       Breakfast.
       findOneAndUpdate({}, {base: 'eggs'}, {}).
-      exec(function (error) {
+      exec(function(error) {
         assert.ifError(error);
         assert.equal(1, preCount);
         assert.equal(1, postCount);
@@ -1114,8 +1114,8 @@ describe('model: findByIdAndUpdate:', function () {
     });
   });
 
-  describe('validators (gh-860)', function () {
-    it('applies defaults on upsert', function (done) {
+  describe('validators (gh-860)', function() {
+    it('applies defaults on upsert', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1129,11 +1129,11 @@ describe('model: findByIdAndUpdate:', function () {
           {},
           {base: 'eggs'},
           updateOptions,
-          function (error, breakfast) {
+          function(error, breakfast) {
             assert.ifError(error);
             assert.equal('eggs', breakfast.base);
             assert.equal('bacon', breakfast.topping);
-            Breakfast.count({topping: 'bacon'}, function (error, count) {
+            Breakfast.count({topping: 'bacon'}, function(error, count) {
               assert.ifError(error);
               assert.equal(count, 1);
               db.close(done);
@@ -1141,7 +1141,7 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('doesnt set default on upsert if query sets it', function (done) {
+    it('doesnt set default on upsert if query sets it', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1155,7 +1155,7 @@ describe('model: findByIdAndUpdate:', function () {
           {topping: 'sausage'},
           {base: 'eggs'},
           updateOptions,
-          function (error, breakfast) {
+          function(error, breakfast) {
             assert.ifError(error);
             assert.equal('eggs', breakfast.base);
             assert.equal('sausage', breakfast.topping);
@@ -1164,7 +1164,7 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('properly sets default on upsert if query wont set it', function (done) {
+    it('properly sets default on upsert if query wont set it', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1178,11 +1178,11 @@ describe('model: findByIdAndUpdate:', function () {
           {topping: {$ne: 'sausage'}},
           {base: 'eggs'},
           updateOptions,
-          function (error, breakfast) {
+          function(error, breakfast) {
             assert.ifError(error);
             assert.equal('eggs', breakfast.base);
             assert.equal('bacon', breakfast.topping);
-            Breakfast.count({topping: 'bacon'}, function (error, count) {
+            Breakfast.count({topping: 'bacon'}, function(error, count) {
               assert.ifError(error);
               assert.equal(count, 1);
               db.close(done);
@@ -1190,19 +1190,19 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('runs validators if theyre set', function (done) {
+    it('runs validators if theyre set', function(done) {
       var db = start();
 
       var s = new Schema({
         topping: {
           type: String,
-          validate: function () {
+          validate: function() {
             return false;
           }
         },
         base: {
           type: String,
-          validate: function () {
+          validate: function() {
             return true;
           }
         }
@@ -1219,7 +1219,7 @@ describe('model: findByIdAndUpdate:', function () {
           {},
           {topping: 'bacon', base: 'eggs'},
           updateOptions,
-          function (error, breakfast) {
+          function(error, breakfast) {
             assert.ok(!!error);
             assert.ok(!breakfast);
             assert.equal(1, Object.keys(error.errors).length);
@@ -1232,13 +1232,13 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('validators handle $unset and $setOnInsert', function (done) {
+    it('validators handle $unset and $setOnInsert', function(done) {
       var db = start();
 
       var s = new Schema({
         steak: {type: String, required: true},
         eggs: {
-          type: String, validate: function () {
+          type: String, validate: function() {
             return false;
           }
         }
@@ -1250,7 +1250,7 @@ describe('model: findByIdAndUpdate:', function () {
           {},
           {$unset: {steak: ''}, $setOnInsert: {eggs: 'softboiled'}},
           updateOptions,
-          function (error, breakfast) {
+          function(error, breakfast) {
             assert.ok(!!error);
             assert.ok(!breakfast);
             assert.equal(2, Object.keys(error.errors).length);
@@ -1263,7 +1263,7 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('min/max, enum, and regex built-in validators work', function (done) {
+    it('min/max, enum, and regex built-in validators work', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1278,7 +1278,7 @@ describe('model: findByIdAndUpdate:', function () {
           {},
           {$set: {steak: 'ribeye', eggs: 3, bacon: '3 strips'}},
           updateOptions,
-          function (error) {
+          function(error) {
             assert.ok(!!error);
             assert.equal(1, Object.keys(error.errors).length);
             assert.equal('eggs', Object.keys(error.errors)[0]);
@@ -1288,7 +1288,7 @@ describe('model: findByIdAndUpdate:', function () {
                 {},
                 {$set: {steak: 'tofu', eggs: 5, bacon: '3 strips'}},
                 updateOptions,
-                function (error) {
+                function(error) {
                   assert.ok(!!error);
                   assert.equal(1, Object.keys(error.errors).length);
                   assert.equal('steak', Object.keys(error.errors)[0]);
@@ -1298,7 +1298,7 @@ describe('model: findByIdAndUpdate:', function () {
                       {},
                       {$set: {steak: 'sirloin', eggs: 6, bacon: 'none'}},
                       updateOptions,
-                      function (error) {
+                      function(error) {
                         assert.ok(!!error);
                         assert.equal(1, Object.keys(error.errors).length);
                         assert.equal('bacon', Object.keys(error.errors)[0]);
@@ -1311,7 +1311,7 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('multiple validation errors', function (done) {
+    it('multiple validation errors', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1326,7 +1326,7 @@ describe('model: findByIdAndUpdate:', function () {
           {},
           {$set: {steak: 'tofu', eggs: 2, bacon: '3 strips'}},
           updateOptions,
-          function (error, breakfast) {
+          function(error, breakfast) {
             assert.ok(!!error);
             assert.equal(2, Object.keys(error.errors).length);
             assert.ok(Object.keys(error.errors).indexOf('steak') !== -1);
@@ -1337,7 +1337,7 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('validators ignore $inc', function (done) {
+    it('validators ignore $inc', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1351,7 +1351,7 @@ describe('model: findByIdAndUpdate:', function () {
           {},
           {$inc: {eggs: 1}},
           updateOptions,
-          function (error, breakfast) {
+          function(error, breakfast) {
             assert.ifError(error);
             assert.ok(!!breakfast);
             assert.equal(1, breakfast.eggs);
@@ -1359,7 +1359,7 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('should work with arrays (gh-3035)', function (done) {
+    it('should work with arrays (gh-3035)', function(done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
@@ -1373,17 +1373,17 @@ describe('model: findByIdAndUpdate:', function () {
       });
 
       var TestModel = db.model('gh3035', testSchema);
-      TestModel.create({id: '1'}, function (error) {
+      TestModel.create({id: '1'}, function(error) {
         assert.ifError(error);
         TestModel.findOneAndUpdate({id: '1'}, {$set: {name: 'Joe'}}, {upsert: true, setDefaultsOnInsert: true},
-            function (error) {
+            function(error) {
               assert.ifError(error);
               db.close(done);
             });
       });
     });
 
-    it('should allow null values in query (gh-3135)', function (done) {
+    it('should allow null values in query (gh-3135)', function(done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
@@ -1393,17 +1393,17 @@ describe('model: findByIdAndUpdate:', function () {
       });
 
       var TestModel = db.model('gh3135', testSchema);
-      TestModel.create({blob: null, status: 'active'}, function (error) {
+      TestModel.create({blob: null, status: 'active'}, function(error) {
         assert.ifError(error);
         TestModel.findOneAndUpdate({id: '1', blob: null}, {$set: {status: 'inactive'}}, {upsert: true, setDefaultsOnInsert: true},
-            function (error) {
+            function(error) {
               assert.ifError(error);
               db.close(done);
             });
       });
     });
 
-    it('should work with array documents (gh-3034)', function (done) {
+    it('should work with array documents (gh-3034)', function(done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
@@ -1419,17 +1419,17 @@ describe('model: findByIdAndUpdate:', function () {
       });
 
       var TestModel = db.model('gh3034', testSchema);
-      TestModel.create({id: '1'}, function (error) {
+      TestModel.create({id: '1'}, function(error) {
         assert.ifError(error);
         TestModel.findOneAndUpdate({id: '1'}, {$set: {name: 'Joe'}}, {upsert: true, setDefaultsOnInsert: true},
-            function (error) {
+            function(error) {
               assert.ifError(error);
               db.close(done);
             });
       });
     });
 
-    it('handles setting array (gh-3107)', function (done) {
+    it('handles setting array (gh-3107)', function(done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
@@ -1443,7 +1443,7 @@ describe('model: findByIdAndUpdate:', function () {
       var TestModel = db.model('gh3107', testSchema);
       TestModel
       .findOneAndUpdate({id: '1'}, {$setOnInsert: {a: [{foo: 'bar'}], b: [2]}}, {upsert: true, 'new': true, setDefaultsOnInsert: true},
-          function (error, doc) {
+          function(error, doc) {
             assert.ifError(error);
             assert.equal(doc.a.length, 1);
             assert.equal(doc.a[0].foo, 'bar');
@@ -1453,7 +1453,7 @@ describe('model: findByIdAndUpdate:', function () {
           });
     });
 
-    it('passes raw result as 3rd param (gh-3173)', function (done) {
+    it('passes raw result as 3rd param (gh-3173)', function(done) {
       var db = start();
 
       var testSchema = new mongoose.Schema({
@@ -1463,7 +1463,7 @@ describe('model: findByIdAndUpdate:', function () {
       var TestModel = db.model('gh3173', testSchema);
 
       TestModel.findOneAndUpdate({}, {$set: {test: 'abc'}}, {upsert: true, 'new': true, passRawResult: true}).
-      exec(function (error, doc, res) {
+      exec(function(error, doc, res) {
         assert.ifError(error);
         assert.ok(res);
         assert.ok(res.ok);
@@ -1471,7 +1471,7 @@ describe('model: findByIdAndUpdate:', function () {
       });
     });
 
-    it('handles nested cast errors (gh-3468)', function (done) {
+    it('handles nested cast errors (gh-3468)', function(done) {
       var db = start();
       var recordSchema = new mongoose.Schema({
         kind: String,
@@ -1490,13 +1490,13 @@ describe('model: findByIdAndUpdate:', function () {
       Shift.create({
         userId: 'tom',
         records: []
-      }, function (error) {
+      }, function(error) {
         assert.ifError(error);
         Shift.findOneAndUpdate({userId: 'tom'}, {
           records: [{kind: 'kind1', amount: NaN}]
         }, {
           'new': true
-        }, function (error) {
+        }, function(error) {
           assert.ok(error);
           assert.ok(error instanceof CastError);
           db.close(done);
@@ -1504,7 +1504,7 @@ describe('model: findByIdAndUpdate:', function () {
       });
     });
 
-    it('cast errors with nested schemas (gh-3580)', function (done) {
+    it('cast errors with nested schemas (gh-3580)', function(done) {
       var db = start();
 
       var nested = new Schema({num: Number});
@@ -1513,13 +1513,13 @@ describe('model: findByIdAndUpdate:', function () {
       var MyModel = db.model('gh3580', s);
 
       var update = {nested: {num: 'Not a Number'}};
-      MyModel.findOneAndUpdate({}, update, function (error) {
+      MyModel.findOneAndUpdate({}, update, function(error) {
         assert.ok(error);
         db.close(done);
       });
     });
 
-    it('pull with nested schemas (gh-3616)', function (done) {
+    it('pull with nested schemas (gh-3616)', function(done) {
       var db = start();
 
       var nested = new Schema({arr: [{num: Number}]});
@@ -1527,11 +1527,11 @@ describe('model: findByIdAndUpdate:', function () {
 
       var MyModel = db.model('gh3616', s);
 
-      MyModel.create({nested: {arr: [{num: 5}]}}, function (error) {
+      MyModel.create({nested: {arr: [{num: 5}]}}, function(error) {
         assert.ifError(error);
         var update = {$pull: {'nested.arr': {num: 5}}};
         var options = {'new': true};
-        MyModel.findOneAndUpdate({}, update, options, function (error, doc) {
+        MyModel.findOneAndUpdate({}, update, options, function(error, doc) {
           assert.ifError(error);
           assert.equal(doc.nested.arr.length, 0);
           db.close(done);
diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js
index 0c286b58f16..fb083a621af 100644
--- a/test/model.geonear.test.js
+++ b/test/model.geonear.test.js
@@ -31,24 +31,24 @@ function metersToRadians(m) {
   return m / (6371 * 1000);
 }
 
-describe('model', function () {
+describe('model', function() {
   var mongo24_or_greater = false;
-  before(function (done) {
-    start.mongodVersion(function (err, version) {
+  before(function(done) {
+    start.mongodVersion(function(err, version) {
       if (err) throw err;
       mongo24_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 4);
       if (!mongo24_or_greater) console.log('not testing mongodb 2.4 features');
       done();
     });
   });
-  describe('geoNear', function () {
-    it('works with legacy coordinate points', function (done) {
+  describe('geoNear', function() {
+    it('works with legacy coordinate points', function(done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoNear instanceof Function);
 
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
 
         var geos = [];
@@ -71,7 +71,7 @@ describe('model', function () {
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function (err) {
+          geos[i].save(function(err) {
             assert.ifError(err);
             --count || next();
           });
@@ -80,7 +80,7 @@ describe('model', function () {
         function next() {
           // using legacy coordinates -- maxDistance units in radians
           var options = {spherical: true, maxDistance: metersToRadians(300)};
-          Geo.geoNear(testLocations.PORT_AUTHORITY_STATION, options).then(function (results) {
+          Geo.geoNear(testLocations.PORT_AUTHORITY_STATION, options).then(function(results) {
             assert.equal(1, results.length);
 
             assert.equal(results[0].obj.type, 'Point');
@@ -95,13 +95,13 @@ describe('model', function () {
       });
     });
 
-    it('works with GeoJSON coordinate points', function (done) {
+    it('works with GeoJSON coordinate points', function(done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoNear instanceof Function);
 
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
 
         var geos = [];
@@ -124,14 +124,14 @@ describe('model', function () {
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function () {
+          geos[i].save(function() {
             --count || next();
           });
         }
 
         function next() {
           var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION};
-          Geo.geoNear(pnt, {spherical: true, maxDistance: 300}, function (err, results) {
+          Geo.geoNear(pnt, {spherical: true, maxDistance: 300}, function(err, results) {
             assert.ifError(err);
 
             assert.equal(1, results.length);
@@ -148,13 +148,13 @@ describe('model', function () {
       });
     });
 
-    it('works with lean', function (done) {
+    it('works with lean', function(done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoNear instanceof Function);
 
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
 
         var geos = [];
@@ -177,14 +177,14 @@ describe('model', function () {
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function () {
+          geos[i].save(function() {
             --count || next();
           });
         }
 
         function next() {
           var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION};
-          Geo.geoNear(pnt, {spherical: true, maxDistance: 300, lean: true}, function (err, results) {
+          Geo.geoNear(pnt, {spherical: true, maxDistance: 300, lean: true}, function(err, results) {
             assert.ifError(err);
 
             assert.equal(1, results.length);
@@ -201,30 +201,30 @@ describe('model', function () {
       });
     });
 
-    it('throws the correct error messages', function (done) {
+    it('throws the correct error messages', function(done) {
       if (!mongo24_or_greater) return done();
 
       var db = start();
       var Geo = getModel(db);
 
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
 
         var g = new Geo({coordinates: [10, 10], type: 'place'});
-        g.save(function () {
-          Geo.geoNear('1,2', {}, function (e) {
+        g.save(function() {
+          Geo.geoNear('1,2', {}, function(e) {
             assert.ok(e);
             assert.equal(e.message, 'Must pass either a legacy coordinate array or GeoJSON Point to geoNear');
 
-            Geo.geoNear([1], {}, function (e) {
+            Geo.geoNear([1], {}, function(e) {
               assert.ok(e);
               assert.equal(e.message, 'If using legacy coordinates, must be an array of size 2 for geoNear');
 
-              Geo.geoNear({type: 'Square'}, {}, function (e) {
+              Geo.geoNear({type: 'Square'}, {}, function(e) {
                 assert.ok(e);
                 assert.equal(e.message, 'Must pass either a legacy coordinate array or GeoJSON Point to geoNear');
 
-                Geo.geoNear({type: 'Point', coordinates: '1,2'}, {}, function (e) {
+                Geo.geoNear({type: 'Point', coordinates: '1,2'}, {}, function(e) {
                   assert.ok(e);
                   assert.equal(e.message, 'Must pass either a legacy coordinate array or GeoJSON Point to geoNear');
 
@@ -236,32 +236,32 @@ describe('model', function () {
         });
       });
     });
-    it('returns a promise (gh-1614)', function (done) {
+    it('returns a promise (gh-1614)', function(done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
 
       var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION};
       // using GeoJSON point
-      var prom = Geo.geoNear(pnt, {spherical: true, maxDistance: 300}, function () {});
+      var prom = Geo.geoNear(pnt, {spherical: true, maxDistance: 300}, function() {});
       assert.ok(prom instanceof mongoose.Promise);
       db.close();
       done();
     });
 
-    it('allows not passing a callback (gh-1614)', function (done) {
+    it('allows not passing a callback (gh-1614)', function(done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
         var g = new Geo({coordinates: testLocations.MONGODB_NYC_OFFICE, type: 'Point'});
-        g.save(function (err) {
+        g.save(function(err) {
           assert.ifError(err);
 
           var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION};
           var promise;
-          assert.doesNotThrow(function () {
+          assert.doesNotThrow(function() {
             promise = Geo.geoNear(pnt, {spherical: true, maxDistance: 300});
           });
 
@@ -280,19 +280,19 @@ describe('model', function () {
         });
       });
     });
-    it('promise fulfill even when no results returned', function (done) {
+    it('promise fulfill even when no results returned', function(done) {
       if (!mongo24_or_greater) return done();
       var db = start();
       var Geo = getModel(db);
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
         var g = new Geo({coordinates: [1, 1], type: 'Point'});
-        g.save(function (err) {
+        g.save(function(err) {
           assert.ifError(err);
 
           var pnt = {type: 'Point', coordinates: [90, 45]};
           var promise;
-          assert.doesNotThrow(function () {
+          assert.doesNotThrow(function() {
             promise = Geo.geoNear(pnt, {spherical: true, maxDistance: 1000});
           });
 
diff --git a/test/model.geosearch.test.js b/test/model.geosearch.test.js
index 002e998e50b..94c011d7344 100644
--- a/test/model.geosearch.test.js
+++ b/test/model.geosearch.test.js
@@ -20,14 +20,14 @@ function getModel(db) {
   return db.model('GeoSearch', schema, 'geosearch-' + random());
 }
 
-describe('model', function () {
-  describe('geoSearch', function () {
-    it('works', function (done) {
+describe('model', function() {
+  describe('geoSearch', function() {
+    it('works', function(done) {
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoSearch instanceof Function);
 
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
 
         var geos = [];
@@ -38,14 +38,14 @@ describe('model', function () {
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function (err) {
+          geos[i].save(function(err) {
             assert.ifError(err);
             --count || next();
           });
         }
 
         function next() {
-          Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5}, function (err, results) {
+          Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5}, function(err, results) {
             assert.ifError(err);
             assert.equal(1, results.length);
 
@@ -56,7 +56,7 @@ describe('model', function () {
             assert.equal(results[0].id, geos[0].id);
             assert.ok(results[0] instanceof Geo);
 
-            Geo.geoSearch({type: 'place'}, {near: [40, 40], maxDistance: 5}, function (err, results) {
+            Geo.geoSearch({type: 'place'}, {near: [40, 40], maxDistance: 5}, function(err, results) {
               assert.ifError(err);
               assert.equal(0, results.length);
               db.close(done);
@@ -65,12 +65,12 @@ describe('model', function () {
         }
       });
     });
-    it('works with lean', function (done) {
+    it('works with lean', function(done) {
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoSearch instanceof Function);
 
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
 
         var geos = [];
@@ -81,14 +81,14 @@ describe('model', function () {
         var count = geos.length;
 
         for (var i = 0; i < geos.length; i++) {
-          geos[i].save(function (err) {
+          geos[i].save(function(err) {
             assert.ifError(err);
             --count || next();
           });
         }
 
         function next() {
-          Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5, lean: true}, function (err, results) {
+          Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5, lean: true}, function(err, results) {
             assert.ifError(err);
             assert.equal(1, results.length);
 
@@ -104,29 +104,29 @@ describe('model', function () {
         }
       });
     });
-    it('throws the correct error messages', function (done) {
+    it('throws the correct error messages', function(done) {
       var db = start();
       var Geo = getModel(db);
       assert.ok(Geo.geoSearch instanceof Function);
 
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
 
         var g = new Geo({pos: [10, 10], type: 'place'});
-        g.save(function () {
-          Geo.geoSearch([], {}, function (e) {
+        g.save(function() {
+          Geo.geoSearch([], {}, function(e) {
             assert.ok(e);
             assert.equal(e.message, 'Must pass conditions to geoSearch');
 
-            Geo.geoSearch({type: 'test'}, {}, function (e) {
+            Geo.geoSearch({type: 'test'}, {}, function(e) {
               assert.ok(e);
               assert.equal(e.message, 'Must specify the near option in geoSearch');
 
-              Geo.geoSearch({type: 'test'}, {near: 'hello'}, function (e) {
+              Geo.geoSearch({type: 'test'}, {near: 'hello'}, function(e) {
                 assert.ok(e);
                 assert.equal(e.message, 'near option must be an array [x, y]');
 
-                Geo.geoSearch({type: 'test'}, {near: [1, 2]}, function (err) {
+                Geo.geoSearch({type: 'test'}, {near: [1, 2]}, function(err) {
                   assert.ok(err);
                   assert.ok(/maxDistance needs a number/.test(err));
                   db.close(done);
@@ -137,27 +137,27 @@ describe('model', function () {
         });
       });
     });
-    it('returns a promise (gh-1614)', function (done) {
+    it('returns a promise (gh-1614)', function(done) {
       var db = start();
       var Geo = getModel(db);
 
-      var prom = Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5}, function () {});
+      var prom = Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5}, function() {});
       assert.ok(prom instanceof mongoose.Promise);
       db.close();
       done();
     });
 
-    it('allows not passing a callback (gh-1614)', function (done) {
+    it('allows not passing a callback (gh-1614)', function(done) {
       var db = start();
       var Geo = getModel(db);
-      Geo.on('index', function (err) {
+      Geo.on('index', function(err) {
         assert.ifError(err);
         var g = new Geo({pos: [10, 10], type: 'place'});
-        g.save(function (err) {
+        g.save(function(err) {
           assert.ifError(err);
 
           var promise;
-          assert.doesNotThrow(function () {
+          assert.doesNotThrow(function() {
             promise = Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5});
           });
           function validate(ret, stat) {
diff --git a/test/model.hydrate.test.js b/test/model.hydrate.test.js
index acedf4f6795..88b8fd442a7 100644
--- a/test/model.hydrate.test.js
+++ b/test/model.hydrate.test.js
@@ -25,8 +25,8 @@ var schemaC = new Schema({
 }, {discriminatorKey: 'type'});
 
 
-describe('model', function () {
-  describe('hydrate()', function () {
+describe('model', function() {
+  describe('hydrate()', function() {
     var db;
     var B;
     var Breakfast;
@@ -35,18 +35,18 @@ describe('model', function () {
       food: {type: String, enum: ['bacon', 'eggs']}
     });
 
-    before(function () {
+    before(function() {
       db = start();
       B = db.model('model-create', schemaB, 'gh-2637-1');
       B.discriminator('C', schemaC);
       Breakfast = db.model('gh-2637-2', breakfastSchema, 'gh-2637-2');
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('hydrates documents with no modified paths', function (done) {
+    it('hydrates documents with no modified paths', function(done) {
       var hydrated = B.hydrate({_id: '541085faedb2f28965d0e8e7', title: 'chair'});
 
       assert.ok(hydrated.get('_id') instanceof DocumentObjectId);
@@ -59,13 +59,13 @@ describe('model', function () {
       done();
     });
 
-    it('runs validators', function (done) {
+    it('runs validators', function(done) {
       var hydrated = Breakfast.hydrate({
         _id: '000000000000000000000001',
         food: 'waffles'
       });
 
-      hydrated.validate(function (err) {
+      hydrated.validate(function(err) {
         assert.ok(err);
         assert.ok(err.errors.food);
         assert.deepEqual(['food'], Object.keys(err.errors));
@@ -73,7 +73,7 @@ describe('model', function () {
       });
     });
 
-    it('works correctly with model discriminators', function (done) {
+    it('works correctly with model discriminators', function(done) {
       var hydrated = B.hydrate({_id: '541085faedb2f28965d0e8e8', title: 'chair', type: 'C'});
 
       assert.equal(hydrated.test, 'test');
diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js
index 5956f20f369..8bc44cb4707 100644
--- a/test/model.indexes.test.js
+++ b/test/model.indexes.test.js
@@ -9,9 +9,9 @@ var start = require('./common'),
     Schema = mongoose.Schema,
     ObjectId = Schema.Types.ObjectId;
 
-describe('model', function () {
-  describe('indexes', function () {
-    it('are created when model is compiled', function (done) {
+describe('model', function() {
+  describe('indexes', function() {
+    it('are created when model is compiled', function(done) {
       var Indexed = new Schema({
         name: {type: String, index: true},
         last: String,
@@ -26,11 +26,11 @@ describe('model', function () {
           IndexedModel = db.model('IndexedModel', Indexed, 'indexedmodel' + random()),
           assertions = 0;
 
-      IndexedModel.on('index', function () {
-        IndexedModel.collection.getIndexes({full: true}, function (err, indexes) {
+      IndexedModel.on('index', function() {
+        IndexedModel.collection.getIndexes({full: true}, function(err, indexes) {
           assert.ifError(err);
 
-          indexes.forEach(function (index) {
+          indexes.forEach(function(index) {
             switch (index.name) {
               case '_id_':
               case 'name_1':
@@ -50,7 +50,7 @@ describe('model', function () {
       });
     });
 
-    it('of embedded documents', function (done) {
+    it('of embedded documents', function(done) {
       var BlogPosts = new Schema({
         _id: {type: ObjectId, index: true},
         title: {type: String, index: true},
@@ -66,12 +66,12 @@ describe('model', function () {
           UserModel = db.model('DeepIndexedModel', User, 'deepindexedmodel' + random()),
           assertions = 0;
 
-      UserModel.on('index', function () {
-        UserModel.collection.getIndexes(function (err, indexes) {
+      UserModel.on('index', function() {
+        UserModel.collection.getIndexes(function(err, indexes) {
           assert.ifError(err);
 
           for (var i in indexes) {
-            indexes[i].forEach(function (index) {
+            indexes[i].forEach(function(index) {
               if (index[0] === 'name') {
                 assertions++;
               }
@@ -90,7 +90,7 @@ describe('model', function () {
       });
     });
 
-    it('of multiple embedded documents with same schema', function (done) {
+    it('of multiple embedded documents with same schema', function(done) {
       var BlogPosts = new Schema({
         _id: {type: ObjectId, index: true},
         title: {type: String, index: true},
@@ -107,12 +107,12 @@ describe('model', function () {
       var UserModel = db.model('DeepIndexedModel', User, 'gh-2322');
       var assertions = 0;
 
-      UserModel.on('index', function () {
-        UserModel.collection.getIndexes(function (err, indexes) {
+      UserModel.on('index', function() {
+        UserModel.collection.getIndexes(function(err, indexes) {
           assert.ifError(err);
 
           for (var i in indexes) {
-            indexes[i].forEach(function (index) {
+            indexes[i].forEach(function(index) {
               if (index[0] === 'name') {
                 ++assertions;
               }
@@ -137,7 +137,7 @@ describe('model', function () {
       });
     });
 
-    it('compound: on embedded docs', function (done) {
+    it('compound: on embedded docs', function(done) {
       var BlogPosts = new Schema({
         title: String,
         desc: String
@@ -154,8 +154,8 @@ describe('model', function () {
           UserModel = db.model('DeepCompoundIndexModel', User, 'deepcompoundindexmodel' + random()),
           found = 0;
 
-      UserModel.on('index', function () {
-        UserModel.collection.getIndexes(function (err, indexes) {
+      UserModel.on('index', function() {
+        UserModel.collection.getIndexes(function(err, indexes) {
           assert.ifError(err);
 
           for (var index in indexes) {
@@ -174,18 +174,18 @@ describe('model', function () {
       });
     });
 
-    it('error should emit on the model', function (done) {
+    it('error should emit on the model', function(done) {
       var db = start(),
           schema = new Schema({name: {type: String}}),
           Test = db.model('IndexError', schema, 'x' + random());
 
-      Test.on('index', function (err) {
+      Test.on('index', function(err) {
         db.close();
         assert.ok(/E11000 duplicate key error/.test(err.message), err);
         done();
       });
 
-      Test.create({name: 'hi'}, {name: 'hi'}, function (err) {
+      Test.create({name: 'hi'}, {name: 'hi'}, function(err) {
         assert.strictEqual(err, null);
         Test.schema.index({name: 1}, {unique: true});
         Test.schema.index({other: 1});
@@ -193,23 +193,23 @@ describe('model', function () {
       });
     });
 
-    describe('auto creation', function () {
-      it('can be disabled', function (done) {
+    describe('auto creation', function() {
+      it('can be disabled', function(done) {
         var db = start();
         var schema = new Schema({name: {type: String, index: true}});
         schema.set('autoIndex', false);
 
         var Test = db.model('AutoIndexing', schema, 'autoindexing-disable');
-        Test.on('index', function () {
+        Test.on('index', function() {
           assert.ok(false, 'Model.ensureIndexes() was called');
         });
 
         // Create a doc because mongodb 3.0 getIndexes errors if db doesn't
         // exist
-        Test.create({name: 'Bacon'}, function (err) {
+        Test.create({name: 'Bacon'}, function(err) {
           assert.ifError(err);
-          setTimeout(function () {
-            Test.collection.getIndexes(function (err, indexes) {
+          setTimeout(function() {
+            Test.collection.getIndexes(function(err, indexes) {
               assert.ifError(err);
               // Only default _id index should exist
               assert.deepEqual(['_id_'], Object.keys(indexes));
@@ -219,15 +219,15 @@ describe('model', function () {
         });
       });
 
-      describe('global autoIndexes (gh-1875)', function () {
-        it('will create indexes as a default', function (done) {
+      describe('global autoIndexes (gh-1875)', function() {
+        it('will create indexes as a default', function(done) {
           var db = start();
           var schema = new Schema({name: {type: String, index: true}});
           var Test = db.model('GlobalAutoIndex', schema, 'gh-1875-1');
-          Test.on('index', function (error) {
+          Test.on('index', function(error) {
             assert.ifError(error);
             assert.ok(true, 'Model.ensureIndexes() was called');
-            Test.collection.getIndexes(function (err, indexes) {
+            Test.collection.getIndexes(function(err, indexes) {
               assert.ifError(err);
               assert.equal(2, Object.keys(indexes).length);
               db.close(done);
@@ -235,18 +235,18 @@ describe('model', function () {
           });
         });
 
-        it('will not create indexes if the global auto index is false and schema option isnt set (gh-1875)', function (done) {
+        it('will not create indexes if the global auto index is false and schema option isnt set (gh-1875)', function(done) {
           var db = start({config: {autoIndex: false}});
           var schema = new Schema({name: {type: String, index: true}});
           var Test = db.model('GlobalAutoIndex', schema, 'x' + random());
-          Test.on('index', function () {
+          Test.on('index', function() {
             assert.ok(false, 'Model.ensureIndexes() was called');
           });
 
-          Test.create({name: 'Bacon'}, function (err) {
+          Test.create({name: 'Bacon'}, function(err) {
             assert.ifError(err);
-            setTimeout(function () {
-              Test.collection.getIndexes(function (err, indexes) {
+            setTimeout(function() {
+              Test.collection.getIndexes(function(err, indexes) {
                 assert.ifError(err);
                 assert.deepEqual(['_id_'], Object.keys(indexes));
                 db.close(done);
@@ -257,7 +257,7 @@ describe('model', function () {
       });
     });
 
-    it('do not trigger "MongoError: cannot add index with a background operation in progress" (gh-1365) LONG', function (done) {
+    it('do not trigger "MongoError: cannot add index with a background operation in progress" (gh-1365) LONG', function(done) {
       this.timeout(45000);
 
       var db = start({uri: 'mongodb://localhost/mongoose_test_indexing'});
@@ -270,23 +270,23 @@ describe('model', function () {
       schema.index({name: 1, furryness: 1});
 
       var K = db.model('Kitten', schema);
-      K.on('index', function (err) {
+      K.on('index', function(err) {
         assert.ifError(err);
         db.close(done);
       });
 
       var neededKittens = 30000;
 
-      db.on('open', function () {
-        K.count({}, function (err, n) {
+      db.on('open', function() {
+        K.count({}, function(err, n) {
           assert.ifError(err);
           if (n >= neededKittens) {
             return index();
           }
           var pending = neededKittens - n;
           for (var i = n; i < neededKittens; ++i) {
-            (function (i) {
-              K.create({name: 'kitten' + i, furryness: i}, function (err) {
+            (function(i) {
+              K.create({name: 'kitten' + i, furryness: i}, function(err) {
                 assert.ifError(err);
                 if (--pending) {
                   return;
@@ -298,7 +298,7 @@ describe('model', function () {
         });
 
         function index() {
-          K.collection.dropAllIndexes(function (err) {
+          K.collection.dropAllIndexes(function(err) {
             assert.ifError(err);
             K.ensureIndexes();
           });
@@ -307,15 +307,15 @@ describe('model', function () {
     });
 
 
-    describe('model.ensureIndexes()', function () {
-      it('is a function', function (done) {
+    describe('model.ensureIndexes()', function() {
+      it('is a function', function(done) {
         var schema = mongoose.Schema({x: 'string'});
         var Test = mongoose.createConnection().model('ensureIndexes-' + random, schema);
         assert.equal('function', typeof Test.ensureIndexes);
         done();
       });
 
-      it('returns a Promise', function (done) {
+      it('returns a Promise', function(done) {
         var schema = mongoose.Schema({x: 'string'});
         var Test = mongoose.createConnection().model('ensureIndexes-' + random, schema);
         var p = Test.ensureIndexes();
@@ -323,7 +323,7 @@ describe('model', function () {
         done();
       });
 
-      it('creates indexes', function (done) {
+      it('creates indexes', function(done) {
         var db = start();
         var schema = new Schema({name: {type: String}}),
             Test = db.model('ManualIndexing', schema, 'x' + random());
@@ -331,11 +331,11 @@ describe('model', function () {
         Test.schema.index({name: 1}, {sparse: true});
 
         var called = false;
-        Test.on('index', function () {
+        Test.on('index', function() {
           called = true;
         });
 
-        Test.ensureIndexes(function (err) {
+        Test.ensureIndexes(function(err) {
           assert.ifError(err);
           assert.ok(called);
           db.close(done);
diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 6ff7acf0a10..f7bf770c94d 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -43,8 +43,8 @@ var BlogPost = new Schema({
 var collection = 'mapreduce_' + random();
 mongoose.model('MapReduce', BlogPost);
 
-describe('model: mapreduce:', function () {
-  it('works', function (done) {
+describe('model: mapreduce:', function() {
+  it('works', function(done) {
     var db = start(),
         MR = db.model('MapReduce', collection);
 
@@ -57,25 +57,25 @@ describe('model: mapreduce:', function () {
       docs.push({author: authors[i % authors.length], owners: [id], published: true});
     }
 
-    MR.create(docs, function (err, insertedDocs) {
+    MR.create(docs, function(err, insertedDocs) {
       assert.ifError(err);
 
       magicID = insertedDocs[1]._id;
 
       var o = {
-        map: function () {
+        map: function() {
           emit(this.author, 1);
         },
-        reduce: function (k, vals) {
+        reduce: function(k, vals) {
           return vals.length;
         }
       };
 
-      MR.mapReduce(o, function (err, ret, stats) {
+      MR.mapReduce(o, function(err, ret, stats) {
         assert.ifError(err);
         assert.ok(Array.isArray(ret));
         assert.ok(stats);
-        ret.forEach(function (res) {
+        ret.forEach(function(res) {
           if (res._id === 'aaron') {
             assert.equal(3, res.value);
           }
@@ -91,16 +91,16 @@ describe('model: mapreduce:', function () {
         });
 
         var o = {
-          map: function () {
+          map: function() {
             emit(this.author, 1);
           },
-          reduce: function (k, vals) {
+          reduce: function(k, vals) {
             return vals.length;
           },
           query: {author: 'aaron', published: 1, owners: id}
         };
 
-        MR.mapReduce(o, function (err, ret, stats) {
+        MR.mapReduce(o, function(err, ret, stats) {
           assert.ifError(err);
 
           assert.ok(Array.isArray(ret));
@@ -115,17 +115,17 @@ describe('model: mapreduce:', function () {
 
       function modeling() {
         var o = {
-          map: function () {
+          map: function() {
             emit(this.author, {own: magicID});
           },
           scope: {magicID: magicID},
-          reduce: function (k, vals) {
+          reduce: function(k, vals) {
             return {own: vals[0].own, count: vals.length};
           },
           out: {replace: '_mapreduce_test_' + random()}
         };
 
-        MR.mapReduce(o, function (err, ret) {
+        MR.mapReduce(o, function(err, ret) {
           assert.ifError(err);
 
           // ret is a model
@@ -134,7 +134,7 @@ describe('model: mapreduce:', function () {
           assert.equal('function', typeof ret.mapReduce);
 
           // queries work
-          ret.where('value.count').gt(1).sort({_id: 1}).exec(function (err, docs) {
+          ret.where('value.count').gt(1).sort({_id: 1}).exec(function(err, docs) {
             assert.ifError(err);
             assert.equal('aaron', docs[0]._id);
             assert.equal('brian', docs[1]._id);
@@ -142,7 +142,7 @@ describe('model: mapreduce:', function () {
             assert.equal('nathan', docs[3]._id);
 
             // update casting works
-            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {'new': true}, function (err, doc) {
+            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {'new': true}, function(err, doc) {
               assert.ifError(err);
               assert.ok(doc);
               assert.equal('aaron', doc._id);
@@ -152,7 +152,7 @@ describe('model: mapreduce:', function () {
               ret
               .findOne({_id: 'aaron'})
               .populate({path: 'value.own', model: 'MapReduce'})
-              .exec(function (err, doc) {
+              .exec(function(err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal('guillermo', doc.value.own.author);
@@ -165,54 +165,54 @@ describe('model: mapreduce:', function () {
     });
   });
 
-  it('withholds stats with false verbosity', function (done) {
+  it('withholds stats with false verbosity', function(done) {
     var db = start(),
         MR = db.model('MapReduce', collection);
 
     var o = {
-      map: function () {
+      map: function() {
       },
-      reduce: function () {
+      reduce: function() {
         return 'test';
       },
       verbose: false
     };
 
-    MR.mapReduce(o, function (err, results, stats) {
+    MR.mapReduce(o, function(err, results, stats) {
       assert.equal('undefined', typeof stats);
       db.close(done);
     });
   });
 
-  describe('promises (gh-1628)', function () {
-    it('are returned', function (done) {
+  describe('promises (gh-1628)', function() {
+    it('are returned', function(done) {
       var db = start(),
           MR = db.model('MapReduce', collection);
 
       var o = {
-        map: function () {
+        map: function() {
         },
-        reduce: function () {
+        reduce: function() {
           return 'test';
         }
       };
 
-      var promise = MR.mapReduce(o, function () {
+      var promise = MR.mapReduce(o, function() {
       });
       assert.ok(promise instanceof mongoose.Promise);
 
       db.close(done);
     });
 
-    it('allow not passing a callback', function (done) {
+    it('allow not passing a callback', function(done) {
       var db = start(),
           MR = db.model('MapReduce', collection);
 
       var o = {
-        map: function () {
+        map: function() {
           emit(this.author, 1);
         },
-        reduce: function (k, vals) {
+        reduce: function(k, vals) {
           return vals.length;
         },
         query: {author: 'aaron', published: 1}
@@ -232,7 +232,7 @@ describe('model: mapreduce:', function () {
 
       var promise;
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         promise = MR.mapReduce(o);
       });
 
@@ -240,7 +240,7 @@ describe('model: mapreduce:', function () {
     });
   });
 
-  it('works using then', function (done) {
+  it('works using then', function(done) {
     var db = start(),
         MR = db.model('MapReduce', collection);
 
@@ -253,25 +253,25 @@ describe('model: mapreduce:', function () {
       docs.push({author: authors[i % authors.length], owners: [id], published: true});
     }
 
-    MR.create(docs, function (err, insertedDocs) {
+    MR.create(docs, function(err, insertedDocs) {
       assert.ifError(err);
 
       var b = insertedDocs[1];
       magicID = b._id;
 
       var o = {
-        map: function () {
+        map: function() {
           emit(this.author, 1);
         },
-        reduce: function (k, vals) {
+        reduce: function(k, vals) {
           return vals.length;
         }
       };
 
-      MR.mapReduce(o).then(function (ret, stats) {
+      MR.mapReduce(o).then(function(ret, stats) {
         assert.ok(Array.isArray(ret));
         assert.ok(stats);
-        ret.forEach(function (res) {
+        ret.forEach(function(res) {
           if (res._id === 'aaron') {
             assert.equal(6, res.value);
           }
@@ -287,16 +287,16 @@ describe('model: mapreduce:', function () {
         });
 
         var o = {
-          map: function () {
+          map: function() {
             emit(this.author, 1);
           },
-          reduce: function (k, vals) {
+          reduce: function(k, vals) {
             return vals.length;
           },
           query: {author: 'aaron', published: 1, owners: id}
         };
 
-        MR.mapReduce(o).then(function (ret, stats) {
+        MR.mapReduce(o).then(function(ret, stats) {
           assert.ok(Array.isArray(ret));
           assert.equal(1, ret.length);
           assert.equal('aaron', ret[0]._id);
@@ -308,24 +308,24 @@ describe('model: mapreduce:', function () {
 
       function modeling() {
         var o = {
-          map: function () {
+          map: function() {
             emit(this.author, {own: magicID});
           },
           scope: {magicID: magicID},
-          reduce: function (k, vals) {
+          reduce: function(k, vals) {
             return {own: vals[0].own, count: vals.length};
           },
           out: {replace: '_mapreduce_test_' + random()}
         };
 
-        MR.mapReduce(o).then(function (ret) {
+        MR.mapReduce(o).then(function(ret) {
           // ret is a model
           assert.ok(!Array.isArray(ret));
           assert.equal('function', typeof ret.findOne);
           assert.equal('function', typeof ret.mapReduce);
 
           // queries work
-          ret.where('value.count').gt(1).sort({_id: 1}).exec(function (err, docs) {
+          ret.where('value.count').gt(1).sort({_id: 1}).exec(function(err, docs) {
             assert.ifError(err);
             assert.equal('aaron', docs[0]._id);
             assert.equal('brian', docs[1]._id);
@@ -333,7 +333,7 @@ describe('model: mapreduce:', function () {
             assert.equal('nathan', docs[3]._id);
 
             // update casting works
-            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {'new': true}, function (err, doc) {
+            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {'new': true}, function(err, doc) {
               assert.ifError(err);
               assert.ok(doc);
               assert.equal('aaron', doc._id);
@@ -343,7 +343,7 @@ describe('model: mapreduce:', function () {
               ret
               .findOne({_id: 'aaron'})
               .populate({path: 'value.own', model: 'MapReduce'})
-              .exec(function (err, doc) {
+              .exec(function(err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal('guillermo', doc.value.own.author);
@@ -356,20 +356,20 @@ describe('model: mapreduce:', function () {
     });
   });
 
-  it('withholds stats with false verbosity using then', function (done) {
+  it('withholds stats with false verbosity using then', function(done) {
     var db = start(),
         MR = db.model('MapReduce', collection);
 
     var o = {
-      map: function () {
+      map: function() {
       },
-      reduce: function () {
+      reduce: function() {
         return 'test';
       },
       verbose: false
     };
 
-    MR.mapReduce(o).then(function (results, stats) {
+    MR.mapReduce(o).then(function(results, stats) {
       assert.equal('undefined', typeof stats);
       db.close(done);
     });
diff --git a/test/model.middleware.test.js b/test/model.middleware.test.js
index c949554f619..326b13d8277 100644
--- a/test/model.middleware.test.js
+++ b/test/model.middleware.test.js
@@ -8,29 +8,29 @@ var start = require('./common'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema;
 
-describe('model middleware', function () {
-  it('post save', function (done) {
+describe('model middleware', function() {
+  it('post save', function(done) {
     var schema = new Schema({
       title: String
     });
 
     var called = 0;
 
-    schema.post('save', function (obj) {
+    schema.post('save', function(obj) {
       assert.equal(obj.title, 'Little Green Running Hood');
       assert.equal(this.title, 'Little Green Running Hood');
       assert.equal(0, called);
       called++;
     });
 
-    schema.post('save', function (obj) {
+    schema.post('save', function(obj) {
       assert.equal(obj.title, 'Little Green Running Hood');
       assert.equal(this.title, 'Little Green Running Hood');
       assert.equal(1, called);
       called++;
     });
 
-    schema.post('save', function (obj, next) {
+    schema.post('save', function(obj, next) {
       assert.equal(obj.title, 'Little Green Running Hood');
       assert.equal(2, called);
       called++;
@@ -42,7 +42,7 @@ describe('model middleware', function () {
 
     var test = new TestMiddleware({title: 'Little Green Running Hood'});
 
-    test.save(function (err) {
+    test.save(function(err) {
       assert.ifError(err);
       assert.equal(test.title, 'Little Green Running Hood');
       assert.equal(3, called);
@@ -51,18 +51,18 @@ describe('model middleware', function () {
     });
   });
 
-  it('validate middleware runs before save middleware (gh-2462)', function (done) {
+  it('validate middleware runs before save middleware (gh-2462)', function(done) {
     var schema = new Schema({
       title: String
     });
     var count = 0;
 
-    schema.pre('validate', function (next) {
+    schema.pre('validate', function(next) {
       assert.equal(0, count++);
       next();
     });
 
-    schema.pre('save', function (next) {
+    schema.pre('save', function(next) {
       assert.equal(1, count++);
       next();
     });
@@ -70,30 +70,30 @@ describe('model middleware', function () {
     var db = start();
     var Book = db.model('gh2462', schema);
 
-    Book.create({}, function () {
+    Book.create({}, function() {
       assert.equal(count, 2);
       db.close(done);
     });
   });
 
-  it('works', function (done) {
+  it('works', function(done) {
     var schema = new Schema({
       title: String
     });
 
     var called = 0;
 
-    schema.pre('init', function (next) {
+    schema.pre('init', function(next) {
       called++;
       next();
     });
 
-    schema.pre('save', function (next) {
+    schema.pre('save', function(next) {
       called++;
       next(new Error('Error 101'));
     });
 
-    schema.pre('remove', function (next) {
+    schema.pre('remove', function(next) {
       called++;
       next();
     });
@@ -111,12 +111,12 @@ describe('model middleware', function () {
 
     assert.equal(1, called);
 
-    test.save(function (err) {
+    test.save(function(err) {
       assert.ok(err instanceof Error);
       assert.equal(err.message, 'Error 101');
       assert.equal(2, called);
 
-      test.remove(function (err) {
+      test.remove(function(err) {
         db.close();
         assert.ifError(err);
         assert.equal(3, called);
@@ -125,7 +125,7 @@ describe('model middleware', function () {
     });
   });
 
-  it('post init', function (done) {
+  it('post init', function(done) {
     var schema = new Schema({
       title: String
     });
@@ -133,12 +133,12 @@ describe('model middleware', function () {
     var preinit = 0,
         postinit = 0;
 
-    schema.pre('init', function (next) {
+    schema.pre('init', function(next) {
       ++preinit;
       next();
     });
 
-    schema.post('init', function (doc) {
+    schema.post('init', function(doc) {
       assert.ok(doc instanceof mongoose.Document);
       ++postinit;
     });
@@ -150,14 +150,14 @@ describe('model middleware', function () {
 
     var test = new Test({title: 'banana'});
 
-    test.save(function (err) {
+    test.save(function(err) {
       assert.ifError(err);
 
-      Test.findById(test._id, function (err, test) {
+      Test.findById(test._id, function(err, test) {
         assert.ifError(err);
         assert.equal(1, preinit);
         assert.equal(1, postinit);
-        test.remove(function () {
+        test.remove(function() {
           db.close();
           done();
         });
@@ -165,7 +165,7 @@ describe('model middleware', function () {
     });
   });
 
-  it('gh-1829', function (done) {
+  it('gh-1829', function(done) {
     var childSchema = new mongoose.Schema({
       name: String
     });
@@ -174,7 +174,7 @@ describe('model middleware', function () {
     var childPreCallsByName = {};
     var parentPreCalls = 0;
 
-    childSchema.pre('save', function (next) {
+    childSchema.pre('save', function(next) {
       childPreCallsByName[this.name] = childPreCallsByName[this.name] || 0;
       ++childPreCallsByName[this.name];
       ++childPreCalls;
@@ -186,7 +186,7 @@ describe('model middleware', function () {
       children: [childSchema]
     });
 
-    parentSchema.pre('save', function (next) {
+    parentSchema.pre('save', function(next) {
       ++parentPreCalls;
       next();
     });
@@ -202,14 +202,14 @@ describe('model middleware', function () {
       ]
     });
 
-    parent.save(function (error) {
+    parent.save(function(error) {
       assert.ifError(error);
       assert.equal(2, childPreCalls);
       assert.equal(1, childPreCallsByName.Jaina);
       assert.equal(1, childPreCallsByName.Jacen);
       assert.equal(1, parentPreCalls);
       parent.children[0].name = 'Anakin';
-      parent.save(function (error) {
+      parent.save(function(error) {
         assert.ifError(error);
         assert.equal(4, childPreCalls);
         assert.equal(1, childPreCallsByName.Anakin);
@@ -223,7 +223,7 @@ describe('model middleware', function () {
     });
   });
 
-  it('validate + remove', function (done) {
+  it('validate + remove', function(done) {
     var schema = new Schema({
       title: String
     });
@@ -233,22 +233,22 @@ describe('model middleware', function () {
         preRemove = 0,
         postRemove = 0;
 
-    schema.pre('validate', function (next) {
+    schema.pre('validate', function(next) {
       ++preValidate;
       next();
     });
 
-    schema.pre('remove', function (next) {
+    schema.pre('remove', function(next) {
       ++preRemove;
       next();
     });
 
-    schema.post('validate', function (doc) {
+    schema.post('validate', function(doc) {
       assert.ok(doc instanceof mongoose.Document);
       ++postValidate;
     });
 
-    schema.post('remove', function (doc) {
+    schema.post('remove', function(doc) {
       assert.ok(doc instanceof mongoose.Document);
       ++postRemove;
     });
@@ -258,13 +258,13 @@ describe('model middleware', function () {
 
     var test = new Test({title: 'banana'});
 
-    test.save(function (err) {
+    test.save(function(err) {
       assert.ifError(err);
       assert.equal(1, preValidate);
       assert.equal(1, postValidate);
       assert.equal(0, preRemove);
       assert.equal(0, postRemove);
-      test.remove(function (err) {
+      test.remove(function(err) {
         db.close();
         assert.ifError(err);
         assert.equal(1, preValidate);
diff --git a/test/model.populate.divergent.test.js b/test/model.populate.divergent.test.js
index ebacb4ddf8a..276315b1fc8 100644
--- a/test/model.populate.divergent.test.js
+++ b/test/model.populate.divergent.test.js
@@ -14,7 +14,7 @@ var start = require('./common'),
  * Tests.
  */
 
-describe('model: populate: divergent arrays', function () {
+describe('model: populate: divergent arrays', function() {
   // match
   // skip
   // limit
@@ -26,7 +26,7 @@ describe('model: populate: divergent arrays', function () {
 
   var db, C, M;
 
-  before(function (done) {
+  before(function(done) {
     db = start();
     C = db.model('Child', {_id: Number, name: String}, 'child-' + random());
     M = db.model('Parent', {array: {type: [{type: Number, ref: 'Child'}]}}, 'parent-' + random());
@@ -34,45 +34,45 @@ describe('model: populate: divergent arrays', function () {
     C.create(
         {_id: 0, name: 'zero'}
       , {_id: 1, name: 'one'}
-      , {_id: 2, name: 'two'}, function (err) {
+      , {_id: 2, name: 'two'}, function(err) {
         assert.ifError(err);
-        M.create({array: [0, 1, 2]}, function (err) {
+        M.create({array: [0, 1, 2]}, function(err) {
           assert.ifError(err);
           done();
         });
       });
   });
 
-  after(function (done) {
+  after(function(done) {
     db.close(done);
   });
 
   function test(check, fn) {
-    it('using $set', function (done) {
-      fn(function (err, doc) {
+    it('using $set', function(done) {
+      fn(function(err, doc) {
         assert.ifError(err);
         doc.array.unshift({_id: 10, name: 'ten'});
-        doc.save(function (err) {
+        doc.save(function(err) {
           check(err);
           done();
         });
       });
     });
-    it('using $pop 1', function (done) {
-      fn(function (err, doc) {
+    it('using $pop 1', function(done) {
+      fn(function(err, doc) {
         assert.ifError(err);
         doc.array.$pop();
-        doc.save(function (err) {
+        doc.save(function(err) {
           check(err);
           done();
         });
       });
     });
-    it('using $pop -1', function (done) {
-      fn(function (err, doc) {
+    it('using $pop -1', function(done) {
+      fn(function(err, doc) {
         assert.ifError(err);
         doc.array.$shift();
-        doc.save(function (err) {
+        doc.save(function(err) {
           check(err);
           done();
         });
@@ -85,59 +85,59 @@ describe('model: populate: divergent arrays', function () {
   }
 
   function testFails(fn) {
-    test(function (err) {
+    test(function(err) {
       assert.ok(err instanceof DivergentArrayError, 'non-divergent error: ' + err);
       assert.ok(/\sarray/.test(err.message));
     }, fn);
   }
 
-  describe('from match', function () {
-    testFails(function (cb) {
+  describe('from match', function() {
+    testFails(function(cb) {
       M.findOne().populate({path: 'array', match: {name: 'one'}}).exec(cb);
     });
   });
-  describe('from skip', function () {
-    describe('2', function () {
-      testFails(function (cb) {
+  describe('from skip', function() {
+    describe('2', function() {
+      testFails(function(cb) {
         M.findOne().populate({path: 'array', options: {skip: 2}}).exec(cb);
       });
     });
-    describe('0', function () {
-      testOk(function (cb) {
+    describe('0', function() {
+      testOk(function(cb) {
         M.findOne().populate({path: 'array', options: {skip: 0}}).exec(cb);
       });
     });
   });
-  describe('from limit', function () {
-    describe('0', function () {
-      testFails(function (cb) {
+  describe('from limit', function() {
+    describe('0', function() {
+      testFails(function(cb) {
         M.findOne().populate({path: 'array', options: {limit: 0}}).exec(cb);
       });
     });
-    describe('1', function () {
-      testFails(function (cb) {
+    describe('1', function() {
+      testFails(function(cb) {
         M.findOne().populate({path: 'array', options: {limit: 1}}).exec(cb);
       });
     });
   });
-  describe('from deselected _id', function () {
-    describe('using string and only -_id', function () {
-      testFails(function (cb) {
+  describe('from deselected _id', function() {
+    describe('using string and only -_id', function() {
+      testFails(function(cb) {
         M.findOne().populate({path: 'array', select: '-_id'}).exec(cb);
       });
     });
-    describe('using string', function () {
-      testFails(function (cb) {
+    describe('using string', function() {
+      testFails(function(cb) {
         M.findOne().populate({path: 'array', select: 'name -_id'}).exec(cb);
       });
     });
-    describe('using object and only _id: 0', function () {
-      testFails(function (cb) {
+    describe('using object and only _id: 0', function() {
+      testFails(function(cb) {
         M.findOne().populate({path: 'array', select: {_id: 0}}).exec(cb);
       });
     });
-    describe('using object', function () {
-      testFails(function (cb) {
+    describe('using object', function() {
+      testFails(function(cb) {
         M.findOne().populate({path: 'array', select: {_id: 0, name: 1}}).exec(cb);
       });
     });
diff --git a/test/model.populate.setting.test.js b/test/model.populate.setting.test.js
index 02a7d1a444f..451e9c78620 100644
--- a/test/model.populate.setting.test.js
+++ b/test/model.populate.setting.test.js
@@ -23,8 +23,8 @@ var posts = 'blogposts_' + random(),
  * Tests.
  */
 
-describe('model: populate:', function () {
-  describe('setting populated paths (gh-570)', function () {
+describe('model: populate:', function() {
+  describe('setting populated paths (gh-570)', function() {
     var types = {
       'ObjectId': DocObjectId,
       'String': String,
@@ -36,19 +36,19 @@ describe('model: populate:', function () {
     construct.String = random;
     construct.ObjectId = DocObjectId;
     construct.Number = random;
-    construct.Buffer = function () {
+    construct.Buffer = function() {
       return new Buffer(random());
     };
 
-    Object.keys(types).forEach(function (id) {
-      describe('should not cast to _id of type ' + id, function () {
+    Object.keys(types).forEach(function(id) {
+      describe('should not cast to _id of type ' + id, function() {
         var refuser;
         var db;
         var B, U;
         var u1;
         var b1, b2;
 
-        before(function (done) {
+        before(function(done) {
           refuser = 'RefUser-' + id;
 
           var bSchema = new Schema({
@@ -81,7 +81,7 @@ describe('model: populate:', function () {
             _id: construct[id](),
             name: 'Fan 2',
             email: 'fan2@learnboost.com'
-          }, function (err, fan1, fan2) {
+          }, function(err, fan1, fan2) {
             assert.ifError(err);
             u1 = fan1;
 
@@ -98,7 +98,7 @@ describe('model: populate:', function () {
               _creator: fan1,
               _creator: fan2,
               embed: [{other: fan2, array: [fan2, fan1]}, {other: fan1, array: [fan1, fan2]}]
-            }, function (err, post1, post2) {
+            }, function(err, post1, post2) {
               assert.ifError(err);
               b1 = post1;
               b2 = post2;
@@ -107,7 +107,7 @@ describe('model: populate:', function () {
           });
         });
 
-        after(function (done) {
+        after(function(done) {
           db.close(done);
         });
 
@@ -119,12 +119,12 @@ describe('model: populate:', function () {
           return new U(userLiteral(name));
         }
 
-        it('if a document', function (done) {
+        it('if a document', function(done) {
           B.findById(b1)
            .populate('fans _creator embed.other embed.array embed.nested.subdoc')
            .populate({path: 'adhoc.subdoc', model: refuser})
            .populate({path: 'adhoc.subarray.things', model: refuser})
-           .exec(function (err, doc) {
+           .exec(function(err, doc) {
              assert.ifError(err);
 
              var user3 = user('user3');
@@ -147,7 +147,7 @@ describe('model: populate:', function () {
              doc.fans.addToSet(user7);
              assert.deepEqual(doc.fans[5].toObject(), user7.toObject());
 
-             doc.fans.forEach(function (doc) {
+             doc.fans.forEach(function(doc) {
                assert.ok(doc instanceof U);
              });
 
@@ -198,9 +198,9 @@ describe('model: populate:', function () {
              doc.adhoc[0].subarray[0].things.push(user2b);
              assert.deepEqual(doc.adhoc[0].subarray[0].things[1].toObject(), user2b.toObject());
 
-             doc.save(function (err) {
+             doc.save(function(err) {
                assert.ifError(err);
-               B.findById(b1).exec(function (err, doc) {
+               B.findById(b1).exec(function(err, doc) {
                 // db is closed in after()
                  assert.ifError(err);
                  assert.equal(8, doc.fans.length);
@@ -220,12 +220,12 @@ describe('model: populate:', function () {
            });
         });
 
-        it('if an object', function (done) {
+        it('if an object', function(done) {
           B.findById(b2)
            .populate('fans _creator embed.other embed.array embed.nested.subdoc')
            .populate({path: 'adhoc.subdoc', model: refuser})
            .populate({path: 'adhoc.subarray.things', model: refuser})
-           .exec(function (err, doc) {
+           .exec(function(err, doc) {
              assert.ifError(err);
 
              var name = 'fan1';
@@ -258,7 +258,7 @@ describe('model: populate:', function () {
              assert.ok(doc.fans[0]._id);
              assert.equal(name, doc.fans[0].name);
 
-             doc.fans.forEach(function (doc) {
+             doc.fans.forEach(function(doc) {
                assert.ok(doc instanceof U);
              });
 
@@ -304,9 +304,9 @@ describe('model: populate:', function () {
              assert.deepEqual(name, doc.adhoc[0].subarray[0].things[1].name);
              var user2bId = doc.adhoc[0].subarray[0].things[1]._id;
 
-             doc.save(function (err) {
+             doc.save(function(err) {
                assert.ifError(err);
-               B.findById(b2).exec(function (err, doc) {
+               B.findById(b2).exec(function(err, doc) {
                 // db is closed in after()
                  assert.ifError(err);
                  assert.equal(6, doc.fans.length);
diff --git a/test/model.populate.test.js b/test/model.populate.test.js
index e02b85c513f..9b561865c24 100644
--- a/test/model.populate.test.js
+++ b/test/model.populate.test.js
@@ -61,16 +61,16 @@ mongoose.model('RefAlternateUser', User);
  * Tests.
  */
 
-describe('model: populate:', function () {
-  it('populating array of object', function (done) {
+describe('model: populate:', function() {
+  it('populating array of object', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
-    User.create({name: 'User 1'}, function (err, user1) {
+    User.create({name: 'User 1'}, function(err, user1) {
       assert.ifError(err);
 
-      User.create({name: 'User 2'}, function (err, user2) {
+      User.create({name: 'User 2'}, function(err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
@@ -80,11 +80,11 @@ describe('model: populate:', function () {
             {_creator: user1._id, content: 'Woot woot'},
             {_creator: user2._id, content: 'Wha wha'}
           ]
-        }, function (err, post) {
+        }, function(err, post) {
           assert.ifError(err);
 
-          assert.doesNotThrow(function () {
-            post.populate('comments', function () {
+          assert.doesNotThrow(function() {
+            post.populate('comments', function() {
             });
           });
           db.close(done);
@@ -93,27 +93,27 @@ describe('model: populate:', function () {
     });
   });
 
-  it('deep population (gh-3103)', function (done) {
+  it('deep population (gh-3103)', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
-    User.create({name: 'User 01'}, function (err, user1) {
+    User.create({name: 'User 01'}, function(err, user1) {
       assert.ifError(err);
 
-      User.create({name: 'User 02', followers: [user1._id]}, function (err, user2) {
+      User.create({name: 'User 02', followers: [user1._id]}, function(err, user2) {
         assert.ifError(err);
 
-        User.create({name: 'User 03', followers: [user2._id]}, function (err, user3) {
+        User.create({name: 'User 03', followers: [user2._id]}, function(err, user3) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'w00tabulous',
             _creator: user3._id
-          }, function (err, post) {
+          }, function(err, post) {
             assert.ifError(err);
 
-            assert.doesNotThrow(function () {
+            assert.doesNotThrow(function() {
               BlogPost
               .findById(post._id)
               .select('_creator')
@@ -132,7 +132,7 @@ describe('model: populate:', function () {
                   }
                 }]
               })
-              .exec(function (err, post) {
+              .exec(function(err, post) {
                 db.close();
                 assert.ifError(err);
                 assert.ok(post._creator);
@@ -152,7 +152,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('deep population with refs (gh-3507)', function (done) {
+  it('deep population with refs (gh-3507)', function(done) {
     var db = start();
     // handler schema
     var handlerSchema = new Schema({
@@ -175,12 +175,12 @@ describe('model: populate:', function () {
     var Task = db.model('gh3507_1', taskSchema);
     var Application = db.model('gh3507_2', applicationSchema);
 
-    Handler.create({name: 'test'}, function (error, doc) {
+    Handler.create({name: 'test'}, function(error, doc) {
       assert.ifError(error);
-      Task.create({name: 'test2', handler: doc._id}, function (error, doc) {
+      Task.create({name: 'test2', handler: doc._id}, function(error, doc) {
         assert.ifError(error);
         var obj = {name: 'test3', tasks: [doc._id]};
-        Application.create(obj, function (error, doc) {
+        Application.create(obj, function(error, doc) {
           assert.ifError(error);
           test(doc._id);
         });
@@ -193,7 +193,7 @@ describe('model: populate:', function () {
       populate([
         {path: 'tasks', populate: {path: 'handler'}}
       ]).
-      exec(function (error, doc) {
+      exec(function(error, doc) {
         assert.ifError(error);
         assert.ok(doc.tasks[0].handler._id);
         db.close(done);
@@ -201,7 +201,7 @@ describe('model: populate:', function () {
     }
   });
 
-  it('populating a single ref', function (done) {
+  it('populating a single ref', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -209,19 +209,19 @@ describe('model: populate:', function () {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function (err, creator) {
+    }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator')
-        .exec(function (err, post) {
+        .exec(function(err, post) {
           assert.ifError(err);
 
           assert.ok(post._creator instanceof User);
@@ -233,20 +233,20 @@ describe('model: populate:', function () {
     });
   });
 
-  it('not failing on null as ref', function (done) {
+  it('not failing on null as ref', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create({
       title: 'woot',
       _creator: null
-    }, function (err, post) {
+    }, function(err, post) {
       assert.ifError(err);
 
       BlogPost
       .findById(post._id)
       .populate('_creator')
-      .exec(function (err, post) {
+      .exec(function(err, post) {
         assert.ifError(err);
 
         assert.equal(post._creator, null);
@@ -255,24 +255,24 @@ describe('model: populate:', function () {
     });
   });
 
-  it('not failing on empty object as ref', function (done) {
+  it('not failing on empty object as ref', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create(
         {title: 'woot'},
-        function (err, post) {
+        function(err, post) {
           assert.ifError(err);
 
           BlogPost.
-          findByIdAndUpdate(post._id, {$set: {_creator: {}}}, function (err) {
+          findByIdAndUpdate(post._id, {$set: {_creator: {}}}, function(err) {
             assert.ok(err);
             db.close(done);
           });
         });
   });
 
-  it('across DBs', function (done) {
+  it('across DBs', function(done) {
     var db = start(),
         db2 = db.useDb('mongoose_test2'),
         BlogPost = db.model('RefBlogPost', posts + '2'),
@@ -281,19 +281,19 @@ describe('model: populate:', function () {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function (err, creator) {
+    }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator._id
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
         BlogPost
         .findById(post._id)
         .populate('_creator', 'name', User)
-        .exec(function (err, post) {
-          db2.db.dropDatabase(function () {
+        .exec(function(err, post) {
+          db2.db.dropDatabase(function() {
             db.close();
             db2.close();
             assert.ifError(err);
@@ -305,7 +305,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('an error in single ref population propagates', function (done) {
+  it('an error in single ref population propagates', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts + '1'),
         User = db.model('RefUser', users + '1');
@@ -313,21 +313,21 @@ describe('model: populate:', function () {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function (err, creator) {
+    }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         var origFind = User.find;
 
         // mock an error
-        User.find = function () {
-          var args = Array.prototype.map.call(arguments, function (arg) {
-            return typeof arg === 'function' ? function () {
+        User.find = function() {
+          var args = Array.prototype.map.call(arguments, function(arg) {
+            return typeof arg === 'function' ? function() {
               arg(new Error('woot'));
             } : arg;
           });
@@ -337,7 +337,7 @@ describe('model: populate:', function () {
         BlogPost
         .findById(post._id)
         .populate('_creator')
-        .exec(function (err) {
+        .exec(function(err) {
           db.close();
           assert.ok(err instanceof Error);
           assert.equal('woot', err.message);
@@ -347,7 +347,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating with partial fields selection', function (done) {
+  it('populating with partial fields selection', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -355,19 +355,19 @@ describe('model: populate:', function () {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function (err, creator) {
+    }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator', 'email')
-        .exec(function (err, post) {
+        .exec(function(err, post) {
           db.close();
           assert.ifError(err);
 
@@ -380,7 +380,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('population of single oid with partial field selection and filter', function (done) {
+  it('population of single oid with partial field selection and filter', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', 'blogposts_' + random()),
         User = db.model('RefUser', 'users_' + random());
@@ -388,26 +388,26 @@ describe('model: populate:', function () {
     User.create({
       name: 'Banana',
       email: 'cats@example.com'
-    }, function (err, creator) {
+    }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator', 'email', {name: 'Peanut'})
-        .exec(function (err, post) {
+        .exec(function(err, post) {
           assert.ifError(err);
           assert.strictEqual(post._creator, null);
 
           BlogPost
           .findById(post._id)
           .populate('_creator', 'email', {name: 'Banana'})
-          .exec(function (err, post) {
+          .exec(function(err, post) {
             db.close();
             assert.ifError(err);
             assert.ok(post._creator instanceof User);
@@ -420,32 +420,32 @@ describe('model: populate:', function () {
     });
   });
 
-  it('population of undefined fields in a collection of docs', function (done) {
+  it('population of undefined fields in a collection of docs', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', 'blogposts_' + random()),
         User = db.model('RefUser', 'users_' + random());
     User.create({
       name: 'Eloy',
       email: 'eloytoro@gmail.com'
-    }, function (err, user) {
+    }, function(err, user) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'I have a user ref',
         _creator: user
-      }, function (err) {
+      }, function(err) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'I don\'t'
-        }, function (err) {
+        }, function(err) {
           assert.ifError(err);
           BlogPost
           .find()
           .populate('_creator')
-          .exec(function (err, posts) {
+          .exec(function(err, posts) {
             db.close();
-            posts.forEach(function (post) {
+            posts.forEach(function(post) {
               if ('_creator' in post) {
                 assert.ok(post._creator !== null);
               }
@@ -457,7 +457,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('population and changing a reference', function (done) {
+  it('population and changing a reference', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -465,19 +465,19 @@ describe('model: populate:', function () {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function (err, creator) {
+    }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator')
-        .exec(function (err, post) {
+        .exec(function(err, post) {
           assert.ifError(err);
 
           assert.ok(post._creator instanceof User);
@@ -487,19 +487,19 @@ describe('model: populate:', function () {
           User.create({
             name: 'Aaron',
             email: 'aaron.heckmann@gmail.com'
-          }, function (err, newCreator) {
+          }, function(err, newCreator) {
             assert.ifError(err);
 
             post._creator = newCreator._id;
             assert.equal(newCreator._id, String(post._creator));
 
-            post.save(function (err) {
+            post.save(function(err) {
               assert.ifError(err);
 
               BlogPost
               .findById(post._id)
               .populate('_creator')
-              .exec(function (err, post) {
+              .exec(function(err, post) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(post._creator.name, 'Aaron');
@@ -513,7 +513,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating with partial fields selection and changing ref', function (done) {
+  it('populating with partial fields selection and changing ref', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -521,19 +521,19 @@ describe('model: populate:', function () {
     User.create({
       name: 'Guillermo',
       email: 'rauchg@gmail.com'
-    }, function (err, creator) {
+    }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator', {'name': 1})
-        .exec(function (err, post) {
+        .exec(function(err, post) {
           assert.ifError(err);
 
           assert.ok(post._creator instanceof User);
@@ -542,17 +542,17 @@ describe('model: populate:', function () {
           User.create({
             name: 'Aaron',
             email: 'aaron@learnboost.com'
-          }, function (err, newCreator) {
+          }, function(err, newCreator) {
             assert.ifError(err);
 
             post._creator = newCreator._id;
-            post.save(function (err) {
+            post.save(function(err) {
               assert.ifError(err);
 
               BlogPost
               .findById(post._id)
               .populate('_creator', '-email')
-              .exec(function (err, post) {
+              .exec(function(err, post) {
                 db.close();
                 assert.ifError(err);
 
@@ -567,7 +567,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating an array of refs and fetching many', function (done) {
+  it('populating an array of refs and fetching many', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -575,31 +575,31 @@ describe('model: populate:', function () {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function (err, fan1) {
+    }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function (err, fan2) {
+      }, function(err, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           fans: [fan1, fan2]
-        }, function (err, post1) {
+        }, function(err, post1) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan2, fan1]
-          }, function (err, post2) {
+          }, function(err, post2) {
             assert.ifError(err);
 
             BlogPost
             .find({_id: {$in: [post1._id, post2._id]}})
             .populate('fans')
-            .exec(function (err, blogposts) {
+            .exec(function(err, blogposts) {
               db.close();
               assert.ifError(err);
 
@@ -620,7 +620,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('an error in array reference population propagates', function (done) {
+  it('an error in array reference population propagates', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts + '2'),
         User = db.model('RefUser', users + '2');
@@ -628,32 +628,32 @@ describe('model: populate:', function () {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function (err, fan1) {
+    }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function (err, fan2) {
+      }, function(err, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           fans: [fan1, fan2]
-        }, function (err, post1) {
+        }, function(err, post1) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan2, fan1]
-          }, function (err, post2) {
+          }, function(err, post2) {
             assert.ifError(err);
 
             // mock an error
             var origFind = User.find;
-            User.find = function () {
-              var args = Array.prototype.map.call(arguments, function (arg) {
-                return typeof arg === 'function' ? function () {
+            User.find = function() {
+              var args = Array.prototype.map.call(arguments, function(arg) {
+                return typeof arg === 'function' ? function() {
                   arg(new Error('woot 2'));
                 } : arg;
               });
@@ -663,7 +663,7 @@ describe('model: populate:', function () {
             BlogPost
             .find({$or: [{_id: post1._id}, {_id: post2._id}]})
             .populate('fans')
-            .exec(function (err) {
+            .exec(function(err) {
               db.close();
 
               assert.ok(err instanceof Error);
@@ -676,7 +676,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating an array of references with fields selection', function (done) {
+  it('populating an array of references with fields selection', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -684,31 +684,31 @@ describe('model: populate:', function () {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function (err, fan1) {
+    }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function (err, fan2) {
+      }, function(err, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'Woot',
           fans: [fan1, fan2]
-        }, function (err, post1) {
+        }, function(err, post1) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan2, fan1]
-          }, function (err, post2) {
+          }, function(err, post2) {
             assert.ifError(err);
 
             BlogPost
             .find({_id: {$in: [post1._id, post2._id]}})
             .populate('fans', 'name')
-            .exec(function (err, blogposts) {
+            .exec(function(err, blogposts) {
               db.close();
               assert.ifError(err);
 
@@ -731,7 +731,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating an array of references and filtering', function (done) {
+  it('populating an array of references and filtering', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -739,39 +739,39 @@ describe('model: populate:', function () {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function (err, fan1) {
+    }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com',
         gender: 'female'
-      }, function (err, fan2) {
+      }, function(err, fan2) {
         assert.ifError(err);
 
         User.create({
           name: 'Fan 3',
           email: 'fan3@learnboost.com',
           gender: 'female'
-        }, function (err, fan3) {
+        }, function(err, fan3) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan1, fan2, fan3]
-          }, function (err, post1) {
+          }, function(err, post1) {
             assert.ifError(err);
 
             BlogPost.create({
               title: 'Woot',
               fans: [fan3, fan2, fan1]
-            }, function (err, post2) {
+            }, function(err, post2) {
               assert.ifError(err);
 
               BlogPost
               .find({_id: {$in: [post1._id, post2._id]}})
               .populate('fans', '', {gender: 'female', _id: {$in: [fan2]}})
-              .exec(function (err, blogposts) {
+              .exec(function(err, blogposts) {
                 assert.ifError(err);
 
                 assert.equal(blogposts[0].fans.length, 1);
@@ -787,7 +787,7 @@ describe('model: populate:', function () {
                 BlogPost
                 .find({_id: {$in: [post1._id, post2._id]}})
                 .populate('fans', false, {gender: 'female'})
-                .exec(function (err, blogposts) {
+                .exec(function(err, blogposts) {
                   db.close();
                   assert.ifError(err);
 
@@ -817,7 +817,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating an array of references and multi-filtering', function (done) {
+  it('populating an array of references and multi-filtering', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -825,14 +825,14 @@ describe('model: populate:', function () {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function (err, fan1) {
+    }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com',
         gender: 'female'
-      }, function (err, fan2) {
+      }, function(err, fan2) {
         assert.ifError(err);
 
         User.create({
@@ -840,25 +840,25 @@ describe('model: populate:', function () {
           email: 'fan3@learnboost.com',
           gender: 'female',
           age: 25
-        }, function (err, fan3) {
+        }, function(err, fan3) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan1, fan2, fan3]
-          }, function (err, post1) {
+          }, function(err, post1) {
             assert.ifError(err);
 
             BlogPost.create({
               title: 'Woot',
               fans: [fan3, fan2, fan1]
-            }, function (err, post2) {
+            }, function(err, post2) {
               assert.ifError(err);
 
               BlogPost
               .find({_id: {$in: [post1._id, post2._id]}})
               .populate('fans', undefined, {_id: fan3})
-              .exec(function (err, blogposts) {
+              .exec(function(err, blogposts) {
                 assert.ifError(err);
 
                 assert.equal(blogposts[0].fans.length, 1);
@@ -876,7 +876,7 @@ describe('model: populate:', function () {
                 BlogPost
                 .find({_id: {$in: [post1._id, post2._id]}})
                 .populate('fans', 0, {gender: 'female'})
-                .exec(function (err, blogposts) {
+                .exec(function(err, blogposts) {
                   db.close();
                   assert.ifError(err);
 
@@ -908,7 +908,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating an array of references and multi-filtering with field selection', function (done) {
+  it('populating an array of references and multi-filtering with field selection', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -916,14 +916,14 @@ describe('model: populate:', function () {
     User.create({
       name: 'Fan 1',
       email: 'fan1@learnboost.com'
-    }, function (err, fan1) {
+    }, function(err, fan1) {
       assert.ifError(err);
 
       User.create({
         name: 'Fan 2',
         email: 'fan2@learnboost.com',
         gender: 'female'
-      }, function (err, fan2) {
+      }, function(err, fan2) {
         assert.ifError(err);
 
         User.create({
@@ -931,25 +931,25 @@ describe('model: populate:', function () {
           email: 'fan3@learnboost.com',
           gender: 'female',
           age: 25
-        }, function (err, fan3) {
+        }, function(err, fan3) {
           assert.ifError(err);
 
           BlogPost.create({
             title: 'Woot',
             fans: [fan1, fan2, fan3]
-          }, function (err, post1) {
+          }, function(err, post1) {
             assert.ifError(err);
 
             BlogPost.create({
               title: 'Woot',
               fans: [fan3, fan2, fan1]
-            }, function (err, post2) {
+            }, function(err, post2) {
               assert.ifError(err);
 
               BlogPost
               .find({_id: {$in: [post1._id, post2._id]}})
               .populate('fans', 'name email', {gender: 'female', age: 25})
-              .exec(function (err, blogposts) {
+              .exec(function(err, blogposts) {
                 db.close();
                 assert.ifError(err);
 
@@ -976,7 +976,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating an array of refs changing one and removing one', function (done) {
+  it('populating an array of refs changing one and removing one', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -993,7 +993,7 @@ describe('model: populate:', function () {
     }, {
       name: 'Fan 4',
       email: 'fan4@learnboost.com'
-    }, function (err, fan1, fan2, fan3, fan4) {
+    }, function(err, fan1, fan2, fan3, fan4) {
       assert.ifError(err);
 
       BlogPost.create({
@@ -1002,13 +1002,13 @@ describe('model: populate:', function () {
       }, {
         title: 'Woot',
         fans: [fan2, fan1]
-      }, function (err, post1, post2) {
+      }, function(err, post1, post2) {
         assert.ifError(err);
 
         BlogPost
         .find({_id: {$in: [post1._id, post2._id]}})
         .populate('fans', 'name')
-        .exec(function (err, blogposts) {
+        .exec(function(err, blogposts) {
           assert.ifError(err);
 
           assert.equal(blogposts[0].fans[0].name, 'Fan 1');
@@ -1023,25 +1023,25 @@ describe('model: populate:', function () {
 
           blogposts[1].fans = [fan3, fan4];
 
-          blogposts[1].save(function (err) {
+          blogposts[1].save(function(err) {
             assert.ifError(err);
 
             BlogPost
             .findById(blogposts[1]._id, '', {populate: ['fans']})
-            .exec(function (err, post) {
+            .exec(function(err, post) {
               assert.ifError(err);
 
               assert.equal(post.fans[0].name, 'Fan 3');
               assert.equal(post.fans[1].name, 'Fan 4');
 
               post.fans.splice(0, 1);
-              post.save(function (err) {
+              post.save(function(err) {
                 assert.ifError(err);
 
                 BlogPost
                 .findById(post._id)
                 .populate('fans')
-                .exec(function (err, post) {
+                .exec(function(err, post) {
                   db.close();
                   assert.ifError(err);
                   assert.equal(post.fans.length, 1);
@@ -1056,16 +1056,16 @@ describe('model: populate:', function () {
     });
   });
 
-  describe('populating sub docs', function () {
-    it('works with findById', function (done) {
+  describe('populating sub docs', function() {
+    it('works with findById', function(done) {
       var db = start(),
           BlogPost = db.model('RefBlogPost', posts),
           User = db.model('RefUser', users);
 
-      User.create({name: 'User 1'}, function (err, user1) {
+      User.create({name: 'User 1'}, function(err, user1) {
         assert.ifError(err);
 
-        User.create({name: 'User 2'}, function (err, user2) {
+        User.create({name: 'User 2'}, function(err, user2) {
           assert.ifError(err);
 
           BlogPost.create({
@@ -1075,14 +1075,14 @@ describe('model: populate:', function () {
               {_creator: user1._id, content: 'Woot woot'},
               {_creator: user2._id, content: 'Wha wha'}
             ]
-          }, function (err, post) {
+          }, function(err, post) {
             assert.ifError(err);
 
             BlogPost
             .findById(post._id)
             .populate('_creator')
             .populate('comments._creator')
-            .exec(function (err, post) {
+            .exec(function(err, post) {
               assert.ifError(err);
 
               assert.equal(post._creator.name, 'User 1');
@@ -1095,12 +1095,12 @@ describe('model: populate:', function () {
       });
     });
 
-    it('works when first doc returned has empty array for populated path (gh-1055)', function (done) {
+    it('works when first doc returned has empty array for populated path (gh-1055)', function(done) {
       var db = start(),
           BlogPost = db.model('RefBlogPost', posts),
           User = db.model('RefUser', users);
 
-      User.create({name: 'gh-1055-1'}, {name: 'gh-1055-2'}, function (err, user1, user2) {
+      User.create({name: 'gh-1055-1'}, {name: 'gh-1055-2'}, function(err, user1, user2) {
         assert.ifError(err);
 
         BlogPost.create({
@@ -1114,7 +1114,7 @@ describe('model: populate:', function () {
             {_creator: user1._id, content: 'Woot woot', asers: []},
             {_creator: user2._id, content: 'Wha wha', asers: [user1, user2]}
           ]
-        }, function (err) {
+        }, function(err) {
           assert.ifError(err);
 
           var ran = false;
@@ -1124,7 +1124,7 @@ describe('model: populate:', function () {
           .select('comments')
           .populate('comments._creator')
           .populate('comments.asers')
-          .exec(function (err, posts) {
+          .exec(function(err, posts) {
             assert.equal(false, ran);
             ran = true;
             assert.ifError(err);
@@ -1138,12 +1138,12 @@ describe('model: populate:', function () {
     });
   });
 
-  it('clears cache when array has been re-assigned (gh-2176)', function (done) {
+  it('clears cache when array has been re-assigned (gh-2176)', function(done) {
     var db = start();
     var BlogPost = db.model('RefBlogPost', posts, 'gh-2176-1');
     var User = db.model('RefUser', users, 'gh-2176-2');
 
-    User.create({name: 'aaron'}, {name: 'val'}, function (err, user1, user2) {
+    User.create({name: 'aaron'}, {name: 'val'}, function(err, user1, user2) {
       assert.ifError(err);
 
       BlogPost.create(
@@ -1152,21 +1152,21 @@ describe('model: populate:', function () {
           _creator: user1._id,
           comments: []
         },
-          function (err) {
+          function(err) {
             assert.ifError(err);
             BlogPost.
             find({title: 'gh-2176'}).
             populate('_creator').
-            exec(function (error, posts) {
+            exec(function(error, posts) {
               assert.ifError(error);
               assert.equal(1, posts.length);
               assert.equal('aaron', posts[0]._creator.name);
               posts[0]._creator = user2;
               assert.equal('val', posts[0]._creator.name);
-              posts[0].save(function (error, post) {
+              posts[0].save(function(error, post) {
                 assert.ifError(error);
                 assert.equal('val', post._creator.name);
-                posts[0].populate('_creator', function (error, doc) {
+                posts[0].populate('_creator', function(error, doc) {
                   assert.ifError(error);
                   assert.equal('val', doc._creator.name);
                   db.close(done);
@@ -1177,7 +1177,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating subdocuments partially', function (done) {
+  it('populating subdocuments partially', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -1185,13 +1185,13 @@ describe('model: populate:', function () {
     User.create({
       name: 'User 1',
       email: 'user1@learnboost.com'
-    }, function (err, user1) {
+    }, function(err, user1) {
       assert.ifError(err);
 
       User.create({
         name: 'User 2',
         email: 'user2@learnboost.com'
-      }, function (err, user2) {
+      }, function(err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
@@ -1200,13 +1200,13 @@ describe('model: populate:', function () {
             {_creator: user1, content: 'Woot woot'},
             {_creator: user2, content: 'Wha wha'}
           ]
-        }, function (err, post) {
+        }, function(err, post) {
           assert.ifError(err);
 
           BlogPost
           .findById(post._id)
           .populate('comments._creator', 'email')
-          .exec(function (err, post) {
+          .exec(function(err, post) {
             db.close();
             assert.ifError(err);
 
@@ -1222,7 +1222,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating subdocuments partially with conditions', function (done) {
+  it('populating subdocuments partially with conditions', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -1230,13 +1230,13 @@ describe('model: populate:', function () {
     User.create({
       name: 'User 1',
       email: 'user1@learnboost.com'
-    }, function (err, user1) {
+    }, function(err, user1) {
       assert.ifError(err);
 
       User.create({
         name: 'User 2',
         email: 'user2@learnboost.com'
-      }, function (err, user2) {
+      }, function(err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
@@ -1245,13 +1245,13 @@ describe('model: populate:', function () {
             {_creator: user1, content: 'Woot woot'},
             {_creator: user2, content: 'Wha wha'}
           ]
-        }, function (err, post) {
+        }, function(err, post) {
           assert.ifError(err);
 
           BlogPost
           .findById(post._id)
           .populate('comments._creator', {'email': 1}, {name: /User/})
-          .exec(function (err, post) {
+          .exec(function(err, post) {
             db.close();
             assert.ifError(err);
 
@@ -1267,7 +1267,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating subdocs with invalid/missing subproperties', function (done) {
+  it('populating subdocs with invalid/missing subproperties', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -1275,13 +1275,13 @@ describe('model: populate:', function () {
     User.create({
       name: 'T-100',
       email: 'terminator100@learnboost.com'
-    }, function (err) {
+    }, function(err) {
       assert.ifError(err);
 
       User.create({
         name: 'T-1000',
         email: 'terminator1000@learnboost.com'
-      }, function (err, user2) {
+      }, function(err, user2) {
         assert.ifError(err);
 
         BlogPost.create({
@@ -1290,20 +1290,20 @@ describe('model: populate:', function () {
             {_creator: null, content: 'Woot woot'},
             {_creator: user2, content: 'Wha wha'}
           ]
-        }, function (err, post) {
+        }, function(err, post) {
           assert.ifError(err);
 
           // non-existant subprop
           BlogPost
           .findById(post._id)
           .populate('comments._idontexist', 'email')
-          .exec(function (err) {
+          .exec(function(err) {
             assert.ifError(err);
 
             // add a non-schema property to the document.
             BlogPost.collection.update(
                 {_id: post._id}
-                , {$set: {'comments.0._idontexist': user2._id}}, function (err) {
+                , {$set: {'comments.0._idontexist': user2._id}}, function(err) {
                   assert.ifError(err);
 
                   // allow population of unknown property by passing model name.
@@ -1311,7 +1311,7 @@ describe('model: populate:', function () {
                   BlogPost
                   .findById(post._id)
                   .populate('comments._idontexist', 'email', 'RefUser')
-                  .exec(function (err, post) {
+                  .exec(function(err, post) {
                     assert.ifError(err);
                     assert.ok(post);
                     assert.equal(post.comments.length, 2);
@@ -1326,7 +1326,7 @@ describe('model: populate:', function () {
                     BlogPost
                     .findById(post._id)
                     .populate('comments._creator', 'email')
-                    .exec(function (err, post) {
+                    .exec(function(err, post) {
                       assert.ifError(err);
 
                       assert.ok(post.comments);
@@ -1347,7 +1347,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('properly handles limit per document (gh-2151)', function (done) {
+  it('properly handles limit per document (gh-2151)', function(done) {
     var db = start();
     var ObjectId = mongoose.Types.ObjectId;
 
@@ -1394,7 +1394,7 @@ describe('model: populate:', function () {
       friends: [userIds[0], userIds[1], userIds[2]]
     });
 
-    User.create(users, function (err) {
+    User.create(users, function(err) {
       assert.ifError(err);
 
       var blogposts = [];
@@ -1414,14 +1414,14 @@ describe('model: populate:', function () {
         author: userIds[2]
       });
 
-      BlogPost.create(blogposts, function (err) {
+      BlogPost.create(blogposts, function(err) {
         assert.ifError(err);
 
         BlogPost.
         find({tags: 'fun'}).
         lean().
         populate('author').
-        exec(function (err, docs) {
+        exec(function(err, docs) {
           assert.ifError(err);
           var opts = {
             path: 'author.friends',
@@ -1429,7 +1429,7 @@ describe('model: populate:', function () {
             options: {limit: 1}
           };
 
-          BlogPost.populate(docs, opts, function (err, docs) {
+          BlogPost.populate(docs, opts, function(err, docs) {
             assert.ifError(err);
             assert.equal(2, docs.length);
             assert.equal(1, docs[0].author.friends.length);
@@ -1441,20 +1441,20 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating subdocuments partially with empty array (gh-481)', function (done) {
+  it('populating subdocuments partially with empty array (gh-481)', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create({
       title: 'Woot',
       comments: [] // EMPTY ARRAY
-    }, function (err, post) {
+    }, function(err, post) {
       assert.ifError(err);
 
       BlogPost
       .findById(post._id)
       .populate('comments._creator', 'email')
-      .exec(function (err, returned) {
+      .exec(function(err, returned) {
         db.close();
         assert.ifError(err);
         assert.equal(returned.id, post.id);
@@ -1463,20 +1463,20 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating subdocuments partially with null array', function (done) {
+  it('populating subdocuments partially with null array', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts);
 
     BlogPost.create({
       title: 'Woot',
       comments: null
-    }, function (err, post) {
+    }, function(err, post) {
       assert.ifError(err);
 
       BlogPost
       .findById(post._id)
       .populate('comments._creator')
-      .exec(function (err, returned) {
+      .exec(function(err, returned) {
         db.close();
         assert.ifError(err);
         assert.equal(returned.id, post.id);
@@ -1485,29 +1485,29 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating subdocuments with array including nulls', function (done) {
+  it('populating subdocuments with array including nulls', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
     var user = new User({name: 'hans zimmer'});
-    user.save(function (err) {
+    user.save(function(err) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'Woot',
         fans: []
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         // shove some uncasted vals
-        BlogPost.collection.update({_id: post._id}, {$set: {fans: [null, undefined, user.id, null]}}, function (err) {
+        BlogPost.collection.update({_id: post._id}, {$set: {fans: [null, undefined, user.id, null]}}, function(err) {
           assert.ifError(err);
 
           BlogPost
           .findById(post._id)
           .populate('fans', 'name')
-          .exec(function (err, returned) {
+          .exec(function(err, returned) {
             db.close();
             assert.ifError(err);
             assert.equal(returned.id, post.id);
@@ -1519,7 +1519,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating more than one array at a time', function (done) {
+  it('populating more than one array at a time', function(done) {
     var db = start(),
         User = db.model('RefUser', users),
         M = db.model('PopMultiSubDocs', new Schema({
@@ -1536,7 +1536,7 @@ describe('model: populate:', function () {
       gender: 'female'
     }, {
       name: 'Fan 3'
-    }, function (err, fan1, fan2, fan3) {
+    }, function(err, fan1, fan2, fan3) {
       assert.ifError(err);
 
       M.create({
@@ -1553,14 +1553,14 @@ describe('model: populate:', function () {
           {_creator: fan3, content: 'hello'},
           {_creator: fan1, content: 'world'}
         ]
-      }, function (err, post1, post2) {
+      }, function(err, post1, post2) {
         assert.ifError(err);
 
         M.where('_id').in([post1, post2])
         .populate('fans', 'name', {gender: 'female'})
         .populate('users', 'name', {gender: 'male'})
         .populate('comments._creator', 'email', {name: null})
-        .exec(function (err, posts) {
+        .exec(function(err, posts) {
           db.close();
           assert.ifError(err);
 
@@ -1594,7 +1594,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating multiple children of a sub-array at a time', function (done) {
+  it('populating multiple children of a sub-array at a time', function(done) {
     var db = start(),
         User = db.model('RefUser', users),
         BlogPost = db.model('RefBlogPost', posts),
@@ -1616,14 +1616,14 @@ describe('model: populate:', function () {
       name: 'Fan 2',
       email: 'fan2@learnboost.com',
       gender: 'female'
-    }, function (err, fan1, fan2) {
+    }, function(err, fan1, fan2) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot'
       }, {
         title: 'yay'
-      }, function (err, post1, post2) {
+      }, function(err, post1, post2) {
         assert.ifError(err);
         M.create({
           kids: [
@@ -1631,13 +1631,13 @@ describe('model: populate:', function () {
             {user: fan2, post: post2, y: 8}
           ],
           x: 4
-        }, function (err, m1) {
+        }, function(err, m1) {
           assert.ifError(err);
 
           M.findById(m1)
           .populate('kids.user', 'name')
           .populate('kids.post', 'title', {title: 'woot'})
-          .exec(function (err, o) {
+          .exec(function(err, o) {
             db.close();
             assert.ifError(err);
             assert.strictEqual(o.kids.length, 2);
@@ -1656,7 +1656,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('passing sort options to the populate method', function (done) {
+  it('passing sort options to the populate method', function(done) {
     var db = start(),
         P = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
@@ -1666,15 +1666,15 @@ describe('model: populate:', function () {
         {name: 'fan2', age: 8},
         {name: 'someone else', age: 3},
         {name: 'val', age: 3},
-        function (err, fan1, fan2, fan3, fan4) {
+        function(err, fan1, fan2, fan3, fan4) {
           assert.ifError(err);
 
-          P.create({fans: [fan4, fan2, fan3, fan1]}, function (err, post) {
+          P.create({fans: [fan4, fan2, fan3, fan1]}, function(err, post) {
             assert.ifError(err);
 
             P.findById(post)
             .populate('fans', null, null, {sort: {age: 1, name: 1}})
-            .exec(function (err, post) {
+            .exec(function(err, post) {
               assert.ifError(err);
 
               assert.equal(post.fans.length, 4);
@@ -1685,7 +1685,7 @@ describe('model: populate:', function () {
 
               P.findById(post)
               .populate('fans', 'name', null, {sort: {'name': -1}})
-              .exec(function (err, post) {
+              .exec(function(err, post) {
                 assert.ifError(err);
 
                 assert.equal(post.fans.length, 4);
@@ -1700,7 +1700,7 @@ describe('model: populate:', function () {
 
                 P.findById(post)
                 .populate('fans', 'age', {age: {$gt: 3}}, {sort: {'name': 'desc'}})
-                .exec(function (err, post) {
+                .exec(function(err, post) {
                   db.close();
                   assert.ifError(err);
 
@@ -1716,7 +1716,7 @@ describe('model: populate:', function () {
         });
   });
 
-  it('limit should apply to each returned doc, not in aggregate (gh-1490)', function (done) {
+  it('limit should apply to each returned doc, not in aggregate (gh-1490)', function(done) {
     var db = start();
     var sB = new Schema({
       name: String
@@ -1755,7 +1755,7 @@ describe('model: populate:', function () {
     }
 
     function next() {
-      J.find().populate({path: 'b', options: {limit: 2}}).exec(function (err, j) {
+      J.find().populate({path: 'b', options: {limit: 2}}).exec(function(err, j) {
         assert.equal(j.length, 2);
         assert.equal(j[0].b.length, 2);
         assert.equal(j[1].b.length, 2);
@@ -1764,7 +1764,7 @@ describe('model: populate:', function () {
     }
   });
 
-  it('refs should cast to ObjectId from hexstrings', function (done) {
+  it('refs should cast to ObjectId from hexstrings', function(done) {
     var BP = mongoose.model('RefBlogPost', BlogPost);
     var bp = new BP;
     bp._creator = new DocObjectId().toString();
@@ -1774,7 +1774,7 @@ describe('model: populate:', function () {
     done();
   });
 
-  it('populate should work on String _ids', function (done) {
+  it('populate should work on String _ids', function(done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -1792,14 +1792,14 @@ describe('model: populate:', function () {
 
     var alice = new User({_id: 'alice', name: 'Alice'});
 
-    alice.save(function (err) {
+    alice.save(function(err) {
       assert.ifError(err);
 
       var note = new Note({author: 'alice', body: 'Buy Milk'});
-      note.save(function (err) {
+      note.save(function(err) {
         assert.ifError(err);
 
-        Note.findById(note.id).populate('author').exec(function (err, note) {
+        Note.findById(note.id).populate('author').exec(function(err, note) {
           db.close();
           assert.ifError(err);
           assert.equal(note.body, 'Buy Milk');
@@ -1811,7 +1811,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populate should work on Number _ids', function (done) {
+  it('populate should work on Number _ids', function(done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -1829,14 +1829,14 @@ describe('model: populate:', function () {
 
     var alice = new User({_id: 2359, name: 'Alice'});
 
-    alice.save(function (err) {
+    alice.save(function(err) {
       assert.ifError(err);
 
       var note = new Note({author: 2359, body: 'Buy Milk'});
-      note.save(function (err) {
+      note.save(function(err) {
         assert.ifError(err);
 
-        Note.findById(note.id).populate('author').exec(function (err, note) {
+        Note.findById(note.id).populate('author').exec(function(err, note) {
           db.close();
           assert.ifError(err);
           assert.equal(note.body, 'Buy Milk');
@@ -1848,7 +1848,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('required works on ref fields (gh-577)', function (done) {
+  it('required works on ref fields (gh-577)', function(done) {
     var db = start();
 
     var userSchema = new Schema({
@@ -1890,7 +1890,7 @@ describe('model: populate:', function () {
         text: 'test'
       });
 
-      comment.save(function (err) {
+      comment.save(function(err) {
         assert.equal('CommentWithRequiredField validation failed', err && err.message);
         assert.ok('num' in err.errors);
         assert.ok('str' in err.errors);
@@ -1903,7 +1903,7 @@ describe('model: populate:', function () {
         comment.num = 1995;
         comment.str = 'my string';
 
-        comment.save(function (err, comment) {
+        comment.save(function(err, comment) {
           assert.strictEqual(null, err);
 
           Comment
@@ -1911,12 +1911,12 @@ describe('model: populate:', function () {
           .populate('user')
           .populate('num')
           .populate('str')
-          .exec(function (err, comment) {
+          .exec(function(err, comment) {
             assert.ifError(err);
 
             comment.set({text: 'test2'});
 
-            comment.save(function (err) {
+            comment.save(function(err) {
               db.close();
               assert.ifError(err);
               done();
@@ -1927,7 +1927,7 @@ describe('model: populate:', function () {
     }
   });
 
-  it('populate works with schemas with both id and _id defined', function (done) {
+  it('populate works with schemas with both id and _id defined', function(done) {
     var db = start(),
         S1 = new Schema({id: String}),
         S2 = new Schema({things: [{type: ObjectId, ref: '_idAndid'}]});
@@ -1936,19 +1936,19 @@ describe('model: populate:', function () {
     var M2 = db.model('populateWorksWith_idAndidSchemas', S2);
 
     M1.create(
-        {id: "The Tiger That Isn't"}
+        {id: 'The Tiger That Isn\'t'}
         , {id: 'Users Guide To The Universe'}
-        , function (err, a, b) {
+        , function(err, a, b) {
           assert.ifError(err);
 
           var m2 = new M2({things: [a, b]});
-          m2.save(function (err) {
+          m2.save(function(err) {
             assert.ifError(err);
-            M2.findById(m2).populate('things').exec(function (err, doc) {
+            M2.findById(m2).populate('things').exec(function(err, doc) {
               db.close();
               assert.ifError(err);
               assert.equal(doc.things.length, 2);
-              assert.equal(doc.things[0].id, "The Tiger That Isn't");
+              assert.equal(doc.things[0].id, 'The Tiger That Isn\'t');
               assert.equal(doc.things[1].id, 'Users Guide To The Universe');
               done();
             });
@@ -1956,22 +1956,22 @@ describe('model: populate:', function () {
         });
   });
 
-  it('Update works with populated arrays (gh-602)', function (done) {
+  it('Update works with populated arrays (gh-602)', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
-    User.create({name: 'aphex'}, {name: 'twin'}, function (err, u1, u2) {
+    User.create({name: 'aphex'}, {name: 'twin'}, function(err, u1, u2) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'Woot',
         fans: []
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         var update = {fans: [u1, u2]};
-        BlogPost.update({_id: post}, update, function (err) {
+        BlogPost.update({_id: post}, update, function(err) {
           assert.ifError(err);
 
           // the original update doc should not be modified
@@ -1980,7 +1980,7 @@ describe('model: populate:', function () {
           assert.ok(update.fans[0] instanceof mongoose.Document);
           assert.ok(update.fans[1] instanceof mongoose.Document);
 
-          BlogPost.findById(post, function (err, post) {
+          BlogPost.findById(post, function(err, post) {
             db.close();
             assert.ifError(err);
             assert.equal(post.fans.length, 2);
@@ -1993,20 +1993,20 @@ describe('model: populate:', function () {
     });
   });
 
-  it('toJSON should also be called for refs (gh-675)', function (done) {
+  it('toJSON should also be called for refs (gh-675)', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefUser', users);
 
     User.prototype._toJSON = User.prototype.toJSON;
-    User.prototype.toJSON = function () {
+    User.prototype.toJSON = function() {
       var res = this._toJSON();
       res.was_in_to_json = true;
       return res;
     };
 
     BlogPost.prototype._toJSON = BlogPost.prototype.toJSON;
-    BlogPost.prototype.toJSON = function () {
+    BlogPost.prototype.toJSON = function() {
       var res = this._toJSON();
       res.was_in_to_json = true;
       return res;
@@ -2015,19 +2015,19 @@ describe('model: populate:', function () {
     User.create({
       name: 'Jerem',
       email: 'jerem@jolicloud.com'
-    }, function (err, creator) {
+    }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'Ping Pong',
         _creator: creator
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator')
-        .exec(function (err, post) {
+        .exec(function(err, post) {
           db.close();
           assert.ifError(err);
 
@@ -2040,7 +2040,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populate should work on Buffer _ids (gh-686)', function (done) {
+  it('populate should work on Buffer _ids (gh-686)', function(done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -2058,14 +2058,14 @@ describe('model: populate:', function () {
 
     var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: 'Alice'});
 
-    alice.save(function (err) {
+    alice.save(function(err) {
       assert.ifError(err);
 
       var note = new Note({author: 'alice', body: 'Buy Milk'});
-      note.save(function (err) {
+      note.save(function(err) {
         assert.ifError(err);
 
-        Note.findById(note.id).populate('author').exec(function (err, note) {
+        Note.findById(note.id).populate('author').exec(function(err, note) {
           db.close();
           assert.ifError(err);
           assert.equal(note.body, 'Buy Milk');
@@ -2077,7 +2077,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populated Buffer _ids should be requireable', function (done) {
+  it('populated Buffer _ids should be requireable', function(done) {
     var db = start();
 
     var UserSchema = new Schema({
@@ -2095,16 +2095,16 @@ describe('model: populate:', function () {
 
     var alice = new User({_id: new mongoose.Types.Buffer('YWxpY2U=', 'base64'), name: 'Alice'});
 
-    alice.save(function (err) {
+    alice.save(function(err) {
       assert.ifError(err);
 
       var note = new Note({author: 'alice', body: 'Buy Milk'});
-      note.save(function (err) {
+      note.save(function(err) {
         assert.ifError(err);
 
-        Note.findById(note.id).populate('author').exec(function (err, note) {
+        Note.findById(note.id).populate('author').exec(function(err, note) {
           assert.ifError(err);
-          note.save(function (err) {
+          note.save(function(err) {
             db.close();
             assert.ifError(err);
             done();
@@ -2114,7 +2114,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populating with custom model selection (gh-773)', function (done) {
+  it('populating with custom model selection (gh-773)', function(done) {
     var db = start(),
         BlogPost = db.model('RefBlogPost', posts),
         User = db.model('RefAlternateUser', users);
@@ -2122,19 +2122,19 @@ describe('model: populate:', function () {
     User.create({
       name: 'Daniel',
       email: 'daniel.baulig@gmx.de'
-    }, function (err, creator) {
+    }, function(err, creator) {
       assert.ifError(err);
 
       BlogPost.create({
         title: 'woot',
         _creator: creator
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
 
         BlogPost
         .findById(post._id)
         .populate('_creator', 'email', 'RefAlternateUser')
-        .exec(function (err, post) {
+        .exec(function(err, post) {
           db.close();
           assert.ifError(err);
 
@@ -2148,20 +2148,20 @@ describe('model: populate:', function () {
     });
   });
 
-  describe('specifying a custom model without specifying a ref in schema', function () {
-    it('with String _id', function (done) {
+  describe('specifying a custom model without specifying a ref in schema', function() {
+    it('with String _id', function(done) {
       var db = start();
       var A = db.model('A', {name: String, _id: String});
       var B = db.model('B', {other: String});
-      A.create({name: 'hello', _id: 'first'}, function (err, a) {
+      A.create({name: 'hello', _id: 'first'}, function(err, a) {
         if (err) {
           return done(err);
         }
-        B.create({other: a._id}, function (err, b) {
+        B.create({other: a._id}, function(err, b) {
           if (err) {
             return done(err);
           }
-          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function (err, b) {
+          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function(err, b) {
             db.close();
             if (err) {
               return done(err);
@@ -2172,19 +2172,19 @@ describe('model: populate:', function () {
         });
       });
     });
-    it('with Number _id', function (done) {
+    it('with Number _id', function(done) {
       var db = start();
       var A = db.model('A', {name: String, _id: Number});
       var B = db.model('B', {other: Number});
-      A.create({name: 'hello', _id: 3}, function (err, a) {
+      A.create({name: 'hello', _id: 3}, function(err, a) {
         if (err) {
           return done(err);
         }
-        B.create({other: a._id}, function (err, b) {
+        B.create({other: a._id}, function(err, b) {
           if (err) {
             return done(err);
           }
-          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function (err, b) {
+          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function(err, b) {
             db.close();
             if (err) {
               return done(err);
@@ -2195,19 +2195,19 @@ describe('model: populate:', function () {
         });
       });
     });
-    it('with Buffer _id', function (done) {
+    it('with Buffer _id', function(done) {
       var db = start();
       var A = db.model('A', {name: String, _id: Buffer});
       var B = db.model('B', {other: Buffer});
-      A.create({name: 'hello', _id: new Buffer('x')}, function (err, a) {
+      A.create({name: 'hello', _id: new Buffer('x')}, function(err, a) {
         if (err) {
           return done(err);
         }
-        B.create({other: a._id}, function (err, b) {
+        B.create({other: a._id}, function(err, b) {
           if (err) {
             return done(err);
           }
-          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function (err, b) {
+          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function(err, b) {
             db.close();
             if (err) {
               return done(err);
@@ -2218,19 +2218,19 @@ describe('model: populate:', function () {
         });
       });
     });
-    it('with ObjectId _id', function (done) {
+    it('with ObjectId _id', function(done) {
       var db = start();
       var A = db.model('A', {name: String});
       var B = db.model('B', {other: Schema.ObjectId});
-      A.create({name: 'hello'}, function (err, a) {
+      A.create({name: 'hello'}, function(err, a) {
         if (err) {
           return done(err);
         }
-        B.create({other: a._id}, function (err, b) {
+        B.create({other: a._id}, function(err, b) {
           if (err) {
             return done(err);
           }
-          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function (err, b) {
+          B.findById(b._id).populate({path: 'other', model: 'A'}).exec(function(err, b) {
             db.close();
             if (err) {
               return done(err);
@@ -2243,11 +2243,11 @@ describe('model: populate:', function () {
     });
   });
 
-  describe('specifying all params using an object', function () {
+  describe('specifying all params using an object', function() {
     var db, B, User;
     var post;
 
-    before(function (done) {
+    before(function(done) {
       db = start();
       B = db.model('RefBlogPost');
       User = db.model('RefAlternateUser');
@@ -2258,13 +2258,13 @@ describe('model: populate:', function () {
       }
           , {name: 'yup'}
           , {name: 'not here'}
-          , function (err, fan1, fan2, fan3) {
+          , function(err, fan1, fan2, fan3) {
             assert.ifError(err);
 
             B.create({
               title: 'woot',
               fans: [fan1, fan2, fan3]
-            }, function (err, post_) {
+            }, function(err, post_) {
               assert.ifError(err);
               post = post_;
               done();
@@ -2272,11 +2272,11 @@ describe('model: populate:', function () {
           });
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('works', function (done) {
+    it('works', function(done) {
       B.findById(post._id)
       .populate({
         path: 'fans',
@@ -2285,7 +2285,7 @@ describe('model: populate:', function () {
         match: {name: /u/},
         options: {sort: {'name': -1}}
       })
-      .exec(function (err, post) {
+      .exec(function(err, post) {
         assert.ifError(err);
 
         assert.ok(Array.isArray(post.fans));
@@ -2304,11 +2304,11 @@ describe('model: populate:', function () {
     });
   });
 
-  describe('Model.populate()', function () {
+  describe('Model.populate()', function() {
     var db, B, User;
     var user1, user2, post1, post2, _id;
 
-    before(function (done) {
+    before(function(done) {
       db = start();
       B = db.model('RefBlogPost', posts);
       User = db.model('RefAlternateUser', users);
@@ -2323,7 +2323,7 @@ describe('model: populate:', function () {
         name: 'Newark',
         email: 'ewr@nj.com',
         blogposts: [_id]
-      }, function (err, u1, u2) {
+      }, function(err, u1, u2) {
         assert.ifError(err);
 
         user1 = u1;
@@ -2337,7 +2337,7 @@ describe('model: populate:', function () {
           title: 'green eggs and ham',
           _creator: user2,
           fans: [user2, user1]
-        }, function (err, p1, p2) {
+        }, function(err, p1, p2) {
           assert.ifError(err);
           post1 = p1;
           post2 = p2;
@@ -2346,12 +2346,12 @@ describe('model: populate:', function () {
       });
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    describe('returns', function () {
-      it('a promise', function (done) {
+    describe('returns', function() {
+      it('a promise', function(done) {
         var p = B.populate(post1, '_creator');
         assert.ok(p instanceof mongoose.Promise);
         p.then(success, done).end();
@@ -2362,11 +2362,11 @@ describe('model: populate:', function () {
       });
     });
 
-    describe('of individual document', function () {
-      it('works', function (done) {
-        B.findById(post1._id, function (error, post1) {
+    describe('of individual document', function() {
+      it('works', function(done) {
+        B.findById(post1._id, function(error, post1) {
           var ret = utils.populate({path: '_creator', model: 'RefAlternateUser'});
-          B.populate(post1, ret, function (err, post) {
+          B.populate(post1, ret, function(err, post) {
             assert.ifError(err);
             assert.ok(post);
             assert.ok(post._creator instanceof User);
@@ -2377,12 +2377,12 @@ describe('model: populate:', function () {
       });
     });
 
-    describe('a document already populated', function () {
-      describe('when paths are not modified', function () {
-        it('works', function (done) {
-          B.findById(post1._id, function (err, doc) {
+    describe('a document already populated', function() {
+      describe('when paths are not modified', function() {
+        it('works', function(done) {
+          B.findById(post1._id, function(err, doc) {
             assert.ifError(err);
-            B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function (err, post) {
+            B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function(err, post) {
               assert.ifError(err);
               assert.ok(post);
               assert.ok(post._creator instanceof User);
@@ -2394,7 +2394,7 @@ describe('model: populate:', function () {
               assert.equal(String(post._creator._id), String(post.populated('_creator')));
               assert.ok(Array.isArray(post.populated('fans')));
 
-              B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function (err, post) {
+              B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function(err, post) {
                 assert.ifError(err);
                 assert.ok(post);
                 assert.ok(post._creator instanceof User);
@@ -2412,11 +2412,11 @@ describe('model: populate:', function () {
           });
         });
       });
-      describe('when paths are modified', function () {
-        it('works', function (done) {
-          B.findById(post1._id, function (err, doc) {
+      describe('when paths are modified', function() {
+        it('works', function(done) {
+          B.findById(post1._id, function(err, doc) {
             assert.ifError(err);
-            B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function (err, post) {
+            B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function(err, post) {
               assert.ifError(err);
               assert.ok(post);
               assert.ok(post._creator instanceof User);
@@ -2432,7 +2432,7 @@ describe('model: populate:', function () {
               doc.markModified('_creator');
               doc.markModified('fans');
 
-              B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function (err, post) {
+              B.populate(doc, [{path: '_creator', model: 'RefAlternateUser'}, {path: 'fans', model: 'RefAlternateUser'}], function(err, post) {
                 assert.ifError(err);
                 assert.ok(post);
                 assert.ok(post._creator instanceof User);
@@ -2456,14 +2456,14 @@ describe('model: populate:', function () {
       });
     });
 
-    describe('of multiple documents', function () {
-      it('works', function (done) {
-        B.findById(post1._id, function (error, post1) {
+    describe('of multiple documents', function() {
+      it('works', function(done) {
+        B.findById(post1._id, function(error, post1) {
           assert.ifError(error);
-          B.findById(post2._id, function (error, post2) {
+          B.findById(post2._id, function(error, post2) {
             assert.ifError(error);
             var ret = utils.populate({path: '_creator', model: 'RefAlternateUser'});
-            B.populate([post1, post2], ret, function (err, posts) {
+            B.populate([post1, post2], ret, function(err, posts) {
               assert.ifError(err);
               assert.ok(posts);
               assert.equal(2, posts.length);
@@ -2481,8 +2481,8 @@ describe('model: populate:', function () {
     });
   });
 
-  describe('populating combined with lean (gh-1260)', function () {
-    it('with findOne', function (done) {
+  describe('populating combined with lean (gh-1260)', function() {
+    it('with findOne', function(done) {
       var db = start(),
           BlogPost = db.model('RefBlogPost', posts + random()),
           User = db.model('RefUser', users + random());
@@ -2490,20 +2490,20 @@ describe('model: populate:', function () {
       User.create({
         name: 'Guillermo',
         email: 'rauchg@gmail.com'
-      }, function (err, creator) {
+      }, function(err, creator) {
         assert.ifError(err);
 
         BlogPost.create({
           title: 'woot',
           _creator: creator
-        }, function (err, post) {
+        }, function(err, post) {
           assert.ifError(err);
 
           BlogPost
           .findById(post._id)
           .lean()
           .populate('_creator')
-          .exec(function (err, post) {
+          .exec(function(err, post) {
             db.close();
             assert.ifError(err);
 
@@ -2517,7 +2517,7 @@ describe('model: populate:', function () {
       });
     });
 
-    it('with find', function (done) {
+    it('with find', function(done) {
       var db = start(),
           BlogPost = db.model('RefBlogPost', posts + random()),
           User = db.model('RefUser', users + random());
@@ -2528,7 +2528,7 @@ describe('model: populate:', function () {
       }, {
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function (err, fan1, fan2) {
+      }, function(err, fan1, fan2) {
         assert.ifError(err);
 
         BlogPost.create({
@@ -2537,14 +2537,14 @@ describe('model: populate:', function () {
         }, {
           title: 'Woot2',
           fans: [fan2, fan1]
-        }, function (err, post1, post2) {
+        }, function(err, post1, post2) {
           assert.ifError(err);
 
           BlogPost
           .find({_id: {$in: [post1._id, post2._id]}})
           .populate('fans')
           .lean()
-          .exec(function (err, blogposts) {
+          .exec(function(err, blogposts) {
             assert.ifError(err);
 
             assert.equal(blogposts[0].fans[0].name, 'Fan 1');
@@ -2567,14 +2567,14 @@ describe('model: populate:', function () {
     });
   });
 
-  describe('records paths and _ids used in population', function () {
+  describe('records paths and _ids used in population', function() {
     var db;
     var B;
     var U;
     var u1, u2;
     var b1;
 
-    before(function (done) {
+    before(function(done) {
       db = start();
       B = db.model('RefBlogPost', posts + random());
       U = db.model('RefUser', users + random());
@@ -2585,7 +2585,7 @@ describe('model: populate:', function () {
       }, {
         name: 'Fan 2',
         email: 'fan2@learnboost.com'
-      }, function (err, fan1, fan2) {
+      }, function(err, fan1, fan2) {
         assert.ifError(err);
         u1 = fan1;
         u2 = fan2;
@@ -2598,7 +2598,7 @@ describe('model: populate:', function () {
           title: 'Woot2',
           fans: [fan2, fan1],
           _creator: fan2
-        }, function (err, post) {
+        }, function(err, post) {
           assert.ifError(err);
           b1 = post;
           done();
@@ -2606,12 +2606,12 @@ describe('model: populate:', function () {
       });
     });
 
-    after(function () {
+    after(function() {
       db.close();
     });
 
-    it('with findOne', function (done) {
-      B.findById(b1).populate('fans _creator').exec(function (err, doc) {
+    it('with findOne', function(done) {
+      B.findById(b1).populate('fans _creator').exec(function(err, doc) {
         assert.ifError(err);
         assert.ok(Array.isArray(doc.populated('fans')));
         assert.equal(2, doc.populated('fans').length);
@@ -2622,8 +2622,8 @@ describe('model: populate:', function () {
       });
     });
 
-    it('with find', function (done) {
-      B.find().sort('title').populate('fans _creator').exec(function (err, docs) {
+    it('with find', function(done) {
+      B.find().sort('title').populate('fans _creator').exec(function(err, docs) {
         assert.ifError(err);
         assert.equal(2, docs.length);
 
@@ -2647,9 +2647,9 @@ describe('model: populate:', function () {
     });
   });
 
-  describe('deselecting _id', function () {
+  describe('deselecting _id', function() {
     var db, C, U, c1, c2;
-    before(function (done) {
+    before(function(done) {
       db = start();
 
       C = db.model('Comment', Schema({
@@ -2662,7 +2662,7 @@ describe('model: populate:', function () {
         comment: {type: Schema.ObjectId, ref: 'Comment'}
       }), 'users_' + random());
 
-      C.create({body: 'comment 1', title: '1'}, {body: 'comment 2', title: 2}, function (err, c1_, c2_) {
+      C.create({body: 'comment 1', title: '1'}, {body: 'comment 2', title: 2}, function(err, c1_, c2_) {
         assert.ifError(err);
         c1 = c1_;
         c2 = c2_;
@@ -2670,46 +2670,46 @@ describe('model: populate:', function () {
         U.create(
             {name: 'u1', comments: [c1, c2], comment: c1}
             , {name: 'u2', comment: c2}
-            , function (err) {
+            , function(err) {
               assert.ifError(err);
               done();
             });
       });
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    describe('in a subdocument', function () {
-      it('works', function (done) {
-        U.find({name: 'u1'}).populate('comments', {_id: 0}).exec(function (err, docs) {
+    describe('in a subdocument', function() {
+      it('works', function(done) {
+        U.find({name: 'u1'}).populate('comments', {_id: 0}).exec(function(err, docs) {
           assert.ifError(err);
 
           var doc = docs[0];
           assert.ok(Array.isArray(doc.comments), 'comments should be an array: ' + JSON.stringify(doc));
           assert.equal(2, doc.comments.length, 'invalid comments length for ' + JSON.stringify(doc));
-          doc.comments.forEach(function (d) {
+          doc.comments.forEach(function(d) {
             assert.equal(undefined, d._id);
             assert.equal(-1, Object.keys(d._doc).indexOf('_id'));
             assert.ok(d.body.length);
             assert.equal('number', typeof d._doc.__v);
           });
 
-          U.findOne({name: 'u1'}).populate('comments', 'title -_id').exec(function (err, doc) {
+          U.findOne({name: 'u1'}).populate('comments', 'title -_id').exec(function(err, doc) {
             assert.ifError(err);
             assert.equal(2, doc.comments.length);
-            doc.comments.forEach(function (d) {
+            doc.comments.forEach(function(d) {
               assert.equal(undefined, d._id);
               assert.equal(-1, Object.keys(d._doc).indexOf('_id'));
               assert.ok(d.title.length);
               assert.equal(undefined, d.body);
               assert.equal(typeof d._doc.__v, 'undefined');
             });
-            U.findOne({name: 'u1'}).populate('comments', '-_id').exec(function (err, doc) {
+            U.findOne({name: 'u1'}).populate('comments', '-_id').exec(function(err, doc) {
               assert.ifError(err);
               assert.equal(2, doc.comments.length);
-              doc.comments.forEach(function (d) {
+              doc.comments.forEach(function(d) {
                 assert.equal(undefined, d._id);
                 assert.equal(-1, Object.keys(d._doc).indexOf('_id'));
                 assert.ok(d.title.length);
@@ -2722,22 +2722,22 @@ describe('model: populate:', function () {
         });
       });
 
-      it('with lean', function (done) {
-        U.find({name: 'u1'}).lean().populate({path: 'comments', select: {_id: 0}, options: {lean: true}}).exec(function (err, docs) {
+      it('with lean', function(done) {
+        U.find({name: 'u1'}).lean().populate({path: 'comments', select: {_id: 0}, options: {lean: true}}).exec(function(err, docs) {
           assert.ifError(err);
 
           var doc = docs[0];
           assert.equal(2, doc.comments.length);
-          doc.comments.forEach(function (d) {
+          doc.comments.forEach(function(d) {
             assert.ok(!('_id' in d));
             assert.ok(d.body.length);
             assert.equal('number', typeof d.__v);
           });
 
-          U.findOne({name: 'u1'}).lean().populate('comments', '-_id', null, {lean: true}).exec(function (err, doc) {
+          U.findOne({name: 'u1'}).lean().populate('comments', '-_id', null, {lean: true}).exec(function(err, doc) {
             assert.ifError(err);
             assert.equal(2, doc.comments.length);
-            doc.comments.forEach(function (d) {
+            doc.comments.forEach(function(d) {
               assert.ok(!('_id' in d));
               assert.ok(d.body.length);
               assert.equal('number', typeof d.__v);
@@ -2748,15 +2748,15 @@ describe('model: populate:', function () {
       });
     });
 
-    describe('of documents being populated', function () {
-      it('still works (gh-1441)', function (done) {
+    describe('of documents being populated', function() {
+      it('still works (gh-1441)', function(done) {
         U.find()
         .select('-_id comment name')
-        .populate('comment', {_id: 0}).exec(function (err, docs) {
+        .populate('comment', {_id: 0}).exec(function(err, docs) {
           assert.ifError(err);
           assert.equal(2, docs.length);
 
-          docs.forEach(function (doc) {
+          docs.forEach(function(doc) {
             assert.ok(doc.comment && doc.comment.body);
             if (doc.name === 'u1') {
               assert.equal('comment 1', doc.comment.body);
@@ -2771,7 +2771,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('maps results back to correct document (gh-1444)', function (done) {
+  it('maps results back to correct document (gh-1444)', function(done) {
     var db = start();
 
     var articleSchema = new Schema({
@@ -2786,22 +2786,22 @@ describe('model: populate:', function () {
     });
     var Media = db.model('1444-Media', mediaSchema);
 
-    Media.create({filename: 'one'}, function (err, media) {
+    Media.create({filename: 'one'}, function(err, media) {
       assert.ifError(err);
 
       Article.create(
           {body: 'body1', author: 'a'}
           , {body: 'body2', author: 'a', mediaAttach: media._id}
-          , {body: 'body3', author: 'a'}, function (err) {
+          , {body: 'body3', author: 'a'}, function(err) {
             if (err) {
               return done(err);
             }
 
-            Article.find().populate('mediaAttach').exec(function (err, docs) {
+            Article.find().populate('mediaAttach').exec(function(err, docs) {
               db.close();
               assert.ifError(err);
 
-              var a2 = docs.filter(function (d) {
+              var a2 = docs.filter(function(d) {
                 return d.body === 'body2';
               })[0];
               assert.equal(a2.mediaAttach.id, media.id);
@@ -2812,13 +2812,13 @@ describe('model: populate:', function () {
     });
   });
 
-  describe('DynRef', function () {
+  describe('DynRef', function() {
     var db;
     var Review;
     var Item1;
     var Item2;
 
-    before(function (done) {
+    before(function(done) {
       db = start();
       var reviewSchema = new Schema({
         _id: Number,
@@ -2866,15 +2866,15 @@ describe('model: populate:', function () {
         items: [{id: 1, type: 'dynrefItem1'}, {id: 2, type: 'dynrefItem2'}]
       };
 
-      Item1.create({_id: 1, name: 'Val'}, function (err) {
+      Item1.create({_id: 1, name: 'Val'}, function(err) {
         if (err) {
           return done(err);
         }
-        Item2.create({_id: 2, otherName: 'Val'}, function (err) {
+        Item2.create({_id: 2, otherName: 'Val'}, function(err) {
           if (err) {
             return done(err);
           }
-          Review.create(review, function (err) {
+          Review.create(review, function(err) {
             if (err) {
               return done(err);
             }
@@ -2884,12 +2884,12 @@ describe('model: populate:', function () {
       });
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('Simple populate', function (done) {
-      Review.find({}).populate('item.id').exec(function (err, results) {
+    it('Simple populate', function(done) {
+      Review.find({}).populate('item.id').exec(function(err, results) {
         assert.ifError(err);
         assert.equal(1, results.length);
         var result = results[0];
@@ -2898,8 +2898,8 @@ describe('model: populate:', function () {
       });
     });
 
-    it('Array populate', function (done) {
-      Review.find({}).populate('items.id').exec(function (err, results) {
+    it('Array populate', function(done) {
+      Review.find({}).populate('items.id').exec(function(err, results) {
         assert.ifError(err);
         assert.equal(1, results.length);
         var result = results[0];
@@ -2911,24 +2911,24 @@ describe('model: populate:', function () {
     });
   });
 
-  describe('leaves Documents within Mixed properties alone (gh-1471)', function () {
+  describe('leaves Documents within Mixed properties alone (gh-1471)', function() {
     var db;
     var Cat;
     var Litter;
 
-    before(function () {
+    before(function() {
       db = start();
       Cat = db.model('cats', new Schema({name: String}));
       var litterSchema = new Schema({name: String, cats: {}, o: {}, a: []});
       Litter = db.model('litters', litterSchema);
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('when saving new docs', function (done) {
-      Cat.create({name: 'new1'}, {name: 'new2'}, {name: 'new3'}, function (err, a, b, c) {
+    it('when saving new docs', function(done) {
+      Cat.create({name: 'new1'}, {name: 'new2'}, {name: 'new3'}, function(err, a, b, c) {
         if (err) {
           return done(err);
         }
@@ -2942,13 +2942,13 @@ describe('model: populate:', function () {
       });
     });
 
-    it('when saving existing docs 5T5', function (done) {
-      Cat.create({name: 'ex1'}, {name: 'ex2'}, {name: 'ex3'}, function (err, a, b, c) {
+    it('when saving existing docs 5T5', function(done) {
+      Cat.create({name: 'ex1'}, {name: 'ex2'}, {name: 'ex3'}, function(err, a, b, c) {
         if (err) {
           return done(err);
         }
 
-        Litter.create({name: 'existing'}, function (err, doc) {
+        Litter.create({name: 'existing'}, function(err, doc) {
           doc.cats = [a];
           doc.o = b;
           doc.a = [c];
@@ -2958,11 +2958,11 @@ describe('model: populate:', function () {
     });
 
     function confirm(done) {
-      return function (err, litter) {
+      return function(err, litter) {
         if (err) {
           return done(err);
         }
-        Litter.findById(litter).lean().exec(function (err, doc) {
+        Litter.findById(litter).lean().exec(function(err, doc) {
           if (err) {
             return done(err);
           }
@@ -2977,8 +2977,8 @@ describe('model: populate:', function () {
     }
   });
 
-  describe('gh-2252', function () {
-    it('handles skip', function (done) {
+  describe('gh-2252', function() {
+    it('handles skip', function(done) {
       var db = start();
 
       var movieSchema = new Schema({});
@@ -2987,14 +2987,14 @@ describe('model: populate:', function () {
       var Movie = db.model('gh-2252-1', movieSchema);
       var Category = db.model('gh-2252-2', categorySchema);
 
-      Movie.create({}, {}, {}, function (error) {
+      Movie.create({}, {}, {}, function(error) {
         assert.ifError(error);
-        Movie.find({}, function (error, docs) {
+        Movie.find({}, function(error, docs) {
           assert.ifError(error);
           assert.equal(docs.length, 3);
-          Category.create({movies: [docs[0]._id, docs[1]._id, docs[2]._id]}, function (error) {
+          Category.create({movies: [docs[0]._id, docs[1]._id, docs[2]._id]}, function(error) {
             assert.ifError(error);
-            Category.findOne({}).populate({path: 'movies', options: {limit: 2, skip: 1}}).exec(function (error, category) {
+            Category.findOne({}).populate({path: 'movies', options: {limit: 2, skip: 1}}).exec(function(error, category) {
               assert.ifError(error);
               assert.equal(2, category.movies.length);
               db.close(done);
@@ -3005,7 +3005,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('handles slice (gh-1934)', function (done) {
+  it('handles slice (gh-1934)', function(done) {
     var db = start();
 
     var movieSchema = new Schema({title: String, actors: [String]});
@@ -3018,11 +3018,11 @@ describe('model: populate:', function () {
       {title: 'Pacific Rim', actors: ['Charlie Hunnam', 'Idris Elba']},
       {title: 'Man of Steel', actors: ['Henry Cavill', 'Amy Adams']}
     ];
-    Movie.create(movies[0], movies[1], movies[2], function (error, m1, m2, m3) {
+    Movie.create(movies[0], movies[1], movies[2], function(error, m1, m2, m3) {
       assert.ifError(error);
-      Category.create({movies: [m1._id, m2._id, m3._id]}, function (error) {
+      Category.create({movies: [m1._id, m2._id, m3._id]}, function(error) {
         assert.ifError(error);
-        Category.findOne({}).populate({path: 'movies', options: {slice: {actors: 1}}}).exec(function (error, category) {
+        Category.findOne({}).populate({path: 'movies', options: {slice: {actors: 1}}}).exec(function(error, category) {
           assert.ifError(error);
           assert.equal(category.movies.length, 3);
           assert.equal(category.movies[0].actors.length, 1);
@@ -3034,7 +3034,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('handles toObject() (gh-3279)', function (done) {
+  it('handles toObject() (gh-3279)', function(done) {
     var db = start();
 
     var teamSchema = new Schema({
@@ -3046,7 +3046,7 @@ describe('model: populate:', function () {
 
     var calls = 0;
     teamSchema.set('toJSON', {
-      transform: function (doc, ret) {
+      transform: function(doc, ret) {
         ++calls;
         return ret;
       }
@@ -3060,7 +3060,7 @@ describe('model: populate:', function () {
     });
 
     userSchema.set('toJSON', {
-      transform: function (doc, ret) {
+      transform: function(doc, ret) {
         return ret;
       }
     });
@@ -3069,13 +3069,13 @@ describe('model: populate:', function () {
 
     var user = new User({username: 'Test'});
 
-    user.save(function (err) {
+    user.save(function(err) {
       assert.ifError(err);
       var team = new Team({members: [{user: user}]});
 
-      team.save(function (err) {
+      team.save(function(err) {
         assert.ifError(err);
-        team.populate('members.user', function () {
+        team.populate('members.user', function() {
           team.toJSON();
           assert.equal(calls, 1);
           done();
@@ -3084,7 +3084,7 @@ describe('model: populate:', function () {
     });
   });
 
-  it('populate option (gh-2321)', function (done) {
+  it('populate option (gh-2321)', function(done) {
     var db = start();
 
     var User = db.model('User', {name: String});
@@ -3093,17 +3093,17 @@ describe('model: populate:', function () {
       name: String
     });
 
-    User.create({name: 'Val'}, function (error, user) {
+    User.create({name: 'Val'}, function(error, user) {
       assert.ifError(error);
-      Group.create({users: [user._id], name: 'test'}, function (error, group) {
+      Group.create({users: [user._id], name: 'test'}, function(error, group) {
         assert.ifError(error);
         test(group._id);
       });
     });
 
-    var test = function (id) {
+    var test = function(id) {
       var options = {populate: {path: 'users', model: 'User'}};
-      Group.find({_id: id}, '-name', options, function (error, group) {
+      Group.find({_id: id}, '-name', options, function(error, group) {
         assert.ifError(error);
         assert.ok(group[0].users[0]._id);
         db.close(done);
diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js
index 78523c9a12a..10929cb2e2f 100644
--- a/test/model.query.casting.test.js
+++ b/test/model.query.casting.test.js
@@ -54,8 +54,8 @@ var geoSchemaArray = new Schema({loc: {type: [Number], index: '2d'}});
 var geoSchemaObject = new Schema({loc: {long: Number, lat: Number}});
 geoSchemaObject.index({'loc': '2d'});
 
-describe('model query casting', function () {
-  it('works', function (done) {
+describe('model query casting', function() {
+  it('works', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         title = 'Loki ' + random();
@@ -65,10 +65,10 @@ describe('model query casting', function () {
 
     post.set('title', title);
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
-      BlogPostB.findOne({_id: id}, function (err, doc) {
+      BlogPostB.findOne({_id: id}, function(err, doc) {
         assert.ifError(err);
         assert.equal(title, doc.get('title'));
         db.close(done);
@@ -76,18 +76,18 @@ describe('model query casting', function () {
     });
   });
 
-  it('returns cast errors', function (done) {
+  it('returns cast errors', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
-    BlogPostB.find({date: 'invalid date'}, function (err) {
+    BlogPostB.find({date: 'invalid date'}, function(err) {
       assert.ok(err instanceof Error);
       assert.ok(err instanceof CastError);
       db.close(done);
     });
   });
 
-  it('casts $modifiers', function (done) {
+  it('casts $modifiers', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection),
         post = new BlogPostB({
@@ -96,11 +96,11 @@ describe('model query casting', function () {
           }
         });
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
       BlogPostB.find({'meta.visitors': {$gt: '-100', $lt: -50}},
-          function (err, found) {
+          function(err, found) {
             assert.ifError(err);
 
             assert.ok(found);
@@ -112,17 +112,17 @@ describe('model query casting', function () {
     });
   });
 
-  it('casts $in values of arrays (gh-199)', function (done) {
+  it('casts $in values of arrays (gh-199)', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
     var post = new BlogPostB(),
         id = post._id.toString();
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
-      BlogPostB.findOne({_id: {$in: [id]}}, function (err, doc) {
+      BlogPostB.findOne({_id: {$in: [id]}}, function(err, doc) {
         assert.ifError(err);
 
         assert.equal(doc._id.toString(), id);
@@ -131,17 +131,17 @@ describe('model query casting', function () {
     });
   });
 
-  it('casts $in values of arrays with single item instead of array (jrl-3238)', function (done) {
+  it('casts $in values of arrays with single item instead of array (jrl-3238)', function(done) {
     var db = start(),
         BlogPostB = db.model(modelName, collection);
 
     var post = new BlogPostB(),
         id = post._id.toString();
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
-      BlogPostB.findOne({_id: {$in: id}}, function (err, doc) {
+      BlogPostB.findOne({_id: {$in: id}}, function(err, doc) {
         assert.ifError(err);
 
         assert.equal(doc._id.toString(), id);
@@ -151,7 +151,7 @@ describe('model query casting', function () {
     });
   });
 
-  it('casts $nin values of arrays (gh-232)', function (done) {
+  it('casts $nin values of arrays (gh-232)', function(done) {
     var db = start(),
         NinSchema = new Schema({
           num: Number
@@ -161,13 +161,13 @@ describe('model query casting', function () {
 
     var Nin = db.model('Nin', 'nins_' + random());
 
-    Nin.create({num: 1}, function (err) {
+    Nin.create({num: 1}, function(err) {
       assert.ifError(err);
-      Nin.create({num: 2}, function (err) {
+      Nin.create({num: 2}, function(err) {
         assert.ifError(err);
-        Nin.create({num: 3}, function (err) {
+        Nin.create({num: 3}, function(err) {
           assert.ifError(err);
-          Nin.find({num: {$nin: [2]}}, function (err, found) {
+          Nin.find({num: {$nin: [2]}}, function(err, found) {
             assert.ifError(err);
             assert.equal(2, found.length);
             db.close(done);
@@ -177,7 +177,7 @@ describe('model query casting', function () {
     });
   });
 
-  it('works when finding by Date (gh-204)', function (done) {
+  it('works when finding by Date (gh-204)', function(done) {
     var db = start(),
         P = db.model(modelName, collection);
 
@@ -185,17 +185,17 @@ describe('model query casting', function () {
 
     post.meta.date = new Date();
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
-      P.findOne({_id: post._id, 'meta.date': {$lte: Date.now()}}, function (err, doc) {
+      P.findOne({_id: post._id, 'meta.date': {$lte: Date.now()}}, function(err, doc) {
         assert.ifError(err);
 
         assert.equal(doc._id.toString(), post._id.toString());
         doc.meta.date = null;
-        doc.save(function (err) {
+        doc.save(function(err) {
           assert.ifError(err);
-          P.findById(doc._id, function (err, doc) {
+          P.findById(doc._id, function(err, doc) {
             assert.ifError(err);
             assert.strictEqual(doc.meta.date, null);
             db.close(done);
@@ -205,14 +205,14 @@ describe('model query casting', function () {
     });
   });
 
-  it('works with $type matching', function (done) {
+  it('works with $type matching', function(done) {
     var db = start(),
         B = db.model(modelName, collection);
 
-    B.find({title: {$type: 'asd'}}, function (err) {
+    B.find({title: {$type: 'asd'}}, function(err) {
       assert.equal(err.message, '$type parameter must be Number');
 
-      B.find({title: {$type: 2}}, function (err, posts) {
+      B.find({title: {$type: 2}}, function(err, posts) {
         assert.ifError(err);
         assert.strictEqual(Array.isArray(posts), true);
         db.close(done);
@@ -220,14 +220,14 @@ describe('model query casting', function () {
     });
   });
 
-  it('works when finding Boolean with $in (gh-998)', function (done) {
+  it('works when finding Boolean with $in (gh-998)', function(done) {
     var db = start(),
         B = db.model(modelName, collection);
 
     var b = new B({published: true});
-    b.save(function (err) {
+    b.save(function(err) {
       assert.ifError(err);
-      B.find({_id: b._id, boolean: {$in: [null, true]}}, function (err, doc) {
+      B.find({_id: b._id, boolean: {$in: [null, true]}}, function(err, doc) {
         assert.ifError(err);
         assert.ok(doc);
         assert.equal(doc[0].id, b.id);
@@ -236,14 +236,14 @@ describe('model query casting', function () {
     });
   });
 
-  it('works when finding Boolean with $ne (gh-1093)', function (done) {
+  it('works when finding Boolean with $ne (gh-1093)', function(done) {
     var db = start(),
         B = db.model(modelName, collection + random());
 
     var b = new B({published: false});
-    b.save(function (err) {
+    b.save(function(err) {
       assert.ifError(err);
-      B.find().ne('published', true).exec(function (err, doc) {
+      B.find().ne('published', true).exec(function(err, doc) {
         assert.ifError(err);
         assert.ok(doc);
         assert.equal(doc[0].id, b.id);
@@ -252,7 +252,7 @@ describe('model query casting', function () {
     });
   });
 
-  it('properly casts $and (gh-1180)', function (done) {
+  it('properly casts $and (gh-1180)', function(done) {
     var db = start(),
         B = db.model(modelName, collection + random()),
         result = B.find({}).cast(B, {$and: [{date: '1987-03-17T20:00:00.000Z'}, {_id: '000000000000000000000000'}]});
@@ -261,10 +261,10 @@ describe('model query casting', function () {
     db.close(done);
   });
 
-  describe('$near', function () {
+  describe('$near', function() {
     this.slow(60);
 
-    it('with arrays', function (done) {
+    it('with arrays', function(done) {
       var db = start(),
           Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
@@ -285,7 +285,7 @@ describe('model query casting', function () {
       }
 
       function test() {
-        Test.find({loc: {$near: ['30', '40']}}, function (err, docs) {
+        Test.find({loc: {$near: ['30', '40']}}, function(err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -294,7 +294,7 @@ describe('model query casting', function () {
       }
     });
 
-    it('with objects', function (done) {
+    it('with objects', function(done) {
       var db = start(),
           Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
@@ -312,7 +312,7 @@ describe('model query casting', function () {
       }
 
       function test() {
-        Test.find({loc: {$near: ['30', '40'], $maxDistance: 51}}, function (err, docs) {
+        Test.find({loc: {$near: ['30', '40'], $maxDistance: 51}}, function(err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -324,7 +324,7 @@ describe('model query casting', function () {
       Test.once('index', complete);
     });
 
-    it('with nested objects', function (done) {
+    it('with nested objects', function(done) {
       var db = start();
       var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
       geoSchemaObject.index({'loc.nested': '2d'});
@@ -345,7 +345,7 @@ describe('model query casting', function () {
       }
 
       function test() {
-        Test.find({'loc.nested': {$near: ['30', '40'], $maxDistance: '50'}}, function (err, docs) {
+        Test.find({'loc.nested': {$near: ['30', '40'], $maxDistance: '50'}}, function(err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(1, docs.length);
@@ -361,10 +361,10 @@ describe('model query casting', function () {
     });
   });
 
-  describe('$nearSphere', function () {
+  describe('$nearSphere', function() {
     this.slow(70);
 
-    it('with arrays', function (done) {
+    it('with arrays', function(done) {
       var db = start(),
           Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
@@ -384,7 +384,7 @@ describe('model query casting', function () {
       Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
       function test() {
-        Test.find({loc: {$nearSphere: ['30', '40']}}, function (err, docs) {
+        Test.find({loc: {$nearSphere: ['30', '40']}}, function(err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -393,7 +393,7 @@ describe('model query casting', function () {
       }
     });
 
-    it('with objects', function (done) {
+    it('with objects', function(done) {
       var db = start(),
           Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
@@ -413,7 +413,7 @@ describe('model query casting', function () {
       Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
       function test() {
-        Test.find({loc: {$nearSphere: ['30', '40'], $maxDistance: 1}}, function (err, docs) {
+        Test.find({loc: {$nearSphere: ['30', '40'], $maxDistance: 1}}, function(err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -422,7 +422,7 @@ describe('model query casting', function () {
       }
     });
 
-    it('with nested objects', function (done) {
+    it('with nested objects', function(done) {
       var db = start();
       var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
       geoSchemaObject.index({'loc.nested': '2d'});
@@ -445,7 +445,7 @@ describe('model query casting', function () {
       Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
       function test() {
-        Test.find({'loc.nested': {$nearSphere: ['30', '40'], $maxDistance: 1}}, function (err, docs) {
+        Test.find({'loc.nested': {$nearSphere: ['30', '40'], $maxDistance: 1}}, function(err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -455,11 +455,11 @@ describe('model query casting', function () {
     });
   });
 
-  describe('$within', function () {
+  describe('$within', function() {
     this.slow(60);
 
-    describe('$centerSphere', function () {
-      it('with arrays', function (done) {
+    describe('$centerSphere', function() {
+      it('with arrays', function(done) {
         var db = start(),
             Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
@@ -479,7 +479,7 @@ describe('model query casting', function () {
         Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
         function test() {
-          Test.find({loc: {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function (err, docs) {
+          Test.find({loc: {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -488,7 +488,7 @@ describe('model query casting', function () {
         }
       });
 
-      it('with objects', function (done) {
+      it('with objects', function(done) {
         var db = start(),
             Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
@@ -508,7 +508,7 @@ describe('model query casting', function () {
         Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
         function test() {
-          Test.find({loc: {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function (err, docs) {
+          Test.find({loc: {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -517,7 +517,7 @@ describe('model query casting', function () {
         }
       });
 
-      it('with nested objects', function (done) {
+      it('with nested objects', function(done) {
         var db = start();
         var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
         geoSchemaObject.index({'loc.nested': '2d'});
@@ -540,7 +540,7 @@ describe('model query casting', function () {
         Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
         function test() {
-          Test.find({'loc.nested': {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function (err, docs) {
+          Test.find({'loc.nested': {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -550,8 +550,8 @@ describe('model query casting', function () {
       });
     });
 
-    describe('$center', function () {
-      it('with arrays', function (done) {
+    describe('$center', function() {
+      it('with arrays', function(done) {
         var db = start(),
             Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
@@ -571,7 +571,7 @@ describe('model query casting', function () {
         Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
         function test() {
-          Test.find({loc: {$within: {$center: [['11', '20'], '1']}}}, function (err, docs) {
+          Test.find({loc: {$within: {$center: [['11', '20'], '1']}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -580,7 +580,7 @@ describe('model query casting', function () {
         }
       });
 
-      it('with objects', function (done) {
+      it('with objects', function(done) {
         var db = start(),
             Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
@@ -600,7 +600,7 @@ describe('model query casting', function () {
         Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
         function test() {
-          Test.find({loc: {$within: {$center: [['11', '20'], '1']}}}, function (err, docs) {
+          Test.find({loc: {$within: {$center: [['11', '20'], '1']}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -609,7 +609,7 @@ describe('model query casting', function () {
         }
       });
 
-      it('with nested objects', function (done) {
+      it('with nested objects', function(done) {
         var db = start();
         var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
         geoSchemaObject.index({'loc.nested': '2d'});
@@ -632,7 +632,7 @@ describe('model query casting', function () {
         Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
         function test() {
-          Test.find({'loc.nested': {$within: {$center: [['11', '20'], '1']}}}, function (err, docs) {
+          Test.find({'loc.nested': {$within: {$center: [['11', '20'], '1']}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -642,8 +642,8 @@ describe('model query casting', function () {
       });
     });
 
-    describe('$polygon', function () {
-      it('with arrays', function (done) {
+    describe('$polygon', function() {
+      it('with arrays', function(done) {
         var db = start(),
             Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
@@ -663,7 +663,7 @@ describe('model query casting', function () {
         Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
         function test() {
-          Test.find({loc: {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function (err, docs) {
+          Test.find({loc: {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -672,7 +672,7 @@ describe('model query casting', function () {
         }
       });
 
-      it('with objects', function (done) {
+      it('with objects', function(done) {
         var db = start(),
             Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
@@ -692,7 +692,7 @@ describe('model query casting', function () {
         Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
         function test() {
-          Test.find({loc: {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function (err, docs) {
+          Test.find({loc: {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -701,7 +701,7 @@ describe('model query casting', function () {
         }
       });
 
-      it('with nested objects', function (done) {
+      it('with nested objects', function(done) {
         var db = start();
         var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
         geoSchemaObject.index({'loc.nested': '2d'});
@@ -724,7 +724,7 @@ describe('model query casting', function () {
         Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
         function test() {
-          Test.find({'loc.nested': {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function (err, docs) {
+          Test.find({'loc.nested': {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -734,8 +734,8 @@ describe('model query casting', function () {
       });
     });
 
-    describe('$box', function () {
-      it('with arrays', function (done) {
+    describe('$box', function() {
+      it('with arrays', function(done) {
         var db = start(),
             Test = db.model('Geo4', geoSchemaArray, 'y' + random());
 
@@ -755,7 +755,7 @@ describe('model query casting', function () {
         Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
         function test() {
-          Test.find({loc: {$within: {$box: [['8', '1'], ['50', '100']]}}}, function (err, docs) {
+          Test.find({loc: {$within: {$box: [['8', '1'], ['50', '100']]}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -764,7 +764,7 @@ describe('model query casting', function () {
         }
       });
 
-      it('with objects', function (done) {
+      it('with objects', function(done) {
         var db = start(),
             Test = db.model('Geo5', geoSchemaObject, 'y' + random());
 
@@ -784,7 +784,7 @@ describe('model query casting', function () {
         Test.create({loc: {long: 10, lat: 20}}, {loc: {long: 40, lat: 90}}, complete);
 
         function test() {
-          Test.find({loc: {$within: {$box: [['8', '1'], ['50', '100']]}}}, function (err, docs) {
+          Test.find({loc: {$within: {$box: [['8', '1'], ['50', '100']]}}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(2, docs.length);
@@ -793,7 +793,7 @@ describe('model query casting', function () {
         }
       });
 
-      it('with nested objects', function (done) {
+      it('with nested objects', function(done) {
         var db = start();
         var geoSchemaObject = new Schema({loc: {nested: {long: Number, lat: Number}}});
         geoSchemaObject.index({'loc.nested': '2d'});
@@ -816,7 +816,7 @@ describe('model query casting', function () {
         Test.create({loc: {nested: {long: 10, lat: 20}}}, {loc: {nested: {long: 40, lat: 90}}}, complete);
 
         function test() {
-          Test.find({'loc.nested': {$within: {$box: [['8', '1'], ['50', '100']]}}}, function (err, docs) {
+          Test.find({'loc.nested': {$within: {$box: [['8', '1'], ['50', '100']]}}}, function(err, docs) {
             assert.ifError(err);
             assert.equal(2, docs.length);
             db.close(done);
@@ -826,10 +826,10 @@ describe('model query casting', function () {
     });
   });
 
-  describe('$options', function () {
-    it('works on arrays gh-1462', function (done) {
+  describe('$options', function() {
+    it('works on arrays gh-1462', function(done) {
       var opts = {};
-      opts.toString = function () {
+      opts.toString = function() {
         return 'img';
       };
 
@@ -842,8 +842,8 @@ describe('model query casting', function () {
     });
   });
 
-  describe('$elemMatch', function () {
-    it('should cast String to ObjectId in $elemMatch', function (done) {
+  describe('$elemMatch', function() {
+    it('should cast String to ObjectId in $elemMatch', function(done) {
       var db = start(),
           BlogPostB = db.model(modelName, collection);
 
@@ -851,10 +851,10 @@ describe('model query casting', function () {
 
       var post = new BlogPostB({comments: [{_id: commentId}]}), id = post._id.toString();
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({_id: id, comments: {$elemMatch: {_id: commentId.toString()}}}, function (err, doc) {
+        BlogPostB.findOne({_id: id, comments: {$elemMatch: {_id: commentId.toString()}}}, function(err, doc) {
           assert.ifError(err);
 
           assert.equal(doc._id.toString(), id);
@@ -863,7 +863,7 @@ describe('model query casting', function () {
       });
     });
 
-    it('should cast String to ObjectId in $elemMatch inside $not', function (done) {
+    it('should cast String to ObjectId in $elemMatch inside $not', function(done) {
       var db = start(),
           BlogPostB = db.model(modelName, collection);
 
@@ -871,10 +871,10 @@ describe('model query casting', function () {
 
       var post = new BlogPostB({comments: [{_id: commentId}]}), id = post._id.toString();
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({_id: id, comments: {$not: {$elemMatch: {_id: commentId.toString()}}}}, function (err, doc) {
+        BlogPostB.findOne({_id: id, comments: {$not: {$elemMatch: {_id: commentId.toString()}}}}, function(err, doc) {
           assert.ifError(err);
 
           assert.equal(doc, null);
@@ -884,7 +884,7 @@ describe('model query casting', function () {
     });
   });
 
-  it('works with $all (gh-3394)', function (done) {
+  it('works with $all (gh-3394)', function(done) {
     var db = start();
 
     var MyModel = db.model('gh3394', {tags: [ObjectId]});
@@ -893,10 +893,10 @@ describe('model query casting', function () {
       tags: ['00000000000000000000000a', '00000000000000000000000b']
     };
 
-    MyModel.create(doc, function (error, savedDoc) {
+    MyModel.create(doc, function(error, savedDoc) {
       assert.ifError(error);
       assert.equal(typeof savedDoc.tags[0], 'object');
-      MyModel.findOne({tags: {$all: doc.tags}}, function (error, doc) {
+      MyModel.findOne({tags: {$all: doc.tags}}, function(error, doc) {
         assert.ifError(error);
         assert.ok(doc);
         db.close(done);
diff --git a/test/model.querying.test.js b/test/model.querying.test.js
index 8e85d25949a..ea623e28846 100644
--- a/test/model.querying.test.js
+++ b/test/model.querying.test.js
@@ -55,10 +55,10 @@ mongoose.model('Mod', ModSchema);
 
 var geoSchema = new Schema({loc: {type: [Number], index: '2d'}});
 
-describe('model: querying:', function () {
+describe('model: querying:', function() {
   var mongo26_or_greater = false;
-  before(function (done) {
-    start.mongodVersion(function (err, version) {
+  before(function(done) {
+    start.mongodVersion(function(err, version) {
       if (err) {
         throw err;
       }
@@ -70,7 +70,7 @@ describe('model: querying:', function () {
     });
   });
 
-  it('find returns a Query', function (done) {
+  it('find returns a Query', function(done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection);
 
@@ -92,7 +92,7 @@ describe('model: querying:', function () {
     db.close(done);
   });
 
-  it('findOne returns a Query', function (done) {
+  it('findOne returns a Query', function(done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection);
 
@@ -114,7 +114,7 @@ describe('model: querying:', function () {
     db.close(done);
   });
 
-  it('an empty find does not hang', function (done) {
+  it('an empty find does not hang', function(done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection);
 
@@ -125,7 +125,7 @@ describe('model: querying:', function () {
     BlogPostB.find({}, fn);
   });
 
-  it('a query is executed when a callback is passed', function (done) {
+  it('a query is executed when a callback is passed', function(done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         count = 5,
@@ -154,7 +154,7 @@ describe('model: querying:', function () {
     assert.ok(BlogPostB.find(q, '', {}, fn) instanceof Query);
   });
 
-  it('query is executed where a callback for findOne', function (done) {
+  it('query is executed where a callback for findOne', function(done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         count = 5,
@@ -184,8 +184,8 @@ describe('model: querying:', function () {
     assert.ok(BlogPostB.findOne(q, null, {}, fn) instanceof Query);
   });
 
-  describe('count', function () {
-    it('returns a Query', function (done) {
+  describe('count', function() {
+    it('returns a Query', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
       assert.ok(BlogPostB.count({}) instanceof Query);
@@ -193,7 +193,7 @@ describe('model: querying:', function () {
       done();
     });
 
-    it('Query executes when you pass a callback', function (done) {
+    it('Query executes when you pass a callback', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           pending = 2;
@@ -210,7 +210,7 @@ describe('model: querying:', function () {
       assert.ok(BlogPostB.count(fn) instanceof Query);
     });
 
-    it('counts documents', function (done) {
+    it('counts documents', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Wooooot ' + random();
@@ -218,16 +218,16 @@ describe('model: querying:', function () {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
         var post = new BlogPostB();
         post.set('title', title);
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
 
-          BlogPostB.count({title: title}, function (err, count) {
+          BlogPostB.count({title: title}, function(err, count) {
             assert.ifError(err);
 
             assert.equal('number', typeof count);
@@ -241,8 +241,8 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('distinct', function () {
-    it('returns a Query', function (done) {
+  describe('distinct', function() {
+    it('returns a Query', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -251,14 +251,14 @@ describe('model: querying:', function () {
       done();
     });
 
-    it('executes when you pass a callback', function (done) {
+    it('executes when you pass a callback', function(done) {
       var db = start();
       var Address = new Schema({zip: String});
       Address = db.model('Address', Address, 'addresses_' + random());
 
-      Address.create({zip: '10010'}, {zip: '10010'}, {zip: '99701'}, function (err) {
+      Address.create({zip: '10010'}, {zip: '10010'}, {zip: '99701'}, function(err) {
         assert.strictEqual(null, err);
-        var query = Address.distinct('zip', {}, function (err, results) {
+        var query = Address.distinct('zip', {}, function(err, results) {
           assert.ifError(err);
           assert.equal(2, results.length);
           assert.ok(results.indexOf('10010') > -1);
@@ -269,13 +269,13 @@ describe('model: querying:', function () {
       });
     });
 
-    it('permits excluding conditions gh-1541', function (done) {
+    it('permits excluding conditions gh-1541', function(done) {
       var db = start();
       var Address = new Schema({zip: String});
       Address = db.model('Address', Address, 'addresses_' + random());
-      Address.create({zip: '10010'}, {zip: '10010'}, {zip: '99701'}, function (err) {
+      Address.create({zip: '10010'}, {zip: '10010'}, {zip: '99701'}, function(err) {
         assert.ifError(err);
-        Address.distinct('zip', function (err, results) {
+        Address.distinct('zip', function(err, results) {
           assert.ifError(err);
           assert.equal(2, results.length);
           assert.ok(results.indexOf('10010') > -1);
@@ -286,8 +286,8 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('update', function () {
-    it('returns a Query', function (done) {
+  describe('update', function() {
+    it('returns a Query', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -297,7 +297,7 @@ describe('model: querying:', function () {
       done();
     });
 
-    it('Query executes when you pass a callback', function (done) {
+    it('Query executes when you pass a callback', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           count = 2;
@@ -314,7 +314,7 @@ describe('model: querying:', function () {
       assert.ok(BlogPostB.update({title: random()}, {}, {}, fn) instanceof Query);
     });
 
-    it('can handle minimize option (gh-3381)', function (done) {
+    it('can handle minimize option (gh-3381)', function(done) {
       var db = start();
       var Model = db.model('gh3381', {
         name: String,
@@ -330,8 +330,8 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('findOne', function () {
-    it('works', function (done) {
+  describe('findOne', function() {
+    it('works', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Wooooot ' + random();
@@ -339,10 +339,10 @@ describe('model: querying:', function () {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({title: title}, function (err, doc) {
+        BlogPostB.findOne({title: title}, function(err, doc) {
           assert.ifError(err);
           assert.equal(title, doc.get('title'));
           assert.equal(false, doc.isNew);
@@ -353,7 +353,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('casts $modifiers', function (done) {
+    it('casts $modifiers', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           post = new BlogPostB({
@@ -362,11 +362,11 @@ describe('model: querying:', function () {
             }
           });
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
         var query = {'meta.visitors': {$gt: '-20', $lt: -1}};
-        BlogPostB.findOne(query, function (err, found) {
+        BlogPostB.findOne(query, function(err, found) {
           assert.ifError(err);
           assert.ok(found);
           assert.equal(found.get('meta.visitors').valueOf(), post.get('meta.visitors').valueOf());
@@ -378,7 +378,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('querying if an array contains one of multiple members $in a set', function (done) {
+    it('querying if an array contains one of multiple members $in a set', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -386,14 +386,14 @@ describe('model: querying:', function () {
 
       post.tags.push('football');
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({tags: {$in: ['football', 'baseball']}}, function (err, doc) {
+        BlogPostB.findOne({tags: {$in: ['football', 'baseball']}}, function(err, doc) {
           assert.ifError(err);
           assert.equal(doc._id.toString(), post._id);
 
-          BlogPostB.findOne({_id: post._id, tags: /otba/i}, function (err, doc) {
+          BlogPostB.findOne({_id: post._id, tags: /otba/i}, function(err, doc) {
             assert.ifError(err);
             assert.equal(doc._id.toString(), post._id);
             db.close();
@@ -403,18 +403,18 @@ describe('model: querying:', function () {
       });
     });
 
-    it('querying if an array contains one of multiple members $in a set 2', function (done) {
+    it('querying if an array contains one of multiple members $in a set 2', function(done) {
       var db = start(),
           BlogPostA = db.model('BlogPostB', collection);
 
       var post = new BlogPostA({tags: ['gooberOne']});
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
         var query = {tags: {$in: ['gooberOne']}};
 
-        BlogPostA.findOne(query, function (err, returned) {
+        BlogPostA.findOne(query, function(err, returned) {
           cb();
           assert.ifError(err);
           assert.ok(!!~returned.tags.indexOf('gooberOne'));
@@ -422,10 +422,10 @@ describe('model: querying:', function () {
         });
       });
 
-      post.collection.insert({meta: {visitors: 9898, a: null}}, {}, function (err, b) {
+      post.collection.insert({meta: {visitors: 9898, a: null}}, {}, function(err, b) {
         assert.ifError(err);
 
-        BlogPostA.findOne({_id: b.ops[0]._id}, function (err, found) {
+        BlogPostA.findOne({_id: b.ops[0]._id}, function(err, found) {
           cb();
           assert.ifError(err);
           assert.equal(found.get('meta.visitors'), 9898);
@@ -443,14 +443,14 @@ describe('model: querying:', function () {
       }
     });
 
-    it('querying via $where a string', function (done) {
+    it('querying via $where a string', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({title: 'Steve Jobs', author: 'Steve Jobs'}, function (err, created) {
+      BlogPostB.create({title: 'Steve Jobs', author: 'Steve Jobs'}, function(err, created) {
         assert.ifError(err);
 
-        BlogPostB.findOne({$where: 'this.title && this.title === this.author'}, function (err, found) {
+        BlogPostB.findOne({$where: 'this.title && this.title === this.author'}, function(err, found) {
           assert.ifError(err);
 
           assert.equal(found._id.toString(), created._id);
@@ -460,18 +460,18 @@ describe('model: querying:', function () {
       });
     });
 
-    it('querying via $where a function', function (done) {
+    it('querying via $where a function', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({author: 'Atari', slug: 'Atari'}, function (err, created) {
+      BlogPostB.create({author: 'Atari', slug: 'Atari'}, function(err, created) {
         assert.ifError(err);
 
         BlogPostB.findOne({
-          $where: function () {
+          $where: function() {
             return (this.author && this.slug && this.author === this.slug);
           }
-        }, function (err, found) {
+        }, function(err, found) {
           assert.ifError(err);
 
           assert.equal(found._id.toString(), created._id);
@@ -481,7 +481,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('based on nested fields', function (done) {
+    it('based on nested fields', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           post = new BlogPostB({
@@ -490,10 +490,10 @@ describe('model: querying:', function () {
             }
           });
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({'meta.visitors': 5678}, function (err, found) {
+        BlogPostB.findOne({'meta.visitors': 5678}, function(err, found) {
           assert.ifError(err);
           assert.equal(found.get('meta.visitors')
           .valueOf(), post.get('meta.visitors').valueOf());
@@ -504,26 +504,26 @@ describe('model: querying:', function () {
       });
     });
 
-    it('based on embedded doc fields (gh-242, gh-463)', function (done) {
+    it('based on embedded doc fields (gh-242, gh-463)', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({comments: [{title: 'i should be queryable'}], numbers: [1, 2, 33333], tags: ['yes', 'no']}, function (err, created) {
+      BlogPostB.create({comments: [{title: 'i should be queryable'}], numbers: [1, 2, 33333], tags: ['yes', 'no']}, function(err, created) {
         assert.ifError(err);
-        BlogPostB.findOne({'comments.title': 'i should be queryable'}, function (err, found) {
+        BlogPostB.findOne({'comments.title': 'i should be queryable'}, function(err, found) {
           assert.ifError(err);
           assert.equal(found._id.toString(), created._id);
 
-          BlogPostB.findOne({'comments.0.title': 'i should be queryable'}, function (err, found) {
+          BlogPostB.findOne({'comments.0.title': 'i should be queryable'}, function(err, found) {
             assert.ifError(err);
             assert.equal(found._id.toString(), created._id);
 
             // GH-463
-            BlogPostB.findOne({'numbers.2': 33333}, function (err, found) {
+            BlogPostB.findOne({'numbers.2': 33333}, function(err, found) {
               assert.ifError(err);
               assert.equal(found._id.toString(), created._id);
 
-              BlogPostB.findOne({'tags.1': 'no'}, function (err, found) {
+              BlogPostB.findOne({'tags.1': 'no'}, function(err, found) {
                 assert.ifError(err);
                 assert.equal(found._id.toString(), created._id);
                 db.close();
@@ -535,14 +535,14 @@ describe('model: querying:', function () {
       });
     });
 
-    it('works with nested docs and string ids (gh-389)', function (done) {
+    it('works with nested docs and string ids (gh-389)', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({comments: [{title: 'i should be queryable by _id'}, {title: 'me too me too!'}]}, function (err, created) {
+      BlogPostB.create({comments: [{title: 'i should be queryable by _id'}, {title: 'me too me too!'}]}, function(err, created) {
         assert.ifError(err);
         var id = created.comments[1]._id.toString();
-        BlogPostB.findOne({'comments._id': id}, function (err, found) {
+        BlogPostB.findOne({'comments._id': id}, function(err, found) {
           db.close();
           assert.ifError(err);
           assert.strictEqual(!!found, true, 'Find by nested doc id hex string fails');
@@ -552,7 +552,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('using #all with nested #elemMatch', function (done) {
+    it('using #all with nested #elemMatch', function(done) {
       var db = start(),
           P = db.model('BlogPostB', collection + '_nestedElemMatch');
 
@@ -562,13 +562,13 @@ describe('model: querying:', function () {
       var id1 = post.comments[1]._id;
       var id2 = post.comments[2]._id;
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
         var query0 = {$elemMatch: {_id: id1, title: 'comment B'}};
         var query1 = {$elemMatch: {_id: id2.toString(), title: 'comment C'}};
 
-        P.findOne({comments: {$all: [query0, query1]}}, function (err, p) {
+        P.findOne({comments: {$all: [query0, query1]}}, function(err, p) {
           db.close();
           assert.ifError(err);
           assert.equal(p.id, post.id);
@@ -577,7 +577,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('using #or with nested #elemMatch', function (done) {
+    it('using #or with nested #elemMatch', function(done) {
       var db = start(),
           P = db.model('BlogPostB', collection);
 
@@ -586,13 +586,13 @@ describe('model: querying:', function () {
 
       var id1 = post.comments[1]._id;
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
         var query0 = {comments: {$elemMatch: {title: 'comment Z'}}};
         var query1 = {comments: {$elemMatch: {_id: id1.toString(), title: 'comment E'}}};
 
-        P.findOne({$or: [query0, query1]}, function (err, p) {
+        P.findOne({$or: [query0, query1]}, function(err, p) {
           db.close();
           assert.ifError(err);
           assert.equal(p.id, post.id);
@@ -601,7 +601,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('buffer $in array', function (done) {
+    it('buffer $in array', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -609,14 +609,14 @@ describe('model: querying:', function () {
         sigs: [new Buffer([1, 2, 3]),
           new Buffer([4, 5, 6]),
           new Buffer([7, 8, 9])]
-      }, function (err, created) {
+      }, function(err, created) {
         assert.ifError(err);
-        BlogPostB.findOne({sigs: new Buffer([1, 2, 3])}, function (err, found) {
+        BlogPostB.findOne({sigs: new Buffer([1, 2, 3])}, function(err, found) {
           assert.ifError(err);
           found.id;
           assert.equal(found._id.toString(), created._id);
           var query = {sigs: {'$in': [new Buffer([3, 3, 3]), new Buffer([4, 5, 6])]}};
-          BlogPostB.findOne(query, function (err) {
+          BlogPostB.findOne(query, function(err) {
             assert.ifError(err);
             db.close();
             done();
@@ -625,18 +625,18 @@ describe('model: querying:', function () {
       });
     });
 
-    it('regex with Array (gh-599)', function (done) {
+    it('regex with Array (gh-599)', function(done) {
       var db = start(),
           B = db.model('BlogPostB', random());
 
-      B.create({tags: 'wooof baaaark meeeeow'.split(' ')}, function (err) {
+      B.create({tags: 'wooof baaaark meeeeow'.split(' ')}, function(err) {
         assert.ifError(err);
-        B.findOne({tags: /ooof$/}, function (err, doc) {
+        B.findOne({tags: /ooof$/}, function(err, doc) {
           assert.ifError(err);
           assert.strictEqual(true, !!doc);
           assert.ok(!!~doc.tags.indexOf('meeeeow'));
 
-          B.findOne({tags: {$regex: 'eow$'}}, function (err, doc) {
+          B.findOne({tags: {$regex: 'eow$'}}, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.strictEqual(true, !!doc);
@@ -647,14 +647,14 @@ describe('model: querying:', function () {
       });
     });
 
-    it('regex with options', function (done) {
+    it('regex with options', function(done) {
       var db = start(),
           B = db.model('BlogPostB', collection);
 
       var post = new B({title: '$option queries'});
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
-        B.findOne({title: {$regex: ' QUERIES$', $options: 'i'}}, function (err, doc) {
+        B.findOne({title: {$regex: ' QUERIES$', $options: 'i'}}, function(err, doc) {
           db.close();
           assert.strictEqual(null, err, err && err.stack);
           assert.equal(doc.id, post.id);
@@ -663,15 +663,15 @@ describe('model: querying:', function () {
       });
     });
 
-    it('works with $elemMatch and $in combo (gh-1100)', function (done) {
+    it('works with $elemMatch and $in combo (gh-1100)', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           id1 = new DocumentObjectId,
           id2 = new DocumentObjectId;
 
-      BlogPostB.create({owners: [id1, id2]}, function (err, created) {
+      BlogPostB.create({owners: [id1, id2]}, function(err, created) {
         assert.ifError(err);
-        BlogPostB.findOne({owners: {'$elemMatch': {$in: [id2.toString()]}}}, function (err, found) {
+        BlogPostB.findOne({owners: {'$elemMatch': {$in: [id2.toString()]}}}, function(err, found) {
           db.close();
           assert.ifError(err);
           assert.ok(found);
@@ -682,8 +682,8 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('findById', function () {
-    it('handles undefined', function (done) {
+  describe('findById', function() {
+    it('handles undefined', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Edwald ' + random();
@@ -691,10 +691,10 @@ describe('model: querying:', function () {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.findById(undefined, function (err, doc) {
+        BlogPostB.findById(undefined, function(err, doc) {
           assert.ifError(err);
           assert.equal(null, doc);
           db.close(done);
@@ -702,7 +702,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('works', function (done) {
+    it('works', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Edwald ' + random();
@@ -710,12 +710,12 @@ describe('model: querying:', function () {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
         var pending = 2;
 
-        BlogPostB.findById(post.get('_id'), function (err, doc) {
+        BlogPostB.findById(post.get('_id'), function(err, doc) {
           assert.ifError(err);
           assert.ok(doc instanceof BlogPostB);
           assert.equal(title, doc.get('title'));
@@ -726,7 +726,7 @@ describe('model: querying:', function () {
           done();
         });
 
-        BlogPostB.findById(post.get('_id').toHexString(), function (err, doc) {
+        BlogPostB.findById(post.get('_id').toHexString(), function(err, doc) {
           assert.ifError(err);
           assert.ok(doc instanceof BlogPostB);
           assert.equal(title, doc.get('title'));
@@ -739,7 +739,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('works with partial initialization', function (done) {
+    it('works with partial initialization', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           queries = 5;
@@ -751,10 +751,10 @@ describe('model: querying:', function () {
       post.meta.visitors = 53;
       post.tags = ['humidity', 'soggy'];
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.findById(post.get('_id'), function (err, doc) {
+        BlogPostB.findById(post.get('_id'), function(err, doc) {
           assert.ifError(err);
 
           assert.equal(true, doc.isInit('title'));
@@ -770,7 +770,7 @@ describe('model: querying:', function () {
           done();
         });
 
-        BlogPostB.findById(post.get('_id'), 'title', function (err, doc) {
+        BlogPostB.findById(post.get('_id'), 'title', function(err, doc) {
           assert.ifError(err);
           assert.equal(true, doc.isInit('title'));
           assert.equal(false, doc.isInit('slug'));
@@ -785,7 +785,7 @@ describe('model: querying:', function () {
           done();
         });
 
-        BlogPostB.findById(post.get('_id'), '-slug', function (err, doc) {
+        BlogPostB.findById(post.get('_id'), '-slug', function(err, doc) {
           assert.ifError(err);
           assert.equal(true, doc.isInit('title'));
           assert.equal(false, doc.isInit('slug'));
@@ -800,7 +800,7 @@ describe('model: querying:', function () {
           done();
         });
 
-        BlogPostB.findById(post.get('_id'), {title: 1}, function (err, doc) {
+        BlogPostB.findById(post.get('_id'), {title: 1}, function(err, doc) {
           assert.ifError(err);
           assert.equal(true, doc.isInit('title'));
           assert.equal(false, doc.isInit('slug'));
@@ -815,7 +815,7 @@ describe('model: querying:', function () {
           done();
         });
 
-        BlogPostB.findById(post.get('_id'), 'slug', function (err, doc) {
+        BlogPostB.findById(post.get('_id'), 'slug', function(err, doc) {
           assert.ifError(err);
           assert.equal(false, doc.isInit('title'));
           assert.equal(true, doc.isInit('slug'));
@@ -832,7 +832,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('querying if an array contains at least a certain single member (gh-220)', function (done) {
+    it('querying if an array contains at least a certain single member (gh-220)', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -840,10 +840,10 @@ describe('model: querying:', function () {
 
       post.tags.push('cat');
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.findOne({tags: 'cat'}, function (err, doc) {
+        BlogPostB.findOne({tags: 'cat'}, function(err, doc) {
           assert.ifError(err);
           assert.equal(doc._id.toString(), post._id);
           db.close();
@@ -853,25 +853,25 @@ describe('model: querying:', function () {
     });
 
 
-    it('where an array where the $slice operator', function (done) {
+    it('where an array where the $slice operator', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({numbers: [500, 600, 700, 800]}, function (err, created) {
+      BlogPostB.create({numbers: [500, 600, 700, 800]}, function(err, created) {
         assert.ifError(err);
-        BlogPostB.findById(created._id, {numbers: {$slice: 2}}, function (err, found) {
+        BlogPostB.findById(created._id, {numbers: {$slice: 2}}, function(err, found) {
           assert.ifError(err);
           assert.equal(found._id.toString(), created._id);
           assert.equal(2, found.numbers.length);
           assert.equal(500, found.numbers[0]);
           assert.equal(600, found.numbers[1]);
-          BlogPostB.findById(created._id, {numbers: {$slice: -2}}, function (err, found) {
+          BlogPostB.findById(created._id, {numbers: {$slice: -2}}, function(err, found) {
             assert.ifError(err);
             assert.equal(found._id.toString(), created._id);
             assert.equal(2, found.numbers.length);
             assert.equal(700, found.numbers[0]);
             assert.equal(800, found.numbers[1]);
-            BlogPostB.findById(created._id, {numbers: {$slice: [1, 2]}}, function (err, found) {
+            BlogPostB.findById(created._id, {numbers: {$slice: [1, 2]}}, function(err, found) {
               assert.ifError(err);
               assert.equal(found._id.toString(), created._id);
               assert.equal(2, found.numbers.length);
@@ -886,8 +886,8 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('find', function () {
-    it('works', function (done) {
+  describe('find', function() {
+    it('works', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           title = 'Wooooot ' + random();
@@ -895,16 +895,16 @@ describe('model: querying:', function () {
       var post = new BlogPostB();
       post.set('title', title);
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
         var post = new BlogPostB();
         post.set('title', title);
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
 
-          BlogPostB.find({title: title}, function (err, docs) {
+          BlogPostB.find({title: title}, function(err, docs) {
             assert.ifError(err);
             assert.equal(2, docs.length);
 
@@ -921,12 +921,12 @@ describe('model: querying:', function () {
       });
     });
 
-    it('returns docs where an array that contains one specific member', function (done) {
+    it('returns docs where an array that contains one specific member', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
-      BlogPostB.create({numbers: [100, 101, 102]}, function (err, created) {
+      BlogPostB.create({numbers: [100, 101, 102]}, function(err, created) {
         assert.ifError(err);
-        BlogPostB.find({numbers: 100}, function (err, found) {
+        BlogPostB.find({numbers: 100}, function(err, found) {
           assert.ifError(err);
           assert.equal(1, found.length);
           assert.equal(found[0]._id.toString(), created._id);
@@ -936,7 +936,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('works when comparing $ne with single value against an array', function (done) {
+    it('works when comparing $ne with single value against an array', function(done) {
       var db = start();
       var schema = new Schema({
         ids: [Schema.ObjectId],
@@ -950,23 +950,23 @@ describe('model: querying:', function () {
       var id3 = new DocumentObjectId;
       var id4 = new DocumentObjectId;
 
-      NE.create({ids: [id1, id4], b: id3}, function (err) {
+      NE.create({ids: [id1, id4], b: id3}, function(err) {
         assert.ifError(err);
-        NE.create({ids: [id2, id4], b: id3}, function (err) {
+        NE.create({ids: [id2, id4], b: id3}, function(err) {
           assert.ifError(err);
 
           var query = NE.find({'b': id3.toString(), 'ids': {$ne: id1}});
-          query.exec(function (err, nes1) {
+          query.exec(function(err, nes1) {
             assert.ifError(err);
             assert.equal(1, nes1.length);
 
-            NE.find({b: {$ne: [1]}}, function (err) {
+            NE.find({b: {$ne: [1]}}, function(err) {
               assert.equal('Cast to ObjectId failed for value "1" at path "b"', err.message);
 
-              NE.find({b: {$ne: 4}}, function (err) {
+              NE.find({b: {$ne: 4}}, function(err) {
                 assert.equal('Cast to ObjectId failed for value "4" at path "b"', err.message);
 
-                NE.find({b: id3, ids: {$ne: id4}}, function (err, nes4) {
+                NE.find({b: id3, ids: {$ne: id4}}, function(err, nes4) {
                   db.close();
                   assert.ifError(err);
                   assert.equal(0, nes4.length);
@@ -979,7 +979,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('with partial initialization', function (done) {
+    it('with partial initialization', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           queries = 4;
@@ -989,10 +989,10 @@ describe('model: querying:', function () {
       post.title = 'hahaha';
       post.slug = 'woot';
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.find({_id: post.get('_id')}, function (err, docs) {
+        BlogPostB.find({_id: post.get('_id')}, function(err, docs) {
           assert.ifError(err);
           assert.equal(true, docs[0].isInit('title'));
           assert.equal(true, docs[0].isInit('slug'));
@@ -1005,7 +1005,7 @@ describe('model: querying:', function () {
           done();
         });
 
-        BlogPostB.find({_id: post.get('_id')}, 'title', function (err, docs) {
+        BlogPostB.find({_id: post.get('_id')}, 'title', function(err, docs) {
           assert.ifError(err);
           assert.equal(true, docs[0].isInit('title'));
           assert.equal(false, docs[0].isInit('slug'));
@@ -1018,7 +1018,7 @@ describe('model: querying:', function () {
           done();
         });
 
-        BlogPostB.find({_id: post.get('_id')}, {slug: 0, def: 0}, function (err, docs) {
+        BlogPostB.find({_id: post.get('_id')}, {slug: 0, def: 0}, function(err, docs) {
           assert.ifError(err);
           assert.equal(true, docs[0].isInit('title'));
           assert.equal(false, docs[0].isInit('slug'));
@@ -1031,7 +1031,7 @@ describe('model: querying:', function () {
           done();
         });
 
-        BlogPostB.find({_id: post.get('_id')}, 'slug', function (err, docs) {
+        BlogPostB.find({_id: post.get('_id')}, 'slug', function(err, docs) {
           assert.ifError(err);
           assert.equal(false, docs[0].isInit('title'));
           assert.equal(true, docs[0].isInit('slug'));
@@ -1046,7 +1046,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('where $exists', function (done) {
+    it('where $exists', function(done) {
       var db = start(),
           ExistsSchema = new Schema({
             a: Number,
@@ -1054,11 +1054,11 @@ describe('model: querying:', function () {
           });
       mongoose.model('Exists', ExistsSchema);
       var Exists = db.model('Exists', 'exists_' + random());
-      Exists.create({a: 1}, function (err) {
+      Exists.create({a: 1}, function(err) {
         assert.ifError(err);
-        Exists.create({b: 'hi'}, function (err) {
+        Exists.create({b: 'hi'}, function(err) {
           assert.ifError(err);
-          Exists.find({b: {$exists: true}}, function (err, docs) {
+          Exists.find({b: {$exists: true}}, function(err, docs) {
             assert.ifError(err);
             db.close();
             assert.equal(1, docs.length);
@@ -1068,15 +1068,15 @@ describe('model: querying:', function () {
       });
     });
 
-    it('works with $elemMatch (gh-1100)', function (done) {
+    it('works with $elemMatch (gh-1100)', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection),
           id1 = new DocumentObjectId,
           id2 = new DocumentObjectId;
 
-      BlogPostB.create({owners: [id1, id2]}, function (err) {
+      BlogPostB.create({owners: [id1, id2]}, function(err) {
         assert.ifError(err);
-        BlogPostB.find({owners: {'$elemMatch': {$in: [id2.toString()]}}}, function (err, found) {
+        BlogPostB.find({owners: {'$elemMatch': {$in: [id2.toString()]}}}, function(err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(1, found.length);
@@ -1085,14 +1085,14 @@ describe('model: querying:', function () {
       });
     });
 
-    it('where $mod', function (done) {
+    it('where $mod', function(done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
-      Mod.create({num: 1}, function (err, one) {
+      Mod.create({num: 1}, function(err, one) {
         assert.ifError(err);
-        Mod.create({num: 2}, function (err) {
+        Mod.create({num: 2}, function(err) {
           assert.ifError(err);
-          Mod.find({num: {$mod: [2, 1]}}, function (err, found) {
+          Mod.find({num: {$mod: [2, 1]}}, function(err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
             assert.equal(found[0]._id.toString(), one._id);
@@ -1103,14 +1103,14 @@ describe('model: querying:', function () {
       });
     });
 
-    it('where $not', function (done) {
+    it('where $not', function(done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
-      Mod.create({num: 1}, function (err) {
+      Mod.create({num: 1}, function(err) {
         assert.ifError(err);
-        Mod.create({num: 2}, function (err, two) {
+        Mod.create({num: 2}, function(err, two) {
           assert.ifError(err);
-          Mod.find({num: {$not: {$mod: [2, 1]}}}, function (err, found) {
+          Mod.find({num: {$not: {$mod: [2, 1]}}}, function(err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
             assert.equal(found[0]._id.toString(), two._id);
@@ -1121,11 +1121,11 @@ describe('model: querying:', function () {
       });
     });
 
-    it('where or()', function (done) {
+    it('where or()', function(done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
 
-      Mod.create({num: 1}, {num: 2, str: 'two'}, function (err, one, two) {
+      Mod.create({num: 1}, {num: 2, str: 'two'}, function(err, one, two) {
         assert.ifError(err);
 
         var pending = 3;
@@ -1134,7 +1134,7 @@ describe('model: querying:', function () {
         test3();
 
         function test1() {
-          Mod.find({$or: [{num: 1}, {num: 2}]}, function (err, found) {
+          Mod.find({$or: [{num: 1}, {num: 2}]}, function(err, found) {
             cb();
             assert.ifError(err);
             assert.equal(2, found.length);
@@ -1142,7 +1142,7 @@ describe('model: querying:', function () {
             var found1 = false;
             var found2 = false;
 
-            found.forEach(function (doc) {
+            found.forEach(function(doc) {
               if (doc.id === one.id) {
                 found1 = true;
               } else if (doc.id === two.id) {
@@ -1156,7 +1156,7 @@ describe('model: querying:', function () {
         }
 
         function test2() {
-          Mod.find({$or: [{str: 'two'}, {str: 'three'}]}, function (err, found) {
+          Mod.find({$or: [{str: 'two'}, {str: 'three'}]}, function(err, found) {
             cb();
             assert.ifError(err);
             assert.equal(1, found.length);
@@ -1165,7 +1165,7 @@ describe('model: querying:', function () {
         }
 
         function test3() {
-          Mod.find({$or: [{num: 1}]}).or([{str: 'two'}]).exec(function (err, found) {
+          Mod.find({$or: [{num: 1}]}).or([{str: 'two'}]).exec(function(err, found) {
             cb();
             assert.ifError(err);
             assert.equal(2, found.length);
@@ -1173,7 +1173,7 @@ describe('model: querying:', function () {
             var found1 = false;
             var found2 = false;
 
-            found.forEach(function (doc) {
+            found.forEach(function(doc) {
               if (doc.id === one.id) {
                 found1 = true;
               } else if (doc.id === two.id) {
@@ -1196,15 +1196,15 @@ describe('model: querying:', function () {
       });
     });
 
-    it('using $or with array of Document', function (done) {
+    it('using $or with array of Document', function(done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
 
-      Mod.create({num: 1}, function (err, one) {
+      Mod.create({num: 1}, function(err, one) {
         assert.ifError(err);
-        Mod.find({num: 1}, function (err, found) {
+        Mod.find({num: 1}, function(err, found) {
           assert.ifError(err);
-          Mod.find({$or: found}, function (err, found) {
+          Mod.find({$or: found}, function(err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
             assert.equal(found[0]._id.toString(), one._id);
@@ -1215,16 +1215,16 @@ describe('model: querying:', function () {
       });
     });
 
-    it('where $ne', function (done) {
+    it('where $ne', function(done) {
       var db = start(),
           Mod = db.model('Mod', 'mods_' + random());
-      Mod.create({num: 1}, function (err) {
+      Mod.create({num: 1}, function(err) {
         assert.ifError(err);
-        Mod.create({num: 2}, function (err, two) {
+        Mod.create({num: 2}, function(err, two) {
           assert.ifError(err);
-          Mod.create({num: 3}, function (err, three) {
+          Mod.create({num: 3}, function(err, three) {
             assert.ifError(err);
-            Mod.find({num: {$ne: 1}}, function (err, found) {
+            Mod.find({num: {$ne: 1}}, function(err, found) {
               assert.ifError(err);
 
               assert.equal(found.length, 2);
@@ -1238,11 +1238,11 @@ describe('model: querying:', function () {
       });
     });
 
-    it('where $nor', function (done) {
+    it('where $nor', function(done) {
       var db = start(),
           Mod = db.model('Mod', 'nor_' + random());
 
-      Mod.create({num: 1}, {num: 2, str: 'two'}, function (err, one, two) {
+      Mod.create({num: 1}, {num: 2, str: 'two'}, function(err, one, two) {
         assert.ifError(err);
 
         var pending = 3;
@@ -1251,7 +1251,7 @@ describe('model: querying:', function () {
         test3();
 
         function test1() {
-          Mod.find({$nor: [{num: 1}, {num: 3}]}, function (err, found) {
+          Mod.find({$nor: [{num: 1}, {num: 3}]}, function(err, found) {
             cb();
             assert.ifError(err);
             assert.equal(1, found.length);
@@ -1260,7 +1260,7 @@ describe('model: querying:', function () {
         }
 
         function test2() {
-          Mod.find({$nor: [{str: 'two'}, {str: 'three'}]}, function (err, found) {
+          Mod.find({$nor: [{str: 'two'}, {str: 'three'}]}, function(err, found) {
             cb();
             assert.ifError(err);
             assert.equal(1, found.length);
@@ -1269,7 +1269,7 @@ describe('model: querying:', function () {
         }
 
         function test3() {
-          Mod.find({$nor: [{num: 2}]}).nor([{str: 'two'}]).exec(function (err, found) {
+          Mod.find({$nor: [{num: 2}]}).nor([{str: 'two'}]).exec(function(err, found) {
             cb();
             assert.ifError(err);
             assert.equal(1, found.length);
@@ -1287,15 +1287,15 @@ describe('model: querying:', function () {
       });
     });
 
-    it('STRICT null matches', function (done) {
+    it('STRICT null matches', function(done) {
       var db = start();
       var BlogPostB = db.model('BlogPostB', collection + random());
 
       var a = {title: 'A', author: null};
       var b = {title: 'B'};
-      BlogPostB.create(a, b, function (err, createdA) {
+      BlogPostB.create(a, b, function(err, createdA) {
         assert.ifError(err);
-        BlogPostB.find({author: {$in: [null], $exists: true}}, function (err, found) {
+        BlogPostB.find({author: {$in: [null], $exists: true}}, function(err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(1, found.length);
@@ -1305,15 +1305,15 @@ describe('model: querying:', function () {
       });
     });
 
-    it('null matches null and undefined', function (done) {
+    it('null matches null and undefined', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection + random());
 
       BlogPostB.create(
           {title: 'A', author: null},
-          {title: 'B'}, function (err) {
+          {title: 'B'}, function(err) {
             assert.ifError(err);
-            BlogPostB.find({author: null}, function (err, found) {
+            BlogPostB.find({author: null}, function(err, found) {
               db.close();
               assert.ifError(err);
               assert.equal(2, found.length);
@@ -1322,7 +1322,7 @@ describe('model: querying:', function () {
           });
     });
 
-    it('a document whose arrays contain at least $all string values', function (done) {
+    it('a document whose arrays contain at least $all string values', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
@@ -1332,29 +1332,29 @@ describe('model: querying:', function () {
       post.tags.push('twox');
       post.tags.push('threex');
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPostB.findById(post._id, function (err, post) {
+        BlogPostB.findById(post._id, function(err, post) {
           assert.ifError(err);
 
-          BlogPostB.find({title: {'$all': ['Aristocats']}}, function (err, docs) {
+          BlogPostB.find({title: {'$all': ['Aristocats']}}, function(err, docs) {
             assert.ifError(err);
             assert.equal(1, docs.length);
 
-            BlogPostB.find({title: {'$all': [/^Aristocats/]}}, function (err, docs) {
+            BlogPostB.find({title: {'$all': [/^Aristocats/]}}, function(err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
 
-              BlogPostB.find({tags: {'$all': ['onex', 'twox', 'threex']}}, function (err, docs) {
+              BlogPostB.find({tags: {'$all': ['onex', 'twox', 'threex']}}, function(err, docs) {
                 assert.ifError(err);
                 assert.equal(1, docs.length);
 
-                BlogPostB.find({tags: {'$all': [/^onex/i]}}, function (err, docs) {
+                BlogPostB.find({tags: {'$all': [/^onex/i]}}, function(err, docs) {
                   assert.ifError(err);
                   assert.equal(1, docs.length);
 
-                  BlogPostB.findOne({tags: {'$all': /^two/}}, function (err, doc) {
+                  BlogPostB.findOne({tags: {'$all': /^two/}}, function(err, doc) {
                     db.close();
                     assert.ifError(err);
                     assert.equal(post.id, doc.id);
@@ -1368,7 +1368,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('using #nor with nested #elemMatch', function (done) {
+    it('using #nor with nested #elemMatch', function(done) {
       var db = start(),
           P = db.model('BlogPostB', collection + '_norWithNestedElemMatch');
 
@@ -1377,7 +1377,7 @@ describe('model: querying:', function () {
       var p1 = {title: 'nested $nor elemMatch0', comments: []};
       p1.comments.push({title: 'comment X'}, {title: 'comment Y'}, {title: 'comment W'});
 
-      P.create(p0, p1, function (err, post0, post1) {
+      P.create(p0, p1, function(err, post0, post1) {
         assert.ifError(err);
 
         var id = post1.comments[1]._id;
@@ -1385,7 +1385,7 @@ describe('model: querying:', function () {
         var query0 = {comments: {$elemMatch: {title: 'comment Z'}}};
         var query1 = {comments: {$elemMatch: {_id: id.toString(), title: 'comment Y'}}};
 
-        P.find({$nor: [query0, query1]}, function (err, posts) {
+        P.find({$nor: [query0, query1]}, function(err, posts) {
           db.close();
           assert.ifError(err);
           assert.equal(1, posts.length);
@@ -1395,32 +1395,32 @@ describe('model: querying:', function () {
       });
     });
 
-    it('strings via regexp', function (done) {
+    it('strings via regexp', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({title: 'Next to Normal'}, function (err, created) {
+      BlogPostB.create({title: 'Next to Normal'}, function(err, created) {
         assert.ifError(err);
-        BlogPostB.findOne({title: /^Next/}, function (err, found) {
+        BlogPostB.findOne({title: /^Next/}, function(err, found) {
           assert.ifError(err);
           assert.equal(found._id.toString(), created._id);
 
           var reg = '^Next to Normal$';
 
-          BlogPostB.find({title: {$regex: reg}}, function (err, found) {
+          BlogPostB.find({title: {$regex: reg}}, function(err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
             assert.equal(found[0]._id.toString(), created._id);
 
-            BlogPostB.findOne({title: {$regex: reg}}, function (err, found) {
+            BlogPostB.findOne({title: {$regex: reg}}, function(err, found) {
               assert.ifError(err);
               assert.equal(found._id.toString(), created._id);
 
-              BlogPostB.where('title').regex(reg).findOne(function (err, found) {
+              BlogPostB.where('title').regex(reg).findOne(function(err, found) {
                 assert.ifError(err);
                 assert.equal(found._id.toString(), created._id);
 
-                BlogPostB.where('title').regex(/^Next/).findOne(function (err, found) {
+                BlogPostB.where('title').regex(/^Next/).findOne(function(err, found) {
                   db.close();
                   assert.ifError(err);
                   assert.equal(found._id.toString(), created._id);
@@ -1433,22 +1433,22 @@ describe('model: querying:', function () {
       });
     });
 
-    it('a document whose arrays contain at least $all values', function (done) {
+    it('a document whose arrays contain at least $all values', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
       var a1 = {numbers: [-1, -2, -3, -4], meta: {visitors: 4}};
       var a2 = {numbers: [0, -1, -2, -3, -4]};
-      BlogPostB.create(a1, a2, function (err, whereoutZero, whereZero) {
+      BlogPostB.create(a1, a2, function(err, whereoutZero, whereZero) {
         assert.ifError(err);
 
-        BlogPostB.find({numbers: {$all: [-1, -2, -3, -4]}}, function (err, found) {
+        BlogPostB.find({numbers: {$all: [-1, -2, -3, -4]}}, function(err, found) {
           assert.ifError(err);
           assert.equal(2, found.length);
-          BlogPostB.find({'meta.visitors': {$all: [4]}}, function (err, found) {
+          BlogPostB.find({'meta.visitors': {$all: [4]}}, function(err, found) {
             assert.ifError(err);
             assert.equal(1, found.length);
             assert.equal(found[0]._id.toString(), whereoutZero._id);
-            BlogPostB.find({numbers: {$all: [0, -1]}}, function (err, found) {
+            BlogPostB.find({numbers: {$all: [0, -1]}}, function(err, found) {
               db.close();
               assert.ifError(err);
               assert.equal(1, found.length);
@@ -1460,20 +1460,20 @@ describe('model: querying:', function () {
       });
     });
 
-    it('where $size', function (done) {
+    it('where $size', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}, function (err) {
+      BlogPostB.create({numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}, function(err) {
         assert.ifError(err);
-        BlogPostB.create({numbers: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]}, function (err) {
+        BlogPostB.create({numbers: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]}, function(err) {
           assert.ifError(err);
-          BlogPostB.create({numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]}, function (err) {
+          BlogPostB.create({numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]}, function(err) {
             assert.ifError(err);
-            BlogPostB.find({numbers: {$size: 10}}, function (err, found) {
+            BlogPostB.find({numbers: {$size: 10}}, function(err, found) {
               assert.ifError(err);
               assert.equal(2, found.length);
-              BlogPostB.find({numbers: {$size: 11}}, function (err, found) {
+              BlogPostB.find({numbers: {$size: 11}}, function(err, found) {
                 assert.ifError(err);
                 assert.equal(1, found.length);
                 db.close();
@@ -1485,7 +1485,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('$gt, $lt, $lte, $gte work on strings', function (done) {
+    it('$gt, $lt, $lte, $gte work on strings', function(done) {
       var db = start();
       var D = db.model('D', new Schema({dt: String}), collection);
 
@@ -1508,7 +1508,7 @@ describe('model: querying:', function () {
 
         pending = 2;
 
-        D.find({'dt': {$gte: '2011-03-30', $lte: '2011-04-01'}}).sort('dt').exec(function (err, docs) {
+        D.find({'dt': {$gte: '2011-03-30', $lte: '2011-04-01'}}).sort('dt').exec(function(err, docs) {
           if (!--pending) {
             db.close();
             done();
@@ -1518,12 +1518,12 @@ describe('model: querying:', function () {
           assert.equal(docs[0].dt, '2011-03-30');
           assert.equal(docs[1].dt, '2011-03-31');
           assert.equal(docs[2].dt, '2011-04-01');
-          assert.equal(false, docs.some(function (d) {
+          assert.equal(false, docs.some(function(d) {
             return d.dt === '2011-04-02';
           }));
         });
 
-        D.find({'dt': {$gt: '2011-03-30', $lt: '2011-04-02'}}).sort('dt').exec(function (err, docs) {
+        D.find({'dt': {$gt: '2011-03-30', $lt: '2011-04-02'}}).sort('dt').exec(function(err, docs) {
           if (!--pending) {
             db.close();
             done();
@@ -1532,18 +1532,18 @@ describe('model: querying:', function () {
           assert.equal(2, docs.length);
           assert.equal(docs[0].dt, '2011-03-31');
           assert.equal(docs[1].dt, '2011-04-01');
-          assert.equal(false, docs.some(function (d) {
+          assert.equal(false, docs.some(function(d) {
             return d.dt === '2011-03-30';
           }));
-          assert.equal(false, docs.some(function (d) {
+          assert.equal(false, docs.some(function(d) {
             return d.dt === '2011-04-02';
           }));
         });
       }
     });
 
-    describe('text search indexes', function () {
-      it('works with text search ensure indexes ', function (done) {
+    describe('text search indexes', function() {
+      it('works with text search ensure indexes ', function(done) {
         if (!mongo26_or_greater) {
           return done();
         }
@@ -1551,24 +1551,24 @@ describe('model: querying:', function () {
         var db = start(),
             blogPost = db.model('BlogPostB', collection);
 
-        blogPost.collection.ensureIndex({title: 'text'}, function (error) {
+        blogPost.collection.ensureIndex({title: 'text'}, function(error) {
           assert.ifError(error);
           var a = new blogPost({title: 'querying in mongoose'});
           var b = new blogPost({title: 'text search in mongoose'});
-          a.save(function (error) {
+          a.save(function(error) {
             assert.ifError(error);
-            b.save(function (error) {
+            b.save(function(error) {
               assert.ifError(error);
               blogPost.
               find({$text: {$search: 'text search'}}, {score: {$meta: 'textScore'}}).
               limit(2).
-              exec(function (error, documents) {
+              exec(function(error, documents) {
                 assert.ifError(error);
                 assert.equal(1, documents.length);
                 assert.equal('text search in mongoose', documents[0].title);
-                a.remove(function (error) {
+                a.remove(function(error) {
                   assert.ifError(error);
-                  b.remove(function (error) {
+                  b.remove(function(error) {
                     assert.ifError(error);
                     db.close(done);
                   });
@@ -1579,7 +1579,7 @@ describe('model: querying:', function () {
         });
       });
 
-      it('works when text search is called by a schema', function (done) {
+      it('works when text search is called by a schema', function(done) {
         var db = start();
 
         var exampleSchema = new Schema({
@@ -1595,18 +1595,18 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('limit', function () {
-    it('works', function (done) {
+  describe('limit', function() {
+    it('works', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({title: 'first limit'}, function (err, first) {
+      BlogPostB.create({title: 'first limit'}, function(err, first) {
         assert.ifError(err);
-        BlogPostB.create({title: 'second limit'}, function (err, second) {
+        BlogPostB.create({title: 'second limit'}, function(err, second) {
           assert.ifError(err);
-          BlogPostB.create({title: 'third limit'}, function (err) {
+          BlogPostB.create({title: 'third limit'}, function(err) {
             assert.ifError(err);
-            BlogPostB.find({title: /limit$/}).limit(2).find(function (err, found) {
+            BlogPostB.find({title: /limit$/}).limit(2).find(function(err, found) {
               db.close();
               assert.ifError(err);
               assert.equal(2, found.length);
@@ -1620,18 +1620,18 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('skip', function () {
-    it('works', function (done) {
+  describe('skip', function() {
+    it('works', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({title: '1 skip'}, function (err) {
+      BlogPostB.create({title: '1 skip'}, function(err) {
         assert.ifError(err);
-        BlogPostB.create({title: '2 skip'}, function (err, second) {
+        BlogPostB.create({title: '2 skip'}, function(err, second) {
           assert.ifError(err);
-          BlogPostB.create({title: '3 skip'}, function (err, third) {
+          BlogPostB.create({title: '3 skip'}, function(err, third) {
             assert.ifError(err);
-            BlogPostB.find({title: /skip$/}).sort({title: 1}).skip(1).limit(2).find(function (err, found) {
+            BlogPostB.find({title: /skip$/}).sort({title: 1}).skip(1).limit(2).find(function(err, found) {
               assert.ifError(err);
               assert.equal(2, found.length);
               assert.equal(found[0].id, second._id);
@@ -1645,21 +1645,21 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('sort', function () {
-    it('works', function (done) {
+  describe('sort', function() {
+    it('works', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.create({meta: {visitors: 100}}, function (err, least) {
+      BlogPostB.create({meta: {visitors: 100}}, function(err, least) {
         assert.ifError(err);
-        BlogPostB.create({meta: {visitors: 300}}, function (err, largest) {
+        BlogPostB.create({meta: {visitors: 300}}, function(err, largest) {
           assert.ifError(err);
-          BlogPostB.create({meta: {visitors: 200}}, function (err, middle) {
+          BlogPostB.create({meta: {visitors: 200}}, function(err, middle) {
             assert.ifError(err);
             BlogPostB
             .where('meta.visitors').gt(99).lt(301)
             .sort('-meta.visitors')
-            .find(function (err, found) {
+            .find(function(err, found) {
               assert.ifError(err);
               assert.equal(3, found.length);
               assert.equal(found[0].id, largest._id);
@@ -1672,7 +1672,7 @@ describe('model: querying:', function () {
         });
       });
     });
-    it('handles sorting by text score', function (done) {
+    it('handles sorting by text score', function(done) {
       if (!mongo26_or_greater) {
         return done();
       }
@@ -1680,19 +1680,19 @@ describe('model: querying:', function () {
       var db = start(),
           blogPost = db.model('BlogPostB', collection);
 
-      blogPost.collection.ensureIndex({title: 'text'}, function (error) {
+      blogPost.collection.ensureIndex({title: 'text'}, function(error) {
         assert.ifError(error);
         var a = new blogPost({title: 'searching in mongoose'});
         var b = new blogPost({title: 'text search in mongoose'});
-        a.save(function (error) {
+        a.save(function(error) {
           assert.ifError(error);
-          b.save(function (error) {
+          b.save(function(error) {
             assert.ifError(error);
             blogPost.
             find({$text: {$search: 'text search'}}, {score: {$meta: 'textScore'}}).
             sort({score: {$meta: 'textScore'}}).
             limit(2).
-            exec(function (error, documents) {
+            exec(function(error, documents) {
               assert.ifError(error);
               assert.equal(2, documents.length);
               assert.equal('text search in mongoose', documents[0].title);
@@ -1706,12 +1706,12 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('nested mixed "x.y.z"', function () {
-    it('works', function (done) {
+  describe('nested mixed "x.y.z"', function() {
+    it('works', function(done) {
       var db = start(),
           BlogPostB = db.model('BlogPostB', collection);
 
-      BlogPostB.find({'mixed.nested.stuff': 'skynet'}, function (err) {
+      BlogPostB.find({'mixed.nested.stuff': 'skynet'}, function(err) {
         db.close();
         assert.ifError(err);
         done();
@@ -1719,15 +1719,15 @@ describe('model: querying:', function () {
     });
   });
 
-  it('by Date (gh-336)', function (done) {
+  it('by Date (gh-336)', function(done) {
     // GH-336
     var db = start(),
         Test = db.model('TestDateQuery', new Schema({date: Date}), 'datetest_' + random()),
         now = new Date;
 
-    Test.create({date: now}, {date: new Date(now - 10000)}, function (err) {
+    Test.create({date: now}, {date: new Date(now - 10000)}, function(err) {
       assert.ifError(err);
-      Test.find({date: now}, function (err, docs) {
+      Test.find({date: now}, function(err, docs) {
         db.close();
         assert.ifError(err);
         assert.equal(1, docs.length);
@@ -1736,7 +1736,7 @@ describe('model: querying:', function () {
     });
   });
 
-  it('mixed types with $elemMatch (gh-591)', function (done) {
+  it('mixed types with $elemMatch (gh-591)', function(done) {
     var db = start(),
         S = new Schema({a: [{}], b: Number}),
         M = db.model('QueryingMixedArrays', S, random());
@@ -1745,10 +1745,10 @@ describe('model: querying:', function () {
     m.a = [1, 2, {name: 'Frodo'}, 'IDK', {name: 100}];
     m.b = 10;
 
-    m.save(function (err) {
+    m.save(function(err) {
       assert.ifError(err);
 
-      M.find({a: {name: 'Frodo'}, b: '10'}, function (err, docs) {
+      M.find({a: {name: 'Frodo'}, b: '10'}, function(err, docs) {
         assert.ifError(err);
         assert.equal(5, docs[0].a.length);
         assert.equal(10, docs[0].b.valueOf());
@@ -1759,7 +1759,7 @@ describe('model: querying:', function () {
           }
         };
 
-        M.find(query, function (err, docs) {
+        M.find(query, function(err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(5, docs[0].a.length);
@@ -1769,8 +1769,8 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('$all', function () {
-    it('with ObjectIds (gh-690)', function (done) {
+  describe('$all', function() {
+    it('with ObjectIds (gh-690)', function(done) {
       var db = start();
 
       var SSchema = new Schema({name: String});
@@ -1779,22 +1779,22 @@ describe('model: querying:', function () {
       var P = db.model('usingAllWithObjectIds', PSchema);
       var sub = [{name: 'one'}, {name: 'two'}, {name: 'three'}];
 
-      P.create({sub: sub}, function (err, p) {
+      P.create({sub: sub}, function(err, p) {
         assert.ifError(err);
 
         var o0 = p.sub[0]._id;
         var o1 = p.sub[1]._id;
         var o2 = p.sub[2]._id;
 
-        P.findOne({'sub._id': {$all: [o1, o2.toString()]}}, function (err, doc) {
+        P.findOne({'sub._id': {$all: [o1, o2.toString()]}}, function(err, doc) {
           assert.ifError(err);
           assert.equal(doc.id, p.id);
 
-          P.findOne({'sub._id': {$all: [o0, new DocumentObjectId]}}, function (err, doc) {
+          P.findOne({'sub._id': {$all: [o0, new DocumentObjectId]}}, function(err, doc) {
             assert.ifError(err);
             assert.equal(false, !!doc);
 
-            P.findOne({'sub._id': {$all: [o2]}}, function (err, doc) {
+            P.findOne({'sub._id': {$all: [o2]}}, function(err, doc) {
               db.close();
               assert.ifError(err);
               assert.equal(doc.id, p.id);
@@ -1805,7 +1805,7 @@ describe('model: querying:', function () {
       });
     });
 
-    it('with Dates', function (done) {
+    it('with Dates', function(done) {
       this.timeout(3000);
       var db = start();
 
@@ -1819,22 +1819,22 @@ describe('model: querying:', function () {
         {d: new Date(Date.now() - 30000)}
       ];
 
-      P.create({sub: sub}, function (err, p) {
+      P.create({sub: sub}, function(err, p) {
         assert.ifError(err);
 
         var o0 = p.sub[0].d;
         var o1 = p.sub[1].d;
         var o2 = p.sub[2].d;
 
-        P.findOne({'sub.d': {$all: [o1, o2]}}, function (err, doc) {
+        P.findOne({'sub.d': {$all: [o1, o2]}}, function(err, doc) {
           assert.ifError(err);
           assert.equal(doc.id, p.id);
 
-          P.findOne({'sub.d': {$all: [o0, new Date]}}, function (err, doc) {
+          P.findOne({'sub.d': {$all: [o0, new Date]}}, function(err, doc) {
             assert.ifError(err);
             assert.equal(false, !!doc);
 
-            P.findOne({'sub.d': {$all: [o2]}}, function (err, doc) {
+            P.findOne({'sub.d': {$all: [o2]}}, function(err, doc) {
               assert.ifError(err);
               assert.equal(doc.id, p.id);
               db.close(done);
@@ -1844,10 +1844,10 @@ describe('model: querying:', function () {
       });
     });
 
-    it('with $elemMatch (gh-3163)', function (done) {
+    it('with $elemMatch (gh-3163)', function(done) {
       var db = start();
 
-      start.mongodVersion(function (err, version) {
+      start.mongodVersion(function(err, version) {
         if (err) {
           throw err;
         }
@@ -1859,14 +1859,14 @@ describe('model: querying:', function () {
         next();
       });
 
-      var next = function () {
+      var next = function() {
         var schema = new Schema({test: [String]});
         var MyModel = db.model('gh3163', schema);
 
-        MyModel.create({test: ['log1', 'log2']}, function (error) {
+        MyModel.create({test: ['log1', 'log2']}, function(error) {
           assert.ifError(error);
           var query = {test: {$all: [{$elemMatch: {$regex: /log/g}}]}};
-          MyModel.find(query, function (error, docs) {
+          MyModel.find(query, function(error, docs) {
             assert.ifError(error);
             assert.equal(docs.length, 1);
             db.close(done);
@@ -1876,23 +1876,23 @@ describe('model: querying:', function () {
     });
   });
 
-  describe('and', function () {
-    it('works with queries gh-1188', function (done) {
+  describe('and', function() {
+    it('works with queries gh-1188', function(done) {
       var db = start();
       var B = db.model('BlogPostB');
 
-      B.create({title: 'and operator', published: false, author: 'Me'}, function (err) {
+      B.create({title: 'and operator', published: false, author: 'Me'}, function(err) {
         assert.ifError(err);
 
-        B.find({$and: [{title: 'and operator'}]}, function (err, docs) {
+        B.find({$and: [{title: 'and operator'}]}, function(err, docs) {
           assert.ifError(err);
           assert.equal(1, docs.length);
 
-          B.find({$and: [{title: 'and operator'}, {published: true}]}, function (err, docs) {
+          B.find({$and: [{title: 'and operator'}, {published: true}]}, function(err, docs) {
             assert.ifError(err);
             assert.equal(0, docs.length);
 
-            B.find({$and: [{title: 'and operator'}, {published: false}]}, function (err, docs) {
+            B.find({$and: [{title: 'and operator'}, {published: false}]}, function(err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
 
@@ -1901,7 +1901,7 @@ describe('model: querying:', function () {
                 {title: 'and operator', published: false},
                 {author: 'Me'}
               ]);
-              query.exec(function (err, docs) {
+              query.exec(function(err, docs) {
                 assert.ifError(err);
                 assert.equal(1, docs.length);
 
@@ -1910,7 +1910,7 @@ describe('model: querying:', function () {
                   {title: 'and operator', published: false},
                   {author: 'You'}
                 ]);
-                query.exec(function (err, docs) {
+                query.exec(function(err, docs) {
                   assert.ifError(err);
                   assert.equal(0, docs.length);
                   db.close(done);
@@ -1922,11 +1922,11 @@ describe('model: querying:', function () {
       });
     });
 
-    it('works with nested query selectors gh-1884', function (done) {
+    it('works with nested query selectors gh-1884', function(done) {
       var db = start();
       var B = db.model('gh1884', {a: String, b: String}, 'gh1884');
 
-      B.remove({$and: [{a: 'coffee'}, {b: {$in: ['bacon', 'eggs']}}]}, function (error) {
+      B.remove({$and: [{a: 'coffee'}, {b: {$in: ['bacon', 'eggs']}}]}, function(error) {
         assert.ifError(error);
         db.close(done);
       });
@@ -1934,8 +1934,8 @@ describe('model: querying:', function () {
   });
 });
 
-describe('buffers', function () {
-  it('works with different methods and query types', function (done) {
+describe('buffers', function() {
+  it('works with different methods and query types', function(done) {
     var db = start(),
         BufSchema = new Schema({name: String, block: Buffer}),
         Test = db.model('Buffer', BufSchema, 'buffers');
@@ -1944,39 +1944,39 @@ describe('buffers', function () {
     var docB = {name: 'B', block: new Buffer('buffer shtuffs are neat')};
     var docC = {name: 'C', block: 'hello world'};
 
-    Test.create(docA, docB, docC, function (err, a, b, c) {
+    Test.create(docA, docB, docC, function(err, a, b, c) {
       assert.ifError(err);
       assert.equal(b.block.toString('utf8'), 'buffer shtuffs are neat');
       assert.equal(a.block.toString('utf8'), 'über');
       assert.equal(c.block.toString('utf8'), 'hello world');
 
-      Test.findById(a._id, function (err, a) {
+      Test.findById(a._id, function(err, a) {
         assert.ifError(err);
         assert.equal(a.block.toString('utf8'), 'über');
 
-        Test.findOne({block: 'buffer shtuffs are neat'}, function (err, rb) {
+        Test.findOne({block: 'buffer shtuffs are neat'}, function(err, rb) {
           assert.ifError(err);
           assert.equal(rb.block.toString('utf8'), 'buffer shtuffs are neat');
 
-          Test.findOne({block: /buffer/i}, function (err) {
+          Test.findOne({block: /buffer/i}, function(err) {
             assert.equal(err.message, 'Cast to buffer failed for value "/buffer/i" at path "block"');
-            Test.findOne({block: [195, 188, 98, 101, 114]}, function (err, rb) {
+            Test.findOne({block: [195, 188, 98, 101, 114]}, function(err, rb) {
               assert.ifError(err);
               assert.equal(rb.block.toString('utf8'), 'über');
 
-              Test.findOne({block: 'aGVsbG8gd29ybGQ='}, function (err, rb) {
+              Test.findOne({block: 'aGVsbG8gd29ybGQ='}, function(err, rb) {
                 assert.ifError(err);
                 assert.strictEqual(rb, null);
 
-                Test.findOne({block: new Buffer('aGVsbG8gd29ybGQ=', 'base64')}, function (err, rb) {
+                Test.findOne({block: new Buffer('aGVsbG8gd29ybGQ=', 'base64')}, function(err, rb) {
                   assert.ifError(err);
                   assert.equal(rb.block.toString('utf8'), 'hello world');
 
-                  Test.findOne({block: new MongooseBuffer('aGVsbG8gd29ybGQ=', 'base64')}, function (err, rb) {
+                  Test.findOne({block: new MongooseBuffer('aGVsbG8gd29ybGQ=', 'base64')}, function(err, rb) {
                     assert.ifError(err);
                     assert.equal(rb.block.toString('utf8'), 'hello world');
 
-                    Test.remove({}, function (err) {
+                    Test.remove({}, function(err) {
                       db.close();
                       assert.ifError(err);
                       done();
@@ -1991,7 +1991,7 @@ describe('buffers', function () {
     });
   });
 
-  it('with conditionals', function (done) {
+  it('with conditionals', function(done) {
     // $in $nin etc
     var db = start(),
         BufSchema = new Schema({name: String, block: Buffer}),
@@ -2001,63 +2001,63 @@ describe('buffers', function () {
     var docB = {name: 'B', block: new MongooseBuffer('buffer shtuffs are neat')};
     var docC = {name: 'C', block: new MongooseBuffer('aGVsbG8gd29ybGQ=', 'base64')};
 
-    Test.create(docA, docB, docC, function (err, a, b, c) {
+    Test.create(docA, docB, docC, function(err, a, b, c) {
       assert.ifError(err);
       assert.equal(a.block.toString('utf8'), 'über');
       assert.equal(b.block.toString('utf8'), 'buffer shtuffs are neat');
       assert.equal(c.block.toString('utf8'), 'hello world');
 
-      Test.find({block: {$in: [[195, 188, 98, 101, 114], 'buffer shtuffs are neat', new Buffer('aGVsbG8gd29ybGQ=', 'base64')]}}, function (err, tests) {
+      Test.find({block: {$in: [[195, 188, 98, 101, 114], 'buffer shtuffs are neat', new Buffer('aGVsbG8gd29ybGQ=', 'base64')]}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(3, tests.length);
       });
 
-      Test.find({block: {$in: ['über', 'hello world']}}, function (err, tests) {
+      Test.find({block: {$in: ['über', 'hello world']}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
       });
 
-      Test.find({block: {$in: ['über']}}, function (err, tests) {
+      Test.find({block: {$in: ['über']}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(1, tests.length);
         assert.equal(tests[0].block.toString('utf8'), 'über');
       });
 
-      Test.find({block: {$nin: ['über']}}, function (err, tests) {
+      Test.find({block: {$nin: ['über']}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
       });
 
-      Test.find({block: {$nin: [[195, 188, 98, 101, 114], new Buffer('aGVsbG8gd29ybGQ=', 'base64')]}}, function (err, tests) {
+      Test.find({block: {$nin: [[195, 188, 98, 101, 114], new Buffer('aGVsbG8gd29ybGQ=', 'base64')]}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(1, tests.length);
         assert.equal(tests[0].block.toString('utf8'), 'buffer shtuffs are neat');
       });
 
-      Test.find({block: {$ne: 'über'}}, function (err, tests) {
+      Test.find({block: {$ne: 'über'}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
       });
 
-      Test.find({block: {$gt: 'über'}}, function (err, tests) {
+      Test.find({block: {$gt: 'über'}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
       });
 
-      Test.find({block: {$gte: 'über'}}, function (err, tests) {
+      Test.find({block: {$gte: 'über'}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(3, tests.length);
       });
 
-      Test.find({block: {$lt: new Buffer('buffer shtuffs are neat')}}, function (err, tests) {
+      Test.find({block: {$lt: new Buffer('buffer shtuffs are neat')}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(2, tests.length);
@@ -2068,7 +2068,7 @@ describe('buffers', function () {
         assert.ok(ret['über'] !== undefined);
       });
 
-      Test.find({block: {$lte: 'buffer shtuffs are neat'}}, function (err, tests) {
+      Test.find({block: {$lte: 'buffer shtuffs are neat'}}, function(err, tests) {
         cb();
         assert.ifError(err);
         assert.equal(3, tests.length);
@@ -2080,7 +2080,7 @@ describe('buffers', function () {
         if (--pending) {
           return;
         }
-        Test.remove({}, function (err) {
+        Test.remove({}, function(err) {
           db.close();
           assert.ifError(err);
           done();
@@ -2090,16 +2090,16 @@ describe('buffers', function () {
   });
 });
 
-describe('backwards compatibility', function () {
-  it('with previously existing null values in the db', function (done) {
+describe('backwards compatibility', function() {
+  it('with previously existing null values in the db', function(done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         post = new BlogPostB();
 
-    post.collection.insert({meta: {visitors: 9898, a: null}}, {}, function (err, b) {
+    post.collection.insert({meta: {visitors: 9898, a: null}}, {}, function(err, b) {
       assert.ifError(err);
 
-      BlogPostB.findOne({_id: b.ops[0]._id}, function (err, found) {
+      BlogPostB.findOne({_id: b.ops[0]._id}, function(err, found) {
         assert.ifError(err);
         assert.equal(9898, found.get('meta.visitors').valueOf());
         db.close();
@@ -2108,18 +2108,18 @@ describe('backwards compatibility', function () {
     });
   });
 
-  it('with unused values in the db', function (done) {
+  it('with unused values in the db', function(done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         post = new BlogPostB();
 
-    post.collection.insert({meta: {visitors: 9898, color: 'blue'}}, {}, function (err, b) {
+    post.collection.insert({meta: {visitors: 9898, color: 'blue'}}, {}, function(err, b) {
       assert.ifError(err);
 
-      BlogPostB.findOne({_id: b.ops[0]._id}, function (err, found) {
+      BlogPostB.findOne({_id: b.ops[0]._id}, function(err, found) {
         assert.ifError(err);
         assert.equal(9898, found.get('meta.visitors').valueOf());
-        found.save(function (err) {
+        found.save(function(err) {
           assert.ifError(err);
           db.close();
           done();
@@ -2129,9 +2129,9 @@ describe('backwards compatibility', function () {
   });
 });
 
-describe('geo-spatial', function () {
-  describe('2d', function () {
-    it('$near (gh-309)', function (done) {
+describe('geo-spatial', function() {
+  describe('2d', function() {
+    it('$near (gh-309)', function(done) {
       var db = start(),
           Test = db.model('Geo1', geoSchema, 'geospatial' + random());
 
@@ -2151,7 +2151,7 @@ describe('geo-spatial', function () {
       Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
       function test() {
-        Test.find({loc: {$near: [30, 40]}}, function (err, docs) {
+        Test.find({loc: {$near: [30, 40]}}, function(err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(2, docs.length);
@@ -2160,7 +2160,7 @@ describe('geo-spatial', function () {
       }
     });
 
-    it('$within arrays (gh-586)', function (done) {
+    it('$within arrays (gh-586)', function(done) {
       var db = start(),
           Test = db.model('Geo2', geoSchema, collection + 'geospatial');
 
@@ -2180,7 +2180,7 @@ describe('geo-spatial', function () {
       Test.create({loc: [35, 50]}, {loc: [-40, -90]}, complete);
 
       function test() {
-        Test.find({loc: {'$within': {'$box': [[30, 40], [40, 60]]}}}, function (err, docs) {
+        Test.find({loc: {'$within': {'$box': [[30, 40], [40, 60]]}}}, function(err, docs) {
           db.close();
           assert.ifError(err);
           assert.equal(1, docs.length);
@@ -2189,7 +2189,7 @@ describe('geo-spatial', function () {
       }
     });
 
-    it('$nearSphere with arrays (gh-610)', function (done) {
+    it('$nearSphere with arrays (gh-610)', function(done) {
       var db = start(),
           Test = db.model('Geo3', geoSchema, 'y' + random());
 
@@ -2209,7 +2209,7 @@ describe('geo-spatial', function () {
       Test.create({loc: [10, 20]}, {loc: [40, 90]}, complete);
 
       function test() {
-        Test.find({loc: {$nearSphere: [30, 40]}}, function (err, docs) {
+        Test.find({loc: {$nearSphere: [30, 40]}}, function(err, docs) {
           assert.ifError(err);
           assert.equal(2, docs.length);
           db.close(done);
@@ -2217,7 +2217,7 @@ describe('geo-spatial', function () {
       }
     });
 
-    it('$nearSphere with invalid coordinate does not crash (gh-1874)', function (done) {
+    it('$nearSphere with invalid coordinate does not crash (gh-1874)', function(done) {
       var geoSchema = new Schema({
         loc: {
           type: {type: String},
@@ -2228,7 +2228,7 @@ describe('geo-spatial', function () {
           Test = db.model('gh1874', geoSchema, 'gh1874');
 
       var pending = 2;
-      var complete = function (err) {
+      var complete = function(err) {
         if (complete.ran) {
           return;
         }
@@ -2244,7 +2244,7 @@ describe('geo-spatial', function () {
           {loc: {coordinates: [31, 40]}},
           complete);
 
-      var test = function () {
+      var test = function() {
         var q = new Query({}, {}, null, Test.collection);
         q.find({
           'loc': {
@@ -2255,7 +2255,7 @@ describe('geo-spatial', function () {
           }
         });
 
-        assert.doesNotThrow(function () {
+        assert.doesNotThrow(function() {
           q.cast(Test);
         });
 
@@ -2263,7 +2263,7 @@ describe('geo-spatial', function () {
       };
     });
 
-    it('$maxDistance with arrays', function (done) {
+    it('$maxDistance with arrays', function(done) {
       var db = start(),
           Test = db.model('Geo4', geoSchema, 'x' + random());
 
@@ -2283,10 +2283,10 @@ describe('geo-spatial', function () {
       Test.create({loc: [20, 80]}, {loc: [25, 30]}, complete);
 
       function test() {
-        Test.find({loc: {$near: [25, 31], $maxDistance: 1}}, function (err, docs) {
+        Test.find({loc: {$near: [25, 31], $maxDistance: 1}}, function(err, docs) {
           assert.ifError(err);
           assert.equal(1, docs.length);
-          Test.find({loc: {$near: [25, 32], $maxDistance: 1}}, function (err, docs) {
+          Test.find({loc: {$near: [25, 32], $maxDistance: 1}}, function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(0, docs.length);
@@ -2297,7 +2297,7 @@ describe('geo-spatial', function () {
     });
   });
 
-  describe('2dsphere', function () {
+  describe('2dsphere', function() {
     // mongodb 2.4
 
     var schema2dsphere = new Schema({loc: {type: [Number], index: '2dsphere'}});
@@ -2310,8 +2310,8 @@ describe('geo-spatial', function () {
     // geoMultiSchema.index({ geom: '2dsphere' });
 
     var mongo24_or_greater = false;
-    before(function (done) {
-      start.mongodVersion(function (err, version) {
+    before(function(done) {
+      start.mongodVersion(function(err, version) {
         if (err) {
           throw err;
         }
@@ -2324,20 +2324,20 @@ describe('geo-spatial', function () {
       });
     });
 
-    it('index is allowed in schema', function (done) {
+    it('index is allowed in schema', function(done) {
       if (!mongo24_or_greater) {
         return done();
       }
 
-      var ok = schema2dsphere.indexes().some(function (index) {
+      var ok = schema2dsphere.indexes().some(function(index) {
         return index[0].loc === '2dsphere';
       });
       assert.ok(ok);
       done();
     });
 
-    describe('$geometry', function () {
-      it('Polygon', function (done) {
+    describe('$geometry', function() {
+      it('Polygon', function(done) {
         if (!mongo24_or_greater) {
           return done();
         }
@@ -2345,20 +2345,20 @@ describe('geo-spatial', function () {
         var db = start(),
             Test = db.model('2dsphere-polygon', schema2dsphere, 'geospatial' + random());
 
-        Test.on('index', function (err) {
+        Test.on('index', function(err) {
           assert.ifError(err);
 
-          Test.create({loc: [0, 0]}, function (err, created) {
+          Test.create({loc: [0, 0]}, function(err, created) {
             assert.ifError(err);
 
             var geojsonPoly = {type: 'Polygon', coordinates: [[[-5, -5], ['-5', 5], [5, 5], [5, -5], [-5, '-5']]]};
 
-            Test.find({loc: {$within: {$geometry: geojsonPoly}}}, function (err, docs) {
+            Test.find({loc: {$within: {$geometry: geojsonPoly}}}, function(err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
               assert.equal(created.id, docs[0].id);
 
-              Test.where('loc').within().geometry(geojsonPoly).exec(function (err, docs) {
+              Test.where('loc').within().geometry(geojsonPoly).exec(function(err, docs) {
                 assert.ifError(err);
                 assert.equal(1, docs.length);
                 assert.equal(created.id, docs[0].id);
@@ -2370,8 +2370,8 @@ describe('geo-spatial', function () {
       });
     });
 
-    describe('$geoIntersects', function () {
-      it('LineString', function (done) {
+    describe('$geoIntersects', function() {
+      it('LineString', function(done) {
         if (!mongo24_or_greater) {
           return done();
         }
@@ -2379,20 +2379,20 @@ describe('geo-spatial', function () {
         var db = start(),
             Test = db.model('2dsphere-geo', geoSchema, 'geospatial' + random());
 
-        Test.on('index', function (err) {
+        Test.on('index', function(err) {
           assert.ifError(err);
 
-          Test.create({line: {type: 'LineString', coordinates: [[-178.0, 10.0], [178.0, 10.0]]}}, function (err, created) {
+          Test.create({line: {type: 'LineString', coordinates: [[-178.0, 10.0], [178.0, 10.0]]}}, function(err, created) {
             assert.ifError(err);
 
             var geojsonLine = {type: 'LineString', coordinates: [[180.0, 11.0], [180.0, '9.00']]};
 
-            Test.find({line: {$geoIntersects: {$geometry: geojsonLine}}}, function (err, docs) {
+            Test.find({line: {$geoIntersects: {$geometry: geojsonLine}}}, function(err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
               assert.equal(created.id, docs[0].id);
 
-              Test.where('line').intersects().geometry(geojsonLine).findOne(function (err, doc) {
+              Test.where('line').intersects().geometry(geojsonLine).findOne(function(err, doc) {
                 assert.ifError(err);
                 assert.equal(created.id, doc.id);
                 db.close(done);
@@ -2402,7 +2402,7 @@ describe('geo-spatial', function () {
         });
       });
 
-      it('MultiLineString', function (done) {
+      it('MultiLineString', function(done) {
         if (!mongo24_or_greater) {
           return done();
         }
@@ -2413,17 +2413,17 @@ describe('geo-spatial', function () {
         Test.create({
           geom: [{type: 'LineString', coordinates: [[-178.0, 10.0], [178.0, 10.0]]},
             {type: 'LineString', coordinates: [[-178.0, 5.0], [178.0, 5.0]]}]
-        }, function (err, created) {
+        }, function(err, created) {
           assert.ifError(err);
 
           var geojsonLine = {type: 'LineString', coordinates: [[180.0, 11.0], [180.0, '9.00']]};
 
-          Test.find({geom: {$geoIntersects: {$geometry: geojsonLine}}}, function (err, docs) {
+          Test.find({geom: {$geoIntersects: {$geometry: geojsonLine}}}, function(err, docs) {
             assert.ifError(err);
             assert.equal(1, docs.length);
             assert.equal(created.id, docs[0].id);
 
-            Test.where('geom').intersects().geometry(geojsonLine).findOne(function (err, doc) {
+            Test.where('geom').intersects().geometry(geojsonLine).findOne(function(err, doc) {
               assert.ifError(err);
               assert.equal(created.id, doc.id);
               db.close(done);
@@ -2432,7 +2432,7 @@ describe('geo-spatial', function () {
         });
       });
 
-      it('MultiPolygon', function (done) {
+      it('MultiPolygon', function(done) {
         if (!mongo24_or_greater) {
           return done();
         }
@@ -2443,17 +2443,17 @@ describe('geo-spatial', function () {
         Test.create({
           geom: [{type: 'Polygon', coordinates: [[[28.7, 41], [29.2, 40.9], [29.1, 41.3], [28.7, 41]]]},
             {type: 'Polygon', coordinates: [[[-1, -1], [1, -1], [1, 1], [-1, 1], [-1, -1]]]}]
-        }, function (err, created) {
+        }, function(err, created) {
           assert.ifError(err);
 
           var geojsonPolygon = {type: 'Polygon', coordinates: [[[26, 36], [45, 36], [45, 42], [26, 42], [26, 36]]]};
 
-          Test.find({geom: {$geoIntersects: {$geometry: geojsonPolygon}}}, function (err, docs) {
+          Test.find({geom: {$geoIntersects: {$geometry: geojsonPolygon}}}, function(err, docs) {
             assert.ifError(err);
             assert.equal(1, docs.length);
             assert.equal(created.id, docs[0].id);
 
-            Test.where('geom').intersects().geometry(geojsonPolygon).findOne(function (err, doc) {
+            Test.where('geom').intersects().geometry(geojsonPolygon).findOne(function(err, doc) {
               assert.ifError(err);
               assert.equal(created.id, doc.id);
               db.close(done);
@@ -2463,8 +2463,8 @@ describe('geo-spatial', function () {
       });
     });
 
-    describe('$near', function () {
-      it('Point', function (done) {
+    describe('$near', function() {
+      it('Point', function(done) {
         if (!mongo24_or_greater) {
           return done();
         }
@@ -2472,20 +2472,20 @@ describe('geo-spatial', function () {
         var db = start(),
             Test = db.model('2dsphere-geo', geoSchema, 'geospatial' + random());
 
-        Test.on('index', function (err) {
+        Test.on('index', function(err) {
           assert.ifError(err);
 
-          Test.create({line: {type: 'Point', coordinates: [-179.0, 0.0]}}, function (err, created) {
+          Test.create({line: {type: 'Point', coordinates: [-179.0, 0.0]}}, function(err, created) {
             assert.ifError(err);
 
             var geojsonPoint = {type: 'Point', coordinates: [-179.0, 0.0]};
 
-            Test.find({line: {$near: geojsonPoint}}, function (err, docs) {
+            Test.find({line: {$near: geojsonPoint}}, function(err, docs) {
               assert.ifError(err);
               assert.equal(1, docs.length);
               assert.equal(created.id, docs[0].id);
 
-              Test.find({line: {$near: {$geometry: geojsonPoint, $maxDistance: 50}}}, function (err, docs) {
+              Test.find({line: {$near: {$geometry: geojsonPoint, $maxDistance: 50}}}, function(err, docs) {
                 assert.ifError(err);
                 assert.equal(1, docs.length);
                 assert.equal(created.id, docs[0].id);
@@ -2496,7 +2496,7 @@ describe('geo-spatial', function () {
         });
       });
 
-      it('works with GeoJSON (gh-1482)', function (done) {
+      it('works with GeoJSON (gh-1482)', function(done) {
         if (!mongo24_or_greater) {
           return done();
         }
@@ -2533,7 +2533,7 @@ describe('geo-spatial', function () {
             center: {
               type: 'Point', coordinates: [11, 20]
             }, maxDistance: 1000000
-          }).exec(function (err, docs) {
+          }).exec(function(err, docs) {
             db.close();
             assert.ifError(err);
             assert.equal(1, docs.length);
@@ -2544,11 +2544,11 @@ describe('geo-spatial', function () {
     });
   });
 
-  describe('hashed indexes', function () {
+  describe('hashed indexes', function() {
     var mongo24_or_greater = false;
 
-    before(function (done) {
-      start.mongodVersion(function (err, version) {
+    before(function(done) {
+      start.mongodVersion(function(err, version) {
         if (err) {
           return done(err);
         }
@@ -2560,7 +2560,7 @@ describe('geo-spatial', function () {
       });
     });
 
-    it('work', function (done) {
+    it('work', function(done) {
       if (!mongo24_or_greater) {
         return done();
       }
@@ -2572,19 +2572,19 @@ describe('geo-spatial', function () {
 
       var pending = schemas.length;
 
-      schemas.forEach(function (schema, i) {
+      schemas.forEach(function(schema, i) {
         var H = db.model('Hashed' + i, schema);
-        H.on('index', function (err) {
+        H.on('index', function(err) {
           assert.ifError(err);
-          H.collection.getIndexes({full: true}, function (err, indexes) {
+          H.collection.getIndexes({full: true}, function(err, indexes) {
             assert.ifError(err);
 
-            var found = indexes.some(function (index) {
+            var found = indexes.some(function(index) {
               return index.key.t === 'hashed';
             });
             assert.ok(found);
 
-            H.create({t: 'hashing'}, {}, function (err, doc1, doc2) {
+            H.create({t: 'hashing'}, {}, function(err, doc1, doc2) {
               assert.ifError(err);
               assert.ok(doc1);
               assert.ok(doc2);
@@ -2603,8 +2603,8 @@ describe('geo-spatial', function () {
   });
 });
 
-describe('lean option:', function () {
-  it('find', function (done) {
+describe('lean option:', function() {
+  it('find', function(done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         title = 'Wooooot ' + random();
@@ -2612,13 +2612,13 @@ describe('lean option:', function () {
     var post = new BlogPostB();
     post.set('title', title);
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
-      BlogPostB.find({title: title}).lean().exec(function (err, docs) {
+      BlogPostB.find({title: title}).lean().exec(function(err, docs) {
         assert.ifError(err);
         assert.equal(docs.length, 1);
         assert.strictEqual(docs[0] instanceof mongoose.Document, false);
-        BlogPostB.find({title: title}, null, {lean: true}, function (err, docs) {
+        BlogPostB.find({title: title}, null, {lean: true}, function(err, docs) {
           assert.ifError(err);
           assert.equal(docs.length, 1);
           assert.strictEqual(docs[0] instanceof mongoose.Document, false);
@@ -2629,7 +2629,7 @@ describe('lean option:', function () {
     });
   });
 
-  it('findOne', function (done) {
+  it('findOne', function(done) {
     var db = start(),
         BlogPostB = db.model('BlogPostB', collection),
         title = 'Wooooot ' + random();
@@ -2637,9 +2637,9 @@ describe('lean option:', function () {
     var post = new BlogPostB();
     post.set('title', title);
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
-      BlogPostB.findOne({title: title}, null, {lean: true}, function (err, doc) {
+      BlogPostB.findOne({title: title}, null, {lean: true}, function(err, doc) {
         db.close();
         assert.ifError(err);
         assert.ok(doc);
@@ -2648,7 +2648,7 @@ describe('lean option:', function () {
       });
     });
   });
-  it('properly casts nested and/or queries (gh-676)', function (done) {
+  it('properly casts nested and/or queries (gh-676)', function(done) {
     var sch = new Schema({
       num: Number,
       subdoc: {title: String, num: Number}
@@ -2669,7 +2669,7 @@ describe('lean option:', function () {
     assert.equal('number', typeof q._conditions.$and[1].$and[1].num);
     done();
   });
-  it('properly casts deeply nested and/or queries (gh-676)', function (done) {
+  it('properly casts deeply nested and/or queries (gh-676)', function(done) {
     var sch = new Schema({
       num: Number,
       subdoc: {title: String, num: Number}
@@ -2686,16 +2686,16 @@ describe('lean option:', function () {
     done();
   });
 
-  it('casts $elemMatch (gh-2199)', function (done) {
+  it('casts $elemMatch (gh-2199)', function(done) {
     var db = start();
     var schema = new Schema({dates: [Date]});
     var Dates = db.model('Date', schema, 'dates');
 
     var array = ['2014-07-01T02:00:00.000Z', '2014-07-01T04:00:00.000Z'];
-    Dates.create({dates: array}, function (err) {
+    Dates.create({dates: array}, function(err) {
       assert.ifError(err);
       var elemMatch = {$gte: '2014-07-01T03:00:00.000Z'};
-      Dates.findOne({}, {dates: {$elemMatch: elemMatch}}, function (err, doc) {
+      Dates.findOne({}, {dates: {$elemMatch: elemMatch}}, function(err, doc) {
         assert.ifError(err);
         assert.equal(doc.dates.length, 1);
         assert.equal(doc.dates[0].getTime(),
@@ -2705,11 +2705,11 @@ describe('lean option:', function () {
     });
   });
 
-  describe('$eq', function () {
+  describe('$eq', function() {
     var mongo26 = false;
 
-    before(function (done) {
-      start.mongodVersion(function (err, version) {
+    before(function(done) {
+      start.mongodVersion(function(err, version) {
         if (err) {
           return done(err);
         }
@@ -2718,13 +2718,13 @@ describe('lean option:', function () {
       });
     });
 
-    it('casts $eq (gh-2752)', function (done) {
+    it('casts $eq (gh-2752)', function(done) {
       var db = start();
       var BlogPostB = db.model('BlogPostB', collection);
 
       BlogPostB.findOne(
           {_id: {$eq: '000000000000000000000001'}, numbers: {$eq: [1, 2]}},
-          function (err, doc) {
+          function(err, doc) {
             if (mongo26) {
               assert.ifError(err);
             } else {
diff --git a/test/model.stream.test.js b/test/model.stream.test.js
index 6990fe103cc..901fb3f48f7 100644
--- a/test/model.stream.test.js
+++ b/test/model.stream.test.js
@@ -24,23 +24,23 @@ var Person = new Schema({
 mongoose.model('PersonForStream', Person);
 var collection = 'personforstream_' + random();
 
-describe('query stream:', function () {
-  before(function (done) {
+describe('query stream:', function() {
+  before(function(done) {
     var db = start(),
         P = db.model('PersonForStream', collection);
 
-    var people = names.map(function (name) {
+    var people = names.map(function(name) {
       return {name: name};
     });
 
-    P.create(people, function (err) {
+    P.create(people, function(err) {
       assert.ifError(err);
       db.close();
       done();
     });
   });
 
-  it('works', function (done) {
+  it('works', function(done) {
     var db = start(),
         P = db.model('PersonForStream', collection),
         i = 0,
@@ -63,7 +63,7 @@ describe('query stream:', function () {
       done();
     }
 
-    stream.on('data', function (doc) {
+    stream.on('data', function(doc) {
       assert.strictEqual(true, !!doc.name);
       assert.strictEqual(true, !!doc._id);
 
@@ -84,7 +84,7 @@ describe('query stream:', function () {
         assert.equal(true, stream.paused);
         paused++;
 
-        setTimeout(function () {
+        setTimeout(function() {
           assert.equal(true, stream.paused);
           resumed++;
           stream.resume();
@@ -98,18 +98,18 @@ describe('query stream:', function () {
       }
     });
 
-    stream.on('error', function (er) {
+    stream.on('error', function(er) {
       err = er;
       cb();
     });
 
-    stream.on('close', function () {
+    stream.on('close', function() {
       closed++;
       cb();
     });
   });
 
-  it('immediately destroying a stream prevents the query from executing', function (done) {
+  it('immediately destroying a stream prevents the query from executing', function(done) {
     var db = start(),
         P = db.model('PersonForStream', collection),
         i = 0;
@@ -119,14 +119,14 @@ describe('query stream:', function () {
     function cb(err) {
       assert.ifError(err);
       assert.equal(0, i);
-      process.nextTick(function () {
+      process.nextTick(function() {
         db.close();
         assert.strictEqual(null, stream._fields);
         done();
       });
     }
 
-    stream.on('data', function () {
+    stream.on('data', function() {
       i++;
     });
     stream.on('close', cb);
@@ -135,7 +135,7 @@ describe('query stream:', function () {
     stream.destroy();
   });
 
-  it('destroying a stream stops it', function (done) {
+  it('destroying a stream stops it', function(done) {
     this.slow(300);
 
     var db = start(),
@@ -150,7 +150,7 @@ describe('query stream:', function () {
 
     function cb(err) {
       ++finished;
-      setTimeout(function () {
+      setTimeout(function() {
         db.close();
         assert.strictEqual(undefined, err);
         assert.equal(5, i);
@@ -162,7 +162,7 @@ describe('query stream:', function () {
       }, 100);
     }
 
-    stream.on('data', function (doc) {
+    stream.on('data', function(doc) {
       assert.strictEqual(undefined, doc.name);
       if (++i === 5) {
         stream.destroy();
@@ -174,7 +174,7 @@ describe('query stream:', function () {
     stream.on('error', cb);
   });
 
-  it('errors', function (done) {
+  it('errors', function(done) {
     this.slow(300);
 
     var db = start({server: {auto_reconnect: false}}),
@@ -187,7 +187,7 @@ describe('query stream:', function () {
 
     function cb(err) {
       ++finished;
-      setTimeout(function () {
+      setTimeout(function() {
         assert.ok(/destroyed/.test(err.message), err.message);
         assert.equal(i, 5);
         assert.equal(1, closed);
@@ -199,20 +199,20 @@ describe('query stream:', function () {
       }, 100);
     }
 
-    stream.on('data', function () {
+    stream.on('data', function() {
       if (++i === 5) {
         db.close();
       }
     });
 
-    stream.on('close', function () {
+    stream.on('close', function() {
       closed++;
     });
 
     stream.on('error', cb);
   });
 
-  it('pipe', function (done) {
+  it('pipe', function(done) {
     var db = start(),
         P = db.model('PersonForStream', collection),
         filename = '/tmp/_mongoose_stream_out.txt',
@@ -239,7 +239,7 @@ describe('query stream:', function () {
     out.on('close', cb);
   });
 
-  it('lean', function (done) {
+  it('lean', function(done) {
     var db = start(),
         P = db.model('PersonForStream', collection),
         i = 0,
@@ -257,7 +257,7 @@ describe('query stream:', function () {
       done();
     }
 
-    stream.on('data', function (doc) {
+    stream.on('data', function(doc) {
       assert.strictEqual(false, doc instanceof mongoose.Document);
       i++;
 
@@ -269,7 +269,7 @@ describe('query stream:', function () {
       } else if (i === 2) {
         stream.pause();
         assert.equal(true, stream.paused);
-        process.nextTick(function () {
+        process.nextTick(function() {
           assert.equal(true, stream.paused);
           stream.resume();
           assert.equal(false, stream.paused);
@@ -277,18 +277,18 @@ describe('query stream:', function () {
       }
     });
 
-    stream.on('error', function (er) {
+    stream.on('error', function(er) {
       err = er;
       cb();
     });
 
-    stream.on('close', function () {
+    stream.on('close', function() {
       closed++;
       cb();
     });
   });
 
-  it('supports $elemMatch with $in (gh-1091)', function (done) {
+  it('supports $elemMatch with $in (gh-1091)', function(done) {
     this.timeout(3000);
 
     var db = start();
@@ -302,7 +302,7 @@ describe('query stream:', function () {
     var _id1 = new mongoose.Types.ObjectId;
     var _id2 = new mongoose.Types.ObjectId;
 
-    B.create({ids: [_id1, _id2]}, function (err, doc) {
+    B.create({ids: [_id1, _id2]}, function(err, doc) {
       assert.ifError(err);
 
       var error;
@@ -312,22 +312,22 @@ describe('query stream:', function () {
         .stream();
 
       stream.
-        on('data', function (found) {
+        on('data', function(found) {
           assert.equal(found.id, doc.id);
           assert.equal(1, found.ids.length);
           assert.equal(_id2.toString(), found.ids[0].toString());
         }).
-        on('error', function (err) {
+        on('error', function(err) {
           error = err;
         }).
-        on('close', function () {
+        on('close', function() {
           db.close();
           done(error);
         });
     });
   });
 
-  it('supports population (gh-1411)', function (done) {
+  it('supports population (gh-1411)', function(done) {
     var db = start();
 
     var barSchema = new Schema({
@@ -350,17 +350,17 @@ describe('query stream:', function () {
       db.close(done);
     }
 
-    Bar.create({value: 2}, {value: 3}, function (err, bar1, bar2) {
+    Bar.create({value: 2}, {value: 3}, function(err, bar1, bar2) {
       if (err) return complete(err);
 
-      Foo.create({bar: bar1}, {bar: bar2}, function (err) {
+      Foo.create({bar: bar1}, {bar: bar2}, function(err) {
         if (err) return complete(err);
 
         Foo.
           find().
           populate('bar').
           stream().
-          on('data', function (foo) {
+          on('data', function(foo) {
             found.push(foo.bar.value);
           }).
           on('end', complete).
@@ -369,7 +369,7 @@ describe('query stream:', function () {
     });
   });
 
-  it('respects schema options (gh-1862)', function (done) {
+  it('respects schema options (gh-1862)', function(done) {
     var db = start();
 
     var schema = new Schema({
@@ -378,16 +378,16 @@ describe('query stream:', function () {
     });
 
     var User = db.model('gh-1862', schema, 'gh-1862');
-    User.create({fullname: 'val', password: 'taco'}, function (error) {
+    User.create({fullname: 'val', password: 'taco'}, function(error) {
       assert.ifError(error);
-      User.find().stream().on('data', function (doc) {
+      User.find().stream().on('data', function(doc) {
         assert.equal(undefined, doc.password);
         db.close(done);
       });
     });
   });
 
-  it('works with populate + lean (gh-2841)', function (done) {
+  it('works with populate + lean (gh-2841)', function(done) {
     var db = start();
 
     var Sku = db.model('Sku', {}, 'gh2841_0');
@@ -395,19 +395,19 @@ describe('query stream:', function () {
       sku: {ref: 'Sku', type: Schema.Types.ObjectId}
     }, 'gh2841_1');
 
-    Sku.create({}, function (error, sku) {
+    Sku.create({}, function(error, sku) {
       assert.ifError(error);
-      Item.create({sku: sku._id}, function (error) {
+      Item.create({sku: sku._id}, function(error) {
         assert.ifError(error);
 
         var found = 0;
         var popOpts = {path: 'sku', options: {lean: true}};
         var stream = Item.find().populate(popOpts).stream();
-        stream.on('data', function (doc) {
+        stream.on('data', function(doc) {
           ++found;
           assert.equal(doc.sku._id.toString(), sku._id.toString());
         });
-        stream.on('end', function () {
+        stream.on('end', function() {
           assert.equal(found, 1);
           db.close(done);
         });
@@ -415,7 +415,7 @@ describe('query stream:', function () {
     });
   });
 
-  it('works with populate + dynref (gh-3108)', function (done) {
+  it('works with populate + dynref (gh-3108)', function(done) {
     var db = start();
 
     var reviewSchema = new Schema({
@@ -459,10 +459,10 @@ describe('query stream:', function () {
 
     var c = 0;
 
-    var create = function (cb) {
-      Item1.create({_id: ++c, name: 'Val'}, function (error) {
+    var create = function(cb) {
+      Item1.create({_id: ++c, name: 'Val'}, function(error) {
         assert.ifError(error);
-        Item2.create({_id: ++c, otherName: 'Val'}, function (error) {
+        Item2.create({_id: ++c, otherName: 'Val'}, function(error) {
           assert.ifError(error);
           var review = {
             _id: c,
@@ -473,7 +473,7 @@ describe('query stream:', function () {
               {id: c, type: 'dynrefItem2'}
             ]
           };
-          Review.create(review, function (error) {
+          Review.create(review, function(error) {
             assert.ifError(error);
             cb();
           });
@@ -481,24 +481,24 @@ describe('query stream:', function () {
       });
     };
 
-    var test = function () {
+    var test = function() {
       var stream = Review.find({}).populate('items.id').stream();
       var count = 0;
 
-      stream.on('data', function (doc) {
+      stream.on('data', function(doc) {
         ++count;
         assert.equal('Val', doc.items[0].id.name);
         assert.equal('Val', doc.items[1].id.otherName);
       });
 
-      stream.on('close', function () {
+      stream.on('close', function() {
         assert.equal(count, 2);
         db.close(done);
       });
     };
 
-    create(function () {
-      create(function () {
+    create(function() {
+      create(function() {
         test();
       });
     });
diff --git a/test/model.test.js b/test/model.test.js
index 7d6069ec28e..501f152833c 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -47,20 +47,20 @@ var BlogPost = new Schema({
 
 BlogPost
 .virtual('titleWithAuthor')
-.get(function () {
+.get(function() {
   return this.get('title') + ' by ' + this.get('author');
 })
-.set(function (val) {
+.set(function(val) {
   var split = val.split(' by ');
   this.set('title', split[0]);
   this.set('author', split[1]);
 });
 
-BlogPost.method('cool', function () {
+BlogPost.method('cool', function() {
   return this;
 });
 
-BlogPost.static('woot', function () {
+BlogPost.static('woot', function() {
   return this;
 });
 
@@ -69,10 +69,10 @@ var bpSchema = BlogPost;
 
 var collection = 'blogposts_' + random();
 
-describe('Model', function () {
+describe('Model', function() {
   var db, Test;
 
-  before(function () {
+  before(function() {
     db = start();
     var testSchema = new Schema({
       _id: {
@@ -88,11 +88,11 @@ describe('Model', function () {
     Test = db.model('test-schema', testSchema);
   });
 
-  after(function () {
+  after(function() {
     db.close();
   });
 
-  it('can be created using _id as embedded document', function (done) {
+  it('can be created using _id as embedded document', function(done) {
     var t = new Test({
       _id: {
         first_name: 'Daniel',
@@ -104,9 +104,9 @@ describe('Model', function () {
       }
     });
 
-    t.save(function (err) {
+    t.save(function(err) {
       assert.ifError(err);
-      Test.findOne({}, function (err, doc) {
+      Test.findOne({}, function(err, doc) {
         assert.ifError(err);
 
         assert.ok('last_name' in doc);
@@ -125,9 +125,9 @@ describe('Model', function () {
   });
 });
 
-describe('Model', function () {
-  describe('constructor', function () {
-    it('works without "new" keyword', function (done) {
+describe('Model', function() {
+  describe('constructor', function() {
+    it('works without "new" keyword', function(done) {
       var B = mongoose.model('BlogPost');
       var b = B();
       assert.ok(b instanceof B);
@@ -138,7 +138,7 @@ describe('Model', function () {
       assert.ok(b instanceof B);
       done();
     });
-    it('works "new" keyword', function (done) {
+    it('works "new" keyword', function(done) {
       var B = mongoose.model('BlogPost');
       var b = new B();
       assert.ok(b instanceof B);
@@ -150,8 +150,8 @@ describe('Model', function () {
       done();
     });
   });
-  describe('isNew', function () {
-    it('is true on instantiation', function (done) {
+  describe('isNew', function() {
+    it('is true on instantiation', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -161,7 +161,7 @@ describe('Model', function () {
       done();
     });
 
-    it('on parent and subdocs on failed inserts', function (done) {
+    it('on parent and subdocs on failed inserts', function(done) {
       var db = start();
 
       var schema = new Schema({
@@ -171,14 +171,14 @@ describe('Model', function () {
 
       var A = db.model('isNewOnFail', schema);
 
-      A.on('index', function () {
+      A.on('index', function() {
         var a = new A({name: 'i am new', em: [{x: 1}]});
-        a.save(function (err) {
+        a.save(function(err) {
           assert.ifError(err);
           assert.equal(a.isNew, false);
           assert.equal(a.em[0].isNew, false);
           var b = new A({name: 'i am new', em: [{x: 2}]});
-          b.save(function (err) {
+          b.save(function(err) {
             db.close();
             assert.ok(err);
             assert.equal(b.isNew, true);
@@ -190,7 +190,7 @@ describe('Model', function () {
     });
   });
 
-  it('gh-2140', function (done) {
+  it('gh-2140', function(done) {
     var db = start();
     var S = new Schema({
       field: [{text: String}]
@@ -205,8 +205,8 @@ describe('Model', function () {
     db.close(done);
   });
 
-  describe('schema', function () {
-    it('should exist', function (done) {
+  describe('schema', function() {
+    it('should exist', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -215,12 +215,12 @@ describe('Model', function () {
       assert.ok(BlogPost.prototype.schema instanceof Schema);
       done();
     });
-    it('emits init event', function (done) {
+    it('emits init event', function(done) {
       var db = start(),
           schema = new Schema({name: String}),
           model;
 
-      schema.on('init', function (model_) {
+      schema.on('init', function(model_) {
         model = model_;
       });
 
@@ -231,8 +231,8 @@ describe('Model', function () {
     });
   });
 
-  describe('structure', function () {
-    it('default when instantiated', function (done) {
+  describe('structure', function() {
+    it('default when instantiated', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -262,9 +262,9 @@ describe('Model', function () {
       done();
     });
 
-    describe('array', function () {
-      describe('defaults', function () {
-        it('to a non-empty array', function (done) {
+    describe('array', function() {
+      describe('defaults', function() {
+        it('to a non-empty array', function(done) {
           var db = start(),
               DefaultArraySchema = new Schema({
                 arr: {type: Array, cast: String, default: ['a', 'b', 'c']},
@@ -283,7 +283,7 @@ describe('Model', function () {
           done();
         });
 
-        it('empty', function (done) {
+        it('empty', function(done) {
           var db = start(),
               DefaultZeroCardArraySchema = new Schema({
                 arr: {type: Array, cast: String, default: []},
@@ -301,7 +301,7 @@ describe('Model', function () {
       });
     });
 
-    it('a hash with one null value', function (done) {
+    it('a hash with one null value', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -313,7 +313,7 @@ describe('Model', function () {
       done();
     });
 
-    it('when saved', function (done) {
+    it('when saved', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           pending = 2;
@@ -327,7 +327,7 @@ describe('Model', function () {
       }
 
       var post = new BlogPost();
-      post.on('save', function (post) {
+      post.on('save', function(post) {
         assert.ok(post.get('_id') instanceof DocumentObjectId);
 
         assert.equal(undefined, post.get('title'));
@@ -345,7 +345,7 @@ describe('Model', function () {
         cb();
       });
 
-      post.save(function (err, post) {
+      post.save(function(err, post) {
         assert.ifError(err);
         assert.ok(post.get('_id') instanceof DocumentObjectId);
 
@@ -366,13 +366,13 @@ describe('Model', function () {
     });
 
 
-    it('when saved using the promise not the callback', function (done) {
+    it('when saved using the promise not the callback', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost();
       var p = post.save();
-      p.onResolve(function (err, post) {
+      p.onResolve(function(err, post) {
         assert.ifError(err);
         assert.ok(post.get('_id') instanceof DocumentObjectId);
 
@@ -393,8 +393,8 @@ describe('Model', function () {
     });
 
 
-    describe('init', function () {
-      it('works', function (done) {
+    describe('init', function() {
+      it('works', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -451,7 +451,7 @@ describe('Model', function () {
         done();
       });
 
-      it('partially', function (done) {
+      it('partially', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -478,7 +478,7 @@ describe('Model', function () {
         done();
       });
 
-      it('with partial hash', function (done) {
+      it('with partial hash', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -494,7 +494,7 @@ describe('Model', function () {
         done();
       });
 
-      it('isNew on embedded documents', function (done) {
+      it('isNew on embedded documents', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -510,7 +510,7 @@ describe('Model', function () {
         done();
       });
 
-      it('isNew on embedded documents after saving', function (done) {
+      it('isNew on embedded documents after saving', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -519,11 +519,11 @@ describe('Model', function () {
         assert.equal(true, post.get('comments')[0].isNew);
         assert.equal(true, post.get('comments')[0].comments[0].isNew);
         post.invalidate('title'); // force error
-        post.save(function () {
+        post.save(function() {
           assert.equal(true, post.isNew);
           assert.equal(true, post.get('comments')[0].isNew);
           assert.equal(true, post.get('comments')[0].comments[0].isNew);
-          post.save(function (err) {
+          post.save(function(err) {
             db.close();
             assert.strictEqual(null, err);
             assert.equal(false, post.isNew);
@@ -536,7 +536,7 @@ describe('Model', function () {
     });
   });
 
-  it('collection name can be specified through schema', function (done) {
+  it('collection name can be specified through schema', function(done) {
     var schema = new Schema({name: String}, {collection: 'users1'});
     var Named = mongoose.model('CollectionNamedInSchema1', schema);
     assert.equal(Named.prototype.collection.name, 'users1');
@@ -549,7 +549,7 @@ describe('Model', function () {
     done();
   });
 
-  it('saving a model with a null value should perpetuate that null value to the db', function (done) {
+  it('saving a model with a null value should perpetuate that null value to the db', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -557,9 +557,9 @@ describe('Model', function () {
       title: null
     });
     assert.strictEqual(null, post.title);
-    post.save(function (err) {
+    post.save(function(err) {
       assert.strictEqual(err, null);
-      BlogPost.findById(post.id, function (err, found) {
+      BlogPost.findById(post.id, function(err, found) {
         db.close();
         assert.strictEqual(err, null);
         assert.strictEqual(found.title, null);
@@ -568,7 +568,7 @@ describe('Model', function () {
     });
   });
 
-  it('saves subdocuments middleware correctly', function (done) {
+  it('saves subdocuments middleware correctly', function(done) {
     var db = start();
 
     var child_hook;
@@ -577,7 +577,7 @@ describe('Model', function () {
       name: String
     });
 
-    childSchema.pre('save', function (next) {
+    childSchema.pre('save', function(next) {
       child_hook = this.name;
       next();
     });
@@ -587,7 +587,7 @@ describe('Model', function () {
       children: [childSchema]
     });
 
-    parentSchema.pre('save', function (next) {
+    parentSchema.pre('save', function(next) {
       parent_hook = this.name;
       next();
     });
@@ -601,12 +601,12 @@ describe('Model', function () {
       }]
     });
 
-    parent.save(function (err, parent) {
+    parent.save(function(err, parent) {
       assert.equal(parent_hook, 'Bob');
       assert.equal(child_hook, 'Mary');
       assert.ifError(err);
       parent.children[0].name = 'Jane';
-      parent.save(function (err) {
+      parent.save(function(err) {
         assert.equal(child_hook, 'Jane');
         assert.ifError(err);
         done();
@@ -614,7 +614,7 @@ describe('Model', function () {
     });
   });
 
-  it('instantiating a model with a hash that maps to at least 1 undefined value', function (done) {
+  it('instantiating a model with a hash that maps to at least 1 undefined value', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -622,9 +622,9 @@ describe('Model', function () {
       title: undefined
     });
     assert.strictEqual(undefined, post.title);
-    post.save(function (err) {
+    post.save(function(err) {
       assert.strictEqual(null, err);
-      BlogPost.findById(post.id, function (err, found) {
+      BlogPost.findById(post.id, function(err, found) {
         db.close();
         assert.strictEqual(err, null);
         assert.strictEqual(found.title, undefined);
@@ -633,7 +633,7 @@ describe('Model', function () {
     });
   });
 
-  it('modified nested objects which contain MongoseNumbers should not cause a RangeError on save (gh-714)', function (done) {
+  it('modified nested objects which contain MongoseNumbers should not cause a RangeError on save (gh-714)', function(done) {
     var db = start();
 
     var schema = new Schema({
@@ -645,13 +645,13 @@ describe('Model', function () {
     var M = db.model('NestedObjectWithMongooseNumber', schema);
     var m = new M;
     m.nested = null;
-    m.save(function (err) {
+    m.save(function(err) {
       assert.ifError(err);
 
-      M.findById(m, function (err, m) {
+      M.findById(m, function(err, m) {
         assert.ifError(err);
         m.nested.num = 5;
-        m.save(function (err) {
+        m.save(function(err) {
           db.close();
           assert.ifError(err);
           done();
@@ -660,7 +660,7 @@ describe('Model', function () {
     });
   });
 
-  it('no RangeError on remove() of a doc with Number _id (gh-714)', function (done) {
+  it('no RangeError on remove() of a doc with Number _id (gh-714)', function(done) {
     var db = start();
 
     var MySchema = new Schema({
@@ -674,13 +674,13 @@ describe('Model', function () {
       name: 'test',
       _id: 35
     });
-    instance.save(function (err) {
+    instance.save(function(err) {
       assert.ifError(err);
 
-      MyModel.findById(35, function (err, doc) {
+      MyModel.findById(35, function(err, doc) {
         assert.ifError(err);
 
-        doc.remove(function (err) {
+        doc.remove(function(err) {
           db.close();
           assert.ifError(err);
           done();
@@ -689,7 +689,7 @@ describe('Model', function () {
     });
   });
 
-  it('over-writing a number should persist to the db (gh-342)', function (done) {
+  it('over-writing a number should persist to the db (gh-342)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -700,12 +700,12 @@ describe('Model', function () {
       }
     });
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
       post.set('meta.visitors', 20);
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
-        BlogPost.findById(post.id, function (err, found) {
+        BlogPost.findById(post.id, function(err, found) {
           assert.ifError(err);
           assert.equal(20, found.get('meta.visitors').valueOf());
           db.close();
@@ -715,8 +715,8 @@ describe('Model', function () {
     });
   });
 
-  describe('methods', function () {
-    it('can be defined', function (done) {
+  describe('methods', function() {
+    it('can be defined', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -726,10 +726,10 @@ describe('Model', function () {
       done();
     });
 
-    it('can be defined on embedded documents', function (done) {
+    it('can be defined on embedded documents', function(done) {
       var db = start();
       var ChildSchema = new Schema({name: String});
-      ChildSchema.method('talk', function () {
+      ChildSchema.method('talk', function() {
         return 'gaga';
       });
 
@@ -750,11 +750,11 @@ describe('Model', function () {
       done();
     });
 
-    it('can be defined with nested key', function (done) {
+    it('can be defined with nested key', function(done) {
       var db = start();
       var NestedKeySchema = new Schema({});
       NestedKeySchema.method('foo', {
-        bar: function () {
+        bar: function() {
           return this;
         }
       });
@@ -765,8 +765,8 @@ describe('Model', function () {
     });
   });
 
-  describe('statics', function () {
-    it('can be defined', function (done) {
+  describe('statics', function() {
+    it('can be defined', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -776,8 +776,8 @@ describe('Model', function () {
     });
   });
 
-  describe('casting as validation errors', function () {
-    it('error', function (done) {
+  describe('casting as validation errors', function() {
+    it('error', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           threw = false;
@@ -799,20 +799,20 @@ describe('Model', function () {
 
       assert.equal(false, threw);
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         assert.equal(2, Object.keys(err.errors).length);
         post.date = new Date;
         post.meta.date = new Date;
-        post.save(function (err) {
+        post.save(function(err) {
           db.close();
           assert.ifError(err);
           done();
         });
       });
     });
-    it('nested error', function (done) {
+    it('nested error', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           threw = false;
@@ -839,7 +839,7 @@ describe('Model', function () {
 
       assert.equal(false, threw);
 
-      post.save(function (err) {
+      post.save(function(err) {
         db.close();
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
@@ -848,7 +848,7 @@ describe('Model', function () {
     });
 
 
-    it('subdocument cast error', function (done) {
+    it('subdocument cast error', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -860,7 +860,7 @@ describe('Model', function () {
 
       post.get('comments')[0].set('date', 'invalid');
 
-      post.save(function (err) {
+      post.save(function(err) {
         db.close();
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
@@ -869,7 +869,7 @@ describe('Model', function () {
     });
 
 
-    it('subdocument validation error', function (done) {
+    it('subdocument validation error', function(done) {
       function failingvalidator() {
         return false;
       }
@@ -887,7 +887,7 @@ describe('Model', function () {
         subs: [{str: 'gaga'}]
       });
 
-      post.save(function (err) {
+      post.save(function(err) {
         db.close();
         assert.ok(err instanceof ValidationError);
         done();
@@ -895,7 +895,7 @@ describe('Model', function () {
     });
 
 
-    it('subdocument error when adding a subdoc', function (done) {
+    it('subdocument error when adding a subdoc', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           threw = false;
@@ -912,7 +912,7 @@ describe('Model', function () {
 
       assert.equal(false, threw);
 
-      post.save(function (err) {
+      post.save(function(err) {
         db.close();
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
@@ -921,7 +921,7 @@ describe('Model', function () {
     });
 
 
-    it('updates', function (done) {
+    it('updates', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -930,13 +930,13 @@ describe('Model', function () {
 
       var id = post.get('_id');
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPost.update({title: 1, _id: id}, {title: 2}, function (err) {
+        BlogPost.update({title: 1, _id: id}, {title: 2}, function(err) {
           assert.ifError(err);
 
-          BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+          BlogPost.findOne({_id: post.get('_id')}, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(doc.get('title'), '2');
@@ -946,7 +946,7 @@ describe('Model', function () {
       });
     });
 
-    it('$pull', function (done) {
+    it('$pull', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost();
@@ -957,18 +957,18 @@ describe('Model', function () {
       done();
     });
 
-    it('$push', function (done) {
+    it('$push', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost();
 
       post.get('numbers').push(1, 2, 3, 4);
-      post.save(function () {
-        BlogPost.findById(post.get('_id'), function (err, found) {
+      post.save(function() {
+        BlogPost.findById(post.get('_id'), function(err, found) {
           assert.equal(found.get('numbers').length, 4);
           found.get('numbers').pull('3');
-          found.save(function () {
-            BlogPost.findById(found.get('_id'), function (err, found2) {
+          found.save(function() {
+            BlogPost.findById(found.get('_id'), function(err, found2) {
               db.close();
               assert.ifError(err);
               assert.equal(found2.get('numbers').length, 3);
@@ -979,17 +979,17 @@ describe('Model', function () {
       });
     });
 
-    it('Number arrays', function (done) {
+    it('Number arrays', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost();
       post.numbers.push(1, '2', 3);
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.strictEqual(err, null);
 
-        BlogPost.findById(post._id, function (err, doc) {
+        BlogPost.findById(post._id, function(err, doc) {
           assert.ifError(err);
 
           assert.ok(~doc.numbers.indexOf(1));
@@ -1002,10 +1002,10 @@ describe('Model', function () {
       });
     });
 
-    it('date casting compat with datejs (gh-502)', function (done) {
+    it('date casting compat with datejs (gh-502)', function(done) {
       var db = start();
 
-      Date.prototype.toObject = function () {
+      Date.prototype.toObject = function() {
         return {
           millisecond: 86,
           second: 42,
@@ -1035,13 +1035,13 @@ describe('Model', function () {
       var M = db.model('gh502', S);
 
       var m = new M;
-      m.save(function (err) {
+      m.save(function(err) {
         assert.ifError(err);
-        M.findById(m._id, function (err, m) {
+        M.findById(m._id, function(err, m) {
           assert.ifError(err);
-          m.save(function (err) {
+          m.save(function(err) {
             assert.ifError(err);
-            M.remove(function (err) {
+            M.remove(function(err) {
               db.close();
               delete Date.prototype.toObject;
               assert.ifError(err);
@@ -1053,8 +1053,8 @@ describe('Model', function () {
     });
   });
 
-  describe('validation', function () {
-    it('works', function (done) {
+  describe('validation', function() {
+    it('works', function(done) {
       function dovalidate() {
         assert.equal('correct', this.asyncScope);
         return true;
@@ -1062,7 +1062,7 @@ describe('Model', function () {
 
       function dovalidateAsync(val, callback) {
         assert.equal('correct', this.scope);
-        process.nextTick(function () {
+        process.nextTick(function() {
           callback(true);
         });
       }
@@ -1081,12 +1081,12 @@ describe('Model', function () {
       post.set('scope', 'correct');
       post.set('asyncScope', 'correct');
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
 
         post.set('simple', 'here');
-        post.save(function (err) {
+        post.save(function(err) {
           db.close();
           assert.ifError(err);
           done();
@@ -1094,7 +1094,7 @@ describe('Model', function () {
       });
     });
 
-    it('custom messaging', function (done) {
+    it('custom messaging', function(done) {
       function validate(val) {
         return val === 'abc';
       }
@@ -1109,7 +1109,7 @@ describe('Model', function () {
       var post = new TestValidationMessage();
       post.set('simple', '');
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         assert.ok(err.errors.simple instanceof ValidatorError);
@@ -1117,7 +1117,7 @@ describe('Model', function () {
         assert.equal(post.errors.simple.message, 'must be abc');
 
         post.set('simple', 'abc');
-        post.save(function (err) {
+        post.save(function(err) {
           db.close();
           assert.ifError(err);
           done();
@@ -1125,17 +1125,17 @@ describe('Model', function () {
       });
     });
 
-    it('with Model.schema.path introspection (gh-272)', function (done) {
+    it('with Model.schema.path introspection (gh-272)', function(done) {
       var db = start();
       var IntrospectionValidationSchema = new Schema({
         name: String
       });
       var IntrospectionValidation = db.model('IntrospectionValidation', IntrospectionValidationSchema, 'introspections_' + random());
-      IntrospectionValidation.schema.path('name').validate(function (value) {
+      IntrospectionValidation.schema.path('name').validate(function(value) {
         return value.length < 2;
       }, 'Name cannot be greater than 1 character for path "{PATH}" with value `{VALUE}`');
       var doc = new IntrospectionValidation({name: 'hi'});
-      doc.save(function (err) {
+      doc.save(function(err) {
         db.close();
         assert.equal(err.errors.name.message, 'Name cannot be greater than 1 character for path "name" with value `hi`');
         assert.equal(err.name, 'ValidationError');
@@ -1144,7 +1144,7 @@ describe('Model', function () {
       });
     });
 
-    it('of required undefined values', function (done) {
+    it('of required undefined values', function(done) {
       mongoose.model('TestUndefinedValidation', new Schema({
         simple: {type: String, required: true}
       }));
@@ -1154,12 +1154,12 @@ describe('Model', function () {
 
       var post = new TestUndefinedValidation;
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
 
         post.set('simple', 'here');
-        post.save(function (err) {
+        post.save(function(err) {
           db.close();
           assert.ifError(err);
           done();
@@ -1167,7 +1167,7 @@ describe('Model', function () {
       });
     });
 
-    it('save callback should only execute once (gh-319)', function (done) {
+    it('save callback should only execute once (gh-319)', function(done) {
       var db = start();
 
       var D = db.model('CallbackFiresOnceValidation', new Schema({
@@ -1184,7 +1184,7 @@ describe('Model', function () {
 
       var timesCalled = 0;
 
-      post.save(function (err) {
+      post.save(function(err) {
         db.close();
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
@@ -1210,7 +1210,7 @@ describe('Model', function () {
       });
     });
 
-    it('query result', function (done) {
+    it('query result', function(done) {
       mongoose.model('TestValidationOnResult', new Schema({
         resultv: {type: String, required: true}
       }));
@@ -1220,17 +1220,17 @@ describe('Model', function () {
 
       var post = new TestV;
 
-      post.validate(function (err) {
+      post.validate(function(err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
 
         post.resultv = 'yeah';
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
-          TestV.findOne({_id: post.id}, function (err, found) {
+          TestV.findOne({_id: post.id}, function(err, found) {
             assert.ifError(err);
             assert.equal(found.resultv, 'yeah');
-            found.save(function (err) {
+            found.save(function(err) {
               db.close();
               assert.ifError(err);
               done();
@@ -1240,7 +1240,7 @@ describe('Model', function () {
       });
     });
 
-    it('of required previously existing null values', function (done) {
+    it('of required previously existing null values', function(done) {
       mongoose.model('TestPreviousNullValidation', new Schema({
         previous: {type: String, required: true},
         a: String
@@ -1249,19 +1249,19 @@ describe('Model', function () {
       var db = start(),
           TestP = db.model('TestPreviousNullValidation');
 
-      TestP.collection.insert({a: null, previous: null}, {}, function (err, f) {
+      TestP.collection.insert({a: null, previous: null}, {}, function(err, f) {
         assert.ifError(err);
-        TestP.findOne({_id: f.ops[0]._id}, function (err, found) {
+        TestP.findOne({_id: f.ops[0]._id}, function(err, found) {
           assert.ifError(err);
           assert.equal(false, found.isNew);
           assert.strictEqual(found.get('previous'), null);
 
-          found.validate(function (err) {
+          found.validate(function(err) {
             assert.ok(err instanceof MongooseError);
             assert.ok(err instanceof ValidationError);
 
             found.set('previous', 'yoyo');
-            found.save(function (err) {
+            found.save(function(err) {
               assert.strictEqual(err, null);
               db.close();
               done();
@@ -1271,7 +1271,7 @@ describe('Model', function () {
       });
     });
 
-    it('nested', function (done) {
+    it('nested', function(done) {
       mongoose.model('TestNestedValidation', new Schema({
         nested: {
           required: {type: String, required: true}
@@ -1284,12 +1284,12 @@ describe('Model', function () {
       var post = new TestNestedValidation();
       post.set('nested.required', null);
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
 
         post.set('nested.required', 'here');
-        post.save(function (err) {
+        post.save(function(err) {
           db.close();
           assert.ifError(err);
           done();
@@ -1297,7 +1297,7 @@ describe('Model', function () {
       });
     });
 
-    it('of nested subdocuments', function (done) {
+    it('of nested subdocuments', function(done) {
       var Subsubdocs = new Schema({required: {type: String, required: true}});
 
       var Subdocs = new Schema({
@@ -1316,7 +1316,7 @@ describe('Model', function () {
 
       post.get('items').push({required: '', subs: [{required: ''}]});
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         assert.ok(err.errors['items.0.subs.0.required'] instanceof ValidatorError);
@@ -1330,7 +1330,7 @@ describe('Model', function () {
         post.items[0].subs[0].set('required', true);
         assert.equal(undefined, post.$__.validationError);
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ok(err);
           assert.ok(err.errors);
           assert.ok(err.errors['items.0.required'] instanceof ValidatorError);
@@ -1342,7 +1342,7 @@ describe('Model', function () {
           assert.ok(!post.errors['items.0.subs.0.required']);
 
           post.get('items')[0].set('required', true);
-          post.save(function (err) {
+          post.save(function(err) {
             db.close();
             assert.ok(!post.errors);
             assert.ifError(err);
@@ -1352,12 +1352,12 @@ describe('Model', function () {
       });
     });
 
-    describe('async', function () {
-      it('works', function (done) {
+    describe('async', function() {
+      it('works', function(done) {
         var executed = false;
 
         function validator(v, fn) {
-          setTimeout(function () {
+          setTimeout(function() {
             executed = true;
             fn(v !== 'test');
           }, 5);
@@ -1373,7 +1373,7 @@ describe('Model', function () {
         var post = new TestAsyncValidation();
         post.set('async', 'test');
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.ok(err.errors.async instanceof ValidatorError);
@@ -1382,7 +1382,7 @@ describe('Model', function () {
           executed = false;
 
           post.set('async', 'woot');
-          post.save(function (err) {
+          post.save(function(err) {
             db.close();
             assert.equal(true, executed);
             assert.strictEqual(err, null);
@@ -1391,11 +1391,11 @@ describe('Model', function () {
         });
       });
 
-      it('nested', function (done) {
+      it('nested', function(done) {
         var executed = false;
 
         function validator(v, fn) {
-          setTimeout(function () {
+          setTimeout(function() {
             executed = true;
             fn(v !== 'test');
           }, 5);
@@ -1413,25 +1413,25 @@ describe('Model', function () {
         var post = new TestNestedAsyncValidation();
         post.set('nested.async', 'test');
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.ok(executed);
           executed = false;
 
-          post.validate(function (err) {
+          post.validate(function(err) {
             assert.ok(err instanceof MongooseError);
             assert.ok(err instanceof ValidationError);
             assert.ok(executed);
             executed = false;
 
             post.set('nested.async', 'woot');
-            post.validate(function (err) {
+            post.validate(function(err) {
               assert.ok(executed);
               assert.equal(err, null);
               executed = false;
 
-              post.save(function (err) {
+              post.save(function(err) {
                 db.close();
                 assert.ok(executed);
                 assert.strictEqual(err, null);
@@ -1442,11 +1442,11 @@ describe('Model', function () {
         });
       });
 
-      it('subdocuments', function (done) {
+      it('subdocuments', function(done) {
         var executed = false;
 
         function validator(v, fn) {
-          setTimeout(function () {
+          setTimeout(function() {
             executed = true;
             fn(v !== '');
           }, 5);
@@ -1467,14 +1467,14 @@ describe('Model', function () {
 
         post.get('items').push({required: ''});
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.ok(executed);
           executed = false;
 
           post.get('items')[0].set({required: 'here'});
-          post.save(function (err) {
+          post.save(function(err) {
             db.close();
             assert.ok(executed);
             assert.strictEqual(err, null);
@@ -1484,7 +1484,7 @@ describe('Model', function () {
       });
     });
 
-    it('without saving', function (done) {
+    it('without saving', function(done) {
       mongoose.model('TestCallingValidation', new Schema({
         item: {type: String, required: true}
       }));
@@ -1497,13 +1497,13 @@ describe('Model', function () {
       assert.equal(true, post.schema.path('item').isRequired);
       assert.strictEqual(post.isNew, true);
 
-      post.validate(function (err) {
+      post.validate(function(err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         assert.strictEqual(post.isNew, true);
 
         post.item = 'yo';
-        post.validate(function (err) {
+        post.validate(function(err) {
           db.close();
           assert.equal(err, null);
           assert.strictEqual(post.isNew, true);
@@ -1512,7 +1512,7 @@ describe('Model', function () {
       });
     });
 
-    it('when required is set to false', function (done) {
+    it('when required is set to false', function(done) {
       function validator() {
         return true;
       }
@@ -1531,8 +1531,8 @@ describe('Model', function () {
       done();
     });
 
-    describe('middleware', function () {
-      it('works', function (done) {
+    describe('middleware', function() {
+      it('works', function(done) {
         var db = start(),
             ValidationMiddlewareSchema = null,
             Post = null,
@@ -1542,7 +1542,7 @@ describe('Model', function () {
           baz: {type: String}
         });
 
-        ValidationMiddlewareSchema.pre('validate', function (next) {
+        ValidationMiddlewareSchema.pre('validate', function(next) {
           if (this.get('baz') === 'bad') {
             this.invalidate('baz', 'bad');
           }
@@ -1555,14 +1555,14 @@ describe('Model', function () {
         post = new Post();
         post.set({baz: 'bad'});
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.equal(err.errors.baz.kind, 'user defined');
           assert.equal(err.errors.baz.path, 'baz');
 
           post.set('baz', 'good');
-          post.save(function (err) {
+          post.save(function(err) {
             assert.ifError(err);
             db.close();
             done();
@@ -1570,7 +1570,7 @@ describe('Model', function () {
         });
       });
 
-      it('async', function (done) {
+      it('async', function(done) {
         var db = start(),
             AsyncValidationMiddlewareSchema = null,
             Post = null,
@@ -1580,9 +1580,9 @@ describe('Model', function () {
           prop: {type: String}
         });
 
-        AsyncValidationMiddlewareSchema.pre('validate', true, function (next, done) {
+        AsyncValidationMiddlewareSchema.pre('validate', true, function(next, done) {
           var _this = this;
-          setTimeout(function () {
+          setTimeout(function() {
             if (_this.get('prop') === 'bad') {
               _this.invalidate('prop', 'bad');
             }
@@ -1597,14 +1597,14 @@ describe('Model', function () {
         post = new Post();
         post.set({prop: 'bad'});
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.equal(err.errors.prop.kind, 'user defined');
           assert.equal(err.errors.prop.path, 'prop');
 
           post.set('prop', 'good');
-          post.save(function (err) {
+          post.save(function(err) {
             assert.ifError(err);
             db.close();
             done();
@@ -1612,12 +1612,12 @@ describe('Model', function () {
         });
       });
 
-      it('complex', function (done) {
+      it('complex', function(done) {
         var db = start(),
             ComplexValidationMiddlewareSchema = null,
             Post = null,
             post = null,
-            abc = function (v) {
+            abc = function(v) {
               return v === 'abc';
             };
 
@@ -1628,9 +1628,9 @@ describe('Model', function () {
           required: {type: String, required: true}
         });
 
-        ComplexValidationMiddlewareSchema.pre('validate', true, function (next, done) {
+        ComplexValidationMiddlewareSchema.pre('validate', true, function(next, done) {
           var _this = this;
-          setTimeout(function () {
+          setTimeout(function() {
             if (_this.get('baz') === 'bad') {
               _this.invalidate('baz', 'bad');
             }
@@ -1649,7 +1649,7 @@ describe('Model', function () {
           test: 'fail'
         });
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ok(err instanceof MongooseError);
           assert.ok(err instanceof ValidationError);
           assert.equal(4, Object.keys(err.errors).length);
@@ -1675,7 +1675,7 @@ describe('Model', function () {
             required: 'here'
           });
 
-          post.save(function (err) {
+          post.save(function(err) {
             assert.ifError(err);
             db.close();
             done();
@@ -1685,8 +1685,8 @@ describe('Model', function () {
     });
   });
 
-  describe('defaults application', function () {
-    it('works', function (done) {
+  describe('defaults application', function() {
+    it('works', function(done) {
       var now = Date.now();
 
       mongoose.model('TestDefaults', new Schema({
@@ -1703,7 +1703,7 @@ describe('Model', function () {
       done();
     });
 
-    it('nested', function (done) {
+    it('nested', function(done) {
       var now = Date.now();
 
       mongoose.model('TestNestedDefaults', new Schema({
@@ -1722,7 +1722,7 @@ describe('Model', function () {
       done();
     });
 
-    it('subdocument', function (done) {
+    it('subdocument', function(done) {
       var now = Date.now();
 
       var Items = new Schema({
@@ -1744,17 +1744,17 @@ describe('Model', function () {
       done();
     });
 
-    it('allows nulls', function (done) {
+    it('allows nulls', function(done) {
       var db = start();
       var T = db.model('NullDefault', new Schema({name: {type: String, default: null}}), collection);
       var t = new T();
 
       assert.strictEqual(null, t.name);
 
-      t.save(function (err) {
+      t.save(function(err) {
         assert.ifError(err);
 
-        T.findById(t._id, function (err, t) {
+        T.findById(t._id, function(err, t) {
           db.close();
           assert.ifError(err);
           assert.strictEqual(null, t.name);
@@ -1763,16 +1763,16 @@ describe('Model', function () {
       });
     });
 
-    it('do not cause the document to stay dirty after save', function (done) {
+    it('do not cause the document to stay dirty after save', function(done) {
       var db = start(),
           Model = db.model('SavingDefault', new Schema({name: {type: String, default: 'saving'}}), collection),
           doc = new Model();
 
-      doc.save(function (err, doc, numberAffected) {
+      doc.save(function(err, doc, numberAffected) {
         assert.ifError(err);
         assert.strictEqual(1, numberAffected);
 
-        doc.save(function (err, doc, numberAffected) {
+        doc.save(function(err, doc, numberAffected) {
           db.close();
           assert.ifError(err);
           // should not have saved a second time
@@ -1783,8 +1783,8 @@ describe('Model', function () {
     });
   });
 
-  describe('virtuals', function () {
-    it('getters', function (done) {
+  describe('virtuals', function() {
+    it('getters', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost({
@@ -1798,7 +1798,7 @@ describe('Model', function () {
       done();
     });
 
-    it('set()', function (done) {
+    it('set()', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost();
@@ -1810,17 +1810,17 @@ describe('Model', function () {
       done();
     });
 
-    it('should not be saved to the db', function (done) {
+    it('should not be saved to the db', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           post = new BlogPost();
 
       post.set('titleWithAuthor', 'Huckleberry Finn by Mark Twain');
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPost.findById(post.get('_id'), function (err, found) {
+        BlogPost.findById(post.get('_id'), function(err, found) {
           assert.ifError(err);
 
           assert.equal(found.get('title'), 'Huckleberry Finn');
@@ -1832,7 +1832,7 @@ describe('Model', function () {
       });
     });
 
-    it('nested', function (done) {
+    it('nested', function(done) {
       var db = start(),
           PersonSchema = new Schema({
             name: {
@@ -1843,10 +1843,10 @@ describe('Model', function () {
 
       PersonSchema
       .virtual('name.full')
-      .get(function () {
+      .get(function() {
         return this.get('name.first') + ' ' + this.get('name.last');
       })
-      .set(function (fullName) {
+      .set(function(fullName) {
         var split = fullName.split(' ');
         this.set('name.first', split[0]);
         this.set('name.last', split[1]);
@@ -1877,19 +1877,19 @@ describe('Model', function () {
     });
   });
 
-  describe('.remove()', function () {
-    it('works', function (done) {
+  describe('.remove()', function() {
+    it('works', function(done) {
       var db = start(),
           collection = 'blogposts_' + random(),
           BlogPost = db.model('BlogPost', collection);
 
-      BlogPost.create({title: 1}, {title: 2}, function (err) {
+      BlogPost.create({title: 1}, {title: 2}, function(err) {
         assert.ifError(err);
 
-        BlogPost.remove({title: 1}, function (err) {
+        BlogPost.remove({title: 1}, function(err) {
           assert.ifError(err);
 
-          BlogPost.find({}, function (err, found) {
+          BlogPost.find({}, function(err, found) {
             db.close();
             assert.ifError(err);
             assert.equal(1, found.length);
@@ -1900,16 +1900,16 @@ describe('Model', function () {
       });
     });
 
-    it('errors when id deselected (gh-3118)', function (done) {
+    it('errors when id deselected (gh-3118)', function(done) {
       var db = start(),
           collection = 'blogposts_' + random(),
           BlogPost = db.model('BlogPost', collection);
 
-      BlogPost.create({title: 1}, {title: 2}, function (err) {
+      BlogPost.create({title: 1}, {title: 2}, function(err) {
         assert.ifError(err);
-        BlogPost.findOne({title: 1}, {_id: 0}, function (error, doc) {
+        BlogPost.findOne({title: 1}, {_id: 0}, function(error, doc) {
           assert.ifError(error);
-          doc.remove(function (err) {
+          doc.remove(function(err) {
             assert.ok(err);
             assert.equal(err.toString(), 'Error: No _id found on document!');
             db.close(done);
@@ -1918,16 +1918,16 @@ describe('Model', function () {
       });
     });
 
-    it('should not remove any records when deleting by id undefined', function (done) {
+    it('should not remove any records when deleting by id undefined', function(done) {
       var db = start();
       var collection = 'blogposts_' + random();
       var BlogPost = db.model('BlogPost', collection);
-      BlogPost.create({title: 1}, {title: 2}, function (err) {
+      BlogPost.create({title: 1}, {title: 2}, function(err) {
         assert.ifError(err);
 
-        BlogPost.remove({_id: undefined}, function (err) {
+        BlogPost.remove({_id: undefined}, function(err) {
           assert.ifError(err);
-          BlogPost.find({}, function (err, found) {
+          BlogPost.find({}, function(err, found) {
             assert.equal(found.length, 2, 'Should not remove any records');
             done();
           });
@@ -1935,18 +1935,18 @@ describe('Model', function () {
       });
     });
 
-    it('should not remove all documents in the collection (gh-3326)', function (done) {
+    it('should not remove all documents in the collection (gh-3326)', function(done) {
       var db = start(),
           collection = 'blogposts_' + random(),
           BlogPost = db.model('BlogPost', collection);
 
-      BlogPost.create({title: 1}, {title: 2}, function (err) {
+      BlogPost.create({title: 1}, {title: 2}, function(err) {
         assert.ifError(err);
-        BlogPost.findOne({title: 1}, function (error, doc) {
+        BlogPost.findOne({title: 1}, function(error, doc) {
           assert.ifError(error);
-          doc.remove(function (err) {
+          doc.remove(function(err) {
             assert.ifError(err);
-            BlogPost.find(function (err, found) {
+            BlogPost.find(function(err, found) {
               db.close();
               assert.ifError(err);
               assert.equal(1, found.length);
@@ -1959,25 +1959,25 @@ describe('Model', function () {
     });
   });
 
-  describe('#remove()', function () {
+  describe('#remove()', function() {
     var db, B;
 
-    before(function () {
+    before(function() {
       db = start();
       B = db.model('BlogPost', 'blogposts_' + random());
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('passes the removed document (gh-1419)', function (done) {
-      B.create({}, function (err, post) {
+    it('passes the removed document (gh-1419)', function(done) {
+      B.create({}, function(err, post) {
         assert.ifError(err);
-        B.findById(post, function (err, found) {
+        B.findById(post, function(err, found) {
           assert.ifError(err);
 
-          found.remove(function (err, doc) {
+          found.remove(function(err, doc) {
             assert.ifError(err);
             assert.ok(doc);
             assert.ok(doc.equals(found));
@@ -1987,13 +1987,13 @@ describe('Model', function () {
       });
     });
 
-    it('works as a promise', function (done) {
-      B.create({}, function (err, post) {
+    it('works as a promise', function(done) {
+      B.create({}, function(err, post) {
         assert.ifError(err);
-        B.findById(post, function (err, found) {
+        B.findById(post, function(err, found) {
           assert.ifError(err);
 
-          found.remove().onResolve(function (err, doc) {
+          found.remove().onResolve(function(err, doc) {
             assert.ifError(err);
             assert.ok(doc);
             assert.ok(doc.equals(found));
@@ -2003,26 +2003,26 @@ describe('Model', function () {
       });
     });
 
-    it('works as a promise with a hook', function (done) {
+    it('works as a promise with a hook', function(done) {
       var called = 0;
       var RHS = new Schema({
         name: String
       });
-      RHS.pre('remove', function (next) {
+      RHS.pre('remove', function(next) {
         called++;
         return next();
       });
 
       var RH = db.model('RH', RHS, 'RH_' + random());
 
-      RH.create({name: 'to be removed'}, function (err, post) {
+      RH.create({name: 'to be removed'}, function(err, post) {
         assert.ifError(err);
         assert.ok(post);
-        RH.findById(post, function (err, found) {
+        RH.findById(post, function(err, found) {
           assert.ifError(err);
           assert.ok(found);
 
-          found.remove().onResolve(function (err, doc) {
+          found.remove().onResolve(function(err, doc) {
             assert.ifError(err);
             assert.equal(called, 1);
             assert.ok(doc);
@@ -2033,13 +2033,13 @@ describe('Model', function () {
       });
     });
 
-    it('passes the removed document (gh-1419)', function (done) {
-      B.create({}, function (err, post) {
+    it('passes the removed document (gh-1419)', function(done) {
+      B.create({}, function(err, post) {
         assert.ifError(err);
-        B.findById(post, function (err, found) {
+        B.findById(post, function(err, found) {
           assert.ifError(err);
 
-          found.remove(function (err, doc) {
+          found.remove(function(err, doc) {
             assert.ifError(err);
             assert.ok(doc);
             assert.ok(doc.equals(found));
@@ -2049,25 +2049,25 @@ describe('Model', function () {
       });
     });
 
-    describe('when called multiple times', function () {
-      it('always executes the passed callback gh-1210', function (done) {
+    describe('when called multiple times', function() {
+      it('always executes the passed callback gh-1210', function(done) {
         var db = start(),
             collection = 'blogposts_' + random(),
             BlogPost = db.model('BlogPost', collection),
             post = new BlogPost();
 
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
 
           var pending = 2;
 
-          post.remove(function () {
+          post.remove(function() {
             if (--pending) {
               return;
             }
             done();
           });
-          post.remove(function () {
+          post.remove(function() {
             if (--pending) {
               return;
             }
@@ -2078,8 +2078,8 @@ describe('Model', function () {
     });
   });
 
-  describe('getters', function () {
-    it('with same name on embedded docs do not class', function (done) {
+  describe('getters', function() {
+    it('with same name on embedded docs do not class', function(done) {
       var Post = new Schema({
         title: String,
         author: {name: String},
@@ -2104,7 +2104,7 @@ describe('Model', function () {
       done();
     });
 
-    it('should not be triggered at construction (gh-685)', function (done) {
+    it('should not be triggered at construction (gh-685)', function(done) {
       var db = start(),
           called = false;
 
@@ -2113,10 +2113,10 @@ describe('Model', function () {
       var schema = new mongoose.Schema({
         number: {
           type: Number,
-          set: function (x) {
+          set: function(x) {
             return x / 2;
           },
-          get: function (x) {
+          get: function(x) {
             called = true;
             return x * 2;
           }
@@ -2143,7 +2143,7 @@ describe('Model', function () {
       done();
     });
 
-    it('with type defined with { type: Native } (gh-190)', function (done) {
+    it('with type defined with { type: Native } (gh-190)', function(done) {
       var schema = new Schema({
         date: {type: Date}
       });
@@ -2160,8 +2160,8 @@ describe('Model', function () {
       done();
     });
 
-    describe('nested', function () {
-      it('works', function (done) {
+    describe('nested', function() {
+      it('works', function(done) {
         var schema = new Schema({
           first: {
             second: [Number]
@@ -2179,7 +2179,7 @@ describe('Model', function () {
         done();
       });
 
-      it('works with object literals', function (done) {
+      it('works with object literals', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost', collection);
 
@@ -2258,7 +2258,7 @@ describe('Model', function () {
         done();
       });
 
-      it('object property access works when root initd with null', function (done) {
+      it('object property access works when root initd with null', function(done) {
         var db = start();
 
         var schema = new Schema({
@@ -2277,14 +2277,14 @@ describe('Model', function () {
         assert.deepEqual(t.nest.toObject(), {st: 'jsconf rules'});
         assert.equal(t.nest.st, 'jsconf rules');
 
-        t.save(function (err) {
+        t.save(function(err) {
           db.close();
           assert.ifError(err);
           done();
         });
       });
 
-      it('object property access works when root initd with undefined', function (done) {
+      it('object property access works when root initd with undefined', function(done) {
         var db = start();
 
         var schema = new Schema({
@@ -2303,14 +2303,14 @@ describe('Model', function () {
         assert.deepEqual(t.nest.toObject(), {st: 'jsconf rules'});
         assert.equal(t.nest.st, 'jsconf rules');
 
-        t.save(function (err) {
+        t.save(function(err) {
           db.close();
           assert.ifError(err);
           done();
         });
       });
 
-      it('pre-existing null object re-save', function (done) {
+      it('pre-existing null object re-save', function(done) {
         var db = start();
 
         var schema = new Schema({
@@ -2325,7 +2325,7 @@ describe('Model', function () {
 
         var t = new T({nest: null});
 
-        t.save(function (err) {
+        t.save(function(err) {
           assert.ifError(err);
 
           t.nest = {st: 'jsconf rules', yep: 'it does'};
@@ -2338,16 +2338,16 @@ describe('Model', function () {
           assert.ok(u.$set.nest.yep);
           assert.ok(u.$set.nest.st);
 
-          t.save(function (err) {
+          t.save(function(err) {
             assert.ifError(err);
 
-            T.findById(t.id, function (err, t) {
+            T.findById(t.id, function(err, t) {
               assert.ifError(err);
               assert.equal(t.nest.st, 'jsconf rules');
               assert.equal(t.nest.yep, 'it does');
 
               t.nest = null;
-              t.save(function (err) {
+              t.save(function(err) {
                 db.close();
                 assert.ifError(err);
                 assert.strictEqual(t._doc.nest, null);
@@ -2358,7 +2358,7 @@ describe('Model', function () {
         });
       });
 
-      it('array of Mixed on existing doc can be pushed to', function (done) {
+      it('array of Mixed on existing doc can be pushed to', function(done) {
         var db = start();
 
         mongoose.model('MySchema', new Schema({
@@ -2373,20 +2373,20 @@ describe('Model', function () {
 
         doodad.nested.arrays.push(['+10', 'yup', date]);
 
-        doodad.save(function (err) {
+        doodad.save(function(err) {
           assert.ifError(err);
 
-          DooDad.findById(doodad._id, function (err, doodad) {
+          DooDad.findById(doodad._id, function(err, doodad) {
             assert.ifError(err);
 
             assert.deepEqual(doodad.nested.arrays.toObject(), [['+10', 'yup', date]]);
 
             doodad.nested.arrays.push(['another', 1]);
 
-            doodad.save(function (err) {
+            doodad.save(function(err) {
               assert.ifError(err);
 
-              DooDad.findById(doodad._id, function (err, doodad) {
+              DooDad.findById(doodad._id, function(err, doodad) {
                 db.close();
                 assert.ifError(err);
                 assert.deepEqual(doodad.nested.arrays.toObject(), [['+10', 'yup', date], ['another', 1]]);
@@ -2397,7 +2397,7 @@ describe('Model', function () {
         });
       });
 
-      it('props can be set directly when property was named "type"', function (done) {
+      it('props can be set directly when property was named "type"', function(done) {
         var db = start();
 
         function def() {
@@ -2416,10 +2416,10 @@ describe('Model', function () {
         var DooDad = db.model('MySchema2', collection),
             doodad = new DooDad();
 
-        doodad.save(function (err) {
+        doodad.save(function(err) {
           assert.ifError(err);
 
-          DooDad.findById(doodad._id, function (err, doodad) {
+          DooDad.findById(doodad._id, function(err, doodad) {
             assert.ifError(err);
 
             assert.equal(doodad.nested.type, 'yep');
@@ -2428,10 +2428,10 @@ describe('Model', function () {
             doodad.nested.type = 'nope';
             doodad.nested.array = ['some', 'new', 'stuff'];
 
-            doodad.save(function (err) {
+            doodad.save(function(err) {
               assert.ifError(err);
 
-              DooDad.findById(doodad._id, function (err, doodad) {
+              DooDad.findById(doodad._id, function(err, doodad) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(doodad.nested.type, 'nope');
@@ -2445,8 +2445,8 @@ describe('Model', function () {
     });
   });
 
-  describe('setters', function () {
-    it('are used on embedded docs (gh-365 gh-390 gh-422)', function (done) {
+  describe('setters', function() {
+    it('are used on embedded docs (gh-365 gh-390 gh-422)', function(done) {
       var db = start();
 
       function setLat(val) {
@@ -2480,9 +2480,9 @@ describe('Model', function () {
       assert.equal(deal.locations[0].lat.valueOf(), 1);
       assert.equal(deal.locations[0].long.valueOf(), 2);
 
-      deal.save(function (err) {
+      deal.save(function(err) {
         assert.ifError(err);
-        Deal.findById(deal._id, function (err, deal) {
+        Deal.findById(deal._id, function(err, deal) {
           db.close();
           assert.ifError(err);
           assert.equal(deal.locations[0].lat.valueOf(), 1);
@@ -2494,7 +2494,7 @@ describe('Model', function () {
     });
   });
 
-  it('changing a number non-atomically (gh-203)', function (done) {
+  it('changing a number non-atomically (gh-203)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -2502,18 +2502,18 @@ describe('Model', function () {
 
     post.meta.visitors = 5;
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
-      BlogPost.findById(post._id, function (err, doc) {
+      BlogPost.findById(post._id, function(err, doc) {
         assert.ifError(err);
 
         doc.meta.visitors -= 2;
 
-        doc.save(function (err) {
+        doc.save(function(err) {
           assert.ifError(err);
 
-          BlogPost.findById(post._id, function (err, doc) {
+          BlogPost.findById(post._id, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(3, +doc.meta.visitors);
@@ -2524,8 +2524,8 @@ describe('Model', function () {
     });
   });
 
-  describe('atomic subdocument', function () {
-    it('saving', function (done) {
+  describe('atomic subdocument', function() {
+    it('saving', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection),
           totalDocs = 4,
@@ -2534,37 +2534,37 @@ describe('Model', function () {
       var post = new BlogPost;
 
       function complete() {
-        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function(err, doc) {
           db.close();
 
           assert.ifError(err);
           assert.equal(doc.get('comments').length, 5);
 
-          var v = doc.get('comments').some(function (comment) {
+          var v = doc.get('comments').some(function(comment) {
             return comment.get('title') === '1';
           });
 
           assert.ok(v);
 
-          v = doc.get('comments').some(function (comment) {
+          v = doc.get('comments').some(function(comment) {
             return comment.get('title') === '2';
           });
 
           assert.ok(v);
 
-          v = doc.get('comments').some(function (comment) {
+          v = doc.get('comments').some(function(comment) {
             return comment.get('title') === '3';
           });
 
           assert.ok(v);
 
-          v = doc.get('comments').some(function (comment) {
+          v = doc.get('comments').some(function(comment) {
             return comment.get('title') === '4';
           });
 
           assert.ok(v);
 
-          v = doc.get('comments').some(function (comment) {
+          v = doc.get('comments').some(function(comment) {
             return comment.get('title') === '5';
           });
 
@@ -2576,8 +2576,8 @@ describe('Model', function () {
       function save(doc) {
         saveQueue.push(doc);
         if (saveQueue.length === 4) {
-          saveQueue.forEach(function (doc) {
-            doc.save(function (err) {
+          saveQueue.forEach(function(doc) {
+            doc.save(function(err) {
               assert.ifError(err);
               --totalDocs || complete();
             });
@@ -2585,28 +2585,28 @@ describe('Model', function () {
         }
       }
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('comments').push({title: '1'});
           save(doc);
         });
 
-        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('comments').push({title: '2'});
           save(doc);
         });
 
-        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('comments').push({title: '3'});
           save(doc);
         });
 
-        BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+        BlogPost.findOne({_id: post.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('comments').push({title: '4'}, {title: '5'});
           save(doc);
@@ -2614,25 +2614,25 @@ describe('Model', function () {
       });
     });
 
-    it('setting (gh-310)', function (done) {
+    it('setting (gh-310)', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       BlogPost.create({
         comments: [{title: 'first-title', body: 'first-body'}]
-      }, function (err, blog) {
+      }, function(err, blog) {
         assert.ifError(err);
-        BlogPost.findById(blog.id, function (err, agent1blog) {
+        BlogPost.findById(blog.id, function(err, agent1blog) {
           assert.ifError(err);
-          BlogPost.findById(blog.id, function (err, agent2blog) {
+          BlogPost.findById(blog.id, function(err, agent2blog) {
             assert.ifError(err);
             agent1blog.get('comments')[0].title = 'second-title';
-            agent1blog.save(function (err) {
+            agent1blog.save(function(err) {
               assert.ifError(err);
               agent2blog.get('comments')[0].body = 'second-body';
-              agent2blog.save(function (err) {
+              agent2blog.save(function(err) {
                 assert.ifError(err);
-                BlogPost.findById(blog.id, function (err, foundBlog) {
+                BlogPost.findById(blog.id, function(err, foundBlog) {
                   assert.ifError(err);
                   db.close();
                   var comment = foundBlog.get('comments')[0];
@@ -2648,7 +2648,7 @@ describe('Model', function () {
     });
   });
 
-  it('doubly nested array saving and loading', function (done) {
+  it('doubly nested array saving and loading', function(done) {
     var Inner = new Schema({
       arr: [Number]
     });
@@ -2663,18 +2663,18 @@ describe('Model', function () {
 
     var outer = new Outer();
     outer.inner.push({});
-    outer.save(function (err) {
+    outer.save(function(err) {
       assert.ifError(err);
       assert.ok(outer.get('_id') instanceof DocumentObjectId);
 
-      Outer.findById(outer.get('_id'), function (err, found) {
+      Outer.findById(outer.get('_id'), function(err, found) {
         assert.ifError(err);
         assert.equal(1, found.inner.length);
         found.inner[0].arr.push(5);
-        found.save(function (err) {
+        found.save(function(err) {
           assert.ifError(err);
           assert.ok(found.get('_id') instanceof DocumentObjectId);
-          Outer.findById(found.get('_id'), function (err, found2) {
+          Outer.findById(found.get('_id'), function(err, found2) {
             db.close();
             assert.ifError(err);
             assert.equal(1, found2.inner.length);
@@ -2687,7 +2687,7 @@ describe('Model', function () {
     });
   });
 
-  it('updating multiple Number $pushes as a single $pushAll', function (done) {
+  it('updating multiple Number $pushes as a single $pushAll', function(done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2698,17 +2698,17 @@ describe('Model', function () {
     mongoose.model('NestedPushes', schema);
     var Temp = db.model('NestedPushes', collection);
 
-    Temp.create({}, function (err, t) {
+    Temp.create({}, function(err, t) {
       assert.ifError(err);
       t.nested.nums.push(1);
       t.nested.nums.push(2);
 
       assert.equal(t.nested.nums.length, 2);
 
-      t.save(function (err) {
+      t.save(function(err) {
         assert.ifError(err);
         assert.equal(t.nested.nums.length, 2);
-        Temp.findById(t._id, function (err) {
+        Temp.findById(t._id, function(err) {
           db.close();
           assert.ifError(err);
           assert.equal(t.nested.nums.length, 2);
@@ -2718,7 +2718,7 @@ describe('Model', function () {
     });
   });
 
-  it('updating at least a single $push and $pushAll as a single $pushAll', function (done) {
+  it('updating at least a single $push and $pushAll as a single $pushAll', function(done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2728,16 +2728,16 @@ describe('Model', function () {
 
     var Temp = db.model('NestedPushes', schema, collection);
 
-    Temp.create({}, function (err, t) {
+    Temp.create({}, function(err, t) {
       assert.ifError(err);
       t.nested.nums.push(1);
       t.nested.nums.push(2, 3);
       assert.equal(3, t.nested.nums.length);
 
-      t.save(function (err) {
+      t.save(function(err) {
         assert.ifError(err);
         assert.equal(t.nested.nums.length, 3);
-        Temp.findById(t._id, function (err, found) {
+        Temp.findById(t._id, function(err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(found.nested.nums.length, 3);
@@ -2747,7 +2747,7 @@ describe('Model', function () {
     });
   });
 
-  it('activePaths should be updated for nested modifieds', function (done) {
+  it('activePaths should be updated for nested modifieds', function(done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2757,7 +2757,7 @@ describe('Model', function () {
 
     var Temp = db.model('NestedPushes', schema, collection);
 
-    Temp.create({nested: {nums: [1, 2, 3, 4, 5]}}, function (err, t) {
+    Temp.create({nested: {nums: [1, 2, 3, 4, 5]}}, function(err, t) {
       assert.ifError(err);
       t.nested.nums.pull(1);
       t.nested.nums.pull(2);
@@ -2768,7 +2768,7 @@ describe('Model', function () {
   });
 
 
-  it('activePaths should be updated for nested modifieds as promise', function (done) {
+  it('activePaths should be updated for nested modifieds as promise', function(done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2779,7 +2779,7 @@ describe('Model', function () {
     var Temp = db.model('NestedPushes', schema, collection);
 
     var p1 = Temp.create({nested: {nums: [1, 2, 3, 4, 5]}});
-    p1.onResolve(function (err, t) {
+    p1.onResolve(function(err, t) {
       assert.ifError(err);
       t.nested.nums.pull(1);
       t.nested.nums.pull(2);
@@ -2789,7 +2789,7 @@ describe('Model', function () {
     });
   });
 
-  it('$pull should affect what you see in an array before a save', function (done) {
+  it('$pull should affect what you see in an array before a save', function(done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2799,7 +2799,7 @@ describe('Model', function () {
 
     var Temp = db.model('NestedPushes', schema, collection);
 
-    Temp.create({nested: {nums: [1, 2, 3, 4, 5]}}, function (err, t) {
+    Temp.create({nested: {nums: [1, 2, 3, 4, 5]}}, function(err, t) {
       assert.ifError(err);
       t.nested.nums.pull(1);
       assert.equal(4, t.nested.nums.length);
@@ -2808,7 +2808,7 @@ describe('Model', function () {
     });
   });
 
-  it('$shift', function (done) {
+  it('$shift', function(done) {
     var db = start(),
         schema = new Schema({
           nested: {
@@ -2819,10 +2819,10 @@ describe('Model', function () {
     mongoose.model('TestingShift', schema);
     var Temp = db.model('TestingShift', collection);
 
-    Temp.create({nested: {nums: [1, 2, 3]}}, function (err, t) {
+    Temp.create({nested: {nums: [1, 2, 3]}}, function(err, t) {
       assert.ifError(err);
 
-      Temp.findById(t._id, function (err, found) {
+      Temp.findById(t._id, function(err, found) {
         assert.ifError(err);
         assert.equal(found.nested.nums.length, 3);
         found.nested.nums.$pop();
@@ -2830,9 +2830,9 @@ describe('Model', function () {
         assert.equal(found.nested.nums[0], 1);
         assert.equal(found.nested.nums[1], 2);
 
-        found.save(function (err) {
+        found.save(function(err) {
           assert.ifError(err);
-          Temp.findById(t._id, function (err, found) {
+          Temp.findById(t._id, function(err, found) {
             assert.ifError(err);
             assert.equal(2, found.nested.nums.length);
             assert.equal(1, found.nested.nums[0], 1);
@@ -2841,9 +2841,9 @@ describe('Model', function () {
             assert.equal(1, found.nested.nums.length);
             assert.equal(found.nested.nums[0], 2);
 
-            found.save(function (err) {
+            found.save(function(err) {
               assert.ifError(err);
-              Temp.findById(t._id, function (err, found) {
+              Temp.findById(t._id, function(err, found) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(found.nested.nums.length, 1);
@@ -2857,8 +2857,8 @@ describe('Model', function () {
     });
   });
 
-  describe('saving embedded arrays', function () {
-    it('of Numbers atomically', function (done) {
+  describe('saving embedded arrays', function() {
+    it('of Numbers atomically', function(done) {
       var db = start(),
           TempSchema = new Schema({
             nums: [Number]
@@ -2872,21 +2872,21 @@ describe('Model', function () {
       var t = new Temp();
 
       function complete() {
-        Temp.findOne({_id: t.get('_id')}, function (err, doc) {
+        Temp.findOne({_id: t.get('_id')}, function(err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.get('nums').length);
 
-          var v = doc.get('nums').some(function (num) {
+          var v = doc.get('nums').some(function(num) {
             return num.valueOf() === 1;
           });
           assert.ok(v);
 
-          v = doc.get('nums').some(function (num) {
+          v = doc.get('nums').some(function(num) {
             return num.valueOf() === 2;
           });
           assert.ok(v);
 
-          v = doc.get('nums').some(function (num) {
+          v = doc.get('nums').some(function(num) {
             return num.valueOf() === 3;
           });
           assert.ok(v);
@@ -2897,8 +2897,8 @@ describe('Model', function () {
       function save(doc) {
         saveQueue.push(doc);
         if (saveQueue.length === totalDocs) {
-          saveQueue.forEach(function (doc) {
-            doc.save(function (err) {
+          saveQueue.forEach(function(doc) {
+            doc.save(function(err) {
               assert.ifError(err);
               --totalDocs || complete();
             });
@@ -2906,16 +2906,16 @@ describe('Model', function () {
         }
       }
 
-      t.save(function (err) {
+      t.save(function(err) {
         assert.ifError(err);
 
-        Temp.findOne({_id: t.get('_id')}, function (err, doc) {
+        Temp.findOne({_id: t.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('nums').push(1);
           save(doc);
         });
 
-        Temp.findOne({_id: t.get('_id')}, function (err, doc) {
+        Temp.findOne({_id: t.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('nums').push(2, 3);
           save(doc);
@@ -2923,7 +2923,7 @@ describe('Model', function () {
       });
     });
 
-    it('of Strings atomically', function (done) {
+    it('of Strings atomically', function(done) {
       var db = start(),
           StrListSchema = new Schema({
             strings: [String]
@@ -2937,23 +2937,23 @@ describe('Model', function () {
       var t = new StrList();
 
       function complete() {
-        StrList.findOne({_id: t.get('_id')}, function (err, doc) {
+        StrList.findOne({_id: t.get('_id')}, function(err, doc) {
           db.close();
           assert.ifError(err);
 
           assert.equal(3, doc.get('strings').length);
 
-          var v = doc.get('strings').some(function (str) {
+          var v = doc.get('strings').some(function(str) {
             return str === 'a';
           });
           assert.ok(v);
 
-          v = doc.get('strings').some(function (str) {
+          v = doc.get('strings').some(function(str) {
             return str === 'b';
           });
           assert.ok(v);
 
-          v = doc.get('strings').some(function (str) {
+          v = doc.get('strings').some(function(str) {
             return str === 'c';
           });
           assert.ok(v);
@@ -2964,8 +2964,8 @@ describe('Model', function () {
       function save(doc) {
         saveQueue.push(doc);
         if (saveQueue.length === totalDocs) {
-          saveQueue.forEach(function (doc) {
-            doc.save(function (err) {
+          saveQueue.forEach(function(doc) {
+            doc.save(function(err) {
               assert.ifError(err);
               --totalDocs || complete();
             });
@@ -2973,16 +2973,16 @@ describe('Model', function () {
         }
       }
 
-      t.save(function (err) {
+      t.save(function(err) {
         assert.ifError(err);
 
-        StrList.findOne({_id: t.get('_id')}, function (err, doc) {
+        StrList.findOne({_id: t.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('strings').push('a');
           save(doc);
         });
 
-        StrList.findOne({_id: t.get('_id')}, function (err, doc) {
+        StrList.findOne({_id: t.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('strings').push('b', 'c');
           save(doc);
@@ -2990,7 +2990,7 @@ describe('Model', function () {
       });
     });
 
-    it('of Buffers atomically', function (done) {
+    it('of Buffers atomically', function(done) {
       var db = start(),
           BufListSchema = new Schema({
             buffers: [Buffer]
@@ -3004,23 +3004,23 @@ describe('Model', function () {
       var t = new BufList();
 
       function complete() {
-        BufList.findOne({_id: t.get('_id')}, function (err, doc) {
+        BufList.findOne({_id: t.get('_id')}, function(err, doc) {
           db.close();
           assert.ifError(err);
 
           assert.equal(3, doc.get('buffers').length);
 
-          var v = doc.get('buffers').some(function (buf) {
+          var v = doc.get('buffers').some(function(buf) {
             return buf[0] === 140;
           });
           assert.ok(v);
 
-          v = doc.get('buffers').some(function (buf) {
+          v = doc.get('buffers').some(function(buf) {
             return buf[0] === 141;
           });
           assert.ok(v);
 
-          v = doc.get('buffers').some(function (buf) {
+          v = doc.get('buffers').some(function(buf) {
             return buf[0] === 142;
           });
           assert.ok(v);
@@ -3032,8 +3032,8 @@ describe('Model', function () {
       function save(doc) {
         saveQueue.push(doc);
         if (saveQueue.length === totalDocs) {
-          saveQueue.forEach(function (doc) {
-            doc.save(function (err) {
+          saveQueue.forEach(function(doc) {
+            doc.save(function(err) {
               assert.ifError(err);
               --totalDocs || complete();
             });
@@ -3041,16 +3041,16 @@ describe('Model', function () {
         }
       }
 
-      t.save(function (err) {
+      t.save(function(err) {
         assert.ifError(err);
 
-        BufList.findOne({_id: t.get('_id')}, function (err, doc) {
+        BufList.findOne({_id: t.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('buffers').push(new Buffer([140]));
           save(doc);
         });
 
-        BufList.findOne({_id: t.get('_id')}, function (err, doc) {
+        BufList.findOne({_id: t.get('_id')}, function(err, doc) {
           assert.ifError(err);
           doc.get('buffers').push(new Buffer([141]), new Buffer([142]));
           save(doc);
@@ -3058,29 +3058,29 @@ describe('Model', function () {
       });
     });
 
-    it('works with modified element properties + doc removal (gh-975)', function (done) {
+    it('works with modified element properties + doc removal (gh-975)', function(done) {
       var db = start(),
           B = db.model('BlogPost', collection),
           b = new B({comments: [{title: 'gh-975'}]});
 
-      b.save(function (err) {
+      b.save(function(err) {
         assert.ifError(err);
 
         b.comments[0].title = 'changed';
-        b.save(function (err) {
+        b.save(function(err) {
           assert.ifError(err);
 
           b.comments[0].remove();
-          b.save(function (err) {
+          b.save(function(err) {
             assert.ifError(err);
 
-            B.findByIdAndUpdate({_id: b._id}, {$set: {comments: [{title: 'a'}]}}, {'new': true}, function (err, doc) {
+            B.findByIdAndUpdate({_id: b._id}, {$set: {comments: [{title: 'a'}]}}, {'new': true}, function(err, doc) {
               assert.ifError(err);
               doc.comments[0].title = 'differ';
               doc.comments[0].remove();
-              doc.save(function (err) {
+              doc.save(function(err) {
                 assert.ifError(err);
-                B.findById(doc._id, function (err, doc) {
+                B.findById(doc._id, function(err, doc) {
                   db.close();
                   assert.ifError(err);
                   assert.equal(0, doc.comments.length);
@@ -3093,7 +3093,7 @@ describe('Model', function () {
       });
     });
 
-    it('updating an embedded document in an embedded array with set call', function (done) {
+    it('updating an embedded document in an embedded array with set call', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -3101,9 +3101,9 @@ describe('Model', function () {
         comments: [{
           title: 'before-change'
         }]
-      }, function (err, post) {
+      }, function(err, post) {
         assert.ifError(err);
-        BlogPost.findById(post._id, function (err, found) {
+        BlogPost.findById(post._id, function(err, found) {
           assert.ifError(err);
           assert.equal('before-change', found.comments[0].title);
           var subDoc = [{
@@ -3112,9 +3112,9 @@ describe('Model', function () {
           }];
           found.set('comments', subDoc);
 
-          found.save(function (err) {
+          found.save(function(err) {
             assert.ifError(err);
-            BlogPost.findById(found._id, function (err, updated) {
+            BlogPost.findById(found._id, function(err, updated) {
               db.close();
               assert.ifError(err);
               assert.equal('after-change', updated.comments[0].title);
@@ -3126,19 +3126,19 @@ describe('Model', function () {
     });
   });
 
-  it('updating an embedded document in an embedded array (gh-255)', function (done) {
+  it('updating an embedded document in an embedded array (gh-255)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
-    BlogPost.create({comments: [{title: 'woot'}]}, function (err, post) {
+    BlogPost.create({comments: [{title: 'woot'}]}, function(err, post) {
       assert.ifError(err);
-      BlogPost.findById(post._id, function (err, found) {
+      BlogPost.findById(post._id, function(err, found) {
         assert.ifError(err);
         assert.equal('woot', found.comments[0].title);
         found.comments[0].title = 'notwoot';
-        found.save(function (err) {
+        found.save(function(err) {
           assert.ifError(err);
-          BlogPost.findById(found._id, function (err, updated) {
+          BlogPost.findById(found._id, function(err, updated) {
             db.close();
             assert.ifError(err);
             assert.equal('notwoot', updated.comments[0].title);
@@ -3149,7 +3149,7 @@ describe('Model', function () {
     });
   });
 
-  it('updating an embedded array document to an Object value (gh-334)', function (done) {
+  it('updating an embedded array document to an Object value (gh-334)', function(done) {
     var db = start(),
         SubSchema = new Schema({
           name: String,
@@ -3162,14 +3162,14 @@ describe('Model', function () {
     var instance = new AModel();
 
     instance.set({name: 'name-value', arrData: [{name: 'arrName1', subObj: {subName: 'subName1'}}]});
-    instance.save(function (err) {
+    instance.save(function(err) {
       assert.ifError(err);
-      AModel.findById(instance.id, function (err, doc) {
+      AModel.findById(instance.id, function(err, doc) {
         assert.ifError(err);
         doc.arrData[0].set('subObj', {subName: 'modified subName'});
-        doc.save(function (err) {
+        doc.save(function(err) {
           assert.ifError(err);
-          AModel.findById(instance.id, function (err, doc) {
+          AModel.findById(instance.id, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(doc.arrData[0].subObj.subName, 'modified subName');
@@ -3180,22 +3180,22 @@ describe('Model', function () {
     });
   });
 
-  it('saving an embedded document twice should not push that doc onto the parent doc twice (gh-267)', function (done) {
+  it('saving an embedded document twice should not push that doc onto the parent doc twice (gh-267)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection),
         post = new BlogPost();
 
     post.comments.push({title: 'woot'});
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
       assert.equal(1, post.comments.length);
-      BlogPost.findById(post.id, function (err, found) {
+      BlogPost.findById(post.id, function(err, found) {
         assert.ifError(err);
         assert.equal(1, found.comments.length);
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
           assert.equal(1, post.comments.length);
-          BlogPost.findById(post.id, function (err, found) {
+          BlogPost.findById(post.id, function(err, found) {
             db.close();
             assert.ifError(err);
             assert.equal(1, found.comments.length);
@@ -3206,8 +3206,8 @@ describe('Model', function () {
     });
   });
 
-  describe('embedded array filtering', function () {
-    it('by the id shortcut function', function (done) {
+  describe('embedded array filtering', function() {
+    it('by the id shortcut function', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -3219,10 +3219,10 @@ describe('Model', function () {
       var subdoc1 = post.comments[0];
       var subdoc2 = post.comments[1];
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPost.findById(post.get('_id'), function (err, doc) {
+        BlogPost.findById(post.get('_id'), function(err, doc) {
           db.close();
           assert.ifError(err);
 
@@ -3237,16 +3237,16 @@ describe('Model', function () {
       });
     });
 
-    it('by the id with cast error', function (done) {
+    it('by the id with cast error', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost();
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPost.findById(post.get('_id'), function (err, doc) {
+        BlogPost.findById(post.get('_id'), function(err, doc) {
           db.close();
           assert.ifError(err);
           assert.strictEqual(doc.comments.id(null), null);
@@ -3255,16 +3255,16 @@ describe('Model', function () {
       });
     });
 
-    it('by the id shortcut with no match', function (done) {
+    it('by the id shortcut with no match', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost();
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        BlogPost.findById(post.get('_id'), function (err, doc) {
+        BlogPost.findById(post.get('_id'), function(err, doc) {
           db.close();
           assert.ifError(err);
           assert.strictEqual(doc.comments.id(new DocumentObjectId), null);
@@ -3274,7 +3274,7 @@ describe('Model', function () {
     });
   });
 
-  it('removing a subdocument atomically', function (done) {
+  it('removing a subdocument atomically', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -3283,17 +3283,17 @@ describe('Model', function () {
     post.comments.push({title: 'woot'});
     post.comments.push({title: 'aaaa'});
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
-      BlogPost.findById(post.get('_id'), function (err, doc) {
+      BlogPost.findById(post.get('_id'), function(err, doc) {
         assert.ifError(err);
 
         doc.comments[0].remove();
-        doc.save(function (err) {
+        doc.save(function(err) {
           assert.ifError(err);
 
-          BlogPost.findById(post.get('_id'), function (err, doc) {
+          BlogPost.findById(post.get('_id'), function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(1, doc.comments.length);
@@ -3305,7 +3305,7 @@ describe('Model', function () {
     });
   });
 
-  it('single pull embedded doc', function (done) {
+  it('single pull embedded doc', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
@@ -3314,18 +3314,18 @@ describe('Model', function () {
     post.comments.push({title: 'woot'});
     post.comments.push({title: 'aaaa'});
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
-      BlogPost.findById(post.get('_id'), function (err, doc) {
+      BlogPost.findById(post.get('_id'), function(err, doc) {
         assert.ifError(err);
 
         doc.comments.pull(doc.comments[0]);
         doc.comments.pull(doc.comments[0]);
-        doc.save(function (err) {
+        doc.save(function(err) {
           assert.ifError(err);
 
-          BlogPost.findById(post.get('_id'), function (err, doc) {
+          BlogPost.findById(post.get('_id'), function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(0, doc.comments.length);
@@ -3336,7 +3336,7 @@ describe('Model', function () {
     });
   });
 
-  it('saving mixed data', function (done) {
+  it('saving mixed data', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection),
         count = 3;
@@ -3344,10 +3344,10 @@ describe('Model', function () {
     // string
     var post = new BlogPost();
     post.mixed = 'woot';
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
-      BlogPost.findById(post._id, function (err) {
+      BlogPost.findById(post._id, function(err) {
         assert.ifError(err);
         if (--count) {
           return;
@@ -3360,19 +3360,19 @@ describe('Model', function () {
     // array
     var post2 = new BlogPost();
     post2.mixed = {name: 'mr bungle', arr: []};
-    post2.save(function (err) {
+    post2.save(function(err) {
       assert.ifError(err);
 
-      BlogPost.findById(post2._id, function (err, doc) {
+      BlogPost.findById(post2._id, function(err, doc) {
         assert.ifError(err);
 
         assert.equal(true, Array.isArray(doc.mixed.arr));
 
         doc.mixed = [{foo: 'bar'}];
-        doc.save(function (err) {
+        doc.save(function(err) {
           assert.ifError(err);
 
-          BlogPost.findById(doc._id, function (err, doc) {
+          BlogPost.findById(doc._id, function(err, doc) {
             assert.ifError(err);
 
             assert.equal(true, Array.isArray(doc.mixed));
@@ -3380,10 +3380,10 @@ describe('Model', function () {
             doc.mixed.push(['foo', 'bar']);
             doc.markModified('mixed');
 
-            doc.save(function (err) {
+            doc.save(function(err) {
               assert.ifError(err);
 
-              BlogPost.findById(post2._id, function (err, doc) {
+              BlogPost.findById(post2._id, function(err, doc) {
                 assert.ifError(err);
 
                 assert.deepEqual(doc.mixed[0], {foo: 'bar'});
@@ -3401,10 +3401,10 @@ describe('Model', function () {
           // date
           var post3 = new BlogPost();
           post3.mixed = new Date;
-          post3.save(function (err) {
+          post3.save(function(err) {
             assert.ifError(err);
 
-            BlogPost.findById(post3._id, function (err, doc) {
+            BlogPost.findById(post3._id, function(err, doc) {
               assert.ifError(err);
               assert.ok(doc.mixed instanceof Date);
               if (--count) {
@@ -3419,7 +3419,7 @@ describe('Model', function () {
     });
   });
 
-  it('populating mixed data from the constructor (gh-200)', function (done) {
+  it('populating mixed data from the constructor (gh-200)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost');
 
@@ -3440,7 +3440,7 @@ describe('Model', function () {
     done();
   });
 
-  it('"type" is allowed as a key', function (done) {
+  it('"type" is allowed as a key', function(done) {
     mongoose.model('TestTypeDefaults', new Schema({
       type: {type: String, default: 'YES!'}
     }));
@@ -3460,30 +3460,30 @@ describe('Model', function () {
     post = new TestDefaults2;
     post.x.y.type = '#402';
     post.x.y.owner = 'me';
-    post.save(function (err) {
+    post.save(function(err) {
       db.close();
       assert.ifError(err);
       done();
     });
   });
 
-  it('unaltered model does not clear the doc (gh-195)', function (done) {
+  it('unaltered model does not clear the doc (gh-195)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
     var post = new BlogPost();
     post.title = 'woot';
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
 
-      BlogPost.findById(post._id, function (err, doc) {
+      BlogPost.findById(post._id, function(err, doc) {
         assert.ifError(err);
 
         // we deliberately make no alterations
-        doc.save(function (err) {
+        doc.save(function(err) {
           assert.ifError(err);
 
-          BlogPost.findById(doc._id, function (err, doc) {
+          BlogPost.findById(doc._id, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(doc.title, 'woot');
@@ -3494,8 +3494,8 @@ describe('Model', function () {
     });
   });
 
-  describe('safe mode', function () {
-    it('works', function (done) {
+  describe('safe mode', function() {
+    it('works', function(done) {
       var Human = new Schema({
         name: String,
         email: {type: String, index: {unique: true, background: false}}
@@ -3506,17 +3506,17 @@ describe('Model', function () {
       var db = start();
       Human = db.model('SafeHuman', 'safehuman' + random());
 
-      Human.on('index', function (err) {
+      Human.on('index', function(err) {
         assert.ifError(err);
         var me = new Human({
           name: 'Guillermo Rauch',
           email: 'rauchg@gmail.com'
         });
 
-        me.save(function (err) {
+        me.save(function(err) {
           assert.ifError(err);
 
-          Human.findById(me._id, function (err, doc) {
+          Human.findById(me._id, function(err, doc) {
             assert.ifError(err);
             assert.equal(doc.email, 'rauchg@gmail.com');
 
@@ -3525,7 +3525,7 @@ describe('Model', function () {
               email: 'rauchg@gmail.com'
             });
 
-            copycat.save(function (err) {
+            copycat.save(function(err) {
               db.close();
               assert.ok(/duplicate/.test(err.message));
               assert.ok(err instanceof Error);
@@ -3536,7 +3536,7 @@ describe('Model', function () {
       });
     });
 
-    it('can be disabled', function (done) {
+    it('can be disabled', function(done) {
       var Human = new Schema({
         name: String,
         email: {type: String, index: {unique: true, background: false}}
@@ -3550,7 +3550,7 @@ describe('Model', function () {
       var db = start();
       Human = db.model('UnsafeHuman', 'unsafehuman' + random());
 
-      Human.on('index', function (err) {
+      Human.on('index', function(err) {
         assert.ifError(err);
       });
 
@@ -3559,13 +3559,13 @@ describe('Model', function () {
         email: 'rauchg@gmail.com'
       });
 
-      me.save(function (err) {
+      me.save(function(err) {
         assert.ifError(err);
 
         // no confirmation the write occured b/c we disabled safe.
         // wait a little bit to ensure the doc exists in the db
-        setTimeout(function () {
-          Human.findById(me._id, function (err, doc) {
+        setTimeout(function() {
+          Human.findById(me._id, function(err, doc) {
             assert.ifError(err);
             assert.equal(doc.email, 'rauchg@gmail.com');
 
@@ -3574,7 +3574,7 @@ describe('Model', function () {
               email: 'rauchg@gmail.com'
             });
 
-            copycat.save(function (err) {
+            copycat.save(function(err) {
               db.close();
               assert.ifError(err);
               done();
@@ -3585,22 +3585,22 @@ describe('Model', function () {
     });
   });
 
-  describe('hooks', function () {
-    describe('pre', function () {
-      it('can pass non-error values to the next middleware', function (done) {
+  describe('hooks', function() {
+    describe('pre', function() {
+      it('can pass non-error values to the next middleware', function(done) {
         var db = start();
         var schema = new Schema({name: String});
 
-        schema.pre('save', function (next) {
+        schema.pre('save', function(next) {
           next('hey there');
-        }).pre('save', function (next, message) {
+        }).pre('save', function(next, message) {
           assert.ok(message);
           assert.equal(message, 'hey there');
           next();
-        }).pre('save', function (next) {
+        }).pre('save', function(next) {
           // just throw error
           next(new Error('error string'));
-        }).pre('save', function (next) {
+        }).pre('save', function(next) {
           // don't call since error thrown in previous save
           assert.ok(false);
           next('don\'t call me');
@@ -3608,7 +3608,7 @@ describe('Model', function () {
         var S = db.model('S', schema, collection);
         var s = new S({name: 'angelina'});
 
-        s.save(function (err) {
+        s.save(function(err) {
           db.close();
           assert.ok(err);
           assert.equal(err.message, 'error string');
@@ -3616,17 +3616,17 @@ describe('Model', function () {
         });
       });
 
-      it('with undefined and null', function (done) {
+      it('with undefined and null', function(done) {
         var db = start();
         var schema = new Schema({name: String});
         var called = 0;
 
-        schema.pre('save', function (next) {
+        schema.pre('save', function(next) {
           called++;
           next(undefined);
         });
 
-        schema.pre('save', function (next) {
+        schema.pre('save', function(next) {
           called++;
           next(null);
         });
@@ -3634,7 +3634,7 @@ describe('Model', function () {
         var S = db.model('S', schema, collection);
         var s = new S({name: 'zupa'});
 
-        s.save(function (err) {
+        s.save(function(err) {
           db.close();
           assert.ifError(err);
           assert.equal(2, called);
@@ -3643,20 +3643,20 @@ describe('Model', function () {
       });
 
 
-      it('with an async waterfall', function (done) {
+      it('with an async waterfall', function(done) {
         var db = start();
         var schema = new Schema({name: String});
         var called = 0;
 
-        schema.pre('save', true, function (next, done) {
+        schema.pre('save', true, function(next, done) {
           called++;
-          process.nextTick(function () {
+          process.nextTick(function() {
             next();
             done();
           });
         });
 
-        schema.pre('save', function (next) {
+        schema.pre('save', function(next) {
           called++;
           return next();
         });
@@ -3665,7 +3665,7 @@ describe('Model', function () {
         var s = new S({name: 'zupa'});
 
         var p = s.save();
-        p.onResolve(function (err) {
+        p.onResolve(function(err) {
           db.close();
           assert.ifError(err);
           assert.equal(2, called);
@@ -3674,24 +3674,24 @@ describe('Model', function () {
       });
 
 
-      it('called on all sub levels', function (done) {
+      it('called on all sub levels', function(done) {
         var db = start();
 
         var grandSchema = new Schema({name: String});
-        grandSchema.pre('save', function (next) {
+        grandSchema.pre('save', function(next) {
           this.name = 'grand';
           next();
         });
 
         var childSchema = new Schema({name: String, grand: [grandSchema]});
-        childSchema.pre('save', function (next) {
+        childSchema.pre('save', function(next) {
           this.name = 'child';
           next();
         });
 
         var schema = new Schema({name: String, child: [childSchema]});
 
-        schema.pre('save', function (next) {
+        schema.pre('save', function(next) {
           this.name = 'parent';
           next();
         });
@@ -3699,7 +3699,7 @@ describe('Model', function () {
         var S = db.model('presave_hook', schema, 'presave_hook');
         var s = new S({name: 'a', child: [{name: 'b', grand: [{name: 'c'}]}]});
 
-        s.save(function (err, doc) {
+        s.save(function(err, doc) {
           db.close();
           assert.ifError(err);
           assert.equal(doc.name, 'parent');
@@ -3710,22 +3710,22 @@ describe('Model', function () {
       });
 
 
-      it('error on any sub level', function (done) {
+      it('error on any sub level', function(done) {
         var db = start();
 
         var grandSchema = new Schema({name: String});
-        grandSchema.pre('save', function (next) {
+        grandSchema.pre('save', function(next) {
           next(new Error('Error 101'));
         });
 
         var childSchema = new Schema({name: String, grand: [grandSchema]});
-        childSchema.pre('save', function (next) {
+        childSchema.pre('save', function(next) {
           this.name = 'child';
           next();
         });
 
         var schema = new Schema({name: String, child: [childSchema]});
-        schema.pre('save', function (next) {
+        schema.pre('save', function(next) {
           this.name = 'parent';
           next();
         });
@@ -3733,7 +3733,7 @@ describe('Model', function () {
         var S = db.model('presave_hook_error', schema, 'presave_hook_error');
         var s = new S({name: 'a', child: [{name: 'b', grand: [{name: 'c'}]}]});
 
-        s.save(function (err) {
+        s.save(function(err) {
           db.close();
           assert.ok(err instanceof Error);
           assert.equal(err.message, 'Error 101');
@@ -3741,13 +3741,13 @@ describe('Model', function () {
         });
       });
 
-      describe('init', function () {
-        it('has access to the true ObjectId when used with querying (gh-289)', function (done) {
+      describe('init', function() {
+        it('has access to the true ObjectId when used with querying (gh-289)', function(done) {
           var db = start(),
               PreInitSchema = new Schema({}),
               preId = null;
 
-          PreInitSchema.pre('init', function (next) {
+          PreInitSchema.pre('init', function(next) {
             preId = this._id;
             next();
           });
@@ -3755,9 +3755,9 @@ describe('Model', function () {
           var PreInit = db.model('PreInit', PreInitSchema, 'pre_inits' + random());
 
           var doc = new PreInit();
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
-            PreInit.findById(doc._id, function (err) {
+            PreInit.findById(doc._id, function(err) {
               db.close();
               assert.ifError(err);
               assert.strictEqual(undefined, preId);
@@ -3767,15 +3767,15 @@ describe('Model', function () {
         });
       });
 
-      it('should not work when calling next() after a thrown error', function (done) {
+      it('should not work when calling next() after a thrown error', function(done) {
         var db = start();
 
         var s = new Schema({});
-        s.methods.funky = function () {
+        s.methods.funky = function() {
           assert.strictEqual(false, true, 'reached unreachable code');
         };
 
-        s.pre('funky', function (next) {
+        s.pre('funky', function(next) {
           db.close();
           try {
             next(new Error);
@@ -3791,8 +3791,8 @@ describe('Model', function () {
       });
     });
 
-    describe('post', function () {
-      it('works', function (done) {
+    describe('post', function() {
+      it('works', function(done) {
         var schema = new Schema({
               title: String
             }),
@@ -3801,16 +3801,16 @@ describe('Model', function () {
             init = false,
             post = undefined;
 
-        schema.post('save', function (arg) {
+        schema.post('save', function(arg) {
           assert.equal(arg.id, post.id);
           save = true;
         });
 
-        schema.post('init', function () {
+        schema.post('init', function() {
           init = true;
         });
 
-        schema.post('remove', function (arg) {
+        schema.post('remove', function(arg) {
           assert.equal(arg.id, post.id);
           remove = true;
         });
@@ -3822,17 +3822,17 @@ describe('Model', function () {
 
         post = new BlogPost();
 
-        post.save(function (err) {
-          process.nextTick(function () {
+        post.save(function(err) {
+          process.nextTick(function() {
             assert.ifError(err);
             assert.ok(save);
-            BlogPost.findById(post._id, function (err, doc) {
-              process.nextTick(function () {
+            BlogPost.findById(post._id, function(err, doc) {
+              process.nextTick(function() {
                 assert.ifError(err);
                 assert.ok(init);
 
-                doc.remove(function (err) {
-                  process.nextTick(function () {
+                doc.remove(function(err) {
+                  process.nextTick(function() {
                     db.close();
                     assert.ifError(err);
                     assert.ok(remove);
@@ -3845,7 +3845,7 @@ describe('Model', function () {
         });
       });
 
-      it('on embedded docs', function (done) {
+      it('on embedded docs', function(done) {
         var save = false;
 
         var EmbeddedSchema = new Schema({
@@ -3856,7 +3856,7 @@ describe('Model', function () {
           embeds: [EmbeddedSchema]
         });
 
-        EmbeddedSchema.post('save', function () {
+        EmbeddedSchema.post('save', function() {
           save = true;
         });
 
@@ -3878,7 +3878,7 @@ describe('Model', function () {
 
         parent.embeds.push({title: 'Testing post hooks for embedded docs'});
 
-        parent.save(function (err) {
+        parent.save(function(err) {
           db.close();
           assert.ifError(err);
           assert.ok(save);
@@ -3888,15 +3888,15 @@ describe('Model', function () {
     });
   });
 
-  describe('#exec()', function () {
-    it('count()', function (done) {
+  describe('#exec()', function() {
+    it('count()', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-      BlogPost.create({title: 'interoperable count as promise'}, function (err) {
+      BlogPost.create({title: 'interoperable count as promise'}, function(err) {
         assert.ifError(err);
         var query = BlogPost.count({title: 'interoperable count as promise'});
-        query.exec(function (err, count) {
+        query.exec(function(err, count) {
           db.close();
           assert.ifError(err);
           assert.equal(1, count);
@@ -3905,17 +3905,17 @@ describe('Model', function () {
       });
     });
 
-    it('update()', function (done) {
+    it('update()', function(done) {
       var col = 'BlogPost' + random();
       var db = start(),
           BlogPost = db.model(col, bpSchema);
 
-      BlogPost.create({title: 'interoperable update as promise'}, function (err) {
+      BlogPost.create({title: 'interoperable update as promise'}, function(err) {
         assert.ifError(err);
         var query = BlogPost.update({title: 'interoperable update as promise'}, {title: 'interoperable update as promise delta'});
-        query.exec(function (err) {
+        query.exec(function(err) {
           assert.ifError(err);
-          BlogPost.count({title: 'interoperable update as promise delta'}, function (err, count) {
+          BlogPost.count({title: 'interoperable update as promise delta'}, function(err, count) {
             db.close();
             assert.ifError(err);
             assert.equal(1, count);
@@ -3925,14 +3925,14 @@ describe('Model', function () {
       });
     });
 
-    it('findOne()', function (done) {
+    it('findOne()', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-      BlogPost.create({title: 'interoperable findOne as promise'}, function (err, created) {
+      BlogPost.create({title: 'interoperable findOne as promise'}, function(err, created) {
         assert.ifError(err);
         var query = BlogPost.findOne({title: 'interoperable findOne as promise'});
-        query.exec(function (err, found) {
+        query.exec(function(err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(found.id, created.id);
@@ -3941,17 +3941,17 @@ describe('Model', function () {
       });
     });
 
-    it('find()', function (done) {
+    it('find()', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema);
 
       BlogPost.create(
           {title: 'interoperable find as promise'},
           {title: 'interoperable find as promise'},
-          function (err, createdOne, createdTwo) {
+          function(err, createdOne, createdTwo) {
             assert.ifError(err);
             var query = BlogPost.find({title: 'interoperable find as promise'}).sort('_id');
-            query.exec(function (err, found) {
+            query.exec(function(err, found) {
               db.close();
               assert.ifError(err);
               assert.equal(found.length, 2);
@@ -3965,18 +3965,18 @@ describe('Model', function () {
           });
     });
 
-    it('remove()', function (done) {
+    it('remove()', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema);
 
       BlogPost.create(
           {title: 'interoperable remove as promise'},
-          function (err) {
+          function(err) {
             assert.ifError(err);
             var query = BlogPost.remove({title: 'interoperable remove as promise'});
-            query.exec(function (err) {
+            query.exec(function(err) {
               assert.ifError(err);
-              BlogPost.count({title: 'interoperable remove as promise'}, function (err, count) {
+              BlogPost.count({title: 'interoperable remove as promise'}, function(err, count) {
                 db.close();
                 assert.equal(count, 0);
                 done();
@@ -3985,15 +3985,15 @@ describe('Model', function () {
           });
     });
 
-    it('op can be changed', function (done) {
+    it('op can be changed', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost' + random(), bpSchema),
           title = 'interop ad-hoc as promise';
 
-      BlogPost.create({title: title}, function (err, created) {
+      BlogPost.create({title: title}, function(err, created) {
         assert.ifError(err);
         var query = BlogPost.count({title: title});
-        query.exec('findOne', function (err, found) {
+        query.exec('findOne', function(err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(found.id, created.id);
@@ -4002,16 +4002,16 @@ describe('Model', function () {
       });
     });
 
-    describe('promises', function () {
-      it('count()', function (done) {
+    describe('promises', function() {
+      it('count()', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-        BlogPost.create({title: 'interoperable count as promise 2'}, function (err) {
+        BlogPost.create({title: 'interoperable count as promise 2'}, function(err) {
           assert.ifError(err);
           var query = BlogPost.count({title: 'interoperable count as promise 2'});
           var promise = query.exec();
-          promise.onResolve(function (err, count) {
+          promise.onResolve(function(err, count) {
             db.close();
             assert.ifError(err);
             assert.equal(1, count);
@@ -4020,18 +4020,18 @@ describe('Model', function () {
         });
       });
 
-      it('update()', function (done) {
+      it('update()', function(done) {
         var col = 'BlogPost' + random();
         var db = start(),
             BlogPost = db.model(col, bpSchema);
 
-        BlogPost.create({title: 'interoperable update as promise 2'}, function (err) {
+        BlogPost.create({title: 'interoperable update as promise 2'}, function(err) {
           assert.ifError(err);
           var query = BlogPost.update({title: 'interoperable update as promise 2'}, {title: 'interoperable update as promise delta 2'});
           var promise = query.exec();
-          promise.onResolve(function (err) {
+          promise.onResolve(function(err) {
             assert.ifError(err);
-            BlogPost.count({title: 'interoperable update as promise delta 2'}, function (err, count) {
+            BlogPost.count({title: 'interoperable update as promise delta 2'}, function(err, count) {
               db.close();
               assert.ifError(err);
               assert.equal(1, count);
@@ -4041,15 +4041,15 @@ describe('Model', function () {
         });
       });
 
-      it('findOne()', function (done) {
+      it('findOne()', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-        BlogPost.create({title: 'interoperable findOne as promise 2'}, function (err, created) {
+        BlogPost.create({title: 'interoperable findOne as promise 2'}, function(err, created) {
           assert.ifError(err);
           var query = BlogPost.findOne({title: 'interoperable findOne as promise 2'});
           var promise = query.exec();
-          promise.onResolve(function (err, found) {
+          promise.onResolve(function(err, found) {
             db.close();
             assert.ifError(err);
             assert.equal(found.id, created.id);
@@ -4058,18 +4058,18 @@ describe('Model', function () {
         });
       });
 
-      it('find()', function (done) {
+      it('find()', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
         BlogPost.create(
             {title: 'interoperable find as promise 2'},
             {title: 'interoperable find as promise 2'},
-            function (err, createdOne, createdTwo) {
+            function(err, createdOne, createdTwo) {
               assert.ifError(err);
               var query = BlogPost.find({title: 'interoperable find as promise 2'}).sort('_id');
               var promise = query.exec();
-              promise.onResolve(function (err, found) {
+              promise.onResolve(function(err, found) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(found.length, 2);
@@ -4080,19 +4080,19 @@ describe('Model', function () {
             });
       });
 
-      it('remove()', function (done) {
+      it('remove()', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
         BlogPost.create(
             {title: 'interoperable remove as promise 2'},
-            function (err) {
+            function(err) {
               assert.ifError(err);
               var query = BlogPost.remove({title: 'interoperable remove as promise 2'});
               var promise = query.exec();
-              promise.onResolve(function (err) {
+              promise.onResolve(function(err) {
                 assert.ifError(err);
-                BlogPost.count({title: 'interoperable remove as promise 2'}, function (err, count) {
+                BlogPost.count({title: 'interoperable remove as promise 2'}, function(err, count) {
                   db.close();
                   assert.equal(count, 0);
                   done();
@@ -4101,15 +4101,15 @@ describe('Model', function () {
             });
       });
 
-      it('are compatible with op modification on the fly', function (done) {
+      it('are compatible with op modification on the fly', function(done) {
         var db = start(),
             BlogPost = db.model('BlogPost' + random(), bpSchema);
 
-        BlogPost.create({title: 'interoperable ad-hoc as promise 2'}, function (err, created) {
+        BlogPost.create({title: 'interoperable ad-hoc as promise 2'}, function(err, created) {
           assert.ifError(err);
           var query = BlogPost.count({title: 'interoperable ad-hoc as promise 2'});
           var promise = query.exec('findOne');
-          promise.onResolve(function (err, found) {
+          promise.onResolve(function(err, found) {
             db.close();
             assert.ifError(err);
             assert.equal(found._id.id, created._id.id);
@@ -4118,7 +4118,7 @@ describe('Model', function () {
         });
       });
 
-      it('are thenable', function (done) {
+      it('are thenable', function(done) {
         var db = start(),
             B = db.model('BlogPost' + random(), bpSchema);
 
@@ -4128,29 +4128,29 @@ describe('Model', function () {
             {title: 'then promise 1'},
             {title: 'then promise 2'},
             {title: 'then promise 3'},
-            function (err, d1, d2, d3) {
+            function(err, d1, d2, d3) {
               assert.ifError(err);
 
               P.create(
                   {name: 'brandon', likes: [d1]},
                   {name: 'ben', likes: [d2]},
                   {name: 'bernie', likes: [d3]},
-                  function (err) {
+                  function(err) {
                     assert.ifError(err);
 
                     var promise = B.find({title: /^then promise/}).select('_id').exec();
-                    promise.then(function (blogs) {
-                      var ids = blogs.map(function (m) {
+                    promise.then(function(blogs) {
+                      var ids = blogs.map(function(m) {
                         return m._id;
                       });
                       return P.where('likes').in(ids).exec();
-                    }).then(function (people) {
+                    }).then(function(people) {
                       assert.equal(3, people.length);
                       return people;
-                    }).then(function () {
+                    }).then(function() {
                       db.close();
                       done();
-                    }, function (err) {
+                    }, function(err) {
                       db.close();
                       done(new Error(err));
                     });
@@ -4160,8 +4160,8 @@ describe('Model', function () {
     });
   });
 
-  describe('console.log', function () {
-    it('hides private props', function (done) {
+  describe('console.log', function() {
+    it('hides private props', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
@@ -4195,8 +4195,8 @@ describe('Model', function () {
     });
   });
 
-  describe('pathnames', function () {
-    it('named path can be used', function (done) {
+  describe('pathnames', function() {
+    it('named path can be used', function(done) {
       var db = start(),
           P = db.model('pathnametest', new Schema({path: String}));
       db.close();
@@ -4213,25 +4213,25 @@ describe('Model', function () {
     });
   });
 
-  describe('auto_reconnect', function () {
-    describe('if disabled', function () {
-      describe('with mongo down', function () {
-        it('and no command buffering should pass an error', function (done) {
+  describe('auto_reconnect', function() {
+    describe('if disabled', function() {
+      describe('with mongo down', function() {
+        it('and no command buffering should pass an error', function(done) {
           var db = start({db: {bufferMaxEntries: 0}});
           var schema = new Schema({type: String}, {bufferCommands: false});
           var T = db.model('Thing', schema);
-          db.on('open', function () {
+          db.on('open', function() {
             var t = new T({type: 'monster'});
             var worked = false;
 
-            t.save(function (err) {
+            t.save(function(err) {
               assert.ok(/(operation|destroyed)/.test(err.message));
               worked = true;
             });
 
             db.db.close();
 
-            setTimeout(function () {
+            setTimeout(function() {
               assert.ok(worked);
               done();
             }, 100);
@@ -4241,7 +4241,7 @@ describe('Model', function () {
     });
   });
 
-  it('subdocuments with changed values should persist the values', function (done) {
+  it('subdocuments with changed values should persist the values', function(done) {
     var db = start();
     var Subdoc = new Schema({name: String, mixed: Schema.Types.Mixed});
     var T = db.model('SubDocMixed', new Schema({subs: [Subdoc]}));
@@ -4251,10 +4251,10 @@ describe('Model', function () {
     assert.equal(t.subs[0].mixed.w, 1);
     assert.equal(t.subs[0].mixed.x, 2);
 
-    t.save(function (err) {
+    t.save(function(err) {
       assert.ifError(err);
 
-      T.findById(t._id, function (err, t) {
+      T.findById(t._id, function(err, t) {
         assert.ifError(err);
         assert.equal(t.subs[0].name, 'Hubot');
         assert.equal(t.subs[0].mixed.w, 1);
@@ -4266,10 +4266,10 @@ describe('Model', function () {
         assert.ok(sub.isModified('name'));
         assert.ok(t.isModified());
 
-        t.save(function (err) {
+        t.save(function(err) {
           assert.ifError(err);
 
-          T.findById(t._id, function (err, t) {
+          T.findById(t._id, function(err, t) {
             assert.ifError(err);
             assert.strictEqual(t.subs[0].name, 'Hubot1');
 
@@ -4282,10 +4282,10 @@ describe('Model', function () {
             assert.ok(sub.isModified());
             assert.ok(t.isModified());
 
-            t.save(function (err) {
+            t.save(function(err) {
               assert.ifError(err);
 
-              T.findById(t._id, function (err, t) {
+              T.findById(t._id, function(err, t) {
                 db.close();
                 assert.ifError(err);
                 assert.strictEqual(t.subs[0].mixed.w, 5);
@@ -4298,17 +4298,17 @@ describe('Model', function () {
     });
   });
 
-  describe('RegExps', function () {
-    it('can be saved', function (done) {
+  describe('RegExps', function() {
+    it('can be saved', function(done) {
       var db = start(),
           BlogPost = db.model('BlogPost', collection);
 
       var post = new BlogPost({mixed: {rgx: /^asdf$/}});
       assert.ok(post.mixed.rgx instanceof RegExp);
       assert.equal(post.mixed.rgx.source, '^asdf$');
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
-        BlogPost.findById(post._id, function (err, post) {
+        BlogPost.findById(post._id, function(err, post) {
           db.close();
           assert.ifError(err);
           assert.ok(post.mixed.rgx instanceof RegExp);
@@ -4320,20 +4320,20 @@ describe('Model', function () {
   });
 
   // Demonstration showing why GH-261 is a misunderstanding
-  it('a single instantiated document should be able to update its embedded documents more than once', function (done) {
+  it('a single instantiated document should be able to update its embedded documents more than once', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPost', collection);
 
     var post = new BlogPost();
     post.comments.push({title: 'one'});
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
       assert.equal(post.comments[0].title, 'one');
       post.comments[0].title = 'two';
       assert.equal(post.comments[0].title, 'two');
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
-        BlogPost.findById(post._id, function (err, found) {
+        BlogPost.findById(post._id, function(err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(found.comments[0].title, 'two');
@@ -4343,19 +4343,19 @@ describe('Model', function () {
     });
   });
 
-  describe('save()', function () {
-    describe('when no callback is passed', function () {
-      it('should emit error on its Model when there are listeners', function (done) {
+  describe('save()', function() {
+    describe('when no callback is passed', function() {
+      it('should emit error on its Model when there are listeners', function(done) {
         var db = start();
 
         var DefaultErrSchema = new Schema({});
-        DefaultErrSchema.pre('save', function (next) {
+        DefaultErrSchema.pre('save', function(next) {
           next(new Error);
         });
 
         var DefaultErr = db.model('DefaultErr3', DefaultErrSchema, 'default_err_' + random());
 
-        DefaultErr.on('error', function (err) {
+        DefaultErr.on('error', function(err) {
           db.close();
           assert.ok(err instanceof Error);
           done();
@@ -4365,16 +4365,16 @@ describe('Model', function () {
       });
     });
 
-    it('returns number of affected docs', function (done) {
+    it('returns number of affected docs', function(done) {
       var db = start();
       var schema = new Schema({name: String});
       var S = db.model('AffectedDocsAreReturned', schema);
       var s = new S({name: 'aaron'});
-      s.save(function (err, doc, affected) {
+      s.save(function(err, doc, affected) {
         assert.ifError(err);
         assert.equal(1, affected);
         s.name = 'heckmanananananana';
-        s.save(function (err, doc, affected) {
+        s.save(function(err, doc, affected) {
           db.close();
           assert.ifError(err);
           assert.equal(1, affected);
@@ -4383,18 +4383,18 @@ describe('Model', function () {
       });
     });
 
-    it('returns 0 as the number of affected docs if doc was not modified', function (done) {
+    it('returns 0 as the number of affected docs if doc was not modified', function(done) {
       var db = start(),
           schema = new Schema({name: String}),
           Model = db.model('AffectedDocsAreReturned', schema),
           doc = new Model({name: 'aaron'});
 
-      doc.save(function (err, doc, affected) {
+      doc.save(function(err, doc, affected) {
         assert.ifError(err);
         assert.equal(1, affected);
 
-        Model.findById(doc.id).then(function (doc) {
-          doc.save(function (err, doc, affected) {
+        Model.findById(doc.id).then(function(doc) {
+          doc.save(function(err, doc, affected) {
             db.close();
             assert.ifError(err);
             assert.equal(0, affected);
@@ -4404,23 +4404,23 @@ describe('Model', function () {
       });
     });
 
-    it('saved changes made within callback of a previous no-op save gh-1139', function (done) {
+    it('saved changes made within callback of a previous no-op save gh-1139', function(done) {
       var db = start(),
           B = db.model('BlogPost', collection);
 
       var post = new B({title: 'first'});
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
         // no op
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
 
           post.title = 'changed';
-          post.save(function (err) {
+          post.save(function(err) {
             assert.ifError(err);
 
-            B.findById(post, function (err, doc) {
+            B.findById(post, function(err, doc) {
               assert.ifError(err);
               assert.equal('changed', doc.title);
               db.close(done);
@@ -4430,12 +4430,12 @@ describe('Model', function () {
       });
     });
 
-    it('rejects new documents that have no _id set (1595)', function (done) {
+    it('rejects new documents that have no _id set (1595)', function(done) {
       var db = start();
       var s = new Schema({_id: {type: String}});
       var B = db.model('1595', s);
       var b = new B;
-      b.save(function (err) {
+      b.save(function(err) {
         db.close();
         assert.ok(err);
         assert.ok(/must have an _id/.test(err));
@@ -4445,14 +4445,14 @@ describe('Model', function () {
   });
 
 
-  describe('_delta()', function () {
-    it('should overwrite arrays when directly set (gh-1126)', function (done) {
+  describe('_delta()', function() {
+    it('should overwrite arrays when directly set (gh-1126)', function(done) {
       var db = start(),
           B = db.model('BlogPost', collection);
 
-      B.create({title: 'gh-1126', numbers: [1, 2]}, function (err, b) {
+      B.create({title: 'gh-1126', numbers: [1, 2]}, function(err, b) {
         assert.ifError(err);
-        B.findById(b._id, function (err, b) {
+        B.findById(b._id, function(err, b) {
           assert.ifError(err);
           assert.deepEqual([1, 2].join(), b.numbers.join());
 
@@ -4465,10 +4465,10 @@ describe('Model', function () {
           assert.equal(d.$set.numbers.length, 1);
           assert.equal(d.$set.numbers[0], 3);
 
-          b.save(function (err) {
+          b.save(function(err) {
             assert.ifError(err);
 
-            B.findById(b._id, function (err, b) {
+            B.findById(b._id, function(err, b) {
               assert.ifError(err);
               assert.ok(Array.isArray(b.numbers));
               assert.equal(1, b.numbers.length);
@@ -4480,9 +4480,9 @@ describe('Model', function () {
 
               b.numbers = [4];
               b.numbers.push(5);
-              b.save(function (err) {
+              b.save(function(err) {
                 assert.ifError(err);
-                B.findById(b._id, function (err, b) {
+                B.findById(b._id, function(err, b) {
                   assert.ifError(err);
                   assert.ok(Array.isArray(b.numbers));
                   assert.equal(2, b.numbers.length);
@@ -4497,15 +4497,15 @@ describe('Model', function () {
       });
     });
 
-    it('should use $set when subdoc changed before pulling (gh-1303)', function (done) {
+    it('should use $set when subdoc changed before pulling (gh-1303)', function(done) {
       var db = start(),
           B = db.model('BlogPost', 'gh-1303-' + random());
 
       B.create(
           {title: 'gh-1303', comments: [{body: 'a'}, {body: 'b'}, {body: 'c'}]},
-          function (err, b) {
+          function(err, b) {
             assert.ifError(err);
-            B.findById(b._id, function (err, b) {
+            B.findById(b._id, function(err, b) {
               assert.ifError(err);
 
               b.comments[2].body = 'changed';
@@ -4520,10 +4520,10 @@ describe('Model', function () {
               assert.ok(Array.isArray(d.$set.comments));
               assert.equal(d.$set.comments.length, 2);
 
-              b.save(function (err) {
+              b.save(function(err) {
                 assert.ifError(err);
 
-                B.findById(b._id, function (err, b) {
+                B.findById(b._id, function(err, b) {
                   db.close();
                   assert.ifError(err);
                   assert.ok(Array.isArray(b.comments));
@@ -4538,13 +4538,13 @@ describe('Model', function () {
     });
   });
 
-  describe('backward compatibility', function () {
-    it('with conflicted data in db', function (done) {
+  describe('backward compatibility', function() {
+    it('with conflicted data in db', function(done) {
       var db = start();
       var M = db.model('backwardDataConflict', new Schema({namey: {first: String, last: String}}));
       var m = new M({namey: '[object Object]'});
       m.namey = {first: 'GI', last: 'Joe'};// <-- should overwrite the string
-      m.save(function (err) {
+      m.save(function(err) {
         db.close();
         assert.strictEqual(err, null);
         assert.strictEqual('GI', m.namey.first);
@@ -4553,11 +4553,11 @@ describe('Model', function () {
       });
     });
 
-    it('with positional notation on path not existing in schema (gh-1048)', function (done) {
+    it('with positional notation on path not existing in schema (gh-1048)', function(done) {
       var db = start();
 
       var M = db.model('backwardCompat-gh-1048', Schema({name: 'string'}));
-      db.on('open', function () {
+      db.on('open', function() {
         var o = {
           name: 'gh-1048',
           _id: new mongoose.Types.ObjectId,
@@ -4567,9 +4567,9 @@ describe('Model', function () {
           }
         };
 
-        M.collection.insert(o, {safe: true}, function (err) {
+        M.collection.insert(o, {safe: true}, function(err) {
           assert.ifError(err);
-          M.findById(o._id, function (err, doc) {
+          M.findById(o._id, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.ok(doc);
@@ -4584,16 +4584,16 @@ describe('Model', function () {
     });
   });
 
-  describe('non-schema adhoc property assignments', function () {
-    it('are not saved', function (done) {
+  describe('non-schema adhoc property assignments', function() {
+    it('are not saved', function(done) {
       var db = start(),
           B = db.model('BlogPost', collection);
 
       var b = new B;
       b.whateveriwant = 10;
-      b.save(function (err) {
+      b.save(function(err) {
         assert.ifError(err);
-        B.collection.findOne({_id: b._id}, function (err, doc) {
+        B.collection.findOne({_id: b._id}, function(err, doc) {
           db.close();
           assert.ifError(err);
           assert.ok(!('whateveriwant' in doc));
@@ -4603,19 +4603,19 @@ describe('Model', function () {
     });
   });
 
-  it('should not throw range error when using Number _id and saving existing doc (gh-691)', function (done) {
+  it('should not throw range error when using Number _id and saving existing doc (gh-691)', function(done) {
     var db = start();
     var T = new Schema({_id: Number, a: String});
     var D = db.model('Testing691', T, 'asdf' + random());
     var d = new D({_id: 1});
-    d.save(function (err) {
+    d.save(function(err) {
       assert.ifError(err);
 
-      D.findById(d._id, function (err, d) {
+      D.findById(d._id, function(err, d) {
         assert.ifError(err);
 
         d.a = 'yo';
-        d.save(function (err) {
+        d.save(function(err) {
           db.close();
           assert.ifError(err);
           done();
@@ -4624,8 +4624,8 @@ describe('Model', function () {
     });
   });
 
-  describe('setting an unset value', function () {
-    it('is saved (gh-742)', function (done) {
+  describe('setting an unset value', function() {
+    it('is saved (gh-742)', function(done) {
       var db = start();
 
       var DefaultTestObject = db.model('defaultTestObject',
@@ -4636,22 +4636,22 @@ describe('Model', function () {
 
       var myTest = new DefaultTestObject();
 
-      myTest.save(function (err, doc) {
+      myTest.save(function(err, doc) {
         assert.ifError(err);
         assert.equal(doc.score, 55);
 
-        DefaultTestObject.findById(doc._id, function (err, doc) {
+        DefaultTestObject.findById(doc._id, function(err, doc) {
           assert.ifError(err);
 
           doc.score = undefined; // unset
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
 
-            DefaultTestObject.findById(doc._id, function (err, doc) {
+            DefaultTestObject.findById(doc._id, function(err, doc) {
               assert.ifError(err);
 
               doc.score = 55;
-              doc.save(function (err, doc, count) {
+              doc.save(function(err, doc, count) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(doc.score, 55);
@@ -4665,13 +4665,13 @@ describe('Model', function () {
     });
   });
 
-  it('path is cast to correct value when retreived from db', function (done) {
+  it('path is cast to correct value when retreived from db', function(done) {
     var db = start();
     var schema = new Schema({title: {type: 'string', index: true}});
     var T = db.model('T', schema);
-    T.collection.insert({title: 234}, {safe: true}, function (err) {
+    T.collection.insert({title: 234}, {safe: true}, function(err) {
       assert.ifError(err);
-      T.findOne(function (err, doc) {
+      T.findOne(function(err, doc) {
         db.close();
         assert.ifError(err);
         assert.equal('234', doc.title);
@@ -4680,7 +4680,7 @@ describe('Model', function () {
     });
   });
 
-  it('setting a path to undefined should retain the value as undefined', function (done) {
+  it('setting a path to undefined should retain the value as undefined', function(done) {
     var db = start(),
         B = db.model('BlogPost', collection + random());
 
@@ -4699,9 +4699,9 @@ describe('Model', function () {
     doc.comments = [{title: 'thanksgiving', body: 'yuuuumm'}];
     doc.comments.push({title: 'turkey', body: 'cranberries'});
 
-    doc.save(function (err) {
+    doc.save(function(err) {
       assert.ifError(err);
-      B.findById(doc._id, function (err, b) {
+      B.findById(doc._id, function(err, b) {
         assert.ifError(err);
         assert.equal(b.title, 'css3');
         assert.equal(b.author, 'aaron');
@@ -4718,9 +4718,9 @@ describe('Model', function () {
         b.meta.visitors = null;
         b.comments[0].title = null;
         b.comments[0].body = undefined;
-        b.save(function (err) {
+        b.save(function(err) {
           assert.ifError(err);
-          B.findById(b._id, function (err, b) {
+          B.findById(b._id, function(err, b) {
             assert.ifError(err);
             assert.strictEqual(undefined, b.title);
             assert.strictEqual(null, b.author);
@@ -4734,9 +4734,9 @@ describe('Model', function () {
 
             b.meta = undefined;
             b.comments = undefined;
-            b.save(function (err) {
+            b.save(function(err) {
               assert.ifError(err);
-              B.collection.findOne({_id: b._id}, function (err, b) {
+              B.collection.findOne({_id: b._id}, function(err, b) {
                 db.close();
                 assert.ifError(err);
                 assert.strictEqual(undefined, b.meta);
@@ -4750,13 +4750,13 @@ describe('Model', function () {
     });
   });
 
-  describe('unsetting a default value', function () {
-    it('should be ignored (gh-758)', function (done) {
+  describe('unsetting a default value', function() {
+    it('should be ignored (gh-758)', function(done) {
       var db = start();
       var M = db.model('758', new Schema({s: String, n: Number, a: Array}));
-      M.collection.insert({}, {safe: true}, function (err) {
+      M.collection.insert({}, {safe: true}, function(err) {
         assert.ifError(err);
-        M.findOne(function (err, m) {
+        M.findOne(function(err, m) {
           assert.ifError(err);
           m.s = m.n = m.a = undefined;
           assert.equal(undefined, m.$__delta());
@@ -4766,7 +4766,7 @@ describe('Model', function () {
     });
   });
 
-  it('allow for object passing to ref paths (gh-1606)', function (done) {
+  it('allow for object passing to ref paths (gh-1606)', function(done) {
     var db = start();
     var schA = new Schema({title: String});
     var schma = new Schema({
@@ -4794,7 +4794,7 @@ describe('Model', function () {
     db.close(done);
   });
 
-  it('setters trigger on null values (gh-1445)', function (done) {
+  it('setters trigger on null values (gh-1445)', function(done) {
     var db = start();
     db.close();
 
@@ -4802,7 +4802,7 @@ describe('Model', function () {
       total: {
         type: Number,
         default: 0,
-        set: function (value) {
+        set: function(value) {
           assert.strictEqual(null, value);
           return 10;
         }
@@ -4815,8 +4815,8 @@ describe('Model', function () {
     done();
   });
 
-  describe('Skip setting default value for Geospatial-indexed fields (gh-1668)', function () {
-    it('2dsphere indexed field with value is saved', function (done) {
+  describe('Skip setting default value for Geospatial-indexed fields (gh-1668)', function() {
+    it('2dsphere indexed field with value is saved', function(done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -4833,10 +4833,10 @@ describe('Model', function () {
         loc: loc
       });
 
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function (err, personDoc) {
+        Person.findById(p._id, function(err, personDoc) {
           assert.ifError(err);
 
           assert.equal(personDoc.loc[0], loc[0]);
@@ -4847,7 +4847,7 @@ describe('Model', function () {
       });
     });
 
-    it('2dsphere indexed field without value is saved (gh-1668)', function (done) {
+    it('2dsphere indexed field without value is saved (gh-1668)', function(done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -4862,10 +4862,10 @@ describe('Model', function () {
         name: 'Jimmy Page'
       });
 
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function (err, personDoc) {
+        Person.findById(p._id, function(err, personDoc) {
           assert.ifError(err);
 
           assert.equal(personDoc.name, 'Jimmy Page');
@@ -4876,7 +4876,7 @@ describe('Model', function () {
       });
     });
 
-    it('2dsphere indexed field in subdoc without value is saved', function (done) {
+    it('2dsphere indexed field in subdoc without value is saved', function(done) {
       var db = start();
       var PersonSchema = new Schema({
         name: {type: String, required: true},
@@ -4897,10 +4897,10 @@ describe('Model', function () {
 
       p.nested.tag = 'guitarist';
 
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function (err, personDoc) {
+        Person.findById(p._id, function(err, personDoc) {
           assert.ifError(err);
 
           assert.equal(personDoc.name, 'Jimmy Page');
@@ -4912,7 +4912,7 @@ describe('Model', function () {
       });
     });
 
-    it('Doc with 2dsphere indexed field without initial value can be updated', function (done) {
+    it('Doc with 2dsphere indexed field without initial value can be updated', function(done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -4927,7 +4927,7 @@ describe('Model', function () {
         name: 'Jimmy Page'
       });
 
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
         var updates = {
@@ -4936,7 +4936,7 @@ describe('Model', function () {
           }
         };
 
-        Person.findByIdAndUpdate(p._id, updates, {'new': true}, function (err, personDoc) {
+        Person.findByIdAndUpdate(p._id, updates, {'new': true}, function(err, personDoc) {
           assert.ifError(err);
 
           assert.equal(personDoc.loc[0], updates.$set.loc[0]);
@@ -4947,7 +4947,7 @@ describe('Model', function () {
       });
     });
 
-    it('2dsphere indexed required field without value is rejected', function (done) {
+    it('2dsphere indexed required field without value is rejected', function(done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -4963,7 +4963,7 @@ describe('Model', function () {
         name: 'Jimmy Page'
       });
 
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ok(err instanceof MongooseError);
         assert.ok(err instanceof ValidationError);
         db.close();
@@ -4971,7 +4971,7 @@ describe('Model', function () {
       });
     });
 
-    it('2dsphere field without value but with schema default is saved', function (done) {
+    it('2dsphere field without value but with schema default is saved', function(done) {
       var db = start();
       var loc = [0, 1];
       var PersonSchema = new Schema({
@@ -4988,10 +4988,10 @@ describe('Model', function () {
         name: 'Jimmy Page'
       });
 
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function (err, personDoc) {
+        Person.findById(p._id, function(err, personDoc) {
           assert.ifError(err);
 
           assert.equal(loc[0], personDoc.loc[0]);
@@ -5002,7 +5002,7 @@ describe('Model', function () {
       });
     });
 
-    it('2d indexed field without value is saved', function (done) {
+    it('2d indexed field without value is saved', function(done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -5017,10 +5017,10 @@ describe('Model', function () {
         name: 'Jimmy Page'
       });
 
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function (err, personDoc) {
+        Person.findById(p._id, function(err, personDoc) {
           assert.ifError(err);
 
           assert.equal(undefined, personDoc.loc);
@@ -5030,7 +5030,7 @@ describe('Model', function () {
       });
     });
 
-    it('Compound index with 2dsphere field without value is saved', function (done) {
+    it('Compound index with 2dsphere field without value is saved', function(done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -5050,10 +5050,10 @@ describe('Model', function () {
         tags: ['guitarist']
       });
 
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function (err, personDoc) {
+        Person.findById(p._id, function(err, personDoc) {
           assert.ifError(err);
 
           assert.equal('Jimmy Page', personDoc.name);
@@ -5065,7 +5065,7 @@ describe('Model', function () {
     });
 
 
-    it('Compound index on field earlier declared with 2dsphere index is saved', function (done) {
+    it('Compound index on field earlier declared with 2dsphere index is saved', function(done) {
       var db = start();
       var PersonSchema = new Schema({
         name: String,
@@ -5086,10 +5086,10 @@ describe('Model', function () {
         tags: ['guitarist']
       });
 
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
-        Person.findById(p._id, function (err, personDoc) {
+        Person.findById(p._id, function(err, personDoc) {
           assert.ifError(err);
 
           assert.equal('Jimmy Page', personDoc.name);
@@ -5101,8 +5101,8 @@ describe('Model', function () {
     });
   });
 
-  describe('gh-1920', function () {
-    it('doesnt crash', function (done) {
+  describe('gh-1920', function() {
+    it('doesnt crash', function(done) {
       var db = start();
 
       var parentSchema = new Schema({
@@ -5115,10 +5115,10 @@ describe('Model', function () {
 
       var parent = new Parent();
       parent.children.push({name: 'child name'});
-      parent.save(function (err, it) {
+      parent.save(function(err, it) {
         assert.ifError(err);
         parent.children.push({name: 'another child'});
-        Parent.findByIdAndUpdate(it._id, {$set: {children: parent.children}}, function (err) {
+        Parent.findByIdAndUpdate(it._id, {$set: {children: parent.children}}, function(err) {
           assert.ifError(err);
           db.close(done);
         });
@@ -5126,8 +5126,8 @@ describe('Model', function () {
     });
   });
 
-  describe('save failure', function () {
-    it('doesnt reset "modified" status for fields', function (done) {
+  describe('save failure', function() {
+    it('doesnt reset "modified" status for fields', function(done) {
       var db = start();
 
       var UniqueSchema = new Schema({
@@ -5150,17 +5150,17 @@ describe('Model', function () {
         unique: 6
       });
 
-      Unique.on('index', function () {
-        u1.save(function (err) {
+      Unique.on('index', function() {
+        u1.save(function(err) {
           assert.ifError(err);
           assert.ok(!u1.isModified('changer'));
-          u2.save(function (err) {
+          u2.save(function(err) {
             assert.ifError(err);
             assert.ok(!u2.isModified('changer'));
             u2.changer = 'b';
             u2.unique = 5;
             assert.ok(u2.isModified('changer'));
-            u2.save(function (err) {
+            u2.save(function(err) {
               assert.ok(err);
               assert.ok(u2.isModified('changer'));
               db.close(done);
@@ -5171,16 +5171,16 @@ describe('Model', function () {
     });
   });
 
-  it('insertMany() (gh-723)', function (done) {
+  it('insertMany() (gh-723)', function(done) {
     var db = start();
     var schema = new Schema({name: String});
     var Movie = db.model('gh723', schema);
 
     var arr = [{name: 'Star Wars'}, {name: 'The Empire Strikes Back'}];
-    Movie.insertMany(arr, function (error, docs) {
+    Movie.insertMany(arr, function(error, docs) {
       assert.ifError(error);
       assert.equal(docs.length, 2);
-      Movie.find({}, function (error, docs) {
+      Movie.find({}, function(error, docs) {
         assert.ifError(error);
         assert.equal(docs.length, 2);
         done();
@@ -5188,8 +5188,8 @@ describe('Model', function () {
     });
   });
 
-  describe('gh-2442', function () {
-    it('marks array as modified when initializing non-array from db', function (done) {
+  describe('gh-2442', function() {
+    it('marks array as modified when initializing non-array from db', function(done) {
       var db = start();
 
       var s1 = new Schema({
@@ -5212,16 +5212,16 @@ describe('Model', function () {
       var M1 = db.model('gh-2442-1', s1, 'gh-2442');
       var M2 = db.model('gh-2442-2', s2, 'gh-2442');
 
-      M1.create({array: {}}, function (err, doc) {
+      M1.create({array: {}}, function(err, doc) {
         assert.ifError(err);
         assert.ok(doc.array);
-        M2.findOne({_id: doc._id}, function (err, doc) {
+        M2.findOne({_id: doc._id}, function(err, doc) {
           assert.ifError(err);
           assert.equal(doc.array[0].value, 0);
           doc.array[0].value = 1;
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
-            M2.findOne({_id: doc._id}, function (err, doc) {
+            M2.findOne({_id: doc._id}, function(err, doc) {
               assert.ifError(err);
               assert.ok(!doc.isModified('array'));
               assert.deepEqual(doc.array[0].value, 1);
diff --git a/test/model.update.test.js b/test/model.update.test.js
index 949f9a4b06b..7b3f154df33 100644
--- a/test/model.update.test.js
+++ b/test/model.update.test.js
@@ -40,20 +40,20 @@ var BlogPost = new Schema({
 }, {strict: false});
 
 BlogPost.virtual('titleWithAuthor')
-.get(function () {
+.get(function() {
   return this.get('title') + ' by ' + this.get('author');
 })
-.set(function (val) {
+.set(function(val) {
   var split = val.split(' by ');
   this.set('title', split[0]);
   this.set('author', split[1]);
 });
 
-BlogPost.method('cool', function () {
+BlogPost.method('cool', function() {
   return this;
 });
 
-BlogPost.static('woot', function () {
+BlogPost.static('woot', function() {
   return this;
 });
 
@@ -62,13 +62,13 @@ mongoose.model('BlogPostForUpdates', BlogPost);
 var collection = 'blogposts_' + random();
 
 var strictSchema = new Schema({name: String, x: {nested: String}});
-strictSchema.virtual('foo').get(function () {
+strictSchema.virtual('foo').get(function() {
   return 'i am a virtual FOO!';
 });
 mongoose.model('UpdateStrictSchema', strictSchema);
 
 
-describe('model: update:', function () {
+describe('model: update:', function() {
   var post,
       title = 'Tobi ' + random(),
       author = 'Brian ' + random(),
@@ -76,7 +76,7 @@ describe('model: update:', function () {
       id0,
       id1;
 
-  before(function (done) {
+  before(function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -94,17 +94,17 @@ describe('model: update:', function () {
     post.owners = [id0, id1];
     post.comments = [{body: 'been there'}, {body: 'done that'}];
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
       db.close(done);
     });
   });
 
-  it('works', function (done) {
+  it('works', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    BlogPost.findById(post._id, function (err, cf) {
+    BlogPost.findById(post._id, function(err, cf) {
       assert.ifError(err);
       assert.equal(title, cf.title);
       assert.equal(cf.author, author);
@@ -135,10 +135,10 @@ describe('model: update:', function () {
         'comments.1.body': 8 // $set
       };
 
-      BlogPost.update({title: title}, update, function (err) {
+      BlogPost.update({title: title}, update, function(err) {
         assert.ifError(err);
 
-        BlogPost.findById(post._id, function (err, up) {
+        BlogPost.findById(post._id, function(err, up) {
           assert.ifError(err);
           assert.equal(up.title, newTitle);
           assert.equal(up.author, author);
@@ -161,17 +161,17 @@ describe('model: update:', function () {
             'comments.body': 'fail'
           };
 
-          BlogPost.update({_id: post._id}, update2, function (err) {
+          BlogPost.update({_id: post._id}, update2, function(err) {
             assert.ok(err);
             assert.ok(err.message.length > 0);
-            BlogPost.findById(post, function (err) {
+            BlogPost.findById(post, function(err) {
               assert.ifError(err);
 
               var update3 = {
                 $pull: 'fail'
               };
 
-              BlogPost.update({_id: post._id}, update3, function (err) {
+              BlogPost.update({_id: post._id}, update3, function(err) {
                 assert.ok(err);
 
                 assert.ok(/Invalid atomic update value for \$pull\. Expected an object, received string/.test(err.message));
@@ -181,10 +181,10 @@ describe('model: update:', function () {
                 };
 
                 // should not overwrite doc when no valid paths are submitted
-                BlogPost.update({_id: post._id}, update4, function (err) {
+                BlogPost.update({_id: post._id}, update4, function(err) {
                   assert.ifError(err);
 
-                  BlogPost.findById(post._id, function (err, up) {
+                  BlogPost.findById(post._id, function(err, up) {
                     assert.ifError(err);
 
                     assert.equal(up.title, newTitle);
@@ -213,7 +213,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('casts doc arrays', function (done) {
+  it('casts doc arrays', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -223,11 +223,11 @@ describe('model: update:', function () {
       $inc: {idontexist: 1}
     };
 
-    BlogPost.update({_id: post._id}, update, function (err) {
+    BlogPost.update({_id: post._id}, update, function(err) {
       assert.ifError(err);
 
       // get the underlying doc
-      BlogPost.collection.findOne({_id: post._id}, function (err, doc) {
+      BlogPost.collection.findOne({_id: post._id}, function(err, doc) {
         assert.ifError(err);
 
         var up = new BlogPost;
@@ -248,7 +248,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $pushAll array of docs', function (done) {
+  it('handles $pushAll array of docs', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -256,9 +256,9 @@ describe('model: update:', function () {
       $pushAll: {comments: [{body: 'i am number 2'}, {body: 'i am number 3'}]}
     };
 
-    BlogPost.update({_id: post._id}, update, function (err) {
+    BlogPost.update({_id: post._id}, update, function(err) {
       assert.ifError(err);
-      BlogPost.findById(post, function (err, ret) {
+      BlogPost.findById(post, function(err, ret) {
         assert.ifError(err);
         assert.equal(3, ret.comments.length);
         assert.equal(ret.comments[1].body, 'i am number 2');
@@ -272,7 +272,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $pull of object literal array of docs (gh-542)', function (done) {
+  it('handles $pull of object literal array of docs (gh-542)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -280,9 +280,9 @@ describe('model: update:', function () {
       $pull: {comments: {body: 'i am number 2'}}
     };
 
-    BlogPost.update({_id: post._id}, update, function (err) {
+    BlogPost.update({_id: post._id}, update, function(err) {
       assert.ifError(err);
-      BlogPost.findById(post, function (err, ret) {
+      BlogPost.findById(post, function(err, ret) {
         assert.ifError(err);
         assert.equal(2, ret.comments.length);
         assert.equal(ret.comments[0].body, 'worked great');
@@ -294,27 +294,27 @@ describe('model: update:', function () {
     });
   });
 
-  it('makes copy of conditions and update options', function (done) {
+  it('makes copy of conditions and update options', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
     var conditions = {'_id': post._id.toString()};
     var update = {'$set': {'some_attrib': post._id.toString()}};
-    BlogPost.update(conditions, update, function (err) {
+    BlogPost.update(conditions, update, function(err) {
       assert.ifError(err);
       assert.equal('string', typeof conditions._id);
       db.close(done);
     });
   });
 
-  it('handles weird casting (gh-479)', function (done) {
+  it('handles weird casting (gh-479)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
     function a() {
     }
 
-    a.prototype.toString = function () {
+    a.prototype.toString = function() {
       return 'MongoDB++';
     };
     var crazy = new a;
@@ -324,9 +324,9 @@ describe('model: update:', function () {
       $set: {'comments.$.title': crazy}
     };
 
-    BlogPost.update({_id: post._id, 'comments.body': 'worked great'}, update, function (err) {
+    BlogPost.update({_id: post._id, 'comments.body': 'worked great'}, update, function(err) {
       assert.ifError(err);
-      BlogPost.findById(post, function (err, ret) {
+      BlogPost.findById(post, function(err, ret) {
         assert.ifError(err);
         assert.equal(2, ret.comments.length);
         assert.equal(ret.comments[0].body, 'worked great');
@@ -345,7 +345,7 @@ describe('model: update:', function () {
   });
 
   var last;
-  it('handles date casting (gh-479)', function (done) {
+  it('handles date casting (gh-479)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -354,9 +354,9 @@ describe('model: update:', function () {
       $set: {date: (new Date).getTime()} // check for single val casting
     };
 
-    BlogPost.update({_id: post._id, 'comments.body': 'worked great'}, update, function (err) {
+    BlogPost.update({_id: post._id, 'comments.body': 'worked great'}, update, function(err) {
       assert.ifError(err);
-      BlogPost.findById(post, function (err, ret) {
+      BlogPost.findById(post, function(err, ret) {
         assert.ifError(err);
         assert.equal(1, ret._doc.comments[0]._doc.newprop);
         assert.strictEqual(undefined, ret._doc.comments[1]._doc.newprop);
@@ -369,7 +369,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $addToSet (gh-545)', function (done) {
+  it('handles $addToSet (gh-545)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -379,9 +379,9 @@ describe('model: update:', function () {
       $addToSet: {'owners': owner}
     };
 
-    BlogPost.update({_id: post._id}, update, function (err) {
+    BlogPost.update({_id: post._id}, update, function(err) {
       assert.ifError(err);
-      BlogPost.findById(post, function (err, ret) {
+      BlogPost.findById(post, function(err, ret) {
         assert.ifError(err);
         assert.equal(1, ret.owners.length);
         assert.equal(ret.owners[0].toString(), owner.toString());
@@ -392,7 +392,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $addToSet with $each (gh-545)', function (done) {
+  it('handles $addToSet with $each (gh-545)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -403,9 +403,9 @@ describe('model: update:', function () {
       $addToSet: {'owners': {$each: [owner, newowner]}}
     };
 
-    BlogPost.update({_id: post._id}, update, function (err) {
+    BlogPost.update({_id: post._id}, update, function(err) {
       assert.ifError(err);
-      BlogPost.findById(post, function (err, ret) {
+      BlogPost.findById(post, function(err, ret) {
         assert.ifError(err);
         assert.equal(2, ret.owners.length);
         assert.equal(ret.owners[0].toString(), owner.toString());
@@ -417,7 +417,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $pop and $unset (gh-574)', function (done) {
+  it('handles $pop and $unset (gh-574)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -427,9 +427,9 @@ describe('model: update:', function () {
     };
 
 
-    BlogPost.update({_id: post._id}, update, function (err) {
+    BlogPost.update({_id: post._id}, update, function(err) {
       assert.ifError(err);
-      BlogPost.findById(post, function (err, ret) {
+      BlogPost.findById(post, function(err, ret) {
         assert.ifError(err);
         assert.equal(1, ret.owners.length);
         assert.equal(ret.owners[0].toString(), last.toString());
@@ -439,7 +439,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('works with nested positional notation', function (done) {
+  it('works with nested positional notation', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
@@ -450,9 +450,9 @@ describe('model: update:', function () {
       }
     };
 
-    BlogPost.update({_id: post._id}, update, function (err) {
+    BlogPost.update({_id: post._id}, update, function(err) {
       assert.ifError(err);
-      BlogPost.findById(post, function (err, ret) {
+      BlogPost.findById(post, function(err, ret) {
         assert.ifError(err);
         assert.equal(2, ret.comments.length, 2);
         assert.equal(ret.comments[0].body, 'worked great');
@@ -464,20 +464,20 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $pull with obj literal (gh-542)', function (done) {
+  it('handles $pull with obj literal (gh-542)', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    BlogPost.findById(post, function (err, last) {
+    BlogPost.findById(post, function(err, last) {
       assert.ifError(err);
 
       var update = {
         $pull: {comments: {_id: last.comments[0].id}}
       };
 
-      BlogPost.update({_id: post._id}, update, function (err) {
+      BlogPost.update({_id: post._id}, update, function(err) {
         assert.ifError(err);
-        BlogPost.findById(post, function (err, ret) {
+        BlogPost.findById(post, function(err, ret) {
           assert.ifError(err);
           assert.equal(1, ret.comments.length);
           assert.equal(ret.comments[0].body, '9000');
@@ -487,19 +487,19 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $pull of obj literal and nested $in', function (done) {
+  it('handles $pull of obj literal and nested $in', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    BlogPost.findById(post, function (err, last) {
+    BlogPost.findById(post, function(err, last) {
       assert.ifError(err);
       var update = {
         $pull: {comments: {body: {$in: [last.comments[0].body]}}}
       };
 
-      BlogPost.update({_id: post._id}, update, function (err) {
+      BlogPost.update({_id: post._id}, update, function(err) {
         assert.ifError(err);
-        BlogPost.findById(post, function (err, ret) {
+        BlogPost.findById(post, function(err, ret) {
           assert.ifError(err);
           assert.equal(0, ret.comments.length);
 
@@ -510,17 +510,17 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $pull and nested $nin', function (done) {
+  it('handles $pull and nested $nin', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection);
 
-    BlogPost.findById(post, function (err, last) {
+    BlogPost.findById(post, function(err, last) {
       assert.ifError(err);
 
       last.comments.push({body: 'hi'}, {body: 'there'});
-      last.save(function (err) {
+      last.save(function(err) {
         assert.ifError(err);
-        BlogPost.findById(post, function (err, ret) {
+        BlogPost.findById(post, function(err, ret) {
           assert.ifError(err);
           assert.equal(2, ret.comments.length);
 
@@ -528,9 +528,9 @@ describe('model: update:', function () {
             $pull: {comments: {body: {$nin: ['there']}}}
           };
 
-          BlogPost.update({_id: ret._id}, update, function (err) {
+          BlogPost.update({_id: ret._id}, update, function(err) {
             assert.ifError(err);
-            BlogPost.findById(post, function (err, ret) {
+            BlogPost.findById(post, function(err, ret) {
               assert.ifError(err);
               assert.equal(1, ret.comments.length);
               db.close(done);
@@ -541,7 +541,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('updates numbers atomically', function (done) {
+  it('updates numbers atomically', function(done) {
     var db = start(),
         BlogPost = db.model('BlogPostForUpdates', collection),
         totalDocs = 4;
@@ -550,7 +550,7 @@ describe('model: update:', function () {
     post.set('meta.visitors', 5);
 
     function complete() {
-      BlogPost.findOne({_id: post.get('_id')}, function (err, doc) {
+      BlogPost.findOne({_id: post.get('_id')}, function(err, doc) {
         db.close();
         assert.ifError(err);
         assert.equal(9, doc.get('meta.visitors'));
@@ -558,11 +558,11 @@ describe('model: update:', function () {
       });
     }
 
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
       for (var i = 0; i < 4; ++i) {
         BlogPost
-        .update({_id: post._id}, {$inc: {'meta.visitors': 1}}, function (err) {
+        .update({_id: post._id}, {$inc: {'meta.visitors': 1}}, function(err) {
           assert.ifError(err);
           --totalDocs || complete();
         });
@@ -570,8 +570,8 @@ describe('model: update:', function () {
     });
   });
 
-  describe('honors strict schemas', function () {
-    it('(gh-699)', function (done) {
+  describe('honors strict schemas', function() {
+    it('(gh-699)', function(done) {
       var db = start();
       var S = db.model('UpdateStrictSchema');
 
@@ -582,28 +582,28 @@ describe('model: update:', function () {
       db.close(done);
     });
 
-    it('works', function (done) {
+    it('works', function(done) {
       var db = start();
       var S = db.model('UpdateStrictSchema');
       var s = new S({name: 'orange crush'});
 
-      s.save(function (err) {
+      s.save(function(err) {
         assert.ifError(err);
 
-        S.update({_id: s._id}, {ignore: true}, function (err, affected) {
+        S.update({_id: s._id}, {ignore: true}, function(err, affected) {
           assert.ifError(err);
           assert.equal(0, affected.n);
 
-          S.findById(s._id, function (err, doc) {
+          S.findById(s._id, function(err, doc) {
             assert.ifError(err);
             assert.ok(!doc.ignore);
             assert.ok(!doc._doc.ignore);
 
-            S.update({_id: s._id}, {name: 'Drukqs', foo: 'fooey'}, function (err, affected) {
+            S.update({_id: s._id}, {name: 'Drukqs', foo: 'fooey'}, function(err, affected) {
               assert.ifError(err);
               assert.equal(1, affected.n);
 
-              S.findById(s._id, function (err, doc) {
+              S.findById(s._id, function(err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.ok(!doc._doc.foo);
@@ -616,13 +616,13 @@ describe('model: update:', function () {
     });
   });
 
-  it('passes number of affected docs', function (done) {
+  it('passes number of affected docs', function(done) {
     var db = start(),
         B = db.model('BlogPostForUpdates', 'wwwwowowo' + random());
 
-    B.create({title: 'one'}, {title: 'two'}, {title: 'three'}, function (err) {
+    B.create({title: 'one'}, {title: 'two'}, {title: 'three'}, function(err) {
       assert.ifError(err);
-      B.update({}, {title: 'newtitle'}, {multi: true}, function (err, affected) {
+      B.update({}, {title: 'newtitle'}, {multi: true}, function(err, affected) {
         db.close();
         assert.ifError(err);
         assert.equal(3, affected.n);
@@ -631,17 +631,17 @@ describe('model: update:', function () {
     });
   });
 
-  it('updates a number to null (gh-640)', function (done) {
+  it('updates a number to null (gh-640)', function(done) {
     var db = start();
     var B = db.model('BlogPostForUpdates', 'wwwwowowo' + random());
     var b = new B({meta: {visitors: null}});
-    b.save(function (err) {
+    b.save(function(err) {
       assert.ifError(err);
-      B.findById(b, function (err, b) {
+      B.findById(b, function(err, b) {
         assert.ifError(err);
         assert.strictEqual(b.meta.visitors, null);
 
-        B.update({_id: b._id}, {meta: {visitors: null}}, function (err) {
+        B.update({_id: b._id}, {meta: {visitors: null}}, function(err) {
           db.close();
           assert.strictEqual(null, err);
           done();
@@ -650,13 +650,13 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $pull from Mixed arrays (gh-735)', function (done) {
+  it('handles $pull from Mixed arrays (gh-735)', function(done) {
     var db = start();
     var schema = new Schema({comments: []});
     var M = db.model('gh-735', schema, 'gh-735_' + random());
-    M.create({comments: [{name: 'node 0.8'}]}, function (err, doc) {
+    M.create({comments: [{name: 'node 0.8'}]}, function(err, doc) {
       assert.ifError(err);
-      M.update({_id: doc._id}, {$pull: {comments: {name: 'node 0.8'}}}, function (err, affected) {
+      M.update({_id: doc._id}, {$pull: {comments: {name: 'node 0.8'}}}, function(err, affected) {
         assert.ifError(err);
         assert.equal(1, affected.n);
         db.close();
@@ -665,7 +665,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles $push with $ positionals (gh-1057)', function (done) {
+  it('handles $push with $ positionals (gh-1057)', function(done) {
     var db = start();
 
     var taskSchema = new Schema({
@@ -684,16 +684,16 @@ describe('model: update:', function () {
 
     var Project = db.model('1057-project', projectSchema, '1057-' + random());
 
-    Project.create({name: 'my project'}, function (err, project) {
+    Project.create({name: 'my project'}, function(err, project) {
       assert.ifError(err);
       var pid = project.id;
       var comp = project.components.create({name: 'component'});
-      Project.update({_id: pid}, {$push: {components: comp}}, function (err) {
+      Project.update({_id: pid}, {$push: {components: comp}}, function(err) {
         assert.ifError(err);
         var task = comp.tasks.create({name: 'my task'});
-        Project.update({_id: pid, 'components._id': comp._id}, {$push: {'components.$.tasks': task}}, function (err) {
+        Project.update({_id: pid, 'components._id': comp._id}, {$push: {'components.$.tasks': task}}, function(err) {
           assert.ifError(err);
-          Project.findById(pid, function (err, proj) {
+          Project.findById(pid, function(err, proj) {
             assert.ifError(err);
             assert.ok(proj);
             assert.equal(1, proj.components.length);
@@ -709,15 +709,15 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles nested paths starting with numbers (gh-1062)', function (done) {
+  it('handles nested paths starting with numbers (gh-1062)', function(done) {
     var db = start();
     var schema = new Schema({counts: Schema.Types.Mixed});
     var M = db.model('gh-1062', schema, '1062-' + random());
-    M.create({counts: {}}, function (err, m) {
+    M.create({counts: {}}, function(err, m) {
       assert.ifError(err);
-      M.update({}, {$inc: {'counts.1': 1, 'counts.1a': 10}}, function (err) {
+      M.update({}, {$inc: {'counts.1': 1, 'counts.1a': 10}}, function(err) {
         assert.ifError(err);
-        M.findById(m, function (err, doc) {
+        M.findById(m, function(err, doc) {
           assert.ifError(err);
           assert.equal(1, doc.counts['1']);
           assert.equal(10, doc.counts['1a']);
@@ -727,19 +727,19 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles positional operators with referenced docs (gh-1572)', function (done) {
+  it('handles positional operators with referenced docs (gh-1572)', function(done) {
     var db = start();
 
     var so = new Schema({title: String, obj: [String]});
     var Some = db.model('Some' + random(), so);
 
-    Some.create({obj: ['a', 'b', 'c']}, function (err, s) {
+    Some.create({obj: ['a', 'b', 'c']}, function(err, s) {
       assert.ifError(err);
 
-      Some.update({_id: s._id, obj: 'b'}, {$set: {'obj.$': 2}}, function (err) {
+      Some.update({_id: s._id, obj: 'b'}, {$set: {'obj.$': 2}}, function(err) {
         assert.ifError(err);
 
-        Some.findById(s._id, function (err, ss) {
+        Some.findById(s._id, function(err, ss) {
           assert.ifError(err);
 
           assert.strictEqual(ss.obj[1], '2');
@@ -749,25 +749,25 @@ describe('model: update:', function () {
     });
   });
 
-  it('use .where for update condition (gh-2170)', function (done) {
+  it('use .where for update condition (gh-2170)', function(done) {
     var db = start();
     var so = new Schema({num: Number});
     var Some = db.model('gh-2170' + random(), so);
 
-    Some.create([{num: 1}, {num: 1}], function (err, docs) {
+    Some.create([{num: 1}, {num: 1}], function(err, docs) {
       assert.ifError(err);
       assert.equal(docs.length, 2);
       var doc0 = docs[0];
       var doc1 = docs[1];
       var sId0 = doc0._id;
       var sId1 = doc1._id;
-      Some.where({_id: sId0}).update({}, {$set: {num: '99'}}, {multi: true}, function (err, cnt) {
+      Some.where({_id: sId0}).update({}, {$set: {num: '99'}}, {multi: true}, function(err, cnt) {
         assert.ifError(err);
         assert.equal(1, cnt.n);
-        Some.findById(sId0, function (err, doc0_1) {
+        Some.findById(sId0, function(err, doc0_1) {
           assert.ifError(err);
           assert.equal(99, doc0_1.num);
-          Some.findById(sId1, function (err, doc1_1) {
+          Some.findById(sId1, function(err, doc1_1) {
             assert.ifError(err);
             assert.equal(1, doc1_1.num);
             db.close(done);
@@ -777,18 +777,18 @@ describe('model: update:', function () {
     });
   });
 
-  describe('mongodb 2.4 features', function () {
+  describe('mongodb 2.4 features', function() {
     var mongo24_or_greater = false;
 
-    before(function (done) {
-      start.mongodVersion(function (err, version) {
+    before(function(done) {
+      start.mongodVersion(function(err, version) {
         assert.ifError(err);
         mongo24_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 4);
         done();
       });
     });
 
-    it('$setOnInsert operator', function (done) {
+    it('$setOnInsert operator', function(done) {
       if (!mongo24_or_greater) {
         console.log('not testing mongodb 2.4 $setOnInsert feature');
         return done();
@@ -800,19 +800,19 @@ describe('model: update:', function () {
 
       var match = {name: 'set on insert'};
       var op = {$setOnInsert: {age: '47'}, x: 'inserted'};
-      M.update(match, op, {upsert: true}, function (err) {
+      M.update(match, op, {upsert: true}, function(err) {
         assert.ifError(err);
-        M.findOne(function (err, doc) {
+        M.findOne(function(err, doc) {
           assert.ifError(err);
           assert.equal(47, doc.age);
           assert.equal('set on insert', doc.name);
 
           var match = {name: 'set on insert'};
           var op = {$setOnInsert: {age: 108}, name: 'changed'};
-          M.update(match, op, {upsert: true}, function (err) {
+          M.update(match, op, {upsert: true}, function(err) {
             assert.ifError(err);
 
-            M.findOne(function (err, doc) {
+            M.findOne(function(err, doc) {
               assert.equal(47, doc.age);
               assert.equal('changed', doc.name);
               db.close(done);
@@ -822,7 +822,7 @@ describe('model: update:', function () {
       });
     });
 
-    it('push with $slice', function (done) {
+    it('push with $slice', function(done) {
       if (!mongo24_or_greater) {
         console.log('not testing mongodb 2.4 $push with $slice feature');
         return done();
@@ -832,7 +832,7 @@ describe('model: update:', function () {
       var schema = new Schema({name: String, n: [{x: Number}]});
       var M = db.model('setoninsert-' + random(), schema);
 
-      M.create({name: '2.4'}, function (err, created) {
+      M.create({name: '2.4'}, function(err, created) {
         assert.ifError(err);
 
         var op = {
@@ -845,9 +845,9 @@ describe('model: update:', function () {
           }
         };
 
-        M.update({_id: created._id}, op, function (err) {
+        M.update({_id: created._id}, op, function(err) {
           assert.ifError(err);
-          M.findById(created._id, function (err, doc) {
+          M.findById(created._id, function(err, doc) {
             assert.ifError(err);
             assert.equal(created.id, doc.id);
             assert.equal(1, doc.n.length);
@@ -861,9 +861,9 @@ describe('model: update:', function () {
                 }
               }
             };
-            M.update({_id: created._id}, op, function (err) {
+            M.update({_id: created._id}, op, function(err) {
               assert.ifError(err);
-              M.findById(created._id, function (error, doc) {
+              M.findById(created._id, function(error, doc) {
                 assert.ifError(error);
                 assert.equal(doc.n.length, 0);
                 db.close(done);
@@ -875,18 +875,18 @@ describe('model: update:', function () {
     });
   });
 
-  describe('mongodb 2.6 features', function () {
+  describe('mongodb 2.6 features', function() {
     var mongo26_or_greater = false;
 
-    before(function (done) {
-      start.mongodVersion(function (err, version) {
+    before(function(done) {
+      start.mongodVersion(function(err, version) {
         assert.ifError(err);
         mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6);
         done();
       });
     });
 
-    it('supports $position', function (done) {
+    it('supports $position', function(done) {
       if (!mongo26_or_greater) {
         return done();
       }
@@ -896,15 +896,15 @@ describe('model: update:', function () {
       var M = db.model('setoninsert-' + random(), schema);
 
       var m = new M({name: '2.6', n: [{x: 0}]});
-      m.save(function (error, m) {
+      m.save(function(error, m) {
         assert.ifError(error);
         assert.equal(1, m.n.length);
         M.update(
             {name: '2.6'},
             {$push: {n: {$each: [{x: 2}, {x: 1}], $position: 0}}},
-            function (error) {
+            function(error) {
               assert.ifError(error);
-              M.findOne({name: '2.6'}, function (error, m) {
+              M.findOne({name: '2.6'}, function(error, m) {
                 assert.ifError(error);
                 assert.equal(3, m.n.length);
                 assert.equal(2, m.n[0].x);
@@ -916,7 +916,7 @@ describe('model: update:', function () {
       });
     });
 
-    it('supports $currentDate', function (done) {
+    it('supports $currentDate', function(done) {
       if (!mongo26_or_greater) {
         return done();
       }
@@ -926,15 +926,15 @@ describe('model: update:', function () {
       var M = db.model('gh-2019', schema);
 
       var m = new M({name: '2.6'});
-      m.save(function (error) {
+      m.save(function(error) {
         assert.ifError(error);
         var before = Date.now();
         M.update(
             {name: '2.6'},
             {$currentDate: {lastModified: true, lastModifiedTS: {$type: 'timestamp'}}},
-            function (error) {
+            function(error) {
               assert.ifError(error);
-              M.findOne({name: '2.6'}, function (error, m) {
+              M.findOne({name: '2.6'}, function(error, m) {
                 var after = Date.now();
                 assert.ifError(error);
                 assert.ok(m.lastModified.getTime() >= before);
@@ -946,18 +946,18 @@ describe('model: update:', function () {
     });
   });
 
-  describe('{overwrite: true}', function () {
-    it('overwrite works', function (done) {
+  describe('{overwrite: true}', function() {
+    it('overwrite works', function(done) {
       var db = start();
       var schema = new Schema({mixed: {}});
       var M = db.model('updatesmixed-' + random(), schema);
 
-      M.create({mixed: 'something'}, function (err, created) {
+      M.create({mixed: 'something'}, function(err, created) {
         assert.ifError(err);
 
-        M.update({_id: created._id}, {mixed: {}}, {overwrite: true}, function (err) {
+        M.update({_id: created._id}, {mixed: {}}, {overwrite: true}, function(err) {
           assert.ifError(err);
-          M.findById(created._id, function (err, doc) {
+          M.findById(created._id, function(err, doc) {
             assert.ifError(err);
             assert.equal(created.id, doc.id);
             assert.equal(typeof doc.mixed, 'object');
@@ -968,18 +968,18 @@ describe('model: update:', function () {
       });
     });
 
-    it('overwrites all properties', function (done) {
+    it('overwrites all properties', function(done) {
       var db = start();
       var sch = new Schema({title: String, subdoc: {name: String, num: Number}});
 
       var M = db.model('updateover' + random(), sch);
 
-      M.create({subdoc: {name: 'that', num: 1}}, function (err, doc) {
+      M.create({subdoc: {name: 'that', num: 1}}, function(err, doc) {
         assert.ifError(err);
 
-        M.update({_id: doc.id}, {title: 'something!'}, {overwrite: true}, function (err) {
+        M.update({_id: doc.id}, {title: 'something!'}, {overwrite: true}, function(err) {
           assert.ifError(err);
-          M.findById(doc.id, function (err, doc) {
+          M.findById(doc.id, function(err, doc) {
             assert.ifError(err);
             assert.equal(doc.title, 'something!');
             assert.equal(doc.subdoc.name, undefined);
@@ -990,18 +990,18 @@ describe('model: update:', function () {
       });
     });
 
-    it('allows users to blow it up', function (done) {
+    it('allows users to blow it up', function(done) {
       var db = start();
       var sch = new Schema({title: String, subdoc: {name: String, num: Number}});
 
       var M = db.model('updateover' + random(), sch);
 
-      M.create({subdoc: {name: 'that', num: 1, title: 'hello'}}, function (err, doc) {
+      M.create({subdoc: {name: 'that', num: 1, title: 'hello'}}, function(err, doc) {
         assert.ifError(err);
 
-        M.update({_id: doc.id}, {}, {overwrite: true}, function (err) {
+        M.update({_id: doc.id}, {}, {overwrite: true}, function(err) {
           assert.ifError(err);
-          M.findById(doc.id, function (err, doc) {
+          M.findById(doc.id, function(err, doc) {
             assert.ifError(err);
             assert.equal(doc.title, undefined);
             assert.equal(doc.subdoc.name, undefined);
@@ -1013,22 +1013,22 @@ describe('model: update:', function () {
     });
   });
 
-  it('casts empty arrays', function (done) {
+  it('casts empty arrays', function(done) {
     var db = start();
 
     var so = new Schema({arr: []});
     var Some = db.model('1838-' + random(), so);
 
-    Some.create({arr: ['a']}, function (err, s) {
+    Some.create({arr: ['a']}, function(err, s) {
       if (err) {
         return done(err);
       }
 
-      Some.update({_id: s._id}, {arr: []}, function (err) {
+      Some.update({_id: s._id}, {arr: []}, function(err) {
         if (err) {
           return done(err);
         }
-        Some.findById(s._id, function (err, doc) {
+        Some.findById(s._id, function(err, doc) {
           if (err) {
             return done(err);
           }
@@ -1040,16 +1040,16 @@ describe('model: update:', function () {
     });
   });
 
-  describe('defaults and validators (gh-860)', function () {
-    it('applies defaults on upsert', function (done) {
+  describe('defaults and validators (gh-860)', function() {
+    it('applies defaults on upsert', function(done) {
       var db = start();
 
       var s = new Schema({topping: {type: String, default: 'bacon'}, base: String});
       var Breakfast = db.model('gh-860-0', s);
       var updateOptions = {upsert: true, setDefaultsOnInsert: true};
-      Breakfast.update({}, {base: 'eggs'}, updateOptions, function (error) {
+      Breakfast.update({}, {base: 'eggs'}, updateOptions, function(error) {
         assert.ifError(error);
-        Breakfast.findOne({}).lean().exec(function (error, breakfast) {
+        Breakfast.findOne({}).lean().exec(function(error, breakfast) {
           assert.ifError(error);
           assert.equal('eggs', breakfast.base);
           assert.equal('bacon', breakfast.topping);
@@ -1058,16 +1058,16 @@ describe('model: update:', function () {
       });
     });
 
-    it('doesnt set default on upsert if query sets it', function (done) {
+    it('doesnt set default on upsert if query sets it', function(done) {
       var db = start();
 
       var s = new Schema({topping: {type: String, default: 'bacon'}, base: String});
       var Breakfast = db.model('gh-860-1', s);
 
       var updateOptions = {upsert: true, setDefaultsOnInsert: true};
-      Breakfast.update({topping: 'sausage'}, {base: 'eggs'}, updateOptions, function (error) {
+      Breakfast.update({topping: 'sausage'}, {base: 'eggs'}, updateOptions, function(error) {
         assert.ifError(error);
-        Breakfast.findOne({}, function (error, breakfast) {
+        Breakfast.findOne({}, function(error, breakfast) {
           assert.ifError(error);
           assert.equal('eggs', breakfast.base);
           assert.equal('sausage', breakfast.topping);
@@ -1077,16 +1077,16 @@ describe('model: update:', function () {
       });
     });
 
-    it('properly sets default on upsert if query wont set it', function (done) {
+    it('properly sets default on upsert if query wont set it', function(done) {
       var db = start();
 
       var s = new Schema({topping: {type: String, default: 'bacon'}, base: String});
       var Breakfast = db.model('gh-860-2', s);
 
       var updateOptions = {upsert: true, setDefaultsOnInsert: true};
-      Breakfast.update({topping: {$ne: 'sausage'}}, {base: 'eggs'}, updateOptions, function (error) {
+      Breakfast.update({topping: {$ne: 'sausage'}}, {base: 'eggs'}, updateOptions, function(error) {
         assert.ifError(error);
-        Breakfast.findOne({}, function (error, breakfast) {
+        Breakfast.findOne({}, function(error, breakfast) {
           assert.ifError(error);
           assert.equal('eggs', breakfast.base);
           assert.equal('bacon', breakfast.topping);
@@ -1096,19 +1096,19 @@ describe('model: update:', function () {
       });
     });
 
-    it('runs validators if theyre set', function (done) {
+    it('runs validators if theyre set', function(done) {
       var db = start();
 
       var s = new Schema({
         topping: {
           type: String,
-          validate: function () {
+          validate: function() {
             return false;
           }
         },
         base: {
           type: String,
-          validate: function () {
+          validate: function() {
             return true;
           }
         }
@@ -1116,13 +1116,13 @@ describe('model: update:', function () {
       var Breakfast = db.model('gh-860-3', s);
 
       var updateOptions = {upsert: true, setDefaultsOnInsert: true, runValidators: true};
-      Breakfast.update({}, {topping: 'bacon', base: 'eggs'}, updateOptions, function (error) {
+      Breakfast.update({}, {topping: 'bacon', base: 'eggs'}, updateOptions, function(error) {
         assert.ok(!!error);
         assert.equal(1, Object.keys(error.errors).length);
         assert.equal('topping', Object.keys(error.errors)[0]);
         assert.equal('Validator failed for path `topping` with value `bacon`', error.errors.topping.message);
 
-        Breakfast.findOne({}, function (error, breakfast) {
+        Breakfast.findOne({}, function(error, breakfast) {
           assert.ifError(error);
           assert.ok(!breakfast);
           db.close();
@@ -1131,14 +1131,14 @@ describe('model: update:', function () {
       });
     });
 
-    it('validators handle $unset and $setOnInsert', function (done) {
+    it('validators handle $unset and $setOnInsert', function(done) {
       var db = start();
 
       var s = new Schema({
         steak: {type: String, required: true},
         eggs: {
           type: String,
-          validate: function () {
+          validate: function() {
             assert.ok(this instanceof require('../').Query);
             return false;
           }
@@ -1147,7 +1147,7 @@ describe('model: update:', function () {
       var Breakfast = db.model('gh-860-4', s);
 
       var updateOptions = {runValidators: true, context: 'query'};
-      Breakfast.update({}, {$unset: {steak: ''}, $setOnInsert: {eggs: 'softboiled'}}, updateOptions, function (error) {
+      Breakfast.update({}, {$unset: {steak: ''}, $setOnInsert: {eggs: 'softboiled'}}, updateOptions, function(error) {
         assert.ok(!!error);
         assert.equal(2, Object.keys(error.errors).length);
         assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1);
@@ -1159,7 +1159,7 @@ describe('model: update:', function () {
       });
     });
 
-    it('min/max, enum, and regex built-in validators work', function (done) {
+    it('min/max, enum, and regex built-in validators work', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1170,19 +1170,19 @@ describe('model: update:', function () {
       var Breakfast = db.model('gh-860-5', s);
 
       var updateOptions = {runValidators: true};
-      Breakfast.update({}, {$set: {steak: 'ribeye', eggs: 3, bacon: '3 strips'}}, updateOptions, function (error) {
+      Breakfast.update({}, {$set: {steak: 'ribeye', eggs: 3, bacon: '3 strips'}}, updateOptions, function(error) {
         assert.ok(!!error);
         assert.equal(1, Object.keys(error.errors).length);
         assert.equal('eggs', Object.keys(error.errors)[0]);
         assert.equal('Path `eggs` (3) is less than minimum allowed value (4).', error.errors.eggs.message);
 
-        Breakfast.update({}, {$set: {steak: 'tofu', eggs: 5, bacon: '3 strips'}}, updateOptions, function (error) {
+        Breakfast.update({}, {$set: {steak: 'tofu', eggs: 5, bacon: '3 strips'}}, updateOptions, function(error) {
           assert.ok(!!error);
           assert.equal(1, Object.keys(error.errors).length);
           assert.equal('steak', Object.keys(error.errors)[0]);
           assert.equal('`tofu` is not a valid enum value for path `steak`.', error.errors.steak);
 
-          Breakfast.update({}, {$set: {steak: 'sirloin', eggs: 6, bacon: 'none'}}, updateOptions, function (error) {
+          Breakfast.update({}, {$set: {steak: 'sirloin', eggs: 6, bacon: 'none'}}, updateOptions, function(error) {
             assert.ok(!!error);
             assert.equal(1, Object.keys(error.errors).length);
             assert.equal('bacon', Object.keys(error.errors)[0]);
@@ -1195,7 +1195,7 @@ describe('model: update:', function () {
       });
     });
 
-    it('multiple validation errors', function (done) {
+    it('multiple validation errors', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1206,7 +1206,7 @@ describe('model: update:', function () {
       var Breakfast = db.model('gh-860-6', s);
 
       var updateOptions = {runValidators: true};
-      Breakfast.update({}, {$set: {steak: 'tofu', eggs: 2, bacon: '3 strips'}}, updateOptions, function (error) {
+      Breakfast.update({}, {$set: {steak: 'tofu', eggs: 2, bacon: '3 strips'}}, updateOptions, function(error) {
         assert.ok(!!error);
         assert.equal(2, Object.keys(error.errors).length);
         assert.ok(Object.keys(error.errors).indexOf('steak') !== -1);
@@ -1216,7 +1216,7 @@ describe('model: update:', function () {
       });
     });
 
-    it('validators ignore $inc', function (done) {
+    it('validators ignore $inc', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1226,14 +1226,14 @@ describe('model: update:', function () {
       var Breakfast = db.model('gh-860-7', s);
 
       var updateOptions = {runValidators: true};
-      Breakfast.update({}, {$inc: {eggs: 1}}, updateOptions, function (error) {
+      Breakfast.update({}, {$inc: {eggs: 1}}, updateOptions, function(error) {
         assert.ifError(error);
         db.close();
         done();
       });
     });
 
-    it('validators handle positional operator (gh-3167)', function (done) {
+    it('validators handle positional operator (gh-3167)', function(done) {
       var db = start();
 
       var s = new Schema({
@@ -1246,7 +1246,7 @@ describe('model: update:', function () {
           {'toppings.name': 'bacon'},
           {'toppings.$.name': 'tofu'},
           updateOptions,
-          function (error) {
+          function(error) {
             assert.ok(error);
             assert.ok(error.errors['toppings.0.name']);
             db.close(done);
@@ -1254,21 +1254,21 @@ describe('model: update:', function () {
     });
   });
 
-  it('works with $set and overwrite (gh-2515)', function (done) {
+  it('works with $set and overwrite (gh-2515)', function(done) {
     var db = start();
 
     var schema = new Schema({breakfast: String});
     var M = db.model('gh-2515', schema);
 
-    M.create({breakfast: 'bacon'}, function (error, doc) {
+    M.create({breakfast: 'bacon'}, function(error, doc) {
       assert.ifError(error);
       M.update(
           {_id: doc._id},
           {$set: {breakfast: 'eggs'}},
           {overwrite: true},
-          function (error) {
+          function(error) {
             assert.ifError(error);
-            M.findOne({_id: doc._id}, function (error, doc) {
+            M.findOne({_id: doc._id}, function(error, doc) {
               assert.ifError(error);
               assert.equal(doc.breakfast, 'eggs');
               db.close(done);
@@ -1277,22 +1277,22 @@ describe('model: update:', function () {
     });
   });
 
-  it('successfully casts set with nested mixed objects (gh-2796)', function (done) {
+  it('successfully casts set with nested mixed objects (gh-2796)', function(done) {
     var db = start();
 
     var schema = new Schema({breakfast: {}});
     var M = db.model('gh-2796', schema);
 
-    M.create({}, function (error, doc) {
+    M.create({}, function(error, doc) {
       assert.ifError(error);
       M.update(
           {_id: doc._id},
           {breakfast: {eggs: 2, bacon: 3}},
-          function (error, result) {
+          function(error, result) {
             assert.ifError(error);
             assert.ok(result.ok);
             assert.equal(result.n, 1);
-            M.findOne({_id: doc._id}, function (error, doc) {
+            M.findOne({_id: doc._id}, function(error, doc) {
               assert.ifError(error);
               assert.equal(doc.breakfast.eggs, 2);
               db.close(done);
@@ -1301,58 +1301,58 @@ describe('model: update:', function () {
     });
   });
 
-  it('handles empty update with promises (gh-2796)', function (done) {
+  it('handles empty update with promises (gh-2796)', function(done) {
     var db = start();
 
     var schema = new Schema({eggs: Number});
     var M = db.model('gh-2796', schema);
 
-    M.create({}, function (error, doc) {
+    M.create({}, function(error, doc) {
       assert.ifError(error);
       M.update(
           {_id: doc._id},
           {notInSchema: 1}).
       exec().
-      then(function (data) {
+      then(function(data) {
         assert.equal(data.ok, 0);
         assert.equal(data.n, 0);
         db.close(done);
       }).
-      onReject(function (error) {
+      onReject(function(error) {
         return done(error);
       });
     });
   });
 
-  describe('middleware', function () {
-    it('can specify pre and post hooks', function (done) {
+  describe('middleware', function() {
+    it('can specify pre and post hooks', function(done) {
       var db = start();
 
       var numPres = 0;
       var numPosts = 0;
       var band = new Schema({members: [String]});
-      band.pre('update', function (next) {
+      band.pre('update', function(next) {
         ++numPres;
         next();
       });
-      band.post('update', function () {
+      band.post('update', function() {
         ++numPosts;
       });
       var Band = db.model('gh-964', band);
 
       var gnr = new Band({members: ['Axl', 'Slash', 'Izzy', 'Duff', 'Adler']});
-      gnr.save(function (error) {
+      gnr.save(function(error) {
         assert.ifError(error);
         assert.equal(0, numPres);
         assert.equal(0, numPosts);
         Band.update(
             {_id: gnr._id},
             {$pull: {members: 'Adler'}},
-            function (error) {
+            function(error) {
               assert.ifError(error);
               assert.equal(1, numPres);
               assert.equal(1, numPosts);
-              Band.findOne({_id: gnr._id}, function (error, doc) {
+              Band.findOne({_id: gnr._id}, function(error, doc) {
                 assert.ifError(error);
                 assert.deepEqual(['Axl', 'Slash', 'Izzy', 'Duff'],
                     doc.toObject().members);
@@ -1362,53 +1362,53 @@ describe('model: update:', function () {
       });
     });
 
-    it('runs before validators (gh-2706)', function (done) {
+    it('runs before validators (gh-2706)', function(done) {
       var db = start();
 
       var bandSchema = new Schema({
         lead: {type: String, enum: ['Axl Rose']}
       });
-      bandSchema.pre('update', function () {
+      bandSchema.pre('update', function() {
         this.options.runValidators = true;
       });
       var Band = db.model('gh2706', bandSchema, 'gh2706');
 
-      Band.update({}, {$set: {lead: 'Not Axl'}}, function (err) {
+      Band.update({}, {$set: {lead: 'Not Axl'}}, function(err) {
         assert.ok(err);
         db.close(done);
       });
     });
 
-    describe('objects and arrays', function () {
+    describe('objects and arrays', function() {
       var db;
 
-      before(function () {
+      before(function() {
         db = start();
       });
 
-      after(function (done) {
+      after(function(done) {
         db.close(done);
       });
 
-      it('embedded objects (gh-2706)', function (done) {
+      it('embedded objects (gh-2706)', function(done) {
         var bandSchema = new Schema({
           singer: {
             firstName: {type: String, enum: ['Axl']},
             lastName: {type: String, enum: ['Rose']}
           }
         });
-        bandSchema.pre('update', function () {
+        bandSchema.pre('update', function() {
           this.options.runValidators = true;
         });
         var Band = db.model('gh2706', bandSchema, 'gh2706');
 
-        Band.update({}, {$set: {singer: {firstName: 'Not', lastName: 'Axl'}}}, function (err) {
+        Band.update({}, {$set: {singer: {firstName: 'Not', lastName: 'Axl'}}}, function(err) {
           assert.ok(err);
           done();
         });
       });
 
-      it('handles document array validation (gh-2733)', function (done) {
+      it('handles document array validation (gh-2733)', function(done) {
         var member = new Schema({
           name: String,
           role: {type: String, required: true, enum: ['singer', 'guitar', 'drums', 'bass']}
@@ -1422,27 +1422,27 @@ describe('model: update:', function () {
         ];
 
         Band.findOneAndUpdate(
-            {name: "Guns N' Roses"},
+            {name: 'Guns N\' Roses'},
             {$set: {members: members}},
             {runValidators: true},
-            function (err) {
+            function(err) {
               assert.ok(err);
               done();
             });
       });
 
-      it('validators on arrays (gh-3724)', function (done) {
+      it('validators on arrays (gh-3724)', function(done) {
         var schema = new Schema({
           arr: [String]
         });
 
-        schema.path('arr').validate(function () {
+        schema.path('arr').validate(function() {
           return false;
         });
 
         var M = db.model('gh3724', schema);
         var options = {runValidators: true};
-        M.findOneAndUpdate({}, {arr: ['test']}, options, function (error) {
+        M.findOneAndUpdate({}, {arr: ['test']}, options, function(error) {
           assert.ok(error);
           assert.ok(/ValidationError/.test(error.toString()));
           done();
@@ -1451,7 +1451,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('works with overwrite but no $set (gh-2568)', function (done) {
+  it('works with overwrite but no $set (gh-2568)', function(done) {
     var db = start();
 
     var chapterSchema = {
@@ -1473,9 +1473,9 @@ describe('model: update:', function () {
     };
 
     Book.update({}, jsonObject, {upsert: true, overwrite: true},
-        function (error) {
+        function(error) {
           assert.ifError(error);
-          Book.findOne({id: 0}, function (error, book) {
+          Book.findOne({id: 0}, function(error, book) {
             assert.ifError(error);
             assert.equal(book.chapters.length, 2);
             assert.ok(book.chapters[0]._id);
@@ -1485,7 +1485,7 @@ describe('model: update:', function () {
         });
   });
 
-  it('works with undefined date (gh-2833)', function (done) {
+  it('works with undefined date (gh-2833)', function(done) {
     var db = start();
 
     var dateSchema = {
@@ -1493,20 +1493,20 @@ describe('model: update:', function () {
     };
     var D = db.model('gh2833', dateSchema);
 
-    assert.doesNotThrow(function () {
-      D.update({}, {d: undefined}, function () {
+    assert.doesNotThrow(function() {
+      D.update({}, {d: undefined}, function() {
         db.close(done);
       });
     });
   });
 
-  it('does not add virtuals to update (gh-2046)', function (done) {
+  it('does not add virtuals to update (gh-2046)', function(done) {
     var db = start();
 
     var childSchema = new Schema({foo: String}, {toObject: {getters: true}});
     var parentSchema = new Schema({children: [childSchema]});
 
-    childSchema.virtual('bar').get(function () {
+    childSchema.virtual('bar').get(function() {
       return 'bar';
     });
 
@@ -1515,9 +1515,9 @@ describe('model: update:', function () {
     var update = Parent.update({}, {$push: {children: {foo: 'foo'}}}, {upsert: true});
     assert.equal(update._update.$push.children.bar, undefined);
 
-    update.exec(function (error) {
+    update.exec(function(error) {
       assert.ifError(error);
-      Parent.findOne({}, function (error, doc) {
+      Parent.findOne({}, function(error, doc) {
         assert.ifError(error);
         assert.equal(doc.children.length, 1);
         assert.ok(!doc.children[0].bar);
@@ -1526,19 +1526,19 @@ describe('model: update:', function () {
     });
   });
 
-  it('can $rename (gh-1845)', function (done) {
+  it('can $rename (gh-1845)', function(done) {
     var db = start();
 
     var schema = new Schema({foo: Date, bar: Date});
     var Model = db.model('gh1845', schema, 'gh1845');
 
-    Model.update({}, {$rename: {foo: 'bar'}}, function (error) {
+    Model.update({}, {$rename: {foo: 'bar'}}, function(error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('doesnt modify original argument doc (gh-3008)', function (done) {
+  it('doesnt modify original argument doc (gh-3008)', function(done) {
     var db = start();
     var FooSchema = new mongoose.Schema({
       key: Number,
@@ -1547,35 +1547,35 @@ describe('model: update:', function () {
     var Model = db.model('gh3008', FooSchema);
 
     var update = {$set: {values: 2, value: 2}};
-    Model.update({key: 1}, update, function () {
+    Model.update({key: 1}, update, function() {
       assert.equal(update.$set.values, 2);
       db.close(done);
     });
   });
 
-  it('can $rename (gh-1845)', function (done) {
+  it('can $rename (gh-1845)', function(done) {
     var db = start();
     var schema = new Schema({foo: Date, bar: Date});
     var Model = db.model('gh1845', schema, 'gh1845');
 
-    Model.update({}, {$rename: {foo: 'bar'}}, function (error) {
+    Model.update({}, {$rename: {foo: 'bar'}}, function(error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('allows objects with positional operator (gh-3185)', function (done) {
+  it('allows objects with positional operator (gh-3185)', function(done) {
     var db = start();
     var schema = new Schema({children: [{_id: Number}]});
     var MyModel = db.model('gh3185', schema, 'gh3185');
 
-    MyModel.create({children: [{_id: 1}]}, function (error, doc) {
+    MyModel.create({children: [{_id: 1}]}, function(error, doc) {
       assert.ifError(error);
       MyModel.findOneAndUpdate(
           {_id: doc._id, 'children._id': 1},
           {$set: {'children.$': {_id: 2}}},
           {'new': true},
-          function (error, doc) {
+          function(error, doc) {
             assert.ifError(error);
             assert.equal(doc.children[0]._id, 2);
             db.close(done);
@@ -1583,17 +1583,17 @@ describe('model: update:', function () {
     });
   });
 
-  it('mixed type casting (gh-3305)', function (done) {
+  it('mixed type casting (gh-3305)', function(done) {
     var db = start();
 
     var Schema = mongoose.Schema({}, {strict: false});
     var Model = db.model('gh3305', Schema);
 
-    Model.create({}, function (error, m) {
+    Model.create({}, function(error, m) {
       assert.ifError(error);
       Model.
       update({_id: m._id}, {'$push': {'myArr': {'key': 'Value'}}}).
-      exec(function (error, res) {
+      exec(function(error, res) {
         assert.ifError(error);
         assert.equal(res.n, 1);
         db.close(done);
@@ -1601,21 +1601,21 @@ describe('model: update:', function () {
     });
   });
 
-  it('mixed nested type casting (gh-3337)', function (done) {
+  it('mixed nested type casting (gh-3337)', function(done) {
     var db = start();
 
     var Schema = mongoose.Schema({attributes: {}}, {strict: true});
     var Model = db.model('gh3337', Schema);
 
-    Model.create({}, function (error, m) {
+    Model.create({}, function(error, m) {
       assert.ifError(error);
       var update = {'$push': {'attributes.scores.bar': {a: 1}}};
       Model.
       update({_id: m._id}, update).
-      exec(function (error, res) {
+      exec(function(error, res) {
         assert.ifError(error);
         assert.equal(res.n, 1);
-        Model.findById(m._id, function (error, doc) {
+        Model.findById(m._id, function(error, doc) {
           assert.ifError(error);
           assert.equal(doc.attributes.scores.bar.length, 1);
           db.close(done);
@@ -1624,19 +1624,19 @@ describe('model: update:', function () {
     });
   });
 
-  it('works with buffers (gh-3496)', function (done) {
+  it('works with buffers (gh-3496)', function(done) {
     var db = start();
 
     var Schema = mongoose.Schema({myBufferField: Buffer});
     var Model = db.model('gh3496', Schema);
 
-    Model.update({}, {myBufferField: new Buffer(1)}, function (error) {
+    Model.update({}, {myBufferField: new Buffer(1)}, function(error) {
       assert.ifError(error);
       db.close(done);
     });
   });
 
-  it('dontThrowCastError option (gh-3512)', function (done) {
+  it('dontThrowCastError option (gh-3512)', function(done) {
     var db = start();
 
     var Schema = mongoose.Schema({name: String});
@@ -1645,13 +1645,13 @@ describe('model: update:', function () {
     var badQuery = {_id: 'foo'};
     var update = {name: 'test'};
     var options = {dontThrowCastError: true};
-    Model.update(badQuery, update, options).then(null, function (error) {
+    Model.update(badQuery, update, options).then(null, function(error) {
       assert.ok(error);
       db.close(done);
     });
   });
 
-  it('.update(doc) (gh-3221)', function (done) {
+  it('.update(doc) (gh-3221)', function(done) {
     var db = start();
 
     var Schema = mongoose.Schema({name: String});
@@ -1666,23 +1666,23 @@ describe('model: update:', function () {
     db.close(done);
   });
 
-  it('middleware update with exec (gh-3549)', function (done) {
+  it('middleware update with exec (gh-3549)', function(done) {
     var db = start();
 
     var Schema = mongoose.Schema({name: String});
 
-    Schema.pre('update', function (next) {
+    Schema.pre('update', function(next) {
       this.update({name: 'Val'});
       next();
     });
 
     var Model = db.model('gh3549', Schema);
 
-    Model.create({}, function (error, doc) {
+    Model.create({}, function(error, doc) {
       assert.ifError(error);
-      Model.update({_id: doc._id}, {name: 'test'}).exec(function (error) {
+      Model.update({_id: doc._id}, {name: 'test'}).exec(function(error) {
         assert.ifError(error);
-        Model.findOne({_id: doc._id}, function (error, doc) {
+        Model.findOne({_id: doc._id}, function(error, doc) {
           assert.ifError(error);
           assert.equal(doc.name, 'Val');
           db.close(done);
@@ -1691,7 +1691,7 @@ describe('model: update:', function () {
     });
   });
 
-  it('casting $push with overwrite (gh-3564)', function (done) {
+  it('casting $push with overwrite (gh-3564)', function(done) {
     var db = start();
 
     var schema = mongoose.Schema({
@@ -1708,15 +1708,15 @@ describe('model: update:', function () {
 
     var M = db.model('gh-3564', schema);
 
-    M.create(doc, function (err) {
+    M.create(doc, function(err) {
       assert.ifError(err);
 
       var update = {$push: {followers: 200}};
       var opts = {overwrite: true, new: true, safe: true, upsert: false, multi: false};
 
-      M.update({topicId: doc.topicId}, update, opts, function (err) {
+      M.update({topicId: doc.topicId}, update, opts, function(err) {
         assert.ifError(err);
-        M.findOne({topicId: doc.topicId}, function (error, doc) {
+        M.findOne({topicId: doc.topicId}, function(error, doc) {
           assert.ifError(error);
           assert.equal(doc.name, 'name');
           assert.deepEqual(doc.followers.toObject(), [500, 200]);
diff --git a/test/object.create.null.test.js b/test/object.create.null.test.js
index 72c0b17b0a4..303273f8818 100644
--- a/test/object.create.null.test.js
+++ b/test/object.create.null.test.js
@@ -17,31 +17,31 @@ var schema = new Schema({
   h: {}
 });
 
-describe('is compatible with object created using Object.create(null) (gh-1484)', function () {
+describe('is compatible with object created using Object.create(null) (gh-1484)', function() {
   var db;
   var M;
 
-  before(function () {
+  before(function() {
     db = start();
     M = db.model('1484', schema);
   });
 
-  after(function (done) {
+  after(function(done) {
     db.close(done);
   });
 
-  it('during construction', function (done) {
-    assert.doesNotThrow(function () {
+  it('during construction', function(done) {
+    assert.doesNotThrow(function() {
       new M(Object.create(null));
     });
 
-    assert.doesNotThrow(function () {
+    assert.doesNotThrow(function() {
       var o = Object.create(null);
       o.b = Object.create(null);
       new M(o);
     });
 
-    assert.doesNotThrow(function () {
+    assert.doesNotThrow(function() {
       var o = Object.create(null);
 
       o.b = Object.create(null);
@@ -75,7 +75,7 @@ describe('is compatible with object created using Object.create(null) (gh-1484)'
     done();
   });
 
-  it('with .set(path, obj)', function (done) {
+  it('with .set(path, obj)', function(done) {
     var m = new M;
 
     var b = Object.create(null);
@@ -103,25 +103,25 @@ describe('is compatible with object created using Object.create(null) (gh-1484)'
     done();
   });
 
-  it('with schema', function (done) {
+  it('with schema', function(done) {
     var o = Object.create(null);
     o.name = String;
     o.created = Date;
     o.nested = Object.create(null);
     o.nested.n = Number;
 
-    assert.doesNotThrow(function () {
+    assert.doesNotThrow(function() {
       new Schema(o);
     });
 
-    assert.doesNotThrow(function () {
+    assert.doesNotThrow(function() {
       var s = new Schema;
       var o = Object.create(null);
       o.yay = Number;
       s.path('works', o);
     });
 
-    assert.doesNotThrow(function () {
+    assert.doesNotThrow(function() {
       var s = new Schema;
       var o = Object.create(null);
       o = {};
diff --git a/test/promise.test.js b/test/promise.test.js
index 665470a4e6c..61322e1abf9 100644
--- a/test/promise.test.js
+++ b/test/promise.test.js
@@ -10,12 +10,12 @@ var Promise = require('../lib/promise');
  * Test.
  */
 
-describe('Promise', function () {
-  it('events fire right after complete()', function (done) {
+describe('Promise', function() {
+  it('events fire right after complete()', function(done) {
     var promise = new Promise(),
         called = 0;
 
-    promise.on('fulfill', function (a, b) {
+    promise.on('fulfill', function(a, b) {
       assert.equal(a, '1');
       assert.equal(b, '2');
       called++;
@@ -23,7 +23,7 @@ describe('Promise', function () {
 
     promise.complete('1', '2');
 
-    promise.on('fulfill', function (a, b) {
+    promise.on('fulfill', function(a, b) {
       assert.equal(a, '1');
       assert.equal(b, '2');
       called++;
@@ -33,18 +33,18 @@ describe('Promise', function () {
     done();
   });
 
-  it('events fire right after error()', function (done) {
+  it('events fire right after error()', function(done) {
     var promise = new Promise(),
         called = 0;
 
-    promise.on('reject', function (err) {
+    promise.on('reject', function(err) {
       assert.ok(err instanceof Error);
       called++;
     });
 
     promise.error('booyah');
 
-    promise.on('reject', function (err) {
+    promise.on('reject', function(err) {
       assert.ok(err instanceof Error);
       called++;
     });
@@ -53,18 +53,18 @@ describe('Promise', function () {
     done();
   });
 
-  it('events fire right after reject()', function (done) {
+  it('events fire right after reject()', function(done) {
     var promise = new Promise(),
         called = 0;
 
-    promise.on('reject', function (err) {
+    promise.on('reject', function(err) {
       assert.equal(9, err);
       called++;
     });
 
     promise.reject(9);
 
-    promise.on('reject', function (err) {
+    promise.on('reject', function(err) {
       assert.equal(9, err);
       called++;
     });
@@ -73,11 +73,11 @@ describe('Promise', function () {
     done();
   });
 
-  describe('onResolve()', function () {
-    it('from constructor works', function (done) {
+  describe('onResolve()', function() {
+    it('from constructor works', function(done) {
       var called = 0;
 
-      var promise = new Promise(function (err) {
+      var promise = new Promise(function(err) {
         assert.ok(err instanceof Error);
         called++;
       });
@@ -88,18 +88,18 @@ describe('Promise', function () {
       done();
     });
 
-    it('after fulfill()', function (done) {
+    it('after fulfill()', function(done) {
       var promise = new Promise(),
           called = 0;
 
       promise.fulfill('woot');
 
-      promise.onResolve(function (err, data) {
+      promise.onResolve(function(err, data) {
         assert.equal(data, 'woot');
         called++;
       });
 
-      promise.onResolve(function (err) {
+      promise.onResolve(function(err) {
         assert.strictEqual(err, null);
         called++;
       });
@@ -108,18 +108,18 @@ describe('Promise', function () {
       done();
     });
 
-    it('after error()', function (done) {
+    it('after error()', function(done) {
       var promise = new Promise(),
           called = 0;
 
       promise.error(new Error('woot'));
 
-      promise.onResolve(function (err) {
+      promise.onResolve(function(err) {
         assert.ok(err instanceof Error);
         called++;
       });
 
-      promise.onResolve(function (err) {
+      promise.onResolve(function(err) {
         assert.ok(err instanceof Error);
         called++;
       });
@@ -128,12 +128,12 @@ describe('Promise', function () {
     });
   });
 
-  describe('onFulfill() shortcut', function () {
-    it('works', function (done) {
+  describe('onFulfill() shortcut', function() {
+    it('works', function(done) {
       var promise = new Promise(),
           called = 0;
 
-      promise.onFulfill(function (woot) {
+      promise.onFulfill(function(woot) {
         assert.strictEqual(woot, undefined);
         called++;
       });
@@ -145,12 +145,12 @@ describe('Promise', function () {
     });
   });
 
-  describe('onReject shortcut', function () {
-    it('works', function (done) {
+  describe('onReject shortcut', function() {
+    it('works', function(done) {
       var promise = new Promise(),
           called = 0;
 
-      promise.onReject(function (err) {
+      promise.onReject(function(err) {
         assert.ok(err instanceof Error);
         called++;
       });
@@ -161,34 +161,34 @@ describe('Promise', function () {
     });
   });
 
-  describe('return values', function () {
-    it('on()', function (done) {
+  describe('return values', function() {
+    it('on()', function(done) {
       var promise = new Promise();
-      assert.ok(promise.on('jump', function () {}) instanceof Promise);
+      assert.ok(promise.on('jump', function() {}) instanceof Promise);
       done();
     });
 
-    it('onFulfill()', function (done) {
+    it('onFulfill()', function(done) {
       var promise = new Promise();
-      assert.ok(promise.onFulfill(function () {}) instanceof Promise);
+      assert.ok(promise.onFulfill(function() {}) instanceof Promise);
       done();
     });
-    it('onReject()', function (done) {
+    it('onReject()', function(done) {
       var promise = new Promise();
-      assert.ok(promise.onReject(function () {}) instanceof Promise);
+      assert.ok(promise.onReject(function() {}) instanceof Promise);
       done();
     });
-    it('onResolve()', function (done) {
+    it('onResolve()', function(done) {
       var promise = new Promise();
-      assert.ok(promise.onResolve(function () {}) instanceof Promise);
+      assert.ok(promise.onResolve(function() {}) instanceof Promise);
       done();
     });
   });
 
-  describe('casting errors', function () {
-    describe('error()', function () {
-      it('casts arguments to Error', function (done) {
-        var p = new Promise(function (err) {
+  describe('casting errors', function() {
+    describe('error()', function() {
+      it('casts arguments to Error', function(done) {
+        var p = new Promise(function(err) {
           assert.ok(err instanceof Error);
           assert.equal('3', err.message);
           done();
@@ -198,9 +198,9 @@ describe('Promise', function () {
       });
     });
 
-    describe('reject()', function () {
-      it('does not cast arguments to Error', function (done) {
-        var p = new Promise(function (err) {
+    describe('reject()', function() {
+      it('does not cast arguments to Error', function(done) {
+        var p = new Promise(function(err) {
           assert.equal(3, err);
           done();
         });
@@ -210,9 +210,9 @@ describe('Promise', function () {
     });
   });
 
-  it('doesnt swallow exceptions (gh-3222)', function (done) {
-    assert.throws(function () {
-      new Promise.ES6(function () {
+  it('doesnt swallow exceptions (gh-3222)', function(done) {
+    assert.throws(function() {
+      new Promise.ES6(function() {
         throw new Error('bacon');
       });
     });
diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js
index 14d485388cb..903b4480bab 100644
--- a/test/promise_provider.test.js
+++ b/test/promise_provider.test.js
@@ -12,19 +12,19 @@ var Schema = require('../lib/schema');
 
 var db;
 var testSchema = new Schema({test: {type: String, required: true}});
-testSchema.pre('save', function (next) {
+testSchema.pre('save', function(next) {
   if (this.$__saveSucceeds === false) {
     return next(new Error('fail'));
   }
   next();
 });
-testSchema.pre('validate', function (next) {
+testSchema.pre('validate', function(next) {
   if (this.$__validateSucceeds === false) {
     return next(new Error('validation failed'));
   }
   next();
 });
-testSchema.pre('findOne', function (next) {
+testSchema.pre('findOne', function(next) {
   if (this.$__findOneSucceeds === false) {
     return next(new Error('findOne failed'));
   }
@@ -32,118 +32,118 @@ testSchema.pre('findOne', function (next) {
 });
 var MyModel;
 
-describe('ES6 promises: ', function () {
-  describe('native: ', function () {
+describe('ES6 promises: ', function() {
+  describe('native: ', function() {
     if (!global.Promise) {
       return;
     }
 
-    before(function () {
+    before(function() {
       PromiseProvider.set(global.Promise);
     });
 
-    before(function () {
+    before(function() {
       db = start();
       MyModel = db.model('es6promise', testSchema);
     });
 
-    after(function (done) {
+    after(function(done) {
       PromiseProvider.reset();
       db.close(done);
     });
 
-    afterEach(function (done) {
+    afterEach(function(done) {
       MyModel.remove({}, done);
     });
 
-    it('save()', function (done) {
+    it('save()', function(done) {
       var m = new MyModel({test: '123'});
       var promise = m.save();
       assert.equal(promise.constructor, global.Promise);
-      promise.then(function (doc) {
+      promise.then(function(doc) {
         assert.equal(m, doc);
         done();
       });
     });
 
-    it('save() with validation error', function (done) {
+    it('save() with validation error', function(done) {
       var m = new MyModel({});
       var promise = m.save();
       assert.equal(promise.constructor, global.Promise);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.ok(err.errors.test);
           done();
         });
     });
 
-    it('save() with middleware error', function (done) {
+    it('save() with middleware error', function(done) {
       var m = new MyModel({test: '123'});
       m.$__saveSucceeds = false;
       var promise = m.save();
       assert.equal(promise.constructor, global.Promise);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: fail');
           done();
         });
     });
 
-    it('save() with validation middleware error', function (done) {
+    it('save() with validation middleware error', function(done) {
       var m = new MyModel({test: '123'});
       m.$__validateSucceeds = false;
       var promise = m.save();
       assert.equal(promise.constructor, global.Promise);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: validation failed');
           done();
         });
     });
 
-    it('validate()', function (done) {
+    it('validate()', function(done) {
       var m = new MyModel({});
       var promise = m.validate();
       assert.equal(promise.constructor, global.Promise);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.ok(err.errors.test);
           done();
         });
     });
 
-    it('queries', function (done) {
-      MyModel.create({test: '123'}, function (error) {
+    it('queries', function(done) {
+      MyModel.create({test: '123'}, function(error) {
         assert.ifError(error);
 
         var promise = MyModel.findOne({test: '123'}).exec();
         assert.equal(promise.constructor, global.Promise);
 
-        promise.then(function (doc) {
+        promise.then(function(doc) {
           assert.equal(doc.test, '123');
           done();
         });
       });
     });
 
-    it('queries with errors', function (done) {
-      MyModel.create({test: '123'}, function (error) {
+    it('queries with errors', function(done) {
+      MyModel.create({test: '123'}, function(error) {
         assert.ifError(error);
 
         var query = MyModel.findOne({test: '123'});
@@ -152,10 +152,10 @@ describe('ES6 promises: ', function () {
         assert.equal(promise.constructor, global.Promise);
 
         promise.
-          then(function () {
+          then(function() {
             assert.ok(false);
           }).
-          catch(function (err) {
+          catch(function(err) {
             assert.ok(err);
             assert.equal(err.toString(), 'Error: findOne failed');
             done();
@@ -163,122 +163,122 @@ describe('ES6 promises: ', function () {
       });
     });
 
-    it('create', function (done) {
+    it('create', function(done) {
       var promise = MyModel.create({test: '123'});
       assert.equal(promise.constructor, global.Promise);
-      promise.then(function () {
+      promise.then(function() {
         done();
       });
     });
   });
 
-  describe('bluebird: ', function () {
-    before(function () {
+  describe('bluebird: ', function() {
+    before(function() {
       PromiseProvider.set(bluebird);
     });
 
-    before(function () {
+    before(function() {
       db = start();
       MyModel = db.model('es6promise_bluebird', testSchema);
     });
 
-    after(function (done) {
+    after(function(done) {
       PromiseProvider.reset();
       db.close(done);
     });
 
-    afterEach(function (done) {
+    afterEach(function(done) {
       MyModel.remove({}, done);
     });
 
-    it('save()', function (done) {
+    it('save()', function(done) {
       var m = new MyModel({test: '123'});
       var promise = m.save();
       assert.equal(promise.constructor, bluebird);
-      promise.then(function (doc) {
+      promise.then(function(doc) {
         assert.equal(m, doc);
         done();
       });
     });
 
-    it('save() with validation error', function (done) {
+    it('save() with validation error', function(done) {
       var m = new MyModel({});
       var promise = m.save();
       assert.equal(promise.constructor, bluebird);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.ok(err.errors.test);
           done();
         });
     });
 
-    it('save() with middleware error', function (done) {
+    it('save() with middleware error', function(done) {
       var m = new MyModel({test: '123'});
       m.$__saveSucceeds = false;
       var promise = m.save();
       assert.equal(promise.constructor, bluebird);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: fail');
           done();
         });
     });
 
-    it('save() with validation middleware error', function (done) {
+    it('save() with validation middleware error', function(done) {
       var m = new MyModel({test: '123'});
       m.$__validateSucceeds = false;
       var promise = m.save();
       assert.equal(promise.constructor, bluebird);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: validation failed');
           done();
         });
     });
 
-    it('validate()', function (done) {
+    it('validate()', function(done) {
       var m = new MyModel({});
       var promise = m.validate();
       assert.equal(promise.constructor, bluebird);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.ok(err.errors.test);
           done();
         });
     });
 
-    it('queries', function (done) {
-      MyModel.create({test: '123'}, function (error) {
+    it('queries', function(done) {
+      MyModel.create({test: '123'}, function(error) {
         assert.ifError(error);
 
         var promise = MyModel.findOne({test: '123'}).exec();
         assert.equal(promise.constructor, bluebird);
 
-        promise.then(function (doc) {
+        promise.then(function(doc) {
           assert.equal(doc.test, '123');
           done();
         });
       });
     });
 
-    it('queries with errors', function (done) {
-      MyModel.create({test: '123'}, function (error) {
+    it('queries with errors', function(done) {
+      MyModel.create({test: '123'}, function(error) {
         assert.ifError(error);
 
         var query = MyModel.findOne({test: '123'});
@@ -287,10 +287,10 @@ describe('ES6 promises: ', function () {
         assert.equal(promise.constructor, bluebird);
 
         promise.
-          then(function () {
+          then(function() {
             assert.ok(false);
           }).
-          catch(function (err) {
+          catch(function(err) {
             assert.ok(err);
             assert.equal(err.toString(), 'Error: findOne failed');
             done();
@@ -298,41 +298,41 @@ describe('ES6 promises: ', function () {
       });
     });
 
-    it('create', function (done) {
+    it('create', function(done) {
       var promise = MyModel.create({test: '123'});
       assert.equal(promise.constructor, bluebird);
-      promise.then(function () {
+      promise.then(function() {
         var p = MyModel.create({});
-        p.catch(function (error) {
+        p.catch(function(error) {
           assert.ok(error);
           done();
         });
       });
     });
 
-    it('subdocument validation (gh-3681)', function (done) {
+    it('subdocument validation (gh-3681)', function(done) {
       var subSchema = new Schema({name: {type: String, required: true}});
       var parentSchema = new Schema({sub: [subSchema]});
       var Parent = db.model('gh3681', parentSchema);
 
-      Parent.create({sub: [{}]}).catch(function () {
+      Parent.create({sub: [{}]}).catch(function() {
         done();
       });
     });
 
-    it('Model.populate (gh-3734)', function (done) {
+    it('Model.populate (gh-3734)', function(done) {
       var doc = new MyModel({});
       var promise = MyModel.populate(doc, 'test');
       assert.equal(promise.constructor, bluebird);
       done();
     });
 
-    it('subdoc pre doesnt cause unhandled rejection (gh-3669)', function (done) {
+    it('subdoc pre doesnt cause unhandled rejection (gh-3669)', function(done) {
       var nestedSchema = new Schema({
         name: {type: String, required: true}
       });
 
-      nestedSchema.pre('validate', function (next) {
+      nestedSchema.pre('validate', function(next) {
         next();
       });
 
@@ -342,120 +342,120 @@ describe('ES6 promises: ', function () {
 
       var MyModel = db.model('gh3669', schema);
 
-      MyModel.create({items: [{name: null}]}).catch(function (error) {
+      MyModel.create({items: [{name: null}]}).catch(function(error) {
         assert.ok(error);
         done();
       });
     });
   });
 
-  describe('q: ', function () {
-    before(function () {
+  describe('q: ', function() {
+    before(function() {
       PromiseProvider.set(q.Promise);
     });
 
-    before(function () {
+    before(function() {
       db = start();
       MyModel = db.model('es6promise_q', testSchema);
     });
 
-    after(function (done) {
+    after(function(done) {
       PromiseProvider.reset();
       db.close(done);
     });
 
-    afterEach(function (done) {
+    afterEach(function(done) {
       MyModel.remove({}, done);
     });
 
-    it('save()', function (done) {
+    it('save()', function(done) {
       var m = new MyModel({test: '123'});
       var promise = m.save();
       assert.ok(promise instanceof q.makePromise);
-      promise.then(function (doc) {
+      promise.then(function(doc) {
         assert.equal(m, doc);
         done();
       });
     });
 
-    it('save() with validation error', function (done) {
+    it('save() with validation error', function(done) {
       var m = new MyModel({});
       var promise = m.save();
       assert.ok(promise instanceof q.makePromise);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.ok(err.errors.test);
           done();
         });
     });
 
-    it('save() with middleware error', function (done) {
+    it('save() with middleware error', function(done) {
       var m = new MyModel({test: '123'});
       m.$__saveSucceeds = false;
       var promise = m.save();
       assert.ok(promise instanceof q.makePromise);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: fail');
           done();
         });
     });
 
-    it('save() with validation middleware error', function (done) {
+    it('save() with validation middleware error', function(done) {
       var m = new MyModel({test: '123'});
       m.$__validateSucceeds = false;
       var promise = m.save();
       assert.ok(promise instanceof q.makePromise);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.equal(err.toString(), 'Error: validation failed');
           done();
         });
     });
 
-    it('validate()', function (done) {
+    it('validate()', function(done) {
       var m = new MyModel({});
       var promise = m.validate();
       assert.ok(promise instanceof q.makePromise);
       promise.
-        then(function () {
+        then(function() {
           assert.ok(false);
         }).
-        catch(function (err) {
+        catch(function(err) {
           assert.ok(err);
           assert.ok(err.errors.test);
           done();
         });
     });
 
-    it('queries', function (done) {
-      MyModel.create({test: '123'}, function (error) {
+    it('queries', function(done) {
+      MyModel.create({test: '123'}, function(error) {
         assert.ifError(error);
 
         var promise = MyModel.findOne({test: '123'}).exec();
         assert.ok(promise instanceof q.makePromise);
 
-        promise.then(function (doc) {
+        promise.then(function(doc) {
           assert.equal(doc.test, '123');
           done();
         });
       });
     });
 
-    it('queries with errors', function (done) {
-      MyModel.create({test: '123'}, function (error) {
+    it('queries with errors', function(done) {
+      MyModel.create({test: '123'}, function(error) {
         assert.ifError(error);
 
         var query = MyModel.findOne({test: '123'});
@@ -464,10 +464,10 @@ describe('ES6 promises: ', function () {
         assert.ok(promise instanceof q.makePromise);
 
         promise.
-          then(function () {
+          then(function() {
             assert.ok(false);
           }).
-          catch(function (err) {
+          catch(function(err) {
             assert.ok(err);
             assert.equal(err.toString(), 'Error: findOne failed');
             done();
@@ -475,10 +475,10 @@ describe('ES6 promises: ', function () {
       });
     });
 
-    it('create', function (done) {
+    it('create', function(done) {
       var promise = MyModel.create({test: '123'});
       assert.ok(promise instanceof q.makePromise);
-      promise.then(function () {
+      promise.then(function() {
         done();
       });
     });
diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js
index 10e18add18f..a16373c27a0 100644
--- a/test/query.middleware.test.js
+++ b/test/query.middleware.test.js
@@ -3,27 +3,27 @@ var assert = require('assert');
 var mongoose = start.mongoose;
 var Schema = mongoose.Schema;
 
-describe('query middleware', function () {
+describe('query middleware', function() {
   var db;
   var schema;
   var publisherSchema;
   var Author;
   var Publisher;
 
-  var initializeData = function (done) {
+  var initializeData = function(done) {
     Author = db.model('gh-2138', schema, 'gh-2138');
     Publisher = db.model('gh-2138-1', publisherSchema, 'gh-2138-1');
 
-    Author.remove({}, function (error) {
+    Author.remove({}, function(error) {
       if (error) {
         return done(error);
       }
 
-      Publisher.remove({}, function (error) {
+      Publisher.remove({}, function(error) {
         if (error) {
           return done(error);
         }
-        Publisher.create({name: 'Wiley'}, function (error, publisher) {
+        Publisher.create({name: 'Wiley'}, function(error, publisher) {
           if (error) {
             return done(error);
           }
@@ -35,7 +35,7 @@ describe('query middleware', function () {
             options: 'bacon'
           };
 
-          Author.create(doc, function (error) {
+          Author.create(doc, function(error) {
             done(error);
           });
         });
@@ -43,7 +43,7 @@ describe('query middleware', function () {
     });
   };
 
-  beforeEach(function (done) {
+  beforeEach(function(done) {
     schema = new Schema({
       title: String,
       author: String,
@@ -60,22 +60,22 @@ describe('query middleware', function () {
     done();
   });
 
-  afterEach(function (done) {
+  afterEach(function(done) {
     db.close(done);
   });
 
-  it('has a pre find hook', function (done) {
+  it('has a pre find hook', function(done) {
     var count = 0;
-    schema.pre('find', function (next) {
+    schema.pre('find', function(next) {
       ++count;
       next();
     });
 
     start();
 
-    initializeData(function (error) {
+    initializeData(function(error) {
       assert.ifError(error);
-      Author.find({x: 1}, function (error) {
+      Author.find({x: 1}, function(error) {
         assert.ifError(error);
         assert.equal(1, count);
         done();
@@ -83,9 +83,9 @@ describe('query middleware', function () {
     });
   });
 
-  it('has post find hooks', function (done) {
+  it('has post find hooks', function(done) {
     var postCount = 0;
-    schema.post('find', function (results, next) {
+    schema.post('find', function(results, next) {
       assert.equal(1, results.length);
       assert.equal('Val', results[0].author);
       assert.equal('bacon', results[0].options);
@@ -93,9 +93,9 @@ describe('query middleware', function () {
       next();
     });
 
-    initializeData(function (error) {
+    initializeData(function(error) {
       assert.ifError(error);
-      Author.find({title: 'Professional AngularJS'}, function (error, docs) {
+      Author.find({title: 'Professional AngularJS'}, function(error, docs) {
         assert.ifError(error);
         assert.equal(1, postCount);
         assert.equal(1, docs.length);
@@ -104,23 +104,23 @@ describe('query middleware', function () {
     });
   });
 
-  it('works when using a chained query builder', function (done) {
+  it('works when using a chained query builder', function(done) {
     var count = 0;
-    schema.pre('find', function (next) {
+    schema.pre('find', function(next) {
       ++count;
       next();
     });
 
     var postCount = 0;
-    schema.post('find', function (results, next) {
+    schema.post('find', function(results, next) {
       assert.equal(1, results.length);
       assert.equal('Val', results[0].author);
       ++postCount;
       next();
     });
 
-    initializeData(function () {
-      Author.find({title: 'Professional AngularJS'}).exec(function (error, docs) {
+    initializeData(function() {
+      Author.find({title: 'Professional AngularJS'}).exec(function(error, docs) {
         assert.ifError(error);
         assert.equal(1, count);
         assert.equal(1, postCount);
@@ -130,22 +130,22 @@ describe('query middleware', function () {
     });
   });
 
-  it('has separate pre-findOne() and post-findOne() hooks', function (done) {
+  it('has separate pre-findOne() and post-findOne() hooks', function(done) {
     var count = 0;
-    schema.pre('findOne', function (next) {
+    schema.pre('findOne', function(next) {
       ++count;
       next();
     });
 
     var postCount = 0;
-    schema.post('findOne', function (result, next) {
+    schema.post('findOne', function(result, next) {
       assert.equal('Val', result.author);
       ++postCount;
       next();
     });
 
-    initializeData(function () {
-      Author.findOne({title: 'Professional AngularJS'}).exec(function (error, doc) {
+    initializeData(function() {
+      Author.findOne({title: 'Professional AngularJS'}).exec(function(error, doc) {
         assert.ifError(error);
         assert.equal(1, count);
         assert.equal(1, postCount);
@@ -155,14 +155,14 @@ describe('query middleware', function () {
     });
   });
 
-  it('can populate in pre hook', function (done) {
-    schema.pre('findOne', function (next) {
+  it('can populate in pre hook', function(done) {
+    schema.pre('findOne', function(next) {
       this.populate('publisher');
       next();
     });
 
-    initializeData(function () {
-      Author.findOne({title: 'Professional AngularJS'}).exec(function (error, doc) {
+    initializeData(function() {
+      Author.findOne({title: 'Professional AngularJS'}).exec(function(error, doc) {
         assert.ifError(error);
         assert.equal('Val', doc.author);
         assert.equal('Wiley', doc.publisher.name);
@@ -171,15 +171,15 @@ describe('query middleware', function () {
     });
   });
 
-  it('can populate in post hook', function (done) {
-    schema.post('findOne', function (doc, next) {
-      doc.populate('publisher', function (error) {
+  it('can populate in post hook', function(done) {
+    schema.post('findOne', function(doc, next) {
+      doc.populate('publisher', function(error) {
         next(error);
       });
     });
 
-    initializeData(function () {
-      Author.findOne({title: 'Professional AngularJS'}).exec(function (error, doc) {
+    initializeData(function() {
+      Author.findOne({title: 'Professional AngularJS'}).exec(function(error, doc) {
         assert.ifError(error);
         assert.equal('Val', doc.author);
         assert.equal('Wiley', doc.publisher.name);
@@ -188,21 +188,21 @@ describe('query middleware', function () {
     });
   });
 
-  it('has hooks for count()', function (done) {
+  it('has hooks for count()', function(done) {
     var preCount = 0;
     var postCount = 0;
 
-    schema.pre('count', function () {
+    schema.pre('count', function() {
       ++preCount;
     });
 
-    schema.post('count', function () {
+    schema.post('count', function() {
       ++postCount;
     });
 
-    initializeData(function (error) {
+    initializeData(function(error) {
       assert.ifError(error);
-      Author.find({title: 'Professional AngularJS'}).count(function (error, count) {
+      Author.find({title: 'Professional AngularJS'}).count(function(error, count) {
         assert.ifError(error);
         assert.equal(1, count);
         assert.equal(1, preCount);
diff --git a/test/query.test.js b/test/query.test.js
index b516a36bfe7..0b67252e9a5 100644
--- a/test/query.test.js
+++ b/test/query.test.js
@@ -31,13 +31,13 @@ var p1;
  * Test.
  */
 
-describe('Query', function () {
-  before(function () {
+describe('Query', function() {
+  before(function() {
     var Prod = mongoose.model('Product');
     p1 = new Prod();
   });
-  describe('constructor', function () {
-    it('should not corrupt options', function (done) {
+  describe('constructor', function() {
+    it('should not corrupt options', function(done) {
       var opts = {};
       var query = new Query({}, opts, null, p1.collection);
       assert.notEqual(opts, query._mongooseOptions);
@@ -45,38 +45,38 @@ describe('Query', function () {
     });
   });
 
-  describe('select', function () {
-    it('(object)', function (done) {
+  describe('select', function() {
+    it('(object)', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.select({a: 1, b: 1, c: 0});
       assert.deepEqual(query._fields, {a: 1, b: 1, c: 0});
       done();
     });
 
-    it('(string)', function (done) {
+    it('(string)', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.select(' a  b -c ');
       assert.deepEqual(query._fields, {a: 1, b: 1, c: 0});
       done();
     });
 
-    it('("a","b","c")', function (done) {
-      assert.throws(function () {
+    it('("a","b","c")', function(done) {
+      assert.throws(function() {
         var query = new Query({}, {}, null, p1.collection);
         query.select('a', 'b', 'c');
       }, /Invalid select/);
       done();
     });
 
-    it('["a","b","c"]', function (done) {
-      assert.throws(function () {
+    it('["a","b","c"]', function(done) {
+      assert.throws(function() {
         var query = new Query({}, {}, null, p1.collection);
         query.select(['a', 'b', 'c']);
       }, /Invalid select/);
       done();
     });
 
-    it('should not overwrite fields set in prior calls', function (done) {
+    it('should not overwrite fields set in prior calls', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.select('a');
       assert.deepEqual(query._fields, {a: 1});
@@ -90,8 +90,8 @@ describe('Query', function () {
     });
   });
 
-  describe('where', function () {
-    it('works', function (done) {
+  describe('where', function() {
+    it('works', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('name', 'guillermo');
       assert.deepEqual(query._conditions, {name: 'guillermo'});
@@ -100,27 +100,27 @@ describe('Query', function () {
       assert.deepEqual(query._conditions, {name: 'guillermo', a: 'b'});
       done();
     });
-    it('throws if non-string or non-object path is passed', function (done) {
+    it('throws if non-string or non-object path is passed', function(done) {
       var query = new Query({}, {}, null, p1.collection);
-      assert.throws(function () {
+      assert.throws(function() {
         query.where(50);
       });
-      assert.throws(function () {
+      assert.throws(function() {
         query.where([]);
       });
       done();
     });
-    it('does not throw when 0 args passed', function (done) {
+    it('does not throw when 0 args passed', function(done) {
       var query = new Query({}, {}, null, p1.collection);
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         query.where();
       });
       done();
     });
   });
 
-  describe('equals', function () {
-    it('works', function (done) {
+  describe('equals', function() {
+    it('works', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('name').equals('guillermo');
       assert.deepEqual(query._conditions, {name: 'guillermo'});
@@ -128,14 +128,14 @@ describe('Query', function () {
     });
   });
 
-  describe('gte', function () {
-    it('with 2 args', function (done) {
+  describe('gte', function() {
+    it('with 2 args', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.gte('age', 18);
       assert.deepEqual(query._conditions, {age: {$gte: 18}});
       done();
     });
-    it('with 1 arg', function (done) {
+    it('with 1 arg', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').gte(18);
       assert.deepEqual(query._conditions, {age: {$gte: 18}});
@@ -143,14 +143,14 @@ describe('Query', function () {
     });
   });
 
-  describe('gt', function () {
-    it('with 1 arg', function (done) {
+  describe('gt', function() {
+    it('with 1 arg', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').gt(17);
       assert.deepEqual(query._conditions, {age: {$gt: 17}});
       done();
     });
-    it('with 2 args', function (done) {
+    it('with 2 args', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.gt('age', 17);
       assert.deepEqual(query._conditions, {age: {$gt: 17}});
@@ -158,14 +158,14 @@ describe('Query', function () {
     });
   });
 
-  describe('lte', function () {
-    it('with 1 arg', function (done) {
+  describe('lte', function() {
+    it('with 1 arg', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').lte(65);
       assert.deepEqual(query._conditions, {age: {$lte: 65}});
       done();
     });
-    it('with 2 args', function (done) {
+    it('with 2 args', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.lte('age', 65);
       assert.deepEqual(query._conditions, {age: {$lte: 65}});
@@ -173,14 +173,14 @@ describe('Query', function () {
     });
   });
 
-  describe('lt', function () {
-    it('with 1 arg', function (done) {
+  describe('lt', function() {
+    it('with 1 arg', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').lt(66);
       assert.deepEqual(query._conditions, {age: {$lt: 66}});
       done();
     });
-    it('with 2 args', function (done) {
+    it('with 2 args', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.lt('age', 66);
       assert.deepEqual(query._conditions, {age: {$lt: 66}});
@@ -188,9 +188,9 @@ describe('Query', function () {
     });
   });
 
-  describe('combined', function () {
-    describe('lt and gt', function () {
-      it('works', function (done) {
+  describe('combined', function() {
+    describe('lt and gt', function() {
+      it('works', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('age').lt(66).gt(17);
         assert.deepEqual(query._conditions, {age: {$lt: 66, $gt: 17}});
@@ -199,8 +199,8 @@ describe('Query', function () {
     });
   });
 
-  describe('tl on one path and gt on another', function () {
-    it('works', function (done) {
+  describe('tl on one path and gt on another', function() {
+    it('works', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query
       .where('age').lt(66)
@@ -210,14 +210,14 @@ describe('Query', function () {
     });
   });
 
-  describe('ne', function () {
-    it('with 1 arg', function (done) {
+  describe('ne', function() {
+    it('with 1 arg', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').ne(21);
       assert.deepEqual(query._conditions, {age: {$ne: 21}});
       done();
     });
-    it('with 2 args', function (done) {
+    it('with 2 args', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.ne('age', 21);
       assert.deepEqual(query._conditions, {age: {$ne: 21}});
@@ -225,26 +225,26 @@ describe('Query', function () {
     });
   });
 
-  describe('in', function () {
-    it('with 1 arg', function (done) {
+  describe('in', function() {
+    it('with 1 arg', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').in([21, 25, 30]);
       assert.deepEqual(query._conditions, {age: {$in: [21, 25, 30]}});
       done();
     });
-    it('with 2 args', function (done) {
+    it('with 2 args', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.in('age', [21, 25, 30]);
       assert.deepEqual(query._conditions, {age: {$in: [21, 25, 30]}});
       done();
     });
-    it('where a non-array value no via where', function (done) {
+    it('where a non-array value no via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.in('age', 21);
       assert.deepEqual(query._conditions, {age: {$in: 21}});
       done();
     });
-    it('where a non-array value via where', function (done) {
+    it('where a non-array value via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').in(21);
       assert.deepEqual(query._conditions, {age: {$in: 21}});
@@ -252,26 +252,26 @@ describe('Query', function () {
     });
   });
 
-  describe('nin', function () {
-    it('with 1 arg', function (done) {
+  describe('nin', function() {
+    it('with 1 arg', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').nin([21, 25, 30]);
       assert.deepEqual(query._conditions, {age: {$nin: [21, 25, 30]}});
       done();
     });
-    it('with 2 args', function (done) {
+    it('with 2 args', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.nin('age', [21, 25, 30]);
       assert.deepEqual(query._conditions, {age: {$nin: [21, 25, 30]}});
       done();
     });
-    it('with a non-array value not via where', function (done) {
+    it('with a non-array value not via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.nin('age', 21);
       assert.deepEqual(query._conditions, {age: {$nin: 21}});
       done();
     });
-    it('with a non-array value via where', function (done) {
+    it('with a non-array value via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').nin(21);
       assert.deepEqual(query._conditions, {age: {$nin: 21}});
@@ -279,26 +279,26 @@ describe('Query', function () {
     });
   });
 
-  describe('mod', function () {
-    it('not via where, where [a, b] param', function (done) {
+  describe('mod', function() {
+    it('not via where, where [a, b] param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.mod('age', [5, 2]);
       assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
       done();
     });
-    it('not via where, where a and b params', function (done) {
+    it('not via where, where a and b params', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.mod('age', 5, 2);
       assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
       done();
     });
-    it('via where, where [a, b] param', function (done) {
+    it('via where, where [a, b] param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').mod([5, 2]);
       assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
       done();
     });
-    it('via where, where a and b params', function (done) {
+    it('via where, where a and b params', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('age').mod(5, 2);
       assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
@@ -306,47 +306,47 @@ describe('Query', function () {
     });
   });
 
-  describe('near', function () {
-    it('via where, where { center :[lat, long]} param', function (done) {
+  describe('near', function() {
+    it('via where, where { center :[lat, long]} param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').near({center: [40, -72]});
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('via where, where [lat, long] param', function (done) {
+    it('via where, where [lat, long] param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').near([40, -72]);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('via where, where lat and long params', function (done) {
+    it('via where, where lat and long params', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').near(40, -72);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('not via where, where [lat, long] param', function (done) {
+    it('not via where, where [lat, long] param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.near('checkin', [40, -72]);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('not via where, where lat and long params', function (done) {
+    it('not via where, where lat and long params', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.near('checkin', 40, -72);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
       done();
     });
-    it('via where, where GeoJSON param', function (done) {
+    it('via where, where GeoJSON param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('numbers').near({center: {type: 'Point', coordinates: [40, -72]}});
       assert.deepEqual(query._conditions, {numbers: {$near: {$geometry: {type: 'Point', coordinates: [40, -72]}}}});
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         query.cast(p1.constructor);
       });
       done();
     });
-    it('with path, where GeoJSON param', function (done) {
+    it('with path, where GeoJSON param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.near('loc', {center: {type: 'Point', coordinates: [40, -72]}});
       assert.deepEqual(query._conditions, {loc: {$near: {$geometry: {type: 'Point', coordinates: [40, -72]}}}});
@@ -354,62 +354,62 @@ describe('Query', function () {
     });
   });
 
-  describe('nearSphere', function () {
-    it('via where, where [lat, long] param', function (done) {
+  describe('nearSphere', function() {
+    it('via where, where [lat, long] param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').nearSphere([40, -72]);
       assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
       done();
     });
-    it('via where, where lat and long params', function (done) {
+    it('via where, where lat and long params', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').nearSphere(40, -72);
       assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
       done();
     });
-    it('not via where, where [lat, long] param', function (done) {
+    it('not via where, where [lat, long] param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.nearSphere('checkin', [40, -72]);
       assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
       done();
     });
-    it('not via where, where lat and long params', function (done) {
+    it('not via where, where lat and long params', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.nearSphere('checkin', 40, -72);
       assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
       done();
     });
 
-    it('via where, with object', function (done) {
+    it('via where, with object', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').nearSphere({center: [20, 23], maxDistance: 2});
       assert.deepEqual(query._conditions, {checkin: {$nearSphere: [20, 23], $maxDistance: 2}});
       done();
     });
 
-    it('via where, where GeoJSON param', function (done) {
+    it('via where, where GeoJSON param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('numbers').nearSphere({center: {type: 'Point', coordinates: [40, -72]}});
       assert.deepEqual(query._conditions, {numbers: {$nearSphere: {$geometry: {type: 'Point', coordinates: [40, -72]}}}});
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         query.cast(p1.constructor);
       });
       done();
     });
 
-    it('with path, with GeoJSON', function (done) {
+    it('with path, with GeoJSON', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.nearSphere('numbers', {center: {type: 'Point', coordinates: [40, -72]}});
       assert.deepEqual(query._conditions, {numbers: {$nearSphere: {$geometry: {type: 'Point', coordinates: [40, -72]}}}});
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         query.cast(p1.constructor);
       });
       done();
     });
   });
 
-  describe('maxDistance', function () {
-    it('via where', function (done) {
+  describe('maxDistance', function() {
+    it('via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('checkin').near([40, -72]).maxDistance(1);
       assert.deepEqual(query._conditions, {checkin: {$near: [40, -72], $maxDistance: 1}});
@@ -417,9 +417,9 @@ describe('Query', function () {
     });
   });
 
-  describe('within', function () {
-    describe('box', function () {
-      it('via where', function (done) {
+  describe('within', function() {
+    describe('box', function() {
+      it('via where', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('gps').within().box({ll: [5, 25], ur: [10, 30]});
         var match = {gps: {$within: {$box: [[5, 25], [10, 30]]}}};
@@ -430,7 +430,7 @@ describe('Query', function () {
         assert.deepEqual(query._conditions, match);
         done();
       });
-      it('via where, no object', function (done) {
+      it('via where, no object', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('gps').within().box([5, 25], [10, 30]);
         var match = {gps: {$within: {$box: [[5, 25], [10, 30]]}}};
@@ -443,8 +443,8 @@ describe('Query', function () {
       });
     });
 
-    describe('center', function () {
-      it('via where', function (done) {
+    describe('center', function() {
+      it('via where', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('gps').within().center({center: [5, 25], radius: 5});
         var match = {gps: {$within: {$center: [[5, 25], 5]}}};
@@ -457,8 +457,8 @@ describe('Query', function () {
       });
     });
 
-    describe('centerSphere', function () {
-      it('via where', function (done) {
+    describe('centerSphere', function() {
+      it('via where', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('gps').within().centerSphere({center: [5, 25], radius: 5});
         var match = {gps: {$within: {$centerSphere: [[5, 25], 5]}}};
@@ -471,8 +471,8 @@ describe('Query', function () {
       });
     });
 
-    describe('polygon', function () {
-      it('via where', function (done) {
+    describe('polygon', function() {
+      it('via where', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('gps').within().polygon({a: {x: 10, y: 20}, b: {x: 15, y: 25}, c: {x: 20, y: 20}});
         var match = {gps: {$within: {$polygon: [{a: {x: 10, y: 20}, b: {x: 15, y: 25}, c: {x: 20, y: 20}}]}}};
@@ -486,27 +486,27 @@ describe('Query', function () {
     });
   });
 
-  describe('exists', function () {
-    it('0 args via where', function (done) {
+  describe('exists', function() {
+    it('0 args via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('username').exists();
       assert.deepEqual(query._conditions, {username: {$exists: true}});
       done();
     });
-    it('1 arg via where', function (done) {
+    it('1 arg via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('username').exists(false);
       assert.deepEqual(query._conditions, {username: {$exists: false}});
       done();
     });
-    it('where 1 argument not via where', function (done) {
+    it('where 1 argument not via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.exists('username');
       assert.deepEqual(query._conditions, {username: {$exists: true}});
       done();
     });
 
-    it('where 2 args not via where', function (done) {
+    it('where 2 args not via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.exists('username', false);
       assert.deepEqual(query._conditions, {username: {$exists: false}});
@@ -514,14 +514,14 @@ describe('Query', function () {
     });
   });
 
-  describe('all', function () {
-    it('via where', function (done) {
+  describe('all', function() {
+    it('via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('pets').all(['dog', 'cat', 'ferret']);
       assert.deepEqual(query._conditions, {pets: {$all: ['dog', 'cat', 'ferret']}});
       done();
     });
-    it('not via where', function (done) {
+    it('not via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.all('pets', ['dog', 'cat', 'ferret']);
       assert.deepEqual(query._conditions, {pets: {$all: ['dog', 'cat', 'ferret']}});
@@ -529,14 +529,14 @@ describe('Query', function () {
     });
   });
 
-  describe('find', function () {
-    it('strict array equivalence condition v', function (done) {
+  describe('find', function() {
+    it('strict array equivalence condition v', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.find({pets: ['dog', 'cat', 'ferret']});
       assert.deepEqual(query._conditions, {pets: ['dog', 'cat', 'ferret']});
       done();
     });
-    it('with no args', function (done) {
+    it('with no args', function(done) {
       var threw = false;
       var q = new Query({}, {}, null, p1.collection);
 
@@ -549,9 +549,9 @@ describe('Query', function () {
       assert.ok(!threw);
       done();
     });
-    it('works with overwriting previous object args (1176)', function (done) {
+    it('works with overwriting previous object args (1176)', function(done) {
       var q = new Query({}, {}, null, p1.collection);
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         q.find({age: {$lt: 30}});
         q.find({age: 20}); // overwrite
       });
@@ -560,14 +560,14 @@ describe('Query', function () {
     });
   });
 
-  describe('size', function () {
-    it('via where', function (done) {
+  describe('size', function() {
+    it('via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').size(5);
       assert.deepEqual(query._conditions, {collection: {$size: 5}});
       done();
     });
-    it('not via where', function (done) {
+    it('not via where', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.size('collection', 5);
       assert.deepEqual(query._conditions, {collection: {$size: 5}});
@@ -575,74 +575,74 @@ describe('Query', function () {
     });
   });
 
-  describe('slice', function () {
-    it('where and positive limit param', function (done) {
+  describe('slice', function() {
+    it('where and positive limit param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(5);
       assert.deepEqual(query._fields, {collection: {$slice: 5}});
       done();
     });
-    it('where just negative limit param', function (done) {
+    it('where just negative limit param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(-5);
       assert.deepEqual(query._fields, {collection: {$slice: -5}});
       done();
     });
-    it('where [skip, limit] param', function (done) {
+    it('where [skip, limit] param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice([14, 10]); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('where skip and limit params', function (done) {
+    it('where skip and limit params', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(14, 10); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('where just positive limit param', function (done) {
+    it('where just positive limit param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(5);
       assert.deepEqual(query._fields, {collection: {$slice: 5}});
       done();
     });
-    it('where just negative limit param', function (done) {
+    it('where just negative limit param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(-5);
       assert.deepEqual(query._fields, {collection: {$slice: -5}});
       done();
     });
-    it('where the [skip, limit] param', function (done) {
+    it('where the [skip, limit] param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice([14, 10]); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('where the skip and limit params', function (done) {
+    it('where the skip and limit params', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.where('collection').slice(14, 10); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('not via where, with just positive limit param', function (done) {
+    it('not via where, with just positive limit param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.slice('collection', 5);
       assert.deepEqual(query._fields, {collection: {$slice: 5}});
       done();
     });
-    it('not via where, where just negative limit param', function (done) {
+    it('not via where, where just negative limit param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.slice('collection', -5);
       assert.deepEqual(query._fields, {collection: {$slice: -5}});
       done();
     });
-    it('not via where, where [skip, limit] param', function (done) {
+    it('not via where, where [skip, limit] param', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.slice('collection', [14, 10]); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
       done();
     });
-    it('not via where, where skip and limit params', function (done) {
+    it('not via where, where skip and limit params', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.slice('collection', 14, 10); // Return the 15th through 25th
       assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
@@ -650,17 +650,17 @@ describe('Query', function () {
     });
   });
 
-  describe('elemMatch', function () {
-    describe('not via where', function () {
-      it('works', function (done) {
+  describe('elemMatch', function() {
+    describe('not via where', function() {
+      it('works', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.elemMatch('comments', {author: 'bnoguchi', votes: {$gte: 5}});
         assert.deepEqual(query._conditions, {comments: {$elemMatch: {author: 'bnoguchi', votes: {$gte: 5}}}});
         done();
       });
-      it('where block notation', function (done) {
+      it('where block notation', function(done) {
         var query = new Query({}, {}, null, p1.collection);
-        query.elemMatch('comments', function (elem) {
+        query.elemMatch('comments', function(elem) {
           elem.where('author', 'bnoguchi');
           elem.where('votes').gte(5);
         });
@@ -668,16 +668,16 @@ describe('Query', function () {
         done();
       });
     });
-    describe('via where', function () {
-      it('works', function (done) {
+    describe('via where', function() {
+      it('works', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.where('comments').elemMatch({author: 'bnoguchi', votes: {$gte: 5}});
         assert.deepEqual(query._conditions, {comments: {$elemMatch: {author: 'bnoguchi', votes: {$gte: 5}}}});
         done();
       });
-      it('where block notation', function (done) {
+      it('where block notation', function(done) {
         var query = new Query({}, {}, null, p1.collection);
-        query.where('comments').elemMatch(function (elem) {
+        query.where('comments').elemMatch(function(elem) {
           elem.where('author', 'bnoguchi');
           elem.where('votes').gte(5);
         });
@@ -687,8 +687,8 @@ describe('Query', function () {
     });
   });
 
-  describe('$where', function () {
-    it('function arg', function (done) {
+  describe('$where', function() {
+    it('function arg', function(done) {
       var query = new Query({}, {}, null, p1.collection);
 
       function filter() {
@@ -699,7 +699,7 @@ describe('Query', function () {
       assert.deepEqual(query._conditions, {$where: filter});
       done();
     });
-    it('string arg', function (done) {
+    it('string arg', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.$where('this.lastName === this.firstName');
       assert.deepEqual(query._conditions, {$where: 'this.lastName === this.firstName'});
@@ -707,8 +707,8 @@ describe('Query', function () {
     });
   });
 
-  describe('limit', function () {
-    it('works', function (done) {
+  describe('limit', function() {
+    it('works', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.limit(5);
       assert.equal(query.options.limit, 5);
@@ -716,8 +716,8 @@ describe('Query', function () {
     });
   });
 
-  describe('skip', function () {
-    it('works', function (done) {
+  describe('skip', function() {
+    it('works', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.skip(9);
       assert.equal(query.options.skip, 9);
@@ -725,8 +725,8 @@ describe('Query', function () {
     });
   });
 
-  describe('sort', function () {
-    it('works', function (done) {
+  describe('sort', function() {
+    it('works', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       query.sort('a -c b');
       assert.deepEqual(query.options.sort, {a: 1, c: -1, b: 1});
@@ -757,12 +757,12 @@ describe('Query', function () {
     });
   });
 
-  describe('or', function () {
-    it('works', function (done) {
+  describe('or', function() {
+    it('works', function(done) {
       var query = new Query;
       query.find({$or: [{x: 1}, {x: 2}]});
       assert.equal(query._conditions.$or.length, 2);
-      query.or([{y: "We're under attack"}, {z: 47}]);
+      query.or([{y: 'We\'re under attack'}, {z: 47}]);
       assert.equal(query._conditions.$or.length, 4);
       assert.equal(query._conditions.$or[3].z, 47);
       query.or({z: 'phew'});
@@ -773,27 +773,27 @@ describe('Query', function () {
     });
   });
 
-  describe('and', function () {
-    it('works', function (done) {
+  describe('and', function() {
+    it('works', function(done) {
       var query = new Query;
       query.find({$and: [{x: 1}, {y: 2}]});
       assert.equal(query._conditions.$and.length, 2);
-      query.and([{z: "We're under attack"}, {w: 47}]);
+      query.and([{z: 'We\'re under attack'}, {w: 47}]);
       assert.equal(query._conditions.$and.length, 4);
       assert.equal(query._conditions.$and[3].w, 47);
       query.and({a: 'phew'});
       assert.equal(query._conditions.$and.length, 5);
       assert.equal(query._conditions.$and[0].x, 1);
       assert.equal(query._conditions.$and[1].y, 2);
-      assert.equal(query._conditions.$and[2].z, "We're under attack");
+      assert.equal(query._conditions.$and[2].z, 'We\'re under attack');
       assert.equal(query._conditions.$and[3].w, 47);
       assert.equal(query._conditions.$and[4].a, 'phew');
       done();
     });
   });
 
-  describe('populate', function () {
-    it('converts to PopulateOptions objects', function (done) {
+  describe('populate', function() {
+    it('converts to PopulateOptions objects', function(done) {
       var q = new Query({}, {}, null, p1.collection);
       var o = {
         path: 'yellow.brick',
@@ -808,7 +808,7 @@ describe('Query', function () {
       done();
     });
 
-    it('overwrites duplicate paths', function (done) {
+    it('overwrites duplicate paths', function(done) {
       var q = new Query({}, {}, null, p1.collection);
       var o = {
         path: 'yellow.brick',
@@ -828,7 +828,7 @@ describe('Query', function () {
       done();
     });
 
-    it('accepts space delimited strings', function (done) {
+    it('accepts space delimited strings', function(done) {
       var q = new Query({}, {}, null, p1.collection);
       q.populate('yellow.brick dirt');
       var o = {
@@ -847,18 +847,18 @@ describe('Query', function () {
     });
   });
 
-  describe('casting', function () {
+  describe('casting', function() {
     var db;
 
-    before(function () {
+    before(function() {
       db = start();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('to an array of mixed', function (done) {
+    it('to an array of mixed', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
       var params = {_id: new DocumentObjectId, tags: {$in: [4, 8, 15, 16]}};
@@ -867,7 +867,7 @@ describe('Query', function () {
       done();
     });
 
-    it('find $ne should not cast single value to array for schematype of Array', function (done) {
+    it('find $ne should not cast single value to array for schematype of Array', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
       var Comment = db.model('Comment');
@@ -911,7 +911,7 @@ describe('Query', function () {
       done();
     });
 
-    it('subdocument array with $ne: null should not throw', function (done) {
+    it('subdocument array with $ne: null should not throw', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
 
@@ -924,7 +924,7 @@ describe('Query', function () {
       done();
     });
 
-    it('find should not cast single value to array for schematype of Array', function (done) {
+    it('find should not cast single value to array for schematype of Array', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
       var Comment = db.model('Comment');
@@ -968,7 +968,7 @@ describe('Query', function () {
       done();
     });
 
-    it('an $elemMatch with $in works (gh-1100)', function (done) {
+    it('an $elemMatch with $in works (gh-1100)', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
       var ids = [String(new DocumentObjectId), String(new DocumentObjectId)];
@@ -981,7 +981,7 @@ describe('Query', function () {
       done();
     });
 
-    it('inequality operators for an array', function (done) {
+    it('inequality operators for an array', function(done) {
       var query = new Query({}, {}, null, p1.collection);
       var Product = db.model('Product');
       var Comment = db.model('Comment');
@@ -1006,36 +1006,36 @@ describe('Query', function () {
     });
   });
 
-  describe('distinct', function () {
-    it('op', function (done) {
+  describe('distinct', function() {
+    it('op', function(done) {
       var db = start();
       var Product = db.model('Product');
       var prod = new Product({});
-      var q = new Query({}, {}, Product, prod.collection).distinct('blah', function () {
+      var q = new Query({}, {}, Product, prod.collection).distinct('blah', function() {
         assert.equal(q.op, 'distinct');
         db.close(done);
       });
     });
   });
 
-  describe('without a callback', function () {
-    it('count, update, remove works', function (done) {
+  describe('without a callback', function() {
+    it('count, update, remove works', function(done) {
       var db = start();
       var Product = db.model('Product', 'update_products_' + random());
       new Query(p1.collection, {}, Product).count();
-      Product.create({tags: 12345}, function (err) {
+      Product.create({tags: 12345}, function(err) {
         assert.ifError(err);
         var time = 20;
         Product.find({tags: 12345}).update({$set: {tags: 123456}});
 
-        setTimeout(function () {
-          Product.find({tags: 12345}, function (err, p) {
+        setTimeout(function() {
+          Product.find({tags: 12345}, function(err, p) {
             assert.ifError(err);
             assert.equal(1, p.length);
 
             Product.find({tags: 123456}).remove();
-            setTimeout(function () {
-              Product.find({tags: 123456}, function (err, p) {
+            setTimeout(function() {
+              Product.find({tags: 123456}, function(err, p) {
                 assert.ifError(err);
                 assert.equal(0, p.length);
                 db.close();
@@ -1048,15 +1048,15 @@ describe('Query', function () {
     });
   });
 
-  describe('findOne', function () {
-    it('sets the op', function (done) {
+  describe('findOne', function() {
+    it('sets the op', function(done) {
       var db = start();
       var Product = db.model('Product');
       var prod = new Product({});
       var q = new Query(prod.collection, {}, Product).distinct();
       // use a timeout here because we have to wait for the connection to start
       // before any ops will get set
-      setTimeout(function () {
+      setTimeout(function() {
         assert.equal(q.op, 'distinct');
         q.findOne();
         assert.equal(q.op, 'findOne');
@@ -1065,26 +1065,26 @@ describe('Query', function () {
       }, 50);
     });
 
-    it('works as a promise', function (done) {
+    it('works as a promise', function(done) {
       var db = start();
       var Product = db.model('Product');
       var promise = Product.findOne();
 
-      promise.then(function () {
+      promise.then(function() {
         db.close(done);
-      }, function (err) {
+      }, function(err) {
         assert.ifError(err);
       });
     });
   });
 
-  describe('remove', function () {
-    it('handles cast errors async', function (done) {
+  describe('remove', function() {
+    it('handles cast errors async', function(done) {
       var db = start();
       var Product = db.model('Product');
 
-      assert.doesNotThrow(function () {
-        Product.where({numbers: [[[]]]}).remove(function (err) {
+      assert.doesNotThrow(function() {
+        Product.where({numbers: [[[]]]}).remove(function(err) {
           db.close();
           assert.ok(err);
           done();
@@ -1092,11 +1092,11 @@ describe('Query', function () {
       });
     });
 
-    it('supports a single conditions arg', function (done) {
+    it('supports a single conditions arg', function(done) {
       var db = start();
       var Product = db.model('Product');
 
-      Product.create({strings: ['remove-single-condition']}).then(function () {
+      Product.create({strings: ['remove-single-condition']}).then(function() {
         db.close();
         var q = Product.where().remove({strings: 'remove-single-condition'});
         assert.ok(q instanceof mongoose.Query);
@@ -1104,15 +1104,15 @@ describe('Query', function () {
       }, done).end();
     });
 
-    it('supports a single callback arg', function (done) {
+    it('supports a single callback arg', function(done) {
       var db = start();
       var Product = db.model('Product');
       var val = 'remove-single-callback';
 
-      Product.create({strings: [val]}).then(function () {
-        Product.where({strings: val}).remove(function (err) {
+      Product.create({strings: [val]}).then(function() {
+        Product.where({strings: val}).remove(function(err) {
           assert.ifError(err);
-          Product.findOne({strings: val}, function (err, doc) {
+          Product.findOne({strings: val}, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.ok(!doc);
@@ -1122,15 +1122,15 @@ describe('Query', function () {
       }, done).end();
     });
 
-    it('supports conditions and callback args', function (done) {
+    it('supports conditions and callback args', function(done) {
       var db = start();
       var Product = db.model('Product');
       var val = 'remove-cond-and-callback';
 
-      Product.create({strings: [val]}).then(function () {
-        Product.where().remove({strings: val}, function (err) {
+      Product.create({strings: [val]}).then(function() {
+        Product.where().remove({strings: val}, function(err) {
           assert.ifError(err);
-          Product.findOne({strings: val}, function (err, doc) {
+          Product.findOne({strings: val}, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.ok(!doc);
@@ -1141,8 +1141,8 @@ describe('Query', function () {
     });
   });
 
-  describe('querying/updating with model instance containing embedded docs should work (#454)', function () {
-    it('works', function (done) {
+  describe('querying/updating with model instance containing embedded docs should work (#454)', function() {
+    it('works', function(done) {
       var db = start();
       var Product = db.model('Product');
 
@@ -1150,18 +1150,18 @@ describe('Query', function () {
       var prod2doc = {comments: [{text: 'goodbye'}]};
 
       var prod = new Product(proddoc);
-      prod.save(function (err) {
+      prod.save(function(err) {
         assert.ifError(err);
 
-        Product.findOne(prod, function (err, product) {
+        Product.findOne(prod, function(err, product) {
           assert.ifError(err);
           assert.equal(product.comments.length, 1);
           assert.equal(product.comments[0].text, 'hello');
 
-          Product.update(product, prod2doc, function (err) {
+          Product.update(product, prod2doc, function(err) {
             assert.ifError(err);
 
-            Product.collection.findOne({_id: product._id}, function (err, doc) {
+            Product.collection.findOne({_id: product._id}, function(err, doc) {
               assert.ifError(err);
               assert.equal(doc.comments.length, 1);
               // ensure hidden private props were not saved to db
@@ -1175,8 +1175,8 @@ describe('Query', function () {
     });
   });
 
-  describe('optionsForExecute', function () {
-    it('should retain key order', function (done) {
+  describe('optionsForExecute', function() {
+    it('should retain key order', function(done) {
       // this is important for query hints
       var hint = {x: 1, y: 1, z: 1};
       var a = JSON.stringify({hint: hint, safe: true});
@@ -1192,9 +1192,9 @@ describe('Query', function () {
 
   // Advanced Query options
 
-  describe('options', function () {
-    describe('maxscan', function () {
-      it('works', function (done) {
+  describe('options', function() {
+    describe('maxscan', function() {
+      it('works', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.maxscan(100);
         assert.equal(query.options.maxScan, 100);
@@ -1202,8 +1202,8 @@ describe('Query', function () {
       });
     });
 
-    describe('slaveOk', function () {
-      it('works', function (done) {
+    describe('slaveOk', function() {
+      it('works', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.slaveOk();
         assert.equal(true, query.options.slaveOk);
@@ -1219,8 +1219,8 @@ describe('Query', function () {
       });
     });
 
-    describe('tailable', function () {
-      it('works', function (done) {
+    describe('tailable', function() {
+      it('works', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.tailable();
         assert.equal(true, query.options.tailable);
@@ -1234,7 +1234,7 @@ describe('Query', function () {
         assert.equal(false, query.options.tailable);
         done();
       });
-      it('supports passing the `await` option', function (done) {
+      it('supports passing the `await` option', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.tailable({awaitdata: true});
         assert.equal(true, query.options.tailable);
@@ -1243,8 +1243,8 @@ describe('Query', function () {
       });
     });
 
-    describe('comment', function () {
-      it('works', function (done) {
+    describe('comment', function() {
+      it('works', function(done) {
         var query = new Query;
         assert.equal('function', typeof query.comment);
         assert.equal(query.comment('Lowpass is more fun'), query);
@@ -1253,13 +1253,13 @@ describe('Query', function () {
       });
     });
 
-    describe('hint', function () {
-      it('works', function (done) {
+    describe('hint', function() {
+      it('works', function(done) {
         var query2 = new Query({}, {}, null, p1.collection);
         query2.hint({indexAttributeA: 1, indexAttributeB: -1});
         assert.deepEqual(query2.options.hint, {indexAttributeA: 1, indexAttributeB: -1});
 
-        assert.throws(function () {
+        assert.throws(function() {
           var query3 = new Query({}, {}, null, p1.collection);
           query3.hint('indexAttributeA');
         }, /Invalid hint./);
@@ -1268,8 +1268,8 @@ describe('Query', function () {
       });
     });
 
-    describe('snapshot', function () {
-      it('works', function (done) {
+    describe('snapshot', function() {
+      it('works', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.snapshot(true);
         assert.equal(true, query.options.snapshot);
@@ -1277,8 +1277,8 @@ describe('Query', function () {
       });
     });
 
-    describe('batchSize', function () {
-      it('works', function (done) {
+    describe('batchSize', function() {
+      it('works', function(done) {
         var query = new Query({}, {}, null, p1.collection);
         query.batchSize(10);
         assert.equal(query.options.batchSize, 10);
@@ -1286,11 +1286,11 @@ describe('Query', function () {
       });
     });
 
-    describe('read', function () {
+    describe('read', function() {
       var P = mongoose.mongo.ReadPreference;
 
-      describe('without tags', function () {
-        it('works', function (done) {
+      describe('without tags', function() {
+        it('works', function(done) {
           var query = new Query({}, {}, null, p1.collection);
           query.read('primary');
           assert.ok(query.options.readPreference instanceof P);
@@ -1346,8 +1346,8 @@ describe('Query', function () {
         });
       });
 
-      describe('with tags', function () {
-        it('works', function (done) {
+      describe('with tags', function() {
+        it('works', function(done) {
           var query = new Query({}, {}, null, p1.collection);
           var tags = [{dc: 'sf', s: 1}, {dc: 'jp', s: 2}];
 
@@ -1364,28 +1364,28 @@ describe('Query', function () {
         });
       });
 
-      describe('inherits its models schema read option', function () {
+      describe('inherits its models schema read option', function() {
         var schema, M, called;
-        before(function () {
+        before(function() {
           schema = new Schema({}, {read: 'p'});
           M = mongoose.model('schemaOptionReadPrefWithQuery', schema);
         });
 
-        it('if not set in query', function (done) {
+        it('if not set in query', function(done) {
           var options = M.where()._optionsForExec(M);
           assert.ok(options.readPreference instanceof P);
           assert.equal(options.readPreference.mode, 'primary');
           done();
         });
 
-        it('if set in query', function (done) {
+        it('if set in query', function(done) {
           var options = M.where().read('s')._optionsForExec(M);
           assert.ok(options.readPreference instanceof P);
           assert.equal(options.readPreference.mode, 'secondary');
           done();
         });
 
-        it('and sends it though the driver', function (done) {
+        it('and sends it though the driver', function(done) {
           var db = start();
           var options = {read: 'secondary', safe: {w: 'majority'}};
           var schema = new Schema({name: String}, options);
@@ -1394,7 +1394,7 @@ describe('Query', function () {
 
           // stub the internal query options call
           var getopts = q._optionsForExec;
-          q._optionsForExec = function (model) {
+          q._optionsForExec = function(model) {
             q._optionsForExec = getopts;
 
             var ret = getopts.call(this, model);
@@ -1407,7 +1407,7 @@ describe('Query', function () {
             return ret;
           };
 
-          q.exec(function (err) {
+          q.exec(function(err) {
             if (err) {
               return done(err);
             }
@@ -1419,8 +1419,8 @@ describe('Query', function () {
     });
   });
 
-  describe('setOptions', function () {
-    it('works', function (done) {
+  describe('setOptions', function() {
+    it('works', function(done) {
       var q = new Query;
       q.setOptions({thing: 'cat'});
       q.setOptions({populate: ['fans']});
@@ -1449,9 +1449,9 @@ describe('Query', function () {
       var Product = db.model('Product', 'Product_setOptions_test');
       Product.create(
           {numbers: [3, 4, 5]},
-          {strings: 'hi there'.split(' ')}, function (err, doc1, doc2) {
+          {strings: 'hi there'.split(' ')}, function(err, doc1, doc2) {
             assert.ifError(err);
-            Product.find().setOptions({limit: 1, sort: {_id: -1}, read: 'n'}).exec(function (err, docs) {
+            Product.find().setOptions({limit: 1, sort: {_id: -1}, read: 'n'}).exec(function(err, docs) {
               db.close();
               assert.ifError(err);
               assert.equal(docs.length, 1);
@@ -1462,35 +1462,35 @@ describe('Query', function () {
     });
   });
 
-  describe('update', function () {
-    it('when empty, nothing is run', function (done) {
+  describe('update', function() {
+    it('when empty, nothing is run', function(done) {
       var q = new Query;
       assert.equal(false, !!q._castUpdate({}));
       done();
     });
   });
 
-  describe('gh-1950', function () {
-    it('ignores sort when passed to count', function (done) {
+  describe('gh-1950', function() {
+    it('ignores sort when passed to count', function(done) {
       var db = start();
       var Product = db.model('Product', 'Product_setOptions_test');
-      Product.find().sort({_id: 1}).count({}).exec(function (error) {
+      Product.find().sort({_id: 1}).count({}).exec(function(error) {
         assert.ifError(error);
         db.close(done);
       });
     });
 
-    it('ignores count when passed to sort', function (done) {
+    it('ignores count when passed to sort', function(done) {
       var db = start();
       var Product = db.model('Product', 'Product_setOptions_test');
-      Product.find().count({}).sort({_id: 1}).exec(function (error) {
+      Product.find().count({}).sort({_id: 1}).exec(function(error) {
         assert.ifError(error);
         db.close(done);
       });
     });
   });
 
-  it('excludes _id when select false and inclusive mode (gh-3010)', function (done) {
+  it('excludes _id when select false and inclusive mode (gh-3010)', function(done) {
     var db = start();
     var User = db.model('gh3010', {
       _id: {
@@ -1501,9 +1501,9 @@ describe('Query', function () {
       username: String
     });
 
-    User.create({username: 'Val'}, function (error, user) {
+    User.create({username: 'Val'}, function(error, user) {
       assert.ifError(error);
-      User.find({_id: user._id}).select('username').exec(function (error, users) {
+      User.find({_id: user._id}).select('username').exec(function(error, users) {
         assert.ifError(error);
         assert.equal(users.length, 1);
         assert.ok(!users[0]._id);
@@ -1513,7 +1513,7 @@ describe('Query', function () {
     });
   });
 
-  it('doesnt reverse key order for update docs (gh-3215)', function (done) {
+  it('doesnt reverse key order for update docs (gh-3215)', function(done) {
     var db = start();
     var Test = db.model('gh3215', {
       arr: [{date: Date, value: Number}]
@@ -1533,7 +1533,7 @@ describe('Query', function () {
     db.close(done);
   });
 
-  it('handles nested $ (gh-3265)', function (done) {
+  it('handles nested $ (gh-3265)', function(done) {
     var db = start();
     var Post = db.model('gh3265', {
       title: String,
@@ -1556,11 +1556,11 @@ describe('Query', function () {
     db.close(done);
   });
 
-  describe('handles falsy and object projections with defaults (gh-3256)', function () {
+  describe('handles falsy and object projections with defaults (gh-3256)', function() {
     var db = start();
     var MyModel;
 
-    before(function (done) {
+    before(function(done) {
       db = start();
 
       var PersonSchema = new Schema({
@@ -1576,7 +1576,7 @@ describe('Query', function () {
         lastName: 'Doe',
         dependents: ['Jake', 'Jill', 'Jane']
       };
-      m.create(obj, function (error) {
+      m.create(obj, function(error) {
         assert.ifError(error);
 
         var PersonSchema = new Schema({
@@ -1592,31 +1592,31 @@ describe('Query', function () {
       });
     });
 
-    after(function () {
+    after(function() {
       db.close();
     });
 
-    it('falsy projection', function (done) {
+    it('falsy projection', function(done) {
       MyModel.findOne({name: 'John'}, {lastName: false}).
-      exec(function (error, person) {
+      exec(function(error, person) {
         assert.ifError(error);
         assert.equal(person.salary, 25000);
         done();
       });
     });
 
-    it('slice projection', function (done) {
+    it('slice projection', function(done) {
       MyModel.findOne({name: 'John'}, {dependents: {$slice: 1}}).
-      exec(function (error, person) {
+      exec(function(error, person) {
         assert.ifError(error);
         assert.equal(person.salary, 25000);
         done();
       });
     });
 
-    it('empty projection', function (done) {
+    it('empty projection', function(done) {
       MyModel.findOne({name: 'John'}, {}).
-      exec(function (error, person) {
+      exec(function(error, person) {
         assert.ifError(error);
         assert.equal(person.salary, 25000);
         done();
diff --git a/test/query.toconstructor.test.js b/test/query.toconstructor.test.js
index 23d6d52c190..e9ac9ebc369 100644
--- a/test/query.toconstructor.test.js
+++ b/test/query.toconstructor.test.js
@@ -24,9 +24,9 @@ var cName = 'Comment' + random();
 mongoose.model(prodName, Product);
 mongoose.model(cName, Comment);
 
-describe('Query:', function () {
-  describe('toConstructor', function () {
-    it('creates a query', function (done) {
+describe('Query:', function() {
+  describe('toConstructor', function() {
+    it('creates a query', function(done) {
       var db = start();
       var Product = db.model(prodName);
       var prodQ = Product.find({title: /test/}).toConstructor();
@@ -36,7 +36,7 @@ describe('Query:', function () {
       db.close(done);
     });
 
-    it('copies all the right values', function (done) {
+    it('copies all the right values', function(done) {
       var db = start();
       var Product = db.model(prodName);
 
@@ -57,14 +57,14 @@ describe('Query:', function () {
       db.close(done);
     });
 
-    it('gets expected results', function (done) {
+    it('gets expected results', function(done) {
       var db = start();
       var Product = db.model(prodName);
-      Product.create({title: 'this is a test'}, function (err, p) {
+      Product.create({title: 'this is a test'}, function(err, p) {
         assert.ifError(err);
         var prodC = Product.find({title: /test/}).toConstructor();
 
-        prodC().exec(function (err, results) {
+        prodC().exec(function(err, results) {
           db.close();
           assert.ifError(err);
           assert.equal(results.length, 1);
@@ -74,25 +74,25 @@ describe('Query:', function () {
       });
     });
 
-    it('can be re-used multiple times', function (done) {
+    it('can be re-used multiple times', function(done) {
       var db = start();
       var Product = db.model(prodName);
 
-      Product.create([{title: 'moar thing'}, {title: 'second thing'}], function (err, prods) {
+      Product.create([{title: 'moar thing'}, {title: 'second thing'}], function(err, prods) {
         assert.ifError(err);
         assert.equal(prods.length, 2);
         var prod = prods[0];
         var prodC = Product.find({title: /thing/}).toConstructor();
 
-        prodC().exec(function (err, results) {
+        prodC().exec(function(err, results) {
           assert.ifError(err);
 
           assert.equal(results.length, 2);
-          prodC().find({_id: prod.id}).exec(function (err, res) {
+          prodC().find({_id: prod.id}).exec(function(err, res) {
             assert.ifError(err);
             assert.equal(res.length, 1);
 
-            prodC().exec(function (err, res) {
+            prodC().exec(function(err, res) {
               db.close();
               assert.ifError(err);
               assert.equal(res.length, 2);
@@ -103,7 +103,7 @@ describe('Query:', function () {
       });
     });
 
-    it('options get merged properly', function (done) {
+    it('options get merged properly', function(done) {
       var db = start();
       var Product = db.model(prodName);
       db.close();
@@ -117,7 +117,7 @@ describe('Query:', function () {
       done();
     });
 
-    it('options get cloned (gh-3176)', function (done) {
+    it('options get cloned (gh-3176)', function(done) {
       var db = start();
       var Product = db.model(prodName);
       db.close();
@@ -134,7 +134,7 @@ describe('Query:', function () {
       done();
     });
 
-    it('creates subclasses of mquery', function (done) {
+    it('creates subclasses of mquery', function(done) {
       var db = start();
       var Product = db.model(prodName);
       db.close();
diff --git a/test/schema.boolean.test.js b/test/schema.boolean.test.js
index d60e2f6507e..fe49e138f7f 100644
--- a/test/schema.boolean.test.js
+++ b/test/schema.boolean.test.js
@@ -8,9 +8,9 @@ var start = require('./common'),
     assert = require('assert'),
     Schema = mongoose.Schema;
 
-describe('schematype', function () {
-  describe('boolean', function () {
-    it('null default is permitted (gh-523)', function (done) {
+describe('schematype', function() {
+  describe('boolean', function() {
+    it('null default is permitted (gh-523)', function(done) {
       var db = start(),
           s1 = new Schema({b: {type: Boolean, default: null}}),
           M1 = db.model('NullDateDefaultIsAllowed1', s1),
diff --git a/test/schema.documentarray.test.js b/test/schema.documentarray.test.js
index 9b49db4e4d1..9699c12aff4 100644
--- a/test/schema.documentarray.test.js
+++ b/test/schema.documentarray.test.js
@@ -11,15 +11,15 @@ var start = require('./common'),
  * Test.
  */
 
-describe('schema.documentarray', function () {
-  it('defaults should be preserved', function (done) {
+describe('schema.documentarray', function() {
+  it('defaults should be preserved', function(done) {
     var child = new Schema({title: String});
 
     var schema1 = new Schema({x: {type: [child], default: [{title: 'Prometheus'}]}});
     var schema2 = new Schema({x: {type: [child], default: {title: 'Prometheus'}}});
     var schema3 = new Schema({
       x: {
-        type: [child], default: function () {
+        type: [child], default: function() {
           return [{title: 'Prometheus'}];
         }
       }
@@ -29,7 +29,7 @@ describe('schema.documentarray', function () {
     var N = mongoose.model('DefaultDocArrays2', schema2);
     var O = mongoose.model('DefaultDocArrays3', schema3);
 
-    [M, N, O].forEach(function (M) {
+    [M, N, O].forEach(function(M) {
       var m = new M;
       assert.ok(Array.isArray(m.x));
       assert.equal(1, m.x.length);
@@ -38,7 +38,7 @@ describe('schema.documentarray', function () {
     done();
   });
 
-  it('only sets if document has same schema (gh-3701)', function (done) {
+  it('only sets if document has same schema (gh-3701)', function(done) {
     var schema1 = new Schema({
       arr: [new Schema({a: Number, b: Number}, {_id: false})]
     });
diff --git a/test/schema.mixed.test.js b/test/schema.mixed.test.js
index cfd25ba4c93..e4670bf4274 100644
--- a/test/schema.mixed.test.js
+++ b/test/schema.mixed.test.js
@@ -8,9 +8,9 @@ var start = require('./common'),
     assert = require('assert'),
     Schema = mongoose.Schema;
 
-describe('schematype mixed', function () {
-  describe('empty object defaults (gh-1380)', function () {
-    it('are interpreted as fns that return new empty objects', function (done) {
+describe('schematype mixed', function() {
+  describe('empty object defaults (gh-1380)', function() {
+    it('are interpreted as fns that return new empty objects', function(done) {
       var s = new Schema({mix: {type: Schema.Types.Mixed, default: {}}});
       var M = mongoose.model('M1', s);
       var m1 = new M;
@@ -20,7 +20,7 @@ describe('schematype mixed', function () {
       assert.equal(undefined, m2.mix.val);
       done();
     });
-    it('can be forced to share the object between documents', function (done) {
+    it('can be forced to share the object between documents', function(done) {
       // silly but necessary for backwards compatibility
       var s = new Schema({mix: {type: Schema.Types.Mixed, default: {}, shared: true}});
       var M = mongoose.model('M2', s);
diff --git a/test/schema.onthefly.test.js b/test/schema.onthefly.test.js
index c59a08b41f9..b5c96aa418f 100644
--- a/test/schema.onthefly.test.js
+++ b/test/schema.onthefly.test.js
@@ -17,8 +17,8 @@ mongoose.model('Decorated', DecoratedSchema);
 
 var collection = 'decorated_' + random();
 
-describe('schema.onthefly', function () {
-  it('setting should cache the schema type and cast values appropriately', function (done) {
+describe('schema.onthefly', function() {
+  it('setting should cache the schema type and cast values appropriately', function(done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
@@ -29,7 +29,7 @@ describe('schema.onthefly', function () {
     done();
   });
 
-  it('should be local to the particular document', function (done) {
+  it('should be local to the particular document', function(done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
@@ -44,7 +44,7 @@ describe('schema.onthefly', function () {
     done();
   });
 
-  it('querying a document that had an on the fly schema should work', function (done) {
+  it('querying a document that had an on the fly schema should work', function(done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
@@ -52,10 +52,10 @@ describe('schema.onthefly', function () {
     // Interpret adhoc as a Number
     post.set('adhoc', '9', Number);
     assert.equal(9, post.get('adhoc').valueOf());
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
       assert.strictEqual(null, err);
-      Decorated.findById(post.id, function (err, found) {
+      Decorated.findById(post.id, function(err, found) {
         db.close();
         assert.strictEqual(null, err);
         assert.equal(9, found.get('adhoc'));
@@ -83,7 +83,7 @@ describe('schema.onthefly', function () {
     });
   });
 
-  it('on the fly Embedded Array schemas should cast properly', function (done) {
+  it('on the fly Embedded Array schemas should cast properly', function(done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
@@ -94,7 +94,7 @@ describe('schema.onthefly', function () {
     done();
   });
 
-  it('on the fly Embedded Array schemas should get from a fresh queried document properly', function (done) {
+  it('on the fly Embedded Array schemas should get from a fresh queried document properly', function(done) {
     var db = start(),
         Decorated = db.model('Decorated', collection);
 
@@ -102,9 +102,9 @@ describe('schema.onthefly', function () {
         ModeratorSchema = new Schema({name: String, ranking: Number});
     post.set('moderators', [{name: 'alex trebek', ranking: '1'}], [ModeratorSchema]);
     assert.equal(post.get('moderators')[0].name, 'alex trebek');
-    post.save(function (err) {
+    post.save(function(err) {
       assert.ifError(err);
-      Decorated.findById(post.id, function (err, found) {
+      Decorated.findById(post.id, function(err, found) {
         db.close();
         assert.ifError(err);
         var rankingPreCast = found.get('moderators')[0].ranking;
@@ -121,7 +121,7 @@ describe('schema.onthefly', function () {
     });
   });
 
-  it('casts on get() (gh-2360)', function (done) {
+  it('casts on get() (gh-2360)', function(done) {
     var db = start();
     var Decorated = db.model('gh2360', DecoratedSchema, 'gh2360');
 
diff --git a/test/schema.select.test.js b/test/schema.select.test.js
index e6e44aff89c..dcbc68f7665 100644
--- a/test/schema.select.test.js
+++ b/test/schema.select.test.js
@@ -8,8 +8,8 @@ var start = require('./common'),
     random = require('../lib/utils').random,
     Schema = mongoose.Schema;
 
-describe('schema select option', function () {
-  it('excluding paths through schematype', function (done) {
+describe('schema select option', function() {
+  it('excluding paths through schematype', function(done) {
     var db = start();
 
     var schema = new Schema({
@@ -19,7 +19,7 @@ describe('schema select option', function () {
     });
 
     var S = db.model('ExcludingBySchemaType', schema);
-    S.create({thin: true, name: 'the excluded', docs: [{bool: true, name: 'test'}]}, function (err, s) {
+    S.create({thin: true, name: 'the excluded', docs: [{bool: true, name: 'test'}]}, function(err, s) {
       assert.ifError(err);
       assert.equal(s.name, 'the excluded');
       assert.equal(s.docs[0].name, 'test');
@@ -55,7 +55,7 @@ describe('schema select option', function () {
     });
   });
 
-  it('including paths through schematype', function (done) {
+  it('including paths through schematype', function(done) {
     var db = start();
 
     var schema = new Schema({
@@ -65,7 +65,7 @@ describe('schema select option', function () {
     });
 
     var S = db.model('IncludingBySchemaType', schema);
-    S.create({thin: true, name: 'the included', docs: [{bool: true, name: 'test'}]}, function (err, s) {
+    S.create({thin: true, name: 'the included', docs: [{bool: true, name: 'test'}]}, function(err, s) {
       assert.ifError(err);
       assert.equal(s.name, 'the included');
       assert.equal(s.docs[0].name, 'test');
@@ -89,11 +89,11 @@ describe('schema select option', function () {
         }
       }
 
-      S.findById(s).select('-thin -docs.bool').exec(function (err, res) {
+      S.findById(s).select('-thin -docs.bool').exec(function(err, res) {
         cb(err, res);
-        S.find({_id: s._id}).select('thin docs.bool').exec(function (err, res) {
+        S.find({_id: s._id}).select('thin docs.bool').exec(function(err, res) {
           cb(err, res);
-          S.findOneAndUpdate({_id: s._id}, {thin: false}, function (err, s) {
+          S.findOneAndUpdate({_id: s._id}, {thin: false}, function(err, s) {
             cb(err, s);
             S.findOneAndRemove({_id: s._id}, cb);
           });
@@ -102,10 +102,10 @@ describe('schema select option', function () {
     });
   });
 
-  describe('overriding schematype select options', function () {
+  describe('overriding schematype select options', function() {
     var db, selected, excluded, S, E;
 
-    before(function () {
+    before(function() {
       db = start();
 
       selected = new Schema({
@@ -123,15 +123,15 @@ describe('schema select option', function () {
       E = db.model('OverriddingExcludedBySchemaType', excluded);
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    describe('works', function () {
-      describe('for inclusions', function () {
+    describe('works', function() {
+      describe('for inclusions', function() {
         var s;
-        before(function (done) {
-          S.create({thin: true, name: 'the included', docs: [{name: 'test', bool: true}]}, function (err, s_) {
+        before(function(done) {
+          S.create({thin: true, name: 'the included', docs: [{name: 'test', bool: true}]}, function(err, s_) {
             assert.ifError(err);
             s = s_;
             assert.equal(s.name, 'the included');
@@ -139,8 +139,8 @@ describe('schema select option', function () {
             done();
           });
         });
-        it('with find', function (done) {
-          S.find({_id: s._id}).select('thin name docs.bool docs.name').exec(function (err, s) {
+        it('with find', function(done) {
+          S.find({_id: s._id}).select('thin name docs.bool docs.name').exec(function(err, s) {
             assert.ifError(err);
             assert.ok(s && s.length > 0, 'no document found');
             s = s[0];
@@ -155,8 +155,8 @@ describe('schema select option', function () {
             done();
           });
         });
-        it('for findById', function (done) {
-          S.findById(s).select('-name -docs.name').exec(function (err, s) {
+        it('for findById', function(done) {
+          S.findById(s).select('-name -docs.name').exec(function(err, s) {
             assert.strictEqual(null, err);
             assert.equal(false, s.isSelected('name'));
             assert.equal(true, s.isSelected('thin'));
@@ -169,8 +169,8 @@ describe('schema select option', function () {
             done();
           });
         });
-        it('with findOneAndUpdate', function (done) {
-          S.findOneAndUpdate({_id: s._id}, {name: 'changed'}, {'new': true}).select('thin name docs.bool docs.name').exec(function (err, s) {
+        it('with findOneAndUpdate', function(done) {
+          S.findOneAndUpdate({_id: s._id}, {name: 'changed'}, {'new': true}).select('thin name docs.bool docs.name').exec(function(err, s) {
             assert.ifError(err);
             assert.strictEqual(true, s.isSelected('name'));
             assert.strictEqual(true, s.isSelected('thin'));
@@ -183,8 +183,8 @@ describe('schema select option', function () {
             done();
           });
         });
-        it('for findByIdAndUpdate', function (done) {
-          S.findByIdAndUpdate(s, {thin: false}, {'new': true}).select('-name -docs.name').exec(function (err, s) {
+        it('for findByIdAndUpdate', function(done) {
+          S.findByIdAndUpdate(s, {thin: false}, {'new': true}).select('-name -docs.name').exec(function(err, s) {
             assert.strictEqual(null, err);
             assert.equal(false, s.isSelected('name'));
             assert.equal(true, s.isSelected('thin'));
@@ -199,10 +199,10 @@ describe('schema select option', function () {
         });
       });
 
-      describe('for exclusions', function () {
+      describe('for exclusions', function() {
         var e;
-        before(function (done) {
-          E.create({thin: true, name: 'the excluded', docs: [{name: 'test', bool: true}]}, function (err, e_) {
+        before(function(done) {
+          E.create({thin: true, name: 'the excluded', docs: [{name: 'test', bool: true}]}, function(err, e_) {
             e = e_;
             assert.ifError(err);
             assert.equal(e.name, 'the excluded');
@@ -210,8 +210,8 @@ describe('schema select option', function () {
             done();
           });
         });
-        it('with find', function (done) {
-          E.find({_id: e._id}).select('thin name docs.name docs.bool').exec(function (err, e) {
+        it('with find', function(done) {
+          E.find({_id: e._id}).select('thin name docs.name docs.bool').exec(function(err, e) {
             e = e[0];
             assert.strictEqual(null, err);
             assert.equal(true, e.isSelected('name'));
@@ -225,8 +225,8 @@ describe('schema select option', function () {
             done();
           });
         });
-        it('with findById', function (done) {
-          E.findById(e).select('-name -docs.name').exec(function (err, e) {
+        it('with findById', function(done) {
+          E.findById(e).select('-name -docs.name').exec(function(err, e) {
             assert.strictEqual(null, err);
             assert.equal(e.isSelected('name'), false);
             assert.equal(e.isSelected('thin'), true);
@@ -239,8 +239,8 @@ describe('schema select option', function () {
             done();
           });
         });
-        it('with findOneAndUpdate', function (done) {
-          E.findOneAndUpdate({_id: e._id}, {name: 'changed'}, {'new': true}).select('thin name docs.name docs.bool').exec(function (err, e) {
+        it('with findOneAndUpdate', function(done) {
+          E.findOneAndUpdate({_id: e._id}, {name: 'changed'}, {'new': true}).select('thin name docs.name docs.bool').exec(function(err, e) {
             assert.strictEqual(null, err);
             assert.equal(true, e.isSelected('name'));
             assert.equal(true, e.isSelected('thin'));
@@ -253,8 +253,8 @@ describe('schema select option', function () {
             done();
           });
         });
-        it('with findOneAndRemove', function (done) {
-          E.findOneAndRemove({_id: e._id}).select('-name -docs.name').exec(function (err, e) {
+        it('with findOneAndRemove', function(done) {
+          E.findOneAndRemove({_id: e._id}).select('-name -docs.name').exec(function(err, e) {
             assert.strictEqual(null, err);
             assert.equal(e.isSelected('name'), false);
             assert.equal(e.isSelected('thin'), true);
@@ -271,8 +271,8 @@ describe('schema select option', function () {
     });
   });
 
-  describe('exclusion in root schema should override child schema', function () {
-    it('works (gh-1333)', function (done) {
+  describe('exclusion in root schema should override child schema', function() {
+    it('works (gh-1333)', function(done) {
       var m = new mongoose.Mongoose();
       var child = new Schema({
         name1: {type: String, select: false},
@@ -293,8 +293,8 @@ describe('schema select option', function () {
     });
   });
 
-  describe('forcing inclusion of a deselected schema path', function () {
-    it('works', function (done) {
+  describe('forcing inclusion of a deselected schema path', function() {
+    it('works', function(done) {
       var db = start();
       var excluded = new Schema({
         thin: Boolean,
@@ -303,12 +303,12 @@ describe('schema select option', function () {
       });
 
       var M = db.model('ForcedInclusionOfPath', excluded);
-      M.create({thin: false, name: '1 meter', docs: [{name: 'test', bool: false}]}, function (err, d) {
+      M.create({thin: false, name: '1 meter', docs: [{name: 'test', bool: false}]}, function(err, d) {
         assert.ifError(err);
 
         M.findById(d)
         .select('+name +docs.name')
-        .exec(function (err, doc) {
+        .exec(function(err, doc) {
           assert.ifError(err);
           assert.equal(false, doc.thin);
           assert.equal('1 meter', doc.name);
@@ -318,7 +318,7 @@ describe('schema select option', function () {
 
           M.findById(d)
           .select('+name -thin +docs.name -docs.bool')
-          .exec(function (err, doc) {
+          .exec(function(err, doc) {
             assert.ifError(err);
             assert.equal(undefined, doc.thin);
             assert.equal('1 meter', doc.name);
@@ -328,7 +328,7 @@ describe('schema select option', function () {
 
             M.findById(d)
             .select('-thin +name -docs.bool +docs.name')
-            .exec(function (err, doc) {
+            .exec(function(err, doc) {
               assert.ifError(err);
               assert.equal(undefined, doc.thin);
               assert.equal('1 meter', doc.name);
@@ -338,7 +338,7 @@ describe('schema select option', function () {
 
               M.findById(d)
               .select('-thin -docs.bool')
-              .exec(function (err, doc) {
+              .exec(function(err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(undefined, doc.thin);
@@ -354,18 +354,18 @@ describe('schema select option', function () {
       });
     });
 
-    it('works with query.slice (gh-1370)', function (done) {
+    it('works with query.slice (gh-1370)', function(done) {
       var db = start();
       var M = db.model('1370', new Schema({many: {type: [String], select: false}}));
 
-      M.create({many: ['1', '2', '3', '4', '5']}, function (err) {
+      M.create({many: ['1', '2', '3', '4', '5']}, function(err) {
         if (err) {
           return done(err);
         }
 
         var query = M.findOne().select('+many').where('many').slice(2);
 
-        query.exec(function (err, doc) {
+        query.exec(function(err, doc) {
           if (err) {
             return done(err);
           }
@@ -376,7 +376,7 @@ describe('schema select option', function () {
     });
   });
 
-  it('conflicting schematype path selection should not error', function (done) {
+  it('conflicting schematype path selection should not error', function(done) {
     var db = start();
 
     var schema = new Schema({
@@ -386,7 +386,7 @@ describe('schema select option', function () {
     });
 
     var S = db.model('ConflictingBySchemaType', schema);
-    S.create({thin: true, name: 'bing', conflict: 'crosby'}, function (err, s) {
+    S.create({thin: true, name: 'bing', conflict: 'crosby'}, function(err, s) {
       assert.strictEqual(null, err);
       assert.equal(s.name, 'bing');
       assert.equal(s.conflict, 'crosby');
@@ -410,7 +410,7 @@ describe('schema select option', function () {
     });
   });
 
-  it('selecting _id works with excluded schematype path', function (done) {
+  it('selecting _id works with excluded schematype path', function(done) {
     var db = start();
 
     var schema = new Schema({
@@ -418,10 +418,10 @@ describe('schema select option', function () {
     });
 
     var M = db.model('SelectingOnly_idWithExcludedSchemaType', schema);
-    M.find().select('_id -name').exec(function (err) {
+    M.find().select('_id -name').exec(function(err) {
       assert.ok(err instanceof Error, 'conflicting path selection error should be instance of Error');
 
-      M.find().select('_id').exec(function (err) {
+      M.find().select('_id').exec(function(err) {
         db.close();
         assert.ifError(err, err && err.stack);
         done();
@@ -429,7 +429,7 @@ describe('schema select option', function () {
     });
   });
 
-  it('selecting _id works with excluded schematype path on sub doc', function (done) {
+  it('selecting _id works with excluded schematype path on sub doc', function(done) {
     var db = start();
 
     var schema = new Schema({
@@ -437,10 +437,10 @@ describe('schema select option', function () {
     });
 
     var M = db.model('SelectingOnly_idWithExcludedSchemaType', schema);
-    M.find().select('_id -docs.name').exec(function (err) {
+    M.find().select('_id -docs.name').exec(function(err) {
       assert.ok(err instanceof Error, 'conflicting path selection error should be instance of Error');
 
-      M.find().select('_id').exec(function (err) {
+      M.find().select('_id').exec(function(err) {
         db.close();
         assert.ifError(err, err && err.stack);
         done();
@@ -448,7 +448,7 @@ describe('schema select option', function () {
     });
   });
 
-  it('all inclusive/exclusive combos work', function (done) {
+  it('all inclusive/exclusive combos work', function(done) {
     var db = start();
     var coll = 'inclusiveexclusivecomboswork_' + random();
 
@@ -471,21 +471,21 @@ describe('schema select option', function () {
     var T = db.model('InclusiveExclusiveCombosWorkWithSchemaSelectionTrue', schema2);
 
     function useId(M, id, cb) {
-      M.findOne().select('_id -name').exec(function (err, d) {
+      M.findOne().select('_id -name').exec(function(err, d) {
         assert.ok(err);
         assert.ok(!d);
-        M.findOne().select('-_id name').exec(function (err, d) {
+        M.findOne().select('-_id name').exec(function(err, d) {
           // mongo special case for exclude _id + include path
           assert.ifError(err);
           assert.equal(undefined, d.id);
           assert.equal('ssd', d.name);
           assert.equal(undefined, d.age);
-          M.findOne().select('-_id -name').exec(function (err, d) {
+          M.findOne().select('-_id -name').exec(function(err, d) {
             assert.ifError(err);
             assert.equal(undefined, d.id);
             assert.equal(undefined, d.name);
             assert.equal(0, d.age);
-            M.findOne().select('_id name').exec(function (err, d) {
+            M.findOne().select('_id name').exec(function(err, d) {
               assert.ifError(err);
               assert.equal(id, d.id);
               assert.equal('ssd', d.name);
@@ -498,18 +498,18 @@ describe('schema select option', function () {
     }
 
     function nonId(M, id, cb) {
-      M.findOne().select('age -name').exec(function (err, d) {
+      M.findOne().select('age -name').exec(function(err, d) {
         assert.ok(err);
         assert.ok(!d);
-        M.findOne().select('-age name').exec(function (err, d) {
+        M.findOne().select('-age name').exec(function(err, d) {
           assert.ok(err);
           assert.ok(!d);
-          M.findOne().select('-age -name').exec(function (err, d) {
+          M.findOne().select('-age -name').exec(function(err, d) {
             assert.ifError(err);
             assert.equal(id, d.id);
             assert.equal(undefined, d.name);
             assert.equal(undefined, d.age);
-            M.findOne().select('age name').exec(function (err, d) {
+            M.findOne().select('age name').exec(function(err, d) {
               assert.ifError(err);
               assert.equal(id, d.id);
               assert.equal('ssd', d.name);
@@ -521,15 +521,15 @@ describe('schema select option', function () {
       });
     }
 
-    M.create({name: 'ssd', age: 0}, function (err, d) {
+    M.create({name: 'ssd', age: 0}, function(err, d) {
       assert.ifError(err);
       var id = d.id;
-      useId(M, id, function () {
-        nonId(M, id, function () {
-          useId(S, id, function () {
-            nonId(S, id, function () {
-              useId(T, id, function () {
-                nonId(T, id, function () {
+      useId(M, id, function() {
+        nonId(M, id, function() {
+          useId(S, id, function() {
+            nonId(S, id, function() {
+              useId(T, id, function() {
+                nonId(T, id, function() {
                   db.close();
                   done();
                 });
@@ -541,7 +541,7 @@ describe('schema select option', function () {
     });
   });
 
-  it('initializes nested defaults with selected objects (gh-2629)', function (done) {
+  it('initializes nested defaults with selected objects (gh-2629)', function(done) {
     var NestedSchema = new mongoose.Schema({
       nested: {
         name: {type: String, default: 'val'}
@@ -553,9 +553,9 @@ describe('schema select option', function () {
 
     var doc = new Model();
     doc.nested.name = undefined;
-    doc.save(function (error) {
+    doc.save(function(error) {
       assert.ifError(error);
-      Model.findOne({}, {nested: 1}, function (error, doc) {
+      Model.findOne({}, {nested: 1}, function(error, doc) {
         assert.ifError(error);
         assert.equal('val', doc.nested.name);
         db.close(done);
diff --git a/test/schema.test.js b/test/schema.test.js
index 66ca25ca9f4..b574c60fb08 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -41,11 +41,11 @@ TestDocument.prototype.$__setSchema(new Schema({
  * Test.
  */
 
-describe('schema', function () {
-  describe('nested fields with same name', function () {
+describe('schema', function() {
+  describe('nested fields with same name', function() {
     var db, NestedModel;
 
-    before(function () {
+    before(function() {
       db = start();
       var NestedSchema = new Schema({
         a: {
@@ -59,11 +59,11 @@ describe('schema', function () {
       NestedModel = db.model('Nested', NestedSchema);
     });
 
-    after(function () {
+    after(function() {
       db.close();
     });
 
-    it('don\'t disappear', function (done) {
+    it('don\'t disappear', function(done) {
       var n = new NestedModel({
         a: {
           b: {
@@ -73,9 +73,9 @@ describe('schema', function () {
         }, b: 'foobar'
       });
 
-      n.save(function (err) {
+      n.save(function(err) {
         assert.ifError(err);
-        NestedModel.findOne({_id: n._id}, function (err, nm) {
+        NestedModel.findOne({_id: n._id}, function(err, nm) {
           assert.ifError(err);
 
           // make sure no field has disappeared
@@ -93,19 +93,19 @@ describe('schema', function () {
   });
 
 
-  it('can be created without the "new" keyword', function (done) {
+  it('can be created without the "new" keyword', function(done) {
     var schema = new Schema({name: String});
     assert.ok(schema instanceof Schema);
     done();
   });
 
-  it('does expose a property for duck-typing instanceof', function (done) {
+  it('does expose a property for duck-typing instanceof', function(done) {
     var schema = new Schema({name: String});
     assert.ok(schema.instanceOfSchema);
     done();
   });
 
-  it('supports different schematypes', function (done) {
+  it('supports different schematypes', function(done) {
     var Checkin = new Schema({
       date: Date,
       location: {
@@ -189,7 +189,7 @@ describe('schema', function () {
     done();
   });
 
-  it('supports dot notation for path accessors', function (done) {
+  it('supports dot notation for path accessors', function(done) {
     var Racoon = new Schema({
       name: {type: String, enum: ['Edwald', 'Tobi']},
       age: Number
@@ -216,7 +216,7 @@ describe('schema', function () {
     done();
   });
 
-  it('allows paths nested > 2 levels', function (done) {
+  it('allows paths nested > 2 levels', function(done) {
     var Nested = new Schema({
       first: {
         second: {
@@ -228,18 +228,18 @@ describe('schema', function () {
     done();
   });
 
-  it('default definition', function (done) {
+  it('default definition', function(done) {
     var Test = new Schema({
       simple: {$type: String, default: 'a'},
       array: {$type: Array, default: [1, 2, 3, 4, 5]},
       arrayX: {$type: Array, default: 9},
       arrayFn: {
-        $type: Array, default: function () {
+        $type: Array, default: function() {
           return [8];
         }
       },
       callback: {
-        $type: Number, default: function () {
+        $type: Number, default: function() {
           assert.equal('b', this.a);
           return '3';
         }
@@ -261,7 +261,7 @@ describe('schema', function () {
     done();
   });
 
-  it('Mixed defaults can be empty arrays', function (done) {
+  it('Mixed defaults can be empty arrays', function(done) {
     var Test = new Schema({
       mixed1: {type: Mixed, default: []},
       mixed2: {type: Mixed, default: Array}
@@ -274,8 +274,8 @@ describe('schema', function () {
     done();
   });
 
-  describe('casting', function () {
-    it('number', function (done) {
+  describe('casting', function() {
+    it('number', function(done) {
       var Tobi = new Schema({
         age: Number
       });
@@ -289,8 +289,8 @@ describe('schema', function () {
       done();
     });
 
-    describe('string', function () {
-      it('works', function (done) {
+    describe('string', function() {
+      it('works', function(done) {
         var Tobi = new Schema({
           nickname: String
         });
@@ -298,7 +298,7 @@ describe('schema', function () {
         function Test() {
         }
 
-        Test.prototype.toString = function () {
+        Test.prototype.toString = function() {
           return 'woot';
         };
 
@@ -313,7 +313,7 @@ describe('schema', function () {
       });
     });
 
-    it('date', function (done) {
+    it('date', function(done) {
       var Loki = new Schema({
         birth_date: {type: Date}
       });
@@ -326,7 +326,7 @@ describe('schema', function () {
       done();
     });
 
-    it('objectid', function (done) {
+    it('objectid', function(done) {
       var Loki = new Schema({
         owner: {type: ObjectId}
       });
@@ -344,7 +344,7 @@ describe('schema', function () {
       done();
     });
 
-    it('array', function (done) {
+    it('array', function(done) {
       var Loki = new Schema({
         oids: [ObjectId],
         dates: [Date],
@@ -402,7 +402,7 @@ describe('schema', function () {
       done();
     });
 
-    it('boolean', function (done) {
+    it('boolean', function(done) {
       var Animal = new Schema({
         isFerret: {type: Boolean, required: true}
       });
@@ -422,30 +422,30 @@ describe('schema', function () {
     });
   });
 
-  it('methods declaration', function (done) {
+  it('methods declaration', function(done) {
     var a = new Schema;
-    a.method('test', function () {
+    a.method('test', function() {
     });
     a.method({
-      a: function () {
+      a: function() {
       },
-      b: function () {
+      b: function() {
       }
     });
     assert.equal(3, Object.keys(a.methods).length);
     done();
   });
 
-  it('static declaration', function (done) {
+  it('static declaration', function(done) {
     var a = new Schema;
-    a.static('test', function () {
+    a.static('test', function() {
     });
     a.static({
-      a: function () {
+      a: function() {
       },
-      b: function () {
+      b: function() {
       },
-      c: function () {
+      c: function() {
       }
     });
 
@@ -453,8 +453,8 @@ describe('schema', function () {
     done();
   });
 
-  describe('setters', function () {
-    it('work', function (done) {
+  describe('setters', function() {
+    it('work', function(done) {
       function lowercase(v) {
         return v.toLowerCase();
       }
@@ -466,7 +466,7 @@ describe('schema', function () {
       assert.equal('woot', Tobi.path('name').applySetters('WOOT'));
       assert.equal(1, Tobi.path('name').setters.length);
 
-      Tobi.path('name').set(function (v) {
+      Tobi.path('name').set(function(v) {
         return v + 'WOOT';
       });
 
@@ -475,7 +475,7 @@ describe('schema', function () {
       done();
     });
 
-    it('order', function (done) {
+    it('order', function(done) {
       function extract(v) {
         return (v && v._id)
             ? v._id
@@ -496,7 +496,7 @@ describe('schema', function () {
       done();
     });
 
-    it('scope', function (done) {
+    it('scope', function(done) {
       function lowercase(v, self) {
         assert.equal('b', this.a);
         assert.equal('name', self.path);
@@ -511,7 +511,7 @@ describe('schema', function () {
       done();
     });
 
-    it('casting', function (done) {
+    it('casting', function(done) {
       function last(v) {
         assert.equal('number', typeof v);
         assert.equal(0, v);
@@ -531,8 +531,8 @@ describe('schema', function () {
       done();
     });
 
-    describe('array', function () {
-      it('object setters will be applied for each object in array', function (done) {
+    describe('array', function() {
+      it('object setters will be applied for each object in array', function(done) {
         var Tobi = new Schema({
           names: [{type: String, lowercase: true, trim: true}]
         });
@@ -544,8 +544,8 @@ describe('schema', function () {
       });
     });
 
-    describe('string', function () {
-      it('lowercase', function (done) {
+    describe('string', function() {
+      it('lowercase', function(done) {
         var Tobi = new Schema({
           name: {type: String, lowercase: true}
         });
@@ -554,7 +554,7 @@ describe('schema', function () {
         assert.equal('1977', Tobi.path('name').applySetters(1977));
         done();
       });
-      it('uppercase', function (done) {
+      it('uppercase', function(done) {
         var Tobi = new Schema({
           name: {type: String, uppercase: true}
         });
@@ -563,7 +563,7 @@ describe('schema', function () {
         assert.equal('1977', Tobi.path('name').applySetters(1977));
         done();
       });
-      it('trim', function (done) {
+      it('trim', function(done) {
         var Tobi = new Schema({
           name: {type: String, uppercase: true, trim: true}
         });
@@ -574,7 +574,7 @@ describe('schema', function () {
       });
     });
 
-    it('applying when none have been defined', function (done) {
+    it('applying when none have been defined', function(done) {
       var Tobi = new Schema({
         name: String
       });
@@ -583,7 +583,7 @@ describe('schema', function () {
       done();
     });
 
-    it('assignment of non-functions throw', function (done) {
+    it('assignment of non-functions throw', function(done) {
       var schema = new Schema({fun: String});
       var g;
 
@@ -599,8 +599,8 @@ describe('schema', function () {
     });
   });
 
-  describe('getters', function () {
-    it('work', function (done) {
+  describe('getters', function() {
+    it('work', function(done) {
       function woot(v) {
         return v + ' woot';
       }
@@ -613,7 +613,7 @@ describe('schema', function () {
       assert.equal('test woot', Tobi.path('name').applyGetters('test'));
       done();
     });
-    it('order', function (done) {
+    it('order', function(done) {
       function format(v) {
         return v
             ? '$' + v
@@ -627,7 +627,7 @@ describe('schema', function () {
       assert.equal('$30', Tobi.path('name').applyGetters(30, {a: 'b'}));
       done();
     });
-    it('scope', function (done) {
+    it('scope', function(done) {
       function woot(v, self) {
         assert.equal('b', this.a);
         assert.equal('name', self.path);
@@ -641,7 +641,7 @@ describe('schema', function () {
       assert.equal('yep', Tobi.path('name').applyGetters('YEP', {a: 'b'}));
       done();
     });
-    it('casting', function (done) {
+    it('casting', function(done) {
       function last(v) {
         assert.equal('number', typeof v);
         assert.equal(0, v);
@@ -660,7 +660,7 @@ describe('schema', function () {
       assert.equal('last', Tobi.path('name').applyGetters('woot'));
       done();
     });
-    it('applying when none have been defined', function (done) {
+    it('applying when none have been defined', function(done) {
       var Tobi = new Schema({
         name: String
       });
@@ -668,7 +668,7 @@ describe('schema', function () {
       assert.equal('woot', Tobi.path('name').applyGetters('woot'));
       done();
     });
-    it('assignment of non-functions throw', function (done) {
+    it('assignment of non-functions throw', function(done) {
       var schema = new Schema({fun: String});
       var g;
 
@@ -682,7 +682,7 @@ describe('schema', function () {
       assert.equal(g.message, 'A getter must be a function.');
       done();
     });
-    it('auto _id', function (done) {
+    it('auto _id', function(done) {
       var schema = new Schema({
         name: String
       });
@@ -711,7 +711,7 @@ describe('schema', function () {
       done();
     });
 
-    it('auto id', function (done) {
+    it('auto id', function(done) {
       var schema = new Schema({
         name: String
       });
@@ -741,28 +741,28 @@ describe('schema', function () {
     });
   });
 
-  describe('hooks', function () {
-    it('registration', function (done) {
+  describe('hooks', function() {
+    it('registration', function(done) {
       var Tobi = new Schema();
 
-      Tobi.pre('save', function () {
+      Tobi.pre('save', function() {
       });
       assert.equal(Tobi.callQueue.length, 3);
 
-      Tobi.post('save', function () {
+      Tobi.post('save', function() {
       });
       assert.equal(Tobi.callQueue.length, 4);
 
-      Tobi.pre('save', function () {
+      Tobi.pre('save', function() {
       });
       assert.equal(Tobi.callQueue.length, 5);
       done();
     });
   });
 
-  describe('indexes', function () {
-    describe('definition', function () {
-      it('basic', function (done) {
+  describe('indexes', function() {
+    describe('definition', function() {
+      it('basic', function(done) {
         var Tobi = new Schema({
           name: {type: String, index: true}
         });
@@ -825,7 +825,7 @@ describe('schema', function () {
 
         done();
       });
-      it('compound', function (done) {
+      it('compound', function(done) {
         var Tobi = new Schema({
           name: {type: String, index: true},
           last: {type: Number, sparse: true},
@@ -848,12 +848,12 @@ describe('schema', function () {
     });
   });
 
-  describe('plugins', function () {
-    it('work', function (done) {
+  describe('plugins', function() {
+    it('work', function(done) {
       var Tobi = new Schema,
           called = false;
 
-      Tobi.plugin(function (schema) {
+      Tobi.plugin(function(schema) {
         assert.equal(schema, Tobi);
         called = true;
       });
@@ -863,8 +863,8 @@ describe('schema', function () {
     });
   });
 
-  describe('options', function () {
-    it('defaults are set', function (done) {
+  describe('options', function() {
+    it('defaults are set', function(done) {
       var Tobi = new Schema();
 
       assert.equal('object', typeof Tobi.options);
@@ -879,7 +879,7 @@ describe('schema', function () {
       done();
     });
 
-    it('setting', function (done) {
+    it('setting', function(done) {
       var Tobi = new Schema({}, {collection: 'users'});
 
       Tobi.set('a', 'b');
@@ -1034,8 +1034,8 @@ describe('schema', function () {
     });
   });
 
-  describe('virtuals', function () {
-    it('works', function (done) {
+  describe('virtuals', function() {
+    it('works', function(done) {
       var Contact = new Schema({
         firstName: String,
         lastName: String
@@ -1043,10 +1043,10 @@ describe('schema', function () {
 
       Contact
       .virtual('fullName')
-      .get(function () {
+      .get(function() {
         return this.get('firstName') + ' ' + this.get('lastName');
       })
-      .set(function (fullName) {
+      .set(function(fullName) {
         var split = fullName.split(' ');
         this.set('firstName', split[0]);
         this.set('lastName', split[1]);
@@ -1056,25 +1056,25 @@ describe('schema', function () {
       done();
     });
 
-    describe('id', function () {
-      it('default creation of id can be overridden (gh-298)', function (done) {
-        assert.doesNotThrow(function () {
+    describe('id', function() {
+      it('default creation of id can be overridden (gh-298)', function(done) {
+        assert.doesNotThrow(function() {
           new Schema({id: String});
         });
         done();
       });
-      it('disabling', function (done) {
+      it('disabling', function(done) {
         var schema = new Schema({name: String}, {noVirtualId: true});
         assert.strictEqual(undefined, schema.virtuals.id);
         done();
       });
     });
 
-    describe('getter', function () {
-      it('scope', function (done) {
+    describe('getter', function() {
+      it('scope', function(done) {
         var Tobi = new Schema;
 
-        Tobi.virtual('name').get(function (v, self) {
+        Tobi.virtual('name').get(function(v, self) {
           assert.equal('b', this.a);
           assert.equal('name', self.path);
           return v.toLowerCase();
@@ -1085,11 +1085,11 @@ describe('schema', function () {
       });
     });
 
-    describe('setter', function () {
-      it('scope', function (done) {
+    describe('setter', function() {
+      it('scope', function(done) {
         var Tobi = new Schema;
 
-        Tobi.virtual('name').set(function (v, self) {
+        Tobi.virtual('name').set(function(v, self) {
           assert.equal('b', this.a);
           assert.equal('name', self.path);
           return v.toLowerCase();
@@ -1101,8 +1101,8 @@ describe('schema', function () {
     });
   });
 
-  describe('other contexts', function () {
-    it('work', function (done) {
+  describe('other contexts', function() {
+    it('work', function(done) {
       var str = 'code = {' +
           '  name: String' +
           ', arr1: Array ' +
@@ -1129,16 +1129,16 @@ describe('schema', function () {
     });
   });
 
-  describe('#add()', function () {
-    it('does not polute existing paths', function (done) {
+  describe('#add()', function() {
+    it('does not polute existing paths', function(done) {
       var o = {name: String};
       var s = new Schema(o);
 
-      assert.throws(function () {
+      assert.throws(function() {
         s.add({age: Number}, 'name.');
       }, /Cannot set nested path/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         s.add({age: {x: Number}}, 'name.');
       }, /Cannot set nested path/);
       assert.equal(false, ('age' in o.name));
@@ -1146,11 +1146,11 @@ describe('schema', function () {
       o = {name: 'string'};
       s = new Schema(o);
 
-      assert.throws(function () {
+      assert.throws(function() {
         s.add({age: Number}, 'name.');
       }, /Cannot set nested path/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         s.add({age: {x: Number}}, 'name.');
       }, /Cannot set nested path/);
 
@@ -1158,7 +1158,7 @@ describe('schema', function () {
       done();
     });
 
-    it('merging nested objects (gh-662)', function (done) {
+    it('merging nested objects (gh-662)', function(done) {
       var db = start();
 
       var MergedSchema = new Schema({
@@ -1188,9 +1188,9 @@ describe('schema', function () {
         }
       });
 
-      merged.save(function (err) {
+      merged.save(function(err) {
         assert.ifError(err);
-        Merged.findById(merged.id, function (err, found) {
+        Merged.findById(merged.id, function(err, found) {
           db.close();
           assert.ifError(err);
           assert.equal(found.a.foo, 'baz');
@@ -1201,7 +1201,7 @@ describe('schema', function () {
     });
   });
 
-  it('debugging msgs', function (done) {
+  it('debugging msgs', function(done) {
     var err;
     try {
       new Schema({name: {first: null}});
@@ -1218,8 +1218,8 @@ describe('schema', function () {
     done();
   });
 
-  describe('construction', function () {
-    it('array of object literal missing a type is interpreted as DocumentArray', function (done) {
+  describe('construction', function() {
+    it('array of object literal missing a type is interpreted as DocumentArray', function(done) {
       var goose = new mongoose.Mongoose;
       var s = new Schema({
         arr: [
@@ -1234,7 +1234,7 @@ describe('schema', function () {
       done();
     });
 
-    it('array of object literal with type.type is interpreted as DocumentArray', function (done) {
+    it('array of object literal with type.type is interpreted as DocumentArray', function(done) {
       var goose = new mongoose.Mongoose;
       var s = new Schema({
         arr: [
@@ -1249,7 +1249,7 @@ describe('schema', function () {
       done();
     });
 
-    it('does not alter original argument (gh-1364)', function (done) {
+    it('does not alter original argument (gh-1364)', function(done) {
       var schema = {
         ids: [{type: Schema.ObjectId, ref: 'something'}],
         a: {type: Array},
@@ -1271,7 +1271,7 @@ describe('schema', function () {
       done();
     });
 
-    it('properly gets value of plain objects when dealing with refs (gh-1606)', function (done) {
+    it('properly gets value of plain objects when dealing with refs (gh-1606)', function(done) {
       var db = start();
       var el = new Schema({title: String});
       var so = new Schema({
@@ -1284,12 +1284,12 @@ describe('schema', function () {
 
       var ele = new Element({title: 'thing'});
 
-      ele.save(function (err) {
+      ele.save(function(err) {
         assert.ifError(err);
         var s = new Some({obj: ele.toObject()});
-        s.save(function (err) {
+        s.save(function(err) {
           assert.ifError(err);
-          Some.findOne({_id: s.id}, function (err, ss) {
+          Some.findOne({_id: s.id}, function(err, ss) {
             assert.ifError(err);
             assert.equal(ss.obj, ele.id);
             db.close(done);
@@ -1299,54 +1299,54 @@ describe('schema', function () {
     });
   });
 
-  describe('property names', function () {
-    it('that conflict throw', function (done) {
+  describe('property names', function() {
+    it('that conflict throw', function(done) {
       var child = new Schema({name: String});
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           on: String,
           child: [child]
         });
       }, /`on` may not be used as a schema pathname/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           collection: String
         });
       }, /`collection` may not be used as a schema pathname/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           schema: String
         });
       }, /`schema` may not be used as a schema pathname/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           db: String
         });
       }, /`db` may not be used as a schema pathname/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           modelName: String
         });
       }, /`modelName` may not be used as a schema pathname/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           isNew: String
         });
       }, /`isNew` may not be used as a schema pathname/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           errors: String
         });
       }, /`errors` may not be used as a schema pathname/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           init: String
         });
@@ -1355,28 +1355,28 @@ describe('schema', function () {
       done();
     });
 
-    it('that do not conflict do not throw', function (done) {
-      assert.doesNotThrow(function () {
+    it('that do not conflict do not throw', function(done) {
+      assert.doesNotThrow(function() {
         new Schema({
           model: String
         });
       });
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         Schema({child: [{parent: String}]});
       });
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         Schema({child: [{parentArray: String}]});
       });
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         var s = new Schema({docs: [{path: String}]});
         var M = mongoose.model('gh-1245', s);
         new M({docs: [{path: 'works'}]});
       });
 
-      assert.doesNotThrow(function () {
+      assert.doesNotThrow(function() {
         var s = new Schema({setMaxListeners: String});
         var M = mongoose.model('setMaxListeners-as-property-name', s);
         new M({setMaxListeners: 'works'});
@@ -1385,12 +1385,12 @@ describe('schema', function () {
       done();
     });
 
-    it('permit _scope to be used (gh-1184)', function (done) {
+    it('permit _scope to be used (gh-1184)', function(done) {
       var db = start();
       var child = new Schema({_scope: Schema.ObjectId});
       var C = db.model('scope', child);
       var c = new C;
-      c.save(function (err) {
+      c.save(function(err) {
         db.close();
         assert.ifError(err);
         try {
@@ -1404,10 +1404,10 @@ describe('schema', function () {
     });
   });
 
-  describe('pathType()', function () {
+  describe('pathType()', function() {
     var schema;
 
-    before(function () {
+    before(function() {
       schema = new Schema({
         n: String,
         nest: {thing: {nests: Boolean}},
@@ -1416,8 +1416,8 @@ describe('schema', function () {
       });
     });
 
-    describe('when called on an explicit real path', function () {
-      it('returns "real"', function (done) {
+    describe('when called on an explicit real path', function() {
+      it('returns "real"', function(done) {
         assert.equal('real', schema.pathType('n'));
         assert.equal('real', schema.pathType('nest.thing.nests'));
         assert.equal('real', schema.pathType('docs'));
@@ -1427,21 +1427,21 @@ describe('schema', function () {
         done();
       });
     });
-    describe('when called on a virtual', function () {
-      it('returns virtual', function (done) {
+    describe('when called on a virtual', function() {
+      it('returns virtual', function(done) {
         assert.equal('virtual', schema.pathType('id'));
         done();
       });
     });
-    describe('when called on nested structure', function () {
-      it('returns nested', function (done) {
+    describe('when called on nested structure', function() {
+      it('returns nested', function(done) {
         assert.equal('nested', schema.pathType('nest'));
         assert.equal('nested', schema.pathType('nest.thing'));
         done();
       });
     });
-    describe('when called on undefined path', function () {
-      it('returns adHocOrUndefined', function (done) {
+    describe('when called on undefined path', function() {
+      it('returns adHocOrUndefined', function(done) {
         assert.equal('adhocOrUndefined', schema.pathType('mixed.what'));
         assert.equal('adhocOrUndefined', schema.pathType('mixed.4'));
         assert.equal('adhocOrUndefined', schema.pathType('mixed.4.thing'));
@@ -1462,7 +1462,7 @@ describe('schema', function () {
     });
   });
 
-  it('required() with doc arrays (gh-3199)', function (done) {
+  it('required() with doc arrays (gh-3199)', function(done) {
     var schema = new Schema({
       test: [{x: String}]
     });
@@ -1475,7 +1475,7 @@ describe('schema', function () {
     done();
   });
 
-  it('custom typeKey in doc arrays (gh-3560)', function (done) {
+  it('custom typeKey in doc arrays (gh-3560)', function(done) {
     var schema = new Schema({
       test: [{
         name: {$type: String}
@@ -1491,7 +1491,7 @@ describe('schema', function () {
     done();
   });
 
-  it('required for single nested schemas (gh-3562)', function (done) {
+  it('required for single nested schemas (gh-3562)', function(done) {
     var personSchema = new Schema({
       name: {type: String, required: true}
     });
@@ -1502,7 +1502,7 @@ describe('schema', function () {
     });
 
     var Band = mongoose.model('gh3562', bandSchema);
-    var band = new Band({name: "Guns N' Roses"});
+    var band = new Band({name: 'Guns N\' Roses'});
 
     assert.ok(band.validateSync());
     assert.ok(band.validateSync().errors.guitarist);
@@ -1512,8 +1512,8 @@ describe('schema', function () {
     done();
   });
 
-  describe('remove()', function () {
-    before(function () {
+  describe('remove()', function() {
+    before(function() {
       this.schema = new Schema({
         a: String,
         b: {
@@ -1527,13 +1527,13 @@ describe('schema', function () {
       });
     });
 
-    it('removes a single path', function (done) {
+    it('removes a single path', function(done) {
       this.schema.remove('a');
       assert.strictEqual(this.schema.path('a'), undefined);
       done();
     });
 
-    it('removes a nested path', function (done) {
+    it('removes a nested path', function(done) {
       this.schema.remove('b.c.d');
       assert.strictEqual(this.schema.path('b'), undefined);
       assert.strictEqual(this.schema.path('b.c'), undefined);
@@ -1541,7 +1541,7 @@ describe('schema', function () {
       done();
     });
 
-    it('removes an array of paths', function (done) {
+    it('removes an array of paths', function(done) {
       this.schema.remove(['e', 'f', 'g']);
       assert.strictEqual(this.schema.path('e'), undefined);
       assert.strictEqual(this.schema.path('f'), undefined);
diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js
index 67f4176a8f1..27d611e47d9 100644
--- a/test/schema.timestamps.test.js
+++ b/test/schema.timestamps.test.js
@@ -8,9 +8,9 @@ var start = require('./common'),
     assert = require('assert'),
     Schema = mongoose.Schema;
 
-describe('schema options.timestamps', function () {
-  describe('create schema with options.timestamps', function () {
-    it('should have createdAt and updatedAt fields', function (done) {
+describe('schema options.timestamps', function() {
+  describe('create schema with options.timestamps', function() {
+    it('should have createdAt and updatedAt fields', function(done) {
       var TestSchema = new Schema({
         name: String
       }, {
@@ -22,7 +22,7 @@ describe('schema options.timestamps', function () {
       done();
     });
 
-    it('should have created and updatedAt fields', function (done) {
+    it('should have created and updatedAt fields', function(done) {
       var TestSchema = new Schema({
         name: String
       }, {
@@ -36,7 +36,7 @@ describe('schema options.timestamps', function () {
       done();
     });
 
-    it('should have created and updated fields', function (done) {
+    it('should have created and updated fields', function(done) {
       var TestSchema = new Schema({
         name: String
       }, {
@@ -52,7 +52,7 @@ describe('schema options.timestamps', function () {
     });
   });
 
-  describe('auto update createdAt and updatedAt when create/save/update document', function () {
+  describe('auto update createdAt and updatedAt when create/save/update document', function() {
     var CatSchema = new Schema({
       name: String,
       hobby: String
@@ -61,13 +61,13 @@ describe('schema options.timestamps', function () {
     var conn = start();
     var Cat = conn.model('Cat', CatSchema);
 
-    before(function (done) {
+    before(function(done) {
       Cat.remove({}, done);
     });
 
-    it('should have fields when create', function (done) {
+    it('should have fields when create', function(done) {
       var cat = new Cat({name: 'newcat'});
-      cat.save(function (err, doc) {
+      cat.save(function(err, doc) {
         assert.ok(doc.createdAt);
         assert.ok(doc.updatedAt);
         assert.ok(doc.createdAt.getTime() === doc.updatedAt.getTime());
@@ -75,8 +75,8 @@ describe('schema options.timestamps', function () {
       });
     });
 
-    it('should have fields when create with findOneAndUpdate', function (done) {
-      Cat.findOneAndUpdate({name: 'notexistname'}, {$set: {}}, {upsert: true, 'new': true}, function (err, doc) {
+    it('should have fields when create with findOneAndUpdate', function(done) {
+      Cat.findOneAndUpdate({name: 'notexistname'}, {$set: {}}, {upsert: true, 'new': true}, function(err, doc) {
         assert.ok(doc.createdAt);
         assert.ok(doc.updatedAt);
         assert.ok(doc.createdAt.getTime() === doc.updatedAt.getTime());
@@ -84,32 +84,32 @@ describe('schema options.timestamps', function () {
       });
     });
 
-    it('should change updatedAt when save', function (done) {
-      Cat.findOne({name: 'newcat'}, function (err, doc) {
+    it('should change updatedAt when save', function(done) {
+      Cat.findOne({name: 'newcat'}, function(err, doc) {
         var old = doc.updatedAt;
 
-        doc.save(function (err, doc) {
+        doc.save(function(err, doc) {
           assert.ok(doc.updatedAt.getTime() > old.getTime());
           done();
         });
       });
     });
 
-    it('should change updatedAt when findOneAndUpdate', function (done) {
-      Cat.findOne({name: 'newcat'}, function (err, doc) {
+    it('should change updatedAt when findOneAndUpdate', function(done) {
+      Cat.findOne({name: 'newcat'}, function(err, doc) {
         var old = doc.updatedAt;
-        Cat.findOneAndUpdate({name: 'newcat'}, {$set: {hobby: 'fish'}}, {'new': true}, function (err, doc) {
+        Cat.findOneAndUpdate({name: 'newcat'}, {$set: {hobby: 'fish'}}, {'new': true}, function(err, doc) {
           assert.ok(doc.updatedAt.getTime() > old.getTime());
           done();
         });
       });
     });
 
-    it('should have fields when update', function (done) {
-      Cat.findOne({name: 'newcat'}, function (err, doc) {
+    it('should have fields when update', function(done) {
+      Cat.findOne({name: 'newcat'}, function(err, doc) {
         var old = doc.updatedAt;
-        Cat.update({name: 'newcat'}, {$set: {hobby: 'fish'}}, function () {
-          Cat.findOne({name: 'newcat'}, function (err, doc) {
+        Cat.update({name: 'newcat'}, {$set: {hobby: 'fish'}}, function() {
+          Cat.findOne({name: 'newcat'}, function(err, doc) {
             assert.ok(doc.updatedAt.getTime() > old.getTime());
             done();
           });
@@ -117,8 +117,8 @@ describe('schema options.timestamps', function () {
       });
     });
 
-    after(function (done) {
-      Cat.remove({}, function () {
+    after(function(done) {
+      Cat.remove({}, function() {
         conn.close(done);
       });
     });
diff --git a/test/schema.type.test.js b/test/schema.type.test.js
index a282c69c4df..5dfd925074f 100644
--- a/test/schema.type.test.js
+++ b/test/schema.type.test.js
@@ -7,8 +7,8 @@ var mongoose = require('./common').mongoose,
     assert = require('assert'),
     Schema = mongoose.Schema;
 
-describe('schematype', function () {
-  it('honors the selected option', function (done) {
+describe('schematype', function() {
+  it('honors the selected option', function(done) {
     var s = new Schema({thought: {type: String, select: false}});
     assert.equal(false, s.path('thought').selected);
 
@@ -17,7 +17,7 @@ describe('schematype', function () {
     done();
   });
 
-  it('properly handles specifying index in combination with unique or sparse', function (done) {
+  it('properly handles specifying index in combination with unique or sparse', function(done) {
     var s = new Schema({name: {type: String, index: true, unique: true}});
     assert.deepEqual(s.path('name')._index, {unique: true});
     s = new Schema({name: {type: String, unique: true, index: true}});
diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js
index 2ff101fdd77..dd1bc88c781 100644
--- a/test/schema.validation.test.js
+++ b/test/schema.validation.test.js
@@ -13,28 +13,28 @@ var start = require('./common'),
     DocumentObjectId = mongoose.Types.ObjectId,
     random = require('../lib/utils').random;
 
-describe('schema', function () {
-  describe('validation', function () {
-    it('invalid arguments are rejected (1044)', function (done) {
-      assert.throws(function () {
+describe('schema', function() {
+  describe('validation', function() {
+    it('invalid arguments are rejected (1044)', function(done) {
+      assert.throws(function() {
         new Schema({
           simple: {type: String, validate: 'nope'}
         });
       }, /Invalid validator/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           simple: {type: String, validate: ['nope']}
         });
       }, /Invalid validator/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           simple: {type: String, validate: {nope: 1, msg: 'nope'}}
         });
       }, /Invalid validator/);
 
-      assert.throws(function () {
+      assert.throws(function() {
         new Schema({
           simple: {type: String, validate: [{nope: 1, msg: 'nope'}, 'nope']}
         });
@@ -43,7 +43,7 @@ describe('schema', function () {
       done();
     });
 
-    it('string enum', function (done) {
+    it('string enum', function(done) {
       var Test = new Schema({
         complex: {type: String, enum: ['a', 'b', undefined, 'c', null]},
         state: {type: String}
@@ -66,90 +66,90 @@ describe('schema', function () {
       assert.equal(Test.path('state').validators.length, 1);
       assert.deepEqual(Test.path('state').enumValues, ['opening', 'open', 'closing', 'closed']);
 
-      Test.path('complex').doValidate('x', function (err) {
+      Test.path('complex').doValidate('x', function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       // allow unsetting enums
-      Test.path('complex').doValidate(undefined, function (err) {
+      Test.path('complex').doValidate(undefined, function(err) {
         assert.ifError(err);
       });
 
-      Test.path('complex').doValidate(null, function (err) {
+      Test.path('complex').doValidate(null, function(err) {
         assert.ifError(err);
       });
 
-      Test.path('complex').doValidate('da', function (err) {
+      Test.path('complex').doValidate('da', function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('state').doValidate('x', function (err) {
+      Test.path('state').doValidate('x', function(err) {
         assert.ok(err instanceof ValidatorError);
         assert.equal(err.message,
             'enum validator failed for path `state`: test');
       });
 
-      Test.path('state').doValidate('opening', function (err) {
+      Test.path('state').doValidate('opening', function(err) {
         assert.ifError(err);
       });
 
-      Test.path('state').doValidate('open', function (err) {
+      Test.path('state').doValidate('open', function(err) {
         assert.ifError(err);
       });
 
       done();
     });
 
-    it('string regexp', function (done) {
+    it('string regexp', function(done) {
       var Test = new Schema({
         simple: {type: String, match: /[a-z]/}
       });
 
       assert.equal(1, Test.path('simple').validators.length);
 
-      Test.path('simple').doValidate('az', function (err) {
+      Test.path('simple').doValidate('az', function(err) {
         assert.ifError(err);
       });
 
       Test.path('simple').match(/[0-9]/);
       assert.equal(2, Test.path('simple').validators.length);
 
-      Test.path('simple').doValidate('12', function (err) {
+      Test.path('simple').doValidate('12', function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
-      Test.path('simple').doValidate('a12', function (err) {
+      Test.path('simple').doValidate('a12', function(err) {
         assert.ifError(err);
       });
 
-      Test.path('simple').doValidate('', function (err) {
+      Test.path('simple').doValidate('', function(err) {
         assert.ifError(err);
       });
-      Test.path('simple').doValidate(null, function (err) {
+      Test.path('simple').doValidate(null, function(err) {
         assert.ifError(err);
       });
-      Test.path('simple').doValidate(undefined, function (err) {
+      Test.path('simple').doValidate(undefined, function(err) {
         assert.ifError(err);
       });
       Test.path('simple').validators = [];
       Test.path('simple').match(/[1-9]/);
-      Test.path('simple').doValidate(0, function (err) {
+      Test.path('simple').doValidate(0, function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       Test.path('simple').match(null);
-      Test.path('simple').doValidate(0, function (err) {
+      Test.path('simple').doValidate(0, function(err) {
         assert.ok(err instanceof ValidatorError);
       });
 
       done();
     });
 
-    describe('non-required fields', function () {
-      describe('are validated correctly', function () {
+    describe('non-required fields', function() {
+      describe('are validated correctly', function() {
         var db, Person;
 
-        before(function () {
+        before(function() {
           db = start();
           var PersonSchema = new Schema({
             name: {type: String},
@@ -158,25 +158,25 @@ describe('schema', function () {
           Person = db.model('person-schema-validation-test', PersonSchema);
         });
 
-        after(function (done) {
+        after(function(done) {
           db.close(done);
         });
 
-        it('and can be set to "undefined" (gh-1594)', function (done) {
+        it('and can be set to "undefined" (gh-1594)', function(done) {
           var p = new Person({name: 'Daniel'});
           p.num_cars = 25;
 
-          p.save(function (err) {
+          p.save(function(err) {
             assert.ifError(err);
             assert.equal(p.num_cars, 25);
             p.num_cars = undefined;
 
-            p.save(function (err) {
+            p.save(function(err) {
               assert.ifError(err);
               assert.equal(p.num_cars, undefined);
               p.num_cars = 5;
 
-              p.save(function (err) {
+              p.save(function(err) {
                 // validation should still work for non-undefined values
                 assert.ok(err);
                 done();
@@ -186,32 +186,32 @@ describe('schema', function () {
         });
       });
 
-      it('number min and max', function (done) {
+      it('number min and max', function(done) {
         var Tobi = new Schema({
           friends: {type: Number, max: 15, min: 5}
         });
 
         assert.equal(Tobi.path('friends').validators.length, 2);
 
-        Tobi.path('friends').doValidate(10, function (err) {
+        Tobi.path('friends').doValidate(10, function(err) {
           assert.ifError(err);
         });
 
-        Tobi.path('friends').doValidate(100, function (err) {
+        Tobi.path('friends').doValidate(100, function(err) {
           assert.ok(err instanceof ValidatorError);
           assert.equal('friends', err.path);
           assert.equal('max', err.kind);
           assert.equal(100, err.value);
         });
 
-        Tobi.path('friends').doValidate(1, function (err) {
+        Tobi.path('friends').doValidate(1, function(err) {
           assert.ok(err instanceof ValidatorError);
           assert.equal('friends', err.path);
           assert.equal('min', err.kind);
         });
 
         // null is allowed
-        Tobi.path('friends').doValidate(null, function (err) {
+        Tobi.path('friends').doValidate(null, function(err) {
           assert.ifError(err);
         });
 
@@ -223,8 +223,8 @@ describe('schema', function () {
       });
     });
 
-    describe('required', function () {
-      it('string required', function (done) {
+    describe('required', function() {
+      it('string required', function(done) {
         var Test = new Schema({
           simple: String
         });
@@ -232,219 +232,219 @@ describe('schema', function () {
         Test.path('simple').required(true);
         assert.equal(Test.path('simple').validators.length, 1);
 
-        Test.path('simple').doValidate(null, function (err) {
+        Test.path('simple').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate(undefined, function (err) {
+        Test.path('simple').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('', function (err) {
+        Test.path('simple').doValidate('', function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('woot', function (err) {
+        Test.path('simple').doValidate('woot', function(err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('string conditional required', function (done) {
+      it('string conditional required', function(done) {
         var Test = new Schema({
           simple: String
         });
 
         var required = true,
-            isRequired = function () {
+            isRequired = function() {
               return required;
             };
 
         Test.path('simple').required(isRequired);
         assert.equal(Test.path('simple').validators.length, 1);
 
-        Test.path('simple').doValidate(null, function (err) {
+        Test.path('simple').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate(undefined, function (err) {
+        Test.path('simple').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('', function (err) {
+        Test.path('simple').doValidate('', function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Test.path('simple').doValidate('woot', function (err) {
+        Test.path('simple').doValidate('woot', function(err) {
           assert.ifError(err);
         });
 
         required = false;
 
-        Test.path('simple').doValidate(null, function (err) {
+        Test.path('simple').doValidate(null, function(err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate(undefined, function (err) {
+        Test.path('simple').doValidate(undefined, function(err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate('', function (err) {
+        Test.path('simple').doValidate('', function(err) {
           assert.ifError(err);
         });
 
-        Test.path('simple').doValidate('woot', function (err) {
+        Test.path('simple').doValidate('woot', function(err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('number required', function (done) {
+      it('number required', function(done) {
         var Edwald = new Schema({
           friends: {type: Number, required: true}
         });
 
-        Edwald.path('friends').doValidate(null, function (err) {
+        Edwald.path('friends').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Edwald.path('friends').doValidate(undefined, function (err) {
+        Edwald.path('friends').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Edwald.path('friends').doValidate(0, function (err) {
+        Edwald.path('friends').doValidate(0, function(err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('date required', function (done) {
+      it('date required', function(done) {
         var Loki = new Schema({
           birth_date: {type: Date, required: true}
         });
 
-        Loki.path('birth_date').doValidate(null, function (err) {
+        Loki.path('birth_date').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('birth_date').doValidate(undefined, function (err) {
+        Loki.path('birth_date').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('birth_date').doValidate(new Date(), function (err) {
+        Loki.path('birth_date').doValidate(new Date(), function(err) {
           assert.ifError(err);
         });
 
         done();
       });
 
-      it('date not empty string (gh-3132)', function (done) {
+      it('date not empty string (gh-3132)', function(done) {
         var HappyBirthday = new Schema({
           date: {type: Date, required: true}
         });
 
-        HappyBirthday.path('date').doValidate('', function (err) {
+        HappyBirthday.path('date').doValidate('', function(err) {
           assert.ok(err instanceof ValidatorError);
           done();
         });
       });
 
-      it('objectid required', function (done) {
+      it('objectid required', function(done) {
         var Loki = new Schema({
           owner: {type: ObjectId, required: true}
         });
 
-        Loki.path('owner').doValidate(new DocumentObjectId(), function (err) {
+        Loki.path('owner').doValidate(new DocumentObjectId(), function(err) {
           assert.ifError(err);
         });
 
-        Loki.path('owner').doValidate(null, function (err) {
+        Loki.path('owner').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('owner').doValidate(undefined, function (err) {
+        Loki.path('owner').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
         done();
       });
 
-      it('array required', function (done) {
+      it('array required', function(done) {
         var Loki = new Schema({
           likes: {type: Array, required: true}
         });
 
-        Loki.path('likes').doValidate(null, function (err) {
+        Loki.path('likes').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('likes').doValidate(undefined, function (err) {
+        Loki.path('likes').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Loki.path('likes').doValidate([], function (err) {
+        Loki.path('likes').doValidate([], function(err) {
           assert.ok(err instanceof ValidatorError);
         });
         done();
       });
 
-      it('boolean required', function (done) {
+      it('boolean required', function(done) {
         var Animal = new Schema({
           isFerret: {type: Boolean, required: true}
         });
 
-        Animal.path('isFerret').doValidate(null, function (err) {
+        Animal.path('isFerret').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('isFerret').doValidate(undefined, function (err) {
+        Animal.path('isFerret').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('isFerret').doValidate(true, function (err) {
+        Animal.path('isFerret').doValidate(true, function(err) {
           assert.ifError(err);
         });
 
-        Animal.path('isFerret').doValidate(false, function (err) {
+        Animal.path('isFerret').doValidate(false, function(err) {
           assert.ifError(err);
         });
         done();
       });
 
-      it('mixed required', function (done) {
+      it('mixed required', function(done) {
         var Animal = new Schema({
           characteristics: {type: Mixed, required: true}
         });
 
-        Animal.path('characteristics').doValidate(null, function (err) {
+        Animal.path('characteristics').doValidate(null, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
-        Animal.path('characteristics').doValidate(undefined, function (err) {
+        Animal.path('characteristics').doValidate(undefined, function(err) {
           assert.ok(err instanceof ValidatorError);
         });
 
         Animal.path('characteristics').doValidate({
           aggresive: true
-        }, function (err) {
+        }, function(err) {
           assert.ifError(err);
         });
 
-        Animal.path('characteristics').doValidate('none available', function (err) {
+        Animal.path('characteristics').doValidate('none available', function(err) {
           assert.ifError(err);
         });
         done();
       });
     });
 
-    describe('async', function () {
-      it('works', function (done) {
+    describe('async', function() {
+      it('works', function(done) {
         var executed = 0;
 
         function validator(value, fn) {
-          setTimeout(function () {
+          setTimeout(function() {
             executed++;
             fn(value === true);
             if (executed === 2) {
@@ -457,20 +457,20 @@ describe('schema', function () {
           ferret: {type: Boolean, validate: validator}
         });
 
-        Animal.path('ferret').doValidate(true, function (err) {
+        Animal.path('ferret').doValidate(true, function(err) {
           assert.ifError(err);
         });
 
-        Animal.path('ferret').doValidate(false, function (err) {
+        Animal.path('ferret').doValidate(false, function(err) {
           assert.ok(err instanceof Error);
         });
       });
 
-      it('multiple', function (done) {
+      it('multiple', function(done) {
         var executed = 0;
 
         function validator(value, fn) {
-          setTimeout(function () {
+          setTimeout(function() {
             executed++;
             fn(value === true);
             if (executed === 2) {
@@ -492,17 +492,17 @@ describe('schema', function () {
           }
         });
 
-        Animal.path('ferret').doValidate(true, function (err) {
+        Animal.path('ferret').doValidate(true, function(err) {
           assert.ifError(err);
         });
       });
 
-      it('multiple sequence', function (done) {
+      it('multiple sequence', function(done) {
         var validator1Executed = false,
             validator2Executed = false;
 
         function validator1(value, fn) {
-          setTimeout(function () {
+          setTimeout(function() {
             validator1Executed = true;
             assert.ok(!validator2Executed);
             fn(value === true);
@@ -510,7 +510,7 @@ describe('schema', function () {
         }
 
         function validator2(value, fn) {
-          setTimeout(function () {
+          setTimeout(function() {
             validator2Executed = true;
             assert.ok(validator1Executed);
             fn(value === true);
@@ -531,18 +531,18 @@ describe('schema', function () {
           }
         });
 
-        Animal.path('ferret').doValidate(true, function (err) {
+        Animal.path('ferret').doValidate(true, function(err) {
           assert.ifError(err);
         });
       });
 
-      it('scope', function (done) {
+      it('scope', function(done) {
         var called = false;
 
         function validator(value, fn) {
           assert.equal('b', this.a);
 
-          setTimeout(function () {
+          setTimeout(function() {
             called = true;
             fn(true);
           }, 5);
@@ -552,7 +552,7 @@ describe('schema', function () {
           ferret: {type: Boolean, validate: validator}
         });
 
-        Animal.path('ferret').doValidate(true, function (err) {
+        Animal.path('ferret').doValidate(true, function(err) {
           assert.ifError(err);
           assert.equal(true, called);
           done();
@@ -560,9 +560,9 @@ describe('schema', function () {
       });
     });
 
-    describe('messages', function () {
-      describe('are customizable', function () {
-        it('within schema definitions', function (done) {
+    describe('messages', function() {
+      describe('are customizable', function() {
+        it('within schema definitions', function(done) {
           var schema = new Schema({
             name: {type: String, enum: ['one', 'two']},
             myenum: {type: String, enum: {values: ['x'], message: 'enum validator failed for path: {PATH} with {VALUE}'}},
@@ -579,7 +579,7 @@ describe('schema', function () {
           var A = mongoose.model('schema-validation-messages-' + random(), schema);
 
           var a = new A;
-          a.validate(function (err) {
+          a.validate(function(err) {
             assert.equal('Path `requiredString1` is required.', err.errors.requiredString1);
             assert.equal('oops, requiredString2 is missing. required', err.errors.requiredString2);
 
@@ -590,7 +590,7 @@ describe('schema', function () {
             a.numMin0 = a.numMin1 = 2;
             a.numMax0 = a.numMax1 = 30;
 
-            a.validate(function (err) {
+            a.validate(function(err) {
               assert.equal('`three` is not a valid enum value for path `name`.', err.errors.name);
               assert.equal('enum validator failed for path: myenum with y', err.errors.myenum);
               assert.equal('Path `matchString0` is invalid (no match).', err.errors.matchString0);
@@ -610,8 +610,8 @@ describe('schema', function () {
           });
         });
 
-        it('for custom validators', function (done) {
-          var validate = function () {
+        it('for custom validators', function(done) {
+          var validate = function() {
             return false;
           };
           var validator = [validate, '{PATH} failed validation ({VALUE})'];
@@ -621,19 +621,19 @@ describe('schema', function () {
 
           var m = new M({x: [3, 4, 5, 6]});
 
-          m.validate(function (err) {
+          m.validate(function(err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('user defined', err.errors.x.kind);
             done();
           });
         });
 
-        it('supports custom properties (gh-2132)', function (done) {
+        it('supports custom properties (gh-2132)', function(done) {
           var schema = new Schema({
             x: {
               type: String,
               validate: [{
-                validator: function () {
+                validator: function() {
                   return false;
                 },
                 msg: 'Error code {ERRORCODE}',
@@ -644,19 +644,19 @@ describe('schema', function () {
           var M = mongoose.model('gh-2132', schema, 'gh-2132');
 
           var m = new M({x: 'a'});
-          m.validate(function (err) {
+          m.validate(function(err) {
             assert.equal('Error code 25', err.errors.x.toString());
             assert.equal(25, err.errors.x.properties.errorCode);
             done();
           });
         });
 
-        it('supports dynamic message for validators with callback (gh-1936)', function (done) {
+        it('supports dynamic message for validators with callback (gh-1936)', function(done) {
           var schema = new Schema({
             x: {
               type: String,
               validate: [{
-                validator: function (value, fn) {
+                validator: function(value, fn) {
                   fn(false, 'Custom message');
                 },
                 msg: 'Does not matter'
@@ -666,7 +666,7 @@ describe('schema', function () {
           var M = mongoose.model('gh-1936', schema, 'gh-1936');
 
           var m = new M({x: 'whatever'});
-          m.validate(function (err) {
+          m.validate(function(err) {
             assert.equal('Custom message', err.errors.x.toString());
             done();
           });
@@ -674,9 +674,9 @@ describe('schema', function () {
       });
     });
 
-    describe('types', function () {
-      describe('are customizable', function () {
-        it('for single custom validators', function (done) {
+    describe('types', function() {
+      describe('are customizable', function() {
+        it('for single custom validators', function(done) {
           function validate() {
             return false;
           }
@@ -688,14 +688,14 @@ describe('schema', function () {
 
           var m = new M({x: [3, 4, 5, 6]});
 
-          m.validate(function (err) {
+          m.validate(function(err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('customType', err.errors.x.kind);
             done();
           });
         });
 
-        it('for many custom validators', function (done) {
+        it('for many custom validators', function(done) {
           function validate() {
             return false;
           }
@@ -708,7 +708,7 @@ describe('schema', function () {
 
           var m = new M({x: [3, 4, 5, 6]});
 
-          m.validate(function (err) {
+          m.validate(function(err) {
             assert.equal('x failed validation (3,4,5,6)', String(err.errors.x));
             assert.equal('customType', err.errors.x.kind);
             done();
@@ -717,17 +717,17 @@ describe('schema', function () {
       });
     });
 
-    it('should clear validator errors (gh-2302)', function (done) {
+    it('should clear validator errors (gh-2302)', function(done) {
       var userSchema = new Schema({name: {type: String, required: true}});
       var User = mongoose.model('gh-2302', userSchema, 'gh-2302');
 
       var user = new User();
-      user.validate(function (err) {
+      user.validate(function(err) {
         assert.ok(err);
         assert.ok(user.errors);
         assert.ok(user.errors.name);
         user.name = 'bacon';
-        user.validate(function (err) {
+        user.validate(function(err) {
           assert.ok(!err);
           assert.ok(!user.$__.validationError);
           done();
@@ -735,7 +735,7 @@ describe('schema', function () {
       });
     });
 
-    it('should allow an array of enums (gh-661)', function (done) {
+    it('should allow an array of enums (gh-661)', function(done) {
       var validBreakfastFoods = ['bacon', 'eggs', 'steak', 'coffee', 'butter'];
       var breakfastSchema = new Schema({
         foods: [{type: String, enum: validBreakfastFoods}]
@@ -743,11 +743,11 @@ describe('schema', function () {
       var Breakfast = mongoose.model('gh-661', breakfastSchema, 'gh-661');
 
       var goodBreakfast = new Breakfast({foods: ['eggs', 'bacon']});
-      goodBreakfast.validate(function (error) {
+      goodBreakfast.validate(function(error) {
         assert.ifError(error);
 
         var badBreakfast = new Breakfast({foods: ['tofu', 'waffles', 'coffee']});
-        badBreakfast.validate(function (error) {
+        badBreakfast.validate(function(error) {
           assert.ok(error);
           assert.ok(error.errors['foods.0']);
           assert.equal(error.errors['foods.0'].message,
@@ -762,7 +762,7 @@ describe('schema', function () {
       });
     });
 
-    it('should allow an array of subdocuments with enums (gh-3521)', function (done) {
+    it('should allow an array of subdocuments with enums (gh-3521)', function(done) {
       var coolSchema = new Schema({
         votes: [{
           vote: {type: String, enum: ['cool', 'not-cool']}
@@ -774,7 +774,7 @@ describe('schema', function () {
       cool.votes.push(cool.votes.create({
         vote: 'cool'
       }));
-      cool.validate(function (error) {
+      cool.validate(function(error) {
         assert.ifError(error);
 
         var terrible = new Cool();
@@ -782,7 +782,7 @@ describe('schema', function () {
           vote: 'terrible'
         }));
 
-        terrible.validate(function (error) {
+        terrible.validate(function(error) {
           assert.ok(error);
           assert.ok(error.errors['votes.0.vote']);
           assert.equal(error.errors['votes.0.vote'].message,
@@ -793,11 +793,11 @@ describe('schema', function () {
       });
     });
 
-    it('doesnt do double validation on document arrays (gh-2618)', function (done) {
+    it('doesnt do double validation on document arrays (gh-2618)', function(done) {
       var A = new Schema({str: String});
       var B = new Schema({a: [A]});
       var validateCalls = 0;
-      B.path('a').validate(function (val, next) {
+      B.path('a').validate(function(val, next) {
         ++validateCalls;
         next();
       });
@@ -806,40 +806,40 @@ describe('schema', function () {
 
       var p = new B();
       p.a.push({str: 'asdf'});
-      p.validate(function (err) {
+      p.validate(function(err) {
         assert.ifError(err);
         assert.equal(1, validateCalls);
         done();
       });
     });
 
-    it('returns cast errors', function (done) {
+    it('returns cast errors', function(done) {
       var breakfastSchema = new Schema({
         eggs: Number
       });
       var Breakfast = mongoose.model('gh-2611', breakfastSchema, 'gh-2611');
 
       var bad = new Breakfast({eggs: 'none'});
-      bad.validate(function (error) {
+      bad.validate(function(error) {
         assert.ok(error);
         done();
       });
     });
 
-    it('handles multiple subdocument errors (gh-2589)', function (done) {
+    it('handles multiple subdocument errors (gh-2589)', function(done) {
       var foodSchema = new Schema({name: {type: String, required: true, enum: ['bacon', 'eggs']}});
       var breakfast = new Schema({foods: [foodSchema], id: Number});
 
       var Breakfast = mongoose.model('gh-2589', breakfast, 'gh-2589');
       var bad = new Breakfast({foods: [{name: 'tofu'}, {name: 'waffles'}], id: 'Not a number'});
-      bad.validate(function (error) {
+      bad.validate(function(error) {
         assert.ok(error);
         assert.deepEqual(['id', 'foods.0.name', 'foods.1.name'], Object.keys(error.errors));
         done();
       });
     });
 
-    it('handles subdocument cast errors (gh-2819)', function (done) {
+    it('handles subdocument cast errors (gh-2819)', function(done) {
       var foodSchema = new Schema({eggs: {type: Number, required: true}});
       var breakfast = new Schema({foods: [foodSchema], id: Number});
 
@@ -847,20 +847,20 @@ describe('schema', function () {
 
       // Initially creating subdocs with cast errors
       var bad = new Breakfast({foods: [{eggs: 'Not a number'}], id: 'Not a number'});
-      bad.validate(function (error) {
+      bad.validate(function(error) {
         assert.ok(error);
         assert.deepEqual(['id', 'foods.0.eggs'], Object.keys(error.errors));
         assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError);
 
         // Pushing docs with cast errors
         bad.foods.push({eggs: 'Also not a number'});
-        bad.validate(function (error) {
+        bad.validate(function(error) {
           assert.deepEqual(['id', 'foods.0.eggs', 'foods.1.eggs'], Object.keys(error.errors));
           assert.ok(error.errors['foods.1.eggs'] instanceof mongoose.Error.CastError);
 
           // Splicing docs with cast errors
           bad.foods.splice(1, 1, {eggs: 'fail1'}, {eggs: 'fail2'});
-          bad.validate(function (error) {
+          bad.validate(function(error) {
             assert.deepEqual(['id', 'foods.0.eggs', 'foods.1.eggs', 'foods.2.eggs'], Object.keys(error.errors));
             assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError);
             assert.ok(error.errors['foods.1.eggs'] instanceof mongoose.Error.CastError);
@@ -868,14 +868,14 @@ describe('schema', function () {
 
             // Remove the cast error by setting field
             bad.foods[2].eggs = 3;
-            bad.validate(function (error) {
+            bad.validate(function(error) {
               assert.deepEqual(['id', 'foods.0.eggs', 'foods.1.eggs'], Object.keys(error.errors));
               assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError);
               assert.ok(error.errors['foods.1.eggs'] instanceof mongoose.Error.CastError);
 
               // Remove the cast error using array.set()
               bad.foods.set(1, {eggs: 1});
-              bad.validate(function (error) {
+              bad.validate(function(error) {
                 assert.deepEqual(['id', 'foods.0.eggs'], Object.keys(error.errors));
                 assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError);
 
@@ -887,13 +887,13 @@ describe('schema', function () {
       });
     });
 
-    it('fails when you try to set a nested path to a primitive (gh-2592)', function (done) {
+    it('fails when you try to set a nested path to a primitive (gh-2592)', function(done) {
       var breakfast = new Schema({foods: {bacon: Number, eggs: Number}});
 
       var Breakfast = mongoose.model('gh-2592', breakfast, 'gh-2592');
       var bad = new Breakfast();
       bad.foods = 'waffles';
-      bad.validate(function (error) {
+      bad.validate(function(error) {
         assert.ok(error);
         var errorMessage = 'CastError: Cast to Object failed for value ' +
             '"waffles" at path "foods"';
@@ -902,12 +902,12 @@ describe('schema', function () {
       });
     });
 
-    it('doesnt execute other validators if required fails (gh-2725)', function (done) {
+    it('doesnt execute other validators if required fails (gh-2725)', function(done) {
       var breakfast = new Schema({description: {type: String, required: true, maxlength: 50}});
 
       var Breakfast = mongoose.model('gh2725', breakfast, 'gh2725');
       var bad = new Breakfast({});
-      bad.validate(function (error) {
+      bad.validate(function(error) {
         assert.ok(error);
         var errorMessage = 'ValidationError: Path `description` is required.';
         assert.equal(errorMessage, error.toString());
@@ -915,7 +915,7 @@ describe('schema', function () {
       });
     });
 
-    it('doesnt execute other validators if required fails (gh-3025)', function (done) {
+    it('doesnt execute other validators if required fails (gh-3025)', function(done) {
       var breakfast = new Schema({description: {type: String, required: true, maxlength: 50}});
 
       var Breakfast = mongoose.model('gh3025', breakfast, 'gh3025');
@@ -928,7 +928,7 @@ describe('schema', function () {
       done();
     });
 
-    it('validateSync allows you to filter paths (gh-3153)', function (done) {
+    it('validateSync allows you to filter paths (gh-3153)', function(done) {
       var breakfast = new Schema({
         description: {type: String, required: true, maxlength: 50},
         other: {type: String, required: true}
@@ -945,12 +945,12 @@ describe('schema', function () {
       done();
     });
 
-    it('adds required validators to the front of the list (gh-2843)', function (done) {
+    it('adds required validators to the front of the list (gh-2843)', function(done) {
       var breakfast = new Schema({description: {type: String, maxlength: 50, required: true}});
 
       var Breakfast = mongoose.model('gh2843', breakfast, 'gh2843');
       var bad = new Breakfast({});
-      bad.validate(function (error) {
+      bad.validate(function(error) {
         assert.ok(error);
         var errorMessage = 'ValidationError: Path `description` is required.';
         assert.equal(errorMessage, error.toString());
@@ -958,17 +958,17 @@ describe('schema', function () {
       });
     });
 
-    it('sets path correctly when setter throws exception (gh-2832)', function (done) {
+    it('sets path correctly when setter throws exception (gh-2832)', function(done) {
       var breakfast = new Schema({
         description: {
-          type: String, set: function () {
+          type: String, set: function() {
             throw new Error('oops');
           }
         }
       });
 
       var Breakfast = mongoose.model('gh2832', breakfast, 'gh2832');
-      Breakfast.create({description: undefined}, function (error) {
+      Breakfast.create({description: undefined}, function(error) {
         assert.ok(error);
         var errorMessage = 'ValidationError: CastError: Cast to String failed for value "undefined" at path "description"';
         assert.equal(errorMessage, error.toString());
@@ -978,7 +978,7 @@ describe('schema', function () {
       });
     });
 
-    it('allows you to validate embedded doc that was .create()-ed (gh-2902) (gh-2929)', function (done) {
+    it('allows you to validate embedded doc that was .create()-ed (gh-2902) (gh-2929)', function(done) {
       var parentSchema = mongoose.Schema({
         children: [{name: {type: String, required: true}}]
       });
@@ -987,11 +987,11 @@ describe('schema', function () {
 
       var p = new Parent();
       var n = p.children.create({name: '2'});
-      n.validate(function (error) {
+      n.validate(function(error) {
         assert.ifError(error);
         var bad = p.children.create({});
         p.children.push(bad);
-        bad.validate(function (error) {
+        bad.validate(function(error) {
           assert.ok(error);
           assert.ok(error.errors['children.0.name']);
           done();
@@ -999,11 +999,11 @@ describe('schema', function () {
       });
     });
 
-    it('returns correct kind for user defined custom validators (gh-2885)', function (done) {
+    it('returns correct kind for user defined custom validators (gh-2885)', function(done) {
       var s = mongoose.Schema({
         n: {
           type: String, validate: {
-            validator: function () {
+            validator: function() {
               return false;
             }
           }, msg: 'fail'
@@ -1012,29 +1012,29 @@ describe('schema', function () {
       var M = mongoose.model('gh2885', s);
 
       var m = new M({n: 'test'});
-      m.validate(function (error) {
+      m.validate(function(error) {
         assert.ok(error);
         assert.equal(error.errors.n.kind, 'user defined');
         done();
       });
     });
 
-    it('enums report kind (gh-3009)', function (done) {
+    it('enums report kind (gh-3009)', function(done) {
       var s = mongoose.Schema({n: {type: String, enum: ['a', 'b']}});
       var M = mongoose.model('gh3009', s);
 
       var m = new M({n: 'test'});
-      m.validate(function (error) {
+      m.validate(function(error) {
         assert.ok(error);
         assert.equal(error.errors.n.kind, 'enum');
         done();
       });
     });
 
-    it('skips conditional required (gh-3539)', function (done) {
+    it('skips conditional required (gh-3539)', function(done) {
       var s = mongoose.Schema({
         n: {
-          type: Number, required: function () {
+          type: Number, required: function() {
             return false;
           }, min: 0
         }
@@ -1042,7 +1042,7 @@ describe('schema', function () {
       var M = mongoose.model('gh3539', s);
 
       var m = new M();
-      m.validate(function (error) {
+      m.validate(function(error) {
         assert.ifError(error);
         done();
       });
diff --git a/test/shard.test.js b/test/shard.test.js
index c9a3e404dcf..d28244f6704 100644
--- a/test/shard.test.js
+++ b/test/shard.test.js
@@ -37,10 +37,10 @@ mongoose.model('ShardPerson', schema, collection);
 var version;
 var greaterThan20x;
 var db;
-describe('shard', function () {
-  before(function (done) {
+describe('shard', function() {
+  before(function(done) {
     db = start({uri: uri});
-    db.on('error', function (err) {
+    db.on('error', function(err) {
       if (/failed to connect/.test(err)) {
         err.message = 'Shard test error: '
             + err.message
@@ -51,18 +51,18 @@ describe('shard', function () {
       }
       return done(err);
     });
-    db.on('open', function () {
+    db.on('open', function() {
       // set up a sharded test collection
       var P = db.model('ShardPerson', collection);
 
       // an existing index on shard key is required before sharding
-      P.on('index', function () {
+      P.on('index', function() {
         // enable sharding on our collection
         var cmd = {};
         cmd.shardcollection = db.name + '.' + collection;
         cmd.key = P.schema.options.shardkey;
 
-        P.db.db.executeDbAdminCommand(cmd, function (err, res) {
+        P.db.db.executeDbAdminCommand(cmd, function(err, res) {
           assert.ifError(err);
 
           if (!(res && res.documents && res.documents[0] && res.documents[0].ok)) {
@@ -74,12 +74,12 @@ describe('shard', function () {
             return done(err);
           }
 
-          db.db.admin(function (err, admin) {
+          db.db.admin(function(err, admin) {
             assert.ifError(err);
-            admin.serverStatus(function (err, info) {
+            admin.serverStatus(function(err, info) {
               db.close();
               assert.ifError(err);
-              version = info.version.split('.').map(function (n) {
+              version = info.version.split('.').map(function(n) {
                 return parseInt(n, 10);
               });
               greaterThan20x = version[0] > 2 || version[0] === 2 && version[0] > 0;
@@ -91,13 +91,13 @@ describe('shard', function () {
     });
   });
 
-  it('can read and write to a shard', function (done) {
+  it('can read and write to a shard', function(done) {
     var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
-    P.create({name: 'ryu', age: 25, likes: ['street fighting']}, function (err, ryu) {
+    P.create({name: 'ryu', age: 25, likes: ['street fighting']}, function(err, ryu) {
       assert.ifError(err);
-      P.findById(ryu._id, function (err, doc) {
+      P.findById(ryu._id, function(err, doc) {
         db.close();
         assert.ifError(err);
         assert.equal(doc.id, ryu.id);
@@ -106,36 +106,36 @@ describe('shard', function () {
     });
   });
 
-  it('save() and remove() works with shard keys transparently', function (done) {
+  it('save() and remove() works with shard keys transparently', function(done) {
     var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
     var zangief = new P({name: 'Zangief', age: 33});
-    zangief.save(function (err) {
+    zangief.save(function(err) {
       assert.ifError(err);
 
       assert.equal(zangief.$__.shardval.name, 'Zangief');
       assert.equal(zangief.$__.shardval.age, 33);
 
-      P.findById(zangief._id, function (err, zang) {
+      P.findById(zangief._id, function(err, zang) {
         assert.ifError(err);
 
         assert.equal(zang.$__.shardval.name, 'Zangief');
         assert.equal(zang.$__.shardval.age, 33);
 
         zang.likes = ['spinning', 'laughing'];
-        zang.save(function (err) {
+        zang.save(function(err) {
           assert.ifError(err);
 
           assert.equal(zang.$__.shardval.name, 'Zangief');
           assert.equal(zang.$__.shardval.age, 33);
 
           zang.likes.addToSet('winning');
-          zang.save(function (err) {
+          zang.save(function(err) {
             assert.ifError(err);
             assert.equal(zang.$__.shardval.name, 'Zangief');
             assert.equal(zang.$__.shardval.age, 33);
-            zang.remove(function (err) {
+            zang.remove(function(err) {
               db.close();
               assert.ifError(err);
               done();
@@ -146,13 +146,13 @@ describe('shard', function () {
     });
   });
 
-  it('inserting to a sharded collection without the full shard key fails', function (done) {
+  it('inserting to a sharded collection without the full shard key fails', function(done) {
     var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
     var pending = 6;
 
-    P.create({name: 'ryu', likes: ['street fighting']}, function (err) {
+    P.create({name: 'ryu', likes: ['street fighting']}, function(err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -161,7 +161,7 @@ describe('shard', function () {
       }
     });
 
-    P.create({likes: ['street fighting']}, function (err) {
+    P.create({likes: ['street fighting']}, function(err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -170,7 +170,7 @@ describe('shard', function () {
       }
     });
 
-    P.create({name: 'ryu'}, function (err) {
+    P.create({name: 'ryu'}, function(err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -179,7 +179,7 @@ describe('shard', function () {
       }
     });
 
-    P.create({age: 49}, function (err) {
+    P.create({age: 49}, function(err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -188,7 +188,7 @@ describe('shard', function () {
       }
     });
 
-    P.create({likes: ['street fighting'], age: 8}, function (err) {
+    P.create({likes: ['street fighting'], age: 8}, function(err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -198,7 +198,7 @@ describe('shard', function () {
     });
 
     var p = new P;
-    p.save(function (err) {
+    p.save(function(err) {
       assert.ok(err);
       assert.ok(err.message);
       if (!--pending) {
@@ -208,17 +208,17 @@ describe('shard', function () {
     });
   });
 
-  it('updating a sharded collection without the full shard key fails', function (done) {
+  it('updating a sharded collection without the full shard key fails', function(done) {
     var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
-    P.create({name: 'ken', age: 27}, function (err, ken) {
+    P.create({name: 'ken', age: 27}, function(err, ken) {
       assert.ifError(err);
 
-      P.update({name: 'ken'}, {likes: ['kicking', 'punching']}, function (err) {
+      P.update({name: 'ken'}, {likes: ['kicking', 'punching']}, function(err) {
         assert.ok(/shard key/.test(err.message));
 
-        P.update({_id: ken._id, name: 'ken'}, {likes: ['kicking', 'punching']}, function (err) {
+        P.update({_id: ken._id, name: 'ken'}, {likes: ['kicking', 'punching']}, function(err) {
           // mongo 2.0.x returns: can't do non-multi update with query that doesn't have a valid shard key
           if (greaterThan20x) {
             assert.ok(!err, err);
@@ -226,7 +226,7 @@ describe('shard', function () {
             assert.ok(/shard key/.test(err.message));
           }
 
-          P.update({_id: ken._id, age: 27}, {likes: ['kicking', 'punching']}, function (err) {
+          P.update({_id: ken._id, age: 27}, {likes: ['kicking', 'punching']}, function(err) {
             // mongo 2.0.x returns: can't do non-multi update with query that doesn't have a valid shard key
             if (greaterThan20x) {
               assert.ok(!err, err);
@@ -234,7 +234,7 @@ describe('shard', function () {
               assert.ok(/shard key/.test(err.message));
             }
 
-            P.update({age: 27}, {likes: ['kicking', 'punching']}, function (err) {
+            P.update({age: 27}, {likes: ['kicking', 'punching']}, function(err) {
               db.close();
               assert.ok(err);
               done();
@@ -245,30 +245,30 @@ describe('shard', function () {
     });
   });
 
-  it('updating shard key values fails', function (done) {
+  it('updating shard key values fails', function(done) {
     var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
-    P.create({name: 'chun li', age: 19, likes: ['street fighting']}, function (err, chunli) {
+    P.create({name: 'chun li', age: 19, likes: ['street fighting']}, function(err, chunli) {
       assert.ifError(err);
 
       assert.equal(chunli.$__.shardval.name, 'chun li');
       assert.equal(chunli.$__.shardval.age, 19);
 
       chunli.age = 20;
-      chunli.save(function (err) {
+      chunli.save(function(err) {
         assert.ok(/^After applying the update to the document/.test(err.message));
 
         assert.equal(chunli.$__.shardval.name, 'chun li');
         assert.equal(chunli.$__.shardval.age, 19);
 
-        P.findById(chunli._id, function (err, chunli) {
+        P.findById(chunli._id, function(err, chunli) {
           assert.ifError(err);
 
           assert.equal(chunli.$__.shardval.name, 'chun li');
           assert.equal(chunli.$__.shardval.age, 19);
 
           chunli.name = 'chuuuun liiiii';
-          chunli.save(function (err) {
+          chunli.save(function(err) {
             db.close();
             assert.ok(/^After applying the update to the document/.test(err.message));
             done();
@@ -278,23 +278,23 @@ describe('shard', function () {
     });
   });
 
-  it('allows null shard key values', function (done) {
+  it('allows null shard key values', function(done) {
     var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
 
-    P.create({name: null, age: 27}, function (err, ken) {
+    P.create({name: null, age: 27}, function(err, ken) {
       assert.ifError(err);
-      P.findById(ken, function (err) {
+      P.findById(ken, function(err) {
         assert.ifError(err);
         done();
       });
     });
   });
 
-  after(function (done) {
+  after(function(done) {
     var db = start({uri: uri});
     var P = db.model('ShardPerson', collection);
-    P.collection.drop(function () {
+    P.collection.drop(function() {
       db.close();
       done();
     });
diff --git a/test/types.array.test.js b/test/types.array.test.js
index 3d8252c9591..7b97547e31a 100644
--- a/test/types.array.test.js
+++ b/test/types.array.test.js
@@ -27,8 +27,8 @@ mongoose.model('Pet', Pet);
  * Test.
  */
 
-describe('types array', function () {
-  it('behaves and quacks like an Array', function (done) {
+describe('types array', function() {
+  it('behaves and quacks like an Array', function(done) {
     var a = new MongooseArray;
 
     assert.ok(a instanceof Array);
@@ -40,8 +40,8 @@ describe('types array', function () {
     done();
   });
 
-  describe('hasAtomics', function () {
-    it('does not throw', function (done) {
+  describe('hasAtomics', function() {
+    it('does not throw', function(done) {
       var b = new MongooseArray([12, 3, 4, 5]).filter(Boolean);
       var threw = false;
 
@@ -66,8 +66,8 @@ describe('types array', function () {
     });
   });
 
-  describe('indexOf()', function () {
-    it('works', function (done) {
+  describe('indexOf()', function() {
+    it('works', function(done) {
       var db = start(),
           User = db.model('User', 'users_' + random()),
           Pet = db.model('Pet', 'pets' + random());
@@ -84,11 +84,11 @@ describe('types array', function () {
       var pending = 3;
 
       function cb() {
-        Pet.find({}, function (err) {
+        Pet.find({}, function(err) {
           assert.ifError(err);
-          tj.save(function (err) {
+          tj.save(function(err) {
             assert.ifError(err);
-            User.findOne({name: 'tj'}, function (err, user) {
+            User.findOne({name: 'tj'}, function(err, user) {
               assert.ifError(err);
               assert.equal(user.pets.length, 3);
               assert.equal(user.pets.indexOf(tobi.id), 0);
@@ -103,19 +103,19 @@ describe('types array', function () {
         });
       }
 
-      [tobi, loki, jane].forEach(function (pet) {
-        pet.save(function () {
+      [tobi, loki, jane].forEach(function(pet) {
+        pet.save(function() {
           --pending || cb();
         });
       });
     });
   });
 
-  describe('push()', function () {
+  describe('push()', function() {
     var db, N, S, B, M, D, ST;
 
     function save(doc, cb) {
-      doc.save(function (err) {
+      doc.save(function(err) {
         if (err) {
           return cb(err);
         }
@@ -123,7 +123,7 @@ describe('types array', function () {
       });
     }
 
-    before(function (done) {
+    before(function(done) {
       db = start();
       N = db.model('arraySet', Schema({arr: [Number]}));
       S = db.model('arraySetString', Schema({arr: [String]}));
@@ -139,20 +139,20 @@ describe('types array', function () {
       done();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('works with numbers', function (done) {
+    it('works with numbers', function(done) {
       var m = new N({arr: [3, 4, 5, 6]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.push(8);
         assert.strictEqual(8, doc.arr[doc.arr.length - 1]);
         assert.strictEqual(8, doc.arr[4]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.strictEqual(3, doc.arr[0]);
@@ -166,16 +166,16 @@ describe('types array', function () {
       });
     });
 
-    it('works with strings', function (done) {
+    it('works with strings', function(done) {
       var m = new S({arr: [3, 4, 5, 6]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.push(8);
         assert.strictEqual('8', doc.arr[doc.arr.length - 1]);
         assert.strictEqual('8', doc.arr[4]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.strictEqual('3', doc.arr[0]);
@@ -189,9 +189,9 @@ describe('types array', function () {
       });
     });
 
-    it('works with buffers', function (done) {
+    it('works with buffers', function(done) {
       var m = new B({arr: [[0], new Buffer(1)]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         assert.ok(doc.arr[0].isMongooseBuffer);
@@ -201,7 +201,7 @@ describe('types array', function () {
         assert.ok(doc.arr[2].isMongooseBuffer);
         assert.strictEqual('nice', doc.arr[2].toString('utf8'));
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.ok(doc.arr[0].isMongooseBuffer);
@@ -214,16 +214,16 @@ describe('types array', function () {
       });
     });
 
-    it('works with mixed', function (done) {
+    it('works with mixed', function(done) {
       var m = new M({arr: [3, {x: 1}, 'yes', [5]]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.push(null);
         assert.equal(5, doc.arr.length);
         assert.strictEqual(null, doc.arr[4]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
 
           assert.equal(5, doc.arr.length);
@@ -242,7 +242,7 @@ describe('types array', function () {
           assert.equal(7, doc.arr.length);
           assert.strictEqual('', doc.arr[6].toString());
 
-          save(doc, function (err, doc) {
+          save(doc, function(err, doc) {
             assert.ifError(err);
 
             assert.equal(7, doc.arr.length);
@@ -261,16 +261,16 @@ describe('types array', function () {
       });
     });
 
-    it('works with sub-docs', function (done) {
+    it('works with sub-docs', function(done) {
       var m = new D({arr: [{name: 'aaron'}, {name: 'moombahton '}]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         doc.arr.push({name: 'Restrepo'});
         assert.equal(3, doc.arr.length);
         assert.equal('Restrepo', doc.arr[2].name);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
 
           // validate
@@ -284,9 +284,9 @@ describe('types array', function () {
       });
     });
 
-    it('applies setters (gh-3032)', function (done) {
+    it('applies setters (gh-3032)', function(done) {
       var m = new ST({arr: ['ONE', 'TWO']});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         doc.arr.push('THREE');
@@ -294,7 +294,7 @@ describe('types array', function () {
         assert.strictEqual('two', doc.arr[1]);
         assert.strictEqual('three', doc.arr[2]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.strictEqual('one', doc.arr[0]);
@@ -307,38 +307,38 @@ describe('types array', function () {
     });
   });
 
-  describe('splice()', function () {
+  describe('splice()', function() {
     var db;
 
-    before(function () {
+    before(function() {
       db = start();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('works', function (done) {
+    it('works', function(done) {
       var collection = 'splicetest-number' + random();
       var schema = new Schema({numbers: [Number]}),
           A = db.model('splicetestNumber', schema, collection);
 
       var a = new A({numbers: [4, 5, 6, 7]});
-      a.save(function (err) {
+      a.save(function(err) {
         assert.ifError(err);
-        A.findById(a._id, function (err, doc) {
+        A.findById(a._id, function(err, doc) {
           assert.ifError(err);
           var removed = doc.numbers.splice(1, 1, '10');
           assert.deepEqual(removed, [5]);
           assert.equal('number', typeof doc.numbers[1]);
           assert.deepEqual(doc.numbers.toObject(), [4, 10, 6, 7]);
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
-            A.findById(a._id, function (err, doc) {
+            A.findById(a._id, function(err, doc) {
               assert.ifError(err);
               assert.deepEqual(doc.numbers.toObject(), [4, 10, 6, 7]);
 
-              A.collection.drop(function (err) {
+              A.collection.drop(function(err) {
                 assert.ifError(err);
                 done();
               });
@@ -348,15 +348,15 @@ describe('types array', function () {
       });
     });
 
-    it('on embedded docs', function (done) {
+    it('on embedded docs', function(done) {
       var collection = 'splicetest-embeddeddocs' + random();
       var schema = new Schema({types: [new Schema({type: String})]}),
           A = db.model('splicetestEmbeddedDoc', schema, collection);
 
       var a = new A({types: [{type: 'bird'}, {type: 'boy'}, {type: 'frog'}, {type: 'cloud'}]});
-      a.save(function (err) {
+      a.save(function(err) {
         assert.ifError(err);
-        A.findById(a._id, function (err, doc) {
+        A.findById(a._id, function(err, doc) {
           assert.ifError(err);
 
           doc.types.$pop();
@@ -369,9 +369,9 @@ describe('types array', function () {
           assert.equal(obj[0].type, 'bird');
           assert.equal(obj[1].type, 'frog');
 
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
-            A.findById(a._id, function (err, doc) {
+            A.findById(a._id, function(err, doc) {
               assert.ifError(err);
 
               var obj = doc.types.toObject();
@@ -385,18 +385,18 @@ describe('types array', function () {
     });
   });
 
-  describe('unshift()', function () {
+  describe('unshift()', function() {
     var db;
 
-    before(function () {
+    before(function() {
       db = start();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('works', function (done) {
+    it('works', function(done) {
       var schema = new Schema({
             types: [new Schema({type: String})],
             nums: [Number],
@@ -410,9 +410,9 @@ describe('types array', function () {
         strs: 'one two three'.split(' ')
       });
 
-      a.save(function (err) {
+      a.save(function(err) {
         assert.ifError(err);
-        A.findById(a._id, function (err, doc) {
+        A.findById(a._id, function(err, doc) {
           assert.ifError(err);
 
           var tlen = doc.types.unshift({type: 'tree'});
@@ -444,9 +444,9 @@ describe('types array', function () {
           assert.equal(obj[2], 'two');
           assert.equal(obj[3], 'three');
 
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
-            A.findById(a._id, function (err, doc) {
+            A.findById(a._id, function(err, doc) {
               assert.ifError(err);
 
               var obj = doc.types.toObject();
@@ -475,7 +475,7 @@ describe('types array', function () {
       });
     });
 
-    it('applies setters (gh-3032)', function (done) {
+    it('applies setters (gh-3032)', function(done) {
       var ST = db.model('setterArray', Schema({
         arr: [{
           type: String,
@@ -483,7 +483,7 @@ describe('types array', function () {
         }]
       }));
       var m = new ST({arr: ['ONE', 'TWO']});
-      m.save(function (err, doc) {
+      m.save(function(err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         doc.arr.unshift('THREE');
@@ -491,7 +491,7 @@ describe('types array', function () {
         assert.strictEqual('one', doc.arr[1]);
         assert.strictEqual('two', doc.arr[2]);
 
-        doc.save(function (err, doc) {
+        doc.save(function(err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.strictEqual('three', doc.arr[0]);
@@ -504,17 +504,17 @@ describe('types array', function () {
     });
   });
 
-  describe('shift()', function () {
+  describe('shift()', function() {
     var db;
-    before(function () {
+    before(function() {
       db = start();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('works', function (done) {
+    it('works', function(done) {
       var schema = new Schema({
         types: [new Schema({type: String})],
         nums: [Number],
@@ -529,9 +529,9 @@ describe('types array', function () {
         strs: 'one two three'.split(' ')
       });
 
-      a.save(function (err) {
+      a.save(function(err) {
         assert.ifError(err);
-        A.findById(a._id, function (err, doc) {
+        A.findById(a._id, function(err, doc) {
           assert.ifError(err);
 
           var t = doc.types.shift();
@@ -557,9 +557,9 @@ describe('types array', function () {
           assert.equal(obj[0], 'two');
           assert.equal(obj[1], 'three');
 
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
-            A.findById(a._id, function (err, doc) {
+            A.findById(a._id, function(err, doc) {
               db.close();
               assert.ifError(err);
 
@@ -584,17 +584,17 @@ describe('types array', function () {
     });
   });
 
-  describe('$shift', function () {
-    it('works', function (done) {
+  describe('$shift', function() {
+    it('works', function(done) {
       // atomic shift uses $pop -1
       var db = start();
       var painting = new Schema({colors: []});
       var Painting = db.model('Painting', painting);
       var p = new Painting({colors: ['blue', 'green', 'yellow']});
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
-        Painting.findById(p, function (err, doc) {
+        Painting.findById(p, function(err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.colors.length);
           var color = doc.colors.$shift();
@@ -605,14 +605,14 @@ describe('types array', function () {
           color = doc.colors.$shift();
           assert.equal(color, undefined);
           assert.equal(2, doc.colors.length);
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.equal(null, err);
             var color = doc.colors.$shift();
             assert.equal(1, doc.colors.length);
             assert.equal(color, 'green');
-            doc.save(function (err) {
+            doc.save(function(err) {
               assert.equal(null, err);
-              Painting.findById(doc, function (err, doc) {
+              Painting.findById(doc, function(err, doc) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(1, doc.colors.length);
@@ -626,8 +626,8 @@ describe('types array', function () {
     });
   });
 
-  describe('pop()', function () {
-    it('works', function (done) {
+  describe('pop()', function() {
+    it('works', function(done) {
       var db = start(),
           schema = new Schema({
             types: [new Schema({type: String})],
@@ -643,9 +643,9 @@ describe('types array', function () {
         strs: 'one two three'.split(' ')
       });
 
-      a.save(function (err) {
+      a.save(function(err) {
         assert.ifError(err);
-        A.findById(a._id, function (err, doc) {
+        A.findById(a._id, function(err, doc) {
           assert.ifError(err);
 
           var t = doc.types.pop();
@@ -671,9 +671,9 @@ describe('types array', function () {
           assert.equal(obj[0], 'one');
           assert.equal(obj[1], 'two');
 
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
-            A.findById(a._id, function (err, doc) {
+            A.findById(a._id, function(err, doc) {
               db.close();
               assert.ifError(err);
 
@@ -698,8 +698,8 @@ describe('types array', function () {
     });
   });
 
-  describe('pull()', function () {
-    it('works', function (done) {
+  describe('pull()', function() {
+    it('works', function(done) {
       var db = start();
       var catschema = new Schema({name: String});
       var Cat = db.model('Cat', catschema);
@@ -708,14 +708,14 @@ describe('types array', function () {
       });
       var A = db.model('TestPull', schema);
       var cat = new Cat({name: 'peanut'});
-      cat.save(function (err) {
+      cat.save(function(err) {
         assert.ifError(err);
 
         var a = new A({a: [cat._id]});
-        a.save(function (err) {
+        a.save(function(err) {
           assert.ifError(err);
 
-          A.findById(a, function (err, doc) {
+          A.findById(a, function(err, doc) {
             db.close();
             assert.ifError(err);
             assert.equal(1, doc.a.length);
@@ -727,7 +727,7 @@ describe('types array', function () {
       });
     });
 
-    it('handles pulling with no _id (gh-3341)', function (done) {
+    it('handles pulling with no _id (gh-3341)', function(done) {
       var db = start();
       var personSchema = new Schema({
         name: String,
@@ -741,7 +741,7 @@ describe('types array', function () {
       var Band = db.model('gh3341', bandSchema, 'gh3341');
 
       var gnr = new Band({
-        name: "Guns N' Roses",
+        name: 'Guns N\' Roses',
         members: [
           {name: 'Axl', role: 'Lead Singer'},
           {name: 'Slash', role: 'Guitar'},
@@ -751,17 +751,17 @@ describe('types array', function () {
         ]
       });
 
-      gnr.save(function (error) {
+      gnr.save(function(error) {
         assert.ifError(error);
         gnr.members.pull({name: 'Slash', role: 'Guitar'});
-        gnr.save(function (error) {
+        gnr.save(function(error) {
           assert.ifError(error);
           assert.equal(gnr.members.length, 4);
           assert.equal(gnr.members[0].name, 'Axl');
           assert.equal(gnr.members[1].name, 'Izzy');
           assert.equal(gnr.members[2].name, 'Duff');
           assert.equal(gnr.members[3].name, 'Adler');
-          Band.findById(gnr._id, function (error, gnr) {
+          Band.findById(gnr._id, function(error, gnr) {
             assert.ifError(error);
             assert.equal(gnr.members.length, 4);
             assert.equal(gnr.members[0].name, 'Axl');
@@ -775,16 +775,16 @@ describe('types array', function () {
     });
   });
 
-  describe('$pop()', function () {
-    it('works', function (done) {
+  describe('$pop()', function() {
+    it('works', function(done) {
       var db = start();
       var painting = new Schema({colors: []});
       var Painting = db.model('Painting', painting);
       var p = new Painting({colors: ['blue', 'green', 'yellow']});
-      p.save(function (err) {
+      p.save(function(err) {
         assert.ifError(err);
 
-        Painting.findById(p, function (err, doc) {
+        Painting.findById(p, function(err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.colors.length);
           var color = doc.colors.$pop();
@@ -796,14 +796,14 @@ describe('types array', function () {
           assert.equal(color, undefined);
           assert.equal(2, doc.colors.length);
           assert.equal(false, '$set' in doc.colors._atomics, 'invalid $atomic op used');
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.equal(null, err);
             var color = doc.colors.$pop();
             assert.equal(1, doc.colors.length);
             assert.equal(color, 'green');
-            doc.save(function (err) {
+            doc.save(function(err) {
               assert.equal(null, err);
-              Painting.findById(doc, function (err, doc) {
+              Painting.findById(doc, function(err, doc) {
                 db.close();
                 assert.strictEqual(null, err);
                 assert.equal(1, doc.colors.length);
@@ -817,8 +817,8 @@ describe('types array', function () {
     });
   });
 
-  describe('addToSet()', function () {
-    it('works', function (done) {
+  describe('addToSet()', function() {
+    it('works', function(done) {
       var db = start(),
           e = new Schema({name: String, arr: []}),
           schema = new Schema({
@@ -869,9 +869,9 @@ describe('types array', function () {
       m.date.addToSet(d3);
       assert.equal(m.date.length, 3);
 
-      m.save(function (err) {
+      m.save(function(err) {
         assert.ifError(err);
-        M.findById(m, function (err, m) {
+        M.findById(m, function(err, m) {
           assert.ifError(err);
 
           assert.equal(m.num.length, 5);
@@ -899,13 +899,13 @@ describe('types array', function () {
           assert.ok(~m.date.indexOf(d3.toString()));
 
           assert.equal(m.doc.length, 3);
-          assert.ok(m.doc.some(function (v) {
+          assert.ok(m.doc.some(function(v) {
             return v.name === 'Waltz';
           }));
-          assert.ok(m.doc.some(function (v) {
+          assert.ok(m.doc.some(function(v) {
             return v.name === 'Dubstep';
           }));
-          assert.ok(m.doc.some(function (v) {
+          assert.ok(m.doc.some(function(v) {
             return v.name === 'Polka';
           }));
 
@@ -923,10 +923,10 @@ describe('types array', function () {
           m.doc.addToSet(m.doc[0], {name: '8bit'});
           assert.equal(m.doc.length, 4);
 
-          m.save(function (err) {
+          m.save(function(err) {
             assert.ifError(err);
 
-            M.findById(m, function (err, m) {
+            M.findById(m, function(err, m) {
               assert.ifError(err);
 
               assert.equal(m.num.length, 6);
@@ -958,16 +958,16 @@ describe('types array', function () {
               assert.ok(~m.date.indexOf(d4.toString()));
 
               assert.equal(m.doc.length, 4);
-              assert.ok(m.doc.some(function (v) {
+              assert.ok(m.doc.some(function(v) {
                 return v.name === 'Waltz';
               }));
-              assert.ok(m.doc.some(function (v) {
+              assert.ok(m.doc.some(function(v) {
                 return v.name === 'Dubstep';
               }));
-              assert.ok(m.doc.some(function (v) {
+              assert.ok(m.doc.some(function(v) {
                 return v.name === 'Polka';
               }));
-              assert.ok(m.doc.some(function (v) {
+              assert.ok(m.doc.some(function(v) {
                 return v.name === '8bit';
               }));
 
@@ -985,10 +985,10 @@ describe('types array', function () {
               m.doc.addToSet(m.doc[1], {name: 'BigBeat'}, {name: 'Funk'});
               assert.equal(m.doc.length, 6);
 
-              m.save(function (err) {
+              m.save(function(err) {
                 assert.ifError(err);
 
-                M.findById(m, function (err, m) {
+                M.findById(m, function(err, m) {
                   db.close();
                   assert.ifError(err);
 
@@ -1029,22 +1029,22 @@ describe('types array', function () {
                   assert.ok(~m.date.indexOf(d6.toString()));
 
                   assert.equal(m.doc.length, 6);
-                  assert.ok(m.doc.some(function (v) {
+                  assert.ok(m.doc.some(function(v) {
                     return v.name === 'Waltz';
                   }));
-                  assert.ok(m.doc.some(function (v) {
+                  assert.ok(m.doc.some(function(v) {
                     return v.name === 'Dubstep';
                   }));
-                  assert.ok(m.doc.some(function (v) {
+                  assert.ok(m.doc.some(function(v) {
                     return v.name === 'Polka';
                   }));
-                  assert.ok(m.doc.some(function (v) {
+                  assert.ok(m.doc.some(function(v) {
                     return v.name === '8bit';
                   }));
-                  assert.ok(m.doc.some(function (v) {
+                  assert.ok(m.doc.some(function(v) {
                     return v.name === 'BigBeat';
                   }));
-                  assert.ok(m.doc.some(function (v) {
+                  assert.ok(m.doc.some(function(v) {
                     return v.name === 'Funk';
                   }));
                   done();
@@ -1056,7 +1056,7 @@ describe('types array', function () {
       });
     });
 
-    it('handles sub-documents that do not have an _id gh-1973', function (done) {
+    it('handles sub-documents that do not have an _id gh-1973', function(done) {
       var db = start(),
           e = new Schema({name: String, arr: []}, {_id: false}),
           schema = new Schema({
@@ -1067,19 +1067,19 @@ describe('types array', function () {
       var m = new M;
 
       m.doc.addToSet({name: 'Rap'});
-      m.save(function (error, m) {
+      m.save(function(error, m) {
         assert.ifError(error);
         assert.equal(1, m.doc.length);
         assert.equal('Rap', m.doc[0].name);
         m.doc.addToSet({name: 'House'});
         assert.equal(2, m.doc.length);
-        m.save(function (error, m) {
+        m.save(function(error, m) {
           assert.ifError(error);
           assert.equal(2, m.doc.length);
-          assert.ok(m.doc.some(function (v) {
+          assert.ok(m.doc.some(function(v) {
             return v.name === 'Rap';
           }));
-          assert.ok(m.doc.some(function (v) {
+          assert.ok(m.doc.some(function(v) {
             return v.name === 'House';
           }));
           db.close(done);
@@ -1087,7 +1087,7 @@ describe('types array', function () {
       });
     });
 
-    it('applies setters (gh-3032)', function (done) {
+    it('applies setters (gh-3032)', function(done) {
       var db = start();
       var ST = db.model('setterArray', Schema({
         arr: [{
@@ -1096,7 +1096,7 @@ describe('types array', function () {
         }]
       }));
       var m = new ST({arr: ['ONE', 'TWO']});
-      m.save(function (err, doc) {
+      m.save(function(err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         doc.arr.addToSet('THREE');
@@ -1104,7 +1104,7 @@ describe('types array', function () {
         assert.strictEqual('two', doc.arr[1]);
         assert.strictEqual('three', doc.arr[2]);
 
-        doc.save(function (err, doc) {
+        doc.save(function(err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.strictEqual('one', doc.arr[0]);
@@ -1117,8 +1117,8 @@ describe('types array', function () {
     });
   });
 
-  describe('nonAtomicPush()', function () {
-    it('works', function (done) {
+  describe('nonAtomicPush()', function() {
+    it('works', function(done) {
       var db = start();
       var U = db.model('User');
       var ID = mongoose.Types.ObjectId;
@@ -1127,9 +1127,9 @@ describe('types array', function () {
       assert.equal(u.pets.length, 1);
       u.pets.nonAtomicPush(new ID);
       assert.equal(u.pets.length, 2);
-      u.save(function (err) {
+      u.save(function(err) {
         assert.ifError(err);
-        U.findById(u._id, function (err) {
+        U.findById(u._id, function(err) {
           assert.ifError(err);
           assert.equal(u.pets.length, 2);
           var id0 = u.pets[0];
@@ -1140,9 +1140,9 @@ describe('types array', function () {
           assert.equal(u.pets.length, 2);
           assert.equal(u.pets[0].toString(), id1.toString());
           assert.equal(u.pets[1].toString(), id2.toString());
-          u.save(function (err) {
+          u.save(function(err) {
             assert.ifError(err);
-            U.findById(u._id, function (err) {
+            U.findById(u._id, function(err) {
               db.close();
               assert.ifError(err);
               assert.equal(u.pets.length, 2);
@@ -1156,14 +1156,14 @@ describe('types array', function () {
     });
   });
 
-  describe('sort()', function () {
-    it('order should be saved', function (done) {
+  describe('sort()', function() {
+    it('order should be saved', function(done) {
       var db = start();
       var M = db.model('ArraySortOrder', new Schema({x: [Number]}));
       var m = new M({x: [1, 4, 3, 2]});
-      m.save(function (err) {
+      m.save(function(err) {
         assert.ifError(err);
-        M.findById(m, function (err, m) {
+        M.findById(m, function(err, m) {
           assert.ifError(err);
 
           assert.equal(1, m.x[0]);
@@ -1173,9 +1173,9 @@ describe('types array', function () {
 
           m.x.sort();
 
-          m.save(function (err) {
+          m.save(function(err) {
             assert.ifError(err);
-            M.findById(m, function (err, m) {
+            M.findById(m, function(err, m) {
               assert.ifError(err);
 
               assert.equal(1, m.x[0]);
@@ -1183,13 +1183,13 @@ describe('types array', function () {
               assert.equal(3, m.x[2]);
               assert.equal(4, m.x[3]);
 
-              m.x.sort(function (a, b) {
+              m.x.sort(function(a, b) {
                 return b > a;
               });
 
-              m.save(function (err) {
+              m.save(function(err) {
                 assert.ifError(err);
-                M.findById(m, function (err, m) {
+                M.findById(m, function(err, m) {
                   assert.ifError(err);
 
                   assert.equal(4, m.x[0]);
@@ -1206,11 +1206,11 @@ describe('types array', function () {
     });
   });
 
-  describe('set()', function () {
+  describe('set()', function() {
     var db, N, S, B, M, D, ST;
 
     function save(doc, cb) {
-      doc.save(function (err) {
+      doc.save(function(err) {
         if (err) {
           return cb(err);
         }
@@ -1218,7 +1218,7 @@ describe('types array', function () {
       });
     }
 
-    before(function (done) {
+    before(function(done) {
       db = start();
       N = db.model('arraySet', Schema({arr: [Number]}));
       S = db.model('arraySetString', Schema({arr: [String]}));
@@ -1234,13 +1234,13 @@ describe('types array', function () {
       done();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('works combined with other ops', function (done) {
+    it('works combined with other ops', function(done) {
       var m = new N({arr: [3, 4, 5, 6]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
 
         assert.equal(4, doc.arr.length);
@@ -1250,7 +1250,7 @@ describe('types array', function () {
         assert.equal(10, doc.arr[2]);
         assert.equal(20, doc.arr[4]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.equal(3, doc.arr[0]);
@@ -1271,7 +1271,7 @@ describe('types array', function () {
           assert.equal(6, doc.arr[2]);
           assert.equal(99, doc.arr[3]);
 
-          save(doc, function (err, doc) {
+          save(doc, function(err, doc) {
             assert.ifError(err);
             assert.equal(4, doc.arr.length);
             assert.equal(3, doc.arr[0]);
@@ -1286,9 +1286,9 @@ describe('types array', function () {
       // after this works go back to finishing doc.populate() branch
     });
 
-    it('works with numbers', function (done) {
+    it('works with numbers', function(done) {
       var m = new N({arr: [3, 4, 5, 6]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.set(2, 10);
@@ -1298,7 +1298,7 @@ describe('types array', function () {
         assert.equal(5, doc.arr.length);
         assert.equal(11, doc.arr[4]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.equal(3, doc.arr[0]);
@@ -1313,7 +1313,7 @@ describe('types array', function () {
           assert.strictEqual(1, doc.arr[8]);
           assert.equal(undefined, doc.arr[7]);
 
-          save(doc, function (err, doc) {
+          save(doc, function(err, doc) {
             assert.ifError(err);
 
             assert.equal(9, doc.arr.length);
@@ -1332,9 +1332,9 @@ describe('types array', function () {
       });
     });
 
-    it('works with strings', function (done) {
+    it('works with strings', function(done) {
       var m = new S({arr: [3, 4, 5, 6]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal('4', doc.arr.length);
         doc.arr.set(2, 10);
@@ -1344,7 +1344,7 @@ describe('types array', function () {
         assert.equal(5, doc.arr.length);
         assert.equal('11', doc.arr[4]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
           assert.equal(5, doc.arr.length);
           assert.equal('3', doc.arr[0]);
@@ -1359,7 +1359,7 @@ describe('types array', function () {
           assert.strictEqual('yo', doc.arr[8]);
           assert.equal(undefined, doc.arr[7]);
 
-          save(doc, function (err, doc) {
+          save(doc, function(err, doc) {
             assert.ifError(err);
 
             assert.equal('9', doc.arr.length);
@@ -1378,9 +1378,9 @@ describe('types array', function () {
       });
     });
 
-    it('works with buffers', function (done) {
+    it('works with buffers', function(done) {
       var m = new B({arr: [[0], new Buffer(1)]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         assert.ok(doc.arr[0].isMongooseBuffer);
@@ -1393,7 +1393,7 @@ describe('types array', function () {
         assert.equal(3, doc.arr.length);
         assert.equal(11, doc.arr[2][0]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.ok(doc.arr[0].isMongooseBuffer);
@@ -1407,9 +1407,9 @@ describe('types array', function () {
       });
     });
 
-    it('works with mixed', function (done) {
+    it('works with mixed', function(done) {
       var m = new M({arr: [3, {x: 1}, 'yes', [5]]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(4, doc.arr.length);
         doc.arr.set(2, null);
@@ -1419,7 +1419,7 @@ describe('types array', function () {
         assert.equal(5, doc.arr.length);
         assert.equal('last', doc.arr[4]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
 
           assert.equal(5, doc.arr.length);
@@ -1439,7 +1439,7 @@ describe('types array', function () {
           assert.equal('', doc.arr[9].toString());
           assert.equal(10, doc.arr.length);
 
-          save(doc, function (err, doc) {
+          save(doc, function(err, doc) {
             assert.ifError(err);
 
             assert.equal(10, doc.arr.length);
@@ -1462,9 +1462,9 @@ describe('types array', function () {
       });
     });
 
-    it('works with sub-docs', function (done) {
+    it('works with sub-docs', function(done) {
       var m = new D({arr: [{name: 'aaron'}, {name: 'moombahton '}]});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         doc.arr.set(0, {name: 'vdrums'});
@@ -1474,7 +1474,7 @@ describe('types array', function () {
         assert.equal(3, doc.arr.length);
         assert.equal('Restrepo', doc.arr[2].name);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
 
           // validate
@@ -1488,7 +1488,7 @@ describe('types array', function () {
           assert.equal('temple of doom', doc.arr[10].name);
           assert.equal(null, doc.arr[9]);
 
-          save(doc, function (err, doc) {
+          save(doc, function(err, doc) {
             assert.ifError(err);
 
             // validate
@@ -1505,7 +1505,7 @@ describe('types array', function () {
             assert.strictEqual('7', doc.arr[7].name);
             assert.equal(10, doc.arr.length);
 
-            save(doc, function (err, doc) {
+            save(doc, function(err, doc) {
               assert.ifError(err);
 
               assert.equal(10, doc.arr.length);
@@ -1524,9 +1524,9 @@ describe('types array', function () {
       });
     });
 
-    it('applies setters (gh-3032)', function (done) {
+    it('applies setters (gh-3032)', function(done) {
       var m = new ST({arr: ['ONE', 'TWO']});
-      save(m, function (err, doc) {
+      save(m, function(err, doc) {
         assert.ifError(err);
         assert.equal(2, doc.arr.length);
         doc.arr.set(0, 'THREE');
@@ -1537,7 +1537,7 @@ describe('types array', function () {
         assert.strictEqual('two', doc.arr[1]);
         assert.strictEqual('four', doc.arr[2]);
 
-        save(doc, function (err, doc) {
+        save(doc, function(err, doc) {
           assert.ifError(err);
           assert.equal(3, doc.arr.length);
           assert.strictEqual('three', doc.arr[0]);
@@ -1550,8 +1550,8 @@ describe('types array', function () {
     });
   });
 
-  describe('setting a doc array', function () {
-    it('should adjust path positions', function (done) {
+  describe('setting a doc array', function() {
+    it('should adjust path positions', function(done) {
       var db = start();
 
       var D = db.model('subDocPositions', new Schema({
@@ -1566,9 +1566,9 @@ describe('types array', function () {
         ]
       });
 
-      d.save(function (err) {
+      d.save(function(err) {
         assert.ifError(err);
-        D.findById(d, function (err, d) {
+        D.findById(d, function(err, d) {
           assert.ifError(err);
 
           var n = d.em1.slice();
@@ -1579,9 +1579,9 @@ describe('types array', function () {
           x = x.filter(Boolean);
           d.em1 = x;
 
-          d.save(function (err) {
+          d.save(function(err) {
             assert.ifError(err);
-            D.findById(d, function (err, d) {
+            D.findById(d, function(err, d) {
               db.close();
               assert.ifError(err);
               assert.equal(d.em1[0].name, 'position two');
@@ -1594,8 +1594,8 @@ describe('types array', function () {
     });
   });
 
-  describe('paths with similar names', function () {
-    it('should be saved', function (done) {
+  describe('paths with similar names', function() {
+    it('should be saved', function(done) {
       var db = start();
 
       var D = db.model('similarPathNames', new Schema({
@@ -1611,9 +1611,9 @@ describe('types array', function () {
         em: [{name: 'bob'}]
       });
 
-      d.save(function (err) {
+      d.save(function(err) {
         assert.ifError(err);
-        D.findById(d, function (err, d) {
+        D.findById(d, function(err, d) {
           assert.ifError(err);
 
           d.account.role = 'president';
@@ -1621,9 +1621,9 @@ describe('types array', function () {
           d.em[0].name = 'memorable';
           d.em = [{name: 'frida'}];
 
-          d.save(function (err) {
+          d.save(function(err) {
             assert.ifError(err);
-            D.findById(d, function (err, d) {
+            D.findById(d, function(err, d) {
               db.close();
               assert.ifError(err);
               assert.equal(d.account.role, 'president');
@@ -1640,20 +1640,20 @@ describe('types array', function () {
     });
   });
 
-  describe('of number', function () {
-    it('allows nulls', function (done) {
+  describe('of number', function() {
+    it('allows nulls', function(done) {
       var db = start();
       var schema = new Schema({x: [Number]}, {collection: 'nullsareallowed' + random()});
       var M = db.model('nullsareallowed', schema);
       var m;
 
       m = new M({x: [1, null, 3]});
-      m.save(function (err) {
+      m.save(function(err) {
         assert.ifError(err);
 
         // undefined is not allowed
         m = new M({x: [1, undefined, 3]});
-        m.save(function (err) {
+        m.save(function(err) {
           db.close();
           assert.ok(err);
           done();
@@ -1662,24 +1662,24 @@ describe('types array', function () {
     });
   });
 
-  it('modifying subdoc props and manipulating the array works (gh-842)', function (done) {
+  it('modifying subdoc props and manipulating the array works (gh-842)', function(done) {
     var db = start();
     var schema = new Schema({em: [new Schema({username: String})]});
     var M = db.model('modifyingSubDocAndPushing', schema);
     var m = new M({em: [{username: 'Arrietty'}]});
 
-    m.save(function (err) {
+    m.save(function(err) {
       assert.ifError(err);
-      M.findById(m, function (err, m) {
+      M.findById(m, function(err, m) {
         assert.ifError(err);
         assert.equal(m.em[0].username, 'Arrietty');
 
         m.em[0].username = 'Shawn';
         m.em.push({username: 'Homily'});
-        m.save(function (err) {
+        m.save(function(err) {
           assert.ifError(err);
 
-          M.findById(m, function (err, m) {
+          M.findById(m, function(err, m) {
             assert.ifError(err);
             assert.equal(m.em.length, 2);
             assert.equal(m.em[0].username, 'Shawn');
@@ -1687,10 +1687,10 @@ describe('types array', function () {
 
             m.em[0].username = 'Arrietty';
             m.em[1].remove();
-            m.save(function (err) {
+            m.save(function(err) {
               assert.ifError(err);
 
-              M.findById(m, function (err, m) {
+              M.findById(m, function(err, m) {
                 db.close();
                 assert.ifError(err);
                 assert.equal(m.em.length, 1);
@@ -1704,13 +1704,13 @@ describe('types array', function () {
     });
   });
 
-  it('pushing top level arrays and subarrays works (gh-1073)', function (done) {
+  it('pushing top level arrays and subarrays works (gh-1073)', function(done) {
     var db = start();
     var schema = new Schema({em: [new Schema({sub: [String]})]});
     var M = db.model('gh1073', schema);
     var m = new M({em: [{sub: []}]});
-    m.save(function () {
-      M.findById(m, function (err, m) {
+    m.save(function() {
+      M.findById(m, function(err, m) {
         assert.ifError(err);
 
         m.em[m.em.length - 1].sub.push('a');
@@ -1719,10 +1719,10 @@ describe('types array', function () {
         assert.equal(2, m.em.length);
         assert.equal(1, m.em[0].sub.length);
 
-        m.save(function (err) {
+        m.save(function(err) {
           assert.ifError(err);
 
-          M.findById(m, function (err, m) {
+          M.findById(m, function(err, m) {
             assert.ifError(err);
             assert.equal(2, m.em.length);
             assert.equal(1, m.em[0].sub.length);
@@ -1734,8 +1734,8 @@ describe('types array', function () {
     });
   });
 
-  describe('default type', function () {
-    it('casts to Mixed', function (done) {
+  describe('default type', function() {
+    it('casts to Mixed', function(done) {
       var db = start(),
           DefaultArraySchema = new Schema({
             num1: Array,
@@ -1776,11 +1776,11 @@ describe('types array', function () {
     });
   });
 
-  describe('removing from an array atomically using MongooseArray#remove', function () {
+  describe('removing from an array atomically using MongooseArray#remove', function() {
     var db;
     var B;
 
-    before(function (done) {
+    before(function(done) {
       var schema = new Schema({
         numbers: ['number'],
         numberIds: [{_id: 'number', name: 'string'}],
@@ -1794,34 +1794,34 @@ describe('types array', function () {
       done();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('works', function (done) {
+    it('works', function(done) {
       var post = new B;
       post.numbers.push(1, 2, 3);
 
-      post.save(function (err) {
+      post.save(function(err) {
         assert.ifError(err);
 
-        B.findById(post._id, function (err, doc) {
+        B.findById(post._id, function(err, doc) {
           assert.ifError(err);
 
           doc.numbers.remove('1');
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
 
-            B.findById(post.get('_id'), function (err, doc) {
+            B.findById(post.get('_id'), function(err, doc) {
               assert.ifError(err);
 
               assert.equal(doc.numbers.length, 2);
               doc.numbers.remove('2', '3');
 
-              doc.save(function (err) {
+              doc.save(function(err) {
                 assert.ifError(err);
 
-                B.findById(post._id, function (err, doc) {
+                B.findById(post._id, function(err, doc) {
                   assert.ifError(err);
                   assert.equal(0, doc.numbers.length);
                   done();
@@ -1833,23 +1833,23 @@ describe('types array', function () {
       });
     });
 
-    describe('with subdocs', function () {
+    describe('with subdocs', function() {
       function docs(arr) {
-        return arr.map(function (val) {
+        return arr.map(function(val) {
           return {_id: val};
         });
       }
 
-      it('supports passing strings', function (done) {
+      it('supports passing strings', function(done) {
         var post = new B({stringIds: docs('a b c d'.split(' '))});
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
-          B.findById(post, function (err, post) {
+          B.findById(post, function(err, post) {
             assert.ifError(err);
             post.stringIds.remove('b');
-            post.save(function (err) {
+            post.save(function(err) {
               assert.ifError(err);
-              B.findById(post, function (err, post) {
+              B.findById(post, function(err, post) {
                 assert.ifError(err);
                 assert.equal(3, post.stringIds.length);
                 assert.ok(!post.stringIds.id('b'));
@@ -1859,16 +1859,16 @@ describe('types array', function () {
           });
         });
       });
-      it('supports passing numbers', function (done) {
+      it('supports passing numbers', function(done) {
         var post = new B({numberIds: docs([1, 2, 3, 4])});
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
-          B.findById(post, function (err, post) {
+          B.findById(post, function(err, post) {
             assert.ifError(err);
             post.numberIds.remove(2, 4);
-            post.save(function (err) {
+            post.save(function(err) {
               assert.ifError(err);
-              B.findById(post, function (err, post) {
+              B.findById(post, function(err, post) {
                 assert.ifError(err);
                 assert.equal(2, post.numberIds.length);
                 assert.ok(!post.numberIds.id(2));
@@ -1879,20 +1879,20 @@ describe('types array', function () {
           });
         });
       });
-      it('supports passing objectids', function (done) {
+      it('supports passing objectids', function(done) {
         var OID = mongoose.Types.ObjectId;
         var a = new OID;
         var b = new OID;
         var c = new OID;
         var post = new B({oidIds: docs([a, b, c])});
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
-          B.findById(post, function (err, post) {
+          B.findById(post, function(err, post) {
             assert.ifError(err);
             post.oidIds.remove(a, c);
-            post.save(function (err) {
+            post.save(function(err) {
               assert.ifError(err);
-              B.findById(post, function (err, post) {
+              B.findById(post, function(err, post) {
                 assert.ifError(err);
                 assert.equal(1, post.oidIds.length);
                 assert.ok(!post.oidIds.id(a));
@@ -1903,16 +1903,16 @@ describe('types array', function () {
           });
         });
       });
-      it('supports passing buffers', function (done) {
+      it('supports passing buffers', function(done) {
         var post = new B({bufferIds: docs(['a', 'b', 'c', 'd'])});
-        post.save(function (err) {
+        post.save(function(err) {
           assert.ifError(err);
-          B.findById(post, function (err, post) {
+          B.findById(post, function(err, post) {
             assert.ifError(err);
             post.bufferIds.remove(new Buffer('a'));
-            post.save(function (err) {
+            post.save(function(err) {
               assert.ifError(err);
-              B.findById(post, function (err, post) {
+              B.findById(post, function(err, post) {
                 assert.ifError(err);
                 assert.equal(3, post.bufferIds.length);
                 assert.ok(!post.bufferIds.id(new Buffer('a')));
diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js
index faca4d4b60f..e67738714e2 100644
--- a/test/types.buffer.test.js
+++ b/test/types.buffer.test.js
@@ -35,8 +35,8 @@ var UserBuffer = new Schema({
  * Test.
  */
 
-describe('types.buffer', function () {
-  it('test that a mongoose buffer behaves and quacks like a buffer', function (done) {
+describe('types.buffer', function() {
+  it('test that a mongoose buffer behaves and quacks like a buffer', function(done) {
     var a = new MongooseBuffer;
 
     assert.ok(a instanceof Buffer);
@@ -55,20 +55,20 @@ describe('types.buffer', function () {
     done();
   });
 
-  it('buffer validation', function (done) {
+  it('buffer validation', function(done) {
     var db = start(),
         User = db.model('UserBuffer', UserBuffer, 'usersbuffer_' + random());
 
-    User.on('index', function () {
+    User.on('index', function() {
       var t = new User({
         name: 'test validation'
       });
 
-      t.validate(function (err) {
+      t.validate(function(err) {
         assert.equal(err.message, 'UserBuffer validation failed');
         assert.equal(err.errors.required.kind, 'required');
         t.required = {x: [20]};
-        t.save(function (err) {
+        t.save(function(err) {
           assert.ok(err);
           assert.equal(err.name, 'ValidationError');
           assert.equal(err.errors.required.name, 'CastError');
@@ -78,17 +78,17 @@ describe('types.buffer', function () {
           t.required = new Buffer('hello');
 
           t.sub.push({name: 'Friday Friday'});
-          t.save(function (err) {
+          t.save(function(err) {
             assert.equal(err.message, 'UserBuffer validation failed');
             assert.equal(err.errors['sub.0.buf'].kind, 'required');
             t.sub[0].buf = new Buffer('well well');
-            t.save(function (err) {
+            t.save(function(err) {
               assert.equal(err.message, 'UserBuffer validation failed');
               assert.equal(err.errors['sub.0.buf'].kind, 'user defined');
               assert.equal(err.errors['sub.0.buf'].message, 'valid failed');
 
               t.sub[0].buf = new Buffer('well well well');
-              t.validate(function (err) {
+              t.validate(function(err) {
                 db.close();
                 assert.ifError(err);
                 done();
@@ -100,11 +100,11 @@ describe('types.buffer', function () {
     });
   });
 
-  it('buffer storage', function (done) {
+  it('buffer storage', function(done) {
     var db = start(),
         User = db.model('UserBuffer', UserBuffer, 'usersbuffer_' + random());
 
-    User.on('index', function () {
+    User.on('index', function() {
       var sampleBuffer = new Buffer([123, 223, 23, 42, 11]);
 
       var tj = new User({
@@ -113,9 +113,9 @@ describe('types.buffer', function () {
         required: new Buffer(sampleBuffer)
       });
 
-      tj.save(function (err) {
+      tj.save(function(err) {
         assert.ifError(err);
-        User.find({}, function (err, users) {
+        User.find({}, function(err, users) {
           db.close();
           assert.ifError(err);
           assert.equal(users.length, 1);
@@ -131,11 +131,11 @@ describe('types.buffer', function () {
     });
   });
 
-  it('test write markModified', function (done) {
+  it('test write markModified', function(done) {
     var db = start(),
         User = db.model('UserBuffer', UserBuffer, 'usersbuffer_' + random());
 
-    User.on('index', function () {
+    User.on('index', function() {
       var sampleBuffer = new Buffer([123, 223, 23, 42, 11]);
 
       var tj = new User({
@@ -144,16 +144,16 @@ describe('types.buffer', function () {
         required: sampleBuffer
       });
 
-      tj.save(function (err) {
+      tj.save(function(err) {
         assert.ifError(err);
 
         tj.serial.write('aa', 1, 'ascii');
         assert.equal(true, tj.isModified('serial'));
 
-        tj.save(function (err) {
+        tj.save(function(err) {
           assert.ifError(err);
 
-          User.findById(tj._id, function (err, user) {
+          User.findById(tj._id, function(err, user) {
             db.close();
             assert.ifError(err);
 
@@ -177,55 +177,55 @@ describe('types.buffer', function () {
 
             // buffer method tests
             var fns = {
-              writeUInt8: function () {
+              writeUInt8: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt8(0x3, 0, 'big');
                 is(tj);
               },
-              writeUInt16: function () {
+              writeUInt16: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt16(0xbeef, 0, 'little');
                 is(tj);
               },
-              writeUInt16LE: function () {
+              writeUInt16LE: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt16LE(0xbeef, 0);
                 is(tj);
               },
-              writeUInt16BE: function () {
+              writeUInt16BE: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt16BE(0xbeef, 0);
                 is(tj);
               },
-              writeUInt32: function () {
+              writeUInt32: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt32(0xfeedface, 0, 'little');
                 is(tj);
               },
-              writeUInt32LE: function () {
+              writeUInt32LE: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt32LE(0xfeedface, 0);
                 is(tj);
               },
-              writeUInt32BE: function () {
+              writeUInt32BE: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeUInt32BE(0xfeedface, 0);
                 is(tj);
               },
-              writeInt8: function () {
+              writeInt8: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt8(-5, 0, 'big');
                 is(tj);
               },
-              writeInt16: function () {
+              writeInt16: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt16(0x0023, 2, 'little');
@@ -233,7 +233,7 @@ describe('types.buffer', function () {
                 assert.equal(tj.required[2], 0x23);
                 assert.equal(tj.required[3], 0x00);
               },
-              writeInt16LE: function () {
+              writeInt16LE: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt16LE(0x0023, 2);
@@ -241,13 +241,13 @@ describe('types.buffer', function () {
                 assert.equal(tj.required[2], 0x23);
                 assert.equal(tj.required[3], 0x00);
               },
-              writeInt16BE: function () {
+              writeInt16BE: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt16BE(0x0023, 2);
                 is(tj);
               },
-              writeInt32: function () {
+              writeInt32: function() {
                 reset(tj);
                 not(tj);
                 tj.required.writeInt32(0x23, 0, 'big');
@@ -258,14 +258,14 @@ describe('types.buffer', function () {
                 assert.equal(tj.required[3], 0x23);
                 tj.required = new Buffer(8);
               },
-              writeInt32LE: function () {
+              writeInt32LE: function() {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
                 tj.required.writeInt32LE(0x23, 0);
                 is(tj);
               },
-              writeInt32BE: function () {
+              writeInt32BE: function() {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
@@ -276,7 +276,7 @@ describe('types.buffer', function () {
                 assert.equal(tj.required[2], 0x00);
                 assert.equal(tj.required[3], 0x23);
               },
-              writeFloat: function () {
+              writeFloat: function() {
                 tj.required = new Buffer(16);
                 reset(tj);
                 not(tj);
@@ -291,35 +291,35 @@ describe('types.buffer', function () {
                 assert.equal(tj.required[6], 0xff);
                 assert.equal(tj.required[7], 0xff);
               },
-              writeFloatLE: function () {
+              writeFloatLE: function() {
                 tj.required = new Buffer(16);
                 reset(tj);
                 not(tj);
                 tj.required.writeFloatLE(2.225073858507201e-308, 0);
                 is(tj);
               },
-              writeFloatBE: function () {
+              writeFloatBE: function() {
                 tj.required = new Buffer(16);
                 reset(tj);
                 not(tj);
                 tj.required.writeFloatBE(2.225073858507201e-308, 0);
                 is(tj);
               },
-              writeDoubleLE: function () {
+              writeDoubleLE: function() {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
                 tj.required.writeDoubleLE(0xdeadbeefcafebabe, 0);
                 is(tj);
               },
-              writeDoubleBE: function () {
+              writeDoubleBE: function() {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
                 tj.required.writeDoubleBE(0xdeadbeefcafebabe, 0);
                 is(tj);
               },
-              fill: function () {
+              fill: function() {
                 tj.required = new Buffer(8);
                 reset(tj);
                 not(tj);
@@ -329,7 +329,7 @@ describe('types.buffer', function () {
                   assert.strictEqual(tj.required[i], 0);
                 }
               },
-              set: function () {
+              set: function() {
                 reset(tj);
                 not(tj);
                 tj.required.set(0, 1);
@@ -356,19 +356,19 @@ describe('types.buffer', function () {
     function reset(model) {
       // internal
       model.$__.activePaths.clear('modify');
-      model.schema.requiredPaths().forEach(function (path) {
+      model.schema.requiredPaths().forEach(function(path) {
         model.$__.activePaths.require(path);
       });
     }
   });
 
-  it('can be set to null', function (done) {
+  it('can be set to null', function(done) {
     var db = start(),
         User = db.model('UserBuffer', UserBuffer, 'usersbuffer_' + random());
     var user = new User({array: [null], required: new Buffer(1)});
-    user.save(function (err, doc) {
+    user.save(function(err, doc) {
       assert.ifError(err);
-      User.findById(doc, function (err, doc) {
+      User.findById(doc, function(err, doc) {
         db.close();
         assert.ifError(err);
         assert.equal(1, doc.array.length);
@@ -378,8 +378,8 @@ describe('types.buffer', function () {
     });
   });
 
-  describe('#toObject', function () {
-    it('retains custom subtypes', function (done) {
+  describe('#toObject', function() {
+    it('retains custom subtypes', function(done) {
       var buf = new MongooseBuffer(0);
       var out = buf.toObject(2);
       // validate the drivers Binary type output retains the option
@@ -388,39 +388,39 @@ describe('types.buffer', function () {
     });
   });
 
-  describe('subtype', function () {
+  describe('subtype', function() {
     var db, bufferSchema, B;
 
-    before(function (done) {
+    before(function(done) {
       db = start();
       bufferSchema = new Schema({buf: Buffer});
       B = db.model('1571', bufferSchema);
       done();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('default value', function (done) {
+    it('default value', function(done) {
       var b = new B({buf: new Buffer('hi')});
       assert.strictEqual(0, b.buf._subtype);
       done();
     });
 
-    it('method works', function (done) {
+    it('method works', function(done) {
       var b = new B({buf: new Buffer('hi')});
       b.buf.subtype(128);
       assert.strictEqual(128, b.buf._subtype);
       done();
     });
 
-    it('is stored', function (done) {
+    it('is stored', function(done) {
       var b = new B({buf: new Buffer('hi')});
       b.buf.subtype(128);
-      b.save(function (err) {
+      b.save(function(err) {
         if (err) return done(err);
-        B.findById(b, function (err, doc) {
+        B.findById(b, function(err, doc) {
           if (err) return done(err);
           assert.equal(128, doc.buf._subtype);
           done();
@@ -428,18 +428,18 @@ describe('types.buffer', function () {
       });
     });
 
-    it('changes are retained', function (done) {
+    it('changes are retained', function(done) {
       var b = new B({buf: new Buffer('hi')});
       b.buf.subtype(128);
-      b.save(function (err) {
+      b.save(function(err) {
         if (err) return done(err);
-        B.findById(b, function (err, doc) {
+        B.findById(b, function(err, doc) {
           if (err) return done(err);
           assert.equal(128, doc.buf._subtype);
           doc.buf.subtype(0);
-          doc.save(function (err) {
+          doc.save(function(err) {
             if (err) return done(err);
-            B.findById(b, function (err, doc) {
+            B.findById(b, function(err, doc) {
               if (err) return done(err);
               assert.strictEqual(0, doc.buf._subtype);
               done();
@@ -449,7 +449,7 @@ describe('types.buffer', function () {
       });
     });
 
-    it('cast from number (gh-3764)', function (done) {
+    it('cast from number (gh-3764)', function(done) {
       var schema = new Schema({buf: Buffer});
       var MyModel = mongoose.model('gh3764', schema);
 
diff --git a/test/types.document.test.js b/test/types.document.test.js
index b78da80f8e2..8b3ae85bb6e 100644
--- a/test/types.document.test.js
+++ b/test/types.document.test.js
@@ -64,14 +64,14 @@ mongoose.model('Movie', MovieSchema);
  * Test.
  */
 
-describe('types.document', function () {
-  it('test that validate sets errors', function (done) {
+describe('types.document', function() {
+  it('test that validate sets errors', function(done) {
     var a = new Subdocument();
     a.set('test', '');
     a.set('work', 'nope');
     a.__index = 0;
 
-    a.validate(function () {
+    a.validate(function() {
       assert.ok(a.__parent.$__.validationError instanceof ValidationError);
       assert.equal(a.__parent.errors['jsconf.ar.0.work'].name, 'ValidatorError');
       assert.equal(a.__parent.$__.validationError.toString(), 'ValidationError: Path `test` is required., Validator failed for path `work` with value `nope`');
@@ -79,7 +79,7 @@ describe('types.document', function () {
     });
   });
 
-  it('objects can be passed to #set', function (done) {
+  it('objects can be passed to #set', function(done) {
     var a = new Subdocument();
     a.set({test: 'paradiddle', work: 'good flam'});
     assert.equal(a.test, 'paradiddle');
@@ -87,7 +87,7 @@ describe('types.document', function () {
     done();
   });
 
-  it('Subdocuments can be passed to #set', function (done) {
+  it('Subdocuments can be passed to #set', function(done) {
     var a = new Subdocument();
     a.set({test: 'paradiddle', work: 'good flam'});
     assert.equal(a.test, 'paradiddle');
@@ -99,7 +99,7 @@ describe('types.document', function () {
     done();
   });
 
-  it('cached _ids', function (done) {
+  it('cached _ids', function(done) {
     var db = start();
     var Movie = db.model('Movie');
     var m = new Movie;
@@ -120,7 +120,7 @@ describe('types.document', function () {
     db.close(done);
   });
 
-  it('Subdocument#remove (gh-531)', function (done) {
+  it('Subdocument#remove (gh-531)', function(done) {
     var db = start();
     var Movie = db.model('Movie');
 
@@ -136,7 +136,7 @@ describe('types.document', function () {
     super8.ratings.push({stars: 7, _id: id3});
     super8.ratings.push({stars: 6, _id: id4});
 
-    super8.save(function (err) {
+    super8.save(function(err) {
       assert.ifError(err);
 
       assert.equal(super8.title, 'Super 8');
@@ -150,10 +150,10 @@ describe('types.document', function () {
       super8.ratings.id(id3).stars = 4;
       super8.ratings.id(id4).stars = 3;
 
-      super8.save(function (err) {
+      super8.save(function(err) {
         assert.ifError(err);
 
-        Movie.findById(super8._id, function (err, movie) {
+        Movie.findById(super8._id, function(err, movie) {
           assert.ifError(err);
 
           assert.equal(movie.title, 'Super 8');
@@ -166,10 +166,10 @@ describe('types.document', function () {
           movie.ratings.id(id3).remove();
           movie.ratings.id(id4).stars = 1;
 
-          movie.save(function (err) {
+          movie.save(function(err) {
             assert.ifError(err);
 
-            Movie.findById(super8._id, function (err, movie) {
+            Movie.findById(super8._id, function(err, movie) {
               assert.ifError(err);
               assert.equal(movie.ratings.length, 2);
               assert.equal(movie.ratings.id(id1).stars.valueOf(), 2);
@@ -178,8 +178,8 @@ describe('types.document', function () {
               // gh-531
               movie.ratings[0].remove();
               movie.ratings[0].remove();
-              movie.save(function () {
-                Movie.findById(super8._id, function (err, movie) {
+              movie.save(function() {
+                Movie.findById(super8._id, function(err, movie) {
                   assert.ifError(err);
                   assert.equal(0, movie.ratings.length);
                   db.close(done);
@@ -192,8 +192,8 @@ describe('types.document', function () {
     });
   });
 
-  describe('setting nested objects', function () {
-    it('works (gh-1394)', function (done) {
+  describe('setting nested objects', function() {
+    it('works (gh-1394)', function(done) {
       var db = start();
       var Movie = db.model('Movie');
 
@@ -207,19 +207,19 @@ describe('types.document', function () {
             }
           }
         }]
-      }, function (err, movie) {
+      }, function(err, movie) {
         assert.ifError(err);
 
-        Movie.findById(movie, function (err, movie) {
+        Movie.findById(movie, function(err, movie) {
           assert.ifError(err);
 
           assert.ok(movie.ratings[0].description.source.time instanceof Date);
           movie.ratings[0].description.source = {url: 'http://www.lifeofpimovie.com/'};
 
-          movie.save(function (err) {
+          movie.save(function(err) {
             assert.ifError(err);
 
-            Movie.findById(movie, function (err, movie) {
+            Movie.findById(movie, function(err, movie) {
               assert.ifError(err);
 
               assert.equal('http://www.lifeofpimovie.com/', movie.ratings[0].description.source.url);
@@ -229,10 +229,10 @@ describe('types.document', function () {
 
               var newDate = new Date;
               movie.ratings[0].set('description.source.time', newDate, {merge: true});
-              movie.save(function (err) {
+              movie.save(function(err) {
                 assert.ifError(err);
 
-                Movie.findById(movie, function (err, movie) {
+                Movie.findById(movie, function(err, movie) {
                   assert.ifError(err);
                   assert.equal(String(newDate), movie.ratings[0].description.source.time);
                   // url not overwritten using merge
diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js
index 4be76934d15..e80feb07dff 100644
--- a/test/types.documentarray.test.js
+++ b/test/types.documentarray.test.js
@@ -18,7 +18,7 @@ var start = require('./common'),
  */
 
 function TestDoc(schema) {
-  var Subdocument = function () {
+  var Subdocument = function() {
     EmbeddedDocument.call(this, {}, new DocumentArray);
   };
 
@@ -45,8 +45,8 @@ function TestDoc(schema) {
  * Test.
  */
 
-describe('types.documentarray', function () {
-  it('behaves and quacks like an array', function (done) {
+describe('types.documentarray', function() {
+  it('behaves and quacks like an array', function(done) {
     var a = new MongooseDocumentArray();
 
     assert.ok(a instanceof Array);
@@ -60,7 +60,7 @@ describe('types.documentarray', function () {
     done();
   });
 
-  it('#id', function (done) {
+  it('#id', function(done) {
     var Subdocument = TestDoc();
 
     var sub1 = new Subdocument();
@@ -188,8 +188,8 @@ describe('types.documentarray', function () {
     done();
   });
 
-  describe('inspect', function () {
-    it('works with bad data', function (done) {
+  describe('inspect', function() {
+    it('works with bad data', function(done) {
       var threw = false;
       var a = new MongooseDocumentArray([null]);
       try {
@@ -203,8 +203,8 @@ describe('types.documentarray', function () {
     });
   });
 
-  describe('toObject', function () {
-    it('works with bad data', function (done) {
+  describe('toObject', function() {
+    it('works with bad data', function(done) {
       var threw = false;
       var a = new MongooseDocumentArray([null]);
       try {
@@ -216,13 +216,13 @@ describe('types.documentarray', function () {
       assert.ok(!threw);
       done();
     });
-    it('passes options to its documents (gh-1415)', function (done) {
+    it('passes options to its documents (gh-1415)', function(done) {
       var subSchema = new Schema({
         title: {type: String}
       });
 
       subSchema.set('toObject', {
-        transform: function (doc, ret) {
+        transform: function(doc, ret) {
           // this should not be called because custom options are
           // passed during MongooseArray#toObject() calls
           ret.changed = 123;
@@ -238,7 +238,7 @@ describe('types.documentarray', function () {
       assert.equal(undefined, delta.$pushAll.docs[0].changed);
       done();
     });
-    it('uses the correct transform (gh-1412)', function (done) {
+    it('uses the correct transform (gh-1412)', function(done) {
       var db = start();
       var SecondSchema = new Schema({});
 
@@ -278,8 +278,8 @@ describe('types.documentarray', function () {
     });
   });
 
-  describe('create()', function () {
-    it('works', function (done) {
+  describe('create()', function() {
+    it('works', function(done) {
       var a = new MongooseDocumentArray([]);
       assert.equal('function', typeof a.create);
 
@@ -295,27 +295,27 @@ describe('types.documentarray', function () {
     });
   });
 
-  describe('push()', function () {
-    it('does not re-cast instances of its embedded doc', function (done) {
+  describe('push()', function() {
+    it('does not re-cast instances of its embedded doc', function(done) {
       var db = start();
 
       var child = new Schema({name: String, date: Date});
-      child.pre('save', function (next) {
+      child.pre('save', function(next) {
         this.date = new Date;
         next();
       });
       var schema = new Schema({children: [child]});
       var M = db.model('embeddedDocArray-push-re-cast', schema, 'edarecast-' + random());
       var m = new M;
-      m.save(function (err) {
+      m.save(function(err) {
         assert.ifError(err);
-        M.findById(m._id, function (err, doc) {
+        M.findById(m._id, function(err, doc) {
           assert.ifError(err);
           var c = doc.children.create({name: 'first'});
           assert.equal(undefined, c.date);
           doc.children.push(c);
           assert.equal(undefined, c.date);
-          doc.save(function (err) {
+          doc.save(function(err) {
             assert.ifError(err);
             assert.ok(doc.children[doc.children.length - 1].date);
             assert.equal(c.date, doc.children[doc.children.length - 1].date);
@@ -323,12 +323,12 @@ describe('types.documentarray', function () {
             doc.children.push(c);
             doc.children.push(c);
 
-            doc.save(function (err) {
+            doc.save(function(err) {
               assert.ifError(err);
-              M.findById(m._id, function (err, doc) {
+              M.findById(m._id, function(err, doc) {
                 assert.ifError(err);
                 assert.equal(3, doc.children.length);
-                doc.children.forEach(function (child) {
+                doc.children.forEach(function(child) {
                   assert.equal(doc.children[0].id, child.id);
                 });
                 db.close(done);
@@ -338,7 +338,7 @@ describe('types.documentarray', function () {
         });
       });
     });
-    it('corrects #ownerDocument() if value was created with array.create() (gh-1385)', function (done) {
+    it('corrects #ownerDocument() if value was created with array.create() (gh-1385)', function(done) {
       var mg = new mongoose.Mongoose;
       var M = mg.model('1385', {docs: [{name: String}]});
       var m = new M;
@@ -350,7 +350,7 @@ describe('types.documentarray', function () {
     });
   });
 
-  it('#push should work on EmbeddedDocuments more than 2 levels deep', function (done) {
+  it('#push should work on EmbeddedDocuments more than 2 levels deep', function(done) {
     var Comments = new Schema;
     Comments.add({
       title: String,
@@ -373,18 +373,18 @@ describe('types.documentarray', function () {
     c1.comments.push(c2);
     c2.comments.push(c3);
 
-    p.save(function (err) {
+    p.save(function(err) {
       assert.ifError(err);
 
-      Post.findById(p._id, function (err, p) {
+      Post.findById(p._id, function(err, p) {
         assert.ifError(err);
 
         var c4 = p.comments.create({title: 'c4'});
         p.comments[0].comments[0].comments[0].comments.push(c4);
-        p.save(function (err) {
+        p.save(function(err) {
           assert.ifError(err);
 
-          Post.findById(p._id, function (err, p) {
+          Post.findById(p._id, function(err, p) {
             assert.ifError(err);
             assert.equal(p.comments[0].comments[0].comments[0].comments[0].title, 'c4');
             db.close(done);
@@ -394,10 +394,10 @@ describe('types.documentarray', function () {
     });
   });
 
-  describe('invalidate()', function () {
-    it('works', function (done) {
+  describe('invalidate()', function() {
+    it('works', function(done) {
       var schema = new Schema({docs: [{name: 'string'}]});
-      schema.pre('validate', function (next) {
+      schema.pre('validate', function(next) {
         var subdoc = this.docs[this.docs.length - 1];
         subdoc.invalidate('name', 'boo boo', '%');
         next();
@@ -407,11 +407,11 @@ describe('types.documentarray', function () {
       t.docs.push({name: 100});
 
       var subdoc = t.docs.create({name: 'yep'});
-      assert.throws(function () {
+      assert.throws(function() {
         // has no parent array
         subdoc.invalidate('name', 'junk', 47);
       }, /^Error: Unable to invalidate a subdocument/);
-      t.validate(function () {
+      t.validate(function() {
         var e = t.errors['docs.0.name'];
         assert.ok(e);
         assert.equal(e.path, 'docs.0.name');
@@ -422,7 +422,7 @@ describe('types.documentarray', function () {
       });
     });
 
-    it('handles validation failures', function (done) {
+    it('handles validation failures', function(done) {
       var db = start();
       var nested = new Schema({v: {type: Number, max: 30}});
       var schema = new Schema({
@@ -430,26 +430,26 @@ describe('types.documentarray', function () {
       }, {collection: 'embedded-invalidate-' + random()});
       var M = db.model('embedded-invalidate', schema);
       var m = new M({docs: [{v: 900}]});
-      m.save(function (err) {
+      m.save(function(err) {
         assert.equal(900, err.errors['docs.0.v'].value);
         db.close(done);
       });
     });
 
-    it('removes attached event listeners when creating new doc array', function (done) {
+    it('removes attached event listeners when creating new doc array', function(done) {
       var db = start();
       var nested = new Schema({v: {type: Number}});
       var schema = new Schema({
         docs: [nested]
       }, {collection: 'gh-2159'});
       var M = db.model('gh-2159', schema);
-      M.create({docs: [{v: 900}]}, function (error, m) {
+      M.create({docs: [{v: 900}]}, function(error, m) {
         m.shouldPrint = true;
         assert.ifError(error);
         var numListeners = m.listeners('save').length;
         assert.ok(numListeners > 0);
         m.docs = [{v: 9000}];
-        m.save(function (error, m) {
+        m.save(function(error, m) {
           assert.ifError(error);
           assert.equal(numListeners, m.listeners('save').length);
           db.close(done);
diff --git a/test/types.number.test.js b/test/types.number.test.js
index e8ce2749c61..ad2dccfad59 100644
--- a/test/types.number.test.js
+++ b/test/types.number.test.js
@@ -11,20 +11,20 @@ var mongoose = require('./common').mongoose,
  * Test.
  */
 
-describe('types.number', function () {
-  it('an empty string casts to null', function (done) {
+describe('types.number', function() {
+  it('an empty string casts to null', function(done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.cast(''), null);
     done();
   });
 
-  it('a null number should castForQuery to null', function (done) {
+  it('a null number should castForQuery to null', function(done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.castForQuery(null), null);
     done();
   });
 
-  it('undefined throws number cast error', function (done) {
+  it('undefined throws number cast error', function(done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -36,7 +36,7 @@ describe('types.number', function () {
     done();
   });
 
-  it('array throws cast number error', function (done) {
+  it('array throws cast number error', function(done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -48,7 +48,7 @@ describe('types.number', function () {
     done();
   });
 
-  it('three throws cast number error', function (done) {
+  it('three throws cast number error', function(done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -60,7 +60,7 @@ describe('types.number', function () {
     done();
   });
 
-  it('{} throws cast number error', function (done) {
+  it('{} throws cast number error', function(done) {
     var n = new SchemaNumber();
     var err;
     try {
@@ -72,7 +72,7 @@ describe('types.number', function () {
     done();
   });
 
-  it('does not throw number cast error', function (done) {
+  it('does not throw number cast error', function(done) {
     var n = new SchemaNumber();
     var items = [1, '2', '0', null, '', new String('47'), new Number(5), Number(47), Number('09'), 0x12];
     var err;
@@ -87,7 +87,7 @@ describe('types.number', function () {
     done();
   });
 
-  it('boolean casts to 0/1 (gh-3475)', function (done) {
+  it('boolean casts to 0/1 (gh-3475)', function(done) {
     var n = new SchemaNumber();
     assert.strictEqual(n.cast(true), 1);
     assert.strictEqual(n.cast(false), 0);
diff --git a/test/updateValidators.unit.test.js b/test/updateValidators.unit.test.js
index 99bdc46872f..fc7ed755bd1 100644
--- a/test/updateValidators.unit.test.js
+++ b/test/updateValidators.unit.test.js
@@ -2,17 +2,17 @@ var assert = require('assert');
 var updateValidators = require('../lib/services/updateValidators');
 var emitter = require('events').EventEmitter;
 
-describe('updateValidators', function () {
+describe('updateValidators', function() {
   var schema;
 
-  beforeEach(function () {
+  beforeEach(function() {
     schema = {};
-    schema._getSchema = function (p) {
+    schema._getSchema = function(p) {
       schema._getSchema.calls.push(p);
       return schema;
     };
     schema._getSchema.calls = [];
-    schema.doValidate = function (v, cb) {
+    schema.doValidate = function(v, cb) {
       schema.doValidate.calls.push({v: v, cb: cb});
       schema.doValidate.emitter.emit('called', {v: v, cb: cb});
     };
@@ -20,13 +20,13 @@ describe('updateValidators', function () {
     schema.doValidate.emitter = new emitter();
   });
 
-  describe('validators', function () {
-    it('flattens paths', function (done) {
+  describe('validators', function() {
+    it('flattens paths', function(done) {
       var fn = updateValidators({}, schema, {test: {a: 1, b: null}}, {});
-      schema.doValidate.emitter.on('called', function (args) {
+      schema.doValidate.emitter.on('called', function(args) {
         args.cb();
       });
-      fn(function (err) {
+      fn(function(err) {
         assert.ifError(err);
         assert.equal(schema._getSchema.calls.length, 2);
         assert.equal(schema.doValidate.calls.length, 2);
@@ -38,13 +38,13 @@ describe('updateValidators', function () {
       });
     });
 
-    it('doesnt flatten dates (gh-3194)', function (done) {
+    it('doesnt flatten dates (gh-3194)', function(done) {
       var dt = new Date();
       var fn = updateValidators({}, schema, {test: dt}, {});
-      schema.doValidate.emitter.on('called', function (args) {
+      schema.doValidate.emitter.on('called', function(args) {
         args.cb();
       });
-      fn(function (err) {
+      fn(function(err) {
         assert.ifError(err);
         assert.equal(schema._getSchema.calls.length, 1);
         assert.equal(schema.doValidate.calls.length, 1);
@@ -54,12 +54,12 @@ describe('updateValidators', function () {
       });
     });
 
-    it('doesnt flatten empty arrays (gh-3554)', function (done) {
+    it('doesnt flatten empty arrays (gh-3554)', function(done) {
       var fn = updateValidators({}, schema, {test: []}, {});
-      schema.doValidate.emitter.on('called', function (args) {
+      schema.doValidate.emitter.on('called', function(args) {
         args.cb();
       });
-      fn(function (err) {
+      fn(function(err) {
         assert.ifError(err);
         assert.equal(schema._getSchema.calls.length, 1);
         assert.equal(schema.doValidate.calls.length, 1);
diff --git a/test/utils.test.js b/test/utils.test.js
index 9b66a1d3b17..934db7408b9 100644
--- a/test/utils.test.js
+++ b/test/utils.test.js
@@ -22,38 +22,38 @@ var ActiveRoster = StateMachine.ctor('require', 'init', 'modify');
  * Test.
  */
 
-describe('utils', function () {
-  describe('toCollectionName', function () {
-    it('works (gh-3490)', function (done) {
+describe('utils', function() {
+  describe('toCollectionName', function() {
+    it('works (gh-3490)', function(done) {
       assert.equal(utils.toCollectionName('stations'), 'stations');
       assert.equal(utils.toCollectionName('category'), 'categories');
       done();
     });
   });
 
-  describe('ActiveRoster', function () {
-    it('should detect a path as required if it has been required', function (done) {
+  describe('ActiveRoster', function() {
+    it('should detect a path as required if it has been required', function(done) {
       var ar = new ActiveRoster();
       ar.require('hello');
       assert.equal(ar.paths.hello, 'require');
       done();
     });
 
-    it('should detect a path as inited if it has been inited', function (done) {
+    it('should detect a path as inited if it has been inited', function(done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       assert.equal(ar.paths.hello, 'init');
       done();
     });
 
-    it('should detect a path as modified', function (done) {
+    it('should detect a path as modified', function(done) {
       var ar = new ActiveRoster();
       ar.modify('hello');
       assert.equal(ar.paths.hello, 'modify');
       done();
     });
 
-    it('should remove a path from an old state upon a state change', function (done) {
+    it('should remove a path from an old state upon a state change', function(done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.modify('hello');
@@ -62,43 +62,43 @@ describe('utils', function () {
       done();
     });
 
-    it('forEach should be able to iterate through the paths belonging to one state', function (done) {
+    it('forEach should be able to iterate through the paths belonging to one state', function(done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.init('goodbye');
       ar.modify('world');
       ar.require('foo');
-      ar.forEach('init', function (path) {
+      ar.forEach('init', function(path) {
         assert.ok(~['hello', 'goodbye'].indexOf(path));
       });
       done();
     });
 
-    it('forEach should be able to iterate through the paths in the union of two or more states', function (done) {
+    it('forEach should be able to iterate through the paths in the union of two or more states', function(done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.init('goodbye');
       ar.modify('world');
       ar.require('foo');
-      ar.forEach('modify', 'require', function (path) {
+      ar.forEach('modify', 'require', function(path) {
         assert.ok(~['world', 'foo'].indexOf(path));
       });
       done();
     });
 
-    it('forEach should iterate through all paths that have any state if given no state arguments', function (done) {
+    it('forEach should iterate through all paths that have any state if given no state arguments', function(done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.init('goodbye');
       ar.modify('world');
       ar.require('foo');
-      ar.forEach(function (path) {
+      ar.forEach(function(path) {
         assert.ok(~['hello', 'goodbye', 'world', 'foo'].indexOf(path));
       });
       done();
     });
 
-    it('should be able to detect if at least one path exists in a set of states', function (done) {
+    it('should be able to detect if at least one path exists in a set of states', function(done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.modify('world');
@@ -111,24 +111,24 @@ describe('utils', function () {
       done();
     });
 
-    it('should be able to `map` over the set of paths in a given state', function (done) {
+    it('should be able to `map` over the set of paths in a given state', function(done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.modify('world');
       ar.require('iAmTheWalrus');
-      var suffixedPaths = ar.map('init', 'modify', function (path) {
+      var suffixedPaths = ar.map('init', 'modify', function(path) {
         return path + '-suffix';
       });
       assert.deepEqual(suffixedPaths, ['hello-suffix', 'world-suffix']);
       done();
     });
 
-    it("should `map` over all states' paths if no states are specified in a `map` invocation", function (done) {
+    it('should `map` over all states\' paths if no states are specified in a `map` invocation', function(done) {
       var ar = new ActiveRoster();
       ar.init('hello');
       ar.modify('world');
       ar.require('iAmTheWalrus');
-      var suffixedPaths = ar.map(function (path) {
+      var suffixedPaths = ar.map(function(path) {
         return path + '-suffix';
       });
       assert.deepEqual(suffixedPaths, ['iAmTheWalrus-suffix', 'hello-suffix', 'world-suffix']);
@@ -136,7 +136,7 @@ describe('utils', function () {
     });
   });
 
-  it('utils.options', function (done) {
+  it('utils.options', function(done) {
     var o = {a: 1, b: 2, c: 3, 0: 'zero1'};
     var defaults = {b: 10, d: 20, 0: 'zero2'};
     var result = utils.options(defaults, o);
@@ -160,7 +160,7 @@ describe('utils', function () {
     done();
   });
 
-  it('deepEquals on ObjectIds', function (done) {
+  it('deepEquals on ObjectIds', function(done) {
     var s = (new ObjectId).toString();
 
     var a = new ObjectId(s),
@@ -172,7 +172,7 @@ describe('utils', function () {
     done();
   });
 
-  it('deepEquals on MongooseDocumentArray works', function (done) {
+  it('deepEquals on MongooseDocumentArray works', function(done) {
     var db = start(),
         A = new Schema({a: String}),
         M = db.model('deepEqualsOnMongooseDocArray', new Schema({
@@ -200,7 +200,7 @@ describe('utils', function () {
   });
 
   // gh-688
-  it('deepEquals with MongooseBuffer', function (done) {
+  it('deepEquals with MongooseBuffer', function(done) {
     var str = 'this is the day';
     var a = new MongooseBuffer(str);
     var b = new MongooseBuffer(str);
@@ -217,8 +217,8 @@ describe('utils', function () {
     done();
   });
 
-  describe('clone', function () {
-    it('retains RegExp options gh-1355', function (done) {
+  describe('clone', function() {
+    it('retains RegExp options gh-1355', function(done) {
       var a = new RegExp('hello', 'igm');
       assert.ok(a.global);
       assert.ok(a.ignoreCase);
@@ -232,7 +232,7 @@ describe('utils', function () {
       done();
     });
 
-    it('clones objects created with Object.create(null)', function (done) {
+    it('clones objects created with Object.create(null)', function(done) {
       var o = Object.create(null);
       o.a = 0;
       o.b = '0';
@@ -250,13 +250,13 @@ describe('utils', function () {
     });
   });
 
-  it('array.flatten', function (done) {
+  it('array.flatten', function(done) {
     var orig = [0, [1, 2, [3, 4, [5, [6]], 7], 8], 9];
     assert.deepEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], utils.array.flatten(orig));
     done();
   });
 
-  it('array.unique', function (done) {
+  it('array.unique', function(done) {
     var case1 = [1, 2, 3, 3, 5, 'a', 6, 'a'];
     assert.deepEqual(utils.array.unique(case1), [1, 2, 3, 5, 'a', 6]);
     var objId = new ObjectId('000000000000000000000001');
@@ -274,21 +274,21 @@ describe('utils', function () {
     done();
   });
 
-  describe('merge', function () {
-    it('merges two objects together without overriding properties & methods', function (done) {
+  describe('merge', function() {
+    it('merges two objects together without overriding properties & methods', function(done) {
       function To() {
         this.name = 'to';
         this.toProperty = true;
       }
-      To.prototype.getName = function () {};
-      To.prototype.toMethod = function () {};
+      To.prototype.getName = function() {};
+      To.prototype.toMethod = function() {};
 
       function From() {
         this.name = 'from';
         this.fromProperty = true;
       }
-      From.prototype.getName = function () {};
-      From.prototype.fromMethod = function () {};
+      From.prototype.getName = function() {};
+      From.prototype.fromMethod = function() {};
 
       var to = new To();
       var from = new From();
@@ -306,18 +306,18 @@ describe('utils', function () {
     });
   });
 
-  describe('pluralize', function () {
+  describe('pluralize', function() {
     var db;
 
-    before(function () {
+    before(function() {
       db = start();
     });
 
-    after(function (done) {
+    after(function(done) {
       db.close(done);
     });
 
-    it('should not pluralize _temp_ (gh-1703)', function (done) {
+    it('should not pluralize _temp_ (gh-1703)', function(done) {
       var ASchema = new Schema({
         value: {type: Schema.Types.Mixed}
       });
@@ -327,7 +327,7 @@ describe('utils', function () {
       assert.equal(A.collection.name, collectionName);
       done();
     });
-    it('should pluralize _temp (gh-1703)', function (done) {
+    it('should pluralize _temp (gh-1703)', function(done) {
       var ASchema = new Schema({
         value: {type: Schema.Types.Mixed}
       });
@@ -337,8 +337,8 @@ describe('utils', function () {
       assert.equal(A.collection.name, collectionName + 's');
       done();
     });
-    describe('option (gh-1707)', function () {
-      it('should pluralize by default', function (done) {
+    describe('option (gh-1707)', function() {
+      it('should pluralize by default', function(done) {
         var ASchema = new Schema({value: String});
 
         var collectionName = 'singular';
@@ -346,7 +346,7 @@ describe('utils', function () {
         assert.equal(A.collection.name, collectionName + 's');
         done();
       });
-      it('should pluralize when global option set to true', function (done) {
+      it('should pluralize when global option set to true', function(done) {
         db.base.set('pluralization', true);
 
         var ASchema = new Schema({value: String});
@@ -356,7 +356,7 @@ describe('utils', function () {
         assert.equal(A.collection.name, collectionName + 's');
         done();
       });
-      it('should not pluralize when global option set to false', function (done) {
+      it('should not pluralize when global option set to false', function(done) {
         db.base.set('pluralization', false);
 
         var ASchema = new Schema({value: String});
@@ -366,7 +366,7 @@ describe('utils', function () {
         assert.equal(A.collection.name, collectionName);
         done();
       });
-      it('should pluralize when local option set to true', function (done) {
+      it('should pluralize when local option set to true', function(done) {
         db.base.set('pluralization', false);
 
         // override
@@ -377,7 +377,7 @@ describe('utils', function () {
         assert.equal(A.collection.name, collectionName + 's');
         done();
       });
-      it('should not pluralize when local option set to false and global is true', function (done) {
+      it('should not pluralize when local option set to false and global is true', function(done) {
         db.base.set('pluralization', true);
 
         var ASchema = new Schema({value: String}, {pluralization: false});
@@ -387,7 +387,7 @@ describe('utils', function () {
         assert.equal(A.collection.name, collectionName);
         done();
       });
-      it('should not pluralize when local option set to false and global not set', function (done) {
+      it('should not pluralize when local option set to false and global not set', function(done) {
         var ASchema = new Schema({value: String}, {pluralization: false});
 
         var collectionName = 'five';
diff --git a/test/versioning.test.js b/test/versioning.test.js
index a954e2df1c3..fbbd8fda8b5 100644
--- a/test/versioning.test.js
+++ b/test/versioning.test.js
@@ -48,25 +48,25 @@ var BlogPost = new Schema(
 
 mongoose.model('Versioning', BlogPost);
 
-describe('versioning', function () {
+describe('versioning', function() {
   var db;
 
-  before(function () {
+  before(function() {
     db = start();
   });
 
-  after(function (done) {
+  after(function(done) {
     db.close(done);
   });
 
-  it('is only added to parent schema (gh-1265)', function (done) {
+  it('is only added to parent schema (gh-1265)', function(done) {
     assert.ok(BlogPost.path('__v'));
     assert.ok(!BlogPost.path('comments').__v);
     assert.ok(!BlogPost.path('meta.nested').__v);
     done();
   });
 
-  it('works', function (done) {
+  it('works', function(done) {
     var V = db.model('Versioning');
 
     var doc = new V;
@@ -95,7 +95,7 @@ describe('versioning', function () {
       var e;
       function lookup() {
         var a1, b1;
-        V.findById(a, function (err, a_) {
+        V.findById(a, function(err, a_) {
           if (err && !e) {
             e = err;
           }
@@ -104,7 +104,7 @@ describe('versioning', function () {
             cb(e, a1, b1);
           }
         });
-        V.findById(b, function (err, b_) {
+        V.findById(b, function(err, b_) {
           if (err && !e) {
             e = err;
           }
@@ -115,11 +115,11 @@ describe('versioning', function () {
         });
       }
       // make sure that a saves before b
-      a.save(function (err) {
+      a.save(function(err) {
         if (err) {
           e = err;
         }
-        b.save(function (err) {
+        b.save(function(err) {
           if (err) {
             e = err;
           }
@@ -208,7 +208,7 @@ describe('versioning', function () {
       a.meta.nested[2].title = 'two';
       b.meta.nested[0].title = 'zero';
       b.meta.nested[1].comments[0].title = 'sub one';
-      save(a, b, function (err, _a, _b) {
+      save(a, b, function(err, _a, _b) {
         assert.ifError(err);
         assert.equal(a._doc.__v, 10);
         assert.equal(b._doc.__v, 10);
@@ -303,18 +303,18 @@ describe('versioning', function () {
       save(a, b, test2);
     }
 
-    doc.save(function (err) {
+    doc.save(function(err) {
       var a, b;
       assert.ifError(err);
       // test 2 concurrent ops
-      V.findById(doc, function (err, _a) {
+      V.findById(doc, function(err, _a) {
         assert.ifError(err);
         a = _a;
         if (a && b) {
           test1(a, b);
         }
       });
-      V.findById(doc, function (err, _b) {
+      V.findById(doc, function(err, _b) {
         assert.ifError(err);
         b = _b;
         if (a && b) {
@@ -324,7 +324,7 @@ describe('versioning', function () {
     });
   });
 
-  it('versioning without version key', function (done) {
+  it('versioning without version key', function(done) {
     var V = db.model('Versioning');
 
     var doc = new V;
@@ -339,7 +339,7 @@ describe('versioning', function () {
     function test(err) {
       assert.ifError(err);
       // test getting docs back from db missing version key
-      V.findById(doc).select('numbers comments').exec(function (err, doc) {
+      V.findById(doc).select('numbers comments').exec(function(err, doc) {
         assert.ifError(err);
         doc.comments[0].title = 'no version was included';
         var d = doc.$__delta();
@@ -351,21 +351,21 @@ describe('versioning', function () {
     doc.save(test);
   });
 
-  it('version works with strict docs', function (done) {
+  it('version works with strict docs', function(done) {
     var schema = new Schema({str: ['string']}, {strict: true, collection: 'versionstrict_' + random()});
     var M = db.model('VersionStrict', schema);
     var m = new M({str: ['death', 'to', 'smootchy']});
-    m.save(function (err) {
+    m.save(function(err) {
       assert.ifError(err);
-      M.find(m, function (err, m) {
+      M.find(m, function(err, m) {
         assert.ifError(err);
         assert.equal(1, m.length);
         m = m[0];
         assert.equal(0, m._doc.__v);
         m.str.pull('death');
-        m.save(function (err) {
+        m.save(function(err) {
           assert.ifError(err);
-          M.findById(m, function (err, m) {
+          M.findById(m, function(err, m) {
             assert.ifError(err);
             assert.equal(1, m._doc.__v);
             assert.equal(2, m.str.length);
@@ -377,12 +377,12 @@ describe('versioning', function () {
     });
   });
 
-  it('version works with existing unversioned docs', function (done) {
+  it('version works with existing unversioned docs', function(done) {
     var V = db.model('Versioning');
 
-    V.collection.insert({title: 'unversioned', numbers: [1, 2, 3]}, {safe: true}, function (err) {
+    V.collection.insert({title: 'unversioned', numbers: [1, 2, 3]}, {safe: true}, function(err) {
       assert.ifError(err);
-      V.findOne({title: 'unversioned'}, function (err, d) {
+      V.findOne({title: 'unversioned'}, function(err, d) {
         assert.ifError(err);
         assert.ok(!d._doc.__v);
         d.numbers.splice(1, 1, 10);
@@ -390,10 +390,10 @@ describe('versioning', function () {
         assert.equal(undefined, o[0].__v);
         assert.ok(o[1].$inc);
         assert.equal(1, o[1].$inc.__v);
-        d.save(function (err, d) {
+        d.save(function(err, d) {
           assert.ifError(err);
           assert.equal(1, d._doc.__v);
-          V.findById(d, function (err, d) {
+          V.findById(d, function(err, d) {
             assert.ifError(err);
             assert.ok(d);
             done();
@@ -403,15 +403,15 @@ describe('versioning', function () {
     });
   });
 
-  it('versionKey is configurable', function (done) {
+  it('versionKey is configurable', function(done) {
     var schema = new Schema(
         {configured: 'bool'},
         {versionKey: 'lolwat', collection: 'configuredversion' + random()});
     var V = db.model('ConfiguredVersionKey', schema);
     var v = new V({configured: true});
-    v.save(function (err) {
+    v.save(function(err) {
       assert.ifError(err);
-      V.findById(v, function (err1, v) {
+      V.findById(v, function(err1, v) {
         assert.ifError(err1);
         assert.equal(0, v._doc.lolwat);
         done();
@@ -419,14 +419,14 @@ describe('versioning', function () {
     });
   });
 
-  it('can be disabled', function (done) {
+  it('can be disabled', function(done) {
     var schema = new Schema({x: ['string']}, {versionKey: false});
     var M = db.model('disabledVersioning', schema, 's' + random());
-    M.create({x: ['hi']}, function (err, doc) {
+    M.create({x: ['hi']}, function(err, doc) {
       assert.ifError(err);
       assert.equal(false, '__v' in doc._doc);
       doc.x.pull('hi');
-      doc.save(function (err) {
+      doc.save(function(err) {
         assert.ifError(err);
         assert.equal(false, '__v' in doc._doc);
 
@@ -434,7 +434,7 @@ describe('versioning', function () {
         var d = doc.$__delta()[0];
         assert.equal(undefined, d.__v, 'version should not be added to where clause');
 
-        M.collection.findOne({_id: doc._id}, function (err, doc) {
+        M.collection.findOne({_id: doc._id}, function(err, doc) {
           assert.equal(false, '__v' in doc);
           done();
         });
@@ -442,34 +442,34 @@ describe('versioning', function () {
     });
   });
 
-  it('works with numbericAlpha paths', function (done) {
+  it('works with numbericAlpha paths', function(done) {
     var M = db.model('Versioning');
     var m = new M({mixed: {}});
     var path = 'mixed.4a';
     m.set(path, 2);
-    m.save(function (err) {
+    m.save(function(err) {
       assert.ifError(err);
       done();
     });
   });
 
-  describe('doc.increment()', function () {
-    it('works without any other changes (gh-1475)', function (done) {
+  describe('doc.increment()', function() {
+    it('works without any other changes (gh-1475)', function(done) {
       var V = db.model('Versioning');
 
       var doc = new V;
-      doc.save(function (err) {
+      doc.save(function(err) {
         assert.ifError(err);
         assert.equal(0, doc.__v);
 
         doc.increment();
 
-        doc.save(function (err) {
+        doc.save(function(err) {
           assert.ifError(err);
 
           assert.equal(1, doc.__v);
 
-          V.findById(doc, function (err, doc) {
+          V.findById(doc, function(err, doc) {
             assert.ifError(err);
             assert.equal(1, doc.__v);
             done();
@@ -479,27 +479,27 @@ describe('versioning', function () {
     });
   });
 
-  describe('versioning is off', function () {
-    it('when { safe: false } is set (gh-1520)', function (done) {
+  describe('versioning is off', function() {
+    it('when { safe: false } is set (gh-1520)', function(done) {
       var schema1 = new Schema({title: String}, {safe: false});
       assert.equal(schema1.options.versionKey, false);
       done();
     });
-    it('when { safe: { w: 0 }} is set (gh-1520)', function (done) {
+    it('when { safe: { w: 0 }} is set (gh-1520)', function(done) {
       var schema1 = new Schema({title: String}, {safe: {w: 0}});
       assert.equal(schema1.options.versionKey, false);
       done();
     });
   });
 
-  it('gh-1898', function (done) {
+  it('gh-1898', function(done) {
     var schema = new Schema({tags: [String], name: String});
 
     var M = db.model('gh-1898', schema, 'gh-1898');
 
     var m = new M({tags: ['eggs']});
 
-    m.save(function (err) {
+    m.save(function(err) {
       assert.ifError(err);
 
       m.tags.push('bacon');
@@ -513,12 +513,12 @@ describe('versioning', function () {
     });
   });
 
-  it('can remove version key from toObject() (gh-2675)', function (done) {
+  it('can remove version key from toObject() (gh-2675)', function(done) {
     var schema = new Schema({name: String});
     var M = db.model('gh2675', schema, 'gh2675');
 
     var m = new M();
-    m.save(function (err, m) {
+    m.save(function(err, m) {
       assert.ifError(err);
       var obj = m.toObject();
       assert.equal(0, obj.__v);
diff --git a/website.js b/website.js
index ca057816f36..a1186a559b5 100644
--- a/website.js
+++ b/website.js
@@ -27,7 +27,7 @@ function getVersion() {
 function getUnstable(ver) {
   ver = ver.replace('-pre');
   var spl = ver.split('.');
-  spl = spl.map(function (i) {
+  spl = spl.map(function(i) {
     return parseInt(i, 10);
   });
   spl[1]++;
@@ -49,14 +49,14 @@ function jadeify(filename, options, newfile) {
   options.linktype = linktype;
   options.href = href;
   options.klass = klass;
-  jade.renderFile(filename, options, function (err, str) {
+  jade.renderFile(filename, options, function(err, str) {
     if (err) {
       console.error(err.stack);
       return;
     }
 
     newfile = newfile || filename.replace('.jade', '.html');
-    fs.writeFile(newfile, str, function (err) {
+    fs.writeFile(newfile, str, function(err) {
       if (err) {
         console.error('could not write', err.stack);
       } else {
@@ -66,12 +66,12 @@ function jadeify(filename, options, newfile) {
   });
 }
 
-files.forEach(function (file) {
+files.forEach(function(file) {
   var filename = __dirname + '/' + file;
   jadeify(filename, filemap[file]);
 
   if (process.argv[2] === '--watch') {
-    fs.watchFile(filename, {interval: 1000}, function (cur, prev) {
+    fs.watchFile(filename, {interval: 1000}, function(cur, prev) {
       if (cur.mtime > prev.mtime) {
         jadeify(filename, filemap[file]);
       }
@@ -81,7 +81,7 @@ files.forEach(function (file) {
 
 var acquit = require('./docs/source/acquit');
 var acquitFiles = Object.keys(acquit);
-acquitFiles.forEach(function (file) {
+acquitFiles.forEach(function(file) {
   var filename = __dirname + '/docs/acquit.jade';
   jadeify(filename, acquit[file], __dirname + '/docs/' + file);
 });

From 774da859f432305b4fa8cc7274a9d974627fa810 Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Mon, 1 Feb 2016 08:43:51 -0700
Subject: [PATCH 0241/2240] post test

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index bf94c6906b2..6180969e7c8 100644
--- a/package.json
+++ b/package.json
@@ -68,7 +68,7 @@
     "fix-lint": "eslint . --fix",
     "install-browser": "npm install `node format_deps.js`",
     "test": "mocha test/*.test.js test/**/*.test.js",
-    "postlint": "eslint . --quiet",
+    "posttest": "eslint . --quiet",
     "test-cov": "istanbul cover --report text --report html _mocha test/*.test.js"
   },
   "main": "./index.js",

From 7b26fdcd8f9dc21b5e776b1fd2a17930a13132fd Mon Sep 17 00:00:00 2001
From: Christian Murphy 
Date: Mon, 1 Feb 2016 10:04:21 -0700
Subject: [PATCH 0242/2240] resolve lint warnings

---
 lib/browser.js           | 2 ++
 lib/document_provider.js | 2 ++
 lib/model.js             | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/lib/browser.js b/lib/browser.js
index d135f66a6a4..74a7b6e817e 100644
--- a/lib/browser.js
+++ b/lib/browser.js
@@ -1,3 +1,5 @@
+/* eslint-env browser */
+
 /**
  * The [MongooseError](#error_MongooseError) constructor.
  *
diff --git a/lib/document_provider.js b/lib/document_provider.js
index 131a6096c1d..10087cc94d8 100644
--- a/lib/document_provider.js
+++ b/lib/document_provider.js
@@ -1,5 +1,7 @@
 'use strict';
 
+/* eslint-env browser */
+
 /*!
  * Module dependencies.
  */
diff --git a/lib/model.js b/lib/model.js
index 8d0e1c7fd18..cfcfa233ff0 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -2,6 +2,8 @@
  * Module dependencies.
  */
 
+/* eslint no-unused-vars: 1 */
+
 var Document = require('./document');
 var MongooseError = require('./error');
 var VersionError = MongooseError.VersionError;

From 4d2152a63b3fb5f9cf993c012f1d407a23cbb203 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 1 Feb 2016 16:17:41 -0500
Subject: [PATCH 0243/2240] feat: export CastError to help #995

---
 lib/index.js | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/lib/index.js b/lib/index.js
index 4ec1d50c704..999415fe6e5 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -679,6 +679,15 @@ Mongoose.prototype.DocumentProvider = require('./document_provider');
 
 Mongoose.prototype.Error = require('./error');
 
+/**
+ * The Mongoose CastError constructor
+ *
+ * @method Error
+ * @api public
+ */
+
+Mongoose.prototype.CastError = require('./error/cast');
+
 /**
  * The [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver Mongoose uses.
  *

From 6f6de9ebbcad6b3769438e16e24218642bc108b2 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 1 Feb 2016 16:18:27 -0500
Subject: [PATCH 0244/2240] feat(types): add default checkRequired re #995

---
 lib/schematype.js | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/lib/schematype.js b/lib/schematype.js
index 7bd25039fce..b1a349bec07 100644
--- a/lib/schematype.js
+++ b/lib/schematype.js
@@ -862,6 +862,17 @@ SchemaType.prototype.castForQuery = function($conditional, val) {
   return this.cast(val);
 };
 
+/**
+ * Default check for if this path satisfies the `required` validator.
+ *
+ * @param {any} val
+ * @api private
+ */
+
+SchemaType.prototype.checkRequired = function(val) {
+  return val != null;
+};
+
 /*!
  * Module exports.
  */

From a35626e2a95c0686b370128cd7c344e923737ec2 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Mon, 1 Feb 2016 20:57:03 -0500
Subject: [PATCH 0245/2240] feat: basic schema type API (Fix #995)

---
 docs/source/acquit.js         |  5 +++
 test/docs/schematypes.test.js | 65 +++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)
 create mode 100644 test/docs/schematypes.test.js

diff --git a/docs/source/acquit.js b/docs/source/acquit.js
index 066643dc102..ba9993d096f 100644
--- a/docs/source/acquit.js
+++ b/docs/source/acquit.js
@@ -19,6 +19,11 @@ var files = [
     input: 'test/docs/promises.test.js',
     output: 'promises.html',
     title: 'Promises'
+  },
+  {
+    input: 'test/docs/schematypes.test.js',
+    output: 'schematypes.html',
+    title: 'Custom Schema Types'
   }
 ];
 
diff --git a/test/docs/schematypes.test.js b/test/docs/schematypes.test.js
new file mode 100644
index 00000000000..c1091fbd184
--- /dev/null
+++ b/test/docs/schematypes.test.js
@@ -0,0 +1,65 @@
+var assert = require('assert');
+var mongoose = require('../../');
+
+describe('schemaTypes', function () {
+  var db;
+  var Schema = mongoose.Schema;
+
+  before(function() {
+    db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test');
+  });
+
+  after(function(done) {
+    db.close(done);
+  });
+
+  /**
+   * _New in Mongoose 4.4.0:_ Mongoose supports custom types. Before you
+   * reach for a custom type, however, know that a custom type is overkill
+   * for most use cases. You can do most basic tasks with
+   * [custom getters/setters](http://mongoosejs.com/docs/2.7.x/docs/getters-setters.html),
+   * [virtuals](http://mongoosejs.com/docs/guide.html#virtuals), and
+   * [single embedded docs](http://mongoosejs.com/docs/subdocs.html#single-embedded).
+   *
+   * Let's take a look at an example of a basic schema type: a 1-byte integer.
+   * To create a new schema type, you need to inherit from `mongoose.SchemaType`
+   * and add the corresponding property to `mongoose.Schema.Types`. The one
+   * method you need to implement is the `cast()` method.
+   */
+  it('Creating a Basic Custom Schema Type', function() {
+    function Int8(key, options) {
+      mongoose.SchemaType.call(this, key, options, 'Int8');
+    }
+    Int8.prototype = Object.create(mongoose.SchemaType.prototype);
+
+    // `cast()` takes a parameter that can be anything. You need to
+    // validate the provided `val` and throw a `CastError` if you
+    // can't convert it.
+    Int8.prototype.cast = function(val) {
+      var _val = Number(val);
+      if (isNaN(_val)) {
+        throw new mongoose.SchemaType.CastError('Int8',
+          val + ' is not a number');
+      }
+      _val = Math.round(_val);
+      if (_val < -0x80 || _val > 0x7F) {
+        throw new mongoose.SchemaType.CastError('Int8', val +
+          ' is outside of the range of valid 8-bit ints');
+      }
+      return _val;
+    };
+
+    // Don't forget to add `Int8` to the type registry
+    mongoose.Schema.Types.Int8 = Int8;
+
+    var testSchema = new Schema({ test: Int8 });
+    var Test = mongoose.model('Test', testSchema);
+
+    var t = new Test();
+    t.test = 'abc';
+    assert.ok(t.validateSync());
+    assert.equal(t.validateSync().errors['test'].name, 'CastError');
+    assert.equal(t.validateSync().errors['test'].message,
+      'Cast to Int8 failed for value "abc" at path "test"');
+  });
+});

From 2da3b356acff6347ff277bacf667d985258b6bf8 Mon Sep 17 00:00:00 2001
From: CTAPbIuMABP 
Date: Mon, 1 Feb 2016 22:28:15 +0800
Subject: [PATCH 0246/2240] power assert: drop-in replacement of native assert
 library

---
 package.json                              | 1 +
 test/aggregate.test.js                    | 2 +-
 test/cast.test.js                         | 2 +-
 test/collection.capped.test.js            | 2 +-
 test/collection.test.js                   | 2 +-
 test/colors.js                            | 2 +-
 test/common.js                            | 2 +-
 test/connection.auth.test.js              | 2 +-
 test/connection.test.js                   | 2 +-
 test/crash.test.js                        | 2 +-
 test/docs/defaults.test.js                | 2 +-
 test/docs/discriminators.test.js          | 2 +-
 test/docs/promises.test.js                | 2 +-
 test/document.hooks.test.js               | 2 +-
 test/document.isselected.test.js          | 2 +-
 test/document.modified.test.js            | 2 +-
 test/document.populate.test.js            | 2 +-
 test/document.strict.test.js              | 2 +-
 test/document.test.js                     | 2 +-
 test/document.unit.test.js                | 2 +-
 test/errors.validation.test.js            | 2 +-
 test/gh-1408.test.js                      | 2 +-
 test/harmony/document.test_.js            | 2 +-
 test/harmony/model.test_.js               | 2 +-
 test/harmony/query.test_.js               | 2 +-
 test/index.test.js                        | 2 +-
 test/mocha.opts                           | 3 ++-
 test/model.aggregate.test.js              | 2 +-
 test/model.create.test.js                 | 2 +-
 test/model.discriminator.querying.test.js | 2 +-
 test/model.discriminator.test.js          | 2 +-
 test/model.field.selection.test.js        | 2 +-
 test/model.findAndRemoveOne.test.js       | 2 +-
 test/model.findOneAndUpdate.test.js       | 2 +-
 test/model.geonear.test.js                | 2 +-
 test/model.geosearch.test.js              | 2 +-
 test/model.hydrate.test.js                | 2 +-
 test/model.indexes.test.js                | 2 +-
 test/model.mapreduce.test.js              | 2 +-
 test/model.middleware.test.js             | 2 +-
 test/model.populate.divergent.test.js     | 2 +-
 test/model.populate.setting.test.js       | 2 +-
 test/model.populate.test.js               | 2 +-
 test/model.query.casting.test.js          | 2 +-
 test/model.querying.test.js               | 2 +-
 test/model.stream.test.js                 | 2 +-
 test/model.test.js                        | 2 +-
 test/model.update.test.js                 | 2 +-
 test/object.create.null.test.js           | 2 +-
 test/promise.test.js                      | 2 +-
 test/promise_provider.test.js             | 2 +-
 test/query.middleware.test.js             | 2 +-
 test/query.test.js                        | 2 +-
 test/query.toconstructor.test.js          | 2 +-
 test/schema.boolean.test.js               | 2 +-
 test/schema.documentarray.test.js         | 2 +-
 test/schema.mixed.test.js                 | 2 +-
 test/schema.onthefly.test.js              | 2 +-
 test/schema.select.test.js                | 2 +-
 test/schema.test.js                       | 2 +-
 test/schema.timestamps.test.js            | 2 +-
 test/schema.type.test.js                  | 2 +-
 test/schema.validation.test.js            | 2 +-
 test/shard.test.js                        | 2 +-
 test/triage/_goosetest.js                 | 2 +-
 test/types.array.test.js                  | 2 +-
 test/types.buffer.test.js                 | 2 +-
 test/types.document.test.js               | 2 +-
 test/types.documentarray.test.js          | 2 +-
 test/types.number.test.js                 | 2 +-
 test/updateValidators.unit.test.js        | 2 +-
 test/utils.test.js                        | 2 +-
 test/versioning.test.js                   | 2 +-
 73 files changed, 74 insertions(+), 72 deletions(-)

diff --git a/package.json b/package.json
index d6bc906de76..e226cfa89c2 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,7 @@
     "mocha": "2.3.4",
     "node-static": "0.7.7",
     "open": "0.0.5",
+    "power-assert": "1.2.0",
     "q": "1.4.1",
     "tbd": "0.6.4",
     "uglify-js": "2.6.1",
diff --git a/test/aggregate.test.js b/test/aggregate.test.js
index 4ec5e100d7f..5dc91c93d7b 100644
--- a/test/aggregate.test.js
+++ b/test/aggregate.test.js
@@ -6,7 +6,7 @@ var start = require('./common'),
     Aggregate = require('../lib/aggregate'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema,
-    assert = require('assert');
+    assert = require('power-assert');
 
 /**
  * Test data
diff --git a/test/cast.test.js b/test/cast.test.js
index 5873dff11b6..e2698fc2970 100644
--- a/test/cast.test.js
+++ b/test/cast.test.js
@@ -3,7 +3,7 @@
  */
 
 var Schema = require('../lib/schema');
-var assert = require('assert');
+var assert = require('power-assert');
 var cast = require('../lib/cast');
 
 describe('cast: ', function () {
diff --git a/test/collection.capped.test.js b/test/collection.capped.test.js
index b61091af753..66b8ff5cfaa 100644
--- a/test/collection.capped.test.js
+++ b/test/collection.capped.test.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema,
     random = require('../lib/utils').random;
 
diff --git a/test/collection.test.js b/test/collection.test.js
index 95f47d09de7..ffb95a5f728 100644
--- a/test/collection.test.js
+++ b/test/collection.test.js
@@ -1,6 +1,6 @@
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Collection = require('../lib/collection');
 
 describe('collections:', function () {
diff --git a/test/colors.js b/test/colors.js
index b2a2c40cc29..edab283ab47 100644
--- a/test/colors.js
+++ b/test/colors.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema,
     MongooseDocumentArray = mongoose.Types.DocumentArray,
     EmbeddedDocument = require('../lib/types/embedded'),
diff --git a/test/common.js b/test/common.js
index 28eeea522fd..69ff199bbca 100644
--- a/test/common.js
+++ b/test/common.js
@@ -4,7 +4,7 @@
 
 var mongoose = require('../'),
     Collection = mongoose.Collection,
-    assert = require('assert'),
+    assert = require('power-assert'),
     queryCount = 0,
     opened = 0,
     closed = 0;
diff --git a/test/connection.auth.test.js b/test/connection.auth.test.js
index af3e8b8ec66..fedcb7a51a9 100644
--- a/test/connection.auth.test.js
+++ b/test/connection.auth.test.js
@@ -1,6 +1,6 @@
 var start = require('./common');
 var mongoose = start.mongoose;
-var assert = require('assert');
+var assert = require('power-assert');
 
 describe('connection:', function () {
   describe('supports authSource', function () {
diff --git a/test/connection.test.js b/test/connection.test.js
index cbdfcead4fd..8028055c6eb 100644
--- a/test/connection.test.js
+++ b/test/connection.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema,
     random = require('../lib/utils').random;
diff --git a/test/crash.test.js b/test/crash.test.js
index 6ab0a0de5a2..9ff30124798 100644
--- a/test/crash.test.js
+++ b/test/crash.test.js
@@ -1,7 +1,7 @@
 // GH-407
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose;
 
 describe('crash: (gh-407)', function () {
diff --git a/test/docs/defaults.test.js b/test/docs/defaults.test.js
index 419a1330ab4..c6cd8712492 100644
--- a/test/docs/defaults.test.js
+++ b/test/docs/defaults.test.js
@@ -1,4 +1,4 @@
-var assert = require('assert');
+var assert = require('power-assert');
 var mongoose = require('../../');
 
 describe('defaults docs', function () {
diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js
index 1b7306b6c66..59359d10f29 100644
--- a/test/docs/discriminators.test.js
+++ b/test/docs/discriminators.test.js
@@ -1,4 +1,4 @@
-var assert = require('assert');
+var assert = require('power-assert');
 var async = require('async');
 var mongoose = require('../../');
 
diff --git a/test/docs/promises.test.js b/test/docs/promises.test.js
index 3b5243b285e..e76f5b2b180 100644
--- a/test/docs/promises.test.js
+++ b/test/docs/promises.test.js
@@ -1,5 +1,5 @@
 var PromiseProvider = require('../../lib/promise_provider');
-var assert = require('assert');
+var assert = require('power-assert');
 var mongoose = require('../../');
 
 describe('promises docs', function () {
diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js
index 8b663a16b59..f93c2d58c54 100644
--- a/test/document.hooks.test.js
+++ b/test/document.hooks.test.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema,
     ObjectId = Schema.ObjectId,
     Document = require('../lib/document'),
diff --git a/test/document.isselected.test.js b/test/document.isselected.test.js
index 9ea4997b196..ce187daf19b 100644
--- a/test/document.isselected.test.js
+++ b/test/document.isselected.test.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema,
     ObjectId = Schema.ObjectId,
     Document = require('../lib/document'),
diff --git a/test/document.modified.test.js b/test/document.modified.test.js
index 531222e594e..1ca6f34f0a6 100644
--- a/test/document.modified.test.js
+++ b/test/document.modified.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
diff --git a/test/document.populate.test.js b/test/document.populate.test.js
index 82e7422c585..54a3afa4af6 100644
--- a/test/document.populate.test.js
+++ b/test/document.populate.test.js
@@ -4,7 +4,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     utils = require('../lib/utils'),
     random = utils.random,
diff --git a/test/document.strict.test.js b/test/document.strict.test.js
index 0940be531cf..05bac1b04d7 100644
--- a/test/document.strict.test.js
+++ b/test/document.strict.test.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     Schema = mongoose.Schema;
 
diff --git a/test/document.test.js b/test/document.test.js
index e97400856d7..905e007592f 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
     ObjectId = Schema.ObjectId,
diff --git a/test/document.unit.test.js b/test/document.unit.test.js
index fb1c4abfb13..5af81950a39 100644
--- a/test/document.unit.test.js
+++ b/test/document.unit.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common');
-var assert = require('assert');
+var assert = require('power-assert');
 var mongoose = start.mongoose;
 
 describe('sharding', function () {
diff --git a/test/errors.validation.test.js b/test/errors.validation.test.js
index eec2e6646ca..3519e54bfc3 100644
--- a/test/errors.validation.test.js
+++ b/test/errors.validation.test.js
@@ -3,7 +3,7 @@
  * Module dependencies.
  */
 
-var assert = require('assert'),
+var assert = require('power-assert'),
     start = require('./common'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema,
diff --git a/test/gh-1408.test.js b/test/gh-1408.test.js
index 993cb5eddf3..dcbee179375 100644
--- a/test/gh-1408.test.js
+++ b/test/gh-1408.test.js
@@ -4,7 +4,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema;
 
diff --git a/test/harmony/document.test_.js b/test/harmony/document.test_.js
index e54a4ffa168..ae4180c1398 100644
--- a/test/harmony/document.test_.js
+++ b/test/harmony/document.test_.js
@@ -3,7 +3,7 @@ var mongoose = start.mongoose;
 var Schema = mongoose.Schema;
 var ValidationError = require('../../lib/error/validation');
 var co = require('co');
-var assert = require('assert');
+var assert = require('power-assert');
 
 /**
  *  Asynchronous document functions return
diff --git a/test/harmony/model.test_.js b/test/harmony/model.test_.js
index aac5f689001..d33b3782e03 100644
--- a/test/harmony/model.test_.js
+++ b/test/harmony/model.test_.js
@@ -3,7 +3,7 @@ var start = require('../common');
 var mongoose = start.mongoose;
 var Schema = mongoose.Schema;
 var co = require('co');
-var assert = require('assert');
+var assert = require('power-assert');
 
 /**
  *  Asynchronous functions on Model return
diff --git a/test/harmony/query.test_.js b/test/harmony/query.test_.js
index b662a538c8c..b5f6225ddf6 100644
--- a/test/harmony/query.test_.js
+++ b/test/harmony/query.test_.js
@@ -2,7 +2,7 @@ var start = require('../common');
 var mongoose = start.mongoose;
 var Schema = mongoose.Schema;
 var co = require('co');
-var assert = require('assert');
+var assert = require('power-assert');
 
 /**
  *  Mongoose queries' .exec() function returns a
diff --git a/test/index.test.js b/test/index.test.js
index eac4d5e1950..05b489c4ab6 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -1,7 +1,7 @@
 
 var url = require('url'),
     start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     Mongoose = mongoose.Mongoose,
     Schema = mongoose.Schema,
diff --git a/test/mocha.opts b/test/mocha.opts
index b98a55c7fb9..a35a923698e 100644
--- a/test/mocha.opts
+++ b/test/mocha.opts
@@ -1 +1,2 @@
---reporter dot
\ No newline at end of file
+--reporter dot
+--ui bdd
\ No newline at end of file
diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js
index c895ace9af3..a2fdab8e274 100644
--- a/test/model.aggregate.test.js
+++ b/test/model.aggregate.test.js
@@ -5,7 +5,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     Aggregate = require('../lib/aggregate'),
     Schema = mongoose.Schema;
diff --git a/test/model.create.test.js b/test/model.create.test.js
index 6e5d8a98210..588e9dfe687 100644
--- a/test/model.create.test.js
+++ b/test/model.create.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js
index 30169f8daab..5865579dd27 100644
--- a/test/model.discriminator.querying.test.js
+++ b/test/model.discriminator.querying.test.js
@@ -5,7 +5,7 @@
 var start = require('./common'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema,
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     util = require('util'),
     async = require('async');
diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js
index 9cc7e0c62df..3daffa95d22 100644
--- a/test/model.discriminator.test.js
+++ b/test/model.discriminator.test.js
@@ -5,7 +5,7 @@
 var start = require('./common'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema,
-    assert = require('assert'),
+    assert = require('power-assert'),
     util = require('util'),
     clone = require('../lib/utils').clone,
     random = require('../lib/utils').random;
diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js
index 765e100e054..3f9915d53b7 100644
--- a/test/model.field.selection.test.js
+++ b/test/model.field.selection.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
diff --git a/test/model.findAndRemoveOne.test.js b/test/model.findAndRemoveOne.test.js
index 19780ed6b9e..568654cf5fc 100644
--- a/test/model.findAndRemoveOne.test.js
+++ b/test/model.findAndRemoveOne.test.js
@@ -5,7 +5,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
     ObjectId = Schema.Types.ObjectId,
diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index afd4112ad90..219a0f55f30 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -4,7 +4,7 @@
 
 var CastError = require('../lib/error/cast');
 var start = require('./common');
-var assert = require('assert');
+var assert = require('power-assert');
 var mongoose = start.mongoose;
 var random = require('../lib/utils').random;
 var Utils = require('../lib/utils');
diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js
index 0c286b58f16..ce800953c36 100644
--- a/test/model.geonear.test.js
+++ b/test/model.geonear.test.js
@@ -1,6 +1,6 @@
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema;
diff --git a/test/model.geosearch.test.js b/test/model.geosearch.test.js
index 002e998e50b..431e73d66f5 100644
--- a/test/model.geosearch.test.js
+++ b/test/model.geosearch.test.js
@@ -1,6 +1,6 @@
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema;
diff --git a/test/model.hydrate.test.js b/test/model.hydrate.test.js
index acedf4f6795..f69c3025bd0 100644
--- a/test/model.hydrate.test.js
+++ b/test/model.hydrate.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema,
     DocumentObjectId = mongoose.Types.ObjectId;
diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js
index 5956f20f369..1143691ef78 100644
--- a/test/model.indexes.test.js
+++ b/test/model.indexes.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 6ff7acf0a10..5cac35abffc 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -5,7 +5,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
     ObjectId = Schema.Types.ObjectId;
diff --git a/test/model.middleware.test.js b/test/model.middleware.test.js
index c949554f619..a7dd8e4a1ca 100644
--- a/test/model.middleware.test.js
+++ b/test/model.middleware.test.js
@@ -4,7 +4,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema;
 
diff --git a/test/model.populate.divergent.test.js b/test/model.populate.divergent.test.js
index ebacb4ddf8a..90d0463b8c2 100644
--- a/test/model.populate.divergent.test.js
+++ b/test/model.populate.divergent.test.js
@@ -4,7 +4,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     DivergentArrayError = mongoose.Error.DivergentArrayError,
     utils = require('../lib/utils'),
diff --git a/test/model.populate.setting.test.js b/test/model.populate.setting.test.js
index 02a7d1a444f..af72a40e288 100644
--- a/test/model.populate.setting.test.js
+++ b/test/model.populate.setting.test.js
@@ -5,7 +5,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     utils = require('../lib/utils'),
     random = utils.random,
diff --git a/test/model.populate.test.js b/test/model.populate.test.js
index e02b85c513f..70cbb150cdf 100644
--- a/test/model.populate.test.js
+++ b/test/model.populate.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     utils = require('../lib/utils'),
     random = utils.random,
diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js
index 78523c9a12a..9d06f60f32f 100644
--- a/test/model.query.casting.test.js
+++ b/test/model.query.casting.test.js
@@ -5,7 +5,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
diff --git a/test/model.querying.test.js b/test/model.querying.test.js
index 8e85d25949a..b61475d36fd 100644
--- a/test/model.querying.test.js
+++ b/test/model.querying.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
diff --git a/test/model.stream.test.js b/test/model.stream.test.js
index 6990fe103cc..6e9e728b7c5 100644
--- a/test/model.stream.test.js
+++ b/test/model.stream.test.js
@@ -4,7 +4,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     utils = require('../lib/utils'),
     random = utils.random,
diff --git a/test/model.test.js b/test/model.test.js
index 7d6069ec28e..e186c81b2e0 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -4,7 +4,7 @@ Error.stackTraceLimit = Infinity;
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
diff --git a/test/model.update.test.js b/test/model.update.test.js
index 949f9a4b06b..e6e123a7594 100644
--- a/test/model.update.test.js
+++ b/test/model.update.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
diff --git a/test/object.create.null.test.js b/test/object.create.null.test.js
index 72c0b17b0a4..2c75f74ddb7 100644
--- a/test/object.create.null.test.js
+++ b/test/object.create.null.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema;
 
diff --git a/test/promise.test.js b/test/promise.test.js
index 665470a4e6c..906828a4fe7 100644
--- a/test/promise.test.js
+++ b/test/promise.test.js
@@ -2,7 +2,7 @@
  * Module dependencies.
  */
 
-var assert = require('assert');
+var assert = require('power-assert');
 
 var Promise = require('../lib/promise');
 
diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js
index 14d485388cb..d3b8fbcc22c 100644
--- a/test/promise_provider.test.js
+++ b/test/promise_provider.test.js
@@ -2,7 +2,7 @@
  * Module dependencies.
  */
 
-var assert = require('assert');
+var assert = require('power-assert');
 var bluebird = require('bluebird');
 var q = require('q');
 var start = require('./common');
diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js
index 10e18add18f..974678a90f3 100644
--- a/test/query.middleware.test.js
+++ b/test/query.middleware.test.js
@@ -1,5 +1,5 @@
 var start = require('./common');
-var assert = require('assert');
+var assert = require('power-assert');
 var mongoose = start.mongoose;
 var Schema = mongoose.Schema;
 
diff --git a/test/query.test.js b/test/query.test.js
index b516a36bfe7..ae6f263e0de 100644
--- a/test/query.test.js
+++ b/test/query.test.js
@@ -6,7 +6,7 @@ var start = require('./common'),
     mongoose = start.mongoose,
     DocumentObjectId = mongoose.Types.ObjectId,
     Schema = mongoose.Schema,
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     Query = require('../lib/query');
 
diff --git a/test/query.toconstructor.test.js b/test/query.toconstructor.test.js
index 23d6d52c190..46e4b404643 100644
--- a/test/query.toconstructor.test.js
+++ b/test/query.toconstructor.test.js
@@ -1,7 +1,7 @@
 var start = require('./common'),
     mongoose = start.mongoose,
     Schema = mongoose.Schema,
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     Query = require('../lib/query');
 
diff --git a/test/schema.boolean.test.js b/test/schema.boolean.test.js
index d60e2f6507e..f4d12c7ef4a 100644
--- a/test/schema.boolean.test.js
+++ b/test/schema.boolean.test.js
@@ -5,7 +5,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema;
 
 describe('schematype', function () {
diff --git a/test/schema.documentarray.test.js b/test/schema.documentarray.test.js
index 9b49db4e4d1..1763fd408fa 100644
--- a/test/schema.documentarray.test.js
+++ b/test/schema.documentarray.test.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema;
 
 /**
diff --git a/test/schema.mixed.test.js b/test/schema.mixed.test.js
index cfd25ba4c93..c587589cb4e 100644
--- a/test/schema.mixed.test.js
+++ b/test/schema.mixed.test.js
@@ -5,7 +5,7 @@
 
 var start = require('./common'),
     mongoose = new start.mongoose.Mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema;
 
 describe('schematype mixed', function () {
diff --git a/test/schema.onthefly.test.js b/test/schema.onthefly.test.js
index c59a08b41f9..a3674a4fb17 100644
--- a/test/schema.onthefly.test.js
+++ b/test/schema.onthefly.test.js
@@ -1,5 +1,5 @@
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
diff --git a/test/schema.select.test.js b/test/schema.select.test.js
index e6e44aff89c..8ac8ef5f40b 100644
--- a/test/schema.select.test.js
+++ b/test/schema.select.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = start.mongoose,
     random = require('../lib/utils').random,
     Schema = mongoose.Schema;
diff --git a/test/schema.test.js b/test/schema.test.js
index 66ca25ca9f4..eb725c9f872 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema,
     Document = mongoose.Document,
     VirtualType = mongoose.VirtualType,
diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js
index 67f4176a8f1..05c659f8c23 100644
--- a/test/schema.timestamps.test.js
+++ b/test/schema.timestamps.test.js
@@ -5,7 +5,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema;
 
 describe('schema options.timestamps', function () {
diff --git a/test/schema.type.test.js b/test/schema.type.test.js
index a282c69c4df..7f88b0eec71 100644
--- a/test/schema.type.test.js
+++ b/test/schema.type.test.js
@@ -4,7 +4,7 @@
  */
 
 var mongoose = require('./common').mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema;
 
 describe('schematype', function () {
diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js
index 2ff101fdd77..7afd116f0bc 100644
--- a/test/schema.validation.test.js
+++ b/test/schema.validation.test.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     Schema = mongoose.Schema,
     ValidatorError = mongoose.Error.ValidatorError,
     SchemaTypes = Schema.Types,
diff --git a/test/shard.test.js b/test/shard.test.js
index c9a3e404dcf..e9998dbef35 100644
--- a/test/shard.test.js
+++ b/test/shard.test.js
@@ -1,5 +1,5 @@
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     mongoose = start.mongoose,
     Schema = mongoose.Schema;
diff --git a/test/triage/_goosetest.js b/test/triage/_goosetest.js
index 6369f364287..9ee39ce66c0 100644
--- a/test/triage/_goosetest.js
+++ b/test/triage/_goosetest.js
@@ -1,7 +1,7 @@
 
 var mongoose = require('../../');
 var Schema = mongoose.Schema;
-var assert = require('assert')
+var assert = require('power-assert')
 
 console.log('\n===========');
 console.log('    mongoose version: %s', mongoose.version);
diff --git a/test/types.array.test.js b/test/types.array.test.js
index 3d8252c9591..beb75c6e97f 100644
--- a/test/types.array.test.js
+++ b/test/types.array.test.js
@@ -3,7 +3,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = require('./common').mongoose,
     Schema = mongoose.Schema,
     random = require('../lib/utils').random,
diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js
index faca4d4b60f..7434916f646 100644
--- a/test/types.buffer.test.js
+++ b/test/types.buffer.test.js
@@ -4,7 +4,7 @@
  */
 
 var start = require('./common'),
-    assert = require('assert'),
+    assert = require('power-assert'),
     mongoose = require('./common').mongoose,
     Schema = mongoose.Schema,
     random = require('../lib/utils').random,
diff --git a/test/types.document.test.js b/test/types.document.test.js
index b78da80f8e2..83306c89e63 100644
--- a/test/types.document.test.js
+++ b/test/types.document.test.js
@@ -3,7 +3,7 @@
  * Module dependencies.
  */
 
-var assert = require('assert'),
+var assert = require('power-assert'),
     start = require('./common'),
     mongoose = start.mongoose,
     EmbeddedDocument = require('../lib/types/embedded'),
diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js
index 4be76934d15..c23abb32214 100644
--- a/test/types.documentarray.test.js
+++ b/test/types.documentarray.test.js
@@ -10,7 +10,7 @@ var start = require('./common'),
     EmbeddedDocument = require('../lib/types/embedded'),
     DocumentArray = require('../lib/types/documentarray'),
     Schema = mongoose.Schema,
-    assert = require('assert'),
+    assert = require('power-assert'),
     collection = 'types.documentarray_' + random();
 
 /**
diff --git a/test/types.number.test.js b/test/types.number.test.js
index e8ce2749c61..c4760d2ca63 100644
--- a/test/types.number.test.js
+++ b/test/types.number.test.js
@@ -5,7 +5,7 @@
 
 var mongoose = require('./common').mongoose,
     SchemaNumber = mongoose.Schema.Types.Number,
-    assert = require('assert');
+    assert = require('power-assert');
 
 /**
  * Test.
diff --git a/test/updateValidators.unit.test.js b/test/updateValidators.unit.test.js
index 99bdc46872f..ef0fb98ed04 100644
--- a/test/updateValidators.unit.test.js
+++ b/test/updateValidators.unit.test.js
@@ -1,4 +1,4 @@
-var assert = require('assert');
+var assert = require('power-assert');
 var updateValidators = require('../lib/services/updateValidators');
 var emitter = require('events').EventEmitter;
 
diff --git a/test/utils.test.js b/test/utils.test.js
index 9b66a1d3b17..d78023038bc 100644
--- a/test/utils.test.js
+++ b/test/utils.test.js
@@ -10,7 +10,7 @@ var start = require('./common'),
     StateMachine = require('../lib/statemachine'),
     ObjectId = require('../lib/types/objectid'),
     MongooseBuffer = require('../lib/types/buffer'),
-    assert = require('assert');
+    assert = require('power-assert');
 
 /**
  * Setup.
diff --git a/test/versioning.test.js b/test/versioning.test.js
index a954e2df1c3..ee3ce5d7172 100644
--- a/test/versioning.test.js
+++ b/test/versioning.test.js
@@ -4,7 +4,7 @@
 
 var start = require('./common'),
     mongoose = start.mongoose,
-    assert = require('assert'),
+    assert = require('power-assert'),
     random = require('../lib/utils').random,
     Schema = mongoose.Schema,
     VersionError = mongoose.Error.VersionError;

From 996e78d7c535f07cafdb0b37faac951dbb81d8ab Mon Sep 17 00:00:00 2001
From: Dmitriy Drenkalyuk 
Date: Tue, 2 Feb 2016 12:15:42 +0200
Subject: [PATCH 0247/2240] Fixed the 'expireAfterSeconds' index option name.

---
 lib/schema/date.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/schema/date.js b/lib/schema/date.js
index eebdd93ae8d..5ef36dde6ab 100644
--- a/lib/schema/date.js
+++ b/lib/schema/date.js
@@ -39,7 +39,7 @@ SchemaDate.prototype.constructor = SchemaDate;
 /**
  * Declares a TTL index (rounded to the nearest second) for _Date_ types only.
  *
- * This sets the `expiresAfterSeconds` index option available in MongoDB >= 2.1.2.
+ * This sets the `expireAfterSeconds` index option available in MongoDB >= 2.1.2.
  * This index type is only compatible with Date types.
  *
  * ####Example:

From f7e8e8d32ed6b6884fa18752a83a4bf5f2b067eb Mon Sep 17 00:00:00 2001
From: Dmitriy Drenkalyuk 
Date: Tue, 2 Feb 2016 13:55:42 +0200
Subject: [PATCH 0248/2240] Fixed typo.

---
 lib/schematype.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/schematype.js b/lib/schematype.js
index b1a349bec07..6b90fe0e59a 100644
--- a/lib/schematype.js
+++ b/lib/schematype.js
@@ -388,7 +388,7 @@ SchemaType.prototype.get = function(fn) {
  *
  * ####Error message templates:
  *
- * From the examples above, you may have noticed that error messages support baseic templating. There are a few other template keywords besides `{PATH}` and `{VALUE}` too. To find out more, details are available [here](#error_messages_MongooseError-messages)
+ * From the examples above, you may have noticed that error messages support basic templating. There are a few other template keywords besides `{PATH}` and `{VALUE}` too. To find out more, details are available [here](#error_messages_MongooseError-messages)
  *
  * ####Asynchronous validation:
  *

From 3766ace181f321933d3e508cdccc6cc30daf410f Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 2 Feb 2016 17:08:13 -0500
Subject: [PATCH 0249/2240] chore: release 4.4.0

---
 History.md      |   18 +
 bin/mongoose.js | 4006 ++++++++++++++++++++++++++---------------------
 package.json    |    2 +-
 3 files changed, 2244 insertions(+), 1782 deletions(-)

diff --git a/History.md b/History.md
index 969cc4e0095..99d501fb6a8 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,21 @@
+4.4.0 / 2016-02-02
+==================
+ * docs: fix expireAfterSeconds index option name #3831 [Flash-](https://github.com/Flash-)
+ * chore: run lint after test #3829 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * chore: use power-assert instead of assert #3828 [TrejGun](https://github.com/TrejGun)
+ * chore: stricter lint #3827 [TrejGun](https://github.com/TrejGun)
+ * feat(types): casting moment to date #3813 [TrejGun](https://github.com/TrejGun)
+ * chore: comma-last lint for test folder #3810 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix: upgrade async mpath, mpromise, muri, and sliced #3801 [TrejGun](https://github.com/TrejGun)
+ * fix(query): geo queries now return proper ES2015 promises #3800 [TrejGun](https://github.com/TrejGun)
+ * perf(types): use `Object.defineProperties()` for array #3799 [TrejGun](https://github.com/TrejGun)
+ * fix(model): mapReduce, ensureIndexes, remove, and save properly return ES2015 promises #3795 #3628 #3595 [TrejGun](https://github.com/TrejGun)
+ * docs: fixed dates in History.md #3791 [Jokero](https://github.com/Jokero)
+ * feat: connect, open, openSet, and disconnect return ES2015 promises #3790 #3622 [TrejGun](https://github.com/TrejGun)
+ * feat: custom type for int32 via mongoose-int32 npm package #3652 #3102
+ * feat: basic custom schema type API #995
+ * feat(model): `insertAll()` for more performant bulk inserts #723
+
 4.3.7 / 2016-01-23
 ==================
  * docs: grammar fix in timestamps docs #3786 [zclancy](https://github.com/zclancy)
diff --git a/bin/mongoose.js b/bin/mongoose.js
index 2cc15a780f0..7c9c67aaf45 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -1,6 +1,4 @@
 (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 2.1.2.
+ * This sets the `expireAfterSeconds` index option available in MongoDB >= 2.1.2.
  * This index type is only compatible with Date types.
  *
  * ####Example:
@@ -5801,7 +5889,7 @@ SchemaDate.prototype.constructor = SchemaDate;
  */
 
 SchemaDate.prototype.expires = function(when) {
-  if (!this._index || 'Object' !== this._index.constructor.name) {
+  if (!this._index || this._index.constructor.name !== 'Object') {
     this._index = {};
   }
 
@@ -5854,17 +5942,17 @@ SchemaDate.prototype.checkRequired = function(value) {
 SchemaDate.prototype.min = function(value, message) {
   if (this.minValidator) {
     this.validators = this.validators.filter(function(v) {
-      return v.validator != this.minValidator;
+      return v.validator !== this.minValidator;
     }, this);
   }
 
   if (value) {
     var msg = message || errorMessages.Date.min;
     msg = msg.replace(/{MIN}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
-    var self = this;
+    var _this = this;
     this.validators.push({
       validator: this.minValidator = function(val) {
-        var min = (value === Date.now ? value() : self.cast(value));
+        var min = (value === Date.now ? value() : _this.cast(value));
         return val === null || val.valueOf() >= min.valueOf();
       },
       message: msg,
@@ -5910,17 +5998,17 @@ SchemaDate.prototype.min = function(value, message) {
 SchemaDate.prototype.max = function(value, message) {
   if (this.maxValidator) {
     this.validators = this.validators.filter(function(v) {
-      return v.validator != this.maxValidator;
+      return v.validator !== this.maxValidator;
     }, this);
   }
 
   if (value) {
     var msg = message || errorMessages.Date.max;
     msg = msg.replace(/{MAX}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
-    var self = this;
+    var _this = this;
     this.validators.push({
       validator: this.maxValidator = function(val) {
-        var max = (value === Date.now ? value() : self.cast(value));
+        var max = (value === Date.now ? value() : _this.cast(value));
         return val === null || val.valueOf() <= max.valueOf();
       },
       message: msg,
@@ -5941,27 +6029,27 @@ SchemaDate.prototype.max = function(value, message) {
 
 SchemaDate.prototype.cast = function(value) {
   // If null or undefined
-  if (value == null || value === '')
+  if (value === null || value === void 0 || value === '') {
     return null;
+  }
 
-  if (value instanceof Date)
+  if (value instanceof Date) {
     return value;
+  }
 
   var date;
 
-  // support for timestamps
-  if (typeof value !== 'undefined') {
-    if (value instanceof Number || 'number' == typeof value
-        || String(value) == Number(value)) {
-      date = new Date(Number(value));
-    } else if (value.toString) {
-      // support for date strings
-      date = new Date(value.toString());
-    }
+  if (value instanceof Number || typeof value === 'number'
+      || String(value) == Number(value)) {
+    // support for timestamps
+    date = new Date(Number(value));
+  } else if (value.valueOf) {
+    // support for moment.js
+    date = new Date(value.valueOf());
+  }
 
-    if (date.toString() != 'Invalid Date') {
-      return date;
-    }
+  if (!Number.isNaN(date.valueOf())) {
+    return date;
   }
 
   throw new CastError('date', value, this.path);
@@ -5978,12 +6066,12 @@ function handleSingle(val) {
 }
 
 SchemaDate.prototype.$conditionalHandlers =
-  utils.options(SchemaType.prototype.$conditionalHandlers, {
-    '$gt': handleSingle,
-    '$gte': handleSingle,
-    '$lt': handleSingle,
-    '$lte': handleSingle
-  });
+    utils.options(SchemaType.prototype.$conditionalHandlers, {
+      '$gt': handleSingle,
+      '$gte': handleSingle,
+      '$lt': handleSingle,
+      '$lte': handleSingle
+    });
 
 
 /**
@@ -5997,14 +6085,14 @@ SchemaDate.prototype.$conditionalHandlers =
 SchemaDate.prototype.castForQuery = function($conditional, val) {
   var handler;
 
-  if (2 !== arguments.length) {
+  if (arguments.length !== 2) {
     return this.cast($conditional);
   }
 
   handler = this.$conditionalHandlers[$conditional];
 
   if (!handler) {
-    throw new Error("Can't use " + $conditional + " with Date.");
+    throw new Error('Can\'t use ' + $conditional + ' with Date.');
   }
 
   return handler.call(this, val);
@@ -6050,12 +6138,14 @@ function DocumentArray(key, schema, options) {
   EmbeddedDocument.schema = schema;
 
   // apply methods
-  for (var i in schema.methods)
+  for (var i in schema.methods) {
     EmbeddedDocument.prototype[i] = schema.methods[i];
+  }
 
   // apply statics
-  for (i in schema.statics)
+  for (i in schema.statics) {
     EmbeddedDocument[i] = schema.statics[i];
+  }
 
   EmbeddedDocument.options = options;
 
@@ -6067,7 +6157,9 @@ function DocumentArray(key, schema, options) {
 
   this.default(function() {
     var arr = fn.call(this);
-    if (!Array.isArray(arr)) arr = [arr];
+    if (!Array.isArray(arr)) {
+      arr = [arr];
+    }
     return new MongooseDocumentArray(arr, path, this);
   });
 }
@@ -6083,7 +6175,7 @@ DocumentArray.schemaName = 'DocumentArray';
 /*!
  * Inherits from ArrayType.
  */
-DocumentArray.prototype = Object.create( ArrayType.prototype );
+DocumentArray.prototype = Object.create(ArrayType.prototype);
 DocumentArray.prototype.constructor = DocumentArray;
 
 /**
@@ -6120,12 +6212,23 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
         continue;
       }
 
-      doc.validate({ __noPromise: true }, function(err) {
-        if (err) {
-          error = err;
-        }
-        --count || fn(error);
-      });
+      // HACK: use $__original_validate to avoid promises so bluebird doesn't
+      // complain
+      if (doc.$__original_validate) {
+        doc.$__original_validate({__noPromise: true}, function(err) {
+          if (err) {
+            error = err;
+          }
+          --count || fn(error);
+        });
+      } else {
+        doc.validate({__noPromise: true}, function(err) {
+          if (err) {
+            error = err;
+          }
+          --count || fn(error);
+        });
+      }
     }
   }, scope);
 };
@@ -6143,7 +6246,9 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
 
 DocumentArray.prototype.doValidateSync = function(array, scope) {
   var schemaTypeError = SchemaType.prototype.doValidateSync.call(this, array, scope);
-  if (schemaTypeError) return schemaTypeError;
+  if (schemaTypeError) {
+    return schemaTypeError;
+  }
 
   var count = array && array.length,
       resultError = null;
@@ -6158,10 +6263,14 @@ DocumentArray.prototype.doValidateSync = function(array, scope) {
 
   for (var i = 0, len = count; i < len; ++i) {
     // only first error
-    if ( resultError ) break;
+    if (resultError) {
+      break;
+    }
     // sidestep sparse entries
     var doc = array[i];
-    if (!doc) continue;
+    if (!doc) {
+      continue;
+    }
 
     var subdocValidateError = doc.validateSync();
 
@@ -6214,7 +6323,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) {
     // Check if the document has a different schema (re gh-3701)
     if ((value[i] instanceof Subdocument) &&
         value[i].schema !== this.casterConstructor.schema) {
-      value[i] = value[i].toObject({ virtuals: false });
+      value[i] = value[i].toObject({virtuals: false});
     }
     if (!(value[i] instanceof Subdocument) && value[i]) {
       if (init) {
@@ -6224,7 +6333,8 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) {
       } else {
         try {
           subdoc = prev.id(value[i]._id);
-        } catch (e) {}
+        } catch (e) {
+        }
 
         if (prev && subdoc) {
           // handle resetting doc with existing id but differing data
@@ -6236,7 +6346,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) {
         } else {
           try {
             subdoc = new this.casterConstructor(value[i], value, undefined,
-              undefined, i);
+                undefined, i);
             // if set() is hooked it will have no return value
             // see gh-746
             value[i] = subdoc;
@@ -6261,7 +6371,9 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) {
  */
 
 function scopePaths(array, fields, init) {
-  if (!(init && fields)) return undefined;
+  if (!(init && fields)) {
+    return undefined;
+  }
 
   var path = array.path + '.',
       keys = Object.keys(fields),
@@ -6272,7 +6384,7 @@ function scopePaths(array, fields, init) {
 
   while (i--) {
     key = keys[i];
-    if (0 === key.indexOf(path)) {
+    if (key.indexOf(path) === 0) {
       hasKeys || (hasKeys = true);
       selected[key.substring(path.length)] = fields[key];
     }
@@ -6374,11 +6486,9 @@ Embedded.prototype.castForQuery = function($conditional, val) {
       throw new Error('Can\'t use ' + $conditional);
     }
     return handler.call(this, val);
-  } else {
-    val = $conditional;
-    return new this.caster(val).
-      toObject({ virtuals: false });
   }
+  val = $conditional;
+  return new this.caster(val).toObject({virtuals: false});
 };
 
 /**
@@ -6395,7 +6505,7 @@ Embedded.prototype.doValidate = function(value, fn) {
     if (!value) {
       return fn(null);
     }
-    value.validate(fn, { __noPromise: true });
+    value.validate(fn, {__noPromise: true});
   });
 };
 
@@ -6459,7 +6569,6 @@ exports.Object = exports.Mixed;
 exports.Bool = exports.Boolean;
 
 },{"./array":27,"./boolean":28,"./buffer":29,"./date":30,"./documentarray":31,"./embedded":32,"./mixed":34,"./number":35,"./objectid":36,"./string":38}],34:[function(require,module,exports){
-
 /*!
  * Module dependencies.
  */
@@ -6479,12 +6588,10 @@ var utils = require('../utils');
 function Mixed(path, options) {
   if (options && options.default) {
     var def = options.default;
-    if (Array.isArray(def) && 0 === def.length) {
+    if (Array.isArray(def) && def.length === 0) {
       // make sure empty array defaults are handled
       options.default = Array;
-    } else if (!options.shared &&
-               utils.isObject(def) &&
-               0 === Object.keys(def).length) {
+    } else if (!options.shared && utils.isObject(def) && Object.keys(def).length === 0) {
       // prevent odd "shared" objects between documents
       options.default = function() {
         return {};
@@ -6506,7 +6613,7 @@ Mixed.schemaName = 'Mixed';
 /*!
  * Inherits from SchemaType.
  */
-Mixed.prototype = Object.create( SchemaType.prototype );
+Mixed.prototype = Object.create(SchemaType.prototype);
 Mixed.prototype.constructor = Mixed;
 
 /**
@@ -6541,7 +6648,9 @@ Mixed.prototype.cast = function(val) {
  */
 
 Mixed.prototype.castForQuery = function($cond, val) {
-  if (arguments.length === 2) return val;
+  if (arguments.length === 2) {
+    return val;
+  }
   return $cond;
 };
 
@@ -6588,7 +6697,7 @@ SchemaNumber.schemaName = 'Number';
 /*!
  * Inherits from SchemaType.
  */
-SchemaNumber.prototype = Object.create( SchemaType.prototype );
+SchemaNumber.prototype = Object.create(SchemaType.prototype);
 SchemaNumber.prototype.constructor = SchemaNumber;
 
 /**
@@ -6599,10 +6708,9 @@ SchemaNumber.prototype.constructor = SchemaNumber;
 
 SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
   if (SchemaType._isRef(this, value, doc, true)) {
-    return null != value;
-  } else {
-    return typeof value == 'number' || value instanceof Number;
+    return !!value;
   }
+  return typeof value === 'number' || value instanceof Number;
 };
 
 /**
@@ -6639,11 +6747,11 @@ SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
 SchemaNumber.prototype.min = function(value, message) {
   if (this.minValidator) {
     this.validators = this.validators.filter(function(v) {
-      return v.validator != this.minValidator;
+      return v.validator !== this.minValidator;
     }, this);
   }
 
-  if (null != value) {
+  if (value !== null && value !== void 0) {
     var msg = message || errorMessages.Number.min;
     msg = msg.replace(/{MIN}/, value);
     this.validators.push({
@@ -6693,11 +6801,11 @@ SchemaNumber.prototype.min = function(value, message) {
 SchemaNumber.prototype.max = function(value, message) {
   if (this.maxValidator) {
     this.validators = this.validators.filter(function(v) {
-      return v.validator != this.maxValidator;
+      return v.validator !== this.maxValidator;
     }, this);
   }
 
-  if (null != value) {
+  if (value !== null && value !== void 0) {
     var msg = message || errorMessages.Number.max;
     msg = msg.replace(/{MAX}/, value);
     this.validators.push({
@@ -6726,7 +6834,7 @@ SchemaNumber.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (null == value) {
+    if (value === null || value === void 0) {
       return value;
     }
 
@@ -6739,7 +6847,7 @@ SchemaNumber.prototype.cast = function(value, doc, init) {
     }
 
     // setting a populated path
-    if ('number' == typeof value) {
+    if (typeof value === 'number') {
       return value;
     } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
       throw new CastError('number', value, this.path);
@@ -6757,19 +6865,26 @@ SchemaNumber.prototype.cast = function(value, doc, init) {
   }
 
   var val = value && value._id
-    ? value._id // documents
-    : value;
+      ? value._id // documents
+      : value;
 
   if (!isNaN(val)) {
-    if (null === val) return val;
-    if ('' === val) return null;
+    if (val === null) {
+      return val;
+    }
+    if (val === '') {
+      return null;
+    }
     if (typeof val === 'string' || typeof val === 'boolean') {
       val = Number(val);
     }
-    if (val instanceof Number) return val;
-    if ('number' == typeof val) return val;
-    if (val.toString && !Array.isArray(val) &&
-        val.toString() == Number(val)) {
+    if (val instanceof Number) {
+      return val;
+    }
+    if (typeof val === 'number') {
+      return val;
+    }
+    if (val.toString && !Array.isArray(val) && val.toString() == Number(val)) {
       return new Number(val);
     }
   }
@@ -6786,27 +6901,27 @@ function handleSingle(val) {
 }
 
 function handleArray(val) {
-  var self = this;
+  var _this = this;
   if (!Array.isArray(val)) {
     return [this.cast(val)];
   }
   return val.map(function(m) {
-    return self.cast(m);
+    return _this.cast(m);
   });
 }
 
 SchemaNumber.prototype.$conditionalHandlers =
-  utils.options(SchemaType.prototype.$conditionalHandlers, {
-    '$bitsAllClear': handleBitwiseOperator,
-    '$bitsAnyClear': handleBitwiseOperator,
-    '$bitsAllSet': handleBitwiseOperator,
-    '$bitsAnySet': handleBitwiseOperator,
-    '$gt' : handleSingle,
-    '$gte': handleSingle,
-    '$lt' : handleSingle,
-    '$lte': handleSingle,
-    '$mod': handleArray
-  });
+    utils.options(SchemaType.prototype.$conditionalHandlers, {
+      '$bitsAllClear': handleBitwiseOperator,
+      '$bitsAnyClear': handleBitwiseOperator,
+      '$bitsAllSet': handleBitwiseOperator,
+      '$bitsAnySet': handleBitwiseOperator,
+      '$gt': handleSingle,
+      '$gte': handleSingle,
+      '$lt': handleSingle,
+      '$lte': handleSingle,
+      '$mod': handleArray
+    });
 
 /**
  * Casts contents for queries.
@@ -6820,13 +6935,13 @@ SchemaNumber.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = this.$conditionalHandlers[$conditional];
-    if (!handler)
-      throw new Error("Can't use " + $conditional + " with Number.");
+    if (!handler) {
+      throw new Error('Can\'t use ' + $conditional + ' with Number.');
+    }
     return handler.call(this, val);
-  } else {
-    val = this.cast($conditional);
-    return val == null ? val : val;
   }
+  val = this.cast($conditional);
+  return val;
 };
 
 /*!
@@ -6874,7 +6989,7 @@ ObjectId.schemaName = 'ObjectId';
 /*!
  * Inherits from SchemaType.
  */
-ObjectId.prototype = Object.create( SchemaType.prototype );
+ObjectId.prototype = Object.create(SchemaType.prototype);
 ObjectId.prototype.constructor = ObjectId;
 
 /**
@@ -6901,10 +7016,9 @@ ObjectId.prototype.auto = function(turnOn) {
 
 ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
   if (SchemaType._isRef(this, value, doc, true)) {
-    return null != value;
-  } else {
-    return value instanceof oid;
+    return !!value;
   }
+  return value instanceof oid;
 };
 
 /**
@@ -6920,7 +7034,7 @@ ObjectId.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (null == value) {
+    if (value === null || value === void 0) {
       return value;
     }
 
@@ -6951,10 +7065,13 @@ ObjectId.prototype.cast = function(value, doc, init) {
   }
 
   // If null or undefined
-  if (value == null) return value;
+  if (value === null || value === void 0) {
+    return value;
+  }
 
-  if (value instanceof oid)
+  if (value instanceof oid) {
     return value;
+  }
 
   if (value._id) {
     if (value._id instanceof oid) {
@@ -6963,7 +7080,8 @@ ObjectId.prototype.cast = function(value, doc, init) {
     if (value._id.toString instanceof Function) {
       try {
         return oid.createFromHexString(value._id.toString());
-      } catch (e) {}
+      } catch (e) {
+      }
     }
   }
 
@@ -6987,12 +7105,12 @@ function handleSingle(val) {
 }
 
 ObjectId.prototype.$conditionalHandlers =
-  utils.options(SchemaType.prototype.$conditionalHandlers, {
-    '$gt': handleSingle,
-    '$gte': handleSingle,
-    '$lt': handleSingle,
-    '$lte': handleSingle
-  });
+    utils.options(SchemaType.prototype.$conditionalHandlers, {
+      '$gt': handleSingle,
+      '$gte': handleSingle,
+      '$lt': handleSingle,
+      '$lte': handleSingle
+    });
 
 /**
  * Casts contents for queries.
@@ -7006,12 +7124,12 @@ ObjectId.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = this.$conditionalHandlers[$conditional];
-    if (!handler)
-      throw new Error("Can't use " + $conditional + " with ObjectId.");
+    if (!handler) {
+      throw new Error('Can\'t use ' + $conditional + ' with ObjectId.');
+    }
     return handler.call(this, val);
-  } else {
-    return this.cast($conditional);
   }
+  return this.cast($conditional);
 };
 
 /*!
@@ -7050,24 +7168,23 @@ function handleBitwiseOperator(val) {
   var _this = this;
   if (Array.isArray(val)) {
     return val.map(function(v) {
-      return _castNumber(_this, v);
+      return _castNumber(_this.path, v);
     });
   } else if (Buffer.isBuffer(val)) {
     return val;
-  } else {
-    // Assume trying to cast to number
-    return _castNumber(_this, val);
   }
+  // Assume trying to cast to number
+  return _castNumber(_this.path, val);
 }
 
 /*!
  * ignore
  */
 
-function _castNumber(_this, num) {
+function _castNumber(path, num) {
   var v = Number(num);
   if (isNaN(v)) {
-    throw new CastError('number', num, _this.path);
+    throw new CastError('number', num, path);
   }
   return v;
 }
@@ -7077,7 +7194,6 @@ module.exports = handleBitwiseOperator;
 }).call(this,require("buffer").Buffer)
 },{"../../error/cast":13,"buffer":71}],38:[function(require,module,exports){
 (function (Buffer){
-
 /*!
  * Module dependencies.
  */
@@ -7114,7 +7230,7 @@ SchemaString.schemaName = 'String';
 /*!
  * Inherits from SchemaType.
  */
-SchemaString.prototype = Object.create( SchemaType.prototype );
+SchemaString.prototype = Object.create(SchemaType.prototype);
 SchemaString.prototype.constructor = SchemaString;
 
 /**
@@ -7155,12 +7271,12 @@ SchemaString.prototype.constructor = SchemaString;
 SchemaString.prototype.enum = function() {
   if (this.enumValidator) {
     this.validators = this.validators.filter(function(v) {
-      return v.validator != this.enumValidator;
+      return v.validator !== this.enumValidator;
     }, this);
     this.enumValidator = false;
   }
 
-  if (undefined === arguments[0] || false === arguments[0]) {
+  if (arguments[0] === void 0 || arguments[0] === false) {
     return this;
   }
 
@@ -7211,8 +7327,12 @@ SchemaString.prototype.enum = function() {
 
 SchemaString.prototype.lowercase = function() {
   return this.set(function(v, self) {
-    if ('string' != typeof v) v = self.cast(v);
-    if (v) return v.toLowerCase();
+    if (typeof v !== 'string') {
+      v = self.cast(v);
+    }
+    if (v) {
+      return v.toLowerCase();
+    }
     return v;
   });
 };
@@ -7233,8 +7353,12 @@ SchemaString.prototype.lowercase = function() {
 
 SchemaString.prototype.uppercase = function() {
   return this.set(function(v, self) {
-    if ('string' != typeof v) v = self.cast(v);
-    if (v) return v.toUpperCase();
+    if (typeof v !== 'string') {
+      v = self.cast(v);
+    }
+    if (v) {
+      return v.toUpperCase();
+    }
     return v;
   });
 };
@@ -7259,8 +7383,12 @@ SchemaString.prototype.uppercase = function() {
 
 SchemaString.prototype.trim = function() {
   return this.set(function(v, self) {
-    if ('string' != typeof v) v = self.cast(v);
-    if (v) return v.trim();
+    if (typeof v !== 'string') {
+      v = self.cast(v);
+    }
+    if (v) {
+      return v.trim();
+    }
     return v;
   });
 };
@@ -7299,11 +7427,11 @@ SchemaString.prototype.trim = function() {
 SchemaString.prototype.minlength = function(value, message) {
   if (this.minlengthValidator) {
     this.validators = this.validators.filter(function(v) {
-      return v.validator != this.minlengthValidator;
+      return v.validator !== this.minlengthValidator;
     }, this);
   }
 
-  if (null != value) {
+  if (value !== null) {
     var msg = message || errorMessages.String.minlength;
     msg = msg.replace(/{MINLENGTH}/, value);
     this.validators.push({
@@ -7353,11 +7481,11 @@ SchemaString.prototype.minlength = function(value, message) {
 SchemaString.prototype.maxlength = function(value, message) {
   if (this.maxlengthValidator) {
     this.validators = this.validators.filter(function(v) {
-      return v.validator != this.maxlengthValidator;
+      return v.validator !== this.maxlengthValidator;
     }, this);
   }
 
-  if (null != value) {
+  if (value != null) {
     var msg = message || errorMessages.String.maxlength;
     msg = msg.replace(/{MAXLENGTH}/, value);
     this.validators.push({
@@ -7421,9 +7549,9 @@ SchemaString.prototype.match = function match(regExp, message) {
       return false;
     }
 
-    var ret = ((null != v && '' !== v)
-      ? regExp.test(v)
-      : true);
+    var ret = ((v != null && v !== '')
+        ? regExp.test(v)
+        : true);
     return ret;
   };
 
@@ -7445,10 +7573,9 @@ SchemaString.prototype.match = function match(regExp, message) {
 
 SchemaString.prototype.checkRequired = function checkRequired(value, doc) {
   if (SchemaType._isRef(this, value, doc, true)) {
-    return null != value;
-  } else {
-    return (value instanceof String || typeof value == 'string') && value.length;
+    return !!value;
   }
+  return (value instanceof String || typeof value === 'string') && value.length;
 };
 
 /**
@@ -7461,7 +7588,7 @@ SchemaString.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (null == value) {
+    if (value === null) {
       return value;
     }
 
@@ -7474,7 +7601,7 @@ SchemaString.prototype.cast = function(value, doc, init) {
     }
 
     // setting a populated path
-    if ('string' == typeof value) {
+    if (typeof value === 'string') {
       return value;
     } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
       throw new CastError('string', value, this.path);
@@ -7492,13 +7619,13 @@ SchemaString.prototype.cast = function(value, doc, init) {
   }
 
   // If null or undefined
-  if (value == null) {
+  if (value === null || value === void 0) {
     return value;
   }
 
-  if ('undefined' !== typeof value) {
+  if (typeof value !== 'undefined') {
     // handle documents being passed
-    if (value._id && 'string' == typeof value._id) {
+    if (value._id && typeof value._id === 'string') {
       return value._id;
     }
 
@@ -7522,25 +7649,25 @@ function handleSingle(val) {
 }
 
 function handleArray(val) {
-  var self = this;
+  var _this = this;
   if (!Array.isArray(val)) {
     return [this.castForQuery(val)];
   }
   return val.map(function(m) {
-    return self.castForQuery(m);
+    return _this.castForQuery(m);
   });
 }
 
 SchemaString.prototype.$conditionalHandlers =
-  utils.options(SchemaType.prototype.$conditionalHandlers, {
-    '$all': handleArray,
-    '$gt' : handleSingle,
-    '$gte': handleSingle,
-    '$lt' : handleSingle,
-    '$lte': handleSingle,
-    '$options': handleSingle,
-    '$regex': handleSingle
-  });
+    utils.options(SchemaType.prototype.$conditionalHandlers, {
+      '$all': handleArray,
+      '$gt': handleSingle,
+      '$gte': handleSingle,
+      '$lt': handleSingle,
+      '$lte': handleSingle,
+      '$options': handleSingle,
+      '$regex': handleSingle
+    });
 
 /**
  * Casts contents for queries.
@@ -7554,16 +7681,16 @@ SchemaString.prototype.castForQuery = function($conditional, val) {
   var handler;
   if (arguments.length === 2) {
     handler = this.$conditionalHandlers[$conditional];
-    if (!handler)
-      throw new Error("Can't use " + $conditional + " with String.");
-    return handler.call(this, val);
-  } else {
-    val = $conditional;
-    if (Object.prototype.toString.call(val) === '[object RegExp]') {
-      return val;
+    if (!handler) {
+      throw new Error('Can\'t use ' + $conditional + ' with String.');
     }
-    return this.cast(val);
+    return handler.call(this, val);
+  }
+  val = $conditional;
+  if (Object.prototype.toString.call(val) === '[object RegExp]') {
+    return val;
   }
+  return this.cast(val);
 };
 
 /*!
@@ -7605,13 +7732,15 @@ function SchemaType(path, options, instance) {
   this.selected;
 
   for (var i in options) {
-    if (this[i] && 'function' == typeof this[i]) {
+    if (this[i] && typeof this[i] === 'function') {
       // { unique: true, index: true }
-      if ('index' == i && this._index) continue;
+      if (i === 'index' && this._index) {
+        continue;
+      }
 
       var opts = Array.isArray(options[i])
-        ? options[i]
-        : [options[i]];
+          ? options[i]
+          : [options[i]];
 
       this[i].apply(this, opts);
     }
@@ -7662,10 +7791,10 @@ function SchemaType(path, options, instance) {
  */
 
 SchemaType.prototype.default = function(val) {
-  if (1 === arguments.length) {
+  if (arguments.length === 1) {
     this.defaultValue = typeof val === 'function'
-      ? val
-      : this.cast(val);
+        ? val
+        : this.cast(val);
     return this;
   } else if (arguments.length > 1) {
     this.defaultValue = utils.args(arguments);
@@ -7720,10 +7849,10 @@ SchemaType.prototype.index = function(options) {
  */
 
 SchemaType.prototype.unique = function(bool) {
-  if (null == this._index || 'boolean' == typeof this._index) {
+  if (this._index === null || typeof this._index === 'boolean') {
     this._index = {};
-  } else if ('string' == typeof this._index) {
-    this._index = { type: this._index };
+  } else if (typeof this._index === 'string') {
+    this._index = {type: this._index};
   }
 
   this._index.unique = bool;
@@ -7743,10 +7872,10 @@ SchemaType.prototype.unique = function(bool) {
  */
 
 SchemaType.prototype.text = function(bool) {
-  if (null == this._index || 'boolean' == typeof this._index) {
+  if (this._index === null || typeof this._index === 'boolean') {
     this._index = {};
-  } else if ('string' == typeof this._index) {
-    this._index = { type: this._index };
+  } else if (typeof this._index === 'string') {
+    this._index = {type: this._index};
   }
 
   this._index.text = bool;
@@ -7767,10 +7896,10 @@ SchemaType.prototype.text = function(bool) {
  */
 
 SchemaType.prototype.sparse = function(bool) {
-  if (null == this._index || 'boolean' == typeof this._index) {
+  if (this._index === null || typeof this._index === 'boolean') {
     this._index = {};
-  } else if ('string' == typeof this._index) {
-    this._index = { type: this._index };
+  } else if (typeof this._index === 'string') {
+    this._index = {type: this._index};
   }
 
   this._index.sparse = bool;
@@ -7783,7 +7912,7 @@ SchemaType.prototype.sparse = function(bool) {
  * ####Example:
  *
  *     function capitalize (val) {
- *       if ('string' != typeof val) val = '';
+ *       if (typeof val !== 'string') val = '';
  *       return val.charAt(0).toUpperCase() + val.substring(1);
  *     }
  *
@@ -7851,8 +7980,9 @@ SchemaType.prototype.sparse = function(bool) {
  */
 
 SchemaType.prototype.set = function(fn) {
-  if ('function' != typeof fn)
+  if (typeof fn !== 'function') {
     throw new TypeError('A setter must be a function.');
+  }
   this.setters.push(fn);
   return this;
 };
@@ -7920,8 +8050,9 @@ SchemaType.prototype.set = function(fn) {
  */
 
 SchemaType.prototype.get = function(fn) {
-  if ('function' != typeof fn)
+  if (typeof fn !== 'function') {
     throw new TypeError('A getter must be a function.');
+  }
   this.getters.push(fn);
   return this;
 };
@@ -7961,7 +8092,7 @@ SchemaType.prototype.get = function(fn) {
  *
  * ####Error message templates:
  *
- * From the examples above, you may have noticed that error messages support baseic templating. There are a few other template keywords besides `{PATH}` and `{VALUE}` too. To find out more, details are available [here](#error_messages_MongooseError-messages)
+ * From the examples above, you may have noticed that error messages support basic templating. There are a few other template keywords besides `{PATH}` and `{VALUE}` too. To find out more, details are available [here](#error_messages_MongooseError-messages)
  *
  * ####Asynchronous validation:
  *
@@ -8009,7 +8140,7 @@ SchemaType.prototype.get = function(fn) {
  */
 
 SchemaType.prototype.validate = function(obj, message, type) {
-  if ('function' == typeof obj || obj && utils.getFunctionName(obj.constructor) === 'RegExp') {
+  if (typeof obj === 'function' || obj && utils.getFunctionName(obj.constructor) === 'RegExp') {
     var properties;
     if (message instanceof Object && !type) {
       properties = utils.clone(message);
@@ -8019,9 +8150,13 @@ SchemaType.prototype.validate = function(obj, message, type) {
       properties.validator = obj;
       properties.type = properties.type || 'user defined';
     } else {
-      if (!message) message = errorMessages.general.default;
-      if (!type) type = 'user defined';
-      properties = { message: message, type: type, validator: obj };
+      if (!message) {
+        message = errorMessages.general.default;
+      }
+      if (!type) {
+        type = 'user defined';
+      }
+      properties = {message: message, type: type, validator: obj};
     }
     this.validators.push(properties);
     return this;
@@ -8033,10 +8168,10 @@ SchemaType.prototype.validate = function(obj, message, type) {
 
   for (i = 0, length = arguments.length; i < length; i++) {
     arg = arguments[i];
-    if (!(arg && utils.getFunctionName(arg.constructor)) === 'Object') {
+    if (!(arg && utils.getFunctionName(arg.constructor) === 'Object')) {
       var msg = 'Invalid validator. Received (' + typeof arg + ') '
-        + arg
-        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
+          + arg
+          + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
 
       throw new Error(msg);
     }
@@ -8075,30 +8210,30 @@ SchemaType.prototype.validate = function(obj, message, type) {
  */
 
 SchemaType.prototype.required = function(required, message) {
-  if (false === required) {
+  if (required === false) {
     this.validators = this.validators.filter(function(v) {
-      return v.validator != this.requiredValidator;
+      return v.validator !== this.requiredValidator;
     }, this);
 
     this.isRequired = false;
     return this;
   }
 
-  var self = this;
+  var _this = this;
   this.isRequired = true;
 
   this.requiredValidator = function(v) {
     // in here, `this` refers to the validating document.
     // no validation when this path wasn't selected in the query.
-    if ('isSelected' in this &&
-        !this.isSelected(self.path) &&
-        !this.isModified(self.path)) return true;
+    if ('isSelected' in this && !this.isSelected(_this.path) && !this.isModified(_this.path)) {
+      return true;
+    }
 
-    return (('function' === typeof required) && !required.apply(this)) ||
-        self.checkRequired(v, this);
+    return ((typeof required === 'function') && !required.apply(this)) ||
+        _this.checkRequired(v, this);
   };
 
-  if ('string' == typeof required) {
+  if (typeof required === 'string') {
     message = required;
     required = undefined;
   }
@@ -8122,15 +8257,14 @@ SchemaType.prototype.required = function(required, message) {
  */
 
 SchemaType.prototype.getDefault = function(scope, init) {
-  var ret = 'function' === typeof this.defaultValue
-    ? this.defaultValue.call(scope)
-    : this.defaultValue;
+  var ret = typeof this.defaultValue === 'function'
+      ? this.defaultValue.call(scope)
+      : this.defaultValue;
 
-  if (null !== ret && undefined !== ret) {
+  if (ret !== null && undefined !== ret) {
     return this.cast(ret, scope, init);
-  } else {
-    return ret;
   }
+  return ret;
 };
 
 /**
@@ -8160,7 +8294,9 @@ SchemaType.prototype.applySetters = function(value, scope, init, priorVal, optio
     v = newVal;
   }
 
-  if (null === v || undefined === v) return v;
+  if (v === null || v === void 0) {
+    return v;
+  }
 
   // do not cast until all setters are applied #665
   v = this.cast(v, scope, init, priorVal, options);
@@ -8228,10 +8364,14 @@ SchemaType.prototype.doValidate = function(value, fn, scope) {
       path = this.path,
       count = this.validators.length;
 
-  if (!count) return fn(null);
+  if (!count) {
+    return fn(null);
+  }
 
   var validate = function(ok, validatorProperties) {
-    if (err) return;
+    if (err) {
+      return;
+    }
     if (ok === undefined || ok) {
       --count || fn(null);
     } else {
@@ -8240,7 +8380,7 @@ SchemaType.prototype.doValidate = function(value, fn, scope) {
     }
   };
 
-  var self = this;
+  var _this = this;
   this.validators.forEach(function(v) {
     if (err) {
       return;
@@ -8254,12 +8394,12 @@ SchemaType.prototype.doValidate = function(value, fn, scope) {
 
     if (validator instanceof RegExp) {
       validate(validator.test(value), validatorProperties);
-    } else if ('function' === typeof validator) {
-      if (value === undefined && !self.isRequired) {
+    } else if (typeof validator === 'function') {
+      if (value === undefined && !_this.isRequired) {
         validate(true, validatorProperties);
         return;
       }
-      if (2 === validator.length) {
+      if (validator.length === 2) {
         validator.call(scope, value, function(ok, customMsg) {
           if (customMsg) {
             validatorProperties.message = customMsg;
@@ -8291,17 +8431,21 @@ SchemaType.prototype.doValidateSync = function(value, scope) {
       path = this.path,
       count = this.validators.length;
 
-  if (!count) return null;
+  if (!count) {
+    return null;
+  }
 
   var validate = function(ok, validatorProperties) {
-    if (err) return;
+    if (err) {
+      return;
+    }
     if (ok !== undefined && !ok) {
       err = new ValidatorError(validatorProperties);
     }
   };
 
-  var self = this;
-  if (value === undefined && !self.isRequired) {
+  var _this = this;
+  if (value === undefined && !_this.isRequired) {
     return null;
   }
 
@@ -8317,9 +8461,9 @@ SchemaType.prototype.doValidateSync = function(value, scope) {
 
     if (validator instanceof RegExp) {
       validate(validator.test(value), validatorProperties);
-    } else if ('function' === typeof validator) {
+    } else if (typeof validator === 'function') {
       // if not async validators
-      if (2 !== validator.length) {
+      if (validator.length !== 2) {
         validate(validator.call(scope, value), validatorProperties);
       }
     }
@@ -8353,11 +8497,13 @@ SchemaType._isRef = function(self, value, doc, init) {
   }
 
   if (ref) {
-    if (null == value) return true;
+    if (value == null) {
+      return true;
+    }
     if (!Buffer.isBuffer(value) &&  // buffers are objects too
-        'Binary' != value._bsontype // raw binary value from the db
+        value._bsontype !== 'Binary' // raw binary value from the db
         && utils.isObject(value)    // might have deselected _id in population query
-       ) {
+    ) {
       return true;
     }
   }
@@ -8392,11 +8538,11 @@ function handleArray(val) {
  */
 
 SchemaType.prototype.$conditionalHandlers = {
-  '$all': handleArray,
-  '$eq': handleSingle,
-  '$in' : handleArray,
-  '$ne' : handleSingle,
-  '$nin': handleArray
+  $all: handleArray,
+  $eq: handleSingle,
+  $in: handleArray,
+  $ne: handleSingle,
+  $nin: handleArray
 };
 
 /**
@@ -8415,10 +8561,20 @@ SchemaType.prototype.castForQuery = function($conditional, val) {
       throw new Error('Can\'t use ' + $conditional);
     }
     return handler.call(this, val);
-  } else {
-    val = $conditional;
-    return this.cast(val);
   }
+  val = $conditional;
+  return this.cast(val);
+};
+
+/**
+ * Default check for if this path satisfies the `required` validator.
+ *
+ * @param {any} val
+ * @api private
+ */
+
+SchemaType.prototype.checkRequired = function(val) {
+  return val != null;
 };
 
 /*!
@@ -8537,10 +8693,10 @@ StateMachine.prototype.clear = function clear(state) {
  */
 
 StateMachine.prototype.some = function some() {
-  var self = this;
+  var _this = this;
   var what = arguments.length ? arguments : this.stateNames;
   return Array.prototype.some.call(what, function(state) {
-    return Object.keys(self.states[state]).length;
+    return Object.keys(_this.states[state]).length;
   });
 };
 
@@ -8561,10 +8717,10 @@ StateMachine.prototype._iter = function _iter(iterMethod) {
 
     if (!states.length) states = this.stateNames;
 
-    var self = this;
+    var _this = this;
 
     var paths = states.reduce(function(paths, state) {
-      return paths.concat(Object.keys(self.states[state]));
+      return paths.concat(Object.keys(_this.states[state]));
     }, []);
 
     return paths[iterMethod](function(path, i, paths) {
@@ -8641,20 +8797,26 @@ var isMongooseObject = utils.isMongooseObject;
 
 function MongooseArray(values, path, doc) {
   var arr = [].concat(values);
+  var props = {
+    isMongooseArray: true,
+    validators: [],
+    _path: path,
+    _atomics: {},
+    _schema: void 0
+  };
+  var tmp = {};
 
-  utils.decorate( arr, MongooseArray.mixin );
-  arr.isMongooseArray = true;
+  var keysMA = Object.keys(MongooseArray.mixin);
+  for (var i = 0; i < keysMA.length; ++i) {
+    tmp[keysMA[i]] = {enumerable: false, configurable: true, writable: true, value: MongooseArray.mixin[keysMA[i]]};
+  }
 
-  var _options = { enumerable: false, configurable: true, writable: true };
-  var keys = Object.keys(MongooseArray.mixin).
-    concat(['isMongooseArray', 'validators', '_path']);
-  for (var i = 0; i < keys.length; ++i) {
-    Object.defineProperty(arr, keys[i], _options);
+  var keysP = Object.keys(props);
+  for (var j = 0; j < keysP.length; ++j) {
+    tmp[keysP[j]] = {enumerable: false, configurable: true, writable: true, value: props[keysP[j]]};
   }
 
-  arr._atomics = {};
-  arr.validators = [];
-  arr._path = path;
+  Object.defineProperties(arr, tmp);
 
   // Because doc comes from the context of another function, doc === global
   // can happen if there was a null somewhere up the chain (see #3020)
@@ -8709,14 +8871,14 @@ MongooseArray.mixin = {
       // instance as specified in the original query.
       if (!owner) {
         owner = this._owner = this._parent.ownerDocument
-          ? this._parent.ownerDocument()
-          : this._parent;
+            ? this._parent.ownerDocument()
+            : this._parent;
       }
 
       populated = owner.populated(this._path, true);
     }
 
-    if (populated && null != value) {
+    if (populated && value !== null) {
       // cast to the populated Models schema
       Model = populated.options.model;
 
@@ -8724,13 +8886,13 @@ MongooseArray.mixin = {
       // non-objects are to be interpreted as _id
       if (Buffer.isBuffer(value) ||
           value instanceof ObjectId || !utils.isObject(value)) {
-        value = { _id: value };
+        value = {_id: value};
       }
 
       // gh-2399
       // we should cast model only when it's not a discriminator
       var isDisc = value.schema && value.schema.discriminatorMapping &&
-        value.schema.discriminatorMapping.key !== undefined;
+          value.schema.discriminatorMapping.key !== undefined;
       if (!isDisc) {
         value = new Model(value);
       }
@@ -8760,7 +8922,7 @@ MongooseArray.mixin = {
       dirtyPath = this._path;
 
       if (arguments.length) {
-        if (null != embeddedPath) {
+        if (embeddedPath != null) {
           // an embedded doc bubbled up the change
           dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
         } else {
@@ -8786,20 +8948,20 @@ MongooseArray.mixin = {
    */
 
   _registerAtomic: function(op, val) {
-    if ('$set' == op) {
+    if (op === '$set') {
       // $set takes precedence over all other ops.
       // mark entire array modified.
-      this._atomics = { $set: val };
+      this._atomics = {$set: val};
       return this;
     }
 
     var atomics = this._atomics;
 
     // reset pop/shift after save
-    if ('$pop' == op && !('$pop' in atomics)) {
-      var self = this;
+    if (op === '$pop' && !('$pop' in atomics)) {
+      var _this = this;
       this._parent.once('save', function() {
-        self._popped = self._shifted = null;
+        _this._popped = _this._shifted = null;
       });
     }
 
@@ -8809,7 +8971,7 @@ MongooseArray.mixin = {
         Object.keys(atomics).length && !(op in atomics)) {
       // a different op was previously registered.
       // save the entire thing.
-      this._atomics = { $set: this };
+      this._atomics = {$set: this};
       return this;
     }
 
@@ -8823,10 +8985,10 @@ MongooseArray.mixin = {
       if (val[0] instanceof EmbeddedDocument) {
         selector = pullOp['$or'] || (pullOp['$or'] = []);
         Array.prototype.push.apply(selector, val.map(function(v) {
-          return v.toObject({ virtuals: false });
+          return v.toObject({virtuals: false});
         }));
       } else {
-        selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
+        selector = pullOp['_id'] || (pullOp['_id'] = {'$in': []});
         selector['$in'] = selector['$in'].concat(val);
       }
     } else {
@@ -8852,8 +9014,8 @@ MongooseArray.mixin = {
     var keys = Object.keys(this._atomics);
     var i = keys.length;
 
-    if (0 === i) {
-      ret[0] = ['$set', this.toObject({ depopulate: 1, transform: false })];
+    if (i === 0) {
+      ret[0] = ['$set', this.toObject({depopulate: 1, transform: false})];
       return ret;
     }
 
@@ -8865,15 +9027,15 @@ MongooseArray.mixin = {
       // need to convert their elements as if they were MongooseArrays
       // to handle populated arrays versus DocumentArrays properly.
       if (isMongooseObject(val)) {
-        val = val.toObject({ depopulate: 1, transform: false });
+        val = val.toObject({depopulate: 1, transform: false});
       } else if (Array.isArray(val)) {
-        val = this.toObject.call(val, { depopulate: 1, transform: false });
+        val = this.toObject.call(val, {depopulate: 1, transform: false});
       } else if (val.valueOf) {
         val = val.valueOf();
       }
 
-      if ('$addToSet' == op) {
-        val = { $each: val };
+      if (op === '$addToSet') {
+        val = {$each: val};
       }
 
       ret.push([op, val]);
@@ -8892,7 +9054,7 @@ MongooseArray.mixin = {
    */
 
   hasAtomics: function hasAtomics() {
-    if (!(this._atomics && this._atomics.constructor.name) === 'Object') {
+    if (!(this._atomics && this._atomics.constructor.name === 'Object')) {
       return 0;
     }
 
@@ -8923,7 +9085,7 @@ MongooseArray.mixin = {
   push: function() {
     var values = [].map.call(arguments, this._mapCast, this);
     values = this._schema.applySetters(values, this._parent, undefined,
-      undefined, { skipDocumentArrayCast: true });
+        undefined, {skipDocumentArrayCast: true});
     var ret = [].push.apply(this, values);
 
     // $pushAll might be fibbed (could be $push). But it makes it easier to
@@ -8994,7 +9156,9 @@ MongooseArray.mixin = {
     this._markModified();
 
     // only allow popping once
-    if (this._popped) return;
+    if (this._popped) {
+      return;
+    }
     this._popped = true;
 
     return [].pop.call(this);
@@ -9058,7 +9222,9 @@ MongooseArray.mixin = {
     this._markModified();
 
     // only allow shifting once
-    if (this._shifted) return;
+    if (this._shifted) {
+      return;
+    }
     this._shifted = true;
 
     return [].shift.call(this);
@@ -9128,7 +9294,9 @@ MongooseArray.mixin = {
     while (i--) {
       mem = cur[i];
       if (mem instanceof Document) {
-        if (values.some(function(v) { return v.equals(mem); } )) {
+        if (values.some(function(v) {
+          return v.equals(mem);
+        })) {
           [].splice.call(cur, i, 1);
         }
       } else if (~cur.indexOf.call(values, mem)) {
@@ -9167,8 +9335,8 @@ MongooseArray.mixin = {
       vals = [];
       for (i = 0; i < arguments.length; ++i) {
         vals[i] = i < 2
-          ? arguments[i]
-          : this._cast(arguments[i], arguments[0] + (i - 2));
+            ? arguments[i]
+            : this._cast(arguments[i], arguments[0] + (i - 2));
       }
       ret = [].splice.apply(this, vals);
       this._registerAtomic('$set', this);
@@ -9239,19 +9407,26 @@ MongooseArray.mixin = {
     var values = [].map.call(arguments, this._mapCast, this);
     values = this._schema.applySetters(values, this._parent);
     var added = [];
-    var type = values[0] instanceof EmbeddedDocument ? 'doc' :
-               values[0] instanceof Date ? 'date' :
-               '';
+    var type = '';
+    if (values[0] instanceof EmbeddedDocument) {
+      type = 'doc';
+    } else if (values[0] instanceof Date) {
+      type = 'date';
+    }
 
     values.forEach(function(v) {
       var found;
       switch (type) {
         case 'doc':
-          found = this.some(function(doc) { return doc.equals(v); });
+          found = this.some(function(doc) {
+            return doc.equals(v);
+          });
           break;
         case 'date':
           var val = +v;
-          found = this.some(function(d) { return +d === val; });
+          found = this.some(function(d) {
+            return +d === val;
+          });
           break;
         default:
           found = ~this.indexOf(v);
@@ -9298,9 +9473,9 @@ MongooseArray.mixin = {
   set: function set(i, val) {
     var value = this._cast(val, i);
     value = this._schema.caster instanceof EmbeddedDocument ?
-            value :
-            this._schema.caster.applySetters(val, this._parent)
-            ;
+        value :
+        this._schema.caster.applySetters(val, this._parent)
+    ;
     this[i] = value;
     this._markModified(i);
     return this;
@@ -9320,8 +9495,8 @@ MongooseArray.mixin = {
     if (options && options.depopulate) {
       return this.map(function(doc) {
         return doc instanceof Document
-          ? doc.toObject(options)
-          : doc;
+            ? doc.toObject(options)
+            : doc;
       });
     }
 
@@ -9351,7 +9526,9 @@ MongooseArray.mixin = {
    */
 
   indexOf: function indexOf(obj) {
-    if (obj instanceof ObjectId) obj = obj.toString();
+    if (obj instanceof ObjectId) {
+      obj = obj.toString();
+    }
     for (var i = 0, len = this.length; i < len; ++i) {
       if (obj == this[i]) {
         return i;
@@ -9406,7 +9583,7 @@ function MongooseBuffer(value, encode, offset) {
   var length = arguments.length;
   var val;
 
-  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
+  if (length === 0 || arguments[0] === null || arguments[0] === void 0) {
     val = 0;
   } else {
     val = value;
@@ -9425,17 +9602,17 @@ function MongooseBuffer(value, encode, offset) {
   }
 
   var buf = new Buffer(val, encoding, offset);
-  utils.decorate( buf, MongooseBuffer.mixin );
+  utils.decorate(buf, MongooseBuffer.mixin);
   buf.isMongooseBuffer = true;
 
   // make sure these internal props don't show up in Object.keys()
   Object.defineProperties(buf, {
-    validators: { value: [] },
-    _path: { value: path },
-    _parent: { value: doc }
+    validators: {value: []},
+    _path: {value: path},
+    _parent: {value: doc}
   });
 
-  if (doc && "string" === typeof path) {
+  if (doc && typeof path === 'string') {
     Object.defineProperty(buf, '_schema', {
       value: doc.schema.path(path)
     });
@@ -9449,7 +9626,7 @@ function MongooseBuffer(value, encode, offset) {
  * Inherit from Buffer.
  */
 
-//MongooseBuffer.prototype = new Buffer(0);
+// MongooseBuffer.prototype = new Buffer(0);
 
 MongooseBuffer.mixin = {
 
@@ -9538,21 +9715,23 @@ MongooseBuffer.mixin = {
 
 (
 // node < 0.5
-'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +
-'writeFloat writeDouble fill ' +
-'utf8Write binaryWrite asciiWrite set ' +
+    'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +
+    'writeFloat writeDouble fill ' +
+    'utf8Write binaryWrite asciiWrite set ' +
 
 // node >= 0.5
-'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +
-'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +
-'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'
+    'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +
+    'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +
+    'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'
 ).split(' ').forEach(function(method) {
-  if (!Buffer.prototype[method]) return;
-  MongooseBuffer.mixin[method] = new Function(
-    'var ret = Buffer.prototype.' + method + '.apply(this, arguments);' +
-    'this._markModified();' +
-    'return ret;'
-  );
+  if (!Buffer.prototype[method]) {
+    return;
+  }
+  MongooseBuffer.mixin[method] = function() {
+    var ret = Buffer.prototype[method].apply(this, arguments);
+    this._markModified();
+    return ret;
+  };
 });
 
 /**
@@ -9579,9 +9758,9 @@ MongooseBuffer.mixin = {
  */
 
 MongooseBuffer.mixin.toObject = function(options) {
-  var subtype = 'number' == typeof options
-    ? options
-    : (this._subtype || 0);
+  var subtype = typeof options === 'number'
+      ? options
+      : (this._subtype || 0);
   return new Binary(this, subtype);
 };
 
@@ -9604,7 +9783,9 @@ MongooseBuffer.mixin.equals = function(other) {
   }
 
   for (var i = 0; i < this.length; ++i) {
-    if (this[i] !== other[i]) return false;
+    if (this[i] !== other[i]) {
+      return false;
+    }
   }
 
   return true;
@@ -9633,11 +9814,11 @@ MongooseBuffer.mixin.equals = function(other) {
  */
 
 MongooseBuffer.mixin.subtype = function(subtype) {
-  if ('number' != typeof subtype) {
+  if (typeof subtype !== 'number') {
     throw new TypeError('Invalid subtype. Expected a number');
   }
 
-  if (this._subtype != subtype) {
+  if (this._subtype !== subtype) {
     this._markModified();
   }
 
@@ -9679,16 +9860,35 @@ var MongooseArray = require('./array'),
 
 function MongooseDocumentArray(values, path, doc) {
   var arr = [].concat(values);
+  var props = {
+    isMongooseArray: true,
+    isMongooseDocumentArray: true,
+    validators: [],
+    _path: path,
+    _atomics: {},
+    _schema: void 0,
+    _handlers: void 0
+  };
+  var tmp = {};
 
   // Values always have to be passed to the constructor to initialize, since
   // otherwise MongooseArray#push will mark the array as modified to the parent.
-  utils.decorate( arr, MongooseDocumentArray.mixin );
-  arr.isMongooseArray = true;
-  arr.isMongooseDocumentArray = true;
+  var keysMA = Object.keys(MongooseArray.mixin);
+  for (var j = 0; j < keysMA.length; ++j) {
+    tmp[keysMA[j]] = {enumerable: false, configurable: true, writable: true, value: MongooseArray.mixin[keysMA[j]]};
+  }
+
+  var keysMDA = Object.keys(MongooseDocumentArray.mixin);
+  for (var i = 0; i < keysMDA.length; ++i) {
+    tmp[keysMDA[i]] = {enumerable: false, configurable: true, writable: true, value: MongooseDocumentArray.mixin[keysMDA[i]]};
+  }
+
+  var keysP = Object.keys(props);
+  for (var k = 0; k < keysP.length; ++k) {
+    tmp[keysP[k]] = {enumerable: false, configurable: true, writable: true, value: props[keysP[k]]};
+  }
 
-  arr._atomics = {};
-  arr.validators = [];
-  arr._path = path;
+  Object.defineProperties(arr, tmp);
 
   // Because doc comes from the context of another function, doc === global
   // can happen if there was a null somewhere up the chain (see #3020 && #3034)
@@ -9712,157 +9912,168 @@ function MongooseDocumentArray(values, path, doc) {
 /*!
  * Inherits from MongooseArray
  */
-MongooseDocumentArray.mixin = Object.create( MongooseArray.mixin );
+// MongooseDocumentArray.mixin = Object.create( MongooseArray.mixin );
+MongooseDocumentArray.mixin = {
 
-/**
- * Overrides MongooseArray#cast
- *
- * @method _cast
- * @api private
- * @receiver MongooseDocumentArray
- */
+  /**
+   * Overrides MongooseArray#cast
+   *
+   * @method _cast
+   * @api private
+   * @receiver MongooseDocumentArray
+   */
 
-MongooseDocumentArray.mixin._cast = function(value, index) {
-  if (value instanceof this._schema.casterConstructor) {
-    if (!(value.__parent && value.__parentArray)) {
-      // value may have been created using array.create()
-      value.__parent = this._parent;
-      value.__parentArray = this;
+  _cast: function(value, index) {
+    if (value instanceof this._schema.casterConstructor) {
+      if (!(value.__parent && value.__parentArray)) {
+        // value may have been created using array.create()
+        value.__parent = this._parent;
+        value.__parentArray = this;
+      }
+      value.__index = index;
+      return value;
     }
-    value.__index = index;
-    return value;
-  }
 
-  // handle cast('string') or cast(ObjectId) etc.
-  // only objects are permitted so we can safely assume that
-  // non-objects are to be interpreted as _id
-  if (Buffer.isBuffer(value) ||
-      value instanceof ObjectId || !utils.isObject(value)) {
-    value = { _id: value };
-  }
-  return new this._schema.casterConstructor(value, this, undefined, undefined, index);
-};
+    // handle cast('string') or cast(ObjectId) etc.
+    // only objects are permitted so we can safely assume that
+    // non-objects are to be interpreted as _id
+    if (Buffer.isBuffer(value) ||
+        value instanceof ObjectId || !utils.isObject(value)) {
+      value = {_id: value};
+    }
+    return new this._schema.casterConstructor(value, this, undefined, undefined, index);
+  },
 
-/**
- * Searches array items for the first document with a matching _id.
- *
- * ####Example:
- *
- *     var embeddedDoc = m.array.id(some_id);
- *
- * @return {EmbeddedDocument|null} the subdocument or null if not found.
- * @param {ObjectId|String|Number|Buffer} id
- * @TODO cast to the _id based on schema for proper comparison
- * @method id
- * @api public
- * @receiver MongooseDocumentArray
- */
+  /**
+   * Searches array items for the first document with a matching _id.
+   *
+   * ####Example:
+   *
+   *     var embeddedDoc = m.array.id(some_id);
+   *
+   * @return {EmbeddedDocument|null} the subdocument or null if not found.
+   * @param {ObjectId|String|Number|Buffer} id
+   * @TODO cast to the _id based on schema for proper comparison
+   * @method id
+   * @api public
+   * @receiver MongooseDocumentArray
+   */
 
-MongooseDocumentArray.mixin.id = function(id) {
-  var casted,
-      sid,
-      _id;
+  id: function(id) {
+    var casted,
+        sid,
+        _id;
 
-  try {
-    var casted_ = ObjectIdSchema.prototype.cast.call({}, id);
-    if (casted_) casted = String(casted_);
-  } catch (e) {
-    casted = null;
-  }
+    try {
+      var casted_ = ObjectIdSchema.prototype.cast.call({}, id);
+      if (casted_) {
+        casted = String(casted_);
+      }
+    } catch (e) {
+      casted = null;
+    }
 
-  for (var i = 0, l = this.length; i < l; i++) {
-    _id = this[i].get('_id');
+    for (var i = 0, l = this.length; i < l; i++) {
+      _id = this[i].get('_id');
 
-    if (_id === null || typeof _id === 'undefined') {
-      continue;
-    } else if (_id instanceof Document) {
-      sid || (sid = String(id));
-      if (sid == _id._id) return this[i];
-    } else if (!(_id instanceof ObjectId)) {
-      if (utils.deepEqual(id, _id)) return this[i];
-    } else if (casted == _id) {
-      return this[i];
+      if (_id === null || typeof _id === 'undefined') {
+        continue;
+      } else if (_id instanceof Document) {
+        sid || (sid = String(id));
+        if (sid == _id._id) {
+          return this[i];
+        }
+      } else if (!(_id instanceof ObjectId)) {
+        if (utils.deepEqual(id, _id)) {
+          return this[i];
+        }
+      } else if (casted == _id) {
+        return this[i];
+      }
     }
-  }
 
-  return null;
-};
+    return null;
+  },
 
-/**
- * Returns a native js Array of plain js objects
- *
- * ####NOTE:
- *
- * _Each sub-document is converted to a plain object by calling its `#toObject` method._
- *
- * @param {Object} [options] optional options to pass to each documents `toObject` method call during conversion
- * @return {Array}
- * @method toObject
- * @api public
- * @receiver MongooseDocumentArray
- */
+  /**
+   * Returns a native js Array of plain js objects
+   *
+   * ####NOTE:
+   *
+   * _Each sub-document is converted to a plain object by calling its `#toObject` method._
+   *
+   * @param {Object} [options] optional options to pass to each documents `toObject` method call during conversion
+   * @return {Array}
+   * @method toObject
+   * @api public
+   * @receiver MongooseDocumentArray
+   */
 
-MongooseDocumentArray.mixin.toObject = function(options) {
-  return this.map(function(doc) {
-    return doc && doc.toObject(options) || null;
-  });
-};
+  toObject: function(options) {
+    return this.map(function(doc) {
+      return doc && doc.toObject(options) || null;
+    });
+  },
 
-/**
- * Helper for console.log
- *
- * @method inspect
- * @api public
- * @receiver MongooseDocumentArray
- */
+  /**
+   * Helper for console.log
+   *
+   * @method inspect
+   * @api public
+   * @receiver MongooseDocumentArray
+   */
 
-MongooseDocumentArray.mixin.inspect = function() {
-  return Array.prototype.slice.call(this);
-};
+  inspect: function() {
+    return Array.prototype.slice.call(this);
+  },
 
-/**
- * Creates a subdocument casted to this schema.
- *
- * This is the same subdocument constructor used for casting.
- *
- * @param {Object} obj the value to cast to this arrays SubDocument schema
- * @method create
- * @api public
- * @receiver MongooseDocumentArray
- */
+  /**
+   * Creates a subdocument casted to this schema.
+   *
+   * This is the same subdocument constructor used for casting.
+   *
+   * @param {Object} obj the value to cast to this arrays SubDocument schema
+   * @method create
+   * @api public
+   * @receiver MongooseDocumentArray
+   */
 
-MongooseDocumentArray.mixin.create = function(obj) {
-  return new this._schema.casterConstructor(obj);
-};
+  create: function(obj) {
+    return new this._schema.casterConstructor(obj);
+  },
 
-/**
- * Creates a fn that notifies all child docs of `event`.
- *
- * @param {String} event
- * @return {Function}
- * @method notify
- * @api private
- * @receiver MongooseDocumentArray
- */
+  /**
+   * Creates a fn that notifies all child docs of `event`.
+   *
+   * @param {String} event
+   * @return {Function}
+   * @method notify
+   * @api private
+   * @receiver MongooseDocumentArray
+   */
 
-MongooseDocumentArray.mixin.notify = function notify(event) {
-  var self = this;
-  return function notify(val) {
-    var i = self.length;
-    while (i--) {
-      if (!self[i]) continue;
-      switch (event) {
-        // only swap for save event for now, we may change this to all event types later
-        case 'save':
-          val = self[i];
-          break;
-        default:
-          // NO-OP
-          break;
+  notify: function notify(event) {
+    var _this = this;
+    return function notify(val) {
+      var i = _this.length;
+      while (i--) {
+        if (!_this[i]) {
+          continue;
+        }
+        switch (event) {
+          // only swap for save event for now, we may change this to all event types later
+          case 'save':
+            val = _this[i];
+            break;
+          default:
+            // NO-OP
+            break;
+        }
+        _this[i].emit(event, val);
       }
-      self[i].emit(event, val);
-    }
-  };
+    };
+  }
+
 };
 
 /*!
@@ -9904,16 +10115,16 @@ function EmbeddedDocument(obj, parentArr, skipId, fields, index) {
 
   Document.call(this, obj, fields, skipId);
 
-  var self = this;
+  var _this = this;
   this.on('isNew', function(val) {
-    self.isNew = val;
+    _this.isNew = val;
   });
 }
 
 /*!
  * Inherit from Document
  */
-EmbeddedDocument.prototype = Object.create( Document.prototype );
+EmbeddedDocument.prototype = Object.create(Document.prototype);
 EmbeddedDocument.prototype.constructor = EmbeddedDocument;
 
 /**
@@ -9932,7 +10143,9 @@ EmbeddedDocument.prototype.constructor = EmbeddedDocument;
 
 EmbeddedDocument.prototype.markModified = function(path) {
   this.$__.activePaths.modify(path);
-  if (!this.__parentArray) return;
+  if (!this.__parentArray) {
+    return;
+  }
 
   if (this.isNew) {
     // Mark the WHOLE parent array as modified
@@ -9964,6 +10177,28 @@ EmbeddedDocument.prototype.save = function(fn) {
   });
 };
 
+/*!
+ * Registers remove event listeners for triggering
+ * on subdocuments.
+ *
+ * @param {EmbeddedDocument} sub
+ * @api private
+ */
+
+function registerRemoveListener(sub) {
+  var owner = sub.ownerDocument();
+
+  function emitRemove() {
+    owner.removeListener('save', emitRemove);
+    owner.removeListener('remove', emitRemove);
+    sub.emit('remove', sub);
+    owner = sub = null;
+  }
+
+  owner.on('save', emitRemove);
+  owner.on('remove', emitRemove);
+}
+
 /**
  * Removes the subdocument from its parent array.
  *
@@ -9972,48 +10207,29 @@ EmbeddedDocument.prototype.save = function(fn) {
  */
 
 EmbeddedDocument.prototype.remove = function(fn) {
-  if (!this.__parentArray) return this;
+  if (!this.__parentArray) {
+    return this;
+  }
 
   var _id;
   if (!this.willRemove) {
     _id = this._doc._id;
     if (!_id) {
       throw new Error('For your own good, Mongoose does not know ' +
-                      'how to remove an EmbeddedDocument that has no _id');
+          'how to remove an EmbeddedDocument that has no _id');
     }
-    this.__parentArray.pull({ _id: _id });
+    this.__parentArray.pull({_id: _id});
     this.willRemove = true;
     registerRemoveListener(this);
   }
 
-  if (fn)
+  if (fn) {
     fn(null);
+  }
 
   return this;
 };
 
-/*!
- * Registers remove event listeners for triggering
- * on subdocuments.
- *
- * @param {EmbeddedDocument} sub
- * @api private
- */
-
-function registerRemoveListener(sub) {
-  var owner = sub.ownerDocument();
-
-  owner.on('save', emitRemove);
-  owner.on('remove', emitRemove);
-
-  function emitRemove() {
-    owner.removeListener('save', emitRemove);
-    owner.removeListener('remove', emitRemove);
-    sub.emit('remove', sub);
-    owner = sub = emitRemove = null;
-  }
-}
-
 /**
  * Override #update method of parent documents.
  * @api private
@@ -10096,9 +10312,7 @@ EmbeddedDocument.prototype.$markValid = function(path) {
 EmbeddedDocument.prototype.$isValid = function(path) {
   var index = this.__index;
   if (typeof index !== 'undefined') {
-
-    return !this.__parent.$__.validationError ||
-      !this.__parent.$__.validationError.errors[path];
+    return !this.__parent.$__.validationError || !this.__parent.$__.validationError.errors[path];
   }
 
   return true;
@@ -10116,13 +10330,16 @@ EmbeddedDocument.prototype.ownerDocument = function() {
   }
 
   var parent = this.__parent;
-  if (!parent) return this;
+  if (!parent) {
+    return this;
+  }
 
   while (parent.__parent) {
     parent = parent.__parent;
   }
 
-  return this.$__.ownerDocument = parent;
+  this.$__.ownerDocument = parent;
+  return this.$__.ownerDocument;
 };
 
 /**
@@ -10137,8 +10354,10 @@ EmbeddedDocument.prototype.ownerDocument = function() {
 
 EmbeddedDocument.prototype.$__fullPath = function(path) {
   if (!this.$__.fullPath) {
-    var parent = this;
-    if (!parent.__parent) return path;
+    var parent = this; // eslint-disable-line consistent-this
+    if (!parent.__parent) {
+      return path;
+    }
 
     var paths = [];
     while (parent.__parent) {
@@ -10155,8 +10374,8 @@ EmbeddedDocument.prototype.$__fullPath = function(path) {
   }
 
   return path
-    ? this.$__.fullPath + '.' + path
-    : this.$__.fullPath;
+      ? this.$__.fullPath + '.' + path
+      : this.$__.fullPath;
 };
 
 /**
@@ -10302,8 +10521,8 @@ Subdocument.prototype.ownerDocument = function() {
   while (parent.$parent) {
     parent = parent.$parent;
   }
-
-  return this.$__.ownerDocument = parent;
+  this.$__.ownerDocument = parent;
+  return this.$__.ownerDocument;
 };
 
 /**
@@ -10331,15 +10550,15 @@ Subdocument.prototype.remove = function(callback) {
 function registerRemoveListener(sub) {
   var owner = sub.ownerDocument();
 
-  owner.on('save', emitRemove);
-  owner.on('remove', emitRemove);
-
   function emitRemove() {
     owner.removeListener('save', emitRemove);
     owner.removeListener('remove', emitRemove);
     sub.emit('remove', sub);
-    owner = sub = emitRemove = null;
+    owner = sub = null;
   }
+
+  owner.on('save', emitRemove);
+  owner.on('remove', emitRemove);
 }
 
 },{"../document":5,"../promise_provider":25}],48:[function(require,module,exports){
@@ -10367,9 +10586,15 @@ var Document;
 
 exports.toCollectionName = function(name, options) {
   options = options || {};
-  if ('system.profile' === name) return name;
-  if ('system.indexes' === name) return name;
-  if (options.pluralization === false) return name;
+  if (name === 'system.profile') {
+    return name;
+  }
+  if (name === 'system.indexes') {
+    return name;
+  }
+  if (options.pluralization === false) {
+    return name;
+  }
   return pluralize(name.toLowerCase());
 };
 
@@ -10459,7 +10684,9 @@ function pluralize(str) {
     found = rules.filter(function(rule) {
       return str.match(rule[0]);
     });
-    if (found[0]) return str.replace(found[0][0], found[0][1]);
+    if (found[0]) {
+      return str.replace(found[0][0], found[0][1]);
+    }
   }
   return str;
 }
@@ -10476,29 +10703,36 @@ function pluralize(str) {
  */
 
 exports.deepEqual = function deepEqual(a, b) {
-  if (a === b) return true;
+  if (a === b) {
+    return true;
+  }
 
-  if (a instanceof Date && b instanceof Date)
+  if (a instanceof Date && b instanceof Date) {
     return a.getTime() === b.getTime();
+  }
 
   if (a instanceof ObjectId && b instanceof ObjectId) {
     return a.toString() === b.toString();
   }
 
   if (a instanceof RegExp && b instanceof RegExp) {
-    return a.source == b.source &&
-           a.ignoreCase == b.ignoreCase &&
-           a.multiline == b.multiline &&
-           a.global == b.global;
+    return a.source === b.source &&
+        a.ignoreCase === b.ignoreCase &&
+        a.multiline === b.multiline &&
+        a.global === b.global;
   }
 
-  if (typeof a !== 'object' && typeof b !== 'object')
+  if (typeof a !== 'object' && typeof b !== 'object') {
     return a == b;
+  }
 
-  if (a === null || b === null || a === undefined || b === undefined)
+  if (a === null || b === null || a === undefined || b === undefined) {
     return false;
+  }
 
-  if (a.prototype !== b.prototype) return false;
+  if (a.prototype !== b.prototype) {
+    return false;
+  }
 
   // Handle MongooseNumbers
   if (a instanceof Number && b instanceof Number) {
@@ -10509,37 +10743,46 @@ exports.deepEqual = function deepEqual(a, b) {
     return exports.buffer.areEqual(a, b);
   }
 
-  if (isMongooseObject(a)) a = a.toObject();
-  if (isMongooseObject(b)) b = b.toObject();
+  if (isMongooseObject(a)) {
+    a = a.toObject();
+  }
+  if (isMongooseObject(b)) {
+    b = b.toObject();
+  }
 
   try {
     var ka = Object.keys(a),
         kb = Object.keys(b),
         key, i;
-  } catch (e) {//happens when one is a string literal and the other isn't
+  } catch (e) {
+    // happens when one is a string literal and the other isn't
     return false;
   }
 
   // having the same number of owned properties (keys incorporates
   // hasOwnProperty)
-  if (ka.length != kb.length)
+  if (ka.length !== kb.length) {
     return false;
+  }
 
-  //the same set of keys (although not necessarily the same order),
+  // the same set of keys (although not necessarily the same order),
   ka.sort();
   kb.sort();
 
-  //~~~cheap key test
+  // ~~~cheap key test
   for (i = ka.length - 1; i >= 0; i--) {
-    if (ka[i] != kb[i])
+    if (ka[i] !== kb[i]) {
       return false;
+    }
   }
 
-  //equivalent values for every corresponding key, and
-  //~~~possibly expensive deep test
+  // equivalent values for every corresponding key, and
+  // ~~~possibly expensive deep test
   for (i = ka.length - 1; i >= 0; i--) {
     key = ka[i];
-    if (!deepEqual(a[key], b[key])) return false;
+    if (!deepEqual(a[key], b[key])) {
+      return false;
+    }
   }
 
   return true;
@@ -10559,18 +10802,19 @@ exports.deepEqual = function deepEqual(a, b) {
  */
 
 exports.clone = function clone(obj, options) {
-  if (obj === undefined || obj === null)
+  if (obj === undefined || obj === null) {
     return obj;
+  }
 
-  if (Array.isArray(obj))
+  if (Array.isArray(obj)) {
     return cloneArray(obj, options);
+  }
 
   if (isMongooseObject(obj)) {
-    if (options && options.json && 'function' === typeof obj.toJSON) {
+    if (options && options.json && typeof obj.toJSON === 'function') {
       return obj.toJSON(options);
-    } else {
-      return obj.toObject(options);
     }
+    return obj.toObject(options);
   }
 
   if (obj.constructor) {
@@ -10587,16 +10831,18 @@ exports.clone = function clone(obj, options) {
     }
   }
 
-  if (obj instanceof ObjectId)
+  if (obj instanceof ObjectId) {
     return new ObjectId(obj.id);
+  }
 
   if (!obj.constructor && exports.isObject(obj)) {
     // object created with Object.create(null)
     return cloneObject(obj, options);
   }
 
-  if (obj.valueOf)
+  if (obj.valueOf) {
     return obj.valueOf();
+  }
 };
 var clone = exports.clone;
 
@@ -10618,7 +10864,7 @@ function cloneObject(obj, options) {
     for (k in obj) {
       val = clone(obj[k], options);
 
-      if (!minimize || ('undefined' !== typeof val)) {
+      if (!minimize || (typeof val !== 'undefined')) {
         hasKeys || (hasKeys = true);
         ret[k] = val;
       }
@@ -10633,22 +10879,25 @@ function cloneObject(obj, options) {
       k = keys[i];
       val = clone(obj[k], options);
 
-      if (!minimize || ('undefined' !== typeof val)) {
-        if (!hasKeys) hasKeys = true;
+      if (!minimize || (typeof val !== 'undefined')) {
+        if (!hasKeys) {
+          hasKeys = true;
+        }
         ret[k] = val;
       }
     }
   }
 
   return minimize
-    ? hasKeys && ret
-    : ret;
+      ? hasKeys && ret
+      : ret;
 }
 
 function cloneArray(arr, options) {
   var ret = [];
-  for (var i = 0, l = arr.length; i < l; i++)
+  for (var i = 0, l = arr.length; i < l; i++) {
     ret.push(clone(arr[i], options));
+  }
   return ret;
 }
 
@@ -10703,7 +10952,7 @@ exports.merge = function merge(to, from) {
 
   while (i--) {
     key = keys[i];
-    if ('undefined' === typeof to[key]) {
+    if (typeof to[key] === 'undefined') {
       to[key] = from[key];
     } else if (exports.isObject(from[key])) {
       merge(to[key], from[key]);
@@ -10772,7 +11021,7 @@ exports.isObject = function(arg) {
   if (Buffer.isBuffer(arg)) {
     return true;
   }
-  return '[object Object]' == toString.call(arg);
+  return toString.call(arg) === '[object Object]';
 };
 
 /*!
@@ -10794,7 +11043,9 @@ exports.args = sliced;
  */
 
 exports.tick = function tick(callback) {
-  if ('function' !== typeof callback) return;
+  if (typeof callback !== 'function') {
+    return;
+  }
   return function() {
     try {
       callback.apply(this, arguments);
@@ -10823,8 +11074,8 @@ exports.isMongooseObject = function(v) {
   MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
 
   return v instanceof Document ||
-         (v && v.isMongooseArray) ||
-         (v && v.isMongooseBuffer);
+      (v && v.isMongooseArray) ||
+      (v && v.isMongooseBuffer);
 };
 var isMongooseObject = exports.isMongooseObject;
 
@@ -10836,11 +11087,15 @@ var isMongooseObject = exports.isMongooseObject;
  */
 
 exports.expires = function expires(object) {
-  if (!(object && 'Object' == object.constructor.name)) return;
-  if (!('expires' in object)) return;
+  if (!(object && object.constructor.name === 'Object')) {
+    return;
+  }
+  if (!('expires' in object)) {
+    return;
+  }
 
   var when;
-  if ('string' != typeof object.expires) {
+  if (typeof object.expires !== 'string') {
     when = object.expires;
   } else {
     when = Math.round(ms(object.expires) / 1000);
@@ -10881,7 +11136,7 @@ exports.populate = function populate(path, select, model, match, options, subPop
   // an array, string, or object literal).
 
   // might have passed an object specifying all arguments
-  if (1 === arguments.length) {
+  if (arguments.length === 1) {
     if (path instanceof PopulateOptions) {
       return [path];
     }
@@ -10900,13 +11155,13 @@ exports.populate = function populate(path, select, model, match, options, subPop
       subPopulate = path.populate;
       path = path.path;
     }
-  } else if ('string' !== typeof model && 'function' !== typeof model) {
+  } else if (typeof model !== 'string' && typeof model !== 'function') {
     options = match;
     match = model;
     model = undefined;
   }
 
-  if ('string' != typeof path) {
+  if (typeof path !== 'string') {
     throw new TypeError('utils.populate: invalid path. Expected string. Got typeof `' + typeof path + '`');
   }
 
@@ -10992,7 +11247,7 @@ exports.object.hasOwnProperty = function(obj, prop) {
  */
 
 exports.isNullOrUndefined = function(val) {
-  return null == val;
+  return val === null || val === void 0;
 };
 
 /*!
@@ -11075,11 +11330,19 @@ exports.array.unique = function(arr) {
 
 exports.buffer = {};
 exports.buffer.areEqual = function(a, b) {
-  if (!Buffer.isBuffer(a)) return false;
-  if (!Buffer.isBuffer(b)) return false;
-  if (a.length !== b.length) return false;
+  if (!Buffer.isBuffer(a)) {
+    return false;
+  }
+  if (!Buffer.isBuffer(b)) {
+    return false;
+  }
+  if (a.length !== b.length) {
+    return false;
+  }
   for (var i = 0, len = a.length; i < len; ++i) {
-    if (a[i] !== b[i]) return false;
+    if (a[i] !== b[i]) {
+      return false;
+    }
   }
   return true;
 };
@@ -11112,17 +11375,17 @@ exports.mergeClone = function(to, from) {
 
   while (i--) {
     key = keys[i];
-    if ('undefined' === typeof to[key]) {
+    if (typeof to[key] === 'undefined') {
       // make sure to retain key order here because of a bug handling the $each
       // operator in mongodb 2.4.4
-      to[key] = exports.clone(from[key], { retainKeyOrder : 1});
+      to[key] = exports.clone(from[key], {retainKeyOrder: 1});
     } else {
       if (exports.isObject(from[key])) {
         exports.mergeClone(to[key], from[key]);
       } else {
         // make sure to retain key order here because of a bug handling the
         // $each operator in mongodb 2.4.4
-        to[key] = exports.clone(from[key], { retainKeyOrder : 1});
+        to[key] = exports.clone(from[key], {retainKeyOrder: 1});
       }
     }
   }
@@ -11143,7 +11406,7 @@ exports.each = function(arr, fn) {
 };
 
 }).call(this,require("g5I+bs"),require("buffer").Buffer)
-},{"./document":5,"./types":45,"./types/objectid":46,"buffer":71,"g5I+bs":92,"mpath":80,"ms":91,"regexp-clone":93,"sliced":94}],49:[function(require,module,exports){
+},{"./document":5,"./types":45,"./types/objectid":46,"buffer":71,"g5I+bs":94,"mpath":80,"ms":93,"regexp-clone":95,"sliced":96}],49:[function(require,module,exports){
 
 /**
  * VirtualType constructor
@@ -11610,8 +11873,8 @@ var objectKeys = Object.keys || function (obj) {
   return keys;
 };
 
-},{"util/":97}],51:[function(require,module,exports){
-(function (process){
+},{"util/":98}],51:[function(require,module,exports){
+(function (process,global){
 /*!
  * async
  * https://github.com/caolan/async
@@ -11619,18 +11882,32 @@ var objectKeys = Object.keys || function (obj) {
  * Copyright 2010-2014 Caolan McMahon
  * Released under the MIT license
  */
-/*jshint onevar: false, indent:4 */
-/*global setImmediate: false, setTimeout: false, console: false */
 (function () {
 
     var async = {};
+    function noop() {}
+    function identity(v) {
+        return v;
+    }
+    function toBool(v) {
+        return !!v;
+    }
+    function notId(v) {
+        return !v;
+    }
 
     // global on the server, window in the browser
-    var root, previous_async;
+    var previous_async;
+
+    // Establish the root object, `window` (`self`) in the browser, `global`
+    // on the server, or `this` in some virtual machines. We use `self`
+    // instead of `window` for `WebWorker` support.
+    var root = typeof self === 'object' && self.self === self && self ||
+            typeof global === 'object' && global.global === global && global ||
+            this;
 
-    root = this;
     if (root != null) {
-      previous_async = root.async;
+        previous_async = root.async;
     }
 
     async.noConflict = function () {
@@ -11639,12 +11916,19 @@ var objectKeys = Object.keys || function (obj) {
     };
 
     function only_once(fn) {
-        var called = false;
         return function() {
-            if (called) throw new Error("Callback was already called.");
-            called = true;
-            fn.apply(root, arguments);
-        }
+            if (fn === null) throw new Error("Callback was already called.");
+            fn.apply(this, arguments);
+            fn = null;
+        };
+    }
+
+    function _once(fn) {
+        return function() {
+            if (fn === null) return;
+            fn.apply(this, arguments);
+            fn = null;
+        };
     }
 
     //// cross-browser compatiblity functions ////
@@ -11655,40 +11939,66 @@ var objectKeys = Object.keys || function (obj) {
         return _toString.call(obj) === '[object Array]';
     };
 
-    var _each = function (arr, iterator) {
-        if (arr.forEach) {
-            return arr.forEach(iterator);
-        }
-        for (var i = 0; i < arr.length; i += 1) {
-            iterator(arr[i], i, arr);
-        }
+    // Ported from underscore.js isObject
+    var _isObject = function(obj) {
+        var type = typeof obj;
+        return type === 'function' || type === 'object' && !!obj;
     };
 
-    var _map = function (arr, iterator) {
-        if (arr.map) {
-            return arr.map(iterator);
+    function _isArrayLike(arr) {
+        return _isArray(arr) || (
+            // has a positive integer length property
+            typeof arr.length === "number" &&
+            arr.length >= 0 &&
+            arr.length % 1 === 0
+        );
+    }
+
+    function _arrayEach(arr, iterator) {
+        var index = -1,
+            length = arr.length;
+
+        while (++index < length) {
+            iterator(arr[index], index, arr);
         }
-        var results = [];
-        _each(arr, function (x, i, a) {
-            results.push(iterator(x, i, a));
-        });
-        return results;
-    };
+    }
+
+    function _map(arr, iterator) {
+        var index = -1,
+            length = arr.length,
+            result = Array(length);
 
-    var _reduce = function (arr, iterator, memo) {
-        if (arr.reduce) {
-            return arr.reduce(iterator, memo);
+        while (++index < length) {
+            result[index] = iterator(arr[index], index, arr);
         }
-        _each(arr, function (x, i, a) {
+        return result;
+    }
+
+    function _range(count) {
+        return _map(Array(count), function (v, i) { return i; });
+    }
+
+    function _reduce(arr, iterator, memo) {
+        _arrayEach(arr, function (x, i, a) {
             memo = iterator(memo, x, i, a);
         });
         return memo;
-    };
+    }
+
+    function _forEachOf(object, iterator) {
+        _arrayEach(_keys(object), function (key) {
+            iterator(object[key], key);
+        });
+    }
 
-    var _keys = function (obj) {
-        if (Object.keys) {
-            return Object.keys(obj);
+    function _indexOf(arr, item) {
+        for (var i = 0; i < arr.length; i++) {
+            if (arr[i] === item) return i;
         }
+        return -1;
+    }
+
+    var _keys = Object.keys || function (obj) {
         var keys = [];
         for (var k in obj) {
             if (obj.hasOwnProperty(k)) {
@@ -11698,191 +12008,247 @@ var objectKeys = Object.keys || function (obj) {
         return keys;
     };
 
-    //// exported async module functions ////
-
-    //// nextTick implementation with browser-compatible fallback ////
-    if (typeof process === 'undefined' || !(process.nextTick)) {
-        if (typeof setImmediate === 'function') {
-            async.nextTick = function (fn) {
-                // not a direct alias for IE10 compatibility
-                setImmediate(fn);
+    function _keyIterator(coll) {
+        var i = -1;
+        var len;
+        var keys;
+        if (_isArrayLike(coll)) {
+            len = coll.length;
+            return function next() {
+                i++;
+                return i < len ? i : null;
             };
-            async.setImmediate = async.nextTick;
-        }
-        else {
-            async.nextTick = function (fn) {
-                setTimeout(fn, 0);
+        } else {
+            keys = _keys(coll);
+            len = keys.length;
+            return function next() {
+                i++;
+                return i < len ? keys[i] : null;
             };
-            async.setImmediate = async.nextTick;
         }
     }
-    else {
+
+    // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html)
+    // This accumulates the arguments passed into an array, after a given index.
+    // From underscore.js (https://github.com/jashkenas/underscore/pull/2140).
+    function _restParam(func, startIndex) {
+        startIndex = startIndex == null ? func.length - 1 : +startIndex;
+        return function() {
+            var length = Math.max(arguments.length - startIndex, 0);
+            var rest = Array(length);
+            for (var index = 0; index < length; index++) {
+                rest[index] = arguments[index + startIndex];
+            }
+            switch (startIndex) {
+                case 0: return func.call(this, rest);
+                case 1: return func.call(this, arguments[0], rest);
+            }
+            // Currently unused but handle cases outside of the switch statement:
+            // var args = Array(startIndex + 1);
+            // for (index = 0; index < startIndex; index++) {
+            //     args[index] = arguments[index];
+            // }
+            // args[startIndex] = rest;
+            // return func.apply(this, args);
+        };
+    }
+
+    function _withoutIndex(iterator) {
+        return function (value, index, callback) {
+            return iterator(value, callback);
+        };
+    }
+
+    //// exported async module functions ////
+
+    //// nextTick implementation with browser-compatible fallback ////
+
+    // capture the global reference to guard against fakeTimer mocks
+    var _setImmediate = typeof setImmediate === 'function' && setImmediate;
+
+    var _delay = _setImmediate ? function(fn) {
+        // not a direct alias for IE10 compatibility
+        _setImmediate(fn);
+    } : function(fn) {
+        setTimeout(fn, 0);
+    };
+
+    if (typeof process === 'object' && typeof process.nextTick === 'function') {
         async.nextTick = process.nextTick;
-        if (typeof setImmediate !== 'undefined') {
-            async.setImmediate = function (fn) {
-              // not a direct alias for IE10 compatibility
-              setImmediate(fn);
-            };
-        }
-        else {
-            async.setImmediate = async.nextTick;
-        }
+    } else {
+        async.nextTick = _delay;
     }
+    async.setImmediate = _setImmediate ? _delay : async.nextTick;
+
 
+    async.forEach =
     async.each = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
+        return async.eachOf(arr, _withoutIndex(iterator), callback);
+    };
+
+    async.forEachSeries =
+    async.eachSeries = function (arr, iterator, callback) {
+        return async.eachOfSeries(arr, _withoutIndex(iterator), callback);
+    };
+
+
+    async.forEachLimit =
+    async.eachLimit = function (arr, limit, iterator, callback) {
+        return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);
+    };
+
+    async.forEachOf =
+    async.eachOf = function (object, iterator, callback) {
+        callback = _once(callback || noop);
+        object = object || [];
+
+        var iter = _keyIterator(object);
+        var key, completed = 0;
+
+        while ((key = iter()) != null) {
+            completed += 1;
+            iterator(object[key], key, only_once(done));
         }
-        var completed = 0;
-        _each(arr, function (x) {
-            iterator(x, only_once(done) );
-        });
+
+        if (completed === 0) callback(null);
+
         function done(err) {
-          if (err) {
-              callback(err);
-              callback = function () {};
-          }
-          else {
-              completed += 1;
-              if (completed >= arr.length) {
-                  callback();
-              }
-          }
+            completed--;
+            if (err) {
+                callback(err);
+            }
+            // Check key is null in case iterator isn't exhausted
+            // and done resolved synchronously.
+            else if (key === null && completed <= 0) {
+                callback(null);
+            }
         }
     };
-    async.forEach = async.each;
 
-    async.eachSeries = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
-        }
-        var completed = 0;
-        var iterate = function () {
-            iterator(arr[completed], function (err) {
+    async.forEachOfSeries =
+    async.eachOfSeries = function (obj, iterator, callback) {
+        callback = _once(callback || noop);
+        obj = obj || [];
+        var nextKey = _keyIterator(obj);
+        var key = nextKey();
+        function iterate() {
+            var sync = true;
+            if (key === null) {
+                return callback(null);
+            }
+            iterator(obj[key], key, only_once(function (err) {
                 if (err) {
                     callback(err);
-                    callback = function () {};
                 }
                 else {
-                    completed += 1;
-                    if (completed >= arr.length) {
-                        callback();
-                    }
-                    else {
-                        iterate();
+                    key = nextKey();
+                    if (key === null) {
+                        return callback(null);
+                    } else {
+                        if (sync) {
+                            async.setImmediate(iterate);
+                        } else {
+                            iterate();
+                        }
                     }
                 }
-            });
-        };
+            }));
+            sync = false;
+        }
         iterate();
     };
-    async.forEachSeries = async.eachSeries;
 
-    async.eachLimit = function (arr, limit, iterator, callback) {
-        var fn = _eachLimit(limit);
-        fn.apply(null, [arr, iterator, callback]);
+
+
+    async.forEachOfLimit =
+    async.eachOfLimit = function (obj, limit, iterator, callback) {
+        _eachOfLimit(limit)(obj, iterator, callback);
     };
-    async.forEachLimit = async.eachLimit;
 
-    var _eachLimit = function (limit) {
+    function _eachOfLimit(limit) {
 
-        return function (arr, iterator, callback) {
-            callback = callback || function () {};
-            if (!arr.length || limit <= 0) {
-                return callback();
+        return function (obj, iterator, callback) {
+            callback = _once(callback || noop);
+            obj = obj || [];
+            var nextKey = _keyIterator(obj);
+            if (limit <= 0) {
+                return callback(null);
             }
-            var completed = 0;
-            var started = 0;
+            var done = false;
             var running = 0;
+            var errored = false;
 
             (function replenish () {
-                if (completed >= arr.length) {
-                    return callback();
+                if (done && running <= 0) {
+                    return callback(null);
                 }
 
-                while (running < limit && started < arr.length) {
-                    started += 1;
+                while (running < limit && !errored) {
+                    var key = nextKey();
+                    if (key === null) {
+                        done = true;
+                        if (running <= 0) {
+                            callback(null);
+                        }
+                        return;
+                    }
                     running += 1;
-                    iterator(arr[started - 1], function (err) {
+                    iterator(obj[key], key, only_once(function (err) {
+                        running -= 1;
                         if (err) {
                             callback(err);
-                            callback = function () {};
+                            errored = true;
                         }
                         else {
-                            completed += 1;
-                            running -= 1;
-                            if (completed >= arr.length) {
-                                callback();
-                            }
-                            else {
-                                replenish();
-                            }
+                            replenish();
                         }
-                    });
+                    }));
                 }
             })();
         };
-    };
+    }
 
 
-    var doParallel = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.each].concat(args));
+    function doParallel(fn) {
+        return function (obj, iterator, callback) {
+            return fn(async.eachOf, obj, iterator, callback);
         };
-    };
-    var doParallelLimit = function(limit, fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [_eachLimit(limit)].concat(args));
+    }
+    function doParallelLimit(fn) {
+        return function (obj, limit, iterator, callback) {
+            return fn(_eachOfLimit(limit), obj, iterator, callback);
         };
-    };
-    var doSeries = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.eachSeries].concat(args));
+    }
+    function doSeries(fn) {
+        return function (obj, iterator, callback) {
+            return fn(async.eachOfSeries, obj, iterator, callback);
         };
-    };
-
+    }
 
-    var _asyncMap = function (eachfn, arr, iterator, callback) {
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        if (!callback) {
-            eachfn(arr, function (x, callback) {
-                iterator(x.value, function (err) {
-                    callback(err);
-                });
-            });
-        } else {
-            var results = [];
-            eachfn(arr, function (x, callback) {
-                iterator(x.value, function (err, v) {
-                    results[x.index] = v;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
+    function _asyncMap(eachfn, arr, iterator, callback) {
+        callback = _once(callback || noop);
+        arr = arr || [];
+        var results = _isArrayLike(arr) ? [] : {};
+        eachfn(arr, function (value, index, callback) {
+            iterator(value, function (err, v) {
+                results[index] = v;
+                callback(err);
             });
-        }
-    };
+        }, function (err) {
+            callback(err, results);
+        });
+    }
+
     async.map = doParallel(_asyncMap);
     async.mapSeries = doSeries(_asyncMap);
-    async.mapLimit = function (arr, limit, iterator, callback) {
-        return _mapLimit(limit)(arr, iterator, callback);
-    };
-
-    var _mapLimit = function(limit) {
-        return doParallelLimit(limit, _asyncMap);
-    };
+    async.mapLimit = doParallelLimit(_asyncMap);
 
     // reduce only has a series version, as doing reduce in parallel won't
     // work in many situations.
+    async.inject =
+    async.foldl =
     async.reduce = function (arr, memo, iterator, callback) {
-        async.eachSeries(arr, function (x, callback) {
+        async.eachOfSeries(arr, function (x, i, callback) {
             iterator(memo, x, function (err, v) {
                 memo = v;
                 callback(err);
@@ -11891,118 +12257,106 @@ var objectKeys = Object.keys || function (obj) {
             callback(err, memo);
         });
     };
-    // inject alias
-    async.inject = async.reduce;
-    // foldl alias
-    async.foldl = async.reduce;
 
+    async.foldr =
     async.reduceRight = function (arr, memo, iterator, callback) {
-        var reversed = _map(arr, function (x) {
-            return x;
-        }).reverse();
+        var reversed = _map(arr, identity).reverse();
         async.reduce(reversed, memo, iterator, callback);
     };
-    // foldr alias
-    async.foldr = async.reduceRight;
 
-    var _filter = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
+    async.transform = function (arr, memo, iterator, callback) {
+        if (arguments.length === 3) {
+            callback = iterator;
+            iterator = memo;
+            memo = _isArray(arr) ? [] : {};
+        }
+
+        async.eachOf(arr, function(v, k, cb) {
+            iterator(memo, v, k, cb);
+        }, function(err) {
+            callback(err, memo);
         });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
+    };
+
+    function _filter(eachfn, arr, iterator, callback) {
+        var results = [];
+        eachfn(arr, function (x, index, callback) {
+            iterator(x, function (v) {
                 if (v) {
-                    results.push(x);
+                    results.push({index: index, value: x});
                 }
                 callback();
             });
-        }, function (err) {
+        }, function () {
             callback(_map(results.sort(function (a, b) {
                 return a.index - b.index;
             }), function (x) {
                 return x.value;
             }));
         });
-    };
+    }
+
+    async.select =
     async.filter = doParallel(_filter);
+
+    async.selectLimit =
+    async.filterLimit = doParallelLimit(_filter);
+
+    async.selectSeries =
     async.filterSeries = doSeries(_filter);
-    // select alias
-    async.select = async.filter;
-    async.selectSeries = async.filterSeries;
 
-    var _reject = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
-                if (!v) {
-                    results.push(x);
-                }
-                callback();
+    function _reject(eachfn, arr, iterator, callback) {
+        _filter(eachfn, arr, function(value, cb) {
+            iterator(value, function(v) {
+                cb(!v);
             });
-        }, function (err) {
-            callback(_map(results.sort(function (a, b) {
-                return a.index - b.index;
-            }), function (x) {
-                return x.value;
-            }));
-        });
-    };
+        }, callback);
+    }
     async.reject = doParallel(_reject);
+    async.rejectLimit = doParallelLimit(_reject);
     async.rejectSeries = doSeries(_reject);
 
-    var _detect = function (eachfn, arr, iterator, main_callback) {
-        eachfn(arr, function (x, callback) {
-            iterator(x, function (result) {
-                if (result) {
-                    main_callback(x);
-                    main_callback = function () {};
-                }
-                else {
+    function _createTester(eachfn, check, getResult) {
+        return function(arr, limit, iterator, cb) {
+            function done() {
+                if (cb) cb(getResult(false, void 0));
+            }
+            function iteratee(x, _, callback) {
+                if (!cb) return callback();
+                iterator(x, function (v) {
+                    if (cb && check(v)) {
+                        cb(getResult(true, x));
+                        cb = iterator = false;
+                    }
                     callback();
-                }
-            });
-        }, function (err) {
-            main_callback();
-        });
-    };
-    async.detect = doParallel(_detect);
-    async.detectSeries = doSeries(_detect);
+                });
+            }
+            if (arguments.length > 3) {
+                eachfn(arr, limit, iteratee, done);
+            } else {
+                cb = iterator;
+                iterator = limit;
+                eachfn(arr, iteratee, done);
+            }
+        };
+    }
 
-    async.some = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (v) {
-                    main_callback(true);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(false);
-        });
-    };
-    // any alias
-    async.any = async.some;
+    async.any =
+    async.some = _createTester(async.eachOf, toBool, identity);
 
-    async.every = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (!v) {
-                    main_callback(false);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(true);
-        });
-    };
-    // all alias
-    async.all = async.every;
+    async.someLimit = _createTester(async.eachOfLimit, toBool, identity);
+
+    async.all =
+    async.every = _createTester(async.eachOf, notId, notId);
+
+    async.everyLimit = _createTester(async.eachOfLimit, notId, notId);
+
+    function _findGetResult(v, x) {
+        return x;
+    }
+    async.detect = _createTester(async.eachOf, identity, _findGetResult);
+    async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);
+    async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult);
 
     async.sortBy = function (arr, iterator, callback) {
         async.map(arr, function (x, callback) {
@@ -12019,147 +12373,206 @@ var objectKeys = Object.keys || function (obj) {
                 return callback(err);
             }
             else {
-                var fn = function (left, right) {
-                    var a = left.criteria, b = right.criteria;
-                    return a < b ? -1 : a > b ? 1 : 0;
-                };
-                callback(null, _map(results.sort(fn), function (x) {
+                callback(null, _map(results.sort(comparator), function (x) {
                     return x.value;
                 }));
             }
+
         });
+
+        function comparator(left, right) {
+            var a = left.criteria, b = right.criteria;
+            return a < b ? -1 : a > b ? 1 : 0;
+        }
     };
 
-    async.auto = function (tasks, callback) {
-        callback = callback || function () {};
+    async.auto = function (tasks, concurrency, callback) {
+        if (typeof arguments[1] === 'function') {
+            // concurrency is optional, shift the args.
+            callback = concurrency;
+            concurrency = null;
+        }
+        callback = _once(callback || noop);
         var keys = _keys(tasks);
-        var remainingTasks = keys.length
+        var remainingTasks = keys.length;
         if (!remainingTasks) {
-            return callback();
+            return callback(null);
+        }
+        if (!concurrency) {
+            concurrency = remainingTasks;
         }
 
         var results = {};
+        var runningTasks = 0;
+
+        var hasError = false;
 
         var listeners = [];
-        var addListener = function (fn) {
+        function addListener(fn) {
             listeners.unshift(fn);
-        };
-        var removeListener = function (fn) {
-            for (var i = 0; i < listeners.length; i += 1) {
-                if (listeners[i] === fn) {
-                    listeners.splice(i, 1);
-                    return;
-                }
-            }
-        };
-        var taskComplete = function () {
-            remainingTasks--
-            _each(listeners.slice(0), function (fn) {
+        }
+        function removeListener(fn) {
+            var idx = _indexOf(listeners, fn);
+            if (idx >= 0) listeners.splice(idx, 1);
+        }
+        function taskComplete() {
+            remainingTasks--;
+            _arrayEach(listeners.slice(0), function (fn) {
                 fn();
             });
-        };
+        }
 
         addListener(function () {
             if (!remainingTasks) {
-                var theCallback = callback;
-                // prevent final callback from calling itself if it errors
-                callback = function () {};
-
-                theCallback(null, results);
+                callback(null, results);
             }
         });
 
-        _each(keys, function (k) {
+        _arrayEach(keys, function (k) {
+            if (hasError) return;
             var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
-            var taskCallback = function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
+            var taskCallback = _restParam(function(err, args) {
+                runningTasks--;
                 if (args.length <= 1) {
                     args = args[0];
                 }
                 if (err) {
                     var safeResults = {};
-                    _each(_keys(results), function(rkey) {
-                        safeResults[rkey] = results[rkey];
+                    _forEachOf(results, function(val, rkey) {
+                        safeResults[rkey] = val;
                     });
                     safeResults[k] = args;
+                    hasError = true;
+
                     callback(err, safeResults);
-                    // stop subsequent errors hitting callback multiple times
-                    callback = function () {};
                 }
                 else {
                     results[k] = args;
                     async.setImmediate(taskComplete);
                 }
-            };
-            var requires = task.slice(0, Math.abs(task.length - 1)) || [];
-            var ready = function () {
-                return _reduce(requires, function (a, x) {
+            });
+            var requires = task.slice(0, task.length - 1);
+            // prevent dead-locks
+            var len = requires.length;
+            var dep;
+            while (len--) {
+                if (!(dep = tasks[requires[len]])) {
+                    throw new Error('Has nonexistent dependency in ' + requires.join(', '));
+                }
+                if (_isArray(dep) && _indexOf(dep, k) >= 0) {
+                    throw new Error('Has cyclic dependencies');
+                }
+            }
+            function ready() {
+                return runningTasks < concurrency && _reduce(requires, function (a, x) {
                     return (a && results.hasOwnProperty(x));
                 }, true) && !results.hasOwnProperty(k);
-            };
+            }
             if (ready()) {
+                runningTasks++;
                 task[task.length - 1](taskCallback, results);
             }
             else {
-                var listener = function () {
-                    if (ready()) {
-                        removeListener(listener);
-                        task[task.length - 1](taskCallback, results);
-                    }
-                };
                 addListener(listener);
             }
+            function listener() {
+                if (ready()) {
+                    runningTasks++;
+                    removeListener(listener);
+                    task[task.length - 1](taskCallback, results);
+                }
+            }
         });
     };
 
+
+
     async.retry = function(times, task, callback) {
         var DEFAULT_TIMES = 5;
+        var DEFAULT_INTERVAL = 0;
+
         var attempts = [];
-        // Use defaults if times not passed
-        if (typeof times === 'function') {
+
+        var opts = {
+            times: DEFAULT_TIMES,
+            interval: DEFAULT_INTERVAL
+        };
+
+        function parseTimes(acc, t){
+            if(typeof t === 'number'){
+                acc.times = parseInt(t, 10) || DEFAULT_TIMES;
+            } else if(typeof t === 'object'){
+                acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;
+                acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;
+            } else {
+                throw new Error('Unsupported argument type for \'times\': ' + typeof t);
+            }
+        }
+
+        var length = arguments.length;
+        if (length < 1 || length > 3) {
+            throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');
+        } else if (length <= 2 && typeof times === 'function') {
             callback = task;
             task = times;
-            times = DEFAULT_TIMES;
         }
-        // Make sure times is a number
-        times = parseInt(times, 10) || DEFAULT_TIMES;
-        var wrappedTask = function(wrappedCallback, wrappedResults) {
-            var retryAttempt = function(task, finalAttempt) {
+        if (typeof times !== 'function') {
+            parseTimes(opts, times);
+        }
+        opts.callback = callback;
+        opts.task = task;
+
+        function wrappedTask(wrappedCallback, wrappedResults) {
+            function retryAttempt(task, finalAttempt) {
                 return function(seriesCallback) {
                     task(function(err, result){
                         seriesCallback(!err || finalAttempt, {err: err, result: result});
                     }, wrappedResults);
                 };
-            };
-            while (times) {
-                attempts.push(retryAttempt(task, !(times-=1)));
             }
+
+            function retryInterval(interval){
+                return function(seriesCallback){
+                    setTimeout(function(){
+                        seriesCallback(null);
+                    }, interval);
+                };
+            }
+
+            while (opts.times) {
+
+                var finalAttempt = !(opts.times-=1);
+                attempts.push(retryAttempt(opts.task, finalAttempt));
+                if(!finalAttempt && opts.interval > 0){
+                    attempts.push(retryInterval(opts.interval));
+                }
+            }
+
             async.series(attempts, function(done, data){
                 data = data[data.length - 1];
-                (wrappedCallback || callback)(data.err, data.result);
+                (wrappedCallback || opts.callback)(data.err, data.result);
             });
         }
+
         // If a callback is passed, run this as a controll flow
-        return callback ? wrappedTask() : wrappedTask
+        return opts.callback ? wrappedTask() : wrappedTask;
     };
 
     async.waterfall = function (tasks, callback) {
-        callback = callback || function () {};
+        callback = _once(callback || noop);
         if (!_isArray(tasks)) {
-          var err = new Error('First argument to waterfall must be an array of functions');
-          return callback(err);
+            var err = new Error('First argument to waterfall must be an array of functions');
+            return callback(err);
         }
         if (!tasks.length) {
             return callback();
         }
-        var wrapIterator = function (iterator) {
-            return function (err) {
+        function wrapIterator(iterator) {
+            return _restParam(function (err, args) {
                 if (err) {
-                    callback.apply(null, arguments);
-                    callback = function () {};
+                    callback.apply(null, [err].concat(args));
                 }
                 else {
-                    var args = Array.prototype.slice.call(arguments, 1);
                     var next = iterator.next();
                     if (next) {
                         args.push(wrapIterator(next));
@@ -12167,260 +12580,254 @@ var objectKeys = Object.keys || function (obj) {
                     else {
                         args.push(callback);
                     }
-                    async.setImmediate(function () {
-                        iterator.apply(null, args);
-                    });
+                    ensureAsync(iterator).apply(null, args);
                 }
-            };
-        };
+            });
+        }
         wrapIterator(async.iterator(tasks))();
     };
 
-    var _parallel = function(eachfn, tasks, callback) {
-        callback = callback || function () {};
-        if (_isArray(tasks)) {
-            eachfn.map(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
-                        }
-                        callback.call(null, err, args);
-                    });
+    function _parallel(eachfn, tasks, callback) {
+        callback = callback || noop;
+        var results = _isArrayLike(tasks) ? [] : {};
+
+        eachfn(tasks, function (task, key, callback) {
+            task(_restParam(function (err, args) {
+                if (args.length <= 1) {
+                    args = args[0];
                 }
-            }, callback);
-        }
-        else {
-            var results = {};
-            eachfn.each(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
+                results[key] = args;
+                callback(err);
+            }));
+        }, function (err) {
+            callback(err, results);
+        });
+    }
 
     async.parallel = function (tasks, callback) {
-        _parallel({ map: async.map, each: async.each }, tasks, callback);
+        _parallel(async.eachOf, tasks, callback);
     };
 
     async.parallelLimit = function(tasks, limit, callback) {
-        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
+        _parallel(_eachOfLimit(limit), tasks, callback);
     };
 
-    async.series = function (tasks, callback) {
-        callback = callback || function () {};
-        if (_isArray(tasks)) {
-            async.mapSeries(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
-                        }
-                        callback.call(null, err, args);
-                    });
-                }
-            }, callback);
-        }
-        else {
-            var results = {};
-            async.eachSeries(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
+    async.series = function(tasks, callback) {
+        _parallel(async.eachOfSeries, tasks, callback);
     };
 
     async.iterator = function (tasks) {
-        var makeCallback = function (index) {
-            var fn = function () {
+        function makeCallback(index) {
+            function fn() {
                 if (tasks.length) {
                     tasks[index].apply(null, arguments);
                 }
                 return fn.next();
-            };
+            }
             fn.next = function () {
                 return (index < tasks.length - 1) ? makeCallback(index + 1): null;
             };
             return fn;
-        };
+        }
         return makeCallback(0);
     };
 
-    async.apply = function (fn) {
-        var args = Array.prototype.slice.call(arguments, 1);
-        return function () {
+    async.apply = _restParam(function (fn, args) {
+        return _restParam(function (callArgs) {
             return fn.apply(
-                null, args.concat(Array.prototype.slice.call(arguments))
+                null, args.concat(callArgs)
             );
-        };
-    };
+        });
+    });
 
-    var _concat = function (eachfn, arr, fn, callback) {
-        var r = [];
-        eachfn(arr, function (x, cb) {
+    function _concat(eachfn, arr, fn, callback) {
+        var result = [];
+        eachfn(arr, function (x, index, cb) {
             fn(x, function (err, y) {
-                r = r.concat(y || []);
+                result = result.concat(y || []);
                 cb(err);
             });
         }, function (err) {
-            callback(err, r);
+            callback(err, result);
         });
-    };
+    }
     async.concat = doParallel(_concat);
     async.concatSeries = doSeries(_concat);
 
     async.whilst = function (test, iterator, callback) {
+        callback = callback || noop;
         if (test()) {
-            iterator(function (err) {
+            var next = _restParam(function(err, args) {
                 if (err) {
-                    return callback(err);
+                    callback(err);
+                } else if (test.apply(this, args)) {
+                    iterator(next);
+                } else {
+                    callback.apply(null, [null].concat(args));
                 }
-                async.whilst(test, iterator, callback);
             });
-        }
-        else {
-            callback();
+            iterator(next);
+        } else {
+            callback(null);
         }
     };
 
     async.doWhilst = function (iterator, test, callback) {
-        iterator(function (err) {
-            if (err) {
-                return callback(err);
-            }
-            var args = Array.prototype.slice.call(arguments, 1);
-            if (test.apply(null, args)) {
-                async.doWhilst(iterator, test, callback);
-            }
-            else {
-                callback();
-            }
-        });
+        var calls = 0;
+        return async.whilst(function() {
+            return ++calls <= 1 || test.apply(this, arguments);
+        }, iterator, callback);
     };
 
     async.until = function (test, iterator, callback) {
-        if (!test()) {
-            iterator(function (err) {
-                if (err) {
-                    return callback(err);
-                }
-                async.until(test, iterator, callback);
-            });
-        }
-        else {
-            callback();
-        }
+        return async.whilst(function() {
+            return !test.apply(this, arguments);
+        }, iterator, callback);
     };
 
     async.doUntil = function (iterator, test, callback) {
-        iterator(function (err) {
+        return async.doWhilst(iterator, function() {
+            return !test.apply(this, arguments);
+        }, callback);
+    };
+
+    async.during = function (test, iterator, callback) {
+        callback = callback || noop;
+
+        var next = _restParam(function(err, args) {
             if (err) {
-                return callback(err);
+                callback(err);
+            } else {
+                args.push(check);
+                test.apply(this, args);
             }
-            var args = Array.prototype.slice.call(arguments, 1);
-            if (!test.apply(null, args)) {
-                async.doUntil(iterator, test, callback);
+        });
+
+        var check = function(err, truth) {
+            if (err) {
+                callback(err);
+            } else if (truth) {
+                iterator(next);
+            } else {
+                callback(null);
             }
-            else {
-                callback();
+        };
+
+        test(check);
+    };
+
+    async.doDuring = function (iterator, test, callback) {
+        var calls = 0;
+        async.during(function(next) {
+            if (calls++ < 1) {
+                next(null, true);
+            } else {
+                test.apply(this, arguments);
             }
-        });
+        }, iterator, callback);
     };
 
-    async.queue = function (worker, concurrency) {
-        if (concurrency === undefined) {
+    function _queue(worker, concurrency, payload) {
+        if (concurrency == null) {
             concurrency = 1;
         }
+        else if(concurrency === 0) {
+            throw new Error('Concurrency must not be zero');
+        }
         function _insert(q, data, pos, callback) {
-          if (!q.started){
+            if (callback != null && typeof callback !== "function") {
+                throw new Error("task callback must be a function");
+            }
             q.started = true;
-          }
-          if (!_isArray(data)) {
-              data = [data];
-          }
-          if(data.length == 0) {
-             // call drain immediately if there are no tasks
-             return async.setImmediate(function() {
-                 if (q.drain) {
-                     q.drain();
-                 }
-             });
-          }
-          _each(data, function(task) {
-              var item = {
-                  data: task,
-                  callback: typeof callback === 'function' ? callback : null
-              };
+            if (!_isArray(data)) {
+                data = [data];
+            }
+            if(data.length === 0 && q.idle()) {
+                // call drain immediately if there are no tasks
+                return async.setImmediate(function() {
+                    q.drain();
+                });
+            }
+            _arrayEach(data, function(task) {
+                var item = {
+                    data: task,
+                    callback: callback || noop
+                };
 
-              if (pos) {
-                q.tasks.unshift(item);
-              } else {
-                q.tasks.push(item);
-              }
+                if (pos) {
+                    q.tasks.unshift(item);
+                } else {
+                    q.tasks.push(item);
+                }
 
-              if (q.saturated && q.tasks.length === q.concurrency) {
-                  q.saturated();
-              }
-              async.setImmediate(q.process);
-          });
+                if (q.tasks.length === q.concurrency) {
+                    q.saturated();
+                }
+            });
+            async.setImmediate(q.process);
+        }
+        function _next(q, tasks) {
+            return function(){
+                workers -= 1;
+
+                var removed = false;
+                var args = arguments;
+                _arrayEach(tasks, function (task) {
+                    _arrayEach(workersList, function (worker, index) {
+                        if (worker === task && !removed) {
+                            workersList.splice(index, 1);
+                            removed = true;
+                        }
+                    });
+
+                    task.callback.apply(task, args);
+                });
+                if (q.tasks.length + workers === 0) {
+                    q.drain();
+                }
+                q.process();
+            };
         }
 
         var workers = 0;
+        var workersList = [];
         var q = {
             tasks: [],
             concurrency: concurrency,
-            saturated: null,
-            empty: null,
-            drain: null,
+            payload: payload,
+            saturated: noop,
+            empty: noop,
+            drain: noop,
             started: false,
             paused: false,
             push: function (data, callback) {
-              _insert(q, data, false, callback);
+                _insert(q, data, false, callback);
             },
             kill: function () {
-              q.drain = null;
-              q.tasks = [];
+                q.drain = noop;
+                q.tasks = [];
             },
             unshift: function (data, callback) {
-              _insert(q, data, true, callback);
+                _insert(q, data, true, callback);
             },
             process: function () {
-                if (!q.paused && workers < q.concurrency && q.tasks.length) {
-                    var task = q.tasks.shift();
-                    if (q.empty && q.tasks.length === 0) {
+                while(!q.paused && workers < q.concurrency && q.tasks.length){
+
+                    var tasks = q.payload ?
+                        q.tasks.splice(0, q.payload) :
+                        q.tasks.splice(0, q.tasks.length);
+
+                    var data = _map(tasks, function (task) {
+                        return task.data;
+                    });
+
+                    if (q.tasks.length === 0) {
                         q.empty();
                     }
                     workers += 1;
-                    var next = function () {
-                        workers -= 1;
-                        if (task.callback) {
-                            task.callback.apply(task, arguments);
-                        }
-                        if (q.drain && q.tasks.length + workers === 0) {
-                            q.drain();
-                        }
-                        q.process();
-                    };
-                    var cb = only_once(next);
-                    worker(task.data, cb);
+                    workersList.push(tasks[0]);
+                    var cb = only_once(_next(q, tasks));
+                    worker(data, cb);
                 }
             },
             length: function () {
@@ -12429,82 +12836,95 @@ var objectKeys = Object.keys || function (obj) {
             running: function () {
                 return workers;
             },
+            workersList: function () {
+                return workersList;
+            },
             idle: function() {
                 return q.tasks.length + workers === 0;
             },
             pause: function () {
-                if (q.paused === true) { return; }
                 q.paused = true;
-                q.process();
             },
             resume: function () {
                 if (q.paused === false) { return; }
                 q.paused = false;
-                q.process();
+                var resumeCount = Math.min(q.concurrency, q.tasks.length);
+                // Need to call q.process once per concurrent
+                // worker to preserve full concurrency after pause
+                for (var w = 1; w <= resumeCount; w++) {
+                    async.setImmediate(q.process);
+                }
             }
         };
+        return q;
+    }
+
+    async.queue = function (worker, concurrency) {
+        var q = _queue(function (items, cb) {
+            worker(items[0], cb);
+        }, concurrency, 1);
+
         return q;
     };
-    
+
     async.priorityQueue = function (worker, concurrency) {
-        
+
         function _compareTasks(a, b){
-          return a.priority - b.priority;
-        };
-        
+            return a.priority - b.priority;
+        }
+
         function _binarySearch(sequence, item, compare) {
-          var beg = -1,
-              end = sequence.length - 1;
-          while (beg < end) {
-            var mid = beg + ((end - beg + 1) >>> 1);
-            if (compare(item, sequence[mid]) >= 0) {
-              beg = mid;
-            } else {
-              end = mid - 1;
+            var beg = -1,
+                end = sequence.length - 1;
+            while (beg < end) {
+                var mid = beg + ((end - beg + 1) >>> 1);
+                if (compare(item, sequence[mid]) >= 0) {
+                    beg = mid;
+                } else {
+                    end = mid - 1;
+                }
             }
-          }
-          return beg;
+            return beg;
         }
-        
+
         function _insert(q, data, priority, callback) {
-          if (!q.started){
+            if (callback != null && typeof callback !== "function") {
+                throw new Error("task callback must be a function");
+            }
             q.started = true;
-          }
-          if (!_isArray(data)) {
-              data = [data];
-          }
-          if(data.length == 0) {
-             // call drain immediately if there are no tasks
-             return async.setImmediate(function() {
-                 if (q.drain) {
-                     q.drain();
-                 }
-             });
-          }
-          _each(data, function(task) {
-              var item = {
-                  data: task,
-                  priority: priority,
-                  callback: typeof callback === 'function' ? callback : null
-              };
-              
-              q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
+            if (!_isArray(data)) {
+                data = [data];
+            }
+            if(data.length === 0) {
+                // call drain immediately if there are no tasks
+                return async.setImmediate(function() {
+                    q.drain();
+                });
+            }
+            _arrayEach(data, function(task) {
+                var item = {
+                    data: task,
+                    priority: priority,
+                    callback: typeof callback === 'function' ? callback : noop
+                };
 
-              if (q.saturated && q.tasks.length === q.concurrency) {
-                  q.saturated();
-              }
-              async.setImmediate(q.process);
-          });
+                q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
+
+                if (q.tasks.length === q.concurrency) {
+                    q.saturated();
+                }
+                async.setImmediate(q.process);
+            });
         }
-        
+
         // Start with a normal queue
         var q = async.queue(worker, concurrency);
-        
+
         // Override push to accept second parameter representing priority
         q.push = function (data, priority, callback) {
-          _insert(q, data, priority, callback);
+            _insert(q, data, priority, callback);
         };
-        
+
         // Remove unshift function
         delete q.unshift;
 
@@ -12512,93 +12932,27 @@ var objectKeys = Object.keys || function (obj) {
     };
 
     async.cargo = function (worker, payload) {
-        var working     = false,
-            tasks       = [];
-
-        var cargo = {
-            tasks: tasks,
-            payload: payload,
-            saturated: null,
-            empty: null,
-            drain: null,
-            drained: true,
-            push: function (data, callback) {
-                if (!_isArray(data)) {
-                    data = [data];
-                }
-                _each(data, function(task) {
-                    tasks.push({
-                        data: task,
-                        callback: typeof callback === 'function' ? callback : null
-                    });
-                    cargo.drained = false;
-                    if (cargo.saturated && tasks.length === payload) {
-                        cargo.saturated();
-                    }
-                });
-                async.setImmediate(cargo.process);
-            },
-            process: function process() {
-                if (working) return;
-                if (tasks.length === 0) {
-                    if(cargo.drain && !cargo.drained) cargo.drain();
-                    cargo.drained = true;
-                    return;
-                }
-
-                var ts = typeof payload === 'number'
-                            ? tasks.splice(0, payload)
-                            : tasks.splice(0, tasks.length);
-
-                var ds = _map(ts, function (task) {
-                    return task.data;
-                });
-
-                if(cargo.empty) cargo.empty();
-                working = true;
-                worker(ds, function () {
-                    working = false;
-
-                    var args = arguments;
-                    _each(ts, function (data) {
-                        if (data.callback) {
-                            data.callback.apply(null, args);
-                        }
-                    });
-
-                    process();
-                });
-            },
-            length: function () {
-                return tasks.length;
-            },
-            running: function () {
-                return working;
-            }
-        };
-        return cargo;
+        return _queue(worker, 1, payload);
     };
 
-    var _console_fn = function (name) {
-        return function (fn) {
-            var args = Array.prototype.slice.call(arguments, 1);
-            fn.apply(null, args.concat([function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
-                if (typeof console !== 'undefined') {
+    function _console_fn(name) {
+        return _restParam(function (fn, args) {
+            fn.apply(null, args.concat([_restParam(function (err, args) {
+                if (typeof console === 'object') {
                     if (err) {
                         if (console.error) {
                             console.error(err);
                         }
                     }
                     else if (console[name]) {
-                        _each(args, function (x) {
+                        _arrayEach(args, function (x) {
                             console[name](x);
                         });
                     }
                 }
-            }]));
-        };
-    };
+            })]));
+        });
+    }
     async.log = _console_fn('log');
     async.dir = _console_fn('dir');
     /*async.info = _console_fn('info');
@@ -12608,123 +12962,174 @@ var objectKeys = Object.keys || function (obj) {
     async.memoize = function (fn, hasher) {
         var memo = {};
         var queues = {};
-        hasher = hasher || function (x) {
-            return x;
-        };
-        var memoized = function () {
-            var args = Array.prototype.slice.call(arguments);
+        var has = Object.prototype.hasOwnProperty;
+        hasher = hasher || identity;
+        var memoized = _restParam(function memoized(args) {
             var callback = args.pop();
             var key = hasher.apply(null, args);
-            if (key in memo) {
-                async.nextTick(function () {
+            if (has.call(memo, key)) {   
+                async.setImmediate(function () {
                     callback.apply(null, memo[key]);
                 });
             }
-            else if (key in queues) {
+            else if (has.call(queues, key)) {
                 queues[key].push(callback);
             }
             else {
                 queues[key] = [callback];
-                fn.apply(null, args.concat([function () {
-                    memo[key] = arguments;
+                fn.apply(null, args.concat([_restParam(function (args) {
+                    memo[key] = args;
                     var q = queues[key];
                     delete queues[key];
                     for (var i = 0, l = q.length; i < l; i++) {
-                      q[i].apply(null, arguments);
+                        q[i].apply(null, args);
                     }
-                }]));
+                })]));
             }
-        };
+        });
         memoized.memo = memo;
         memoized.unmemoized = fn;
         return memoized;
     };
 
     async.unmemoize = function (fn) {
-      return function () {
-        return (fn.unmemoized || fn).apply(null, arguments);
-      };
+        return function () {
+            return (fn.unmemoized || fn).apply(null, arguments);
+        };
     };
 
-    async.times = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
-        }
-        return async.map(counter, iterator, callback);
-    };
+    function _times(mapper) {
+        return function (count, iterator, callback) {
+            mapper(_range(count), iterator, callback);
+        };
+    }
 
-    async.timesSeries = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
-        }
-        return async.mapSeries(counter, iterator, callback);
+    async.times = _times(async.map);
+    async.timesSeries = _times(async.mapSeries);
+    async.timesLimit = function (count, limit, iterator, callback) {
+        return async.mapLimit(_range(count), limit, iterator, callback);
     };
 
     async.seq = function (/* functions... */) {
         var fns = arguments;
-        return function () {
+        return _restParam(function (args) {
             var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
+
+            var callback = args[args.length - 1];
+            if (typeof callback == 'function') {
+                args.pop();
+            } else {
+                callback = noop;
+            }
+
             async.reduce(fns, args, function (newargs, fn, cb) {
-                fn.apply(that, newargs.concat([function () {
-                    var err = arguments[0];
-                    var nextargs = Array.prototype.slice.call(arguments, 1);
+                fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {
                     cb(err, nextargs);
-                }]))
+                })]));
             },
             function (err, results) {
                 callback.apply(that, [err].concat(results));
             });
-        };
+        });
     };
 
     async.compose = function (/* functions... */) {
-      return async.seq.apply(null, Array.prototype.reverse.call(arguments));
+        return async.seq.apply(null, Array.prototype.reverse.call(arguments));
     };
 
-    var _applyEach = function (eachfn, fns /*args...*/) {
-        var go = function () {
-            var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            return eachfn(fns, function (fn, cb) {
-                fn.apply(that, args.concat([cb]));
-            },
-            callback);
-        };
-        if (arguments.length > 2) {
-            var args = Array.prototype.slice.call(arguments, 2);
-            return go.apply(this, args);
-        }
-        else {
-            return go;
-        }
-    };
-    async.applyEach = doParallel(_applyEach);
-    async.applyEachSeries = doSeries(_applyEach);
+
+    function _applyEach(eachfn) {
+        return _restParam(function(fns, args) {
+            var go = _restParam(function(args) {
+                var that = this;
+                var callback = args.pop();
+                return eachfn(fns, function (fn, _, cb) {
+                    fn.apply(that, args.concat([cb]));
+                },
+                callback);
+            });
+            if (args.length) {
+                return go.apply(this, args);
+            }
+            else {
+                return go;
+            }
+        });
+    }
+
+    async.applyEach = _applyEach(async.eachOf);
+    async.applyEachSeries = _applyEach(async.eachOfSeries);
+
 
     async.forever = function (fn, callback) {
+        var done = only_once(callback || noop);
+        var task = ensureAsync(fn);
         function next(err) {
             if (err) {
-                if (callback) {
-                    return callback(err);
-                }
-                throw err;
+                return done(err);
             }
-            fn(next);
+            task(next);
         }
         next();
     };
 
+    function ensureAsync(fn) {
+        return _restParam(function (args) {
+            var callback = args.pop();
+            args.push(function () {
+                var innerArgs = arguments;
+                if (sync) {
+                    async.setImmediate(function () {
+                        callback.apply(null, innerArgs);
+                    });
+                } else {
+                    callback.apply(null, innerArgs);
+                }
+            });
+            var sync = true;
+            fn.apply(this, args);
+            sync = false;
+        });
+    }
+
+    async.ensureAsync = ensureAsync;
+
+    async.constant = _restParam(function(values) {
+        var args = [null].concat(values);
+        return function (callback) {
+            return callback.apply(this, args);
+        };
+    });
+
+    async.wrapSync =
+    async.asyncify = function asyncify(func) {
+        return _restParam(function (args) {
+            var callback = args.pop();
+            var result;
+            try {
+                result = func.apply(this, args);
+            } catch (e) {
+                return callback(e);
+            }
+            // if result is Promise object
+            if (_isObject(result) && typeof result.then === "function") {
+                result.then(function(value) {
+                    callback(null, value);
+                })["catch"](function(err) {
+                    callback(err.message ? err : new Error(err));
+                });
+            } else {
+                callback(null, result);
+            }
+        });
+    };
+
     // Node.js
-    if (typeof module !== 'undefined' && module.exports) {
+    if (typeof module === 'object' && module.exports) {
         module.exports = async;
     }
     // AMD / RequireJS
-    else if (typeof define !== 'undefined' && define.amd) {
+    else if (typeof define === 'function' && define.amd) {
         define([], function () {
             return async;
         });
@@ -12736,8 +13141,8 @@ var objectKeys = Object.keys || function (obj) {
 
 }());
 
-}).call(this,require("g5I+bs"))
-},{"g5I+bs":92}],52:[function(require,module,exports){
+}).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"g5I+bs":94}],52:[function(require,module,exports){
 var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 
 ;(function (exports) {
@@ -13594,7 +13999,7 @@ BinaryParser.Buffer = BinaryParserBuffer;
 exports.BinaryParser = BinaryParser;
 
 }).call(this,require("g5I+bs"))
-},{"g5I+bs":92,"util":97}],55:[function(require,module,exports){
+},{"g5I+bs":94,"util":98}],55:[function(require,module,exports){
 (function (Buffer){
 // "use strict"
 
@@ -15433,7 +15838,7 @@ module.exports.ObjectID = ObjectID;
 module.exports.ObjectId = ObjectID;
 
 }).call(this,require("g5I+bs"))
-},{"./binary_parser":54,"g5I+bs":92}],65:[function(require,module,exports){
+},{"./binary_parser":54,"g5I+bs":94}],65:[function(require,module,exports){
 (function (Buffer){
 "use strict"
 
@@ -16274,7 +16679,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000);  // Any integer down t
 
 module.exports = deserialize
 
-},{"../binary":53,"../code":56,"../db_ref":57,"../double":58,"../float_parser":59,"../long":60,"../max_key":62,"../min_key":63,"../objectid":64,"../regexp":68,"../symbol":69,"../timestamp":70,"util":97}],67:[function(require,module,exports){
+},{"../binary":53,"../code":56,"../db_ref":57,"../double":58,"../float_parser":59,"../long":60,"../max_key":62,"../min_key":63,"../objectid":64,"../regexp":68,"../symbol":69,"../timestamp":70,"util":98}],67:[function(require,module,exports){
 (function (Buffer){
 "use strict"
 
@@ -19549,7 +19954,7 @@ function coerce(val) {
   return val;
 }
 
-},{"ms":91}],74:[function(require,module,exports){
+},{"ms":93}],74:[function(require,module,exports){
 // Copyright Joyent, Inc. and other Node contributors.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
@@ -20424,11 +20829,10 @@ Kareem.prototype.clone = function() {
 module.exports = Kareem;
 
 }).call(this,require("g5I+bs"))
-},{"g5I+bs":92}],80:[function(require,module,exports){
+},{"g5I+bs":94}],80:[function(require,module,exports){
 module.exports = exports = require('./lib');
 
 },{"./lib":81}],81:[function(require,module,exports){
-
 /**
  * Returns the value of object `o` at the given `path`.
  *
@@ -20458,9 +20862,16 @@ module.exports = exports = require('./lib');
  */
 
 exports.get = function (path, o, special, map) {
+  var lookup;
+
   if ('function' == typeof special) {
-    map = special;
-    special = undefined;
+    if (special.length < 2) {
+      map = special;
+      special = undefined;
+    } else {
+      lookup = special;
+      special = undefined;
+    }
   }
 
   map || (map = K);
@@ -20485,14 +20896,18 @@ exports.get = function (path, o, special, map) {
 
       return obj.map(function (item) {
         return item
-          ? exports.get(paths, item, special, map)
+          ? exports.get(paths, item, special || lookup, map)
           : map(undefined);
       });
     }
 
-    obj = special && obj[special]
-      ? obj[special][part]
-      : obj[part];
+    if (lookup) {
+      obj = lookup(obj, part);
+    } else {
+      obj = special && obj[special]
+        ? obj[special][part]
+        : obj[part];
+    }
 
     if (!obj) return map(obj);
   }
@@ -20508,13 +20923,19 @@ exports.get = function (path, o, special, map) {
  * @param {Object} o
  * @param {String} [special] When this property name is present on any object in the path, walking will continue on the value of this property.
  * @param {Function} [map] Optional function which is passed each individual value before setting it. The value returned from `map` is used in the original values place.
-
  */
 
 exports.set = function (path, val, o, special, map, _copying) {
+  var lookup;
+
   if ('function' == typeof special) {
-    map = special;
-    special = undefined;
+    if (special.length < 2) {
+      map = special;
+      special = undefined;
+    } else {
+      lookup = special;
+      special = undefined;
+    }
   }
 
   map || (map = K);
@@ -20553,20 +20974,24 @@ exports.set = function (path, val, o, special, map, _copying) {
       if (!copy && Array.isArray(val)) {
         for (var j = 0; j < obj.length && j < val.length; ++j) {
           // assignment of single values of array
-          exports.set(paths, val[j], obj[j], special, map, copy);
+          exports.set(paths, val[j], obj[j], special || lookup, map, copy);
         }
       } else {
         for (var j = 0; j < obj.length; ++j) {
           // assignment of entire value
-          exports.set(paths, val, obj[j], special, map, copy);
+          exports.set(paths, val, obj[j], special || lookup, map, copy);
         }
       }
       return;
     }
 
-    obj = special && obj[special]
-      ? obj[special][part]
-      : obj[part];
+    if (lookup) {
+      obj = lookup(obj, part);
+    } else {
+      obj = special && obj[special]
+        ? obj[special][part]
+        : obj[part];
+    }
 
     if (!obj) return;
   }
@@ -20586,21 +21011,33 @@ exports.set = function (path, val, o, special, map, _copying) {
       for (var item, j = 0; j < obj.length && j < val.length; ++j) {
         item = obj[j];
         if (item) {
-          if (item[special]) item = item[special];
-          item[part] = map(val[j]);
+          if (lookup) {
+            lookup(item, part, map(val[j]));
+          } else {
+            if (item[special]) item = item[special];
+            item[part] = map(val[j]);
+          }
         }
       }
     } else {
       for (var j = 0; j < obj.length; ++j) {
         item = obj[j];
         if (item) {
-          if (item[special]) item = item[special];
-          item[part] = map(val);
+          if (lookup) {
+            lookup(item, part, map(val));
+          } else {
+            if (item[special]) item = item[special];
+            item[part] = map(val);
+          }
         }
       }
     }
   } else {
-    obj[part] = map(val);
+    if (lookup) {
+      lookup(obj, part, map(val));
+    } else {
+      obj[part] = map(val);
+    }
   }
 }
 
@@ -20628,7 +21065,7 @@ function strongUnshift(x, arrLike) {
 
 
 /**
- * Promise constructor.
+ * MPromise constructor.
  *
  * _NOTE: The success and failure event names can be overridden by setting `Promise.SUCCESS` and `Promise.FAILURE` respectively._
  *
@@ -20642,8 +21079,10 @@ function Promise(back) {
   this.emitter = new EventEmitter();
   this.emitted = {};
   this.ended = false;
-  if ('function' == typeof back)
+  if ('function' == typeof back) {
+    this.ended = true;
     this.onResolve(back);
+  }
 }
 
 
@@ -20667,7 +21106,7 @@ Promise.FAILURE = 'reject';
  *
  * @param {String} event
  * @param {Function} callback
- * @return {Promise} this
+ * @return {MPromise} this
  * @api private
  */
 Promise.prototype.on = function (event, callback) {
@@ -20699,6 +21138,14 @@ Promise.prototype.safeEmit = function (event) {
 };
 
 
+/**
+ * @api private
+ */
+Promise.prototype.hasRejectListeners = function () {
+  return EventEmitter.listenerCount(this.emitter, Promise.FAILURE) > 0;
+};
+
+
 /**
  * Fulfills this promise with passed arguments.
  *
@@ -20718,10 +21165,11 @@ Promise.prototype.fulfill = function () {
  *
  * @api public
  * @param {Object|String} reason
- * @return {Promise} this
+ * @return {MPromise} this
  */
 Promise.prototype.reject = function (reason) {
-  if (this.ended && !this.hasRejectListeners()) throw reason;
+  if (this.ended && !this.hasRejectListeners())
+    throw reason;
   return this.safeEmit(Promise.FAILURE, reason);
 };
 
@@ -20743,7 +21191,7 @@ Promise.prototype.resolve = function (err, val) {
 /**
  * Adds a listener to the SUCCESS event.
  *
- * @return {Promise} this
+ * @return {MPromise} this
  * @api public
  */
 Promise.prototype.onFulfill = function (fn) {
@@ -20753,15 +21201,10 @@ Promise.prototype.onFulfill = function (fn) {
 };
 
 
-Promise.prototype.hasRejectListeners = function () {
-  return this.emitter.listeners(Promise.FAILURE).length > 0;
-};
-
-
 /**
  * Adds a listener to the FAILURE event.
  *
- * @return {Promise} this
+ * @return {MPromise} this
  * @api public
  */
 Promise.prototype.onReject = function (fn) {
@@ -20781,10 +21224,9 @@ Promise.prototype.onReject = function (fn) {
  * side effects unless `fn` is undefined or null.
  *
  * @param {Function} fn
- * @return {Promise} this
+ * @return {MPromise} this
  */
 Promise.prototype.onResolve = function (fn) {
-  this.end();
   if (!fn) return this;
   if ('function' != typeof fn) throw new TypeError("fn should be a function");
   this.on(Promise.FAILURE, function (err) { fn.call(this, err); });
@@ -20816,7 +21258,7 @@ Promise.prototype.onResolve = function (fn) {
  * @see promises-A+ https://github.com/promises-aplus/promises-spec
  * @param {Function} onFulfill
  * @param {Function} [onReject]
- * @return {Promise} newPromise
+ * @return {MPromise} newPromise
  */
 Promise.prototype.then = function (onFulfill, onReject) {
   var newPromise = new Promise;
@@ -20924,9 +21366,11 @@ function resolve(promise, x) {
  *
  * @api public
  * @param {Function} [onReject]
- * @return {Promise} this
+ * @return {MPromise} this
  */
-Promise.prototype.end = function (onReject) {
+Promise.prototype.end = Promise.prototype['catch'] = function (onReject) {
+  if (!onReject && !this.hasRejectListeners())
+    onReject = function idRejector(e) { throw e; };
   this.onReject(onReject);
   this.ended = true;
   return this;
@@ -20955,9 +21399,9 @@ Promise.prototype.end = function (onReject) {
  *     }, 10);
  *
  * @api public
- * @param {Promise} p
+ * @param {MPromise} p
  * @param {String} name
- * @return {Promise} this
+ * @return {MPromise} this
  */
 Promise.trace = function (p, name) {
   p.then(
@@ -21053,10 +21497,8 @@ Promise.deferred = function deferred() {
 };
 /* End A+ tests adapter bit */
 
-
-
 }).call(this,require("g5I+bs"))
-},{"events":74,"g5I+bs":92,"util":97}],83:[function(require,module,exports){
+},{"events":74,"g5I+bs":94,"util":98}],83:[function(require,module,exports){
 'use strict';
 
 /**
@@ -21243,7 +21685,7 @@ exports.type = exports.isNode ? 'node'
   : 'unknown'
 
 }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
-},{"buffer":71,"g5I+bs":92}],87:[function(require,module,exports){
+},{"buffer":71,"g5I+bs":94}],87:[function(require,module,exports){
 'use strict';
 
 /**
@@ -23857,7 +24299,7 @@ module.exports = exports = Query;
 // TODO
 // test utils
 
-},{"./collection":84,"./collection/collection":83,"./env":86,"./permissions":88,"./utils":89,"assert":50,"bluebird":90,"debug":72,"sliced":94,"util":97}],88:[function(require,module,exports){
+},{"./collection":84,"./collection/collection":83,"./env":86,"./permissions":88,"./utils":89,"assert":50,"bluebird":90,"debug":72,"sliced":91,"util":98}],88:[function(require,module,exports){
 'use strict';
 
 var denied = exports;
@@ -23994,13 +24436,13 @@ var clone = exports.clone = function clone (obj, options) {
         : new obj.constructor(obj.value(true), obj.sub_type);
     }
 
-    if ('Date' === obj.constructor.name || obj.constructor.name === 'Function')
+    if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
       return new obj.constructor(+obj);
 
-    if (obj.constructor.name === 'RegExp')
+    if ('RegExp' === obj.constructor.name)
       return RegExpClone(obj);
 
-    if (obj.constructor.name === 'Buffer')
+    if ('Buffer' === obj.constructor.name)
       return exports.cloneBuffer(obj);
   }
 
@@ -24284,7 +24726,7 @@ exports.cloneBuffer = function (buff) {
 };
 
 }).call(this,require("g5I+bs"),require("buffer").Buffer)
-},{"buffer":71,"g5I+bs":92,"regexp-clone":93}],90:[function(require,module,exports){
+},{"buffer":71,"g5I+bs":94,"regexp-clone":95}],90:[function(require,module,exports){
 (function (process,global){
 /* @preserve
  * The MIT License (MIT)
@@ -29392,7 +29834,45 @@ function isUndefined(arg) {
 },{}]},{},[4])(4)
 });                    ;if (typeof window !== 'undefined' && window !== null) {                               window.P = window.Promise;                                                     } else if (typeof self !== 'undefined' && self !== null) {                             self.P = self.Promise;                                                         }
 }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"g5I+bs":92}],91:[function(require,module,exports){
+},{"g5I+bs":94}],91:[function(require,module,exports){
+module.exports = exports = require('./lib/sliced');
+
+},{"./lib/sliced":92}],92:[function(require,module,exports){
+
+/**
+ * An Array.prototype.slice.call(arguments) alternative
+ *
+ * @param {Object} args something with a length
+ * @param {Number} slice
+ * @param {Number} sliceEnd
+ * @api public
+ */
+
+module.exports = function (args, slice, sliceEnd) {
+  var ret = [];
+  var len = args.length;
+
+  if (0 === len) return ret;
+
+  var start = slice < 0
+    ? Math.max(0, slice + len)
+    : slice || 0;
+
+  if (sliceEnd !== undefined) {
+    len = sliceEnd < 0
+      ? sliceEnd + len
+      : sliceEnd
+  }
+
+  while (len-- > start) {
+    ret[len - start] = args[len];
+  }
+
+  return ret;
+}
+
+
+},{}],93:[function(require,module,exports){
 /**
  * Helpers.
  */
@@ -29519,7 +29999,7 @@ function plural(ms, n, name) {
   return Math.ceil(ms / n) + ' ' + name + 's';
 }
 
-},{}],92:[function(require,module,exports){
+},{}],94:[function(require,module,exports){
 // shim for using process in browser
 
 var process = module.exports = {};
@@ -29584,7 +30064,7 @@ process.chdir = function (dir) {
     throw new Error('process.chdir is not supported');
 };
 
-},{}],93:[function(require,module,exports){
+},{}],95:[function(require,module,exports){
 
 var toString = Object.prototype.toString;
 
@@ -29606,52 +30086,16 @@ module.exports = exports = function (regexp) {
 }
 
 
-},{}],94:[function(require,module,exports){
-module.exports = exports = require('./lib/sliced');
-
-},{"./lib/sliced":95}],95:[function(require,module,exports){
-
-/**
- * An Array.prototype.slice.call(arguments) alternative
- *
- * @param {Object} args something with a length
- * @param {Number} slice
- * @param {Number} sliceEnd
- * @api public
- */
-
-module.exports = function (args, slice, sliceEnd) {
-  var ret = [];
-  var len = args.length;
-
-  if (0 === len) return ret;
-
-  var start = slice < 0
-    ? Math.max(0, slice + len)
-    : slice || 0;
-
-  if (sliceEnd !== undefined) {
-    len = sliceEnd < 0
-      ? sliceEnd + len
-      : sliceEnd
-  }
-
-  while (len-- > start) {
-    ret[len - start] = args[len];
-  }
-
-  return ret;
-}
-
-
 },{}],96:[function(require,module,exports){
+module.exports=require(92)
+},{}],97:[function(require,module,exports){
 module.exports = function isBuffer(arg) {
   return arg && typeof arg === 'object'
     && typeof arg.copy === 'function'
     && typeof arg.fill === 'function'
     && typeof arg.readUInt8 === 'function';
 }
-},{}],97:[function(require,module,exports){
+},{}],98:[function(require,module,exports){
 (function (process,global){
 // Copyright Joyent, Inc. and other Node contributors.
 //
@@ -30241,4 +30685,4 @@ function hasOwnProperty(obj, prop) {
 }
 
 }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./support/isBuffer":96,"g5I+bs":92,"inherits":77}]},{},[2])
\ No newline at end of file
+},{"./support/isBuffer":97,"g5I+bs":94,"inherits":77}]},{},[2])
\ No newline at end of file
diff --git a/package.json b/package.json
index 65a8dad2488..ad1a624f6f4 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.3.8-pre",
+  "version": "4.4.0",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From d2a3d004620b845620568f9e4cb982c7ee570c0f Mon Sep 17 00:00:00 2001
From: CTAPbIuMABP 
Date: Wed, 3 Feb 2016 16:19:19 +0800
Subject: [PATCH 0250/2240] lint

---
 .eslintrc.yml                                 |   2 +-
 benchmarks/benchjs/population.js              |  23 +--
 benchmarks/mem.js                             | 113 ++++++------
 docs/migration.jade                           |   2 +-
 lib/cast.js                                   |  53 +++---
 lib/drivers/node-mongodb-native/collection.js |  76 ++++----
 lib/model.js                                  | 158 +++++++++--------
 lib/query.js                                  |   9 +-
 lib/querystream.js                            |   2 +-
 lib/schema.js                                 |   8 +-
 lib/schema/buffer.js                          |  16 +-
 lib/schema/date.js                            |   8 +-
 lib/schema/documentarray.js                   |  21 +--
 lib/schema/number.js                          |  18 +-
 lib/schema/objectid.js                        |   8 +-
 lib/schema/string.js                          |  14 +-
 lib/services/updateValidators.js              |  19 +-
 lib/types/array.js                            |   7 +-
 test/browser/schema.validation.test_.js       |  16 +-
 test/browser/types.objectid.test_.js          | 166 +++++++++---------
 test/docs/defaults.test.js                    |   2 +-
 test/document.isselected.test.js              |  16 +-
 test/model.discriminator.querying.test.js     |   4 +-
 test/model.findOneAndUpdate.test.js           |  56 +++---
 test/model.geosearch.test.js                  |   2 +-
 test/model.indexes.test.js                    |  83 +++++----
 test/model.mapreduce.test.js                  |   4 +-
 test/model.populate.setting.test.js           |   8 +-
 test/model.populate.test.js                   |   2 +-
 test/model.query.casting.test.js              |   2 +-
 test/model.querying.test.js                   |   8 +-
 test/model.test.js                            |   6 +-
 test/model.update.test.js                     |  27 +--
 test/schema.select.test.js                    |   6 +-
 test/schema.timestamps.test.js                |   4 +-
 test/types.array.test.js                      |   6 +-
 test/types.buffer.test.js                     |  37 ++--
 37 files changed, 536 insertions(+), 476 deletions(-)

diff --git a/.eslintrc.yml b/.eslintrc.yml
index 419fce4eedb..c16c3369b56 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -7,7 +7,7 @@ env:
 rules:
   comma-style: 2
   consistent-this:
-    - 1
+    - 2
     - _this
   indent:
     - 2
diff --git a/benchmarks/benchjs/population.js b/benchmarks/benchjs/population.js
index 0a966d45c3a..d7b7cb7608b 100644
--- a/benchmarks/benchjs/population.js
+++ b/benchmarks/benchjs/population.js
@@ -256,19 +256,22 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function(err) {
       blog[6].dummy4.push(getNextdId(8));
     }
 
-    // insert all of the data here
     var count = 7;
+
+    function iter(c) {
+      BlogPost.create(blog[c], function(err, bl) {
+        if (err) {
+          throw err;
+        }
+        blog[c] = bl;
+        --count || next();
+      });
+    }
+
+    // insert all of the data here
     for (i = 0; i < blog.length; i++) {
       // use some closure magic to make sure we retain the index
-      (function(c) {
-        BlogPost.create(blog[c], function(err, bl) {
-          if (err) {
-            throw err;
-          }
-          blog[c] = bl;
-          --count || next();
-        });
-      })(i);
+      iter(i);
     }
   }
 
diff --git a/benchmarks/mem.js b/benchmarks/mem.js
index d3449d7e96e..7ba33d0f3a1 100644
--- a/benchmarks/mem.js
+++ b/benchmarks/mem.js
@@ -98,64 +98,65 @@ var start = new Date;
 var total = 10000;
 var i = total;
 
-mongoose.connection.on('open', function() {
+function done() {
+  var time = (new Date - start);
+  var used = process.memoryUsage();
+
+  var res = {};
+  res.rss = used.rss - started.rss;
+  res.heapTotal = used.heapTotal - started.heapTotal;
+  res.heapUsed = used.heapUsed - started.heapUsed;
+
+  console.error('took %d ms for %d docs (%d dps)', time, total, total / (time / 1000), 'change: ', res);
+
   mongoose.connection.db.dropDatabase(function() {
-    (function cycle() {
-      if (i-- === 0) {
-        return done();
-      }
-      var a = new A({
-        string: 'hello world',
-        number: 444848484,
-        date: new Date,
-        bool: true,
-        buffer: new Buffer(0),
-        objectid: new mongoose.Types.ObjectId(),
-        array: [4, {}, [], 'asdfa'],
-        strings: ['one', 'two', 'three', 'four'],
-        numbers: [72, 6493, 83984643, 348282.55],
-        dates: [new Date, new Date, new Date],
-        bools: [true, false, false, true, true],
-        buffers: [new Buffer([33]), new Buffer([12])],
-        objectids: [new mongoose.Types.ObjectId],
-        docs: [{title: 'yo'}, {title: 'nowafasdi0fas asjkdfla fa'}]
-      });
-
-      a.save(function() {
-        methods[Math.random() * methods.length | 0](a, function() {
-          a = null;
-          process.nextTick(cycle);
-        });
-      });
-
-      /* if (i%2)
-        a.toObject({ depopulate: true });
-      else
-        a._delta();
-
-      if (!(i%50)) {
-        var u = process.memoryUsage();
-        console.error('rss: %d, vsize: %d, heapTotal: %d, heapUsed: %d',
-            u.rss, u.vsize, u.heapTotal, u.heapUsed);
-      } */
-    })();
-
-    function done() {
-      var time = (new Date - start);
-      var used = process.memoryUsage();
-
-      var res = {};
-      res.rss = used.rss - started.rss;
-      res.heapTotal = used.heapTotal - started.heapTotal;
-      res.heapUsed = used.heapUsed - started.heapUsed;
-
-      console.error('took %d ms for %d docs (%d dps)', time, total, total / (time / 1000), 'change: ', res);
-
-      mongoose.connection.db.dropDatabase(function() {
-        mongoose.connection.close();
-      });
-    }
+    mongoose.connection.close();
+  });
+}
 
+function cycle() {
+  if (i-- === 0) {
+    return done();
+  }
+  var a = new A({
+    string: 'hello world',
+    number: 444848484,
+    date: new Date,
+    bool: true,
+    buffer: new Buffer(0),
+    objectid: new mongoose.Types.ObjectId(),
+    array: [4, {}, [], 'asdfa'],
+    strings: ['one', 'two', 'three', 'four'],
+    numbers: [72, 6493, 83984643, 348282.55],
+    dates: [new Date, new Date, new Date],
+    bools: [true, false, false, true, true],
+    buffers: [new Buffer([33]), new Buffer([12])],
+    objectids: [new mongoose.Types.ObjectId],
+    docs: [{title: 'yo'}, {title: 'nowafasdi0fas asjkdfla fa'}]
+  });
+
+  a.save(function() {
+    methods[Math.random() * methods.length | 0](a, function() {
+      a = null;
+      process.nextTick(cycle);
+    });
+  });
+
+  /* if (i%2)
+    a.toObject({ depopulate: true });
+  else
+    a._delta();
+
+  if (!(i%50)) {
+    var u = process.memoryUsage();
+    console.error('rss: %d, vsize: %d, heapTotal: %d, heapUsed: %d',
+        u.rss, u.vsize, u.heapTotal, u.heapUsed);
+  } */
+}
+
+mongoose.connection.on('open', function() {
+  mongoose.connection.db.dropDatabase(function() {
+    cycle();
     // --trace-opt --trace-deopt --trace-bailout
   });
 });
diff --git a/docs/migration.jade b/docs/migration.jade
index 7172f1f7b50..b59f3b58428 100644
--- a/docs/migration.jade
+++ b/docs/migration.jade
@@ -28,7 +28,7 @@ block content
     To return the document with modifications made on the update, use the `new: true` option.
 
   :js
-    MyModel.findOneAndUpdate({}, { $set: { test: 1 } }, { 'new': true }, callback);
+    MyModel.findOneAndUpdate({}, { $set: { test: 1 } }, { new: true }, callback);
 
   h3 CastError and ValidationError now use `kind` instead of `type` to report error types
   :markdown
diff --git a/lib/cast.js b/lib/cast.js
index 111c027f86a..9c63ee32a46 100644
--- a/lib/cast.js
+++ b/lib/cast.js
@@ -9,11 +9,10 @@ var Types = require('./schema/index');
  * Handles internal casting for queries
  *
  * @param {Schema} schema
- * @param {Object obj Object to cast
+ * @param {Object} obj Object to cast
  * @api private
  */
-
-var cast = module.exports = function(schema, obj) {
+module.exports = function cast(schema, obj) {
   var paths = Object.keys(obj),
       i = paths.length,
       any$conditionals,
@@ -128,29 +127,7 @@ var cast = module.exports = function(schema, obj) {
             value = value.$geometry.coordinates;
           }
 
-          (function _cast(val) {
-            if (Array.isArray(val)) {
-              val.forEach(function(item, i) {
-                if (Array.isArray(item) || utils.isObject(item)) {
-                  return _cast(item);
-                }
-                val[i] = numbertype.castForQuery(item);
-              });
-            } else {
-              var nearKeys = Object.keys(val);
-              var nearLen = nearKeys.length;
-              while (nearLen--) {
-                var nkey = nearKeys[nearLen];
-                var item = val[nkey];
-                if (Array.isArray(item) || utils.isObject(item)) {
-                  _cast(item);
-                  val[nkey] = item;
-                } else {
-                  val[nkey] = numbertype.castForQuery(item);
-                }
-              }
-            }
-          })(value);
+          _cast(value, numbertype);
         }
       } else if (val === null || val === undefined) {
         obj[path] = null;
@@ -201,3 +178,27 @@ var cast = module.exports = function(schema, obj) {
 
   return obj;
 };
+
+function _cast(val, numbertype) {
+  if (Array.isArray(val)) {
+    val.forEach(function(item, i) {
+      if (Array.isArray(item) || utils.isObject(item)) {
+        return _cast(item, numbertype);
+      }
+      val[i] = numbertype.castForQuery(item);
+    });
+  } else {
+    var nearKeys = Object.keys(val);
+    var nearLen = nearKeys.length;
+    while (nearLen--) {
+      var nkey = nearKeys[nearLen];
+      var item = val[nkey];
+      if (Array.isArray(item) || utils.isObject(item)) {
+        _cast(item, numbertype);
+        val[nkey] = item;
+      } else {
+        val[nkey] = numbertype.castForQuery(item);
+      }
+    }
+  }
+}
diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js
index 9038f0e38f7..38886d95d7c 100644
--- a/lib/drivers/node-mongodb-native/collection.js
+++ b/lib/drivers/node-mongodb-native/collection.js
@@ -100,6 +100,31 @@ NativeCollection.prototype.onClose = function() {
  * Copy the collection methods and make them subject to queues
  */
 
+function iter(i) {
+  NativeCollection.prototype[i] = function() {
+    if (this.buffer) {
+      this.addQueue(i, arguments);
+      return;
+    }
+
+    var collection = this.collection,
+        args = arguments,
+        _this = this,
+        debug = _this.conn.base.options.debug;
+
+    if (debug) {
+      if (typeof debug === 'function') {
+        debug.apply(debug
+            , [_this.name, i].concat(utils.args(args, 0, args.length - 1)));
+      } else {
+        this.$print(_this.name, i, args);
+      }
+    }
+
+    return collection[i].apply(collection, args);
+  };
+}
+
 for (var i in Collection.prototype) {
   // Janky hack to work around gh-3005 until we can get rid of the mongoose
   // collection abstraction
@@ -111,30 +136,7 @@ for (var i in Collection.prototype) {
     continue;
   }
 
-  (function(i) {
-    NativeCollection.prototype[i] = function() {
-      if (this.buffer) {
-        this.addQueue(i, arguments);
-        return;
-      }
-
-      var collection = this.collection,
-          args = arguments,
-          _this = this,
-          debug = _this.conn.base.options.debug;
-
-      if (debug) {
-        if (typeof debug === 'function') {
-          debug.apply(debug
-              , [_this.name, i].concat(utils.args(args, 0, args.length - 1)));
-        } else {
-          this.$print(_this.name, i, args);
-        }
-      }
-
-      return collection[i].apply(collection, args);
-    };
-  })(i);
+  iter(i);
 }
 
 /**
@@ -170,9 +172,21 @@ NativeCollection.prototype.$format = function(arg) {
  * Debug print helper
  */
 
+function map(o) {
+  return format(o, true);
+}
+function formatObjectId(x, key) {
+  var representation = 'ObjectId("' + x[key].toHexString() + '")';
+  x[key] = {inspect: function() { return representation; }};
+}
+function formatDate(x, key) {
+  var representation = 'new Date("' + x[key].toUTCString() + '")';
+  x[key] = {inspect: function() { return representation; }};
+}
 function format(obj, sub) {
   var x = utils.clone(obj, {retainKeyOrder: 1});
   var representation;
+
   if (x != null) {
     if (x.constructor.name === 'Binary') {
       x = '[object Buffer]';
@@ -194,19 +208,11 @@ function format(obj, sub) {
           } else if (x[key].constructor.name === 'Object') {
             x[key] = format(x[key], true);
           } else if (x[key].constructor.name === 'ObjectID') {
-            (function(x) {
-              var representation = 'ObjectId("' + x[key].toHexString() + '")';
-              x[key] = {inspect: function() { return representation; }};
-            })(x);
+            formatObjectId(x, key);
           } else if (x[key].constructor.name === 'Date') {
-            (function(x) {
-              var representation = 'new Date("' + x[key].toUTCString() + '")';
-              x[key] = {inspect: function() { return representation; }};
-            })(x);
+            formatDate(x, key);
           } else if (Array.isArray(x[key])) {
-            x[key] = x[key].map(function(o) {
-              return format(o, true);
-            });
+            x[key] = x[key].map(map);
           }
         }
       }
diff --git a/lib/model.js b/lib/model.js
index cfcfa233ff0..479546d37b9 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -2,8 +2,6 @@
  * Module dependencies.
  */
 
-/* eslint no-unused-vars: 1 */
-
 var Document = require('./document');
 var MongooseError = require('./error');
 var VersionError = MongooseError.VersionError;
@@ -421,6 +419,12 @@ function handleAtomics(self, where, delta, data, value) {
     return operand(self, where, delta, data, value);
   }
 
+  function iter(mem) {
+    return isMongooseObject(mem)
+        ? mem.toObject({depopulate: 1})
+        : mem;
+  }
+
   while (i--) {
     op = ops[i];
     val = atomics[op];
@@ -428,11 +432,7 @@ function handleAtomics(self, where, delta, data, value) {
     if (isMongooseObject(val)) {
       val = val.toObject({depopulate: 1});
     } else if (Array.isArray(val)) {
-      val = val.map(function(mem) {
-        return isMongooseObject(mem)
-            ? mem.toObject({depopulate: 1})
-            : mem;
-      });
+      val = val.map(iter);
     } else if (val.valueOf) {
       val = val.valueOf();
     }
@@ -780,8 +780,23 @@ Model.discriminator = function discriminator(name, schema) {
         '" cannot have field with name "' + key + '"');
   }
 
-  // merges base schema into new discriminator schema and sets new type field.
-  (function(schema, baseSchema) {
+  function clean(a, b) {
+    a = utils.clone(a);
+    b = utils.clone(b);
+    delete a.toJSON;
+    delete a.toObject;
+    delete b.toJSON;
+    delete b.toObject;
+    delete a._id;
+    delete b._id;
+
+    if (!utils.deepEqual(a, b)) {
+      throw new Error('Discriminator options are not customizable ' +
+          '(except toJSON, toObject, _id)');
+    }
+  }
+
+  function merge(schema, baseSchema) {
     utils.merge(schema, baseSchema);
 
     var obj = {};
@@ -794,21 +809,7 @@ Model.discriminator = function discriminator(name, schema) {
     }
 
     // throws error if options are invalid
-    (function(a, b) {
-      a = utils.clone(a);
-      b = utils.clone(b);
-      delete a.toJSON;
-      delete a.toObject;
-      delete b.toJSON;
-      delete b.toObject;
-      delete a._id;
-      delete b._id;
-
-      if (!utils.deepEqual(a, b)) {
-        throw new Error('Discriminator options are not customizable ' +
-            '(except toJSON, toObject, _id)');
-      }
-    })(schema.options, baseSchema.options);
+    clean(schema.options, baseSchema.options);
 
     var toJSON = schema.options.toJSON;
     var toObject = schema.options.toObject;
@@ -823,7 +824,10 @@ Model.discriminator = function discriminator(name, schema) {
 
     schema.callQueue = baseSchema.callQueue.concat(schema.callQueue.slice(schema._defaultMiddleware.length));
     schema._requiredpaths = undefined; // reset just in case Schema#requiredPaths() was called on either schema
-  })(schema, this.schema);
+  }
+
+  // merges base schema into new discriminator schema and sets new type field.
+  merge(schema, this.schema);
 
   if (!this.discriminators) {
     this.discriminators = {};
@@ -1335,6 +1339,7 @@ Model.distinct = function distinct(field, conditions, callback) {
  */
 
 Model.where = function where(path, val) {
+  void val; // eslint
   // get the mongodb collection object
   var mq = new Query({}, {}, this, this.collection).find({});
   return mq.where.apply(mq, arguments);
@@ -2128,21 +2133,24 @@ Model.geoNear = function(near, options, callback) {
       }
 
       var errSeen = false;
+
+      function init(err) {
+        if (err && !errSeen) {
+          errSeen = true;
+          reject(err);
+          callback && callback(err);
+          return;
+        }
+        if (--count <= 0) {
+          resolve(res.results, res.stats);
+          callback && callback(null, res.results, res.stats);
+        }
+      }
+
       for (var i = 0; i < res.results.length; i++) {
         var temp = res.results[i].obj;
         res.results[i].obj = new _this();
-        res.results[i].obj.init(temp, function(err) {
-          if (err && !errSeen) {
-            errSeen = true;
-            reject(err);
-            callback && callback(err);
-            return;
-          }
-          if (--count <= 0) {
-            resolve(res.results, res.stats);
-            callback && callback(null, res.results, res.stats);
-          }
-        });
+        res.results[i].obj.init(temp, init);
       }
     };
 
@@ -2303,21 +2311,24 @@ Model.geoSearch = function(conditions, options, callback) {
       }
 
       var errSeen = false;
+
+      function init(err) {
+        if (err && !errSeen) {
+          callback && callback(err);
+          reject(err);
+          return;
+        }
+
+        if (!--count && !errSeen) {
+          callback && callback(null, res.results, res.stats);
+          resolve(res.results, res.stats);
+        }
+      }
+
       for (var i = 0; i < res.results.length; i++) {
         var temp = res.results[i];
         res.results[i] = new _this();
-        res.results[i].init(temp, {}, function(err) {
-          if (err && !errSeen) {
-            callback && callback(err);
-            reject(err);
-            return;
-          }
-
-          if (!--count && !errSeen) {
-            callback && callback(null, res.results, res.stats);
-            resolve(res.results, res.stats);
-          }
-        });
+        res.results[i].init(temp, {}, init);
       }
     });
   });
@@ -2562,6 +2573,11 @@ function populate(model, docs, options, cb) {
     cb();
   });
 
+  function flatten(item) {
+    // no need to include undefined values in our query
+    return undefined !== item;
+  }
+
   var _remaining = len;
   for (i = 0; i < len; i++) {
     mod = modelsMap[i];
@@ -2573,10 +2589,7 @@ function populate(model, docs, options, cb) {
       match = {};
     }
 
-    var ids = utils.array.flatten(mod.ids, function(item) {
-      // no need to include undefined values in our query
-      return undefined !== item;
-    });
+    var ids = utils.array.flatten(mod.ids, flatten);
 
     ids = utils.array.unique(ids);
 
@@ -2793,13 +2806,15 @@ function assignVals(o) {
   var rawIds = o.rawIds;
   var options = o.options;
 
+  function setValue(val) {
+    return valueFilter(val, options);
+  }
+
   for (var i = 0; i < docs.length; ++i) {
     if (utils.getValue(path, docs[i]) == null) {
       continue;
     }
-    utils.setValue(path, rawIds[i], docs[i], function(val) {
-      return valueFilter(val, options);
-    });
+    utils.setValue(path, rawIds[i], docs[i], setValue);
   }
 }
 
@@ -3062,22 +3077,23 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
  * @param {Schema} schema
  */
 var applyMethods = function(model, schema) {
-  for (var i in schema.methods) {
-    if (typeof schema.methods[i] === 'function') {
-      model.prototype[i] = schema.methods[i];
+  function apply(method, schema) {
+    Object.defineProperty(model.prototype, method, {
+      get: function() {
+        var h = {};
+        for (var k in schema.methods[method]) {
+          h[k] = schema.methods[method][k].bind(this);
+        }
+        return h;
+      },
+      configurable: true
+    });
+  }
+  for (var method in schema.methods) {
+    if (typeof schema.methods[method] === 'function') {
+      model.prototype[method] = schema.methods[method];
     } else {
-      (function(_i) {
-        Object.defineProperty(model.prototype, _i, {
-          get: function() {
-            var h = {};
-            for (var k in schema.methods[_i]) {
-              h[k] = schema.methods[_i][k].bind(this);
-            }
-            return h;
-          },
-          configurable: true
-        });
-      })(i);
+      apply(method, schema);
     }
   }
 };
diff --git a/lib/query.js b/lib/query.js
index e8d39641c7b..865275784b5 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -1118,12 +1118,13 @@ function completeMany(model, docs, fields, self, pop, callback) {
   var opts = pop ?
   {populated: pop}
       : undefined;
+  function init(err) {
+    if (err) return callback(err);
+    --count || callback(null, arr);
+  }
   for (var i = 0; i < len; ++i) {
     arr[i] = helpers.createModel(model, docs[i], fields);
-    arr[i].init(docs[i], opts, function(err) {
-      if (err) return callback(err);
-      --count || callback(null, arr);
-    });
+    arr[i].init(docs[i], opts, init);
   }
 }
 
diff --git a/lib/querystream.js b/lib/querystream.js
index f62294ad9fa..25bcb9ebea7 100644
--- a/lib/querystream.js
+++ b/lib/querystream.js
@@ -155,7 +155,7 @@ QueryStream.prototype._next = function _next() {
 
   if (this._buffer && this._buffer.length) {
     var arg;
-    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
+    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) { // eslint-disable-line no-cond-assign
       this._onNextObject.apply(this, arg);
     }
   }
diff --git a/lib/schema.js b/lib/schema.js
index 80d6793e326..65812f0642c 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -1229,8 +1229,7 @@ Schema.prototype._getSchema = function(path) {
     return pathschema;
   }
 
-  // look for arrays
-  return (function search(parts, schema) {
+  function search(parts, schema) {
     var p = parts.length + 1,
         foundschema,
         trypath;
@@ -1263,7 +1262,10 @@ Schema.prototype._getSchema = function(path) {
         return foundschema;
       }
     }
-  })(path.split('.'), _this);
+  }
+
+  // look for arrays
+  return search(path.split('.'), _this);
 };
 
 /*!
diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js
index 2114b7331c3..b057ba3f4b4 100644
--- a/lib/schema/buffer.js
+++ b/lib/schema/buffer.js
@@ -145,14 +145,14 @@ function handleSingle(val) {
 
 SchemaBuffer.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$bitsAllClear': handleBitwiseOperator,
-      '$bitsAnyClear': handleBitwiseOperator,
-      '$bitsAllSet': handleBitwiseOperator,
-      '$bitsAnySet': handleBitwiseOperator,
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle
+      $bitsAllClear: handleBitwiseOperator,
+      $bitsAnyClear: handleBitwiseOperator,
+      $bitsAllSet: handleBitwiseOperator,
+      $bitsAnySet: handleBitwiseOperator,
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle
     });
 
 /**
diff --git a/lib/schema/date.js b/lib/schema/date.js
index 5ef36dde6ab..cea9af01d5a 100644
--- a/lib/schema/date.js
+++ b/lib/schema/date.js
@@ -246,10 +246,10 @@ function handleSingle(val) {
 
 SchemaDate.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle
     });
 
 
diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js
index 40b44e3565b..e41f6747525 100644
--- a/lib/schema/documentarray.js
+++ b/lib/schema/documentarray.js
@@ -97,6 +97,13 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
     // iterate over sparse elements yet reports array.length including
     // them :(
 
+    function callback(err) {
+      if (err) {
+        error = err;
+      }
+      --count || fn(error);
+    }
+
     for (var i = 0, len = count; i < len; ++i) {
       // sidestep sparse entries
       var doc = array[i];
@@ -108,19 +115,9 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
       // HACK: use $__original_validate to avoid promises so bluebird doesn't
       // complain
       if (doc.$__original_validate) {
-        doc.$__original_validate({__noPromise: true}, function(err) {
-          if (err) {
-            error = err;
-          }
-          --count || fn(error);
-        });
+        doc.$__original_validate({__noPromise: true}, callback);
       } else {
-        doc.validate({__noPromise: true}, function(err) {
-          if (err) {
-            error = err;
-          }
-          --count || fn(error);
-        });
+        doc.validate({__noPromise: true}, callback);
       }
     }
   }, scope);
diff --git a/lib/schema/number.js b/lib/schema/number.js
index 3f182a48637..d0485028540 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -248,15 +248,15 @@ function handleArray(val) {
 
 SchemaNumber.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$bitsAllClear': handleBitwiseOperator,
-      '$bitsAnyClear': handleBitwiseOperator,
-      '$bitsAllSet': handleBitwiseOperator,
-      '$bitsAnySet': handleBitwiseOperator,
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle,
-      '$mod': handleArray
+      $bitsAllClear: handleBitwiseOperator,
+      $bitsAnyClear: handleBitwiseOperator,
+      $bitsAllSet: handleBitwiseOperator,
+      $bitsAnySet: handleBitwiseOperator,
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle,
+      $mod: handleArray
     });
 
 /**
diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js
index 0dc212aa750..bad69fed638 100644
--- a/lib/schema/objectid.js
+++ b/lib/schema/objectid.js
@@ -151,10 +151,10 @@ function handleSingle(val) {
 
 ObjectId.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle
     });
 
 /**
diff --git a/lib/schema/string.js b/lib/schema/string.js
index 6157051baea..3bd6c818dc1 100644
--- a/lib/schema/string.js
+++ b/lib/schema/string.js
@@ -464,13 +464,13 @@ function handleArray(val) {
 
 SchemaString.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$all': handleArray,
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle,
-      '$options': handleSingle,
-      '$regex': handleSingle
+      $all: handleArray,
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle,
+      $options: handleSingle,
+      $regex: handleSingle
     });
 
 /**
diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js
index beb7c9bb543..fd1298914b2 100644
--- a/lib/services/updateValidators.js
+++ b/lib/services/updateValidators.js
@@ -114,12 +114,11 @@ module.exports = function(query, schema, castedDoc, options) {
   var numUpdates = updates.length;
   var validatorsToExecute = [];
   var validationErrors = [];
-  for (i = 0; i < numUpdates; ++i) {
-    (function(i) {
-      var schemaPath = schema._getSchema(updates[i]);
-      if (schemaPath) {
-        validatorsToExecute.push(function(callback) {
-          schemaPath.doValidate(
+  function iter(i) {
+    var schemaPath = schema._getSchema(updates[i]);
+    if (schemaPath) {
+      validatorsToExecute.push(function(callback) {
+        schemaPath.doValidate(
             updatedValues[updates[i]],
             function(err) {
               if (err) {
@@ -130,9 +129,11 @@ module.exports = function(query, schema, castedDoc, options) {
             },
             options && options.context === 'query' ? query : null,
             {updateValidator: true});
-        });
-      }
-    })(i);
+      });
+    }
+  }
+  for (i = 0; i < numUpdates; ++i) {
+    iter(i);
   }
 
   return function(callback) {
diff --git a/lib/types/array.js b/lib/types/array.js
index be1e40a2d97..83818fa9251 100644
--- a/lib/types/array.js
+++ b/lib/types/array.js
@@ -216,7 +216,7 @@ MongooseArray.mixin = {
           return v.toObject({virtuals: false});
         }));
       } else {
-        selector = pullOp['_id'] || (pullOp['_id'] = {'$in': []});
+        selector = pullOp['_id'] || (pullOp['_id'] = {$in: []});
         selector['$in'] = selector['$in'].concat(val);
       }
     } else {
@@ -522,9 +522,10 @@ MongooseArray.mixin = {
     while (i--) {
       mem = cur[i];
       if (mem instanceof Document) {
-        if (values.some(function(v) {
+        var some = values.some(function(v) {
           return v.equals(mem);
-        })) {
+        });
+        if (some) {
           [].splice.call(cur, i, 1);
         }
       } else if (~cur.indexOf.call(values, mem)) {
diff --git a/test/browser/schema.validation.test_.js b/test/browser/schema.validation.test_.js
index 1d2d0616231..09de999c8ee 100644
--- a/test/browser/schema.validation.test_.js
+++ b/test/browser/schema.validation.test_.js
@@ -416,11 +416,11 @@ describe('schema', function() {
           ferret: {
             type: Boolean,
             validate: [{
-              'validator': validator,
-              'msg': 'validator1'
+              validator: validator,
+              msg: 'validator1'
             }, {
-              'validator': validator,
-              'msg': 'validator2'
+              validator: validator,
+              msg: 'validator2'
             }]
           }
         });
@@ -596,11 +596,11 @@ describe('schema', function() {
           ferret: {
             type: Boolean,
             validate: [{
-              'validator': validator,
-              'msg': 'validator1'
+              validator: validator,
+              msg: 'validator1'
             }, {
-              'validator': validator,
-              'msg': 'validator2'
+              validator: validator,
+              msg: 'validator2'
             }]
           }
         });
diff --git a/test/browser/types.objectid.test_.js b/test/browser/types.objectid.test_.js
index da13d2b1442..67c9c33cf0f 100644
--- a/test/browser/types.objectid.test_.js
+++ b/test/browser/types.objectid.test_.js
@@ -1,93 +1,91 @@
-(function() {
-  var ObjectId = mongoose.Types.ObjectId;
-
-  describe('types.objectid', function() {
-    it('Should Correctly convert ObjectId to itself', function(done) {
-      var myObject, newObject;
-      var selfConvertion = function() {
-        myObject = new ObjectId();
-        newObject = ObjectId(myObject);
-      };
-
-      assert.doesNotThrow(selfConvertion);
-      assert.equal(myObject, newObject);
-      done();
-    });
+var ObjectId = mongoose.Types.ObjectId;
+
+describe('types.objectid', function() {
+  it('Should Correctly convert ObjectId to itself', function(done) {
+    var myObject, newObject;
+    var selfConvertion = function() {
+      myObject = new ObjectId();
+      newObject = ObjectId(myObject);
+    };
+
+    assert.doesNotThrow(selfConvertion);
+    assert.equal(myObject, newObject);
+    done();
+  });
 
-    it('ObjectId should correctly create objects', function(done) {
-      try {
-        ObjectId.createFromHexString('000000000000000000000001');
-        ObjectId.createFromHexString('00000000000000000000001');
-        assert.ok(false);
-      } catch (err) {
-        assert.ok(err !== null);
-      }
+  it('ObjectId should correctly create objects', function(done) {
+    try {
+      ObjectId.createFromHexString('000000000000000000000001');
+      ObjectId.createFromHexString('00000000000000000000001');
+      assert.ok(false);
+    } catch (err) {
+      assert.ok(err !== null);
+    }
 
-      done();
-    });
+    done();
+  });
 
-    it('ObjectId should correctly retrieve timestamp', function(done) {
-      var testDate = new Date();
-      var object1 = new ObjectId();
-      assert.equal(Math.floor(testDate.getTime() / 1000), Math.floor(object1.getTimestamp().getTime() / 1000));
+  it('ObjectId should correctly retrieve timestamp', function(done) {
+    var testDate = new Date();
+    var object1 = new ObjectId();
+    assert.equal(Math.floor(testDate.getTime() / 1000), Math.floor(object1.getTimestamp().getTime() / 1000));
 
-      done();
-    });
+    done();
+  });
 
-    it('ObjectId should have a correct cached representation of the hexString', function(done) {
-      ObjectId.cacheHexString = true;
-      var a = new ObjectId;
-      var __id = a.__id;
-      assert.equal(__id, a.toHexString());
-
-      // hexString
-      a = new ObjectId(__id);
-      assert.equal(__id, a.toHexString());
-
-      // fromHexString
-      a = ObjectId.createFromHexString(__id);
-      assert.equal(a.__id, a.toHexString());
-      assert.equal(__id, a.toHexString());
-
-      // number
-      var genTime = a.generationTime;
-      a = new ObjectId(genTime);
-      __id = a.__id;
-      assert.equal(__id, a.toHexString());
-
-      // generationTime
-      delete a.__id;
-      a.generationTime = genTime;
-      assert.equal(__id, a.toHexString());
-
-      // createFromTime
-      a = ObjectId.createFromTime(genTime);
-      __id = a.__id;
-      assert.equal(__id, a.toHexString());
-      ObjectId.cacheHexString = false;
-
-      done();
-    });
+  it('ObjectId should have a correct cached representation of the hexString', function(done) {
+    ObjectId.cacheHexString = true;
+    var a = new ObjectId;
+    var __id = a.__id;
+    assert.equal(__id, a.toHexString());
+
+    // hexString
+    a = new ObjectId(__id);
+    assert.equal(__id, a.toHexString());
+
+    // fromHexString
+    a = ObjectId.createFromHexString(__id);
+    assert.equal(a.__id, a.toHexString());
+    assert.equal(__id, a.toHexString());
+
+    // number
+    var genTime = a.generationTime;
+    a = new ObjectId(genTime);
+    __id = a.__id;
+    assert.equal(__id, a.toHexString());
+
+    // generationTime
+    delete a.__id;
+    a.generationTime = genTime;
+    assert.equal(__id, a.toHexString());
+
+    // createFromTime
+    a = ObjectId.createFromTime(genTime);
+    __id = a.__id;
+    assert.equal(__id, a.toHexString());
+    ObjectId.cacheHexString = false;
+
+    done();
+  });
 
-    it('Should fail to create ObjectId due to illegal hex code', function(done) {
-      assert.throws(function() {
-        new ObjectId('zzzzzzzzzzzzzzzzzzzzzzzz');
-      });
-      done();
+  it('Should fail to create ObjectId due to illegal hex code', function(done) {
+    assert.throws(function() {
+      new ObjectId('zzzzzzzzzzzzzzzzzzzzzzzz');
     });
+    done();
+  });
 
-    it('Should validate ObjectId', function(done) {
-      assert.equal(false, ObjectId.isValid(null));
-      assert.equal(false, ObjectId.isValid({}));
-      assert.equal(false, ObjectId.isValid([]));
-      assert.equal(false, ObjectId.isValid(true));
-      assert.equal(true, ObjectId.isValid(0));
-      assert.equal(false, ObjectId.isValid('invalid'));
-      assert.equal(true, ObjectId.isValid('zzzzzzzzzzzz'));
-      assert.equal(false, ObjectId.isValid('zzzzzzzzzzzzzzzzzzzzzzzz'));
-      assert.equal(true, ObjectId.isValid('000000000000000000000000'));
-
-      done();
-    });
+  it('Should validate ObjectId', function(done) {
+    assert.equal(false, ObjectId.isValid(null));
+    assert.equal(false, ObjectId.isValid({}));
+    assert.equal(false, ObjectId.isValid([]));
+    assert.equal(false, ObjectId.isValid(true));
+    assert.equal(true, ObjectId.isValid(0));
+    assert.equal(false, ObjectId.isValid('invalid'));
+    assert.equal(true, ObjectId.isValid('zzzzzzzzzzzz'));
+    assert.equal(false, ObjectId.isValid('zzzzzzzzzzzzzzzzzzzzzzzz'));
+    assert.equal(true, ObjectId.isValid('000000000000000000000000'));
+
+    done();
   });
-})();
+});
diff --git a/test/docs/defaults.test.js b/test/docs/defaults.test.js
index c6cd8712492..7a4d1893f44 100644
--- a/test/docs/defaults.test.js
+++ b/test/docs/defaults.test.js
@@ -80,7 +80,7 @@ describe('defaults docs', function () {
     var update = {title: 'The Terminator'};
     var options = {
       // Return the document after updates are applied
-      'new': true,
+      new: true,
       // Create a document if one isn't found. Required
       // for `setDefaultsOnInsert`
       upsert: true,
diff --git a/test/document.isselected.test.js b/test/document.isselected.test.js
index a1dfd406f5f..7ff0cd2e454 100644
--- a/test/document.isselected.test.js
+++ b/test/document.isselected.test.js
@@ -125,10 +125,10 @@ describe('document', function() {
     assert.ok(doc.isSelected('em.nonpath')); // not a path
 
     var selection = {
-      'test': 1,
-      'numbers': 1,
+      test: 1,
+      numbers: 1,
       'nested.deep': 1,
-      'oids': 1
+      oids: 1
     };
 
     doc = new TestDocument(undefined, selection);
@@ -192,7 +192,7 @@ describe('document', function() {
     assert.ok(!doc.isSelected('em.nonpath'));
 
     selection = {
-      'em': 0
+      em: 0
     };
 
     doc = new TestDocument(undefined, selection);
@@ -229,7 +229,7 @@ describe('document', function() {
     assert.ok(!doc.isSelected('em.nonpath'));
 
     selection = {
-      '_id': 0
+      _id: 0
     };
 
     doc = new TestDocument(undefined, selection);
@@ -270,7 +270,7 @@ describe('document', function() {
     assert.ok(doc.isSelected('em.nonpath'));
 
     selection = {
-      '_id': 1
+      _id: 1
     };
 
     doc = new TestDocument(undefined, selection);
@@ -301,8 +301,8 @@ describe('document', function() {
     assert.ok(doc.isSelected('em.nonpath'));
 
     selection = {
-      '_id': 1,
-      'n': 1
+      _id: 1,
+      n: 1
     };
 
     doc = new TestDocument(undefined, selection);
diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js
index 77e2982eef8..bba3c8f7e6b 100644
--- a/test/model.discriminator.querying.test.js
+++ b/test/model.discriminator.querying.test.js
@@ -606,7 +606,7 @@ describe('model', function() {
             assert.ifError(err);
             conversionEvent.save(function(err) {
               assert.ifError(err);
-              var query = ConversionEvent.findOneAndUpdate({name: 'Conversion event'}, {$set: {name: 'Conversion event - updated'}}, {'new': true});
+              var query = ConversionEvent.findOneAndUpdate({name: 'Conversion event'}, {$set: {name: 'Conversion event - updated'}}, {new: true});
               assert.deepEqual(query._conditions, {name: 'Conversion event', __t: 'model-discriminator-querying-conversion'});
               query.exec(function(err, document) {
                 assert.ifError(err);
@@ -631,7 +631,7 @@ describe('model', function() {
             assert.ifError(err);
             conversionEvent.save(function(err) {
               assert.ifError(err);
-              var query = BaseEvent.findOneAndUpdate({name: 'Conversion event'}, {$set: {name: 'Conversion event - updated'}}, {'new': true});
+              var query = BaseEvent.findOneAndUpdate({name: 'Conversion event'}, {$set: {name: 'Conversion event - updated'}}, {new: true});
               assert.deepEqual(query._conditions, {name: 'Conversion event'});
               query.exec(function(err, document) {
                 assert.ifError(err);
diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js
index 050f0c142e8..ca886c2a44f 100644
--- a/test/model.findOneAndUpdate.test.js
+++ b/test/model.findOneAndUpdate.test.js
@@ -121,11 +121,11 @@ describe('model: findOneAndUpdate:', function() {
           published: false, // becomes $set
           mixed: {x: 'ECKS', y: 'why'}, // $set
           $pullAll: {numbers: [4, 6]},
-          $pull: {'owners': id0},
+          $pull: {owners: id0},
           'comments.1.body': 8 // $set
         };
 
-        M.findOneAndUpdate({title: title}, update, {'new': true}, function(err, up) {
+        M.findOneAndUpdate({title: title}, update, {new: true}, function(err, up) {
           db.close();
           assert.equal(err, null, err && err.stack);
 
@@ -457,12 +457,14 @@ describe('model: findOneAndUpdate:', function() {
     post.save(function(err) {
       assert.ifError(err);
 
+      function callback(err) {
+        assert.ifError(err);
+        --totalDocs || complete();
+      }
+
       for (var i = 0; i < 4; ++i) {
         BlogPost
-        .findOneAndUpdate({_id: post._id}, {$inc: {'meta.visitors': 1}}, function(err) {
-          assert.ifError(err);
-          --totalDocs || complete();
-        });
+        .findOneAndUpdate({_id: post._id}, {$inc: {'meta.visitors': 1}}, callback);
       }
 
       function complete() {
@@ -484,7 +486,7 @@ describe('model: findOneAndUpdate:', function() {
     s.save(function(err) {
       assert.ifError(err);
       var name = Date.now();
-      S.findOneAndUpdate({name: name}, {ignore: true}, {upsert: true, 'new': true}, function(err, doc) {
+      S.findOneAndUpdate({name: name}, {ignore: true}, {upsert: true, new: true}, function(err, doc) {
         assert.ifError(err);
         assert.ok(doc);
         assert.ok(doc._id);
@@ -796,7 +798,7 @@ describe('model: findByIdAndUpdate:', function() {
       assert.ifError(err);
 
       B
-      .findByIdAndUpdate(doc._id, {title: 'woot'}, {'new': true})
+      .findByIdAndUpdate(doc._id, {title: 'woot'}, {new: true})
       .select({title: 1, ids: {$elemMatch: {$in: [_id2.toString()]}}})
       .exec(function(err, found) {
         assert.ifError(err);
@@ -845,17 +847,17 @@ describe('model: findByIdAndUpdate:', function() {
       _id: String,
       flag: {
         type: Boolean,
-        'default': false
+        default: false
       }
     });
 
     var Thing = db.model('Thing', thingSchema);
     var key = 'some-id';
 
-    Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, 'new': false}).exec(function(err, thing) {
+    Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, new: false}).exec(function(err, thing) {
       assert.ifError(err);
       assert.equal(null, thing);
-      Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, 'new': false}).exec(function(err, thing2) {
+      Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, new: false}).exec(function(err, thing2) {
         assert.ifError(err);
         assert.equal(key, thing2.id);
         assert.equal(false, thing2.flag);
@@ -877,7 +879,7 @@ describe('model: findByIdAndUpdate:', function() {
       if (err) {
         return done(err);
       }
-      Thing.findOneAndUpdate({_id: thing._id}, {name: null}, {'new': true})
+      Thing.findOneAndUpdate({_id: thing._id}, {name: null}, {new: true})
       .exec(function(err, doc) {
         if (err) {
           return done(err);
@@ -896,7 +898,7 @@ describe('model: findByIdAndUpdate:', function() {
       if (err) {
         return done(err);
       }
-      M.findByIdAndUpdate(doc._id, {change: true}, {overwrite: true, 'new': true}, function(err, doc) {
+      M.findByIdAndUpdate(doc._id, {change: true}, {overwrite: true, new: true}, function(err, doc) {
         if (err) {
           return done(err);
         }
@@ -930,7 +932,7 @@ describe('model: findByIdAndUpdate:', function() {
         Account.findOneAndUpdate(
             {name: 'parent'},
             {$push: {contacts: {account: a2._id, name: 'child'}}},
-            {'new': true},
+            {new: true},
             function(error, doc) {
               assert.ifError(error);
               assert.ok(Utils.deepEqual(doc.contacts[0].account, a2._id));
@@ -1035,7 +1037,7 @@ describe('model: findByIdAndUpdate:', function() {
     var Breakfast = db.model('gh2947', s);
     var q = Breakfast.findOneAndUpdate({},
         {notInSchema: {a: 1}, test: 'abc'},
-        {'new': true, strict: true, upsert: true});
+        {new: true, strict: true, upsert: true});
 
     q.lean();
     q.exec(function(error, doc) {
@@ -1124,7 +1126,7 @@ describe('model: findByIdAndUpdate:', function() {
       });
       var Breakfast = db.model('fam-gh-860-0', s);
 
-      var updateOptions = {upsert: true, setDefaultsOnInsert: true, 'new': true};
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true, new: true};
       Breakfast.findOneAndUpdate(
           {},
           {base: 'eggs'},
@@ -1150,7 +1152,7 @@ describe('model: findByIdAndUpdate:', function() {
       });
       var Breakfast = db.model('fam-gh-860-1', s);
 
-      var updateOptions = {upsert: true, setDefaultsOnInsert: true, 'new': true};
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true, new: true};
       Breakfast.findOneAndUpdate(
           {topping: 'sausage'},
           {base: 'eggs'},
@@ -1173,7 +1175,7 @@ describe('model: findByIdAndUpdate:', function() {
       });
       var Breakfast = db.model('fam-gh-860-2', s);
 
-      var updateOptions = {upsert: true, setDefaultsOnInsert: true, 'new': true};
+      var updateOptions = {upsert: true, setDefaultsOnInsert: true, new: true};
       Breakfast.findOneAndUpdate(
           {topping: {$ne: 'sausage'}},
           {base: 'eggs'},
@@ -1213,7 +1215,7 @@ describe('model: findByIdAndUpdate:', function() {
         upsert: true,
         setDefaultsOnInsert: true,
         runValidators: true,
-        'new': true
+        new: true
       };
       Breakfast.findOneAndUpdate(
           {},
@@ -1245,7 +1247,7 @@ describe('model: findByIdAndUpdate:', function() {
       });
       var Breakfast = db.model('fam-gh-860-4', s);
 
-      var updateOptions = {runValidators: true, 'new': true};
+      var updateOptions = {runValidators: true, new: true};
       Breakfast.findOneAndUpdate(
           {},
           {$unset: {steak: ''}, $setOnInsert: {eggs: 'softboiled'}},
@@ -1273,7 +1275,7 @@ describe('model: findByIdAndUpdate:', function() {
       });
       var Breakfast = db.model('fam-gh-860-5', s);
 
-      var updateOptions = {runValidators: true, 'new': true};
+      var updateOptions = {runValidators: true, new: true};
       Breakfast.findOneAndUpdate(
           {},
           {$set: {steak: 'ribeye', eggs: 3, bacon: '3 strips'}},
@@ -1321,7 +1323,7 @@ describe('model: findByIdAndUpdate:', function() {
       });
       var Breakfast = db.model('fam-gh-860-6', s);
 
-      var updateOptions = {runValidators: true, 'new': true};
+      var updateOptions = {runValidators: true, new: true};
       Breakfast.findOneAndUpdate(
           {},
           {$set: {steak: 'tofu', eggs: 2, bacon: '3 strips'}},
@@ -1346,7 +1348,7 @@ describe('model: findByIdAndUpdate:', function() {
       });
       var Breakfast = db.model('fam-gh-860-7', s);
 
-      var updateOptions = {runValidators: true, upsert: true, 'new': true};
+      var updateOptions = {runValidators: true, upsert: true, new: true};
       Breakfast.findOneAndUpdate(
           {},
           {$inc: {eggs: 1}},
@@ -1442,7 +1444,7 @@ describe('model: findByIdAndUpdate:', function() {
 
       var TestModel = db.model('gh3107', testSchema);
       TestModel
-      .findOneAndUpdate({id: '1'}, {$setOnInsert: {a: [{foo: 'bar'}], b: [2]}}, {upsert: true, 'new': true, setDefaultsOnInsert: true},
+      .findOneAndUpdate({id: '1'}, {$setOnInsert: {a: [{foo: 'bar'}], b: [2]}}, {upsert: true, new: true, setDefaultsOnInsert: true},
           function(error, doc) {
             assert.ifError(error);
             assert.equal(doc.a.length, 1);
@@ -1462,7 +1464,7 @@ describe('model: findByIdAndUpdate:', function() {
 
       var TestModel = db.model('gh3173', testSchema);
 
-      TestModel.findOneAndUpdate({}, {$set: {test: 'abc'}}, {upsert: true, 'new': true, passRawResult: true}).
+      TestModel.findOneAndUpdate({}, {$set: {test: 'abc'}}, {upsert: true, new: true, passRawResult: true}).
       exec(function(error, doc, res) {
         assert.ifError(error);
         assert.ok(res);
@@ -1495,7 +1497,7 @@ describe('model: findByIdAndUpdate:', function() {
         Shift.findOneAndUpdate({userId: 'tom'}, {
           records: [{kind: 'kind1', amount: NaN}]
         }, {
-          'new': true
+          new: true
         }, function(error) {
           assert.ok(error);
           assert.ok(error instanceof CastError);
@@ -1530,7 +1532,7 @@ describe('model: findByIdAndUpdate:', function() {
       MyModel.create({nested: {arr: [{num: 5}]}}, function(error) {
         assert.ifError(error);
         var update = {$pull: {'nested.arr': {num: 5}}};
-        var options = {'new': true};
+        var options = {new: true};
         MyModel.findOneAndUpdate({}, update, options, function(error, doc) {
           assert.ifError(error);
           assert.equal(doc.nested.arr.length, 0);
diff --git a/test/model.geosearch.test.js b/test/model.geosearch.test.js
index 1bf695931d4..7bdda83e942 100644
--- a/test/model.geosearch.test.js
+++ b/test/model.geosearch.test.js
@@ -14,7 +14,7 @@ var schema = new Schema({
   complex: {},
   type: String
 });
-schema.index({'pos': 'geoHaystack', type: 1}, {bucketSize: 1});
+schema.index({pos: 'geoHaystack', type: 1}, {bucketSize: 1});
 
 function getModel(db) {
   return db.model('GeoSearch', schema, 'geosearch-' + random());
diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js
index a67b05be9f5..1538a34283d 100644
--- a/test/model.indexes.test.js
+++ b/test/model.indexes.test.js
@@ -70,18 +70,20 @@ describe('model', function() {
         UserModel.collection.getIndexes(function(err, indexes) {
           assert.ifError(err);
 
+          function iter(index) {
+            if (index[0] === 'name') {
+              assertions++;
+            }
+            if (index[0] === 'blogposts._id') {
+              assertions++;
+            }
+            if (index[0] === 'blogposts.title') {
+              assertions++;
+            }
+          }
+
           for (var i in indexes) {
-            indexes[i].forEach(function(index) {
-              if (index[0] === 'name') {
-                assertions++;
-              }
-              if (index[0] === 'blogposts._id') {
-                assertions++;
-              }
-              if (index[0] === 'blogposts.title') {
-                assertions++;
-              }
-            });
+            indexes[i].forEach(iter);
           }
 
           assert.equal(3, assertions);
@@ -111,24 +113,26 @@ describe('model', function() {
         UserModel.collection.getIndexes(function(err, indexes) {
           assert.ifError(err);
 
+          function iter(index) {
+            if (index[0] === 'name') {
+              ++assertions;
+            }
+            if (index[0] === 'blogposts._id') {
+              ++assertions;
+            }
+            if (index[0] === 'blogposts.title') {
+              ++assertions;
+            }
+            if (index[0] === 'featured._id') {
+              ++assertions;
+            }
+            if (index[0] === 'featured.title') {
+              ++assertions;
+            }
+          }
+
           for (var i in indexes) {
-            indexes[i].forEach(function(index) {
-              if (index[0] === 'name') {
-                ++assertions;
-              }
-              if (index[0] === 'blogposts._id') {
-                ++assertions;
-              }
-              if (index[0] === 'blogposts.title') {
-                ++assertions;
-              }
-              if (index[0] === 'featured._id') {
-                ++assertions;
-              }
-              if (index[0] === 'featured.title') {
-                ++assertions;
-              }
-            });
+            indexes[i].forEach(iter);
           }
 
           assert.equal(5, assertions);
@@ -284,16 +288,21 @@ describe('model', function() {
             return index();
           }
           var pending = neededKittens - n;
+
+          function callback(err) {
+            assert.ifError(err);
+            if (--pending) {
+              return;
+            }
+            index();
+          }
+
+          function iter(i) {
+            K.create({name: 'kitten' + i, furryness: i}, callback);
+          }
+
           for (var i = n; i < neededKittens; ++i) {
-            (function(i) {
-              K.create({name: 'kitten' + i, furryness: i}, function(err) {
-                assert.ifError(err);
-                if (--pending) {
-                  return;
-                }
-                index();
-              });
-            })(i);
+            iter(i);
           }
         });
 
diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js
index 096fe4d9e82..d58ab1a4e1e 100644
--- a/test/model.mapreduce.test.js
+++ b/test/model.mapreduce.test.js
@@ -142,7 +142,7 @@ describe('model: mapreduce:', function() {
             assert.equal('nathan', docs[3]._id);
 
             // update casting works
-            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {'new': true}, function(err, doc) {
+            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {new: true}, function(err, doc) {
               assert.ifError(err);
               assert.ok(doc);
               assert.equal('aaron', doc._id);
@@ -333,7 +333,7 @@ describe('model: mapreduce:', function() {
             assert.equal('nathan', docs[3]._id);
 
             // update casting works
-            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {'new': true}, function(err, doc) {
+            ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {new: true}, function(err, doc) {
               assert.ifError(err);
               assert.ok(doc);
               assert.equal('aaron', doc._id);
diff --git a/test/model.populate.setting.test.js b/test/model.populate.setting.test.js
index 821ecd34915..60a8050fb84 100644
--- a/test/model.populate.setting.test.js
+++ b/test/model.populate.setting.test.js
@@ -26,10 +26,10 @@ var posts = 'blogposts_' + random(),
 describe('model: populate:', function() {
   describe('setting populated paths (gh-570)', function() {
     var types = {
-      'ObjectId': DocObjectId,
-      'String': String,
-      'Number': Number,
-      'Buffer': Buffer
+      ObjectId: DocObjectId,
+      String: String,
+      Number: Number,
+      Buffer: Buffer
     };
 
     var construct = {};
diff --git a/test/model.populate.test.js b/test/model.populate.test.js
index 1b8c3c1a200..a74bc69ebdf 100644
--- a/test/model.populate.test.js
+++ b/test/model.populate.test.js
@@ -2283,7 +2283,7 @@ describe('model: populate:', function() {
         select: 'name',
         model: 'RefAlternateUser',
         match: {name: /u/},
-        options: {sort: {'name': -1}}
+        options: {sort: {name: -1}}
       })
       .exec(function(err, post) {
         assert.ifError(err);
diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js
index de89a9d3304..e1610db5d55 100644
--- a/test/model.query.casting.test.js
+++ b/test/model.query.casting.test.js
@@ -52,7 +52,7 @@ var collection = 'blogposts_' + random();
 
 var geoSchemaArray = new Schema({loc: {type: [Number], index: '2d'}});
 var geoSchemaObject = new Schema({loc: {long: Number, lat: Number}});
-geoSchemaObject.index({'loc': '2d'});
+geoSchemaObject.index({loc: '2d'});
 
 describe('model query casting', function() {
   it('works', function(done) {
diff --git a/test/model.querying.test.js b/test/model.querying.test.js
index 358dd72d084..7d7042c6cf1 100644
--- a/test/model.querying.test.js
+++ b/test/model.querying.test.js
@@ -2233,7 +2233,8 @@ describe('geo-spatial', function() {
           return;
         }
         if (err) {
-          return done(complete.ran = err);
+          done(complete.ran = err);
+          return;
         }
         --pending || test();
       };
@@ -2247,7 +2248,7 @@ describe('geo-spatial', function() {
       var test = function() {
         var q = new Query({}, {}, null, Test.collection);
         q.find({
-          'loc': {
+          loc: {
             $nearSphere: {
               $geometry: {type: 'Point', coordinates: [30, 40]},
               $maxDistance: 10000000
@@ -2274,7 +2275,8 @@ describe('geo-spatial', function() {
           return;
         }
         if (err) {
-          return done(complete.ran = err);
+          done(complete.ran = err);
+          return;
         }
         --pending || test();
       }
diff --git a/test/model.test.js b/test/model.test.js
index 30b5e313e7e..7bbff34a169 100644
--- a/test/model.test.js
+++ b/test/model.test.js
@@ -3074,7 +3074,7 @@ describe('Model', function() {
           b.save(function(err) {
             assert.ifError(err);
 
-            B.findByIdAndUpdate({_id: b._id}, {$set: {comments: [{title: 'a'}]}}, {'new': true}, function(err, doc) {
+            B.findByIdAndUpdate({_id: b._id}, {$set: {comments: [{title: 'a'}]}}, {new: true}, function(err, doc) {
               assert.ifError(err);
               doc.comments[0].title = 'differ';
               doc.comments[0].remove();
@@ -4630,7 +4630,7 @@ describe('Model', function() {
 
       var DefaultTestObject = db.model('defaultTestObject',
           new Schema({
-            score: {type: Number, 'default': 55}
+            score: {type: Number, default: 55}
           })
       );
 
@@ -4936,7 +4936,7 @@ describe('Model', function() {
           }
         };
 
-        Person.findByIdAndUpdate(p._id, updates, {'new': true}, function(err, personDoc) {
+        Person.findByIdAndUpdate(p._id, updates, {new: true}, function(err, personDoc) {
           assert.ifError(err);
 
           assert.equal(personDoc.loc[0], updates.$set.loc[0]);
diff --git a/test/model.update.test.js b/test/model.update.test.js
index 569c6d55dd5..332fc904e1c 100644
--- a/test/model.update.test.js
+++ b/test/model.update.test.js
@@ -129,9 +129,9 @@ describe('model: update:', function() {
         $inc: {'meta.visitors': 2},
         $set: {date: new Date},
         published: false, // becomes $set
-        'mixed': {x: 'ECKS', y: 'why'}, // $set
-        $pullAll: {'numbers': [4, 6]},
-        $pull: {'owners': id0},
+        mixed: {x: 'ECKS', y: 'why'}, // $set
+        $pullAll: {numbers: [4, 6]},
+        $pull: {owners: id0},
         'comments.1.body': 8 // $set
       };
 
@@ -376,7 +376,7 @@ describe('model: update:', function() {
     var owner = last.owners[0];
 
     var update = {
-      $addToSet: {'owners': owner}
+      $addToSet: {owners: owner}
     };
 
     BlogPost.update({_id: post._id}, update, function(err) {
@@ -400,7 +400,7 @@ describe('model: update:', function() {
         newowner = new DocumentObjectId;
 
     var update = {
-      $addToSet: {'owners': {$each: [owner, newowner]}}
+      $addToSet: {owners: {$each: [owner, newowner]}}
     };
 
     BlogPost.update({_id: post._id}, update, function(err) {
@@ -422,7 +422,7 @@ describe('model: update:', function() {
         BlogPost = db.model('BlogPostForUpdates', collection);
 
     var update = {
-      $pop: {'owners': -1},
+      $pop: {owners: -1},
       $unset: {title: 1}
     };
 
@@ -560,12 +560,13 @@ describe('model: update:', function() {
 
     post.save(function(err) {
       assert.ifError(err);
+      function callback(err) {
+        assert.ifError(err);
+        --totalDocs || complete();
+      }
       for (var i = 0; i < 4; ++i) {
         BlogPost
-        .update({_id: post._id}, {$inc: {'meta.visitors': 1}}, function(err) {
-          assert.ifError(err);
-          --totalDocs || complete();
-        });
+        .update({_id: post._id}, {$inc: {'meta.visitors': 1}}, callback);
       }
     });
   });
@@ -1574,7 +1575,7 @@ describe('model: update:', function() {
       MyModel.findOneAndUpdate(
           {_id: doc._id, 'children._id': 1},
           {$set: {'children.$': {_id: 2}}},
-          {'new': true},
+          {new: true},
           function(error, doc) {
             assert.ifError(error);
             assert.equal(doc.children[0]._id, 2);
@@ -1592,7 +1593,7 @@ describe('model: update:', function() {
     Model.create({}, function(error, m) {
       assert.ifError(error);
       Model.
-      update({_id: m._id}, {'$push': {'myArr': {'key': 'Value'}}}).
+      update({_id: m._id}, {$push: {myArr: {key: 'Value'}}}).
       exec(function(error, res) {
         assert.ifError(error);
         assert.equal(res.n, 1);
@@ -1609,7 +1610,7 @@ describe('model: update:', function() {
 
     Model.create({}, function(error, m) {
       assert.ifError(error);
-      var update = {'$push': {'attributes.scores.bar': {a: 1}}};
+      var update = {$push: {'attributes.scores.bar': {a: 1}}};
       Model.
       update({_id: m._id}, update).
       exec(function(error, res) {
diff --git a/test/schema.select.test.js b/test/schema.select.test.js
index df941d19727..4180d7d9ebc 100644
--- a/test/schema.select.test.js
+++ b/test/schema.select.test.js
@@ -170,7 +170,7 @@ describe('schema select option', function() {
           });
         });
         it('with findOneAndUpdate', function(done) {
-          S.findOneAndUpdate({_id: s._id}, {name: 'changed'}, {'new': true}).select('thin name docs.bool docs.name').exec(function(err, s) {
+          S.findOneAndUpdate({_id: s._id}, {name: 'changed'}, {new: true}).select('thin name docs.bool docs.name').exec(function(err, s) {
             assert.ifError(err);
             assert.strictEqual(true, s.isSelected('name'));
             assert.strictEqual(true, s.isSelected('thin'));
@@ -184,7 +184,7 @@ describe('schema select option', function() {
           });
         });
         it('for findByIdAndUpdate', function(done) {
-          S.findByIdAndUpdate(s, {thin: false}, {'new': true}).select('-name -docs.name').exec(function(err, s) {
+          S.findByIdAndUpdate(s, {thin: false}, {new: true}).select('-name -docs.name').exec(function(err, s) {
             assert.strictEqual(null, err);
             assert.equal(false, s.isSelected('name'));
             assert.equal(true, s.isSelected('thin'));
@@ -240,7 +240,7 @@ describe('schema select option', function() {
           });
         });
         it('with findOneAndUpdate', function(done) {
-          E.findOneAndUpdate({_id: e._id}, {name: 'changed'}, {'new': true}).select('thin name docs.name docs.bool').exec(function(err, e) {
+          E.findOneAndUpdate({_id: e._id}, {name: 'changed'}, {new: true}).select('thin name docs.name docs.bool').exec(function(err, e) {
             assert.strictEqual(null, err);
             assert.equal(true, e.isSelected('name'));
             assert.equal(true, e.isSelected('thin'));
diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js
index 6a58e21d43f..6729a08fb34 100644
--- a/test/schema.timestamps.test.js
+++ b/test/schema.timestamps.test.js
@@ -76,7 +76,7 @@ describe('schema options.timestamps', function() {
     });
 
     it('should have fields when create with findOneAndUpdate', function(done) {
-      Cat.findOneAndUpdate({name: 'notexistname'}, {$set: {}}, {upsert: true, 'new': true}, function(err, doc) {
+      Cat.findOneAndUpdate({name: 'notexistname'}, {$set: {}}, {upsert: true, new: true}, function(err, doc) {
         assert.ok(doc.createdAt);
         assert.ok(doc.updatedAt);
         assert.ok(doc.createdAt.getTime() === doc.updatedAt.getTime());
@@ -98,7 +98,7 @@ describe('schema options.timestamps', function() {
     it('should change updatedAt when findOneAndUpdate', function(done) {
       Cat.findOne({name: 'newcat'}, function(err, doc) {
         var old = doc.updatedAt;
-        Cat.findOneAndUpdate({name: 'newcat'}, {$set: {hobby: 'fish'}}, {'new': true}, function(err, doc) {
+        Cat.findOneAndUpdate({name: 'newcat'}, {$set: {hobby: 'fish'}}, {new: true}, function(err, doc) {
           assert.ok(doc.updatedAt.getTime() > old.getTime());
           done();
         });
diff --git a/test/types.array.test.js b/test/types.array.test.js
index 0b7892d26b2..73638a6ff34 100644
--- a/test/types.array.test.js
+++ b/test/types.array.test.js
@@ -117,7 +117,8 @@ describe('types array', function() {
     function save(doc, cb) {
       doc.save(function(err) {
         if (err) {
-          return cb(err);
+          cb(err);
+          return;
         }
         doc.constructor.findById(doc._id, cb);
       });
@@ -1212,7 +1213,8 @@ describe('types array', function() {
     function save(doc, cb) {
       doc.save(function(err) {
         if (err) {
-          return cb(err);
+          cb(err);
+          return;
         }
         doc.constructor.findById(doc._id, cb);
       });
diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js
index 02aeb2420a9..c4fe683a7d6 100644
--- a/test/types.buffer.test.js
+++ b/test/types.buffer.test.js
@@ -1,4 +1,3 @@
-
 /**
  * Module dependencies.
  */
@@ -122,9 +121,9 @@ describe('types.buffer', function() {
           var user = users[0];
           var base64 = sampleBuffer.toString('base64');
           assert.equal(base64,
-                       user.serial.toString('base64'), 'buffer mismatch');
+              user.serial.toString('base64'), 'buffer mismatch');
           assert.equal(base64,
-                       user.required.toString('base64'), 'buffer mismatch');
+              user.required.toString('base64'), 'buffer mismatch');
           done();
         });
       });
@@ -160,7 +159,7 @@ describe('types.buffer', function() {
             var expectedBuffer = new Buffer([123, 97, 97, 42, 11]);
 
             assert.equal(expectedBuffer.toString('base64'),
-                         user.serial.toString('base64'), 'buffer mismatch');
+                user.serial.toString('base64'), 'buffer mismatch');
 
             assert.equal(false, tj.isModified('required'));
             tj.serial.copy(tj.required, 1);
@@ -419,9 +418,15 @@ describe('types.buffer', function() {
       var b = new B({buf: new Buffer('hi')});
       b.buf.subtype(128);
       b.save(function(err) {
-        if (err) return done(err);
+        if (err) {
+          done(err);
+          return;
+        }
         B.findById(b, function(err, doc) {
-          if (err) return done(err);
+          if (err) {
+            done(err);
+            return;
+          }
           assert.equal(128, doc.buf._subtype);
           done();
         });
@@ -432,15 +437,27 @@ describe('types.buffer', function() {
       var b = new B({buf: new Buffer('hi')});
       b.buf.subtype(128);
       b.save(function(err) {
-        if (err) return done(err);
+        if (err) {
+          done(err);
+          return;
+        }
         B.findById(b, function(err, doc) {
-          if (err) return done(err);
+          if (err) {
+            done(err);
+            return;
+          }
           assert.equal(128, doc.buf._subtype);
           doc.buf.subtype(0);
           doc.save(function(err) {
-            if (err) return done(err);
+            if (err) {
+              done(err);
+              return;
+            }
             B.findById(b, function(err, doc) {
-              if (err) return done(err);
+              if (err) {
+                done(err);
+                return;
+              }
               assert.strictEqual(0, doc.buf._subtype);
               done();
             });

From 474c68724d3785c004d3010c6d70f00ebc9e1386 Mon Sep 17 00:00:00 2001
From: Dmitriy Drenkalyuk 
Date: Wed, 3 Feb 2016 13:45:55 +0200
Subject: [PATCH 0251/2240] Fixed typo.

---
 docs/connections.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/connections.jade b/docs/connections.jade
index 1ba6b01580d..d744203dc4b 100644
--- a/docs/connections.jade
+++ b/docs/connections.jade
@@ -56,7 +56,7 @@ block content
   h4#keepAlive A note about keepAlive
   .important
     :markdown
-      For long running applictions it is often prudent to enable `keepAlive`
+      For long running applications, it is often prudent to enable `keepAlive`
       with a number of milliseconds. Without it, after some period of time
       you may start to see `"connection closed"` errors for what seems like
       no reason. If so, after

From 8a1752336bcf12f19e46103514f3323f46c4cd3f Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 10:37:20 -0500
Subject: [PATCH 0252/2240] docs: wrong function name in changelog #723

---
 History.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/History.md b/History.md
index 99d501fb6a8..24f35c158c1 100644
--- a/History.md
+++ b/History.md
@@ -14,7 +14,7 @@
  * feat: connect, open, openSet, and disconnect return ES2015 promises #3790 #3622 [TrejGun](https://github.com/TrejGun)
  * feat: custom type for int32 via mongoose-int32 npm package #3652 #3102
  * feat: basic custom schema type API #995
- * feat(model): `insertAll()` for more performant bulk inserts #723
+ * feat(model): `insertMany()` for more performant bulk inserts #723
 
 4.3.7 / 2016-01-23
 ==================

From 559fa6c0ff68f8b836ddb6f44f047948a9a5cc03 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 15:39:43 -0500
Subject: [PATCH 0253/2240] chore: now working on 4.4.1

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index ad1a624f6f4..7ca7a6a2c04 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.4.0",
+  "version": "4.4.1-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From dc9612a5af412dc6f66365945b9acc67cccd578b Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 16:35:03 -0500
Subject: [PATCH 0254/2240] fix: backwards compat for connect() #3790 (Fix
 #3847)

---
 lib/index.js       | 46 +++++++++++++++++++++++++++++++++++++++++-----
 test/index.test.js | 25 +++++++++++++++++++++++--
 2 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/lib/index.js b/lib/index.js
index 826ff12ea12..5f1c90fd957 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -230,12 +230,13 @@ Mongoose.prototype.createConnection = function(uri, options) {
 
 Mongoose.prototype.connect = function() {
   var conn = this.connection;
-
   if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) {
-    return conn.openSet.apply(conn, arguments);
+    this.$opPromise = conn.openSet.apply(conn, arguments);
+    return this;
   }
 
-  return conn.open.apply(conn, arguments);
+  this.$opPromise = conn.open.apply(conn, arguments);
+  return this;
 };
 
 /**
@@ -248,7 +249,6 @@ Mongoose.prototype.connect = function() {
 
 Mongoose.prototype.disconnect = function(fn) {
   var error;
-
   this.connections.forEach(function(conn) {
     conn.close(function(err) {
       if (error) {
@@ -261,7 +261,7 @@ Mongoose.prototype.disconnect = function(fn) {
   });
 
   var Promise = PromiseProvider.get();
-  return new Promise.ES6(function(resolve, reject) {
+  this.$opPromise = new Promise.ES6(function(resolve, reject) {
     fn && fn(error);
     if (error) {
       reject(error);
@@ -269,6 +269,42 @@ Mongoose.prototype.disconnect = function(fn) {
     }
     resolve();
   });
+  return this;
+};
+
+/**
+ * Ability to use mongoose object as a pseudo-promise so `.connect().then()`
+ * and `.disconnect().then()` are viable.
+ *
+ * @param {Function} onFulfilled
+ * @param {Function} onRejected
+ * @return {Promise}
+ * @api public
+ */
+
+Mongoose.prototype.then = function(onFulfilled, onRejected) {
+  var Promise = PromiseProvider.get();
+  if (!this.$opPromise) {
+    return new Promise.ES6(function(resolve, reject) {
+      reject(new Error('Can only call `.then()` if connect() or disconnect() ' +
+        'has been called'));
+    }).then(onFulfilled, onRejected);
+  }
+  return this.$opPromise.then(onFulfilled, onRejected);
+};
+
+/**
+ * Ability to use mongoose object as a pseudo-promise so `.connect().then()`
+ * and `.disconnect().then()` are viable.
+ *
+ * @param {Function} onFulfilled
+ * @param {Function} onRejected
+ * @return {Promise}
+ * @api public
+ */
+
+Mongoose.prototype.catch = function(onRejected) {
+  return this.then(null, onRejected);
 };
 
 /**
diff --git a/test/index.test.js b/test/index.test.js
index e693c82ff0f..25e80077565 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -37,6 +37,16 @@ describe('mongoose module:', function() {
         });
       });
     });
+
+    it('with promise (gh-3790)', function(done) {
+      var goose = new Mongoose;
+      var db = goose.connection,
+          uri = 'mongodb://localhost/mongoose_test';
+
+      goose.connect(process.env.MONGOOSE_TEST_URI || uri).then(function() {
+        db.close(done);
+      });
+    });
   });
 
   it('{g,s}etting options', function(done) {
@@ -128,8 +138,8 @@ describe('mongoose module:', function() {
           cb(new Error('bam'));
         };
 
-        mong.disconnect()
-          .on('error', function(error) {
+        mong.disconnect().connection.
+          on('error', function(error) {
             assert.equal('bam', error.message);
           });
 
@@ -149,6 +159,17 @@ describe('mongoose module:', function() {
         });
       });
     });
+
+    it('with promise (gh-3790)', function(done) {
+      var mong = new Mongoose();
+      var uri = 'mongodb://localhost/mongoose_test';
+
+      mong.connect(process.env.MONGOOSE_TEST_URI || uri);
+
+      mong.connection.on('open', function() {
+        mong.disconnect().then(function() { done(); });
+      });
+    });
   });
 
   describe('model()', function() {

From 8fbe3288778a3585d95490e3aa4d63a314c305c1 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 16:42:26 -0500
Subject: [PATCH 0255/2240] fix(document): check for null and undefined in
 storeShard (Fix #3841)

---
 lib/document.js | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index edd70125b37..92906bc1f29 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -376,8 +376,7 @@ Document.prototype.$__storeShard = function() {
     val = this.getValue(paths[i]);
     if (isMongooseObject(val)) {
       orig[paths[i]] = val.toObject({depopulate: true});
-    } else if (val !== null &&
-        val.valueOf &&
+    } else if (val !== null && val !== undefined && val.valueOf &&
           // Explicitly don't take value of dates
         (!val.constructor || utils.getFunctionName(val.constructor) !== 'Date')) {
       orig[paths[i]] = val.valueOf();

From 913028ee4c386da02833c175903065b3b0876bac Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 16:58:26 -0500
Subject: [PATCH 0256/2240] fix: various places where linting broke == check
 (Fix #3852)

---
 lib/document.js        |  5 ++++-
 lib/schema.js          |  2 +-
 lib/schema/buffer.js   |  2 +-
 lib/schema/number.js   |  6 +++---
 lib/schema/objectid.js |  5 ++---
 lib/schema/string.js   |  8 ++++----
 lib/schematype.js      | 13 ++++++++-----
 lib/types/array.js     |  2 +-
 lib/types/buffer.js    |  2 +-
 lib/utils.js           |  2 +-
 10 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index 92906bc1f29..2665e8bd012 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -273,7 +273,8 @@ Document.prototype.init = function(doc, opts, fn) {
 
   // handle docs with populated paths
   // If doc._id is not null or undefined
-  if (doc._id !== null && opts && opts.populated && opts.populated.length) {
+  if (doc._id !== null && doc._id !== undefined &&
+    opts && opts.populated && opts.populated.length) {
     var id = String(doc._id);
     for (var i = 0; i < opts.populated.length; ++i) {
       var item = opts.populated[i];
@@ -502,6 +503,7 @@ Document.prototype.set = function(path, val, type, options) {
         pathtype = this.schema.pathType(pathName);
 
         if (path[key] !== null
+            && path[key] !== undefined
               // need to know if plain object - no Buffer, ObjectId, ref, etc
             && utils.isObject(path[key])
             && (!path[key].constructor || utils.getFunctionName(path[key].constructor) === 'Object')
@@ -718,6 +720,7 @@ Document.prototype.$__shouldModify = function(pathToMark, path, constructing, pa
 
   if (!constructing &&
       val !== null &&
+      val !== undefined &&
       path in this.$__.activePaths.states.default &&
       deepEqual(val, schema.getDefault(this, constructing))) {
     // a path with a default was $unset on the server
diff --git a/lib/schema.js b/lib/schema.js
index 65812f0642c..2c458d34c5e 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -1092,7 +1092,7 @@ Schema.prototype.indexes = function() {
       } else {
         index = path._index;
 
-        if (index !== false && index !== null) {
+        if (index !== false && index !== null && index !== undefined) {
           field = {};
           isObject = utils.isObject(index);
           options = isObject ? index : {};
diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js
index b057ba3f4b4..16432b40380 100644
--- a/lib/schema/buffer.js
+++ b/lib/schema/buffer.js
@@ -66,7 +66,7 @@ SchemaBuffer.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (value === null || value === void 0) {
+    if (value === null || value === undefined) {
       return value;
     }
 
diff --git a/lib/schema/number.js b/lib/schema/number.js
index d0485028540..ff8f500b918 100644
--- a/lib/schema/number.js
+++ b/lib/schema/number.js
@@ -87,7 +87,7 @@ SchemaNumber.prototype.min = function(value, message) {
     }, this);
   }
 
-  if (value !== null && value !== void 0) {
+  if (value !== null && value !== undefined) {
     var msg = message || errorMessages.Number.min;
     msg = msg.replace(/{MIN}/, value);
     this.validators.push({
@@ -141,7 +141,7 @@ SchemaNumber.prototype.max = function(value, message) {
     }, this);
   }
 
-  if (value !== null && value !== void 0) {
+  if (value !== null && value !== undefined) {
     var msg = message || errorMessages.Number.max;
     msg = msg.replace(/{MAX}/, value);
     this.validators.push({
@@ -170,7 +170,7 @@ SchemaNumber.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (value === null || value === void 0) {
+    if (value === null || value === undefined) {
       return value;
     }
 
diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js
index bad69fed638..51bcb4947e9 100644
--- a/lib/schema/objectid.js
+++ b/lib/schema/objectid.js
@@ -79,7 +79,7 @@ ObjectId.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (value === null || value === void 0) {
+    if (value === null || value === undefined) {
       return value;
     }
 
@@ -109,8 +109,7 @@ ObjectId.prototype.cast = function(value, doc, init) {
     return ret;
   }
 
-  // If null or undefined
-  if (value === null || value === void 0) {
+  if (value === null || value === undefined) {
     return value;
   }
 
diff --git a/lib/schema/string.js b/lib/schema/string.js
index 3bd6c818dc1..6213471349d 100644
--- a/lib/schema/string.js
+++ b/lib/schema/string.js
@@ -235,7 +235,7 @@ SchemaString.prototype.minlength = function(value, message) {
     }, this);
   }
 
-  if (value !== null) {
+  if (value !== null && value !== undefined) {
     var msg = message || errorMessages.String.minlength;
     msg = msg.replace(/{MINLENGTH}/, value);
     this.validators.push({
@@ -289,7 +289,7 @@ SchemaString.prototype.maxlength = function(value, message) {
     }, this);
   }
 
-  if (value != null) {
+  if (value !== null && value !== undefined) {
     var msg = message || errorMessages.String.maxlength;
     msg = msg.replace(/{MAXLENGTH}/, value);
     this.validators.push({
@@ -392,7 +392,7 @@ SchemaString.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (value === null) {
+    if (value === null || value === undefined) {
       return value;
     }
 
@@ -423,7 +423,7 @@ SchemaString.prototype.cast = function(value, doc, init) {
   }
 
   // If null or undefined
-  if (value === null || value === void 0) {
+  if (value === null || value === undefined) {
     return value;
   }
 
diff --git a/lib/schematype.js b/lib/schematype.js
index 6b90fe0e59a..bfab06b9ef7 100644
--- a/lib/schematype.js
+++ b/lib/schematype.js
@@ -145,7 +145,8 @@ SchemaType.prototype.index = function(options) {
  */
 
 SchemaType.prototype.unique = function(bool) {
-  if (this._index === null || typeof this._index === 'boolean') {
+  if (this._index === null || this._index === undefined ||
+    typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
@@ -168,7 +169,8 @@ SchemaType.prototype.unique = function(bool) {
  */
 
 SchemaType.prototype.text = function(bool) {
-  if (this._index === null || typeof this._index === 'boolean') {
+  if (this._index === null || this._index === undefined ||
+    typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
@@ -192,7 +194,8 @@ SchemaType.prototype.text = function(bool) {
  */
 
 SchemaType.prototype.sparse = function(bool) {
-  if (this._index === null || typeof this._index === 'boolean') {
+  if (this._index === null || this._index === undefined ||
+    typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
@@ -557,7 +560,7 @@ SchemaType.prototype.getDefault = function(scope, init) {
       ? this.defaultValue.call(scope)
       : this.defaultValue;
 
-  if (ret !== null && undefined !== ret) {
+  if (ret !== null && ret !== undefined) {
     return this.cast(ret, scope, init);
   }
   return ret;
@@ -590,7 +593,7 @@ SchemaType.prototype.applySetters = function(value, scope, init, priorVal, optio
     v = newVal;
   }
 
-  if (v === null || v === void 0) {
+  if (v === null || v === undefined) {
     return v;
   }
 
diff --git a/lib/types/array.js b/lib/types/array.js
index 83818fa9251..5bb07f2e8bb 100644
--- a/lib/types/array.js
+++ b/lib/types/array.js
@@ -106,7 +106,7 @@ MongooseArray.mixin = {
       populated = owner.populated(this._path, true);
     }
 
-    if (populated && value !== null) {
+    if (populated && value !== null && value !== undefined) {
       // cast to the populated Models schema
       Model = populated.options.model;
 
diff --git a/lib/types/buffer.js b/lib/types/buffer.js
index 2cd66507a15..0c7bbe32ed5 100644
--- a/lib/types/buffer.js
+++ b/lib/types/buffer.js
@@ -22,7 +22,7 @@ function MongooseBuffer(value, encode, offset) {
   var length = arguments.length;
   var val;
 
-  if (length === 0 || arguments[0] === null || arguments[0] === void 0) {
+  if (length === 0 || arguments[0] === null || arguments[0] === undefined) {
     val = 0;
   } else {
     val = value;
diff --git a/lib/utils.js b/lib/utils.js
index 295dd0ee1f2..8747774d00f 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -682,7 +682,7 @@ exports.object.hasOwnProperty = function(obj, prop) {
  */
 
 exports.isNullOrUndefined = function(val) {
-  return val === null || val === void 0;
+  return val === null || val === undefined;
 };
 
 /*!

From 9dba1562dc2a07ed475de3bb3550eb7201a9cb48 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 17:31:48 -0500
Subject: [PATCH 0257/2240] test(model): repro #3824

---
 test/model.querying.test.js | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/test/model.querying.test.js b/test/model.querying.test.js
index 7d7042c6cf1..12155bc8fbb 100644
--- a/test/model.querying.test.js
+++ b/test/model.querying.test.js
@@ -1579,18 +1579,24 @@ describe('model: querying:', function() {
         });
       });
 
-      it('works when text search is called by a schema', function(done) {
+      it('works when text search is called by a schema (gh-3824)', function(done) {
         var db = start();
 
         var exampleSchema = new Schema({
           title: String,
-          name: {type: String, text: true},
+          name: { type: String, text: true },
           large_text: String
         });
 
-        var indexes = exampleSchema.indexes();
-        assert.equal(indexes[0][1].text, true);
-        db.close(done);
+        var Example = db.model('gh3824', exampleSchema);
+
+        Example.on('index', function(error) {
+          assert.ifError(error);
+          Example.findOne({ $text: { $search: 'text search' } }, function(error) {
+            assert.ifError(error);
+            db.close(done);
+          });
+        });
       });
     });
   });

From a48a648e61e0cfa463bd54de4a2d40fdf5ea31b9 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 17:32:23 -0500
Subject: [PATCH 0258/2240] fix(schema): enable `text: true` to create a text
 index (Fix #3824)

---
 lib/schema.js | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/schema.js b/lib/schema.js
index 2c458d34c5e..0809f3a935e 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -1102,6 +1102,9 @@ Schema.prototype.indexes = function() {
 
           if (type && ~Schema.indexTypes.indexOf(type)) {
             field[prefix + key] = type;
+          } else if (options.text) {
+            field[prefix + key] = 'text';
+            delete options.text;
           } else {
             field[prefix + key] = 1;
           }

From 2dbe49459220f096fa968f7a7afd58e4be935779 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 17:35:48 -0500
Subject: [PATCH 0259/2240] test(model): dont run text search test unless mongo
 2.6 or greater

---
 test/model.querying.test.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/test/model.querying.test.js b/test/model.querying.test.js
index 12155bc8fbb..054de33b137 100644
--- a/test/model.querying.test.js
+++ b/test/model.querying.test.js
@@ -1580,6 +1580,10 @@ describe('model: querying:', function() {
       });
 
       it('works when text search is called by a schema (gh-3824)', function(done) {
+        if (!mongo26_or_greater) {
+          return done();
+        }
+
         var db = start();
 
         var exampleSchema = new Schema({

From e810a19ed23cd2ffa1f3c26b373f3c48c35174e5 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 17:40:51 -0500
Subject: [PATCH 0260/2240] test: use mongodb 2.6.11 on travis because we miss
 a lot of tests

---
 .travis.yml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index dcdb2c7d4db..76c3b88bb5f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,3 +8,8 @@ node_js:
   - "iojs"
 services:
   - mongodb
+before_script:
+  - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.11.tgz
+  - tar -zxvf mongodb-linux-x86_64-2.6.11.tgz
+  - mkdir -p ./data/db
+  - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --nopreallocj --dbpath ./data/db --syslog --port 27017

From b0fefaf6d5a393e4054ad02353d3e06a8f26b04a Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 17:44:20 -0500
Subject: [PATCH 0261/2240] test: remove mongodb service from travis.yml

---
 .travis.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 76c3b88bb5f..05a3e8dd9ef 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,8 +6,6 @@ node_js:
   - "0.12"
   - "0.10"
   - "iojs"
-services:
-  - mongodb
 before_script:
   - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.11.tgz
   - tar -zxvf mongodb-linux-x86_64-2.6.11.tgz

From bde44d935325afac77a565e81e11652a60cf4a80 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 17:46:32 -0500
Subject: [PATCH 0262/2240] chore: revert to older dox and highlight.js from
 #3801 (Fix #3845)

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 7ca7a6a2c04..9fd13d7a864 100644
--- a/package.json
+++ b/package.json
@@ -38,9 +38,9 @@
     "benchmark": "2.0.0",
     "bluebird": "3.1.4",
     "co": "4.6.0",
-    "dox": "0.8.0",
+    "dox": "0.3.1",
     "eslint": "2.0.0-beta.3",
-    "highlight.js": "9.1.0",
+    "highlight.js": "7.0.1",
     "istanbul": "0.4.2",
     "jade": "0.26.3",
     "markdown": "0.5.0",

From 831142c7a1c03aec017976117fa093e79da4fc11 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 3 Feb 2016 17:58:44 -0500
Subject: [PATCH 0263/2240] chore: release 4.4.1

---
 History.md      |  11 +++
 bin/mongoose.js | 206 +++++++++++++++++++++++++-----------------------
 package.json    |   2 +-
 3 files changed, 119 insertions(+), 100 deletions(-)

diff --git a/History.md b/History.md
index 24f35c158c1..7354068be02 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,14 @@
+4.4.1 / 2016-02-03
+==================
+ * fix: linting broke some cases where we use `== null` as shorthand #3852
+ * docs: fix up schematype.html conflict #3848 #3843 [mynameiscoffey](https://github.com/mynameiscoffey)
+ * fix: backwards breaking change with `.connect()` return value #3847
+ * docs: downgrade dox and highlight.js to fix docs build #3845
+ * docs: clean up typo #3842 [Flash-](https://github.com/Flash-)
+ * fix(document): storeShard handles undefined values #3841
+ * chore: more linting #3838 [TrejGun](https://github.com/TrejGun)
+ * fix(schema): handle `text: true` as a way to declare a text index #3824
+
 4.4.0 / 2016-02-02
 ==================
  * docs: fix expireAfterSeconds index option name #3831 [Flash-](https://github.com/Flash-)
diff --git a/bin/mongoose.js b/bin/mongoose.js
index 7c9c67aaf45..5a7883af1fe 100644
--- a/bin/mongoose.js
+++ b/bin/mongoose.js
@@ -246,11 +246,10 @@ var Types = require('./schema/index');
  * Handles internal casting for queries
  *
  * @param {Schema} schema
- * @param {Object obj Object to cast
+ * @param {Object} obj Object to cast
  * @api private
  */
-
-var cast = module.exports = function(schema, obj) {
+module.exports = function cast(schema, obj) {
   var paths = Object.keys(obj),
       i = paths.length,
       any$conditionals,
@@ -365,29 +364,7 @@ var cast = module.exports = function(schema, obj) {
             value = value.$geometry.coordinates;
           }
 
-          (function _cast(val) {
-            if (Array.isArray(val)) {
-              val.forEach(function(item, i) {
-                if (Array.isArray(item) || utils.isObject(item)) {
-                  return _cast(item);
-                }
-                val[i] = numbertype.castForQuery(item);
-              });
-            } else {
-              var nearKeys = Object.keys(val);
-              var nearLen = nearKeys.length;
-              while (nearLen--) {
-                var nkey = nearKeys[nearLen];
-                var item = val[nkey];
-                if (Array.isArray(item) || utils.isObject(item)) {
-                  _cast(item);
-                  val[nkey] = item;
-                } else {
-                  val[nkey] = numbertype.castForQuery(item);
-                }
-              }
-            }
-          })(value);
+          _cast(value, numbertype);
         }
       } else if (val === null || val === undefined) {
         obj[path] = null;
@@ -439,6 +416,30 @@ var cast = module.exports = function(schema, obj) {
   return obj;
 };
 
+function _cast(val, numbertype) {
+  if (Array.isArray(val)) {
+    val.forEach(function(item, i) {
+      if (Array.isArray(item) || utils.isObject(item)) {
+        return _cast(item, numbertype);
+      }
+      val[i] = numbertype.castForQuery(item);
+    });
+  } else {
+    var nearKeys = Object.keys(val);
+    var nearLen = nearKeys.length;
+    while (nearLen--) {
+      var nkey = nearKeys[nearLen];
+      var item = val[nkey];
+      if (Array.isArray(item) || utils.isObject(item)) {
+        _cast(item, numbertype);
+        val[nkey] = item;
+      } else {
+        val[nkey] = numbertype.castForQuery(item);
+      }
+    }
+  }
+}
+
 },{"./schema/index":33,"./utils":48}],5:[function(require,module,exports){
 (function (process,Buffer){
 /*!
@@ -716,7 +717,8 @@ Document.prototype.init = function(doc, opts, fn) {
 
   // handle docs with populated paths
   // If doc._id is not null or undefined
-  if (doc._id !== null && opts && opts.populated && opts.populated.length) {
+  if (doc._id !== null && doc._id !== undefined &&
+    opts && opts.populated && opts.populated.length) {
     var id = String(doc._id);
     for (var i = 0; i < opts.populated.length; ++i) {
       var item = opts.populated[i];
@@ -819,8 +821,7 @@ Document.prototype.$__storeShard = function() {
     val = this.getValue(paths[i]);
     if (isMongooseObject(val)) {
       orig[paths[i]] = val.toObject({depopulate: true});
-    } else if (val !== null &&
-        val.valueOf &&
+    } else if (val !== null && val !== undefined && val.valueOf &&
           // Explicitly don't take value of dates
         (!val.constructor || utils.getFunctionName(val.constructor) !== 'Date')) {
       orig[paths[i]] = val.valueOf();
@@ -946,6 +947,7 @@ Document.prototype.set = function(path, val, type, options) {
         pathtype = this.schema.pathType(pathName);
 
         if (path[key] !== null
+            && path[key] !== undefined
               // need to know if plain object - no Buffer, ObjectId, ref, etc
             && utils.isObject(path[key])
             && (!path[key].constructor || utils.getFunctionName(path[key].constructor) === 'Object')
@@ -1162,6 +1164,7 @@ Document.prototype.$__shouldModify = function(pathToMark, path, constructing, pa
 
   if (!constructing &&
       val !== null &&
+      val !== undefined &&
       path in this.$__.activePaths.states.default &&
       deepEqual(val, schema.getDefault(this, constructing))) {
     // a path with a default was $unset on the server
@@ -4919,7 +4922,7 @@ Schema.prototype.indexes = function() {
       } else {
         index = path._index;
 
-        if (index !== false && index !== null) {
+        if (index !== false && index !== null && index !== undefined) {
           field = {};
           isObject = utils.isObject(index);
           options = isObject ? index : {};
@@ -4929,6 +4932,9 @@ Schema.prototype.indexes = function() {
 
           if (type && ~Schema.indexTypes.indexOf(type)) {
             field[prefix + key] = type;
+          } else if (options.text) {
+            field[prefix + key] = 'text';
+            delete options.text;
           } else {
             field[prefix + key] = 1;
           }
@@ -5056,8 +5062,7 @@ Schema.prototype._getSchema = function(path) {
     return pathschema;
   }
 
-  // look for arrays
-  return (function search(parts, schema) {
+  function search(parts, schema) {
     var p = parts.length + 1,
         foundschema,
         trypath;
@@ -5090,7 +5095,10 @@ Schema.prototype._getSchema = function(path) {
         return foundschema;
       }
     }
-  })(path.split('.'), _this);
+  }
+
+  // look for arrays
+  return search(path.split('.'), _this);
 };
 
 /*!
@@ -5701,7 +5709,7 @@ SchemaBuffer.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (value === null || value === void 0) {
+    if (value === null || value === undefined) {
       return value;
     }
 
@@ -5780,14 +5788,14 @@ function handleSingle(val) {
 
 SchemaBuffer.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$bitsAllClear': handleBitwiseOperator,
-      '$bitsAnyClear': handleBitwiseOperator,
-      '$bitsAllSet': handleBitwiseOperator,
-      '$bitsAnySet': handleBitwiseOperator,
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle
+      $bitsAllClear: handleBitwiseOperator,
+      $bitsAnyClear: handleBitwiseOperator,
+      $bitsAllSet: handleBitwiseOperator,
+      $bitsAnySet: handleBitwiseOperator,
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle
     });
 
 /**
@@ -6067,10 +6075,10 @@ function handleSingle(val) {
 
 SchemaDate.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle
     });
 
 
@@ -6204,6 +6212,13 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
     // iterate over sparse elements yet reports array.length including
     // them :(
 
+    function callback(err) {
+      if (err) {
+        error = err;
+      }
+      --count || fn(error);
+    }
+
     for (var i = 0, len = count; i < len; ++i) {
       // sidestep sparse entries
       var doc = array[i];
@@ -6215,19 +6230,9 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
       // HACK: use $__original_validate to avoid promises so bluebird doesn't
       // complain
       if (doc.$__original_validate) {
-        doc.$__original_validate({__noPromise: true}, function(err) {
-          if (err) {
-            error = err;
-          }
-          --count || fn(error);
-        });
+        doc.$__original_validate({__noPromise: true}, callback);
       } else {
-        doc.validate({__noPromise: true}, function(err) {
-          if (err) {
-            error = err;
-          }
-          --count || fn(error);
-        });
+        doc.validate({__noPromise: true}, callback);
       }
     }
   }, scope);
@@ -6751,7 +6756,7 @@ SchemaNumber.prototype.min = function(value, message) {
     }, this);
   }
 
-  if (value !== null && value !== void 0) {
+  if (value !== null && value !== undefined) {
     var msg = message || errorMessages.Number.min;
     msg = msg.replace(/{MIN}/, value);
     this.validators.push({
@@ -6805,7 +6810,7 @@ SchemaNumber.prototype.max = function(value, message) {
     }, this);
   }
 
-  if (value !== null && value !== void 0) {
+  if (value !== null && value !== undefined) {
     var msg = message || errorMessages.Number.max;
     msg = msg.replace(/{MAX}/, value);
     this.validators.push({
@@ -6834,7 +6839,7 @@ SchemaNumber.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (value === null || value === void 0) {
+    if (value === null || value === undefined) {
       return value;
     }
 
@@ -6912,15 +6917,15 @@ function handleArray(val) {
 
 SchemaNumber.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$bitsAllClear': handleBitwiseOperator,
-      '$bitsAnyClear': handleBitwiseOperator,
-      '$bitsAllSet': handleBitwiseOperator,
-      '$bitsAnySet': handleBitwiseOperator,
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle,
-      '$mod': handleArray
+      $bitsAllClear: handleBitwiseOperator,
+      $bitsAnyClear: handleBitwiseOperator,
+      $bitsAllSet: handleBitwiseOperator,
+      $bitsAnySet: handleBitwiseOperator,
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle,
+      $mod: handleArray
     });
 
 /**
@@ -7034,7 +7039,7 @@ ObjectId.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (value === null || value === void 0) {
+    if (value === null || value === undefined) {
       return value;
     }
 
@@ -7064,8 +7069,7 @@ ObjectId.prototype.cast = function(value, doc, init) {
     return ret;
   }
 
-  // If null or undefined
-  if (value === null || value === void 0) {
+  if (value === null || value === undefined) {
     return value;
   }
 
@@ -7106,10 +7110,10 @@ function handleSingle(val) {
 
 ObjectId.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle
     });
 
 /**
@@ -7431,7 +7435,7 @@ SchemaString.prototype.minlength = function(value, message) {
     }, this);
   }
 
-  if (value !== null) {
+  if (value !== null && value !== undefined) {
     var msg = message || errorMessages.String.minlength;
     msg = msg.replace(/{MINLENGTH}/, value);
     this.validators.push({
@@ -7485,7 +7489,7 @@ SchemaString.prototype.maxlength = function(value, message) {
     }, this);
   }
 
-  if (value != null) {
+  if (value !== null && value !== undefined) {
     var msg = message || errorMessages.String.maxlength;
     msg = msg.replace(/{MAXLENGTH}/, value);
     this.validators.push({
@@ -7588,7 +7592,7 @@ SchemaString.prototype.cast = function(value, doc, init) {
   if (SchemaType._isRef(this, value, doc, init)) {
     // wait! we may need to cast this to a document
 
-    if (value === null) {
+    if (value === null || value === undefined) {
       return value;
     }
 
@@ -7619,7 +7623,7 @@ SchemaString.prototype.cast = function(value, doc, init) {
   }
 
   // If null or undefined
-  if (value === null || value === void 0) {
+  if (value === null || value === undefined) {
     return value;
   }
 
@@ -7660,13 +7664,13 @@ function handleArray(val) {
 
 SchemaString.prototype.$conditionalHandlers =
     utils.options(SchemaType.prototype.$conditionalHandlers, {
-      '$all': handleArray,
-      '$gt': handleSingle,
-      '$gte': handleSingle,
-      '$lt': handleSingle,
-      '$lte': handleSingle,
-      '$options': handleSingle,
-      '$regex': handleSingle
+      $all: handleArray,
+      $gt: handleSingle,
+      $gte: handleSingle,
+      $lt: handleSingle,
+      $lte: handleSingle,
+      $options: handleSingle,
+      $regex: handleSingle
     });
 
 /**
@@ -7849,7 +7853,8 @@ SchemaType.prototype.index = function(options) {
  */
 
 SchemaType.prototype.unique = function(bool) {
-  if (this._index === null || typeof this._index === 'boolean') {
+  if (this._index === null || this._index === undefined ||
+    typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
@@ -7872,7 +7877,8 @@ SchemaType.prototype.unique = function(bool) {
  */
 
 SchemaType.prototype.text = function(bool) {
-  if (this._index === null || typeof this._index === 'boolean') {
+  if (this._index === null || this._index === undefined ||
+    typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
@@ -7896,7 +7902,8 @@ SchemaType.prototype.text = function(bool) {
  */
 
 SchemaType.prototype.sparse = function(bool) {
-  if (this._index === null || typeof this._index === 'boolean') {
+  if (this._index === null || this._index === undefined ||
+    typeof this._index === 'boolean') {
     this._index = {};
   } else if (typeof this._index === 'string') {
     this._index = {type: this._index};
@@ -8261,7 +8268,7 @@ SchemaType.prototype.getDefault = function(scope, init) {
       ? this.defaultValue.call(scope)
       : this.defaultValue;
 
-  if (ret !== null && undefined !== ret) {
+  if (ret !== null && ret !== undefined) {
     return this.cast(ret, scope, init);
   }
   return ret;
@@ -8294,7 +8301,7 @@ SchemaType.prototype.applySetters = function(value, scope, init, priorVal, optio
     v = newVal;
   }
 
-  if (v === null || v === void 0) {
+  if (v === null || v === undefined) {
     return v;
   }
 
@@ -8878,7 +8885,7 @@ MongooseArray.mixin = {
       populated = owner.populated(this._path, true);
     }
 
-    if (populated && value !== null) {
+    if (populated && value !== null && value !== undefined) {
       // cast to the populated Models schema
       Model = populated.options.model;
 
@@ -8988,7 +8995,7 @@ MongooseArray.mixin = {
           return v.toObject({virtuals: false});
         }));
       } else {
-        selector = pullOp['_id'] || (pullOp['_id'] = {'$in': []});
+        selector = pullOp['_id'] || (pullOp['_id'] = {$in: []});
         selector['$in'] = selector['$in'].concat(val);
       }
     } else {
@@ -9294,9 +9301,10 @@ MongooseArray.mixin = {
     while (i--) {
       mem = cur[i];
       if (mem instanceof Document) {
-        if (values.some(function(v) {
+        var some = values.some(function(v) {
           return v.equals(mem);
-        })) {
+        });
+        if (some) {
           [].splice.call(cur, i, 1);
         }
       } else if (~cur.indexOf.call(values, mem)) {
@@ -9583,7 +9591,7 @@ function MongooseBuffer(value, encode, offset) {
   var length = arguments.length;
   var val;
 
-  if (length === 0 || arguments[0] === null || arguments[0] === void 0) {
+  if (length === 0 || arguments[0] === null || arguments[0] === undefined) {
     val = 0;
   } else {
     val = value;
@@ -11247,7 +11255,7 @@ exports.object.hasOwnProperty = function(obj, prop) {
  */
 
 exports.isNullOrUndefined = function(val) {
-  return val === null || val === void 0;
+  return val === null || val === undefined;
 };
 
 /*!
diff --git a/package.json b/package.json
index 9fd13d7a864..5d74807079b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.4.1-pre",
+  "version": "4.4.1",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From 47ed40460b335949928f63fec94f1ec31bb9e16a Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 4 Feb 2016 11:29:38 -0500
Subject: [PATCH 0264/2240] chore: now working on 4.4.2

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 5d74807079b..aba703aac36 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "4.4.1",
+  "version": "4.4.2-pre",
   "author": "Guillermo Rauch ",
   "keywords": [
     "mongodb",

From a5837aad11e7786e23d3d7da18fdd4c41df01e53 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 4 Feb 2016 11:42:21 -0500
Subject: [PATCH 0265/2240] refactor(document): use priorVal to make parameters
 more clear

---
 lib/document.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index 2665e8bd012..3b1ea3ce2fa 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -738,10 +738,11 @@ Document.prototype.$__shouldModify = function(pathToMark, path, constructing, pa
  * @memberOf Document
  */
 
-Document.prototype.$__set = function(pathToMark, path, constructing, parts, schema, val/* , priorVal */) {
+Document.prototype.$__set = function(pathToMark, path, constructing, parts, schema, val, priorVal) {
   Embedded = Embedded || require('./types/embedded');
 
-  var shouldModify = this.$__shouldModify.apply(this, arguments);
+  var shouldModify = this.$__shouldModify(pathToMark, path, constructing, parts,
+    schema, val, priorVal);
   var _this = this;
 
   if (shouldModify) {

From 37cd895273fb8e2f8b5bd1dccb71077f9e75c934 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 4 Feb 2016 11:50:00 -0500
Subject: [PATCH 0266/2240] docs: fix docs build issues

---
 lib/document.js                               | 1 +
 lib/drivers/node-mongodb-native/collection.js | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/lib/document.js b/lib/document.js
index 3b1ea3ce2fa..f9da6988127 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -949,6 +949,7 @@ Document.prototype.isModified = function(path) {
  *
  * @param {String} [path]
  * @return {Boolean}
+ * @method $isDefault
  * @api public
  */
 
diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js
index 38886d95d7c..5fc73194b64 100644
--- a/lib/drivers/node-mongodb-native/collection.js
+++ b/lib/drivers/node-mongodb-native/collection.js
@@ -143,6 +143,7 @@ for (var i in Collection.prototype) {
  * Debug print helper
  *
  * @api public
+ * @method $print
  */
 
 NativeCollection.prototype.$print = function(name, i, args) {
@@ -160,6 +161,7 @@ NativeCollection.prototype.$print = function(name, i, args) {
  * Formatter for debug print args
  *
  * @api public
+ * @method $format
  */
 
 NativeCollection.prototype.$format = function(arg) {

From 38545b967e5e95c05fc1224c64c05606776d1b1a Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 4 Feb 2016 11:58:06 -0500
Subject: [PATCH 0267/2240] docs: downgrade markdown and fix example thats
 rendering badly

---
 lib/model.js | 2 +-
 package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/model.js b/lib/model.js
index 479546d37b9..40d32b2202e 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -1350,7 +1350,7 @@ Model.where = function where(path, val) {
  *
  * Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via `find({ $where: javascript })`, or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.
  *
- *     Blog.$where('this.comments.length > 5').exec(function (err, docs) {});
+ *     Blog.$where('this.username.indexOf("val") !== -1').exec(function (err, docs) {});
  *
  * @param {String|Function} argument is a javascript string or anonymous function
  * @method $where
diff --git a/package.json b/package.json
index aba703aac36..be25ebf1c24 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
     "highlight.js": "7.0.1",
     "istanbul": "0.4.2",
     "jade": "0.26.3",
-    "markdown": "0.5.0",
+    "markdown": "0.3.1",
     "marked": "0.3.5",
     "mocha": "2.3.4",
     "node-static": "0.7.7",

From 58fdabcf1452175bfe00e0731f0b8a6a9003df74 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 4 Feb 2016 11:58:54 -0500
Subject: [PATCH 0268/2240] chore: remove spammy open module

---
 package.json | 1 -
 static.js    | 2 --
 2 files changed, 3 deletions(-)

diff --git a/package.json b/package.json
index be25ebf1c24..42f94ed0cf6 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,6 @@
     "marked": "0.3.5",
     "mocha": "2.3.4",
     "node-static": "0.7.7",
-    "open": "0.0.5",
     "power-assert": "1.2.0",
     "q": "1.4.1",
     "tbd": "0.6.4",
diff --git a/static.js b/static.js
index c701653c15e..d84e59f7a3a 100644
--- a/static.js
+++ b/static.js
@@ -1,7 +1,6 @@
 
 var static = require('node-static');
 var server = new static.Server('.', {cache: 0});
-var open = require('open');
 
 require('http').createServer(function(req, res) {
   if (req.url === '/favicon.ico') {
@@ -23,4 +22,3 @@ require('http').createServer(function(req, res) {
 }).listen(8088);
 
 console.error('now listening on http://localhost:8088');
-open('http://localhost:8088');

From c84034f540a4e04418f60fad10b766c5d01812d4 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 4 Feb 2016 12:10:50 -0500
Subject: [PATCH 0269/2240] docs: parse params as markdown

---
 docs/api.jade      |  2 +-
 docs/source/api.js | 18 ++++++++++++++----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/docs/api.jade b/docs/api.jade
index 1db2474ab23..17afa0a4aa2 100644
--- a/docs/api.jade
+++ b/docs/api.jade
@@ -108,7 +108,7 @@ html(lang='en')
                                 if i+1 < tag.types.length
                                   | , 
                               | > 
-                          span= tag.description
+                          span!= tag.description
                 if method.return
                   .returns
                     h4 Returns:
diff --git a/docs/source/api.js b/docs/source/api.js
index 998a59cf77f..031a9a9089d 100644
--- a/docs/source/api.js
+++ b/docs/source/api.js
@@ -4,8 +4,8 @@
 
 var fs = require('fs');
 var link = require('../helpers/linktype');
-var hl = require('highlight.js')
-var md = require('markdown')
+var hl = require('highlight.js');
+var md = require('markdown');
 
 module.exports = {
     docs: []
@@ -39,8 +39,9 @@ function parse (docs) {
     var constructor = null;
 
     json.forEach(function (comment) {
-      if (comment.description)
+      if (comment.description) {
         highlight(comment.description);
+      }
 
       var prop = false;
       comment.params = [];
@@ -102,6 +103,8 @@ function parse (docs) {
         case 'param':
           comment.params.unshift(tag);
           comment.tags.splice(i, 1);
+          tag.description = tag.description ?
+            md.parse(tag.description).replace(/^

/, '').replace(/<\/p>$/, '') : ''; break; case 'return': comment.return = tag; @@ -139,7 +142,14 @@ function parse (docs) { props = props.filter(ignored); function ignored (method) { - if (method.ignore) return false; + if (method.ignore) { + return false; + } + // Ignore eslint declarations + if (method.description && method.description.full && + method.description.full.indexOf('

eslint') === 0) { + return false; + } return true; } From 4149b5290b6079eb3c64fd2729329525d54ca99a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Feb 2016 15:14:26 -0500 Subject: [PATCH 0270/2240] docs: clean up schematypes.html mixup (Fix #3843) --- docs/includes/nav.jade | 5 ++++- docs/source/acquit.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/includes/nav.jade b/docs/includes/nav.jade index 80d5a1cfe0a..2a102cb4d27 100644 --- a/docs/includes/nav.jade +++ b/docs/includes/nav.jade @@ -64,10 +64,13 @@ ul | contributing li a(href="./harmony.html") - | ES6 integration + | ES2015 integration li a(href="./browser.html") | schemas in the browser + li + a(href="./customschematypes.html") + | custom schema types li a(href="./compatibility.html") | MongoDB Version Compatibility diff --git a/docs/source/acquit.js b/docs/source/acquit.js index ba9993d096f..060a7d2df42 100644 --- a/docs/source/acquit.js +++ b/docs/source/acquit.js @@ -22,7 +22,7 @@ var files = [ }, { input: 'test/docs/schematypes.test.js', - output: 'schematypes.html', + output: 'customschematypes.html', title: 'Custom Schema Types' } ]; From 573e6f98e0e1155ec596cb7cc67540f18c722ae2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Feb 2016 15:53:23 -0500 Subject: [PATCH 0271/2240] fix(model): bluebird unhandled rejection on index error re: #3837 --- lib/model.js | 108 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 44 deletions(-) diff --git a/lib/model.js b/lib/model.js index 40d32b2202e..e050c00e0ab 100644 --- a/lib/model.js +++ b/lib/model.js @@ -875,7 +875,7 @@ for (var i in EventEmitter.prototype) { Model.init = function init() { if ((this.schema.options.autoIndex) || (this.schema.options.autoIndex === null && this.db.config.autoIndex)) { - this.ensureIndexes(); + this.ensureIndexes({ __noPromise: true }); } this.schema.emit('init', this); @@ -905,64 +905,84 @@ Model.init = function init() { * * The `ensureIndex` commands are not sent in parallel. This is to avoid the `MongoError: cannot add index with a background operation in progress` error. See [this ticket](https://github.com/Automattic/mongoose/issues/1365) for more information. * + * @param {Object} [options] internal options * @param {Function} [cb] optional callback * @return {Promise} * @api public */ -Model.ensureIndexes = function ensureIndexes(cb) { +Model.ensureIndexes = function ensureIndexes(options, cb) { + if (typeof options === 'function') { + cb = options; + options = null; + } + + if (options && options.__noPromise) { + _ensureIndexes(this, cb); + return; + } + var _this = this; var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { - var indexes = _this.schema.indexes(); - if (!indexes.length) { - process.nextTick(function() { - cb && cb(); - resolve(); - }); - return; - } - // Indexes are created one-by-one to support how MongoDB < 2.4 deals - // with background indexes. - - var done = function(err) { - if (err && _this.schema.options.emitIndexErrors) { - _this.emit('error', err); + _ensureIndexes(_this, function(error) { + if (error) { + cb && cb(error); + reject(error); } - _this.emit('index', err); - cb && cb(err); - err ? reject(err) : resolve(); - }; + cb && cb(); + resolve(); + }); + }); +}; - var indexSingleDone = function(err, fields, options, name) { - _this.emit('index-single-done', err, fields, options, name); - }; - var indexSingleStart = function(fields, options) { - _this.emit('index-single-start', fields, options); - }; +function _ensureIndexes(model, callback) { + var indexes = model.schema.indexes(); + if (!indexes.length) { + process.nextTick(function() { + callback && callback(); + }); + return; + } + // Indexes are created one-by-one to support how MongoDB < 2.4 deals + // with background indexes. - var create = function() { - var index = indexes.shift(); - if (!index) return done(); + var done = function(err) { + if (err && model.schema.options.emitIndexErrors) { + model.emit('error', err); + } + model.emit('index', err); + callback && callback(err); + }; - var indexFields = index[0]; - var options = index[1]; - _handleSafe(options); + var indexSingleDone = function(err, fields, options, name) { + model.emit('index-single-done', err, fields, options, name); + }; + var indexSingleStart = function(fields, options) { + model.emit('index-single-start', fields, options); + }; - indexSingleStart(indexFields, options); + var create = function() { + var index = indexes.shift(); + if (!index) return done(); - _this.collection.ensureIndex(indexFields, options, tick(function(err, name) { - indexSingleDone(err, indexFields, options, name); - if (err) { - return done(err); - } - create(); - })); - }; + var indexFields = index[0]; + var options = index[1]; + _handleSafe(options); - create(); - }); -}; + indexSingleStart(indexFields, options); + + model.collection.ensureIndex(indexFields, options, tick(function(err, name) { + indexSingleDone(err, indexFields, options, name); + if (err) { + return done(err); + } + create(); + })); + }; + + create(); +} function _handleSafe(options) { if (options.safe) { From 2fe0fd807e7e4365ec7874362f869a499deb89f3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Feb 2016 16:00:38 -0500 Subject: [PATCH 0272/2240] fix: upgrade mongodb -> 2.1.5 for gridfs memory leak (Fix #3854) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 42f94ed0cf6..79f7ac890db 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "0.4.21", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.1.4", + "mongodb": "2.1.5", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.6.3", From 4ccc4dd03f92f061c85eb40a6a31af75c5b9f764 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Feb 2016 16:10:58 -0500 Subject: [PATCH 0273/2240] test: repro #3855 --- test/aggregate.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 80d15ca5699..938df2c2efd 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -667,4 +667,19 @@ describe('aggregate: ', function() { db.close(done); }); }); + + it('cursor() without options (gh-3855)', function(done) { + var db = start(); + + var MyModel = db.model('gh3855', {name: String}); + + db.on('open', function() { + var cursor = MyModel. + aggregate([{$match: {name: 'test'}}]). + cursor(). + exec(); + assert.ok(cursor instanceof require('stream').Readable); + done(); + }); + }); }); From 02815aa2ba56cf9a8a091ee68e14e59d9826e7bb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Feb 2016 16:12:51 -0500 Subject: [PATCH 0274/2240] fix(aggregate): handle cursor() with no args (Fix #3855) --- lib/aggregate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 7aa45f287e0..fd2c2fcf71b 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -469,7 +469,7 @@ Aggregate.prototype.cursor = function(options) { if (!this.options) { this.options = {}; } - this.options.cursor = options; + this.options.cursor = options || {}; return this; }; @@ -518,7 +518,7 @@ Aggregate.prototype.exec = function(callback) { }); } return this._model.collection. - aggregate(this._pipeline, this.options || {}); + aggregate(this._pipeline, this.options || {}); } return new Promise.ES6(function(resolve, reject) { From b5397d8e12b436ce44f3b75f79283835efe8f440 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 Feb 2016 11:16:06 -0500 Subject: [PATCH 0275/2240] docs: autoIndex option for createConnection (Fix #3805) --- lib/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/index.js b/lib/index.js index 5f1c90fd957..57679496cd3 100644 --- a/lib/index.js +++ b/lib/index.js @@ -165,6 +165,8 @@ var checkReplicaSetInUri = function(uri) { * * @param {String} [uri] a mongodb:// URI * @param {Object} [options] options to pass to the driver + * @param {Object} [options.config] mongoose-specific options + * @param {Boolean} [options.config.autoIndex] set to false to disable automatic index creation for all models associated with this connection. * @see Connection#open #connection_Connection-open * @see Connection#openSet #connection_Connection-openSet * @return {Connection} the created Connection object From 1ed81cb3a1aabb1a7e2a921d9a90f4870efb6246 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 Feb 2016 12:27:08 -0500 Subject: [PATCH 0276/2240] test(model): increase timeout for really slow test because of travis --- test/model.indexes.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index 1538a34283d..6e04a0b023e 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -262,7 +262,7 @@ describe('model', function() { }); it('do not trigger "MongoError: cannot add index with a background operation in progress" (gh-1365) LONG', function(done) { - this.timeout(45000); + this.timeout(90000); var db = start({uri: 'mongodb://localhost/mongoose_test_indexing'}); From edff51eb831a12a7f437f4e8c7d0f56f527ab124 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 Feb 2016 12:38:18 -0500 Subject: [PATCH 0277/2240] chore: release 4.4.2 --- History.md | 8 ++++++++ bin/mongoose.js | 6 ++++-- package.json | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 7354068be02..e12abf74f27 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.4.2 / 2016-02-05 +================== + * fix(aggregate): handle calling .cursor() with no options #3855 + * fix: upgrade mongodb driver to 2.1.5 for GridFS memory leak fix #3854 + * docs: fix schematype.html conflict #3853 #3850 #3843 + * fix(model): bluebird unhandled rejection with ensureIndexes() on init #3837 + * docs: autoIndex option for createConnection #3805 + 4.4.1 / 2016-02-03 ================== * fix: linting broke some cases where we use `== null` as shorthand #3852 diff --git a/bin/mongoose.js b/bin/mongoose.js index 5a7883af1fe..1a9b2c9baf0 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -1182,10 +1182,11 @@ Document.prototype.$__shouldModify = function(pathToMark, path, constructing, pa * @memberOf Document */ -Document.prototype.$__set = function(pathToMark, path, constructing, parts, schema, val/* , priorVal */) { +Document.prototype.$__set = function(pathToMark, path, constructing, parts, schema, val, priorVal) { Embedded = Embedded || require('./types/embedded'); - var shouldModify = this.$__shouldModify.apply(this, arguments); + var shouldModify = this.$__shouldModify(pathToMark, path, constructing, parts, + schema, val, priorVal); var _this = this; if (shouldModify) { @@ -1392,6 +1393,7 @@ Document.prototype.isModified = function(path) { * * @param {String} [path] * @return {Boolean} + * @method $isDefault * @api public */ diff --git a/package.json b/package.json index 79f7ac890db..557171ff9a9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.2-pre", + "version": "4.4.2", "author": "Guillermo Rauch ", "keywords": [ "mongodb", @@ -55,6 +55,7 @@ }, "browserDependencies": { "browserify": "4.1.10", + "chai": "3.5.0", "karma": "0.12.16", "karma-chai": "0.1.0", "karma-mocha": "0.1.4", From 8fe1fa3822fa056ca4628aa279870ca2a6e95f44 Mon Sep 17 00:00:00 2001 From: cartucho Date: Sat, 6 Feb 2016 09:51:38 +0000 Subject: [PATCH 0278/2240] Updated mongodb dep to 2.1.6 to avoid kerberos error message --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 557171ff9a9..03e01cc9084 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "0.4.21", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.1.5", + "mongodb": "2.1.6", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.6.3", From e66bfc6165c70f39e7e3c96c7f2f3c1a78f25407 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Feb 2016 17:44:20 -0500 Subject: [PATCH 0279/2240] chore: now working on 4.4.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 557171ff9a9..73eb686cf21 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.2", + "version": "4.4.3-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 0a04079472c6ba18bdbed8d423a6dd648f8f8161 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Feb 2016 17:54:06 -0500 Subject: [PATCH 0280/2240] fix: create a thenable wrapper around mongoose singleton (Fix #3856) --- lib/index.js | 106 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 44 deletions(-) diff --git a/lib/index.js b/lib/index.js index 57679496cd3..6c857036094 100644 --- a/lib/index.js +++ b/lib/index.js @@ -43,6 +43,62 @@ function Mongoose() { conn.models = this.models; } +/** + * Wraps the given Mongoose instance into a thenable (pseudo-promise). This + * is so `connect()` and `disconnect()` can return a thenable while maintaining + * backwards compatibility. + * + * @api private + */ + +function MongooseThenable(mongoose, promise) { + for (var key in mongoose) { + if (typeof mongoose[key] === 'function') { + this[key] = function() { + return mongoose[key].apply(mongoose, arguments); + }; + } else { + this[key] = mongoose[key]; + } + } + this.$opPromise = promise; +} + +/** + * Ability to use mongoose object as a pseudo-promise so `.connect().then()` + * and `.disconnect().then()` are viable. + * + * @param {Function} onFulfilled + * @param {Function} onRejected + * @return {Promise} + * @api private + */ + +MongooseThenable.prototype.then = function(onFulfilled, onRejected) { + var Promise = PromiseProvider.get(); + if (!this.$opPromise) { + return new Promise.ES6(function(resolve, reject) { + reject(new Error('Can only call `.then()` if connect() or disconnect() ' + + 'has been called')); + }).then(onFulfilled, onRejected); + } + return this.$opPromise.then(onFulfilled, onRejected); +}; + +/** + * Ability to use mongoose object as a pseudo-promise so `.connect().then()` + * and `.disconnect().then()` are viable. + * + * @param {Function} onFulfilled + * @param {Function} onRejected + * @return {Promise} + * @api private + */ + +MongooseThenable.prototype.catch = function(onRejected) { + return this.then(null, onRejected); +}; + /** * Expose connection states for user-land * @@ -227,25 +283,23 @@ Mongoose.prototype.createConnection = function(uri, options) { * @param {Function} [callback] * @see Mongoose#createConnection #index_Mongoose-createConnection * @api public - * @return {Mongoose} this + * @return {MongooseThenable} pseudo-promise wrapper around this */ Mongoose.prototype.connect = function() { var conn = this.connection; if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) { - this.$opPromise = conn.openSet.apply(conn, arguments); - return this; + return new MongooseThenable(this, conn.openSet.apply(conn, arguments)); } - this.$opPromise = conn.open.apply(conn, arguments); - return this; + return new MongooseThenable(this, conn.open.apply(conn, arguments)); }; /** * Disconnects all connections. * * @param {Function} [fn] called after all connection close. - * @return {Mongoose} this + * @return {MongooseThenable} pseudo-promise wrapper around this * @api public */ @@ -263,50 +317,14 @@ Mongoose.prototype.disconnect = function(fn) { }); var Promise = PromiseProvider.get(); - this.$opPromise = new Promise.ES6(function(resolve, reject) { + return new MongooseThenable(this, new Promise.ES6(function(resolve, reject) { fn && fn(error); if (error) { reject(error); return; } resolve(); - }); - return this; -}; - -/** - * Ability to use mongoose object as a pseudo-promise so `.connect().then()` - * and `.disconnect().then()` are viable. - * - * @param {Function} onFulfilled - * @param {Function} onRejected - * @return {Promise} - * @api public - */ - -Mongoose.prototype.then = function(onFulfilled, onRejected) { - var Promise = PromiseProvider.get(); - if (!this.$opPromise) { - return new Promise.ES6(function(resolve, reject) { - reject(new Error('Can only call `.then()` if connect() or disconnect() ' + - 'has been called')); - }).then(onFulfilled, onRejected); - } - return this.$opPromise.then(onFulfilled, onRejected); -}; - -/** - * Ability to use mongoose object as a pseudo-promise so `.connect().then()` - * and `.disconnect().then()` are viable. - * - * @param {Function} onFulfilled - * @param {Function} onRejected - * @return {Promise} - * @api public - */ - -Mongoose.prototype.catch = function(onRejected) { - return this.then(null, onRejected); + })); }; /** From 354f994cc63bdabe8f12b0f36fe774cbc57e33d6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 8 Feb 2016 16:16:09 -0500 Subject: [PATCH 0281/2240] fix(types): dont use ES2015 Number.isNaN for backwards compat re #3832 --- lib/schema/date.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/date.js b/lib/schema/date.js index cea9af01d5a..67940565373 100644 --- a/lib/schema/date.js +++ b/lib/schema/date.js @@ -227,7 +227,7 @@ SchemaDate.prototype.cast = function(value) { date = new Date(value.valueOf()); } - if (!Number.isNaN(date.valueOf())) { + if (!isNaN(date.valueOf())) { return date; } From b1aad6554da1e6ace657e1b65f4d749369d7c6ce Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 9 Feb 2016 16:18:14 -0500 Subject: [PATCH 0282/2240] test(populate): repro #3808 --- test/model.populate.test.js | 158 ++++++++++++++++++++++++++---------- 1 file changed, 117 insertions(+), 41 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index a74bc69ebdf..8cfd2021ffc 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -2,14 +2,14 @@ * Test dependencies. */ -var start = require('./common'), - assert = require('power-assert'), - mongoose = start.mongoose, - utils = require('../lib/utils'), - random = utils.random, - Schema = mongoose.Schema, - ObjectId = Schema.ObjectId, - DocObjectId = mongoose.Types.ObjectId; +var start = require('./common'); +var assert = require('power-assert'); +var mongoose = start.mongoose; +var utils = require('../lib/utils'); +var random = utils.random; +var Schema = mongoose.Schema; +var ObjectId = Schema.ObjectId; +var DocObjectId = mongoose.Types.ObjectId; /** * Setup. @@ -152,53 +152,129 @@ describe('model: populate:', function() { }); }); - it('deep population with refs (gh-3507)', function(done) { - var db = start(); - // handler schema - var handlerSchema = new Schema({ - name: String - }); + describe('deep populate', function() { + var db; - // task schema - var taskSchema = new Schema({ - name: String, - handler: {type: Schema.Types.ObjectId, ref: 'gh3507_0'} + before(function() { + db = start(); }); - // application schema - var applicationSchema = new Schema({ - name: String, - tasks: [{type: Schema.Types.ObjectId, ref: 'gh3507_1'}] + after(function(done) { + db.close(done); }); - var Handler = db.model('gh3507_0', handlerSchema); - var Task = db.model('gh3507_1', taskSchema); - var Application = db.model('gh3507_2', applicationSchema); + it('deep population with refs (gh-3507)', function(done) { + // handler schema + var handlerSchema = new Schema({ + name: String + }); - Handler.create({name: 'test'}, function(error, doc) { - assert.ifError(error); - Task.create({name: 'test2', handler: doc._id}, function(error, doc) { + // task schema + var taskSchema = new Schema({ + name: String, + handler: {type: Schema.Types.ObjectId, ref: 'gh3507_0'} + }); + + // application schema + var applicationSchema = new Schema({ + name: String, + tasks: [{type: Schema.Types.ObjectId, ref: 'gh3507_1'}] + }); + + var Handler = db.model('gh3507_0', handlerSchema); + var Task = db.model('gh3507_1', taskSchema); + var Application = db.model('gh3507_2', applicationSchema); + + Handler.create({name: 'test'}, function(error, doc) { assert.ifError(error); - var obj = {name: 'test3', tasks: [doc._id]}; - Application.create(obj, function(error, doc) { + Task.create({name: 'test2', handler: doc._id}, function(error, doc) { assert.ifError(error); - test(doc._id); + var obj = {name: 'test3', tasks: [doc._id]}; + Application.create(obj, function(error, doc) { + assert.ifError(error); + test(doc._id); + }); }); }); + + function test(id) { + Application. + findById(id). + populate([ + {path: 'tasks', populate: {path: 'handler'}} + ]). + exec(function(error, doc) { + assert.ifError(error); + assert.ok(doc.tasks[0].handler._id); + done(); + }); + } }); - function test(id) { - Application. - findById(id). - populate([ - {path: 'tasks', populate: {path: 'handler'}} - ]). - exec(function(error, doc) { + it('multiple paths with same options (gh-3808)', function(done) { + var companySchema = new Schema({ + name: String, + description: String + }); + + var userSchema = new Schema({ + name: String, + company: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Company', + select: false + } + }); + + var messageSchema = new Schema({ + message: String, + author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, + target: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } + }); + + var Company = db.model('Company', companySchema); + var User = db.model('User', userSchema); + var Message = db.model('Message', messageSchema); + + var company = new Company({ name: 'IniTech' }); + var user1 = new User({ name: 'Bill', company: company._id }); + var user2 = new User({ name: 'Peter', company: company._id }); + var message = new Message({ + message: 'Problems with TPS Report', + author: user1._id, + target: user2._id + }); + + company.save(function(error) { assert.ifError(error); - assert.ok(doc.tasks[0].handler._id); - db.close(done); + User.create(user1, user2, function(error) { + assert.ifError(error); + message.save(function(error) { + assert.ifError(error); + next(); + }); + }); }); - } + + function next() { + Message.findOne({ _id: message._id }, function(error, message) { + assert.ifError(error); + var options = { + path: 'author target', + select: '_id name company', + populate: { + path: 'company', + model: 'Company' + } + }; + message.populate(options, function(error) { + assert.ifError(error); + assert.equal(message.target.company.name, 'IniTech'); + done(); + }); + }); + } + }); }); it('populating a single ref', function(done) { From a91c04ee24d30b646b745716b8144951019fa4e9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 9 Feb 2016 16:22:46 -0500 Subject: [PATCH 0283/2240] fix(populate): clone options before modifying (Fix #3808) --- lib/model.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/model.js b/lib/model.js index e050c00e0ab..185f83a87c0 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2516,6 +2516,7 @@ function subPopulate(docs, options, cb) { if (err || !pending) return cb(err); pop.forEach(function(subOptions) { + subOptions = utils.clone(subOptions); // path needs parent's path prefixed to it if (!subOptions._originalPath) { subOptions._originalPath = subOptions.path; From 0aeb6716da4522b736d8833ac101339545201968 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 9 Feb 2016 17:31:40 -0500 Subject: [PATCH 0284/2240] test(query): repro #3820 --- test/model.update.test.js | 121 +++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 42 deletions(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 332fc904e1c..fb02ebbba7e 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1565,61 +1565,98 @@ describe('model: update:', function() { }); }); - it('allows objects with positional operator (gh-3185)', function(done) { - var db = start(); - var schema = new Schema({children: [{_id: Number}]}); - var MyModel = db.model('gh3185', schema, 'gh3185'); + describe('deep casting', function() { + var db; - MyModel.create({children: [{_id: 1}]}, function(error, doc) { - assert.ifError(error); - MyModel.findOneAndUpdate( - {_id: doc._id, 'children._id': 1}, - {$set: {'children.$': {_id: 2}}}, - {new: true}, - function(error, doc) { - assert.ifError(error); - assert.equal(doc.children[0]._id, 2); - db.close(done); - }); + before(function() { + db = start(); }); - }); - it('mixed type casting (gh-3305)', function(done) { - var db = start(); + after(function(done) { + db.close(done); + }); - var Schema = mongoose.Schema({}, {strict: false}); - var Model = db.model('gh3305', Schema); + it('allows objects with positional operator (gh-3185)', function(done) { + var schema = new Schema({children: [{_id: Number}]}); + var MyModel = db.model('gh3185', schema, 'gh3185'); - Model.create({}, function(error, m) { - assert.ifError(error); - Model. - update({_id: m._id}, {$push: {myArr: {key: 'Value'}}}). - exec(function(error, res) { + MyModel.create({children: [{_id: 1}]}, function(error, doc) { assert.ifError(error); - assert.equal(res.n, 1); - db.close(done); + MyModel.findOneAndUpdate( + {_id: doc._id, 'children._id': 1}, + {$set: {'children.$': {_id: 2}}}, + {new: true}, + function(error, doc) { + assert.ifError(error); + assert.equal(doc.children[0]._id, 2); + done(); + }); }); }); - }); - it('mixed nested type casting (gh-3337)', function(done) { - var db = start(); + it('mixed type casting (gh-3305)', function(done) { + var Schema = mongoose.Schema({}, {strict: false}); + var Model = db.model('gh3305', Schema); - var Schema = mongoose.Schema({attributes: {}}, {strict: true}); - var Model = db.model('gh3337', Schema); + Model.create({}, function(error, m) { + assert.ifError(error); + Model. + update({_id: m._id}, {$push: {myArr: {key: 'Value'}}}). + exec(function(error, res) { + assert.ifError(error); + assert.equal(res.n, 1); + done(); + }); + }); + }); - Model.create({}, function(error, m) { - assert.ifError(error); - var update = {$push: {'attributes.scores.bar': {a: 1}}}; - Model. - update({_id: m._id}, update). - exec(function(error, res) { + it('mixed nested type casting (gh-3337)', function(done) { + var Schema = mongoose.Schema({attributes: {}}, {strict: true}); + var Model = db.model('gh3337', Schema); + + Model.create({}, function(error, m) { assert.ifError(error); - assert.equal(res.n, 1); - Model.findById(m._id, function(error, doc) { + var update = {$push: {'attributes.scores.bar': {a: 1}}}; + Model. + update({_id: m._id}, update). + exec(function(error, res) { assert.ifError(error); - assert.equal(doc.attributes.scores.bar.length, 1); - db.close(done); + assert.equal(res.n, 1); + Model.findById(m._id, function(error, doc) { + assert.ifError(error); + assert.equal(doc.attributes.scores.bar.length, 1); + done(); + }); + }); + }); + }); + + it('with single nested (gh-3820)', function(done) { + var child = new mongoose.Schema({ + item2: { + item3: String, + item4: String + } + }); + + var parentSchema = new mongoose.Schema({ + name: String, + item1: child + }); + + var Parent = db.model('Parent', parentSchema); + + Parent.create({ name: 'test' }, function(error, doc) { + assert.ifError(error); + var update = { 'item1.item2': { item3: 'test1', item4: 'test2' } }; + doc.update(update, function(error) { + assert.ifError(error); + Parent.findOne({ _id: doc._id }, function(error, doc) { + assert.ifError(error); + assert.equal(doc.item1.item2.item3, 'test1'); + assert.equal(doc.item1.item2.item4, 'test2'); + done(); + }); }); }); }); From e192865b2a0d803c6b70fa30bc8d33d2778670d9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 9 Feb 2016 17:32:23 -0500 Subject: [PATCH 0285/2240] fix(query): update casting for single nested subdocs (Fix #3820) --- lib/query.js | 11 +++------- lib/schema.js | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/lib/query.js b/lib/query.js index 865275784b5..ac426e28a85 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2343,14 +2343,9 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) { obj[key] = this._castUpdateVal(schema, val, op); hasKeys = true; } else { - var pathToCheck = (prefix + key).replace(/\.\$$/, ''); - pathToCheck = pathToCheck.replace('.$.', '.0.'); - var positionalPath = (prefix + '0.' + key).replace(/\.\$$/, ''); - positionalPath = positionalPath.replace('.$.', '.0.'); - if (this.model.schema.pathType(pathToCheck) === 'adhocOrUndefined' && - !this.model.schema.hasMixedParent(pathToCheck) && - this.model.schema.pathType(positionalPath) === 'adhocOrUndefined' && - !this.model.schema.hasMixedParent(positionalPath)) { + var pathToCheck = (prefix + key); + var v = this.model.schema._getPathType(pathToCheck); + if (v === 'undefined') { if (strict === 'throw') { throw new StrictModeError(pathToCheck); } else if (strict) { diff --git a/lib/schema.js b/lib/schema.js index 0809f3a935e..06b2d7ae5a4 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1271,6 +1271,65 @@ Schema.prototype._getSchema = function(path) { return search(path.split('.'), _this); }; +/*! + * ignore + */ + +Schema.prototype._getPathType = function(path) { + var _this = this; + var pathschema = _this.path(path); + + if (pathschema) { + return 'real'; + } + + function search(parts, schema) { + var p = parts.length + 1, + foundschema, + trypath; + + while (p--) { + trypath = parts.slice(0, p).join('.'); + foundschema = schema.path(trypath); + if (foundschema) { + if (foundschema.caster) { + // array of Mixed? + if (foundschema.caster instanceof MongooseTypes.Mixed) { + return 'mixed'; + } + + // Now that we found the array, we need to check if there + // are remaining document paths to look up for casting. + // Also we need to handle array.$.path since schema.path + // doesn't work for that. + // If there is no foundschema.schema we are dealing with + // a path like array.$ + if (p !== parts.length && foundschema.schema) { + if (parts[p] === '$') { + if (p === parts.length - 1) { + return 'nested'; + } + // comments.$.comments.$.title + return search(parts.slice(p + 1), foundschema.schema); + } + // this is the last path of the selector + return search(parts.slice(p), foundschema.schema); + } + return foundschema.$isSingleNested ? 'nested' : 'array'; + } + return 'real'; + } else if (p === parts.length && schema.nested[trypath]) { + return 'nested'; + } + } + return 'undefined'; + } + + // look for arrays + return search(path.split('.'), _this); +}; + + /*! * Module exports. */ From fae8ac673d6118b11fc86462d874b6f222f8ff12 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 9 Feb 2016 17:44:42 -0500 Subject: [PATCH 0286/2240] docs(middleware): hook order (Fix #1149) --- docs/middleware.jade | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/middleware.jade b/docs/middleware.jade index 16898c69b32..c8afaced3dc 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -136,6 +136,26 @@ block content next(); }); + h3#order Save/Validate Hooks + :markdown + The `save()` function triggers `validate()` hooks, because mongoose + has a built-in `pre('save')` hook that calls `validate()`. This means + that all `pre('validate')` and `post('validate')` hooks get called + **before** any `pre('save')` hooks. + :js + schema.pre('validate', function() { + console.log('this gets printed first'); + }); + schema.post('validate', function() { + console.log('this gets printed second'); + }); + schema.pre('save', function() { + console.log('this gets printed third'); + }); + schema.post('save', function() { + console.log('this gets printed fourth'); + }); + h3#notes Notes on findAndUpdate() and Query Middleware :markdown Pre and post `save()` hooks are **not** executed on `update()`, From 059520ff1c2242c02e1bf9f00ddb9a962947dd37 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 9 Feb 2016 18:38:45 -0500 Subject: [PATCH 0287/2240] chore: release 4.4.3 --- History.md | 8 +++++++ bin/mongoose.js | 61 ++++++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index e12abf74f27..81e18b97e9f 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.4.3 / 2016-02-09 +================== + * fix: upgrade to mongodb 2.1.6 to remove kerberos log output #3861 #3860 [cartuchogl](https://github.com/cartuchogl) + * fix: require('mongoose') is no longer a pseudo-promise #3856 + * fix(query): update casting for single nested docs #3820 + * fix(populate): deep populating multiple paths with same options #3808 + * docs(middleware): clarify save/validate hook order #1149 + 4.4.2 / 2016-02-05 ================== * fix(aggregate): handle calling .cursor() with no options #3855 diff --git a/bin/mongoose.js b/bin/mongoose.js index 1a9b2c9baf0..e39b42d5a53 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -5103,6 +5103,65 @@ Schema.prototype._getSchema = function(path) { return search(path.split('.'), _this); }; +/*! + * ignore + */ + +Schema.prototype._getPathType = function(path) { + var _this = this; + var pathschema = _this.path(path); + + if (pathschema) { + return 'real'; + } + + function search(parts, schema) { + var p = parts.length + 1, + foundschema, + trypath; + + while (p--) { + trypath = parts.slice(0, p).join('.'); + foundschema = schema.path(trypath); + if (foundschema) { + if (foundschema.caster) { + // array of Mixed? + if (foundschema.caster instanceof MongooseTypes.Mixed) { + return 'mixed'; + } + + // Now that we found the array, we need to check if there + // are remaining document paths to look up for casting. + // Also we need to handle array.$.path since schema.path + // doesn't work for that. + // If there is no foundschema.schema we are dealing with + // a path like array.$ + if (p !== parts.length && foundschema.schema) { + if (parts[p] === '$') { + if (p === parts.length - 1) { + return 'nested'; + } + // comments.$.comments.$.title + return search(parts.slice(p + 1), foundschema.schema); + } + // this is the last path of the selector + return search(parts.slice(p), foundschema.schema); + } + return foundschema.$isSingleNested ? 'nested' : 'array'; + } + return 'real'; + } else if (p === parts.length && schema.nested[trypath]) { + return 'nested'; + } + } + return 'undefined'; + } + + // look for arrays + return search(path.split('.'), _this); +}; + + /*! * Module exports. */ @@ -6058,7 +6117,7 @@ SchemaDate.prototype.cast = function(value) { date = new Date(value.valueOf()); } - if (!Number.isNaN(date.valueOf())) { + if (!isNaN(date.valueOf())) { return date; } diff --git a/package.json b/package.json index 3fa58ad0169..f4998327c39 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.3-pre", + "version": "4.4.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 38f47d21b01fcce078af1c733056c35a1183ec59 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 10 Feb 2016 09:43:05 -0500 Subject: [PATCH 0288/2240] chore: now working on 4.4.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4998327c39..5373f1060d0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.3", + "version": "4.4.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From dce50b53e65e83d336b6938d8b02aa471f4b5b9e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 11 Feb 2016 10:06:16 -0500 Subject: [PATCH 0289/2240] docs: link to execPopulate from document.populate (Fix #3836) --- lib/document.js | 18 +++++++++++------- lib/drivers/node-mongodb-native/connection.js | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/document.js b/lib/document.js index f9da6988127..522c687e9d8 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2208,6 +2208,8 @@ Document.prototype.equals = function(doc) { /** * Populates document references, executing the `callback` when complete. + * If you want to use promises instead, use this function with + * [`execPopulate()`](#document_Document-execPopulate) * * ####Example: * @@ -2224,11 +2226,12 @@ Document.prototype.equals = function(doc) { * }) * * // summary - * doc.populate(path) // not executed - * doc.populate(options); // not executed - * doc.populate(path, callback) // executed - * doc.populate(options, callback); // executed - * doc.populate(callback); // executed + * doc.populate(path) // not executed + * doc.populate(options); // not executed + * doc.populate(path, callback) // executed + * doc.populate(options, callback); // executed + * doc.populate(callback); // executed + * doc.populate(options).execPopulate() // executed, returns promise * * * ####NOTE: @@ -2239,6 +2242,7 @@ Document.prototype.equals = function(doc) { * See [Model.populate()](#model_Model.populate) for explaination of options. * * @see Model.populate #model_Model.populate + * @see Document.execPopulate #document_Document-execPopulate * @param {String|Object} [path] The path to populate or an options object * @param {Function} [callback] When passed, population is invoked * @api public @@ -2278,7 +2282,7 @@ Document.prototype.populate = function populate() { }; /** - * Explicitly executes population and returns a promise. Useful for ES6 + * Explicitly executes population and returns a promise. Useful for ES2015 * integration. * * ####Example: @@ -2295,7 +2299,7 @@ Document.prototype.populate = function populate() { * execPopulate(); * * // summary - * doc.execPopulate() + * doc.execPopulate().then(resolve, reject); * * * @see Document.populate #Document_model.populate diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 0e417f7143f..be9cc73ff1c 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -55,8 +55,8 @@ NativeConnection.prototype.doOpen = function(fn) { var _this = this; this.db.open(function(err) { - if (err) return fn(err); listen(_this); + if (err) return fn(err); fn(); }); From bf7c4f445fef7a952a3dccd590e148f51fddbdf9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 11 Feb 2016 18:36:11 -0500 Subject: [PATCH 0290/2240] test(document): repro #3867 --- test/document.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 5312fc41f43..a7abce6524e 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2377,5 +2377,30 @@ describe('document', function() { }); }); }); + + it('handles conflicting names (gh-3867)', function(done) { + var testSchema = new Schema({ + name: { + type: String, + required: true + }, + things: [{ + name: { + type: String, + required: true + } + }] + }); + + var M = mongoose.model('gh3867', testSchema); + + var doc = M({ + things: [{}] + }); + + var fields = Object.keys(doc.validateSync().errors).sort(); + assert.deepEqual(fields, ['name', 'things.0.name']); + done(); + }); }); }); From 5f39017399dd4f11cd50604cc893e296631a6626 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 11 Feb 2016 18:36:32 -0500 Subject: [PATCH 0291/2240] fix(document): conflicting names (Fix #3867) --- lib/types/embedded.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/types/embedded.js b/lib/types/embedded.js index feecf12cd9d..c1bdd9a0f6c 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -226,7 +226,8 @@ EmbeddedDocument.prototype.$markValid = function(path) { EmbeddedDocument.prototype.$isValid = function(path) { var index = this.__index; if (typeof index !== 'undefined') { - return !this.__parent.$__.validationError || !this.__parent.$__.validationError.errors[path]; + return !this.__parent.$__.validationError || + !this.__parent.$__.validationError.errors[this.$__fullPath(path)]; } return true; From cca28e1ce554371812e53f122f9b8173496392eb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 11 Feb 2016 20:58:01 -0500 Subject: [PATCH 0292/2240] fix(drivers): pass promiseLibrary along to mongodb re: #3869 --- lib/drivers/node-mongodb-native/connection.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index be9cc73ff1c..f600665ad3e 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -330,6 +330,10 @@ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { o.db.w = 1; } + if (o.promiseLibrary) { + o.db.promiseLibrary = o.promiseLibrary; + } + validate(o); return o; }; From 4237515684bbab8401e579125f2a3b204765bd83 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 11 Feb 2016 20:59:17 -0500 Subject: [PATCH 0293/2240] docs: clarify promiseLibrary for underlying driver re #3869 --- test/docs/promises.test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/docs/promises.test.js b/test/docs/promises.test.js index e76f5b2b180..e0496c2f38e 100644 --- a/test/docs/promises.test.js +++ b/test/docs/promises.test.js @@ -125,4 +125,32 @@ describe('promises docs', function () { done(); // acquit:ignore:end }); + + /** + * The `mongoose.Promise` property sets the promises mongoose uses. However, + * this does **not** affect the underlying MongoDB driver. If you use the + * underlying driver, for instance `Model.collection.db.insert()`, you + * need to do a little extra work to change the underlying promises library. + * Note that the below code assumes mongoose >= 4.4.4. + */ + it('Promises for the MongoDB Driver', function (done) { + // acquit:ignore:start + if (!global.Promise) { + return done(); + } + // acquit:ignore:end + var uri = 'mongodb://localhost:27017/mongoose_test'; + // Use bluebird + var options = { promiseLibrary: require('bluebird') }; + var db = mongoose.createConnection(uri, options); + + Band = db.model('band-promises', { name: String }); + + db.on('open', function() { + assert.equal(Band.collection.findOne().constructor, require('bluebird')); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); }); From 8c27f40760eab87f7f1c5559f07c06ba730db0bc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 12 Feb 2016 08:36:48 -0500 Subject: [PATCH 0294/2240] fix(connection): dont auth if already connected for useDb (Fix #3871) --- lib/connection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index e2fa0037da0..84cc68add35 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -511,8 +511,8 @@ Connection.prototype.onOpen = function(callback) { _this.emit('open'); } - // re-authenticate - if (this.shouldAuthenticate()) { + // re-authenticate if we're not already connected #3871 + if (this._readyState !== STATES.connected && this.shouldAuthenticate()) { _this.db.authenticate(_this.user, _this.pass, _this.options.auth, function(err) { open(err, true); }); From 3ea27b79ee66f0bd96171b761eec9fa1a1bb6665 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 12 Feb 2016 09:37:26 -0500 Subject: [PATCH 0295/2240] test: repro #3873 --- test/document.test.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index a7abce6524e..975b93d2bf7 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2402,5 +2402,42 @@ describe('document', function() { assert.deepEqual(fields, ['name', 'things.0.name']); done(); }); + + it('populate with lean (gh-3873)', function(done) { + var companySchema = new mongoose.Schema({ + name: String, + description: String, + userCnt: { type: Number, default: 0, select: false } + }); + + var userSchema = new mongoose.Schema({ + name: String, + company: { type: mongoose.Schema.Types.ObjectId, ref: 'gh3873' } + }); + + var Company = db.model('gh3873', companySchema); + var User = db.model('gh3873_0', userSchema); + + var company = new Company({ name: 'IniTech', userCnt: 1 }); + var user = new User({ name: 'Peter', company: company._id }); + + company.save(function(error) { + assert.ifError(error); + user.save(function(error) { + assert.ifError(error); + next(); + }); + }); + + function next() { + var pop = { path: 'company', select: 'name', options: { lean: true } }; + User.find({}).populate(pop).exec(function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 1); + assert.strictEqual(docs[0].company.userCnt, undefined); + done(); + }); + } + }); }); }); From f87eafae8ba1303bec73ab639d9aaeb44f5c78c8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 12 Feb 2016 09:45:37 -0500 Subject: [PATCH 0296/2240] fix: dont hydrate populated subdoc if lean (Fix #3873) --- lib/schema/objectid.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index 51bcb4947e9..ef11b875542 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -104,8 +104,16 @@ ObjectId.prototype.cast = function(value, doc, init) { var path = doc.$__fullPath(this.path); var owner = doc.ownerDocument ? doc.ownerDocument() : doc; var pop = owner.populated(path, true); - var ret = new pop.options.model(value); - ret.$__.wasPopulated = true; + var ret = value; + if (!doc.$__.populated || + !doc.$__.populated[path] || + !doc.$__.populated[path].options || + !doc.$__.populated[path].options.options || + !doc.$__.populated[path].options.options.lean) { + ret = new pop.options.model(value); + ret.$__.wasPopulated = true; + } + return ret; } From 7e29e5651c5a0f8faf6b9f9744aca849f1413030 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 13 Feb 2016 19:54:24 -0500 Subject: [PATCH 0297/2240] style(document): clean up some weird indentation --- lib/document.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/document.js b/lib/document.js index 522c687e9d8..aef314566cf 100644 --- a/lib/document.js +++ b/lib/document.js @@ -634,13 +634,14 @@ Document.prototype.set = function(path, val, type, options) { schema.options.ref === val.constructor.modelName) { if (this.ownerDocument) { this.ownerDocument().populated(this.$__fullPath(path), - val._id, {model: val.constructor}); + val._id, {model: val.constructor}); } else { this.populated(path, val._id, {model: val.constructor}); } didPopulate = true; } + var popOpts; if (schema.options && Array.isArray(schema.options.type) && schema.options.type.length && @@ -651,17 +652,12 @@ Document.prototype.set = function(path, val, type, options) { val[0].constructor.modelName && schema.options.type[0].ref === val[0].constructor.modelName) { if (this.ownerDocument) { + popOpts = { model: val[0].constructor }; this.ownerDocument().populated(this.$__fullPath(path), - val.map(function(v) { - return v._id; - }), - {model: val[0].constructor}); + val.map(function(v) { return v._id; }), popOpts); } else { - this.populated(path, val - .map(function(v) { - return v._id; - }), - {model: val[0].constructor}); + popOpts = { model: val[0].constructor }; + this.populated(path, val.map(function(v) { return v._id; }), popOpts); } didPopulate = true; } From 16195821bbbe35044d131f21c3d802a3ed62a9c5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 14 Feb 2016 14:51:40 -0500 Subject: [PATCH 0298/2240] fix: need to curry MongooseThenable loop (Fix #3874) --- lib/index.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/index.js b/lib/index.js index 6c857036094..9546e61f715 100644 --- a/lib/index.js +++ b/lib/index.js @@ -52,11 +52,14 @@ function Mongoose() { */ function MongooseThenable(mongoose, promise) { + var _this = this; for (var key in mongoose) { if (typeof mongoose[key] === 'function') { - this[key] = function() { - return mongoose[key].apply(mongoose, arguments); - }; + (function(key) { + _this[key] = function() { + return mongoose[key].apply(mongoose, arguments); + }; + })(key); } else { this[key] = mongoose[key]; } From 8f14ee26968c015e312318aae7e00a4313020306 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 15 Feb 2016 12:46:41 -0500 Subject: [PATCH 0299/2240] docs: coverage for global plugin function (Fix #3732) --- docs/plugins.jade | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/plugins.jade b/docs/plugins.jade index d768c95d4d9..58277af9c36 100644 --- a/docs/plugins.jade +++ b/docs/plugins.jade @@ -33,6 +33,20 @@ block content Player.plugin(lastMod); :markdown We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code. + h3#global Global Plugins + :markdown + Want to register a plugin for all schemas? The mongoose singleton has a + `.plugin()` function that registers a plugin for every schema. For + example: + :js + var mongoose = require('mongoose'); + mongoose.plugin(require('./lastMod')); + + var gameSchema = new Schema({ ... }); + var playerSchema = new Schema({ ... }); + // `lastModifiedPlugin` gets attached to both schemas + var Game = mongoose.model('Game', gameSchema); + var Player = mongoose.model('Player', playerSchema); h3 Community! :markdown Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. From b5df43eda4b5525a3f483c099560dcc4dd99b911 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 16 Feb 2016 15:34:47 -0500 Subject: [PATCH 0300/2240] test: repro #3859 --- test/model.populate.test.js | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 8cfd2021ffc..ef68ff4e374 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -533,6 +533,58 @@ describe('model: populate:', function() { }); }); + it('undefined for nested paths (gh-3859)', function(done) { + var db = start(); + + var companySchema = new mongoose.Schema({ + name: String, + description: String + }); + + var userSchema = new mongoose.Schema({ + name: String, + company: {type: mongoose.Schema.Types.ObjectId, ref: 'Company'} + }); + + var sampleSchema = new mongoose.Schema({ + items: [userSchema] + }); + + var Company = db.model('gh3859_0', companySchema); + var User = db.model('gh3859_1', userSchema); + var Sample = db.model('gh3859_2', sampleSchema); + + var company = new Company({name: 'Reynholm Industrie'}); + var user1 = new User({name: 'Douglas', company: company._id}); + var user2 = new User({name: 'Lambda'}); + var sample = new Sample({ + items: [user1, user2] + }); + + company.save(function(error) { + assert.ifError(error); + User.create(user1, user2, function(error) { + assert.ifError(error); + sample.save(function(error) { + assert.ifError(error); + next(); + }); + }); + }); + + function next() { + Sample.findOne({}, function(error, sample) { + assert.ifError(error); + var opts = { path: 'items.company', options: { lean: true } }; + Company.populate(sample, opts, function(error) { + assert.ifError(error); + assert.strictEqual(sample.items[1].company, void 0); + db.close(done); + }); + }); + } + }); + it('population and changing a reference', function(done) { var db = start(), BlogPost = db.model('RefBlogPost', posts), From 6dab7d9d653ca21d8291a639c46ed5b66d0454e3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 16 Feb 2016 15:35:54 -0500 Subject: [PATCH 0301/2240] fix(populate): dont assign null unnecessarily (Fix #3859) re: #3074 --- lib/model.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/model.js b/lib/model.js index 185f83a87c0..b007bca9199 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3013,6 +3013,9 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re // can safely use this to our advantage dealing with sorted // result sets too. newOrder.forEach(function(doc, i) { + if (!doc) { + return; + } rawIds[i] = doc; }); } From 99411981084d12c65737cfc0416a4d6881b394c8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 Feb 2016 10:23:34 -0500 Subject: [PATCH 0302/2240] test: move some populate tests to use same db --- test/model.populate.test.js | 172 ++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 85 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index ef68ff4e374..c32144a4223 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3105,10 +3105,18 @@ describe('model: populate:', function() { } }); - describe('gh-2252', function() { - it('handles skip', function(done) { - var db = start(); + describe('edge cases', function() { + var db; + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('handles skip', function(done) { var movieSchema = new Schema({}); var categorySchema = new Schema({movies: [{type: ObjectId, ref: 'gh-2252-1'}]}); @@ -3125,117 +3133,111 @@ describe('model: populate:', function() { Category.findOne({}).populate({path: 'movies', options: {limit: 2, skip: 1}}).exec(function(error, category) { assert.ifError(error); assert.equal(2, category.movies.length); - db.close(done); + done(); }); }); }); }); }); - }); - it('handles slice (gh-1934)', function(done) { - var db = start(); + it('handles slice (gh-1934)', function(done) { + var movieSchema = new Schema({title: String, actors: [String]}); + var categorySchema = new Schema({movies: [{type: ObjectId, ref: 'gh-1934-1'}]}); - var movieSchema = new Schema({title: String, actors: [String]}); - var categorySchema = new Schema({movies: [{type: ObjectId, ref: 'gh-1934-1'}]}); - - var Movie = db.model('gh-1934-1', movieSchema); - var Category = db.model('gh-1934-2', categorySchema); - var movies = [ - {title: 'Rush', actors: ['Chris Hemsworth', 'Daniel Bruhl']}, - {title: 'Pacific Rim', actors: ['Charlie Hunnam', 'Idris Elba']}, - {title: 'Man of Steel', actors: ['Henry Cavill', 'Amy Adams']} - ]; - Movie.create(movies[0], movies[1], movies[2], function(error, m1, m2, m3) { - assert.ifError(error); - Category.create({movies: [m1._id, m2._id, m3._id]}, function(error) { + var Movie = db.model('gh-1934-1', movieSchema); + var Category = db.model('gh-1934-2', categorySchema); + var movies = [ + {title: 'Rush', actors: ['Chris Hemsworth', 'Daniel Bruhl']}, + {title: 'Pacific Rim', actors: ['Charlie Hunnam', 'Idris Elba']}, + {title: 'Man of Steel', actors: ['Henry Cavill', 'Amy Adams']} + ]; + Movie.create(movies[0], movies[1], movies[2], function(error, m1, m2, m3) { assert.ifError(error); - Category.findOne({}).populate({path: 'movies', options: {slice: {actors: 1}}}).exec(function(error, category) { + Category.create({movies: [m1._id, m2._id, m3._id]}, function(error) { assert.ifError(error); - assert.equal(category.movies.length, 3); - assert.equal(category.movies[0].actors.length, 1); - assert.equal(category.movies[1].actors.length, 1); - assert.equal(category.movies[2].actors.length, 1); - done(); + Category.findOne({}).populate({path: 'movies', options: {slice: {actors: 1}}}).exec(function(error, category) { + assert.ifError(error); + assert.equal(category.movies.length, 3); + assert.equal(category.movies[0].actors.length, 1); + assert.equal(category.movies[1].actors.length, 1); + assert.equal(category.movies[2].actors.length, 1); + done(); + }); }); }); }); - }); - it('handles toObject() (gh-3279)', function(done) { - var db = start(); - - var teamSchema = new Schema({ - members: [{ - user: {type: ObjectId, ref: 'gh3279'}, - role: String - }] - }); - - var calls = 0; - teamSchema.set('toJSON', { - transform: function(doc, ret) { - ++calls; - return ret; - } - }); + it('handles toObject() (gh-3279)', function(done) { + var teamSchema = new Schema({ + members: [{ + user: {type: ObjectId, ref: 'gh3279'}, + role: String + }] + }); + var calls = 0; + teamSchema.set('toJSON', { + transform: function(doc, ret) { + ++calls; + return ret; + } + }); - var Team = db.model('gh3279_1', teamSchema); - var userSchema = new Schema({ - username: String - }); + var Team = db.model('gh3279_1', teamSchema); - userSchema.set('toJSON', { - transform: function(doc, ret) { - return ret; - } - }); + var userSchema = new Schema({ + username: String + }); - var User = db.model('gh3279', userSchema); + userSchema.set('toJSON', { + transform: function(doc, ret) { + return ret; + } + }); - var user = new User({username: 'Test'}); + var User = db.model('gh3279', userSchema); - user.save(function(err) { - assert.ifError(err); - var team = new Team({members: [{user: user}]}); + var user = new User({username: 'Test'}); - team.save(function(err) { + user.save(function(err) { assert.ifError(err); - team.populate('members.user', function() { - team.toJSON(); - assert.equal(calls, 1); - done(); + var team = new Team({members: [{user: user}]}); + + team.save(function(err) { + assert.ifError(err); + team.populate('members.user', function() { + team.toJSON(); + assert.equal(calls, 1); + done(); + }); }); }); }); - }); - - it('populate option (gh-2321)', function(done) { - var db = start(); - var User = db.model('User', {name: String}); - var Group = db.model('Group', { - users: [{type: mongoose.Schema.Types.ObjectId, ref: 'User'}], - name: String - }); - - User.create({name: 'Val'}, function(error, user) { - assert.ifError(error); - Group.create({users: [user._id], name: 'test'}, function(error, group) { - assert.ifError(error); - test(group._id); + it('populate option (gh-2321)', function(done) { + var User = db.model('User', {name: String}); + var Group = db.model('Group', { + users: [{type: mongoose.Schema.Types.ObjectId, ref: 'User'}], + name: String }); - }); - var test = function(id) { - var options = {populate: {path: 'users', model: 'User'}}; - Group.find({_id: id}, '-name', options, function(error, group) { + User.create({name: 'Val'}, function(error, user) { assert.ifError(error); - assert.ok(group[0].users[0]._id); - db.close(done); + Group.create({users: [user._id], name: 'test'}, function(error, group) { + assert.ifError(error); + test(group._id); + }); }); - }; + + var test = function(id) { + var options = {populate: {path: 'users', model: 'User'}}; + Group.find({_id: id}, '-name', options, function(error, group) { + assert.ifError(error); + assert.ok(group[0].users[0]._id); + db.close(done); + }); + }; + }); }); }); From bf0b27b95f6b4c8d2febe579684a430622c76525 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 Feb 2016 10:36:30 -0500 Subject: [PATCH 0303/2240] test: repro #3878 --- test/model.populate.test.js | 43 ++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index c32144a4223..71472766f2a 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3235,9 +3235,50 @@ describe('model: populate:', function() { Group.find({_id: id}, '-name', options, function(error, group) { assert.ifError(error); assert.ok(group[0].users[0]._id); - db.close(done); + done(); }); }; }); + + it('discriminator child schemas (gh-3878)', function(done) { + var options = { discriminatorKey: 'kind' }; + var activitySchema = new Schema({ title: { type: String } }, options); + + var dateActivitySchema = new Schema({ + postedBy: { type: Schema.Types.ObjectId, ref: 'gh3878', required: true } + }, options); + + var eventActivitySchema = new Schema({ test: String }, options); + + var User = db.model('gh3878', { name: String }); + var Activity = db.model('gh3878_0', activitySchema); + var DateActivity = Activity.discriminator('Date', dateActivitySchema); + var EventActivity = Activity.discriminator('Event', eventActivitySchema); + + User.create({ name: 'val' }, function(error, user) { + assert.ifError(error); + var dateActivity = { title: 'test', postedBy: user._id }; + DateActivity.create(dateActivity, function(error) { + assert.ifError(error); + var eventActivity = { + title: 'test2', + test: 'test' + }; + EventActivity.create(eventActivity, function(error) { + assert.ifError(error); + test(); + }); + }); + }); + + function test() { + Activity.find({}).populate('postedBy').exec(function(error, results) { + assert.ifError(error); + assert.equal(results.length, 2); + assert.equal(results[0].postedBy.name, 'val'); + done(); + }); + } + }); }); }); From 35c496ddeb0a2b1fdeab1807e59e0416e2bdf9f8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 Feb 2016 10:37:50 -0500 Subject: [PATCH 0304/2240] fix(populate): dont stop populate if no ids for a doc (Fix #3878) --- lib/model.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index b007bca9199..4635f7ad226 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2600,6 +2600,7 @@ function populate(model, docs, options, cb) { } var _remaining = len; + var hasOne = false; for (i = 0; i < len; i++) { mod = modelsMap[i]; select = mod.options.select; @@ -2611,13 +2612,14 @@ function populate(model, docs, options, cb) { } var ids = utils.array.flatten(mod.ids, flatten); - ids = utils.array.unique(ids); if (ids.length === 0 || ids.every(utils.isNullOrUndefined)) { - return cb(); + --_remaining; + continue; } + hasOne = true; match._id || (match._id = { $in: ids }); @@ -2647,6 +2649,10 @@ function populate(model, docs, options, cb) { mod.Model.find(match, select, mod.options.options, next.bind(this, mod.options, assignmentOpts)); } + if (!hasOne) { + return cb(); + } + function next(options, assignmentOpts, err, valsFromDb) { if (err) return promise.resolve(err); vals = vals.concat(valsFromDb); From 5f84f72fd0b70e412278a1c58777bd1a57a5cca0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 Feb 2016 11:35:48 -0500 Subject: [PATCH 0305/2240] test: repro #3880 --- test/document.test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 975b93d2bf7..8741965db9c 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2439,5 +2439,36 @@ describe('document', function() { }); } }); + + it('init single nested subdoc with select (gh-3880)', function(done) { + var childSchema = new mongoose.Schema({ + name: { type: String }, + friends: [{ type: String }] + }); + + var parentSchema = new mongoose.Schema({ + name: { type: String }, + child: childSchema + }); + + var Parent = db.model('gh3880', parentSchema); + var p = new Parent({ + name: 'Mufasa', + child: { + name: 'Simba', + friends: ['Pumbaa', 'Timon', 'Nala'] + } + }); + + p.save(function(error) { + assert.ifError(error); + var fields = 'name child.name'; + Parent.findById(p._id).select(fields).exec(function(error, doc) { + assert.ifError(error); + assert.strictEqual(doc.child.friends, void 0); + done(); + }); + }); + }); }); }); From be4584b699de05464868546aa0682697c1a51861 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 Feb 2016 11:37:16 -0500 Subject: [PATCH 0306/2240] fix(types): handle fields when casting single nested subdoc (Fix #3880) --- lib/document.js | 1 + lib/schema/embedded.js | 2 +- lib/types/subdocument.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index aef314566cf..a5e52afb9e0 100644 --- a/lib/document.js +++ b/lib/document.js @@ -155,6 +155,7 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) { // determine if this doc is a result of a query with // excluded fields + if (fields && utils.getFunctionName(fields.constructor) === 'Object') { keys = Object.keys(fields); ki = keys.length; diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index f0444f5eb28..46d997a25c7 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -59,7 +59,7 @@ Embedded.prototype.cast = function(val, doc, init) { if (val && val.$isSingleNested) { return val; } - var subdoc = new this.caster(undefined, undefined, doc); + var subdoc = new this.caster(undefined, doc.$__.selected, doc); if (init) { subdoc.init(val); } else { diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index de127a5dae3..56d14484033 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -11,8 +11,8 @@ module.exports = Subdocument; */ function Subdocument() { - Document.apply(this, arguments); this.$isSingleNested = true; + Document.apply(this, arguments); } Subdocument.prototype = Object.create(Document.prototype); From 576d057403a38ae7dfa8c3e43c3496083e710928 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 Feb 2016 11:54:11 -0500 Subject: [PATCH 0307/2240] chore: release 4.4.4 --- History.md | 13 ++++++++++++ bin/mongoose.js | 54 +++++++++++++++++++++++++++++-------------------- package.json | 2 +- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/History.md b/History.md index 81e18b97e9f..8730b12fcc7 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,16 @@ +4.4.4 / 2016-02-17 +================== + * fix(schema): handle field selection when casting single nested subdocs #3880 + * fix(populate): populating using base model with multiple child models in result #3878 + * fix: ability to properly use return value of `mongoose.connect()` #3874 + * fix(populate): dont hydrate populated subdoc if lean option set #3873 + * fix(connection): dont re-auth if already connected with useDb #3871 + * docs: cover how to set underlying driver's promise lib #3869 + * fix(document): handle conflicting names in validation errors with subdocs #3867 + * fix(populate): set undefined instead of null consistently when populate couldn't find results #3859 + * docs: link to `execPopulate()` in `doc.populate()` docs #3836 + * docs(plugin): link to the `mongoose.plugin()` function #3732 + 4.4.3 / 2016-02-09 ================== * fix: upgrade to mongodb 2.1.6 to remove kerberos log output #3861 #3860 [cartuchogl](https://github.com/cartuchogl) diff --git a/bin/mongoose.js b/bin/mongoose.js index e39b42d5a53..9c7b2947ae0 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -599,6 +599,7 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) { // determine if this doc is a result of a query with // excluded fields + if (fields && utils.getFunctionName(fields.constructor) === 'Object') { keys = Object.keys(fields); ki = keys.length; @@ -1078,13 +1079,14 @@ Document.prototype.set = function(path, val, type, options) { schema.options.ref === val.constructor.modelName) { if (this.ownerDocument) { this.ownerDocument().populated(this.$__fullPath(path), - val._id, {model: val.constructor}); + val._id, {model: val.constructor}); } else { this.populated(path, val._id, {model: val.constructor}); } didPopulate = true; } + var popOpts; if (schema.options && Array.isArray(schema.options.type) && schema.options.type.length && @@ -1095,17 +1097,12 @@ Document.prototype.set = function(path, val, type, options) { val[0].constructor.modelName && schema.options.type[0].ref === val[0].constructor.modelName) { if (this.ownerDocument) { + popOpts = { model: val[0].constructor }; this.ownerDocument().populated(this.$__fullPath(path), - val.map(function(v) { - return v._id; - }), - {model: val[0].constructor}); + val.map(function(v) { return v._id; }), popOpts); } else { - this.populated(path, val - .map(function(v) { - return v._id; - }), - {model: val[0].constructor}); + popOpts = { model: val[0].constructor }; + this.populated(path, val.map(function(v) { return v._id; }), popOpts); } didPopulate = true; } @@ -2652,6 +2649,8 @@ Document.prototype.equals = function(doc) { /** * Populates document references, executing the `callback` when complete. + * If you want to use promises instead, use this function with + * [`execPopulate()`](#document_Document-execPopulate) * * ####Example: * @@ -2668,11 +2667,12 @@ Document.prototype.equals = function(doc) { * }) * * // summary - * doc.populate(path) // not executed - * doc.populate(options); // not executed - * doc.populate(path, callback) // executed - * doc.populate(options, callback); // executed - * doc.populate(callback); // executed + * doc.populate(path) // not executed + * doc.populate(options); // not executed + * doc.populate(path, callback) // executed + * doc.populate(options, callback); // executed + * doc.populate(callback); // executed + * doc.populate(options).execPopulate() // executed, returns promise * * * ####NOTE: @@ -2683,6 +2683,7 @@ Document.prototype.equals = function(doc) { * See [Model.populate()](#model_Model.populate) for explaination of options. * * @see Model.populate #model_Model.populate + * @see Document.execPopulate #document_Document-execPopulate * @param {String|Object} [path] The path to populate or an options object * @param {Function} [callback] When passed, population is invoked * @api public @@ -2722,7 +2723,7 @@ Document.prototype.populate = function populate() { }; /** - * Explicitly executes population and returns a promise. Useful for ES6 + * Explicitly executes population and returns a promise. Useful for ES2015 * integration. * * ####Example: @@ -2739,7 +2740,7 @@ Document.prototype.populate = function populate() { * execPopulate(); * * // summary - * doc.execPopulate() + * doc.execPopulate().then(resolve, reject); * * * @see Document.populate #Document_model.populate @@ -6527,7 +6528,7 @@ Embedded.prototype.cast = function(val, doc, init) { if (val && val.$isSingleNested) { return val; } - var subdoc = new this.caster(undefined, undefined, doc); + var subdoc = new this.caster(undefined, doc.$__.selected, doc); if (init) { subdoc.init(val); } else { @@ -7125,8 +7126,16 @@ ObjectId.prototype.cast = function(value, doc, init) { var path = doc.$__fullPath(this.path); var owner = doc.ownerDocument ? doc.ownerDocument() : doc; var pop = owner.populated(path, true); - var ret = new pop.options.model(value); - ret.$__.wasPopulated = true; + var ret = value; + if (!doc.$__.populated || + !doc.$__.populated[path] || + !doc.$__.populated[path].options || + !doc.$__.populated[path].options.options || + !doc.$__.populated[path].options.options.lean) { + ret = new pop.options.model(value); + ret.$__.wasPopulated = true; + } + return ret; } @@ -10381,7 +10390,8 @@ EmbeddedDocument.prototype.$markValid = function(path) { EmbeddedDocument.prototype.$isValid = function(path) { var index = this.__index; if (typeof index !== 'undefined') { - return !this.__parent.$__.validationError || !this.__parent.$__.validationError.errors[path]; + return !this.__parent.$__.validationError || + !this.__parent.$__.validationError.errors[this.$__fullPath(path)]; } return true; @@ -10519,8 +10529,8 @@ module.exports = Subdocument; */ function Subdocument() { - Document.apply(this, arguments); this.$isSingleNested = true; + Document.apply(this, arguments); } Subdocument.prototype = Object.create(Document.prototype); diff --git a/package.json b/package.json index 5373f1060d0..14283f5056b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.4-pre", + "version": "4.4.4", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ad298cb0e58105271a794043fa5ac6d8da812f93 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 18 Feb 2016 11:58:14 -0500 Subject: [PATCH 0308/2240] docs: use plugins.mongoosejs.io --- CONTRIBUTING.md | 6 +++--- README.md | 2 +- docs/guide.jade | 2 +- docs/plugins.jade | 2 +- index.jade | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 02f24b7d2ea..aae2ca0a1a0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,7 @@ If you have a question about Mongoose (not a bug report) please post it to eithe - Before opening a new issue, look for existing [issues](https://github.com/learnboost/mongoose/issues) to avoid duplication. If the issue does not yet exist, [create one](https://github.com/learnboost/mongoose/issues/new). - Please describe the issue you are experiencing, along with any associated stack trace. - Please post code that reproduces the issue, the version of mongoose, node version, and mongodb version. - - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. + - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. ### Requesting new features @@ -18,7 +18,7 @@ If you have a question about Mongoose (not a bug report) please post it to eithe ### Fixing bugs / Adding features - Before starting to write code, look for existing [issues](https://github.com/learnboost/mongoose/issues). That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. You can create a new issue [here](https://github.com/learnboost/mongoose/issues/new). - - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. + - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. - Fork the [repo](https://github.com/Automattic/mongoose) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. - Follow the general coding style of the rest of the project: - 2 space tabs @@ -48,4 +48,4 @@ If you'd like to preview your documentation changes, first commit your changes t ### Plugins website -The [plugins](http://plugins.mongoosejs.com/) site is also an [open source project](https://github.com/aheckmann/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! +The [plugins](http://plugins.mongoosejs.io/) site is also an [open source project](https://github.com/aheckmann/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! diff --git a/README.md b/README.md index 0f9e9580b4b..f137e04c88c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed ## Plugins -Check out the [plugins search site](http://plugins.mongoosejs.com/) to see hundreds of related modules from the community. +Check out the [plugins search site](http://plugins.mongoosejs.io/) to see hundreds of related modules from the community. Build your own Mongoose plugin through [generator-mongoose-plugin](https://github.com/huei90/generator-mongoose-plugin). diff --git a/docs/guide.jade b/docs/guide.jade index e1d7c579b48..bf3bcdd9914 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -629,7 +629,7 @@ block content | Schemas are also a(href="./plugins.html") pluggable | which allows us to package up reusable features into - a(href="http://plugins.mongoosejs.com") plugins + a(href="http://plugins.mongoosejs.io") plugins | that can be shared with the community or just between your projects. h3#next Next Up diff --git a/docs/plugins.jade b/docs/plugins.jade index 58277af9c36..a78a97e4e0b 100644 --- a/docs/plugins.jade +++ b/docs/plugins.jade @@ -49,7 +49,7 @@ block content var Player = mongoose.model('Player', playerSchema); h3 Community! :markdown - Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. + Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.io) page. h3#next Next Up :markdown diff --git a/index.jade b/index.jade index e106075976f..8d88146ee68 100644 --- a/index.jade +++ b/index.jade @@ -25,7 +25,7 @@ html(lang='en') li a(href="docs/guide.html") Read the Docs li - a(href="http://plugins.mongoosejs.com") Discover Plugins + a(href="http://plugins.mongoosejs.io") Discover Plugins #follow ul li From 128e0859fb4b6be78a42adc2d3a00a4eae00876d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 18 Feb 2016 14:24:50 -0500 Subject: [PATCH 0309/2240] chore: now working on 4.4.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 14283f5056b..04bbe2fb878 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.4", + "version": "4.4.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 12cd0e6001bf3e960b2049c263c6f09e1f4c1811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=A4=AA?= Date: Sat, 20 Feb 2016 22:08:26 +1100 Subject: [PATCH 0310/2240] Include the nested error when throwing CastError from arrays --- lib/schema/array.js | 2 +- lib/schema/documentarray.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index 7fec9e86077..c964c89e893 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -152,7 +152,7 @@ SchemaArray.prototype.cast = function(value, doc, init) { } } catch (e) { // rethrow - throw new CastError(e.type, value, this.path); + throw new CastError(e.type, value, this.path, e); } } diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index e41f6747525..6dcdd2c1102 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -241,7 +241,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { // see gh-746 value[i] = subdoc; } catch (error) { - throw new CastError('embedded', value[i], value._path); + throw new CastError('embedded', value[i], value._path, error); } } } From 3f29ffb8f84628d35702a0aa9090d77e53719ad8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 Feb 2016 16:33:29 -0500 Subject: [PATCH 0311/2240] test: repro #3889 --- test/model.findOneAndUpdate.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index ca886c2a44f..54a4124e4c7 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1540,5 +1540,19 @@ describe('model: findByIdAndUpdate:', function() { }); }); }); + + it('setting nested schema (gh-3889)', function(done) { + var db = start(); + var nested = new Schema({ test: String }); + var s = new Schema({ nested: nested }); + var MyModel = db.model('gh3889', s); + MyModel.findOneAndUpdate( + {}, + { $set: { nested: { test: 'abc' } } }, + function(error) { + assert.ifError(error); + db.close(done); + }); + }); }); }); From 7aef0f0da90cfaa49304cf6583fd08c4dc6e15c7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 Feb 2016 16:33:54 -0500 Subject: [PATCH 0312/2240] fix(schema): check for doc existence before taking fields --- lib/schema/embedded.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 46d997a25c7..9fc36d6137a 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -59,7 +59,7 @@ Embedded.prototype.cast = function(val, doc, init) { if (val && val.$isSingleNested) { return val; } - var subdoc = new this.caster(undefined, doc.$__.selected, doc); + var subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); if (init) { subdoc.init(val); } else { From 828d8259086befbf538fa4acbece48376efb749c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Feb 2016 22:48:38 -0500 Subject: [PATCH 0313/2240] docs: add mongoose-int32 to schema types docs --- docs/schematypes.jade | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index 3dac61f6bed..8294f4583cd 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -149,6 +149,8 @@ block content a(href="http://plugins.mongoosejs.com") plugins | site for compatible types like a(href="https://github.com/aheckmann/mongoose-long") mongoose-long + | ,  + a(href="https://github.com/vkarpov15/mongoose-int32") mongoose-int32 | and a(href="https://github.com/aheckmann/mongoose-function") other | From ccc6920486b406d9ae6679c1fe3975a40402d164 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Feb 2016 12:19:54 -0500 Subject: [PATCH 0314/2240] test(schema): repro #2398 --- test/schema.test.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index b663be810c9..4fbfa658cf8 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1548,5 +1548,14 @@ describe('schema', function() { assert.strictEqual(this.schema.path('g'), undefined); done(); }); + + it('works properly with virtuals (gh-2398)', function(done) { + this.schema.remove('a'); + this.schema.virtual('a').get(function() { return 42; }); + var Test = mongoose.model('gh2398', this.schema); + var t = new Test(); + assert.equal(t.a, 42); + done(); + }); }); }); From 24e79898fdab69206ffe0a15b0d95ae94cfd4d78 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Feb 2016 12:20:18 -0500 Subject: [PATCH 0315/2240] fix(schema): remove() removes from tree as well as flat map (Fix #2398) --- lib/schema.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index 06b2d7ae5a4..63fe7e26e7f 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1215,6 +1215,14 @@ Schema.prototype.remove = function(path) { path.forEach(function(name) { if (this.path(name)) { delete this.paths[name]; + + var pieces = name.split('.'); + var last = pieces.pop(); + var branch = this.tree; + for (var i = 0; i < pieces.length; ++i) { + branch = branch[pieces[i]]; + } + delete branch[last]; } }, this); } From 4c350cb54db9c6539587e0aaa09a1889645b7af6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Feb 2016 13:28:43 -0500 Subject: [PATCH 0316/2240] test: repro #3883 --- test/model.update.test.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index fb02ebbba7e..de7d388cf1b 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -14,7 +14,7 @@ var start = require('./common'), * Setup. */ -var Comments = new Schema; +var Comments = new Schema({}); Comments.add({ title: String, @@ -1704,6 +1704,30 @@ describe('model: update:', function() { db.close(done); }); + it('nested schemas with strict false (gh-3883)', function(done) { + var db = start(); + var OrderSchema = new mongoose.Schema({ + }, { strict: false, _id: false }); + + var SeasonSchema = new mongoose.Schema({ + regions: [OrderSchema] + }, { useNestedStrict: true }); + + var Season = db.model('gh3883', SeasonSchema); + var obj = { regions: [{ r: 'test', action: { order: 'hold' } }] }; + Season.create(obj, function(error) { + assert.ifError(error); + var query = { 'regions.r': 'test' }; + var update = { $set: { 'regions.$.action': { order: 'move' } } }; + var opts = { 'new': true }; + Season.findOneAndUpdate(query, update, opts, function(error, doc) { + assert.ifError(error); + assert.equal(doc.toObject().regions[0].action.order, 'move'); + done(); + }); + }); + }); + it('middleware update with exec (gh-3549)', function(done) { var db = start(); From 681bd7474ddcdab27e3881230ffd174291ccaef9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Feb 2016 13:29:14 -0500 Subject: [PATCH 0317/2240] fix(query): add useNestedStrict option (Fix #3883) --- lib/query.js | 30 ++++++++++++++++++------------ lib/schema.js | 16 ++++++++++------ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/lib/query.js b/lib/query.js index ac426e28a85..2cc325638f3 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2301,9 +2301,7 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) { key, val; - var strict = 'strict' in this._mongooseOptions - ? this._mongooseOptions.strict - : this.model.schema.options.strict; + var useNestedStrict = this.schema.options.useNestedStrict; while (i--) { key = keys[i]; @@ -2345,10 +2343,13 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) { } else { var pathToCheck = (prefix + key); var v = this.model.schema._getPathType(pathToCheck); - if (v === 'undefined') { - if (strict === 'throw') { + var _strict = 'strict' in this._mongooseOptions ? + this._mongooseOptions.strict : + ((useNestedStrict && v.schema) || this.schema).options.strict; + if (v.pathType === 'undefined') { + if (_strict === 'throw') { throw new StrictModeError(pathToCheck); - } else if (strict) { + } else if (_strict) { delete obj[key]; continue; } @@ -2361,16 +2362,21 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) { (utils.isObject(val) && Object.keys(val).length === 0); } } else { - schema = (key === '$each' || key === '$or' || key === '$and') - ? this._getSchema(pref) - : this._getSchema(prefix + key); + var checkPath = (key === '$each' || key === '$or' || key === '$and') ? + pref : prefix + key; + schema = this._getSchema(checkPath); - var skip = strict && + var pathDetails = this.model.schema._getPathType(checkPath); + var isStrict = 'strict' in this._mongooseOptions ? + this._mongooseOptions.strict : + ((useNestedStrict && pathDetails.schema) || this.schema).options.strict; + + var skip = isStrict && !schema && - !/real|nested/.test(this.model.schema.pathType(prefix + key)); + !/real|nested/.test(pathDetails.pathType); if (skip) { - if (strict === 'throw') { + if (isStrict === 'throw') { throw new StrictModeError(prefix + key); } else { delete obj[key]; diff --git a/lib/schema.js b/lib/schema.js index 63fe7e26e7f..96236db2763 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -48,6 +48,7 @@ var IS_QUERY_HOOK = { * - [toJSON](/docs/guide.html#toJSON) - object - no default * - [toObject](/docs/guide.html#toObject) - object - no default * - [typeKey](/docs/guide.html#typeKey) - string - defaults to 'type' + * - [useNestedStrict](/docs/guide.html#useNestedStrict) - boolean - defaults to false * - [validateBeforeSave](/docs/guide.html#validateBeforeSave) - bool - defaults to `true` * - [versionKey](/docs/guide.html#versionKey): string - defaults to "__v" * @@ -1303,7 +1304,7 @@ Schema.prototype._getPathType = function(path) { if (foundschema.caster) { // array of Mixed? if (foundschema.caster instanceof MongooseTypes.Mixed) { - return 'mixed'; + return { schema: foundschema, pathType: 'mixed' }; } // Now that we found the array, we need to check if there @@ -1315,7 +1316,7 @@ Schema.prototype._getPathType = function(path) { if (p !== parts.length && foundschema.schema) { if (parts[p] === '$') { if (p === parts.length - 1) { - return 'nested'; + return { schema: foundschema, pathType: 'nested' }; } // comments.$.comments.$.title return search(parts.slice(p + 1), foundschema.schema); @@ -1323,14 +1324,17 @@ Schema.prototype._getPathType = function(path) { // this is the last path of the selector return search(parts.slice(p), foundschema.schema); } - return foundschema.$isSingleNested ? 'nested' : 'array'; + return { + schema: foundschema, + pathType: foundschema.$isSingleNested ? 'nested' : 'array' + }; } - return 'real'; + return { schema: foundschema, pathType: 'real' }; } else if (p === parts.length && schema.nested[trypath]) { - return 'nested'; + return { schema: schema, pathType: 'nested' }; } } - return 'undefined'; + return { schema: foundschema || schema, pathType: 'undefined' }; } // look for arrays From 15886b0f36585ab888736e24508e45d0e20e27b8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Feb 2016 13:29:28 -0500 Subject: [PATCH 0318/2240] docs(schema): document useNestedStrict option re: #3883 --- docs/guide.jade | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/guide.jade b/docs/guide.jade index bf3bcdd9914..db657977e87 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -624,6 +624,37 @@ block content var thing = new Thing(); thing.save(); // `created_at` & `updatedAt` will be included + h4#useNestedStrict option: useNestedStrict + :markdown + In mongoose 4, `update()` and `findOneAndUpdate()` only check the top-level + schema's strict mode setting. + :js + var childSchema = new Schema({}, { strict: false }); + var parentSchema = new Schema({ child: childSchema }, { strict: 'throw' }); + var Parent = mongoose.model('Parent', parentSchema); + Parent.update({}, { 'child.name': 'Luke Skywalker' }, function(error) { + // Error because parentSchema has `strict: throw`, even though + // `childSchema` has `strict: false` + }); + + var update = { 'child.name': 'Luke Skywalker' }; + var opts = { strict: false }; + Parent.update({}, update, opts, function(error) { + // This works because passing `strict: false` to `update()` overwrites + // the parent schema. + }); + :markdown + If you set `useNestedStrict` to true, mongoose will use the child schema's + `strict` option for casting updates. + :js + var childSchema = new Schema({}, { strict: false }); + var parentSchema = new Schema({ child: childSchema }, + { strict: 'throw', useNestedStrict: true }); + var Parent = mongoose.model('Parent', parentSchema); + Parent.update({}, { 'child.name': 'Luke Skywalker' }, function(error) { + // Works! + }); + h3#plugins Pluggable p | Schemas are also From 6317ca17f75bac149b542038a20f1ebe89de0e8f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 Feb 2016 15:14:03 -0500 Subject: [PATCH 0319/2240] test(query): repro #3903 --- test/model.field.selection.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js index a7cbfdd9640..baa65023aa0 100644 --- a/test/model.field.selection.test.js +++ b/test/model.field.selection.test.js @@ -380,6 +380,26 @@ describe('model field selection', function() { }); }); + it('select properties named length (gh-3903)', function(done) { + var db = start(); + + var schema = new mongoose.Schema({ + length: Number, + name: String + }); + + var MyModel = db.model('gh3903', schema); + + MyModel.create({ name: 'val', length: 3 }, function(error) { + assert.ifError(error); + MyModel.findOne({}).select({ length: 1 }).exec(function(error, doc) { + assert.ifError(error); + assert.ok(!doc.name); + db.close(done); + }); + }); + }); + it('appropriately filters subdocuments based on properties (gh-1280)', function(done) { var db = start(); var RouteSchema = new Schema({ From 9a48ddd0e23e1810307e2bae2a37856ddd45bd3a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 Feb 2016 15:14:21 -0500 Subject: [PATCH 0320/2240] fix(query): upgrade mquery to fix #3903 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 04bbe2fb878..82b2529e17f 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.1.6", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "1.6.3", + "mquery": "1.7.0", "ms": "0.7.1", "muri": "1.1.0", "regexp-clone": "0.0.1", From bfae57d52d1f16bd52a03e2eeebce4ca58f60ccc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 Feb 2016 15:52:59 -0500 Subject: [PATCH 0321/2240] docs: toggle dropdown when clicking on filename (Fix #3807) --- docs/api.jade | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/api.jade b/docs/api.jade index 17afa0a4aa2..455c1ec4f75 100644 --- a/docs/api.jade +++ b/docs/api.jade @@ -22,10 +22,11 @@ html(lang='en') .doclinks each item in docs div.file(class=item.hasPublic ? '' : 'private') - a.section(href='#' + item.cleantitle) - | #{item.title} - |   - i.fa.fa-caret-right.toggle-item + span.toggle-item + a.section(href='#' + item.cleantitle) + | #{item.title} + |   + i.fa.fa-caret-right ul each method in item.methods if method.ctx && !method.ignore From 5ed2bc0be23a7e9088f85d91df71e706a2a4dc1c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 24 Feb 2016 09:24:45 -0500 Subject: [PATCH 0322/2240] docs(schema): clarify relationship between required validator and SchemaType#checkRequired #3822 --- lib/schema/array.js | 8 +++++--- lib/schema/boolean.js | 8 ++++++-- lib/schema/buffer.js | 9 +++++++-- lib/schema/date.js | 8 ++++++-- lib/schema/embedded.js | 10 ---------- lib/schema/mixed.js | 10 ---------- lib/schema/number.js | 7 +++++-- lib/schema/objectid.js | 7 +++++-- lib/schema/string.js | 8 +++++--- lib/schematype.js | 19 +++++++++++++++++-- 10 files changed, 56 insertions(+), 38 deletions(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index c964c89e893..06aec7bb308 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -92,10 +92,12 @@ SchemaArray.prototype = Object.create(SchemaType.prototype); SchemaArray.prototype.constructor = SchemaArray; /** - * Check required + * Check if the given value satisfies a required validator. The given value + * must be not null nor undefined, and have a non-zero length. * - * @param {Array} value - * @api private + * @param {Any} value + * @return {Boolean} + * @api public */ SchemaArray.prototype.checkRequired = function(value) { diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js index 6ca03ec5196..206d9fd98f5 100644 --- a/lib/schema/boolean.js +++ b/lib/schema/boolean.js @@ -34,9 +34,13 @@ SchemaBoolean.prototype = Object.create(SchemaType.prototype); SchemaBoolean.prototype.constructor = SchemaBoolean; /** - * Required validator + * Check if the given value satisfies a required validator. For a boolean + * to satisfy a required validator, it must be strictly equal to true or to + * false. * - * @api private + * @param {Any} value + * @return {Boolean} + * @api public */ SchemaBoolean.prototype.checkRequired = function(value) { diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js index 16432b40380..1dda3c8d1a2 100644 --- a/lib/schema/buffer.js +++ b/lib/schema/buffer.js @@ -40,9 +40,14 @@ SchemaBuffer.prototype = Object.create(SchemaType.prototype); SchemaBuffer.prototype.constructor = SchemaBuffer; /** - * Check required + * Check if the given value satisfies a required validator. To satisfy a + * required validator, a buffer must not be null or undefined and have + * non-zero length. * - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ SchemaBuffer.prototype.checkRequired = function(value, doc) { diff --git a/lib/schema/date.js b/lib/schema/date.js index 67940565373..04c02aa56b8 100644 --- a/lib/schema/date.js +++ b/lib/schema/date.js @@ -78,9 +78,13 @@ SchemaDate.prototype.expires = function(when) { }; /** - * Required validator for date + * Check if the given value satisfies a required validator. To satisfy + * a required validator, the given value must be an instance of `Date`. * - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ SchemaDate.prototype.checkRequired = function(value) { diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 9fc36d6137a..e882af7b343 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -123,13 +123,3 @@ Embedded.prototype.doValidateSync = function(value) { } return value.validateSync(); }; - -/** - * Required validator for single nested docs - * - * @api private - */ - -Embedded.prototype.checkRequired = function(value) { - return !!value && value.$isSingleNested; -}; diff --git a/lib/schema/mixed.js b/lib/schema/mixed.js index c1b4cab793d..e4c23caaa80 100644 --- a/lib/schema/mixed.js +++ b/lib/schema/mixed.js @@ -45,16 +45,6 @@ Mixed.schemaName = 'Mixed'; Mixed.prototype = Object.create(SchemaType.prototype); Mixed.prototype.constructor = Mixed; -/** - * Required validator - * - * @api private - */ - -Mixed.prototype.checkRequired = function(val) { - return (val !== undefined) && (val !== null); -}; - /** * Casts `val` for Mixed. * diff --git a/lib/schema/number.js b/lib/schema/number.js index ff8f500b918..03df1816da0 100644 --- a/lib/schema/number.js +++ b/lib/schema/number.js @@ -37,9 +37,12 @@ SchemaNumber.prototype = Object.create(SchemaType.prototype); SchemaNumber.prototype.constructor = SchemaNumber; /** - * Required validator for number + * Check if the given value satisfies a required validator. * - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) { diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index ef11b875542..d1b1e1f0e6d 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -54,9 +54,12 @@ ObjectId.prototype.auto = function(turnOn) { }; /** - * Check required + * Check if the given value satisfies a required validator. * - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ ObjectId.prototype.checkRequired = function checkRequired(value, doc) { diff --git a/lib/schema/string.js b/lib/schema/string.js index 6213471349d..1190dd77e51 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -369,10 +369,12 @@ SchemaString.prototype.match = function match(regExp, message) { }; /** - * Check required + * Check if the given value satisfies a required validator. * - * @param {String|null|undefined} value - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ SchemaString.prototype.checkRequired = function checkRequired(value, doc) { diff --git a/lib/schematype.js b/lib/schematype.js index bfab06b9ef7..f3e9148140e 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -481,8 +481,8 @@ SchemaType.prototype.validate = function(obj, message, type) { }; /** - * Adds a required validator to this schematype. The required validator is added - * to the front of the validators array using `unshift()`. + * Adds a required validator to this SchemaType. The validator gets added + * to the front of this SchemaType's validators array using `unshift()`. * * ####Example: * @@ -500,11 +500,26 @@ SchemaType.prototype.validate = function(obj, message, type) { * * Schema.path('name').required(true, 'grrr :( '); * + * // or make a path conditionally required based on a function + * var isOver18 = function() { return this.age >= 18; }; + * Schema.path('voterRegistrationId').required(isOver18); + * + * The required validator uses the SchemaType's `checkRequired` function to + * determine whether a given value satisfies the required validator. By default, + * a value satisfies the required validator if `val != null` (that is, if + * the value is not null nor undefined). However, most built-in mongoose schema + * types override the default `checkRequired` function: * * @param {Boolean} required enable/disable the validator * @param {String} [message] optional custom error message * @return {SchemaType} this * @see Customized Error Messages #error_messages_MongooseError-messages + * @see SchemaArray#checkRequired #schema_array_SchemaArray.checkRequired + * @see SchemaBoolean#checkRequired #schema_boolean_SchemaBoolean-checkRequired + * @see SchemaBuffer#checkRequired #schema_buffer_SchemaBuffer.schemaName + * @see SchemaNumber#checkRequired #schema_number_SchemaNumber-min + * @see SchemaObjectId#checkRequired #schema_objectid_ObjectId-auto + * @see SchemaString#checkRequired #schema_string_SchemaString-checkRequired * @api public */ From 4414f94dbd15bba75209ac13793a61cd9bfb1115 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 24 Feb 2016 09:27:17 -0500 Subject: [PATCH 0323/2240] docs(validation): clarify relationship between required and checkRequired re #3822 --- docs/validation.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/validation.jade b/docs/validation.jade index 128e3f9c93f..7557d8c5b6d 100644 --- a/docs/validation.jade +++ b/docs/validation.jade @@ -16,7 +16,7 @@ block content :markdown Mongoose has several built in validators. - - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. + - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. The required validator uses the [SchemaType's `checkRequired()` function](./api.html#schematype_SchemaType-checkRequired) to determine if the value satisfies the required validator. - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum), [match](./api.html#schema_string_SchemaString-match), [maxlength](./api.html#schema_string_SchemaString-maxlength) and [minlength](./api.html#schema_string_SchemaString-minlength) validators. From 07b064ebefe65e04ebea9ee1a03288e7fa846812 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 24 Feb 2016 11:02:25 -0500 Subject: [PATCH 0324/2240] docs(populate): dynref docs (Fix #3809) --- docs/populate.jade | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/populate.jade b/docs/populate.jade index dba890e98eb..c567ed57462 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -260,6 +260,54 @@ block content This is known as a "cross-database populate," because it enables you to populate across MongoDB databases and even acrosss MongoDB instances. + h3#dynamic-ref Dynamic References + :markdown + Mongoose can also populate from multiple collections at the same time. + Let's say you have a user schema that has an array of "connections" - a + user can be connected to either other users or an organization. + :js + var userSchema = new Schema({ + name: String, + connections: [{ + kind: String, + item: { type: ObjectId, refPath: 'connections.kind' } + }] + }); + + var organizationSchema = new Schema({ name: String, kind: String }); + + var User = mongoose.model('User', userSchema); + var Organization = mongoose.model('Organization', organizationSchema); + :markdown + The `refPath` property above means that mongoose will look at the + `connections.kind` path to determine which model to use for `populate()`. + In other words, the `refPath` property enables you to make the `ref` + property dynamic. + :js + // Say we have one organization: + // `{ _id: ObjectId('000000000000000000000001'), name: "Guns N' Roses", kind: 'Band' }` + // And two users: + // { + // _id: ObjectId('000000000000000000000002') + // name: 'Axl Rose', + // connections: [ + // { kind: 'User', item: ObjectId('000000000000000000000003') }, + // { kind: 'Organization', item: ObjectId('000000000000000000000001') } + // ] + // }, + // { + // _id: ObjectId('000000000000000000000003') + // name: 'Slash', + // connections: [] + // } + User. + findOne({ name: 'Axl Rose' }). + populate('connections'). + exec(function(error, doc) { + // doc.connections[0].item is a User doc + // doc.connections[1].item is an Organization doc + }); + h3#next Next Up :markdown Now that we've covered query population, let's take a look at [connections](/docs/connections.html). From 080ed23d2973474c85ee55113805c51263643e69 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 24 Feb 2016 11:10:15 -0500 Subject: [PATCH 0325/2240] chore: release 4.4.5 --- History.md | 12 ++++ bin/mongoose.js | 178 +++++++++++++++++++++++++++++++++++------------- package.json | 2 +- 3 files changed, 143 insertions(+), 49 deletions(-) diff --git a/History.md b/History.md index 8730b12fcc7..fef46b3f407 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,15 @@ +4.4.5 / 2016-02-24 +================== + * fix(query): ability to select a length field (upgrade to mquery 1.7.0) #3903 + * fix: include nested CastError as reason for array CastError #3897 [kotarou3](https://github.com/kotarou3) + * fix(schema): check for doc existence before taking fields #3889 + * feat(schema): useNestedStrict option to take nested strict mode for update #3883 + * docs(validation): clarify relationship between required and checkRequired #3822 + * docs(populate): dynamic reference docs #3809 + * docs: expand dropdown when clicking on file name #3807 + * docs: plugins.mongoose.io is up #3127 + * fix(schema): ability to add a virtual with same name as removed path #2398 + 4.4.4 / 2016-02-17 ================== * fix(schema): handle field selection when casting single nested subdocs #3880 diff --git a/bin/mongoose.js b/bin/mongoose.js index 9c7b2947ae0..f7ee49f456f 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -3881,6 +3881,7 @@ var IS_QUERY_HOOK = { * - [toJSON](/docs/guide.html#toJSON) - object - no default * - [toObject](/docs/guide.html#toObject) - object - no default * - [typeKey](/docs/guide.html#typeKey) - string - defaults to 'type' + * - [useNestedStrict](/docs/guide.html#useNestedStrict) - boolean - defaults to false * - [validateBeforeSave](/docs/guide.html#validateBeforeSave) - bool - defaults to `true` * - [versionKey](/docs/guide.html#versionKey): string - defaults to "__v" * @@ -5048,6 +5049,14 @@ Schema.prototype.remove = function(path) { path.forEach(function(name) { if (this.path(name)) { delete this.paths[name]; + + var pieces = name.split('.'); + var last = pieces.pop(); + var branch = this.tree; + for (var i = 0; i < pieces.length; ++i) { + branch = branch[pieces[i]]; + } + delete branch[last]; } }, this); } @@ -5128,7 +5137,7 @@ Schema.prototype._getPathType = function(path) { if (foundschema.caster) { // array of Mixed? if (foundschema.caster instanceof MongooseTypes.Mixed) { - return 'mixed'; + return { schema: foundschema, pathType: 'mixed' }; } // Now that we found the array, we need to check if there @@ -5140,7 +5149,7 @@ Schema.prototype._getPathType = function(path) { if (p !== parts.length && foundschema.schema) { if (parts[p] === '$') { if (p === parts.length - 1) { - return 'nested'; + return { schema: foundschema, pathType: 'nested' }; } // comments.$.comments.$.title return search(parts.slice(p + 1), foundschema.schema); @@ -5148,14 +5157,17 @@ Schema.prototype._getPathType = function(path) { // this is the last path of the selector return search(parts.slice(p), foundschema.schema); } - return foundschema.$isSingleNested ? 'nested' : 'array'; + return { + schema: foundschema, + pathType: foundschema.$isSingleNested ? 'nested' : 'array' + }; } - return 'real'; + return { schema: foundschema, pathType: 'real' }; } else if (p === parts.length && schema.nested[trypath]) { - return 'nested'; + return { schema: schema, pathType: 'nested' }; } } - return 'undefined'; + return { schema: foundschema || schema, pathType: 'undefined' }; } // look for arrays @@ -5302,10 +5314,12 @@ SchemaArray.prototype = Object.create(SchemaType.prototype); SchemaArray.prototype.constructor = SchemaArray; /** - * Check required + * Check if the given value satisfies a required validator. The given value + * must be not null nor undefined, and have a non-zero length. * - * @param {Array} value - * @api private + * @param {Any} value + * @return {Boolean} + * @api public */ SchemaArray.prototype.checkRequired = function(value) { @@ -5362,7 +5376,7 @@ SchemaArray.prototype.cast = function(value, doc, init) { } } catch (e) { // rethrow - throw new CastError(e.type, value, this.path); + throw new CastError(e.type, value, this.path, e); } } @@ -5637,9 +5651,13 @@ SchemaBoolean.prototype = Object.create(SchemaType.prototype); SchemaBoolean.prototype.constructor = SchemaBoolean; /** - * Required validator + * Check if the given value satisfies a required validator. For a boolean + * to satisfy a required validator, it must be strictly equal to true or to + * false. * - * @api private + * @param {Any} value + * @return {Boolean} + * @api public */ SchemaBoolean.prototype.checkRequired = function(value) { @@ -5745,9 +5763,14 @@ SchemaBuffer.prototype = Object.create(SchemaType.prototype); SchemaBuffer.prototype.constructor = SchemaBuffer; /** - * Check required + * Check if the given value satisfies a required validator. To satisfy a + * required validator, a buffer must not be null or undefined and have + * non-zero length. * - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ SchemaBuffer.prototype.checkRequired = function(value, doc) { @@ -5969,9 +5992,13 @@ SchemaDate.prototype.expires = function(when) { }; /** - * Required validator for date + * Check if the given value satisfies a required validator. To satisfy + * a required validator, the given value must be an instance of `Date`. * - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ SchemaDate.prototype.checkRequired = function(value) { @@ -6418,7 +6445,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { // see gh-746 value[i] = subdoc; } catch (error) { - throw new CastError('embedded', value[i], value._path); + throw new CastError('embedded', value[i], value._path, error); } } } @@ -6528,7 +6555,7 @@ Embedded.prototype.cast = function(val, doc, init) { if (val && val.$isSingleNested) { return val; } - var subdoc = new this.caster(undefined, doc.$__.selected, doc); + var subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); if (init) { subdoc.init(val); } else { @@ -6593,16 +6620,6 @@ Embedded.prototype.doValidateSync = function(value) { return value.validateSync(); }; -/** - * Required validator for single nested docs - * - * @api private - */ - -Embedded.prototype.checkRequired = function(value) { - return !!value && value.$isSingleNested; -}; - },{"../schematype":39,"../types/subdocument":47}],33:[function(require,module,exports){ /*! @@ -6683,16 +6700,6 @@ Mixed.schemaName = 'Mixed'; Mixed.prototype = Object.create(SchemaType.prototype); Mixed.prototype.constructor = Mixed; -/** - * Required validator - * - * @api private - */ - -Mixed.prototype.checkRequired = function(val) { - return (val !== undefined) && (val !== null); -}; - /** * Casts `val` for Mixed. * @@ -6768,9 +6775,12 @@ SchemaNumber.prototype = Object.create(SchemaType.prototype); SchemaNumber.prototype.constructor = SchemaNumber; /** - * Required validator for number + * Check if the given value satisfies a required validator. * - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) { @@ -7076,9 +7086,12 @@ ObjectId.prototype.auto = function(turnOn) { }; /** - * Check required + * Check if the given value satisfies a required validator. * - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ ObjectId.prototype.checkRequired = function checkRequired(value, doc) { @@ -7639,10 +7652,12 @@ SchemaString.prototype.match = function match(regExp, message) { }; /** - * Check required + * Check if the given value satisfies a required validator. * - * @param {String|null|undefined} value - * @api private + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public */ SchemaString.prototype.checkRequired = function checkRequired(value, doc) { @@ -8259,8 +8274,8 @@ SchemaType.prototype.validate = function(obj, message, type) { }; /** - * Adds a required validator to this schematype. The required validator is added - * to the front of the validators array using `unshift()`. + * Adds a required validator to this SchemaType. The validator gets added + * to the front of this SchemaType's validators array using `unshift()`. * * ####Example: * @@ -8278,11 +8293,26 @@ SchemaType.prototype.validate = function(obj, message, type) { * * Schema.path('name').required(true, 'grrr :( '); * + * // or make a path conditionally required based on a function + * var isOver18 = function() { return this.age >= 18; }; + * Schema.path('voterRegistrationId').required(isOver18); + * + * The required validator uses the SchemaType's `checkRequired` function to + * determine whether a given value satisfies the required validator. By default, + * a value satisfies the required validator if `val != null` (that is, if + * the value is not null nor undefined). However, most built-in mongoose schema + * types override the default `checkRequired` function: * * @param {Boolean} required enable/disable the validator * @param {String} [message] optional custom error message * @return {SchemaType} this * @see Customized Error Messages #error_messages_MongooseError-messages + * @see SchemaArray#checkRequired #schema_array_SchemaArray.checkRequired + * @see SchemaBoolean#checkRequired #schema_boolean_SchemaBoolean-checkRequired + * @see SchemaBuffer#checkRequired #schema_buffer_SchemaBuffer.schemaName + * @see SchemaNumber#checkRequired #schema_number_SchemaNumber-min + * @see SchemaObjectId#checkRequired #schema_objectid_ObjectId-auto + * @see SchemaString#checkRequired #schema_string_SchemaString-checkRequired * @api public */ @@ -21726,6 +21756,14 @@ NodeCollection.prototype.findStream = function(match, findOptions, streamOptions return this.collection.find(match, findOptions).stream(streamOptions); } +/** + * var cursor = findCursor(match, findOptions) + */ + +NodeCollection.prototype.findCursor = function(match, findOptions) { + return this.collection.find(match, findOptions); +} + /** * aggregation(operators..., function(err, doc)) * TODO @@ -22841,7 +22879,8 @@ Query.prototype.select = function select () { var fields = this._fields || (this._fields = {}); var type = typeof arg; - if ('string' == type || 'object' == type && 'number' == typeof arg.length && !Array.isArray(arg)) { + if (('string' == type || utils.isArgumentsObject(arg)) && + 'number' == typeof arg.length) { if ('string' == type) arg = arg.split(/\s+/); @@ -23397,6 +23436,37 @@ Query.prototype.find = function (criteria, callback) { return this; } +/** + * Returns the query cursor + * + * ####Examples + * + * query.find().cursor(); + * query.cursor({ name: 'Burning Lights' }); + * + * @param {Object} [criteria] mongodb selector + * @return {Object} cursor + * @api public + */ + +Query.prototype.cursor = function cursor (criteria) { + if (this.op) { + if (this.op !== 'find') { + throw new TypeError(".cursor only support .find method"); + } + } else { + this.find(criteria); + } + + var conds = this._conditions + , options = this._optionsForExec() + + options.fields = this._fieldsForExec() + + debug('findCursor', this._collection.collectionName, conds, options); + return this._collection.findCursor(conds, options); +} + /** * Executes the query as a findOne() operation. * @@ -24291,6 +24361,7 @@ Query.prototype._updateForExec = function () { } } + this._compiledUpdate = ret; return ret; } @@ -24804,6 +24875,17 @@ exports.cloneBuffer = function (buff) { return dupe; }; +/** + * Check if this object is an arguments object + * + * @param {Any} v + * @return {Boolean} + */ + +exports.isArgumentsObject = function(v) { + return Object.prototype.toString.call(v) === '[object Arguments]'; +}; + }).call(this,require("g5I+bs"),require("buffer").Buffer) },{"buffer":71,"g5I+bs":94,"regexp-clone":95}],90:[function(require,module,exports){ (function (process,global){ diff --git a/package.json b/package.json index 82b2529e17f..fdf4a3d3bcf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.5-pre", + "version": "4.4.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From eff3c95c0a7c6219df832210b45588ba890a104e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 24 Feb 2016 16:54:34 -0500 Subject: [PATCH 0326/2240] docs: fix bad url in readme.md --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index fef46b3f407..58acb91077f 100644 --- a/History.md +++ b/History.md @@ -7,7 +7,7 @@ * docs(validation): clarify relationship between required and checkRequired #3822 * docs(populate): dynamic reference docs #3809 * docs: expand dropdown when clicking on file name #3807 - * docs: plugins.mongoose.io is up #3127 + * docs: plugins.mongoosejs.io is up #3127 * fix(schema): ability to add a virtual with same name as removed path #2398 4.4.4 / 2016-02-17 From 0d57b3a367943884103a6f40b7dd4eae6a81d890 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 27 Feb 2016 13:23:16 -0500 Subject: [PATCH 0327/2240] docs: clarify driver access bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f137e04c88c..f25540bb919 100644 --- a/README.md +++ b/README.md @@ -284,9 +284,9 @@ new Schema({ }); ``` -### Driver access +### Driver Access -The driver being used defaults to [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) and is directly accessible through `YourModel.collection`. **Note**: using the driver directly bypasses all Mongoose power-tools like validation, getters, setters, hooks, etc. +Mongoose is built on top of the [official MongoDB Node.js driver](https://github.com/mongodb/node-mongodb-native). Each mongoose model keeps a reference to a [native MongoDB driver collection](http://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html). The collection object can be accessed using `YourModel.collection`. However, using the collection object directly bypasses all mongoose features, including hooks, validation, etc. ## API Docs From ea3ac320fcd411fcbeba8c4a4f9f1e8766d8b5ed Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 29 Feb 2016 19:40:04 -0500 Subject: [PATCH 0328/2240] docs: remove IRC from contributing.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aae2ca0a1a0..c976cfd9f77 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ ## Contributing to Mongoose -If you have a question about Mongoose (not a bug report) please post it to either [StackOverflow](http://stackoverflow.com/questions/tagged/mongoose), our [Google Group](http://groups.google.com/group/mongoose-orm), or on the #mongoosejs irc channel on freenode. +If you have a question about Mongoose (not a bug report) please post it to either [StackOverflow](http://stackoverflow.com/questions/tagged/mongoose), our [Google Group](http://groups.google.com/group/mongoose-orm), or on [Gitter](https://gitter.im/Automattic/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ### Reporting bugs From 041bb03b1efd03fd13fc498b2254d449d38e8acd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 1 Mar 2016 08:21:13 -0800 Subject: [PATCH 0329/2240] chore: now working on 4.4.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fdf4a3d3bcf..825d94b8aee 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.5", + "version": "4.4.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 139a90b6c3ff0d13c50dcb6e041b6b0b9827598d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 1 Mar 2016 08:37:39 -0800 Subject: [PATCH 0330/2240] test: repro #3914 --- test/query.test.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index e89a7560581..1d02e3887e2 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1556,6 +1556,42 @@ describe('Query', function() { db.close(done); }); + describe('bug fixes', function() { + var db; + + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('allows sort with count (gh-3914)', function(done) { + var Post = db.model('gh3914_0', { + title: String + }); + + Post.count({}).sort({ title: 1 }).exec(function(error, count) { + assert.ifError(error); + assert.strictEqual(count, 0); + done(); + }); + }); + + it('allows sort with select (gh-3914)', function(done) { + var Post = db.model('gh3914_1', { + title: String + }); + + Post.count({}).select({ _id: 0 }).exec(function(error, count) { + assert.ifError(error); + assert.strictEqual(count, 0); + done(); + }); + }); + }); + describe('handles falsy and object projections with defaults (gh-3256)', function() { var db = start(); var MyModel; From cee754580d1bac45292b9e0c967ecb7d9809a705 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 1 Mar 2016 08:38:04 -0800 Subject: [PATCH 0331/2240] fix(query): upgrade mquery->1.8.0 to allow count with sort+select --- lib/query.js | 5 ----- package.json | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/query.js b/lib/query.js index 2cc325638f3..e00e3d07e90 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1418,11 +1418,6 @@ Query.prototype.sort = function(arg) { nArg = arg; } - // workaround for gh-2374 when sort is called after count - // if previous operation is count, we ignore - if (this.op === 'count') { - delete this.op; - } return Query.base.sort.call(this, nArg); }; diff --git a/package.json b/package.json index 825d94b8aee..71c55e5bcee 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.1.6", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "1.7.0", + "mquery": "1.8.0", "ms": "0.7.1", "muri": "1.1.0", "regexp-clone": "0.0.1", From b3400f2a49aab3170ab842309fb22e8a3c774963 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 2 Mar 2016 09:37:37 -0800 Subject: [PATCH 0332/2240] test: repro #3890 --- test/model.update.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index de7d388cf1b..0a6882b4411 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1787,4 +1787,31 @@ describe('model: update:', function() { }); }); }); + + it('$push with buffer doesnt throw error (gh-3890)', function(done) { + var db = start(); + + var InfoSchema = new Schema({ + prop: { type: Buffer } + }); + + var ModelASchema = new Schema({ + infoList: { type: [InfoSchema] } + }); + + var ModelA = db.model('gh3890', ModelASchema); + + var propValue = new Buffer('aa267824dc1796f265ab47870e279780', 'base64'); + + var update = { + $push: { + info_list: { prop: propValue } + } + }; + + ModelA.update({}, update, function(error) { + assert.ifError(error); + db.close(done); + }); + }); }); From 5b0fffd14f08164b74e5bf4db6985eea68d4e9e2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 2 Mar 2016 09:38:18 -0800 Subject: [PATCH 0333/2240] fix(query): _mergeUpdate handles subdocs correctly (Fix #3890) --- lib/utils.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/utils.js b/lib/utils.js index 8747774d00f..be40d12c9ee 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -816,7 +816,11 @@ exports.mergeClone = function(to, from) { to[key] = exports.clone(from[key], {retainKeyOrder: 1}); } else { if (exports.isObject(from[key])) { - exports.mergeClone(to[key], from[key]); + var obj = from[key]; + if (isMongooseObject(from[key])) { + obj = obj.toObject({ virtuals: false }); + } + exports.mergeClone(to[key], obj); } else { // make sure to retain key order here because of a bug handling the // $each operator in mongodb 2.4.4 From f802dea53cdafaf732c2cc2d97059f9bb5ae20df Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 2 Mar 2016 16:53:55 -0800 Subject: [PATCH 0334/2240] chore: upgrade mongodb driver -> 2.1.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 71c55e5bcee..e5f727f3bf0 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "0.4.21", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.1.6", + "mongodb": "2.1.7", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.8.0", From a7e498609e4eaa327955c70f65e2edffed10f6d2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 2 Mar 2016 17:04:16 -0800 Subject: [PATCH 0335/2240] chore: release 4.4.6 --- History.md | 7 +++++++ bin/mongoose.js | 22 ++++++++++++++++++---- package.json | 2 +- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index 58acb91077f..a3c9cf05919 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.4.6 / 2016-03-02 +================== + * fix: upgrade mongodb driver to 2.1.7 #3938 + * docs: fix plugins link #3917 #3909 [fbertone](https://github.com/fbertone) + * fix(query): sort+select with count works #3914 + * fix(query): improve mergeUpdate's ability to handle nested docs #3890 + 4.4.5 / 2016-02-24 ================== * fix(query): ability to select a length field (upgrade to mquery 1.7.0) #3903 diff --git a/bin/mongoose.js b/bin/mongoose.js index f7ee49f456f..ca8c05d9023 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -11490,7 +11490,11 @@ exports.mergeClone = function(to, from) { to[key] = exports.clone(from[key], {retainKeyOrder: 1}); } else { if (exports.isObject(from[key])) { - exports.mergeClone(to[key], from[key]); + var obj = from[key]; + if (isMongooseObject(from[key])) { + obj = obj.toObject({ virtuals: false }); + } + exports.mergeClone(to[key], obj); } else { // make sure to retain key order here because of a bug handling the // $each operator in mongodb 2.4.4 @@ -24149,7 +24153,19 @@ Query.prototype.exec = function exec (op, callback) { callback || (callback = true); } - this[this.op](callback); + var self = this; + + if ('function' == typeof callback) { + this[this.op](callback); + } else { + return new Query.Promise(function(success, error) { + self[self.op](function(err, val) { + if (err) error(err); + else success(val); + self = success = error = null; + }); + }); + } } /** @@ -24532,9 +24548,7 @@ denied.count = function (self) { return err; } -denied.count.select = denied.count.slice = -denied.count.sort = denied.count.batchSize = denied.count.comment = denied.count.maxScan = diff --git a/package.json b/package.json index e5f727f3bf0..5f9b255faf6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.6-pre", + "version": "4.4.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 41d148b54ecdc867ecacbba83fef7e66068ef530 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 3 Mar 2016 07:55:19 -0800 Subject: [PATCH 0336/2240] chore: now working on 4.4.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5f9b255faf6..1a79fad5c24 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.6", + "version": "4.4.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From f62afe51d06b08a5616e0e108072307ec8e549bb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 4 Mar 2016 08:28:15 -0800 Subject: [PATCH 0337/2240] refactor(test): make a bunch of document tests reuse a connection --- test/document.test.js | 251 +++++++++++++++++++----------------------- 1 file changed, 114 insertions(+), 137 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index 8741965db9c..fe81610d15e 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2005,183 +2005,160 @@ describe('document', function() { }); }); - it('single embedded schemas with populate (gh-3501)', function(done) { - var db = start(); - var PopulateMeSchema = new Schema({}); - - var Child = db.model('gh3501', PopulateMeSchema); + describe('bug fixes', function() { + var db; - var SingleNestedSchema = new Schema({ - populateMeArray: [{ - type: Schema.Types.ObjectId, - ref: 'gh3501' - }] + before(function() { + db = start(); }); - var parentSchema = new Schema({ - singleNested: SingleNestedSchema + after(function(done) { + db.close(done); }); - var P = db.model('gh3501_1', parentSchema); + it('single embedded schemas with populate (gh-3501)', function(done) { + var PopulateMeSchema = new Schema({}); - Child.create([{}, {}], function(error, docs) { - assert.ifError(error); - var obj = { - singleNested: {populateMeArray: [docs[0]._id, docs[1]._id]} - }; - P.create(obj, function(error, doc) { + var Child = db.model('gh3501', PopulateMeSchema); + + var SingleNestedSchema = new Schema({ + populateMeArray: [{ + type: Schema.Types.ObjectId, + ref: 'gh3501' + }] + }); + + var parentSchema = new Schema({ + singleNested: SingleNestedSchema + }); + + var P = db.model('gh3501_1', parentSchema); + + Child.create([{}, {}], function(error, docs) { assert.ifError(error); - P. - findById(doc._id). - populate('singleNested.populateMeArray'). - exec(function(error, doc) { - assert.ok(doc.singleNested.populateMeArray[0]._id); - db.close(done); + var obj = { + singleNested: {populateMeArray: [docs[0]._id, docs[1]._id]} + }; + P.create(obj, function(error, doc) { + assert.ifError(error); + P. + findById(doc._id). + populate('singleNested.populateMeArray'). + exec(function(error, doc) { + assert.ok(doc.singleNested.populateMeArray[0]._id); + done(); + }); }); }); }); - }); - it('single embedded schemas with methods (gh-3534)', function(done) { - var db = start(); - var personSchema = new Schema({name: String}); - personSchema.methods.firstName = function() { - return this.name.substr(0, this.name.indexOf(' ')); - }; + it('single embedded schemas with methods (gh-3534)', function(done) { + var personSchema = new Schema({name: String}); + personSchema.methods.firstName = function() { + return this.name.substr(0, this.name.indexOf(' ')); + }; - var bandSchema = new Schema({leadSinger: personSchema}); - var Band = db.model('gh3534', bandSchema); + var bandSchema = new Schema({leadSinger: personSchema}); + var Band = db.model('gh3534', bandSchema); - var gnr = new Band({leadSinger: {name: 'Axl Rose'}}); - assert.equal(gnr.leadSinger.firstName(), 'Axl'); - db.close(done); - }); + var gnr = new Band({leadSinger: {name: 'Axl Rose'}}); + assert.equal(gnr.leadSinger.firstName(), 'Axl'); + done(); + }); - it('single embedded schemas with models (gh-3535)', function(done) { - var db = start(); - var personSchema = new Schema({name: String}); - var Person = db.model('gh3535_0', personSchema); + it('single embedded schemas with models (gh-3535)', function(done) { + var db = start(); + var personSchema = new Schema({name: String}); + var Person = db.model('gh3535_0', personSchema); - var bandSchema = new Schema({leadSinger: personSchema}); - var Band = db.model('gh3535', bandSchema); + var bandSchema = new Schema({leadSinger: personSchema}); + var Band = db.model('gh3535', bandSchema); - var axl = new Person({name: 'Axl Rose'}); - var gnr = new Band({leadSinger: axl}); + var axl = new Person({name: 'Axl Rose'}); + var gnr = new Band({leadSinger: axl}); - gnr.save(function(error) { - assert.ifError(error); - assert.equal(gnr.leadSinger.name, 'Axl Rose'); - db.close(done); + gnr.save(function(error) { + assert.ifError(error); + assert.equal(gnr.leadSinger.name, 'Axl Rose'); + done(); + }); }); - }); - - it('single embedded schemas with indexes (gh-3594)', function(done) { - var personSchema = new Schema({name: {type: String, unique: true}}); - var bandSchema = new Schema({leadSinger: personSchema}); - - assert.equal(bandSchema.indexes().length, 1); - var index = bandSchema.indexes()[0]; - assert.deepEqual(index[0], {'leadSinger.name': 1}); - assert.ok(index[1].unique); - done(); - }); - - it('single embedded docs have an ownerDocument function (gh-3589)', function(done) { - var db = start(); - var personSchema = new Schema({name: String}); - personSchema.methods.display = function() { - return this.name + ' of ' + this.ownerDocument().name; - }; + it('single embedded schemas with indexes (gh-3594)', function(done) { + var personSchema = new Schema({name: {type: String, unique: true}}); - var bandSchema = new Schema({leadSinger: personSchema, name: String}); - var Band = db.model('gh3589', bandSchema); + var bandSchema = new Schema({leadSinger: personSchema}); - var gnr = new Band({ - name: 'Guns N\' Roses', - leadSinger: {name: 'Axl Rose'} + assert.equal(bandSchema.indexes().length, 1); + var index = bandSchema.indexes()[0]; + assert.deepEqual(index[0], {'leadSinger.name': 1}); + assert.ok(index[1].unique); + done(); }); - assert.equal(gnr.leadSinger.display(), 'Axl Rose of Guns N\' Roses'); - db.close(done); - }); - it('removing single embedded docs (gh-3596)', function(done) { - var db = start(); - var personSchema = new Schema({name: String}); + it('removing single embedded docs (gh-3596)', function(done) { + var personSchema = new Schema({name: String}); - var bandSchema = new Schema({guitarist: personSchema, name: String}); - var Band = db.model('gh3596', bandSchema); + var bandSchema = new Schema({guitarist: personSchema, name: String}); + var Band = db.model('gh3596', bandSchema); - var gnr = new Band({ - name: 'Guns N\' Roses', - guitarist: {name: 'Slash'} - }); - gnr.save(function(error, gnr) { - assert.ifError(error); - gnr.guitarist = undefined; + var gnr = new Band({ + name: 'Guns N\' Roses', + guitarist: {name: 'Slash'} + }); gnr.save(function(error, gnr) { assert.ifError(error); - assert.ok(!gnr.guitarist); - db.close(done); + gnr.guitarist = undefined; + gnr.save(function(error, gnr) { + assert.ifError(error); + assert.ok(!gnr.guitarist); + done(); + }); }); }); - }); - it('setting single embedded docs (gh-3601)', function(done) { - var db = start(); - var personSchema = new Schema({name: String}); + it('setting single embedded docs (gh-3601)', function(done) { + var personSchema = new Schema({name: String}); - var bandSchema = new Schema({guitarist: personSchema, name: String}); - var Band = db.model('gh3601', bandSchema); + var bandSchema = new Schema({guitarist: personSchema, name: String}); + var Band = db.model('gh3601', bandSchema); - var gnr = new Band({ - name: 'Guns N\' Roses', - guitarist: {name: 'Slash'} - }); - var velvetRevolver = new Band({ - name: 'Velvet Revolver' - }); - velvetRevolver.guitarist = gnr.guitarist; - velvetRevolver.save(function(error) { - assert.ifError(error); - assert.equal(velvetRevolver.guitarist, gnr.guitarist); - db.close(done); + var gnr = new Band({ + name: 'Guns N\' Roses', + guitarist: {name: 'Slash'} + }); + var velvetRevolver = new Band({ + name: 'Velvet Revolver' + }); + velvetRevolver.guitarist = gnr.guitarist; + velvetRevolver.save(function(error) { + assert.ifError(error); + assert.equal(velvetRevolver.guitarist, gnr.guitarist); + done(); + }); }); - }); - it('single embedded docs init obeys strict mode (gh-3642)', function(done) { - var db = start(); - var personSchema = new Schema({name: String}); + it('single embedded docs init obeys strict mode (gh-3642)', function(done) { + var personSchema = new Schema({name: String}); - var bandSchema = new Schema({guitarist: personSchema, name: String}); - var Band = db.model('gh3642', bandSchema); + var bandSchema = new Schema({guitarist: personSchema, name: String}); + var Band = db.model('gh3642', bandSchema); - var velvetRevolver = new Band({ - name: 'Velvet Revolver', - guitarist: {name: 'Slash', realName: 'Saul Hudson'} - }); + var velvetRevolver = new Band({ + name: 'Velvet Revolver', + guitarist: {name: 'Slash', realName: 'Saul Hudson'} + }); - velvetRevolver.save(function(error) { - assert.ifError(error); - var query = {name: 'Velvet Revolver'}; - Band.collection.findOne(query, function(error, band) { + velvetRevolver.save(function(error) { assert.ifError(error); - assert.ok(!band.guitarist.realName); - db.close(done); + var query = {name: 'Velvet Revolver'}; + Band.collection.findOne(query, function(error, band) { + assert.ifError(error); + assert.ok(!band.guitarist.realName); + done(); + }); }); }); - }); - - describe('bug fixes', function() { - var db; - - before(function() { - db = start(); - }); - - after(function(done) { - db.close(done); - }); it('single embedded docs post hooks (gh-3679)', function(done) { var postHookCalls = []; From 6deeaa9c7333671035a214622c0c8405f822e481 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 4 Mar 2016 08:38:17 -0800 Subject: [PATCH 0338/2240] docs(model): clarify runValidators and setDefaultsOnInsert options Re: #3892 --- lib/model.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/model.js b/lib/model.js index 4635f7ad226..5dcb8b3f86b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1394,9 +1394,12 @@ Model.$where = function $where() { * * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0) * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. + * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. + * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `select`: sets the document fields to return * + * * ####Examples: * * A.findOneAndUpdate(conditions, update, options, callback) // executes @@ -1502,6 +1505,8 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { * * - `new`: bool - true to return the modified document rather than the original. defaults to false * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. + * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. + * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `select`: sets the document fields to return * @@ -1891,6 +1896,8 @@ Model.hydrate = function(obj) { * - `safe` (boolean) safe mode (defaults to value set in schema (true)) * - `upsert` (boolean) whether to create the doc if it doesn't match (false) * - `multi` (boolean) whether multiple documents should be updated (false) + * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. + * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `strict` (boolean) overrides the `strict` option for this update * - `overwrite` (boolean) disables update-only mode, allowing you to overwrite the doc (false) * From 82895787e9b2a78ab7c6179b31b97a54487bc59e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 4 Mar 2016 08:38:44 -0800 Subject: [PATCH 0339/2240] docs(query): clarify runValidators and setDefaultsOnInsert options Fix #3892 --- lib/query.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/query.js b/lib/query.js index e00e3d07e90..0c75b2b31cb 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1528,6 +1528,8 @@ function prepareDiscriminatorCriteria(query) { * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0) * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. + * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) * * ####Callback Signature @@ -1927,6 +1929,16 @@ Query.prototype._execUpdate = function(callback) { * * Model.where({ _id: id }).update({ $set: { title: 'words' }}) * + * ####Valid options: + * + * - `safe` (boolean) safe mode (defaults to value set in schema (true)) + * - `upsert` (boolean) whether to create the doc if it doesn't match (false) + * - `multi` (boolean) whether multiple documents should be updated (false) + * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. + * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). + * - `strict` (boolean) overrides the `strict` option for this update + * - `overwrite` (boolean) disables update-only mode, allowing you to overwrite the doc (false) + * * ####Note * * Passing an empty object `{}` as the doc will result in a no-op unless the `overwrite` option is passed. Without the `overwrite` option set, the update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting documents in the collection. From e4053d8f48b9a505321b5449b394527bb61aa11b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 4 Mar 2016 09:15:11 -0800 Subject: [PATCH 0340/2240] test(document): repro #3902 --- package.json | 1 + test/document.test.js | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/package.json b/package.json index 1a79fad5c24..b109a6a79c2 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "highlight.js": "7.0.1", "istanbul": "0.4.2", "jade": "0.26.3", + "lodash": "4.6.1", "markdown": "0.3.1", "marked": "0.3.5", "mocha": "2.3.4", diff --git a/test/document.test.js b/test/document.test.js index fe81610d15e..7b6a33d68ee 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -17,6 +17,8 @@ var start = require('./common'), EmbeddedDocument = require('../lib/types/embedded'), Query = require('../lib/query'); +var _ = require('lodash'); + /** * Test Document constructor. */ @@ -2447,5 +2449,20 @@ describe('document', function() { }); }); }); + + it('pre and post as schema keys (gh-3902)', function(done) { + var schema = new mongoose.Schema({ + pre: String, + post: String + }, { versionKey: false }); + var MyModel = db.model('gh3902', schema); + + MyModel.create({ pre: 'test', post: 'test' }, function(error, doc) { + assert.ifError(error); + assert.deepEqual(_.omit(doc.toObject(), '_id'), + { pre: 'test', post: 'test' }); + done(); + }); + }); }); }); From fbc03bac80d6249640bb56677a4eca24bf5aa57f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 4 Mar 2016 09:15:37 -0800 Subject: [PATCH 0341/2240] fix(document): prefix pre and post with $ to prevent name collisions #3902 --- lib/document.js | 18 +++++++++++------- test/document.hooks.test.js | 36 ++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/lib/document.js b/lib/document.js index a5e52afb9e0..d754b39e318 100644 --- a/lib/document.js +++ b/lib/document.js @@ -393,7 +393,11 @@ Document.prototype.$__storeShard = function() { */ for (var k in hooks) { - Document.prototype[k] = Document[k] = hooks[k]; + if (k === 'pre' || k === 'post') { + Document.prototype['$' + k] = Document['$' + k] = hooks[k]; + } else { + Document.prototype[k] = Document[k] = hooks[k]; + } } /** @@ -1765,12 +1769,12 @@ Document.prototype.$__registerHooksFromSchema = function() { if (toWrap.init && _this instanceof Embedded) { if (toWrap.init.pre) { toWrap.init.pre.forEach(function(args) { - _this.pre.apply(_this, args); + _this.$pre.apply(_this, args); }); } if (toWrap.init.post) { toWrap.init.post.forEach(function(args) { - _this.post.apply(_this, args); + _this.$post.apply(_this, args); }); } delete toWrap.init; @@ -1778,12 +1782,12 @@ Document.prototype.$__registerHooksFromSchema = function() { // Set hooks also need to be sync re: gh-3479 if (toWrap.set.pre) { toWrap.set.pre.forEach(function(args) { - _this.pre.apply(_this, args); + _this.$pre.apply(_this, args); }); } if (toWrap.set.post) { toWrap.set.post.forEach(function(args) { - _this.post.apply(_this, args); + _this.$post.apply(_this, args); }); } delete toWrap.set; @@ -1825,11 +1829,11 @@ Document.prototype.$__registerHooksFromSchema = function() { toWrap[pointCut].pre.forEach(function(args) { args[0] = newName; - _this.pre.apply(_this, args); + _this.$pre.apply(_this, args); }); toWrap[pointCut].post.forEach(function(args) { args[0] = newName; - _this.post.apply(_this, args); + _this.$post.apply(_this, args); }); }); return _this; diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js index 9f2efeb17f4..ec1ec5be8ef 100644 --- a/test/document.hooks.test.js +++ b/test/document.hooks.test.js @@ -83,7 +83,7 @@ describe('document: hooks:', function() { steps = 0; // serial - doc.pre('hooksTest', function(next) { + doc.$pre('hooksTest', function(next) { steps++; setTimeout(function() { // make sure next step hasn't executed yet @@ -92,13 +92,13 @@ describe('document: hooks:', function() { }, 50); }); - doc.pre('hooksTest', function(next) { + doc.$pre('hooksTest', function(next) { steps++; next(); }); // parallel - doc.pre('hooksTest', true, function(next, done) { + doc.$pre('hooksTest', true, function(next, done) { steps++; assert.equal(3, steps); setTimeout(function() { @@ -111,7 +111,7 @@ describe('document: hooks:', function() { next(); }); - doc.pre('hooksTest', true, function(next, done) { + doc.$pre('hooksTest', true, function(next, done) { steps++; setTimeout(function() { assert.equal(4, steps); @@ -134,13 +134,13 @@ describe('document: hooks:', function() { var doc = new TestDocument(), steps = 0; - doc.pre('hooksTest', function(next) { + doc.$pre('hooksTest', function(next) { steps++; next(); next(); }); - doc.pre('hooksTest', function(next) { + doc.$pre('hooksTest', function(next) { steps++; next(); }); @@ -156,14 +156,14 @@ describe('document: hooks:', function() { var doc = new TestDocument(), steps = 0; - doc.pre('hooksTest', true, function(next, done) { + doc.$pre('hooksTest', true, function(next, done) { steps++; next(); done(); done(); }); - doc.pre('hooksTest', true, function(next, done) { + doc.$pre('hooksTest', true, function(next, done) { steps++; next(); done(); @@ -181,17 +181,17 @@ describe('document: hooks:', function() { var doc = new TestDocument(), steps = 0; - doc.pre('hooksTest', function(next) { + doc.$pre('hooksTest', function(next) { steps++; next(); }); - doc.pre('hooksTest', function(next) { + doc.$pre('hooksTest', function(next) { steps++; next(new Error); }); - doc.pre('hooksTest', function() { + doc.$pre('hooksTest', function() { steps++; }); @@ -205,7 +205,7 @@ describe('document: hooks:', function() { it('errors from last serial hook', function(done) { var doc = new TestDocument(); - doc.pre('hooksTest', function(next) { + doc.$pre('hooksTest', function(next) { next(new Error); }); @@ -218,7 +218,7 @@ describe('document: hooks:', function() { it('mutating incoming args via middleware', function(done) { var doc = new TestDocument(); - doc.pre('set', function(next, path, val) { + doc.$pre('set', function(next, path, val) { next(path, 'altered-' + val); }); @@ -231,19 +231,19 @@ describe('document: hooks:', function() { var doc = new TestDocument(), steps = 0; - doc.pre('hooksTest', true, function(next, done) { + doc.$pre('hooksTest', true, function(next, done) { steps++; next(); done(); }); - doc.pre('hooksTest', true, function(next, done) { + doc.$pre('hooksTest', true, function(next, done) { steps++; next(); done(); }); - doc.pre('hooksTest', true, function(next, done) { + doc.$pre('hooksTest', true, function(next, done) { steps++; next(); done(new Error); @@ -259,7 +259,7 @@ describe('document: hooks:', function() { it('passing two arguments to a method subject to hooks and return value', function(done) { var doc = new TestDocument(); - doc.pre('hooksTest', function(next) { + doc.$pre('hooksTest', function(next) { next(); }); @@ -411,7 +411,7 @@ describe('document: hooks:', function() { var Bar = db.model('gh-1335-2', BarSchema); var b = new Bar(); - b.pre('save', function(next) { + b.$pre('save', function(next) { if (this.isNew && this.foos.length === 0) { this.foos = undefined; } From 9b81f61e154d4aa7bf156a63c85cb34a561207cb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 4 Mar 2016 09:54:38 -0800 Subject: [PATCH 0342/2240] test(populate): repro #3904 --- test/model.populate.test.js | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 71472766f2a..65f2c9ee8be 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -2,6 +2,7 @@ * Test dependencies. */ +var _ = require('lodash'); var start = require('./common'); var assert = require('power-assert'); var mongoose = start.mongoose; @@ -3280,5 +3281,71 @@ describe('model: populate:', function() { }); } }); + + it('deep populate single -> array (gh-3904)', function(done) { + var personSchema = new Schema({ + name: { type: String } + }); + + var teamSchema = new Schema({ + name: { type: String }, + members: [{ type: Schema.Types.ObjectId, ref: 'gh3904' }] + }); + + var gameSchema = new Schema({ + team: { type: Schema.Types.ObjectId, ref: 'gh3904_0' }, + opponent: { type: Schema.Types.ObjectId, ref: 'gh3904_0' } + }); + + var Person = db.model('gh3904', personSchema); + var Team = db.model('gh3904_0', teamSchema); + var Game = db.model('gh3904_1', gameSchema); + + var people = [ + { name: 'Shaq' }, + { name: 'Kobe' }, + { name: 'Horry' }, + { name: 'Duncan' }, + { name: 'Robinson' }, + { name: 'Johnson' } + ]; + + Person.create(people, function(error, people) { + assert.ifError(error); + var lakers = { + name: 'Lakers', + members: [people[0]._id, people[1]._id, people[2]._id] + }; + var spurs = { + name: 'Spurs', + members: [people[1]._id, people[2]._id, people[3]._id] + }; + var teams = [lakers, spurs]; + Team.create(teams, function(error, teams) { + assert.ifError(error); + var game = { team: teams[0]._id, opponent: teams[1]._id }; + Game.create(game, function(error, game) { + assert.ifError(error); + test(game._id); + }); + }); + }); + + function test(id) { + var query = Game.findById(id).populate({ + path: 'team', + select: 'name members', + populate: { path: 'members', select: 'name' } + }); + query.exec(function(error, doc) { + assert.ifError(error); + var arr = _.map(doc.toObject().team.members, function(v) { + return v.name; + }); + assert.deepEqual(arr, ['Shaq', 'Kobe', 'Horry']); + done(); + }); + } + }); }); }); From 5b3cda5497c9257424dec0e50a8a2e594bff40fc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 4 Mar 2016 09:54:53 -0800 Subject: [PATCH 0343/2240] fix(populate): get subpopulate model correctly when array under nested Fix #3904 --- lib/model.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index 5dcb8b3f86b..786be9328bc 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2531,15 +2531,25 @@ function subPopulate(docs, options, cb) { } var schema = _this.schema._getSchema(prefix); + var subSchema; if (typeof subOptions.model === 'string') { subOptions.model = _this.model(subOptions.model); } else if (schema && schema.caster && schema.caster.options && schema.caster.options.ref) { - var subSchema = _this.model(schema.caster.options.ref).schema. - _getSchema(subOptions._originalPath); + subSchema = _this.model(schema.caster.options.ref).schema. + _getSchema(subOptions._originalPath); if (subSchema && subSchema.options && subSchema.options.ref) { subOptions.model = _this.model(subSchema.options.ref); } + } else if (schema && schema.options && schema.options.ref) { + subSchema = _this.model(schema.options.ref).schema. + _getSchema(subOptions._originalPath); + if (subSchema && subSchema.options && subSchema.options.ref) { + subOptions.model = _this.model(subSchema.options.ref); + } else if (subSchema && subSchema.caster && subSchema.caster.options && + subSchema.caster.options.ref) { + subOptions.model = _this.model(subSchema.caster.options.ref); + } } Model.populate.call(subOptions.model || _this, docs, subOptions, next); }); From 692fdb099a0d7e598451630fd5e658b18699a35a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 5 Mar 2016 08:04:46 -0800 Subject: [PATCH 0344/2240] test: reuse connections for query tests --- test/query.test.js | 127 ++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 65 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index 1d02e3887e2..c89cabbea1a 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1490,81 +1490,56 @@ describe('Query', function() { }); }); - it('excludes _id when select false and inclusive mode (gh-3010)', function(done) { - var db = start(); - var User = db.model('gh3010', { - _id: { - select: false, - type: Schema.Types.ObjectId, - default: mongoose.Types.ObjectId - }, - username: String - }); - - User.create({username: 'Val'}, function(error, user) { - assert.ifError(error); - User.find({_id: user._id}).select('username').exec(function(error, users) { - assert.ifError(error); - assert.equal(users.length, 1); - assert.ok(!users[0]._id); - assert.equal(users[0].username, 'Val'); - db.close(done); - }); - }); - }); + describe('bug fixes', function() { + var db; - it('doesnt reverse key order for update docs (gh-3215)', function(done) { - var db = start(); - var Test = db.model('gh3215', { - arr: [{date: Date, value: Number}] + before(function() { + db = start(); }); - var q = Test.update({}, { - $push: { - arr: { - $each: [{date: new Date(), value: 1}], - $sort: {value: -1, date: -1} - } - } + after(function(done) { + db.close(done); }); - assert.deepEqual(Object.keys(q.getUpdate().$push.arr.$sort), - ['value', 'date']); - db.close(done); - }); + it('excludes _id when select false and inclusive mode (gh-3010)', function(done) { + var User = db.model('gh3010', { + _id: { + select: false, + type: Schema.Types.ObjectId, + default: mongoose.Types.ObjectId + }, + username: String + }); - it('handles nested $ (gh-3265)', function(done) { - var db = start(); - var Post = db.model('gh3265', { - title: String, - answers: [{ - details: String, - stats: { - votes: Number, - count: Number - } - }] + User.create({username: 'Val'}, function(error, user) { + assert.ifError(error); + User.find({_id: user._id}).select('username').exec(function(error, users) { + assert.ifError(error); + assert.equal(users.length, 1); + assert.ok(!users[0]._id); + assert.equal(users[0].username, 'Val'); + done(); + }); + }); }); - var answersUpdate = {details: 'blah', stats: {votes: 1, count: '3'}}; - var q = Post.update( - {'answers._id': '507f1f77bcf86cd799439011'}, - {$set: {'answers.$': answersUpdate}}); - - assert.deepEqual(q.getUpdate().$set['answers.$'].stats, - {votes: 1, count: 3}); - db.close(done); - }); - - describe('bug fixes', function() { - var db; + it('doesnt reverse key order for update docs (gh-3215)', function(done) { + var Test = db.model('gh3215', { + arr: [{date: Date, value: Number}] + }); - before(function() { - db = start(); - }); + var q = Test.update({}, { + $push: { + arr: { + $each: [{date: new Date(), value: 1}], + $sort: {value: -1, date: -1} + } + } + }); - after(function(done) { - db.close(done); + assert.deepEqual(Object.keys(q.getUpdate().$push.arr.$sort), + ['value', 'date']); + done(); }); it('allows sort with count (gh-3914)', function(done) { @@ -1590,6 +1565,28 @@ describe('Query', function() { done(); }); }); + + it('handles nested $ (gh-3265)', function(done) { + var Post = db.model('gh3265', { + title: String, + answers: [{ + details: String, + stats: { + votes: Number, + count: Number + } + }] + }); + + var answersUpdate = {details: 'blah', stats: {votes: 1, count: '3'}}; + var q = Post.update( + {'answers._id': '507f1f77bcf86cd799439011'}, + {$set: {'answers.$': answersUpdate}}); + + assert.deepEqual(q.getUpdate().$set['answers.$'].stats, + {votes: 1, count: 3}); + done(); + }); }); describe('handles falsy and object projections with defaults (gh-3256)', function() { From b7f2b4a1e5f9418197aaae1e4208b1c6017b1c8b Mon Sep 17 00:00:00 2001 From: Fonger Date: Mon, 7 Mar 2016 01:18:12 +0800 Subject: [PATCH 0345/2240] allow setup timestamps by Schema.prototype.set --- lib/schema.js | 105 ++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 96236db2763..e8a670ea69b 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -119,51 +119,8 @@ function Schema(obj, options) { this[m.kind](m.hook, !!m.isAsync, m.fn); } - // adds updatedAt and createdAt timestamps to documents if enabled - var timestamps = this.options.timestamps; - if (timestamps) { - var createdAt = timestamps.createdAt || 'createdAt', - updatedAt = timestamps.updatedAt || 'updatedAt', - schemaAdditions = {}; - - schemaAdditions[updatedAt] = Date; - - if (!this.paths[createdAt]) { - schemaAdditions[createdAt] = Date; - } - - this.add(schemaAdditions); - - this.pre('save', function(next) { - var defaultTimestamp = new Date(); - - if (!this[createdAt]) { - this[createdAt] = auto_id ? this._id.getTimestamp() : defaultTimestamp; - } - - this[updatedAt] = this.isNew ? this[createdAt] : defaultTimestamp; - - next(); - }); - - var genUpdates = function() { - var now = new Date(); - var updates = {$set: {}, $setOnInsert: {}}; - updates.$set[updatedAt] = now; - updates.$setOnInsert[createdAt] = now; - - return updates; - }; - - this.pre('findOneAndUpdate', function(next) { - this.findOneAndUpdate({}, genUpdates()); - next(); - }); - - this.pre('update', function(next) { - this.update({}, genUpdates()); - next(); - }); + if (this.options.timestamps) { + this.setupTimestamp(this.options.timestamps); } } @@ -722,6 +679,60 @@ Schema.prototype.hasMixedParent = function(path) { return false; }; +/** + * Setup updatedAt and createdAt timestamps to documents if enabled + * + * @param {Boolean|Object} timestamps timestamps options + * @api private + */ +Schema.prototype.setupTimestamp = function(timestamps) { + if (timestamps) { + var createdAt = timestamps.createdAt || 'createdAt', + updatedAt = timestamps.updatedAt || 'updatedAt', + schemaAdditions = {}; + + schemaAdditions[updatedAt] = Date; + + if (!this.paths[createdAt]) { + schemaAdditions[createdAt] = Date; + } + + this.add(schemaAdditions); + + this.pre('save', function(next) { + var defaultTimestamp = new Date(); + var auto_id = this._id && this._id.auto; + + if (!this[createdAt]) { + this[createdAt] = auto_id ? this._id.getTimestamp() : defaultTimestamp; + } + + this[updatedAt] = this.isNew ? this[createdAt] : defaultTimestamp; + + next(); + }); + + var genUpdates = function() { + var now = new Date(); + var updates = {$set: {}, $setOnInsert: {}}; + updates.$set[updatedAt] = now; + updates.$setOnInsert[createdAt] = now; + + return updates; + }; + + this.pre('findOneAndUpdate', function(next) { + this.findOneAndUpdate({}, genUpdates()); + next(); + }); + + this.pre('update', function(next) { + this.update({}, genUpdates()); + next(); + }); + } +}; + /*! * ignore */ @@ -1025,6 +1036,10 @@ Schema.prototype.set = function(key, value, _tags) { ? {w: 0} : value; break; + case 'timestamps': + this.setupTimestamp(value); + this.options[key] = value; + break; default: this.options[key] = value; } From 36a365ec3e356831bdd82a3fe4451da80322445a Mon Sep 17 00:00:00 2001 From: Fonger Date: Mon, 7 Mar 2016 01:18:35 +0800 Subject: [PATCH 0346/2240] add test cases for timestamps --- test/schema.timestamps.test.js | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js index 6729a08fb34..14c950f4ff1 100644 --- a/test/schema.timestamps.test.js +++ b/test/schema.timestamps.test.js @@ -22,6 +22,18 @@ describe('schema options.timestamps', function() { done(); }); + it('should have createdAt and updatedAt fields', function(done) { + var TestSchema = new Schema({ + name: String + }); + + TestSchema.set('timestamps', true); + + assert.ok(TestSchema.path('createdAt')); + assert.ok(TestSchema.path('updatedAt')); + done(); + }); + it('should have created and updatedAt fields', function(done) { var TestSchema = new Schema({ name: String @@ -36,6 +48,20 @@ describe('schema options.timestamps', function() { done(); }); + it('should have created and updatedAt fields', function(done) { + var TestSchema = new Schema({ + name: String + }); + + TestSchema.set('timestamps', { + createdAt: 'created' + }); + + assert.ok(TestSchema.path('created')); + assert.ok(TestSchema.path('updatedAt')); + done(); + }); + it('should have created and updated fields', function(done) { var TestSchema = new Schema({ name: String @@ -50,6 +76,21 @@ describe('schema options.timestamps', function() { assert.ok(TestSchema.path('updated')); done(); }); + + it('should have created and updated fields', function(done) { + var TestSchema = new Schema({ + name: String + }); + + TestSchema.set('timestamps', { + createdAt: 'created', + updatedAt: 'updated' + }); + + assert.ok(TestSchema.path('created')); + assert.ok(TestSchema.path('updated')); + done(); + }); }); describe('auto update createdAt and updatedAt when create/save/update document', function() { From aaa3ff2357fa53d9409982445babd44d667eeed8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 6 Mar 2016 12:59:51 -0800 Subject: [PATCH 0347/2240] test: repro #3935 --- test/schema.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 4fbfa658cf8..6d4c05c3bd7 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1512,6 +1512,20 @@ describe('schema', function() { done(); }); + it('booleans cause cast error for date (gh-3935)', function(done) { + var testSchema = new Schema({ + test: Date + }); + + var Test = mongoose.model('gh3935', testSchema); + var test = new Test({ test: true }); + + assert.ok(test.validateSync()); + assert.equal(test.validateSync().errors.test.name, 'CastError'); + + done(); + }); + describe('remove()', function() { before(function() { this.schema = new Schema({ From ea6369d6436dfa3f161aaddd3b3c14b850ad49ac Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 6 Mar 2016 12:59:56 -0800 Subject: [PATCH 0348/2240] fix(schema): don't cast boolean to date Fix #3935 --- lib/schema/date.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/schema/date.js b/lib/schema/date.js index 04c02aa56b8..0d1fb921cb0 100644 --- a/lib/schema/date.js +++ b/lib/schema/date.js @@ -222,6 +222,10 @@ SchemaDate.prototype.cast = function(value) { var date; + if (typeof value === 'boolean') { + throw new CastError('date', value, this.path); + } + if (value instanceof Number || typeof value === 'number' || String(value) == Number(value)) { // support for timestamps From 4dcfba58a206707c0c06671821ebbcbe5e0cd789 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 6 Mar 2016 13:30:11 -0800 Subject: [PATCH 0349/2240] test: repro #3940 --- test/index.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/index.test.js b/test/index.test.js index 25e80077565..27c45cc1ea3 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -392,6 +392,7 @@ describe('mongoose module:', function() { assert.equal('function', typeof mongoose.Collection); assert.equal('function', typeof mongoose.Connection); assert.equal('function', typeof mongoose.Schema); + assert.ok(mongoose.Schema.Types); assert.equal('function', typeof mongoose.SchemaType); assert.equal('function', typeof mongoose.Query); assert.equal('function', typeof mongoose.Promise); @@ -413,5 +414,12 @@ describe('mongoose module:', function() { test(new mongoose.Mongoose); done(); }); + + it('of result from .connect() (gh-3940)', function(done) { + var m = new mongoose.Mongoose; + test(m.connect('mongodb://localhost:27017')); + m.disconnect(); + done(); + }); }); }); From 5eebc94834dfb107269574d7bbc2d232b24bd0d5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 6 Mar 2016 13:30:16 -0800 Subject: [PATCH 0350/2240] fix: MongooseThenable doesn't overwrite constructors Fix #3940 --- lib/error.js | 1 + lib/index.js | 118 +++++++++++++++++++++++++------------------------- lib/schema.js | 1 + 3 files changed, 61 insertions(+), 59 deletions(-) diff --git a/lib/error.js b/lib/error.js index b084e764c95..98158f74fdc 100644 --- a/lib/error.js +++ b/lib/error.js @@ -16,6 +16,7 @@ function MongooseError(msg) { this.message = msg; this.name = 'MongooseError'; } +MongooseError.$isConstructor = true; /*! * Inherits from Error. diff --git a/lib/index.js b/lib/index.js index 9546e61f715..9b17b54b6e8 100644 --- a/lib/index.js +++ b/lib/index.js @@ -43,65 +43,6 @@ function Mongoose() { conn.models = this.models; } -/** - * Wraps the given Mongoose instance into a thenable (pseudo-promise). This - * is so `connect()` and `disconnect()` can return a thenable while maintaining - * backwards compatibility. - * - * @api private - */ - -function MongooseThenable(mongoose, promise) { - var _this = this; - for (var key in mongoose) { - if (typeof mongoose[key] === 'function') { - (function(key) { - _this[key] = function() { - return mongoose[key].apply(mongoose, arguments); - }; - })(key); - } else { - this[key] = mongoose[key]; - } - } - this.$opPromise = promise; -} - -/** - * Ability to use mongoose object as a pseudo-promise so `.connect().then()` - * and `.disconnect().then()` are viable. - * - * @param {Function} onFulfilled - * @param {Function} onRejected - * @return {Promise} - * @api private - */ - -MongooseThenable.prototype.then = function(onFulfilled, onRejected) { - var Promise = PromiseProvider.get(); - if (!this.$opPromise) { - return new Promise.ES6(function(resolve, reject) { - reject(new Error('Can only call `.then()` if connect() or disconnect() ' + - 'has been called')); - }).then(onFulfilled, onRejected); - } - return this.$opPromise.then(onFulfilled, onRejected); -}; - -/** - * Ability to use mongoose object as a pseudo-promise so `.connect().then()` - * and `.disconnect().then()` are viable. - * - * @param {Function} onFulfilled - * @param {Function} onRejected - * @return {Promise} - * @api private - */ - -MongooseThenable.prototype.catch = function(onRejected) { - return this.then(null, onRejected); -}; - /** * Expose connection states for user-land * @@ -765,6 +706,65 @@ Mongoose.prototype.mongo = require('mongodb'); Mongoose.prototype.mquery = require('mquery'); +/** + * Wraps the given Mongoose instance into a thenable (pseudo-promise). This + * is so `connect()` and `disconnect()` can return a thenable while maintaining + * backwards compatibility. + * + * @api private + */ + +function MongooseThenable(mongoose, promise) { + var _this = this; + for (var key in mongoose) { + if (typeof mongoose[key] === 'function' && !mongoose[key].$isConstructor) { + (function(key) { + _this[key] = function() { + return mongoose[key].apply(mongoose, arguments); + }; + })(key); + } + } + this.$opPromise = promise; +} + +MongooseThenable.prototype = new Mongoose; + +/** + * Ability to use mongoose object as a pseudo-promise so `.connect().then()` + * and `.disconnect().then()` are viable. + * + * @param {Function} onFulfilled + * @param {Function} onRejected + * @return {Promise} + * @api private + */ + +MongooseThenable.prototype.then = function(onFulfilled, onRejected) { + var Promise = PromiseProvider.get(); + if (!this.$opPromise) { + return new Promise.ES6(function(resolve, reject) { + reject(new Error('Can only call `.then()` if connect() or disconnect() ' + + 'has been called')); + }).then(onFulfilled, onRejected); + } + return this.$opPromise.then(onFulfilled, onRejected); +}; + +/** + * Ability to use mongoose object as a pseudo-promise so `.connect().then()` + * and `.disconnect().then()` are viable. + * + * @param {Function} onFulfilled + * @param {Function} onRejected + * @return {Promise} + * @api private + */ + +MongooseThenable.prototype.catch = function(onRejected) { + return this.then(null, onRejected); +}; + /*! * The exports object is an instance of Mongoose. * diff --git a/lib/schema.js b/lib/schema.js index 96236db2763..3ca2ab2e0fa 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -166,6 +166,7 @@ function Schema(obj, options) { }); } } +Schema.$isConstructor = true; /*! * Returns this documents _id cast to a string. From 8fd872b8cbefc4ab5a9a25487b4f48381de442ac Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 7 Mar 2016 09:25:56 -0800 Subject: [PATCH 0351/2240] fix: declare index methods as having side effects for #3940 --- lib/error.js | 1 - lib/index.js | 10 +++++++++- lib/schema.js | 1 - 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/error.js b/lib/error.js index 98158f74fdc..b084e764c95 100644 --- a/lib/error.js +++ b/lib/error.js @@ -16,7 +16,6 @@ function MongooseError(msg) { this.message = msg; this.name = 'MongooseError'; } -MongooseError.$isConstructor = true; /*! * Inherits from Error. diff --git a/lib/index.js b/lib/index.js index 9b17b54b6e8..9ebebf147f5 100644 --- a/lib/index.js +++ b/lib/index.js @@ -73,6 +73,7 @@ Mongoose.prototype.set = function(key, value) { this.options[key] = value; return this; }; +Mongoose.prototype.set.$hasSideEffects = true; /** * Gets mongoose options @@ -190,6 +191,7 @@ Mongoose.prototype.createConnection = function(uri, options) { return conn; }; +Mongoose.prototype.createConnection.$hasSideEffects = true; /** * Opens the default mongoose connection. @@ -238,6 +240,7 @@ Mongoose.prototype.connect = function() { return new MongooseThenable(this, conn.open.apply(conn, arguments)); }; +Mongoose.prototype.connect.$hasSideEffects = true; /** * Disconnects all connections. @@ -270,6 +273,7 @@ Mongoose.prototype.disconnect = function(fn) { resolve(); })); }; +Mongoose.prototype.disconnect.$hasSideEffects = true; /** * Defines a model or retrieves it. @@ -398,6 +402,7 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) { this.models[name] = model; return this.models[name]; }; +Mongoose.prototype.model.$hasSideEffects = true; /** * Returns an array of model names created on this instance of Mongoose. @@ -414,6 +419,7 @@ Mongoose.prototype.modelNames = function() { var names = Object.keys(this.models); return names; }; +Mongoose.prototype.modelNames.$hasSideEffects = true; /** * Applies global plugins to `schema`. @@ -427,6 +433,7 @@ Mongoose.prototype._applyPlugins = function(schema) { schema.plugin(this.plugins[i][0], this.plugins[i][1]); } }; +Mongoose.prototype._applyPlugins.$hasSideEffects = true; /** * Declares a global plugin executed on all Schemas. @@ -444,6 +451,7 @@ Mongoose.prototype.plugin = function(fn, opts) { this.plugins.push([fn, opts]); return this; }; +Mongoose.prototype.plugin.$hasSideEffects = true; /** * The default connection of the mongoose module. @@ -717,7 +725,7 @@ Mongoose.prototype.mquery = require('mquery'); function MongooseThenable(mongoose, promise) { var _this = this; for (var key in mongoose) { - if (typeof mongoose[key] === 'function' && !mongoose[key].$isConstructor) { + if (typeof mongoose[key] === 'function' && mongoose[key].$hasSideEffects) { (function(key) { _this[key] = function() { return mongoose[key].apply(mongoose, arguments); diff --git a/lib/schema.js b/lib/schema.js index 3ca2ab2e0fa..96236db2763 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -166,7 +166,6 @@ function Schema(obj, options) { }); } } -Schema.$isConstructor = true; /*! * Returns this documents _id cast to a string. From f4fc60ac673536b64862200222bae869a25afb87 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 8 Mar 2016 08:34:54 -0800 Subject: [PATCH 0352/2240] test: repro #3929 --- test/connection.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/connection.test.js b/test/connection.test.js index cbc2bfcbf5e..edb709fddf8 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -391,7 +391,7 @@ describe('connections:', function() { + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true' + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true' + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags=' - + 'dc:ny,rack:1&readPreferenceTags=dc:sf'; + + 'dc:ny,rack:1&readPreferenceTags=dc:sf&sslValidate=true'; var db = mongoose.createConnection(conn); db.on('error', function() { @@ -425,6 +425,7 @@ describe('connections:', function() { assert.equal('nearest', db.options.db.readPreference); assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags); assert.equal(false, db.options.db.forceServerObjectId); + assert.strictEqual(db.options.server.sslValidate, true); done(); }); it('mixed with passed options', function(done) { From 3a890bb257049c76b480b76287c52f96c64ae997 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 8 Mar 2016 08:35:44 -0800 Subject: [PATCH 0353/2240] fix(drivers): support sslValidate in connection string Fix #3929 --- lib/drivers/node-mongodb-native/connection.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index f600665ad3e..6ad3e51f974 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -314,6 +314,9 @@ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { o.db.read_preference_tags = opts[name]; } break; + case 'sslValidate': + o.server.sslValidate = opts.sslValidate; + o.replset.sslValidate = opts.sslValidate; } }); From c92207d701de76d6734688d2dd494e30efc45b16 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 10:08:48 -0800 Subject: [PATCH 0354/2240] docs(validation): show how to use custom required messages in schema Fix #2616 --- docs/validation.jade | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/validation.jade b/docs/validation.jade index 7557d8c5b6d..3c8f677476a 100644 --- a/docs/validation.jade +++ b/docs/validation.jade @@ -38,7 +38,8 @@ block content return /\d{3}-\d{3}-\d{4}/.test(v); }, message: '{VALUE} is not a valid phone number!' - } + }, + required: [true, 'User phone number required'] } }); @@ -50,6 +51,10 @@ block content // Prints "ValidationError: 555.0123 is not a valid phone number!" console.log(u.validateSync().toString()); + u.phone = ''; + // Prints "ValidationError: User phone number required" + console.log(u.validateSync().toString()); + u.phone = '201-555-0123'; // Prints undefined - validation succeeded! console.log(u.validateSync()); From 90f9003755b9baafd6baf1f40f28045d7f52827c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 10:44:10 -0800 Subject: [PATCH 0355/2240] refactor(test): reuse connection for some model tests --- test/model.test.js | 55 ++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/test/model.test.js b/test/model.test.js index 7bbff34a169..246bfe58989 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5102,9 +5102,21 @@ describe('Model', function() { }); describe('gh-1920', function() { - it('doesnt crash', function(done) { - var db = start(); + }); + + describe('bug fixes', function() { + var db; + + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('doesnt crash (gh-1920)', function(done) { var parentSchema = new Schema({ children: [new Schema({ name: String @@ -5120,16 +5132,12 @@ describe('Model', function() { parent.children.push({name: 'another child'}); Parent.findByIdAndUpdate(it._id, {$set: {children: parent.children}}, function(err) { assert.ifError(err); - db.close(done); + done(); }); }); }); - }); - describe('save failure', function() { it('doesnt reset "modified" status for fields', function(done) { - var db = start(); - var UniqueSchema = new Schema({ changer: String, unique: { @@ -5163,35 +5171,30 @@ describe('Model', function() { u2.save(function(err) { assert.ok(err); assert.ok(u2.isModified('changer')); - db.close(done); + done(); }); }); }); }); }); - }); - it('insertMany() (gh-723)', function(done) { - var db = start(); - var schema = new Schema({name: String}); - var Movie = db.model('gh723', schema); - - var arr = [{name: 'Star Wars'}, {name: 'The Empire Strikes Back'}]; - Movie.insertMany(arr, function(error, docs) { - assert.ifError(error); - assert.equal(docs.length, 2); - Movie.find({}, function(error, docs) { + it('insertMany() (gh-723)', function(done) { + var schema = new Schema({name: String}); + var Movie = db.model('gh723', schema); + + var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }]; + Movie.insertMany(arr, function(error, docs) { assert.ifError(error); assert.equal(docs.length, 2); - done(); + Movie.find({}, function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 2); + done(); + }); }); }); - }); - - describe('gh-2442', function() { - it('marks array as modified when initializing non-array from db', function(done) { - var db = start(); + it('marks array as modified when initializing non-array from db (gh-2442)', function(done) { var s1 = new Schema({ array: mongoose.Schema.Types.Mixed }, {minimize: false}); @@ -5226,7 +5229,7 @@ describe('Model', function() { assert.ok(!doc.isModified('array')); assert.deepEqual(doc.array[0].value, 1); assert.equal('[{"value":1}]', JSON.stringify(doc.array)); - db.close(done); + done(); }); }); }); From db5cac9a49dd5ae9dcacb9da7a134699de2112bb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 11:10:31 -0800 Subject: [PATCH 0356/2240] test(model): repro #3906 --- test/model.test.js | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/test/model.test.js b/test/model.test.js index 246bfe58989..c69f1b84ab5 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5101,15 +5101,51 @@ describe('Model', function() { }); }); - describe('gh-1920', function() { + it('save max bson size error with buffering (gh-3906)', function(done) { + this.timeout(10000); + var db = start({ noErrorListener: true }); + var Test = db.model('gh3906_0', { name: Object }); + + var test = new Test({ + name: { + data: (new Array(16 * 1024 * 1024)).join('x') + } + }); + + test.save(function(error) { + assert.ok(error); + assert.equal(error.toString(), + 'MongoError: document is larger than the maximum size 16777216'); + db.close(done); + }); + }); + + it('reports max bson size error in save (gh-3906)', function(done) { + this.timeout(10000); + var db = start({ noErrorListener: true }); + var Test = db.model('gh3906', { name: Object }); + var test = new Test({ + name: { + data: (new Array(16 * 1024 * 1024)).join('x') + } + }); + + db.on('connected', function() { + test.save(function(error) { + assert.ok(error); + assert.equal(error.toString(), + 'MongoError: document is larger than the maximum size 16777216'); + db.close(done); + }); + }); }); describe('bug fixes', function() { var db; before(function() { - db = start(); + db = start({ noErrorListener: true }); }); after(function(done) { From 194e9bbb803460c24dbf125751fead458e26a3b2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 11:11:01 -0800 Subject: [PATCH 0357/2240] fix(drivers): catch and report any errors that occur in driver methods Fix #3906 --- lib/drivers/node-mongodb-native/collection.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js index 5fc73194b64..9bd78b5baeb 100644 --- a/lib/drivers/node-mongodb-native/collection.js +++ b/lib/drivers/node-mongodb-native/collection.js @@ -121,7 +121,18 @@ function iter(i) { } } - return collection[i].apply(collection, args); + try { + return collection[i].apply(collection, args); + } catch (error) { + // Collection operation may throw because of max bson size, catch it here + // See gh-3906 + if (args.length > 0 && + typeof args[args.length - 1] === 'function') { + args[args.length - 1](error); + } else { + throw error; + } + } }; } From b2e7aee2bea0b0d15054c3340ec808cdce4ea256 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 11:22:43 -0800 Subject: [PATCH 0358/2240] refactor(test): reuse connections for geo index tests --- test/model.test.js | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/test/model.test.js b/test/model.test.js index c69f1b84ab5..103a020f2c4 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -4816,8 +4816,17 @@ describe('Model', function() { }); describe('Skip setting default value for Geospatial-indexed fields (gh-1668)', function() { + var db; + + before(function() { + db = start({ noErrorListener: true }); + }); + + after(function(done) { + db.close(done); + }); + it('2dsphere indexed field with value is saved', function(done) { - var db = start(); var PersonSchema = new Schema({ name: String, loc: { @@ -4841,14 +4850,12 @@ describe('Model', function() { assert.equal(personDoc.loc[0], loc[0]); assert.equal(personDoc.loc[1], loc[1]); - db.close(); done(); }); }); }); it('2dsphere indexed field without value is saved (gh-1668)', function(done) { - var db = start(); var PersonSchema = new Schema({ name: String, loc: { @@ -4870,14 +4877,12 @@ describe('Model', function() { assert.equal(personDoc.name, 'Jimmy Page'); assert.equal(personDoc.loc, undefined); - db.close(); done(); }); }); }); it('2dsphere indexed field in subdoc without value is saved', function(done) { - var db = start(); var PersonSchema = new Schema({ name: {type: String, required: true}, nested: { @@ -4906,14 +4911,12 @@ describe('Model', function() { assert.equal(personDoc.name, 'Jimmy Page'); assert.equal(personDoc.nested.tag, 'guitarist'); assert.equal(personDoc.nested.loc, undefined); - db.close(); done(); }); }); }); it('Doc with 2dsphere indexed field without initial value can be updated', function(done) { - var db = start(); var PersonSchema = new Schema({ name: String, loc: { @@ -4941,14 +4944,12 @@ describe('Model', function() { assert.equal(personDoc.loc[0], updates.$set.loc[0]); assert.equal(personDoc.loc[1], updates.$set.loc[1]); - db.close(); done(); }); }); }); it('2dsphere indexed required field without value is rejected', function(done) { - var db = start(); var PersonSchema = new Schema({ name: String, loc: { @@ -4966,13 +4967,11 @@ describe('Model', function() { p.save(function(err) { assert.ok(err instanceof MongooseError); assert.ok(err instanceof ValidationError); - db.close(); done(); }); }); it('2dsphere field without value but with schema default is saved', function(done) { - var db = start(); var loc = [0, 1]; var PersonSchema = new Schema({ name: String, @@ -4996,14 +4995,12 @@ describe('Model', function() { assert.equal(loc[0], personDoc.loc[0]); assert.equal(loc[1], personDoc.loc[1]); - db.close(); done(); }); }); }); it('2d indexed field without value is saved', function(done) { - var db = start(); var PersonSchema = new Schema({ name: String, loc: { @@ -5024,14 +5021,12 @@ describe('Model', function() { assert.ifError(err); assert.equal(undefined, personDoc.loc); - db.close(); done(); }); }); }); it('Compound index with 2dsphere field without value is saved', function(done) { - var db = start(); var PersonSchema = new Schema({ name: String, type: String, @@ -5058,7 +5053,6 @@ describe('Model', function() { assert.equal('Jimmy Page', personDoc.name); assert.equal(undefined, personDoc.loc); - db.close(); done(); }); }); @@ -5066,7 +5060,6 @@ describe('Model', function() { it('Compound index on field earlier declared with 2dsphere index is saved', function(done) { - var db = start(); var PersonSchema = new Schema({ name: String, type: String, @@ -5094,7 +5087,6 @@ describe('Model', function() { assert.equal('Jimmy Page', personDoc.name); assert.equal(undefined, personDoc.loc); - db.close(); done(); }); }); From 7432da85c81f29b64a100144629b82649015a589 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 11:23:05 -0800 Subject: [PATCH 0359/2240] test(types): repro #3910 --- test/document.test.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 7b6a33d68ee..e1f42c9bbb7 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2450,6 +2450,40 @@ describe('document', function() { }); }); + it('single nested subdoc isModified() (gh-3910)', function(done) { + var called = 0; + + var ChildSchema = new Schema({ + name: String + }); + + ChildSchema.pre('save', function(next) { + assert.ok(this.isModified('name')); + ++called; + next(); + }); + + var ParentSchema = new Schema({ + name: String, + child: ChildSchema + }); + + var Parent = db.model('gh3910', ParentSchema); + + var p = new Parent({ + name: 'Darth Vader', + child: { + name: 'Luke Skywalker' + } + }); + + p.save(function(error) { + assert.ifError(error); + assert.strictEqual(called, 1); + done(); + }); + }); + it('pre and post as schema keys (gh-3902)', function(done) { var schema = new mongoose.Schema({ pre: String, From 0d7f54e3af2b75d1159127a9a6f8097be59ce639 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 11:23:26 -0800 Subject: [PATCH 0360/2240] fix(types): correct markModified() for single nested subdocs Fix #3910 --- lib/types/subdocument.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 56d14484033..ebe5b4cfd36 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -44,6 +44,7 @@ Subdocument.prototype.$isValid = function(path) { }; Subdocument.prototype.markModified = function(path) { + Document.prototype.markModified.call(this, path); if (this.$parent) { this.$parent.markModified([this.$basePath, path].join('.')); } From 2daf74be220dbc76a6ff41c36f77686f3e1a1165 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 12:20:36 -0800 Subject: [PATCH 0361/2240] docs: add validation acquit docs --- test/docs/validation.test.js | 329 +++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 test/docs/validation.test.js diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js new file mode 100644 index 00000000000..7130d0f349f --- /dev/null +++ b/test/docs/validation.test.js @@ -0,0 +1,329 @@ +var assert = require('assert'); +var mongoose = require('../../'); + +describe('validation docs', function() { + var db; + var Schema = mongoose.Schema; + + before(function() { + db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test'); + }); + + after(function(done) { + db.close(done); + }); + + /** + * Before we get into the specifics of validation syntax, please keep the following rules in mind: + * + * - Validation is defined in the [SchemaType](./schematypes.html) + * - Validation is [middleware](./middleware.html). Mongoose registers validation as a `pre('save')` hook on every schema by default. + * - You can manually run validation using `doc.validate(callback)` or `doc.validateSync()` + * - Validators are not run on undefined values. The only exception is the [`required` validator](./api.html#schematype_SchemaType-required). + * - Validation is asynchronously recursive; when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed as well. If an error occurs, your [Model#save](./api.html#model_Model-save) callback receives it + * - Validation is customizable + */ + + it('Validation', function(done) { + var schema = new Schema({ + name: { + type: String, + required: true + } + }); + var Cat = db.model('Cat', schema); + + // This cat has no name :( + var cat = new Cat(); + cat.save(function(error) { + assert.equal(error.errors['name'].message, + 'Path `name` is required.'); + + error = cat.validateSync(); + assert.equal(error.errors['name'].message, + 'Path `name` is required.'); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); + + /** + * Mongoose has several built-in validators. + * + * - All [SchemaTypes](./schematypes.html) have the built-in [required](./api.html#schematype_SchemaType-required) validator. The required validator uses the [SchemaType's `checkRequired()` function](./api.html#schematype_SchemaType-checkRequired) to determine if the value satisfies the required validator. + * - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. + * - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum), [match](./api.html#schema_string_SchemaString-match), [maxlength](./api.html#schema_string_SchemaString-maxlength) and [minlength](./api.html#schema_string_SchemaString-minlength) validators. + * + * Each of the validator links above provide more information about how to enable them and customize their error messages. + */ + + it('Built-in Validators', function(done) { + var breakfastSchema = new Schema({ + eggs: { + type: Number, + min: [6, 'Too few eggs'], + max: 12 + }, + bacon: { + type: Number, + required: [true, 'Why no bacon?'] + }, + drink: { + type: String, + enum: ['Coffee', 'Tea'] + } + }); + var Breakfast = db.model('Breakfast', breakfastSchema); + + var badBreakfast = new Breakfast({ + eggs: 2, + bacon: 0, + drink: 'Milk' + }); + var error = badBreakfast.validateSync(); + assert.equal(error.errors['eggs'].message, + 'Too few eggs'); + assert.ok(!error.errors['bacon']); + assert.equal(error.errors['drink'].message, + '`Milk` is not a valid enum value for path `drink`.'); + + badBreakfast.bacon = null; + error = badBreakfast.validateSync(); + assert.equal(error.errors['bacon'].message, 'Why no bacon?'); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + + /** + * If the built-in validators aren't enough, you can define custom validators + * to suit your needs. + * + * Custom validation is declared by passing a validation function. + * You can find detailed instructions on how to do this in the + * [`SchemaType#validate()` API docs](./api.html#schematype_SchemaType-validate). + */ + it('Custom Validators', function(done) { + var userSchema = new Schema({ + phone: { + type: String, + validate: { + validator: function(v) { + return /\d{3}-\d{3}-\d{4}/.test(v); + }, + message: '{VALUE} is not a valid phone number!' + }, + required: [true, 'User phone number required'] + } + }); + + var User = db.model('user', userSchema); + var user = new User(); + var error; + + user.phone = '555.0123'; + error = user.validateSync(); + assert.equal(error.errors['phone'].message, + '555.0123 is not a valid phone number!'); + + user.phone = ''; + error = user.validateSync(); + assert.equal(error.errors['phone'].message, + 'User phone number required'); + + user.phone = '201-555-0123'; + // Validation succeeds! Phone number is defined + // and fits `DDD-DDD-DDDD` + error = user.validateSync(); + assert.equal(error, null); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + + /** + * Errors returned after failed validation contain an `errors` object + * holding the actual `ValidatorError` objects. Each + * [ValidatorError](./api.html#error-validation-js) has `kind`, `path`, + * `value`, and `message` properties. + */ + + it('Validation Errors', function(done) { + var toySchema = new Schema({ + color: String, + name: String + }); + + var Toy = db.model('Toy', toySchema); + + var validator = function (value) { + return /blue|green|white|red|orange|periwinkle/i.test(value); + }; + Toy.schema.path('color').validate(validator, + 'Color `{VALUE}` not valid', 'Invalid color'); + + var toy = new Toy({ color: 'grease'}); + + toy.save(function (err) { + // err is our ValidationError object + // err.errors.color is a ValidatorError object + assert.equal(err.errors.color.message, 'Color `grease` not valid'); + assert.equal(err.errors.color.kind, 'Invalid color'); + assert.equal(err.errors.color.path, 'color'); + assert.equal(err.errors.color.value, 'grease'); + assert.equal(err.name, 'ValidationError'); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); + + /** + * In the above examples, you learned about document validation. Mongoose also + * supports validation for `update()` and `findOneAndUpdate()` operations. + * In Mongoose 4.x, update validators are off by default - you need to specify + * the `runValidators` option. + */ + describe('Update Validators', function() { + /** + * To turn on update validators, set the `runValidators` option for + * `update()` or `findOneAndUpdate()`. Be careful: update validators + * are off by default because they have several caveats. + */ + it('Basic Update Validators', function(done) { + var toySchema = new Schema({ + color: String, + name: String + }); + + var Toy = db.model('Toys', toySchema); + + Toy.schema.path('color').validate(function (value) { + return /blue|green|white|red|orange|periwinkle/i.test(value); + }, 'Invalid color'); + + var opts = { runValidators: true }; + Toy.update({}, { color: 'bacon' }, opts, function (err) { + assert.equal(err.errors.color.message, + 'Invalid color'); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); + + /** + * There are a couple of key differences between update validators and + * document validators. In the color validation function above, `this` refers + * to the document being validated when using document validation. + * However, when running update validators, the document being updated + * may not be in the server's memory, so by default the value of `this` is + * not defined. However, you can set the `context` option to 'query' to make + * `this` refer to the underlying query. + */ + + it('Update Validators and `this`', function(done) { + var toySchema = new Schema({ + color: String, + name: String + }); + + toySchema.path('color').validate(function(value) { + // When running in `validate()` or `validateSync()`, the + // validator can access the document using `this`. + // Does **not** work with update validators. + if (this.name.toLowerCase().indexOf('red') !== -1) { + return value !== 'red'; + } + return true; + }); + + var Toy = db.model('ActionFigure', toySchema); + + var toy = new Toy({ color: 'red', name: 'Red Power Ranger' }); + var error = toy.validateSync(); + assert.ok(error.errors['color']); + + var update = { color: 'red', name: 'Red Power Ranger' }; + var opts = { runValidators: true }; + + Toy.update({}, update, opts, function(error) { + // The update validator throws an error, because `this` + // is **not** the document in the validator when using + // update validators + assert.ok(error); + assert.equal(error.toString(), + "TypeError: Cannot read property 'toLowerCase' of undefined"); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); + + /** + * The other key difference that update validators only run on the paths + * specified in the update. For instance, in the below example, because + * 'name' is not specified in the update operation, update validation will + * succeed. + * + * When using update validators, `required` validators **only** fail when + * you try to explicitly `$unset` the key. + */ + + it('Update Validator Paths', function(done) { + // acquit:ignore:start + var outstanding = 2; + // acquit:ignore:end + var kittenSchema = new Schema({ + name: { type: String, required: true }, + age: Number + }); + + var Kitten = db.model('Kitten', kittenSchema); + + var update = { color: 'blue' }; + var opts = { runValidators: true }; + Kitten.update({}, update, opts, function(err) { + // Operation succeeds despite the fact that 'name' is not specified + // acquit:ignore:start + --outstanding || done(); + // acquit:ignore:end + }); + + var unset = { $unset: { name: 1 } }; + Kitten.update({}, unset, opts, function(err) { + // Operation fails because 'name' is required + assert.ok(err); + assert.ok(err.errors['name']); + // acquit:ignore:start + --outstanding || done(); + // acquit:ignore:end + }); + }); + + /** + * One final detail worth noting: update validators **only** run on `$set` + * and `$unset` operations. For instance, the below update will succeed, + * regardless of the value of `number`. + */ + + it('Update Validators Only Run On Specified Paths', function(done) { + var testSchema = new Schema({ + number: { type: Number, max: 0 }, + }); + + var Test = db.model('Test', testSchema); + + var update = { $inc: { number: 1 } }; + var opts = { runValidators: true }; + Test.update({}, update, opts, function(error) { + // There will never be a validation error here + // acquit:ignore:start + assert.ifError(error); + done(); + // acquit:ignore:end + }); + }); + }); +}); From b64178a16d9b0bde1376427511e69c3e2ef672ae Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 12:20:50 -0800 Subject: [PATCH 0362/2240] fix(query): dont crash on update validator errors --- lib/query.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/query.js b/lib/query.js index 0c75b2b31cb..37cafb12e32 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1818,14 +1818,20 @@ Query.prototype._findAndModify = function(type, callback) { }; if ((opts.runValidators || opts.setDefaultsOnInsert) && doValidate) { - doValidate(function(error) { + var _callback = function(error) { if (error) { return callback(error); } _this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) { return cb(error, res ? res.value : res, res); })); - }); + }; + + try { + doValidate(_callback); + } catch (error) { + callback(error); + } } else { this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) { return cb(error, res ? res.value : res, res); @@ -1902,13 +1908,20 @@ Query.prototype._execUpdate = function(callback) { if (this.options.runValidators || this.options.setDefaultsOnInsert) { _this = this; doValidate = updateValidators(this, schema, castedDoc, options); - doValidate(function(err) { + var _callback = function(err) { if (err) { return callback(err); } Query.base.update.call(_this, castedQuery, castedDoc, options, callback); - }); + }; + try { + doValidate(_callback); + } catch (err) { + process.nextTick(function() { + callback(err); + }); + } return this; } From 0e8f734b3752263c44d54a478e8ba30257859428 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Mar 2016 12:22:01 -0800 Subject: [PATCH 0363/2240] docs: use acquitified validation docs re: #3392 --- docs/source/acquit.js | 5 + docs/validation.jade | 217 ------------------------------------------ 2 files changed, 5 insertions(+), 217 deletions(-) delete mode 100644 docs/validation.jade diff --git a/docs/source/acquit.js b/docs/source/acquit.js index 060a7d2df42..b94212d1037 100644 --- a/docs/source/acquit.js +++ b/docs/source/acquit.js @@ -24,6 +24,11 @@ var files = [ input: 'test/docs/schematypes.test.js', output: 'customschematypes.html', title: 'Custom Schema Types' + }, + { + input: 'test/docs/validation.test.js', + output: 'validation.html', + title: 'Validation' } ]; diff --git a/docs/validation.jade b/docs/validation.jade deleted file mode 100644 index 3c8f677476a..00000000000 --- a/docs/validation.jade +++ /dev/null @@ -1,217 +0,0 @@ -extends layout - -block content - h2 Validation - :markdown - Before we get into the specifics of validation syntax, please keep the following rules in mind: - - - Validation is defined in the [SchemaType](./schematypes.html) - - Validation is an internal piece of [middleware](./middleware.html) - - Validation occurs when a document attempts to be [saved](./api.html#model_Model-save), after defaults have been applied - - Validators are not run on undefined values. The only exception is the [`required` validator](./api.html#schematype_SchemaType-required). - - Validation is asynchronously recursive; when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed as well. If an error occurs, your [Model#save](./api.html#model_Model-save) callback receives it - - Validation supports complete customization - - h3#built-in-validators Built in validators - :markdown - Mongoose has several built in validators. - - - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. The required validator uses the [SchemaType's `checkRequired()` function](./api.html#schematype_SchemaType-checkRequired) to determine if the value satisfies the required validator. - - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. - - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum), [match](./api.html#schema_string_SchemaString-match), [maxlength](./api.html#schema_string_SchemaString-maxlength) and [minlength](./api.html#schema_string_SchemaString-minlength) validators. - - Each of the validator links above provide more information about how to enable them as well as customize their associated error messages. - h3#customized Custom validators - :markdown - If the built-in validators aren't enough, validation can be completely tailored to suit your needs. - - Custom validation is declared by passing a validation function. - You can find detailed instructions on how to do this in the - [`SchemaType#validate()` API docs](./api.html#schematype_SchemaType-validate). - - :js - var userSchema = new Schema({ - phone: { - type: String, - validate: { - validator: function(v) { - return /\d{3}-\d{3}-\d{4}/.test(v); - }, - message: '{VALUE} is not a valid phone number!' - }, - required: [true, 'User phone number required'] - } - }); - - var User = mongoose.model('user', userSchema); - - var u = new User(); - - u.phone = '555.0123'; - // Prints "ValidationError: 555.0123 is not a valid phone number!" - console.log(u.validateSync().toString()); - - u.phone = ''; - // Prints "ValidationError: User phone number required" - console.log(u.validateSync().toString()); - - u.phone = '201-555-0123'; - // Prints undefined - validation succeeded! - console.log(u.validateSync()); - h3#validation-errors Validation errors - :markdown - Errors returned after failed validation contain an `errors` object - holding the actual `ValidatorError` objects. Each - [ValidatorError](./api.html#error-validation-js) has `kind`, `path`, - `value`, and `message` properties. - :js - var toySchema = new Schema({ - color: String, - name: String - }); - - var Toy = mongoose.model('Toy', toySchema); - - Toy.schema.path('color').validate(function (value) { - return /blue|green|white|red|orange|periwinkle/i.test(value); - }, 'Invalid color'); - - var toy = new Toy({ color: 'grease'}); - - toy.save(function (err) { - // err is our ValidationError object - // err.errors.color is a ValidatorError object - - console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color with value `grease`' - console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color with value `grease`' - console.log(err.errors.color.kind) // prints "Invalid color" - console.log(err.errors.color.path) // prints "color" - console.log(err.errors.color.value) // prints "grease" - console.log(err.name) // prints "ValidationError" - console.log(err.message) // prints "Validation failed" - }); - - :markdown - After a validation error, the document will also have the same `errors` property available: - :js - toy.errors.color.message === err.errors.color.message - - h3#validate-sync Synchronous Validation - :markdown - Validation is asynchronous by default. Mongoose evaluates each individual - path in a separate `process.nextTick()` call, which helps make sure - validation doesn't block the event loop if there are a lot of paths to - validate. However, mongoose's built-in validators are all synchronous, and - it's often more convenient to validate synchronously. - - Mongoose documents also have a `validateSync()` function, which returns - a `ValidationError` if there was an error, or falsy if there was no error. - Note that `validateSync()` **only** executes synchronous validators. - Custom asynchronous validators won't execute. - - :js - var toySchema = new Schema({ - color: String, - name: String - }); - - var Toy = mongoose.model('Toy', toySchema); - - Toy.schema.path('color').validate(function (value) { - return /blue|green|white|red|orange|periwinkle/i.test(value); - }, 'Invalid color'); - - var toy = new Toy({ color: 'grease'}); - - // `error` is a ValidationError analogous to the one from `validate()` - var error = toy.validateSync(); - - // prints 'Validator "Invalid color" failed for path color with value `grease`' - console.log(error.errors.color.message); - - h3#update-validators Update Validators - :markdown - In the above examples, you learned about document validation. Mongoose also - supports validation for `update()` and `findOneAndUpdate()` operations. - In Mongoose 4.x, update validators are off by default - you need to specify - the `runValidators` option. - :js - var toySchema = new Schema({ - color: String, - name: String - }); - - var Toy = mongoose.model('Toy', toySchema); - - Toy.schema.path('color').validate(function (value) { - return /blue|green|white|red|orange|periwinkle/i.test(value); - }, 'Invalid color'); - - Toy.update({}, { color: 'bacon' }, { runValidators: true }, function (err) { - console.log(err.errors.color.message); // prints 'Validator "Invalid color" failed for path color with value `bacon`' - }); - :markdown - There are a couple of key differences between update validators and - document validators. In the color validation function above, `this` refers - to the document being validated when using document validation. - However, when running update validators, the document being updated - may not be in the server's memory, so by default the value of `this` is - not defined. However, you can set the `context` option to 'query' to make - `this` refer to the underlying query. - - :js - Toy.schema.path('color').validate(function (value) { - this.schema; // refers to the query's schema if you set the `context` option - return /blue|green|white|red|orange|periwinkle/i.test(value); - }, 'Invalid color'); - - var options = { runValidators: true, context: 'query' }; - Toy.update({}, { color: 'bacon' }, options, function (err) { - console.log(err.errors.color.message); // prints 'Validator "Invalid color" failed for path color with value `bacon`' - }); - - :markdown - The other key difference that update validators only run on the paths - specified in the update. For instance, in the below example, because - 'name' is not specified in the update operation, update validation will - succeed. - - :js - var toySchema = new Schema({ - color: String, - name: { type: String, required: true } - }); - - var Toy = mongoose.model('Toy', toySchema); - - Toy.update({}, { color: 'blue' }, { runValidators: true }, function(err) { - // Operation succeeds despite the fact that 'name' is not specified - }); - - :markdown - When using update validators, `required` validators **only** fail when - you try to explicitly `$unset` the key. - :js - var unsetOp = { $unset: { name: 1 } }; - Toy.update({}, unsetOp, { runValidators: true }, function(err) { - // Operation fails because 'name' is required - }); - - :markdown - One final detail worth noting: update validators **only** run on `$set` - and `$unset` operations. For instance, the below update will succeed, - regardless of the value of `number`. - :js - var testSchema = new Schema({ - number: { type: Number, max: 0 }, - }); - - var Test = mongoose.model('Test', testSchema); - - Test.update({}, { $inc: { number: 1 } }, { runValidators: true }, function (err) { - // There will never be a validation error here - }); - - h3#next Next Up - :markdown - Now that we've covered `validation`, let's take a look at how you might handle advanced validation with Mongoose's [middleware](/docs/middleware.html). From 4e1b35627a56903746b0e1f8ffb8f32214fba2e9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 11 Mar 2016 06:59:17 -0800 Subject: [PATCH 0364/2240] docs: clarify index.html example re #3966 --- index.jade | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/index.jade b/index.jade index 8d88146ee68..56142852d66 100644 --- a/index.jade +++ b/index.jade @@ -50,8 +50,11 @@ html(lang='en') var kitty = new Cat({ name: 'Zildjian' }); kitty.save(function (err) { - if (err) // ... - console.log('meow'); + if (err) { + console.log(err); + } else { + console.log('meow'); + } }); p.what Mongoose provides a straight-forward, schema-based solution to model your application data. It includes built-in type casting, validation, query building, business logic hooks and more, out of the box. #getstarted From 157b0f0f0a71d6f98a6a3033a13c9cf68b012ba3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 11 Mar 2016 07:37:47 -0800 Subject: [PATCH 0365/2240] test(populate): repro #3954 --- test/model.populate.test.js | 72 ++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 65f2c9ee8be..bafa7c3980c 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3318,7 +3318,7 @@ describe('model: populate:', function() { }; var spurs = { name: 'Spurs', - members: [people[1]._id, people[2]._id, people[3]._id] + members: [people[3]._id, people[4]._id, people[5]._id] }; var teams = [lakers, spurs]; Team.create(teams, function(error, teams) { @@ -3347,5 +3347,75 @@ describe('model: populate:', function() { }); } }); + + it('deep populate array -> array (gh-3954)', function(done) { + var personSchema = new Schema({ + name: { type: String } + }); + + var teamSchema = new Schema({ + name: { type: String }, + members: [{ type: Schema.Types.ObjectId, ref: 'gh3954' }] + }); + + var gameSchema = new Schema({ + teams: [{ type: Schema.Types.ObjectId, ref: 'gh3954_0' }] + }); + + var Person = db.model('gh3954', personSchema); + var Team = db.model('gh3954_0', teamSchema); + var Game = db.model('gh3954_1', gameSchema); + + var people = [ + { name: 'Shaq' }, + { name: 'Kobe' }, + { name: 'Horry' }, + { name: 'Duncan' }, + { name: 'Robinson' }, + { name: 'Johnson' } + ]; + + Person.create(people, function(error, people) { + assert.ifError(error); + var lakers = { + name: 'Lakers', + members: [people[0]._id, people[1]._id, people[2]._id] + }; + var spurs = { + name: 'Spurs', + members: [people[3]._id, people[4]._id, people[5]._id] + }; + var teams = [lakers, spurs]; + Team.create(teams, function(error, teams) { + assert.ifError(error); + var game = { + teams: [teams[0]._id, teams[1]._id] + }; + Game.create(game, function(error, game) { + assert.ifError(error); + test(game._id); + }); + }); + }); + + function test(id) { + var query = Game.findById(id).populate({ + path: 'teams', + select: 'name members', + populate: { path: 'members', select: 'name' } + }); + query.exec(function(error, doc) { + assert.ifError(error); + var players = doc.toObject().teams[0].members. + concat(doc.toObject().teams[1].members); + var arr = _.map(players, function(v) { + return v.name; + }); + assert.deepEqual(arr, + ['Shaq', 'Kobe', 'Horry', 'Duncan', 'Robinson', 'Johnson']); + done(); + }); + } + }); }); }); From ab494ea4747af14c8fe99d0368d9ce021b07d7bc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 11 Mar 2016 07:38:19 -0800 Subject: [PATCH 0366/2240] fix(populate): handle deep populate array -> array Fix #3954 --- lib/model.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/model.js b/lib/model.js index 786be9328bc..30b0efb71a9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2540,6 +2540,9 @@ function subPopulate(docs, options, cb) { _getSchema(subOptions._originalPath); if (subSchema && subSchema.options && subSchema.options.ref) { subOptions.model = _this.model(subSchema.options.ref); + } else if (subSchema && subSchema.caster && subSchema.caster.options && + subSchema.caster.options.ref) { + subOptions.model = _this.model(subSchema.caster.options.ref); } } else if (schema && schema.options && schema.options.ref) { subSchema = _this.model(schema.options.ref).schema. From 8c40404dc670229e1d0c98f6bea148099b82e6fe Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 11 Mar 2016 07:50:14 -0800 Subject: [PATCH 0367/2240] refactor(test): reuse connection for model.update tests --- test/model.update.test.js | 234 ++++++++++++++++++-------------------- 1 file changed, 110 insertions(+), 124 deletions(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 0a6882b4411..5a41ff2b4d1 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1554,18 +1554,7 @@ describe('model: update:', function() { }); }); - it('can $rename (gh-1845)', function(done) { - var db = start(); - var schema = new Schema({foo: Date, bar: Date}); - var Model = db.model('gh1845', schema, 'gh1845'); - - Model.update({}, {$rename: {foo: 'bar'}}, function(error) { - assert.ifError(error); - db.close(done); - }); - }); - - describe('deep casting', function() { + describe('bug fixes', function() { var db; before(function() { @@ -1576,6 +1565,16 @@ describe('model: update:', function() { db.close(done); }); + it('can $rename (gh-1845)', function(done) { + var schema = new Schema({foo: Date, bar: Date}); + var Model = db.model('gh1845', schema, 'gh1845'); + + Model.update({}, {$rename: {foo: 'bar'}}, function(error) { + assert.ifError(error); + done(); + }); + }); + it('allows objects with positional operator (gh-3185)', function(done) { var schema = new Schema({children: [{_id: Number}]}); var MyModel = db.model('gh3185', schema, 'gh3185'); @@ -1660,158 +1659,145 @@ describe('model: update:', function() { }); }); }); - }); - it('works with buffers (gh-3496)', function(done) { - var db = start(); - - var Schema = mongoose.Schema({myBufferField: Buffer}); - var Model = db.model('gh3496', Schema); + it('works with buffers (gh-3496)', function(done) { + var Schema = mongoose.Schema({myBufferField: Buffer}); + var Model = db.model('gh3496', Schema); - Model.update({}, {myBufferField: new Buffer(1)}, function(error) { - assert.ifError(error); - db.close(done); + Model.update({}, {myBufferField: new Buffer(1)}, function(error) { + assert.ifError(error); + done(); + }); }); - }); - it('dontThrowCastError option (gh-3512)', function(done) { - var db = start(); - - var Schema = mongoose.Schema({name: String}); - var Model = db.model('gh3412', Schema); + it('dontThrowCastError option (gh-3512)', function(done) { + var Schema = mongoose.Schema({name: String}); + var Model = db.model('gh3412', Schema); - var badQuery = {_id: 'foo'}; - var update = {name: 'test'}; - var options = {dontThrowCastError: true}; - Model.update(badQuery, update, options).then(null, function(error) { - assert.ok(error); - db.close(done); + var badQuery = {_id: 'foo'}; + var update = {name: 'test'}; + var options = {dontThrowCastError: true}; + Model.update(badQuery, update, options).then(null, function(error) { + assert.ok(error); + done(); + }); }); - }); - - it('.update(doc) (gh-3221)', function(done) { - var db = start(); - var Schema = mongoose.Schema({name: String}); - var Model = db.model('gh3412', Schema); + it('.update(doc) (gh-3221)', function(done) { + var Schema = mongoose.Schema({name: String}); + var Model = db.model('gh3221', Schema); - var query = Model.update({name: 'Val'}); - assert.equal(query.getUpdate().$set.name, 'Val'); + var query = Model.update({name: 'Val'}); + assert.equal(query.getUpdate().$set.name, 'Val'); - query = Model.find().update({name: 'Val'}); - assert.equal(query.getUpdate().$set.name, 'Val'); + query = Model.find().update({name: 'Val'}); + assert.equal(query.getUpdate().$set.name, 'Val'); - db.close(done); - }); + done(); + }); - it('nested schemas with strict false (gh-3883)', function(done) { - var db = start(); - var OrderSchema = new mongoose.Schema({ - }, { strict: false, _id: false }); + it('nested schemas with strict false (gh-3883)', function(done) { + var OrderSchema = new mongoose.Schema({ + }, { strict: false, _id: false }); - var SeasonSchema = new mongoose.Schema({ - regions: [OrderSchema] - }, { useNestedStrict: true }); + var SeasonSchema = new mongoose.Schema({ + regions: [OrderSchema] + }, { useNestedStrict: true }); - var Season = db.model('gh3883', SeasonSchema); - var obj = { regions: [{ r: 'test', action: { order: 'hold' } }] }; - Season.create(obj, function(error) { - assert.ifError(error); - var query = { 'regions.r': 'test' }; - var update = { $set: { 'regions.$.action': { order: 'move' } } }; - var opts = { 'new': true }; - Season.findOneAndUpdate(query, update, opts, function(error, doc) { + var Season = db.model('gh3883', SeasonSchema); + var obj = { regions: [{ r: 'test', action: { order: 'hold' } }] }; + Season.create(obj, function(error) { assert.ifError(error); - assert.equal(doc.toObject().regions[0].action.order, 'move'); - done(); + var query = { 'regions.r': 'test' }; + var update = { $set: { 'regions.$.action': { order: 'move' } } }; + var opts = { 'new': true }; + Season.findOneAndUpdate(query, update, opts, function(error, doc) { + assert.ifError(error); + assert.equal(doc.toObject().regions[0].action.order, 'move'); + done(); + }); }); }); - }); - - it('middleware update with exec (gh-3549)', function(done) { - var db = start(); - var Schema = mongoose.Schema({name: String}); + it('middleware update with exec (gh-3549)', function(done) { + var Schema = mongoose.Schema({name: String}); - Schema.pre('update', function(next) { - this.update({name: 'Val'}); - next(); - }); + Schema.pre('update', function(next) { + this.update({name: 'Val'}); + next(); + }); - var Model = db.model('gh3549', Schema); + var Model = db.model('gh3549', Schema); - Model.create({}, function(error, doc) { - assert.ifError(error); - Model.update({_id: doc._id}, {name: 'test'}).exec(function(error) { + Model.create({}, function(error, doc) { assert.ifError(error); - Model.findOne({_id: doc._id}, function(error, doc) { + Model.update({_id: doc._id}, {name: 'test'}).exec(function(error) { assert.ifError(error); - assert.equal(doc.name, 'Val'); - db.close(done); + Model.findOne({_id: doc._id}, function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Val'); + done(); + }); }); }); }); - }); - - it('casting $push with overwrite (gh-3564)', function(done) { - var db = start(); - var schema = mongoose.Schema({ - topicId: Number, - name: String, - followers: [Number] - }); + it('casting $push with overwrite (gh-3564)', function(done) { + var schema = mongoose.Schema({ + topicId: Number, + name: String, + followers: [Number] + }); - var doc = { - topicId: 100, - name: 'name', - followers: [500] - }; + var doc = { + topicId: 100, + name: 'name', + followers: [500] + }; - var M = db.model('gh-3564', schema); + var M = db.model('gh-3564', schema); - M.create(doc, function(err) { - assert.ifError(err); + M.create(doc, function(err) { + assert.ifError(err); - var update = {$push: {followers: 200}}; - var opts = {overwrite: true, new: true, safe: true, upsert: false, multi: false}; + var update = {$push: {followers: 200}}; + var opts = {overwrite: true, new: true, safe: true, upsert: false, multi: false}; - M.update({topicId: doc.topicId}, update, opts, function(err) { - assert.ifError(err); - M.findOne({topicId: doc.topicId}, function(error, doc) { - assert.ifError(error); - assert.equal(doc.name, 'name'); - assert.deepEqual(doc.followers.toObject(), [500, 200]); - db.close(done); + M.update({topicId: doc.topicId}, update, opts, function(err) { + assert.ifError(err); + M.findOne({topicId: doc.topicId}, function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'name'); + assert.deepEqual(doc.followers.toObject(), [500, 200]); + done(); + }); }); }); }); - }); - it('$push with buffer doesnt throw error (gh-3890)', function(done) { - var db = start(); - - var InfoSchema = new Schema({ - prop: { type: Buffer } - }); + it('$push with buffer doesnt throw error (gh-3890)', function(done) { + var InfoSchema = new Schema({ + prop: { type: Buffer } + }); - var ModelASchema = new Schema({ - infoList: { type: [InfoSchema] } - }); + var ModelASchema = new Schema({ + infoList: { type: [InfoSchema] } + }); - var ModelA = db.model('gh3890', ModelASchema); + var ModelA = db.model('gh3890', ModelASchema); - var propValue = new Buffer('aa267824dc1796f265ab47870e279780', 'base64'); + var propValue = new Buffer('aa267824dc1796f265ab47870e279780', 'base64'); - var update = { - $push: { - info_list: { prop: propValue } - } - }; + var update = { + $push: { + info_list: { prop: propValue } + } + }; - ModelA.update({}, update, function(error) { - assert.ifError(error); - db.close(done); + ModelA.update({}, update, function(error) { + assert.ifError(error); + done(); + }); }); }); }); From 241876ca517e7cf48f7560fc3f712fea4e493357 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 11 Mar 2016 08:10:11 -0800 Subject: [PATCH 0368/2240] test(query): repro #3961 --- test/model.test.js | 1 - test/model.update.test.js | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/test/model.test.js b/test/model.test.js index 103a020f2c4..ac735de97b3 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -1,4 +1,3 @@ -Error.stackTraceLimit = Infinity; /** * Test dependencies. */ diff --git a/test/model.update.test.js b/test/model.update.test.js index 5a41ff2b4d1..def89d18d73 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1799,5 +1799,26 @@ describe('model: update:', function() { done(); }); }); + + it('$set with buffer (gh-3961)', function(done) { + var schema = { + name: Buffer + }; + + var Model = db.model('gh3961', schema); + + var value = new Buffer('aa267824dc1796f265ab47870e279780', 'base64'); + var instance = new Model({ name: null }); + + instance.save(function(error) { + assert.ifError(error); + var query = { _id: instance._id }; + var update = { $set: { name: value } }; + var ok = function() { + done(); + }; + Model.update(query, update).then(ok, done); + }); + }); }); }); From 6e2e43d8c71d0080c3e48682751dbc6ed7d29147 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 11 Mar 2016 08:10:18 -0800 Subject: [PATCH 0369/2240] fix(query): stop infinite recursion caused by merging a mongoose buffer Fix #3961 --- lib/utils.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index be40d12c9ee..bb544743f95 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -799,12 +799,12 @@ exports.decorate = function(destination, source) { * merges to with a copy of from * * @param {Object} to - * @param {Object} from + * @param {Object} fromObj * @api private */ -exports.mergeClone = function(to, from) { - var keys = Object.keys(from), +exports.mergeClone = function(to, fromObj) { + var keys = Object.keys(fromObj), i = keys.length, key; @@ -813,18 +813,18 @@ exports.mergeClone = function(to, from) { if (typeof to[key] === 'undefined') { // make sure to retain key order here because of a bug handling the $each // operator in mongodb 2.4.4 - to[key] = exports.clone(from[key], {retainKeyOrder: 1}); + to[key] = exports.clone(fromObj[key], {retainKeyOrder: 1}); } else { - if (exports.isObject(from[key])) { - var obj = from[key]; - if (isMongooseObject(from[key])) { + if (exports.isObject(fromObj[key])) { + var obj = fromObj[key]; + if (isMongooseObject(fromObj[key]) && !fromObj[key].isMongooseBuffer) { obj = obj.toObject({ virtuals: false }); } exports.mergeClone(to[key], obj); } else { // make sure to retain key order here because of a bug handling the // $each operator in mongodb 2.4.4 - to[key] = exports.clone(from[key], {retainKeyOrder: 1}); + to[key] = exports.clone(fromObj[key], {retainKeyOrder: 1}); } } } From 995f3d87c1403775e30601d27e029bbac811b6bc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 11 Mar 2016 08:16:58 -0800 Subject: [PATCH 0370/2240] test(validation): dont assert on error message thats different on node 0.10 --- test/docs/validation.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 7130d0f349f..8f7b6e6f4eb 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -249,13 +249,13 @@ describe('validation docs', function() { var opts = { runValidators: true }; Toy.update({}, update, opts, function(error) { - // The update validator throws an error, because `this` - // is **not** the document in the validator when using + // The update validator throws an error: + // "TypeError: Cannot read property 'toLowerCase' of undefined", + // because `this` is **not** the document being updated when using // update validators assert.ok(error); - assert.equal(error.toString(), - "TypeError: Cannot read property 'toLowerCase' of undefined"); // acquit:ignore:start + assert.ok(error.toString().indexOf('TypeError: Cannot read') !== -1); done(); // acquit:ignore:end }); From b7bfe44874b2953ec87a266adf5ab006e1da11eb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 11 Mar 2016 08:20:55 -0800 Subject: [PATCH 0371/2240] test(docs): remove error message assert thats failing on 0.10 --- test/docs/validation.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 8f7b6e6f4eb..7650a784af6 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -255,7 +255,6 @@ describe('validation docs', function() { // update validators assert.ok(error); // acquit:ignore:start - assert.ok(error.toString().indexOf('TypeError: Cannot read') !== -1); done(); // acquit:ignore:end }); From d23f6101872595ed231065b5fdcf3f3b3689dab1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 11 Mar 2016 15:54:50 -0800 Subject: [PATCH 0372/2240] chore: release 4.4.7 --- History.md | 15 +++++ bin/mongoose.js | 144 ++++++++++++++++++++++++++++-------------------- package.json | 2 +- 3 files changed, 100 insertions(+), 61 deletions(-) diff --git a/History.md b/History.md index a3c9cf05919..f6b179b828f 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,18 @@ +4.4.7 / 2016-03-11 +================== + * fix(query): stop infinite recursion caused by merging a mongoose buffer #3961 + * fix(populate): handle deep populate array -> array #3954 + * fix(schema): allow setting timestamps with .set() #3952 #3951 #3907 [Fonger](https://github.com/Fonger) + * fix: MongooseThenable doesn't overwrite constructors #3940 + * fix(schema): don't cast boolean to date #3935 + * fix(drivers): support sslValidate in connection string #3929 + * fix(types): correct markModified() for single nested subdocs #3910 + * fix(drivers): catch and report any errors that occur in driver methods #3906 + * fix(populate): get subpopulate model correctly when array under nested #3904 + * fix(document): allow fields named 'pre' and 'post' #3902 + * docs(query): clarify runValidators and setDefaultsOnInsert options #3892 + * docs(validation): show how to use custom required messages in schema #2616 + 4.4.6 / 2016-03-02 ================== * fix: upgrade mongodb driver to 2.1.7 #3938 diff --git a/bin/mongoose.js b/bin/mongoose.js index ca8c05d9023..e06cfab3737 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -837,7 +837,11 @@ Document.prototype.$__storeShard = function() { */ for (var k in hooks) { - Document.prototype[k] = Document[k] = hooks[k]; + if (k === 'pre' || k === 'post') { + Document.prototype['$' + k] = Document['$' + k] = hooks[k]; + } else { + Document.prototype[k] = Document[k] = hooks[k]; + } } /** @@ -2209,12 +2213,12 @@ Document.prototype.$__registerHooksFromSchema = function() { if (toWrap.init && _this instanceof Embedded) { if (toWrap.init.pre) { toWrap.init.pre.forEach(function(args) { - _this.pre.apply(_this, args); + _this.$pre.apply(_this, args); }); } if (toWrap.init.post) { toWrap.init.post.forEach(function(args) { - _this.post.apply(_this, args); + _this.$post.apply(_this, args); }); } delete toWrap.init; @@ -2222,12 +2226,12 @@ Document.prototype.$__registerHooksFromSchema = function() { // Set hooks also need to be sync re: gh-3479 if (toWrap.set.pre) { toWrap.set.pre.forEach(function(args) { - _this.pre.apply(_this, args); + _this.$pre.apply(_this, args); }); } if (toWrap.set.post) { toWrap.set.post.forEach(function(args) { - _this.post.apply(_this, args); + _this.$post.apply(_this, args); }); } delete toWrap.set; @@ -2269,11 +2273,11 @@ Document.prototype.$__registerHooksFromSchema = function() { toWrap[pointCut].pre.forEach(function(args) { args[0] = newName; - _this.pre.apply(_this, args); + _this.$pre.apply(_this, args); }); toWrap[pointCut].post.forEach(function(args) { args[0] = newName; - _this.post.apply(_this, args); + _this.$post.apply(_this, args); }); }); return _this; @@ -3952,51 +3956,8 @@ function Schema(obj, options) { this[m.kind](m.hook, !!m.isAsync, m.fn); } - // adds updatedAt and createdAt timestamps to documents if enabled - var timestamps = this.options.timestamps; - if (timestamps) { - var createdAt = timestamps.createdAt || 'createdAt', - updatedAt = timestamps.updatedAt || 'updatedAt', - schemaAdditions = {}; - - schemaAdditions[updatedAt] = Date; - - if (!this.paths[createdAt]) { - schemaAdditions[createdAt] = Date; - } - - this.add(schemaAdditions); - - this.pre('save', function(next) { - var defaultTimestamp = new Date(); - - if (!this[createdAt]) { - this[createdAt] = auto_id ? this._id.getTimestamp() : defaultTimestamp; - } - - this[updatedAt] = this.isNew ? this[createdAt] : defaultTimestamp; - - next(); - }); - - var genUpdates = function() { - var now = new Date(); - var updates = {$set: {}, $setOnInsert: {}}; - updates.$set[updatedAt] = now; - updates.$setOnInsert[createdAt] = now; - - return updates; - }; - - this.pre('findOneAndUpdate', function(next) { - this.findOneAndUpdate({}, genUpdates()); - next(); - }); - - this.pre('update', function(next) { - this.update({}, genUpdates()); - next(); - }); + if (this.options.timestamps) { + this.setupTimestamp(this.options.timestamps); } } @@ -4555,6 +4516,60 @@ Schema.prototype.hasMixedParent = function(path) { return false; }; +/** + * Setup updatedAt and createdAt timestamps to documents if enabled + * + * @param {Boolean|Object} timestamps timestamps options + * @api private + */ +Schema.prototype.setupTimestamp = function(timestamps) { + if (timestamps) { + var createdAt = timestamps.createdAt || 'createdAt', + updatedAt = timestamps.updatedAt || 'updatedAt', + schemaAdditions = {}; + + schemaAdditions[updatedAt] = Date; + + if (!this.paths[createdAt]) { + schemaAdditions[createdAt] = Date; + } + + this.add(schemaAdditions); + + this.pre('save', function(next) { + var defaultTimestamp = new Date(); + var auto_id = this._id && this._id.auto; + + if (!this[createdAt]) { + this[createdAt] = auto_id ? this._id.getTimestamp() : defaultTimestamp; + } + + this[updatedAt] = this.isNew ? this[createdAt] : defaultTimestamp; + + next(); + }); + + var genUpdates = function() { + var now = new Date(); + var updates = {$set: {}, $setOnInsert: {}}; + updates.$set[updatedAt] = now; + updates.$setOnInsert[createdAt] = now; + + return updates; + }; + + this.pre('findOneAndUpdate', function(next) { + this.findOneAndUpdate({}, genUpdates()); + next(); + }); + + this.pre('update', function(next) { + this.update({}, genUpdates()); + next(); + }); + } +}; + /*! * ignore */ @@ -4858,6 +4873,10 @@ Schema.prototype.set = function(key, value, _tags) { ? {w: 0} : value; break; + case 'timestamps': + this.setupTimestamp(value); + this.options[key] = value; + break; default: this.options[key] = value; } @@ -6136,6 +6155,10 @@ SchemaDate.prototype.cast = function(value) { var date; + if (typeof value === 'boolean') { + throw new CastError('date', value, this.path); + } + if (value instanceof Number || typeof value === 'number' || String(value) == Number(value)) { // support for timestamps @@ -10592,6 +10615,7 @@ Subdocument.prototype.$isValid = function(path) { }; Subdocument.prototype.markModified = function(path) { + Document.prototype.markModified.call(this, path); if (this.$parent) { this.$parent.markModified([this.$basePath, path].join('.')); } @@ -11473,12 +11497,12 @@ exports.decorate = function(destination, source) { * merges to with a copy of from * * @param {Object} to - * @param {Object} from + * @param {Object} fromObj * @api private */ -exports.mergeClone = function(to, from) { - var keys = Object.keys(from), +exports.mergeClone = function(to, fromObj) { + var keys = Object.keys(fromObj), i = keys.length, key; @@ -11487,18 +11511,18 @@ exports.mergeClone = function(to, from) { if (typeof to[key] === 'undefined') { // make sure to retain key order here because of a bug handling the $each // operator in mongodb 2.4.4 - to[key] = exports.clone(from[key], {retainKeyOrder: 1}); + to[key] = exports.clone(fromObj[key], {retainKeyOrder: 1}); } else { - if (exports.isObject(from[key])) { - var obj = from[key]; - if (isMongooseObject(from[key])) { + if (exports.isObject(fromObj[key])) { + var obj = fromObj[key]; + if (isMongooseObject(fromObj[key]) && !fromObj[key].isMongooseBuffer) { obj = obj.toObject({ virtuals: false }); } exports.mergeClone(to[key], obj); } else { // make sure to retain key order here because of a bug handling the // $each operator in mongodb 2.4.4 - to[key] = exports.clone(from[key], {retainKeyOrder: 1}); + to[key] = exports.clone(fromObj[key], {retainKeyOrder: 1}); } } } diff --git a/package.json b/package.json index b109a6a79c2..b415e89e2e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.7-pre", + "version": "4.4.7", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From cc2aa59436f31de2d8d374b941e6241d9482eec6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Mar 2016 11:18:04 -0800 Subject: [PATCH 0373/2240] chore: now working on 4.4.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b415e89e2e8..f8ba8f5fd9d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.7", + "version": "4.4.8-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 84958af18eb2b686a7423e5c700769e208ec3a06 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Mar 2016 11:30:31 -0800 Subject: [PATCH 0374/2240] fix(error): make ValidatorError.properties not enumerable Fix #3925 --- lib/error/validator.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/error/validator.js b/lib/error/validator.js index 959073bc86e..59e26ecb46c 100644 --- a/lib/error/validator.js +++ b/lib/error/validator.js @@ -19,7 +19,6 @@ function ValidatorError(properties) { msg = errorMessages.general.default; } - this.properties = properties; var message = this.formatMessage(msg, properties); MongooseError.call(this, message); if (Error.captureStackTrace) { @@ -27,6 +26,7 @@ function ValidatorError(properties) { } else { this.stack = new Error().stack; } + this.properties = properties; this.name = 'ValidatorError'; this.kind = properties.type; this.path = properties.path; @@ -40,6 +40,17 @@ function ValidatorError(properties) { ValidatorError.prototype = Object.create(MongooseError.prototype); ValidatorError.prototype.constructor = MongooseError; +/*! + * The object used to define this validator. Not enumerable to hide + * it from `require('util').inspect()` output re: gh-3925 + */ + +Object.defineProperty(ValidatorError.prototype, 'properties', { + enumerable: false, + writable: true, + value: null +}); + /*! * Formats error messages */ From 86fadaad3a9dd89950cfd2532d87a1eb084cac6c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Mar 2016 12:35:28 -0800 Subject: [PATCH 0375/2240] docs(query): fields option for findOneAndUpdate #3933 --- lib/query.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/query.js b/lib/query.js index 37cafb12e32..1ef025df5b6 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1527,6 +1527,7 @@ function prepareDiscriminatorCriteria(query) { * * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0) * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. + * - `fields`: {Object|String} - Field selection. Equivalent to `.select(fields).findOneAndUpdate()` * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). From 65e744b9fa7066495ab965b7be3c53c51ca2b00b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Mar 2016 12:35:45 -0800 Subject: [PATCH 0376/2240] docs(model): fields option for findOneAndUpdate #3933 --- lib/model.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index 30b0efb71a9..f2b9beb4ed1 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1394,10 +1394,11 @@ Model.$where = function $where() { * * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0) * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. + * - `fields`: {Object|String} - Field selection. Equivalent to `.select(fields).findOneAndUpdate()` + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). - * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update - * - `select`: sets the document fields to return + * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) * * * ####Examples: From a9f01f8b9a5e67e00c92df1ef12345c7ca6ff9b6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Mar 2016 13:20:19 -0800 Subject: [PATCH 0377/2240] test(populate): add skipped test for #3937 --- lib/query.js | 2 +- test/model.populate.test.js | 67 +++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 1ef025df5b6..ed35d0f130a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1527,7 +1527,7 @@ function prepareDiscriminatorCriteria(query) { * * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0) * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. - * - `fields`: {Object|String} - Field selection. Equivalent to `.select(fields).findOneAndUpdate()` + * - `fields`: {Object|String} - Field selection. Equivalent to `.select(fields).findOneAndUpdate()` * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). diff --git a/test/model.populate.test.js b/test/model.populate.test.js index bafa7c3980c..f3d28d21c52 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3417,5 +3417,72 @@ describe('model: populate:', function() { }); } }); + + it('does not assign null under array (gh-3937)', function(done) { + this.skip(); + var personSchema = new mongoose.Schema({ + name: String + }); + + var saleSchema = new mongoose.Schema({ + amount: Number, + person: { + type: mongoose.Schema.Types.ObjectId, + ref: 'gh3937' + } + }); + + var companySchema = new mongoose.Schema({ + name: String, + description: String, + sales: [saleSchema] + }); + + var Person = db.model('gh3937', personSchema); + var Company = db.model('gh3937_0', companySchema); + var Sale = db.model('gh3937_1', saleSchema); + + var acmeCorp = new Company({ + name: 'ACME Corp' + }); + var person1 = new Person({ + name: 'John' + }); + var person2 = new Person({ + name: 'Phantom InMemory' + }); + var sale1 = new Sale({ + amount: 100, + person: person1 + }); + var sale2 = new Sale({ + amount: 200, + person: person2.id + }); + + acmeCorp.sales = [sale1, sale2]; + + Company.create(acmeCorp, function(error, company) { + assert.ifError(error); + Sale.create([sale1, sale2], function(error) { + assert.ifError(error); + Person.create(person1, function(error) { + assert.ifError(error); + test(company._id); + }); + }); + }); + + function test(id) { + var path = 'sales.person'; + Company.findById(id).populate(path).exec(function(error, company) { + assert.ifError(error); + assert.strictEqual(company.sales[1].person, undefined); + assert.deepEqual(Object.keys(company.toObject().sales[1]), + ['_id', 'amount']); + done(); + }); + } + }); }); }); From 70cf0284e76a08fa3c14ab4e5ce634ba99039feb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Mar 2016 13:32:45 -0800 Subject: [PATCH 0378/2240] docs(connection): clarify object and connection string options #3941 --- docs/connections.jade | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index d744203dc4b..52d4c46cee2 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -29,9 +29,9 @@ block content :markdown The following option keys are available: - db - passed to the connection db instance - server - passed to the connection server instance(s) - replset - passed to the connection ReplSet instance + db - passed to the [underlying driver's db instance](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) + server - passed to the [underlying driver's server instance(s)](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + replset - passed to the [underlying driver's ReplSet instance](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) user - username for authentication (if not specified in uri) pass - password for authentication (if not specified in uri) auth - options for authentication @@ -53,6 +53,28 @@ block content See the [driver](https://github.com/mongodb/node-mongodb-native) for more information about available options. + h4#connection-string-options Connection String Options + :markdown + Mongoose supports the following options in the connection string. + + * [ssl](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + * [poolSize](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + * [autoReconnect](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + * [socketTimeoutMS](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + * [connectTimeoutMS](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + * [authSource](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) + * [retries](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + * [reconnectWait](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + * [rs_name](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) + * [replicaSet](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) + * [nativeParser](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) + * [w](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) + * [journal](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) + * [wtimeoutMS](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) + * [readPreference](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) + * [readPreferenceTags](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) + * [sslValidate](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + h4#keepAlive A note about keepAlive .important :markdown From 0ca4fbc601b60e20a8a75cdc6cde8f55d0eee801 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 13 Mar 2016 15:44:56 -0700 Subject: [PATCH 0379/2240] docs(validation): clarify how required validators work with nested schemas Fix #3915 --- test/docs/validation.test.js | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 7650a784af6..1a569014444 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -179,6 +179,47 @@ describe('validation docs', function() { }); }); + /** + * Defining validators on nested objects in mongoose is tricky, because + * nested objects are not fully fledged paths. + */ + + it('Required Validators On Nested Objects', function(done) { + var personSchema = new Schema({ + name: { + first: String, + last: String + } + }); + + assert.throws(function() { + // This throws an error, because 'name' isn't a full fledged path + personSchema.path('name').required(true); + }, /Cannot read property 'required'/); + + // To make a nested object required, use a single nested schema + var nameSchema = new Schema({ + first: String, + last: String + }); + + personSchema = new Schema({ + name: { + type: nameSchema, + required: true + } + }); + + var Person = db.model('Person', personSchema); + + var person = new Person(); + var error = person.validateSync(); + assert.ok(error.errors['name']); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + /** * In the above examples, you learned about document validation. Mongoose also * supports validation for `update()` and `findOneAndUpdate()` operations. From 3a20f4bed31b94ecd8742412fd8d0a19c7744c81 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 14 Mar 2016 11:06:10 -0700 Subject: [PATCH 0380/2240] test: repro #3964 --- test/document.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/document.test.js b/test/document.test.js index e1f42c9bbb7..5c89f3bfe22 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -1314,7 +1314,8 @@ describe('document', function() { Post = db.model('InvalidateSchema'); post = new Post(); post.set({baz: 'val'}); - post.invalidate('baz', 'validation failed for path {PATH}'); + var _err = post.invalidate('baz', 'validation failed for path {PATH}'); + assert.ok(_err instanceof ValidationError); post.save(function(err) { assert.ok(err instanceof MongooseError); From bc73af50b4f9b24a71911e6c897eda3228d27e47 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 14 Mar 2016 11:06:15 -0700 Subject: [PATCH 0381/2240] feat(document): return validation error from invalidate() Fix #3964 --- lib/document.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index d754b39e318..16d7f4fdbdd 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1320,6 +1320,7 @@ Document.prototype.validateSync = function(pathsToValidate) { * @param {String} path the field to invalidate * @param {String|Error} errorMsg the error which states the reason `path` was invalid * @param {Object|String|Number|any} value optional invalid value + * @return {ValidationError} the current ValidationError, with all currently invalidated paths * @api public */ @@ -1342,10 +1343,11 @@ Document.prototype.invalidate = function(path, err, val) { } if (this.$__.validationError === err) { - return; + return this.$__.validationError; } this.$__.validationError.errors[path] = err; + return this.$__.validationError; }; /** From cf3b00d6e98dc204b30c068d1ea2d18a1873297c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 14 Mar 2016 11:07:06 -0700 Subject: [PATCH 0382/2240] test(populate): remove unused test re #3937 --- test/model.populate.test.js | 67 ------------------------------------- 1 file changed, 67 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index f3d28d21c52..bafa7c3980c 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3417,72 +3417,5 @@ describe('model: populate:', function() { }); } }); - - it('does not assign null under array (gh-3937)', function(done) { - this.skip(); - var personSchema = new mongoose.Schema({ - name: String - }); - - var saleSchema = new mongoose.Schema({ - amount: Number, - person: { - type: mongoose.Schema.Types.ObjectId, - ref: 'gh3937' - } - }); - - var companySchema = new mongoose.Schema({ - name: String, - description: String, - sales: [saleSchema] - }); - - var Person = db.model('gh3937', personSchema); - var Company = db.model('gh3937_0', companySchema); - var Sale = db.model('gh3937_1', saleSchema); - - var acmeCorp = new Company({ - name: 'ACME Corp' - }); - var person1 = new Person({ - name: 'John' - }); - var person2 = new Person({ - name: 'Phantom InMemory' - }); - var sale1 = new Sale({ - amount: 100, - person: person1 - }); - var sale2 = new Sale({ - amount: 200, - person: person2.id - }); - - acmeCorp.sales = [sale1, sale2]; - - Company.create(acmeCorp, function(error, company) { - assert.ifError(error); - Sale.create([sale1, sale2], function(error) { - assert.ifError(error); - Person.create(person1, function(error) { - assert.ifError(error); - test(company._id); - }); - }); - }); - - function test(id) { - var path = 'sales.person'; - Company.findById(id).populate(path).exec(function(error, company) { - assert.ifError(error); - assert.strictEqual(company.sales[1].person, undefined); - assert.deepEqual(Object.keys(company.toObject().sales[1]), - ['_id', 'amount']); - done(); - }); - } - }); }); }); From 3e757ff05f2a7bf21c3b6905f0a57dc2b0240f82 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 15 Mar 2016 06:26:17 -0700 Subject: [PATCH 0383/2240] fix(drivers): upgrade to mongodb 2.1.8 for #3864 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f8ba8f5fd9d..2d2ab5a39c4 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "0.4.21", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.1.7", + "mongodb": "2.1.8", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.8.0", From 6d0b58e77fee1d4152abce62f641bb4b8889e180 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 15 Mar 2016 07:42:12 -0700 Subject: [PATCH 0384/2240] feat(query): upgrade mquery -> 1.9.0 for #3980 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d2ab5a39c4..5ed1e08854f 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.1.8", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "1.8.0", + "mquery": "1.9.0", "ms": "0.7.1", "muri": "1.1.0", "regexp-clone": "0.0.1", From 3709d1bc62d4ce78aeb722f8d1f3362d8b199ae7 Mon Sep 17 00:00:00 2001 From: Xu Zhipei Date: Mon, 14 Mar 2016 22:29:14 +0800 Subject: [PATCH 0385/2240] Add 'all' event --- lib/connection.js | 3 ++- lib/drivers/node-mongodb-native/connection.js | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index 84cc68add35..f1274aa06df 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -45,7 +45,8 @@ var authMechanismsWhichDontRequirePassword = [ * @event `close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models. * @event `reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection. * @event `error`: Emitted when an error occurs on this connection. - * @event `fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected. + * @event `fullsetup`: Emitted in a replica-set scenario, when primary and at least one seconaries specified in the connection string are connected. + * @event `all`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected. * @api public */ diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 6ad3e51f974..ea278079508 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -197,6 +197,10 @@ NativeConnection.prototype.doOpenSet = function(fn) { _this.emit('fullsetup'); }); + this.db.on('all', function() { + _this.emit('all'); + }); + this.db.open(function(err) { if (err) return fn(err); fn(); From 384d545f2c678ed0271fbe20d0f3c99e1abea836 Mon Sep 17 00:00:00 2001 From: Manuel Ernst Date: Wed, 16 Mar 2016 08:07:36 +0100 Subject: [PATCH 0386/2240] DOC: add remark about MoongooseArray.pull(...) It took me a while to figure out why my pull operations resulted in actual `$set` operations until I figured out that this is only the case when more then one `pull`s are happening. --- lib/types/array.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/types/array.js b/lib/types/array.js index 5bb07f2e8bb..2a8122df5fb 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -506,6 +506,8 @@ MongooseArray.mixin = { * doc.subdocs.push({ _id: 4815162342 }) * doc.subdocs.pull(4815162342); // works * + * The first pull call will result in a atomic operation on the database, if pull is called repeatedly without saving the document, a $set operation is used on the complete array instead, overwriting possible changes that happend on the database in the meantime. + * * @param {any} [args...] * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull * @api public From 2c102b939297c172e37e9ed6e86aaad3e1a61cf4 Mon Sep 17 00:00:00 2001 From: Manuel Ernst Date: Wed, 16 Mar 2016 08:56:49 +0100 Subject: [PATCH 0387/2240] remove trailing space --- lib/types/array.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/array.js b/lib/types/array.js index 2a8122df5fb..d5d413c71b2 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -507,7 +507,7 @@ MongooseArray.mixin = { * doc.subdocs.pull(4815162342); // works * * The first pull call will result in a atomic operation on the database, if pull is called repeatedly without saving the document, a $set operation is used on the complete array instead, overwriting possible changes that happend on the database in the meantime. - * + * * @param {any} [args...] * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull * @api public From af77f2b13930e4e6ad0976998444ed8d2e5a845a Mon Sep 17 00:00:00 2001 From: Oleg Matskiv Date: Wed, 16 Mar 2016 17:09:52 +0100 Subject: [PATCH 0388/2240] Update mquery to 1.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ed1e08854f..3f62f7559bf 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.1.8", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "1.9.0", + "mquery": "1.10.0", "ms": "0.7.1", "muri": "1.1.0", "regexp-clone": "0.0.1", From 03a6009b77954c0a120b6116e7742ed993318265 Mon Sep 17 00:00:00 2001 From: apimenov Date: Wed, 16 Mar 2016 19:24:34 +0300 Subject: [PATCH 0389/2240] Incorrect doc, see #3958. --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index f2b9beb4ed1..9a70b4edcfd 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2210,7 +2210,7 @@ Model.geoNear = function(near, options, callback) { /** * Performs [aggregations](http://docs.mongodb.org/manual/applications/aggregation/) on the models collection. * - * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned. + * If a `callback` is passed, the `aggregate` is executed. If a callback is not passed, the `aggregate` itself is returned. * * ####Example: * From 85c85fb8e993ce96d36ac59908eb5689ea3db24f Mon Sep 17 00:00:00 2001 From: apimenov Date: Wed, 16 Mar 2016 19:31:50 +0300 Subject: [PATCH 0390/2240] Revert "Incorrect doc, see #3958." This reverts commit 03a6009b77954c0a120b6116e7742ed993318265. --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 9a70b4edcfd..f2b9beb4ed1 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2210,7 +2210,7 @@ Model.geoNear = function(near, options, callback) { /** * Performs [aggregations](http://docs.mongodb.org/manual/applications/aggregation/) on the models collection. * - * If a `callback` is passed, the `aggregate` is executed. If a callback is not passed, the `aggregate` itself is returned. + * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned. * * ####Example: * From aaf9301820d1a539694e58724b228c70135121b0 Mon Sep 17 00:00:00 2001 From: apimenov Date: Wed, 16 Mar 2016 19:33:13 +0300 Subject: [PATCH 0391/2240] Incorrect doc, see #3946. --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index f2b9beb4ed1..9a70b4edcfd 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2210,7 +2210,7 @@ Model.geoNear = function(near, options, callback) { /** * Performs [aggregations](http://docs.mongodb.org/manual/applications/aggregation/) on the models collection. * - * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned. + * If a `callback` is passed, the `aggregate` is executed. If a callback is not passed, the `aggregate` itself is returned. * * ####Example: * From 8926d611c3a7ab907d1656752571185241d4de3c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 16 Mar 2016 19:19:36 -0400 Subject: [PATCH 0392/2240] Docs: small typo --- lib/types/array.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/array.js b/lib/types/array.js index d5d413c71b2..11f6a4f95f0 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -506,7 +506,7 @@ MongooseArray.mixin = { * doc.subdocs.push({ _id: 4815162342 }) * doc.subdocs.pull(4815162342); // works * - * The first pull call will result in a atomic operation on the database, if pull is called repeatedly without saving the document, a $set operation is used on the complete array instead, overwriting possible changes that happend on the database in the meantime. + * The first pull call will result in a atomic operation on the database, if pull is called repeatedly without saving the document, a $set operation is used on the complete array instead, overwriting possible changes that happened on the database in the meantime. * * @param {any} [args...] * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull From 1a99bea60abe79a1196e7d1ae110a066f69abb10 Mon Sep 17 00:00:00 2001 From: Oleg Matskiv Date: Wed, 16 Mar 2016 17:12:08 +0100 Subject: [PATCH 0393/2240] Update mquery to 1.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1e0a63a9c49..a650448bb1d 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ , "mpromise": "0.4.3" , "mpath": "0.1.1" , "regexp-clone": "0.0.1" - , "mquery" : "1.6.1" + , "mquery" : "1.10.0" } , "devDependencies": { "mocha": "1.12.0" From 7ba05d8377fd4a9a966fa1424b71af3f5e88f6b8 Mon Sep 17 00:00:00 2001 From: apimenov Date: Thu, 17 Mar 2016 16:03:59 +0300 Subject: [PATCH 0394/2240] Hack for backward compatibility, see #3946 --- lib/aggregate.js | 2 +- lib/model.js | 5 +++-- test/model.aggregate.test.js | 13 +++++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index fd2c2fcf71b..522728d8144 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -547,7 +547,7 @@ Aggregate.prototype.exec = function(callback) { if (callback) { callback(null, result); } - resolve(result); + resolve(null,result); }); }); }; diff --git a/lib/model.js b/lib/model.js index 9a70b4edcfd..aa834654251 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2210,7 +2210,7 @@ Model.geoNear = function(near, options, callback) { /** * Performs [aggregations](http://docs.mongodb.org/manual/applications/aggregation/) on the models collection. * - * If a `callback` is passed, the `aggregate` is executed. If a callback is not passed, the `aggregate` itself is returned. + * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned. * * ####Example: * @@ -2263,7 +2263,8 @@ Model.aggregate = function aggregate() { aggregate.model(this); - if (typeof callback === 'undefined') { + //TODO find proper way to check that we will need call done() + if (typeof callback === 'undefined' && arguments.callee.caller.toString().indexOf(").then") == -1) { return aggregate; } diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js index 6c3b3343803..36debea1f9e 100644 --- a/test/model.aggregate.test.js +++ b/test/model.aggregate.test.js @@ -73,6 +73,19 @@ describe('model aggregate', function() { }); }); + it('should return promise', function(done) { + this.timeout(4000); + + A.aggregate(group, project).then( function(err, res) { + assert.ifError(err); + assert.ok(res); + assert.equal(1, res.length); + assert.ok('maxAge' in res[0]); + assert.equal(maxAge, res[0].maxAge); + done(); + }); + }); + it('with arrays', function(done) { this.timeout(4000); From 637fc610b41198b50afb72b20bfe3223595cbceb Mon Sep 17 00:00:00 2001 From: apimenov Date: Thu, 17 Mar 2016 16:34:01 +0300 Subject: [PATCH 0395/2240] Correct args order passing to resolve #3946 . --- lib/aggregate.js | 2 +- test/model.aggregate.test.js | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 522728d8144..fd2c2fcf71b 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -547,7 +547,7 @@ Aggregate.prototype.exec = function(callback) { if (callback) { callback(null, result); } - resolve(null,result); + resolve(result); }); }); }; diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js index 36debea1f9e..8dba2a8cd99 100644 --- a/test/model.aggregate.test.js +++ b/test/model.aggregate.test.js @@ -73,11 +73,10 @@ describe('model aggregate', function() { }); }); - it('should return promise', function(done) { + it('when return promise', function(done) { this.timeout(4000); - A.aggregate(group, project).then( function(err, res) { - assert.ifError(err); + A.aggregate(group, project).then( function(res) { assert.ok(res); assert.equal(1, res.length); assert.ok('maxAge' in res[0]); From 18bdab64cd99d447f7067852809998d2d4cbf4b7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 17 Mar 2016 07:40:13 -0700 Subject: [PATCH 0396/2240] docs(connection): add note re reconnectTries and reconnectInterval Fix #3969 --- docs/connections.jade | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/connections.jade b/docs/connections.jade index 52d4c46cee2..5437b129b32 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -52,6 +52,14 @@ block content The db option `forceServerObjectId` is set to false which _cannot_ be overridden. See the [driver](https://github.com/mongodb/node-mongodb-native) for more information about available options. + :markdown + **Note:** + If `auto_reconnect` is on, mongoose will give up trying to reconnect after a certain number of failures. Set the [`server.reconnectTries` and `server.reconnectInterval` options](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) to increase the number of times mongoose will try to reconnect. + :js + // Good way to make sure mongoose never stops trying to reconnect + mongoose.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } }); + + h4#connection-string-options Connection String Options :markdown From 12d3b5350d8bae38c41fa4148dff4781dbf36986 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 17 Mar 2016 09:09:34 -0700 Subject: [PATCH 0397/2240] docs(query): clarify tailable options re: #2922 --- lib/query.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/query.js b/lib/query.js index ed35d0f130a..078e9eab4c2 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2782,6 +2782,9 @@ Query.prototype.maxscan = Query.base.maxScan; * Cannot be used with `distinct()` * * @param {Boolean} bool defaults to true + * @param {Object} [opts] options to set + * @param {Number} [opts.numberOfRetries] if cursor is exhausted, retry this many times before giving up + * @param {Number} [opts.tailableRetryInterval] if cursor is exhausted, wait this many milliseconds before retrying * @see tailable http://docs.mongodb.org/manual/tutorial/create-tailable-cursor/ * @api public */ From 1441e6a77cc76df9c5154f54dd88af0e5d930bd5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 18 Mar 2016 05:25:09 -0700 Subject: [PATCH 0398/2240] fix: copy connection over to MongooseThenable Fix #3972 --- lib/index.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/index.js b/lib/index.js index 9ebebf147f5..eacc88f898d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -473,6 +473,10 @@ Mongoose.prototype.__defineGetter__('connection', function() { return this.connections[0]; }); +Mongoose.prototype.__defineSetter__('connection', function(v) { + this.connections[0] = v; +}); + /*! * Driver depentend APIs */ @@ -731,6 +735,8 @@ function MongooseThenable(mongoose, promise) { return mongoose[key].apply(mongoose, arguments); }; })(key); + } else if (['connection', 'connections'].indexOf(key) !== -1) { + _this[key] = mongoose[key]; } } this.$opPromise = promise; From 3630b7cc51e202af2d316b9549133d6a7e465360 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 18 Mar 2016 05:55:41 -0700 Subject: [PATCH 0399/2240] test(populate): repro #3973 --- test/model.populate.test.js | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index bafa7c3980c..0394a25c559 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3417,5 +3417,63 @@ describe('model: populate:', function() { }); } }); + + it('4 level population (gh-3973)', function(done) { + var level4Schema = new Schema({ + name: { type: String } + }); + + var level3Schema = new Schema({ + name: { type: String }, + level4: [{ type: Schema.Types.ObjectId, ref: 'level_4' }] + }); + + var level2Schema = new Schema({ + name: { type: String }, + level3: [{ type: Schema.Types.ObjectId, ref: 'level_3' }] + }); + + var level1Schema = new Schema({ + name: { type: String }, + level2: [{ type: Schema.Types.ObjectId, ref: 'level_2' }] + }); + + var level4 = db.model('level_4', level4Schema); + var level3 = db.model('level_3', level3Schema); + var level2 = db.model('level_2', level2Schema); + var level1 = db.model('level_1', level1Schema); + + var l4docs = [{ name: 'level 4' }]; + + level4.create(l4docs, function(error, l4) { + assert.ifError(error); + var l3docs = [{ name: 'level 3', level4: l4[0]._id }]; + level3.create(l3docs, function(error, l3) { + assert.ifError(error); + var l2docs = [{ name: 'level 2', level3: l3[0]._id }]; + level2.create(l2docs, function(error, l2) { + assert.ifError(error); + var l1docs = [{ name: 'level 1', level2: l2[0]._id }]; + level1.create(l1docs, function(error, l1) { + assert.ifError(error); + var opts = { + path: 'level2', + populate: { + path: 'level3', + populate: { + path: 'level4' + } + } + }; + level1.findById(l1[0]._id).populate(opts).exec(function(error, obj) { + assert.ifError(error); + assert.equal(obj.level2[0].level3[0].level4[0].name, 'level 4'); + done(); + }); + }); + }); + }); + }); + }); }); }); From dad9d3898c07dae654fd68db0776551e0fba0c00 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 18 Mar 2016 05:56:05 -0700 Subject: [PATCH 0400/2240] fix(populate): cache schemas for paths between subPopulate calls Fix #3973 --- lib/model.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/model.js b/lib/model.js index 9a70b4edcfd..bd15001caaf 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2431,12 +2431,15 @@ Model.populate = function(docs, paths, cb) { var noPromise = paths && !!paths.__noPromise; paths = utils.populate(paths); + // data that should persist across subPopulate calls + var cache = {}; + if (noPromise) { - _populate(this, docs, paths, cb); + _populate(this, docs, paths, cache, cb); } else { var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { - _populate(_this, docs, paths, function(error, docs) { + _populate(_this, docs, paths, cache, function(error, docs) { if (error) { cb && cb(error); reject(error); @@ -2460,7 +2463,7 @@ Model.populate = function(docs, paths, cb) { * @api private */ -function _populate(model, docs, paths, cb) { +function _populate(model, docs, paths, cache, cb) { var pending = paths.length; if (pending === 0) { @@ -2475,7 +2478,7 @@ function _populate(model, docs, paths, cb) { if (typeof path.model === 'function') { model = path.model; } - populate(model, docs, path, subPopulate.call(model, docs, path, next)); + populate(model, docs, path, subPopulate.call(model, docs, path, cache, next)); } function next(err) { @@ -2498,7 +2501,7 @@ function _populate(model, docs, paths, cb) { * @return {Function} * @api private */ -function subPopulate(docs, options, cb) { +function subPopulate(docs, options, cache, cb) { var _this = this; var prefix = options.path + '.'; var pop = options.populate; @@ -2531,7 +2534,8 @@ function subPopulate(docs, options, cb) { subOptions.path = prefix + subOptions.path; } - var schema = _this.schema._getSchema(prefix); + var schema = cache[prefix.substr(0, prefix.length - 1)] || + _this.schema._getSchema(prefix); var subSchema; if (typeof subOptions.model === 'string') { subOptions.model = _this.model(subOptions.model); @@ -2539,6 +2543,7 @@ function subPopulate(docs, options, cb) { schema.caster.options.ref) { subSchema = _this.model(schema.caster.options.ref).schema. _getSchema(subOptions._originalPath); + cache[subOptions.path] = subSchema; if (subSchema && subSchema.options && subSchema.options.ref) { subOptions.model = _this.model(subSchema.options.ref); } else if (subSchema && subSchema.caster && subSchema.caster.options && @@ -2555,7 +2560,8 @@ function subPopulate(docs, options, cb) { subOptions.model = _this.model(subSchema.caster.options.ref); } } - Model.populate.call(subOptions.model || _this, docs, subOptions, next); + _populate(subOptions.model || _this, docs, utils.populate(subOptions), + cache, next); }); }; } From 23b1325c166565388d3cd56013b149a10fcf2b41 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 18 Mar 2016 06:11:39 -0700 Subject: [PATCH 0401/2240] fix(test): make regexp more flexible for node 0.10 --- test/docs/validation.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 1a569014444..3716d3d7224 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -195,7 +195,7 @@ describe('validation docs', function() { assert.throws(function() { // This throws an error, because 'name' isn't a full fledged path personSchema.path('name').required(true); - }, /Cannot read property 'required'/); + }, /Cannot.*'required'/); // To make a nested object required, use a single nested schema var nameSchema = new Schema({ From 55858cf8d1220822794b6dd8fef5a82b38064cda Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 18 Mar 2016 06:30:35 -0700 Subject: [PATCH 0402/2240] chore: release 4.4.8 --- History.md | 18 ++ bin/mongoose.js | 822 ++++++++++++++++++++---------------------------- package.json | 2 +- 3 files changed, 360 insertions(+), 482 deletions(-) diff --git a/History.md b/History.md index f6b179b828f..dd062086204 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,21 @@ +4.4.8 / 2016-03-18 +================== + * docs(aggregate): clarify promises #3990 [megagon](https://github.com/megagon) + * fix: upgrade mquery -> 1.10 #3988 [matskiv](https://github.com/matskiv) + * feat(connection): 'all' event for repl sets #3986 [xizhibei](https://github.com/xizhibei) + * docs(types): clarify Array.pull #3985 [seriousManual](https://github.com/seriousManual) + * feat(query): support array syntax for .sort() via mquery 1.9 #3980 + * fix(populate): support > 3 level nested populate #3973 + * fix: MongooseThenable exposes connection correctly #3972 + * docs(connection): add note about reconnectTries and reconnectInterval #3969 + * feat(document): invalidate returns the new validationError #3964 + * fix(query): .eq() as shorthand for .equals #3953 [Fonger](https://github.com/Fonger) + * docs(connection): clarify connection string vs passed options #3941 + * docs(query): select option for findOneAndUpdate #3933 + * fix(error): ValidationError.properties no longer enumerable #3925 + * docs(validation): clarify how required validators work with nested schemas #3915 + * fix: upgrade mongodb driver -> 2.1.8 to make partial index errors more sane #3864 + 4.4.7 / 2016-03-11 ================== * fix(query): stop infinite recursion caused by merging a mongoose buffer #3961 diff --git a/bin/mongoose.js b/bin/mongoose.js index e06cfab3737..395b1a0628e 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -1764,6 +1764,7 @@ Document.prototype.validateSync = function(pathsToValidate) { * @param {String} path the field to invalidate * @param {String|Error} errorMsg the error which states the reason `path` was invalid * @param {Object|String|Number|any} value optional invalid value + * @return {ValidationError} the current ValidationError, with all currently invalidated paths * @api public */ @@ -1786,10 +1787,11 @@ Document.prototype.invalidate = function(path, err, val) { } if (this.$__.validationError === err) { - return; + return this.$__.validationError; } this.$__.validationError.errors[path] = err; + return this.$__.validationError; }; /** @@ -3369,7 +3371,6 @@ function ValidatorError(properties) { msg = errorMessages.general.default; } - this.properties = properties; var message = this.formatMessage(msg, properties); MongooseError.call(this, message); if (Error.captureStackTrace) { @@ -3377,6 +3378,7 @@ function ValidatorError(properties) { } else { this.stack = new Error().stack; } + this.properties = properties; this.name = 'ValidatorError'; this.kind = properties.type; this.path = properties.path; @@ -3390,6 +3392,17 @@ function ValidatorError(properties) { ValidatorError.prototype = Object.create(MongooseError.prototype); ValidatorError.prototype.constructor = MongooseError; +/*! + * The object used to define this validator. Not enumerable to hide + * it from `require('util').inspect()` output re: gh-3925 + */ + +Object.defineProperty(ValidatorError.prototype, 'properties', { + enumerable: false, + writable: true, + value: null +}); + /*! * Formats error messages */ @@ -9408,6 +9421,8 @@ MongooseArray.mixin = { * doc.subdocs.push({ _id: 4815162342 }) * doc.subdocs.pull(4815162342); // works * + * The first pull call will result in a atomic operation on the database, if pull is called repeatedly without saving the document, a $set operation is used on the complete array instead, overwriting possible changes that happened on the database in the meantime. + * * @param {any} [args...] * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull * @api public @@ -22135,6 +22150,34 @@ Query.prototype.equals = function equals (val) { return this; } +/** + * Specifies the complementary comparison value for paths specified with `where()` + * This is alias of `equals` + * + * ####Example + * + * User.where('age').eq(49); + * + * // is the same as + * + * User.shere('age').equals(49); + * + * // is the same as + * + * User.where('age', 49); + * + * @param {Object} val + * @return {Query} this + * @api public + */ + +Query.prototype.eq = function eq (val) { + this._ensurePath('eq'); + var path = this._path; + this._conditions[path] = val; + return this; +} + /** * Specifies arguments for an `$or` condition. * @@ -23004,27 +23047,40 @@ Query.prototype.slice = function () { * // these are equivalent * query.sort({ field: 'asc', test: -1 }); * query.sort('field -test'); + * query.sort([['field', 1], ['test', -1]]); * * ####Note * - * Cannot be used with `distinct()` + * - The array syntax `.sort([['field', 1], ['test', -1]])` can only be used with [mongodb driver >= 2.0.46](https://github.com/mongodb/node-mongodb-native/blob/2.1/HISTORY.md#2046-2015-10-15). + * - Cannot be used with `distinct()` * - * @param {Object|String} arg + * @param {Object|String|Array} arg * @return {Query} this * @api public */ Query.prototype.sort = function (arg) { if (!arg) return this; + var len; this._validate('sort'); var type = typeof arg; + // .sort([['field', 1], ['test', -1]]) + if (Array.isArray(arg)) { + len = arg.length; + for (var i = 0; i < arg.length; ++i) { + _pushArr(this.options, arg[i][0], arg[i][1]); + } + return this; + } + + // .sort('field -test') if (1 === arguments.length && 'string' == type) { arg = arg.split(/\s+/); - - for (var i = 0, len = arg.length; i < len; ++i) { + len = arg.length; + for (var i = 0; i < len; ++i) { var field = arg[i]; if (!field) continue; var ascend = '-' == field[0] ? -1 : 1; @@ -23035,6 +23091,7 @@ Query.prototype.sort = function (arg) { return this; } + // .sort({ field: 1, test: -1 }) if (utils.isObject(arg)) { var keys = utils.keys(arg); for (var i = 0; i < keys.length; ++i) { @@ -23045,7 +23102,7 @@ Query.prototype.sort = function (arg) { return this; } - throw new TypeError('Invalid sort() argument. Must be a string or object.'); + throw new TypeError('Invalid sort() argument. Must be a string, object, or array.'); } /*! @@ -23053,6 +23110,12 @@ Query.prototype.sort = function (arg) { */ function push (opts, field, value) { + if (Array.isArray(opts.sort)) { + throw new TypeError("Can't mix sort syntaxes. Use either array or object:" + + "\n- `.sort([['field', 1], ['test', -1]])`" + + "\n- `.sort({ field: 1, test: -1 })`"); + } + if (value && value.$meta) { var s = opts.sort || (opts.sort = {}); s[field] = { $meta : value.$meta }; @@ -23074,6 +23137,21 @@ function push (opts, field, value) { s[field] = parseInt(valueStr, 10); } +function _pushArr (opts, field, value) { + opts.sort = opts.sort || []; + if (!Array.isArray(opts.sort)) { + throw new TypeError("Can't mix sort syntaxes. Use either array or object:" + + "\n- `.sort([['field', 1], ['test', -1]])`" + + "\n- `.sort({ field: 1, test: -1 })`"); + } + var valueStr = value.toString() + .replace("asc", "1") + .replace("ascending", "1") + .replace("desc", "-1") + .replace("descending", "-1"); + opts.sort.push([field, value]); +} + /** * Specifies the limit option. * @@ -24930,14 +25008,14 @@ exports.isArgumentsObject = function(v) { /* @preserve * The MIT License (MIT) * - * Copyright (c) 2014 Petka Antonov + * Copyright (c) 2013-2015 Petka Antonov * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions:

+ * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. @@ -24952,7 +25030,7 @@ exports.isArgumentsObject = function(v) { * */ /** - * bluebird build version 2.9.26 + * bluebird build version 2.10.2 * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, cancel, using, filter, any, each, timers */ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o 10) || (version[0] > 0) - ? function(fn) { global.setImmediate(fn); } : process.nextTick; - - if (!schedule) { - if (typeof setImmediate !== "undefined") { - schedule = setImmediate; - } else if (typeof setTimeout !== "undefined") { - schedule = setTimeout; - } else { - schedule = noAsyncScheduler; - } - } -} else if (typeof MutationObserver !== "undefined") { +if (util.isNode && typeof MutationObserver === "undefined") { + var GlobalSetImmediate = global.setImmediate; + var ProcessNextTick = process.nextTick; + schedule = util.isRecentNode + ? function(fn) { GlobalSetImmediate.call(global, fn); } + : function(fn) { ProcessNextTick.call(process, fn); }; +} else if ((typeof MutationObserver !== "undefined") && + !(typeof window !== "undefined" && + window.navigator && + window.navigator.standalone)) { schedule = function(fn) { var div = document.createElement("div"); var observer = new MutationObserver(fn); @@ -28825,7 +28935,7 @@ if (_dereq_("./util.js").isNode) { } module.exports = schedule; -},{"./util.js":38}],32:[function(_dereq_,module,exports){ +},{"./util":38}],32:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, PromiseArray) { @@ -29154,12 +29264,7 @@ function doThenable(x, then, context) { function resolveFromThenable(value) { if (!promise) return; - if (x === value) { - promise._rejectCallback( - Promise._makeSelfResolutionError(), false, true); - } else { - promise._resolveCallback(value); - } + promise._resolveCallback(value); promise = null; } @@ -29189,10 +29294,16 @@ var TimeoutError = Promise.TimeoutError; var afterTimeout = function (promise, message) { if (!promise.isPending()) return; - if (typeof message !== "string") { - message = "operation timed out"; + + var err; + if(!util.isPrimitive(message) && (message instanceof Error)) { + err = message; + } else { + if (typeof message !== "string") { + message = "operation timed out"; + } + err = new TimeoutError(message); } - var err = new TimeoutError(message); util.markAsOriginatingFromRejection(err); promise._attachExtraTrace(err); promise._cancel(err); @@ -29379,10 +29490,20 @@ module.exports = function (Promise, apiRejection, tryConvertToPromise, "you must pass at least 2 arguments to Promise.using"); var fn = arguments[len - 1]; if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); - len--; + + var input; + var spreadArgs = true; + if (len === 2 && Array.isArray(arguments[0])) { + input = arguments[0]; + len = input.length; + spreadArgs = false; + } else { + input = arguments; + len--; + } var resources = new Array(len); for (var i = 0; i < len; ++i) { - var resource = arguments[i]; + var resource = input[i]; if (Disposer.isDisposer(resource)) { var disposer = resource; resource = resource.promise(); @@ -29406,7 +29527,8 @@ module.exports = function (Promise, apiRejection, tryConvertToPromise, promise._pushContext(); var ret; try { - ret = fn.apply(undefined, vals); + ret = spreadArgs + ? fn.apply(undefined, vals) : fn.call(undefined, vals); } finally { promise._popContext(); } @@ -29469,7 +29591,9 @@ var errorObj = {e: {}}; var tryCatchTarget; function tryCatcher() { try { - return tryCatchTarget.apply(this, arguments); + var target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); } catch (e) { errorObj.e = e; return errorObj; @@ -29530,6 +29654,7 @@ function withAppended(target, appendee) { function getDataPropertyOrDefault(obj, key, defaultValue) { if (es5.isES5) { var desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc != null) { return desc.get == null && desc.set == null ? desc.value @@ -29552,23 +29677,32 @@ function notEnumerableProp(obj, name, value) { return obj; } - -var wrapsPrimitiveReceiver = (function() { - return this !== "string"; -}).call("string"); - function thrower(r) { throw r; } var inheritedDataKeys = (function() { + var excludedPrototypes = [ + Array.prototype, + Object.prototype, + Function.prototype + ]; + + var isExcludedProto = function(val) { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (excludedPrototypes[i] === val) { + return true; + } + } + return false; + }; + if (es5.isES5) { - var oProto = Object.prototype; var getKeys = Object.getOwnPropertyNames; return function(obj) { var ret = []; var visitedKeys = Object.create(null); - while (obj != null && obj !== oProto) { + while (obj != null && !isExcludedProto(obj)) { var keys; try { keys = getKeys(obj); @@ -29589,11 +29723,23 @@ var inheritedDataKeys = (function() { return ret; }; } else { + var hasProp = {}.hasOwnProperty; return function(obj) { + if (isExcludedProto(obj)) return []; var ret = []; + /*jshint forin:false */ - for (var key in obj) { - ret.push(key); + enumeration: for (var key in obj) { + if (hasProp.call(obj, key)) { + ret.push(key); + } else { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (hasProp.call(excludedPrototypes[i], key)) { + continue enumeration; + } + } + ret.push(key); + } } return ret; }; @@ -29601,13 +29747,22 @@ var inheritedDataKeys = (function() { })(); +var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; function isClass(fn) { try { if (typeof fn === "function") { var keys = es5.names(fn.prototype); - if (es5.isES5) return keys.length > 1; - return keys.length > 0 && - !(keys.length === 1 && keys[0] === "constructor"); + + var hasMethods = es5.isES5 && keys.length > 1; + var hasMethodsOtherThanConstructor = keys.length > 0 && + !(keys.length === 1 && keys[0] === "constructor"); + var hasThisAssignmentAndStaticMethods = + thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; + + if (hasMethods || hasMethodsOtherThanConstructor || + hasThisAssignmentAndStaticMethods) { + return true; + } } return false; } catch (e) { @@ -29687,7 +29842,9 @@ function copyDescriptors(from, to, filter) { for (var i = 0; i < keys.length; ++i) { var key = keys[i]; if (filter(key)) { - es5.defineProperty(to, key, es5.getDescriptor(from, key)); + try { + es5.defineProperty(to, key, es5.getDescriptor(from, key)); + } catch (ignore) {} } } } @@ -29709,7 +29866,6 @@ var ret = { inherits: inherits, withAppended: withAppended, maybeWrapAsError: maybeWrapAsError, - wrapsPrimitiveReceiver: wrapsPrimitiveReceiver, toFastProperties: toFastProperties, filledRange: filledRange, toString: safeToString, @@ -29724,313 +29880,17 @@ var ret = { isNode: typeof process !== "undefined" && classString(process).toLowerCase() === "[object process]" }; -try {throw new Error(); } catch (e) {ret.lastLineError = e;} -module.exports = ret; - -},{"./es5.js":14}],39:[function(_dereq_,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } - throw TypeError('Uncaught, unspecified "error" event.'); - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} +ret.isRecentNode = ret.isNode && (function() { + var version = process.versions.node.split(".").map(Number); + return (version[0] === 0 && version[1] > 10) || (version[0] > 0); +})(); -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} +if (ret.isNode) ret.toFastProperties(process); -function isUndefined(arg) { - return arg === void 0; -} +try {throw new Error(); } catch (e) {ret.lastLineError = e;} +module.exports = ret; -},{}]},{},[4])(4) +},{"./es5.js":14}]},{},[4])(4) }); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"g5I+bs":94}],91:[function(require,module,exports){ diff --git a/package.json b/package.json index 3f62f7559bf..d0b4727950d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.8-pre", + "version": "4.4.8", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a36c358aeb9e706b5bc8d16f149cc1ec72772b1f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 18 Mar 2016 06:36:55 -0700 Subject: [PATCH 0403/2240] docs(discriminators): correct default discriminator key --- test/docs/discriminators.test.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index 59359d10f29..cb4674c50f6 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -11,16 +11,14 @@ describe('discriminator docs', function () { before(function (done) { db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test'); - var options = {discriminatorKey: 'kind'}; - - var eventSchema = new mongoose.Schema({time: Date}, options); + var eventSchema = new mongoose.Schema({time: Date}); Event = db.model('_event', eventSchema); ClickedLinkEvent = Event.discriminator('ClickedLink', - new mongoose.Schema({url: String}, options)); + new mongoose.Schema({url: String})); SignedUpEvent = Event.discriminator('SignedUp', - new mongoose.Schema({username: String}, options)); + new mongoose.Schema({username: String})); done(); }); @@ -108,7 +106,7 @@ describe('discriminator docs', function () { /** * The way mongoose tells the difference between the different * discriminator models is by the 'discriminator key', which is - * `kind` by default. Mongoose adds a String path called `kind` + * `__t` by default. Mongoose adds a String path called `__t` * to your schemas that it uses to track which discriminator * this document is an instance of. */ @@ -117,9 +115,9 @@ describe('discriminator docs', function () { var event2 = new ClickedLinkEvent({time: Date.now(), url: 'google.com'}); var event3 = new SignedUpEvent({time: Date.now(), user: 'testuser'}); - assert.ok(!event1.kind); - assert.equal(event2.kind, 'ClickedLink'); - assert.equal(event3.kind, 'SignedUp'); + assert.ok(!event1.__t); + assert.equal(event2.__t, 'ClickedLink'); + assert.equal(event3.__t, 'SignedUp'); // acquit:ignore:start done(); From 9723807f13c0c7614315c253f57a1f656926ed09 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 19 Mar 2016 12:36:51 -0700 Subject: [PATCH 0404/2240] chore: now working on 4.4.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d0b4727950d..9cd756ddfed 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.8", + "version": "4.4.9-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 77f4458484239eb177f607a18ce45a74460ee2bf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 19 Mar 2016 12:47:28 -0700 Subject: [PATCH 0405/2240] docs: proper syntax highlighting for acquit examples Fix #3975 --- docs/acquit.jade | 2 +- docs/source/acquit.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/acquit.jade b/docs/acquit.jade index f88a04bd672..926de46a731 100644 --- a/docs/acquit.jade +++ b/docs/acquit.jade @@ -6,4 +6,4 @@ block content if block.comments && block.comments.length | !{block.comments[block.comments.length - 1]} :js - #{block.code} + !{block.code} diff --git a/docs/source/acquit.js b/docs/source/acquit.js index b94212d1037..ae4a68c02c3 100644 --- a/docs/source/acquit.js +++ b/docs/source/acquit.js @@ -1,5 +1,6 @@ var fs = require('fs'); var acquit = require('acquit'); +var hl = require('highlight.js'); var marked = require('marked'); require('acquit-ignore')(); @@ -44,6 +45,9 @@ files.forEach(function(file) { block.comments[last] = marked(acquit.trimEachLine(block.comments[last])); } + if (block.code) { + b.code = hl.highlight('javascript', b.code).value; + } for (var j = 0; j < block.blocks.length; ++j) { var b = block.blocks[j]; @@ -53,6 +57,9 @@ files.forEach(function(file) { var last = b.comments.length - 1; b.comments[last] = marked(acquit.trimEachLine(b.comments[last])); } + if (b.code) { + b.code = hl.highlight('javascript', b.code).value; + } } } From 027d8aa72a695a1154f44e99599cf4651f25522f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 19 Mar 2016 12:47:59 -0700 Subject: [PATCH 0406/2240] docs: remove conflicting validation.jade --- docs/source/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/index.js b/docs/source/index.js index 487bf20b8f0..1e63db42054 100644 --- a/docs/source/index.js +++ b/docs/source/index.js @@ -13,7 +13,6 @@ exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' } exports['docs/models.jade'] = { guide: true, title: 'Models' } exports['docs/queries.jade'] = { guide: true, title: 'Queries' } exports['docs/populate.jade'] = { guide: true, title: 'Query Population' } -exports['docs/validation.jade'] = { guide: true, title: 'Validation' } exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' } exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' } exports['docs/connections.jade'] = { guide: true, title: 'Connecting to MongoDB' } From c6f3145e723e275a0155a4c49ebb619e3d100fa4 Mon Sep 17 00:00:00 2001 From: Tom Marien Date: Sun, 20 Mar 2016 16:45:51 +0100 Subject: [PATCH 0407/2240] Fixes #3991 * Make sure timestamp functionality does not trigger any unnecessary update --- lib/schema.js | 4 +++- test/schema.timestamps.test.js | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index e8a670ea69b..d9edc3ba985 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -707,7 +707,9 @@ Schema.prototype.setupTimestamp = function(timestamps) { this[createdAt] = auto_id ? this._id.getTimestamp() : defaultTimestamp; } - this[updatedAt] = this.isNew ? this[createdAt] : defaultTimestamp; + if (this.isNew || this.isModified()) { + this[updatedAt] = this.isNew ? this[createdAt] : defaultTimestamp; + } next(); }); diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js index 14c950f4ff1..8040dbd370d 100644 --- a/test/schema.timestamps.test.js +++ b/test/schema.timestamps.test.js @@ -129,6 +129,8 @@ describe('schema options.timestamps', function() { Cat.findOne({name: 'newcat'}, function(err, doc) { var old = doc.updatedAt; + doc.hobby = 'coding'; + doc.save(function(err, doc) { assert.ok(doc.updatedAt.getTime() > old.getTime()); done(); @@ -136,6 +138,17 @@ describe('schema options.timestamps', function() { }); }); + it('should not change updatedAt when save with no modifications', function (done) { + Cat.findOne({name: 'newcat'}, function(err, doc) { + var old = doc.updatedAt; + + doc.save(function(err, doc) { + assert.ok(doc.updatedAt.getTime() === old.getTime()); + done(); + }); + }); + }); + it('should change updatedAt when findOneAndUpdate', function(done) { Cat.findOne({name: 'newcat'}, function(err, doc) { var old = doc.updatedAt; From a73d9b6a51c43153b367121a32da832773a80375 Mon Sep 17 00:00:00 2001 From: Tom Marien Date: Sun, 20 Mar 2016 16:55:54 +0100 Subject: [PATCH 0408/2240] Fixed eslint issue --- test/schema.timestamps.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js index 8040dbd370d..5cabfcc4e4b 100644 --- a/test/schema.timestamps.test.js +++ b/test/schema.timestamps.test.js @@ -138,7 +138,7 @@ describe('schema options.timestamps', function() { }); }); - it('should not change updatedAt when save with no modifications', function (done) { + it('should not change updatedAt when save with no modifications', function(done) { Cat.findOne({name: 'newcat'}, function(err, doc) { var old = doc.updatedAt; From b79a41876b20fabb7fed9ea8921ee0f4f2d3827e Mon Sep 17 00:00:00 2001 From: Maheshkumar Date: Sun, 20 Mar 2016 22:01:25 +0530 Subject: [PATCH 0409/2240] Added dependency status badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f25540bb919..631fa2b80be 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed [![Build Status](https://api.travis-ci.org/Automattic/mongoose.png?branch=master)](https://travis-ci.org/Automattic/mongoose) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Automattic/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![NPM version](https://badge.fury.io/js/mongoose.svg)](http://badge.fury.io/js/mongoose) +[![Dependency Status](https://gemnasium.com/Maheshkumar-Kakade/mongoose.svg)](https://gemnasium.com/Maheshkumar-Kakade/mongoose) ## Documentation From 9d08069bec3d0c9910b9815739d05cd22309b767 Mon Sep 17 00:00:00 2001 From: Christian Murphy Date: Tue, 22 Mar 2016 10:05:41 -0700 Subject: [PATCH 0410/2240] update eslint to 2.4.0 run autofix across project --- examples/aggregate/aggregate.js | 70 +++++++++++------------ examples/geospatial/geospatial.js | 80 +++++++++++++-------------- examples/lean/lean.js | 70 +++++++++++------------ examples/mapreduce/mapreduce.js | 60 ++++++++++---------- examples/promises/promise.js | 50 ++++++++--------- examples/querybuilder/querybuilder.js | 50 ++++++++--------- examples/replicasets/replica-sets.js | 50 ++++++++--------- package.json | 2 +- test/browser/document.test_.js | 18 +++--- test/document.populate.test.js | 8 +-- test/model.field.selection.test.js | 8 +-- test/model.populate.test.js | 16 +++--- test/model.stream.test.js | 16 +++--- test/versioning.test.js | 40 +++++++------- 14 files changed, 269 insertions(+), 269 deletions(-) diff --git a/examples/aggregate/aggregate.js b/examples/aggregate/aggregate.js index ccafd493c26..793c8cb2fcf 100644 --- a/examples/aggregate/aggregate.js +++ b/examples/aggregate/aggregate.js @@ -11,41 +11,41 @@ var Person = mongoose.model('Person'); // define some dummy data var data = [ - { - name: 'bill', - age: 25, - birthday: new Date().setFullYear((new Date().getFullYear() - 25)), - gender: 'Male', - likes: ['movies', 'games', 'dogs'] - }, - { - name: 'mary', - age: 30, - birthday: new Date().setFullYear((new Date().getFullYear() - 30)), - gender: 'Female', - likes: ['movies', 'birds', 'cats'] - }, - { - name: 'bob', - age: 21, - birthday: new Date().setFullYear((new Date().getFullYear() - 21)), - gender: 'Male', - likes: ['tv', 'games', 'rabbits'] - }, - { - name: 'lilly', - age: 26, - birthday: new Date().setFullYear((new Date().getFullYear() - 26)), - gender: 'Female', - likes: ['books', 'cats', 'dogs'] - }, - { - name: 'alucard', - age: 1000, - birthday: new Date().setFullYear((new Date().getFullYear() - 1000)), - gender: 'Male', - likes: ['glasses', 'wine', 'the night'] - } + { + name: 'bill', + age: 25, + birthday: new Date().setFullYear((new Date().getFullYear() - 25)), + gender: 'Male', + likes: ['movies', 'games', 'dogs'] + }, + { + name: 'mary', + age: 30, + birthday: new Date().setFullYear((new Date().getFullYear() - 30)), + gender: 'Female', + likes: ['movies', 'birds', 'cats'] + }, + { + name: 'bob', + age: 21, + birthday: new Date().setFullYear((new Date().getFullYear() - 21)), + gender: 'Male', + likes: ['tv', 'games', 'rabbits'] + }, + { + name: 'lilly', + age: 26, + birthday: new Date().setFullYear((new Date().getFullYear() - 26)), + gender: 'Female', + likes: ['books', 'cats', 'dogs'] + }, + { + name: 'alucard', + age: 1000, + birthday: new Date().setFullYear((new Date().getFullYear() - 1000)), + gender: 'Male', + likes: ['glasses', 'wine', 'the night'] + } ]; diff --git a/examples/geospatial/geospatial.js b/examples/geospatial/geospatial.js index 6e4b439cbf3..3ff8c0bd519 100644 --- a/examples/geospatial/geospatial.js +++ b/examples/geospatial/geospatial.js @@ -10,46 +10,46 @@ var Person = mongoose.model('Person'); // define some dummy data var data = [ - { - name: 'bill', - age: 25, - birthday: new Date().setFullYear((new Date().getFullYear() - 25)), - gender: 'Male', - likes: ['movies', 'games', 'dogs'], - loc: [0, 0] - }, - { - name: 'mary', - age: 30, - birthday: new Date().setFullYear((new Date().getFullYear() - 30)), - gender: 'Female', - likes: ['movies', 'birds', 'cats'], - loc: [1, 1] - }, - { - name: 'bob', - age: 21, - birthday: new Date().setFullYear((new Date().getFullYear() - 21)), - gender: 'Male', - likes: ['tv', 'games', 'rabbits'], - loc: [3, 3] - }, - { - name: 'lilly', - age: 26, - birthday: new Date().setFullYear((new Date().getFullYear() - 26)), - gender: 'Female', - likes: ['books', 'cats', 'dogs'], - loc: [6, 6] - }, - { - name: 'alucard', - age: 1000, - birthday: new Date().setFullYear((new Date().getFullYear() - 1000)), - gender: 'Male', - likes: ['glasses', 'wine', 'the night'], - loc: [10, 10] - } + { + name: 'bill', + age: 25, + birthday: new Date().setFullYear((new Date().getFullYear() - 25)), + gender: 'Male', + likes: ['movies', 'games', 'dogs'], + loc: [0, 0] + }, + { + name: 'mary', + age: 30, + birthday: new Date().setFullYear((new Date().getFullYear() - 30)), + gender: 'Female', + likes: ['movies', 'birds', 'cats'], + loc: [1, 1] + }, + { + name: 'bob', + age: 21, + birthday: new Date().setFullYear((new Date().getFullYear() - 21)), + gender: 'Male', + likes: ['tv', 'games', 'rabbits'], + loc: [3, 3] + }, + { + name: 'lilly', + age: 26, + birthday: new Date().setFullYear((new Date().getFullYear() - 26)), + gender: 'Female', + likes: ['books', 'cats', 'dogs'], + loc: [6, 6] + }, + { + name: 'alucard', + age: 1000, + birthday: new Date().setFullYear((new Date().getFullYear() - 1000)), + gender: 'Male', + likes: ['glasses', 'wine', 'the night'], + loc: [10, 10] + } ]; diff --git a/examples/lean/lean.js b/examples/lean/lean.js index c3e682e32f2..763367f0a07 100644 --- a/examples/lean/lean.js +++ b/examples/lean/lean.js @@ -11,41 +11,41 @@ var Person = mongoose.model('Person'); // define some dummy data var data = [ - { - name: 'bill', - age: 25, - birthday: new Date().setFullYear((new Date().getFullYear() - 25)), - gender: 'Male', - likes: ['movies', 'games', 'dogs'] - }, - { - name: 'mary', - age: 30, - birthday: new Date().setFullYear((new Date().getFullYear() - 30)), - gender: 'Female', - likes: ['movies', 'birds', 'cats'] - }, - { - name: 'bob', - age: 21, - birthday: new Date().setFullYear((new Date().getFullYear() - 21)), - gender: 'Male', - likes: ['tv', 'games', 'rabbits'] - }, - { - name: 'lilly', - age: 26, - birthday: new Date().setFullYear((new Date().getFullYear() - 26)), - gender: 'Female', - likes: ['books', 'cats', 'dogs'] - }, - { - name: 'alucard', - age: 1000, - birthday: new Date().setFullYear((new Date().getFullYear() - 1000)), - gender: 'Male', - likes: ['glasses', 'wine', 'the night'] - } + { + name: 'bill', + age: 25, + birthday: new Date().setFullYear((new Date().getFullYear() - 25)), + gender: 'Male', + likes: ['movies', 'games', 'dogs'] + }, + { + name: 'mary', + age: 30, + birthday: new Date().setFullYear((new Date().getFullYear() - 30)), + gender: 'Female', + likes: ['movies', 'birds', 'cats'] + }, + { + name: 'bob', + age: 21, + birthday: new Date().setFullYear((new Date().getFullYear() - 21)), + gender: 'Male', + likes: ['tv', 'games', 'rabbits'] + }, + { + name: 'lilly', + age: 26, + birthday: new Date().setFullYear((new Date().getFullYear() - 26)), + gender: 'Female', + likes: ['books', 'cats', 'dogs'] + }, + { + name: 'alucard', + age: 1000, + birthday: new Date().setFullYear((new Date().getFullYear() - 1000)), + gender: 'Male', + likes: ['glasses', 'wine', 'the night'] + } ]; diff --git a/examples/mapreduce/mapreduce.js b/examples/mapreduce/mapreduce.js index 593d73a568e..6d67fbf4e76 100644 --- a/examples/mapreduce/mapreduce.js +++ b/examples/mapreduce/mapreduce.js @@ -10,36 +10,36 @@ var Person = mongoose.model('Person'); // define some dummy data var data = [ - { - name: 'bill', - age: 25, - birthday: new Date().setFullYear((new Date().getFullYear() - 25)), - gender: 'Male' - }, - { - name: 'mary', - age: 30, - birthday: new Date().setFullYear((new Date().getFullYear() - 30)), - gender: 'Female' - }, - { - name: 'bob', - age: 21, - birthday: new Date().setFullYear((new Date().getFullYear() - 21)), - gender: 'Male' - }, - { - name: 'lilly', - age: 26, - birthday: new Date().setFullYear((new Date().getFullYear() - 26)), - gender: 'Female' - }, - { - name: 'alucard', - age: 1000, - birthday: new Date().setFullYear((new Date().getFullYear() - 1000)), - gender: 'Male' - } + { + name: 'bill', + age: 25, + birthday: new Date().setFullYear((new Date().getFullYear() - 25)), + gender: 'Male' + }, + { + name: 'mary', + age: 30, + birthday: new Date().setFullYear((new Date().getFullYear() - 30)), + gender: 'Female' + }, + { + name: 'bob', + age: 21, + birthday: new Date().setFullYear((new Date().getFullYear() - 21)), + gender: 'Male' + }, + { + name: 'lilly', + age: 26, + birthday: new Date().setFullYear((new Date().getFullYear() - 26)), + gender: 'Female' + }, + { + name: 'alucard', + age: 1000, + birthday: new Date().setFullYear((new Date().getFullYear() - 1000)), + gender: 'Male' + } ]; diff --git a/examples/promises/promise.js b/examples/promises/promise.js index fd1ff7a8149..3f17206a343 100644 --- a/examples/promises/promise.js +++ b/examples/promises/promise.js @@ -10,31 +10,31 @@ var Person = mongoose.model('Person'); // define some dummy data var data = [ - { - name: 'bill', - age: 25, - birthday: new Date().setFullYear((new Date().getFullYear() - 25)) - }, - { - name: 'mary', - age: 30, - birthday: new Date().setFullYear((new Date().getFullYear() - 30)) - }, - { - name: 'bob', - age: 21, - birthday: new Date().setFullYear((new Date().getFullYear() - 21)) - }, - { - name: 'lilly', - age: 26, - birthday: new Date().setFullYear((new Date().getFullYear() - 26)) - }, - { - name: 'alucard', - age: 1000, - birthday: new Date().setFullYear((new Date().getFullYear() - 1000)) - } + { + name: 'bill', + age: 25, + birthday: new Date().setFullYear((new Date().getFullYear() - 25)) + }, + { + name: 'mary', + age: 30, + birthday: new Date().setFullYear((new Date().getFullYear() - 30)) + }, + { + name: 'bob', + age: 21, + birthday: new Date().setFullYear((new Date().getFullYear() - 21)) + }, + { + name: 'lilly', + age: 26, + birthday: new Date().setFullYear((new Date().getFullYear() - 26)) + }, + { + name: 'alucard', + age: 1000, + birthday: new Date().setFullYear((new Date().getFullYear() - 1000)) + } ]; diff --git a/examples/querybuilder/querybuilder.js b/examples/querybuilder/querybuilder.js index 723a357f4e3..6f8645b5eac 100644 --- a/examples/querybuilder/querybuilder.js +++ b/examples/querybuilder/querybuilder.js @@ -11,31 +11,31 @@ var Person = mongoose.model('Person'); // define some dummy data var data = [ - { - name: 'bill', - age: 25, - birthday: new Date().setFullYear((new Date().getFullYear() - 25)) - }, - { - name: 'mary', - age: 30, - birthday: new Date().setFullYear((new Date().getFullYear() - 30)) - }, - { - name: 'bob', - age: 21, - birthday: new Date().setFullYear((new Date().getFullYear() - 21)) - }, - { - name: 'lilly', - age: 26, - birthday: new Date().setFullYear((new Date().getFullYear() - 26)) - }, - { - name: 'alucard', - age: 1000, - birthday: new Date().setFullYear((new Date().getFullYear() - 1000)) - } + { + name: 'bill', + age: 25, + birthday: new Date().setFullYear((new Date().getFullYear() - 25)) + }, + { + name: 'mary', + age: 30, + birthday: new Date().setFullYear((new Date().getFullYear() - 30)) + }, + { + name: 'bob', + age: 21, + birthday: new Date().setFullYear((new Date().getFullYear() - 21)) + }, + { + name: 'lilly', + age: 26, + birthday: new Date().setFullYear((new Date().getFullYear() - 26)) + }, + { + name: 'alucard', + age: 1000, + birthday: new Date().setFullYear((new Date().getFullYear() - 1000)) + } ]; diff --git a/examples/replicasets/replica-sets.js b/examples/replicasets/replica-sets.js index 6aa27b5cbda..9ebac1b6b3b 100644 --- a/examples/replicasets/replica-sets.js +++ b/examples/replicasets/replica-sets.js @@ -11,31 +11,31 @@ var Person = mongoose.model('Person'); // define some dummy data var data = [ - { - name: 'bill', - age: 25, - birthday: new Date().setFullYear((new Date().getFullYear() - 25)) - }, - { - name: 'mary', - age: 30, - birthday: new Date().setFullYear((new Date().getFullYear() - 30)) - }, - { - name: 'bob', - age: 21, - birthday: new Date().setFullYear((new Date().getFullYear() - 21)) - }, - { - name: 'lilly', - age: 26, - birthday: new Date().setFullYear((new Date().getFullYear() - 26)) - }, - { - name: 'alucard', - age: 1000, - birthday: new Date().setFullYear((new Date().getFullYear() - 1000)) - } + { + name: 'bill', + age: 25, + birthday: new Date().setFullYear((new Date().getFullYear() - 25)) + }, + { + name: 'mary', + age: 30, + birthday: new Date().setFullYear((new Date().getFullYear() - 30)) + }, + { + name: 'bob', + age: 21, + birthday: new Date().setFullYear((new Date().getFullYear() - 21)) + }, + { + name: 'lilly', + age: 26, + birthday: new Date().setFullYear((new Date().getFullYear() - 26)) + }, + { + name: 'alucard', + age: 1000, + birthday: new Date().setFullYear((new Date().getFullYear() - 1000)) + } ]; diff --git a/package.json b/package.json index 9cd756ddfed..c03a3a5bd5b 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "bluebird": "3.1.4", "co": "4.6.0", "dox": "0.3.1", - "eslint": "2.0.0-beta.3", + "eslint": "2.4.0", "highlight.js": "7.0.1", "istanbul": "0.4.2", "jade": "0.26.3", diff --git a/test/browser/document.test_.js b/test/browser/document.test_.js index c0c4be7f3ae..04055ad647f 100644 --- a/test/browser/document.test_.js +++ b/test/browser/document.test_.js @@ -68,15 +68,15 @@ describe('browser:document', function() { assert.equal(doc.getValue('nested.setr'), 'set it setter'); var doc2 = new mongoose.Document( - { - test: 'toop', - oids: [], - nested: { - age: 2, - cool: mongoose.Types.ObjectId.createFromHexString('4cf70857337498f95900001c'), - deep: {x: 'yay'} - } - }, + { + test: 'toop', + oids: [], + nested: { + age: 2, + cool: mongoose.Types.ObjectId.createFromHexString('4cf70857337498f95900001c'), + deep: {x: 'yay'} + } + }, schema); assert.equal('toop', doc2.get('test')); diff --git a/test/document.populate.test.js b/test/document.populate.test.js index 4b27d54f420..26a5b03a36a 100644 --- a/test/document.populate.test.js +++ b/test/document.populate.test.js @@ -537,10 +537,10 @@ describe('document.populate', function() { var Person = db.model('gh-2214-2', { name: String, cars: [ - { - type: Schema.Types.ObjectId, - ref: 'gh-2214-1' - } + { + type: Schema.Types.ObjectId, + ref: 'gh-2214-1' + } ] }); diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js index baa65023aa0..22fef8c88f3 100644 --- a/test/model.field.selection.test.js +++ b/test/model.field.selection.test.js @@ -413,10 +413,10 @@ describe('model field selection', function() { loc: {type: [Number], index: '2d'} }, points: [ - { - name: {type: String}, - loc: {type: [Number], index: '2d'} - } + { + name: {type: String}, + loc: {type: [Number], index: '2d'} + } ] } }); diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 0394a25c559..5c29e06632a 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -2962,15 +2962,15 @@ describe('model: populate:', function() { } }, items: [ - { - id: { - type: Number, - refPath: 'items.type' - }, - type: { - type: String - } + { + id: { + type: Number, + refPath: 'items.type' + }, + type: { + type: String } + } ] }); diff --git a/test/model.stream.test.js b/test/model.stream.test.js index 6df91e08e91..105826afe97 100644 --- a/test/model.stream.test.js +++ b/test/model.stream.test.js @@ -431,15 +431,15 @@ describe('query stream:', function() { } }, items: [ - { - id: { - type: Number, - refPath: 'items.type' - }, - type: { - type: String - } + { + id: { + type: Number, + refPath: 'items.type' + }, + type: { + type: String } + } ] }); diff --git a/test/versioning.test.js b/test/versioning.test.js index 153a57fa5cf..c9bac221bf5 100644 --- a/test/versioning.test.js +++ b/test/versioning.test.js @@ -23,28 +23,28 @@ Comments.add({ }); var BlogPost = new Schema( - { - title: String, + { + title: String, + date: Date, + meta: { date: Date, - meta: { - date: Date, - visitors: Number, - nested: [Comments], - numbers: [Number] - }, - mixed: {}, - numbers: [Number], - comments: [Comments], - arr: [], - dontVersionMe: [] + visitors: Number, + nested: [Comments], + numbers: [Number] }, - { - collection: 'versioning_' + random(), - skipVersioning: { - dontVersionMe: true, - 'comments.dontVersionMeEither': true - } - }); + mixed: {}, + numbers: [Number], + comments: [Comments], + arr: [], + dontVersionMe: [] + }, + { + collection: 'versioning_' + random(), + skipVersioning: { + dontVersionMe: true, + 'comments.dontVersionMeEither': true + } + }); mongoose.model('Versioning', BlogPost); From bdb7aef5e0b26d9d20c2c1d5954f7eab92fd2fe5 Mon Sep 17 00:00:00 2001 From: Christian Murphy Date: Tue, 22 Mar 2016 10:11:40 -0700 Subject: [PATCH 0411/2240] use textual reporting level --- .eslintrc.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index c16c3369b56..013d2ec3dd1 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -5,27 +5,27 @@ env: mocha: true rules: - comma-style: 2 + comma-style: error consistent-this: - - 2 + - error - _this indent: - - 2 + - error - 2 - SwitchCase: 1 VariableDeclarator: 2 - keyword-spacing: 2 - no-console: 0 - no-multi-spaces: 2 - no-spaced-func: 2 - no-trailing-spaces: 2 + keyword-spacing: error + no-console: off + no-multi-spaces: error + no-spaced-func: error + no-trailing-spaces: error quotes: - - 2 + - error - single - semi: 2 - space-before-blocks: 2 + semi: error + space-before-blocks: error space-before-function-paren: - - 2 + - error - never - space-infix-ops: 2 - space-unary-ops: 2 + space-infix-ops: error + space-unary-ops: error From 230bdb0453577d1e0b9cabaff3c89b35b64a8193 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 22 Mar 2016 18:52:16 -0700 Subject: [PATCH 0412/2240] fix: upgrade mongodb -> 2.1.10 re https://jira.mongodb.org/browse/NODE-679 Fix #4010 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9cd756ddfed..fac17f572a4 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "0.4.21", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.1.8", + "mongodb": "2.1.10", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.10.0", From 45769959fd7aca8584c85922f5d4f597f9095e97 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 22 Mar 2016 18:58:21 -0700 Subject: [PATCH 0413/2240] chore: release 4.4.9 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index dd062086204..aba1a4d307e 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +4.4.9 / 2016-03-22 +================== + * fix: upgrade mongodb -> 2.1.10 re https://jira.mongodb.org/browse/NODE-679 #4010 + * docs: add syntax highlighting for acquit examples #3975 + 4.4.8 / 2016-03-18 ================== * docs(aggregate): clarify promises #3990 [megagon](https://github.com/megagon) diff --git a/package.json b/package.json index fac17f572a4..5aa9712136c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.9-pre", + "version": "4.4.9", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 931e79cfbdaa0463fa02df7b3bf38124590676a3 Mon Sep 17 00:00:00 2001 From: Maheshkumar Date: Wed, 23 Mar 2016 11:13:21 +0530 Subject: [PATCH 0414/2240] Update Dependency Status link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 631fa2b80be..c1710d14a6b 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed [![Build Status](https://api.travis-ci.org/Automattic/mongoose.png?branch=master)](https://travis-ci.org/Automattic/mongoose) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Automattic/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![NPM version](https://badge.fury.io/js/mongoose.svg)](http://badge.fury.io/js/mongoose) -[![Dependency Status](https://gemnasium.com/Maheshkumar-Kakade/mongoose.svg)](https://gemnasium.com/Maheshkumar-Kakade/mongoose) +[![Dependency Status](https://gemnasium.com/Automattic/mongoose.svg)](https://gemnasium.com/Automattic/mongoose) ## Documentation From 2d87f2520e846032c52bd21d96aea3f75b50b23d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 24 Mar 2016 08:16:22 -0700 Subject: [PATCH 0415/2240] chore: now working on 4.4.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5aa9712136c..1b9d122b6fe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.9", + "version": "4.4.10-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4e837d01be3493758ebb2965fe02f3146e166d20 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 24 Mar 2016 08:30:24 -0700 Subject: [PATCH 0416/2240] test(populate): repro #3974 --- test/model.populate.test.js | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 0394a25c559..6244e9044f8 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3475,5 +3475,63 @@ describe('model: populate:', function() { }); }); }); + + it('deep populate two paths (gh-3974)', function(done) { + var level3Schema = new Schema({ + name: { type: String } + }); + + var level2Schema = new Schema({ + name: { type: String }, + level31: [{ type: Schema.Types.ObjectId, ref: 'gh3974' }], + level32: [{ type: Schema.Types.ObjectId, ref: 'gh3974' }] + }); + + var level1Schema = new Schema({ + name: { type: String }, + level2: [{ type: Schema.Types.ObjectId, ref: 'gh3974_0' }] + }); + + var level3 = db.model('gh3974', level3Schema); + var level2 = db.model('gh3974_0', level2Schema); + var level1 = db.model('gh3974_1', level1Schema); + + var l3 = [ + { name: 'level 3/1' }, + { name: 'level 3/2' } + ]; + level3.create(l3, function(error, l3) { + assert.ifError(error); + var l2 = [ + { name: 'level 2', level31: l3[0]._id, level32: l3[1]._id } + ]; + level2.create(l2, function(error, l2) { + assert.ifError(error); + var l1 = [{ name: 'level 1', level2: l2[0]._id }]; + level1.create(l1, function(error, l1) { + assert.ifError(error); + level1.findById(l1[0]._id). + populate({ + path: 'level2', + populate: [{ + path: 'level31' + }] + }). + populate({ + path: 'level2', + populate: [{ + path: 'level32' + }] + }). + exec(function(error, obj) { + assert.ifError(error); + assert.equal(obj.level2[0].level31[0].name, 'level 3/1'); + assert.equal(obj.level2[0].level32[0].name, 'level 3/2'); + done(); + }); + }); + }); + }); + }); }); }); From fee992012141b6e953b3b79ad32e9821d2a5bd9f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 24 Mar 2016 08:31:37 -0700 Subject: [PATCH 0417/2240] fix(populate): merge multiple deep populate opts for the same path Fix #3974 --- lib/query.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 078e9eab4c2..ea7b6edd33d 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2538,8 +2538,14 @@ Query.prototype.populate = function() { opts.populate = {}; } + var pop = opts.populate; + for (var i = 0; i < res.length; ++i) { - opts.populate[res[i].path] = res[i]; + var path = res[i].path; + if (pop[path] && pop[path].populate && res[i].populate) { + res[i].populate = pop[path].populate.concat(res[i].populate); + } + pop[res[i].path] = res[i]; } return this; From 24bca8794500d6a3589bb0b6b8e6cf066c2b5b3c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 24 Mar 2016 08:53:14 -0700 Subject: [PATCH 0418/2240] test(document): repro #3981 --- test/docs/defaults.test.js | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/test/docs/defaults.test.js b/test/docs/defaults.test.js index 7a4d1893f44..d6dd1784964 100644 --- a/test/docs/defaults.test.js +++ b/test/docs/defaults.test.js @@ -17,26 +17,41 @@ describe('defaults docs', function () { * Your schemas can define default values for certain paths. If you create * a new document without that path set, the default will kick in. */ - it('Declaring defaults in your schema', function () { + it('Declaring defaults in your schema', function() { var schema = new Schema({ name: String, - role: {type: String, default: 'guitarist'} + role: { type: String, default: 'guitarist' } }); var Person = db.model('Person', schema); - var axl = new Person({name: 'Axl Rose', role: 'singer'}); + var axl = new Person({ name: 'Axl Rose', role: 'singer' }); assert.equal(axl.role, 'singer'); - var slash = new Person({name: 'Slash'}); + var slash = new Person({ name: 'Slash' }); assert.equal(slash.role, 'guitarist'); + + var izzy = new Person({ name: 'Izzy', role: undefined }); + assert.equal(izzy.role, 'guitarist'); + + Person.create(axl, slash, function(error) { + assert.ifError(error); + Person.find({ role: 'guitarist' }, function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 1); + assert.equal(docs[0].name, 'Slash'); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); }); /** * You can also set the `default` schema option to a function. Mongoose will * execute that function and use the return value as the default. */ - it('Default functions', function () { + it('Default functions', function() { var schema = new Schema({ title: String, date: { @@ -68,7 +83,7 @@ describe('defaults docs', function () { * The `$setOnInsert` operator was introduced in MongoDB 2.4. If you're * using MongoDB server < 2.4.0, do **not** use `setDefaultsOnInsert`. */ - it('The `setDefaultsOnInsert` option', function (done) { + it('The `setDefaultsOnInsert` option', function(done) { var schema = new Schema({ title: String, genre: {type: String, default: 'Action'} From de72d9b85b6b36a6e72ad5cd1399060fc9a8c2e2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 24 Mar 2016 08:53:21 -0700 Subject: [PATCH 0419/2240] fix(document): don't overwrite defaults with undefined keys Fix #3981 --- lib/document.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 16d7f4fdbdd..72df0a93cde 100644 --- a/lib/document.js +++ b/lib/document.js @@ -508,7 +508,7 @@ Document.prototype.set = function(path, val, type, options) { pathtype = this.schema.pathType(pathName); if (path[key] !== null - && path[key] !== undefined + && path[key] !== void 0 // need to know if plain object - no Buffer, ObjectId, ref, etc && utils.isObject(path[key]) && (!path[key].constructor || utils.getFunctionName(path[key].constructor) === 'Object') @@ -520,6 +520,12 @@ Document.prototype.set = function(path, val, type, options) { this.schema.paths[pathName].options.ref)) { this.set(path[key], prefix + key, constructing); } else if (strict) { + // Don't overwrite defaults with undefined keys (gh-3981) + if (constructing && path[key] === void 0 && + this.get(key) !== void 0) { + continue; + } + if (pathtype === 'real' || pathtype === 'virtual') { // Check for setting single embedded schema to document (gh-3535) if (this.schema.paths[pathName] && @@ -538,7 +544,7 @@ Document.prototype.set = function(path, val, type, options) { throw new StrictModeError(key); } } - } else if (undefined !== path[key]) { + } else if (path[key] !== void 0) { this.set(prefix + key, path[key], constructing); } } From 4d9e64d8cfbc106c6f2b637e84f8a2876135b43a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 24 Mar 2016 09:35:47 -0700 Subject: [PATCH 0420/2240] test(document): repro #3982 --- test/document.test.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 5c89f3bfe22..5569112d99e 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2499,5 +2499,44 @@ describe('document', function() { done(); }); }); + + it('manual population and isNew (gh-3982)', function(done) { + var NestedModelSchema = new mongoose.Schema({ + field: String + }); + + var NestedModel = db.model('gh3982', NestedModelSchema); + + var ModelSchema = new mongoose.Schema({ + field: String, + array: [{ + type: mongoose.Schema.ObjectId, + ref: 'gh3982', + required: true + }] + }); + + var Model = db.model('gh3982_0', ModelSchema); + + var nestedModel = new NestedModel({ + 'field': 'nestedModel' + }); + + nestedModel.save(function(error, nestedModel) { + assert.ifError(error); + Model.create({ array: [nestedModel._id] }, function(error, doc) { + assert.ifError(error); + Model.findById(doc._id).populate('array').exec(function(error, doc) { + assert.ifError(error); + doc.array.push(nestedModel); + assert.strictEqual(doc.isNew, false); + assert.strictEqual(doc.array[0].isNew, false); + assert.strictEqual(doc.array[1].isNew, false); + assert.strictEqual(nestedModel.isNew, false); + done(); + }); + }); + }); + }); }); }); From 0c8b6e551e38fa1a11c5733c45b44dd4c577b24b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 24 Mar 2016 09:35:53 -0700 Subject: [PATCH 0421/2240] fix(document): copy isNew when copying a document Fix #3982 --- lib/document.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/document.js b/lib/document.js index 72df0a93cde..865222e04a3 100644 --- a/lib/document.js +++ b/lib/document.js @@ -59,6 +59,9 @@ function Document(obj, fields, skipId) { this._doc = this.$__buildDoc(obj, fields, skipId); if (obj) { + if (obj instanceof Document) { + this.isNew = obj.isNew; + } this.set(obj, undefined, true); } From 857af4990bd4db6bce316ef72dc33f5356093a54 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 24 Mar 2016 10:16:27 -0700 Subject: [PATCH 0422/2240] chore: release 4.4.10 --- History.md | 6 ++++++ bin/mongoose.js | 13 +++++++++++-- package.json | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index aba1a4d307e..cf4956496cb 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +4.4.10 / 2016-03-24 +=================== + * fix(document): copy isNew when copying a document #3982 + * fix(document): don't override defaults with undefined keys #3981 + * fix(populate): merge multiple deep populate options for the same path #3974 + 4.4.9 / 2016-03-22 ================== * fix: upgrade mongodb -> 2.1.10 re https://jira.mongodb.org/browse/NODE-679 #4010 diff --git a/bin/mongoose.js b/bin/mongoose.js index 395b1a0628e..32ade1ef358 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -503,6 +503,9 @@ function Document(obj, fields, skipId) { this._doc = this.$__buildDoc(obj, fields, skipId); if (obj) { + if (obj instanceof Document) { + this.isNew = obj.isNew; + } this.set(obj, undefined, true); } @@ -952,7 +955,7 @@ Document.prototype.set = function(path, val, type, options) { pathtype = this.schema.pathType(pathName); if (path[key] !== null - && path[key] !== undefined + && path[key] !== void 0 // need to know if plain object - no Buffer, ObjectId, ref, etc && utils.isObject(path[key]) && (!path[key].constructor || utils.getFunctionName(path[key].constructor) === 'Object') @@ -964,6 +967,12 @@ Document.prototype.set = function(path, val, type, options) { this.schema.paths[pathName].options.ref)) { this.set(path[key], prefix + key, constructing); } else if (strict) { + // Don't overwrite defaults with undefined keys (gh-3981) + if (constructing && path[key] === void 0 && + this.get(key) !== void 0) { + continue; + } + if (pathtype === 'real' || pathtype === 'virtual') { // Check for setting single embedded schema to document (gh-3535) if (this.schema.paths[pathName] && @@ -982,7 +991,7 @@ Document.prototype.set = function(path, val, type, options) { throw new StrictModeError(key); } } - } else if (undefined !== path[key]) { + } else if (path[key] !== void 0) { this.set(prefix + key, path[key], constructing); } } diff --git a/package.json b/package.json index 1b9d122b6fe..98321284aab 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.10-pre", + "version": "4.4.10", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From eed8ff9d60116cadd091e2594a095059abfde494 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 26 Mar 2016 11:22:44 -0700 Subject: [PATCH 0423/2240] now working on 4.4.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8f0ef134161..045e43c44a5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.10", + "version": "4.4.11", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 96955798bda63d1a6f99f1de2ab868abf6d83018 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 26 Mar 2016 11:25:05 -0700 Subject: [PATCH 0424/2240] chore: now working on 4.4.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 045e43c44a5..b16d74e7977 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.11", + "version": "4.4.11-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 7067c3508ace1f2d182c6b264289700daeb44d7a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 26 Mar 2016 11:34:19 -0700 Subject: [PATCH 0425/2240] test(document): repro #3965 --- test/document.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index 5569112d99e..eabd4b3aa8d 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -1314,7 +1314,8 @@ describe('document', function() { Post = db.model('InvalidateSchema'); post = new Post(); post.set({baz: 'val'}); - var _err = post.invalidate('baz', 'validation failed for path {PATH}'); + var _err = post.invalidate('baz', 'validation failed for path {PATH}', + 'val', 'custom error'); assert.ok(_err instanceof ValidationError); post.save(function(err) { @@ -1322,8 +1323,9 @@ describe('document', function() { assert.ok(err instanceof ValidationError); assert.ok(err.errors.baz instanceof ValidatorError); assert.equal(err.errors.baz.message, 'validation failed for path baz'); - assert.equal(err.errors.baz.kind, 'user defined'); assert.equal(err.errors.baz.path, 'baz'); + assert.equal(err.errors.baz.value, 'val'); + assert.equal(err.errors.baz.kind, 'custom error'); post.save(function(err) { db.close(); From abae1bfbb03805532adda8dcee84abd79df78422 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 26 Mar 2016 11:34:32 -0700 Subject: [PATCH 0426/2240] feat(document): support kind argument to document Fix #3965 --- lib/document.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 865222e04a3..ebf290a9bc8 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1329,11 +1329,12 @@ Document.prototype.validateSync = function(pathsToValidate) { * @param {String} path the field to invalidate * @param {String|Error} errorMsg the error which states the reason `path` was invalid * @param {Object|String|Number|any} value optional invalid value + * @param {String} [kind] optional `kind` property for the error * @return {ValidationError} the current ValidationError, with all currently invalidated paths * @api public */ -Document.prototype.invalidate = function(path, err, val) { +Document.prototype.invalidate = function(path, err, val, kind) { if (!this.$__.validationError) { this.$__.validationError = new ValidationError(this); } @@ -1346,7 +1347,7 @@ Document.prototype.invalidate = function(path, err, val) { err = new ValidatorError({ path: path, message: err, - type: 'user defined', + type: kind || 'user defined', value: val }); } From 7c7eff620aa53d431d5772422f9aed80a0f677ce Mon Sep 17 00:00:00 2001 From: Eugene Song Date: Tue, 29 Mar 2016 11:46:51 -0700 Subject: [PATCH 0427/2240] Add autoIndex config example at connection level --- docs/guide.jade | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/guide.jade b/docs/guide.jade index db657977e87..91663b43ebd 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -148,6 +148,10 @@ block content While nice for development, it is recommended this behavior be disabled in production since index creation can cause a [significant performance impact](http://docs.mongodb.org/manual/core/indexes/#index-creation-operations). Disable the behavior by setting the `autoIndex` option of your schema to `false`, or globally on the connection by setting the option `config.autoIndex` to `false`. :js + mongoose.connect('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } }); + // or + mongoose.createConnection('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } }); + // or animalSchema.set('autoIndex', false); // or new Schema({..}, { autoIndex: false }); From e24d199787bc2466becdd036725c33a17323ac1c Mon Sep 17 00:00:00 2001 From: Jacob Burton Date: Thu, 31 Mar 2016 15:12:46 -0600 Subject: [PATCH 0428/2240] allow connecting with {mongos: true} to handle connection query params --- lib/drivers/node-mongodb-native/connection.js | 6 ++ test/connection.test.js | 98 +++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index ea278079508..b8ca9d888cf 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -241,11 +241,16 @@ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { o.replset || (o.replset = o.replSet) || (o.replset = {}); o.server.socketOptions || (o.server.socketOptions = {}); o.replset.socketOptions || (o.replset.socketOptions = {}); + (o.mongos === true) && (o.mongos = {}); var opts = connStrOpts || {}; Object.keys(opts).forEach(function(name) { switch (name) { case 'ssl': + o.server.ssl = opts.ssl; + o.replset.ssl = opts.ssl; + o.mongos && (o.mongos.ssl = opts.ssl); + break; case 'poolSize': if (typeof o.server[name] === 'undefined') { o.server[name] = o.replset[name] = opts[name]; @@ -321,6 +326,7 @@ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { case 'sslValidate': o.server.sslValidate = opts.sslValidate; o.replset.sslValidate = opts.sslValidate; + o.mongos && (o.mongos.sslValidate = opts.sslValidate); } }); diff --git a/test/connection.test.js b/test/connection.test.js index edb709fddf8..41a4b336005 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -403,6 +403,7 @@ describe('connections:', function() { assert.equal('object', typeof db.options.db); assert.equal('object', typeof db.options.replset); assert.equal('object', typeof db.options.replset.socketOptions); + assert.equal(undefined, db.options.mongos); assert.equal(false, db.options.server.auto_reconnect); assert.equal(2, db.options.server.poolSize); assert.equal(false, db.options.server.slave_ok); @@ -446,6 +447,7 @@ describe('connections:', function() { assert.equal('object', typeof db.options.db); assert.equal('object', typeof db.options.replset); assert.equal('object', typeof db.options.replset.socketOptions); + assert.equal(undefined, db.options.mongos); assert.equal(false, db.options.server.auto_reconnect); assert.equal(3, db.options.server.poolSize); assert.equal(false, db.options.server.slave_ok); @@ -490,6 +492,7 @@ describe('connections:', function() { assert.equal('object', typeof db.options.db); assert.equal('object', typeof db.options.replset); assert.equal('object', typeof db.options.replset.socketOptions); + assert.equal(undefined, db.options.mongos); assert.equal(false, db.options.server.auto_reconnect); assert.equal(2, db.options.server.poolSize); assert.equal(false, db.options.server.slave_ok); @@ -527,6 +530,7 @@ describe('connections:', function() { assert.equal('object', typeof db.options.db); assert.equal('object', typeof db.options.replset); assert.equal('object', typeof db.options.replset.socketOptions); + assert.equal(undefined, db.options.mongos); assert.equal(false, db.options.server.auto_reconnect); assert.equal(80, db.options.db.wtimeoutMS); assert.equal(2, db.options.server.poolSize); @@ -549,6 +553,100 @@ describe('connections:', function() { done(); }); }); + describe('when mongos is passed', function() { + it('works when specifying {mongos: true}', function(done) { + var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2' + + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12' + + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true' + + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true' + + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags=' + + 'dc:ny,rack:1&readPreferenceTags=dc:sf&sslValidate=true'; + + var db = mongoose.createConnection(conn, {mongos: true}); + db.on('error', done); + db.close(); + assert.equal('object', typeof db.options); + assert.equal('object', typeof db.options.server); + assert.equal('object', typeof db.options.server.socketOptions); + assert.equal('object', typeof db.options.db); + assert.equal('object', typeof db.options.replset); + assert.equal('object', typeof db.options.replset.socketOptions); + assert.equal('object', typeof db.options.mongos); + assert.equal(false, db.options.server.auto_reconnect); + assert.equal(2, db.options.server.poolSize); + assert.equal(false, db.options.server.slave_ok); + assert.equal(true, db.options.server.ssl); + assert.equal(true, db.options.replset.ssl); + assert.equal(true, db.options.mongos.ssl); + assert.equal(10, db.options.server.socketOptions.socketTimeoutMS); + assert.equal(10, db.options.replset.socketOptions.socketTimeoutMS); + assert.equal(12, db.options.server.socketOptions.connectTimeoutMS); + assert.equal(12, db.options.replset.socketOptions.connectTimeoutMS); + assert.equal(10, db.options.replset.retries); + assert.equal(5, db.options.replset.reconnectWait); + assert.equal('replworld', db.options.replset.rs_name); + assert.equal(true, db.options.replset.read_secondary); + assert.equal(false, db.options.db.native_parser); + assert.equal(2, db.options.db.w); + assert.equal(true, db.options.db.safe); + assert.equal(true, db.options.db.fsync); + assert.equal(true, db.options.db.journal); + assert.equal(80, db.options.db.wtimeoutMS); + assert.equal('nearest', db.options.db.readPreference); + assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags); + assert.equal(false, db.options.db.forceServerObjectId); + assert.strictEqual(db.options.server.sslValidate, true); + assert.strictEqual(db.options.mongos.sslValidate, true); + done(); + }); + it('works when specifying mongos opts', function(done) { + var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2' + + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12' + + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true' + + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true' + + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags=' + + 'dc:ny,rack:1&readPreferenceTags=dc:sf&sslValidate=true'; + + var db = mongoose.createConnection(conn, {mongos: {w: 3, wtimeoutMS: 80}}); + db.on('error', done); + db.close(); + assert.equal('object', typeof db.options); + assert.equal('object', typeof db.options.server); + assert.equal('object', typeof db.options.server.socketOptions); + assert.equal('object', typeof db.options.db); + assert.equal('object', typeof db.options.replset); + assert.equal('object', typeof db.options.replset.socketOptions); + assert.equal('object', typeof db.options.mongos); + assert.equal(false, db.options.server.auto_reconnect); + assert.equal(2, db.options.server.poolSize); + assert.equal(false, db.options.server.slave_ok); + assert.equal(true, db.options.server.ssl); + assert.equal(true, db.options.replset.ssl); + assert.equal(true, db.options.mongos.ssl); + assert.equal(10, db.options.server.socketOptions.socketTimeoutMS); + assert.equal(10, db.options.replset.socketOptions.socketTimeoutMS); + assert.equal(12, db.options.server.socketOptions.connectTimeoutMS); + assert.equal(12, db.options.replset.socketOptions.connectTimeoutMS); + assert.equal(10, db.options.replset.retries); + assert.equal(5, db.options.replset.reconnectWait); + assert.equal('replworld', db.options.replset.rs_name); + assert.equal(true, db.options.replset.read_secondary); + assert.equal(false, db.options.db.native_parser); + assert.equal(2, db.options.db.w); + assert.equal(true, db.options.db.safe); + assert.equal(true, db.options.db.fsync); + assert.equal(true, db.options.db.journal); + assert.equal(80, db.options.db.wtimeoutMS); + assert.equal('nearest', db.options.db.readPreference); + assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags); + assert.equal(false, db.options.db.forceServerObjectId); + assert.strictEqual(db.options.server.sslValidate, true); + assert.strictEqual(db.options.mongos.sslValidate, true); + assert.equal(db.options.mongos.w, 3); + assert.equal(db.options.mongos.wtimeoutMS, 80); + done(); + }); + }); }); describe('missing protocols', function() { From e0326ef06d6edaeb779dfba5c03441105b980561 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 12:47:22 -0700 Subject: [PATCH 0429/2240] refactor(test): reuse connection for test --- test/model.populate.test.js | 80 ++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index c1987c40599..0b59f5e4f3a 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -2900,47 +2900,6 @@ describe('model: populate:', function() { }); }); - it('maps results back to correct document (gh-1444)', function(done) { - var db = start(); - - var articleSchema = new Schema({ - body: String, - mediaAttach: {type: Schema.ObjectId, ref: '1444-Media'}, - author: String - }); - var Article = db.model('1444-Article', articleSchema); - - var mediaSchema = new Schema({ - filename: String - }); - var Media = db.model('1444-Media', mediaSchema); - - Media.create({filename: 'one'}, function(err, media) { - assert.ifError(err); - - Article.create( - {body: 'body1', author: 'a'} - , {body: 'body2', author: 'a', mediaAttach: media._id} - , {body: 'body3', author: 'a'}, function(err) { - if (err) { - return done(err); - } - - Article.find().populate('mediaAttach').exec(function(err, docs) { - db.close(); - assert.ifError(err); - - var a2 = docs.filter(function(d) { - return d.body === 'body2'; - })[0]; - assert.equal(a2.mediaAttach.id, media.id); - - done(); - }); - }); - }); - }); - describe('DynRef', function() { var db; var Review; @@ -3117,6 +3076,45 @@ describe('model: populate:', function() { db.close(done); }); + it('maps results back to correct document (gh-1444)', function(done) { + var articleSchema = new Schema({ + body: String, + mediaAttach: {type: Schema.ObjectId, ref: '1444-Media'}, + author: String + }); + var Article = db.model('1444-Article', articleSchema); + + var mediaSchema = new Schema({ + filename: String + }); + var Media = db.model('1444-Media', mediaSchema); + + Media.create({filename: 'one'}, function(err, media) { + assert.ifError(err); + + Article.create( + {body: 'body1', author: 'a'} + , {body: 'body2', author: 'a', mediaAttach: media._id} + , {body: 'body3', author: 'a'}, function(err) { + if (err) { + return done(err); + } + + Article.find().populate('mediaAttach').exec(function(err, docs) { + db.close(); + assert.ifError(err); + + var a2 = docs.filter(function(d) { + return d.body === 'body2'; + })[0]; + assert.equal(a2.mediaAttach.id, media.id); + + done(); + }); + }); + }); + }); + it('handles skip', function(done) { var movieSchema = new Schema({}); var categorySchema = new Schema({movies: [{type: ObjectId, ref: 'gh-2252-1'}]}); From 4e706d9a3db027b2a020a4157d2a42dbab609201 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 13:06:01 -0700 Subject: [PATCH 0430/2240] test(populate): repro #3992 --- test/model.populate.test.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 0b59f5e4f3a..0a8bb62ca5f 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3101,7 +3101,6 @@ describe('model: populate:', function() { } Article.find().populate('mediaAttach').exec(function(err, docs) { - db.close(); assert.ifError(err); var a2 = docs.filter(function(d) { @@ -3280,6 +3279,33 @@ describe('model: populate:', function() { } }); + it('set to obj w/ same id doesnt mark modified (gh-3992)', function(done) { + var personSchema = new Schema({ + name: { type: String } + }); + var jobSchema = new Schema({ + title: String, + person: { type: Schema.Types.ObjectId, ref: 'gh3992' } + }); + + var Person = db.model('gh3992', personSchema); + var Job = db.model('gh3992_0', jobSchema); + + Person.create({ name: 'Val' }, function(error, person) { + assert.ifError(error); + var job = { title: 'Engineer', person: person._id }; + Job.create(job, function(error, job) { + assert.ifError(error); + Job.findById(job._id, function(error, job) { + assert.ifError(error); + job.person = person; + assert.ok(!job.isModified('person')); + done(); + }); + }); + }); + }); + it('deep populate single -> array (gh-3904)', function(done) { var personSchema = new Schema({ name: { type: String } From 8e2561fb3d78c70902faf8e3c75162b34fad0d80 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 13:06:07 -0700 Subject: [PATCH 0431/2240] fix(populate): don't mark populated path as modified if setting to the same field Fix #3992 --- lib/document.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/document.js b/lib/document.js index ebf290a9bc8..9488391aa79 100644 --- a/lib/document.js +++ b/lib/document.js @@ -724,6 +724,14 @@ Document.prototype.$__shouldModify = function(pathToMark, path, constructing, pa return false; } + // gh-3992: if setting a populated field to a doc, don't mark modified + // if they have the same _id + if (this.populated(path) && + val instanceof Document && + deepEqual(val._id, priorVal)) { + return false; + } + if (!deepEqual(val, priorVal || this.get(path))) { return true; } From d349401c07a395ffc45ad3b363463e3f6ec7a0b1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 13:35:57 -0700 Subject: [PATCH 0432/2240] test(document): repro #4001 --- test/document.test.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index eabd4b3aa8d..393a8d35540 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2540,5 +2540,38 @@ describe('document', function() { }); }); }); + + it('inspect inherits schema options (gh-4001)', function(done) { + var opts = { + toObject: { virtuals: true }, + toJSON: { virtuals: true } + }; + var taskSchema = mongoose.Schema({ + name: { + type: String, + required: true + } + }, opts); + + taskSchema.virtual('title'). + get(function() { + return this.name; + }). + set(function(title) { + this.name = title; + }); + + var Task = db.model('gh4001', taskSchema); + + var doc = { name: 'task1', title: 'task999' }; + Task.collection.insert(doc, function(error) { + assert.ifError(error); + Task.findById(doc._id, function(error, doc) { + assert.ifError(error); + assert.equal(doc.inspect().title, 'task1'); + done(); + }); + }); + }); }); }); From 48f9bbcf2530b220f1cea95f82f49921d02f2e75 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 13:39:01 -0700 Subject: [PATCH 0433/2240] fix(document): inspect inherits schema options Fix #4001 --- lib/document.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/document.js b/lib/document.js index 9488391aa79..f2f5c026133 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1898,14 +1898,14 @@ Document.prototype.$toObject = function(options, json) { (options && options._useSchemaOptions)) { if (json) { options = this.schema.options.toJSON ? - clone(this.schema.options.toJSON) : - {}; + clone(this.schema.options.toJSON) : + {}; options.json = true; options._useSchemaOptions = true; } else { options = this.schema.options.toObject ? - clone(this.schema.options.toObject) : - {}; + clone(this.schema.options.toObject) : + {}; options.json = false; options._useSchemaOptions = true; } @@ -2187,7 +2187,16 @@ Document.prototype.toJSON = function(options) { */ Document.prototype.inspect = function(options) { - var opts = options && utils.getFunctionName(options.constructor) === 'Object' ? options : {}; + var isPOJO = options && + utils.getFunctionName(options.constructor) === 'Object'; + var opts; + if (isPOJO) { + opts = options; + } else if (this.schema.options.toObject) { + opts = clone(this.schema.options.toObject); + } else { + opts = {}; + } opts.minimize = false; opts.retainKeyOrder = true; return this.toObject(opts); From d37ce5f88f5efb9518f73ce33b942a4bf9eb2841 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 14:04:21 -0700 Subject: [PATCH 0434/2240] test(document): repro #4008 --- test/document.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 393a8d35540..124b58b08c4 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2573,5 +2573,26 @@ describe('document', function() { }); }); }); + + it('doesnt skipId for single nested subdocs (gh-4008)', function(done) { + var childSchema = new Schema({ + name: String + }); + + var parentSchema = new Schema({ + child: childSchema + }); + + var Parent = db.model('gh4008', parentSchema); + + Parent.create({ child: { name: 'My child' } }, function(error, doc) { + assert.ifError(error); + Parent.collection.findOne({ _id: doc._id }, function(error, doc) { + assert.ifError(error); + assert.ok(doc.child._id); + done(); + }); + }); + }); }); }); From 46b8a702eeb4e32145839ba4c4e167ace21b9286 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 14:06:24 -0700 Subject: [PATCH 0435/2240] fix(types): single nested docs dont treat parent doc as skipId param Fix #4008 --- lib/types/subdocument.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index ebe5b4cfd36..83953c98e07 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -10,9 +10,9 @@ module.exports = Subdocument; * @api private */ -function Subdocument() { +function Subdocument(value, fields) { this.$isSingleNested = true; - Document.apply(this, arguments); + Document.call(this, value, fields); } Subdocument.prototype = Object.create(Document.prototype); From 80dc610611e5a8ab29bb50e19110bc07cc9c6dc5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 14:22:07 -0700 Subject: [PATCH 0436/2240] refactor(test): reuse connections across aggregate tests --- test/aggregate.test.js | 330 ++++++++++++++++++----------------------- 1 file changed, 147 insertions(+), 183 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 938df2c2efd..6d7b9ec4fcc 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -43,12 +43,6 @@ function setupData(callback) { }); } -function clearData(db, callback) { - db.model('Employee').remove(function() { - db.close(callback); - }); -} - /** * Test. */ @@ -384,164 +378,143 @@ describe('aggregate: ', function() { }); describe('exec', function() { + var db; + + before(function(done) { + setupData(function(_db) { + db = _db; + done(); + }); + }); + + after(function(done) { + db.close(done); + }); + it('project', function(done) { var aggregate = new Aggregate(); - setupData(function(db) { - aggregate - .model(db.model('Employee')) - .project({sal: 1, sal_k: {$divide: ['$sal', 1000]}}) - .exec(function(err, docs) { - assert.ifError(err); - docs.forEach(function(doc) { - assert.equal(doc.sal / 1000, doc.sal_k); - }); - - clearData(db, function() { - done(); - }); - }); - }); + aggregate. + model(db.model('Employee')). + project({sal: 1, sal_k: {$divide: ['$sal', 1000]}}). + exec(function(err, docs) { + assert.ifError(err); + docs.forEach(function(doc) { + assert.equal(doc.sal / 1000, doc.sal_k); + }); + + done(); + }); }); it('group', function(done) { var aggregate = new Aggregate(); - setupData(function(db) { - aggregate - .model(db.model('Employee')) - .group({_id: '$dept'}) - .exec(function(err, docs) { - var depts; - - assert.ifError(err); - assert.equal(docs.length, 2); - - depts = docs.map(function(doc) { - return doc._id; - }); - assert.notEqual(depts.indexOf('sales'), -1); - assert.notEqual(depts.indexOf('r&d'), -1); - - clearData(db, function() { - done(); - }); - }); - }); + aggregate. + model(db.model('Employee')). + group({_id: '$dept'}). + exec(function(err, docs) { + var depts; + assert.ifError(err); + assert.equal(docs.length, 2); + + depts = docs.map(function(doc) { + return doc._id; + }); + assert.notEqual(depts.indexOf('sales'), -1); + assert.notEqual(depts.indexOf('r&d'), -1); + done(); + }); }); it('skip', function(done) { var aggregate = new Aggregate(); - setupData(function(db) { - aggregate - .model(db.model('Employee')) - .skip(1) - .exec(function(err, docs) { - assert.ifError(err); - assert.equal(docs.length, 3); - - clearData(db, function() { - done(); - }); - }); - }); + aggregate. + model(db.model('Employee')). + skip(1). + exec(function(err, docs) { + assert.ifError(err); + assert.equal(docs.length, 3); + + done(); + }); }); it('limit', function(done) { var aggregate = new Aggregate(); - setupData(function(db) { - aggregate - .model(db.model('Employee')) - .limit(3) - .exec(function(err, docs) { - assert.ifError(err); - assert.equal(docs.length, 3); - - clearData(db, function() { - done(); - }); - }); - }); + aggregate. + model(db.model('Employee')). + limit(3). + exec(function(err, docs) { + assert.ifError(err); + assert.equal(docs.length, 3); + + done(); + }); }); it('unwind', function(done) { var aggregate = new Aggregate(); - setupData(function(db) { - aggregate - .model(db.model('Employee')) - .unwind('customers') - .exec(function(err, docs) { - assert.ifError(err); - assert.equal(docs.length, 5); - - clearData(db, function() { - done(); - }); - }); - }); + aggregate. + model(db.model('Employee')). + unwind('customers'). + exec(function(err, docs) { + assert.ifError(err); + assert.equal(docs.length, 5); + + done(); + }); }); it('match', function(done) { var aggregate = new Aggregate(); - setupData(function(db) { - aggregate - .model(db.model('Employee')) - .match({sal: {$gt: 15000}}) - .exec(function(err, docs) { - assert.ifError(err); - assert.equal(docs.length, 1); - - clearData(db, function() { - done(); - }); - }); - }); + aggregate. + model(db.model('Employee')). + match({sal: {$gt: 15000}}). + exec(function(err, docs) { + assert.ifError(err); + assert.equal(docs.length, 1); + + done(); + }); }); it('sort', function(done) { var aggregate = new Aggregate(); - setupData(function(db) { - aggregate - .model(db.model('Employee')) - .sort('sal') - .exec(function(err, docs) { - assert.ifError(err); - assert.equal(docs[0].sal, 14000); - - clearData(db, function() { - done(); - }); - }); - }); + aggregate. + model(db.model('Employee')). + sort('sal'). + exec(function(err, docs) { + assert.ifError(err); + assert.equal(docs[0].sal, 14000); + + done(); + }); }); it('complex pipeline', function(done) { var aggregate = new Aggregate(); - setupData(function(db) { - aggregate - .model(db.model('Employee')) - .match({sal: {$lt: 16000}}) - .unwind('customers') - .project({emp: '$name', cust: '$customers'}) - .sort('-cust') - .skip(2) - .exec(function(err, docs) { - assert.ifError(err); - assert.equal(docs.length, 1); - assert.equal(docs[0].cust, 'Gary'); - assert.equal(docs[0].emp, 'Bob'); - - clearData(db, function() { - done(); - }); - }); - }); + aggregate. + model(db.model('Employee')). + match({sal: {$lt: 16000}}). + unwind('customers'). + project({emp: '$name', cust: '$customers'}). + sort('-cust'). + skip(2). + exec(function(err, docs) { + assert.ifError(err); + assert.equal(docs.length, 1); + assert.equal(docs[0].cust, 'Gary'); + assert.equal(docs[0].emp, 'Bob'); + + done(); + }); }); it('explain()', function(done) { @@ -557,8 +530,7 @@ describe('aggregate: ', function() { return; } - setupData(function(db) { - aggregate. + aggregate. model(db.model('Employee')). match({sal: {$lt: 16000}}). explain(function(err1, output) { @@ -567,26 +539,22 @@ describe('aggregate: ', function() { // make sure we got explain output assert.ok(output.stages); - clearData(db, function() { - done(); - }); + done(); }); - }); }); }); describe('error when empty pipeline', function() { it('without a callback', function(done) { var agg = new Aggregate; - setupData(function(db) { - agg.model(db.model('Employee')); - var promise = agg.exec(); - assert.ok(promise instanceof mongoose.Promise); - promise.onResolve(function(err) { - assert.ok(err); - assert.equal(err.message, 'Aggregate has empty pipeline'); - done(); - }); + + agg.model(db.model('Employee')); + var promise = agg.exec(); + assert.ok(promise instanceof mongoose.Promise); + promise.onResolve(function(err) { + assert.ok(err); + assert.equal(err.message, 'Aggregate has empty pipeline'); + done(); }); }); @@ -594,16 +562,14 @@ describe('aggregate: ', function() { var aggregate = new Aggregate(); var callback; - setupData(function(db) { - aggregate.model(db.model('Employee')); - callback = function(err) { - assert.ok(err); - assert.equal(err.message, 'Aggregate has empty pipeline'); - done(); - }; + aggregate.model(db.model('Employee')); + callback = function(err) { + assert.ok(err); + assert.equal(err.message, 'Aggregate has empty pipeline'); + done(); + }; - aggregate.exec(callback); - }); + aggregate.exec(callback); }); }); @@ -621,34 +587,32 @@ describe('aggregate: ', function() { }); it('handles aggregation options', function(done) { - setupData(function(db) { - start.mongodVersion(function(err, version) { - if (err) { - throw err; - } - var mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6); - - var m = db.model('Employee'); - var match = {$match: {sal: {$gt: 15000}}}; - var pref = 'primaryPreferred'; - var aggregate = m.aggregate(match).read(pref); - if (mongo26_or_greater) { - aggregate.allowDiskUse(true); - } + start.mongodVersion(function(err, version) { + if (err) { + throw err; + } + var mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6); + + var m = db.model('Employee'); + var match = {$match: {sal: {$gt: 15000}}}; + var pref = 'primaryPreferred'; + var aggregate = m.aggregate(match).read(pref); + if (mongo26_or_greater) { + aggregate.allowDiskUse(true); + } - assert.equal(aggregate.options.readPreference.mode, pref); - if (mongo26_or_greater) { - assert.equal(aggregate.options.allowDiskUse, true); - } + assert.equal(aggregate.options.readPreference.mode, pref); + if (mongo26_or_greater) { + assert.equal(aggregate.options.allowDiskUse, true); + } - aggregate - .exec(function(err, docs) { - assert.ifError(err); - assert.equal(1, docs.length); - assert.equal(docs[0].sal, 18000); - clearData(db, done); - }); - }); + aggregate. + exec(function(err, docs) { + assert.ifError(err); + assert.equal(1, docs.length); + assert.equal(docs[0].sal, 18000); + done(); + }); }); }); }); @@ -659,13 +623,13 @@ describe('aggregate: ', function() { var MyModel = db.model('gh3160', {name: String}); MyModel. - aggregate([{$match: {name: 'test'}}]). - cursor({async: true}). - exec(function(error, cursor) { - assert.ifError(error); - assert.ok(cursor); - db.close(done); - }); + aggregate([{$match: {name: 'test'}}]). + cursor({async: true}). + exec(function(error, cursor) { + assert.ifError(error); + assert.ok(cursor); + db.close(done); + }); }); it('cursor() without options (gh-3855)', function(done) { From 31e281084070624499315ca3db755a3f1d81a31b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 14:34:43 -0700 Subject: [PATCH 0437/2240] fix: make test async --- test/docs/defaults.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/docs/defaults.test.js b/test/docs/defaults.test.js index d6dd1784964..ded1e0a43be 100644 --- a/test/docs/defaults.test.js +++ b/test/docs/defaults.test.js @@ -17,7 +17,7 @@ describe('defaults docs', function () { * Your schemas can define default values for certain paths. If you create * a new document without that path set, the default will kick in. */ - it('Declaring defaults in your schema', function() { + it('Declaring defaults in your schema', function(done) { var schema = new Schema({ name: String, role: { type: String, default: 'guitarist' } From ad313da0b031ab9102b5667cec772aa915ae7305 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 14:52:22 -0700 Subject: [PATCH 0438/2240] test(query): repro #4023 --- test/model.findOneAndUpdate.test.js | 73 ++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 54a4124e4c7..79ef364d685 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1455,23 +1455,6 @@ describe('model: findByIdAndUpdate:', function() { }); }); - it('passes raw result as 3rd param (gh-3173)', function(done) { - var db = start(); - - var testSchema = new mongoose.Schema({ - test: String - }); - - var TestModel = db.model('gh3173', testSchema); - - TestModel.findOneAndUpdate({}, {$set: {test: 'abc'}}, {upsert: true, new: true, passRawResult: true}). - exec(function(error, doc, res) { - assert.ifError(error); - assert.ok(res); - assert.ok(res.ok); - db.close(done); - }); - }); it('handles nested cast errors (gh-3468)', function(done) { var db = start(); @@ -1555,4 +1538,60 @@ describe('model: findByIdAndUpdate:', function() { }); }); }); + + describe('bug fixes', function() { + var db; + + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('passes raw result as 3rd param (gh-3173)', function(done) { + var db = start(); + + var testSchema = new mongoose.Schema({ + test: String + }); + + var TestModel = db.model('gh3173', testSchema); + var options = { upsert: true, new: true, passRawResult: true }; + var update = { $set: { test: 'abc' } }; + + TestModel.findOneAndUpdate({}, update, options). + exec(function(error, doc, res) { + assert.ifError(error); + assert.ok(res); + assert.ok(res.ok); + + db.close(done); + }); + }); + + it('raw result as 3rd param w/ no result (gh-4023)', function(done) { + var db = start(); + + var testSchema = new mongoose.Schema({ + test: String + }); + + var TestModel = db.model('gh4023', testSchema); + var options = { upsert: true, new: false, passRawResult: true }; + var update = { $set: { test: 'abc' } }; + + TestModel.findOneAndUpdate({}, update, options). + exec(function(error, doc, res) { + assert.ifError(error); + assert.ok(res); + assert.ok(res.ok); + + options.new = false; + + db.close(done); + }); + }); + }); }); From 7bb0130050eeeab2b71db60a9c7dc9116b48c898 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 14:52:28 -0700 Subject: [PATCH 0439/2240] fix(query): handle passRawResult when zero results Fix #4023 --- lib/query.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/query.js b/lib/query.js index ea7b6edd33d..43b7477d6e8 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1792,6 +1792,9 @@ Query.prototype._findAndModify = function(type, callback) { } if (!doc || (utils.isObject(doc) && Object.keys(doc).length === 0)) { + if (opts.passRawResult) { + return callback(null, null, res); + } return callback(null, null); } From 201b175b26a50766567e84f4be9293b38105a9c5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 15:02:36 -0700 Subject: [PATCH 0440/2240] test(populate): repro #4022 --- test/model.populate.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 0a8bb62ca5f..f51ac4cdf29 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -1555,7 +1555,7 @@ describe('model: populate:', function() { var opts = { path: 'author.friends', select: 'name', - options: {limit: 1} + options: { limit: 1 } }; BlogPost.populate(docs, opts, function(err, docs) { @@ -1563,6 +1563,7 @@ describe('model: populate:', function() { assert.equal(2, docs.length); assert.equal(1, docs[0].author.friends.length); assert.equal(1, docs[1].author.friends.length); + assert.equal(opts.options.limit, 1); db.close(done); }); }); From 45471ad0bc9b20da80f935c6aa95a32907569320 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 15:02:40 -0700 Subject: [PATCH 0441/2240] fix(populate): clone options before modifying Fix #4022 --- lib/utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utils.js b/lib/utils.js index bb544743f95..677d350166c 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -606,6 +606,7 @@ exports.populate = function populate(path, select, model, match, options, subPop var ret = []; var paths = path.split(' '); + options = exports.clone(options, { retainKeyOrder: true }); for (var i = 0; i < paths.length; ++i) { ret.push(new PopulateOptions(paths[i], select, match, options, model, subPopulate)); } From b1758ebfa23768a160e3507e2e4975f91a094dbd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 15:06:38 -0700 Subject: [PATCH 0442/2240] chore: upgrade mongodb -> 2.1.14 Fix #4036 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b16d74e7977..ddbd39ddfa1 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,10 @@ "license": "MIT", "dependencies": { "async": "1.5.2", - "bson": "0.4.21", + "bson": "~0.4.21", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.1.10", + "mongodb": "2.1.14", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.10.0", From 3cc6aa344d53f35644717766ca7a02cddd9bafe3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Apr 2016 15:11:52 -0700 Subject: [PATCH 0443/2240] style(test): kill off some more commas --- test/query.test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index c89cabbea1a..402045dfadc 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2,13 +2,13 @@ * Module dependencies. */ -var start = require('./common'), - mongoose = start.mongoose, - DocumentObjectId = mongoose.Types.ObjectId, - Schema = mongoose.Schema, - assert = require('power-assert'), - random = require('../lib/utils').random, - Query = require('../lib/query'); +var start = require('./common'); +var mongoose = start.mongoose; +var DocumentObjectId = mongoose.Types.ObjectId; +var Schema = mongoose.Schema; +var assert = require('power-assert'); +var random = require('../lib/utils').random; +var Query = require('../lib/query'); var Comment = new Schema({ text: String From 1974402404817c2c54cbe4e6503b5d9b6edf910c Mon Sep 17 00:00:00 2001 From: apimenov Date: Sun, 3 Apr 2016 13:49:13 +0300 Subject: [PATCH 0444/2240] Promise returning on aggregate call. --- lib/aggregate.js | 24 ++++++++++++++++++++++++ lib/model.js | 5 ++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index fd2c2fcf71b..63d7935126b 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -552,6 +552,30 @@ Aggregate.prototype.exec = function(callback) { }); }; +/** + * Provides promise for aggregate. + * + * ####Example: + * + * Model.aggregate(..).then(successCallback, errorCallback); + * + * @see Promise #promise_Promise + * @param {Function} [resolve] successCallback + * @param {Function} [reject] errorCallback + * @return {Promise} + */ +Aggregate.prototype.then = function(resolve, reject) { + var _this = this; + var Promise = PromiseProvider.get(); + var promise = new Promise.ES6(function(success, error) { + _this.exec(function(err, val) { + if (err) error(err); + else success(val); + }); + }); + return promise.then(resolve, reject); +}; + /*! * Helpers */ diff --git a/lib/model.js b/lib/model.js index aa834654251..7e8a598f312 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2263,12 +2263,11 @@ Model.aggregate = function aggregate() { aggregate.model(this); - //TODO find proper way to check that we will need call done() - if (typeof callback === 'undefined' && arguments.callee.caller.toString().indexOf(").then") == -1) { + if (typeof callback === 'undefined') { return aggregate; } - return aggregate.exec(callback); + aggregate.exec(callback); }; /** From 7ea48a5e46e95a7da17595f02046131e46e6bc11 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Apr 2016 09:45:53 -0700 Subject: [PATCH 0445/2240] chore: release 4.4.11 --- History.md | 16 +++++++++++++ bin/mongoose.js | 63 ++++++++++++++++++++++++++++++++++++++----------- package.json | 2 +- 3 files changed, 66 insertions(+), 15 deletions(-) diff --git a/History.md b/History.md index cf4956496cb..f2e42700611 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,19 @@ +4.4.11 / 2016-04-03 +=================== + * fix: upgrade to mongodb driver 2.1.14 #4036 #4030 #3945 + * fix(connection): allow connecting with { mongos: true } to handle query params #4032 [burtonjc](https://github.com/burtonjc) + * docs(connection): add autoIndex example #4026 [tilleps](https://github.com/tilleps) + * fix(query): handle passRawResult option when zero results #4023 + * fix(populate): clone options before modifying #4022 + * docs: add missing whitespace #4019 [chenxsan](https://github.com/chenxsan) + * chore: upgrade to ESLint 2.4.0 #4015 [ChristianMurphy](https://github.com/ChristianMurphy) + * fix(types): single nested subdocs get ids by default #4008 + * chore(project): add dependency status badge #4007 [Maheshkumar-Kakade](http://github.com/Maheshkumar-Kakade) + * fix: make sure timestamps don't trigger unnecessary updates #4005 #3991 [tommarien](https://github.com/tommarien) + * fix(document): inspect inherits schema options #4001 + * fix(populate): don't mark populated path as modified if setting to object w/ same id #3992 + * fix(document): support kind argument to invalidate #3965 + 4.4.10 / 2016-03-24 =================== * fix(document): copy isNew when copying a document #3982 diff --git a/bin/mongoose.js b/bin/mongoose.js index 32ade1ef358..70a721be094 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -1168,6 +1168,14 @@ Document.prototype.$__shouldModify = function(pathToMark, path, constructing, pa return false; } + // gh-3992: if setting a populated field to a doc, don't mark modified + // if they have the same _id + if (this.populated(path) && + val instanceof Document && + deepEqual(val._id, priorVal)) { + return false; + } + if (!deepEqual(val, priorVal || this.get(path))) { return true; } @@ -1773,11 +1781,12 @@ Document.prototype.validateSync = function(pathsToValidate) { * @param {String} path the field to invalidate * @param {String|Error} errorMsg the error which states the reason `path` was invalid * @param {Object|String|Number|any} value optional invalid value + * @param {String} [kind] optional `kind` property for the error * @return {ValidationError} the current ValidationError, with all currently invalidated paths * @api public */ -Document.prototype.invalidate = function(path, err, val) { +Document.prototype.invalidate = function(path, err, val, kind) { if (!this.$__.validationError) { this.$__.validationError = new ValidationError(this); } @@ -1790,7 +1799,7 @@ Document.prototype.invalidate = function(path, err, val) { err = new ValidatorError({ path: path, message: err, - type: 'user defined', + type: kind || 'user defined', value: val }); } @@ -2333,14 +2342,14 @@ Document.prototype.$toObject = function(options, json) { (options && options._useSchemaOptions)) { if (json) { options = this.schema.options.toJSON ? - clone(this.schema.options.toJSON) : - {}; + clone(this.schema.options.toJSON) : + {}; options.json = true; options._useSchemaOptions = true; } else { options = this.schema.options.toObject ? - clone(this.schema.options.toObject) : - {}; + clone(this.schema.options.toObject) : + {}; options.json = false; options._useSchemaOptions = true; } @@ -2622,7 +2631,16 @@ Document.prototype.toJSON = function(options) { */ Document.prototype.inspect = function(options) { - var opts = options && utils.getFunctionName(options.constructor) === 'Object' ? options : {}; + var isPOJO = options && + utils.getFunctionName(options.constructor) === 'Object'; + var opts; + if (isPOJO) { + opts = options; + } else if (this.schema.options.toObject) { + opts = clone(this.schema.options.toObject); + } else { + opts = {}; + } opts.minimize = false; opts.retainKeyOrder = true; return this.toObject(opts); @@ -4566,7 +4584,9 @@ Schema.prototype.setupTimestamp = function(timestamps) { this[createdAt] = auto_id ? this._id.getTimestamp() : defaultTimestamp; } - this[updatedAt] = this.isNew ? this[createdAt] : defaultTimestamp; + if (this.isNew || this.isModified()) { + this[updatedAt] = this.isNew ? this[createdAt] : defaultTimestamp; + } next(); }); @@ -10605,9 +10625,9 @@ module.exports = Subdocument; * @api private */ -function Subdocument() { +function Subdocument(value, fields) { this.$isSingleNested = true; - Document.apply(this, arguments); + Document.call(this, value, fields); } Subdocument.prototype = Object.create(Document.prototype); @@ -11328,6 +11348,7 @@ exports.populate = function populate(path, select, model, match, options, subPop var ret = []; var paths = path.split(' '); + options = exports.clone(options, { retainKeyOrder: true }); for (var i = 0; i < paths.length; ++i) { ret.push(new PopulateOptions(paths[i], select, match, options, model, subPopulate)); } @@ -13426,11 +13447,15 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; }(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) },{}],53:[function(require,module,exports){ +(function (global){ /** * Module dependencies. * @ignore */ -if(typeof window === 'undefined') { + +// Test if we're in Node via presence of "global" not absence of "window" +// to support hybrid environments like Electron +if(typeof global !== 'undefined') { var Buffer = require('buffer').Buffer; // TODO just use global Buffer } @@ -13771,6 +13796,7 @@ Binary.SUBTYPE_USER_DEFINED = 128; module.exports = Binary; module.exports.Binary = Binary; +}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"buffer":71}],54:[function(require,module,exports){ (function (process){ /** @@ -15972,6 +15998,9 @@ ObjectID.isValid = function isValid(id) { if(typeof id == 'string') { return id.length == 12 || (id.length == 24 && checkForHexRegExp.test(id)); } + if(id instanceof ObjectID) { + return true; + } return false; }; @@ -16334,7 +16363,7 @@ var deserialize = function(buffer, options, isArray) { options = options == null ? {} : options; var index = options && options.index ? options.index : 0; // Read the document size - var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var size = buffer[index] | buffer[index+1] << 8 | buffer[index+2] << 16 | buffer[index+3] << 24; // Ensure buffer is valid size if(size < 5 || buffer.length < size) { @@ -16342,12 +16371,12 @@ var deserialize = function(buffer, options, isArray) { } // Illegal end value - if(buffer[size - 1] != 0) { + if(buffer[index + size - 1] != 0) { throw new Error("One object, sized correctly, with a spot for an EOO, but the EOO isn't 0x00"); } // Start deserializtion - return deserializeObject(buffer, index - 4, options, isArray); + return deserializeObject(buffer, index, options, isArray); } var deserializeObject = function(buffer, index, options, isArray) { @@ -16707,6 +16736,12 @@ BSON.BSON_DATA_ARRAY = 4; * @classconstant BSON_DATA_BINARY **/ BSON.BSON_DATA_BINARY = 5; +/** + * Binary BSON Type + * + * @classconstant BSON_DATA_UNDEFINED + **/ +BSON.BSON_DATA_UNDEFINED = 7; /** * ObjectID BSON Type * diff --git a/package.json b/package.json index ddbd39ddfa1..6a6627260a8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.11-pre", + "version": "4.4.11", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From da3272c2bb14f6cdd5cd318351270191f8d2db49 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Apr 2016 10:19:42 -0700 Subject: [PATCH 0446/2240] chore: now working on 4.4.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6a6627260a8..b474e72114c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.11", + "version": "4.4.12-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From da46f56c77331d58975561153ec8017feac3af78 Mon Sep 17 00:00:00 2001 From: apimenov Date: Thu, 17 Mar 2016 16:03:59 +0300 Subject: [PATCH 0447/2240] Hack for backward compatibility, see #3946 --- lib/aggregate.js | 2 +- lib/model.js | 5 +++-- test/model.aggregate.test.js | 13 +++++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index fd2c2fcf71b..522728d8144 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -547,7 +547,7 @@ Aggregate.prototype.exec = function(callback) { if (callback) { callback(null, result); } - resolve(result); + resolve(null,result); }); }); }; diff --git a/lib/model.js b/lib/model.js index bd15001caaf..b258dd549cb 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2210,7 +2210,7 @@ Model.geoNear = function(near, options, callback) { /** * Performs [aggregations](http://docs.mongodb.org/manual/applications/aggregation/) on the models collection. * - * If a `callback` is passed, the `aggregate` is executed. If a callback is not passed, the `aggregate` itself is returned. + * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned. * * ####Example: * @@ -2263,7 +2263,8 @@ Model.aggregate = function aggregate() { aggregate.model(this); - if (typeof callback === 'undefined') { + //TODO find proper way to check that we will need call done() + if (typeof callback === 'undefined' && arguments.callee.caller.toString().indexOf(").then") == -1) { return aggregate; } diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js index 6c3b3343803..36debea1f9e 100644 --- a/test/model.aggregate.test.js +++ b/test/model.aggregate.test.js @@ -73,6 +73,19 @@ describe('model aggregate', function() { }); }); + it('should return promise', function(done) { + this.timeout(4000); + + A.aggregate(group, project).then( function(err, res) { + assert.ifError(err); + assert.ok(res); + assert.equal(1, res.length); + assert.ok('maxAge' in res[0]); + assert.equal(maxAge, res[0].maxAge); + done(); + }); + }); + it('with arrays', function(done) { this.timeout(4000); From 5e12c6622eaff7b7bdddcf236b16f1cbdb91cdad Mon Sep 17 00:00:00 2001 From: apimenov Date: Thu, 17 Mar 2016 16:34:01 +0300 Subject: [PATCH 0448/2240] Correct args order passing to resolve #3946 . --- lib/aggregate.js | 2 +- test/model.aggregate.test.js | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 522728d8144..fd2c2fcf71b 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -547,7 +547,7 @@ Aggregate.prototype.exec = function(callback) { if (callback) { callback(null, result); } - resolve(null,result); + resolve(result); }); }); }; diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js index 36debea1f9e..8dba2a8cd99 100644 --- a/test/model.aggregate.test.js +++ b/test/model.aggregate.test.js @@ -73,11 +73,10 @@ describe('model aggregate', function() { }); }); - it('should return promise', function(done) { + it('when return promise', function(done) { this.timeout(4000); - A.aggregate(group, project).then( function(err, res) { - assert.ifError(err); + A.aggregate(group, project).then( function(res) { assert.ok(res); assert.equal(1, res.length); assert.ok('maxAge' in res[0]); From 7dbb059740cd2a486d15db47946bc960ef26209a Mon Sep 17 00:00:00 2001 From: apimenov Date: Sun, 3 Apr 2016 13:49:13 +0300 Subject: [PATCH 0449/2240] Promise returning on aggregate call. --- lib/aggregate.js | 24 ++++++++++++++++++++++++ lib/model.js | 5 ++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index fd2c2fcf71b..63d7935126b 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -552,6 +552,30 @@ Aggregate.prototype.exec = function(callback) { }); }; +/** + * Provides promise for aggregate. + * + * ####Example: + * + * Model.aggregate(..).then(successCallback, errorCallback); + * + * @see Promise #promise_Promise + * @param {Function} [resolve] successCallback + * @param {Function} [reject] errorCallback + * @return {Promise} + */ +Aggregate.prototype.then = function(resolve, reject) { + var _this = this; + var Promise = PromiseProvider.get(); + var promise = new Promise.ES6(function(success, error) { + _this.exec(function(err, val) { + if (err) error(err); + else success(val); + }); + }); + return promise.then(resolve, reject); +}; + /*! * Helpers */ diff --git a/lib/model.js b/lib/model.js index b258dd549cb..157b6473e32 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2263,12 +2263,11 @@ Model.aggregate = function aggregate() { aggregate.model(this); - //TODO find proper way to check that we will need call done() - if (typeof callback === 'undefined' && arguments.callee.caller.toString().indexOf(").then") == -1) { + if (typeof callback === 'undefined') { return aggregate; } - return aggregate.exec(callback); + aggregate.exec(callback); }; /** From dc488c5829f4ddebb2d5f8a8092b9a81b267a800 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 4 Apr 2016 13:34:45 -0700 Subject: [PATCH 0450/2240] docs(validation): move update validator tests to top level --- test/docs/validation.test.js | 257 +++++++++++++++++------------------ 1 file changed, 127 insertions(+), 130 deletions(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 3716d3d7224..66506f1fd9d 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -225,145 +225,142 @@ describe('validation docs', function() { * supports validation for `update()` and `findOneAndUpdate()` operations. * In Mongoose 4.x, update validators are off by default - you need to specify * the `runValidators` option. + * + * To turn on update validators, set the `runValidators` option for + * `update()` or `findOneAndUpdate()`. Be careful: update validators + * are off by default because they have several caveats. + */ + it('Update Validators', function(done) { + var toySchema = new Schema({ + color: String, + name: String + }); + + var Toy = db.model('Toys', toySchema); + + Toy.schema.path('color').validate(function (value) { + return /blue|green|white|red|orange|periwinkle/i.test(value); + }, 'Invalid color'); + + var opts = { runValidators: true }; + Toy.update({}, { color: 'bacon' }, opts, function (err) { + assert.equal(err.errors.color.message, + 'Invalid color'); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); + + /** + * There are a couple of key differences between update validators and + * document validators. In the color validation function above, `this` refers + * to the document being validated when using document validation. + * However, when running update validators, the document being updated + * may not be in the server's memory, so by default the value of `this` is + * not defined. However, you can set the `context` option to 'query' to make + * `this` refer to the underlying query. + */ + + it('Update Validators and `this`', function(done) { + var toySchema = new Schema({ + color: String, + name: String + }); + + toySchema.path('color').validate(function(value) { + // When running in `validate()` or `validateSync()`, the + // validator can access the document using `this`. + // Does **not** work with update validators. + if (this.name.toLowerCase().indexOf('red') !== -1) { + return value !== 'red'; + } + return true; + }); + + var Toy = db.model('ActionFigure', toySchema); + + var toy = new Toy({ color: 'red', name: 'Red Power Ranger' }); + var error = toy.validateSync(); + assert.ok(error.errors['color']); + + var update = { color: 'red', name: 'Red Power Ranger' }; + var opts = { runValidators: true }; + + Toy.update({}, update, opts, function(error) { + // The update validator throws an error: + // "TypeError: Cannot read property 'toLowerCase' of undefined", + // because `this` is **not** the document being updated when using + // update validators + assert.ok(error); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); + + /** + * The other key difference that update validators only run on the paths + * specified in the update. For instance, in the below example, because + * 'name' is not specified in the update operation, update validation will + * succeed. + * + * When using update validators, `required` validators **only** fail when + * you try to explicitly `$unset` the key. */ - describe('Update Validators', function() { - /** - * To turn on update validators, set the `runValidators` option for - * `update()` or `findOneAndUpdate()`. Be careful: update validators - * are off by default because they have several caveats. - */ - it('Basic Update Validators', function(done) { - var toySchema = new Schema({ - color: String, - name: String - }); - - var Toy = db.model('Toys', toySchema); - - Toy.schema.path('color').validate(function (value) { - return /blue|green|white|red|orange|periwinkle/i.test(value); - }, 'Invalid color'); - - var opts = { runValidators: true }; - Toy.update({}, { color: 'bacon' }, opts, function (err) { - assert.equal(err.errors.color.message, - 'Invalid color'); - // acquit:ignore:start - done(); - // acquit:ignore:end - }); + + it('Update Validator Paths', function(done) { + // acquit:ignore:start + var outstanding = 2; + // acquit:ignore:end + var kittenSchema = new Schema({ + name: { type: String, required: true }, + age: Number }); - /** - * There are a couple of key differences between update validators and - * document validators. In the color validation function above, `this` refers - * to the document being validated when using document validation. - * However, when running update validators, the document being updated - * may not be in the server's memory, so by default the value of `this` is - * not defined. However, you can set the `context` option to 'query' to make - * `this` refer to the underlying query. - */ - - it('Update Validators and `this`', function(done) { - var toySchema = new Schema({ - color: String, - name: String - }); - - toySchema.path('color').validate(function(value) { - // When running in `validate()` or `validateSync()`, the - // validator can access the document using `this`. - // Does **not** work with update validators. - if (this.name.toLowerCase().indexOf('red') !== -1) { - return value !== 'red'; - } - return true; - }); - - var Toy = db.model('ActionFigure', toySchema); - - var toy = new Toy({ color: 'red', name: 'Red Power Ranger' }); - var error = toy.validateSync(); - assert.ok(error.errors['color']); - - var update = { color: 'red', name: 'Red Power Ranger' }; - var opts = { runValidators: true }; - - Toy.update({}, update, opts, function(error) { - // The update validator throws an error: - // "TypeError: Cannot read property 'toLowerCase' of undefined", - // because `this` is **not** the document being updated when using - // update validators - assert.ok(error); - // acquit:ignore:start - done(); - // acquit:ignore:end - }); + var Kitten = db.model('Kitten', kittenSchema); + + var update = { color: 'blue' }; + var opts = { runValidators: true }; + Kitten.update({}, update, opts, function(err) { + // Operation succeeds despite the fact that 'name' is not specified + // acquit:ignore:start + --outstanding || done(); + // acquit:ignore:end }); - /** - * The other key difference that update validators only run on the paths - * specified in the update. For instance, in the below example, because - * 'name' is not specified in the update operation, update validation will - * succeed. - * - * When using update validators, `required` validators **only** fail when - * you try to explicitly `$unset` the key. - */ - - it('Update Validator Paths', function(done) { + var unset = { $unset: { name: 1 } }; + Kitten.update({}, unset, opts, function(err) { + // Operation fails because 'name' is required + assert.ok(err); + assert.ok(err.errors['name']); // acquit:ignore:start - var outstanding = 2; + --outstanding || done(); // acquit:ignore:end - var kittenSchema = new Schema({ - name: { type: String, required: true }, - age: Number - }); - - var Kitten = db.model('Kitten', kittenSchema); - - var update = { color: 'blue' }; - var opts = { runValidators: true }; - Kitten.update({}, update, opts, function(err) { - // Operation succeeds despite the fact that 'name' is not specified - // acquit:ignore:start - --outstanding || done(); - // acquit:ignore:end - }); - - var unset = { $unset: { name: 1 } }; - Kitten.update({}, unset, opts, function(err) { - // Operation fails because 'name' is required - assert.ok(err); - assert.ok(err.errors['name']); - // acquit:ignore:start - --outstanding || done(); - // acquit:ignore:end - }); }); + }); + + /** + * One final detail worth noting: update validators **only** run on `$set` + * and `$unset` operations. For instance, the below update will succeed, + * regardless of the value of `number`. + */ - /** - * One final detail worth noting: update validators **only** run on `$set` - * and `$unset` operations. For instance, the below update will succeed, - * regardless of the value of `number`. - */ - - it('Update Validators Only Run On Specified Paths', function(done) { - var testSchema = new Schema({ - number: { type: Number, max: 0 }, - }); - - var Test = db.model('Test', testSchema); - - var update = { $inc: { number: 1 } }; - var opts = { runValidators: true }; - Test.update({}, update, opts, function(error) { - // There will never be a validation error here - // acquit:ignore:start - assert.ifError(error); - done(); - // acquit:ignore:end - }); + it('Update Validators Only Run On Specified Paths', function(done) { + var testSchema = new Schema({ + number: { type: Number, max: 0 }, + }); + + var Test = db.model('Test', testSchema); + + var update = { $inc: { number: 1 } }; + var opts = { runValidators: true }; + Test.update({}, update, opts, function(error) { + // There will never be a validation error here + // acquit:ignore:start + assert.ifError(error); + done(); + // acquit:ignore:end }); }); }); From 47341e8bc5ed3fc399372859e84bad25024beb3d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 6 Apr 2016 10:18:37 -0700 Subject: [PATCH 0451/2240] fix: upgrade mongodb -> 2.1.15 for several bug fixes Fix #4048 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b474e72114c..19a3f7ae03d 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.21", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.1.14", + "mongodb": "2.1.15", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.10.0", From cf8ecba9ef61730fdfd34d811f7a6eaafa77d5c1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 6 Apr 2016 10:21:14 -0700 Subject: [PATCH 0452/2240] docs(connection): clarify relationship between models and connections Fix #2157 --- docs/connections.jade | 4 +++- docs/models.jade | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index 5437b129b32..8731c5ce0ca 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -118,7 +118,9 @@ block content var conn = mongoose.createConnection('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]', options); :markdown - This [connection](./api.html#connection_Connection) object can then be used for creating and retrieving [models](./api.html#model_Model) that are scoped only to this specific connection. + This [connection](./api.html#connection_Connection) object is then used to + create and retrieve [models](./api.html#model_Model). Models are + **always** scoped to a single connection. h3#connection_pools Connection pools :markdown diff --git a/docs/models.jade b/docs/models.jade index fd6b7e7093b..5d654ab0cf7 100644 --- a/docs/models.jade +++ b/docs/models.jade @@ -34,9 +34,17 @@ block content // saved! }) :markdown - Note that no tanks will be created/removed until the connection your model uses is open. In this case we are using `mongoose.model()` so let's open the default mongoose connection: + Note that no tanks will be created/removed until the connection your model + uses is open. Every model has an associated connection. When you use + `mongoose.model()`, your model will use the default mongoose connection. :js mongoose.connect('localhost', 'gettingstarted'); + :markdown + If you create a custom connection, use that connection's `model()` function + instead. + :js + var connection = mongoose.createConnection('mongodb://localhost:27017/test'); + var Tank = connection.model('Tank', yourSchema); h3 Querying :markdown From 9a4c2f104ffbb6ddca1881930cfa4c880f38fe5c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 6 Apr 2016 10:33:48 -0700 Subject: [PATCH 0453/2240] docs: remove google groups from contrib guide --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c976cfd9f77..16c90f47e4f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ ## Contributing to Mongoose -If you have a question about Mongoose (not a bug report) please post it to either [StackOverflow](http://stackoverflow.com/questions/tagged/mongoose), our [Google Group](http://groups.google.com/group/mongoose-orm), or on [Gitter](https://gitter.im/Automattic/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +If you have a question about Mongoose (not a bug report) please post it to either [StackOverflow](http://stackoverflow.com/questions/tagged/mongoose), or on [Gitter](https://gitter.im/Automattic/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ### Reporting bugs From 881a16b079b1c0dfa515aaac70abd779db3c387b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 6 Apr 2016 10:37:18 -0700 Subject: [PATCH 0454/2240] docs: improve reporting bugs section on contrib guide --- CONTRIBUTING.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16c90f47e4f..c0f1cbc5f46 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,10 +4,13 @@ If you have a question about Mongoose (not a bug report) please post it to eithe ### Reporting bugs -- Before opening a new issue, look for existing [issues](https://github.com/learnboost/mongoose/issues) to avoid duplication. If the issue does not yet exist, [create one](https://github.com/learnboost/mongoose/issues/new). - - Please describe the issue you are experiencing, along with any associated stack trace. - - Please post code that reproduces the issue, the version of mongoose, node version, and mongodb version. - - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. +- Before opening a new issue, look for existing [issues](https://github.com/Automattic/mongoose/issues) to avoid duplication. If the issue does not yet exist, [create one](https://github.com/Automattic/mongoose/issues/new). + - Please post any relevant code samples, preferably a standalone script that + reproduces your issue. Do **not** describe your issue in prose, show your + code. + - If the bug involves an error, please post the stack trace. + - Please post the version of mongoose and mongodb that you're using. + - Please write bug reports in JavaScript (ES5 or ES2015), not coffeescript, typescript, etc. ### Requesting new features From 0dcd9f83398fe207d5c3120758253c1966090714 Mon Sep 17 00:00:00 2001 From: Allison Reinheimer Moore Date: Wed, 6 Apr 2016 14:16:35 -0400 Subject: [PATCH 0455/2240] Correct broken link to MongoDB $geoWithin docs --- lib/query.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 43b7477d6e8..e35e70481de 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3084,7 +3084,7 @@ Query.prototype.box = function(ll, ur) { * @return {Query} this * @see $center http://docs.mongodb.org/manual/reference/operator/center/ * @see $centerSphere http://docs.mongodb.org/manual/reference/operator/centerSphere/ - * @see $geoWithin http://docs.mongodb.org/manual/reference/operator/within/ + * @see $geoWithin http://docs.mongodb.org/manual/reference/operator/geoWithin/ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing * @api public */ From 8e08ed2409a1b601aec66ab957c5e13c2b7d1c60 Mon Sep 17 00:00:00 2001 From: Lukas Winter Date: Thu, 7 Apr 2016 15:27:04 +0200 Subject: [PATCH 0456/2240] Allow saving of array fields selected via --- lib/model.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index bd15001caaf..54f8cafe5c7 100644 --- a/lib/model.js +++ b/lib/model.js @@ -475,6 +475,19 @@ Model.prototype.$__delta = function() { continue; } + var pop = this.populated(data.path, true); + if (!pop && this.$__.selected) { + // If any array was selected using an $elemMatch projection, we alter the path and where clause + // NOTE: MongoDB only supports projected $elemMatch on top level array. + var pathSplit = data.path.split('.'); + var top = pathSplit[0]; + if (this.$__.selected[top] && this.$__.selected[top].$elemMatch) { + where[top] = this.$__.selected[top]; //FIXME: will we overwrite anything? + pathSplit[1] = '$'; //FIXME: check if the path is really top.0.something + data.path = pathSplit.join('.'); + } + } + if (divergent.length) continue; if (undefined === value) { @@ -523,8 +536,7 @@ function checkDivergentArray(doc, path, array) { // If any array was selected using an $elemMatch projection, we deny the update. // NOTE: MongoDB only supports projected $elemMatch on top level array. var top = path.split('.')[0]; - if ((doc.$__.selected[top] && doc.$__.selected[top].$elemMatch) || - doc.$__.selected[top + '.$']) { + if (doc.$__.selected[top + '.$']) { return top; } } From 7dff69ccb7e418f1c3506d062536771c377d0aa1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Apr 2016 06:46:32 -0700 Subject: [PATCH 0457/2240] test(query): repro #3171 --- test/model.update.test.js | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index def89d18d73..30d371c93ab 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1527,18 +1527,6 @@ describe('model: update:', function() { }); }); - it('can $rename (gh-1845)', function(done) { - var db = start(); - - var schema = new Schema({foo: Date, bar: Date}); - var Model = db.model('gh1845', schema, 'gh1845'); - - Model.update({}, {$rename: {foo: 'bar'}}, function(error) { - assert.ifError(error); - db.close(done); - }); - }); - it('doesnt modify original argument doc (gh-3008)', function(done) { var db = start(); var FooSchema = new mongoose.Schema({ @@ -1566,12 +1554,20 @@ describe('model: update:', function() { }); it('can $rename (gh-1845)', function(done) { - var schema = new Schema({foo: Date, bar: Date}); + var db = start(); + + var schema = new Schema({ foo: Date, bar: Date }); var Model = db.model('gh1845', schema, 'gh1845'); - Model.update({}, {$rename: {foo: 'bar'}}, function(error) { + var update = { $rename: { foo: 'bar'} }; + Model.create({ foo: Date.now() }, function(error) { assert.ifError(error); - done(); + Model.update({}, update, { multi: true }, function(error, res) { + assert.ifError(error); + assert.ok(res.ok); + assert.equal(res.nModified, 1); + db.close(done); + }); }); }); From 5c5f02382019542beecdd9d01fc0266777884adb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Apr 2016 06:46:41 -0700 Subject: [PATCH 0458/2240] fix(query): remove premature return when using $rename Fix #3171 --- lib/query.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 43b7477d6e8..b5a920f072e 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2410,7 +2410,7 @@ Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) { // improving this. if (op === '$rename') { hasKeys = true; - return; + continue; } hasKeys = true; From b9a893c73368f257e70a4acc05ef6b5ca3fb0502 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Apr 2016 07:32:46 -0700 Subject: [PATCH 0459/2240] refactor(test): reuse connection for array tests --- test/types.array.test.js | 103 +++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/test/types.array.test.js b/test/types.array.test.js index 73638a6ff34..6bc85052a25 100644 --- a/test/types.array.test.js +++ b/test/types.array.test.js @@ -1664,72 +1664,81 @@ describe('types array', function() { }); }); - it('modifying subdoc props and manipulating the array works (gh-842)', function(done) { - var db = start(); - var schema = new Schema({em: [new Schema({username: String})]}); - var M = db.model('modifyingSubDocAndPushing', schema); - var m = new M({em: [{username: 'Arrietty'}]}); - - m.save(function(err) { - assert.ifError(err); - M.findById(m, function(err, m) { - assert.ifError(err); - assert.equal(m.em[0].username, 'Arrietty'); + describe('bug fixes', function() { + var db; - m.em[0].username = 'Shawn'; - m.em.push({username: 'Homily'}); - m.save(function(err) { + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('modifying subdoc props and manipulating the array works (gh-842)', function(done) { + var schema = new Schema({em: [new Schema({username: String})]}); + var M = db.model('modifyingSubDocAndPushing', schema); + var m = new M({em: [{username: 'Arrietty'}]}); + + m.save(function(err) { + assert.ifError(err); + M.findById(m, function(err, m) { assert.ifError(err); + assert.equal(m.em[0].username, 'Arrietty'); - M.findById(m, function(err, m) { + m.em[0].username = 'Shawn'; + m.em.push({username: 'Homily'}); + m.save(function(err) { assert.ifError(err); - assert.equal(m.em.length, 2); - assert.equal(m.em[0].username, 'Shawn'); - assert.equal(m.em[1].username, 'Homily'); - m.em[0].username = 'Arrietty'; - m.em[1].remove(); - m.save(function(err) { + M.findById(m, function(err, m) { assert.ifError(err); + assert.equal(m.em.length, 2); + assert.equal(m.em[0].username, 'Shawn'); + assert.equal(m.em[1].username, 'Homily'); - M.findById(m, function(err, m) { - db.close(); + m.em[0].username = 'Arrietty'; + m.em[1].remove(); + m.save(function(err) { assert.ifError(err); - assert.equal(m.em.length, 1); - assert.equal(m.em[0].username, 'Arrietty'); - done(); + + M.findById(m, function(err, m) { + assert.ifError(err); + assert.equal(m.em.length, 1); + assert.equal(m.em[0].username, 'Arrietty'); + done(); + }); }); }); }); }); }); }); - }); - it('pushing top level arrays and subarrays works (gh-1073)', function(done) { - var db = start(); - var schema = new Schema({em: [new Schema({sub: [String]})]}); - var M = db.model('gh1073', schema); - var m = new M({em: [{sub: []}]}); - m.save(function() { - M.findById(m, function(err, m) { - assert.ifError(err); + it('pushing top level arrays and subarrays works (gh-1073)', function(done) { + var schema = new Schema({em: [new Schema({sub: [String]})]}); + var M = db.model('gh1073', schema); + var m = new M({em: [{sub: []}]}); + m.save(function() { + M.findById(m, function(err, m) { + assert.ifError(err); - m.em[m.em.length - 1].sub.push('a'); - m.em.push({sub: []}); + m.em[m.em.length - 1].sub.push('a'); + m.em.push({sub: []}); - assert.equal(2, m.em.length); - assert.equal(1, m.em[0].sub.length); + assert.equal(2, m.em.length); + assert.equal(1, m.em[0].sub.length); - m.save(function(err) { - assert.ifError(err); - - M.findById(m, function(err, m) { + m.save(function(err) { assert.ifError(err); - assert.equal(2, m.em.length); - assert.equal(1, m.em[0].sub.length); - assert.equal('a', m.em[0].sub[0]); - db.close(done); + + M.findById(m, function(err, m) { + assert.ifError(err); + assert.equal(2, m.em.length); + assert.equal(1, m.em[0].sub.length); + assert.equal('a', m.em[0].sub[0]); + done(); + }); }); }); }); From 6d4017ce39b9397da330c6a78db16cd69db20361 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Apr 2016 07:42:07 -0700 Subject: [PATCH 0460/2240] test(types): repro #4011 --- test/types.array.test.js | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/test/types.array.test.js b/test/types.array.test.js index 6bc85052a25..cf29959705b 100644 --- a/test/types.array.test.js +++ b/test/types.array.test.js @@ -2,13 +2,14 @@ * Module dependencies. */ -var start = require('./common'), - assert = require('power-assert'), - mongoose = require('./common').mongoose, - Schema = mongoose.Schema, - random = require('../lib/utils').random, - MongooseArray = mongoose.Types.Array, - collection = 'avengers_' + random(); +var start = require('./common'); +var assert = require('power-assert'); +var mongoose = require('./common').mongoose; +var Schema = mongoose.Schema; +var random = require('../lib/utils').random; +var mongodb = require('mongodb'); +var MongooseArray = mongoose.Types.Array; +var collection = 'avengers_' + random(); var User = new Schema({ name: String, @@ -1743,6 +1744,25 @@ describe('types array', function() { }); }); }); + + it('finding ids by string (gh-4011)', function(done) { + var sub = new Schema({ + _id: String, + other: String + }); + + var main = new Schema({ + subs: [sub] + }); + + var Model = db.model('gh4011', main); + + var doc = new Model({ subs: [{ _id: '57067021ee0870440c76f489' }] }); + + assert.ok(doc.subs.id('57067021ee0870440c76f489')); + assert.ok(doc.subs.id(new mongodb.ObjectId('57067021ee0870440c76f489'))); + done(); + }); }); describe('default type', function() { From 3c7b66c21f427b847f15ff04f9aee708893fb4d2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Apr 2016 07:42:14 -0700 Subject: [PATCH 0461/2240] fix(types): improve .id() check for document arrays Fix #4011 --- lib/types/documentarray.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index 5382b350119..7e5f4c32acb 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -145,7 +145,7 @@ MongooseDocumentArray.mixin = { if (sid == _id._id) { return this[i]; } - } else if (!(_id instanceof ObjectId)) { + } else if (!(id instanceof ObjectId) && !(_id instanceof ObjectId)) { if (utils.deepEqual(id, _id)) { return this[i]; } From efd35bb95f18b1ba20cc613b6bc759bf29e35e12 Mon Sep 17 00:00:00 2001 From: Lukas Winter Date: Thu, 7 Apr 2016 18:00:21 +0200 Subject: [PATCH 0462/2240] Fix test (gh-1334) to work with new elemMatch behaviour when saving document --- test/model.field.selection.test.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js index 22fef8c88f3..fea1e7ca33a 100644 --- a/test/model.field.selection.test.js +++ b/test/model.field.selection.test.js @@ -304,7 +304,7 @@ describe('model field selection', function() { }); }); - it('disallows saving modified elemMatch paths (gh-1334)', function(done) { + it('saves modified elemMatch paths (gh-1334)', function(done) { var db = start(); var postSchema = new Schema({ @@ -330,11 +330,17 @@ describe('model field selection', function() { found.ids = []; found.ids2.set(0, _id2); found.save(function(err) { - db.close(); - assert.ok(/\$elemMatch projection/.test(err)); - assert.ok(/ ids/.test(err)); - assert.ok(/ ids2/.test(err)); - done(); + assert.ifError(err); + + B.findById(doc._id).exec(function(err, found) { + assert.equal(0, found.ids.length); //FIXME is this the intended behaviour? + + assert.equal(2, found.ids2.length); + assert.equal(_id2.toHexString(), found.ids2[0].toHexString()); + assert.equal(_id2.toHexString(), found.ids2[1].toHexString()); + + done(); + }); }); }); }); From 31b5e2fafb3f91834aa0b6d0bec434aa993f6a23 Mon Sep 17 00:00:00 2001 From: Lukas Winter Date: Thu, 7 Apr 2016 18:58:30 +0200 Subject: [PATCH 0463/2240] throw error when trying to save an array that was selected via elemMatch and modified in an incompatible way --- lib/model.js | 17 ++++++++++++++--- test/model.field.selection.test.js | 5 +++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index 54f8cafe5c7..29c2d86b1bd 100644 --- a/lib/model.js +++ b/lib/model.js @@ -482,9 +482,20 @@ Model.prototype.$__delta = function() { var pathSplit = data.path.split('.'); var top = pathSplit[0]; if (this.$__.selected[top] && this.$__.selected[top].$elemMatch) { - where[top] = this.$__.selected[top]; //FIXME: will we overwrite anything? - pathSplit[1] = '$'; //FIXME: check if the path is really top.0.something - data.path = pathSplit.join('.'); + //If the selected array entry was modified + if (pathSplit.length > 1 && pathSplit[1] == 0) { + where[top] = this.$__.selected[top]; //FIXME: will we overwrite anything? + pathSplit[1] = '$'; + data.path = pathSplit.join('.'); + } + //if the selected array was entirely reassigned or uses an incompatible operation + else if (pathSplit.length == 1 && ( + typeof value.hasAtomics === 'undefined' || + '$set' in value._atomics || + '$pop' in value._atomics)) { + divergent.push(data.path); + continue; + } } } diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js index fea1e7ca33a..801f0fc930f 100644 --- a/test/model.field.selection.test.js +++ b/test/model.field.selection.test.js @@ -327,13 +327,14 @@ describe('model field selection', function() { assert.ifError(err); assert.equal(1, found.ids.length); assert.equal(1, found.ids2.length); - found.ids = []; + found.ids.pull(_id2); found.ids2.set(0, _id2); found.save(function(err) { assert.ifError(err); B.findById(doc._id).exec(function(err, found) { - assert.equal(0, found.ids.length); //FIXME is this the intended behaviour? + assert.equal(1, found.ids.length); + assert.equal(_id1.toHexString(), found.ids[0].toHexString()); assert.equal(2, found.ids2.length); assert.equal(_id2.toHexString(), found.ids2[0].toHexString()); From 46cea742e8b96c875e4e09748724dec0a0ca7693 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Apr 2016 11:55:28 -0700 Subject: [PATCH 0464/2240] test: remove flakey tests --- test/connection.test.js | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/test/connection.test.js b/test/connection.test.js index 41a4b336005..4084cc2a8df 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -649,29 +649,6 @@ describe('connections:', function() { }); }); - describe('missing protocols', function() { - it('are allowed with replsets', function(done) { - var conn = mongoose.createConnection('localhost:12345,127.0.0.1:14326?replicaSet=bacon', function(err) { - // force missing db error so we don't actually connect. - assert.ok(err); - }); - assert.deepEqual([{host: 'localhost', port: 12345}, {host: '127.0.0.1', port: 14326}], conn.hosts); - assert.deepEqual(null, conn.host); - assert.deepEqual(null, conn.port); - setTimeout(done, 10); - }); - - it('are allowed with single connections', function(done) { - var conn = mongoose.createConnection(); - conn.doOpen = function() { - }; - conn.open('localhost:12345/woot'); - assert.deepEqual('localhost', conn.host); - assert.deepEqual(12345, conn.port); - done(); - }); - }); - describe('connect callbacks', function() { it('execute with user:pwd connection strings', function(done) { var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {server: {auto_reconnect: true}}, function() { From 63e255e62ed7777a2cee15e4f6bd925e124aeffc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Apr 2016 09:56:51 -0700 Subject: [PATCH 0465/2240] docs(query): document context option for update and findOneAndUpdate Re: #4055 --- lib/query.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/query.js b/lib/query.js index 9d5e37cb22d..0dcbaa05e45 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1532,6 +1532,7 @@ function prepareDiscriminatorCriteria(query) { * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * - `context` (string) if set to 'query' and `runValidators` is on, `this` will refer to the query in custom validator functions that update validation runs. Does nothing if `runValidators` is false. * * ####Callback Signature * function(error, doc) { @@ -1955,6 +1956,7 @@ Query.prototype._execUpdate = function(callback) { * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `strict` (boolean) overrides the `strict` option for this update * - `overwrite` (boolean) disables update-only mode, allowing you to overwrite the doc (false) + * - `context` (string) if set to 'query' and `runValidators` is on, `this` will refer to the query in custom validator functions that update validation runs. Does nothing if `runValidators` is false. * * ####Note * From 58eed031dc444520cf411ce8ce1a45812b9fb5e7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Apr 2016 10:15:28 -0700 Subject: [PATCH 0466/2240] docs(validation): add context option example for update validators Fix #4055 --- test/docs/validation.test.js | 38 ++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 66506f1fd9d..fcaffd0dc88 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -258,8 +258,7 @@ describe('validation docs', function() { * to the document being validated when using document validation. * However, when running update validators, the document being updated * may not be in the server's memory, so by default the value of `this` is - * not defined. However, you can set the `context` option to 'query' to make - * `this` refer to the underlying query. + * not defined. */ it('Update Validators and `this`', function(done) { @@ -299,6 +298,41 @@ describe('validation docs', function() { }); }); + /** + * The `context` option lets you set the value of `this` in update validators + * to the underlying query. + */ + + it('The `context` option', function(done) { + // acquit:ignore:start + var toySchema = new Schema({ + color: String, + name: String + }); + // acquit:ignore:end + toySchema.path('color').validate(function(value) { + // When running update validators with the `context` option set to + // 'query', `this` refers to the query object. + if (this.getUpdate().$set.name.toLowerCase().indexOf('red') !== -1) { + return value === 'red'; + } + return true; + }); + + var Toy = db.model('ActionFigure', toySchema); + + var update = { color: 'blue', name: 'Red Power Ranger' }; + // Note the context option + var opts = { runValidators: true, context: 'query' }; + + Toy.update({}, update, opts, function(error) { + assert.ok(error.errors['color']); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); + /** * The other key difference that update validators only run on the paths * specified in the update. For instance, in the below example, because From 7166fddfc3b33b3d6e3d28fb67602a715b0beee7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Apr 2016 10:23:09 -0700 Subject: [PATCH 0467/2240] fix(test): rename model to prevent conflict --- package.json | 2 +- test/docs/validation.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 19a3f7ae03d..bc9ccb93b3c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.21", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.1.15", + "mongodb": "2.1.16", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.10.0", diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index fcaffd0dc88..26c97b31315 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -319,7 +319,7 @@ describe('validation docs', function() { return true; }); - var Toy = db.model('ActionFigure', toySchema); + var Toy = db.model('Figure', toySchema); var update = { color: 'blue', name: 'Red Power Ranger' }; // Note the context option From 239006ca12982d62369b8716e3fde917084d69ce Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Apr 2016 11:46:00 -0700 Subject: [PATCH 0468/2240] chore: release 4.4.12 --- bin/mongoose.js | 2676 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 1339 insertions(+), 1339 deletions(-) diff --git a/bin/mongoose.js b/bin/mongoose.js index 70a721be094..adca1315973 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -234,7 +234,7 @@ Document.prototype.constructor = Document; Document.ValidationError = ValidationError; module.exports = exports = Document; -},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":46,"./utils":48,"events":74}],4:[function(require,module,exports){ +},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":46,"./utils":48,"events":72}],4:[function(require,module,exports){ /*! * Module dependencies. */ @@ -2890,7 +2890,7 @@ Document.ValidationError = ValidationError; module.exports = exports = Document; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":39,"./types/array":41,"./types/documentarray":43,"./types/embedded":44,"./utils":48,"buffer":71,"events":74,"g5I+bs":94,"hooks-fixed":75,"util":98}],6:[function(require,module,exports){ +},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":39,"./types/array":41,"./types/documentarray":43,"./types/embedded":44,"./utils":48,"buffer":71,"events":72,"g5I+bs":94,"hooks-fixed":73,"util":98}],6:[function(require,module,exports){ 'use strict'; /* eslint-env browser */ @@ -3820,7 +3820,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject; module.exports = Promise; -},{"mpromise":82,"util":98}],25:[function(require,module,exports){ +},{"mpromise":80,"util":98}],25:[function(require,module,exports){ /*! * Module dependencies. */ @@ -3873,7 +3873,7 @@ Promise.reset = function() { module.exports = Promise; -},{"./ES6Promise":1,"./promise":24,"mquery":87}],26:[function(require,module,exports){ +},{"./ES6Promise":1,"./promise":24,"mquery":85}],26:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -5280,7 +5280,7 @@ Schema.Types = MongooseTypes = require('./schema/index'); exports.ObjectId = MongooseTypes.ObjectId; }).call(this,require("buffer").Buffer) -},{"./drivers":11,"./schema/index":33,"./utils":48,"./virtualtype":49,"async":51,"buffer":71,"events":74,"kareem":79}],27:[function(require,module,exports){ +},{"./drivers":11,"./schema/index":33,"./utils":48,"./virtualtype":49,"async":51,"buffer":71,"events":72,"kareem":77}],27:[function(require,module,exports){ /*! * Module dependencies. */ @@ -10158,7 +10158,7 @@ MongooseDocumentArray.mixin = { if (sid == _id._id) { return this[i]; } - } else if (!(_id instanceof ObjectId)) { + } else if (!(id instanceof ObjectId) && !(_id instanceof ObjectId)) { if (utils.deepEqual(id, _id)) { return this[i]; } @@ -11588,7 +11588,7 @@ exports.each = function(arr, fn) { }; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./document":5,"./types":45,"./types/objectid":46,"buffer":71,"g5I+bs":94,"mpath":80,"ms":93,"regexp-clone":95,"sliced":96}],49:[function(require,module,exports){ +},{"./document":5,"./types":45,"./types/objectid":46,"buffer":71,"g5I+bs":94,"mpath":78,"ms":93,"regexp-clone":95,"sliced":96}],49:[function(require,module,exports){ /** * VirtualType constructor @@ -19781,679 +19781,310 @@ function decodeUtf8Char (str) { } } -},{"base64-js":52,"ieee754":76,"is-array":78}],72:[function(require,module,exports){ - -/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ +},{"base64-js":52,"ieee754":74,"is-array":76}],72:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. -exports = module.exports = require('./debug'); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; -/** - * Colors. - */ +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; -exports.colors = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' -]; +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; -function useColors() { - // is webkit? http://stackoverflow.com/a/16459606/376773 - return ('WebkitAppearance' in document.documentElement.style) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (window.console && (console.firebug || (console.exception && console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); -} +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; -exports.formatters.j = function(v) { - return JSON.stringify(v); -}; + if (!this._events) + this._events = {}; + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } -/** - * Colorize log arguments if enabled. - * - * @api public - */ + handler = this._events[type]; -function formatArgs() { - var args = arguments; - var useColors = this.useColors; + if (isUndefined(handler)) + return false; - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; - if (!useColors) return args; + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } - var c = 'color: ' + this.color; - args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); + return true; +}; - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); +EventEmitter.prototype.addListener = function(type, listener) { + var m; - args.splice(lastC, 0, c); - return args; -} + if (!isFunction(listener)) + throw TypeError('listener must be a function'); -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ + if (!this._events) + this._events = {}; -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; } else { - exports.storage.debug = namespaces; + m = EventEmitter.defaultMaxListeners; } - } catch(e) {} -} -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} - return r; -} + return this; +}; -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ - -exports.enable(load()); - -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ - -function localstorage(){ - try { - return window.localStorage; - } catch (e) {} -} - -},{"./debug":73}],73:[function(require,module,exports){ +EventEmitter.prototype.on = EventEmitter.prototype.addListener; -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); -exports = module.exports = debug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = require('ms'); + var fired = false; -/** - * The currently active debug mode names, and names to skip. - */ + function g() { + this.removeListener(type, g); -exports.names = []; -exports.skips = []; + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lowercased letter, i.e. "n". - */ + g.listener = listener; + this.on(type, g); -exports.formatters = {}; + return this; +}; -/** - * Previously assigned color. - */ +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; -var prevColor = 0; + if (!isFunction(listener)) + throw TypeError('listener must be a function'); -/** - * Previous log timestamp. - */ + if (!this._events || !this._events[type]) + return this; -var prevTime; + list = this._events[type]; + length = list.length; + position = -1; -/** - * Select a color. - * - * @return {Number} - * @api private - */ + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); -function selectColor() { - return exports.colors[prevColor++ % exports.colors.length]; -} + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ + if (position < 0) + return this; -function debug(namespace) { + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } - // define the `disabled` version - function disabled() { + if (this._events.removeListener) + this.emit('removeListener', type, listener); } - disabled.enabled = false; - // define the `enabled` version - function enabled() { - - var self = enabled; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; + return this; +}; - // add the `color` if not set - if (null == self.useColors) self.useColors = exports.useColors(); - if (null == self.color && self.useColors) self.color = selectColor(); +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; - var args = Array.prototype.slice.call(arguments); + if (!this._events) + return this; - args[0] = exports.coerce(args[0]); + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } - if ('string' !== typeof args[0]) { - // anything else let's inspect with %o - args = ['%o'].concat(args); + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); + listeners = this._events[type]; - if ('function' === typeof exports.formatArgs) { - args = exports.formatArgs.apply(self, args); - } - var logFn = enabled.log || exports.log || console.log.bind(console); - logFn.apply(self, args); + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); } - enabled.enabled = true; + delete this._events[type]; - var fn = exports.enabled(namespace) ? enabled : disabled; + return this; +}; - fn.namespace = namespace; +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; - return fn; -} +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ +function isFunction(arg) { + return typeof arg === 'function'; +} -function enable(namespaces) { - exports.save(namespaces); +function isNumber(arg) { + return typeof arg === 'number'; +} - var split = (namespaces || '').split(/[\s,]+/); - var len = split.length; +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } +function isUndefined(arg) { + return arg === void 0; } -/** - * Disable debug output. - * - * @api public - */ - -function disable() { - exports.enable(''); -} - -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -function enabled(name) { - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; -} - -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} - -},{"ms":93}],74:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } - throw TypeError('Uncaught, unspecified "error" event.'); - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],75:[function(require,module,exports){ +},{}],73:[function(require,module,exports){ // TODO Add in pre and post skipping options module.exports = { /** @@ -20646,7 +20277,7 @@ function once (fn, scope) { }; } -},{}],76:[function(require,module,exports){ +},{}],74:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 @@ -20732,7 +20363,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],77:[function(require,module,exports){ +},{}],75:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -20757,7 +20388,7 @@ if (typeof Object.create === 'function') { } } -},{}],78:[function(require,module,exports){ +},{}],76:[function(require,module,exports){ /** * isArray @@ -20792,7 +20423,7 @@ module.exports = isArray || function (val) { return !! val && '[object Array]' == str.call(val); }; -},{}],79:[function(require,module,exports){ +},{}],77:[function(require,module,exports){ (function (process){ 'use strict'; @@ -21025,10 +20656,10 @@ Kareem.prototype.clone = function() { module.exports = Kareem; }).call(this,require("g5I+bs")) -},{"g5I+bs":94}],80:[function(require,module,exports){ +},{"g5I+bs":94}],78:[function(require,module,exports){ module.exports = exports = require('./lib'); -},{"./lib":81}],81:[function(require,module,exports){ +},{"./lib":79}],79:[function(require,module,exports){ /** * Returns the value of object `o` at the given `path`. * @@ -21245,7 +20876,7 @@ function K (v) { return v; } -},{}],82:[function(require,module,exports){ +},{}],80:[function(require,module,exports){ (function (process){ 'use strict'; var util = require('util'); @@ -21694,7 +21325,7 @@ Promise.deferred = function deferred() { /* End A+ tests adapter bit */ }).call(this,require("g5I+bs")) -},{"events":74,"g5I+bs":94,"util":98}],83:[function(require,module,exports){ +},{"events":72,"g5I+bs":94,"util":98}],81:[function(require,module,exports){ 'use strict'; /** @@ -21738,7 +21369,7 @@ function notImplemented (method) { } -},{}],84:[function(require,module,exports){ +},{}],82:[function(require,module,exports){ 'use strict'; var env = require('../env') @@ -21753,7 +21384,7 @@ module.exports = require('./collection'); -},{"../env":86,"./collection":83,"./node":85}],85:[function(require,module,exports){ +},{"../env":84,"./collection":81,"./node":83}],83:[function(require,module,exports){ 'use strict'; /** @@ -21863,7 +21494,7 @@ NodeCollection.prototype.findCursor = function(match, findOptions) { module.exports = exports = NodeCollection; -},{"../utils":89,"./collection":83}],86:[function(require,module,exports){ +},{"../utils":87,"./collection":81}],84:[function(require,module,exports){ (function (process,global,Buffer){ 'use strict'; @@ -21889,7 +21520,7 @@ exports.type = exports.isNode ? 'node' : 'unknown' }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"buffer":71,"g5I+bs":94}],87:[function(require,module,exports){ +},{"buffer":71,"g5I+bs":94}],85:[function(require,module,exports){ 'use strict'; /** @@ -24611,7 +24242,7 @@ module.exports = exports = Query; // TODO // test utils -},{"./collection":84,"./collection/collection":83,"./env":86,"./permissions":88,"./utils":89,"assert":50,"bluebird":90,"debug":72,"sliced":91,"util":98}],88:[function(require,module,exports){ +},{"./collection":82,"./collection/collection":81,"./env":84,"./permissions":86,"./utils":87,"assert":50,"bluebird":88,"debug":89,"sliced":91,"util":98}],86:[function(require,module,exports){ 'use strict'; var denied = exports; @@ -24701,7 +24332,7 @@ denied.count.maxScan = denied.count.snapshot = denied.count.tailable = true; -},{}],89:[function(require,module,exports){ +},{}],87:[function(require,module,exports){ (function (process,Buffer){ 'use strict'; @@ -25047,7 +24678,7 @@ exports.isArgumentsObject = function(v) { }; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"buffer":71,"g5I+bs":94,"regexp-clone":95}],90:[function(require,module,exports){ +},{"buffer":71,"g5I+bs":94,"regexp-clone":95}],88:[function(require,module,exports){ (function (process,global){ /* @preserve * The MIT License (MIT) @@ -29084,860 +28715,1229 @@ SomePromiseArray.prototype._promiseFulfilled = function (value) { } } -}; -SomePromiseArray.prototype._promiseRejected = function (reason) { - this._addRejected(reason); - if (this.howMany() > this._canPossiblyFulfill()) { - var e = new AggregateError(); - for (var i = this.length(); i < this._values.length; ++i) { - e.push(this._values[i]); +}; +SomePromiseArray.prototype._promiseRejected = function (reason) { + this._addRejected(reason); + if (this.howMany() > this._canPossiblyFulfill()) { + var e = new AggregateError(); + for (var i = this.length(); i < this._values.length; ++i) { + e.push(this._values[i]); + } + this._reject(e); + } +}; + +SomePromiseArray.prototype._fulfilled = function () { + return this._totalResolved; +}; + +SomePromiseArray.prototype._rejected = function () { + return this._values.length - this.length(); +}; + +SomePromiseArray.prototype._addRejected = function (reason) { + this._values.push(reason); +}; + +SomePromiseArray.prototype._addFulfilled = function (value) { + this._values[this._totalResolved++] = value; +}; + +SomePromiseArray.prototype._canPossiblyFulfill = function () { + return this.length() - this._rejected(); +}; + +SomePromiseArray.prototype._getRangeError = function (count) { + var message = "Input array must contain at least " + + this._howMany + " items but contains only " + count + " items"; + return new RangeError(message); +}; + +SomePromiseArray.prototype._resolveEmptyArray = function () { + this._reject(this._getRangeError(0)); +}; + +function some(promises, howMany) { + if ((howMany | 0) !== howMany || howMany < 0) { + return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/1wAmHx\u000a"); + } + var ret = new SomePromiseArray(promises); + var promise = ret.promise(); + ret.setHowMany(howMany); + ret.init(); + return promise; +} + +Promise.some = function (promises, howMany) { + return some(promises, howMany); +}; + +Promise.prototype.some = function (howMany) { + return some(this, howMany); +}; + +Promise._SomePromiseArray = SomePromiseArray; +}; + +},{"./errors.js":13,"./util.js":38}],34:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +function PromiseInspection(promise) { + if (promise !== undefined) { + promise = promise._target(); + this._bitField = promise._bitField; + this._settledValue = promise._settledValue; + } + else { + this._bitField = 0; + this._settledValue = undefined; + } +} + +PromiseInspection.prototype.value = function () { + if (!this.isFulfilled()) { + throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/hc1DLj\u000a"); + } + return this._settledValue; +}; + +PromiseInspection.prototype.error = +PromiseInspection.prototype.reason = function () { + if (!this.isRejected()) { + throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/hPuiwB\u000a"); + } + return this._settledValue; +}; + +PromiseInspection.prototype.isFulfilled = +Promise.prototype._isFulfilled = function () { + return (this._bitField & 268435456) > 0; +}; + +PromiseInspection.prototype.isRejected = +Promise.prototype._isRejected = function () { + return (this._bitField & 134217728) > 0; +}; + +PromiseInspection.prototype.isPending = +Promise.prototype._isPending = function () { + return (this._bitField & 402653184) === 0; +}; + +PromiseInspection.prototype.isResolved = +Promise.prototype._isResolved = function () { + return (this._bitField & 402653184) > 0; +}; + +Promise.prototype.isPending = function() { + return this._target()._isPending(); +}; + +Promise.prototype.isRejected = function() { + return this._target()._isRejected(); +}; + +Promise.prototype.isFulfilled = function() { + return this._target()._isFulfilled(); +}; + +Promise.prototype.isResolved = function() { + return this._target()._isResolved(); +}; + +Promise.prototype._value = function() { + return this._settledValue; +}; + +Promise.prototype._reason = function() { + this._unsetRejectionIsUnhandled(); + return this._settledValue; +}; + +Promise.prototype.value = function() { + var target = this._target(); + if (!target.isFulfilled()) { + throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/hc1DLj\u000a"); + } + return target._settledValue; +}; + +Promise.prototype.reason = function() { + var target = this._target(); + if (!target.isRejected()) { + throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/hPuiwB\u000a"); + } + target._unsetRejectionIsUnhandled(); + return target._settledValue; +}; + + +Promise.PromiseInspection = PromiseInspection; +}; + +},{}],35:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var util = _dereq_("./util.js"); +var errorObj = util.errorObj; +var isObject = util.isObject; + +function tryConvertToPromise(obj, context) { + if (isObject(obj)) { + if (obj instanceof Promise) { + return obj; + } + else if (isAnyBluebirdPromise(obj)) { + var ret = new Promise(INTERNAL); + obj._then( + ret._fulfillUnchecked, + ret._rejectUncheckedCheckError, + ret._progressUnchecked, + ret, + null + ); + return ret; + } + var then = util.tryCatch(getThen)(obj); + if (then === errorObj) { + if (context) context._pushContext(); + var ret = Promise.reject(then.e); + if (context) context._popContext(); + return ret; + } else if (typeof then === "function") { + return doThenable(obj, then, context); + } + } + return obj; +} + +function getThen(obj) { + return obj.then; +} + +var hasProp = {}.hasOwnProperty; +function isAnyBluebirdPromise(obj) { + return hasProp.call(obj, "_promise0"); +} + +function doThenable(x, then, context) { + var promise = new Promise(INTERNAL); + var ret = promise; + if (context) context._pushContext(); + promise._captureStackTrace(); + if (context) context._popContext(); + var synchronous = true; + var result = util.tryCatch(then).call(x, + resolveFromThenable, + rejectFromThenable, + progressFromThenable); + synchronous = false; + if (promise && result === errorObj) { + promise._rejectCallback(result.e, true, true); + promise = null; + } + + function resolveFromThenable(value) { + if (!promise) return; + promise._resolveCallback(value); + promise = null; + } + + function rejectFromThenable(reason) { + if (!promise) return; + promise._rejectCallback(reason, synchronous, true); + promise = null; + } + + function progressFromThenable(value) { + if (!promise) return; + if (typeof promise._progress === "function") { + promise._progress(value); } - this._reject(e); } -}; - -SomePromiseArray.prototype._fulfilled = function () { - return this._totalResolved; -}; - -SomePromiseArray.prototype._rejected = function () { - return this._values.length - this.length(); -}; + return ret; +} -SomePromiseArray.prototype._addRejected = function (reason) { - this._values.push(reason); +return tryConvertToPromise; }; -SomePromiseArray.prototype._addFulfilled = function (value) { - this._values[this._totalResolved++] = value; -}; +},{"./util.js":38}],36:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var util = _dereq_("./util.js"); +var TimeoutError = Promise.TimeoutError; -SomePromiseArray.prototype._canPossiblyFulfill = function () { - return this.length() - this._rejected(); +var afterTimeout = function (promise, message) { + if (!promise.isPending()) return; + + var err; + if(!util.isPrimitive(message) && (message instanceof Error)) { + err = message; + } else { + if (typeof message !== "string") { + message = "operation timed out"; + } + err = new TimeoutError(message); + } + util.markAsOriginatingFromRejection(err); + promise._attachExtraTrace(err); + promise._cancel(err); }; -SomePromiseArray.prototype._getRangeError = function (count) { - var message = "Input array must contain at least " + - this._howMany + " items but contains only " + count + " items"; - return new RangeError(message); +var afterValue = function(value) { return delay(+this).thenReturn(value); }; +var delay = Promise.delay = function (value, ms) { + if (ms === undefined) { + ms = value; + value = undefined; + var ret = new Promise(INTERNAL); + setTimeout(function() { ret._fulfill(); }, ms); + return ret; + } + ms = +ms; + return Promise.resolve(value)._then(afterValue, null, null, ms, undefined); }; -SomePromiseArray.prototype._resolveEmptyArray = function () { - this._reject(this._getRangeError(0)); +Promise.prototype.delay = function (ms) { + return delay(this, ms); }; -function some(promises, howMany) { - if ((howMany | 0) !== howMany || howMany < 0) { - return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/1wAmHx\u000a"); - } - var ret = new SomePromiseArray(promises); - var promise = ret.promise(); - ret.setHowMany(howMany); - ret.init(); - return promise; +function successClear(value) { + var handle = this; + if (handle instanceof Number) handle = +handle; + clearTimeout(handle); + return value; } -Promise.some = function (promises, howMany) { - return some(promises, howMany); -}; +function failureClear(reason) { + var handle = this; + if (handle instanceof Number) handle = +handle; + clearTimeout(handle); + throw reason; +} -Promise.prototype.some = function (howMany) { - return some(this, howMany); +Promise.prototype.timeout = function (ms, message) { + ms = +ms; + var ret = this.then().cancellable(); + ret._cancellationParent = this; + var handle = setTimeout(function timeoutTimeout() { + afterTimeout(ret, message); + }, ms); + return ret._then(successClear, failureClear, undefined, handle, undefined); }; -Promise._SomePromiseArray = SomePromiseArray; }; -},{"./errors.js":13,"./util.js":38}],34:[function(_dereq_,module,exports){ +},{"./util.js":38}],37:[function(_dereq_,module,exports){ "use strict"; -module.exports = function(Promise) { -function PromiseInspection(promise) { - if (promise !== undefined) { - promise = promise._target(); - this._bitField = promise._bitField; - this._settledValue = promise._settledValue; - } - else { - this._bitField = 0; - this._settledValue = undefined; - } -} +module.exports = function (Promise, apiRejection, tryConvertToPromise, + createContext) { + var TypeError = _dereq_("./errors.js").TypeError; + var inherits = _dereq_("./util.js").inherits; + var PromiseInspection = Promise.PromiseInspection; -PromiseInspection.prototype.value = function () { - if (!this.isFulfilled()) { - throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/hc1DLj\u000a"); + function inspectionMapper(inspections) { + var len = inspections.length; + for (var i = 0; i < len; ++i) { + var inspection = inspections[i]; + if (inspection.isRejected()) { + return Promise.reject(inspection.error()); + } + inspections[i] = inspection._settledValue; + } + return inspections; } - return this._settledValue; -}; -PromiseInspection.prototype.error = -PromiseInspection.prototype.reason = function () { - if (!this.isRejected()) { - throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/hPuiwB\u000a"); + function thrower(e) { + setTimeout(function(){throw e;}, 0); } - return this._settledValue; -}; - -PromiseInspection.prototype.isFulfilled = -Promise.prototype._isFulfilled = function () { - return (this._bitField & 268435456) > 0; -}; - -PromiseInspection.prototype.isRejected = -Promise.prototype._isRejected = function () { - return (this._bitField & 134217728) > 0; -}; -PromiseInspection.prototype.isPending = -Promise.prototype._isPending = function () { - return (this._bitField & 402653184) === 0; -}; + function castPreservingDisposable(thenable) { + var maybePromise = tryConvertToPromise(thenable); + if (maybePromise !== thenable && + typeof thenable._isDisposable === "function" && + typeof thenable._getDisposer === "function" && + thenable._isDisposable()) { + maybePromise._setDisposable(thenable._getDisposer()); + } + return maybePromise; + } + function dispose(resources, inspection) { + var i = 0; + var len = resources.length; + var ret = Promise.defer(); + function iterator() { + if (i >= len) return ret.resolve(); + var maybePromise = castPreservingDisposable(resources[i++]); + if (maybePromise instanceof Promise && + maybePromise._isDisposable()) { + try { + maybePromise = tryConvertToPromise( + maybePromise._getDisposer().tryDispose(inspection), + resources.promise); + } catch (e) { + return thrower(e); + } + if (maybePromise instanceof Promise) { + return maybePromise._then(iterator, thrower, + null, null, null); + } + } + iterator(); + } + iterator(); + return ret.promise; + } -PromiseInspection.prototype.isResolved = -Promise.prototype._isResolved = function () { - return (this._bitField & 402653184) > 0; -}; + function disposerSuccess(value) { + var inspection = new PromiseInspection(); + inspection._settledValue = value; + inspection._bitField = 268435456; + return dispose(this, inspection).thenReturn(value); + } -Promise.prototype.isPending = function() { - return this._target()._isPending(); -}; + function disposerFail(reason) { + var inspection = new PromiseInspection(); + inspection._settledValue = reason; + inspection._bitField = 134217728; + return dispose(this, inspection).thenThrow(reason); + } -Promise.prototype.isRejected = function() { - return this._target()._isRejected(); -}; + function Disposer(data, promise, context) { + this._data = data; + this._promise = promise; + this._context = context; + } -Promise.prototype.isFulfilled = function() { - return this._target()._isFulfilled(); -}; + Disposer.prototype.data = function () { + return this._data; + }; -Promise.prototype.isResolved = function() { - return this._target()._isResolved(); -}; + Disposer.prototype.promise = function () { + return this._promise; + }; -Promise.prototype._value = function() { - return this._settledValue; -}; + Disposer.prototype.resource = function () { + if (this.promise().isFulfilled()) { + return this.promise().value(); + } + return null; + }; -Promise.prototype._reason = function() { - this._unsetRejectionIsUnhandled(); - return this._settledValue; -}; + Disposer.prototype.tryDispose = function(inspection) { + var resource = this.resource(); + var context = this._context; + if (context !== undefined) context._pushContext(); + var ret = resource !== null + ? this.doDispose(resource, inspection) : null; + if (context !== undefined) context._popContext(); + this._promise._unsetDisposable(); + this._data = null; + return ret; + }; -Promise.prototype.value = function() { - var target = this._target(); - if (!target.isFulfilled()) { - throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/hc1DLj\u000a"); - } - return target._settledValue; -}; + Disposer.isDisposer = function (d) { + return (d != null && + typeof d.resource === "function" && + typeof d.tryDispose === "function"); + }; -Promise.prototype.reason = function() { - var target = this._target(); - if (!target.isRejected()) { - throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/hPuiwB\u000a"); + function FunctionDisposer(fn, promise, context) { + this.constructor$(fn, promise, context); } - target._unsetRejectionIsUnhandled(); - return target._settledValue; -}; + inherits(FunctionDisposer, Disposer); + FunctionDisposer.prototype.doDispose = function (resource, inspection) { + var fn = this.data(); + return fn.call(resource, resource, inspection); + }; -Promise.PromiseInspection = PromiseInspection; -}; + function maybeUnwrapDisposer(value) { + if (Disposer.isDisposer(value)) { + this.resources[this.index]._setDisposable(value); + return value.promise(); + } + return value; + } -},{}],35:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, INTERNAL) { -var util = _dereq_("./util.js"); -var errorObj = util.errorObj; -var isObject = util.isObject; + Promise.using = function () { + var len = arguments.length; + if (len < 2) return apiRejection( + "you must pass at least 2 arguments to Promise.using"); + var fn = arguments[len - 1]; + if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); -function tryConvertToPromise(obj, context) { - if (isObject(obj)) { - if (obj instanceof Promise) { - return obj; - } - else if (isAnyBluebirdPromise(obj)) { - var ret = new Promise(INTERNAL); - obj._then( - ret._fulfillUnchecked, - ret._rejectUncheckedCheckError, - ret._progressUnchecked, - ret, - null - ); - return ret; + var input; + var spreadArgs = true; + if (len === 2 && Array.isArray(arguments[0])) { + input = arguments[0]; + len = input.length; + spreadArgs = false; + } else { + input = arguments; + len--; } - var then = util.tryCatch(getThen)(obj); - if (then === errorObj) { - if (context) context._pushContext(); - var ret = Promise.reject(then.e); - if (context) context._popContext(); - return ret; - } else if (typeof then === "function") { - return doThenable(obj, then, context); + var resources = new Array(len); + for (var i = 0; i < len; ++i) { + var resource = input[i]; + if (Disposer.isDisposer(resource)) { + var disposer = resource; + resource = resource.promise(); + resource._setDisposable(disposer); + } else { + var maybePromise = tryConvertToPromise(resource); + if (maybePromise instanceof Promise) { + resource = + maybePromise._then(maybeUnwrapDisposer, null, null, { + resources: resources, + index: i + }, undefined); + } + } + resources[i] = resource; } - } - return obj; -} -function getThen(obj) { - return obj.then; -} + var promise = Promise.settle(resources) + .then(inspectionMapper) + .then(function(vals) { + promise._pushContext(); + var ret; + try { + ret = spreadArgs + ? fn.apply(undefined, vals) : fn.call(undefined, vals); + } finally { + promise._popContext(); + } + return ret; + }) + ._then( + disposerSuccess, disposerFail, undefined, resources, undefined); + resources.promise = promise; + return promise; + }; -var hasProp = {}.hasOwnProperty; -function isAnyBluebirdPromise(obj) { - return hasProp.call(obj, "_promise0"); -} + Promise.prototype._setDisposable = function (disposer) { + this._bitField = this._bitField | 262144; + this._disposer = disposer; + }; -function doThenable(x, then, context) { - var promise = new Promise(INTERNAL); - var ret = promise; - if (context) context._pushContext(); - promise._captureStackTrace(); - if (context) context._popContext(); - var synchronous = true; - var result = util.tryCatch(then).call(x, - resolveFromThenable, - rejectFromThenable, - progressFromThenable); - synchronous = false; - if (promise && result === errorObj) { - promise._rejectCallback(result.e, true, true); - promise = null; - } + Promise.prototype._isDisposable = function () { + return (this._bitField & 262144) > 0; + }; - function resolveFromThenable(value) { - if (!promise) return; - promise._resolveCallback(value); - promise = null; - } + Promise.prototype._getDisposer = function () { + return this._disposer; + }; - function rejectFromThenable(reason) { - if (!promise) return; - promise._rejectCallback(reason, synchronous, true); - promise = null; - } + Promise.prototype._unsetDisposable = function () { + this._bitField = this._bitField & (~262144); + this._disposer = undefined; + }; - function progressFromThenable(value) { - if (!promise) return; - if (typeof promise._progress === "function") { - promise._progress(value); + Promise.prototype.disposer = function (fn) { + if (typeof fn === "function") { + return new FunctionDisposer(fn, this, createContext()); } - } - return ret; -} + throw new TypeError(); + }; -return tryConvertToPromise; }; -},{"./util.js":38}],36:[function(_dereq_,module,exports){ +},{"./errors.js":13,"./util.js":38}],38:[function(_dereq_,module,exports){ "use strict"; -module.exports = function(Promise, INTERNAL) { -var util = _dereq_("./util.js"); -var TimeoutError = Promise.TimeoutError; +var es5 = _dereq_("./es5.js"); +var canEvaluate = typeof navigator == "undefined"; +var haveGetters = (function(){ + try { + var o = {}; + es5.defineProperty(o, "f", { + get: function () { + return 3; + } + }); + return o.f === 3; + } + catch (e) { + return false; + } -var afterTimeout = function (promise, message) { - if (!promise.isPending()) return; - - var err; - if(!util.isPrimitive(message) && (message instanceof Error)) { - err = message; - } else { - if (typeof message !== "string") { - message = "operation timed out"; - } - err = new TimeoutError(message); +})(); + +var errorObj = {e: {}}; +var tryCatchTarget; +function tryCatcher() { + try { + var target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); + } catch (e) { + errorObj.e = e; + return errorObj; } - util.markAsOriginatingFromRejection(err); - promise._attachExtraTrace(err); - promise._cancel(err); -}; +} +function tryCatch(fn) { + tryCatchTarget = fn; + return tryCatcher; +} -var afterValue = function(value) { return delay(+this).thenReturn(value); }; -var delay = Promise.delay = function (value, ms) { - if (ms === undefined) { - ms = value; - value = undefined; - var ret = new Promise(INTERNAL); - setTimeout(function() { ret._fulfill(); }, ms); - return ret; +var inherits = function(Child, Parent) { + var hasProp = {}.hasOwnProperty; + + function T() { + this.constructor = Child; + this.constructor$ = Parent; + for (var propertyName in Parent.prototype) { + if (hasProp.call(Parent.prototype, propertyName) && + propertyName.charAt(propertyName.length-1) !== "$" + ) { + this[propertyName + "$"] = Parent.prototype[propertyName]; + } + } } - ms = +ms; - return Promise.resolve(value)._then(afterValue, null, null, ms, undefined); + T.prototype = Parent.prototype; + Child.prototype = new T(); + return Child.prototype; }; -Promise.prototype.delay = function (ms) { - return delay(this, ms); -}; -function successClear(value) { - var handle = this; - if (handle instanceof Number) handle = +handle; - clearTimeout(handle); - return value; +function isPrimitive(val) { + return val == null || val === true || val === false || + typeof val === "string" || typeof val === "number"; + } -function failureClear(reason) { - var handle = this; - if (handle instanceof Number) handle = +handle; - clearTimeout(handle); - throw reason; +function isObject(value) { + return !isPrimitive(value); } -Promise.prototype.timeout = function (ms, message) { - ms = +ms; - var ret = this.then().cancellable(); - ret._cancellationParent = this; - var handle = setTimeout(function timeoutTimeout() { - afterTimeout(ret, message); - }, ms); - return ret._then(successClear, failureClear, undefined, handle, undefined); -}; +function maybeWrapAsError(maybeError) { + if (!isPrimitive(maybeError)) return maybeError; -}; + return new Error(safeToString(maybeError)); +} -},{"./util.js":38}],37:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function (Promise, apiRejection, tryConvertToPromise, - createContext) { - var TypeError = _dereq_("./errors.js").TypeError; - var inherits = _dereq_("./util.js").inherits; - var PromiseInspection = Promise.PromiseInspection; +function withAppended(target, appendee) { + var len = target.length; + var ret = new Array(len + 1); + var i; + for (i = 0; i < len; ++i) { + ret[i] = target[i]; + } + ret[i] = appendee; + return ret; +} - function inspectionMapper(inspections) { - var len = inspections.length; - for (var i = 0; i < len; ++i) { - var inspection = inspections[i]; - if (inspection.isRejected()) { - return Promise.reject(inspection.error()); - } - inspections[i] = inspection._settledValue; +function getDataPropertyOrDefault(obj, key, defaultValue) { + if (es5.isES5) { + var desc = Object.getOwnPropertyDescriptor(obj, key); + + if (desc != null) { + return desc.get == null && desc.set == null + ? desc.value + : defaultValue; } - return inspections; + } else { + return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; } +} - function thrower(e) { - setTimeout(function(){throw e;}, 0); - } +function notEnumerableProp(obj, name, value) { + if (isPrimitive(obj)) return obj; + var descriptor = { + value: value, + configurable: true, + enumerable: false, + writable: true + }; + es5.defineProperty(obj, name, descriptor); + return obj; +} - function castPreservingDisposable(thenable) { - var maybePromise = tryConvertToPromise(thenable); - if (maybePromise !== thenable && - typeof thenable._isDisposable === "function" && - typeof thenable._getDisposer === "function" && - thenable._isDisposable()) { - maybePromise._setDisposable(thenable._getDisposer()); +function thrower(r) { + throw r; +} + +var inheritedDataKeys = (function() { + var excludedPrototypes = [ + Array.prototype, + Object.prototype, + Function.prototype + ]; + + var isExcludedProto = function(val) { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (excludedPrototypes[i] === val) { + return true; + } } - return maybePromise; - } - function dispose(resources, inspection) { - var i = 0; - var len = resources.length; - var ret = Promise.defer(); - function iterator() { - if (i >= len) return ret.resolve(); - var maybePromise = castPreservingDisposable(resources[i++]); - if (maybePromise instanceof Promise && - maybePromise._isDisposable()) { + return false; + }; + + if (es5.isES5) { + var getKeys = Object.getOwnPropertyNames; + return function(obj) { + var ret = []; + var visitedKeys = Object.create(null); + while (obj != null && !isExcludedProto(obj)) { + var keys; try { - maybePromise = tryConvertToPromise( - maybePromise._getDisposer().tryDispose(inspection), - resources.promise); + keys = getKeys(obj); } catch (e) { - return thrower(e); + return ret; } - if (maybePromise instanceof Promise) { - return maybePromise._then(iterator, thrower, - null, null, null); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (visitedKeys[key]) continue; + visitedKeys[key] = true; + var desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc != null && desc.get == null && desc.set == null) { + ret.push(key); + } } + obj = es5.getPrototypeOf(obj); } - iterator(); - } - iterator(); - return ret.promise; - } - - function disposerSuccess(value) { - var inspection = new PromiseInspection(); - inspection._settledValue = value; - inspection._bitField = 268435456; - return dispose(this, inspection).thenReturn(value); - } + return ret; + }; + } else { + var hasProp = {}.hasOwnProperty; + return function(obj) { + if (isExcludedProto(obj)) return []; + var ret = []; - function disposerFail(reason) { - var inspection = new PromiseInspection(); - inspection._settledValue = reason; - inspection._bitField = 134217728; - return dispose(this, inspection).thenThrow(reason); + /*jshint forin:false */ + enumeration: for (var key in obj) { + if (hasProp.call(obj, key)) { + ret.push(key); + } else { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (hasProp.call(excludedPrototypes[i], key)) { + continue enumeration; + } + } + ret.push(key); + } + } + return ret; + }; } - function Disposer(data, promise, context) { - this._data = data; - this._promise = promise; - this._context = context; - } +})(); - Disposer.prototype.data = function () { - return this._data; - }; +var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; +function isClass(fn) { + try { + if (typeof fn === "function") { + var keys = es5.names(fn.prototype); - Disposer.prototype.promise = function () { - return this._promise; - }; + var hasMethods = es5.isES5 && keys.length > 1; + var hasMethodsOtherThanConstructor = keys.length > 0 && + !(keys.length === 1 && keys[0] === "constructor"); + var hasThisAssignmentAndStaticMethods = + thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; - Disposer.prototype.resource = function () { - if (this.promise().isFulfilled()) { - return this.promise().value(); + if (hasMethods || hasMethodsOtherThanConstructor || + hasThisAssignmentAndStaticMethods) { + return true; + } } - return null; - }; + return false; + } catch (e) { + return false; + } +} - Disposer.prototype.tryDispose = function(inspection) { - var resource = this.resource(); - var context = this._context; - if (context !== undefined) context._pushContext(); - var ret = resource !== null - ? this.doDispose(resource, inspection) : null; - if (context !== undefined) context._popContext(); - this._promise._unsetDisposable(); - this._data = null; - return ret; - }; +function toFastProperties(obj) { + /*jshint -W027,-W055,-W031*/ + function f() {} + f.prototype = obj; + var l = 8; + while (l--) new f(); + return obj; + eval(obj); +} + +var rident = /^[a-z$_][a-z$_0-9]*$/i; +function isIdentifier(str) { + return rident.test(str); +} + +function filledRange(count, prefix, suffix) { + var ret = new Array(count); + for(var i = 0; i < count; ++i) { + ret[i] = prefix + i + suffix; + } + return ret; +} - Disposer.isDisposer = function (d) { - return (d != null && - typeof d.resource === "function" && - typeof d.tryDispose === "function"); - }; +function safeToString(obj) { + try { + return obj + ""; + } catch (e) { + return "[no string representation]"; + } +} - function FunctionDisposer(fn, promise, context) { - this.constructor$(fn, promise, context); +function markAsOriginatingFromRejection(e) { + try { + notEnumerableProp(e, "isOperational", true); } - inherits(FunctionDisposer, Disposer); + catch(ignore) {} +} - FunctionDisposer.prototype.doDispose = function (resource, inspection) { - var fn = this.data(); - return fn.call(resource, resource, inspection); - }; +function originatesFromRejection(e) { + if (e == null) return false; + return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || + e["isOperational"] === true); +} - function maybeUnwrapDisposer(value) { - if (Disposer.isDisposer(value)) { - this.resources[this.index]._setDisposable(value); - return value.promise(); - } - return value; +function canAttachTrace(obj) { + return obj instanceof Error && es5.propertyIsWritable(obj, "stack"); +} + +var ensureErrorObject = (function() { + if (!("stack" in new Error())) { + return function(value) { + if (canAttachTrace(value)) return value; + try {throw new Error(safeToString(value));} + catch(err) {return err;} + }; + } else { + return function(value) { + if (canAttachTrace(value)) return value; + return new Error(safeToString(value)); + }; } +})(); - Promise.using = function () { - var len = arguments.length; - if (len < 2) return apiRejection( - "you must pass at least 2 arguments to Promise.using"); - var fn = arguments[len - 1]; - if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); +function classString(obj) { + return {}.toString.call(obj); +} - var input; - var spreadArgs = true; - if (len === 2 && Array.isArray(arguments[0])) { - input = arguments[0]; - len = input.length; - spreadArgs = false; - } else { - input = arguments; - len--; - } - var resources = new Array(len); - for (var i = 0; i < len; ++i) { - var resource = input[i]; - if (Disposer.isDisposer(resource)) { - var disposer = resource; - resource = resource.promise(); - resource._setDisposable(disposer); - } else { - var maybePromise = tryConvertToPromise(resource); - if (maybePromise instanceof Promise) { - resource = - maybePromise._then(maybeUnwrapDisposer, null, null, { - resources: resources, - index: i - }, undefined); - } - } - resources[i] = resource; +function copyDescriptors(from, to, filter) { + var keys = es5.names(from); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (filter(key)) { + try { + es5.defineProperty(to, key, es5.getDescriptor(from, key)); + } catch (ignore) {} } + } +} - var promise = Promise.settle(resources) - .then(inspectionMapper) - .then(function(vals) { - promise._pushContext(); - var ret; - try { - ret = spreadArgs - ? fn.apply(undefined, vals) : fn.call(undefined, vals); - } finally { - promise._popContext(); - } - return ret; - }) - ._then( - disposerSuccess, disposerFail, undefined, resources, undefined); - resources.promise = promise; - return promise; - }; +var ret = { + isClass: isClass, + isIdentifier: isIdentifier, + inheritedDataKeys: inheritedDataKeys, + getDataPropertyOrDefault: getDataPropertyOrDefault, + thrower: thrower, + isArray: es5.isArray, + haveGetters: haveGetters, + notEnumerableProp: notEnumerableProp, + isPrimitive: isPrimitive, + isObject: isObject, + canEvaluate: canEvaluate, + errorObj: errorObj, + tryCatch: tryCatch, + inherits: inherits, + withAppended: withAppended, + maybeWrapAsError: maybeWrapAsError, + toFastProperties: toFastProperties, + filledRange: filledRange, + toString: safeToString, + canAttachTrace: canAttachTrace, + ensureErrorObject: ensureErrorObject, + originatesFromRejection: originatesFromRejection, + markAsOriginatingFromRejection: markAsOriginatingFromRejection, + classString: classString, + copyDescriptors: copyDescriptors, + hasDevTools: typeof chrome !== "undefined" && chrome && + typeof chrome.loadTimes === "function", + isNode: typeof process !== "undefined" && + classString(process).toLowerCase() === "[object process]" +}; +ret.isRecentNode = ret.isNode && (function() { + var version = process.versions.node.split(".").map(Number); + return (version[0] === 0 && version[1] > 10) || (version[0] > 0); +})(); - Promise.prototype._setDisposable = function (disposer) { - this._bitField = this._bitField | 262144; - this._disposer = disposer; - }; +if (ret.isNode) ret.toFastProperties(process); - Promise.prototype._isDisposable = function () { - return (this._bitField & 262144) > 0; - }; +try {throw new Error(); } catch (e) {ret.lastLineError = e;} +module.exports = ret; - Promise.prototype._getDisposer = function () { - return this._disposer; - }; +},{"./es5.js":14}]},{},[4])(4) +}); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } +}).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"g5I+bs":94}],89:[function(require,module,exports){ - Promise.prototype._unsetDisposable = function () { - this._bitField = this._bitField & (~262144); - this._disposer = undefined; - }; +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ - Promise.prototype.disposer = function (fn) { - if (typeof fn === "function") { - return new FunctionDisposer(fn, this, createContext()); - } - throw new TypeError(); - }; +exports = module.exports = require('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); -}; +/** + * Colors. + */ -},{"./errors.js":13,"./util.js":38}],38:[function(_dereq_,module,exports){ -"use strict"; -var es5 = _dereq_("./es5.js"); -var canEvaluate = typeof navigator == "undefined"; -var haveGetters = (function(){ - try { - var o = {}; - es5.defineProperty(o, "f", { - get: function () { - return 3; - } - }); - return o.f === 3; - } - catch (e) { - return false; - } +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; -})(); +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ -var errorObj = {e: {}}; -var tryCatchTarget; -function tryCatcher() { - try { - var target = tryCatchTarget; - tryCatchTarget = null; - return target.apply(this, arguments); - } catch (e) { - errorObj.e = e; - return errorObj; - } -} -function tryCatch(fn) { - tryCatchTarget = fn; - return tryCatcher; +function useColors() { + // is webkit? http://stackoverflow.com/a/16459606/376773 + return ('WebkitAppearance' in document.documentElement.style) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (window.console && (console.firebug || (console.exception && console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); } -var inherits = function(Child, Parent) { - var hasProp = {}.hasOwnProperty; +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ - function T() { - this.constructor = Child; - this.constructor$ = Parent; - for (var propertyName in Parent.prototype) { - if (hasProp.call(Parent.prototype, propertyName) && - propertyName.charAt(propertyName.length-1) !== "$" - ) { - this[propertyName + "$"] = Parent.prototype[propertyName]; - } - } - } - T.prototype = Parent.prototype; - Child.prototype = new T(); - return Child.prototype; +exports.formatters.j = function(v) { + return JSON.stringify(v); }; -function isPrimitive(val) { - return val == null || val === true || val === false || - typeof val === "string" || typeof val === "number"; +/** + * Colorize log arguments if enabled. + * + * @api public + */ -} +function formatArgs() { + var args = arguments; + var useColors = this.useColors; -function isObject(value) { - return !isPrimitive(value); -} + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); -function maybeWrapAsError(maybeError) { - if (!isPrimitive(maybeError)) return maybeError; + if (!useColors) return args; - return new Error(safeToString(maybeError)); -} + var c = 'color: ' + this.color; + args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); -function withAppended(target, appendee) { - var len = target.length; - var ret = new Array(len + 1); - var i; - for (i = 0; i < len; ++i) { - ret[i] = target[i]; + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; } - ret[i] = appendee; - return ret; + }); + + args.splice(lastC, 0, c); + return args; } -function getDataPropertyOrDefault(obj, key, defaultValue) { - if (es5.isES5) { - var desc = Object.getOwnPropertyDescriptor(obj, key); +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ - if (desc != null) { - return desc.get == null && desc.set == null - ? desc.value - : defaultValue; - } +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); } else { - return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; + exports.storage.debug = namespaces; } + } catch(e) {} } -function notEnumerableProp(obj, name, value) { - if (isPrimitive(obj)) return obj; - var descriptor = { - value: value, - configurable: true, - enumerable: false, - writable: true - }; - es5.defineProperty(obj, name, descriptor); - return obj; +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + return r; } -function thrower(r) { - throw r; +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage(){ + try { + return window.localStorage; + } catch (e) {} } -var inheritedDataKeys = (function() { - var excludedPrototypes = [ - Array.prototype, - Object.prototype, - Function.prototype - ]; +},{"./debug":90}],90:[function(require,module,exports){ - var isExcludedProto = function(val) { - for (var i = 0; i < excludedPrototypes.length; ++i) { - if (excludedPrototypes[i] === val) { - return true; - } - } - return false; - }; +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ - if (es5.isES5) { - var getKeys = Object.getOwnPropertyNames; - return function(obj) { - var ret = []; - var visitedKeys = Object.create(null); - while (obj != null && !isExcludedProto(obj)) { - var keys; - try { - keys = getKeys(obj); - } catch (e) { - return ret; - } - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - if (visitedKeys[key]) continue; - visitedKeys[key] = true; - var desc = Object.getOwnPropertyDescriptor(obj, key); - if (desc != null && desc.get == null && desc.set == null) { - ret.push(key); - } - } - obj = es5.getPrototypeOf(obj); - } - return ret; - }; - } else { - var hasProp = {}.hasOwnProperty; - return function(obj) { - if (isExcludedProto(obj)) return []; - var ret = []; +exports = module.exports = debug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = require('ms'); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lowercased letter, i.e. "n". + */ + +exports.formatters = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Previous log timestamp. + */ + +var prevTime; + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function selectColor() { + return exports.colors[prevColor++ % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ - /*jshint forin:false */ - enumeration: for (var key in obj) { - if (hasProp.call(obj, key)) { - ret.push(key); - } else { - for (var i = 0; i < excludedPrototypes.length; ++i) { - if (hasProp.call(excludedPrototypes[i], key)) { - continue enumeration; - } - } - ret.push(key); - } - } - return ret; - }; - } +function debug(namespace) { -})(); + // define the `disabled` version + function disabled() { + } + disabled.enabled = false; -var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; -function isClass(fn) { - try { - if (typeof fn === "function") { - var keys = es5.names(fn.prototype); + // define the `enabled` version + function enabled() { - var hasMethods = es5.isES5 && keys.length > 1; - var hasMethodsOtherThanConstructor = keys.length > 0 && - !(keys.length === 1 && keys[0] === "constructor"); - var hasThisAssignmentAndStaticMethods = - thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; + var self = enabled; - if (hasMethods || hasMethodsOtherThanConstructor || - hasThisAssignmentAndStaticMethods) { - return true; - } - } - return false; - } catch (e) { - return false; - } -} + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; -function toFastProperties(obj) { - /*jshint -W027,-W055,-W031*/ - function f() {} - f.prototype = obj; - var l = 8; - while (l--) new f(); - return obj; - eval(obj); -} + // add the `color` if not set + if (null == self.useColors) self.useColors = exports.useColors(); + if (null == self.color && self.useColors) self.color = selectColor(); -var rident = /^[a-z$_][a-z$_0-9]*$/i; -function isIdentifier(str) { - return rident.test(str); -} + var args = Array.prototype.slice.call(arguments); -function filledRange(count, prefix, suffix) { - var ret = new Array(count); - for(var i = 0; i < count; ++i) { - ret[i] = prefix + i + suffix; - } - return ret; -} + args[0] = exports.coerce(args[0]); -function safeToString(obj) { - try { - return obj + ""; - } catch (e) { - return "[no string representation]"; + if ('string' !== typeof args[0]) { + // anything else let's inspect with %o + args = ['%o'].concat(args); } -} -function markAsOriginatingFromRejection(e) { - try { - notEnumerableProp(e, "isOperational", true); + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + if ('function' === typeof exports.formatArgs) { + args = exports.formatArgs.apply(self, args); } - catch(ignore) {} -} + var logFn = enabled.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + enabled.enabled = true; -function originatesFromRejection(e) { - if (e == null) return false; - return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || - e["isOperational"] === true); -} + var fn = exports.enabled(namespace) ? enabled : disabled; -function canAttachTrace(obj) { - return obj instanceof Error && es5.propertyIsWritable(obj, "stack"); + fn.namespace = namespace; + + return fn; } -var ensureErrorObject = (function() { - if (!("stack" in new Error())) { - return function(value) { - if (canAttachTrace(value)) return value; - try {throw new Error(safeToString(value));} - catch(err) {return err;} - }; +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + var split = (namespaces || '').split(/[\s,]+/); + var len = split.length; + + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); } else { - return function(value) { - if (canAttachTrace(value)) return value; - return new Error(safeToString(value)); - }; + exports.names.push(new RegExp('^' + namespaces + '$')); } -})(); + } +} -function classString(obj) { - return {}.toString.call(obj); +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); } -function copyDescriptors(from, to, filter) { - var keys = es5.names(from); - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - if (filter(key)) { - try { - es5.defineProperty(to, key, es5.getDescriptor(from, key)); - } catch (ignore) {} - } +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; } + } + return false; } -var ret = { - isClass: isClass, - isIdentifier: isIdentifier, - inheritedDataKeys: inheritedDataKeys, - getDataPropertyOrDefault: getDataPropertyOrDefault, - thrower: thrower, - isArray: es5.isArray, - haveGetters: haveGetters, - notEnumerableProp: notEnumerableProp, - isPrimitive: isPrimitive, - isObject: isObject, - canEvaluate: canEvaluate, - errorObj: errorObj, - tryCatch: tryCatch, - inherits: inherits, - withAppended: withAppended, - maybeWrapAsError: maybeWrapAsError, - toFastProperties: toFastProperties, - filledRange: filledRange, - toString: safeToString, - canAttachTrace: canAttachTrace, - ensureErrorObject: ensureErrorObject, - originatesFromRejection: originatesFromRejection, - markAsOriginatingFromRejection: markAsOriginatingFromRejection, - classString: classString, - copyDescriptors: copyDescriptors, - hasDevTools: typeof chrome !== "undefined" && chrome && - typeof chrome.loadTimes === "function", - isNode: typeof process !== "undefined" && - classString(process).toLowerCase() === "[object process]" -}; -ret.isRecentNode = ret.isNode && (function() { - var version = process.versions.node.split(".").map(Number); - return (version[0] === 0 && version[1] > 10) || (version[0] > 0); -})(); - -if (ret.isNode) ret.toFastProperties(process); +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ -try {throw new Error(); } catch (e) {ret.lastLineError = e;} -module.exports = ret; +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} -},{"./es5.js":14}]},{},[4])(4) -}); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } -}).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"g5I+bs":94}],91:[function(require,module,exports){ +},{"ms":93}],91:[function(require,module,exports){ module.exports = exports = require('./lib/sliced'); },{"./lib/sliced":92}],92:[function(require,module,exports){ @@ -30788,4 +30788,4 @@ function hasOwnProperty(obj, prop) { } }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":97,"g5I+bs":94,"inherits":77}]},{},[2]) \ No newline at end of file +},{"./support/isBuffer":97,"g5I+bs":94,"inherits":75}]},{},[2]) \ No newline at end of file diff --git a/package.json b/package.json index bc9ccb93b3c..3a503e5dec7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.12-pre", + "version": "4.4.12", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ad838252e11e49ec22785de807fbd35d9f542500 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Apr 2016 11:52:46 -0700 Subject: [PATCH 0469/2240] docs: add changelog for 4.4.12 --- History.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/History.md b/History.md index f2e42700611..a868ce8d8f8 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.4.12 / 2016-04-08 +=================== + * docs(query): document context option for update and findOneAndUpdate #4055 + * docs(query): correct link to $geoWithin docs #4050 + * fix(project): upgrade to mongodb driver 2.1.16 #4048 [schmalliso](https://github.com/schmalliso) + * docs(validation): fix validation docs #4028 + * fix(types): improve .id() check for document arrays #4011 + * fix(query): remove premature return when using $rename #3171 + * docs(connection): clarify relationship between models and connections #2157 + 4.4.11 / 2016-04-03 =================== * fix: upgrade to mongodb driver 2.1.14 #4036 #4030 #3945 From 390954e5a729e3c0a54d83f18a123d29635516a2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 12:24:19 -0700 Subject: [PATCH 0470/2240] chore: now working on 4.4.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a503e5dec7..e62e829e919 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.12", + "version": "4.4.13-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From b979750fd61c72d3af5263c3c5be3e6c2f7b661e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 13:19:06 -0700 Subject: [PATCH 0471/2240] test(schema): repro #4042 --- test/schema.test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 6d4c05c3bd7..acdc7b5ee62 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1526,6 +1526,17 @@ describe('schema', function() { done(); }); + it('trim: false works with strings (gh-4042)', function(done) { + var testSchema = new Schema({ + test: { type: String, trim: false } + }); + + var Test = mongoose.model('gh4042', testSchema); + var test = new Test({ test: ' test ' }); + assert.equal(test.test, ' test '); + done(); + }); + describe('remove()', function() { before(function() { this.schema = new Schema({ From 9674257c4bd2baaa790f1e5d1222f85574e52e95 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 13:19:12 -0700 Subject: [PATCH 0472/2240] fix(schema): handle setting trim to falsy Fix #4042 --- lib/schema/string.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/string.js b/lib/schema/string.js index 1190dd77e51..db923d0afdf 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -190,7 +190,7 @@ SchemaString.prototype.trim = function() { if (typeof v !== 'string') { v = self.cast(v); } - if (v) { + if (v && self.options.trim) { return v.trim(); } return v; From f614c592e7f6ccb2f44db4ecaba1b7b16cafb8b4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 14:00:21 -0700 Subject: [PATCH 0473/2240] refactor(test): remove connection leak in query tests --- test/query.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index 402045dfadc..e7258609813 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1590,7 +1590,7 @@ describe('Query', function() { }); describe('handles falsy and object projections with defaults (gh-3256)', function() { - var db = start(); + var db; var MyModel; before(function(done) { @@ -1625,8 +1625,8 @@ describe('Query', function() { }); }); - after(function() { - db.close(); + after(function(done) { + db.close(done); }); it('falsy projection', function(done) { From 5222424be11f5fd9a4ef75cf45577b775f288441 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 14:09:45 -0700 Subject: [PATCH 0474/2240] test(query): repro #4044 --- test/query.test.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index e7258609813..315874a65c6 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1587,6 +1587,36 @@ describe('Query', function() { {votes: 1, count: 3}); done(); }); + + it('$geoWithin with single nested schemas (gh-4044)', function(done) { + var locationSchema = new Schema({ + type: { type: String }, + coordinates: [] + }, { _id:false }); + + var schema = new Schema({ + title : String, + location: { type: locationSchema, required: true } + }); + schema.index({ location: '2dsphere' }); + + var Model = db.model('gh4044', schema); + + var query = { + location:{ + $geoWithin:{ + $geometry:{ + type: 'Polygon', + coordinates: [[[-1,0],[-1,3],[4,3],[4,0],[-1,0]]] + } + } + } + }; + Model.find(query, function(error) { + assert.ifError(error); + done(); + }); + }); }); describe('handles falsy and object projections with defaults (gh-3256)', function() { From c1245af8876ddf9ce465ca61dd951d2b33f4095b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 14:10:24 -0700 Subject: [PATCH 0475/2240] fix(query): add $geoWithin query casting for single embedded Fix #4044 --- lib/schema/embedded.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index e882af7b343..ad0f90a8bd0 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -48,6 +48,19 @@ function Embedded(schema, path, options) { Embedded.prototype = Object.create(SchemaType.prototype); +/** + * Special case for when users use a common location schema to represent + * locations for use with $geoWithin. + * https://docs.mongodb.org/manual/reference/operator/query/geoWithin/ + * + * @param {Object} val + * @api private + */ + +Embedded.prototype.$conditionalHandlers.$geoWithin = function(val) { + return { $geometry: this.castForQuery(val.$geometry) }; +}; + /** * Casts contents * From 5af4a404caa612b4e330ab1a0cf3494f06d0a7ea Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 14:15:31 -0700 Subject: [PATCH 0476/2240] refactor(test): reuse connections for query test --- test/query.test.js | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index 315874a65c6..8147009603b 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1470,26 +1470,6 @@ describe('Query', function() { }); }); - describe('gh-1950', function() { - it('ignores sort when passed to count', function(done) { - var db = start(); - var Product = db.model('Product', 'Product_setOptions_test'); - Product.find().sort({_id: 1}).count({}).exec(function(error) { - assert.ifError(error); - db.close(done); - }); - }); - - it('ignores count when passed to sort', function(done) { - var db = start(); - var Product = db.model('Product', 'Product_setOptions_test'); - Product.find().count({}).sort({_id: 1}).exec(function(error) { - assert.ifError(error); - db.close(done); - }); - }); - }); - describe('bug fixes', function() { var db; @@ -1501,6 +1481,24 @@ describe('Query', function() { db.close(done); }); + describe('gh-1950', function() { + it('ignores sort when passed to count', function(done) { + var Product = db.model('Product', 'Product_setOptions_test'); + Product.find().sort({_id: 1}).count({}).exec(function(error) { + assert.ifError(error); + done(); + }); + }); + + it('ignores count when passed to sort', function(done) { + var Product = db.model('Product', 'Product_setOptions_test'); + Product.find().count({}).sort({_id: 1}).exec(function(error) { + assert.ifError(error); + done(); + }); + }); + }); + it('excludes _id when select false and inclusive mode (gh-3010)', function(done) { var User = db.model('gh3010', { _id: { From 9c6a73d5aff13215cb69c1ace5e496e7f3dceee6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 15:59:37 -0700 Subject: [PATCH 0477/2240] feat(model): add basic proof of concept for error processing re: #2284 --- lib/model.js | 21 ++++++++++++++++----- lib/schema.js | 12 +++++++++++- test/document.test.js | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index bd15001caaf..f6a3c2ce330 100644 --- a/lib/model.js +++ b/lib/model.js @@ -266,6 +266,8 @@ Model.prototype.$__save = function(options, callback) { */ Model.prototype.save = function(options, fn) { + var _this = this; + if (typeof options === 'function') { fn = options; options = undefined; @@ -276,14 +278,20 @@ Model.prototype.save = function(options, fn) { } if (options.__noPromise) { - return this.$__save(options, fn); + return this.$__save(options, function(error, doc, numAffected) { + if (error) { + error = _this.schema.options.processError(error); + return fn(error); + } + fn && fn(null, doc, numAffected); + }); } - var _this = this; var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { _this.$__save(options, function(error, doc, numAffected) { if (error) { + error = _this.schema.options.processError(error); fn && fn(error); reject(error); return; @@ -698,6 +706,7 @@ Model.prototype.remove = function remove(options, fn) { this.$__.removing = new Promise.ES6(function(resolve, reject) { var where = _this.$__where(); if (where instanceof Error) { + where = _this.schema.options.processError(where); reject(where); fn && fn(where); return; @@ -714,7 +723,7 @@ Model.prototype.remove = function remove(options, fn) { fn && fn(null, _this); return; } - + err = _this.schema.options.processError(err); reject(err); fn && fn(err); }); @@ -789,6 +798,8 @@ Model.discriminator = function discriminator(name, schema) { delete b.toObject; delete a._id; delete b._id; + delete a.processError; + delete b.processError; if (!utils.deepEqual(a, b)) { throw new Error('Discriminator options are not customizable ' + @@ -1772,9 +1783,9 @@ Model.create = function create(doc, callback) { // Hack to avoid getting a promise because of // $__registerHooksFromSchema if (toSave.$__original_save) { - toSave.$__original_save({__noPromise: true}, callbackWrapper); + toSave.$__original_save({ __noPromise: true }, callbackWrapper); } else { - toSave.save({__noPromise: true}, callbackWrapper); + toSave.save({ __noPromise: true }, callbackWrapper); } }); }); diff --git a/lib/schema.js b/lib/schema.js index d9edc3ba985..c30b23dd68b 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -164,6 +164,7 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { kind: 'pre', hook: 'save', fn: function(next, options) { + var _this = this; // Nested docs have their own presave if (this.ownerDocument) { return next(); @@ -186,10 +187,16 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { // complain if (this.$__original_validate) { this.$__original_validate({__noPromise: true}, function(error) { + if (error) { + error = _this.schema.options.processError(error); + } next(error); }); } else { this.validate({__noPromise: true}, function(error) { + if (error) { + error = _this.schema.options.processError(error); + } next(error); }); } @@ -202,6 +209,7 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { hook: 'save', isAsync: true, fn: function(next, done) { + var _this = this; var subdocs = this.$__getAllSubdocs(); if (!subdocs.length || this.$__preSavingFromParent) { @@ -220,6 +228,7 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { delete subdocs[i].$__preSavingFromParent; } if (error) { + error = _this.schema.options.processError(error); done(error); return; } @@ -296,7 +305,8 @@ Schema.prototype.defaultOptions = function(options) { _id: true, noVirtualId: false, // deprecated, use { id: false } id: true, - typeKey: 'type' + typeKey: 'type', + processError: function(v) { return v; } }, options); if (options.read) { diff --git a/test/document.test.js b/test/document.test.js index 124b58b08c4..0ca1bdf6ad4 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2010,6 +2010,38 @@ describe('document', function() { }); }); + describe('error processing (gh-2284)', function() { + var db; + + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('save errors', function(done) { + var opts = { + processError: function() { + return new Error('catchAll'); + } + }; + + var schema = new Schema({ + name: { type: String, required: true } + }, opts); + + var Model = mongoose.model('gh2284', schema); + + Model.create({}, function(error) { + assert.ok(error); + assert.equal(error.toString(), 'Error: catchAll'); + done(); + }); + }); + }); + describe('bug fixes', function() { var db; From 3ce74fb18a40732d528e5d9535c401d9412ea51c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 16:18:45 -0700 Subject: [PATCH 0478/2240] feat(model): inherit options from discriminator base schema Fix #3414 --- lib/model.js | 45 +++++++++++++++++--------------- test/model.discriminator.test.js | 13 ++++----- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/model.js b/lib/model.js index f6a3c2ce330..837121170c9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -773,6 +773,14 @@ Model.prototype.model = function model(name) { * @api public */ +var CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = { + toJSON: true, + toObject: true, + _id: true, + id: true, + processError: true +}; + Model.discriminator = function discriminator(name, schema) { if (!(schema && schema.instanceOfSchema)) { throw new Error('You must pass a valid discriminator Schema'); @@ -789,24 +797,6 @@ Model.discriminator = function discriminator(name, schema) { '" cannot have field with name "' + key + '"'); } - function clean(a, b) { - a = utils.clone(a); - b = utils.clone(b); - delete a.toJSON; - delete a.toObject; - delete b.toJSON; - delete b.toObject; - delete a._id; - delete b._id; - delete a.processError; - delete b.processError; - - if (!utils.deepEqual(a, b)) { - throw new Error('Discriminator options are not customizable ' + - '(except toJSON, toObject, _id)'); - } - } - function merge(schema, baseSchema) { utils.merge(schema, baseSchema); @@ -819,12 +809,24 @@ Model.discriminator = function discriminator(name, schema) { schema.options.collection = baseSchema.options.collection; } - // throws error if options are invalid - clean(schema.options, baseSchema.options); - var toJSON = schema.options.toJSON; var toObject = schema.options.toObject; var _id = schema.options._id; + var id = schema.options.id; + + var keys = Object.keys(schema.options); + + for (var i = 0; i < keys.length; ++i) { + var _key = keys[i]; + if (!CUSTOMIZABLE_DISCRIMINATOR_OPTIONS[_key]) { + if (!utils.deepEqual(schema.options[_key], baseSchema.options[_key])) { + throw new Error('Can\'t customize discriminator option ' + _key + + ' (can only modify ' + + Object.keys(CUSTOMIZABLE_DISCRIMINATOR_OPTIONS).join(', ') + + ')'); + } + } + } schema.options = utils.clone(baseSchema.options); if (toJSON) schema.options.toJSON = toJSON; @@ -832,6 +834,7 @@ Model.discriminator = function discriminator(name, schema) { if (typeof _id !== 'undefined') { schema.options._id = _id; } + schema.options.id = id; schema.callQueue = baseSchema.callQueue.concat(schema.callQueue.slice(schema._defaultMiddleware.length)); schema._requiredpaths = undefined; // reset just in case Schema#requiredPaths() was called on either schema diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 92da5436f80..6536c5cee59 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -226,7 +226,7 @@ describe('model', function() { var PersonSchema = new BaseSchema(); var BossSchema = new BaseSchema({ department: String - }); + }, { id: false }); assert.doesNotThrow(function() { var Person = db.model('gh2821', PersonSchema); @@ -249,15 +249,12 @@ describe('model', function() { }); it('is not customizable', function(done) { - var errorMessage, - CustomizedSchema = new Schema({}, {capped: true}); - try { + var CustomizedSchema = new Schema({}, {capped: true}); + + assert.throws(function() { Person.discriminator('model-discriminator-custom', CustomizedSchema); - } catch (e) { - errorMessage = e.message; - } + }, /Can't customize discriminator option capped/); - assert.equal(errorMessage, 'Discriminator options are not customizable (except toJSON, toObject, _id)'); done(); }); }); From 975e5a344cbb58e4ecdd2e885e520ac14a8c4089 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Apr 2016 16:19:38 -0700 Subject: [PATCH 0479/2240] chore: now working on 4.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e62e829e919..ad561fd493d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.13-pre", + "version": "4.5.0-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c32c93eba8a8b8de2646dab5a7502b140d142712 Mon Sep 17 00:00:00 2001 From: Lukas Winter Date: Mon, 11 Apr 2016 17:44:37 +0200 Subject: [PATCH 0480/2240] make error throwing stricter when modifying array element selected via elemMatch --- lib/model.js | 13 +++++-------- test/model.field.selection.test.js | 21 +++++++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/model.js b/lib/model.js index 29c2d86b1bd..24304be9456 100644 --- a/lib/model.js +++ b/lib/model.js @@ -482,17 +482,14 @@ Model.prototype.$__delta = function() { var pathSplit = data.path.split('.'); var top = pathSplit[0]; if (this.$__.selected[top] && this.$__.selected[top].$elemMatch) { - //If the selected array entry was modified - if (pathSplit.length > 1 && pathSplit[1] == 0) { - where[top] = this.$__.selected[top]; //FIXME: will we overwrite anything? + // If the selected array entry was modified + if (pathSplit.length > 1 && pathSplit[1] == 0 && typeof where[top] === 'undefined') { + where[top] = this.$__.selected[top]; pathSplit[1] = '$'; data.path = pathSplit.join('.'); } - //if the selected array was entirely reassigned or uses an incompatible operation - else if (pathSplit.length == 1 && ( - typeof value.hasAtomics === 'undefined' || - '$set' in value._atomics || - '$pop' in value._atomics)) { + // if the selected array was modified in any other way throw an error + else { divergent.push(data.path); continue; } diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js index 801f0fc930f..1b56e486407 100644 --- a/test/model.field.selection.test.js +++ b/test/model.field.selection.test.js @@ -321,26 +321,31 @@ describe('model field selection', function() { B .findById(doc._id) - .select({ids: {$elemMatch: {$in: [_id2.toString()]}}}) .select({ids2: {$elemMatch: {$in: [_id1.toString()]}}}) .exec(function(err, found) { assert.ifError(err); - assert.equal(1, found.ids.length); assert.equal(1, found.ids2.length); - found.ids.pull(_id2); found.ids2.set(0, _id2); + found.save(function(err) { assert.ifError(err); - B.findById(doc._id).exec(function(err, found) { - assert.equal(1, found.ids.length); - assert.equal(_id1.toHexString(), found.ids[0].toHexString()); - + B + .findById(doc._id) + .select({ids: {$elemMatch: {$in: [_id2.toString()]}}}) + .select('ids2') + .exec(function(err, found) { assert.equal(2, found.ids2.length); assert.equal(_id2.toHexString(), found.ids2[0].toHexString()); assert.equal(_id2.toHexString(), found.ids2[1].toHexString()); - done(); + found.ids.pull(_id2); + + found.save(function(err) { + assert.ok(err); + + db.close(done); + }); }); }); }); From ea3085290375c9e1bd55a154acd17f5f3330051b Mon Sep 17 00:00:00 2001 From: Dmitry Kirilyuk Date: Thu, 14 Apr 2016 16:48:31 +0300 Subject: [PATCH 0481/2240] Fixed Model.remove return value type --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index bd15001caaf..1baac18ff48 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1071,7 +1071,7 @@ Model.discriminators; * * @param {Object} conditions * @param {Function} [callback] - * @return {Promise} Promise + * @return {Query} * @api public */ From a604129c7deedc0e463484131fd261199cae24a5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 15 Apr 2016 15:38:52 -0700 Subject: [PATCH 0482/2240] refactor(test): remove unused variables --- test/model.findOneAndUpdate.test.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 79ef364d685..dd8676b3bd6 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1551,8 +1551,6 @@ describe('model: findByIdAndUpdate:', function() { }); it('passes raw result as 3rd param (gh-3173)', function(done) { - var db = start(); - var testSchema = new mongoose.Schema({ test: String }); @@ -1566,14 +1564,11 @@ describe('model: findByIdAndUpdate:', function() { assert.ifError(error); assert.ok(res); assert.ok(res.ok); - - db.close(done); + done(); }); }); it('raw result as 3rd param w/ no result (gh-4023)', function(done) { - var db = start(); - var testSchema = new mongoose.Schema({ test: String }); @@ -1588,9 +1583,7 @@ describe('model: findByIdAndUpdate:', function() { assert.ok(res); assert.ok(res.ok); - options.new = false; - - db.close(done); + done(); }); }); }); From 1928b30809adeb6d32c9fe37666fa625931462f9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 15 Apr 2016 16:07:19 -0700 Subject: [PATCH 0483/2240] test(schema): add coverage for timestamps with nested docs re: #4049 --- test/schema.timestamps.test.js | 37 ++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js index 5cabfcc4e4b..e31c518da59 100644 --- a/test/schema.timestamps.test.js +++ b/test/schema.timestamps.test.js @@ -171,6 +171,43 @@ describe('schema options.timestamps', function() { }); }); + it('nested docs (gh-4049)', function(done) { + var GroupSchema = new Schema({ + cats: [CatSchema] + }); + + var Group = conn.model('gh4049', GroupSchema); + var now = Date.now(); + Group.create({ cats: [{ name: 'Garfield' }] }, function(error, group) { + assert.ifError(error); + assert.ok(group.cats[0].createdAt); + assert.ok(group.cats[0].createdAt.getTime() >= now); + done(); + }); + }); + + it('nested docs with push (gh-4049)', function(done) { + var GroupSchema = new Schema({ + cats: [CatSchema] + }); + + var Group = conn.model('gh4049_0', GroupSchema); + var now = Date.now(); + Group.create({ cats: [{ name: 'Garfield' }] }, function(error, group) { + assert.ifError(error); + group.cats.push({ name: 'Keanu' }); + group.save(function(error) { + assert.ifError(error); + Group.findById(group._id, function(error, group) { + assert.ifError(error); + assert.ok(group.cats[1].createdAt); + assert.ok(group.cats[1].createdAt.getTime() > now); + done(); + }); + }); + }); + }); + after(function(done) { Cat.remove({}, function() { conn.close(done); From fa39d45551f5c841da91892a16f241ef9fd172c3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 16 Apr 2016 12:43:39 -0700 Subject: [PATCH 0484/2240] test(query): repro #3385 --- lib/services/common.js | 59 +++++++++++++++ lib/services/setDefaultsOnInsert.js | 112 ++++++++++++++++++++++++++++ test/query.test.js | 21 ++++++ 3 files changed, 192 insertions(+) create mode 100644 lib/services/common.js create mode 100644 lib/services/setDefaultsOnInsert.js diff --git a/lib/services/common.js b/lib/services/common.js new file mode 100644 index 00000000000..3d3d28e91c7 --- /dev/null +++ b/lib/services/common.js @@ -0,0 +1,59 @@ +'use strict'; + +var ObjectId = require('../types/objectid'); + +exports.flatten = flatten; +exports.modifiedPaths = modifiedPaths; + +function flatten(update, path) { + var keys = Object.keys(update || {}); + var numKeys = keys.length; + var result = {}; + path = path ? path + '.' : ''; + + for (var i = 0; i < numKeys; ++i) { + var key = keys[i]; + var val = update[key]; + if (shouldFlatten(val)) { + var flat = flatten(val, path + key); + for (var k in flat) { + result[k] = flat[k]; + } + if (Array.isArray(val)) { + result[path + key] = val; + } + } else { + result[path + key] = val; + } + } + + return result; +} + +function modifiedPaths(update, path, result) { + var keys = Object.keys(update || {}); + var numKeys = keys.length; + result = result || {}; + path = path ? path + '.' : ''; + + for (var i = 0; i < numKeys; ++i) { + var key = keys[i]; + var val = update[key]; + + result[path + key] = true; + if (shouldFlatten(val)) { + modifiedPaths(val, path + key, result); + } + } + + return result; +} + +function shouldFlatten(val) { + return val && + typeof val === 'object' && + !(val instanceof Date) && + !(val instanceof ObjectId) && + (!Array.isArray(val) || val.length > 0) && + !(val instanceof Buffer); +} diff --git a/lib/services/setDefaultsOnInsert.js b/lib/services/setDefaultsOnInsert.js new file mode 100644 index 00000000000..f122f400fa4 --- /dev/null +++ b/lib/services/setDefaultsOnInsert.js @@ -0,0 +1,112 @@ +'use strict'; + +var flatten = require('./common').flatten; +var modifiedPaths = require('./common').modifiedPaths; + +/** + * Applies defaults to update and findOneAndUpdate operations. + * + * @param {Query} query + * @param {Schema} schema + * @param {Object} castedDoc + * @param {Object} options + * @method setDefaultsOnInsert + * @api private + */ + +module.exports = function(query, schema, castedDoc, options) { + var keys = Object.keys(castedDoc || {}); + var updatedKeys = {}; + var updatedValues = {}; + var numKeys = keys.length; + var hasDollarUpdate = false; + var modified = {}; + + for (var i = 0; i < numKeys; ++i) { + if (keys[i].charAt(0) === '$') { + modifiedPaths(castedDoc[keys[i]], '', modified); + var flat = flatten(castedDoc[keys[i]]); + var paths = Object.keys(flat); + var numPaths = paths.length; + for (var j = 0; j < numPaths; ++j) { + var updatedPath = paths[j].replace('.$.', '.0.'); + updatedPath = updatedPath.replace(/\.\$$/, '.0'); + if (keys[i] === '$set' || keys[i] === '$setOnInsert') { + updatedValues[updatedPath] = flat[paths[j]]; + } else if (keys[i] === '$unset') { + updatedValues[updatedPath] = undefined; + } + updatedKeys[updatedPath] = true; + } + hasDollarUpdate = true; + } + } + + if (!hasDollarUpdate) { + modifiedPaths(castedDoc, '', modified); + updatedValues = flatten(castedDoc); + updatedKeys = Object.keys(updatedValues); + } + + if (options && options.upsert) { + paths = Object.keys(query._conditions); + numPaths = keys.length; + for (i = 0; i < numPaths; ++i) { + var path = paths[i]; + var condition = query._conditions[path]; + if (condition && typeof condition === 'object') { + var conditionKeys = Object.keys(condition); + var numConditionKeys = conditionKeys.length; + var hasDollarKey = false; + for (j = 0; j < numConditionKeys; ++j) { + if (conditionKeys[j].charAt(0) === '$') { + hasDollarKey = true; + break; + } + } + if (hasDollarKey) { + continue; + } + } + updatedKeys[path] = true; + modified[path] = true; + } + + if (options.setDefaultsOnInsert) { + schema.eachPath(function(path, schemaType) { + if (path === '_id') { + // Ignore _id for now because it causes bugs in 2.4 + return; + } + if (schemaType.$isSingleNested) { + // Only handle nested schemas 1-level deep to avoid infinite + // recursion re: https://github.com/mongodb-js/mongoose-autopopulate/issues/11 + schemaType.schema.eachPath(function(_path, _schemaType) { + if (path === '_id') { + // Ignore _id for now because it causes bugs in 2.4 + return; + } + + var def = _schemaType.getDefault(null, true); + if (!modified[path + '.' + _path] && typeof def !== 'undefined') { + castedDoc = castedDoc || {}; + castedDoc.$setOnInsert = castedDoc.$setOnInsert || {}; + castedDoc.$setOnInsert[path + '.' + _path] = def; + updatedValues[path + '.' + _path] = def; + } + }); + } else { + var def = schemaType.getDefault(null, true); + if (!modified[path] && typeof def !== 'undefined') { + castedDoc = castedDoc || {}; + castedDoc.$setOnInsert = castedDoc.$setOnInsert || {}; + castedDoc.$setOnInsert[path] = def; + updatedValues[path] = def; + } + } + }); + } + } + + return castedDoc; +}; diff --git a/test/query.test.js b/test/query.test.js index 8147009603b..915958a89c0 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1615,6 +1615,27 @@ describe('Query', function() { done(); }); }); + + it('setDefaultsOnInsert with empty update (gh-3825)', function(done) { + var schema = new mongoose.Schema({ + test: { type: Number, default: 8472 }, + name: String + }); + + var MyModel = db.model('gh3825', schema); + + var opts = { setDefaultsOnInsert: true, upsert: true }; + MyModel.update({}, {}, opts, function(error) { + assert.ifError(error); + MyModel.findOne({}, function(error, doc) { + assert.ifError(error); + assert.ok(doc); + assert.strictEqual(doc.test, 8472); + assert.ok(!doc.name); + done(); + }); + }); + }); }); describe('handles falsy and object projections with defaults (gh-3256)', function() { From 7e626435c604efd62dea7ad16d32ffc96e0cbbb6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 16 Apr 2016 12:44:43 -0700 Subject: [PATCH 0485/2240] fix(query): run setDefaultsOnInsert before checking if doc is empty Fix #3835 --- lib/query.js | 19 ++--- lib/services/updateValidators.js | 116 +------------------------------ 2 files changed, 14 insertions(+), 121 deletions(-) diff --git a/lib/query.js b/lib/query.js index 0dcbaa05e45..4fc177c797f 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2,16 +2,17 @@ * Module dependencies. */ -var mquery = require('mquery'); -var util = require('util'); -var readPref = require('./drivers').ReadPreference; var PromiseProvider = require('./promise_provider'); -var updateValidators = require('./services/updateValidators'); -var utils = require('./utils'); -var helpers = require('./queryhelpers'); var QueryStream = require('./querystream'); var StrictModeError = require('./error/strict'); var cast = require('./cast'); +var helpers = require('./queryhelpers'); +var mquery = require('mquery'); +var readPref = require('./drivers').ReadPreference; +var setDefaultsOnInsert = require('./services/setDefaultsOnInsert'); +var updateValidators = require('./services/updateValidators'); +var util = require('util'); +var utils = require('./utils'); /** * Query constructor used for building queries. @@ -1750,6 +1751,7 @@ Query.prototype._findAndModify = function(type, callback) { } castedDoc = castDoc(this, opts.overwrite); + castedDoc = setDefaultsOnInsert(this, schema, castedDoc, opts); if (!castedDoc) { if (opts.upsert) { // still need to do the upsert to empty doc @@ -1822,7 +1824,7 @@ Query.prototype._findAndModify = function(type, callback) { }); }; - if ((opts.runValidators || opts.setDefaultsOnInsert) && doValidate) { + if (opts.runValidators && doValidate) { var _callback = function(error) { if (error) { return callback(error); @@ -1910,7 +1912,7 @@ Query.prototype._execUpdate = function(callback) { return this; } - if (this.options.runValidators || this.options.setDefaultsOnInsert) { + if (this.options.runValidators) { _this = this; doValidate = updateValidators(this, schema, castedDoc, options); var _callback = function(err) { @@ -2110,6 +2112,7 @@ Query.prototype.update = function(conditions, doc, options, callback) { } } + castedDoc = setDefaultsOnInsert(this, this.schema, castedDoc, options); if (!castedDoc) { // Make sure promises know that this is still an update, see gh-2796 this.op = 'update'; diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index fd1298914b2..6f97bbe1c85 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -2,9 +2,10 @@ * Module dependencies. */ -var async = require('async'); var ValidationError = require('../error/validation.js'); -var ObjectId = require('../types/objectid'); +var async = require('async'); +var flatten = require('./common').flatten; +var modifiedPaths = require('./common').modifiedPaths; /** * Applies validators and defaults to update and findOneAndUpdate operations, @@ -52,64 +53,6 @@ module.exports = function(query, schema, castedDoc, options) { updatedKeys = Object.keys(updatedValues); } - if (options && options.upsert) { - paths = Object.keys(query._conditions); - numPaths = keys.length; - for (i = 0; i < numPaths; ++i) { - var path = paths[i]; - var condition = query._conditions[path]; - if (condition && typeof condition === 'object') { - var conditionKeys = Object.keys(condition); - var numConditionKeys = conditionKeys.length; - var hasDollarKey = false; - for (j = 0; j < numConditionKeys; ++j) { - if (conditionKeys[j].charAt(0) === '$') { - hasDollarKey = true; - break; - } - } - if (hasDollarKey) { - continue; - } - } - updatedKeys[path] = true; - modified[path] = true; - } - - if (options.setDefaultsOnInsert) { - schema.eachPath(function(path, schemaType) { - if (path === '_id') { - // Ignore _id for now because it causes bugs in 2.4 - return; - } - if (schemaType.$isSingleNested) { - // Only handle nested schemas 1-level deep to avoid infinite - // recursion re: https://github.com/mongodb-js/mongoose-autopopulate/issues/11 - schemaType.schema.eachPath(function(_path, _schemaType) { - if (path === '_id') { - // Ignore _id for now because it causes bugs in 2.4 - return; - } - - var def = _schemaType.getDefault(null, true); - if (!modified[path + '.' + _path] && typeof def !== 'undefined') { - castedDoc.$setOnInsert = castedDoc.$setOnInsert || {}; - castedDoc.$setOnInsert[path + '.' + _path] = def; - updatedValues[path + '.' + _path] = def; - } - }); - } else { - var def = schemaType.getDefault(null, true); - if (!modified[path] && typeof def !== 'undefined') { - castedDoc.$setOnInsert = castedDoc.$setOnInsert || {}; - castedDoc.$setOnInsert[path] = def; - updatedValues[path] = def; - } - } - }); - } - } - var updates = Object.keys(updatedValues); var numUpdates = updates.length; var validatorsToExecute = []; @@ -149,56 +92,3 @@ module.exports = function(query, schema, castedDoc, options) { }); }; }; - -function modifiedPaths(update, path, result) { - var keys = Object.keys(update); - var numKeys = keys.length; - result = result || {}; - path = path ? path + '.' : ''; - - for (var i = 0; i < numKeys; ++i) { - var key = keys[i]; - var val = update[key]; - - result[path + key] = true; - if (shouldFlatten(val)) { - modifiedPaths(val, path + key, result); - } - } - - return result; -} - -function flatten(update, path) { - var keys = Object.keys(update); - var numKeys = keys.length; - var result = {}; - path = path ? path + '.' : ''; - - for (var i = 0; i < numKeys; ++i) { - var key = keys[i]; - var val = update[key]; - if (shouldFlatten(val)) { - var flat = flatten(val, path + key); - for (var k in flat) { - result[k] = flat[k]; - } - if (Array.isArray(val)) { - result[path + key] = val; - } - } else { - result[path + key] = val; - } - } - - return result; -} - -function shouldFlatten(val) { - return val && - typeof val === 'object' && - !(val instanceof Date) && - !(val instanceof ObjectId) && - (!Array.isArray(val) || val.length > 0) && - !(val instanceof Buffer); -} From e6a079f1394b50d89a469988068c21231329c715 Mon Sep 17 00:00:00 2001 From: Robert Jones Date: Sun, 17 Apr 2016 09:58:43 -0500 Subject: [PATCH 0486/2240] Add docs favicons. --- docs/api.jade | 1 + docs/images/favicon/android-icon-144x144.png | Bin 0 -> 5625 bytes docs/images/favicon/android-icon-192x192.png | Bin 0 -> 6815 bytes docs/images/favicon/android-icon-36x36.png | Bin 0 -> 1412 bytes docs/images/favicon/android-icon-48x48.png | Bin 0 -> 1673 bytes docs/images/favicon/android-icon-72x72.png | Bin 0 -> 2156 bytes docs/images/favicon/android-icon-96x96.png | Bin 0 -> 3637 bytes docs/images/favicon/apple-icon-114x114.png | Bin 0 -> 4335 bytes docs/images/favicon/apple-icon-120x120.png | Bin 0 -> 4607 bytes docs/images/favicon/apple-icon-144x144.png | Bin 0 -> 5625 bytes docs/images/favicon/apple-icon-152x152.png | Bin 0 -> 5986 bytes docs/images/favicon/apple-icon-180x180.png | Bin 0 -> 7209 bytes docs/images/favicon/apple-icon-57x57.png | Bin 0 -> 1874 bytes docs/images/favicon/apple-icon-60x60.png | Bin 0 -> 1864 bytes docs/images/favicon/apple-icon-72x72.png | Bin 0 -> 2156 bytes docs/images/favicon/apple-icon-76x76.png | Bin 0 -> 2159 bytes .../images/favicon/apple-icon-precomposed.png | Bin 0 -> 7304 bytes docs/images/favicon/apple-icon.png | Bin 0 -> 7304 bytes docs/images/favicon/browserconfig.xml | 2 + docs/images/favicon/favicon-16x16.png | Bin 0 -> 1031 bytes docs/images/favicon/favicon-32x32.png | Bin 0 -> 1364 bytes docs/images/favicon/favicon-96x96.png | Bin 0 -> 3637 bytes docs/images/favicon/favicon.ico | Bin 0 -> 1150 bytes docs/images/favicon/manifest.json | 41 ++++++++++++++++++ docs/images/favicon/ms-icon-144x144.png | Bin 0 -> 5625 bytes docs/images/favicon/ms-icon-150x150.png | Bin 0 -> 5906 bytes docs/images/favicon/ms-icon-310x310.png | Bin 0 -> 13953 bytes docs/images/favicon/ms-icon-70x70.png | Bin 0 -> 2106 bytes docs/includes/favicon.jade | 13 ++++++ docs/index.jade | 1 + docs/layout.jade | 18 ++++++++ docs/redirect.jade | 1 + 32 files changed, 77 insertions(+) create mode 100644 docs/images/favicon/android-icon-144x144.png create mode 100644 docs/images/favicon/android-icon-192x192.png create mode 100644 docs/images/favicon/android-icon-36x36.png create mode 100644 docs/images/favicon/android-icon-48x48.png create mode 100644 docs/images/favicon/android-icon-72x72.png create mode 100644 docs/images/favicon/android-icon-96x96.png create mode 100644 docs/images/favicon/apple-icon-114x114.png create mode 100644 docs/images/favicon/apple-icon-120x120.png create mode 100644 docs/images/favicon/apple-icon-144x144.png create mode 100644 docs/images/favicon/apple-icon-152x152.png create mode 100644 docs/images/favicon/apple-icon-180x180.png create mode 100644 docs/images/favicon/apple-icon-57x57.png create mode 100644 docs/images/favicon/apple-icon-60x60.png create mode 100644 docs/images/favicon/apple-icon-72x72.png create mode 100644 docs/images/favicon/apple-icon-76x76.png create mode 100644 docs/images/favicon/apple-icon-precomposed.png create mode 100644 docs/images/favicon/apple-icon.png create mode 100644 docs/images/favicon/browserconfig.xml create mode 100644 docs/images/favicon/favicon-16x16.png create mode 100644 docs/images/favicon/favicon-32x32.png create mode 100644 docs/images/favicon/favicon-96x96.png create mode 100644 docs/images/favicon/favicon.ico create mode 100644 docs/images/favicon/manifest.json create mode 100644 docs/images/favicon/ms-icon-144x144.png create mode 100644 docs/images/favicon/ms-icon-150x150.png create mode 100644 docs/images/favicon/ms-icon-310x310.png create mode 100644 docs/images/favicon/ms-icon-70x70.png create mode 100644 docs/includes/favicon.jade diff --git a/docs/api.jade b/docs/api.jade index 455c1ec4f75..b7790a38fc3 100644 --- a/docs/api.jade +++ b/docs/api.jade @@ -4,6 +4,7 @@ html(lang='en') meta(charset="utf-8") meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") title Mongoose API v#{package.version} + include ./includes/favicon.jade link( rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css") link(href='//fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') diff --git a/docs/images/favicon/android-icon-144x144.png b/docs/images/favicon/android-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..81e370f6e6d7c56989f1908c18d1f004449ac6e5 GIT binary patch literal 5625 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 E0P&?VsQ>@~ literal 0 HcmV?d00001 diff --git a/docs/images/favicon/android-icon-48x48.png b/docs/images/favicon/android-icon-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..c1ceb6d93d946a05d9d23efce12231251df31af6 GIT binary patch literal 1673 zcmZ{k4K&kh9LJxD*b{N7eoO^uAaE-Ned z^*wKDdTQCS;|mv_P*Xdjt$h)OYeXW&>({Nt#V6F&e*@q}cD5LRL=5JhP&oeaV}D~~ zsh3yMf(6+$+MCi>(R|pBf$Q zs;RjEL5WIASp>or8=KtCn=|nEL;z&Q#_#ItQWr1otgcR7vZU10v-R4w$xojq6pGQ_ z-uDd+_hVwt>glCwX|)s-NY|~ai;f=Y?j9c+>ZqtFc6U!%wCMNP*vt(ZzD`fSx_Wh} zwe>oaS>)>a;mMObAt6ndE+r``Wty2)ayTb7GzuAvG9RCjo}N!{-xluJaeBpy_R`XB zx%@JfI@H!CKYTcS&6>fMmYMPKF9QRYDU{~Cyv}>~t~onjAQDI3y^|UlWp3Q~xvQ&! z&AuBNIy*I$guy&cNx89a-?!P>SNZv)@83U+kMDl)pf)P%I2N0}YE_L;_@=V5Mj)u< za?hKYzN6Y8k(oqU9- zo$EV+?G2$eC@{uw*vfQz6v#4M1(9GFj?;a*vFN~{L8f1awJO8k<`8D95qqgS951bm z&pk_av$}nvD6={)`%HOqp&s-2U2$Iet(5HSk_$CQjr@+CE=#i3S&&*#6PF}Y)0KYo z@s2CHRqjbWiqZGogwMzRx)A61OR!ED4!6(CGD<6Uvpx>Dix`2$uGufdZ3+7hCh82M zM_H0nZt>z$zLBFOvEIb~NuRW}ax$JJd0>n++m9RVIs5#jw2!P9Ta?AZO?X#|pB62V z44Opdt6ANN!Q&OtQ}@+X5}?|>+NK$O+H$h;Ipd6TBNp=5UO&!iKmRVSzfXc{Mo279 zlEIaVS(0{o`Y3rsSFyjBgiY?G32*HNU-x7LPoLl=ga4BIA^xFV9BluEG!WqHFZ zf`lbetX>Yw{c%~wQmmxr&~iqZnyo(G)o!VCGf8HxQo`P#mE1#a=wxN}=bLi37cfdS zESSfpc49@E_{TS%lgDJrjhwiL@=U*-nnGWQ^7K5m+0AB+hds$MPpkrIj$}#onA4wI zJL?k)j7(N|9Qz|*?5=6Q{n&DE^oV8Fcf|>K&W1icZJErLENVYUBsio6?QI&W6|F4v zel7T}SkY~20?TPx~N`{{z3Bs!Xkoroap}#Pnz@xBnv!e|QOseIp*u`97bmr;&%XsmEMBF*#MUjyzimaT6xbVUdQ8XU`KUPKLhX-#d_jLV9$AyVf z047r*E69RIg+B#w22n(7o{k4E1_6+r-PvrLxhckn7ehn>5QKw}XaQ`PM5S2-uo0L9v1tJ?4Y8!bmM{U0AfW4$>SIgM41lrC K)uF_W755Ke$G&L* literal 0 HcmV?d00001 diff --git a/docs/images/favicon/android-icon-72x72.png b/docs/images/favicon/android-icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..39b576e8013a59c1313b128620319c1d3ee97616 GIT binary patch literal 2156 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 z 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 C4|a6` literal 0 HcmV?d00001 diff --git a/docs/images/favicon/apple-icon-144x144.png b/docs/images/favicon/apple-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..81e370f6e6d7c56989f1908c18d1f004449ac6e5 GIT binary patch literal 5625 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 O2jF1mOerLLUHd=bK}7ce literal 0 HcmV?d00001 diff --git a/docs/images/favicon/apple-icon-60x60.png b/docs/images/favicon/apple-icon-60x60.png new file mode 100644 index 0000000000000000000000000000000000000000..81600df0a555f6819a63fce670b593f724f526b7 GIT binary patch literal 1864 zcmZ{kc{J2}AIHDerYYHHM6M<4#VnSYF~vpJ$I@^yEgp{<^BXfwjLgX6mQIg*Q%Hmf zV{C~wG!h_q0~ zLSy56EcT|WYYl_ZmYqG>+4);aN|B9C5rI%>ZT&DR>dWZp%iP>_6e>|h<~#sNva(ln zbZQ}Ju&L?W+}yjncdJ7}vi0?o5r_*?QYlDeJ`UHKmUcfPA_0Kgo}P;n6CWEJZ+m&A z?A&<)fJABO>7JfCHalHi{gQ&hz2M;S*RLONxn*8ny;W5OczgyLou#XrV`!MYcdtNO z`?8u^TUOTE^73d~TbYkfs*+NUfkBp@Ub4J=UrmiTFmUMEv+?%!$+vGuC6cc4^2aeT z$=kN|-n%!^-d^hHSiEoF;FBjW1OhRYx(r`!Yim7+Q%<2QO-)rDJ=&I&v$nF*dFxg_ z29v3&dB@*BOGoFWQ22Frw%pfOl9`#RsF)-tR}&g4*t6$NNl9OAZ8{pg`t93;6DOYj z{Ikf+Y~br70_SS5)+f#g|o8uaZc$Oy;N7)<-;E$CMh(x{;iCR-rFYVkp+|u$YFYiNreNScO>-_xJ1qI!A?!>BP#KTP{MfY@b z1{dVC-C<{Yr2AnWY&Ylb!1X!D9_}{2hqI%>{}yLdC4+P(mB=H;D9ZaB#BzB&9kGgzjt=i%p6Z5T z=^r+LTOlGyA7`RbWGic;G_Hq2O(XpKm6Ug@Ypag#@YB{pD`p;azXvqOa@ADxM06pt zV`|XM^kS*4cT;b(x#2&J_hw+t_8AlRE1DcDXnRbdj7|)y9%3+Z^PW;EL4KN`BQNV{ zLRoj~k>8q)-!=qoM~&92`#1y$qyyeuvcL4gM!y=j(fLM3Kpfi3*~Rs;;U0@{M7j+G z7LIg@YEI7Yih-^HR8BQua18cETjGGy+fE?uQ9y++Zcy4chk1J7#BWmIEywp9{0PkkCP`lDMJz`eZ7$7Lv%fO{KrN|twT-cj3V|+dYh?Ihv&cS z)-a78F{hlCpj^>2RWiu7n=UMZ;-}`9`#V)`be{;es3&!vw$hpBM;J(Upy;gNYuh_| z?d1-LXqD$u>v~mw8R;N+*{pj0$CT3@<&~)JAX$EbkeE>iUOwoNxzD^oY)oWGf+mG= zt1Dto@cmsyv18;(VJEl$*NVd@m7RD4u5fHY1HlOnzj%PBr7Y~Ti)6jkbK;p`BsQ6> z(v}flNwLt)M$tktqNa8rcaCuVA4&9E-TH$1*a?EUuy&?PbPQp7yYA$4Pc?_g40uYZ z3G1wQSa!%dZ2Da_r$M2~L_@APM9l$!e}6Q86%rp64mYA9-{laWLE}T@&?pEtz!HZi zSm3NJ@I-&SHQ9hjMfY7$SybVXF(5w6?(6Sl}&neencc7M~wU#$sb)VleDY8Xho>;YNk^ zCQQMCKx0$UpA{WWCzGAIq0!+`1fNW%z$g#kuW#JP{*C#gCYj8F*kLR_z}s3Xf~a#a zgWjU^Cqrd3_^eH&y-W`QBfGaC-t2IQ9~%jQKX!$Uj0pSTZlKTKbiDmx3gE2?I9r?* ziGZJ_Gbdq0af{B6?4KZjb8^bOYQGr@+!6}#^8iftaR@#>HavoVoEwH^(oV8Nxe+|< zUk`(Y=n%w&EJ<`4-jYDFqSGL}C5}d-<4F*ageT%La0Uk6U$&OK7_I<3Tzs4>oI>LN E2jE#EcmMzZ literal 0 HcmV?d00001 diff --git a/docs/images/favicon/apple-icon-72x72.png b/docs/images/favicon/apple-icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..39b576e8013a59c1313b128620319c1d3ee97616 GIT binary patch literal 2156 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 literal 0 HcmV?d00001 diff --git a/docs/images/favicon/apple-icon-precomposed.png b/docs/images/favicon/apple-icon-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..06d1d487a8c04783c3b44dcae6dcddf0772af9bd GIT binary patch literal 7304 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

+OQ0f>lFspjrLU>Y%A^sI6e{Nk>@YLpt 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 literal 0 HcmV?d00001 diff --git a/docs/images/favicon/apple-icon.png b/docs/images/favicon/apple-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..06d1d487a8c04783c3b44dcae6dcddf0772af9bd GIT binary patch literal 7304 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

+OQ0f>lFspjrLU>Y%A^sI6e{Nk>@YLpt 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 literal 0 HcmV?d00001 diff --git a/docs/images/favicon/browserconfig.xml b/docs/images/favicon/browserconfig.xml new file mode 100644 index 00000000000..c5541482230 --- /dev/null +++ b/docs/images/favicon/browserconfig.xml @@ -0,0 +1,2 @@ + +#ffffff \ No newline at end of file diff --git a/docs/images/favicon/favicon-16x16.png b/docs/images/favicon/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..2c76d9a7777d596d8ad47e2ac5224bf0a2b6c6a3 GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstUx|vage(c z!@6@aFM%9|WRD45bDP46hOx7_4S6Fo+k-*%fF5lz0{3 z6XN>gNJ-R8w=fuI|C!y?=lI zesT8fA`6SNlP9n8^4b_4zC9&nv8Cl&fB!evukXpvU+(0zEhS|`SlAqG?Mw6LKR%+b+# zb@}q9sHp${{>|0Xdwu!xfy&CwF){NE4exH<`u*+Odpmag`0(NBi4(uSeY>}Fr$mON zE6~@BN#5=*9BuceRslJj1s;*bK-vS0-A-oP0U4d1E{-7*my;6`Qj*dVQ5lE9*7Hw2#E=b3QwOfWzw{XPZK6g4u25(Bp@g(F!XW2b%6^h6E0tR#=s;SYpZZ_ zP5yy|j1(Rr14C2hNzZ? z;mh1A2`_n-YHLg-EiN!fGBK3glT7XT<+>Z_DAf|zh?11Vl2ohYqEsNoU}RuurfXoL zYiJ%~Xkuk-Ze?PqZD3$!U@)KS1TY04X~@k_$xN%nt>ImG!AGD5H;@g*`DrEPiAAXl zp1FzXslJKnnaSA-W_sp&7P^)SKr2mj4NP?njT8b6%@i_9N(!v>^~=l4^)f-Kff%S- zFTW`LPTO0cfeaEL6GJjebCayBT=J7kb5rw5tgHfnN{bl`m;c|bkERA}r*C=uTl}I8f@y*OlEvYO>WdOTMzaTH&ep8qq znmN89KvfKeCT0ef2F4a{j|ig%;fyMVtqu!=%*&7rlzGDStKPI8kt!bCncsD8W|*7BpF(ynp+r} b8|ndd=mFg~Lz-;^&;|xiS3j3^P63T literal 0 HcmV?d00001 diff --git a/docs/images/favicon/favicon-32x32.png b/docs/images/favicon/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..48afe4233ecc2eadc26c108e24aec681e3f202b9 GIT binary patch literal 1364 zcmZ{j3rtg27{?E_V5x#St>A-Mb)Z{?-rLr;-WZpXQd$&;(1|7{qb;`&rBLauh*=ym zR~~}mi>d7dIv*`%$UsHG2W}05_yiRchNDP@f=*s>qT)`?k`a@g9yvKN zYa{)rbEyCTKZ#fv3nSfADU)C;Jds-u16d`A769<;zA0~I-f--tkBtlm<+tbec}Rsg zHX48(Apm6T24Dl$8TUs7h zRMaFT*+ilu7OR-Uv9DQkg&>~Yy!oWIHjhf(>*wdJs~d7UtCh;V{{BV)awbjMXp_=Sid-GWlq5aI4LhPo?hj_iwdY&&0)LlSn08?)9v!wz9I$ z3m2{%jb;Yp$3=@=jg8ibh~rGABQvwDw6wFj`cZj#V_seniWbu8PaTf@DO2(&luJ6@ z)B5`J3dIGr`kY+;qP^YS-2Cp%n`{8G0Jx~pydD~=+rE9zGGX@%0^e`0&vD z`NKUuCI;i~v1894J-V8fR+pasqNC&T)~$aJ4mRZG_B1r;Z+!R8^UCtokwTE|9VCVW zU!8cP9!5`J3`C7vRzYBaL@1E*n-mEdBvFWR_WHoA{GX0~e{jZ)E~l#tPw43mm_F;1 z*)zOzker;=;wVW|L-?$QM#j=FKDS#-ZFXDfW;F{@Yx;ZLwtl;NZeXV0em0AXE@xL) zoUJ^2e%-lq-IehM9g(_it0B(t3NT)duv!OQ-X_=2CGP&yt_8qFj_Mop-bEv4?KTR6 zW_{|U&6wleBb+?XkwM$-sJ~`jP&EC3mD2rL@Vt{5H0!BT*Bs4kDZ47coRn|glucWS zEHqyF_5q21`fkVxN?GxSnG%86H(a0*&uKFq?-5fo83nXM8MLL+MGWh2mg2b^1-GoE z0cz}K!}Nt4gMvgqqjE?rF!I*iFoOG^vW zcxYH59hQ=+>M%Zsh9J=6C{-J@atsruC=6OWnZU3Zi0T1)`h6|)Bj!U+3{&G8m6`zP z3f44`3V#_0nBem-6R$}m)E=azY#{|Ab0#3s8ZAzw>u~U4S4>^9>dVUYYd`XdmO=`k z94@i~Ve`4@OSy6YBGV@L#A$Zm00|F2WLf1|T0ddw>sSd;YLakxe5N*;NJ>#Lm9lLb zMM|=s`QO7ZaXF4FaTZ@LLs?utTQ0*<79!)zQ9jP&qdYVWD#GCYj?D9^fEj=!Vy&<| HJR$QRpIa|) literal 0 HcmV?d00001 diff --git a/docs/images/favicon/favicon-96x96.png b/docs/images/favicon/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..c1bcfdc8891bd567da54fa0d3803e536b899c8e4 GIT binary patch literal 3637 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 Rec0Hz6jjxztfE54$ literal 0 HcmV?d00001 diff --git a/docs/images/favicon/manifest.json b/docs/images/favicon/manifest.json new file mode 100644 index 00000000000..013d4a6a533 --- /dev/null +++ b/docs/images/favicon/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "App", + "icons": [ + { + "src": "\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} \ No newline at end of file diff --git a/docs/images/favicon/ms-icon-144x144.png b/docs/images/favicon/ms-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..81e370f6e6d7c56989f1908c18d1f004449ac6e5 GIT binary patch literal 5625 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 literal 0 HcmV?d00001 diff --git a/docs/images/favicon/ms-icon-310x310.png b/docs/images/favicon/ms-icon-310x310.png new file mode 100644 index 0000000000000000000000000000000000000000..20b18479ad42dff15947b813ad8e774fe47c4904 GIT binary patch literal 13953 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 Mpe|n~`!?kN0C+B$IsgCw literal 0 HcmV?d00001 diff --git a/docs/images/favicon/ms-icon-70x70.png b/docs/images/favicon/ms-icon-70x70.png new file mode 100644 index 0000000000000000000000000000000000000000..a83d8a61ad5373e5d06a84248cbfa0304b8176ff GIT binary patch literal 2106 zcmZ{ldo+|=AICS7DN>Z%pvzbx)LfpyjHYu6A$qAvDqi#&GlNksF(uY<&WunrUdAPt z-s_2?oIbfj zPD2g=u*1gM!XA!Rn{69nv!B`h6b@TF&FstoD2v^`PL+XksX+Ua=AgKJ&u2J6)2!|7 z00_|qfE^Bi1Ri2f0B{Wtz@!@hI(ye}-Ac=KjOEQZA^ zGc%t%I(mzWgwfG8SFb+v^n4CuK|!L##DU7nuYG-Mi;GLs)7{zGt#NT}JYHu;#=^ve zWN~q%zP>gjB=`971a}ocPcQYrfkbuncomhl`1rok()$=ptfFGl-o5Dt25AQmCTnR$NlO>l*oX%P zgj{Yk5}B&4UFPKUCN*{H-MjYWK2{_9>0_(%)Y^I5<>Yoq@$hNl7h>#T70t>4y&& z+uO&hsY9cgLHU%zJH@!}63a!pNN`uVM|tYj03AZjc$)!s%^71{ox$ho7u3|9W6%@oNDz+sgybca-x^-*3rKPW=;kfy24XlKhj{$%{*jSi3IM&nLvb5aj?jF=e9igD^-_E;tnwUI)7JOrM zMP^GxxTVF}F^k3q9qrtQt91IkyZlTM=j~i zswu+MG)-qPCNGaE;`>}Nrf|zDf;s~6SGSa>r@OlBm6u=0e*L;bG+3|nsI9fX>EeFu z*2IPGxsya)bcg8>S`Rg$Jf`?_DH);2&flpbk2n+{7u(TuGGRW3Yfcgvrr?Dfe~x2%xnR$qb;?zwxSn%PmLuf-ZYD1}7bCQjNJQ$GA|L$h_2Qjz z$IHppsD^3|cOv7%F;&NSint1S1m_`L0R0-Fw73|fYv*CUvr_*YhJ7ke=S*fNzr@ct zP&HuPuss8jc+VNH(2Lrb;D&_etX6b%nSYVadOHwdaEHBwy%cuWDmiSulCRu|a_gAH z{ENd=y;v-L>T_{>*E`o74)!@wQ!lS-XAdfLW3euU8FE6&qMbUTYbz9GW%cil^tPS6 zU}c-sKcHo!O+z45kA|^1FG9B#Ku2pz^XbDfc^Q1y>N0DISW2V&iCQD7CiJwU17Ru% zs0V&T6Q7^h&e2fVZw3i=6rPIA`9167vJ=Pd^azSFGON@qK!vx}dAHe6`0Yux;|C)L z^Vk}gc#4bRkWwL(_Xdn{+uf6BJf!#AR!gGb)1E`VG;Ts!%QR9ma9?kVL>rkdKs~$k znkKJsARh8nn?)rA$W}q3WF8l~t=~v%OVV%9sF*U?M{6nBb=kH9`IEq9$bt{OHdn5K zNWR0+_#gRDj)1FS=-rkN)pwokMii-*gfh~1KC zS34_8OJ8m`_DC3*cCHc+Hu-V~Z}wOHv2fWfDbN7nJ^CrE@~)*BTWTv>Pl%VZs?|fu z<=sNmc%~Dgx`e@%hHiWr?MDiS^xtMfPjaH7`zb%A~`@tWJ40!2s(tvlkxaW zxn}sM@q@s}kIwW6{{Mon7yV~pfz@V(KtB&w5H)}SY<#Gm3_GePlXe+R#FDTkm?LPo zq!9*hjDZN~vk(#O#bWuBak!wMAS`o}h8s*{{Q^7(BBxxls(pg@cNHp87_4A_2KZ}LIDcQyb$)T@L*nHz}v_9__D6}dEz{%*O@dw-$2~|4hF|?XD~b%1QT~EL?D_N ox>Fet0Z%n?hfEkG6Nm(1VFeamUy3HO6s`blEKge$o4bYm2X9-or2qf` literal 0 HcmV?d00001 diff --git a/docs/includes/favicon.jade b/docs/includes/favicon.jade new file mode 100644 index 00000000000..4bc3e53c60a --- /dev/null +++ b/docs/includes/favicon.jade @@ -0,0 +1,13 @@ +link(rel='apple-touch-icon', sizes='57x57', href='images/favicon/apple-icon-57x57.png') +link(rel='apple-touch-icon', sizes='60x60', href='images/favicon/apple-icon-60x60.png') +link(rel='apple-touch-icon', sizes='72x72', href='images/favicon/apple-icon-72x72.png') +link(rel='apple-touch-icon', sizes='76x76', href='images/favicon/apple-icon-76x76.png') +link(rel='apple-touch-icon', sizes='114x114', href='images/favicon/apple-icon-114x114.png') +link(rel='apple-touch-icon', sizes='120x120', href='images/favicon/apple-icon-120x120.png') +link(rel='apple-touch-icon', sizes='144x144', href='images/favicon/apple-icon-144x144.png') +link(rel='apple-touch-icon', sizes='152x152', href='images/favicon/apple-icon-152x152.png') +link(rel='apple-touch-icon', sizes='180x180', href='images/favicon/apple-icon-180x180.png') +link(rel='icon', type='image/png', sizes='192x192', href='images/favicon/android-icon-192x192.png') +link(rel='icon', type='image/png', sizes='32x32', href='images/favicon/favicon-32x32.png') +link(rel='icon', type='image/png', sizes='96x96', href='images/favicon/favicon-96x96.png') +link(rel='icon', type='image/png', sizes='16x16', href='images/favicon/favicon-16x16.png') diff --git a/docs/index.jade b/docs/index.jade index 2898cbb9d6f..4ee1755f3fc 100644 --- a/docs/index.jade +++ b/docs/index.jade @@ -4,6 +4,7 @@ html(lang='en') meta(charset="utf-8") meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") title Mongoose Quick Start v#{package.version} + include ./includes/favicon.jade link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') link(href='/docs/css/default.css', rel='stylesheet', type='text/css') link(href='/docs/css/guide.css', rel='stylesheet', type='text/css') diff --git a/docs/layout.jade b/docs/layout.jade index 4e019387c93..957802987b2 100644 --- a/docs/layout.jade +++ b/docs/layout.jade @@ -4,10 +4,28 @@ html(lang='en') meta(charset="utf-8") meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") title Mongoose #{title} v#{package.version} + include ./includes/favicon.jade block style link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') link(href='css/default.css', rel='stylesheet', type='text/css') link(href='css/guide.css', rel='stylesheet', type='text/css') + link(rel='apple-touch-icon', sizes='57x57', href='images/favicon/apple-icon-57x57.png') + link(rel='apple-touch-icon', sizes='60x60', href='images/favicon/apple-icon-60x60.png') + link(rel='apple-touch-icon', sizes='72x72', href='images/favicon/apple-icon-72x72.png') + link(rel='apple-touch-icon', sizes='76x76', href='images/favicon/apple-icon-76x76.png') + link(rel='apple-touch-icon', sizes='114x114', href='images/favicon/apple-icon-114x114.png') + link(rel='apple-touch-icon', sizes='120x120', href='images/favicon/apple-icon-120x120.png') + link(rel='apple-touch-icon', sizes='144x144', href='images/favicon/apple-icon-144x144.png') + link(rel='apple-touch-icon', sizes='152x152', href='images/favicon/apple-icon-152x152.png') + link(rel='apple-touch-icon', sizes='180x180', href='images/favicon/apple-icon-180x180.png') + link(rel='icon', type='image/png', sizes='192x192', href='images/favicon/android-icon-192x192.png') + link(rel='icon', type='image/png', sizes='32x32', href='images/favicon/favicon-32x32.png') + link(rel='icon', type='image/png', sizes='96x96', href='images/favicon/favicon-96x96.png') + link(rel='icon', type='image/png', sizes='16x16', href='images/favicon/favicon-16x16.png') + link(rel='manifest', href='images/favicon/manifest.json') + meta(name='msapplication-TileColor', content='#ffffff') + meta(name='msapplication-TileImage', content='images/favicon/ms-icon-144x144.png') + meta(name='theme-color', content='#ffffff') body a#forkbanner(href="http://github.com/Automattic/mongoose") img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") diff --git a/docs/redirect.jade b/docs/redirect.jade index d2abdb05201..38d81ee14ac 100644 --- a/docs/redirect.jade +++ b/docs/redirect.jade @@ -4,6 +4,7 @@ html(lang='en') meta(charset="utf-8") meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") title Mongoose + include ./includes/favicon.jade block meta block style link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') From 61dacd63fa47f356e540dc61538ccc1be07b8e8a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 18 Apr 2016 08:50:38 -0700 Subject: [PATCH 0487/2240] docs(query): add maxTimeMS option to findOneAndUpdate re: #4066 --- lib/model.js | 2 ++ lib/query.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/lib/model.js b/lib/model.js index 1baac18ff48..c181ae9fe6c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1395,6 +1395,7 @@ Model.$where = function $where() { * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0) * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. * - `fields`: {Object|String} - Field selection. Equivalent to `.select(fields).findOneAndUpdate()` + * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). @@ -1593,6 +1594,7 @@ Model.findByIdAndUpdate = function(id, update, options, callback) { * ####Options: * * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0 * - `select`: sets the document fields to return * * ####Examples: diff --git a/lib/query.js b/lib/query.js index 4fc177c797f..d1f1278f838 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1530,6 +1530,7 @@ function prepareDiscriminatorCriteria(query) { * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. * - `fields`: {Object|String} - Field selection. Equivalent to `.select(fields).findOneAndUpdate()` * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0 * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) @@ -1630,6 +1631,7 @@ Query.prototype._findOneAndUpdate = function(callback) { * ####Available options * * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0 * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) * * ####Callback Signature From dd857f054a6bf1f33d02a1a44699f45b81bf625e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 21 Apr 2016 15:10:11 -0700 Subject: [PATCH 0488/2240] chore: release 4.4.13 --- History.md | 8 + bin/mongoose.js | 16286 +++++++++++++++++++++++----------------------- package.json | 2 +- 3 files changed, 8161 insertions(+), 8135 deletions(-) diff --git a/History.md b/History.md index a868ce8d8f8..d01f8a9dc62 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.4.13 / 2016-04-21 +=================== + * docs: add docs favicons #4082 [robertjustjones](https://github.com/robertjustjones) + * docs(model): correct Model.remove() return value #4075 [Jokero](https://github.com/Jokero) + * fix(query): add $geoWithin query casting for single embedded docs #4044 + * fix(schema): handle setting trim option to falsy #4042 + * fix(query): handle setDefaultsOnInsert with empty update #3835 + 4.4.12 / 2016-04-08 =================== * docs(query): document context option for update and findOneAndUpdate #4055 diff --git a/bin/mongoose.js b/bin/mongoose.js index adca1315973..77c158c8a6b 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -234,7 +234,7 @@ Document.prototype.constructor = Document; Document.ValidationError = ValidationError; module.exports = exports = Document; -},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":46,"./utils":48,"events":72}],4:[function(require,module,exports){ +},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":46,"./utils":48,"events":74}],4:[function(require,module,exports){ /*! * Module dependencies. */ @@ -2890,7 +2890,7 @@ Document.ValidationError = ValidationError; module.exports = exports = Document; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":39,"./types/array":41,"./types/documentarray":43,"./types/embedded":44,"./utils":48,"buffer":71,"events":72,"g5I+bs":94,"hooks-fixed":73,"util":98}],6:[function(require,module,exports){ +},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":39,"./types/array":41,"./types/documentarray":43,"./types/embedded":44,"./utils":48,"buffer":71,"events":74,"g5I+bs":94,"hooks-fixed":75,"util":98}],6:[function(require,module,exports){ 'use strict'; /* eslint-env browser */ @@ -3820,7 +3820,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject; module.exports = Promise; -},{"mpromise":80,"util":98}],25:[function(require,module,exports){ +},{"mpromise":82,"util":98}],25:[function(require,module,exports){ /*! * Module dependencies. */ @@ -3873,7 +3873,7 @@ Promise.reset = function() { module.exports = Promise; -},{"./ES6Promise":1,"./promise":24,"mquery":85}],26:[function(require,module,exports){ +},{"./ES6Promise":1,"./promise":24,"mquery":87}],26:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -5280,7 +5280,7 @@ Schema.Types = MongooseTypes = require('./schema/index'); exports.ObjectId = MongooseTypes.ObjectId; }).call(this,require("buffer").Buffer) -},{"./drivers":11,"./schema/index":33,"./utils":48,"./virtualtype":49,"async":51,"buffer":71,"events":72,"kareem":77}],27:[function(require,module,exports){ +},{"./drivers":11,"./schema/index":33,"./utils":48,"./virtualtype":49,"async":51,"buffer":71,"events":74,"kareem":79}],27:[function(require,module,exports){ /*! * Module dependencies. */ @@ -6609,6 +6609,19 @@ function Embedded(schema, path, options) { Embedded.prototype = Object.create(SchemaType.prototype); +/** + * Special case for when users use a common location schema to represent + * locations for use with $geoWithin. + * https://docs.mongodb.org/manual/reference/operator/query/geoWithin/ + * + * @param {Object} val + * @api private + */ + +Embedded.prototype.$conditionalHandlers.$geoWithin = function(val) { + return { $geometry: this.castForQuery(val.$geometry) }; +}; + /** * Casts contents * @@ -7538,7 +7551,7 @@ SchemaString.prototype.trim = function() { if (typeof v !== 'string') { v = self.cast(v); } - if (v) { + if (v && self.options.trim) { return v.trim(); } return v; @@ -11588,7 +11601,7 @@ exports.each = function(arr, fn) { }; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./document":5,"./types":45,"./types/objectid":46,"buffer":71,"g5I+bs":94,"mpath":78,"ms":93,"regexp-clone":95,"sliced":96}],49:[function(require,module,exports){ +},{"./document":5,"./types":45,"./types/objectid":46,"buffer":71,"g5I+bs":94,"mpath":80,"ms":93,"regexp-clone":95,"sliced":96}],49:[function(require,module,exports){ /** * VirtualType constructor @@ -15774,7 +15787,8 @@ var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$"); */ var ObjectID = function ObjectID(id) { if(!(this instanceof ObjectID)) return new ObjectID(id); - if((id instanceof ObjectID)) return id; + // Duck-typing to support ObjectId from different npm packages + if((id instanceof ObjectID) || (id && id.toHexString)) return id; this._bsontype = 'ObjectID'; var __id = null; @@ -16001,6 +16015,10 @@ ObjectID.isValid = function isValid(id) { if(id instanceof ObjectID) { return true; } + // Duck-Typing detection of ObjectId like objects + if(id.toHexString) { + return id.id.length == 12 || (id.id.length == 24 && checkForHexRegExp.test(id.id)); + } return false; }; @@ -19781,10163 +19799,10163 @@ function decodeUtf8Char (str) { } } -},{"base64-js":52,"ieee754":74,"is-array":76}],72:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. +},{"base64-js":52,"ieee754":76,"is-array":78}],72:[function(require,module,exports){ -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; +exports = module.exports = require('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; +/** + * Colors. + */ -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; +function useColors() { + // is webkit? http://stackoverflow.com/a/16459606/376773 + return ('WebkitAppearance' in document.documentElement.style) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (window.console && (console.firebug || (console.exception && console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); +} - if (!this._events) - this._events = {}; +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } - throw TypeError('Uncaught, unspecified "error" event.'); - } - } +exports.formatters.j = function(v) { + return JSON.stringify(v); +}; - handler = this._events[type]; - if (isUndefined(handler)) - return false; +/** + * Colorize log arguments if enabled. + * + * @api public + */ - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; +function formatArgs() { + var args = arguments; + var useColors = this.useColors; - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); - return true; -}; + if (!useColors) return args; -EventEmitter.prototype.addListener = function(type, listener) { - var m; + var c = 'color: ' + this.color; + args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); - if (!isFunction(listener)) - throw TypeError('listener must be a function'); + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); - if (!this._events) - this._events = {}; + args.splice(lastC, 0, c); + return args; +} - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); +} - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); } else { - m = EventEmitter.defaultMaxListeners; + exports.storage.debug = namespaces; } + } catch(e) {} +} - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; +function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + return r; +} -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ - var fired = false; +exports.enable(load()); - function g() { - this.removeListener(type, g); +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } +function localstorage(){ + try { + return window.localStorage; + } catch (e) {} +} - g.listener = listener; - this.on(type, g); +},{"./debug":73}],73:[function(require,module,exports){ - return this; -}; +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; +exports = module.exports = debug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = require('ms'); - if (!isFunction(listener)) - throw TypeError('listener must be a function'); +/** + * The currently active debug mode names, and names to skip. + */ - if (!this._events || !this._events[type]) - return this; +exports.names = []; +exports.skips = []; - list = this._events[type]; - length = list.length; - position = -1; +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lowercased letter, i.e. "n". + */ - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); +exports.formatters = {}; - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } +/** + * Previously assigned color. + */ - if (position < 0) - return this; +var prevColor = 0; - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } +/** + * Previous log timestamp. + */ - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } +var prevTime; - return this; -}; +/** + * Select a color. + * + * @return {Number} + * @api private + */ -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; +function selectColor() { + return exports.colors[prevColor++ % exports.colors.length]; +} - if (!this._events) - return this; +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } +function debug(namespace) { - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; + // define the `disabled` version + function disabled() { } + disabled.enabled = false; - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; + // define the `enabled` version + function enabled() { - return this; -}; + var self = enabled; -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; + // add the `color` if not set + if (null == self.useColors) self.useColors = exports.useColors(); + if (null == self.color && self.useColors) self.color = selectColor(); -function isFunction(arg) { - return typeof arg === 'function'; -} + var args = Array.prototype.slice.call(arguments); -function isNumber(arg) { - return typeof arg === 'number'; -} + args[0] = exports.coerce(args[0]); -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} + if ('string' !== typeof args[0]) { + // anything else let's inspect with %o + args = ['%o'].concat(args); + } -function isUndefined(arg) { - return arg === void 0; -} + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); -},{}],73:[function(require,module,exports){ -// TODO Add in pre and post skipping options -module.exports = { - /** - * Declares a new hook to which you can add pres and posts - * @param {String} name of the function - * @param {Function} the method - * @param {Function} the error handler callback - */ - hook: function (name, fn, errorCb) { - if (arguments.length === 1 && typeof name === 'object') { - for (var k in name) { // `name` is a hash of hookName->hookFn - this.hook(k, name[k]); + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; } - return; + return match; + }); + + if ('function' === typeof exports.formatArgs) { + args = exports.formatArgs.apply(self, args); } + var logFn = enabled.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + enabled.enabled = true; - var proto = this.prototype || this - , pres = proto._pres = proto._pres || {} - , posts = proto._posts = proto._posts || {}; - pres[name] = pres[name] || []; - posts[name] = posts[name] || []; + var fn = exports.enabled(namespace) ? enabled : disabled; - proto[name] = function () { - var self = this - , hookArgs // arguments eventually passed to the hook - are mutable - , lastArg = arguments[arguments.length-1] - , pres = this._pres[name] - , posts = this._posts[name] - , _total = pres.length - , _current = -1 - , _asyncsLeft = proto[name].numAsyncPres - , _asyncsDone = function(err) { - if (err) { - return handleError(err); - } - --_asyncsLeft || _done.apply(self, hookArgs); - } - , handleError = function(err) { - if ('function' == typeof lastArg) - return lastArg(err); - if (errorCb) return errorCb.call(self, err); - throw err; - } - , _next = function () { - if (arguments[0] instanceof Error) { - return handleError(arguments[0]); - } - var _args = Array.prototype.slice.call(arguments) - , currPre - , preArgs; - if (_args.length && !(arguments[0] == null && typeof lastArg === 'function')) - hookArgs = _args; - if (++_current < _total) { - currPre = pres[_current] - if (currPre.isAsync && currPre.length < 2) - throw new Error("Your pre must have next and done arguments -- e.g., function (next, done, ...)"); - if (currPre.length < 1) - throw new Error("Your pre must have a next argument -- e.g., function (next, ...)"); - preArgs = (currPre.isAsync - ? [once(_next), once(_asyncsDone)] - : [once(_next)]).concat(hookArgs); - return currPre.apply(self, preArgs); - } else if (!_asyncsLeft) { - return _done.apply(self, hookArgs); - } - } - , _done = function () { - var args_ = Array.prototype.slice.call(arguments) - , ret, total_, current_, next_, done_, postArgs; - - if (_current === _total) { - - next_ = function () { - if (arguments[0] instanceof Error) { - return handleError(arguments[0]); - } - var args_ = Array.prototype.slice.call(arguments, 1) - , currPost - , postArgs; - if (args_.length) hookArgs = args_; - if (++current_ < total_) { - currPost = posts[current_] - if (currPost.length < 1) - throw new Error("Your post must have a next argument -- e.g., function (next, ...)"); - postArgs = [once(next_)].concat(hookArgs); - return currPost.apply(self, postArgs); - } else if (typeof lastArg === 'function'){ - // All post handlers are done, call original callback function - return lastArg.apply(self, arguments); - } - }; - - // We are assuming that if the last argument provided to the wrapped function is a function, it was expecting - // a callback. We trap that callback and wait to call it until all post handlers have finished. - if(typeof lastArg === 'function'){ - args_[args_.length - 1] = once(next_); - } - - total_ = posts.length; - current_ = -1; - ret = fn.apply(self, args_); // Execute wrapped function, post handlers come afterward - - if (total_ && typeof lastArg !== 'function') return next_(); // no callback provided, execute next_() manually - return ret; - } - }; - - return _next.apply(this, arguments); - }; - - proto[name].numAsyncPres = 0; + fn.namespace = namespace; - return this; - }, + return fn; +} - pre: function (name, isAsync, fn, errorCb) { - if ('boolean' !== typeof arguments[1]) { - errorCb = fn; - fn = isAsync; - isAsync = false; - } - var proto = this.prototype || this - , pres = proto._pres = proto._pres || {}; +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ - this._lazySetupHooks(proto, name, errorCb); +function enable(namespaces) { + exports.save(namespaces); - if (fn.isAsync = isAsync) { - proto[name].numAsyncPres++; - } + var split = (namespaces || '').split(/[\s,]+/); + var len = split.length; - (pres[name] = pres[name] || []).push(fn); - return this; - }, - post: function (name, isAsync, fn) { - if (arguments.length === 2) { - fn = isAsync; - isAsync = false; - } - var proto = this.prototype || this - , posts = proto._posts = proto._posts || {}; - - this._lazySetupHooks(proto, name); - (posts[name] = posts[name] || []).push(fn); - return this; - }, - removePre: function (name, fnToRemove) { - var proto = this.prototype || this - , pres = proto._pres || (proto._pres || {}); - if (!pres[name]) return this; - if (arguments.length === 1) { - // Remove all pre callbacks for hook `name` - pres[name].length = 0; - } else { - pres[name] = pres[name].filter( function (currFn) { - return currFn !== fnToRemove; - }); - } - return this; - }, - removePost: function (name, fnToRemove) { - var proto = this.prototype || this - , posts = proto._posts || (proto._posts || {}); - if (!posts[name]) return this; - if (arguments.length === 1) { - // Remove all post callbacks for hook `name` - posts[name].length = 0; + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); } else { - posts[name] = posts[name].filter( function (currFn) { - return currFn !== fnToRemove; - }); - } - return this; - }, - - _lazySetupHooks: function (proto, methodName, errorCb) { - if ('undefined' === typeof proto[methodName].numAsyncPres) { - this.hook(methodName, proto[methodName], errorCb); + exports.names.push(new RegExp('^' + namespaces + '$')); } } -}; - -function once (fn, scope) { - return function fnWrapper () { - if (fnWrapper.hookCalled) return; - fnWrapper.hookCalled = true; - var ret = fn.apply(scope, arguments); - if (ret && ret.then) { - ret.then(function() {}, function() {}); - } - }; } -},{}],74:[function(require,module,exports){ -exports.read = function (buffer, offset, isLE, mLen, nBytes) { - var e, m - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var nBits = -7 - var i = isLE ? (nBytes - 1) : 0 - var d = isLE ? -1 : 1 - var s = buffer[offset + i] - - i += d +/** + * Disable debug output. + * + * @api public + */ - e = s & ((1 << (-nBits)) - 1) - s >>= (-nBits) - nBits += eLen - for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} +function disable() { + exports.enable(''); +} - m = e & ((1 << (-nBits)) - 1) - e >>= (-nBits) - nBits += mLen - for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ - if (e === 0) { - e = 1 - eBias - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity) - } else { - m = m + Math.pow(2, mLen) - e = e - eBias +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen) + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; } -exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) - var i = isLE ? 0 : (nBytes - 1) - var d = isLE ? 1 : -1 - var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ - value = Math.abs(value) +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0 - e = eMax - } else { - e = Math.floor(Math.log(value) / Math.LN2) - if (value * (c = Math.pow(2, -e)) < 1) { - e-- - c *= 2 - } - if (e + eBias >= 1) { - value += rt / c - } else { - value += rt * Math.pow(2, 1 - eBias) - } - if (value * c >= 2) { - e++ - c /= 2 - } +},{"ms":93}],74:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. - if (e + eBias >= eMax) { - m = 0 - e = eMax - } else if (e + eBias >= 1) { - m = (value * c - 1) * Math.pow(2, mLen) - e = e + eBias - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) - e = 0 +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); } } - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + handler = this._events[type]; - e = (e << mLen) | m - eLen += mLen - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + if (isUndefined(handler)) + return false; - buffer[offset + i - d] |= s * 128 -} + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; -},{}],75:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); } -} -},{}],76:[function(require,module,exports){ + return true; +}; -/** - * isArray - */ +EventEmitter.prototype.addListener = function(type, listener) { + var m; -var isArray = Array.isArray; + if (!isFunction(listener)) + throw TypeError('listener must be a function'); -/** - * toString - */ + if (!this._events) + this._events = {}; -var str = Object.prototype.toString; + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); -/** - * Whether or not the given `val` - * is an array. - * - * example: - * - * isArray([]); - * // > true - * isArray(arguments); - * // > false - * isArray(''); - * // > false - * - * @param {mixed} val - * @return {bool} - */ + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; -module.exports = isArray || function (val) { - return !! val && '[object Array]' == str.call(val); + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; }; -},{}],77:[function(require,module,exports){ -(function (process){ -'use strict'; +EventEmitter.prototype.on = EventEmitter.prototype.addListener; -function Kareem() { - this._pres = {}; - this._posts = {}; -} +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); -Kareem.prototype.execPre = function(name, context, callback) { - var pres = this._pres[name] || []; - var numPres = pres.length; - var numAsyncPres = pres.numAsync || 0; - var currentPre = 0; - var asyncPresLeft = numAsyncPres; - var done = false; + var fired = false; - if (!numPres) { - return process.nextTick(function() { - callback(null); - }); - } + function g() { + this.removeListener(type, g); - var next = function() { - if (currentPre >= numPres) { - return; + if (!fired) { + fired = true; + listener.apply(this, arguments); } - var pre = pres[currentPre]; + } - if (pre.isAsync) { - pre.fn.call( - context, - function(error) { - if (error) { - if (done) { - return; - } - done = true; - return callback(error); - } - - ++currentPre; - next.apply(context, arguments); - }, - function(error) { - if (error) { - if (done) { - return; - } - done = true; - return callback(error); - } - - if (--numAsyncPres === 0) { - return callback(null); - } - }); - } else if (pre.fn.length > 0) { - var args = [function(error) { - if (error) { - if (done) { - return; - } - done = true; - return callback(error); - } - - if (++currentPre >= numPres) { - if (asyncPresLeft > 0) { - // Leave parallel hooks to run - return; - } else { - return callback(null); - } - } - - next.apply(context, arguments); - }]; - if (arguments.length >= 2) { - for (var i = 1; i < arguments.length; ++i) { - args.push(arguments[i]); - } - } - pre.fn.apply(context, args); - } else { - pre.fn.call(context); - if (++currentPre >= numPres) { - if (asyncPresLeft > 0) { - // Leave parallel hooks to run - return; - } else { - return process.nextTick(function() { - callback(null); - }); - } - } - next(); - } - }; + g.listener = listener; + this.on(type, g); - next(); + return this; }; -Kareem.prototype.execPost = function(name, context, args, callback) { - var posts = this._posts[name] || []; - var numPosts = posts.length; - var currentPost = 0; - - if (!numPosts) { - return process.nextTick(function() { - callback.apply(null, [null].concat(args)); - }); - } +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; - var next = function() { - var post = posts[currentPost]; + if (!isFunction(listener)) + throw TypeError('listener must be a function'); - if (post.length > args.length) { - post.apply(context, args.concat(function(error) { - if (error) { - return callback(error); - } + if (!this._events || !this._events[type]) + return this; - if (++currentPost >= numPosts) { - return callback.apply(null, [null].concat(args)); - } + list = this._events[type]; + length = list.length; + position = -1; - next(); - })); - } else { - post.apply(context, args); + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); - if (++currentPost >= numPosts) { - return callback.apply(null, [null].concat(args)); + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; } - - next(); } - }; - - next(); -}; -Kareem.prototype.wrap = function(name, fn, context, args, useLegacyPost) { - var lastArg = (args.length > 0 ? args[args.length - 1] : null); - var _this = this; + if (position < 0) + return this; - this.execPre(name, context, function(error) { - if (error) { - if (typeof lastArg === 'function') { - return lastArg(error); - } - return; + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); } - var end = (typeof lastArg === 'function' ? args.length - 1 : args.length); - - fn.apply(context, args.slice(0, end).concat(function() { - if (arguments[0]) { - // Assume error - return typeof lastArg === 'function' ? - lastArg(arguments[0]) : - undefined; - } + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } - if (useLegacyPost && typeof lastArg === 'function') { - lastArg.apply(context, arguments); - } + return this; +}; - var argsWithoutError = Array.prototype.slice.call(arguments, 1); - _this.execPost(name, context, argsWithoutError, function() { - if (arguments[0]) { - return typeof lastArg === 'function' ? - lastArg(arguments[0]) : - undefined; - } +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; - return typeof lastArg === 'function' && !useLegacyPost ? - lastArg.apply(context, arguments) : - undefined; - }); - })); - }); -}; + if (!this._events) + return this; -Kareem.prototype.createWrapper = function(name, fn, context) { - var _this = this; - return function() { - var args = Array.prototype.slice.call(arguments); - _this.wrap(name, fn, context, args); - }; -}; + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } -Kareem.prototype.pre = function(name, isAsync, fn, error) { - if (typeof arguments[1] !== 'boolean') { - error = fn; - fn = isAsync; - isAsync = false; + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; } - this._pres[name] = this._pres[name] || []; - var pres = this._pres[name]; + listeners = this._events[type]; - if (isAsync) { - pres.numAsync = pres.numAsync || 0; - ++pres.numAsync; + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); } - - pres.push({ fn: fn, isAsync: isAsync }); + delete this._events[type]; return this; }; -Kareem.prototype.post = function(name, fn) { - (this._posts[name] = this._posts[name] || []).push(fn); - return this; +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; }; -Kareem.prototype.clone = function() { - var n = new Kareem(); - for (var key in this._pres) { - n._pres[key] = this._pres[key].slice(); - } - for (var key in this._posts) { - n._posts[key] = this._posts[key].slice(); - } - - return n; +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; }; -module.exports = Kareem; +function isFunction(arg) { + return typeof arg === 'function'; +} -}).call(this,require("g5I+bs")) -},{"g5I+bs":94}],78:[function(require,module,exports){ -module.exports = exports = require('./lib'); +function isNumber(arg) { + return typeof arg === 'number'; +} -},{"./lib":79}],79:[function(require,module,exports){ -/** - * Returns the value of object `o` at the given `path`. - * - * ####Example: - * - * var obj = { - * comments: [ - * { title: 'exciting!', _doc: { title: 'great!' }} - * , { title: 'number dos' } - * ] - * } - * - * mpath.get('comments.0.title', o) // 'exciting!' - * mpath.get('comments.0.title', o, '_doc') // 'great!' - * mpath.get('comments.title', o) // ['exciting!', 'number dos'] - * - * // summary - * mpath.get(path, o) - * mpath.get(path, o, special) - * mpath.get(path, o, map) - * mpath.get(path, o, special, map) - * - * @param {String} path - * @param {Object} o - * @param {String} [special] When this property name is present on any object in the path, walking will continue on the value of this property. - * @param {Function} [map] Optional function which receives each individual found value. The value returned from `map` is used in the original values place. - */ +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} -exports.get = function (path, o, special, map) { - var lookup; +function isUndefined(arg) { + return arg === void 0; +} - if ('function' == typeof special) { - if (special.length < 2) { - map = special; - special = undefined; - } else { - lookup = special; - special = undefined; +},{}],75:[function(require,module,exports){ +// TODO Add in pre and post skipping options +module.exports = { + /** + * Declares a new hook to which you can add pres and posts + * @param {String} name of the function + * @param {Function} the method + * @param {Function} the error handler callback + */ + hook: function (name, fn, errorCb) { + if (arguments.length === 1 && typeof name === 'object') { + for (var k in name) { // `name` is a hash of hookName->hookFn + this.hook(k, name[k]); + } + return; } - } - map || (map = K); + var proto = this.prototype || this + , pres = proto._pres = proto._pres || {} + , posts = proto._posts = proto._posts || {}; + pres[name] = pres[name] || []; + posts[name] = posts[name] || []; - var parts = 'string' == typeof path - ? path.split('.') - : path + proto[name] = function () { + var self = this + , hookArgs // arguments eventually passed to the hook - are mutable + , lastArg = arguments[arguments.length-1] + , pres = this._pres[name] + , posts = this._posts[name] + , _total = pres.length + , _current = -1 + , _asyncsLeft = proto[name].numAsyncPres + , _asyncsDone = function(err) { + if (err) { + return handleError(err); + } + --_asyncsLeft || _done.apply(self, hookArgs); + } + , handleError = function(err) { + if ('function' == typeof lastArg) + return lastArg(err); + if (errorCb) return errorCb.call(self, err); + throw err; + } + , _next = function () { + if (arguments[0] instanceof Error) { + return handleError(arguments[0]); + } + var _args = Array.prototype.slice.call(arguments) + , currPre + , preArgs; + if (_args.length && !(arguments[0] == null && typeof lastArg === 'function')) + hookArgs = _args; + if (++_current < _total) { + currPre = pres[_current] + if (currPre.isAsync && currPre.length < 2) + throw new Error("Your pre must have next and done arguments -- e.g., function (next, done, ...)"); + if (currPre.length < 1) + throw new Error("Your pre must have a next argument -- e.g., function (next, ...)"); + preArgs = (currPre.isAsync + ? [once(_next), once(_asyncsDone)] + : [once(_next)]).concat(hookArgs); + return currPre.apply(self, preArgs); + } else if (!_asyncsLeft) { + return _done.apply(self, hookArgs); + } + } + , _done = function () { + var args_ = Array.prototype.slice.call(arguments) + , ret, total_, current_, next_, done_, postArgs; - if (!Array.isArray(parts)) { - throw new TypeError('Invalid `path`. Must be either string or array'); - } + if (_current === _total) { + + next_ = function () { + if (arguments[0] instanceof Error) { + return handleError(arguments[0]); + } + var args_ = Array.prototype.slice.call(arguments, 1) + , currPost + , postArgs; + if (args_.length) hookArgs = args_; + if (++current_ < total_) { + currPost = posts[current_] + if (currPost.length < 1) + throw new Error("Your post must have a next argument -- e.g., function (next, ...)"); + postArgs = [once(next_)].concat(hookArgs); + return currPost.apply(self, postArgs); + } else if (typeof lastArg === 'function'){ + // All post handlers are done, call original callback function + return lastArg.apply(self, arguments); + } + }; - var obj = o - , part; + // We are assuming that if the last argument provided to the wrapped function is a function, it was expecting + // a callback. We trap that callback and wait to call it until all post handlers have finished. + if(typeof lastArg === 'function'){ + args_[args_.length - 1] = once(next_); + } - for (var i = 0; i < parts.length; ++i) { - part = parts[i]; + total_ = posts.length; + current_ = -1; + ret = fn.apply(self, args_); // Execute wrapped function, post handlers come afterward - if (Array.isArray(obj) && !/^\d+$/.test(part)) { - // reading a property from the array items - var paths = parts.slice(i); + if (total_ && typeof lastArg !== 'function') return next_(); // no callback provided, execute next_() manually + return ret; + } + }; - return obj.map(function (item) { - return item - ? exports.get(paths, item, special || lookup, map) - : map(undefined); - }); + return _next.apply(this, arguments); + }; + + proto[name].numAsyncPres = 0; + + return this; + }, + + pre: function (name, isAsync, fn, errorCb) { + if ('boolean' !== typeof arguments[1]) { + errorCb = fn; + fn = isAsync; + isAsync = false; } + var proto = this.prototype || this + , pres = proto._pres = proto._pres || {}; - if (lookup) { - obj = lookup(obj, part); - } else { - obj = special && obj[special] - ? obj[special][part] - : obj[part]; + this._lazySetupHooks(proto, name, errorCb); + + if (fn.isAsync = isAsync) { + proto[name].numAsyncPres++; } - if (!obj) return map(obj); + (pres[name] = pres[name] || []).push(fn); + return this; + }, + post: function (name, isAsync, fn) { + if (arguments.length === 2) { + fn = isAsync; + isAsync = false; + } + var proto = this.prototype || this + , posts = proto._posts = proto._posts || {}; + + this._lazySetupHooks(proto, name); + (posts[name] = posts[name] || []).push(fn); + return this; + }, + removePre: function (name, fnToRemove) { + var proto = this.prototype || this + , pres = proto._pres || (proto._pres || {}); + if (!pres[name]) return this; + if (arguments.length === 1) { + // Remove all pre callbacks for hook `name` + pres[name].length = 0; + } else { + pres[name] = pres[name].filter( function (currFn) { + return currFn !== fnToRemove; + }); + } + return this; + }, + removePost: function (name, fnToRemove) { + var proto = this.prototype || this + , posts = proto._posts || (proto._posts || {}); + if (!posts[name]) return this; + if (arguments.length === 1) { + // Remove all post callbacks for hook `name` + posts[name].length = 0; + } else { + posts[name] = posts[name].filter( function (currFn) { + return currFn !== fnToRemove; + }); + } + return this; + }, + + _lazySetupHooks: function (proto, methodName, errorCb) { + if ('undefined' === typeof proto[methodName].numAsyncPres) { + this.hook(methodName, proto[methodName], errorCb); + } } +}; - return map(obj); +function once (fn, scope) { + return function fnWrapper () { + if (fnWrapper.hookCalled) return; + fnWrapper.hookCalled = true; + var ret = fn.apply(scope, arguments); + if (ret && ret.then) { + ret.then(function() {}, function() {}); + } + }; } -/** - * Sets the `val` at the given `path` of object `o`. - * - * @param {String} path - * @param {Anything} val - * @param {Object} o - * @param {String} [special] When this property name is present on any object in the path, walking will continue on the value of this property. - * @param {Function} [map] Optional function which is passed each individual value before setting it. The value returned from `map` is used in the original values place. - */ - -exports.set = function (path, val, o, special, map, _copying) { - var lookup; +},{}],76:[function(require,module,exports){ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] - if ('function' == typeof special) { - if (special.length < 2) { - map = special; - special = undefined; - } else { - lookup = special; - special = undefined; - } - } + i += d - map || (map = K); + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} - var parts = 'string' == typeof path - ? path.split('.') - : path + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} - if (!Array.isArray(parts)) { - throw new TypeError('Invalid `path`. Must be either string or array'); + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} - if (null == o) return; - - // the existance of $ in a path tells us if the user desires - // the copying of an array instead of setting each value of - // the array to the one by one to matching positions of the - // current array. - var copy = _copying || /\$/.test(path) - , obj = o - , part +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 - for (var i = 0, len = parts.length - 1; i < len; ++i) { - part = parts[i]; + value = Math.abs(value) - if ('$' == part) { - if (i == len - 1) { - break; - } else { - continue; - } + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 } - - if (Array.isArray(obj) && !/^\d+$/.test(part)) { - var paths = parts.slice(i); - if (!copy && Array.isArray(val)) { - for (var j = 0; j < obj.length && j < val.length; ++j) { - // assignment of single values of array - exports.set(paths, val[j], obj[j], special || lookup, map, copy); - } - } else { - for (var j = 0; j < obj.length; ++j) { - // assignment of entire value - exports.set(paths, val, obj[j], special || lookup, map, copy); - } - } - return; + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 } - if (lookup) { - obj = lookup(obj, part); + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen) + e = e + eBias } else { - obj = special && obj[special] - ? obj[special][part] - : obj[part]; + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 } - - if (!obj) return; } - // process the last property of the path + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} - part = parts[len]; + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} - // use the special property if exists - if (special && obj[special]) { - obj = obj[special]; - } + buffer[offset + i - d] |= s * 128 +} - // set the value on the last branch - if (Array.isArray(obj) && !/^\d+$/.test(part)) { - if (!copy && Array.isArray(val)) { - for (var item, j = 0; j < obj.length && j < val.length; ++j) { - item = obj[j]; - if (item) { - if (lookup) { - lookup(item, part, map(val[j])); - } else { - if (item[special]) item = item[special]; - item[part] = map(val[j]); - } - } - } - } else { - for (var j = 0; j < obj.length; ++j) { - item = obj[j]; - if (item) { - if (lookup) { - lookup(item, part, map(val)); - } else { - if (item[special]) item = item[special]; - item[part] = map(val); - } - } +},{}],77:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true } - } - } else { - if (lookup) { - lookup(obj, part, map(val)); - } else { - obj[part] = map(val); - } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor } } -/*! - * Returns the value passed to it. +},{}],78:[function(require,module,exports){ + +/** + * isArray */ -function K (v) { - return v; -} +var isArray = Array.isArray; -},{}],80:[function(require,module,exports){ -(function (process){ -'use strict'; -var util = require('util'); -var EventEmitter = require('events').EventEmitter; -function toArray(arr, start, end) { - return Array.prototype.slice.call(arr, start, end) -} -function strongUnshift(x, arrLike) { - var arr = toArray(arrLike); - arr.unshift(x); - return arr; -} +/** + * toString + */ +var str = Object.prototype.toString; /** - * MPromise constructor. + * Whether or not the given `val` + * is an array. * - * _NOTE: The success and failure event names can be overridden by setting `Promise.SUCCESS` and `Promise.FAILURE` respectively._ + * example: * - * @param {Function} back a function that accepts `fn(err, ...){}` as signature - * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter - * @event `reject`: Emits when the promise is rejected (event name may be overridden) - * @event `fulfill`: Emits when the promise is fulfilled (event name may be overridden) - * @api public + * isArray([]); + * // > true + * isArray(arguments); + * // > false + * isArray(''); + * // > false + * + * @param {mixed} val + * @return {bool} */ -function Promise(back) { - this.emitter = new EventEmitter(); - this.emitted = {}; - this.ended = false; - if ('function' == typeof back) { - this.ended = true; - this.onResolve(back); - } -} +module.exports = isArray || function (val) { + return !! val && '[object Array]' == str.call(val); +}; -/* - * Module exports. - */ -module.exports = Promise; +},{}],79:[function(require,module,exports){ +(function (process){ +'use strict'; +function Kareem() { + this._pres = {}; + this._posts = {}; +} -/*! - * event names - */ -Promise.SUCCESS = 'fulfill'; -Promise.FAILURE = 'reject'; +Kareem.prototype.execPre = function(name, context, callback) { + var pres = this._pres[name] || []; + var numPres = pres.length; + var numAsyncPres = pres.numAsync || 0; + var currentPre = 0; + var asyncPresLeft = numAsyncPres; + var done = false; + if (!numPres) { + return process.nextTick(function() { + callback(null); + }); + } -/** - * Adds `listener` to the `event`. - * - * If `event` is either the success or failure event and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event. - * - * @param {String} event - * @param {Function} callback - * @return {MPromise} this - * @api private - */ -Promise.prototype.on = function (event, callback) { - if (this.emitted[event]) - callback.apply(undefined, this.emitted[event]); - else - this.emitter.on(event, callback); + var next = function() { + if (currentPre >= numPres) { + return; + } + var pre = pres[currentPre]; - return this; -}; + if (pre.isAsync) { + pre.fn.call( + context, + function(error) { + if (error) { + if (done) { + return; + } + done = true; + return callback(error); + } + ++currentPre; + next.apply(context, arguments); + }, + function(error) { + if (error) { + if (done) { + return; + } + done = true; + return callback(error); + } -/** - * Keeps track of emitted events to run them on `on`. - * - * @api private - */ -Promise.prototype.safeEmit = function (event) { - // ensures a promise can't be fulfill() or reject() more than once - if (event == Promise.SUCCESS || event == Promise.FAILURE) { - if (this.emitted[Promise.SUCCESS] || this.emitted[Promise.FAILURE]) { - return this; - } - this.emitted[event] = toArray(arguments, 1); - } + if (--numAsyncPres === 0) { + return callback(null); + } + }); + } else if (pre.fn.length > 0) { + var args = [function(error) { + if (error) { + if (done) { + return; + } + done = true; + return callback(error); + } - this.emitter.emit.apply(this.emitter, arguments); - return this; -}; + if (++currentPre >= numPres) { + if (asyncPresLeft > 0) { + // Leave parallel hooks to run + return; + } else { + return callback(null); + } + } + next.apply(context, arguments); + }]; + if (arguments.length >= 2) { + for (var i = 1; i < arguments.length; ++i) { + args.push(arguments[i]); + } + } + pre.fn.apply(context, args); + } else { + pre.fn.call(context); + if (++currentPre >= numPres) { + if (asyncPresLeft > 0) { + // Leave parallel hooks to run + return; + } else { + return process.nextTick(function() { + callback(null); + }); + } + } + next(); + } + }; -/** - * @api private - */ -Promise.prototype.hasRejectListeners = function () { - return EventEmitter.listenerCount(this.emitter, Promise.FAILURE) > 0; + next(); }; +Kareem.prototype.execPost = function(name, context, args, callback) { + var posts = this._posts[name] || []; + var numPosts = posts.length; + var currentPost = 0; + + if (!numPosts) { + return process.nextTick(function() { + callback.apply(null, [null].concat(args)); + }); + } -/** - * Fulfills this promise with passed arguments. - * - * If this promise has already been fulfilled or rejected, no action is taken. - * - * @api public - */ -Promise.prototype.fulfill = function () { - return this.safeEmit.apply(this, strongUnshift(Promise.SUCCESS, arguments)); -}; + var next = function() { + var post = posts[currentPost]; + if (post.length > args.length) { + post.apply(context, args.concat(function(error) { + if (error) { + return callback(error); + } -/** - * Rejects this promise with `reason`. - * - * If this promise has already been fulfilled or rejected, no action is taken. - * - * @api public - * @param {Object|String} reason - * @return {MPromise} this - */ -Promise.prototype.reject = function (reason) { - if (this.ended && !this.hasRejectListeners()) - throw reason; - return this.safeEmit(Promise.FAILURE, reason); -}; + if (++currentPost >= numPosts) { + return callback.apply(null, [null].concat(args)); + } + next(); + })); + } else { + post.apply(context, args); -/** - * Resolves this promise to a rejected state if `err` is passed or - * fulfilled state if no `err` is passed. - * - * @param {Error} [err] error or null - * @param {Object} [val] value to fulfill the promise with - * @api public - */ -Promise.prototype.resolve = function (err, val) { - if (err) return this.reject(err); - return this.fulfill(val); -}; + if (++currentPost >= numPosts) { + return callback.apply(null, [null].concat(args)); + } + next(); + } + }; -/** - * Adds a listener to the SUCCESS event. - * - * @return {MPromise} this - * @api public - */ -Promise.prototype.onFulfill = function (fn) { - if (!fn) return this; - if ('function' != typeof fn) throw new TypeError("fn should be a function"); - return this.on(Promise.SUCCESS, fn); + next(); }; +Kareem.prototype.wrap = function(name, fn, context, args, useLegacyPost) { + var lastArg = (args.length > 0 ? args[args.length - 1] : null); + var _this = this; -/** - * Adds a listener to the FAILURE event. - * - * @return {MPromise} this - * @api public - */ -Promise.prototype.onReject = function (fn) { - if (!fn) return this; - if ('function' != typeof fn) throw new TypeError("fn should be a function"); - return this.on(Promise.FAILURE, fn); -}; + this.execPre(name, context, function(error) { + if (error) { + if (typeof lastArg === 'function') { + return lastArg(error); + } + return; + } + var end = (typeof lastArg === 'function' ? args.length - 1 : args.length); -/** - * Adds a single function as a listener to both SUCCESS and FAILURE. - * - * It will be executed with traditional node.js argument position: - * function (err, args...) {} - * - * Also marks the promise as `end`ed, since it's the common use-case, and yet has no - * side effects unless `fn` is undefined or null. - * - * @param {Function} fn - * @return {MPromise} this - */ -Promise.prototype.onResolve = function (fn) { - if (!fn) return this; - if ('function' != typeof fn) throw new TypeError("fn should be a function"); - this.on(Promise.FAILURE, function (err) { fn.call(this, err); }); - this.on(Promise.SUCCESS, function () { fn.apply(this, strongUnshift(null, arguments)); }); - return this; -}; + fn.apply(context, args.slice(0, end).concat(function() { + if (arguments[0]) { + // Assume error + return typeof lastArg === 'function' ? + lastArg(arguments[0]) : + undefined; + } + if (useLegacyPost && typeof lastArg === 'function') { + lastArg.apply(context, arguments); + } -/** - * Creates a new promise and returns it. If `onFulfill` or - * `onReject` are passed, they are added as SUCCESS/ERROR callbacks - * to this promise after the next tick. - * - * Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification. Read for more detail how to use this method. - * - * ####Example: - * - * var p = new Promise; - * p.then(function (arg) { - * return arg + 1; - * }).then(function (arg) { - * throw new Error(arg + ' is an error!'); - * }).then(null, function (err) { - * assert.ok(err instanceof Error); - * assert.equal('2 is an error', err.message); - * }); - * p.complete(1); - * - * @see promises-A+ https://github.com/promises-aplus/promises-spec - * @param {Function} onFulfill - * @param {Function} [onReject] - * @return {MPromise} newPromise - */ -Promise.prototype.then = function (onFulfill, onReject) { - var newPromise = new Promise; - - if ('function' == typeof onFulfill) { - this.onFulfill(handler(newPromise, onFulfill)); - } else { - this.onFulfill(newPromise.fulfill.bind(newPromise)); - } - - if ('function' == typeof onReject) { - this.onReject(handler(newPromise, onReject)); - } else { - this.onReject(newPromise.reject.bind(newPromise)); - } + var argsWithoutError = Array.prototype.slice.call(arguments, 1); + _this.execPost(name, context, argsWithoutError, function() { + if (arguments[0]) { + return typeof lastArg === 'function' ? + lastArg(arguments[0]) : + undefined; + } - return newPromise; + return typeof lastArg === 'function' && !useLegacyPost ? + lastArg.apply(context, arguments) : + undefined; + }); + })); + }); }; +Kareem.prototype.createWrapper = function(name, fn, context) { + var _this = this; + return function() { + var args = Array.prototype.slice.call(arguments); + _this.wrap(name, fn, context, args); + }; +}; -function handler(promise, fn) { - function newTickHandler() { - var pDomain = promise.emitter.domain; - if (pDomain && pDomain !== process.domain) pDomain.enter(); - try { - var x = fn.apply(undefined, boundHandler.args); - } catch (err) { - promise.reject(err); - return; - } - resolve(promise, x); - } - function boundHandler() { - boundHandler.args = arguments; - process.nextTick(newTickHandler); +Kareem.prototype.pre = function(name, isAsync, fn, error) { + if (typeof arguments[1] !== 'boolean') { + error = fn; + fn = isAsync; + isAsync = false; } - return boundHandler; -} + this._pres[name] = this._pres[name] || []; + var pres = this._pres[name]; -function resolve(promise, x) { - function fulfillOnce() { - if (done++) return; - resolve.apply(undefined, strongUnshift(promise, arguments)); - } - function rejectOnce(reason) { - if (done++) return; - promise.reject(reason); + if (isAsync) { + pres.numAsync = pres.numAsync || 0; + ++pres.numAsync; } - if (promise === x) { - promise.reject(new TypeError("promise and x are the same")); - return; - } - var rest = toArray(arguments, 1); - var type = typeof x; - if ('undefined' == type || null == x || !('object' == type || 'function' == type)) { - promise.fulfill.apply(promise, rest); - return; - } + pres.push({ fn: fn, isAsync: isAsync }); - try { - var theThen = x.then; - } catch (err) { - promise.reject(err); - return; - } + return this; +}; - if ('function' != typeof theThen) { - promise.fulfill.apply(promise, rest); - return; - } +Kareem.prototype.post = function(name, fn) { + (this._posts[name] = this._posts[name] || []).push(fn); + return this; +}; - var done = 0; - try { - var ret = theThen.call(x, fulfillOnce, rejectOnce); - return ret; - } catch (err) { - if (done++) return; - promise.reject(err); +Kareem.prototype.clone = function() { + var n = new Kareem(); + for (var key in this._pres) { + n._pres[key] = this._pres[key].slice(); + } + for (var key in this._posts) { + n._posts[key] = this._posts[key].slice(); } -} - -/** - * Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught. - * - * ####Example: - * - * var p = new Promise; - * p.then(function(){ throw new Error('shucks') }); - * setTimeout(function () { - * p.fulfill(); - * // error was caught and swallowed by the promise returned from - * // p.then(). we either have to always register handlers on - * // the returned promises or we can do the following... - * }, 10); - * - * // this time we use .end() which prevents catching thrown errors - * var p = new Promise; - * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <-- - * setTimeout(function () { - * p.fulfill(); // throws "shucks" - * }, 10); - * - * @api public - * @param {Function} [onReject] - * @return {MPromise} this - */ -Promise.prototype.end = Promise.prototype['catch'] = function (onReject) { - if (!onReject && !this.hasRejectListeners()) - onReject = function idRejector(e) { throw e; }; - this.onReject(onReject); - this.ended = true; - return this; + return n; }; +module.exports = Kareem; + +}).call(this,require("g5I+bs")) +},{"g5I+bs":94}],80:[function(require,module,exports){ +module.exports = exports = require('./lib'); +},{"./lib":81}],81:[function(require,module,exports){ /** - * A debug utility function that adds handlers to a promise that will log some output to the `console` + * Returns the value of object `o` at the given `path`. * * ####Example: * - * var p = new Promise; - * p.then(function(){ throw new Error('shucks') }); - * setTimeout(function () { - * p.fulfill(); - * // error was caught and swallowed by the promise returned from - * // p.then(). we either have to always register handlers on - * // the returned promises or we can do the following... - * }, 10); + * var obj = { + * comments: [ + * { title: 'exciting!', _doc: { title: 'great!' }} + * , { title: 'number dos' } + * ] + * } * - * // this time we use .end() which prevents catching thrown errors - * var p = new Promise; - * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <-- - * setTimeout(function () { - * p.fulfill(); // throws "shucks" - * }, 10); + * mpath.get('comments.0.title', o) // 'exciting!' + * mpath.get('comments.0.title', o, '_doc') // 'great!' + * mpath.get('comments.title', o) // ['exciting!', 'number dos'] * - * @api public - * @param {MPromise} p - * @param {String} name - * @return {MPromise} this + * // summary + * mpath.get(path, o) + * mpath.get(path, o, special) + * mpath.get(path, o, map) + * mpath.get(path, o, special, map) + * + * @param {String} path + * @param {Object} o + * @param {String} [special] When this property name is present on any object in the path, walking will continue on the value of this property. + * @param {Function} [map] Optional function which receives each individual found value. The value returned from `map` is used in the original values place. */ -Promise.trace = function (p, name) { - p.then( - function () { - console.log("%s fulfill %j", name, toArray(arguments)); - }, - function () { - console.log("%s reject %j", name, toArray(arguments)); + +exports.get = function (path, o, special, map) { + var lookup; + + if ('function' == typeof special) { + if (special.length < 2) { + map = special; + special = undefined; + } else { + lookup = special; + special = undefined; } - ) -}; + } + map || (map = K); -Promise.prototype.chain = function (p2) { - var p1 = this; - p1.onFulfill(p2.fulfill.bind(p2)); - p1.onReject(p2.reject.bind(p2)); - return p2; -}; + var parts = 'string' == typeof path + ? path.split('.') + : path + if (!Array.isArray(parts)) { + throw new TypeError('Invalid `path`. Must be either string or array'); + } -Promise.prototype.all = function (promiseOfArr) { - var pRet = new Promise; - this.then(promiseOfArr).then( - function (promiseArr) { - var count = 0; - var ret = []; - var errSentinel; - if (!promiseArr.length) pRet.resolve(); - promiseArr.forEach(function (promise, index) { - if (errSentinel) return; - count++; - promise.then( - function (val) { - if (errSentinel) return; - ret[index] = val; - --count; - if (count == 0) pRet.fulfill(ret); - }, - function (err) { - if (errSentinel) return; - errSentinel = err; - pRet.reject(err); - } - ); - }); - return pRet; - } - , pRet.reject.bind(pRet) - ); - return pRet; -}; - + var obj = o + , part; -Promise.hook = function (arr) { - var p1 = new Promise; - var pFinal = new Promise; - var signalP = function () { - --count; - if (count == 0) - pFinal.fulfill(); - return pFinal; - }; - var count = 1; - var ps = p1; - arr.forEach(function (hook) { - ps = ps.then( - function () { - var p = new Promise; - count++; - hook(p.resolve.bind(p), signalP); - return p; - } - ) - }); - ps = ps.then(signalP); - p1.resolve(); - return ps; -}; + for (var i = 0; i < parts.length; ++i) { + part = parts[i]; + if (Array.isArray(obj) && !/^\d+$/.test(part)) { + // reading a property from the array items + var paths = parts.slice(i); -/* This is for the A+ tests, but it's very useful as well */ -Promise.fulfilled = function fulfilled() { var p = new Promise; p.fulfill.apply(p, arguments); return p; }; -Promise.rejected = function rejected(reason) { return new Promise().reject(reason); }; -Promise.deferred = function deferred() { - var p = new Promise; - return { - promise: p, - reject: p.reject.bind(p), - resolve: p.fulfill.bind(p), - callback: p.resolve.bind(p) - } -}; -/* End A+ tests adapter bit */ + return obj.map(function (item) { + return item + ? exports.get(paths, item, special || lookup, map) + : map(undefined); + }); + } -}).call(this,require("g5I+bs")) -},{"events":72,"g5I+bs":94,"util":98}],81:[function(require,module,exports){ -'use strict'; + if (lookup) { + obj = lookup(obj, part); + } else { + obj = special && obj[special] + ? obj[special][part] + : obj[part]; + } -/** - * methods a collection must implement - */ + if (!obj) return map(obj); + } -var methods = [ - 'find' - , 'findOne' - , 'update' - , 'remove' - , 'count' - , 'distinct' - , 'findAndModify' - , 'aggregate' - , 'findStream' -]; + return map(obj); +} /** - * Collection base class from which implementations inherit + * Sets the `val` at the given `path` of object `o`. + * + * @param {String} path + * @param {Anything} val + * @param {Object} o + * @param {String} [special] When this property name is present on any object in the path, walking will continue on the value of this property. + * @param {Function} [map] Optional function which is passed each individual value before setting it. The value returned from `map` is used in the original values place. */ -function Collection () {} +exports.set = function (path, val, o, special, map, _copying) { + var lookup; -for (var i = 0, len = methods.length; i < len; ++i) { - var method = methods[i]; - Collection.prototype[method] = notImplemented(method); -} + if ('function' == typeof special) { + if (special.length < 2) { + map = special; + special = undefined; + } else { + lookup = special; + special = undefined; + } + } -module.exports = exports = Collection; -Collection.methods = methods; + map || (map = K); -/** - * creates a function which throws an implementation error - */ + var parts = 'string' == typeof path + ? path.split('.') + : path -function notImplemented (method) { - return function () { - throw new Error('collection.' + method + ' not implemented'); + if (!Array.isArray(parts)) { + throw new TypeError('Invalid `path`. Must be either string or array'); } -} + if (null == o) return; -},{}],82:[function(require,module,exports){ -'use strict'; - -var env = require('../env') + // the existance of $ in a path tells us if the user desires + // the copying of an array instead of setting each value of + // the array to the one by one to matching positions of the + // current array. + var copy = _copying || /\$/.test(path) + , obj = o + , part -if ('unknown' == env.type) { - throw new Error('Unknown environment') -} + for (var i = 0, len = parts.length - 1; i < len; ++i) { + part = parts[i]; -module.exports = - env.isNode ? require('./node') : - env.isMongo ? require('./collection') : - require('./collection'); + if ('$' == part) { + if (i == len - 1) { + break; + } else { + continue; + } + } + if (Array.isArray(obj) && !/^\d+$/.test(part)) { + var paths = parts.slice(i); + if (!copy && Array.isArray(val)) { + for (var j = 0; j < obj.length && j < val.length; ++j) { + // assignment of single values of array + exports.set(paths, val[j], obj[j], special || lookup, map, copy); + } + } else { + for (var j = 0; j < obj.length; ++j) { + // assignment of entire value + exports.set(paths, val, obj[j], special || lookup, map, copy); + } + } + return; + } -},{"../env":84,"./collection":81,"./node":83}],83:[function(require,module,exports){ -'use strict'; + if (lookup) { + obj = lookup(obj, part); + } else { + obj = special && obj[special] + ? obj[special][part] + : obj[part]; + } -/** - * Module dependencies - */ + if (!obj) return; + } -var Collection = require('./collection'); -var utils = require('../utils'); + // process the last property of the path -function NodeCollection (col) { - this.collection = col; - this.collectionName = col.collectionName; -} + part = parts[len]; -/** - * inherit from collection base class - */ + // use the special property if exists + if (special && obj[special]) { + obj = obj[special]; + } -utils.inherits(NodeCollection, Collection); + // set the value on the last branch + if (Array.isArray(obj) && !/^\d+$/.test(part)) { + if (!copy && Array.isArray(val)) { + for (var item, j = 0; j < obj.length && j < val.length; ++j) { + item = obj[j]; + if (item) { + if (lookup) { + lookup(item, part, map(val[j])); + } else { + if (item[special]) item = item[special]; + item[part] = map(val[j]); + } + } + } + } else { + for (var j = 0; j < obj.length; ++j) { + item = obj[j]; + if (item) { + if (lookup) { + lookup(item, part, map(val)); + } else { + if (item[special]) item = item[special]; + item[part] = map(val); + } + } + } + } + } else { + if (lookup) { + lookup(obj, part, map(val)); + } else { + obj[part] = map(val); + } + } +} -/** - * find(match, options, function(err, docs)) +/*! + * Returns the value passed to it. */ -NodeCollection.prototype.find = function (match, options, cb) { - this.collection.find(match, options, function (err, cursor) { - if (err) return cb(err); - - cursor.toArray(cb); - }); +function K (v) { + return v; } -/** - * findOne(match, options, function(err, doc)) - */ - -NodeCollection.prototype.findOne = function (match, options, cb) { - this.collection.findOne(match, options, cb); +},{}],82:[function(require,module,exports){ +(function (process){ +'use strict'; +var util = require('util'); +var EventEmitter = require('events').EventEmitter; +function toArray(arr, start, end) { + return Array.prototype.slice.call(arr, start, end) +} +function strongUnshift(x, arrLike) { + var arr = toArray(arrLike); + arr.unshift(x); + return arr; } + /** - * count(match, options, function(err, count)) + * MPromise constructor. + * + * _NOTE: The success and failure event names can be overridden by setting `Promise.SUCCESS` and `Promise.FAILURE` respectively._ + * + * @param {Function} back a function that accepts `fn(err, ...){}` as signature + * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter + * @event `reject`: Emits when the promise is rejected (event name may be overridden) + * @event `fulfill`: Emits when the promise is fulfilled (event name may be overridden) + * @api public */ - -NodeCollection.prototype.count = function (match, options, cb) { - this.collection.count(match, options, cb); +function Promise(back) { + this.emitter = new EventEmitter(); + this.emitted = {}; + this.ended = false; + if ('function' == typeof back) { + this.ended = true; + this.onResolve(back); + } } -/** - * distinct(prop, match, options, function(err, count)) + +/* + * Module exports. */ +module.exports = Promise; -NodeCollection.prototype.distinct = function (prop, match, options, cb) { - this.collection.distinct(prop, match, options, cb); -} -/** - * update(match, update, options, function(err[, result])) +/*! + * event names */ +Promise.SUCCESS = 'fulfill'; +Promise.FAILURE = 'reject'; -NodeCollection.prototype.update = function (match, update, options, cb) { - this.collection.update(match, update, options, cb); -} /** - * remove(match, options, function(err[, result]) + * Adds `listener` to the `event`. + * + * If `event` is either the success or failure event and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event. + * + * @param {String} event + * @param {Function} callback + * @return {MPromise} this + * @api private */ +Promise.prototype.on = function (event, callback) { + if (this.emitted[event]) + callback.apply(undefined, this.emitted[event]); + else + this.emitter.on(event, callback); + + return this; +}; -NodeCollection.prototype.remove = function (match, options, cb) { - this.collection.remove(match, options, cb); -} /** - * findAndModify(match, update, options, function(err, doc)) + * Keeps track of emitted events to run them on `on`. + * + * @api private */ +Promise.prototype.safeEmit = function (event) { + // ensures a promise can't be fulfill() or reject() more than once + if (event == Promise.SUCCESS || event == Promise.FAILURE) { + if (this.emitted[Promise.SUCCESS] || this.emitted[Promise.FAILURE]) { + return this; + } + this.emitted[event] = toArray(arguments, 1); + } + + this.emitter.emit.apply(this.emitter, arguments); + return this; +}; -NodeCollection.prototype.findAndModify = function (match, update, options, cb) { - var sort = Array.isArray(options.sort) ? options.sort : []; - this.collection.findAndModify(match, sort, update, options, cb); -} /** - * var stream = findStream(match, findOptions, streamOptions) + * @api private */ +Promise.prototype.hasRejectListeners = function () { + return EventEmitter.listenerCount(this.emitter, Promise.FAILURE) > 0; +}; -NodeCollection.prototype.findStream = function(match, findOptions, streamOptions) { - return this.collection.find(match, findOptions).stream(streamOptions); -} /** - * var cursor = findCursor(match, findOptions) + * Fulfills this promise with passed arguments. + * + * If this promise has already been fulfilled or rejected, no action is taken. + * + * @api public */ +Promise.prototype.fulfill = function () { + return this.safeEmit.apply(this, strongUnshift(Promise.SUCCESS, arguments)); +}; -NodeCollection.prototype.findCursor = function(match, findOptions) { - return this.collection.find(match, findOptions); -} /** - * aggregation(operators..., function(err, doc)) - * TODO + * Rejects this promise with `reason`. + * + * If this promise has already been fulfilled or rejected, no action is taken. + * + * @api public + * @param {Object|String} reason + * @return {MPromise} this */ +Promise.prototype.reject = function (reason) { + if (this.ended && !this.hasRejectListeners()) + throw reason; + return this.safeEmit(Promise.FAILURE, reason); +}; + /** - * Expose + * Resolves this promise to a rejected state if `err` is passed or + * fulfilled state if no `err` is passed. + * + * @param {Error} [err] error or null + * @param {Object} [val] value to fulfill the promise with + * @api public */ +Promise.prototype.resolve = function (err, val) { + if (err) return this.reject(err); + return this.fulfill(val); +}; -module.exports = exports = NodeCollection; - - -},{"../utils":87,"./collection":81}],84:[function(require,module,exports){ -(function (process,global,Buffer){ -'use strict'; - -exports.isNode = 'undefined' != typeof process - && 'object' == typeof module - && 'object' == typeof global - && 'function' == typeof Buffer - && process.argv -exports.isMongo = !exports.isNode - && 'function' == typeof printjson - && 'function' == typeof ObjectId - && 'function' == typeof rs - && 'function' == typeof sh; +/** + * Adds a listener to the SUCCESS event. + * + * @return {MPromise} this + * @api public + */ +Promise.prototype.onFulfill = function (fn) { + if (!fn) return this; + if ('function' != typeof fn) throw new TypeError("fn should be a function"); + return this.on(Promise.SUCCESS, fn); +}; -exports.isBrowser = !exports.isNode - && !exports.isMongo - && 'undefined' != typeof window; -exports.type = exports.isNode ? 'node' - : exports.isMongo ? 'mongo' - : exports.isBrowser ? 'browser' - : 'unknown' +/** + * Adds a listener to the FAILURE event. + * + * @return {MPromise} this + * @api public + */ +Promise.prototype.onReject = function (fn) { + if (!fn) return this; + if ('function' != typeof fn) throw new TypeError("fn should be a function"); + return this.on(Promise.FAILURE, fn); +}; -}).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"buffer":71,"g5I+bs":94}],85:[function(require,module,exports){ -'use strict'; /** - * Dependencies + * Adds a single function as a listener to both SUCCESS and FAILURE. + * + * It will be executed with traditional node.js argument position: + * function (err, args...) {} + * + * Also marks the promise as `end`ed, since it's the common use-case, and yet has no + * side effects unless `fn` is undefined or null. + * + * @param {Function} fn + * @return {MPromise} this */ +Promise.prototype.onResolve = function (fn) { + if (!fn) return this; + if ('function' != typeof fn) throw new TypeError("fn should be a function"); + this.on(Promise.FAILURE, function (err) { fn.call(this, err); }); + this.on(Promise.SUCCESS, function () { fn.apply(this, strongUnshift(null, arguments)); }); + return this; +}; -var slice = require('sliced') -var assert = require('assert') -var util = require('util') -var utils = require('./utils') -var debug = require('debug')('mquery'); /** - * Query constructor used for building queries. + * Creates a new promise and returns it. If `onFulfill` or + * `onReject` are passed, they are added as SUCCESS/ERROR callbacks + * to this promise after the next tick. + * + * Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification. Read for more detail how to use this method. * * ####Example: * - * var query = new Query({ name: 'mquery' }); - * query.setOptions({ collection: moduleCollection }) - * query.where('age').gte(21).exec(callback); + * var p = new Promise; + * p.then(function (arg) { + * return arg + 1; + * }).then(function (arg) { + * throw new Error(arg + ' is an error!'); + * }).then(null, function (err) { + * assert.ok(err instanceof Error); + * assert.equal('2 is an error', err.message); + * }); + * p.complete(1); * - * @param {Object} [criteria] - * @param {Object} [options] - * @api public + * @see promises-A+ https://github.com/promises-aplus/promises-spec + * @param {Function} onFulfill + * @param {Function} [onReject] + * @return {MPromise} newPromise */ +Promise.prototype.then = function (onFulfill, onReject) { + var newPromise = new Promise; -function Query (criteria, options) { - if (!(this instanceof Query)) - return new Query(criteria, options); + if ('function' == typeof onFulfill) { + this.onFulfill(handler(newPromise, onFulfill)); + } else { + this.onFulfill(newPromise.fulfill.bind(newPromise)); + } - var proto = this.constructor.prototype; + if ('function' == typeof onReject) { + this.onReject(handler(newPromise, onReject)); + } else { + this.onReject(newPromise.reject.bind(newPromise)); + } - this.op = proto.op || undefined; + return newPromise; +}; - this.options = {}; - this.setOptions(proto.options); - this._conditions = proto._conditions - ? utils.clone(proto._conditions) - : {}; +function handler(promise, fn) { + function newTickHandler() { + var pDomain = promise.emitter.domain; + if (pDomain && pDomain !== process.domain) pDomain.enter(); + try { + var x = fn.apply(undefined, boundHandler.args); + } catch (err) { + promise.reject(err); + return; + } + resolve(promise, x); + } + function boundHandler() { + boundHandler.args = arguments; + process.nextTick(newTickHandler); + } + return boundHandler; +} - this._fields = proto._fields - ? utils.clone(proto._fields) - : undefined; - this._update = proto._update - ? utils.clone(proto._update) - : undefined; +function resolve(promise, x) { + function fulfillOnce() { + if (done++) return; + resolve.apply(undefined, strongUnshift(promise, arguments)); + } + function rejectOnce(reason) { + if (done++) return; + promise.reject(reason); + } - this._path = proto._path || undefined; - this._distinct = proto._distinct || undefined; - this._collection = proto._collection || undefined; - this._traceFunction = proto._traceFunction || undefined; + if (promise === x) { + promise.reject(new TypeError("promise and x are the same")); + return; + } + var rest = toArray(arguments, 1); + var type = typeof x; + if ('undefined' == type || null == x || !('object' == type || 'function' == type)) { + promise.fulfill.apply(promise, rest); + return; + } - if (options) { - this.setOptions(options); + try { + var theThen = x.then; + } catch (err) { + promise.reject(err); + return; } - if (criteria) { - if (criteria.find && criteria.remove && criteria.update) { - // quack quack! - this.collection(criteria); - } else { - this.find(criteria); - } + if ('function' != typeof theThen) { + promise.fulfill.apply(promise, rest); + return; } -} -/** - * This is a parameter that the user can set which determines if mquery - * uses $within or $geoWithin for queries. It defaults to true which - * means $geoWithin will be used. If using MongoDB < 2.4 you should - * set this to false. - * - * @api public - * @property use$geoWithin - */ + var done = 0; + try { + var ret = theThen.call(x, fulfillOnce, rejectOnce); + return ret; + } catch (err) { + if (done++) return; + promise.reject(err); + } +} -var $withinCmd = '$geoWithin'; -Object.defineProperty(Query, 'use$geoWithin', { - get: function ( ) { return $withinCmd == '$geoWithin' } - , set: function (v) { - if (true === v) { - // mongodb >= 2.4 - $withinCmd = '$geoWithin'; - } else { - $withinCmd = '$within'; - } - } -}); /** - * Converts this query to a constructor function with all arguments and options retained. - * - * ####Example - * - * // Create a query that will read documents with a "video" category from - * // `aCollection` on the primary node in the replica-set unless it is down, - * // in which case we'll read from a secondary node. - * var query = mquery({ category: 'video' }) - * query.setOptions({ collection: aCollection, read: 'primaryPreferred' }); + * Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught. * - * // create a constructor based off these settings - * var Video = query.toConstructor(); + * ####Example: * - * // Video is now a subclass of mquery() and works the same way but with the - * // default query parameters and options set. + * var p = new Promise; + * p.then(function(){ throw new Error('shucks') }); + * setTimeout(function () { + * p.fulfill(); + * // error was caught and swallowed by the promise returned from + * // p.then(). we either have to always register handlers on + * // the returned promises or we can do the following... + * }, 10); * - * // run a query with the previous settings but filter for movies with names - * // that start with "Life". - * Video().where({ name: /^Life/ }).exec(cb); + * // this time we use .end() which prevents catching thrown errors + * var p = new Promise; + * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <-- + * setTimeout(function () { + * p.fulfill(); // throws "shucks" + * }, 10); * - * @return {Query} new Query * @api public + * @param {Function} [onReject] + * @return {MPromise} this */ +Promise.prototype.end = Promise.prototype['catch'] = function (onReject) { + if (!onReject && !this.hasRejectListeners()) + onReject = function idRejector(e) { throw e; }; + this.onReject(onReject); + this.ended = true; + return this; +}; -Query.prototype.toConstructor = function toConstructor () { - function CustomQuery (criteria, options) { - if (!(this instanceof CustomQuery)) - return new CustomQuery(criteria, options); - Query.call(this, criteria, options); - } - - utils.inherits(CustomQuery, Query); - - // set inherited defaults - var p = CustomQuery.prototype; - - p.options = {}; - p.setOptions(this.options); - - p.op = this.op; - p._conditions = utils.clone(this._conditions); - p._fields = utils.clone(this._fields); - p._update = utils.clone(this._update); - p._path = this._path; - p._distinct = this._distinct; - p._collection = this._collection; - p._traceFunction = this._traceFunction; - - return CustomQuery; -} /** - * Sets query options. + * A debug utility function that adds handlers to a promise that will log some output to the `console` * - * ####Options: + * ####Example: * - * - [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors) * - * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D) * - * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D) * - * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D) * - * - [maxScan](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan) * - * - [maxTime](http://docs.mongodb.org/manual/reference/operator/meta/maxTimeMS/#op._S_maxTimeMS) * - * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D) * - * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment) * - * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D) * - * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint) * - * - [slaveOk](http://docs.mongodb.org/manual/applications/replication/#read-preference) * - * - [safe](http://www.mongodb.org/display/DOCS/getLastError+Command) - * - collection the collection to query against + * var p = new Promise; + * p.then(function(){ throw new Error('shucks') }); + * setTimeout(function () { + * p.fulfill(); + * // error was caught and swallowed by the promise returned from + * // p.then(). we either have to always register handlers on + * // the returned promises or we can do the following... + * }, 10); * - * _* denotes a query helper method is also available_ + * // this time we use .end() which prevents catching thrown errors + * var p = new Promise; + * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <-- + * setTimeout(function () { + * p.fulfill(); // throws "shucks" + * }, 10); * - * @param {Object} options * @api public + * @param {MPromise} p + * @param {String} name + * @return {MPromise} this */ - -Query.prototype.setOptions = function (options) { - if (!(options && utils.isObject(options))) - return this; - - // set arbitrary options - var methods = utils.keys(options) - , method - - for (var i = 0; i < methods.length; ++i) { - method = methods[i]; - - // use methods if exist (safer option manipulation) - if ('function' == typeof this[method]) { - var args = utils.isArray(options[method]) - ? options[method] - : [options[method]]; - this[method].apply(this, args) - } else { - this.options[method] = options[method]; +Promise.trace = function (p, name) { + p.then( + function () { + console.log("%s fulfill %j", name, toArray(arguments)); + }, + function () { + console.log("%s reject %j", name, toArray(arguments)); } - } - - return this; -} + ) +}; -/** - * Sets this Querys collection. - * - * @param {Collection} coll - * @return {Query} this - */ -Query.prototype.collection = function collection (coll) { - this._collection = new Query.Collection(coll); +Promise.prototype.chain = function (p2) { + var p1 = this; + p1.onFulfill(p2.fulfill.bind(p2)); + p1.onReject(p2.reject.bind(p2)); + return p2; +}; - return this; -} -/** - * Specifies a `$where` condition - * - * Use `$where` when you need to select documents using a JavaScript expression. - * - * ####Example - * - * query.$where('this.comments.length > 10 || this.name.length > 5') - * - * query.$where(function () { - * return this.comments.length > 10 || this.name.length > 5; - * }) - * - * @param {String|Function} js javascript string or function - * @return {Query} this - * @memberOf Query - * @method $where - * @api public +Promise.prototype.all = function (promiseOfArr) { + var pRet = new Promise; + this.then(promiseOfArr).then( + function (promiseArr) { + var count = 0; + var ret = []; + var errSentinel; + if (!promiseArr.length) pRet.resolve(); + promiseArr.forEach(function (promise, index) { + if (errSentinel) return; + count++; + promise.then( + function (val) { + if (errSentinel) return; + ret[index] = val; + --count; + if (count == 0) pRet.fulfill(ret); + }, + function (err) { + if (errSentinel) return; + errSentinel = err; + pRet.reject(err); + } + ); + }); + return pRet; + } + , pRet.reject.bind(pRet) + ); + return pRet; +}; + + +Promise.hook = function (arr) { + var p1 = new Promise; + var pFinal = new Promise; + var signalP = function () { + --count; + if (count == 0) + pFinal.fulfill(); + return pFinal; + }; + var count = 1; + var ps = p1; + arr.forEach(function (hook) { + ps = ps.then( + function () { + var p = new Promise; + count++; + hook(p.resolve.bind(p), signalP); + return p; + } + ) + }); + ps = ps.then(signalP); + p1.resolve(); + return ps; +}; + + +/* This is for the A+ tests, but it's very useful as well */ +Promise.fulfilled = function fulfilled() { var p = new Promise; p.fulfill.apply(p, arguments); return p; }; +Promise.rejected = function rejected(reason) { return new Promise().reject(reason); }; +Promise.deferred = function deferred() { + var p = new Promise; + return { + promise: p, + reject: p.reject.bind(p), + resolve: p.fulfill.bind(p), + callback: p.resolve.bind(p) + } +}; +/* End A+ tests adapter bit */ + +}).call(this,require("g5I+bs")) +},{"events":74,"g5I+bs":94,"util":98}],83:[function(require,module,exports){ +'use strict'; + +/** + * methods a collection must implement */ -Query.prototype.$where = function (js) { - this._conditions.$where = js; - return this; -} +var methods = [ + 'find' + , 'findOne' + , 'update' + , 'remove' + , 'count' + , 'distinct' + , 'findAndModify' + , 'aggregate' + , 'findStream' +]; /** - * Specifies a `path` for use with chaining. - * - * ####Example - * - * // instead of writing: - * User.find({age: {$gte: 21, $lte: 65}}, callback); - * - * // we can instead write: - * User.where('age').gte(21).lte(65); - * - * // passing query conditions is permitted - * User.find().where({ name: 'vonderful' }) - * - * // chaining - * User - * .where('age').gte(21).lte(65) - * .where('name', /^vonderful/i) - * .where('friends').slice(10) - * .exec(callback) - * - * @param {String} [path] - * @param {Object} [val] - * @return {Query} this - * @api public + * Collection base class from which implementations inherit */ -Query.prototype.where = function () { - if (!arguments.length) return this; - if (!this.op) this.op = 'find'; +function Collection () {} - var type = typeof arguments[0]; +for (var i = 0, len = methods.length; i < len; ++i) { + var method = methods[i]; + Collection.prototype[method] = notImplemented(method); +} - if ('string' == type) { - this._path = arguments[0]; +module.exports = exports = Collection; +Collection.methods = methods; - if (2 === arguments.length) { - this._conditions[this._path] = arguments[1]; - } +/** + * creates a function which throws an implementation error + */ - return this; +function notImplemented (method) { + return function () { + throw new Error('collection.' + method + ' not implemented'); } +} - if ('object' == type && !Array.isArray(arguments[0])) { - return this.merge(arguments[0]); - } - throw new TypeError('path must be a string or object'); +},{}],84:[function(require,module,exports){ +'use strict'; + +var env = require('../env') + +if ('unknown' == env.type) { + throw new Error('Unknown environment') } +module.exports = + env.isNode ? require('./node') : + env.isMongo ? require('./collection') : + require('./collection'); + + +},{"../env":86,"./collection":83,"./node":85}],85:[function(require,module,exports){ +'use strict'; + /** - * Specifies the complementary comparison value for paths specified with `where()` - * - * ####Example - * - * User.where('age').equals(49); - * - * // is the same as - * - * User.where('age', 49); - * - * @param {Object} val - * @return {Query} this - * @api public + * Module dependencies */ -Query.prototype.equals = function equals (val) { - this._ensurePath('equals'); - var path = this._path; - this._conditions[path] = val; - return this; +var Collection = require('./collection'); +var utils = require('../utils'); + +function NodeCollection (col) { + this.collection = col; + this.collectionName = col.collectionName; } /** - * Specifies the complementary comparison value for paths specified with `where()` - * This is alias of `equals` - * - * ####Example - * - * User.where('age').eq(49); - * - * // is the same as - * - * User.shere('age').equals(49); - * - * // is the same as - * - * User.where('age', 49); - * - * @param {Object} val - * @return {Query} this - * @api public + * inherit from collection base class */ -Query.prototype.eq = function eq (val) { - this._ensurePath('eq'); - var path = this._path; - this._conditions[path] = val; - return this; +utils.inherits(NodeCollection, Collection); + +/** + * find(match, options, function(err, docs)) + */ + +NodeCollection.prototype.find = function (match, options, cb) { + this.collection.find(match, options, function (err, cursor) { + if (err) return cb(err); + + cursor.toArray(cb); + }); } /** - * Specifies arguments for an `$or` condition. - * - * ####Example - * - * query.or([{ color: 'red' }, { status: 'emergency' }]) - * - * @param {Array} array array of conditions - * @return {Query} this - * @api public + * findOne(match, options, function(err, doc)) */ -Query.prototype.or = function or (array) { - var or = this._conditions.$or || (this._conditions.$or = []); - if (!utils.isArray(array)) array = [array]; - or.push.apply(or, array); - return this; +NodeCollection.prototype.findOne = function (match, options, cb) { + this.collection.findOne(match, options, cb); } /** - * Specifies arguments for a `$nor` condition. - * - * ####Example - * - * query.nor([{ color: 'green' }, { status: 'ok' }]) - * - * @param {Array} array array of conditions - * @return {Query} this - * @api public + * count(match, options, function(err, count)) */ -Query.prototype.nor = function nor (array) { - var nor = this._conditions.$nor || (this._conditions.$nor = []); - if (!utils.isArray(array)) array = [array]; - nor.push.apply(nor, array); - return this; +NodeCollection.prototype.count = function (match, options, cb) { + this.collection.count(match, options, cb); } /** - * Specifies arguments for a `$and` condition. - * - * ####Example - * - * query.and([{ color: 'green' }, { status: 'ok' }]) - * - * @see $and http://docs.mongodb.org/manual/reference/operator/and/ - * @param {Array} array array of conditions - * @return {Query} this - * @api public + * distinct(prop, match, options, function(err, count)) */ -Query.prototype.and = function and (array) { - var and = this._conditions.$and || (this._conditions.$and = []); - if (!Array.isArray(array)) array = [array]; - and.push.apply(and, array); - return this; +NodeCollection.prototype.distinct = function (prop, match, options, cb) { + this.collection.distinct(prop, match, options, cb); } /** - * Specifies a $gt query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * ####Example - * - * Thing.find().where('age').gt(21) - * - * // or - * Thing.find().gt('age', 21) - * - * @method gt - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public + * update(match, update, options, function(err[, result])) */ -/** - * Specifies a $gte query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * @method gte - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public - */ +NodeCollection.prototype.update = function (match, update, options, cb) { + this.collection.update(match, update, options, cb); +} /** - * Specifies a $lt query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * @method lt - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public + * remove(match, options, function(err[, result]) */ -/** - * Specifies a $lte query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * @method lte - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public - */ +NodeCollection.prototype.remove = function (match, options, cb) { + this.collection.remove(match, options, cb); +} /** - * Specifies a $ne query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * @method ne - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public + * findAndModify(match, update, options, function(err, doc)) */ +NodeCollection.prototype.findAndModify = function (match, update, options, cb) { + var sort = Array.isArray(options.sort) ? options.sort : []; + this.collection.findAndModify(match, sort, update, options, cb); +} + /** - * Specifies an $in query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * @method in - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public + * var stream = findStream(match, findOptions, streamOptions) */ +NodeCollection.prototype.findStream = function(match, findOptions, streamOptions) { + return this.collection.find(match, findOptions).stream(streamOptions); +} + /** - * Specifies an $nin query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * @method nin - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public + * var cursor = findCursor(match, findOptions) */ +NodeCollection.prototype.findCursor = function(match, findOptions) { + return this.collection.find(match, findOptions); +} + /** - * Specifies an $all query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * @method all - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public + * aggregation(operators..., function(err, doc)) + * TODO */ /** - * Specifies a $size query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * @method size - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public + * Expose */ +module.exports = exports = NodeCollection; + + +},{"../utils":89,"./collection":83}],86:[function(require,module,exports){ +(function (process,global,Buffer){ +'use strict'; + +exports.isNode = 'undefined' != typeof process + && 'object' == typeof module + && 'object' == typeof global + && 'function' == typeof Buffer + && process.argv + +exports.isMongo = !exports.isNode + && 'function' == typeof printjson + && 'function' == typeof ObjectId + && 'function' == typeof rs + && 'function' == typeof sh; + +exports.isBrowser = !exports.isNode + && !exports.isMongo + && 'undefined' != typeof window; + +exports.type = exports.isNode ? 'node' + : exports.isMongo ? 'mongo' + : exports.isBrowser ? 'browser' + : 'unknown' + +}).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) +},{"buffer":71,"g5I+bs":94}],87:[function(require,module,exports){ +'use strict'; + /** - * Specifies a $regex query condition. - * - * When called with one argument, the most recent path passed to `where()` is used. - * - * @method regex - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public + * Dependencies */ +var slice = require('sliced') +var assert = require('assert') +var util = require('util') +var utils = require('./utils') +var debug = require('debug')('mquery'); + /** - * Specifies a $maxDistance query condition. + * Query constructor used for building queries. * - * When called with one argument, the most recent path passed to `where()` is used. + * ####Example: * - * @method maxDistance - * @memberOf Query - * @param {String} [path] - * @param {Number} val - * @api public - */ - -/*! - * gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance + * var query = new Query({ name: 'mquery' }); + * query.setOptions({ collection: moduleCollection }) + * query.where('age').gte(21).exec(callback); * - * Thing.where('type').nin(array) + * @param {Object} [criteria] + * @param {Object} [options] + * @api public */ -'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) { - Query.prototype[$conditional] = function () { - var path, val; +function Query (criteria, options) { + if (!(this instanceof Query)) + return new Query(criteria, options); - if (1 === arguments.length) { - this._ensurePath($conditional); - val = arguments[0]; - path = this._path; - } else { - val = arguments[1]; - path = arguments[0]; - } + var proto = this.constructor.prototype; - var conds = this._conditions[path] || (this._conditions[path] = {}); - conds['$' + $conditional] = val; - return this; - }; -}) + this.op = proto.op || undefined; -/** - * Specifies a `$mod` condition - * - * @param {String} [path] - * @param {Number} val - * @return {Query} this - * @api public - */ + this.options = {}; + this.setOptions(proto.options); -Query.prototype.mod = function () { - var val, path; + this._conditions = proto._conditions + ? utils.clone(proto._conditions) + : {}; - if (1 === arguments.length) { - this._ensurePath('mod') - val = arguments[0]; - path = this._path; - } else if (2 === arguments.length && !utils.isArray(arguments[1])) { - this._ensurePath('mod') - val = slice(arguments); - path = this._path; - } else if (3 === arguments.length) { - val = slice(arguments, 1); - path = arguments[0]; - } else { - val = arguments[1]; - path = arguments[0]; + this._fields = proto._fields + ? utils.clone(proto._fields) + : undefined; + + this._update = proto._update + ? utils.clone(proto._update) + : undefined; + + this._path = proto._path || undefined; + this._distinct = proto._distinct || undefined; + this._collection = proto._collection || undefined; + this._traceFunction = proto._traceFunction || undefined; + + if (options) { + this.setOptions(options); } - var conds = this._conditions[path] || (this._conditions[path] = {}); - conds.$mod = val; - return this; + if (criteria) { + if (criteria.find && criteria.remove && criteria.update) { + // quack quack! + this.collection(criteria); + } else { + this.find(criteria); + } + } } /** - * Specifies an `$exists` condition - * - * ####Example - * - * // { name: { $exists: true }} - * Thing.where('name').exists() - * Thing.where('name').exists(true) - * Thing.find().exists('name') - * - * // { name: { $exists: false }} - * Thing.where('name').exists(false); - * Thing.find().exists('name', false); + * This is a parameter that the user can set which determines if mquery + * uses $within or $geoWithin for queries. It defaults to true which + * means $geoWithin will be used. If using MongoDB < 2.4 you should + * set this to false. * - * @param {String} [path] - * @param {Number} val - * @return {Query} this * @api public + * @property use$geoWithin */ -Query.prototype.exists = function () { - var path, val; - - if (0 === arguments.length) { - this._ensurePath('exists'); - path = this._path; - val = true; - } else if (1 === arguments.length) { - if ('boolean' === typeof arguments[0]) { - this._ensurePath('exists'); - path = this._path; - val = arguments[0]; - } else { - path = arguments[0]; - val = true; +var $withinCmd = '$geoWithin'; +Object.defineProperty(Query, 'use$geoWithin', { + get: function ( ) { return $withinCmd == '$geoWithin' } + , set: function (v) { + if (true === v) { + // mongodb >= 2.4 + $withinCmd = '$geoWithin'; + } else { + $withinCmd = '$within'; + } } - } else if (2 === arguments.length) { - path = arguments[0]; - val = arguments[1]; - } - - var conds = this._conditions[path] || (this._conditions[path] = {}); - conds.$exists = val; - return this; -} +}); /** - * Specifies an `$elemMatch` condition + * Converts this query to a constructor function with all arguments and options retained. * * ####Example * - * query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}}) + * // Create a query that will read documents with a "video" category from + * // `aCollection` on the primary node in the replica-set unless it is down, + * // in which case we'll read from a secondary node. + * var query = mquery({ category: 'video' }) + * query.setOptions({ collection: aCollection, read: 'primaryPreferred' }); * - * query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}}) + * // create a constructor based off these settings + * var Video = query.toConstructor(); * - * query.elemMatch('comment', function (elem) { - * elem.where('author').equals('autobot'); - * elem.where('votes').gte(5); - * }) + * // Video is now a subclass of mquery() and works the same way but with the + * // default query parameters and options set. * - * query.where('comment').elemMatch(function (elem) { - * elem.where({ author: 'autobot' }); - * elem.where('votes').gte(5); - * }) + * // run a query with the previous settings but filter for movies with names + * // that start with "Life". + * Video().where({ name: /^Life/ }).exec(cb); * - * @param {String|Object|Function} path - * @param {Object|Function} criteria - * @return {Query} this + * @return {Query} new Query * @api public */ -Query.prototype.elemMatch = function () { - if (null == arguments[0]) - throw new TypeError("Invalid argument"); +Query.prototype.toConstructor = function toConstructor () { + function CustomQuery (criteria, options) { + if (!(this instanceof CustomQuery)) + return new CustomQuery(criteria, options); + Query.call(this, criteria, options); + } - var fn, path, criteria; + utils.inherits(CustomQuery, Query); - if ('function' === typeof arguments[0]) { - this._ensurePath('elemMatch'); - path = this._path; - fn = arguments[0]; - } else if (utils.isObject(arguments[0])) { - this._ensurePath('elemMatch'); - path = this._path; - criteria = arguments[0]; - } else if ('function' === typeof arguments[1]) { - path = arguments[0]; - fn = arguments[1]; - } else if (arguments[1] && utils.isObject(arguments[1])) { - path = arguments[0]; - criteria = arguments[1]; - } else { - throw new TypeError("Invalid argument"); - } + // set inherited defaults + var p = CustomQuery.prototype; - if (fn) { - criteria = new Query; - fn(criteria); - criteria = criteria._conditions; - } + p.options = {}; + p.setOptions(this.options); - var conds = this._conditions[path] || (this._conditions[path] = {}); - conds.$elemMatch = criteria; - return this; -} + p.op = this.op; + p._conditions = utils.clone(this._conditions); + p._fields = utils.clone(this._fields); + p._update = utils.clone(this._update); + p._path = this._path; + p._distinct = this._distinct; + p._collection = this._collection; + p._traceFunction = this._traceFunction; -// Spatial queries + return CustomQuery; +} /** - * Sugar for geo-spatial queries. - * - * ####Example - * - * query.within().box() - * query.within().circle() - * query.within().geometry() - * - * query.where('loc').within({ center: [50,50], radius: 10, unique: true, spherical: true }); - * query.where('loc').within({ box: [[40.73, -73.9], [40.7, -73.988]] }); - * query.where('loc').within({ polygon: [[],[],[],[]] }); + * Sets query options. * - * query.where('loc').within([], [], []) // polygon - * query.where('loc').within([], []) // box - * query.where('loc').within({ type: 'LineString', coordinates: [...] }); // geometry + * ####Options: * - * ####NOTE: + * - [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors) * + * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D) * + * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D) * + * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D) * + * - [maxScan](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan) * + * - [maxTime](http://docs.mongodb.org/manual/reference/operator/meta/maxTimeMS/#op._S_maxTimeMS) * + * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D) * + * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment) * + * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D) * + * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint) * + * - [slaveOk](http://docs.mongodb.org/manual/applications/replication/#read-preference) * + * - [safe](http://www.mongodb.org/display/DOCS/getLastError+Command) + * - collection the collection to query against * - * Must be used after `where()`. + * _* denotes a query helper method is also available_ * - * @memberOf Query - * @return {Query} this + * @param {Object} options * @api public */ -Query.prototype.within = function within () { - // opinionated, must be used after where - this._ensurePath('within'); - this._geoComparison = $withinCmd; - - if (0 === arguments.length) { +Query.prototype.setOptions = function (options) { + if (!(options && utils.isObject(options))) return this; - } - - if (2 === arguments.length) { - return this.box.apply(this, arguments); - } else if (2 < arguments.length) { - return this.polygon.apply(this, arguments); - } - - var area = arguments[0]; - - if (!area) - throw new TypeError('Invalid argument'); - - if (area.center) - return this.circle(area); - if (area.box) - return this.box.apply(this, area.box); + // set arbitrary options + var methods = utils.keys(options) + , method - if (area.polygon) - return this.polygon.apply(this, area.polygon); + for (var i = 0; i < methods.length; ++i) { + method = methods[i]; - if (area.type && area.coordinates) - return this.geometry(area); + // use methods if exist (safer option manipulation) + if ('function' == typeof this[method]) { + var args = utils.isArray(options[method]) + ? options[method] + : [options[method]]; + this[method].apply(this, args) + } else { + this.options[method] = options[method]; + } + } - throw new TypeError('Invalid argument'); + return this; } /** - * Specifies a $box condition - * - * ####Example - * - * var lowerLeft = [40.73083, -73.99756] - * var upperRight= [40.741404, -73.988135] - * - * query.where('loc').within().box(lowerLeft, upperRight) - * query.box('loc', lowerLeft, upperRight ) + * Sets this Querys collection. * - * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing - * @see Query#within #query_Query-within - * @param {String} path - * @param {Object} val + * @param {Collection} coll * @return {Query} this - * @api public */ -Query.prototype.box = function () { - var path, box; - - if (3 === arguments.length) { - // box('loc', [], []) - path = arguments[0]; - box = [arguments[1], arguments[2]]; - } else if (2 === arguments.length) { - // box([], []) - this._ensurePath('box'); - path = this._path; - box = [arguments[0], arguments[1]]; - } else { - throw new TypeError("Invalid argument"); - } +Query.prototype.collection = function collection (coll) { + this._collection = new Query.Collection(coll); - var conds = this._conditions[path] || (this._conditions[path] = {}); - conds[this._geoComparison || $withinCmd] = { '$box': box }; return this; } /** - * Specifies a $polygon condition + * Specifies a `$where` condition + * + * Use `$where` when you need to select documents using a JavaScript expression. * * ####Example * - * query.where('loc').within().polygon([10,20], [13, 25], [7,15]) - * query.polygon('loc', [10,20], [13, 25], [7,15]) + * query.$where('this.comments.length > 10 || this.name.length > 5') * - * @param {String|Array} [path] - * @param {Array|Object} [val] + * query.$where(function () { + * return this.comments.length > 10 || this.name.length > 5; + * }) + * + * @param {String|Function} js javascript string or function * @return {Query} this - * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @memberOf Query + * @method $where * @api public */ -Query.prototype.polygon = function () { - var val, path; - - if ('string' == typeof arguments[0]) { - // polygon('loc', [],[],[]) - path = arguments[0]; - val = slice(arguments, 1); - } else { - // polygon([],[],[]) - this._ensurePath('polygon'); - path = this._path; - val = slice(arguments); - } - - var conds = this._conditions[path] || (this._conditions[path] = {}); - conds[this._geoComparison || $withinCmd] = { '$polygon': val }; +Query.prototype.$where = function (js) { + this._conditions.$where = js; return this; } /** - * Specifies a $center or $centerSphere condition. + * Specifies a `path` for use with chaining. * * ####Example * - * var area = { center: [50, 50], radius: 10, unique: true } - * query.where('loc').within().circle(area) - * query.center('loc', area); + * // instead of writing: + * User.find({age: {$gte: 21, $lte: 65}}, callback); * - * // for spherical calculations - * var area = { center: [50, 50], radius: 10, unique: true, spherical: true } - * query.where('loc').within().circle(area) - * query.center('loc', area); + * // we can instead write: + * User.where('age').gte(21).lte(65); + * + * // passing query conditions is permitted + * User.find().where({ name: 'vonderful' }) + * + * // chaining + * User + * .where('age').gte(21).lte(65) + * .where('name', /^vonderful/i) + * .where('friends').slice(10) + * .exec(callback) * * @param {String} [path] - * @param {Object} area + * @param {Object} [val] * @return {Query} this - * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing * @api public */ -Query.prototype.circle = function () { - var path, val; - - if (1 === arguments.length) { - this._ensurePath('circle'); - path = this._path; - val = arguments[0]; - } else if (2 === arguments.length) { - path = arguments[0]; - val = arguments[1]; - } else { - throw new TypeError("Invalid argument"); - } +Query.prototype.where = function () { + if (!arguments.length) return this; + if (!this.op) this.op = 'find'; - if (!('radius' in val && val.center)) - throw new Error('center and radius are required'); + var type = typeof arguments[0]; - var conds = this._conditions[path] || (this._conditions[path] = {}); + if ('string' == type) { + this._path = arguments[0]; - var type = val.spherical - ? '$centerSphere' - : '$center'; + if (2 === arguments.length) { + this._conditions[this._path] = arguments[1]; + } - var wKey = this._geoComparison || $withinCmd; - conds[wKey] = {}; - conds[wKey][type] = [val.center, val.radius]; + return this; + } - if ('unique' in val) - conds[wKey].$uniqueDocs = !! val.unique; + if ('object' == type && !Array.isArray(arguments[0])) { + return this.merge(arguments[0]); + } - return this; + throw new TypeError('path must be a string or object'); } /** - * Specifies a `$near` or `$nearSphere` condition - * - * These operators return documents sorted by distance. + * Specifies the complementary comparison value for paths specified with `where()` * * ####Example * - * query.where('loc').near({ center: [10, 10] }); - * query.where('loc').near({ center: [10, 10], maxDistance: 5 }); - * query.where('loc').near({ center: [10, 10], maxDistance: 5, spherical: true }); - * query.near('loc', { center: [10, 10], maxDistance: 5 }); - * query.near({ center: { type: 'Point', coordinates: [..] }}) - * query.near().geometry({ type: 'Point', coordinates: [..] }) + * User.where('age').equals(49); + * + * // is the same as + * + * User.where('age', 49); * - * @param {String} [path] * @param {Object} val * @return {Query} this - * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing * @api public */ -Query.prototype.near = function near () { - var path, val; - - this._geoComparison = '$near'; - - if (0 === arguments.length) { - return this; - } else if (1 === arguments.length) { - this._ensurePath('near'); - path = this._path; - val = arguments[0]; - } else if (2 === arguments.length) { - path = arguments[0]; - val = arguments[1]; - } else { - throw new TypeError("Invalid argument"); - } - - if (!val.center) { - throw new Error('center is required'); - } - - var conds = this._conditions[path] || (this._conditions[path] = {}); - - var type = val.spherical - ? '$nearSphere' - : '$near'; - - // center could be a GeoJSON object or an Array - if (Array.isArray(val.center)) { - conds[type] = val.center; - - var radius = 'maxDistance' in val - ? val.maxDistance - : null; - - if (null != radius) { - conds.$maxDistance = radius; - } - } else { - // GeoJSON? - if (val.center.type != 'Point' || !Array.isArray(val.center.coordinates)) { - throw new Error(util.format("Invalid GeoJSON specified for %s", type)); - } - conds[type] = { $geometry : val.center }; - - // MongoDB 2.6 insists on maxDistance being in $near / $nearSphere - if ('maxDistance' in val) { - conds[type]['$maxDistance'] = val.maxDistance; - } - } - +Query.prototype.equals = function equals (val) { + this._ensurePath('equals'); + var path = this._path; + this._conditions[path] = val; return this; } /** - * Declares an intersects query for `geometry()`. + * Specifies the complementary comparison value for paths specified with `where()` + * This is alias of `equals` * * ####Example * - * query.where('path').intersects().geometry({ - * type: 'LineString' - * , coordinates: [[180.0, 11.0], [180, 9.0]] - * }) + * User.where('age').eq(49); * - * query.where('path').intersects({ - * type: 'LineString' - * , coordinates: [[180.0, 11.0], [180, 9.0]] - * }) + * // is the same as * - * @param {Object} [arg] + * User.shere('age').equals(49); + * + * // is the same as + * + * User.where('age', 49); + * + * @param {Object} val * @return {Query} this * @api public */ -Query.prototype.intersects = function intersects () { - // opinionated, must be used after where - this._ensurePath('intersects'); - - this._geoComparison = '$geoIntersects'; - - if (0 === arguments.length) { - return this; - } - - var area = arguments[0]; - - if (null != area && area.type && area.coordinates) - return this.geometry(area); - - throw new TypeError('Invalid argument'); +Query.prototype.eq = function eq (val) { + this._ensurePath('eq'); + var path = this._path; + this._conditions[path] = val; + return this; } /** - * Specifies a `$geometry` condition + * Specifies arguments for an `$or` condition. * * ####Example * - * var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]] - * query.where('loc').within().geometry({ type: 'Polygon', coordinates: polyA }) + * query.or([{ color: 'red' }, { status: 'emergency' }]) * - * // or - * var polyB = [[ 0, 0 ], [ 1, 1 ]] - * query.where('loc').within().geometry({ type: 'LineString', coordinates: polyB }) - * - * // or - * var polyC = [ 0, 0 ] - * query.where('loc').within().geometry({ type: 'Point', coordinates: polyC }) - * - * // or - * query.where('loc').intersects().geometry({ type: 'Point', coordinates: polyC }) - * - * ####NOTE: - * - * `geometry()` **must** come after either `intersects()` or `within()`. - * - * The `object` argument must contain `type` and `coordinates` properties. - * - type {String} - * - coordinates {Array} - * - * The most recent path passed to `where()` is used. - * - * @param {Object} object Must contain a `type` property which is a String and a `coordinates` property which is an Array. See the examples. + * @param {Array} array array of conditions * @return {Query} this - * @see http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry - * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing - * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/ * @api public */ -Query.prototype.geometry = function geometry () { - if (!('$within' == this._geoComparison || - '$geoWithin' == this._geoComparison || - '$near' == this._geoComparison || - '$geoIntersects' == this._geoComparison)) { - throw new Error('geometry() must come after `within()`, `intersects()`, or `near()'); - } - - var val, path; - - if (1 === arguments.length) { - this._ensurePath('geometry'); - path = this._path; - val = arguments[0]; - } else { - throw new TypeError("Invalid argument"); - } - - if (!(val.type && Array.isArray(val.coordinates))) { - throw new TypeError('Invalid argument'); - } - - var conds = this._conditions[path] || (this._conditions[path] = {}); - conds[this._geoComparison] = { $geometry: val }; - +Query.prototype.or = function or (array) { + var or = this._conditions.$or || (this._conditions.$or = []); + if (!utils.isArray(array)) array = [array]; + or.push.apply(or, array); return this; } -// end spatial - /** - * Specifies which document fields to include or exclude - * - * ####String syntax - * - * When passing a string, prefixing a path with `-` will flag that path as excluded. When a path does not have the `-` prefix, it is included. + * Specifies arguments for a `$nor` condition. * * ####Example * - * // include a and b, exclude c - * query.select('a b -c'); - * - * // or you may use object notation, useful when - * // you have keys already prefixed with a "-" - * query.select({a: 1, b: 1, c: 0}); - * - * ####Note - * - * Cannot be used with `distinct()` + * query.nor([{ color: 'green' }, { status: 'ok' }]) * - * @param {Object|String} arg + * @param {Array} array array of conditions * @return {Query} this - * @see SchemaType * @api public */ -Query.prototype.select = function select () { - var arg = arguments[0]; - if (!arg) return this; - - if (arguments.length !== 1) { - throw new Error("Invalid select: select only takes 1 argument"); - } - - this._validate('select'); - - var fields = this._fields || (this._fields = {}); - var type = typeof arg; - - if (('string' == type || utils.isArgumentsObject(arg)) && - 'number' == typeof arg.length) { - if ('string' == type) - arg = arg.split(/\s+/); - - for (var i = 0, len = arg.length; i < len; ++i) { - var field = arg[i]; - if (!field) continue; - var include = '-' == field[0] ? 0 : 1; - if (include === 0) field = field.substring(1); - fields[field] = include; - } - - return this; - } - - if (utils.isObject(arg) && !Array.isArray(arg)) { - var keys = utils.keys(arg); - for (var i = 0; i < keys.length; ++i) { - fields[keys[i]] = arg[keys[i]]; - } - return this; - } - - throw new TypeError('Invalid select() argument. Must be string or object.'); +Query.prototype.nor = function nor (array) { + var nor = this._conditions.$nor || (this._conditions.$nor = []); + if (!utils.isArray(array)) array = [array]; + nor.push.apply(nor, array); + return this; } /** - * Specifies a $slice condition for a `path` + * Specifies arguments for a `$and` condition. * * ####Example * - * query.slice('comments', 5) - * query.slice('comments', -5) - * query.slice('comments', [10, 5]) - * query.where('comments').slice(5) - * query.where('comments').slice([-10, 5]) + * query.and([{ color: 'green' }, { status: 'ok' }]) * - * @param {String} [path] - * @param {Number} val number/range of elements to slice + * @see $and http://docs.mongodb.org/manual/reference/operator/and/ + * @param {Array} array array of conditions * @return {Query} this - * @see mongodb http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements * @api public */ -Query.prototype.slice = function () { - if (0 === arguments.length) - return this; - - this._validate('slice'); - - var path, val; - - if (1 === arguments.length) { - var arg = arguments[0]; - if (typeof arg === 'object' && !Array.isArray(arg)) { - var keys = Object.keys(arg); - var numKeys = keys.length; - for (var i = 0; i < numKeys; ++i) { - this.slice(keys[i], arg[keys[i]]); - } - return this; - } - this._ensurePath('slice'); - path = this._path; - val = arguments[0]; - } else if (2 === arguments.length) { - if ('number' === typeof arguments[0]) { - this._ensurePath('slice'); - path = this._path; - val = slice(arguments); - } else { - path = arguments[0]; - val = arguments[1]; - } - } else if (3 === arguments.length) { - path = arguments[0]; - val = slice(arguments, 1); - } - - var myFields = this._fields || (this._fields = {}); - myFields[path] = { '$slice': val }; +Query.prototype.and = function and (array) { + var and = this._conditions.$and || (this._conditions.$and = []); + if (!Array.isArray(array)) array = [array]; + and.push.apply(and, array); return this; } /** - * Sets the sort order - * - * If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1. + * Specifies a $gt query condition. * - * If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending. + * When called with one argument, the most recent path passed to `where()` is used. * * ####Example * - * // these are equivalent - * query.sort({ field: 'asc', test: -1 }); - * query.sort('field -test'); - * query.sort([['field', 1], ['test', -1]]); - * - * ####Note + * Thing.find().where('age').gt(21) * - * - The array syntax `.sort([['field', 1], ['test', -1]])` can only be used with [mongodb driver >= 2.0.46](https://github.com/mongodb/node-mongodb-native/blob/2.1/HISTORY.md#2046-2015-10-15). - * - Cannot be used with `distinct()` + * // or + * Thing.find().gt('age', 21) * - * @param {Object|String|Array} arg - * @return {Query} this + * @method gt + * @memberOf Query + * @param {String} [path] + * @param {Number} val * @api public */ -Query.prototype.sort = function (arg) { - if (!arg) return this; - var len; +/** + * Specifies a $gte query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @method gte + * @memberOf Query + * @param {String} [path] + * @param {Number} val + * @api public + */ - this._validate('sort'); +/** + * Specifies a $lt query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @method lt + * @memberOf Query + * @param {String} [path] + * @param {Number} val + * @api public + */ - var type = typeof arg; +/** + * Specifies a $lte query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @method lte + * @memberOf Query + * @param {String} [path] + * @param {Number} val + * @api public + */ - // .sort([['field', 1], ['test', -1]]) - if (Array.isArray(arg)) { - len = arg.length; - for (var i = 0; i < arg.length; ++i) { - _pushArr(this.options, arg[i][0], arg[i][1]); - } - return this; - } - - // .sort('field -test') - if (1 === arguments.length && 'string' == type) { - arg = arg.split(/\s+/); - len = arg.length; - for (var i = 0; i < len; ++i) { - var field = arg[i]; - if (!field) continue; - var ascend = '-' == field[0] ? -1 : 1; - if (ascend === -1) field = field.substring(1); - push(this.options, field, ascend); - } - - return this; - } - - // .sort({ field: 1, test: -1 }) - if (utils.isObject(arg)) { - var keys = utils.keys(arg); - for (var i = 0; i < keys.length; ++i) { - var field = keys[i]; - push(this.options, field, arg[field]); - } - - return this; - } - - throw new TypeError('Invalid sort() argument. Must be a string, object, or array.'); -} - -/*! - * @ignore - */ - -function push (opts, field, value) { - if (Array.isArray(opts.sort)) { - throw new TypeError("Can't mix sort syntaxes. Use either array or object:" + - "\n- `.sort([['field', 1], ['test', -1]])`" + - "\n- `.sort({ field: 1, test: -1 })`"); - } - - if (value && value.$meta) { - var s = opts.sort || (opts.sort = {}); - s[field] = { $meta : value.$meta }; - return; - } - - var val = String(value || 1).toLowerCase(); - if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) { - if (utils.isArray(value)) value = '['+value+']'; - throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }'); - } - // store `sort` in a sane format - var s = opts.sort || (opts.sort = {}); - var valueStr = value.toString() - .replace("asc", "1") - .replace("ascending", "1") - .replace("desc", "-1") - .replace("descending", "-1"); - s[field] = parseInt(valueStr, 10); -} - -function _pushArr (opts, field, value) { - opts.sort = opts.sort || []; - if (!Array.isArray(opts.sort)) { - throw new TypeError("Can't mix sort syntaxes. Use either array or object:" + - "\n- `.sort([['field', 1], ['test', -1]])`" + - "\n- `.sort({ field: 1, test: -1 })`"); - } - var valueStr = value.toString() - .replace("asc", "1") - .replace("ascending", "1") - .replace("desc", "-1") - .replace("descending", "-1"); - opts.sort.push([field, value]); -} +/** + * Specifies a $ne query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @method ne + * @memberOf Query + * @param {String} [path] + * @param {Number} val + * @api public + */ /** - * Specifies the limit option. - * - * ####Example - * - * query.limit(20) - * - * ####Note + * Specifies an $in query condition. * - * Cannot be used with `distinct()` + * When called with one argument, the most recent path passed to `where()` is used. * - * @method limit + * @method in * @memberOf Query + * @param {String} [path] * @param {Number} val - * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D * @api public */ + /** - * Specifies the skip option. - * - * ####Example - * - * query.skip(100).limit(20) - * - * ####Note + * Specifies an $nin query condition. * - * Cannot be used with `distinct()` + * When called with one argument, the most recent path passed to `where()` is used. * - * @method skip + * @method nin * @memberOf Query + * @param {String} [path] * @param {Number} val - * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D * @api public */ + /** - * Specifies the maxScan option. - * - * ####Example - * - * query.maxScan(100) - * - * ####Note + * Specifies an $all query condition. * - * Cannot be used with `distinct()` + * When called with one argument, the most recent path passed to `where()` is used. * - * @method maxScan + * @method all * @memberOf Query + * @param {String} [path] * @param {Number} val - * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan * @api public */ + /** - * Specifies the batchSize option. - * - * ####Example - * - * query.batchSize(100) - * - * ####Note + * Specifies a $size query condition. * - * Cannot be used with `distinct()` + * When called with one argument, the most recent path passed to `where()` is used. * - * @method batchSize + * @method size * @memberOf Query + * @param {String} [path] * @param {Number} val - * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D * @api public */ + /** - * Specifies the `comment` option. - * - * ####Example + * Specifies a $regex query condition. * - * query.comment('login query') + * When called with one argument, the most recent path passed to `where()` is used. * - * ####Note + * @method regex + * @memberOf Query + * @param {String} [path] + * @param {Number} val + * @api public + */ + +/** + * Specifies a $maxDistance query condition. * - * Cannot be used with `distinct()` + * When called with one argument, the most recent path passed to `where()` is used. * - * @method comment + * @method maxDistance * @memberOf Query + * @param {String} [path] * @param {Number} val - * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment * @api public */ /*! - * limit, skip, maxScan, batchSize, comment - * - * Sets these associated options. + * gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance * - * query.comment('feed query'); + * Thing.where('type').nin(array) */ -;['limit', 'skip', 'maxScan', 'batchSize', 'comment'].forEach(function (method) { - Query.prototype[method] = function (v) { - this._validate(method); - this.options[method] = v; +'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) { + Query.prototype[$conditional] = function () { + var path, val; + + if (1 === arguments.length) { + this._ensurePath($conditional); + val = arguments[0]; + path = this._path; + } else { + val = arguments[1]; + path = arguments[0]; + } + + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds['$' + $conditional] = val; return this; }; }) /** - * Specifies the maxTimeMS option. - * - * ####Example - * - * query.maxTime(100) + * Specifies a `$mod` condition * - * @method maxTime - * @memberOf Query + * @param {String} [path] * @param {Number} val - * @see mongodb http://docs.mongodb.org/manual/reference/operator/meta/maxTimeMS/#op._S_maxTimeMS - * @api public - */ - -Query.prototype.maxTime = function (v) { - this._validate('maxTime'); - this.options.maxTimeMS = v; - return this; -}; - -/** - * Specifies this query as a `snapshot` query. - * - * ####Example - * - * mquery().snapshot() // true - * mquery().snapshot(true) - * mquery().snapshot(false) - * - * ####Note - * - * Cannot be used with `distinct()` - * - * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D * @return {Query} this * @api public */ -Query.prototype.snapshot = function () { - this._validate('snapshot'); +Query.prototype.mod = function () { + var val, path; - this.options.snapshot = arguments.length - ? !! arguments[0] - : true + if (1 === arguments.length) { + this._ensurePath('mod') + val = arguments[0]; + path = this._path; + } else if (2 === arguments.length && !utils.isArray(arguments[1])) { + this._ensurePath('mod') + val = slice(arguments); + path = this._path; + } else if (3 === arguments.length) { + val = slice(arguments, 1); + path = arguments[0]; + } else { + val = arguments[1]; + path = arguments[0]; + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds.$mod = val; return this; } /** - * Sets query hints. + * Specifies an `$exists` condition * * ####Example * - * query.hint({ indexA: 1, indexB: -1}) - * - * ####Note + * // { name: { $exists: true }} + * Thing.where('name').exists() + * Thing.where('name').exists(true) + * Thing.find().exists('name') * - * Cannot be used with `distinct()` + * // { name: { $exists: false }} + * Thing.where('name').exists(false); + * Thing.find().exists('name', false); * - * @param {Object} val a hint object + * @param {String} [path] + * @param {Number} val * @return {Query} this - * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint * @api public */ -Query.prototype.hint = function () { - if (0 === arguments.length) return this; - - this._validate('hint'); - - var arg = arguments[0]; - if (utils.isObject(arg)) { - var hint = this.options.hint || (this.options.hint = {}); +Query.prototype.exists = function () { + var path, val; - // must keep object keys in order so don't use Object.keys() - for (var k in arg) { - hint[k] = arg[k]; + if (0 === arguments.length) { + this._ensurePath('exists'); + path = this._path; + val = true; + } else if (1 === arguments.length) { + if ('boolean' === typeof arguments[0]) { + this._ensurePath('exists'); + path = this._path; + val = arguments[0]; + } else { + path = arguments[0]; + val = true; } - - return this; + } else if (2 === arguments.length) { + path = arguments[0]; + val = arguments[1]; } - throw new TypeError('Invalid hint. ' + arg); -} - -/** - * Sets the slaveOk option. _Deprecated_ in MongoDB 2.2 in favor of read preferences. - * - * ####Example: - * - * query.slaveOk() // true - * query.slaveOk(true) - * query.slaveOk(false) - * - * @deprecated use read() preferences instead if on mongodb >= 2.2 - * @param {Boolean} v defaults to true - * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference - * @see read() - * @return {Query} this - * @api public - */ - -Query.prototype.slaveOk = function (v) { - this.options.slaveOk = arguments.length ? !!v : true; + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds.$exists = val; return this; } /** - * Sets the readPreference option for the query. - * - * ####Example: - * - * new Query().read('primary') - * new Query().read('p') // same as primary - * - * new Query().read('primaryPreferred') - * new Query().read('pp') // same as primaryPreferred - * - * new Query().read('secondary') - * new Query().read('s') // same as secondary - * - * new Query().read('secondaryPreferred') - * new Query().read('sp') // same as secondaryPreferred - * - * new Query().read('nearest') - * new Query().read('n') // same as nearest - * - * // you can also use mongodb.ReadPreference class to also specify tags - * new Query().read(mongodb.ReadPreference('secondary', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])) + * Specifies an `$elemMatch` condition * - * ####Preferences: + * ####Example * - * primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags. - * secondary Read from secondary if available, otherwise error. - * primaryPreferred Read from primary if available, otherwise a secondary. - * secondaryPreferred Read from a secondary if available, otherwise read from the primary. - * nearest All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection. + * query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}}) * - * Aliases + * query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}}) * - * p primary - * pp primaryPreferred - * s secondary - * sp secondaryPreferred - * n nearest + * query.elemMatch('comment', function (elem) { + * elem.where('author').equals('autobot'); + * elem.where('votes').gte(5); + * }) * - * Read more about how to use read preferences [here](http://docs.mongodb.org/manual/applications/replication/#read-preference) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences). + * query.where('comment').elemMatch(function (elem) { + * elem.where({ author: 'autobot' }); + * elem.where('votes').gte(5); + * }) * - * @param {String|ReadPreference} pref one of the listed preference options or their aliases - * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference - * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences + * @param {String|Object|Function} path + * @param {Object|Function} criteria * @return {Query} this * @api public */ -Query.prototype.read = function (pref) { - if (arguments.length > 1 && !Query.prototype.read.deprecationWarningIssued) { - console.error("Deprecation warning: 'tags' argument is not supported anymore in Query.read() method. Please use mongodb.ReadPreference object instead."); - Query.prototype.read.deprecationWarningIssued = true; +Query.prototype.elemMatch = function () { + if (null == arguments[0]) + throw new TypeError("Invalid argument"); + + var fn, path, criteria; + + if ('function' === typeof arguments[0]) { + this._ensurePath('elemMatch'); + path = this._path; + fn = arguments[0]; + } else if (utils.isObject(arguments[0])) { + this._ensurePath('elemMatch'); + path = this._path; + criteria = arguments[0]; + } else if ('function' === typeof arguments[1]) { + path = arguments[0]; + fn = arguments[1]; + } else if (arguments[1] && utils.isObject(arguments[1])) { + path = arguments[0]; + criteria = arguments[1]; + } else { + throw new TypeError("Invalid argument"); } - this.options.readPreference = utils.readPref(pref); + + if (fn) { + criteria = new Query; + fn(criteria); + criteria = criteria._conditions; + } + + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds.$elemMatch = criteria; return this; } +// Spatial queries + /** - * Sets tailable option. + * Sugar for geo-spatial queries. * * ####Example * - * query.tailable() <== true - * query.tailable(true) - * query.tailable(false) + * query.within().box() + * query.within().circle() + * query.within().geometry() * - * ####Note + * query.where('loc').within({ center: [50,50], radius: 10, unique: true, spherical: true }); + * query.where('loc').within({ box: [[40.73, -73.9], [40.7, -73.988]] }); + * query.where('loc').within({ polygon: [[],[],[],[]] }); * - * Cannot be used with `distinct()` + * query.where('loc').within([], [], []) // polygon + * query.where('loc').within([], []) // box + * query.where('loc').within({ type: 'LineString', coordinates: [...] }); // geometry * - * @param {Boolean} v defaults to true - * @see mongodb http://www.mongodb.org/display/DOCS/Tailable+Cursors - * @api public - */ - -Query.prototype.tailable = function () { - this._validate('tailable'); - - this.options.tailable = arguments.length - ? !! arguments[0] - : true; - - return this; -} - -/** - * Merges another Query or conditions object into this one. + * ####NOTE: * - * When a Query is passed, conditions, field selection and options are merged. + * Must be used after `where()`. * - * @param {Query|Object} source + * @memberOf Query * @return {Query} this + * @api public */ -Query.prototype.merge = function (source) { - if (!source) - return this; - - if (!Query.canMerge(source)) - throw new TypeError('Invalid argument. Expected instanceof mquery or plain object'); +Query.prototype.within = function within () { + // opinionated, must be used after where + this._ensurePath('within'); + this._geoComparison = $withinCmd; - if (source instanceof Query) { - // if source has a feature, apply it to ourselves + if (0 === arguments.length) { + return this; + } - if (source._conditions) { - utils.merge(this._conditions, source._conditions); - } + if (2 === arguments.length) { + return this.box.apply(this, arguments); + } else if (2 < arguments.length) { + return this.polygon.apply(this, arguments); + } - if (source._fields) { - this._fields || (this._fields = {}); - utils.merge(this._fields, source._fields); - } + var area = arguments[0]; - if (source.options) { - this.options || (this.options = {}); - utils.merge(this.options, source.options); - } + if (!area) + throw new TypeError('Invalid argument'); - if (source._update) { - this._update || (this._update = {}); - utils.mergeClone(this._update, source._update); - } + if (area.center) + return this.circle(area); - if (source._distinct) { - this._distinct = source._distinct; - } + if (area.box) + return this.box.apply(this, area.box); - return this; - } + if (area.polygon) + return this.polygon.apply(this, area.polygon); - // plain object - utils.merge(this._conditions, source); + if (area.type && area.coordinates) + return this.geometry(area); - return this; + throw new TypeError('Invalid argument'); } /** - * Finds documents. - * - * Passing a `callback` executes the query. + * Specifies a $box condition * * ####Example * - * query.find() - * query.find(callback) - * query.find({ name: 'Burning Lights' }, callback) + * var lowerLeft = [40.73083, -73.99756] + * var upperRight= [40.741404, -73.988135] * - * @param {Object} [criteria] mongodb selector - * @param {Function} [callback] + * query.where('loc').within().box(lowerLeft, upperRight) + * query.box('loc', lowerLeft, upperRight ) + * + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @see Query#within #query_Query-within + * @param {String} path + * @param {Object} val * @return {Query} this * @api public */ -Query.prototype.find = function (criteria, callback) { - this.op = 'find'; +Query.prototype.box = function () { + var path, box; - if ('function' === typeof criteria) { - callback = criteria; - criteria = undefined; - } else if (Query.canMerge(criteria)) { - this.merge(criteria); + if (3 === arguments.length) { + // box('loc', [], []) + path = arguments[0]; + box = [arguments[1], arguments[2]]; + } else if (2 === arguments.length) { + // box([], []) + this._ensurePath('box'); + path = this._path; + box = [arguments[0], arguments[1]]; + } else { + throw new TypeError("Invalid argument"); } - if (!callback) return this; - - var self = this - , conds = this._conditions - , options = this._optionsForExec() - - options.fields = this._fieldsForExec() - - debug('find', this._collection.collectionName, conds, options); - callback = this._wrapCallback('find', callback, { - conditions: conds - , options: options - }); - - this._collection.find(conds, options, utils.tick(callback)); + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds[this._geoComparison || $withinCmd] = { '$box': box }; return this; } /** - * Returns the query cursor + * Specifies a $polygon condition * - * ####Examples + * ####Example * - * query.find().cursor(); - * query.cursor({ name: 'Burning Lights' }); + * query.where('loc').within().polygon([10,20], [13, 25], [7,15]) + * query.polygon('loc', [10,20], [13, 25], [7,15]) * - * @param {Object} [criteria] mongodb selector - * @return {Object} cursor + * @param {String|Array} [path] + * @param {Array|Object} [val] + * @return {Query} this + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing * @api public */ -Query.prototype.cursor = function cursor (criteria) { - if (this.op) { - if (this.op !== 'find') { - throw new TypeError(".cursor only support .find method"); - } +Query.prototype.polygon = function () { + var val, path; + + if ('string' == typeof arguments[0]) { + // polygon('loc', [],[],[]) + path = arguments[0]; + val = slice(arguments, 1); } else { - this.find(criteria); + // polygon([],[],[]) + this._ensurePath('polygon'); + path = this._path; + val = slice(arguments); } - var conds = this._conditions - , options = this._optionsForExec() - - options.fields = this._fieldsForExec() - - debug('findCursor', this._collection.collectionName, conds, options); - return this._collection.findCursor(conds, options); + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds[this._geoComparison || $withinCmd] = { '$polygon': val }; + return this; } /** - * Executes the query as a findOne() operation. - * - * Passing a `callback` executes the query. + * Specifies a $center or $centerSphere condition. * * ####Example * - * query.findOne().where('name', /^Burning/); - * - * query.findOne({ name: /^Burning/ }) - * - * query.findOne({ name: /^Burning/ }, callback); // executes - * - * query.findOne(function (err, doc) { - * if (err) return handleError(err); - * if (doc) { - * // doc may be null if no document matched + * var area = { center: [50, 50], radius: 10, unique: true } + * query.where('loc').within().circle(area) + * query.center('loc', area); * - * } - * }); + * // for spherical calculations + * var area = { center: [50, 50], radius: 10, unique: true, spherical: true } + * query.where('loc').within().circle(area) + * query.center('loc', area); * - * @param {Object|Query} [criteria] mongodb selector - * @param {Function} [callback] + * @param {String} [path] + * @param {Object} area * @return {Query} this + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing * @api public */ -Query.prototype.findOne = function (criteria, callback) { - this.op = 'findOne'; +Query.prototype.circle = function () { + var path, val; - if ('function' === typeof criteria) { - callback = criteria; - criteria = undefined; - } else if (Query.canMerge(criteria)) { - this.merge(criteria); + if (1 === arguments.length) { + this._ensurePath('circle'); + path = this._path; + val = arguments[0]; + } else if (2 === arguments.length) { + path = arguments[0]; + val = arguments[1]; + } else { + throw new TypeError("Invalid argument"); } - if (!callback) return this; + if (!('radius' in val && val.center)) + throw new Error('center and radius are required'); - var self = this - , conds = this._conditions - , options = this._optionsForExec() + var conds = this._conditions[path] || (this._conditions[path] = {}); - options.fields = this._fieldsForExec(); + var type = val.spherical + ? '$centerSphere' + : '$center'; - debug('findOne', this._collection.collectionName, conds, options); - callback = this._wrapCallback('findOne', callback, { - conditions: conds - , options: options - }); + var wKey = this._geoComparison || $withinCmd; + conds[wKey] = {}; + conds[wKey][type] = [val.center, val.radius]; - this._collection.findOne(conds, options, utils.tick(callback)); + if ('unique' in val) + conds[wKey].$uniqueDocs = !! val.unique; return this; } /** - * Exectues the query as a count() operation. + * Specifies a `$near` or `$nearSphere` condition * - * Passing a `callback` executes the query. + * These operators return documents sorted by distance. * * ####Example * - * query.count().where('color', 'black').exec(callback); - * - * query.count({ color: 'black' }).count(callback) - * - * query.count({ color: 'black' }, callback) - * - * query.where('color', 'black').count(function (err, count) { - * if (err) return handleError(err); - * console.log('there are %d kittens', count); - * }) + * query.where('loc').near({ center: [10, 10] }); + * query.where('loc').near({ center: [10, 10], maxDistance: 5 }); + * query.where('loc').near({ center: [10, 10], maxDistance: 5, spherical: true }); + * query.near('loc', { center: [10, 10], maxDistance: 5 }); + * query.near({ center: { type: 'Point', coordinates: [..] }}) + * query.near().geometry({ type: 'Point', coordinates: [..] }) * - * @param {Object} [criteria] mongodb selector - * @param {Function} [callback] + * @param {String} [path] + * @param {Object} val * @return {Query} this - * @see mongodb http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing * @api public */ -Query.prototype.count = function (criteria, callback) { - this.op = 'count'; - this._validate(); +Query.prototype.near = function near () { + var path, val; - if ('function' === typeof criteria) { - callback = criteria; - criteria = undefined; - } else if (Query.canMerge(criteria)) { - this.merge(criteria); + this._geoComparison = '$near'; + + if (0 === arguments.length) { + return this; + } else if (1 === arguments.length) { + this._ensurePath('near'); + path = this._path; + val = arguments[0]; + } else if (2 === arguments.length) { + path = arguments[0]; + val = arguments[1]; + } else { + throw new TypeError("Invalid argument"); } - if (!callback) return this; + if (!val.center) { + throw new Error('center is required'); + } - var conds = this._conditions - , options = this._optionsForExec() + var conds = this._conditions[path] || (this._conditions[path] = {}); - debug('count', this._collection.collectionName, conds, options); - callback = this._wrapCallback('count', callback, { - conditions: conds - , options: options - }); + var type = val.spherical + ? '$nearSphere' + : '$near'; + + // center could be a GeoJSON object or an Array + if (Array.isArray(val.center)) { + conds[type] = val.center; + + var radius = 'maxDistance' in val + ? val.maxDistance + : null; + + if (null != radius) { + conds.$maxDistance = radius; + } + } else { + // GeoJSON? + if (val.center.type != 'Point' || !Array.isArray(val.center.coordinates)) { + throw new Error(util.format("Invalid GeoJSON specified for %s", type)); + } + conds[type] = { $geometry : val.center }; + + // MongoDB 2.6 insists on maxDistance being in $near / $nearSphere + if ('maxDistance' in val) { + conds[type]['$maxDistance'] = val.maxDistance; + } + } - this._collection.count(conds, options, utils.tick(callback)); return this; } /** - * Declares or executes a distinct() operation. - * - * Passing a `callback` executes the query. + * Declares an intersects query for `geometry()`. * * ####Example * - * distinct(criteria, field, fn) - * distinct(criteria, field) - * distinct(field, fn) - * distinct(field) - * distinct(fn) - * distinct() + * query.where('path').intersects().geometry({ + * type: 'LineString' + * , coordinates: [[180.0, 11.0], [180, 9.0]] + * }) * - * @param {Object|Query} [criteria] - * @param {String} [field] - * @param {Function} [callback] + * query.where('path').intersects({ + * type: 'LineString' + * , coordinates: [[180.0, 11.0], [180, 9.0]] + * }) + * + * @param {Object} [arg] * @return {Query} this - * @see mongodb http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct * @api public */ -Query.prototype.distinct = function (criteria, field, callback) { - this.op = 'distinct'; - this._validate(); - - if (!callback) { - switch (typeof field) { - case 'function': - callback = field; - if ('string' == typeof criteria) { - field = criteria; - criteria = undefined; - } - break; - case 'undefined': - case 'string': - break; - default: - throw new TypeError('Invalid `field` argument. Must be string or function') - break; - } - - switch (typeof criteria) { - case 'function': - callback = criteria; - criteria = field = undefined; - break; - case 'string': - field = criteria; - criteria = undefined; - break; - } - } - - if ('string' == typeof field) { - this._distinct = field; - } +Query.prototype.intersects = function intersects () { + // opinionated, must be used after where + this._ensurePath('intersects'); - if (Query.canMerge(criteria)) { - this.merge(criteria); - } + this._geoComparison = '$geoIntersects'; - if (!callback) { + if (0 === arguments.length) { return this; } - if (!this._distinct) { - throw new Error('No value for `distinct` has been declared'); - } - - var conds = this._conditions - , options = this._optionsForExec() - - debug('distinct', this._collection.collectionName, conds, options); - callback = this._wrapCallback('distinct', callback, { - conditions: conds - , options: options - }); + var area = arguments[0]; - this._collection.distinct(this._distinct, conds, options, utils.tick(callback)); + if (null != area && area.type && area.coordinates) + return this.geometry(area); - return this; + throw new TypeError('Invalid argument'); } /** - * Declare and/or execute this query as an update() operation. - * - * _All paths passed that are not $atomic operations will become $set ops._ + * Specifies a `$geometry` condition * * ####Example * - * mquery({ _id: id }).update({ title: 'words' }, ...) - * - * becomes - * - * collection.update({ _id: id }, { $set: { title: 'words' }}, ...) - * - * ####Note - * - * Passing an empty object `{}` as the doc will result in a no-op unless the `overwrite` option is passed. Without the `overwrite` option set, the update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting documents in the collection. - * - * ####Note - * - * The operation is only executed when a callback is passed. To force execution without a callback (which would be an unsafe write), we must first call update() and then execute it by using the `exec()` method. - * - * var q = mquery(collection).where({ _id: id }); - * q.update({ $set: { name: 'bob' }}).update(); // not executed - * - * var q = mquery(collection).where({ _id: id }); - * q.update({ $set: { name: 'bob' }}).exec(); // executed as unsafe + * var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]] + * query.where('loc').within().geometry({ type: 'Polygon', coordinates: polyA }) * - * // keys that are not $atomic ops become $set. - * // this executes the same command as the previous example. - * q.update({ name: 'bob' }).where({ _id: id }).exec(); + * // or + * var polyB = [[ 0, 0 ], [ 1, 1 ]] + * query.where('loc').within().geometry({ type: 'LineString', coordinates: polyB }) * - * var q = mquery(collection).update(); // not executed + * // or + * var polyC = [ 0, 0 ] + * query.where('loc').within().geometry({ type: 'Point', coordinates: polyC }) * - * // overwriting with empty docs - * var q.where({ _id: id }).setOptions({ overwrite: true }) - * q.update({ }, callback); // executes + * // or + * query.where('loc').intersects().geometry({ type: 'Point', coordinates: polyC }) * - * // multi update with overwrite to empty doc - * var q = mquery(collection).where({ _id: id }); - * q.setOptions({ multi: true, overwrite: true }) - * q.update({ }); - * q.update(callback); // executed + * ####NOTE: * - * // multi updates - * mquery() - * .collection(coll) - * .update({ name: /^match/ }, { $set: { arr: [] }}, { multi: true }, callback) - * // more multi updates - * mquery({ }) - * .collection(coll) - * .setOptions({ multi: true }) - * .update({ $set: { arr: [] }}, callback) + * `geometry()` **must** come after either `intersects()` or `within()`. * - * // single update by default - * mquery({ email: 'address@example.com' }) - * .collection(coll) - * .update({ $inc: { counter: 1 }}, callback) + * The `object` argument must contain `type` and `coordinates` properties. + * - type {String} + * - coordinates {Array} * - * // summary - * update(criteria, doc, opts, cb) // executes - * update(criteria, doc, opts) - * update(criteria, doc, cb) // executes - * update(criteria, doc) - * update(doc, cb) // executes - * update(doc) - * update(cb) // executes - * update(true) // executes (unsafe write) - * update() + * The most recent path passed to `where()` is used. * - * @param {Object} [criteria] - * @param {Object} [doc] the update command - * @param {Object} [options] - * @param {Function} [callback] + * @param {Object} object Must contain a `type` property which is a String and a `coordinates` property which is an Array. See the examples. * @return {Query} this + * @see http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/ * @api public */ -Query.prototype.update = function update (criteria, doc, options, callback) { - this.op = 'update'; - var force; - - switch (arguments.length) { - case 3: - if ('function' == typeof options) { - callback = options; - options = undefined; - } - break; - case 2: - if ('function' == typeof doc) { - callback = doc; - doc = criteria; - criteria = undefined; - } - break; - case 1: - switch (typeof criteria) { - case 'function': - callback = criteria; - criteria = options = doc = undefined; - break; - case 'boolean': - // execution with no callback (unsafe write) - force = criteria; - criteria = undefined; - break; - default: - doc = criteria; - criteria = options = undefined; - break; - } - } - - if (Query.canMerge(criteria)) { - this.merge(criteria); +Query.prototype.geometry = function geometry () { + if (!('$within' == this._geoComparison || + '$geoWithin' == this._geoComparison || + '$near' == this._geoComparison || + '$geoIntersects' == this._geoComparison)) { + throw new Error('geometry() must come after `within()`, `intersects()`, or `near()'); } - if (doc) { - this._mergeUpdate(doc); - } + var val, path; - if (utils.isObject(options)) { - // { overwrite: true } - this.setOptions(options); + if (1 === arguments.length) { + this._ensurePath('geometry'); + path = this._path; + val = arguments[0]; + } else { + throw new TypeError("Invalid argument"); } - // we are done if we don't have callback and they are - // not forcing an unsafe write. - if (!(force || callback)) - return this; - - if (!this._update || - !this.options.overwrite && 0 === utils.keys(this._update).length) { - callback && utils.soon(callback.bind(null, null, 0)); - return this; + if (!(val.type && Array.isArray(val.coordinates))) { + throw new TypeError('Invalid argument'); } - options = this._optionsForExec(); - if (!callback) options.safe = false; - - var criteria = this._conditions; - doc = this._updateForExec(); - - debug('update', this._collection.collectionName, criteria, doc, options); - callback = this._wrapCallback('update', callback, { - conditions: criteria - , doc: doc - , options: options - }); - - this._collection.update(criteria, doc, options, utils.tick(callback)); + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds[this._geoComparison] = { $geometry: val }; return this; } +// end spatial + /** - * Declare and/or execute this query as a remove() operation. + * Specifies which document fields to include or exclude * - * ####Example + * ####String syntax * - * mquery(collection).remove({ artist: 'Anne Murray' }, callback) + * When passing a string, prefixing a path with `-` will flag that path as excluded. When a path does not have the `-` prefix, it is included. * - * ####Note + * ####Example * - * The operation is only executed when a callback is passed. To force execution without a callback (which would be an unsafe write), we must first call remove() and then execute it by using the `exec()` method. + * // include a and b, exclude c + * query.select('a b -c'); * - * // not executed - * var query = mquery(collection).remove({ name: 'Anne Murray' }) + * // or you may use object notation, useful when + * // you have keys already prefixed with a "-" + * query.select({a: 1, b: 1, c: 0}); * - * // executed - * mquery(collection).remove({ name: 'Anne Murray' }, callback) - * mquery(collection).remove({ name: 'Anne Murray' }).remove(callback) + * ####Note * - * // executed without a callback (unsafe write) - * query.exec() + * Cannot be used with `distinct()` * - * // summary - * query.remove(conds, fn); // executes - * query.remove(conds) - * query.remove(fn) // executes - * query.remove() - * - * @param {Object|Query} [criteria] mongodb selector - * @param {Function} [callback] + * @param {Object|String} arg * @return {Query} this + * @see SchemaType * @api public */ -Query.prototype.remove = function (criteria, callback) { - this.op = 'remove'; - var force; +Query.prototype.select = function select () { + var arg = arguments[0]; + if (!arg) return this; - if ('function' === typeof criteria) { - callback = criteria; - criteria = undefined; - } else if (Query.canMerge(criteria)) { - this.merge(criteria); - } else if (true === criteria) { - force = criteria; - criteria = undefined; + if (arguments.length !== 1) { + throw new Error("Invalid select: select only takes 1 argument"); } - if (!(force || callback)) - return this; + this._validate('select'); - var options = this._optionsForExec() - if (!callback) options.safe = false; + var fields = this._fields || (this._fields = {}); + var type = typeof arg; - var conds = this._conditions; + if (('string' == type || utils.isArgumentsObject(arg)) && + 'number' == typeof arg.length) { + if ('string' == type) + arg = arg.split(/\s+/); - debug('remove', this._collection.collectionName, conds, options); - callback = this._wrapCallback('remove', callback, { - conditions: conds - , options: options - }); + for (var i = 0, len = arg.length; i < len; ++i) { + var field = arg[i]; + if (!field) continue; + var include = '-' == field[0] ? 0 : 1; + if (include === 0) field = field.substring(1); + fields[field] = include; + } - this._collection.remove(conds, options, utils.tick(callback)); + return this; + } - return this; + if (utils.isObject(arg) && !Array.isArray(arg)) { + var keys = utils.keys(arg); + for (var i = 0; i < keys.length; ++i) { + fields[keys[i]] = arg[keys[i]]; + } + return this; + } + + throw new TypeError('Invalid select() argument. Must be string or object.'); } /** - * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) update command. - * - * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed. - * - * ####Available options - * - * - `new`: bool - true to return the modified document rather than the original. defaults to true - * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. - * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * Specifies a $slice condition for a `path` * - * ####Examples + * ####Example * - * query.findOneAndUpdate(conditions, update, options, callback) // executes - * query.findOneAndUpdate(conditions, update, options) // returns Query - * query.findOneAndUpdate(conditions, update, callback) // executes - * query.findOneAndUpdate(conditions, update) // returns Query - * query.findOneAndUpdate(update, callback) // returns Query - * query.findOneAndUpdate(update) // returns Query - * query.findOneAndUpdate(callback) // executes - * query.findOneAndUpdate() // returns Query + * query.slice('comments', 5) + * query.slice('comments', -5) + * query.slice('comments', [10, 5]) + * query.where('comments').slice(5) + * query.where('comments').slice([-10, 5]) * - * @param {Object|Query} [query] - * @param {Object} [doc] - * @param {Object} [options] - * @param {Function} [callback] - * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + * @param {String} [path] + * @param {Number} val number/range of elements to slice * @return {Query} this + * @see mongodb http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements * @api public */ -Query.prototype.findOneAndUpdate = function (criteria, doc, options, callback) { - this.op = 'findOneAndUpdate'; - this._validate(); +Query.prototype.slice = function () { + if (0 === arguments.length) + return this; - switch (arguments.length) { - case 3: - if ('function' == typeof options) { - callback = options; - options = {}; - } - break; - case 2: - if ('function' == typeof doc) { - callback = doc; - doc = criteria; - criteria = undefined; - } - options = undefined; - break; - case 1: - if ('function' == typeof criteria) { - callback = criteria; - criteria = options = doc = undefined; - } else { - doc = criteria; - criteria = options = undefined; - } - } + this._validate('slice'); - if (Query.canMerge(criteria)) { - this.merge(criteria); - } + var path, val; - // apply doc - if (doc) { - this._mergeUpdate(doc); + if (1 === arguments.length) { + var arg = arguments[0]; + if (typeof arg === 'object' && !Array.isArray(arg)) { + var keys = Object.keys(arg); + var numKeys = keys.length; + for (var i = 0; i < numKeys; ++i) { + this.slice(keys[i], arg[keys[i]]); + } + return this; + } + this._ensurePath('slice'); + path = this._path; + val = arguments[0]; + } else if (2 === arguments.length) { + if ('number' === typeof arguments[0]) { + this._ensurePath('slice'); + path = this._path; + val = slice(arguments); + } else { + path = arguments[0]; + val = arguments[1]; + } + } else if (3 === arguments.length) { + path = arguments[0]; + val = slice(arguments, 1); } - options && this.setOptions(options); - - if (!callback) return this; - return this._findAndModify('update', callback); + var myFields = this._fields || (this._fields = {}); + myFields[path] = { '$slice': val }; + return this; } /** - * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) remove command. + * Sets the sort order * - * Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if `callback` is passed. + * If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1. * - * ####Available options + * If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending. * - * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * ####Example * - * ####Examples + * // these are equivalent + * query.sort({ field: 'asc', test: -1 }); + * query.sort('field -test'); + * query.sort([['field', 1], ['test', -1]]); * - * A.where().findOneAndRemove(conditions, options, callback) // executes - * A.where().findOneAndRemove(conditions, options) // return Query - * A.where().findOneAndRemove(conditions, callback) // executes - * A.where().findOneAndRemove(conditions) // returns Query - * A.where().findOneAndRemove(callback) // executes - * A.where().findOneAndRemove() // returns Query + * ####Note * - * @param {Object} [conditions] - * @param {Object} [options] - * @param {Function} [callback] + * - The array syntax `.sort([['field', 1], ['test', -1]])` can only be used with [mongodb driver >= 2.0.46](https://github.com/mongodb/node-mongodb-native/blob/2.1/HISTORY.md#2046-2015-10-15). + * - Cannot be used with `distinct()` + * + * @param {Object|String|Array} arg * @return {Query} this - * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command * @api public */ -Query.prototype.findOneAndRemove = function (conditions, options, callback) { - this.op = 'findOneAndRemove'; - this._validate(); +Query.prototype.sort = function (arg) { + if (!arg) return this; + var len; - if ('function' == typeof options) { - callback = options; - options = undefined; - } else if ('function' == typeof conditions) { - callback = conditions; - conditions = undefined; + this._validate('sort'); + + var type = typeof arg; + + // .sort([['field', 1], ['test', -1]]) + if (Array.isArray(arg)) { + len = arg.length; + for (var i = 0; i < arg.length; ++i) { + _pushArr(this.options, arg[i][0], arg[i][1]); + } + return this; } - // apply conditions - if (Query.canMerge(conditions)) { - this.merge(conditions); + // .sort('field -test') + if (1 === arguments.length && 'string' == type) { + arg = arg.split(/\s+/); + len = arg.length; + for (var i = 0; i < len; ++i) { + var field = arg[i]; + if (!field) continue; + var ascend = '-' == field[0] ? -1 : 1; + if (ascend === -1) field = field.substring(1); + push(this.options, field, ascend); + } + + return this; } - // apply options - options && this.setOptions(options); + // .sort({ field: 1, test: -1 }) + if (utils.isObject(arg)) { + var keys = utils.keys(arg); + for (var i = 0; i < keys.length; ++i) { + var field = keys[i]; + push(this.options, field, arg[field]); + } - if (!callback) return this; + return this; + } - return this._findAndModify('remove', callback); + throw new TypeError('Invalid sort() argument. Must be a string, object, or array.'); } -/** - * _findAndModify - * - * @param {String} type - either "remove" or "update" - * @param {Function} callback - * @api private +/*! + * @ignore */ -Query.prototype._findAndModify = function (type, callback) { - assert.equal('function', typeof callback); - - var opts = this._optionsForExec() - , self = this - , fields - , sort - , doc - - if ('remove' == type) { - opts.remove = true; - } else { - if (!('new' in opts)) opts.new = true; - if (!('upsert' in opts)) opts.upsert = false; - - doc = this._updateForExec() - if (!doc) { - if (opts.upsert) { - // still need to do the upsert to empty doc - doc = { $set: {} }; - } else { - return this.findOne(callback); - } - } +function push (opts, field, value) { + if (Array.isArray(opts.sort)) { + throw new TypeError("Can't mix sort syntaxes. Use either array or object:" + + "\n- `.sort([['field', 1], ['test', -1]])`" + + "\n- `.sort({ field: 1, test: -1 })`"); } - var fields = this._fieldsForExec(); - if (fields) { - opts.fields = fields; + if (value && value.$meta) { + var s = opts.sort || (opts.sort = {}); + s[field] = { $meta : value.$meta }; + return; } - var conds = this._conditions; - - debug('findAndModify', this._collection.collectionName, conds, doc, opts); - callback = this._wrapCallback('findAndModify', callback, { - conditions: conds - , doc: doc - , options: opts - }); - - this._collection - .findAndModify(conds, doc, opts, utils.tick(callback)); - - return this; + var val = String(value || 1).toLowerCase(); + if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) { + if (utils.isArray(value)) value = '['+value+']'; + throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }'); + } + // store `sort` in a sane format + var s = opts.sort || (opts.sort = {}); + var valueStr = value.toString() + .replace("asc", "1") + .replace("ascending", "1") + .replace("desc", "-1") + .replace("descending", "-1"); + s[field] = parseInt(valueStr, 10); } -/** - * Wrap callback to add tracing - * - * @param {Function} callback - * @param {Object} [queryInfo] - * @api private - */ -Query.prototype._wrapCallback = function (method, callback, queryInfo) { - var traceFunction = this._traceFunction || Query.traceFunction; - - if (traceFunction) { - queryInfo.collectionName = this._collection.collectionName; - - var traceCallback = traceFunction && - traceFunction.call(null, method, queryInfo, this); - - var startTime = new Date().getTime(); - - return function wrapperCallback (err, result) { - if (traceCallback) { - var millis = new Date().getTime() - startTime; - traceCallback.call(null, err, result, millis); - } - - if (callback) { - callback.apply(null, arguments); - } - }; +function _pushArr (opts, field, value) { + opts.sort = opts.sort || []; + if (!Array.isArray(opts.sort)) { + throw new TypeError("Can't mix sort syntaxes. Use either array or object:" + + "\n- `.sort([['field', 1], ['test', -1]])`" + + "\n- `.sort({ field: 1, test: -1 })`"); } - - return callback; + var valueStr = value.toString() + .replace("asc", "1") + .replace("ascending", "1") + .replace("desc", "-1") + .replace("descending", "-1"); + opts.sort.push([field, value]); } /** - * Add trace function that gets called when the query is executed. - * The function will be called with (method, queryInfo, query) and - * should return a callback function which will be called - * with (err, result, millis) when the query is complete. + * Specifies the limit option. * - * queryInfo is an object containing: { - * collectionName: , - * conditions: , - * options: , - * doc: [document to update, if applicable] - * } + * ####Example * - * NOTE: Does not trace stream queries. + * query.limit(20) * - * @param {Function} traceFunction - * @return {Query} this + * ####Note + * + * Cannot be used with `distinct()` + * + * @method limit + * @memberOf Query + * @param {Number} val + * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D * @api public */ -Query.prototype.setTraceFunction = function (traceFunction) { - this._traceFunction = traceFunction; - return this; -} - /** - * Executes the query + * Specifies the skip option. * - * ####Examples + * ####Example * - * query.exec(); - * query.exec(callback); - * query.exec('update'); - * query.exec('find', callback); + * query.skip(100).limit(20) * - * @param {String|Function} [operation] - * @param {Function} [callback] + * ####Note + * + * Cannot be used with `distinct()` + * + * @method skip + * @memberOf Query + * @param {Number} val + * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D * @api public */ - -Query.prototype.exec = function exec (op, callback) { - switch (typeof op) { - case 'function': - callback = op; - op = null; - break; - case 'string': - this.op = op; - break; - } - - assert.ok(this.op, "Missing query type: (find, update, etc)"); - - if ('update' == this.op || 'remove' == this.op) { - callback || (callback = true); - } - - var self = this; - - if ('function' == typeof callback) { - this[this.op](callback); - } else { - return new Query.Promise(function(success, error) { - self[self.op](function(err, val) { - if (err) error(err); - else success(val); - self = success = error = null; - }); - }); - } -} - /** - * Returns a thunk which when called runs this.exec() + * Specifies the maxScan option. * - * The thunk receives a callback function which will be - * passed to `this.exec()` + * ####Example * - * @return {Function} + * query.maxScan(100) + * + * ####Note + * + * Cannot be used with `distinct()` + * + * @method maxScan + * @memberOf Query + * @param {Number} val + * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan * @api public */ - -Query.prototype.thunk = function() { - var self = this; - return function(cb) { - self.exec(cb); - } -} - /** - * Executes the query returning a `Promise` which will be - * resolved with either the doc(s) or rejected with the error. + * Specifies the batchSize option. * - * @param {Function} [resolve] - * @param {Function} [reject] - * @return {Promise} + * ####Example + * + * query.batchSize(100) + * + * ####Note + * + * Cannot be used with `distinct()` + * + * @method batchSize + * @memberOf Query + * @param {Number} val + * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D * @api public */ - -Query.prototype.then = function(resolve, reject) { - var self = this; - var promise = new Query.Promise(function(success, error) { - self.exec(function(err, val) { - if (err) error(err); - else success(val); - self = success = error = null; - }); - }); - return promise.then(resolve, reject); -} - /** - * Returns a stream for the given find query. + * Specifies the `comment` option. * - * @throws Error if operation is not a find - * @returns {Stream} Node 0.8 style + * ####Example + * + * query.comment('login query') + * + * ####Note + * + * Cannot be used with `distinct()` + * + * @method comment + * @memberOf Query + * @param {Number} val + * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment + * @api public */ -Query.prototype.stream = function(streamOptions) { - if ('find' != this.op) - throw new Error('stream() is only available for find'); - - var conds = this._conditions; - - var options = this._optionsForExec() - options.fields = this._fieldsForExec() - - debug('stream', this._collection.collectionName, conds, options, streamOptions); +/*! + * limit, skip, maxScan, batchSize, comment + * + * Sets these associated options. + * + * query.comment('feed query'); + */ - return this._collection.findStream(conds, options, streamOptions); -} +;['limit', 'skip', 'maxScan', 'batchSize', 'comment'].forEach(function (method) { + Query.prototype[method] = function (v) { + this._validate(method); + this.options[method] = v; + return this; + }; +}) /** - * Determines if field selection has been made. + * Specifies the maxTimeMS option. * - * @return {Boolean} + * ####Example + * + * query.maxTime(100) + * + * @method maxTime + * @memberOf Query + * @param {Number} val + * @see mongodb http://docs.mongodb.org/manual/reference/operator/meta/maxTimeMS/#op._S_maxTimeMS * @api public */ -Query.prototype.selected = function selected () { - return !! (this._fields && Object.keys(this._fields).length > 0); -} +Query.prototype.maxTime = function (v) { + this._validate('maxTime'); + this.options.maxTimeMS = v; + return this; +}; /** - * Determines if inclusive field selection has been made. + * Specifies this query as a `snapshot` query. * - * query.selectedInclusively() // false - * query.select('name') - * query.selectedInclusively() // true - * query.selectedExlusively() // false + * ####Example * - * @returns {Boolean} + * mquery().snapshot() // true + * mquery().snapshot(true) + * mquery().snapshot(false) + * + * ####Note + * + * Cannot be used with `distinct()` + * + * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D + * @return {Query} this + * @api public */ -Query.prototype.selectedInclusively = function selectedInclusively () { - if (!this._fields) return false; - - var keys = Object.keys(this._fields); - if (0 === keys.length) return false; +Query.prototype.snapshot = function () { + this._validate('snapshot'); - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - if (0 === this._fields[key]) return false; - if (this._fields[key] && - typeof this._fields[key] === 'object' && - this._fields[key].$meta) { - return false; - } - } + this.options.snapshot = arguments.length + ? !! arguments[0] + : true - return true; + return this; } /** - * Determines if exclusive field selection has been made. + * Sets query hints. * - * query.selectedExlusively() // false - * query.select('-name') - * query.selectedExlusively() // true - * query.selectedInclusively() // false + * ####Example * - * @returns {Boolean} + * query.hint({ indexA: 1, indexB: -1}) + * + * ####Note + * + * Cannot be used with `distinct()` + * + * @param {Object} val a hint object + * @return {Query} this + * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint + * @api public */ -Query.prototype.selectedExclusively = function selectedExclusively () { - if (!this._fields) return false; +Query.prototype.hint = function () { + if (0 === arguments.length) return this; - var keys = Object.keys(this._fields); - if (0 === keys.length) return false; + this._validate('hint'); - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - if (0 === this._fields[key]) return true; + var arg = arguments[0]; + if (utils.isObject(arg)) { + var hint = this.options.hint || (this.options.hint = {}); + + // must keep object keys in order so don't use Object.keys() + for (var k in arg) { + hint[k] = arg[k]; + } + + return this; } - return false; + throw new TypeError('Invalid hint. ' + arg); } /** - * Merges `doc` with the current update object. + * Sets the slaveOk option. _Deprecated_ in MongoDB 2.2 in favor of read preferences. * - * @param {Object} doc + * ####Example: + * + * query.slaveOk() // true + * query.slaveOk(true) + * query.slaveOk(false) + * + * @deprecated use read() preferences instead if on mongodb >= 2.2 + * @param {Boolean} v defaults to true + * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference + * @see read() + * @return {Query} this + * @api public */ -Query.prototype._mergeUpdate = function (doc) { - if (!this._update) this._update = {}; - if (doc instanceof Query) { - if (doc._update) { - utils.mergeClone(this._update, doc._update); - } - } else { - utils.mergeClone(this._update, doc); - } +Query.prototype.slaveOk = function (v) { + this.options.slaveOk = arguments.length ? !!v : true; + return this; } /** - * Returns default options. + * Sets the readPreference option for the query. * - * @return {Object} - * @api private + * ####Example: + * + * new Query().read('primary') + * new Query().read('p') // same as primary + * + * new Query().read('primaryPreferred') + * new Query().read('pp') // same as primaryPreferred + * + * new Query().read('secondary') + * new Query().read('s') // same as secondary + * + * new Query().read('secondaryPreferred') + * new Query().read('sp') // same as secondaryPreferred + * + * new Query().read('nearest') + * new Query().read('n') // same as nearest + * + * // you can also use mongodb.ReadPreference class to also specify tags + * new Query().read(mongodb.ReadPreference('secondary', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])) + * + * ####Preferences: + * + * primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags. + * secondary Read from secondary if available, otherwise error. + * primaryPreferred Read from primary if available, otherwise a secondary. + * secondaryPreferred Read from a secondary if available, otherwise read from the primary. + * nearest All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection. + * + * Aliases + * + * p primary + * pp primaryPreferred + * s secondary + * sp secondaryPreferred + * n nearest + * + * Read more about how to use read preferences [here](http://docs.mongodb.org/manual/applications/replication/#read-preference) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences). + * + * @param {String|ReadPreference} pref one of the listed preference options or their aliases + * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference + * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences + * @return {Query} this + * @api public */ -Query.prototype._optionsForExec = function () { - var options = utils.clone(this.options, { retainKeyOrder: true }); - return options; +Query.prototype.read = function (pref) { + if (arguments.length > 1 && !Query.prototype.read.deprecationWarningIssued) { + console.error("Deprecation warning: 'tags' argument is not supported anymore in Query.read() method. Please use mongodb.ReadPreference object instead."); + Query.prototype.read.deprecationWarningIssued = true; + } + this.options.readPreference = utils.readPref(pref); + return this; } /** - * Returns fields selection for this query. + * Sets tailable option. * - * @return {Object} - * @api private + * ####Example + * + * query.tailable() <== true + * query.tailable(true) + * query.tailable(false) + * + * ####Note + * + * Cannot be used with `distinct()` + * + * @param {Boolean} v defaults to true + * @see mongodb http://www.mongodb.org/display/DOCS/Tailable+Cursors + * @api public */ -Query.prototype._fieldsForExec = function () { - return utils.clone(this._fields, { retainKeyOrder: true }); +Query.prototype.tailable = function () { + this._validate('tailable'); + + this.options.tailable = arguments.length + ? !! arguments[0] + : true; + + return this; } /** - * Return an update document with corrected $set operations. + * Merges another Query or conditions object into this one. * - * @api private + * When a Query is passed, conditions, field selection and options are merged. + * + * @param {Query|Object} source + * @return {Query} this */ -Query.prototype._updateForExec = function () { - var update = utils.clone(this._update, { retainKeyOrder: true }) - , ops = utils.keys(update) - , i = ops.length - , ret = {} - , hasKeys - , val +Query.prototype.merge = function (source) { + if (!source) + return this; - while (i--) { - var op = ops[i]; + if (!Query.canMerge(source)) + throw new TypeError('Invalid argument. Expected instanceof mquery or plain object'); - if (this.options.overwrite) { - ret[op] = update[op]; - continue; + if (source instanceof Query) { + // if source has a feature, apply it to ourselves + + if (source._conditions) { + utils.merge(this._conditions, source._conditions); } - if ('$' !== op[0]) { - // fix up $set sugar - if (!ret.$set) { - if (update.$set) { - ret.$set = update.$set; - } else { - ret.$set = {}; - } - } - ret.$set[op] = update[op]; - ops.splice(i, 1); - if (!~ops.indexOf('$set')) ops.push('$set'); - } else if ('$set' === op) { - if (!ret.$set) { - ret[op] = update[op]; - } - } else { - ret[op] = update[op]; + if (source._fields) { + this._fields || (this._fields = {}); + utils.merge(this._fields, source._fields); } - } - this._compiledUpdate = ret; - return ret; -} + if (source.options) { + this.options || (this.options = {}); + utils.merge(this.options, source.options); + } -/** - * Make sure _path is set. - * - * @parmam {String} method - */ + if (source._update) { + this._update || (this._update = {}); + utils.mergeClone(this._update, source._update); + } -Query.prototype._ensurePath = function (method) { - if (!this._path) { - var msg = method + '() must be used after where() ' - + 'when called with these arguments' - throw new Error(msg); + if (source._distinct) { + this._distinct = source._distinct; + } + + return this; } + + // plain object + utils.merge(this._conditions, source); + + return this; } -/*! - * Permissions +/** + * Finds documents. + * + * Passing a `callback` executes the query. + * + * ####Example + * + * query.find() + * query.find(callback) + * query.find({ name: 'Burning Lights' }, callback) + * + * @param {Object} [criteria] mongodb selector + * @param {Function} [callback] + * @return {Query} this + * @api public */ -Query.permissions = require('./permissions'); - -Query._isPermitted = function (a, b) { - var denied = Query.permissions[b]; - if (!denied) return true; - return true !== denied[a]; -} +Query.prototype.find = function (criteria, callback) { + this.op = 'find'; -Query.prototype._validate = function (action) { - var fail; - var validator; + if ('function' === typeof criteria) { + callback = criteria; + criteria = undefined; + } else if (Query.canMerge(criteria)) { + this.merge(criteria); + } - if (undefined === action) { + if (!callback) return this; - validator = Query.permissions[this.op]; - if ('function' != typeof validator) return true; + var self = this + , conds = this._conditions + , options = this._optionsForExec() - fail = validator(this); + options.fields = this._fieldsForExec() - } else if (!Query._isPermitted(action, this.op)) { - fail = action; - } + debug('find', this._collection.collectionName, conds, options); + callback = this._wrapCallback('find', callback, { + conditions: conds + , options: options + }); - if (fail) { - throw new Error(fail + ' cannot be used with ' + this.op); - } + this._collection.find(conds, options, utils.tick(callback)); + return this; } /** - * Determines if `conds` can be merged using `mquery().merge()` + * Returns the query cursor * - * @param {Object} conds - * @return {Boolean} + * ####Examples + * + * query.find().cursor(); + * query.cursor({ name: 'Burning Lights' }); + * + * @param {Object} [criteria] mongodb selector + * @return {Object} cursor + * @api public */ -Query.canMerge = function (conds) { - return conds instanceof Query || utils.isObject(conds); +Query.prototype.cursor = function cursor (criteria) { + if (this.op) { + if (this.op !== 'find') { + throw new TypeError(".cursor only support .find method"); + } + } else { + this.find(criteria); + } + + var conds = this._conditions + , options = this._optionsForExec() + + options.fields = this._fieldsForExec() + + debug('findCursor', this._collection.collectionName, conds, options); + return this._collection.findCursor(conds, options); } /** - * Set a trace function that will get called whenever a - * query is executed. + * Executes the query as a findOne() operation. * - * See `setTraceFunction()` for details. + * Passing a `callback` executes the query. * - * @param {Object} conds - * @return {Boolean} - */ -Query.setGlobalTraceFunction = function (traceFunction) { - Query.traceFunction = traceFunction; -} - -/*! - * Exports. + * ####Example + * + * query.findOne().where('name', /^Burning/); + * + * query.findOne({ name: /^Burning/ }) + * + * query.findOne({ name: /^Burning/ }, callback); // executes + * + * query.findOne(function (err, doc) { + * if (err) return handleError(err); + * if (doc) { + * // doc may be null if no document matched + * + * } + * }); + * + * @param {Object|Query} [criteria] mongodb selector + * @param {Function} [callback] + * @return {Query} this + * @api public */ -Query.utils = utils; -Query.env = require('./env') -Query.Collection = require('./collection'); -Query.BaseCollection = require('./collection/collection'); -Query.Promise = require('bluebird'); -module.exports = exports = Query; - -// TODO -// test utils - -},{"./collection":82,"./collection/collection":81,"./env":84,"./permissions":86,"./utils":87,"assert":50,"bluebird":88,"debug":89,"sliced":91,"util":98}],86:[function(require,module,exports){ -'use strict'; - -var denied = exports; +Query.prototype.findOne = function (criteria, callback) { + this.op = 'findOne'; -denied.distinct = function (self) { - if (self._fields && Object.keys(self._fields).length > 0) { - return 'field selection and slice' + if ('function' === typeof criteria) { + callback = criteria; + criteria = undefined; + } else if (Query.canMerge(criteria)) { + this.merge(criteria); } - var keys = Object.keys(denied.distinct); - var err; - - keys.every(function (option) { - if (self.options[option]) { - err = option; - return false; - } - return true; - }); - - return err; -}; -denied.distinct.select = -denied.distinct.slice = -denied.distinct.sort = -denied.distinct.limit = -denied.distinct.skip = -denied.distinct.batchSize = -denied.distinct.comment = -denied.distinct.maxScan = -denied.distinct.snapshot = -denied.distinct.hint = -denied.distinct.tailable = true; - - -// aggregation integration + if (!callback) return this; + var self = this + , conds = this._conditions + , options = this._optionsForExec() -denied.findOneAndUpdate = -denied.findOneAndRemove = function (self) { - var keys = Object.keys(denied.findOneAndUpdate); - var err; + options.fields = this._fieldsForExec(); - keys.every(function (option) { - if (self.options[option]) { - err = option; - return false; - } - return true; + debug('findOne', this._collection.collectionName, conds, options); + callback = this._wrapCallback('findOne', callback, { + conditions: conds + , options: options }); - return err; + this._collection.findOne(conds, options, utils.tick(callback)); + + return this; } -denied.findOneAndUpdate.limit = -denied.findOneAndUpdate.skip = -denied.findOneAndUpdate.batchSize = -denied.findOneAndUpdate.maxScan = -denied.findOneAndUpdate.snapshot = -denied.findOneAndUpdate.hint = -denied.findOneAndUpdate.tailable = -denied.findOneAndUpdate.comment = true; +/** + * Exectues the query as a count() operation. + * + * Passing a `callback` executes the query. + * + * ####Example + * + * query.count().where('color', 'black').exec(callback); + * + * query.count({ color: 'black' }).count(callback) + * + * query.count({ color: 'black' }, callback) + * + * query.where('color', 'black').count(function (err, count) { + * if (err) return handleError(err); + * console.log('there are %d kittens', count); + * }) + * + * @param {Object} [criteria] mongodb selector + * @param {Function} [callback] + * @return {Query} this + * @see mongodb http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count + * @api public + */ -denied.count = function (self) { - if (self._fields && Object.keys(self._fields).length > 0) { - return 'field selection and slice' +Query.prototype.count = function (criteria, callback) { + this.op = 'count'; + this._validate(); + + if ('function' === typeof criteria) { + callback = criteria; + criteria = undefined; + } else if (Query.canMerge(criteria)) { + this.merge(criteria); } - var keys = Object.keys(denied.count); - var err; + if (!callback) return this; - keys.every(function (option) { - if (self.options[option]) { - err = option; - return false; - } - return true; + var conds = this._conditions + , options = this._optionsForExec() + + debug('count', this._collection.collectionName, conds, options); + callback = this._wrapCallback('count', callback, { + conditions: conds + , options: options }); - return err; + this._collection.count(conds, options, utils.tick(callback)); + return this; } -denied.count.slice = -denied.count.batchSize = -denied.count.comment = -denied.count.maxScan = -denied.count.snapshot = -denied.count.tailable = true; - -},{}],87:[function(require,module,exports){ -(function (process,Buffer){ -'use strict'; - -/*! - * Module dependencies. - */ - -var RegExpClone = require('regexp-clone') - /** - * Clones objects + * Declares or executes a distinct() operation. * - * @param {Object} obj the object to clone - * @param {Object} options - * @return {Object} the cloned object - * @api private + * Passing a `callback` executes the query. + * + * ####Example + * + * distinct(criteria, field, fn) + * distinct(criteria, field) + * distinct(field, fn) + * distinct(field) + * distinct(fn) + * distinct() + * + * @param {Object|Query} [criteria] + * @param {String} [field] + * @param {Function} [callback] + * @return {Query} this + * @see mongodb http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct + * @api public */ -var clone = exports.clone = function clone (obj, options) { - if (obj === undefined || obj === null) - return obj; - - if (Array.isArray(obj)) - return exports.cloneArray(obj, options); - - if (obj.constructor) { - if (/ObjectI[dD]$/.test(obj.constructor.name)) { - return 'function' == typeof obj.clone - ? obj.clone() - : new obj.constructor(obj.id); - } +Query.prototype.distinct = function (criteria, field, callback) { + this.op = 'distinct'; + this._validate(); - if ('ReadPreference' === obj._type && obj.isValid && obj.toObject) { - return 'function' == typeof obj.clone - ? obj.clone() - : new obj.constructor(obj.mode, clone(obj.tags, options)); + if (!callback) { + switch (typeof field) { + case 'function': + callback = field; + if ('string' == typeof criteria) { + field = criteria; + criteria = undefined; + } + break; + case 'undefined': + case 'string': + break; + default: + throw new TypeError('Invalid `field` argument. Must be string or function') + break; } - if ('Binary' == obj._bsontype && obj.buffer && obj.value) { - return 'function' == typeof obj.clone - ? obj.clone() - : new obj.constructor(obj.value(true), obj.sub_type); + switch (typeof criteria) { + case 'function': + callback = criteria; + criteria = field = undefined; + break; + case 'string': + field = criteria; + criteria = undefined; + break; } - - if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name) - return new obj.constructor(+obj); - - if ('RegExp' === obj.constructor.name) - return RegExpClone(obj); - - if ('Buffer' === obj.constructor.name) - return exports.cloneBuffer(obj); } - if (isObject(obj)) - return exports.cloneObject(obj, options); - - if (obj.valueOf) - return obj.valueOf(); -}; - -/*! - * ignore - */ - -var cloneObject = exports.cloneObject = function cloneObject (obj, options) { - var retainKeyOrder = options && options.retainKeyOrder - , minimize = options && options.minimize - , ret = {} - , hasKeys - , keys - , val - , k - , i + if ('string' == typeof field) { + this._distinct = field; + } - if (retainKeyOrder) { - for (k in obj) { - val = clone(obj[k], options); + if (Query.canMerge(criteria)) { + this.merge(criteria); + } - if (!minimize || ('undefined' !== typeof val)) { - hasKeys || (hasKeys = true); - ret[k] = val; - } - } - } else { - // faster + if (!callback) { + return this; + } - keys = Object.keys(obj); - i = keys.length; + if (!this._distinct) { + throw new Error('No value for `distinct` has been declared'); + } - while (i--) { - k = keys[i]; - val = clone(obj[k], options); + var conds = this._conditions + , options = this._optionsForExec() - if (!minimize || ('undefined' !== typeof val)) { - if (!hasKeys) hasKeys = true; - ret[k] = val; - } - } - } + debug('distinct', this._collection.collectionName, conds, options); + callback = this._wrapCallback('distinct', callback, { + conditions: conds + , options: options + }); - return minimize - ? hasKeys && ret - : ret; -}; + this._collection.distinct(this._distinct, conds, options, utils.tick(callback)); -var cloneArray = exports.cloneArray = function cloneArray (arr, options) { - var ret = []; - for (var i = 0, l = arr.length; i < l; i++) - ret.push(clone(arr[i], options)); - return ret; -}; + return this; +} /** - * process.nextTick helper. + * Declare and/or execute this query as an update() operation. * - * Wraps the given `callback` in a try/catch. If an error is - * caught it will be thrown on nextTick. + * _All paths passed that are not $atomic operations will become $set ops._ * - * node-mongodb-native had a habit of state corruption when - * an error was immediately thrown from within a collection - * method (find, update, etc) callback. + * ####Example * - * @param {Function} [callback] - * @api private - */ - -var tick = exports.tick = function tick (callback) { - if ('function' !== typeof callback) return; - return function () { - // callbacks should always be fired on the next - // turn of the event loop. A side benefit is - // errors thrown from executing the callback - // will not cause drivers state to be corrupted - // which has historically been a problem. - var args = arguments; - soon(function(){ - callback.apply(this, args); - }); - } -} - -/** - * Merges `from` into `to` without overwriting existing properties. + * mquery({ _id: id }).update({ title: 'words' }, ...) * - * @param {Object} to - * @param {Object} from - * @api private - */ - -var merge = exports.merge = function merge (to, from) { - var keys = Object.keys(from) - , i = keys.length - , key - - while (i--) { - key = keys[i]; - if ('undefined' === typeof to[key]) { - to[key] = from[key]; - } else { - if (exports.isObject(from[key])) { - merge(to[key], from[key]); - } else { - to[key] = from[key]; - } - } - } -} - -/** - * Same as merge but clones the assigned values. + * becomes * - * @param {Object} to - * @param {Object} from - * @api private - */ - -var mergeClone = exports.mergeClone = function mergeClone (to, from) { - var keys = Object.keys(from) - , i = keys.length - , key - - while (i--) { - key = keys[i]; - if ('undefined' === typeof to[key]) { - // make sure to retain key order here because of a bug handling the $each - // operator in mongodb 2.4.4 - to[key] = clone(from[key], { retainKeyOrder : 1}); - } else { - if (exports.isObject(from[key])) { - mergeClone(to[key], from[key]); - } else { - // make sure to retain key order here because of a bug handling the - // $each operator in mongodb 2.4.4 - to[key] = clone(from[key], { retainKeyOrder : 1}); - } - } - } -} - -/** - * Read pref helper (mongo 2.2 drivers support this) + * collection.update({ _id: id }, { $set: { title: 'words' }}, ...) * - * Allows using aliases instead of full preference names: + * ####Note * - * p primary - * pp primaryPreferred - * s secondary - * sp secondaryPreferred - * n nearest + * Passing an empty object `{}` as the doc will result in a no-op unless the `overwrite` option is passed. Without the `overwrite` option set, the update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting documents in the collection. * - * @param {String} pref + * ####Note + * + * The operation is only executed when a callback is passed. To force execution without a callback (which would be an unsafe write), we must first call update() and then execute it by using the `exec()` method. + * + * var q = mquery(collection).where({ _id: id }); + * q.update({ $set: { name: 'bob' }}).update(); // not executed + * + * var q = mquery(collection).where({ _id: id }); + * q.update({ $set: { name: 'bob' }}).exec(); // executed as unsafe + * + * // keys that are not $atomic ops become $set. + * // this executes the same command as the previous example. + * q.update({ name: 'bob' }).where({ _id: id }).exec(); + * + * var q = mquery(collection).update(); // not executed + * + * // overwriting with empty docs + * var q.where({ _id: id }).setOptions({ overwrite: true }) + * q.update({ }, callback); // executes + * + * // multi update with overwrite to empty doc + * var q = mquery(collection).where({ _id: id }); + * q.setOptions({ multi: true, overwrite: true }) + * q.update({ }); + * q.update(callback); // executed + * + * // multi updates + * mquery() + * .collection(coll) + * .update({ name: /^match/ }, { $set: { arr: [] }}, { multi: true }, callback) + * // more multi updates + * mquery({ }) + * .collection(coll) + * .setOptions({ multi: true }) + * .update({ $set: { arr: [] }}, callback) + * + * // single update by default + * mquery({ email: 'address@example.com' }) + * .collection(coll) + * .update({ $inc: { counter: 1 }}, callback) + * + * // summary + * update(criteria, doc, opts, cb) // executes + * update(criteria, doc, opts) + * update(criteria, doc, cb) // executes + * update(criteria, doc) + * update(doc, cb) // executes + * update(doc) + * update(cb) // executes + * update(true) // executes (unsafe write) + * update() + * + * @param {Object} [criteria] + * @param {Object} [doc] the update command + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} this + * @api public */ -exports.readPref = function readPref (pref) { - switch (pref) { - case 'p': - pref = 'primary'; - break; - case 'pp': - pref = 'primaryPreferred'; - break; - case 's': - pref = 'secondary'; - break; - case 'sp': - pref = 'secondaryPreferred'; +Query.prototype.update = function update (criteria, doc, options, callback) { + this.op = 'update'; + var force; + + switch (arguments.length) { + case 3: + if ('function' == typeof options) { + callback = options; + options = undefined; + } break; - case 'n': - pref = 'nearest'; + case 2: + if ('function' == typeof doc) { + callback = doc; + doc = criteria; + criteria = undefined; + } break; + case 1: + switch (typeof criteria) { + case 'function': + callback = criteria; + criteria = options = doc = undefined; + break; + case 'boolean': + // execution with no callback (unsafe write) + force = criteria; + criteria = undefined; + break; + default: + doc = criteria; + criteria = options = undefined; + break; + } } - return pref; -} + if (Query.canMerge(criteria)) { + this.merge(criteria); + } -/** - * Object.prototype.toString.call helper - */ + if (doc) { + this._mergeUpdate(doc); + } -var _toString = Object.prototype.toString; -var toString = exports.toString = function (arg) { - return _toString.call(arg); -} + if (utils.isObject(options)) { + // { overwrite: true } + this.setOptions(options); + } -/** - * Determines if `arg` is an object. - * - * @param {Object|Array|String|Function|RegExp|any} arg - * @return {Boolean} - */ + // we are done if we don't have callback and they are + // not forcing an unsafe write. + if (!(force || callback)) + return this; -var isObject = exports.isObject = function (arg) { - return '[object Object]' == exports.toString(arg); -} + if (!this._update || + !this.options.overwrite && 0 === utils.keys(this._update).length) { + callback && utils.soon(callback.bind(null, null, 0)); + return this; + } -/** - * Determines if `arg` is an array. - * - * @param {Object} - * @return {Boolean} - * @see nodejs utils - */ + options = this._optionsForExec(); + if (!callback) options.safe = false; -var isArray = exports.isArray = function (arg) { - return Array.isArray(arg) || - 'object' == typeof arg && '[object Array]' == exports.toString(arg); -} + var criteria = this._conditions; + doc = this._updateForExec(); -/** - * Object.keys helper - */ + debug('update', this._collection.collectionName, criteria, doc, options); + callback = this._wrapCallback('update', callback, { + conditions: criteria + , doc: doc + , options: options + }); -exports.keys = Object.keys || function (obj) { - var keys = []; - for (var k in obj) if (obj.hasOwnProperty(k)) { - keys.push(k); - } - return keys; + this._collection.update(criteria, doc, options, utils.tick(callback)); + + return this; } /** - * Basic Object.create polyfill. - * Only one argument is supported. + * Declare and/or execute this query as a remove() operation. * - * Based on https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create - */ - -exports.create = 'function' == typeof Object.create - ? Object.create - : create; + * ####Example + * + * mquery(collection).remove({ artist: 'Anne Murray' }, callback) + * + * ####Note + * + * The operation is only executed when a callback is passed. To force execution without a callback (which would be an unsafe write), we must first call remove() and then execute it by using the `exec()` method. + * + * // not executed + * var query = mquery(collection).remove({ name: 'Anne Murray' }) + * + * // executed + * mquery(collection).remove({ name: 'Anne Murray' }, callback) + * mquery(collection).remove({ name: 'Anne Murray' }).remove(callback) + * + * // executed without a callback (unsafe write) + * query.exec() + * + * // summary + * query.remove(conds, fn); // executes + * query.remove(conds) + * query.remove(fn) // executes + * query.remove() + * + * @param {Object|Query} [criteria] mongodb selector + * @param {Function} [callback] + * @return {Query} this + * @api public + */ -function create (proto) { - if (arguments.length > 1) { - throw new Error("Adding properties is not supported") +Query.prototype.remove = function (criteria, callback) { + this.op = 'remove'; + var force; + + if ('function' === typeof criteria) { + callback = criteria; + criteria = undefined; + } else if (Query.canMerge(criteria)) { + this.merge(criteria); + } else if (true === criteria) { + force = criteria; + criteria = undefined; } - function F () {} - F.prototype = proto; - return new F; -} + if (!(force || callback)) + return this; -/** - * inheritance - */ + var options = this._optionsForExec() + if (!callback) options.safe = false; -exports.inherits = function (ctor, superCtor) { - ctor.prototype = exports.create(superCtor.prototype); - ctor.prototype.constructor = ctor; -} + var conds = this._conditions; -/** - * nextTick helper - * compat with node 0.10 which behaves differently than previous versions - */ + debug('remove', this._collection.collectionName, conds, options); + callback = this._wrapCallback('remove', callback, { + conditions: conds + , options: options + }); -var soon = exports.soon = 'function' == typeof setImmediate - ? setImmediate - : process.nextTick; + this._collection.remove(conds, options, utils.tick(callback)); + + return this; +} /** - * Clones the contents of a buffer. + * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) update command. * - * @param {Buffer} buff - * @return {Buffer} + * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed. + * + * ####Available options + * + * - `new`: bool - true to return the modified document rather than the original. defaults to true + * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * + * ####Examples + * + * query.findOneAndUpdate(conditions, update, options, callback) // executes + * query.findOneAndUpdate(conditions, update, options) // returns Query + * query.findOneAndUpdate(conditions, update, callback) // executes + * query.findOneAndUpdate(conditions, update) // returns Query + * query.findOneAndUpdate(update, callback) // returns Query + * query.findOneAndUpdate(update) // returns Query + * query.findOneAndUpdate(callback) // executes + * query.findOneAndUpdate() // returns Query + * + * @param {Object|Query} [query] + * @param {Object} [doc] + * @param {Object} [options] + * @param {Function} [callback] + * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + * @return {Query} this + * @api public */ -exports.cloneBuffer = function (buff) { - var dupe = new Buffer(buff.length); - buff.copy(dupe, 0, 0, buff.length); - return dupe; -}; +Query.prototype.findOneAndUpdate = function (criteria, doc, options, callback) { + this.op = 'findOneAndUpdate'; + this._validate(); + + switch (arguments.length) { + case 3: + if ('function' == typeof options) { + callback = options; + options = {}; + } + break; + case 2: + if ('function' == typeof doc) { + callback = doc; + doc = criteria; + criteria = undefined; + } + options = undefined; + break; + case 1: + if ('function' == typeof criteria) { + callback = criteria; + criteria = options = doc = undefined; + } else { + doc = criteria; + criteria = options = undefined; + } + } + + if (Query.canMerge(criteria)) { + this.merge(criteria); + } + + // apply doc + if (doc) { + this._mergeUpdate(doc); + } + + options && this.setOptions(options); + + if (!callback) return this; + return this._findAndModify('update', callback); +} /** - * Check if this object is an arguments object + * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) remove command. * - * @param {Any} v - * @return {Boolean} + * Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if `callback` is passed. + * + * ####Available options + * + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * + * ####Examples + * + * A.where().findOneAndRemove(conditions, options, callback) // executes + * A.where().findOneAndRemove(conditions, options) // return Query + * A.where().findOneAndRemove(conditions, callback) // executes + * A.where().findOneAndRemove(conditions) // returns Query + * A.where().findOneAndRemove(callback) // executes + * A.where().findOneAndRemove() // returns Query + * + * @param {Object} [conditions] + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} this + * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + * @api public */ -exports.isArgumentsObject = function(v) { - return Object.prototype.toString.call(v) === '[object Arguments]'; -}; +Query.prototype.findOneAndRemove = function (conditions, options, callback) { + this.op = 'findOneAndRemove'; + this._validate(); -}).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"buffer":71,"g5I+bs":94,"regexp-clone":95}],88:[function(require,module,exports){ -(function (process,global){ -/* @preserve - * The MIT License (MIT) - * - * Copyright (c) 2013-2015 Petka Antonov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ -/** - * bluebird build version 2.10.2 - * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, cancel, using, filter, any, each, timers -*/ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o 0; -}; + var opts = this._optionsForExec() + , self = this + , fields + , sort + , doc -Async.prototype.throwLater = function(fn, arg) { - if (arguments.length === 1) { - arg = fn; - fn = function () { throw arg; }; - } - if (typeof setTimeout !== "undefined") { - setTimeout(function() { - fn(arg); - }, 0); - } else try { - this._schedule(function() { - fn(arg); - }); - } catch (e) { - throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/m3OTXk\u000a"); - } -}; + if ('remove' == type) { + opts.remove = true; + } else { + if (!('new' in opts)) opts.new = true; + if (!('upsert' in opts)) opts.upsert = false; -function AsyncInvokeLater(fn, receiver, arg) { - this._lateQueue.push(fn, receiver, arg); - this._queueTick(); -} + doc = this._updateForExec() + if (!doc) { + if (opts.upsert) { + // still need to do the upsert to empty doc + doc = { $set: {} }; + } else { + return this.findOne(callback); + } + } + } -function AsyncInvoke(fn, receiver, arg) { - this._normalQueue.push(fn, receiver, arg); - this._queueTick(); -} + var fields = this._fieldsForExec(); + if (fields) { + opts.fields = fields; + } -function AsyncSettlePromises(promise) { - this._normalQueue._pushOne(promise); - this._queueTick(); -} + var conds = this._conditions; -if (!util.hasDevTools) { - Async.prototype.invokeLater = AsyncInvokeLater; - Async.prototype.invoke = AsyncInvoke; - Async.prototype.settlePromises = AsyncSettlePromises; -} else { - if (schedule.isStatic) { - schedule = function(fn) { setTimeout(fn, 0); }; - } - Async.prototype.invokeLater = function (fn, receiver, arg) { - if (this._trampolineEnabled) { - AsyncInvokeLater.call(this, fn, receiver, arg); - } else { - this._schedule(function() { - setTimeout(function() { - fn.call(receiver, arg); - }, 100); - }); - } - }; + debug('findAndModify', this._collection.collectionName, conds, doc, opts); + callback = this._wrapCallback('findAndModify', callback, { + conditions: conds + , doc: doc + , options: opts + }); - Async.prototype.invoke = function (fn, receiver, arg) { - if (this._trampolineEnabled) { - AsyncInvoke.call(this, fn, receiver, arg); - } else { - this._schedule(function() { - fn.call(receiver, arg); - }); - } - }; + this._collection + .findAndModify(conds, doc, opts, utils.tick(callback)); - Async.prototype.settlePromises = function(promise) { - if (this._trampolineEnabled) { - AsyncSettlePromises.call(this, promise); - } else { - this._schedule(function() { - promise._settlePromises(); - }); - } - }; + return this; } -Async.prototype.invokeFirst = function (fn, receiver, arg) { - this._normalQueue.unshift(fn, receiver, arg); - this._queueTick(); -}; - -Async.prototype._drainQueue = function(queue) { - while (queue.length() > 0) { - var fn = queue.shift(); - if (typeof fn !== "function") { - fn._settlePromises(); - continue; - } - var receiver = queue.shift(); - var arg = queue.shift(); - fn.call(receiver, arg); - } -}; +/** + * Wrap callback to add tracing + * + * @param {Function} callback + * @param {Object} [queryInfo] + * @api private + */ +Query.prototype._wrapCallback = function (method, callback, queryInfo) { + var traceFunction = this._traceFunction || Query.traceFunction; -Async.prototype._drainQueues = function () { - this._drainQueue(this._normalQueue); - this._reset(); - this._drainQueue(this._lateQueue); -}; + if (traceFunction) { + queryInfo.collectionName = this._collection.collectionName; -Async.prototype._queueTick = function () { - if (!this._isTickUsed) { - this._isTickUsed = true; - this._schedule(this.drainQueues); - } -}; + var traceCallback = traceFunction && + traceFunction.call(null, method, queryInfo, this); -Async.prototype._reset = function () { - this._isTickUsed = false; -}; + var startTime = new Date().getTime(); -module.exports = new Async(); -module.exports.firstLineError = firstLineError; + return function wrapperCallback (err, result) { + if (traceCallback) { + var millis = new Date().getTime() - startTime; + traceCallback.call(null, err, result, millis); + } -},{"./queue.js":28,"./schedule.js":31,"./util.js":38}],3:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, INTERNAL, tryConvertToPromise) { -var rejectThis = function(_, e) { - this._reject(e); -}; + if (callback) { + callback.apply(null, arguments); + } + }; + } -var targetRejected = function(e, context) { - context.promiseRejectionQueued = true; - context.bindingPromise._then(rejectThis, rejectThis, null, this, e); -}; + return callback; +} -var bindingResolved = function(thisArg, context) { - if (this._isPending()) { - this._resolveCallback(context.target); - } -}; +/** + * Add trace function that gets called when the query is executed. + * The function will be called with (method, queryInfo, query) and + * should return a callback function which will be called + * with (err, result, millis) when the query is complete. + * + * queryInfo is an object containing: { + * collectionName: , + * conditions: , + * options: , + * doc: [document to update, if applicable] + * } + * + * NOTE: Does not trace stream queries. + * + * @param {Function} traceFunction + * @return {Query} this + * @api public + */ +Query.prototype.setTraceFunction = function (traceFunction) { + this._traceFunction = traceFunction; + return this; +} -var bindingRejected = function(e, context) { - if (!context.promiseRejectionQueued) this._reject(e); -}; +/** + * Executes the query + * + * ####Examples + * + * query.exec(); + * query.exec(callback); + * query.exec('update'); + * query.exec('find', callback); + * + * @param {String|Function} [operation] + * @param {Function} [callback] + * @api public + */ -Promise.prototype.bind = function (thisArg) { - var maybePromise = tryConvertToPromise(thisArg); - var ret = new Promise(INTERNAL); - ret._propagateFrom(this, 1); - var target = this._target(); +Query.prototype.exec = function exec (op, callback) { + switch (typeof op) { + case 'function': + callback = op; + op = null; + break; + case 'string': + this.op = op; + break; + } - ret._setBoundTo(maybePromise); - if (maybePromise instanceof Promise) { - var context = { - promiseRejectionQueued: false, - promise: ret, - target: target, - bindingPromise: maybePromise - }; - target._then(INTERNAL, targetRejected, ret._progress, ret, context); - maybePromise._then( - bindingResolved, bindingRejected, ret._progress, ret, context); - } else { - ret._resolveCallback(target); - } - return ret; -}; + assert.ok(this.op, "Missing query type: (find, update, etc)"); -Promise.prototype._setBoundTo = function (obj) { - if (obj !== undefined) { - this._bitField = this._bitField | 131072; - this._boundTo = obj; - } else { - this._bitField = this._bitField & (~131072); - } -}; + if ('update' == this.op || 'remove' == this.op) { + callback || (callback = true); + } -Promise.prototype._isBound = function () { - return (this._bitField & 131072) === 131072; -}; + var self = this; -Promise.bind = function (thisArg, value) { - var maybePromise = tryConvertToPromise(thisArg); - var ret = new Promise(INTERNAL); + if ('function' == typeof callback) { + this[this.op](callback); + } else { + return new Query.Promise(function(success, error) { + self[self.op](function(err, val) { + if (err) error(err); + else success(val); + self = success = error = null; + }); + }); + } +} - ret._setBoundTo(maybePromise); - if (maybePromise instanceof Promise) { - maybePromise._then(function() { - ret._resolveCallback(value); - }, ret._reject, ret._progress, ret, null); - } else { - ret._resolveCallback(value); - } - return ret; -}; -}; +/** + * Returns a thunk which when called runs this.exec() + * + * The thunk receives a callback function which will be + * passed to `this.exec()` + * + * @return {Function} + * @api public + */ -},{}],4:[function(_dereq_,module,exports){ -"use strict"; -var old; -if (typeof Promise !== "undefined") old = Promise; -function noConflict() { - try { if (Promise === bluebird) Promise = old; } - catch (e) {} - return bluebird; +Query.prototype.thunk = function() { + var self = this; + return function(cb) { + self.exec(cb); + } } -var bluebird = _dereq_("./promise.js")(); -bluebird.noConflict = noConflict; -module.exports = bluebird; -},{"./promise.js":23}],5:[function(_dereq_,module,exports){ -"use strict"; -var cr = Object.create; -if (cr) { - var callerCache = cr(null); - var getterCache = cr(null); - callerCache[" size"] = getterCache[" size"] = 0; +/** + * Executes the query returning a `Promise` which will be + * resolved with either the doc(s) or rejected with the error. + * + * @param {Function} [resolve] + * @param {Function} [reject] + * @return {Promise} + * @api public + */ + +Query.prototype.then = function(resolve, reject) { + var self = this; + var promise = new Query.Promise(function(success, error) { + self.exec(function(err, val) { + if (err) error(err); + else success(val); + self = success = error = null; + }); + }); + return promise.then(resolve, reject); } -module.exports = function(Promise) { -var util = _dereq_("./util.js"); -var canEvaluate = util.canEvaluate; -var isIdentifier = util.isIdentifier; +/** + * Returns a stream for the given find query. + * + * @throws Error if operation is not a find + * @returns {Stream} Node 0.8 style + */ -var getMethodCaller; -var getGetter; -if (!true) { -var makeMethodCaller = function (methodName) { - return new Function("ensureMethod", " \n\ - return function(obj) { \n\ - 'use strict' \n\ - var len = this.length; \n\ - ensureMethod(obj, 'methodName'); \n\ - switch(len) { \n\ - case 1: return obj.methodName(this[0]); \n\ - case 2: return obj.methodName(this[0], this[1]); \n\ - case 3: return obj.methodName(this[0], this[1], this[2]); \n\ - case 0: return obj.methodName(); \n\ - default: \n\ - return obj.methodName.apply(obj, this); \n\ - } \n\ - }; \n\ - ".replace(/methodName/g, methodName))(ensureMethod); -}; +Query.prototype.stream = function(streamOptions) { + if ('find' != this.op) + throw new Error('stream() is only available for find'); -var makeGetter = function (propertyName) { - return new Function("obj", " \n\ - 'use strict'; \n\ - return obj.propertyName; \n\ - ".replace("propertyName", propertyName)); -}; + var conds = this._conditions; -var getCompiled = function(name, compiler, cache) { - var ret = cache[name]; - if (typeof ret !== "function") { - if (!isIdentifier(name)) { - return null; - } - ret = compiler(name); - cache[name] = ret; - cache[" size"]++; - if (cache[" size"] > 512) { - var keys = Object.keys(cache); - for (var i = 0; i < 256; ++i) delete cache[keys[i]]; - cache[" size"] = keys.length - 256; - } - } - return ret; -}; + var options = this._optionsForExec() + options.fields = this._fieldsForExec() -getMethodCaller = function(name) { - return getCompiled(name, makeMethodCaller, callerCache); -}; + debug('stream', this._collection.collectionName, conds, options, streamOptions); -getGetter = function(name) { - return getCompiled(name, makeGetter, getterCache); -}; + return this._collection.findStream(conds, options, streamOptions); } -function ensureMethod(obj, methodName) { - var fn; - if (obj != null) fn = obj[methodName]; - if (typeof fn !== "function") { - var message = "Object " + util.classString(obj) + " has no method '" + - util.toString(methodName) + "'"; - throw new Promise.TypeError(message); - } - return fn; -} +/** + * Determines if field selection has been made. + * + * @return {Boolean} + * @api public + */ -function caller(obj) { - var methodName = this.pop(); - var fn = ensureMethod(obj, methodName); - return fn.apply(obj, this); +Query.prototype.selected = function selected () { + return !! (this._fields && Object.keys(this._fields).length > 0); } -Promise.prototype.call = function (methodName) { - var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];} - if (!true) { - if (canEvaluate) { - var maybeCaller = getMethodCaller(methodName); - if (maybeCaller !== null) { - return this._then( - maybeCaller, undefined, undefined, args, undefined); - } - } + +/** + * Determines if inclusive field selection has been made. + * + * query.selectedInclusively() // false + * query.select('name') + * query.selectedInclusively() // true + * query.selectedExlusively() // false + * + * @returns {Boolean} + */ + +Query.prototype.selectedInclusively = function selectedInclusively () { + if (!this._fields) return false; + + var keys = Object.keys(this._fields); + if (0 === keys.length) return false; + + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (0 === this._fields[key]) return false; + if (this._fields[key] && + typeof this._fields[key] === 'object' && + this._fields[key].$meta) { + return false; } - args.push(methodName); - return this._then(caller, undefined, undefined, args, undefined); -}; + } -function namedGetter(obj) { - return obj[this]; + return true; } -function indexedGetter(obj) { - var index = +this; - if (index < 0) index = Math.max(0, index + obj.length); - return obj[index]; -} -Promise.prototype.get = function (propertyName) { - var isIndex = (typeof propertyName === "number"); - var getter; - if (!isIndex) { - if (canEvaluate) { - var maybeGetter = getGetter(propertyName); - getter = maybeGetter !== null ? maybeGetter : namedGetter; - } else { - getter = namedGetter; - } - } else { - getter = indexedGetter; - } - return this._then(getter, undefined, undefined, propertyName, undefined); -}; -}; - -},{"./util.js":38}],6:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise) { -var errors = _dereq_("./errors.js"); -var async = _dereq_("./async.js"); -var CancellationError = errors.CancellationError; - -Promise.prototype._cancel = function (reason) { - if (!this.isCancellable()) return this; - var parent; - var promiseToReject = this; - while ((parent = promiseToReject._cancellationParent) !== undefined && - parent.isCancellable()) { - promiseToReject = parent; - } - this._unsetCancellable(); - promiseToReject._target()._rejectCallback(reason, false, true); -}; -Promise.prototype.cancel = function (reason) { - if (!this.isCancellable()) return this; - if (reason === undefined) reason = new CancellationError(); - async.invokeLater(this._cancel, this, reason); - return this; -}; +/** + * Determines if exclusive field selection has been made. + * + * query.selectedExlusively() // false + * query.select('-name') + * query.selectedExlusively() // true + * query.selectedInclusively() // false + * + * @returns {Boolean} + */ -Promise.prototype.cancellable = function () { - if (this._cancellable()) return this; - async.enableTrampoline(); - this._setCancellable(); - this._cancellationParent = undefined; - return this; -}; +Query.prototype.selectedExclusively = function selectedExclusively () { + if (!this._fields) return false; -Promise.prototype.uncancellable = function () { - var ret = this.then(); - ret._unsetCancellable(); - return ret; -}; + var keys = Object.keys(this._fields); + if (0 === keys.length) return false; -Promise.prototype.fork = function (didFulfill, didReject, didProgress) { - var ret = this._then(didFulfill, didReject, didProgress, - undefined, undefined); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (0 === this._fields[key]) return true; + } - ret._setCancellable(); - ret._cancellationParent = undefined; - return ret; -}; -}; + return false; +} -},{"./async.js":2,"./errors.js":13}],7:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function() { -var async = _dereq_("./async.js"); -var util = _dereq_("./util.js"); -var bluebirdFramePattern = - /[\\\/]bluebird[\\\/]js[\\\/](main|debug|zalgo|instrumented)/; -var stackFramePattern = null; -var formatStack = null; -var indentStackFrames = false; -var warn; +/** + * Merges `doc` with the current update object. + * + * @param {Object} doc + */ -function CapturedTrace(parent) { - this._parent = parent; - var length = this._length = 1 + (parent === undefined ? 0 : parent._length); - captureStackTrace(this, CapturedTrace); - if (length > 32) this.uncycle(); +Query.prototype._mergeUpdate = function (doc) { + if (!this._update) this._update = {}; + if (doc instanceof Query) { + if (doc._update) { + utils.mergeClone(this._update, doc._update); + } + } else { + utils.mergeClone(this._update, doc); + } } -util.inherits(CapturedTrace, Error); -CapturedTrace.prototype.uncycle = function() { - var length = this._length; - if (length < 2) return; - var nodes = []; - var stackToIndex = {}; +/** + * Returns default options. + * + * @return {Object} + * @api private + */ - for (var i = 0, node = this; node !== undefined; ++i) { - nodes.push(node); - node = node._parent; - } - length = this._length = i; - for (var i = length - 1; i >= 0; --i) { - var stack = nodes[i].stack; - if (stackToIndex[stack] === undefined) { - stackToIndex[stack] = i; - } - } - for (var i = 0; i < length; ++i) { - var currentStack = nodes[i].stack; - var index = stackToIndex[currentStack]; - if (index !== undefined && index !== i) { - if (index > 0) { - nodes[index - 1]._parent = undefined; - nodes[index - 1]._length = 1; - } - nodes[i]._parent = undefined; - nodes[i]._length = 1; - var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; +Query.prototype._optionsForExec = function () { + var options = utils.clone(this.options, { retainKeyOrder: true }); + return options; +} - if (index < length - 1) { - cycleEdgeNode._parent = nodes[index + 1]; - cycleEdgeNode._parent.uncycle(); - cycleEdgeNode._length = - cycleEdgeNode._parent._length + 1; - } else { - cycleEdgeNode._parent = undefined; - cycleEdgeNode._length = 1; - } - var currentChildLength = cycleEdgeNode._length + 1; - for (var j = i - 2; j >= 0; --j) { - nodes[j]._length = currentChildLength; - currentChildLength++; - } - return; - } - } -}; +/** + * Returns fields selection for this query. + * + * @return {Object} + * @api private + */ -CapturedTrace.prototype.parent = function() { - return this._parent; -}; +Query.prototype._fieldsForExec = function () { + return utils.clone(this._fields, { retainKeyOrder: true }); +} -CapturedTrace.prototype.hasParent = function() { - return this._parent !== undefined; -}; +/** + * Return an update document with corrected $set operations. + * + * @api private + */ -CapturedTrace.prototype.attachExtraTrace = function(error) { - if (error.__stackCleaned__) return; - this.uncycle(); - var parsed = CapturedTrace.parseStackAndMessage(error); - var message = parsed.message; - var stacks = [parsed.stack]; +Query.prototype._updateForExec = function () { + var update = utils.clone(this._update, { retainKeyOrder: true }) + , ops = utils.keys(update) + , i = ops.length + , ret = {} + , hasKeys + , val - var trace = this; - while (trace !== undefined) { - stacks.push(cleanStack(trace.stack.split("\n"))); - trace = trace._parent; - } - removeCommonRoots(stacks); - removeDuplicateOrEmptyJumps(stacks); - util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); - util.notEnumerableProp(error, "__stackCleaned__", true); -}; + while (i--) { + var op = ops[i]; -function reconstructStack(message, stacks) { - for (var i = 0; i < stacks.length - 1; ++i) { - stacks[i].push("From previous event:"); - stacks[i] = stacks[i].join("\n"); - } - if (i < stacks.length) { - stacks[i] = stacks[i].join("\n"); + if (this.options.overwrite) { + ret[op] = update[op]; + continue; } - return message + "\n" + stacks.join("\n"); -} -function removeDuplicateOrEmptyJumps(stacks) { - for (var i = 0; i < stacks.length; ++i) { - if (stacks[i].length === 0 || - ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { - stacks.splice(i, 1); - i--; + if ('$' !== op[0]) { + // fix up $set sugar + if (!ret.$set) { + if (update.$set) { + ret.$set = update.$set; + } else { + ret.$set = {}; } + } + ret.$set[op] = update[op]; + ops.splice(i, 1); + if (!~ops.indexOf('$set')) ops.push('$set'); + } else if ('$set' === op) { + if (!ret.$set) { + ret[op] = update[op]; + } + } else { + ret[op] = update[op]; } + } + + this._compiledUpdate = ret; + return ret; } -function removeCommonRoots(stacks) { - var current = stacks[0]; - for (var i = 1; i < stacks.length; ++i) { - var prev = stacks[i]; - var currentLastIndex = current.length - 1; - var currentLastLine = current[currentLastIndex]; - var commonRootMeetPoint = -1; +/** + * Make sure _path is set. + * + * @parmam {String} method + */ - for (var j = prev.length - 1; j >= 0; --j) { - if (prev[j] === currentLastLine) { - commonRootMeetPoint = j; - break; - } - } +Query.prototype._ensurePath = function (method) { + if (!this._path) { + var msg = method + '() must be used after where() ' + + 'when called with these arguments' + throw new Error(msg); + } +} - for (var j = commonRootMeetPoint; j >= 0; --j) { - var line = prev[j]; - if (current[currentLastIndex] === line) { - current.pop(); - currentLastIndex--; - } else { - break; - } - } - current = prev; - } +/*! + * Permissions + */ + +Query.permissions = require('./permissions'); + +Query._isPermitted = function (a, b) { + var denied = Query.permissions[b]; + if (!denied) return true; + return true !== denied[a]; } -function cleanStack(stack) { - var ret = []; - for (var i = 0; i < stack.length; ++i) { - var line = stack[i]; - var isTraceLine = stackFramePattern.test(line) || - " (No stack trace)" === line; - var isInternalFrame = isTraceLine && shouldIgnore(line); - if (isTraceLine && !isInternalFrame) { - if (indentStackFrames && line.charAt(0) !== " ") { - line = " " + line; - } - ret.push(line); - } - } - return ret; +Query.prototype._validate = function (action) { + var fail; + var validator; + + if (undefined === action) { + + validator = Query.permissions[this.op]; + if ('function' != typeof validator) return true; + + fail = validator(this); + + } else if (!Query._isPermitted(action, this.op)) { + fail = action; + } + + if (fail) { + throw new Error(fail + ' cannot be used with ' + this.op); + } } -function stackFramesAsArray(error) { - var stack = error.stack.replace(/\s+$/g, "").split("\n"); - for (var i = 0; i < stack.length; ++i) { - var line = stack[i]; - if (" (No stack trace)" === line || stackFramePattern.test(line)) { - break; - } - } - if (i > 0) { - stack = stack.slice(i); - } - return stack; +/** + * Determines if `conds` can be merged using `mquery().merge()` + * + * @param {Object} conds + * @return {Boolean} + */ + +Query.canMerge = function (conds) { + return conds instanceof Query || utils.isObject(conds); } -CapturedTrace.parseStackAndMessage = function(error) { - var stack = error.stack; - var message = error.toString(); - stack = typeof stack === "string" && stack.length > 0 - ? stackFramesAsArray(error) : [" (No stack trace)"]; - return { - message: message, - stack: cleanStack(stack) - }; -}; +/** + * Set a trace function that will get called whenever a + * query is executed. + * + * See `setTraceFunction()` for details. + * + * @param {Object} conds + * @return {Boolean} + */ +Query.setGlobalTraceFunction = function (traceFunction) { + Query.traceFunction = traceFunction; +} -CapturedTrace.formatAndLogError = function(error, title) { - if (typeof console !== "undefined") { - var message; - if (typeof error === "object" || typeof error === "function") { - var stack = error.stack; - message = title + formatStack(stack, error); - } else { - message = title + String(error); - } - if (typeof warn === "function") { - warn(message); - } else if (typeof console.log === "function" || - typeof console.log === "object") { - console.log(message); - } - } -}; +/*! + * Exports. + */ -CapturedTrace.unhandledRejection = function (reason) { - CapturedTrace.formatAndLogError(reason, "^--- With additional stack trace: "); -}; +Query.utils = utils; +Query.env = require('./env') +Query.Collection = require('./collection'); +Query.BaseCollection = require('./collection/collection'); +Query.Promise = require('bluebird'); +module.exports = exports = Query; -CapturedTrace.isSupported = function () { - return typeof captureStackTrace === "function"; -}; +// TODO +// test utils -CapturedTrace.fireRejectionEvent = -function(name, localHandler, reason, promise) { - var localEventFired = false; - try { - if (typeof localHandler === "function") { - localEventFired = true; - if (name === "rejectionHandled") { - localHandler(promise); - } else { - localHandler(reason, promise); - } - } - } catch (e) { - async.throwLater(e); - } +},{"./collection":84,"./collection/collection":83,"./env":86,"./permissions":88,"./utils":89,"assert":50,"bluebird":90,"debug":72,"sliced":91,"util":98}],88:[function(require,module,exports){ +'use strict'; - var globalEventFired = false; - try { - globalEventFired = fireGlobalEvent(name, reason, promise); - } catch (e) { - globalEventFired = true; - async.throwLater(e); - } +var denied = exports; - var domEventFired = false; - if (fireDomEvent) { - try { - domEventFired = fireDomEvent(name.toLowerCase(), { - reason: reason, - promise: promise - }); - } catch (e) { - domEventFired = true; - async.throwLater(e); - } - } +denied.distinct = function (self) { + if (self._fields && Object.keys(self._fields).length > 0) { + return 'field selection and slice' + } - if (!globalEventFired && !localEventFired && !domEventFired && - name === "unhandledRejection") { - CapturedTrace.formatAndLogError(reason, "Unhandled rejection "); + var keys = Object.keys(denied.distinct); + var err; + + keys.every(function (option) { + if (self.options[option]) { + err = option; + return false; } + return true; + }); + + return err; }; +denied.distinct.select = +denied.distinct.slice = +denied.distinct.sort = +denied.distinct.limit = +denied.distinct.skip = +denied.distinct.batchSize = +denied.distinct.comment = +denied.distinct.maxScan = +denied.distinct.snapshot = +denied.distinct.hint = +denied.distinct.tailable = true; -function formatNonError(obj) { - var str; - if (typeof obj === "function") { - str = "[function " + - (obj.name || "anonymous") + - "]"; - } else { - str = obj.toString(); - var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/; - if (ruselessToString.test(str)) { - try { - var newStr = JSON.stringify(obj); - str = newStr; - } - catch(e) { - } - } - if (str.length === 0) { - str = "(empty array)"; - } - } - return ("(<" + snip(str) + ">, no stack trace)"); -} +// aggregation integration -function snip(str) { - var maxChars = 41; - if (str.length < maxChars) { - return str; - } - return str.substr(0, maxChars - 3) + "..."; -} -var shouldIgnore = function() { return false; }; -var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; -function parseLineInfo(line) { - var matches = line.match(parseLineInfoRegex); - if (matches) { - return { - fileName: matches[1], - line: parseInt(matches[2], 10) - }; +denied.findOneAndUpdate = +denied.findOneAndRemove = function (self) { + var keys = Object.keys(denied.findOneAndUpdate); + var err; + + keys.every(function (option) { + if (self.options[option]) { + err = option; + return false; } + return true; + }); + + return err; } -CapturedTrace.setBounds = function(firstLineError, lastLineError) { - if (!CapturedTrace.isSupported()) return; - var firstStackLines = firstLineError.stack.split("\n"); - var lastStackLines = lastLineError.stack.split("\n"); - var firstIndex = -1; - var lastIndex = -1; - var firstFileName; - var lastFileName; - for (var i = 0; i < firstStackLines.length; ++i) { - var result = parseLineInfo(firstStackLines[i]); - if (result) { - firstFileName = result.fileName; - firstIndex = result.line; - break; - } +denied.findOneAndUpdate.limit = +denied.findOneAndUpdate.skip = +denied.findOneAndUpdate.batchSize = +denied.findOneAndUpdate.maxScan = +denied.findOneAndUpdate.snapshot = +denied.findOneAndUpdate.hint = +denied.findOneAndUpdate.tailable = +denied.findOneAndUpdate.comment = true; + + +denied.count = function (self) { + if (self._fields && Object.keys(self._fields).length > 0) { + return 'field selection and slice' + } + + var keys = Object.keys(denied.count); + var err; + + keys.every(function (option) { + if (self.options[option]) { + err = option; + return false; } - for (var i = 0; i < lastStackLines.length; ++i) { - var result = parseLineInfo(lastStackLines[i]); - if (result) { - lastFileName = result.fileName; - lastIndex = result.line; - break; - } + return true; + }); + + return err; +} + +denied.count.slice = +denied.count.batchSize = +denied.count.comment = +denied.count.maxScan = +denied.count.snapshot = +denied.count.tailable = true; + +},{}],89:[function(require,module,exports){ +(function (process,Buffer){ +'use strict'; + +/*! + * Module dependencies. + */ + +var RegExpClone = require('regexp-clone') + +/** + * Clones objects + * + * @param {Object} obj the object to clone + * @param {Object} options + * @return {Object} the cloned object + * @api private + */ + +var clone = exports.clone = function clone (obj, options) { + if (obj === undefined || obj === null) + return obj; + + if (Array.isArray(obj)) + return exports.cloneArray(obj, options); + + if (obj.constructor) { + if (/ObjectI[dD]$/.test(obj.constructor.name)) { + return 'function' == typeof obj.clone + ? obj.clone() + : new obj.constructor(obj.id); } - if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || - firstFileName !== lastFileName || firstIndex >= lastIndex) { - return; + + if ('ReadPreference' === obj._type && obj.isValid && obj.toObject) { + return 'function' == typeof obj.clone + ? obj.clone() + : new obj.constructor(obj.mode, clone(obj.tags, options)); } - shouldIgnore = function(line) { - if (bluebirdFramePattern.test(line)) return true; - var info = parseLineInfo(line); - if (info) { - if (info.fileName === firstFileName && - (firstIndex <= info.line && info.line <= lastIndex)) { - return true; - } - } - return false; - }; + if ('Binary' == obj._bsontype && obj.buffer && obj.value) { + return 'function' == typeof obj.clone + ? obj.clone() + : new obj.constructor(obj.value(true), obj.sub_type); + } + + if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name) + return new obj.constructor(+obj); + + if ('RegExp' === obj.constructor.name) + return RegExpClone(obj); + + if ('Buffer' === obj.constructor.name) + return exports.cloneBuffer(obj); + } + + if (isObject(obj)) + return exports.cloneObject(obj, options); + + if (obj.valueOf) + return obj.valueOf(); }; -var captureStackTrace = (function stackDetection() { - var v8stackFramePattern = /^\s*at\s*/; - var v8stackFormatter = function(stack, error) { - if (typeof stack === "string") return stack; +/*! + * ignore + */ - if (error.name !== undefined && - error.message !== undefined) { - return error.toString(); - } - return formatNonError(error); - }; +var cloneObject = exports.cloneObject = function cloneObject (obj, options) { + var retainKeyOrder = options && options.retainKeyOrder + , minimize = options && options.minimize + , ret = {} + , hasKeys + , keys + , val + , k + , i - if (typeof Error.stackTraceLimit === "number" && - typeof Error.captureStackTrace === "function") { - Error.stackTraceLimit = Error.stackTraceLimit + 6; - stackFramePattern = v8stackFramePattern; - formatStack = v8stackFormatter; - var captureStackTrace = Error.captureStackTrace; + if (retainKeyOrder) { + for (k in obj) { + val = clone(obj[k], options); - shouldIgnore = function(line) { - return bluebirdFramePattern.test(line); - }; - return function(receiver, ignoreUntil) { - Error.stackTraceLimit = Error.stackTraceLimit + 6; - captureStackTrace(receiver, ignoreUntil); - Error.stackTraceLimit = Error.stackTraceLimit - 6; - }; + if (!minimize || ('undefined' !== typeof val)) { + hasKeys || (hasKeys = true); + ret[k] = val; + } } - var err = new Error(); + } else { + // faster - if (typeof err.stack === "string" && - err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { - stackFramePattern = /@/; - formatStack = v8stackFormatter; - indentStackFrames = true; - return function captureStackTrace(o) { - o.stack = new Error().stack; - }; + keys = Object.keys(obj); + i = keys.length; + + while (i--) { + k = keys[i]; + val = clone(obj[k], options); + + if (!minimize || ('undefined' !== typeof val)) { + if (!hasKeys) hasKeys = true; + ret[k] = val; + } } + } - var hasStackAfterThrow; - try { throw new Error(); } - catch(e) { - hasStackAfterThrow = ("stack" in e); + return minimize + ? hasKeys && ret + : ret; +}; + +var cloneArray = exports.cloneArray = function cloneArray (arr, options) { + var ret = []; + for (var i = 0, l = arr.length; i < l; i++) + ret.push(clone(arr[i], options)); + return ret; +}; + +/** + * process.nextTick helper. + * + * Wraps the given `callback` in a try/catch. If an error is + * caught it will be thrown on nextTick. + * + * node-mongodb-native had a habit of state corruption when + * an error was immediately thrown from within a collection + * method (find, update, etc) callback. + * + * @param {Function} [callback] + * @api private + */ + +var tick = exports.tick = function tick (callback) { + if ('function' !== typeof callback) return; + return function () { + // callbacks should always be fired on the next + // turn of the event loop. A side benefit is + // errors thrown from executing the callback + // will not cause drivers state to be corrupted + // which has historically been a problem. + var args = arguments; + soon(function(){ + callback.apply(this, args); + }); + } +} + +/** + * Merges `from` into `to` without overwriting existing properties. + * + * @param {Object} to + * @param {Object} from + * @api private + */ + +var merge = exports.merge = function merge (to, from) { + var keys = Object.keys(from) + , i = keys.length + , key + + while (i--) { + key = keys[i]; + if ('undefined' === typeof to[key]) { + to[key] = from[key]; + } else { + if (exports.isObject(from[key])) { + merge(to[key], from[key]); + } else { + to[key] = from[key]; + } } - if (!("stack" in err) && hasStackAfterThrow && - typeof Error.stackTraceLimit === "number") { - stackFramePattern = v8stackFramePattern; - formatStack = v8stackFormatter; - return function captureStackTrace(o) { - Error.stackTraceLimit = Error.stackTraceLimit + 6; - try { throw new Error(); } - catch(e) { o.stack = e.stack; } - Error.stackTraceLimit = Error.stackTraceLimit - 6; - }; + } +} + +/** + * Same as merge but clones the assigned values. + * + * @param {Object} to + * @param {Object} from + * @api private + */ + +var mergeClone = exports.mergeClone = function mergeClone (to, from) { + var keys = Object.keys(from) + , i = keys.length + , key + + while (i--) { + key = keys[i]; + if ('undefined' === typeof to[key]) { + // make sure to retain key order here because of a bug handling the $each + // operator in mongodb 2.4.4 + to[key] = clone(from[key], { retainKeyOrder : 1}); + } else { + if (exports.isObject(from[key])) { + mergeClone(to[key], from[key]); + } else { + // make sure to retain key order here because of a bug handling the + // $each operator in mongodb 2.4.4 + to[key] = clone(from[key], { retainKeyOrder : 1}); + } } + } +} - formatStack = function(stack, error) { - if (typeof stack === "string") return stack; +/** + * Read pref helper (mongo 2.2 drivers support this) + * + * Allows using aliases instead of full preference names: + * + * p primary + * pp primaryPreferred + * s secondary + * sp secondaryPreferred + * n nearest + * + * @param {String} pref + */ - if ((typeof error === "object" || - typeof error === "function") && - error.name !== undefined && - error.message !== undefined) { - return error.toString(); - } - return formatNonError(error); - }; +exports.readPref = function readPref (pref) { + switch (pref) { + case 'p': + pref = 'primary'; + break; + case 'pp': + pref = 'primaryPreferred'; + break; + case 's': + pref = 'secondary'; + break; + case 'sp': + pref = 'secondaryPreferred'; + break; + case 'n': + pref = 'nearest'; + break; + } - return null; + return pref; +} -})([]); +/** + * Object.prototype.toString.call helper + */ -var fireDomEvent; -var fireGlobalEvent = (function() { - if (util.isNode) { - return function(name, reason, promise) { - if (name === "rejectionHandled") { - return process.emit(name, promise); - } else { - return process.emit(name, reason, promise); - } - }; - } else { - var customEventWorks = false; - var anyEventWorks = true; - try { - var ev = new self.CustomEvent("test"); - customEventWorks = ev instanceof CustomEvent; - } catch (e) {} - if (!customEventWorks) { - try { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent("testingtheevent", false, true, {}); - self.dispatchEvent(event); - } catch (e) { - anyEventWorks = false; - } - } - if (anyEventWorks) { - fireDomEvent = function(type, detail) { - var event; - if (customEventWorks) { - event = new self.CustomEvent(type, { - detail: detail, - bubbles: false, - cancelable: true - }); - } else if (self.dispatchEvent) { - event = document.createEvent("CustomEvent"); - event.initCustomEvent(type, false, true, detail); - } +var _toString = Object.prototype.toString; +var toString = exports.toString = function (arg) { + return _toString.call(arg); +} - return event ? !self.dispatchEvent(event) : false; - }; - } +/** + * Determines if `arg` is an object. + * + * @param {Object|Array|String|Function|RegExp|any} arg + * @return {Boolean} + */ - var toWindowMethodNameMap = {}; - toWindowMethodNameMap["unhandledRejection"] = ("on" + - "unhandledRejection").toLowerCase(); - toWindowMethodNameMap["rejectionHandled"] = ("on" + - "rejectionHandled").toLowerCase(); +var isObject = exports.isObject = function (arg) { + return '[object Object]' == exports.toString(arg); +} - return function(name, reason, promise) { - var methodName = toWindowMethodNameMap[name]; - var method = self[methodName]; - if (!method) return false; - if (name === "rejectionHandled") { - method.call(self, promise); - } else { - method.call(self, reason, promise); - } - return true; - }; - } -})(); +/** + * Determines if `arg` is an array. + * + * @param {Object} + * @return {Boolean} + * @see nodejs utils + */ -if (typeof console !== "undefined" && typeof console.warn !== "undefined") { - warn = function (message) { - console.warn(message); - }; - if (util.isNode && process.stderr.isTTY) { - warn = function(message) { - process.stderr.write("\u001b[31m" + message + "\u001b[39m\n"); - }; - } else if (!util.isNode && typeof (new Error().stack) === "string") { - warn = function(message) { - console.warn("%c" + message, "color: red"); - }; - } +var isArray = exports.isArray = function (arg) { + return Array.isArray(arg) || + 'object' == typeof arg && '[object Array]' == exports.toString(arg); } -return CapturedTrace; -}; - -},{"./async.js":2,"./util.js":38}],8:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(NEXT_FILTER) { -var util = _dereq_("./util.js"); -var errors = _dereq_("./errors.js"); -var tryCatch = util.tryCatch; -var errorObj = util.errorObj; -var keys = _dereq_("./es5.js").keys; -var TypeError = errors.TypeError; +/** + * Object.keys helper + */ -function CatchFilter(instances, callback, promise) { - this._instances = instances; - this._callback = callback; - this._promise = promise; +exports.keys = Object.keys || function (obj) { + var keys = []; + for (var k in obj) if (obj.hasOwnProperty(k)) { + keys.push(k); + } + return keys; } -function safePredicate(predicate, e) { - var safeObject = {}; - var retfilter = tryCatch(predicate).call(safeObject, e); +/** + * Basic Object.create polyfill. + * Only one argument is supported. + * + * Based on https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create + */ - if (retfilter === errorObj) return retfilter; +exports.create = 'function' == typeof Object.create + ? Object.create + : create; - var safeKeys = keys(safeObject); - if (safeKeys.length) { - errorObj.e = new TypeError("Catch filter must inherit from Error or be a simple predicate function\u000a\u000a See http://goo.gl/o84o68\u000a"); - return errorObj; - } - return retfilter; +function create (proto) { + if (arguments.length > 1) { + throw new Error("Adding properties is not supported") + } + + function F () {} + F.prototype = proto; + return new F; } -CatchFilter.prototype.doFilter = function (e) { - var cb = this._callback; - var promise = this._promise; - var boundTo = promise._boundValue(); - for (var i = 0, len = this._instances.length; i < len; ++i) { - var item = this._instances[i]; - var itemIsErrorType = item === Error || - (item != null && item.prototype instanceof Error); +/** + * inheritance + */ - if (itemIsErrorType && e instanceof item) { - var ret = tryCatch(cb).call(boundTo, e); - if (ret === errorObj) { - NEXT_FILTER.e = ret.e; - return NEXT_FILTER; - } - return ret; - } else if (typeof item === "function" && !itemIsErrorType) { - var shouldHandle = safePredicate(item, e); - if (shouldHandle === errorObj) { - e = errorObj.e; - break; - } else if (shouldHandle) { - var ret = tryCatch(cb).call(boundTo, e); - if (ret === errorObj) { - NEXT_FILTER.e = ret.e; - return NEXT_FILTER; - } - return ret; - } - } - } - NEXT_FILTER.e = e; - return NEXT_FILTER; +exports.inherits = function (ctor, superCtor) { + ctor.prototype = exports.create(superCtor.prototype); + ctor.prototype.constructor = ctor; +} + +/** + * nextTick helper + * compat with node 0.10 which behaves differently than previous versions + */ + +var soon = exports.soon = 'function' == typeof setImmediate + ? setImmediate + : process.nextTick; + +/** + * Clones the contents of a buffer. + * + * @param {Buffer} buff + * @return {Buffer} + */ + +exports.cloneBuffer = function (buff) { + var dupe = new Buffer(buff.length); + buff.copy(dupe, 0, 0, buff.length); + return dupe; }; -return CatchFilter; +/** + * Check if this object is an arguments object + * + * @param {Any} v + * @return {Boolean} + */ + +exports.isArgumentsObject = function(v) { + return Object.prototype.toString.call(v) === '[object Arguments]'; }; -},{"./errors.js":13,"./es5.js":14,"./util.js":38}],9:[function(_dereq_,module,exports){ +}).call(this,require("g5I+bs"),require("buffer").Buffer) +},{"buffer":71,"g5I+bs":94,"regexp-clone":95}],90:[function(require,module,exports){ +(function (process,global){ +/* @preserve + * The MIT License (MIT) + * + * Copyright (c) 2013-2015 Petka Antonov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +/** + * bluebird build version 2.10.2 + * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, cancel, using, filter, any, each, timers +*/ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o= 0) { - return contextStack[lastIndex]; - } - return undefined; -} - -Promise.prototype._peekContext = peekContext; -Promise.prototype._pushContext = Context.prototype._pushContext; -Promise.prototype._popContext = Context.prototype._popContext; +Promise.prototype.any = function () { + return any(this); +}; -return createContext; }; -},{}],10:[function(_dereq_,module,exports){ +},{}],2:[function(_dereq_,module,exports){ "use strict"; -module.exports = function(Promise, CapturedTrace) { -var getDomain = Promise._getDomain; -var async = _dereq_("./async.js"); -var Warning = _dereq_("./errors.js").Warning; +var firstLineError; +try {throw new Error(); } catch (e) {firstLineError = e;} +var schedule = _dereq_("./schedule.js"); +var Queue = _dereq_("./queue.js"); var util = _dereq_("./util.js"); -var canAttachTrace = util.canAttachTrace; -var unhandledRejectionHandled; -var possiblyUnhandledRejection; -var debugging = false || (util.isNode && - (!!process.env["BLUEBIRD_DEBUG"] || - process.env["NODE_ENV"] === "development")); -if (util.isNode && process.env["BLUEBIRD_DEBUG"] == 0) debugging = false; - -if (debugging) { - async.disableTrampolineIfNecessary(); +function Async() { + this._isTickUsed = false; + this._lateQueue = new Queue(16); + this._normalQueue = new Queue(16); + this._trampolineEnabled = true; + var self = this; + this.drainQueues = function () { + self._drainQueues(); + }; + this._schedule = + schedule.isStatic ? schedule(this.drainQueues) : schedule; } -Promise.prototype._ignoreRejections = function() { - this._unsetRejectionIsUnhandled(); - this._bitField = this._bitField | 16777216; +Async.prototype.disableTrampolineIfNecessary = function() { + if (util.hasDevTools) { + this._trampolineEnabled = false; + } }; -Promise.prototype._ensurePossibleRejectionHandled = function () { - if ((this._bitField & 16777216) !== 0) return; - this._setRejectionIsUnhandled(); - async.invokeLater(this._notifyUnhandledRejection, this, undefined); +Async.prototype.enableTrampoline = function() { + if (!this._trampolineEnabled) { + this._trampolineEnabled = true; + this._schedule = function(fn) { + setTimeout(fn, 0); + }; + } }; -Promise.prototype._notifyUnhandledRejectionIsHandled = function () { - CapturedTrace.fireRejectionEvent("rejectionHandled", - unhandledRejectionHandled, undefined, this); +Async.prototype.haveItemsQueued = function () { + return this._normalQueue.length() > 0; }; -Promise.prototype._notifyUnhandledRejection = function () { - if (this._isRejectionUnhandled()) { - var reason = this._getCarriedStackTrace() || this._settledValue; - this._setUnhandledRejectionIsNotified(); - CapturedTrace.fireRejectionEvent("unhandledRejection", - possiblyUnhandledRejection, reason, this); +Async.prototype.throwLater = function(fn, arg) { + if (arguments.length === 1) { + arg = fn; + fn = function () { throw arg; }; + } + if (typeof setTimeout !== "undefined") { + setTimeout(function() { + fn(arg); + }, 0); + } else try { + this._schedule(function() { + fn(arg); + }); + } catch (e) { + throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/m3OTXk\u000a"); } }; -Promise.prototype._setUnhandledRejectionIsNotified = function () { - this._bitField = this._bitField | 524288; -}; +function AsyncInvokeLater(fn, receiver, arg) { + this._lateQueue.push(fn, receiver, arg); + this._queueTick(); +} -Promise.prototype._unsetUnhandledRejectionIsNotified = function () { - this._bitField = this._bitField & (~524288); -}; +function AsyncInvoke(fn, receiver, arg) { + this._normalQueue.push(fn, receiver, arg); + this._queueTick(); +} -Promise.prototype._isUnhandledRejectionNotified = function () { - return (this._bitField & 524288) > 0; -}; +function AsyncSettlePromises(promise) { + this._normalQueue._pushOne(promise); + this._queueTick(); +} -Promise.prototype._setRejectionIsUnhandled = function () { - this._bitField = this._bitField | 2097152; +if (!util.hasDevTools) { + Async.prototype.invokeLater = AsyncInvokeLater; + Async.prototype.invoke = AsyncInvoke; + Async.prototype.settlePromises = AsyncSettlePromises; +} else { + if (schedule.isStatic) { + schedule = function(fn) { setTimeout(fn, 0); }; + } + Async.prototype.invokeLater = function (fn, receiver, arg) { + if (this._trampolineEnabled) { + AsyncInvokeLater.call(this, fn, receiver, arg); + } else { + this._schedule(function() { + setTimeout(function() { + fn.call(receiver, arg); + }, 100); + }); + } + }; + + Async.prototype.invoke = function (fn, receiver, arg) { + if (this._trampolineEnabled) { + AsyncInvoke.call(this, fn, receiver, arg); + } else { + this._schedule(function() { + fn.call(receiver, arg); + }); + } + }; + + Async.prototype.settlePromises = function(promise) { + if (this._trampolineEnabled) { + AsyncSettlePromises.call(this, promise); + } else { + this._schedule(function() { + promise._settlePromises(); + }); + } + }; +} + +Async.prototype.invokeFirst = function (fn, receiver, arg) { + this._normalQueue.unshift(fn, receiver, arg); + this._queueTick(); }; -Promise.prototype._unsetRejectionIsUnhandled = function () { - this._bitField = this._bitField & (~2097152); - if (this._isUnhandledRejectionNotified()) { - this._unsetUnhandledRejectionIsNotified(); - this._notifyUnhandledRejectionIsHandled(); +Async.prototype._drainQueue = function(queue) { + while (queue.length() > 0) { + var fn = queue.shift(); + if (typeof fn !== "function") { + fn._settlePromises(); + continue; + } + var receiver = queue.shift(); + var arg = queue.shift(); + fn.call(receiver, arg); } }; -Promise.prototype._isRejectionUnhandled = function () { - return (this._bitField & 2097152) > 0; +Async.prototype._drainQueues = function () { + this._drainQueue(this._normalQueue); + this._reset(); + this._drainQueue(this._lateQueue); }; -Promise.prototype._setCarriedStackTrace = function (capturedTrace) { - this._bitField = this._bitField | 1048576; - this._fulfillmentHandler0 = capturedTrace; +Async.prototype._queueTick = function () { + if (!this._isTickUsed) { + this._isTickUsed = true; + this._schedule(this.drainQueues); + } }; -Promise.prototype._isCarryingStackTrace = function () { - return (this._bitField & 1048576) > 0; +Async.prototype._reset = function () { + this._isTickUsed = false; }; -Promise.prototype._getCarriedStackTrace = function () { - return this._isCarryingStackTrace() - ? this._fulfillmentHandler0 - : undefined; -}; +module.exports = new Async(); +module.exports.firstLineError = firstLineError; -Promise.prototype._captureStackTrace = function () { - if (debugging) { - this._trace = new CapturedTrace(this._peekContext()); - } - return this; +},{"./queue.js":28,"./schedule.js":31,"./util.js":38}],3:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise) { +var rejectThis = function(_, e) { + this._reject(e); }; - -Promise.prototype._attachExtraTrace = function (error, ignoreSelf) { - if (debugging && canAttachTrace(error)) { - var trace = this._trace; - if (trace !== undefined) { - if (ignoreSelf) trace = trace._parent; - } - if (trace !== undefined) { - trace.attachExtraTrace(error); - } else if (!error.__stackCleaned__) { - var parsed = CapturedTrace.parseStackAndMessage(error); - util.notEnumerableProp(error, "stack", - parsed.message + "\n" + parsed.stack.join("\n")); - util.notEnumerableProp(error, "__stackCleaned__", true); - } - } + +var targetRejected = function(e, context) { + context.promiseRejectionQueued = true; + context.bindingPromise._then(rejectThis, rejectThis, null, this, e); }; -Promise.prototype._warn = function(message) { - var warning = new Warning(message); - var ctx = this._peekContext(); - if (ctx) { - ctx.attachExtraTrace(warning); - } else { - var parsed = CapturedTrace.parseStackAndMessage(warning); - warning.stack = parsed.message + "\n" + parsed.stack.join("\n"); +var bindingResolved = function(thisArg, context) { + if (this._isPending()) { + this._resolveCallback(context.target); } - CapturedTrace.formatAndLogError(warning, ""); }; -Promise.onPossiblyUnhandledRejection = function (fn) { - var domain = getDomain(); - possiblyUnhandledRejection = - typeof fn === "function" ? (domain === null ? fn : domain.bind(fn)) - : undefined; +var bindingRejected = function(e, context) { + if (!context.promiseRejectionQueued) this._reject(e); }; -Promise.onUnhandledRejectionHandled = function (fn) { - var domain = getDomain(); - unhandledRejectionHandled = - typeof fn === "function" ? (domain === null ? fn : domain.bind(fn)) - : undefined; -}; +Promise.prototype.bind = function (thisArg) { + var maybePromise = tryConvertToPromise(thisArg); + var ret = new Promise(INTERNAL); + ret._propagateFrom(this, 1); + var target = this._target(); -Promise.longStackTraces = function () { - if (async.haveItemsQueued() && - debugging === false - ) { - throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/DT1qyG\u000a"); + ret._setBoundTo(maybePromise); + if (maybePromise instanceof Promise) { + var context = { + promiseRejectionQueued: false, + promise: ret, + target: target, + bindingPromise: maybePromise + }; + target._then(INTERNAL, targetRejected, ret._progress, ret, context); + maybePromise._then( + bindingResolved, bindingRejected, ret._progress, ret, context); + } else { + ret._resolveCallback(target); } - debugging = CapturedTrace.isSupported(); - if (debugging) { - async.disableTrampolineIfNecessary(); + return ret; +}; + +Promise.prototype._setBoundTo = function (obj) { + if (obj !== undefined) { + this._bitField = this._bitField | 131072; + this._boundTo = obj; + } else { + this._bitField = this._bitField & (~131072); } }; -Promise.hasLongStackTraces = function () { - return debugging && CapturedTrace.isSupported(); +Promise.prototype._isBound = function () { + return (this._bitField & 131072) === 131072; }; -if (!CapturedTrace.isSupported()) { - Promise.longStackTraces = function(){}; - debugging = false; -} +Promise.bind = function (thisArg, value) { + var maybePromise = tryConvertToPromise(thisArg); + var ret = new Promise(INTERNAL); -return function() { - return debugging; + ret._setBoundTo(maybePromise); + if (maybePromise instanceof Promise) { + maybePromise._then(function() { + ret._resolveCallback(value); + }, ret._reject, ret._progress, ret, null); + } else { + ret._resolveCallback(value); + } + return ret; }; }; -},{"./async.js":2,"./errors.js":13,"./util.js":38}],11:[function(_dereq_,module,exports){ +},{}],4:[function(_dereq_,module,exports){ "use strict"; -var util = _dereq_("./util.js"); -var isPrimitive = util.isPrimitive; +var old; +if (typeof Promise !== "undefined") old = Promise; +function noConflict() { + try { if (Promise === bluebird) Promise = old; } + catch (e) {} + return bluebird; +} +var bluebird = _dereq_("./promise.js")(); +bluebird.noConflict = noConflict; +module.exports = bluebird; + +},{"./promise.js":23}],5:[function(_dereq_,module,exports){ +"use strict"; +var cr = Object.create; +if (cr) { + var callerCache = cr(null); + var getterCache = cr(null); + callerCache[" size"] = getterCache[" size"] = 0; +} module.exports = function(Promise) { -var returner = function () { - return this; -}; -var thrower = function () { - throw this; +var util = _dereq_("./util.js"); +var canEvaluate = util.canEvaluate; +var isIdentifier = util.isIdentifier; + +var getMethodCaller; +var getGetter; +if (!true) { +var makeMethodCaller = function (methodName) { + return new Function("ensureMethod", " \n\ + return function(obj) { \n\ + 'use strict' \n\ + var len = this.length; \n\ + ensureMethod(obj, 'methodName'); \n\ + switch(len) { \n\ + case 1: return obj.methodName(this[0]); \n\ + case 2: return obj.methodName(this[0], this[1]); \n\ + case 3: return obj.methodName(this[0], this[1], this[2]); \n\ + case 0: return obj.methodName(); \n\ + default: \n\ + return obj.methodName.apply(obj, this); \n\ + } \n\ + }; \n\ + ".replace(/methodName/g, methodName))(ensureMethod); }; -var returnUndefined = function() {}; -var throwUndefined = function() { - throw undefined; + +var makeGetter = function (propertyName) { + return new Function("obj", " \n\ + 'use strict'; \n\ + return obj.propertyName; \n\ + ".replace("propertyName", propertyName)); }; -var wrapper = function (value, action) { - if (action === 1) { - return function () { - throw value; - }; - } else if (action === 2) { - return function () { - return value; - }; +var getCompiled = function(name, compiler, cache) { + var ret = cache[name]; + if (typeof ret !== "function") { + if (!isIdentifier(name)) { + return null; + } + ret = compiler(name); + cache[name] = ret; + cache[" size"]++; + if (cache[" size"] > 512) { + var keys = Object.keys(cache); + for (var i = 0; i < 256; ++i) delete cache[keys[i]]; + cache[" size"] = keys.length - 256; + } } + return ret; }; +getMethodCaller = function(name) { + return getCompiled(name, makeMethodCaller, callerCache); +}; -Promise.prototype["return"] = -Promise.prototype.thenReturn = function (value) { - if (value === undefined) return this.then(returnUndefined); +getGetter = function(name) { + return getCompiled(name, makeGetter, getterCache); +}; +} - if (isPrimitive(value)) { - return this._then( - wrapper(value, 2), - undefined, - undefined, - undefined, - undefined - ); - } else if (value instanceof Promise) { - value._ignoreRejections(); +function ensureMethod(obj, methodName) { + var fn; + if (obj != null) fn = obj[methodName]; + if (typeof fn !== "function") { + var message = "Object " + util.classString(obj) + " has no method '" + + util.toString(methodName) + "'"; + throw new Promise.TypeError(message); } - return this._then(returner, undefined, undefined, value, undefined); + return fn; +} + +function caller(obj) { + var methodName = this.pop(); + var fn = ensureMethod(obj, methodName); + return fn.apply(obj, this); +} +Promise.prototype.call = function (methodName) { + var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];} + if (!true) { + if (canEvaluate) { + var maybeCaller = getMethodCaller(methodName); + if (maybeCaller !== null) { + return this._then( + maybeCaller, undefined, undefined, args, undefined); + } + } + } + args.push(methodName); + return this._then(caller, undefined, undefined, args, undefined); }; -Promise.prototype["throw"] = -Promise.prototype.thenThrow = function (reason) { - if (reason === undefined) return this.then(throwUndefined); +function namedGetter(obj) { + return obj[this]; +} +function indexedGetter(obj) { + var index = +this; + if (index < 0) index = Math.max(0, index + obj.length); + return obj[index]; +} +Promise.prototype.get = function (propertyName) { + var isIndex = (typeof propertyName === "number"); + var getter; + if (!isIndex) { + if (canEvaluate) { + var maybeGetter = getGetter(propertyName); + getter = maybeGetter !== null ? maybeGetter : namedGetter; + } else { + getter = namedGetter; + } + } else { + getter = indexedGetter; + } + return this._then(getter, undefined, undefined, propertyName, undefined); +}; +}; - if (isPrimitive(reason)) { - return this._then( - wrapper(reason, 1), - undefined, - undefined, - undefined, - undefined - ); +},{"./util.js":38}],6:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +var errors = _dereq_("./errors.js"); +var async = _dereq_("./async.js"); +var CancellationError = errors.CancellationError; + +Promise.prototype._cancel = function (reason) { + if (!this.isCancellable()) return this; + var parent; + var promiseToReject = this; + while ((parent = promiseToReject._cancellationParent) !== undefined && + parent.isCancellable()) { + promiseToReject = parent; } - return this._then(thrower, undefined, undefined, reason, undefined); + this._unsetCancellable(); + promiseToReject._target()._rejectCallback(reason, false, true); }; + +Promise.prototype.cancel = function (reason) { + if (!this.isCancellable()) return this; + if (reason === undefined) reason = new CancellationError(); + async.invokeLater(this._cancel, this, reason); + return this; }; -},{"./util.js":38}],12:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, INTERNAL) { -var PromiseReduce = Promise.reduce; +Promise.prototype.cancellable = function () { + if (this._cancellable()) return this; + async.enableTrampoline(); + this._setCancellable(); + this._cancellationParent = undefined; + return this; +}; -Promise.prototype.each = function (fn) { - return PromiseReduce(this, fn, null, INTERNAL); +Promise.prototype.uncancellable = function () { + var ret = this.then(); + ret._unsetCancellable(); + return ret; }; -Promise.each = function (promises, fn) { - return PromiseReduce(promises, fn, null, INTERNAL); +Promise.prototype.fork = function (didFulfill, didReject, didProgress) { + var ret = this._then(didFulfill, didReject, didProgress, + undefined, undefined); + + ret._setCancellable(); + ret._cancellationParent = undefined; + return ret; }; }; -},{}],13:[function(_dereq_,module,exports){ +},{"./async.js":2,"./errors.js":13}],7:[function(_dereq_,module,exports){ "use strict"; -var es5 = _dereq_("./es5.js"); -var Objectfreeze = es5.freeze; +module.exports = function() { +var async = _dereq_("./async.js"); var util = _dereq_("./util.js"); -var inherits = util.inherits; -var notEnumerableProp = util.notEnumerableProp; - -function subError(nameProperty, defaultMessage) { - function SubError(message) { - if (!(this instanceof SubError)) return new SubError(message); - notEnumerableProp(this, "message", - typeof message === "string" ? message : defaultMessage); - notEnumerableProp(this, "name", nameProperty); - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } else { - Error.call(this); - } - } - inherits(SubError, Error); - return SubError; -} +var bluebirdFramePattern = + /[\\\/]bluebird[\\\/]js[\\\/](main|debug|zalgo|instrumented)/; +var stackFramePattern = null; +var formatStack = null; +var indentStackFrames = false; +var warn; -var _TypeError, _RangeError; -var Warning = subError("Warning", "warning"); -var CancellationError = subError("CancellationError", "cancellation error"); -var TimeoutError = subError("TimeoutError", "timeout error"); -var AggregateError = subError("AggregateError", "aggregate error"); -try { - _TypeError = TypeError; - _RangeError = RangeError; -} catch(e) { - _TypeError = subError("TypeError", "type error"); - _RangeError = subError("RangeError", "range error"); +function CapturedTrace(parent) { + this._parent = parent; + var length = this._length = 1 + (parent === undefined ? 0 : parent._length); + captureStackTrace(this, CapturedTrace); + if (length > 32) this.uncycle(); } +util.inherits(CapturedTrace, Error); -var methods = ("join pop push shift unshift slice filter forEach some " + - "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" "); +CapturedTrace.prototype.uncycle = function() { + var length = this._length; + if (length < 2) return; + var nodes = []; + var stackToIndex = {}; -for (var i = 0; i < methods.length; ++i) { - if (typeof Array.prototype[methods[i]] === "function") { - AggregateError.prototype[methods[i]] = Array.prototype[methods[i]]; + for (var i = 0, node = this; node !== undefined; ++i) { + nodes.push(node); + node = node._parent; } -} + length = this._length = i; + for (var i = length - 1; i >= 0; --i) { + var stack = nodes[i].stack; + if (stackToIndex[stack] === undefined) { + stackToIndex[stack] = i; + } + } + for (var i = 0; i < length; ++i) { + var currentStack = nodes[i].stack; + var index = stackToIndex[currentStack]; + if (index !== undefined && index !== i) { + if (index > 0) { + nodes[index - 1]._parent = undefined; + nodes[index - 1]._length = 1; + } + nodes[i]._parent = undefined; + nodes[i]._length = 1; + var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; -es5.defineProperty(AggregateError.prototype, "length", { - value: 0, - configurable: false, - writable: true, - enumerable: true -}); -AggregateError.prototype["isOperational"] = true; -var level = 0; -AggregateError.prototype.toString = function() { - var indent = Array(level * 4 + 1).join(" "); - var ret = "\n" + indent + "AggregateError of:" + "\n"; - level++; - indent = Array(level * 4 + 1).join(" "); - for (var i = 0; i < this.length; ++i) { - var str = this[i] === this ? "[Circular AggregateError]" : this[i] + ""; - var lines = str.split("\n"); - for (var j = 0; j < lines.length; ++j) { - lines[j] = indent + lines[j]; + if (index < length - 1) { + cycleEdgeNode._parent = nodes[index + 1]; + cycleEdgeNode._parent.uncycle(); + cycleEdgeNode._length = + cycleEdgeNode._parent._length + 1; + } else { + cycleEdgeNode._parent = undefined; + cycleEdgeNode._length = 1; + } + var currentChildLength = cycleEdgeNode._length + 1; + for (var j = i - 2; j >= 0; --j) { + nodes[j]._length = currentChildLength; + currentChildLength++; + } + return; } - str = lines.join("\n"); - ret += str + "\n"; } - level--; - return ret; }; -function OperationalError(message) { - if (!(this instanceof OperationalError)) - return new OperationalError(message); - notEnumerableProp(this, "name", "OperationalError"); - notEnumerableProp(this, "message", message); - this.cause = message; - this["isOperational"] = true; - - if (message instanceof Error) { - notEnumerableProp(this, "message", message.message); - notEnumerableProp(this, "stack", message.stack); - } else if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } +CapturedTrace.prototype.parent = function() { + return this._parent; +}; -} -inherits(OperationalError, Error); +CapturedTrace.prototype.hasParent = function() { + return this._parent !== undefined; +}; -var errorTypes = Error["__BluebirdErrorTypes__"]; -if (!errorTypes) { - errorTypes = Objectfreeze({ - CancellationError: CancellationError, - TimeoutError: TimeoutError, - OperationalError: OperationalError, - RejectionError: OperationalError, - AggregateError: AggregateError - }); - notEnumerableProp(Error, "__BluebirdErrorTypes__", errorTypes); -} +CapturedTrace.prototype.attachExtraTrace = function(error) { + if (error.__stackCleaned__) return; + this.uncycle(); + var parsed = CapturedTrace.parseStackAndMessage(error); + var message = parsed.message; + var stacks = [parsed.stack]; -module.exports = { - Error: Error, - TypeError: _TypeError, - RangeError: _RangeError, - CancellationError: errorTypes.CancellationError, - OperationalError: errorTypes.OperationalError, - TimeoutError: errorTypes.TimeoutError, - AggregateError: errorTypes.AggregateError, - Warning: Warning + var trace = this; + while (trace !== undefined) { + stacks.push(cleanStack(trace.stack.split("\n"))); + trace = trace._parent; + } + removeCommonRoots(stacks); + removeDuplicateOrEmptyJumps(stacks); + util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); + util.notEnumerableProp(error, "__stackCleaned__", true); }; -},{"./es5.js":14,"./util.js":38}],14:[function(_dereq_,module,exports){ -var isES5 = (function(){ - "use strict"; - return this === undefined; -})(); +function reconstructStack(message, stacks) { + for (var i = 0; i < stacks.length - 1; ++i) { + stacks[i].push("From previous event:"); + stacks[i] = stacks[i].join("\n"); + } + if (i < stacks.length) { + stacks[i] = stacks[i].join("\n"); + } + return message + "\n" + stacks.join("\n"); +} -if (isES5) { - module.exports = { - freeze: Object.freeze, - defineProperty: Object.defineProperty, - getDescriptor: Object.getOwnPropertyDescriptor, - keys: Object.keys, - names: Object.getOwnPropertyNames, - getPrototypeOf: Object.getPrototypeOf, - isArray: Array.isArray, - isES5: isES5, - propertyIsWritable: function(obj, prop) { - var descriptor = Object.getOwnPropertyDescriptor(obj, prop); - return !!(!descriptor || descriptor.writable || descriptor.set); +function removeDuplicateOrEmptyJumps(stacks) { + for (var i = 0; i < stacks.length; ++i) { + if (stacks[i].length === 0 || + ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { + stacks.splice(i, 1); + i--; + } + } +} + +function removeCommonRoots(stacks) { + var current = stacks[0]; + for (var i = 1; i < stacks.length; ++i) { + var prev = stacks[i]; + var currentLastIndex = current.length - 1; + var currentLastLine = current[currentLastIndex]; + var commonRootMeetPoint = -1; + + for (var j = prev.length - 1; j >= 0; --j) { + if (prev[j] === currentLastLine) { + commonRootMeetPoint = j; + break; + } } - }; -} else { - var has = {}.hasOwnProperty; - var str = {}.toString; - var proto = {}.constructor.prototype; - var ObjectKeys = function (o) { - var ret = []; - for (var key in o) { - if (has.call(o, key)) { - ret.push(key); + for (var j = commonRootMeetPoint; j >= 0; --j) { + var line = prev[j]; + if (current[currentLastIndex] === line) { + current.pop(); + currentLastIndex--; + } else { + break; } } - return ret; - }; + current = prev; + } +} - var ObjectGetDescriptor = function(o, key) { - return {value: o[key]}; - }; +function cleanStack(stack) { + var ret = []; + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + var isTraceLine = stackFramePattern.test(line) || + " (No stack trace)" === line; + var isInternalFrame = isTraceLine && shouldIgnore(line); + if (isTraceLine && !isInternalFrame) { + if (indentStackFrames && line.charAt(0) !== " ") { + line = " " + line; + } + ret.push(line); + } + } + return ret; +} - var ObjectDefineProperty = function (o, key, desc) { - o[key] = desc.value; - return o; - }; +function stackFramesAsArray(error) { + var stack = error.stack.replace(/\s+$/g, "").split("\n"); + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + if (" (No stack trace)" === line || stackFramePattern.test(line)) { + break; + } + } + if (i > 0) { + stack = stack.slice(i); + } + return stack; +} - var ObjectFreeze = function (obj) { - return obj; +CapturedTrace.parseStackAndMessage = function(error) { + var stack = error.stack; + var message = error.toString(); + stack = typeof stack === "string" && stack.length > 0 + ? stackFramesAsArray(error) : [" (No stack trace)"]; + return { + message: message, + stack: cleanStack(stack) }; +}; - var ObjectGetPrototypeOf = function (obj) { - try { - return Object(obj).constructor.prototype; +CapturedTrace.formatAndLogError = function(error, title) { + if (typeof console !== "undefined") { + var message; + if (typeof error === "object" || typeof error === "function") { + var stack = error.stack; + message = title + formatStack(stack, error); + } else { + message = title + String(error); } - catch (e) { - return proto; + if (typeof warn === "function") { + warn(message); + } else if (typeof console.log === "function" || + typeof console.log === "object") { + console.log(message); } - }; + } +}; - var ArrayIsArray = function (obj) { - try { - return str.call(obj) === "[object Array]"; - } - catch(e) { - return false; - } - }; +CapturedTrace.unhandledRejection = function (reason) { + CapturedTrace.formatAndLogError(reason, "^--- With additional stack trace: "); +}; - module.exports = { - isArray: ArrayIsArray, - keys: ObjectKeys, - names: ObjectKeys, - defineProperty: ObjectDefineProperty, - getDescriptor: ObjectGetDescriptor, - freeze: ObjectFreeze, - getPrototypeOf: ObjectGetPrototypeOf, - isES5: isES5, - propertyIsWritable: function() { - return true; +CapturedTrace.isSupported = function () { + return typeof captureStackTrace === "function"; +}; + +CapturedTrace.fireRejectionEvent = +function(name, localHandler, reason, promise) { + var localEventFired = false; + try { + if (typeof localHandler === "function") { + localEventFired = true; + if (name === "rejectionHandled") { + localHandler(promise); + } else { + localHandler(reason, promise); + } } - }; -} + } catch (e) { + async.throwLater(e); + } -},{}],15:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, INTERNAL) { -var PromiseMap = Promise.map; + var globalEventFired = false; + try { + globalEventFired = fireGlobalEvent(name, reason, promise); + } catch (e) { + globalEventFired = true; + async.throwLater(e); + } -Promise.prototype.filter = function (fn, options) { - return PromiseMap(this, fn, options, INTERNAL); -}; + var domEventFired = false; + if (fireDomEvent) { + try { + domEventFired = fireDomEvent(name.toLowerCase(), { + reason: reason, + promise: promise + }); + } catch (e) { + domEventFired = true; + async.throwLater(e); + } + } -Promise.filter = function (promises, fn, options) { - return PromiseMap(promises, fn, options, INTERNAL); -}; + if (!globalEventFired && !localEventFired && !domEventFired && + name === "unhandledRejection") { + CapturedTrace.formatAndLogError(reason, "Unhandled rejection "); + } }; -},{}],16:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, NEXT_FILTER, tryConvertToPromise) { -var util = _dereq_("./util.js"); -var isPrimitive = util.isPrimitive; -var thrower = util.thrower; +function formatNonError(obj) { + var str; + if (typeof obj === "function") { + str = "[function " + + (obj.name || "anonymous") + + "]"; + } else { + str = obj.toString(); + var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/; + if (ruselessToString.test(str)) { + try { + var newStr = JSON.stringify(obj); + str = newStr; + } + catch(e) { -function returnThis() { - return this; -} -function throwThis() { - throw this; + } + } + if (str.length === 0) { + str = "(empty array)"; + } + } + return ("(<" + snip(str) + ">, no stack trace)"); } -function return$(r) { - return function() { - return r; - }; + +function snip(str) { + var maxChars = 41; + if (str.length < maxChars) { + return str; + } + return str.substr(0, maxChars - 3) + "..."; } -function throw$(r) { - return function() { - throw r; - }; + +var shouldIgnore = function() { return false; }; +var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; +function parseLineInfo(line) { + var matches = line.match(parseLineInfoRegex); + if (matches) { + return { + fileName: matches[1], + line: parseInt(matches[2], 10) + }; + } } -function promisedFinally(ret, reasonOrValue, isFulfilled) { - var then; - if (isPrimitive(reasonOrValue)) { - then = isFulfilled ? return$(reasonOrValue) : throw$(reasonOrValue); - } else { - then = isFulfilled ? returnThis : throwThis; +CapturedTrace.setBounds = function(firstLineError, lastLineError) { + if (!CapturedTrace.isSupported()) return; + var firstStackLines = firstLineError.stack.split("\n"); + var lastStackLines = lastLineError.stack.split("\n"); + var firstIndex = -1; + var lastIndex = -1; + var firstFileName; + var lastFileName; + for (var i = 0; i < firstStackLines.length; ++i) { + var result = parseLineInfo(firstStackLines[i]); + if (result) { + firstFileName = result.fileName; + firstIndex = result.line; + break; + } } - return ret._then(then, thrower, undefined, reasonOrValue, undefined); -} - -function finallyHandler(reasonOrValue) { - var promise = this.promise; - var handler = this.handler; - - var ret = promise._isBound() - ? handler.call(promise._boundValue()) - : handler(); - - if (ret !== undefined) { - var maybePromise = tryConvertToPromise(ret, promise); - if (maybePromise instanceof Promise) { - maybePromise = maybePromise._target(); - return promisedFinally(maybePromise, reasonOrValue, - promise.isFulfilled()); + for (var i = 0; i < lastStackLines.length; ++i) { + var result = parseLineInfo(lastStackLines[i]); + if (result) { + lastFileName = result.fileName; + lastIndex = result.line; + break; } } - - if (promise.isRejected()) { - NEXT_FILTER.e = reasonOrValue; - return NEXT_FILTER; - } else { - return reasonOrValue; + if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || + firstFileName !== lastFileName || firstIndex >= lastIndex) { + return; } -} - -function tapHandler(value) { - var promise = this.promise; - var handler = this.handler; - - var ret = promise._isBound() - ? handler.call(promise._boundValue(), value) - : handler(value); - if (ret !== undefined) { - var maybePromise = tryConvertToPromise(ret, promise); - if (maybePromise instanceof Promise) { - maybePromise = maybePromise._target(); - return promisedFinally(maybePromise, value, true); + shouldIgnore = function(line) { + if (bluebirdFramePattern.test(line)) return true; + var info = parseLineInfo(line); + if (info) { + if (info.fileName === firstFileName && + (firstIndex <= info.line && info.line <= lastIndex)) { + return true; + } } - } - return value; -} + return false; + }; +}; -Promise.prototype._passThroughHandler = function (handler, isFinally) { - if (typeof handler !== "function") return this.then(); +var captureStackTrace = (function stackDetection() { + var v8stackFramePattern = /^\s*at\s*/; + var v8stackFormatter = function(stack, error) { + if (typeof stack === "string") return stack; - var promiseAndHandler = { - promise: this, - handler: handler + if (error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); }; - return this._then( - isFinally ? finallyHandler : tapHandler, - isFinally ? finallyHandler : undefined, undefined, - promiseAndHandler, undefined); -}; - -Promise.prototype.lastly = -Promise.prototype["finally"] = function (handler) { - return this._passThroughHandler(handler, true); -}; + if (typeof Error.stackTraceLimit === "number" && + typeof Error.captureStackTrace === "function") { + Error.stackTraceLimit = Error.stackTraceLimit + 6; + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + var captureStackTrace = Error.captureStackTrace; -Promise.prototype.tap = function (handler) { - return this._passThroughHandler(handler, false); -}; -}; + shouldIgnore = function(line) { + return bluebirdFramePattern.test(line); + }; + return function(receiver, ignoreUntil) { + Error.stackTraceLimit = Error.stackTraceLimit + 6; + captureStackTrace(receiver, ignoreUntil); + Error.stackTraceLimit = Error.stackTraceLimit - 6; + }; + } + var err = new Error(); -},{"./util.js":38}],17:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, - apiRejection, - INTERNAL, - tryConvertToPromise) { -var errors = _dereq_("./errors.js"); -var TypeError = errors.TypeError; -var util = _dereq_("./util.js"); -var errorObj = util.errorObj; -var tryCatch = util.tryCatch; -var yieldHandlers = []; + if (typeof err.stack === "string" && + err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { + stackFramePattern = /@/; + formatStack = v8stackFormatter; + indentStackFrames = true; + return function captureStackTrace(o) { + o.stack = new Error().stack; + }; + } -function promiseFromYieldHandler(value, yieldHandlers, traceParent) { - for (var i = 0; i < yieldHandlers.length; ++i) { - traceParent._pushContext(); - var result = tryCatch(yieldHandlers[i])(value); - traceParent._popContext(); - if (result === errorObj) { - traceParent._pushContext(); - var ret = Promise.reject(errorObj.e); - traceParent._popContext(); - return ret; - } - var maybePromise = tryConvertToPromise(result, traceParent); - if (maybePromise instanceof Promise) return maybePromise; + var hasStackAfterThrow; + try { throw new Error(); } + catch(e) { + hasStackAfterThrow = ("stack" in e); + } + if (!("stack" in err) && hasStackAfterThrow && + typeof Error.stackTraceLimit === "number") { + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + return function captureStackTrace(o) { + Error.stackTraceLimit = Error.stackTraceLimit + 6; + try { throw new Error(); } + catch(e) { o.stack = e.stack; } + Error.stackTraceLimit = Error.stackTraceLimit - 6; + }; } - return null; -} -function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) { - var promise = this._promise = new Promise(INTERNAL); - promise._captureStackTrace(); - this._stack = stack; - this._generatorFunction = generatorFunction; - this._receiver = receiver; - this._generator = undefined; - this._yieldHandlers = typeof yieldHandler === "function" - ? [yieldHandler].concat(yieldHandlers) - : yieldHandlers; -} + formatStack = function(stack, error) { + if (typeof stack === "string") return stack; -PromiseSpawn.prototype.promise = function () { - return this._promise; -}; + if ((typeof error === "object" || + typeof error === "function") && + error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; -PromiseSpawn.prototype._run = function () { - this._generator = this._generatorFunction.call(this._receiver); - this._receiver = - this._generatorFunction = undefined; - this._next(undefined); -}; + return null; -PromiseSpawn.prototype._continue = function (result) { - if (result === errorObj) { - return this._promise._rejectCallback(result.e, false, true); - } +})([]); - var value = result.value; - if (result.done === true) { - this._promise._resolveCallback(value); +var fireDomEvent; +var fireGlobalEvent = (function() { + if (util.isNode) { + return function(name, reason, promise) { + if (name === "rejectionHandled") { + return process.emit(name, promise); + } else { + return process.emit(name, reason, promise); + } + }; } else { - var maybePromise = tryConvertToPromise(value, this._promise); - if (!(maybePromise instanceof Promise)) { - maybePromise = - promiseFromYieldHandler(maybePromise, - this._yieldHandlers, - this._promise); - if (maybePromise === null) { - this._throw( - new TypeError( - "A value %s was yielded that could not be treated as a promise\u000a\u000a See http://goo.gl/4Y4pDk\u000a\u000a".replace("%s", value) + - "From coroutine:\u000a" + - this._stack.split("\n").slice(1, -7).join("\n") - ) - ); - return; + var customEventWorks = false; + var anyEventWorks = true; + try { + var ev = new self.CustomEvent("test"); + customEventWorks = ev instanceof CustomEvent; + } catch (e) {} + if (!customEventWorks) { + try { + var event = document.createEvent("CustomEvent"); + event.initCustomEvent("testingtheevent", false, true, {}); + self.dispatchEvent(event); + } catch (e) { + anyEventWorks = false; } } - maybePromise._then( - this._next, - this._throw, - undefined, - this, - null - ); - } -}; + if (anyEventWorks) { + fireDomEvent = function(type, detail) { + var event; + if (customEventWorks) { + event = new self.CustomEvent(type, { + detail: detail, + bubbles: false, + cancelable: true + }); + } else if (self.dispatchEvent) { + event = document.createEvent("CustomEvent"); + event.initCustomEvent(type, false, true, detail); + } -PromiseSpawn.prototype._throw = function (reason) { - this._promise._attachExtraTrace(reason); - this._promise._pushContext(); - var result = tryCatch(this._generator["throw"]) - .call(this._generator, reason); - this._promise._popContext(); - this._continue(result); -}; + return event ? !self.dispatchEvent(event) : false; + }; + } -PromiseSpawn.prototype._next = function (value) { - this._promise._pushContext(); - var result = tryCatch(this._generator.next).call(this._generator, value); - this._promise._popContext(); - this._continue(result); -}; + var toWindowMethodNameMap = {}; + toWindowMethodNameMap["unhandledRejection"] = ("on" + + "unhandledRejection").toLowerCase(); + toWindowMethodNameMap["rejectionHandled"] = ("on" + + "rejectionHandled").toLowerCase(); -Promise.coroutine = function (generatorFunction, options) { - if (typeof generatorFunction !== "function") { - throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/6Vqhm0\u000a"); + return function(name, reason, promise) { + var methodName = toWindowMethodNameMap[name]; + var method = self[methodName]; + if (!method) return false; + if (name === "rejectionHandled") { + method.call(self, promise); + } else { + method.call(self, reason, promise); + } + return true; + }; } - var yieldHandler = Object(options).yieldHandler; - var PromiseSpawn$ = PromiseSpawn; - var stack = new Error().stack; - return function () { - var generator = generatorFunction.apply(this, arguments); - var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler, - stack); - spawn._generator = generator; - spawn._next(undefined); - return spawn.promise(); - }; -}; - -Promise.coroutine.addYieldHandler = function(fn) { - if (typeof fn !== "function") throw new TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); - yieldHandlers.push(fn); -}; +})(); -Promise.spawn = function (generatorFunction) { - if (typeof generatorFunction !== "function") { - return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/6Vqhm0\u000a"); +if (typeof console !== "undefined" && typeof console.warn !== "undefined") { + warn = function (message) { + console.warn(message); + }; + if (util.isNode && process.stderr.isTTY) { + warn = function(message) { + process.stderr.write("\u001b[31m" + message + "\u001b[39m\n"); + }; + } else if (!util.isNode && typeof (new Error().stack) === "string") { + warn = function(message) { + console.warn("%c" + message, "color: red"); + }; } - var spawn = new PromiseSpawn(generatorFunction, this); - var ret = spawn.promise(); - spawn._run(Promise.spawn); - return ret; -}; +} + +return CapturedTrace; }; -},{"./errors.js":13,"./util.js":38}],18:[function(_dereq_,module,exports){ +},{"./async.js":2,"./util.js":38}],8:[function(_dereq_,module,exports){ "use strict"; -module.exports = -function(Promise, PromiseArray, tryConvertToPromise, INTERNAL) { +module.exports = function(NEXT_FILTER) { var util = _dereq_("./util.js"); -var canEvaluate = util.canEvaluate; +var errors = _dereq_("./errors.js"); var tryCatch = util.tryCatch; var errorObj = util.errorObj; -var reject; +var keys = _dereq_("./es5.js").keys; +var TypeError = errors.TypeError; -if (!true) { -if (canEvaluate) { - var thenCallback = function(i) { - return new Function("value", "holder", " \n\ - 'use strict'; \n\ - holder.pIndex = value; \n\ - holder.checkFulfillment(this); \n\ - ".replace(/Index/g, i)); - }; +function CatchFilter(instances, callback, promise) { + this._instances = instances; + this._callback = callback; + this._promise = promise; +} - var caller = function(count) { - var values = []; - for (var i = 1; i <= count; ++i) values.push("holder.p" + i); - return new Function("holder", " \n\ - 'use strict'; \n\ - var callback = holder.fn; \n\ - return callback(values); \n\ - ".replace(/values/g, values.join(", "))); - }; - var thenCallbacks = []; - var callers = [undefined]; - for (var i = 1; i <= 5; ++i) { - thenCallbacks.push(thenCallback(i)); - callers.push(caller(i)); +function safePredicate(predicate, e) { + var safeObject = {}; + var retfilter = tryCatch(predicate).call(safeObject, e); + + if (retfilter === errorObj) return retfilter; + + var safeKeys = keys(safeObject); + if (safeKeys.length) { + errorObj.e = new TypeError("Catch filter must inherit from Error or be a simple predicate function\u000a\u000a See http://goo.gl/o84o68\u000a"); + return errorObj; } + return retfilter; +} - var Holder = function(total, fn) { - this.p1 = this.p2 = this.p3 = this.p4 = this.p5 = null; - this.fn = fn; - this.total = total; - this.now = 0; - }; +CatchFilter.prototype.doFilter = function (e) { + var cb = this._callback; + var promise = this._promise; + var boundTo = promise._boundValue(); + for (var i = 0, len = this._instances.length; i < len; ++i) { + var item = this._instances[i]; + var itemIsErrorType = item === Error || + (item != null && item.prototype instanceof Error); - Holder.prototype.callers = callers; - Holder.prototype.checkFulfillment = function(promise) { - var now = this.now; - now++; - var total = this.total; - if (now >= total) { - var handler = this.callers[total]; - promise._pushContext(); - var ret = tryCatch(handler)(this); - promise._popContext(); + if (itemIsErrorType && e instanceof item) { + var ret = tryCatch(cb).call(boundTo, e); if (ret === errorObj) { - promise._rejectCallback(ret.e, false, true); - } else { - promise._resolveCallback(ret); + NEXT_FILTER.e = ret.e; + return NEXT_FILTER; } - } else { - this.now = now; - } - }; - - var reject = function (reason) { - this._reject(reason); - }; -} -} - -Promise.join = function () { - var last = arguments.length - 1; - var fn; - if (last > 0 && typeof arguments[last] === "function") { - fn = arguments[last]; - if (!true) { - if (last < 6 && canEvaluate) { - var ret = new Promise(INTERNAL); - ret._captureStackTrace(); - var holder = new Holder(last, fn); - var callbacks = thenCallbacks; - for (var i = 0; i < last; ++i) { - var maybePromise = tryConvertToPromise(arguments[i], ret); - if (maybePromise instanceof Promise) { - maybePromise = maybePromise._target(); - if (maybePromise._isPending()) { - maybePromise._then(callbacks[i], reject, - undefined, ret, holder); - } else if (maybePromise._isFulfilled()) { - callbacks[i].call(ret, - maybePromise._value(), holder); - } else { - ret._reject(maybePromise._reason()); - } - } else { - callbacks[i].call(ret, maybePromise, holder); - } + return ret; + } else if (typeof item === "function" && !itemIsErrorType) { + var shouldHandle = safePredicate(item, e); + if (shouldHandle === errorObj) { + e = errorObj.e; + break; + } else if (shouldHandle) { + var ret = tryCatch(cb).call(boundTo, e); + if (ret === errorObj) { + NEXT_FILTER.e = ret.e; + return NEXT_FILTER; } return ret; } } } - var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];} - if (fn) args.pop(); - var ret = new PromiseArray(args).promise(); - return fn !== undefined ? ret.spread(fn) : ret; + NEXT_FILTER.e = e; + return NEXT_FILTER; +}; + +return CatchFilter; +}; + +},{"./errors.js":13,"./es5.js":14,"./util.js":38}],9:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, CapturedTrace, isDebugging) { +var contextStack = []; +function Context() { + this._trace = new CapturedTrace(peekContext()); +} +Context.prototype._pushContext = function () { + if (!isDebugging()) return; + if (this._trace !== undefined) { + contextStack.push(this._trace); + } }; +Context.prototype._popContext = function () { + if (!isDebugging()) return; + if (this._trace !== undefined) { + contextStack.pop(); + } +}; + +function createContext() { + if (isDebugging()) return new Context(); +} + +function peekContext() { + var lastIndex = contextStack.length - 1; + if (lastIndex >= 0) { + return contextStack[lastIndex]; + } + return undefined; +} + +Promise.prototype._peekContext = peekContext; +Promise.prototype._pushContext = Context.prototype._pushContext; +Promise.prototype._popContext = Context.prototype._popContext; + +return createContext; }; -},{"./util.js":38}],19:[function(_dereq_,module,exports){ +},{}],10:[function(_dereq_,module,exports){ "use strict"; -module.exports = function(Promise, - PromiseArray, - apiRejection, - tryConvertToPromise, - INTERNAL) { +module.exports = function(Promise, CapturedTrace) { var getDomain = Promise._getDomain; var async = _dereq_("./async.js"); +var Warning = _dereq_("./errors.js").Warning; var util = _dereq_("./util.js"); -var tryCatch = util.tryCatch; -var errorObj = util.errorObj; -var PENDING = {}; -var EMPTY_ARRAY = []; - -function MappingPromiseArray(promises, fn, limit, _filter) { - this.constructor$(promises); - this._promise._captureStackTrace(); - var domain = getDomain(); - this._callback = domain === null ? fn : domain.bind(fn); - this._preservedValues = _filter === INTERNAL - ? new Array(this.length()) - : null; - this._limit = limit; - this._inFlight = 0; - this._queue = limit >= 1 ? [] : EMPTY_ARRAY; - async.invoke(init, this, undefined); -} -util.inherits(MappingPromiseArray, PromiseArray); -function init() {this._init$(undefined, -2);} +var canAttachTrace = util.canAttachTrace; +var unhandledRejectionHandled; +var possiblyUnhandledRejection; +var debugging = false || (util.isNode && + (!!process.env["BLUEBIRD_DEBUG"] || + process.env["NODE_ENV"] === "development")); -MappingPromiseArray.prototype._init = function () {}; +if (util.isNode && process.env["BLUEBIRD_DEBUG"] == 0) debugging = false; -MappingPromiseArray.prototype._promiseFulfilled = function (value, index) { - var values = this._values; - var length = this.length(); - var preservedValues = this._preservedValues; - var limit = this._limit; - if (values[index] === PENDING) { - values[index] = value; - if (limit >= 1) { - this._inFlight--; - this._drainQueue(); - if (this._isResolved()) return; - } - } else { - if (limit >= 1 && this._inFlight >= limit) { - values[index] = value; - this._queue.push(index); - return; - } - if (preservedValues !== null) preservedValues[index] = value; +if (debugging) { + async.disableTrampolineIfNecessary(); +} - var callback = this._callback; - var receiver = this._promise._boundValue(); - this._promise._pushContext(); - var ret = tryCatch(callback).call(receiver, value, index, length); - this._promise._popContext(); - if (ret === errorObj) return this._reject(ret.e); +Promise.prototype._ignoreRejections = function() { + this._unsetRejectionIsUnhandled(); + this._bitField = this._bitField | 16777216; +}; - var maybePromise = tryConvertToPromise(ret, this._promise); - if (maybePromise instanceof Promise) { - maybePromise = maybePromise._target(); - if (maybePromise._isPending()) { - if (limit >= 1) this._inFlight++; - values[index] = PENDING; - return maybePromise._proxyPromiseArray(this, index); - } else if (maybePromise._isFulfilled()) { - ret = maybePromise._value(); - } else { - return this._reject(maybePromise._reason()); - } - } - values[index] = ret; - } - var totalResolved = ++this._totalResolved; - if (totalResolved >= length) { - if (preservedValues !== null) { - this._filter(values, preservedValues); - } else { - this._resolve(values); - } +Promise.prototype._ensurePossibleRejectionHandled = function () { + if ((this._bitField & 16777216) !== 0) return; + this._setRejectionIsUnhandled(); + async.invokeLater(this._notifyUnhandledRejection, this, undefined); +}; - } +Promise.prototype._notifyUnhandledRejectionIsHandled = function () { + CapturedTrace.fireRejectionEvent("rejectionHandled", + unhandledRejectionHandled, undefined, this); }; -MappingPromiseArray.prototype._drainQueue = function () { - var queue = this._queue; - var limit = this._limit; - var values = this._values; - while (queue.length > 0 && this._inFlight < limit) { - if (this._isResolved()) return; - var index = queue.pop(); - this._promiseFulfilled(values[index], index); +Promise.prototype._notifyUnhandledRejection = function () { + if (this._isRejectionUnhandled()) { + var reason = this._getCarriedStackTrace() || this._settledValue; + this._setUnhandledRejectionIsNotified(); + CapturedTrace.fireRejectionEvent("unhandledRejection", + possiblyUnhandledRejection, reason, this); } }; -MappingPromiseArray.prototype._filter = function (booleans, values) { - var len = values.length; - var ret = new Array(len); - var j = 0; - for (var i = 0; i < len; ++i) { - if (booleans[i]) ret[j++] = values[i]; - } - ret.length = j; - this._resolve(ret); +Promise.prototype._setUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField | 524288; }; -MappingPromiseArray.prototype.preservedValues = function () { - return this._preservedValues; +Promise.prototype._unsetUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField & (~524288); }; -function map(promises, fn, options, _filter) { - var limit = typeof options === "object" && options !== null - ? options.concurrency - : 0; - limit = typeof limit === "number" && - isFinite(limit) && limit >= 1 ? limit : 0; - return new MappingPromiseArray(promises, fn, limit, _filter); -} +Promise.prototype._isUnhandledRejectionNotified = function () { + return (this._bitField & 524288) > 0; +}; -Promise.prototype.map = function (fn, options) { - if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); +Promise.prototype._setRejectionIsUnhandled = function () { + this._bitField = this._bitField | 2097152; +}; - return map(this, fn, options, null).promise(); +Promise.prototype._unsetRejectionIsUnhandled = function () { + this._bitField = this._bitField & (~2097152); + if (this._isUnhandledRejectionNotified()) { + this._unsetUnhandledRejectionIsNotified(); + this._notifyUnhandledRejectionIsHandled(); + } }; -Promise.map = function (promises, fn, options, _filter) { - if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); - return map(promises, fn, options, _filter).promise(); +Promise.prototype._isRejectionUnhandled = function () { + return (this._bitField & 2097152) > 0; }; +Promise.prototype._setCarriedStackTrace = function (capturedTrace) { + this._bitField = this._bitField | 1048576; + this._fulfillmentHandler0 = capturedTrace; +}; +Promise.prototype._isCarryingStackTrace = function () { + return (this._bitField & 1048576) > 0; }; -},{"./async.js":2,"./util.js":38}],20:[function(_dereq_,module,exports){ -"use strict"; -module.exports = -function(Promise, INTERNAL, tryConvertToPromise, apiRejection) { -var util = _dereq_("./util.js"); -var tryCatch = util.tryCatch; +Promise.prototype._getCarriedStackTrace = function () { + return this._isCarryingStackTrace() + ? this._fulfillmentHandler0 + : undefined; +}; -Promise.method = function (fn) { - if (typeof fn !== "function") { - throw new Promise.TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); +Promise.prototype._captureStackTrace = function () { + if (debugging) { + this._trace = new CapturedTrace(this._peekContext()); } - return function () { - var ret = new Promise(INTERNAL); - ret._captureStackTrace(); - ret._pushContext(); - var value = tryCatch(fn).apply(this, arguments); - ret._popContext(); - ret._resolveFromSyncValue(value); - return ret; - }; + return this; }; -Promise.attempt = Promise["try"] = function (fn, args, ctx) { - if (typeof fn !== "function") { - return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); +Promise.prototype._attachExtraTrace = function (error, ignoreSelf) { + if (debugging && canAttachTrace(error)) { + var trace = this._trace; + if (trace !== undefined) { + if (ignoreSelf) trace = trace._parent; + } + if (trace !== undefined) { + trace.attachExtraTrace(error); + } else if (!error.__stackCleaned__) { + var parsed = CapturedTrace.parseStackAndMessage(error); + util.notEnumerableProp(error, "stack", + parsed.message + "\n" + parsed.stack.join("\n")); + util.notEnumerableProp(error, "__stackCleaned__", true); + } } - var ret = new Promise(INTERNAL); - ret._captureStackTrace(); - ret._pushContext(); - var value = util.isArray(args) - ? tryCatch(fn).apply(ctx, args) - : tryCatch(fn).call(ctx, args); - ret._popContext(); - ret._resolveFromSyncValue(value); - return ret; }; -Promise.prototype._resolveFromSyncValue = function (value) { - if (value === util.errorObj) { - this._rejectCallback(value.e, false, true); +Promise.prototype._warn = function(message) { + var warning = new Warning(message); + var ctx = this._peekContext(); + if (ctx) { + ctx.attachExtraTrace(warning); } else { - this._resolveCallback(value, true); + var parsed = CapturedTrace.parseStackAndMessage(warning); + warning.stack = parsed.message + "\n" + parsed.stack.join("\n"); } -}; + CapturedTrace.formatAndLogError(warning, ""); }; -},{"./util.js":38}],21:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise) { -var util = _dereq_("./util.js"); -var async = _dereq_("./async.js"); -var tryCatch = util.tryCatch; -var errorObj = util.errorObj; +Promise.onPossiblyUnhandledRejection = function (fn) { + var domain = getDomain(); + possiblyUnhandledRejection = + typeof fn === "function" ? (domain === null ? fn : domain.bind(fn)) + : undefined; +}; -function spreadAdapter(val, nodeback) { - var promise = this; - if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback); - var ret = - tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val)); - if (ret === errorObj) { - async.throwLater(ret.e); - } -} +Promise.onUnhandledRejectionHandled = function (fn) { + var domain = getDomain(); + unhandledRejectionHandled = + typeof fn === "function" ? (domain === null ? fn : domain.bind(fn)) + : undefined; +}; -function successAdapter(val, nodeback) { - var promise = this; - var receiver = promise._boundValue(); - var ret = val === undefined - ? tryCatch(nodeback).call(receiver, null) - : tryCatch(nodeback).call(receiver, null, val); - if (ret === errorObj) { - async.throwLater(ret.e); - } -} -function errorAdapter(reason, nodeback) { - var promise = this; - if (!reason) { - var target = promise._target(); - var newReason = target._getCarriedStackTrace(); - newReason.cause = reason; - reason = newReason; +Promise.longStackTraces = function () { + if (async.haveItemsQueued() && + debugging === false + ) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/DT1qyG\u000a"); } - var ret = tryCatch(nodeback).call(promise._boundValue(), reason); - if (ret === errorObj) { - async.throwLater(ret.e); + debugging = CapturedTrace.isSupported(); + if (debugging) { + async.disableTrampolineIfNecessary(); } +}; + +Promise.hasLongStackTraces = function () { + return debugging && CapturedTrace.isSupported(); +}; + +if (!CapturedTrace.isSupported()) { + Promise.longStackTraces = function(){}; + debugging = false; } -Promise.prototype.asCallback = -Promise.prototype.nodeify = function (nodeback, options) { - if (typeof nodeback == "function") { - var adapter = successAdapter; - if (options !== undefined && Object(options).spread) { - adapter = spreadAdapter; - } - this._then( - adapter, - errorAdapter, - undefined, - this, - nodeback - ); - } - return this; +return function() { + return debugging; }; }; -},{"./async.js":2,"./util.js":38}],22:[function(_dereq_,module,exports){ +},{"./async.js":2,"./errors.js":13,"./util.js":38}],11:[function(_dereq_,module,exports){ "use strict"; -module.exports = function(Promise, PromiseArray) { var util = _dereq_("./util.js"); -var async = _dereq_("./async.js"); -var tryCatch = util.tryCatch; -var errorObj = util.errorObj; +var isPrimitive = util.isPrimitive; -Promise.prototype.progressed = function (handler) { - return this._then(undefined, undefined, handler, undefined, undefined); +module.exports = function(Promise) { +var returner = function () { + return this; }; - -Promise.prototype._progress = function (progressValue) { - if (this._isFollowingOrFulfilledOrRejected()) return; - this._target()._progressUnchecked(progressValue); - +var thrower = function () { + throw this; +}; +var returnUndefined = function() {}; +var throwUndefined = function() { + throw undefined; }; -Promise.prototype._progressHandlerAt = function (index) { - return index === 0 - ? this._progressHandler0 - : this[(index << 2) + index - 5 + 2]; +var wrapper = function (value, action) { + if (action === 1) { + return function () { + throw value; + }; + } else if (action === 2) { + return function () { + return value; + }; + } }; -Promise.prototype._doProgressWith = function (progression) { - var progressValue = progression.value; - var handler = progression.handler; - var promise = progression.promise; - var receiver = progression.receiver; - var ret = tryCatch(handler).call(receiver, progressValue); - if (ret === errorObj) { - if (ret.e != null && - ret.e.name !== "StopProgressPropagation") { - var trace = util.canAttachTrace(ret.e) - ? ret.e : new Error(util.toString(ret.e)); - promise._attachExtraTrace(trace); - promise._progress(ret.e); - } - } else if (ret instanceof Promise) { - ret._then(promise._progress, null, null, promise, undefined); - } else { - promise._progress(ret); +Promise.prototype["return"] = +Promise.prototype.thenReturn = function (value) { + if (value === undefined) return this.then(returnUndefined); + + if (isPrimitive(value)) { + return this._then( + wrapper(value, 2), + undefined, + undefined, + undefined, + undefined + ); + } else if (value instanceof Promise) { + value._ignoreRejections(); } + return this._then(returner, undefined, undefined, value, undefined); }; +Promise.prototype["throw"] = +Promise.prototype.thenThrow = function (reason) { + if (reason === undefined) return this.then(throwUndefined); -Promise.prototype._progressUnchecked = function (progressValue) { - var len = this._length(); - var progress = this._progress; - for (var i = 0; i < len; i++) { - var handler = this._progressHandlerAt(i); - var promise = this._promiseAt(i); - if (!(promise instanceof Promise)) { - var receiver = this._receiverAt(i); - if (typeof handler === "function") { - handler.call(receiver, progressValue, promise); - } else if (receiver instanceof PromiseArray && - !receiver._isResolved()) { - receiver._promiseProgressed(progressValue, promise); - } - continue; - } - - if (typeof handler === "function") { - async.invoke(this._doProgressWith, this, { - handler: handler, - promise: promise, - receiver: this._receiverAt(i), - value: progressValue - }); - } else { - async.invoke(progress, promise, progressValue); - } + if (isPrimitive(reason)) { + return this._then( + wrapper(reason, 1), + undefined, + undefined, + undefined, + undefined + ); } + return this._then(thrower, undefined, undefined, reason, undefined); }; }; -},{"./async.js":2,"./util.js":38}],23:[function(_dereq_,module,exports){ +},{"./util.js":38}],12:[function(_dereq_,module,exports){ "use strict"; -module.exports = function() { -var makeSelfResolutionError = function () { - return new TypeError("circular promise resolution chain\u000a\u000a See http://goo.gl/LhFpo0\u000a"); +module.exports = function(Promise, INTERNAL) { +var PromiseReduce = Promise.reduce; + +Promise.prototype.each = function (fn) { + return PromiseReduce(this, fn, null, INTERNAL); }; -var reflect = function() { - return new Promise.PromiseInspection(this._target()); + +Promise.each = function (promises, fn) { + return PromiseReduce(promises, fn, null, INTERNAL); }; -var apiRejection = function(msg) { - return Promise.reject(new TypeError(msg)); }; +},{}],13:[function(_dereq_,module,exports){ +"use strict"; +var es5 = _dereq_("./es5.js"); +var Objectfreeze = es5.freeze; var util = _dereq_("./util.js"); +var inherits = util.inherits; +var notEnumerableProp = util.notEnumerableProp; -var getDomain; -if (util.isNode) { - getDomain = function() { - var ret = process.domain; - if (ret === undefined) ret = null; - return ret; - }; -} else { - getDomain = function() { - return null; - }; +function subError(nameProperty, defaultMessage) { + function SubError(message) { + if (!(this instanceof SubError)) return new SubError(message); + notEnumerableProp(this, "message", + typeof message === "string" ? message : defaultMessage); + notEnumerableProp(this, "name", nameProperty); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } else { + Error.call(this); + } + } + inherits(SubError, Error); + return SubError; } -util.notEnumerableProp(Promise, "_getDomain", getDomain); -var UNDEFINED_BINDING = {}; -var async = _dereq_("./async.js"); -var errors = _dereq_("./errors.js"); -var TypeError = Promise.TypeError = errors.TypeError; -Promise.RangeError = errors.RangeError; -Promise.CancellationError = errors.CancellationError; -Promise.TimeoutError = errors.TimeoutError; -Promise.OperationalError = errors.OperationalError; -Promise.RejectionError = errors.OperationalError; -Promise.AggregateError = errors.AggregateError; -var INTERNAL = function(){}; -var APPLY = {}; -var NEXT_FILTER = {e: null}; -var tryConvertToPromise = _dereq_("./thenables.js")(Promise, INTERNAL); -var PromiseArray = - _dereq_("./promise_array.js")(Promise, INTERNAL, - tryConvertToPromise, apiRejection); -var CapturedTrace = _dereq_("./captured_trace.js")(); -var isDebugging = _dereq_("./debuggability.js")(Promise, CapturedTrace); - /*jshint unused:false*/ -var createContext = - _dereq_("./context.js")(Promise, CapturedTrace, isDebugging); -var CatchFilter = _dereq_("./catch_filter.js")(NEXT_FILTER); -var PromiseResolver = _dereq_("./promise_resolver.js"); -var nodebackForPromise = PromiseResolver._nodebackForPromise; -var errorObj = util.errorObj; -var tryCatch = util.tryCatch; -function Promise(resolver) { - if (typeof resolver !== "function") { - throw new TypeError("the promise constructor requires a resolver function\u000a\u000a See http://goo.gl/EC22Yn\u000a"); - } - if (this.constructor !== Promise) { - throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a See http://goo.gl/KsIlge\u000a"); - } - this._bitField = 0; - this._fulfillmentHandler0 = undefined; - this._rejectionHandler0 = undefined; - this._progressHandler0 = undefined; - this._promise0 = undefined; - this._receiver0 = undefined; - this._settledValue = undefined; - if (resolver !== INTERNAL) this._resolveFromResolver(resolver); +var _TypeError, _RangeError; +var Warning = subError("Warning", "warning"); +var CancellationError = subError("CancellationError", "cancellation error"); +var TimeoutError = subError("TimeoutError", "timeout error"); +var AggregateError = subError("AggregateError", "aggregate error"); +try { + _TypeError = TypeError; + _RangeError = RangeError; +} catch(e) { + _TypeError = subError("TypeError", "type error"); + _RangeError = subError("RangeError", "range error"); } -Promise.prototype.toString = function () { - return "[object Promise]"; -}; +var methods = ("join pop push shift unshift slice filter forEach some " + + "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" "); -Promise.prototype.caught = Promise.prototype["catch"] = function (fn) { - var len = arguments.length; - if (len > 1) { - var catchInstances = new Array(len - 1), - j = 0, i; - for (i = 0; i < len - 1; ++i) { - var item = arguments[i]; - if (typeof item === "function") { - catchInstances[j++] = item; - } else { - return Promise.reject( - new TypeError("Catch filter must inherit from Error or be a simple predicate function\u000a\u000a See http://goo.gl/o84o68\u000a")); - } +for (var i = 0; i < methods.length; ++i) { + if (typeof Array.prototype[methods[i]] === "function") { + AggregateError.prototype[methods[i]] = Array.prototype[methods[i]]; + } +} + +es5.defineProperty(AggregateError.prototype, "length", { + value: 0, + configurable: false, + writable: true, + enumerable: true +}); +AggregateError.prototype["isOperational"] = true; +var level = 0; +AggregateError.prototype.toString = function() { + var indent = Array(level * 4 + 1).join(" "); + var ret = "\n" + indent + "AggregateError of:" + "\n"; + level++; + indent = Array(level * 4 + 1).join(" "); + for (var i = 0; i < this.length; ++i) { + var str = this[i] === this ? "[Circular AggregateError]" : this[i] + ""; + var lines = str.split("\n"); + for (var j = 0; j < lines.length; ++j) { + lines[j] = indent + lines[j]; } - catchInstances.length = j; - fn = arguments[i]; - var catchFilter = new CatchFilter(catchInstances, fn, this); - return this._then(undefined, catchFilter.doFilter, undefined, - catchFilter, undefined); + str = lines.join("\n"); + ret += str + "\n"; } - return this._then(undefined, fn, undefined, undefined, undefined); + level--; + return ret; }; -Promise.prototype.reflect = function () { - return this._then(reflect, reflect, undefined, this, undefined); -}; +function OperationalError(message) { + if (!(this instanceof OperationalError)) + return new OperationalError(message); + notEnumerableProp(this, "name", "OperationalError"); + notEnumerableProp(this, "message", message); + this.cause = message; + this["isOperational"] = true; -Promise.prototype.then = function (didFulfill, didReject, didProgress) { - if (isDebugging() && arguments.length > 0 && - typeof didFulfill !== "function" && - typeof didReject !== "function") { - var msg = ".then() only accepts functions but was passed: " + - util.classString(didFulfill); - if (arguments.length > 1) { - msg += ", " + util.classString(didReject); - } - this._warn(msg); + if (message instanceof Error) { + notEnumerableProp(this, "message", message.message); + notEnumerableProp(this, "stack", message.stack); + } else if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); } - return this._then(didFulfill, didReject, didProgress, - undefined, undefined); -}; -Promise.prototype.done = function (didFulfill, didReject, didProgress) { - var promise = this._then(didFulfill, didReject, didProgress, - undefined, undefined); - promise._setIsFinal(); -}; +} +inherits(OperationalError, Error); -Promise.prototype.spread = function (didFulfill, didReject) { - return this.all()._then(didFulfill, didReject, undefined, APPLY, undefined); -}; +var errorTypes = Error["__BluebirdErrorTypes__"]; +if (!errorTypes) { + errorTypes = Objectfreeze({ + CancellationError: CancellationError, + TimeoutError: TimeoutError, + OperationalError: OperationalError, + RejectionError: OperationalError, + AggregateError: AggregateError + }); + notEnumerableProp(Error, "__BluebirdErrorTypes__", errorTypes); +} -Promise.prototype.isCancellable = function () { - return !this.isResolved() && - this._cancellable(); +module.exports = { + Error: Error, + TypeError: _TypeError, + RangeError: _RangeError, + CancellationError: errorTypes.CancellationError, + OperationalError: errorTypes.OperationalError, + TimeoutError: errorTypes.TimeoutError, + AggregateError: errorTypes.AggregateError, + Warning: Warning }; -Promise.prototype.toJSON = function () { - var ret = { - isFulfilled: false, - isRejected: false, - fulfillmentValue: undefined, - rejectionReason: undefined +},{"./es5.js":14,"./util.js":38}],14:[function(_dereq_,module,exports){ +var isES5 = (function(){ + "use strict"; + return this === undefined; +})(); + +if (isES5) { + module.exports = { + freeze: Object.freeze, + defineProperty: Object.defineProperty, + getDescriptor: Object.getOwnPropertyDescriptor, + keys: Object.keys, + names: Object.getOwnPropertyNames, + getPrototypeOf: Object.getPrototypeOf, + isArray: Array.isArray, + isES5: isES5, + propertyIsWritable: function(obj, prop) { + var descriptor = Object.getOwnPropertyDescriptor(obj, prop); + return !!(!descriptor || descriptor.writable || descriptor.set); + } }; - if (this.isFulfilled()) { - ret.fulfillmentValue = this.value(); - ret.isFulfilled = true; - } else if (this.isRejected()) { - ret.rejectionReason = this.reason(); - ret.isRejected = true; - } - return ret; -}; +} else { + var has = {}.hasOwnProperty; + var str = {}.toString; + var proto = {}.constructor.prototype; -Promise.prototype.all = function () { - return new PromiseArray(this).promise(); -}; + var ObjectKeys = function (o) { + var ret = []; + for (var key in o) { + if (has.call(o, key)) { + ret.push(key); + } + } + return ret; + }; -Promise.prototype.error = function (fn) { - return this.caught(util.originatesFromRejection, fn); -}; + var ObjectGetDescriptor = function(o, key) { + return {value: o[key]}; + }; -Promise.is = function (val) { - return val instanceof Promise; -}; + var ObjectDefineProperty = function (o, key, desc) { + o[key] = desc.value; + return o; + }; -Promise.fromNode = function(fn) { - var ret = new Promise(INTERNAL); - var result = tryCatch(fn)(nodebackForPromise(ret)); - if (result === errorObj) { - ret._rejectCallback(result.e, true, true); - } - return ret; -}; + var ObjectFreeze = function (obj) { + return obj; + }; -Promise.all = function (promises) { - return new PromiseArray(promises).promise(); -}; + var ObjectGetPrototypeOf = function (obj) { + try { + return Object(obj).constructor.prototype; + } + catch (e) { + return proto; + } + }; -Promise.defer = Promise.pending = function () { - var promise = new Promise(INTERNAL); - return new PromiseResolver(promise); -}; + var ArrayIsArray = function (obj) { + try { + return str.call(obj) === "[object Array]"; + } + catch(e) { + return false; + } + }; -Promise.cast = function (obj) { - var ret = tryConvertToPromise(obj); - if (!(ret instanceof Promise)) { - var val = ret; - ret = new Promise(INTERNAL); - ret._fulfillUnchecked(val); - } - return ret; -}; + module.exports = { + isArray: ArrayIsArray, + keys: ObjectKeys, + names: ObjectKeys, + defineProperty: ObjectDefineProperty, + getDescriptor: ObjectGetDescriptor, + freeze: ObjectFreeze, + getPrototypeOf: ObjectGetPrototypeOf, + isES5: isES5, + propertyIsWritable: function() { + return true; + } + }; +} -Promise.resolve = Promise.fulfilled = Promise.cast; +},{}],15:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var PromiseMap = Promise.map; -Promise.reject = Promise.rejected = function (reason) { - var ret = new Promise(INTERNAL); - ret._captureStackTrace(); - ret._rejectCallback(reason, true); - return ret; +Promise.prototype.filter = function (fn, options) { + return PromiseMap(this, fn, options, INTERNAL); }; -Promise.setScheduler = function(fn) { - if (typeof fn !== "function") throw new TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); - var prev = async._schedule; - async._schedule = fn; - return prev; +Promise.filter = function (promises, fn, options) { + return PromiseMap(promises, fn, options, INTERNAL); +}; }; -Promise.prototype._then = function ( - didFulfill, - didReject, - didProgress, - receiver, - internalData -) { - var haveInternalData = internalData !== undefined; - var ret = haveInternalData ? internalData : new Promise(INTERNAL); +},{}],16:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, NEXT_FILTER, tryConvertToPromise) { +var util = _dereq_("./util.js"); +var isPrimitive = util.isPrimitive; +var thrower = util.thrower; - if (!haveInternalData) { - ret._propagateFrom(this, 4 | 1); - ret._captureStackTrace(); +function returnThis() { + return this; +} +function throwThis() { + throw this; +} +function return$(r) { + return function() { + return r; + }; +} +function throw$(r) { + return function() { + throw r; + }; +} +function promisedFinally(ret, reasonOrValue, isFulfilled) { + var then; + if (isPrimitive(reasonOrValue)) { + then = isFulfilled ? return$(reasonOrValue) : throw$(reasonOrValue); + } else { + then = isFulfilled ? returnThis : throwThis; } + return ret._then(then, thrower, undefined, reasonOrValue, undefined); +} - var target = this._target(); - if (target !== this) { - if (receiver === undefined) receiver = this._boundTo; - if (!haveInternalData) ret._setIsMigrated(); +function finallyHandler(reasonOrValue) { + var promise = this.promise; + var handler = this.handler; + + var ret = promise._isBound() + ? handler.call(promise._boundValue()) + : handler(); + + if (ret !== undefined) { + var maybePromise = tryConvertToPromise(ret, promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + return promisedFinally(maybePromise, reasonOrValue, + promise.isFulfilled()); + } } - var callbackIndex = target._addCallbacks(didFulfill, - didReject, - didProgress, - ret, - receiver, - getDomain()); + if (promise.isRejected()) { + NEXT_FILTER.e = reasonOrValue; + return NEXT_FILTER; + } else { + return reasonOrValue; + } +} - if (target._isResolved() && !target._isSettlePromisesQueued()) { - async.invoke( - target._settlePromiseAtPostResolution, target, callbackIndex); +function tapHandler(value) { + var promise = this.promise; + var handler = this.handler; + + var ret = promise._isBound() + ? handler.call(promise._boundValue(), value) + : handler(value); + + if (ret !== undefined) { + var maybePromise = tryConvertToPromise(ret, promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + return promisedFinally(maybePromise, value, true); + } } + return value; +} - return ret; -}; +Promise.prototype._passThroughHandler = function (handler, isFinally) { + if (typeof handler !== "function") return this.then(); -Promise.prototype._settlePromiseAtPostResolution = function (index) { - if (this._isRejectionUnhandled()) this._unsetRejectionIsUnhandled(); - this._settlePromiseAt(index); -}; + var promiseAndHandler = { + promise: this, + handler: handler + }; -Promise.prototype._length = function () { - return this._bitField & 131071; + return this._then( + isFinally ? finallyHandler : tapHandler, + isFinally ? finallyHandler : undefined, undefined, + promiseAndHandler, undefined); }; -Promise.prototype._isFollowingOrFulfilledOrRejected = function () { - return (this._bitField & 939524096) > 0; +Promise.prototype.lastly = +Promise.prototype["finally"] = function (handler) { + return this._passThroughHandler(handler, true); }; -Promise.prototype._isFollowing = function () { - return (this._bitField & 536870912) === 536870912; +Promise.prototype.tap = function (handler) { + return this._passThroughHandler(handler, false); }; - -Promise.prototype._setLength = function (len) { - this._bitField = (this._bitField & -131072) | - (len & 131071); }; -Promise.prototype._setFulfilled = function () { - this._bitField = this._bitField | 268435456; -}; +},{"./util.js":38}],17:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, + apiRejection, + INTERNAL, + tryConvertToPromise) { +var errors = _dereq_("./errors.js"); +var TypeError = errors.TypeError; +var util = _dereq_("./util.js"); +var errorObj = util.errorObj; +var tryCatch = util.tryCatch; +var yieldHandlers = []; -Promise.prototype._setRejected = function () { - this._bitField = this._bitField | 134217728; -}; +function promiseFromYieldHandler(value, yieldHandlers, traceParent) { + for (var i = 0; i < yieldHandlers.length; ++i) { + traceParent._pushContext(); + var result = tryCatch(yieldHandlers[i])(value); + traceParent._popContext(); + if (result === errorObj) { + traceParent._pushContext(); + var ret = Promise.reject(errorObj.e); + traceParent._popContext(); + return ret; + } + var maybePromise = tryConvertToPromise(result, traceParent); + if (maybePromise instanceof Promise) return maybePromise; + } + return null; +} -Promise.prototype._setFollowing = function () { - this._bitField = this._bitField | 536870912; -}; +function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) { + var promise = this._promise = new Promise(INTERNAL); + promise._captureStackTrace(); + this._stack = stack; + this._generatorFunction = generatorFunction; + this._receiver = receiver; + this._generator = undefined; + this._yieldHandlers = typeof yieldHandler === "function" + ? [yieldHandler].concat(yieldHandlers) + : yieldHandlers; +} -Promise.prototype._setIsFinal = function () { - this._bitField = this._bitField | 33554432; +PromiseSpawn.prototype.promise = function () { + return this._promise; }; -Promise.prototype._isFinal = function () { - return (this._bitField & 33554432) > 0; +PromiseSpawn.prototype._run = function () { + this._generator = this._generatorFunction.call(this._receiver); + this._receiver = + this._generatorFunction = undefined; + this._next(undefined); }; -Promise.prototype._cancellable = function () { - return (this._bitField & 67108864) > 0; -}; +PromiseSpawn.prototype._continue = function (result) { + if (result === errorObj) { + return this._promise._rejectCallback(result.e, false, true); + } -Promise.prototype._setCancellable = function () { - this._bitField = this._bitField | 67108864; + var value = result.value; + if (result.done === true) { + this._promise._resolveCallback(value); + } else { + var maybePromise = tryConvertToPromise(value, this._promise); + if (!(maybePromise instanceof Promise)) { + maybePromise = + promiseFromYieldHandler(maybePromise, + this._yieldHandlers, + this._promise); + if (maybePromise === null) { + this._throw( + new TypeError( + "A value %s was yielded that could not be treated as a promise\u000a\u000a See http://goo.gl/4Y4pDk\u000a\u000a".replace("%s", value) + + "From coroutine:\u000a" + + this._stack.split("\n").slice(1, -7).join("\n") + ) + ); + return; + } + } + maybePromise._then( + this._next, + this._throw, + undefined, + this, + null + ); + } }; -Promise.prototype._unsetCancellable = function () { - this._bitField = this._bitField & (~67108864); +PromiseSpawn.prototype._throw = function (reason) { + this._promise._attachExtraTrace(reason); + this._promise._pushContext(); + var result = tryCatch(this._generator["throw"]) + .call(this._generator, reason); + this._promise._popContext(); + this._continue(result); }; -Promise.prototype._setIsMigrated = function () { - this._bitField = this._bitField | 4194304; +PromiseSpawn.prototype._next = function (value) { + this._promise._pushContext(); + var result = tryCatch(this._generator.next).call(this._generator, value); + this._promise._popContext(); + this._continue(result); }; -Promise.prototype._unsetIsMigrated = function () { - this._bitField = this._bitField & (~4194304); +Promise.coroutine = function (generatorFunction, options) { + if (typeof generatorFunction !== "function") { + throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/6Vqhm0\u000a"); + } + var yieldHandler = Object(options).yieldHandler; + var PromiseSpawn$ = PromiseSpawn; + var stack = new Error().stack; + return function () { + var generator = generatorFunction.apply(this, arguments); + var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler, + stack); + spawn._generator = generator; + spawn._next(undefined); + return spawn.promise(); + }; }; -Promise.prototype._isMigrated = function () { - return (this._bitField & 4194304) > 0; +Promise.coroutine.addYieldHandler = function(fn) { + if (typeof fn !== "function") throw new TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); + yieldHandlers.push(fn); }; -Promise.prototype._receiverAt = function (index) { - var ret = index === 0 - ? this._receiver0 - : this[ - index * 5 - 5 + 4]; - if (ret === UNDEFINED_BINDING) { - return undefined; - } else if (ret === undefined && this._isBound()) { - return this._boundValue(); +Promise.spawn = function (generatorFunction) { + if (typeof generatorFunction !== "function") { + return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/6Vqhm0\u000a"); } + var spawn = new PromiseSpawn(generatorFunction, this); + var ret = spawn.promise(); + spawn._run(Promise.spawn); return ret; }; - -Promise.prototype._promiseAt = function (index) { - return index === 0 - ? this._promise0 - : this[index * 5 - 5 + 3]; }; -Promise.prototype._fulfillmentHandlerAt = function (index) { - return index === 0 - ? this._fulfillmentHandler0 - : this[index * 5 - 5 + 0]; -}; +},{"./errors.js":13,"./util.js":38}],18:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, PromiseArray, tryConvertToPromise, INTERNAL) { +var util = _dereq_("./util.js"); +var canEvaluate = util.canEvaluate; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var reject; -Promise.prototype._rejectionHandlerAt = function (index) { - return index === 0 - ? this._rejectionHandler0 - : this[index * 5 - 5 + 1]; -}; +if (!true) { +if (canEvaluate) { + var thenCallback = function(i) { + return new Function("value", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = value; \n\ + holder.checkFulfillment(this); \n\ + ".replace(/Index/g, i)); + }; -Promise.prototype._boundValue = function() { - var ret = this._boundTo; - if (ret !== undefined) { - if (ret instanceof Promise) { - if (ret.isFulfilled()) { - return ret.value(); + var caller = function(count) { + var values = []; + for (var i = 1; i <= count; ++i) values.push("holder.p" + i); + return new Function("holder", " \n\ + 'use strict'; \n\ + var callback = holder.fn; \n\ + return callback(values); \n\ + ".replace(/values/g, values.join(", "))); + }; + var thenCallbacks = []; + var callers = [undefined]; + for (var i = 1; i <= 5; ++i) { + thenCallbacks.push(thenCallback(i)); + callers.push(caller(i)); + } + + var Holder = function(total, fn) { + this.p1 = this.p2 = this.p3 = this.p4 = this.p5 = null; + this.fn = fn; + this.total = total; + this.now = 0; + }; + + Holder.prototype.callers = callers; + Holder.prototype.checkFulfillment = function(promise) { + var now = this.now; + now++; + var total = this.total; + if (now >= total) { + var handler = this.callers[total]; + promise._pushContext(); + var ret = tryCatch(handler)(this); + promise._popContext(); + if (ret === errorObj) { + promise._rejectCallback(ret.e, false, true); } else { - return undefined; + promise._resolveCallback(ret); + } + } else { + this.now = now; + } + }; + + var reject = function (reason) { + this._reject(reason); + }; +} +} + +Promise.join = function () { + var last = arguments.length - 1; + var fn; + if (last > 0 && typeof arguments[last] === "function") { + fn = arguments[last]; + if (!true) { + if (last < 6 && canEvaluate) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var holder = new Holder(last, fn); + var callbacks = thenCallbacks; + for (var i = 0; i < last; ++i) { + var maybePromise = tryConvertToPromise(arguments[i], ret); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + if (maybePromise._isPending()) { + maybePromise._then(callbacks[i], reject, + undefined, ret, holder); + } else if (maybePromise._isFulfilled()) { + callbacks[i].call(ret, + maybePromise._value(), holder); + } else { + ret._reject(maybePromise._reason()); + } + } else { + callbacks[i].call(ret, maybePromise, holder); + } + } + return ret; } } } - return ret; + var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];} + if (fn) args.pop(); + var ret = new PromiseArray(args).promise(); + return fn !== undefined ? ret.spread(fn) : ret; }; -Promise.prototype._migrateCallbacks = function (follower, index) { - var fulfill = follower._fulfillmentHandlerAt(index); - var reject = follower._rejectionHandlerAt(index); - var progress = follower._progressHandlerAt(index); - var promise = follower._promiseAt(index); - var receiver = follower._receiverAt(index); - if (promise instanceof Promise) promise._setIsMigrated(); - if (receiver === undefined) receiver = UNDEFINED_BINDING; - this._addCallbacks(fulfill, reject, progress, promise, receiver, null); }; -Promise.prototype._addCallbacks = function ( - fulfill, - reject, - progress, - promise, - receiver, - domain -) { - var index = this._length(); +},{"./util.js":38}],19:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL) { +var getDomain = Promise._getDomain; +var async = _dereq_("./async.js"); +var util = _dereq_("./util.js"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var PENDING = {}; +var EMPTY_ARRAY = []; - if (index >= 131071 - 5) { - index = 0; - this._setLength(0); - } +function MappingPromiseArray(promises, fn, limit, _filter) { + this.constructor$(promises); + this._promise._captureStackTrace(); + var domain = getDomain(); + this._callback = domain === null ? fn : domain.bind(fn); + this._preservedValues = _filter === INTERNAL + ? new Array(this.length()) + : null; + this._limit = limit; + this._inFlight = 0; + this._queue = limit >= 1 ? [] : EMPTY_ARRAY; + async.invoke(init, this, undefined); +} +util.inherits(MappingPromiseArray, PromiseArray); +function init() {this._init$(undefined, -2);} - if (index === 0) { - this._promise0 = promise; - if (receiver !== undefined) this._receiver0 = receiver; - if (typeof fulfill === "function" && !this._isCarryingStackTrace()) { - this._fulfillmentHandler0 = - domain === null ? fulfill : domain.bind(fulfill); - } - if (typeof reject === "function") { - this._rejectionHandler0 = - domain === null ? reject : domain.bind(reject); - } - if (typeof progress === "function") { - this._progressHandler0 = - domain === null ? progress : domain.bind(progress); +MappingPromiseArray.prototype._init = function () {}; + +MappingPromiseArray.prototype._promiseFulfilled = function (value, index) { + var values = this._values; + var length = this.length(); + var preservedValues = this._preservedValues; + var limit = this._limit; + if (values[index] === PENDING) { + values[index] = value; + if (limit >= 1) { + this._inFlight--; + this._drainQueue(); + if (this._isResolved()) return; } } else { - var base = index * 5 - 5; - this[base + 3] = promise; - this[base + 4] = receiver; - if (typeof fulfill === "function") { - this[base + 0] = - domain === null ? fulfill : domain.bind(fulfill); + if (limit >= 1 && this._inFlight >= limit) { + values[index] = value; + this._queue.push(index); + return; } - if (typeof reject === "function") { - this[base + 1] = - domain === null ? reject : domain.bind(reject); + if (preservedValues !== null) preservedValues[index] = value; + + var callback = this._callback; + var receiver = this._promise._boundValue(); + this._promise._pushContext(); + var ret = tryCatch(callback).call(receiver, value, index, length); + this._promise._popContext(); + if (ret === errorObj) return this._reject(ret.e); + + var maybePromise = tryConvertToPromise(ret, this._promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + if (maybePromise._isPending()) { + if (limit >= 1) this._inFlight++; + values[index] = PENDING; + return maybePromise._proxyPromiseArray(this, index); + } else if (maybePromise._isFulfilled()) { + ret = maybePromise._value(); + } else { + return this._reject(maybePromise._reason()); + } } - if (typeof progress === "function") { - this[base + 2] = - domain === null ? progress : domain.bind(progress); + values[index] = ret; + } + var totalResolved = ++this._totalResolved; + if (totalResolved >= length) { + if (preservedValues !== null) { + this._filter(values, preservedValues); + } else { + this._resolve(values); } + } - this._setLength(index + 1); - return index; }; -Promise.prototype._setProxyHandlers = function (receiver, promiseSlotValue) { - var index = this._length(); - - if (index >= 131071 - 5) { - index = 0; - this._setLength(0); +MappingPromiseArray.prototype._drainQueue = function () { + var queue = this._queue; + var limit = this._limit; + var values = this._values; + while (queue.length > 0 && this._inFlight < limit) { + if (this._isResolved()) return; + var index = queue.pop(); + this._promiseFulfilled(values[index], index); } - if (index === 0) { - this._promise0 = promiseSlotValue; - this._receiver0 = receiver; - } else { - var base = index * 5 - 5; - this[base + 3] = promiseSlotValue; - this[base + 4] = receiver; +}; + +MappingPromiseArray.prototype._filter = function (booleans, values) { + var len = values.length; + var ret = new Array(len); + var j = 0; + for (var i = 0; i < len; ++i) { + if (booleans[i]) ret[j++] = values[i]; } - this._setLength(index + 1); + ret.length = j; + this._resolve(ret); }; -Promise.prototype._proxyPromiseArray = function (promiseArray, index) { - this._setProxyHandlers(promiseArray, index); +MappingPromiseArray.prototype.preservedValues = function () { + return this._preservedValues; }; -Promise.prototype._resolveCallback = function(value, shouldBind) { - if (this._isFollowingOrFulfilledOrRejected()) return; - if (value === this) - return this._rejectCallback(makeSelfResolutionError(), false, true); - var maybePromise = tryConvertToPromise(value, this); - if (!(maybePromise instanceof Promise)) return this._fulfill(value); +function map(promises, fn, options, _filter) { + var limit = typeof options === "object" && options !== null + ? options.concurrency + : 0; + limit = typeof limit === "number" && + isFinite(limit) && limit >= 1 ? limit : 0; + return new MappingPromiseArray(promises, fn, limit, _filter); +} - var propagationFlags = 1 | (shouldBind ? 4 : 0); - this._propagateFrom(maybePromise, propagationFlags); - var promise = maybePromise._target(); - if (promise._isPending()) { - var len = this._length(); - for (var i = 0; i < len; ++i) { - promise._migrateCallbacks(this, i); - } - this._setFollowing(); - this._setLength(0); - this._setFollowee(promise); - } else if (promise._isFulfilled()) { - this._fulfillUnchecked(promise._value()); - } else { - this._rejectUnchecked(promise._reason(), - promise._getCarriedStackTrace()); - } +Promise.prototype.map = function (fn, options) { + if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); + + return map(this, fn, options, null).promise(); }; -Promise.prototype._rejectCallback = -function(reason, synchronous, shouldNotMarkOriginatingFromRejection) { - if (!shouldNotMarkOriginatingFromRejection) { - util.markAsOriginatingFromRejection(reason); - } - var trace = util.ensureErrorObject(reason); - var hasStack = trace === reason; - this._attachExtraTrace(trace, synchronous ? hasStack : false); - this._reject(reason, hasStack ? undefined : trace); +Promise.map = function (promises, fn, options, _filter) { + if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); + return map(promises, fn, options, _filter).promise(); }; -Promise.prototype._resolveFromResolver = function (resolver) { - var promise = this; - this._captureStackTrace(); - this._pushContext(); - var synchronous = true; - var r = tryCatch(resolver)(function(value) { - if (promise === null) return; - promise._resolveCallback(value); - promise = null; - }, function (reason) { - if (promise === null) return; - promise._rejectCallback(reason, synchronous); - promise = null; - }); - synchronous = false; - this._popContext(); - if (r !== undefined && r === errorObj && promise !== null) { - promise._rejectCallback(r.e, true, true); - promise = null; +}; + +},{"./async.js":2,"./util.js":38}],20:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, INTERNAL, tryConvertToPromise, apiRejection) { +var util = _dereq_("./util.js"); +var tryCatch = util.tryCatch; + +Promise.method = function (fn) { + if (typeof fn !== "function") { + throw new Promise.TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); } + return function () { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value = tryCatch(fn).apply(this, arguments); + ret._popContext(); + ret._resolveFromSyncValue(value); + return ret; + }; }; -Promise.prototype._settlePromiseFromHandler = function ( - handler, receiver, value, promise -) { - if (promise._isRejected()) return; - promise._pushContext(); - var x; - if (receiver === APPLY && !this._isRejected()) { - x = tryCatch(handler).apply(this._boundValue(), value); - } else { - x = tryCatch(handler).call(receiver, value); +Promise.attempt = Promise["try"] = function (fn, args, ctx) { + if (typeof fn !== "function") { + return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); } - promise._popContext(); + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value = util.isArray(args) + ? tryCatch(fn).apply(ctx, args) + : tryCatch(fn).call(ctx, args); + ret._popContext(); + ret._resolveFromSyncValue(value); + return ret; +}; - if (x === errorObj || x === promise || x === NEXT_FILTER) { - var err = x === promise ? makeSelfResolutionError() : x.e; - promise._rejectCallback(err, false, true); +Promise.prototype._resolveFromSyncValue = function (value) { + if (value === util.errorObj) { + this._rejectCallback(value.e, false, true); } else { - promise._resolveCallback(x); + this._resolveCallback(value, true); } }; +}; -Promise.prototype._target = function() { - var ret = this; - while (ret._isFollowing()) ret = ret._followee(); - return ret; +},{"./util.js":38}],21:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +var util = _dereq_("./util.js"); +var async = _dereq_("./async.js"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; + +function spreadAdapter(val, nodeback) { + var promise = this; + if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback); + var ret = + tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val)); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} + +function successAdapter(val, nodeback) { + var promise = this; + var receiver = promise._boundValue(); + var ret = val === undefined + ? tryCatch(nodeback).call(receiver, null) + : tryCatch(nodeback).call(receiver, null, val); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} +function errorAdapter(reason, nodeback) { + var promise = this; + if (!reason) { + var target = promise._target(); + var newReason = target._getCarriedStackTrace(); + newReason.cause = reason; + reason = newReason; + } + var ret = tryCatch(nodeback).call(promise._boundValue(), reason); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} + +Promise.prototype.asCallback = +Promise.prototype.nodeify = function (nodeback, options) { + if (typeof nodeback == "function") { + var adapter = successAdapter; + if (options !== undefined && Object(options).spread) { + adapter = spreadAdapter; + } + this._then( + adapter, + errorAdapter, + undefined, + this, + nodeback + ); + } + return this; +}; }; -Promise.prototype._followee = function() { - return this._rejectionHandler0; +},{"./async.js":2,"./util.js":38}],22:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, PromiseArray) { +var util = _dereq_("./util.js"); +var async = _dereq_("./async.js"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; + +Promise.prototype.progressed = function (handler) { + return this._then(undefined, undefined, handler, undefined, undefined); +}; + +Promise.prototype._progress = function (progressValue) { + if (this._isFollowingOrFulfilledOrRejected()) return; + this._target()._progressUnchecked(progressValue); + }; -Promise.prototype._setFollowee = function(promise) { - this._rejectionHandler0 = promise; +Promise.prototype._progressHandlerAt = function (index) { + return index === 0 + ? this._progressHandler0 + : this[(index << 2) + index - 5 + 2]; }; -Promise.prototype._cleanValues = function () { - if (this._cancellable()) { - this._cancellationParent = undefined; +Promise.prototype._doProgressWith = function (progression) { + var progressValue = progression.value; + var handler = progression.handler; + var promise = progression.promise; + var receiver = progression.receiver; + + var ret = tryCatch(handler).call(receiver, progressValue); + if (ret === errorObj) { + if (ret.e != null && + ret.e.name !== "StopProgressPropagation") { + var trace = util.canAttachTrace(ret.e) + ? ret.e : new Error(util.toString(ret.e)); + promise._attachExtraTrace(trace); + promise._progress(ret.e); + } + } else if (ret instanceof Promise) { + ret._then(promise._progress, null, null, promise, undefined); + } else { + promise._progress(ret); } }; -Promise.prototype._propagateFrom = function (parent, flags) { - if ((flags & 1) > 0 && parent._cancellable()) { - this._setCancellable(); - this._cancellationParent = parent; - } - if ((flags & 4) > 0 && parent._isBound()) { - this._setBoundTo(parent._boundTo); + +Promise.prototype._progressUnchecked = function (progressValue) { + var len = this._length(); + var progress = this._progress; + for (var i = 0; i < len; i++) { + var handler = this._progressHandlerAt(i); + var promise = this._promiseAt(i); + if (!(promise instanceof Promise)) { + var receiver = this._receiverAt(i); + if (typeof handler === "function") { + handler.call(receiver, progressValue, promise); + } else if (receiver instanceof PromiseArray && + !receiver._isResolved()) { + receiver._promiseProgressed(progressValue, promise); + } + continue; + } + + if (typeof handler === "function") { + async.invoke(this._doProgressWith, this, { + handler: handler, + promise: promise, + receiver: this._receiverAt(i), + value: progressValue + }); + } else { + async.invoke(progress, promise, progressValue); + } } }; - -Promise.prototype._fulfill = function (value) { - if (this._isFollowingOrFulfilledOrRejected()) return; - this._fulfillUnchecked(value); }; -Promise.prototype._reject = function (reason, carriedStackTrace) { - if (this._isFollowingOrFulfilledOrRejected()) return; - this._rejectUnchecked(reason, carriedStackTrace); +},{"./async.js":2,"./util.js":38}],23:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function() { +var makeSelfResolutionError = function () { + return new TypeError("circular promise resolution chain\u000a\u000a See http://goo.gl/LhFpo0\u000a"); +}; +var reflect = function() { + return new Promise.PromiseInspection(this._target()); +}; +var apiRejection = function(msg) { + return Promise.reject(new TypeError(msg)); }; -Promise.prototype._settlePromiseAt = function (index) { - var promise = this._promiseAt(index); - var isPromise = promise instanceof Promise; +var util = _dereq_("./util.js"); - if (isPromise && promise._isMigrated()) { - promise._unsetIsMigrated(); - return async.invoke(this._settlePromiseAt, this, index); +var getDomain; +if (util.isNode) { + getDomain = function() { + var ret = process.domain; + if (ret === undefined) ret = null; + return ret; + }; +} else { + getDomain = function() { + return null; + }; +} +util.notEnumerableProp(Promise, "_getDomain", getDomain); + +var UNDEFINED_BINDING = {}; +var async = _dereq_("./async.js"); +var errors = _dereq_("./errors.js"); +var TypeError = Promise.TypeError = errors.TypeError; +Promise.RangeError = errors.RangeError; +Promise.CancellationError = errors.CancellationError; +Promise.TimeoutError = errors.TimeoutError; +Promise.OperationalError = errors.OperationalError; +Promise.RejectionError = errors.OperationalError; +Promise.AggregateError = errors.AggregateError; +var INTERNAL = function(){}; +var APPLY = {}; +var NEXT_FILTER = {e: null}; +var tryConvertToPromise = _dereq_("./thenables.js")(Promise, INTERNAL); +var PromiseArray = + _dereq_("./promise_array.js")(Promise, INTERNAL, + tryConvertToPromise, apiRejection); +var CapturedTrace = _dereq_("./captured_trace.js")(); +var isDebugging = _dereq_("./debuggability.js")(Promise, CapturedTrace); + /*jshint unused:false*/ +var createContext = + _dereq_("./context.js")(Promise, CapturedTrace, isDebugging); +var CatchFilter = _dereq_("./catch_filter.js")(NEXT_FILTER); +var PromiseResolver = _dereq_("./promise_resolver.js"); +var nodebackForPromise = PromiseResolver._nodebackForPromise; +var errorObj = util.errorObj; +var tryCatch = util.tryCatch; +function Promise(resolver) { + if (typeof resolver !== "function") { + throw new TypeError("the promise constructor requires a resolver function\u000a\u000a See http://goo.gl/EC22Yn\u000a"); } - var handler = this._isFulfilled() - ? this._fulfillmentHandlerAt(index) - : this._rejectionHandlerAt(index); + if (this.constructor !== Promise) { + throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a See http://goo.gl/KsIlge\u000a"); + } + this._bitField = 0; + this._fulfillmentHandler0 = undefined; + this._rejectionHandler0 = undefined; + this._progressHandler0 = undefined; + this._promise0 = undefined; + this._receiver0 = undefined; + this._settledValue = undefined; + if (resolver !== INTERNAL) this._resolveFromResolver(resolver); +} - var carriedStackTrace = - this._isCarryingStackTrace() ? this._getCarriedStackTrace() : undefined; - var value = this._settledValue; - var receiver = this._receiverAt(index); - this._clearCallbackDataAtIndex(index); +Promise.prototype.toString = function () { + return "[object Promise]"; +}; - if (typeof handler === "function") { - if (!isPromise) { - handler.call(receiver, value, promise); - } else { - this._settlePromiseFromHandler(handler, receiver, value, promise); - } - } else if (receiver instanceof PromiseArray) { - if (!receiver._isResolved()) { - if (this._isFulfilled()) { - receiver._promiseFulfilled(value, promise); - } - else { - receiver._promiseRejected(value, promise); +Promise.prototype.caught = Promise.prototype["catch"] = function (fn) { + var len = arguments.length; + if (len > 1) { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (typeof item === "function") { + catchInstances[j++] = item; + } else { + return Promise.reject( + new TypeError("Catch filter must inherit from Error or be a simple predicate function\u000a\u000a See http://goo.gl/o84o68\u000a")); } } - } else if (isPromise) { - if (this._isFulfilled()) { - promise._fulfill(value); - } else { - promise._reject(value, carriedStackTrace); - } + catchInstances.length = j; + fn = arguments[i]; + var catchFilter = new CatchFilter(catchInstances, fn, this); + return this._then(undefined, catchFilter.doFilter, undefined, + catchFilter, undefined); } + return this._then(undefined, fn, undefined, undefined, undefined); +}; - if (index >= 4 && (index & 31) === 4) - async.invokeLater(this._setLength, this, 0); +Promise.prototype.reflect = function () { + return this._then(reflect, reflect, undefined, this, undefined); }; -Promise.prototype._clearCallbackDataAtIndex = function(index) { - if (index === 0) { - if (!this._isCarryingStackTrace()) { - this._fulfillmentHandler0 = undefined; +Promise.prototype.then = function (didFulfill, didReject, didProgress) { + if (isDebugging() && arguments.length > 0 && + typeof didFulfill !== "function" && + typeof didReject !== "function") { + var msg = ".then() only accepts functions but was passed: " + + util.classString(didFulfill); + if (arguments.length > 1) { + msg += ", " + util.classString(didReject); } - this._rejectionHandler0 = - this._progressHandler0 = - this._receiver0 = - this._promise0 = undefined; - } else { - var base = index * 5 - 5; - this[base + 3] = - this[base + 4] = - this[base + 0] = - this[base + 1] = - this[base + 2] = undefined; + this._warn(msg); } + return this._then(didFulfill, didReject, didProgress, + undefined, undefined); }; -Promise.prototype._isSettlePromisesQueued = function () { - return (this._bitField & - -1073741824) === -1073741824; +Promise.prototype.done = function (didFulfill, didReject, didProgress) { + var promise = this._then(didFulfill, didReject, didProgress, + undefined, undefined); + promise._setIsFinal(); +}; + +Promise.prototype.spread = function (didFulfill, didReject) { + return this.all()._then(didFulfill, didReject, undefined, APPLY, undefined); +}; + +Promise.prototype.isCancellable = function () { + return !this.isResolved() && + this._cancellable(); +}; + +Promise.prototype.toJSON = function () { + var ret = { + isFulfilled: false, + isRejected: false, + fulfillmentValue: undefined, + rejectionReason: undefined + }; + if (this.isFulfilled()) { + ret.fulfillmentValue = this.value(); + ret.isFulfilled = true; + } else if (this.isRejected()) { + ret.rejectionReason = this.reason(); + ret.isRejected = true; + } + return ret; }; -Promise.prototype._setSettlePromisesQueued = function () { - this._bitField = this._bitField | -1073741824; +Promise.prototype.all = function () { + return new PromiseArray(this).promise(); }; -Promise.prototype._unsetSettlePromisesQueued = function () { - this._bitField = this._bitField & (~-1073741824); +Promise.prototype.error = function (fn) { + return this.caught(util.originatesFromRejection, fn); }; -Promise.prototype._queueSettlePromises = function() { - async.settlePromises(this); - this._setSettlePromisesQueued(); +Promise.is = function (val) { + return val instanceof Promise; }; -Promise.prototype._fulfillUnchecked = function (value) { - if (value === this) { - var err = makeSelfResolutionError(); - this._attachExtraTrace(err); - return this._rejectUnchecked(err, undefined); - } - this._setFulfilled(); - this._settledValue = value; - this._cleanValues(); - - if (this._length() > 0) { - this._queueSettlePromises(); +Promise.fromNode = function(fn) { + var ret = new Promise(INTERNAL); + var result = tryCatch(fn)(nodebackForPromise(ret)); + if (result === errorObj) { + ret._rejectCallback(result.e, true, true); } + return ret; }; -Promise.prototype._rejectUncheckedCheckError = function (reason) { - var trace = util.ensureErrorObject(reason); - this._rejectUnchecked(reason, trace === reason ? undefined : trace); +Promise.all = function (promises) { + return new PromiseArray(promises).promise(); }; -Promise.prototype._rejectUnchecked = function (reason, trace) { - if (reason === this) { - var err = makeSelfResolutionError(); - this._attachExtraTrace(err); - return this._rejectUnchecked(err); - } - this._setRejected(); - this._settledValue = reason; - this._cleanValues(); - - if (this._isFinal()) { - async.throwLater(function(e) { - if ("stack" in e) { - async.invokeFirst( - CapturedTrace.unhandledRejection, undefined, e); - } - throw e; - }, trace === undefined ? reason : trace); - return; - } - - if (trace !== undefined && trace !== reason) { - this._setCarriedStackTrace(trace); - } - - if (this._length() > 0) { - this._queueSettlePromises(); - } else { - this._ensurePossibleRejectionHandled(); - } +Promise.defer = Promise.pending = function () { + var promise = new Promise(INTERNAL); + return new PromiseResolver(promise); }; -Promise.prototype._settlePromises = function () { - this._unsetSettlePromisesQueued(); - var len = this._length(); - for (var i = 0; i < len; i++) { - this._settlePromiseAt(i); +Promise.cast = function (obj) { + var ret = tryConvertToPromise(obj); + if (!(ret instanceof Promise)) { + var val = ret; + ret = new Promise(INTERNAL); + ret._fulfillUnchecked(val); } + return ret; }; -util.notEnumerableProp(Promise, - "_makeSelfResolutionError", - makeSelfResolutionError); +Promise.resolve = Promise.fulfilled = Promise.cast; -_dereq_("./progress.js")(Promise, PromiseArray); -_dereq_("./method.js")(Promise, INTERNAL, tryConvertToPromise, apiRejection); -_dereq_("./bind.js")(Promise, INTERNAL, tryConvertToPromise); -_dereq_("./finally.js")(Promise, NEXT_FILTER, tryConvertToPromise); -_dereq_("./direct_resolve.js")(Promise); -_dereq_("./synchronous_inspection.js")(Promise); -_dereq_("./join.js")(Promise, PromiseArray, tryConvertToPromise, INTERNAL); -Promise.Promise = Promise; -_dereq_('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL); -_dereq_('./cancel.js')(Promise); -_dereq_('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext); -_dereq_('./generators.js')(Promise, apiRejection, INTERNAL, tryConvertToPromise); -_dereq_('./nodeify.js')(Promise); -_dereq_('./call_get.js')(Promise); -_dereq_('./props.js')(Promise, PromiseArray, tryConvertToPromise, apiRejection); -_dereq_('./race.js')(Promise, INTERNAL, tryConvertToPromise, apiRejection); -_dereq_('./reduce.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL); -_dereq_('./settle.js')(Promise, PromiseArray); -_dereq_('./some.js')(Promise, PromiseArray, apiRejection); -_dereq_('./promisify.js')(Promise, INTERNAL); -_dereq_('./any.js')(Promise); -_dereq_('./each.js')(Promise, INTERNAL); -_dereq_('./timers.js')(Promise, INTERNAL); -_dereq_('./filter.js')(Promise, INTERNAL); - - util.toFastProperties(Promise); - util.toFastProperties(Promise.prototype); - function fillTypes(value) { - var p = new Promise(INTERNAL); - p._fulfillmentHandler0 = value; - p._rejectionHandler0 = value; - p._progressHandler0 = value; - p._promise0 = value; - p._receiver0 = value; - p._settledValue = value; - } - // Complete slack tracking, opt out of field-type tracking and - // stabilize map - fillTypes({a: 1}); - fillTypes({b: 2}); - fillTypes({c: 3}); - fillTypes(1); - fillTypes(function(){}); - fillTypes(undefined); - fillTypes(false); - fillTypes(new Promise(INTERNAL)); - CapturedTrace.setBounds(async.firstLineError, util.lastLineError); - return Promise; +Promise.reject = Promise.rejected = function (reason) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._rejectCallback(reason, true); + return ret; +}; +Promise.setScheduler = function(fn) { + if (typeof fn !== "function") throw new TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); + var prev = async._schedule; + async._schedule = fn; + return prev; }; -},{"./any.js":1,"./async.js":2,"./bind.js":3,"./call_get.js":5,"./cancel.js":6,"./captured_trace.js":7,"./catch_filter.js":8,"./context.js":9,"./debuggability.js":10,"./direct_resolve.js":11,"./each.js":12,"./errors.js":13,"./filter.js":15,"./finally.js":16,"./generators.js":17,"./join.js":18,"./map.js":19,"./method.js":20,"./nodeify.js":21,"./progress.js":22,"./promise_array.js":24,"./promise_resolver.js":25,"./promisify.js":26,"./props.js":27,"./race.js":29,"./reduce.js":30,"./settle.js":32,"./some.js":33,"./synchronous_inspection.js":34,"./thenables.js":35,"./timers.js":36,"./using.js":37,"./util.js":38}],24:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, INTERNAL, tryConvertToPromise, - apiRejection) { -var util = _dereq_("./util.js"); -var isArray = util.isArray; +Promise.prototype._then = function ( + didFulfill, + didReject, + didProgress, + receiver, + internalData +) { + var haveInternalData = internalData !== undefined; + var ret = haveInternalData ? internalData : new Promise(INTERNAL); -function toResolutionValue(val) { - switch(val) { - case -2: return []; - case -3: return {}; + if (!haveInternalData) { + ret._propagateFrom(this, 4 | 1); + ret._captureStackTrace(); } -} -function PromiseArray(values) { - var promise = this._promise = new Promise(INTERNAL); - var parent; - if (values instanceof Promise) { - parent = values; - promise._propagateFrom(parent, 1 | 4); + var target = this._target(); + if (target !== this) { + if (receiver === undefined) receiver = this._boundTo; + if (!haveInternalData) ret._setIsMigrated(); } - this._values = values; - this._length = 0; - this._totalResolved = 0; - this._init(undefined, -2); -} -PromiseArray.prototype.length = function () { - return this._length; -}; - -PromiseArray.prototype.promise = function () { - return this._promise; -}; -PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) { - var values = tryConvertToPromise(this._values, this._promise); - if (values instanceof Promise) { - values = values._target(); - this._values = values; - if (values._isFulfilled()) { - values = values._value(); - if (!isArray(values)) { - var err = new Promise.TypeError("expecting an array, a promise or a thenable\u000a\u000a See http://goo.gl/s8MMhc\u000a"); - this.__hardReject__(err); - return; - } - } else if (values._isPending()) { - values._then( - init, - this._reject, - undefined, - this, - resolveValueIfEmpty - ); - return; - } else { - this._reject(values._reason()); - return; - } - } else if (!isArray(values)) { - this._promise._reject(apiRejection("expecting an array, a promise or a thenable\u000a\u000a See http://goo.gl/s8MMhc\u000a")._reason()); - return; - } + var callbackIndex = target._addCallbacks(didFulfill, + didReject, + didProgress, + ret, + receiver, + getDomain()); - if (values.length === 0) { - if (resolveValueIfEmpty === -5) { - this._resolveEmptyArray(); - } - else { - this._resolve(toResolutionValue(resolveValueIfEmpty)); - } - return; - } - var len = this.getActualLength(values.length); - this._length = len; - this._values = this.shouldCopyValues() ? new Array(len) : this._values; - var promise = this._promise; - for (var i = 0; i < len; ++i) { - var isResolved = this._isResolved(); - var maybePromise = tryConvertToPromise(values[i], promise); - if (maybePromise instanceof Promise) { - maybePromise = maybePromise._target(); - if (isResolved) { - maybePromise._ignoreRejections(); - } else if (maybePromise._isPending()) { - maybePromise._proxyPromiseArray(this, i); - } else if (maybePromise._isFulfilled()) { - this._promiseFulfilled(maybePromise._value(), i); - } else { - this._promiseRejected(maybePromise._reason(), i); - } - } else if (!isResolved) { - this._promiseFulfilled(maybePromise, i); - } + if (target._isResolved() && !target._isSettlePromisesQueued()) { + async.invoke( + target._settlePromiseAtPostResolution, target, callbackIndex); } -}; -PromiseArray.prototype._isResolved = function () { - return this._values === null; + return ret; }; -PromiseArray.prototype._resolve = function (value) { - this._values = null; - this._promise._fulfill(value); +Promise.prototype._settlePromiseAtPostResolution = function (index) { + if (this._isRejectionUnhandled()) this._unsetRejectionIsUnhandled(); + this._settlePromiseAt(index); }; -PromiseArray.prototype.__hardReject__ = -PromiseArray.prototype._reject = function (reason) { - this._values = null; - this._promise._rejectCallback(reason, false, true); +Promise.prototype._length = function () { + return this._bitField & 131071; }; -PromiseArray.prototype._promiseProgressed = function (progressValue, index) { - this._promise._progress({ - index: index, - value: progressValue - }); +Promise.prototype._isFollowingOrFulfilledOrRejected = function () { + return (this._bitField & 939524096) > 0; }; - -PromiseArray.prototype._promiseFulfilled = function (value, index) { - this._values[index] = value; - var totalResolved = ++this._totalResolved; - if (totalResolved >= this._length) { - this._resolve(this._values); - } +Promise.prototype._isFollowing = function () { + return (this._bitField & 536870912) === 536870912; }; -PromiseArray.prototype._promiseRejected = function (reason, index) { - this._totalResolved++; - this._reject(reason); +Promise.prototype._setLength = function (len) { + this._bitField = (this._bitField & -131072) | + (len & 131071); }; -PromiseArray.prototype.shouldCopyValues = function () { - return true; +Promise.prototype._setFulfilled = function () { + this._bitField = this._bitField | 268435456; }; -PromiseArray.prototype.getActualLength = function (len) { - return len; +Promise.prototype._setRejected = function () { + this._bitField = this._bitField | 134217728; }; -return PromiseArray; +Promise.prototype._setFollowing = function () { + this._bitField = this._bitField | 536870912; }; -},{"./util.js":38}],25:[function(_dereq_,module,exports){ -"use strict"; -var util = _dereq_("./util.js"); -var maybeWrapAsError = util.maybeWrapAsError; -var errors = _dereq_("./errors.js"); -var TimeoutError = errors.TimeoutError; -var OperationalError = errors.OperationalError; -var haveGetters = util.haveGetters; -var es5 = _dereq_("./es5.js"); - -function isUntypedError(obj) { - return obj instanceof Error && - es5.getPrototypeOf(obj) === Error.prototype; -} - -var rErrorKey = /^(?:name|message|stack|cause)$/; -function wrapAsOperationalError(obj) { - var ret; - if (isUntypedError(obj)) { - ret = new OperationalError(obj); - ret.name = obj.name; - ret.message = obj.message; - ret.stack = obj.stack; - var keys = es5.keys(obj); - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - if (!rErrorKey.test(key)) { - ret[key] = obj[key]; - } - } - return ret; - } - util.markAsOriginatingFromRejection(obj); - return obj; -} - -function nodebackForPromise(promise) { - return function(err, value) { - if (promise === null) return; - - if (err) { - var wrapped = wrapAsOperationalError(maybeWrapAsError(err)); - promise._attachExtraTrace(wrapped); - promise._reject(wrapped); - } else if (arguments.length > 2) { - var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];} - promise._fulfill(args); - } else { - promise._fulfill(value); - } - - promise = null; - }; -} - - -var PromiseResolver; -if (!haveGetters) { - PromiseResolver = function (promise) { - this.promise = promise; - this.asCallback = nodebackForPromise(promise); - this.callback = this.asCallback; - }; -} -else { - PromiseResolver = function (promise) { - this.promise = promise; - }; -} -if (haveGetters) { - var prop = { - get: function() { - return nodebackForPromise(this.promise); - } - }; - es5.defineProperty(PromiseResolver.prototype, "asCallback", prop); - es5.defineProperty(PromiseResolver.prototype, "callback", prop); -} - -PromiseResolver._nodebackForPromise = nodebackForPromise; - -PromiseResolver.prototype.toString = function () { - return "[object PromiseResolver]"; +Promise.prototype._setIsFinal = function () { + this._bitField = this._bitField | 33554432; }; -PromiseResolver.prototype.resolve = -PromiseResolver.prototype.fulfill = function (value) { - if (!(this instanceof PromiseResolver)) { - throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.\u000a\u000a See http://goo.gl/sdkXL9\u000a"); - } - this.promise._resolveCallback(value); +Promise.prototype._isFinal = function () { + return (this._bitField & 33554432) > 0; }; -PromiseResolver.prototype.reject = function (reason) { - if (!(this instanceof PromiseResolver)) { - throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.\u000a\u000a See http://goo.gl/sdkXL9\u000a"); - } - this.promise._rejectCallback(reason); +Promise.prototype._cancellable = function () { + return (this._bitField & 67108864) > 0; }; -PromiseResolver.prototype.progress = function (value) { - if (!(this instanceof PromiseResolver)) { - throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.\u000a\u000a See http://goo.gl/sdkXL9\u000a"); - } - this.promise._progress(value); +Promise.prototype._setCancellable = function () { + this._bitField = this._bitField | 67108864; }; -PromiseResolver.prototype.cancel = function (err) { - this.promise.cancel(err); +Promise.prototype._unsetCancellable = function () { + this._bitField = this._bitField & (~67108864); }; -PromiseResolver.prototype.timeout = function () { - this.reject(new TimeoutError("timeout")); +Promise.prototype._setIsMigrated = function () { + this._bitField = this._bitField | 4194304; }; -PromiseResolver.prototype.isResolved = function () { - return this.promise.isResolved(); +Promise.prototype._unsetIsMigrated = function () { + this._bitField = this._bitField & (~4194304); }; -PromiseResolver.prototype.toJSON = function () { - return this.promise.toJSON(); +Promise.prototype._isMigrated = function () { + return (this._bitField & 4194304) > 0; }; -module.exports = PromiseResolver; - -},{"./errors.js":13,"./es5.js":14,"./util.js":38}],26:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, INTERNAL) { -var THIS = {}; -var util = _dereq_("./util.js"); -var nodebackForPromise = _dereq_("./promise_resolver.js") - ._nodebackForPromise; -var withAppended = util.withAppended; -var maybeWrapAsError = util.maybeWrapAsError; -var canEvaluate = util.canEvaluate; -var TypeError = _dereq_("./errors").TypeError; -var defaultSuffix = "Async"; -var defaultPromisified = {__isPromisified__: true}; -var noCopyProps = [ - "arity", "length", - "name", - "arguments", - "caller", - "callee", - "prototype", - "__isPromisified__" -]; -var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$"); - -var defaultFilter = function(name) { - return util.isIdentifier(name) && - name.charAt(0) !== "_" && - name !== "constructor"; +Promise.prototype._receiverAt = function (index) { + var ret = index === 0 + ? this._receiver0 + : this[ + index * 5 - 5 + 4]; + if (ret === UNDEFINED_BINDING) { + return undefined; + } else if (ret === undefined && this._isBound()) { + return this._boundValue(); + } + return ret; }; -function propsFilter(key) { - return !noCopyPropsPattern.test(key); -} +Promise.prototype._promiseAt = function (index) { + return index === 0 + ? this._promise0 + : this[index * 5 - 5 + 3]; +}; -function isPromisified(fn) { - try { - return fn.__isPromisified__ === true; - } - catch (e) { - return false; - } -} +Promise.prototype._fulfillmentHandlerAt = function (index) { + return index === 0 + ? this._fulfillmentHandler0 + : this[index * 5 - 5 + 0]; +}; -function hasPromisified(obj, key, suffix) { - var val = util.getDataPropertyOrDefault(obj, key + suffix, - defaultPromisified); - return val ? isPromisified(val) : false; -} -function checkValid(ret, suffix, suffixRegexp) { - for (var i = 0; i < ret.length; i += 2) { - var key = ret[i]; - if (suffixRegexp.test(key)) { - var keyWithoutAsyncSuffix = key.replace(suffixRegexp, ""); - for (var j = 0; j < ret.length; j += 2) { - if (ret[j] === keyWithoutAsyncSuffix) { - throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a See http://goo.gl/iWrZbw\u000a" - .replace("%s", suffix)); - } - } - } - } -} +Promise.prototype._rejectionHandlerAt = function (index) { + return index === 0 + ? this._rejectionHandler0 + : this[index * 5 - 5 + 1]; +}; -function promisifiableMethods(obj, suffix, suffixRegexp, filter) { - var keys = util.inheritedDataKeys(obj); - var ret = []; - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - var value = obj[key]; - var passesDefaultFilter = filter === defaultFilter - ? true : defaultFilter(key, value, obj); - if (typeof value === "function" && - !isPromisified(value) && - !hasPromisified(obj, key, suffix) && - filter(key, value, obj, passesDefaultFilter)) { - ret.push(key, value); +Promise.prototype._boundValue = function() { + var ret = this._boundTo; + if (ret !== undefined) { + if (ret instanceof Promise) { + if (ret.isFulfilled()) { + return ret.value(); + } else { + return undefined; + } } } - checkValid(ret, suffix, suffixRegexp); return ret; -} +}; -var escapeIdentRegex = function(str) { - return str.replace(/([$])/, "\\$"); +Promise.prototype._migrateCallbacks = function (follower, index) { + var fulfill = follower._fulfillmentHandlerAt(index); + var reject = follower._rejectionHandlerAt(index); + var progress = follower._progressHandlerAt(index); + var promise = follower._promiseAt(index); + var receiver = follower._receiverAt(index); + if (promise instanceof Promise) promise._setIsMigrated(); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, progress, promise, receiver, null); }; -var makeNodePromisifiedEval; -if (!true) { -var switchCaseArgumentOrder = function(likelyArgumentCount) { - var ret = [likelyArgumentCount]; - var min = Math.max(0, likelyArgumentCount - 1 - 3); - for(var i = likelyArgumentCount - 1; i >= min; --i) { - ret.push(i); +Promise.prototype._addCallbacks = function ( + fulfill, + reject, + progress, + promise, + receiver, + domain +) { + var index = this._length(); + + if (index >= 131071 - 5) { + index = 0; + this._setLength(0); } - for(var i = likelyArgumentCount + 1; i <= 3; ++i) { - ret.push(i); + + if (index === 0) { + this._promise0 = promise; + if (receiver !== undefined) this._receiver0 = receiver; + if (typeof fulfill === "function" && !this._isCarryingStackTrace()) { + this._fulfillmentHandler0 = + domain === null ? fulfill : domain.bind(fulfill); + } + if (typeof reject === "function") { + this._rejectionHandler0 = + domain === null ? reject : domain.bind(reject); + } + if (typeof progress === "function") { + this._progressHandler0 = + domain === null ? progress : domain.bind(progress); + } + } else { + var base = index * 5 - 5; + this[base + 3] = promise; + this[base + 4] = receiver; + if (typeof fulfill === "function") { + this[base + 0] = + domain === null ? fulfill : domain.bind(fulfill); + } + if (typeof reject === "function") { + this[base + 1] = + domain === null ? reject : domain.bind(reject); + } + if (typeof progress === "function") { + this[base + 2] = + domain === null ? progress : domain.bind(progress); + } } - return ret; + this._setLength(index + 1); + return index; }; -var argumentSequence = function(argumentCount) { - return util.filledRange(argumentCount, "_arg", ""); -}; +Promise.prototype._setProxyHandlers = function (receiver, promiseSlotValue) { + var index = this._length(); -var parameterDeclaration = function(parameterCount) { - return util.filledRange( - Math.max(parameterCount, 3), "_arg", ""); + if (index >= 131071 - 5) { + index = 0; + this._setLength(0); + } + if (index === 0) { + this._promise0 = promiseSlotValue; + this._receiver0 = receiver; + } else { + var base = index * 5 - 5; + this[base + 3] = promiseSlotValue; + this[base + 4] = receiver; + } + this._setLength(index + 1); }; -var parameterCount = function(fn) { - if (typeof fn.length === "number") { - return Math.max(Math.min(fn.length, 1023 + 1), 0); - } - return 0; +Promise.prototype._proxyPromiseArray = function (promiseArray, index) { + this._setProxyHandlers(promiseArray, index); }; -makeNodePromisifiedEval = -function(callback, receiver, originalName, fn) { - var newParameterCount = Math.max(0, parameterCount(fn) - 1); - var argumentOrder = switchCaseArgumentOrder(newParameterCount); - var shouldProxyThis = typeof callback === "string" || receiver === THIS; +Promise.prototype._resolveCallback = function(value, shouldBind) { + if (this._isFollowingOrFulfilledOrRejected()) return; + if (value === this) + return this._rejectCallback(makeSelfResolutionError(), false, true); + var maybePromise = tryConvertToPromise(value, this); + if (!(maybePromise instanceof Promise)) return this._fulfill(value); - function generateCallForArgumentCount(count) { - var args = argumentSequence(count).join(", "); - var comma = count > 0 ? ", " : ""; - var ret; - if (shouldProxyThis) { - ret = "ret = callback.call(this, {{args}}, nodeback); break;\n"; - } else { - ret = receiver === undefined - ? "ret = callback({{args}}, nodeback); break;\n" - : "ret = callback.call(receiver, {{args}}, nodeback); break;\n"; + var propagationFlags = 1 | (shouldBind ? 4 : 0); + this._propagateFrom(maybePromise, propagationFlags); + var promise = maybePromise._target(); + if (promise._isPending()) { + var len = this._length(); + for (var i = 0; i < len; ++i) { + promise._migrateCallbacks(this, i); } - return ret.replace("{{args}}", args).replace(", ", comma); + this._setFollowing(); + this._setLength(0); + this._setFollowee(promise); + } else if (promise._isFulfilled()) { + this._fulfillUnchecked(promise._value()); + } else { + this._rejectUnchecked(promise._reason(), + promise._getCarriedStackTrace()); } +}; - function generateArgumentSwitchCase() { - var ret = ""; - for (var i = 0; i < argumentOrder.length; ++i) { - ret += "case " + argumentOrder[i] +":" + - generateCallForArgumentCount(argumentOrder[i]); - } - - ret += " \n\ - default: \n\ - var args = new Array(len + 1); \n\ - var i = 0; \n\ - for (var i = 0; i < len; ++i) { \n\ - args[i] = arguments[i]; \n\ - } \n\ - args[i] = nodeback; \n\ - [CodeForCall] \n\ - break; \n\ - ".replace("[CodeForCall]", (shouldProxyThis - ? "ret = callback.apply(this, args);\n" - : "ret = callback.apply(receiver, args);\n")); - return ret; +Promise.prototype._rejectCallback = +function(reason, synchronous, shouldNotMarkOriginatingFromRejection) { + if (!shouldNotMarkOriginatingFromRejection) { + util.markAsOriginatingFromRejection(reason); } + var trace = util.ensureErrorObject(reason); + var hasStack = trace === reason; + this._attachExtraTrace(trace, synchronous ? hasStack : false); + this._reject(reason, hasStack ? undefined : trace); +}; - var getFunctionCode = typeof callback === "string" - ? ("this != null ? this['"+callback+"'] : fn") - : "fn"; +Promise.prototype._resolveFromResolver = function (resolver) { + var promise = this; + this._captureStackTrace(); + this._pushContext(); + var synchronous = true; + var r = tryCatch(resolver)(function(value) { + if (promise === null) return; + promise._resolveCallback(value); + promise = null; + }, function (reason) { + if (promise === null) return; + promise._rejectCallback(reason, synchronous); + promise = null; + }); + synchronous = false; + this._popContext(); - return new Function("Promise", - "fn", - "receiver", - "withAppended", - "maybeWrapAsError", - "nodebackForPromise", - "tryCatch", - "errorObj", - "notEnumerableProp", - "INTERNAL","'use strict'; \n\ - var ret = function (Parameters) { \n\ - 'use strict'; \n\ - var len = arguments.length; \n\ - var promise = new Promise(INTERNAL); \n\ - promise._captureStackTrace(); \n\ - var nodeback = nodebackForPromise(promise); \n\ - var ret; \n\ - var callback = tryCatch([GetFunctionCode]); \n\ - switch(len) { \n\ - [CodeForSwitchCase] \n\ - } \n\ - if (ret === errorObj) { \n\ - promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\ - } \n\ - return promise; \n\ - }; \n\ - notEnumerableProp(ret, '__isPromisified__', true); \n\ - return ret; \n\ - " - .replace("Parameters", parameterDeclaration(newParameterCount)) - .replace("[CodeForSwitchCase]", generateArgumentSwitchCase()) - .replace("[GetFunctionCode]", getFunctionCode))( - Promise, - fn, - receiver, - withAppended, - maybeWrapAsError, - nodebackForPromise, - util.tryCatch, - util.errorObj, - util.notEnumerableProp, - INTERNAL - ); + if (r !== undefined && r === errorObj && promise !== null) { + promise._rejectCallback(r.e, true, true); + promise = null; + } }; -} -function makeNodePromisifiedClosure(callback, receiver, _, fn) { - var defaultThis = (function() {return this;})(); - var method = callback; - if (typeof method === "string") { - callback = fn; +Promise.prototype._settlePromiseFromHandler = function ( + handler, receiver, value, promise +) { + if (promise._isRejected()) return; + promise._pushContext(); + var x; + if (receiver === APPLY && !this._isRejected()) { + x = tryCatch(handler).apply(this._boundValue(), value); + } else { + x = tryCatch(handler).call(receiver, value); } - function promisified() { - var _receiver = receiver; - if (receiver === THIS) _receiver = this; - var promise = new Promise(INTERNAL); - promise._captureStackTrace(); - var cb = typeof method === "string" && this !== defaultThis - ? this[method] : callback; - var fn = nodebackForPromise(promise); - try { - cb.apply(_receiver, withAppended(arguments, fn)); - } catch(e) { - promise._rejectCallback(maybeWrapAsError(e), true, true); - } - return promise; + promise._popContext(); + + if (x === errorObj || x === promise || x === NEXT_FILTER) { + var err = x === promise ? makeSelfResolutionError() : x.e; + promise._rejectCallback(err, false, true); + } else { + promise._resolveCallback(x); } - util.notEnumerableProp(promisified, "__isPromisified__", true); - return promisified; -} +}; -var makeNodePromisified = canEvaluate - ? makeNodePromisifiedEval - : makeNodePromisifiedClosure; +Promise.prototype._target = function() { + var ret = this; + while (ret._isFollowing()) ret = ret._followee(); + return ret; +}; -function promisifyAll(obj, suffix, filter, promisifier) { - var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$"); - var methods = - promisifiableMethods(obj, suffix, suffixRegexp, filter); +Promise.prototype._followee = function() { + return this._rejectionHandler0; +}; - for (var i = 0, len = methods.length; i < len; i+= 2) { - var key = methods[i]; - var fn = methods[i+1]; - var promisifiedKey = key + suffix; - if (promisifier === makeNodePromisified) { - obj[promisifiedKey] = - makeNodePromisified(key, THIS, key, fn, suffix); - } else { - var promisified = promisifier(fn, function() { - return makeNodePromisified(key, THIS, key, fn, suffix); - }); - util.notEnumerableProp(promisified, "__isPromisified__", true); - obj[promisifiedKey] = promisified; - } - } - util.toFastProperties(obj); - return obj; -} +Promise.prototype._setFollowee = function(promise) { + this._rejectionHandler0 = promise; +}; -function promisify(callback, receiver) { - return makeNodePromisified(callback, receiver, undefined, callback); -} +Promise.prototype._cleanValues = function () { + if (this._cancellable()) { + this._cancellationParent = undefined; + } +}; -Promise.promisify = function (fn, receiver) { - if (typeof fn !== "function") { - throw new TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); +Promise.prototype._propagateFrom = function (parent, flags) { + if ((flags & 1) > 0 && parent._cancellable()) { + this._setCancellable(); + this._cancellationParent = parent; } - if (isPromisified(fn)) { - return fn; + if ((flags & 4) > 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); } - var ret = promisify(fn, arguments.length < 2 ? THIS : receiver); - util.copyDescriptors(fn, ret, propsFilter); - return ret; }; -Promise.promisifyAll = function (target, options) { - if (typeof target !== "function" && typeof target !== "object") { - throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a See http://goo.gl/9ITlV0\u000a"); +Promise.prototype._fulfill = function (value) { + if (this._isFollowingOrFulfilledOrRejected()) return; + this._fulfillUnchecked(value); +}; + +Promise.prototype._reject = function (reason, carriedStackTrace) { + if (this._isFollowingOrFulfilledOrRejected()) return; + this._rejectUnchecked(reason, carriedStackTrace); +}; + +Promise.prototype._settlePromiseAt = function (index) { + var promise = this._promiseAt(index); + var isPromise = promise instanceof Promise; + + if (isPromise && promise._isMigrated()) { + promise._unsetIsMigrated(); + return async.invoke(this._settlePromiseAt, this, index); } - options = Object(options); - var suffix = options.suffix; - if (typeof suffix !== "string") suffix = defaultSuffix; - var filter = options.filter; - if (typeof filter !== "function") filter = defaultFilter; - var promisifier = options.promisifier; - if (typeof promisifier !== "function") promisifier = makeNodePromisified; + var handler = this._isFulfilled() + ? this._fulfillmentHandlerAt(index) + : this._rejectionHandlerAt(index); - if (!util.isIdentifier(suffix)) { - throw new RangeError("suffix must be a valid identifier\u000a\u000a See http://goo.gl/8FZo5V\u000a"); + var carriedStackTrace = + this._isCarryingStackTrace() ? this._getCarriedStackTrace() : undefined; + var value = this._settledValue; + var receiver = this._receiverAt(index); + this._clearCallbackDataAtIndex(index); + + if (typeof handler === "function") { + if (!isPromise) { + handler.call(receiver, value, promise); + } else { + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (receiver instanceof PromiseArray) { + if (!receiver._isResolved()) { + if (this._isFulfilled()) { + receiver._promiseFulfilled(value, promise); + } + else { + receiver._promiseRejected(value, promise); + } + } + } else if (isPromise) { + if (this._isFulfilled()) { + promise._fulfill(value); + } else { + promise._reject(value, carriedStackTrace); + } } - var keys = util.inheritedDataKeys(target); - for (var i = 0; i < keys.length; ++i) { - var value = target[keys[i]]; - if (keys[i] !== "constructor" && - util.isClass(value)) { - promisifyAll(value.prototype, suffix, filter, promisifier); - promisifyAll(value, suffix, filter, promisifier); + if (index >= 4 && (index & 31) === 4) + async.invokeLater(this._setLength, this, 0); +}; + +Promise.prototype._clearCallbackDataAtIndex = function(index) { + if (index === 0) { + if (!this._isCarryingStackTrace()) { + this._fulfillmentHandler0 = undefined; } + this._rejectionHandler0 = + this._progressHandler0 = + this._receiver0 = + this._promise0 = undefined; + } else { + var base = index * 5 - 5; + this[base + 3] = + this[base + 4] = + this[base + 0] = + this[base + 1] = + this[base + 2] = undefined; } +}; - return promisifyAll(target, suffix, filter, promisifier); +Promise.prototype._isSettlePromisesQueued = function () { + return (this._bitField & + -1073741824) === -1073741824; +}; + +Promise.prototype._setSettlePromisesQueued = function () { + this._bitField = this._bitField | -1073741824; }; + +Promise.prototype._unsetSettlePromisesQueued = function () { + this._bitField = this._bitField & (~-1073741824); }; +Promise.prototype._queueSettlePromises = function() { + async.settlePromises(this); + this._setSettlePromisesQueued(); +}; -},{"./errors":13,"./promise_resolver.js":25,"./util.js":38}],27:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function( - Promise, PromiseArray, tryConvertToPromise, apiRejection) { -var util = _dereq_("./util.js"); -var isObject = util.isObject; -var es5 = _dereq_("./es5.js"); +Promise.prototype._fulfillUnchecked = function (value) { + if (value === this) { + var err = makeSelfResolutionError(); + this._attachExtraTrace(err); + return this._rejectUnchecked(err, undefined); + } + this._setFulfilled(); + this._settledValue = value; + this._cleanValues(); -function PropertiesPromiseArray(obj) { - var keys = es5.keys(obj); - var len = keys.length; - var values = new Array(len * 2); - for (var i = 0; i < len; ++i) { - var key = keys[i]; - values[i] = obj[key]; - values[i + len] = key; + if (this._length() > 0) { + this._queueSettlePromises(); + } +}; + +Promise.prototype._rejectUncheckedCheckError = function (reason) { + var trace = util.ensureErrorObject(reason); + this._rejectUnchecked(reason, trace === reason ? undefined : trace); +}; + +Promise.prototype._rejectUnchecked = function (reason, trace) { + if (reason === this) { + var err = makeSelfResolutionError(); + this._attachExtraTrace(err); + return this._rejectUnchecked(err); + } + this._setRejected(); + this._settledValue = reason; + this._cleanValues(); + + if (this._isFinal()) { + async.throwLater(function(e) { + if ("stack" in e) { + async.invokeFirst( + CapturedTrace.unhandledRejection, undefined, e); + } + throw e; + }, trace === undefined ? reason : trace); + return; + } + + if (trace !== undefined && trace !== reason) { + this._setCarriedStackTrace(trace); } - this.constructor$(values); -} -util.inherits(PropertiesPromiseArray, PromiseArray); -PropertiesPromiseArray.prototype._init = function () { - this._init$(undefined, -3) ; + if (this._length() > 0) { + this._queueSettlePromises(); + } else { + this._ensurePossibleRejectionHandled(); + } }; -PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) { - this._values[index] = value; - var totalResolved = ++this._totalResolved; - if (totalResolved >= this._length) { - var val = {}; - var keyOffset = this.length(); - for (var i = 0, len = this.length(); i < len; ++i) { - val[this._values[i + keyOffset]] = this._values[i]; - } - this._resolve(val); +Promise.prototype._settlePromises = function () { + this._unsetSettlePromisesQueued(); + var len = this._length(); + for (var i = 0; i < len; i++) { + this._settlePromiseAt(i); } }; -PropertiesPromiseArray.prototype._promiseProgressed = function (value, index) { - this._promise._progress({ - key: this._values[index + this.length()], - value: value - }); -}; +util.notEnumerableProp(Promise, + "_makeSelfResolutionError", + makeSelfResolutionError); -PropertiesPromiseArray.prototype.shouldCopyValues = function () { - return false; -}; +_dereq_("./progress.js")(Promise, PromiseArray); +_dereq_("./method.js")(Promise, INTERNAL, tryConvertToPromise, apiRejection); +_dereq_("./bind.js")(Promise, INTERNAL, tryConvertToPromise); +_dereq_("./finally.js")(Promise, NEXT_FILTER, tryConvertToPromise); +_dereq_("./direct_resolve.js")(Promise); +_dereq_("./synchronous_inspection.js")(Promise); +_dereq_("./join.js")(Promise, PromiseArray, tryConvertToPromise, INTERNAL); +Promise.Promise = Promise; +_dereq_('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL); +_dereq_('./cancel.js')(Promise); +_dereq_('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext); +_dereq_('./generators.js')(Promise, apiRejection, INTERNAL, tryConvertToPromise); +_dereq_('./nodeify.js')(Promise); +_dereq_('./call_get.js')(Promise); +_dereq_('./props.js')(Promise, PromiseArray, tryConvertToPromise, apiRejection); +_dereq_('./race.js')(Promise, INTERNAL, tryConvertToPromise, apiRejection); +_dereq_('./reduce.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL); +_dereq_('./settle.js')(Promise, PromiseArray); +_dereq_('./some.js')(Promise, PromiseArray, apiRejection); +_dereq_('./promisify.js')(Promise, INTERNAL); +_dereq_('./any.js')(Promise); +_dereq_('./each.js')(Promise, INTERNAL); +_dereq_('./timers.js')(Promise, INTERNAL); +_dereq_('./filter.js')(Promise, INTERNAL); + + util.toFastProperties(Promise); + util.toFastProperties(Promise.prototype); + function fillTypes(value) { + var p = new Promise(INTERNAL); + p._fulfillmentHandler0 = value; + p._rejectionHandler0 = value; + p._progressHandler0 = value; + p._promise0 = value; + p._receiver0 = value; + p._settledValue = value; + } + // Complete slack tracking, opt out of field-type tracking and + // stabilize map + fillTypes({a: 1}); + fillTypes({b: 2}); + fillTypes({c: 3}); + fillTypes(1); + fillTypes(function(){}); + fillTypes(undefined); + fillTypes(false); + fillTypes(new Promise(INTERNAL)); + CapturedTrace.setBounds(async.firstLineError, util.lastLineError); + return Promise; -PropertiesPromiseArray.prototype.getActualLength = function (len) { - return len >> 1; }; -function props(promises) { - var ret; - var castValue = tryConvertToPromise(promises); +},{"./any.js":1,"./async.js":2,"./bind.js":3,"./call_get.js":5,"./cancel.js":6,"./captured_trace.js":7,"./catch_filter.js":8,"./context.js":9,"./debuggability.js":10,"./direct_resolve.js":11,"./each.js":12,"./errors.js":13,"./filter.js":15,"./finally.js":16,"./generators.js":17,"./join.js":18,"./map.js":19,"./method.js":20,"./nodeify.js":21,"./progress.js":22,"./promise_array.js":24,"./promise_resolver.js":25,"./promisify.js":26,"./props.js":27,"./race.js":29,"./reduce.js":30,"./settle.js":32,"./some.js":33,"./synchronous_inspection.js":34,"./thenables.js":35,"./timers.js":36,"./using.js":37,"./util.js":38}],24:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise, + apiRejection) { +var util = _dereq_("./util.js"); +var isArray = util.isArray; - if (!isObject(castValue)) { - return apiRejection("cannot await properties of a non-object\u000a\u000a See http://goo.gl/OsFKC8\u000a"); - } else if (castValue instanceof Promise) { - ret = castValue._then( - Promise.props, undefined, undefined, undefined, undefined); - } else { - ret = new PropertiesPromiseArray(castValue).promise(); +function toResolutionValue(val) { + switch(val) { + case -2: return []; + case -3: return {}; } +} - if (castValue instanceof Promise) { - ret._propagateFrom(castValue, 4); +function PromiseArray(values) { + var promise = this._promise = new Promise(INTERNAL); + var parent; + if (values instanceof Promise) { + parent = values; + promise._propagateFrom(parent, 1 | 4); } - return ret; + this._values = values; + this._length = 0; + this._totalResolved = 0; + this._init(undefined, -2); } - -Promise.prototype.props = function () { - return props(this); +PromiseArray.prototype.length = function () { + return this._length; }; -Promise.props = function (promises) { - return props(promises); -}; +PromiseArray.prototype.promise = function () { + return this._promise; }; -},{"./es5.js":14,"./util.js":38}],28:[function(_dereq_,module,exports){ -"use strict"; -function arrayMove(src, srcIndex, dst, dstIndex, len) { - for (var j = 0; j < len; ++j) { - dst[j + dstIndex] = src[j + srcIndex]; - src[j + srcIndex] = void 0; +PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) { + var values = tryConvertToPromise(this._values, this._promise); + if (values instanceof Promise) { + values = values._target(); + this._values = values; + if (values._isFulfilled()) { + values = values._value(); + if (!isArray(values)) { + var err = new Promise.TypeError("expecting an array, a promise or a thenable\u000a\u000a See http://goo.gl/s8MMhc\u000a"); + this.__hardReject__(err); + return; + } + } else if (values._isPending()) { + values._then( + init, + this._reject, + undefined, + this, + resolveValueIfEmpty + ); + return; + } else { + this._reject(values._reason()); + return; + } + } else if (!isArray(values)) { + this._promise._reject(apiRejection("expecting an array, a promise or a thenable\u000a\u000a See http://goo.gl/s8MMhc\u000a")._reason()); + return; } -} - -function Queue(capacity) { - this._capacity = capacity; - this._length = 0; - this._front = 0; -} -Queue.prototype._willBeOverCapacity = function (size) { - return this._capacity < size; + if (values.length === 0) { + if (resolveValueIfEmpty === -5) { + this._resolveEmptyArray(); + } + else { + this._resolve(toResolutionValue(resolveValueIfEmpty)); + } + return; + } + var len = this.getActualLength(values.length); + this._length = len; + this._values = this.shouldCopyValues() ? new Array(len) : this._values; + var promise = this._promise; + for (var i = 0; i < len; ++i) { + var isResolved = this._isResolved(); + var maybePromise = tryConvertToPromise(values[i], promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + if (isResolved) { + maybePromise._ignoreRejections(); + } else if (maybePromise._isPending()) { + maybePromise._proxyPromiseArray(this, i); + } else if (maybePromise._isFulfilled()) { + this._promiseFulfilled(maybePromise._value(), i); + } else { + this._promiseRejected(maybePromise._reason(), i); + } + } else if (!isResolved) { + this._promiseFulfilled(maybePromise, i); + } + } }; -Queue.prototype._pushOne = function (arg) { - var length = this.length(); - this._checkCapacity(length + 1); - var i = (this._front + length) & (this._capacity - 1); - this[i] = arg; - this._length = length + 1; +PromiseArray.prototype._isResolved = function () { + return this._values === null; }; -Queue.prototype._unshiftOne = function(value) { - var capacity = this._capacity; - this._checkCapacity(this.length() + 1); - var front = this._front; - var i = (((( front - 1 ) & - ( capacity - 1) ) ^ capacity ) - capacity ); - this[i] = value; - this._front = i; - this._length = this.length() + 1; +PromiseArray.prototype._resolve = function (value) { + this._values = null; + this._promise._fulfill(value); }; -Queue.prototype.unshift = function(fn, receiver, arg) { - this._unshiftOne(arg); - this._unshiftOne(receiver); - this._unshiftOne(fn); +PromiseArray.prototype.__hardReject__ = +PromiseArray.prototype._reject = function (reason) { + this._values = null; + this._promise._rejectCallback(reason, false, true); }; -Queue.prototype.push = function (fn, receiver, arg) { - var length = this.length() + 3; - if (this._willBeOverCapacity(length)) { - this._pushOne(fn); - this._pushOne(receiver); - this._pushOne(arg); - return; - } - var j = this._front + length - 3; - this._checkCapacity(length); - var wrapMask = this._capacity - 1; - this[(j + 0) & wrapMask] = fn; - this[(j + 1) & wrapMask] = receiver; - this[(j + 2) & wrapMask] = arg; - this._length = length; +PromiseArray.prototype._promiseProgressed = function (progressValue, index) { + this._promise._progress({ + index: index, + value: progressValue + }); }; -Queue.prototype.shift = function () { - var front = this._front, - ret = this[front]; - this[front] = undefined; - this._front = (front + 1) & (this._capacity - 1); - this._length--; - return ret; +PromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + } }; -Queue.prototype.length = function () { - return this._length; +PromiseArray.prototype._promiseRejected = function (reason, index) { + this._totalResolved++; + this._reject(reason); }; -Queue.prototype._checkCapacity = function (size) { - if (this._capacity < size) { - this._resizeTo(this._capacity << 1); - } +PromiseArray.prototype.shouldCopyValues = function () { + return true; }; -Queue.prototype._resizeTo = function (capacity) { - var oldCapacity = this._capacity; - this._capacity = capacity; - var front = this._front; - var length = this._length; - var moveItemsCount = (front + length) & (oldCapacity - 1); - arrayMove(this, 0, this, oldCapacity, moveItemsCount); +PromiseArray.prototype.getActualLength = function (len) { + return len; }; -module.exports = Queue; +return PromiseArray; +}; -},{}],29:[function(_dereq_,module,exports){ +},{"./util.js":38}],25:[function(_dereq_,module,exports){ "use strict"; -module.exports = function( - Promise, INTERNAL, tryConvertToPromise, apiRejection) { -var isArray = _dereq_("./util.js").isArray; - -var raceLater = function (promise) { - return promise.then(function(array) { - return race(array, promise); - }); -}; +var util = _dereq_("./util.js"); +var maybeWrapAsError = util.maybeWrapAsError; +var errors = _dereq_("./errors.js"); +var TimeoutError = errors.TimeoutError; +var OperationalError = errors.OperationalError; +var haveGetters = util.haveGetters; +var es5 = _dereq_("./es5.js"); -function race(promises, parent) { - var maybePromise = tryConvertToPromise(promises); +function isUntypedError(obj) { + return obj instanceof Error && + es5.getPrototypeOf(obj) === Error.prototype; +} - if (maybePromise instanceof Promise) { - return raceLater(maybePromise); - } else if (!isArray(promises)) { - return apiRejection("expecting an array, a promise or a thenable\u000a\u000a See http://goo.gl/s8MMhc\u000a"); +var rErrorKey = /^(?:name|message|stack|cause)$/; +function wrapAsOperationalError(obj) { + var ret; + if (isUntypedError(obj)) { + ret = new OperationalError(obj); + ret.name = obj.name; + ret.message = obj.message; + ret.stack = obj.stack; + var keys = es5.keys(obj); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (!rErrorKey.test(key)) { + ret[key] = obj[key]; + } + } + return ret; } + util.markAsOriginatingFromRejection(obj); + return obj; +} - var ret = new Promise(INTERNAL); - if (parent !== undefined) { - ret._propagateFrom(parent, 4 | 1); - } - var fulfill = ret._fulfill; - var reject = ret._reject; - for (var i = 0, len = promises.length; i < len; ++i) { - var val = promises[i]; +function nodebackForPromise(promise) { + return function(err, value) { + if (promise === null) return; - if (val === undefined && !(i in promises)) { - continue; + if (err) { + var wrapped = wrapAsOperationalError(maybeWrapAsError(err)); + promise._attachExtraTrace(wrapped); + promise._reject(wrapped); + } else if (arguments.length > 2) { + var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];} + promise._fulfill(args); + } else { + promise._fulfill(value); } - Promise.cast(val)._then(fulfill, reject, undefined, ret, null); - } - return ret; + promise = null; + }; } -Promise.race = function (promises) { - return race(promises, undefined); + +var PromiseResolver; +if (!haveGetters) { + PromiseResolver = function (promise) { + this.promise = promise; + this.asCallback = nodebackForPromise(promise); + this.callback = this.asCallback; + }; +} +else { + PromiseResolver = function (promise) { + this.promise = promise; + }; +} +if (haveGetters) { + var prop = { + get: function() { + return nodebackForPromise(this.promise); + } + }; + es5.defineProperty(PromiseResolver.prototype, "asCallback", prop); + es5.defineProperty(PromiseResolver.prototype, "callback", prop); +} + +PromiseResolver._nodebackForPromise = nodebackForPromise; + +PromiseResolver.prototype.toString = function () { + return "[object PromiseResolver]"; }; -Promise.prototype.race = function () { - return race(this, undefined); +PromiseResolver.prototype.resolve = +PromiseResolver.prototype.fulfill = function (value) { + if (!(this instanceof PromiseResolver)) { + throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.\u000a\u000a See http://goo.gl/sdkXL9\u000a"); + } + this.promise._resolveCallback(value); }; +PromiseResolver.prototype.reject = function (reason) { + if (!(this instanceof PromiseResolver)) { + throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.\u000a\u000a See http://goo.gl/sdkXL9\u000a"); + } + this.promise._rejectCallback(reason); }; -},{"./util.js":38}],30:[function(_dereq_,module,exports){ +PromiseResolver.prototype.progress = function (value) { + if (!(this instanceof PromiseResolver)) { + throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.\u000a\u000a See http://goo.gl/sdkXL9\u000a"); + } + this.promise._progress(value); +}; + +PromiseResolver.prototype.cancel = function (err) { + this.promise.cancel(err); +}; + +PromiseResolver.prototype.timeout = function () { + this.reject(new TimeoutError("timeout")); +}; + +PromiseResolver.prototype.isResolved = function () { + return this.promise.isResolved(); +}; + +PromiseResolver.prototype.toJSON = function () { + return this.promise.toJSON(); +}; + +module.exports = PromiseResolver; + +},{"./errors.js":13,"./es5.js":14,"./util.js":38}],26:[function(_dereq_,module,exports){ "use strict"; -module.exports = function(Promise, - PromiseArray, - apiRejection, - tryConvertToPromise, - INTERNAL) { -var getDomain = Promise._getDomain; -var async = _dereq_("./async.js"); +module.exports = function(Promise, INTERNAL) { +var THIS = {}; var util = _dereq_("./util.js"); -var tryCatch = util.tryCatch; -var errorObj = util.errorObj; -function ReductionPromiseArray(promises, fn, accum, _each) { - this.constructor$(promises); - this._promise._captureStackTrace(); - this._preservedValues = _each === INTERNAL ? [] : null; - this._zerothIsAccum = (accum === undefined); - this._gotAccum = false; - this._reducingIndex = (this._zerothIsAccum ? 1 : 0); - this._valuesPhase = undefined; - var maybePromise = tryConvertToPromise(accum, this._promise); - var rejected = false; - var isPromise = maybePromise instanceof Promise; - if (isPromise) { - maybePromise = maybePromise._target(); - if (maybePromise._isPending()) { - maybePromise._proxyPromiseArray(this, -1); - } else if (maybePromise._isFulfilled()) { - accum = maybePromise._value(); - this._gotAccum = true; - } else { - this._reject(maybePromise._reason()); - rejected = true; - } - } - if (!(isPromise || this._zerothIsAccum)) this._gotAccum = true; - var domain = getDomain(); - this._callback = domain === null ? fn : domain.bind(fn); - this._accum = accum; - if (!rejected) async.invoke(init, this, undefined); -} -function init() { - this._init$(undefined, -5); -} -util.inherits(ReductionPromiseArray, PromiseArray); +var nodebackForPromise = _dereq_("./promise_resolver.js") + ._nodebackForPromise; +var withAppended = util.withAppended; +var maybeWrapAsError = util.maybeWrapAsError; +var canEvaluate = util.canEvaluate; +var TypeError = _dereq_("./errors").TypeError; +var defaultSuffix = "Async"; +var defaultPromisified = {__isPromisified__: true}; +var noCopyProps = [ + "arity", "length", + "name", + "arguments", + "caller", + "callee", + "prototype", + "__isPromisified__" +]; +var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$"); -ReductionPromiseArray.prototype._init = function () {}; +var defaultFilter = function(name) { + return util.isIdentifier(name) && + name.charAt(0) !== "_" && + name !== "constructor"; +}; -ReductionPromiseArray.prototype._resolveEmptyArray = function () { - if (this._gotAccum || this._zerothIsAccum) { - this._resolve(this._preservedValues !== null - ? [] : this._accum); +function propsFilter(key) { + return !noCopyPropsPattern.test(key); +} + +function isPromisified(fn) { + try { + return fn.__isPromisified__ === true; } -}; + catch (e) { + return false; + } +} -ReductionPromiseArray.prototype._promiseFulfilled = function (value, index) { - var values = this._values; - values[index] = value; - var length = this.length(); - var preservedValues = this._preservedValues; - var isEach = preservedValues !== null; - var gotAccum = this._gotAccum; - var valuesPhase = this._valuesPhase; - var valuesPhaseIndex; - if (!valuesPhase) { - valuesPhase = this._valuesPhase = new Array(length); - for (valuesPhaseIndex=0; valuesPhaseIndex= min; --i) { + ret.push(i); + } + for(var i = likelyArgumentCount + 1; i <= 3; ++i) { + ret.push(i); + } + return ret; +}; - if (ret === errorObj) return this._reject(ret.e); +var argumentSequence = function(argumentCount) { + return util.filledRange(argumentCount, "_arg", ""); +}; - var maybePromise = tryConvertToPromise(ret, this._promise); - if (maybePromise instanceof Promise) { - maybePromise = maybePromise._target(); - if (maybePromise._isPending()) { - valuesPhase[i] = 4; - return maybePromise._proxyPromiseArray(this, i); - } else if (maybePromise._isFulfilled()) { - ret = maybePromise._value(); - } else { - return this._reject(maybePromise._reason()); - } - } +var parameterDeclaration = function(parameterCount) { + return util.filledRange( + Math.max(parameterCount, 3), "_arg", ""); +}; - this._reducingIndex = i + 1; - this._accum = ret; +var parameterCount = function(fn) { + if (typeof fn.length === "number") { + return Math.max(Math.min(fn.length, 1023 + 1), 0); } - - this._resolve(isEach ? preservedValues : this._accum); + return 0; }; -function reduce(promises, fn, initialValue, _each) { - if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); - var array = new ReductionPromiseArray(promises, fn, initialValue, _each); - return array.promise(); -} +makeNodePromisifiedEval = +function(callback, receiver, originalName, fn) { + var newParameterCount = Math.max(0, parameterCount(fn) - 1); + var argumentOrder = switchCaseArgumentOrder(newParameterCount); + var shouldProxyThis = typeof callback === "string" || receiver === THIS; -Promise.prototype.reduce = function (fn, initialValue) { - return reduce(this, fn, initialValue, null); -}; + function generateCallForArgumentCount(count) { + var args = argumentSequence(count).join(", "); + var comma = count > 0 ? ", " : ""; + var ret; + if (shouldProxyThis) { + ret = "ret = callback.call(this, {{args}}, nodeback); break;\n"; + } else { + ret = receiver === undefined + ? "ret = callback({{args}}, nodeback); break;\n" + : "ret = callback.call(receiver, {{args}}, nodeback); break;\n"; + } + return ret.replace("{{args}}", args).replace(", ", comma); + } -Promise.reduce = function (promises, fn, initialValue, _each) { - return reduce(promises, fn, initialValue, _each); -}; -}; + function generateArgumentSwitchCase() { + var ret = ""; + for (var i = 0; i < argumentOrder.length; ++i) { + ret += "case " + argumentOrder[i] +":" + + generateCallForArgumentCount(argumentOrder[i]); + } -},{"./async.js":2,"./util.js":38}],31:[function(_dereq_,module,exports){ -"use strict"; -var schedule; -var util = _dereq_("./util"); -var noAsyncScheduler = function() { - throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/m3OTXk\u000a"); -}; -if (util.isNode && typeof MutationObserver === "undefined") { - var GlobalSetImmediate = global.setImmediate; - var ProcessNextTick = process.nextTick; - schedule = util.isRecentNode - ? function(fn) { GlobalSetImmediate.call(global, fn); } - : function(fn) { ProcessNextTick.call(process, fn); }; -} else if ((typeof MutationObserver !== "undefined") && - !(typeof window !== "undefined" && - window.navigator && - window.navigator.standalone)) { - schedule = function(fn) { - var div = document.createElement("div"); - var observer = new MutationObserver(fn); - observer.observe(div, {attributes: true}); - return function() { div.classList.toggle("foo"); }; - }; - schedule.isStatic = true; -} else if (typeof setImmediate !== "undefined") { - schedule = function (fn) { - setImmediate(fn); - }; -} else if (typeof setTimeout !== "undefined") { - schedule = function (fn) { - setTimeout(fn, 0); - }; -} else { - schedule = noAsyncScheduler; -} -module.exports = schedule; + ret += " \n\ + default: \n\ + var args = new Array(len + 1); \n\ + var i = 0; \n\ + for (var i = 0; i < len; ++i) { \n\ + args[i] = arguments[i]; \n\ + } \n\ + args[i] = nodeback; \n\ + [CodeForCall] \n\ + break; \n\ + ".replace("[CodeForCall]", (shouldProxyThis + ? "ret = callback.apply(this, args);\n" + : "ret = callback.apply(receiver, args);\n")); + return ret; + } -},{"./util":38}],32:[function(_dereq_,module,exports){ -"use strict"; -module.exports = - function(Promise, PromiseArray) { -var PromiseInspection = Promise.PromiseInspection; -var util = _dereq_("./util.js"); + var getFunctionCode = typeof callback === "string" + ? ("this != null ? this['"+callback+"'] : fn") + : "fn"; -function SettledPromiseArray(values) { - this.constructor$(values); + return new Function("Promise", + "fn", + "receiver", + "withAppended", + "maybeWrapAsError", + "nodebackForPromise", + "tryCatch", + "errorObj", + "notEnumerableProp", + "INTERNAL","'use strict'; \n\ + var ret = function (Parameters) { \n\ + 'use strict'; \n\ + var len = arguments.length; \n\ + var promise = new Promise(INTERNAL); \n\ + promise._captureStackTrace(); \n\ + var nodeback = nodebackForPromise(promise); \n\ + var ret; \n\ + var callback = tryCatch([GetFunctionCode]); \n\ + switch(len) { \n\ + [CodeForSwitchCase] \n\ + } \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\ + } \n\ + return promise; \n\ + }; \n\ + notEnumerableProp(ret, '__isPromisified__', true); \n\ + return ret; \n\ + " + .replace("Parameters", parameterDeclaration(newParameterCount)) + .replace("[CodeForSwitchCase]", generateArgumentSwitchCase()) + .replace("[GetFunctionCode]", getFunctionCode))( + Promise, + fn, + receiver, + withAppended, + maybeWrapAsError, + nodebackForPromise, + util.tryCatch, + util.errorObj, + util.notEnumerableProp, + INTERNAL + ); +}; } -util.inherits(SettledPromiseArray, PromiseArray); -SettledPromiseArray.prototype._promiseResolved = function (index, inspection) { - this._values[index] = inspection; - var totalResolved = ++this._totalResolved; - if (totalResolved >= this._length) { - this._resolve(this._values); +function makeNodePromisifiedClosure(callback, receiver, _, fn) { + var defaultThis = (function() {return this;})(); + var method = callback; + if (typeof method === "string") { + callback = fn; } -}; - -SettledPromiseArray.prototype._promiseFulfilled = function (value, index) { - var ret = new PromiseInspection(); - ret._bitField = 268435456; - ret._settledValue = value; - this._promiseResolved(index, ret); -}; -SettledPromiseArray.prototype._promiseRejected = function (reason, index) { - var ret = new PromiseInspection(); - ret._bitField = 134217728; - ret._settledValue = reason; - this._promiseResolved(index, ret); -}; - -Promise.settle = function (promises) { - return new SettledPromiseArray(promises).promise(); -}; + function promisified() { + var _receiver = receiver; + if (receiver === THIS) _receiver = this; + var promise = new Promise(INTERNAL); + promise._captureStackTrace(); + var cb = typeof method === "string" && this !== defaultThis + ? this[method] : callback; + var fn = nodebackForPromise(promise); + try { + cb.apply(_receiver, withAppended(arguments, fn)); + } catch(e) { + promise._rejectCallback(maybeWrapAsError(e), true, true); + } + return promise; + } + util.notEnumerableProp(promisified, "__isPromisified__", true); + return promisified; +} -Promise.prototype.settle = function () { - return new SettledPromiseArray(this).promise(); -}; -}; +var makeNodePromisified = canEvaluate + ? makeNodePromisifiedEval + : makeNodePromisifiedClosure; -},{"./util.js":38}],33:[function(_dereq_,module,exports){ -"use strict"; -module.exports = -function(Promise, PromiseArray, apiRejection) { -var util = _dereq_("./util.js"); -var RangeError = _dereq_("./errors.js").RangeError; -var AggregateError = _dereq_("./errors.js").AggregateError; -var isArray = util.isArray; +function promisifyAll(obj, suffix, filter, promisifier) { + var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$"); + var methods = + promisifiableMethods(obj, suffix, suffixRegexp, filter); + for (var i = 0, len = methods.length; i < len; i+= 2) { + var key = methods[i]; + var fn = methods[i+1]; + var promisifiedKey = key + suffix; + if (promisifier === makeNodePromisified) { + obj[promisifiedKey] = + makeNodePromisified(key, THIS, key, fn, suffix); + } else { + var promisified = promisifier(fn, function() { + return makeNodePromisified(key, THIS, key, fn, suffix); + }); + util.notEnumerableProp(promisified, "__isPromisified__", true); + obj[promisifiedKey] = promisified; + } + } + util.toFastProperties(obj); + return obj; +} -function SomePromiseArray(values) { - this.constructor$(values); - this._howMany = 0; - this._unwrap = false; - this._initialized = false; +function promisify(callback, receiver) { + return makeNodePromisified(callback, receiver, undefined, callback); } -util.inherits(SomePromiseArray, PromiseArray); -SomePromiseArray.prototype._init = function () { - if (!this._initialized) { - return; - } - if (this._howMany === 0) { - this._resolve([]); - return; +Promise.promisify = function (fn, receiver) { + if (typeof fn !== "function") { + throw new TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); } - this._init$(undefined, -5); - var isArrayResolved = isArray(this._values); - if (!this._isResolved() && - isArrayResolved && - this._howMany > this._canPossiblyFulfill()) { - this._reject(this._getRangeError(this.length())); + if (isPromisified(fn)) { + return fn; } + var ret = promisify(fn, arguments.length < 2 ? THIS : receiver); + util.copyDescriptors(fn, ret, propsFilter); + return ret; }; -SomePromiseArray.prototype.init = function () { - this._initialized = true; - this._init(); -}; - -SomePromiseArray.prototype.setUnwrap = function () { - this._unwrap = true; -}; - -SomePromiseArray.prototype.howMany = function () { - return this._howMany; -}; - -SomePromiseArray.prototype.setHowMany = function (count) { - this._howMany = count; -}; +Promise.promisifyAll = function (target, options) { + if (typeof target !== "function" && typeof target !== "object") { + throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a See http://goo.gl/9ITlV0\u000a"); + } + options = Object(options); + var suffix = options.suffix; + if (typeof suffix !== "string") suffix = defaultSuffix; + var filter = options.filter; + if (typeof filter !== "function") filter = defaultFilter; + var promisifier = options.promisifier; + if (typeof promisifier !== "function") promisifier = makeNodePromisified; -SomePromiseArray.prototype._promiseFulfilled = function (value) { - this._addFulfilled(value); - if (this._fulfilled() === this.howMany()) { - this._values.length = this.howMany(); - if (this.howMany() === 1 && this._unwrap) { - this._resolve(this._values[0]); - } else { - this._resolve(this._values); - } + if (!util.isIdentifier(suffix)) { + throw new RangeError("suffix must be a valid identifier\u000a\u000a See http://goo.gl/8FZo5V\u000a"); } -}; -SomePromiseArray.prototype._promiseRejected = function (reason) { - this._addRejected(reason); - if (this.howMany() > this._canPossiblyFulfill()) { - var e = new AggregateError(); - for (var i = this.length(); i < this._values.length; ++i) { - e.push(this._values[i]); + var keys = util.inheritedDataKeys(target); + for (var i = 0; i < keys.length; ++i) { + var value = target[keys[i]]; + if (keys[i] !== "constructor" && + util.isClass(value)) { + promisifyAll(value.prototype, suffix, filter, promisifier); + promisifyAll(value, suffix, filter, promisifier); } - this._reject(e); } -}; - -SomePromiseArray.prototype._fulfilled = function () { - return this._totalResolved; -}; -SomePromiseArray.prototype._rejected = function () { - return this._values.length - this.length(); + return promisifyAll(target, suffix, filter, promisifier); }; - -SomePromiseArray.prototype._addRejected = function (reason) { - this._values.push(reason); }; -SomePromiseArray.prototype._addFulfilled = function (value) { - this._values[this._totalResolved++] = value; -}; -SomePromiseArray.prototype._canPossiblyFulfill = function () { - return this.length() - this._rejected(); -}; +},{"./errors":13,"./promise_resolver.js":25,"./util.js":38}],27:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function( + Promise, PromiseArray, tryConvertToPromise, apiRejection) { +var util = _dereq_("./util.js"); +var isObject = util.isObject; +var es5 = _dereq_("./es5.js"); -SomePromiseArray.prototype._getRangeError = function (count) { - var message = "Input array must contain at least " + - this._howMany + " items but contains only " + count + " items"; - return new RangeError(message); -}; +function PropertiesPromiseArray(obj) { + var keys = es5.keys(obj); + var len = keys.length; + var values = new Array(len * 2); + for (var i = 0; i < len; ++i) { + var key = keys[i]; + values[i] = obj[key]; + values[i + len] = key; + } + this.constructor$(values); +} +util.inherits(PropertiesPromiseArray, PromiseArray); -SomePromiseArray.prototype._resolveEmptyArray = function () { - this._reject(this._getRangeError(0)); +PropertiesPromiseArray.prototype._init = function () { + this._init$(undefined, -3) ; }; -function some(promises, howMany) { - if ((howMany | 0) !== howMany || howMany < 0) { - return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/1wAmHx\u000a"); +PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + var val = {}; + var keyOffset = this.length(); + for (var i = 0, len = this.length(); i < len; ++i) { + val[this._values[i + keyOffset]] = this._values[i]; + } + this._resolve(val); } - var ret = new SomePromiseArray(promises); - var promise = ret.promise(); - ret.setHowMany(howMany); - ret.init(); - return promise; -} +}; -Promise.some = function (promises, howMany) { - return some(promises, howMany); +PropertiesPromiseArray.prototype._promiseProgressed = function (value, index) { + this._promise._progress({ + key: this._values[index + this.length()], + value: value + }); }; -Promise.prototype.some = function (howMany) { - return some(this, howMany); +PropertiesPromiseArray.prototype.shouldCopyValues = function () { + return false; }; -Promise._SomePromiseArray = SomePromiseArray; +PropertiesPromiseArray.prototype.getActualLength = function (len) { + return len >> 1; }; -},{"./errors.js":13,"./util.js":38}],34:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise) { -function PromiseInspection(promise) { - if (promise !== undefined) { - promise = promise._target(); - this._bitField = promise._bitField; - this._settledValue = promise._settledValue; +function props(promises) { + var ret; + var castValue = tryConvertToPromise(promises); + + if (!isObject(castValue)) { + return apiRejection("cannot await properties of a non-object\u000a\u000a See http://goo.gl/OsFKC8\u000a"); + } else if (castValue instanceof Promise) { + ret = castValue._then( + Promise.props, undefined, undefined, undefined, undefined); + } else { + ret = new PropertiesPromiseArray(castValue).promise(); } - else { - this._bitField = 0; - this._settledValue = undefined; + + if (castValue instanceof Promise) { + ret._propagateFrom(castValue, 4); } + return ret; } -PromiseInspection.prototype.value = function () { - if (!this.isFulfilled()) { - throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/hc1DLj\u000a"); - } - return this._settledValue; +Promise.prototype.props = function () { + return props(this); }; -PromiseInspection.prototype.error = -PromiseInspection.prototype.reason = function () { - if (!this.isRejected()) { - throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/hPuiwB\u000a"); - } - return this._settledValue; +Promise.props = function (promises) { + return props(promises); }; - -PromiseInspection.prototype.isFulfilled = -Promise.prototype._isFulfilled = function () { - return (this._bitField & 268435456) > 0; }; -PromiseInspection.prototype.isRejected = -Promise.prototype._isRejected = function () { - return (this._bitField & 134217728) > 0; -}; +},{"./es5.js":14,"./util.js":38}],28:[function(_dereq_,module,exports){ +"use strict"; +function arrayMove(src, srcIndex, dst, dstIndex, len) { + for (var j = 0; j < len; ++j) { + dst[j + dstIndex] = src[j + srcIndex]; + src[j + srcIndex] = void 0; + } +} -PromiseInspection.prototype.isPending = -Promise.prototype._isPending = function () { - return (this._bitField & 402653184) === 0; -}; +function Queue(capacity) { + this._capacity = capacity; + this._length = 0; + this._front = 0; +} -PromiseInspection.prototype.isResolved = -Promise.prototype._isResolved = function () { - return (this._bitField & 402653184) > 0; +Queue.prototype._willBeOverCapacity = function (size) { + return this._capacity < size; }; -Promise.prototype.isPending = function() { - return this._target()._isPending(); +Queue.prototype._pushOne = function (arg) { + var length = this.length(); + this._checkCapacity(length + 1); + var i = (this._front + length) & (this._capacity - 1); + this[i] = arg; + this._length = length + 1; }; -Promise.prototype.isRejected = function() { - return this._target()._isRejected(); +Queue.prototype._unshiftOne = function(value) { + var capacity = this._capacity; + this._checkCapacity(this.length() + 1); + var front = this._front; + var i = (((( front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[i] = value; + this._front = i; + this._length = this.length() + 1; }; -Promise.prototype.isFulfilled = function() { - return this._target()._isFulfilled(); +Queue.prototype.unshift = function(fn, receiver, arg) { + this._unshiftOne(arg); + this._unshiftOne(receiver); + this._unshiftOne(fn); }; -Promise.prototype.isResolved = function() { - return this._target()._isResolved(); +Queue.prototype.push = function (fn, receiver, arg) { + var length = this.length() + 3; + if (this._willBeOverCapacity(length)) { + this._pushOne(fn); + this._pushOne(receiver); + this._pushOne(arg); + return; + } + var j = this._front + length - 3; + this._checkCapacity(length); + var wrapMask = this._capacity - 1; + this[(j + 0) & wrapMask] = fn; + this[(j + 1) & wrapMask] = receiver; + this[(j + 2) & wrapMask] = arg; + this._length = length; }; -Promise.prototype._value = function() { - return this._settledValue; -}; +Queue.prototype.shift = function () { + var front = this._front, + ret = this[front]; -Promise.prototype._reason = function() { - this._unsetRejectionIsUnhandled(); - return this._settledValue; + this[front] = undefined; + this._front = (front + 1) & (this._capacity - 1); + this._length--; + return ret; }; -Promise.prototype.value = function() { - var target = this._target(); - if (!target.isFulfilled()) { - throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/hc1DLj\u000a"); - } - return target._settledValue; +Queue.prototype.length = function () { + return this._length; }; -Promise.prototype.reason = function() { - var target = this._target(); - if (!target.isRejected()) { - throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/hPuiwB\u000a"); +Queue.prototype._checkCapacity = function (size) { + if (this._capacity < size) { + this._resizeTo(this._capacity << 1); } - target._unsetRejectionIsUnhandled(); - return target._settledValue; }; - -Promise.PromiseInspection = PromiseInspection; +Queue.prototype._resizeTo = function (capacity) { + var oldCapacity = this._capacity; + this._capacity = capacity; + var front = this._front; + var length = this._length; + var moveItemsCount = (front + length) & (oldCapacity - 1); + arrayMove(this, 0, this, oldCapacity, moveItemsCount); }; -},{}],35:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, INTERNAL) { -var util = _dereq_("./util.js"); -var errorObj = util.errorObj; -var isObject = util.isObject; - -function tryConvertToPromise(obj, context) { - if (isObject(obj)) { - if (obj instanceof Promise) { - return obj; - } - else if (isAnyBluebirdPromise(obj)) { - var ret = new Promise(INTERNAL); - obj._then( - ret._fulfillUnchecked, - ret._rejectUncheckedCheckError, - ret._progressUnchecked, - ret, - null - ); - return ret; - } - var then = util.tryCatch(getThen)(obj); - if (then === errorObj) { - if (context) context._pushContext(); - var ret = Promise.reject(then.e); - if (context) context._popContext(); - return ret; - } else if (typeof then === "function") { - return doThenable(obj, then, context); - } - } - return obj; -} +module.exports = Queue; -function getThen(obj) { - return obj.then; -} +},{}],29:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function( + Promise, INTERNAL, tryConvertToPromise, apiRejection) { +var isArray = _dereq_("./util.js").isArray; -var hasProp = {}.hasOwnProperty; -function isAnyBluebirdPromise(obj) { - return hasProp.call(obj, "_promise0"); -} +var raceLater = function (promise) { + return promise.then(function(array) { + return race(array, promise); + }); +}; -function doThenable(x, then, context) { - var promise = new Promise(INTERNAL); - var ret = promise; - if (context) context._pushContext(); - promise._captureStackTrace(); - if (context) context._popContext(); - var synchronous = true; - var result = util.tryCatch(then).call(x, - resolveFromThenable, - rejectFromThenable, - progressFromThenable); - synchronous = false; - if (promise && result === errorObj) { - promise._rejectCallback(result.e, true, true); - promise = null; - } +function race(promises, parent) { + var maybePromise = tryConvertToPromise(promises); - function resolveFromThenable(value) { - if (!promise) return; - promise._resolveCallback(value); - promise = null; + if (maybePromise instanceof Promise) { + return raceLater(maybePromise); + } else if (!isArray(promises)) { + return apiRejection("expecting an array, a promise or a thenable\u000a\u000a See http://goo.gl/s8MMhc\u000a"); } - function rejectFromThenable(reason) { - if (!promise) return; - promise._rejectCallback(reason, synchronous, true); - promise = null; + var ret = new Promise(INTERNAL); + if (parent !== undefined) { + ret._propagateFrom(parent, 4 | 1); } - - function progressFromThenable(value) { - if (!promise) return; - if (typeof promise._progress === "function") { - promise._progress(value); + var fulfill = ret._fulfill; + var reject = ret._reject; + for (var i = 0, len = promises.length; i < len; ++i) { + var val = promises[i]; + + if (val === undefined && !(i in promises)) { + continue; } + + Promise.cast(val)._then(fulfill, reject, undefined, ret, null); } return ret; } -return tryConvertToPromise; -}; - -},{"./util.js":38}],36:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function(Promise, INTERNAL) { -var util = _dereq_("./util.js"); -var TimeoutError = Promise.TimeoutError; - -var afterTimeout = function (promise, message) { - if (!promise.isPending()) return; - - var err; - if(!util.isPrimitive(message) && (message instanceof Error)) { - err = message; - } else { - if (typeof message !== "string") { - message = "operation timed out"; - } - err = new TimeoutError(message); - } - util.markAsOriginatingFromRejection(err); - promise._attachExtraTrace(err); - promise._cancel(err); +Promise.race = function (promises) { + return race(promises, undefined); }; -var afterValue = function(value) { return delay(+this).thenReturn(value); }; -var delay = Promise.delay = function (value, ms) { - if (ms === undefined) { - ms = value; - value = undefined; - var ret = new Promise(INTERNAL); - setTimeout(function() { ret._fulfill(); }, ms); - return ret; - } - ms = +ms; - return Promise.resolve(value)._then(afterValue, null, null, ms, undefined); +Promise.prototype.race = function () { + return race(this, undefined); }; -Promise.prototype.delay = function (ms) { - return delay(this, ms); }; -function successClear(value) { - var handle = this; - if (handle instanceof Number) handle = +handle; - clearTimeout(handle); - return value; +},{"./util.js":38}],30:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL) { +var getDomain = Promise._getDomain; +var async = _dereq_("./async.js"); +var util = _dereq_("./util.js"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +function ReductionPromiseArray(promises, fn, accum, _each) { + this.constructor$(promises); + this._promise._captureStackTrace(); + this._preservedValues = _each === INTERNAL ? [] : null; + this._zerothIsAccum = (accum === undefined); + this._gotAccum = false; + this._reducingIndex = (this._zerothIsAccum ? 1 : 0); + this._valuesPhase = undefined; + var maybePromise = tryConvertToPromise(accum, this._promise); + var rejected = false; + var isPromise = maybePromise instanceof Promise; + if (isPromise) { + maybePromise = maybePromise._target(); + if (maybePromise._isPending()) { + maybePromise._proxyPromiseArray(this, -1); + } else if (maybePromise._isFulfilled()) { + accum = maybePromise._value(); + this._gotAccum = true; + } else { + this._reject(maybePromise._reason()); + rejected = true; + } + } + if (!(isPromise || this._zerothIsAccum)) this._gotAccum = true; + var domain = getDomain(); + this._callback = domain === null ? fn : domain.bind(fn); + this._accum = accum; + if (!rejected) async.invoke(init, this, undefined); } - -function failureClear(reason) { - var handle = this; - if (handle instanceof Number) handle = +handle; - clearTimeout(handle); - throw reason; +function init() { + this._init$(undefined, -5); } +util.inherits(ReductionPromiseArray, PromiseArray); -Promise.prototype.timeout = function (ms, message) { - ms = +ms; - var ret = this.then().cancellable(); - ret._cancellationParent = this; - var handle = setTimeout(function timeoutTimeout() { - afterTimeout(ret, message); - }, ms); - return ret._then(successClear, failureClear, undefined, handle, undefined); -}; +ReductionPromiseArray.prototype._init = function () {}; +ReductionPromiseArray.prototype._resolveEmptyArray = function () { + if (this._gotAccum || this._zerothIsAccum) { + this._resolve(this._preservedValues !== null + ? [] : this._accum); + } }; -},{"./util.js":38}],37:[function(_dereq_,module,exports){ -"use strict"; -module.exports = function (Promise, apiRejection, tryConvertToPromise, - createContext) { - var TypeError = _dereq_("./errors.js").TypeError; - var inherits = _dereq_("./util.js").inherits; - var PromiseInspection = Promise.PromiseInspection; - - function inspectionMapper(inspections) { - var len = inspections.length; - for (var i = 0; i < len; ++i) { - var inspection = inspections[i]; - if (inspection.isRejected()) { - return Promise.reject(inspection.error()); - } - inspections[i] = inspection._settledValue; +ReductionPromiseArray.prototype._promiseFulfilled = function (value, index) { + var values = this._values; + values[index] = value; + var length = this.length(); + var preservedValues = this._preservedValues; + var isEach = preservedValues !== null; + var gotAccum = this._gotAccum; + var valuesPhase = this._valuesPhase; + var valuesPhaseIndex; + if (!valuesPhase) { + valuesPhase = this._valuesPhase = new Array(length); + for (valuesPhaseIndex=0; valuesPhaseIndex= len) return ret.resolve(); - var maybePromise = castPreservingDisposable(resources[i++]); - if (maybePromise instanceof Promise && - maybePromise._isDisposable()) { - try { - maybePromise = tryConvertToPromise( - maybePromise._getDisposer().tryDispose(inspection), - resources.promise); - } catch (e) { - return thrower(e); - } - if (maybePromise instanceof Promise) { - return maybePromise._then(iterator, thrower, - null, null, null); - } + if (valuesPhaseIndex !== 1) return; + value = values[i]; + this._promise._pushContext(); + if (isEach) { + preservedValues.push(value); + ret = tryCatch(callback).call(receiver, value, i, length); + } + else { + ret = tryCatch(callback) + .call(receiver, this._accum, value, i, length); + } + this._promise._popContext(); + + if (ret === errorObj) return this._reject(ret.e); + + var maybePromise = tryConvertToPromise(ret, this._promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + if (maybePromise._isPending()) { + valuesPhase[i] = 4; + return maybePromise._proxyPromiseArray(this, i); + } else if (maybePromise._isFulfilled()) { + ret = maybePromise._value(); + } else { + return this._reject(maybePromise._reason()); } - iterator(); } - iterator(); - return ret.promise; - } - function disposerSuccess(value) { - var inspection = new PromiseInspection(); - inspection._settledValue = value; - inspection._bitField = 268435456; - return dispose(this, inspection).thenReturn(value); + this._reducingIndex = i + 1; + this._accum = ret; } - function disposerFail(reason) { - var inspection = new PromiseInspection(); - inspection._settledValue = reason; - inspection._bitField = 134217728; - return dispose(this, inspection).thenThrow(reason); - } + this._resolve(isEach ? preservedValues : this._accum); +}; + +function reduce(promises, fn, initialValue, _each) { + if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); + var array = new ReductionPromiseArray(promises, fn, initialValue, _each); + return array.promise(); +} + +Promise.prototype.reduce = function (fn, initialValue) { + return reduce(this, fn, initialValue, null); +}; - function Disposer(data, promise, context) { - this._data = data; - this._promise = promise; - this._context = context; - } +Promise.reduce = function (promises, fn, initialValue, _each) { + return reduce(promises, fn, initialValue, _each); +}; +}; - Disposer.prototype.data = function () { - return this._data; +},{"./async.js":2,"./util.js":38}],31:[function(_dereq_,module,exports){ +"use strict"; +var schedule; +var util = _dereq_("./util"); +var noAsyncScheduler = function() { + throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/m3OTXk\u000a"); +}; +if (util.isNode && typeof MutationObserver === "undefined") { + var GlobalSetImmediate = global.setImmediate; + var ProcessNextTick = process.nextTick; + schedule = util.isRecentNode + ? function(fn) { GlobalSetImmediate.call(global, fn); } + : function(fn) { ProcessNextTick.call(process, fn); }; +} else if ((typeof MutationObserver !== "undefined") && + !(typeof window !== "undefined" && + window.navigator && + window.navigator.standalone)) { + schedule = function(fn) { + var div = document.createElement("div"); + var observer = new MutationObserver(fn); + observer.observe(div, {attributes: true}); + return function() { div.classList.toggle("foo"); }; }; - - Disposer.prototype.promise = function () { - return this._promise; + schedule.isStatic = true; +} else if (typeof setImmediate !== "undefined") { + schedule = function (fn) { + setImmediate(fn); }; - - Disposer.prototype.resource = function () { - if (this.promise().isFulfilled()) { - return this.promise().value(); - } - return null; +} else if (typeof setTimeout !== "undefined") { + schedule = function (fn) { + setTimeout(fn, 0); }; +} else { + schedule = noAsyncScheduler; +} +module.exports = schedule; - Disposer.prototype.tryDispose = function(inspection) { - var resource = this.resource(); - var context = this._context; - if (context !== undefined) context._pushContext(); - var ret = resource !== null - ? this.doDispose(resource, inspection) : null; - if (context !== undefined) context._popContext(); - this._promise._unsetDisposable(); - this._data = null; - return ret; - }; +},{"./util":38}],32:[function(_dereq_,module,exports){ +"use strict"; +module.exports = + function(Promise, PromiseArray) { +var PromiseInspection = Promise.PromiseInspection; +var util = _dereq_("./util.js"); - Disposer.isDisposer = function (d) { - return (d != null && - typeof d.resource === "function" && - typeof d.tryDispose === "function"); - }; +function SettledPromiseArray(values) { + this.constructor$(values); +} +util.inherits(SettledPromiseArray, PromiseArray); - function FunctionDisposer(fn, promise, context) { - this.constructor$(fn, promise, context); +SettledPromiseArray.prototype._promiseResolved = function (index, inspection) { + this._values[index] = inspection; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); } - inherits(FunctionDisposer, Disposer); +}; - FunctionDisposer.prototype.doDispose = function (resource, inspection) { - var fn = this.data(); - return fn.call(resource, resource, inspection); - }; +SettledPromiseArray.prototype._promiseFulfilled = function (value, index) { + var ret = new PromiseInspection(); + ret._bitField = 268435456; + ret._settledValue = value; + this._promiseResolved(index, ret); +}; +SettledPromiseArray.prototype._promiseRejected = function (reason, index) { + var ret = new PromiseInspection(); + ret._bitField = 134217728; + ret._settledValue = reason; + this._promiseResolved(index, ret); +}; - function maybeUnwrapDisposer(value) { - if (Disposer.isDisposer(value)) { - this.resources[this.index]._setDisposable(value); - return value.promise(); - } - return value; - } +Promise.settle = function (promises) { + return new SettledPromiseArray(promises).promise(); +}; - Promise.using = function () { - var len = arguments.length; - if (len < 2) return apiRejection( - "you must pass at least 2 arguments to Promise.using"); - var fn = arguments[len - 1]; - if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); +Promise.prototype.settle = function () { + return new SettledPromiseArray(this).promise(); +}; +}; - var input; - var spreadArgs = true; - if (len === 2 && Array.isArray(arguments[0])) { - input = arguments[0]; - len = input.length; - spreadArgs = false; - } else { - input = arguments; - len--; - } - var resources = new Array(len); - for (var i = 0; i < len; ++i) { - var resource = input[i]; - if (Disposer.isDisposer(resource)) { - var disposer = resource; - resource = resource.promise(); - resource._setDisposable(disposer); - } else { - var maybePromise = tryConvertToPromise(resource); - if (maybePromise instanceof Promise) { - resource = - maybePromise._then(maybeUnwrapDisposer, null, null, { - resources: resources, - index: i - }, undefined); - } - } - resources[i] = resource; - } +},{"./util.js":38}],33:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, PromiseArray, apiRejection) { +var util = _dereq_("./util.js"); +var RangeError = _dereq_("./errors.js").RangeError; +var AggregateError = _dereq_("./errors.js").AggregateError; +var isArray = util.isArray; - var promise = Promise.settle(resources) - .then(inspectionMapper) - .then(function(vals) { - promise._pushContext(); - var ret; - try { - ret = spreadArgs - ? fn.apply(undefined, vals) : fn.call(undefined, vals); - } finally { - promise._popContext(); - } - return ret; - }) - ._then( - disposerSuccess, disposerFail, undefined, resources, undefined); - resources.promise = promise; - return promise; - }; - Promise.prototype._setDisposable = function (disposer) { - this._bitField = this._bitField | 262144; - this._disposer = disposer; - }; +function SomePromiseArray(values) { + this.constructor$(values); + this._howMany = 0; + this._unwrap = false; + this._initialized = false; +} +util.inherits(SomePromiseArray, PromiseArray); - Promise.prototype._isDisposable = function () { - return (this._bitField & 262144) > 0; - }; +SomePromiseArray.prototype._init = function () { + if (!this._initialized) { + return; + } + if (this._howMany === 0) { + this._resolve([]); + return; + } + this._init$(undefined, -5); + var isArrayResolved = isArray(this._values); + if (!this._isResolved() && + isArrayResolved && + this._howMany > this._canPossiblyFulfill()) { + this._reject(this._getRangeError(this.length())); + } +}; - Promise.prototype._getDisposer = function () { - return this._disposer; - }; +SomePromiseArray.prototype.init = function () { + this._initialized = true; + this._init(); +}; - Promise.prototype._unsetDisposable = function () { - this._bitField = this._bitField & (~262144); - this._disposer = undefined; - }; +SomePromiseArray.prototype.setUnwrap = function () { + this._unwrap = true; +}; - Promise.prototype.disposer = function (fn) { - if (typeof fn === "function") { - return new FunctionDisposer(fn, this, createContext()); - } - throw new TypeError(); - }; +SomePromiseArray.prototype.howMany = function () { + return this._howMany; +}; +SomePromiseArray.prototype.setHowMany = function (count) { + this._howMany = count; }; -},{"./errors.js":13,"./util.js":38}],38:[function(_dereq_,module,exports){ -"use strict"; -var es5 = _dereq_("./es5.js"); -var canEvaluate = typeof navigator == "undefined"; -var haveGetters = (function(){ - try { - var o = {}; - es5.defineProperty(o, "f", { - get: function () { - return 3; - } - }); - return o.f === 3; +SomePromiseArray.prototype._promiseFulfilled = function (value) { + this._addFulfilled(value); + if (this._fulfilled() === this.howMany()) { + this._values.length = this.howMany(); + if (this.howMany() === 1 && this._unwrap) { + this._resolve(this._values[0]); + } else { + this._resolve(this._values); + } } - catch (e) { - return false; + +}; +SomePromiseArray.prototype._promiseRejected = function (reason) { + this._addRejected(reason); + if (this.howMany() > this._canPossiblyFulfill()) { + var e = new AggregateError(); + for (var i = this.length(); i < this._values.length; ++i) { + e.push(this._values[i]); + } + this._reject(e); } +}; -})(); +SomePromiseArray.prototype._fulfilled = function () { + return this._totalResolved; +}; -var errorObj = {e: {}}; -var tryCatchTarget; -function tryCatcher() { - try { - var target = tryCatchTarget; - tryCatchTarget = null; - return target.apply(this, arguments); - } catch (e) { - errorObj.e = e; - return errorObj; - } -} -function tryCatch(fn) { - tryCatchTarget = fn; - return tryCatcher; -} +SomePromiseArray.prototype._rejected = function () { + return this._values.length - this.length(); +}; -var inherits = function(Child, Parent) { - var hasProp = {}.hasOwnProperty; +SomePromiseArray.prototype._addRejected = function (reason) { + this._values.push(reason); +}; - function T() { - this.constructor = Child; - this.constructor$ = Parent; - for (var propertyName in Parent.prototype) { - if (hasProp.call(Parent.prototype, propertyName) && - propertyName.charAt(propertyName.length-1) !== "$" - ) { - this[propertyName + "$"] = Parent.prototype[propertyName]; - } - } - } - T.prototype = Parent.prototype; - Child.prototype = new T(); - return Child.prototype; +SomePromiseArray.prototype._addFulfilled = function (value) { + this._values[this._totalResolved++] = value; }; +SomePromiseArray.prototype._canPossiblyFulfill = function () { + return this.length() - this._rejected(); +}; -function isPrimitive(val) { - return val == null || val === true || val === false || - typeof val === "string" || typeof val === "number"; +SomePromiseArray.prototype._getRangeError = function (count) { + var message = "Input array must contain at least " + + this._howMany + " items but contains only " + count + " items"; + return new RangeError(message); +}; -} +SomePromiseArray.prototype._resolveEmptyArray = function () { + this._reject(this._getRangeError(0)); +}; -function isObject(value) { - return !isPrimitive(value); +function some(promises, howMany) { + if ((howMany | 0) !== howMany || howMany < 0) { + return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/1wAmHx\u000a"); + } + var ret = new SomePromiseArray(promises); + var promise = ret.promise(); + ret.setHowMany(howMany); + ret.init(); + return promise; } -function maybeWrapAsError(maybeError) { - if (!isPrimitive(maybeError)) return maybeError; +Promise.some = function (promises, howMany) { + return some(promises, howMany); +}; - return new Error(safeToString(maybeError)); -} +Promise.prototype.some = function (howMany) { + return some(this, howMany); +}; -function withAppended(target, appendee) { - var len = target.length; - var ret = new Array(len + 1); - var i; - for (i = 0; i < len; ++i) { - ret[i] = target[i]; +Promise._SomePromiseArray = SomePromiseArray; +}; + +},{"./errors.js":13,"./util.js":38}],34:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +function PromiseInspection(promise) { + if (promise !== undefined) { + promise = promise._target(); + this._bitField = promise._bitField; + this._settledValue = promise._settledValue; + } + else { + this._bitField = 0; + this._settledValue = undefined; } - ret[i] = appendee; - return ret; } -function getDataPropertyOrDefault(obj, key, defaultValue) { - if (es5.isES5) { - var desc = Object.getOwnPropertyDescriptor(obj, key); +PromiseInspection.prototype.value = function () { + if (!this.isFulfilled()) { + throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/hc1DLj\u000a"); + } + return this._settledValue; +}; - if (desc != null) { - return desc.get == null && desc.set == null - ? desc.value - : defaultValue; - } - } else { - return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; +PromiseInspection.prototype.error = +PromiseInspection.prototype.reason = function () { + if (!this.isRejected()) { + throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/hPuiwB\u000a"); } -} + return this._settledValue; +}; -function notEnumerableProp(obj, name, value) { - if (isPrimitive(obj)) return obj; - var descriptor = { - value: value, - configurable: true, - enumerable: false, - writable: true - }; - es5.defineProperty(obj, name, descriptor); - return obj; -} +PromiseInspection.prototype.isFulfilled = +Promise.prototype._isFulfilled = function () { + return (this._bitField & 268435456) > 0; +}; -function thrower(r) { - throw r; -} +PromiseInspection.prototype.isRejected = +Promise.prototype._isRejected = function () { + return (this._bitField & 134217728) > 0; +}; -var inheritedDataKeys = (function() { - var excludedPrototypes = [ - Array.prototype, - Object.prototype, - Function.prototype - ]; +PromiseInspection.prototype.isPending = +Promise.prototype._isPending = function () { + return (this._bitField & 402653184) === 0; +}; - var isExcludedProto = function(val) { - for (var i = 0; i < excludedPrototypes.length; ++i) { - if (excludedPrototypes[i] === val) { - return true; - } - } - return false; - }; +PromiseInspection.prototype.isResolved = +Promise.prototype._isResolved = function () { + return (this._bitField & 402653184) > 0; +}; - if (es5.isES5) { - var getKeys = Object.getOwnPropertyNames; - return function(obj) { - var ret = []; - var visitedKeys = Object.create(null); - while (obj != null && !isExcludedProto(obj)) { - var keys; - try { - keys = getKeys(obj); - } catch (e) { - return ret; - } - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - if (visitedKeys[key]) continue; - visitedKeys[key] = true; - var desc = Object.getOwnPropertyDescriptor(obj, key); - if (desc != null && desc.get == null && desc.set == null) { - ret.push(key); - } - } - obj = es5.getPrototypeOf(obj); - } - return ret; - }; - } else { - var hasProp = {}.hasOwnProperty; - return function(obj) { - if (isExcludedProto(obj)) return []; - var ret = []; +Promise.prototype.isPending = function() { + return this._target()._isPending(); +}; - /*jshint forin:false */ - enumeration: for (var key in obj) { - if (hasProp.call(obj, key)) { - ret.push(key); - } else { - for (var i = 0; i < excludedPrototypes.length; ++i) { - if (hasProp.call(excludedPrototypes[i], key)) { - continue enumeration; - } - } - ret.push(key); - } - } - return ret; - }; +Promise.prototype.isRejected = function() { + return this._target()._isRejected(); +}; + +Promise.prototype.isFulfilled = function() { + return this._target()._isFulfilled(); +}; + +Promise.prototype.isResolved = function() { + return this._target()._isResolved(); +}; + +Promise.prototype._value = function() { + return this._settledValue; +}; + +Promise.prototype._reason = function() { + this._unsetRejectionIsUnhandled(); + return this._settledValue; +}; + +Promise.prototype.value = function() { + var target = this._target(); + if (!target.isFulfilled()) { + throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/hc1DLj\u000a"); } + return target._settledValue; +}; -})(); +Promise.prototype.reason = function() { + var target = this._target(); + if (!target.isRejected()) { + throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/hPuiwB\u000a"); + } + target._unsetRejectionIsUnhandled(); + return target._settledValue; +}; -var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; -function isClass(fn) { - try { - if (typeof fn === "function") { - var keys = es5.names(fn.prototype); - var hasMethods = es5.isES5 && keys.length > 1; - var hasMethodsOtherThanConstructor = keys.length > 0 && - !(keys.length === 1 && keys[0] === "constructor"); - var hasThisAssignmentAndStaticMethods = - thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; +Promise.PromiseInspection = PromiseInspection; +}; - if (hasMethods || hasMethodsOtherThanConstructor || - hasThisAssignmentAndStaticMethods) { - return true; - } +},{}],35:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var util = _dereq_("./util.js"); +var errorObj = util.errorObj; +var isObject = util.isObject; + +function tryConvertToPromise(obj, context) { + if (isObject(obj)) { + if (obj instanceof Promise) { + return obj; + } + else if (isAnyBluebirdPromise(obj)) { + var ret = new Promise(INTERNAL); + obj._then( + ret._fulfillUnchecked, + ret._rejectUncheckedCheckError, + ret._progressUnchecked, + ret, + null + ); + return ret; + } + var then = util.tryCatch(getThen)(obj); + if (then === errorObj) { + if (context) context._pushContext(); + var ret = Promise.reject(then.e); + if (context) context._popContext(); + return ret; + } else if (typeof then === "function") { + return doThenable(obj, then, context); } - return false; - } catch (e) { - return false; } + return obj; } -function toFastProperties(obj) { - /*jshint -W027,-W055,-W031*/ - function f() {} - f.prototype = obj; - var l = 8; - while (l--) new f(); - return obj; - eval(obj); +function getThen(obj) { + return obj.then; } -var rident = /^[a-z$_][a-z$_0-9]*$/i; -function isIdentifier(str) { - return rident.test(str); +var hasProp = {}.hasOwnProperty; +function isAnyBluebirdPromise(obj) { + return hasProp.call(obj, "_promise0"); } -function filledRange(count, prefix, suffix) { - var ret = new Array(count); - for(var i = 0; i < count; ++i) { - ret[i] = prefix + i + suffix; +function doThenable(x, then, context) { + var promise = new Promise(INTERNAL); + var ret = promise; + if (context) context._pushContext(); + promise._captureStackTrace(); + if (context) context._popContext(); + var synchronous = true; + var result = util.tryCatch(then).call(x, + resolveFromThenable, + rejectFromThenable, + progressFromThenable); + synchronous = false; + if (promise && result === errorObj) { + promise._rejectCallback(result.e, true, true); + promise = null; } - return ret; -} -function safeToString(obj) { - try { - return obj + ""; - } catch (e) { - return "[no string representation]"; + function resolveFromThenable(value) { + if (!promise) return; + promise._resolveCallback(value); + promise = null; } -} -function markAsOriginatingFromRejection(e) { - try { - notEnumerableProp(e, "isOperational", true); + function rejectFromThenable(reason) { + if (!promise) return; + promise._rejectCallback(reason, synchronous, true); + promise = null; } - catch(ignore) {} -} -function originatesFromRejection(e) { - if (e == null) return false; - return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || - e["isOperational"] === true); + function progressFromThenable(value) { + if (!promise) return; + if (typeof promise._progress === "function") { + promise._progress(value); + } + } + return ret; } -function canAttachTrace(obj) { - return obj instanceof Error && es5.propertyIsWritable(obj, "stack"); -} +return tryConvertToPromise; +}; -var ensureErrorObject = (function() { - if (!("stack" in new Error())) { - return function(value) { - if (canAttachTrace(value)) return value; - try {throw new Error(safeToString(value));} - catch(err) {return err;} - }; +},{"./util.js":38}],36:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var util = _dereq_("./util.js"); +var TimeoutError = Promise.TimeoutError; + +var afterTimeout = function (promise, message) { + if (!promise.isPending()) return; + + var err; + if(!util.isPrimitive(message) && (message instanceof Error)) { + err = message; } else { - return function(value) { - if (canAttachTrace(value)) return value; - return new Error(safeToString(value)); - }; + if (typeof message !== "string") { + message = "operation timed out"; + } + err = new TimeoutError(message); } -})(); - -function classString(obj) { - return {}.toString.call(obj); -} + util.markAsOriginatingFromRejection(err); + promise._attachExtraTrace(err); + promise._cancel(err); +}; -function copyDescriptors(from, to, filter) { - var keys = es5.names(from); - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - if (filter(key)) { - try { - es5.defineProperty(to, key, es5.getDescriptor(from, key)); - } catch (ignore) {} - } +var afterValue = function(value) { return delay(+this).thenReturn(value); }; +var delay = Promise.delay = function (value, ms) { + if (ms === undefined) { + ms = value; + value = undefined; + var ret = new Promise(INTERNAL); + setTimeout(function() { ret._fulfill(); }, ms); + return ret; } -} + ms = +ms; + return Promise.resolve(value)._then(afterValue, null, null, ms, undefined); +}; -var ret = { - isClass: isClass, - isIdentifier: isIdentifier, - inheritedDataKeys: inheritedDataKeys, - getDataPropertyOrDefault: getDataPropertyOrDefault, - thrower: thrower, - isArray: es5.isArray, - haveGetters: haveGetters, - notEnumerableProp: notEnumerableProp, - isPrimitive: isPrimitive, - isObject: isObject, - canEvaluate: canEvaluate, - errorObj: errorObj, - tryCatch: tryCatch, - inherits: inherits, - withAppended: withAppended, - maybeWrapAsError: maybeWrapAsError, - toFastProperties: toFastProperties, - filledRange: filledRange, - toString: safeToString, - canAttachTrace: canAttachTrace, - ensureErrorObject: ensureErrorObject, - originatesFromRejection: originatesFromRejection, - markAsOriginatingFromRejection: markAsOriginatingFromRejection, - classString: classString, - copyDescriptors: copyDescriptors, - hasDevTools: typeof chrome !== "undefined" && chrome && - typeof chrome.loadTimes === "function", - isNode: typeof process !== "undefined" && - classString(process).toLowerCase() === "[object process]" +Promise.prototype.delay = function (ms) { + return delay(this, ms); }; -ret.isRecentNode = ret.isNode && (function() { - var version = process.versions.node.split(".").map(Number); - return (version[0] === 0 && version[1] > 10) || (version[0] > 0); -})(); -if (ret.isNode) ret.toFastProperties(process); +function successClear(value) { + var handle = this; + if (handle instanceof Number) handle = +handle; + clearTimeout(handle); + return value; +} -try {throw new Error(); } catch (e) {ret.lastLineError = e;} -module.exports = ret; +function failureClear(reason) { + var handle = this; + if (handle instanceof Number) handle = +handle; + clearTimeout(handle); + throw reason; +} -},{"./es5.js":14}]},{},[4])(4) -}); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } -}).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"g5I+bs":94}],89:[function(require,module,exports){ +Promise.prototype.timeout = function (ms, message) { + ms = +ms; + var ret = this.then().cancellable(); + ret._cancellationParent = this; + var handle = setTimeout(function timeoutTimeout() { + afterTimeout(ret, message); + }, ms); + return ret._then(successClear, failureClear, undefined, handle, undefined); +}; + +}; -/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ +},{"./util.js":38}],37:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function (Promise, apiRejection, tryConvertToPromise, + createContext) { + var TypeError = _dereq_("./errors.js").TypeError; + var inherits = _dereq_("./util.js").inherits; + var PromiseInspection = Promise.PromiseInspection; -exports = module.exports = require('./debug'); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); + function inspectionMapper(inspections) { + var len = inspections.length; + for (var i = 0; i < len; ++i) { + var inspection = inspections[i]; + if (inspection.isRejected()) { + return Promise.reject(inspection.error()); + } + inspections[i] = inspection._settledValue; + } + return inspections; + } -/** - * Colors. - */ + function thrower(e) { + setTimeout(function(){throw e;}, 0); + } -exports.colors = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' -]; + function castPreservingDisposable(thenable) { + var maybePromise = tryConvertToPromise(thenable); + if (maybePromise !== thenable && + typeof thenable._isDisposable === "function" && + typeof thenable._getDisposer === "function" && + thenable._isDisposable()) { + maybePromise._setDisposable(thenable._getDisposer()); + } + return maybePromise; + } + function dispose(resources, inspection) { + var i = 0; + var len = resources.length; + var ret = Promise.defer(); + function iterator() { + if (i >= len) return ret.resolve(); + var maybePromise = castPreservingDisposable(resources[i++]); + if (maybePromise instanceof Promise && + maybePromise._isDisposable()) { + try { + maybePromise = tryConvertToPromise( + maybePromise._getDisposer().tryDispose(inspection), + resources.promise); + } catch (e) { + return thrower(e); + } + if (maybePromise instanceof Promise) { + return maybePromise._then(iterator, thrower, + null, null, null); + } + } + iterator(); + } + iterator(); + return ret.promise; + } -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ + function disposerSuccess(value) { + var inspection = new PromiseInspection(); + inspection._settledValue = value; + inspection._bitField = 268435456; + return dispose(this, inspection).thenReturn(value); + } -function useColors() { - // is webkit? http://stackoverflow.com/a/16459606/376773 - return ('WebkitAppearance' in document.documentElement.style) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (window.console && (console.firebug || (console.exception && console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); -} + function disposerFail(reason) { + var inspection = new PromiseInspection(); + inspection._settledValue = reason; + inspection._bitField = 134217728; + return dispose(this, inspection).thenThrow(reason); + } -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ + function Disposer(data, promise, context) { + this._data = data; + this._promise = promise; + this._context = context; + } -exports.formatters.j = function(v) { - return JSON.stringify(v); -}; + Disposer.prototype.data = function () { + return this._data; + }; + Disposer.prototype.promise = function () { + return this._promise; + }; -/** - * Colorize log arguments if enabled. - * - * @api public - */ + Disposer.prototype.resource = function () { + if (this.promise().isFulfilled()) { + return this.promise().value(); + } + return null; + }; -function formatArgs() { - var args = arguments; - var useColors = this.useColors; + Disposer.prototype.tryDispose = function(inspection) { + var resource = this.resource(); + var context = this._context; + if (context !== undefined) context._pushContext(); + var ret = resource !== null + ? this.doDispose(resource, inspection) : null; + if (context !== undefined) context._popContext(); + this._promise._unsetDisposable(); + this._data = null; + return ret; + }; - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); + Disposer.isDisposer = function (d) { + return (d != null && + typeof d.resource === "function" && + typeof d.tryDispose === "function"); + }; - if (!useColors) return args; + function FunctionDisposer(fn, promise, context) { + this.constructor$(fn, promise, context); + } + inherits(FunctionDisposer, Disposer); - var c = 'color: ' + this.color; - args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); + FunctionDisposer.prototype.doDispose = function (resource, inspection) { + var fn = this.data(); + return fn.call(resource, resource, inspection); + }; - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; + function maybeUnwrapDisposer(value) { + if (Disposer.isDisposer(value)) { + this.resources[this.index]._setDisposable(value); + return value.promise(); + } + return value; } - }); - args.splice(lastC, 0, c); - return args; -} + Promise.using = function () { + var len = arguments.length; + if (len < 2) return apiRejection( + "you must pass at least 2 arguments to Promise.using"); + var fn = arguments[len - 1]; + if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ + var input; + var spreadArgs = true; + if (len === 2 && Array.isArray(arguments[0])) { + input = arguments[0]; + len = input.length; + spreadArgs = false; + } else { + input = arguments; + len--; + } + var resources = new Array(len); + for (var i = 0; i < len; ++i) { + var resource = input[i]; + if (Disposer.isDisposer(resource)) { + var disposer = resource; + resource = resource.promise(); + resource._setDisposable(disposer); + } else { + var maybePromise = tryConvertToPromise(resource); + if (maybePromise instanceof Promise) { + resource = + maybePromise._then(maybeUnwrapDisposer, null, null, { + resources: resources, + index: i + }, undefined); + } + } + resources[i] = resource; + } + + var promise = Promise.settle(resources) + .then(inspectionMapper) + .then(function(vals) { + promise._pushContext(); + var ret; + try { + ret = spreadArgs + ? fn.apply(undefined, vals) : fn.call(undefined, vals); + } finally { + promise._popContext(); + } + return ret; + }) + ._then( + disposerSuccess, disposerFail, undefined, resources, undefined); + resources.promise = promise; + return promise; + }; -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} + Promise.prototype._setDisposable = function (disposer) { + this._bitField = this._bitField | 262144; + this._disposer = disposer; + }; -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ + Promise.prototype._isDisposable = function () { + return (this._bitField & 262144) > 0; + }; -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); - } else { - exports.storage.debug = namespaces; - } - } catch(e) {} -} + Promise.prototype._getDisposer = function () { + return this._disposer; + }; -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ + Promise.prototype._unsetDisposable = function () { + this._bitField = this._bitField & (~262144); + this._disposer = undefined; + }; -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} - return r; -} + Promise.prototype.disposer = function (fn) { + if (typeof fn === "function") { + return new FunctionDisposer(fn, this, createContext()); + } + throw new TypeError(); + }; -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ +}; -exports.enable(load()); +},{"./errors.js":13,"./util.js":38}],38:[function(_dereq_,module,exports){ +"use strict"; +var es5 = _dereq_("./es5.js"); +var canEvaluate = typeof navigator == "undefined"; +var haveGetters = (function(){ + try { + var o = {}; + es5.defineProperty(o, "f", { + get: function () { + return 3; + } + }); + return o.f === 3; + } + catch (e) { + return false; + } -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ +})(); -function localstorage(){ - try { - return window.localStorage; - } catch (e) {} +var errorObj = {e: {}}; +var tryCatchTarget; +function tryCatcher() { + try { + var target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} +function tryCatch(fn) { + tryCatchTarget = fn; + return tryCatcher; } -},{"./debug":90}],90:[function(require,module,exports){ - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = debug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = require('ms'); +var inherits = function(Child, Parent) { + var hasProp = {}.hasOwnProperty; -/** - * The currently active debug mode names, and names to skip. - */ + function T() { + this.constructor = Child; + this.constructor$ = Parent; + for (var propertyName in Parent.prototype) { + if (hasProp.call(Parent.prototype, propertyName) && + propertyName.charAt(propertyName.length-1) !== "$" + ) { + this[propertyName + "$"] = Parent.prototype[propertyName]; + } + } + } + T.prototype = Parent.prototype; + Child.prototype = new T(); + return Child.prototype; +}; -exports.names = []; -exports.skips = []; -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lowercased letter, i.e. "n". - */ +function isPrimitive(val) { + return val == null || val === true || val === false || + typeof val === "string" || typeof val === "number"; -exports.formatters = {}; +} -/** - * Previously assigned color. - */ +function isObject(value) { + return !isPrimitive(value); +} -var prevColor = 0; +function maybeWrapAsError(maybeError) { + if (!isPrimitive(maybeError)) return maybeError; -/** - * Previous log timestamp. - */ + return new Error(safeToString(maybeError)); +} -var prevTime; +function withAppended(target, appendee) { + var len = target.length; + var ret = new Array(len + 1); + var i; + for (i = 0; i < len; ++i) { + ret[i] = target[i]; + } + ret[i] = appendee; + return ret; +} -/** - * Select a color. - * - * @return {Number} - * @api private - */ +function getDataPropertyOrDefault(obj, key, defaultValue) { + if (es5.isES5) { + var desc = Object.getOwnPropertyDescriptor(obj, key); -function selectColor() { - return exports.colors[prevColor++ % exports.colors.length]; + if (desc != null) { + return desc.get == null && desc.set == null + ? desc.value + : defaultValue; + } + } else { + return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; + } } -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ +function notEnumerableProp(obj, name, value) { + if (isPrimitive(obj)) return obj; + var descriptor = { + value: value, + configurable: true, + enumerable: false, + writable: true + }; + es5.defineProperty(obj, name, descriptor); + return obj; +} -function debug(namespace) { +function thrower(r) { + throw r; +} - // define the `disabled` version - function disabled() { - } - disabled.enabled = false; +var inheritedDataKeys = (function() { + var excludedPrototypes = [ + Array.prototype, + Object.prototype, + Function.prototype + ]; - // define the `enabled` version - function enabled() { + var isExcludedProto = function(val) { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (excludedPrototypes[i] === val) { + return true; + } + } + return false; + }; - var self = enabled; + if (es5.isES5) { + var getKeys = Object.getOwnPropertyNames; + return function(obj) { + var ret = []; + var visitedKeys = Object.create(null); + while (obj != null && !isExcludedProto(obj)) { + var keys; + try { + keys = getKeys(obj); + } catch (e) { + return ret; + } + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (visitedKeys[key]) continue; + visitedKeys[key] = true; + var desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc != null && desc.get == null && desc.set == null) { + ret.push(key); + } + } + obj = es5.getPrototypeOf(obj); + } + return ret; + }; + } else { + var hasProp = {}.hasOwnProperty; + return function(obj) { + if (isExcludedProto(obj)) return []; + var ret = []; - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; + /*jshint forin:false */ + enumeration: for (var key in obj) { + if (hasProp.call(obj, key)) { + ret.push(key); + } else { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (hasProp.call(excludedPrototypes[i], key)) { + continue enumeration; + } + } + ret.push(key); + } + } + return ret; + }; + } - // add the `color` if not set - if (null == self.useColors) self.useColors = exports.useColors(); - if (null == self.color && self.useColors) self.color = selectColor(); +})(); - var args = Array.prototype.slice.call(arguments); +var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; +function isClass(fn) { + try { + if (typeof fn === "function") { + var keys = es5.names(fn.prototype); - args[0] = exports.coerce(args[0]); + var hasMethods = es5.isES5 && keys.length > 1; + var hasMethodsOtherThanConstructor = keys.length > 0 && + !(keys.length === 1 && keys[0] === "constructor"); + var hasThisAssignmentAndStaticMethods = + thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; - if ('string' !== typeof args[0]) { - // anything else let's inspect with %o - args = ['%o'].concat(args); + if (hasMethods || hasMethodsOtherThanConstructor || + hasThisAssignmentAndStaticMethods) { + return true; + } + } + return false; + } catch (e) { + return false; } +} - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); +function toFastProperties(obj) { + /*jshint -W027,-W055,-W031*/ + function f() {} + f.prototype = obj; + var l = 8; + while (l--) new f(); + return obj; + eval(obj); +} - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); +var rident = /^[a-z$_][a-z$_0-9]*$/i; +function isIdentifier(str) { + return rident.test(str); +} - if ('function' === typeof exports.formatArgs) { - args = exports.formatArgs.apply(self, args); +function filledRange(count, prefix, suffix) { + var ret = new Array(count); + for(var i = 0; i < count; ++i) { + ret[i] = prefix + i + suffix; } - var logFn = enabled.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - enabled.enabled = true; - - var fn = exports.enabled(namespace) ? enabled : disabled; - - fn.namespace = namespace; + return ret; +} - return fn; +function safeToString(obj) { + try { + return obj + ""; + } catch (e) { + return "[no string representation]"; + } } -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ +function markAsOriginatingFromRejection(e) { + try { + notEnumerableProp(e, "isOperational", true); + } + catch(ignore) {} +} -function enable(namespaces) { - exports.save(namespaces); +function originatesFromRejection(e) { + if (e == null) return false; + return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || + e["isOperational"] === true); +} - var split = (namespaces || '').split(/[\s,]+/); - var len = split.length; +function canAttachTrace(obj) { + return obj instanceof Error && es5.propertyIsWritable(obj, "stack"); +} - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); +var ensureErrorObject = (function() { + if (!("stack" in new Error())) { + return function(value) { + if (canAttachTrace(value)) return value; + try {throw new Error(safeToString(value));} + catch(err) {return err;} + }; } else { - exports.names.push(new RegExp('^' + namespaces + '$')); + return function(value) { + if (canAttachTrace(value)) return value; + return new Error(safeToString(value)); + }; } - } -} - -/** - * Disable debug output. - * - * @api public - */ +})(); -function disable() { - exports.enable(''); +function classString(obj) { + return {}.toString.call(obj); } -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -function enabled(name) { - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; +function copyDescriptors(from, to, filter) { + var keys = es5.names(from); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (filter(key)) { + try { + es5.defineProperty(to, key, es5.getDescriptor(from, key)); + } catch (ignore) {} + } } - } - return false; } -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ +var ret = { + isClass: isClass, + isIdentifier: isIdentifier, + inheritedDataKeys: inheritedDataKeys, + getDataPropertyOrDefault: getDataPropertyOrDefault, + thrower: thrower, + isArray: es5.isArray, + haveGetters: haveGetters, + notEnumerableProp: notEnumerableProp, + isPrimitive: isPrimitive, + isObject: isObject, + canEvaluate: canEvaluate, + errorObj: errorObj, + tryCatch: tryCatch, + inherits: inherits, + withAppended: withAppended, + maybeWrapAsError: maybeWrapAsError, + toFastProperties: toFastProperties, + filledRange: filledRange, + toString: safeToString, + canAttachTrace: canAttachTrace, + ensureErrorObject: ensureErrorObject, + originatesFromRejection: originatesFromRejection, + markAsOriginatingFromRejection: markAsOriginatingFromRejection, + classString: classString, + copyDescriptors: copyDescriptors, + hasDevTools: typeof chrome !== "undefined" && chrome && + typeof chrome.loadTimes === "function", + isNode: typeof process !== "undefined" && + classString(process).toLowerCase() === "[object process]" +}; +ret.isRecentNode = ret.isNode && (function() { + var version = process.versions.node.split(".").map(Number); + return (version[0] === 0 && version[1] > 10) || (version[0] > 0); +})(); -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} +if (ret.isNode) ret.toFastProperties(process); + +try {throw new Error(); } catch (e) {ret.lastLineError = e;} +module.exports = ret; -},{"ms":93}],91:[function(require,module,exports){ +},{"./es5.js":14}]},{},[4])(4) +}); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } +}).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"g5I+bs":94}],91:[function(require,module,exports){ module.exports = exports = require('./lib/sliced'); },{"./lib/sliced":92}],92:[function(require,module,exports){ @@ -30788,4 +30806,4 @@ function hasOwnProperty(obj, prop) { } }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":97,"g5I+bs":94,"inherits":75}]},{},[2]) \ No newline at end of file +},{"./support/isBuffer":97,"g5I+bs":94,"inherits":77}]},{},[2]) \ No newline at end of file diff --git a/package.json b/package.json index e62e829e919..232e89234c1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.13-pre", + "version": "4.4.13", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 2935ebab6446b1d7d154aae63b1612201d4b9ed4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 21 Apr 2016 15:12:22 -0700 Subject: [PATCH 0489/2240] style(services): add missing comments --- lib/services/common.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/services/common.js b/lib/services/common.js index 3d3d28e91c7..863b4708cab 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -1,10 +1,18 @@ 'use strict'; +/*! + * Module dependencies. + */ + var ObjectId = require('../types/objectid'); exports.flatten = flatten; exports.modifiedPaths = modifiedPaths; +/*! + * ignore + */ + function flatten(update, path) { var keys = Object.keys(update || {}); var numKeys = keys.length; @@ -30,6 +38,10 @@ function flatten(update, path) { return result; } +/*! + * ignore + */ + function modifiedPaths(update, path, result) { var keys = Object.keys(update || {}); var numKeys = keys.length; @@ -49,6 +61,10 @@ function modifiedPaths(update, path, result) { return result; } +/*! + * ignore + */ + function shouldFlatten(val) { return val && typeof val === 'object' && From 28da9723c089ef4d577fc3ebf6d158b61f4f9c78 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 22 Apr 2016 06:30:49 -0700 Subject: [PATCH 0490/2240] feat(schema): support arrays of arrays Fix #1361 --- lib/schema.js | 4 ++++ lib/schema/array.js | 42 ++++++++++++++++++++++++------------------ test/schema.test.js | 25 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index c30b23dd68b..329c7e0a946 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -524,6 +524,10 @@ Schema.interpretAsType = function(path, obj, options) { return new MongooseTypes.DocumentArray(path, cast, obj); } + if (Array.isArray(cast)) { + return new MongooseTypes.Array(path, Schema.interpretAsType(path, cast, options), obj); + } + if (typeof cast === 'string') { cast = MongooseTypes[cast.charAt(0).toUpperCase() + cast.substring(1)]; } else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type)) diff --git a/lib/schema/array.js b/lib/schema/array.js index 06aec7bb308..28e14af450e 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -2,22 +2,23 @@ * Module dependencies. */ -var SchemaType = require('../schematype'), - CastError = SchemaType.CastError, - Types = { - Boolean: require('./boolean'), - Date: require('./date'), - Number: require('./number'), - String: require('./string'), - ObjectId: require('./objectid'), - Buffer: require('./buffer') - }, - MongooseArray = require('../types').Array, - EmbeddedDoc = require('../types').Embedded, - Mixed = require('./mixed'), - cast = require('../cast'), - utils = require('../utils'), - isMongooseObject = utils.isMongooseObject; +var SchemaType = require('../schematype'); +var CastError = SchemaType.CastError; +var Types = { + Boolean: require('./boolean'), + Date: require('./date'), + Number: require('./number'), + String: require('./string'), + ObjectId: require('./objectid'), + Buffer: require('./buffer') +}; +var MongooseArray = require('../types').Array; +var EmbeddedDoc = require('../types').Embedded; +var Mixed = require('./mixed'); +var cast = require('../cast'); +var util = require('util'); +var utils = require('../utils'); +var isMongooseObject = utils.isMongooseObject; /** * Array SchemaType constructor @@ -54,7 +55,12 @@ function SchemaArray(key, cast, options) { : cast; this.casterConstructor = caster; - this.caster = new caster(null, castOptions); + if (typeof caster === 'function') { + this.caster = new caster(null, castOptions); + } else { + this.caster = caster; + } + if (!(this.caster instanceof EmbeddedDoc)) { this.caster.path = key; } @@ -154,7 +160,7 @@ SchemaArray.prototype.cast = function(value, doc, init) { } } catch (e) { // rethrow - throw new CastError(e.type, value, this.path, e); + throw new CastError('[' + e.kind + ']', util.inspect(value), this.path, e); } } diff --git a/test/schema.test.js b/test/schema.test.js index acdc7b5ee62..51cabd31840 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -399,6 +399,31 @@ describe('schema', function() { assert.equal(typeof mixed[3], 'object'); assert.ok(mixed[4] instanceof Date); assert.ok(mixed[5] instanceof DocumentObjectId); + + done(); + }); + + it('array of arrays', function(done) { + var test = new Schema({ + nums: [[Number]] + }); + var nums = test.path('nums').cast([['1', '2']]); + assert.deepEqual(nums, [[1, 2]]); + + nums = test.path('nums').cast(1); + assert.deepEqual(nums, [[1]]); + + var threw = false; + try { + test.path('nums').cast([['abcd']]); + } catch (error) { + threw = true; + assert.equal(error.name, 'CastError'); + assert.equal(error.message, + 'Cast to [[number]] failed for value "[["abcd"]]" at path "nums"'); + } + assert.ok(threw); + done(); }); From b69bbe4b4996a371a093bcbdaf82d9dc62b8c7f6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 22 Apr 2016 06:56:08 -0700 Subject: [PATCH 0491/2240] refactor(test): reuse connection for stream test --- test/model.stream.test.js | 84 +++++++++++++++------------------------ 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/test/model.stream.test.js b/test/model.stream.test.js index 105826afe97..a36117543c4 100644 --- a/test/model.stream.test.js +++ b/test/model.stream.test.js @@ -25,35 +25,35 @@ mongoose.model('PersonForStream', Person); var collection = 'personforstream_' + random(); describe('query stream:', function() { - before(function(done) { - var db = start(), - P = db.model('PersonForStream', collection); + var db = start(); + var P = db.model('PersonForStream', collection); + before(function(done) { var people = names.map(function(name) { return {name: name}; }); P.create(people, function(err) { assert.ifError(err); - db.close(); done(); }); }); + after(function(done) { + db.close(done); + }); + it('works', function(done) { - var db = start(), - P = db.model('PersonForStream', collection), - i = 0, - closed = 0, - paused = 0, - resumed = 0, - seen = {}, - err; + var i = 0; + var closed = 0; + var paused = 0; + var resumed = 0; + var seen = {}; + var err; var stream = P.find().batchSize(3).stream(); function cb() { - db.close(); assert.strictEqual(undefined, err); assert.equal(i, names.length); assert.equal(1, closed); @@ -110,9 +110,7 @@ describe('query stream:', function() { }); it('immediately destroying a stream prevents the query from executing', function(done) { - var db = start(), - P = db.model('PersonForStream', collection), - i = 0; + var i = 0; var stream = P.where('name', 'Jonah').select('name').findOne().stream(); @@ -120,7 +118,6 @@ describe('query stream:', function() { assert.ifError(err); assert.equal(0, i); process.nextTick(function() { - db.close(); assert.strictEqual(null, stream._fields); done(); }); @@ -138,10 +135,8 @@ describe('query stream:', function() { it('destroying a stream stops it', function(done) { this.slow(300); - var db = start(), - P = db.model('PersonForStream', collection), - finished = 0, - i = 0; + var finished = 0; + var i = 0; var stream = P.where('name').exists().limit(10).select('_id').stream(); @@ -151,7 +146,6 @@ describe('query stream:', function() { function cb(err) { ++finished; setTimeout(function() { - db.close(); assert.strictEqual(undefined, err); assert.equal(5, i); assert.equal(1, finished); @@ -177,11 +171,12 @@ describe('query stream:', function() { it('errors', function(done) { this.slow(300); - var db = start({server: {auto_reconnect: false}}), - P = db.model('PersonForStream', collection), - finished = 0, - closed = 0, - i = 0; + var db = start({server: {auto_reconnect: false}}); + var P = db.model('PersonForStream', collection); + + var finished = 0; + var closed = 0; + var i = 0; var stream = P.find().batchSize(5).stream(); @@ -213,17 +208,14 @@ describe('query stream:', function() { }); it('pipe', function(done) { - var db = start(), - P = db.model('PersonForStream', collection), - filename = '/tmp/_mongoose_stream_out.txt', - out = fs.createWriteStream(filename); + var filename = '/tmp/_mongoose_stream_out.txt'; + var out = fs.createWriteStream(filename); var opts = {transform: JSON.stringify}; var stream = P.find().sort('name').limit(20).stream(opts); stream.pipe(out); function cb(err) { - db.close(); assert.ifError(err); var contents = fs.readFileSync(filename, 'utf8'); assert.ok(/Aaden/.test(contents)); @@ -240,16 +232,13 @@ describe('query stream:', function() { }); it('lean', function(done) { - var db = start(), - P = db.model('PersonForStream', collection), - i = 0, - closed = 0, - err; + var i = 0; + var closed = 0; + var err; var stream = P.find({}).lean().stream(); function cb() { - db.close(); assert.strictEqual(undefined, err); assert.equal(i, names.length); assert.equal(1, closed); @@ -291,8 +280,6 @@ describe('query stream:', function() { it('supports $elemMatch with $in (gh-1091)', function(done) { this.timeout(3000); - var db = start(); - var postSchema = new Schema({ ids: [{type: Schema.ObjectId}], title: String @@ -321,15 +308,12 @@ describe('query stream:', function() { error = err; }). on('close', function() { - db.close(); done(error); }); }); }); it('supports population (gh-1411)', function(done) { - var db = start(); - var barSchema = new Schema({ value: Number }); @@ -347,7 +331,7 @@ describe('query stream:', function() { assert.ok(~found.indexOf(2)); assert.ok(~found.indexOf(3)); } - db.close(done); + done(); } Bar.create({value: 2}, {value: 3}, function(err, bar1, bar2) { @@ -370,8 +354,6 @@ describe('query stream:', function() { }); it('respects schema options (gh-1862)', function(done) { - var db = start(); - var schema = new Schema({ fullname: {type: String}, password: {type: String, select: false} @@ -382,14 +364,12 @@ describe('query stream:', function() { assert.ifError(error); User.find().stream().on('data', function(doc) { assert.equal(undefined, doc.password); - db.close(done); + done(); }); }); }); it('works with populate + lean (gh-2841)', function(done) { - var db = start(); - var Sku = db.model('Sku', {}, 'gh2841_0'); var Item = db.model('Item', { sku: {ref: 'Sku', type: Schema.Types.ObjectId} @@ -409,15 +389,13 @@ describe('query stream:', function() { }); stream.on('end', function() { assert.equal(found, 1); - db.close(done); + done(); }); }); }); }); it('works with populate + dynref (gh-3108)', function(done) { - var db = start(); - var reviewSchema = new Schema({ _id: Number, text: String, @@ -493,7 +471,7 @@ describe('query stream:', function() { stream.on('close', function() { assert.equal(count, 2); - db.close(done); + done(); }); }; From 41a1f7def6c43903c79a88833e5cae9c56108e6d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 22 Apr 2016 07:01:37 -0700 Subject: [PATCH 0492/2240] chore: now working on 4.4.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 232e89234c1..8b3b76ede0e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.13", + "version": "4.4.14-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ebebb0f5481b85cf220ce5339dbc4eff0854af0c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 22 Apr 2016 07:46:12 -0700 Subject: [PATCH 0493/2240] docs(validation): warn that validators that take 2 args are async re: #4084 --- test/docs/validation.test.js | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 26c97b31315..8875f03c453 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -142,6 +142,46 @@ describe('validation docs', function() { // acquit:ignore:end }); + /** + * Custom validators can also be asynchronous. If your validator function + * takes 2 arguments, mongoose will assume the 2nd argument is a callback. + * + * Even if you don't want to use asynchronous validators, be careful, + * because mongoose 4 will assume that **all** functions that take 2 + * arguments are asynchronous, like the + * [`validator.isEmail` function](https://www.npmjs.com/package/validator) + */ + it('Async Custom Validators', function(done) { + var userSchema = new Schema({ + phone: { + type: String, + validate: { + validator: function(v, cb) { + setTimeout(function() { + cb(/\d{3}-\d{3}-\d{4}/.test(v)); + }, 5); + }, + message: '{VALUE} is not a valid phone number!' + }, + required: [true, 'User phone number required'] + } + }); + + var User = db.model('user', userSchema); + var user = new User(); + var error; + + user.phone = '555.0123'; + user.validate(function(error) { + assert.ok(error); + assert.equal(error.errors['phone'].message, + '555.0123 is not a valid phone number!'); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); + /** * Errors returned after failed validation contain an `errors` object * holding the actual `ValidatorError` objects. Each From b983e56ef03de87db260f6e541e4165b95196156 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 22 Apr 2016 12:17:16 -0700 Subject: [PATCH 0494/2240] docs: use correct issue number in history.md Re: https://github.com/Automattic/mongoose/issues/3254#issuecomment-212205869 --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index d01f8a9dc62..0c5364426e5 100644 --- a/History.md +++ b/History.md @@ -312,7 +312,7 @@ 4.2.4 / 2015-11-02 ================== - * fixed; upgraded `ms` package for security vulnerability #3254 [fhemberger](https://github.com/fhemberger) + * fixed; upgraded `ms` package for security vulnerability #3524 [fhemberger](https://github.com/fhemberger) * fixed; ESlint rules #3517 [ChristianMurphy](https://github.com/ChristianMurphy) * docs; typo in aggregation docs #3513 [rafakato](https://github.com/rafakato) * fixed; add `dontThrowCastError` option to .update() for promises #3512 From 977f7616de952b16e5d0398c6174ac3a477fe536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Co=CC=82te=CC=81-Roy?= Date: Sat, 23 Apr 2016 09:33:43 -0400 Subject: [PATCH 0495/2240] add unmarkModified method this clears the modified state on the specified field. --- lib/document.js | 17 +++++++++++++ test/document.modified.test.js | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/lib/document.js b/lib/document.js index f2f5c026133..3d5d680903c 100644 --- a/lib/document.js +++ b/lib/document.js @@ -914,6 +914,23 @@ Document.prototype.markModified = function(path) { this.$__.activePaths.modify(path); }; +/** + * Clears the modified state on the specified path. + * + * ####Example: + * + * doc.foo = 'bar'; + * doc.unmarkModified('foo'); + * doc.save() // changes to foo will not be persisted + * + * @param {String} path the path to unmark modified + * @api public + */ + +Document.prototype.unmarkModified = function(path) { + this.$__.activePaths.init(path); +}; + /** * Returns the list of paths that have been modified. * diff --git a/test/document.modified.test.js b/test/document.modified.test.js index 665520f0898..f4a84ad9aa8 100644 --- a/test/document.modified.test.js +++ b/test/document.modified.test.js @@ -513,5 +513,49 @@ describe('document modified', function() { }); }); }); + + + it('should reset the modified state after calling unmarkModified', function(done) { + var db = start(), + BlogPost = db.model(modelName, collection); + + var b = new BlogPost(); + assert.equal(false, b.isModified('author')) + b.author = 'foo'; + assert.equal(true, b.isModified('author')); + assert.equal(true, b.isModified()) + b.unmarkModified('author'); + assert.equal(false, b.isModified('author')); + assert.equal(false, b.isModified()) + + b.save(function(err) { + assert.strictEqual(null, err); + + BlogPost.findById(b._id, function(err2, b2) { + assert.strictEqual(null, err2); + + assert.equal(false, b2.isModified('author')) + assert.equal(false, b2.isModified()) + b2.author = 'bar'; + assert.equal(true, b2.isModified('author')); + assert.equal(true, b2.isModified()) + b2.unmarkModified('author'); + assert.equal(false, b2.isModified('author')); + assert.equal(false, b2.isModified()) + + b2.save(function(err3) { + assert.strictEqual(null, err3); + BlogPost.findById(b._id, function(err4, b3) { + assert.strictEqual(null, err4); + // was not saved because modified state was unset + assert.equal(b3.author, 'foo'); + db.close(); + done(); + }); + }); + }); + }); + }); + }); }); From 2cdc4f383a4b9cac8cf9d0c309eefd0ecfafd367 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Apr 2016 10:44:47 -0700 Subject: [PATCH 0496/2240] refactor(schema): move array geospatial query casting into separate file Re: #4014 --- lib/schema/array.js | 139 +++++------------------------ lib/schema/operators/geospatial.js | 95 ++++++++++++++++++++ lib/schema/operators/helpers.js | 34 +++++++ test/docs/validation.test.js | 2 +- 4 files changed, 151 insertions(+), 119 deletions(-) create mode 100644 lib/schema/operators/geospatial.js create mode 100644 lib/schema/operators/helpers.js diff --git a/lib/schema/array.js b/lib/schema/array.js index 06aec7bb308..ee5055a56f4 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -2,22 +2,24 @@ * Module dependencies. */ -var SchemaType = require('../schematype'), - CastError = SchemaType.CastError, - Types = { - Boolean: require('./boolean'), - Date: require('./date'), - Number: require('./number'), - String: require('./string'), - ObjectId: require('./objectid'), - Buffer: require('./buffer') - }, - MongooseArray = require('../types').Array, - EmbeddedDoc = require('../types').Embedded, - Mixed = require('./mixed'), - cast = require('../cast'), - utils = require('../utils'), - isMongooseObject = utils.isMongooseObject; +var SchemaType = require('../schematype'); +var CastError = SchemaType.CastError; +var Types = { + Boolean: require('./boolean'), + Date: require('./date'), + Number: require('./number'), + String: require('./string'), + ObjectId: require('./objectid'), + Buffer: require('./buffer') +}; +var MongooseArray = require('../types').Array; +var EmbeddedDoc = require('../types').Embedded; +var Mixed = require('./mixed'); +var cast = require('../cast'); +var utils = require('../utils'); +var isMongooseObject = utils.isMongooseObject; +var castToNumber = require('./operators/helpers').castToNumber; +var geospatial = require('./operators/geospatial'); /** * Array SchemaType constructor @@ -216,95 +218,6 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { val; }; -/*! - * @ignore - * - * $atomic cast helpers - */ - -function castToNumber(val) { - return Types.Number.prototype.cast.call(this, val); -} - -function castArraysOfNumbers(arr, self) { - arr.forEach(function(v, i) { - if (Array.isArray(v)) { - castArraysOfNumbers(v, self); - } else { - arr[i] = castToNumber.call(self, v); - } - }); -} - -function cast$near(val) { - if (Array.isArray(val)) { - castArraysOfNumbers(val, this); - return val; - } - - if (val && val.$geometry) { - return cast$geometry(val, this); - } - - return SchemaArray.prototype.castForQuery.call(this, val); -} - -function cast$geometry(val, self) { - switch (val.$geometry.type) { - case 'Polygon': - case 'LineString': - case 'Point': - castArraysOfNumbers(val.$geometry.coordinates, self); - break; - default: - // ignore unknowns - break; - } - - if (val.$maxDistance) { - val.$maxDistance = castToNumber.call(self, val.$maxDistance); - } - - return val; -} - -function cast$within(val) { - var _this = this; - - if (val.$maxDistance) { - val.$maxDistance = castToNumber.call(_this, val.$maxDistance); - } - - if (val.$box || val.$polygon) { - var type = val.$box ? '$box' : '$polygon'; - val[type].forEach(function(arr) { - if (!Array.isArray(arr)) { - var msg = 'Invalid $within $box argument. ' - + 'Expected an array, received ' + arr; - throw new TypeError(msg); - } - arr.forEach(function(v, i) { - arr[i] = castToNumber.call(this, v); - }); - }); - } else if (val.$center || val.$centerSphere) { - type = val.$center ? '$center' : '$centerSphere'; - val[type].forEach(function(item, i) { - if (Array.isArray(item)) { - item.forEach(function(v, j) { - item[j] = castToNumber.call(this, v); - }); - } else { - val[type][i] = castToNumber.call(this, item); - } - }); - } else if (val.$geometry) { - cast$geometry(val, this); - } - - return val; -} - function cast$all(val) { if (!Array.isArray(val)) { val = [val]; @@ -338,22 +251,12 @@ function cast$elemMatch(val) { return cast(this.casterConstructor.schema, val); } -function cast$geoIntersects(val) { - var geo = val.$geometry; - if (!geo) { - return; - } - - cast$geometry(val, this); - return val; -} - var handle = SchemaArray.prototype.$conditionalHandlers = {}; handle.$all = cast$all; handle.$options = String; handle.$elemMatch = cast$elemMatch; -handle.$geoIntersects = cast$geoIntersects; +handle.$geoIntersects = geospatial.cast$geoIntersects; handle.$or = handle.$and = function(val) { if (!Array.isArray(val)) { throw new TypeError('conditional $or/$and require array'); @@ -368,10 +271,10 @@ handle.$or = handle.$and = function(val) { }; handle.$near = -handle.$nearSphere = cast$near; +handle.$nearSphere = geospatial.cast$near; handle.$within = -handle.$geoWithin = cast$within; +handle.$geoWithin = geospatial.cast$within; handle.$size = handle.$maxDistance = castToNumber; diff --git a/lib/schema/operators/geospatial.js b/lib/schema/operators/geospatial.js new file mode 100644 index 00000000000..fc2433961a4 --- /dev/null +++ b/lib/schema/operators/geospatial.js @@ -0,0 +1,95 @@ +/*! + * Module requirements. + */ + +var castArraysOfNumbers = require('./helpers').castArraysOfNumbers; +var castToNumber = require('./helpers').castToNumber; + +/*! + * ignore + */ + +exports.cast$geoIntersects = cast$geoIntersects; +exports.cast$near = cast$near; +exports.cast$within = cast$within; + +function cast$near(val) { + var SchemaArray = require('../array'); + + if (Array.isArray(val)) { + castArraysOfNumbers(val, this); + return val; + } + + if (val && val.$geometry) { + return cast$geometry(val, this); + } + + return SchemaArray.prototype.castForQuery.call(this, val); +} + +function cast$geometry(val, self) { + switch (val.$geometry.type) { + case 'Polygon': + case 'LineString': + case 'Point': + castArraysOfNumbers(val.$geometry.coordinates, self); + break; + default: + // ignore unknowns + break; + } + + if (val.$maxDistance) { + val.$maxDistance = castToNumber.call(self, val.$maxDistance); + } + + return val; +} + +function cast$within(val) { + var _this = this; + + if (val.$maxDistance) { + val.$maxDistance = castToNumber.call(_this, val.$maxDistance); + } + + if (val.$box || val.$polygon) { + var type = val.$box ? '$box' : '$polygon'; + val[type].forEach(function(arr) { + if (!Array.isArray(arr)) { + var msg = 'Invalid $within $box argument. ' + + 'Expected an array, received ' + arr; + throw new TypeError(msg); + } + arr.forEach(function(v, i) { + arr[i] = castToNumber.call(this, v); + }); + }); + } else if (val.$center || val.$centerSphere) { + type = val.$center ? '$center' : '$centerSphere'; + val[type].forEach(function(item, i) { + if (Array.isArray(item)) { + item.forEach(function(v, j) { + item[j] = castToNumber.call(this, v); + }); + } else { + val[type][i] = castToNumber.call(this, item); + } + }); + } else if (val.$geometry) { + cast$geometry(val, this); + } + + return val; +} + +function cast$geoIntersects(val) { + var geo = val.$geometry; + if (!geo) { + return; + } + + cast$geometry(val, this); + return val; +} diff --git a/lib/schema/operators/helpers.js b/lib/schema/operators/helpers.js new file mode 100644 index 00000000000..850354a8b57 --- /dev/null +++ b/lib/schema/operators/helpers.js @@ -0,0 +1,34 @@ +'use strict'; + +/*! + * Module requirements. + */ + +var Types = { + Number: require('../number') +}; + +/*! + * @ignore + */ + +exports.castToNumber = castToNumber; +exports.castArraysOfNumbers = castArraysOfNumbers; + +/*! + * @ignore + */ + +function castToNumber(val) { + return Types.Number.prototype.cast.call(this, val); +} + +function castArraysOfNumbers(arr, self) { + arr.forEach(function(v, i) { + if (Array.isArray(v)) { + castArraysOfNumbers(v, self); + } else { + arr[i] = castToNumber.call(self, v); + } + }); +} diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 8875f03c453..dc13bb1f052 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -167,7 +167,7 @@ describe('validation docs', function() { } }); - var User = db.model('user', userSchema); + var User = db.model('User', userSchema); var user = new User(); var error; From 6510e8446990a4318ac9235f88edf0a5369f5fdb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Apr 2016 11:00:48 -0700 Subject: [PATCH 0497/2240] test(schema): repro #4014 --- test/document.test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 124b58b08c4..cfb36e10c39 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2594,5 +2594,36 @@ describe('document', function() { }); }); }); + + it('single embedded docs with $near (gh-4014)', function(done) { + var schema = new mongoose.Schema({ + placeName: String + }); + + var geoSchema = new mongoose.Schema({ + type: { + type: String, + enum: 'Point', + default: 'Point' + }, + coordinates: { + type: [Number], + default: [0, 0] + } + }); + + schema.add({ geo: geoSchema }); + schema.index({ geo: '2dsphere' }); + + var MyModel = db.model('gh4014', schema); + + MyModel. + where('geo').near({ center: [50, 50] }). + exec(function(error) { + assert.ifError(error); + done(); + }); + + }); }); }); From f3310cb37c6558c40626cc447c7e30427723413a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Apr 2016 11:00:52 -0700 Subject: [PATCH 0498/2240] fix(schema): add complete set of geospatial operators for single embedded subdocs Fix #4014 --- lib/schema/embedded.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index ad0f90a8bd0..edfe3aef2c9 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -1,5 +1,13 @@ +'use strict'; + +/*! + * Module dependencies. + */ + var SchemaType = require('../schematype'); var Subdocument = require('../types/subdocument'); +var castToNumber = require('./operators/helpers').castToNumber; +var geospatial = require('./operators/geospatial'); module.exports = Embedded; @@ -61,6 +69,21 @@ Embedded.prototype.$conditionalHandlers.$geoWithin = function(val) { return { $geometry: this.castForQuery(val.$geometry) }; }; +/*! + * ignore + */ + +Embedded.prototype.$conditionalHandlers.$near = +Embedded.prototype.$conditionalHandlers.$nearSphere = geospatial.cast$near; + +Embedded.prototype.$conditionalHandlers.$within = +Embedded.prototype.$conditionalHandlers.$geoWithin = geospatial.cast$within; + +Embedded.prototype.$conditionalHandlers.$geoIntersects = + geospatial.cast$geoIntersects; + +Embedded.prototype.$conditionalHandlers.$maxDistance = castToNumber; + /** * Casts contents * From cecd6a32ffdd2e630dcfa19edb368932470679b0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Apr 2016 13:08:58 -0700 Subject: [PATCH 0499/2240] test(populate): repro #4073 --- test/model.populate.test.js | 110 ++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index f51ac4cdf29..6cde9146943 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4,6 +4,7 @@ var _ = require('lodash'); var start = require('./common'); +var async = require('async'); var assert = require('power-assert'); var mongoose = start.mongoose; var utils = require('../lib/utils'); @@ -3558,5 +3559,114 @@ describe('model: populate:', function() { }); }); }); + + it('out-of-order discriminators (gh-4073)', function(done) { + var UserSchema = new Schema({ + name: String + }); + + var CommentSchema = new Schema({ + content: String + }); + + var BlogPostSchema = new Schema({ + title: String + }); + + var EventSchema = new Schema({ + name: String, + createdAt: { type: Date, default: Date.now } + }); + + var UserEventSchema = new Schema({ + user: { type: ObjectId, ref: 'gh4073_0' } + }); + + var CommentEventSchema = new Schema({ + comment: { type: ObjectId, ref: 'gh4073_1' } + }); + + var BlogPostEventSchema = new Schema({ + blogpost: { type: ObjectId, ref: 'gh4073_2' } + }); + + var User = db.model('gh4073_0', UserSchema); + var Comment = db.model('gh4073_1', CommentSchema); + var BlogPost = db.model('gh4073_2', BlogPostSchema); + + var Event = db.model('gh4073_3', EventSchema); + var UserEvent = Event.discriminator('User4073', UserEventSchema); + var CommentEvent = Event.discriminator('Comment4073', + CommentEventSchema); + var BlogPostEvent = Event.discriminator('BlogPost4073', BlogPostEventSchema); + + var u1 = new User({ name: 'user 1' }); + var u2 = new User({ name: 'user 2' }); + var u3 = new User({ name: 'user 3' }); + var c1 = new Comment({ content: 'comment 1' }); + var c2 = new Comment({ content: 'comment 2' }); + var c3 = new Comment({ content: 'comment 3' }); + var b1 = new BlogPost({ title: 'blog post 1' }); + var b2 = new BlogPost({ title: 'blog post 2' }); + var b3 = new BlogPost({ title: 'blog post 3' }); + var ue1 = new UserEvent({ user: u1 }); + var ue2 = new UserEvent({ user: u2 }); + var ue3 = new UserEvent({ user: u3 }); + var ce1 = new CommentEvent({ comment: c1 }); + var ce2 = new CommentEvent({ comment: c2 }); + var ce3 = new CommentEvent({ comment: c3 }); + var be1 = new BlogPostEvent({ blogpost: b1 }); + var be2 = new BlogPostEvent({ blogpost: b2 }); + var be3 = new BlogPostEvent({ blogpost: b3 }); + + async.series( + [ + u1.save, + u2.save, + u3.save, + + c1.save, + c2.save, + c3.save, + + b1.save, + b2.save, + b3.save, + + ce1.save, + ue1.save, + be1.save, + + ce2.save, + ue2.save, + be2.save, + + ce3.save, + ue3.save, + be3.save, + + function(next) { + Event. + find({}). + populate('user comment blogpost'). + exec(function(err, docs) { + docs.forEach(function(doc) { + if (doc.__t === 'User4073') { + assert.ok(doc.user.name.indexOf('user') !== -1); + } else if (doc.__t === 'Comment4073') { + assert.ok(doc.comment.content.indexOf('comment') !== -1); + } else if (doc.__t === 'BlogPost4073') { + assert.ok(doc.blogpost.title.indexOf('blog post') !== -1); + } else { + assert.ok(false); + } + }); + next(); + }); + } + ], + done + ); + }); }); }); From 47580d3500b7025c862383c527895aec9fbfa6de Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Apr 2016 13:09:25 -0700 Subject: [PATCH 0500/2240] fix(populate): make sure to use correct assignment order for each model Fix #4073 --- lib/model.js | 63 +++++++++++++--------------------------------------- 1 file changed, 15 insertions(+), 48 deletions(-) diff --git a/lib/model.js b/lib/model.js index c181ae9fe6c..5d2d11128f7 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2575,7 +2575,7 @@ var excludeIdReg = /\s?-_id\s?/, excludeIdRegGlobal = /\s?-_id\s?/g; function populate(model, docs, options, cb) { - var modelsMap, rawIds; + var modelsMap; // normalize single / multiple docs passed if (!Array.isArray(docs)) { @@ -2587,14 +2587,14 @@ function populate(model, docs, options, cb) { } modelsMap = getModelsMapForPopulate(model, docs, options); - rawIds = getIdsForAndAddIdsInMapPopulate(modelsMap); var i, len = modelsMap.length, mod, match, select, promise, vals = []; - promise = new Promise(function(err, vals, options, assignmentOpts) { + promise = new Promise(function(err, vals, mod, assignmentOpts) { if (err) return cb(err); + var options = mod.options; var lean = options.options && options.options.lean, len = vals.length, rawOrder = {}, rawDocs = {}, key, val; @@ -2613,10 +2613,10 @@ function populate(model, docs, options, cb) { } assignVals({ - rawIds: rawIds, + rawIds: mod.ids, rawDocs: rawDocs, rawOrder: rawOrder, - docs: docs, + docs: mod.docs, path: options.path, options: assignmentOpts }); @@ -2675,7 +2675,7 @@ function populate(model, docs, options, cb) { mod.options.options.limit = mod.options.options.limit * ids.length; } - mod.Model.find(match, select, mod.options.options, next.bind(this, mod.options, assignmentOpts)); + mod.Model.find(match, select, mod.options.options, next.bind(this, mod, assignmentOpts)); } if (!hasOne) { @@ -2750,6 +2750,13 @@ function getModelsMapForPopulate(model, docs, options) { modelNames = [modelNames]; } + var ret = convertTo_id(utils.getValue(options.path, doc)); + var id = String(utils.getValue('_id', doc)); + options._docs[id] = Array.isArray(ret) ? ret.slice() : ret; + if (doc.$__) { + doc.populated(options.path, options._docs[id], options); + } + var k = modelNames.length; while (k--) { modelName = modelNames[k]; @@ -2769,11 +2776,12 @@ function getModelsMapForPopulate(model, docs, options) { Model: Model, options: currentOptions, docs: [doc], - ids: [] + ids: [ret] }; map.push(available[modelName]); } else { available[modelName].docs.push(doc); + available[modelName].ids.push(ret); } } } @@ -2781,46 +2789,6 @@ function getModelsMapForPopulate(model, docs, options) { return map; } -function getIdsForAndAddIdsInMapPopulate(modelsMap) { - var rawIds = [], // for the correct position - i, j, doc, docs, id, len, len2, ret, isDocument, options, path; - - len2 = modelsMap.length; - for (j = 0; j < len2; j++) { - docs = modelsMap[j].docs; - len = docs.length; - options = modelsMap[j].options; - path = options.path; - - for (i = 0; i < len; i++) { - ret = undefined; - doc = docs[i]; - id = String(utils.getValue('_id', doc)); - isDocument = !!doc.$__; - - if (!ret || Array.isArray(ret) && ret.length === 0) { - ret = utils.getValue(path, doc); - } - - if (ret) { - ret = convertTo_id(ret); - - options._docs[id] = Array.isArray(ret) ? ret.slice() : ret; - } - - rawIds.push(ret); - modelsMap[j].ids.push(ret); - - if (isDocument) { - // cache original populated _ids and model used - doc.populated(path, options._docs[id], options); - } - } - } - - return rawIds; -} - /*! * Retrieve the _id of `val` if a Document or Array of Documents. * @@ -2851,7 +2819,6 @@ function convertTo_id(val) { function assignVals(o) { // replace the original ids in our intermediate _ids structure // with the documents found by query - assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, o.options); // now update the original documents being populated using the From ba0b2a84a08935e0600baa84e9c5c6b55b9b1b5a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 24 Apr 2016 09:22:20 -0700 Subject: [PATCH 0501/2240] chore: release 3.8.40 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 087cebe92e0..a3ad4eb21a4 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +3.8.40 / 2016-04-24 +=================== + * upgraded; mquery -> 1.10.0 #3989 + 3.8.39 / 2016-01-15 =================== * fixed; casting a number to a buffer #3764 diff --git a/package.json b/package.json index 28e695e4a3b..5078cc2ad96 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose" , "description": "Mongoose MongoDB ODM" - , "version": "3.8.39" + , "version": "3.8.40" , "author": "Guillermo Rauch " , "keywords": ["mongodb", "document", "model", "schema", "database", "odm", "data", "datastore", "query", "nosql", "orm", "db"] , "dependencies": { From d74e6798d549f5898427abc2e3eae85d9e78794f Mon Sep 17 00:00:00 2001 From: Jacob Burton Date: Mon, 25 Apr 2016 12:33:42 -0600 Subject: [PATCH 0502/2240] support specifying mongos as a connection string query parameter --- lib/drivers/node-mongodb-native/connection.js | 1 + test/connection.test.js | 53 +++++++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index b8ca9d888cf..f7d70020944 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -241,6 +241,7 @@ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { o.replset || (o.replset = o.replSet) || (o.replset = {}); o.server.socketOptions || (o.server.socketOptions = {}); o.replset.socketOptions || (o.replset.socketOptions = {}); + o.mongos || (o.mongos = (connStrOpts && connStrOpts.mongos)); (o.mongos === true) && (o.mongos = {}); var opts = connStrOpts || {}; diff --git a/test/connection.test.js b/test/connection.test.js index 4084cc2a8df..9058d1b1a65 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -553,8 +553,8 @@ describe('connections:', function() { done(); }); }); - describe('when mongos is passed', function() { - it('works when specifying {mongos: true}', function(done) { + describe('for sharded clusters (mongos)', function() { + it('works when specifying {mongos: true} as an option', function(done) { var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2' + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12' + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true' @@ -599,7 +599,54 @@ describe('connections:', function() { assert.strictEqual(db.options.mongos.sslValidate, true); done(); }); - it('works when specifying mongos opts', function(done) { + it('works when specifying mongos as a query param on the connection string', function(done) { + var newQueryParam = '&mongos=true'; + var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2' + + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12' + + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true' + + '&nativeParser=false&w=2&safe=true&fsync=true&journal=true' + + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags=' + + 'dc:ny,rack:1&readPreferenceTags=dc:sf&sslValidate=true' + + newQueryParam; + + var db = mongoose.createConnection(conn); + db.on('error', done); + db.close(); + assert.strictEqual(typeof db.options, 'object'); + assert.strictEqual(typeof db.options.server, 'object'); + assert.strictEqual(typeof db.options.server.socketOptions, 'object'); + assert.strictEqual(typeof db.options.db, 'object'); + assert.strictEqual(typeof db.options.replset, 'object'); + assert.strictEqual(typeof db.options.replset.socketOptions, 'object'); + assert.strictEqual(typeof db.options.mongos, 'object'); + assert.strictEqual(db.options.server.auto_reconnect, false); + assert.strictEqual(db.options.server.poolSize, 2); + assert.strictEqual(db.options.server.slave_ok, false); + assert.strictEqual(db.options.server.ssl, true); + assert.strictEqual(db.options.replset.ssl, true); + assert.strictEqual(db.options.mongos.ssl, true); + assert.strictEqual(db.options.server.socketOptions.socketTimeoutMS, 10); + assert.strictEqual(db.options.replset.socketOptions.socketTimeoutMS, 10); + assert.strictEqual(db.options.server.socketOptions.connectTimeoutMS, 12); + assert.strictEqual(db.options.replset.socketOptions.connectTimeoutMS, 12); + assert.strictEqual(db.options.replset.retries, 10); + assert.strictEqual(db.options.replset.reconnectWait, 5); + assert.strictEqual(db.options.replset.rs_name, 'replworld'); + assert.strictEqual(db.options.replset.read_secondary, true); + assert.strictEqual(db.options.db.native_parser, false); + assert.strictEqual(db.options.db.w, 2); + assert.strictEqual(db.options.db.safe, true); + assert.strictEqual(db.options.db.fsync, true); + assert.strictEqual(db.options.db.journal, true); + assert.strictEqual(db.options.db.wtimeoutMS, 80); + assert.strictEqual(db.options.db.readPreference, 'nearest'); + assert.deepEqual(db.options.db.read_preference_tags, [{dc: 'ny', rack: 1}, {dc: 'sf'}]); + assert.strictEqual(db.options.db.forceServerObjectId, false); + assert.strictEqual(db.options.server.sslValidate, true); + assert.strictEqual(db.options.mongos.sslValidate, true); + done(); + }); + it('works when specifying mongos as an object with options', function(done) { var conn = 'mongodb://localhost/fake?autoReconnect=false&poolSize=2' + '&slaveOk=false&ssl=true&socketTimeoutMS=10&connectTimeoutMS=12' + '&retries=10&reconnectWait=5&rs_name=replworld&readSecondary=true' From d0e4f500c58e469c85e8be036d167645ad0f6f1b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 26 Apr 2016 13:30:25 -0700 Subject: [PATCH 0503/2240] docs: add DataFox and SixPlus to index.jade --- index.jade | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.jade b/index.jade index 56142852d66..0b342aa97ec 100644 --- a/index.jade +++ b/index.jade @@ -112,11 +112,11 @@ html(lang='en') a(href="http://www.elevenjames.com") img(src="http://i.imgur.com/vx8KH9Z.jpg", alt="Eleven James") li - a(href="https://bozuko.com/", alt="Bozuko") - img(src="docs/images/apps/h_bozuko.jpg", alt="Bozuko") + a(href="http://www.datafox.com/", alt="DataFox") + img(src="http://i.imgur.com/VxHJfAJ.png", alt="DataFox") li - a(href="http://yourquestions.mcdonalds.ca/") - img#mcds(src="docs/images/apps/h_mcds.png", alt="McDonalds") + a(href="https://sixplus.com") + img(src="https://pbs.twimg.com/profile_images/687026787260313601/wnJaH97y.jpg", alt="SixPlus") p#footer Licensed under MIT. Copyright 2011 LearnBoost. script. document.body.className = 'load'; From c2cab6a7a4608001d74cf15c364e5b2a4517e5b4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Apr 2016 12:53:34 -0700 Subject: [PATCH 0504/2240] fix: upgrade mongodb -> 2.1.18 Fix #4102 --- package.json | 2 +- test/types.buffer.test.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8b3b76ede0e..a6a9486f93c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.21", "hooks-fixed": "1.1.0", "kareem": "1.0.1", - "mongodb": "2.1.16", + "mongodb": "2.1.18", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.10.0", diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js index c4fe683a7d6..ae0c882b333 100644 --- a/test/types.buffer.test.js +++ b/test/types.buffer.test.js @@ -331,7 +331,8 @@ describe('types.buffer', function() { set: function() { reset(tj); not(tj); - tj.required.set(0, 1); + tj.required[0] = 1; + tj.markModified('required'); is(tj); } }; From 0ab247d543e00bfdf20ba07c2157301df07e7b0f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Apr 2016 13:58:53 -0700 Subject: [PATCH 0505/2240] fix: upgrade bson to ~0.4.23 re: #4102 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a6a9486f93c..d0c68ea0423 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "license": "MIT", "dependencies": { "async": "1.5.2", - "bson": "~0.4.21", + "bson": "~0.4.23", "hooks-fixed": "1.1.0", "kareem": "1.0.1", "mongodb": "2.1.18", From f7ca361b9c24d06a4f47f7db22e9982c74d15592 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Apr 2016 14:03:33 -0700 Subject: [PATCH 0506/2240] chore: release 4.4.14 --- History.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index d0880cf26ac..aaee07d7e7c 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.4.14 / 2016-04-27 +=================== + * fix: upgrade mongodb -> 2.1.18 #4102 + * feat(connection): allow setting mongos as a uri query param #4093 #4035 [burtonjc](https://github.com/burtonjc) + * fix(populate): make sure to use correct assignment order for each model #4073 + * fix(schema): add complete set of geospatial operators for single embedded subdocs #4014 + 3.8.40 / 2016-04-24 =================== * upgraded; mquery -> 1.10.0 #3989 diff --git a/package.json b/package.json index d0c68ea0423..64fc3545b78 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.14-pre", + "version": "4.4.14", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e3bb55d36f2c3fcb587294e376494f9600d70b85 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Apr 2016 14:11:10 -0700 Subject: [PATCH 0507/2240] docs(index): use better sixplus logo --- index.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.jade b/index.jade index 0b342aa97ec..69570082aaf 100644 --- a/index.jade +++ b/index.jade @@ -116,7 +116,7 @@ html(lang='en') img(src="http://i.imgur.com/VxHJfAJ.png", alt="DataFox") li a(href="https://sixplus.com") - img(src="https://pbs.twimg.com/profile_images/687026787260313601/wnJaH97y.jpg", alt="SixPlus") + img(src="https://s3.amazonaws.com/bookalokal-assets/sixplus/sixplus-logo-horizontal-dark.png" alt="SixPlus") p#footer Licensed under MIT. Copyright 2011 LearnBoost. script. document.body.className = 'load'; From 61d9fa59ed8083c554d79b58ed10b6904be1b737 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Apr 2016 14:13:11 -0700 Subject: [PATCH 0508/2240] docs(index): add missing comma --- index.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.jade b/index.jade index 69570082aaf..7d956fb6837 100644 --- a/index.jade +++ b/index.jade @@ -116,7 +116,7 @@ html(lang='en') img(src="http://i.imgur.com/VxHJfAJ.png", alt="DataFox") li a(href="https://sixplus.com") - img(src="https://s3.amazonaws.com/bookalokal-assets/sixplus/sixplus-logo-horizontal-dark.png" alt="SixPlus") + img(src="https://s3.amazonaws.com/bookalokal-assets/sixplus/sixplus-logo-horizontal-dark.png", alt="SixPlus") p#footer Licensed under MIT. Copyright 2011 LearnBoost. script. document.body.className = 'load'; From 76f399e43a2e7d4d5b7d3c1f602557140159692c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Apr 2016 14:15:19 -0700 Subject: [PATCH 0509/2240] chore: now working on 4.4.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64fc3545b78..bb929162268 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.14", + "version": "4.4.15-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 6bcdb275f8282f0de3be2746b3a5992742aa43b3 Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Thu, 28 Apr 2016 11:47:36 -0700 Subject: [PATCH 0510/2240] apply plugins to schemas only once --- lib/schema.js | 3 +++ test/schema.test.js | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index d9edc3ba985..8904b788d16 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -81,6 +81,7 @@ function Schema(obj, options) { this._requiredpaths = undefined; this.discriminatorMapping = undefined; this._indexedpaths = undefined; + this._appliedPlugins = []; this.s = { hooks: new Kareem(), @@ -905,6 +906,8 @@ Schema.prototype.post = function(method, fn) { */ Schema.prototype.plugin = function(fn, opts) { + if (this._appliedPlugins.indexOf(fn) > -1) { return this; } + this._appliedPlugins.push(fn); fn(this, opts); return this; }; diff --git a/test/schema.test.js b/test/schema.test.js index acdc7b5ee62..78aae1e72a3 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -861,6 +861,22 @@ describe('schema', function() { assert.equal(true, called); done(); }); + + it('does not apply more than once', function(done) { + var Tobi = new Schema, + called = 0; + + var plugin = function(schema) { + assert.equal(schema, Tobi); + called += 1; + }; + + Tobi.plugin(plugin); + Tobi.plugin(plugin); + + assert.equal(1, called); + done(); + }); }); describe('options', function() { From 84def0f6fec1e41509f62eedcabc9c30b7a32d98 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Apr 2016 11:53:18 -0700 Subject: [PATCH 0511/2240] test(document): repro #4094 --- test/document.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index cfb36e10c39..d99b8fcb9b6 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2623,7 +2623,20 @@ describe('document', function() { assert.ifError(error); done(); }); + }); + it('skip validation if required returns false (gh-4094)', function(done) { + var schema = new Schema({ + div: { + type: Number, + required: function() { return false; }, + validate: function(v) { return !!v; } + } + }); + var Model = db.model('gh4094', schema); + var m = new Model(); + assert.ifError(m.validateSync()); + done(); }); }); }); From 423dc8f567e21e50e14a16d2f77a7f5387b543cc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Apr 2016 11:53:28 -0700 Subject: [PATCH 0512/2240] fix(document): treat required fn that returns false as required: false Fix #4094 --- lib/document.js | 8 ++++++++ lib/schematype.js | 1 + 2 files changed, 9 insertions(+) diff --git a/lib/document.js b/lib/document.js index f2f5c026133..814ff360f40 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1145,6 +1145,10 @@ Document.prototype.$__validate = function(callback) { if (!_this.isSelected(path) && !_this.isModified(path)) { return false; } + var p = _this.schema.path(path); + if (typeof p.originalRequiredValue === 'function') { + return p.originalRequiredValue.call(this); + } return true; }); @@ -1254,6 +1258,10 @@ Document.prototype.validateSync = function(pathsToValidate) { if (!_this.isSelected(path) && !_this.isModified(path)) { return false; } + var p = _this.schema.path(path); + if (typeof p.originalRequiredValue === 'function') { + return p.originalRequiredValue.call(this); + } return true; }); diff --git a/lib/schematype.js b/lib/schematype.js index f3e9148140e..099b101dab7 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -546,6 +546,7 @@ SchemaType.prototype.required = function(required, message) { return ((typeof required === 'function') && !required.apply(this)) || _this.checkRequired(v, this); }; + this.originalRequiredValue = required; if (typeof required === 'string') { message = required; From df56f2f4c836a2f42fdff70e81b7db12057535ff Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Apr 2016 12:27:02 -0700 Subject: [PATCH 0513/2240] fix(connection): emit on error if listeners and no callback Fix #4098 --- lib/connection.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index f1274aa06df..34fc434a937 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -284,6 +284,9 @@ Connection.prototype.open = function(host, database, port, options, callback) { callback && callback(error); if (error) { reject(error); + if (!callback && _this.listeners('error').length) { + _this.emit('error', error); + } return; } resolve(); @@ -418,6 +421,9 @@ Connection.prototype.openSet = function(uris, database, options, callback) { callback && callback(error); if (error) { reject(error); + if (!callback && _this.listeners('error').length) { + _this.emit('error', error); + } return; } resolve(); @@ -490,13 +496,7 @@ Connection.prototype.onOpen = function(callback) { function open(err, isAuth) { if (err) { _this.readyState = isAuth ? STATES.unauthorized : STATES.disconnected; - if (_this._hasOpened) { - if (callback) { - callback(err); - } - } else { - _this.error(err, callback); - } + _this.error(err, callback); return; } From 9dc540418338ce63eca44d083f3e28a07265486d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Apr 2016 10:46:29 -0700 Subject: [PATCH 0514/2240] test(model): repro #4099 --- test/model.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index ac735de97b3..fd5d96dfffb 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5213,6 +5213,8 @@ describe('Model', function() { Movie.insertMany(arr, function(error, docs) { assert.ifError(error); assert.equal(docs.length, 2); + assert.ok(!docs[0].isNew); + assert.ok(!docs[1].isNew); Movie.find({}, function(error, docs) { assert.ifError(error); assert.equal(docs.length, 2); From 5ad5817e7f683dda9b32ea696c54f760973df7d3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Apr 2016 10:46:51 -0700 Subject: [PATCH 0515/2240] fix(model): ensure isNew set to false after insertMany Fix #4099 --- lib/model.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/model.js b/lib/model.js index 5d2d11128f7..a9d820ac95f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1856,6 +1856,10 @@ Model.insertMany = function(arr, callback) { callback && callback(error); return; } + for (var i = 0; i < docs.length; ++i) { + docs[i].isNew = false; + docs[i].emit('isNew', false); + } resolve(docs); callback && callback(null, docs); }); From 94e06a00b4160307c065d400c462654f49d7ab0d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Apr 2016 11:02:36 -0700 Subject: [PATCH 0516/2240] test(aggregate): repro #4101 --- test/aggregate.test.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 6d7b9ec4fcc..091ef6a3fae 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -622,14 +622,21 @@ describe('aggregate: ', function() { var MyModel = db.model('gh3160', {name: String}); - MyModel. - aggregate([{$match: {name: 'test'}}]). - cursor({async: true}). - exec(function(error, cursor) { - assert.ifError(error); - assert.ok(cursor); - db.close(done); - }); + MyModel.create({ name: 'test' }, function(error) { + assert.ifError(error); + MyModel. + aggregate([{$match: {name: 'test'}}, {$project:{name:'$name'}}]). + allowDiskUse(true). + cursor({ batchSize: 2500, async: true }). + exec(function(error, cursor) { + assert.ifError(error); + assert.ok(cursor); + cursor.toArray(function(error) { + assert.ifError(error); + db.close(done); + }); + }); + }); }); it('cursor() without options (gh-3855)', function(done) { From 44cfd474ca03b4070358c6258e0a7f1d8a042c77 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Apr 2016 11:02:49 -0700 Subject: [PATCH 0517/2240] fix(aggregate): dont send async option to server Fix #4101 --- lib/aggregate.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index fd2c2fcf71b..8ff1e79e765 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -496,22 +496,24 @@ Aggregate.prototype.exec = function(callback) { } var _this = this; var Promise = PromiseProvider.get(); + var options = utils.clone(this.options); - if (this.options && this.options.cursor) { - if (this.options.cursor.async) { + if (options && options.cursor) { + if (options.cursor.async) { + delete options.cursor.async; return new Promise.ES6(function(resolve) { if (!_this._model.collection.buffer) { process.nextTick(function() { var cursor = _this._model.collection. - aggregate(_this._pipeline, _this.options || {}); + aggregate(_this._pipeline, options || {}); resolve(cursor); - callback && callback(cursor); + callback && callback(null, cursor); }); return; } _this._model.collection.emitter.once('queue', function() { var cursor = _this._model.collection. - aggregate(_this._pipeline, _this.options || {}); + aggregate(_this._pipeline, options || {}); resolve(cursor); callback && callback(null, cursor); }); From 91c3eacb93800a05ce63624ec0a03fcfec21cf6e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Apr 2016 11:34:32 -0700 Subject: [PATCH 0518/2240] test(populate): repro #4104 --- test/model.populate.test.js | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 6cde9146943..13772d5f5c5 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3668,5 +3668,44 @@ describe('model: populate:', function() { done ); }); + + it('dynref bug (gh-4104)', function(done) { + var PersonSchema = new Schema({ + name: { type: String } + }); + + var AnimalSchema = new Schema({ + name: { type: String } + }); + + var ThingSchema = new Schema({ + createdByModel: { type: String }, + createdBy: { + type: mongoose.Schema.Types.ObjectId, refPath: 'createdByModel' + } + }); + + var Thing = db.model('Thing4104', ThingSchema); + var Person = db.model('Person4104', PersonSchema); + var Animal = db.model('Animal4104', AnimalSchema); + + Person.create({ name: 'Val' }, function(error, person) { + assert.ifError(error); + Animal.create({ name: 'Air Bud' }, function(error, animal) { + assert.ifError(error); + var obj1 = { createdByModel: 'Person4104', createdBy: person._id }; + var obj2 = { createdByModel: 'Animal4104', createdBy: animal._id }; + Thing.create(obj1, obj2, function(error) { + assert.ifError(error); + Thing.find({}).populate('createdBy').exec(function(error, things) { + assert.ifError(error); + assert.ok(things[0].createdBy.name); + assert.ok(things[1].createdBy.name); + done(); + }); + }); + }); + }); + }); }); }); From e3271381673789826c9c9aecc4881a9a6c7bf618 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Apr 2016 11:34:48 -0700 Subject: [PATCH 0519/2240] fix(populate): assign values when resolving each populate Fix #4104 --- lib/model.js | 71 ++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/lib/model.js b/lib/model.js index a9d820ac95f..764dd4cc43e 100644 --- a/lib/model.js +++ b/lib/model.js @@ -13,7 +13,6 @@ var utils = require('./utils'); var hasOwnProperty = utils.object.hasOwnProperty; var isMongooseObject = utils.isMongooseObject; var EventEmitter = require('events').EventEmitter; -var Promise = require('./promise'); var util = require('util'); var tick = utils.tick; @@ -2593,39 +2592,7 @@ function populate(model, docs, options, cb) { modelsMap = getModelsMapForPopulate(model, docs, options); var i, len = modelsMap.length, - mod, match, select, promise, vals = []; - - promise = new Promise(function(err, vals, mod, assignmentOpts) { - if (err) return cb(err); - - var options = mod.options; - var lean = options.options && options.options.lean, - len = vals.length, - rawOrder = {}, rawDocs = {}, key, val; - - // optimization: - // record the document positions as returned by - // the query result. - for (var i = 0; i < len; i++) { - val = vals[i]; - key = String(utils.getValue('_id', val)); - rawDocs[key] = val; - rawOrder[key] = i; - - // flag each as result of population - if (!lean) val.$__.wasPopulated = true; - } - - assignVals({ - rawIds: mod.ids, - rawDocs: rawDocs, - rawOrder: rawOrder, - docs: mod.docs, - path: options.path, - options: assignmentOpts - }); - cb(); - }); + mod, match, select, vals = []; function flatten(item) { // no need to include undefined values in our query @@ -2687,12 +2654,44 @@ function populate(model, docs, options, cb) { } function next(options, assignmentOpts, err, valsFromDb) { - if (err) return promise.resolve(err); + if (err) return cb(err); vals = vals.concat(valsFromDb); + _assign(null, vals, options, assignmentOpts); if (--_remaining === 0) { - promise.resolve(err, vals, options, assignmentOpts); + cb(); } } + + function _assign(err, vals, mod, assignmentOpts) { + if (err) return cb(err); + + var options = mod.options; + var lean = options.options && options.options.lean, + len = vals.length, + rawOrder = {}, rawDocs = {}, key, val; + + // optimization: + // record the document positions as returned by + // the query result. + for (var i = 0; i < len; i++) { + val = vals[i]; + key = String(utils.getValue('_id', val)); + rawDocs[key] = val; + rawOrder[key] = i; + + // flag each as result of population + if (!lean) val.$__.wasPopulated = true; + } + + assignVals({ + rawIds: mod.ids, + rawDocs: rawDocs, + rawOrder: rawOrder, + docs: mod.docs, + path: options.path, + options: assignmentOpts + }); + } } function getModelsMapForPopulate(model, docs, options) { From dcbfcb41c7274df138e2772d7c2eef43994bd53f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Apr 2016 10:24:34 -0700 Subject: [PATCH 0520/2240] docs: add waffle.io to home page --- index.jade | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.jade b/index.jade index 7d956fb6837..26bbc91b0f2 100644 --- a/index.jade +++ b/index.jade @@ -99,6 +99,9 @@ html(lang='en') li a(href="https://prezi.com/pa1ub5unrapt/trello-architecture-2013/") img(src="http://upload.wikimedia.org/wikipedia/en/3/3e/Trello_Logo.png", alt="Trello") + li + a(href="http://waffle.io", alt="Waffle.io") + img(src="https://waffle.io/resources/images/waffle-yellow-on-blue.png", alt="Waffle.io") li a(href="http://storify.com/", alt="Storify") img(src="docs/images/apps/h_storify.jpg", alt="Storify") From e2f94a4ba1bd734c1dd3be72b8a3f3a05bee4991 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 1 May 2016 13:22:22 -0700 Subject: [PATCH 0521/2240] refactor(connection): use separate var statements --- lib/connection.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 34fc434a937..f6feea3fd70 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -2,15 +2,15 @@ * Module dependencies. */ -var utils = require('./utils'), - EventEmitter = require('events').EventEmitter, - driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native', - Schema = require('./schema'), - Collection = require(driver + '/collection'), - STATES = require('./connectionstate'), - MongooseError = require('./error'), - muri = require('muri'), - PromiseProvider = require('./promise_provider'); +var utils = require('./utils'); +var EventEmitter = require('events').EventEmitter; +var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'; +var Schema = require('./schema'); +var Collection = require(driver + '/collection'); +var STATES = require('./connectionstate'); +var MongooseError = require('./error'); +var muri = require('muri'); +var PromiseProvider = require('./promise_provider'); /*! * Protocol prefix regexp. From 76ff26cceb51e760abb0ae4971ec378f1e8f3694 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 May 2016 07:52:41 -0700 Subject: [PATCH 0522/2240] test(schema): repro #4109 --- test/document.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index d99b8fcb9b6..bb5d47fa8f9 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2638,5 +2638,26 @@ describe('document', function() { assert.ifError(m.validateSync()); done(); }); + + it('ability to overwrite array default (gh-4109)', function(done) { + var schema = new Schema({ + names: { + type: [String], + default: void 0 + } + }); + + var Model = db.model('gh4109', schema); + var m = new Model(); + assert.ok(!m.names); + m.save(function(error, m) { + assert.ifError(error); + Model.collection.findOne({ _id: m._id }, function(error, doc) { + assert.ifError(error); + assert.ok(!('names' in doc)); + done(); + }); + }); + }); }); }); From 8e013c34246874b3813089921b3f9ea19172340b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 May 2016 07:53:00 -0700 Subject: [PATCH 0523/2240] fix(schema): support overwriting array default Fix #4109 --- lib/schema/array.js | 16 +++++++++------- lib/schema/documentarray.js | 16 +++++++++------- lib/schematype.js | 6 +++++- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index ee5055a56f4..68219d0d180 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -64,19 +64,21 @@ function SchemaArray(key, cast, options) { SchemaType.call(this, key, options, 'Array'); - var _this = this, - defaultArr, - fn; + var _this = this; + var defaultArr; + var fn; if (this.defaultValue) { defaultArr = this.defaultValue; fn = typeof defaultArr === 'function'; } - this.default(function() { - var arr = fn ? defaultArr() : defaultArr || []; - return new MongooseArray(arr, _this.path, this); - }); + if (!('defaultValue' in this) || this.defaultValue !== void 0) { + this.default(function() { + var arr = fn ? defaultArr() : defaultArr || []; + return new MongooseArray(arr, _this.path, this); + }); + } } /** diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 6dcdd2c1102..bbec55c5bf1 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -48,13 +48,15 @@ function DocumentArray(key, schema, options) { var path = this.path; var fn = this.defaultValue; - this.default(function() { - var arr = fn.call(this); - if (!Array.isArray(arr)) { - arr = [arr]; - } - return new MongooseDocumentArray(arr, path, this); - }); + if (!('defaultValue' in this) || fn !== void 0) { + this.default(function() { + var arr = fn.call(this); + if (!Array.isArray(arr)) { + arr = [arr]; + } + return new MongooseDocumentArray(arr, path, this); + }); + } } /** diff --git a/lib/schematype.js b/lib/schematype.js index 099b101dab7..8d4bc78696e 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -88,10 +88,14 @@ function SchemaType(path, options, instance) { SchemaType.prototype.default = function(val) { if (arguments.length === 1) { + if (val === void 0) { + this.defaultValue = void 0; + return void 0; + } this.defaultValue = typeof val === 'function' ? val : this.cast(val); - return this; + return this.defaultValue; } else if (arguments.length > 1) { this.defaultValue = utils.args(arguments); } From 0b128d272f558266e1daf784e54e6f1707c3907e Mon Sep 17 00:00:00 2001 From: Bertrand Marron Date: Mon, 2 May 2016 11:19:39 +0200 Subject: [PATCH 0524/2240] Add test for broken subdoc subprop enum validation --- test/schema.validation.test.js | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 1e3cd859524..3fc2ff2d67a 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -793,6 +793,41 @@ describe('schema', function() { }); }); + it('should validate subdocuments subproperty enums', function(done) { + var M = mongoose.model('M', new Schema({ + children: [{ + prop: { + val: {type: String, enum: ['valid']} + } + }] + })); + + var model = new M(); + var child = model.children.create(); + + child.prop = { + val: 'valid' + }; + + model.children.push(child); + + model.validate(function(error) { + assert.ifError(error); + + child.prop.val = 'invalid'; + + assert.equal(model.children[0].prop.val, 'invalid'); + + model.validate(function(error) { + assert.ok(error); + assert.equal(error.errors['children.0.prop.val'].message, + '`invalid` is not a valid enum value for path `prop.val`.'); + + done(); + }); + }); + }); + it('doesnt do double validation on document arrays (gh-2618)', function(done) { var A = new Schema({str: String}); var B = new Schema({a: [A]}); From e64f8cbb37b8a769b39c297494f6e65ddba2f6fe Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 May 2016 08:45:43 -0700 Subject: [PATCH 0525/2240] feat(query): basic query cursor function --- lib/query.js | 7 +++ lib/querycursor.js | 92 +++++++++++++++++++++++++++++++++++++++ lib/querystream.js | 4 +- test/query.cursor.test.js | 67 ++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 lib/querycursor.js create mode 100644 test/query.cursor.test.js diff --git a/lib/query.js b/lib/query.js index d1f1278f838..2b522fd54e8 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3,6 +3,7 @@ */ var PromiseProvider = require('./promise_provider'); +var QueryCursor = require('./querycursor'); var QueryStream = require('./querystream'); var StrictModeError = require('./error/strict'); var cast = require('./cast'); @@ -2771,6 +2772,12 @@ Query.prototype.stream = function stream(opts) { return new QueryStream(this, opts); }; +Query.prototype.cursor = function cursor(opts) { + this._applyPaths(); + this._fields = this._castFields(this._fields); + return new QueryCursor(this, opts); +}; + // the rest of these are basically to support older Mongoose syntax with mquery /** diff --git a/lib/querycursor.js b/lib/querycursor.js new file mode 100644 index 00000000000..e15bc3d025f --- /dev/null +++ b/lib/querycursor.js @@ -0,0 +1,92 @@ +var helpers = require('./queryhelpers'); +var Readable = require('stream').Readable; +var util = require('util'); + +function QueryCursor(query, options) { + Readable.call(this, { objectMode: true }); + + this.cursor = null; + this.query = query; + var _this = this; + var model = query.model; + model.collection.find(query._conditions, options, function(err, cursor) { + if (err) { + return _this.emit('error', err); + } + _this.cursor = cursor; + _this.emit('cursor', cursor); + }); +} + +util.inherits(QueryCursor, Readable); + +QueryCursor.prototype._read = function() { + var _this = this; + this.next(function(error, doc) { + if (error) { + return _this.emit('error', error); + } + if (!doc) { + _this.push(null); + return _this.cursor.close(function(error) { + if (error) { + return _this.emit('error', error); + } + _this.emit('close'); + }); + } + _this.push(doc); + }); +}; + +QueryCursor.prototype.next = function(cb) { + var _this = this; + if (this.cursor) { + this.cursor.next(function(error, doc) { + if (error) { + return cb(error); + } + if (!doc) { + return cb(null, null); + } + + var opts = _this.query._mongooseOptions; + if (!opts.populate) { + return _create(_this, doc, null, cb); + } + + var pop = helpers.preparePopulationOptionsMQ(_this.query, + _this.query._mongooseOptions); + pop.forEach(function(option) { + delete option.model; + }); + pop.__noPromise = true; + _this.query.model.populate(doc, pop, function(err, doc) { + if (err) { + return cb(err); + } + _create(_this, doc, pop, cb); + }); + }); + } else { + this.once('cursor', function() { + _this.next(cb); + }); + } +}; + +function _create(ctx, doc, populatedIds, cb) { + var instance = helpers.createModel(ctx.query.model, doc, ctx.query._fields); + var opts = populatedIds ? + {populated: populatedIds} : + undefined; + + instance.init(doc, opts, function(err) { + if (err) { + return cb(err); + } + cb(null, instance); + }); +} + +module.exports = QueryCursor; diff --git a/lib/querystream.js b/lib/querystream.js index 25bcb9ebea7..b0630e3723a 100644 --- a/lib/querystream.js +++ b/lib/querystream.js @@ -257,8 +257,8 @@ QueryStream.prototype._onNextObject = function _onNextObject(err, doc) { function createAndEmit(self, populatedIds, doc) { var instance = helpers.createModel(self.query.model, doc, self._fields); var opts = populatedIds ? - {populated: populatedIds} : - undefined; + {populated: populatedIds} : + undefined; instance.init(doc, opts, function(err) { if (err) { diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js new file mode 100644 index 00000000000..3eb2029514b --- /dev/null +++ b/test/query.cursor.test.js @@ -0,0 +1,67 @@ +/** + * Module dependencies. + */ + +var assert = require('assert'); +var start = require('./common'); + +var mongoose = start.mongoose; +var Schema = mongoose.Schema; + +describe('QueryCursor', function() { + var db; + var Model; + + before(function(done) { + db = start(); + + var schema = new Schema({ name: String }); + schema.virtual('test').get(function() { return 'test'; }); + + Model = db.model('gh1907_0', schema); + + Model.create({ name: 'Axl' }, { name: 'Slash' }, function(error) { + assert.ifError(error); + done(); + }); + }); + + after(function(done) { + db.close(done); + }); + + it('#next()', function(done) { + var cursor = Model.find().sort({ name: 1 }).cursor(); + cursor.next(function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Axl'); + assert.equal(doc.test, 'test'); + cursor.next(function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Slash'); + assert.equal(doc.test, 'test'); + done(); + }); + }); + }); + + it('as readable stream', function(done) { + var cursor = Model.find().sort({ name: 1 }).cursor(); + + var expectedNames = ['Axl', 'Slash']; + var cur = 0; + cursor.on('data', function(doc) { + assert.equal(doc.name, expectedNames[cur++]); + assert.equal(doc.test, 'test'); + }); + + cursor.on('error', function(error) { + done(error); + }); + + cursor.on('end', function() { + assert.equal(cur, 2); + done(); + }); + }); +}); From 65b328cebf578989fe0d411c30ae5be469351f0f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 May 2016 06:58:07 -0700 Subject: [PATCH 0526/2240] feat(querycursor): return promise from next --- lib/querycursor.js | 92 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 18 deletions(-) diff --git a/lib/querycursor.js b/lib/querycursor.js index e15bc3d025f..d278dacebcf 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -1,7 +1,26 @@ -var helpers = require('./queryhelpers'); +/*! + * Module dependencies. + */ + +var PromiseProvider = require('./promise_provider'); var Readable = require('stream').Readable; +var helpers = require('./queryhelpers'); var util = require('util'); +/** + * QueryCursor constructor. Do **not** instantiate this class directly, use + * `Query.prototype.cursor()` instead. + * + * @param {Query} query + * @param {Object} options query options passed to `.find()` + * @inherits Readable + * @event `cursor`: Emitted when the cursor is created + * @event `error`: Emitted when an error occurred + * @event `data`: Emitted when the stream is flowing and the next doc is ready + * @event `end`: Emitted when the stream is exhausted + * @api private + */ + function QueryCursor(query, options) { Readable.call(this, { objectMode: true }); @@ -20,9 +39,13 @@ function QueryCursor(query, options) { util.inherits(QueryCursor, Readable); +/*! + * Necessary to satisfy the Readable API + */ + QueryCursor.prototype._read = function() { var _this = this; - this.next(function(error, doc) { + _next(this, function(error, doc) { if (error) { return _this.emit('error', error); } @@ -39,46 +62,79 @@ QueryCursor.prototype._read = function() { }); }; -QueryCursor.prototype.next = function(cb) { +/** + * Get the next document from this cursor. Will return `null` when there are + * no documents left. + * + * @param {Function} callback + * @return {Promise} + * @api public + * @method next + */ + +QueryCursor.prototype.next = function(callback) { + var Promise = PromiseProvider.get(); var _this = this; - if (this.cursor) { - this.cursor.next(function(error, doc) { + return new Promise.ES6(function(resolve, reject) { + _next(_this, function(error, doc) { + if (error) { + callback && callback(error); + return reject(error); + } + callback && callback(null, doc); + resolve(doc); + }); + }); +}; + +/*! + * Get the next doc from the underlying cursor and mongooseify it + * (populate, etc.) + */ + +function _next(ctx, callback) { + if (ctx.cursor) { + ctx.cursor.next(function(error, doc) { if (error) { - return cb(error); + return callback(error); } if (!doc) { - return cb(null, null); + return callback(null, null); } - var opts = _this.query._mongooseOptions; + var opts = ctx.query._mongooseOptions; if (!opts.populate) { - return _create(_this, doc, null, cb); + return _create(ctx, doc, null, callback); } - var pop = helpers.preparePopulationOptionsMQ(_this.query, - _this.query._mongooseOptions); + var pop = helpers.preparePopulationOptionsMQ(ctx.query, + ctx.query._mongooseOptions); pop.forEach(function(option) { delete option.model; }); pop.__noPromise = true; - _this.query.model.populate(doc, pop, function(err, doc) { + ctx.query.model.populate(doc, pop, function(err, doc) { if (err) { - return cb(err); + return callback(err); } - _create(_this, doc, pop, cb); + _create(ctx, doc, pop, callback); }); }); } else { - this.once('cursor', function() { - _this.next(cb); + ctx.once('cursor', function() { + _next(ctx, callback); }); } -}; +} + +/*! + * Convert a raw doc into a full mongoose doc. + */ function _create(ctx, doc, populatedIds, cb) { var instance = helpers.createModel(ctx.query.model, doc, ctx.query._fields); var opts = populatedIds ? - {populated: populatedIds} : + { populated: populatedIds } : undefined; instance.init(doc, opts, function(err) { From a957cd5e63642a8e422a3f9ef778b2af9e30d496 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 May 2016 06:58:31 -0700 Subject: [PATCH 0527/2240] test(querycursor): cover promises and populate --- test/query.cursor.test.js | 77 +++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 8 deletions(-) diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index 3eb2029514b..ca7ba2a27c2 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -30,17 +30,78 @@ describe('QueryCursor', function() { db.close(done); }); - it('#next()', function(done) { - var cursor = Model.find().sort({ name: 1 }).cursor(); - cursor.next(function(error, doc) { - assert.ifError(error); - assert.equal(doc.name, 'Axl'); - assert.equal(doc.test, 'test'); + describe('#next()', function() { + it('with callbacks', function(done) { + var cursor = Model.find().sort({ name: 1 }).cursor(); cursor.next(function(error, doc) { assert.ifError(error); - assert.equal(doc.name, 'Slash'); + assert.equal(doc.name, 'Axl'); + assert.equal(doc.test, 'test'); + cursor.next(function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Slash'); + assert.equal(doc.test, 'test'); + done(); + }); + }); + }); + + it('with promises', function(done) { + var cursor = Model.find().sort({ name: 1 }).cursor(); + cursor.next().then(function(doc) { + assert.equal(doc.name, 'Axl'); assert.equal(doc.test, 'test'); - done(); + cursor.next().then(function(doc) { + assert.equal(doc.name, 'Slash'); + assert.equal(doc.test, 'test'); + done(); + }); + }); + }); + + it('with populate', function(done) { + var bandSchema = new Schema({ + name: String, + members: [{ type: mongoose.Schema.ObjectId, ref: 'Person1907' }] + }); + var personSchema = new Schema({ + name: String + }); + + var Person = db.model('Person1907', personSchema); + var Band = db.model('Band1907', bandSchema); + + var people = [ + { name: 'Axl Rose' }, + { name: 'Slash' }, + { name: 'Nikki Sixx' }, + { name: 'Vince Neil' } + ]; + Person.create(people, function(error, docs) { + assert.ifError(error); + var bands = [ + { name: 'Guns N\' Roses', members: [docs[0], docs[1]] }, + { name: 'Motley Crue', members: [docs[2], docs[3]] } + ]; + Band.create(bands, function(error) { + assert.ifError(error); + var cursor = + Band.find().sort({ name: 1 }).populate('members').cursor(); + cursor.next(function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Guns N\' Roses'); + assert.equal(doc.members.length, 2); + assert.equal(doc.members[0].name, 'Axl Rose'); + assert.equal(doc.members[1].name, 'Slash'); + cursor.next(function(error, doc) { + assert.equal(doc.name, 'Motley Crue'); + assert.equal(doc.members.length, 2); + assert.equal(doc.members[0].name, 'Nikki Sixx'); + assert.equal(doc.members[1].name, 'Vince Neil'); + done(); + }); + }); + }); }); }); }); From 429304f03fbf92f83170c5311b7162e6cb21ca77 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 May 2016 07:09:47 -0700 Subject: [PATCH 0528/2240] docs(query): coverage for .cursor() --- lib/query.js | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/query.js b/lib/query.js index 2b522fd54e8..09449520693 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2772,6 +2772,44 @@ Query.prototype.stream = function stream(opts) { return new QueryStream(this, opts); }; +/** + * Returns a wrapper around a [mongodb driver cursor](http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html). + * A QueryCursor exposes a [Streams3](https://strongloop.com/strongblog/whats-new-io-js-beta-streams3/)-compatible + * interface, as well as a `.next()` function. + * + * ####Example + * + * // There are 2 ways to use a cursor. First, as a stream: + * Thing. + * find({ name: /^hello/ }). + * cursor(). + * on('data', function(doc) { console.log(doc); }). + * on('end', function() { console.log('Done!'); }); + * + * // Or you can use `.next()` to manually get the next doc in the stream. + * // `.next()` returns a promise, so you can use promises or callbacks. + * var cursor = Thing.find({ name: /^hello/ }).cursor(); + * cursor.next(function(error, doc) { + * console.log(doc); + * }); + * + * // Because `.next()` returns a promise, you can use co + * // to easily iterate through all documents without loading them + * // all into memory. + * co(function*() { + * const cursor = Thing.find({ name: /^hello/ }).cursor(); + * for (let doc = yield cursor.next(); doc != null; doc = yield cursor.next()) { + * console.log(doc); + * } + * }); + * + * + * @return {QueryCursor} + * @param {Object} [options] + * @see QueryCursor + * @api public + */ + Query.prototype.cursor = function cursor(opts) { this._applyPaths(); this._fields = this._castFields(this._fields); From 94557653dba2cd9046f1b2ffab427cef4632a7c3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 May 2016 07:12:48 -0700 Subject: [PATCH 0529/2240] docs(query): deprecate `.stream()` --- lib/query.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/query.js b/lib/query.js index 09449520693..6ad14482c5a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2771,6 +2771,9 @@ Query.prototype.stream = function stream(opts) { this._fields = this._castFields(this._fields); return new QueryStream(this, opts); }; +Query.prototype.stream = util.deprecate(Query.prototype.stream, 'Mongoose: ' + + 'Query.prototype.stream() is deprecated in mongoose >= 4.5.0, ' + + 'use Query.prototype.cursor() instead'); /** * Returns a wrapper around a [mongodb driver cursor](http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html). From f42f6061ff75289eff4024eac311edaa45515f06 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 May 2016 07:42:57 -0700 Subject: [PATCH 0530/2240] fix(model): disallow setting discriminator key Fix #2041 --- lib/model.js | 8 +++++++- test/model.discriminator.test.js | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 35863867eb1..ac25198850c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -800,7 +800,13 @@ Model.discriminator = function discriminator(name, schema) { utils.merge(schema, baseSchema); var obj = {}; - obj[key] = {type: String, default: name}; + obj[key] = { + type: String, + default: name, + set: function() { + return name; + } + }; schema.add(obj); schema.discriminatorMapping = {key: key, value: name, isRoot: false}; diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 6536c5cee59..dd18340fbfb 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -338,6 +338,12 @@ describe('model', function() { assert.deepEqual(personOptions, employeeOptions); done(); }); + + it('does not allow setting discriminator key (gh-2041)', function(done) { + var doc = new Employee({ __t: 'fake' }); + assert.equal(doc.__t, 'model-discriminator-employee'); + done(); + }); }); }); }); From 522a2af455c816b1a8b35bccd9e41115b19aa52c Mon Sep 17 00:00:00 2001 From: Anthony Cheung Date: Thu, 5 May 2016 12:26:59 -0400 Subject: [PATCH 0531/2240] Updated QueryStream#destroy documentation. --- docs/2.7.x/docs/querystream.html | 2 +- docs/2.8.x/docs/querystream.html | 2 +- lib/querystream.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/2.7.x/docs/querystream.html b/docs/2.7.x/docs/querystream.html index c6784414848..03def90cfdb 100644 --- a/docs/2.7.x/docs/querystream.html +++ b/docs/2.7.x/docs/querystream.html @@ -301,7 +301,7 @@

QuerySteam#resume

QueryStream#destroy

-

Destroys the stream. No more events will be emitted after
calling this method.

+

Destroys the stream and emits the close event. No more events will be emitted after
the close event.

stream.destroy([err])
 
diff --git a/docs/2.8.x/docs/querystream.html b/docs/2.8.x/docs/querystream.html index c6784414848..03def90cfdb 100644 --- a/docs/2.8.x/docs/querystream.html +++ b/docs/2.8.x/docs/querystream.html @@ -301,7 +301,7 @@

QuerySteam#resume

QueryStream#destroy

-

Destroys the stream. No more events will be emitted after
calling this method.

+

Destroys the stream and emits the close event. No more events will be emitted after
the close event.

stream.destroy([err])
 
diff --git a/lib/querystream.js b/lib/querystream.js index 25bcb9ebea7..fd817079011 100644 --- a/lib/querystream.js +++ b/lib/querystream.js @@ -322,7 +322,7 @@ QueryStream.prototype.resume = function() { }; /** - * Destroys the stream, closing the underlying cursor. No more events will be emitted. + * Destroys the stream, closing the underlying cursor, which emits the close event. No more events will be emitted after the close event. * * @param {Error} [err] * @api public From 749520858c33c2852b496e7945dd5d6bc8a97e80 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 6 May 2016 09:51:16 -0700 Subject: [PATCH 0532/2240] Revert "Apply plugins to schemas only once" --- lib/schema.js | 3 --- test/schema.test.js | 16 ---------------- 2 files changed, 19 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 8904b788d16..d9edc3ba985 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -81,7 +81,6 @@ function Schema(obj, options) { this._requiredpaths = undefined; this.discriminatorMapping = undefined; this._indexedpaths = undefined; - this._appliedPlugins = []; this.s = { hooks: new Kareem(), @@ -906,8 +905,6 @@ Schema.prototype.post = function(method, fn) { */ Schema.prototype.plugin = function(fn, opts) { - if (this._appliedPlugins.indexOf(fn) > -1) { return this; } - this._appliedPlugins.push(fn); fn(this, opts); return this; }; diff --git a/test/schema.test.js b/test/schema.test.js index 78aae1e72a3..acdc7b5ee62 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -861,22 +861,6 @@ describe('schema', function() { assert.equal(true, called); done(); }); - - it('does not apply more than once', function(done) { - var Tobi = new Schema, - called = 0; - - var plugin = function(schema) { - assert.equal(schema, Tobi); - called += 1; - }; - - Tobi.plugin(plugin); - Tobi.plugin(plugin); - - assert.equal(1, called); - done(); - }); }); describe('options', function() { From 517442e402f9a14861ad81c5820346ce5db16d69 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 6 May 2016 09:55:25 -0700 Subject: [PATCH 0533/2240] chore: release 4.4.15 --- History.md | 9 + bin/mongoose.js | 508 ++++++++++++++++++++++++++++-------------------- package.json | 2 +- 3 files changed, 302 insertions(+), 217 deletions(-) diff --git a/History.md b/History.md index aaee07d7e7c..d183d31fc43 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.4.15 / 2016-05-06 +=================== + * fix(schema): support overwriting array default #4109 + * fix(populate): assign values when resolving each populate #4104 + * fix(aggregate): dont send async option to server #4101 + * fix(model): ensure isNew set to false after insertMany #4099 + * fix(connection): emit on error if listeners and no callback #4098 + * fix(document): treat required fn that returns false as required: false #4094 + 4.4.14 / 2016-04-27 =================== * fix: upgrade mongodb -> 2.1.18 #4102 diff --git a/bin/mongoose.js b/bin/mongoose.js index 77c158c8a6b..28d2f97fc8e 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -129,7 +129,7 @@ if (typeof window !== 'undefined') { } }).call(this,require("buffer").Buffer) -},{"./document_provider.js":6,"./error":12,"./schema":26,"./schematype.js":39,"./types":45,"./utils.js":48,"./virtualtype":49,"buffer":71}],3:[function(require,module,exports){ +},{"./document_provider.js":6,"./error":12,"./schema":26,"./schematype.js":41,"./types":47,"./utils.js":50,"./virtualtype":51,"buffer":73}],3:[function(require,module,exports){ /*! * Module dependencies. */ @@ -234,7 +234,7 @@ Document.prototype.constructor = Document; Document.ValidationError = ValidationError; module.exports = exports = Document; -},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":46,"./utils":48,"events":74}],4:[function(require,module,exports){ +},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":48,"./utils":50,"events":76}],4:[function(require,module,exports){ /*! * Module dependencies. */ @@ -440,7 +440,7 @@ function _cast(val, numbertype) { } } -},{"./schema/index":33,"./utils":48}],5:[function(require,module,exports){ +},{"./schema/index":33,"./utils":50}],5:[function(require,module,exports){ (function (process,Buffer){ /*! * Module dependencies. @@ -1589,6 +1589,10 @@ Document.prototype.$__validate = function(callback) { if (!_this.isSelected(path) && !_this.isModified(path)) { return false; } + var p = _this.schema.path(path); + if (typeof p.originalRequiredValue === 'function') { + return p.originalRequiredValue.call(this); + } return true; }); @@ -1698,6 +1702,10 @@ Document.prototype.validateSync = function(pathsToValidate) { if (!_this.isSelected(path) && !_this.isModified(path)) { return false; } + var p = _this.schema.path(path); + if (typeof p.originalRequiredValue === 'function') { + return p.originalRequiredValue.call(this); + } return true; }); @@ -2890,7 +2898,7 @@ Document.ValidationError = ValidationError; module.exports = exports = Document; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":39,"./types/array":41,"./types/documentarray":43,"./types/embedded":44,"./utils":48,"buffer":71,"events":74,"g5I+bs":94,"hooks-fixed":75,"util":98}],6:[function(require,module,exports){ +},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":41,"./types/array":43,"./types/documentarray":45,"./types/embedded":46,"./utils":50,"buffer":73,"events":76,"g5I+bs":96,"hooks-fixed":77,"util":100}],6:[function(require,module,exports){ 'use strict'; /* eslint-env browser */ @@ -2934,7 +2942,7 @@ var Binary = require('bson').Binary; module.exports = exports = Binary; -},{"bson":55}],9:[function(require,module,exports){ +},{"bson":57}],9:[function(require,module,exports){ /*! * Module exports. */ @@ -2959,7 +2967,7 @@ var ObjectId = require('bson').ObjectID; module.exports = exports = ObjectId; -},{"bson":55}],11:[function(require,module,exports){ +},{"bson":57}],11:[function(require,module,exports){ (function (global){ /*! * ignore @@ -3527,7 +3535,7 @@ function InternalCache() { this.fullPath = undefined; } -},{"./statemachine":40}],24:[function(require,module,exports){ +},{"./statemachine":42}],24:[function(require,module,exports){ /*! * Module dependencies */ @@ -3820,7 +3828,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject; module.exports = Promise; -},{"mpromise":82,"util":98}],25:[function(require,module,exports){ +},{"mpromise":84,"util":100}],25:[function(require,module,exports){ /*! * Module dependencies. */ @@ -3873,7 +3881,7 @@ Promise.reset = function() { module.exports = Promise; -},{"./ES6Promise":1,"./promise":24,"mquery":87}],26:[function(require,module,exports){ +},{"./ES6Promise":1,"./promise":24,"mquery":89}],26:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -5280,27 +5288,29 @@ Schema.Types = MongooseTypes = require('./schema/index'); exports.ObjectId = MongooseTypes.ObjectId; }).call(this,require("buffer").Buffer) -},{"./drivers":11,"./schema/index":33,"./utils":48,"./virtualtype":49,"async":51,"buffer":71,"events":74,"kareem":79}],27:[function(require,module,exports){ +},{"./drivers":11,"./schema/index":33,"./utils":50,"./virtualtype":51,"async":53,"buffer":73,"events":76,"kareem":81}],27:[function(require,module,exports){ /*! * Module dependencies. */ -var SchemaType = require('../schematype'), - CastError = SchemaType.CastError, - Types = { - Boolean: require('./boolean'), - Date: require('./date'), - Number: require('./number'), - String: require('./string'), - ObjectId: require('./objectid'), - Buffer: require('./buffer') - }, - MongooseArray = require('../types').Array, - EmbeddedDoc = require('../types').Embedded, - Mixed = require('./mixed'), - cast = require('../cast'), - utils = require('../utils'), - isMongooseObject = utils.isMongooseObject; +var SchemaType = require('../schematype'); +var CastError = SchemaType.CastError; +var Types = { + Boolean: require('./boolean'), + Date: require('./date'), + Number: require('./number'), + String: require('./string'), + ObjectId: require('./objectid'), + Buffer: require('./buffer') +}; +var MongooseArray = require('../types').Array; +var EmbeddedDoc = require('../types').Embedded; +var Mixed = require('./mixed'); +var cast = require('../cast'); +var utils = require('../utils'); +var isMongooseObject = utils.isMongooseObject; +var castToNumber = require('./operators/helpers').castToNumber; +var geospatial = require('./operators/geospatial'); /** * Array SchemaType constructor @@ -5345,19 +5355,21 @@ function SchemaArray(key, cast, options) { SchemaType.call(this, key, options, 'Array'); - var _this = this, - defaultArr, - fn; + var _this = this; + var defaultArr; + var fn; if (this.defaultValue) { defaultArr = this.defaultValue; fn = typeof defaultArr === 'function'; } - this.default(function() { - var arr = fn ? defaultArr() : defaultArr || []; - return new MongooseArray(arr, _this.path, this); - }); + if (!('defaultValue' in this) || this.defaultValue !== void 0) { + this.default(function() { + var arr = fn ? defaultArr() : defaultArr || []; + return new MongooseArray(arr, _this.path, this); + }); + } } /** @@ -5499,95 +5511,6 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { val; }; -/*! - * @ignore - * - * $atomic cast helpers - */ - -function castToNumber(val) { - return Types.Number.prototype.cast.call(this, val); -} - -function castArraysOfNumbers(arr, self) { - arr.forEach(function(v, i) { - if (Array.isArray(v)) { - castArraysOfNumbers(v, self); - } else { - arr[i] = castToNumber.call(self, v); - } - }); -} - -function cast$near(val) { - if (Array.isArray(val)) { - castArraysOfNumbers(val, this); - return val; - } - - if (val && val.$geometry) { - return cast$geometry(val, this); - } - - return SchemaArray.prototype.castForQuery.call(this, val); -} - -function cast$geometry(val, self) { - switch (val.$geometry.type) { - case 'Polygon': - case 'LineString': - case 'Point': - castArraysOfNumbers(val.$geometry.coordinates, self); - break; - default: - // ignore unknowns - break; - } - - if (val.$maxDistance) { - val.$maxDistance = castToNumber.call(self, val.$maxDistance); - } - - return val; -} - -function cast$within(val) { - var _this = this; - - if (val.$maxDistance) { - val.$maxDistance = castToNumber.call(_this, val.$maxDistance); - } - - if (val.$box || val.$polygon) { - var type = val.$box ? '$box' : '$polygon'; - val[type].forEach(function(arr) { - if (!Array.isArray(arr)) { - var msg = 'Invalid $within $box argument. ' - + 'Expected an array, received ' + arr; - throw new TypeError(msg); - } - arr.forEach(function(v, i) { - arr[i] = castToNumber.call(this, v); - }); - }); - } else if (val.$center || val.$centerSphere) { - type = val.$center ? '$center' : '$centerSphere'; - val[type].forEach(function(item, i) { - if (Array.isArray(item)) { - item.forEach(function(v, j) { - item[j] = castToNumber.call(this, v); - }); - } else { - val[type][i] = castToNumber.call(this, item); - } - }); - } else if (val.$geometry) { - cast$geometry(val, this); - } - - return val; -} - function cast$all(val) { if (!Array.isArray(val)) { val = [val]; @@ -5621,22 +5544,12 @@ function cast$elemMatch(val) { return cast(this.casterConstructor.schema, val); } -function cast$geoIntersects(val) { - var geo = val.$geometry; - if (!geo) { - return; - } - - cast$geometry(val, this); - return val; -} - var handle = SchemaArray.prototype.$conditionalHandlers = {}; handle.$all = cast$all; handle.$options = String; handle.$elemMatch = cast$elemMatch; -handle.$geoIntersects = cast$geoIntersects; +handle.$geoIntersects = geospatial.cast$geoIntersects; handle.$or = handle.$and = function(val) { if (!Array.isArray(val)) { throw new TypeError('conditional $or/$and require array'); @@ -5651,10 +5564,10 @@ handle.$or = handle.$and = function(val) { }; handle.$near = -handle.$nearSphere = cast$near; +handle.$nearSphere = geospatial.cast$near; handle.$within = -handle.$geoWithin = cast$within; +handle.$geoWithin = geospatial.cast$within; handle.$size = handle.$maxDistance = castToNumber; @@ -5675,7 +5588,7 @@ handle.$regex = SchemaArray.prototype.castForQuery; module.exports = SchemaArray; -},{"../cast":4,"../schematype":39,"../types":45,"../utils":48,"./boolean":28,"./buffer":29,"./date":30,"./mixed":34,"./number":35,"./objectid":36,"./string":38}],28:[function(require,module,exports){ +},{"../cast":4,"../schematype":41,"../types":47,"../utils":50,"./boolean":28,"./buffer":29,"./date":30,"./mixed":34,"./number":35,"./objectid":36,"./operators/geospatial":38,"./operators/helpers":39,"./string":40}],28:[function(require,module,exports){ /*! * Module dependencies. */ @@ -5780,7 +5693,7 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val) { module.exports = SchemaBoolean; -},{"../schematype":39,"../utils":48}],29:[function(require,module,exports){ +},{"../schematype":41,"../utils":50}],29:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -5972,7 +5885,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) { module.exports = SchemaBuffer; }).call(this,require("buffer").Buffer) -},{"../schematype":39,"../types":45,"../utils":48,"./../document":5,"./operators/bitwise":37,"buffer":71}],30:[function(require,module,exports){ +},{"../schematype":41,"../types":47,"../utils":50,"./../document":5,"./operators/bitwise":37,"buffer":73}],30:[function(require,module,exports){ /*! * Module requirements. */ @@ -6266,7 +6179,7 @@ SchemaDate.prototype.castForQuery = function($conditional, val) { module.exports = SchemaDate; -},{"../error":12,"../schematype":39,"../utils":48}],31:[function(require,module,exports){ +},{"../error":12,"../schematype":41,"../utils":50}],31:[function(require,module,exports){ /* eslint no-empty: 1 */ /*! @@ -6317,13 +6230,15 @@ function DocumentArray(key, schema, options) { var path = this.path; var fn = this.defaultValue; - this.default(function() { - var arr = fn.call(this); - if (!Array.isArray(arr)) { - arr = [arr]; - } - return new MongooseDocumentArray(arr, path, this); - }); + if (!('defaultValue' in this) || fn !== void 0) { + this.default(function() { + var arr = fn.call(this); + if (!Array.isArray(arr)) { + arr = [arr]; + } + return new MongooseDocumentArray(arr, path, this); + }); + } } /** @@ -6558,9 +6473,17 @@ function scopePaths(array, fields, init) { module.exports = DocumentArray; -},{"../error/cast":13,"../schematype":39,"../types/documentarray":43,"../types/embedded":44,"./array":27}],32:[function(require,module,exports){ +},{"../error/cast":13,"../schematype":41,"../types/documentarray":45,"../types/embedded":46,"./array":27}],32:[function(require,module,exports){ +'use strict'; + +/*! + * Module dependencies. + */ + var SchemaType = require('../schematype'); var Subdocument = require('../types/subdocument'); +var castToNumber = require('./operators/helpers').castToNumber; +var geospatial = require('./operators/geospatial'); module.exports = Embedded; @@ -6622,6 +6545,21 @@ Embedded.prototype.$conditionalHandlers.$geoWithin = function(val) { return { $geometry: this.castForQuery(val.$geometry) }; }; +/*! + * ignore + */ + +Embedded.prototype.$conditionalHandlers.$near = +Embedded.prototype.$conditionalHandlers.$nearSphere = geospatial.cast$near; + +Embedded.prototype.$conditionalHandlers.$within = +Embedded.prototype.$conditionalHandlers.$geoWithin = geospatial.cast$within; + +Embedded.prototype.$conditionalHandlers.$geoIntersects = + geospatial.cast$geoIntersects; + +Embedded.prototype.$conditionalHandlers.$maxDistance = castToNumber; + /** * Casts contents * @@ -6698,7 +6636,7 @@ Embedded.prototype.doValidateSync = function(value) { return value.validateSync(); }; -},{"../schematype":39,"../types/subdocument":47}],33:[function(require,module,exports){ +},{"../schematype":41,"../types/subdocument":49,"./operators/geospatial":38,"./operators/helpers":39}],33:[function(require,module,exports){ /*! * Module exports. @@ -6730,7 +6668,7 @@ exports.Oid = exports.ObjectId; exports.Object = exports.Mixed; exports.Bool = exports.Boolean; -},{"./array":27,"./boolean":28,"./buffer":29,"./date":30,"./documentarray":31,"./embedded":32,"./mixed":34,"./number":35,"./objectid":36,"./string":38}],34:[function(require,module,exports){ +},{"./array":27,"./boolean":28,"./buffer":29,"./date":30,"./documentarray":31,"./embedded":32,"./mixed":34,"./number":35,"./objectid":36,"./string":40}],34:[function(require,module,exports){ /*! * Module dependencies. */ @@ -6812,7 +6750,7 @@ Mixed.prototype.castForQuery = function($cond, val) { module.exports = Mixed; -},{"../schematype":39,"../utils":48}],35:[function(require,module,exports){ +},{"../schematype":41,"../utils":50}],35:[function(require,module,exports){ (function (Buffer){ /*! * Module requirements. @@ -7106,7 +7044,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val) { module.exports = SchemaNumber; }).call(this,require("buffer").Buffer) -},{"../error":12,"../schematype":39,"../utils":48,"./../document":5,"./operators/bitwise":37,"buffer":71}],36:[function(require,module,exports){ +},{"../error":12,"../schematype":41,"../utils":50,"./../document":5,"./operators/bitwise":37,"buffer":73}],36:[function(require,module,exports){ (function (Buffer){ /* eslint no-empty: 1 */ @@ -7317,7 +7255,7 @@ function resetId(v) { module.exports = ObjectId; }).call(this,require("buffer").Buffer) -},{"../schematype":39,"../types/objectid":46,"../utils":48,"./../document":5,"buffer":71}],37:[function(require,module,exports){ +},{"../schematype":41,"../types/objectid":48,"../utils":50,"./../document":5,"buffer":73}],37:[function(require,module,exports){ (function (Buffer){ /*! * Module requirements. @@ -7357,7 +7295,140 @@ function _castNumber(path, num) { module.exports = handleBitwiseOperator; }).call(this,require("buffer").Buffer) -},{"../../error/cast":13,"buffer":71}],38:[function(require,module,exports){ +},{"../../error/cast":13,"buffer":73}],38:[function(require,module,exports){ +/*! + * Module requirements. + */ + +var castArraysOfNumbers = require('./helpers').castArraysOfNumbers; +var castToNumber = require('./helpers').castToNumber; + +/*! + * ignore + */ + +exports.cast$geoIntersects = cast$geoIntersects; +exports.cast$near = cast$near; +exports.cast$within = cast$within; + +function cast$near(val) { + var SchemaArray = require('../array'); + + if (Array.isArray(val)) { + castArraysOfNumbers(val, this); + return val; + } + + if (val && val.$geometry) { + return cast$geometry(val, this); + } + + return SchemaArray.prototype.castForQuery.call(this, val); +} + +function cast$geometry(val, self) { + switch (val.$geometry.type) { + case 'Polygon': + case 'LineString': + case 'Point': + castArraysOfNumbers(val.$geometry.coordinates, self); + break; + default: + // ignore unknowns + break; + } + + if (val.$maxDistance) { + val.$maxDistance = castToNumber.call(self, val.$maxDistance); + } + + return val; +} + +function cast$within(val) { + var _this = this; + + if (val.$maxDistance) { + val.$maxDistance = castToNumber.call(_this, val.$maxDistance); + } + + if (val.$box || val.$polygon) { + var type = val.$box ? '$box' : '$polygon'; + val[type].forEach(function(arr) { + if (!Array.isArray(arr)) { + var msg = 'Invalid $within $box argument. ' + + 'Expected an array, received ' + arr; + throw new TypeError(msg); + } + arr.forEach(function(v, i) { + arr[i] = castToNumber.call(this, v); + }); + }); + } else if (val.$center || val.$centerSphere) { + type = val.$center ? '$center' : '$centerSphere'; + val[type].forEach(function(item, i) { + if (Array.isArray(item)) { + item.forEach(function(v, j) { + item[j] = castToNumber.call(this, v); + }); + } else { + val[type][i] = castToNumber.call(this, item); + } + }); + } else if (val.$geometry) { + cast$geometry(val, this); + } + + return val; +} + +function cast$geoIntersects(val) { + var geo = val.$geometry; + if (!geo) { + return; + } + + cast$geometry(val, this); + return val; +} + +},{"../array":27,"./helpers":39}],39:[function(require,module,exports){ +'use strict'; + +/*! + * Module requirements. + */ + +var Types = { + Number: require('../number') +}; + +/*! + * @ignore + */ + +exports.castToNumber = castToNumber; +exports.castArraysOfNumbers = castArraysOfNumbers; + +/*! + * @ignore + */ + +function castToNumber(val) { + return Types.Number.prototype.cast.call(this, val); +} + +function castArraysOfNumbers(arr, self) { + arr.forEach(function(v, i) { + if (Array.isArray(v)) { + castArraysOfNumbers(v, self); + } else { + arr[i] = castToNumber.call(self, v); + } + }); +} + +},{"../number":35}],40:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -7867,7 +7938,7 @@ SchemaString.prototype.castForQuery = function($conditional, val) { module.exports = SchemaString; }).call(this,require("buffer").Buffer) -},{"../error":12,"../schematype":39,"../utils":48,"./../document":5,"buffer":71}],39:[function(require,module,exports){ +},{"../error":12,"../schematype":41,"../utils":50,"./../document":5,"buffer":73}],41:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -7959,10 +8030,14 @@ function SchemaType(path, options, instance) { SchemaType.prototype.default = function(val) { if (arguments.length === 1) { + if (val === void 0) { + this.defaultValue = void 0; + return void 0; + } this.defaultValue = typeof val === 'function' ? val : this.cast(val); - return this; + return this.defaultValue; } else if (arguments.length > 1) { this.defaultValue = utils.args(arguments); } @@ -8417,6 +8492,7 @@ SchemaType.prototype.required = function(required, message) { return ((typeof required === 'function') && !required.apply(this)) || _this.checkRequired(v, this); }; + this.originalRequiredValue = required; if (typeof required === 'string') { message = required; @@ -8773,7 +8849,7 @@ exports.CastError = CastError; exports.ValidatorError = ValidatorError; }).call(this,require("buffer").Buffer) -},{"./error":12,"./utils":48,"buffer":71}],40:[function(require,module,exports){ +},{"./error":12,"./utils":50,"buffer":73}],42:[function(require,module,exports){ /*! * Module dependencies. @@ -8953,7 +9029,7 @@ StateMachine.prototype.map = function map() { return this.map.apply(this, arguments); }; -},{"./utils":48}],41:[function(require,module,exports){ +},{"./utils":50}],43:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -9745,7 +9821,7 @@ MongooseArray.mixin.remove = MongooseArray.mixin.pull; module.exports = exports = MongooseArray; }).call(this,require("buffer").Buffer) -},{"../document":5,"../utils":48,"./embedded":44,"./objectid":46,"buffer":71}],42:[function(require,module,exports){ +},{"../document":5,"../utils":50,"./embedded":46,"./objectid":48,"buffer":73}],44:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -10022,7 +10098,7 @@ MongooseBuffer.Binary = Binary; module.exports = MongooseBuffer; }).call(this,require("buffer").Buffer) -},{"../drivers":11,"../utils":48,"buffer":71}],43:[function(require,module,exports){ +},{"../drivers":11,"../utils":50,"buffer":73}],45:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -10271,7 +10347,7 @@ MongooseDocumentArray.mixin = { module.exports = MongooseDocumentArray; }).call(this,require("buffer").Buffer) -},{"../document":5,"../schema/objectid":36,"../utils":48,"./array":41,"./objectid":46,"buffer":71}],44:[function(require,module,exports){ +},{"../document":5,"../schema/objectid":36,"../utils":50,"./array":43,"./objectid":48,"buffer":73}],46:[function(require,module,exports){ /* eslint no-func-assign: 1 */ /*! @@ -10593,7 +10669,7 @@ EmbeddedDocument.prototype.parentArray = function() { module.exports = EmbeddedDocument; -},{"../document_provider":6,"../promise_provider":25}],45:[function(require,module,exports){ +},{"../document_provider":6,"../promise_provider":25}],47:[function(require,module,exports){ /*! * Module exports. @@ -10610,7 +10686,7 @@ exports.ObjectId = require('./objectid'); exports.Subdocument = require('./subdocument'); -},{"./array":41,"./buffer":42,"./documentarray":43,"./embedded":44,"./objectid":46,"./subdocument":47}],46:[function(require,module,exports){ +},{"./array":43,"./buffer":44,"./documentarray":45,"./embedded":46,"./objectid":48,"./subdocument":49}],48:[function(require,module,exports){ /** * ObjectId type constructor * @@ -10625,7 +10701,7 @@ var ObjectId = require('../drivers').ObjectId; module.exports = ObjectId; -},{"../drivers":11}],47:[function(require,module,exports){ +},{"../drivers":11}],49:[function(require,module,exports){ var Document = require('../document'); var PromiseProvider = require('../promise_provider'); @@ -10751,7 +10827,7 @@ function registerRemoveListener(sub) { owner.on('remove', emitRemove); } -},{"../document":5,"../promise_provider":25}],48:[function(require,module,exports){ +},{"../document":5,"../promise_provider":25}],50:[function(require,module,exports){ (function (process,Buffer){ /*! * Module dependencies. @@ -11601,7 +11677,7 @@ exports.each = function(arr, fn) { }; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./document":5,"./types":45,"./types/objectid":46,"buffer":71,"g5I+bs":94,"mpath":80,"ms":93,"regexp-clone":95,"sliced":96}],49:[function(require,module,exports){ +},{"./document":5,"./types":47,"./types/objectid":48,"buffer":73,"g5I+bs":96,"mpath":82,"ms":95,"regexp-clone":97,"sliced":98}],51:[function(require,module,exports){ /** * VirtualType constructor @@ -11706,7 +11782,7 @@ VirtualType.prototype.applySetters = function(value, scope) { module.exports = VirtualType; -},{}],50:[function(require,module,exports){ +},{}],52:[function(require,module,exports){ // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! @@ -12068,7 +12144,7 @@ var objectKeys = Object.keys || function (obj) { return keys; }; -},{"util/":98}],51:[function(require,module,exports){ +},{"util/":100}],53:[function(require,module,exports){ (function (process,global){ /*! * async @@ -13337,7 +13413,7 @@ var objectKeys = Object.keys || function (obj) { }()); }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"g5I+bs":94}],52:[function(require,module,exports){ +},{"g5I+bs":96}],54:[function(require,module,exports){ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; ;(function (exports) { @@ -13459,7 +13535,7 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; exports.fromByteArray = uint8ToBase64 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) -},{}],53:[function(require,module,exports){ +},{}],55:[function(require,module,exports){ (function (global){ /** * Module dependencies. @@ -13810,7 +13886,7 @@ module.exports = Binary; module.exports.Binary = Binary; }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"buffer":71}],54:[function(require,module,exports){ +},{"buffer":73}],56:[function(require,module,exports){ (function (process){ /** * Binary Parser. @@ -14199,7 +14275,7 @@ BinaryParser.Buffer = BinaryParserBuffer; exports.BinaryParser = BinaryParser; }).call(this,require("g5I+bs")) -},{"g5I+bs":94,"util":98}],55:[function(require,module,exports){ +},{"g5I+bs":96,"util":100}],57:[function(require,module,exports){ (function (Buffer){ // "use strict" @@ -14526,7 +14602,7 @@ module.exports.MaxKey = MaxKey; module.exports.BSONRegExp = BSONRegExp; }).call(this,require("buffer").Buffer) -},{"./binary":53,"./code":56,"./db_ref":57,"./double":58,"./float_parser":59,"./long":60,"./map":61,"./max_key":62,"./min_key":63,"./objectid":64,"./parser/calculate_size":65,"./parser/deserializer":66,"./parser/serializer":67,"./regexp":68,"./symbol":69,"./timestamp":70,"buffer":71}],56:[function(require,module,exports){ +},{"./binary":55,"./code":58,"./db_ref":59,"./double":60,"./float_parser":61,"./long":62,"./map":63,"./max_key":64,"./min_key":65,"./objectid":66,"./parser/calculate_size":67,"./parser/deserializer":68,"./parser/serializer":69,"./regexp":70,"./symbol":71,"./timestamp":72,"buffer":73}],58:[function(require,module,exports){ /** * A class representation of the BSON Code type. * @@ -14551,7 +14627,7 @@ Code.prototype.toJSON = function() { module.exports = Code; module.exports.Code = Code; -},{}],57:[function(require,module,exports){ +},{}],59:[function(require,module,exports){ /** * A class representation of the BSON DBRef type. * @@ -14584,7 +14660,7 @@ DBRef.prototype.toJSON = function() { module.exports = DBRef; module.exports.DBRef = DBRef; -},{}],58:[function(require,module,exports){ +},{}],60:[function(require,module,exports){ /** * A class representation of the BSON Double type. * @@ -14618,7 +14694,7 @@ Double.prototype.toJSON = function() { module.exports = Double; module.exports.Double = Double; -},{}],59:[function(require,module,exports){ +},{}],61:[function(require,module,exports){ // Copyright (c) 2008, Fair Oaks Labs, Inc. // All rights reserved. // @@ -14740,7 +14816,7 @@ var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) { exports.readIEEE754 = readIEEE754; exports.writeIEEE754 = writeIEEE754; -},{}],60:[function(require,module,exports){ +},{}],62:[function(require,module,exports){ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15597,7 +15673,7 @@ Long.TWO_PWR_24_ = Long.fromInt(1 << 24); */ module.exports = Long; module.exports.Long = Long; -},{}],61:[function(require,module,exports){ +},{}],63:[function(require,module,exports){ (function (global){ "use strict" @@ -15726,7 +15802,7 @@ if(typeof global.Map !== 'undefined') { module.exports.Map = Map; } }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],62:[function(require,module,exports){ +},{}],64:[function(require,module,exports){ /** * A class representation of the BSON MaxKey type. * @@ -15741,7 +15817,7 @@ function MaxKey() { module.exports = MaxKey; module.exports.MaxKey = MaxKey; -},{}],63:[function(require,module,exports){ +},{}],65:[function(require,module,exports){ /** * A class representation of the BSON MinKey type. * @@ -15756,7 +15832,7 @@ function MinKey() { module.exports = MinKey; module.exports.MinKey = MinKey; -},{}],64:[function(require,module,exports){ +},{}],66:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -16046,7 +16122,7 @@ module.exports.ObjectID = ObjectID; module.exports.ObjectId = ObjectID; }).call(this,require("g5I+bs")) -},{"./binary_parser":54,"g5I+bs":94}],65:[function(require,module,exports){ +},{"./binary_parser":56,"g5I+bs":96}],67:[function(require,module,exports){ (function (Buffer){ "use strict" @@ -16360,7 +16436,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down t module.exports = calculateObjectSize; }).call(this,require("buffer").Buffer) -},{"../binary":53,"../code":56,"../db_ref":57,"../double":58,"../float_parser":59,"../long":60,"../max_key":62,"../min_key":63,"../objectid":64,"../regexp":68,"../symbol":69,"../timestamp":70,"buffer":71}],66:[function(require,module,exports){ +},{"../binary":55,"../code":58,"../db_ref":59,"../double":60,"../float_parser":61,"../long":62,"../max_key":64,"../min_key":65,"../objectid":66,"../regexp":70,"../symbol":71,"../timestamp":72,"buffer":73}],68:[function(require,module,exports){ "use strict" var readIEEE754 = require('../float_parser').readIEEE754, @@ -16893,7 +16969,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down t module.exports = deserialize -},{"../binary":53,"../code":56,"../db_ref":57,"../double":58,"../float_parser":59,"../long":60,"../max_key":62,"../min_key":63,"../objectid":64,"../regexp":68,"../symbol":69,"../timestamp":70,"util":98}],67:[function(require,module,exports){ +},{"../binary":55,"../code":58,"../db_ref":59,"../double":60,"../float_parser":61,"../long":62,"../max_key":64,"../min_key":65,"../objectid":66,"../regexp":70,"../symbol":71,"../timestamp":72,"util":100}],69:[function(require,module,exports){ (function (Buffer){ "use strict" @@ -17809,7 +17885,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down t module.exports = serializeInto; }).call(this,require("buffer").Buffer) -},{"../binary":53,"../code":56,"../db_ref":57,"../double":58,"../float_parser":59,"../long":60,"../map":61,"../max_key":62,"../min_key":63,"../objectid":64,"../regexp":68,"../symbol":69,"../timestamp":70,"buffer":71}],68:[function(require,module,exports){ +},{"../binary":55,"../code":58,"../db_ref":59,"../double":60,"../float_parser":61,"../long":62,"../map":63,"../max_key":64,"../min_key":65,"../objectid":66,"../regexp":70,"../symbol":71,"../timestamp":72,"buffer":73}],70:[function(require,module,exports){ /** * A class representation of the BSON RegExp type. * @@ -17840,7 +17916,7 @@ function BSONRegExp(pattern, options) { module.exports = BSONRegExp; module.exports.BSONRegExp = BSONRegExp; -},{}],69:[function(require,module,exports){ +},{}],71:[function(require,module,exports){ /** * A class representation of the BSON Symbol type. * @@ -17888,7 +17964,7 @@ Symbol.prototype.toJSON = function() { module.exports = Symbol; module.exports.Symbol = Symbol; -},{}],70:[function(require,module,exports){ +},{}],72:[function(require,module,exports){ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -18745,7 +18821,7 @@ Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24); */ module.exports = Timestamp; module.exports.Timestamp = Timestamp; -},{}],71:[function(require,module,exports){ +},{}],73:[function(require,module,exports){ /*! * The buffer module from node.js, for the browser. * @@ -19799,7 +19875,7 @@ function decodeUtf8Char (str) { } } -},{"base64-js":52,"ieee754":76,"is-array":78}],72:[function(require,module,exports){ +},{"base64-js":54,"ieee754":78,"is-array":80}],74:[function(require,module,exports){ /** * This is the web browser implementation of `debug()`. @@ -19969,7 +20045,7 @@ function localstorage(){ } catch (e) {} } -},{"./debug":73}],73:[function(require,module,exports){ +},{"./debug":75}],75:[function(require,module,exports){ /** * This is the common logic for both the Node.js and web browser @@ -20168,7 +20244,7 @@ function coerce(val) { return val; } -},{"ms":93}],74:[function(require,module,exports){ +},{"ms":95}],76:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20471,7 +20547,7 @@ function isUndefined(arg) { return arg === void 0; } -},{}],75:[function(require,module,exports){ +},{}],77:[function(require,module,exports){ // TODO Add in pre and post skipping options module.exports = { /** @@ -20664,7 +20740,7 @@ function once (fn, scope) { }; } -},{}],76:[function(require,module,exports){ +},{}],78:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 @@ -20750,7 +20826,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],77:[function(require,module,exports){ +},{}],79:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -20775,7 +20851,7 @@ if (typeof Object.create === 'function') { } } -},{}],78:[function(require,module,exports){ +},{}],80:[function(require,module,exports){ /** * isArray @@ -20810,7 +20886,7 @@ module.exports = isArray || function (val) { return !! val && '[object Array]' == str.call(val); }; -},{}],79:[function(require,module,exports){ +},{}],81:[function(require,module,exports){ (function (process){ 'use strict'; @@ -21043,10 +21119,10 @@ Kareem.prototype.clone = function() { module.exports = Kareem; }).call(this,require("g5I+bs")) -},{"g5I+bs":94}],80:[function(require,module,exports){ +},{"g5I+bs":96}],82:[function(require,module,exports){ module.exports = exports = require('./lib'); -},{"./lib":81}],81:[function(require,module,exports){ +},{"./lib":83}],83:[function(require,module,exports){ /** * Returns the value of object `o` at the given `path`. * @@ -21263,7 +21339,7 @@ function K (v) { return v; } -},{}],82:[function(require,module,exports){ +},{}],84:[function(require,module,exports){ (function (process){ 'use strict'; var util = require('util'); @@ -21712,7 +21788,7 @@ Promise.deferred = function deferred() { /* End A+ tests adapter bit */ }).call(this,require("g5I+bs")) -},{"events":74,"g5I+bs":94,"util":98}],83:[function(require,module,exports){ +},{"events":76,"g5I+bs":96,"util":100}],85:[function(require,module,exports){ 'use strict'; /** @@ -21756,7 +21832,7 @@ function notImplemented (method) { } -},{}],84:[function(require,module,exports){ +},{}],86:[function(require,module,exports){ 'use strict'; var env = require('../env') @@ -21771,7 +21847,7 @@ module.exports = require('./collection'); -},{"../env":86,"./collection":83,"./node":85}],85:[function(require,module,exports){ +},{"../env":88,"./collection":85,"./node":87}],87:[function(require,module,exports){ 'use strict'; /** @@ -21881,7 +21957,7 @@ NodeCollection.prototype.findCursor = function(match, findOptions) { module.exports = exports = NodeCollection; -},{"../utils":89,"./collection":83}],86:[function(require,module,exports){ +},{"../utils":91,"./collection":85}],88:[function(require,module,exports){ (function (process,global,Buffer){ 'use strict'; @@ -21907,7 +21983,7 @@ exports.type = exports.isNode ? 'node' : 'unknown' }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"buffer":71,"g5I+bs":94}],87:[function(require,module,exports){ +},{"buffer":73,"g5I+bs":96}],89:[function(require,module,exports){ 'use strict'; /** @@ -24629,7 +24705,7 @@ module.exports = exports = Query; // TODO // test utils -},{"./collection":84,"./collection/collection":83,"./env":86,"./permissions":88,"./utils":89,"assert":50,"bluebird":90,"debug":72,"sliced":91,"util":98}],88:[function(require,module,exports){ +},{"./collection":86,"./collection/collection":85,"./env":88,"./permissions":90,"./utils":91,"assert":52,"bluebird":92,"debug":74,"sliced":93,"util":100}],90:[function(require,module,exports){ 'use strict'; var denied = exports; @@ -24719,7 +24795,7 @@ denied.count.maxScan = denied.count.snapshot = denied.count.tailable = true; -},{}],89:[function(require,module,exports){ +},{}],91:[function(require,module,exports){ (function (process,Buffer){ 'use strict'; @@ -25065,7 +25141,7 @@ exports.isArgumentsObject = function(v) { }; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"buffer":71,"g5I+bs":94,"regexp-clone":95}],90:[function(require,module,exports){ +},{"buffer":73,"g5I+bs":96,"regexp-clone":97}],92:[function(require,module,exports){ (function (process,global){ /* @preserve * The MIT License (MIT) @@ -29955,10 +30031,10 @@ module.exports = ret; },{"./es5.js":14}]},{},[4])(4) }); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"g5I+bs":94}],91:[function(require,module,exports){ +},{"g5I+bs":96}],93:[function(require,module,exports){ module.exports = exports = require('./lib/sliced'); -},{"./lib/sliced":92}],92:[function(require,module,exports){ +},{"./lib/sliced":94}],94:[function(require,module,exports){ /** * An Array.prototype.slice.call(arguments) alternative @@ -29993,7 +30069,7 @@ module.exports = function (args, slice, sliceEnd) { } -},{}],93:[function(require,module,exports){ +},{}],95:[function(require,module,exports){ /** * Helpers. */ @@ -30120,7 +30196,7 @@ function plural(ms, n, name) { return Math.ceil(ms / n) + ' ' + name + 's'; } -},{}],94:[function(require,module,exports){ +},{}],96:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -30185,7 +30261,7 @@ process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; -},{}],95:[function(require,module,exports){ +},{}],97:[function(require,module,exports){ var toString = Object.prototype.toString; @@ -30207,16 +30283,16 @@ module.exports = exports = function (regexp) { } -},{}],96:[function(require,module,exports){ -module.exports=require(92) -},{}],97:[function(require,module,exports){ +},{}],98:[function(require,module,exports){ +module.exports=require(94) +},{}],99:[function(require,module,exports){ module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } -},{}],98:[function(require,module,exports){ +},{}],100:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -30806,4 +30882,4 @@ function hasOwnProperty(obj, prop) { } }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":97,"g5I+bs":94,"inherits":77}]},{},[2]) \ No newline at end of file +},{"./support/isBuffer":99,"g5I+bs":96,"inherits":79}]},{},[2]) \ No newline at end of file diff --git a/package.json b/package.json index bb929162268..dd8a59e75a9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.15-pre", + "version": "4.4.15", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From f4217470a2a06009b1bcd4511c894d089dc08ab4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 May 2016 10:14:25 -0700 Subject: [PATCH 0534/2240] chore: now working on 4.4.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dd8a59e75a9..6894495e528 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.15", + "version": "4.4.16-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From feba5a2ebdb1c8823c35944237d49f4e84c6bd2a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 May 2016 10:28:19 -0700 Subject: [PATCH 0535/2240] test(schema): repro #3816 --- test/document.test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index bb5d47fa8f9..e3a369ed477 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2659,5 +2659,36 @@ describe('document', function() { }); }); }); + + it('validation works when setting array index (gh-3816)', function(done) { + var mySchema = new mongoose.Schema({ + items: [ + { month: Number, date: Date } + ] + }); + + var Test = db.model('test', mySchema); + + var a = [ + { month: 0, date: new Date() }, + { month: 1, date: new Date() } + ]; + Test.create({ items: a }, function(error, doc) { + assert.ifError(error); + Test.findById(doc._id).exec(function(error, doc) { + assert.ifError(error); + assert.ok(doc); + doc.items[0] = { + month: 5, + date : new Date() + }; + doc.markModified('items'); + doc.save(function(error) { + assert.ifError(error); + done(); + }); + }); + }); + }); }); }); From c2e57cd17aac24e6c85c333fdcabb46a739c7a42 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 May 2016 10:30:50 -0700 Subject: [PATCH 0536/2240] fix(schema): make sure always a subdoc in doc array validation Fix #3816 --- lib/schema/documentarray.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index bbec55c5bf1..f6eea8b78e3 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -80,6 +80,7 @@ DocumentArray.prototype.constructor = DocumentArray; */ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { + var _this = this; SchemaType.prototype.doValidate.call(this, array, function(err) { if (err) { return fn(err); @@ -114,6 +115,13 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { continue; } + // If you set the array index directly, the doc might not yet be + // a full fledged mongoose subdoc, so make it into one. + if (!(doc instanceof Subdocument)) { + doc = array[i] = new _this.casterConstructor(doc, array, undefined, + undefined, i); + } + // HACK: use $__original_validate to avoid promises so bluebird doesn't // complain if (doc.$__original_validate) { From 808597de44ab9582894924ce7a8c1a1e135f57ed Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 May 2016 11:32:30 -0700 Subject: [PATCH 0537/2240] fix(document): mark nested paths for validation Fix #4111 --- lib/document.js | 53 ++++++++++++++++++++++------------ lib/services/common.js | 4 +++ test/gh-1408.test.js | 1 - test/schema.validation.test.js | 11 ++++--- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/lib/document.js b/lib/document.js index 814ff360f40..fe414971766 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2,25 +2,26 @@ * Module dependencies. */ -var EventEmitter = require('events').EventEmitter, - MongooseError = require('./error'), - MixedSchema = require('./schema/mixed'), - Schema = require('./schema'), - ObjectExpectedError = require('./error/objectExpected'), - StrictModeError = require('./error/strict'), - ValidatorError = require('./schematype').ValidatorError, - utils = require('./utils'), - clone = utils.clone, - isMongooseObject = utils.isMongooseObject, - inspect = require('util').inspect, - ValidationError = MongooseError.ValidationError, - InternalCache = require('./internal'), - deepEqual = utils.deepEqual, - hooks = require('hooks-fixed'), - PromiseProvider = require('./promise_provider'), - DocumentArray, - MongooseArray, - Embedded; +var EventEmitter = require('events').EventEmitter; +var MongooseError = require('./error'); +var MixedSchema = require('./schema/mixed'); +var Schema = require('./schema'); +var ObjectExpectedError = require('./error/objectExpected'); +var StrictModeError = require('./error/strict'); +var ValidatorError = require('./schematype').ValidatorError; +var utils = require('./utils'); +var clone = utils.clone; +var isMongooseObject = utils.isMongooseObject; +var inspect = require('util').inspect; +var ValidationError = MongooseError.ValidationError; +var InternalCache = require('./internal'); +var deepEqual = utils.deepEqual; +var hooks = require('hooks-fixed'); +var PromiseProvider = require('./promise_provider'); +var DocumentArray; +var MongooseArray; +var Embedded; +var flatten = require('./services/common').flatten; /** * Document constructor. @@ -1183,6 +1184,20 @@ Document.prototype.$__validate = function(callback) { } } + for (i = 0; i < paths.length; ++i) { + var pathToCheck = paths[i]; + if (this.schema.nested[pathToCheck]) { + var _v = this.getValue(pathToCheck); + if (utils.isMongooseObject(_v)) { + _v = _v.toObject({ virtuals: false }); + } + var _subpaths = Object.keys(flatten(_v)).map(function(p) { + return pathToCheck + '.' + p; + }); + paths = paths.concat(_subpaths); + } + } + var complete = function() { var err = _complete(); if (err) { diff --git a/lib/services/common.js b/lib/services/common.js index 863b4708cab..24b4e1ed063 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -5,6 +5,7 @@ */ var ObjectId = require('../types/objectid'); +var utils = require('../utils'); exports.flatten = flatten; exports.modifiedPaths = modifiedPaths; @@ -22,6 +23,9 @@ function flatten(update, path) { for (var i = 0; i < numKeys; ++i) { var key = keys[i]; var val = update[key]; + if (utils.isMongooseObject(val) && !Buffer.isBuffer(val)) { + val = val.toObject({ virtuals: false }); + } if (shouldFlatten(val)) { var flat = flatten(val, path + key); for (var k in flat) { diff --git a/test/gh-1408.test.js b/test/gh-1408.test.js index 05249a08126..0231388d1f1 100644 --- a/test/gh-1408.test.js +++ b/test/gh-1408.test.js @@ -58,7 +58,6 @@ describe('documents should not be converted to _id (gh-1408)', function() { doc.set('settings', newData.settings, {merge: true}); doc.markModified('settings'); // <== this caused the bug - doc.save(function(err) { if (err) return done(err); diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 3fc2ff2d67a..46a9acf0938 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -793,18 +793,21 @@ describe('schema', function() { }); }); - it('should validate subdocuments subproperty enums', function(done) { + it('should validate subdocuments subproperty enums (gh-4111)', function(done) { var M = mongoose.model('M', new Schema({ + p: { + val: { type: String, enum: ['test'] } + }, children: [{ prop: { - val: {type: String, enum: ['valid']} + val: { type: String, enum: ['valid'] } } }] })); var model = new M(); + model.p = { val: 'test' }; var child = model.children.create(); - child.prop = { val: 'valid' }; @@ -821,7 +824,7 @@ describe('schema', function() { model.validate(function(error) { assert.ok(error); assert.equal(error.errors['children.0.prop.val'].message, - '`invalid` is not a valid enum value for path `prop.val`.'); + '`invalid` is not a valid enum value for path `prop.val`.'); done(); }); From dc4b5dfac23102a6347c5116db5a6de825ba98c5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 May 2016 13:29:40 -0400 Subject: [PATCH 0538/2240] Update release-items.md --- release-items.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/release-items.md b/release-items.md index 3dc270e908e..1ad190c9a24 100644 --- a/release-items.md +++ b/release-items.md @@ -7,10 +7,9 @@ 5. git tag x.x.x 6. git push origin BRANCH --tags && npm publish 7. update mongoosejs.com (see "updating the website" below) -8. announce to google groups - include the relevant change log and links to issues -9. tweet google group announcement from [@mongoosejs](https://twitter.com/mongoosejs) -10. change package.json version to next patch version suffixed with '-pre' and commit "now working on x.x.x" -11. if this is a legacy release, `git merge` changes into master. +8. tweet changelog link from [@mongoosejs](https://twitter.com/mongoosejs) +9. change package.json version to next patch version suffixed with '-pre' and commit "now working on x.x.x" +10. if this is a legacy release, `git merge` changes into master. ## updating the website From cc690ef63b420ec6f1396fd5f3a8519ac80a75d2 Mon Sep 17 00:00:00 2001 From: Denis Ciccale Date: Sun, 8 May 2016 20:59:02 +0200 Subject: [PATCH 0539/2240] chore(document): use function reference --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index fe414971766..3027529f595 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1188,7 +1188,7 @@ Document.prototype.$__validate = function(callback) { var pathToCheck = paths[i]; if (this.schema.nested[pathToCheck]) { var _v = this.getValue(pathToCheck); - if (utils.isMongooseObject(_v)) { + if (isMongooseObject(_v)) { _v = _v.toObject({ virtuals: false }); } var _subpaths = Object.keys(flatten(_v)).map(function(p) { From 4796285fd1166e2f891a85b7b91814a9694095d2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 May 2016 17:34:22 -0700 Subject: [PATCH 0540/2240] test(schematype): repro #4115 --- test/document.test.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index e3a369ed477..8e4106149c2 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2690,5 +2690,27 @@ describe('document', function() { }); }); }); + + it('single embedded with defaults have $parent (gh-4115)', function(done) { + var ChildSchema = new Schema({ + name: { + type: String, + 'default': 'child' + } + }); + + var ParentSchema = new Schema({ + child: { + type: ChildSchema, + 'default': {} + } + }); + + var Parent = db.model('gh4115', ParentSchema); + + var p = new Parent(); + assert.equal(p.child.$parent, p); + done(); + }); }); }); From 3a9b24070fa03f88b9857b0e46fe76f1bc23f0c6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 May 2016 17:35:35 -0700 Subject: [PATCH 0541/2240] fix(schematype): ensure single embedded defaults have $parent Fix #4115 --- lib/schematype.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/schematype.js b/lib/schematype.js index 8d4bc78696e..fb2ace93065 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -581,7 +581,11 @@ SchemaType.prototype.getDefault = function(scope, init) { : this.defaultValue; if (ret !== null && ret !== undefined) { - return this.cast(ret, scope, init); + var casted = this.cast(ret, scope, init); + if (casted && casted.$isSingleNested) { + casted.$parent = scope; + } + return casted; } return ret; }; From 669488f99c2e0f428cd0bdd7eae9fba886f120cd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 May 2016 06:38:12 -0700 Subject: [PATCH 0542/2240] test: make before hook fail fast if can't connect Fix #4121 --- test/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common.js b/test/common.js index a43535b58cd..ec0c119aa9e 100644 --- a/test/common.js +++ b/test/common.js @@ -132,7 +132,7 @@ module.exports.mongodVersion = function(cb) { }; function dropDBs(done) { - var db = module.exports(); + var db = module.exports({ noErrorListener: true }); db.once('open', function() { // drop the default test database db.db.dropDatabase(function() { From b1c18b5a27632ec126cf2ee0968e567d305ddd89 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 May 2016 06:46:19 -0700 Subject: [PATCH 0543/2240] test(connection): ensure result from createConnection has expected type Re: #4112 --- test/connection.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/connection.test.js b/test/connection.test.js index 9058d1b1a65..5cbf4d9481d 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -24,6 +24,7 @@ describe('connections:', function() { var db = mongoose.createConnection('mongodb://localhost/fake'); db.on('error', function() { }); + assert.ok(db instanceof mongoose.Connection); assert.equal('object', typeof db.options); assert.equal('object', typeof db.options.server); assert.equal(true, db.options.server.auto_reconnect); From bc28bc3c5d61273b1d029951924b151dabe55b8e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 May 2016 06:59:52 -0700 Subject: [PATCH 0544/2240] docs(schematypes): don't throw CastError in examples Re: #4113 --- lib/document.js | 6 +----- test/docs/schematypes.test.js | 7 ++++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/document.js b/lib/document.js index fe414971766..159a9cf9799 100644 --- a/lib/document.js +++ b/lib/document.js @@ -684,12 +684,8 @@ Document.prototype.set = function(path, val, type, options) { this.$markValid(path); } catch (e) { - var reason; - if (!(e instanceof MongooseError.CastError)) { - reason = e; - } this.invalidate(path, - new MongooseError.CastError(schema.instance, val, path, reason)); + new MongooseError.CastError(schema.instance, val, path, e)); shouldSet = false; } diff --git a/test/docs/schematypes.test.js b/test/docs/schematypes.test.js index c1091fbd184..d1a8e90f5a9 100644 --- a/test/docs/schematypes.test.js +++ b/test/docs/schematypes.test.js @@ -38,12 +38,11 @@ describe('schemaTypes', function () { Int8.prototype.cast = function(val) { var _val = Number(val); if (isNaN(_val)) { - throw new mongoose.SchemaType.CastError('Int8', - val + ' is not a number'); + throw new Error('Int8: ' + val + ' is not a number'); } _val = Math.round(_val); if (_val < -0x80 || _val > 0x7F) { - throw new mongoose.SchemaType.CastError('Int8', val + + throw new Error('Int8: ' + val + ' is outside of the range of valid 8-bit ints'); } return _val; @@ -61,5 +60,7 @@ describe('schemaTypes', function () { assert.equal(t.validateSync().errors['test'].name, 'CastError'); assert.equal(t.validateSync().errors['test'].message, 'Cast to Int8 failed for value "abc" at path "test"'); + assert.equal(t.validateSync().errors['test'].reason.message, + 'Int8: abc is not a number'); }); }); From ec061a967deaa2292c32760e8561db650e5fc964 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 May 2016 07:51:52 -0700 Subject: [PATCH 0545/2240] docs: add CastError params Fix #4120 --- lib/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index eacc88f898d..0be0c9f8442 100644 --- a/lib/index.js +++ b/lib/index.js @@ -694,7 +694,11 @@ Mongoose.prototype.Error = require('./error'); /** * The Mongoose CastError constructor * - * @method Error + * @method CastError + * @param {String} type The name of the type + * @param {Any} value The value that failed to cast + * @param {String} path The path `a.b.c` in the doc where this cast error occurred + * @param {Error} [reason] The original error that was thrown * @api public */ From 8a54c28c950429b9c4202d5a046ab12d85de5d2c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 May 2016 08:57:22 -0700 Subject: [PATCH 0546/2240] chore: release 4.4.16 --- History.md | 10 ++ bin/mongoose.js | 318 ++++++++++++++++++++++++++++++++---------------- package.json | 2 +- 3 files changed, 223 insertions(+), 107 deletions(-) diff --git a/History.md b/History.md index d183d31fc43..f252433c8bc 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.4.16 / 2016-05-09 +=================== + * refactor(document): use function reference #4133 [dciccale](https://github.com/dciccale) + * docs(querystream): clarify `destroy()` and close event #4126 [AnthonyCC](https://github.com/AnthonyCC) + * test: make before hook fail fast if it can't connect #4121 + * docs: add description of CastError constructor params #4120 + * fix(schematype): ensure single embedded defaults have $parent #4115 + * fix(document): mark nested paths for validation #4111 + * fix(schema): make sure element is always a subdoc in doc array validation #3816 + 4.4.15 / 2016-05-06 =================== * fix(schema): support overwriting array default #4109 diff --git a/bin/mongoose.js b/bin/mongoose.js index 28d2f97fc8e..c1adbecca59 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -129,7 +129,7 @@ if (typeof window !== 'undefined') { } }).call(this,require("buffer").Buffer) -},{"./document_provider.js":6,"./error":12,"./schema":26,"./schematype.js":41,"./types":47,"./utils.js":50,"./virtualtype":51,"buffer":73}],3:[function(require,module,exports){ +},{"./document_provider.js":6,"./error":12,"./schema":26,"./schematype.js":41,"./types":48,"./utils.js":51,"./virtualtype":52,"buffer":74}],3:[function(require,module,exports){ /*! * Module dependencies. */ @@ -234,7 +234,7 @@ Document.prototype.constructor = Document; Document.ValidationError = ValidationError; module.exports = exports = Document; -},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":48,"./utils":50,"events":76}],4:[function(require,module,exports){ +},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":49,"./utils":51,"events":77}],4:[function(require,module,exports){ /*! * Module dependencies. */ @@ -440,31 +440,32 @@ function _cast(val, numbertype) { } } -},{"./schema/index":33,"./utils":50}],5:[function(require,module,exports){ +},{"./schema/index":33,"./utils":51}],5:[function(require,module,exports){ (function (process,Buffer){ /*! * Module dependencies. */ -var EventEmitter = require('events').EventEmitter, - MongooseError = require('./error'), - MixedSchema = require('./schema/mixed'), - Schema = require('./schema'), - ObjectExpectedError = require('./error/objectExpected'), - StrictModeError = require('./error/strict'), - ValidatorError = require('./schematype').ValidatorError, - utils = require('./utils'), - clone = utils.clone, - isMongooseObject = utils.isMongooseObject, - inspect = require('util').inspect, - ValidationError = MongooseError.ValidationError, - InternalCache = require('./internal'), - deepEqual = utils.deepEqual, - hooks = require('hooks-fixed'), - PromiseProvider = require('./promise_provider'), - DocumentArray, - MongooseArray, - Embedded; +var EventEmitter = require('events').EventEmitter; +var MongooseError = require('./error'); +var MixedSchema = require('./schema/mixed'); +var Schema = require('./schema'); +var ObjectExpectedError = require('./error/objectExpected'); +var StrictModeError = require('./error/strict'); +var ValidatorError = require('./schematype').ValidatorError; +var utils = require('./utils'); +var clone = utils.clone; +var isMongooseObject = utils.isMongooseObject; +var inspect = require('util').inspect; +var ValidationError = MongooseError.ValidationError; +var InternalCache = require('./internal'); +var deepEqual = utils.deepEqual; +var hooks = require('hooks-fixed'); +var PromiseProvider = require('./promise_provider'); +var DocumentArray; +var MongooseArray; +var Embedded; +var flatten = require('./services/common').flatten; /** * Document constructor. @@ -1127,12 +1128,8 @@ Document.prototype.set = function(path, val, type, options) { this.$markValid(path); } catch (e) { - var reason; - if (!(e instanceof MongooseError.CastError)) { - reason = e; - } this.invalidate(path, - new MongooseError.CastError(schema.instance, val, path, reason)); + new MongooseError.CastError(schema.instance, val, path, e)); shouldSet = false; } @@ -1627,6 +1624,20 @@ Document.prototype.$__validate = function(callback) { } } + for (i = 0; i < paths.length; ++i) { + var pathToCheck = paths[i]; + if (this.schema.nested[pathToCheck]) { + var _v = this.getValue(pathToCheck); + if (utils.isMongooseObject(_v)) { + _v = _v.toObject({ virtuals: false }); + } + var _subpaths = Object.keys(flatten(_v)).map(function(p) { + return pathToCheck + '.' + p; + }); + paths = paths.concat(_subpaths); + } + } + var complete = function() { var err = _complete(); if (err) { @@ -2898,7 +2909,7 @@ Document.ValidationError = ValidationError; module.exports = exports = Document; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":41,"./types/array":43,"./types/documentarray":45,"./types/embedded":46,"./utils":50,"buffer":73,"events":76,"g5I+bs":96,"hooks-fixed":77,"util":100}],6:[function(require,module,exports){ +},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":41,"./services/common":42,"./types/array":44,"./types/documentarray":46,"./types/embedded":47,"./utils":51,"buffer":74,"events":77,"g5I+bs":97,"hooks-fixed":78,"util":101}],6:[function(require,module,exports){ 'use strict'; /* eslint-env browser */ @@ -2942,7 +2953,7 @@ var Binary = require('bson').Binary; module.exports = exports = Binary; -},{"bson":57}],9:[function(require,module,exports){ +},{"bson":58}],9:[function(require,module,exports){ /*! * Module exports. */ @@ -2967,7 +2978,7 @@ var ObjectId = require('bson').ObjectID; module.exports = exports = ObjectId; -},{"bson":57}],11:[function(require,module,exports){ +},{"bson":58}],11:[function(require,module,exports){ (function (global){ /*! * ignore @@ -3535,7 +3546,7 @@ function InternalCache() { this.fullPath = undefined; } -},{"./statemachine":42}],24:[function(require,module,exports){ +},{"./statemachine":43}],24:[function(require,module,exports){ /*! * Module dependencies */ @@ -3828,7 +3839,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject; module.exports = Promise; -},{"mpromise":84,"util":100}],25:[function(require,module,exports){ +},{"mpromise":85,"util":101}],25:[function(require,module,exports){ /*! * Module dependencies. */ @@ -3881,7 +3892,7 @@ Promise.reset = function() { module.exports = Promise; -},{"./ES6Promise":1,"./promise":24,"mquery":89}],26:[function(require,module,exports){ +},{"./ES6Promise":1,"./promise":24,"mquery":90}],26:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -5288,7 +5299,7 @@ Schema.Types = MongooseTypes = require('./schema/index'); exports.ObjectId = MongooseTypes.ObjectId; }).call(this,require("buffer").Buffer) -},{"./drivers":11,"./schema/index":33,"./utils":50,"./virtualtype":51,"async":53,"buffer":73,"events":76,"kareem":81}],27:[function(require,module,exports){ +},{"./drivers":11,"./schema/index":33,"./utils":51,"./virtualtype":52,"async":54,"buffer":74,"events":77,"kareem":82}],27:[function(require,module,exports){ /*! * Module dependencies. */ @@ -5588,7 +5599,7 @@ handle.$regex = SchemaArray.prototype.castForQuery; module.exports = SchemaArray; -},{"../cast":4,"../schematype":41,"../types":47,"../utils":50,"./boolean":28,"./buffer":29,"./date":30,"./mixed":34,"./number":35,"./objectid":36,"./operators/geospatial":38,"./operators/helpers":39,"./string":40}],28:[function(require,module,exports){ +},{"../cast":4,"../schematype":41,"../types":48,"../utils":51,"./boolean":28,"./buffer":29,"./date":30,"./mixed":34,"./number":35,"./objectid":36,"./operators/geospatial":38,"./operators/helpers":39,"./string":40}],28:[function(require,module,exports){ /*! * Module dependencies. */ @@ -5693,7 +5704,7 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val) { module.exports = SchemaBoolean; -},{"../schematype":41,"../utils":50}],29:[function(require,module,exports){ +},{"../schematype":41,"../utils":51}],29:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -5885,7 +5896,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) { module.exports = SchemaBuffer; }).call(this,require("buffer").Buffer) -},{"../schematype":41,"../types":47,"../utils":50,"./../document":5,"./operators/bitwise":37,"buffer":73}],30:[function(require,module,exports){ +},{"../schematype":41,"../types":48,"../utils":51,"./../document":5,"./operators/bitwise":37,"buffer":74}],30:[function(require,module,exports){ /*! * Module requirements. */ @@ -6179,7 +6190,7 @@ SchemaDate.prototype.castForQuery = function($conditional, val) { module.exports = SchemaDate; -},{"../error":12,"../schematype":41,"../utils":50}],31:[function(require,module,exports){ +},{"../error":12,"../schematype":41,"../utils":51}],31:[function(require,module,exports){ /* eslint no-empty: 1 */ /*! @@ -6262,6 +6273,7 @@ DocumentArray.prototype.constructor = DocumentArray; */ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { + var _this = this; SchemaType.prototype.doValidate.call(this, array, function(err) { if (err) { return fn(err); @@ -6296,6 +6308,13 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { continue; } + // If you set the array index directly, the doc might not yet be + // a full fledged mongoose subdoc, so make it into one. + if (!(doc instanceof Subdocument)) { + doc = array[i] = new _this.casterConstructor(doc, array, undefined, + undefined, i); + } + // HACK: use $__original_validate to avoid promises so bluebird doesn't // complain if (doc.$__original_validate) { @@ -6473,7 +6492,7 @@ function scopePaths(array, fields, init) { module.exports = DocumentArray; -},{"../error/cast":13,"../schematype":41,"../types/documentarray":45,"../types/embedded":46,"./array":27}],32:[function(require,module,exports){ +},{"../error/cast":13,"../schematype":41,"../types/documentarray":46,"../types/embedded":47,"./array":27}],32:[function(require,module,exports){ 'use strict'; /*! @@ -6636,7 +6655,7 @@ Embedded.prototype.doValidateSync = function(value) { return value.validateSync(); }; -},{"../schematype":41,"../types/subdocument":49,"./operators/geospatial":38,"./operators/helpers":39}],33:[function(require,module,exports){ +},{"../schematype":41,"../types/subdocument":50,"./operators/geospatial":38,"./operators/helpers":39}],33:[function(require,module,exports){ /*! * Module exports. @@ -6750,7 +6769,7 @@ Mixed.prototype.castForQuery = function($cond, val) { module.exports = Mixed; -},{"../schematype":41,"../utils":50}],35:[function(require,module,exports){ +},{"../schematype":41,"../utils":51}],35:[function(require,module,exports){ (function (Buffer){ /*! * Module requirements. @@ -7044,7 +7063,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val) { module.exports = SchemaNumber; }).call(this,require("buffer").Buffer) -},{"../error":12,"../schematype":41,"../utils":50,"./../document":5,"./operators/bitwise":37,"buffer":73}],36:[function(require,module,exports){ +},{"../error":12,"../schematype":41,"../utils":51,"./../document":5,"./operators/bitwise":37,"buffer":74}],36:[function(require,module,exports){ (function (Buffer){ /* eslint no-empty: 1 */ @@ -7255,7 +7274,7 @@ function resetId(v) { module.exports = ObjectId; }).call(this,require("buffer").Buffer) -},{"../schematype":41,"../types/objectid":48,"../utils":50,"./../document":5,"buffer":73}],37:[function(require,module,exports){ +},{"../schematype":41,"../types/objectid":49,"../utils":51,"./../document":5,"buffer":74}],37:[function(require,module,exports){ (function (Buffer){ /*! * Module requirements. @@ -7295,7 +7314,7 @@ function _castNumber(path, num) { module.exports = handleBitwiseOperator; }).call(this,require("buffer").Buffer) -},{"../../error/cast":13,"buffer":73}],38:[function(require,module,exports){ +},{"../../error/cast":13,"buffer":74}],38:[function(require,module,exports){ /*! * Module requirements. */ @@ -7938,7 +7957,7 @@ SchemaString.prototype.castForQuery = function($conditional, val) { module.exports = SchemaString; }).call(this,require("buffer").Buffer) -},{"../error":12,"../schematype":41,"../utils":50,"./../document":5,"buffer":73}],41:[function(require,module,exports){ +},{"../error":12,"../schematype":41,"../utils":51,"./../document":5,"buffer":74}],41:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -8523,7 +8542,11 @@ SchemaType.prototype.getDefault = function(scope, init) { : this.defaultValue; if (ret !== null && ret !== undefined) { - return this.cast(ret, scope, init); + var casted = this.cast(ret, scope, init); + if (casted && casted.$isSingleNested) { + casted.$parent = scope; + } + return casted; } return ret; }; @@ -8849,7 +8872,90 @@ exports.CastError = CastError; exports.ValidatorError = ValidatorError; }).call(this,require("buffer").Buffer) -},{"./error":12,"./utils":50,"buffer":73}],42:[function(require,module,exports){ +},{"./error":12,"./utils":51,"buffer":74}],42:[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +/*! + * Module dependencies. + */ + +var ObjectId = require('../types/objectid'); +var utils = require('../utils'); + +exports.flatten = flatten; +exports.modifiedPaths = modifiedPaths; + +/*! + * ignore + */ + +function flatten(update, path) { + var keys = Object.keys(update || {}); + var numKeys = keys.length; + var result = {}; + path = path ? path + '.' : ''; + + for (var i = 0; i < numKeys; ++i) { + var key = keys[i]; + var val = update[key]; + if (utils.isMongooseObject(val) && !Buffer.isBuffer(val)) { + val = val.toObject({ virtuals: false }); + } + if (shouldFlatten(val)) { + var flat = flatten(val, path + key); + for (var k in flat) { + result[k] = flat[k]; + } + if (Array.isArray(val)) { + result[path + key] = val; + } + } else { + result[path + key] = val; + } + } + + return result; +} + +/*! + * ignore + */ + +function modifiedPaths(update, path, result) { + var keys = Object.keys(update || {}); + var numKeys = keys.length; + result = result || {}; + path = path ? path + '.' : ''; + + for (var i = 0; i < numKeys; ++i) { + var key = keys[i]; + var val = update[key]; + + result[path + key] = true; + if (shouldFlatten(val)) { + modifiedPaths(val, path + key, result); + } + } + + return result; +} + +/*! + * ignore + */ + +function shouldFlatten(val) { + return val && + typeof val === 'object' && + !(val instanceof Date) && + !(val instanceof ObjectId) && + (!Array.isArray(val) || val.length > 0) && + !(val instanceof Buffer); +} + +}).call(this,require("buffer").Buffer) +},{"../types/objectid":49,"../utils":51,"buffer":74}],43:[function(require,module,exports){ /*! * Module dependencies. @@ -9029,7 +9135,7 @@ StateMachine.prototype.map = function map() { return this.map.apply(this, arguments); }; -},{"./utils":50}],43:[function(require,module,exports){ +},{"./utils":51}],44:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -9821,7 +9927,7 @@ MongooseArray.mixin.remove = MongooseArray.mixin.pull; module.exports = exports = MongooseArray; }).call(this,require("buffer").Buffer) -},{"../document":5,"../utils":50,"./embedded":46,"./objectid":48,"buffer":73}],44:[function(require,module,exports){ +},{"../document":5,"../utils":51,"./embedded":47,"./objectid":49,"buffer":74}],45:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -10098,7 +10204,7 @@ MongooseBuffer.Binary = Binary; module.exports = MongooseBuffer; }).call(this,require("buffer").Buffer) -},{"../drivers":11,"../utils":50,"buffer":73}],45:[function(require,module,exports){ +},{"../drivers":11,"../utils":51,"buffer":74}],46:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -10347,7 +10453,7 @@ MongooseDocumentArray.mixin = { module.exports = MongooseDocumentArray; }).call(this,require("buffer").Buffer) -},{"../document":5,"../schema/objectid":36,"../utils":50,"./array":43,"./objectid":48,"buffer":73}],46:[function(require,module,exports){ +},{"../document":5,"../schema/objectid":36,"../utils":51,"./array":44,"./objectid":49,"buffer":74}],47:[function(require,module,exports){ /* eslint no-func-assign: 1 */ /*! @@ -10669,7 +10775,7 @@ EmbeddedDocument.prototype.parentArray = function() { module.exports = EmbeddedDocument; -},{"../document_provider":6,"../promise_provider":25}],47:[function(require,module,exports){ +},{"../document_provider":6,"../promise_provider":25}],48:[function(require,module,exports){ /*! * Module exports. @@ -10686,7 +10792,7 @@ exports.ObjectId = require('./objectid'); exports.Subdocument = require('./subdocument'); -},{"./array":43,"./buffer":44,"./documentarray":45,"./embedded":46,"./objectid":48,"./subdocument":49}],48:[function(require,module,exports){ +},{"./array":44,"./buffer":45,"./documentarray":46,"./embedded":47,"./objectid":49,"./subdocument":50}],49:[function(require,module,exports){ /** * ObjectId type constructor * @@ -10701,7 +10807,7 @@ var ObjectId = require('../drivers').ObjectId; module.exports = ObjectId; -},{"../drivers":11}],49:[function(require,module,exports){ +},{"../drivers":11}],50:[function(require,module,exports){ var Document = require('../document'); var PromiseProvider = require('../promise_provider'); @@ -10827,7 +10933,7 @@ function registerRemoveListener(sub) { owner.on('remove', emitRemove); } -},{"../document":5,"../promise_provider":25}],50:[function(require,module,exports){ +},{"../document":5,"../promise_provider":25}],51:[function(require,module,exports){ (function (process,Buffer){ /*! * Module dependencies. @@ -11677,7 +11783,7 @@ exports.each = function(arr, fn) { }; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./document":5,"./types":47,"./types/objectid":48,"buffer":73,"g5I+bs":96,"mpath":82,"ms":95,"regexp-clone":97,"sliced":98}],51:[function(require,module,exports){ +},{"./document":5,"./types":48,"./types/objectid":49,"buffer":74,"g5I+bs":97,"mpath":83,"ms":96,"regexp-clone":98,"sliced":99}],52:[function(require,module,exports){ /** * VirtualType constructor @@ -11782,7 +11888,7 @@ VirtualType.prototype.applySetters = function(value, scope) { module.exports = VirtualType; -},{}],52:[function(require,module,exports){ +},{}],53:[function(require,module,exports){ // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! @@ -12144,7 +12250,7 @@ var objectKeys = Object.keys || function (obj) { return keys; }; -},{"util/":100}],53:[function(require,module,exports){ +},{"util/":101}],54:[function(require,module,exports){ (function (process,global){ /*! * async @@ -13413,7 +13519,7 @@ var objectKeys = Object.keys || function (obj) { }()); }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"g5I+bs":96}],54:[function(require,module,exports){ +},{"g5I+bs":97}],55:[function(require,module,exports){ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; ;(function (exports) { @@ -13535,7 +13641,7 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; exports.fromByteArray = uint8ToBase64 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) -},{}],55:[function(require,module,exports){ +},{}],56:[function(require,module,exports){ (function (global){ /** * Module dependencies. @@ -13886,7 +13992,7 @@ module.exports = Binary; module.exports.Binary = Binary; }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"buffer":73}],56:[function(require,module,exports){ +},{"buffer":74}],57:[function(require,module,exports){ (function (process){ /** * Binary Parser. @@ -14275,7 +14381,7 @@ BinaryParser.Buffer = BinaryParserBuffer; exports.BinaryParser = BinaryParser; }).call(this,require("g5I+bs")) -},{"g5I+bs":96,"util":100}],57:[function(require,module,exports){ +},{"g5I+bs":97,"util":101}],58:[function(require,module,exports){ (function (Buffer){ // "use strict" @@ -14602,7 +14708,7 @@ module.exports.MaxKey = MaxKey; module.exports.BSONRegExp = BSONRegExp; }).call(this,require("buffer").Buffer) -},{"./binary":55,"./code":58,"./db_ref":59,"./double":60,"./float_parser":61,"./long":62,"./map":63,"./max_key":64,"./min_key":65,"./objectid":66,"./parser/calculate_size":67,"./parser/deserializer":68,"./parser/serializer":69,"./regexp":70,"./symbol":71,"./timestamp":72,"buffer":73}],58:[function(require,module,exports){ +},{"./binary":56,"./code":59,"./db_ref":60,"./double":61,"./float_parser":62,"./long":63,"./map":64,"./max_key":65,"./min_key":66,"./objectid":67,"./parser/calculate_size":68,"./parser/deserializer":69,"./parser/serializer":70,"./regexp":71,"./symbol":72,"./timestamp":73,"buffer":74}],59:[function(require,module,exports){ /** * A class representation of the BSON Code type. * @@ -14627,7 +14733,7 @@ Code.prototype.toJSON = function() { module.exports = Code; module.exports.Code = Code; -},{}],59:[function(require,module,exports){ +},{}],60:[function(require,module,exports){ /** * A class representation of the BSON DBRef type. * @@ -14660,7 +14766,7 @@ DBRef.prototype.toJSON = function() { module.exports = DBRef; module.exports.DBRef = DBRef; -},{}],60:[function(require,module,exports){ +},{}],61:[function(require,module,exports){ /** * A class representation of the BSON Double type. * @@ -14694,7 +14800,7 @@ Double.prototype.toJSON = function() { module.exports = Double; module.exports.Double = Double; -},{}],61:[function(require,module,exports){ +},{}],62:[function(require,module,exports){ // Copyright (c) 2008, Fair Oaks Labs, Inc. // All rights reserved. // @@ -14816,7 +14922,7 @@ var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) { exports.readIEEE754 = readIEEE754; exports.writeIEEE754 = writeIEEE754; -},{}],62:[function(require,module,exports){ +},{}],63:[function(require,module,exports){ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15673,7 +15779,7 @@ Long.TWO_PWR_24_ = Long.fromInt(1 << 24); */ module.exports = Long; module.exports.Long = Long; -},{}],63:[function(require,module,exports){ +},{}],64:[function(require,module,exports){ (function (global){ "use strict" @@ -15802,7 +15908,7 @@ if(typeof global.Map !== 'undefined') { module.exports.Map = Map; } }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],64:[function(require,module,exports){ +},{}],65:[function(require,module,exports){ /** * A class representation of the BSON MaxKey type. * @@ -15817,7 +15923,7 @@ function MaxKey() { module.exports = MaxKey; module.exports.MaxKey = MaxKey; -},{}],65:[function(require,module,exports){ +},{}],66:[function(require,module,exports){ /** * A class representation of the BSON MinKey type. * @@ -15832,7 +15938,7 @@ function MinKey() { module.exports = MinKey; module.exports.MinKey = MinKey; -},{}],66:[function(require,module,exports){ +},{}],67:[function(require,module,exports){ (function (process){ /** * Module dependencies. @@ -16122,7 +16228,7 @@ module.exports.ObjectID = ObjectID; module.exports.ObjectId = ObjectID; }).call(this,require("g5I+bs")) -},{"./binary_parser":56,"g5I+bs":96}],67:[function(require,module,exports){ +},{"./binary_parser":57,"g5I+bs":97}],68:[function(require,module,exports){ (function (Buffer){ "use strict" @@ -16436,7 +16542,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down t module.exports = calculateObjectSize; }).call(this,require("buffer").Buffer) -},{"../binary":55,"../code":58,"../db_ref":59,"../double":60,"../float_parser":61,"../long":62,"../max_key":64,"../min_key":65,"../objectid":66,"../regexp":70,"../symbol":71,"../timestamp":72,"buffer":73}],68:[function(require,module,exports){ +},{"../binary":56,"../code":59,"../db_ref":60,"../double":61,"../float_parser":62,"../long":63,"../max_key":65,"../min_key":66,"../objectid":67,"../regexp":71,"../symbol":72,"../timestamp":73,"buffer":74}],69:[function(require,module,exports){ "use strict" var readIEEE754 = require('../float_parser').readIEEE754, @@ -16969,7 +17075,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down t module.exports = deserialize -},{"../binary":55,"../code":58,"../db_ref":59,"../double":60,"../float_parser":61,"../long":62,"../max_key":64,"../min_key":65,"../objectid":66,"../regexp":70,"../symbol":71,"../timestamp":72,"util":100}],69:[function(require,module,exports){ +},{"../binary":56,"../code":59,"../db_ref":60,"../double":61,"../float_parser":62,"../long":63,"../max_key":65,"../min_key":66,"../objectid":67,"../regexp":71,"../symbol":72,"../timestamp":73,"util":101}],70:[function(require,module,exports){ (function (Buffer){ "use strict" @@ -17885,7 +17991,7 @@ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down t module.exports = serializeInto; }).call(this,require("buffer").Buffer) -},{"../binary":55,"../code":58,"../db_ref":59,"../double":60,"../float_parser":61,"../long":62,"../map":63,"../max_key":64,"../min_key":65,"../objectid":66,"../regexp":70,"../symbol":71,"../timestamp":72,"buffer":73}],70:[function(require,module,exports){ +},{"../binary":56,"../code":59,"../db_ref":60,"../double":61,"../float_parser":62,"../long":63,"../map":64,"../max_key":65,"../min_key":66,"../objectid":67,"../regexp":71,"../symbol":72,"../timestamp":73,"buffer":74}],71:[function(require,module,exports){ /** * A class representation of the BSON RegExp type. * @@ -17916,7 +18022,7 @@ function BSONRegExp(pattern, options) { module.exports = BSONRegExp; module.exports.BSONRegExp = BSONRegExp; -},{}],71:[function(require,module,exports){ +},{}],72:[function(require,module,exports){ /** * A class representation of the BSON Symbol type. * @@ -17964,7 +18070,7 @@ Symbol.prototype.toJSON = function() { module.exports = Symbol; module.exports.Symbol = Symbol; -},{}],72:[function(require,module,exports){ +},{}],73:[function(require,module,exports){ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -18821,7 +18927,7 @@ Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24); */ module.exports = Timestamp; module.exports.Timestamp = Timestamp; -},{}],73:[function(require,module,exports){ +},{}],74:[function(require,module,exports){ /*! * The buffer module from node.js, for the browser. * @@ -19875,7 +19981,7 @@ function decodeUtf8Char (str) { } } -},{"base64-js":54,"ieee754":78,"is-array":80}],74:[function(require,module,exports){ +},{"base64-js":55,"ieee754":79,"is-array":81}],75:[function(require,module,exports){ /** * This is the web browser implementation of `debug()`. @@ -20045,7 +20151,7 @@ function localstorage(){ } catch (e) {} } -},{"./debug":75}],75:[function(require,module,exports){ +},{"./debug":76}],76:[function(require,module,exports){ /** * This is the common logic for both the Node.js and web browser @@ -20244,7 +20350,7 @@ function coerce(val) { return val; } -},{"ms":95}],76:[function(require,module,exports){ +},{"ms":96}],77:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20547,7 +20653,7 @@ function isUndefined(arg) { return arg === void 0; } -},{}],77:[function(require,module,exports){ +},{}],78:[function(require,module,exports){ // TODO Add in pre and post skipping options module.exports = { /** @@ -20740,7 +20846,7 @@ function once (fn, scope) { }; } -},{}],78:[function(require,module,exports){ +},{}],79:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 @@ -20826,7 +20932,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],79:[function(require,module,exports){ +},{}],80:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -20851,7 +20957,7 @@ if (typeof Object.create === 'function') { } } -},{}],80:[function(require,module,exports){ +},{}],81:[function(require,module,exports){ /** * isArray @@ -20886,7 +20992,7 @@ module.exports = isArray || function (val) { return !! val && '[object Array]' == str.call(val); }; -},{}],81:[function(require,module,exports){ +},{}],82:[function(require,module,exports){ (function (process){ 'use strict'; @@ -21119,10 +21225,10 @@ Kareem.prototype.clone = function() { module.exports = Kareem; }).call(this,require("g5I+bs")) -},{"g5I+bs":96}],82:[function(require,module,exports){ +},{"g5I+bs":97}],83:[function(require,module,exports){ module.exports = exports = require('./lib'); -},{"./lib":83}],83:[function(require,module,exports){ +},{"./lib":84}],84:[function(require,module,exports){ /** * Returns the value of object `o` at the given `path`. * @@ -21339,7 +21445,7 @@ function K (v) { return v; } -},{}],84:[function(require,module,exports){ +},{}],85:[function(require,module,exports){ (function (process){ 'use strict'; var util = require('util'); @@ -21788,7 +21894,7 @@ Promise.deferred = function deferred() { /* End A+ tests adapter bit */ }).call(this,require("g5I+bs")) -},{"events":76,"g5I+bs":96,"util":100}],85:[function(require,module,exports){ +},{"events":77,"g5I+bs":97,"util":101}],86:[function(require,module,exports){ 'use strict'; /** @@ -21832,7 +21938,7 @@ function notImplemented (method) { } -},{}],86:[function(require,module,exports){ +},{}],87:[function(require,module,exports){ 'use strict'; var env = require('../env') @@ -21847,7 +21953,7 @@ module.exports = require('./collection'); -},{"../env":88,"./collection":85,"./node":87}],87:[function(require,module,exports){ +},{"../env":89,"./collection":86,"./node":88}],88:[function(require,module,exports){ 'use strict'; /** @@ -21957,7 +22063,7 @@ NodeCollection.prototype.findCursor = function(match, findOptions) { module.exports = exports = NodeCollection; -},{"../utils":91,"./collection":85}],88:[function(require,module,exports){ +},{"../utils":92,"./collection":86}],89:[function(require,module,exports){ (function (process,global,Buffer){ 'use strict'; @@ -21983,7 +22089,7 @@ exports.type = exports.isNode ? 'node' : 'unknown' }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"buffer":73,"g5I+bs":96}],89:[function(require,module,exports){ +},{"buffer":74,"g5I+bs":97}],90:[function(require,module,exports){ 'use strict'; /** @@ -24705,7 +24811,7 @@ module.exports = exports = Query; // TODO // test utils -},{"./collection":86,"./collection/collection":85,"./env":88,"./permissions":90,"./utils":91,"assert":52,"bluebird":92,"debug":74,"sliced":93,"util":100}],90:[function(require,module,exports){ +},{"./collection":87,"./collection/collection":86,"./env":89,"./permissions":91,"./utils":92,"assert":53,"bluebird":93,"debug":75,"sliced":94,"util":101}],91:[function(require,module,exports){ 'use strict'; var denied = exports; @@ -24795,7 +24901,7 @@ denied.count.maxScan = denied.count.snapshot = denied.count.tailable = true; -},{}],91:[function(require,module,exports){ +},{}],92:[function(require,module,exports){ (function (process,Buffer){ 'use strict'; @@ -25141,7 +25247,7 @@ exports.isArgumentsObject = function(v) { }; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"buffer":73,"g5I+bs":96,"regexp-clone":97}],92:[function(require,module,exports){ +},{"buffer":74,"g5I+bs":97,"regexp-clone":98}],93:[function(require,module,exports){ (function (process,global){ /* @preserve * The MIT License (MIT) @@ -30031,10 +30137,10 @@ module.exports = ret; },{"./es5.js":14}]},{},[4])(4) }); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"g5I+bs":96}],93:[function(require,module,exports){ +},{"g5I+bs":97}],94:[function(require,module,exports){ module.exports = exports = require('./lib/sliced'); -},{"./lib/sliced":94}],94:[function(require,module,exports){ +},{"./lib/sliced":95}],95:[function(require,module,exports){ /** * An Array.prototype.slice.call(arguments) alternative @@ -30069,7 +30175,7 @@ module.exports = function (args, slice, sliceEnd) { } -},{}],95:[function(require,module,exports){ +},{}],96:[function(require,module,exports){ /** * Helpers. */ @@ -30196,7 +30302,7 @@ function plural(ms, n, name) { return Math.ceil(ms / n) + ' ' + name + 's'; } -},{}],96:[function(require,module,exports){ +},{}],97:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -30261,7 +30367,7 @@ process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; -},{}],97:[function(require,module,exports){ +},{}],98:[function(require,module,exports){ var toString = Object.prototype.toString; @@ -30283,16 +30389,16 @@ module.exports = exports = function (regexp) { } -},{}],98:[function(require,module,exports){ -module.exports=require(94) },{}],99:[function(require,module,exports){ +module.exports=require(95) +},{}],100:[function(require,module,exports){ module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } -},{}],100:[function(require,module,exports){ +},{}],101:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -30882,4 +30988,4 @@ function hasOwnProperty(obj, prop) { } }).call(this,require("g5I+bs"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":99,"g5I+bs":96,"inherits":79}]},{},[2]) \ No newline at end of file +},{"./support/isBuffer":100,"g5I+bs":97,"inherits":80}]},{},[2]) \ No newline at end of file diff --git a/package.json b/package.json index 6894495e528..c688baf28a0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.16-pre", + "version": "4.4.16", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 741dce047ba9f00f48ab392fc9af8ab74db59ffd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 May 2016 06:45:27 -0700 Subject: [PATCH 0547/2240] chore: now working on 4.4.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c688baf28a0..c744f6108c1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.16", + "version": "4.4.17-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From bde243cba9efc5a8309bb8bccb835778aab6868c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 May 2016 06:50:07 -0700 Subject: [PATCH 0548/2240] fix(promise): formally deprecate mpromise --- lib/promise.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/promise.js b/lib/promise.js index 403eaa37b3d..917e1aef56d 100644 --- a/lib/promise.js +++ b/lib/promise.js @@ -66,6 +66,11 @@ Promise.prototype = Object.create(MPromise.prototype, { } }); +Promise.prototype.then = util.deprecate(Promise.prototype.then, + 'Mongoose: mpromise (mongoose\'s default promise library) is deprecated, ' + + 'plug in your own promise library instead: ' + + 'http://mongoosejs.com/docs/promises.html'); + /*! * Override event names for backward compatibility. */ From 51729d8748ff23570375a4cb012aa9ab873214c7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 May 2016 07:50:01 -0700 Subject: [PATCH 0549/2240] feat(server): use express-style error handling with post hooks --- lib/model.js | 11 ++++------- lib/schema.js | 29 ++++++++++++++++------------- test/document.test.js | 18 ++++++++++-------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/lib/model.js b/lib/model.js index ac25198850c..6ae9f5a13f8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -184,7 +184,9 @@ Model.prototype.$__save = function(options, callback) { _this.$__handleSave(options, function(error, result) { if (error) { - return callback(error); + return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { + callback(error); + }); } _this.$__reset(); @@ -279,7 +281,6 @@ Model.prototype.save = function(options, fn) { if (options.__noPromise) { return this.$__save(options, function(error, doc, numAffected) { if (error) { - error = _this.schema.options.processError(error); return fn(error); } fn && fn(null, doc, numAffected); @@ -290,7 +291,6 @@ Model.prototype.save = function(options, fn) { return new Promise.ES6(function(resolve, reject) { _this.$__save(options, function(error, doc, numAffected) { if (error) { - error = _this.schema.options.processError(error); fn && fn(error); reject(error); return; @@ -705,7 +705,6 @@ Model.prototype.remove = function remove(options, fn) { this.$__.removing = new Promise.ES6(function(resolve, reject) { var where = _this.$__where(); if (where instanceof Error) { - where = _this.schema.options.processError(where); reject(where); fn && fn(where); return; @@ -722,7 +721,6 @@ Model.prototype.remove = function remove(options, fn) { fn && fn(null, _this); return; } - err = _this.schema.options.processError(err); reject(err); fn && fn(err); }); @@ -776,8 +774,7 @@ var CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = { toJSON: true, toObject: true, _id: true, - id: true, - processError: true + id: true }; Model.discriminator = function discriminator(name, schema) { diff --git a/lib/schema.js b/lib/schema.js index 329c7e0a946..1d703de9bc7 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -187,17 +187,15 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { // complain if (this.$__original_validate) { this.$__original_validate({__noPromise: true}, function(error) { - if (error) { - error = _this.schema.options.processError(error); - } - next(error); + return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { + next(error); + }); }); } else { this.validate({__noPromise: true}, function(error) { - if (error) { - error = _this.schema.options.processError(error); - } - next(error); + return _this.schema.s.hooks.execPost('save:error', _this, [ _this], { error: error }, function(error) { + next(error); + }); }); } } else { @@ -227,10 +225,11 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { for (var i = 0; i < subdocs.length; ++i) { delete subdocs[i].$__preSavingFromParent; } + if (error) { - error = _this.schema.options.processError(error); - done(error); - return; + return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { + done(error); + }); } next(); done(); @@ -305,8 +304,7 @@ Schema.prototype.defaultOptions = function(options) { _id: true, noVirtualId: false, // deprecated, use { id: false } id: true, - typeKey: 'type', - processError: function(v) { return v; } + typeKey: 'type' }, options); if (options.read) { @@ -898,6 +896,11 @@ Schema.prototype.post = function(method, fn) { }]); } + if (fn.length === 3) { + this.s.hooks.post(method + ':error', fn); + return this; + } + return this.queue('post', [arguments[0], function(next) { // wrap original function so that the callback goes last, // for compatibility with old code that is using synchronous post hooks diff --git a/test/document.test.js b/test/document.test.js index 98a7805932f..f1560532c28 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2022,21 +2022,23 @@ describe('document', function() { }); it('save errors', function(done) { - var opts = { - processError: function() { - return new Error('catchAll'); - } - }; - var schema = new Schema({ name: { type: String, required: true } - }, opts); + }); + + schema.post('save', function(error, doc, next) { + next(new Error('Catch all')); + }); + + schema.post('save', function(error, doc, next) { + next(new Error('Catch all #2')); + }); var Model = mongoose.model('gh2284', schema); Model.create({}, function(error) { assert.ok(error); - assert.equal(error.toString(), 'Error: catchAll'); + assert.equal(error.message, 'Catch all #2'); done(); }); }); From 9a964c286ff4a19e06f402be00737abbb56f41f0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 May 2016 16:51:28 -0700 Subject: [PATCH 0550/2240] feat(query): enable error handlers for query middleware --- lib/query.js | 13 ++++++------ test/query.middleware.test.js | 39 ++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/query.js b/lib/query.js index 6ad14482c5a..a9d6a3f5972 100644 --- a/lib/query.js +++ b/lib/query.js @@ -71,18 +71,19 @@ function Query(conditions, options, model, collection) { } if (this.schema) { + var kareemOptions = { useErrorHandlers: true }; this._count = this.model.hooks.createWrapper('count', - Query.prototype._count, this); + Query.prototype._count, this, kareemOptions); this._execUpdate = this.model.hooks.createWrapper('update', - Query.prototype._execUpdate, this); + Query.prototype._execUpdate, this, kareemOptions); this._find = this.model.hooks.createWrapper('find', - Query.prototype._find, this); + Query.prototype._find, this, kareemOptions); this._findOne = this.model.hooks.createWrapper('findOne', - Query.prototype._findOne, this); + Query.prototype._findOne, this, kareemOptions); this._findOneAndRemove = this.model.hooks.createWrapper('findOneAndRemove', - Query.prototype._findOneAndRemove, this); + Query.prototype._findOneAndRemove, this, kareemOptions); this._findOneAndUpdate = this.model.hooks.createWrapper('findOneAndUpdate', - Query.prototype._findOneAndUpdate, this); + Query.prototype._findOneAndUpdate, this, kareemOptions); } } diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 41cfe1d5c8b..c0344e3b5fe 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -202,12 +202,41 @@ describe('query middleware', function() { initializeData(function(error) { assert.ifError(error); - Author.find({title: 'Professional AngularJS'}).count(function(error, count) { + Author. + find({ title: 'Professional AngularJS' }). + count(function(error, count) { + assert.ifError(error); + assert.equal(1, count); + assert.equal(1, preCount); + assert.equal(1, postCount); + done(); + }); + }); + }); + + it('error handlers (gh-2284)', function(done) { + var testSchema = new Schema({ title: { type: String, unique: true } }); + + testSchema.post('update', function(error, res, next) { + next(new Error('woops')); + }); + + var Book = db.model('gh2284', testSchema); + + Book.on('index', function(error) { + assert.ifError(error); + var books = [ + { title: 'Professional AngularJS' }, + { title: 'The 80/20 Guide to ES2015 Generators' } + ]; + Book.create(books, function(error, books) { assert.ifError(error); - assert.equal(1, count); - assert.equal(1, preCount); - assert.equal(1, postCount); - done(); + var query = { _id: books[1]._id }; + var update = { title: 'Professional AngularJS' }; + Book.update(query, update, function(error) { + assert.equal(error.message, 'woops'); + done(); + }); }); }); }); From 816849ffb5e9cc3b1d440c05a1156e87ef652dc5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 May 2016 20:21:25 -0700 Subject: [PATCH 0551/2240] feat: upgrade kareem -> 1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 60477f48852..d95acd49837 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "1.5.2", "bson": "~0.4.23", "hooks-fixed": "1.1.0", - "kareem": "1.0.1", + "kareem": "1.1.0", "mongodb": "2.1.18", "mpath": "0.2.1", "mpromise": "0.5.5", From afe4c6e2b97fd8d20d2de11622714a2517a0a6ff Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 May 2016 20:45:24 -0700 Subject: [PATCH 0552/2240] feat(document): trigger remove hooks on subdocs when removing parent Fix #2348 --- lib/schema.js | 165 +++++++++++++++++++------------ lib/types/embedded.js | 5 +- test/common.js | 2 + test/document.test.js | 31 ++++++ test/model.discriminator.test.js | 2 +- test/schema.test.js | 6 +- 6 files changed, 140 insertions(+), 71 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 329c7e0a946..f19dc57d052 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -160,83 +160,118 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { configurable: false, enumerable: false, writable: false, - value: [{ - kind: 'pre', - hook: 'save', - fn: function(next, options) { - var _this = this; - // Nested docs have their own presave - if (this.ownerDocument) { - return next(); - } + value: [ + { + kind: 'pre', + hook: 'save', + fn: function(next, options) { + var _this = this; + // Nested docs have their own presave + if (this.ownerDocument) { + return next(); + } - var hasValidateBeforeSaveOption = options && - (typeof options === 'object') && - ('validateBeforeSave' in options); + var hasValidateBeforeSaveOption = options && + (typeof options === 'object') && + ('validateBeforeSave' in options); - var shouldValidate; - if (hasValidateBeforeSaveOption) { - shouldValidate = !!options.validateBeforeSave; - } else { - shouldValidate = this.schema.options.validateBeforeSave; - } + var shouldValidate; + if (hasValidateBeforeSaveOption) { + shouldValidate = !!options.validateBeforeSave; + } else { + shouldValidate = this.schema.options.validateBeforeSave; + } - // Validate - if (shouldValidate) { - // HACK: use $__original_validate to avoid promises so bluebird doesn't - // complain - if (this.$__original_validate) { - this.$__original_validate({__noPromise: true}, function(error) { - if (error) { - error = _this.schema.options.processError(error); - } - next(error); - }); + // Validate + if (shouldValidate) { + // HACK: use $__original_validate to avoid promises so bluebird doesn't + // complain + if (this.$__original_validate) { + this.$__original_validate({__noPromise: true}, function(error) { + if (error) { + error = _this.schema.options.processError(error); + } + next(error); + }); + } else { + this.validate({__noPromise: true}, function(error) { + if (error) { + error = _this.schema.options.processError(error); + } + next(error); + }); + } } else { - this.validate({__noPromise: true}, function(error) { - if (error) { - error = _this.schema.options.processError(error); - } - next(error); - }); + next(); } - } else { - next(); - } - } - }, { - kind: 'pre', - hook: 'save', - isAsync: true, - fn: function(next, done) { - var _this = this; - var subdocs = this.$__getAllSubdocs(); - - if (!subdocs.length || this.$__preSavingFromParent) { - done(); - next(); - return; } + }, + { + kind: 'pre', + hook: 'save', + isAsync: true, + fn: function(next, done) { + var _this = this; + var subdocs = this.$__getAllSubdocs(); + + if (!subdocs.length || this.$__preSavingFromParent) { + done(); + next(); + return; + } - async.each(subdocs, function(subdoc, cb) { - subdoc.$__preSavingFromParent = true; - subdoc.save(function(err) { - cb(err); + async.each(subdocs, function(subdoc, cb) { + subdoc.$__preSavingFromParent = true; + subdoc.save(function(err) { + cb(err); + }); + }, function(error) { + for (var i = 0; i < subdocs.length; ++i) { + delete subdocs[i].$__preSavingFromParent; + } + if (error) { + error = _this.schema.options.processError(error); + done(error); + return; + } + next(); + done(); }); - }, function(error) { - for (var i = 0; i < subdocs.length; ++i) { - delete subdocs[i].$__preSavingFromParent; + } + }, + { + kind: 'pre', + hook: 'remove', + isAsync: true, + fn: function(next, done) { + if (this.ownerDocument) { + done(); + next(); + return; } - if (error) { - error = _this.schema.options.processError(error); - done(error); + var subdocs = this.$__getAllSubdocs(); + + if (!subdocs.length) { + done(); + next(); return; } - next(); - done(); - }); + + async.each(subdocs, function(subdoc, cb) { + subdoc.remove({ noop: true }, function(err) { + cb(err); + }); + }, function(error) { + if (error) { + done(error); + return; + } + next(); + done(); + }); + } } - }] + ] }); /** diff --git a/lib/types/embedded.js b/lib/types/embedded.js index c1bdd9a0f6c..8aed57dc12c 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -120,8 +120,9 @@ function registerRemoveListener(sub) { * @api public */ -EmbeddedDocument.prototype.remove = function(fn) { - if (!this.__parentArray) { +EmbeddedDocument.prototype.remove = function(options, fn) { + if (!this.__parentArray || (options && options.noop)) { + fn && fn(null); return this; } diff --git a/test/common.js b/test/common.js index ec0c119aa9e..077741b6954 100644 --- a/test/common.js +++ b/test/common.js @@ -2,6 +2,8 @@ * Module dependencies. */ +Error.stackTraceLimit = 10; + var mongoose = require('../'), Collection = mongoose.Collection, assert = require('power-assert'), diff --git a/test/document.test.js b/test/document.test.js index 98a7805932f..ea522ed4765 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2744,5 +2744,36 @@ describe('document', function() { assert.equal(p.child.$parent, p); done(); }); + + it('removing parent doc calls remove hooks on subdocs (gh-2348)', function(done) { + var ChildSchema = new Schema({ + name: String + }); + + var called = {}; + ChildSchema.pre('remove', function(next) { + called[this.name] = true; + next(); + }); + + var ParentSchema = new Schema({ + children: [ChildSchema] + }); + + var Parent = db.model('gh2348', ParentSchema); + + var doc = { children: [{ name: 'Luke' }, { name: 'Leia' }] }; + Parent.create(doc, function(error, doc) { + assert.ifError(error); + doc.remove(function(error) { + assert.ifError(error); + assert.deepEqual(called, { + Luke: true, + Leia: true + }); + done(); + }); + }); + }); }); }); diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index dd18340fbfb..2dd67c45da0 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -308,7 +308,7 @@ describe('model', function() { }); it('merges callQueue with base queue defined before discriminator types callQueue', function(done) { - assert.equal(Employee.schema.callQueue.length, 4); + assert.equal(Employee.schema.callQueue.length, 5); // PersonSchema.post('save') assert.strictEqual(Employee.schema.callQueue[0], Person.schema.callQueue[0]); diff --git a/test/schema.test.js b/test/schema.test.js index 51cabd31840..85215843b36 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -772,15 +772,15 @@ describe('schema', function() { Tobi.pre('save', function() { }); - assert.equal(Tobi.callQueue.length, 3); + assert.equal(Tobi.callQueue.length, 4); Tobi.post('save', function() { }); - assert.equal(Tobi.callQueue.length, 4); + assert.equal(Tobi.callQueue.length, 5); Tobi.pre('save', function() { }); - assert.equal(Tobi.callQueue.length, 5); + assert.equal(Tobi.callQueue.length, 6); done(); }); }); From 88b10f594639db57fa10dab6f27353e45c8b5f4b Mon Sep 17 00:00:00 2001 From: Jed Watson Date: Wed, 11 May 2016 23:59:53 +1000 Subject: [PATCH 0553/2240] Path validation is called with the incorrect scope Unless I'm mistaken, calling `p.originalRequiredValue` with `this` instead of `_this` doesn't pass the correct scope to custom validation functions. --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 656decad904..8903ce12478 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1144,7 +1144,7 @@ Document.prototype.$__validate = function(callback) { } var p = _this.schema.path(path); if (typeof p.originalRequiredValue === 'function') { - return p.originalRequiredValue.call(this); + return p.originalRequiredValue.call(_this); } return true; }); From 9f9fac7984d3583841947fd98d330fa50ca8a93c Mon Sep 17 00:00:00 2001 From: Jed Watson Date: Thu, 12 May 2016 01:43:18 +1000 Subject: [PATCH 0554/2240] Fixing scope error in validateSync method --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 8903ce12478..04ea6223d36 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1271,7 +1271,7 @@ Document.prototype.validateSync = function(pathsToValidate) { } var p = _this.schema.path(path); if (typeof p.originalRequiredValue === 'function') { - return p.originalRequiredValue.call(this); + return p.originalRequiredValue.call(_this); } return true; }); From 8d28cdbe283d0df6d1a8048989761abf2597a044 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 May 2016 08:34:40 -0700 Subject: [PATCH 0555/2240] test(document): repro #4145 --- test/schema.validation.test.js | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 46a9acf0938..8dd7381d4bf 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -851,6 +851,50 @@ describe('schema', function() { }); }); + it('no double validation on set nested docarray (gh-4145)', function(done) { + var calls = 0; + var myValidator = function() { + ++calls; + return true; + } + var InnerSchema = new mongoose.Schema({ + myfield: { + type: String, + validate: { + validator: myValidator, + message: 'Message' + } + }, + sibling: String + }); + + var MySchema = new mongoose.Schema({ + nest: { + myarray: [InnerSchema] + }, + rootSibling: String + }); + + var Model = mongoose.model('gh4145', MySchema); + + var instance = new Model({ + rootSibling: 'This is the root sibling' + }); + // Direct object assignment + instance.nest = { + myarray: [{ + myfield: 'This is my field', + sibling: 'This is the nested sibling' + }] + }; + + instance.validate(function(error) { + assert.ifError(error); + assert.equal(calls, 1); + done(); + }); + }); + it('returns cast errors', function(done) { var breakfastSchema = new Schema({ eggs: Number From b6be9607e938326a0c01b4e0d521c71857a840b6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 May 2016 08:44:27 -0700 Subject: [PATCH 0556/2240] fix(document): dont double-validate doc array elements Fix #4145 --- lib/document.js | 110 ++++++++++++++++----------------- lib/services/common.js | 5 +- test/schema.validation.test.js | 3 +- 3 files changed, 61 insertions(+), 57 deletions(-) diff --git a/lib/document.js b/lib/document.js index 04ea6223d36..de833120f73 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1115,6 +1115,59 @@ Document.prototype.validate = function(options, callback) { }); }; +/*! + * ignore + */ + +function _getPathsToValidate(doc) { + // only validate required fields when necessary + var paths = Object.keys(doc.$__.activePaths.states.require).filter(function(path) { + if (!doc.isSelected(path) && !doc.isModified(path)) { + return false; + } + var p = doc.schema.path(path); + if (typeof p.originalRequiredValue === 'function') { + return p.originalRequiredValue.call(doc); + } + return true; + }); + + paths = paths.concat(Object.keys(doc.$__.activePaths.states.init)); + paths = paths.concat(Object.keys(doc.$__.activePaths.states.modify)); + paths = paths.concat(Object.keys(doc.$__.activePaths.states.default)); + + // gh-661: if a whole array is modified, make sure to run validation on all + // the children as well + for (var i = 0; i < paths.length; ++i) { + var path = paths[i]; + var val = doc.getValue(path); + if (val && val.isMongooseArray && !Buffer.isBuffer(val) && !val.isMongooseDocumentArray) { + var numElements = val.length; + for (var j = 0; j < numElements; ++j) { + paths.push(path + '.' + j); + } + } + } + + var flattenOptions = { skipArrays: true }; + for (i = 0; i < paths.length; ++i) { + var pathToCheck = paths[i]; + if (doc.schema.nested[pathToCheck]) { + var _v = doc.getValue(pathToCheck); + if (isMongooseObject(_v)) { + _v = _v.toObject({ virtuals: false }); + } + var flat = flatten(_v, '', flattenOptions); + var _subpaths = Object.keys(flat).map(function(p) { + return pathToCheck + '.' + p; + }); + paths = paths.concat(_subpaths); + } + } + + return paths; +} + /*! * ignore */ @@ -1138,20 +1191,7 @@ Document.prototype.$__validate = function(callback) { }; // only validate required fields when necessary - var paths = Object.keys(this.$__.activePaths.states.require).filter(function(path) { - if (!_this.isSelected(path) && !_this.isModified(path)) { - return false; - } - var p = _this.schema.path(path); - if (typeof p.originalRequiredValue === 'function') { - return p.originalRequiredValue.call(_this); - } - return true; - }); - - paths = paths.concat(Object.keys(this.$__.activePaths.states.init)); - paths = paths.concat(Object.keys(this.$__.activePaths.states.modify)); - paths = paths.concat(Object.keys(this.$__.activePaths.states.default)); + var paths = _getPathsToValidate(this); if (paths.length === 0) { process.nextTick(function() { @@ -1167,33 +1207,6 @@ Document.prototype.$__validate = function(callback) { var validating = {}, total = 0; - // gh-661: if a whole array is modified, make sure to run validation on all - // the children as well - for (var i = 0; i < paths.length; ++i) { - var path = paths[i]; - var val = _this.getValue(path); - if (val && val.isMongooseArray && !Buffer.isBuffer(val) && !val.isMongooseDocumentArray) { - var numElements = val.length; - for (var j = 0; j < numElements; ++j) { - paths.push(path + '.' + j); - } - } - } - - for (i = 0; i < paths.length; ++i) { - var pathToCheck = paths[i]; - if (this.schema.nested[pathToCheck]) { - var _v = this.getValue(pathToCheck); - if (isMongooseObject(_v)) { - _v = _v.toObject({ virtuals: false }); - } - var _subpaths = Object.keys(flatten(_v)).map(function(p) { - return pathToCheck + '.' + p; - }); - paths = paths.concat(_subpaths); - } - } - var complete = function() { var err = _complete(); if (err) { @@ -1265,20 +1278,7 @@ Document.prototype.validateSync = function(pathsToValidate) { } // only validate required fields when necessary - var paths = Object.keys(this.$__.activePaths.states.require).filter(function(path) { - if (!_this.isSelected(path) && !_this.isModified(path)) { - return false; - } - var p = _this.schema.path(path); - if (typeof p.originalRequiredValue === 'function') { - return p.originalRequiredValue.call(_this); - } - return true; - }); - - paths = paths.concat(Object.keys(this.$__.activePaths.states.init)); - paths = paths.concat(Object.keys(this.$__.activePaths.states.modify)); - paths = paths.concat(Object.keys(this.$__.activePaths.states.default)); + var paths = _getPathsToValidate(this); if (pathsToValidate && pathsToValidate.length) { var tmp = []; diff --git a/lib/services/common.js b/lib/services/common.js index 24b4e1ed063..7c60a743cec 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -14,7 +14,7 @@ exports.modifiedPaths = modifiedPaths; * ignore */ -function flatten(update, path) { +function flatten(update, path, options) { var keys = Object.keys(update || {}); var numKeys = keys.length; var result = {}; @@ -27,6 +27,9 @@ function flatten(update, path) { val = val.toObject({ virtuals: false }); } if (shouldFlatten(val)) { + if (options && options.skipArrays && Array.isArray(val)) { + continue; + } var flat = flatten(val, path + key); for (var k in flat) { result[k] = flat[k]; diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 8dd7381d4bf..2a675a118ba 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -856,7 +856,8 @@ describe('schema', function() { var myValidator = function() { ++calls; return true; - } + }; + var InnerSchema = new mongoose.Schema({ myfield: { type: String, From 702f5b792c27881ee99fed246b6f614337826480 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 May 2016 08:49:39 -0700 Subject: [PATCH 0557/2240] chore: release 4.4.17 --- History.md | 6 +++ bin/mongoose.js | 115 +++++++++++++++++++++++++----------------------- package.json | 2 +- 3 files changed, 66 insertions(+), 57 deletions(-) diff --git a/History.md b/History.md index f252433c8bc..a8ac200a954 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +4.4.17 / 2016-05-13 +=================== + * docs: remove repetition in QueryStream docs #4147 [hugoabonizio](https://github.com/hugoabonizio) + * fix(document): dont double-validate doc array elements #4145 + * fix(document): call required function with correct scope #4142 [JedWatson](https://github.com/JedWatson) + 4.4.16 / 2016-05-09 =================== * refactor(document): use function reference #4133 [dciccale](https://github.com/dciccale) diff --git a/bin/mongoose.js b/bin/mongoose.js index c1adbecca59..2df894457b1 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -1559,6 +1559,59 @@ Document.prototype.validate = function(options, callback) { }); }; +/*! + * ignore + */ + +function _getPathsToValidate(doc) { + // only validate required fields when necessary + var paths = Object.keys(doc.$__.activePaths.states.require).filter(function(path) { + if (!doc.isSelected(path) && !doc.isModified(path)) { + return false; + } + var p = doc.schema.path(path); + if (typeof p.originalRequiredValue === 'function') { + return p.originalRequiredValue.call(doc); + } + return true; + }); + + paths = paths.concat(Object.keys(doc.$__.activePaths.states.init)); + paths = paths.concat(Object.keys(doc.$__.activePaths.states.modify)); + paths = paths.concat(Object.keys(doc.$__.activePaths.states.default)); + + // gh-661: if a whole array is modified, make sure to run validation on all + // the children as well + for (var i = 0; i < paths.length; ++i) { + var path = paths[i]; + var val = doc.getValue(path); + if (val && val.isMongooseArray && !Buffer.isBuffer(val) && !val.isMongooseDocumentArray) { + var numElements = val.length; + for (var j = 0; j < numElements; ++j) { + paths.push(path + '.' + j); + } + } + } + + var flattenOptions = { skipArrays: true }; + for (i = 0; i < paths.length; ++i) { + var pathToCheck = paths[i]; + if (doc.schema.nested[pathToCheck]) { + var _v = doc.getValue(pathToCheck); + if (isMongooseObject(_v)) { + _v = _v.toObject({ virtuals: false }); + } + var flat = flatten(_v, '', flattenOptions); + var _subpaths = Object.keys(flat).map(function(p) { + return pathToCheck + '.' + p; + }); + paths = paths.concat(_subpaths); + } + } + + return paths; +} + /*! * ignore */ @@ -1582,20 +1635,7 @@ Document.prototype.$__validate = function(callback) { }; // only validate required fields when necessary - var paths = Object.keys(this.$__.activePaths.states.require).filter(function(path) { - if (!_this.isSelected(path) && !_this.isModified(path)) { - return false; - } - var p = _this.schema.path(path); - if (typeof p.originalRequiredValue === 'function') { - return p.originalRequiredValue.call(this); - } - return true; - }); - - paths = paths.concat(Object.keys(this.$__.activePaths.states.init)); - paths = paths.concat(Object.keys(this.$__.activePaths.states.modify)); - paths = paths.concat(Object.keys(this.$__.activePaths.states.default)); + var paths = _getPathsToValidate(this); if (paths.length === 0) { process.nextTick(function() { @@ -1611,33 +1651,6 @@ Document.prototype.$__validate = function(callback) { var validating = {}, total = 0; - // gh-661: if a whole array is modified, make sure to run validation on all - // the children as well - for (var i = 0; i < paths.length; ++i) { - var path = paths[i]; - var val = _this.getValue(path); - if (val && val.isMongooseArray && !Buffer.isBuffer(val) && !val.isMongooseDocumentArray) { - var numElements = val.length; - for (var j = 0; j < numElements; ++j) { - paths.push(path + '.' + j); - } - } - } - - for (i = 0; i < paths.length; ++i) { - var pathToCheck = paths[i]; - if (this.schema.nested[pathToCheck]) { - var _v = this.getValue(pathToCheck); - if (utils.isMongooseObject(_v)) { - _v = _v.toObject({ virtuals: false }); - } - var _subpaths = Object.keys(flatten(_v)).map(function(p) { - return pathToCheck + '.' + p; - }); - paths = paths.concat(_subpaths); - } - } - var complete = function() { var err = _complete(); if (err) { @@ -1709,20 +1722,7 @@ Document.prototype.validateSync = function(pathsToValidate) { } // only validate required fields when necessary - var paths = Object.keys(this.$__.activePaths.states.require).filter(function(path) { - if (!_this.isSelected(path) && !_this.isModified(path)) { - return false; - } - var p = _this.schema.path(path); - if (typeof p.originalRequiredValue === 'function') { - return p.originalRequiredValue.call(this); - } - return true; - }); - - paths = paths.concat(Object.keys(this.$__.activePaths.states.init)); - paths = paths.concat(Object.keys(this.$__.activePaths.states.modify)); - paths = paths.concat(Object.keys(this.$__.activePaths.states.default)); + var paths = _getPathsToValidate(this); if (pathsToValidate && pathsToValidate.length) { var tmp = []; @@ -8890,7 +8890,7 @@ exports.modifiedPaths = modifiedPaths; * ignore */ -function flatten(update, path) { +function flatten(update, path, options) { var keys = Object.keys(update || {}); var numKeys = keys.length; var result = {}; @@ -8903,6 +8903,9 @@ function flatten(update, path) { val = val.toObject({ virtuals: false }); } if (shouldFlatten(val)) { + if (options && options.skipArrays && Array.isArray(val)) { + continue; + } var flat = flatten(val, path + key); for (var k in flat) { result[k] = flat[k]; diff --git a/package.json b/package.json index c744f6108c1..60edaac7480 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.17-pre", + "version": "4.4.17", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From cc5ee9cf5c5cb9ce2a89b3c16c0598b2d72d985a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 May 2016 10:38:39 -0700 Subject: [PATCH 0558/2240] chore: now working on 4.4.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 60edaac7480..be921f26443 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.17", + "version": "4.4.18-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 6afc0e2c8a742b83132e16b0fb89dffd2f90ac4a Mon Sep 17 00:00:00 2001 From: Alejandro Oviedo Date: Tue, 17 May 2016 09:54:20 -0300 Subject: [PATCH 0559/2240] change build badge to svg as it looks better on retina --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c1710d14a6b..c38e90d9cbe 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. -[![Build Status](https://api.travis-ci.org/Automattic/mongoose.png?branch=master)](https://travis-ci.org/Automattic/mongoose) +[![Build Status](https://api.travis-ci.org/Automattic/mongoose.svg?branch=master)](https://travis-ci.org/Automattic/mongoose) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Automattic/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![NPM version](https://badge.fury.io/js/mongoose.svg)](http://badge.fury.io/js/mongoose) [![Dependency Status](https://gemnasium.com/Automattic/mongoose.svg)](https://gemnasium.com/Automattic/mongoose) From e485758899249187a16934d46287e496558600c6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 19 May 2016 07:29:37 -0700 Subject: [PATCH 0560/2240] feat(drivers): emit error on 'serverClosed' because that means that reconnect failed Fix #3615 --- lib/drivers/node-mongodb-native/connection.js | 23 +++++++---- lib/error/disconnected.js | 40 +++++++++++++++++++ 2 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 lib/error/disconnected.js diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index f7d70020944..aabaca3fea9 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -2,13 +2,14 @@ * Module dependencies. */ -var MongooseConnection = require('../../connection'), - mongo = require('mongodb'), - Db = mongo.Db, - Server = mongo.Server, - Mongos = mongo.Mongos, - STATES = require('../../connectionstate'), - ReplSetServers = mongo.ReplSet; +var MongooseConnection = require('../../connection'); +var mongo = require('mongodb'); +var Db = mongo.Db; +var Server = mongo.Server; +var Mongos = mongo.Mongos; +var STATES = require('../../connectionstate'); +var ReplSetServers = mongo.ReplSet; +var DisconnectedError = require('../../error/disconnected'); /** * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) connection implementation. @@ -44,6 +45,7 @@ NativeConnection.prototype.__proto__ = MongooseConnection.prototype; */ NativeConnection.prototype.doOpen = function(fn) { + var _this = this; var server = new Server(this.host, this.port, this.options.server); if (this.options && this.options.mongos) { @@ -53,10 +55,15 @@ NativeConnection.prototype.doOpen = function(fn) { this.db = new Db(this.name, server, this.options.db); } - var _this = this; this.db.open(function(err) { listen(_this); + + server.s.server.on('serverClosed', function(error) { + _this.emit('error', new DisconnectedError(server.s.server.name)); + }); + if (err) return fn(err); + fn(); }); diff --git a/lib/error/disconnected.js b/lib/error/disconnected.js new file mode 100644 index 00000000000..b4eece1cac1 --- /dev/null +++ b/lib/error/disconnected.js @@ -0,0 +1,40 @@ +/*! + * Module dependencies. + */ + +var MongooseError = require('../error.js'); + +/** + * Casting Error constructor. + * + * @param {String} type + * @param {String} value + * @inherits MongooseError + * @api private + */ + +function DisconnectedError(connectionString) { + MongooseError.call(this, 'Ran out of retries trying to reconnect to "' + + connectionString + '". Try setting `server.reconnectTries` and ' + + '`server.reconnectInterval` to something higher.'); + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack; + } + this.name = 'DisconnectedError'; +} + +/*! + * Inherits from MongooseError. + */ + +DisconnectedError.prototype = Object.create(MongooseError.prototype); +DisconnectedError.prototype.constructor = MongooseError; + + +/*! + * exports + */ + +module.exports = DisconnectedError; From 9c7c0b3d1702a885dd8f0c716e1800dd93edacb8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 19 May 2016 15:03:16 -0700 Subject: [PATCH 0561/2240] fix(connection): handle disconnected error properly Fix #3615 --- lib/drivers/node-mongodb-native/connection.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index aabaca3fea9..36d0207ddab 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -58,9 +58,13 @@ NativeConnection.prototype.doOpen = function(fn) { this.db.open(function(err) { listen(_this); - server.s.server.on('serverClosed', function(error) { - _this.emit('error', new DisconnectedError(server.s.server.name)); - }); + if (!mongos) { + server.s.server.on('error', function(error) { + if (/after \d+ retries/.test(error.message)) { + _this.emit('error', new DisconnectedError(server.s.server.name)); + } + }); + } if (err) return fn(err); From 947faa6472a1abbaf87f3ce02e817fc29e762ab1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 May 2016 07:16:49 -0700 Subject: [PATCH 0562/2240] feat(querycursor): add `eachAsync()` function, thanks RethinkDB Fix #3637 --- lib/querycursor.js | 56 +++++++++++++++++++++++++++++++++++++++ test/query.cursor.test.js | 26 ++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/lib/querycursor.js b/lib/querycursor.js index d278dacebcf..7ee84dad666 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -87,6 +87,62 @@ QueryCursor.prototype.next = function(callback) { }); }; +/** + * Execute `fn` for every document in the cursor. If `fn` returns a promise, + * will wait for the promise to resolve before iterating on to the next one. + * Returns a promise that resolves when done. + * + * @param {Function} fn + * @param {Function} [callback] executed when all docs have been processed + * @return {Promise} + * @api public + * @method eachAsync + */ + +QueryCursor.prototype.eachAsync = function(fn, callback) { + var Promise = PromiseProvider.get(); + var _this = this; + + var handleNextResult = function(doc, callback) { + var promise = fn(doc); + if (promise && typeof promise.then === 'function') { + promise.then( + function() { callback(null); }, + function(error) { callback(error); }); + } else { + callback(null); + } + }; + + var iterate = function(callback) { + return _next(_this, function(error, doc) { + if (error) { + return callback(error); + } + if (!doc) { + return callback(null); + } + handleNextResult(doc, function(error) { + if (error) { + return callback(error); + } + iterate(callback); + }); + }); + }; + + return new Promise.ES6(function(resolve, reject) { + iterate(function(error) { + if (error) { + callback && callback(error); + return reject(error); + } + callback && callback(null); + return resolve(); + }); + }); +}; + /*! * Get the next doc from the underlying cursor and mongooseify it * (populate, etc.) diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index ca7ba2a27c2..73c60435dbd 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -125,4 +125,30 @@ describe('QueryCursor', function() { done(); }); }); + + describe('#eachAsync()', function() { + it('iterates one-by-one, stopping for promises', function(done) { + var cursor = Model.find().sort({ name: 1 }).cursor(); + + var expectedNames = ['Axl', 'Slash']; + var cur = 0; + + var checkDoc = function(doc) { + var _cur = cur; + assert.equal(doc.name, expectedNames[cur]); + return { + then: function(onResolve) { + setTimeout(function() { + assert.equal(_cur, cur++); + onResolve(); + }, 50); + } + }; + }; + cursor.eachAsync(checkDoc).then(function() { + assert.equal(cur, 2); + done(); + }).catch(done); + }); + }); }); From 67b3f47355b166520c8b397bde10b7aefceb854a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 May 2016 07:29:01 -0700 Subject: [PATCH 0563/2240] test(update): add coverage for #2593 --- test/model.update.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 30d371c93ab..b4c6f5261df 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1816,5 +1816,25 @@ describe('model: update:', function() { Model.update(query, update).then(ok, done); }); }); + + it('versioning with setDefaultsOnInsert (gh-2593)', function(done) { + var schema = new Schema({ + num: Number, + arr: [{ num: Number }] + }); + + var Model = db.model('gh2593', schema); + var update = { $inc: { num: 1 }, $push: { arr: { num: 5 } } }; + var options = { + upsert: true, + setDefaultsOnInsert: true, + new: true, + runValidators: true + }; + Model.update({}, update, options, function(error) { + assert.ifError(error); + done(); + }); + }); }); }); From 17bb37e52c8f534a6729ed8fae4d023395776a6c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 May 2016 07:36:24 -0700 Subject: [PATCH 0564/2240] docs(schema): correct the description of `bufferCommands` Re: #4137 --- docs/guide.jade | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/guide.jade b/docs/guide.jade index 91663b43ebd..160c2c0b2a4 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -273,7 +273,9 @@ block content h4#bufferCommands option: bufferCommands :markdown - When running with the drivers `autoReconnect` option disabled and connected to a single `mongod` (non-replica-set), mongoose buffers commands when the connection goes down until you manually reconnect. To disable mongoose buffering under these conditions, set this option to `false`. + By default, mongoose buffers commands when the connection goes down until + the driver manages to reconnect. To disable buffering, set `bufferCommands` + to false. :js var schema = new Schema({..}, { bufferCommands: false }); From 4b3af8a850126b298a31562faf1745e4ddd1c06b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 May 2016 08:23:45 -0700 Subject: [PATCH 0565/2240] test(model): repro #4148 --- test/model.discriminator.test.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 92da5436f80..0e5e7650b53 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -202,6 +202,17 @@ describe('model', function() { done(); }); + it('throws error if model name is taken (gh-4148)', function(done) { + var Foo = db.model('model-discriminator-4148', new Schema({})); + db.model('model-discriminator-4148-bar', new Schema({})); + assert.throws( + function() { + Foo.discriminator('model-discriminator-4148-bar', new Schema()); + }, + /Cannot overwrite `model-discriminator-4148-bar`/); + done(); + }); + it('works with nested schemas (gh-2821)', function(done) { var MinionSchema = function() { mongoose.Schema.apply(this, arguments); @@ -230,7 +241,7 @@ describe('model', function() { assert.doesNotThrow(function() { var Person = db.model('gh2821', PersonSchema); - Person.discriminator('Boss', BossSchema); + Person.discriminator('gh2821-Boss', BossSchema); }); done(); }); From 7bd853434528c76f917ec9c388a24669e1cb39c5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 May 2016 08:24:00 -0700 Subject: [PATCH 0566/2240] fix(model): throw overwrite error when discriminator name conflicts Fix #4148 --- lib/model.js | 3 +++ test/docs/discriminators.test.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 764dd4cc43e..2cad40c8057 100644 --- a/lib/model.js +++ b/lib/model.js @@ -839,6 +839,9 @@ Model.discriminator = function discriminator(name, schema) { if (this.discriminators[name]) { throw new Error('Discriminator with name "' + name + '" already exists'); } + if (this.db.models[name]) { + throw new MongooseError.OverwriteModelError(name); + } this.discriminators[name] = this.db.model(name, schema, this.collection.name); this.discriminators[name].prototype.__proto__ = this.prototype; diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index cb4674c50f6..b33bd150b9e 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -181,7 +181,7 @@ describe('discriminator docs', function () { ++clickedSchemaCalls; next(); }); - var ClickedLinkEvent = Event.discriminator('ClickedLink', + var ClickedLinkEvent = Event.discriminator('ClickedLinkEvent', clickedLinkSchema); var event1 = new ClickedLinkEvent(); From 2c1e2a03fd24db56b80be6d45d4e63f9d0a3e3fa Mon Sep 17 00:00:00 2001 From: gitname Date: Sat, 21 May 2016 12:10:49 -0700 Subject: [PATCH 0567/2240] Add period to abbreviation --- docs/faq.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.jade b/docs/faq.jade index 68ecac9839f..4f4bc593593 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -63,7 +63,7 @@ block content :markdown **Q**. My `save()` callback never executes. What am I doing wrong? - **A**. All `collection` actions (insert, remove, queries, etc) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. + **A**. All `collection` actions (insert, remove, queries, etc.) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. :js // if connecting on the default mongoose connection mongoose.connect(..); From 6ceb5b923bbe66bf52c7621534b5f85fc95e7df0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 May 2016 12:38:09 -0700 Subject: [PATCH 0568/2240] fix(utils): make sure to require in document properly Fix #4152 --- lib/utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utils.js b/lib/utils.js index 677d350166c..5c40d84b4bf 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -410,6 +410,7 @@ var toString = Object.prototype.toString; */ exports.toObject = function toObject(obj) { + Document || (Document = require('./document')); var ret; if (exports.isNullOrUndefined(obj)) { From 1729c8cfb40d5c8b6baa19fb74952a52080c63ba Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 May 2016 12:54:54 -0700 Subject: [PATCH 0569/2240] test(model): repro #4155 --- test/model.test.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/model.test.js b/test/model.test.js index fd5d96dfffb..173df720a70 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5206,7 +5206,9 @@ describe('Model', function() { }); it('insertMany() (gh-723)', function(done) { - var schema = new Schema({name: String}); + var schema = new Schema({ + name: String + }, { timestamps: true }); var Movie = db.model('gh723', schema); var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }]; @@ -5215,9 +5217,13 @@ describe('Model', function() { assert.equal(docs.length, 2); assert.ok(!docs[0].isNew); assert.ok(!docs[1].isNew); + assert.ok(docs[0].createdAt); + assert.ok(docs[1].createdAt); Movie.find({}, function(error, docs) { assert.ifError(error); assert.equal(docs.length, 2); + assert.ok(docs[0].createdAt); + assert.ok(docs[1].createdAt); done(); }); }); From 8e6814baaecb2a0f6ba4d311541ef7bb85ba954b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 May 2016 12:54:56 -0700 Subject: [PATCH 0570/2240] fix(model): initialize timestamps when insertMany Fix #4155 --- lib/model.js | 2 +- lib/schema.js | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 2cad40c8057..b0511820eaa 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1850,7 +1850,7 @@ Model.insertMany = function(arr, callback) { return; } var docObjects = docs.map(function(doc) { - return doc.toObject({virtuals: false}); + return doc.initializeTimestamps().toObject({ virtuals: false }); }); _this.collection.insertMany(docObjects, function(error) { if (error) { diff --git a/lib/schema.js b/lib/schema.js index d9edc3ba985..09446da76dc 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -723,6 +723,16 @@ Schema.prototype.setupTimestamp = function(timestamps) { return updates; }; + this.methods.initializeTimestamps = function() { + if (!this[createdAt]) { + this[createdAt] = new Date(); + } + if (!this[updatedAt]) { + this[updatedAt] = new Date(); + } + return this; + }; + this.pre('findOneAndUpdate', function(next) { this.findOneAndUpdate({}, genUpdates()); next(); From b6d4feeb0541d7561374f28698ae04ad6821c221 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 May 2016 13:30:32 -0700 Subject: [PATCH 0571/2240] chore: release 4.4.18 --- History.md | 8 ++++++++ bin/mongoose.js | 11 +++++++++++ package.json | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index a8ac200a954..048777dac0e 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.4.18 / 2016-05-21 +=================== + * docs: add missing period #4170 [gitname](https://github.com/gitname) + * docs: change build badge to svg #4158 [a0viedo](https://github.com/a0viedo) + * fix(model): update timestamps when setting `createdAt` #4155 + * fix(utils): make sure to require in document properly #4152 + * fix(model): throw overwrite error when discriminator name conflicts #4148 + 4.4.17 / 2016-05-13 =================== * docs: remove repetition in QueryStream docs #4147 [hugoabonizio](https://github.com/hugoabonizio) diff --git a/bin/mongoose.js b/bin/mongoose.js index 2df894457b1..e9b0e539cd3 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -4619,6 +4619,16 @@ Schema.prototype.setupTimestamp = function(timestamps) { return updates; }; + this.methods.initializeTimestamps = function() { + if (!this[createdAt]) { + this[createdAt] = new Date(); + } + if (!this[updatedAt]) { + this[updatedAt] = new Date(); + } + return this; + }; + this.pre('findOneAndUpdate', function(next) { this.findOneAndUpdate({}, genUpdates()); next(); @@ -11350,6 +11360,7 @@ var toString = Object.prototype.toString; */ exports.toObject = function toObject(obj) { + Document || (Document = require('./document')); var ret; if (exports.isNullOrUndefined(obj)) { diff --git a/package.json b/package.json index be921f26443..ba6df07d78e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.18-pre", + "version": "4.4.18", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 6ddccacf794e7b766d0091ff92a9e6a85d1f4be3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 May 2016 13:51:13 -0700 Subject: [PATCH 0572/2240] feat(model): add hooks for `insertMany` Fix #3846 --- lib/model.js | 9 ++++++++- lib/schema.js | 9 +++++---- test/model.test.js | 25 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index 78cd90baabd..3cb17949356 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1867,7 +1867,10 @@ Model.insertMany = function(arr, callback) { return; } var docObjects = docs.map(function(doc) { - return doc.initializeTimestamps().toObject({ virtuals: false }); + if (doc.initializeTimestamps) { + return doc.initializeTimestamps().toObject({ virtuals: false }); + } + return doc.toObject({ virtuals: false }); }); _this.collection.insertMany(docObjects, function(error) { if (error) { @@ -3116,6 +3119,10 @@ Model.compile = function compile(name, schema, collectionName, connection, base) model.schema = model.prototype.schema; model.collection = model.prototype.collection; + var kareemOptions = { useErrorHandlers: true }; + model.insertMany = model.hooks.createWrapper('insertMany', + model.insertMany, model, kareemOptions); + return model; }; diff --git a/lib/schema.js b/lib/schema.js index 2d3ddd28cb3..bb5265f03cc 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -10,12 +10,13 @@ var MongooseTypes; var Kareem = require('kareem'); var async = require('async'); -var IS_QUERY_HOOK = { +var IS_KAREEM_HOOK = { count: true, find: true, findOne: true, findOneAndUpdate: true, findOneAndRemove: true, + insertMany: true, update: true }; @@ -84,7 +85,7 @@ function Schema(obj, options) { this.s = { hooks: new Kareem(), - queryHooks: IS_QUERY_HOOK + kareemHooks: IS_KAREEM_HOOK }; this.options = this.defaultOptions(options); @@ -899,7 +900,7 @@ Schema.prototype.queue = function(name, args) { Schema.prototype.pre = function() { var name = arguments[0]; - if (IS_QUERY_HOOK[name]) { + if (IS_KAREEM_HOOK[name]) { this.s.hooks.pre.apply(this.s.hooks, arguments); return this; } @@ -930,7 +931,7 @@ Schema.prototype.pre = function() { */ Schema.prototype.post = function(method, fn) { - if (IS_QUERY_HOOK[method]) { + if (IS_KAREEM_HOOK[method]) { this.s.hooks.post.apply(this.s.hooks, arguments); return this; } diff --git a/test/model.test.js b/test/model.test.js index 173df720a70..f95da597f48 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5229,6 +5229,31 @@ describe('Model', function() { }); }); + it('insertMany() hooks (gh-3846)', function(done) { + var schema = new Schema({ + name: String + }); + var calledPre = 0; + var calledPost = 0; + schema.pre('insertMany', function(next) { + ++calledPre; + next(); + }); + schema.post('insertMany', function() { + ++calledPost; + }); + var Movie = db.model('gh3846', schema); + + var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }]; + Movie.insertMany(arr, function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 2); + assert.equal(calledPre, 1); + assert.equal(calledPost, 1); + done(); + }); + }); + it('marks array as modified when initializing non-array from db (gh-2442)', function(done) { var s1 = new Schema({ array: mongoose.Schema.Types.Mixed From c1182c30be87c63d6f893822e6479554e2180c69 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 May 2016 13:54:43 -0700 Subject: [PATCH 0573/2240] fix(model): handle insertMany if timestamps not set Fix #4171 --- lib/model.js | 5 ++++- test/model.test.js | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index b0511820eaa..8fb8ad3c440 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1850,7 +1850,10 @@ Model.insertMany = function(arr, callback) { return; } var docObjects = docs.map(function(doc) { - return doc.initializeTimestamps().toObject({ virtuals: false }); + if (doc.initializeTimestamps) { + return doc.initializeTimestamps().toObject({ virtuals: false }); + } + return doc.toObject({ virtuals: false }); }); _this.collection.insertMany(docObjects, function(error) { if (error) { diff --git a/test/model.test.js b/test/model.test.js index 173df720a70..904fff5bb22 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5229,6 +5229,26 @@ describe('Model', function() { }); }); + it('insertMany() with timestamps (gh-723)', function(done) { + var schema = new Schema({ + name: String + }); + var Movie = db.model('gh723_0', schema); + + var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }]; + Movie.insertMany(arr, function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 2); + assert.ok(!docs[0].isNew); + assert.ok(!docs[1].isNew); + Movie.find({}, function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 2); + done(); + }); + }); + }); + it('marks array as modified when initializing non-array from db (gh-2442)', function(done) { var s1 = new Schema({ array: mongoose.Schema.Types.Mixed From 4c88f0ef8f6fcceabbf65d9e9b93004f2135fa03 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 May 2016 13:57:39 -0700 Subject: [PATCH 0574/2240] chore: release 4.4.19 --- History.md | 4 ++ bin/mongoose.js | 146 +++++++++++++++++++++++++++++++++++------------- package.json | 2 +- 3 files changed, 112 insertions(+), 40 deletions(-) diff --git a/History.md b/History.md index 048777dac0e..31ff49d6527 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +4.4.19 / 2016-05-21 +=================== + * fix(model): handle insertMany if timestamps not set #4171 + 4.4.18 / 2016-05-21 =================== * docs: add missing period #4170 [gitname](https://github.com/gitname) diff --git a/bin/mongoose.js b/bin/mongoose.js index e9b0e539cd3..d12af61e179 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -21109,93 +21109,161 @@ Kareem.prototype.execPre = function(name, context, callback) { next(); }; -Kareem.prototype.execPost = function(name, context, args, callback) { +Kareem.prototype.execPreSync = function(name, context) { + var pres = this._pres[name] || []; + var numPres = pres.length; + + for (var i = 0; i < numPres; ++i) { + pres[i].fn.call(context); + } +}; + +Kareem.prototype.execPost = function(name, context, args, options, callback) { + if (arguments.length < 5) { + callback = options; + options = null; + } var posts = this._posts[name] || []; var numPosts = posts.length; var currentPost = 0; + var firstError = null; + if (options && options.error) { + firstError = options.error; + } + if (!numPosts) { return process.nextTick(function() { - callback.apply(null, [null].concat(args)); + callback.apply(null, [firstError].concat(args)); }); } var next = function() { var post = posts[currentPost]; - if (post.length > args.length) { - post.apply(context, args.concat(function(error) { - if (error) { - return callback(error); + if (firstError) { + if (post.length === args.length + 2) { + post.apply(context, [firstError].concat(args).concat(function(error) { + if (error) { + firstError = error; + } + if (++currentPost >= numPosts) { + return callback.call(null, firstError); + } + next(); + })); + } else { + if (++currentPost >= numPosts) { + return callback.call(null, firstError); } + next(); + } + } else { + if (post.length === args.length + 1) { + post.apply(context, args.concat(function(error) { + if (error) { + firstError = error; + return next(); + } + + if (++currentPost >= numPosts) { + return callback.apply(null, [null].concat(args)); + } + + next(); + })); + } else { + post.apply(context, args); if (++currentPost >= numPosts) { return callback.apply(null, [null].concat(args)); } next(); - })); - } else { - post.apply(context, args); - - if (++currentPost >= numPosts) { - return callback.apply(null, [null].concat(args)); } - - next(); } }; next(); }; -Kareem.prototype.wrap = function(name, fn, context, args, useLegacyPost) { +Kareem.prototype.execPostSync = function(name, context) { + var posts = this._posts[name] || []; + var numPosts = posts.length; + + for (var i = 0; i < numPosts; ++i) { + posts[i].call(context); + } +}; + +function _handleWrapError(instance, error, name, context, args, options, callback) { + if (options.useErrorHandlers) { + var _options = { error: error }; + return instance.execPost(name, context, args, _options, function(error) { + return typeof callback === 'function' && callback(error); + }); + } else { + return typeof callback === 'function' ? + callback(error) : + undefined; + } +} + +Kareem.prototype.wrap = function(name, fn, context, args, options) { var lastArg = (args.length > 0 ? args[args.length - 1] : null); + var argsWithoutCb = typeof lastArg === 'function' ? + args.slice(1) : + args; var _this = this; + var useLegacyPost; + if (typeof options === 'object') { + useLegacyPost = options && options.useLegacyPost; + } else { + useLegacyPost = options; + } + options = options || {}; + this.execPre(name, context, function(error) { if (error) { - if (typeof lastArg === 'function') { - return lastArg(error); - } - return; + return _handleWrapError(_this, error, name, context, argsWithoutCb, + options, lastArg) } var end = (typeof lastArg === 'function' ? args.length - 1 : args.length); fn.apply(context, args.slice(0, end).concat(function() { + var argsWithoutError = Array.prototype.slice.call(arguments, 1); if (arguments[0]) { // Assume error - return typeof lastArg === 'function' ? - lastArg(arguments[0]) : - undefined; - } + return _handleWrapError(_this, arguments[0], name, context, + argsWithoutError, options, lastArg); + } else { + if (useLegacyPost && typeof lastArg === 'function') { + lastArg.apply(context, arguments); + } - if (useLegacyPost && typeof lastArg === 'function') { - lastArg.apply(context, arguments); - } + _this.execPost(name, context, argsWithoutError, function() { + if (arguments[0]) { + return typeof lastArg === 'function' ? + lastArg(arguments[0]) : + undefined; + } - var argsWithoutError = Array.prototype.slice.call(arguments, 1); - _this.execPost(name, context, argsWithoutError, function() { - if (arguments[0]) { - return typeof lastArg === 'function' ? - lastArg(arguments[0]) : + return typeof lastArg === 'function' && !useLegacyPost ? + lastArg.apply(context, arguments) : undefined; - } - - return typeof lastArg === 'function' && !useLegacyPost ? - lastArg.apply(context, arguments) : - undefined; - }); + }); + } })); }); }; -Kareem.prototype.createWrapper = function(name, fn, context) { +Kareem.prototype.createWrapper = function(name, fn, context, options) { var _this = this; return function() { var args = Array.prototype.slice.call(arguments); - _this.wrap(name, fn, context, args); + _this.wrap(name, fn, context, args, options); }; }; diff --git a/package.json b/package.json index ba6df07d78e..1620fb5cd4d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.18", + "version": "4.4.19", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From b4f4f19ee3801850599c6c5722edbc53d752ca95 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 22 May 2016 14:41:58 -0700 Subject: [PATCH 0575/2240] chore: now working on 4.4.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1620fb5cd4d..b2d04ba04bc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.19", + "version": "4.4.20-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c3afabdfc09d784070414777af42099052a4f9ef Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 22 May 2016 15:13:46 -0700 Subject: [PATCH 0576/2240] test(connection): refactor a bunch of assert calls re: #4122 --- test/collection.capped.test.js | 4 +- test/connection.auth.test.js | 4 +- test/connection.test.js | 232 ++++++++++++++++----------------- 3 files changed, 120 insertions(+), 120 deletions(-) diff --git a/test/collection.capped.test.js b/test/collection.capped.test.js index b3d84724ff5..db76aca06b8 100644 --- a/test/collection.capped.test.js +++ b/test/collection.capped.test.js @@ -32,7 +32,7 @@ describe('collections: capped:', function() { it('schemas should have option size', function(done) { assert.ok(capped.options.capped); - assert.equal(1000, capped.options.capped.size); + assert.equal(capped.options.capped.size, 1000); done(); }); it('creation', function(done) { @@ -57,7 +57,7 @@ describe('collections: capped:', function() { Capped.collection.options(function(err, options) { assert.ifError(err); assert.ok(options.capped, 'should create a capped collection'); - assert.equal(8192, options.size); + assert.equal(options.size, 8192); done(); }); }); diff --git a/test/connection.auth.test.js b/test/connection.auth.test.js index 10fe06928f4..86897c12cf0 100644 --- a/test/connection.auth.test.js +++ b/test/connection.auth.test.js @@ -9,7 +9,7 @@ describe('connection:', function() { conn._open = function() { assert.ok(conn.options); assert.ok(conn.options.auth); - assert.equal('users', conn.options.auth.authSource); + assert.equal(conn.options.auth.authSource, 'users'); conn.close(done); }; conn.open(start.uri + '?authSource=users'); @@ -20,7 +20,7 @@ describe('connection:', function() { conn._open = function() { assert.ok(conn.options); assert.ok(conn.options.auth); - assert.equal('users', conn.options.auth.authSource); + assert.equal(conn.options.auth.authSource, 'users'); conn.close(done); }; conn.open(start.uri, {auth: {authSource: 'users'}}); diff --git a/test/connection.test.js b/test/connection.test.js index 5cbf4d9481d..c145aad6615 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -16,7 +16,7 @@ describe('connections:', function() { it('should allow closing a closed connection', function(done) { var db = mongoose.createConnection(); - assert.equal(0, db.readyState); + assert.equal(db.readyState, 0); db.close(done); }); @@ -25,16 +25,16 @@ describe('connections:', function() { db.on('error', function() { }); assert.ok(db instanceof mongoose.Connection); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal(undefined, db.pass); - assert.equal(undefined, db.user); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27017, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.pass, undefined); + assert.equal(db.user, undefined); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27017); db.close(done); }); @@ -42,15 +42,15 @@ describe('connections:', function() { var db = mongoose.createConnection('mongodb://localhost/fake?replicaSet=rs0'); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal(undefined, db.pass); - assert.equal(undefined, db.user); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.pass, void 0); + assert.equal(db.user, void 0); assert.equal('fake', db.name); - assert.deepEqual([{host: 'localhost', port: 27017}], db.hosts); + assert.deepEqual(db.hosts, [{host: 'localhost', port: 27017}]); // Should be a replica set assert.ok(db.replica); @@ -62,11 +62,11 @@ describe('connections:', function() { var db = mongoose.createConnection('mongodb://localhost:27000/fake'); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(27000, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.port, 27000); db.close(); done(); }); @@ -75,16 +75,16 @@ describe('connections:', function() { var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake'); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('psw', db.pass); - assert.equal('aaron', db.user); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.pass, 'psw'); + assert.equal(db.user, 'aaron'); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); db.close(); done(); }); @@ -93,11 +93,11 @@ describe('connections:', function() { var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {db: {forceServerObjectId: true}}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); db.close(); done(); }); @@ -106,11 +106,11 @@ describe('connections:', function() { var db = mongoose.createConnection('mongodb://aaron:psw@localhost:27000/fake', {server: {auto_reconnect: false}}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); db.close(); done(); }); @@ -119,15 +119,15 @@ describe('connections:', function() { var db = mongoose.createConnection('mongodb://aaron:psw@/tmp/mongodb-27017.sock/fake', {server: {auto_reconnect: false}}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('/tmp/mongodb-27017.sock', db.host); - assert.equal('psw', db.pass); - assert.equal('aaron', db.user); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, '/tmp/mongodb-27017.sock'); + assert.equal(db.pass, 'psw'); + assert.equal(db.user, 'aaron'); db.close(); done(); }); @@ -255,28 +255,28 @@ describe('connections:', function() { var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, {server: {auto_reconnect: true}}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('faker', db.name); - assert.equal('127.0.0.1', db.host); - assert.equal(28000, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'faker'); + assert.equal(db.host, '127.0.0.1'); + assert.equal(db.port, 28000); db.close(); db = mongoose.createConnection('127.0.0.1', 'faker', {blah: 1}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('faker', db.name); - assert.equal('127.0.0.1', db.host); - assert.equal(27017, db.port); - assert.equal(1, db.options.blah); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'faker'); + assert.equal(db.host, '127.0.0.1'); + assert.equal(db.port, 27017); + assert.equal(db.options.blah, 1); db.close(); done(); }); @@ -285,16 +285,16 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'aaron', pass: 'psw'}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal('psw', db.pass); - assert.equal('aaron', db.user); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, 'psw'); + assert.equal(db.user, 'aaron'); db.close(); done(); }); @@ -303,16 +303,16 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'no_pass'}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal(undefined, db.pass); - assert.equal(undefined, db.user); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, undefined); + assert.equal(db.user, undefined); db.close(); done(); }); @@ -321,16 +321,16 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'no_pass', auth: {authMechanism: 'MONGODB-X509'}}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal(undefined, db.pass); - assert.equal('no_pass', db.user); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, undefined); + assert.equal(db.user, 'no_pass'); db.close(); done(); }); @@ -341,27 +341,27 @@ describe('connections:', function() { var db = mongoose.createConnection('127.0.0.1', 'faker', 28001); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('faker', db.name); - assert.equal('127.0.0.1', db.host); - assert.equal(28001, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'faker'); + assert.equal(db.host, '127.0.0.1'); + assert.equal(db.port, 28001); db.close(); db = mongoose.createConnection('127.0.0.1', 'faker'); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('faker', db.name); - assert.equal('127.0.0.1', db.host); - assert.equal(27017, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'faker'); + assert.equal(db.host, '127.0.0.1'); + assert.equal(db.port, 27017); db.close(); done(); }); From 0c3b95b89644ca42ccdce7a30edd87480cf4e326 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 23 May 2016 15:43:01 -0700 Subject: [PATCH 0577/2240] refactor(test): correct order for assert.equal calls in connection test re #4122 --- test/connection.test.js | 694 ++++++++++++++++++++-------------------- 1 file changed, 347 insertions(+), 347 deletions(-) diff --git a/test/connection.test.js b/test/connection.test.js index c145aad6615..987786dc6fe 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -324,7 +324,7 @@ describe('connections:', function() { assert.equal(typeof db.options, 'object'); assert.equal(typeof db.options.server, 'object'); assert.equal(db.options.server.auto_reconnect, true); - assert.equal(db.options.db, 'object'); + assert.equal(typeof db.options.db, 'object'); assert.equal(db.options.db.forceServerObjectId, false); assert.equal(db.name, 'fake'); assert.equal(db.host, 'localhost'); @@ -369,16 +369,16 @@ describe('connections:', function() { var db = mongoose.createConnection('aaron:psw@localhost', 'fake', 27000); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal('psw', db.pass); - assert.equal('aaron', db.user); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, 'psw'); + assert.equal(db.user, 'aaron'); db.close(); done(); }); @@ -398,35 +398,35 @@ describe('connections:', function() { db.on('error', function() { }); db.close(); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal('object', typeof db.options.server.socketOptions); - assert.equal('object', typeof db.options.db); - assert.equal('object', typeof db.options.replset); - assert.equal('object', typeof db.options.replset.socketOptions); - assert.equal(undefined, db.options.mongos); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal(2, db.options.server.poolSize); - assert.equal(false, db.options.server.slave_ok); - assert.equal(true, db.options.server.ssl); - assert.equal(true, db.options.replset.ssl); - assert.equal(10, db.options.server.socketOptions.socketTimeoutMS); - assert.equal(10, db.options.replset.socketOptions.socketTimeoutMS); - assert.equal(12, db.options.server.socketOptions.connectTimeoutMS); - assert.equal(12, db.options.replset.socketOptions.connectTimeoutMS); - assert.equal(10, db.options.replset.retries); - assert.equal(5, db.options.replset.reconnectWait); - assert.equal('replworld', db.options.replset.rs_name); - assert.equal(true, db.options.replset.read_secondary); - assert.equal(false, db.options.db.native_parser); - assert.equal(2, db.options.db.w); - assert.equal(true, db.options.db.safe); - assert.equal(true, db.options.db.fsync); - assert.equal(true, db.options.db.journal); - assert.equal(80, db.options.db.wtimeoutMS); - assert.equal('nearest', db.options.db.readPreference); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(typeof db.options.server.socketOptions, 'object'); + assert.equal(typeof db.options.db, 'object'); + assert.equal(typeof db.options.replset, 'object'); + assert.equal(typeof db.options.replset.socketOptions, 'object'); + assert.equal(db.options.mongos, undefined); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(db.options.server.poolSize, 2); + assert.equal(db.options.server.slave_ok, false); + assert.equal(db.options.server.ssl, true); + assert.equal(db.options.replset.ssl, true); + assert.equal(db.options.server.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.replset.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.server.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.retries, 10); + assert.equal(db.options.replset.reconnectWait, 5); + assert.equal(db.options.replset.rs_name, 'replworld'); + assert.equal(db.options.replset.read_secondary, true); + assert.equal(db.options.db.native_parser, false); + assert.equal(db.options.db.w, 2); + assert.equal(db.options.db.safe, true); + assert.equal(db.options.db.fsync, true); + assert.equal(db.options.db.journal, true); + assert.equal(db.options.db.wtimeoutMS, 80); + assert.equal(db.options.db.readPreference, 'nearest'); assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags); - assert.equal(false, db.options.db.forceServerObjectId); + assert.equal(db.options.db.forceServerObjectId, false); assert.strictEqual(db.options.server.sslValidate, true); done(); }); @@ -442,35 +442,35 @@ describe('connections:', function() { db.on('error', function() { }); db.close(); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal('object', typeof db.options.server.socketOptions); - assert.equal('object', typeof db.options.db); - assert.equal('object', typeof db.options.replset); - assert.equal('object', typeof db.options.replset.socketOptions); - assert.equal(undefined, db.options.mongos); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal(3, db.options.server.poolSize); - assert.equal(false, db.options.server.slave_ok); - assert.equal(true, db.options.server.ssl); - assert.equal(true, db.options.replset.ssl); - assert.equal(10, db.options.server.socketOptions.socketTimeoutMS); - assert.equal(10, db.options.replset.socketOptions.socketTimeoutMS); - assert.equal(12, db.options.server.socketOptions.connectTimeoutMS); - assert.equal(12, db.options.replset.socketOptions.connectTimeoutMS); - assert.equal(10, db.options.replset.retries); - assert.equal(5, db.options.replset.reconnectWait); - assert.equal('replworld', db.options.replset.rs_name); - assert.equal(true, db.options.replset.read_secondary); - assert.equal(false, db.options.db.native_parser); - assert.equal(2, db.options.db.w); - assert.equal(true, db.options.db.safe); - assert.equal(true, db.options.db.fsync); - assert.equal(true, db.options.db.journal); - assert.equal(80, db.options.db.wtimeoutMS); - assert.equal('nearest', db.options.db.readPreference); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(typeof db.options.server.socketOptions, 'object'); + assert.equal(typeof db.options.db, 'object'); + assert.equal(typeof db.options.replset, 'object'); + assert.equal(typeof db.options.replset.socketOptions, 'object'); + assert.equal(db.options.mongos, undefined); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(db.options.server.poolSize, 3); + assert.equal(db.options.server.slave_ok, false); + assert.equal(db.options.server.ssl, true); + assert.equal(db.options.replset.ssl, true); + assert.equal(db.options.server.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.replset.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.server.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.retries, 10); + assert.equal(db.options.replset.reconnectWait, 5); + assert.equal(db.options.replset.rs_name, 'replworld'); + assert.equal(db.options.replset.read_secondary, true); + assert.equal(db.options.db.native_parser, false); + assert.equal(db.options.db.w, 2); + assert.equal(db.options.db.safe, true); + assert.equal(db.options.db.fsync, true); + assert.equal(db.options.db.journal, true); + assert.equal(db.options.db.wtimeoutMS, 80); + assert.equal(db.options.db.readPreference, 'nearest'); assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags); - assert.equal(false, db.options.db.forceServerObjectId); + assert.equal(db.options.db.forceServerObjectId, false); done(); }); @@ -487,32 +487,32 @@ describe('connections:', function() { db.on('error', function() { }); db.close(); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal('object', typeof db.options.server.socketOptions); - assert.equal('object', typeof db.options.db); - assert.equal('object', typeof db.options.replset); - assert.equal('object', typeof db.options.replset.socketOptions); - assert.equal(undefined, db.options.mongos); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal(2, db.options.server.poolSize); - assert.equal(false, db.options.server.slave_ok); - assert.equal(true, db.options.server.ssl); - assert.equal(true, db.options.replset.ssl); - assert.equal(10, db.options.server.socketOptions.socketTimeoutMS); - assert.equal(10, db.options.replset.socketOptions.socketTimeoutMS); - assert.equal(12, db.options.server.socketOptions.connectTimeoutMS); - assert.equal(12, db.options.replset.socketOptions.connectTimeoutMS); - assert.equal(10, db.options.replset.retries); - assert.equal(5, db.options.replset.reconnectWait); - assert.equal(true, db.options.replset.read_secondary); - assert.equal(false, db.options.db.native_parser); - assert.equal(2, db.options.db.w); - assert.equal(true, db.options.db.safe); - assert.equal(true, db.options.db.fsync); - assert.equal(true, db.options.db.journal); - assert.equal(80, db.options.db.wtimeoutMS); - assert.equal(false, db.options.db.forceServerObjectId); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(typeof db.options.server.socketOptions, 'object'); + assert.equal(typeof db.options.db, 'object'); + assert.equal(typeof db.options.replset, 'object'); + assert.equal(typeof db.options.replset.socketOptions, 'object'); + assert.equal(db.options.mongos, undefined); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(db.options.server.poolSize, 2); + assert.equal(db.options.server.slave_ok, false); + assert.equal(db.options.server.ssl, true); + assert.equal(db.options.replset.ssl, true); + assert.equal(db.options.server.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.replset.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.server.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.retries, 10); + assert.equal(db.options.replset.reconnectWait, 5); + assert.equal(db.options.replset.read_secondary, true); + assert.equal(db.options.db.native_parser, false); + assert.equal(db.options.db.w, 2); + assert.equal(db.options.db.safe, true); + assert.equal(db.options.db.fsync, true); + assert.equal(db.options.db.journal, true); + assert.equal(db.options.db.wtimeoutMS, 80); + assert.equal(db.options.db.forceServerObjectId, false); done(); }); it('mixed with passed options', function(done) { @@ -525,32 +525,32 @@ describe('connections:', function() { db.on('error', function() { }); db.close(); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal('object', typeof db.options.server.socketOptions); - assert.equal('object', typeof db.options.db); - assert.equal('object', typeof db.options.replset); - assert.equal('object', typeof db.options.replset.socketOptions); - assert.equal(undefined, db.options.mongos); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal(80, db.options.db.wtimeoutMS); - assert.equal(2, db.options.server.poolSize); - assert.equal(false, db.options.server.slave_ok); - assert.equal(true, db.options.server.ssl); - assert.equal(true, db.options.replset.ssl); - assert.equal(10, db.options.server.socketOptions.socketTimeoutMS); - assert.equal(10, db.options.replset.socketOptions.socketTimeoutMS); - assert.equal(12, db.options.server.socketOptions.connectTimeoutMS); - assert.equal(12, db.options.replset.socketOptions.connectTimeoutMS); - assert.equal(10, db.options.replset.retries); - assert.equal(5, db.options.replset.reconnectWait); - assert.equal(true, db.options.replset.read_secondary); - assert.equal(false, db.options.db.native_parser); - assert.equal(3, db.options.db.w); - assert.equal(true, db.options.db.safe); - assert.equal(true, db.options.db.fsync); - assert.equal(true, db.options.db.journal); - assert.equal(false, db.options.db.forceServerObjectId); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(typeof db.options.server.socketOptions, 'object'); + assert.equal(typeof db.options.db, 'object'); + assert.equal(typeof db.options.replset, 'object'); + assert.equal(typeof db.options.replset.socketOptions, 'object'); + assert.equal(db.options.mongos, undefined); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(db.options.db.wtimeoutMS, 80); + assert.equal(db.options.server.poolSize, 2); + assert.equal(db.options.server.slave_ok, false); + assert.equal(db.options.server.ssl, true); + assert.equal(db.options.replset.ssl, true); + assert.equal(db.options.server.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.replset.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.server.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.retries, 10); + assert.equal(db.options.replset.reconnectWait, 5); + assert.equal(db.options.replset.read_secondary, true); + assert.equal(db.options.db.native_parser, false); + assert.equal(db.options.db.w, 3); + assert.equal(db.options.db.safe, true); + assert.equal(db.options.db.fsync, true); + assert.equal(db.options.db.journal, true); + assert.equal(db.options.db.forceServerObjectId, false); done(); }); }); @@ -566,36 +566,36 @@ describe('connections:', function() { var db = mongoose.createConnection(conn, {mongos: true}); db.on('error', done); db.close(); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal('object', typeof db.options.server.socketOptions); - assert.equal('object', typeof db.options.db); - assert.equal('object', typeof db.options.replset); - assert.equal('object', typeof db.options.replset.socketOptions); - assert.equal('object', typeof db.options.mongos); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal(2, db.options.server.poolSize); - assert.equal(false, db.options.server.slave_ok); - assert.equal(true, db.options.server.ssl); - assert.equal(true, db.options.replset.ssl); - assert.equal(true, db.options.mongos.ssl); - assert.equal(10, db.options.server.socketOptions.socketTimeoutMS); - assert.equal(10, db.options.replset.socketOptions.socketTimeoutMS); - assert.equal(12, db.options.server.socketOptions.connectTimeoutMS); - assert.equal(12, db.options.replset.socketOptions.connectTimeoutMS); - assert.equal(10, db.options.replset.retries); - assert.equal(5, db.options.replset.reconnectWait); - assert.equal('replworld', db.options.replset.rs_name); - assert.equal(true, db.options.replset.read_secondary); - assert.equal(false, db.options.db.native_parser); - assert.equal(2, db.options.db.w); - assert.equal(true, db.options.db.safe); - assert.equal(true, db.options.db.fsync); - assert.equal(true, db.options.db.journal); - assert.equal(80, db.options.db.wtimeoutMS); - assert.equal('nearest', db.options.db.readPreference); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(typeof db.options.server.socketOptions, 'object'); + assert.equal(typeof db.options.db, 'object'); + assert.equal(typeof db.options.replset, 'object'); + assert.equal(typeof db.options.replset.socketOptions, 'object'); + assert.equal(typeof db.options.mongos, 'object'); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(db.options.server.poolSize, 2); + assert.equal(db.options.server.slave_ok, false); + assert.equal(db.options.server.ssl, true); + assert.equal(db.options.replset.ssl, true); + assert.equal(db.options.mongos.ssl, true); + assert.equal(db.options.server.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.replset.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.server.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.retries, 10); + assert.equal(db.options.replset.reconnectWait, 5); + assert.equal(db.options.replset.rs_name, 'replworld'); + assert.equal(db.options.replset.read_secondary, true); + assert.equal(db.options.db.native_parser, false); + assert.equal(db.options.db.w, 2); + assert.equal(db.options.db.safe, true); + assert.equal(db.options.db.fsync, true); + assert.equal(db.options.db.journal, true); + assert.equal(db.options.db.wtimeoutMS, 80); + assert.equal(db.options.db.readPreference, 'nearest'); assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags); - assert.equal(false, db.options.db.forceServerObjectId); + assert.equal(db.options.db.forceServerObjectId, false); assert.strictEqual(db.options.server.sslValidate, true); assert.strictEqual(db.options.mongos.sslValidate, true); done(); @@ -658,40 +658,40 @@ describe('connections:', function() { var db = mongoose.createConnection(conn, {mongos: {w: 3, wtimeoutMS: 80}}); db.on('error', done); db.close(); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal('object', typeof db.options.server.socketOptions); - assert.equal('object', typeof db.options.db); - assert.equal('object', typeof db.options.replset); - assert.equal('object', typeof db.options.replset.socketOptions); - assert.equal('object', typeof db.options.mongos); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal(2, db.options.server.poolSize); - assert.equal(false, db.options.server.slave_ok); - assert.equal(true, db.options.server.ssl); - assert.equal(true, db.options.replset.ssl); - assert.equal(true, db.options.mongos.ssl); - assert.equal(10, db.options.server.socketOptions.socketTimeoutMS); - assert.equal(10, db.options.replset.socketOptions.socketTimeoutMS); - assert.equal(12, db.options.server.socketOptions.connectTimeoutMS); - assert.equal(12, db.options.replset.socketOptions.connectTimeoutMS); - assert.equal(10, db.options.replset.retries); - assert.equal(5, db.options.replset.reconnectWait); - assert.equal('replworld', db.options.replset.rs_name); - assert.equal(true, db.options.replset.read_secondary); - assert.equal(false, db.options.db.native_parser); - assert.equal(2, db.options.db.w); - assert.equal(true, db.options.db.safe); - assert.equal(true, db.options.db.fsync); - assert.equal(true, db.options.db.journal); - assert.equal(80, db.options.db.wtimeoutMS); - assert.equal('nearest', db.options.db.readPreference); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(typeof db.options.server.socketOptions, 'object'); + assert.equal(typeof db.options.db, 'object'); + assert.equal(typeof db.options.replset, 'object'); + assert.equal(typeof db.options.replset.socketOptions, 'object'); + assert.equal(typeof db.options.mongos, 'object'); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(db.options.server.poolSize, 2); + assert.equal(db.options.server.slave_ok, false); + assert.equal(db.options.server.ssl, true); + assert.equal(db.options.replset.ssl, true); + assert.equal(db.options.mongos.ssl, true); + assert.equal(db.options.server.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.replset.socketOptions.socketTimeoutMS, 10); + assert.equal(db.options.server.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.socketOptions.connectTimeoutMS, 12); + assert.equal(db.options.replset.retries, 10); + assert.equal(db.options.replset.reconnectWait, 5); + assert.equal(db.options.replset.rs_name, 'replworld'); + assert.equal(db.options.replset.read_secondary, true); + assert.equal(db.options.db.native_parser, false); + assert.equal(db.options.db.w, 2); + assert.equal(db.options.db.safe, true); + assert.equal(db.options.db.fsync, true); + assert.equal(db.options.db.journal, true); + assert.equal(db.options.db.wtimeoutMS, 80); + assert.equal(db.options.db.readPreference, 'nearest'); assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags); - assert.equal(false, db.options.db.forceServerObjectId); + assert.equal(db.options.db.forceServerObjectId, false); assert.strictEqual(db.options.server.sslValidate, true); assert.strictEqual(db.options.mongos.sslValidate, true); - assert.equal(db.options.mongos.w, 3); - assert.equal(db.options.mongos.wtimeoutMS, 80); + assert.equal(3, db.options.mongos.w); + assert.equal(80, db.options.mongos.wtimeoutMS); done(); }); }); @@ -705,11 +705,11 @@ describe('connections:', function() { db.on('error', function(err) { assert.ok(err); }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); db.close(); }); it('execute without user:pwd connection strings', function(done) { @@ -718,15 +718,15 @@ describe('connections:', function() { db.on('error', function(err) { assert.ok(err); }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal(undefined, db.user); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27017, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.user, undefined); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27017); db.close(); setTimeout(done, 10); }); @@ -742,54 +742,54 @@ describe('connections:', function() { var db = mongoose.createConnection('mongodb://u:p@localhost', function() { done(); }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('admin', db.name); - assert.equal('localhost', db.host); - assert.equal(27017, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'admin'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27017); db.close(); }); it('should fire when individual args are passed', function(done) { var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, {server: {auto_reconnect: false}}, function() { done(); }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('faker', db.name); - assert.equal('127.0.0.1', db.host); - assert.equal(28000, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'faker'); + assert.equal(db.host, '127.0.0.1'); + assert.equal(db.port, 28000); db.close(); }); it('should fire when no options are passed', function(done) { var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, function() { done(); }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('faker', db.name); - assert.equal('127.0.0.1', db.host); - assert.equal(28000, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'faker'); + assert.equal(db.host, '127.0.0.1'); + assert.equal(db.port, 28000); db.close(); }); it('should fire when default port utilized', function(done) { var db = mongoose.createConnection('127.0.0.1', 'faker', done); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('faker', db.name); - assert.equal('127.0.0.1', db.host); - assert.equal(27017, db.port); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'faker'); + assert.equal(db.host, '127.0.0.1'); + assert.equal(db.port, 27017); db.close(); }); }); @@ -827,7 +827,7 @@ describe('connections:', function() { assert.ok(MyModel.prototype.schema instanceof Schema); var m = new MyModel({name: 'aaron'}); - assert.equal('aaron', m.name); + assert.equal(m.name, 'aaron'); done(); }); @@ -905,8 +905,8 @@ describe('connections:', function() { mongoose.model('some-th-1458', new Schema({test: String}, {capped: {size: 1000, max: 10}})); var db = start(); var m = db.model('some-th-1458'); - assert.equal(m.collection.opts.capped.size, 1000); - assert.equal(m.collection.opts.capped.max, 10); + assert.equal(1000, m.collection.opts.capped.size); + assert.equal(10, m.collection.opts.capped.max); db.close(); done(); }); @@ -980,8 +980,8 @@ describe('connections:', function() { db.openSet('mongodb://aaron:psw@localhost:27000,b,c', {server: {auto_reconnect: false}}); db.on('error', function() { }); - assert.equal('aaron', db.user); - assert.equal('psw', db.pass); + assert.equal(db.user, 'aaron'); + assert.equal(db.pass, 'psw'); db.close(); done(); }); @@ -995,8 +995,8 @@ describe('connections:', function() { db.openSet('mongodb://aaron:psw@localhost:27000,b,c', {user: 'tester', pass: 'testpsw'}); db.on('error', function() { }); - assert.equal('tester', db.user); - assert.equal('testpsw', db.pass); + assert.equal(db.user, 'tester'); + assert.equal(db.pass, 'testpsw'); db.close(); done(); }); @@ -1007,17 +1007,17 @@ describe('connections:', function() { var db = mongoose.createConnection(url, {server: {auto_reconnect: false}}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(false, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, false); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); assert.ok(Array.isArray(db.hosts)); - assert.equal('/tmp/mongodb-27018.sock', db.hosts[0].ipc); - assert.equal('/tmp/mongodb-27019.sock', db.hosts[1].ipc); - assert.equal('psw', db.pass); - assert.equal('aaron', db.user); + assert.equal(db.hosts[0].ipc, '/tmp/mongodb-27018.sock'); + assert.equal(db.hosts[1].ipc, '/tmp/mongodb-27019.sock'); + assert.equal(db.pass, 'psw'); + assert.equal(db.user, 'aaron'); db.close(); done(); }); @@ -1075,7 +1075,7 @@ describe('connections:', function() { var s = m.connection.db.serverConfig; assert.ok(s instanceof mongoose.mongo.Mongos); - assert.equal(2, s.servers.length); + assert.equal(s.servers.length, 2); var M = m.model('TestMultipleMongos', {name: String}, 'test-multi-mongos-' + random()); M.create({name: 'works'}, function(err, d) { @@ -1083,7 +1083,7 @@ describe('connections:', function() { M.findOne({name: 'works'}, function(err, doc) { assert.ifError(err); - assert.equal(doc.id, d.id); + assert.equal(d.id, doc.id); m.disconnect(done); }); }); @@ -1103,15 +1103,15 @@ describe('connections:', function() { var names = db.modelNames(); assert.ok(Array.isArray(names)); - assert.equal(1, names.length); - assert.equal('something', names[0]); + assert.equal(names.length, 1); + assert.equal(names[0], 'something'); names = m.modelNames(); assert.ok(Array.isArray(names)); - assert.equal(3, names.length); - assert.equal('root', names[0]); - assert.equal('another', names[1]); - assert.equal('discriminated', names[2]); + assert.equal(names.length, 3); + assert.equal(names[0], 'root'); + assert.equal(names[1], 'another'); + assert.equal(names[2], 'discriminated'); db.close(done); }); @@ -1123,16 +1123,16 @@ describe('connections:', function() { var db2 = db.useDb('mongoose2'); - assert.equal(db2.name, 'mongoose2'); - assert.equal(db.name, 'mongoose1'); + assert.equal('mongoose2', db2.name); + assert.equal('mongoose1', db.name); - assert.equal(db.port, db2.port); - assert.equal(db.replica, db2.replica); - assert.equal(db.hosts, db2.hosts); - assert.equal(db.host, db2.host); - assert.equal(db.port, db2.port); - assert.equal(db.user, db2.user); - assert.equal(db.pass, db2.pass); + assert.equal(db2.port, db.port); + assert.equal(db2.replica, db.replica); + assert.equal(db2.hosts, db.hosts); + assert.equal(db2.host, db.host); + assert.equal(db2.port, db.port); + assert.equal(db2.user, db.user); + assert.equal(db2.pass, db.pass); assert.deepEqual(db.options, db2.options); db2.close(done); @@ -1157,13 +1157,13 @@ describe('connections:', function() { m1.findById(i1.id, function(err, item1) { assert.ifError(err); - assert.equal(item1.body, 'this is some text'); - assert.equal(item1.thing, 1); + assert.equal('this is some text', item1.body); + assert.equal(1, item1.thing); m2.findById(i2.id, function(err, item2) { assert.ifError(err); - assert.equal(item2.body, 'this is another body'); - assert.equal(item2.thing, 2); + assert.equal('this is another body', item2.body); + assert.equal(2, item2.thing); // validate the doc doesn't exist in the other db m1.findById(i2.id, function(err, nothing) { @@ -1346,18 +1346,18 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal(undefined, db.pass); - assert.equal(undefined, db.user); - - assert.equal(false, db.shouldAuthenticate()); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, undefined); + assert.equal(db.user, undefined); + + assert.equal(db.shouldAuthenticate(), false); db.close(); done(); @@ -1368,18 +1368,18 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {user: '', pass: ''}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal(undefined, db.pass); - assert.equal(undefined, db.user); - - assert.equal(false, db.shouldAuthenticate()); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, undefined); + assert.equal(db.user, undefined); + + assert.equal(db.shouldAuthenticate(), false); db.close(); done(); @@ -1390,18 +1390,18 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user'}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal(undefined, db.pass); - assert.equal(undefined, db.user); - - assert.equal(false, db.shouldAuthenticate()); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, undefined); + assert.equal(db.user, undefined); + + assert.equal(db.shouldAuthenticate(), false); db.close(); done(); @@ -1412,18 +1412,18 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user', pass: 'pass'}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal('pass', db.pass); - assert.equal('user', db.user); - - assert.equal(true, db.shouldAuthenticate()); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, 'pass'); + assert.equal(db.user, 'user'); + + assert.equal(db.shouldAuthenticate(), true); db.close(); done(); @@ -1436,18 +1436,18 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal(undefined, db.pass); - assert.equal(undefined, db.user); - - assert.equal(false, db.shouldAuthenticate()); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, undefined); + assert.equal(db.user, undefined); + + assert.equal(db.shouldAuthenticate(), false); db.close(); done(); @@ -1458,18 +1458,18 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user', auth: {authMechanism: 'MONGODB-X509'}}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal(undefined, db.pass); - assert.equal('user', db.user); - - assert.equal(true, db.shouldAuthenticate()); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, undefined); + assert.equal(db.user, 'user'); + + assert.equal(db.shouldAuthenticate(), true); db.close(); done(); @@ -1480,18 +1480,18 @@ describe('connections:', function() { var db = mongoose.createConnection('localhost', 'fake', 27000, {user: 'user', pass: 'pass', auth: {authMechanism: 'MONGODB-X509'}}); db.on('error', function() { }); - assert.equal('object', typeof db.options); - assert.equal('object', typeof db.options.server); - assert.equal(true, db.options.server.auto_reconnect); - assert.equal('object', typeof db.options.db); - assert.equal(false, db.options.db.forceServerObjectId); - assert.equal('fake', db.name); - assert.equal('localhost', db.host); - assert.equal(27000, db.port); - assert.equal('pass', db.pass); - assert.equal('user', db.user); - - assert.equal(true, db.shouldAuthenticate()); + assert.equal(typeof db.options, 'object'); + assert.equal(typeof db.options.server, 'object'); + assert.equal(db.options.server.auto_reconnect, true); + assert.equal(typeof db.options.db, 'object'); + assert.equal(db.options.db.forceServerObjectId, false); + assert.equal(db.name, 'fake'); + assert.equal(db.host, 'localhost'); + assert.equal(db.port, 27000); + assert.equal(db.pass, 'pass'); + assert.equal(db.user, 'user'); + + assert.equal(db.shouldAuthenticate(), true); db.close(); done(); From ec2e28ecd3a9f45fa083b12c07ba3d6ff9c68178 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 23 May 2016 15:49:38 -0700 Subject: [PATCH 0578/2240] refactor(test): correct assert.equals() param order for more test files re #4122 --- test/crash.test.js | 3 +- test/document.hooks.test.js | 48 ++++++++++++++++---------------- test/document.isselected.test.js | 2 +- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/test/crash.test.js b/test/crash.test.js index 40a25982561..6f3bb793c8a 100644 --- a/test/crash.test.js +++ b/test/crash.test.js @@ -25,7 +25,8 @@ describe('crash: (gh-407)', function() { db.close(done); try { - assert.equal('Cast to ObjectId failed for value "" at path "_id"', err.message); + assert.equal(err.message, + 'Cast to ObjectId failed for value "" at path "_id"'); } catch (er) { console.error(err); throw er; diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js index ec1ec5be8ef..633a7386cea 100644 --- a/test/document.hooks.test.js +++ b/test/document.hooks.test.js @@ -87,7 +87,7 @@ describe('document: hooks:', function() { steps++; setTimeout(function() { // make sure next step hasn't executed yet - assert.equal(1, steps); + assert.equal(steps, 1); next(); }, 50); }); @@ -100,9 +100,9 @@ describe('document: hooks:', function() { // parallel doc.$pre('hooksTest', true, function(next, done) { steps++; - assert.equal(3, steps); + assert.equal(steps, 3); setTimeout(function() { - assert.equal(4, steps); + assert.equal(steps, 4); }, 10); setTimeout(function() { steps++; @@ -114,7 +114,7 @@ describe('document: hooks:', function() { doc.$pre('hooksTest', true, function(next, done) { steps++; setTimeout(function() { - assert.equal(4, steps); + assert.equal(steps, 4); }, 10); setTimeout(function() { steps++; @@ -125,7 +125,7 @@ describe('document: hooks:', function() { doc.hooksTest(function(err) { assert.ifError(err); - assert.equal(6, steps); + assert.equal(steps, 6); done(); }); }); @@ -147,7 +147,7 @@ describe('document: hooks:', function() { doc.hooksTest(function(err) { assert.ifError(err); - assert.equal(2, steps); + assert.equal(steps, 2); done(); }); }); @@ -172,7 +172,7 @@ describe('document: hooks:', function() { doc.hooksTest(function(err) { assert.ifError(err); - assert.equal(2, steps); + assert.equal(steps, 2); done(); }); }); @@ -197,7 +197,7 @@ describe('document: hooks:', function() { doc.hooksTest(function(err) { assert.ok(err instanceof Error); - assert.equal(2, steps); + assert.equal(steps, 2); done(); }); }); @@ -223,7 +223,7 @@ describe('document: hooks:', function() { }); doc.set('test', 'me'); - assert.equal('altered-me', doc.test); + assert.equal(doc.test, 'altered-me'); done(); }); @@ -251,7 +251,7 @@ describe('document: hooks:', function() { doc.hooksTest(function(err) { assert.ok(err instanceof Error); - assert.equal(3, steps); + assert.equal(steps, 3); done(); }); }); @@ -264,7 +264,7 @@ describe('document: hooks:', function() { }); doc.hooksTest(function(err, args) { - assert.equal(2, args.length); + assert.equal(args.length, 2); assert.equal(args[1], 'test'); done(); }, 'test'); @@ -301,7 +301,7 @@ describe('document: hooks:', function() { S.findById(s.id, function(err, s) { db.close(); assert.ifError(err); - assert.equal('bye', s.e[0].text); + assert.equal(s.e[0].text, 'bye'); done(); }); }); @@ -333,7 +333,7 @@ describe('document: hooks:', function() { try { assert.ok(err); assert.ok(err.errors['e.0.text']); - assert.equal(false, presave); + assert.equal(presave, false); done(); } catch (e) { done(e); @@ -362,8 +362,8 @@ describe('document: hooks:', function() { var m = new M({sub: [{_id: 1}, {_id: 2}]}); m.save(function(err) { assert.ifError(err); - assert.equal(0, called.pre); - assert.equal(0, called.post); + assert.equal(called.pre, 0); + assert.equal(called.post, 0); M.findById(m, function(err1, doc) { assert.ifError(err1); @@ -371,27 +371,27 @@ describe('document: hooks:', function() { doc.sub.id(1).remove(); doc.save(function(err2) { assert.ifError(err2); - assert.equal(1, called.pre); - assert.equal(1, called.post); + assert.equal(called.pre, 1); + assert.equal(called.post, 1); // does not get called when not removed doc.name = 'changed1'; doc.save(function(err3) { assert.ifError(err3); - assert.equal(1, called.pre); - assert.equal(1, called.post); + assert.equal(called.pre, 1); + assert.equal(called.post, 1); doc.sub.id(2).remove(); doc.remove(function(err4) { assert.ifError(err4); - assert.equal(2, called.pre); - assert.equal(2, called.post); + assert.equal(called.pre, 2); + assert.equal(called.post, 2); // does not get called twice doc.remove(function(err5) { assert.ifError(err5); - assert.equal(2, called.pre); - assert.equal(2, called.post); + assert.equal(called.pre, 2); + assert.equal(called.post, 2); db.close(done); }); }); @@ -467,7 +467,7 @@ describe('document: hooks:', function() { m.save(function(err) { assert.ifError(err); - assert.equal(2, called.post); + assert.equal(called.post, 2); called.post = 0; M.findById(m, function(err, doc) { diff --git a/test/document.isselected.test.js b/test/document.isselected.test.js index 7ff0cd2e454..4e6b8513b5e 100644 --- a/test/document.isselected.test.js +++ b/test/document.isselected.test.js @@ -71,7 +71,7 @@ schema.path('nested.setr').set(function(v) { schema.path('date').set(function(v) { // should not have been cast to a Date yet - assert.equal('string', typeof v); + assert.equal(typeof v, 'string'); return v; }); From 2e0af3f34b3b8f975b86054f2014f0c96acb84b4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 23 May 2016 15:52:41 -0700 Subject: [PATCH 0579/2240] refactor(test): correct assert.equals() order for document.modified.test.js re #4122 --- test/document.modified.test.js | 100 ++++++++++++++++----------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/test/document.modified.test.js b/test/document.modified.test.js index 665520f0898..04cc443da41 100644 --- a/test/document.modified.test.js +++ b/test/document.modified.test.js @@ -91,7 +91,7 @@ describe('document modified', function() { B.findById(b, function(err2, b) { assert.strictEqual(null, err2); - assert.equal(2, b.numbers.length); + assert.equal(b.numbers.length, 2); db.close(); done(); @@ -110,8 +110,8 @@ describe('document modified', function() { db.close(); assert.strictEqual(null, err); var mFlag = post.comments[0].isModified('title'); - assert.equal(false, mFlag); - assert.equal(false, post.isModified('title')); + assert.equal(mFlag, false); + assert.equal(post.isModified('title'), false); done(); }); }); @@ -143,7 +143,7 @@ describe('document modified', function() { threw = true; } - assert.equal(false, threw); + assert.equal(threw, false); done(); }); @@ -159,15 +159,15 @@ describe('document modified', function() { date: new Date }); - assert.equal(false, post.isModified('title')); + assert.equal(post.isModified('title'), false); post.set('title', 'test'); - assert.equal(true, post.isModified('title')); + assert.equal(post.isModified('title'), true); - assert.equal(false, post.isModified('date')); + assert.equal(post.isModified('date'), false); post.set('date', new Date(post.date + 10)); - assert.equal(true, post.isModified('date')); + assert.equal(post.isModified('date'), true); - assert.equal(false, post.isModified('meta.date')); + assert.equal(post.isModified('meta.date'), false); done(); }); @@ -183,9 +183,9 @@ describe('document modified', function() { date: new Date }); - assert.equal(false, post.isModified('title')); + assert.equal(post.isModified('title'), false); post.set('title', 'Test'); - assert.equal(false, post.isModified('title')); + assert.equal(post.isModified('title'), false); done(); }); @@ -201,12 +201,12 @@ describe('document modified', function() { comments: [{title: 'Test', date: new Date, body: 'Test'}] }); - assert.equal(false, post.isModified('comments.0.title')); + assert.equal(post.isModified('comments.0.title'), false); post.get('comments')[0].set('title', 'Woot'); - assert.equal(true, post.isModified('comments')); - assert.equal(false, post.isDirectModified('comments')); - assert.equal(true, post.isModified('comments.0.title')); - assert.equal(true, post.isDirectModified('comments.0.title')); + assert.equal(post.isModified('comments'), true); + assert.equal(post.isDirectModified('comments'), false); + assert.equal(post.isModified('comments.0.title'), true); + assert.equal(post.isDirectModified('comments.0.title'), true); db.close(done); }); @@ -221,12 +221,12 @@ describe('document modified', function() { comments: [{title: 'Test', date: new Date, body: 'Test'}] }); - assert.equal(false, post.isModified('comments.0.body')); + assert.equal(post.isModified('comments.0.body'), false); post.get('comments')[0].body = 'Woot'; - assert.equal(true, post.isModified('comments')); - assert.equal(false, post.isDirectModified('comments')); - assert.equal(true, post.isModified('comments.0.body')); - assert.equal(true, post.isDirectModified('comments.0.body')); + assert.equal(post.isModified('comments'), true); + assert.equal(post.isDirectModified('comments'), false); + assert.equal(post.isModified('comments.0.body'), true); + assert.equal(post.isDirectModified('comments.0.body'), true); db.close(); done(); @@ -241,9 +241,9 @@ describe('document modified', function() { db.close(); var post = new BlogPost(); - assert.equal(false, post.isModified('owners')); + assert.equal(post.isModified('owners'), false); post.get('owners').push(new DocumentObjectId); - assert.equal(true, post.isModified('owners')); + assert.equal(post.isModified('owners'), true); done(); }); it('native methods', function(done) { @@ -253,7 +253,7 @@ describe('document modified', function() { db.close(); var post = new BlogPost; - assert.equal(false, post.isModified('owners')); + assert.equal(post.isModified('owners'), false); done(); }); }); @@ -287,24 +287,24 @@ describe('document modified', function() { assert.ifError(err); // set the same data again back to the document. // expected result, nothing should be set to modified - assert.equal(false, postRead.isModified('comments')); - assert.equal(false, postRead.isNew); + assert.equal(postRead.isModified('comments'), false); + assert.equal(postRead.isNew, false); postRead.set(postRead.toObject()); - assert.equal(false, postRead.isModified('title')); - assert.equal(false, postRead.isModified('slug')); - assert.equal(false, postRead.isModified('date')); - assert.equal(false, postRead.isModified('meta.date')); - assert.equal(false, postRead.isModified('meta.visitors')); - assert.equal(false, postRead.isModified('published')); - assert.equal(false, postRead.isModified('mixed')); - assert.equal(false, postRead.isModified('numbers')); - assert.equal(false, postRead.isModified('owners')); - assert.equal(false, postRead.isModified('comments')); + assert.equal(postRead.isModified('title'), false); + assert.equal(postRead.isModified('slug'), false); + assert.equal(postRead.isModified('date'), false); + assert.equal(postRead.isModified('meta.date'), false); + assert.equal(postRead.isModified('meta.visitors'), false); + assert.equal(postRead.isModified('published'), false); + assert.equal(postRead.isModified('mixed'), false); + assert.equal(postRead.isModified('numbers'), false); + assert.equal(postRead.isModified('owners'), false); + assert.equal(postRead.isModified('comments'), false); var arr = postRead.comments.slice(); arr[2] = postRead.comments.create({title: 'index'}); postRead.comments = arr; - assert.equal(true, postRead.isModified('comments')); + assert.equal(postRead.isModified('comments'), true); done(); }); }); @@ -335,7 +335,7 @@ describe('document modified', function() { var Child = db.model('gh-1530-2', childSchema); var p = new Parent(); - var c = new Child({name: 'Luke'}); + var c = new Child({ name: 'Luke' }); p.child = c; assert.equal(p.child.name, 'Luke'); @@ -347,8 +347,8 @@ describe('document modified', function() { assert.ifError(error); assert.ok(p.child); assert.ok(typeof p.child.name === 'undefined'); - assert.equal(0, preCalls); - assert.equal(0, postCalls); + assert.equal(preCalls, 0); + assert.equal(postCalls, 0); Child.findOne({name: 'Luke'}, function(error, child) { assert.ifError(error); assert.ok(!child); @@ -357,7 +357,7 @@ describe('document modified', function() { Child.findOne({name: 'Luke'}, function(error, child) { assert.ifError(error); assert.ok(child); - assert.equal(child._id.toString(), p.child.toString()); + assert.equal(p.child.toString(), child._id.toString()); db.close(done); }); }); @@ -380,7 +380,7 @@ describe('document modified', function() { var child = new Child({name: 'Mary'}); var p = new Parent({name: 'Alex', child: child}); - assert.equal(p.populated('child').toString(), child._id.toString()); + assert.equal(child._id.toString(), p.populated('child').toString()); db.close(done); }); @@ -407,7 +407,7 @@ describe('document modified', function() { var child = new Child({name: 'Luke'}); var p = new Parent({name: 'Anakin', children: [child]}); - assert.equal(p.children[0].name, 'Luke'); + assert.equal('Luke', p.children[0].name); assert.ok(p.populated('children')); done(); }); @@ -450,14 +450,14 @@ describe('document modified', function() { b.set(path, 3); assert.ok(b.isModified(path)); - assert.equal(3, b.get(path)); + assert.equal(b.get(path), 3); b = new BlogPost; b.init({mixed: {}}); path = 'mixed.9a'; b.set(path, 4); assert.ok(b.isModified(path)); - assert.equal(4, b.get(path)); + assert.equal(b.get(path), 4); b = new BlogPost({mixed: {}}); b.save(function(err) { @@ -466,13 +466,13 @@ describe('document modified', function() { path = 'mixed.9a.x'; b.set(path, 8); assert.ok(b.isModified(path)); - assert.equal(8, b.get(path)); + assert.equal(b.get(path), 8); b.save(function(err) { assert.ifError(err); BlogPost.findById(b, function(err, doc) { assert.ifError(err); - assert.equal(8, doc.get(path)); + assert.equal(doc.get(path), 8); db.close(done); }); }); @@ -502,13 +502,13 @@ describe('document modified', function() { function(error, p) { assert.ifError(error); assert.ok(p); - assert.equal(1, p.child.length); - assert.equal(1, p.child[0].grandChild.length); + assert.equal(p.child.length, 1); + assert.equal(p.child[0].grandChild.length, 1); p.child[0].grandChild[0].name = 'Jason'; assert.ok(p.isModified('child.0.grandChild.0.name')); p.save(function(error1, inDb) { assert.ifError(error1); - assert.equal('Jason', inDb.child[0].grandChild[0].name); + assert.equal(inDb.child[0].grandChild[0].name, 'Jason'); db.close(done); }); }); From 9024902db6e72925d3b1ea8fc317d006bbc60784 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 24 May 2016 07:22:23 -0700 Subject: [PATCH 0580/2240] refactor(test): correct more assert.equals() params re: #4122 --- test/document.populate.test.js | 70 ++++---- test/document.strict.test.js | 87 +++++----- test/document.test.js | 251 ++++++++++++++-------------- test/document.unit.test.js | 2 +- test/errors.validation.test.js | 2 +- test/harmony/document.test_.js | 17 +- test/harmony/model.test_.js | 19 ++- test/harmony/query.test_.js | 13 +- test/index.test.js | 53 +++--- test/model.aggregate.test.js | 16 +- test/model.create.test.js | 10 +- test/model.field.selection.test.js | 48 +++--- test/model.findAndRemoveOne.test.js | 95 +++++------ test/model.findOneAndUpdate.test.js | 244 +++++++++++++-------------- 14 files changed, 467 insertions(+), 460 deletions(-) diff --git a/test/document.populate.test.js b/test/document.populate.test.js index 26a5b03a36a..9bdffbc6ef9 100644 --- a/test/document.populate.test.js +++ b/test/document.populate.test.js @@ -147,17 +147,17 @@ describe('document.populate', function() { B.findById(post, function(err, post) { assert.ifError(err); post.populate('_creator'); - assert.equal(1, Object.keys(post.$__.populate).length); + assert.equal(Object.keys(post.$__.populate).length, 1); assert.ok('_creator' in post.$__.populate); post.populate('_creator'); - assert.equal(1, Object.keys(post.$__.populate).length); + assert.equal(Object.keys(post.$__.populate).length, 1); assert.ok('_creator' in post.$__.populate); post.populate('_creator fans'); - assert.equal(2, Object.keys(post.$__.populate).length); + assert.equal(Object.keys(post.$__.populate).length, 2); assert.ok('_creator' in post.$__.populate); assert.ok('fans' in post.$__.populate); post.populate({path: '_creator'}); - assert.equal(2, Object.keys(post.$__.populate).length); + assert.equal(Object.keys(post.$__.populate).length, 2); assert.ok('_creator' in post.$__.populate); assert.ok('fans' in post.$__.populate); done(); @@ -167,12 +167,12 @@ describe('document.populate', function() { B.findById(post, function(err, post) { assert.ifError(err); post.populate('_creator'); - assert.equal(1, Object.keys(post.$__.populate).length); - assert.equal(undefined, post.$__.populate._creator.select); + assert.equal(Object.keys(post.$__.populate).length, 1); + assert.equal(post.$__.populate._creator.select, undefined); post.populate({path: '_creator', select: 'name'}); - assert.equal(1, Object.keys(post.$__.populate).length); + assert.equal(Object.keys(post.$__.populate).length, 1); assert.ok('_creator' in post.$__.populate); - assert.equal('name', post.$__.populate._creator.select); + assert.equal(post.$__.populate._creator.select, 'name'); done(); }); }); @@ -187,7 +187,7 @@ describe('document.populate', function() { assert.ifError(err); assert.ok(!post.$__.populate); assert.ok(post._creator); - assert.equal(String(creator_id), String(post._creator._id)); + assert.equal(String(post._creator._id), String(creator_id)); done(); }); }); @@ -209,9 +209,9 @@ describe('document.populate', function() { post.populate('_creator fans', function(err) { assert.ifError(err); assert.ok(post._creator); - assert.equal(String(creator_id), String(post._creator._id)); - assert.equal(String(creator_id), String(post.fans[0]._id)); - assert.equal(String(alt_id), String(post.fans[1]._id)); + assert.equal(String(post._creator._id), String(creator_id)); + assert.equal(String(post.fans[0]._id), String(creator_id)); + assert.equal(String(post.fans[1]._id), String(alt_id)); done(); }); }); @@ -225,8 +225,8 @@ describe('document.populate', function() { post.populate('_creator').populate(function(err) { assert.ifError(err); assert.ok(post._creator); - assert.equal(String(creator_id), String(post._creator._id)); - assert.equal(String(alt_id), String(post.fans[1])); + assert.equal(String(post._creator._id), String(creator_id)); + assert.equal(String(post.fans[1]), String(alt_id)); done(); }); }); @@ -243,10 +243,10 @@ describe('document.populate', function() { var alt_id = post.fans[1]; post.populate(param, function(err, post) { assert.ifError(err); - assert.equal(2, post.fans.length); - assert.equal(String(creator_id), String(post._creator._id)); - assert.equal(String(creator_id), String(post.fans[1]._id)); - assert.equal(String(alt_id), String(post.fans[0]._id)); + assert.equal(post.fans.length, 2); + assert.equal(String(post._creator._id), String(creator_id)); + assert.equal(String(post.fans[1]._id), String(creator_id)); + assert.equal(String(post.fans[0]._id), String(alt_id)); assert.ok(!post.fans[0].email); assert.ok(!post.fans[1].email); assert.ok(!post.fans[0].isInit('email')); @@ -270,10 +270,10 @@ describe('document.populate', function() { post.populate(param, function(err, post) { assert.ifError(err); - assert.equal(2, post.fans.length); - assert.equal(String(creator_id), String(post._creator._id)); - assert.equal(String(creator_id), String(post.fans[1]._id)); - assert.equal(String(alt_id), String(post.fans[0]._id)); + assert.equal(post.fans.length, 2); + assert.equal(String(post._creator._id), String(creator_id)); + assert.equal(String(post.fans[1]._id), String(creator_id)); + assert.equal(String(post.fans[0]._id), String(alt_id)); assert.ok(!post.fans[0].email); assert.ok(!post.fans[1].email); assert.ok(!post.fans[0].isInit('email')); @@ -295,10 +295,10 @@ describe('document.populate', function() { var alt_id = post.fans[1]; post.populate(param, function(err, post) { assert.ifError(err); - assert.equal(2, post.fans.length); - assert.equal(String(creator_id), String(post._creator._id)); - assert.equal(String(creator_id), String(post.fans[1]._id)); - assert.equal(String(alt_id), String(post.fans[0]._id)); + assert.equal(post.fans.length, 2); + assert.equal(String(post._creator._id), String(creator_id)); + assert.equal(String(post.fans[1]._id), String(creator_id)); + assert.equal(String(post.fans[0]._id), String(alt_id)); assert.ok(!post.fans[0].email); assert.ok(!post.fans[1].email); assert.ok(!post.fans[0].isInit('email')); @@ -321,7 +321,7 @@ describe('document.populate', function() { post.populate({path: 'idontexist', model: 'doc.populate.u'}, function(err, post) { assert.ifError(err); assert.ok(post); - assert.equal(post.get('idontexist')._id, user1._id.toString()); + assert.equal(user1._id.toString(), post.get('idontexist')._id); assert.equal(post.get('idontexist').name, 'Phoenix'); done(); }); @@ -385,7 +385,7 @@ describe('document.populate', function() { db.close(); assert.ifError(err); assert.ok(note.author); - assert.equal('alice', note.author._id); + assert.equal(note.author._id, 'alice'); assert.equal(note.author.name, 'Alice In Wonderland'); done(); }); @@ -419,7 +419,7 @@ describe('document.populate', function() { Note.findById(note.id, function(err, note) { assert.ifError(err); - assert.equal('alice', note.author); + assert.equal(note.author, 'alice'); note.populate('author', function(err, note) { db.close(); assert.ifError(err); @@ -459,8 +459,8 @@ describe('document.populate', function() { db.close(); assert.ifError(err); assert.ok(note.author); - assert.equal(2359, note.author._id); - assert.equal(note.author.name, 'Alice'); + assert.equal(note.author._id, 2359); + assert.equal('Alice', note.author.name); done(); }); }); @@ -473,9 +473,9 @@ describe('document.populate', function() { var id1 = post.comments[1]._creator; post.populate('comments._creator', function(err, post) { assert.ifError(err); - assert.equal(2, post.comments.length); - assert.equal(id0, post.comments[0]._creator.id); - assert.equal(id1, post.comments[1]._creator.id); + assert.equal(post.comments.length, 2); + assert.equal(post.comments[0]._creator.id, id0); + assert.equal(post.comments[1]._creator.id, id1); done(); }); }); @@ -487,7 +487,7 @@ describe('document.populate', function() { var b = new B({_creator: user1}); b.populate('_creator', function(err, b) { if (err) return done(err); - assert.equal('Phoenix', b._creator.name); + assert.equal(b._creator.name, 'Phoenix'); b.save(function(err) { assert.ifError(err); B.collection.findOne({_id: b._id}, function(err, b) { diff --git a/test/document.strict.test.js b/test/document.strict.test.js index 3ce92e3519e..9afa5398781 100644 --- a/test/document.strict.test.js +++ b/test/document.strict.test.js @@ -36,27 +36,27 @@ describe('document: strict mode:', function() { it('when creating models with non-strict schemas', function(done) { var l = new Lax({content: 'sample', rouge: 'data'}); - assert.equal(false, l.$__.strictMode); + assert.equal(l.$__.strictMode, false); var lo = l.toObject(); assert.ok('ts' in l); assert.ok('ts' in lo); - assert.equal('sample', l.content); - assert.equal('sample', lo.content); - assert.equal('data', l.rouge); - assert.equal('data', lo.rouge); + assert.equal(l.content, 'sample'); + assert.equal(lo.content, 'sample'); + assert.equal(l.rouge, 'data'); + assert.equal(lo.rouge, 'data'); done(); }); it('when creating models with strict schemas', function(done) { var s = new Strict({content: 'sample', rouge: 'data'}); - assert.equal(true, s.$__.strictMode); + assert.equal(s.$__.strictMode, true); var so = s.toObject(); assert.ok('ts' in s); assert.ok('ts' in so); - assert.equal('sample', s.content); - assert.equal('sample', so.content); + assert.equal(s.content, 'sample'); + assert.equal(so.content, 'sample'); assert.ok(!('rouge' in s)); assert.ok(!('rouge' in so)); assert.ok(!s.rouge); @@ -70,23 +70,23 @@ describe('document: strict mode:', function() { assert.ok(instance.$__.strictMode); instance = instance.toObject(); - assert.equal('sample', instance.content); + assert.equal(instance.content, 'sample'); assert.ok(!instance.rouge); assert.ok('ts' in instance); // hydrate works as normal, but supports the schema level flag. var s2 = new Strict({content: 'sample', rouge: 'data'}, false); - assert.equal(false, s2.$__.strictMode); + assert.equal(s2.$__.strictMode, false); s2 = s2.toObject(); assert.ok('ts' in s2); - assert.equal('sample', s2.content); + assert.equal(s2.content, 'sample'); assert.ok('rouge' in s2); // testing init var s3 = new Strict(); s3.init({content: 'sample', rouge: 'data'}); s3.toObject(); - assert.equal('sample', s3.content); + assert.equal(s3.content, 'sample'); assert.ok(!('rouge' in s3)); assert.ok(!s3.rouge); done(); @@ -95,7 +95,7 @@ describe('document: strict mode:', function() { it('when using Model#create', function(done) { // strict on create Strict.create({content: 'sample2', rouge: 'data'}, function(err, doc) { - assert.equal('sample2', doc.content); + assert.equal(doc.content, 'sample2'); assert.ok(!('rouge' in doc)); assert.ok(!doc.rouge); done(); @@ -124,13 +124,13 @@ describe('document: strict mode:', function() { var l = new Lax; l.set('name', {last: 'goose', hack: 'xx'}); l = l.toObject(); - assert.equal('goose', l.name.last); - assert.equal('xx', l.name.hack); + assert.equal(l.name.last, 'goose'); + assert.equal(l.name.hack, 'xx'); var s = new Strict; s.set({name: {last: 'goose', hack: 'xx'}}); s = s.toObject(); - assert.equal('goose', s.name.last); + assert.equal(s.name.last, 'goose'); assert.ok(!('hack' in s.name)); assert.ok(!s.name.hack); @@ -138,7 +138,7 @@ describe('document: strict mode:', function() { s.set('name', {last: 'goose', hack: 'xx'}); s.set('shouldnt.exist', ':('); s = s.toObject(); - assert.equal('goose', s.name.last); + assert.equal(s.name.last, 'goose'); assert.ok(!('hack' in s.name)); assert.ok(!s.name.hack); assert.ok(!s.shouldnt); @@ -162,17 +162,17 @@ describe('document: strict mode:', function() { var Strict = db.model('EmbeddedStrict', new Schema({dox: [strict]}, {strict: false}), 'embdoc' + random()); var l = new Lax({dox: [{content: 'sample', rouge: 'data'}]}); - assert.equal(false, l.dox[0].$__.strictMode); + assert.equal(l.dox[0].$__.strictMode, false); l = l.dox[0].toObject(); - assert.equal('sample', l.content); - assert.equal('data', l.rouge); + assert.equal(l.content, 'sample'); + assert.equal(l.rouge, 'data'); assert.ok(l.rouge); var s = new Strict({dox: [{content: 'sample', rouge: 'data'}]}); - assert.equal(true, s.dox[0].$__.strictMode); + assert.equal(s.dox[0].$__.strictMode, true); s = s.dox[0].toObject(); assert.ok('ts' in s); - assert.equal('sample', s.content); + assert.equal(s.content, 'sample'); assert.ok(!('rouge' in s)); assert.ok(!s.rouge); @@ -180,13 +180,13 @@ describe('document: strict mode:', function() { var s3 = new Strict(); s3.init({dox: [{content: 'sample', rouge: 'data'}]}); s3.toObject(); - assert.equal('sample', s3.dox[0].content); + assert.equal(s3.dox[0].content, 'sample'); assert.ok(!('rouge' in s3.dox[0])); assert.ok(!s3.dox[0].rouge); // strict on create Strict.create({dox: [{content: 'sample2', rouge: 'data'}]}, function(err, doc) { - assert.equal('sample2', doc.dox[0].content); + assert.equal(doc.dox[0].content, 'sample2'); assert.ok(!('rouge' in doc.dox[0])); assert.ok(!doc.dox[0].rouge); db.close(done); @@ -222,17 +222,17 @@ describe('document: strict mode:', function() { myvirtual: 'test' }); - assert.equal(0, getCount); - assert.equal(1, setCount); + assert.equal(getCount, 0); + assert.equal(setCount, 1); strictInstance.myvirtual = 'anotherone'; - assert.equal(0, getCount); - assert.equal(2, setCount); + assert.equal(getCount, 0); + assert.equal(setCount, 2); var temp = strictInstance.myvirtual; - assert.equal(typeof temp, 'string'); - assert.equal(1, getCount); - assert.equal(2, setCount); + assert.equal('string', typeof temp); + assert.equal(getCount, 1); + assert.equal(setCount, 2); db.close(done); }); @@ -255,15 +255,15 @@ describe('document: strict mode:', function() { assert.ifError(err); Strict.findById(doc._id, function(err, doc) { assert.ifError(err); - assert.equal(true, doc._doc.bool); - assert.equal(true, doc._doc.notInSchema); + assert.equal(doc._doc.bool, true); + assert.equal(doc._doc.notInSchema, true); doc.bool = undefined; doc.set('notInSchema', undefined, {strict: false}); doc.save(function() { Strict.findById(doc._id, function(err, doc) { assert.ifError(err); - assert.equal(undefined, doc._doc.bool); - assert.equal(undefined, doc._doc.notInSchema); + assert.equal(doc._doc.bool, undefined); + assert.equal(doc._doc.notInSchema, undefined); db.close(done); }); }); @@ -290,8 +290,8 @@ describe('document: strict mode:', function() { Strict.findById(doc._id, function(err, doc) { assert.ifError(err); - assert.equal(true, doc._doc.bool); - assert.equal(true, doc._doc.notInSchema); + assert.equal(doc._doc.bool, true); + assert.equal(doc._doc.notInSchema, true); Strict.update({_id: doc._id}, {$unset: {bool: 1, notInSchema: 1}}, {strict: false, w: 1}, function(err) { @@ -300,8 +300,8 @@ describe('document: strict mode:', function() { Strict.findById(doc._id, function(err, doc) { db.close(); assert.ifError(err); - assert.equal(undefined, doc._doc.bool); - assert.equal(undefined, doc._doc.notInSchema); + assert.equal(doc._doc.bool, undefined); + assert.equal(doc._doc.notInSchema, undefined); done(); }); }); @@ -328,8 +328,8 @@ describe('document: strict mode:', function() { Strict.findById(doc._id, function(err, doc) { assert.ifError(err); - assert.equal(true, doc._doc.bool); - assert.equal(true, doc._doc.notInSchema); + assert.equal(doc._doc.bool, true); + assert.equal(doc._doc.notInSchema, true); Strict.findOneAndUpdate({_id: doc._id}, {$unset: {bool: 1, notInSchema: 1}}, {strict: false, w: 1}, function(err) { @@ -337,8 +337,8 @@ describe('document: strict mode:', function() { Strict.findById(doc._id, function(err, doc) { assert.ifError(err); - assert.equal(undefined, doc._doc.bool); - assert.equal(undefined, doc._doc.notInSchema); + assert.equal(doc._doc.bool, undefined); + assert.equal(doc._doc.notInSchema, undefined); db.close(done); }); }); @@ -448,3 +448,4 @@ describe('document: strict mode:', function() { }); }); }); + diff --git a/test/document.test.js b/test/document.test.js index 8e4106149c2..03e4d141157 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -82,7 +82,7 @@ var dateSetterCalled = false; schema.path('date').set(function(v) { // should not have been cast to a Date yet if (v !== undefined) { - assert.equal('string', typeof v); + assert.equal(typeof v, 'string'); } dateSetterCalled = true; return v; @@ -129,14 +129,14 @@ describe('document', function() { } }); - assert.equal('test', doc.test); + assert.equal(doc.test, 'test'); assert.ok(doc.oids instanceof Array); assert.equal(doc.nested.age, 5); assert.equal(String(doc.nested.cool), '4c6c2d6240ced95d0e00003c'); - assert.equal(7, doc.nested.agePlus2); - assert.equal('5my path', doc.nested.path); + assert.equal(doc.nested.agePlus2, 7); + assert.equal(doc.nested.path, '5my path'); doc.nested.setAge = 10; - assert.equal(10, doc.nested.age); + assert.equal(doc.nested.age, 10); doc.nested.setr = 'set it'; assert.equal(doc.getValue('nested.setr'), 'set it setter'); @@ -151,7 +151,7 @@ describe('document', function() { } }); - assert.equal('toop', doc2.test); + assert.equal(doc2.test, 'toop'); assert.ok(doc2.oids instanceof Array); assert.equal(doc2.nested.age, 2); @@ -169,7 +169,7 @@ describe('document', function() { assert.equal(doc2.nested2.yup.nested2, undefined); assert.equal(doc2.nested2.yup.yup, undefined); assert.equal(doc2.nested2.yup.age, undefined); - assert.equal('object', typeof doc2.nested2.yup); + assert.equal(typeof doc2.nested2.yup, 'object'); doc2.nested2.yup = { age: 150, @@ -185,7 +185,7 @@ describe('document', function() { assert.equal(doc2.nested2.nested, 'y'); assert.equal(doc2.nested2.yup.nested, true); assert.equal(doc2.nested2.yup.yup, 'Yesiree'); - assert.equal(150, doc2.nested2.yup.age); + assert.equal(doc2.nested2.yup.age, 150); assert.equal(String(doc2.nested.cool), '4cf70857337498f95900001c'); @@ -206,18 +206,18 @@ describe('document', function() { assert.equal(doc.isModified('test'), false); doc.test = 'Woot'; - assert.equal('Woot', doc.test); - assert.equal(true, doc.isModified('test')); + assert.equal(doc.test, 'Woot'); + assert.equal(doc.isModified('test'), true); assert.equal(doc.isModified('nested.age'), false); doc.nested.age = 2; - assert.equal(2, doc.nested.age); + assert.equal(doc.nested.age, 2); assert.ok(doc.isModified('nested.age')); doc.nested = {path: 'overwrite the entire nested object'}; - assert.equal(undefined, doc.nested.age); - assert.equal(1, Object.keys(doc._doc.nested).length); - assert.equal('overwrite the entire nested object', doc.nested.path); + assert.equal(doc.nested.age, undefined); + assert.equal(Object.keys(doc._doc.nested).length, 1); + assert.equal(doc.nested.path, 'overwrite the entire nested object'); assert.ok(doc.isModified('nested')); done(); }); @@ -230,7 +230,7 @@ describe('document', function() { it('test shortcut of id hexString', function(done) { var doc = new TestDocument(); - assert.equal('string', typeof doc.id); + assert.equal(typeof doc.id, 'string'); done(); }); @@ -279,70 +279,70 @@ describe('document', function() { assert.equal(clone.test, 'test'); assert.ok(clone.oids instanceof Array); - assert.equal(5, clone.nested.age); + assert.equal(clone.nested.age, 5); assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); - assert.equal('5my path', clone.nested.path); - assert.equal(undefined, clone.nested.agePlus2); - assert.equal(undefined, clone.em[0].works); + assert.equal(clone.nested.path, '5my path'); + assert.equal(clone.nested.agePlus2, undefined); + assert.equal(clone.em[0].works, undefined); assert.ok(clone.date instanceof Date); clone = doc.toObject({virtuals: true}); - assert.equal('test', clone.test); + assert.equal(clone.test, 'test'); assert.ok(clone.oids instanceof Array); - assert.equal(5, clone.nested.age); + assert.equal(clone.nested.age, 5); assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); - assert.equal('my path', clone.nested.path); - assert.equal(7, clone.nested.agePlus2); + assert.equal(clone.nested.path, 'my path'); + assert.equal(clone.nested.agePlus2, 7); assert.equal(clone.em[0].works, 'em virtual works'); clone = doc.toObject({getters: true}); - assert.equal('test', clone.test); + assert.equal(clone.test, 'test'); assert.ok(clone.oids instanceof Array); - assert.equal(5, clone.nested.age); + assert.equal(clone.nested.age, 5); assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); - assert.equal('5my path', clone.nested.path); - assert.equal(7, clone.nested.agePlus2); - assert.equal('em virtual works', clone.em[0].works); + assert.equal(clone.nested.path, '5my path'); + assert.equal(clone.nested.agePlus2, 7); + assert.equal(clone.em[0].works, 'em virtual works'); // test toObject options doc.schema.options.toObject = {virtuals: true}; clone = doc.toObject({transform: false, virtuals: true}); - assert.equal('test', clone.test); + assert.equal(clone.test, 'test'); assert.ok(clone.oids instanceof Array); - assert.equal(5, clone.nested.age); + assert.equal(clone.nested.age, 5); assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); - assert.equal('my path', clone.nested.path); - assert.equal(7, clone.nested.agePlus2); - assert.equal('asdf', clone.em[0].title); + assert.equal(clone.nested.path, 'my path'); + assert.equal(clone.nested.agePlus2, 7); + assert.equal(clone.em[0].title, 'asdf'); delete doc.schema.options.toObject; // minimize clone = doc.toObject({minimize: true}); - assert.equal(undefined, clone.nested2); + assert.equal(clone.nested2, undefined); clone = doc.toObject({minimize: true, getters: true}); - assert.equal(undefined, clone.nested2); + assert.equal(clone.nested2, undefined); clone = doc.toObject({minimize: false}); - assert.equal('Object', clone.nested2.constructor.name); - assert.equal(1, Object.keys(clone.nested2).length); + assert.equal(clone.nested2.constructor.name, 'Object'); + assert.equal(Object.keys(clone.nested2).length, 1); clone = doc.toObject('2'); - assert.equal(undefined, clone.nested2); + assert.equal(clone.nested2, undefined); doc.schema.options.toObject = {minimize: false}; clone = doc.toObject({transform: false, minimize: false}); - assert.equal('Object', clone.nested2.constructor.name); - assert.equal(1, Object.keys(clone.nested2).length); + assert.equal(clone.nested2.constructor.name, 'Object'); + assert.equal(Object.keys(clone.nested2).length, 1); delete doc.schema.options.toObject; doc.schema.options.minimize = false; clone = doc.toObject(); - assert.equal('Object', clone.nested2.constructor.name); - assert.equal(1, Object.keys(clone.nested2).length); + assert.equal(clone.nested2.constructor.name, 'Object'); + assert.equal(Object.keys(clone.nested2).length, 1); doc.schema.options.minimize = true; clone = doc.toObject(); - assert.equal(undefined, clone.nested2); + assert.equal(clone.nested2, undefined); // transform doc.schema.options.toObject = {}; @@ -363,8 +363,8 @@ describe('document', function() { assert.ok(undefined === clone.em); assert.ok(undefined === clone.numbers); assert.ok(undefined === clone.oids); - assert.equal('test', clone.test); - assert.equal(5, clone.nested.age); + assert.equal(clone.test, 'test'); + assert.equal(clone.nested.age, 5); // transform with return value var out = {myid: doc._id.toString()}; @@ -383,12 +383,12 @@ describe('document', function() { // ignored transform with inline options clone = doc.toObject({x: 1, transform: false}); assert.ok(!('myid' in clone)); - assert.equal('test', clone.test); + assert.equal(clone.test, 'test'); assert.ok(clone.oids instanceof Array); - assert.equal(5, clone.nested.age); + assert.equal(clone.nested.age, 5); assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); - assert.equal('my path', clone.nested.path); - assert.equal('Object', clone.em[0].constructor.name); + assert.equal(clone.nested.path, 'my path'); + assert.equal(clone.em[0].constructor.name, 'Object'); // applied transform when inline transform is true clone = doc.toObject({x: 1}); @@ -405,7 +405,7 @@ describe('document', function() { transform: xform, fields: '_id em numbers oids nested' }); - assert.equal('test', doc.test); + assert.equal(doc.test, 'test'); assert.ok(undefined === clone.em); assert.ok(undefined === clone.numbers); assert.ok(undefined === clone.oids); @@ -573,10 +573,10 @@ describe('document', function() { }); var output = topic.toObject({transform: true}); - assert.equal('favorite foods', output.title); - assert.equal('a@b.co', output.email); - assert.equal('Val', output.followers[0].name); - assert.equal(undefined, output.followers[0].email); + assert.equal(output.title, 'favorite foods'); + assert.equal(output.email, 'a@b.co'); + assert.equal(output.followers[0].name, 'Val'); + assert.equal(output.followers[0].email, undefined); db.close(done); }); @@ -647,24 +647,24 @@ describe('document', function() { doc.schema.options.toJSON = {virtuals: true}; var clone = doc.toJSON(); - assert.equal('test', clone.test); + assert.equal(clone.test, 'test'); assert.ok(clone.oids instanceof Array); - assert.equal(5, clone.nested.age); + assert.equal(clone.nested.age, 5); assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); - assert.equal('my path', clone.nested.path); - assert.equal(7, clone.nested.agePlus2); - assert.equal('Object', clone.em[0].constructor.name); - assert.equal(0, Object.keys(clone.em[0]).length); + assert.equal(clone.nested.path, 'my path'); + assert.equal(clone.nested.agePlus2, 7); + assert.equal(clone.em[0].constructor.name, 'Object'); + assert.equal(Object.keys(clone.em[0]).length, 0); delete doc.schema.options.toJSON; delete path.casterConstructor.prototype.toJSON; doc.schema.options.toJSON = {minimize: false}; clone = doc.toJSON(); - assert.equal('Object', clone.nested2.constructor.name); - assert.equal(1, Object.keys(clone.nested2).length); + assert.equal(clone.nested2.constructor.name, 'Object'); + assert.equal(Object.keys(clone.nested2).length, 1); clone = doc.toJSON('8'); - assert.equal('Object', clone.nested2.constructor.name); - assert.equal(1, Object.keys(clone.nested2).length); + assert.equal(clone.nested2.constructor.name, 'Object'); + assert.equal(Object.keys(clone.nested2).length, 1); // gh-852 var arr = [doc], @@ -675,10 +675,10 @@ describe('document', function() { } catch (_) { err = true; } - assert.equal(false, err); + assert.equal(err, false); assert.ok(/nested2/.test(str)); - assert.equal('Object', clone.nested2.constructor.name); - assert.equal(1, Object.keys(clone.nested2).length); + assert.equal(clone.nested2.constructor.name, 'Object'); + assert.equal(Object.keys(clone.nested2).length, 1); // transform doc.schema.options.toJSON = {}; @@ -695,12 +695,12 @@ describe('document', function() { }; clone = doc.toJSON(); - assert.equal(doc.id, clone._id); + assert.equal(clone._id, doc.id); assert.ok(undefined === clone.em); assert.ok(undefined === clone.numbers); assert.ok(undefined === clone.oids); - assert.equal('test', clone.test); - assert.equal(5, clone.nested.age); + assert.equal(clone.test, 'test'); + assert.equal(clone.nested.age, 5); // transform with return value var out = {myid: doc._id.toString()}; @@ -719,12 +719,12 @@ describe('document', function() { // ignored transform with inline options clone = doc.toJSON({x: 1, transform: false}); assert.ok(!('myid' in clone)); - assert.equal('test', clone.test); + assert.equal(clone.test, 'test'); assert.ok(clone.oids instanceof Array); - assert.equal(5, clone.nested.age); + assert.equal(clone.nested.age, 5); assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); - assert.equal('my path', clone.nested.path); - assert.equal('Object', clone.em[0].constructor.name); + assert.equal(clone.nested.path, 'my path'); + assert.equal(clone.em[0].constructor.name, 'Object'); // applied transform when inline transform is true clone = doc.toJSON({x: 1}); @@ -741,7 +741,7 @@ describe('document', function() { transform: xform, fields: '_id em numbers oids nested' }); - assert.equal('test', doc.test); + assert.equal(doc.test, 'test'); assert.ok(undefined === clone.em); assert.ok(undefined === clone.numbers); assert.ok(undefined === clone.oids); @@ -761,7 +761,7 @@ describe('document', function() { // parse again var obj = JSON.parse(json); - assert.equal('woot', obj.test); + assert.equal(obj.test, 'woot'); assert.equal(obj._id, oidString); done(); }); @@ -814,10 +814,10 @@ describe('document', function() { d.save(function() { var oldUpdate = docs.update; docs.update = function(query, operation) { - assert.equal(1, Object.keys(query).length); - assert.equal(query._id, d._id); - assert.equal(1, Object.keys(operation).length); - assert.equal(1, Object.keys(operation.$set).length); + assert.equal(Object.keys(query).length, 1); + assert.equal(d._id, query._id); + assert.equal(Object.keys(operation).length, 1); + assert.equal(Object.keys(operation.$set).length, 1); assert.equal(operation.$set.text, 'A changed doc'); called = true; docs.update = oldUpdate; @@ -825,7 +825,7 @@ describe('document', function() { }; d.update({$set: {text: 'A changed doc'}}, function(err) { assert.ifError(err); - assert.equal(true, called); + assert.equal(called, true); db.close(done); }); }); @@ -873,28 +873,28 @@ describe('document', function() { db.close(); var p = new P({embed: [{name: 'peanut'}]}); - assert.equal('function', typeof p.embed[0].test); - assert.equal('function', typeof E.ten); - assert.equal('peanut butter', p.embed[0].test()); - assert.equal(10, E.ten()); + assert.equal(typeof p.embed[0].test, 'function'); + assert.equal(typeof E.ten, 'function'); + assert.equal(p.embed[0].test(), 'peanut butter'); + assert.equal(E.ten(), 10); // test push casting p = new P; p.embed.push({name: 'apple'}); - assert.equal('function', typeof p.embed[0].test); - assert.equal('function', typeof E.ten); - assert.equal('apple butter', p.embed[0].test()); + assert.equal(typeof p.embed[0].test, 'function'); + assert.equal(typeof E.ten, 'function'); + assert.equal(p.embed[0].test(), 'apple butter'); done(); }); it('setting a positional path does not cast value to array', function(done) { var doc = new TestDocument; doc.init({numbers: [1, 3]}); - assert.equal(1, doc.numbers[0]); - assert.equal(3, doc.numbers[1]); + assert.equal(doc.numbers[0], 1); + assert.equal(doc.numbers[1], 3); doc.set('numbers.1', 2); - assert.equal(1, doc.numbers[0]); - assert.equal(2, doc.numbers[1]); + assert.equal(doc.numbers[0], 1); + assert.equal(doc.numbers[1], 2); done(); }); @@ -928,7 +928,7 @@ describe('document', function() { new S({title: 'test'}); db.close(); - assert.equal(false, traced); + assert.equal(traced, false); done(); }); @@ -942,7 +942,7 @@ describe('document', function() { assert.ifError(err); T.findById(t).select('name').exec(function(err, t) { assert.ifError(err); - assert.equal(undefined, t.req); + assert.equal(t.req, void 0); t.name = 'wooo'; t.save(function(err) { assert.ifError(err); @@ -995,14 +995,14 @@ describe('document', function() { var m = new M({prop: 'gh891', nick: 'validation test'}); m.save(function(err) { assert.ifError(err); - assert.equal(true, called); + assert.equal(called, true); called = false; M.findById(m, 'nick', function(err, m) { - assert.equal(false, called); + assert.equal(called, false); assert.ifError(err); m.nick = 'gh-891'; m.save(function(err) { - assert.equal(false, called); + assert.equal(called, false); assert.ifError(err); db.close(done); }); @@ -1155,14 +1155,14 @@ describe('document', function() { var M = db.model('validateSchema-array2', schema, collection); var m = new M({name: 'gh1109-2', arr: [1]}); - assert.equal(false, called); + assert.equal(called, false); m.save(function(err) { - assert.equal('ValidationError: BAM', String(err)); - assert.equal(true, called); + assert.equal(String(err), 'ValidationError: BAM'); + assert.equal(called, true); m.arr.push(2); called = false; m.save(function(err) { - assert.equal(true, called); + assert.equal(called, true); assert.ifError(err); done(); }); @@ -1417,7 +1417,7 @@ describe('document', function() { it('works with undefined (gh-1892)', function(done) { var d = new TestDocument(); d.nested.setr = undefined; - assert.equal('undefined setter', d.nested.setr); + assert.equal(d.nested.setr, 'undefined setter'); dateSetterCalled = false; d.date = undefined; d.validate(function(err) { @@ -1440,16 +1440,16 @@ describe('document', function() { }); doc.set('nested', {path: 'overwrite the entire nested object'}); - assert.equal(undefined, doc.nested.age); - assert.equal(1, Object.keys(doc._doc.nested).length); - assert.equal('overwrite the entire nested object', doc.nested.path); + assert.equal(doc.nested.age, undefined); + assert.equal(Object.keys(doc._doc.nested).length, 1); + assert.equal(doc.nested.path, 'overwrite the entire nested object'); assert.ok(doc.isModified('nested')); // vs merging using doc.set(object) doc.set({test: 'Test', nested: {age: 4}}); - assert.equal('4overwrite the entire nested object', doc.nested.path); - assert.equal(4, doc.nested.age); - assert.equal(2, Object.keys(doc._doc.nested).length); + assert.equal(doc.nested.path, '4overwrite the entire nested object'); + assert.equal(doc.nested.age, 4); + assert.equal(Object.keys(doc._doc.nested).length, 2); assert.ok(doc.isModified('nested')); doc = new TestDocument(); @@ -1462,9 +1462,9 @@ describe('document', function() { // vs merging using doc.set(path, object, {merge: true}) doc.set('nested', {path: 'did not overwrite the nested object'}, {merge: true}); - assert.equal('5did not overwrite the nested object', doc.nested.path); - assert.equal(5, doc.nested.age); - assert.equal(3, Object.keys(doc._doc.nested).length); + assert.equal(doc.nested.path, '5did not overwrite the nested object'); + assert.equal(doc.nested.age, 5); + assert.equal(Object.keys(doc._doc.nested).length, 3); assert.ok(doc.isModified('nested')); doc = new TestDocument(); @@ -1482,16 +1482,16 @@ describe('document', function() { assert.ok(!doc.isModified('nested.age')); doc.nested = {path: 'overwrite the entire nested object', age: 5}; - assert.equal(5, doc.nested.age); - assert.equal(2, Object.keys(doc._doc.nested).length); - assert.equal('5overwrite the entire nested object', doc.nested.path); + assert.equal(doc.nested.age, 5); + assert.equal(Object.keys(doc._doc.nested).length, 2); + assert.equal(doc.nested.path, '5overwrite the entire nested object'); assert.ok(doc.isModified('nested')); doc.nested.deep = {x: 'Hank and Marie'}; - assert.equal(3, Object.keys(doc._doc.nested).length); - assert.equal('5overwrite the entire nested object', doc.nested.path); + assert.equal(Object.keys(doc._doc.nested).length, 3); + assert.equal(doc.nested.path, '5overwrite the entire nested object'); assert.ok(doc.isModified('nested')); - assert.equal('Hank and Marie', doc.nested.deep.x); + assert.equal(doc.nested.deep.x, 'Hank and Marie'); doc = new TestDocument(); doc.init({ @@ -1502,13 +1502,13 @@ describe('document', function() { }); doc.set('nested.deep', {x: 'Hank and Marie'}); - assert.equal(2, Object.keys(doc._doc.nested).length); - assert.equal(1, Object.keys(doc._doc.nested.deep).length); + assert.equal(Object.keys(doc._doc.nested).length, 2); + assert.equal(Object.keys(doc._doc.nested.deep).length, 1); assert.ok(doc.isModified('nested')); assert.ok(!doc.isModified('nested.path')); assert.ok(!doc.isModified('nested.age')); assert.ok(doc.isModified('nested.deep')); - assert.equal('Hank and Marie', doc.nested.deep.x); + assert.equal(doc.nested.deep.x, 'Hank and Marie'); done(); }); @@ -1532,8 +1532,8 @@ describe('document', function() { assert.ok(doc.schedule); assert.ok(doc.schedule.isMongooseDocumentArray); assert.ok(doc.schedule[0] instanceof EmbeddedDocument); - assert.equal(1100, doc.schedule[0].open); - assert.equal(1900, doc.schedule[0].close); + assert.equal(doc.schedule[0].open, 1100); + assert.equal(doc.schedule[0].close, 1900); done(); }); @@ -1611,7 +1611,7 @@ describe('document', function() { assert.ifError(err); Parent.findOne({}, function(error, parent) { assert.ifError(error); - assert.equal(2, parent.children[0].counter); + assert.equal(parent.children[0].counter, 2); db.close(done); }); }); @@ -1669,7 +1669,7 @@ describe('document', function() { p.children = [c2]; p.save(function(error, doc) { assert.ifError(error); - assert.equal(1, doc.children.length); + assert.equal(doc.children.length, 1); db.close(done); }); }); @@ -1697,7 +1697,7 @@ describe('document', function() { // item.st is 3 but may not be saved to DB Item.findById(item._id, function(error, doc) { assert.ifError(error); - assert.equal(3, doc.st); + assert.equal(doc.st, 3); db.close(done); }); }); @@ -2714,3 +2714,4 @@ describe('document', function() { }); }); }); + diff --git a/test/document.unit.test.js b/test/document.unit.test.js index 3ad4319201d..6f491d3a201 100644 --- a/test/document.unit.test.js +++ b/test/document.unit.test.js @@ -23,7 +23,7 @@ describe('sharding', function() { d._doc = {date: currentTime}; d.$__storeShard(); - assert.equal(currentTime, d.$__.shardval.date); + assert.equal(d.$__.shardval.date, currentTime); done(); }); }); diff --git a/test/errors.validation.test.js b/test/errors.validation.test.js index 7c79e2e5e54..53435dbfe5f 100644 --- a/test/errors.validation.test.js +++ b/test/errors.validation.test.js @@ -192,7 +192,7 @@ describe('ValidationError', function() { var message = 'I had {BASE} and {TOPPING} for breakfast'; var result = ValidatorError.prototype.formatMessage(message, props); - assert.equal('I had eggs and bacon for breakfast', result); + assert.equal(result, 'I had eggs and bacon for breakfast'); done(); }); }); diff --git a/test/harmony/document.test_.js b/test/harmony/document.test_.js index 7c50c72a9fb..977037b7352 100644 --- a/test/harmony/document.test_.js +++ b/test/harmony/document.test_.js @@ -60,7 +60,7 @@ describe('Documents in ES6', function() { } assert.ok(!error); - assert.equal(true, called); + assert.equal(called, true); called = false; // The validator function above should now fail @@ -103,7 +103,7 @@ describe('Documents in ES6', function() { error = e; } assert.ifError(error); - assert.equal('eggs & bacon', result.description); + assert.equal(result.description, 'eggs & bacon'); // Should cause a validation error because `description` is required var badBreakfast = new Breakfast({}); @@ -158,7 +158,7 @@ describe('Documents in ES6', function() { error = e; } assert.ifError(error); - assert.equal(2, result.foods.length); + assert.equal(result.foods.length, 2); try { result = yield result.populate('foods').execPopulate(); @@ -166,9 +166,9 @@ describe('Documents in ES6', function() { error = e; } assert.ifError(error); - assert.equal(2, result.foods.length); - assert.equal('bacon', result.foods[0].name); - assert.equal('eggs', result.foods[1].name); + assert.equal(result.foods.length, 2); + assert.equal(result.foods[0].name, 'bacon'); + assert.equal(result.foods[1].name, 'eggs'); done(); })(); @@ -201,9 +201,10 @@ describe('Documents in ES6', function() { } assert.ifError(error); assert.equal(breakfast._id.toString(), result._id.toString()); - assert.equal('Ribeye', result.steak); - assert.equal('Scrambled', result.eggs); + assert.equal(result.steak, 'Ribeye'); + assert.equal(result.eggs, 'Scrambled'); done(); })(); }); }); + diff --git a/test/harmony/model.test_.js b/test/harmony/model.test_.js index 0c457f56e35..4a8464e7db8 100644 --- a/test/harmony/model.test_.js +++ b/test/harmony/model.test_.js @@ -52,9 +52,9 @@ describe('Models in ES6', function() { return done(e); } - assert.equal(2, results.length); - assert.equal('sunny-side up', results[0].eggs); - assert.equal('scrambled', results[1].eggs); + assert.equal(results.length, 2); + assert.equal(results[0].eggs, 'sunny-side up'); + assert.equal(results[1].eggs, 'scrambled'); done(); })(); @@ -87,11 +87,11 @@ describe('Models in ES6', function() { return done(e); } - assert.equal(2, results.length); - assert.equal(false, results[0]._id); - assert.equal('sunny-side up', results[0].eggs); - assert.equal(true, results[1]._id); - assert.equal('scrambled', results[1].eggs); + assert.equal(results.length, 2); + assert.equal(results[0]._id, false); + assert.equal(results[0].eggs, 'sunny-side up'); + assert.equal(results[1]._id, true); + assert.equal(results[1].eggs, 'scrambled'); done(); })(); @@ -125,7 +125,7 @@ describe('Models in ES6', function() { return done(e); } - assert.equal(2, results.length); + assert.equal(results.length, 2); assert.ok(results[0]._id === 'sunny-side up' || results[1]._id === 'sunny-side up'); assert.ok(results[0]._id === 'scrambled' || results[1]._id === 'scrambled'); @@ -133,3 +133,4 @@ describe('Models in ES6', function() { })(); }); }); + diff --git a/test/harmony/query.test_.js b/test/harmony/query.test_.js index 1b507ddf105..f637cad808c 100644 --- a/test/harmony/query.test_.js +++ b/test/harmony/query.test_.js @@ -54,7 +54,7 @@ describe('Queries in ES6', function() { return done(e); } - assert.equal(2, result.bacon); + assert.equal(result.bacon, 2); var results; try { @@ -63,9 +63,9 @@ describe('Queries in ES6', function() { return done(e); } - assert.equal(2, results.length); - assert.equal(2, results[0].bacon); - assert.equal(3, results[1].bacon); + assert.equal(results.length, 2); + assert.equal(results[0].bacon, 2); + assert.equal(results[1].bacon, 3); var count; try { @@ -74,7 +74,7 @@ describe('Queries in ES6', function() { return done(e); } - assert.equal(2, count); + assert.equal(count, 2); done(); })(); @@ -108,9 +108,10 @@ describe('Queries in ES6', function() { return done(e); } - assert.equal('Victor Hugo', result.author.name); + assert.equal(result.author.name, 'Victor Hugo'); done(); })(); }); }); + diff --git a/test/index.test.js b/test/index.test.js index 27c45cc1ea3..fab6e72b7bd 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -55,9 +55,9 @@ describe('mongoose module:', function() { mongoose.set('a', 'b'); mongoose.set('long option', 'c'); - assert.equal('b', mongoose.get('a')); - assert.equal('b', mongoose.set('a')); - assert.equal('c', mongoose.get('long option')); + assert.equal(mongoose.get('a'), 'b'); + assert.equal(mongoose.set('a'), 'b'); + assert.equal(mongoose.get('long option'), 'c'); done(); }); @@ -78,7 +78,7 @@ describe('mongoose module:', function() { mong.model('GlobalPlugins', schema); - assert.equal(2, called); + assert.equal(called, 2); done(); }); @@ -96,8 +96,8 @@ describe('mongoose module:', function() { function cb() { if (--pending) return; - assert.equal(2, connections); - assert.equal(2, disconnections); + assert.equal(connections, 2); + assert.equal(disconnections, 2); done(); } @@ -140,7 +140,7 @@ describe('mongoose module:', function() { mong.disconnect().connection. on('error', function(error) { - assert.equal('bam', error.message); + assert.equal(error.message, 'bam'); }); done(); @@ -184,7 +184,7 @@ describe('mongoose module:', function() { thrown = true; } - assert.equal(true, thrown); + assert.equal(thrown, true); done(); }); @@ -198,7 +198,7 @@ describe('mongoose module:', function() { var schema = new Schema({number: Number}); var Numbered = mongoose.model('Numbered', schema, collection); var n3 = new Numbered({number: 1234}); - assert.equal(1234, n3.number.valueOf()); + assert.equal(n3.number.valueOf(), 1234); done(); }); @@ -330,7 +330,7 @@ describe('mongoose module:', function() { Test.findById(test._id, function(err, doc) { assert.ifError(err); - assert.equal('aa', doc.test); + assert.equal(doc.test, 'aa'); mong.connection.close(); complete(); }); @@ -369,7 +369,7 @@ describe('mongoose module:', function() { Test.findById(test._id, function(err, doc) { assert.ifError(err); - assert.equal('aa', doc.test); + assert.equal(doc.test, 'aa'); conn.close(); complete(); }); @@ -387,22 +387,22 @@ describe('mongoose module:', function() { describe('exports', function() { function test(mongoose) { - assert.equal('string', typeof mongoose.version); - assert.equal('function', typeof mongoose.Mongoose); - assert.equal('function', typeof mongoose.Collection); - assert.equal('function', typeof mongoose.Connection); - assert.equal('function', typeof mongoose.Schema); + assert.equal(typeof mongoose.version, 'string'); + assert.equal(typeof mongoose.Mongoose, 'function'); + assert.equal(typeof mongoose.Collection, 'function'); + assert.equal(typeof mongoose.Connection, 'function'); + assert.equal(typeof mongoose.Schema, 'function'); assert.ok(mongoose.Schema.Types); - assert.equal('function', typeof mongoose.SchemaType); - assert.equal('function', typeof mongoose.Query); - assert.equal('function', typeof mongoose.Promise); - assert.equal('function', typeof mongoose.Model); - assert.equal('function', typeof mongoose.Document); - assert.equal('function', typeof mongoose.Error); - assert.equal('function', typeof mongoose.Error.CastError); - assert.equal('function', typeof mongoose.Error.ValidationError); - assert.equal('function', typeof mongoose.Error.ValidatorError); - assert.equal('function', typeof mongoose.Error.VersionError); + assert.equal(typeof mongoose.SchemaType, 'function'); + assert.equal(typeof mongoose.Query, 'function'); + assert.equal(typeof mongoose.Promise, 'function'); + assert.equal(typeof mongoose.Model, 'function'); + assert.equal(typeof mongoose.Document, 'function'); + assert.equal(typeof mongoose.Error, 'function'); + assert.equal(typeof mongoose.Error.CastError, 'function'); + assert.equal(typeof mongoose.Error.ValidationError, 'function'); + assert.equal(typeof mongoose.Error.ValidatorError, 'function'); + assert.equal(typeof mongoose.Error.VersionError, 'function'); } it('of module', function(done) { @@ -423,3 +423,4 @@ describe('mongoose module:', function() { }); }); }); + diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js index 6c3b3343803..076613d10a2 100644 --- a/test/model.aggregate.test.js +++ b/test/model.aggregate.test.js @@ -66,9 +66,9 @@ describe('model aggregate', function() { A.aggregate(group, project, function(err, res) { assert.ifError(err); assert.ok(res); - assert.equal(1, res.length); + assert.equal(res.length, 1); assert.ok('maxAge' in res[0]); - assert.equal(maxAge, res[0].maxAge); + assert.equal(res[0].maxAge, maxAge); done(); }); }); @@ -79,9 +79,9 @@ describe('model aggregate', function() { A.aggregate([group, project], function(err, res) { assert.ifError(err); assert.ok(res); - assert.equal(1, res.length); + assert.equal(res.length, 1); assert.ok('maxAge' in res[0]); - assert.equal(maxAge, res[0].maxAge); + assert.equal(res[0].maxAge, maxAge); done(); }); }); @@ -96,9 +96,9 @@ describe('model aggregate', function() { assert.ifError(err); assert.ok(promise instanceof mongoose.Promise); assert.ok(res); - assert.equal(1, res.length); + assert.equal(res.length, 1); assert.ok('maxAge' in res[0]); - assert.equal(maxAge, res[0].maxAge); + assert.equal(res[0].maxAge, maxAge); done(); }); }); @@ -114,7 +114,7 @@ describe('model aggregate', function() { promise.then(function(res) { assert.ok(promise instanceof mongoose.Promise); assert.ok(res); - assert.equal(1, res.length); + assert.equal(res.length, 1); assert.ok('maxAge' in res[0]); assert.equal(maxAge, res[0].maxAge); done(); @@ -142,7 +142,7 @@ describe('model aggregate', function() { assert.ifError(error); A.db.collection(outputCollection).find().toArray(function(error, documents) { assert.ifError(error); - assert.equal(1, documents.length); + assert.equal(documents.length, 1); assert.ok('maxAge' in documents[0]); assert.equal(maxAge, documents[0].maxAge); done(); diff --git a/test/model.create.test.js b/test/model.create.test.js index 5cb037c878d..32fc3a21291 100644 --- a/test/model.create.test.js +++ b/test/model.create.test.js @@ -123,7 +123,7 @@ describe('model', function() { it('with one doc', function(done) { var p = B.create({title: 'optional callback'}); p.then(function(doc) { - assert.equal('optional callback', doc.title); + assert.equal(doc.title, 'optional callback'); done(); }, done).end(); }); @@ -131,8 +131,8 @@ describe('model', function() { it('with more than one doc', function(done) { var p = B.create({title: 'optional callback 2'}, {title: 'orient expressions'}); p.then(function(doc1, doc2) { - assert.equal('optional callback 2', doc1.title); - assert.equal('orient expressions', doc2.title); + assert.equal(doc1.title, 'optional callback 2'); + assert.equal(doc2.title, 'orient expressions'); done(); }, done).end(); }); @@ -144,8 +144,8 @@ describe('model', function() { assert.equal(docs.length, 2); var doc1 = docs[0]; var doc2 = docs[1]; - assert.equal('optional callback3', doc1.title); - assert.equal('3', doc2.title); + assert.equal(doc1.title, 'optional callback3'); + assert.equal(doc2.title, '3'); done(); }, done).end(); }); diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js index 22fef8c88f3..2a6052d639e 100644 --- a/test/model.field.selection.test.js +++ b/test/model.field.selection.test.js @@ -71,13 +71,13 @@ describe('model field selection', function() { assert.strictEqual('kandinsky', found.def); assert.strictEqual('me', found.author); assert.strictEqual(true, Array.isArray(found.numbers)); - assert.equal(undefined, found.meta.date); + assert.equal(found.meta.date, undefined); assert.equal(found.numbers.length, 0); - assert.equal(undefined, found.owners); + assert.equal(found.owners, undefined); assert.strictEqual(true, Array.isArray(found.comments)); assert.equal(found.comments.length, 2); found.comments.forEach(function(comment) { - assert.equal(undefined, comment.user); + assert.equal(comment.user, undefined); }); done(); }); @@ -198,7 +198,7 @@ describe('model field selection', function() { assert.strictEqual('kandinsky', found.def); assert.strictEqual(undefined, found.author); assert.strictEqual(true, Array.isArray(found.comments)); - assert.equal(0, found.comments.length); + assert.equal(found.comments.length, 0); done(); }); }); @@ -215,13 +215,13 @@ describe('model field selection', function() { db.close(); assert.ifError(err); assert.ok(found); - assert.equal(found._id.toString(), doc._id.toString()); + assert.equal(doc._id.toString(), found._id.toString()); assert.strictEqual(undefined, found.title); assert.strictEqual(true, Array.isArray(found.comments)); found.comments.forEach(function(comment) { - assert.equal(undefined, comment.body); - assert.equal(undefined, comment.comments); - assert.equal(undefined, comment._id); + assert.equal(comment.body, undefined); + assert.equal(comment.comments, undefined); + assert.equal(comment._id, undefined); assert.ok(!!comment.title); }); done(); @@ -240,19 +240,19 @@ describe('model field selection', function() { db.close(); assert.ifError(err); assert.ok(found); - assert.equal(undefined, found._id); - assert.strictEqual('top', found.title); - assert.equal(undefined, found.numbers); + assert.equal(found._id, undefined); + assert.strictEqual(found.title, 'top'); + assert.equal(found.numbers, undefined); assert.strictEqual(true, Array.isArray(found.comments)); found.comments.forEach(function(comment) { - assert.equal(undefined, comment.title); - assert.equal('body', comment.body); - assert.strictEqual(true, Array.isArray(comment.comments)); + assert.equal(comment.title, undefined); + assert.equal(comment.body, 'body'); + assert.strictEqual(Array.isArray(comment.comments), true); assert.ok(comment._id); comment.comments.forEach(function(comment) { - assert.equal('c', comment.title); - assert.equal(undefined, comment.body); - assert.equal(undefined, comment.comments); + assert.equal(comment.title, 'c'); + assert.equal(comment.body, undefined); + assert.equal(comment.comments, undefined); assert.ok(comment._id); }); }); @@ -285,8 +285,8 @@ describe('model field selection', function() { assert.ifError(err); assert.ok(found); assert.equal(found.id, doc.id); - assert.equal(1, found.ids.length); - assert.equal(_id2.toString(), found.ids[0].toString()); + assert.equal(found.ids.length, 1); + assert.equal(found.ids[0].toString(), _id2.toString()); B .find({_id: doc._id}) @@ -296,8 +296,8 @@ describe('model field selection', function() { assert.ok(found.length); found = found[0]; assert.equal(found.id, doc.id); - assert.equal(1, found.ids.length); - assert.equal(_id2.toString(), found.ids[0].toString()); + assert.equal(found.ids.length, 1); + assert.equal(found.ids[0].toString(), _id2.toString()); db.close(done); }); }); @@ -325,8 +325,8 @@ describe('model field selection', function() { .select({ids2: {$elemMatch: {$in: [_id1.toString()]}}}) .exec(function(err, found) { assert.ifError(err); - assert.equal(1, found.ids.length); - assert.equal(1, found.ids2.length); + assert.equal(found.ids.length, 1); + assert.equal(found.ids2.length, 1); found.ids = []; found.ids2.set(0, _id2); found.save(function(err) { @@ -373,7 +373,7 @@ describe('model field selection', function() { M.findById(doc._id).select('comments').exec(function(err, found) { assert.ifError(err); assert.ok(Array.isArray(found.comments)); - assert.equal(1, found.comments.length); + assert.equal(found.comments.length, 1); assert.ok(Array.isArray(found.comments[0].comments)); db.close(done); }); diff --git a/test/model.findAndRemoveOne.test.js b/test/model.findAndRemoveOne.test.js index 4e496a167fb..d0e137b3e48 100644 --- a/test/model.findAndRemoveOne.test.js +++ b/test/model.findAndRemoveOne.test.js @@ -77,11 +77,11 @@ describe('model: findOneAndRemove:', function() { assert.ifError(err); M.findOneAndRemove({title: title}, function(err, doc) { assert.ifError(err); - assert.equal(doc.id, post.id); + assert.equal(post.id, doc.id); M.findById(post.id, function(err, gone) { db.close(); assert.ifError(err); - assert.equal(null, gone); + assert.equal(gone, null); done(); }); }); @@ -99,31 +99,31 @@ describe('model: findOneAndRemove:', function() { // Model.findOneAndRemove query = M.findOneAndRemove({author: 'aaron'}, {select: 'author'}); - assert.equal(1, query._fields.author); - assert.equal('aaron', query._conditions.author); + assert.equal(query._fields.author, 1); + assert.equal(query._conditions.author, 'aaron'); query = M.findOneAndRemove({author: 'aaron'}); - assert.equal(undefined, query._fields); - assert.equal('aaron', query._conditions.author); + assert.equal(query._fields, undefined); + assert.equal(query._conditions.author, 'aaron'); query = M.findOneAndRemove(); - assert.equal(undefined, query.options.new); - assert.equal(undefined, query._fields); - assert.equal(undefined, query._conditions.author); + assert.equal(query.options.new, undefined); + assert.equal(query._fields, undefined); + assert.equal(query._conditions.author, undefined); // Query.findOneAndRemove query = M.where('author', 'aaron').findOneAndRemove({date: now}); - assert.equal(undefined, query._fields); - assert.equal(now, query._conditions.date); - assert.equal('aaron', query._conditions.author); + assert.equal(query._fields, undefined); + assert.equal(query._conditions.date, now); + assert.equal(query._conditions.author, 'aaron'); query = M.find().findOneAndRemove({author: 'aaron'}, {select: 'author'}); - assert.equal(1, query._fields.author); - assert.equal('aaron', query._conditions.author); + assert.equal(query._fields.author, 1); + assert.equal(query._conditions.author, 'aaron'); query = M.find().findOneAndRemove(); - assert.equal(undefined, query._fields); - assert.equal(undefined, query._conditions.author); + assert.equal(query._fields, undefined); + assert.equal(query._conditions.author, undefined); done(); }); @@ -140,7 +140,7 @@ describe('model: findOneAndRemove:', function() { function cb(err, doc) { assert.ifError(err); - assert.equal(null, doc); // no previously existing doc + assert.equal(doc, null); // no previously existing doc if (--pending) return; db.close(); done(); @@ -192,7 +192,7 @@ describe('model: findByIdAndRemove:', function() { function cb(err, doc) { assert.ifError(err); - assert.equal(null, doc); // no previously existing doc + assert.equal(doc, null); // no previously existing doc if (--pending) return; db.close(); done(); @@ -209,11 +209,11 @@ describe('model: findByIdAndRemove:', function() { assert.ifError(err); M.findByIdAndRemove(post.id, function(err, doc) { assert.ifError(err); - assert.equal(doc.id, post.id); + assert.equal(post.id, doc.id); M.findById(post.id, function(err, gone) { db.close(); assert.ifError(err); - assert.equal(null, gone); + assert.equal(gone, null); done(); }); }); @@ -231,17 +231,17 @@ describe('model: findByIdAndRemove:', function() { // Model.findByIdAndRemove query = M.findByIdAndRemove(_id, {select: 'author'}); - assert.equal(1, query._fields.author); - assert.equal(_id.toString(), query._conditions._id.toString()); + assert.equal(query._fields.author, 1); + assert.equal(query._conditions._id.toString(), _id.toString()); query = M.findByIdAndRemove(_id.toString()); - assert.equal(undefined, query._fields); - assert.equal(_id.toString(), query._conditions._id); + assert.equal(query._fields, undefined); + assert.equal(query._conditions._id, _id.toString()); query = M.findByIdAndRemove(); - assert.equal(undefined, query.options.new); - assert.equal(undefined, query._fields); - assert.equal(undefined, query._conditions._id); + assert.equal(query.options.new, undefined); + assert.equal(query._fields, undefined); + assert.equal(query._conditions._id, undefined); done(); }); @@ -293,14 +293,14 @@ describe('model: findByIdAndRemove:', function() { var query; query = M.findByIdAndRemove(_id, {sort: 'author -title'}); - assert.equal(2, Object.keys(query.options.sort).length); - assert.equal(1, query.options.sort.author); - assert.equal(-1, query.options.sort.title); + assert.equal(Object.keys(query.options.sort).length, 2); + assert.equal(query.options.sort.author, 1); + assert.equal(query.options.sort.title, -1); query = M.findOneAndRemove({}, {sort: 'author -title'}); - assert.equal(2, Object.keys(query.options.sort).length); - assert.equal(1, query.options.sort.author); - assert.equal(-1, query.options.sort.title); + assert.equal(Object.keys(query.options.sort).length, 2); + assert.equal(query.options.sort.author, 1); + assert.equal(query.options.sort.title, -1); done(); }); @@ -312,14 +312,14 @@ describe('model: findByIdAndRemove:', function() { var query; query = M.findByIdAndRemove(_id, {sort: {author: 1, title: -1}}); - assert.equal(2, Object.keys(query.options.sort).length); - assert.equal(1, query.options.sort.author); - assert.equal(-1, query.options.sort.title); + assert.equal(Object.keys(query.options.sort).length, 2); + assert.equal(query.options.sort.author, 1); + assert.equal(query.options.sort.title, -1); query = M.findOneAndRemove(_id, {sort: {author: 1, title: -1}}); - assert.equal(2, Object.keys(query.options.sort).length); - assert.equal(1, query.options.sort.author); - assert.equal(-1, query.options.sort.title); + assert.equal(Object.keys(query.options.sort).length, 2); + assert.equal(query.options.sort.author, 1); + assert.equal(query.options.sort.title, -1); db.close(done); }); @@ -338,9 +338,9 @@ describe('model: findByIdAndRemove:', function() { .exec(function(err, doc) { if (err) return done(err); assert.ok(doc); - assert.equal(undefined, doc._id); + assert.equal(doc._id, undefined); assert.ok(doc.a); - assert.equal(doc.a.name, 'i am an A'); + assert.equal('i am an A', doc.a.name); db.close(done); }); }); @@ -387,9 +387,9 @@ describe('model: findByIdAndRemove:', function() { {}, function(error, breakfast) { assert.ifError(error); - assert.equal('eggs', breakfast.base); - assert.equal(1, preCount); - assert.equal(1, postCount); + assert.equal(breakfast.base, 'eggs'); + assert.equal(preCount, 1); + assert.equal(postCount, 1); done(); }); }); @@ -423,12 +423,13 @@ describe('model: findByIdAndRemove:', function() { findOneAndRemove({base: 'eggs'}, {}). exec(function(error, breakfast) { assert.ifError(error); - assert.equal('eggs', breakfast.base); - assert.equal(1, preCount); - assert.equal(1, postCount); + assert.equal(breakfast.base, 'eggs'); + assert.equal(preCount, 1); + assert.equal(postCount, 1); done(); }); }); }); }); }); + diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index dd8676b3bd6..b7d27f0b1ed 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -96,19 +96,19 @@ describe('model: findOneAndUpdate:', function() { assert.ifError(err); M.findById(post._id, function(err, cf) { assert.ifError(err); - assert.equal(title, cf.title); - assert.equal(author, cf.author); - assert.equal(0, cf.meta.visitors.valueOf()); - assert.equal(post.date.toString(), cf.date); - assert.equal(true, cf.published); - assert.equal('ex', cf.mixed.x); + assert.equal(cf.title, title); + assert.equal(cf.author, author); + assert.equal(cf.meta.visitors.valueOf(), 0); + assert.equal(cf.date, post.date.toString()); + assert.equal(cf.published, true); + assert.equal(cf.mixed.x, 'ex'); assert.deepEqual([4, 5, 6, 7], cf.numbers.toObject()); - assert.equal(2, cf.owners.length); - assert.equal(id0.toString(), cf.owners[0].toString()); - assert.equal(id1.toString(), cf.owners[1].toString()); - assert.equal(2, cf.comments.length); - assert.equal('been there', cf.comments[0].body); - assert.equal('done that', cf.comments[1].body); + assert.equal(cf.owners.length, 2); + assert.equal(cf.owners[0].toString(), id0.toString()); + assert.equal(cf.owners[1].toString(), id1.toString()); + assert.equal(cf.comments.length, 2); + assert.equal(cf.comments[0].body, 'been there'); + assert.equal(cf.comments[1].body, 'done that'); assert.ok(cf.comments[0]._id); assert.ok(cf.comments[1]._id); assert.ok(cf.comments[0]._id instanceof DocumentObjectId); @@ -127,20 +127,20 @@ describe('model: findOneAndUpdate:', function() { M.findOneAndUpdate({title: title}, update, {new: true}, function(err, up) { db.close(); - assert.equal(err, null, err && err.stack); - - assert.equal(newTitle, up.title); - assert.equal(author, up.author); - assert.equal(2, up.meta.visitors.valueOf()); - assert.equal(update.$set.date.toString(), up.date.toString()); - assert.equal(false, up.published); - assert.equal('ECKS', up.mixed.x); - assert.equal('why', up.mixed.y); + assert.equal(err && err.stack, err, null); + + assert.equal(up.title, newTitle); + assert.equal(up.author, author); + assert.equal(up.meta.visitors.valueOf(), 2); + assert.equal(up.date.toString(), update.$set.date.toString()); + assert.equal(up.published, false); + assert.equal(up.mixed.x, 'ECKS'); + assert.equal(up.mixed.y, 'why'); assert.deepEqual([5, 7], up.numbers.toObject()); - assert.equal(1, up.owners.length); - assert.equal(id1.toString(), up.owners[0].toString()); - assert.equal('been there', up.comments[0].body); - assert.equal('8', up.comments[1].body); + assert.equal(up.owners.length, 1); + assert.equal(up.owners[0].toString(), id1.toString()); + assert.equal(up.comments[0].body, 'been there'); + assert.equal(up.comments[1].body, '8'); assert.ok(up.comments[0]._id); assert.ok(up.comments[1]._id); assert.ok(up.comments[0]._id instanceof DocumentObjectId); @@ -259,18 +259,18 @@ describe('model: findOneAndUpdate:', function() { db.close(); assert.ifError(err); - assert.equal(post.title, up.title); - assert.equal(post.author, up.author); - assert.equal(post.meta.visitors, up.meta.visitors.valueOf()); - assert.equal(up.date.toString(), post.date.toString()); - assert.equal(up.published, post.published); - assert.equal(up.mixed.x, post.mixed.x); - assert.equal(up.mixed.y, post.mixed.y); + assert.equal(up.title, post.title); + assert.equal(up.author, post.author); + assert.equal(up.meta.visitors.valueOf(), post.meta.visitors); + assert.equal(post.date.toString(), up.date.toString()); + assert.equal(post.published, up.published); + assert.equal(post.mixed.x, up.mixed.x); + assert.equal(post.mixed.y, up.mixed.y); assert.deepEqual(up.numbers.toObject(), post.numbers.toObject()); - assert.equal(up.owners.length, post.owners.length); - assert.equal(up.owners[0].toString(), post.owners[0].toString()); - assert.equal(up.comments[0].body, post.comments[0].body); - assert.equal(up.comments[1].body, post.comments[1].body); + assert.equal(post.owners.length, up.owners.length); + assert.equal(post.owners[0].toString(), up.owners[0].toString()); + assert.equal(post.comments[0].body, up.comments[0].body); + assert.equal(post.comments[1].body, up.comments[1].body); assert.ok(up.comments[0]._id); assert.ok(up.comments[1]._id); assert.ok(up.comments[0]._id instanceof DocumentObjectId); @@ -315,10 +315,10 @@ describe('model: findOneAndUpdate:', function() { db.close(); assert.ifError(err); - assert.equal(newTitle, up.title); - assert.equal(2, up.meta.visitors.valueOf()); - assert.equal(up.date.toString(), update.$set.date.toString()); - assert.equal(update.published, up.published); + assert.equal(up.title, newTitle); + assert.equal(up.meta.visitors.valueOf(), 2); + assert.equal(update.$set.date.toString(), up.date.toString()); + assert.equal(up.published, update.published); assert.deepEqual(update.mixed.x, up.mixed.x); assert.strictEqual(up.mixed.y, update.mixed.y); assert.ok(Array.isArray(up.numbers)); @@ -342,43 +342,43 @@ describe('model: findOneAndUpdate:', function() { query = M.findOneAndUpdate({author: 'aaron'}, {$set: {date: now}}, {new: false, fields: 'author'}); assert.strictEqual(false, query.options.new); assert.strictEqual(1, query._fields.author); - assert.equal(now.toString(), query._update.$set.date.toString()); + assert.equal(query._update.$set.date.toString(), now.toString()); assert.strictEqual('aaron', query._conditions.author); query = M.findOneAndUpdate({author: 'aaron'}, {$set: {date: now}}); assert.strictEqual(undefined, query.options.new); - assert.equal(now.toString(), query._update.$set.date.toString()); + assert.equal(query._update.$set.date.toString(), now.toString()); assert.strictEqual('aaron', query._conditions.author); query = M.findOneAndUpdate({$set: {date: now}}); assert.strictEqual(undefined, query.options.new); - assert.equal(now.toString(), query._update.$set.date.toString()); + assert.equal(query._update.$set.date.toString(), now.toString()); assert.strictEqual(undefined, query._conditions.author); query = M.findOneAndUpdate(); assert.strictEqual(undefined, query.options.new); - assert.equal(undefined, query._update); + assert.equal(query._update, undefined); assert.strictEqual(undefined, query._conditions.author); // Query.findOneAndUpdate query = M.where('author', 'aaron').findOneAndUpdate({date: now}); assert.strictEqual(undefined, query.options.new); - assert.equal(now.toString(), query._update.date.toString()); + assert.equal(query._update.date.toString(), now.toString()); assert.strictEqual('aaron', query._conditions.author); query = M.find().findOneAndUpdate({author: 'aaron'}, {date: now}); assert.strictEqual(undefined, query.options.new); - assert.equal(now.toString(), query._update.date.toString()); + assert.equal(query._update.date.toString(), now.toString()); assert.strictEqual('aaron', query._conditions.author); query = M.find().findOneAndUpdate({date: now}); assert.strictEqual(undefined, query.options.new); - assert.equal(now.toString(), query._update.date.toString()); + assert.equal(query._update.date.toString(), now.toString()); assert.strictEqual(undefined, query._conditions.author); query = M.find().findOneAndUpdate(); assert.strictEqual(undefined, query.options.new); - assert.equal(undefined, query._update); + assert.equal(query._update, undefined); assert.strictEqual(undefined, query._conditions.author); done(); }); @@ -471,7 +471,7 @@ describe('model: findOneAndUpdate:', function() { BlogPost.findOne({_id: post.get('_id')}, function(err, doc) { db.close(); assert.ifError(err); - assert.equal(9, doc.get('meta.visitors')); + assert.equal(doc.get('meta.visitors'), 9); done(); }); } @@ -490,20 +490,20 @@ describe('model: findOneAndUpdate:', function() { assert.ifError(err); assert.ok(doc); assert.ok(doc._id); - assert.equal(undefined, doc.ignore); - assert.equal(undefined, doc._doc.ignore); - assert.equal(name, doc.name); + assert.equal(doc.ignore, undefined); + assert.equal(doc._doc.ignore, undefined); + assert.equal(doc.name, name); S.findOneAndUpdate({name: 'orange crush'}, {ignore: true}, {upsert: true}, function(err, doc) { assert.ifError(err); assert.ok(!doc.ignore); assert.ok(!doc._doc.ignore); - assert.equal('orange crush', doc.name); + assert.equal(doc.name, 'orange crush'); S.findOneAndUpdate({name: 'orange crush'}, {ignore: true}, function(err, doc) { db.close(); assert.ifError(err); assert.ok(!doc.ignore); assert.ok(!doc._doc.ignore); - assert.equal('orange crush', doc.name); + assert.equal(doc.name, 'orange crush'); done(); }); }); @@ -632,18 +632,18 @@ describe('model: findByIdAndUpdate:', function() { M.findByIdAndUpdate(post.id, update, {new: false}, function(err, up) { assert.ifError(err); - assert.equal(up.title, post.title); - assert.equal(up.author, post.author); - assert.equal(up.meta.visitors.valueOf(), post.meta.visitors); - assert.equal(up.date.toString(), post.date.toString()); - assert.equal(up.published, post.published); - assert.equal(up.mixed.x, post.mixed.x); + assert.equal(post.title, up.title); + assert.equal(post.author, up.author); + assert.equal(post.meta.visitors, up.meta.visitors.valueOf()); + assert.equal(post.date.toString(), up.date.toString()); + assert.equal(post.published, up.published); + assert.equal(post.mixed.x, up.mixed.x); assert.strictEqual(up.mixed.y, post.mixed.y); assert.deepEqual(up.numbers.toObject(), post.numbers.toObject()); - assert.equal(up.owners.length, post.owners.length); - assert.equal(up.owners[0].toString(), post.owners[0].toString()); - assert.equal(up.comments[0].body, post.comments[0].body); - assert.equal(up.comments[1].body, post.comments[1].body); + assert.equal(post.owners.length, up.owners.length); + assert.equal(post.owners[0].toString(), up.owners[0].toString()); + assert.equal(post.comments[0].body, up.comments[0].body); + assert.equal(post.comments[1].body, up.comments[1].body); assert.ok(up.comments[0]._id); assert.ok(up.comments[1]._id); assert.ok(up.comments[0]._id instanceof DocumentObjectId); @@ -666,12 +666,12 @@ describe('model: findByIdAndUpdate:', function() { query = M.findByIdAndUpdate(_id, {$set: {date: now}}, {new: false, fields: 'author'}); assert.strictEqual(false, query.options.new); assert.strictEqual(1, query._fields.author); - assert.equal(now.toString(), query._update.$set.date.toString()); + assert.equal(query._update.$set.date.toString(), now.toString()); assert.strictEqual(_id.toString(), query._conditions._id.toString()); query = M.findByIdAndUpdate(_id, {$set: {date: now}}); assert.strictEqual(undefined, query.options.new); - assert.equal(now.toString(), query._update.$set.date.toString()); + assert.equal(query._update.$set.date.toString(), now.toString()); assert.strictEqual(_id.toString(), query._conditions._id.toString()); query = M.findByIdAndUpdate(_id); @@ -680,7 +680,7 @@ describe('model: findByIdAndUpdate:', function() { query = M.findByIdAndUpdate(); assert.strictEqual(undefined, query.options.new); - assert.equal(undefined, query._update); + assert.equal(query._update, undefined); assert.strictEqual(undefined, query._conditions._id); db.close(done); }); @@ -730,14 +730,14 @@ describe('model: findByIdAndUpdate:', function() { var query; query = M.findByIdAndUpdate(_id, {$set: {date: now}}, {sort: 'author -title'}); - assert.equal(2, Object.keys(query.options.sort).length); - assert.equal(1, query.options.sort.author); - assert.equal(-1, query.options.sort.title); + assert.equal(Object.keys(query.options.sort).length, 2); + assert.equal(query.options.sort.author, 1); + assert.equal(query.options.sort.title, -1); query = M.findOneAndUpdate({}, {$set: {date: now}}, {sort: 'author -title'}); - assert.equal(2, Object.keys(query.options.sort).length); - assert.equal(1, query.options.sort.author); - assert.equal(-1, query.options.sort.title); + assert.equal(Object.keys(query.options.sort).length, 2); + assert.equal(query.options.sort.author, 1); + assert.equal(query.options.sort.title, -1); // gh-1887 M.create( @@ -755,7 +755,7 @@ describe('model: findByIdAndUpdate:', function() { if (err) { return done(err); } - assert.equal(10, doc.meta.visitors); + assert.equal(doc.meta.visitors, 10); db.close(done); }); }); @@ -770,14 +770,14 @@ describe('model: findByIdAndUpdate:', function() { query; query = M.findByIdAndUpdate(_id, {$set: {date: now}}, {sort: {author: 1, title: -1}}); - assert.equal(2, Object.keys(query.options.sort).length); - assert.equal(1, query.options.sort.author); - assert.equal(-1, query.options.sort.title); + assert.equal(Object.keys(query.options.sort).length, 2); + assert.equal(query.options.sort.author, 1); + assert.equal(query.options.sort.title, -1); query = M.findOneAndUpdate(_id, {$set: {date: now}}, {sort: {author: 1, title: -1}}); - assert.equal(2, Object.keys(query.options.sort).length); - assert.equal(1, query.options.sort.author); - assert.equal(-1, query.options.sort.title); + assert.equal(Object.keys(query.options.sort).length, 2); + assert.equal(query.options.sort.author, 1); + assert.equal(query.options.sort.title, -1); db.close(done); }); @@ -803,10 +803,10 @@ describe('model: findByIdAndUpdate:', function() { .exec(function(err, found) { assert.ifError(err); assert.ok(found); - assert.equal(found.id, doc.id); - assert.equal('woot', found.title); - assert.equal(1, found.ids.length); - assert.equal(_id2.toString(), found.ids[0].toString()); + assert.equal(doc.id, found.id); + assert.equal(found.title, 'woot'); + assert.equal(found.ids.length, 1); + assert.equal(found.ids[0].toString(), _id2.toString()); db.close(done); }); }); @@ -834,7 +834,7 @@ describe('model: findByIdAndUpdate:', function() { } assert.ok(doc); assert.ok(doc.a); - assert.equal(doc.a.name, 'i am an A'); + assert.equal('i am an A', doc.a.name); db.close(done); }); }); @@ -856,11 +856,11 @@ describe('model: findByIdAndUpdate:', function() { Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, new: false}).exec(function(err, thing) { assert.ifError(err); - assert.equal(null, thing); + assert.equal(thing, null); Thing.findOneAndUpdate({_id: key}, {$set: {flag: false}}, {upsert: true, new: false}).exec(function(err, thing2) { assert.ifError(err); - assert.equal(key, thing2.id); - assert.equal(false, thing2.flag); + assert.equal(thing2.id, key); + assert.equal(thing2.flag, false); db.close(done); }); }); @@ -885,7 +885,7 @@ describe('model: findByIdAndUpdate:', function() { return done(err); } assert.ok(doc); - assert.equal(doc.name, null); + assert.equal(null, doc.name); db.close(done); }); }); @@ -903,7 +903,7 @@ describe('model: findByIdAndUpdate:', function() { return done(err); } assert.ok(doc.change); - assert.equal(undefined, doc.name); + assert.equal(doc.name, undefined); db.close(done); }); }); @@ -964,7 +964,7 @@ describe('model: findByIdAndUpdate:', function() { {upsert: true, new: true}, function(error, doc) { assert.ifError(error); - assert.equal(0, doc.__v); + assert.equal(doc.__v, 0); db.close(done); }); }); @@ -984,8 +984,8 @@ describe('model: findByIdAndUpdate:', function() { assert.ifError(error); TestModel.findOne({}, function(error, doc) { assert.ifError(error); - assert.equal(1, doc.ticks.length); - assert.equal('coffee', doc.ticks[0].name); + assert.equal(doc.ticks.length, 1); + assert.equal(doc.ticks[0].name, 'coffee'); db.close(done); }); }); @@ -1081,8 +1081,8 @@ describe('model: findByIdAndUpdate:', function() { {}, function(error) { assert.ifError(error); - assert.equal(1, preCount); - assert.equal(1, postCount); + assert.equal(preCount, 1); + assert.equal(postCount, 1); done(); }); }); @@ -1109,8 +1109,8 @@ describe('model: findByIdAndUpdate:', function() { findOneAndUpdate({}, {base: 'eggs'}, {}). exec(function(error) { assert.ifError(error); - assert.equal(1, preCount); - assert.equal(1, postCount); + assert.equal(preCount, 1); + assert.equal(postCount, 1); done(); }); }); @@ -1133,11 +1133,11 @@ describe('model: findByIdAndUpdate:', function() { updateOptions, function(error, breakfast) { assert.ifError(error); - assert.equal('eggs', breakfast.base); - assert.equal('bacon', breakfast.topping); + assert.equal(breakfast.base, 'eggs'); + assert.equal(breakfast.topping, 'bacon'); Breakfast.count({topping: 'bacon'}, function(error, count) { assert.ifError(error); - assert.equal(count, 1); + assert.equal(1, count); db.close(done); }); }); @@ -1159,8 +1159,8 @@ describe('model: findByIdAndUpdate:', function() { updateOptions, function(error, breakfast) { assert.ifError(error); - assert.equal('eggs', breakfast.base); - assert.equal('sausage', breakfast.topping); + assert.equal(breakfast.base, 'eggs'); + assert.equal(breakfast.topping, 'sausage'); db.close(); done(); }); @@ -1182,11 +1182,11 @@ describe('model: findByIdAndUpdate:', function() { updateOptions, function(error, breakfast) { assert.ifError(error); - assert.equal('eggs', breakfast.base); - assert.equal('bacon', breakfast.topping); + assert.equal(breakfast.base, 'eggs'); + assert.equal(breakfast.topping, 'bacon'); Breakfast.count({topping: 'bacon'}, function(error, count) { assert.ifError(error); - assert.equal(count, 1); + assert.equal(1, count); db.close(done); }); }); @@ -1224,9 +1224,9 @@ describe('model: findByIdAndUpdate:', function() { function(error, breakfast) { assert.ok(!!error); assert.ok(!breakfast); - assert.equal(1, Object.keys(error.errors).length); - assert.equal('topping', Object.keys(error.errors)[0]); - assert.equal('Validator failed for path `topping` with value `bacon`', error.errors.topping.message); + assert.equal(Object.keys(error.errors).length, 1); + assert.equal(Object.keys(error.errors)[0], 'topping'); + assert.equal(error.errors.topping.message, 'Validator failed for path `topping` with value `bacon`'); assert.ok(!breakfast); db.close(); @@ -1255,11 +1255,11 @@ describe('model: findByIdAndUpdate:', function() { function(error, breakfast) { assert.ok(!!error); assert.ok(!breakfast); - assert.equal(2, Object.keys(error.errors).length); + assert.equal(Object.keys(error.errors).length, 2); assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1); assert.ok(Object.keys(error.errors).indexOf('steak') !== -1); - assert.equal('Validator failed for path `eggs` with value `softboiled`', error.errors.eggs.message); - assert.equal('Path `steak` is required.', error.errors.steak.message); + assert.equal(error.errors.eggs.message, 'Validator failed for path `eggs` with value `softboiled`'); + assert.equal(error.errors.steak.message, 'Path `steak` is required.'); db.close(); done(); }); @@ -1282,9 +1282,9 @@ describe('model: findByIdAndUpdate:', function() { updateOptions, function(error) { assert.ok(!!error); - assert.equal(1, Object.keys(error.errors).length); - assert.equal('eggs', Object.keys(error.errors)[0]); - assert.equal('Path `eggs` (3) is less than minimum allowed value (4).', error.errors.eggs.message); + assert.equal(Object.keys(error.errors).length, 1); + assert.equal(Object.keys(error.errors)[0], 'eggs'); + assert.equal(error.errors.eggs.message, 'Path `eggs` (3) is less than minimum allowed value (4).'); Breakfast.findOneAndUpdate( {}, @@ -1292,9 +1292,9 @@ describe('model: findByIdAndUpdate:', function() { updateOptions, function(error) { assert.ok(!!error); - assert.equal(1, Object.keys(error.errors).length); - assert.equal('steak', Object.keys(error.errors)[0]); - assert.equal('`tofu` is not a valid enum value for path `steak`.', error.errors.steak); + assert.equal(Object.keys(error.errors).length, 1); + assert.equal(Object.keys(error.errors)[0], 'steak'); + assert.equal(error.errors.steak, '`tofu` is not a valid enum value for path `steak`.'); Breakfast.findOneAndUpdate( {}, @@ -1302,9 +1302,9 @@ describe('model: findByIdAndUpdate:', function() { updateOptions, function(error) { assert.ok(!!error); - assert.equal(1, Object.keys(error.errors).length); - assert.equal('bacon', Object.keys(error.errors)[0]); - assert.equal('Path `bacon` is invalid (none).', error.errors.bacon.message); + assert.equal(Object.keys(error.errors).length, 1); + assert.equal(Object.keys(error.errors)[0], 'bacon'); + assert.equal(error.errors.bacon.message, 'Path `bacon` is invalid (none).'); db.close(); done(); @@ -1330,7 +1330,7 @@ describe('model: findByIdAndUpdate:', function() { updateOptions, function(error, breakfast) { assert.ok(!!error); - assert.equal(2, Object.keys(error.errors).length); + assert.equal(Object.keys(error.errors).length, 2); assert.ok(Object.keys(error.errors).indexOf('steak') !== -1); assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1); assert.ok(!breakfast); @@ -1356,7 +1356,7 @@ describe('model: findByIdAndUpdate:', function() { function(error, breakfast) { assert.ifError(error); assert.ok(!!breakfast); - assert.equal(1, breakfast.eggs); + assert.equal(breakfast.eggs, 1); db.close(done); }); }); From 309c2747d71e759950db7d5c956fa2cc32fa76e4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 24 May 2016 07:44:16 -0700 Subject: [PATCH 0581/2240] refactor(test): correct order for assert.equals() calls re #4122 --- test/model.geonear.test.js | 6 +- test/model.geosearch.test.js | 8 +- test/model.indexes.test.js | 12 +- test/model.mapreduce.test.js | 75 +++---- test/model.middleware.test.js | 57 +++--- test/model.populate.setting.test.js | 28 +-- test/model.populate.test.js | 124 ++++++------ test/model.query.casting.test.js | 44 ++-- test/model.querying.test.js | 292 +++++++++++++-------------- test/model.stream.test.js | 66 +++--- test/model.test.js | 302 ++++++++++++++-------------- 11 files changed, 508 insertions(+), 506 deletions(-) diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js index 8082fe348d0..2389bb07951 100644 --- a/test/model.geonear.test.js +++ b/test/model.geonear.test.js @@ -134,7 +134,7 @@ describe('model', function() { Geo.geoNear(pnt, {spherical: true, maxDistance: 300}, function(err, results) { assert.ifError(err); - assert.equal(1, results.length); + assert.equal(results.length, 1); assert.equal(results[0].obj.type, 'Point'); assert.equal(results[0].obj.coordinates.length, 2); @@ -187,7 +187,7 @@ describe('model', function() { Geo.geoNear(pnt, {spherical: true, maxDistance: 300, lean: true}, function(err, results) { assert.ifError(err); - assert.equal(1, results.length); + assert.equal(results.length, 1); assert.equal(results[0].obj.type, 'Point'); assert.equal(results[0].obj.coordinates.length, 2); @@ -266,7 +266,7 @@ describe('model', function() { }); function validate(ret, stat) { - assert.equal(1, ret.length); + assert.equal(ret.length, 1); assert.equal(ret[0].obj.coordinates[0], testLocations.MONGODB_NYC_OFFICE[0]); assert.equal(ret[0].obj.coordinates[1], testLocations.MONGODB_NYC_OFFICE[1]); assert.ok(stat); diff --git a/test/model.geosearch.test.js b/test/model.geosearch.test.js index 7bdda83e942..a58ebb15090 100644 --- a/test/model.geosearch.test.js +++ b/test/model.geosearch.test.js @@ -47,7 +47,7 @@ describe('model', function() { function next() { Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5}, function(err, results) { assert.ifError(err); - assert.equal(1, results.length); + assert.equal(results.length, 1); assert.equal(results[0].type, 'place'); assert.equal(results[0].pos.length, 2); @@ -58,7 +58,7 @@ describe('model', function() { Geo.geoSearch({type: 'place'}, {near: [40, 40], maxDistance: 5}, function(err, results) { assert.ifError(err); - assert.equal(0, results.length); + assert.equal(results.length, 0); db.close(done); }); }); @@ -90,7 +90,7 @@ describe('model', function() { function next() { Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5, lean: true}, function(err, results) { assert.ifError(err); - assert.equal(1, results.length); + assert.equal(results.length, 1); assert.equal(results[0].type, 'place'); assert.equal(results[0].pos.length, 2); @@ -161,7 +161,7 @@ describe('model', function() { promise = Geo.geoSearch({type: 'place'}, {near: [9, 9], maxDistance: 5}); }); function validate(ret, stat) { - assert.equal(1, ret.length); + assert.equal(ret.length, 1); assert.equal(ret[0].pos[0], 10); assert.equal(ret[0].pos[1], 10); assert.ok(stat); diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index 6e04a0b023e..890a74656f3 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -44,7 +44,7 @@ describe('model', function() { } }); - assert.equal(4, assertions); + assert.equal(assertions, 4); db.close(done); }); }); @@ -86,7 +86,7 @@ describe('model', function() { indexes[i].forEach(iter); } - assert.equal(3, assertions); + assert.equal(assertions, 3); db.close(done); }); }); @@ -135,7 +135,7 @@ describe('model', function() { indexes[i].forEach(iter); } - assert.equal(5, assertions); + assert.equal(assertions, 5); db.close(done); }); }); @@ -172,7 +172,7 @@ describe('model', function() { } db.close(); - assert.equal(2, found); + assert.equal(found, 2); done(); }); }); @@ -233,7 +233,7 @@ describe('model', function() { assert.ok(true, 'Model.ensureIndexes() was called'); Test.collection.getIndexes(function(err, indexes) { assert.ifError(err); - assert.equal(2, Object.keys(indexes).length); + assert.equal(Object.keys(indexes).length, 2); db.close(done); }); }); @@ -320,7 +320,7 @@ describe('model', function() { it('is a function', function(done) { var schema = mongoose.Schema({x: 'string'}); var Test = mongoose.createConnection().model('ensureIndexes-' + random, schema); - assert.equal('function', typeof Test.ensureIndexes); + assert.equal(typeof Test.ensureIndexes, 'function'); done(); }); diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js index d58ab1a4e1e..14f69a90d54 100644 --- a/test/model.mapreduce.test.js +++ b/test/model.mapreduce.test.js @@ -77,16 +77,16 @@ describe('model: mapreduce:', function() { assert.ok(stats); ret.forEach(function(res) { if (res._id === 'aaron') { - assert.equal(3, res.value); + assert.equal(res.value, 3); } if (res._id === 'guillermo') { - assert.equal(3, res.value); + assert.equal(res.value, 3); } if (res._id === 'brian') { - assert.equal(2, res.value); + assert.equal(res.value, 2); } if (res._id === 'nathan') { - assert.equal(2, res.value); + assert.equal(res.value, 2); } }); @@ -104,9 +104,9 @@ describe('model: mapreduce:', function() { assert.ifError(err); assert.ok(Array.isArray(ret)); - assert.equal(1, ret.length); - assert.equal('aaron', ret[0]._id); - assert.equal(3, ret[0].value); + assert.equal(ret.length, 1); + assert.equal(ret[0]._id, 'aaron'); + assert.equal(ret[0].value, 3); assert.ok(stats); modeling(); @@ -130,23 +130,23 @@ describe('model: mapreduce:', function() { // ret is a model assert.ok(!Array.isArray(ret)); - assert.equal('function', typeof ret.findOne); - assert.equal('function', typeof ret.mapReduce); + assert.equal(typeof ret.findOne, 'function'); + assert.equal(typeof ret.mapReduce, 'function'); // queries work ret.where('value.count').gt(1).sort({_id: 1}).exec(function(err, docs) { assert.ifError(err); - assert.equal('aaron', docs[0]._id); - assert.equal('brian', docs[1]._id); - assert.equal('guillermo', docs[2]._id); - assert.equal('nathan', docs[3]._id); + assert.equal(docs[0]._id, 'aaron'); + assert.equal(docs[1]._id, 'brian'); + assert.equal(docs[2]._id, 'guillermo'); + assert.equal(docs[3]._id, 'nathan'); // update casting works ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {new: true}, function(err, doc) { assert.ifError(err); assert.ok(doc); - assert.equal('aaron', doc._id); - assert.equal(true, doc.published); + assert.equal(doc._id, 'aaron'); + assert.equal(doc.published, true); // ad-hoc population works ret @@ -155,7 +155,7 @@ describe('model: mapreduce:', function() { .exec(function(err, doc) { db.close(); assert.ifError(err); - assert.equal('guillermo', doc.value.own.author); + assert.equal(doc.value.own.author, 'guillermo'); done(); }); }); @@ -179,7 +179,7 @@ describe('model: mapreduce:', function() { }; MR.mapReduce(o, function(err, results, stats) { - assert.equal('undefined', typeof stats); + assert.equal(typeof stats, 'undefined'); db.close(done); }); }); @@ -220,9 +220,9 @@ describe('model: mapreduce:', function() { function validate(ret, stats) { assert.ok(Array.isArray(ret)); - assert.equal(1, ret.length); - assert.equal('aaron', ret[0]._id); - assert.equal(6, ret[0].value); + assert.equal(ret.length, 1); + assert.equal(ret[0]._id, 'aaron'); + assert.equal(ret[0].value, 6); assert.ok(stats); } @@ -273,16 +273,16 @@ describe('model: mapreduce:', function() { assert.ok(stats); ret.forEach(function(res) { if (res._id === 'aaron') { - assert.equal(6, res.value); + assert.equal(res.value, 6); } if (res._id === 'guillermo') { - assert.equal(6, res.value); + assert.equal(res.value, 6); } if (res._id === 'brian') { - assert.equal(4, res.value); + assert.equal(res.value, 4); } if (res._id === 'nathan') { - assert.equal(4, res.value); + assert.equal(res.value, 4); } }); @@ -298,9 +298,9 @@ describe('model: mapreduce:', function() { MR.mapReduce(o).then(function(ret, stats) { assert.ok(Array.isArray(ret)); - assert.equal(1, ret.length); - assert.equal('aaron', ret[0]._id); - assert.equal(3, ret[0].value); + assert.equal(ret.length, 1); + assert.equal(ret[0]._id, 'aaron'); + assert.equal(ret[0].value, 3); assert.ok(stats); modeling(); }); @@ -321,23 +321,23 @@ describe('model: mapreduce:', function() { MR.mapReduce(o).then(function(ret) { // ret is a model assert.ok(!Array.isArray(ret)); - assert.equal('function', typeof ret.findOne); - assert.equal('function', typeof ret.mapReduce); + assert.equal(typeof ret.findOne, 'function'); + assert.equal(typeof ret.mapReduce, 'function'); // queries work ret.where('value.count').gt(1).sort({_id: 1}).exec(function(err, docs) { assert.ifError(err); - assert.equal('aaron', docs[0]._id); - assert.equal('brian', docs[1]._id); - assert.equal('guillermo', docs[2]._id); - assert.equal('nathan', docs[3]._id); + assert.equal(docs[0]._id, 'aaron'); + assert.equal(docs[1]._id, 'brian'); + assert.equal(docs[2]._id, 'guillermo'); + assert.equal(docs[3]._id, 'nathan'); // update casting works ret.findOneAndUpdate({_id: 'aaron'}, {published: true}, {new: true}, function(err, doc) { assert.ifError(err); assert.ok(doc); - assert.equal('aaron', doc._id); - assert.equal(true, doc.published); + assert.equal(doc._id, 'aaron'); + assert.equal(doc.published, true); // ad-hoc population works ret @@ -346,7 +346,7 @@ describe('model: mapreduce:', function() { .exec(function(err, doc) { db.close(); assert.ifError(err); - assert.equal('guillermo', doc.value.own.author); + assert.equal(doc.value.own.author, 'guillermo'); done(); }); }); @@ -370,8 +370,9 @@ describe('model: mapreduce:', function() { }; MR.mapReduce(o).then(function(results, stats) { - assert.equal('undefined', typeof stats); + assert.equal(typeof stats, 'undefined'); db.close(done); }); }); }); + diff --git a/test/model.middleware.test.js b/test/model.middleware.test.js index 92a2fbd9293..41f28e301bc 100644 --- a/test/model.middleware.test.js +++ b/test/model.middleware.test.js @@ -19,20 +19,20 @@ describe('model middleware', function() { schema.post('save', function(obj) { assert.equal(obj.title, 'Little Green Running Hood'); assert.equal(this.title, 'Little Green Running Hood'); - assert.equal(0, called); + assert.equal(called, 0); called++; }); schema.post('save', function(obj) { assert.equal(obj.title, 'Little Green Running Hood'); assert.equal(this.title, 'Little Green Running Hood'); - assert.equal(1, called); + assert.equal(called, 1); called++; }); schema.post('save', function(obj, next) { assert.equal(obj.title, 'Little Green Running Hood'); - assert.equal(2, called); + assert.equal(called, 2); called++; next(); }); @@ -45,7 +45,7 @@ describe('model middleware', function() { test.save(function(err) { assert.ifError(err); assert.equal(test.title, 'Little Green Running Hood'); - assert.equal(3, called); + assert.equal(called, 3); db.close(); done(); }); @@ -58,12 +58,12 @@ describe('model middleware', function() { var count = 0; schema.pre('validate', function(next) { - assert.equal(0, count++); + assert.equal(count++, 0); next(); }); schema.pre('save', function(next) { - assert.equal(1, count++); + assert.equal(count++, 1); next(); }); @@ -109,17 +109,17 @@ describe('model middleware', function() { title: 'Test' }); - assert.equal(1, called); + assert.equal(called, 1); test.save(function(err) { assert.ok(err instanceof Error); assert.equal(err.message, 'Error 101'); - assert.equal(2, called); + assert.equal(called, 2); test.remove(function(err) { db.close(); assert.ifError(err); - assert.equal(3, called); + assert.equal(called, 3); done(); }); }); @@ -155,8 +155,8 @@ describe('model middleware', function() { Test.findById(test._id, function(err, test) { assert.ifError(err); - assert.equal(1, preinit); - assert.equal(1, postinit); + assert.equal(preinit, 1); + assert.equal(postinit, 1); test.remove(function() { db.close(); done(); @@ -204,19 +204,19 @@ describe('model middleware', function() { parent.save(function(error) { assert.ifError(error); - assert.equal(2, childPreCalls); - assert.equal(1, childPreCallsByName.Jaina); - assert.equal(1, childPreCallsByName.Jacen); - assert.equal(1, parentPreCalls); + assert.equal(childPreCalls, 2); + assert.equal(childPreCallsByName.Jaina, 1); + assert.equal(childPreCallsByName.Jacen, 1); + assert.equal(parentPreCalls, 1); parent.children[0].name = 'Anakin'; parent.save(function(error) { assert.ifError(error); - assert.equal(4, childPreCalls); - assert.equal(1, childPreCallsByName.Anakin); - assert.equal(1, childPreCallsByName.Jaina); - assert.equal(2, childPreCallsByName.Jacen); + assert.equal(childPreCalls, 4); + assert.equal(childPreCallsByName.Anakin, 1); + assert.equal(childPreCallsByName.Jaina, 1); + assert.equal(childPreCallsByName.Jacen, 2); - assert.equal(2, parentPreCalls); + assert.equal(parentPreCalls, 2); db.close(); done(); }); @@ -260,19 +260,20 @@ describe('model middleware', function() { test.save(function(err) { assert.ifError(err); - assert.equal(1, preValidate); - assert.equal(1, postValidate); - assert.equal(0, preRemove); - assert.equal(0, postRemove); + assert.equal(preValidate, 1); + assert.equal(postValidate, 1); + assert.equal(preRemove, 0); + assert.equal(postRemove, 0); test.remove(function(err) { db.close(); assert.ifError(err); - assert.equal(1, preValidate); - assert.equal(1, postValidate); - assert.equal(1, preRemove); - assert.equal(1, postRemove); + assert.equal(preValidate, 1); + assert.equal(postValidate, 1); + assert.equal(preRemove, 1); + assert.equal(postRemove, 1); done(); }); }); }); }); + diff --git a/test/model.populate.setting.test.js b/test/model.populate.setting.test.js index 60a8050fb84..d1dcffae3da 100644 --- a/test/model.populate.setting.test.js +++ b/test/model.populate.setting.test.js @@ -169,7 +169,7 @@ describe('model: populate:', function() { assert.equal(doc._creator.email, u1.email); doc._creator = null; - assert.equal(null, doc._creator); + assert.equal(doc._creator, null); var creator = user('creator'); doc._creator = creator; @@ -203,7 +203,7 @@ describe('model: populate:', function() { B.findById(b1).exec(function(err, doc) { // db is closed in after() assert.ifError(err); - assert.equal(8, doc.fans.length); + assert.equal(doc.fans.length, 8); assert.equal(doc.fans[0], user8.id); assert.equal(doc.fans[5], user7.id); assert.equal(doc.fans[6], null); @@ -231,32 +231,32 @@ describe('model: populate:', function() { var name = 'fan1'; doc.fans.push(userLiteral(name)); assert.ok(doc.fans[2]._id); - assert.equal(name, doc.fans[2].name); + assert.equal(doc.fans[2].name, name); name = 'fan2'; doc.fans.nonAtomicPush(userLiteral(name)); assert.ok(doc.fans[3]._id); - assert.equal(name, doc.fans[3].name); + assert.equal(doc.fans[3].name, name); name = 'fan3'; doc.fans.splice(2, 1, userLiteral(name)); assert.ok(doc.fans[2]._id); - assert.equal(name, doc.fans[2].name); + assert.equal(doc.fans[2].name, name); name = 'fan4'; doc.fans.unshift(userLiteral(name)); assert.ok(doc.fans[0]._id); - assert.equal(name, doc.fans[0].name); + assert.equal(doc.fans[0].name, name); name = 'fan5'; doc.fans.addToSet(userLiteral(name)); assert.ok(doc.fans[5]._id); - assert.equal(name, doc.fans[5].name); + assert.equal(doc.fans[5].name, name); name = 'fan6'; doc.fans.set(0, userLiteral(name)); assert.ok(doc.fans[0]._id); - assert.equal(name, doc.fans[0].name); + assert.equal(doc.fans[0].name, name); doc.fans.forEach(function(doc) { assert.ok(doc instanceof U); @@ -267,7 +267,7 @@ describe('model: populate:', function() { doc._creator = creator; var creatorId = doc._creator._id; assert.ok(creatorId); - assert.equal(name, doc._creator.name); + assert.equal(doc._creator.name, name); assert.ok(doc._creator instanceof U); var fan2Id = doc.fans[2]._id; @@ -276,26 +276,26 @@ describe('model: populate:', function() { name = 'user1a'; var user1a = userLiteral(name); doc.embed[0].array.set(0, user1a); - assert.equal(name, doc.embed[0].array[0].name); + assert.equal(doc.embed[0].array[0].name, name); var user1aId = doc.embed[0].array[0]._id; name = 'user1b'; var user1b = userLiteral(name); doc.embed[0].other = user1b; - assert.equal(name, doc.embed[0].other.name); + assert.equal(doc.embed[0].other.name, name); var user1bId = doc.embed[0].other._id; name = 'user1c'; var user1c = userLiteral(name); doc.embed[0].nested = [{subdoc: user1c}]; - assert.equal(name, doc.embed[0].nested[0].subdoc.name); + assert.equal(doc.embed[0].nested[0].subdoc.name, name); var user1cId = doc.embed[0].nested[0].subdoc._id; // embedded without declared ref in schema name = 'user2a'; var user2a = userLiteral(name); doc.adhoc[0].subdoc = user2a; - assert.equal(name, doc.adhoc[0].subdoc.name); + assert.equal(doc.adhoc[0].subdoc.name, name); var user2aId = doc.adhoc[0].subdoc._id; name = 'user2b'; @@ -309,7 +309,7 @@ describe('model: populate:', function() { B.findById(b2).exec(function(err, doc) { // db is closed in after() assert.ifError(err); - assert.equal(6, doc.fans.length); + assert.equal(doc.fans.length, 6); assert.equal(String(doc._creator), creatorId); assert.equal(doc.fans[2], String(fan2Id)); assert.equal(doc.fans[5], String(fan5Id)); diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 13772d5f5c5..2946c5ed02a 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -418,7 +418,7 @@ describe('model: populate:', function() { .exec(function(err) { db.close(); assert.ok(err instanceof Error); - assert.equal('woot', err.message); + assert.equal(err.message, 'woot'); done(); }); }); @@ -450,7 +450,7 @@ describe('model: populate:', function() { assert.ifError(err); assert.ok(post._creator instanceof User); - assert.equal(false, post._creator.isInit('name')); + assert.equal(post._creator.isInit('name'), false); assert.equal(post._creator.email, 'rauchg@gmail.com'); done(); }); @@ -1255,12 +1255,12 @@ describe('model: populate:', function() { .populate('comments._creator') .populate('comments.asers') .exec(function(err, posts) { - assert.equal(false, ran); + assert.equal(ran, false); ran = true; assert.ifError(err); assert.ok(posts.length); assert.ok(posts[1].comments[0]._creator); - assert.equal('gh-1055-1', posts[1].comments[0]._creator.name); + assert.equal(posts[1].comments[0]._creator.name, 'gh-1055-1'); db.close(done); }); }); @@ -1289,16 +1289,16 @@ describe('model: populate:', function() { populate('_creator'). exec(function(error, posts) { assert.ifError(error); - assert.equal(1, posts.length); - assert.equal('aaron', posts[0]._creator.name); + assert.equal(posts.length, 1); + assert.equal(posts[0]._creator.name, 'aaron'); posts[0]._creator = user2; - assert.equal('val', posts[0]._creator.name); + assert.equal(posts[0]._creator.name, 'val'); posts[0].save(function(error, post) { assert.ifError(error); - assert.equal('val', post._creator.name); + assert.equal(post._creator.name, 'val'); posts[0].populate('_creator', function(error, doc) { assert.ifError(error); - assert.equal('val', doc._creator.name); + assert.equal(doc._creator.name, 'val'); db.close(done); }); }); @@ -1561,9 +1561,9 @@ describe('model: populate:', function() { BlogPost.populate(docs, opts, function(err, docs) { assert.ifError(err); - assert.equal(2, docs.length); - assert.equal(1, docs[0].author.friends.length); - assert.equal(1, docs[1].author.friends.length); + assert.equal(docs.length, 2); + assert.equal(docs[0].author.friends.length, 1); + assert.equal(docs[1].author.friends.length, 1); assert.equal(opts.options.limit, 1); db.close(done); }); @@ -2297,7 +2297,7 @@ describe('model: populate:', function() { if (err) { return done(err); } - assert.equal('hello', b.other.name); + assert.equal(b.other.name, 'hello'); done(); }); }); @@ -2320,7 +2320,7 @@ describe('model: populate:', function() { if (err) { return done(err); } - assert.equal('hello', b.other.name); + assert.equal(b.other.name, 'hello'); done(); }); }); @@ -2343,7 +2343,7 @@ describe('model: populate:', function() { if (err) { return done(err); } - assert.equal('hello', b.other.name); + assert.equal(b.other.name, 'hello'); done(); }); }); @@ -2366,7 +2366,7 @@ describe('model: populate:', function() { if (err) { return done(err); } - assert.equal('hello', b.other.name); + assert.equal(b.other.name, 'hello'); done(); }); }); @@ -2420,7 +2420,7 @@ describe('model: populate:', function() { assert.ifError(err); assert.ok(Array.isArray(post.fans)); - assert.equal(2, post.fans.length); + assert.equal(post.fans.length, 2); assert.ok(post.fans[0] instanceof User); assert.ok(post.fans[1] instanceof User); assert.equal(post.fans[0].isInit('name'), true); @@ -2501,7 +2501,7 @@ describe('model: populate:', function() { assert.ifError(err); assert.ok(post); assert.ok(post._creator instanceof User); - assert.equal('Phoenix', post._creator.name); + assert.equal(post._creator.name, 'Phoenix'); done(); }); }); @@ -2518,7 +2518,7 @@ describe('model: populate:', function() { assert.ok(post); assert.ok(post._creator instanceof User); assert.equal('Phoenix', post._creator.name); - assert.equal(2, post.fans.length); + assert.equal(post.fans.length, 2); assert.equal(post.fans[0].name, user1.name); assert.equal(post.fans[1].name, user2.name); @@ -2529,8 +2529,8 @@ describe('model: populate:', function() { assert.ifError(err); assert.ok(post); assert.ok(post._creator instanceof User); - assert.equal('Phoenix', post._creator.name); - assert.equal(2, post.fans.length); + assert.equal(post._creator.name, 'Phoenix'); + assert.equal(post.fans.length, 2); assert.equal(post.fans[0].name, user1.name); assert.equal(post.fans[1].name, user2.name); assert.ok(Array.isArray(post.populated('fans'))); @@ -2551,8 +2551,8 @@ describe('model: populate:', function() { assert.ifError(err); assert.ok(post); assert.ok(post._creator instanceof User); - assert.equal('Phoenix', post._creator.name); - assert.equal(2, post.fans.length); + assert.equal(post._creator.name, 'Phoenix'); + assert.equal(post.fans.length, 2); assert.equal(post.fans[0].name, user1.name); assert.equal(post.fans[1].name, user2.name); @@ -2567,8 +2567,8 @@ describe('model: populate:', function() { assert.ifError(err); assert.ok(post); assert.ok(post._creator instanceof User); - assert.equal('Phoenix', post._creator.name); - assert.equal(2, post.fans.length); + assert.equal(post._creator.name, 'Phoenix'); + assert.equal(post.fans.length, 2); assert.equal(post.fans[0].name, user1.name); assert.equal(post.fans[1].name, user2.name); assert.ok(Array.isArray(post.populated('fans'))); @@ -2597,13 +2597,13 @@ describe('model: populate:', function() { B.populate([post1, post2], ret, function(err, posts) { assert.ifError(err); assert.ok(posts); - assert.equal(2, posts.length); + assert.equal(posts.length, 2); var p1 = posts[0]; var p2 = posts[1]; assert.ok(p1._creator instanceof User); - assert.equal('Phoenix', p1._creator.name); + assert.equal(p1._creator.name, 'Phoenix'); assert.ok(p2._creator instanceof User); - assert.equal('Newark', p2._creator.name); + assert.equal(p2._creator.name, 'Newark'); done(); }); }); @@ -2641,7 +2641,7 @@ describe('model: populate:', function() { assert.ok(utils.isObject(post._creator)); assert.equal(post._creator.name, 'Guillermo'); assert.equal(post._creator.email, 'rauchg@gmail.com'); - assert.equal('undefined', typeof post._creator.update); + assert.equal(typeof post._creator.update, 'undefined'); done(); }); }); @@ -2680,17 +2680,17 @@ describe('model: populate:', function() { assert.equal(blogposts[0].fans[0].name, 'Fan 1'); assert.equal(blogposts[0].fans[0].email, 'fan1@learnboost.com'); - assert.equal('undefined', typeof blogposts[0].fans[0].update); + assert.equal(typeof blogposts[0].fans[0].update, 'undefined'); assert.equal(blogposts[0].fans[1].name, 'Fan 2'); assert.equal(blogposts[0].fans[1].email, 'fan2@learnboost.com'); - assert.equal('undefined', typeof blogposts[0].fans[1].update); + assert.equal(typeof blogposts[0].fans[1].update, 'undefined'); assert.equal(blogposts[1].fans[0].name, 'Fan 2'); assert.equal(blogposts[1].fans[0].email, 'fan2@learnboost.com'); - assert.equal('undefined', typeof blogposts[1].fans[0].update); + assert.equal(typeof blogposts[1].fans[0].update, 'undefined'); assert.equal(blogposts[1].fans[1].name, 'Fan 1'); assert.equal(blogposts[1].fans[1].email, 'fan1@learnboost.com'); - assert.equal('undefined', typeof blogposts[1].fans[1].update); + assert.equal(typeof blogposts[1].fans[1].update, 'undefined'); db.close(done); }); }); @@ -2745,7 +2745,7 @@ describe('model: populate:', function() { B.findById(b1).populate('fans _creator').exec(function(err, doc) { assert.ifError(err); assert.ok(Array.isArray(doc.populated('fans'))); - assert.equal(2, doc.populated('fans').length); + assert.equal(doc.populated('fans').length, 2); assert.equal(doc.populated('fans')[0], String(u1._id)); assert.equal(doc.populated('fans')[1], String(u2._id)); assert.equal(doc.populated('_creator'), String(u1._id)); @@ -2756,20 +2756,20 @@ describe('model: populate:', function() { it('with find', function(done) { B.find().sort('title').populate('fans _creator').exec(function(err, docs) { assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); var doc1 = docs[0]; var doc2 = docs[1]; assert.ok(Array.isArray(doc1.populated('fans'))); - assert.equal(2, doc1.populated('fans').length); + assert.equal(doc1.populated('fans').length, 2); assert.equal(doc1.populated('fans')[0], String(u1._id)); assert.equal(doc1.populated('fans')[1], String(u2._id)); assert.equal(doc1.populated('_creator'), String(u1._id)); assert.ok(Array.isArray(doc2.populated('fans'))); - assert.equal(2, doc2.populated('fans').length); + assert.equal(doc2.populated('fans').length, 2); assert.equal(doc2.populated('fans')[0], String(u2._id)); assert.equal(doc2.populated('fans')[1], String(u1._id)); assert.equal(doc2.populated('_creator'), String(u2._id)); @@ -2819,30 +2819,30 @@ describe('model: populate:', function() { var doc = docs[0]; assert.ok(Array.isArray(doc.comments), 'comments should be an array: ' + JSON.stringify(doc)); - assert.equal(2, doc.comments.length, 'invalid comments length for ' + JSON.stringify(doc)); + assert.equal(doc.comments.length, 2, 'invalid comments length for ' + JSON.stringify(doc)); doc.comments.forEach(function(d) { - assert.equal(undefined, d._id); - assert.equal(-1, Object.keys(d._doc).indexOf('_id')); + assert.equal(d._id, undefined); + assert.equal(Object.keys(d._doc).indexOf('_id'), -1); assert.ok(d.body.length); - assert.equal('number', typeof d._doc.__v); + assert.equal(typeof d._doc.__v, 'number'); }); U.findOne({name: 'u1'}).populate('comments', 'title -_id').exec(function(err, doc) { assert.ifError(err); - assert.equal(2, doc.comments.length); + assert.equal(doc.comments.length, 2); doc.comments.forEach(function(d) { - assert.equal(undefined, d._id); - assert.equal(-1, Object.keys(d._doc).indexOf('_id')); + assert.equal(d._id, undefined); + assert.equal(Object.keys(d._doc).indexOf('_id'), -1); assert.ok(d.title.length); - assert.equal(undefined, d.body); + assert.equal(d.body, undefined); assert.equal(typeof d._doc.__v, 'undefined'); }); U.findOne({name: 'u1'}).populate('comments', '-_id').exec(function(err, doc) { assert.ifError(err); - assert.equal(2, doc.comments.length); + assert.equal(doc.comments.length, 2); doc.comments.forEach(function(d) { - assert.equal(undefined, d._id); - assert.equal(-1, Object.keys(d._doc).indexOf('_id')); + assert.equal(d._id, undefined); + assert.equal(Object.keys(d._doc).indexOf('_id'), -1); assert.ok(d.title.length); assert.ok(d.body.length); assert.equal(typeof d._doc.__v, 'number'); @@ -2858,20 +2858,20 @@ describe('model: populate:', function() { assert.ifError(err); var doc = docs[0]; - assert.equal(2, doc.comments.length); + assert.equal(doc.comments.length, 2); doc.comments.forEach(function(d) { assert.ok(!('_id' in d)); assert.ok(d.body.length); - assert.equal('number', typeof d.__v); + assert.equal(typeof d.__v, 'number'); }); U.findOne({name: 'u1'}).lean().populate('comments', '-_id', null, {lean: true}).exec(function(err, doc) { assert.ifError(err); - assert.equal(2, doc.comments.length); + assert.equal(doc.comments.length, 2); doc.comments.forEach(function(d) { assert.ok(!('_id' in d)); assert.ok(d.body.length); - assert.equal('number', typeof d.__v); + assert.equal(typeof d.__v, 'number'); }); done(); }); @@ -2885,14 +2885,14 @@ describe('model: populate:', function() { .select('-_id comment name') .populate('comment', {_id: 0}).exec(function(err, docs) { assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); docs.forEach(function(doc) { assert.ok(doc.comment && doc.comment.body); if (doc.name === 'u1') { - assert.equal('comment 1', doc.comment.body); + assert.equal(doc.comment.body, 'comment 1'); } else { - assert.equal('comment 2', doc.comment.body); + assert.equal(doc.comment.body, 'comment 2'); } }); @@ -2981,9 +2981,9 @@ describe('model: populate:', function() { it('Simple populate', function(done) { Review.find({}).populate('item.id').exec(function(err, results) { assert.ifError(err); - assert.equal(1, results.length); + assert.equal(results.length, 1); var result = results[0]; - assert.equal('Val', result.item.id.name); + assert.equal(result.item.id.name, 'Val'); done(); }); }); @@ -2991,11 +2991,11 @@ describe('model: populate:', function() { it('Array populate', function(done) { Review.find({}).populate('items.id').exec(function(err, results) { assert.ifError(err); - assert.equal(1, results.length); + assert.equal(results.length, 1); var result = results[0]; - assert.equal(2, result.items.length); - assert.equal('Val', result.items[0].id.name); - assert.equal('Val', result.items[1].id.otherName); + assert.equal(result.items.length, 2); + assert.equal(result.items[0].id.name, 'Val'); + assert.equal(result.items[1].id.otherName, 'Val'); done(); }); }); @@ -3132,7 +3132,7 @@ describe('model: populate:', function() { assert.ifError(error); Category.findOne({}).populate({path: 'movies', options: {limit: 2, skip: 1}}).exec(function(error, category) { assert.ifError(error); - assert.equal(2, category.movies.length); + assert.equal(category.movies.length, 2); done(); }); }); diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index e1610db5d55..c648ccf4797 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -70,7 +70,7 @@ describe('model query casting', function() { BlogPostB.findOne({_id: id}, function(err, doc) { assert.ifError(err); - assert.equal(title, doc.get('title')); + assert.equal(doc.get('title'), title); db.close(done); }); }); @@ -104,7 +104,7 @@ describe('model query casting', function() { assert.ifError(err); assert.ok(found); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0].get('_id').toString(), post.get('_id')); assert.equal(found[0].get('meta.visitors').valueOf(), post.get('meta.visitors').valueOf()); db.close(done); @@ -169,7 +169,7 @@ describe('model query casting', function() { assert.ifError(err); Nin.find({num: {$nin: [2]}}, function(err, found) { assert.ifError(err); - assert.equal(2, found.length); + assert.equal(found.length, 2); db.close(done); }); }); @@ -288,7 +288,7 @@ describe('model query casting', function() { Test.find({loc: {$near: ['30', '40']}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -315,7 +315,7 @@ describe('model query casting', function() { Test.find({loc: {$near: ['30', '40'], $maxDistance: 51}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -348,7 +348,7 @@ describe('model query casting', function() { Test.find({'loc.nested': {$near: ['30', '40'], $maxDistance: '50'}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); } @@ -387,7 +387,7 @@ describe('model query casting', function() { Test.find({loc: {$nearSphere: ['30', '40']}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -416,7 +416,7 @@ describe('model query casting', function() { Test.find({loc: {$nearSphere: ['30', '40'], $maxDistance: 1}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -448,7 +448,7 @@ describe('model query casting', function() { Test.find({'loc.nested': {$nearSphere: ['30', '40'], $maxDistance: 1}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -482,7 +482,7 @@ describe('model query casting', function() { Test.find({loc: {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); } @@ -511,7 +511,7 @@ describe('model query casting', function() { Test.find({loc: {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); } @@ -543,7 +543,7 @@ describe('model query casting', function() { Test.find({'loc.nested': {$within: {$centerSphere: [['11', '20'], '0.4']}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); } @@ -574,7 +574,7 @@ describe('model query casting', function() { Test.find({loc: {$within: {$center: [['11', '20'], '1']}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); } @@ -603,7 +603,7 @@ describe('model query casting', function() { Test.find({loc: {$within: {$center: [['11', '20'], '1']}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); } @@ -635,7 +635,7 @@ describe('model query casting', function() { Test.find({'loc.nested': {$within: {$center: [['11', '20'], '1']}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); } @@ -666,7 +666,7 @@ describe('model query casting', function() { Test.find({loc: {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -695,7 +695,7 @@ describe('model query casting', function() { Test.find({loc: {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -727,7 +727,7 @@ describe('model query casting', function() { Test.find({'loc.nested': {$within: {$polygon: [['8', '1'], ['8', '100'], ['50', '100'], ['50', '1']]}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -758,7 +758,7 @@ describe('model query casting', function() { Test.find({loc: {$within: {$box: [['8', '1'], ['50', '100']]}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -787,7 +787,7 @@ describe('model query casting', function() { Test.find({loc: {$within: {$box: [['8', '1'], ['50', '100']]}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -818,7 +818,7 @@ describe('model query casting', function() { function test() { Test.find({'loc.nested': {$within: {$box: [['8', '1'], ['50', '100']]}}}, function(err, docs) { assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); db.close(done); }); } @@ -837,7 +837,7 @@ describe('model query casting', function() { B = db.model(modelName, collection + random()), result = B.find({}).cast(B, {tags: {$regex: /a/, $options: opts}}); - assert.equal('img', result.tags.$options); + assert.equal(result.tags.$options, 'img'); db.close(done); }); }); diff --git a/test/model.querying.test.js b/test/model.querying.test.js index 054de33b137..be7b6099c75 100644 --- a/test/model.querying.test.js +++ b/test/model.querying.test.js @@ -230,8 +230,8 @@ describe('model: querying:', function() { BlogPostB.count({title: title}, function(err, count) { assert.ifError(err); - assert.equal('number', typeof count); - assert.equal(2, count); + assert.equal(typeof count, 'number'); + assert.equal(count, 2); db.close(); done(); @@ -260,7 +260,7 @@ describe('model: querying:', function() { assert.strictEqual(null, err); var query = Address.distinct('zip', {}, function(err, results) { assert.ifError(err); - assert.equal(2, results.length); + assert.equal(results.length, 2); assert.ok(results.indexOf('10010') > -1); assert.ok(results.indexOf('99701') > -1); db.close(done); @@ -277,7 +277,7 @@ describe('model: querying:', function() { assert.ifError(err); Address.distinct('zip', function(err, results) { assert.ifError(err); - assert.equal(2, results.length); + assert.equal(results.length, 2); assert.ok(results.indexOf('10010') > -1); assert.ok(results.indexOf('99701') > -1); db.close(done); @@ -345,7 +345,7 @@ describe('model: querying:', function() { BlogPostB.findOne({title: title}, function(err, doc) { assert.ifError(err); assert.equal(title, doc.get('title')); - assert.equal(false, doc.isNew); + assert.equal(doc.isNew, false); db.close(); done(); @@ -696,7 +696,7 @@ describe('model: querying:', function() { BlogPostB.findById(undefined, function(err, doc) { assert.ifError(err); - assert.equal(null, doc); + assert.equal(doc, null); db.close(done); }); }); @@ -718,7 +718,7 @@ describe('model: querying:', function() { BlogPostB.findById(post.get('_id'), function(err, doc) { assert.ifError(err); assert.ok(doc instanceof BlogPostB); - assert.equal(title, doc.get('title')); + assert.equal(doc.get('title'), title); if (--pending) { return; } @@ -729,7 +729,7 @@ describe('model: querying:', function() { BlogPostB.findById(post.get('_id').toHexString(), function(err, doc) { assert.ifError(err); assert.ok(doc instanceof BlogPostB); - assert.equal(title, doc.get('title')); + assert.equal(doc.get('title'), title); if (--pending) { return; } @@ -757,12 +757,12 @@ describe('model: querying:', function() { BlogPostB.findById(post.get('_id'), function(err, doc) { assert.ifError(err); - assert.equal(true, doc.isInit('title')); - assert.equal(true, doc.isInit('slug')); - assert.equal(false, doc.isInit('date')); - assert.equal(true, doc.isInit('meta.visitors')); - assert.equal(53, doc.meta.visitors.valueOf()); - assert.equal(2, doc.tags.length); + assert.equal(doc.isInit('title'), true); + assert.equal(doc.isInit('slug'), true); + assert.equal(doc.isInit('date'), false); + assert.equal(doc.isInit('meta.visitors'), true); + assert.equal(doc.meta.visitors.valueOf(), 53); + assert.equal(doc.tags.length, 2); if (--queries) { return; } @@ -772,12 +772,12 @@ describe('model: querying:', function() { BlogPostB.findById(post.get('_id'), 'title', function(err, doc) { assert.ifError(err); - assert.equal(true, doc.isInit('title')); - assert.equal(false, doc.isInit('slug')); - assert.equal(false, doc.isInit('date')); - assert.equal(false, doc.isInit('meta.visitors')); - assert.equal(undefined, doc.meta.visitors); - assert.equal(undefined, doc.tags); + assert.equal(doc.isInit('title'), true); + assert.equal(doc.isInit('slug'), false); + assert.equal(doc.isInit('date'), false); + assert.equal(doc.isInit('meta.visitors'), false); + assert.equal(doc.meta.visitors, undefined); + assert.equal(doc.tags, undefined); if (--queries) { return; } @@ -787,12 +787,12 @@ describe('model: querying:', function() { BlogPostB.findById(post.get('_id'), '-slug', function(err, doc) { assert.ifError(err); - assert.equal(true, doc.isInit('title')); - assert.equal(false, doc.isInit('slug')); - assert.equal(false, doc.isInit('date')); - assert.equal(true, doc.isInit('meta.visitors')); - assert.equal(53, doc.meta.visitors); - assert.equal(2, doc.tags.length); + assert.equal(doc.isInit('title'), true); + assert.equal(doc.isInit('slug'), false); + assert.equal(doc.isInit('date'), false); + assert.equal(doc.isInit('meta.visitors'), true); + assert.equal(doc.meta.visitors, 53); + assert.equal(doc.tags.length, 2); if (--queries) { return; } @@ -802,12 +802,12 @@ describe('model: querying:', function() { BlogPostB.findById(post.get('_id'), {title: 1}, function(err, doc) { assert.ifError(err); - assert.equal(true, doc.isInit('title')); - assert.equal(false, doc.isInit('slug')); - assert.equal(false, doc.isInit('date')); - assert.equal(false, doc.isInit('meta.visitors')); - assert.equal(undefined, doc.meta.visitors); - assert.equal(undefined, doc.tags); + assert.equal(doc.isInit('title'), true); + assert.equal(doc.isInit('slug'), false); + assert.equal(doc.isInit('date'), false); + assert.equal(doc.isInit('meta.visitors'), false); + assert.equal(doc.meta.visitors, undefined); + assert.equal(doc.tags, undefined); if (--queries) { return; } @@ -817,12 +817,12 @@ describe('model: querying:', function() { BlogPostB.findById(post.get('_id'), 'slug', function(err, doc) { assert.ifError(err); - assert.equal(false, doc.isInit('title')); - assert.equal(true, doc.isInit('slug')); - assert.equal(false, doc.isInit('date')); - assert.equal(false, doc.isInit('meta.visitors')); - assert.equal(undefined, doc.meta.visitors); - assert.equal(undefined, doc.tags); + assert.equal(doc.isInit('title'), false); + assert.equal(doc.isInit('slug'), true); + assert.equal(doc.isInit('date'), false); + assert.equal(doc.isInit('meta.visitors'), false); + assert.equal(doc.meta.visitors, undefined); + assert.equal(doc.tags, undefined); if (--queries) { return; } @@ -862,21 +862,21 @@ describe('model: querying:', function() { BlogPostB.findById(created._id, {numbers: {$slice: 2}}, function(err, found) { assert.ifError(err); assert.equal(found._id.toString(), created._id); - assert.equal(2, found.numbers.length); - assert.equal(500, found.numbers[0]); - assert.equal(600, found.numbers[1]); + assert.equal(found.numbers.length, 2); + assert.equal(found.numbers[0], 500); + assert.equal(found.numbers[1], 600); BlogPostB.findById(created._id, {numbers: {$slice: -2}}, function(err, found) { assert.ifError(err); assert.equal(found._id.toString(), created._id); - assert.equal(2, found.numbers.length); - assert.equal(700, found.numbers[0]); - assert.equal(800, found.numbers[1]); + assert.equal(found.numbers.length, 2); + assert.equal(found.numbers[0], 700); + assert.equal(found.numbers[1], 800); BlogPostB.findById(created._id, {numbers: {$slice: [1, 2]}}, function(err, found) { assert.ifError(err); assert.equal(found._id.toString(), created._id); - assert.equal(2, found.numbers.length); - assert.equal(600, found.numbers[0]); - assert.equal(700, found.numbers[1]); + assert.equal(found.numbers.length, 2); + assert.equal(found.numbers[0], 600); + assert.equal(found.numbers[1], 700); db.close(); done(); }); @@ -906,13 +906,13 @@ describe('model: querying:', function() { BlogPostB.find({title: title}, function(err, docs) { assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); assert.equal(title, docs[0].get('title')); - assert.equal(false, docs[0].isNew); + assert.equal(docs[0].isNew, false); assert.equal(title, docs[1].get('title')); - assert.equal(false, docs[1].isNew); + assert.equal(docs[1].isNew, false); db.close(); done(); @@ -928,7 +928,7 @@ describe('model: querying:', function() { assert.ifError(err); BlogPostB.find({numbers: 100}, function(err, found) { assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), created._id); db.close(); done(); @@ -958,18 +958,18 @@ describe('model: querying:', function() { var query = NE.find({'b': id3.toString(), 'ids': {$ne: id1}}); query.exec(function(err, nes1) { assert.ifError(err); - assert.equal(1, nes1.length); + assert.equal(nes1.length, 1); NE.find({b: {$ne: [1]}}, function(err) { - assert.equal('Cast to ObjectId failed for value "1" at path "b"', err.message); + assert.equal(err.message, 'Cast to ObjectId failed for value "1" at path "b"'); NE.find({b: {$ne: 4}}, function(err) { - assert.equal('Cast to ObjectId failed for value "4" at path "b"', err.message); + assert.equal(err.message, 'Cast to ObjectId failed for value "4" at path "b"'); NE.find({b: id3, ids: {$ne: id4}}, function(err, nes4) { db.close(); assert.ifError(err); - assert.equal(0, nes4.length); + assert.equal(nes4.length, 0); done(); }); }); @@ -994,9 +994,9 @@ describe('model: querying:', function() { BlogPostB.find({_id: post.get('_id')}, function(err, docs) { assert.ifError(err); - assert.equal(true, docs[0].isInit('title')); - assert.equal(true, docs[0].isInit('slug')); - assert.equal(false, docs[0].isInit('date')); + assert.equal(docs[0].isInit('title'), true); + assert.equal(docs[0].isInit('slug'), true); + assert.equal(docs[0].isInit('date'), false); assert.strictEqual('kandinsky', docs[0].def); if (--queries) { return; @@ -1007,9 +1007,9 @@ describe('model: querying:', function() { BlogPostB.find({_id: post.get('_id')}, 'title', function(err, docs) { assert.ifError(err); - assert.equal(true, docs[0].isInit('title')); - assert.equal(false, docs[0].isInit('slug')); - assert.equal(false, docs[0].isInit('date')); + assert.equal(docs[0].isInit('title'), true); + assert.equal(docs[0].isInit('slug'), false); + assert.equal(docs[0].isInit('date'), false); assert.strictEqual(undefined, docs[0].def); if (--queries) { return; @@ -1020,9 +1020,9 @@ describe('model: querying:', function() { BlogPostB.find({_id: post.get('_id')}, {slug: 0, def: 0}, function(err, docs) { assert.ifError(err); - assert.equal(true, docs[0].isInit('title')); - assert.equal(false, docs[0].isInit('slug')); - assert.equal(false, docs[0].isInit('date')); + assert.equal(docs[0].isInit('title'), true); + assert.equal(docs[0].isInit('slug'), false); + assert.equal(docs[0].isInit('date'), false); assert.strictEqual(undefined, docs[0].def); if (--queries) { return; @@ -1033,9 +1033,9 @@ describe('model: querying:', function() { BlogPostB.find({_id: post.get('_id')}, 'slug', function(err, docs) { assert.ifError(err); - assert.equal(false, docs[0].isInit('title')); - assert.equal(true, docs[0].isInit('slug')); - assert.equal(false, docs[0].isInit('date')); + assert.equal(docs[0].isInit('title'), false); + assert.equal(docs[0].isInit('slug'), true); + assert.equal(docs[0].isInit('date'), false); assert.strictEqual(undefined, docs[0].def); if (--queries) { return; @@ -1061,7 +1061,7 @@ describe('model: querying:', function() { Exists.find({b: {$exists: true}}, function(err, docs) { assert.ifError(err); db.close(); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); }); @@ -1079,7 +1079,7 @@ describe('model: querying:', function() { BlogPostB.find({owners: {'$elemMatch': {$in: [id2.toString()]}}}, function(err, found) { db.close(); assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); done(); }); }); @@ -1094,7 +1094,7 @@ describe('model: querying:', function() { assert.ifError(err); Mod.find({num: {$mod: [2, 1]}}, function(err, found) { assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), one._id); db.close(); done(); @@ -1112,7 +1112,7 @@ describe('model: querying:', function() { assert.ifError(err); Mod.find({num: {$not: {$mod: [2, 1]}}}, function(err, found) { assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), two._id); db.close(); done(); @@ -1137,7 +1137,7 @@ describe('model: querying:', function() { Mod.find({$or: [{num: 1}, {num: 2}]}, function(err, found) { cb(); assert.ifError(err); - assert.equal(2, found.length); + assert.equal(found.length, 2); var found1 = false; var found2 = false; @@ -1159,7 +1159,7 @@ describe('model: querying:', function() { Mod.find({$or: [{str: 'two'}, {str: 'three'}]}, function(err, found) { cb(); assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), two._id); }); } @@ -1168,7 +1168,7 @@ describe('model: querying:', function() { Mod.find({$or: [{num: 1}]}).or([{str: 'two'}]).exec(function(err, found) { cb(); assert.ifError(err); - assert.equal(2, found.length); + assert.equal(found.length, 2); var found1 = false; var found2 = false; @@ -1206,7 +1206,7 @@ describe('model: querying:', function() { assert.ifError(err); Mod.find({$or: found}, function(err, found) { assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), one._id); db.close(); done(); @@ -1254,7 +1254,7 @@ describe('model: querying:', function() { Mod.find({$nor: [{num: 1}, {num: 3}]}, function(err, found) { cb(); assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), two._id); }); } @@ -1263,7 +1263,7 @@ describe('model: querying:', function() { Mod.find({$nor: [{str: 'two'}, {str: 'three'}]}, function(err, found) { cb(); assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), one._id); }); } @@ -1272,7 +1272,7 @@ describe('model: querying:', function() { Mod.find({$nor: [{num: 2}]}).nor([{str: 'two'}]).exec(function(err, found) { cb(); assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), one._id); }); } @@ -1298,7 +1298,7 @@ describe('model: querying:', function() { BlogPostB.find({author: {$in: [null], $exists: true}}, function(err, found) { db.close(); assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), createdA._id); done(); }); @@ -1316,7 +1316,7 @@ describe('model: querying:', function() { BlogPostB.find({author: null}, function(err, found) { db.close(); assert.ifError(err); - assert.equal(2, found.length); + assert.equal(found.length, 2); done(); }); }); @@ -1340,19 +1340,19 @@ describe('model: querying:', function() { BlogPostB.find({title: {'$all': ['Aristocats']}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); BlogPostB.find({title: {'$all': [/^Aristocats/]}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); BlogPostB.find({tags: {'$all': ['onex', 'twox', 'threex']}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); BlogPostB.find({tags: {'$all': [/^onex/i]}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); BlogPostB.findOne({tags: {'$all': /^two/}}, function(err, doc) { db.close(); @@ -1388,7 +1388,7 @@ describe('model: querying:', function() { P.find({$nor: [query0, query1]}, function(err, posts) { db.close(); assert.ifError(err); - assert.equal(1, posts.length); + assert.equal(posts.length, 1); assert.equal(posts[0].id, post0.id); done(); }); @@ -1409,7 +1409,7 @@ describe('model: querying:', function() { BlogPostB.find({title: {$regex: reg}}, function(err, found) { assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), created._id); BlogPostB.findOne({title: {$regex: reg}}, function(err, found) { @@ -1443,15 +1443,15 @@ describe('model: querying:', function() { BlogPostB.find({numbers: {$all: [-1, -2, -3, -4]}}, function(err, found) { assert.ifError(err); - assert.equal(2, found.length); + assert.equal(found.length, 2); BlogPostB.find({'meta.visitors': {$all: [4]}}, function(err, found) { assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), whereoutZero._id); BlogPostB.find({numbers: {$all: [0, -1]}}, function(err, found) { db.close(); assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); assert.equal(found[0]._id.toString(), whereZero._id); done(); }); @@ -1472,10 +1472,10 @@ describe('model: querying:', function() { assert.ifError(err); BlogPostB.find({numbers: {$size: 10}}, function(err, found) { assert.ifError(err); - assert.equal(2, found.length); + assert.equal(found.length, 2); BlogPostB.find({numbers: {$size: 11}}, function(err, found) { assert.ifError(err); - assert.equal(1, found.length); + assert.equal(found.length, 1); db.close(); done(); }); @@ -1514,11 +1514,11 @@ describe('model: querying:', function() { done(); } assert.ifError(err); - assert.equal(3, docs.length); + assert.equal(docs.length, 3); assert.equal(docs[0].dt, '2011-03-30'); assert.equal(docs[1].dt, '2011-03-31'); assert.equal(docs[2].dt, '2011-04-01'); - assert.equal(false, docs.some(function(d) { + assert.ok(!docs.some(function(d) { return d.dt === '2011-04-02'; })); }); @@ -1529,13 +1529,13 @@ describe('model: querying:', function() { done(); } assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); assert.equal(docs[0].dt, '2011-03-31'); assert.equal(docs[1].dt, '2011-04-01'); - assert.equal(false, docs.some(function(d) { + assert.ok(!docs.some(function(d) { return d.dt === '2011-03-30'; })); - assert.equal(false, docs.some(function(d) { + assert.ok(!docs.some(function(d) { return d.dt === '2011-04-02'; })); }); @@ -1564,8 +1564,8 @@ describe('model: querying:', function() { limit(2). exec(function(error, documents) { assert.ifError(error); - assert.equal(1, documents.length); - assert.equal('text search in mongoose', documents[0].title); + assert.equal(documents.length, 1); + assert.equal(documents[0].title, 'text search in mongoose'); a.remove(function(error) { assert.ifError(error); b.remove(function(error) { @@ -1619,7 +1619,7 @@ describe('model: querying:', function() { BlogPostB.find({title: /limit$/}).limit(2).find(function(err, found) { db.close(); assert.ifError(err); - assert.equal(2, found.length); + assert.equal(found.length, 2); assert.equal(found[0].id, first.id); assert.equal(found[1].id, second.id); done(); @@ -1643,7 +1643,7 @@ describe('model: querying:', function() { assert.ifError(err); BlogPostB.find({title: /skip$/}).sort({title: 1}).skip(1).limit(2).find(function(err, found) { assert.ifError(err); - assert.equal(2, found.length); + assert.equal(found.length, 2); assert.equal(found[0].id, second._id); assert.equal(found[1].id, third._id); db.close(); @@ -1671,7 +1671,7 @@ describe('model: querying:', function() { .sort('-meta.visitors') .find(function(err, found) { assert.ifError(err); - assert.equal(3, found.length); + assert.equal(found.length, 3); assert.equal(found[0].id, largest._id); assert.equal(found[1].id, middle._id); assert.equal(found[2].id, least._id); @@ -1704,9 +1704,9 @@ describe('model: querying:', function() { limit(2). exec(function(error, documents) { assert.ifError(error); - assert.equal(2, documents.length); - assert.equal('text search in mongoose', documents[0].title); - assert.equal('searching in mongoose', documents[1].title); + assert.equal(documents.length, 2); + assert.equal(documents[0].title, 'text search in mongoose'); + assert.equal(documents[1].title, 'searching in mongoose'); db.close(); done(); }); @@ -1740,7 +1740,7 @@ describe('model: querying:', function() { Test.find({date: now}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); }); @@ -1760,8 +1760,8 @@ describe('model: querying:', function() { M.find({a: {name: 'Frodo'}, b: '10'}, function(err, docs) { assert.ifError(err); - assert.equal(5, docs[0].a.length); - assert.equal(10, docs[0].b.valueOf()); + assert.equal(docs[0].a.length, 5); + assert.equal(docs[0].b.valueOf(), 10); var query = { a: { @@ -1772,7 +1772,7 @@ describe('model: querying:', function() { M.find(query, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(5, docs[0].a.length); + assert.equal(docs[0].a.length, 5); done(); }); }); @@ -1802,7 +1802,7 @@ describe('model: querying:', function() { P.findOne({'sub._id': {$all: [o0, new DocumentObjectId]}}, function(err, doc) { assert.ifError(err); - assert.equal(false, !!doc); + assert.equal(!!doc, false); P.findOne({'sub._id': {$all: [o2]}}, function(err, doc) { db.close(); @@ -1842,7 +1842,7 @@ describe('model: querying:', function() { P.findOne({'sub.d': {$all: [o0, new Date]}}, function(err, doc) { assert.ifError(err); - assert.equal(false, !!doc); + assert.equal(!!doc, false); P.findOne({'sub.d': {$all: [o2]}}, function(err, doc) { assert.ifError(err); @@ -1896,15 +1896,15 @@ describe('model: querying:', function() { B.find({$and: [{title: 'and operator'}]}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); B.find({$and: [{title: 'and operator'}, {published: true}]}, function(err, docs) { assert.ifError(err); - assert.equal(0, docs.length); + assert.equal(docs.length, 0); B.find({$and: [{title: 'and operator'}, {published: false}]}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); var query = B.find(); query.and([ @@ -1913,7 +1913,7 @@ describe('model: querying:', function() { ]); query.exec(function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); var query = B.find(); query.and([ @@ -1922,7 +1922,7 @@ describe('model: querying:', function() { ]); query.exec(function(err, docs) { assert.ifError(err); - assert.equal(0, docs.length); + assert.equal(docs.length, 0); db.close(done); }); }); @@ -2020,57 +2020,57 @@ describe('buffers', function() { Test.find({block: {$in: [[195, 188, 98, 101, 114], 'buffer shtuffs are neat', new Buffer('aGVsbG8gd29ybGQ=', 'base64')]}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(3, tests.length); + assert.equal(tests.length, 3); }); Test.find({block: {$in: ['über', 'hello world']}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(2, tests.length); + assert.equal(tests.length, 2); }); Test.find({block: {$in: ['über']}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(1, tests.length); + assert.equal(tests.length, 1); assert.equal(tests[0].block.toString('utf8'), 'über'); }); Test.find({block: {$nin: ['über']}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(2, tests.length); + assert.equal(tests.length, 2); }); Test.find({block: {$nin: [[195, 188, 98, 101, 114], new Buffer('aGVsbG8gd29ybGQ=', 'base64')]}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(1, tests.length); + assert.equal(tests.length, 1); assert.equal(tests[0].block.toString('utf8'), 'buffer shtuffs are neat'); }); Test.find({block: {$ne: 'über'}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(2, tests.length); + assert.equal(tests.length, 2); }); Test.find({block: {$gt: 'über'}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(2, tests.length); + assert.equal(tests.length, 2); }); Test.find({block: {$gte: 'über'}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(3, tests.length); + assert.equal(tests.length, 3); }); Test.find({block: {$lt: new Buffer('buffer shtuffs are neat')}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(2, tests.length); + assert.equal(tests.length, 2); var ret = {}; ret[tests[0].block.toString('utf8')] = 1; ret[tests[1].block.toString('utf8')] = 1; @@ -2081,7 +2081,7 @@ describe('buffers', function() { Test.find({block: {$lte: 'buffer shtuffs are neat'}}, function(err, tests) { cb(); assert.ifError(err); - assert.equal(3, tests.length); + assert.equal(tests.length, 3); }); var pending = 9; @@ -2111,7 +2111,7 @@ describe('backwards compatibility', function() { BlogPostB.findOne({_id: b.ops[0]._id}, function(err, found) { assert.ifError(err); - assert.equal(9898, found.get('meta.visitors').valueOf()); + assert.equal(found.get('meta.visitors').valueOf(), 9898); db.close(); done(); }); @@ -2128,7 +2128,7 @@ describe('backwards compatibility', function() { BlogPostB.findOne({_id: b.ops[0]._id}, function(err, found) { assert.ifError(err); - assert.equal(9898, found.get('meta.visitors').valueOf()); + assert.equal(found.get('meta.visitors').valueOf(), 9898); found.save(function(err) { assert.ifError(err); db.close(); @@ -2164,7 +2164,7 @@ describe('geo-spatial', function() { Test.find({loc: {$near: [30, 40]}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); done(); }); } @@ -2193,7 +2193,7 @@ describe('geo-spatial', function() { Test.find({loc: {'$within': {'$box': [[30, 40], [40, 60]]}}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); } @@ -2221,7 +2221,7 @@ describe('geo-spatial', function() { function test() { Test.find({loc: {$nearSphere: [30, 40]}}, function(err, docs) { assert.ifError(err); - assert.equal(2, docs.length); + assert.equal(docs.length, 2); db.close(done); }); } @@ -2297,11 +2297,11 @@ describe('geo-spatial', function() { function test() { Test.find({loc: {$near: [25, 31], $maxDistance: 1}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); Test.find({loc: {$near: [25, 32], $maxDistance: 1}}, function(err, docs) { db.close(); assert.ifError(err); - assert.equal(0, docs.length); + assert.equal(docs.length, 0); done(); }); }); @@ -2367,12 +2367,12 @@ describe('geo-spatial', function() { Test.find({loc: {$within: {$geometry: geojsonPoly}}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); assert.equal(created.id, docs[0].id); Test.where('loc').within().geometry(geojsonPoly).exec(function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); assert.equal(created.id, docs[0].id); db.close(done); }); @@ -2401,7 +2401,7 @@ describe('geo-spatial', function() { Test.find({line: {$geoIntersects: {$geometry: geojsonLine}}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); assert.equal(created.id, docs[0].id); Test.where('line').intersects().geometry(geojsonLine).findOne(function(err, doc) { @@ -2432,7 +2432,7 @@ describe('geo-spatial', function() { Test.find({geom: {$geoIntersects: {$geometry: geojsonLine}}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); assert.equal(created.id, docs[0].id); Test.where('geom').intersects().geometry(geojsonLine).findOne(function(err, doc) { @@ -2462,7 +2462,7 @@ describe('geo-spatial', function() { Test.find({geom: {$geoIntersects: {$geometry: geojsonPolygon}}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); assert.equal(created.id, docs[0].id); Test.where('geom').intersects().geometry(geojsonPolygon).findOne(function(err, doc) { @@ -2494,12 +2494,12 @@ describe('geo-spatial', function() { Test.find({line: {$near: geojsonPoint}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); assert.equal(created.id, docs[0].id); Test.find({line: {$near: {$geometry: geojsonPoint, $maxDistance: 50}}}, function(err, docs) { assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); assert.equal(created.id, docs[0].id); db.close(done); }); @@ -2548,7 +2548,7 @@ describe('geo-spatial', function() { }).exec(function(err, docs) { db.close(); assert.ifError(err); - assert.equal(1, docs.length); + assert.equal(docs.length, 1); done(); }); } @@ -2675,10 +2675,10 @@ describe('lean option:', function() { ] }; var q = M.find(cond); - assert.equal('number', typeof q._conditions.$and[0].$or[0].num); - assert.equal('number', typeof q._conditions.$and[0].$or[1]['subdoc.num']); - assert.equal('string', typeof q._conditions.$and[1].$and[0]['subdoc.title']); - assert.equal('number', typeof q._conditions.$and[1].$and[1].num); + assert.equal(typeof q._conditions.$and[0].$or[0].num, 'number'); + assert.equal(typeof q._conditions.$and[0].$or[1]['subdoc.num'], 'number'); + assert.equal(typeof q._conditions.$and[1].$and[0]['subdoc.title'], 'string'); + assert.equal(typeof q._conditions.$and[1].$and[1].num, 'number'); done(); }); it('properly casts deeply nested and/or queries (gh-676)', function(done) { @@ -2693,8 +2693,8 @@ describe('lean option:', function() { $and: [{$or: [{$and: [{$or: [{num: '12345'}, {'subdoc.num': '56789'}]}]}]}] }; var q = M.find(cond); - assert.equal('number', typeof q._conditions.$and[0].$or[0].$and[0].$or[0].num); - assert.equal('number', typeof q._conditions.$and[0].$or[0].$and[0].$or[1]['subdoc.num']); + assert.equal(typeof q._conditions.$and[0].$or[0].$and[0].$or[0].num, 'number'); + assert.equal(typeof q._conditions.$and[0].$or[0].$and[0].$or[1]['subdoc.num'], 'number'); done(); }); diff --git a/test/model.stream.test.js b/test/model.stream.test.js index 105826afe97..b31e28262d8 100644 --- a/test/model.stream.test.js +++ b/test/model.stream.test.js @@ -55,11 +55,11 @@ describe('query stream:', function() { function cb() { db.close(); assert.strictEqual(undefined, err); - assert.equal(i, names.length); - assert.equal(1, closed); - assert.equal(1, paused); - assert.equal(1, resumed); - assert.equal(true, stream._cursor.isClosed()); + assert.equal(names.length, i); + assert.equal(closed, 1); + assert.equal(paused, 1); + assert.equal(resumed, 1); + assert.equal(stream._cursor.isClosed(), true); done(); } @@ -79,22 +79,22 @@ describe('query stream:', function() { ++i; if (i === 3) { - assert.equal(false, stream.paused); + assert.equal(stream.paused, false); stream.pause(); - assert.equal(true, stream.paused); + assert.equal(stream.paused, true); paused++; setTimeout(function() { - assert.equal(true, stream.paused); + assert.equal(stream.paused, true); resumed++; stream.resume(); - assert.equal(false, stream.paused); + assert.equal(stream.paused, false); }, 20); } else if (i === 4) { stream.pause(); - assert.equal(true, stream.paused); + assert.equal(stream.paused, true); stream.resume(); - assert.equal(false, stream.paused); + assert.equal(stream.paused, false); } }); @@ -118,7 +118,7 @@ describe('query stream:', function() { function cb(err) { assert.ifError(err); - assert.equal(0, i); + assert.equal(i, 0); process.nextTick(function() { db.close(); assert.strictEqual(null, stream._fields); @@ -146,18 +146,18 @@ describe('query stream:', function() { var stream = P.where('name').exists().limit(10).select('_id').stream(); assert.strictEqual(null, stream._destroyed); - assert.equal(true, stream.readable); + assert.equal(stream.readable, true); function cb(err) { ++finished; setTimeout(function() { db.close(); assert.strictEqual(undefined, err); - assert.equal(5, i); - assert.equal(1, finished); - assert.equal(true, stream._destroyed); - assert.equal(false, stream.readable); - assert.equal(true, stream._cursor.isClosed()); + assert.equal(i, 5); + assert.equal(finished, 1); + assert.equal(stream._destroyed, true); + assert.equal(stream.readable, false); + assert.equal(stream._cursor.isClosed(), true); done(); }, 100); } @@ -166,7 +166,7 @@ describe('query stream:', function() { assert.strictEqual(undefined, doc.name); if (++i === 5) { stream.destroy(); - assert.equal(false, stream.readable); + assert.equal(stream.readable, false); } }); @@ -190,8 +190,8 @@ describe('query stream:', function() { setTimeout(function() { assert.ok(/destroyed/.test(err.message), err.message); assert.equal(i, 5); - assert.equal(1, closed); - assert.equal(1, finished); + assert.equal(closed, 1); + assert.equal(finished, 1); assert.equal(stream._destroyed, true); assert.equal(stream.readable, false); assert.equal(stream._cursor.isClosed(), true); @@ -251,9 +251,9 @@ describe('query stream:', function() { function cb() { db.close(); assert.strictEqual(undefined, err); - assert.equal(i, names.length); - assert.equal(1, closed); - assert.equal(true, stream._cursor.isClosed()); + assert.equal(names.length, i); + assert.equal(closed, 1); + assert.equal(stream._cursor.isClosed(), true); done(); } @@ -263,16 +263,16 @@ describe('query stream:', function() { if (i === 1) { stream.pause(); - assert.equal(true, stream.paused); + assert.equal(stream.paused, true); stream.resume(); - assert.equal(false, stream.paused); + assert.equal(stream.paused, false); } else if (i === 2) { stream.pause(); - assert.equal(true, stream.paused); + assert.equal(stream.paused, true); process.nextTick(function() { - assert.equal(true, stream.paused); + assert.equal(stream.paused, true); stream.resume(); - assert.equal(false, stream.paused); + assert.equal(stream.paused, false); }); } }); @@ -314,7 +314,7 @@ describe('query stream:', function() { stream. on('data', function(found) { assert.equal(found.id, doc.id); - assert.equal(1, found.ids.length); + assert.equal(found.ids.length, 1); assert.equal(_id2.toString(), found.ids[0].toString()); }). on('error', function(err) { @@ -381,7 +381,7 @@ describe('query stream:', function() { User.create({fullname: 'val', password: 'taco'}, function(error) { assert.ifError(error); User.find().stream().on('data', function(doc) { - assert.equal(undefined, doc.password); + assert.equal(doc.password, undefined); db.close(done); }); }); @@ -487,8 +487,8 @@ describe('query stream:', function() { stream.on('data', function(doc) { ++count; - assert.equal('Val', doc.items[0].id.name); - assert.equal('Val', doc.items[1].id.otherName); + assert.equal(doc.items[0].id.name, 'Val'); + assert.equal(doc.items[1].id.otherName, 'Val'); }); stream.on('close', function() { diff --git a/test/model.test.js b/test/model.test.js index 904fff5bb22..4872b089b77 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -111,13 +111,13 @@ describe('Model', function() { assert.ok('last_name' in doc); assert.ok('_id' in doc); assert.ok('first_name' in doc._id); - assert.equal('Daniel', doc._id.first_name); + assert.equal(doc._id.first_name, 'Daniel'); assert.ok('age' in doc._id); - assert.equal(21, doc._id.age); + assert.equal(doc._id.age, 21); assert.ok('doc_embed' in doc); assert.ok('some' in doc.doc_embed); - assert.equal('a', doc.doc_embed.some); + assert.equal(doc.doc_embed.some, 'a'); done(); }); }); @@ -156,7 +156,7 @@ describe('Model', function() { db.close(); var post = new BlogPost; - assert.equal(true, post.isNew); + assert.equal(post.isNew, true); done(); }); @@ -242,16 +242,16 @@ describe('Model', function() { assert.ok(post.get('_id') instanceof DocumentObjectId); - assert.equal(undefined, post.get('title')); - assert.equal(undefined, post.get('slug')); - assert.equal(undefined, post.get('date')); + assert.equal(post.get('title'), undefined); + assert.equal(post.get('slug'), undefined); + assert.equal(post.get('date'), undefined); - assert.equal('object', typeof post.get('meta')); + assert.equal(typeof post.get('meta'), 'object'); assert.deepEqual(post.get('meta'), {}); - assert.equal(undefined, post.get('meta.date')); - assert.equal(undefined, post.get('meta.visitors')); - assert.equal(undefined, post.get('published')); - assert.equal(1, Object.keys(post.get('nested')).length); + assert.equal(post.get('meta.date'), undefined); + assert.equal(post.get('meta.visitors'), undefined); + assert.equal(post.get('published'), undefined); + assert.equal(Object.keys(post.get('nested')).length, 1); assert.ok(Array.isArray(post.get('nested').array)); assert.ok(post.get('numbers').isMongooseArray); @@ -329,15 +329,15 @@ describe('Model', function() { post.on('save', function(post) { assert.ok(post.get('_id') instanceof DocumentObjectId); - assert.equal(undefined, post.get('title')); - assert.equal(undefined, post.get('slug')); - assert.equal(undefined, post.get('date')); - assert.equal(undefined, post.get('published')); + assert.equal(post.get('title'), undefined); + assert.equal(post.get('slug'), undefined); + assert.equal(post.get('date'), undefined); + assert.equal(post.get('published'), undefined); assert.equal(typeof post.get('meta'), 'object'); assert.deepEqual(post.get('meta'), {}); - assert.equal(undefined, post.get('meta.date')); - assert.equal(undefined, post.get('meta.visitors')); + assert.equal(post.get('meta.date'), undefined); + assert.equal(post.get('meta.visitors'), undefined); assert.ok(post.get('owners').isMongooseArray); assert.ok(post.get('comments').isMongooseDocumentArray); @@ -348,15 +348,15 @@ describe('Model', function() { assert.ifError(err); assert.ok(post.get('_id') instanceof DocumentObjectId); - assert.equal(undefined, post.get('title')); - assert.equal(undefined, post.get('slug')); - assert.equal(undefined, post.get('date')); - assert.equal(undefined, post.get('published')); + assert.equal(post.get('title'), undefined); + assert.equal(post.get('slug'), undefined); + assert.equal(post.get('date'), undefined); + assert.equal(post.get('published'), undefined); assert.equal(typeof post.get('meta'), 'object'); assert.deepEqual(post.get('meta'), {}); - assert.equal(undefined, post.get('meta.date')); - assert.equal(undefined, post.get('meta.visitors')); + assert.equal(post.get('meta.date'), undefined); + assert.equal(post.get('meta.visitors'), undefined); assert.ok(post.get('owners').isMongooseArray); assert.ok(post.get('comments').isMongooseDocumentArray); @@ -375,15 +375,15 @@ describe('Model', function() { assert.ifError(err); assert.ok(post.get('_id') instanceof DocumentObjectId); - assert.equal(undefined, post.get('title')); - assert.equal(undefined, post.get('slug')); - assert.equal(undefined, post.get('date')); - assert.equal(undefined, post.get('published')); + assert.equal(post.get('title'), undefined); + assert.equal(post.get('slug'), undefined); + assert.equal(post.get('date'), undefined); + assert.equal(post.get('published'), undefined); assert.equal(typeof post.get('meta'), 'object'); assert.deepEqual(post.get('meta'), {}); - assert.equal(undefined, post.get('meta.date')); - assert.equal(undefined, post.get('meta.visitors')); + assert.equal(post.get('meta.date'), undefined); + assert.equal(post.get('meta.visitors'), undefined); assert.ok(post.get('owners').isMongooseArray); assert.ok(post.get('comments').isMongooseDocumentArray); @@ -419,7 +419,7 @@ describe('Model', function() { assert.equal(post.get('title'), 'Test'); assert.equal(post.get('slug'), 'test'); assert.ok(post.get('date') instanceof Date); - assert.equal('object', typeof post.get('meta')); + assert.equal(typeof post.get('meta'), 'object'); assert.ok(post.get('meta').date instanceof Date); assert.equal(typeof post.get('meta').visitors, 'number'); assert.equal(post.get('published'), true); @@ -465,12 +465,12 @@ describe('Model', function() { assert.equal(post.get('title'), 'Test'); assert.equal(post.get('slug'), 'test'); assert.ok(post.get('date') instanceof Date); - assert.equal('object', typeof post.get('meta')); + assert.equal(typeof post.get('meta'), 'object'); assert.deepEqual(post.get('meta'), {}); - assert.equal(undefined, post.get('meta.date')); - assert.equal(undefined, post.get('meta.visitors')); - assert.equal(undefined, post.get('published')); + assert.equal(post.get('meta.date'), undefined); + assert.equal(post.get('meta.visitors'), undefined); + assert.equal(post.get('published'), undefined); assert.ok(post.get('owners').isMongooseArray); assert.ok(post.get('comments').isMongooseDocumentArray); @@ -489,7 +489,7 @@ describe('Model', function() { } }); - assert.equal(5, post.get('meta.visitors').valueOf()); + assert.equal(post.get('meta.visitors').valueOf(), 5); done(); }); @@ -505,7 +505,7 @@ describe('Model', function() { comments: [{title: 'Test', date: new Date, body: 'Test'}] }); - assert.equal(false, post.get('comments')[0].isNew); + assert.equal(post.get('comments')[0].isNew, false); done(); }); @@ -515,19 +515,19 @@ describe('Model', function() { var post = new BlogPost({title: 'hocus pocus'}); post.comments.push({title: 'Humpty Dumpty', comments: [{title: 'nested'}]}); - assert.equal(true, post.get('comments')[0].isNew); - assert.equal(true, post.get('comments')[0].comments[0].isNew); + assert.equal(post.get('comments')[0].isNew, true); + assert.equal(post.get('comments')[0].comments[0].isNew, true); post.invalidate('title'); // force error post.save(function() { - assert.equal(true, post.isNew); - assert.equal(true, post.get('comments')[0].isNew); - assert.equal(true, post.get('comments')[0].comments[0].isNew); + assert.equal(post.isNew, true); + assert.equal(post.get('comments')[0].isNew, true); + assert.equal(post.get('comments')[0].comments[0].isNew, true); post.save(function(err) { db.close(); assert.strictEqual(null, err); - assert.equal(false, post.isNew); - assert.equal(false, post.get('comments')[0].isNew); - assert.equal(false, post.get('comments')[0].comments[0].isNew); + assert.equal(post.isNew, false); + assert.equal(post.get('comments')[0].isNew, false); + assert.equal(post.get('comments')[0].comments[0].isNew, false); done(); }); }); @@ -706,7 +706,7 @@ describe('Model', function() { assert.ifError(err); BlogPost.findById(post.id, function(err, found) { assert.ifError(err); - assert.equal(20, found.get('meta.visitors').valueOf()); + assert.equal(found.get('meta.visitors').valueOf(), 20); db.close(); done(); }); @@ -721,7 +721,7 @@ describe('Model', function() { db.close(); var post = new BlogPost(); - assert.equal(post, post.cool()); + assert.equal(post.cool(), post); done(); }); @@ -741,11 +741,11 @@ describe('Model', function() { db.close(); var c = new ChildA; - assert.equal('function', typeof c.talk); + assert.equal(typeof c.talk, 'function'); var p = new ParentA(); p.children.push({}); - assert.equal('function', typeof p.children[0].talk); + assert.equal(typeof p.children[0].talk, 'function'); done(); }); @@ -759,7 +759,7 @@ describe('Model', function() { }); var NestedKey = db.model('NestedKey', NestedKeySchema); var n = new NestedKey(); - assert.equal(n, n.foo.bar()); + assert.equal(n.foo.bar(), n); done(); }); }); @@ -770,7 +770,7 @@ describe('Model', function() { BlogPost = db.model('BlogPost', collection); db.close(); - assert.equal(BlogPost, BlogPost.woot()); + assert.equal(BlogPost.woot(), BlogPost); done(); }); }); @@ -788,7 +788,7 @@ describe('Model', function() { threw = true; } - assert.equal(false, threw); + assert.equal(threw, false); try { post.set('title', 'Test'); @@ -796,12 +796,12 @@ describe('Model', function() { threw = true; } - assert.equal(false, threw); + assert.equal(threw, false); post.save(function(err) { assert.ok(err instanceof MongooseError); assert.ok(err instanceof ValidationError); - assert.equal(2, Object.keys(err.errors).length); + assert.equal(Object.keys(err.errors).length, 2); post.date = new Date; post.meta.date = new Date; post.save(function(err) { @@ -828,7 +828,7 @@ describe('Model', function() { threw = true; } - assert.equal(false, threw); + assert.equal(threw, false); try { post.set('meta.date', 'Test'); @@ -836,7 +836,7 @@ describe('Model', function() { threw = true; } - assert.equal(false, threw); + assert.equal(threw, false); post.save(function(err) { db.close(); @@ -909,7 +909,7 @@ describe('Model', function() { threw = true; } - assert.equal(false, threw); + assert.equal(threw, false); post.save(function(err) { db.close(); @@ -1055,12 +1055,12 @@ describe('Model', function() { describe('validation', function() { it('works', function(done) { function dovalidate() { - assert.equal('correct', this.asyncScope); + assert.equal(this.asyncScope, 'correct'); return true; } function dovalidateAsync(val, callback) { - assert.equal('correct', this.scope); + assert.equal(this.scope, 'correct'); process.nextTick(function() { callback(true); }); @@ -1188,7 +1188,7 @@ describe('Model', function() { assert.ok(err instanceof MongooseError); assert.ok(err instanceof ValidationError); - assert.equal(1, ++timesCalled); + assert.equal(++timesCalled, 1); assert.equal(Object.keys(err.errors).length, 3); assert.ok(err.errors.password instanceof ValidatorError); @@ -1252,7 +1252,7 @@ describe('Model', function() { assert.ifError(err); TestP.findOne({_id: f.ops[0]._id}, function(err, found) { assert.ifError(err); - assert.equal(false, found.isNew); + assert.equal(found.isNew, false); assert.strictEqual(found.get('previous'), null); found.validate(function(err) { @@ -1327,7 +1327,7 @@ describe('Model', function() { assert.ok(post.errors['items.0.required']); post.items[0].subs[0].set('required', true); - assert.equal(undefined, post.$__.validationError); + assert.equal(post.$__.validationError, undefined); post.save(function(err) { assert.ok(err); @@ -1377,13 +1377,13 @@ describe('Model', function() { assert.ok(err instanceof ValidationError); assert.ok(err.errors.async instanceof ValidatorError); assert.equal(err.errors.async.message, 'async validator failed for `async`'); - assert.equal(true, executed); + assert.equal(executed, true); executed = false; post.set('async', 'woot'); post.save(function(err) { db.close(); - assert.equal(true, executed); + assert.equal(executed, true); assert.strictEqual(err, null); done(); }); @@ -1493,7 +1493,7 @@ describe('Model', function() { var post = new TestCallingValidation; - assert.equal(true, post.schema.path('item').isRequired); + assert.equal(post.schema.path('item').isRequired, true); assert.strictEqual(post.isNew, true); post.validate(function(err) { @@ -1526,7 +1526,7 @@ describe('Model', function() { var post = new TestV; db.close(); - assert.equal(false, post.schema.path('result').isRequired); + assert.equal(post.schema.path('result').isRequired, false); done(); }); @@ -1651,7 +1651,7 @@ describe('Model', function() { post.save(function(err) { assert.ok(err instanceof MongooseError); assert.ok(err instanceof ValidationError); - assert.equal(4, Object.keys(err.errors).length); + assert.equal(Object.keys(err.errors).length, 4); assert.ok(err.errors.baz instanceof ValidatorError); assert.equal(err.errors.baz.kind, 'user defined'); assert.equal(err.errors.baz.path, 'baz'); @@ -1891,8 +1891,8 @@ describe('Model', function() { BlogPost.find({}, function(err, found) { db.close(); assert.ifError(err); - assert.equal(1, found.length); - assert.equal('2', found[0].title); + assert.equal(found.length, 1); + assert.equal(found[0].title, '2'); done(); }); }); @@ -1948,8 +1948,8 @@ describe('Model', function() { BlogPost.find(function(err, found) { db.close(); assert.ifError(err); - assert.equal(1, found.length); - assert.equal('2', found[0].title); + assert.equal(found.length, 1); + assert.equal(found[0].title, '2'); done(); }); }); @@ -2125,20 +2125,20 @@ describe('Model', function() { var A = mongoose.model('gettersShouldNotBeTriggeredAtConstruction', schema); var a = new A({number: 100}); - assert.equal(false, called); + assert.equal(called, false); var num = a.number; - assert.equal(true, called); - assert.equal(100, num.valueOf()); - assert.equal(50, a.getValue('number').valueOf()); + assert.equal(called, true); + assert.equal(num.valueOf(), 100); + assert.equal(a.getValue('number').valueOf(), 50); called = false; var b = new A; b.init({number: 50}); - assert.equal(false, called); + assert.equal(called, false); num = b.number; - assert.equal(true, called); - assert.equal(100, num.valueOf()); - assert.equal(50, b.getValue('number').valueOf()); + assert.equal(called, true); + assert.equal(num.valueOf(), 100); + assert.equal(b.getValue('number').valueOf(), 50); done(); }); @@ -2173,7 +2173,7 @@ describe('Model', function() { doc = new ShortcutGetterNested(); db.close(); - assert.equal('object', typeof doc.first); + assert.equal(typeof doc.first, 'object'); assert.ok(doc.first.second.isMongooseArray); done(); }); @@ -2209,7 +2209,7 @@ describe('Model', function() { threw = true; } - assert.equal(false, threw); + assert.equal(threw, false); getter1 = JSON.parse(getter1); getter2 = JSON.parse(getter2); assert.equal(getter1.visitors, 5); @@ -2221,8 +2221,8 @@ describe('Model', function() { assert.ok(post.get('meta').date instanceof Date); post.meta.visitors = 2; - assert.equal('number', typeof post.get('meta').visitors); - assert.equal('number', typeof post.meta.visitors); + assert.equal(typeof post.get('meta').visitors, 'number'); + assert.equal(typeof post.meta.visitors, 'number'); var newmeta = { date: date - 2000, @@ -2233,8 +2233,8 @@ describe('Model', function() { assert.ok(post.meta.date instanceof Date); assert.ok(post.get('meta').date instanceof Date); - assert.equal('number', typeof post.meta.visitors); - assert.equal('number', typeof post.get('meta').visitors); + assert.equal(typeof post.meta.visitors, 'number'); + assert.equal(typeof post.get('meta').visitors, 'number'); assert.equal((+post.meta.date), date - 2000); assert.equal((+post.get('meta').date), date - 2000); assert.equal((+post.meta.visitors), 234); @@ -2248,8 +2248,8 @@ describe('Model', function() { assert.ok(post.meta.date instanceof Date); assert.ok(post.get('meta').date instanceof Date); - assert.equal('number', typeof post.meta.visitors); - assert.equal('number', typeof post.get('meta').visitors); + assert.equal(typeof post.meta.visitors, 'number'); + assert.equal(typeof post.get('meta').visitors, 'number'); assert.equal((+post.meta.date), date - 3000); assert.equal((+post.get('meta').date), date - 3000); assert.equal((+post.meta.visitors), 4815162342); @@ -2333,7 +2333,7 @@ describe('Model', function() { var u = t.$__delta()[1]; assert.ok(u.$set); assert.ok(u.$set.nest); - assert.equal(2, Object.keys(u.$set.nest).length); + assert.equal(Object.keys(u.$set.nest).length, 2); assert.ok(u.$set.nest.yep); assert.ok(u.$set.nest.st); @@ -2515,7 +2515,7 @@ describe('Model', function() { BlogPost.findById(post._id, function(err, doc) { db.close(); assert.ifError(err); - assert.equal(3, +doc.meta.visitors); + assert.equal(+doc.meta.visitors, 3); done(); }); }); @@ -2668,7 +2668,7 @@ describe('Model', function() { Outer.findById(outer.get('_id'), function(err, found) { assert.ifError(err); - assert.equal(1, found.inner.length); + assert.equal(found.inner.length, 1); found.inner[0].arr.push(5); found.save(function(err) { assert.ifError(err); @@ -2676,9 +2676,9 @@ describe('Model', function() { Outer.findById(found.get('_id'), function(err, found2) { db.close(); assert.ifError(err); - assert.equal(1, found2.inner.length); - assert.equal(1, found2.inner[0].arr.length); - assert.equal(5, found2.inner[0].arr[0]); + assert.equal(found2.inner.length, 1); + assert.equal(found2.inner[0].arr.length, 1); + assert.equal(found2.inner[0].arr[0], 5); done(); }); }); @@ -2731,7 +2731,7 @@ describe('Model', function() { assert.ifError(err); t.nested.nums.push(1); t.nested.nums.push(2, 3); - assert.equal(3, t.nested.nums.length); + assert.equal(t.nested.nums.length, 3); t.save(function(err) { assert.ifError(err); @@ -2801,7 +2801,7 @@ describe('Model', function() { Temp.create({nested: {nums: [1, 2, 3, 4, 5]}}, function(err, t) { assert.ifError(err); t.nested.nums.pull(1); - assert.equal(4, t.nested.nums.length); + assert.equal(t.nested.nums.length, 4); db.close(); done(); }); @@ -2833,11 +2833,11 @@ describe('Model', function() { assert.ifError(err); Temp.findById(t._id, function(err, found) { assert.ifError(err); - assert.equal(2, found.nested.nums.length); - assert.equal(1, found.nested.nums[0], 1); - assert.equal(2, found.nested.nums[1], 2); + assert.equal(found.nested.nums.length, 2); + assert.equal(found.nested.nums[0], 1, 1); + assert.equal(found.nested.nums[1], 2, 2); found.nested.nums.$shift(); - assert.equal(1, found.nested.nums.length); + assert.equal(found.nested.nums.length, 1); assert.equal(found.nested.nums[0], 2); found.save(function(err) { @@ -2873,7 +2873,7 @@ describe('Model', function() { function complete() { Temp.findOne({_id: t.get('_id')}, function(err, doc) { assert.ifError(err); - assert.equal(3, doc.get('nums').length); + assert.equal(doc.get('nums').length, 3); var v = doc.get('nums').some(function(num) { return num.valueOf() === 1; @@ -2940,7 +2940,7 @@ describe('Model', function() { db.close(); assert.ifError(err); - assert.equal(3, doc.get('strings').length); + assert.equal(doc.get('strings').length, 3); var v = doc.get('strings').some(function(str) { return str === 'a'; @@ -3007,7 +3007,7 @@ describe('Model', function() { db.close(); assert.ifError(err); - assert.equal(3, doc.get('buffers').length); + assert.equal(doc.get('buffers').length, 3); var v = doc.get('buffers').some(function(buf) { return buf[0] === 140; @@ -3082,7 +3082,7 @@ describe('Model', function() { B.findById(doc._id, function(err, doc) { db.close(); assert.ifError(err); - assert.equal(0, doc.comments.length); + assert.equal(doc.comments.length, 0); done(); }); }); @@ -3104,7 +3104,7 @@ describe('Model', function() { assert.ifError(err); BlogPost.findById(post._id, function(err, found) { assert.ifError(err); - assert.equal('before-change', found.comments[0].title); + assert.equal(found.comments[0].title, 'before-change'); var subDoc = [{ _id: found.comments[0]._id, title: 'after-change' @@ -3116,7 +3116,7 @@ describe('Model', function() { BlogPost.findById(found._id, function(err, updated) { db.close(); assert.ifError(err); - assert.equal('after-change', updated.comments[0].title); + assert.equal(updated.comments[0].title, 'after-change'); done(); }); }); @@ -3133,14 +3133,14 @@ describe('Model', function() { assert.ifError(err); BlogPost.findById(post._id, function(err, found) { assert.ifError(err); - assert.equal('woot', found.comments[0].title); + assert.equal(found.comments[0].title, 'woot'); found.comments[0].title = 'notwoot'; found.save(function(err) { assert.ifError(err); BlogPost.findById(found._id, function(err, updated) { db.close(); assert.ifError(err); - assert.equal('notwoot', updated.comments[0].title); + assert.equal(updated.comments[0].title, 'notwoot'); done(); }); }); @@ -3187,17 +3187,17 @@ describe('Model', function() { post.comments.push({title: 'woot'}); post.save(function(err) { assert.ifError(err); - assert.equal(1, post.comments.length); + assert.equal(post.comments.length, 1); BlogPost.findById(post.id, function(err, found) { assert.ifError(err); - assert.equal(1, found.comments.length); + assert.equal(found.comments.length, 1); post.save(function(err) { assert.ifError(err); - assert.equal(1, post.comments.length); + assert.equal(post.comments.length, 1); BlogPost.findById(post.id, function(err, found) { db.close(); assert.ifError(err); - assert.equal(1, found.comments.length); + assert.equal(found.comments.length, 1); done(); }); }); @@ -3295,7 +3295,7 @@ describe('Model', function() { BlogPost.findById(post.get('_id'), function(err, doc) { db.close(); assert.ifError(err); - assert.equal(1, doc.comments.length); + assert.equal(doc.comments.length, 1); assert.equal(doc.comments[0].title, 'aaaa'); done(); }); @@ -3327,7 +3327,7 @@ describe('Model', function() { BlogPost.findById(post.get('_id'), function(err, doc) { db.close(); assert.ifError(err); - assert.equal(0, doc.comments.length); + assert.equal(doc.comments.length, 0); done(); }); }); @@ -3365,7 +3365,7 @@ describe('Model', function() { BlogPost.findById(post2._id, function(err, doc) { assert.ifError(err); - assert.equal(true, Array.isArray(doc.mixed.arr)); + assert.equal(Array.isArray(doc.mixed.arr), true); doc.mixed = [{foo: 'bar'}]; doc.save(function(err) { @@ -3374,7 +3374,7 @@ describe('Model', function() { BlogPost.findById(doc._id, function(err, doc) { assert.ifError(err); - assert.equal(true, Array.isArray(doc.mixed)); + assert.equal(Array.isArray(doc.mixed), true); doc.mixed.push({hello: 'world'}); doc.mixed.push(['foo', 'bar']); doc.markModified('mixed'); @@ -3433,9 +3433,9 @@ describe('Model', function() { }); db.close(); - assert.equal('test', post.mixed.type); - assert.equal('rules', post.mixed.github); - assert.equal(3, post.mixed.nested.number); + assert.equal(post.mixed.type, 'test'); + assert.equal(post.mixed.github, 'rules'); + assert.equal(post.mixed.nested.number, 3); done(); }); @@ -3636,7 +3636,7 @@ describe('Model', function() { s.save(function(err) { db.close(); assert.ifError(err); - assert.equal(2, called); + assert.equal(called, 2); done(); }); }); @@ -3667,7 +3667,7 @@ describe('Model', function() { p.onResolve(function(err) { db.close(); assert.ifError(err); - assert.equal(2, called); + assert.equal(called, 2); done(); }); }); @@ -3898,7 +3898,7 @@ describe('Model', function() { query.exec(function(err, count) { db.close(); assert.ifError(err); - assert.equal(1, count); + assert.equal(count, 1); done(); }); }); @@ -3917,7 +3917,7 @@ describe('Model', function() { BlogPost.count({title: 'interoperable update as promise delta'}, function(err, count) { db.close(); assert.ifError(err); - assert.equal(1, count); + assert.equal(count, 1); done(); }); }); @@ -4013,7 +4013,7 @@ describe('Model', function() { promise.onResolve(function(err, count) { db.close(); assert.ifError(err); - assert.equal(1, count); + assert.equal(count, 1); done(); }); }); @@ -4033,7 +4033,7 @@ describe('Model', function() { BlogPost.count({title: 'interoperable update as promise delta 2'}, function(err, count) { db.close(); assert.ifError(err); - assert.equal(1, count); + assert.equal(count, 1); done(); }); }); @@ -4144,7 +4144,7 @@ describe('Model', function() { }); return P.where('likes').in(ids).exec(); }).then(function(people) { - assert.equal(3, people.length); + assert.equal(people.length, 3); return people; }).then(function() { db.close(); @@ -4371,12 +4371,12 @@ describe('Model', function() { var s = new S({name: 'aaron'}); s.save(function(err, doc, affected) { assert.ifError(err); - assert.equal(1, affected); + assert.equal(affected, 1); s.name = 'heckmanananananana'; s.save(function(err, doc, affected) { db.close(); assert.ifError(err); - assert.equal(1, affected); + assert.equal(affected, 1); done(); }); }); @@ -4390,13 +4390,13 @@ describe('Model', function() { doc.save(function(err, doc, affected) { assert.ifError(err); - assert.equal(1, affected); + assert.equal(affected, 1); Model.findById(doc.id).then(function(doc) { doc.save(function(err, doc, affected) { db.close(); assert.ifError(err); - assert.equal(0, affected); + assert.equal(affected, 0); done(); }); }); @@ -4421,7 +4421,7 @@ describe('Model', function() { B.findById(post, function(err, doc) { assert.ifError(err); - assert.equal('changed', doc.title); + assert.equal(doc.title, 'changed'); db.close(done); }); }); @@ -4470,8 +4470,8 @@ describe('Model', function() { B.findById(b._id, function(err, b) { assert.ifError(err); assert.ok(Array.isArray(b.numbers)); - assert.equal(1, b.numbers.length); - assert.equal(3, b.numbers[0]); + assert.equal(b.numbers.length, 1); + assert.equal(b.numbers[0], 3); b.numbers = [3]; var d = b.$__delta(); @@ -4484,9 +4484,9 @@ describe('Model', function() { B.findById(b._id, function(err, b) { assert.ifError(err); assert.ok(Array.isArray(b.numbers)); - assert.equal(2, b.numbers.length); - assert.equal(4, b.numbers[0]); - assert.equal(5, b.numbers[1]); + assert.equal(b.numbers.length, 2); + assert.equal(b.numbers[0], 4); + assert.equal(b.numbers[1], 5); db.close(done); }); }); @@ -4510,9 +4510,9 @@ describe('Model', function() { b.comments[2].body = 'changed'; b.comments.pull(b.comments[1]); - assert.equal(2, b.comments.length); - assert.equal('a', b.comments[0].body); - assert.equal('changed', b.comments[1].body); + assert.equal(b.comments.length, 2); + assert.equal(b.comments[0].body, 'a'); + assert.equal(b.comments[1].body, 'changed'); var d = b.$__delta()[1]; assert.ok('$set' in d, 'invalid delta ' + JSON.stringify(d)); @@ -4526,9 +4526,9 @@ describe('Model', function() { db.close(); assert.ifError(err); assert.ok(Array.isArray(b.comments)); - assert.equal(2, b.comments.length); - assert.equal('a', b.comments[0].body); - assert.equal('changed', b.comments[1].body); + assert.equal(b.comments.length, 2); + assert.equal(b.comments[0].body, 'a'); + assert.equal(b.comments[1].body, 'changed'); done(); }); }); @@ -4575,7 +4575,7 @@ describe('Model', function() { assert.ok(doc._doc.databases); assert.ok(doc._doc.databases['0']); assert.ok(doc._doc.databases['15']); - assert.equal(undefined, doc.databases); + assert.equal(doc.databases, undefined); done(); }); }); @@ -4673,7 +4673,7 @@ describe('Model', function() { T.findOne(function(err, doc) { db.close(); assert.ifError(err); - assert.equal('234', doc.title); + assert.equal(doc.title, '234'); done(); }); }); @@ -4706,7 +4706,7 @@ describe('Model', function() { assert.equal(b.author, 'aaron'); assert.equal(b.meta.date.toString(), doc.meta.date.toString()); assert.equal(b.meta.visitors.valueOf(), doc.meta.visitors.valueOf()); - assert.equal(2, b.comments.length); + assert.equal(b.comments.length, 2); assert.equal(b.comments[0].title, 'thanksgiving'); assert.equal(b.comments[0].body, 'yuuuumm'); assert.equal(b.comments[1].title, 'turkey'); @@ -4758,7 +4758,7 @@ describe('Model', function() { M.findOne(function(err, m) { assert.ifError(err); m.s = m.n = m.a = undefined; - assert.equal(undefined, m.$__delta()); + assert.equal(m.$__delta(), undefined); db.close(done); }); }); @@ -5019,7 +5019,7 @@ describe('Model', function() { Person.findById(p._id, function(err, personDoc) { assert.ifError(err); - assert.equal(undefined, personDoc.loc); + assert.equal(personDoc.loc, undefined); done(); }); }); @@ -5050,8 +5050,8 @@ describe('Model', function() { Person.findById(p._id, function(err, personDoc) { assert.ifError(err); - assert.equal('Jimmy Page', personDoc.name); - assert.equal(undefined, personDoc.loc); + assert.equal(personDoc.name, 'Jimmy Page'); + assert.equal(personDoc.loc, undefined); done(); }); }); @@ -5084,8 +5084,8 @@ describe('Model', function() { Person.findById(p._id, function(err, personDoc) { assert.ifError(err); - assert.equal('Jimmy Page', personDoc.name); - assert.equal(undefined, personDoc.loc); + assert.equal(personDoc.name, 'Jimmy Page'); + assert.equal(personDoc.loc, undefined); done(); }); }); @@ -5283,7 +5283,7 @@ describe('Model', function() { assert.ifError(err); assert.ok(!doc.isModified('array')); assert.deepEqual(doc.array[0].value, 1); - assert.equal('[{"value":1}]', JSON.stringify(doc.array)); + assert.equal(JSON.stringify(doc.array), '[{"value":1}]'); done(); }); }); From a4d7e7b1d94a74455afab95e40b4d9e61b1ad2e4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 24 May 2016 08:14:37 -0700 Subject: [PATCH 0582/2240] refactor(test): ensure correct assert.equals() param order Fix #4122 --- test/model.update.test.js | 144 +++++------ test/object.create.null.test.js | 13 +- test/promise.test.js | 25 +- test/query.middleware.test.js | 45 ++-- test/query.test.js | 34 +-- test/schema.documentarray.test.js | 4 +- test/schema.mixed.test.js | 8 +- test/schema.onthefly.test.js | 28 +-- test/schema.select.test.js | 120 ++++----- test/schema.test.js | 322 ++++++++++++------------ test/schema.type.test.js | 4 +- test/schema.validation.test.js | 59 ++--- test/types.array.test.js | 392 ++++++++++++++--------------- test/types.buffer.test.js | 8 +- test/types.document.test.js | 2 +- test/types.documentarray.test.js | 19 +- test/updateValidators.unit.test.js | 13 +- test/utils.test.js | 4 +- test/versioning.test.js | 68 ++--- 19 files changed, 659 insertions(+), 653 deletions(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index b4c6f5261df..4f028d2f0e6 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -106,12 +106,12 @@ describe('model: update:', function() { BlogPost.findById(post._id, function(err, cf) { assert.ifError(err); - assert.equal(title, cf.title); + assert.equal(cf.title, title); assert.equal(cf.author, author); assert.equal(cf.meta.visitors.valueOf(), 0); assert.equal(cf.date.toString(), post.date.toString()); - assert.equal(true, cf.published); - assert.equal('ex', cf.mixed.x); + assert.equal(cf.published, true); + assert.equal(cf.mixed.x, 'ex'); assert.deepEqual(cf.numbers.toObject(), [4, 5, 6, 7]); assert.equal(cf.owners.length, 2); assert.equal(cf.owners[0].toString(), id0.toString()); @@ -235,13 +235,13 @@ describe('model: update:', function() { assert.equal(up.comments.length, 1); assert.equal(up.comments[0].body, 'worked great'); assert.strictEqual(true, !!doc.comments[0]._id); - assert.equal(2, up.meta.visitors.valueOf()); + assert.equal(up.meta.visitors.valueOf(), 2); assert.equal(up.mixed.x, 'ECKS'); assert.deepEqual(up.numbers.toObject(), [5, 100]); assert.strictEqual(up.numbers[1].valueOf(), 100); - assert.equal(2, doc.idontexist); - assert.equal(100, doc.numbers[1]); + assert.equal(doc.idontexist, 2); + assert.equal(doc.numbers[1], 100); db.close(done); }); @@ -260,7 +260,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(3, ret.comments.length); + assert.equal(ret.comments.length, 3); assert.equal(ret.comments[1].body, 'i am number 2'); assert.strictEqual(true, !!ret.comments[1]._id); assert.ok(ret.comments[1]._id instanceof DocumentObjectId); @@ -284,7 +284,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(2, ret.comments.length); + assert.equal(ret.comments.length, 2); assert.equal(ret.comments[0].body, 'worked great'); assert.ok(ret.comments[0]._id instanceof DocumentObjectId); assert.equal(ret.comments[1].body, 'i am number 3'); @@ -302,7 +302,7 @@ describe('model: update:', function() { var update = {'$set': {'some_attrib': post._id.toString()}}; BlogPost.update(conditions, update, function(err) { assert.ifError(err); - assert.equal('string', typeof conditions._id); + assert.equal(typeof conditions._id, 'string'); db.close(done); }); }); @@ -328,7 +328,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(2, ret.comments.length); + assert.equal(ret.comments.length, 2); assert.equal(ret.comments[0].body, 'worked great'); assert.equal(ret.comments[0].title, 'MongoDB++'); assert.strictEqual(true, !!ret.comments[0].comments); @@ -358,7 +358,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(1, ret._doc.comments[0]._doc.newprop); + assert.equal(ret._doc.comments[0]._doc.newprop, 1); assert.strictEqual(undefined, ret._doc.comments[1]._doc.newprop); assert.ok(ret.date instanceof Date); assert.equal(ret.date.toString(), new Date(update.$set.date).toString()); @@ -383,7 +383,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(1, ret.owners.length); + assert.equal(ret.owners.length, 1); assert.equal(ret.owners[0].toString(), owner.toString()); last = ret; @@ -407,7 +407,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(2, ret.owners.length); + assert.equal(ret.owners.length, 2); assert.equal(ret.owners[0].toString(), owner.toString()); assert.equal(ret.owners[1].toString(), newowner.toString()); @@ -431,7 +431,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(1, ret.owners.length); + assert.equal(ret.owners.length, 1); assert.equal(ret.owners[0].toString(), last.toString()); assert.strictEqual(undefined, ret.title); db.close(done); @@ -454,7 +454,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(2, ret.comments.length, 2); + assert.equal(ret.comments.length, 2, 2); assert.equal(ret.comments[0].body, 'worked great'); assert.equal(ret.comments[1].body, '9000'); assert.equal(ret.comments[0].comments[0].date.toString(), new Date('11/5/2011').toString()); @@ -479,7 +479,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(1, ret.comments.length); + assert.equal(ret.comments.length, 1); assert.equal(ret.comments[0].body, '9000'); db.close(done); }); @@ -501,7 +501,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(0, ret.comments.length); + assert.equal(ret.comments.length, 0); last = ret; db.close(done); @@ -522,7 +522,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(2, ret.comments.length); + assert.equal(ret.comments.length, 2); var update = { $pull: {comments: {body: {$nin: ['there']}}} @@ -532,7 +532,7 @@ describe('model: update:', function() { assert.ifError(err); BlogPost.findById(post, function(err, ret) { assert.ifError(err); - assert.equal(1, ret.comments.length); + assert.equal(ret.comments.length, 1); db.close(done); }); }); @@ -553,7 +553,7 @@ describe('model: update:', function() { BlogPost.findOne({_id: post.get('_id')}, function(err, doc) { db.close(); assert.ifError(err); - assert.equal(9, doc.get('meta.visitors')); + assert.equal(doc.get('meta.visitors'), 9); done(); }); } @@ -577,9 +577,9 @@ describe('model: update:', function() { var S = db.model('UpdateStrictSchema'); var doc = S.find()._castUpdate({ignore: true}); - assert.equal(false, doc); + assert.equal(doc, false); doc = S.find()._castUpdate({$unset: {x: 1}}); - assert.equal(1, Object.keys(doc.$unset).length); + assert.equal(Object.keys(doc.$unset).length, 1); db.close(done); }); @@ -593,7 +593,7 @@ describe('model: update:', function() { S.update({_id: s._id}, {ignore: true}, function(err, affected) { assert.ifError(err); - assert.equal(0, affected.n); + assert.equal(affected.n, 0); S.findById(s._id, function(err, doc) { assert.ifError(err); @@ -602,7 +602,7 @@ describe('model: update:', function() { S.update({_id: s._id}, {name: 'Drukqs', foo: 'fooey'}, function(err, affected) { assert.ifError(err); - assert.equal(1, affected.n); + assert.equal(affected.n, 1); S.findById(s._id, function(err, doc) { db.close(); @@ -626,7 +626,7 @@ describe('model: update:', function() { B.update({}, {title: 'newtitle'}, {multi: true}, function(err, affected) { db.close(); assert.ifError(err); - assert.equal(3, affected.n); + assert.equal(affected.n, 3); done(); }); }); @@ -659,7 +659,7 @@ describe('model: update:', function() { assert.ifError(err); M.update({_id: doc._id}, {$pull: {comments: {name: 'node 0.8'}}}, function(err, affected) { assert.ifError(err); - assert.equal(1, affected.n); + assert.equal(affected.n, 1); db.close(); done(); }); @@ -697,11 +697,11 @@ describe('model: update:', function() { Project.findById(pid, function(err, proj) { assert.ifError(err); assert.ok(proj); - assert.equal(1, proj.components.length); - assert.equal('component', proj.components[0].name); + assert.equal(proj.components.length, 1); + assert.equal(proj.components[0].name, 'component'); assert.equal(comp.id, proj.components[0].id); - assert.equal(1, proj.components[0].tasks.length); - assert.equal('my task', proj.components[0].tasks[0].name); + assert.equal(proj.components[0].tasks.length, 1); + assert.equal(proj.components[0].tasks[0].name, 'my task'); assert.equal(task.id, proj.components[0].tasks[0].id); db.close(done); }); @@ -720,8 +720,8 @@ describe('model: update:', function() { assert.ifError(err); M.findById(m, function(err, doc) { assert.ifError(err); - assert.equal(1, doc.counts['1']); - assert.equal(10, doc.counts['1a']); + assert.equal(doc.counts['1'], 1); + assert.equal(doc.counts['1a'], 10); db.close(done); }); }); @@ -764,13 +764,13 @@ describe('model: update:', function() { var sId1 = doc1._id; Some.where({_id: sId0}).update({}, {$set: {num: '99'}}, {multi: true}, function(err, cnt) { assert.ifError(err); - assert.equal(1, cnt.n); + assert.equal(cnt.n, 1); Some.findById(sId0, function(err, doc0_1) { assert.ifError(err); - assert.equal(99, doc0_1.num); + assert.equal(doc0_1.num, 99); Some.findById(sId1, function(err, doc1_1) { assert.ifError(err); - assert.equal(1, doc1_1.num); + assert.equal(doc1_1.num, 1); db.close(done); }); }); @@ -805,8 +805,8 @@ describe('model: update:', function() { assert.ifError(err); M.findOne(function(err, doc) { assert.ifError(err); - assert.equal(47, doc.age); - assert.equal('set on insert', doc.name); + assert.equal(doc.age, 47); + assert.equal(doc.name, 'set on insert'); var match = {name: 'set on insert'}; var op = {$setOnInsert: {age: 108}, name: 'changed'}; @@ -814,8 +814,8 @@ describe('model: update:', function() { assert.ifError(err); M.findOne(function(err, doc) { - assert.equal(47, doc.age); - assert.equal('changed', doc.name); + assert.equal(doc.age, 47); + assert.equal(doc.name, 'changed'); db.close(done); }); }); @@ -851,8 +851,8 @@ describe('model: update:', function() { M.findById(created._id, function(err, doc) { assert.ifError(err); assert.equal(created.id, doc.id); - assert.equal(1, doc.n.length); - assert.equal(10, doc.n[0].x); + assert.equal(doc.n.length, 1); + assert.equal(doc.n[0].x, 10); op = { $push: { @@ -899,7 +899,7 @@ describe('model: update:', function() { var m = new M({name: '2.6', n: [{x: 0}]}); m.save(function(error, m) { assert.ifError(error); - assert.equal(1, m.n.length); + assert.equal(m.n.length, 1); M.update( {name: '2.6'}, {$push: {n: {$each: [{x: 2}, {x: 1}], $position: 0}}}, @@ -907,10 +907,10 @@ describe('model: update:', function() { assert.ifError(error); M.findOne({name: '2.6'}, function(error, m) { assert.ifError(error); - assert.equal(3, m.n.length); - assert.equal(2, m.n[0].x); - assert.equal(1, m.n[1].x); - assert.equal(0, m.n[2].x); + assert.equal(m.n.length, 3); + assert.equal(m.n[0].x, 2); + assert.equal(m.n[1].x, 1); + assert.equal(m.n[2].x, 0); db.close(done); }); }); @@ -1052,8 +1052,8 @@ describe('model: update:', function() { assert.ifError(error); Breakfast.findOne({}).lean().exec(function(error, breakfast) { assert.ifError(error); - assert.equal('eggs', breakfast.base); - assert.equal('bacon', breakfast.topping); + assert.equal(breakfast.base, 'eggs'); + assert.equal(breakfast.topping, 'bacon'); db.close(done); }); }); @@ -1070,8 +1070,8 @@ describe('model: update:', function() { assert.ifError(error); Breakfast.findOne({}, function(error, breakfast) { assert.ifError(error); - assert.equal('eggs', breakfast.base); - assert.equal('sausage', breakfast.topping); + assert.equal(breakfast.base, 'eggs'); + assert.equal(breakfast.topping, 'sausage'); db.close(); done(); }); @@ -1089,8 +1089,8 @@ describe('model: update:', function() { assert.ifError(error); Breakfast.findOne({}, function(error, breakfast) { assert.ifError(error); - assert.equal('eggs', breakfast.base); - assert.equal('bacon', breakfast.topping); + assert.equal(breakfast.base, 'eggs'); + assert.equal(breakfast.topping, 'bacon'); db.close(); done(); }); @@ -1119,9 +1119,9 @@ describe('model: update:', function() { var updateOptions = {upsert: true, setDefaultsOnInsert: true, runValidators: true}; Breakfast.update({}, {topping: 'bacon', base: 'eggs'}, updateOptions, function(error) { assert.ok(!!error); - assert.equal(1, Object.keys(error.errors).length); - assert.equal('topping', Object.keys(error.errors)[0]); - assert.equal('Validator failed for path `topping` with value `bacon`', error.errors.topping.message); + assert.equal(Object.keys(error.errors).length, 1); + assert.equal(Object.keys(error.errors)[0], 'topping'); + assert.equal(error.errors.topping.message, 'Validator failed for path `topping` with value `bacon`'); Breakfast.findOne({}, function(error, breakfast) { assert.ifError(error); @@ -1150,11 +1150,11 @@ describe('model: update:', function() { var updateOptions = {runValidators: true, context: 'query'}; Breakfast.update({}, {$unset: {steak: ''}, $setOnInsert: {eggs: 'softboiled'}}, updateOptions, function(error) { assert.ok(!!error); - assert.equal(2, Object.keys(error.errors).length); + assert.equal(Object.keys(error.errors).length, 2); assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1); assert.ok(Object.keys(error.errors).indexOf('steak') !== -1); - assert.equal('Validator failed for path `eggs` with value `softboiled`', error.errors.eggs.message); - assert.equal('Path `steak` is required.', error.errors.steak.message); + assert.equal(error.errors.eggs.message, 'Validator failed for path `eggs` with value `softboiled`'); + assert.equal(error.errors.steak.message, 'Path `steak` is required.'); db.close(); done(); }); @@ -1173,21 +1173,21 @@ describe('model: update:', function() { var updateOptions = {runValidators: true}; Breakfast.update({}, {$set: {steak: 'ribeye', eggs: 3, bacon: '3 strips'}}, updateOptions, function(error) { assert.ok(!!error); - assert.equal(1, Object.keys(error.errors).length); - assert.equal('eggs', Object.keys(error.errors)[0]); - assert.equal('Path `eggs` (3) is less than minimum allowed value (4).', error.errors.eggs.message); + assert.equal(Object.keys(error.errors).length, 1); + assert.equal(Object.keys(error.errors)[0], 'eggs'); + assert.equal(error.errors.eggs.message, 'Path `eggs` (3) is less than minimum allowed value (4).'); Breakfast.update({}, {$set: {steak: 'tofu', eggs: 5, bacon: '3 strips'}}, updateOptions, function(error) { assert.ok(!!error); - assert.equal(1, Object.keys(error.errors).length); - assert.equal('steak', Object.keys(error.errors)[0]); - assert.equal('`tofu` is not a valid enum value for path `steak`.', error.errors.steak); + assert.equal(Object.keys(error.errors).length, 1); + assert.equal(Object.keys(error.errors)[0], 'steak'); + assert.equal(error.errors.steak, '`tofu` is not a valid enum value for path `steak`.'); Breakfast.update({}, {$set: {steak: 'sirloin', eggs: 6, bacon: 'none'}}, updateOptions, function(error) { assert.ok(!!error); - assert.equal(1, Object.keys(error.errors).length); - assert.equal('bacon', Object.keys(error.errors)[0]); - assert.equal('Path `bacon` is invalid (none).', error.errors.bacon.message); + assert.equal(Object.keys(error.errors).length, 1); + assert.equal(Object.keys(error.errors)[0], 'bacon'); + assert.equal(error.errors.bacon.message, 'Path `bacon` is invalid (none).'); db.close(); done(); @@ -1209,7 +1209,7 @@ describe('model: update:', function() { var updateOptions = {runValidators: true}; Breakfast.update({}, {$set: {steak: 'tofu', eggs: 2, bacon: '3 strips'}}, updateOptions, function(error) { assert.ok(!!error); - assert.equal(2, Object.keys(error.errors).length); + assert.equal(Object.keys(error.errors).length, 2); assert.ok(Object.keys(error.errors).indexOf('steak') !== -1); assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1); db.close(); @@ -1344,15 +1344,15 @@ describe('model: update:', function() { var gnr = new Band({members: ['Axl', 'Slash', 'Izzy', 'Duff', 'Adler']}); gnr.save(function(error) { assert.ifError(error); - assert.equal(0, numPres); - assert.equal(0, numPosts); + assert.equal(numPres, 0); + assert.equal(numPosts, 0); Band.update( {_id: gnr._id}, {$pull: {members: 'Adler'}}, function(error) { assert.ifError(error); - assert.equal(1, numPres); - assert.equal(1, numPosts); + assert.equal(numPres, 1); + assert.equal(numPosts, 1); Band.findOne({_id: gnr._id}, function(error, doc) { assert.ifError(error); assert.deepEqual(['Axl', 'Slash', 'Izzy', 'Duff'], diff --git a/test/object.create.null.test.js b/test/object.create.null.test.js index d49f95ba7aa..19e11b2ab6f 100644 --- a/test/object.create.null.test.js +++ b/test/object.create.null.test.js @@ -64,11 +64,11 @@ describe('is compatible with object created using Object.create(null) (gh-1484)' var m = new M(o); - assert.equal(9, m.b.c); - assert.equal('hi i am a string', m.b.d[0].e); + assert.equal(m.b.c, 9); + assert.equal(m.b.d[0].e, 'hi i am a string'); assert.equal(date, m.f.g); - assert.equal(1, m.h.ad); - assert.equal(2, m.h.hoc); + assert.equal(m.h.ad, 1); + assert.equal(m.h.hoc, 2); assert.deepEqual({}, m.h.obj); }); @@ -96,8 +96,8 @@ describe('is compatible with object created using Object.create(null) (gh-1484)' thing.h = 'yes'; m.set('h.obj.thing', thing); - assert.equal(9, m.b.c); - assert.equal('hi i am a string', m.b.d[0].e); + assert.equal(m.b.c, 9); + assert.equal(m.b.d[0].e, 'hi i am a string'); assert.equal(date, m.f.g); assert.deepEqual('yes', m.h.obj.thing.h); done(); @@ -133,3 +133,4 @@ describe('is compatible with object created using Object.create(null) (gh-1484)' done(); }); }); + diff --git a/test/promise.test.js b/test/promise.test.js index 621bdc5b4e6..baacf81de5e 100644 --- a/test/promise.test.js +++ b/test/promise.test.js @@ -29,7 +29,7 @@ describe('Promise', function() { called++; }); - assert.equal(2, called); + assert.equal(called, 2); done(); }); @@ -49,7 +49,7 @@ describe('Promise', function() { called++; }); - assert.equal(2, called); + assert.equal(called, 2); done(); }); @@ -58,18 +58,18 @@ describe('Promise', function() { called = 0; promise.on('reject', function(err) { - assert.equal(9, err); + assert.equal(err, 9); called++; }); promise.reject(9); promise.on('reject', function(err) { - assert.equal(9, err); + assert.equal(err, 9); called++; }); - assert.equal(2, called); + assert.equal(called, 2); done(); }); @@ -84,7 +84,7 @@ describe('Promise', function() { promise.reject(new Error('dawg')); - assert.equal(1, called); + assert.equal(called, 1); done(); }); @@ -104,7 +104,7 @@ describe('Promise', function() { called++; }); - assert.equal(2, called); + assert.equal(called, 2); done(); }); @@ -123,7 +123,7 @@ describe('Promise', function() { assert.ok(err instanceof Error); called++; }); - assert.equal(2, called); + assert.equal(called, 2); done(); }); }); @@ -140,7 +140,7 @@ describe('Promise', function() { promise.fulfill(); - assert.equal(1, called); + assert.equal(called, 1); done(); }); }); @@ -156,7 +156,7 @@ describe('Promise', function() { }); promise.reject(new Error); - assert.equal(1, called); + assert.equal(called, 1); done(); }); }); @@ -190,7 +190,7 @@ describe('Promise', function() { it('casts arguments to Error', function(done) { var p = new Promise(function(err) { assert.ok(err instanceof Error); - assert.equal('3', err.message); + assert.equal(err.message, '3'); done(); }); @@ -201,7 +201,7 @@ describe('Promise', function() { describe('reject()', function() { it('does not cast arguments to Error', function(done) { var p = new Promise(function(err) { - assert.equal(3, err); + assert.equal(err, 3); done(); }); @@ -219,3 +219,4 @@ describe('Promise', function() { done(); }); }); + diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 41cfe1d5c8b..3418464cb20 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -77,7 +77,7 @@ describe('query middleware', function() { assert.ifError(error); Author.find({x: 1}, function(error) { assert.ifError(error); - assert.equal(1, count); + assert.equal(count, 1); done(); }); }); @@ -86,9 +86,9 @@ describe('query middleware', function() { it('has post find hooks', function(done) { var postCount = 0; schema.post('find', function(results, next) { - assert.equal(1, results.length); - assert.equal('Val', results[0].author); - assert.equal('bacon', results[0].options); + assert.equal(results.length, 1); + assert.equal(results[0].author, 'Val'); + assert.equal(results[0].options, 'bacon'); ++postCount; next(); }); @@ -97,8 +97,8 @@ describe('query middleware', function() { assert.ifError(error); Author.find({title: 'Professional AngularJS'}, function(error, docs) { assert.ifError(error); - assert.equal(1, postCount); - assert.equal(1, docs.length); + assert.equal(postCount, 1); + assert.equal(docs.length, 1); done(); }); }); @@ -113,8 +113,8 @@ describe('query middleware', function() { var postCount = 0; schema.post('find', function(results, next) { - assert.equal(1, results.length); - assert.equal('Val', results[0].author); + assert.equal(results.length, 1); + assert.equal(results[0].author, 'Val'); ++postCount; next(); }); @@ -122,9 +122,9 @@ describe('query middleware', function() { initializeData(function() { Author.find({title: 'Professional AngularJS'}).exec(function(error, docs) { assert.ifError(error); - assert.equal(1, count); - assert.equal(1, postCount); - assert.equal(1, docs.length); + assert.equal(count, 1); + assert.equal(postCount, 1); + assert.equal(docs.length, 1); done(); }); }); @@ -139,7 +139,7 @@ describe('query middleware', function() { var postCount = 0; schema.post('findOne', function(result, next) { - assert.equal('Val', result.author); + assert.equal(result.author, 'Val'); ++postCount; next(); }); @@ -147,9 +147,9 @@ describe('query middleware', function() { initializeData(function() { Author.findOne({title: 'Professional AngularJS'}).exec(function(error, doc) { assert.ifError(error); - assert.equal(1, count); - assert.equal(1, postCount); - assert.equal('Val', doc.author); + assert.equal(count, 1); + assert.equal(postCount, 1); + assert.equal(doc.author, 'Val'); done(); }); }); @@ -164,8 +164,8 @@ describe('query middleware', function() { initializeData(function() { Author.findOne({title: 'Professional AngularJS'}).exec(function(error, doc) { assert.ifError(error); - assert.equal('Val', doc.author); - assert.equal('Wiley', doc.publisher.name); + assert.equal(doc.author, 'Val'); + assert.equal(doc.publisher.name, 'Wiley'); done(); }); }); @@ -181,8 +181,8 @@ describe('query middleware', function() { initializeData(function() { Author.findOne({title: 'Professional AngularJS'}).exec(function(error, doc) { assert.ifError(error); - assert.equal('Val', doc.author); - assert.equal('Wiley', doc.publisher.name); + assert.equal(doc.author, 'Val'); + assert.equal(doc.publisher.name, 'Wiley'); done(); }); }); @@ -204,11 +204,12 @@ describe('query middleware', function() { assert.ifError(error); Author.find({title: 'Professional AngularJS'}).count(function(error, count) { assert.ifError(error); - assert.equal(1, count); - assert.equal(1, preCount); - assert.equal(1, postCount); + assert.equal(count, 1); + assert.equal(preCount, 1); + assert.equal(postCount, 1); done(); }); }); }); }); + diff --git a/test/query.test.js b/test/query.test.js index 915958a89c0..799c69a3d93 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -819,10 +819,10 @@ describe('Query', function() { _docs: {} }; q.populate(o); - assert.equal(1, Object.keys(q._mongooseOptions.populate).length); + assert.equal(Object.keys(q._mongooseOptions.populate).length, 1); assert.deepEqual(o, q._mongooseOptions.populate['yellow.brick']); q.populate('yellow.brick'); - assert.equal(1, Object.keys(q._mongooseOptions.populate).length); + assert.equal(Object.keys(q._mongooseOptions.populate).length, 1); o.match = undefined; assert.deepEqual(o, q._mongooseOptions.populate['yellow.brick']); done(); @@ -839,7 +839,7 @@ describe('Query', function() { options: undefined, _docs: {} }; - assert.equal(2, Object.keys(q._mongooseOptions.populate).length); + assert.equal(Object.keys(q._mongooseOptions.populate).length, 2); assert.deepEqual(o, q._mongooseOptions.populate['yellow.brick']); o.path = 'dirt'; assert.deepEqual(o, q._mongooseOptions.populate.dirt); @@ -1031,13 +1031,13 @@ describe('Query', function() { setTimeout(function() { Product.find({tags: 12345}, function(err, p) { assert.ifError(err); - assert.equal(1, p.length); + assert.equal(p.length, 1); Product.find({tags: 123456}).remove(); setTimeout(function() { Product.find({tags: 123456}, function(err, p) { assert.ifError(err); - assert.equal(0, p.length); + assert.equal(p.length, 0); db.close(); done(); }); @@ -1185,7 +1185,7 @@ describe('Query', function() { q.hint(hint); var options = q._optionsForExec({schema: {options: {safe: true}}}); - assert.equal(a, JSON.stringify(options)); + assert.equal(JSON.stringify(options), a); done(); }); }); @@ -1206,15 +1206,15 @@ describe('Query', function() { it('works', function(done) { var query = new Query({}, {}, null, p1.collection); query.slaveOk(); - assert.equal(true, query.options.slaveOk); + assert.equal(query.options.slaveOk, true); query = new Query({}, {}, null, p1.collection); query.slaveOk(true); - assert.equal(true, query.options.slaveOk); + assert.equal(query.options.slaveOk, true); query = new Query({}, {}, null, p1.collection); query.slaveOk(false); - assert.equal(false, query.options.slaveOk); + assert.equal(query.options.slaveOk, false); done(); }); }); @@ -1223,22 +1223,22 @@ describe('Query', function() { it('works', function(done) { var query = new Query({}, {}, null, p1.collection); query.tailable(); - assert.equal(true, query.options.tailable); + assert.equal(query.options.tailable, true); query = new Query({}, {}, null, p1.collection); query.tailable(true); - assert.equal(true, query.options.tailable); + assert.equal(query.options.tailable, true); query = new Query({}, {}, null, p1.collection); query.tailable(false); - assert.equal(false, query.options.tailable); + assert.equal(query.options.tailable, false); done(); }); it('supports passing the `await` option', function(done) { var query = new Query({}, {}, null, p1.collection); query.tailable({awaitdata: true}); - assert.equal(true, query.options.tailable); - assert.equal(true, query.options.awaitdata); + assert.equal(query.options.tailable, true); + assert.equal(query.options.awaitdata, true); done(); }); }); @@ -1246,7 +1246,7 @@ describe('Query', function() { describe('comment', function() { it('works', function(done) { var query = new Query; - assert.equal('function', typeof query.comment); + assert.equal(typeof query.comment, 'function'); assert.equal(query.comment('Lowpass is more fun'), query); assert.equal(query.options.comment, 'Lowpass is more fun'); done(); @@ -1272,7 +1272,7 @@ describe('Query', function() { it('works', function(done) { var query = new Query({}, {}, null, p1.collection); query.snapshot(true); - assert.equal(true, query.options.snapshot); + assert.equal(query.options.snapshot, true); done(); }); }); @@ -1400,7 +1400,7 @@ describe('Query', function() { var ret = getopts.call(this, model); assert.ok(ret.readPreference); - assert.equal('secondary', ret.readPreference.mode); + assert.equal(ret.readPreference.mode, 'secondary'); assert.deepEqual({w: 'majority'}, ret.safe); called = true; diff --git a/test/schema.documentarray.test.js b/test/schema.documentarray.test.js index fb91288d060..e706555b924 100644 --- a/test/schema.documentarray.test.js +++ b/test/schema.documentarray.test.js @@ -32,8 +32,8 @@ describe('schema.documentarray', function() { [M, N, O].forEach(function(M) { var m = new M; assert.ok(Array.isArray(m.x)); - assert.equal(1, m.x.length); - assert.equal('Prometheus', m.x[0].title); + assert.equal(m.x.length, 1); + assert.equal(m.x[0].title, 'Prometheus'); }); done(); }); diff --git a/test/schema.mixed.test.js b/test/schema.mixed.test.js index 83c5a49b482..43b122a0fbd 100644 --- a/test/schema.mixed.test.js +++ b/test/schema.mixed.test.js @@ -16,8 +16,8 @@ describe('schematype mixed', function() { var m1 = new M; var m2 = new M; m1.mix.val = 3; - assert.equal(3, m1.mix.val); - assert.equal(undefined, m2.mix.val); + assert.equal(m1.mix.val, 3); + assert.equal(m2.mix.val, undefined); done(); }); it('can be forced to share the object between documents', function(done) { @@ -27,8 +27,8 @@ describe('schematype mixed', function() { var m1 = new M; var m2 = new M; m1.mix.val = 3; - assert.equal(3, m1.mix.val); - assert.equal(3, m2.mix.val); + assert.equal(m1.mix.val, 3); + assert.equal(m2.mix.val, 3); done(); }); }); diff --git a/test/schema.onthefly.test.js b/test/schema.onthefly.test.js index 8f54ff6e1dc..20910aa8df1 100644 --- a/test/schema.onthefly.test.js +++ b/test/schema.onthefly.test.js @@ -25,7 +25,7 @@ describe('schema.onthefly', function() { db.close(); var post = new Decorated(); post.set('adhoc', '9', Number); - assert.equal(9, post.get('adhoc').valueOf()); + assert.equal(post.get('adhoc').valueOf(), 9); done(); }); @@ -51,23 +51,23 @@ describe('schema.onthefly', function() { var post = new Decorated({title: 'AD HOC'}); // Interpret adhoc as a Number post.set('adhoc', '9', Number); - assert.equal(9, post.get('adhoc').valueOf()); + assert.equal(post.get('adhoc').valueOf(), 9); post.save(function(err) { assert.ifError(err); assert.strictEqual(null, err); Decorated.findById(post.id, function(err, found) { db.close(); assert.strictEqual(null, err); - assert.equal(9, found.get('adhoc')); + assert.equal(found.get('adhoc'), 9); // Interpret adhoc as a String instead of a Number now - assert.equal('9', found.get('adhoc', String)); - assert.equal('9', found.get('adhoc')); + assert.equal(found.get('adhoc', String), '9'); + assert.equal(found.get('adhoc'), '9'); // set adhoc as an Object found.set('adhoc', '3', Object); - assert.equal('string', typeof found.get('adhoc')); + assert.equal(typeof found.get('adhoc'), 'string'); found.set('adhoc', 3, Object); - assert.equal('number', typeof found.get('adhoc')); + assert.equal(typeof found.get('adhoc'), 'number'); found.set('adhoc', ['hello'], Object); assert.ok(Array.isArray(found.get('adhoc'))); @@ -75,9 +75,9 @@ describe('schema.onthefly', function() { assert.ok(Array.isArray(found.get('adhoc'))); found.set('adhoc', 3, String); - assert.equal('string', typeof found.get('adhoc')); + assert.equal(typeof found.get('adhoc'), 'string'); found.set('adhoc', 3, Object); - assert.equal('number', typeof found.get('adhoc')); + assert.equal(typeof found.get('adhoc'), 'number'); done(); }); }); @@ -108,14 +108,14 @@ describe('schema.onthefly', function() { db.close(); assert.ifError(err); var rankingPreCast = found.get('moderators')[0].ranking; - assert.equal(1, rankingPreCast); + assert.equal(rankingPreCast, 1); assert.strictEqual(undefined, rankingPreCast.increment); var rankingPostCast = found.get('moderators', [ModeratorSchema])[0].ranking; - assert.equal(1, rankingPostCast); + assert.equal(rankingPostCast, 1); var NewModeratorSchema = new Schema({name: String, ranking: String}); rankingPostCast = found.get('moderators', [NewModeratorSchema])[0].ranking; - assert.equal(1, rankingPostCast); + assert.equal(rankingPostCast, 1); done(); }); }); @@ -126,13 +126,13 @@ describe('schema.onthefly', function() { var Decorated = db.model('gh2360', DecoratedSchema, 'gh2360'); var d = new Decorated({title: '1'}); - assert.equal('number', typeof d.get('title', 'Number')); + assert.equal(typeof d.get('title', Number), 'number'); d.title = '000000000000000000000001'; assert.equal(d.get('title', ObjectId).constructor.name, 'ObjectID'); d.set('title', 1, Number); - assert.equal('number', typeof d.get('title')); + assert.equal(typeof d.get('title'), 'number'); db.close(done); }); diff --git a/test/schema.select.test.js b/test/schema.select.test.js index 4180d7d9ebc..83d33e9c18f 100644 --- a/test/schema.select.test.js +++ b/test/schema.select.test.js @@ -36,8 +36,8 @@ describe('schema select option', function() { s = s[0]; } assert.strictEqual(null, err); - assert.equal(false, s.isSelected('name')); - assert.equal(false, s.isSelected('docs.name')); + assert.equal(s.isSelected('name'), false); + assert.equal(s.isSelected('docs.name'), false); assert.strictEqual(undefined, s.name); // we need to make sure this executes absolutely last. if (pending === 1) { @@ -158,14 +158,14 @@ describe('schema select option', function() { it('for findById', function(done) { S.findById(s).select('-name -docs.name').exec(function(err, s) { assert.strictEqual(null, err); - assert.equal(false, s.isSelected('name')); - assert.equal(true, s.isSelected('thin')); - assert.equal(false, s.isSelected('docs.name')); - assert.equal(true, s.isSelected('docs.bool')); + assert.equal(s.isSelected('name'), false); + assert.equal(s.isSelected('thin'), true); + assert.equal(s.isSelected('docs.name'), false); + assert.equal(s.isSelected('docs.bool'), true); assert.strictEqual(undefined, s.name); assert.strictEqual(undefined, s.docs[0].name); - assert.equal(true, s.thin); - assert.equal(true, s.docs[0].bool); + assert.equal(s.thin, true); + assert.equal(s.docs[0].bool, true); done(); }); }); @@ -186,14 +186,14 @@ describe('schema select option', function() { it('for findByIdAndUpdate', function(done) { S.findByIdAndUpdate(s, {thin: false}, {new: true}).select('-name -docs.name').exec(function(err, s) { assert.strictEqual(null, err); - assert.equal(false, s.isSelected('name')); - assert.equal(true, s.isSelected('thin')); - assert.equal(false, s.isSelected('docs.name')); - assert.equal(true, s.isSelected('docs.bool')); + assert.equal(s.isSelected('name'), false); + assert.equal(s.isSelected('thin'), true); + assert.equal(s.isSelected('docs.name'), false); + assert.equal(s.isSelected('docs.bool'), true); assert.strictEqual(undefined, s.name); assert.strictEqual(undefined, s.docs[0].name); - assert.equal(false, s.thin); - assert.equal(true, s.docs[0].bool); + assert.equal(s.thin, false); + assert.equal(s.docs[0].bool, true); done(); }); }); @@ -214,10 +214,10 @@ describe('schema select option', function() { E.find({_id: e._id}).select('thin name docs.name docs.bool').exec(function(err, e) { e = e[0]; assert.strictEqual(null, err); - assert.equal(true, e.isSelected('name')); - assert.equal(true, e.isSelected('thin')); - assert.equal(true, e.isSelected('docs.name')); - assert.equal(true, e.isSelected('docs.bool')); + assert.equal(e.isSelected('name'), true); + assert.equal(e.isSelected('thin'), true); + assert.equal(e.isSelected('docs.name'), true); + assert.equal(e.isSelected('docs.bool'), true); assert.equal(e.name, 'the excluded'); assert.equal(e.docs[0].name, 'test'); assert.ok(e.thin); @@ -242,10 +242,10 @@ describe('schema select option', function() { it('with findOneAndUpdate', function(done) { E.findOneAndUpdate({_id: e._id}, {name: 'changed'}, {new: true}).select('thin name docs.name docs.bool').exec(function(err, e) { assert.strictEqual(null, err); - assert.equal(true, e.isSelected('name')); - assert.equal(true, e.isSelected('thin')); - assert.equal(true, e.isSelected('docs.name')); - assert.equal(true, e.isSelected('docs.bool')); + assert.equal(e.isSelected('name'), true); + assert.equal(e.isSelected('thin'), true); + assert.equal(e.isSelected('docs.name'), true); + assert.equal(e.isSelected('docs.bool'), true); assert.equal(e.name, 'changed'); assert.equal(e.docs[0].name, 'test'); assert.ok(e.thin); @@ -285,10 +285,10 @@ describe('schema select option', function() { var query = M.findOne(); query._applyPaths(); - assert.equal(1, Object.keys(query._fields).length); - assert.equal(undefined, query._fields['docs.name1']); - assert.equal(undefined, query._fields['docs.name2']); - assert.equal(0, query._fields.docs); + assert.equal(Object.keys(query._fields).length, 1); + assert.equal(query._fields['docs.name1'], undefined); + assert.equal(query._fields['docs.name2'], undefined); + assert.equal(query._fields.docs, 0); done(); }); }); @@ -310,30 +310,30 @@ describe('schema select option', function() { .select('+name +docs.name') .exec(function(err, doc) { assert.ifError(err); - assert.equal(false, doc.thin); - assert.equal('1 meter', doc.name); - assert.equal(false, doc.docs[0].bool); - assert.equal('test', doc.docs[0].name); + assert.equal(doc.thin, false); + assert.equal(doc.name, '1 meter'); + assert.equal(doc.docs[0].bool, false); + assert.equal(doc.docs[0].name, 'test'); assert.equal(d.id, doc.id); M.findById(d) .select('+name -thin +docs.name -docs.bool') .exec(function(err, doc) { assert.ifError(err); - assert.equal(undefined, doc.thin); - assert.equal('1 meter', doc.name); - assert.equal(undefined, doc.docs[0].bool); - assert.equal('test', doc.docs[0].name); + assert.equal(doc.thin, undefined); + assert.equal(doc.name, '1 meter'); + assert.equal(doc.docs[0].bool, undefined); + assert.equal(doc.docs[0].name, 'test'); assert.equal(d.id, doc.id); M.findById(d) .select('-thin +name -docs.bool +docs.name') .exec(function(err, doc) { assert.ifError(err); - assert.equal(undefined, doc.thin); - assert.equal('1 meter', doc.name); - assert.equal(undefined, doc.docs[0].bool); - assert.equal('test', doc.docs[0].name); + assert.equal(doc.thin, undefined); + assert.equal(doc.name, '1 meter'); + assert.equal(doc.docs[0].bool, undefined); + assert.equal(doc.docs[0].name, 'test'); assert.equal(d.id, doc.id); M.findById(d) @@ -341,10 +341,10 @@ describe('schema select option', function() { .exec(function(err, doc) { db.close(); assert.ifError(err); - assert.equal(undefined, doc.thin); - assert.equal(undefined, doc.name); - assert.equal(undefined, doc.docs[0].bool); - assert.equal(undefined, doc.docs[0].name); + assert.equal(doc.thin, undefined); + assert.equal(doc.name, undefined); + assert.equal(doc.docs[0].bool, undefined); + assert.equal(doc.docs[0].name, undefined); assert.equal(d.id, doc.id); done(); }); @@ -369,7 +369,7 @@ describe('schema select option', function() { if (err) { return done(err); } - assert.equal(2, doc.many.length); + assert.equal(doc.many.length, 2); db.close(done); }); }); @@ -402,7 +402,7 @@ describe('schema select option', function() { } assert.ifError(err); assert.equal(s.name, 'bing'); - assert.equal(undefined, s.conflict); + assert.equal(s.conflict, undefined); } S.findById(s).exec(cb); @@ -477,19 +477,19 @@ describe('schema select option', function() { M.findOne().select('-_id name').exec(function(err, d) { // mongo special case for exclude _id + include path assert.ifError(err); - assert.equal(undefined, d.id); - assert.equal('ssd', d.name); - assert.equal(undefined, d.age); + assert.equal(d.id, undefined); + assert.equal(d.name, 'ssd'); + assert.equal(d.age, undefined); M.findOne().select('-_id -name').exec(function(err, d) { assert.ifError(err); - assert.equal(undefined, d.id); - assert.equal(undefined, d.name); - assert.equal(0, d.age); + assert.equal(d.id, undefined); + assert.equal(d.name, undefined); + assert.equal(d.age, 0); M.findOne().select('_id name').exec(function(err, d) { assert.ifError(err); - assert.equal(id, d.id); - assert.equal('ssd', d.name); - assert.equal(undefined, d.age); + assert.equal(d.id, id); + assert.equal(d.name, 'ssd'); + assert.equal(d.age, undefined); cb(); }); }); @@ -506,14 +506,14 @@ describe('schema select option', function() { assert.ok(!d); M.findOne().select('-age -name').exec(function(err, d) { assert.ifError(err); - assert.equal(id, d.id); - assert.equal(undefined, d.name); - assert.equal(undefined, d.age); + assert.equal(d.id, id); + assert.equal(d.name, undefined); + assert.equal(d.age, undefined); M.findOne().select('age name').exec(function(err, d) { assert.ifError(err); - assert.equal(id, d.id); - assert.equal('ssd', d.name); - assert.equal(0, d.age); + assert.equal(d.id, id); + assert.equal(d.name, 'ssd'); + assert.equal(d.age, 0); cb(); }); }); @@ -557,7 +557,7 @@ describe('schema select option', function() { assert.ifError(error); Model.findOne({}, {nested: 1}, function(error, doc) { assert.ifError(error); - assert.equal('val', doc.nested.name); + assert.equal(doc.nested.name, 'val'); db.close(done); }); }); diff --git a/test/schema.test.js b/test/schema.test.js index acdc7b5ee62..a4af0102605 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -196,7 +196,7 @@ describe('schema', function() { }); // check for global variable leak - assert.equal('undefined', typeof errorMessage); + assert.equal(typeof errorMessage, 'undefined'); var Person = new Schema({ name: String, @@ -240,7 +240,7 @@ describe('schema', function() { }, callback: { $type: Number, default: function() { - assert.equal('b', this.a); + assert.equal(this.a, 'b'); return '3'; } } @@ -281,11 +281,11 @@ describe('schema', function() { }); // test String -> Number cast - assert.equal('number', typeof Tobi.path('age').cast('0')); - assert.equal(0, (+Tobi.path('age').cast('0'))); + assert.equal(typeof Tobi.path('age').cast('0'), 'number'); + assert.equal((+Tobi.path('age').cast('0')), 0); - assert.equal('number', typeof Tobi.path('age').cast(0)); - assert.equal(0, (+Tobi.path('age').cast(0))); + assert.equal(typeof Tobi.path('age').cast(0), 'number'); + assert.equal((+Tobi.path('age').cast(0)), 0); done(); }); @@ -303,12 +303,12 @@ describe('schema', function() { }; // test Number -> String cast - assert.equal('string', typeof Tobi.path('nickname').cast(0)); - assert.equal('0', Tobi.path('nickname').cast(0)); + assert.equal(typeof Tobi.path('nickname').cast(0), 'string'); + assert.equal(Tobi.path('nickname').cast(0), '0'); // test any object that implements toString - assert.equal('string', typeof Tobi.path('nickname').cast(new Test)); - assert.equal('woot', Tobi.path('nickname').cast(new Test)); + assert.equal(typeof Tobi.path('nickname').cast(new Test), 'string'); + assert.equal(Tobi.path('nickname').cast(new Test), 'woot'); done(); }); }); @@ -340,7 +340,7 @@ describe('schema', function() { assert.ok(Loki.path('owner').cast(doc) instanceof DocumentObjectId); - assert.equal(id, Loki.path('owner').cast(doc).toString()); + assert.equal(Loki.path('owner').cast(doc).toString(), id); done(); }); @@ -373,10 +373,10 @@ describe('schema', function() { var strings = Loki.path('strings').cast(['test', 123]); assert.equal(typeof strings[0], 'string'); - assert.equal('test', strings[0]); + assert.equal(strings[0], 'test'); assert.equal(typeof strings[1], 'string'); - assert.equal('123', strings[1]); + assert.equal(strings[1], '123'); var buffers = Loki.path('buffers').cast(['\0\0\0', new Buffer('abc')]); @@ -386,10 +386,10 @@ describe('schema', function() { var nocasts = Loki.path('nocast').cast(['test', 123]); assert.equal(typeof nocasts[0], 'string'); - assert.equal('test', nocasts[0]); + assert.equal(nocasts[0], 'test'); assert.equal(typeof nocasts[1], 'number'); - assert.equal(123, nocasts[1]); + assert.equal(nocasts[1], 123); var mixed = Loki.path('mixed').cast(['test', 123, '123', {}, new Date, new DocumentObjectId]); @@ -408,16 +408,16 @@ describe('schema', function() { }); assert.strictEqual(Animal.path('isFerret').cast(null), null); - assert.equal(false, Animal.path('isFerret').cast(undefined)); - assert.equal(false, Animal.path('isFerret').cast(false)); - assert.equal(false, Animal.path('isFerret').cast(0)); - assert.equal(false, Animal.path('isFerret').cast('0')); - assert.equal(false, Animal.path('isFerret').cast('false')); - assert.equal(true, Animal.path('isFerret').cast({})); - assert.equal(true, Animal.path('isFerret').cast(true)); - assert.equal(true, Animal.path('isFerret').cast(1)); - assert.equal(true, Animal.path('isFerret').cast('1')); - assert.equal(true, Animal.path('isFerret').cast('true')); + assert.equal(Animal.path('isFerret').cast(undefined), false); + assert.equal(Animal.path('isFerret').cast(false), false); + assert.equal(Animal.path('isFerret').cast(0), false); + assert.equal(Animal.path('isFerret').cast('0'), false); + assert.equal(Animal.path('isFerret').cast('false'), false); + assert.equal(Animal.path('isFerret').cast({}), true); + assert.equal(Animal.path('isFerret').cast(true), true); + assert.equal(Animal.path('isFerret').cast(1), true); + assert.equal(Animal.path('isFerret').cast('1'), true); + assert.equal(Animal.path('isFerret').cast('true'), true); done(); }); }); @@ -432,7 +432,7 @@ describe('schema', function() { b: function() { } }); - assert.equal(3, Object.keys(a.methods).length); + assert.equal(Object.keys(a.methods).length, 3); done(); }); @@ -463,15 +463,15 @@ describe('schema', function() { name: {type: String, set: lowercase} }); - assert.equal('woot', Tobi.path('name').applySetters('WOOT')); - assert.equal(1, Tobi.path('name').setters.length); + assert.equal(Tobi.path('name').applySetters('WOOT'), 'woot'); + assert.equal(Tobi.path('name').setters.length, 1); Tobi.path('name').set(function(v) { return v + 'WOOT'; }); - assert.equal('wootwoot', Tobi.path('name').applySetters('WOOT')); - assert.equal(2, Tobi.path('name').setters.length); + assert.equal(Tobi.path('name').applySetters('WOOT'), 'wootwoot'); + assert.equal(Tobi.path('name').setters.length, 2); done(); }); @@ -498,8 +498,8 @@ describe('schema', function() { it('scope', function(done) { function lowercase(v, self) { - assert.equal('b', this.a); - assert.equal('name', self.path); + assert.equal(this.a, 'b'); + assert.equal(self.path, 'name'); return v.toLowerCase(); } @@ -507,14 +507,14 @@ describe('schema', function() { name: {type: String, set: lowercase} }); - assert.equal('what', Tobi.path('name').applySetters('WHAT', {a: 'b'})); + assert.equal(Tobi.path('name').applySetters('WHAT', {a: 'b'}), 'what'); done(); }); it('casting', function(done) { function last(v) { - assert.equal('number', typeof v); - assert.equal(0, v); + assert.equal(typeof v, 'number'); + assert.equal(v, 0); return 'last'; } @@ -527,7 +527,7 @@ describe('schema', function() { }); Tobi.path('name').set(first); - assert.equal('last', Tobi.path('name').applySetters('woot')); + assert.equal(Tobi.path('name').applySetters('woot'), 'last'); done(); }); @@ -550,8 +550,8 @@ describe('schema', function() { name: {type: String, lowercase: true} }); - assert.equal('what', Tobi.path('name').applySetters('WHAT')); - assert.equal('1977', Tobi.path('name').applySetters(1977)); + assert.equal(Tobi.path('name').applySetters('WHAT'), 'what'); + assert.equal(Tobi.path('name').applySetters(1977), '1977'); done(); }); it('uppercase', function(done) { @@ -559,8 +559,8 @@ describe('schema', function() { name: {type: String, uppercase: true} }); - assert.equal('WHAT', Tobi.path('name').applySetters('what')); - assert.equal('1977', Tobi.path('name').applySetters(1977)); + assert.equal(Tobi.path('name').applySetters('what'), 'WHAT'); + assert.equal(Tobi.path('name').applySetters(1977), '1977'); done(); }); it('trim', function(done) { @@ -568,8 +568,8 @@ describe('schema', function() { name: {type: String, uppercase: true, trim: true} }); - assert.equal('WHAT', Tobi.path('name').applySetters(' what ')); - assert.equal('1977', Tobi.path('name').applySetters(1977)); + assert.equal(Tobi.path('name').applySetters(' what '), 'WHAT'); + assert.equal(Tobi.path('name').applySetters(1977), '1977'); done(); }); }); @@ -579,7 +579,7 @@ describe('schema', function() { name: String }); - assert.equal('woot', Tobi.path('name').applySetters('woot')); + assert.equal(Tobi.path('name').applySetters('woot'), 'woot'); done(); }); @@ -609,8 +609,8 @@ describe('schema', function() { name: {type: String, get: woot} }); - assert.equal(1, Tobi.path('name').getters.length); - assert.equal('test woot', Tobi.path('name').applyGetters('test')); + assert.equal(Tobi.path('name').getters.length, 1); + assert.equal(Tobi.path('name').applyGetters('test'), 'test woot'); done(); }); it('order', function(done) { @@ -624,13 +624,13 @@ describe('schema', function() { name: {type: Number, get: format} }); - assert.equal('$30', Tobi.path('name').applyGetters(30, {a: 'b'})); + assert.equal(Tobi.path('name').applyGetters(30, {a: 'b'}), '$30'); done(); }); it('scope', function(done) { function woot(v, self) { - assert.equal('b', this.a); - assert.equal('name', self.path); + assert.equal(this.a, 'b'); + assert.equal(self.path, 'name'); return v.toLowerCase(); } @@ -638,13 +638,13 @@ describe('schema', function() { name: {type: String, get: woot} }); - assert.equal('yep', Tobi.path('name').applyGetters('YEP', {a: 'b'})); + assert.equal(Tobi.path('name').applyGetters('YEP', {a: 'b'}), 'yep'); done(); }); it('casting', function(done) { function last(v) { - assert.equal('number', typeof v); - assert.equal(0, v); + assert.equal(typeof v, 'number'); + assert.equal(v, 0); return 'last'; } @@ -657,7 +657,7 @@ describe('schema', function() { }); Tobi.path('name').get(first); - assert.equal('last', Tobi.path('name').applyGetters('woot')); + assert.equal(Tobi.path('name').applyGetters('woot'), 'last'); done(); }); it('applying when none have been defined', function(done) { @@ -665,7 +665,7 @@ describe('schema', function() { name: String }); - assert.equal('woot', Tobi.path('name').applyGetters('woot')); + assert.equal(Tobi.path('name').applyGetters('woot'), 'woot'); done(); }); it('assignment of non-functions throw', function(done) { @@ -696,7 +696,7 @@ describe('schema', function() { schema = new Schema({ name: String }, {_id: false}); - assert.equal(undefined, schema.path('_id')); + assert.equal(schema.path('_id'), undefined); // old options schema = new Schema({ @@ -707,7 +707,7 @@ describe('schema', function() { schema = new Schema({ name: String }, {noId: true}); - assert.equal(undefined, schema.path('_id')); + assert.equal(schema.path('_id'), undefined); done(); }); @@ -725,7 +725,7 @@ describe('schema', function() { schema = new Schema({ name: String }, {id: false}); - assert.equal(undefined, schema.virtualpath('id')); + assert.equal(schema.virtualpath('id'), undefined); // old options schema = new Schema({ @@ -736,7 +736,7 @@ describe('schema', function() { schema = new Schema({ name: String }, {noVirtualId: true}); - assert.equal(undefined, schema.virtualpath('id')); + assert.equal(schema.virtualpath('id'), undefined); done(); }); }); @@ -767,7 +767,7 @@ describe('schema', function() { name: {type: String, index: true} }); - assert.equal(true, Tobi.path('name')._index); + assert.equal(Tobi.path('name')._index, true); Tobi.path('name').index({unique: true}); assert.deepEqual(Tobi.path('name')._index, {unique: true}); Tobi.path('name').unique(false); @@ -804,24 +804,24 @@ describe('schema', function() { name: {type: String, unique: true, sparse: true} }); i = T.path('name')._index; - assert.equal(true, i.unique); - assert.equal(true, i.sparse); + assert.equal(i.unique, true); + assert.equal(i.sparse, true); T = new Schema({ name: {type: String, index: {sparse: true, unique: true, expireAfterSeconds: 65}} }); i = T.path('name')._index; - assert.equal(true, i.unique); - assert.equal(true, i.sparse); - assert.equal(65, i.expireAfterSeconds); + assert.equal(i.unique, true); + assert.equal(i.sparse, true); + assert.equal(i.expireAfterSeconds, 65); T = new Schema({ name: {type: Date, index: {sparse: true, unique: true, expires: '24h'}} }); i = T.path('name')._index; - assert.equal(true, i.unique); - assert.equal(true, i.sparse); - assert.equal(60 * 60 * 24, i.expireAfterSeconds); + assert.equal(i.unique, true); + assert.equal(i.sparse, true); + assert.equal(i.expireAfterSeconds, 60 * 60 * 24); done(); }); @@ -858,7 +858,7 @@ describe('schema', function() { called = true; }); - assert.equal(true, called); + assert.equal(called, true); done(); }); }); @@ -867,15 +867,15 @@ describe('schema', function() { it('defaults are set', function(done) { var Tobi = new Schema(); - assert.equal('object', typeof Tobi.options); - assert.equal(undefined, Tobi.options.safe); - assert.equal(true, Tobi.options.strict); - assert.equal(false, Tobi.options.capped); - assert.equal('__v', Tobi.options.versionKey); - assert.equal('__t', Tobi.options.discriminatorKey); - assert.equal(null, Tobi.options.shardKey); - assert.equal(null, Tobi.options.read); - assert.equal(true, Tobi.options._id); + assert.equal(typeof Tobi.options, 'object'); + assert.equal(Tobi.options.safe, undefined); + assert.equal(Tobi.options.strict, true); + assert.equal(Tobi.options.capped, false); + assert.equal(Tobi.options.versionKey, '__v'); + assert.equal(Tobi.options.discriminatorKey, '__t'); + assert.equal(Tobi.options.shardKey, null); + assert.equal(Tobi.options.read, null); + assert.equal(Tobi.options._id, true); done(); }); @@ -884,151 +884,151 @@ describe('schema', function() { Tobi.set('a', 'b'); Tobi.set('safe', false); - assert.equal('users', Tobi.options.collection); + assert.equal(Tobi.options.collection, 'users'); - assert.equal('b', Tobi.options.a); + assert.equal(Tobi.options.a, 'b'); assert.deepEqual(Tobi.options.safe, {w: 0}); - assert.equal(null, Tobi.options.read); + assert.equal(Tobi.options.read, null); var tags = [{x: 1}]; Tobi.set('read', 'n'); assert.ok(Tobi.options.read instanceof ReadPref); - assert.equal('nearest', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'nearest'); Tobi.set('read', 'n', tags); - assert.equal('nearest', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'nearest'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi.set('read', ['n', tags]); - assert.equal('nearest', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'nearest'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 'p'}); assert.ok(Tobi.options.read instanceof ReadPref); - assert.equal('primary', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'primary'); Tobi = new Schema({}, {read: ['p', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); - assert.equal('primary', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'primary'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 'primary'}); assert.ok(Tobi.options.read instanceof ReadPref); - assert.equal('primary', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'primary'); Tobi = new Schema({}, {read: ['primary', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); - assert.equal('primary', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'primary'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 's'}); assert.ok(Tobi.options.read instanceof ReadPref); - assert.equal('secondary', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'secondary'); Tobi = new Schema({}, {read: ['s', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); - assert.equal('secondary', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'secondary'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 'secondary'}); assert.ok(Tobi.options.read instanceof ReadPref); - assert.equal('secondary', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'secondary'); Tobi = new Schema({}, {read: ['secondary', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); - assert.equal('secondary', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'secondary'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 'pp'}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('primaryPreferred', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'primaryPreferred'); Tobi = new Schema({}, {read: ['pp', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('primaryPreferred', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'primaryPreferred'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 'primaryPreferred'}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('primaryPreferred', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'primaryPreferred'); Tobi = new Schema({}, {read: ['primaryPreferred', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('primaryPreferred', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'primaryPreferred'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 'sp'}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('secondaryPreferred', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'secondaryPreferred'); Tobi = new Schema({}, {read: ['sp', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('secondaryPreferred', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'secondaryPreferred'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 'secondaryPreferred'}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('secondaryPreferred', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'secondaryPreferred'); Tobi = new Schema({}, {read: ['secondaryPreferred', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('secondaryPreferred', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'secondaryPreferred'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 'n'}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('nearest', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'nearest'); Tobi = new Schema({}, {read: ['n', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('nearest', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'nearest'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); Tobi = new Schema({}, {read: 'nearest'}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('nearest', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'nearest'); Tobi = new Schema({}, {read: ['nearest', tags]}); assert.ok(Tobi.options.read instanceof ReadPref); assert.ok(Tobi.options.read.isValid()); - assert.equal('nearest', Tobi.options.read.mode); + assert.equal(Tobi.options.read.mode, 'nearest'); assert.ok(Array.isArray(Tobi.options.read.tags)); - assert.equal(1, Tobi.options.read.tags.length); - assert.equal(1, Tobi.options.read.tags[0].x); + assert.equal(Tobi.options.read.tags.length, 1); + assert.equal(Tobi.options.read.tags[0].x, 1); done(); }); @@ -1075,12 +1075,12 @@ describe('schema', function() { var Tobi = new Schema; Tobi.virtual('name').get(function(v, self) { - assert.equal('b', this.a); - assert.equal('name', self.path); + assert.equal(this.a, 'b'); + assert.equal(self.path, 'name'); return v.toLowerCase(); }); - assert.equal('yep', Tobi.virtualpath('name').applyGetters('YEP', {a: 'b'})); + assert.equal(Tobi.virtualpath('name').applyGetters('YEP', {a: 'b'}), 'yep'); done(); }); }); @@ -1090,12 +1090,12 @@ describe('schema', function() { var Tobi = new Schema; Tobi.virtual('name').set(function(v, self) { - assert.equal('b', this.a); - assert.equal('name', self.path); + assert.equal(this.a, 'b'); + assert.equal(self.path, 'name'); return v.toLowerCase(); }); - assert.equal('yep', Tobi.virtualpath('name').applySetters('YEP', {a: 'b'})); + assert.equal(Tobi.virtualpath('name').applySetters('YEP', {a: 'b'}), 'yep'); done(); }); }); @@ -1141,7 +1141,7 @@ describe('schema', function() { assert.throws(function() { s.add({age: {x: Number}}, 'name.'); }, /Cannot set nested path/); - assert.equal(false, ('age' in o.name)); + assert.equal(('age' in o.name), false); o = {name: 'string'}; s = new Schema(o); @@ -1154,7 +1154,7 @@ describe('schema', function() { s.add({age: {x: Number}}, 'name.'); }, /Cannot set nested path/); - assert.equal('string', o.name); + assert.equal(o.name, 'string'); done(); }); @@ -1229,7 +1229,7 @@ describe('schema', function() { assert.ok(s.path('arr') instanceof SchemaTypes.DocumentArray); var M = goose.model('objectliteralschema', s); var m = new M({arr: [{something: 'wicked this way comes'}]}); - assert.equal('wicked this way comes', m.arr[0].something); + assert.equal(m.arr[0].something, 'wicked this way comes'); assert.ok(m.arr[0]._id); done(); }); @@ -1244,7 +1244,7 @@ describe('schema', function() { assert.ok(s.path('arr') instanceof SchemaTypes.DocumentArray); var M = goose.model('objectliteralschema2', s); var m = new M({arr: [{type: 'works'}]}); - assert.equal('works', m.arr[0].type); + assert.equal(m.arr[0].type, 'works'); assert.ok(m.arr[0]._id); done(); }); @@ -1260,7 +1260,7 @@ describe('schema', function() { }; new Schema(schema); - assert.equal(6, Object.keys(schema).length); + assert.equal(Object.keys(schema).length, 6); assert.deepEqual([{type: Schema.ObjectId, ref: 'something'}], schema.ids); assert.deepEqual({type: Array}, schema.a); assert.deepEqual(Array, schema.b); @@ -1418,45 +1418,45 @@ describe('schema', function() { describe('when called on an explicit real path', function() { it('returns "real"', function(done) { - assert.equal('real', schema.pathType('n')); - assert.equal('real', schema.pathType('nest.thing.nests')); - assert.equal('real', schema.pathType('docs')); - assert.equal('real', schema.pathType('docs.0.x')); - assert.equal('real', schema.pathType('docs.0.x.3.y')); - assert.equal('real', schema.pathType('mixed')); + assert.equal(schema.pathType('n'), 'real'); + assert.equal(schema.pathType('nest.thing.nests'), 'real'); + assert.equal(schema.pathType('docs'), 'real'); + assert.equal(schema.pathType('docs.0.x'), 'real'); + assert.equal(schema.pathType('docs.0.x.3.y'), 'real'); + assert.equal(schema.pathType('mixed'), 'real'); done(); }); }); describe('when called on a virtual', function() { it('returns virtual', function(done) { - assert.equal('virtual', schema.pathType('id')); + assert.equal(schema.pathType('id'), 'virtual'); done(); }); }); describe('when called on nested structure', function() { it('returns nested', function(done) { - assert.equal('nested', schema.pathType('nest')); - assert.equal('nested', schema.pathType('nest.thing')); + assert.equal(schema.pathType('nest'), 'nested'); + assert.equal(schema.pathType('nest.thing'), 'nested'); done(); }); }); describe('when called on undefined path', function() { it('returns adHocOrUndefined', function(done) { - assert.equal('adhocOrUndefined', schema.pathType('mixed.what')); - assert.equal('adhocOrUndefined', schema.pathType('mixed.4')); - assert.equal('adhocOrUndefined', schema.pathType('mixed.4.thing')); - assert.equal('adhocOrUndefined', schema.pathType('mixed.4a.thing')); - assert.equal('adhocOrUndefined', schema.pathType('mixed.4.9.thing')); - assert.equal('adhocOrUndefined', schema.pathType('n.3')); - assert.equal('adhocOrUndefined', schema.pathType('n.3a')); - assert.equal('adhocOrUndefined', schema.pathType('n.3.four')); - assert.equal('adhocOrUndefined', schema.pathType('n.3.4')); - assert.equal('adhocOrUndefined', schema.pathType('n.3.4a')); - assert.equal('adhocOrUndefined', schema.pathType('nest.x')); - assert.equal('adhocOrUndefined', schema.pathType('nest.thing.x')); - assert.equal('adhocOrUndefined', schema.pathType('nest.thing.nests.9')); - assert.equal('adhocOrUndefined', schema.pathType('nest.thing.nests.9a')); - assert.equal('adhocOrUndefined', schema.pathType('nest.thing.nests.a')); + assert.equal(schema.pathType('mixed.what'), 'adhocOrUndefined'); + assert.equal(schema.pathType('mixed.4'), 'adhocOrUndefined'); + assert.equal(schema.pathType('mixed.4.thing'), 'adhocOrUndefined'); + assert.equal(schema.pathType('mixed.4a.thing'), 'adhocOrUndefined'); + assert.equal(schema.pathType('mixed.4.9.thing'), 'adhocOrUndefined'); + assert.equal(schema.pathType('n.3'), 'adhocOrUndefined'); + assert.equal(schema.pathType('n.3a'), 'adhocOrUndefined'); + assert.equal(schema.pathType('n.3.four'), 'adhocOrUndefined'); + assert.equal(schema.pathType('n.3.4'), 'adhocOrUndefined'); + assert.equal(schema.pathType('n.3.4a'), 'adhocOrUndefined'); + assert.equal(schema.pathType('nest.x'), 'adhocOrUndefined'); + assert.equal(schema.pathType('nest.thing.x'), 'adhocOrUndefined'); + assert.equal(schema.pathType('nest.thing.nests.9'), 'adhocOrUndefined'); + assert.equal(schema.pathType('nest.thing.nests.9a'), 'adhocOrUndefined'); + assert.equal(schema.pathType('nest.thing.nests.a'), 'adhocOrUndefined'); done(); }); }); diff --git a/test/schema.type.test.js b/test/schema.type.test.js index 056fcdec47d..98fd5b6ea68 100644 --- a/test/schema.type.test.js +++ b/test/schema.type.test.js @@ -10,10 +10,10 @@ var mongoose = require('./common').mongoose, describe('schematype', function() { it('honors the selected option', function(done) { var s = new Schema({thought: {type: String, select: false}}); - assert.equal(false, s.path('thought').selected); + assert.ok(!s.path('thought').selected); var a = new Schema({thought: {type: String, select: true}}); - assert.equal(true, a.path('thought').selected); + assert.ok(a.path('thought').selected); done(); }); diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 2a675a118ba..0f389b26463 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -105,14 +105,14 @@ describe('schema', function() { simple: {type: String, match: /[a-z]/} }); - assert.equal(1, Test.path('simple').validators.length); + assert.equal(Test.path('simple').validators.length, 1); Test.path('simple').doValidate('az', function(err) { assert.ifError(err); }); Test.path('simple').match(/[0-9]/); - assert.equal(2, Test.path('simple').validators.length); + assert.equal(Test.path('simple').validators.length, 2); Test.path('simple').doValidate('12', function(err) { assert.ok(err instanceof ValidatorError); @@ -199,15 +199,15 @@ describe('schema', function() { Tobi.path('friends').doValidate(100, function(err) { assert.ok(err instanceof ValidatorError); - assert.equal('friends', err.path); - assert.equal('max', err.kind); - assert.equal(100, err.value); + assert.equal(err.path, 'friends'); + assert.equal(err.kind, 'max'); + assert.equal(err.value, 100); }); Tobi.path('friends').doValidate(1, function(err) { assert.ok(err instanceof ValidatorError); - assert.equal('friends', err.path); - assert.equal('min', err.kind); + assert.equal(err.path, 'friends'); + assert.equal(err.kind, 'min'); }); // null is allowed @@ -540,7 +540,7 @@ describe('schema', function() { var called = false; function validator(value, fn) { - assert.equal('b', this.a); + assert.equal(this.a, 'b'); setTimeout(function() { called = true; @@ -554,7 +554,7 @@ describe('schema', function() { Animal.path('ferret').doValidate(true, function(err) { assert.ifError(err); - assert.equal(true, called); + assert.equal(called, true); done(); }, {a: 'b'}); }); @@ -580,8 +580,8 @@ describe('schema', function() { var a = new A; a.validate(function(err) { - assert.equal('Path `requiredString1` is required.', err.errors.requiredString1); - assert.equal('oops, requiredString2 is missing. required', err.errors.requiredString2); + assert.equal(err.errors.requiredString1, 'Path `requiredString1` is required.'); + assert.equal(err.errors.requiredString2, 'oops, requiredString2 is missing. required'); a.requiredString1 = a.requiredString2 = 'hi'; a.name = 'three'; @@ -591,14 +591,14 @@ describe('schema', function() { a.numMax0 = a.numMax1 = 30; a.validate(function(err) { - assert.equal('`three` is not a valid enum value for path `name`.', err.errors.name); - assert.equal('enum validator failed for path: myenum with y', err.errors.myenum); - assert.equal('Path `matchString0` is invalid (no match).', err.errors.matchString0); - assert.equal('invalid string for matchString1 with value: no match', err.errors.matchString1); - assert.equal('Path `numMin0` (2) is less than minimum allowed value (10).', String(err.errors.numMin0)); - assert.equal('hey, numMin1 is too small', String(err.errors.numMin1)); - assert.equal('Path `numMax0` (30) is more than maximum allowed value (20).', err.errors.numMax0); - assert.equal('hey, numMax1 (30) is greater than 20', String(err.errors.numMax1)); + assert.equal(err.errors.name, '`three` is not a valid enum value for path `name`.'); + assert.equal(err.errors.myenum, 'enum validator failed for path: myenum with y'); + assert.equal(err.errors.matchString0, 'Path `matchString0` is invalid (no match).'); + assert.equal(err.errors.matchString1, 'invalid string for matchString1 with value: no match'); + assert.equal(String(err.errors.numMin0), 'Path `numMin0` (2) is less than minimum allowed value (10).'); + assert.equal(String(err.errors.numMin1), 'hey, numMin1 is too small'); + assert.equal(err.errors.numMax0, 'Path `numMax0` (30) is more than maximum allowed value (20).'); + assert.equal(String(err.errors.numMax1), 'hey, numMax1 (30) is greater than 20'); a.name = 'one'; a.myenum = 'x'; @@ -622,8 +622,8 @@ describe('schema', function() { var m = new M({x: [3, 4, 5, 6]}); m.validate(function(err) { - assert.equal('x failed validation (3,4,5,6)', String(err.errors.x)); - assert.equal('user defined', err.errors.x.kind); + assert.equal(String(err.errors.x), 'x failed validation (3,4,5,6)'); + assert.equal(err.errors.x.kind, 'user defined'); done(); }); }); @@ -645,8 +645,8 @@ describe('schema', function() { var m = new M({x: 'a'}); m.validate(function(err) { - assert.equal('Error code 25', err.errors.x.toString()); - assert.equal(25, err.errors.x.properties.errorCode); + assert.equal(err.errors.x.toString(), 'Error code 25'); + assert.equal(err.errors.x.properties.errorCode, 25); done(); }); }); @@ -667,7 +667,7 @@ describe('schema', function() { var m = new M({x: 'whatever'}); m.validate(function(err) { - assert.equal('Custom message', err.errors.x.toString()); + assert.equal(err.errors.x.toString(), 'Custom message'); done(); }); }); @@ -689,8 +689,8 @@ describe('schema', function() { var m = new M({x: [3, 4, 5, 6]}); m.validate(function(err) { - assert.equal('x failed validation (3,4,5,6)', String(err.errors.x)); - assert.equal('customType', err.errors.x.kind); + assert.equal(String(err.errors.x), 'x failed validation (3,4,5,6)'); + assert.equal(err.errors.x.kind, 'customType'); done(); }); }); @@ -709,8 +709,8 @@ describe('schema', function() { var m = new M({x: [3, 4, 5, 6]}); m.validate(function(err) { - assert.equal('x failed validation (3,4,5,6)', String(err.errors.x)); - assert.equal('customType', err.errors.x.kind); + assert.equal(String(err.errors.x), 'x failed validation (3,4,5,6)'); + assert.equal(err.errors.x.kind, 'customType'); done(); }); }); @@ -846,7 +846,7 @@ describe('schema', function() { p.a.push({str: 'asdf'}); p.validate(function(err) { assert.ifError(err); - assert.equal(1, validateCalls); + assert.equal(validateCalls, 1); done(); }); }); @@ -1132,3 +1132,4 @@ describe('schema', function() { }); }); }); + diff --git a/test/types.array.test.js b/test/types.array.test.js index cf29959705b..b33670b9cbf 100644 --- a/test/types.array.test.js +++ b/test/types.array.test.js @@ -34,7 +34,7 @@ describe('types array', function() { assert.ok(a instanceof Array); assert.ok(a.isMongooseArray); - assert.equal(true, Array.isArray(a)); + assert.equal(Array.isArray(a), true); assert.deepEqual(Object.keys(a), Object.keys(a.toObject())); assert.deepEqual(a._atomics.constructor, Object); @@ -149,14 +149,14 @@ describe('types array', function() { var m = new N({arr: [3, 4, 5, 6]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(4, doc.arr.length); + assert.equal(doc.arr.length, 4); doc.arr.push(8); assert.strictEqual(8, doc.arr[doc.arr.length - 1]); assert.strictEqual(8, doc.arr[4]); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(5, doc.arr.length); + assert.equal(doc.arr.length, 5); assert.strictEqual(3, doc.arr[0]); assert.strictEqual(4, doc.arr[1]); assert.strictEqual(5, doc.arr[2]); @@ -172,14 +172,14 @@ describe('types array', function() { var m = new S({arr: [3, 4, 5, 6]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(4, doc.arr.length); + assert.equal(doc.arr.length, 4); doc.arr.push(8); assert.strictEqual('8', doc.arr[doc.arr.length - 1]); assert.strictEqual('8', doc.arr[4]); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(5, doc.arr.length); + assert.equal(doc.arr.length, 5); assert.strictEqual('3', doc.arr[0]); assert.strictEqual('4', doc.arr[1]); assert.strictEqual('5', doc.arr[2]); @@ -195,17 +195,17 @@ describe('types array', function() { var m = new B({arr: [[0], new Buffer(1)]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(2, doc.arr.length); + assert.equal(doc.arr.length, 2); assert.ok(doc.arr[0].isMongooseBuffer); assert.ok(doc.arr[1].isMongooseBuffer); doc.arr.push('nice'); - assert.equal(3, doc.arr.length); + assert.equal(doc.arr.length, 3); assert.ok(doc.arr[2].isMongooseBuffer); assert.strictEqual('nice', doc.arr[2].toString('utf8')); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(3, doc.arr.length); + assert.equal(doc.arr.length, 3); assert.ok(doc.arr[0].isMongooseBuffer); assert.ok(doc.arr[1].isMongooseBuffer); assert.ok(doc.arr[2].isMongooseBuffer); @@ -220,15 +220,15 @@ describe('types array', function() { var m = new M({arr: [3, {x: 1}, 'yes', [5]]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(4, doc.arr.length); + assert.equal(doc.arr.length, 4); doc.arr.push(null); - assert.equal(5, doc.arr.length); + assert.equal(doc.arr.length, 5); assert.strictEqual(null, doc.arr[4]); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(5, doc.arr.length); + assert.equal(doc.arr.length, 5); assert.strictEqual(3, doc.arr[0]); assert.strictEqual(1, doc.arr[1].x); assert.strictEqual('yes', doc.arr[2]); @@ -237,17 +237,17 @@ describe('types array', function() { assert.strictEqual(null, doc.arr[4]); doc.arr.push(Infinity); - assert.equal(6, doc.arr.length); + assert.equal(doc.arr.length, 6); assert.strictEqual(Infinity, doc.arr[5]); doc.arr.push(new Buffer(0)); - assert.equal(7, doc.arr.length); + assert.equal(doc.arr.length, 7); assert.strictEqual('', doc.arr[6].toString()); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(7, doc.arr.length); + assert.equal(doc.arr.length, 7); assert.strictEqual(3, doc.arr[0]); assert.strictEqual(1, doc.arr[1].x); assert.strictEqual('yes', doc.arr[2]); @@ -267,19 +267,19 @@ describe('types array', function() { var m = new D({arr: [{name: 'aaron'}, {name: 'moombahton '}]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(2, doc.arr.length); + assert.equal(doc.arr.length, 2); doc.arr.push({name: 'Restrepo'}); - assert.equal(3, doc.arr.length); - assert.equal('Restrepo', doc.arr[2].name); + assert.equal(doc.arr.length, 3); + assert.equal(doc.arr[2].name, 'Restrepo'); save(doc, function(err, doc) { assert.ifError(err); // validate - assert.equal(3, doc.arr.length); - assert.equal('aaron', doc.arr[0].name); - assert.equal('moombahton ', doc.arr[1].name); - assert.equal('Restrepo', doc.arr[2].name); + assert.equal(doc.arr.length, 3); + assert.equal(doc.arr[0].name, 'aaron'); + assert.equal(doc.arr[1].name, 'moombahton '); + assert.equal(doc.arr[2].name, 'Restrepo'); done(); }); @@ -290,7 +290,7 @@ describe('types array', function() { var m = new ST({arr: ['ONE', 'TWO']}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(2, doc.arr.length); + assert.equal(doc.arr.length, 2); doc.arr.push('THREE'); assert.strictEqual('one', doc.arr[0]); assert.strictEqual('two', doc.arr[1]); @@ -298,7 +298,7 @@ describe('types array', function() { save(doc, function(err, doc) { assert.ifError(err); - assert.equal(3, doc.arr.length); + assert.equal(doc.arr.length, 3); assert.strictEqual('one', doc.arr[0]); assert.strictEqual('two', doc.arr[1]); assert.strictEqual('three', doc.arr[2]); @@ -332,7 +332,7 @@ describe('types array', function() { assert.ifError(err); var removed = doc.numbers.splice(1, 1, '10'); assert.deepEqual(removed, [5]); - assert.equal('number', typeof doc.numbers[1]); + assert.equal(typeof doc.numbers[1], 'number'); assert.deepEqual(doc.numbers.toObject(), [4, 10, 6, 7]); doc.save(function(err) { assert.ifError(err); @@ -487,7 +487,7 @@ describe('types array', function() { var m = new ST({arr: ['ONE', 'TWO']}); m.save(function(err, doc) { assert.ifError(err); - assert.equal(2, doc.arr.length); + assert.equal(doc.arr.length, 2); doc.arr.unshift('THREE'); assert.strictEqual('three', doc.arr[0]); assert.strictEqual('one', doc.arr[1]); @@ -495,7 +495,7 @@ describe('types array', function() { doc.save(function(err, doc) { assert.ifError(err); - assert.equal(3, doc.arr.length); + assert.equal(doc.arr.length, 3); assert.strictEqual('three', doc.arr[0]); assert.strictEqual('one', doc.arr[1]); assert.strictEqual('two', doc.arr[2]); @@ -551,7 +551,7 @@ describe('types array', function() { doc.nums.push(4); obj = doc.nums.toObject(); - assert.equal(2, obj[0].valueOf()); + assert.equal(obj[0].valueOf(), 2); assert.equal(obj[1].valueOf(), 3); assert.equal(obj[2].valueOf(), 4); @@ -598,26 +598,26 @@ describe('types array', function() { Painting.findById(p, function(err, doc) { assert.ifError(err); - assert.equal(3, doc.colors.length); + assert.equal(doc.colors.length, 3); var color = doc.colors.$shift(); - assert.equal(2, doc.colors.length); + assert.equal(doc.colors.length, 2); assert.equal(color, 'blue'); // MongoDB pop command can only be called once per save, each // time only removing one element. color = doc.colors.$shift(); assert.equal(color, undefined); - assert.equal(2, doc.colors.length); + assert.equal(doc.colors.length, 2); doc.save(function(err) { - assert.equal(null, err); + assert.equal(err, null); var color = doc.colors.$shift(); - assert.equal(1, doc.colors.length); + assert.equal(doc.colors.length, 1); assert.equal(color, 'green'); doc.save(function(err) { - assert.equal(null, err); + assert.equal(err, null); Painting.findById(doc, function(err, doc) { db.close(); assert.ifError(err); - assert.equal(1, doc.colors.length); + assert.equal(doc.colors.length, 1); assert.equal(doc.colors[0], 'yellow'); done(); }); @@ -720,7 +720,7 @@ describe('types array', function() { A.findById(a, function(err, doc) { db.close(); assert.ifError(err); - assert.equal(1, doc.a.length); + assert.equal(doc.a.length, 1); doc.a.pull(cat.id); assert.equal(doc.a.length, 0); done(); @@ -788,27 +788,27 @@ describe('types array', function() { Painting.findById(p, function(err, doc) { assert.ifError(err); - assert.equal(3, doc.colors.length); + assert.equal(doc.colors.length, 3); var color = doc.colors.$pop(); - assert.equal(2, doc.colors.length); + assert.equal(doc.colors.length, 2); assert.equal(color, 'yellow'); // MongoDB pop command can only be called once per save, each // time only removing one element. color = doc.colors.$pop(); assert.equal(color, undefined); - assert.equal(2, doc.colors.length); - assert.equal(false, '$set' in doc.colors._atomics, 'invalid $atomic op used'); + assert.equal(doc.colors.length, 2); + assert.ok(!('$set' in doc.colors._atomics), 'invalid $atomic op used'); doc.save(function(err) { - assert.equal(null, err); + assert.equal(err, null); var color = doc.colors.$pop(); - assert.equal(1, doc.colors.length); + assert.equal(doc.colors.length, 1); assert.equal(color, 'green'); doc.save(function(err) { - assert.equal(null, err); + assert.equal(err, null); Painting.findById(doc, function(err, doc) { db.close(); assert.strictEqual(null, err); - assert.equal(1, doc.colors.length); + assert.equal(doc.colors.length, 1); assert.equal(doc.colors[0], 'blue'); done(); }); @@ -856,7 +856,7 @@ describe('types array', function() { m.id.push(id1, id2); m.num.addToSet(3, 4, 5); - assert.equal(5, m.num.length); + assert.equal(m.num.length, 5); m.str.addToSet('four', 'five', 'two'); assert.equal(m.str.length, 5); m.id.addToSet(id2, id3); @@ -1071,13 +1071,13 @@ describe('types array', function() { m.doc.addToSet({name: 'Rap'}); m.save(function(error, m) { assert.ifError(error); - assert.equal(1, m.doc.length); - assert.equal('Rap', m.doc[0].name); + assert.equal(m.doc.length, 1); + assert.equal(m.doc[0].name, 'Rap'); m.doc.addToSet({name: 'House'}); - assert.equal(2, m.doc.length); + assert.equal(m.doc.length, 2); m.save(function(error, m) { assert.ifError(error); - assert.equal(2, m.doc.length); + assert.equal(m.doc.length, 2); assert.ok(m.doc.some(function(v) { return v.name === 'Rap'; })); @@ -1100,7 +1100,7 @@ describe('types array', function() { var m = new ST({arr: ['ONE', 'TWO']}); m.save(function(err, doc) { assert.ifError(err); - assert.equal(2, doc.arr.length); + assert.equal(doc.arr.length, 2); doc.arr.addToSet('THREE'); assert.strictEqual('one', doc.arr[0]); assert.strictEqual('two', doc.arr[1]); @@ -1108,7 +1108,7 @@ describe('types array', function() { doc.save(function(err, doc) { assert.ifError(err); - assert.equal(3, doc.arr.length); + assert.equal(doc.arr.length, 3); assert.strictEqual('one', doc.arr[0]); assert.strictEqual('two', doc.arr[1]); assert.strictEqual('three', doc.arr[2]); @@ -1168,10 +1168,10 @@ describe('types array', function() { M.findById(m, function(err, m) { assert.ifError(err); - assert.equal(1, m.x[0]); - assert.equal(4, m.x[1]); - assert.equal(3, m.x[2]); - assert.equal(2, m.x[3]); + assert.equal(m.x[0], 1); + assert.equal(m.x[1], 4); + assert.equal(m.x[2], 3); + assert.equal(m.x[3], 2); m.x.sort(); @@ -1180,10 +1180,10 @@ describe('types array', function() { M.findById(m, function(err, m) { assert.ifError(err); - assert.equal(1, m.x[0]); - assert.equal(2, m.x[1]); - assert.equal(3, m.x[2]); - assert.equal(4, m.x[3]); + assert.equal(m.x[0], 1); + assert.equal(m.x[1], 2); + assert.equal(m.x[2], 3); + assert.equal(m.x[3], 4); m.x.sort(function(a, b) { return b > a; @@ -1194,10 +1194,10 @@ describe('types array', function() { M.findById(m, function(err, m) { assert.ifError(err); - assert.equal(4, m.x[0]); - assert.equal(3, m.x[1]); - assert.equal(2, m.x[2]); - assert.equal(1, m.x[3]); + assert.equal(m.x[0], 4); + assert.equal(m.x[1], 3); + assert.equal(m.x[2], 2); + assert.equal(m.x[3], 1); db.close(done); }); }); @@ -1246,41 +1246,41 @@ describe('types array', function() { save(m, function(err, doc) { assert.ifError(err); - assert.equal(4, doc.arr.length); + assert.equal(doc.arr.length, 4); doc.arr.push(20); doc.arr.set(2, 10); - assert.equal(5, doc.arr.length); - assert.equal(10, doc.arr[2]); - assert.equal(20, doc.arr[4]); + assert.equal(doc.arr.length, 5); + assert.equal(doc.arr[2], 10); + assert.equal(doc.arr[4], 20); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(5, doc.arr.length); - assert.equal(3, doc.arr[0]); - assert.equal(4, doc.arr[1]); - assert.equal(10, doc.arr[2]); - assert.equal(6, doc.arr[3]); - assert.equal(20, doc.arr[4]); + assert.equal(doc.arr.length, 5); + assert.equal(doc.arr[0], 3); + assert.equal(doc.arr[1], 4); + assert.equal(doc.arr[2], 10); + assert.equal(doc.arr[3], 6); + assert.equal(doc.arr[4], 20); doc.arr.$pop(); - assert.equal(4, doc.arr.length); + assert.equal(doc.arr.length, 4); doc.arr.set(4, 99); - assert.equal(5, doc.arr.length); - assert.equal(99, doc.arr[4]); + assert.equal(doc.arr.length, 5); + assert.equal(doc.arr[4], 99); doc.arr.remove(10); - assert.equal(4, doc.arr.length); - assert.equal(3, doc.arr[0]); - assert.equal(4, doc.arr[1]); - assert.equal(6, doc.arr[2]); - assert.equal(99, doc.arr[3]); + assert.equal(doc.arr.length, 4); + assert.equal(doc.arr[0], 3); + assert.equal(doc.arr[1], 4); + assert.equal(doc.arr[2], 6); + assert.equal(doc.arr[3], 99); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(4, doc.arr.length); - assert.equal(3, doc.arr[0]); - assert.equal(4, doc.arr[1]); - assert.equal(6, doc.arr[2]); - assert.equal(99, doc.arr[3]); + assert.equal(doc.arr.length, 4); + assert.equal(doc.arr[0], 3); + assert.equal(doc.arr[1], 4); + assert.equal(doc.arr[2], 6); + assert.equal(doc.arr[3], 99); done(); }); }); @@ -1293,41 +1293,41 @@ describe('types array', function() { var m = new N({arr: [3, 4, 5, 6]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(4, doc.arr.length); + assert.equal(doc.arr.length, 4); doc.arr.set(2, 10); - assert.equal(4, doc.arr.length); - assert.equal(10, doc.arr[2]); + assert.equal(doc.arr.length, 4); + assert.equal(doc.arr[2], 10); doc.arr.set(doc.arr.length, 11); - assert.equal(5, doc.arr.length); - assert.equal(11, doc.arr[4]); + assert.equal(doc.arr.length, 5); + assert.equal(doc.arr[4], 11); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(5, doc.arr.length); - assert.equal(3, doc.arr[0]); - assert.equal(4, doc.arr[1]); - assert.equal(10, doc.arr[2]); - assert.equal(6, doc.arr[3]); - assert.equal(11, doc.arr[4]); + assert.equal(doc.arr.length, 5); + assert.equal(doc.arr[0], 3); + assert.equal(doc.arr[1], 4); + assert.equal(doc.arr[2], 10); + assert.equal(doc.arr[3], 6); + assert.equal(doc.arr[4], 11); // casting + setting beyond current array length doc.arr.set(8, '1'); - assert.equal(9, doc.arr.length); + assert.equal(doc.arr.length, 9); assert.strictEqual(1, doc.arr[8]); - assert.equal(undefined, doc.arr[7]); + assert.equal(doc.arr[7], undefined); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(9, doc.arr.length); - assert.equal(3, doc.arr[0]); - assert.equal(4, doc.arr[1]); - assert.equal(10, doc.arr[2]); - assert.equal(6, doc.arr[3]); - assert.equal(11, doc.arr[4]); - assert.equal(null, doc.arr[5]); - assert.equal(null, doc.arr[6]); - assert.equal(null, doc.arr[7]); + assert.equal(doc.arr.length, 9); + assert.equal(doc.arr[0], 3); + assert.equal(doc.arr[1], 4); + assert.equal(doc.arr[2], 10); + assert.equal(doc.arr[3], 6); + assert.equal(doc.arr[4], 11); + assert.equal(doc.arr[5], null); + assert.equal(doc.arr[6], null); + assert.equal(doc.arr[7], null); assert.strictEqual(1, doc.arr[8]); done(); }); @@ -1339,41 +1339,41 @@ describe('types array', function() { var m = new S({arr: [3, 4, 5, 6]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal('4', doc.arr.length); + assert.equal(doc.arr.length, '4'); doc.arr.set(2, 10); - assert.equal(4, doc.arr.length); - assert.equal('10', doc.arr[2]); + assert.equal(doc.arr.length, 4); + assert.equal(doc.arr[2], '10'); doc.arr.set(doc.arr.length, '11'); - assert.equal(5, doc.arr.length); - assert.equal('11', doc.arr[4]); + assert.equal(doc.arr.length, 5); + assert.equal(doc.arr[4], '11'); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(5, doc.arr.length); - assert.equal('3', doc.arr[0]); - assert.equal('4', doc.arr[1]); - assert.equal('10', doc.arr[2]); - assert.equal('6', doc.arr[3]); - assert.equal('11', doc.arr[4]); + assert.equal(doc.arr.length, 5); + assert.equal(doc.arr[0], '3'); + assert.equal(doc.arr[1], '4'); + assert.equal(doc.arr[2], '10'); + assert.equal(doc.arr[3], '6'); + assert.equal(doc.arr[4], '11'); // casting + setting beyond current array length doc.arr.set(8, 'yo'); - assert.equal(9, doc.arr.length); + assert.equal(doc.arr.length, 9); assert.strictEqual('yo', doc.arr[8]); - assert.equal(undefined, doc.arr[7]); + assert.equal(doc.arr[7], undefined); save(doc, function(err, doc) { assert.ifError(err); - assert.equal('9', doc.arr.length); - assert.equal('3', doc.arr[0]); - assert.equal('4', doc.arr[1]); - assert.equal('10', doc.arr[2]); - assert.equal('6', doc.arr[3]); - assert.equal('11', doc.arr[4]); - assert.equal(null, doc.arr[5]); - assert.equal(null, doc.arr[6]); - assert.equal(null, doc.arr[7]); + assert.equal(doc.arr.length, '9'); + assert.equal(doc.arr[0], '3'); + assert.equal(doc.arr[1], '4'); + assert.equal(doc.arr[2], '10'); + assert.equal(doc.arr[3], '6'); + assert.equal(doc.arr[4], '11'); + assert.equal(doc.arr[5], null); + assert.equal(doc.arr[6], null); + assert.equal(doc.arr[7], null); assert.strictEqual('yo', doc.arr[8]); done(); }); @@ -1385,26 +1385,26 @@ describe('types array', function() { var m = new B({arr: [[0], new Buffer(1)]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(2, doc.arr.length); + assert.equal(doc.arr.length, 2); assert.ok(doc.arr[0].isMongooseBuffer); assert.ok(doc.arr[1].isMongooseBuffer); doc.arr.set(1, 'nice'); - assert.equal(2, doc.arr.length); + assert.equal(doc.arr.length, 2); assert.ok(doc.arr[1].isMongooseBuffer); - assert.equal('nice', doc.arr[1].toString('utf8')); + assert.equal(doc.arr[1].toString('utf8'), 'nice'); doc.arr.set(doc.arr.length, [11]); - assert.equal(3, doc.arr.length); - assert.equal(11, doc.arr[2][0]); + assert.equal(doc.arr.length, 3); + assert.equal(doc.arr[2][0], 11); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(3, doc.arr.length); + assert.equal(doc.arr.length, 3); assert.ok(doc.arr[0].isMongooseBuffer); assert.ok(doc.arr[1].isMongooseBuffer); assert.ok(doc.arr[2].isMongooseBuffer); - assert.equal('\u0000', doc.arr[0].toString()); - assert.equal('nice', doc.arr[1].toString()); - assert.equal(11, doc.arr[2][0]); + assert.equal(doc.arr[0].toString(), '\u0000'); + assert.equal(doc.arr[1].toString(), 'nice'); + assert.equal(doc.arr[2][0], 11); done(); }); }); @@ -1414,50 +1414,50 @@ describe('types array', function() { var m = new M({arr: [3, {x: 1}, 'yes', [5]]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(4, doc.arr.length); + assert.equal(doc.arr.length, 4); doc.arr.set(2, null); - assert.equal(4, doc.arr.length); - assert.equal(null, doc.arr[2]); + assert.equal(doc.arr.length, 4); + assert.equal(doc.arr[2], null); doc.arr.set(doc.arr.length, 'last'); - assert.equal(5, doc.arr.length); - assert.equal('last', doc.arr[4]); + assert.equal(doc.arr.length, 5); + assert.equal(doc.arr[4], 'last'); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(5, doc.arr.length); - assert.equal(3, doc.arr[0]); + assert.equal(doc.arr.length, 5); + assert.equal(doc.arr[0], 3); assert.strictEqual(1, doc.arr[1].x); - assert.equal(null, doc.arr[2]); + assert.equal(doc.arr[2], null); assert.ok(Array.isArray(doc.arr[3])); - assert.equal(5, doc.arr[3][0]); - assert.equal('last', doc.arr[4]); + assert.equal(doc.arr[3][0], 5); + assert.equal(doc.arr[4], 'last'); doc.arr.set(8, Infinity); - assert.equal(9, doc.arr.length); + assert.equal(doc.arr.length, 9); assert.strictEqual(Infinity, doc.arr[8]); - assert.equal(undefined, doc.arr[7]); + assert.equal(doc.arr[7], undefined); doc.arr.push(new Buffer(0)); - assert.equal('', doc.arr[9].toString()); - assert.equal(10, doc.arr.length); + assert.equal(doc.arr[9].toString(), ''); + assert.equal(doc.arr.length, 10); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(10, doc.arr.length); - assert.equal(3, doc.arr[0]); + assert.equal(doc.arr.length, 10); + assert.equal(doc.arr[0], 3); assert.strictEqual(1, doc.arr[1].x); - assert.equal(null, doc.arr[2]); + assert.equal(doc.arr[2], null); assert.ok(Array.isArray(doc.arr[3])); - assert.equal(5, doc.arr[3][0]); - assert.equal('last', doc.arr[4]); + assert.equal(doc.arr[3][0], 5); + assert.equal(doc.arr[4], 'last'); assert.strictEqual(null, doc.arr[5]); assert.strictEqual(null, doc.arr[6]); assert.strictEqual(null, doc.arr[7]); assert.strictEqual(Infinity, doc.arr[8]); // arr[9] is actually a mongodb Binary since mixed won't cast to buffer - assert.equal('', doc.arr[9].toString()); + assert.equal(doc.arr[9].toString(), ''); done(); }); @@ -1469,56 +1469,56 @@ describe('types array', function() { var m = new D({arr: [{name: 'aaron'}, {name: 'moombahton '}]}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(2, doc.arr.length); + assert.equal(doc.arr.length, 2); doc.arr.set(0, {name: 'vdrums'}); - assert.equal(2, doc.arr.length); - assert.equal('vdrums', doc.arr[0].name); + assert.equal(doc.arr.length, 2); + assert.equal(doc.arr[0].name, 'vdrums'); doc.arr.set(doc.arr.length, {name: 'Restrepo'}); - assert.equal(3, doc.arr.length); - assert.equal('Restrepo', doc.arr[2].name); + assert.equal(doc.arr.length, 3); + assert.equal(doc.arr[2].name, 'Restrepo'); save(doc, function(err, doc) { assert.ifError(err); // validate - assert.equal(3, doc.arr.length); - assert.equal('vdrums', doc.arr[0].name); - assert.equal('moombahton ', doc.arr[1].name); - assert.equal('Restrepo', doc.arr[2].name); + assert.equal(doc.arr.length, 3); + assert.equal(doc.arr[0].name, 'vdrums'); + assert.equal(doc.arr[1].name, 'moombahton '); + assert.equal(doc.arr[2].name, 'Restrepo'); doc.arr.set(10, {name: 'temple of doom'}); - assert.equal(11, doc.arr.length); - assert.equal('temple of doom', doc.arr[10].name); - assert.equal(null, doc.arr[9]); + assert.equal(doc.arr.length, 11); + assert.equal(doc.arr[10].name, 'temple of doom'); + assert.equal(doc.arr[9], null); save(doc, function(err, doc) { assert.ifError(err); // validate - assert.equal(11, doc.arr.length); - assert.equal('vdrums', doc.arr[0].name); - assert.equal('moombahton ', doc.arr[1].name); - assert.equal('Restrepo', doc.arr[2].name); - assert.equal(null, doc.arr[3]); - assert.equal(null, doc.arr[9]); - assert.equal('temple of doom', doc.arr[10].name); + assert.equal(doc.arr.length, 11); + assert.equal(doc.arr[0].name, 'vdrums'); + assert.equal(doc.arr[1].name, 'moombahton '); + assert.equal(doc.arr[2].name, 'Restrepo'); + assert.equal(doc.arr[3], null); + assert.equal(doc.arr[9], null); + assert.equal(doc.arr[10].name, 'temple of doom'); doc.arr.remove(doc.arr[0]); doc.arr.set(7, {name: 7}); assert.strictEqual('7', doc.arr[7].name); - assert.equal(10, doc.arr.length); + assert.equal(doc.arr.length, 10); save(doc, function(err, doc) { assert.ifError(err); - assert.equal(10, doc.arr.length); - assert.equal('moombahton ', doc.arr[0].name); - assert.equal('Restrepo', doc.arr[1].name); - assert.equal(null, doc.arr[2]); + assert.equal(doc.arr.length, 10); + assert.equal(doc.arr[0].name, 'moombahton '); + assert.equal(doc.arr[1].name, 'Restrepo'); + assert.equal(doc.arr[2], null); assert.ok(doc.arr[7]); assert.strictEqual('7', doc.arr[7].name); - assert.equal(null, doc.arr[8]); - assert.equal('temple of doom', doc.arr[9].name); + assert.equal(doc.arr[8], null); + assert.equal(doc.arr[9].name, 'temple of doom'); done(); }); @@ -1531,7 +1531,7 @@ describe('types array', function() { var m = new ST({arr: ['ONE', 'TWO']}); save(m, function(err, doc) { assert.ifError(err); - assert.equal(2, doc.arr.length); + assert.equal(doc.arr.length, 2); doc.arr.set(0, 'THREE'); assert.strictEqual('three', doc.arr[0]); assert.strictEqual('two', doc.arr[1]); @@ -1542,7 +1542,7 @@ describe('types array', function() { save(doc, function(err, doc) { assert.ifError(err); - assert.equal(3, doc.arr.length); + assert.equal(doc.arr.length, 3); assert.strictEqual('three', doc.arr[0]); assert.strictEqual('two', doc.arr[1]); assert.strictEqual('four', doc.arr[2]); @@ -1727,17 +1727,17 @@ describe('types array', function() { m.em[m.em.length - 1].sub.push('a'); m.em.push({sub: []}); - assert.equal(2, m.em.length); - assert.equal(1, m.em[0].sub.length); + assert.equal(m.em.length, 2); + assert.equal(m.em[0].sub.length, 1); m.save(function(err) { assert.ifError(err); M.findById(m, function(err, m) { assert.ifError(err); - assert.equal(2, m.em.length); - assert.equal(1, m.em[0].sub.length); - assert.equal('a', m.em[0].sub[0]); + assert.equal(m.em.length, 2); + assert.equal(m.em[0].sub.length, 1); + assert.equal(m.em[0].sub[0], 'a'); done(); }); }); @@ -1854,7 +1854,7 @@ describe('types array', function() { B.findById(post._id, function(err, doc) { assert.ifError(err); - assert.equal(0, doc.numbers.length); + assert.equal(doc.numbers.length, 0); done(); }); }); @@ -1882,7 +1882,7 @@ describe('types array', function() { assert.ifError(err); B.findById(post, function(err, post) { assert.ifError(err); - assert.equal(3, post.stringIds.length); + assert.equal(post.stringIds.length, 3); assert.ok(!post.stringIds.id('b')); done(); }); @@ -1901,7 +1901,7 @@ describe('types array', function() { assert.ifError(err); B.findById(post, function(err, post) { assert.ifError(err); - assert.equal(2, post.numberIds.length); + assert.equal(post.numberIds.length, 2); assert.ok(!post.numberIds.id(2)); assert.ok(!post.numberIds.id(4)); done(); @@ -1925,7 +1925,7 @@ describe('types array', function() { assert.ifError(err); B.findById(post, function(err, post) { assert.ifError(err); - assert.equal(1, post.oidIds.length); + assert.equal(post.oidIds.length, 1); assert.ok(!post.oidIds.id(a)); assert.ok(!post.oidIds.id(c)); done(); @@ -1945,7 +1945,7 @@ describe('types array', function() { assert.ifError(err); B.findById(post, function(err, post) { assert.ifError(err); - assert.equal(3, post.bufferIds.length); + assert.equal(post.bufferIds.length, 3); assert.ok(!post.bufferIds.id(new Buffer('a'))); done(); }); diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js index ae0c882b333..3879208196a 100644 --- a/test/types.buffer.test.js +++ b/test/types.buffer.test.js @@ -371,8 +371,8 @@ describe('types.buffer', function() { User.findById(doc, function(err, doc) { db.close(); assert.ifError(err); - assert.equal(1, doc.array.length); - assert.equal(null, doc.array[0]); + assert.equal(doc.array.length, 1); + assert.equal(doc.array[0], null); done(); }); }); @@ -428,7 +428,7 @@ describe('types.buffer', function() { done(err); return; } - assert.equal(128, doc.buf._subtype); + assert.equal(doc.buf._subtype, 128); done(); }); }); @@ -447,7 +447,7 @@ describe('types.buffer', function() { done(err); return; } - assert.equal(128, doc.buf._subtype); + assert.equal(doc.buf._subtype, 128); doc.buf.subtype(0); doc.save(function(err) { if (err) { diff --git a/test/types.document.test.js b/test/types.document.test.js index cafc89ae077..c00f91a8714 100644 --- a/test/types.document.test.js +++ b/test/types.document.test.js @@ -181,7 +181,7 @@ describe('types.document', function() { movie.save(function() { Movie.findById(super8._id, function(err, movie) { assert.ifError(err); - assert.equal(0, movie.ratings.length); + assert.equal(movie.ratings.length, 0); db.close(done); }); }); diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js index 0a157dd6a88..d8c0c78e593 100644 --- a/test/types.documentarray.test.js +++ b/test/types.documentarray.test.js @@ -142,7 +142,7 @@ describe('types.documentarray', function() { } catch (err) { threw = err; } - assert.equal(false, threw); + assert.equal(threw, false); // test the _id option, noId is deprecated NoId = new Schema({ @@ -161,7 +161,7 @@ describe('types.documentarray', function() { } catch (err) { threw = err; } - assert.equal(false, threw); + assert.equal(threw, false); // undefined and null should not match a nonexistent _id assert.strictEqual(null, a.id(undefined)); assert.strictEqual(null, a.id(null)); @@ -235,7 +235,7 @@ describe('types.documentarray', function() { var m = new M; m.docs.push({docs: [{title: 'hello'}]}); var delta = m.$__delta()[1]; - assert.equal(undefined, delta.$pushAll.docs[0].changed); + assert.equal(delta.$pushAll.docs[0].changed, undefined); done(); }); it('uses the correct transform (gh-1412)', function(done) { @@ -281,12 +281,12 @@ describe('types.documentarray', function() { describe('create()', function() { it('works', function(done) { var a = new MongooseDocumentArray([]); - assert.equal('function', typeof a.create); + assert.equal(typeof a.create, 'function'); var schema = new Schema({docs: [new Schema({name: 'string'})]}); var T = mongoose.model('embeddedDocument#create_test', schema, 'asdfasdfa' + random()); var t = new T; - assert.equal('function', typeof t.docs.create); + assert.equal(typeof t.docs.create, 'function'); var subdoc = t.docs.create({name: 100}); assert.ok(subdoc._id); assert.equal(subdoc.name, '100'); @@ -312,9 +312,9 @@ describe('types.documentarray', function() { M.findById(m._id, function(err, doc) { assert.ifError(err); var c = doc.children.create({name: 'first'}); - assert.equal(undefined, c.date); + assert.equal(c.date, undefined); doc.children.push(c); - assert.equal(undefined, c.date); + assert.equal(c.date, undefined); doc.save(function(err) { assert.ifError(err); assert.ok(doc.children[doc.children.length - 1].date); @@ -327,7 +327,7 @@ describe('types.documentarray', function() { assert.ifError(err); M.findById(m._id, function(err, doc) { assert.ifError(err); - assert.equal(3, doc.children.length); + assert.equal(doc.children.length, 3); doc.children.forEach(function(child) { assert.equal(doc.children[0].id, child.id); }); @@ -431,7 +431,7 @@ describe('types.documentarray', function() { var M = db.model('embedded-invalidate', schema); var m = new M({docs: [{v: 900}]}); m.save(function(err) { - assert.equal(900, err.errors['docs.0.v'].value); + assert.equal(err.errors['docs.0.v'].value, 900); db.close(done); }); }); @@ -458,3 +458,4 @@ describe('types.documentarray', function() { }); }); }); + diff --git a/test/updateValidators.unit.test.js b/test/updateValidators.unit.test.js index 7eb34b1e17b..1052a45c0fa 100644 --- a/test/updateValidators.unit.test.js +++ b/test/updateValidators.unit.test.js @@ -30,10 +30,10 @@ describe('updateValidators', function() { assert.ifError(err); assert.equal(schema._getSchema.calls.length, 2); assert.equal(schema.doValidate.calls.length, 2); - assert.equal('test.a', schema._getSchema.calls[0]); - assert.equal('test.b', schema._getSchema.calls[1]); - assert.equal(1, schema.doValidate.calls[0].v); - assert.equal(null, schema.doValidate.calls[1].v); + assert.equal(schema._getSchema.calls[0], 'test.a'); + assert.equal(schema._getSchema.calls[1], 'test.b'); + assert.equal(schema.doValidate.calls[0].v, 1); + assert.equal(schema.doValidate.calls[1].v, null); done(); }); }); @@ -48,7 +48,7 @@ describe('updateValidators', function() { assert.ifError(err); assert.equal(schema._getSchema.calls.length, 1); assert.equal(schema.doValidate.calls.length, 1); - assert.equal('test', schema._getSchema.calls[0]); + assert.equal(schema._getSchema.calls[0], 'test'); assert.equal(dt, schema.doValidate.calls[0].v); done(); }); @@ -63,10 +63,11 @@ describe('updateValidators', function() { assert.ifError(err); assert.equal(schema._getSchema.calls.length, 1); assert.equal(schema.doValidate.calls.length, 1); - assert.equal('test', schema._getSchema.calls[0]); + assert.equal(schema._getSchema.calls[0], 'test'); assert.deepEqual(schema.doValidate.calls[0].v, []); done(); }); }); }); }); + diff --git a/test/utils.test.js b/test/utils.test.js index acd6170049f..edb6f19c411 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -140,7 +140,7 @@ describe('utils', function() { var o = {a: 1, b: 2, c: 3, 0: 'zero1'}; var defaults = {b: 10, d: 20, 0: 'zero2'}; var result = utils.options(defaults, o); - assert.equal(1, result.a); + assert.equal(result.a, 1); assert.equal(result.b, 2); assert.equal(result.c, 3); assert.equal(result.d, 20); @@ -244,7 +244,7 @@ describe('utils', function() { assert.strictEqual('0', out.b); assert.strictEqual(1, out.c); assert.strictEqual('1', out.d); - assert.equal(4, Object.keys(out).length); + assert.equal(Object.keys(out).length, 4); done(); }); diff --git a/test/versioning.test.js b/test/versioning.test.js index c9bac221bf5..c29445d09f2 100644 --- a/test/versioning.test.js +++ b/test/versioning.test.js @@ -151,20 +151,20 @@ describe('versioning', function() { function test12(err, a, b) { assert.ok(err instanceof VersionError); assert.ok(/No matching document/.test(err), 'changes to b should not be applied'); - assert.equal(5, a.comments.length); + assert.equal(a.comments.length, 5); a.comments.addToSet({title: 'aven'}); a.comments.addToSet({title: 'avengers'}); var d = a.$__delta(); - assert.equal(undefined, d[0].__v, 'version should not be included in where clause'); + assert.equal(d[0].__v, undefined, 'version should not be included in where clause'); assert.ok(!d[1].$set); assert.ok(d[1].$addToSet); assert.ok(d[1].$addToSet.comments); a.comments.$shift(); d = a.$__delta(); - assert.equal(12, d[0].__v, 'version should be included in where clause'); + assert.equal(d[0].__v, 12, 'version should be included in where clause'); assert.ok(d[1].$set, 'two differing atomic ops on same path should create a $set'); assert.ok(d[1].$inc, 'a $set of an array should trigger versioning'); assert.ok(!d[1].$addToSet); @@ -174,10 +174,10 @@ describe('versioning', function() { function test11(err, a, b) { assert.ifError(err); assert.equal(a._doc.__v, 11); - assert.equal(6, a.mixed.arr.length); - assert.equal(1, a.mixed.arr[4].x); - assert.equal('woot', a.mixed.arr[5]); - assert.equal(10, a.mixed.arr[3][0]); + assert.equal(a.mixed.arr.length, 6); + assert.equal(a.mixed.arr[4].x, 1); + assert.equal(a.mixed.arr[5], 'woot'); + assert.equal(a.mixed.arr[3][0], 10); a.comments.addToSet({title: 'monkey'}); b.markModified('comments'); @@ -190,11 +190,11 @@ describe('versioning', function() { function test10(err, a, b) { assert.ifError(err); - assert.equal('two', b.meta.nested[2].title); - assert.equal('zero', b.meta.nested[0].title); - assert.equal('sub one', b.meta.nested[1].comments[0].title); + assert.equal(b.meta.nested[2].title, 'two'); + assert.equal(b.meta.nested[0].title, 'zero'); + assert.equal(b.meta.nested[1].comments[0].title, 'sub one'); assert.equal(a._doc.__v, 10); - assert.equal(3, a.mixed.arr.length); + assert.equal(a.mixed.arr.length, 3); a.mixed.arr.push([10], {x: 1}, 'woot'); a.markModified('mixed.arr'); save(a, b, test11); @@ -202,7 +202,7 @@ describe('versioning', function() { function test9(err, a, b) { assert.ifError(err); - assert.equal(6, a.meta.nested.length); + assert.equal(a.meta.nested.length, 6); assert.equal(a._doc.__v, 10); // nested subdoc property changes should not trigger version increments a.meta.nested[2].title = 'two'; @@ -229,8 +229,8 @@ describe('versioning', function() { function test7(err, a, b) { assert.ok(/No matching document/.test(err), 'changes to b should not be applied'); assert.equal(a.arr.length, 2); - assert.equal('updated', a.arr[0][0]); - assert.equal('woot', a.arr[1]); + assert.equal(a.arr[0][0], 'updated'); + assert.equal(a.arr[1], 'woot'); assert.equal(a._doc.__v, 7); a.meta.nested.$pop(); b.meta.nested.$pop(); @@ -240,8 +240,8 @@ describe('versioning', function() { function test6(err, a, b) { assert.ifError(err); assert.equal(a.arr.length, 2); - assert.equal('updated', a.arr[0][0]); - assert.equal('using set', a.arr[1]); + assert.equal(a.arr[0][0], 'updated'); + assert.equal(a.arr[1], 'using set'); assert.equal(a._doc.__v, 6); b.set('arr.0', 'not an array'); // should overwrite b's changes, last write wins @@ -254,7 +254,7 @@ describe('versioning', function() { function test5(err, a, b) { assert.ifError(err); - assert.equal('updated', a.arr[0][0]); + assert.equal(a.arr[0][0], 'updated'); assert.equal(a._doc.__v, 5); a.set('arr.0', 'not an array'); // should overwrite a's changes, last write wins @@ -359,16 +359,16 @@ describe('versioning', function() { assert.ifError(err); M.find(m, function(err, m) { assert.ifError(err); - assert.equal(1, m.length); + assert.equal(m.length, 1); m = m[0]; - assert.equal(0, m._doc.__v); + assert.equal(m._doc.__v, 0); m.str.pull('death'); m.save(function(err) { assert.ifError(err); M.findById(m, function(err, m) { assert.ifError(err); - assert.equal(1, m._doc.__v); - assert.equal(2, m.str.length); + assert.equal(m._doc.__v, 1); + assert.equal(m.str.length, 2); assert.ok(!~m.str.indexOf('death')); done(); }); @@ -387,12 +387,12 @@ describe('versioning', function() { assert.ok(!d._doc.__v); d.numbers.splice(1, 1, 10); var o = d.$__delta(); - assert.equal(undefined, o[0].__v); + assert.equal(o[0].__v, undefined); assert.ok(o[1].$inc); - assert.equal(1, o[1].$inc.__v); + assert.equal(o[1].$inc.__v, 1); d.save(function(err, d) { assert.ifError(err); - assert.equal(1, d._doc.__v); + assert.equal(d._doc.__v, 1); V.findById(d, function(err, d) { assert.ifError(err); assert.ok(d); @@ -413,7 +413,7 @@ describe('versioning', function() { assert.ifError(err); V.findById(v, function(err1, v) { assert.ifError(err1); - assert.equal(0, v._doc.lolwat); + assert.equal(v._doc.lolwat, 0); done(); }); }); @@ -424,18 +424,18 @@ describe('versioning', function() { var M = db.model('disabledVersioning', schema, 's' + random()); M.create({x: ['hi']}, function(err, doc) { assert.ifError(err); - assert.equal(false, '__v' in doc._doc); + assert.equal('__v' in doc._doc, false); doc.x.pull('hi'); doc.save(function(err) { assert.ifError(err); - assert.equal(false, '__v' in doc._doc); + assert.equal('__v' in doc._doc, false); doc.set('x.0', 'updated'); var d = doc.$__delta()[0]; - assert.equal(undefined, d.__v, 'version should not be added to where clause'); + assert.equal(d.__v, undefined, 'version should not be added to where clause'); M.collection.findOne({_id: doc._id}, function(err, doc) { - assert.equal(false, '__v' in doc); + assert.equal('__v' in doc, false); done(); }); }); @@ -460,18 +460,18 @@ describe('versioning', function() { var doc = new V; doc.save(function(err) { assert.ifError(err); - assert.equal(0, doc.__v); + assert.equal(doc.__v, 0); doc.increment(); doc.save(function(err) { assert.ifError(err); - assert.equal(1, doc.__v); + assert.equal(doc.__v, 1); V.findById(doc, function(err, doc) { assert.ifError(err); - assert.equal(1, doc.__v); + assert.equal(doc.__v, 1); done(); }); }); @@ -521,9 +521,9 @@ describe('versioning', function() { m.save(function(err, m) { assert.ifError(err); var obj = m.toObject(); - assert.equal(0, obj.__v); + assert.equal(obj.__v, 0); obj = m.toObject({versionKey: false}); - assert.equal(undefined, obj.__v); + assert.equal(obj.__v, undefined); done(); }); }); From d2585afeaa4f9906b06bbe450ac55883b1dfb090 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 May 2016 08:36:17 -0700 Subject: [PATCH 0583/2240] fix(schema): cast all valid ObjectId strings to object ids Fix #3365 --- lib/schema/objectid.js | 4 ++-- test/document.test.js | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index d1b1e1f0e6d..28858236893 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -134,7 +134,7 @@ ObjectId.prototype.cast = function(value, doc, init) { } if (value._id.toString instanceof Function) { try { - return oid.createFromHexString(value._id.toString()); + return new oid(value._id.toString()); } catch (e) { } } @@ -142,7 +142,7 @@ ObjectId.prototype.cast = function(value, doc, init) { if (value.toString instanceof Function) { try { - return oid.createFromHexString(value.toString()); + return new oid(value.toString()); } catch (err) { throw new CastError('ObjectId', value, this.path); } diff --git a/test/document.test.js b/test/document.test.js index 03e4d141157..a85acd39f20 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2712,6 +2712,15 @@ describe('document', function() { assert.equal(p.child.$parent, p); done(); }); + + it('strings of length 12 are valid oids (gh-3365)', function(done) { + var schema = new Schema({ myId: mongoose.Schema.Types.ObjectId }); + var M = db.model('gh3365', schema); + var doc = new M({ myId: 'blablablabla' }); + doc.validate(function(error) { + assert.ifError(error); + done(); + }); + }); }); }); - From ed4606e11db8bc8f52bb63355eed02413717cbea Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 May 2016 13:23:38 -0400 Subject: [PATCH 0584/2240] Docs: change commit msg guideline for docs --- release-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-items.md b/release-items.md index 1ad190c9a24..c7b3d148070 100644 --- a/release-items.md +++ b/release-items.md @@ -17,7 +17,7 @@ For 4.x 0. Change to the master branch 1. execute `make docs` (when this process completes you'll be on the gh-pages branch) -2. `git commit -a -m 'website; regen <4.x.x>'` +2. `git commit -a -m 'docs: release 4.x.x'` 3. `git push origin gh-pages` For 3.8.x: From 96300cd52f505c4cfdc70650ffcfaf30038c2a9f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 May 2016 17:06:24 -0400 Subject: [PATCH 0585/2240] docs: clarify how to run tests Plus handy tips re #4153 --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c0f1cbc5f46..6575aae6c3e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,9 +37,11 @@ If you have a question about Mongoose (not a bug report) please post it to eithe ### Running the tests - Open a terminal and navigate to the root of the project - execute `npm install` to install the necessary dependencies +- start a mongodb instance on port 27017 if one isn't running already. `mongod --dbpath --port 27017` - execute `npm test` to run the tests (we're using [mocha](http://mochajs.org/)) - or to execute a single test `npm test -- -g 'some regexp that matches the test description'` - any mocha flags can be specified with `-- ` + - For example, you can use `npm test -- -R spec` to use the spec reporter, rather than the dot reporter (by default, the test output looks like a bunch of dots) ### Documentation From ace522148c23ae6d096535c7e88704143d2a4cc5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 May 2016 09:13:34 -0700 Subject: [PATCH 0586/2240] refactor(test): remove stale code --- test/triage/.gitignore | 0 test/triage/_goosetest.js | 42 --------------------------------------- test/triage/createtest | 17 ---------------- 3 files changed, 59 deletions(-) delete mode 100644 test/triage/.gitignore delete mode 100644 test/triage/_goosetest.js delete mode 100644 test/triage/createtest diff --git a/test/triage/.gitignore b/test/triage/.gitignore deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test/triage/_goosetest.js b/test/triage/_goosetest.js deleted file mode 100644 index 9ee39ce66c0..00000000000 --- a/test/triage/_goosetest.js +++ /dev/null @@ -1,42 +0,0 @@ - -var mongoose = require('../../'); -var Schema = mongoose.Schema; -var assert = require('power-assert') - -console.log('\n==========='); -console.log(' mongoose version: %s', mongoose.version); -console.log('========\n\n'); - -var dbname = 'goosetest-{NAME}'; -mongoose.connect('localhost', dbname); -mongoose.connection.on('error', function () { - console.error('connection error', arguments); -}); - - -var schema = new Schema({ - name: String -}); - -var A = mongoose.model('A', schema); - - -mongoose.connection.on('open', function () { - var a = new A({ name: '{NAME}' }); - - a.save(function (err) { - if (err) return done(err); - - A.findById(a, function (err, doc) { - console.log(arguments); - done(err); - }) - }) -}); - -function done (err) { - if (err) console.error(err.stack); - mongoose.connection.db.dropDatabase(function () { - mongoose.connection.close(); - }); -} diff --git a/test/triage/createtest b/test/triage/createtest deleted file mode 100644 index 58cfef17770..00000000000 --- a/test/triage/createtest +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# copy our _goosetest.js to another filename passed on the cmd line -# and replace all occurances of {NAME} with the filename too. -test $# -ne 1 && echo "usage: createtest scriptname" && exit 0; - -# EDITOR must be set -test -e $EDITOR && echo "Please set your EDITOR environment variable" && exit 0; - -# does the file they are about to create exist? -if test -e triage/$1.js; then - # do not overwrite. open for editing. - $EDITOR triage/$1.js -else - # create - cat _goosetest.js | sed "s/{NAME}/$1/g" >> triage/$1.js - $EDITOR triage/$1.js -fi From e7c6d0852e08247711033ab2c932531b1f1e3e07 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 1 Jun 2016 18:55:57 -0400 Subject: [PATCH 0587/2240] docs: remove unclear "unsafe" term in query docs Fix #3282 --- lib/query.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/query.js b/lib/query.js index d1f1278f838..5f17dac6cad 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1440,7 +1440,7 @@ Query.prototype.sort = function(arg) { * query.remove({ name: 'Anne Murray' }, callback) * query.remove({ name: 'Anne Murray' }).remove(callback) * - * // executed without a callback (unsafe write) + * // executed without a callback * query.exec() * * // summary @@ -1968,12 +1968,12 @@ Query.prototype._execUpdate = function(callback) { * * ####Note * - * The operation is only executed when a callback is passed. To force execution without a callback (which would be an unsafe write), we must first call update() and then execute it by using the `exec()` method. + * The operation is only executed when a callback is passed. To force execution without a callback, we must first call update() and then execute it by using the `exec()` method. * * var q = Model.where({ _id: id }); * q.update({ $set: { name: 'bob' }}).update(); // not executed * - * q.update({ $set: { name: 'bob' }}).exec(); // executed as unsafe + * q.update({ $set: { name: 'bob' }}).exec(); // executed * * // keys that are not $atomic ops become $set. * // this executes the same command as the previous example. @@ -2011,7 +2011,7 @@ Query.prototype._execUpdate = function(callback) { * update(doc, cb) // executes * update(doc) * update(cb) // executes - * update(true) // executes (unsafe write) + * update(true) // executes * update() * * @param {Object} [criteria] From 0e9cbd4cec9a5e558f0c113c87c085bf65a11812 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 3 Jun 2016 08:35:22 -0700 Subject: [PATCH 0588/2240] test(model): repro #4177 --- test/promise_provider.test.js | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js index 939c6e67c7b..c5dcf1204ca 100644 --- a/test/promise_provider.test.js +++ b/test/promise_provider.test.js @@ -327,6 +327,45 @@ describe('ES6 promises: ', function() { done(); }); + it('gh-4177', function(done) { + var subSchema = new Schema({ + name: { type: String, required: true } + }); + + var mainSchema = new Schema({ + name: String, + type: String, + children: [subSchema] + }); + + mainSchema.index({ name: 1, account: 1 }, { unique: true }); + + var Main = db.model('gh4177', mainSchema); + + Main.on('index', function(error) { + assert.ifError(error); + + var data = { + name: 'foo', + type: 'bar', + children: [{ name: 'child' }] + }; + + var firstSucceeded = false; + new Main(data). + save(). + then(function() { + firstSucceeded = true; + return new Main(data).save(); + }). + catch(function(error) { + assert.ok(firstSucceeded); + assert.ok(error.toString().indexOf('E11000') !== -1); + done(); + }); + }); + }); + it('subdoc pre doesnt cause unhandled rejection (gh-3669)', function(done) { var nestedSchema = new Schema({ name: {type: String, required: true} From 048b776cc3137ef476a4c495a6d02c7aedb78d7a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 3 Jun 2016 08:35:35 -0700 Subject: [PATCH 0589/2240] fix(model): remove unnecessary .save() promise This is possible because $__registerHooksFromSchema wraps it in a promise anyway. Fix #4177 --- lib/model.js | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/lib/model.js b/lib/model.js index 8fb8ad3c440..9f7fb781509 100644 --- a/lib/model.js +++ b/lib/model.js @@ -274,24 +274,7 @@ Model.prototype.save = function(options, fn) { options = {}; } - if (options.__noPromise) { - return this.$__save(options, fn); - } - - var _this = this; - var Promise = PromiseProvider.get(); - return new Promise.ES6(function(resolve, reject) { - _this.$__save(options, function(error, doc, numAffected) { - if (error) { - fn && fn(error); - reject(error); - return; - } - - fn && fn(null, doc, numAffected); - resolve(doc, numAffected); - }); - }); + return this.$__save(options, fn); }; /** From 90b14404a0e8c02a7c1c4e3a9d4ca4856ad53a38 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 3 Jun 2016 15:55:59 -0700 Subject: [PATCH 0590/2240] test(document): repro #4182 --- test/document.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index a85acd39f20..484c4c91338 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2722,5 +2722,30 @@ describe('document', function() { done(); }); }); + + it('set() empty obj unmodifies subpaths (gh-4182)', function(done) { + var omeletteSchema = new Schema({ + topping: { + meat: { + type: String, + enum: ['bacon', 'sausage'] + }, + cheese: Boolean + } + }); + var Omelette = db.model('gh4182', omeletteSchema); + var doc = new Omelette({ + topping: { + meat: 'bacon', + cheese: true + } + }); + doc.topping = {}; + doc.save(function(error) { + assert.ifError(error); + assert.strictEqual(doc.topping.meat, void 0); + done(); + }); + }); }); }); From 61cdf9d419345c178f4ee0faf37ebdbbad8d6762 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 3 Jun 2016 15:56:58 -0700 Subject: [PATCH 0591/2240] fix(document): clean modified subpaths when set path to empty obj Fix #4182 --- lib/document.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index de833120f73..fa9f30a5371 100644 --- a/lib/document.js +++ b/lib/document.js @@ -566,6 +566,7 @@ Document.prototype.set = function(path, val, type, options) { (!val.constructor || utils.getFunctionName(val.constructor) === 'Object')) { if (!merge) { this.setValue(path, null); + cleanModifiedSubpaths(this, path); } this.set(val, path, constructing); return this; @@ -696,6 +697,20 @@ Document.prototype.set = function(path, val, type, options) { return this; }; +/*! + * ignore + */ + +function cleanModifiedSubpaths(doc, path) { + var _modifiedPaths = Object.keys(doc.$__.activePaths.states.modify); + var _numModifiedPaths = _modifiedPaths.length; + for (var j = 0; j < _numModifiedPaths; ++j) { + if (_modifiedPaths[j].indexOf(path + '.') === 0) { + delete doc.$__.activePaths.states.modify[_modifiedPaths[j]]; + } + } +} + /** * Determine if we should mark this change as modified. * @@ -920,7 +935,6 @@ Document.prototype.markModified = function(path) { Document.prototype.modifiedPaths = function() { var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify); - return directModifiedPaths.reduce(function(list, path) { var parts = path.split('.'); return list.concat(parts.reduce(function(chains, part, i) { From 0f2f8a1964899d7814d1367b5392add0b89d4480 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Jun 2016 13:33:48 -0700 Subject: [PATCH 0592/2240] docs: clarify command buffering when using driver directly Fix #4195 --- README.md | 5 ++++- docs/2.7.x/index.html | 19 ++++++++++++++----- docs/2.8.x/index.html | 17 ++++++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c38e90d9cbe..3f5326cab0f 100644 --- a/README.md +++ b/README.md @@ -287,7 +287,10 @@ new Schema({ ### Driver Access -Mongoose is built on top of the [official MongoDB Node.js driver](https://github.com/mongodb/node-mongodb-native). Each mongoose model keeps a reference to a [native MongoDB driver collection](http://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html). The collection object can be accessed using `YourModel.collection`. However, using the collection object directly bypasses all mongoose features, including hooks, validation, etc. +Mongoose is built on top of the [official MongoDB Node.js driver](https://github.com/mongodb/node-mongodb-native). Each mongoose model keeps a reference to a [native MongoDB driver collection](http://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html). The collection object can be accessed using `YourModel.collection`. However, using the collection object directly bypasses all mongoose features, including hooks, validation, etc. The one +notable exception that `YourModel.collection` still buffers +commands. As such, `YourModel.collection.find()` will **not** +return a cursor. ## API Docs diff --git a/docs/2.7.x/index.html b/docs/2.7.x/index.html index 6847f656dff..302f43aef80 100644 --- a/docs/2.7.x/index.html +++ b/docs/2.7.x/index.html @@ -156,7 +156,7 @@ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); - + function getMembers(data){ if (!(data && data.query && data.query.results && data.query.results.p)) return; var members = document.createElement('span'); @@ -485,14 +485,14 @@

Intercepting and mutating method arguments

// pre declaration is chainable .pre(method, function secondPre (next, methodArg1, methodArg2) { console.log(methodArg1); - // => 'altered-originalValOfMethodArg1' + // => 'altered-originalValOfMethodArg1' console.log(methodArg2); - // => 'originalValOfMethodArg2' + // => 'originalValOfMethodArg2' // Passing no arguments to `next` automatically passes along the current argument values // i.e., the following `next()` is equivalent to `next(methodArg1, methodArg2)` - // and also equivalent to, with the example method arg + // and also equivalent to, with the example method arg // values, `next('altered-originalValOfMethodArg1', 'originalValOfMethodArg2')` next(); }) @@ -531,7 +531,16 @@

Getting support

Driver access

-

The driver being used defaults to node-mongodb-native and is directly accessible through YourModel.collection. Note: using the driver directly bypasses all Mongoose power-tools like validation, getters, setters, hooks, etc.

+

+ The driver being used defaults to + node-mongodb-native + and is directly accessible through YourModel.collection. + Note: using the driver directly bypasses all Mongoose + power-tools like validation, getters, setters, hooks, etc., with the + notable exception that YourModel.collection still buffers + commands. As such, YourModel.collection.find() will not + return a cursor. +

Mongoose Plugins

diff --git a/docs/2.8.x/index.html b/docs/2.8.x/index.html index 068de1d09c3..a4193150b0b 100644 --- a/docs/2.8.x/index.html +++ b/docs/2.8.x/index.html @@ -156,7 +156,7 @@ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); - + function getMembers(data){ if (!(data && data.query && data.query.results && data.query.results.p)) return; var members = document.createElement('span'); @@ -483,14 +483,14 @@

Intercepting and mutating method arguments

// pre declaration is chainable .pre(method, function secondPre (next, methodArg1, methodArg2) { console.log(methodArg1); - // => 'altered-originalValOfMethodArg1' + // => 'altered-originalValOfMethodArg1' console.log(methodArg2); - // => 'originalValOfMethodArg2' + // => 'originalValOfMethodArg2' // Passing no arguments to `next` automatically passes along the current argument values // i.e., the following `next()` is equivalent to `next(methodArg1, methodArg2)` - // and also equivalent to, with the example method arg + // and also equivalent to, with the example method arg // values, `next('altered-originalValOfMethodArg1', 'originalValOfMethodArg2')` next(); }) @@ -529,7 +529,14 @@

Getting support

Driver access

-

The driver being used defaults to node-mongodb-native and is directly accessible through YourModel.collection. Note: using the driver directly bypasses all Mongoose power-tools like validation, getters, setters, hooks, etc.

+The driver being used defaults to +node-mongodb-native +and is directly accessible through YourModel.collection. +Note: using the driver directly bypasses all Mongoose +power-tools like validation, getters, setters, hooks, etc., with the +notable exception that YourModel.collection still buffers +commands. As such, YourModel.collection.find() will not +return a cursor.

Mongoose Plugins

From 1a541b1367e3863e04d5d8ad55b8be99f290829d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Jun 2016 13:51:37 -0700 Subject: [PATCH 0593/2240] test(promise): repro #4189 --- test/promise.test.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/test/promise.test.js b/test/promise.test.js index baacf81de5e..4efc55d15ed 100644 --- a/test/promise.test.js +++ b/test/promise.test.js @@ -218,5 +218,21 @@ describe('Promise', function() { }); done(); }); -}); + it('.catch() works correctly (gh-4189)', function(done) { + var promise = new Promise.ES6(function(resolve, reject) { + reject(new Error('error1')); + }); + promise. + catch(function(error) { + assert.ok(error); + return new Promise.ES6(function(resolve, reject) { + reject(new Error('error2')); + }); + }). + catch(function(error) { + assert.equal(error.message, 'error2'); + done(); + }); + }); +}); From d42daa7b123579ff0f5185c5425d82d0e335b02d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Jun 2016 13:51:57 -0700 Subject: [PATCH 0594/2240] fix(promise): correct broken mpromise .catch() Fix #4189 --- lib/promise.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/promise.js b/lib/promise.js index 403eaa37b3d..72eb7e557e6 100644 --- a/lib/promise.js +++ b/lib/promise.js @@ -66,6 +66,20 @@ Promise.prototype = Object.create(MPromise.prototype, { } }); +/** + * ES6-style `.catch()` shorthand + * + * @method catch + * @memberOf Promise + * @param {Function} onReject + * @return {Promise} + * @api public + */ + +Promise.prototype.catch = function(onReject) { + return this.then(null, onReject); +}; + /*! * Override event names for backward compatibility. */ From 7839aea3ec1ab0c0be207728118af71d9c989e32 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Jun 2016 17:18:00 -0700 Subject: [PATCH 0595/2240] test(query): repro #4179 --- test/model.query.casting.test.js | 66 +++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index c648ccf4797..dc7f076f6f0 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -4,15 +4,16 @@ * Test dependencies. */ -var start = require('./common'), - assert = require('power-assert'), - mongoose = start.mongoose, - random = require('../lib/utils').random, - Schema = mongoose.Schema, - SchemaType = mongoose.SchemaType, - CastError = SchemaType.CastError, - ObjectId = Schema.Types.ObjectId, - DocumentObjectId = mongoose.Types.ObjectId; +var assert = require('power-assert'); +var random = require('../lib/utils').random; +var start = require('./common'); + +var mongoose = start.mongoose; + +var CastError = mongoose.SchemaType.CastError; +var DocumentObjectId = mongoose.Types.ObjectId; +var ObjectId = mongoose.Schema.Types.ObjectId; +var Schema = mongoose.Schema; /** * Setup. @@ -903,4 +904,51 @@ describe('model query casting', function() { }); }); }); + + it('minDistance (gh-4197)', function(done) { + var db = start(); + + var schema = new Schema({ + name: String, + loc: { + type: { type: String }, + coordinates: [Number] + } + }); + + schema.index({ loc: '2dsphere' }); + + var MyModel = db.model('gh4197', schema); + + MyModel.on('index', function(error) { + assert.ifError(error); + var docs = [ + { name: 'San Mateo Caltrain', loc: _geojsonPoint([-122.33, 37.57]) }, + { name: 'Squaw Valley', loc: _geojsonPoint([-120.24, 39.21]) }, + { name: 'Mammoth Lakes', loc: _geojsonPoint([-118.9, 37.61]) } + ]; + var RADIUS_OF_EARTH_IN_METERS = 6378100; + MyModel.create(docs, function(error) { + assert.ifError(error); + MyModel. + find(). + near('loc', { + center: [-122.33, 37.57], + minDistance: (1000 / RADIUS_OF_EARTH_IN_METERS).toString(), + maxDistance: (280000 / RADIUS_OF_EARTH_IN_METERS).toString(), + spherical: true + }). + exec(function(error, results) { + assert.ifError(error); + assert.equal(results.length, 1); + assert.equal(results[0].name, 'Squaw Valley'); + done(); + }); + }); + }); + }); }); + +function _geojsonPoint(coordinates) { + return { type: 'Point', coordinates: coordinates }; +} From b97896f9a9781d81705472763741472e7c57a640 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Jun 2016 17:18:49 -0700 Subject: [PATCH 0596/2240] fix(query): support minDistance with query casting and `.near()` Fix #4179 Pull in aheckmann/mquery#7be555c5fce96e30d159e96d7202756af4126f8a --- lib/cast.js | 12 ++++++++++-- lib/schema/array.js | 1 + lib/schema/embedded.js | 1 + lib/schema/operators/geospatial.js | 21 +++++++++++++-------- package.json | 2 +- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index 9c63ee32a46..ddecddf11f3 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -101,9 +101,12 @@ module.exports = function cast(schema, obj) { var numbertype = new Types.Number('__QueryCasting__'); var value = val[geo]; - if (val.$maxDistance) { + if (val.$maxDistance != null) { val.$maxDistance = numbertype.castForQuery(val.$maxDistance); } + if (val.$minDistance != null) { + val.$minDistance = numbertype.castForQuery(val.$minDistance); + } if (geo === '$within') { var withinType = value.$center @@ -123,7 +126,12 @@ module.exports = function cast(schema, obj) { } else if ((geo === '$near' || geo === '$nearSphere' || geo === '$geoIntersects') && value.$geometry && typeof value.$geometry.type === 'string' && Array.isArray(value.$geometry.coordinates)) { - // geojson; cast the coordinates + if (value.$maxDistance != null) { + value.$maxDistance = numbertype.castForQuery(value.$maxDistance); + } + if (value.$minDistance != null) { + value.$minDistance = numbertype.castForQuery(value.$minDistance); + } value = value.$geometry.coordinates; } diff --git a/lib/schema/array.js b/lib/schema/array.js index 68219d0d180..52ced79fa67 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -279,6 +279,7 @@ handle.$within = handle.$geoWithin = geospatial.cast$within; handle.$size = +handle.$minDistance = handle.$maxDistance = castToNumber; handle.$eq = diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index edfe3aef2c9..b817d2b1aa3 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -82,6 +82,7 @@ Embedded.prototype.$conditionalHandlers.$geoWithin = geospatial.cast$within; Embedded.prototype.$conditionalHandlers.$geoIntersects = geospatial.cast$geoIntersects; +Embedded.prototype.$conditionalHandlers.$minDistance = castToNumber; Embedded.prototype.$conditionalHandlers.$maxDistance = castToNumber; /** diff --git a/lib/schema/operators/geospatial.js b/lib/schema/operators/geospatial.js index fc2433961a4..b490d2db2ec 100644 --- a/lib/schema/operators/geospatial.js +++ b/lib/schema/operators/geospatial.js @@ -21,6 +21,8 @@ function cast$near(val) { return val; } + _castMinMaxDistance(this, val); + if (val && val.$geometry) { return cast$geometry(val, this); } @@ -40,19 +42,13 @@ function cast$geometry(val, self) { break; } - if (val.$maxDistance) { - val.$maxDistance = castToNumber.call(self, val.$maxDistance); - } + _castMinMaxDistance(this, val); return val; } function cast$within(val) { - var _this = this; - - if (val.$maxDistance) { - val.$maxDistance = castToNumber.call(_this, val.$maxDistance); - } + _castMinMaxDistance(this, val); if (val.$box || val.$polygon) { var type = val.$box ? '$box' : '$polygon'; @@ -93,3 +89,12 @@ function cast$geoIntersects(val) { cast$geometry(val, this); return val; } + +function _castMinMaxDistance(self, val) { + if (val.$maxDistance) { + val.$maxDistance = castToNumber.call(self, val.$maxDistance); + } + if (val.$minDistance) { + val.$minDistance = castToNumber.call(self, val.$minDistance); + } +} diff --git a/package.json b/package.json index b2d04ba04bc..a151a813f03 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.1.18", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "1.10.0", + "mquery": "1.11.0", "ms": "0.7.1", "muri": "1.1.0", "regexp-clone": "0.0.1", From b2af130f0e7bce9735045760e79e0ff03c75b1c3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 5 Jun 2016 14:11:03 -0700 Subject: [PATCH 0597/2240] chore: release 4.4.20 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 31ff49d6527..bb24a5117ca 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.4.20 / 2016-06-05 +=================== + * docs: clarify command buffering when using driver directly #4195 + * fix(promise): correct broken mpromise .catch() #4189 + * fix(document): clean modified subpaths when set path to empty obj #4182 + * fix(query): support minDistance with query casting and `.near()` #4179 + * fix(model): remove unnecessary .save() promise #4177 + * fix(schema): cast all valid ObjectId strings to object ids #3365 + * docs: remove unclear "unsafe" term in query docs #3282 + 4.4.19 / 2016-05-21 =================== * fix(model): handle insertMany if timestamps not set #4171 diff --git a/package.json b/package.json index a151a813f03..26e5288da8a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.20-pre", + "version": "4.4.20", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From d5597f1d522689b99cc662670561a5f026aec415 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Jun 2016 06:38:48 -0700 Subject: [PATCH 0598/2240] chore: now working on 4.4.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 26e5288da8a..0de4130abb9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.4.20", + "version": "4.4.21-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 33461ba19c7c21170d11281899acc4197b62be39 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Jun 2016 06:46:29 -0700 Subject: [PATCH 0599/2240] fix: resolve merge issues --- lib/model.js | 2 -- test/query.middleware.test.js | 3 --- 2 files changed, 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index b3b87431cfa..df46205e48a 100644 --- a/lib/model.js +++ b/lib/model.js @@ -267,8 +267,6 @@ Model.prototype.$__save = function(options, callback) { */ Model.prototype.save = function(options, fn) { - var _this = this; - if (typeof options === 'function') { fn = options; options = undefined; diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 9484ce9ce71..88536fcee55 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -231,9 +231,6 @@ describe('query middleware', function() { ]; Book.create(books, function(error, books) { assert.ifError(error); - assert.equal(count, 1); - assert.equal(preCount, 1); - assert.equal(postCount, 1); var query = { _id: books[1]._id }; var update = { title: 'Professional AngularJS' }; Book.update(query, update, function(error) { From 8fc2c7f14feafbf20649b0d73fe01aba2f49c84b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Jun 2016 07:45:40 -0700 Subject: [PATCH 0600/2240] feat(model): add custom query helpers Fix #3470 Fix #2372 Re: #3714 --- lib/model.js | 44 +++++--- lib/schema.js | 1 + test/model.populate.setting.test.js | 154 ++++++++++++++-------------- test/query.test.js | 22 ++++ 4 files changed, 132 insertions(+), 89 deletions(-) diff --git a/lib/model.js b/lib/model.js index df46205e48a..12481f24d4b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1078,7 +1078,7 @@ Model.remove = function remove(conditions, callback) { } // get the mongodb collection object - var mq = new Query(conditions, {}, this, this.collection); + var mq = new this.Query(conditions, {}, this, this.collection); return mq.remove(callback); }; @@ -1139,8 +1139,7 @@ Model.find = function find(conditions, projection, options, callback) { options = null; } - // get the raw mongodb collection object - var mq = new Query({}, {}, this, this.collection); + var mq = new this.Query({}, {}, this, this.collection); mq.select(projection); mq.setOptions(options); if (this.schema.discriminatorMapping && mq.selectedInclusively()) { @@ -1256,7 +1255,7 @@ Model.findOne = function findOne(conditions, projection, options, callback) { } // get the mongodb collection object - var mq = new Query({}, {}, this, this.collection); + var mq = new this.Query({}, {}, this, this.collection); mq.select(projection); mq.setOptions(options); if (this.schema.discriminatorMapping && mq.selectedInclusively()) { @@ -1289,7 +1288,7 @@ Model.count = function count(conditions, callback) { } // get the mongodb collection object - var mq = new Query({}, {}, this, this.collection); + var mq = new this.Query({}, {}, this, this.collection); return mq.count(conditions, callback); }; @@ -1320,7 +1319,7 @@ Model.count = function count(conditions, callback) { Model.distinct = function distinct(field, conditions, callback) { // get the mongodb collection object - var mq = new Query({}, {}, this, this.collection); + var mq = new this.Query({}, {}, this, this.collection); if (typeof conditions === 'function') { callback = conditions; @@ -1357,7 +1356,7 @@ Model.distinct = function distinct(field, conditions, callback) { Model.where = function where(path, val) { void val; // eslint // get the mongodb collection object - var mq = new Query({}, {}, this, this.collection).find({}); + var mq = new this.Query({}, {}, this, this.collection).find({}); return mq.where.apply(mq, arguments); }; @@ -1377,7 +1376,7 @@ Model.where = function where(path, val) { */ Model.$where = function $where() { - var mq = new Query({}, {}, this, this.collection).find({}); + var mq = new this.Query({}, {}, this, this.collection).find({}); return mq.$where.apply(mq, arguments); }; @@ -1482,7 +1481,7 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { update.$setOnInsert[this.schema.options.versionKey] = 0; } - var mq = new Query({}, {}, this, this.collection); + var mq = new this.Query({}, {}, this, this.collection); mq.select(fields); return mq.findOneAndUpdate(conditions, update, options, callback); @@ -1648,7 +1647,7 @@ Model.findOneAndRemove = function(conditions, options, callback) { options.select = undefined; } - var mq = new Query({}, {}, this, this.collection); + var mq = new this.Query({}, {}, this, this.collection); mq.select(fields); return mq.findOneAndRemove(conditions, options, callback); @@ -1967,7 +1966,7 @@ Model.hydrate = function(obj) { */ Model.update = function update(conditions, doc, options, callback) { - var mq = new Query({}, {}, this, this.collection); + var mq = new this.Query({}, {}, this, this.collection); // gh-2406 // make local deep copy of conditions if (conditions instanceof Document) { @@ -2063,7 +2062,7 @@ Model.mapReduce = function mapReduce(o, callback) { o.reduce = String(o.reduce); if (o.query) { - var q = new Query(o.query); + var q = new _this.Query(o.query); q.cast(_this); o.query = q._conditions; q = undefined; @@ -3096,6 +3095,14 @@ Model.compile = function compile(name, schema, collectionName, connection, base) model.schema = model.prototype.schema; model.collection = model.prototype.collection; + // Create custom query constructor + model.Query = function() { + Query.apply(this, arguments); + }; + model.Query.prototype = Object.create(Query.prototype); + model.Query.base = Query.base; + applyQueryMethods(model, schema.query); + var kareemOptions = { useErrorHandlers: true }; model.insertMany = model.hooks.createWrapper('insertMany', model.insertMany, model, kareemOptions); @@ -3142,6 +3149,19 @@ var applyStatics = function(model, schema) { } }; +/*! + * Register custom query methods for this model + * + * @param {Model} model + * @param {Schema} schema + */ + +function applyQueryMethods(model, methods) { + for (var i in methods) { + model.Query.prototype[i] = methods[i]; + } +} + /*! * Subclass this model with `conn`, `schema`, and `collection` settings. * diff --git a/lib/schema.js b/lib/schema.js index bb5265f03cc..5924614b155 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -82,6 +82,7 @@ function Schema(obj, options) { this._requiredpaths = undefined; this.discriminatorMapping = undefined; this._indexedpaths = undefined; + this.query = {}; this.s = { hooks: new Kareem(), diff --git a/test/model.populate.setting.test.js b/test/model.populate.setting.test.js index d1dcffae3da..ac279c898e3 100644 --- a/test/model.populate.setting.test.js +++ b/test/model.populate.setting.test.js @@ -120,104 +120,104 @@ describe('model: populate:', function() { } it('if a document', function(done) { - B.findById(b1) - .populate('fans _creator embed.other embed.array embed.nested.subdoc') - .populate({path: 'adhoc.subdoc', model: refuser}) - .populate({path: 'adhoc.subarray.things', model: refuser}) - .exec(function(err, doc) { - assert.ifError(err); + var query = B.findById(b1). + populate('fans _creator embed.other embed.array embed.nested.subdoc'). + populate({path: 'adhoc.subdoc', model: refuser}). + populate({path: 'adhoc.subarray.things', model: refuser}); + query.exec(function(err, doc) { + assert.ifError(err); - var user3 = user('user3'); - doc.fans.push(user3); - assert.deepEqual(doc.fans[2].toObject(), user3.toObject()); + var user3 = user('user3'); + doc.fans.push(user3); + assert.deepEqual(doc.fans[2].toObject(), user3.toObject()); - var user4 = user('user4'); - doc.fans.nonAtomicPush(user4); - assert.deepEqual(doc.fans[3].toObject(), user4.toObject()); + var user4 = user('user4'); + doc.fans.nonAtomicPush(user4); + assert.deepEqual(doc.fans[3].toObject(), user4.toObject()); - var user5 = user('user5'); - doc.fans.splice(2, 1, user5); - assert.deepEqual(doc.fans[2].toObject(), user5.toObject()); + var user5 = user('user5'); + doc.fans.splice(2, 1, user5); + assert.deepEqual(doc.fans[2].toObject(), user5.toObject()); - var user6 = user('user6'); - doc.fans.unshift(user6); - assert.deepEqual(doc.fans[0].toObject(), user6.toObject()); + var user6 = user('user6'); + doc.fans.unshift(user6); + assert.deepEqual(doc.fans[0].toObject(), user6.toObject()); - var user7 = user('user7'); - doc.fans.addToSet(user7); - assert.deepEqual(doc.fans[5].toObject(), user7.toObject()); + var user7 = user('user7'); + doc.fans.addToSet(user7); + assert.deepEqual(doc.fans[5].toObject(), user7.toObject()); - doc.fans.forEach(function(doc) { - assert.ok(doc instanceof U); - }); + doc.fans.forEach(function(doc) { + assert.ok(doc instanceof U); + }); - var user8 = user('user8'); - doc.fans.set(0, user8); - assert.deepEqual(doc.fans[0].toObject(), user8.toObject()); + var user8 = user('user8'); + doc.fans.set(0, user8); + assert.deepEqual(doc.fans[0].toObject(), user8.toObject()); - doc.fans.push(null); - assert.equal(doc.fans[6], null); + doc.fans.push(null); + assert.equal(doc.fans[6], null); - var _id = construct[id](); - doc.fans.addToSet(_id); - if (Buffer.isBuffer(_id)) { - assert.equal(doc.fans[7]._id.toString('utf8'), _id.toString('utf8')); - } else { - assert.equal(doc.fans[7]._id, String(_id)); - } + var _id = construct[id](); + doc.fans.addToSet(_id); + if (Buffer.isBuffer(_id)) { + assert.equal(doc.fans[7]._id.toString('utf8'), _id.toString('utf8')); + } else { + assert.equal(doc.fans[7]._id, String(_id)); + } - assert.equal(doc._creator.email, u1.email); + assert.equal(doc._creator.email, u1.email); - doc._creator = null; - assert.equal(doc._creator, null); + doc._creator = null; + assert.equal(doc._creator, null); - var creator = user('creator'); - doc._creator = creator; - assert.ok(doc._creator instanceof mongoose.Document); - assert.deepEqual(doc._creator.toObject(), creator.toObject()); + var creator = user('creator'); + doc._creator = creator; + assert.ok(doc._creator instanceof mongoose.Document); + assert.deepEqual(doc._creator.toObject(), creator.toObject()); // embedded with declared ref in schema - var user1a = user('user1a'); - doc.embed[0].array.set(0, user1a); - assert.deepEqual(doc.embed[0].array[0].toObject(), user1a.toObject()); + var user1a = user('user1a'); + doc.embed[0].array.set(0, user1a); + assert.deepEqual(doc.embed[0].array[0].toObject(), user1a.toObject()); - var user1b = user('user1b'); - doc.embed[0].other = user1b; - assert.deepEqual(doc.embed[0].other.toObject(), user1b.toObject()); + var user1b = user('user1b'); + doc.embed[0].other = user1b; + assert.deepEqual(doc.embed[0].other.toObject(), user1b.toObject()); - var user1c = user('user2c'); - doc.embed[0].nested = [{subdoc: user1c}]; - assert.deepEqual(doc.embed[0].nested[0].subdoc.toObject(), user1c.toObject()); + var user1c = user('user2c'); + doc.embed[0].nested = [{subdoc: user1c}]; + assert.deepEqual(doc.embed[0].nested[0].subdoc.toObject(), user1c.toObject()); // embedded without declared ref in schema - var user2a = user('user2a'); - doc.adhoc[0].subdoc = user2a; - assert.deepEqual(doc.adhoc[0].subdoc.toObject(), user2a.toObject()); + var user2a = user('user2a'); + doc.adhoc[0].subdoc = user2a; + assert.deepEqual(doc.adhoc[0].subdoc.toObject(), user2a.toObject()); - var user2b = user('user2b'); - doc.adhoc[0].subarray[0].things.push(user2b); - assert.deepEqual(doc.adhoc[0].subarray[0].things[1].toObject(), user2b.toObject()); + var user2b = user('user2b'); + doc.adhoc[0].subarray[0].things.push(user2b); + assert.deepEqual(doc.adhoc[0].subarray[0].things[1].toObject(), user2b.toObject()); - doc.save(function(err) { - assert.ifError(err); - B.findById(b1).exec(function(err, doc) { + doc.save(function(err) { + assert.ifError(err); + B.findById(b1).exec(function(err, doc) { // db is closed in after() - assert.ifError(err); - assert.equal(doc.fans.length, 8); - assert.equal(doc.fans[0], user8.id); - assert.equal(doc.fans[5], user7.id); - assert.equal(doc.fans[6], null); - assert.equal(doc.fans[7], String(_id)); - assert.equal(String(doc._creator), creator._id); - assert.equal(doc.embed[0].array[0], user1a.id); - assert.equal(doc.embed[0].other, user1b.id); - assert.equal(doc.embed[0].nested[0].subdoc, user1c.id); - assert.equal(doc.adhoc[0].subdoc, user2a.id); - assert.equal(doc.adhoc[0].subarray[0].things[1], user2b.id); - done(); - }); - }); - }); + assert.ifError(err); + assert.equal(doc.fans.length, 8); + assert.equal(doc.fans[0], user8.id); + assert.equal(doc.fans[5], user7.id); + assert.equal(doc.fans[6], null); + assert.equal(doc.fans[7], String(_id)); + assert.equal(String(doc._creator), creator._id); + assert.equal(doc.embed[0].array[0], user1a.id); + assert.equal(doc.embed[0].other, user1b.id); + assert.equal(doc.embed[0].nested[0].subdoc, user1c.id); + assert.equal(doc.adhoc[0].subdoc, user2a.id); + assert.equal(doc.adhoc[0].subarray[0].things[1], user2b.id); + done(); + }); + }); + }); }); it('if an object', function(done) { diff --git a/test/query.test.js b/test/query.test.js index 799c69a3d93..fe0deb0727e 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1636,6 +1636,28 @@ describe('Query', function() { }); }); }); + + it('custom query methods (gh-3714)', function(done) { + var schema = new mongoose.Schema({ + name: String + }); + + schema.query.byName = function(name) { + return this.find({ name: name }); + }; + + var MyModel = db.model('gh3714', schema); + + MyModel.create({ name: 'Val' }, function(error) { + assert.ifError(error); + MyModel.find().byName('Val').exec(function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 1); + assert.equal(docs[0].name, 'Val'); + done(); + }); + }); + }); }); describe('handles falsy and object projections with defaults (gh-3256)', function() { From 36a47c8a373dae59e0d105ecc28b8c40d30cf2ae Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Jun 2016 09:39:57 -0700 Subject: [PATCH 0601/2240] feat(model): emit error event when cb throws exception Re: #3499 --- lib/model.js | 142 ++++++++++++++++++++++++++++++++++-------- test/document.test.js | 73 ++++++++++++++++++++++ 2 files changed, 188 insertions(+), 27 deletions(-) diff --git a/lib/model.js b/lib/model.js index 12481f24d4b..a11a76c8011 100644 --- a/lib/model.js +++ b/lib/model.js @@ -276,6 +276,10 @@ Model.prototype.save = function(options, fn) { options = {}; } + if (fn) { + fn = this.constructor.$wrapCallback(fn); + } + return this.$__save(options, fn); }; @@ -679,6 +683,11 @@ Model.prototype.remove = function remove(options, fn) { var _this = this; var Promise = PromiseProvider.get(); + + if (fn) { + fn = this.constructor.$wrapCallback(fn); + } + this.$__.removing = new Promise.ES6(function(resolve, reject) { var where = _this.$__where(); if (where instanceof Error) { @@ -907,26 +916,30 @@ Model.init = function init() { * @api public */ -Model.ensureIndexes = function ensureIndexes(options, cb) { +Model.ensureIndexes = function ensureIndexes(options, callback) { if (typeof options === 'function') { - cb = options; + callback = options; options = null; } if (options && options.__noPromise) { - _ensureIndexes(this, cb); + _ensureIndexes(this, callback); return; } + if (callback) { + callback = this.$wrapCallback(callback); + } + var _this = this; var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { _ensureIndexes(_this, function(error) { if (error) { - cb && cb(error); + callback && callback(error); reject(error); } - cb && cb(); + callback && callback(); resolve(); }); }); @@ -1080,6 +1093,10 @@ Model.remove = function remove(conditions, callback) { // get the mongodb collection object var mq = new this.Query(conditions, {}, this, this.collection); + if (callback) { + callback = this.$wrapCallback(callback); + } + return mq.remove(callback); }; @@ -1146,6 +1163,10 @@ Model.find = function find(conditions, projection, options, callback) { mq.select(this.schema.options.discriminatorKey); } + if (callback) { + callback = this.$wrapCallback(callback); + } + return mq.find(conditions, callback); }; @@ -1198,6 +1219,11 @@ Model.findById = function findById(id, projection, options, callback) { if (typeof id === 'undefined') { id = null; } + + if (callback) { + callback = this.$wrapCallback(callback); + } + return this.findOne({_id: id}, projection, options, callback); }; @@ -1262,6 +1288,10 @@ Model.findOne = function findOne(conditions, projection, options, callback) { mq.select(this.schema.options.discriminatorKey); } + if (callback) { + callback = this.$wrapCallback(callback); + } + return mq.findOne(conditions, callback); }; @@ -1290,6 +1320,10 @@ Model.count = function count(conditions, callback) { // get the mongodb collection object var mq = new this.Query({}, {}, this, this.collection); + if (callback) { + callback = this.$wrapCallback(callback); + } + return mq.count(conditions, callback); }; @@ -1325,6 +1359,9 @@ Model.distinct = function distinct(field, conditions, callback) { callback = conditions; conditions = {}; } + if (callback) { + callback = this.$wrapCallback(callback); + } return mq.distinct(field, conditions, callback); }; @@ -1466,6 +1503,9 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { update = conditions; conditions = undefined; } + if (callback) { + callback = this.$wrapCallback(callback); + } var fields; if (options && options.fields) { @@ -1560,6 +1600,9 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { */ Model.findByIdAndUpdate = function(id, update, options, callback) { + if (callback) { + callback = this.$wrapCallback(callback); + } if (arguments.length === 1) { if (typeof id === 'function') { var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n' @@ -1640,6 +1683,9 @@ Model.findOneAndRemove = function(conditions, options, callback) { callback = options; options = undefined; } + if (callback) { + callback = this.$wrapCallback(callback); + } var fields; if (options) { @@ -1689,6 +1735,9 @@ Model.findByIdAndRemove = function(id, options, callback) { + ' ' + this.modelName + '.findByIdAndRemove()\n'; throw new TypeError(msg); } + if (callback) { + callback = this.$wrapCallback(callback); + } return this.findOneAndRemove({_id: id}, options, callback); }; @@ -1727,8 +1776,8 @@ Model.findByIdAndRemove = function(id, options, callback) { */ Model.create = function create(doc, callback) { - var args, - cb; + var args; + var cb; if (Array.isArray(doc)) { args = doc; @@ -1745,6 +1794,9 @@ Model.create = function create(doc, callback) { var Promise = PromiseProvider.get(); var _this = this; + if (cb) { + cb = this.$wrapCallback(cb); + } var promise = new Promise.ES6(function(resolve, reject) { if (args.length === 0) { @@ -1821,6 +1873,9 @@ Model.create = function create(doc, callback) { Model.insertMany = function(arr, callback) { var _this = this; var Promise = PromiseProvider.get(); + if (callback) { + callback = this.$wrapCallback(callback); + } return new Promise.ES6(function(resolve, reject) { var toExecute = []; @@ -1967,6 +2022,9 @@ Model.hydrate = function(obj) { Model.update = function update(conditions, doc, options, callback) { var mq = new this.Query({}, {}, this, this.collection); + if (callback) { + callback = this.$wrapCallback(callback); + } // gh-2406 // make local deep copy of conditions if (conditions instanceof Document) { @@ -2048,6 +2106,9 @@ Model.update = function update(conditions, doc, options, callback) { Model.mapReduce = function mapReduce(o, callback) { var _this = this; + if (callback) { + callback = this.$wrapCallback(callback); + } var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { if (!Model.mapReduce.schema) { @@ -2131,6 +2192,10 @@ Model.geoNear = function(near, options, callback) { options = {}; } + if (callback) { + callback = this.$wrapCallback(callback); + } + var _this = this; var Promise = PromiseProvider.get(); if (!near) { @@ -2271,6 +2336,10 @@ Model.aggregate = function aggregate() { return aggregate; } + if (callback) { + callback = this.$wrapCallback(callback); + } + aggregate.exec(callback); }; @@ -2304,6 +2373,9 @@ Model.geoSearch = function(conditions, options, callback) { callback = options; options = {}; } + if (callback) { + callback = this.$wrapCallback(callback); + } var _this = this; var Promise = PromiseProvider.get(); @@ -2423,13 +2495,16 @@ Model.geoSearch = function(conditions, options, callback) { * * @param {Document|Array} docs Either a single document or array of documents to populate. * @param {Object} options A hash of key/val (path, options) used for population. - * @param {Function} [cb(err,doc)] Optional callback, executed upon completion. Receives `err` and the `doc(s)`. + * @param {Function} [callback(err,doc)] Optional callback, executed upon completion. Receives `err` and the `doc(s)`. * @return {Promise} * @api public */ -Model.populate = function(docs, paths, cb) { +Model.populate = function(docs, paths, callback) { var _this = this; + if (callback) { + callback = this.$wrapCallback(callback); + } // normalized paths var noPromise = paths && !!paths.__noPromise; @@ -2439,16 +2514,16 @@ Model.populate = function(docs, paths, cb) { var cache = {}; if (noPromise) { - _populate(this, docs, paths, cache, cb); + _populate(this, docs, paths, cache, callback); } else { var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { _populate(_this, docs, paths, cache, function(error, docs) { if (error) { - cb && cb(error); + callback && callback(error); reject(error); } else { - cb && cb(null, docs); + callback && callback(null, docs); resolve(docs); } }); @@ -2467,11 +2542,11 @@ Model.populate = function(docs, paths, cb) { * @api private */ -function _populate(model, docs, paths, cache, cb) { +function _populate(model, docs, paths, cache, callback) { var pending = paths.length; if (pending === 0) { - return cb(null, docs); + return callback(null, docs); } // each path has its own query options and must be executed separately @@ -2487,12 +2562,12 @@ function _populate(model, docs, paths, cache, cb) { function next(err) { if (err) { - return cb(err); + return callback(err); } if (--pending) { return; } - cb(null, docs); + callback(null, docs); } } @@ -2505,13 +2580,13 @@ function _populate(model, docs, paths, cache, cb) { * @return {Function} * @api private */ -function subPopulate(docs, options, cache, cb) { +function subPopulate(docs, options, cache, callback) { var _this = this; var prefix = options.path + '.'; var pop = options.populate; if (!pop) { - return cb; + return callback; } // normalize as array @@ -2523,12 +2598,14 @@ function subPopulate(docs, options, cache, cb) { var pending = pop.length; function next(err) { - if (err) return cb(err); + if (err) return callback(err); if (--pending) return; - cb(); + callback(); } - if (err || !pending) return cb(err); + if (err || !pending) { + return callback(err); + } pop.forEach(function(subOptions) { subOptions = utils.clone(subOptions); @@ -2576,7 +2653,7 @@ function subPopulate(docs, options, cache, cb) { var excludeIdReg = /\s?-_id\s?/, excludeIdRegGlobal = /\s?-_id\s?/g; -function populate(model, docs, options, cb) { +function populate(model, docs, options, callback) { var modelsMap; // normalize single / multiple docs passed @@ -2585,7 +2662,7 @@ function populate(model, docs, options, cb) { } if (docs.length === 0 || docs.every(utils.isNullOrUndefined)) { - return cb(); + return callback(); } modelsMap = getModelsMapForPopulate(model, docs, options); @@ -2649,20 +2726,20 @@ function populate(model, docs, options, cb) { } if (!hasOne) { - return cb(); + return callback(); } function next(options, assignmentOpts, err, valsFromDb) { - if (err) return cb(err); + if (err) return callback(err); vals = vals.concat(valsFromDb); _assign(null, vals, options, assignmentOpts); if (--_remaining === 0) { - cb(); + callback(); } } function _assign(err, vals, mod, assignmentOpts) { - if (err) return cb(err); + if (err) return callback(err); var options = mod.options; var lean = options.options && options.options.lean, @@ -3208,6 +3285,17 @@ Model.__subclass = function subclass(conn, schema, collection) { return Model; }; +Model.$wrapCallback = function(callback) { + var _this = this; + return function(error, res, extra) { + try { + callback(error, res, extra); + } catch (error) { + _this.emit('error', error); + } + }; +}; + /*! * Module exports. */ diff --git a/test/document.test.js b/test/document.test.js index 97078e3ed31..6699d612edf 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2812,5 +2812,78 @@ describe('document', function() { done(); }); }); + + it('emits cb errors on model for save (gh-3499)', function(done) { + var testSchema = new Schema({ name: String }); + + var Test = db.model('gh3499', testSchema); + + Test.on('error', function(error) { + assert.equal(error.message, 'fail!'); + done(); + }); + + new Test({}).save(function() { + throw new Error('fail!'); + }); + }); + + it('emits cb errors on model for save with hooks (gh-3499)', function(done) { + var testSchema = new Schema({ name: String }); + + testSchema.pre('save', function(next) { + next(); + }); + + testSchema.post('save', function(doc, next) { + next(); + }); + + var Test = db.model('gh3499_0', testSchema); + + Test.on('error', function(error) { + assert.equal(error.message, 'fail!'); + done(); + }); + + new Test({}).save(function() { + throw new Error('fail!'); + }); + }); + + it('emits cb errors on model for find() (gh-3499)', function(done) { + var testSchema = new Schema({ name: String }); + + var Test = db.model('gh3499_1', testSchema); + + Test.on('error', function(error) { + assert.equal(error.message, 'fail!'); + done(); + }); + + Test.find({}, function() { + throw new Error('fail!'); + }); + }); + + it('emits cb errors on model for find() + hooks (gh-3499)', function(done) { + var testSchema = new Schema({ name: String }); + + testSchema.post('find', function(results, next) { + assert.equal(results.length, 0); + next(); + }); + + var Test = db.model('gh3499_2', testSchema); + + Test.on('error', function(error) { + assert.equal(error.message, 'fail!'); + done(); + }); + + Test.find({}, function() { + throw new Error('fail!'); + }); + }); }); }); From ce0f16da04ed4bad3724627ef51e544d2f210254 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Jun 2016 09:46:52 -0700 Subject: [PATCH 0602/2240] refactor(test): more robust test for #3222 #3478 Fix #3499 --- lib/model.js | 4 ++-- test/model.test.js | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index a11a76c8011..749be069d61 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3287,9 +3287,9 @@ Model.__subclass = function subclass(conn, schema, collection) { Model.$wrapCallback = function(callback) { var _this = this; - return function(error, res, extra) { + return function() { try { - callback(error, res, extra); + callback.apply(null, arguments); } catch (error) { _this.emit('error', error); } diff --git a/test/model.test.js b/test/model.test.js index 96ec18b0b86..394c709e40a 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5274,6 +5274,21 @@ describe('Model', function() { }); }); + it('emits errors in create cb (gh-3222) (gh-3478)', function(done) { + var schema = new Schema({ name: 'String' }); + var Movie = db.model('gh3222', schema); + + Movie.on('error', function(error) { + assert.equal(error.message, 'fail!'); + done(); + }); + + Movie.create({ name: 'Conan the Barbarian' }, function(error) { + assert.ifError(error); + throw new Error('fail!'); + }); + }); + it('marks array as modified when initializing non-array from db (gh-2442)', function(done) { var s1 = new Schema({ array: mongoose.Schema.Types.Mixed From da73648a6fa855338db820c1aa642088922d4d83 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Jun 2016 08:33:37 -0700 Subject: [PATCH 0603/2240] chore: use latest bluebird in tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0de4130abb9..1a4df64494e 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "acquit": "0.4.1", "acquit-ignore": "0.0.3", "benchmark": "2.0.0", - "bluebird": "3.1.4", + "bluebird": "3.4.0", "co": "4.6.0", "dox": "0.3.1", "eslint": "2.4.0", From 5fd0e89739e27d3647e29297cf7c831d96f48f37 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Jun 2016 12:35:11 -0700 Subject: [PATCH 0604/2240] test(error): repro #4207 --- test/errors.validation.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/errors.validation.test.js b/test/errors.validation.test.js index 53435dbfe5f..38226c9d085 100644 --- a/test/errors.validation.test.js +++ b/test/errors.validation.test.js @@ -131,6 +131,32 @@ describe('ValidationError', function() { }); }); }); + + it('with correct error message (gh-4207)', function(done) { + var old = mongoose.Error.messages; + mongoose.Error.messages = { + 'String': { + minlength: 'woops!' + } + }; + + var AddressSchema = new Schema({ + postalCode: { type: String, minlength: 5 } + }); + + var Address = mongoose.model('gh4207', AddressSchema); + + var model = new Address({ + postalCode: '9512' + }); + + // should fail validation + model.validate(function(err) { + assert.equal(err.errors['postalCode'].message, 'woops!'); + mongoose.Error.messages = old; + done(); + }); + }); }); describe('#maxlength', function() { From 599a9b5022e26632c7baa9e4738c24d91a7f8e47 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Jun 2016 12:35:15 -0700 Subject: [PATCH 0605/2240] fix(error): allow setting .messages object Fix #4207 --- lib/error/validator.js | 3 +-- lib/schema/date.js | 6 +++--- lib/schema/number.js | 6 +++--- lib/schema/string.js | 10 +++++----- lib/schematype.js | 11 +++++------ 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/lib/error/validator.js b/lib/error/validator.js index 59e26ecb46c..96a3ba1bf59 100644 --- a/lib/error/validator.js +++ b/lib/error/validator.js @@ -3,7 +3,6 @@ */ var MongooseError = require('../error.js'); -var errorMessages = MongooseError.messages; /** * Schema validator error @@ -16,7 +15,7 @@ var errorMessages = MongooseError.messages; function ValidatorError(properties) { var msg = properties.message; if (!msg) { - msg = errorMessages.general.default; + msg = MongooseError.messages.general.default; } var message = this.formatMessage(msg, properties); diff --git a/lib/schema/date.js b/lib/schema/date.js index 0d1fb921cb0..361b87b80c0 100644 --- a/lib/schema/date.js +++ b/lib/schema/date.js @@ -2,7 +2,7 @@ * Module requirements. */ -var errorMessages = require('../error').messages; +var MongooseError = require('../error'); var utils = require('../utils'); var SchemaType = require('../schematype'); @@ -130,7 +130,7 @@ SchemaDate.prototype.min = function(value, message) { } if (value) { - var msg = message || errorMessages.Date.min; + var msg = message || MongooseError.messages.Date.min; msg = msg.replace(/{MIN}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString())); var _this = this; this.validators.push({ @@ -186,7 +186,7 @@ SchemaDate.prototype.max = function(value, message) { } if (value) { - var msg = message || errorMessages.Date.max; + var msg = message || MongooseError.messages.Date.max; msg = msg.replace(/{MAX}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString())); var _this = this; this.validators.push({ diff --git a/lib/schema/number.js b/lib/schema/number.js index 03df1816da0..3fec612dc43 100644 --- a/lib/schema/number.js +++ b/lib/schema/number.js @@ -5,7 +5,7 @@ var SchemaType = require('../schematype'); var CastError = SchemaType.CastError; var handleBitwiseOperator = require('./operators/bitwise'); -var errorMessages = require('../error').messages; +var MongooseError = require('../error'); var utils = require('../utils'); var Document; @@ -91,7 +91,7 @@ SchemaNumber.prototype.min = function(value, message) { } if (value !== null && value !== undefined) { - var msg = message || errorMessages.Number.min; + var msg = message || MongooseError.messages.Number.min; msg = msg.replace(/{MIN}/, value); this.validators.push({ validator: this.minValidator = function(v) { @@ -145,7 +145,7 @@ SchemaNumber.prototype.max = function(value, message) { } if (value !== null && value !== undefined) { - var msg = message || errorMessages.Number.max; + var msg = message || MongooseError.messages.Number.max; msg = msg.replace(/{MAX}/, value); this.validators.push({ validator: this.maxValidator = function(v) { diff --git a/lib/schema/string.js b/lib/schema/string.js index db923d0afdf..545e4bdb3a6 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -4,7 +4,7 @@ var SchemaType = require('../schematype'); var CastError = SchemaType.CastError; -var errorMessages = require('../error').messages; +var MongooseError = require('../error'); var utils = require('../utils'); var Document; @@ -92,7 +92,7 @@ SchemaString.prototype.enum = function() { errorMessage = arguments[0].message; } else { values = arguments; - errorMessage = errorMessages.String.enum; + errorMessage = MongooseError.messages.String.enum; } for (var i = 0; i < values.length; i++) { @@ -236,7 +236,7 @@ SchemaString.prototype.minlength = function(value, message) { } if (value !== null && value !== undefined) { - var msg = message || errorMessages.String.minlength; + var msg = message || MongooseError.messages.String.minlength; msg = msg.replace(/{MINLENGTH}/, value); this.validators.push({ validator: this.minlengthValidator = function(v) { @@ -290,7 +290,7 @@ SchemaString.prototype.maxlength = function(value, message) { } if (value !== null && value !== undefined) { - var msg = message || errorMessages.String.maxlength; + var msg = message || MongooseError.messages.String.maxlength; msg = msg.replace(/{MAXLENGTH}/, value); this.validators.push({ validator: this.maxlengthValidator = function(v) { @@ -346,7 +346,7 @@ SchemaString.prototype.maxlength = function(value, message) { SchemaString.prototype.match = function match(regExp, message) { // yes, we allow multiple match validators - var msg = message || errorMessages.String.match; + var msg = message || MongooseError.messages.String.match; var matchValidator = function(v) { if (!regExp) { diff --git a/lib/schematype.js b/lib/schematype.js index fb2ace93065..252aa201a9d 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -3,10 +3,9 @@ */ var utils = require('./utils'); -var error = require('./error'); -var errorMessages = error.messages; -var CastError = error.CastError; -var ValidatorError = error.ValidatorError; +var MongooseError = require('./error'); +var CastError = MongooseError.CastError; +var ValidatorError = MongooseError.ValidatorError; /** * SchemaType constructor @@ -454,7 +453,7 @@ SchemaType.prototype.validate = function(obj, message, type) { properties.type = properties.type || 'user defined'; } else { if (!message) { - message = errorMessages.general.default; + message = MongooseError.messages.general.default; } if (!type) { type = 'user defined'; @@ -557,7 +556,7 @@ SchemaType.prototype.required = function(required, message) { required = undefined; } - var msg = message || errorMessages.general.required; + var msg = message || MongooseError.messages.general.required; this.validators.unshift({ validator: this.requiredValidator, message: msg, From 700237937bb9497c8abba9ce37c6ada0b5df400e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 9 Jun 2016 08:10:47 -0700 Subject: [PATCH 0606/2240] refactor(test): reuse connections for more document tests --- test/document.test.js | 465 +++++++++++++++++++++--------------------- 1 file changed, 228 insertions(+), 237 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index 484c4c91338..ad612507d8c 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -1723,303 +1723,294 @@ describe('document', function() { db.close(done); }); - it('applies toJSON transform correctly for populated docs (gh-2910) (gh-2990)', function(done) { - var db = start(); - var parentSchema = mongoose.Schema({ - c: {type: mongoose.Schema.Types.ObjectId, ref: 'gh-2910-1'} - }); + describe('bug fixes', function() { + var db; - var called = []; - parentSchema.options.toJSON = { - transform: function(doc, ret) { - called.push(ret); - return ret; - } - }; + before(function() { + db = start(); + }); - var childSchema = mongoose.Schema({ - name: String + after(function(done) { + db.close(done); }); - var childCalled = []; - childSchema.options.toJSON = { - transform: function(doc, ret) { - childCalled.push(ret); - return ret; - } - }; + it('applies toJSON transform correctly for populated docs (gh-2910) (gh-2990)', function(done) { + var parentSchema = mongoose.Schema({ + c: {type: mongoose.Schema.Types.ObjectId, ref: 'gh-2910-1'} + }); - var Child = db.model('gh-2910-1', childSchema); - var Parent = db.model('gh-2910-0', parentSchema); - - Child.create({name: 'test'}, function(error, c) { - Parent.create({c: c._id}, function(error, p) { - Parent.findOne({_id: p._id}).populate('c').exec(function(error, p) { - var doc = p.toJSON(); - assert.equal(called.length, 1); - assert.equal(called[0]._id.toString(), p._id.toString()); - assert.equal(doc._id.toString(), p._id.toString()); - assert.equal(childCalled.length, 1); - assert.equal(childCalled[0]._id.toString(), c._id.toString()); - - called = []; - childCalled = []; - - // JSON.stringify() passes field name, so make sure we don't treat - // that as a param to toJSON (gh-2990) - doc = JSON.parse(JSON.stringify({parent: p})).parent; - assert.equal(called.length, 1); - assert.equal(called[0]._id.toString(), p._id.toString()); - assert.equal(doc._id.toString(), p._id.toString()); - assert.equal(childCalled.length, 1); - assert.equal(childCalled[0]._id.toString(), c._id.toString()); + var called = []; + parentSchema.options.toJSON = { + transform: function(doc, ret) { + called.push(ret); + return ret; + } + }; - db.close(done); - }); + var childSchema = mongoose.Schema({ + name: String }); - }); - }); - it('setters firing with objects on real paths (gh-2943)', function(done) { - var M = mongoose.model('gh2943', { - myStr: { - type: String, set: function(v) { - return v.value; + var childCalled = []; + childSchema.options.toJSON = { + transform: function(doc, ret) { + childCalled.push(ret); + return ret; } - }, - otherStr: String + }; + + var Child = db.model('gh-2910-1', childSchema); + var Parent = db.model('gh-2910-0', parentSchema); + + Child.create({name: 'test'}, function(error, c) { + Parent.create({c: c._id}, function(error, p) { + Parent.findOne({_id: p._id}).populate('c').exec(function(error, p) { + var doc = p.toJSON(); + assert.equal(called.length, 1); + assert.equal(called[0]._id.toString(), p._id.toString()); + assert.equal(doc._id.toString(), p._id.toString()); + assert.equal(childCalled.length, 1); + assert.equal(childCalled[0]._id.toString(), c._id.toString()); + + called = []; + childCalled = []; + + // JSON.stringify() passes field name, so make sure we don't treat + // that as a param to toJSON (gh-2990) + doc = JSON.parse(JSON.stringify({parent: p})).parent; + assert.equal(called.length, 1); + assert.equal(called[0]._id.toString(), p._id.toString()); + assert.equal(doc._id.toString(), p._id.toString()); + assert.equal(childCalled.length, 1); + assert.equal(childCalled[0]._id.toString(), c._id.toString()); + + done(); + }); + }); + }); }); - var t = new M({myStr: {value: 'test'}}); - assert.equal(t.myStr, 'test'); + it('setters firing with objects on real paths (gh-2943)', function(done) { + var M = mongoose.model('gh2943', { + myStr: { + type: String, set: function(v) { + return v.value; + } + }, + otherStr: String + }); - new M({otherStr: {value: 'test'}}); - assert.ok(!t.otherStr); + var t = new M({myStr: {value: 'test'}}); + assert.equal(t.myStr, 'test'); - done(); - }); + new M({otherStr: {value: 'test'}}); + assert.ok(!t.otherStr); - describe('gh-2782', function() { - it('should set data from a sub doc', function(done) { + done(); + }); + + describe('gh-2782', function() { + it('should set data from a sub doc', function(done) { + var schema1 = new mongoose.Schema({ + data: { + email: String + } + }); + var schema2 = new mongoose.Schema({ + email: String + }); + var Model1 = mongoose.model('gh-2782-1', schema1); + var Model2 = mongoose.model('gh-2782-2', schema2); + + var doc1 = new Model1({'data.email': 'some@example.com'}); + assert.equal(doc1.data.email, 'some@example.com'); + var doc2 = new Model2(); + doc2.set(doc1.data); + assert.equal(doc2.email, 'some@example.com'); + done(); + }); + }); + + it('set data from subdoc keys (gh-3346)', function(done) { var schema1 = new mongoose.Schema({ data: { email: String } }); - var schema2 = new mongoose.Schema({ - email: String - }); - var Model1 = mongoose.model('gh-2782-1', schema1); - var Model2 = mongoose.model('gh-2782-2', schema2); + var Model1 = mongoose.model('gh3346', schema1); var doc1 = new Model1({'data.email': 'some@example.com'}); assert.equal(doc1.data.email, 'some@example.com'); - var doc2 = new Model2(); - doc2.set(doc1.data); - assert.equal(doc2.email, 'some@example.com'); + var doc2 = new Model1({data: doc1.data}); + assert.equal(doc2.data.email, 'some@example.com'); done(); }); - }); - - it('set data from subdoc keys (gh-3346)', function(done) { - var schema1 = new mongoose.Schema({ - data: { - email: String - } - }); - var Model1 = mongoose.model('gh3346', schema1); - - var doc1 = new Model1({'data.email': 'some@example.com'}); - assert.equal(doc1.data.email, 'some@example.com'); - var doc2 = new Model1({data: doc1.data}); - assert.equal(doc2.data.email, 'some@example.com'); - done(); - }); - it('doesnt attempt to cast generic objects as strings (gh-3030)', function(done) { - var M = mongoose.model('gh3030', { - myStr: { - type: String - } - }); - - var t = new M({myStr: {thisIs: 'anObject'}}); - assert.ok(!t.myStr); - t.validate(function(error) { - assert.ok(error); - done(); - }); - }); - - it('single embedded schemas (gh-2689)', function(done) { - var db = start(); - - var userSchema = new mongoose.Schema({ - name: String, - email: String - }, {_id: false, id: false}); - - var userHookCount = 0; - userSchema.pre('save', function(next) { - ++userHookCount; - next(); - }); - - var eventSchema = new mongoose.Schema({ - user: userSchema, - name: String - }); + it('doesnt attempt to cast generic objects as strings (gh-3030)', function(done) { + var M = mongoose.model('gh3030', { + myStr: { + type: String + } + }); - var eventHookCount = 0; - eventSchema.pre('save', function(next) { - ++eventHookCount; - next(); + var t = new M({myStr: {thisIs: 'anObject'}}); + assert.ok(!t.myStr); + t.validate(function(error) { + assert.ok(error); + done(); + }); }); - var Event = db.model('gh2689', eventSchema); - - var e = new Event({name: 'test', user: {name: 123, email: 'val'}}); - e.save(function(error) { - assert.ifError(error); - assert.strictEqual(e.user.name, '123'); - assert.equal(eventHookCount, 1); - assert.equal(userHookCount, 1); + it('single embedded schemas (gh-2689)', function(done) { + var userSchema = new mongoose.Schema({ + name: String, + email: String + }, {_id: false, id: false}); - Event.findOne( - {user: {name: '123', email: 'val'}}, - function(error, doc) { - assert.ifError(error); - assert.ok(doc); + var userHookCount = 0; + userSchema.pre('save', function(next) { + ++userHookCount; + next(); + }); - Event.findOne( - {user: {$in: [{name: '123', email: 'val'}]}}, - function(error, doc) { - assert.ifError(error); - assert.ok(doc); - db.close(done); - }); - }); - }); - }); + var eventSchema = new mongoose.Schema({ + user: userSchema, + name: String + }); - it('single embedded schemas with validation (gh-2689)', function(done) { - var db = start(); + var eventHookCount = 0; + eventSchema.pre('save', function(next) { + ++eventHookCount; + next(); + }); - var userSchema = new mongoose.Schema({ - name: String, - email: {type: String, required: true, match: /.+@.+/} - }, {_id: false, id: false}); + var Event = db.model('gh2689', eventSchema); - var eventSchema = new mongoose.Schema({ - user: userSchema, - name: String + var e = new Event({name: 'test', user: {name: 123, email: 'val'}}); + e.save(function(error) { + assert.ifError(error); + assert.strictEqual(e.user.name, '123'); + assert.equal(eventHookCount, 1); + assert.equal(userHookCount, 1); + + Event.findOne( + {user: {name: '123', email: 'val'}}, + function(error, doc) { + assert.ifError(error); + assert.ok(doc); + + Event.findOne( + {user: {$in: [{name: '123', email: 'val'}]}}, + function(error, doc) { + assert.ifError(error); + assert.ok(doc); + done(); + }); + }); + }); }); - var Event = db.model('gh2689_1', eventSchema); - - var e = new Event({name: 'test', user: {}}); - var error = e.validateSync(); - assert.ok(error); - assert.ok(error.errors['user.email']); - assert.equal(error.errors['user.email'].kind, 'required'); + it('single embedded schemas with validation (gh-2689)', function(done) { + var userSchema = new mongoose.Schema({ + name: String, + email: {type: String, required: true, match: /.+@.+/} + }, {_id: false, id: false}); - e.user.email = 'val'; - error = e.validateSync(); + var eventSchema = new mongoose.Schema({ + user: userSchema, + name: String + }); - assert.ok(error); - assert.ok(error.errors['user.email']); - assert.equal(error.errors['user.email'].kind, 'regexp'); + var Event = db.model('gh2689_1', eventSchema); - db.close(done); - }); + var e = new Event({name: 'test', user: {}}); + var error = e.validateSync(); + assert.ok(error); + assert.ok(error.errors['user.email']); + assert.equal(error.errors['user.email'].kind, 'required'); - it('single embedded schemas with markmodified (gh-2689)', function(done) { - var db = start(); + e.user.email = 'val'; + error = e.validateSync(); - var userSchema = new mongoose.Schema({ - name: String, - email: {type: String, required: true, match: /.+@.+/} - }, {_id: false, id: false}); + assert.ok(error); + assert.ok(error.errors['user.email']); + assert.equal(error.errors['user.email'].kind, 'regexp'); - var eventSchema = new mongoose.Schema({ - user: userSchema, - name: String + done(); }); - var Event = db.model('gh2689_2', eventSchema); - - var e = new Event({name: 'test', user: {email: 'a@b'}}); - e.save(function(error, doc) { - assert.ifError(error); - assert.ok(doc); - assert.ok(!doc.isModified('user')); - assert.ok(!doc.isModified('user.email')); - assert.ok(!doc.isModified('user.name')); - doc.user.name = 'Val'; - assert.ok(doc.isModified('user')); - assert.ok(!doc.isModified('user.email')); - assert.ok(doc.isModified('user.name')); + it('single embedded schemas with markmodified (gh-2689)', function(done) { + var userSchema = new mongoose.Schema({ + name: String, + email: {type: String, required: true, match: /.+@.+/} + }, {_id: false, id: false}); - var delta = doc.$__delta()[1]; - assert.deepEqual(delta, { - $set: {'user.name': 'Val'} + var eventSchema = new mongoose.Schema({ + user: userSchema, + name: String }); - doc.save(function(error) { + var Event = db.model('gh2689_2', eventSchema); + + var e = new Event({name: 'test', user: {email: 'a@b'}}); + e.save(function(error, doc) { assert.ifError(error); - Event.findOne({_id: doc._id}, function(error, doc) { + assert.ok(doc); + assert.ok(!doc.isModified('user')); + assert.ok(!doc.isModified('user.email')); + assert.ok(!doc.isModified('user.name')); + doc.user.name = 'Val'; + assert.ok(doc.isModified('user')); + assert.ok(!doc.isModified('user.email')); + assert.ok(doc.isModified('user.name')); + + var delta = doc.$__delta()[1]; + assert.deepEqual(delta, { + $set: {'user.name': 'Val'} + }); + + doc.save(function(error) { assert.ifError(error); - assert.deepEqual(doc.user.toObject(), {email: 'a@b', name: 'Val'}); - db.close(done); + Event.findOne({_id: doc._id}, function(error, doc) { + assert.ifError(error); + assert.deepEqual(doc.user.toObject(), {email: 'a@b', name: 'Val'}); + done(); + }); }); }); }); - }); - - it('single embedded schemas + update validators (gh-2689)', function(done) { - var db = start(); - var userSchema = new mongoose.Schema({ - name: {type: String, default: 'Val'}, - email: {type: String, required: true, match: /.+@.+/} - }, {_id: false, id: false}); + it('single embedded schemas + update validators (gh-2689)', function(done) { + var userSchema = new mongoose.Schema({ + name: {type: String, default: 'Val'}, + email: {type: String, required: true, match: /.+@.+/} + }, {_id: false, id: false}); - var eventSchema = new mongoose.Schema({ - user: userSchema, - name: String - }); + var eventSchema = new mongoose.Schema({ + user: userSchema, + name: String + }); - var Event = db.model('gh2689_3', eventSchema); + var Event = db.model('gh2689_3', eventSchema); - var badUpdate = {$set: {'user.email': 'a'}}; - var options = {runValidators: true}; - Event.update({}, badUpdate, options, function(error) { - assert.ok(error); - assert.equal(error.errors['user.email'].kind, 'regexp'); + var badUpdate = {$set: {'user.email': 'a'}}; + var options = {runValidators: true}; + Event.update({}, badUpdate, options, function(error) { + assert.ok(error); + assert.equal(error.errors['user.email'].kind, 'regexp'); - var nestedUpdate = {name: 'test'}; - var options = {upsert: true, setDefaultsOnInsert: true}; - Event.update({}, nestedUpdate, options, function(error) { - assert.ifError(error); - Event.findOne({name: 'test'}, function(error, ev) { + var nestedUpdate = {name: 'test'}; + var options = {upsert: true, setDefaultsOnInsert: true}; + Event.update({}, nestedUpdate, options, function(error) { assert.ifError(error); - assert.equal(ev.user.name, 'Val'); - db.close(done); + Event.findOne({name: 'test'}, function(error, ev) { + assert.ifError(error); + assert.equal(ev.user.name, 'Val'); + done(); + }); }); }); }); - }); - - describe('bug fixes', function() { - var db; - - before(function() { - db = start(); - }); - - after(function(done) { - db.close(done); - }); it('single embedded schemas with populate (gh-3501)', function(done) { var PopulateMeSchema = new Schema({}); From 339bfca640b9774084759a1164c0a03d1a3c54d2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 9 Jun 2016 10:47:03 -0700 Subject: [PATCH 0607/2240] feat(populate): start work on integrating mongoose-populate-virtuals --- lib/model.js | 268 +++++++++++++++++++----------------- lib/schema.js | 29 ++++ test/model.populate.test.js | 35 +++++ 3 files changed, 209 insertions(+), 123 deletions(-) diff --git a/lib/model.js b/lib/model.js index 749be069d61..6c431144352 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2666,6 +2666,7 @@ function populate(model, docs, options, callback) { } modelsMap = getModelsMapForPopulate(model, docs, options); + console.log('GZ', modelsMap); var i, len = modelsMap.length, mod, match, select, vals = []; @@ -2696,9 +2697,12 @@ function populate(model, docs, options, callback) { } hasOne = true; - match._id || (match._id = { - $in: ids - }); + match.$or = []; + for (var i = 0; i < mod.docs.length; ++i) { + var query = {}; + query[mod.foreignFields[i]] = mod.ids[i]; + match.$or.push(query); + } var assignmentOpts = {}; assignmentOpts.sort = mod.options.options && mod.options.options.sort || undefined; @@ -2761,6 +2765,8 @@ function populate(model, docs, options, callback) { assignVals({ rawIds: mod.ids, + localFields: mod.localFields, + foreignFields: mod.foreignFields, rawDocs: rawDocs, rawOrder: rawOrder, docs: mod.docs, @@ -2770,6 +2776,120 @@ function populate(model, docs, options, callback) { } } +/*! + * Assigns documents returned from a population query back + * to the original document path. + */ + +function assignVals(o) { + // replace the original ids in our intermediate _ids structure + // with the documents found by query + assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, o.options, + o.localFields, o.foreignFields); + + // now update the original documents being populated using the + // result structure that contains real documents. + + var docs = o.docs; + var path = o.path; + var rawIds = o.rawIds; + var options = o.options; + + function setValue(val) { + return valueFilter(val, options); + } + + for (var i = 0; i < docs.length; ++i) { + if (utils.getValue(o.foreignFields[i], docs[i]) == null) { + continue; + } + utils.setValue(foreignFields[i], rawIds[i], docs[i], setValue); + } +} + +/*! + * Assign `vals` returned by mongo query to the `rawIds` + * structure returned from utils.getVals() honoring + * query sort order if specified by user. + * + * This can be optimized. + * + * Rules: + * + * if the value of the path is not an array, use findOne rules, else find. + * for findOne the results are assigned directly to doc path (including null results). + * for find, if user specified sort order, results are assigned directly + * else documents are put back in original order of array if found in results + * + * @param {Array} rawIds + * @param {Array} vals + * @param {Boolean} sort + * @api private + */ + +function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, localFields, foreignFields, recursed) { + // honor user specified sort order + var newOrder = []; + var sorting = options.sort && rawIds.length > 1; + var doc; + var sid; + var id; + + for (var i = 0; i < rawIds.length; ++i) { + id = rawIds[i]; + + if (Array.isArray(id)) { + // handle [ [id0, id2], [id3] ] + assignRawDocsToIdStructure(id, resultDocs, resultOrder, options, localFields, foreignFields, true); + newOrder.push(id); + continue; + } + + if (id === null && !sorting) { + // keep nulls for findOne unless sorting, which always + // removes them (backward compat) + newOrder.push(id); + continue; + } + + sid = String(id); + + if (recursed) { + // apply find behavior + + // assign matching documents in original order unless sorting + doc = resultDocs[sid]; + if (doc) { + if (sorting) { + newOrder[resultOrder[sid]] = doc; + } else { + newOrder.push(doc); + } + } else { + newOrder.push(id); + } + } else { + // apply findOne behavior - if document in results, assign, else assign null + newOrder[i] = doc = resultDocs[sid] || null; + } + } + + rawIds.length = 0; + if (newOrder.length) { + // reassign the documents based on corrected order + + // forEach skips over sparse entries in arrays so we + // can safely use this to our advantage dealing with sorted + // result sets too. + newOrder.forEach(function(doc, i) { + if (!doc) { + return; + } + rawIds[i] = doc; + }); + } +} + function getModelsMapForPopulate(model, docs, options) { var i, doc, len = docs.length, available = {}, @@ -2796,13 +2916,15 @@ function getModelsMapForPopulate(model, docs, options) { modelNames = utils.getValue(refPath, doc); } else { if (!modelNameFromQuery) { + var modelForCurrentDoc = model; var schemaForCurrentDoc; if (!schema && discriminatorKey) { modelForFindSchema = utils.getValue(discriminatorKey, doc); if (modelForFindSchema) { - schemaForCurrentDoc = model.db.model(modelForFindSchema)._getSchema(options.path); + modelForCurrentDoc = model.db.model(modelForFindSchema); + schemaForCurrentDoc = modelForCurrentDoc._getSchema(options.path); if (schemaForCurrentDoc && schemaForCurrentDoc.caster) { schemaForCurrentDoc = schemaForCurrentDoc.caster; @@ -2811,9 +2933,11 @@ function getModelsMapForPopulate(model, docs, options) { } else { schemaForCurrentDoc = schema; } + var virtual = modelForCurrentDoc.schema.virtuals[options.path]; modelNames = [ schemaForCurrentDoc && schemaForCurrentDoc.options && schemaForCurrentDoc.options.ref // declared in schema + || virtual && virtual.options && virtual.options.ref || model.modelName // an ad-hoc structure ]; } else { @@ -2829,18 +2953,25 @@ function getModelsMapForPopulate(model, docs, options) { modelNames = [modelNames]; } - var ret = convertTo_id(utils.getValue(options.path, doc)); - var id = String(utils.getValue('_id', doc)); - options._docs[id] = Array.isArray(ret) ? ret.slice() : ret; + var virtual = model.schema.virtuals[options.path]; + var localField = virtual && virtual.options ? + virtual.options.localField : + options.path; + var foreignField = virtual && virtual.options ? + virtual.options.foreignField : + '_id'; + + var ret = convertTo_id(utils.getValue(localField, doc)); if (doc.$__) { - doc.populated(options.path, options._docs[id], options); + doc.populated(options.path, Array.isArray(ret) ? ret.slice() : ret, options); } var k = modelNames.length; while (k--) { modelName = modelNames[k]; + Model = model.db.model(modelName); + if (!available[modelName]) { - Model = model.db.model(modelName); currentOptions = { model: Model }; @@ -2855,12 +2986,16 @@ function getModelsMapForPopulate(model, docs, options) { Model: Model, options: currentOptions, docs: [doc], - ids: [ret] + ids: [ret], + localFields: [localField], + foreignFields: [foreignField] }; map.push(available[modelName]); } else { available[modelName].docs.push(doc); available[modelName].ids.push(ret); + available[modelName].localFields.push(localField); + available[modelName].foreignFields.push(foreignField); } } } @@ -2890,36 +3025,6 @@ function convertTo_id(val) { return val; } -/*! - * Assigns documents returned from a population query back - * to the original document path. - */ - -function assignVals(o) { - // replace the original ids in our intermediate _ids structure - // with the documents found by query - assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, o.options); - - // now update the original documents being populated using the - // result structure that contains real documents. - - var docs = o.docs; - var path = o.path; - var rawIds = o.rawIds; - var options = o.options; - - function setValue(val) { - return valueFilter(val, options); - } - - for (var i = 0; i < docs.length; ++i) { - if (utils.getValue(path, docs[i]) == null) { - continue; - } - utils.setValue(path, rawIds[i], docs[i], setValue); - } -} - /*! * 1) Apply backwards compatible find/findOne behavior to sub documents * @@ -3019,89 +3124,6 @@ function isDoc(doc) { return true; } -/*! - * Assign `vals` returned by mongo query to the `rawIds` - * structure returned from utils.getVals() honoring - * query sort order if specified by user. - * - * This can be optimized. - * - * Rules: - * - * if the value of the path is not an array, use findOne rules, else find. - * for findOne the results are assigned directly to doc path (including null results). - * for find, if user specified sort order, results are assigned directly - * else documents are put back in original order of array if found in results - * - * @param {Array} rawIds - * @param {Array} vals - * @param {Boolean} sort - * @api private - */ - -function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, recursed) { - // honor user specified sort order - var newOrder = []; - var sorting = options.sort && rawIds.length > 1; - var doc; - var sid; - var id; - - for (var i = 0; i < rawIds.length; ++i) { - id = rawIds[i]; - - if (Array.isArray(id)) { - // handle [ [id0, id2], [id3] ] - assignRawDocsToIdStructure(id, resultDocs, resultOrder, options, true); - newOrder.push(id); - continue; - } - - if (id === null && !sorting) { - // keep nulls for findOne unless sorting, which always - // removes them (backward compat) - newOrder.push(id); - continue; - } - - sid = String(id); - - if (recursed) { - // apply find behavior - - // assign matching documents in original order unless sorting - doc = resultDocs[sid]; - if (doc) { - if (sorting) { - newOrder[resultOrder[sid]] = doc; - } else { - newOrder.push(doc); - } - } else { - newOrder.push(id); - } - } else { - // apply findOne behavior - if document in results, assign, else assign null - newOrder[i] = doc = resultDocs[sid] || null; - } - } - - rawIds.length = 0; - if (newOrder.length) { - // reassign the documents based on corrected order - - // forEach skips over sparse entries in arrays so we - // can safely use this to our advantage dealing with sorted - // result sets too. - newOrder.forEach(function(doc, i) { - if (!doc) { - return; - } - rawIds[i] = doc; - }); - } -} - /** * Finds the schema for `path`. This is different than * calling `schema.path` as it also resolves paths with diff --git a/lib/schema.js b/lib/schema.js index 5924614b155..90007bddbe0 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1260,6 +1260,35 @@ Schema.prototype.indexes = function() { */ Schema.prototype.virtual = function(name, options) { + if (options && options.ref) { + if (!options.localField) { + throw new Error("Reference virtuals require `localField` option") + } + + if (!options.foreignField) { + throw new Error("Reference virtuals require `foreignField` option") + } + + var virtual = this.virtual(name); + virtual.options = options; + return virtual. + get(function() { + if (!this.$$populatedVirtuals) { + this.$$populatedVirtuals = {}; + } + if ('name' in this.$$populatedVirtuals) { + return this.$$populatedVirtuals[name]; + } + return null + }) + .set(function(v) { + if (!this.$$populatedVirtuals) { + this.$$populatedVirtuals = {}; + } + this.$$populatedVirtuals[name] = v; + }); + } + var virtuals = this.virtuals; var parts = name.split('.'); virtuals[name] = parts.reduce(function(mem, part, i) { diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 2946c5ed02a..e44c9f86405 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3707,5 +3707,40 @@ describe('model: populate:', function() { }); }); }); + + it('basic populate virtuals (gh-2562)', function(done) { + var PersonSchema = new Schema({ + name: String, + band: String + }); + + var BandSchema = new Schema({ + name: String + }); + BandSchema.virtual('members', { + ref: 'gh2562', + localField: 'name', + foreignField: 'band' + }); + + var Person = db.model('gh2562', PersonSchema); + var Band = db.model('gh2562_0', BandSchema); + + var people = ['Axl Rose', 'Slash'].map(function(v) { + return { name: v, band: "Guns N' Roses" }; + }); + Person.create(people, function(error) { + assert.ifError(error); + Band.create({ name: "Guns N' Roses" }, function(error) { + assert.ifError(error); + var query = { name: "Guns N' Roses" }; + Band.findOne(query).populate('members').exec(function(error, gnr) { + assert.ifError(error); + assert.equal(gnr.members.length, 2); + done(); + }); + }); + }); + }); }); }); From 5c490f99e5d281e5303c023bade93a0624e5db66 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 9 Jun 2016 11:53:37 -0700 Subject: [PATCH 0608/2240] feat(populate): basic PoC for mongoose-populate-virtuals integration Re: #2562 --- lib/model.js | 51 ++++++++++++++++++++++--------------- lib/query.js | 1 - lib/schema.js | 24 ++++++++++++----- test/model.populate.test.js | 6 ++--- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/lib/model.js b/lib/model.js index 6c431144352..f382b791dfc 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2666,7 +2666,6 @@ function populate(model, docs, options, callback) { } modelsMap = getModelsMapForPopulate(model, docs, options); - console.log('GZ', modelsMap); var i, len = modelsMap.length, mod, match, select, vals = []; @@ -2697,11 +2696,8 @@ function populate(model, docs, options, callback) { } hasOne = true; - match.$or = []; - for (var i = 0; i < mod.docs.length; ++i) { - var query = {}; - query[mod.foreignFields[i]] = mod.ids[i]; - match.$or.push(query); + if (mod.foreignField !== '_id' || !match['_id']) { + match[mod.foreignField] = { $in: ids }; } var assignmentOpts = {}; @@ -2755,18 +2751,29 @@ function populate(model, docs, options, callback) { // the query result. for (var i = 0; i < len; i++) { val = vals[i]; - key = String(utils.getValue('_id', val)); - rawDocs[key] = val; - rawOrder[key] = i; + key = String(utils.getValue(mod.foreignField, val)); + if (rawDocs[key]) { + if (Array.isArray(rawDocs[key])) { + rawDocs[key].push(val); + rawOrder[key].push(i); + } else { + rawDocs[key] = [rawDocs[key], val]; + rawOrder[key] = [rawOrder[key], i]; + } + } else { + rawDocs[key] = val; + rawOrder[key] = i; + } // flag each as result of population if (!lean) val.$__.wasPopulated = true; } assignVals({ + originalModel: model, rawIds: mod.ids, - localFields: mod.localFields, - foreignFields: mod.foreignFields, + localField: mod.localField, + foreignField: mod.foreignField, rawDocs: rawDocs, rawOrder: rawOrder, docs: mod.docs, @@ -2785,13 +2792,12 @@ function assignVals(o) { // replace the original ids in our intermediate _ids structure // with the documents found by query assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, o.options, - o.localFields, o.foreignFields); + o.localField, o.foreignField); // now update the original documents being populated using the // result structure that contains real documents. var docs = o.docs; - var path = o.path; var rawIds = o.rawIds; var options = o.options; @@ -2800,10 +2806,12 @@ function assignVals(o) { } for (var i = 0; i < docs.length; ++i) { - if (utils.getValue(o.foreignFields[i], docs[i]) == null) { + if (utils.getValue(o.path, docs[i]) == null && + !o.originalModel.schema.virtuals[o.path]) { continue; } - utils.setValue(foreignFields[i], rawIds[i], docs[i], setValue); + + utils.setValue(o.path, rawIds[i], docs[i], setValue); } } @@ -2953,7 +2961,7 @@ function getModelsMapForPopulate(model, docs, options) { modelNames = [modelNames]; } - var virtual = model.schema.virtuals[options.path]; + virtual = model.schema.virtuals[options.path]; var localField = virtual && virtual.options ? virtual.options.localField : options.path; @@ -2962,8 +2970,10 @@ function getModelsMapForPopulate(model, docs, options) { '_id'; var ret = convertTo_id(utils.getValue(localField, doc)); + var id = String(utils.getValue(foreignField, doc)); + options._docs[id] = Array.isArray(ret) ? ret.slice() : ret; if (doc.$__) { - doc.populated(options.path, Array.isArray(ret) ? ret.slice() : ret, options); + doc.populated(options.path, options._docs[id], options); } var k = modelNames.length; @@ -2987,15 +2997,14 @@ function getModelsMapForPopulate(model, docs, options) { options: currentOptions, docs: [doc], ids: [ret], - localFields: [localField], - foreignFields: [foreignField] + // Assume only 1 localField + foreignField + localField: localField, + foreignField: foreignField }; map.push(available[modelName]); } else { available[modelName].docs.push(doc); available[modelName].ids.push(ret); - available[modelName].localFields.push(localField); - available[modelName].foreignFields.push(foreignField); } } } diff --git a/lib/query.js b/lib/query.js index fa283a9993d..6bf36c88514 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1172,7 +1172,6 @@ Query.prototype._findOne = function(callback) { if (err) { return callback(err); } - return options.lean === true ? callback(null, doc) : completeOne(_this.model, doc, null, projection, _this, pop, callback); diff --git a/lib/schema.js b/lib/schema.js index 90007bddbe0..2cda73bb5bd 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1262,13 +1262,25 @@ Schema.prototype.indexes = function() { Schema.prototype.virtual = function(name, options) { if (options && options.ref) { if (!options.localField) { - throw new Error("Reference virtuals require `localField` option") + throw new Error('Reference virtuals require `localField` option'); } if (!options.foreignField) { - throw new Error("Reference virtuals require `foreignField` option") + throw new Error('Reference virtuals require `foreignField` option'); } + this.pre('init', function(next, obj) { + if (obj[name]) { + if (!this.populatedVirtuals) { + this.$$populatedVirtuals = {}; + } + + this.$$populatedVirtuals[name] = obj[name]; + delete obj[name]; + } + next(); + }); + var virtual = this.virtual(name); virtual.options = options; return virtual. @@ -1276,12 +1288,12 @@ Schema.prototype.virtual = function(name, options) { if (!this.$$populatedVirtuals) { this.$$populatedVirtuals = {}; } - if ('name' in this.$$populatedVirtuals) { + if (name in this.$$populatedVirtuals) { return this.$$populatedVirtuals[name]; } - return null - }) - .set(function(v) { + return null; + }). + set(function(v) { if (!this.$$populatedVirtuals) { this.$$populatedVirtuals = {}; } diff --git a/test/model.populate.test.js b/test/model.populate.test.js index e44c9f86405..e62e0da42ba 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3727,13 +3727,13 @@ describe('model: populate:', function() { var Band = db.model('gh2562_0', BandSchema); var people = ['Axl Rose', 'Slash'].map(function(v) { - return { name: v, band: "Guns N' Roses" }; + return { name: v, band: 'Guns N\' Roses' }; }); Person.create(people, function(error) { assert.ifError(error); - Band.create({ name: "Guns N' Roses" }, function(error) { + Band.create({ name: 'Guns N\' Roses' }, function(error) { assert.ifError(error); - var query = { name: "Guns N' Roses" }; + var query = { name: 'Guns N\' Roses' }; Band.findOne(query).populate('members').exec(function(error, gnr) { assert.ifError(error); assert.equal(gnr.members.length, 2); From c929132ff179a6d2a4dd8721420e4bd755735da2 Mon Sep 17 00:00:00 2001 From: Adam Buczynski Date: Fri, 10 Jun 2016 08:19:52 +1200 Subject: [PATCH 0609/2240] Add Query prototype `.catch()` method - See #4173 --- lib/query.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/query.js b/lib/query.js index 5f17dac6cad..5f8bc1f9cf2 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2197,6 +2197,20 @@ Query.prototype.then = function(resolve, reject) { return this.exec().then(resolve, reject); }; +/** + * Executes the query returning a `Promise` which will be + * resolved with either the doc(s) or rejected with the error. + * Like `.then()`, but only takes a rejection handler. + * + * @param {Function} [reject] + * @return {Promise} + * @api public + */ + +Query.prototype.catch = function(reject) { + return this.exec().then(null, reject); +}; + /** * Finds the schema for `path`. This is different than * calling `schema.path` as it also resolves paths with From 274b0d9e23958b087b5968b0c0dfbd9c916fc177 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Jun 2016 08:18:45 -0700 Subject: [PATCH 0610/2240] test(populate): more coverage for virtual populate re: #2562 --- test/model.populate.test.js | 162 ++++++++++++++++++++++++++++++------ 1 file changed, 138 insertions(+), 24 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index e62e0da42ba..9fa664947e6 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3067,7 +3067,7 @@ describe('model: populate:', function() { } }); - describe('edge cases', function() { + describe('github issues', function() { var db; before(function() { @@ -3708,36 +3708,150 @@ describe('model: populate:', function() { }); }); - it('basic populate virtuals (gh-2562)', function(done) { - var PersonSchema = new Schema({ - name: String, - band: String - }); + describe('populate virtuals (gh-2562)', function() { + it('basic populate virtuals', function(done) { + var PersonSchema = new Schema({ + name: String, + band: String + }); - var BandSchema = new Schema({ - name: String - }); - BandSchema.virtual('members', { - ref: 'gh2562', - localField: 'name', - foreignField: 'band' + var BandSchema = new Schema({ + name: String + }); + BandSchema.virtual('members', { + ref: 'gh2562', + localField: 'name', + foreignField: 'band' + }); + + var Person = db.model('gh2562', PersonSchema); + var Band = db.model('gh2562_0', BandSchema); + + var people = _.map(['Axl Rose', 'Slash'], function(v) { + return { name: v, band: 'Guns N\' Roses' }; + }); + Person.create(people, function(error) { + assert.ifError(error); + Band.create({ name: 'Guns N\' Roses' }, function(error) { + assert.ifError(error); + var query = { name: 'Guns N\' Roses' }; + Band.findOne(query).populate('members').exec(function(error, gnr) { + assert.ifError(error); + assert.equal(gnr.members.length, 2); + done(); + }); + }); + }); }); - var Person = db.model('gh2562', PersonSchema); - var Band = db.model('gh2562_0', BandSchema); + it('multiple source docs', function(done) { + var PersonSchema = new Schema({ + name: String, + band: String + }); + + var BandSchema = new Schema({ + name: String + }); + BandSchema.virtual('members', { + ref: 'gh2562_a0', + localField: 'name', + foreignField: 'band' + }); + + var Person = db.model('gh2562_a0', PersonSchema); + var Band = db.model('gh2562_a1', BandSchema); + + var people = _.map(['Axl Rose', 'Slash'], function(v) { + return { name: v, band: 'Guns N\' Roses' }; + }); + people = people.concat(_.map(['Vince Neil', 'Nikki Sixx'], function(v) { + return { name: v, band: 'Motley Crue' }; + })); + Person.create(people, function(error) { + assert.ifError(error); + var bands = [ + { name: 'Guns N\' Roses' }, + { name: 'Motley Crue' } + ]; + Band.create(bands, function(error) { + assert.ifError(error); + Band. + find({}). + sort({ name: 1 }). + populate({ path: 'members', options: { sort: { name: 1 } } }). + exec(function(error, bands) { + assert.ifError(error); + + assert.equal(bands.length, 2); + assert.equal(bands[0].name, 'Guns N\' Roses'); + assert.equal(bands[0].members.length, 2); + assert.deepEqual(_.map(bands[0].members, 'name'), + ['Axl Rose', 'Slash']); - var people = ['Axl Rose', 'Slash'].map(function(v) { - return { name: v, band: 'Guns N\' Roses' }; + assert.equal(bands[1].name, 'Motley Crue'); + assert.equal(bands[1].members.length, 2); + assert.deepEqual(_.map(bands[1].members, 'name'), + ['Nikki Sixx', 'Vince Neil']); + done(); + }); + }); + }); }); - Person.create(people, function(error) { - assert.ifError(error); - Band.create({ name: 'Guns N\' Roses' }, function(error) { + + it('source array', function(done) { + var PersonSchema = new Schema({ + name: String + }); + + var BandSchema = new Schema({ + name: String, + people: [String] + }); + BandSchema.virtual('members', { + ref: 'gh2562_b0', + localField: 'people', + foreignField: 'name' + }); + + var Person = db.model('gh2562_b0', PersonSchema); + var Band = db.model('gh2562_b1', BandSchema); + + var bands = [ + { name: 'Guns N\' Roses', people: ['Axl Rose', 'Slash'] }, + { name: 'Motley Crue', people: ['Vince Neil', 'Nikki Sixx'] } + ]; + var people = [ + { name: 'Axl Rose' }, + { name: 'Slash' }, + { name: 'Vince Neil' }, + { name: 'Nikki Sixx' } + ]; + + Person.create(people, function(error) { assert.ifError(error); - var query = { name: 'Guns N\' Roses' }; - Band.findOne(query).populate('members').exec(function(error, gnr) { + Band.insertMany(bands, function(error) { assert.ifError(error); - assert.equal(gnr.members.length, 2); - done(); + Band. + find({}). + sort({ name: 1 }). + populate({ path: 'members', options: { sort: { name: 1 } } }). + exec(function(error, bands) { + assert.ifError(error); + + assert.equal(bands.length, 2); + assert.equal(bands[0].name, 'Guns N\' Roses'); + assert.equal(bands[0].members.length, 2); + assert.deepEqual(_.map(bands[0].members, 'name'), + ['Axl Rose', 'Slash']); + + assert.equal(bands[1].name, 'Motley Crue'); + assert.equal(bands[1].members.length, 2); + assert.deepEqual(_.map(bands[1].members, 'name'), + ['Nikki Sixx', 'Vince Neil']); + + done(); + }); }); }); }); From 86d9c5058d8ef3c605d6b2cde5f6f2b6134c028a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Jun 2016 08:34:56 -0700 Subject: [PATCH 0611/2240] docs(populate): add basic populate virtuals docs --- docs/populate.jade | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/docs/populate.jade b/docs/populate.jade index c567ed57462..aca8dd075ca 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -307,6 +307,47 @@ block content // doc.connections[0].item is a User doc // doc.connections[1].item is an Organization doc }); + + h3#populate-virtuals Populate Virtuals + :markdown + _New in 4.5.0_ + + So far you've only populated based on the `_id` field. However, that's + sometimes not the right choice. + In particular, [arrays that grow without bound are a MongoDB anti-pattern](https://docs.mongodb.com/manual/tutorial/model-referenced-one-to-many-relationships-between-documents/). + Using mongoose virtuals, you can define more sophisticated relationships + between documents. + + :js + var PersonSchema = new Schema({ + name: String, + band: String + }); + + var BandSchema = new Schema({ + name: String + }); + BandSchema.virtual('members', { + ref: 'Person', // The model to use + localField: 'name', // Find people where `localField` + foreignField: 'band' // is equal to `foreignField` + }); + + var Person = mongoose.model('Person', personSchema); + var Band = mongoose.model('Band', bandSchema); + + /** + * Suppose you have 2 bands: "Guns N' Roses" and "Motley Crue" + * And 4 people: "Axl Rose" and "Slash" with "Guns N' Roses", and + * "Vince Neil" and "Nikki Sixx" with "Motley Crue" + */ + Band.find({}).populate('members').exec(function(error, bands) { + /** + * [ { name: 'Guns N\' Roses', members: [ [Object], [Object] ] }, + * { name: 'Motley Crue', members: [ [Object], [Object] ] } ] + */ + console.log(bands); + }); h3#next Next Up :markdown From 7987d83822bebe7770b9a7dd82737efb282c480d Mon Sep 17 00:00:00 2001 From: Adam Buczynski Date: Sun, 12 Jun 2016 09:00:02 +1200 Subject: [PATCH 0612/2240] Filter out chains already in the list before concatenating --- lib/document.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index fa9f30a5371..d98e7ffd5e8 100644 --- a/lib/document.js +++ b/lib/document.js @@ -939,7 +939,9 @@ Document.prototype.modifiedPaths = function() { var parts = path.split('.'); return list.concat(parts.reduce(function(chains, part, i) { return chains.concat(parts.slice(0, i).concat(part).join('.')); - }, [])); + }, []).filter(function(chain) { + return (list.indexOf(chain) === -1); + })); }, []); }; From 6e71af00abe8abe33de0dc0866a81459252c4f02 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 13 Jun 2016 07:00:12 -0700 Subject: [PATCH 0613/2240] style(test): clean up lint violations --- test/document.modified.test.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/document.modified.test.js b/test/document.modified.test.js index e917ff6a676..0074cc61684 100644 --- a/test/document.modified.test.js +++ b/test/document.modified.test.js @@ -516,17 +516,17 @@ describe('document modified', function() { it('should reset the modified state after calling unmarkModified', function(done) { - var db = start(), - BlogPost = db.model(modelName, collection); + var db = start(); + var BlogPost = db.model(modelName, collection); var b = new BlogPost(); - assert.equal(false, b.isModified('author')) + assert.equal(b.isModified('author'), false); b.author = 'foo'; - assert.equal(true, b.isModified('author')); - assert.equal(true, b.isModified()) + assert.equal(b.isModified('author'), true); + assert.equal(b.isModified(), true); b.unmarkModified('author'); - assert.equal(false, b.isModified('author')); - assert.equal(false, b.isModified()) + assert.equal(b.isModified('author'), false); + assert.equal(b.isModified(), false); b.save(function(err) { assert.strictEqual(null, err); @@ -534,24 +534,24 @@ describe('document modified', function() { BlogPost.findById(b._id, function(err2, b2) { assert.strictEqual(null, err2); - assert.equal(false, b2.isModified('author')) - assert.equal(false, b2.isModified()) + assert.equal(b2.isModified('author'), false); + assert.equal(b2.isModified(), false); b2.author = 'bar'; - assert.equal(true, b2.isModified('author')); - assert.equal(true, b2.isModified()) + assert.equal(b2.isModified('author'), true); + assert.equal(b2.isModified(), true); b2.unmarkModified('author'); - assert.equal(false, b2.isModified('author')); - assert.equal(false, b2.isModified()) + assert.equal(b2.isModified('author'), false); + assert.equal(b2.isModified(), false); b2.save(function(err3) { - assert.strictEqual(null, err3); + assert.strictEqual(err3, null); BlogPost.findById(b._id, function(err4, b3) { - assert.strictEqual(null, err4); + assert.strictEqual(err4, null); // was not saved because modified state was unset assert.equal(b3.author, 'foo'); db.close(); done(); - }); + }); }); }); }); From 3ebf10440fb74345dfe66beb7cfc2b0850ac42f9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 13 Jun 2016 07:19:14 -0700 Subject: [PATCH 0614/2240] perf(types): remove defineProperties call for arrays Fix #3886 --- lib/types/array.js | 24 ++++++++---------------- test/schema.test.js | 6 ++++-- test/types.array.test.js | 1 - 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/lib/types/array.js b/lib/types/array.js index 11f6a4f95f0..943265d87de 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -25,26 +25,18 @@ var isMongooseObject = utils.isMongooseObject; function MongooseArray(values, path, doc) { var arr = [].concat(values); - var props = { - isMongooseArray: true, - validators: [], - _path: path, - _atomics: {}, - _schema: void 0 - }; - var tmp = {}; var keysMA = Object.keys(MongooseArray.mixin); - for (var i = 0; i < keysMA.length; ++i) { - tmp[keysMA[i]] = {enumerable: false, configurable: true, writable: true, value: MongooseArray.mixin[keysMA[i]]}; + var numKeys = keysMA.length; + for (var i = 0; i < numKeys; ++i) { + arr[keysMA[i]] = MongooseArray.mixin[keysMA[i]]; } - var keysP = Object.keys(props); - for (var j = 0; j < keysP.length; ++j) { - tmp[keysP[j]] = {enumerable: false, configurable: true, writable: true, value: props[keysP[j]]}; - } - - Object.defineProperties(arr, tmp); + arr._path = path; + arr.isMongooseArray = true; + arr.validators = []; + arr._atomics = {}; + arr._schema = void 0; // Because doc comes from the context of another function, doc === global // can happen if there was a null somewhere up the chain (see #3020) diff --git a/test/schema.test.js b/test/schema.test.js index 403969d0ac6..f4541da7749 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -408,10 +408,12 @@ describe('schema', function() { nums: [[Number]] }); var nums = test.path('nums').cast([['1', '2']]); - assert.deepEqual(nums, [[1, 2]]); + assert.equal(nums.length, 1); + assert.deepEqual(nums[0].toObject(), [1, 2]); nums = test.path('nums').cast(1); - assert.deepEqual(nums, [[1]]); + assert.equal(nums.length, 1); + assert.deepEqual(nums[0].toObject(), [1]); var threw = false; try { diff --git a/test/types.array.test.js b/test/types.array.test.js index b33670b9cbf..975f85250c4 100644 --- a/test/types.array.test.js +++ b/test/types.array.test.js @@ -36,7 +36,6 @@ describe('types array', function() { assert.ok(a.isMongooseArray); assert.equal(Array.isArray(a), true); - assert.deepEqual(Object.keys(a), Object.keys(a.toObject())); assert.deepEqual(a._atomics.constructor, Object); done(); }); From caba5be5c71aa7856cb29f9a3e86f37235183be4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 13 Jun 2016 07:38:13 -0700 Subject: [PATCH 0615/2240] chore: release 4.5.0 --- History.md | 18 ++++++++++++++++++ package.json | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index bb24a5117ca..765c909087d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,21 @@ +4.5.0 / 2016-06-13 +================== + * feat(query): added Query.prototype.catch() #4215 #4173 [adambuczynski](https://github.com/adambuczynski) + * feat(query): add Query.prototype.cursor() as a .stream() alternative #4117 #3637 #1907 + * feat(document): add markUnmodified() function #4092 [vincentcr](https://github.com/vincentcr) + * feat(aggregate): convert aggregate object to a thenable #3995 #3946 [megagon](https://github.com/megagon) + * perf(types): remove defineProperties call for array #3886 + * feat(model): add hooks for insertMany() #3846 + * feat(schema): add support for custom query methods #3740 #2372 + * feat(drivers): emit error on 'serverClosed' because that means that reconnect failed #3615 + * feat(model): emit error event when callback throws exception #3499 + * feat(model): inherit options from discriminator base schema #3414 #1818 + * feat(populate): expose mongoose-populate-virtuals inspired populate API #2562 + * feat(document): trigger remove hooks on subdocs when removing parent #2348 + * feat(schema): add support for express-style error handling middleware #2284 + * fix(model): disallow setting discriminator key #2041 + * feat(schema): add support for nested arrays #1361 + 4.4.20 / 2016-06-05 =================== * docs: clarify command buffering when using driver directly #4195 diff --git a/package.json b/package.json index 34d7e8a1db1..181110f2662 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.0-pre", + "version": "4.5.0", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 85969ef591e96b073d01176ea068df8c34fe001d Mon Sep 17 00:00:00 2001 From: Thomas de Barochez Date: Mon, 13 Jun 2016 22:51:43 +0200 Subject: [PATCH 0616/2240] TypeError-- subdocument removing callback, ensure executing a function --- lib/types/subdocument.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 83953c98e07..017a4309517 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -96,7 +96,7 @@ Subdocument.prototype.ownerDocument = function() { Subdocument.prototype.remove = function(callback) { this.$parent.set(this.$basePath, null); registerRemoveListener(this); - if (callback) { + if (typeof callback === 'function') { callback(null); } }; From e2ac186ff08ff392db2074769872e48cb3118962 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 14 Jun 2016 06:54:04 -0700 Subject: [PATCH 0617/2240] docs: add warning about assert.deepEqual in 4.5.0 Re: https://github.com/Automattic/mongoose/issues/3886#issuecomment-225737018 --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 765c909087d..e4025f7674c 100644 --- a/History.md +++ b/History.md @@ -4,7 +4,7 @@ * feat(query): add Query.prototype.cursor() as a .stream() alternative #4117 #3637 #1907 * feat(document): add markUnmodified() function #4092 [vincentcr](https://github.com/vincentcr) * feat(aggregate): convert aggregate object to a thenable #3995 #3946 [megagon](https://github.com/megagon) - * perf(types): remove defineProperties call for array #3886 + * perf(types): remove defineProperties call for array (**Note:** Because of this, a mongoose array will no longer `assert.deepEqual()` a plain old JS array) #3886 * feat(model): add hooks for insertMany() #3846 * feat(schema): add support for custom query methods #3740 #2372 * feat(drivers): emit error on 'serverClosed' because that means that reconnect failed #3615 From 6726a7d0efa9467497179a41747f3d643d77532c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 16 Jun 2016 08:01:33 -0700 Subject: [PATCH 0618/2240] chore: now working on 4.5.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 181110f2662..a222246a1b8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.0", + "version": "4.5.1-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 06e3aee2f7b92623380322fe90d77bbdc41a50f1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 16 Jun 2016 08:04:13 -0700 Subject: [PATCH 0619/2240] fix(types): improve solution for #4231 --- lib/types/subdocument.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 017a4309517..a5d9cc22977 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -90,10 +90,16 @@ Subdocument.prototype.ownerDocument = function() { /** * Null-out this subdoc * + * @param {Object} [options] * @param {Function} [callback] optional callback for compatibility with Document.prototype.remove */ -Subdocument.prototype.remove = function(callback) { +Subdocument.prototype.remove = function(options, callback) { + if (typeof options === 'function') { + callback = options; + options = null; + } + this.$parent.set(this.$basePath, null); registerRemoveListener(this); if (typeof callback === 'function') { From 5ea69e17e5f73ccae0b40bd4be4e324591b5bfac Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 16 Jun 2016 08:09:40 -0700 Subject: [PATCH 0620/2240] docs(model): clarify relationship between create() and save() Fix #4233 --- lib/model.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index f38a5836554..ccd6b6082df 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1763,8 +1763,12 @@ Model.findByIdAndRemove = function(id, options, callback) { }; /** - * Shortcut for creating a new Document that is automatically saved to the db - * if valid. + * Shortcut for saving one or more documents to the database. + * `MyModel.create(docs)` does `new MyModel(doc).save()` for every doc in + * docs. + * + * Hooks Triggered: + * - `save()` * * ####Example: * From 9650fba713cbc1a6c93e9dfab35d8ca8b133f6c9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Jun 2016 07:10:21 -0700 Subject: [PATCH 0621/2240] refactor(test): reuse connections for toJSON+toObject tests --- test/document.test.js | 501 ++++++++++++++++++++++-------------------- 1 file changed, 260 insertions(+), 241 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index eee6c5da491..9b7c5e6855b 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -499,299 +499,318 @@ describe('document', function() { }); }); - it('does not apply toObject functions of subdocuments to root document', function(done) { - var subdocSchema = new Schema({ - test: String, - wow: String + describe('toObject', function() { + var db; + before(function() { + db = start(); }); - subdocSchema.options.toObject = {}; - subdocSchema.options.toObject.transform = function(doc, ret) { - delete ret.wow; - }; - - var docSchema = new Schema({ - foo: String, - wow: Boolean, - sub: [subdocSchema] + after(function(done) { + db.close(done); }); - var db = start(), - Doc = db.model('Doc', docSchema); - - Doc.create({ - foo: 'someString', - wow: true, - sub: [{ - test: 'someOtherString', - wow: 'thisIsAString' - }] - }, function(err, doc) { - var obj = doc.toObject({ - transform: function(doc, ret) { - ret.phew = 'new'; - } + it('does not apply toObject functions of subdocuments to root document', function(done) { + var subdocSchema = new Schema({ + test: String, + wow: String }); - assert.equal(obj.phew, 'new'); - assert.ok(!doc.sub.wow); + subdocSchema.options.toObject = {}; + subdocSchema.options.toObject.transform = function(doc, ret) { + delete ret.wow; + }; - db.close(done); - }); - }); + var docSchema = new Schema({ + foo: String, + wow: Boolean, + sub: [subdocSchema] + }); - it('handles child schema transforms', function(done) { - var db = start(); - var userSchema = new Schema({ - name: String, - email: String - }); - var topicSchema = new Schema({ - title: String, - email: String, - followers: [userSchema] + var Doc = db.model('Doc', docSchema); + + Doc.create({ + foo: 'someString', + wow: true, + sub: [{ + test: 'someOtherString', + wow: 'thisIsAString' + }] + }, function(err, doc) { + var obj = doc.toObject({ + transform: function(doc, ret) { + ret.phew = 'new'; + } + }); + + assert.equal(obj.phew, 'new'); + assert.ok(!doc.sub.wow); + + done(); + }); }); - userSchema.options.toObject = { - transform: function(doc, ret) { - delete ret.email; - } - }; + it('handles child schema transforms', function(done) { + var userSchema = new Schema({ + name: String, + email: String + }); + var topicSchema = new Schema({ + title: String, + email: String, + followers: [userSchema] + }); - topicSchema.options.toObject = { - transform: function(doc, ret) { - ret.title = ret.title.toLowerCase(); - } - }; + userSchema.options.toObject = { + transform: function(doc, ret) { + delete ret.email; + } + }; - var Topic = db.model('gh2691', topicSchema, 'gh2691'); + topicSchema.options.toObject = { + transform: function(doc, ret) { + ret.title = ret.title.toLowerCase(); + } + }; - var topic = new Topic({ - title: 'Favorite Foods', - email: 'a@b.co', - followers: [{name: 'Val', email: 'val@test.co'}] - }); + var Topic = db.model('gh2691', topicSchema, 'gh2691'); - var output = topic.toObject({transform: true}); - assert.equal(output.title, 'favorite foods'); - assert.equal(output.email, 'a@b.co'); - assert.equal(output.followers[0].name, 'Val'); - assert.equal(output.followers[0].email, undefined); - db.close(done); - }); + var topic = new Topic({ + title: 'Favorite Foods', + email: 'a@b.co', + followers: [{name: 'Val', email: 'val@test.co'}] + }); - it('doesnt clobber child schema options when called with no params (gh-2035)', function(done) { - var db = start(); - var userSchema = new Schema({ - firstName: String, - lastName: String, - password: String + var output = topic.toObject({transform: true}); + assert.equal(output.title, 'favorite foods'); + assert.equal(output.email, 'a@b.co'); + assert.equal(output.followers[0].name, 'Val'); + assert.equal(output.followers[0].email, undefined); + done(); }); - userSchema.virtual('fullName').get(function() { - return this.firstName + ' ' + this.lastName; - }); + it('doesnt clobber child schema options when called with no params (gh-2035)', function(done) { + var userSchema = new Schema({ + firstName: String, + lastName: String, + password: String + }); + + userSchema.virtual('fullName').get(function() { + return this.firstName + ' ' + this.lastName; + }); - userSchema.set('toObject', {virtuals: false}); + userSchema.set('toObject', {virtuals: false}); - var postSchema = new Schema({ - owner: {type: Schema.Types.ObjectId, ref: 'gh-2035-user'}, - content: String - }); + var postSchema = new Schema({ + owner: {type: Schema.Types.ObjectId, ref: 'gh-2035-user'}, + content: String + }); - postSchema.virtual('capContent').get(function() { - return this.content.toUpperCase(); - }); + postSchema.virtual('capContent').get(function() { + return this.content.toUpperCase(); + }); - postSchema.set('toObject', {virtuals: true}); - var User = db.model('gh-2035-user', userSchema, 'gh-2035-user'); - var Post = db.model('gh-2035-post', postSchema, 'gh-2035-post'); + postSchema.set('toObject', {virtuals: true}); + var User = db.model('gh-2035-user', userSchema, 'gh-2035-user'); + var Post = db.model('gh-2035-post', postSchema, 'gh-2035-post'); - var user = new User({firstName: 'Joe', lastName: 'Smith', password: 'password'}); + var user = new User({firstName: 'Joe', lastName: 'Smith', password: 'password'}); - user.save(function(err, savedUser) { - assert.ifError(err); - var post = new Post({owner: savedUser._id, content: 'lorem ipsum'}); - post.save(function(err, savedPost) { + user.save(function(err, savedUser) { assert.ifError(err); - Post.findById(savedPost._id).populate('owner').exec(function(err, newPost) { + var post = new Post({owner: savedUser._id, content: 'lorem ipsum'}); + post.save(function(err, savedPost) { assert.ifError(err); - var obj = newPost.toObject(); - assert.equal(obj.owner.fullName, undefined); - db.close(done); + Post.findById(savedPost._id).populate('owner').exec(function(err, newPost) { + assert.ifError(err); + var obj = newPost.toObject(); + assert.equal(obj.owner.fullName, undefined); + done(); + }); }); }); }); }); - it('toJSON options', function(done) { - var doc = new TestDocument(); - - doc.init({ - test: 'test', - oids: [], - em: [{title: 'asdf'}], - nested: { - age: 5, - cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'), - path: 'my path' - }, - nested2: {} + describe('toJSON', function() { + var db; + before(function() { + db = start(); }); - // override to check if toJSON gets fired - var path = TestDocument.prototype.schema.path('em'); - path.casterConstructor.prototype.toJSON = function() { - return {}; - }; - - doc.schema.options.toJSON = {virtuals: true}; - var clone = doc.toJSON(); - assert.equal(clone.test, 'test'); - assert.ok(clone.oids instanceof Array); - assert.equal(clone.nested.age, 5); - assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); - assert.equal(clone.nested.path, 'my path'); - assert.equal(clone.nested.agePlus2, 7); - assert.equal(clone.em[0].constructor.name, 'Object'); - assert.equal(Object.keys(clone.em[0]).length, 0); - delete doc.schema.options.toJSON; - delete path.casterConstructor.prototype.toJSON; - - doc.schema.options.toJSON = {minimize: false}; - clone = doc.toJSON(); - assert.equal(clone.nested2.constructor.name, 'Object'); - assert.equal(Object.keys(clone.nested2).length, 1); - clone = doc.toJSON('8'); - assert.equal(clone.nested2.constructor.name, 'Object'); - assert.equal(Object.keys(clone.nested2).length, 1); - - // gh-852 - var arr = [doc], - err = false, - str; - try { - str = JSON.stringify(arr); - } catch (_) { - err = true; - } - assert.equal(err, false); - assert.ok(/nested2/.test(str)); - assert.equal(clone.nested2.constructor.name, 'Object'); - assert.equal(Object.keys(clone.nested2).length, 1); + after(function(done) { + db.close(done); + }); - // transform - doc.schema.options.toJSON = {}; - doc.schema.options.toJSON.transform = function xform(doc, ret) { - // ignore embedded docs - if (typeof doc.ownerDocument === 'function') { - return; - } + it('toJSON options', function(done) { + var doc = new TestDocument(); - delete ret.em; - delete ret.numbers; - delete ret.oids; - ret._id = ret._id.toString(); - }; + doc.init({ + test: 'test', + oids: [], + em: [{title: 'asdf'}], + nested: { + age: 5, + cool: DocumentObjectId.createFromHexString('4c6c2d6240ced95d0e00003c'), + path: 'my path' + }, + nested2: {} + }); - clone = doc.toJSON(); - assert.equal(clone._id, doc.id); - assert.ok(undefined === clone.em); - assert.ok(undefined === clone.numbers); - assert.ok(undefined === clone.oids); - assert.equal(clone.test, 'test'); - assert.equal(clone.nested.age, 5); + // override to check if toJSON gets fired + var path = TestDocument.prototype.schema.path('em'); + path.casterConstructor.prototype.toJSON = function() { + return {}; + }; - // transform with return value - var out = {myid: doc._id.toString()}; - doc.schema.options.toJSON.transform = function(doc, ret) { - // ignore embedded docs - if (typeof doc.ownerDocument === 'function') { - return; + doc.schema.options.toJSON = {virtuals: true}; + var clone = doc.toJSON(); + assert.equal(clone.test, 'test'); + assert.ok(clone.oids instanceof Array); + assert.equal(clone.nested.age, 5); + assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); + assert.equal(clone.nested.path, 'my path'); + assert.equal(clone.nested.agePlus2, 7); + assert.equal(clone.em[0].constructor.name, 'Object'); + assert.equal(Object.keys(clone.em[0]).length, 0); + delete doc.schema.options.toJSON; + delete path.casterConstructor.prototype.toJSON; + + doc.schema.options.toJSON = {minimize: false}; + clone = doc.toJSON(); + assert.equal(clone.nested2.constructor.name, 'Object'); + assert.equal(Object.keys(clone.nested2).length, 1); + clone = doc.toJSON('8'); + assert.equal(clone.nested2.constructor.name, 'Object'); + assert.equal(Object.keys(clone.nested2).length, 1); + + // gh-852 + var arr = [doc], + err = false, + str; + try { + str = JSON.stringify(arr); + } catch (_) { + err = true; } + assert.equal(err, false); + assert.ok(/nested2/.test(str)); + assert.equal(clone.nested2.constructor.name, 'Object'); + assert.equal(Object.keys(clone.nested2).length, 1); + + // transform + doc.schema.options.toJSON = {}; + doc.schema.options.toJSON.transform = function xform(doc, ret) { + // ignore embedded docs + if (typeof doc.ownerDocument === 'function') { + return; + } - return {myid: ret._id.toString()}; - }; + delete ret.em; + delete ret.numbers; + delete ret.oids; + ret._id = ret._id.toString(); + }; - clone = doc.toJSON(); - assert.deepEqual(out, clone); + clone = doc.toJSON(); + assert.equal(clone._id, doc.id); + assert.ok(undefined === clone.em); + assert.ok(undefined === clone.numbers); + assert.ok(undefined === clone.oids); + assert.equal(clone.test, 'test'); + assert.equal(clone.nested.age, 5); + + // transform with return value + var out = {myid: doc._id.toString()}; + doc.schema.options.toJSON.transform = function(doc, ret) { + // ignore embedded docs + if (typeof doc.ownerDocument === 'function') { + return; + } - // ignored transform with inline options - clone = doc.toJSON({x: 1, transform: false}); - assert.ok(!('myid' in clone)); - assert.equal(clone.test, 'test'); - assert.ok(clone.oids instanceof Array); - assert.equal(clone.nested.age, 5); - assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); - assert.equal(clone.nested.path, 'my path'); - assert.equal(clone.em[0].constructor.name, 'Object'); + return {myid: ret._id.toString()}; + }; - // applied transform when inline transform is true - clone = doc.toJSON({x: 1}); - assert.deepEqual(out, clone); + clone = doc.toJSON(); + assert.deepEqual(out, clone); + + // ignored transform with inline options + clone = doc.toJSON({x: 1, transform: false}); + assert.ok(!('myid' in clone)); + assert.equal(clone.test, 'test'); + assert.ok(clone.oids instanceof Array); + assert.equal(clone.nested.age, 5); + assert.equal(clone.nested.cool.toString(), '4c6c2d6240ced95d0e00003c'); + assert.equal(clone.nested.path, 'my path'); + assert.equal(clone.em[0].constructor.name, 'Object'); + + // applied transform when inline transform is true + clone = doc.toJSON({x: 1}); + assert.deepEqual(out, clone); + + // transform passed inline + function xform(self, doc, opts) { + opts.fields.split(' ').forEach(function(field) { + delete doc[field]; + }); + } - // transform passed inline - function xform(self, doc, opts) { - opts.fields.split(' ').forEach(function(field) { - delete doc[field]; + clone = doc.toJSON({ + transform: xform, + fields: '_id em numbers oids nested' }); - } - - clone = doc.toJSON({ - transform: xform, - fields: '_id em numbers oids nested' + assert.equal(doc.test, 'test'); + assert.ok(undefined === clone.em); + assert.ok(undefined === clone.numbers); + assert.ok(undefined === clone.oids); + assert.ok(undefined === clone._id); + assert.ok(undefined === clone.nested); + + // all done + delete doc.schema.options.toJSON; + done(); }); - assert.equal(doc.test, 'test'); - assert.ok(undefined === clone.em); - assert.ok(undefined === clone.numbers); - assert.ok(undefined === clone.oids); - assert.ok(undefined === clone._id); - assert.ok(undefined === clone.nested); - // all done - delete doc.schema.options.toJSON; - done(); - }); + it('jsonifying an object', function(done) { + var doc = new TestDocument({test: 'woot'}), + oidString = doc._id.toString(); + // convert to json string + var json = JSON.stringify(doc); + // parse again + var obj = JSON.parse(json); - it('jsonifying an object', function(done) { - var doc = new TestDocument({test: 'woot'}), - oidString = doc._id.toString(); - // convert to json string - var json = JSON.stringify(doc); - // parse again - var obj = JSON.parse(json); + assert.equal(obj.test, 'woot'); + assert.equal(obj._id, oidString); + done(); + }); - assert.equal(obj.test, 'woot'); - assert.equal(obj._id, oidString); - done(); - }); - it('jsonifying an object\'s populated items works (gh-1376)', function(done) { - var db = start(); - var userSchema, User, groupSchema, Group; + it('jsonifying an object\'s populated items works (gh-1376)', function(done) { + var userSchema, User, groupSchema, Group; - userSchema = new Schema({name: String}); - // includes virtual path when 'toJSON' - userSchema.set('toJSON', {getters: true}); - userSchema.virtual('hello').get(function() { - return 'Hello, ' + this.name; - }); - User = db.model('User', userSchema); + userSchema = new Schema({name: String}); + // includes virtual path when 'toJSON' + userSchema.set('toJSON', {getters: true}); + userSchema.virtual('hello').get(function() { + return 'Hello, ' + this.name; + }); + User = db.model('User', userSchema); - groupSchema = new Schema({ - name: String, - _users: [{type: Schema.ObjectId, ref: 'User'}] - }); + groupSchema = new Schema({ + name: String, + _users: [{type: Schema.ObjectId, ref: 'User'}] + }); - Group = db.model('Group', groupSchema); + Group = db.model('Group', groupSchema); - User.create({name: 'Alice'}, {name: 'Bob'}, function(err, alice, bob) { - assert.ifError(err); + User.create({name: 'Alice'}, {name: 'Bob'}, function(err, alice, bob) { + assert.ifError(err); - new Group({name: 'mongoose', _users: [alice, bob]}).save(function(err, group) { - Group.findById(group).populate('_users').exec(function(err, group) { - assert.ifError(err); - assert.ok(group.toJSON()._users[0].hello); - db.close(done); + new Group({name: 'mongoose', _users: [alice, bob]}).save(function(err, group) { + Group.findById(group).populate('_users').exec(function(err, group) { + assert.ifError(err); + assert.ok(group.toJSON()._users[0].hello); + done(); + }); }); }); }); From cc3bf85f3ee128355dd1b0b0ae01ec3be5ba6da2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Jun 2016 07:27:14 -0700 Subject: [PATCH 0622/2240] test(document): repro #4213 --- test/document.test.js | 123 ++++++++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 33 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index 9b7c5e6855b..dc650a7d2d0 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -816,6 +816,96 @@ describe('document', function() { }); }); + describe('inspect', function() { + var db; + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('inspect inherits schema options (gh-4001)', function(done) { + var opts = { + toObject: { virtuals: true }, + toJSON: { virtuals: true } + }; + var taskSchema = mongoose.Schema({ + name: { + type: String, + required: true + } + }, opts); + + taskSchema.virtual('title'). + get(function() { + return this.name; + }). + set(function(title) { + this.name = title; + }); + + var Task = db.model('gh4001', taskSchema); + + var doc = { name: 'task1', title: 'task999' }; + Task.collection.insert(doc, function(error) { + assert.ifError(error); + Task.findById(doc._id, function(error, doc) { + assert.ifError(error); + assert.equal(doc.inspect().title, 'task1'); + done(); + }); + }); + }); + + it('does not apply transform to populated docs (gh-4213)', function(done) { + var UserSchema = new Schema({ + name: String + }); + + var PostSchema = new Schema({ + title: String, + postedBy: { + type: mongoose.Schema.Types.ObjectId, + ref: 'gh4213' + } + }, { + toObject: { + transform: function(doc, ret) { + delete ret._id; + } + }, + toJSON: { + transform: function(doc, ret) { + delete ret._id; + } + } + }); + + var User = db.model('gh4213', UserSchema); + var Post = db.model('gh4213_0', PostSchema); + + var val = new User({ name: 'Val' }); + var post = new Post({ title: 'Test', postedBy: val._id }); + + Post.create(post, function(error) { + assert.ifError(error); + User.create(val, function(error) { + assert.ifError(error); + Post.find({}). + populate('postedBy'). + exec(function(error, posts) { + assert.ifError(error); + assert.equal(posts.length, 1); + assert.ok(posts[0].postedBy._id); + done(); + }); + }); + }); + }); + }); + describe('#update', function() { it('returns a Query', function(done) { var mg = new mongoose.Mongoose; @@ -2597,39 +2687,6 @@ describe('document', function() { }); }); - it('inspect inherits schema options (gh-4001)', function(done) { - var opts = { - toObject: { virtuals: true }, - toJSON: { virtuals: true } - }; - var taskSchema = mongoose.Schema({ - name: { - type: String, - required: true - } - }, opts); - - taskSchema.virtual('title'). - get(function() { - return this.name; - }). - set(function(title) { - this.name = title; - }); - - var Task = db.model('gh4001', taskSchema); - - var doc = { name: 'task1', title: 'task999' }; - Task.collection.insert(doc, function(error) { - assert.ifError(error); - Task.findById(doc._id, function(error, doc) { - assert.ifError(error); - assert.equal(doc.inspect().title, 'task1'); - done(); - }); - }); - }); - it('doesnt skipId for single nested subdocs (gh-4008)', function(done) { var childSchema = new Schema({ name: String From 649099fc924ea0ebe32ab88d930be20ad28ad893 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Jun 2016 07:27:18 -0700 Subject: [PATCH 0623/2240] fix(document): don't force transform on subdocs with inspect Fix #4213 --- lib/document.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/document.js b/lib/document.js index f1d53a8d6a1..124bad98496 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2244,13 +2244,9 @@ Document.prototype.inspect = function(options) { var opts; if (isPOJO) { opts = options; - } else if (this.schema.options.toObject) { - opts = clone(this.schema.options.toObject); - } else { - opts = {}; + opts.minimize = false; + opts.retainKeyOrder = true; } - opts.minimize = false; - opts.retainKeyOrder = true; return this.toObject(opts); }; From f3f244505673f4d4f34ea25dd6526ce81f5bcccb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Jun 2016 08:56:45 -0700 Subject: [PATCH 0624/2240] test(document): repro #4216 --- test/document.test.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index dc650a7d2d0..a71ec97a3bd 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2964,5 +2964,34 @@ describe('document', function() { throw new Error('fail!'); }); }); + + it('clears subpaths when removing single nested (gh-4216)', function(done) { + var RecurrenceSchema = new Schema({ + frequency: Number, + interval: { + type: String, + enum: ['days', 'weeks', 'months', 'years'] + } + }, { _id: false }); + + var EventSchema = new Schema({ + name: { + type: String, + trim: true + }, + recurrence: RecurrenceSchema + }); + + var Event = db.model('gh4216', EventSchema); + var ev = new Event({ + name: 'test', + recurrence: { frequency: 2, interval: 'days' } + }); + ev.recurrence = null; + ev.save(function(error) { + assert.ifError(error); + done(); + }); + }); }); }); From 00eaaed473c7de7524681b4dc7a394491bcfc909 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Jun 2016 08:57:29 -0700 Subject: [PATCH 0625/2240] fix(document): clean subpaths when removing single nested Fix #4216 --- lib/document.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/document.js b/lib/document.js index 124bad98496..b247031ca1b 100644 --- a/lib/document.js +++ b/lib/document.js @@ -690,6 +690,10 @@ Document.prototype.set = function(path, val, type, options) { shouldSet = false; } + if (schema.$isSingleNested) { + cleanModifiedSubpaths(this, path); + } + if (shouldSet) { this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal); } From 47befefa4c121b3659c3c01f98f6eae96667c390 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Jun 2016 16:51:22 -0700 Subject: [PATCH 0626/2240] test(document): repro #4218 --- test/document.test.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index a71ec97a3bd..3d3fa2e732a 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2993,5 +2993,29 @@ describe('document', function() { done(); }); }); + + it('setting path to empty object works (gh-4218)', function(done) { + var schema = new Schema({ + object: { + nested: { + field1: { type: Number, default: 1 } + } + } + }); + + var MyModel = db.model('gh4218', schema); + + MyModel.create({}, function(error, doc) { + doc.object.nested = {}; + doc.save(function(error, doc) { + assert.ifError(error); + MyModel.collection.findOne({ _id: doc._id }, function(error, doc) { + assert.ifError(error); + assert.deepEqual(doc.object.nested, {}); + done(); + }); + }); + }); + }); }); }); From 0d88dc6a950877626cbeea5ab292aa6c84966f0e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Jun 2016 16:52:32 -0700 Subject: [PATCH 0627/2240] fix(document): handle setting nested path to empty object Fix #4218 --- lib/document.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/document.js b/lib/document.js index b247031ca1b..c877283f1aa 100644 --- a/lib/document.js +++ b/lib/document.js @@ -501,10 +501,10 @@ Document.prototype.set = function(path, val, type, options) { } } - var keys = Object.keys(path), - i = keys.length, - pathtype, - key; + var keys = Object.keys(path); + var i = keys.length; + var pathtype; + var key; while (i--) { key = keys[i]; @@ -568,7 +568,14 @@ Document.prototype.set = function(path, val, type, options) { this.setValue(path, null); cleanModifiedSubpaths(this, path); } - this.set(val, path, constructing); + + if (Object.keys(val).length === 0) { + this.setValue(path, {}); + this.markModified(path); + cleanModifiedSubpaths(this, path); + } else { + this.set(val, path, constructing); + } return this; } this.invalidate(path, new MongooseError.CastError('Object', val, path)); From fa7e80dbc04168e0aac40c4af0b2c44a105dca8b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Jun 2016 16:55:58 -0700 Subject: [PATCH 0628/2240] fix(model): don't modify user-provided options object Fix #4221 --- lib/model.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index ccd6b6082df..c1a65af7311 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1530,7 +1530,6 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { var fields; if (options && options.fields) { fields = options.fields; - options.fields = undefined; } update = utils.clone(update, {depopulate: 1}); From 2e1327ed491feee20bdc6c861dbae98aa07b3e93 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Jun 2016 13:13:41 -0700 Subject: [PATCH 0629/2240] test(model): repro #4237 --- test/model.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index 394c709e40a..2cbd7d59f65 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5274,6 +5274,25 @@ describe('Model', function() { }); }); + it('insertMany() with promises (gh-4237)', function(done) { + var schema = new Schema({ + name: String + }); + var Movie = db.model('gh4237', schema); + + var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }]; + Movie.insertMany(arr).then(function(docs) { + assert.equal(docs.length, 2); + assert.ok(!docs[0].isNew); + assert.ok(!docs[1].isNew); + Movie.find({}, function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 2); + done(); + }); + }); + }); + it('emits errors in create cb (gh-3222) (gh-3478)', function(done) { var schema = new Schema({ name: 'String' }); var Movie = db.model('gh3222', schema); From 537e91212de7df075cec061265d8ff8ed9ab4649 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Jun 2016 13:13:56 -0700 Subject: [PATCH 0630/2240] fix(model): ensure wrapped insertMany() returns a promise Fix #4237 --- lib/model.js | 75 ++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/lib/model.js b/lib/model.js index c1a65af7311..82228beff00 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1895,50 +1895,44 @@ Model.create = function create(doc, callback) { Model.insertMany = function(arr, callback) { var _this = this; - var Promise = PromiseProvider.get(); if (callback) { callback = this.$wrapCallback(callback); } - return new Promise.ES6(function(resolve, reject) { - var toExecute = []; - arr.forEach(function(doc) { - toExecute.push(function(callback) { - doc = new _this(doc); - doc.validate({__noPromise: true}, function(error) { - if (error) { - return callback(error); - } - callback(null, doc); - }); + var toExecute = []; + arr.forEach(function(doc) { + toExecute.push(function(callback) { + doc = new _this(doc); + doc.validate({ __noPromise: true }, function(error) { + if (error) { + return callback(error); + } + callback(null, doc); }); }); + }); - async.parallel(toExecute, function(error, docs) { + async.parallel(toExecute, function(error, docs) { + if (error) { + callback && callback(error); + return; + } + var docObjects = docs.map(function(doc) { + if (doc.initializeTimestamps) { + return doc.initializeTimestamps().toObject({ virtuals: false }); + } + return doc.toObject({ virtuals: false }); + }); + _this.collection.insertMany(docObjects, function(error) { if (error) { - reject(error); callback && callback(error); return; } - var docObjects = docs.map(function(doc) { - if (doc.initializeTimestamps) { - return doc.initializeTimestamps().toObject({ virtuals: false }); - } - return doc.toObject({ virtuals: false }); - }); - _this.collection.insertMany(docObjects, function(error) { - if (error) { - reject(error); - callback && callback(error); - return; - } - for (var i = 0; i < docs.length; ++i) { - docs[i].isNew = false; - docs[i].emit('isNew', false); - } - resolve(docs); - callback && callback(null, docs); - }); + for (var i = 0; i < docs.length; ++i) { + docs[i].isNew = false; + docs[i].emit('isNew', false); + } + callback && callback(null, docs); }); }); }; @@ -3235,8 +3229,21 @@ Model.compile = function compile(name, schema, collectionName, connection, base) applyQueryMethods(model, schema.query); var kareemOptions = { useErrorHandlers: true }; - model.insertMany = model.hooks.createWrapper('insertMany', + model.$__insertMany = model.hooks.createWrapper('insertMany', model.insertMany, model, kareemOptions); + model.insertMany = function(arr, callback) { + var Promise = PromiseProvider.get(); + return new Promise.ES6(function(resolve, reject) { + model.$__insertMany(arr, function(error, result) { + if (error) { + callback && callback(error); + return reject(error); + } + callback && callback(null, result); + resolve(result); + }); + }); + }; return model; }; From 2e58a9ad4bcb1383e18ed7f218faf55a0d987efe Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Jun 2016 16:06:28 -0700 Subject: [PATCH 0631/2240] test(populate): repro #4234 --- test/model.populate.test.js | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 9fa664947e6..4b13c72ff62 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3855,6 +3855,54 @@ describe('model: populate:', function() { }); }); }); + + it('multiple paths (gh-4234)', function(done) { + var PersonSchema = new Schema({ + name: String, + authored: [Number], + favorites: [Number] + }); + + var BlogPostSchema = new Schema({ + _id: Number, + title: String + }); + BlogPostSchema.virtual('authors', { + ref: 'gh4234', + localField: '_id', + foreignField: 'authored' + }); + BlogPostSchema.virtual('favoritedBy', { + ref: 'gh4234', + localField: '_id', + foreignField: 'favorites' + }); + + var Person = db.model('gh4234', PersonSchema); + var BlogPost = db.model('gh4234_0', BlogPostSchema); + + var blogPosts = [{ _id: 0, title: 'Bacon is Great' }]; + var people = [{ name: 'Val', authored: [0], favorites: [0] }]; + + Person.create(people, function(error) { + assert.ifError(error); + BlogPost.create(blogPosts, function(error) { + assert.ifError(error); + BlogPost. + findOne({ _id: 0 }). + populate('authors favoritedBy'). + exec(function(error, post) { + assert.ifError(error); + console.log(post.toObject({ virtuals: true })); + assert.equal(post.authors.length, 1); + assert.equal(post.authors[0].name, 'Val'); + assert.equal(post.favoritedBy.length, 1); + assert.equal(post.favoritedBy[0].name, 'Val'); + done(); + }); + }); + }); + }); }); }); }); From f3501847b2c189bef5b20b0a869bb7f33fe2d090 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Jun 2016 16:06:33 -0700 Subject: [PATCH 0632/2240] fix(populate): dont overwrite populateVirtuals when populating multiple paths Fix #4234 --- lib/model.js | 1 - lib/schema.js | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index 82228beff00..a0dab5267fb 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2827,7 +2827,6 @@ function assignVals(o) { !o.originalModel.schema.virtuals[o.path]) { continue; } - utils.setValue(o.path, rawIds[i], docs[i], setValue); } } diff --git a/lib/schema.js b/lib/schema.js index 2cda73bb5bd..49ce6d2b63c 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1271,11 +1271,13 @@ Schema.prototype.virtual = function(name, options) { this.pre('init', function(next, obj) { if (obj[name]) { - if (!this.populatedVirtuals) { + if (!this.$$populatedVirtuals) { this.$$populatedVirtuals = {}; } - this.$$populatedVirtuals[name] = obj[name]; + this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? + obj[name] : + [obj[name]]; delete obj[name]; } next(); From 65a4efa27573ed820107611f4bb6e290b9aaae11 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Jun 2016 16:20:54 -0700 Subject: [PATCH 0633/2240] chore: release 4.5.1 --- History.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e4025f7674c..058aed883df 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,16 @@ +4.5.1 / 2016-06-18 +================== + * fix(model): ensure wrapped insertMany() returns a promise #4237 + * fix(populate): dont overwrite populateVirtuals when populating multiple paths #4234 + * docs(model): clarify relationship between create() and save() #4233 + * fix(types): handle option param in subdoc remove() #4231 [tdebarochez](https://github.com/tdebarochez) + * fix(document): dedupe modified paths #4226 #4223 [adambuczynski](https://github.com/adambuczynski) + * fix(model): don't modify user-provided options object #4221 + * fix(document): handle setting nested path to empty object #4218 #4182 + * fix(document): clean subpaths when removing single nested #4216 + * fix(document): don't force transform on subdocs with inspect #4213 + * fix(error): allow setting .messages object #4207 + 4.5.0 / 2016-06-13 ================== * feat(query): added Query.prototype.catch() #4215 #4173 [adambuczynski](https://github.com/adambuczynski) diff --git a/package.json b/package.json index a222246a1b8..482010eb522 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.1-pre", + "version": "4.5.1", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From bdbbe815ea633dc0774e516569a87c640113384f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Jun 2016 15:56:19 -0700 Subject: [PATCH 0634/2240] chore: now working on 4.5.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 482010eb522..a85aee3fb2b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.1", + "version": "4.5.2-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e4eccc1cce922efeee2270eb2ec0e7bb590cd5d7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Jun 2016 16:21:26 -0700 Subject: [PATCH 0635/2240] test(model): repro #2633 --- test/versioning.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/versioning.test.js b/test/versioning.test.js index c29445d09f2..bc6ef14c00b 100644 --- a/test/versioning.test.js +++ b/test/versioning.test.js @@ -150,6 +150,7 @@ describe('versioning', function() { function test12(err, a, b) { assert.ok(err instanceof VersionError); + assert.ok(err.stack.indexOf('versioning.test.js') !== -1); assert.ok(/No matching document/.test(err), 'changes to b should not be applied'); assert.equal(a.comments.length, 5); From 6d46e8e7397016d6b34d71ff83808173663dd499 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Jun 2016 16:22:23 -0700 Subject: [PATCH 0636/2240] fix(document): show additional context for VersionError Fix #2633 --- lib/document.js | 8 ++++++++ lib/error/version.js | 5 +++-- lib/model.js | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/document.js b/lib/document.js index c877283f1aa..ef394c56872 100644 --- a/lib/document.js +++ b/lib/document.js @@ -9,6 +9,7 @@ var Schema = require('./schema'); var ObjectExpectedError = require('./error/objectExpected'); var StrictModeError = require('./error/strict'); var ValidatorError = require('./schematype').ValidatorError; +var VersionError = require('./error').VersionError; var utils = require('./utils'); var clone = utils.clone; var isMongooseObject = utils.isMongooseObject; @@ -1887,6 +1888,7 @@ Document.prototype.$__registerHooksFromSchema = function() { var args = [].slice.call(arguments); var lastArg = args.pop(); var fn; + var originalStack = new Error().stack; return new Promise.ES6(function(resolve, reject) { if (lastArg && typeof lastArg !== 'function') { @@ -1896,6 +1898,12 @@ Document.prototype.$__registerHooksFromSchema = function() { } args.push(function(error, result) { if (error) { + // gh-2633: since VersionError is very generic, take the + // stack trace of the original save() function call rather + // than the async trace + if (error instanceof VersionError) { + error.stack = originalStack; + } _this.$__handleReject(error); fn && fn(error); reject(error); diff --git a/lib/error/version.js b/lib/error/version.js index 815b1bc31da..f38030d1543 100644 --- a/lib/error/version.js +++ b/lib/error/version.js @@ -12,8 +12,9 @@ var MongooseError = require('../error.js'); * @api private */ -function VersionError() { - MongooseError.call(this, 'No matching document found.'); +function VersionError(doc) { + MongooseError.call(this, 'No matching document found for id "' + doc._id + + '"'); Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); this.name = 'VersionError'; } diff --git a/lib/model.js b/lib/model.js index a0dab5267fb..f83c9fe26ad 100644 --- a/lib/model.js +++ b/lib/model.js @@ -212,7 +212,7 @@ Model.prototype.$__save = function(options, callback) { if (numAffected <= 0) { // the update failed. pass an error back - var err = new VersionError(); + var err = new VersionError(_this); return callback(err); } From c14f68e5ff7157c7e12485e5b29b7e0885d7bb77 Mon Sep 17 00:00:00 2001 From: Sebastian Mayr Date: Mon, 20 Jun 2016 21:29:30 +0200 Subject: [PATCH 0637/2240] Make mongoose handle undefined slightly better --- lib/document.js | 4 ++++ lib/types/array.js | 2 +- lib/types/documentarray.js | 4 ++++ test/types.array.test.js | 31 +++++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index fa9f30a5371..c6750d5b9e3 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2259,6 +2259,10 @@ Document.prototype.toString = function() { */ Document.prototype.equals = function(doc) { + if (!doc) { + return false; + } + var tid = this.get('_id'); var docid = doc.get ? doc.get('_id') : doc; if (!tid && !docid) { diff --git a/lib/types/array.js b/lib/types/array.js index 11f6a4f95f0..b0513667f65 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -525,7 +525,7 @@ MongooseArray.mixin = { mem = cur[i]; if (mem instanceof Document) { var some = values.some(function(v) { - return v.equals(mem); + return mem.equals(v); }); if (some) { [].splice.call(cur, i, 1); diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index 7e5f4c32acb..dbb9c432708 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -96,6 +96,10 @@ MongooseDocumentArray.mixin = { return value; } + if (value === undefined || value === null) { + return null; + } + // handle cast('string') or cast(ObjectId) etc. // only objects are permitted so we can safely assume that // non-objects are to be interpreted as _id diff --git a/test/types.array.test.js b/test/types.array.test.js index b33670b9cbf..881489662f6 100644 --- a/test/types.array.test.js +++ b/test/types.array.test.js @@ -775,6 +775,37 @@ describe('types array', function() { }); }); }); + + it('properly works with undefined', function(done) { + var db = start(); + var catschema = new Schema({ name: String, colors: [{hex: String}] }); + var Cat = db.model('Cat', catschema); + + var cat = new Cat({name: 'peanut', colors: [ + {hex: '#FFF'}, {hex: '#000'}, null + ]}); + + cat.save(function(err) { + assert.ifError(err); + + cat.colors.pull(undefined); // converted to null (as mongodb does) + assert.equal(cat.colors.length, 2); + assert.equal(cat.colors[0].hex, '#FFF'); + assert.equal(cat.colors[1].hex, '#000'); + + cat.save(function(err) { + assert.ifError(err); + + Cat.findById(cat._id, function(err, doc) { + assert.ifError(err); + assert.equal(doc.colors.length, 2); + assert.equal(doc.colors[0].hex, '#FFF'); + assert.equal(doc.colors[1].hex, '#000'); + db.close(done); + }); + }); + }); + }); }); describe('$pop()', function() { From 89e0ea87d0b44a487c2c4ef051e44fa21a73cbc1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Jun 2016 13:06:57 -0700 Subject: [PATCH 0638/2240] fix(connection): ensure promise.catch() catches initial connection error Fix #4135 --- lib/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index f6feea3fd70..995cd4e4dee 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -475,7 +475,7 @@ Connection.prototype._open = function(emit, callback) { callback(err); } } else { - _this.error(err, emit && callback); + _this.error(err, callback); } return; } From 0bca9f0bd42a9ef3de321869fb25ebf822a2a447 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Jun 2016 13:07:51 -0700 Subject: [PATCH 0639/2240] refactor(test): remove test print statement --- test/model.populate.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 4b13c72ff62..6d93427e774 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3893,7 +3893,6 @@ describe('model: populate:', function() { populate('authors favoritedBy'). exec(function(error, post) { assert.ifError(error); - console.log(post.toObject({ virtuals: true })); assert.equal(post.authors.length, 1); assert.equal(post.authors[0].name, 'Val'); assert.equal(post.favoritedBy.length, 1); From 57b4cb2f1a285e80308078372d5135349e70ffef Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Jun 2016 13:51:00 -0700 Subject: [PATCH 0640/2240] test(aggregate): repro #4241 --- test/aggregate.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 091ef6a3fae..380ec28a8e1 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -653,4 +653,22 @@ describe('aggregate: ', function() { done(); }); }); + + it('ability to add noCursorTimeout option (gh-4241)', function(done) { + var db = start(); + + var MyModel = db.model('gh4241', { + name: String + }); + + MyModel. + aggregate([{ $match: {name: 'test' } }]). + addCursorFlag('noCursorTimeout', true). + cursor({ async: true }). + exec(function(error, cursor) { + assert.ifError(error); + assert.ok(cursor.s.cmd.noCursorTimeout); + done(); + }); + }); }); From 5bb77f1b3136949305365ae12ac6787b27657931 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Jun 2016 13:51:03 -0700 Subject: [PATCH 0641/2240] fix(aggregate): allow setting noCursorTimeout option Fix #4241 --- lib/aggregate.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/aggregate.js b/lib/aggregate.js index 455dba9b587..9eb47d4488c 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -473,6 +473,29 @@ Aggregate.prototype.cursor = function(options) { return this; }; +/** + * Adds a [cursor flag](http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#addCursorFlag) + * + * ####Example: + * + * var cursor = Model.aggregate(..).cursor({ batchSize: 1000 }).exec(); + * cursor.each(function(error, doc) { + * // use doc + * }); + * + * @param {String} flag + * @param {Boolean} value + * @see mongodb http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#addCursorFlag + */ + +Aggregate.prototype.addCursorFlag = function(flag, value) { + if (!this.options) { + this.options = {}; + } + this.options[flag] = value; + return this; +}; + /** * Executes the aggregate pipeline on the currently bound Model. * From a12802274321c9452a5a52345c1390702c8ebfbc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 21 Jun 2016 11:00:17 -0600 Subject: [PATCH 0642/2240] chore: remove unused sauce config --- karma.sauce.conf.js | 96 --------------------------------------------- 1 file changed, 96 deletions(-) delete mode 100644 karma.sauce.conf.js diff --git a/karma.sauce.conf.js b/karma.sauce.conf.js deleted file mode 100644 index 8afa737969d..00000000000 --- a/karma.sauce.conf.js +++ /dev/null @@ -1,96 +0,0 @@ -module.exports = function(config) { - var customLaunchers = { - sl_chrome_35: { - base: 'SauceLabs', - browserName: 'chrome', - version: '35' - }, - sl_safari_6: { - base: 'SauceLabs', - browserName: 'safari', - platform: 'OS X 10.8', - version: '6' - }, - /* sl_safari_7: { - base: 'SauceLabs', - browserName: 'safari', - platform: 'OS X 10.9', - version: '7' - }, */ - sl_ie_9: { - base: 'SauceLabs', - browserName: 'internet explorer', - platform: 'Windows 7', - version: '9' - }, - sl_ie_10: { - base: 'SauceLabs', - browserName: 'internet explorer', - platform: 'Windows 7', - version: '10' - }, - sl_ie_11: { - base: 'SauceLabs', - browserName: 'internet explorer', - platform: 'Windows 7', - version: '11' - }, - sl_android_43: { - base: 'SauceLabs', - browserName: 'android', - platform: 'Linux', - version: '4.3', - deviceName: 'Android', - 'device-orientation': 'portrait' - } - }; - - config.set({ - - // base path that will be used to resolve all patterns (eg. files, exclude) - basePath: '', - - // frameworks to use - // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['mocha', 'chai'], - - // list of files / patterns to load in the browser - files: [ - './bin/mongoose.js', - './test/browser/*.js' - ], - - // test results reporter to use - // possible values: 'dots', 'progress' - // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['dots', 'saucelabs'], - - // web server port - port: 9876, - - // enable / disable colors in the output (reporters and logs) - colors: true, - - logLevel: config.LOG_INFO, - - - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, - - // Use these custom launchers for starting browsers on Sauce - customLaunchers: customLaunchers, - - // start these browsers - // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: Object.keys(customLaunchers), - - - // Continuous Integration mode - // if true, Karma captures browsers, runs the tests and exits - singleRun: true, - - sauceLabs: { - testName: 'Mongoose ' + Date.now() - } - }); -}; From 45fbda8f2d5a7104789c00630163a075a5372b00 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 21 Jun 2016 10:15:15 -0700 Subject: [PATCH 0643/2240] failing test shows lean() isn't supported yet for cursor() --- test/query.cursor.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index 73c60435dbd..a906244abd8 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -151,4 +151,29 @@ describe('QueryCursor', function() { }).catch(done); }); }); + + describe('#lean()', function() { + it('lean', function(done) { + var cursor = Model.find().sort({ name: 1 }).lean().cursor(); + + var expectedNames = ['Axl', 'Slash']; + var cur = 0; + cursor.on('data', function(doc) { + assert.equal(doc.name, expectedNames[cur++]); + assert.strictEqual(false, doc instanceof mongoose.Document); + assert.equal(doc.test, 'test'); + }); + + cursor.on('error', function(error) { + done(error); + }); + + cursor.on('end', function() { + assert.equal(cur, 2); + done(); + }); + + }); + }); + }); From d99275912f2a064623f1ea391be844be55ddb75f Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 21 Jun 2016 10:20:43 -0700 Subject: [PATCH 0644/2240] added lean() to cursor() --- lib/querycursor.js | 4 +++- test/query.cursor.test.js | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/querycursor.js b/lib/querycursor.js index 7ee84dad666..53fce88b454 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -160,7 +160,9 @@ function _next(ctx, callback) { var opts = ctx.query._mongooseOptions; if (!opts.populate) { - return _create(ctx, doc, null, callback); + return opts.lean === true ? + callback(null, doc) : + _create(ctx, doc, null, callback); } var pop = helpers.preparePopulationOptionsMQ(ctx.query, diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index a906244abd8..811921f1d72 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -161,7 +161,6 @@ describe('QueryCursor', function() { cursor.on('data', function(doc) { assert.equal(doc.name, expectedNames[cur++]); assert.strictEqual(false, doc instanceof mongoose.Document); - assert.equal(doc.test, 'test'); }); cursor.on('error', function(error) { From a248d702656e2744b2126abfa445c2303ded60b5 Mon Sep 17 00:00:00 2001 From: Pavel Chertorogov Date: Thu, 23 Jun 2016 10:36:44 +0600 Subject: [PATCH 0645/2240] Add checks for collection presence for `onOpen` and `onClose`. Problem in `for (var i in `, which can return prototype keys. I got this problem in Mocha tests. `for (var i in this.collections)` in addition to collections name, became returns `getClassName` value. And this produced following error: ``` TypeError: _this.collections[i].onOpen is not a function at open (/Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongoose/lib/connection.js:508:28) at NativeConnection.Connection.onOpen (/Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongoose/lib/connection.js:521:5) at /Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongoose/lib/connection.js:483:11 at /Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js:60:5 at /Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb/lib/db.js:234:5 at connectHandler (/Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb/lib/server.js:306:7) at g (events.js:286:16) at emitOne (events.js:96:13) at emit (events.js:188:7) at /Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb-core/lib/topologies/server.js:572:23 at /Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb-core/lib/topologies/server.js:492:18 at ScramSHA1.reauthenticate (/Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb-core/lib/auth/scram.js:312:25) at applyAuthentications (/Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb-core/lib/topologies/server.js:488:36) at /Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb-core/lib/topologies/server.js:527:7 at commandCallback (/Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb-core/lib/topologies/server.js:1194:9) at Callbacks.emit (/Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb-core/lib/topologies/server.js:119:3) at .messageHandler (/Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb-core/lib/topologies/server.js:358:23) at Socket. (/Users/nod/www/_npm/graphql-compose-mongoose/node_modules/mongodb-core/lib/connection/connection.js:292:22) at emitOne (events.js:96:13) at Socket.emit (events.js:188:7) at readableAddChunk (_stream_readable.js:172:18) at Socket.Readable.push (_stream_readable.js:130:10) at TCP.onread (net.js:542:20) ``` --- lib/connection.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 995cd4e4dee..daace096e12 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -505,7 +505,9 @@ Connection.prototype.onOpen = function(callback) { // avoid having the collection subscribe to our event emitter // to prevent 0.3 warning for (var i in _this.collections) { - _this.collections[i].onOpen(); + if (_this.collections[i]) { + _this.collections[i].onOpen(); + } } callback && callback(); @@ -604,7 +606,9 @@ Connection.prototype.onClose = function() { // avoid having the collection subscribe to our event emitter // to prevent 0.3 warning for (var i in this.collections) { - this.collections[i].onClose(); + if (this.collections[i]) { + this.collections[i].onClose(); + } } this.emit('close'); From 89f90ac5e81f0bc7c21d9f2ea7942e7b409b6d51 Mon Sep 17 00:00:00 2001 From: Pavel Chertorogov Date: Thu, 23 Jun 2016 11:42:45 +0600 Subject: [PATCH 0646/2240] fix change check presence via utils.object.hasOwnProperty --- lib/connection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index daace096e12..f1dccd764ac 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -505,7 +505,7 @@ Connection.prototype.onOpen = function(callback) { // avoid having the collection subscribe to our event emitter // to prevent 0.3 warning for (var i in _this.collections) { - if (_this.collections[i]) { + if (utils.object.hasOwnProperty(_this.collections, i)) { _this.collections[i].onOpen(); } } @@ -606,7 +606,7 @@ Connection.prototype.onClose = function() { // avoid having the collection subscribe to our event emitter // to prevent 0.3 warning for (var i in this.collections) { - if (this.collections[i]) { + if (utils.object.hasOwnProperty(this.collections, i)) { this.collections[i].onClose(); } } From ae884e4d53085ca026e6d767bcec096a20d8c81a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 23 Jun 2016 11:25:28 -0600 Subject: [PATCH 0647/2240] fix(cast): allow strings for $type operator Fix #4256 --- lib/cast.js | 4 ++-- test/model.query.casting.test.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index ddecddf11f3..6223f1a47f4 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -165,8 +165,8 @@ module.exports = function cast(schema, obj) { } if ($cond === '$type') { - if (typeof nested !== 'number') { - throw new Error('$type parameter must be Number'); + if (typeof nested !== 'number' && typeof nested !== 'string') { + throw new Error('$type parameter must be number or string'); } continue; } diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index dc7f076f6f0..b29202bc376 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -207,11 +207,11 @@ describe('model query casting', function() { }); it('works with $type matching', function(done) { - var db = start(), - B = db.model(modelName, collection); + var db = start(); + var B = db.model(modelName, collection); - B.find({title: {$type: 'asd'}}, function(err) { - assert.equal(err.message, '$type parameter must be Number'); + B.find({title: {$type: {x:1}}}, function(err) { + assert.equal(err.message, '$type parameter must be number or string'); B.find({title: {$type: 2}}, function(err, posts) { assert.ifError(err); From 242173000ac3541221edd3a802161111c58eca8a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 23 Jun 2016 11:52:58 -0600 Subject: [PATCH 0648/2240] fix(connection): emit error if no promise handler Fix #4135 --- lib/connection.js | 16 +++++++++------- lib/index.js | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 995cd4e4dee..1d5887cda3e 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -279,12 +279,12 @@ Connection.prototype.open = function(host, database, port, options, callback) { var _this = this; var Promise = PromiseProvider.get(); - return new Promise.ES6(function(resolve, reject) { - _this._open(!!callback, function(error) { + var promise = new Promise.ES6(function(resolve, reject) { + _this._open(true, function(error) { callback && callback(error); if (error) { reject(error); - if (!callback && _this.listeners('error').length) { + if (!callback && !promise.$hasHandler) { _this.emit('error', error); } return; @@ -292,6 +292,7 @@ Connection.prototype.open = function(host, database, port, options, callback) { resolve(); }); }); + return promise; }; /** @@ -416,12 +417,12 @@ Connection.prototype.openSet = function(uris, database, options, callback) { var _this = this; var Promise = PromiseProvider.get(); - return new Promise.ES6(function(resolve, reject) { - _this._open(!!callback, function(error) { + var promise = new Promise.ES6(function(resolve, reject) { + _this._open(true, function(error) { callback && callback(error); if (error) { reject(error); - if (!callback && _this.listeners('error').length) { + if (!callback && !promise.$hasHandler) { _this.emit('error', error); } return; @@ -429,6 +430,7 @@ Connection.prototype.openSet = function(uris, database, options, callback) { resolve(); }); }); + return promise; }; /** @@ -475,7 +477,7 @@ Connection.prototype._open = function(emit, callback) { callback(err); } } else { - _this.error(err, callback); + _this.error(err, emit && callback); } return; } diff --git a/lib/index.js b/lib/index.js index 0be0c9f8442..ed39c2f0ffb 100644 --- a/lib/index.js +++ b/lib/index.js @@ -766,6 +766,7 @@ MongooseThenable.prototype.then = function(onFulfilled, onRejected) { 'has been called')); }).then(onFulfilled, onRejected); } + this.$opPromise.$hasHandler = true; return this.$opPromise.then(onFulfilled, onRejected); }; From 31f38439e0a3acde8bee7f998df1673690b55065 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 24 Jun 2016 20:48:17 -0400 Subject: [PATCH 0649/2240] chore: release 4.5.2 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 058aed883df..0575b09059c 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.5.2 / 2016-06-24 +================== + * fix(connection): add checks for collection presence for `onOpen` and `onClose` #4259 [nodkz](https://github.com/nodkz) + * fix(cast): allow strings for $type operator #4256 + * fix(querycursor): support lean() #4255 [pyramation](https://github.com/pyramation) + * fix(aggregate): allow setting noCursorTimeout option #4241 + * fix(document): handle undefined for Array.pull #4222 [Sebmaster](https://github.com/Sebmaster) + * fix(connection): ensure promise.catch() catches initial connection error #4135 + * fix(document): show additional context for VersionError #2633 + 4.5.1 / 2016-06-18 ================== * fix(model): ensure wrapped insertMany() returns a promise #4237 diff --git a/package.json b/package.json index a85aee3fb2b..431916999d1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.2-pre", + "version": "4.5.2", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 70baf9fb2c46d1ef2e58437f787249679a998578 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Jun 2016 11:48:43 -0700 Subject: [PATCH 0650/2240] chore: now working on 4.5.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 431916999d1..b2a2e13cb04 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.2", + "version": "4.5.3-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From fbbba27ec5eb05afa5091cfd942003921d9e51ff Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Jun 2016 11:54:08 -0700 Subject: [PATCH 0651/2240] docs(guide): introduce query helpers in guide Re: #3714 --- docs/guide.jade | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/docs/guide.jade b/docs/guide.jade index 160c2c0b2a4..9134611c8b7 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -89,9 +89,9 @@ block content var animalSchema = new Schema({ name: String, type: String }); // assign a function to the "methods" object of our animalSchema - animalSchema.methods.findSimilarTypes = function (cb) { + animalSchema.methods.findSimilarTypes = function(cb) { return this.model('Animal').find({ type: this.type }, cb); - } + }; p | Now all of our code animal @@ -102,7 +102,7 @@ block content var Animal = mongoose.model('Animal', animalSchema); var dog = new Animal({ type: 'dog' }); - dog.findSimilarTypes(function (err, dogs) { + dog.findSimilarTypes(function(err, dogs) { console.log(dogs); // woof }); @@ -116,12 +116,28 @@ block content :js // assign a function to the "statics" object of our animalSchema - animalSchema.statics.findByName = function (name, cb) { + animalSchema.statics.findByName = function(name, cb) { return this.find({ name: new RegExp(name, 'i') }, cb); - } + }; var Animal = mongoose.model('Animal', animalSchema); - Animal.findByName('fido', function (err, animals) { + Animal.findByName('fido', function(err, animals) { + console.log(animals); + }); + + h3#query-helpers Query Helpers + :markdown + You can also add query helper functions, which are like instance methods, + but for mongoose queries. Query helper methods let you extend mongoose's + [chainable query builder API](./queries.html). + + :js + animalSchema.query.byName = function(name) { + return this.find({ name: new RegExp(name, 'i') }); + }; + + var Animal = mongoose.model('Animal', animalSchema); + Animal.find().byName('fido').exec(function(err, animals) { console.log(animals); }); From 3a23bd373a6bb58bb04e6c69f814fb62d1d48f9c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Jun 2016 12:21:32 -0700 Subject: [PATCH 0652/2240] test(populate): repro #4263 --- test/model.populate.test.js | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 6d93427e774..de27fcfd27d 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3902,6 +3902,48 @@ describe('model: populate:', function() { }); }); }); + + it('justOne option (gh-4263)', function(done) { + var PersonSchema = new Schema({ + name: String, + authored: [Number] + }); + + var BlogPostSchema = new Schema({ + _id: Number, + title: String + }); + BlogPostSchema.virtual('author', { + ref: 'gh4263', + localField: '_id', + foreignField: 'authored', + justOne: true + }); + + var Person = db.model('gh4263', PersonSchema); + var BlogPost = db.model('gh4263_0', BlogPostSchema); + + var blogPosts = [{ _id: 0, title: 'Bacon is Great' }]; + var people = [ + { name: 'Val', authored: [0] }, + { name: 'Test', authored: [0] } + ]; + + Person.create(people, function(error) { + assert.ifError(error); + BlogPost.create(blogPosts, function(error) { + assert.ifError(error); + BlogPost. + findOne({ _id: 0 }). + populate('author'). + exec(function(error, post) { + assert.ifError(error); + assert.equal(post.author.name, 'Val'); + done(); + }); + }); + }); + }); }); }); }); From 904f3a17a7ded5367e7f710b6386c7b0dcbd6e3c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Jun 2016 12:21:36 -0700 Subject: [PATCH 0653/2240] fix(populate): support `justOne` option for populate virtuals Fix #4263 --- lib/model.js | 12 ++++++++++-- lib/schema.js | 11 ++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index f83c9fe26ad..c18c8a62510 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2739,7 +2739,13 @@ function populate(model, docs, options, callback) { mod.options.options.limit = mod.options.options.limit * ids.length; } - mod.Model.find(match, select, mod.options.options, next.bind(this, mod, assignmentOpts)); + if (mod.justOne) { + mod.Model.findOne(match, select, mod.options.options, + next.bind(this, mod, assignmentOpts)); + } else { + mod.Model.find(match, select, mod.options.options, + next.bind(this, mod, assignmentOpts)); + } } if (!hasOne) { @@ -2984,6 +2990,7 @@ function getModelsMapForPopulate(model, docs, options) { var foreignField = virtual && virtual.options ? virtual.options.foreignField : '_id'; + var justOne = virtual && virtual.options && virtual.options.justOne; var ret = convertTo_id(utils.getValue(localField, doc)); var id = String(utils.getValue(foreignField, doc)); @@ -3015,7 +3022,8 @@ function getModelsMapForPopulate(model, docs, options) { ids: [ret], // Assume only 1 localField + foreignField localField: localField, - foreignField: foreignField + foreignField: foreignField, + justOne: justOne }; map.push(available[modelName]); } else { diff --git a/lib/schema.js b/lib/schema.js index 49ce6d2b63c..4f47e70ebd3 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1275,9 +1275,14 @@ Schema.prototype.virtual = function(name, options) { this.$$populatedVirtuals = {}; } - this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? - obj[name] : - [obj[name]]; + if (options.justOne) { + this.$$populatedVirtuals[name] = obj[name]; + } else { + this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? + obj[name] : + [obj[name]]; + } + delete obj[name]; } next(); From adf7fac51672e15c5f855ba9b1ffc1ce7a5f0293 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Jun 2016 13:24:10 -0700 Subject: [PATCH 0654/2240] test(populate): repro #4261 --- test/model.populate.test.js | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index de27fcfd27d..1825e5a28c4 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3944,6 +3944,47 @@ describe('model: populate:', function() { }); }); }); + + it('specify model in populate (gh-4264)', function(done) { + var PersonSchema = new Schema({ + name: String, + authored: [Number] + }); + + var BlogPostSchema = new Schema({ + _id: Number, + title: String + }); + BlogPostSchema.virtual('authors', { + ref: true, + localField: '_id', + foreignField: 'authored' + }); + + var Person = db.model('gh4264', PersonSchema); + var BlogPost = db.model('gh4264_0', BlogPostSchema); + + var blogPosts = [{ _id: 0, title: 'Bacon is Great' }]; + var people = [ + { name: 'Val', authored: [0] } + ]; + + Person.create(people, function(error) { + assert.ifError(error); + BlogPost.create(blogPosts, function(error) { + assert.ifError(error); + BlogPost. + findOne({ _id: 0 }). + populate({ path: 'authors', model: Person }). + exec(function(error, post) { + assert.ifError(error); + assert.equal(post.authors.length, 1); + assert.equal(post.authors[0].name, 'Val'); + done(); + }); + }); + }); + }); }); }); }); From b70926e50cc3d44df4276e55d06c3554f178b7ee Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Jun 2016 13:24:14 -0700 Subject: [PATCH 0655/2240] fix(populate): ensure model param gets used for populate virtuals Fix #4261 --- lib/model.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/model.js b/lib/model.js index c18c8a62510..a45a78a7d20 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2571,9 +2571,6 @@ function _populate(model, docs, paths, cache, callback) { var path; while (i--) { path = paths[i]; - if (typeof path.model === 'function') { - model = path.model; - } populate(model, docs, path, subPopulate.call(model, docs, path, cache, next)); } @@ -2927,6 +2924,8 @@ function getModelsMapForPopulate(model, docs, options) { modelNameFromQuery = options.model && options.model.modelName || options.model, schema, refPath, Model, currentOptions, modelNames, modelName, discriminatorKey, modelForFindSchema; + var originalOptions = utils.clone(options); + schema = model._getSchema(options.path); if (schema && schema.caster) { @@ -3002,18 +3001,20 @@ function getModelsMapForPopulate(model, docs, options) { var k = modelNames.length; while (k--) { modelName = modelNames[k]; - Model = model.db.model(modelName); + Model = originalOptions.model && originalOptions.model.modelName ? + originalOptions.model : + model.db.model(modelName); if (!available[modelName]) { currentOptions = { model: Model }; + utils.merge(currentOptions, options); if (schema && !discriminatorKey) { - options.model = Model; + currentOptions.model = Model; } - - utils.merge(currentOptions, options); + options.model = Model; available[modelName] = { Model: Model, From ecf8ed11695a810cc810d6f6a91925224a10f0fb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Jun 2016 14:05:42 -0700 Subject: [PATCH 0656/2240] test(querycursor): repro #4258 --- test/query.cursor.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index 811921f1d72..4f9987981a9 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -175,4 +175,29 @@ describe('QueryCursor', function() { }); }); + describe('#close()', function() { + it('works (gh-4258)', function(done) { + var cursor = Model.find().sort({ name: 1 }).cursor(); + cursor.next(function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Axl'); + assert.equal(doc.test, 'test'); + + var closed = false; + cursor.on('close', function() { + closed = true; + }); + + cursor.close(function(error) { + assert.ifError(error); + assert.ok(closed); + cursor.next(function(error) { + assert.ok(error); + assert.equal(error.message, 'Cursor is closed'); + done(); + }); + }); + }); + }); + }); }); From 4a4662a6692311652505129bb79e27c1266937a7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Jun 2016 14:05:48 -0700 Subject: [PATCH 0657/2240] fix(querycursor): add ability to properly close the cursor Fix #4258 --- lib/querycursor.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lib/querycursor.js b/lib/querycursor.js index 53fce88b454..dc0bf98bca2 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -62,6 +62,35 @@ QueryCursor.prototype._read = function() { }); }; +/** + * Marks this cursor as closed. Will stop streaming and subsequent calls to + * `next()` will error. + * + * @param {Function} callback + * @return {Promise} + * @api public + * @method close + * @emits close + * @see MongoDB driver cursor#close http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#close + */ + +QueryCursor.prototype.close = function(callback) { + var Promise = PromiseProvider.get(); + var _this = this; + return new Promise.ES6(function(resolve, reject) { + _this.cursor.close(function(error) { + if (error) { + callback && callback(error); + reject(error); + return _this.emit('error', error); + } + _this.emit('close'); + resolve(); + callback && callback(); + }); + }); +}; + /** * Get the next document from this cursor. Will return `null` when there are * no documents left. From e00de5df662dec33c80aeca964f0b372d8bf799c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Jun 2016 14:23:37 -0700 Subject: [PATCH 0658/2240] docs(querycursor): improve cursor docs re: #4258 --- docs/queries.jade | 14 +++++++++++++- lib/querycursor.js | 11 ++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/queries.jade b/docs/queries.jade index 4c253ebefae..5a920028519 100644 --- a/docs/queries.jade +++ b/docs/queries.jade @@ -85,7 +85,19 @@ block content h3 Streaming :markdown - Queries can be [streamed](http://nodejs.org/api/stream.html) from MongoDB to your application as well. Simply call the query's [stream](./api.html#query_Query-stream) method instead of [exec](./api.html#query_Query-exec) to return an instance of [QueryStream](./api.html#querystream_QueryStream). Note: QueryStreams are Node.js 0.8 style read streams not Node.js 0.10 style. + You can [stream](http://nodejs.org/api/stream.html) query results from + MongoDB. You need to call the + [Query#cursor()](./api.html#query_Query-stream) function instead of + [Query#exec](./api.html#query_Query-exec) to return an instance of + [QueryCursor](./api.html#querycursor-js). + :js + var cursor = Person.find({ occupation: /host/ }).cursor(); + cursor.on('data', function(doc) { + // Called once for every document + }); + cursor.on('close', function() { + // Called when done + }); h3#next Next Up :markdown diff --git a/lib/querycursor.js b/lib/querycursor.js index dc0bf98bca2..1a08c751c2f 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -8,8 +8,13 @@ var helpers = require('./queryhelpers'); var util = require('util'); /** - * QueryCursor constructor. Do **not** instantiate this class directly, use - * `Query.prototype.cursor()` instead. + * A QueryCursor is a concurrency primitive for processing query results + * one document at a time. A QueryCursor fulfills the [Node.js streams3 API](https://strongloop.com/strongblog/whats-new-io-js-beta-streams3/), + * in addition to several other mechanisms for loading documents from MongoDB + * one at a time. + * + * Unless you're an advanced user, do **not** instantiate this class directly. + * Use [`Query#cursor()`](/api.html#query_Query-cursor) instead. * * @param {Query} query * @param {Object} options query options passed to `.find()` @@ -18,7 +23,7 @@ var util = require('util'); * @event `error`: Emitted when an error occurred * @event `data`: Emitted when the stream is flowing and the next doc is ready * @event `end`: Emitted when the stream is exhausted - * @api private + * @api public */ function QueryCursor(query, options) { From 6192a638ad31cf24fe09e58e5797526587fcd437 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Jun 2016 11:00:24 -0700 Subject: [PATCH 0659/2240] test(querycursor): repro #4266 --- test/query.cursor.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index 4f9987981a9..48b56f2d11e 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -59,6 +59,19 @@ describe('QueryCursor', function() { }); }); + it('with limit (gh-4266)', function(done) { + var cursor = Model.find().limit(1).sort({ name: 1 }).cursor(); + cursor.next(function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Axl'); + cursor.next(function(error, doc) { + assert.ifError(error); + assert.ok(!doc); + done(); + }); + }); + }); + it('with populate', function(done) { var bandSchema = new Schema({ name: String, From 837dc7c288a330883735126a7dd2f440553c7313 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Jun 2016 11:00:28 -0700 Subject: [PATCH 0660/2240] fix(query): pass correct options to QueryCursor Fix #4266 --- lib/query.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index d294c7a6449..de832782fb5 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2830,7 +2830,10 @@ Query.prototype.stream = util.deprecate(Query.prototype.stream, 'Mongoose: ' + Query.prototype.cursor = function cursor(opts) { this._applyPaths(); this._fields = this._castFields(this._fields); - return new QueryCursor(this, opts); + if (opts) { + this.setOptions(opts); + } + return new QueryCursor(this, this.options); }; // the rest of these are basically to support older Mongoose syntax with mquery From 0c5da971d29c6dc4720d47460fad93e574b0e181 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 27 Jun 2016 07:38:41 -0700 Subject: [PATCH 0661/2240] test(document): repro #4275 --- test/document.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 3d3fa2e732a..b3f1e6ec10c 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2154,6 +2154,27 @@ describe('document', function() { done(); }); }); + + it('handles non-errors', function(done) { + var schema = new Schema({ + name: { type: String, required: true } + }); + + schema.post('save', function(error, doc, next) { + next(new Error('Catch all')); + }); + + schema.post('save', function(error, doc, next) { + next(new Error('Catch all #2')); + }); + + var Model = db.model('gh2284_1', schema); + + Model.create({ name: 'test' }, function(error) { + assert.ifError(error); + done(); + }); + }); }); describe('bug fixes', function() { From e12c6e89afbdd48257760539e42bbadd53dec0e9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 27 Jun 2016 07:39:10 -0700 Subject: [PATCH 0662/2240] fix(document): upgrade to kareem 1.1.2 to fix error handling when no error occurred Fix #4275 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b2a2e13cb04..c748960360f 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "1.5.2", "bson": "~0.4.23", "hooks-fixed": "1.1.0", - "kareem": "1.1.0", + "kareem": "1.1.2", "mongodb": "2.1.18", "mpath": "0.2.1", "mpromise": "0.5.5", From a213b49f594e1667b05ff9a3f51372e71b6a06b4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 27 Jun 2016 08:16:38 -0700 Subject: [PATCH 0663/2240] fix: upgrade to latest kareem for issues with error handling for update Re: #4275 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c748960360f..460338d88ba 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "1.5.2", "bson": "~0.4.23", "hooks-fixed": "1.1.0", - "kareem": "1.1.2", + "kareem": "1.1.3", "mongodb": "2.1.18", "mpath": "0.2.1", "mpromise": "0.5.5", From d1433d71cb7f4dab3220f45a3af2a42dc3a5fb69 Mon Sep 17 00:00:00 2001 From: Grigoriy Chudnov Date: Mon, 27 Jun 2016 18:28:00 +0300 Subject: [PATCH 0664/2240] consider lean option in populate --- lib/querycursor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/querycursor.js b/lib/querycursor.js index 1a08c751c2f..2b9bcadf09e 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -209,7 +209,9 @@ function _next(ctx, callback) { if (err) { return callback(err); } - _create(ctx, doc, pop, callback); + return opts.lean === true ? + callback(null, doc) : + _create(ctx, doc, pop, callback); }); }); } else { From 50de81e719ba0ca7dd24ea6cbf6e9621c709211f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Jun 2016 08:43:14 -0700 Subject: [PATCH 0665/2240] fix(error): use strict mode for version error Fix #4272 --- lib/error/version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/error/version.js b/lib/error/version.js index f38030d1543..e509b9b5fa5 100644 --- a/lib/error/version.js +++ b/lib/error/version.js @@ -1,3 +1,4 @@ +'use strict'; /*! * Module dependencies. @@ -15,7 +16,6 @@ var MongooseError = require('../error.js'); function VersionError(doc) { MongooseError.call(this, 'No matching document found for id "' + doc._id + '"'); - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); this.name = 'VersionError'; } From 4eb1e4cdd942277733986cba4bb62010de5bbda8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Jun 2016 09:04:22 -0700 Subject: [PATCH 0666/2240] docs(populate): fix broken populate docs compilation Fix #4267 --- docs/populate.jade | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/populate.jade b/docs/populate.jade index aca8dd075ca..d3360c88cf1 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -342,11 +342,7 @@ block content * "Vince Neil" and "Nikki Sixx" with "Motley Crue" */ Band.find({}).populate('members').exec(function(error, bands) { - /** - * [ { name: 'Guns N\' Roses', members: [ [Object], [Object] ] }, - * { name: 'Motley Crue', members: [ [Object], [Object] ] } ] - */ - console.log(bands); + /* `bands.members` is now an array of instances of `Person` */ }); h3#next Next Up From 17217852114844eecf529080baa9206bf8acd4ec Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Jun 2016 09:20:51 -0700 Subject: [PATCH 0667/2240] test(populate): add coverage for deep populating virtuals Re: #4261 --- test/model.populate.test.js | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 1825e5a28c4..b90ba198efc 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3945,6 +3945,59 @@ describe('model: populate:', function() { }); }); + it('deep populate (gh-4261)', function(done) { + var PersonSchema = new Schema({ + name: String + }); + + PersonSchema.virtual('blogPosts', { + ref: 'gh4261', + localField: '_id', + foreignField: 'author' + }); + + var BlogPostSchema = new Schema({ + title: String, + author: { type: ObjectId }, + comments: [{ author: { type: ObjectId, ref: 'gh4261' } }] + }); + + var Person = db.model('gh4261', PersonSchema); + var BlogPost = db.model('gh4261_0', BlogPostSchema); + + var people = [ + { name: 'Val' }, + { name: 'Test' } + ]; + + Person.create(people, function(error, people) { + assert.ifError(error); + var post = { + title: 'Test1', + author: people[0]._id, + comments: [{ author: people[1]._id }] + }; + BlogPost.create(post, function(error) { + assert.ifError(error); + Person.findById(people[0]._id). + populate({ + path: 'blogPosts', + model: BlogPost, + populate: { + path: 'comments.author', + model: Person + } + }). + exec(function(error, person) { + assert.ifError(error); + assert.equal(person.blogPosts[0].comments[0].author.name, + 'Test'); + done(); + }); + }); + }); + }); + it('specify model in populate (gh-4264)', function(done) { var PersonSchema = new Schema({ name: String, From a0e8f981fc5bdb348bc23a06f81dc84ea930347f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Jun 2016 09:35:44 -0700 Subject: [PATCH 0668/2240] docs(model): correct link to Document Fix #4250 --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index a45a78a7d20..71944dd0951 100644 --- a/lib/model.js +++ b/lib/model.js @@ -29,7 +29,7 @@ var VERSION_WHERE = 1, * Provides the interface to MongoDB collections as well as creates document instances. * * @param {Object} doc values with which to create the document - * @inherits Document + * @inherits Document http://mongoosejs.com/docs/api.html#document-js * @event `error`: If listening to this event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model. * @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event. * @event `index-single-start`: Emitted when an individual index starts within `Model#ensureIndexes`. The fields and options being used to build the index are also passed with the event. From f2a362cadbd1b49731268379a1072cfc3f27b1b9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Jun 2016 09:47:22 -0700 Subject: [PATCH 0669/2240] docs(populate): correct path for refPath populate Fix #4240 --- docs/populate.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/populate.jade b/docs/populate.jade index d3360c88cf1..2d497039a85 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -302,7 +302,7 @@ block content // } User. findOne({ name: 'Axl Rose' }). - populate('connections'). + populate('connections.item'). exec(function(error, doc) { // doc.connections[0].item is a User doc // doc.connections[1].item is an Organization doc From fbe04d9a8446dce3351c18f94190a71a68798936 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Jun 2016 12:11:49 -0700 Subject: [PATCH 0670/2240] test(document): repro #4064 --- package.json | 3 ++- test/document.test.js | 43 +++++++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 460338d88ba..8530b4cfe44 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,8 @@ "q": "1.4.1", "tbd": "0.6.4", "uglify-js": "2.6.1", - "underscore": "1.8.3" + "underscore": "1.8.3", + "validator": "5.4.0" }, "browserDependencies": { "browserify": "4.1.10", diff --git a/test/document.test.js b/test/document.test.js index b3f1e6ec10c..2a1a7882c2f 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2,20 +2,21 @@ * Module dependencies. */ -var start = require('./common'), - mongoose = start.mongoose, - assert = require('power-assert'), - random = require('../lib/utils').random, - Schema = mongoose.Schema, - ObjectId = Schema.ObjectId, - Document = require('../lib/document'), - DocumentObjectId = mongoose.Types.ObjectId, - SchemaType = mongoose.SchemaType, - ValidatorError = SchemaType.ValidatorError, - ValidationError = mongoose.Document.ValidationError, - MongooseError = mongoose.Error, - EmbeddedDocument = require('../lib/types/embedded'), - Query = require('../lib/query'); +var start = require('./common'); +var mongoose = start.mongoose; +var assert = require('power-assert'); +var random = require('../lib/utils').random; +var Schema = mongoose.Schema; +var ObjectId = Schema.ObjectId; +var Document = require('../lib/document'); +var DocumentObjectId = mongoose.Types.ObjectId; +var SchemaType = mongoose.SchemaType; +var ValidatorError = SchemaType.ValidatorError; +var ValidationError = mongoose.Document.ValidationError; +var MongooseError = mongoose.Error; +var EmbeddedDocument = require('../lib/types/embedded'); +var Query = require('../lib/query'); +var validator = require('validator'); var _ = require('lodash'); @@ -3015,6 +3016,20 @@ describe('document', function() { }); }); + it('using validator.isEmail as a validator (gh-4064) (gh-4084)', function(done) { + var schema = new Schema({ + email: { type: String, validate: validator.isEmail } + }); + + var MyModel = db.model('gh4064', schema); + + MyModel.create({ email: 'invalid' }, function(error) { + assert.ok(error); + assert.ok(error.errors['email']); + done(); + }); + }); + it('setting path to empty object works (gh-4218)', function(done) { var schema = new Schema({ object: { From 69b6b71d6454e2755d8e92b8d2a5fdee2638d97b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Jun 2016 12:11:53 -0700 Subject: [PATCH 0671/2240] fix(document): support validator.isEmail as validator Fix #4064 --- lib/schematype.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/schematype.js b/lib/schematype.js index 252aa201a9d..484f4bd9471 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -722,12 +722,18 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { return; } if (validator.length === 2) { - validator.call(scope, value, function(ok, customMsg) { + var returnVal = validator.call(scope, value, function(ok, customMsg) { + if (typeof returnVal === 'boolean') { + return; + } if (customMsg) { validatorProperties.message = customMsg; } validate(ok, validatorProperties); }); + if (typeof returnVal === 'boolean') { + validate(returnVal, validatorProperties); + } } else { validate(validator.call(scope, value), validatorProperties); } From d2740d32392eb2c4dd5e08f1fd567e9872aa8134 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Jun 2016 17:11:42 -0700 Subject: [PATCH 0672/2240] chore: release 4.5.3 --- History.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0575b09059c..895d9927f2b 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,17 @@ +4.5.3 / 2016-06-30 +================== + * fix(query): pass correct options to QueryCursor #4277 #4266 + * fix(querycursor): handle lean option correctly #4276 [gchudnov](https://github.com/gchudnov) + * fix(document): fix error handling when no error occurred #4275 + * fix(error): use strict mode for version error #4272 + * docs(populate): fix crashing compilation for populate.jade #4267 + * fix(populate): support `justOne` option for populate virtuals #4263 + * fix(populate): ensure model param gets used for populate virtuals #4261 #4243 + * fix(querycursor): add ability to properly close the cursor #4258 + * docs(model): correct link to Document #4250 + * docs(populate): correct path for refPath populate #4240 + * fix(document): support validator.isEmail as validator #4064 + 4.5.2 / 2016-06-24 ================== * fix(connection): add checks for collection presence for `onOpen` and `onClose` #4259 [nodkz](https://github.com/nodkz) diff --git a/package.json b/package.json index 8530b4cfe44..fb1433ff183 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.3-pre", + "version": "4.5.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From f29fcef376cdbce773e69aea9e8c1d943eb34320 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 1 Jul 2016 08:38:25 -0700 Subject: [PATCH 0673/2240] chore: now working on 4.5.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fb1433ff183..38161b41659 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.3", + "version": "4.5.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From f84e8068525c5ea3566796ec356597380220c112 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Jul 2016 20:05:46 -0700 Subject: [PATCH 0674/2240] docs(document): add return statements to transform examples Fix #1963 --- lib/document.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/document.js b/lib/document.js index 65842796aef..9b32566b2b1 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2093,6 +2093,7 @@ Document.prototype.$toObject = function(options, json) { * schema.options.toObject.transform = function (doc, ret, options) { * // remove the _id of every document before returning the result * delete ret._id; + * return ret; * } * * // without the transformation in the schema @@ -2135,6 +2136,7 @@ Document.prototype.$toObject = function(options, json) { * delete ret[prop]; * }); * } + * return ret; * } * * var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }); From 5c531dbda8a175c8c228ac160bb73cc1b0ba8427 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Jul 2016 20:35:50 -0700 Subject: [PATCH 0675/2240] test(types): repro #4281 --- test/model.findOneAndUpdate.test.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index b7d27f0b1ed..fc202cfa410 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1586,5 +1586,29 @@ describe('model: findByIdAndUpdate:', function() { done(); }); }); + + it('handles setting single embedded docs to null (gh-4281)', function(done) { + var foodSchema = new mongoose.Schema({ + name: { type: String, default: 'Bacon' } + }); + + var breakfastSchema = new mongoose.Schema({ + main: foodSchema, + for: String + }); + + var TestModel = db.model('gh4281', breakfastSchema); + var options = { upsert: true, new: true }; + var update = { $set: { main: null, for: 'Val' } }; + + TestModel.findOneAndUpdate({}, update, options). + exec(function(error, doc) { + assert.ifError(error); + assert.ok(doc); + assert.equal(doc.main, null); + + done(); + }); + }); }); }); From fc35912f0ab41e97aeefe1e64cb6a80c3f8e48e3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Jul 2016 20:36:04 -0700 Subject: [PATCH 0676/2240] fix(types): allow setting single nested doc to null Fix #4281 --- lib/schema/embedded.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index b817d2b1aa3..fd496af2feb 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -123,6 +123,9 @@ Embedded.prototype.castForQuery = function($conditional, val) { return handler.call(this, val); } val = $conditional; + if (val == null) { + return val; + } return new this.caster(val).toObject({virtuals: false}); }; From d485c4c84aa42715b0c3d944db0f40146a39c154 Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Sat, 2 Jul 2016 21:43:38 -0700 Subject: [PATCH 0677/2240] Added support for modern node versions --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 05a3e8dd9ef..b9348aa0a95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: node_js sudo: false node_js: + - "6" - "5" - "4" - "0.12" From abeb9478a3c5e13729b020887fed2366862e7fab Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Jul 2016 13:18:38 -0700 Subject: [PATCH 0678/2240] docs: improve waffle.io logo --- index.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.jade b/index.jade index 26bbc91b0f2..796b3c59fa3 100644 --- a/index.jade +++ b/index.jade @@ -101,7 +101,7 @@ html(lang='en') img(src="http://upload.wikimedia.org/wikipedia/en/3/3e/Trello_Logo.png", alt="Trello") li a(href="http://waffle.io", alt="Waffle.io") - img(src="https://waffle.io/resources/images/waffle-yellow-on-blue.png", alt="Waffle.io") + img(src="http://i.imgur.com/nqzTvft.png", alt="Waffle.io") li a(href="http://storify.com/", alt="Storify") img(src="docs/images/apps/h_storify.jpg", alt="Storify") From 697eea6f5e700b65400fdaf5e405d697d65bf229 Mon Sep 17 00:00:00 2001 From: Simon Xiong Date: Sun, 3 Jul 2016 21:09:23 -0400 Subject: [PATCH 0679/2240] Small doc fix for Connection#global Connection#global as shown in the docs is undefined Should be Connection#config --- lib/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index 28858160be9..154aeb5b0f5 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -138,7 +138,7 @@ Connection.prototype.db; /** * A hash of the global options that are associated with this connection * - * @property global + * @property config */ Connection.prototype.config; From 9163860a9ba0eb5d5d82e35d4b4f323b71c6572b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Jul 2016 18:06:56 -0700 Subject: [PATCH 0680/2240] test(query): repro #4283 --- package.json | 1 + test/model.update.test.js | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/package.json b/package.json index 38161b41659..3e0a91cfb4e 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "markdown": "0.3.1", "marked": "0.3.5", "mocha": "2.3.4", + "mongoose-long": "0.1.0", "node-static": "0.7.7", "power-assert": "1.2.0", "q": "1.4.1", diff --git a/test/model.update.test.js b/test/model.update.test.js index 4f028d2f0e6..fec8f4f3d80 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1836,5 +1836,25 @@ describe('model: update:', function() { done(); }); }); + + it('update handles casting with mongoose-long (gh-4283)', function(done) { + require('mongoose-long')(mongoose); + + var Model = db.model('gh4283', { + number: { type: mongoose.Types.Long } + }); + + Model.create({ number: mongoose.mongo.Long.fromString('0') }, function(error) { + assert.ifError(error); + Model.update({}, { $inc: { number: mongoose.mongo.Long.fromString('2147483648') } }, function(error) { + assert.ifError(error); + Model.findOne({ number: { $type: 18 } }, function(error, doc) { + assert.ifError(error); + assert.ok(doc); + done(); + }); + }); + }); + }); }); }); From c4aed81422eee7c264b7c6968fb8fd31f21ada7d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Jul 2016 18:12:38 -0700 Subject: [PATCH 0681/2240] fix(query): dont cast $inc to number if type is long Fix #4283 --- lib/query.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/lib/query.js b/lib/query.js index de832782fb5..5ba8422b784 100644 --- a/lib/query.js +++ b/lib/query.js @@ -935,6 +935,45 @@ Query.prototype.getUpdate = function() { * @receiver Query */ +Query.prototype._updateForExec = function() { + var update = utils.clone(this._update, { retainKeyOrder: true }); + var ops = Object.keys(update); + var i = ops.length; + var ret = {}; + + while (i--) { + var op = ops[i]; + + if (this.options.overwrite) { + ret[op] = update[op]; + continue; + } + + if ('$' !== op[0]) { + // fix up $set sugar + if (!ret.$set) { + if (update.$set) { + ret.$set = update.$set; + } else { + ret.$set = {}; + } + } + ret.$set[op] = update[op]; + ops.splice(i, 1); + if (!~ops.indexOf('$set')) ops.push('$set'); + } else if ('$set' === op) { + if (!ret.$set) { + ret[op] = update[op]; + } + } else { + ret[op] = update[op]; + } + } + + this._compiledUpdate = ret; + return ret; +}; + /** * Makes sure _path is set. * @@ -2477,6 +2516,9 @@ Query.prototype._castUpdateVal = function _castUpdateVal(schema, val, op, $condi } if (op in numberOps) { + if (op === '$inc') { + return schema.castForQuery(val); + } return Number(val); } if (op === '$currentDate') { From 4a862a097de0cd103e49c42404eeb5db31a36237 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 3 Jul 2016 23:29:46 -0400 Subject: [PATCH 0682/2240] fixes document.validate(optional, optional) to (optional, callback) --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 9b32566b2b1..0abfd575b28 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1130,7 +1130,7 @@ Document.prototype.isSelected = function isSelected(path) { * }); * * @param {Object} optional options internal options - * @param {Function} optional callback called after validation completes, passing an error if one occurred + * @param {Function} callback optional callback called after validation completes, passing an error if one occurred * @return {Promise} Promise * @api public */ From 3d161ecabf6a8706518696225712679efefd8cba Mon Sep 17 00:00:00 2001 From: rcatoio Date: Mon, 4 Jul 2016 08:30:20 +0200 Subject: [PATCH 0683/2240] increase mongodb native client version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3e0a91cfb4e..5d06222e88a 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.23", "hooks-fixed": "1.1.0", "kareem": "1.1.3", - "mongodb": "2.1.18", + "mongodb": "2.1.21", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.11.0", From c19bf7cd6d5ff194f17cbde4fff95b285b12d698 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 4 Jul 2016 12:40:46 -0400 Subject: [PATCH 0684/2240] docs(schematype): add missing bool param to .text() --- lib/schematype.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schematype.js b/lib/schematype.js index 484f4bd9471..081f421b440 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -166,7 +166,7 @@ SchemaType.prototype.unique = function(bool) { * * var s = new Schema({name : {type: String, text : true }) * Schema.path('name').index({text : true}); - * @param bool + * @param {Boolean} bool * @return {SchemaType} this * @api public */ From 3bd7f706606ba647408cb34b31ace59372314c44 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 4 Jul 2016 13:22:46 -0400 Subject: [PATCH 0685/2240] docs(query): remove duplicate .then() method --- lib/query.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/query.js b/lib/query.js index 5ba8422b784..f6defba079a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3256,15 +3256,6 @@ Query.prototype.centerSphere = function() { * @api public */ -/** - * Executes this query and returns a promise - * - * @method then - * @memberOf Query - * @return {Promise} - * @api public - */ - /** * Determines if inclusive field selection has been made. * From d151cf0b440725a32edc8b8dc8b5891dd0dc1ae9 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 4 Jul 2016 14:28:03 -0400 Subject: [PATCH 0686/2240] docs(model): move discriminator options inside discriminator method --- lib/model.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/model.js b/lib/model.js index 71944dd0951..bc68156bc23 100644 --- a/lib/model.js +++ b/lib/model.js @@ -776,14 +776,14 @@ Model.prototype.model = function model(name) { * @api public */ -var CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = { - toJSON: true, - toObject: true, - _id: true, - id: true -}; - Model.discriminator = function discriminator(name, schema) { + var CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = { + toJSON: true, + toObject: true, + _id: true, + id: true + }; + if (!(schema && schema.instanceOfSchema)) { throw new Error('You must pass a valid discriminator Schema'); } From 071512078d8a1dc5076e9ca756d8ca0a8258aaba Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 4 Jul 2016 14:42:56 -0400 Subject: [PATCH 0687/2240] docs(model) remove private function shouldSkipVersioning from public docs --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index bc68156bc23..b1f8defbebb 100644 --- a/lib/model.js +++ b/lib/model.js @@ -283,7 +283,7 @@ Model.prototype.save = function(options, fn) { return this.$__save(options, fn); }; -/** +/*! * Determines whether versioning should be skipped for the given path * * @param {Document} self From 9ebfe53006a6848e419ad9cb841350489eed37c7 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 6 Jul 2016 11:38:16 -0400 Subject: [PATCH 0688/2240] docs(error/message.js) messages is defined as static on MongooseError --- lib/error/messages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/error/messages.js b/lib/error/messages.js index f825a4f2749..88ddf6e89f8 100644 --- a/lib/error/messages.js +++ b/lib/error/messages.js @@ -16,7 +16,7 @@ * * Click the "show code" link below to see all defaults. * - * @property messages + * @static messages * @receiver MongooseError * @api public */ From 2827ee8360c9f5f14e6bdf0a0c240c2f5488e9de Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 6 Jul 2016 17:00:19 -0400 Subject: [PATCH 0689/2240] docs(types/buffer) changes return type of copy() to Number --- lib/types/buffer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/buffer.js b/lib/types/buffer.js index 0c7bbe32ed5..8be67c80a5e 100644 --- a/lib/types/buffer.js +++ b/lib/types/buffer.js @@ -131,7 +131,7 @@ MongooseBuffer.mixin = { * * `Buffer#copy` does not mark `target` as modified so you must copy from a `MongooseBuffer` for it to work as expected. This is a work around since `copy` modifies the target, not this. * - * @return {MongooseBuffer} + * @return {Number} The number of bytes copied. * @param {Buffer} target * @method copy * @receiver MongooseBuffer From 7f5ffadbced45acaea619e4a4732a582a0ace54d Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 7 Jul 2016 11:50:36 -0400 Subject: [PATCH 0690/2240] docs(schema) adds options param to constructor --- lib/schema.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/schema.js b/lib/schema.js index 4f47e70ebd3..794bc892c84 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -58,6 +58,7 @@ var IS_KAREEM_HOOK = { * _When nesting schemas, (`children` in the example above), always declare the child schema first before passing it into its parent._ * * @param {Object} definition + * @param {Object} [options] * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter * @event `init`: Emitted after the schema is compiled into a `Model`. * @api public From cd6238efb42b2c85d3bd14332b2664ae5e65a810 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 7 Jul 2016 16:41:47 -0400 Subject: [PATCH 0691/2240] doc(schema/buffer) fixes params for SchemaBuffer constructor --- lib/schema/buffer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js index 1dda3c8d1a2..035f1273df4 100644 --- a/lib/schema/buffer.js +++ b/lib/schema/buffer.js @@ -16,7 +16,7 @@ var Document; * Buffer SchemaType constructor * * @param {String} key - * @param {SchemaType} cast + * @param {Object} options * @inherits SchemaType * @api public */ From e24f3f077b7f6c864a6169a2e1f9eb3f37fb50a1 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 7 Jul 2016 18:32:18 -0400 Subject: [PATCH 0692/2240] doc(schema) removes private variable warnings from public api --- lib/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 794bc892c84..310639703f2 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -434,7 +434,7 @@ reserved.validate = // hooks.js reserved._pres = reserved._posts = 1; -/** +/*! * Document keys to print warnings for */ From 203fc72facec604d8c61e7156774a19f876e1b58 Mon Sep 17 00:00:00 2001 From: rcatoio Date: Fri, 8 Jul 2016 12:13:33 +0200 Subject: [PATCH 0693/2240] fix embededDocument remove documentation, and set options as an optionnal param --- lib/types/embedded.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 8aed57dc12c..5049ff9e9a9 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -116,11 +116,16 @@ function registerRemoveListener(sub) { /** * Removes the subdocument from its parent array. * + * @param {Object} [options] * @param {Function} [fn] * @api public */ EmbeddedDocument.prototype.remove = function(options, fn) { + if ( typeof options === 'function' && !fn ) { + fn = options; + options = undefined; + } if (!this.__parentArray || (options && options.noop)) { fn && fn(null); return this; From dd7b82ab906c4515a5780afdf68d27fa54852a52 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Jul 2016 06:59:30 -0700 Subject: [PATCH 0694/2240] test(populate): repro #4284 --- test/model.populate.test.js | 127 +++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 2 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index b90ba198efc..e27cf19c7f4 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -2012,7 +2012,7 @@ describe('model: populate:', function() { user.save(next); function next(err) { - assert.strictEqual(null, err); + assert.strictEqual(err, null); if (--pending) { return; } @@ -2035,7 +2035,7 @@ describe('model: populate:', function() { comment.str = 'my string'; comment.save(function(err, comment) { - assert.strictEqual(null, err); + assert.strictEqual(err, null); Comment .findById(comment.id) @@ -3708,6 +3708,32 @@ describe('model: populate:', function() { }); }); + it('empty array (gh-4284)', function(done) { + var PersonSchema = new Schema({ + name: { type: String } + }); + + var BandSchema = new Schema({ + people: [{ + type: mongoose.Schema.Types.ObjectId + }] + }); + + var Person = db.model('gh4284_b', PersonSchema); + var Band = db.model('gh4284_b0', BandSchema); + + var band = { people: [new mongoose.Types.ObjectId()] }; + Band.create(band, function(error, band) { + assert.ifError(error); + var opts = { path: 'people', model: Person }; + Band.findById(band).populate(opts).exec(function(error, band) { + assert.ifError(error); + assert.equal(band.people.length, 0); + done(); + }); + }); + }); + describe('populate virtuals (gh-2562)', function() { it('basic populate virtuals', function(done) { var PersonSchema = new Schema({ @@ -3945,6 +3971,103 @@ describe('model: populate:', function() { }); }); + it('with no results and justOne (gh-4284)', function(done) { + var PersonSchema = new Schema({ + name: String, + authored: [Number] + }); + + var BlogPostSchema = new Schema({ + _id: Number, + title: String + }); + BlogPostSchema.virtual('author', { + ref: 'gh4284', + localField: '_id', + foreignField: 'authored', + justOne: true + }); + + var Person = db.model('gh4284', PersonSchema); + var BlogPost = db.model('gh4284_0', BlogPostSchema); + + var blogPosts = [ + { _id: 0, title: 'Bacon is Great' }, + { _id: 1, title: 'Bacon is OK' } + ]; + var people = [ + { name: 'Val', authored: [0] } + ]; + + Person.create(people, function(error) { + assert.ifError(error); + BlogPost.create(blogPosts, function(error) { + assert.ifError(error); + BlogPost. + find({}). + sort({ title: 1 }). + populate('author'). + exec(function(error, posts) { + assert.ifError(error); + assert.equal(posts[0].author.name, 'Val'); + assert.strictEqual(posts[1].author, null); + done(); + }); + }); + }); + }); + + it('with no results (gh-4284)', function(done) { + var PersonSchema = new Schema({ + name: String, + authored: [Number] + }); + + var BlogPostSchema = new Schema({ + _id: Number, + title: String + }); + BlogPostSchema.virtual('authors', { + ref: 'gh4284_a', + localField: '_id', + foreignField: 'authored' + }); + + var Person = db.model('gh4284_a', PersonSchema); + var BlogPost = db.model('gh4284_a0', BlogPostSchema); + + var blogPosts = [ + { _id: 0, title: 'Bacon is Great' }, + { _id: 1, title: 'Bacon is OK' }, + { _id: 2, title: 'Bacon is not great' } + ]; + var people = [ + { name: 'Val', authored: [0] }, + { name: 'Test', authored: [0, 1] } + ]; + + Person.create(people, function(error) { + assert.ifError(error); + BlogPost.create(blogPosts, function(error) { + assert.ifError(error); + BlogPost. + find({}). + sort({ _id: 1 }). + populate('authors'). + exec(function(error, posts) { + assert.ifError(error); + assert.equal(posts[0].authors.length, 2); + assert.equal(posts[0].authors[0].name, 'Val'); + assert.equal(posts[0].authors[1].name, 'Test'); + assert.equal(posts[1].authors.length, 1); + assert.equal(posts[1].authors[0].name, 'Test'); + assert.equal(posts[2].authors.length, 0); + done(); + }); + }); + }); + }); + it('deep populate (gh-4261)', function(done) { var PersonSchema = new Schema({ name: String From 1eeddb567dccea704f64431a7e95b1535eba8b58 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Jul 2016 07:01:19 -0700 Subject: [PATCH 0695/2240] fix(populate): handle empty results for populate virtuals properly Fix #4284 --- lib/model.js | 50 +++++++++++++++++++++++++++++++++++++------------- lib/schema.js | 4 ++-- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/lib/model.js b/lib/model.js index 71944dd0951..66f52e45bc7 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2762,6 +2762,7 @@ function populate(model, docs, options, callback) { if (err) return callback(err); var options = mod.options; + var _val; var lean = options.options && options.options.lean, len = vals.length, rawOrder = {}, rawDocs = {}, key, val; @@ -2771,22 +2772,45 @@ function populate(model, docs, options, callback) { // the query result. for (var i = 0; i < len; i++) { val = vals[i]; - key = String(utils.getValue(mod.foreignField, val)); - if (rawDocs[key]) { - if (Array.isArray(rawDocs[key])) { - rawDocs[key].push(val); - rawOrder[key].push(i); + if (val) { + _val = utils.getValue(mod.foreignField, val); + if (Array.isArray(_val)) { + var _valLength = _val.length; + for (var j = 0; j < _valLength; ++j) { + key = String(_val[j]); + if (rawDocs[key]) { + if (Array.isArray(rawDocs[key])) { + rawDocs[key].push(val); + rawOrder[key].push(i); + } else { + rawDocs[key] = [rawDocs[key], val]; + rawOrder[key] = [rawOrder[key], i]; + } + } else { + rawDocs[key] = val; + rawOrder[key] = i; + } + } } else { - rawDocs[key] = [rawDocs[key], val]; - rawOrder[key] = [rawOrder[key], i]; + key = String(utils.getValue(mod.foreignField, val)); + if (rawDocs[key]) { + if (Array.isArray(rawDocs[key])) { + rawDocs[key].push(val); + rawOrder[key].push(i); + } else { + rawDocs[key] = [rawDocs[key], val]; + rawOrder[key] = [rawOrder[key], i]; + } + } else { + rawDocs[key] = val; + rawOrder[key] = i; + } + } + // flag each as result of population + if (!lean) { + val.$__.wasPopulated = true; } - } else { - rawDocs[key] = val; - rawOrder[key] = i; } - - // flag each as result of population - if (!lean) val.$__.wasPopulated = true; } assignVals({ diff --git a/lib/schema.js b/lib/schema.js index 4f47e70ebd3..ffd89353120 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1270,7 +1270,7 @@ Schema.prototype.virtual = function(name, options) { } this.pre('init', function(next, obj) { - if (obj[name]) { + if (name in obj) { if (!this.$$populatedVirtuals) { this.$$populatedVirtuals = {}; } @@ -1280,7 +1280,7 @@ Schema.prototype.virtual = function(name, options) { } else { this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? obj[name] : - [obj[name]]; + obj[name] == null ? [] : [obj[name]]; } delete obj[name]; From b1d8303a4ca67f9eae215b3993722ac119385c3c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Jul 2016 07:17:31 -0700 Subject: [PATCH 0696/2240] test(populate): repro #4288 --- test/model.populate.test.js | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index e27cf19c7f4..0409e745efc 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4121,6 +4121,51 @@ describe('model: populate:', function() { }); }); + it('lean with single result and no justOne (gh-4288)', function(done) { + var PersonSchema = new Schema({ + name: String, + authored: [Number] + }); + + var BlogPostSchema = new Schema({ + _id: Number, + title: String + }); + BlogPostSchema.virtual('authors', { + ref: true, + localField: '_id', + foreignField: 'authored', + justOne: false + }); + + var Person = db.model('gh4288', PersonSchema); + var BlogPost = db.model('gh4288_0', BlogPostSchema); + + var blogPosts = [ + { _id: 0, title: 'Bacon is Great' } + ]; + var people = [ + { name: 'Val', authored: [0] } + ]; + + Person.create(people, function(error) { + assert.ifError(error); + BlogPost.create(blogPosts, function(error) { + assert.ifError(error); + BlogPost. + findOne({}). + lean(). + populate({ path: 'authors', model: Person }). + exec(function(error, post) { + assert.ifError(error); + assert.equal(post.authors.length, 1); + assert.equal(post.authors[0].name, 'Val'); + done(); + }); + }); + }); + }); + it('specify model in populate (gh-4264)', function(done) { var PersonSchema = new Schema({ name: String, From ccab73e71e5b3fd43ef7886ab2f953a11ca50e22 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Jul 2016 07:28:35 -0700 Subject: [PATCH 0697/2240] fix(populate): convert single result to array for virtual populate because of lean Fix #4288 --- lib/model.js | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/model.js b/lib/model.js index 66f52e45bc7..834d898e846 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2822,7 +2822,9 @@ function populate(model, docs, options, callback) { rawOrder: rawOrder, docs: mod.docs, path: options.path, - options: assignmentOpts + options: assignmentOpts, + justOne: mod.justOne, + isVirtual: mod.isVirtual }); } } @@ -2854,6 +2856,10 @@ function assignVals(o) { !o.originalModel.schema.virtuals[o.path]) { continue; } + + if (o.isVirtual && !o.justOne && !Array.isArray(rawIds[i])) { + rawIds[i] = [rawIds[i]]; + } utils.setValue(o.path, rawIds[i], docs[i], setValue); } } @@ -2949,6 +2955,7 @@ function getModelsMapForPopulate(model, docs, options) { schema, refPath, Model, currentOptions, modelNames, modelName, discriminatorKey, modelForFindSchema; var originalOptions = utils.clone(options); + var isVirtual = false; schema = model._getSchema(options.path); @@ -2988,11 +2995,14 @@ function getModelsMapForPopulate(model, docs, options) { } var virtual = modelForCurrentDoc.schema.virtuals[options.path]; - modelNames = [ - schemaForCurrentDoc && schemaForCurrentDoc.options && schemaForCurrentDoc.options.ref // declared in schema - || virtual && virtual.options && virtual.options.ref - || model.modelName // an ad-hoc structure - ]; + if (schemaForCurrentDoc && schemaForCurrentDoc.options && schemaForCurrentDoc.options.ref) { + modelNames = [schemaForCurrentDoc.options.ref]; + } else if (virtual && virtual.options && virtual.options.ref) { + modelNames = [virtual && virtual.options && virtual.options.ref]; + isVirtual = true; + } else { + modelNames = [model.modelName]; + } } else { modelNames = [modelNameFromQuery]; // query options } @@ -3014,6 +3024,9 @@ function getModelsMapForPopulate(model, docs, options) { virtual.options.foreignField : '_id'; var justOne = virtual && virtual.options && virtual.options.justOne; + if (virtual && virtual.options && virtual.options.ref) { + isVirtual = true; + } var ret = convertTo_id(utils.getValue(localField, doc)); var id = String(utils.getValue(foreignField, doc)); @@ -3048,7 +3061,8 @@ function getModelsMapForPopulate(model, docs, options) { // Assume only 1 localField + foreignField localField: localField, foreignField: foreignField, - justOne: justOne + justOne: justOne, + isVirtual: isVirtual }; map.push(available[modelName]); } else { From 462a80d97ea6662b3367f759bc3b88ca61018581 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 8 Jul 2016 11:27:31 -0400 Subject: [PATCH 0698/2240] doc(schema) changed schema.static() params to match schema.method() --- lib/schema.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 310639703f2..64db5ebc087 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1034,8 +1034,8 @@ Schema.prototype.method = function(name, fn) { * * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics. * - * @param {String} name - * @param {Function} fn + * @param {String|Object} name + * @param {Function} [fn] * @api public */ From a61071e51b6a011199048fbfe867676320e21045 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Jul 2016 12:25:19 -0700 Subject: [PATCH 0699/2240] test(populate): repro #4278 --- test/model.populate.test.js | 58 ++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 0409e745efc..cf7734aa51e 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4068,7 +4068,7 @@ describe('model: populate:', function() { }); }); - it('deep populate (gh-4261)', function(done) { + it('deep populate virtual -> conventional (gh-4261)', function(done) { var PersonSchema = new Schema({ name: String }); @@ -4121,6 +4121,62 @@ describe('model: populate:', function() { }); }); + it('deep populate virtual -> virtual (gh-4278)', function(done) { + var ASchema = new Schema({ + name: String + }); + ASchema.virtual('bs', { + ref: 'gh4278_1', + localField: '_id', + foreignField: 'a' + }) + + var BSchema = new Schema({ + a: mongoose.Schema.Types.ObjectId, + name: String + }); + BSchema.virtual('cs', { + ref: 'gh4278_2', + localField: '_id', + foreignField: 'b' + }) + + var CSchema = new Schema({ + b: mongoose.Schema.Types.ObjectId, + name: String + }); + + var A = db.model('gh4278_0', ASchema); + var B = db.model('gh4278_1', BSchema); + var C = db.model('gh4278_2', CSchema); + + A.create({ name: 'A1' }, function(error, a) { + assert.ifError(error); + B.create({ name: 'B1', a: a._id }, function(error, b) { + assert.ifError(error); + C.create({ name: 'C1', b: b._id }, function(error, c) { + assert.ifError(error); + var options = { + path: 'bs', + populate: { + path: 'cs' + } + }; + A.findById(a).populate(options).exec(function(error, res) { + assert.ifError(error); + console.log(require('util').inspect(res.toObject({ virtuals: true }), { depth: 10, colors: true })) + assert.equal(res.bs.length, 1); + assert.equal(res.bs[0].name, 'B1'); + console.log('FT', res.bs[0]); + assert.equal(res.bs[0].cs.length, 1); + assert.equal(res.bs[0].cs[0].name, 'C1'); + done(); + }); + }); + }); + }); + }); + it('lean with single result and no justOne (gh-4288)', function(done) { var PersonSchema = new Schema({ name: String, From 76ea42508b62000c7a8e92b4b021de926c8f2218 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Jul 2016 12:41:28 -0700 Subject: [PATCH 0700/2240] fix(populate): handle deeply nested virtual populate The `subPopulate()` function was proving to be a weak abstraction, primarily because it created a strange ordering for initializing populated docs. For A -> B -> C, it would initialize B -> C -> A (as opposed to C -> B -> A) because it treated top-level populate differently from sub populates. This caused deeply nested virtual population to fail, because 'B' would not know about 'C' when getting initialized. Fix #4278 --- lib/model.js | 94 +++++-------------------------------- test/model.populate.test.js | 22 ++++----- 2 files changed, 24 insertions(+), 92 deletions(-) diff --git a/lib/model.js b/lib/model.js index 834d898e846..4b33e7cb935 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2571,7 +2571,7 @@ function _populate(model, docs, paths, cache, callback) { var path; while (i--) { path = paths[i]; - populate(model, docs, path, subPopulate.call(model, docs, path, cache, next)); + populate(model, docs, path, next); } function next(err) { @@ -2585,82 +2585,6 @@ function _populate(model, docs, paths, cache, callback) { } } -/*! - * Populates deeply if `populate` option is present. - * - * @param {Document|Array} docs - * @param {Object} options - * @param {Function} cb - * @return {Function} - * @api private - */ -function subPopulate(docs, options, cache, callback) { - var _this = this; - var prefix = options.path + '.'; - var pop = options.populate; - - if (!pop) { - return callback; - } - - // normalize as array - if (!Array.isArray(pop)) { - pop = [pop]; - } - - return function(err) { - var pending = pop.length; - - function next(err) { - if (err) return callback(err); - if (--pending) return; - callback(); - } - - if (err || !pending) { - return callback(err); - } - - pop.forEach(function(subOptions) { - subOptions = utils.clone(subOptions); - // path needs parent's path prefixed to it - if (!subOptions._originalPath) { - subOptions._originalPath = subOptions.path; - subOptions.path = prefix + subOptions.path; - } - - var schema = cache[prefix.substr(0, prefix.length - 1)] || - _this.schema._getSchema(prefix); - var subSchema; - if (typeof subOptions.model === 'string') { - subOptions.model = _this.model(subOptions.model); - } else if (schema && schema.caster && schema.caster.options && - schema.caster.options.ref) { - subSchema = _this.model(schema.caster.options.ref).schema. - _getSchema(subOptions._originalPath); - cache[subOptions.path] = subSchema; - if (subSchema && subSchema.options && subSchema.options.ref) { - subOptions.model = _this.model(subSchema.options.ref); - } else if (subSchema && subSchema.caster && subSchema.caster.options && - subSchema.caster.options.ref) { - subOptions.model = _this.model(subSchema.caster.options.ref); - } - } else if (schema && schema.options && schema.options.ref) { - subSchema = _this.model(schema.options.ref).schema. - _getSchema(subOptions._originalPath); - if (subSchema && subSchema.options && subSchema.options.ref) { - subOptions.model = _this.model(subSchema.options.ref); - } else if (subSchema && subSchema.caster && subSchema.caster.options && - subSchema.caster.options.ref) { - subOptions.model = _this.model(subSchema.caster.options.ref); - } - } - _populate(subOptions.model || _this, docs, utils.populate(subOptions), - cache, next); - }); - }; -} - /*! * Populates `docs` */ @@ -2736,12 +2660,20 @@ function populate(model, docs, options, callback) { mod.options.options.limit = mod.options.options.limit * ids.length; } + var subPopulate = mod.options.populate; + var query; if (mod.justOne) { - mod.Model.findOne(match, select, mod.options.options, - next.bind(this, mod, assignmentOpts)); + query = mod.Model.findOne(match, select, mod.options.options); + if (subPopulate) { + query.populate(subPopulate); + } + query.exec(next.bind(this, mod, assignmentOpts)); } else { - mod.Model.find(match, select, mod.options.options, - next.bind(this, mod, assignmentOpts)); + query = mod.Model.find(match, select, mod.options.options); + if (subPopulate) { + query.populate(subPopulate); + } + query.exec(next.bind(this, mod, assignmentOpts)); } } diff --git a/test/model.populate.test.js b/test/model.populate.test.js index cf7734aa51e..36370d66f1f 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -400,16 +400,16 @@ describe('model: populate:', function() { }, function(err, post) { assert.ifError(err); - var origFind = User.find; + var origExec = User.Query.prototype.exec; // mock an error - User.find = function() { + User.Query.prototype.exec = function() { var args = Array.prototype.map.call(arguments, function(arg) { return typeof arg === 'function' ? function() { arg(new Error('woot')); } : arg; }); - return origFind.apply(this, args); + return origExec.apply(this, args); }; BlogPost @@ -419,6 +419,7 @@ describe('model: populate:', function() { db.close(); assert.ok(err instanceof Error); assert.equal(err.message, 'woot'); + User.Query.prototype.exec = origExec; done(); }); }); @@ -780,14 +781,14 @@ describe('model: populate:', function() { assert.ifError(err); // mock an error - var origFind = User.find; - User.find = function() { + var origExec = User.Query.prototype.exec; + User.Query.prototype.exec = function() { var args = Array.prototype.map.call(arguments, function(arg) { return typeof arg === 'function' ? function() { arg(new Error('woot 2')); } : arg; }); - return origFind.apply(this, args); + return origExec.apply(this, args); }; BlogPost @@ -798,6 +799,7 @@ describe('model: populate:', function() { assert.ok(err instanceof Error); assert.equal(err.message, 'woot 2'); + User.Query.prototype.exec = origExec; done(); }); }); @@ -4129,7 +4131,7 @@ describe('model: populate:', function() { ref: 'gh4278_1', localField: '_id', foreignField: 'a' - }) + }); var BSchema = new Schema({ a: mongoose.Schema.Types.ObjectId, @@ -4139,7 +4141,7 @@ describe('model: populate:', function() { ref: 'gh4278_2', localField: '_id', foreignField: 'b' - }) + }); var CSchema = new Schema({ b: mongoose.Schema.Types.ObjectId, @@ -4154,7 +4156,7 @@ describe('model: populate:', function() { assert.ifError(error); B.create({ name: 'B1', a: a._id }, function(error, b) { assert.ifError(error); - C.create({ name: 'C1', b: b._id }, function(error, c) { + C.create({ name: 'C1', b: b._id }, function(error) { assert.ifError(error); var options = { path: 'bs', @@ -4164,10 +4166,8 @@ describe('model: populate:', function() { }; A.findById(a).populate(options).exec(function(error, res) { assert.ifError(error); - console.log(require('util').inspect(res.toObject({ virtuals: true }), { depth: 10, colors: true })) assert.equal(res.bs.length, 1); assert.equal(res.bs[0].name, 'B1'); - console.log('FT', res.bs[0]); assert.equal(res.bs[0].cs.length, 1); assert.equal(res.bs[0].cs[0].name, 'C1'); done(); From 9262402f48c95090430cd7902304347b46541207 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Jul 2016 13:57:26 -0700 Subject: [PATCH 0701/2240] test(document): repro #4274 --- test/document.strict.test.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/test/document.strict.test.js b/test/document.strict.test.js index 9afa5398781..3e819414155 100644 --- a/test/document.strict.test.js +++ b/test/document.strict.test.js @@ -23,7 +23,7 @@ describe('document: strict mode:', function() { arrayMixed: [] }; - var lax = new Schema(raw, {strict: false}); + var lax = new Schema(raw, {strict: false, minimize: false}); var strict = new Schema(raw); Lax = db.model('Lax', lax); @@ -34,8 +34,8 @@ describe('document: strict mode:', function() { db.close(done); }); - it('when creating models with non-strict schemas', function(done) { - var l = new Lax({content: 'sample', rouge: 'data'}); + it('when creating models with non-strict schemas (gh-4274)', function(done) { + var l = new Lax({ content: 'sample', rouge: 'data', items: {} }); assert.equal(l.$__.strictMode, false); var lo = l.toObject(); @@ -45,7 +45,20 @@ describe('document: strict mode:', function() { assert.equal(lo.content, 'sample'); assert.equal(l.rouge, 'data'); assert.equal(lo.rouge, 'data'); - done(); + assert.deepEqual(l.items, {}); + assert.deepEqual(lo.items, {}); + + l.save(function(error) { + assert.ifError(error); + Lax.findById(l).exec(function(error, doc) { + assert.ifError(error); + var lo = doc.toObject(); + assert.equal(lo.content, 'sample'); + assert.equal(lo.rouge, 'data'); + assert.deepEqual(lo.items, {}); + done(); + }); + }); }); it('when creating models with strict schemas', function(done) { @@ -448,4 +461,3 @@ describe('document: strict mode:', function() { }); }); }); - From d330135ee077956fd92acc3f96b1e6fbea568f11 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Jul 2016 13:58:31 -0700 Subject: [PATCH 0702/2240] fix(document): allow setting empty obj if strict mode is false Fix #4274 --- lib/document.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/document.js b/lib/document.js index 0abfd575b28..8abf32150e2 100644 --- a/lib/document.js +++ b/lib/document.js @@ -507,6 +507,11 @@ Document.prototype.set = function(path, val, type, options) { var pathtype; var key; + if (i === 0 && !this.schema.options.minimize) { + this.set(val, {}); + return; + } + while (i--) { key = keys[i]; var pathName = prefix + key; From 592056d015603f12859c580919a5b6da0399de07 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 11 Jul 2016 07:20:55 -0700 Subject: [PATCH 0703/2240] test(aggregate): repro #4239 --- test/aggregate.test.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 380ec28a8e1..0ecca67c9c8 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -469,6 +469,35 @@ describe('aggregate: ', function() { }); }); + it('unwind with obj', function(done) { + var aggregate = new Aggregate(); + + var agg = aggregate. + model(db.model('Employee')). + unwind({ path: '$customers', preserveNullAndEmptyArrays: true }); + + assert.equal(agg._pipeline.length, 1); + assert.strictEqual(agg._pipeline[0].$unwind.preserveNullAndEmptyArrays, + true); + done(); + }); + + it('unwind throws with bad arg', function(done) { + var aggregate = new Aggregate(); + + var threw = false; + try { + aggregate. + model(db.model('Employee')). + unwind(36); + } catch (err) { + assert.ok(err.message.indexOf('to unwind()') !== -1); + threw = true; + } + assert.ok(threw); + done(); + }); + it('match', function(done) { var aggregate = new Aggregate(); From 5e385ae75bb5e74e0fb1c5ce5ad756ec9b3e0618 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 11 Jul 2016 07:21:00 -0700 Subject: [PATCH 0704/2240] fix(aggregate): allow passing obj to .unwind() Fix #4239 --- lib/aggregate.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 9eb47d4488c..bb24e88db15 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -276,9 +276,22 @@ Aggregate.prototype.near = function(arg) { Aggregate.prototype.unwind = function() { var args = utils.args(arguments); - return this.append.apply(this, args.map(function(arg) { - return {$unwind: (arg && arg.charAt(0) === '$') ? arg : '$' + arg}; - })); + var res = []; + for (var i = 0; i < args.length; ++i) { + var arg = args[i]; + if (arg && typeof arg === 'object') { + res.push({ $unwind: arg }); + } else if (typeof arg === 'string') { + res.push({ + $unwind: (arg && arg.charAt(0) === '$') ? arg : '$' + arg + }); + } else { + throw new Error('Invalid arg "' + arg + '" to unwind(), ' + + 'must be string or object'); + } + } + + return this.append.apply(this, res); }; /** From 73988625c12a40e507a37a1a236971f240e80dc6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 11 Jul 2016 15:19:17 -0700 Subject: [PATCH 0705/2240] chore: release 4.5.4 --- History.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 895d9927f2b..a3e7149b66e 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,17 @@ +4.5.4 / 2016-07-11 +================== + * fix(types): fix removing embedded documents #4309 [RoCat](https://github.com/RoCat) + * docs: various docs improvements #4302 #4294 [simonxca](https://github.com/simonxca) + * fix: upgrade mongodb -> 2.1.21 #4295 #4202 [RoCat](https://github.com/RoCat) + * fix(populate): convert single result to array for virtual populate because of lean #4288 + * fix(populate): handle empty results for populate virtuals properly #4285 #4284 + * fix(query): dont cast $inc to number if type is long #4283 + * fix(types): allow setting single nested doc to null #4281 + * fix(populate): handle deeply nested virtual populate #4278 + * fix(document): allow setting empty obj if strict mode is false #4274 + * fix(aggregate): allow passing obj to .unwind() #4239 + * docs(document): add return statements to transform examples #1963 + 4.5.3 / 2016-06-30 ================== * fix(query): pass correct options to QueryCursor #4277 #4266 diff --git a/package.json b/package.json index 5d06222e88a..70cb803c166 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.4-pre", + "version": "4.5.4", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 25810a378989b478c13d2356322aa98c36a31fd3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 13 Jul 2016 17:02:26 -0700 Subject: [PATCH 0706/2240] chore: now working on 4.5.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 70cb803c166..9909b34705e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.4", + "version": "4.5.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ba0c9fa9427ebbdbb7135d72c642bdad2fe84fdd Mon Sep 17 00:00:00 2001 From: Christopher Chang Date: Thu, 14 Jul 2016 16:38:41 -0700 Subject: [PATCH 0707/2240] Update package.json version 2.1.21 is broken per https://jira.mongodb.org/browse/NODE-722?focusedCommentId=1287950&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-1287950. revert to 2.1.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9909b34705e..0685610e090 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.23", "hooks-fixed": "1.1.0", "kareem": "1.1.3", - "mongodb": "2.1.21", + "mongodb": "2.1.18", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.11.0", From e5c75be598eae6e56421d866d7f4dd59ca8e4063 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 14 Jul 2016 18:04:32 -0700 Subject: [PATCH 0708/2240] test(query): repro #4318 --- test/query.toconstructor.test.js | 45 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/test/query.toconstructor.test.js b/test/query.toconstructor.test.js index 5aafe67b783..7e097604592 100644 --- a/test/query.toconstructor.test.js +++ b/test/query.toconstructor.test.js @@ -26,18 +26,25 @@ mongoose.model(cName, Comment); describe('Query:', function() { describe('toConstructor', function() { + var db; + + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + it('creates a query', function(done) { - var db = start(); var Product = db.model(prodName); var prodQ = Product.find({title: /test/}).toConstructor(); assert.ok(prodQ() instanceof Query); - - db.close(done); + done(); }); it('copies all the right values', function(done) { - var db = start(); var Product = db.model(prodName); var prodQ = Product.update({title: /test/}, {title: 'blah'}); @@ -53,19 +60,16 @@ describe('Query:', function() { assert.deepEqual(prodQ.model, prodC().model); assert.deepEqual(prodQ.mongooseCollection, prodC().mongooseCollection); assert.deepEqual(prodQ._mongooseOptions, prodC()._mongooseOptions); - - db.close(done); + done(); }); it('gets expected results', function(done) { - var db = start(); var Product = db.model(prodName); Product.create({title: 'this is a test'}, function(err, p) { assert.ifError(err); var prodC = Product.find({title: /test/}).toConstructor(); prodC().exec(function(err, results) { - db.close(); assert.ifError(err); assert.equal(results.length, 1); assert.equal(p.title, results[0].title); @@ -75,7 +79,6 @@ describe('Query:', function() { }); it('can be re-used multiple times', function(done) { - var db = start(); var Product = db.model(prodName); Product.create([{title: 'moar thing'}, {title: 'second thing'}], function(err, prods) { @@ -93,7 +96,6 @@ describe('Query:', function() { assert.equal(res.length, 1); prodC().exec(function(err, res) { - db.close(); assert.ifError(err); assert.equal(res.length, 2); done(); @@ -104,9 +106,7 @@ describe('Query:', function() { }); it('options get merged properly', function(done) { - var db = start(); var Product = db.model(prodName); - db.close(); var prodC = Product.find({title: /blah/}).setOptions({sort: 'title', lean: true}); prodC = prodC.toConstructor(); @@ -118,9 +118,7 @@ describe('Query:', function() { }); it('options get cloned (gh-3176)', function(done) { - var db = start(); var Product = db.model(prodName); - db.close(); var prodC = Product.find({title: /blah/}).setOptions({sort: 'title', lean: true}); prodC = prodC.toConstructor(); @@ -131,13 +129,12 @@ describe('Query:', function() { var nq2 = prodC(null, {limit: 5}); assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3}); assert.deepEqual(nq2._mongooseOptions, {lean: true, limit: 5}); + done(); }); it('creates subclasses of mquery', function(done) { - var db = start(); var Product = db.model(prodName); - db.close(); var opts = {safe: {w: 'majority'}, readPreference: 'p'}; var match = {title: 'test', count: {$gt: 101}}; @@ -163,5 +160,21 @@ describe('Query:', function() { assert.equal('find', m.op); done(); }); + + it('with findOneAndUpdate (gh-4318)', function(done) { + var Product = db.model(prodName); + + var Q = Product.where({ title: 'test' }).toConstructor(); + + var query = { 'tags.test': 1 }; + var update = { + strings: ['123'], + numbers: [1, 2, 3] + }; + Q().findOneAndUpdate(query, update, function(error) { + assert.ifError(error); + done(); + }); + }); }); }); From 9ccb885d73ae6ea4bcecb3dcf7d9a78b08df5815 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 14 Jul 2016 18:07:12 -0700 Subject: [PATCH 0709/2240] fix(query): correctly pass model in .toConstructor() Fix #4318 --- lib/query.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/query.js b/lib/query.js index f6defba079a..7e3a44df6bd 100644 --- a/lib/query.js +++ b/lib/query.js @@ -153,12 +153,15 @@ Query.use$geoWithin = mquery.use$geoWithin; */ Query.prototype.toConstructor = function toConstructor() { + var model = this.model; + var coll = this.mongooseCollection; + var CustomQuery = function(criteria, options) { if (!(this instanceof CustomQuery)) { return new CustomQuery(criteria, options); } this._mongooseOptions = utils.clone(p._mongooseOptions); - Query.call(this, criteria, options || null); + Query.call(this, criteria, options || null, model, coll); }; util.inherits(CustomQuery, Query); @@ -177,8 +180,6 @@ Query.prototype.toConstructor = function toConstructor() { p._path = this._path; p._distinct = this._distinct; p._collection = this._collection; - p.model = this.model; - p.mongooseCollection = this.mongooseCollection; p._mongooseOptions = this._mongooseOptions; return CustomQuery; From d5ab46b802fed3c4b43f055a223f964347235f29 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 15 Jul 2016 16:10:21 -0400 Subject: [PATCH 0710/2240] docs(middleware): add docs describing error handling middleware Fix #4229 --- docs/middleware.jade | 69 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/docs/middleware.jade b/docs/middleware.jade index c8afaced3dc..3ea93c1cfff 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -26,7 +26,7 @@ block content Both document middleware and query middleware support pre and post hooks. How pre and post hooks work is described in more detail below. - + **Note:** There is no query hook for `remove()`, only for documents. If you set a 'remove' hook, it will be fired when you call `myDoc.remove()`, not when you call `MyModel.remove()`. @@ -48,7 +48,7 @@ block content | Parallel middleware offer more fine-grained flow control. :js var schema = new Schema(..); - + // `true` means this is a parallel middleware. You **must** specify `true` // as the second parameter if you want to use parallel middleware. schema.pre('save', true, function(next, done) { @@ -111,7 +111,7 @@ block content schema.post('remove', function(doc) { console.log('%s has been removed', doc._id); }); - + h3#post-async Asynchronous Post Hooks :markdown While post middleware doesn't receive flow control, you can still make @@ -119,7 +119,7 @@ block content If your post hook function takes at least 2 parameters, mongoose will assume the second parameter is a `next()` function that you will call to trigger the next middleware in the sequence. - + :js // Takes 2 parameters: this is an asynchronous post hook schema.post('save', function(doc, next) { @@ -192,6 +192,67 @@ block content this.update({},{ $set: { updatedAt: new Date() } }); }); + h3#error-handling Error Handling Middleware + :markdown + _New in 4.5.0_ + + Middleware execution normally stops the first time a piece of middleware + calls `next()` with an error. However, there is a special kind of post + middleware called "error handling middleware" that executes specifically + when an error occurs. + + Error handling middleware is defined as middleware that takes one extra + parameter: the 'error' that occurred as the first parameter to the function. + Error handling middleware can then transform the error however you want. + + :js + var schema = new Schema({ + name: { + type: String, + // Will trigger a MongoError with code 11000 when + // you save a duplicate + unique: true + } + }); + + // Handler **must** take 3 parameters: the error that occurred, the document + // in question, and the `next()` function + schema.post('save', function(error, doc, next) { + if (error.name === 'MongoError' && error.code === 11000) { + next(new Error('There was a duplicate key error')); + } else { + next(error); + } + }); + + // Will trigger the `post('save')` error handler + Person.create([{ name: 'Axl Rose' }, { name: 'Axl Rose' }]); + + :markdown + Error handling middleware also works with query middleware. You can + also define a post `update()` hook that will catch MongoDB duplicate key + errors. + + :js + // The same E11000 error can occur when you call `update()` + // This function **must** take 3 parameters. If you use the + // `passRawResult` function, this function **must** take 4 + // parameters + schema.post('update', function(error, res, next) { + if (error.name === 'MongoError' && error.code === 11000) { + next(new Error('There was a duplicate key error')); + } else { + next(error); + } + }); + + var people = [{ name: 'Axl Rose' }, { name: 'Slash' }]; + Person.create(people, function(error) { + Person.update({ name: 'Slash' }, { $set: { name: 'Axl Rose' } }, function(error) { + // `error.message` will be "There was a duplicate key error" + }); + }); + h3#next Next Up :markdown Now that we've covered middleware, let's take a look at Mongoose's approach From a2b84974eaeb2476517c0dc3556440c62e322812 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 15 Jul 2016 17:48:14 -0400 Subject: [PATCH 0711/2240] fix(schema): log whole object when invalidating document array Re: #3602 --- lib/schema/documentarray.js | 5 ++++- test/model.findOneAndUpdate.test.js | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index f6eea8b78e3..0812efff08b 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -9,6 +9,7 @@ var CastError = require('../error/cast'); var MongooseDocumentArray = require('../types/documentarray'); var SchemaType = require('../schematype'); var Subdocument = require('../types/embedded'); +var util = require('util'); /** * SubdocsArray SchemaType constructor @@ -251,7 +252,9 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { // see gh-746 value[i] = subdoc; } catch (error) { - throw new CastError('embedded', value[i], value._path, error); + var valueInErrorMessage = util.inspect(value[i]); + throw new CastError('embedded', valueInErrorMessage, + value._path, error); } } } diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index fc202cfa410..18259b186f6 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1610,5 +1610,25 @@ describe('model: findByIdAndUpdate:', function() { done(); }); }); + + it('single nested doc cast errors (gh-3602)', function(done) { + var AddressSchema = new Schema({ + street: { + type: Number + } + }); + + var PersonSchema = new Schema({ + addresses: [AddressSchema] + }); + + var Person = db.model('gh3602', PersonSchema); + + var update = { $push: { addresses: { street: 'not a num' } } }; + Person.findOneAndUpdate({}, update, function(error) { + assert.ok(error.message.indexOf('street') !== -1); + done(); + }); + }); }); }); From 20a5763bafa3b592fb694598ad2dbc68bc466fad Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 16 Jul 2016 09:16:57 -0400 Subject: [PATCH 0712/2240] perf(types): remove defineProperty usage in documentarray Fix #4333 --- lib/types/documentarray.js | 21 +++++++++++---------- test/types.documentarray.test.js | 2 -- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index dbb9c432708..f18bde1c659 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -22,36 +22,37 @@ var MongooseArray = require('./array'), function MongooseDocumentArray(values, path, doc) { var arr = [].concat(values); + arr._path = path; + var props = { isMongooseArray: true, isMongooseDocumentArray: true, validators: [], - _path: path, _atomics: {}, _schema: void 0, _handlers: void 0 }; - var tmp = {}; // Values always have to be passed to the constructor to initialize, since // otherwise MongooseArray#push will mark the array as modified to the parent. var keysMA = Object.keys(MongooseArray.mixin); - for (var j = 0; j < keysMA.length; ++j) { - tmp[keysMA[j]] = {enumerable: false, configurable: true, writable: true, value: MongooseArray.mixin[keysMA[j]]}; + var numKeys = keysMA.length; + for (var j = 0; j < numKeys; ++j) { + arr[keysMA[j]] = MongooseArray.mixin[keysMA[j]]; } var keysMDA = Object.keys(MongooseDocumentArray.mixin); - for (var i = 0; i < keysMDA.length; ++i) { - tmp[keysMDA[i]] = {enumerable: false, configurable: true, writable: true, value: MongooseDocumentArray.mixin[keysMDA[i]]}; + numKeys = keysMDA.length; + for (var i = 0; i < numKeys; ++i) { + arr[keysMDA[i]] = MongooseDocumentArray.mixin[keysMDA[i]]; } var keysP = Object.keys(props); - for (var k = 0; k < keysP.length; ++k) { - tmp[keysP[k]] = {enumerable: false, configurable: true, writable: true, value: props[keysP[k]]}; + numKeys = keysP.length; + for (var k = 0; k < numKeys; ++k) { + arr[keysP[k]] = props[keysP[k]]; } - Object.defineProperties(arr, tmp); - // Because doc comes from the context of another function, doc === global // can happen if there was a null somewhere up the chain (see #3020 && #3034) // RB Jun 17, 2015 updated to check for presence of expected paths instead diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js index d8c0c78e593..3c09e4395c5 100644 --- a/test/types.documentarray.test.js +++ b/test/types.documentarray.test.js @@ -54,7 +54,6 @@ describe('types.documentarray', function() { assert.ok(a.isMongooseDocumentArray); assert.ok(Array.isArray(a)); - assert.deepEqual(Object.keys(a), Object.keys(a.toObject())); assert.deepEqual(a._atomics.constructor, Object); done(); @@ -458,4 +457,3 @@ describe('types.documentarray', function() { }); }); }); - From 15bc3e8b3c915903f0ac46fd77fec46cff62f71b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 17 Jul 2016 14:40:12 -0400 Subject: [PATCH 0713/2240] test(document): repro #4337 --- test/document.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 2a1a7882c2f..10442ceefdf 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3053,5 +3053,23 @@ describe('document', function() { }); }); }); + + it('minimize + empty object (gh-4337)', function(done) { + var SomeModel; + var SomeModelSchema; + + SomeModelSchema = new mongoose.Schema({}, { + minimize: false + }); + + SomeModel = mongoose.model('somemodel', SomeModelSchema); + + try { + new SomeModel({}); + } catch (error) { + assert.ifError(error); + } + done(); + }); }); }); From 3516c7a5a186b49f6059f5857ce257032c3ae2c7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 17 Jul 2016 14:40:38 -0400 Subject: [PATCH 0714/2240] fix(document): handle setting root to empty obj if minimize false Fix #4337 --- lib/document.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 8abf32150e2..32c2eebe4b7 100644 --- a/lib/document.js +++ b/lib/document.js @@ -508,8 +508,10 @@ Document.prototype.set = function(path, val, type, options) { var key; if (i === 0 && !this.schema.options.minimize) { - this.set(val, {}); - return; + if (val) { + this.set(val, {}); + } + return this; } while (i--) { From 3e5e0e98bc31d1446f392adb8a31d4dcb4144716 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 17 Jul 2016 15:04:44 -0400 Subject: [PATCH 0715/2240] test(types): repro #3602 part 2 --- test/model.findOneAndUpdate.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 18259b186f6..3f092663871 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1627,6 +1627,8 @@ describe('model: findByIdAndUpdate:', function() { var update = { $push: { addresses: { street: 'not a num' } } }; Person.findOneAndUpdate({}, update, function(error) { assert.ok(error.message.indexOf('street') !== -1); + assert.equal(error.reason.message, + 'Cast to Number failed for value "not a num" at path "street"'); done(); }); }); From 9f6b6aef118a5d64b338ad5d3c2671e1d5691804 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 17 Jul 2016 15:04:51 -0400 Subject: [PATCH 0716/2240] fix(types): throw correct error when invalidating doc array Fix #3602 --- lib/types/embedded.js | 3 +-- test/types.documentarray.test.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 5049ff9e9a9..37fac192f50 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -180,8 +180,7 @@ EmbeddedDocument.prototype.inspect = function() { EmbeddedDocument.prototype.invalidate = function(path, err, val, first) { if (!this.__parent) { - var msg = 'Unable to invalidate a subdocument that has not been added to an array.'; - throw new Error(msg); + throw err; } var index = this.__index; diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js index 3c09e4395c5..b909a4f07db 100644 --- a/test/types.documentarray.test.js +++ b/test/types.documentarray.test.js @@ -409,7 +409,7 @@ describe('types.documentarray', function() { assert.throws(function() { // has no parent array subdoc.invalidate('name', 'junk', 47); - }, /^Error: Unable to invalidate a subdocument/); + }); t.validate(function() { var e = t.errors['docs.0.name']; assert.ok(e); From 911d6ecf707893a242eee1608048af7211e8ec93 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 17 Jul 2016 22:04:58 -0400 Subject: [PATCH 0717/2240] test(services): repro #4305 --- test/model.findOneAndUpdate.test.js | 50 +++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 3f092663871..00d82a4dc9a 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1611,6 +1611,56 @@ describe('model: findByIdAndUpdate:', function() { }); }); + it('custom validator on mixed field (gh-4305)', function(done) { + var called = 0; + + var boardSchema = new Schema({ + name: { + type: String, + required: true + }, + structure: { + type: Schema.Types.Mixed, + required: true, + validate: { + validator: function() { + ++called; + return true; + }, + message: 'The structure of the board is invalid' + } + } + }); + var Board = db.model('gh4305', boardSchema); + + var update = { + structure: [ + { + capacity: 0, + size: 0, + category: 0, + isColumn: true, + title: 'Backlog' + } + ] + }; + var opts = { + 'new': true, + upsert: false, + passRawResult: false, + overwrite: false, + runValidators: true, + setDefaultsOnInsert: true + }; + Board. + findOneAndUpdate({}, update, opts). + exec(function(error) { + assert.ifError(error); + assert.equal(called, 1); + done(); + }); + }); + it('single nested doc cast errors (gh-3602)', function(done) { var AddressSchema = new Schema({ street: { From 9165f0f26fe172596a8d6e6dec58377bd7370ed8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 17 Jul 2016 22:05:03 -0400 Subject: [PATCH 0718/2240] fix(services): avoid double-validating mixed types with update validators Fix #4305 --- lib/services/updateValidators.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 6f97bbe1c85..8d7cd5c133e 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -2,7 +2,8 @@ * Module dependencies. */ -var ValidationError = require('../error/validation.js'); +var Mixed = require('../schema/mixed'); +var ValidationError = require('../error/validation'); var async = require('async'); var flatten = require('./common').flatten; var modifiedPaths = require('./common').modifiedPaths; @@ -60,6 +61,12 @@ module.exports = function(query, schema, castedDoc, options) { function iter(i) { var schemaPath = schema._getSchema(updates[i]); if (schemaPath) { + // gh-4305: `_getSchema()` will report all sub-fields of a 'Mixed' path + // as 'Mixed', so avoid double validating them. + if (schemaPath instanceof Mixed && schemaPath.path !== updates[i]) { + return; + } + validatorsToExecute.push(function(callback) { schemaPath.doValidate( updatedValues[updates[i]], From e2effa6ff4068a54c0c47de00fb4ccf51f431d56 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 18 Jul 2016 06:56:50 -0700 Subject: [PATCH 0719/2240] chore: release 4.5.5 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index a3e7149b66e..b5cce319052 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.5.5 / 2016-07-18 +================== + * fix(document): handle setting root to empty obj if minimize false #4337 + * fix: downgrade to mongodb 2.1.18 #4335 #4334 #4328 #4323 + * perf(types): remove defineProperty usage in documentarray #4333 + * fix(query): correctly pass model in .toConstructor() #4318 + * fix(services): avoid double-validating mixed types with update validators #4305 + * docs(middleware): add docs describing error handling middleware #4229 + * fix(types): throw correct error when invalidating doc array #3602 + 4.5.4 / 2016-07-11 ================== * fix(types): fix removing embedded documents #4309 [RoCat](https://github.com/RoCat) diff --git a/package.json b/package.json index 0685610e090..58370addf63 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.5-pre", + "version": "4.5.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 864b10e0a747d06e5c908e89cdf1127f08100ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Ljungstr=C3=B6m?= Date: Tue, 19 Jul 2016 14:43:00 +0200 Subject: [PATCH 0720/2240] ownerDocument() now works when nesting arrays and single embedded docs (Fix #3589) --- lib/types/embedded.js | 14 +++++--- lib/types/subdocument.js | 4 +-- test/types.embeddeddocument.test.js | 53 +++++++++++++++++++++++++++++ test/types.subdocument.test.js | 53 +++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 test/types.embeddeddocument.test.js create mode 100644 test/types.subdocument.test.js diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 37fac192f50..811e9322f6c 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -254,8 +254,8 @@ EmbeddedDocument.prototype.ownerDocument = function() { return this; } - while (parent.__parent) { - parent = parent.__parent; + while (parent.__parent || parent.$parent) { + parent = parent.__parent || parent.$parent; } this.$__.ownerDocument = parent; @@ -280,9 +280,13 @@ EmbeddedDocument.prototype.$__fullPath = function(path) { } var paths = []; - while (parent.__parent) { - paths.unshift(parent.__parentArray._path); - parent = parent.__parent; + while (parent.__parent || parent.$parent) { + if (parent.__parent) { + paths.unshift(parent.__parentArray._path); + } else { + paths.unshift(parent.$basePath); + } + parent = parent.__parent || parent.$parent; } this.$__.fullPath = paths.join('.'); diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index a5d9cc22977..d617254d00c 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -80,8 +80,8 @@ Subdocument.prototype.ownerDocument = function() { return this; } - while (parent.$parent) { - parent = parent.$parent; + while (parent.$parent || parent.__parent) { + parent = parent.$parent || parent.__parent; } this.$__.ownerDocument = parent; return this.$__.ownerDocument; diff --git a/test/types.embeddeddocument.test.js b/test/types.embeddeddocument.test.js new file mode 100644 index 00000000000..d15f6de87b4 --- /dev/null +++ b/test/types.embeddeddocument.test.js @@ -0,0 +1,53 @@ + +/** + * Module dependencies. + */ + +var assert = require('power-assert'), + start = require('./common'), + mongoose = start.mongoose, + Schema = mongoose.Schema; + +/** + * Schema. + */ + +var GrandChildSchema = new Schema({ + name: String +}); + +var ChildSchema = new Schema({ + name: String, + children: [GrandChildSchema] +}); + +var ParentSchema = new Schema({ + name: String, + child: ChildSchema +}); + +mongoose.model('Parent-3589-Embedded', ParentSchema); + +/** + * Test. + */ + +describe('types.embeddeddocument', function() { + it('returns a proper ownerDocument (gh-3589)', function(done) { + var Parent = mongoose.model('Parent-3589-Embedded'); + var p = new Parent({ + name: 'Parent Parentson', + child: { + name: 'Child Parentson', + children: [ + { + name: 'GrandChild Parentson' + } + ] + } + }); + + assert.equal(p._id, p.child.children[0].ownerDocument()._id); + done(); + }); +}); diff --git a/test/types.subdocument.test.js b/test/types.subdocument.test.js new file mode 100644 index 00000000000..051281700fc --- /dev/null +++ b/test/types.subdocument.test.js @@ -0,0 +1,53 @@ + +/** + * Module dependencies. + */ + +var assert = require('power-assert'), + start = require('./common'), + mongoose = start.mongoose, + Schema = mongoose.Schema; + +/** + * Schema. + */ + +var GrandChildSchema = new Schema({ + name: String +}); + +var ChildSchema = new Schema({ + name: String, + child: GrandChildSchema +}); + +var ParentSchema = new Schema({ + name: String, + children: [ChildSchema] +}); + +mongoose.model('Parent-3589-Sub', ParentSchema); + +/** + * Test. + */ + +describe('types.subdocument', function() { + it('returns a proper ownerDocument (gh-3589)', function(done) { + var Parent = mongoose.model('Parent-3589-Sub'); + var p = new Parent({ + name: 'Parent Parentson', + children: [ + { + name: 'Child Parentson', + child: { + name: 'GrandChild Parentson' + } + } + ] + }); + + assert.equal(p._id, p.children[0].child.ownerDocument()._id); + done(); + }); +}); From 28c07be598c98eb84490a0c5dabf2702a5c6b6b2 Mon Sep 17 00:00:00 2001 From: Delapouite Date: Tue, 19 Jul 2016 18:17:04 +0200 Subject: [PATCH 0721/2240] docs(api): fix link to populate() and add a new one from depopulate() --- lib/document.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 32c2eebe4b7..0bcb5f2cc3b 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2412,7 +2412,7 @@ Document.prototype.populate = function populate() { * doc.execPopulate().then(resolve, reject); * * - * @see Document.populate #Document_model.populate + * @see Document.populate #document_Document-populate * @api public * @return {Promise} promise that resolves to the document when population is done */ @@ -2490,6 +2490,7 @@ Document.prototype.populated = function(path, val, options) { * If the path was not populated, this is a no-op. * * @param {String} path + * @see Document.populate #document_Document-populate * @api public */ From a83f2f30966de64b39c4364f01d308b87e6f2473 Mon Sep 17 00:00:00 2001 From: Bertrand Marron Date: Wed, 20 Jul 2016 18:47:06 +0200 Subject: [PATCH 0722/2240] Make sure that createdAt does not get overriden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit createdAt should always represent the document’s creation date. Whenever createdAt is not selected (so undefined) and we update the document – it should not be set to a new value. Fix #4340 --- lib/schema.js | 2 +- test/schema.timestamps.test.js | 47 ++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 4cf8bce6c35..f4dc70df4b5 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -753,7 +753,7 @@ Schema.prototype.setupTimestamp = function(timestamps) { var defaultTimestamp = new Date(); var auto_id = this._id && this._id.auto; - if (!this[createdAt]) { + if (!this[createdAt] && this.isSelected(createdAt)) { this[createdAt] = auto_id ? this._id.getTimestamp() : defaultTimestamp; } diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js index e31c518da59..35a9f23d103 100644 --- a/test/schema.timestamps.test.js +++ b/test/schema.timestamps.test.js @@ -91,6 +91,53 @@ describe('schema options.timestamps', function() { assert.ok(TestSchema.path('updated')); done(); }); + + it('should not override createdAt when not selected (gh-4340)', function(done) { + var TestSchema = new Schema({ + name: String + }, { + timestamps: true + }); + + var conn = start(); + var Test = conn.model('Test', TestSchema); + + Test.create({ + name: 'hello' + }, function(err, doc) { + // Let’s save the dates to compare later. + var createdAt = doc.createdAt; + var updatedAt = doc.updatedAt; + + assert.ok(doc.createdAt); + + Test.findById(doc._id, { name: true }, function(err, doc) { + // The dates shouldn’t be selected here. + assert.ok(!doc.createdAt); + assert.ok(!doc.updatedAt); + + doc.name = 'world'; + + doc.save(function(err, doc) { + // Let’s save the new updatedAt date as it should have changed. + var newUpdatedAt = doc.updatedAt; + + assert.ok(!doc.createdAt); + assert.ok(doc.updatedAt); + + Test.findById(doc._id, function(err, doc) { + // Let’s make sure that everything is working again by + // comparing the dates with the ones we saved. + assert.equal(doc.createdAt.valueOf(), createdAt.valueOf()); + assert.notEqual(doc.updatedAt.valueOf(), updatedAt.valueOf()); + assert.equal(doc.updatedAt.valueOf(), newUpdatedAt.valueOf()); + + done(); + }); + }); + }); + }); + }); }); describe('auto update createdAt and updatedAt when create/save/update document', function() { From cc3f4e0b889b2ff457a2a2910c096302a31a5a22 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 20 Jul 2016 13:41:38 -0700 Subject: [PATCH 0723/2240] chore: now working on 4.5.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 58370addf63..08e0a8609f7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.5", + "version": "4.5.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 59eb8c8d504c438171d677ffd8025073c1b56301 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 20 Jul 2016 13:57:21 -0700 Subject: [PATCH 0724/2240] test(populate): repro #4329 --- test/model.populate.test.js | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 36370d66f1f..5cc5af454fc 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4019,6 +4019,52 @@ describe('model: populate:', function() { }); }); + it('with multiple results and justOne (gh-4329)', function(done) { + var UserSchema = new Schema({ + openId: { + type: String, + unique: true + } + }); + var TaskSchema = new Schema({ + openId: { + type: String + } + }); + + TaskSchema.virtual('user', { + ref: 'gh4329', + localField: 'openId', + foreignField: 'openId', + justOne: true + }); + + var User = db.model('gh4329', UserSchema); + var Task = db.model('gh4329_0', TaskSchema); + + User.create({ openId: 'user1' }, { openId: 'user2' }, function(error) { + assert.ifError(error); + Task.create({ openId: 'user1' }, { openId: 'user2' }, function(error) { + assert.ifError(error); + Task. + find(). + sort({ openId: 1 }). + populate('user'). + exec(function(error, tasks) { + assert.ifError(error); + + assert.ok(tasks[0].user); + assert.ok(tasks[1].user); + var users = tasks.map(function(task) { + return task.user.openId; + }); + assert.deepEqual(users, ['user1', 'user2']); + done(); + }); + }); + }); + }); + it('with no results (gh-4284)', function(done) { var PersonSchema = new Schema({ name: String, From 0a560949c701cc22f8208bafe277eb3fc52f0224 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 20 Jul 2016 13:57:42 -0700 Subject: [PATCH 0725/2240] fix(populate): dont use findOne when justOne option set --- lib/model.js | 17 ++++------------- lib/schema.js | 4 +++- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/lib/model.js b/lib/model.js index a87fd23b401..b2fdaad92cc 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2661,20 +2661,11 @@ function populate(model, docs, options, callback) { } var subPopulate = mod.options.populate; - var query; - if (mod.justOne) { - query = mod.Model.findOne(match, select, mod.options.options); - if (subPopulate) { - query.populate(subPopulate); - } - query.exec(next.bind(this, mod, assignmentOpts)); - } else { - query = mod.Model.find(match, select, mod.options.options); - if (subPopulate) { - query.populate(subPopulate); - } - query.exec(next.bind(this, mod, assignmentOpts)); + var query = mod.Model.find(match, select, mod.options.options); + if (subPopulate) { + query.populate(subPopulate); } + query.exec(next.bind(this, mod, assignmentOpts)); } if (!hasOne) { diff --git a/lib/schema.js b/lib/schema.js index 4cf8bce6c35..7b09df8e8b5 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1277,7 +1277,9 @@ Schema.prototype.virtual = function(name, options) { } if (options.justOne) { - this.$$populatedVirtuals[name] = obj[name]; + this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? + obj[name][0] : + obj[name]; } else { this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? obj[name] : From 9d035bb17899180acec6739d19f04f1dfebb4447 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 21 Jul 2016 07:26:45 -0700 Subject: [PATCH 0726/2240] test(plugins): repro #4271 --- test/index.test.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/test/index.test.js b/test/index.test.js index fab6e72b7bd..7b5a053672e 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -62,13 +62,16 @@ describe('mongoose module:', function() { }); it('declaring global plugins', function(done) { - var mong = new Mongoose(), - schema = new Schema(), - called = 0; + var mong = new Mongoose(); + var subSchema = new Schema(); + var schema = new Schema({ + test: [subSchema] + }); + var called = 0; + var calls = []; mong.plugin(function(s) { - assert.equal(s, schema); - called++; + calls.push(s); }); schema.plugin(function(s) { @@ -78,7 +81,10 @@ describe('mongoose module:', function() { mong.model('GlobalPlugins', schema); - assert.equal(called, 2); + assert.equal(called, 1); + assert.equal(calls.length, 2); + assert.equal(calls[0], schema); + assert.equal(calls[1], subSchema); done(); }); @@ -423,4 +429,3 @@ describe('mongoose module:', function() { }); }); }); - From e0039d8f0e0609904ee78b895f148fb68f16e1d7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 21 Jul 2016 07:27:24 -0700 Subject: [PATCH 0727/2240] fix(plugins): apply global plugins to subschemas Fix #4271 --- lib/index.js | 11 ++++++++++- lib/schema.js | 6 ++++++ lib/schema/documentarray.js | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index ed39c2f0ffb..7b72ed92a97 100644 --- a/lib/index.js +++ b/lib/index.js @@ -429,9 +429,18 @@ Mongoose.prototype.modelNames.$hasSideEffects = true; */ Mongoose.prototype._applyPlugins = function(schema) { - for (var i = 0, l = this.plugins.length; i < l; i++) { + if (schema.$globalPluginsApplied) { + return; + } + var i; + var len; + for (i = 0, len = this.plugins.length; i < len; ++i) { schema.plugin(this.plugins[i][0], this.plugins[i][1]); } + schema.$globalPluginsApplied = true; + for (i = 0, len = schema.childSchemas.length; i < len; ++i) { + this._applyPlugins(schema.childSchemas[i]); + } }; Mongoose.prototype._applyPlugins.$hasSideEffects = true; diff --git a/lib/schema.js b/lib/schema.js index 7b09df8e8b5..0306ab6db33 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -84,6 +84,7 @@ function Schema(obj, options) { this.discriminatorMapping = undefined; this._indexedpaths = undefined; this.query = {}; + this.childSchemas = []; this.s = { hooks: new Kareem(), @@ -508,6 +509,7 @@ Schema.prototype.path = function(path, obj) { branch[last] = utils.clone(obj); this.paths[path] = Schema.interpretAsType(path, obj, this.options); + if (this.paths[path].$isSingleNested) { for (var key in this.paths[path].schema.paths) { this.singleNestedPaths[path + '.' + key] = @@ -517,6 +519,10 @@ Schema.prototype.path = function(path, obj) { this.singleNestedPaths[path + '.' + key] = this.paths[path].schema.singleNestedPaths[key]; } + + this.childSchemas.push(this.paths[path].schema); + } else if (this.paths[path].$isMongooseDocumentArray) { + this.childSchemas.push(this.paths[path].schema); } return this; }; diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 0812efff08b..821facdae35 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -46,6 +46,7 @@ function DocumentArray(key, schema, options) { ArrayType.call(this, key, EmbeddedDocument, options); this.schema = schema; + this.$isMongooseDocumentArray = true; var path = this.path; var fn = this.defaultValue; From c320fa79c03083ab874b5c37f79f8cf0735c5fbf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 21 Jul 2016 08:05:43 -0700 Subject: [PATCH 0728/2240] fix(document): dont trigger .then() deprecated warning when calling doc.remove() Fix #4291 --- lib/document.js | 18 +----------------- lib/schema.js | 10 ++++++++++ package.json | 2 +- test/model.discriminator.test.js | 2 +- test/schema.test.js | 6 +++--- 5 files changed, 16 insertions(+), 22 deletions(-) diff --git a/lib/document.js b/lib/document.js index 32c2eebe4b7..ddc132f7d4f 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1143,28 +1143,12 @@ Document.prototype.isSelected = function isSelected(path) { */ Document.prototype.validate = function(options, callback) { - var _this = this; - var Promise = PromiseProvider.get(); if (typeof options === 'function') { callback = options; options = null; } - if (options && options.__noPromise) { - this.$__validate(callback); - return; - } - - return new Promise.ES6(function(resolve, reject) { - _this.$__validate(function(error) { - callback && callback(error); - if (error) { - reject(error); - return; - } - resolve(); - }); - }); + this.$__validate(callback); }; /*! diff --git a/lib/schema.js b/lib/schema.js index 0306ab6db33..a060ad9283b 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -241,6 +241,16 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { }); } }, + { + kind: 'pre', + hook: 'validate', + isAsync: true, + fn: function(next, done) { + // Hack to ensure that we always wrap validate() in a promise + next(); + done(); + } + }, { kind: 'pre', hook: 'remove', diff --git a/package.json b/package.json index 08e0a8609f7..ca07d73f31d 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "async": "1.5.2", "bson": "~0.4.23", - "hooks-fixed": "1.1.0", + "hooks-fixed": "1.2.0", "kareem": "1.1.3", "mongodb": "2.1.18", "mpath": "0.2.1", diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index cc41d26a3c6..f9107e11baf 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -319,7 +319,7 @@ describe('model', function() { }); it('merges callQueue with base queue defined before discriminator types callQueue', function(done) { - assert.equal(Employee.schema.callQueue.length, 5); + assert.equal(Employee.schema.callQueue.length, 6); // PersonSchema.post('save') assert.strictEqual(Employee.schema.callQueue[0], Person.schema.callQueue[0]); diff --git a/test/schema.test.js b/test/schema.test.js index f4541da7749..28436d80397 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -774,15 +774,15 @@ describe('schema', function() { Tobi.pre('save', function() { }); - assert.equal(Tobi.callQueue.length, 4); + assert.equal(Tobi.callQueue.length, 5); Tobi.post('save', function() { }); - assert.equal(Tobi.callQueue.length, 5); + assert.equal(Tobi.callQueue.length, 6); Tobi.pre('save', function() { }); - assert.equal(Tobi.callQueue.length, 6); + assert.equal(Tobi.callQueue.length, 7); done(); }); }); From b24c8b9936d72768a983977e4b6b188fe543235c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 22 Jul 2016 07:48:54 -0700 Subject: [PATCH 0729/2240] fix(model): ensure `ensureIndex()` never calls back in the same tick Fix #4246 --- lib/model.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index b2fdaad92cc..5f489bf904b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1010,7 +1010,9 @@ function _ensureIndexes(model, callback) { })); }; - create(); + process.nextTick(function() { + create(); + }); } function _handleSafe(options) { From 627b057c4709baf30a4c8c687a02e432d1a15a0d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 22 Jul 2016 08:44:52 -0700 Subject: [PATCH 0730/2240] docs(connection): add promiseLibrary option Fix #3869 --- docs/connections.jade | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index 8731c5ce0ca..708e6c09b98 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -29,13 +29,14 @@ block content :markdown The following option keys are available: - db - passed to the [underlying driver's db instance](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) - server - passed to the [underlying driver's server instance(s)](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) - replset - passed to the [underlying driver's ReplSet instance](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) - user - username for authentication (if not specified in uri) - pass - password for authentication (if not specified in uri) - auth - options for authentication - mongos - passed to the [underlying driver's mongos options](http://mongodb.github.io/node-mongodb-native/2.0/api/Mongos.html) + db - passed to the [underlying driver's db instance](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) + server - passed to the [underlying driver's server instance(s)](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + replset - passed to the [underlying driver's ReplSet instance](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) + user - username for authentication (if not specified in uri) + pass - password for authentication (if not specified in uri) + auth - options for authentication + mongos - passed to the [underlying driver's mongos options](http://mongodb.github.io/node-mongodb-native/2.1/api/Mongos.html) + promiseLibrary - sets the [underlying driver's promise library](http://mongodb.github.io/node-mongodb-native/2.1/api/MongoClient.html) Example: :js var options = { From c4f316aeae81b729cd7e1a3ab9541777401e1f90 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Jul 2016 12:47:36 -0700 Subject: [PATCH 0731/2240] docs(schema): improve post hook docs on schema Fix #4238 --- lib/schema.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 73655c09093..f228ccbf9d3 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -928,23 +928,31 @@ Schema.prototype.pre = function() { /** * Defines a post hook for the document * - * Post hooks fire `on` the event emitted from document instances of Models compiled from this schema. - * * var schema = new Schema(..); * schema.post('save', function (doc) { * console.log('this fired after a document was saved'); * }); * + * shema.post('find', function(docs) { + * console.log('this fired after you run a find query'); + * }); + * * var Model = mongoose.model('Model', schema); * * var m = new Model(..); - * m.save(function (err) { + * m.save(function(err) { * console.log('this fires after the `post` hook'); * }); * + * m.find(function(err, docs) { + * console.log('this fires after the post find hook'); + * }); + * * @param {String} method name of the method to hook * @param {Function} fn callback - * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3 + * @see middleware http://mongoosejs.com/docs/middleware.html + * @see hooks.js https://www.npmjs.com/package/hooks-fixed + * @see kareem http://npmjs.org/package/kareem * @api public */ From 0b0fb8c6f462335befd42282176404c59378826b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Jul 2016 12:50:50 -0700 Subject: [PATCH 0732/2240] docs: fix link to cursor --- docs/queries.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/queries.jade b/docs/queries.jade index 5a920028519..3ce822f70cd 100644 --- a/docs/queries.jade +++ b/docs/queries.jade @@ -87,7 +87,7 @@ block content :markdown You can [stream](http://nodejs.org/api/stream.html) query results from MongoDB. You need to call the - [Query#cursor()](./api.html#query_Query-stream) function instead of + [Query#cursor()](./api.html#query_Query-cursor) function instead of [Query#exec](./api.html#query_Query-exec) to return an instance of [QueryCursor](./api.html#querycursor-js). :js From a2585a5c041140af3db3d15af9618ad98cb8e0d0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Jul 2016 13:05:52 -0700 Subject: [PATCH 0733/2240] chore: release 4.5.6 --- History.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index b5cce319052..c76704e71fe 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,15 @@ +4.5.6 / 2016-07-23 +================== + * fix(schema): don't overwrite createdAt if it isn't selected #4351 [tusbar](https://github.com/tusbar) + * docs(api): fix link to populate() and add a new one from depopulate() #4345 [Delapouite](https://github.com/Delapouite) + * fix(types): ownerDocument() works properly with single nested docs #4344 [vichle](https://github.com/vichle) + * fix(populate): dont use findOne when justOne option set #4329 + * fix(document): dont trigger .then() deprecated warning when calling doc.remove() #4291 + * docs(connection): add promiseLibrary option #4280 + * fix(plugins): apply global plugins to subschemas #4271 + * fix(model): ensure `ensureIndex()` never calls back in the same tick #4246 + * docs(schema): improve post hook docs on schema #4238 + 4.5.5 / 2016-07-18 ================== * fix(document): handle setting root to empty obj if minimize false #4337 diff --git a/package.json b/package.json index ca07d73f31d..203f34e4835 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.6-pre", + "version": "4.5.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 8410d8041956357c7697abad133b67590e3f21c3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Jul 2016 13:19:44 -0700 Subject: [PATCH 0734/2240] fix: upgrade mongodb -> 2.2.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 203f34e4835..bc3ccb7257d 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.23", "hooks-fixed": "1.2.0", "kareem": "1.1.3", - "mongodb": "2.1.18", + "mongodb": "2.2.4", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.11.0", From d81b0c73c2a9593ab6a7de34ba674527e90c83da Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Jul 2016 13:20:17 -0700 Subject: [PATCH 0735/2240] fix(test): handle mongos connection failure correctly --- test/connection.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/connection.test.js b/test/connection.test.js index 987786dc6fe..8afded32c42 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -1057,7 +1057,9 @@ describe('connections:', function() { it('connecting to single mongos (gh-3537)', function(done) { var db = mongoose.createConnection('localhost:27017', {mongos: true}); assert.ok(db.db.serverConfig instanceof mongoose.mongo.Mongos); - db.close(done); + db.on('error', function() { + done(); + }); }); describe('connecting to multiple mongos nodes (gh-1037)', function() { From c57ccf993f24e8955320c9878046edbff329faf3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Jul 2016 13:46:38 -0700 Subject: [PATCH 0736/2240] fix(test): correct assertion issue --- test/model.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.test.js b/test/model.test.js index 2cbd7d59f65..d86ce4ac8fc 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -4111,7 +4111,7 @@ describe('Model', function() { promise.onResolve(function(err, found) { db.close(); assert.ifError(err); - assert.equal(found._id.id, created._id.id); + assert.equal(found._id.toHexString(), created._id.toHexString()); done(); }); }); From e2b32cb6337beaa18db6689133380edc3e04c2a1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Jul 2016 14:11:11 -0700 Subject: [PATCH 0737/2240] fix: dont try to connect to nonexistent mongos in tests --- lib/connection.js | 4 +++- test/connection.test.js | 27 ++++++++++++--------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 154aeb5b0f5..796ebd2c30b 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -417,12 +417,14 @@ Connection.prototype.openSet = function(uris, database, options, callback) { var _this = this; var Promise = PromiseProvider.get(); + var emitted = false; var promise = new Promise.ES6(function(resolve, reject) { _this._open(true, function(error) { callback && callback(error); if (error) { reject(error); - if (!callback && !promise.$hasHandler) { + if (!callback && !promise.$hasHandler && !emitted) { + emitted = true; _this.emit('error', error); } return; diff --git a/test/connection.test.js b/test/connection.test.js index 8afded32c42..2ddd6361da5 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -2,11 +2,12 @@ * Module dependencies. */ -var start = require('./common'), - assert = require('power-assert'), - mongoose = start.mongoose, - Schema = mongoose.Schema, - random = require('../lib/utils').random; +var start = require('./common'); +var assert = require('power-assert'); +var mongoose = start.mongoose; +var Schema = mongoose.Schema; +var random = require('../lib/utils').random; +var muri = require('muri'); /** * Test. @@ -563,9 +564,8 @@ describe('connections:', function() { + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags=' + 'dc:ny,rack:1&readPreferenceTags=dc:sf&sslValidate=true'; - var db = mongoose.createConnection(conn, {mongos: true}); - db.on('error', done); - db.close(); + var db = new mongoose.Connection(); + db.options = db.parseOptions({mongos: true}, muri(conn).options); assert.equal(typeof db.options, 'object'); assert.equal(typeof db.options.server, 'object'); assert.equal(typeof db.options.server.socketOptions, 'object'); @@ -610,9 +610,8 @@ describe('connections:', function() { + 'dc:ny,rack:1&readPreferenceTags=dc:sf&sslValidate=true' + newQueryParam; - var db = mongoose.createConnection(conn); - db.on('error', done); - db.close(); + var db = new mongoose.Connection(); + db.options = db.parseOptions({}, muri(conn).options); assert.strictEqual(typeof db.options, 'object'); assert.strictEqual(typeof db.options.server, 'object'); assert.strictEqual(typeof db.options.server.socketOptions, 'object'); @@ -655,9 +654,8 @@ describe('connections:', function() { + '&wtimeoutMS=80&readPreference=nearest&readPreferenceTags=' + 'dc:ny,rack:1&readPreferenceTags=dc:sf&sslValidate=true'; - var db = mongoose.createConnection(conn, {mongos: {w: 3, wtimeoutMS: 80}}); - db.on('error', done); - db.close(); + var db = new mongoose.Connection(); + db.options = db.parseOptions({mongos: {w: 3,wtimeoutMS: 80}}, muri(conn).options); assert.equal(typeof db.options, 'object'); assert.equal(typeof db.options.server, 'object'); assert.equal(typeof db.options.server.socketOptions, 'object'); @@ -684,7 +682,6 @@ describe('connections:', function() { assert.equal(db.options.db.safe, true); assert.equal(db.options.db.fsync, true); assert.equal(db.options.db.journal, true); - assert.equal(db.options.db.wtimeoutMS, 80); assert.equal(db.options.db.readPreference, 'nearest'); assert.deepEqual([{dc: 'ny', rack: 1}, {dc: 'sf'}], db.options.db.read_preference_tags); assert.equal(db.options.db.forceServerObjectId, false); From d9fdd14b4937d4ef388e2d345fc8cda1b4c8b032 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 24 Jul 2016 11:30:00 -0700 Subject: [PATCH 0738/2240] chore: now working on 4.5.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 203f34e4835..c4245e1889f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.6", + "version": "4.5.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e27430f12b050f5657abbd04b9957fac6b0e3367 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 25 Jul 2016 07:04:53 -0700 Subject: [PATCH 0739/2240] fix(document): ensure no unhandled rejections if callback specified for save Fix #4364 --- lib/document.js | 39 ++++++++++++++++++++++++++--------- test/promise_provider.test.js | 20 ++++++++++++++---- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/lib/document.js b/lib/document.js index 9302b04a449..056133b9103 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1880,14 +1880,15 @@ Document.prototype.$__registerHooksFromSchema = function() { var lastArg = args.pop(); var fn; var originalStack = new Error().stack; + var $results; + if (lastArg && typeof lastArg !== 'function') { + args.push(lastArg); + } else { + fn = lastArg; + } - return new Promise.ES6(function(resolve, reject) { - if (lastArg && typeof lastArg !== 'function') { - args.push(lastArg); - } else { - fn = lastArg; - } - args.push(function(error, result) { + var promise = new Promise.ES6(function(resolve, reject) { + args.push(function(error) { if (error) { // gh-2633: since VersionError is very generic, take the // stack trace of the original save() function call rather @@ -1896,17 +1897,35 @@ Document.prototype.$__registerHooksFromSchema = function() { error.stack = originalStack; } _this.$__handleReject(error); - fn && fn(error); reject(error); return; } - fn && fn.apply(null, [null].concat(Array.prototype.slice.call(arguments, 1))); - resolve(result); + // There may be multiple results and promise libs other than + // mpromise don't support passing multiple values to `resolve()` + $results = Array.prototype.slice.call(arguments, 1); + resolve.apply(promise, $results); }); _this[newName].apply(_this, args); }); + if (fn) { + if (_this.constructor.$wrapCallback) { + fn = _this.constructor.$wrapCallback(fn); + } + return promise.then( + function() { + process.nextTick(function() { + fn.apply(null, [null].concat($results)); + }); + }, + function(error) { + process.nextTick(function() { + fn(error); + }); + }); + } + return promise; }; toWrap[pointCut].pre.forEach(function(args) { diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js index c5dcf1204ca..994ace1e54e 100644 --- a/test/promise_provider.test.js +++ b/test/promise_provider.test.js @@ -192,12 +192,18 @@ describe('ES6 promises: ', function() { }); it('save()', function(done) { - var m = new MyModel({test: '123'}); + var m = new MyModel({ test: '123' }); var promise = m.save(); assert.equal(promise.constructor, bluebird); promise.then(function(doc) { assert.equal(m, doc); - done(); + m.test = '456'; + m.save(function(error, doc, numAffected) { + assert.ifError(error); + assert.ok(doc); + assert.equal(numAffected, 1); + done(); + }); }); }); @@ -217,7 +223,7 @@ describe('ES6 promises: ', function() { }); it('save() with middleware error', function(done) { - var m = new MyModel({test: '123'}); + var m = new MyModel({ test: '123' }); m.$__saveSucceeds = false; var promise = m.save(); assert.equal(promise.constructor, bluebird); @@ -228,7 +234,13 @@ describe('ES6 promises: ', function() { catch(function(err) { assert.ok(err); assert.equal(err.toString(), 'Error: fail'); - done(); + + // Shouldn't log an unhandled rejection error + m.save(function(err) { + assert.ok(err); + assert.equal(err.toString(), 'Error: fail'); + done(); + }); }); }); From d5f16106dc6e52f72864ec3455b5dd28851cb883 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 25 Jul 2016 07:18:45 -0700 Subject: [PATCH 0740/2240] chore: release 4.5.7 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c76704e71fe..d1dfa93da5a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +4.5.7 / 2016-07-25 +================== + * fix(document): ensure no unhandled rejections if callback specified for save #4364 + 4.5.6 / 2016-07-23 ================== * fix(schema): don't overwrite createdAt if it isn't selected #4351 [tusbar](https://github.com/tusbar) diff --git a/package.json b/package.json index c4245e1889f..a14d0a37bca 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.7-pre", + "version": "4.5.7", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From facc22968f3672eefc873de822bbb303e12ee7b6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 26 Jul 2016 15:55:21 -0700 Subject: [PATCH 0741/2240] chore: now working on 4.5.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a14d0a37bca..d81d551b972 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.7", + "version": "4.5.8-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c99434aa79e030185f2ce16278c58ebaf72e96d1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 26 Jul 2016 16:09:18 -0700 Subject: [PATCH 0742/2240] test(querycursor): repro #4355 --- test/query.cursor.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index 48b56f2d11e..f6da3c46ecd 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -117,6 +117,19 @@ describe('QueryCursor', function() { }); }); }); + + it('casting ObjectIds with where() (gh-4355)', function(done) { + Model.findOne(function(error, doc) { + assert.ifError(error); + assert.ok(doc); + var query = { _id: doc._id.toHexString() }; + Model.find().where(query).cursor().next(function(error, doc) { + assert.ifError(error); + assert.ok(doc); + done(); + }); + }); + }); }); it('as readable stream', function(done) { From a8499faa4f25d58ecfee4c3788e18d7ca02d0c4f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 26 Jul 2016 16:09:52 -0700 Subject: [PATCH 0743/2240] fix(querycursor): always cast fields before returning cursor Fix #4355 --- lib/query.js | 7 +++++++ lib/querycursor.js | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/lib/query.js b/lib/query.js index 7e3a44df6bd..2cf74ad1fdc 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2876,6 +2876,13 @@ Query.prototype.cursor = function cursor(opts) { if (opts) { this.setOptions(opts); } + + try { + this.cast(this.model); + } catch (err) { + return (new QueryCursor(this, this.options))._markError(err); + } + return new QueryCursor(this, this.options); }; diff --git a/lib/querycursor.js b/lib/querycursor.js index 2b9bcadf09e..c1e2ca9131c 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -34,6 +34,11 @@ function QueryCursor(query, options) { var _this = this; var model = query.model; model.collection.find(query._conditions, options, function(err, cursor) { + if (_this._error) { + return cursor.close(function() { + _this.emit('error', _this.error); + }); + } if (err) { return _this.emit('error', err); } @@ -67,6 +72,34 @@ QueryCursor.prototype._read = function() { }); }; +/*! + * Marks this cursor as errored + */ + +QueryCursor.prototype._markError = function(error) { + this._error = error; + return this; +}; + +QueryCursor.prototype._read = function() { + var _this = this; + _next(this, function(error, doc) { + if (error) { + return _this.emit('error', error); + } + if (!doc) { + _this.push(null); + return _this.cursor.close(function(error) { + if (error) { + return _this.emit('error', error); + } + _this.emit('close'); + }); + } + _this.push(doc); + }); +}; + /** * Marks this cursor as closed. Will stop streaming and subsequent calls to * `next()` will error. @@ -183,6 +216,12 @@ QueryCursor.prototype.eachAsync = function(fn, callback) { */ function _next(ctx, callback) { + if (ctx._error) { + return process.nextTick(function() { + callback(ctx._error); + }); + } + if (ctx.cursor) { ctx.cursor.next(function(error, doc) { if (error) { From 921192a2ef1c25c3f5cca0c729aeaf958b5d8451 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 26 Jul 2016 16:15:53 -0700 Subject: [PATCH 0744/2240] fix(querycursor): correct some cast error handling issues Re: #4355 --- lib/querycursor.js | 27 ++++----------------------- test/query.cursor.test.js | 9 +++++++++ 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/lib/querycursor.js b/lib/querycursor.js index c1e2ca9131c..3779df08372 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -35,9 +35,8 @@ function QueryCursor(query, options) { var model = query.model; model.collection.find(query._conditions, options, function(err, cursor) { if (_this._error) { - return cursor.close(function() { - _this.emit('error', _this.error); - }); + cursor.close(function() {}); + _this.listeners('error').length > 0 && _this.emit('error', _this._error); } if (err) { return _this.emit('error', err); @@ -81,25 +80,6 @@ QueryCursor.prototype._markError = function(error) { return this; }; -QueryCursor.prototype._read = function() { - var _this = this; - _next(this, function(error, doc) { - if (error) { - return _this.emit('error', error); - } - if (!doc) { - _this.push(null); - return _this.cursor.close(function(error) { - if (error) { - return _this.emit('error', error); - } - _this.emit('close'); - }); - } - _this.push(doc); - }); -}; - /** * Marks this cursor as closed. Will stop streaming and subsequent calls to * `next()` will error. @@ -120,7 +100,8 @@ QueryCursor.prototype.close = function(callback) { if (error) { callback && callback(error); reject(error); - return _this.emit('error', error); + return _this.listeners('error').length > 0 && + _this.emit('error', error); } _this.emit('close'); resolve(); diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index f6da3c46ecd..04917c24530 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -130,6 +130,15 @@ describe('QueryCursor', function() { }); }); }); + + it('cast errors (gh-4355)', function(done) { + Model.find().where({ _id: 'BadId' }).cursor().next(function(error) { + assert.ok(error); + assert.equal(error.name, 'CastError'); + assert.equal(error.path, '_id'); + done(); + }); + }); }); it('as readable stream', function(done) { From ed78511e03f81814883b082e22d1038e738a7dda Mon Sep 17 00:00:00 2001 From: Adam Buczynski Date: Wed, 27 Jul 2016 12:15:31 +1200 Subject: [PATCH 0745/2240] Support multiple paths for isModified --- lib/document.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/document.js b/lib/document.js index 056133b9103..0242dad6511 100644 --- a/lib/document.js +++ b/lib/document.js @@ -989,20 +989,28 @@ Document.prototype.modifiedPaths = function() { * ####Example * * doc.set('documents.0.title', 'changed'); - * doc.isModified() // true - * doc.isModified('documents') // true - * doc.isModified('documents.0.title') // true - * doc.isDirectModified('documents') // false + * doc.isModified() // true + * doc.isModified('documents') // true + * doc.isModified('documents.0.title') // true + * doc.isModified('documents otherProp') // true + * doc.isDirectModified('documents') // false * * @param {String} [path] optional * @return {Boolean} * @api public */ -Document.prototype.isModified = function(path) { - return path - ? !!~this.modifiedPaths().indexOf(path) - : this.$__.activePaths.some('modify'); +Document.prototype.isModified = function(paths) { + if (paths) { + if (!Array.isArray(paths)) { + paths = paths.split(' '); + } + var modified = this.modifiedPaths(); + return paths.some(function(path) { + return !!~modified.indexOf(path); + }); + } + return this.$__.activePaths.some('modify'); }; /** From 43bba0db0fdc0367a1ca05c196f7d6646da60ed7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Jul 2016 15:08:58 -0700 Subject: [PATCH 0746/2240] test(schema): repro #4304 --- test/schema.test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 28436d80397..0d7152daead 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -850,6 +850,12 @@ describe('schema', function() { assert.equal(i.sparse, true); assert.equal(i.expireAfterSeconds, 60 * 60 * 24); + T = new Schema({ + name: {type: String, index: false, unique: false} + }); + assert.equal(T.path('name')._index, false); + assert.equal(T.indexes().length, 0); + done(); }); it('compound', function(done) { From ecbfcc8d2228d5f45a5d7dece81563bbe6efbce1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Jul 2016 15:09:15 -0700 Subject: [PATCH 0747/2240] fix(schema): treat index false + unique false as no index Fix #4304 --- lib/schematype.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/schematype.js b/lib/schematype.js index 081f421b440..3cf90bbe600 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -148,8 +148,14 @@ SchemaType.prototype.index = function(options) { */ SchemaType.prototype.unique = function(bool) { - if (this._index === null || this._index === undefined || - typeof this._index === 'boolean') { + if (this._index === false) { + if (!bool) { + return; + } + throw new Error('Path "' + this.path + '" may not have `index` set to ' + + 'false and `unique` set to true'); + } + if (this._index == null || this._index === true) { this._index = {}; } else if (typeof this._index === 'string') { this._index = {type: this._index}; From 671ef5b95fddecf101bf9960fc4a912215a14b68 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Jul 2016 15:31:02 -0700 Subject: [PATCH 0748/2240] test(document): repro #4224 --- test/document.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 10442ceefdf..dbdae2906fa 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3071,5 +3071,23 @@ describe('document', function() { } done(); }); + + it('doesnt markModified child paths if parent is modified (gh-4224)', function(done) { + var childSchema = new Schema({ + name: String + }); + var parentSchema = new Schema({ + child: childSchema + }); + + var Parent = db.model('gh4224', parentSchema); + Parent.create({ child: { name: 'Jacen' } }, function(error, doc) { + assert.ifError(error); + doc.child = { name: 'Jaina' }; + doc.child.name = 'Anakin'; + assert.deepEqual(doc.modifiedPaths(), ['child']); + done(); + }); + }); }); }); From 9aa42574d8f1bb8dd3a5f23c287350f239b012cc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Jul 2016 15:35:05 -0700 Subject: [PATCH 0749/2240] fix(types): dont mark single nested subpath as modified if whole doc already modified Fix #4224 --- lib/types/subdocument.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index d617254d00c..cf295c2895a 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -46,6 +46,9 @@ Subdocument.prototype.$isValid = function(path) { Subdocument.prototype.markModified = function(path) { Document.prototype.markModified.call(this, path); if (this.$parent) { + if (this.$parent.isModified(this.$basePath)) { + return; + } this.$parent.markModified([this.$basePath, path].join('.')); } }; From dd04f0b159a2d1530368ec52c65b8031ccb36b37 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Jul 2016 07:08:37 -0700 Subject: [PATCH 0750/2240] fix(model): use set immediate consistently rather than nextTick() Re: https://github.com/Automattic/mongoose/commit/b24c8b9936d72768a983977e4b6b188fe543235c#commitcomment-18359829 --- lib/model.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index 5f489bf904b..5e1a622c43e 100644 --- a/lib/model.js +++ b/lib/model.js @@ -968,7 +968,7 @@ Model.ensureIndexes = function ensureIndexes(options, callback) { function _ensureIndexes(model, callback) { var indexes = model.schema.indexes(); if (!indexes.length) { - process.nextTick(function() { + setImmediate(function() { callback && callback(); }); return; @@ -1010,7 +1010,7 @@ function _ensureIndexes(model, callback) { })); }; - process.nextTick(function() { + setImmediate(function() { create(); }); } @@ -1825,7 +1825,7 @@ Model.create = function create(doc, callback) { var promise = new Promise.ES6(function(resolve, reject) { if (args.length === 0) { - process.nextTick(function() { + setImmediate(function() { cb && cb(null); resolve(null); }); From 88ec4afb28b95501dfe0da17831fb8300867e774 Mon Sep 17 00:00:00 2001 From: Dhananjoy Biswas Date: Thu, 28 Jul 2016 04:16:48 +0600 Subject: [PATCH 0751/2240] fix(query): pass projection fields to cursor Fix #4342 --- lib/query.js | 1 + test/query.cursor.test.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib/query.js b/lib/query.js index 2cf74ad1fdc..127c62e0328 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2873,6 +2873,7 @@ Query.prototype.stream = util.deprecate(Query.prototype.stream, 'Mongoose: ' + Query.prototype.cursor = function cursor(opts) { this._applyPaths(); this._fields = this._castFields(this._fields); + this.setOptions({ fields: this._fieldsForExec() }); if (opts) { this.setOptions(opts); } diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index 04917c24530..9dc47ab420c 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -72,6 +72,35 @@ describe('QueryCursor', function() { }); }); + it('with projection', function(done) { + var personSchema = new Schema({ + name: String, + born: String + }); + var Person = db.model('Person4342', personSchema); + var people = [ + { name: 'Axl Rose', born: 'William Bruce Rose' }, + { name: 'Slash', born: 'Saul Hudson' } + ]; + Person.create(people, function(error) { + assert.ifError(error); + var cursor = Person.find({}, { _id: 0, name: 1 }).sort({ name: 1 }).cursor(); + cursor.next(function(error, doc) { + assert.ifError(error); + assert.equal(doc._id, undefined); + assert.equal(doc.name, 'Axl Rose'); + assert.equal(doc.born, undefined); + cursor.next(function(error, doc) { + assert.ifError(error); + assert.equal(doc._id, undefined); + assert.equal(doc.name, 'Slash'); + assert.equal(doc.born, undefined); + done(); + }); + }); + }); + }); + it('with populate', function(done) { var bandSchema = new Schema({ name: String, From 37325fdabbc788445fe79558b3b3bbd6913b5695 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Jul 2016 16:15:43 -0700 Subject: [PATCH 0752/2240] test(query): repro #4315 --- test/model.findOneAndUpdate.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 00d82a4dc9a..f564181c071 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1682,5 +1682,21 @@ describe('model: findByIdAndUpdate:', function() { done(); }); }); + + it('projection option as alias for fields (gh-4315)', function(done) { + var TestSchema = new Schema({ + test1: String, + test2: String + }); + var Test = db.model('gh4315', TestSchema); + var update = { $set: { test1: 'a', test2: 'b' } }; + var options = { projection: { test2: 0 }, new: true, upsert: true }; + Test.findOneAndUpdate({}, update, options, function(error, doc) { + assert.ifError(error); + assert.ok(!doc.test2); + assert.equal(doc.test1, 'a'); + done(); + }); + }); }); }); From 470ec21d43fe274547e768bb9cdb67cef6885acd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Jul 2016 16:15:45 -0700 Subject: [PATCH 0753/2240] fix(query): support projection as alias for fields in findOneAndUpdate Fix #4315 --- lib/query.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 2cf74ad1fdc..fdec262ee72 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1643,7 +1643,19 @@ Query.prototype.findOneAndUpdate = function(criteria, doc, options, callback) { this._mergeUpdate(doc); } - options && this.setOptions(options); + if (options) { + options = utils.clone(options, { retainKeyOrder: true }); + if (options.projection) { + this.select(options.projection); + delete options.projection; + } + if (options.fields) { + this.select(options.fields); + delete options.fields; + } + + this.setOptions(options); + } if (!callback) { return this; From 1d4d0fdbe2da34b0b5231d9997b4bcdf016d67a8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Jul 2016 16:39:47 -0700 Subject: [PATCH 0754/2240] fix: upgrade to driver 2.2.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e5f4e28608d..93247f1bb1c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.23", "hooks-fixed": "1.2.0", "kareem": "1.1.3", - "mongodb": "2.2.4", + "mongodb": "2.2.5", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.11.0", From 5d1f0526108faecf0bb9459e893c9428bd5eb1e4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Jul 2016 13:28:51 -0700 Subject: [PATCH 0755/2240] chore: upgrade dev dependencies --- package.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index d81d551b972..74ec3d7362d 100644 --- a/package.json +++ b/package.json @@ -35,24 +35,23 @@ "devDependencies": { "acquit": "0.4.1", "acquit-ignore": "0.0.3", - "benchmark": "2.0.0", - "bluebird": "3.4.0", + "bluebird": "3.4.1", "co": "4.6.0", "dox": "0.3.1", "eslint": "2.4.0", "highlight.js": "7.0.1", - "istanbul": "0.4.2", + "istanbul": "0.4.4", "jade": "0.26.3", - "lodash": "4.6.1", + "lodash": "4.14.1", "markdown": "0.3.1", - "marked": "0.3.5", + "marked": "0.3.6", "mocha": "2.3.4", "mongoose-long": "0.1.0", "node-static": "0.7.7", "power-assert": "1.2.0", "q": "1.4.1", "tbd": "0.6.4", - "uglify-js": "2.6.1", + "uglify-js": "2.7.0", "underscore": "1.8.3", "validator": "5.4.0" }, From 8dde71f34cd75a5de4bb696340c3c53cf5c263f6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Jul 2016 13:30:09 -0700 Subject: [PATCH 0756/2240] docs: add slack channel to replace irc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f5326cab0f..9bda25def25 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed - [bug reports](https://github.com/Automattic/mongoose/issues/) - [help forum](http://groups.google.com/group/mongoose-orm) - [MongoDB support](https://docs.mongodb.org/manual/support/) - - (irc) #mongoosejs on freenode + - [Mongoose Slack Channel](https://mongoosejs.slack.com/) ## Plugins From e1c2f3e94c7d8ba7020a504d4e733c0b7aef2ed6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 31 Jul 2016 16:33:21 -0700 Subject: [PATCH 0757/2240] test(model): repro #4374 --- test/model.discriminator.test.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index f9107e11baf..82522378cbe 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -38,9 +38,6 @@ PersonSchema.virtual('name.full').set(function(name) { PersonSchema.path('gender').validate(function(value) { return /[A-Z]/.test(value); }, 'Invalid name'); -PersonSchema.post('save', function(next) { - next(); -}); PersonSchema.set('toObject', {getters: true, virtuals: true}); PersonSchema.set('toJSON', {getters: true, virtuals: true}); @@ -319,7 +316,7 @@ describe('model', function() { }); it('merges callQueue with base queue defined before discriminator types callQueue', function(done) { - assert.equal(Employee.schema.callQueue.length, 6); + assert.equal(Employee.schema.callQueue.length, 5); // PersonSchema.post('save') assert.strictEqual(Employee.schema.callQueue[0], Person.schema.callQueue[0]); @@ -353,7 +350,12 @@ describe('model', function() { it('does not allow setting discriminator key (gh-2041)', function(done) { var doc = new Employee({ __t: 'fake' }); assert.equal(doc.__t, 'model-discriminator-employee'); - done(); + doc.save(function(error) { + assert.ok(error); + assert.equal(error.errors['__t'].reason.message, + 'Can\'t set discriminator key "__t"'); + done(); + }); }); }); }); From f16a447746de0154807bf4452c812a78b60c5c85 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 31 Jul 2016 16:33:50 -0700 Subject: [PATCH 0758/2240] fix(model): make changing the discriminator key cause a cast error Fix #4374 --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 5e1a622c43e..81c8a13479f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -807,7 +807,7 @@ Model.discriminator = function discriminator(name, schema) { type: String, default: name, set: function() { - return name; + throw new Error('Can\'t set discriminator key "' + key + '"'); } }; schema.add(obj); From 2dcde9fe9b6047dae52f1ba3ba276dd9d89b4979 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 1 Aug 2016 15:17:39 -0700 Subject: [PATCH 0759/2240] chore: release 4.5.8 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index d1dfa93da5a..55405f136a6 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.5.8 / 2016-08-01 +================== + * fix(model): make changing the discriminator key cause a cast error #4374 + * fix(query): pass projection fields to cursor #4371 #4342 [Corei13](https://github.com/Corei13) + * fix(document): support multiple paths for isModified #4370 [adambuczynski](https://github.com/adambuczynski) + * fix(querycursor): always cast fields before returning cursor #4355 + * fix(query): support projection as alias for fields in findOneAndUpdate #4315 + * fix(schema): treat index false + unique false as no index #4304 + * fix(types): dont mark single nested subpath as modified if whole doc already modified #4224 + 4.5.7 / 2016-07-25 ================== * fix(document): ensure no unhandled rejections if callback specified for save #4364 diff --git a/package.json b/package.json index 74ec3d7362d..9c3cc1b593b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.8-pre", + "version": "4.5.8", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From bd49469d1f86e27186ceeb75fe60f5b065d4a2da Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 1 Aug 2016 15:20:14 -0700 Subject: [PATCH 0760/2240] chore: now working on 4.5.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c3cc1b593b..3cc173dcdc6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.8", + "version": "4.5.9-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 6d4528dd3783493ee4dd15fe2e5567d2db6823d5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 3 Aug 2016 15:47:48 -0700 Subject: [PATCH 0761/2240] test(document): repro #4369 --- test/document.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index dbdae2906fa..32729cd65de 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3089,5 +3089,30 @@ describe('document', function() { done(); }); }); + + it('single nested isNew (gh-4369)', function(done) { + var childSchema = new Schema({ + name: String + }); + var parentSchema = new Schema({ + child: childSchema + }); + + var Parent = db.model('gh4369', parentSchema); + var remaining = 2; + + var doc = new Parent({ child: { name: 'Jacen' } }); + doc.child.on('isNew', function(val) { + assert.ok(!val); + assert.ok(!doc.child.isNew); + --remaining || done(); + }); + + doc.save(function(error, doc) { + assert.ifError(error); + assert.ok(!doc.child.isNew); + --remaining || done(); + }); + }); }); }); From e6d04fe76c51f054d7a7c413daa7dea1893a95a7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 3 Aug 2016 15:47:52 -0700 Subject: [PATCH 0762/2240] fix(document): set single nested doc isNew correctly Fix #4369 --- lib/schema/embedded.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index fd496af2feb..3f8a157f6b1 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -30,6 +30,11 @@ function Embedded(schema, path, options) { parent.on('save', function() { _this.emit('save', _this); }); + + parent.on('isNew', function(val) { + _this.isNew = val; + _this.emit('isNew', val); + }); } }; _embedded.prototype = Object.create(Subdocument.prototype); From 2dc25827a8621d10fb5e0ebeb19beae98dcfbbfc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 Aug 2016 20:14:14 -0400 Subject: [PATCH 0763/2240] Chore: remove more unused makefile rules --- Makefile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Makefile b/Makefile index a2681d2f1fe..89f2bdc0f78 100644 --- a/Makefile +++ b/Makefile @@ -65,9 +65,3 @@ browser: npm install `node format_deps.js` ./node_modules/browserify/bin/cmd.js -o ./bin/mongoose.js lib/browser.js ./node_modules/uglify-js/bin/uglifyjs ./bin/mongoose.js -o ./bin/mongoose.min.js --screw-ie8 -c -m - -browser_debug: - ./node_modules/browserify/bin/cmd.js -o ./bin/mongoose.debug.js lib/browser.js -d - -test_browser: - ./node_modules/karma/bin/karma start karma.local.conf.js From 7a0a8e3fb011afdd16f8a4199fdcda563726c329 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 Aug 2016 20:17:29 -0400 Subject: [PATCH 0764/2240] Docs: add missing space --- docs/connections.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/connections.jade b/docs/connections.jade index 708e6c09b98..dee15b8392f 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -98,7 +98,7 @@ block content options.server.socketOptions = options.replset.socketOptions = { keepAlive: 120 }; mongoose.connect(uri, options); - h3#replicaset_connections ReplicaSet Connections + h3#replicaset_connections Replica Set Connections :markdown The same method is used to connect to a replica set but instead of passing a single `uri` we pass a comma delimited list of `uri`s. From 55e601a173eabc7d9ae8055aa45c2026a1daba15 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 Aug 2016 17:23:11 -0700 Subject: [PATCH 0765/2240] docs(connections): clarify connecting to single node repl set --- docs/connections.jade | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/connections.jade b/docs/connections.jade index dee15b8392f..954f5d9d5ce 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -100,11 +100,18 @@ block content h3#replicaset_connections Replica Set Connections :markdown - The same method is used to connect to a replica set but instead of passing a single `uri` we pass a comma delimited list of `uri`s. + To connect to a replica set you pass a comma delimited list of hosts to + connect to rather than a single host. :js mongoose.connect('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]' [, options]); + :markdown + To connect to a single node replica set, specify the `replicaSet` option. + + :js + mongoose.connect('mongodb://host1:port1/?replicaSet=rsName'); + h3#mongos_connections Multi-mongos support :markdown High availability over multiple `mongos` instances is also supported. Pass a connection string for your `mongos` instances and set the `mongos` option to true: From 845642f38c7a29e52101452514ea05d0be176543 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Aug 2016 08:41:00 -0700 Subject: [PATCH 0766/2240] test(services): repro #4332 --- test/model.update.test.js | 36 ++++++++++++++++++++++++++++++ test/updateValidators.unit.test.js | 18 +++++++++------ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index fec8f4f3d80..11cdcc1f772 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1837,6 +1837,42 @@ describe('model: update:', function() { }); }); + it('update validators on single nested (gh-4332)', function(done) { + var AreaSchema = new Schema({ + a: String + }); + + var CompanySchema = new Schema({ + area: { + type: AreaSchema, + validate: { + validator: function() { + return false; + }, + message: 'Not valid Area' + } + } + }); + + var Company = mongoose.model('Company', CompanySchema); + + var update = { + area: { + a: 'Helo' + } + }; + + var opts = { + runValidators: true + }; + + Company.update({}, update, opts, function(error) { + assert.ok(error); + assert.equal(error.errors['area'].message, 'Not valid Area'); + done(); + }); + }); + it('update handles casting with mongoose-long (gh-4283)', function(done) { require('mongoose-long')(mongoose); diff --git a/test/updateValidators.unit.test.js b/test/updateValidators.unit.test.js index 1052a45c0fa..34f645d548f 100644 --- a/test/updateValidators.unit.test.js +++ b/test/updateValidators.unit.test.js @@ -28,12 +28,17 @@ describe('updateValidators', function() { }); fn(function(err) { assert.ifError(err); - assert.equal(schema._getSchema.calls.length, 2); - assert.equal(schema.doValidate.calls.length, 2); - assert.equal(schema._getSchema.calls[0], 'test.a'); - assert.equal(schema._getSchema.calls[1], 'test.b'); - assert.equal(schema.doValidate.calls[0].v, 1); - assert.equal(schema.doValidate.calls[1].v, null); + assert.equal(schema._getSchema.calls.length, 3); + assert.equal(schema.doValidate.calls.length, 3); + assert.equal(schema._getSchema.calls[0], 'test'); + assert.equal(schema._getSchema.calls[1], 'test.a'); + assert.equal(schema._getSchema.calls[2], 'test.b'); + assert.deepEqual(schema.doValidate.calls[0].v, { + a: 1, + b: null + }); + assert.equal(schema.doValidate.calls[1].v, 1); + assert.equal(schema.doValidate.calls[2].v, null); done(); }); }); @@ -70,4 +75,3 @@ describe('updateValidators', function() { }); }); }); - From 4926e1b259d4d28e92f1845bc9130c1d2abdea9a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Aug 2016 08:41:43 -0700 Subject: [PATCH 0767/2240] fix(services): run update validators on nested paths --- lib/services/common.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/services/common.js b/lib/services/common.js index 7c60a743cec..956aee54708 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -27,6 +27,7 @@ function flatten(update, path, options) { val = val.toObject({ virtuals: false }); } if (shouldFlatten(val)) { + result[path + key] = val; if (options && options.skipArrays && Array.isArray(val)) { continue; } From f5b654111920e746db7c668ac824a59fd05fbce9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Aug 2016 08:56:44 -0700 Subject: [PATCH 0768/2240] test(model): repro #4339 --- test/model.discriminator.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 82522378cbe..1401b41481e 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -357,6 +357,16 @@ describe('model', function() { done(); }); }); + + it('with typeKey (gh-4339)', function(done) { + var options = { typeKey: '$type', discriminatorKey: '_t' }; + var schema = new Schema({ test: { $type: String } }, options); + var Model = mongoose.model('gh4339', schema); + Model.discriminator('gh4339_0', new Schema({ + test2: String + }, options)); + done(); + }); }); }); }); From 8abbd257e62fdd8a02e0b9372c60502bae912351 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Aug 2016 08:56:47 -0700 Subject: [PATCH 0769/2240] fix(model): handle typeKey with discriminators Fix #4339 --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 81c8a13479f..08a6d16426c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -804,12 +804,12 @@ Model.discriminator = function discriminator(name, schema) { var obj = {}; obj[key] = { - type: String, default: name, set: function() { throw new Error('Can\'t set discriminator key "' + key + '"'); } }; + obj[key][schema.options.typeKey] = String; schema.add(obj); schema.discriminatorMapping = {key: key, value: name, isRoot: false}; From 14ee34e98996d643577eb559e32027ff56453368 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Aug 2016 14:14:52 -0700 Subject: [PATCH 0770/2240] test(schematype): repro #4390 --- test/document.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 32729cd65de..57546944ba5 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3114,5 +3114,24 @@ describe('document', function() { --remaining || done(); }); }); + + it('default values with subdoc array (gh-4390)', function(done) { + var childSchema = new Schema({ + name: String + }); + var parentSchema = new Schema({ + child: [childSchema] + }); + + parentSchema.path('child').default([{ name: 'test' }]); + + var Parent = db.model('gh4390', parentSchema); + + Parent.create({}, function(error, doc) { + assert.ifError(error); + assert.deepEqual(doc.toObject().child, [{ name: 'test' }]); + done(); + }); + }); }); }); From fdd050fbff03941762a3347bf73c5faf14dadaeb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Aug 2016 14:15:20 -0700 Subject: [PATCH 0771/2240] fix(schematype): dont cast defaults without parent doc Fix #4390 --- lib/schematype.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/schematype.js b/lib/schematype.js index 3cf90bbe600..a69be4533bd 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -91,9 +91,7 @@ SchemaType.prototype.default = function(val) { this.defaultValue = void 0; return void 0; } - this.defaultValue = typeof val === 'function' - ? val - : this.cast(val); + this.defaultValue = val; return this.defaultValue; } else if (arguments.length > 1) { this.defaultValue = utils.args(arguments); From 7e3538be8018197bd764f4f3033308c7c848351b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 Aug 2016 11:46:57 -0400 Subject: [PATCH 0772/2240] docs: improve contrib guide --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6575aae6c3e..904aeef38a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,7 @@ If you have a question about Mongoose (not a bug report) please post it to eithe - 2 space tabs - no trailing whitespace - inline documentation for new methods, class members, etc. - - 1 space between conditionals/functions, and their parenthesis and curly braces + - 1 space between conditionals, no space before function parenthesis - `if (..) {` - `for (..) {` - `while (..) {` @@ -53,4 +53,4 @@ If you'd like to preview your documentation changes, first commit your changes t ### Plugins website -The [plugins](http://plugins.mongoosejs.io/) site is also an [open source project](https://github.com/aheckmann/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! +The [plugins](http://plugins.mongoosejs.io/) site is also an [open source project](https://github.com/vkarpov15/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! From 767b6d290939cb56e4096f58214e399116c57109 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 Aug 2016 14:20:30 -0700 Subject: [PATCH 0773/2240] test(query): repro #4378 --- test/query.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index fe0deb0727e..cb871e03d56 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1658,6 +1658,20 @@ describe('Query', function() { }); }); }); + + it('string as input (gh-4378)', function(done) { + var schema = new mongoose.Schema({ + name: String + }); + + var MyModel = db.model('gh4378', schema); + + assert.throws(function() { + MyModel.findOne(''); + }, /Invalid argument to findOne()/); + + done(); + }); }); describe('handles falsy and object projections with defaults (gh-3256)', function() { From 08ad1500e3508251bea02921ad0e4d0b1046b67d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 Aug 2016 14:20:33 -0700 Subject: [PATCH 0774/2240] fix(query): disallow passing empty string to findOne() Fix #4378 --- lib/query.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/query.js b/lib/query.js index 49a0163c92a..4d8ef6798df 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1273,6 +1273,9 @@ Query.prototype.findOne = function(conditions, projection, options, callback) { if (mquery.canMerge(conditions)) { this.merge(conditions); + } else if (conditions != null) { + throw new Error('Invalid argument to findOne(): ' + + util.inspect(conditions)); } prepareDiscriminatorCriteria(this); From e57dc1aa9e82103fa220d700d8697c99eab0cf76 Mon Sep 17 00:00:00 2001 From: Kiko Beats Date: Mon, 8 Aug 2016 12:01:39 +0200 Subject: [PATCH 0775/2240] Add mixed schema doc for Object literal --- docs/schematypes.jade | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index 8294f4583cd..db861b7a834 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -97,6 +97,7 @@ block content p An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent: :js var Any = new Schema({ any: {} }); + var Any = new Schema({ any: Object }); var Any = new Schema({ any: Schema.Types.Mixed }); p | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the From af2828c972ec63f5b1e68b2a6f1ca37291eadd3a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 10 Aug 2016 10:24:43 -0700 Subject: [PATCH 0776/2240] test(types): repro #4365 --- test/model.populate.test.js | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 5cc5af454fc..b2d41b3b44c 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3736,6 +3736,55 @@ describe('model: populate:', function() { }); }); + it('checks field name correctly with nested arrays (gh-4365)', function(done) { + var UserSchema = new mongoose.Schema({ + name: { + type: String, + default: '' + } + }); + db.model('gh4365_0', UserSchema); + + var GroupSchema = new mongoose.Schema({ + name: String, + members: [String] + }); + + var OrganizationSchema = new mongoose.Schema({ + members: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'gh4365_0' + }], + groups: [GroupSchema] + }); + var OrganizationModel = db.model('gh4365_1', OrganizationSchema); + + var org = { + members: [], + groups: [] + }; + OrganizationModel.create(org, function(error) { + assert.ifError(error); + OrganizationModel. + findOne({}). + populate('members', 'name'). + exec(function(error, org) { + assert.ifError(error); + org.groups.push({ name: 'Team Rocket' }); + org.save(function(error) { + assert.ifError(error); + org.groups[0].members.push('Jessie'); + assert.equal(org.groups[0].members[0], 'Jessie'); + org.save(function(error) { + assert.ifError(error); + assert.equal(org.groups[0].members[0], 'Jessie'); + done(); + }); + }); + }); + }); + }); + describe('populate virtuals (gh-2562)', function() { it('basic populate virtuals', function(done) { var PersonSchema = new Schema({ From f779017ff4d8bca17ae27d7ab4e87b720713f628 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 10 Aug 2016 10:24:47 -0700 Subject: [PATCH 0777/2240] fix(types): checks field name correctly with nested arrays and populate Fix #4365 --- lib/types/array.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/types/array.js b/lib/types/array.js index a50e21a0f14..044d5de9ddd 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -82,20 +82,11 @@ MongooseArray.mixin = { */ _cast: function(value) { - var owner = this._owner; var populated = false; var Model; if (this._parent) { - // if a populated array, we must cast to the same model - // instance as specified in the original query. - if (!owner) { - owner = this._owner = this._parent.ownerDocument - ? this._parent.ownerDocument() - : this._parent; - } - - populated = owner.populated(this._path, true); + populated = this._parent.populated(this._path, true); } if (populated && value !== null && value !== undefined) { From bf2974530129a549dc6b3f6a966a96d6e272beb1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 10 Aug 2016 13:49:16 -0700 Subject: [PATCH 0778/2240] test(query): repro #4392 --- test/query.test.js | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index cb871e03d56..490d13b555c 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1672,6 +1672,77 @@ describe('Query', function() { done(); }); + + it('handles geoWithin with mongoose docs (gh-4392)', function(done) { + var areaSchema = new Schema({ + name: {type: String}, + loc: { + type: { + type: String, + enum: ['Polygon'], + default: 'Polygon' + }, + coordinates: [[[Number]]] + } + }); + + var Area = db.model('gh4392_0', areaSchema); + + var observationSchema = new Schema({ + geometry: { + type: { + type: String, + enum: ['Point'], + default: 'Point' + }, + coordinates: { type: [Number] } + }, + properties: { + temperature: { type: Number } + } + }); + observationSchema.index({ geometry: '2dsphere' }); + + var Observation = db.model('gh4392_1', observationSchema); + + Observation.on('index', function(error) { + assert.ifError(error); + var tromso = new Area({ + name: 'Tromso, Norway', + loc: { + type: 'Polygon', + coordinates: [[ + [18.89, 69.62], + [18.89, 69.72], + [19.03, 69.72], + [19.03, 69.62], + [18.89, 69.62] + ]] + } + }); + tromso.save(function(error) { + assert.ifError(error); + var observation = { + geometry: { + type: 'Point', + coordinates: [18.895, 69.67] + } + }; + Observation.create(observation, function(error) { + assert.ifError(error); + + Observation. + find(). + where('geometry').within().geometry(tromso.loc). + exec(function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 1); + done(); + }); + }); + }); + }); + }); }); describe('handles falsy and object projections with defaults (gh-3256)', function() { From 978732b12187976606cd590e60b653aa0cbd7a7d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 10 Aug 2016 13:50:54 -0700 Subject: [PATCH 0779/2240] fix(query): cast $geoWithin and convert mongoose objects to POJOs before casting Fix #4392 --- lib/cast.js | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index 6223f1a47f4..0cf67d8abaa 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -5,6 +5,8 @@ var utils = require('./utils'); var Types = require('./schema/index'); +var ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon']; + /** * Handles internal casting for queries * @@ -89,10 +91,18 @@ module.exports = function cast(schema, obj) { // handle geo schemas that use object notation // { loc: { long: Number, lat: Number } - var geo = val.$near ? '$near' : - val.$nearSphere ? '$nearSphere' : - val.$within ? '$within' : - val.$geoIntersects ? '$geoIntersects' : ''; + var geo = ''; + if (val.$near) { + geo = '$near'; + } else if (val.$nearSphere) { + geo = '$nearSphere'; + } else if (val.$within) { + geo = '$within'; + } else if (val.$geoIntersects) { + geo = '$geoIntersects'; + } else if (val.$geoWithin) { + geo = '$geoWithin'; + } if (!geo) { continue; @@ -132,6 +142,22 @@ module.exports = function cast(schema, obj) { if (value.$minDistance != null) { value.$minDistance = numbertype.castForQuery(value.$minDistance); } + if (utils.isMongooseObject(value.$geometry)) { + value.$geometry = value.$geometry.toObject({ virtuals: false }); + } + value = value.$geometry.coordinates; + } else if (geo === '$geoWithin') { + if (!value.$geometry) { + throw new Error('$geoWithin must specify $geometry'); + } + if (utils.isMongooseObject(value.$geometry)) { + value.$geometry = value.$geometry.toObject({ virtuals: false }); + } + var geoWithinType = value.$geometry.type; + if (ALLOWED_GEOWITHIN_GEOJSON_TYPES.indexOf(geoWithinType) === -1) { + throw new Error('Invalid geoJSON type for $geoWithin "' + + geoWithinType + '", must be "Polygon" or "MultiPolygon"'); + } value = value.$geometry.coordinates; } From 6403cc34cddfe6c509e7ccd42f0344f3d6a8da68 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 11 Aug 2016 13:41:40 -0700 Subject: [PATCH 0780/2240] fix(drivers): make debug output copy-pastable into mongodb shell Fix #4352 --- lib/drivers/node-mongodb-native/collection.js | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js index 9bd78b5baeb..0976ffcce7a 100644 --- a/lib/drivers/node-mongodb-native/collection.js +++ b/lib/drivers/node-mongodb-native/collection.js @@ -114,8 +114,8 @@ function iter(i) { if (debug) { if (typeof debug === 'function') { - debug.apply(debug - , [_this.name, i].concat(utils.args(args, 0, args.length - 1))); + debug.apply(debug, + [_this.name, i].concat(utils.args(args, 0, args.length - 1))); } else { this.$print(_this.name, i, args); } @@ -158,14 +158,17 @@ for (var i in Collection.prototype) { */ NativeCollection.prototype.$print = function(name, i, args) { - console.error( - '\x1B[0;36mMongoose:\x1B[0m %s.%s(%s) %s %s %s', - name, - i, - this.$format(args[0]), - this.$format(args[1]), - this.$format(args[2]), - this.$format(args[3])); + var moduleName = '\x1B[0;36mMongoose:\x1B[0m '; + var functionCall = [name, i].join('.'); + var _args = []; + for (var j = args.length - 1; j >= 0; --j) { + if (this.$format(args[j]) || _args.length) { + _args.unshift(this.$format(args[j])); + } + } + var params = '(' + _args.join(', ') + ')'; + + console.error(moduleName + functionCall + params); }; /** From d54737ef97b60955bea5d5066e200af9887dbfe4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 12 Aug 2016 19:00:46 -0700 Subject: [PATCH 0781/2240] test(schema): repro #1730 --- test/schema.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 0d7152daead..fae4307c5ca 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1232,6 +1232,16 @@ describe('schema', function() { }); }); }); + + it('prefix (gh-1730)', function(done) { + var s = new Schema({}); + + s.add({ n: Number }, 'prefix.'); + + assert.equal(s.pathType('prefix.n'), 'real'); + assert.equal(s.pathType('prefix'), 'nested'); + done(); + }); }); it('debugging msgs', function(done) { From d092d228ac1c5ab290a45097889f3743588b65df Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 12 Aug 2016 19:00:49 -0700 Subject: [PATCH 0782/2240] fix(schema): set prefix as nested path with add() Fix #1730 --- lib/schema.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index f228ccbf9d3..3aac8d44b86 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -399,9 +399,15 @@ Schema.prototype.add = function add(obj, prefix) { this.nested[prefix + key] = true; this.add(obj[key], prefix + key + '.'); } else { + if (prefix) { + this.nested[prefix.substr(0, prefix.length - 1)] = true; + } this.path(prefix + key, obj[key]); // mixed type } } else { + if (prefix) { + this.nested[prefix.substr(0, prefix.length - 1)] = true; + } this.path(prefix + key, obj[key]); } } From a884cb94672912356bae93e7b9bc6a5d5fb48bc4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 13 Aug 2016 18:31:06 -0700 Subject: [PATCH 0783/2240] test(query): repro #4049 --- test/model.update.test.js | 83 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 11cdcc1f772..11742068d5b 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1873,6 +1873,89 @@ describe('model: update:', function() { }); }); + it('updates child schema timestamps with $push (gh-4049)', function(done) { + var opts = { + timestamps: true, + toObject: { + virtuals: true + }, + toJSON: { + virtuals: true + } + }; + + var childSchema = new mongoose.Schema({ + senderId: { type: String } + }, opts); + + var parentSchema = new mongoose.Schema({ + children: [childSchema] + }, opts); + + var Parent = db.model('gh4049', parentSchema); + + var b2 = new Parent(); + b2.save(function(err, doc) { + var query = { _id: doc._id }; + var update = { $push: { children: { senderId: '234' } } }; + var opts = { 'new': true }; + Parent.findOneAndUpdate(query, update, opts).exec(function(error, res) { + assert.ifError(error); + assert.equal(res.children.length, 1); + assert.equal(res.children[0].senderId, '234'); + assert.ok(res.children[0].createdAt); + assert.ok(res.children[0].updatedAt); + done(); + }); + }); + }); + + it('updates child schema timestamps with $set (gh-4049)', function(done) { + var opts = { + timestamps: true, + toObject: { + virtuals: true + }, + toJSON: { + virtuals: true + } + }; + + var childSchema = new mongoose.Schema({ + senderId: { type: String } + }, opts); + + var parentSchema = new mongoose.Schema({ + children: [childSchema], + child: childSchema + }, opts); + + var Parent = db.model('gh4049_0', parentSchema); + + var b2 = new Parent(); + b2.save(function(err, doc) { + var query = { _id: doc._id }; + var update = { + $set: { + children: [{ senderId: '234' }], + child: { senderId: '567' } + } + }; + var opts = { 'new': true }; + Parent.findOneAndUpdate(query, update, opts).exec(function(error, res) { + assert.ifError(error); + assert.equal(res.children.length, 1); + assert.equal(res.children[0].senderId, '234'); + assert.ok(res.children[0].createdAt); + assert.ok(res.children[0].updatedAt); + + assert.ok(res.child.createdAt); + assert.ok(res.child.updatedAt); + done(); + }); + }); + }); + it('update handles casting with mongoose-long (gh-4283)', function(done) { require('mongoose-long')(mongoose); From 5edeb344d687592af2b49ca1e1bf5705bd4cfc7b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 13 Aug 2016 18:31:27 -0700 Subject: [PATCH 0784/2240] fix(query): apply timestamps to child schemas when explicitly specified in update Fix #4049 --- lib/schema.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 3aac8d44b86..d77edbc8b37 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -759,9 +759,9 @@ Schema.prototype.hasMixedParent = function(path) { */ Schema.prototype.setupTimestamp = function(timestamps) { if (timestamps) { - var createdAt = timestamps.createdAt || 'createdAt', - updatedAt = timestamps.updatedAt || 'updatedAt', - schemaAdditions = {}; + var createdAt = timestamps.createdAt || 'createdAt'; + var updatedAt = timestamps.updatedAt || 'updatedAt'; + var schemaAdditions = {}; schemaAdditions[updatedAt] = Date; @@ -788,7 +788,7 @@ Schema.prototype.setupTimestamp = function(timestamps) { var genUpdates = function() { var now = new Date(); - var updates = {$set: {}, $setOnInsert: {}}; + var updates = { $set: {}, $setOnInsert: {} }; updates.$set[updatedAt] = now; updates.$setOnInsert[createdAt] = now; @@ -807,16 +807,73 @@ Schema.prototype.setupTimestamp = function(timestamps) { this.pre('findOneAndUpdate', function(next) { this.findOneAndUpdate({}, genUpdates()); + applyTimestampsToChildren(this); next(); }); this.pre('update', function(next) { this.update({}, genUpdates()); + applyTimestampsToChildren(this); next(); }); } }; +/*! + * ignore + */ + +function applyTimestampsToChildren(query) { + var now = new Date(); + var update = query.getUpdate(); + var keys = Object.keys(update); + var key; + var schema = query.model.schema; + var len; + var createdAt; + var updatedAt; + var timestamps; + + var hasDollarKey = keys.length && keys[0].charAt(0) === '$'; + + if (hasDollarKey) { + if (update.$push) { + for (key in update.$push) { + if (update.$push[key] && + schema.path(key).$isMongooseDocumentArray && + schema.path(key).schema.options.timestamps) { + timestamps = schema.path(key).schema.options.timestamps; + createdAt = timestamps.createdAt || 'createdAt'; + updatedAt = timestamps.updatedAt || 'updatedAt'; + update.$push[key][updatedAt] = now; + update.$push[key][createdAt] = now; + } + } + } + if (update.$set) { + for (key in update.$set) { + if (Array.isArray(update.$set[key]) && + schema.path(key).$isMongooseDocumentArray) { + len = update.$set[key].length; + timestamps = schema.path(key).schema.options.timestamps; + createdAt = timestamps.createdAt || 'createdAt'; + updatedAt = timestamps.updatedAt || 'updatedAt'; + for (var i = 0; i < len; ++i) { + update.$set[key][i][updatedAt] = now; + update.$set[key][i][createdAt] = now; + } + } else if (update.$set[key] && schema.path(key).$isSingleNested) { + timestamps = schema.path(key).schema.options.timestamps; + createdAt = timestamps.createdAt || 'createdAt'; + updatedAt = timestamps.updatedAt || 'updatedAt'; + update.$set[key][updatedAt] = now; + update.$set[key][createdAt] = now; + } + } + } + } +} + /*! * ignore */ From 5aba434ae2bbbb9aedf8dbe4598e4c6219b003d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C5=BBaczek?= Date: Sun, 14 Aug 2016 21:55:19 +0200 Subject: [PATCH 0785/2240] Update Contributors Count --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9bda25def25..ccc1afb3581 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Build your own Mongoose plugin through [generator-mongoose-plugin](https://githu ## Contributors -View all 100+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors). Stand up and be counted as a [contributor](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md) too! +View all 200+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors). Stand up and be counted as a [contributor](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md) too! ## Live Examples From 53eab2be3341eff4833579155a0adf0177ab7451 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 14 Aug 2016 14:08:37 -0700 Subject: [PATCH 0786/2240] chore: release 4.5.9 --- History.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 55405f136a6..98e3bb28fb9 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,17 @@ +4.5.9 / 2016-08-14 +================== + * docs: add mixed schema doc for Object literal #4400 [Kikobeats](https://github.com/Kikobeats) + * fix(query): cast $geoWithin and convert mongoose objects to POJOs before casting #4392 + * fix(schematype): dont cast defaults without parent doc #4390 + * fix(query): disallow passing empty string to findOne() #4378 + * fix(document): set single nested doc isNew correctly #4369 + * fix(types): checks field name correctly with nested arrays and populate #4365 + * fix(drivers): make debug output copy-pastable into mongodb shell #4352 + * fix(services): run update validators on nested paths #4332 + * fix(model): handle typeKey with discriminators #4339 + * fix(query): apply timestamps to child schemas when explicitly specified in update #4049 + * fix(schema): set prefix as nested path with add() #1730 + 4.5.8 / 2016-08-01 ================== * fix(model): make changing the discriminator key cause a cast error #4374 diff --git a/package.json b/package.json index 3cc173dcdc6..e6c641ea11e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.9-pre", + "version": "4.5.9", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From d1056586767c50fb573375236afb782f35e76a60 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 14 Aug 2016 15:24:06 -0700 Subject: [PATCH 0787/2240] chore: now working on 4.5.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e6c641ea11e..7ff665dc1c3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.9", + "version": "4.5.10-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 400509e94deff836d2430d2c5007eb2cf992d798 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 14 Aug 2016 16:08:05 -0700 Subject: [PATCH 0788/2240] test(model): repro #4387 --- test/model.discriminator.test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 1401b41481e..2597c309b1c 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -367,6 +367,17 @@ describe('model', function() { }, options)); done(); }); + + it('cloning with discriminator key (gh-4387)', function(done) { + var employee = new Employee({ name: { first: 'Val', last: 'Karpov' } }); + var clone = new employee.constructor(employee); + + // Should not error because we have the same discriminator key + clone.save(function(error) { + assert.ifError(error); + done(); + }); + }); }); }); }); From f22256cfb186bdaf4170530779b3befd636e493c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 14 Aug 2016 16:10:02 -0700 Subject: [PATCH 0789/2240] fix(model): dont error if the discriminator key is unchanged Fix #4387 --- lib/model.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 08a6d16426c..a02d320dbc9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -805,7 +805,10 @@ Model.discriminator = function discriminator(name, schema) { var obj = {}; obj[key] = { default: name, - set: function() { + set: function(newName) { + if (newName === name) { + return name; + } throw new Error('Can\'t set discriminator key "' + key + '"'); } }; From 6d9127482ac90f74343d9d0f2e8587077ad4957a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 15 Aug 2016 15:04:40 -0700 Subject: [PATCH 0790/2240] test(schema): repro #4404 --- test/document.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 57546944ba5..3095e9e9d9c 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3133,5 +3133,19 @@ describe('document', function() { done(); }); }); + + it('handles invalid dates (gh-4404)', function(done) { + var testSchema = new Schema({ + date: Date + }); + + var Test = db.model('gh4404', testSchema); + + Test.create({ date: new Date('invalid date') }, function(error) { + assert.ok(error); + assert.equal(error.errors['date'].name, 'CastError'); + done(); + }); + }); }); }); From 89272fa7899d809c2db2190111a81be679c5f323 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 15 Aug 2016 15:04:44 -0700 Subject: [PATCH 0791/2240] fix(schema): throw cast error if provided date invalid Fix #4404 --- lib/schema/date.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/schema/date.js b/lib/schema/date.js index 361b87b80c0..b7bcf227b33 100644 --- a/lib/schema/date.js +++ b/lib/schema/date.js @@ -217,6 +217,10 @@ SchemaDate.prototype.cast = function(value) { } if (value instanceof Date) { + if (isNaN(value.valueOf())) { + throw new CastError('date', value, this.path); + } + return value; } From 9b254ed285b9293f5bf7476a999343cb9030b8c7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 16 Aug 2016 08:46:09 -0700 Subject: [PATCH 0792/2240] docs: add more clarification re: the index event Fix #4410 --- docs/guide.jade | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/guide.jade b/docs/guide.jade index 9134611c8b7..4312aaeaa34 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -172,6 +172,21 @@ block content // or new Schema({..}, { autoIndex: false }); + :markdown + Mongoose will emit an `index` event on the model when indexes are done + building or an error occurred. + + :js + // Will cause an error because mongodb has an _id index by default that + // is not sparse + animalSchema.index({ _id: 1 }, { sparse: true }); + var Animal = mongoose.model('Animal', animalSchema); + + Animal.on('index', function(error) { + // "_id index cannot be sparse" + console.log(error.message); + }); + :markdown See also the [Model#ensureIndexes](./api.html#model_Model.ensureIndexes) method. From f35cbdefb01b0b11e419394649bc0c71f2cfedbb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 16 Aug 2016 09:08:09 -0700 Subject: [PATCH 0793/2240] feat(error): use util.inspect() so CastError never prints "[object Object]" Fix #4398 --- lib/error/cast.js | 9 ++++++++- test/model.querying.test.js | 2 +- test/types.buffer.test.js | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/error/cast.js b/lib/error/cast.js index fcace73ee01..d42d6e8245d 100644 --- a/lib/error/cast.js +++ b/lib/error/cast.js @@ -3,6 +3,7 @@ */ var MongooseError = require('../error.js'); +var util = require('util'); /** * Casting Error constructor. @@ -14,7 +15,13 @@ var MongooseError = require('../error.js'); */ function CastError(type, value, path, reason) { - MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '" at path "' + path + '"'); + var stringValue = util.inspect(value); + stringValue = stringValue.replace(/^'/, '"').replace(/'$/, '"'); + if (stringValue.charAt(0) !== '"') { + stringValue = '"' + stringValue + '"'; + } + MongooseError.call(this, 'Cast to ' + type + ' failed for value ' + + stringValue + ' at path "' + path + '"'); if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { diff --git a/test/model.querying.test.js b/test/model.querying.test.js index be7b6099c75..58d1d5e58ab 100644 --- a/test/model.querying.test.js +++ b/test/model.querying.test.js @@ -961,7 +961,7 @@ describe('model: querying:', function() { assert.equal(nes1.length, 1); NE.find({b: {$ne: [1]}}, function(err) { - assert.equal(err.message, 'Cast to ObjectId failed for value "1" at path "b"'); + assert.equal(err.message, 'Cast to ObjectId failed for value "[ 1 ]" at path "b"'); NE.find({b: {$ne: 4}}, function(err) { assert.equal(err.message, 'Cast to ObjectId failed for value "4" at path "b"'); diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js index 3879208196a..3254438bcc3 100644 --- a/test/types.buffer.test.js +++ b/test/types.buffer.test.js @@ -72,7 +72,7 @@ describe('types.buffer', function() { assert.equal(err.name, 'ValidationError'); assert.equal(err.errors.required.name, 'CastError'); assert.equal(err.errors.required.kind, 'Buffer'); - assert.equal(err.errors.required.message, 'Cast to Buffer failed for value "[object Object]" at path "required"'); + assert.equal(err.errors.required.message, 'Cast to Buffer failed for value "{ x: [ 20 ] }" at path "required"'); assert.deepEqual(err.errors.required.value, {x: [20]}); t.required = new Buffer('hello'); From 0a66821539c7fff1588d1d3ec74e3ae816e77982 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 18 Aug 2016 09:04:13 -0700 Subject: [PATCH 0794/2240] test(document): repro #4405 --- test/document.test.js | 47 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 3095e9e9d9c..e96151b344f 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3147,5 +3147,52 @@ describe('document', function() { done(); }); }); + + it('modify multiple subdoc paths (gh-4405)', function(done) { + var ChildObjectSchema = new Schema({ + childProperty1: String, + childProperty2: String, + childProperty3: String + }); + + var ParentObjectSchema = new Schema({ + parentProperty1: String, + parentProperty2: String, + child: ChildObjectSchema + }); + + var Parent = db.model('gh4405', ParentObjectSchema); + + var p = new Parent({ + parentProperty1: 'abc', + parentProperty2: '123', + child: { + childProperty1: 'a', + childProperty2: 'b', + childProperty3: 'c' + } + }); + p.save(function(error) { + assert.ifError(error); + Parent.findById(p._id, function(error, p) { + assert.ifError(error); + p.parentProperty1 = 'foo'; + p.parentProperty2 = 'bar'; + p.child.childProperty1 = 'ping'; + p.child.childProperty2 = 'pong'; + p.child.childProperty3 = 'weee'; + p.save(function(error) { + assert.ifError(error); + Parent.findById(p._id, function(error, p) { + assert.ifError(error); + assert.equal(p.child.childProperty1, 'ping'); + assert.equal(p.child.childProperty2, 'pong'); + assert.equal(p.child.childProperty3, 'weee'); + done(); + }); + }); + }); + }); + }); }); }); From 0ccf493d08518e97db69953ef6451ac514a41e16 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 18 Aug 2016 09:05:22 -0700 Subject: [PATCH 0795/2240] fix(document): only skip modifying subdoc path if parent is direct modified Fix #4405 --- lib/types/subdocument.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index cf295c2895a..37da6965576 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -46,7 +46,7 @@ Subdocument.prototype.$isValid = function(path) { Subdocument.prototype.markModified = function(path) { Document.prototype.markModified.call(this, path); if (this.$parent) { - if (this.$parent.isModified(this.$basePath)) { + if (this.$parent.isDirectModified(this.$basePath)) { return; } this.$parent.markModified([this.$basePath, path].join('.')); From 7a4a4f5343c640e368d8ddef21aacd2c4ce8264c Mon Sep 17 00:00:00 2001 From: Derick Yang Date: Thu, 18 Aug 2016 13:18:28 -0400 Subject: [PATCH 0796/2240] fix #4434 subdocuments causing error with parent timestamp on update --- lib/schema.js | 22 ++++++++++++--------- test/types.subdocument.test.js | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index d77edbc8b37..c8f32f7e7e1 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -856,18 +856,22 @@ function applyTimestampsToChildren(query) { schema.path(key).$isMongooseDocumentArray) { len = update.$set[key].length; timestamps = schema.path(key).schema.options.timestamps; - createdAt = timestamps.createdAt || 'createdAt'; - updatedAt = timestamps.updatedAt || 'updatedAt'; - for (var i = 0; i < len; ++i) { - update.$set[key][i][updatedAt] = now; - update.$set[key][i][createdAt] = now; + if (timestamps) { + createdAt = timestamps.createdAt || 'createdAt'; + updatedAt = timestamps.updatedAt || 'updatedAt'; + for (var i = 0; i < len; ++i) { + update.$set[key][i][updatedAt] = now; + update.$set[key][i][createdAt] = now; + } } } else if (update.$set[key] && schema.path(key).$isSingleNested) { timestamps = schema.path(key).schema.options.timestamps; - createdAt = timestamps.createdAt || 'createdAt'; - updatedAt = timestamps.updatedAt || 'updatedAt'; - update.$set[key][updatedAt] = now; - update.$set[key][createdAt] = now; + if (timestamps) { + createdAt = timestamps.createdAt || 'createdAt'; + updatedAt = timestamps.updatedAt || 'updatedAt'; + update.$set[key][updatedAt] = now; + update.$set[key][createdAt] = now; + } } } } diff --git a/test/types.subdocument.test.js b/test/types.subdocument.test.js index 051281700fc..4bd4baa30b2 100644 --- a/test/types.subdocument.test.js +++ b/test/types.subdocument.test.js @@ -50,4 +50,39 @@ describe('types.subdocument', function() { assert.equal(p._id, p.children[0].child.ownerDocument()._id); done(); }); + it('not setting timestamps in subdocuments', function() { + var Thing = mongoose.model('Thing', new Schema({ + subArray: [{ + testString: String + }] + }, { + timestamps: true + })); + + var thingy = new Thing({ + subArray: [{ + testString: 'Test 1' + }] + }); + var id; + thingy.save(function(err, item) { + assert(!err); + id = item._id; + }) + .then(function() { + var thingy2 = { + subArray: [{ + testString: 'Test 2' + }] + }; + return Thing.update({ + _id: id + }, {$set: thingy2}); + }) + .then(function() { + mongoose.connection.close(); + }, function(reason) { + assert(!reason); + }); + }); }); From c78512695731fca99efda1271d308788fa443d1c Mon Sep 17 00:00:00 2001 From: Trej Gun Date: Fri, 19 Aug 2016 11:26:25 +0300 Subject: [PATCH 0797/2240] mocha updated to 3.0.2 --- package.json | 2 +- test/document.populate.test.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 7ff665dc1c3..ba8581ccc78 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "lodash": "4.14.1", "markdown": "0.3.1", "marked": "0.3.6", - "mocha": "2.3.4", + "mocha": "3.0.2", "mongoose-long": "0.1.0", "node-static": "0.7.7", "power-assert": "1.2.0", diff --git a/test/document.populate.test.js b/test/document.populate.test.js index 9bdffbc6ef9..b65c6fb49b8 100644 --- a/test/document.populate.test.js +++ b/test/document.populate.test.js @@ -526,7 +526,7 @@ describe('document.populate', function() { }); describe('gh-2214', function() { - it('should return a real document array when populating', function(done) { + it('should return a real document array when populating', function() { var db = start(); var Car = db.model('gh-2214-1', { @@ -565,7 +565,6 @@ describe('document.populate', function() { joe.cars.push(car); assert.ok(joe.isModified('cars')); db.close(); - done(); }); }); }); From d9aba1062ec26ca754365279232ceb2280fa392f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 19 Aug 2016 09:42:11 -0700 Subject: [PATCH 0798/2240] test(query): repro #4420 --- test/model.update.test.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 11742068d5b..46ad3bac012 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1975,5 +1975,28 @@ describe('model: update:', function() { }); }); }); + + it('single nested with runValidators (gh-4420)', function(done) { + var FileSchema = new Schema({ + name: String + }); + + var CompanySchema = new Schema({ + name: String, + file: FileSchema + }); + + var Company = db.model('Company', CompanySchema); + + Company.create({ name: 'Booster Fuels' }, function(error) { + assert.ifError(error); + var update = { file: { name: 'new-name' } }; + var options = { runValidators: true }; + Company.update({}, update, options, function(error) { + assert.ifError(error); + done(); + }); + }); + }); }); }); From b15b5b6f2e965c9a0b9310c437b45b52a149b53b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 19 Aug 2016 09:42:35 -0700 Subject: [PATCH 0799/2240] fix(query): ensure single nested subdoc is hydrated when running update validators Fix #4420 --- lib/schema/embedded.js | 6 +++++- lib/services/common.js | 2 +- test/document.test.js | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 3f8a157f6b1..ccb7038c7a6 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -42,6 +42,9 @@ function Embedded(schema, path, options) { _embedded.schema = schema; _embedded.$isSingleNested = true; _embedded.prototype.$basePath = path; + _embedded.prototype.toBSON = function() { + return this.toObject({ virtuals: false }); + }; // apply methods for (var i in schema.methods) { @@ -131,7 +134,8 @@ Embedded.prototype.castForQuery = function($conditional, val) { if (val == null) { return val; } - return new this.caster(val).toObject({virtuals: false}); + + return new this.caster(val); }; /** diff --git a/lib/services/common.js b/lib/services/common.js index 956aee54708..121829e2d5b 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -23,7 +23,7 @@ function flatten(update, path, options) { for (var i = 0; i < numKeys; ++i) { var key = keys[i]; var val = update[key]; - if (utils.isMongooseObject(val) && !Buffer.isBuffer(val)) { + if (utils.isMongooseObject(val) && !val.$isSingleNested && !Buffer.isBuffer(val)) { val = val.toObject({ virtuals: false }); } if (shouldFlatten(val)) { diff --git a/test/document.test.js b/test/document.test.js index e96151b344f..5f47b632f54 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -1971,7 +1971,7 @@ describe('document', function() { }); }); - it('single embedded schemas (gh-2689)', function(done) { + it('single embedded schemas 1 (gh-2689)', function(done) { var userSchema = new mongoose.Schema({ name: String, email: String From d21f4bfe578ac0963fe5bce7bffdf64fc38fa5b1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 Aug 2016 20:18:07 -0700 Subject: [PATCH 0800/2240] test(query): repro #4418 --- test/model.update.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 46ad3bac012..8504ccd3424 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1956,6 +1956,23 @@ describe('model: update:', function() { }); }); + it('handles positional operator with timestamps (gh-4418)', function(done) { + var schema = new Schema({ + thing: [{ + thing2: { type: String }, + test: String + }] + }, { timestamps: true }); + + var Model = db.model('gh4418', schema); + var query = { 'thing.thing2': 'test' }; + var update = { $set: { 'thing.$.test': 'test' } }; + Model.update(query, update, function(error) { + assert.ifError(error); + done(); + }); + }); + it('update handles casting with mongoose-long (gh-4283)', function(done) { require('mongoose-long')(mongoose); From 658d6d0c55644f851c4022571c652a9128a61ed8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 Aug 2016 20:18:46 -0700 Subject: [PATCH 0801/2240] fix(query): don't crash if timestamps on and update doesn't have a path Fix #4418 --- lib/schema.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index d77edbc8b37..7caa436fb63 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -833,6 +833,7 @@ function applyTimestampsToChildren(query) { var createdAt; var updatedAt; var timestamps; + var path; var hasDollarKey = keys.length && keys[0].charAt(0) === '$'; @@ -852,8 +853,11 @@ function applyTimestampsToChildren(query) { } if (update.$set) { for (key in update.$set) { - if (Array.isArray(update.$set[key]) && - schema.path(key).$isMongooseDocumentArray) { + path = schema.path(key); + if (!path) { + continue; + } + if (Array.isArray(update.$set[key]) && path.$isMongooseDocumentArray) { len = update.$set[key].length; timestamps = schema.path(key).schema.options.timestamps; createdAt = timestamps.createdAt || 'createdAt'; @@ -862,7 +866,7 @@ function applyTimestampsToChildren(query) { update.$set[key][i][updatedAt] = now; update.$set[key][i][createdAt] = now; } - } else if (update.$set[key] && schema.path(key).$isSingleNested) { + } else if (update.$set[key] && path.$isSingleNested) { timestamps = schema.path(key).schema.options.timestamps; createdAt = timestamps.createdAt || 'createdAt'; updatedAt = timestamps.updatedAt || 'updatedAt'; From 41fe113fa04d20b86e3b5c8f785be70817bc2066 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Aug 2016 15:09:35 -0700 Subject: [PATCH 0802/2240] test(query): repro #4419 --- test/query.test.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index 490d13b555c..d145190c088 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1673,6 +1673,60 @@ describe('Query', function() { done(); }); + it('handles geoWithin with $center and mongoose object (gh-4419)', function(done) { + var areaSchema = new Schema({ + name: String, + circle: Array + }); + var Area = db.model('gh4419', areaSchema); + + var placeSchema = new Schema({ + name: String, + geometry: { + type: { + type: String, + enum: ['Point'], + default: 'Point' + }, + coordinates: { type: [Number] } + } + }); + placeSchema.index({ geometry: '2dsphere' }); + var Place = db.model('gh4419_0', placeSchema); + + var tromso = new Area({ + name: 'Tromso, Norway', + circle: [[18.89, 69.62], 10 / 3963.2] + }); + tromso.save(function(error) { + assert.ifError(error); + + var airport = { + name: 'Center', + geometry: { + type: 'Point', + coordinates: [18.895, 69.67] + } + }; + Place.create(airport, function(error) { + assert.ifError(error); + var q = { + geometry: { + $geoWithin: { + $centerSphere: tromso.circle + } + } + }; + Place.find(q).exec(function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 1); + assert.equal(docs[0].name, 'Center'); + done(); + }); + }); + }); + }); + it('handles geoWithin with mongoose docs (gh-4392)', function(done) { var areaSchema = new Schema({ name: {type: String}, From d7f820e8180f12049c3bde9541fb62f442e892df Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Aug 2016 15:24:39 -0700 Subject: [PATCH 0803/2240] fix(query): cast non-$geometry operators for $geoWithin Fix #4419 --- lib/cast.js | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index 0cf67d8abaa..e8179307348 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -147,18 +147,23 @@ module.exports = function cast(schema, obj) { } value = value.$geometry.coordinates; } else if (geo === '$geoWithin') { - if (!value.$geometry) { - throw new Error('$geoWithin must specify $geometry'); - } - if (utils.isMongooseObject(value.$geometry)) { - value.$geometry = value.$geometry.toObject({ virtuals: false }); - } - var geoWithinType = value.$geometry.type; - if (ALLOWED_GEOWITHIN_GEOJSON_TYPES.indexOf(geoWithinType) === -1) { - throw new Error('Invalid geoJSON type for $geoWithin "' + - geoWithinType + '", must be "Polygon" or "MultiPolygon"'); + if (value.$geometry) { + if (utils.isMongooseObject(value.$geometry)) { + value.$geometry = value.$geometry.toObject({ virtuals: false }); + } + var geoWithinType = value.$geometry.type; + if (ALLOWED_GEOWITHIN_GEOJSON_TYPES.indexOf(geoWithinType) === -1) { + throw new Error('Invalid geoJSON type for $geoWithin "' + + geoWithinType + '", must be "Polygon" or "MultiPolygon"'); + } + value = value.$geometry.coordinates; + } else { + value = value.$box || value.$polygon || value.$center || + value.$centerSphere; + if (utils.isMongooseObject(value)) { + value = value.toObject({ virtuals: false }); + } } - value = value.$geometry.coordinates; } _cast(value, numbertype); From aa8a76402d212ab4e6b4ce24ad8845000baf0cca Mon Sep 17 00:00:00 2001 From: Gabriele Cimato Date: Sun, 21 Aug 2016 19:23:26 -0700 Subject: [PATCH 0804/2240] doc: fix typo on documents.jade --- docs/documents.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/documents.jade b/docs/documents.jade index b16531c8722..ed2f1713fdb 100644 --- a/docs/documents.jade +++ b/docs/documents.jade @@ -21,7 +21,7 @@ block content }); }); :markdown - This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model.update) is right for us: + This approach involves first retrieving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model.update) is right for us: :js Tank.update({ _id: id }, { $set: { size: 'large' }}, callback); :markdown From 23cb8ed75fee053eac2cdd58b5fa74405d8f8c4f Mon Sep 17 00:00:00 2001 From: Gabriele Cimato Date: Sun, 21 Aug 2016 19:29:25 -0700 Subject: [PATCH 0805/2240] doc: fix typo on documents.html --- docs/documents.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/documents.html b/docs/documents.html index e0a06b86036..135e56b4eef 100644 --- a/docs/documents.html +++ b/docs/documents.html @@ -6,7 +6,7 @@ if (err) return handleError(err); res.send(tank); }); -});

This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

If we do need the document returned in our application there is another, often better, option:

Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
+});

This approach involves first retrieving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

If we do need the document returned in our application there is another, often better, option:

Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
   if (err) return handleError(err);
   res.send(tank);
 });

The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

Validating

Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

Next Up

Now that we've covered Documents, let's take a look at Sub-documents.

\ No newline at end of file +})(); From 89106b683f75a97138667982fd52e8c2f94c0776 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Aug 2016 14:33:07 -0700 Subject: [PATCH 0806/2240] test(query): repro #4379 --- test/promise_provider.test.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js index 994ace1e54e..273f9fc9806 100644 --- a/test/promise_provider.test.js +++ b/test/promise_provider.test.js @@ -310,6 +310,15 @@ describe('ES6 promises: ', function() { }); }); + it('no unhandled rejection on query w/ cb (gh-4379)', function(done) { + var query = MyModel.findOne({test: '123'}); + query.$__findOneSucceeds = false; + query.exec(function(error) { + assert.ok(error); + done(); + }); + }); + it('create', function(done) { var promise = MyModel.create({test: '123'}); assert.equal(promise.constructor, bluebird); From 15e271ac8b5d73b80045f61f032206dc1635c0c6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Aug 2016 14:35:18 -0700 Subject: [PATCH 0807/2240] fix(query): don't throw unhandled rejection with bluebird when using cbs Fix #4379 --- lib/query.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/query.js b/lib/query.js index 4d8ef6798df..d4154d1ab1a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2220,23 +2220,34 @@ Query.prototype.exec = function exec(op, callback) { this.op = op; } - return new Promise.ES6(function(resolve, reject) { + var _results; + var promise = new Promise.ES6(function(resolve, reject) { if (!_this.op) { - callback && callback(null, undefined); resolve(); return; } _this[_this.op].call(_this, function(error, res) { if (error) { - callback && callback(error); reject(error); return; } - callback && callback.apply(null, arguments); + _results = arguments; resolve(res); }); }); + + if (callback) { + promise.then( + function() { + callback.apply(null, _results); + }, + function(error) { + callback(error); + }); + } + + return promise; }; /** From c34c525d2f8270db8f30de2bde3b98893a036a28 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Aug 2016 14:54:14 -0700 Subject: [PATCH 0808/2240] test(query): coverage for #4408 --- test/query.test.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index d145190c088..b70a2f3f93d 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1727,6 +1727,49 @@ describe('Query', function() { }); }); + it('geoIntersects with mongoose doc as coords (gh-4408)', function(done) { + var lineStringSchema = new Schema({ + name: String, + geo: { + type: { type: String, default: 'LineString' }, + coordinates: [[Number]] + } + }); + + var LineString = db.model('gh4408', lineStringSchema); + + var ls = { + name: 'test', + geo: { + coordinates: [ [14.59, 24.847], [28.477, 15.961] ] + } + }; + var ls2 = { + name: 'test2', + geo: { + coordinates: [ [27.528, 25.006], [14.063, 15.591] ] + } + }; + LineString.create(ls, ls2, function(error, ls1) { + assert.ifError(error); + var query = { + geo: { + $geoIntersects: { + $geometry: { + type: 'LineString', + coordinates: ls1.geo.coordinates + } + } + } + }; + LineString.find(query, function(error, results) { + assert.ifError(error); + assert.equal(results.length, 2); + done(); + }); + }); + }); + it('handles geoWithin with mongoose docs (gh-4392)', function(done) { var areaSchema = new Schema({ name: {type: String}, From d2e34a0beb169435d2660c094200e64eb6438c4a Mon Sep 17 00:00:00 2001 From: isayme Date: Sat, 20 Aug 2016 16:46:43 +0800 Subject: [PATCH 0809/2240] fix(model): should not cause unhandle reject promise --- lib/model.js | 7 +++++-- test/model.create.test.js | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index a02d320dbc9..9fa28a9079f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1858,8 +1858,11 @@ Model.create = function create(doc, callback) { async.parallel(toExecute, function(error, savedDocs) { if (error) { - cb && cb(error); - reject(error); + if (cb) { + cb(error); + } else { + reject(error); + } return; } diff --git a/test/model.create.test.js b/test/model.create.test.js index 32fc3a21291..fa6eff4d5c9 100644 --- a/test/model.create.test.js +++ b/test/model.create.test.js @@ -7,7 +7,8 @@ var start = require('./common'), mongoose = start.mongoose, random = require('../lib/utils').random, Schema = mongoose.Schema, - DocumentObjectId = mongoose.Types.ObjectId; + DocumentObjectId = mongoose.Types.ObjectId, + PromiseProvider = require('../lib/promise_provider'); /** * Setup @@ -66,6 +67,19 @@ describe('model', function() { }); }); + it('should not cause unhandled reject promise', function(done) { + mongoose.Promise = global.Promise; + mongoose.Promise = require('bluebird'); + B.create({title: 'reject promise'}, function(err, b) { + assert.ifError(err); + B.create({_id: b._id}, function(err) { + assert(err); + PromiseProvider.reset(); + done(); + }); + }); + }); + it('returns a promise', function(done) { var p = B.create({title: 'returns promise'}, function() { assert.ok(p instanceof mongoose.Promise); From 8124ff3f0f4be330f0351270689cb0dbc6fd1d6c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 Aug 2016 16:06:36 -0700 Subject: [PATCH 0810/2240] chore: release 4.5.10 --- History.md | 16 ++++++++++++++++ package.json | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 98e3bb28fb9..fee785e425a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,19 @@ +4.5.10 / 2016-08-23 +=================== + * docs: fix typo on documents.jade #4444 [Gabri3l](https://github.com/Gabri3l) + * chore: upgrade mocha to 3.0.2 #4437 [TrejGun](https://github.com/TrejGun) + * fix: subdocuments causing error with parent timestamp on update #4434 [dyang108](https://github.com/dyang108) + * fix(query): don't crash if timestamps on and update doesn't have a path #4425 #4424 #4418 + * fix(query): ensure single nested subdoc is hydrated when running update validators #4420 + * fix(query): cast non-$geometry operators for $geoWithin #4419 + * docs: update contributor count #4415 [AdamZaczek](https://github.com/AdamZaczek) + * docs: add more clarification re: the index event #4410 + * fix(document): only skip modifying subdoc path if parent is direct modified #4405 + * fix(schema): throw cast error if provided date invalid #4404 + * feat(error): use util.inspect() so CastError never prints "[object Object]" #4398 + * fix(model): dont error if the discriminator key is unchanged #4387 + * fix(query): don't throw unhandled rejection with bluebird when using cbs #4379 + 4.5.9 / 2016-08-14 ================== * docs: add mixed schema doc for Object literal #4400 [Kikobeats](https://github.com/Kikobeats) diff --git a/package.json b/package.json index ba8581ccc78..39067fd3172 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.10-pre", + "version": "4.5.10", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 5b9426e6942f68e1cfbe4c7ac3141c27574444d9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 Aug 2016 16:12:38 -0700 Subject: [PATCH 0811/2240] chore: now working on 4.5.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 39067fd3172..41ad892dfe9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.10", + "version": "4.5.11-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From b8bbd8028fcfe0a668c5f666d39c6eec69685441 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 Aug 2016 16:19:34 -0700 Subject: [PATCH 0812/2240] chore: upgrade mongodb -> 2.2.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index baeb1cea84e..6ba3e9221c7 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.23", "hooks-fixed": "1.2.0", "kareem": "1.1.3", - "mongodb": "2.2.5", + "mongodb": "2.2.8", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.11.0", From 30c78cbace87d569e953a1604edda837640e1c5b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 Aug 2016 17:12:12 -0700 Subject: [PATCH 0813/2240] docs: fix typo in index.jade --- docs/index.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.jade b/docs/index.jade index 4ee1755f3fc..0055313b232 100644 --- a/docs/index.jade +++ b/docs/index.jade @@ -98,7 +98,7 @@ html(lang='en') We just logged all of the kittens in our db to the console. If we want to filter our kittens by name, Mongoose supports MongoDBs rich [querying](/docs/queries.html) syntax. :js - Kitten.find({ name: /^Fluff/ }, callback); + Kitten.find({ name: /^fluff/ }, callback); :markdown This performs a search for all documents with a name property that begins with "Fluff" and returns the result as an array of kittens to the callback. h3 Congratulations From ebfabac43e99e7216c1a36200b492efd9b8e07e1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 25 Aug 2016 21:53:42 -0700 Subject: [PATCH 0814/2240] test(query): repro #4446 --- test/query.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index b70a2f3f93d..b0342c51b89 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1460,6 +1460,14 @@ describe('Query', function() { }); }); }); + + it('populate as array in options (gh-4446)', function(done) { + var q = new Query; + q.setOptions({ populate: [{ path: 'path1' }, { path: 'path2' }] }); + assert.deepEqual(Object.keys(q._mongooseOptions.populate), + ['path1', 'path2']); + done(); + }); }); describe('update', function() { From 7cdc5aca179613aa1fb3bbacb2a926afa8174b16 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 25 Aug 2016 21:54:13 -0700 Subject: [PATCH 0815/2240] fix(query): allow array for populate options Fix #4446 --- lib/query.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/query.js b/lib/query.js index d4154d1ab1a..07ccb444853 100644 --- a/lib/query.js +++ b/lib/query.js @@ -882,6 +882,15 @@ Query.prototype.setOptions = function(options, overwrite) { return this; } + if (options && Array.isArray(options.populate)) { + var populate = options.populate; + delete options.populate; + var _numPopulate = populate.length; + for (var i = 0; i < _numPopulate; ++i) { + this.populate(populate[i]); + } + } + return Query.base.setOptions.call(this, options); }; From c9786d3d5c75d1f892c5154ff717e3dce4722377 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 Aug 2016 15:06:27 -0700 Subject: [PATCH 0816/2240] test(model): repro #4449 --- test/model.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index 2cbd7d59f65..f4954fd4e50 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5308,6 +5308,32 @@ describe('Model', function() { }); }); + it('creates new array when initializing from existing doc (gh-4449)', function(done) { + var TodoSchema = new mongoose.Schema({ + title: String + }, { _id: false }); + + var UserSchema = new mongoose.Schema({ + name: String, + todos: [TodoSchema] + }); + var User = db.model('User', UserSchema); + + var val = new User({ name: 'Val' }); + User.create(val, function(error, val) { + assert.ifError(error); + val.todos.push({ title: 'Groceries' }); + val.save(function(error) { + assert.ifError(error); + User.findById(val, function(error, val) { + assert.ifError(error); + assert.deepEqual(val.toObject().todos, [{ title: 'Groceries' }]); + done(); + }); + }); + }); + }); + it('marks array as modified when initializing non-array from db (gh-2442)', function(done) { var s1 = new Schema({ array: mongoose.Schema.Types.Mixed From cf0452b1582d327ab6ee43b3f0f37de887735a4f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 Aug 2016 15:06:31 -0700 Subject: [PATCH 0817/2240] fix(schema): create new array when copying from existing object to preserve change tracking Fix #4449 --- lib/schema/array.js | 4 ++++ lib/schema/documentarray.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lib/schema/array.js b/lib/schema/array.js index bc4fe3ba828..63d761c003a 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -155,6 +155,10 @@ SchemaArray.prototype.cast = function(value, doc, init) { if (!(value && value.isMongooseArray)) { value = new MongooseArray(value, this.path, doc); + } else if (value && value.isMongooseArray) { + // We need to create a new array, otherwise change tracking will + // update the old doc (gh-4449) + value = new MongooseArray(value.toObject(), this.path, doc); } if (this.caster) { diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 821facdae35..d7a5f4555c5 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -214,6 +214,10 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { doc.removeListener(key, prev._handlers[key]); } } + } else if (value && value.isMongooseDocumentArray) { + // We need to create a new array, otherwise change tracking will + // update the old doc (gh-4449) + value = new MongooseDocumentArray(value.toObject(), this.path, doc); } i = value.length; From 0ab100a59fa529d5f157ed8fa2f0ec3dc34a8af1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 Aug 2016 15:34:21 -0700 Subject: [PATCH 0818/2240] fix: couple issues re: #4449 --- lib/schema/array.js | 4 ++-- lib/schema/documentarray.js | 4 ++-- test/model.test.js | 13 ++++++++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index 63d761c003a..3a7c759bd00 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -155,10 +155,10 @@ SchemaArray.prototype.cast = function(value, doc, init) { if (!(value && value.isMongooseArray)) { value = new MongooseArray(value, this.path, doc); - } else if (value && value.isMongooseArray) { + } else if (value && value.isMongooseArray && !init) { // We need to create a new array, otherwise change tracking will // update the old doc (gh-4449) - value = new MongooseArray(value.toObject(), this.path, doc); + value = new MongooseArray(value, this.path, doc); } if (this.caster) { diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index d7a5f4555c5..43407791829 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -214,10 +214,10 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { doc.removeListener(key, prev._handlers[key]); } } - } else if (value && value.isMongooseDocumentArray) { + } else if (value && value.isMongooseDocumentArray && !init) { // We need to create a new array, otherwise change tracking will // update the old doc (gh-4449) - value = new MongooseDocumentArray(value.toObject(), this.path, doc); + value = new MongooseDocumentArray(value, this.path, doc); } i = value.length; diff --git a/test/model.test.js b/test/model.test.js index f4954fd4e50..293cdf31b8d 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5328,7 +5328,18 @@ describe('Model', function() { User.findById(val, function(error, val) { assert.ifError(error); assert.deepEqual(val.toObject().todos, [{ title: 'Groceries' }]); - done(); + var u2 = new User(); + val.todos = u2.todos; + val.todos.push({ title: 'Cook' }); + val.save(function(error) { + assert.ifError(error); + User.findById(val, function(error, val) { + assert.ifError(error); + assert.equal(val.todos.length, 1); + assert.equal(val.todos[0].title, 'Cook'); + done(); + }); + }); }); }); }); From 5a84e575705756a4efc1b8d4a59c0aeddec2e038 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 Aug 2016 19:29:06 -0700 Subject: [PATCH 0819/2240] fix(schema): make some corrections re #4449 --- lib/schema/array.js | 6 +++--- lib/schema/documentarray.js | 6 +++--- test/types.documentarray.test.js | 7 +++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index 3a7c759bd00..3a35c9f40d8 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -70,7 +70,6 @@ function SchemaArray(key, cast, options) { SchemaType.call(this, key, options, 'Array'); - var _this = this; var defaultArr; var fn; @@ -82,7 +81,8 @@ function SchemaArray(key, cast, options) { if (!('defaultValue' in this) || this.defaultValue !== void 0) { this.default(function() { var arr = fn ? defaultArr() : defaultArr || []; - return new MongooseArray(arr, _this.path, this); + // Leave it up to `cast()` to convert the array + return arr; }); } } @@ -155,7 +155,7 @@ SchemaArray.prototype.cast = function(value, doc, init) { if (!(value && value.isMongooseArray)) { value = new MongooseArray(value, this.path, doc); - } else if (value && value.isMongooseArray && !init) { + } else if (value && value.isMongooseArray) { // We need to create a new array, otherwise change tracking will // update the old doc (gh-4449) value = new MongooseArray(value, this.path, doc); diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 43407791829..e3181597796 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -47,7 +47,6 @@ function DocumentArray(key, schema, options) { this.schema = schema; this.$isMongooseDocumentArray = true; - var path = this.path; var fn = this.defaultValue; if (!('defaultValue' in this) || fn !== void 0) { @@ -56,7 +55,8 @@ function DocumentArray(key, schema, options) { if (!Array.isArray(arr)) { arr = [arr]; } - return new MongooseDocumentArray(arr, path, this); + // Leave it up to `cast()` to convert this to a documentarray + return arr; }); } } @@ -214,7 +214,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { doc.removeListener(key, prev._handlers[key]); } } - } else if (value && value.isMongooseDocumentArray && !init) { + } else if (value && value.isMongooseDocumentArray) { // We need to create a new array, otherwise change tracking will // update the old doc (gh-4449) value = new MongooseDocumentArray(value, this.path, doc); diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js index b909a4f07db..3644b78118c 100644 --- a/test/types.documentarray.test.js +++ b/test/types.documentarray.test.js @@ -365,8 +365,8 @@ describe('types.documentarray', function() { var p = new Post({title: 'comment nesting'}); var c1 = p.comments.create({title: 'c1'}); - var c2 = p.comments.create({title: 'c2'}); - var c3 = p.comments.create({title: 'c3'}); + var c2 = c1.comments.create({title: 'c2'}); + var c3 = c2.comments.create({title: 'c3'}); p.comments.push(c1); c1.comments.push(c2); @@ -378,8 +378,7 @@ describe('types.documentarray', function() { Post.findById(p._id, function(err, p) { assert.ifError(err); - var c4 = p.comments.create({title: 'c4'}); - p.comments[0].comments[0].comments[0].comments.push(c4); + p.comments[0].comments[0].comments[0].comments.push({title: 'c4'}); p.save(function(err) { assert.ifError(err); From 94d63ac09351044bff64d618a50c62c1b04e4896 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 Aug 2016 19:33:07 -0700 Subject: [PATCH 0820/2240] test(model): repro separate issue re: #4449 --- test/model.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index 293cdf31b8d..406e8f0aa28 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5308,6 +5308,20 @@ describe('Model', function() { }); }); + it('create() reuses existing doc if one passed in (gh-4449)', function(done) { + var testSchema = new mongoose.Schema({ + name: String + }); + var Test = db.model('gh4449_0', testSchema); + + var t = new Test(); + Test.create(t, function(error, t2) { + assert.ifError(error); + assert.strictEqual(t, t2); + done(); + }); + }); + it('creates new array when initializing from existing doc (gh-4449)', function(done) { var TodoSchema = new mongoose.Schema({ title: String From 14db0935a892aafedf62475d0932a51dceda7b39 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 Aug 2016 19:34:33 -0700 Subject: [PATCH 0821/2240] fix(model): reuse existing doc in create() if one passed in Re: #4449 --- lib/model.js | 2 +- test/model.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index a02d320dbc9..15e3a1060be 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1838,7 +1838,7 @@ Model.create = function create(doc, callback) { var toExecute = []; args.forEach(function(doc) { toExecute.push(function(callback) { - var toSave = new _this(doc); + var toSave = doc instanceof _this ? doc : new _this(doc); var callbackWrapper = function(error, doc) { if (error) { return callback(error); diff --git a/test/model.test.js b/test/model.test.js index 406e8f0aa28..503eec96858 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5317,7 +5317,7 @@ describe('Model', function() { var t = new Test(); Test.create(t, function(error, t2) { assert.ifError(error); - assert.strictEqual(t, t2); + assert.ok(t === t2); done(); }); }); From 603c2919473c96f1275776e6dfbaf8855560aabf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 27 Aug 2016 12:50:53 -0700 Subject: [PATCH 0822/2240] docs: fixes re #4366 --- docs/subdocs.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/subdocs.jade b/docs/subdocs.jade index fbcd347e5f5..e32b7927dc0 100644 --- a/docs/subdocs.jade +++ b/docs/subdocs.jade @@ -41,7 +41,7 @@ block content :markdown Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. :js - var doc = parent.children.id(id); + var doc = parent.children.id(_id); h3 Adding sub-docs :markdown @@ -76,7 +76,7 @@ block content Each sub-document has it's own [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. :js - var doc = parent.children.id(id).remove(); + var doc = parent.children.id(_id).remove(); parent.save(function (err) { if (err) return handleError(err); console.log('the sub-doc was removed') From 7c5ee3063e04a127f156fc4560db692841dec40d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 28 Aug 2016 16:56:04 -0700 Subject: [PATCH 0823/2240] docs(schematypes): add details re: options Fix #4452 --- docs/schematypes.jade | 84 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index db861b7a834..6e711364c00 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -78,6 +78,90 @@ block content m.nested.stuff = 'good'; m.save(callback); + h3 SchemaType Options + :markdown + You can declare a schema type using the type directly, or an object with + a `type` property. + :js + var schema1 = new Schema({ + test: String // `test` is a path of type String + }); + + var schema2 = new Schema({ + test: { type: String } // `test` is a path of type string + }); + :markdown + In addition to the type property, you can specify additional properties + for a path. For example, if you want to lowercase a string before saving: + :js + var schema2 = new Schema({ + test: { + type: String, + lowercase: true // Always convert `test` to lowercase + } + }); + :markdown + The `lowercase` property only works for strings. There are certain options + which apply for all schema types, and some that apply for specific schema + types. + h5 All Schema Types + :markdown + * `required`: boolean or function, if true adds a [required validator](http://mongoosejs.com/docs/validation.html#built-in-validators) for this property + * `default`: Any or function, sets a default value for the path. If the value is a function, the return value of the function is used as the default. + * `select`: boolean, specifies default [projections](https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/) for queries + * `validate: function, adds a [validator function](http://mongoosejs.com/docs/validation.html#built-in-validators) for this property + * `get`: function, defines a custom getter for this property using [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). + * `set`: function, defines a custom setter for this property using [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). + + :js + var numberSchema = new Schema({ + integerOnly: { + type: Number, + get: v => Math.round(v), + set: v => Math.round(v) + } + }); + + var Number = mongoose.model('Number', numberSchema); + + var doc = new Number(); + doc.integerOnly = 2.001; + doc.integerOnly; // 2 + + h5 Indexes + p + You can also define [MongoDB indexes](https://docs.mongodb.com/manual/indexes/) + using schema type options. + + * `index`: boolean, whether to define an on this property. + * `unique`: boolean, whether to define a [unique index](https://docs.mongodb.com/manual/core/index-unique/) on this property. + * `sparse`: boolean, whether to define a [sparse index](https://docs.mongodb.com/manual/core/index-sparse/) on this property. + :js + var schema2 = new Schema({ + test: { + type: String, + index: true, + unique: true // Unique index. If you specify `unique: true` + // specifying `index: true` is optional if you do `unique: true` + } + }); + h5 String + :markdown + * `lowercase`: boolean, whether to always call `.toLowerCase()` on the value + * `uppercase`: boolean, whether to always call `.toUpperCase()` on the value + * `trim`: boolean, whether to always call `.trim()` on the value + * `match`: RegExp, creates a [validator](http://mongoosejs.com/docs/validation.html) that checks if the value matches the given regular expression + * `enum`: Array, creates a [validator](http://mongoosejs.com/docs/validation.html) that checks if the value is in the given array. + + h5 Number + :markdown + * `min`: Number, creates a [validator](http://mongoosejs.com/docs/validation.html) that checks if the value is greater than or equal to the given minimum. + * `max`: Number, creates a [validator](http://mongoosejs.com/docs/validation.html) that checks if the value is less than or equal to the given maximum. + + h5 Date + * `min`: Date + * `max`: Date + h3 Usage notes: h4#Dates Dates :markdown From fc0840cd815ddb26848282aff36b4094313f9fa4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 29 Aug 2016 14:24:49 -0700 Subject: [PATCH 0824/2240] docs(query): improve docs re: handling undefined in findOne() Re: comments on #559 --- lib/model.js | 14 ++++++++++---- lib/query.js | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/model.js b/lib/model.js index 15e3a1060be..f421a3e4198 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1197,15 +1197,17 @@ Model.find = function find(conditions, projection, options, callback) { /** * Finds a single document by its _id field. `findById(id)` is almost* - * equivalent to `findOne({ _id: id })`. + * equivalent to `findOne({ _id: id })`. If you want to query by a document's + * `_id`, use `findById()` instead of `findOne()`. * * The `id` is cast based on the Schema before sending the command. * * Note: `findById()` triggers `findOne` hooks. * - * * Except for how it treats `undefined`. Because the MongoDB driver - * deletes keys that have value `undefined`, `findById(undefined)` gets - * translated to `findById({ _id: null })`. + * * Except for how it treats `undefined`. If you use `findOne()`, you'll see + * that `findOne(undefined)` and `findOne({ _id: undefined })` are equivalent + * to `findOne({})` and return arbitrary documents. However, mongoose + * translates `findById(undefined)` into `findOne({ _id: null })`. * * ####Example: * @@ -1257,6 +1259,10 @@ Model.findById = function findById(id, projection, options, callback) { * * The `conditions` are cast to their respective SchemaTypes before the command is sent. * + * *Note:* `conditions` is optional, and if `conditions` is null or undefined, + * mongoose will send an empty `findOne` command to MongoDB, which will return + * an arbitrary document. If you're querying by `_id`, use `findById()` instead. + * * ####Example: * * // find one iphone adventures - iphone adventures?? diff --git a/lib/query.js b/lib/query.js index 07ccb444853..a501cb3b9fa 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1233,6 +1233,11 @@ Query.prototype._findOne = function(callback) { * * Passing a `callback` executes the query. The result of the query is a single document. * + * * *Note:* `conditions` is optional, and if `conditions` is null or undefined, + * mongoose will send an empty `findOne` command to MongoDB, which will return + * an arbitrary document. If you're querying by `_id`, use `Model.findById()` + * instead. + * * ####Example * * var query = Kitten.where({ color: 'white' }); From f1b828840b707d5e32081ee4c61ce4a9825a8cc2 Mon Sep 17 00:00:00 2001 From: Matthew Canham Date: Tue, 30 Aug 2016 15:31:43 -0400 Subject: [PATCH 0825/2240] docs(document): updated document is returned in both the findById and findByIdAndUpdate examples to improve consistency --- docs/documents.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/documents.jade b/docs/documents.jade index ed2f1713fdb..f999a96a58d 100644 --- a/docs/documents.jade +++ b/docs/documents.jade @@ -27,7 +27,7 @@ block content :markdown If we do need the document returned in our application there is another, often [better](./api.html#model_Model.findByIdAndUpdate), option: :js - Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) { + Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, { new: true }, function (err, tank) { if (err) return handleError(err); res.send(tank); }); From b1385356b76f8db338b51d5613c08d94fae8aeca Mon Sep 17 00:00:00 2001 From: Matthew Canham Date: Tue, 30 Aug 2016 15:56:40 -0400 Subject: [PATCH 0826/2240] docs(document): in the findById example respond with the actual updated document from db --- docs/documents.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/documents.jade b/docs/documents.jade index f999a96a58d..16d19c2874f 100644 --- a/docs/documents.jade +++ b/docs/documents.jade @@ -15,9 +15,9 @@ block content if (err) return handleError(err); tank.size = 'large'; - tank.save(function (err) { + tank.save(function (err, updatedTank) { if (err) return handleError(err); - res.send(tank); + res.send(updatedTank); }); }); :markdown From 2ef39cfaea12e8a8aa6a74f1275ecf08fb98c9c1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 30 Aug 2016 21:00:10 -0700 Subject: [PATCH 0827/2240] fix: upgrade to mongodb driver 2.2.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ba3e9221c7..c32ab7a3c14 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.4.23", "hooks-fixed": "1.2.0", "kareem": "1.1.3", - "mongodb": "2.2.8", + "mongodb": "2.2.9", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.11.0", From 659f2111a7149d9d49812db02d3bac6a85d413b7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 31 Aug 2016 09:57:02 -0700 Subject: [PATCH 0828/2240] test: make notes about equality check issues Re: https://github.com/mongodb/js-bson/commit/aa0b54597a0af28cce3530d2144af708e4b66bf0 --- format_deps.js | 2 +- package.json | 3 +-- test/model.findOneAndUpdate.test.js | 23 +++++++++++++++++++---- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/format_deps.js b/format_deps.js index 39e5e74322e..206feb77b3d 100644 --- a/format_deps.js +++ b/format_deps.js @@ -1,5 +1,5 @@ var p = require('./package.json'); -var _ = require('underscore'); +var _ = require('lodash'); var result = _.map(p.browserDependencies, function(v, k) { return k + '@' + v; diff --git a/package.json b/package.json index c32ab7a3c14..481f65c03e5 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "license": "MIT", "dependencies": { "async": "1.5.2", - "bson": "~0.4.23", + "bson": "~0.5.4", "hooks-fixed": "1.2.0", "kareem": "1.1.3", "mongodb": "2.2.9", @@ -52,7 +52,6 @@ "q": "1.4.1", "tbd": "0.6.4", "uglify-js": "2.7.0", - "underscore": "1.8.3", "validator": "5.4.0" }, "browserDependencies": { diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index f564181c071..1a67f1cc824 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -11,7 +11,7 @@ var Utils = require('../lib/utils'); var Schema = mongoose.Schema; var ObjectId = Schema.Types.ObjectId; var DocumentObjectId = mongoose.Types.ObjectId; -var _ = require('underscore'); +var _ = require('lodash'); /** * Setup. @@ -909,7 +909,7 @@ describe('model: findByIdAndUpdate:', function() { }); }); - it('can do deep equals on object id after findOneAndUpdate (gh-2070)', function(done) { + it.only('can do deep equals on object id after findOneAndUpdate (gh-2070)', function(done) { var db = start(); var accountSchema = new Schema({ @@ -936,17 +936,32 @@ describe('model: findByIdAndUpdate:', function() { function(error, doc) { assert.ifError(error); assert.ok(Utils.deepEqual(doc.contacts[0].account, a2._id)); - assert.ok(_.isEqual(doc.contacts[0].account, a2._id)); + assert.ok(_.isEqualWith(doc.contacts[0].account, a2._id, compareBuffers)); + // Re: commends on https://github.com/mongodb/js-bson/commit/aa0b54597a0af28cce3530d2144af708e4b66bf0 + // Deep equality checks no longer work as expected with node 0.10. + // Please file an issue if this is a problem for you + if (!/^v0.10.\d+$/.test(process.version)) { + assert.ok(_.isEqual(doc.contacts[0].account, a2._id)); + } Account.findOne({name: 'parent'}, function(error, doc) { assert.ifError(error); assert.ok(Utils.deepEqual(doc.contacts[0].account, a2._id)); - assert.ok(_.isEqual(doc.contacts[0].account, a2._id)); + assert.ok(_.isEqualWith(doc.contacts[0].account, a2._id, compareBuffers)); + if (!/^v0.10.\d+$/.test(process.version)) { + assert.ok(_.isEqual(doc.contacts[0].account, a2._id)); + } db.close(done); }); }); }); }); + + function compareBuffers(a, b) { + if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { + return a.toString('hex') === b.toString('hex') + } + } }); it('adds __v on upsert (gh-2122)', function(done) { From cc367f26ebeb07f09c1f15902cd272ab8fb1cbf6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 31 Aug 2016 10:04:54 -0700 Subject: [PATCH 0829/2240] test: fix tests --- test/model.findOneAndUpdate.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 1a67f1cc824..950b2792948 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -909,7 +909,7 @@ describe('model: findByIdAndUpdate:', function() { }); }); - it.only('can do deep equals on object id after findOneAndUpdate (gh-2070)', function(done) { + it('can do deep equals on object id after findOneAndUpdate (gh-2070)', function(done) { var db = start(); var accountSchema = new Schema({ @@ -959,7 +959,7 @@ describe('model: findByIdAndUpdate:', function() { function compareBuffers(a, b) { if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { - return a.toString('hex') === b.toString('hex') + return a.toString('hex') === b.toString('hex'); } } }); From a7282d86cf4c80f873f333af8b400fc26020d8e6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 31 Aug 2016 20:25:37 -0700 Subject: [PATCH 0830/2240] docs(middleware): add docs for insertMany hooks Fix #4451 --- docs/middleware.jade | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/middleware.jade b/docs/middleware.jade index 3ea93c1cfff..9f8fc308338 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -22,6 +22,7 @@ block content * [findOne](./api.html#query_Query-findOne) * [findOneAndRemove](./api.html#query_Query-findOneAndRemove) * [findOneAndUpdate](./api.html#query_Query-findOneAndUpdate) + * [insertMany](./api.html#model_Model.insertMany) * [update](./api.html#query_Query-update) Both document middleware and query middleware support pre and post hooks. @@ -30,6 +31,7 @@ block content **Note:** There is no query hook for `remove()`, only for documents. If you set a 'remove' hook, it will be fired when you call `myDoc.remove()`, not when you call `MyModel.remove()`. + **Note:** The `create()` function fires `save()` hooks. h3#pre Pre :markdown From 2dd4294207adb918a5d68cf795e90a6dba06d062 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 2 Sep 2016 11:14:26 -0700 Subject: [PATCH 0831/2240] chore: release 4.6.0 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index fee785e425a..c0600c85183 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,14 @@ +4.6.0 / 2016-09-02 +================== + * docs(document): clarify the findById and findByIdAndUpdate examples #4471 [mdcanham](https://github.com/mdcanham) + * docs(schematypes): add details re: options #4452 + * docs(middleware): add docs for insertMany hooks #4451 + * fix(schema): create new array when copying from existing object to preserve change tracking #4449 + * docs: fix typo in index.jade #4448 + * fix(query): allow array for populate options #4446 + * fix(model): create should not cause unhandle reject promise #4439 + * fix: upgrade to mongodb driver 2.2.9 #4363 #4341 #4311 (see [comments here](https://github.com/mongodb/js-bson/commit/aa0b54597a0af28cce3530d2144af708e4b66bf0#commitcomment-18850498) if you use node 0.10) + 4.5.10 / 2016-08-23 =================== * docs: fix typo on documents.jade #4444 [Gabri3l](https://github.com/Gabri3l) diff --git a/package.json b/package.json index 481f65c03e5..64e4f735e91 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.5.11-pre", + "version": "4.6.0", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 1d577e048f51e3cc6703c4d169c2b19bdb1bb8b8 Mon Sep 17 00:00:00 2001 From: Fedotov Date: Sat, 3 Sep 2016 14:27:33 +0300 Subject: [PATCH 0832/2240] Fix an error on findOneAndUpdate with array of arrays Details are here https://github.com/Automattic/mongoose/issues/4470 --- lib/schema/array.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index 3a35c9f40d8..be7a4cdcdc0 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -205,7 +205,7 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { } else { val = $conditional; var proto = this.casterConstructor.prototype; - var method = proto.castForQuery || proto.cast; + var method = proto && (proto.castForQuery || proto.cast); var caster = this.caster; if (Array.isArray(val)) { From 49bda15bc28766a424883c11e49233e4d0f08ec8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 3 Sep 2016 09:21:08 -0700 Subject: [PATCH 0833/2240] test(update): repro #4465 --- test/model.update.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 8504ccd3424..ddd49adb12b 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2015,5 +2015,19 @@ describe('model: update:', function() { }); }); }); + + it('single nested schema with geo (gh-4465)', function(done) { + var addressSchema = new Schema({ + geo: {type: [Number], index: '2dsphere'} + }, { _id : false }); + var containerSchema = new Schema({ address: addressSchema }); + var Container = db.model('gh4465', containerSchema); + + Container.update({}, { address: { geo: [-120.24, 39.21] } }). + exec(function(error) { + assert.ifError(error); + done(); + }); + }); }); }); From 00d27f84b890d8b29b792e6a78277f22b1110aaa Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 3 Sep 2016 09:21:12 -0700 Subject: [PATCH 0834/2240] fix(query): properly handle setting single embedded in update Fix #4465 --- lib/services/common.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/services/common.js b/lib/services/common.js index 121829e2d5b..c09c2f0c014 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -61,6 +61,9 @@ function modifiedPaths(update, path, result) { var val = update[key]; result[path + key] = true; + if (utils.isMongooseObject(val) && !Buffer.isBuffer(val)) { + val = val.toObject({ virtuals: false }); + } if (shouldFlatten(val)) { modifiedPaths(val, path + key, result); } From 060b6dd13de6bdfe515d494ab0261302376efefb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 4 Sep 2016 09:29:07 -0700 Subject: [PATCH 0835/2240] test(query): repro #4441 --- test/model.update.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index ddd49adb12b..23e1035cae0 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2029,5 +2029,31 @@ describe('model: update:', function() { done(); }); }); + + it('runs validation on Mixed properties of embedded arrays during updates (gh-4441)', function(done) { + var db = start(); + + var A = new Schema({ str: {} }); + var validateCalls = 0; + A.path('str').validate(function(val, next) { + ++validateCalls; + next(); + }); + + var B = new Schema({a: [A]}); + + B = db.model('b', B); + + B.findOneAndUpdate( + {foo: 'bar'}, + {$set: {a: [{str: {somekey: 'someval'}}]}}, + {runValidators: true}, + function(err) { + assert.ifError(err); + assert.equal(validateCalls, 1); // AssertionError: 0 == 1 + db.close(done); + } + ); + }); }); }); From 561ef0120100f0a5c9089edb23b0d0b9c94ebabb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 4 Sep 2016 09:29:24 -0700 Subject: [PATCH 0836/2240] fix(query): check nested path when avoiding double-validating Mixed Fix #4441 Re: #4305 --- lib/schema.js | 8 ++++++++ lib/services/updateValidators.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index c6e543d2b3d..97a346dc17f 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1463,8 +1463,10 @@ Schema.prototype.remove = function(path) { Schema.prototype._getSchema = function(path) { var _this = this; var pathschema = _this.path(path); + var resultPath = []; if (pathschema) { + pathschema.$fullPath = path; return pathschema; } @@ -1477,9 +1479,12 @@ Schema.prototype._getSchema = function(path) { trypath = parts.slice(0, p).join('.'); foundschema = schema.path(trypath); if (foundschema) { + resultPath.push(trypath); + if (foundschema.caster) { // array of Mixed? if (foundschema.caster instanceof MongooseTypes.Mixed) { + foundschema.caster.$fullPath = resultPath.join('.'); return foundschema.caster; } @@ -1498,6 +1503,9 @@ Schema.prototype._getSchema = function(path) { return search(parts.slice(p), foundschema.schema); } } + + foundschema.$fullPath = resultPath.join('.'); + return foundschema; } } diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 8d7cd5c133e..31161ea19df 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -63,7 +63,7 @@ module.exports = function(query, schema, castedDoc, options) { if (schemaPath) { // gh-4305: `_getSchema()` will report all sub-fields of a 'Mixed' path // as 'Mixed', so avoid double validating them. - if (schemaPath instanceof Mixed && schemaPath.path !== updates[i]) { + if (schemaPath instanceof Mixed && schemaPath.$fullPath !== updates[i]) { return; } From 838fa18bc3545d829dc573c1969b4f195e7f01c5 Mon Sep 17 00:00:00 2001 From: Danny Hurlburt Date: Mon, 5 Sep 2016 16:05:21 -0600 Subject: [PATCH 0837/2240] Fix Indentation --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ccc1afb3581..0595e6b8cca 100644 --- a/README.md +++ b/README.md @@ -270,10 +270,10 @@ Moreover, you can mutate the incoming `method` arguments so that subsequent midd ```js new Schema({ broken: { type: Boolean }, - asset : { - name: String, - type: String // uh oh, it broke. asset will be interpreted as String - } + asset: { + name: String, + type: String // uh oh, it broke. asset will be interpreted as String + } }); new Schema({ From 0abd86570b24dd281f94ed89d4d754b2f121ae8a Mon Sep 17 00:00:00 2001 From: isayme Date: Wed, 7 Sep 2016 21:42:16 +0800 Subject: [PATCH 0838/2240] test(update): update test case for PR:4439 --- test/model.create.test.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/model.create.test.js b/test/model.create.test.js index fa6eff4d5c9..256b14424ee 100644 --- a/test/model.create.test.js +++ b/test/model.create.test.js @@ -70,12 +70,23 @@ describe('model', function() { it('should not cause unhandled reject promise', function(done) { mongoose.Promise = global.Promise; mongoose.Promise = require('bluebird'); + B.create({title: 'reject promise'}, function(err, b) { assert.ifError(err); - B.create({_id: b._id}, function(err) { + + var perr = null; + var p = B.create({_id: b._id}, function(err) { assert(err); - PromiseProvider.reset(); - done(); + setTimeout(function() { + PromiseProvider.reset(); + // perr should be null + done(perr); + }, 100); + }); + + p.catch(function(err) { + // should not go here + perr = err; }); }); }); From b0b541c9d718d73606f1471cda8c5a211f483a2b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Sep 2016 17:35:56 -0800 Subject: [PATCH 0839/2240] test(document): repro #4472 --- test/document.test.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 5f47b632f54..258cc139322 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3148,6 +3148,30 @@ describe('document', function() { }); }); + it('setting array subpath (gh-4472)', function(done) { + var ChildSchema = new mongoose.Schema({ + name: String, + age: Number + }, { _id: false }); + + var ParentSchema = new mongoose.Schema({ + data: { + children: [ChildSchema] + } + }); + + var Parent = db.model('gh4472', ParentSchema); + + var p = new Parent(); + p.set('data.children.0', { + name: 'Bob', + age: 900 + }); + + assert.deepEqual(p.toObject().data.children, [{ name: 'Bob', age: 900 }]); + done(); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From 0de34d3d71fda1517d69933a7ceb20f7f9d147de Mon Sep 17 00:00:00 2001 From: Saiichi Hashimoto Date: Mon, 12 Sep 2016 16:10:03 -0700 Subject: [PATCH 0840/2240] fix(webpack): Webpack version of driver Webpack prefers having a `.web.js` extension for webpack specific implementations. https://github.com/webpack/webpack/issues/35#issuecomment-10140851 --- lib/drivers/index.web.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 lib/drivers/index.web.js diff --git a/lib/drivers/index.web.js b/lib/drivers/index.web.js new file mode 100644 index 00000000000..c4883c9ad5b --- /dev/null +++ b/lib/drivers/index.web.js @@ -0,0 +1 @@ +module.exports = require('./browser'); From eda8c551880352ac713e252fcbc0c2fe09e9cbc3 Mon Sep 17 00:00:00 2001 From: Saiichi Hashimoto Date: Mon, 12 Sep 2016 16:38:18 -0700 Subject: [PATCH 0841/2240] Webpack version of document_provider Did a search of the codebase for `window` and this was the last place it mattered: https://github.com/Automattic/mongoose/search?l=javascript&q=window --- lib/document_provider.web.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 lib/document_provider.web.js diff --git a/lib/document_provider.web.js b/lib/document_provider.web.js new file mode 100644 index 00000000000..4223fc39750 --- /dev/null +++ b/lib/document_provider.web.js @@ -0,0 +1,17 @@ +'use strict'; + +/* eslint-env browser */ + +/*! + * Module dependencies. + */ +var BrowserDocument = require('./browserDocument.js'); + +/** + * Returns the Document constructor for the current context + * + * @api private + */ +module.exports = function() { + return BrowserDocument; +}; From 67c465aac5c864c3004d11d49934605037c8f520 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Sep 2016 17:57:35 -0700 Subject: [PATCH 0842/2240] fix(schema): hack around one part of #4472 --- lib/schema.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 97a346dc17f..ed591ede5fe 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -9,6 +9,7 @@ var utils = require('./utils'); var MongooseTypes; var Kareem = require('kareem'); var async = require('async'); +var SchemaType = require('./schematype'); var IS_KAREEM_HOOK = { count: true, @@ -906,8 +907,14 @@ function getPositionalPathType(self, path) { isNested = false; subpath = subpaths[i]; - if (i === last && val && !val.schema && !/\D/.test(subpath)) { - if (val instanceof MongooseTypes.Array) { + if (i === last && val && !/\D/.test(subpath)) { + if (val.$isMongooseDocumentArray) { + var oldVal = val; + val = new SchemaType(subpath); + val.cast = function(value, doc, init) { + return oldVal.cast(value, doc, init)[0]; + }; + } else if (val instanceof MongooseTypes.Array) { // StringSchema, NumberSchema, etc val = val.caster; } else { From c08bfa5a4675446a89eb18cc46fc167373ea82a2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 14 Sep 2016 18:36:10 -0700 Subject: [PATCH 0843/2240] test(query): test coverage for #4440 --- test/model.findOneAndUpdate.test.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 950b2792948..0662680500c 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1713,5 +1713,29 @@ describe('model: findByIdAndUpdate:', function() { done(); }); }); + + it('doesnt do double validation on document arrays during updates (gh-4440)', function(done) { + var A = new Schema({str: String}); + var B = new Schema({a: [A]}); + var validateCalls = 0; + B.path('a').validate(function(val, next) { + ++validateCalls; + assert(Array.isArray(val)); + next(); + }); + + B = db.model('b', B); + + B.findOneAndUpdate( + {foo: 'bar'}, + {$set: {a: [{str: 'asdf'}]}}, + {runValidators: true}, + function(err) { + assert.ifError(err); + assert.equal(validateCalls, 1); // Assertion error: 1 == 2 + db.close(done); + } + ); + }); }); }); From 237c4954211b3e51d7c2e7a2f7e27ad5476659a3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 14 Sep 2016 18:52:14 -0700 Subject: [PATCH 0844/2240] test(model): repro #4475 --- test/model.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index e0bfab1faa2..11f7bfd94c3 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5293,6 +5293,26 @@ describe('Model', function() { }); }); + it('method with same name as prop should throw (gh-4475)', function(done) { + var testSchema = new mongoose.Schema({ + isPaid: Boolean + }); + testSchema.methods.isPaid = function() { + return false; + }; + + var threw = false; + try { + db.model('gh4475', testSchema); + } catch (error) { + threw = true; + assert.equal(error.message, 'You have a method and a property in ' + + 'your schema both named "isPaid"'); + } + assert.ok(threw); + done(); + }); + it('emits errors in create cb (gh-3222) (gh-3478)', function(done) { var schema = new Schema({ name: 'String' }); var Movie = db.model('gh3222', schema); From 95de985679c2f534ee382ec5e14d9d1a61dca9ca Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 14 Sep 2016 18:52:17 -0700 Subject: [PATCH 0845/2240] fix(model): throw handy error when method name conflicts with property name Fix #4475 --- lib/model.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/model.js b/lib/model.js index ff7c5c8ddfb..2365f76e4bf 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3251,6 +3251,10 @@ var applyMethods = function(model, schema) { }); } for (var method in schema.methods) { + if (schema.tree[method]) { + throw new Error('You have a method and a property in your schema both ' + + 'named "' + method + '"'); + } if (typeof schema.methods[method] === 'function') { model.prototype[method] = schema.methods[method]; } else { From aad3939091dd1b845aa3ab978376596de8ee37d2 Mon Sep 17 00:00:00 2001 From: Nick Baugh Date: Thu, 15 Sep 2016 21:02:02 -0400 Subject: [PATCH 0846/2240] Added Slack channel URL and badge --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0595e6b8cca..550da7b833a 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. +[![Slack Status](http://slack.mongoosejs.io/badge.svg)](http://slack.mongoosejs.io) [![Build Status](https://api.travis-ci.org/Automattic/mongoose.svg?branch=master)](https://travis-ci.org/Automattic/mongoose) -[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Automattic/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![NPM version](https://badge.fury.io/js/mongoose.svg)](http://badge.fury.io/js/mongoose) [![Dependency Status](https://gemnasium.com/Automattic/mongoose.svg)](https://gemnasium.com/Automattic/mongoose) @@ -14,10 +14,10 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed ## Support - [Stack Overflow](http://stackoverflow.com/questions/tagged/mongoose) - - [bug reports](https://github.com/Automattic/mongoose/issues/) - - [help forum](http://groups.google.com/group/mongoose-orm) - - [MongoDB support](https://docs.mongodb.org/manual/support/) - - [Mongoose Slack Channel](https://mongoosejs.slack.com/) + - [Bug Reports](https://github.com/Automattic/mongoose/issues/) + - [Mongoose Slack Channel](http://slack.mongoosejs.io/) + - [Help Forum](http://groups.google.com/group/mongoose-orm) + - [MongoDB Support](https://docs.mongodb.org/manual/support/) ## Plugins From 2a52bde92f6233e82d35d06bb67426d126d18d99 Mon Sep 17 00:00:00 2001 From: Timbo White <> Date: Fri, 16 Sep 2016 17:13:12 +0000 Subject: [PATCH 0847/2240] fix #3719 --- lib/cast.js | 4 ++- test/model.query.casting.test.js | 60 ++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/lib/cast.js b/lib/cast.js index e8179307348..98435b6e4bc 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -203,7 +203,9 @@ module.exports = function cast(schema, obj) { } if ($cond === '$not') { - cast(schema, nested); + //cast(schema.paths[path], nested); + //cast(schematype.caster.schema, nested); + cast(schematype.caster ? schematype.caster.schema : schema, nested); } else { val[$cond] = schematype.castForQuery($cond, nested); } diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index b29202bc376..53a8c1fa768 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -883,6 +883,66 @@ describe('model query casting', function() { }); }); }); + + it('should cast subdoc _id typed as String to String in $elemMatch gh3719', function(done) { + var db = start(); + + var child = new Schema({ + _id: {type: String} + }, {_id: false}); + + var parent = new Schema({ + children: [child] + }); + + var Parent = db.model('gh3719-1', parent); + + Parent.create({children: [{ _id: 'foobar' }] }, function(error) { + assert.ifError(error); + test(); + }); + + function test() { + Parent.find({ + $and: [{children: {$elemMatch: {_id: 'foobar'}}}] + }, function(error, docs) { + assert.ifError(error); + + assert.equal(docs.length, 1); + db.close(done); + }); + } + }); + + it('should cast subdoc _id typed as String to String in $elemMatch inside $not gh3719', function(done) { + var db = start(); + + var child = new Schema({ + _id: {type: String} + }, {_id: false}); + + var parent = new Schema({ + children: [child] + }); + + var Parent = db.model('gh3719-2', parent); + + Parent.create({children: [{ _id: 'foobar' }] }, function(error) { + assert.ifError(error); + test(); + }); + + function test() { + Parent.find({ + $and: [{children: {$not: {$elemMatch: {_id: 'foobar'}}}}] + }, function(error, docs) { + assert.ifError(error); + + assert.equal(docs.length, 0); + db.close(done); + }); + } + }); }); it('works with $all (gh-3394)', function(done) { From 8b5864b1d48fdfe38caf7afade4bb6e59278965d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 16 Sep 2016 18:38:52 -0700 Subject: [PATCH 0848/2240] style: fix merge issues --- lib/cast.js | 4 +--- test/model.query.casting.test.js | 12 ++++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index 98435b6e4bc..32605327274 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -203,9 +203,7 @@ module.exports = function cast(schema, obj) { } if ($cond === '$not') { - //cast(schema.paths[path], nested); - //cast(schematype.caster.schema, nested); - cast(schematype.caster ? schematype.caster.schema : schema, nested); + cast(schematype.caster ? schematype.caster.schema : schema, nested); } else { val[$cond] = schematype.castForQuery($cond, nested); } diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index 53a8c1fa768..aeaf4903a02 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -888,7 +888,7 @@ describe('model query casting', function() { var db = start(); var child = new Schema({ - _id: {type: String} + _id: {type: String} }, {_id: false}); var parent = new Schema({ @@ -904,12 +904,12 @@ describe('model query casting', function() { function test() { Parent.find({ - $and: [{children: {$elemMatch: {_id: 'foobar'}}}] + $and: [{children: {$elemMatch: {_id: 'foobar'}}}] }, function(error, docs) { assert.ifError(error); assert.equal(docs.length, 1); - db.close(done); + db.close(done); }); } }); @@ -918,7 +918,7 @@ describe('model query casting', function() { var db = start(); var child = new Schema({ - _id: {type: String} + _id: {type: String} }, {_id: false}); var parent = new Schema({ @@ -934,12 +934,12 @@ describe('model query casting', function() { function test() { Parent.find({ - $and: [{children: {$not: {$elemMatch: {_id: 'foobar'}}}}] + $and: [{children: {$not: {$elemMatch: {_id: 'foobar'}}}}] }, function(error, docs) { assert.ifError(error); assert.equal(docs.length, 0); - db.close(done); + db.close(done); }); } }); From 09afd203f8f66db162ff61b26b2c36629491db6e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Sep 2016 15:10:02 -0700 Subject: [PATCH 0849/2240] test(update): repro #4479 --- test/model.update.test.js | 62 ++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 23e1035cae0..dd1db8cf92e 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1042,9 +1042,17 @@ describe('model: update:', function() { }); describe('defaults and validators (gh-860)', function() { - it('applies defaults on upsert', function(done) { - var db = start(); + var db; + + before(function() { + db = start(); + }); + after(function(done) { + db.close(done); + }); + + it('applies defaults on upsert', function(done) { var s = new Schema({topping: {type: String, default: 'bacon'}, base: String}); var Breakfast = db.model('gh-860-0', s); var updateOptions = {upsert: true, setDefaultsOnInsert: true}; @@ -1054,14 +1062,12 @@ describe('model: update:', function() { assert.ifError(error); assert.equal(breakfast.base, 'eggs'); assert.equal(breakfast.topping, 'bacon'); - db.close(done); + done(); }); }); }); it('doesnt set default on upsert if query sets it', function(done) { - var db = start(); - var s = new Schema({topping: {type: String, default: 'bacon'}, base: String}); var Breakfast = db.model('gh-860-1', s); @@ -1072,15 +1078,12 @@ describe('model: update:', function() { assert.ifError(error); assert.equal(breakfast.base, 'eggs'); assert.equal(breakfast.topping, 'sausage'); - db.close(); done(); }); }); }); it('properly sets default on upsert if query wont set it', function(done) { - var db = start(); - var s = new Schema({topping: {type: String, default: 'bacon'}, base: String}); var Breakfast = db.model('gh-860-2', s); @@ -1091,15 +1094,12 @@ describe('model: update:', function() { assert.ifError(error); assert.equal(breakfast.base, 'eggs'); assert.equal(breakfast.topping, 'bacon'); - db.close(); done(); }); }); }); it('runs validators if theyre set', function(done) { - var db = start(); - var s = new Schema({ topping: { type: String, @@ -1126,15 +1126,12 @@ describe('model: update:', function() { Breakfast.findOne({}, function(error, breakfast) { assert.ifError(error); assert.ok(!breakfast); - db.close(); done(); }); }); }); it('validators handle $unset and $setOnInsert', function(done) { - var db = start(); - var s = new Schema({ steak: {type: String, required: true}, eggs: { @@ -1155,14 +1152,11 @@ describe('model: update:', function() { assert.ok(Object.keys(error.errors).indexOf('steak') !== -1); assert.equal(error.errors.eggs.message, 'Validator failed for path `eggs` with value `softboiled`'); assert.equal(error.errors.steak.message, 'Path `steak` is required.'); - db.close(); done(); }); }); it('min/max, enum, and regex built-in validators work', function(done) { - var db = start(); - var s = new Schema({ steak: {type: String, enum: ['ribeye', 'sirloin']}, eggs: {type: Number, min: 4, max: 6}, @@ -1189,7 +1183,6 @@ describe('model: update:', function() { assert.equal(Object.keys(error.errors)[0], 'bacon'); assert.equal(error.errors.bacon.message, 'Path `bacon` is invalid (none).'); - db.close(); done(); }); }); @@ -1197,8 +1190,6 @@ describe('model: update:', function() { }); it('multiple validation errors', function(done) { - var db = start(); - var s = new Schema({ steak: {type: String, enum: ['ribeye', 'sirloin']}, eggs: {type: Number, min: 4, max: 6}, @@ -1212,14 +1203,11 @@ describe('model: update:', function() { assert.equal(Object.keys(error.errors).length, 2); assert.ok(Object.keys(error.errors).indexOf('steak') !== -1); assert.ok(Object.keys(error.errors).indexOf('eggs') !== -1); - db.close(); done(); }); }); it('validators ignore $inc', function(done) { - var db = start(); - var s = new Schema({ steak: {type: String, required: true}, eggs: {type: Number, min: 4} @@ -1229,14 +1217,11 @@ describe('model: update:', function() { var updateOptions = {runValidators: true}; Breakfast.update({}, {$inc: {eggs: 1}}, updateOptions, function(error) { assert.ifError(error); - db.close(); done(); }); }); it('validators handle positional operator (gh-3167)', function(done) { - var db = start(); - var s = new Schema({ toppings: [{name: {type: String, enum: ['bacon', 'cheese']}}] }); @@ -1250,9 +1235,32 @@ describe('model: update:', function() { function(error) { assert.ok(error); assert.ok(error.errors['toppings.0.name']); - db.close(done); + done(); }); }); + + it('required and single nested (gh-4479)', function(done) { + var FileSchema = new Schema({ + name: { + type: String, + required: true + } + }); + + var CompanySchema = new Schema({ + file: FileSchema + }); + + var Company = db.model('gh4479', CompanySchema); + var update = { file: { name: '' } }; + var options = { runValidators: true }; + Company.update({}, update, options, function(error) { + assert.ok(error); + assert.equal(error.errors['file.name'].message, + 'Path `name` is required.'); + done(); + }); + }); }); it('works with $set and overwrite (gh-2515)', function(done) { From c8df9107479651516beefce92ac6c2d6ea8aaf71 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Sep 2016 15:10:06 -0700 Subject: [PATCH 0850/2240] fix(updateValidators): handle single nested schema subpaths correctly Fix #4479 --- lib/services/common.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/services/common.js b/lib/services/common.js index c09c2f0c014..a9677fd94e8 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -23,11 +23,18 @@ function flatten(update, path, options) { for (var i = 0; i < numKeys; ++i) { var key = keys[i]; var val = update[key]; - if (utils.isMongooseObject(val) && !val.$isSingleNested && !Buffer.isBuffer(val)) { - val = val.toObject({ virtuals: false }); + if (utils.isMongooseObject(val) && !Buffer.isBuffer(val)) { + if (val.$isSingleNested) { + result[path + key] = val; + val = val.toObject({ virtuals: false }); + } else { + val = val.toObject({ virtuals: false }); + result[path + key] = val; + } + } else { + result[path + key] = val; } if (shouldFlatten(val)) { - result[path + key] = val; if (options && options.skipArrays && Array.isArray(val)) { continue; } @@ -38,8 +45,6 @@ function flatten(update, path, options) { if (Array.isArray(val)) { result[path + key] = val; } - } else { - result[path + key] = val; } } From bc51e33705edc77ebb0a723ed35a25b3402e99b5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Sep 2016 20:48:56 -0700 Subject: [PATCH 0851/2240] test(document): coverage for $ignore re: #4480 --- test/document.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 258cc139322..8384837339a 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3172,6 +3172,31 @@ describe('document', function() { done(); }); + it('ignore paths (gh-4480)', function(done) { + var TestSchema = new Schema({ + name: { type: String, required: true } + }); + + var Test = db.model('gh4480', TestSchema); + + Test.create({ name: 'val' }, function(error) { + assert.ifError(error); + Test.findOne(function(error, doc) { + assert.ifError(error); + doc.name = null; + doc.$ignore('name'); + doc.save(function(error) { + assert.ifError(error); + Test.findById(doc._id, function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'val'); + done(); + }); + }); + }); + }); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From dc231dbb7969da28e22c3bfc1f21268024419b02 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Sep 2016 20:49:00 -0700 Subject: [PATCH 0852/2240] feat(document): add $ignore to make a path ignored Re: #4480 --- lib/document.js | 17 +++++++++++++++++ test/document.modified.test.js | 2 -- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 0242dad6511..d6bda01d9bd 100644 --- a/lib/document.js +++ b/lib/document.js @@ -962,6 +962,23 @@ Document.prototype.unmarkModified = function(path) { this.$__.activePaths.init(path); }; +/** + * Don't run validation on this path or persist changes to this path. + * + * ####Example: + * + * doc.foo = null; + * doc.$ignore('foo'); + * doc.save() // changes to foo will not be persisted and validators won't be run + * + * @param {String} path the path to ignore + * @api public + */ + +Document.prototype.$ignore = function(path) { + this.$__.activePaths.ignore(path); +}; + /** * Returns the list of paths that have been modified. * diff --git a/test/document.modified.test.js b/test/document.modified.test.js index 0074cc61684..d222257ba96 100644 --- a/test/document.modified.test.js +++ b/test/document.modified.test.js @@ -514,7 +514,6 @@ describe('document modified', function() { }); }); - it('should reset the modified state after calling unmarkModified', function(done) { var db = start(); var BlogPost = db.model(modelName, collection); @@ -556,6 +555,5 @@ describe('document modified', function() { }); }); }); - }); }); From cb937de071844a61174506ae8fd5d341467f8693 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Sep 2016 20:55:40 -0700 Subject: [PATCH 0853/2240] fix: upgrade mongodb -> 2.2.10 Fix #4517 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64e4f735e91..3401b1ff335 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.5.4", "hooks-fixed": "1.2.0", "kareem": "1.1.3", - "mongodb": "2.2.9", + "mongodb": "2.2.10", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "1.11.0", From e13a453edd79ff910899bcd5caade5b192d21264 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Sep 2016 10:22:26 -0700 Subject: [PATCH 0854/2240] fix(schema): handle calling path.trim() with no args correctly Fix #4042 --- lib/schema/string.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/schema/string.js b/lib/schema/string.js index 545e4bdb3a6..ba25b38044e 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -185,12 +185,15 @@ SchemaString.prototype.uppercase = function() { * @return {SchemaType} this */ -SchemaString.prototype.trim = function() { +SchemaString.prototype.trim = function(shouldTrim) { + if (arguments.length > 0 && !shouldTrim) { + return this; + } return this.set(function(v, self) { if (typeof v !== 'string') { v = self.cast(v); } - if (v && self.options.trim) { + if (v) { return v.trim(); } return v; From 71ce5ae372da38e82ae1678d80fdd9287dc0b7df Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Sep 2016 10:46:05 -0700 Subject: [PATCH 0855/2240] test(query): repro #4500 --- test/model.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index 11f7bfd94c3..378f8685ec1 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5342,6 +5342,24 @@ describe('Model', function() { }); }); + it('emits errors correctly from exec (gh-4500)', function(done) { + var someModel = db.model('gh4500', new Schema({})); + + someModel.on('error', function(error) { + assert.equal(error.message, 'This error will not disappear'); + assert.ok(cleared); + done(); + }); + + var cleared = false; + someModel.findOne().exec(function() { + setImmediate(function() { + cleared = true; + }); + throw new Error('This error will not disappear'); + }); + }); + it('creates new array when initializing from existing doc (gh-4449)', function(done) { var TodoSchema = new mongoose.Schema({ title: String From 8bef459979ce63fcc58d8128a0ee83899f618912 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Sep 2016 10:46:37 -0700 Subject: [PATCH 0856/2240] fix(query): emit error on next tick when exec callback errors Fix #4500 --- lib/query.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/query.js b/lib/query.js index a501cb3b9fa..03e6261846b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2258,6 +2258,13 @@ Query.prototype.exec = function exec(op, callback) { }, function(error) { callback(error); + }). + catch(function(error) { + // If we made it here, we must have an error in the callback re: + // gh-4500, so we need to emit. + setImmediate(function() { + _this.model.emit('error', error); + }); }); } From 1df58bc87db28d49b859e7bfed1fcfa78adda033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20Demette?= Date: Mon, 19 Sep 2016 12:45:56 +0200 Subject: [PATCH 0857/2240] Read Model from this --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 7b72ed92a97..e46e185539c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -389,7 +389,7 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) { } var connection = options.connection || this.connection; - model = Model.compile(name, schema, collection, connection, this); + model = this.Model.compile(name, schema, collection, connection, this); if (!skipInit) { model.init(); From 868b3a66d56a49d3bb952237ed0861dca889510f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Sep 2016 08:36:56 -0700 Subject: [PATCH 0858/2240] fix(schema): expose original object passed to constructor Fix #4486 --- lib/schema.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index ed591ede5fe..d09e28c9b8d 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -70,6 +70,7 @@ function Schema(obj, options) { return new Schema(obj, options); } + this.obj = obj; this.paths = {}; this.subpaths = {}; this.virtuals = {}; @@ -288,6 +289,21 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { ] }); + +/** + * The original object passed to the schema constructor + * + * ####Example: + * + * var schema = new Schema({ a: String }).add({ b: String }); + * schema.obj; // { a: String } + * + * @api public + * @property obj + */ + +Schema.prototype.obj; + /** * Schema as flat paths * From 48ff577387b4b4b518045f7d06cd6f166cdc1f3c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Sep 2016 10:04:42 -0700 Subject: [PATCH 0859/2240] fix(schema): use same check for array types and top-level types Fix #4493 --- lib/schema.js | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index d09e28c9b8d..1ba90b184c0 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -606,17 +606,36 @@ Schema.interpretAsType = function(path, obj, options) { if (typeof cast === 'string') { cast = MongooseTypes[cast.charAt(0).toUpperCase() + cast.substring(1)]; } else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type)) - && utils.getFunctionName(cast.constructor) === 'Object' - && Object.keys(cast).length) { - // The `minimize` and `typeKey` options propagate to child schemas - // declared inline, like `{ arr: [{ val: { $type: String } }] }`. - // See gh-3560 - var childSchemaOptions = {minimize: options.minimize}; - if (options.typeKey) { - childSchemaOptions.typeKey = options.typeKey; + && utils.getFunctionName(cast.constructor) === 'Object') { + if (Object.keys(cast).length) { + // The `minimize` and `typeKey` options propagate to child schemas + // declared inline, like `{ arr: [{ val: { $type: String } }] }`. + // See gh-3560 + var childSchemaOptions = {minimize: options.minimize}; + if (options.typeKey) { + childSchemaOptions.typeKey = options.typeKey; + } + var childSchema = new Schema(cast, childSchemaOptions); + return new MongooseTypes.DocumentArray(path, childSchema, obj); + } else { + // Special case: empty object becomes mixed + return new MongooseTypes.Array(path, MongooseTypes.Mixed, obj); + } + } + + if (cast) { + type = cast[options.typeKey] && (options.typeKey !== 'type' || !cast.type.type) + ? cast[options.typeKey] + : cast; + + name = typeof type === 'string' + ? type + : type.schemaName || utils.getFunctionName(type); + + if (!(name in MongooseTypes)) { + throw new TypeError('Undefined type `' + name + '` at array `' + path + + '`'); } - var childSchema = new Schema(cast, childSchemaOptions); - return new MongooseTypes.DocumentArray(path, childSchema, obj); } return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj); From 705bbedf8f4c65f07a42b3f6ec294fb73148f9ac Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Sep 2016 11:50:13 -0700 Subject: [PATCH 0860/2240] chore: release 4.6.1 --- History.md | 19 +++++++++++++++++++ package.json | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c0600c85183..dfb40ebc362 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,22 @@ +4.6.1 / 2016-09-20 +================== + * fix(query): improve handling of $not with $elemMatch #4531 #3719 [timbowhite](https://github.com/timbowhite) + * fix: upgrade mongodb -> 2.2.10 #4517 + * chore: fix webpack build issue #4512 [saiichihashimoto](https://github.com/saiichihashimoto) + * fix(query): emit error on next tick when exec callback errors #4500 + * test: improve test case #4496 [isayme](https://github.com/isayme) + * fix(schema): use same check for array types and top-level types #4493 + * style: fix indentation in docs #4489 [dhurlburtusa](https://github.com/dhurlburtusa) + * fix(schema): expose original object passed to constructor #4486 + * fix(query): handle findOneAndUpdate with array of arrays #4484 #4470 [fedotov](https://github.com/fedotov) + * feat(document): add $ignore to make a path ignored #4480 + * fix(query): properly handle setting single embedded in update #4475 #4466 #4465 + * fix(updateValidators): handle single nested schema subpaths correctly #4479 + * fix(model): throw handy error when method name conflicts with property name #4475 + * fix(schema): handle .set() with array field #4472 + * fix(query): check nested path when avoiding double-validating Mixed #4441 + * fix(schema): handle calling path.trim() with no args correctly #4042 + 4.6.0 / 2016-09-02 ================== * docs(document): clarify the findById and findByIdAndUpdate examples #4471 [mdcanham](https://github.com/mdcanham) diff --git a/package.json b/package.json index 3401b1ff335..63076581697 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.6.0", + "version": "4.6.1", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 0e3cfb8ff5846fa20dfd560c7f8e752cc55f0681 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Sep 2016 14:50:59 -0700 Subject: [PATCH 0861/2240] chore: now working on 4.6.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 63076581697..d6ac7dd5cc7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.6.1", + "version": "4.6.2-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 8e7d355fc861c1623a0848bc61d1a3370fa9f96d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Sep 2016 14:51:12 -0700 Subject: [PATCH 0862/2240] docs: add missing comment --- lib/drivers/index.web.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/drivers/index.web.js b/lib/drivers/index.web.js index c4883c9ad5b..f833eb223fd 100644 --- a/lib/drivers/index.web.js +++ b/lib/drivers/index.web.js @@ -1 +1,5 @@ +/*! + * ignore + */ + module.exports = require('./browser'); From 637270f956d99ef0ffa323d254f07920b8ecd7b0 Mon Sep 17 00:00:00 2001 From: Volodymyr Fedyk Date: Wed, 21 Sep 2016 09:24:08 +0300 Subject: [PATCH 0863/2240] fix wrong link in documentation Existing link didn't go anywhere. --- lib/schematype.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schematype.js b/lib/schematype.js index a69be4533bd..8c796d9bb18 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -398,7 +398,7 @@ SchemaType.prototype.get = function(fn) { * * ####Error message templates: * - * From the examples above, you may have noticed that error messages support basic templating. There are a few other template keywords besides `{PATH}` and `{VALUE}` too. To find out more, details are available [here](#error_messages_MongooseError-messages) + * From the examples above, you may have noticed that error messages support basic templating. There are a few other template keywords besides `{PATH}` and `{VALUE}` too. To find out more, details are available [here](#error_messages_MongooseError.messages) * * ####Asynchronous validation: * From 8f2360b7bbfc0486ad3833a53083334fc0e04c3b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 22 Sep 2016 16:28:43 -0700 Subject: [PATCH 0864/2240] fix: use replSet option if replset not specified Fix #4535 --- lib/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index 7b72ed92a97..2a7dbb61e2b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -178,11 +178,12 @@ Mongoose.prototype.createConnection = function(uri, options) { var conn = new Connection(this); this.connections.push(conn); + var rsOption = options && (options.replset || options.replSet); if (arguments.length) { if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) { conn.openSet.apply(conn, arguments); - } else if (options && options.replset && - (options.replset.replicaSet || options.replset.rs_name)) { + } else if (rsOption && + (rsOption.replicaSet || rsOption.rs_name)) { conn.openSet.apply(conn, arguments); } else { conn.open.apply(conn, arguments); From e42e5a0a2d22420f21d41a299cfd49aca4ef2e2e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 22 Sep 2016 17:36:30 -0700 Subject: [PATCH 0865/2240] refactor(types): rely on toBSON() instead of manually doing toObject() Re: #4519 --- lib/schema/array.js | 9 ++------- lib/types/array.js | 6 ++++++ lib/types/documentarray.js | 6 ++++++ lib/types/embedded.js | 4 ++++ lib/types/subdocument.js | 4 ++++ test/query.test.js | 10 +++++----- 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index be7a4cdcdc0..7a0331ccef7 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -18,7 +18,6 @@ var Mixed = require('./mixed'); var cast = require('../cast'); var util = require('util'); var utils = require('../utils'); -var isMongooseObject = utils.isMongooseObject; var castToNumber = require('./operators/helpers').castToNumber; var geospatial = require('./operators/geospatial'); @@ -216,18 +215,14 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { if (method) { v = method.call(caster, v); } - return isMongooseObject(v) ? - v.toObject({virtuals: false}) : - v; + return v; }); } else if (method) { val = method.call(caster, val); } } - return val && isMongooseObject(val) ? - val.toObject({virtuals: false}) : - val; + return val; }; function cast$all(val) { diff --git a/lib/types/array.js b/lib/types/array.js index 044d5de9ddd..af8cd7f0a31 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -51,6 +51,12 @@ function MongooseArray(values, path, doc) { } MongooseArray.mixin = { + /*! + * ignore + */ + toBSON: function() { + return this.toObject({ virtuals: false }); + }, /** * Stores a queue of atomic operations to perform diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index f18bde1c659..b3e932cf74d 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -77,6 +77,12 @@ function MongooseDocumentArray(values, path, doc) { */ // MongooseDocumentArray.mixin = Object.create( MongooseArray.mixin ); MongooseDocumentArray.mixin = { + /*! + * ignore + */ + toBSON: function() { + return this.toObject({ virtuals: false }); + }, /** * Overrides MongooseArray#cast diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 811e9322f6c..6433c7b95a4 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -41,6 +41,10 @@ function EmbeddedDocument(obj, parentArr, skipId, fields, index) { EmbeddedDocument.prototype = Object.create(Document.prototype); EmbeddedDocument.prototype.constructor = EmbeddedDocument; +EmbeddedDocument.prototype.toBSON = function() { + return this.toObject({ virtuals: false }); +}; + /** * Marks the embedded doc modified. * diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 37da6965576..96f22df104a 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -17,6 +17,10 @@ function Subdocument(value, fields) { Subdocument.prototype = Object.create(Document.prototype); +Subdocument.prototype.toBSON = function() { + return this.toObject({ virtuals: false }); +}, + /** * Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3) * diff --git a/test/query.test.js b/test/query.test.js index b0342c51b89..ad7b9212d8d 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -888,7 +888,7 @@ describe('Query', function() { assert.equal(params.array.$ne, 5); assert.equal(params.ids.$ne, id); params.comments.$ne._id.toHexString(); - assert.deepEqual(params.comments.$ne, castedComment); + assert.deepEqual(params.comments.$ne.toObject(), castedComment); assert.equal(params.strings.$ne, 'Hi there'); assert.equal(params.numbers.$ne, 10000); @@ -903,7 +903,7 @@ describe('Query', function() { assert.ok(params.ids.$ne instanceof Array); assert.equal(params.ids.$ne[0].toString(), id.toString()); assert.ok(params.comments.$ne instanceof Array); - assert.deepEqual(params.comments.$ne[0], castedComment); + assert.deepEqual(params.comments.$ne[0].toObject(), castedComment); assert.ok(params.strings.$ne instanceof Array); assert.equal(params.strings.$ne[0], 'Hi there'); assert.ok(params.numbers.$ne instanceof Array); @@ -945,7 +945,7 @@ describe('Query', function() { assert.equal(params.array, 5); assert.equal(params.ids, id); params.comments._id.toHexString(); - assert.deepEqual(params.comments, castedComment); + assert.deepEqual(params.comments.toObject(), castedComment); assert.equal(params.strings, 'Hi there'); assert.equal(params.numbers, 10000); @@ -960,7 +960,7 @@ describe('Query', function() { assert.ok(params.ids instanceof Array); assert.equal(params.ids[0].toString(), id.toString()); assert.ok(params.comments instanceof Array); - assert.deepEqual(params.comments[0], castedComment); + assert.deepEqual(params.comments[0].toObject(), castedComment); assert.ok(params.strings instanceof Array); assert.equal(params.strings[0], 'Hi there'); assert.ok(params.numbers instanceof Array); @@ -999,7 +999,7 @@ describe('Query', function() { query.cast(Product, params); assert.equal(params.ids.$gt, id); - assert.deepEqual(params.comments.$gt, castedComment); + assert.deepEqual(params.comments.$gt.toObject(), castedComment); assert.equal(params.strings.$gt, 'Hi there'); assert.equal(params.numbers.$gt, 10000); done(); From cb25f8e5db1acf274dcbc3278c50642384bf5f68 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 22 Sep 2016 17:46:44 -0700 Subject: [PATCH 0866/2240] refactor(services): don't convert to pojo in update validators Re: #4519 --- lib/services/common.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/services/common.js b/lib/services/common.js index a9677fd94e8..eccda1e81ea 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -15,7 +15,13 @@ exports.modifiedPaths = modifiedPaths; */ function flatten(update, path, options) { - var keys = Object.keys(update || {}); + var keys; + if (update && utils.isMongooseObject(update) && !Buffer.isBuffer(update)) { + keys = Object.keys(update.toObject({ virtuals: false })); + } else { + keys = Object.keys(update || {}); + } + var numKeys = keys.length; var result = {}; path = path ? path + '.' : ''; @@ -23,17 +29,7 @@ function flatten(update, path, options) { for (var i = 0; i < numKeys; ++i) { var key = keys[i]; var val = update[key]; - if (utils.isMongooseObject(val) && !Buffer.isBuffer(val)) { - if (val.$isSingleNested) { - result[path + key] = val; - val = val.toObject({ virtuals: false }); - } else { - val = val.toObject({ virtuals: false }); - result[path + key] = val; - } - } else { - result[path + key] = val; - } + result[path + key] = val; if (shouldFlatten(val)) { if (options && options.skipArrays && Array.isArray(val)) { continue; From 96f8dc2c805a87dfe02735c1f9cb050f1e00a96f Mon Sep 17 00:00:00 2001 From: isayme Date: Fri, 23 Sep 2016 11:48:54 +0800 Subject: [PATCH 0867/2240] docs: fix link for query cursor --- lib/querycursor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/querycursor.js b/lib/querycursor.js index 3779df08372..455b17d65d1 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -14,7 +14,7 @@ var util = require('util'); * one at a time. * * Unless you're an advanced user, do **not** instantiate this class directly. - * Use [`Query#cursor()`](/api.html#query_Query-cursor) instead. + * Use [`Query#cursor()`](/docs/api.html#query_Query-cursor) instead. * * @param {Query} query * @param {Object} options query options passed to `.find()` From a095e239383aa1c107c972cfc084d3b16598fab9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 22 Sep 2016 23:17:30 -0700 Subject: [PATCH 0868/2240] fix(types): ensure nested single doc schema errors reach update validators Fix #4519 --- lib/services/updateValidators.js | 1 - lib/types/embedded.js | 6 +++++- lib/types/subdocument.js | 1 + test/model.update.test.js | 33 +++++++++++++++++++++++++++++++- test/types.document.test.js | 1 - 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 31161ea19df..ca0b2047b1c 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -66,7 +66,6 @@ module.exports = function(query, schema, castedDoc, options) { if (schemaPath instanceof Mixed && schemaPath.$fullPath !== updates[i]) { return; } - validatorsToExecute.push(function(callback) { schemaPath.doValidate( updatedValues[updates[i]], diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 6433c7b95a4..46c38eae3f6 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -183,7 +183,11 @@ EmbeddedDocument.prototype.inspect = function() { */ EmbeddedDocument.prototype.invalidate = function(path, err, val, first) { + Document.prototype.invalidate.call(this, path, err, val); if (!this.__parent) { + if (err.name === 'ValidatorError') { + return true; + } throw err; } @@ -234,7 +238,7 @@ EmbeddedDocument.prototype.$markValid = function(path) { EmbeddedDocument.prototype.$isValid = function(path) { var index = this.__index; - if (typeof index !== 'undefined') { + if (typeof index !== 'undefined' && this.__parent) { return !this.__parent.$__.validationError || !this.__parent.$__.validationError.errors[this.$__fullPath(path)]; } diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 96f22df104a..465b6e7e834 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -64,6 +64,7 @@ Subdocument.prototype.$markValid = function(path) { }; Subdocument.prototype.invalidate = function(path, err, val) { + Document.prototype.invalidate.call(this, path, err, val); if (this.$parent) { this.$parent.invalidate([this.$basePath, path].join('.'), err, val); } else if (err.kind === 'cast' || err.name === 'CastError') { diff --git a/test/model.update.test.js b/test/model.update.test.js index dd1db8cf92e..877341c27d3 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2058,10 +2058,41 @@ describe('model: update:', function() { {runValidators: true}, function(err) { assert.ifError(err); - assert.equal(validateCalls, 1); // AssertionError: 0 == 1 + assert.equal(validateCalls, 1); db.close(done); } ); }); + + it('single embedded schema under document array (gh-4519)', function(done) { + var PermissionSchema = new mongoose.Schema({ + read: { type: Boolean, required: true }, + write: Boolean + }); + var UserSchema = new mongoose.Schema({ + permission: { + type: PermissionSchema + } + }); + var GroupSchema = new mongoose.Schema({ + users: [UserSchema] + }); + + var Group = db.model('Group', GroupSchema); + var update = { + users:[{ + permission:{} + }] + }; + var opts = { + runValidators: true + }; + + Group.update({}, update, opts, function(error) { + assert.ok(error); + assert.ok(error.errors['users.0.permission']); + done(); + }); + }); }); }); diff --git a/test/types.document.test.js b/test/types.document.test.js index c00f91a8714..1f5663867bb 100644 --- a/test/types.document.test.js +++ b/test/types.document.test.js @@ -74,7 +74,6 @@ describe('types.document', function() { a.validate(function() { assert.ok(a.__parent.$__.validationError instanceof ValidationError); assert.equal(a.__parent.errors['jsconf.ar.0.work'].name, 'ValidatorError'); - assert.equal(a.__parent.$__.validationError.toString(), 'ValidationError: Path `test` is required., Validator failed for path `work` with value `nope`'); done(); }); }); From 91f88c252cad125689c3de2359c9e6b2dcfab207 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 24 Sep 2016 18:45:45 -0700 Subject: [PATCH 0869/2240] test(model): repro #4551 --- test/schema.test.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index fae4307c5ca..734244cef8b 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1625,5 +1625,14 @@ describe('schema', function() { assert.equal(t.a, 42); done(); }); + + it('methods named toString (gh-4551)', function(done) { + this.schema.methods.toString = function() { + return 'test'; + }; + // should not throw + mongoose.model('gh4551', this.schema); + done(); + }); }); }); From dd11fa21af41ba1ef996d781922acb1284355de5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 24 Sep 2016 18:45:49 -0700 Subject: [PATCH 0870/2240] fix(model): don't throw if method name conflicts with Object.prototype prop Fix #4551 --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 2365f76e4bf..874aaa0a2de 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3251,7 +3251,7 @@ var applyMethods = function(model, schema) { }); } for (var method in schema.methods) { - if (schema.tree[method]) { + if (schema.tree.hasOwnProperty(method)) { throw new Error('You have a method and a property in your schema both ' + 'named "' + method + '"'); } From 26b40380f0bc3f5c2e887187340077ee7a2d5394 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 25 Sep 2016 20:16:39 -0700 Subject: [PATCH 0871/2240] refactor: start cleaning up in preparation for `retainKeyOrder` option Re: #4542 --- lib/document.js | 24 ++++++++------- lib/model.js | 7 ++--- lib/query.js | 52 +++++++++++++++++++++++++++++++- lib/schema/embedded.js | 2 +- lib/utils.js | 22 ++++++++------ package.json | 2 +- test/common.js | 5 +-- test/model.query.casting.test.js | 2 +- test/schema.validation.test.js | 11 +++---- 9 files changed, 90 insertions(+), 37 deletions(-) diff --git a/lib/document.js b/lib/document.js index d6bda01d9bd..d3e87df2732 100644 --- a/lib/document.js +++ b/lib/document.js @@ -310,14 +310,15 @@ Document.prototype.init = function(doc, opts, fn) { function init(self, obj, doc, prefix) { prefix = prefix || ''; - var keys = Object.keys(obj), - len = keys.length, - schema, - path, - i; + var keys = Object.keys(obj); + var len = keys.length; + var schema; + var path; + var i; + var index = 0; - while (len--) { - i = keys[len]; + while (index < len) { + i = keys[index++]; path = prefix + i; schema = self.schema.path(path); @@ -503,19 +504,20 @@ Document.prototype.set = function(path, val, type, options) { } var keys = Object.keys(path); - var i = keys.length; + var len = keys.length; + var i = 0; var pathtype; var key; - if (i === 0 && !this.schema.options.minimize) { + if (len === 0 && !this.schema.options.minimize) { if (val) { this.set(val, {}); } return this; } - while (i--) { - key = keys[i]; + while (i < len) { + key = keys[i++]; var pathName = prefix + key; pathtype = this.schema.pathType(pathName); diff --git a/lib/model.js b/lib/model.js index 874aaa0a2de..0db322651b6 100644 --- a/lib/model.js +++ b/lib/model.js @@ -99,11 +99,8 @@ Model.prototype.$__handleSave = function(options, callback) { if (this.isNew) { // send entire doc var toObjectOptions = {}; - if (this.schema.options.toObject && - this.schema.options.toObject.retainKeyOrder) { - toObjectOptions.retainKeyOrder = true; - } + toObjectOptions.retainKeyOrder = true; toObjectOptions.depopulate = 1; toObjectOptions._skipDepopulateTopLevel = true; toObjectOptions.transform = false; @@ -151,6 +148,7 @@ Model.prototype.$__handleSave = function(options, callback) { callback(delta); return; } + var where = this.$__where(delta[0]); if (where instanceof Error) { @@ -3206,6 +3204,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base) // Create custom query constructor model.Query = function() { Query.apply(this, arguments); + this.options.retainKeyOrder = true; }; model.Query.prototype = Object.create(Query.prototype); model.Query.base = Query.base; diff --git a/lib/query.js b/lib/query.js index 03e6261846b..d5b16afb77a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -174,7 +174,7 @@ Query.prototype.toConstructor = function toConstructor() { p.setOptions(this.options); p.op = this.op; - p._conditions = utils.clone(this._conditions); + p._conditions = utils.clone(this._conditions, { retainKeyOrder: true }); p._fields = utils.clone(this._fields); p._update = utils.clone(this._update); p._path = this._path; @@ -1014,6 +1014,7 @@ Query.prototype._optionsForExec = function(model) { var options = Query.base._optionsForExec.call(this); delete options.populate; + delete options.retainKeyOrder; model = model || this.model; if (!model) { @@ -1152,6 +1153,55 @@ Query.prototype.find = function(conditions, callback) { return this; }; +/** + * Merges another Query or conditions object into this one. + * + * When a Query is passed, conditions, field selection and options are merged. + * + * @param {Query|Object} source + * @return {Query} this + */ + +Query.prototype.merge = function (source) { + if (!source) { + return this; + } + + if (source instanceof Query) { + // if source has a feature, apply it to ourselves + + if (source._conditions) { + utils.merge(this._conditions, source._conditions); + } + + if (source._fields) { + this._fields || (this._fields = {}); + utils.merge(this._fields, source._fields); + } + + if (source.options) { + this.options || (this.options = {}); + utils.merge(this.options, source.options); + } + + if (source._update) { + this._update || (this._update = {}); + utils.mergeClone(this._update, source._update); + } + + if (source._distinct) { + this._distinct = source._distinct; + } + + return this; + } + + // plain object + utils.merge(this._conditions, source); + + return this; +}; + /*! * hydrates many documents * diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index ccb7038c7a6..885e3fc9a28 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -43,7 +43,7 @@ function Embedded(schema, path, options) { _embedded.$isSingleNested = true; _embedded.prototype.$basePath = path; _embedded.prototype.toBSON = function() { - return this.toObject({ virtuals: false }); + return this.toObject({ virtuals: false, retainKeyOrder: true }); }; // apply methods diff --git a/lib/utils.js b/lib/utils.js index 5c40d84b4bf..1c52ea23c04 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -381,12 +381,13 @@ exports.random = function() { */ exports.merge = function merge(to, from) { - var keys = Object.keys(from), - i = keys.length, - key; + var keys = Object.keys(from); + var i = 0; + var len = keys.length; + var key; - while (i--) { - key = keys[i]; + while (i < len) { + key = keys[i++]; if (typeof to[key] === 'undefined') { to[key] = from[key]; } else if (exports.isObject(from[key])) { @@ -806,12 +807,13 @@ exports.decorate = function(destination, source) { */ exports.mergeClone = function(to, fromObj) { - var keys = Object.keys(fromObj), - i = keys.length, - key; + var keys = Object.keys(fromObj); + var len = keys.length; + var i = 0; + var key; - while (i--) { - key = keys[i]; + while (i < len) { + key = keys[i++]; if (typeof to[key] === 'undefined') { // make sure to retain key order here because of a bug handling the $each // operator in mongodb 2.4.4 diff --git a/package.json b/package.json index d6ac7dd5cc7..77d8de0262a 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.2.10", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "1.11.0", + "mquery": "2.0.0", "ms": "0.7.1", "muri": "1.1.0", "regexp-clone": "0.0.1", diff --git a/test/common.js b/test/common.js index 077741b6954..9cd8d5b853b 100644 --- a/test/common.js +++ b/test/common.js @@ -162,6 +162,7 @@ before(function(done) { }); after(function(done) { // DropDBs can be extraordinarily slow on 3.2 - this.timeout(120 * 1000); - dropDBs(done); + //this.timeout(120 * 1000); + //dropDBs(done); + done(); }); diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index aeaf4903a02..44839c95b63 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -581,7 +581,7 @@ describe('model query casting', function() { } }); - it('with objects', function(done) { + it('with objects (lv426)', function(done) { var db = start(), Test = db.model('Geo5', geoSchemaObject, 'y' + random()); diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 0f389b26463..7c1a2a74b2a 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -932,19 +932,19 @@ describe('schema', function() { var bad = new Breakfast({foods: [{eggs: 'Not a number'}], id: 'Not a number'}); bad.validate(function(error) { assert.ok(error); - assert.deepEqual(['id', 'foods.0.eggs'], Object.keys(error.errors)); + assert.deepEqual(['foods.0.eggs', 'id'], Object.keys(error.errors).sort()); assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError); // Pushing docs with cast errors bad.foods.push({eggs: 'Also not a number'}); bad.validate(function(error) { - assert.deepEqual(['id', 'foods.0.eggs', 'foods.1.eggs'], Object.keys(error.errors)); + assert.deepEqual(['foods.0.eggs', 'foods.1.eggs', 'id'], Object.keys(error.errors).sort()); assert.ok(error.errors['foods.1.eggs'] instanceof mongoose.Error.CastError); // Splicing docs with cast errors bad.foods.splice(1, 1, {eggs: 'fail1'}, {eggs: 'fail2'}); bad.validate(function(error) { - assert.deepEqual(['id', 'foods.0.eggs', 'foods.1.eggs', 'foods.2.eggs'], Object.keys(error.errors)); + assert.deepEqual(['foods.0.eggs', 'foods.1.eggs', 'foods.2.eggs', 'id'], Object.keys(error.errors).sort()); assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError); assert.ok(error.errors['foods.1.eggs'] instanceof mongoose.Error.CastError); assert.ok(error.errors['foods.2.eggs'] instanceof mongoose.Error.CastError); @@ -952,14 +952,14 @@ describe('schema', function() { // Remove the cast error by setting field bad.foods[2].eggs = 3; bad.validate(function(error) { - assert.deepEqual(['id', 'foods.0.eggs', 'foods.1.eggs'], Object.keys(error.errors)); + assert.deepEqual(['foods.0.eggs', 'foods.1.eggs', 'id'], Object.keys(error.errors).sort()); assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError); assert.ok(error.errors['foods.1.eggs'] instanceof mongoose.Error.CastError); // Remove the cast error using array.set() bad.foods.set(1, {eggs: 1}); bad.validate(function(error) { - assert.deepEqual(['id', 'foods.0.eggs'], Object.keys(error.errors)); + assert.deepEqual(['foods.0.eggs','id'], Object.keys(error.errors).sort()); assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError); done(); @@ -1132,4 +1132,3 @@ describe('schema', function() { }); }); }); - From f2a40b24d68a929d00108c74bde72ab960de5fd8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 26 Sep 2016 18:18:15 -0700 Subject: [PATCH 0872/2240] fix: upgrade to muri 1.1.1 Fix #4556 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d6ac7dd5cc7..1b7b71b5d62 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "mpromise": "0.5.5", "mquery": "1.11.0", "ms": "0.7.1", - "muri": "1.1.0", + "muri": "1.1.1", "regexp-clone": "0.0.1", "sliced": "1.0.1" }, From bdfad3a6cb201e03c3f32d8e920431f50997de9d Mon Sep 17 00:00:00 2001 From: Trej Gun Date: Tue, 27 Sep 2016 09:40:38 +0800 Subject: [PATCH 0873/2240] db.open emits error even if it was caught --- lib/connection.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 796ebd2c30b..8372988591e 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -281,15 +281,17 @@ Connection.prototype.open = function(host, database, port, options, callback) { var Promise = PromiseProvider.get(); var promise = new Promise.ES6(function(resolve, reject) { _this._open(true, function(error) { - callback && callback(error); if (error) { - reject(error); - if (!callback && !promise.$hasHandler) { + if (callback) { + callback(error); + } else if (reject) { + reject(error); + } else { _this.emit('error', error); } - return; + } else { + resolve(); } - resolve(); }); }); return promise; From 3c8db7997e02e93110b3a417640233abc66e9b41 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 27 Sep 2016 19:49:10 -0700 Subject: [PATCH 0874/2240] test(types): repro #4552 --- test/document.populate.test.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/document.populate.test.js b/test/document.populate.test.js index b65c6fb49b8..1035fd83974 100644 --- a/test/document.populate.test.js +++ b/test/document.populate.test.js @@ -614,6 +614,28 @@ describe('document.populate', function() { }); }); + it('does not allow you to call populate() on nested docs (gh-4552)', function(done) { + var EmbeddedSchema = new Schema({ + reference: { + type: mongoose.Schema.ObjectId, + ref: 'Reference' + } + }); + + var ModelSchema = new Schema({ + embedded: EmbeddedSchema + }); + + var Model = db.model('gh4552', ModelSchema); + + var m = new Model({}); + m.embedded = {}; + assert.throws(function() { + m.embedded.populate('reference'); + }, /on nested docs/); + done(); + }); + it('handles pulling from populated array (gh-3579)', function(done) { var db = start(); var barSchema = new Schema({name: String}); From 3fbb315b748908e7785356f3bfb0f23eec2e0440 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 27 Sep 2016 19:49:23 -0700 Subject: [PATCH 0875/2240] fix(types): throw error when populate on subdocs --- lib/types/embedded.js | 10 ++++++++++ lib/types/subdocument.js | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 811e9322f6c..a90f915d239 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -71,6 +71,16 @@ EmbeddedDocument.prototype.markModified = function(path) { } }; +/*! + * ignore + */ + +EmbeddedDocument.prototype.populate = function() { + throw new Error('Mongoose does not support calling populate() on nested ' + + 'docs. Instead of `doc.arr[0].populate("path")`, use ' + + '`doc.populate("arr.0.path")`'); +}; + /** * Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3) * diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 37da6965576..3262d00a074 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -110,6 +110,16 @@ Subdocument.prototype.remove = function(options, callback) { } }; +/*! + * ignore + */ + +Subdocument.prototype.populate = function() { + throw new Error('Mongoose does not support calling populate() on nested ' + + 'docs. Instead of `doc.nested.populate("path")`, use ' + + '`doc.populate("nested.path")`'); +}; + /*! * Registers remove event listeners for triggering * on subdocuments. From bd7b89c0a01f2b1c702862171fcdc7d7ead226f1 Mon Sep 17 00:00:00 2001 From: billouboq Date: Thu, 29 Sep 2016 23:31:44 +0200 Subject: [PATCH 0876/2240] upgrade async to 2.0.1 --- lib/model.js | 6 +++--- lib/schema.js | 6 +++--- lib/services/updateValidators.js | 4 ++-- package.json | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/model.js b/lib/model.js index 874aaa0a2de..ae6fe5bd9ff 100644 --- a/lib/model.js +++ b/lib/model.js @@ -16,7 +16,7 @@ var EventEmitter = require('events').EventEmitter; var util = require('util'); var tick = utils.tick; -var async = require('async'); +var parallel = require('async/parallel'); var PromiseProvider = require('./promise_provider'); var VERSION_WHERE = 1, @@ -1862,7 +1862,7 @@ Model.create = function create(doc, callback) { }); }); - async.parallel(toExecute, function(error, savedDocs) { + parallel(toExecute, function(error, savedDocs) { if (error) { if (cb) { cb(error); @@ -1926,7 +1926,7 @@ Model.insertMany = function(arr, callback) { }); }); - async.parallel(toExecute, function(error, docs) { + parallel(toExecute, function(error, docs) { if (error) { callback && callback(error); return; diff --git a/lib/schema.js b/lib/schema.js index 1ba90b184c0..e3fd7d529b2 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -8,7 +8,7 @@ var VirtualType = require('./virtualtype'); var utils = require('./utils'); var MongooseTypes; var Kareem = require('kareem'); -var async = require('async'); +var each = require('async/each'); var SchemaType = require('./schematype'); var IS_KAREEM_HOOK = { @@ -224,7 +224,7 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { return; } - async.each(subdocs, function(subdoc, cb) { + each(subdocs, function(subdoc, cb) { subdoc.$__preSavingFromParent = true; subdoc.save(function(err) { cb(err); @@ -272,7 +272,7 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { return; } - async.each(subdocs, function(subdoc, cb) { + each(subdocs, function(subdoc, cb) { subdoc.remove({ noop: true }, function(err) { cb(err); }); diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 31161ea19df..84eb484fba5 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -4,7 +4,7 @@ var Mixed = require('../schema/mixed'); var ValidationError = require('../error/validation'); -var async = require('async'); +var parallel = require('async/parallel'); var flatten = require('./common').flatten; var modifiedPaths = require('./common').modifiedPaths; @@ -87,7 +87,7 @@ module.exports = function(query, schema, castedDoc, options) { } return function(callback) { - async.parallel(validatorsToExecute, function() { + parallel(validatorsToExecute, function() { if (validationErrors.length) { var err = new ValidationError(null); for (var i = 0; i < validationErrors.length; ++i) { diff --git a/package.json b/package.json index 1b7b71b5d62..47508c6103f 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ ], "license": "MIT", "dependencies": { - "async": "1.5.2", + "async": "2.0.1", "bson": "~0.5.4", "hooks-fixed": "1.2.0", "kareem": "1.1.3", From 57bee9f39c9cd471d4e3c8ea288ee52820dcb6dc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 29 Sep 2016 22:33:16 -0700 Subject: [PATCH 0877/2240] test(query): repro #4495 --- test/query.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index b0342c51b89..cb70717f1f8 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1735,6 +1735,26 @@ describe('Query', function() { }); }); + it('$not with objects (gh-4495)', function(done) { + var schema = new Schema({ + createdAt: Date + }); + + var M = db.model('gh4495', schema); + var q = M.find({ + createdAt:{ + $not:{ + $gte: '2016/09/02 00:00:00', + $lte: '2016/09/02 23:59:59' + } + } + }); + + assert.ok(q._conditions.createdAt.$not.$gte instanceof Date); + assert.ok(q._conditions.createdAt.$not.$lte instanceof Date); + done(); + }); + it('geoIntersects with mongoose doc as coords (gh-4408)', function(done) { var lineStringSchema = new Schema({ name: String, From 154b2c9b215e5482b57c49ba76af68d600bb2441 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 29 Sep 2016 22:34:08 -0700 Subject: [PATCH 0878/2240] fix(query): cast $not objects Fix #4495 --- lib/cast.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/cast.js b/lib/cast.js index 32605327274..88fbc87d7c7 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -17,6 +17,7 @@ var ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon']; module.exports = function cast(schema, obj) { var paths = Object.keys(obj), i = paths.length, + _keys, any$conditionals, schematype, nested, @@ -203,6 +204,17 @@ module.exports = function cast(schema, obj) { } if ($cond === '$not') { + if (nested && schematype && !schematype.caster) { + _keys = Object.keys(nested); + if (_keys.length && _keys[0].charAt(0) === '$') { + for (var key in nested) { + nested[key] = schematype.castForQuery(key, nested[key]); + } + } else { + val[$cond] = schematype.castForQuery($cond, nested); + } + continue; + } cast(schematype.caster ? schematype.caster.schema : schema, nested); } else { val[$cond] = schematype.castForQuery($cond, nested); From 06d9887de123356a2bb2f91124e4378e71b15d7b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Sep 2016 19:23:59 -0700 Subject: [PATCH 0879/2240] test(document): repro #4540 --- test/document.test.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/document.test.js b/test/document.test.js index 8384837339a..a79714c3f6a 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3115,6 +3115,21 @@ describe('document', function() { }); }); + it('deep default array values (gh-4540)', function(done) { + var schema = new Schema({ + arr: [{ + test: { + type: Array, + default: ['test'] + } + }] + }); + assert.doesNotThrow(function() { + db.model('gh4540', schema); + }); + done(); + }); + it('default values with subdoc array (gh-4390)', function(done) { var childSchema = new Schema({ name: String @@ -3129,7 +3144,12 @@ describe('document', function() { Parent.create({}, function(error, doc) { assert.ifError(error); - assert.deepEqual(doc.toObject().child, [{ name: 'test' }]); + var arr = doc.toObject().child.map(function(doc) { + assert.ok(doc._id); + delete doc._id; + return doc; + }); + assert.deepEqual(arr, [{ name: 'test' }]); done(); }); }); From a02fc73d43fa5e7ff569cc51e270d1f993982b58 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Sep 2016 19:27:26 -0700 Subject: [PATCH 0880/2240] fix(document): don't use init: true when building doc defaults Fix #4540 --- lib/document.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/document.js b/lib/document.js index d6bda01d9bd..ff2e41a91b4 100644 --- a/lib/document.js +++ b/lib/document.js @@ -226,21 +226,21 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) { continue; } - def = type.getDefault(_this, true); + def = type.getDefault(_this, false); if (typeof def !== 'undefined') { doc_[piece] = def; _this.$__.activePaths.default(p); } } else if (included) { // selected field - def = type.getDefault(_this, true); + def = type.getDefault(_this, false); if (typeof def !== 'undefined') { doc_[piece] = def; _this.$__.activePaths.default(p); } } } else { - def = type.getDefault(_this, true); + def = type.getDefault(_this, false); if (typeof def !== 'undefined') { doc_[piece] = def; _this.$__.activePaths.default(p); From 4913935d321efbf2b6dccc4b4ba1679a73d5bd08 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Sep 2016 19:41:30 -0700 Subject: [PATCH 0881/2240] chore: release 4.6.2 --- History.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index dfb40ebc362..b63d2e2ad4f 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,15 @@ +4.6.2 / 2016-09-30 +================== + * chore: upgrade to async 2.0.1 internally #4579 [billouboq](https://github.com/billouboq) + * fix(types): ensure nested single doc schema errors reach update validators #4557 #4519 + * fix(connection): handle rs names with leading numbers (muri 1.1.1) #4556 + * fix(model): don't throw if method name conflicts with Object.prototype prop #4551 + * docs: fix broken link #4544 [VFedyk](https://github.com/VFedyk) + * fix: allow overwriting model on mongoose singleton #4541 [Nainterceptor](https://github.com/Nainterceptor) + * fix(document): don't use init: true when building doc defaults #4540 + * fix(connection): use replSet option if replset not specified #4535 + * fix(query): cast $not objects #4495 + 4.6.1 / 2016-09-20 ================== * fix(query): improve handling of $not with $elemMatch #4531 #3719 [timbowhite](https://github.com/timbowhite) diff --git a/package.json b/package.json index 47508c6103f..4620c9e3d07 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.6.2-pre", + "version": "4.6.2", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 399c6bc0859a8716c9751e7e91248a63b6f1bcdc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Oct 2016 12:01:35 -0700 Subject: [PATCH 0882/2240] chore: now working on 4.6.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4620c9e3d07..1e2b5dceaaf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.6.2", + "version": "4.6.3-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c7fa5f6c1c96779dc5809253bf818d3c7f40e077 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Oct 2016 12:44:12 -0700 Subject: [PATCH 0883/2240] test(model): repro #4561 --- test/model.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index 378f8685ec1..a79cd2c8d08 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5219,6 +5219,8 @@ describe('Model', function() { assert.ok(!docs[1].isNew); assert.ok(docs[0].createdAt); assert.ok(docs[1].createdAt); + assert.strictEqual(docs[0].__v, 0); + assert.strictEqual(docs[1].__v, 0); Movie.find({}, function(error, docs) { assert.ifError(error); assert.equal(docs.length, 2); From c5d64b5a01fc0fc9780b58a8241f73ac1a093138 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Oct 2016 12:44:19 -0700 Subject: [PATCH 0884/2240] fix(model): ensure versionKey gets set in insertMany Fix #4561 --- lib/model.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/model.js b/lib/model.js index ae6fe5bd9ff..922ec1304e8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1932,6 +1932,9 @@ Model.insertMany = function(arr, callback) { return; } var docObjects = docs.map(function(doc) { + if (doc.schema.options.versionKey) { + doc[doc.schema.options.versionKey] = 0; + } if (doc.initializeTimestamps) { return doc.initializeTimestamps().toObject({ virtuals: false }); } From 73a53e058335bdef071f0009e41fb54333ebaa71 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Oct 2016 13:12:57 -0700 Subject: [PATCH 0885/2240] Revert "db.open emits error even if it was caught" --- lib/connection.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 8372988591e..796ebd2c30b 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -281,17 +281,15 @@ Connection.prototype.open = function(host, database, port, options, callback) { var Promise = PromiseProvider.get(); var promise = new Promise.ES6(function(resolve, reject) { _this._open(true, function(error) { + callback && callback(error); if (error) { - if (callback) { - callback(error); - } else if (reject) { - reject(error); - } else { + reject(error); + if (!callback && !promise.$hasHandler) { _this.emit('error', error); } - } else { - resolve(); + return; } + resolve(); }); }); return promise; From b06a53519bcc3f4b8eaed96cb4a1339f144ec259 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Oct 2016 13:22:12 -0700 Subject: [PATCH 0886/2240] test(document): repro #4578 --- test/document.test.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index a79714c3f6a..65e1cc1a811 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3217,6 +3217,30 @@ describe('document', function() { }); }); + it('setting full path under single nested schema works (gh-4578)', function(done) { + var ChildSchema = new mongoose.Schema({ + age: Number + }); + + var ParentSchema = new mongoose.Schema({ + age: Number, + family: { + child: ChildSchema + } + }); + + var M = db.model('gh4578', ParentSchema); + + M.create({ age: 45 }, function(error, doc) { + assert.ifError(error); + assert.ok(!doc.family.child); + doc.set('family.child.age', 15); + assert.ok(doc.family.child.schema); + assert.equal(doc.family.child.toObject().age, 15); + done(); + }); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From af184312bcb2bb5d044e3f27ab077b96c14bd640 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Oct 2016 13:22:17 -0700 Subject: [PATCH 0887/2240] fix(document): ensure single nested docs get initialized correctly when setting nested paths Fix #4578 --- lib/document.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/document.js b/lib/document.js index ff2e41a91b4..fd4484b0e55 100644 --- a/lib/document.js +++ b/lib/document.js @@ -812,13 +812,15 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche } } - var obj = this._doc, - i = 0, - l = parts.length; + var obj = this._doc; + var i = 0; + var l = parts.length; + var cur = ''; for (; i < l; i++) { - var next = i + 1, - last = next === l; + var next = i + 1; + var last = next === l; + cur += (cur ? '.' + parts[i] : parts[i]); if (last) { obj[parts[i]] = val; @@ -832,7 +834,8 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) { obj = obj[parts[i]]; } else { - obj = obj[parts[i]] = {}; + this.set(cur, {}); + obj = obj[parts[i]]; } } } From 63da883c86467d1601014473691174354b92efa8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Oct 2016 15:24:27 -0700 Subject: [PATCH 0888/2240] test(query): repro #4574 --- test/model.findOneAndUpdate.test.js | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 0662680500c..bddb45eb580 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1714,6 +1714,37 @@ describe('model: findByIdAndUpdate:', function() { }); }); + it('should not apply schema transforms (gh-4574)', function(done) { + var options = { + toObject: { + transform: function() { + assert.ok(false, 'should not call transform'); + } + } + }; + + var SubdocSchema = new Schema({ test: String }, options); + + var CollectionSchema = new Schema({ + field1: { type: String }, + field2 : { + arrayField: [SubdocSchema] + } + }, options); + + var Collection = db.model('test', CollectionSchema); + + Collection.create({ field2: { arrayField: [] } }). + then(function(doc) { + return Collection.findByIdAndUpdate(doc._id, { + $push: { 'field2.arrayField': { test: 'test' } } + }, { new: true }); + }). + then(function() { + done(); + }); + }); + it('doesnt do double validation on document arrays during updates (gh-4440)', function(done) { var A = new Schema({str: String}); var B = new Schema({a: [A]}); From 6a6927925f7db483a9ceaaa1ef980957ade06182 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Oct 2016 15:24:55 -0700 Subject: [PATCH 0889/2240] fix: turn off transforms when writing nested docs to db Fix #4574 --- lib/cast.js | 2 +- lib/document.js | 6 +++--- lib/drivers/node-mongodb-native/collection.js | 2 +- lib/model.js | 4 ++-- lib/schema/buffer.js | 2 +- lib/schema/documentarray.js | 2 +- lib/schema/embedded.js | 2 +- lib/services/common.js | 4 ++-- lib/types/array.js | 4 ++-- lib/types/documentarray.js | 2 +- lib/types/embedded.js | 4 ++-- lib/types/subdocument.js | 2 +- lib/utils.js | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index 88fbc87d7c7..3f687d0d7f8 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -144,7 +144,7 @@ module.exports = function cast(schema, obj) { value.$minDistance = numbertype.castForQuery(value.$minDistance); } if (utils.isMongooseObject(value.$geometry)) { - value.$geometry = value.$geometry.toObject({ virtuals: false }); + value.$geometry = value.$geometry.toObject({ transform: false }); } value = value.$geometry.coordinates; } else if (geo === '$geoWithin') { diff --git a/lib/document.js b/lib/document.js index fd4484b0e55..91f73c1d3f5 100644 --- a/lib/document.js +++ b/lib/document.js @@ -548,7 +548,7 @@ Document.prototype.set = function(path, val, type, options) { this.set(prefix + key, path[key], constructing); } else if (pathtype === 'nested' && path[key] instanceof Document) { this.set(prefix + key, - path[key].toObject({virtuals: false}), constructing); + path[key].toObject({transform: false}), constructing); } else if (strict === 'throw') { if (pathtype === 'nested') { throw new ObjectExpectedError(key, path[key]); @@ -1219,7 +1219,7 @@ function _getPathsToValidate(doc) { if (doc.schema.nested[pathToCheck]) { var _v = doc.getValue(pathToCheck); if (isMongooseObject(_v)) { - _v = _v.toObject({ virtuals: false }); + _v = _v.toObject({ transform: false }); } var flat = flatten(_v, '', flattenOptions); var _subpaths = Object.keys(flat).map(function(p) { @@ -1716,7 +1716,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { }, set: function(v) { if (v instanceof Document) { - v = v.toObject(); + v = v.toObject({ transform: false }); } return (this.$__.scope || this).set(path, v); } diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js index 0976ffcce7a..c8e01e7c34b 100644 --- a/lib/drivers/node-mongodb-native/collection.js +++ b/lib/drivers/node-mongodb-native/collection.js @@ -200,7 +200,7 @@ function formatDate(x, key) { x[key] = {inspect: function() { return representation; }}; } function format(obj, sub) { - var x = utils.clone(obj, {retainKeyOrder: 1}); + var x = utils.clone(obj, {retainKeyOrder: 1, transform: false}); var representation; if (x != null) { diff --git a/lib/model.js b/lib/model.js index 922ec1304e8..e431578d2ea 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1936,9 +1936,9 @@ Model.insertMany = function(arr, callback) { doc[doc.schema.options.versionKey] = 0; } if (doc.initializeTimestamps) { - return doc.initializeTimestamps().toObject({ virtuals: false }); + return doc.initializeTimestamps().toObject({ transform: false }); } - return doc.toObject({ virtuals: false }); + return doc.toObject({ transform: false }); }); _this.collection.insertMany(docObjects, function(error) { if (error) { diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js index 035f1273df4..e7fe8143e0e 100644 --- a/lib/schema/buffer.js +++ b/lib/schema/buffer.js @@ -178,7 +178,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) { return handler.call(this, val); } val = $conditional; - return this.cast(val).toObject(); + return this.cast(val).toObject({ transform: false }); }; /*! diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index e3181597796..828811ed338 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -229,7 +229,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { // Check if the document has a different schema (re gh-3701) if ((value[i] instanceof Subdocument) && value[i].schema !== this.casterConstructor.schema) { - value[i] = value[i].toObject({virtuals: false}); + value[i] = value[i].toObject({transform: false}); } if (!(value[i] instanceof Subdocument) && value[i]) { if (init) { diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index ccb7038c7a6..e9752e8dd79 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -43,7 +43,7 @@ function Embedded(schema, path, options) { _embedded.$isSingleNested = true; _embedded.prototype.$basePath = path; _embedded.prototype.toBSON = function() { - return this.toObject({ virtuals: false }); + return this.toObject({ transform: false }); }; // apply methods diff --git a/lib/services/common.js b/lib/services/common.js index eccda1e81ea..d12598760a3 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -17,7 +17,7 @@ exports.modifiedPaths = modifiedPaths; function flatten(update, path, options) { var keys; if (update && utils.isMongooseObject(update) && !Buffer.isBuffer(update)) { - keys = Object.keys(update.toObject({ virtuals: false })); + keys = Object.keys(update.toObject({ transform: false })); } else { keys = Object.keys(update || {}); } @@ -63,7 +63,7 @@ function modifiedPaths(update, path, result) { result[path + key] = true; if (utils.isMongooseObject(val) && !Buffer.isBuffer(val)) { - val = val.toObject({ virtuals: false }); + val = val.toObject({ transform: false }); } if (shouldFlatten(val)) { modifiedPaths(val, path + key, result); diff --git a/lib/types/array.js b/lib/types/array.js index af8cd7f0a31..e63c02367e8 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -55,7 +55,7 @@ MongooseArray.mixin = { * ignore */ toBSON: function() { - return this.toObject({ virtuals: false }); + return this.toObject({ transform: false }); }, /** @@ -202,7 +202,7 @@ MongooseArray.mixin = { if (val[0] instanceof EmbeddedDocument) { selector = pullOp['$or'] || (pullOp['$or'] = []); Array.prototype.push.apply(selector, val.map(function(v) { - return v.toObject({virtuals: false}); + return v.toObject({transform: false}); })); } else { selector = pullOp['_id'] || (pullOp['_id'] = {$in: []}); diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index b3e932cf74d..f6fb2274e8d 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -81,7 +81,7 @@ MongooseDocumentArray.mixin = { * ignore */ toBSON: function() { - return this.toObject({ virtuals: false }); + return this.toObject({ transform: false }); }, /** diff --git a/lib/types/embedded.js b/lib/types/embedded.js index cfca0160ef7..a3c4df4090a 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -42,7 +42,7 @@ EmbeddedDocument.prototype = Object.create(Document.prototype); EmbeddedDocument.prototype.constructor = EmbeddedDocument; EmbeddedDocument.prototype.toBSON = function() { - return this.toObject({ virtuals: false }); + return this.toObject({ transform: false }); }; /** @@ -180,7 +180,7 @@ EmbeddedDocument.prototype.update = function() { */ EmbeddedDocument.prototype.inspect = function() { - return this.toObject(); + return this.toObject({ transform: false, retainKeyOrder: true }); }; /** diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 90060271560..61325370e32 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -18,7 +18,7 @@ function Subdocument(value, fields) { Subdocument.prototype = Object.create(Document.prototype); Subdocument.prototype.toBSON = function() { - return this.toObject({ virtuals: false }); + return this.toObject({ transform: false }); }, /** diff --git a/lib/utils.js b/lib/utils.js index 5c40d84b4bf..6fa6a57822b 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -820,7 +820,7 @@ exports.mergeClone = function(to, fromObj) { if (exports.isObject(fromObj[key])) { var obj = fromObj[key]; if (isMongooseObject(fromObj[key]) && !fromObj[key].isMongooseBuffer) { - obj = obj.toObject({ virtuals: false }); + obj = obj.toObject({ transform: false }); } exports.mergeClone(to[key], obj); } else { From 924e0da945007fbc350e350779cafc3137920076 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Oct 2016 16:21:41 -0700 Subject: [PATCH 0890/2240] test(document): repro #4566 --- test/document.test.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index 65e1cc1a811..b6dc35c02f7 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2848,7 +2848,7 @@ describe('document', function() { done(); }); - it('removing parent doc calls remove hooks on subdocs (gh-2348)', function(done) { + it('removing parent doc calls remove hooks on subdocs (gh-2348) (gh-4566)', function(done) { var ChildSchema = new Schema({ name: String }); @@ -2860,20 +2860,28 @@ describe('document', function() { }); var ParentSchema = new Schema({ - children: [ChildSchema] + children: [ChildSchema], + child: ChildSchema }); var Parent = db.model('gh2348', ParentSchema); - var doc = { children: [{ name: 'Luke' }, { name: 'Leia' }] }; + var doc = { + children: [{ name: 'Jacen' }, { name: 'Jaina' }], + child: { name: 'Anakin' } + }; Parent.create(doc, function(error, doc) { assert.ifError(error); - doc.remove(function(error) { + doc.remove(function(error, doc) { assert.ifError(error); assert.deepEqual(called, { - Luke: true, - Leia: true + Jacen: true, + Jaina: true, + Anakin: true }); + var arr = doc.children.toObject().map(function(v) { return v.name; }); + assert.deepEqual(arr, ['Jacen', 'Jaina']); + assert.equal(doc.child.name, 'Anakin'); done(); }); }); From 409abe05f396189aa7fdd58cc791e20104997bec Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Oct 2016 16:22:04 -0700 Subject: [PATCH 0891/2240] fix(document): don't set single nested subdocs to null when removing parent doc Fix #4566 --- lib/types/subdocument.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 61325370e32..606cfa76ce6 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -108,8 +108,12 @@ Subdocument.prototype.remove = function(options, callback) { options = null; } - this.$parent.set(this.$basePath, null); - registerRemoveListener(this); + // If removing entire doc, no need to remove subdoc + if (!options || !options.noop) { + this.$parent.set(this.$basePath, null); + registerRemoveListener(this); + } + if (typeof callback === 'function') { callback(null); } From e6d2cc2c53ced9410f793904a9c8d3f62158cc07 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 3 Oct 2016 19:40:55 -0700 Subject: [PATCH 0892/2240] test(schema): repro #4443 --- test/schema.documentarray.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/schema.documentarray.test.js b/test/schema.documentarray.test.js index e706555b924..191a57d702e 100644 --- a/test/schema.documentarray.test.js +++ b/test/schema.documentarray.test.js @@ -55,4 +55,19 @@ describe('schema.documentarray', function() { assert.deepEqual(dest.toObject().arr, [{a: 1}, {a: 2}]); done(); }); + + it('sets $implicitlyCreated if created by interpretAsType (gh-4271)', function(done) { + var schema1 = new Schema({ + arr: [{ name: String }] + }); + var schema2 = new Schema({ + arr: [new Schema({ name: String })] + }); + + assert.equal(schema1.childSchemas.length, 1); + assert.equal(schema2.childSchemas.length, 1); + assert.ok(schema1.childSchemas[0].$implicitlyCreated); + assert.ok(!schema2.childSchemas[0].$implicitlyCreated); + done(); + }); }); From 349b6975a7f28a31d9b0deabfaf9a7bc2f90eb2e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 3 Oct 2016 19:41:18 -0700 Subject: [PATCH 0893/2240] feat(schema): set $implicitlyCreated on schema if created by interpretAsType Fix #4443 --- lib/schema.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/schema.js b/lib/schema.js index e3fd7d529b2..89cc6264818 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -616,6 +616,7 @@ Schema.interpretAsType = function(path, obj, options) { childSchemaOptions.typeKey = options.typeKey; } var childSchema = new Schema(cast, childSchemaOptions); + childSchema.$implicitlyCreated = true; return new MongooseTypes.DocumentArray(path, childSchema, obj); } else { // Special case: empty object becomes mixed From b73b635e1291281aa28fb5a94ca7f0a94141d5ff Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 4 Oct 2016 22:34:09 -0700 Subject: [PATCH 0894/2240] test(schema): repro #4548 --- test/schema.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 734244cef8b..c7c0810aa64 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1580,6 +1580,19 @@ describe('schema', function() { done(); }); + it('arrays with typeKey (gh-4548)', function(done) { + var testSchema = new Schema({ + test: [{ $type: String }] + }, { typeKey: '$type' }); + + assert.equal(testSchema.paths.test.caster.instance, 'String'); + + var Test = mongoose.model('gh4548', testSchema); + var test = new Test({ test: [123] }); + assert.strictEqual(test.test[0], '123'); + done(); + }); + describe('remove()', function() { before(function() { this.schema = new Schema({ From 35cd4cd6bf798692e37d4cbac0c5ada760227135 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 4 Oct 2016 22:34:17 -0700 Subject: [PATCH 0895/2240] fix(schema): handle typeKey in arrays Fix #4548 --- lib/schema.js | 2 +- lib/schema/array.js | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 89cc6264818..0d8d0f13c66 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -639,7 +639,7 @@ Schema.interpretAsType = function(path, obj, options) { } } - return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj); + return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj, options); } if (type && type.instanceOfSchema) { diff --git a/lib/schema/array.js b/lib/schema/array.js index 7a0331ccef7..329d410165f 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -31,16 +31,21 @@ var geospatial = require('./operators/geospatial'); * @api public */ -function SchemaArray(key, cast, options) { +function SchemaArray(key, cast, options, schemaOptions) { + var typeKey = 'type'; + if (schemaOptions && schemaOptions.typeKey) { + typeKey = schemaOptions.typeKey; + } + if (cast) { var castOptions = {}; if (utils.getFunctionName(cast.constructor) === 'Object') { - if (cast.type) { + if (cast[typeKey]) { // support { type: Woot } castOptions = utils.clone(cast); // do not alter user arguments - delete castOptions.type; - cast = cast.type; + delete castOptions[typeKey]; + cast = cast[typeKey]; } else { cast = Mixed; } From 78291d38b98b0ebeea7e917682920e9f978276fb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 5 Oct 2016 22:21:54 -0700 Subject: [PATCH 0896/2240] chore: release 4.6.3 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index b63d2e2ad4f..229358012a3 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.6.3 / 2016-10-05 +================== + * fix(document): ensure single nested docs get initialized correctly when setting nested paths #4578 + * fix: turn off transforms when writing nested docs to db #4574 + * fix(document): don't set single nested subdocs to null when removing parent doc #4566 + * fix(model): ensure versionKey gets set in insertMany #4561 + * fix(schema): handle typeKey in arrays #4548 + * feat(schema): set $implicitlyCreated on schema if created by interpretAsType #4443 + 4.6.2 / 2016-09-30 ================== * chore: upgrade to async 2.0.1 internally #4579 [billouboq](https://github.com/billouboq) diff --git a/package.json b/package.json index 1e2b5dceaaf..e75e4933224 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.6.3-pre", + "version": "4.6.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 1d05e3f4ebb2ff75d430e2a7fd35d1280806b44a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 6 Oct 2016 20:32:13 -0700 Subject: [PATCH 0897/2240] chore: now working on 4.6.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e75e4933224..ba020993963 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.6.3", + "version": "4.6.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From d7872d7ccc95658473445f48d2754a4585db7060 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 6 Oct 2016 20:44:14 -0700 Subject: [PATCH 0898/2240] test(model): repro #4590 --- test/model.test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index a79cd2c8d08..41b2c004f00 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5276,6 +5276,34 @@ describe('Model', function() { }); }); + it('insertMany() depopulate (gh-4590)', function(done) { + var personSchema = new Schema({ + name: String + }); + var movieSchema = new Schema({ + name: String, + leadActor: { + type: Schema.Types.ObjectId, + ref: 'gh4590' + } + }); + + var Person = db.model('gh4590', personSchema); + var Movie = db.model('gh4590_0', movieSchema); + + var arnold = new Person({ name: 'Arnold Schwarzenegger' }); + var movies = [{ name: 'Predator', leadActor: arnold }]; + Movie.insertMany(movies, function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 1); + Movie.findOne({ name: 'Predator' }, function(error, doc) { + assert.ifError(error); + assert.equal(doc.leadActor.toHexString(), arnold._id.toHexString()); + done(); + }); + }); + }); + it('insertMany() with promises (gh-4237)', function(done) { var schema = new Schema({ name: String From 752664e60ad7018dfb85b45865c9ecb07faa6a75 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 6 Oct 2016 20:46:06 -0700 Subject: [PATCH 0899/2240] fix(model): make sure to depopulate in insertMany Fix #4590 --- lib/model.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index e431578d2ea..d777c64c0f9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -23,6 +23,12 @@ var VERSION_WHERE = 1, VERSION_INC = 2, VERSION_ALL = VERSION_WHERE | VERSION_INC; +var POJO_TO_OBJECT_OPTIONS = { + depopulate: true, + transform: false, + _skipDepopulateTopLevel: true +}; + /** * Model constructor * @@ -1936,9 +1942,9 @@ Model.insertMany = function(arr, callback) { doc[doc.schema.options.versionKey] = 0; } if (doc.initializeTimestamps) { - return doc.initializeTimestamps().toObject({ transform: false }); + return doc.initializeTimestamps().toObject(POJO_TO_OBJECT_OPTIONS); } - return doc.toObject({ transform: false }); + return doc.toObject(POJO_TO_OBJECT_OPTIONS); }); _this.collection.insertMany(docObjects, function(error) { if (error) { From 4f4732b0660246781d94dcd16753aff844c7a5c8 Mon Sep 17 00:00:00 2001 From: Trej Gun Date: Fri, 7 Oct 2016 16:05:29 +0800 Subject: [PATCH 0900/2240] fixes problem with global plugins and cache --- lib/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index be9aacd0901..24b5b34bc62 100644 --- a/lib/index.js +++ b/lib/index.js @@ -345,12 +345,15 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) { if (schema) { // cache it so we only apply plugins once this.modelSchemas[name] = schema; - this._applyPlugins(schema); } else { throw new mongoose.Error.MissingSchemaError(name); } } + if (schema) { + this._applyPlugins(schema); + } + var model; var sub; From 9912cc0638e9b714b2fb333038e7027e33210a30 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Oct 2016 11:47:16 -0700 Subject: [PATCH 0901/2240] fix(model): buffer autoIndex if bufferCommands disabled Fix #4589 --- lib/collection.js | 6 +++++- lib/model.js | 15 ++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/collection.js b/lib/collection.js index 3aee0aa5f2b..e550ec2da58 100644 --- a/lib/collection.js +++ b/lib/collection.js @@ -117,7 +117,11 @@ Collection.prototype.addQueue = function(name, args) { Collection.prototype.doQueue = function() { for (var i = 0, l = this.queue.length; i < l; i++) { - this[this.queue[i][0]].apply(this, this.queue[i][1]); + if (typeof this.queue[i][0] === 'function') { + this.queue[i][0].apply(this, this.queue[i][1]); + } else { + this[this.queue[i][0]].apply(this, this.queue[i][1]); + } } this.queue = []; var _this = this; diff --git a/lib/model.js b/lib/model.js index d777c64c0f9..89782060e9c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -909,7 +909,7 @@ for (var i in EventEmitter.prototype) { Model.init = function init() { if ((this.schema.options.autoIndex) || (this.schema.options.autoIndex === null && this.db.config.autoIndex)) { - this.ensureIndexes({ __noPromise: true }); + this.ensureIndexes({ __noPromise: true, _automatic: true }); } this.schema.emit('init', this); @@ -952,7 +952,7 @@ Model.ensureIndexes = function ensureIndexes(options, callback) { } if (options && options.__noPromise) { - _ensureIndexes(this, callback); + _ensureIndexes(this, options, callback); return; } @@ -963,7 +963,7 @@ Model.ensureIndexes = function ensureIndexes(options, callback) { var _this = this; var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { - _ensureIndexes(_this, function(error) { + _ensureIndexes(_this, options || {}, function(error) { if (error) { callback && callback(error); reject(error); @@ -974,7 +974,7 @@ Model.ensureIndexes = function ensureIndexes(options, callback) { }); }; -function _ensureIndexes(model, callback) { +function _ensureIndexes(model, options, callback) { var indexes = model.schema.indexes(); if (!indexes.length) { setImmediate(function() { @@ -1020,7 +1020,12 @@ function _ensureIndexes(model, callback) { }; setImmediate(function() { - create(); + // If buffering is off, do this manually. + if (options._automatic && !model.collection.collection) { + model.collection.addQueue(create, []); + } else { + create(); + } }); } From c466f8b30d638482ccdec36944d81b736e0ac805 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Oct 2016 12:24:49 -0700 Subject: [PATCH 0902/2240] test: repro #4455 --- test/types.documentarray.test.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js index 3644b78118c..b5197ae0512 100644 --- a/test/types.documentarray.test.js +++ b/test/types.documentarray.test.js @@ -215,7 +215,7 @@ describe('types.documentarray', function() { assert.ok(!threw); done(); }); - it('passes options to its documents (gh-1415)', function(done) { + it('passes options to its documents (gh-1415) (gh-4455)', function(done) { var subSchema = new Schema({ title: {type: String} }); @@ -235,6 +235,15 @@ describe('types.documentarray', function() { m.docs.push({docs: [{title: 'hello'}]}); var delta = m.$__delta()[1]; assert.equal(delta.$pushAll.docs[0].changed, undefined); + + M = db.model('gh-1415-1', new Schema({docs: [subSchema]}, { + usePushEach: true + })); + m = new M; + m.docs.push({docs: [{title: 'hello'}]}); + delta = m.$__delta()[1]; + assert.equal(delta.$push.docs.$each[0].changed, undefined); + done(); }); it('uses the correct transform (gh-1412)', function(done) { From 992f4f717bef98713429ebb2476beaa677aad01c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Oct 2016 12:26:09 -0700 Subject: [PATCH 0903/2240] fix(model): add usePushEach option for schemas Fix #4455 --- lib/model.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 89782060e9c..5b8242a216d 100644 --- a/lib/model.js +++ b/lib/model.js @@ -388,6 +388,10 @@ function handleAtomics(self, where, delta, data, value) { value.$__getAtomics().forEach(function(atomic) { var op = atomic[0]; var val = atomic[1]; + if (self.schema.options.usePushEach && op === '$pushAll') { + op = '$push'; + val = { $each: val }; + } operand(self, where, delta, data, val, op); }); return; @@ -424,7 +428,7 @@ function handleAtomics(self, where, delta, data, value) { val = atomics[op]; if (isMongooseObject(val)) { - val = val.toObject({depopulate: 1}); + val = val.toObject({depopulate: true, transform: false}); } else if (Array.isArray(val)) { val = val.map(iter); } else if (val.valueOf) { From 19714f0276379580651aa1a1d7739f7c1ee70e80 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Oct 2016 18:43:19 -0700 Subject: [PATCH 0904/2240] test(document): repro #4528 --- test/document.test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/document.test.js b/test/document.test.js index b6dc35c02f7..7a19f2bd25e 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3094,6 +3094,7 @@ describe('document', function() { doc.child = { name: 'Jaina' }; doc.child.name = 'Anakin'; assert.deepEqual(doc.modifiedPaths(), ['child']); + assert.ok(doc.isModified('child.name')); done(); }); }); @@ -3225,7 +3226,7 @@ describe('document', function() { }); }); - it('setting full path under single nested schema works (gh-4578)', function(done) { + it('setting full path under single nested schema works (gh-4578) (gh-4528)', function(done) { var ChildSchema = new mongoose.Schema({ age: Number }); @@ -3244,6 +3245,8 @@ describe('document', function() { assert.ok(!doc.family.child); doc.set('family.child.age', 15); assert.ok(doc.family.child.schema); + assert.ok(doc.isModified('family.child')); + assert.ok(doc.isModified('family.child.age')); assert.equal(doc.family.child.toObject().age, 15); done(); }); From 97f6e6882b18dec5de97f3a73728ed0df0989fad Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Oct 2016 18:43:22 -0700 Subject: [PATCH 0905/2240] fix(document): return isModified true for children of direct modified paths Fix #4528 --- lib/document.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 91f73c1d3f5..2688c2e5693 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1026,9 +1026,15 @@ Document.prototype.isModified = function(paths) { paths = paths.split(' '); } var modified = this.modifiedPaths(); - return paths.some(function(path) { + var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify); + var isModifiedChild = paths.some(function(path) { return !!~modified.indexOf(path); }); + return isModifiedChild || paths.some(function(path) { + return directModifiedPaths.some(function(mod) { + return mod === path || path.indexOf(mod + '.') === 0; + }); + }); } return this.$__.activePaths.some('modify'); }; From 011690e7bf5b795b28eaed5fec4ea7ab371291ed Mon Sep 17 00:00:00 2001 From: Robin Persson Date: Mon, 10 Oct 2016 11:50:27 +0200 Subject: [PATCH 0906/2240] Added $not to SchemaString.prototype.$conditionalHandlers --- lib/schema/string.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/schema/string.js b/lib/schema/string.js index ba25b38044e..02ff495f934 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -475,7 +475,8 @@ SchemaString.prototype.$conditionalHandlers = $lt: handleSingle, $lte: handleSingle, $options: handleSingle, - $regex: handleSingle + $regex: handleSingle, + $not: handleSingle }); /** From 93ee95995184e29724ecec87d2208ca66a515f88 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 10 Oct 2016 21:23:48 -0700 Subject: [PATCH 0907/2240] test(query): repro #4592 --- test/query.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index 710851cfb8d..e98f6d17679 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1798,6 +1798,19 @@ describe('Query', function() { }); }); + it('string with $not (gh-4592)', function(done) { + var TestSchema = new Schema({ + test: String + }); + + var Test = db.model('gh4592', TestSchema); + + Test.findOne({ test: { $not: /test/ } }, function(error) { + assert.ifError(error); + done(); + }); + }); + it('handles geoWithin with mongoose docs (gh-4392)', function(done) { var areaSchema = new Schema({ name: {type: String}, From 6eefbc717e3874ab1d6e883ffdde225a19876cea Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 10 Oct 2016 21:25:10 -0700 Subject: [PATCH 0908/2240] fix(query): cast $not correctly Fix #4592 --- lib/cast.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cast.js b/lib/cast.js index 3f687d0d7f8..7d64209fb26 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -211,7 +211,7 @@ module.exports = function cast(schema, obj) { nested[key] = schematype.castForQuery(key, nested[key]); } } else { - val[$cond] = schematype.castForQuery($cond, nested); + val[$cond] = schematype.castForQuery('$eq', nested); } continue; } From a2f90d80ad0f58c144e7f88e6ab563659526e439 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 12 Oct 2016 18:34:42 -0700 Subject: [PATCH 0909/2240] test(populate): repro #4585 --- test/model.populate.test.js | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index b2d41b3b44c..3338b0557b3 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4272,6 +4272,62 @@ describe('model: populate:', function() { }); }); + it('source array (gh-4585)', function(done) { + var tagSchema = new mongoose.Schema({ + name: String, + tagId: { type:String, unique:true } + }); + + var blogPostSchema = new mongoose.Schema({ + name : String, + body: String, + tags : [String] + }); + + blogPostSchema.virtual('tagsDocuments', { + ref: 'gh4585', // model + localField: 'tags', + foreignField: 'tagId' + }); + + var Tag = db.model('gh4585', tagSchema); + var BlogPost = db.model('gh4585_0', blogPostSchema); + + var tags = [ + { + name : 'angular.js', + tagId : 'angular' + }, + { + name : 'node.js', + tagId : 'node' + }, + { + name : 'javascript', + tagId : 'javascript' + } + ]; + + Tag.create(tags). + then(function() { + return BlogPost.create({ + title: 'test', + tags: ['angular', 'javascript'] + }); + }). + then(function(post) { + return BlogPost.findById(post._id).populate('tagsDocuments'); + }). + then(function(doc) { + assert.equal(doc.tags[0], 'angular'); + assert.equal(doc.tags[1], 'javascript'); + assert.equal(doc.tagsDocuments[0].tagId, 'angular'); + assert.equal(doc.tagsDocuments[1].tagId, 'javascript'); + done(); + }). + catch(done); + }); + it('lean with single result and no justOne (gh-4288)', function(done) { var PersonSchema = new Schema({ name: String, From 687eecde0c1564b873b8e3c0651f1066c47c3379 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 12 Oct 2016 18:34:56 -0700 Subject: [PATCH 0910/2240] fix(populate): copy ids array before modifying Fix #4585 --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 5b8242a216d..70ca2907f2b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3046,7 +3046,7 @@ function convertTo_id(val) { val[i] = val[i]._id; } } - return val; + return [].concat(val); } return val; From 381ee63c67e2f687feac0f4fcdf14f679225488c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 13 Oct 2016 19:52:28 -0700 Subject: [PATCH 0911/2240] fix(connection): add dropDatabase() helper Fix #4490 --- lib/connection.js | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 796ebd2c30b..81852c8eed5 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -295,6 +295,44 @@ Connection.prototype.open = function(host, database, port, options, callback) { return promise; }; +/** + * Helper for `dropDatabase()`. + * + * @param {Function} callback + * @return {Promise} + * @api public + */ + +Connection.prototype.dropDatabase = function(callback) { + var Promise = PromiseProvider.get(); + var _this = this; + var promise = new Promise.ES6(function(resolve, reject) { + if (_this.readyState !== STATES.connected) { + _this.on('open', function() { + _this.db.dropDatabase(function(error) { + if (error) { + reject(error); + } else { + resolve(); + } + }); + }); + } else { + _this.db.dropDatabase(function(error) { + if (error) { + reject(error); + } else { + resolve(); + } + }); + } + }); + if (callback) { + promise.then(function() { callback(); }, callback); + } + return promise; +}; + /** * Opens the connection to a replica set. * From 84d5801936839ca2dccd9fde90eb62689241d794 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 14 Oct 2016 08:48:39 -0700 Subject: [PATCH 0912/2240] docs(connections): add some warnings about buffering Fix #4413 --- docs/connections.jade | 31 +++++++++++++++++++++++++++++++ docs/faq.jade | 8 ++++++++ 2 files changed, 39 insertions(+) diff --git a/docs/connections.jade b/docs/connections.jade index 954f5d9d5ce..5d6c0f259f2 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -19,6 +19,37 @@ block content :markdown See the [mongodb connection string spec](http://docs.mongodb.org/manual/reference/connection-string/) for more detail. + h3#buffering Operation Buffering + :markdown + Mongoose lets you start using your models immediately, without waiting for + mongoose to establish a connection to MongoDB. + + :js + mongoose.connect('mongodb://localhost/myapp'); + var MyModel = mongoose.model('Test', new Schema({ name: String })); + // Works + MyModel.findOne(function(error, result) { /* ... */ }); + + :markdown + That's because mongoose buffers model function calls internally. This + buffering is convenient, but also a common source of confusion. Mongoose + will *not* throw any errors by default if you use a model without + connecting. + + :js + var MyModel = mongoose.model('Test', new Schema({ name: String })); + // Will just hang until mongoose successfully connects + MyModel.findOne(function(error, result) { /* ... */ }); + + setTimeout(function() { + mongoose.connect('mongodb://localhost/myapp'); + }, 60000); + + :markdown + To disable buffering, turn off the [`bufferCommands` option on your schema](http://mongoosejs.com/docs/guide.html#bufferCommands). + If you have `bufferCommands` on and your connection is hanging, try turning + `bufferCommands` off to see if you haven't opened a connection properly. + h3#options Options :markdown The `connect` method also accepts an `options` object which will be passed on to the underlying driver. All options included here take precedence over options passed in the connection string. diff --git a/docs/faq.jade b/docs/faq.jade index 4f4bc593593..4b1f83fc2d6 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -50,6 +50,14 @@ block content doc.createdAt = new Date(2011, 5, 1).setHours(4); doc.save(); // Works + hr#model_functions_hanging + :markdown + **Q**. All function calls on my models hang, what am I doing wrong? + + **A**. By default, mongoose will buffer your function calls until it can + connect to MongoDB. Read the [buffering section of the connection docs](http://mongoosejs.com/docs/connections.html#buffering) + for more information. + hr#enable_debugging :markdown **Q**. How can I enable debugging? From 908ed3ca95b92e5f33447c9f4132b4da514f7f93 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 15 Oct 2016 18:35:59 -0700 Subject: [PATCH 0913/2240] test(document): add repro for #4542 --- test/document.test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 7a19f2bd25e..89475867bb7 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3226,6 +3226,34 @@ describe('document', function() { }); }); + it('composite _ids (gh-4542)', function(done) { + var schema = new Schema({ + _id: { + key1: String, + key2: String + }, + content: String + }, { retainKeyOrder: true }); + + var Model = db.model('gh4542', schema); + + var object = new Model(); + object._id = {key1: 'foo', key2: 'bar'}; + object.save(). + then(function(obj) { + obj.content = 'Hello'; + return obj.save(); + }). + then(function(obj) { + return Model.findOne({ _id: obj._id }); + }). + then(function(obj) { + assert.equal(obj.content, 'Hello'); + done(); + }). + catch(done); + }); + it('setting full path under single nested schema works (gh-4578) (gh-4528)', function(done) { var ChildSchema = new mongoose.Schema({ age: Number From 72c8a5a472b5d944bf0690f4ebc0648eadf3cb44 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 15 Oct 2016 18:36:16 -0700 Subject: [PATCH 0914/2240] feat(schema): add retainKeyOrder prop Fix #4542 --- lib/document.js | 118 +++++++++++++++++++------------ lib/model.js | 4 +- lib/query.js | 12 ++-- lib/schema.js | 3 +- lib/schema/embedded.js | 5 +- lib/utils.js | 30 ++++++-- test/model.query.casting.test.js | 2 +- test/query.test.js | 4 +- test/query.toconstructor.test.js | 6 +- test/schema.validation.test.js | 2 +- 10 files changed, 116 insertions(+), 70 deletions(-) diff --git a/lib/document.js b/lib/document.js index bcb6527a7d4..26d7bf5da82 100644 --- a/lib/document.js +++ b/lib/document.js @@ -317,8 +317,18 @@ function init(self, obj, doc, prefix) { var i; var index = 0; - while (index < len) { - i = keys[index++]; + if (self.schema.options.retainKeyOrder) { + while (index < len) { + _init(index++); + } + } else { + while (len--) { + _init(len); + } + } + + function _init(index) { + i = keys[index]; path = prefix + i; schema = self.schema.path(path); @@ -516,50 +526,13 @@ Document.prototype.set = function(path, val, type, options) { return this; } - while (i < len) { - key = keys[i++]; - var pathName = prefix + key; - pathtype = this.schema.pathType(pathName); - - if (path[key] !== null - && path[key] !== void 0 - // need to know if plain object - no Buffer, ObjectId, ref, etc - && utils.isObject(path[key]) - && (!path[key].constructor || utils.getFunctionName(path[key].constructor) === 'Object') - && pathtype !== 'virtual' - && pathtype !== 'real' - && !(this.$__path(pathName) instanceof MixedSchema) - && !(this.schema.paths[pathName] && - this.schema.paths[pathName].options && - this.schema.paths[pathName].options.ref)) { - this.set(path[key], prefix + key, constructing); - } else if (strict) { - // Don't overwrite defaults with undefined keys (gh-3981) - if (constructing && path[key] === void 0 && - this.get(key) !== void 0) { - continue; - } - - if (pathtype === 'real' || pathtype === 'virtual') { - // Check for setting single embedded schema to document (gh-3535) - if (this.schema.paths[pathName] && - this.schema.paths[pathName].$isSingleNested && - path[key] instanceof Document) { - path[key] = path[key].toObject({virtuals: false}); - } - this.set(prefix + key, path[key], constructing); - } else if (pathtype === 'nested' && path[key] instanceof Document) { - this.set(prefix + key, - path[key].toObject({transform: false}), constructing); - } else if (strict === 'throw') { - if (pathtype === 'nested') { - throw new ObjectExpectedError(key, path[key]); - } else { - throw new StrictModeError(key); - } - } - } else if (path[key] !== void 0) { - this.set(prefix + key, path[key], constructing); + if (this.schema.options.retainKeyOrder) { + while (i < len) { + _handleIndex.call(this, i++); + } + } else { + while (len--) { + _handleIndex.call(this, len); } } @@ -567,6 +540,53 @@ Document.prototype.set = function(path, val, type, options) { } } + function _handleIndex(i) { + key = keys[i]; + var pathName = prefix + key; + pathtype = this.schema.pathType(pathName); + + if (path[key] !== null + && path[key] !== void 0 + // need to know if plain object - no Buffer, ObjectId, ref, etc + && utils.isObject(path[key]) + && (!path[key].constructor || utils.getFunctionName(path[key].constructor) === 'Object') + && pathtype !== 'virtual' + && pathtype !== 'real' + && !(this.$__path(pathName) instanceof MixedSchema) + && !(this.schema.paths[pathName] && + this.schema.paths[pathName].options && + this.schema.paths[pathName].options.ref)) { + this.set(path[key], prefix + key, constructing); + } else if (strict) { + // Don't overwrite defaults with undefined keys (gh-3981) + if (constructing && path[key] === void 0 && + this.get(key) !== void 0) { + return; + } + + if (pathtype === 'real' || pathtype === 'virtual') { + // Check for setting single embedded schema to document (gh-3535) + if (this.schema.paths[pathName] && + this.schema.paths[pathName].$isSingleNested && + path[key] instanceof Document) { + path[key] = path[key].toObject({virtuals: false}); + } + this.set(prefix + key, path[key], constructing); + } else if (pathtype === 'nested' && path[key] instanceof Document) { + this.set(prefix + key, + path[key].toObject({transform: false}), constructing); + } else if (strict === 'throw') { + if (pathtype === 'nested') { + throw new ObjectExpectedError(key, path[key]); + } else { + throw new StrictModeError(key); + } + } + } else if (path[key] !== void 0) { + this.set(prefix + key, path[key], constructing); + } + } + // ensure _strict is honored for obj props // docschema = new Schema({ path: { nest: 'string' }}) // doc.set('path', obj); @@ -1996,7 +2016,11 @@ Document.prototype.$__handleReject = function handleReject(err) { */ Document.prototype.$toObject = function(options, json) { - var defaultOptions = {transform: true, json: json}; + var defaultOptions = { + transform: true, + json: json, + retainKeyOrder: this.schema.options.retainKeyOrder + }; if (options && options.depopulate && !options._skipDepopulateTopLevel && this.$__.wasPopulated) { // populated paths that we set to a document diff --git a/lib/model.js b/lib/model.js index ff9dcd508ee..7583a852f95 100644 --- a/lib/model.js +++ b/lib/model.js @@ -106,7 +106,7 @@ Model.prototype.$__handleSave = function(options, callback) { // send entire doc var toObjectOptions = {}; - toObjectOptions.retainKeyOrder = true; + toObjectOptions.retainKeyOrder = this.schema.options.retainKeyOrder; toObjectOptions.depopulate = 1; toObjectOptions._skipDepopulateTopLevel = true; toObjectOptions.transform = false; @@ -3222,7 +3222,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base) // Create custom query constructor model.Query = function() { Query.apply(this, arguments); - this.options.retainKeyOrder = true; + this.options.retainKeyOrder = model.schema.options.retainKeyOrder; }; model.Query.prototype = Object.create(Query.prototype); model.Query.base = Query.base; diff --git a/lib/query.js b/lib/query.js index d5b16afb77a..a02873371bf 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1162,26 +1162,28 @@ Query.prototype.find = function(conditions, callback) { * @return {Query} this */ -Query.prototype.merge = function (source) { +Query.prototype.merge = function(source) { if (!source) { return this; } + var opts = { retainKeyOrder: this.options.retainKeyOrder, overwrite: true }; + if (source instanceof Query) { // if source has a feature, apply it to ourselves if (source._conditions) { - utils.merge(this._conditions, source._conditions); + utils.merge(this._conditions, source._conditions, opts); } if (source._fields) { this._fields || (this._fields = {}); - utils.merge(this._fields, source._fields); + utils.merge(this._fields, source._fields, opts); } if (source.options) { this.options || (this.options = {}); - utils.merge(this.options, source.options); + utils.merge(this.options, source.options, opts); } if (source._update) { @@ -1197,7 +1199,7 @@ Query.prototype.merge = function (source) { } // plain object - utils.merge(this._conditions, source); + utils.merge(this._conditions, source, opts); return this; }; diff --git a/lib/schema.js b/lib/schema.js index 0d8d0f13c66..adb76dc5425 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -370,7 +370,8 @@ Schema.prototype.defaultOptions = function(options) { _id: true, noVirtualId: false, // deprecated, use { id: false } id: true, - typeKey: 'type' + typeKey: 'type', + retainKeyOrder: false }, options); if (options.read) { diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 1f789f037fc..cb5ed851e5c 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -43,7 +43,10 @@ function Embedded(schema, path, options) { _embedded.$isSingleNested = true; _embedded.prototype.$basePath = path; _embedded.prototype.toBSON = function() { - return this.toObject({ transform: false, retainKeyOrder: true }); + return this.toObject({ + transform: false, + retainKeyOrder: schema.options.retainKeyOrder + }); }; // apply methods diff --git a/lib/utils.js b/lib/utils.js index de87a88cdbc..a5aa720060a 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -380,18 +380,34 @@ exports.random = function() { * @api private */ -exports.merge = function merge(to, from) { +exports.merge = function merge(to, from, options) { + options = options || {}; var keys = Object.keys(from); var i = 0; var len = keys.length; var key; - while (i < len) { - key = keys[i++]; - if (typeof to[key] === 'undefined') { - to[key] = from[key]; - } else if (exports.isObject(from[key])) { - merge(to[key], from[key]); + if (options.retainKeyOrder) { + while (i < len) { + key = keys[i++]; + if (typeof to[key] === 'undefined') { + to[key] = from[key]; + } else if (exports.isObject(from[key])) { + merge(to[key], from[key]); + } else if (options.overwrite) { + to[key] = from[key]; + } + } + } else { + while (len--) { + key = keys[len]; + if (typeof to[key] === 'undefined') { + to[key] = from[key]; + } else if (exports.isObject(from[key])) { + merge(to[key], from[key]); + } else if (options.overwrite) { + to[key] = from[key]; + } } } }; diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index 44839c95b63..aeaf4903a02 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -581,7 +581,7 @@ describe('model query casting', function() { } }); - it('with objects (lv426)', function(done) { + it('with objects', function(done) { var db = start(), Test = db.model('Geo5', geoSchemaObject, 'y' + random()); diff --git a/test/query.test.js b/test/query.test.js index e98f6d17679..28a8fe1dd58 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1153,12 +1153,12 @@ describe('Query', function() { prod.save(function(err) { assert.ifError(err); - Product.findOne(prod, function(err, product) { + Product.findOne({ _id: prod._id }, function(err, product) { assert.ifError(err); assert.equal(product.comments.length, 1); assert.equal(product.comments[0].text, 'hello'); - Product.update(product, prod2doc, function(err) { + Product.update({ _id: prod._id }, prod2doc, function(err) { assert.ifError(err); Product.collection.findOne({_id: product._id}, function(err, doc) { diff --git a/test/query.toconstructor.test.js b/test/query.toconstructor.test.js index 7e097604592..01a32bc3da8 100644 --- a/test/query.toconstructor.test.js +++ b/test/query.toconstructor.test.js @@ -113,7 +113,7 @@ describe('Query:', function() { var nq = prodC(null, {limit: 3}); assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3}); - assert.deepEqual(nq.options, {sort: {title: 1}, limit: 3}); + assert.deepEqual(nq.options, {sort: {title: 1}, limit: 3, retainKeyOrder: false}); done(); }); @@ -125,7 +125,7 @@ describe('Query:', function() { var nq = prodC(null, {limit: 3}); assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3}); - assert.deepEqual(nq.options, {sort: {title: 1}, limit: 3}); + assert.deepEqual(nq.options, {sort: {title: 1}, limit: 3, retainKeyOrder: false}); var nq2 = prodC(null, {limit: 5}); assert.deepEqual(nq._mongooseOptions, {lean: true, limit: 3}); assert.deepEqual(nq2._mongooseOptions, {lean: true, limit: 5}); @@ -136,7 +136,7 @@ describe('Query:', function() { it('creates subclasses of mquery', function(done) { var Product = db.model(prodName); - var opts = {safe: {w: 'majority'}, readPreference: 'p'}; + var opts = {safe: {w: 'majority'}, readPreference: 'p', retainKeyOrder: true}; var match = {title: 'test', count: {$gt: 101}}; var select = {name: 1, count: 0}; var update = {$set: {title: 'thing'}}; diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 7c1a2a74b2a..fc77b9e6594 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -959,7 +959,7 @@ describe('schema', function() { // Remove the cast error using array.set() bad.foods.set(1, {eggs: 1}); bad.validate(function(error) { - assert.deepEqual(['foods.0.eggs','id'], Object.keys(error.errors).sort()); + assert.deepEqual(['foods.0.eggs', 'id'], Object.keys(error.errors).sort()); assert.ok(error.errors['foods.0.eggs'] instanceof mongoose.Error.CastError); done(); From b4f17016bd3824a513eb270f8591ed34e8132c98 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 16 Oct 2016 17:58:35 -0700 Subject: [PATCH 0915/2240] fix: add ability to set promise implementation in browser Fix #4395 --- bin/mongoose.js | 12169 +++++++++++++++++++++++++--------------------- lib/browser.js | 27 + 2 files changed, 6656 insertions(+), 5540 deletions(-) diff --git a/bin/mongoose.js b/bin/mongoose.js index d12af61e179..ac7378e3e13 100644 --- a/bin/mongoose.js +++ b/bin/mongoose.js @@ -30,6 +30,33 @@ module.exports = ES6Promise; (function (Buffer){ /* eslint-env browser */ +var PromiseProvider = require('./promise_provider'); + +/** + * The Mongoose [Promise](#promise_Promise) constructor. + * + * @method Promise + * @api public + */ + +Object.defineProperty(exports, 'Promise', { + get: function() { + return PromiseProvider.get(); + }, + set: function(lib) { + PromiseProvider.set(lib); + } +}); + +/** + * Storage layer for mongoose promises + * + * @method PromiseProvider + * @api public + */ + +exports.PromiseProvider = PromiseProvider; + /** * The [MongooseError](#error_MongooseError) constructor. * @@ -129,7 +156,7 @@ if (typeof window !== 'undefined') { } }).call(this,require("buffer").Buffer) -},{"./document_provider.js":6,"./error":12,"./schema":26,"./schematype.js":41,"./types":48,"./utils.js":51,"./virtualtype":52,"buffer":74}],3:[function(require,module,exports){ +},{"./document_provider.js":6,"./error":12,"./promise_provider":25,"./schema":26,"./schematype.js":41,"./types":48,"./utils.js":51,"./virtualtype":52,"buffer":84}],3:[function(require,module,exports){ /*! * Module dependencies. */ @@ -234,7 +261,7 @@ Document.prototype.constructor = Document; Document.ValidationError = ValidationError; module.exports = exports = Document; -},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":49,"./utils":51,"events":77}],4:[function(require,module,exports){ +},{"./document":5,"./error":12,"./internal":23,"./schema":26,"./types/objectid":49,"./utils":51,"events":87}],4:[function(require,module,exports){ /*! * Module dependencies. */ @@ -242,6 +269,8 @@ module.exports = exports = Document; var utils = require('./utils'); var Types = require('./schema/index'); +var ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon']; + /** * Handles internal casting for queries * @@ -252,6 +281,7 @@ var Types = require('./schema/index'); module.exports = function cast(schema, obj) { var paths = Object.keys(obj), i = paths.length, + _keys, any$conditionals, schematype, nested, @@ -326,10 +356,18 @@ module.exports = function cast(schema, obj) { // handle geo schemas that use object notation // { loc: { long: Number, lat: Number } - var geo = val.$near ? '$near' : - val.$nearSphere ? '$nearSphere' : - val.$within ? '$within' : - val.$geoIntersects ? '$geoIntersects' : ''; + var geo = ''; + if (val.$near) { + geo = '$near'; + } else if (val.$nearSphere) { + geo = '$nearSphere'; + } else if (val.$within) { + geo = '$within'; + } else if (val.$geoIntersects) { + geo = '$geoIntersects'; + } else if (val.$geoWithin) { + geo = '$geoWithin'; + } if (!geo) { continue; @@ -338,9 +376,12 @@ module.exports = function cast(schema, obj) { var numbertype = new Types.Number('__QueryCasting__'); var value = val[geo]; - if (val.$maxDistance) { + if (val.$maxDistance != null) { val.$maxDistance = numbertype.castForQuery(val.$maxDistance); } + if (val.$minDistance != null) { + val.$minDistance = numbertype.castForQuery(val.$minDistance); + } if (geo === '$within') { var withinType = value.$center @@ -360,8 +401,34 @@ module.exports = function cast(schema, obj) { } else if ((geo === '$near' || geo === '$nearSphere' || geo === '$geoIntersects') && value.$geometry && typeof value.$geometry.type === 'string' && Array.isArray(value.$geometry.coordinates)) { - // geojson; cast the coordinates + if (value.$maxDistance != null) { + value.$maxDistance = numbertype.castForQuery(value.$maxDistance); + } + if (value.$minDistance != null) { + value.$minDistance = numbertype.castForQuery(value.$minDistance); + } + if (utils.isMongooseObject(value.$geometry)) { + value.$geometry = value.$geometry.toObject({ transform: false }); + } value = value.$geometry.coordinates; + } else if (geo === '$geoWithin') { + if (value.$geometry) { + if (utils.isMongooseObject(value.$geometry)) { + value.$geometry = value.$geometry.toObject({ virtuals: false }); + } + var geoWithinType = value.$geometry.type; + if (ALLOWED_GEOWITHIN_GEOJSON_TYPES.indexOf(geoWithinType) === -1) { + throw new Error('Invalid geoJSON type for $geoWithin "' + + geoWithinType + '", must be "Polygon" or "MultiPolygon"'); + } + value = value.$geometry.coordinates; + } else { + value = value.$box || value.$polygon || value.$center || + value.$centerSphere; + if (utils.isMongooseObject(value)) { + value = value.toObject({ virtuals: false }); + } + } } _cast(value, numbertype); @@ -394,14 +461,25 @@ module.exports = function cast(schema, obj) { } if ($cond === '$type') { - if (typeof nested !== 'number') { - throw new Error('$type parameter must be Number'); + if (typeof nested !== 'number' && typeof nested !== 'string') { + throw new Error('$type parameter must be number or string'); } continue; } if ($cond === '$not') { - cast(schema, nested); + if (nested && schematype && !schematype.caster) { + _keys = Object.keys(nested); + if (_keys.length && _keys[0].charAt(0) === '$') { + for (var key in nested) { + nested[key] = schematype.castForQuery(key, nested[key]); + } + } else { + val[$cond] = schematype.castForQuery('$eq', nested); + } + continue; + } + cast(schematype.caster ? schematype.caster.schema : schema, nested); } else { val[$cond] = schematype.castForQuery($cond, nested); } @@ -453,6 +531,7 @@ var Schema = require('./schema'); var ObjectExpectedError = require('./error/objectExpected'); var StrictModeError = require('./error/strict'); var ValidatorError = require('./schematype').ValidatorError; +var VersionError = require('./error').VersionError; var utils = require('./utils'); var clone = utils.clone; var isMongooseObject = utils.isMongooseObject; @@ -669,21 +748,21 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) { continue; } - def = type.getDefault(_this, true); + def = type.getDefault(_this, false); if (typeof def !== 'undefined') { doc_[piece] = def; _this.$__.activePaths.default(p); } } else if (included) { // selected field - def = type.getDefault(_this, true); + def = type.getDefault(_this, false); if (typeof def !== 'undefined') { doc_[piece] = def; _this.$__.activePaths.default(p); } } } else { - def = type.getDefault(_this, true); + def = type.getDefault(_this, false); if (typeof def !== 'undefined') { doc_[piece] = def; _this.$__.activePaths.default(p); @@ -945,10 +1024,17 @@ Document.prototype.set = function(path, val, type, options) { } } - var keys = Object.keys(path), - i = keys.length, - pathtype, - key; + var keys = Object.keys(path); + var i = keys.length; + var pathtype; + var key; + + if (i === 0 && !this.schema.options.minimize) { + if (val) { + this.set(val, {}); + } + return this; + } while (i--) { key = keys[i]; @@ -984,7 +1070,7 @@ Document.prototype.set = function(path, val, type, options) { this.set(prefix + key, path[key], constructing); } else if (pathtype === 'nested' && path[key] instanceof Document) { this.set(prefix + key, - path[key].toObject({virtuals: false}), constructing); + path[key].toObject({transform: false}), constructing); } else if (strict === 'throw') { if (pathtype === 'nested') { throw new ObjectExpectedError(key, path[key]); @@ -1010,8 +1096,16 @@ Document.prototype.set = function(path, val, type, options) { (!val.constructor || utils.getFunctionName(val.constructor) === 'Object')) { if (!merge) { this.setValue(path, null); + cleanModifiedSubpaths(this, path); + } + + if (Object.keys(val).length === 0) { + this.setValue(path, {}); + this.markModified(path); + cleanModifiedSubpaths(this, path); + } else { + this.set(val, path, constructing); } - this.set(val, path, constructing); return this; } this.invalidate(path, new MongooseError.CastError('Object', val, path)); @@ -1133,6 +1227,10 @@ Document.prototype.set = function(path, val, type, options) { shouldSet = false; } + if (schema.$isSingleNested) { + cleanModifiedSubpaths(this, path); + } + if (shouldSet) { this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal); } @@ -1140,6 +1238,20 @@ Document.prototype.set = function(path, val, type, options) { return this; }; +/*! + * ignore + */ + +function cleanModifiedSubpaths(doc, path) { + var _modifiedPaths = Object.keys(doc.$__.activePaths.states.modify); + var _numModifiedPaths = _modifiedPaths.length; + for (var j = 0; j < _numModifiedPaths; ++j) { + if (_modifiedPaths[j].indexOf(path + '.') === 0) { + delete doc.$__.activePaths.states.modify[_modifiedPaths[j]]; + } + } +} + /** * Determine if we should mark this change as modified. * @@ -1222,13 +1334,15 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche } } - var obj = this._doc, - i = 0, - l = parts.length; + var obj = this._doc; + var i = 0; + var l = parts.length; + var cur = ''; for (; i < l; i++) { - var next = i + 1, - last = next === l; + var next = i + 1; + var last = next === l; + cur += (cur ? '.' + parts[i] : parts[i]); if (last) { obj[parts[i]] = val; @@ -1242,7 +1356,8 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) { obj = obj[parts[i]]; } else { - obj = obj[parts[i]] = {}; + this.set(cur, {}); + obj = obj[parts[i]]; } } } @@ -1355,6 +1470,40 @@ Document.prototype.markModified = function(path) { this.$__.activePaths.modify(path); }; +/** + * Clears the modified state on the specified path. + * + * ####Example: + * + * doc.foo = 'bar'; + * doc.unmarkModified('foo'); + * doc.save() // changes to foo will not be persisted + * + * @param {String} path the path to unmark modified + * @api public + */ + +Document.prototype.unmarkModified = function(path) { + this.$__.activePaths.init(path); +}; + +/** + * Don't run validation on this path or persist changes to this path. + * + * ####Example: + * + * doc.foo = null; + * doc.$ignore('foo'); + * doc.save() // changes to foo will not be persisted and validators won't be run + * + * @param {String} path the path to ignore + * @api public + */ + +Document.prototype.$ignore = function(path) { + this.$__.activePaths.ignore(path); +}; + /** * Returns the list of paths that have been modified. * @@ -1364,12 +1513,13 @@ Document.prototype.markModified = function(path) { Document.prototype.modifiedPaths = function() { var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify); - return directModifiedPaths.reduce(function(list, path) { var parts = path.split('.'); return list.concat(parts.reduce(function(chains, part, i) { return chains.concat(parts.slice(0, i).concat(part).join('.')); - }, [])); + }, []).filter(function(chain) { + return (list.indexOf(chain) === -1); + })); }, []); }; @@ -1381,20 +1531,34 @@ Document.prototype.modifiedPaths = function() { * ####Example * * doc.set('documents.0.title', 'changed'); - * doc.isModified() // true - * doc.isModified('documents') // true - * doc.isModified('documents.0.title') // true - * doc.isDirectModified('documents') // false + * doc.isModified() // true + * doc.isModified('documents') // true + * doc.isModified('documents.0.title') // true + * doc.isModified('documents otherProp') // true + * doc.isDirectModified('documents') // false * * @param {String} [path] optional * @return {Boolean} * @api public */ -Document.prototype.isModified = function(path) { - return path - ? !!~this.modifiedPaths().indexOf(path) - : this.$__.activePaths.some('modify'); +Document.prototype.isModified = function(paths) { + if (paths) { + if (!Array.isArray(paths)) { + paths = paths.split(' '); + } + var modified = this.modifiedPaths(); + var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify); + var isModifiedChild = paths.some(function(path) { + return !!~modified.indexOf(path); + }); + return isModifiedChild || paths.some(function(path) { + return directModifiedPaths.some(function(mod) { + return mod === path || path.indexOf(mod + '.') === 0; + }); + }); + } + return this.$__.activePaths.some('modify'); }; /** @@ -1529,34 +1693,18 @@ Document.prototype.isSelected = function isSelected(path) { * }); * * @param {Object} optional options internal options - * @param {Function} optional callback called after validation completes, passing an error if one occurred + * @param {Function} callback optional callback called after validation completes, passing an error if one occurred * @return {Promise} Promise * @api public */ Document.prototype.validate = function(options, callback) { - var _this = this; - var Promise = PromiseProvider.get(); if (typeof options === 'function') { callback = options; options = null; } - if (options && options.__noPromise) { - this.$__validate(callback); - return; - } - - return new Promise.ES6(function(resolve, reject) { - _this.$__validate(function(error) { - callback && callback(error); - if (error) { - reject(error); - return; - } - resolve(); - }); - }); + this.$__validate(callback); }; /*! @@ -1599,7 +1747,7 @@ function _getPathsToValidate(doc) { if (doc.schema.nested[pathToCheck]) { var _v = doc.getValue(pathToCheck); if (isMongooseObject(_v)) { - _v = _v.toObject({ virtuals: false }); + _v = _v.toObject({ transform: false }); } var flat = flatten(_v, '', flattenOptions); var _subpaths = Object.keys(flat).map(function(p) { @@ -2096,7 +2244,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { }, set: function(v) { if (v instanceof Document) { - v = v.toObject(); + v = v.toObject({ transform: false }); } return (this.$__.scope || this).set(path, v); } @@ -2287,27 +2435,53 @@ Document.prototype.$__registerHooksFromSchema = function() { var args = [].slice.call(arguments); var lastArg = args.pop(); var fn; + var originalStack = new Error().stack; + var $results; + if (lastArg && typeof lastArg !== 'function') { + args.push(lastArg); + } else { + fn = lastArg; + } - return new Promise.ES6(function(resolve, reject) { - if (lastArg && typeof lastArg !== 'function') { - args.push(lastArg); - } else { - fn = lastArg; - } - args.push(function(error, result) { + var promise = new Promise.ES6(function(resolve, reject) { + args.push(function(error) { if (error) { + // gh-2633: since VersionError is very generic, take the + // stack trace of the original save() function call rather + // than the async trace + if (error instanceof VersionError) { + error.stack = originalStack; + } _this.$__handleReject(error); - fn && fn(error); reject(error); return; } - fn && fn.apply(null, [null].concat(Array.prototype.slice.call(arguments, 1))); - resolve(result); + // There may be multiple results and promise libs other than + // mpromise don't support passing multiple values to `resolve()` + $results = Array.prototype.slice.call(arguments, 1); + resolve.apply(promise, $results); }); _this[newName].apply(_this, args); }); + if (fn) { + if (_this.constructor.$wrapCallback) { + fn = _this.constructor.$wrapCallback(fn); + } + return promise.then( + function() { + process.nextTick(function() { + fn.apply(null, [null].concat($results)); + }); + }, + function(error) { + process.nextTick(function() { + fn(error); + }); + }); + } + return promise; }; toWrap[pointCut].pre.forEach(function(args) { @@ -2485,6 +2659,7 @@ Document.prototype.$toObject = function(options, json) { * schema.options.toObject.transform = function (doc, ret, options) { * // remove the _id of every document before returning the result * delete ret._id; + * return ret; * } * * // without the transformation in the schema @@ -2527,6 +2702,7 @@ Document.prototype.$toObject = function(options, json) { * delete ret[prop]; * }); * } + * return ret; * } * * var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }); @@ -2655,13 +2831,9 @@ Document.prototype.inspect = function(options) { var opts; if (isPOJO) { opts = options; - } else if (this.schema.options.toObject) { - opts = clone(this.schema.options.toObject); - } else { - opts = {}; + opts.minimize = false; + opts.retainKeyOrder = true; } - opts.minimize = false; - opts.retainKeyOrder = true; return this.toObject(opts); }; @@ -2689,6 +2861,10 @@ Document.prototype.toString = function() { */ Document.prototype.equals = function(doc) { + if (!doc) { + return false; + } + var tid = this.get('_id'); var docid = doc.get ? doc.get('_id') : doc; if (!tid && !docid) { @@ -2795,7 +2971,7 @@ Document.prototype.populate = function populate() { * doc.execPopulate().then(resolve, reject); * * - * @see Document.populate #Document_model.populate + * @see Document.populate #document_Document-populate * @api public * @return {Promise} promise that resolves to the document when population is done */ @@ -2873,6 +3049,7 @@ Document.prototype.populated = function(path, val, options) { * If the path was not populated, this is a no-op. * * @param {String} path + * @see Document.populate #document_Document-populate * @api public */ @@ -2909,7 +3086,7 @@ Document.ValidationError = ValidationError; module.exports = exports = Document; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":41,"./services/common":42,"./types/array":44,"./types/documentarray":46,"./types/embedded":47,"./utils":51,"buffer":74,"events":77,"g5I+bs":97,"hooks-fixed":78,"util":101}],6:[function(require,module,exports){ +},{"./error":12,"./error/objectExpected":17,"./error/strict":19,"./internal":23,"./promise_provider":25,"./schema":26,"./schema/mixed":34,"./schematype":41,"./services/common":42,"./types/array":44,"./types/documentarray":46,"./types/embedded":47,"./utils":51,"buffer":84,"events":87,"g5I+bs":133,"hooks-fixed":88,"util":138}],6:[function(require,module,exports){ 'use strict'; /* eslint-env browser */ @@ -2953,7 +3130,7 @@ var Binary = require('bson').Binary; module.exports = exports = Binary; -},{"bson":58}],9:[function(require,module,exports){ +},{"bson":66}],9:[function(require,module,exports){ /*! * Module exports. */ @@ -2978,7 +3155,7 @@ var ObjectId = require('bson').ObjectID; module.exports = exports = ObjectId; -},{"bson":58}],11:[function(require,module,exports){ +},{"bson":66}],11:[function(require,module,exports){ (function (global){ /*! * ignore @@ -3062,6 +3239,7 @@ MongooseError.DivergentArrayError = require('./error/divergentArray'); */ var MongooseError = require('../error.js'); +var util = require('util'); /** * Casting Error constructor. @@ -3073,7 +3251,13 @@ var MongooseError = require('../error.js'); */ function CastError(type, value, path, reason) { - MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '" at path "' + path + '"'); + var stringValue = util.inspect(value); + stringValue = stringValue.replace(/^'/, '"').replace(/'$/, '"'); + if (stringValue.charAt(0) !== '"') { + stringValue = '"' + stringValue + '"'; + } + MongooseError.call(this, 'Cast to ' + type + ' failed for value ' + + stringValue + ' at path "' + path + '"'); if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { @@ -3100,7 +3284,7 @@ CastError.prototype.constructor = MongooseError; module.exports = CastError; -},{"../error.js":12}],14:[function(require,module,exports){ +},{"../error.js":12,"util":138}],14:[function(require,module,exports){ /*! * Module dependencies. @@ -3163,7 +3347,7 @@ module.exports = DivergentArrayError; * * Click the "show code" link below to see all defaults. * - * @property messages + * @static messages * @receiver MongooseError * @api public */ @@ -3401,7 +3585,6 @@ module.exports = exports = ValidationError; */ var MongooseError = require('../error.js'); -var errorMessages = MongooseError.messages; /** * Schema validator error @@ -3414,7 +3597,7 @@ var errorMessages = MongooseError.messages; function ValidatorError(properties) { var msg = properties.message; if (!msg) { - msg = errorMessages.general.default; + msg = MongooseError.messages.general.default; } var message = this.formatMessage(msg, properties); @@ -3480,6 +3663,7 @@ ValidatorError.prototype.toString = function() { module.exports = ValidatorError; },{"../error.js":12}],22:[function(require,module,exports){ +'use strict'; /*! * Module dependencies. @@ -3494,9 +3678,9 @@ var MongooseError = require('../error.js'); * @api private */ -function VersionError() { - MongooseError.call(this, 'No matching document found.'); - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); +function VersionError(doc) { + MongooseError.call(this, 'No matching document found for id "' + doc._id + + '"'); this.name = 'VersionError'; } @@ -3615,6 +3799,29 @@ Promise.prototype = Object.create(MPromise.prototype, { } }); +/*! + * ignore + */ + +Promise.prototype.then = util.deprecate(Promise.prototype.then, + 'Mongoose: mpromise (mongoose\'s default promise library) is deprecated, ' + + 'plug in your own promise library instead: ' + + 'http://mongoosejs.com/docs/promises.html'); + +/** + * ES6-style `.catch()` shorthand + * + * @method catch + * @memberOf Promise + * @param {Function} onReject + * @return {Promise} + * @api public + */ + +Promise.prototype.catch = function(onReject) { + return this.then(null, onReject); +}; + /*! * Override event names for backward compatibility. */ @@ -3839,7 +4046,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject; module.exports = Promise; -},{"mpromise":85,"util":101}],25:[function(require,module,exports){ +},{"mpromise":121,"util":138}],25:[function(require,module,exports){ /*! * Module dependencies. */ @@ -3892,7 +4099,7 @@ Promise.reset = function() { module.exports = Promise; -},{"./ES6Promise":1,"./promise":24,"mquery":90}],26:[function(require,module,exports){ +},{"./ES6Promise":1,"./promise":24,"mquery":126}],26:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -3904,14 +4111,16 @@ var VirtualType = require('./virtualtype'); var utils = require('./utils'); var MongooseTypes; var Kareem = require('kareem'); -var async = require('async'); +var each = require('async/each'); +var SchemaType = require('./schematype'); -var IS_QUERY_HOOK = { +var IS_KAREEM_HOOK = { count: true, find: true, findOne: true, findOneAndUpdate: true, findOneAndRemove: true, + insertMany: true, update: true }; @@ -3953,6 +4162,7 @@ var IS_QUERY_HOOK = { * _When nesting schemas, (`children` in the example above), always declare the child schema first before passing it into its parent._ * * @param {Object} definition + * @param {Object} [options] * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter * @event `init`: Emitted after the schema is compiled into a `Model`. * @api public @@ -3963,6 +4173,7 @@ function Schema(obj, options) { return new Schema(obj, options); } + this.obj = obj; this.paths = {}; this.subpaths = {}; this.virtuals = {}; @@ -3977,10 +4188,12 @@ function Schema(obj, options) { this._requiredpaths = undefined; this.discriminatorMapping = undefined; this._indexedpaths = undefined; + this.query = {}; + this.childSchemas = []; this.s = { hooks: new Kareem(), - queryHooks: IS_QUERY_HOOK + kareemHooks: IS_KAREEM_HOOK }; this.options = this.defaultOptions(options); @@ -4056,76 +4269,144 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { configurable: false, enumerable: false, writable: false, - value: [{ - kind: 'pre', - hook: 'save', - fn: function(next, options) { - // Nested docs have their own presave - if (this.ownerDocument) { - return next(); - } + value: [ + { + kind: 'pre', + hook: 'save', + fn: function(next, options) { + var _this = this; + // Nested docs have their own presave + if (this.ownerDocument) { + return next(); + } - var hasValidateBeforeSaveOption = options && - (typeof options === 'object') && - ('validateBeforeSave' in options); + var hasValidateBeforeSaveOption = options && + (typeof options === 'object') && + ('validateBeforeSave' in options); - var shouldValidate; - if (hasValidateBeforeSaveOption) { - shouldValidate = !!options.validateBeforeSave; - } else { - shouldValidate = this.schema.options.validateBeforeSave; - } + var shouldValidate; + if (hasValidateBeforeSaveOption) { + shouldValidate = !!options.validateBeforeSave; + } else { + shouldValidate = this.schema.options.validateBeforeSave; + } - // Validate - if (shouldValidate) { - // HACK: use $__original_validate to avoid promises so bluebird doesn't - // complain - if (this.$__original_validate) { - this.$__original_validate({__noPromise: true}, function(error) { - next(error); - }); + // Validate + if (shouldValidate) { + // HACK: use $__original_validate to avoid promises so bluebird doesn't + // complain + if (this.$__original_validate) { + this.$__original_validate({__noPromise: true}, function(error) { + return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { + next(error); + }); + }); + } else { + this.validate({__noPromise: true}, function(error) { + return _this.schema.s.hooks.execPost('save:error', _this, [ _this], { error: error }, function(error) { + next(error); + }); + }); + } } else { - this.validate({__noPromise: true}, function(error) { - next(error); - }); + next(); } - } else { - next(); } - } - }, { - kind: 'pre', - hook: 'save', - isAsync: true, - fn: function(next, done) { - var subdocs = this.$__getAllSubdocs(); + }, + { + kind: 'pre', + hook: 'save', + isAsync: true, + fn: function(next, done) { + var _this = this; + var subdocs = this.$__getAllSubdocs(); - if (!subdocs.length || this.$__preSavingFromParent) { - done(); - next(); - return; - } + if (!subdocs.length || this.$__preSavingFromParent) { + done(); + next(); + return; + } - async.each(subdocs, function(subdoc, cb) { - subdoc.$__preSavingFromParent = true; - subdoc.save(function(err) { - cb(err); + each(subdocs, function(subdoc, cb) { + subdoc.$__preSavingFromParent = true; + subdoc.save(function(err) { + cb(err); + }); + }, function(error) { + for (var i = 0; i < subdocs.length; ++i) { + delete subdocs[i].$__preSavingFromParent; + } + if (error) { + return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { + done(error); + }); + } + next(); + done(); }); - }, function(error) { - for (var i = 0; i < subdocs.length; ++i) { - delete subdocs[i].$__preSavingFromParent; + } + }, + { + kind: 'pre', + hook: 'validate', + isAsync: true, + fn: function(next, done) { + // Hack to ensure that we always wrap validate() in a promise + next(); + done(); + } + }, + { + kind: 'pre', + hook: 'remove', + isAsync: true, + fn: function(next, done) { + if (this.ownerDocument) { + done(); + next(); + return; } - if (error) { - done(error); + + var subdocs = this.$__getAllSubdocs(); + + if (!subdocs.length || this.$__preSavingFromParent) { + done(); + next(); return; } - next(); - done(); - }); + + each(subdocs, function(subdoc, cb) { + subdoc.remove({ noop: true }, function(err) { + cb(err); + }); + }, function(error) { + if (error) { + done(error); + return; + } + next(); + done(); + }); + } } - }] + ] }); + +/** + * The original object passed to the schema constructor + * + * ####Example: + * + * var schema = new Schema({ a: String }).add({ b: String }); + * schema.obj; // { a: String } + * + * @api public + * @property obj + */ + +Schema.prototype.obj; + /** * Schema as flat paths * @@ -4238,9 +4519,15 @@ Schema.prototype.add = function add(obj, prefix) { this.nested[prefix + key] = true; this.add(obj[key], prefix + key + '.'); } else { + if (prefix) { + this.nested[prefix.substr(0, prefix.length - 1)] = true; + } this.path(prefix + key, obj[key]); // mixed type } } else { + if (prefix) { + this.nested[prefix.substr(0, prefix.length - 1)] = true; + } this.path(prefix + key, obj[key]); } } @@ -4284,7 +4571,7 @@ reserved.validate = // hooks.js reserved._pres = reserved._posts = 1; -/** +/*! * Document keys to print warnings for */ @@ -4358,6 +4645,7 @@ Schema.prototype.path = function(path, obj) { branch[last] = utils.clone(obj); this.paths[path] = Schema.interpretAsType(path, obj, this.options); + if (this.paths[path].$isSingleNested) { for (var key in this.paths[path].schema.paths) { this.singleNestedPaths[path + '.' + key] = @@ -4367,6 +4655,10 @@ Schema.prototype.path = function(path, obj) { this.singleNestedPaths[path + '.' + key] = this.paths[path].schema.singleNestedPaths[key]; } + + this.childSchemas.push(this.paths[path].schema); + } else if (this.paths[path].$isMongooseDocumentArray) { + this.childSchemas.push(this.paths[path].schema); } return this; }; @@ -4410,23 +4702,47 @@ Schema.interpretAsType = function(path, obj, options) { return new MongooseTypes.DocumentArray(path, cast, obj); } + if (Array.isArray(cast)) { + return new MongooseTypes.Array(path, Schema.interpretAsType(path, cast, options), obj); + } + if (typeof cast === 'string') { cast = MongooseTypes[cast.charAt(0).toUpperCase() + cast.substring(1)]; } else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type)) - && utils.getFunctionName(cast.constructor) === 'Object' - && Object.keys(cast).length) { - // The `minimize` and `typeKey` options propagate to child schemas - // declared inline, like `{ arr: [{ val: { $type: String } }] }`. - // See gh-3560 - var childSchemaOptions = {minimize: options.minimize}; - if (options.typeKey) { - childSchemaOptions.typeKey = options.typeKey; + && utils.getFunctionName(cast.constructor) === 'Object') { + if (Object.keys(cast).length) { + // The `minimize` and `typeKey` options propagate to child schemas + // declared inline, like `{ arr: [{ val: { $type: String } }] }`. + // See gh-3560 + var childSchemaOptions = {minimize: options.minimize}; + if (options.typeKey) { + childSchemaOptions.typeKey = options.typeKey; + } + var childSchema = new Schema(cast, childSchemaOptions); + childSchema.$implicitlyCreated = true; + return new MongooseTypes.DocumentArray(path, childSchema, obj); + } else { + // Special case: empty object becomes mixed + return new MongooseTypes.Array(path, MongooseTypes.Mixed, obj); + } + } + + if (cast) { + type = cast[options.typeKey] && (options.typeKey !== 'type' || !cast.type.type) + ? cast[options.typeKey] + : cast; + + name = typeof type === 'string' + ? type + : type.schemaName || utils.getFunctionName(type); + + if (!(name in MongooseTypes)) { + throw new TypeError('Undefined type `' + name + '` at array `' + path + + '`'); } - var childSchema = new Schema(cast, childSchemaOptions); - return new MongooseTypes.DocumentArray(path, childSchema, obj); } - return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj); + return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj, options); } if (type && type.instanceOfSchema) { @@ -4583,9 +4899,9 @@ Schema.prototype.hasMixedParent = function(path) { */ Schema.prototype.setupTimestamp = function(timestamps) { if (timestamps) { - var createdAt = timestamps.createdAt || 'createdAt', - updatedAt = timestamps.updatedAt || 'updatedAt', - schemaAdditions = {}; + var createdAt = timestamps.createdAt || 'createdAt'; + var updatedAt = timestamps.updatedAt || 'updatedAt'; + var schemaAdditions = {}; schemaAdditions[updatedAt] = Date; @@ -4599,7 +4915,7 @@ Schema.prototype.setupTimestamp = function(timestamps) { var defaultTimestamp = new Date(); var auto_id = this._id && this._id.auto; - if (!this[createdAt]) { + if (!this[createdAt] && this.isSelected(createdAt)) { this[createdAt] = auto_id ? this._id.getTimestamp() : defaultTimestamp; } @@ -4612,7 +4928,7 @@ Schema.prototype.setupTimestamp = function(timestamps) { var genUpdates = function() { var now = new Date(); - var updates = {$set: {}, $setOnInsert: {}}; + var updates = { $set: {}, $setOnInsert: {} }; updates.$set[updatedAt] = now; updates.$setOnInsert[createdAt] = now; @@ -4631,16 +4947,81 @@ Schema.prototype.setupTimestamp = function(timestamps) { this.pre('findOneAndUpdate', function(next) { this.findOneAndUpdate({}, genUpdates()); + applyTimestampsToChildren(this); next(); }); this.pre('update', function(next) { this.update({}, genUpdates()); + applyTimestampsToChildren(this); next(); }); } }; +/*! + * ignore + */ + +function applyTimestampsToChildren(query) { + var now = new Date(); + var update = query.getUpdate(); + var keys = Object.keys(update); + var key; + var schema = query.model.schema; + var len; + var createdAt; + var updatedAt; + var timestamps; + var path; + + var hasDollarKey = keys.length && keys[0].charAt(0) === '$'; + + if (hasDollarKey) { + if (update.$push) { + for (key in update.$push) { + if (update.$push[key] && + schema.path(key).$isMongooseDocumentArray && + schema.path(key).schema.options.timestamps) { + timestamps = schema.path(key).schema.options.timestamps; + createdAt = timestamps.createdAt || 'createdAt'; + updatedAt = timestamps.updatedAt || 'updatedAt'; + update.$push[key][updatedAt] = now; + update.$push[key][createdAt] = now; + } + } + } + if (update.$set) { + for (key in update.$set) { + path = schema.path(key); + if (!path) { + continue; + } + if (Array.isArray(update.$set[key]) && path.$isMongooseDocumentArray) { + len = update.$set[key].length; + timestamps = schema.path(key).schema.options.timestamps; + if (timestamps) { + createdAt = timestamps.createdAt || 'createdAt'; + updatedAt = timestamps.updatedAt || 'updatedAt'; + for (var i = 0; i < len; ++i) { + update.$set[key][i][updatedAt] = now; + update.$set[key][i][createdAt] = now; + } + } + } else if (update.$set[key] && path.$isSingleNested) { + timestamps = schema.path(key).schema.options.timestamps; + if (timestamps) { + createdAt = timestamps.createdAt || 'createdAt'; + updatedAt = timestamps.updatedAt || 'updatedAt'; + update.$set[key][updatedAt] = now; + update.$set[key][createdAt] = now; + } + } + } + } + } +} + /*! * ignore */ @@ -4665,8 +5046,14 @@ function getPositionalPathType(self, path) { isNested = false; subpath = subpaths[i]; - if (i === last && val && !val.schema && !/\D/.test(subpath)) { - if (val instanceof MongooseTypes.Array) { + if (i === last && val && !/\D/.test(subpath)) { + if (val.$isMongooseDocumentArray) { + var oldVal = val; + val = new SchemaType(subpath); + val.cast = function(value, doc, init) { + return oldVal.cast(value, doc, init)[0]; + }; + } else if (val instanceof MongooseTypes.Array) { // StringSchema, NumberSchema, etc val = val.caster; } else { @@ -4748,7 +5135,7 @@ Schema.prototype.queue = function(name, args) { Schema.prototype.pre = function() { var name = arguments[0]; - if (IS_QUERY_HOOK[name]) { + if (IS_KAREEM_HOOK[name]) { this.s.hooks.pre.apply(this.s.hooks, arguments); return this; } @@ -4758,28 +5145,36 @@ Schema.prototype.pre = function() { /** * Defines a post hook for the document * - * Post hooks fire `on` the event emitted from document instances of Models compiled from this schema. - * * var schema = new Schema(..); * schema.post('save', function (doc) { * console.log('this fired after a document was saved'); * }); * + * shema.post('find', function(docs) { + * console.log('this fired after you run a find query'); + * }); + * * var Model = mongoose.model('Model', schema); * * var m = new Model(..); - * m.save(function (err) { + * m.save(function(err) { * console.log('this fires after the `post` hook'); * }); * + * m.find(function(err, docs) { + * console.log('this fires after the post find hook'); + * }); + * * @param {String} method name of the method to hook * @param {Function} fn callback - * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3 + * @see middleware http://mongoosejs.com/docs/middleware.html + * @see hooks.js https://www.npmjs.com/package/hooks-fixed + * @see kareem http://npmjs.org/package/kareem * @api public */ Schema.prototype.post = function(method, fn) { - if (IS_QUERY_HOOK[method]) { + if (IS_KAREEM_HOOK[method]) { this.s.hooks.post.apply(this.s.hooks, arguments); return this; } @@ -4790,6 +5185,11 @@ Schema.prototype.post = function(method, fn) { }]); } + if (fn.length === 3) { + this.s.hooks.post(method + ':error', fn); + return this; + } + return this.queue('post', [arguments[0], function(next) { // wrap original function so that the callback goes last, // for compatibility with old code that is using synchronous post hooks @@ -4875,8 +5275,8 @@ Schema.prototype.method = function(name, fn) { * * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics. * - * @param {String} name - * @param {Function} fn + * @param {String|Object} name + * @param {Function} [fn] * @api public */ @@ -5102,18 +5502,68 @@ Schema.prototype.indexes = function() { */ Schema.prototype.virtual = function(name, options) { - var virtuals = this.virtuals; - var parts = name.split('.'); - virtuals[name] = parts.reduce(function(mem, part, i) { - mem[part] || (mem[part] = (i === parts.length - 1) - ? new VirtualType(options, name) - : {}); - return mem[part]; - }, this.tree); - return virtuals[name]; -}; + if (options && options.ref) { + if (!options.localField) { + throw new Error('Reference virtuals require `localField` option'); + } -/** + if (!options.foreignField) { + throw new Error('Reference virtuals require `foreignField` option'); + } + + this.pre('init', function(next, obj) { + if (name in obj) { + if (!this.$$populatedVirtuals) { + this.$$populatedVirtuals = {}; + } + + if (options.justOne) { + this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? + obj[name][0] : + obj[name]; + } else { + this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? + obj[name] : + obj[name] == null ? [] : [obj[name]]; + } + + delete obj[name]; + } + next(); + }); + + var virtual = this.virtual(name); + virtual.options = options; + return virtual. + get(function() { + if (!this.$$populatedVirtuals) { + this.$$populatedVirtuals = {}; + } + if (name in this.$$populatedVirtuals) { + return this.$$populatedVirtuals[name]; + } + return null; + }). + set(function(v) { + if (!this.$$populatedVirtuals) { + this.$$populatedVirtuals = {}; + } + this.$$populatedVirtuals[name] = v; + }); + } + + var virtuals = this.virtuals; + var parts = name.split('.'); + virtuals[name] = parts.reduce(function(mem, part, i) { + mem[part] || (mem[part] = (i === parts.length - 1) + ? new VirtualType(options, name) + : {}); + return mem[part]; + }, this.tree); + return virtuals[name]; +}; + +/** * Returns the virtual type with the given `name`. * * @param {String} name @@ -5159,8 +5609,10 @@ Schema.prototype.remove = function(path) { Schema.prototype._getSchema = function(path) { var _this = this; var pathschema = _this.path(path); + var resultPath = []; if (pathschema) { + pathschema.$fullPath = path; return pathschema; } @@ -5173,9 +5625,12 @@ Schema.prototype._getSchema = function(path) { trypath = parts.slice(0, p).join('.'); foundschema = schema.path(trypath); if (foundschema) { + resultPath.push(trypath); + if (foundschema.caster) { // array of Mixed? if (foundschema.caster instanceof MongooseTypes.Mixed) { + foundschema.caster.$fullPath = resultPath.join('.'); return foundschema.caster; } @@ -5194,6 +5649,9 @@ Schema.prototype._getSchema = function(path) { return search(parts.slice(p), foundschema.schema); } } + + foundschema.$fullPath = resultPath.join('.'); + return foundschema; } } @@ -5309,7 +5767,7 @@ Schema.Types = MongooseTypes = require('./schema/index'); exports.ObjectId = MongooseTypes.ObjectId; }).call(this,require("buffer").Buffer) -},{"./drivers":11,"./schema/index":33,"./utils":51,"./virtualtype":52,"async":54,"buffer":74,"events":77,"kareem":82}],27:[function(require,module,exports){ +},{"./drivers":11,"./schema/index":33,"./schematype":41,"./utils":51,"./virtualtype":52,"async/each":54,"buffer":84,"events":87,"kareem":91}],27:[function(require,module,exports){ /*! * Module dependencies. */ @@ -5328,8 +5786,8 @@ var MongooseArray = require('../types').Array; var EmbeddedDoc = require('../types').Embedded; var Mixed = require('./mixed'); var cast = require('../cast'); +var util = require('util'); var utils = require('../utils'); -var isMongooseObject = utils.isMongooseObject; var castToNumber = require('./operators/helpers').castToNumber; var geospatial = require('./operators/geospatial'); @@ -5343,16 +5801,21 @@ var geospatial = require('./operators/geospatial'); * @api public */ -function SchemaArray(key, cast, options) { +function SchemaArray(key, cast, options, schemaOptions) { + var typeKey = 'type'; + if (schemaOptions && schemaOptions.typeKey) { + typeKey = schemaOptions.typeKey; + } + if (cast) { var castOptions = {}; if (utils.getFunctionName(cast.constructor) === 'Object') { - if (cast.type) { + if (cast[typeKey]) { // support { type: Woot } castOptions = utils.clone(cast); // do not alter user arguments - delete castOptions.type; - cast = cast.type; + delete castOptions[typeKey]; + cast = cast[typeKey]; } else { cast = Mixed; } @@ -5368,7 +5831,12 @@ function SchemaArray(key, cast, options) { : cast; this.casterConstructor = caster; - this.caster = new caster(null, castOptions); + if (typeof caster === 'function') { + this.caster = new caster(null, castOptions); + } else { + this.caster = caster; + } + if (!(this.caster instanceof EmbeddedDoc)) { this.caster.path = key; } @@ -5376,7 +5844,6 @@ function SchemaArray(key, cast, options) { SchemaType.call(this, key, options, 'Array'); - var _this = this; var defaultArr; var fn; @@ -5388,7 +5855,8 @@ function SchemaArray(key, cast, options) { if (!('defaultValue' in this) || this.defaultValue !== void 0) { this.default(function() { var arr = fn ? defaultArr() : defaultArr || []; - return new MongooseArray(arr, _this.path, this); + // Leave it up to `cast()` to convert the array + return arr; }); } } @@ -5461,6 +5929,10 @@ SchemaArray.prototype.cast = function(value, doc, init) { if (!(value && value.isMongooseArray)) { value = new MongooseArray(value, this.path, doc); + } else if (value && value.isMongooseArray) { + // We need to create a new array, otherwise change tracking will + // update the old doc (gh-4449) + value = new MongooseArray(value, this.path, doc); } if (this.caster) { @@ -5470,7 +5942,7 @@ SchemaArray.prototype.cast = function(value, doc, init) { } } catch (e) { // rethrow - throw new CastError(e.type, value, this.path, e); + throw new CastError('[' + e.kind + ']', util.inspect(value), this.path, e); } } @@ -5507,7 +5979,7 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { } else { val = $conditional; var proto = this.casterConstructor.prototype; - var method = proto.castForQuery || proto.cast; + var method = proto && (proto.castForQuery || proto.cast); var caster = this.caster; if (Array.isArray(val)) { @@ -5518,18 +5990,14 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { if (method) { v = method.call(caster, v); } - return isMongooseObject(v) ? - v.toObject({virtuals: false}) : - v; + return v; }); } else if (method) { val = method.call(caster, val); } } - return val && isMongooseObject(val) ? - val.toObject({virtuals: false}) : - val; + return val; }; function cast$all(val) { @@ -5591,6 +6059,7 @@ handle.$within = handle.$geoWithin = geospatial.cast$within; handle.$size = +handle.$minDistance = handle.$maxDistance = castToNumber; handle.$eq = @@ -5609,7 +6078,7 @@ handle.$regex = SchemaArray.prototype.castForQuery; module.exports = SchemaArray; -},{"../cast":4,"../schematype":41,"../types":48,"../utils":51,"./boolean":28,"./buffer":29,"./date":30,"./mixed":34,"./number":35,"./objectid":36,"./operators/geospatial":38,"./operators/helpers":39,"./string":40}],28:[function(require,module,exports){ +},{"../cast":4,"../schematype":41,"../types":48,"../utils":51,"./boolean":28,"./buffer":29,"./date":30,"./mixed":34,"./number":35,"./objectid":36,"./operators/geospatial":38,"./operators/helpers":39,"./string":40,"util":138}],28:[function(require,module,exports){ /*! * Module dependencies. */ @@ -5734,7 +6203,7 @@ var Document; * Buffer SchemaType constructor * * @param {String} key - * @param {SchemaType} cast + * @param {Object} options * @inherits SchemaType * @api public */ @@ -5896,7 +6365,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) { return handler.call(this, val); } val = $conditional; - return this.cast(val).toObject(); + return this.cast(val).toObject({ transform: false }); }; /*! @@ -5906,12 +6375,12 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) { module.exports = SchemaBuffer; }).call(this,require("buffer").Buffer) -},{"../schematype":41,"../types":48,"../utils":51,"./../document":5,"./operators/bitwise":37,"buffer":74}],30:[function(require,module,exports){ +},{"../schematype":41,"../types":48,"../utils":51,"./../document":5,"./operators/bitwise":37,"buffer":84}],30:[function(require,module,exports){ /*! * Module requirements. */ -var errorMessages = require('../error').messages; +var MongooseError = require('../error'); var utils = require('../utils'); var SchemaType = require('../schematype'); @@ -6039,7 +6508,7 @@ SchemaDate.prototype.min = function(value, message) { } if (value) { - var msg = message || errorMessages.Date.min; + var msg = message || MongooseError.messages.Date.min; msg = msg.replace(/{MIN}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString())); var _this = this; this.validators.push({ @@ -6095,7 +6564,7 @@ SchemaDate.prototype.max = function(value, message) { } if (value) { - var msg = message || errorMessages.Date.max; + var msg = message || MongooseError.messages.Date.max; msg = msg.replace(/{MAX}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString())); var _this = this; this.validators.push({ @@ -6126,6 +6595,10 @@ SchemaDate.prototype.cast = function(value) { } if (value instanceof Date) { + if (isNaN(value.valueOf())) { + throw new CastError('date', value, this.path); + } + return value; } @@ -6212,6 +6685,7 @@ var CastError = require('../error/cast'); var MongooseDocumentArray = require('../types/documentarray'); var SchemaType = require('../schematype'); var Subdocument = require('../types/embedded'); +var util = require('util'); /** * SubdocsArray SchemaType constructor @@ -6248,7 +6722,7 @@ function DocumentArray(key, schema, options) { ArrayType.call(this, key, EmbeddedDocument, options); this.schema = schema; - var path = this.path; + this.$isMongooseDocumentArray = true; var fn = this.defaultValue; if (!('defaultValue' in this) || fn !== void 0) { @@ -6257,7 +6731,8 @@ function DocumentArray(key, schema, options) { if (!Array.isArray(arr)) { arr = [arr]; } - return new MongooseDocumentArray(arr, path, this); + // Leave it up to `cast()` to convert this to a documentarray + return arr; }); } } @@ -6415,6 +6890,10 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { doc.removeListener(key, prev._handlers[key]); } } + } else if (value && value.isMongooseDocumentArray) { + // We need to create a new array, otherwise change tracking will + // update the old doc (gh-4449) + value = new MongooseDocumentArray(value, this.path, doc); } i = value.length; @@ -6426,7 +6905,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { // Check if the document has a different schema (re gh-3701) if ((value[i] instanceof Subdocument) && value[i].schema !== this.casterConstructor.schema) { - value[i] = value[i].toObject({virtuals: false}); + value[i] = value[i].toObject({transform: false}); } if (!(value[i] instanceof Subdocument) && value[i]) { if (init) { @@ -6454,7 +6933,9 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { // see gh-746 value[i] = subdoc; } catch (error) { - throw new CastError('embedded', value[i], value._path, error); + var valueInErrorMessage = util.inspect(value[i]); + throw new CastError('embedded', valueInErrorMessage, + value._path, error); } } } @@ -6502,7 +6983,7 @@ function scopePaths(array, fields, init) { module.exports = DocumentArray; -},{"../error/cast":13,"../schematype":41,"../types/documentarray":46,"../types/embedded":47,"./array":27}],32:[function(require,module,exports){ +},{"../error/cast":13,"../schematype":41,"../types/documentarray":46,"../types/embedded":47,"./array":27,"util":138}],32:[function(require,module,exports){ 'use strict'; /*! @@ -6535,6 +7016,11 @@ function Embedded(schema, path, options) { parent.on('save', function() { _this.emit('save', _this); }); + + parent.on('isNew', function(val) { + _this.isNew = val; + _this.emit('isNew', val); + }); } }; _embedded.prototype = Object.create(Subdocument.prototype); @@ -6542,6 +7028,9 @@ function Embedded(schema, path, options) { _embedded.schema = schema; _embedded.$isSingleNested = true; _embedded.prototype.$basePath = path; + _embedded.prototype.toBSON = function() { + return this.toObject({ transform: false }); + }; // apply methods for (var i in schema.methods) { @@ -6587,6 +7076,7 @@ Embedded.prototype.$conditionalHandlers.$geoWithin = geospatial.cast$within; Embedded.prototype.$conditionalHandlers.$geoIntersects = geospatial.cast$geoIntersects; +Embedded.prototype.$conditionalHandlers.$minDistance = castToNumber; Embedded.prototype.$conditionalHandlers.$maxDistance = castToNumber; /** @@ -6627,7 +7117,11 @@ Embedded.prototype.castForQuery = function($conditional, val) { return handler.call(this, val); } val = $conditional; - return new this.caster(val).toObject({virtuals: false}); + if (val == null) { + return val; + } + + return new this.caster(val); }; /** @@ -6788,7 +7282,7 @@ module.exports = Mixed; var SchemaType = require('../schematype'); var CastError = SchemaType.CastError; var handleBitwiseOperator = require('./operators/bitwise'); -var errorMessages = require('../error').messages; +var MongooseError = require('../error'); var utils = require('../utils'); var Document; @@ -6874,7 +7368,7 @@ SchemaNumber.prototype.min = function(value, message) { } if (value !== null && value !== undefined) { - var msg = message || errorMessages.Number.min; + var msg = message || MongooseError.messages.Number.min; msg = msg.replace(/{MIN}/, value); this.validators.push({ validator: this.minValidator = function(v) { @@ -6928,7 +7422,7 @@ SchemaNumber.prototype.max = function(value, message) { } if (value !== null && value !== undefined) { - var msg = message || errorMessages.Number.max; + var msg = message || MongooseError.messages.Number.max; msg = msg.replace(/{MAX}/, value); this.validators.push({ validator: this.maxValidator = function(v) { @@ -7073,7 +7567,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val) { module.exports = SchemaNumber; }).call(this,require("buffer").Buffer) -},{"../error":12,"../schematype":41,"../utils":51,"./../document":5,"./operators/bitwise":37,"buffer":74}],36:[function(require,module,exports){ +},{"../error":12,"../schematype":41,"../utils":51,"./../document":5,"./operators/bitwise":37,"buffer":84}],36:[function(require,module,exports){ (function (Buffer){ /* eslint no-empty: 1 */ @@ -7211,7 +7705,7 @@ ObjectId.prototype.cast = function(value, doc, init) { } if (value._id.toString instanceof Function) { try { - return oid.createFromHexString(value._id.toString()); + return new oid(value._id.toString()); } catch (e) { } } @@ -7219,7 +7713,7 @@ ObjectId.prototype.cast = function(value, doc, init) { if (value.toString instanceof Function) { try { - return oid.createFromHexString(value.toString()); + return new oid(value.toString()); } catch (err) { throw new CastError('ObjectId', value, this.path); } @@ -7284,7 +7778,7 @@ function resetId(v) { module.exports = ObjectId; }).call(this,require("buffer").Buffer) -},{"../schematype":41,"../types/objectid":49,"../utils":51,"./../document":5,"buffer":74}],37:[function(require,module,exports){ +},{"../schematype":41,"../types/objectid":49,"../utils":51,"./../document":5,"buffer":84}],37:[function(require,module,exports){ (function (Buffer){ /*! * Module requirements. @@ -7324,7 +7818,7 @@ function _castNumber(path, num) { module.exports = handleBitwiseOperator; }).call(this,require("buffer").Buffer) -},{"../../error/cast":13,"buffer":74}],38:[function(require,module,exports){ +},{"../../error/cast":13,"buffer":84}],38:[function(require,module,exports){ /*! * Module requirements. */ @@ -7348,6 +7842,8 @@ function cast$near(val) { return val; } + _castMinMaxDistance(this, val); + if (val && val.$geometry) { return cast$geometry(val, this); } @@ -7367,19 +7863,13 @@ function cast$geometry(val, self) { break; } - if (val.$maxDistance) { - val.$maxDistance = castToNumber.call(self, val.$maxDistance); - } + _castMinMaxDistance(this, val); return val; } function cast$within(val) { - var _this = this; - - if (val.$maxDistance) { - val.$maxDistance = castToNumber.call(_this, val.$maxDistance); - } + _castMinMaxDistance(this, val); if (val.$box || val.$polygon) { var type = val.$box ? '$box' : '$polygon'; @@ -7421,6 +7911,15 @@ function cast$geoIntersects(val) { return val; } +function _castMinMaxDistance(self, val) { + if (val.$maxDistance) { + val.$maxDistance = castToNumber.call(self, val.$maxDistance); + } + if (val.$minDistance) { + val.$minDistance = castToNumber.call(self, val.$minDistance); + } +} + },{"../array":27,"./helpers":39}],39:[function(require,module,exports){ 'use strict'; @@ -7465,7 +7964,7 @@ function castArraysOfNumbers(arr, self) { var SchemaType = require('../schematype'); var CastError = SchemaType.CastError; -var errorMessages = require('../error').messages; +var MongooseError = require('../error'); var utils = require('../utils'); var Document; @@ -7553,7 +8052,7 @@ SchemaString.prototype.enum = function() { errorMessage = arguments[0].message; } else { values = arguments; - errorMessage = errorMessages.String.enum; + errorMessage = MongooseError.messages.String.enum; } for (var i = 0; i < values.length; i++) { @@ -7646,12 +8145,15 @@ SchemaString.prototype.uppercase = function() { * @return {SchemaType} this */ -SchemaString.prototype.trim = function() { +SchemaString.prototype.trim = function(shouldTrim) { + if (arguments.length > 0 && !shouldTrim) { + return this; + } return this.set(function(v, self) { if (typeof v !== 'string') { v = self.cast(v); } - if (v && self.options.trim) { + if (v) { return v.trim(); } return v; @@ -7697,7 +8199,7 @@ SchemaString.prototype.minlength = function(value, message) { } if (value !== null && value !== undefined) { - var msg = message || errorMessages.String.minlength; + var msg = message || MongooseError.messages.String.minlength; msg = msg.replace(/{MINLENGTH}/, value); this.validators.push({ validator: this.minlengthValidator = function(v) { @@ -7751,7 +8253,7 @@ SchemaString.prototype.maxlength = function(value, message) { } if (value !== null && value !== undefined) { - var msg = message || errorMessages.String.maxlength; + var msg = message || MongooseError.messages.String.maxlength; msg = msg.replace(/{MAXLENGTH}/, value); this.validators.push({ validator: this.maxlengthValidator = function(v) { @@ -7807,7 +8309,7 @@ SchemaString.prototype.maxlength = function(value, message) { SchemaString.prototype.match = function match(regExp, message) { // yes, we allow multiple match validators - var msg = message || errorMessages.String.match; + var msg = message || MongooseError.messages.String.match; var matchValidator = function(v) { if (!regExp) { @@ -7933,7 +8435,8 @@ SchemaString.prototype.$conditionalHandlers = $lt: handleSingle, $lte: handleSingle, $options: handleSingle, - $regex: handleSingle + $regex: handleSingle, + $not: handleSingle }); /** @@ -7967,17 +8470,16 @@ SchemaString.prototype.castForQuery = function($conditional, val) { module.exports = SchemaString; }).call(this,require("buffer").Buffer) -},{"../error":12,"../schematype":41,"../utils":51,"./../document":5,"buffer":74}],41:[function(require,module,exports){ +},{"../error":12,"../schematype":41,"../utils":51,"./../document":5,"buffer":84}],41:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. */ var utils = require('./utils'); -var error = require('./error'); -var errorMessages = error.messages; -var CastError = error.CastError; -var ValidatorError = error.ValidatorError; +var MongooseError = require('./error'); +var CastError = MongooseError.CastError; +var ValidatorError = MongooseError.ValidatorError; /** * SchemaType constructor @@ -8063,9 +8565,7 @@ SchemaType.prototype.default = function(val) { this.defaultValue = void 0; return void 0; } - this.defaultValue = typeof val === 'function' - ? val - : this.cast(val); + this.defaultValue = val; return this.defaultValue; } else if (arguments.length > 1) { this.defaultValue = utils.args(arguments); @@ -8120,8 +8620,14 @@ SchemaType.prototype.index = function(options) { */ SchemaType.prototype.unique = function(bool) { - if (this._index === null || this._index === undefined || - typeof this._index === 'boolean') { + if (this._index === false) { + if (!bool) { + return; + } + throw new Error('Path "' + this.path + '" may not have `index` set to ' + + 'false and `unique` set to true'); + } + if (this._index == null || this._index === true) { this._index = {}; } else if (typeof this._index === 'string') { this._index = {type: this._index}; @@ -8138,7 +8644,7 @@ SchemaType.prototype.unique = function(bool) { * * var s = new Schema({name : {type: String, text : true }) * Schema.path('name').index({text : true}); - * @param bool + * @param {Boolean} bool * @return {SchemaType} this * @api public */ @@ -8366,7 +8872,7 @@ SchemaType.prototype.get = function(fn) { * * ####Error message templates: * - * From the examples above, you may have noticed that error messages support basic templating. There are a few other template keywords besides `{PATH}` and `{VALUE}` too. To find out more, details are available [here](#error_messages_MongooseError-messages) + * From the examples above, you may have noticed that error messages support basic templating. There are a few other template keywords besides `{PATH}` and `{VALUE}` too. To find out more, details are available [here](#error_messages_MongooseError.messages) * * ####Asynchronous validation: * @@ -8425,7 +8931,7 @@ SchemaType.prototype.validate = function(obj, message, type) { properties.type = properties.type || 'user defined'; } else { if (!message) { - message = errorMessages.general.default; + message = MongooseError.messages.general.default; } if (!type) { type = 'user defined'; @@ -8528,7 +9034,7 @@ SchemaType.prototype.required = function(required, message) { required = undefined; } - var msg = message || errorMessages.general.required; + var msg = message || MongooseError.messages.general.required; this.validators.unshift({ validator: this.requiredValidator, message: msg, @@ -8694,12 +9200,18 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { return; } if (validator.length === 2) { - validator.call(scope, value, function(ok, customMsg) { + var returnVal = validator.call(scope, value, function(ok, customMsg) { + if (typeof returnVal === 'boolean') { + return; + } if (customMsg) { validatorProperties.message = customMsg; } validate(ok, validatorProperties); }); + if (typeof returnVal === 'boolean') { + validate(returnVal, validatorProperties); + } } else { validate(validator.call(scope, value), validatorProperties); } @@ -8882,7 +9394,7 @@ exports.CastError = CastError; exports.ValidatorError = ValidatorError; }).call(this,require("buffer").Buffer) -},{"./error":12,"./utils":51,"buffer":74}],42:[function(require,module,exports){ +},{"./error":12,"./utils":51,"buffer":84}],42:[function(require,module,exports){ (function (Buffer){ 'use strict'; @@ -8901,7 +9413,13 @@ exports.modifiedPaths = modifiedPaths; */ function flatten(update, path, options) { - var keys = Object.keys(update || {}); + var keys; + if (update && utils.isMongooseObject(update) && !Buffer.isBuffer(update)) { + keys = Object.keys(update.toObject({ transform: false })); + } else { + keys = Object.keys(update || {}); + } + var numKeys = keys.length; var result = {}; path = path ? path + '.' : ''; @@ -8909,9 +9427,7 @@ function flatten(update, path, options) { for (var i = 0; i < numKeys; ++i) { var key = keys[i]; var val = update[key]; - if (utils.isMongooseObject(val) && !Buffer.isBuffer(val)) { - val = val.toObject({ virtuals: false }); - } + result[path + key] = val; if (shouldFlatten(val)) { if (options && options.skipArrays && Array.isArray(val)) { continue; @@ -8923,8 +9439,6 @@ function flatten(update, path, options) { if (Array.isArray(val)) { result[path + key] = val; } - } else { - result[path + key] = val; } } @@ -8946,6 +9460,9 @@ function modifiedPaths(update, path, result) { var val = update[key]; result[path + key] = true; + if (utils.isMongooseObject(val) && !Buffer.isBuffer(val)) { + val = val.toObject({ transform: false }); + } if (shouldFlatten(val)) { modifiedPaths(val, path + key, result); } @@ -8968,7 +9485,7 @@ function shouldFlatten(val) { } }).call(this,require("buffer").Buffer) -},{"../types/objectid":49,"../utils":51,"buffer":74}],43:[function(require,module,exports){ +},{"../types/objectid":49,"../utils":51,"buffer":84}],43:[function(require,module,exports){ /*! * Module dependencies. @@ -9177,26 +9694,18 @@ var isMongooseObject = utils.isMongooseObject; function MongooseArray(values, path, doc) { var arr = [].concat(values); - var props = { - isMongooseArray: true, - validators: [], - _path: path, - _atomics: {}, - _schema: void 0 - }; - var tmp = {}; var keysMA = Object.keys(MongooseArray.mixin); - for (var i = 0; i < keysMA.length; ++i) { - tmp[keysMA[i]] = {enumerable: false, configurable: true, writable: true, value: MongooseArray.mixin[keysMA[i]]}; - } - - var keysP = Object.keys(props); - for (var j = 0; j < keysP.length; ++j) { - tmp[keysP[j]] = {enumerable: false, configurable: true, writable: true, value: props[keysP[j]]}; + var numKeys = keysMA.length; + for (var i = 0; i < numKeys; ++i) { + arr[keysMA[i]] = MongooseArray.mixin[keysMA[i]]; } - Object.defineProperties(arr, tmp); + arr._path = path; + arr.isMongooseArray = true; + arr.validators = []; + arr._atomics = {}; + arr._schema = void 0; // Because doc comes from the context of another function, doc === global // can happen if there was a null somewhere up the chain (see #3020) @@ -9211,6 +9720,12 @@ function MongooseArray(values, path, doc) { } MongooseArray.mixin = { + /*! + * ignore + */ + toBSON: function() { + return this.toObject({ transform: false }); + }, /** * Stores a queue of atomic operations to perform @@ -9242,20 +9757,11 @@ MongooseArray.mixin = { */ _cast: function(value) { - var owner = this._owner; var populated = false; var Model; if (this._parent) { - // if a populated array, we must cast to the same model - // instance as specified in the original query. - if (!owner) { - owner = this._owner = this._parent.ownerDocument - ? this._parent.ownerDocument() - : this._parent; - } - - populated = owner.populated(this._path, true); + populated = this._parent.populated(this._path, true); } if (populated && value !== null && value !== undefined) { @@ -9365,7 +9871,7 @@ MongooseArray.mixin = { if (val[0] instanceof EmbeddedDocument) { selector = pullOp['$or'] || (pullOp['$or'] = []); Array.prototype.push.apply(selector, val.map(function(v) { - return v.toObject({virtuals: false}); + return v.toObject({transform: false}); })); } else { selector = pullOp['_id'] || (pullOp['_id'] = {$in: []}); @@ -9677,7 +10183,7 @@ MongooseArray.mixin = { mem = cur[i]; if (mem instanceof Document) { var some = values.some(function(v) { - return v.equals(mem); + return mem.equals(v); }); if (some) { [].splice.call(cur, i, 1); @@ -9940,7 +10446,7 @@ MongooseArray.mixin.remove = MongooseArray.mixin.pull; module.exports = exports = MongooseArray; }).call(this,require("buffer").Buffer) -},{"../document":5,"../utils":51,"./embedded":47,"./objectid":49,"buffer":74}],45:[function(require,module,exports){ +},{"../document":5,"../utils":51,"./embedded":47,"./objectid":49,"buffer":84}],45:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -10075,7 +10581,7 @@ MongooseBuffer.mixin = { * * `Buffer#copy` does not mark `target` as modified so you must copy from a `MongooseBuffer` for it to work as expected. This is a work around since `copy` modifies the target, not this. * - * @return {MongooseBuffer} + * @return {Number} The number of bytes copied. * @param {Buffer} target * @method copy * @receiver MongooseBuffer @@ -10217,7 +10723,7 @@ MongooseBuffer.Binary = Binary; module.exports = MongooseBuffer; }).call(this,require("buffer").Buffer) -},{"../drivers":11,"../utils":51,"buffer":74}],46:[function(require,module,exports){ +},{"../drivers":11,"../utils":51,"buffer":84}],46:[function(require,module,exports){ (function (Buffer){ /*! * Module dependencies. @@ -10243,36 +10749,37 @@ var MongooseArray = require('./array'), function MongooseDocumentArray(values, path, doc) { var arr = [].concat(values); + arr._path = path; + var props = { isMongooseArray: true, isMongooseDocumentArray: true, validators: [], - _path: path, _atomics: {}, _schema: void 0, _handlers: void 0 }; - var tmp = {}; // Values always have to be passed to the constructor to initialize, since // otherwise MongooseArray#push will mark the array as modified to the parent. var keysMA = Object.keys(MongooseArray.mixin); - for (var j = 0; j < keysMA.length; ++j) { - tmp[keysMA[j]] = {enumerable: false, configurable: true, writable: true, value: MongooseArray.mixin[keysMA[j]]}; + var numKeys = keysMA.length; + for (var j = 0; j < numKeys; ++j) { + arr[keysMA[j]] = MongooseArray.mixin[keysMA[j]]; } var keysMDA = Object.keys(MongooseDocumentArray.mixin); - for (var i = 0; i < keysMDA.length; ++i) { - tmp[keysMDA[i]] = {enumerable: false, configurable: true, writable: true, value: MongooseDocumentArray.mixin[keysMDA[i]]}; + numKeys = keysMDA.length; + for (var i = 0; i < numKeys; ++i) { + arr[keysMDA[i]] = MongooseDocumentArray.mixin[keysMDA[i]]; } var keysP = Object.keys(props); - for (var k = 0; k < keysP.length; ++k) { - tmp[keysP[k]] = {enumerable: false, configurable: true, writable: true, value: props[keysP[k]]}; + numKeys = keysP.length; + for (var k = 0; k < numKeys; ++k) { + arr[keysP[k]] = props[keysP[k]]; } - Object.defineProperties(arr, tmp); - // Because doc comes from the context of another function, doc === global // can happen if there was a null somewhere up the chain (see #3020 && #3034) // RB Jun 17, 2015 updated to check for presence of expected paths instead @@ -10297,6 +10804,12 @@ function MongooseDocumentArray(values, path, doc) { */ // MongooseDocumentArray.mixin = Object.create( MongooseArray.mixin ); MongooseDocumentArray.mixin = { + /*! + * ignore + */ + toBSON: function() { + return this.toObject({ transform: false }); + }, /** * Overrides MongooseArray#cast @@ -10317,6 +10830,10 @@ MongooseDocumentArray.mixin = { return value; } + if (value === undefined || value === null) { + return null; + } + // handle cast('string') or cast(ObjectId) etc. // only objects are permitted so we can safely assume that // non-objects are to be interpreted as _id @@ -10466,7 +10983,7 @@ MongooseDocumentArray.mixin = { module.exports = MongooseDocumentArray; }).call(this,require("buffer").Buffer) -},{"../document":5,"../schema/objectid":36,"../utils":51,"./array":44,"./objectid":49,"buffer":74}],47:[function(require,module,exports){ +},{"../document":5,"../schema/objectid":36,"../utils":51,"./array":44,"./objectid":49,"buffer":84}],47:[function(require,module,exports){ /* eslint no-func-assign: 1 */ /*! @@ -10510,6 +11027,10 @@ function EmbeddedDocument(obj, parentArr, skipId, fields, index) { EmbeddedDocument.prototype = Object.create(Document.prototype); EmbeddedDocument.prototype.constructor = EmbeddedDocument; +EmbeddedDocument.prototype.toBSON = function() { + return this.toObject({ transform: false }); +}; + /** * Marks the embedded doc modified. * @@ -10540,6 +11061,16 @@ EmbeddedDocument.prototype.markModified = function(path) { } }; +/*! + * ignore + */ + +EmbeddedDocument.prototype.populate = function() { + throw new Error('Mongoose does not support calling populate() on nested ' + + 'docs. Instead of `doc.arr[0].populate("path")`, use ' + + '`doc.populate("arr.0.path")`'); +}; + /** * Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3) * @@ -10585,12 +11116,18 @@ function registerRemoveListener(sub) { /** * Removes the subdocument from its parent array. * + * @param {Object} [options] * @param {Function} [fn] * @api public */ -EmbeddedDocument.prototype.remove = function(fn) { - if (!this.__parentArray) { +EmbeddedDocument.prototype.remove = function(options, fn) { + if ( typeof options === 'function' && !fn ) { + fn = options; + options = undefined; + } + if (!this.__parentArray || (options && options.noop)) { + fn && fn(null); return this; } @@ -10629,7 +11166,7 @@ EmbeddedDocument.prototype.update = function() { */ EmbeddedDocument.prototype.inspect = function() { - return this.toObject(); + return this.toObject({ transform: false, retainKeyOrder: true }); }; /** @@ -10642,9 +11179,12 @@ EmbeddedDocument.prototype.inspect = function() { */ EmbeddedDocument.prototype.invalidate = function(path, err, val, first) { + Document.prototype.invalidate.call(this, path, err, val); if (!this.__parent) { - var msg = 'Unable to invalidate a subdocument that has not been added to an array.'; - throw new Error(msg); + if (err.name === 'ValidatorError') { + return true; + } + throw err; } var index = this.__index; @@ -10694,7 +11234,7 @@ EmbeddedDocument.prototype.$markValid = function(path) { EmbeddedDocument.prototype.$isValid = function(path) { var index = this.__index; - if (typeof index !== 'undefined') { + if (typeof index !== 'undefined' && this.__parent) { return !this.__parent.$__.validationError || !this.__parent.$__.validationError.errors[this.$__fullPath(path)]; } @@ -10718,8 +11258,8 @@ EmbeddedDocument.prototype.ownerDocument = function() { return this; } - while (parent.__parent) { - parent = parent.__parent; + while (parent.__parent || parent.$parent) { + parent = parent.__parent || parent.$parent; } this.$__.ownerDocument = parent; @@ -10744,9 +11284,13 @@ EmbeddedDocument.prototype.$__fullPath = function(path) { } var paths = []; - while (parent.__parent) { - paths.unshift(parent.__parentArray._path); - parent = parent.__parent; + while (parent.__parent || parent.$parent) { + if (parent.__parent) { + paths.unshift(parent.__parentArray._path); + } else { + paths.unshift(parent.$basePath); + } + parent = parent.__parent || parent.$parent; } this.$__.fullPath = paths.join('.'); @@ -10840,6 +11384,10 @@ function Subdocument(value, fields) { Subdocument.prototype = Object.create(Document.prototype); +Subdocument.prototype.toBSON = function() { + return this.toObject({ transform: false }); +}, + /** * Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3) * @@ -10869,6 +11417,9 @@ Subdocument.prototype.$isValid = function(path) { Subdocument.prototype.markModified = function(path) { Document.prototype.markModified.call(this, path); if (this.$parent) { + if (this.$parent.isDirectModified(this.$basePath)) { + return; + } this.$parent.markModified([this.$basePath, path].join('.')); } }; @@ -10880,6 +11431,7 @@ Subdocument.prototype.$markValid = function(path) { }; Subdocument.prototype.invalidate = function(path, err, val) { + Document.prototype.invalidate.call(this, path, err, val); if (this.$parent) { this.$parent.invalidate([this.$basePath, path].join('.'), err, val); } else if (err.kind === 'cast' || err.name === 'CastError') { @@ -10903,8 +11455,8 @@ Subdocument.prototype.ownerDocument = function() { return this; } - while (parent.$parent) { - parent = parent.$parent; + while (parent.$parent || parent.__parent) { + parent = parent.$parent || parent.__parent; } this.$__.ownerDocument = parent; return this.$__.ownerDocument; @@ -10913,17 +11465,37 @@ Subdocument.prototype.ownerDocument = function() { /** * Null-out this subdoc * + * @param {Object} [options] * @param {Function} [callback] optional callback for compatibility with Document.prototype.remove */ -Subdocument.prototype.remove = function(callback) { - this.$parent.set(this.$basePath, null); - registerRemoveListener(this); - if (callback) { +Subdocument.prototype.remove = function(options, callback) { + if (typeof options === 'function') { + callback = options; + options = null; + } + + // If removing entire doc, no need to remove subdoc + if (!options || !options.noop) { + this.$parent.set(this.$basePath, null); + registerRemoveListener(this); + } + + if (typeof callback === 'function') { callback(null); } }; +/*! + * ignore + */ + +Subdocument.prototype.populate = function() { + throw new Error('Mongoose does not support calling populate() on nested ' + + 'docs. Instead of `doc.nested.populate("path")`, use ' + + '`doc.populate("nested.path")`'); +}; + /*! * Registers remove event listeners for triggering * on subdocuments. @@ -11770,7 +12342,7 @@ exports.mergeClone = function(to, fromObj) { if (exports.isObject(fromObj[key])) { var obj = fromObj[key]; if (isMongooseObject(fromObj[key]) && !fromObj[key].isMongooseBuffer) { - obj = obj.toObject({ virtuals: false }); + obj = obj.toObject({ transform: false }); } exports.mergeClone(to[key], obj); } else { @@ -11797,7 +12369,7 @@ exports.each = function(arr, fn) { }; }).call(this,require("g5I+bs"),require("buffer").Buffer) -},{"./document":5,"./types":48,"./types/objectid":49,"buffer":74,"g5I+bs":97,"mpath":83,"ms":96,"regexp-clone":98,"sliced":99}],52:[function(require,module,exports){ +},{"./document":5,"./types":48,"./types/objectid":49,"buffer":84,"g5I+bs":133,"mpath":119,"ms":132,"regexp-clone":134,"sliced":135}],52:[function(require,module,exports){ /** * VirtualType constructor @@ -12264,2523 +12836,2027 @@ var objectKeys = Object.keys || function (obj) { return keys; }; -},{"util/":101}],54:[function(require,module,exports){ -(function (process,global){ -/*! - * async - * https://github.com/caolan/async +},{"util/":138}],54:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = eachLimit; + +var _eachOf = require('./eachOf'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _withoutIndex = require('./internal/withoutIndex'); + +var _withoutIndex2 = _interopRequireDefault(_withoutIndex); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Applies the function `iteratee` to each item in `coll`, in parallel. + * The `iteratee` is called with an item from the list, and a callback for when + * it has finished. If the `iteratee` passes an error to its `callback`, the + * main `callback` (for the `each` function) is immediately called with the + * error. * - * Copyright 2010-2014 Caolan McMahon - * Released under the MIT license + * Note, that since this function applies `iteratee` to each item in parallel, + * there is no guarantee that the iteratee functions will complete in order. + * + * @name each + * @static + * @memberOf module:Collections + * @method + * @alias forEach + * @category Collection + * @param {Array|Iterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A function to apply to each item + * in `coll`. The iteratee is passed a `callback(err)` which must be called once + * it has completed. If no error has occurred, the `callback` should be run + * without arguments or with an explicit `null` argument. The array index is not + * passed to the iteratee. Invoked with (item, callback). If you need the index, + * use `eachOf`. + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @example + * + * // assuming openFiles is an array of file names and saveFile is a function + * // to save the modified contents of that file: + * + * async.each(openFiles, saveFile, function(err){ + * // if any of the saves produced an error, err would equal that error + * }); + * + * // assuming openFiles is an array of file names + * async.each(openFiles, function(file, callback) { + * + * // Perform operation on file here. + * console.log('Processing file ' + file); + * + * if( file.length > 32 ) { + * console.log('This file name is too long'); + * callback('File name too long'); + * } else { + * // Do work to process file here + * console.log('File processed'); + * callback(); + * } + * }, function(err) { + * // if any of the file processing produced an error, err would equal that error + * if( err ) { + * // One of the iterations produced an error. + * // All processing will now stop. + * console.log('A file failed to process'); + * } else { + * console.log('All files have been processed successfully'); + * } + * }); */ -(function () { +function eachLimit(coll, iteratee, callback) { + (0, _eachOf2.default)(coll, (0, _withoutIndex2.default)(iteratee), callback); +} +module.exports = exports['default']; +},{"./eachOf":55,"./internal/withoutIndex":63}],55:[function(require,module,exports){ +'use strict'; - var async = {}; - function noop() {} - function identity(v) { - return v; - } - function toBool(v) { - return !!v; - } - function notId(v) { - return !v; - } +Object.defineProperty(exports, "__esModule", { + value: true +}); - // global on the server, window in the browser - var previous_async; +exports.default = function (coll, iteratee, callback) { + var eachOfImplementation = (0, _isArrayLike2.default)(coll) ? eachOfArrayLike : eachOfGeneric; + eachOfImplementation(coll, iteratee, callback); +}; - // Establish the root object, `window` (`self`) in the browser, `global` - // on the server, or `this` in some virtual machines. We use `self` - // instead of `window` for `WebWorker` support. - var root = typeof self === 'object' && self.self === self && self || - typeof global === 'object' && global.global === global && global || - this; +var _isArrayLike = require('lodash/isArrayLike'); - if (root != null) { - previous_async = root.async; - } +var _isArrayLike2 = _interopRequireDefault(_isArrayLike); - async.noConflict = function () { - root.async = previous_async; - return async; - }; +var _eachOfLimit = require('./eachOfLimit'); - function only_once(fn) { - return function() { - if (fn === null) throw new Error("Callback was already called."); - fn.apply(this, arguments); - fn = null; - }; - } +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); - function _once(fn) { - return function() { - if (fn === null) return; - fn.apply(this, arguments); - fn = null; - }; - } +var _doLimit = require('./internal/doLimit'); - //// cross-browser compatiblity functions //// +var _doLimit2 = _interopRequireDefault(_doLimit); - var _toString = Object.prototype.toString; +var _noop = require('lodash/noop'); - var _isArray = Array.isArray || function (obj) { - return _toString.call(obj) === '[object Array]'; - }; +var _noop2 = _interopRequireDefault(_noop); - // Ported from underscore.js isObject - var _isObject = function(obj) { - var type = typeof obj; - return type === 'function' || type === 'object' && !!obj; - }; +var _once = require('lodash/once'); - function _isArrayLike(arr) { - return _isArray(arr) || ( - // has a positive integer length property - typeof arr.length === "number" && - arr.length >= 0 && - arr.length % 1 === 0 - ); - } +var _once2 = _interopRequireDefault(_once); - function _arrayEach(arr, iterator) { - var index = -1, - length = arr.length; +var _onlyOnce = require('./internal/onlyOnce'); - while (++index < length) { - iterator(arr[index], index, arr); - } - } +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); - function _map(arr, iterator) { - var index = -1, - length = arr.length, - result = Array(length); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - while (++index < length) { - result[index] = iterator(arr[index], index, arr); - } - return result; +// eachOf implementation optimized for array-likes +function eachOfArrayLike(coll, iteratee, callback) { + callback = (0, _once2.default)(callback || _noop2.default); + var index = 0, + completed = 0, + length = coll.length; + if (length === 0) { + callback(null); } - function _range(count) { - return _map(Array(count), function (v, i) { return i; }); + function iteratorCallback(err) { + if (err) { + callback(err); + } else if (++completed === length) { + callback(null); + } } - function _reduce(arr, iterator, memo) { - _arrayEach(arr, function (x, i, a) { - memo = iterator(memo, x, i, a); - }); - return memo; + for (; index < length; index++) { + iteratee(coll[index], index, (0, _onlyOnce2.default)(iteratorCallback)); } +} - function _forEachOf(object, iterator) { - _arrayEach(_keys(object), function (key) { - iterator(object[key], key); - }); - } +// a generic version of eachOf which can handle array, object, and iterator cases. +var eachOfGeneric = (0, _doLimit2.default)(_eachOfLimit2.default, Infinity); - function _indexOf(arr, item) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] === item) return i; - } - return -1; - } +/** + * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument + * to the iteratee. + * + * @name eachOf + * @static + * @memberOf module:Collections + * @method + * @alias forEachOf + * @category Collection + * @see [async.each]{@link module:Collections.each} + * @param {Array|Iterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A function to apply to each + * item in `coll`. The `key` is the item's key, or index in the case of an + * array. The iteratee is passed a `callback(err)` which must be called once it + * has completed. If no error has occurred, the callback should be run without + * arguments or with an explicit `null` argument. Invoked with + * (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @example + * + * var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"}; + * var configs = {}; + * + * async.forEachOf(obj, function (value, key, callback) { + * fs.readFile(__dirname + value, "utf8", function (err, data) { + * if (err) return callback(err); + * try { + * configs[key] = JSON.parse(data); + * } catch (e) { + * return callback(e); + * } + * callback(); + * }); + * }, function (err) { + * if (err) console.error(err.message); + * // configs is now a map of JSON data + * doSomethingWith(configs); + * }); + */ +module.exports = exports['default']; +},{"./eachOfLimit":56,"./internal/doLimit":57,"./internal/onlyOnce":62,"lodash/isArrayLike":105,"lodash/noop":114,"lodash/once":115}],56:[function(require,module,exports){ +'use strict'; - var _keys = Object.keys || function (obj) { - var keys = []; - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - keys.push(k); - } - } - return keys; - }; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = eachOfLimit; - function _keyIterator(coll) { - var i = -1; - var len; - var keys; - if (_isArrayLike(coll)) { - len = coll.length; - return function next() { - i++; - return i < len ? i : null; - }; - } else { - keys = _keys(coll); - len = keys.length; - return function next() { - i++; - return i < len ? keys[i] : null; - }; - } - } +var _eachOfLimit2 = require('./internal/eachOfLimit'); - // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html) - // This accumulates the arguments passed into an array, after a given index. - // From underscore.js (https://github.com/jashkenas/underscore/pull/2140). - function _restParam(func, startIndex) { - startIndex = startIndex == null ? func.length - 1 : +startIndex; - return function() { - var length = Math.max(arguments.length - startIndex, 0); - var rest = Array(length); - for (var index = 0; index < length; index++) { - rest[index] = arguments[index + startIndex]; - } - switch (startIndex) { - case 0: return func.call(this, rest); - case 1: return func.call(this, arguments[0], rest); - } - // Currently unused but handle cases outside of the switch statement: - // var args = Array(startIndex + 1); - // for (index = 0; index < startIndex; index++) { - // args[index] = arguments[index]; - // } - // args[startIndex] = rest; - // return func.apply(this, args); - }; - } +var _eachOfLimit3 = _interopRequireDefault(_eachOfLimit2); - function _withoutIndex(iterator) { - return function (value, index, callback) { - return iterator(value, callback); - }; - } +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - //// exported async module functions //// +/** + * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a + * time. + * + * @name eachOfLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.eachOf]{@link module:Collections.eachOf} + * @alias forEachOfLimit + * @category Collection + * @param {Array|Iterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} iteratee - A function to apply to each + * item in `coll`. The `key` is the item's key, or index in the case of an + * array. The iteratee is passed a `callback(err)` which must be called once it + * has completed. If no error has occurred, the callback should be run without + * arguments or with an explicit `null` argument. Invoked with + * (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + */ +function eachOfLimit(coll, limit, iteratee, callback) { + (0, _eachOfLimit3.default)(limit)(coll, iteratee, callback); +} +module.exports = exports['default']; +},{"./internal/eachOfLimit":58}],57:[function(require,module,exports){ +"use strict"; - //// nextTick implementation with browser-compatible fallback //// +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = doLimit; +function doLimit(fn, limit) { + return function (iterable, iteratee, callback) { + return fn(iterable, limit, iteratee, callback); + }; +} +module.exports = exports['default']; +},{}],58:[function(require,module,exports){ +'use strict'; - // capture the global reference to guard against fakeTimer mocks - var _setImmediate = typeof setImmediate === 'function' && setImmediate; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = _eachOfLimit; - var _delay = _setImmediate ? function(fn) { - // not a direct alias for IE10 compatibility - _setImmediate(fn); - } : function(fn) { - setTimeout(fn, 0); - }; +var _noop = require('lodash/noop'); - if (typeof process === 'object' && typeof process.nextTick === 'function') { - async.nextTick = process.nextTick; - } else { - async.nextTick = _delay; - } - async.setImmediate = _setImmediate ? _delay : async.nextTick; +var _noop2 = _interopRequireDefault(_noop); +var _once = require('./once'); - async.forEach = - async.each = function (arr, iterator, callback) { - return async.eachOf(arr, _withoutIndex(iterator), callback); - }; +var _once2 = _interopRequireDefault(_once); - async.forEachSeries = - async.eachSeries = function (arr, iterator, callback) { - return async.eachOfSeries(arr, _withoutIndex(iterator), callback); - }; +var _iterator = require('./iterator'); +var _iterator2 = _interopRequireDefault(_iterator); - async.forEachLimit = - async.eachLimit = function (arr, limit, iterator, callback) { - return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback); - }; +var _onlyOnce = require('./onlyOnce'); - async.forEachOf = - async.eachOf = function (object, iterator, callback) { - callback = _once(callback || noop); - object = object || []; +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); - var iter = _keyIterator(object); - var key, completed = 0; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - while ((key = iter()) != null) { - completed += 1; - iterator(object[key], key, only_once(done)); +function _eachOfLimit(limit) { + return function (obj, iteratee, callback) { + callback = (0, _once2.default)(callback || _noop2.default); + if (limit <= 0 || !obj) { + return callback(null); } + var nextElem = (0, _iterator2.default)(obj); + var done = false; + var running = 0; - if (completed === 0) callback(null); - - function done(err) { - completed--; + function iterateeCallback(err) { + running -= 1; if (err) { + done = true; callback(err); - } - // Check key is null in case iterator isn't exhausted - // and done resolved synchronously. - else if (key === null && completed <= 0) { - callback(null); + } else if (done && running <= 0) { + return callback(null); + } else { + replenish(); } } - }; - async.forEachOfSeries = - async.eachOfSeries = function (obj, iterator, callback) { - callback = _once(callback || noop); - obj = obj || []; - var nextKey = _keyIterator(obj); - var key = nextKey(); - function iterate() { - var sync = true; - if (key === null) { - return callback(null); - } - iterator(obj[key], key, only_once(function (err) { - if (err) { - callback(err); - } - else { - key = nextKey(); - if (key === null) { - return callback(null); - } else { - if (sync) { - async.setImmediate(iterate); - } else { - iterate(); - } + function replenish() { + while (running < limit && !done) { + var elem = nextElem(); + if (elem === null) { + done = true; + if (running <= 0) { + callback(null); } + return; } - })); - sync = false; + running += 1; + iteratee(elem.value, elem.key, (0, _onlyOnce2.default)(iterateeCallback)); + } } - iterate(); - }; - - - async.forEachOfLimit = - async.eachOfLimit = function (obj, limit, iterator, callback) { - _eachOfLimit(limit)(obj, iterator, callback); + replenish(); }; +} +module.exports = exports['default']; +},{"./iterator":60,"./once":61,"./onlyOnce":62,"lodash/noop":114}],59:[function(require,module,exports){ +'use strict'; - function _eachOfLimit(limit) { +Object.defineProperty(exports, "__esModule", { + value: true +}); - return function (obj, iterator, callback) { - callback = _once(callback || noop); - obj = obj || []; - var nextKey = _keyIterator(obj); - if (limit <= 0) { - return callback(null); - } - var done = false; - var running = 0; - var errored = false; +exports.default = function (coll) { + return iteratorSymbol && coll[iteratorSymbol] && coll[iteratorSymbol](); +}; - (function replenish () { - if (done && running <= 0) { - return callback(null); - } +var iteratorSymbol = typeof Symbol === 'function' && Symbol.iterator; - while (running < limit && !errored) { - var key = nextKey(); - if (key === null) { - done = true; - if (running <= 0) { - callback(null); - } - return; - } - running += 1; - iterator(obj[key], key, only_once(function (err) { - running -= 1; - if (err) { - callback(err); - errored = true; - } - else { - replenish(); - } - })); - } - })(); - }; - } +module.exports = exports['default']; +},{}],60:[function(require,module,exports){ +'use strict'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = iterator; - function doParallel(fn) { - return function (obj, iterator, callback) { - return fn(async.eachOf, obj, iterator, callback); - }; - } - function doParallelLimit(fn) { - return function (obj, limit, iterator, callback) { - return fn(_eachOfLimit(limit), obj, iterator, callback); - }; - } - function doSeries(fn) { - return function (obj, iterator, callback) { - return fn(async.eachOfSeries, obj, iterator, callback); - }; - } +var _isArrayLike = require('lodash/isArrayLike'); - function _asyncMap(eachfn, arr, iterator, callback) { - callback = _once(callback || noop); - arr = arr || []; - var results = _isArrayLike(arr) ? [] : {}; - eachfn(arr, function (value, index, callback) { - iterator(value, function (err, v) { - results[index] = v; - callback(err); - }); - }, function (err) { - callback(err, results); - }); - } +var _isArrayLike2 = _interopRequireDefault(_isArrayLike); - async.map = doParallel(_asyncMap); - async.mapSeries = doSeries(_asyncMap); - async.mapLimit = doParallelLimit(_asyncMap); +var _getIterator = require('./getIterator'); - // reduce only has a series version, as doing reduce in parallel won't - // work in many situations. - async.inject = - async.foldl = - async.reduce = function (arr, memo, iterator, callback) { - async.eachOfSeries(arr, function (x, i, callback) { - iterator(memo, x, function (err, v) { - memo = v; - callback(err); - }); - }, function (err) { - callback(err, memo); - }); - }; +var _getIterator2 = _interopRequireDefault(_getIterator); - async.foldr = - async.reduceRight = function (arr, memo, iterator, callback) { - var reversed = _map(arr, identity).reverse(); - async.reduce(reversed, memo, iterator, callback); +var _keys = require('lodash/keys'); + +var _keys2 = _interopRequireDefault(_keys); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function createArrayIterator(coll) { + var i = -1; + var len = coll.length; + return function next() { + return ++i < len ? { value: coll[i], key: i } : null; }; +} - async.transform = function (arr, memo, iterator, callback) { - if (arguments.length === 3) { - callback = iterator; - iterator = memo; - memo = _isArray(arr) ? [] : {}; - } +function createES2015Iterator(iterator) { + var i = -1; + return function next() { + var item = iterator.next(); + if (item.done) return null; + i++; + return { value: item.value, key: i }; + }; +} - async.eachOf(arr, function(v, k, cb) { - iterator(memo, v, k, cb); - }, function(err) { - callback(err, memo); - }); +function createObjectIterator(obj) { + var okeys = (0, _keys2.default)(obj); + var i = -1; + var len = okeys.length; + return function next() { + var key = okeys[++i]; + return i < len ? { value: obj[key], key: key } : null; }; +} - function _filter(eachfn, arr, iterator, callback) { - var results = []; - eachfn(arr, function (x, index, callback) { - iterator(x, function (v) { - if (v) { - results.push({index: index, value: x}); - } - callback(); - }); - }, function () { - callback(_map(results.sort(function (a, b) { - return a.index - b.index; - }), function (x) { - return x.value; - })); - }); +function iterator(coll) { + if ((0, _isArrayLike2.default)(coll)) { + return createArrayIterator(coll); } - async.select = - async.filter = doParallel(_filter); + var iterator = (0, _getIterator2.default)(coll); + return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll); +} +module.exports = exports['default']; +},{"./getIterator":59,"lodash/isArrayLike":105,"lodash/keys":113}],61:[function(require,module,exports){ +"use strict"; - async.selectLimit = - async.filterLimit = doParallelLimit(_filter); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = once; +function once(fn) { + return function () { + if (fn === null) return; + var callFn = fn; + fn = null; + callFn.apply(this, arguments); + }; +} +module.exports = exports['default']; +},{}],62:[function(require,module,exports){ +"use strict"; - async.selectSeries = - async.filterSeries = doSeries(_filter); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = onlyOnce; +function onlyOnce(fn) { + return function () { + if (fn === null) throw new Error("Callback was already called."); + var callFn = fn; + fn = null; + callFn.apply(this, arguments); + }; +} +module.exports = exports['default']; +},{}],63:[function(require,module,exports){ +"use strict"; - function _reject(eachfn, arr, iterator, callback) { - _filter(eachfn, arr, function(value, cb) { - iterator(value, function(v) { - cb(!v); - }); - }, callback); - } - async.reject = doParallel(_reject); - async.rejectLimit = doParallelLimit(_reject); - async.rejectSeries = doSeries(_reject); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = _withoutIndex; +function _withoutIndex(iteratee) { + return function (value, index, callback) { + return iteratee(value, callback); + }; +} +module.exports = exports['default']; +},{}],64:[function(require,module,exports){ +var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - function _createTester(eachfn, check, getResult) { - return function(arr, limit, iterator, cb) { - function done() { - if (cb) cb(getResult(false, void 0)); - } - function iteratee(x, _, callback) { - if (!cb) return callback(); - iterator(x, function (v) { - if (cb && check(v)) { - cb(getResult(true, x)); - cb = iterator = false; - } - callback(); - }); - } - if (arguments.length > 3) { - eachfn(arr, limit, iteratee, done); - } else { - cb = iterator; - iterator = limit; - eachfn(arr, iteratee, done); - } - }; - } +;(function (exports) { + 'use strict'; - async.any = - async.some = _createTester(async.eachOf, toBool, identity); + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array - async.someLimit = _createTester(async.eachOfLimit, toBool, identity); + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) - async.all = - async.every = _createTester(async.eachOf, notId, notId); + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS) + return 62 // '+' + if (code === SLASH) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } - async.everyLimit = _createTester(async.eachOfLimit, notId, notId); + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr - function _findGetResult(v, x) { - return x; - } - async.detect = _createTester(async.eachOf, identity, _findGetResult); - async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult); - async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult); + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } - async.sortBy = function (arr, iterator, callback) { - async.map(arr, function (x, callback) { - iterator(x, function (err, criteria) { - if (err) { - callback(err); - } - else { - callback(null, {value: x, criteria: criteria}); - } - }); - }, function (err, results) { - if (err) { - return callback(err); - } - else { - callback(null, _map(results.sort(comparator), function (x) { - return x.value; - })); - } + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 - }); + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) - function comparator(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - } - }; + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length - async.auto = function (tasks, concurrency, callback) { - if (typeof arguments[1] === 'function') { - // concurrency is optional, shift the args. - callback = concurrency; - concurrency = null; - } - callback = _once(callback || noop); - var keys = _keys(tasks); - var remainingTasks = keys.length; - if (!remainingTasks) { - return callback(null); - } - if (!concurrency) { - concurrency = remainingTasks; - } + var L = 0 - var results = {}; - var runningTasks = 0; + function push (v) { + arr[L++] = v + } - var hasError = false; + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } - var listeners = []; - function addListener(fn) { - listeners.unshift(fn); - } - function removeListener(fn) { - var idx = _indexOf(listeners, fn); - if (idx >= 0) listeners.splice(idx, 1); - } - function taskComplete() { - remainingTasks--; - _arrayEach(listeners.slice(0), function (fn) { - fn(); - }); - } + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } - addListener(function () { - if (!remainingTasks) { - callback(null, results); - } - }); + return arr + } - _arrayEach(keys, function (k) { - if (hasError) return; - var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; - var taskCallback = _restParam(function(err, args) { - runningTasks--; - if (args.length <= 1) { - args = args[0]; - } - if (err) { - var safeResults = {}; - _forEachOf(results, function(val, rkey) { - safeResults[rkey] = val; - }); - safeResults[k] = args; - hasError = true; + function uint8ToBase64 (uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length - callback(err, safeResults); - } - else { - results[k] = args; - async.setImmediate(taskComplete); - } - }); - var requires = task.slice(0, task.length - 1); - // prevent dead-locks - var len = requires.length; - var dep; - while (len--) { - if (!(dep = tasks[requires[len]])) { - throw new Error('Has nonexistent dependency in ' + requires.join(', ')); - } - if (_isArray(dep) && _indexOf(dep, k) >= 0) { - throw new Error('Has cyclic dependencies'); - } - } - function ready() { - return runningTasks < concurrency && _reduce(requires, function (a, x) { - return (a && results.hasOwnProperty(x)); - }, true) && !results.hasOwnProperty(k); - } - if (ready()) { - runningTasks++; - task[task.length - 1](taskCallback, results); - } - else { - addListener(listener); - } - function listener() { - if (ready()) { - runningTasks++; - removeListener(listener); - task[task.length - 1](taskCallback, results); - } - } - }); - }; + function encode (num) { + return lookup.charAt(num) + } + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } - async.retry = function(times, task, callback) { - var DEFAULT_TIMES = 5; - var DEFAULT_INTERVAL = 0; + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } - var attempts = []; + return output + } - var opts = { - times: DEFAULT_TIMES, - interval: DEFAULT_INTERVAL - }; + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 +}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) - function parseTimes(acc, t){ - if(typeof t === 'number'){ - acc.times = parseInt(t, 10) || DEFAULT_TIMES; - } else if(typeof t === 'object'){ - acc.times = parseInt(t.times, 10) || DEFAULT_TIMES; - acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL; - } else { - throw new Error('Unsupported argument type for \'times\': ' + typeof t); - } - } +},{}],65:[function(require,module,exports){ +(function (global){ +/** + * Module dependencies. + * @ignore + */ - var length = arguments.length; - if (length < 1 || length > 3) { - throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)'); - } else if (length <= 2 && typeof times === 'function') { - callback = task; - task = times; - } - if (typeof times !== 'function') { - parseTimes(opts, times); - } - opts.callback = callback; - opts.task = task; - - function wrappedTask(wrappedCallback, wrappedResults) { - function retryAttempt(task, finalAttempt) { - return function(seriesCallback) { - task(function(err, result){ - seriesCallback(!err || finalAttempt, {err: err, result: result}); - }, wrappedResults); - }; - } +// Test if we're in Node via presence of "global" not absence of "window" +// to support hybrid environments like Electron +if(typeof global !== 'undefined') { + var Buffer = require('buffer').Buffer; // TODO just use global Buffer +} - function retryInterval(interval){ - return function(seriesCallback){ - setTimeout(function(){ - seriesCallback(null); - }, interval); - }; - } +/** + * A class representation of the BSON Binary type. + * + * Sub types + * - **BSON.BSON_BINARY_SUBTYPE_DEFAULT**, default BSON type. + * - **BSON.BSON_BINARY_SUBTYPE_FUNCTION**, BSON function type. + * - **BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY**, BSON byte array type. + * - **BSON.BSON_BINARY_SUBTYPE_UUID**, BSON uuid type. + * - **BSON.BSON_BINARY_SUBTYPE_MD5**, BSON md5 type. + * - **BSON.BSON_BINARY_SUBTYPE_USER_DEFINED**, BSON user defined type. + * + * @class + * @param {Buffer} buffer a buffer object containing the binary data. + * @param {Number} [subType] the option binary type. + * @return {Binary} + */ +function Binary(buffer, subType) { + if(!(this instanceof Binary)) return new Binary(buffer, subType); - while (opts.times) { + this._bsontype = 'Binary'; - var finalAttempt = !(opts.times-=1); - attempts.push(retryAttempt(opts.task, finalAttempt)); - if(!finalAttempt && opts.interval > 0){ - attempts.push(retryInterval(opts.interval)); - } - } + if(buffer instanceof Number) { + this.sub_type = buffer; + this.position = 0; + } else { + this.sub_type = subType == null ? BSON_BINARY_SUBTYPE_DEFAULT : subType; + this.position = 0; + } - async.series(attempts, function(done, data){ - data = data[data.length - 1]; - (wrappedCallback || opts.callback)(data.err, data.result); - }); - } - - // If a callback is passed, run this as a controll flow - return opts.callback ? wrappedTask() : wrappedTask; - }; - - async.waterfall = function (tasks, callback) { - callback = _once(callback || noop); - if (!_isArray(tasks)) { - var err = new Error('First argument to waterfall must be an array of functions'); - return callback(err); - } - if (!tasks.length) { - return callback(); - } - function wrapIterator(iterator) { - return _restParam(function (err, args) { - if (err) { - callback.apply(null, [err].concat(args)); - } - else { - var next = iterator.next(); - if (next) { - args.push(wrapIterator(next)); - } - else { - args.push(callback); - } - ensureAsync(iterator).apply(null, args); - } - }); - } - wrapIterator(async.iterator(tasks))(); - }; - - function _parallel(eachfn, tasks, callback) { - callback = callback || noop; - var results = _isArrayLike(tasks) ? [] : {}; - - eachfn(tasks, function (task, key, callback) { - task(_restParam(function (err, args) { - if (args.length <= 1) { - args = args[0]; - } - results[key] = args; - callback(err); - })); - }, function (err) { - callback(err, results); - }); + if(buffer != null && !(buffer instanceof Number)) { + // Only accept Buffer, Uint8Array or Arrays + if(typeof buffer == 'string') { + // Different ways of writing the length of the string for the different types + if(typeof Buffer != 'undefined') { + this.buffer = new Buffer(buffer); + } else if(typeof Uint8Array != 'undefined' || (Object.prototype.toString.call(buffer) == '[object Array]')) { + this.buffer = writeStringToArray(buffer); + } else { + throw new Error("only String, Buffer, Uint8Array or Array accepted"); + } + } else { + this.buffer = buffer; } + this.position = buffer.length; + } else { + if(typeof Buffer != 'undefined') { + this.buffer = new Buffer(Binary.BUFFER_SIZE); + } else if(typeof Uint8Array != 'undefined'){ + this.buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE)); + } else { + this.buffer = new Array(Binary.BUFFER_SIZE); + } + // Set position to start of buffer + this.position = 0; + } +}; - async.parallel = function (tasks, callback) { - _parallel(async.eachOf, tasks, callback); - }; - - async.parallelLimit = function(tasks, limit, callback) { - _parallel(_eachOfLimit(limit), tasks, callback); - }; +/** + * Updates this binary with byte_value. + * + * @method + * @param {string} byte_value a single byte we wish to write. + */ +Binary.prototype.put = function put(byte_value) { + // If it's a string and a has more than one character throw an error + if(byte_value['length'] != null && typeof byte_value != 'number' && byte_value.length != 1) throw new Error("only accepts single character String, Uint8Array or Array"); + if(typeof byte_value != 'number' && byte_value < 0 || byte_value > 255) throw new Error("only accepts number in a valid unsigned byte range 0-255"); - async.series = function(tasks, callback) { - _parallel(async.eachOfSeries, tasks, callback); - }; + // Decode the byte value once + var decoded_byte = null; + if(typeof byte_value == 'string') { + decoded_byte = byte_value.charCodeAt(0); + } else if(byte_value['length'] != null) { + decoded_byte = byte_value[0]; + } else { + decoded_byte = byte_value; + } - async.iterator = function (tasks) { - function makeCallback(index) { - function fn() { - if (tasks.length) { - tasks[index].apply(null, arguments); - } - return fn.next(); - } - fn.next = function () { - return (index < tasks.length - 1) ? makeCallback(index + 1): null; - }; - return fn; - } - return makeCallback(0); - }; + if(this.buffer.length > this.position) { + this.buffer[this.position++] = decoded_byte; + } else { + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + // Create additional overflow buffer + var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length); + // Combine the two buffers together + this.buffer.copy(buffer, 0, 0, this.buffer.length); + this.buffer = buffer; + this.buffer[this.position++] = decoded_byte; + } else { + var buffer = null; + // Create a new buffer (typed or normal array) + if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE + this.buffer.length)); + } else { + buffer = new Array(Binary.BUFFER_SIZE + this.buffer.length); + } - async.apply = _restParam(function (fn, args) { - return _restParam(function (callArgs) { - return fn.apply( - null, args.concat(callArgs) - ); - }); - }); + // We need to copy all the content to the new array + for(var i = 0; i < this.buffer.length; i++) { + buffer[i] = this.buffer[i]; + } - function _concat(eachfn, arr, fn, callback) { - var result = []; - eachfn(arr, function (x, index, cb) { - fn(x, function (err, y) { - result = result.concat(y || []); - cb(err); - }); - }, function (err) { - callback(err, result); - }); + // Reassign the buffer + this.buffer = buffer; + // Write the byte + this.buffer[this.position++] = decoded_byte; } - async.concat = doParallel(_concat); - async.concatSeries = doSeries(_concat); - - async.whilst = function (test, iterator, callback) { - callback = callback || noop; - if (test()) { - var next = _restParam(function(err, args) { - if (err) { - callback(err); - } else if (test.apply(this, args)) { - iterator(next); - } else { - callback.apply(null, [null].concat(args)); - } - }); - iterator(next); - } else { - callback(null); - } - }; + } +}; - async.doWhilst = function (iterator, test, callback) { - var calls = 0; - return async.whilst(function() { - return ++calls <= 1 || test.apply(this, arguments); - }, iterator, callback); - }; +/** + * Writes a buffer or string to the binary. + * + * @method + * @param {(Buffer|string)} string a string or buffer to be written to the Binary BSON object. + * @param {number} offset specify the binary of where to write the content. + * @return {null} + */ +Binary.prototype.write = function write(string, offset) { + offset = typeof offset == 'number' ? offset : this.position; - async.until = function (test, iterator, callback) { - return async.whilst(function() { - return !test.apply(this, arguments); - }, iterator, callback); - }; + // If the buffer is to small let's extend the buffer + if(this.buffer.length < offset + string.length) { + var buffer = null; + // If we are in node.js + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + buffer = new Buffer(this.buffer.length + string.length); + this.buffer.copy(buffer, 0, 0, this.buffer.length); + } else if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + // Create a new buffer + buffer = new Uint8Array(new ArrayBuffer(this.buffer.length + string.length)) + // Copy the content + for(var i = 0; i < this.position; i++) { + buffer[i] = this.buffer[i]; + } + } - async.doUntil = function (iterator, test, callback) { - return async.doWhilst(iterator, function() { - return !test.apply(this, arguments); - }, callback); - }; + // Assign the new buffer + this.buffer = buffer; + } - async.during = function (test, iterator, callback) { - callback = callback || noop; + if(typeof Buffer != 'undefined' && Buffer.isBuffer(string) && Buffer.isBuffer(this.buffer)) { + string.copy(this.buffer, offset, 0, string.length); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length + } else if(typeof Buffer != 'undefined' && typeof string == 'string' && Buffer.isBuffer(this.buffer)) { + this.buffer.write(string, offset, 'binary'); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length; + } else if(Object.prototype.toString.call(string) == '[object Uint8Array]' + || Object.prototype.toString.call(string) == '[object Array]' && typeof string != 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string[i]; + } - var next = _restParam(function(err, args) { - if (err) { - callback(err); - } else { - args.push(check); - test.apply(this, args); - } - }); + this.position = offset > this.position ? offset : this.position; + } else if(typeof string == 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string.charCodeAt(i); + } - var check = function(err, truth) { - if (err) { - callback(err); - } else if (truth) { - iterator(next); - } else { - callback(null); - } - }; + this.position = offset > this.position ? offset : this.position; + } +}; - test(check); - }; +/** + * Reads **length** bytes starting at **position**. + * + * @method + * @param {number} position read from the given position in the Binary. + * @param {number} length the number of bytes to read. + * @return {Buffer} + */ +Binary.prototype.read = function read(position, length) { + length = length && length > 0 + ? length + : this.position; - async.doDuring = function (iterator, test, callback) { - var calls = 0; - async.during(function(next) { - if (calls++ < 1) { - next(null, true); - } else { - test.apply(this, arguments); - } - }, iterator, callback); - }; + // Let's return the data based on the type we have + if(this.buffer['slice']) { + return this.buffer.slice(position, position + length); + } else { + // Create a buffer to keep the result + var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(length)) : new Array(length); + for(var i = 0; i < length; i++) { + buffer[i] = this.buffer[position++]; + } + } + // Return the buffer + return buffer; +}; - function _queue(worker, concurrency, payload) { - if (concurrency == null) { - concurrency = 1; - } - else if(concurrency === 0) { - throw new Error('Concurrency must not be zero'); - } - function _insert(q, data, pos, callback) { - if (callback != null && typeof callback !== "function") { - throw new Error("task callback must be a function"); - } - q.started = true; - if (!_isArray(data)) { - data = [data]; - } - if(data.length === 0 && q.idle()) { - // call drain immediately if there are no tasks - return async.setImmediate(function() { - q.drain(); - }); - } - _arrayEach(data, function(task) { - var item = { - data: task, - callback: callback || noop - }; - - if (pos) { - q.tasks.unshift(item); - } else { - q.tasks.push(item); - } +/** + * Returns the value of this binary as a string. + * + * @method + * @return {string} + */ +Binary.prototype.value = function value(asRaw) { + asRaw = asRaw == null ? false : asRaw; - if (q.tasks.length === q.concurrency) { - q.saturated(); - } - }); - async.setImmediate(q.process); - } - function _next(q, tasks) { - return function(){ - workers -= 1; - - var removed = false; - var args = arguments; - _arrayEach(tasks, function (task) { - _arrayEach(workersList, function (worker, index) { - if (worker === task && !removed) { - workersList.splice(index, 1); - removed = true; - } - }); + // Optimize to serialize for the situation where the data == size of buffer + if(asRaw && typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer) && this.buffer.length == this.position) + return this.buffer; - task.callback.apply(task, args); - }); - if (q.tasks.length + workers === 0) { - q.drain(); - } - q.process(); - }; + // If it's a node.js buffer object + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position); + } else { + if(asRaw) { + // we support the slice command use it + if(this.buffer['slice'] != null) { + return this.buffer.slice(0, this.position); + } else { + // Create a new buffer to copy content to + var newBuffer = Object.prototype.toString.call(this.buffer) == '[object Uint8Array]' ? new Uint8Array(new ArrayBuffer(this.position)) : new Array(this.position); + // Copy content + for(var i = 0; i < this.position; i++) { + newBuffer[i] = this.buffer[i]; } + // Return the buffer + return newBuffer; + } + } else { + return convertArraytoUtf8BinaryString(this.buffer, 0, this.position); + } + } +}; - var workers = 0; - var workersList = []; - var q = { - tasks: [], - concurrency: concurrency, - payload: payload, - saturated: noop, - empty: noop, - drain: noop, - started: false, - paused: false, - push: function (data, callback) { - _insert(q, data, false, callback); - }, - kill: function () { - q.drain = noop; - q.tasks = []; - }, - unshift: function (data, callback) { - _insert(q, data, true, callback); - }, - process: function () { - while(!q.paused && workers < q.concurrency && q.tasks.length){ - - var tasks = q.payload ? - q.tasks.splice(0, q.payload) : - q.tasks.splice(0, q.tasks.length); - - var data = _map(tasks, function (task) { - return task.data; - }); - - if (q.tasks.length === 0) { - q.empty(); - } - workers += 1; - workersList.push(tasks[0]); - var cb = only_once(_next(q, tasks)); - worker(data, cb); - } - }, - length: function () { - return q.tasks.length; - }, - running: function () { - return workers; - }, - workersList: function () { - return workersList; - }, - idle: function() { - return q.tasks.length + workers === 0; - }, - pause: function () { - q.paused = true; - }, - resume: function () { - if (q.paused === false) { return; } - q.paused = false; - var resumeCount = Math.min(q.concurrency, q.tasks.length); - // Need to call q.process once per concurrent - // worker to preserve full concurrency after pause - for (var w = 1; w <= resumeCount; w++) { - async.setImmediate(q.process); - } - } - }; - return q; - } +/** + * Length. + * + * @method + * @return {number} the length of the binary. + */ +Binary.prototype.length = function length() { + return this.position; +}; - async.queue = function (worker, concurrency) { - var q = _queue(function (items, cb) { - worker(items[0], cb); - }, concurrency, 1); +/** + * @ignore + */ +Binary.prototype.toJSON = function() { + return this.buffer != null ? this.buffer.toString('base64') : ''; +} - return q; - }; +/** + * @ignore + */ +Binary.prototype.toString = function(format) { + return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : ''; +} - async.priorityQueue = function (worker, concurrency) { +/** + * Binary default subtype + * @ignore + */ +var BSON_BINARY_SUBTYPE_DEFAULT = 0; - function _compareTasks(a, b){ - return a.priority - b.priority; - } +/** + * @ignore + */ +var writeStringToArray = function(data) { + // Create a buffer + var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(data.length)) : new Array(data.length); + // Write the content to the buffer + for(var i = 0; i < data.length; i++) { + buffer[i] = data.charCodeAt(i); + } + // Write the string to the buffer + return buffer; +} - function _binarySearch(sequence, item, compare) { - var beg = -1, - end = sequence.length - 1; - while (beg < end) { - var mid = beg + ((end - beg + 1) >>> 1); - if (compare(item, sequence[mid]) >= 0) { - beg = mid; - } else { - end = mid - 1; - } - } - return beg; - } +/** + * Convert Array ot Uint8Array to Binary String + * + * @ignore + */ +var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { + var result = ""; + for(var i = startIndex; i < endIndex; i++) { + result = result + String.fromCharCode(byteArray[i]); + } + return result; +}; - function _insert(q, data, priority, callback) { - if (callback != null && typeof callback !== "function") { - throw new Error("task callback must be a function"); - } - q.started = true; - if (!_isArray(data)) { - data = [data]; - } - if(data.length === 0) { - // call drain immediately if there are no tasks - return async.setImmediate(function() { - q.drain(); - }); - } - _arrayEach(data, function(task) { - var item = { - data: task, - priority: priority, - callback: typeof callback === 'function' ? callback : noop - }; +Binary.BUFFER_SIZE = 256; - q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); +/** + * Default BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_DEFAULT = 0; +/** + * Function BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_FUNCTION = 1; +/** + * Byte Array BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_BYTE_ARRAY = 2; +/** + * OLD UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID_OLD = 3; +/** + * UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID = 4; +/** + * MD5 BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_MD5 = 5; +/** + * User BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_USER_DEFINED = 128; - if (q.tasks.length === q.concurrency) { - q.saturated(); - } - async.setImmediate(q.process); - }); - } +/** + * Expose. + */ +module.exports = Binary; +module.exports.Binary = Binary; - // Start with a normal queue - var q = async.queue(worker, concurrency); +}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"buffer":84}],66:[function(require,module,exports){ +(function (Buffer){ +"use strict" - // Override push to accept second parameter representing priority - q.push = function (data, priority, callback) { - _insert(q, data, priority, callback); - }; +var writeIEEE754 = require('./float_parser').writeIEEE754, + readIEEE754 = require('./float_parser').readIEEE754, + Map = require('./map'), + Long = require('./long'), + Double = require('./double'), + Timestamp = require('./timestamp'), + ObjectID = require('./objectid'), + BSONRegExp = require('./regexp'), + Symbol = require('./symbol'), + Int32 = require('./int_32'), + Code = require('./code'), + Decimal128 = require('./decimal128'), + MinKey = require('./min_key'), + MaxKey = require('./max_key'), + DBRef = require('./db_ref'), + Binary = require('./binary'); - // Remove unshift function - delete q.unshift; +// Parts of the parser +var deserialize = require('./parser/deserializer'), + serializer = require('./parser/serializer'), + calculateObjectSize = require('./parser/calculate_size'); - return q; - }; +/** + * @ignore + * @api private + */ +// Max Size +var MAXSIZE = (1024*1024*17); +// Max Document Buffer size +var buffer = new Buffer(MAXSIZE); - async.cargo = function (worker, payload) { - return _queue(worker, 1, payload); - }; +var BSON = function() { +} - function _console_fn(name) { - return _restParam(function (fn, args) { - fn.apply(null, args.concat([_restParam(function (err, args) { - if (typeof console === 'object') { - if (err) { - if (console.error) { - console.error(err); - } - } - else if (console[name]) { - _arrayEach(args, function (x) { - console[name](x); - }); - } - } - })])); - }); - } - async.log = _console_fn('log'); - async.dir = _console_fn('dir'); - /*async.info = _console_fn('info'); - async.warn = _console_fn('warn'); - async.error = _console_fn('error');*/ - - async.memoize = function (fn, hasher) { - var memo = {}; - var queues = {}; - var has = Object.prototype.hasOwnProperty; - hasher = hasher || identity; - var memoized = _restParam(function memoized(args) { - var callback = args.pop(); - var key = hasher.apply(null, args); - if (has.call(memo, key)) { - async.setImmediate(function () { - callback.apply(null, memo[key]); - }); - } - else if (has.call(queues, key)) { - queues[key].push(callback); - } - else { - queues[key] = [callback]; - fn.apply(null, args.concat([_restParam(function (args) { - memo[key] = args; - var q = queues[key]; - delete queues[key]; - for (var i = 0, l = q.length; i < l; i++) { - q[i].apply(null, args); - } - })])); - } - }); - memoized.memo = memo; - memoized.unmemoized = fn; - return memoized; - }; +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.prototype.serialize = function serialize(object, checkKeys, asBuffer, serializeFunctions, index, ignoreUndefined) { + // Attempt to serialize + var serializationIndex = serializer(buffer, object, checkKeys, index || 0, 0, serializeFunctions, ignoreUndefined); + // Create the final buffer + var finishedBuffer = new Buffer(serializationIndex); + // Copy into the finished buffer + buffer.copy(finishedBuffer, 0, 0, finishedBuffer.length); + // Return the buffer + return finishedBuffer; +} - async.unmemoize = function (fn) { - return function () { - return (fn.unmemoized || fn).apply(null, arguments); - }; - }; +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the index pointing to the last written byte in the buffer. + * @api public + */ +BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, finalBuffer, startIndex, serializeFunctions, ignoreUndefined) { + // Attempt to serialize + var serializationIndex = serializer(buffer, object, checkKeys, startIndex || 0, 0, serializeFunctions, ignoreUndefined); + buffer.copy(finalBuffer, startIndex, 0, serializationIndex); + // Return the index + return serializationIndex - 1; +} - function _times(mapper) { - return function (count, iterator, callback) { - mapper(_range(count), iterator, callback); - }; - } +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.prototype.deserialize = function(data, options) { + return deserialize(data, options); +} - async.times = _times(async.map); - async.timesSeries = _times(async.mapSeries); - async.timesLimit = function (count, limit, iterator, callback) { - return async.mapLimit(_range(count), limit, iterator, callback); - }; +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.prototype.calculateObjectSize = function(object, serializeFunctions, ignoreUndefined) { + return calculateObjectSize(object, serializeFunctions, ignoreUndefined); +} - async.seq = function (/* functions... */) { - var fns = arguments; - return _restParam(function (args) { - var that = this; +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents"); + options = options != null ? options : {}; + var index = startIndex; + // Loop over all documents + for(var i = 0; i < numberOfDocuments; i++) { + // Find size of the document + var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24; + // Update options with index + options['index'] = index; + // Parse the document at this point + documents[docStartIndex + i] = this.deserialize(data, options); + // Adjust index by the document size + index = index + size; + } - var callback = args[args.length - 1]; - if (typeof callback == 'function') { - args.pop(); - } else { - callback = noop; - } - - async.reduce(fns, args, function (newargs, fn, cb) { - fn.apply(that, newargs.concat([_restParam(function (err, nextargs) { - cb(err, nextargs); - })])); - }, - function (err, results) { - callback.apply(that, [err].concat(results)); - }); - }); - }; - - async.compose = function (/* functions... */) { - return async.seq.apply(null, Array.prototype.reverse.call(arguments)); - }; - - - function _applyEach(eachfn) { - return _restParam(function(fns, args) { - var go = _restParam(function(args) { - var that = this; - var callback = args.pop(); - return eachfn(fns, function (fn, _, cb) { - fn.apply(that, args.concat([cb])); - }, - callback); - }); - if (args.length) { - return go.apply(this, args); - } - else { - return go; - } - }); - } - - async.applyEach = _applyEach(async.eachOf); - async.applyEachSeries = _applyEach(async.eachOfSeries); - - - async.forever = function (fn, callback) { - var done = only_once(callback || noop); - var task = ensureAsync(fn); - function next(err) { - if (err) { - return done(err); - } - task(next); - } - next(); - }; - - function ensureAsync(fn) { - return _restParam(function (args) { - var callback = args.pop(); - args.push(function () { - var innerArgs = arguments; - if (sync) { - async.setImmediate(function () { - callback.apply(null, innerArgs); - }); - } else { - callback.apply(null, innerArgs); - } - }); - var sync = true; - fn.apply(this, args); - sync = false; - }); - } - - async.ensureAsync = ensureAsync; - - async.constant = _restParam(function(values) { - var args = [null].concat(values); - return function (callback) { - return callback.apply(this, args); - }; - }); - - async.wrapSync = - async.asyncify = function asyncify(func) { - return _restParam(function (args) { - var callback = args.pop(); - var result; - try { - result = func.apply(this, args); - } catch (e) { - return callback(e); - } - // if result is Promise object - if (_isObject(result) && typeof result.then === "function") { - result.then(function(value) { - callback(null, value); - })["catch"](function(err) { - callback(err.message ? err : new Error(err)); - }); - } else { - callback(null, result); - } - }); - }; - - // Node.js - if (typeof module === 'object' && module.exports) { - module.exports = async; - } - // AMD / RequireJS - else if (typeof define === 'function' && define.amd) { - define([], function () { - return async; - }); - } - // included directly via From 08a6f71c63aae88683964f1a17890d56305d9e13 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Dec 2016 19:04:24 -0800 Subject: [PATCH 1057/2240] test(document): repro #4778 --- test/document.test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 5bdd9a646eb..d6efac32a74 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3601,6 +3601,34 @@ describe('document', function() { }); }); + it('handles mark valid in subdocs correctly (gh-4778)', function(done) { + var SubSchema = new mongoose.Schema({ + field: { + nestedField: { + type: mongoose.Schema.ObjectId, + required: false + } + } + }, { _id: false, id: false }); + + var Model2Schema = new mongoose.Schema({ + sub: { + type: SubSchema, + required: false + } + }); + var Model2 = db.model('gh4778', Model2Schema); + + var doc = new Model2({ + sub: {} + }); + + doc.sub.field.nestedField = { }; + doc.sub.field.nestedField = '574b69d0d9daf106aaa62974'; + assert.ok(!doc.validateSync()); + done(); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From d958cd962f83e6ff3c9ed41ed52e7ca0c9a7aca6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Dec 2016 19:08:47 -0800 Subject: [PATCH 1058/2240] fix(document): handle mark valid in subdocs correctly Fix #4778 --- lib/types/subdocument.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 5510ef2477d..0fef2dca35f 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -58,6 +58,7 @@ Subdocument.prototype.markModified = function(path) { }; Subdocument.prototype.$markValid = function(path) { + Document.prototype.$markValid.call(this, path); if (this.$parent) { this.$parent.$markValid([this.$basePath, path].join('.')); } From 8761d58e0505170e147f1427e948ea31b8de87bb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 12 Dec 2016 17:32:41 -0800 Subject: [PATCH 1059/2240] fix: pull down kareem 1.1.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a15d81583aa..b6b006eaf96 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "2.1.4", "bson": "~0.5.4", "hooks-fixed": "1.2.0", - "kareem": "1.1.4", + "kareem": "1.1.5", "mongodb": "2.2.15", "mpath": "0.2.1", "mpromise": "0.5.5", From ccfed685a6ced89a40c997967b89082a8d938916 Mon Sep 17 00:00:00 2001 From: Paul Spicer Date: Tue, 13 Dec 2016 11:50:04 -0500 Subject: [PATCH 1060/2240] cloning mongoose array during population: simplified cast expression --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 7fd62be9e5e..25a515e5bbb 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3082,7 +3082,7 @@ function convertTo_id(val) { } } if (val.isMongooseArray) { - return val._parent.schema.path(val._path).cast(val, val._parent); + return val._schema.cast(val, val._parent); } return [].concat(val); From 5b552bf74e58f44c918c9a327deda0fde82721de Mon Sep 17 00:00:00 2001 From: Olivier Louvignes Date: Wed, 14 Dec 2016 17:56:39 +0100 Subject: [PATCH 1061/2240] chore(github): add ISSUE_TEMPLATE.md and PULL_REQUEST_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 12 ++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 9 +++++++++ 2 files changed, 21 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000000..aade40646ff --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,12 @@ + + +**Do you want to request a *feature* or report a *bug*?** + +**What is the current behavior?** + +**If the current behavior is a bug, please provide the steps to reproduce.** + + +**What is the expected behavior?** + +**Please mention your node.js, mongoose and operating system version.** diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..65654629d59 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ + + +**Summary** + + + +**Test plan** + + From ce6c73ce714ff05e52e2531764db61a9ccb31348 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 14 Dec 2016 17:02:37 -0800 Subject: [PATCH 1062/2240] fix(model): ensure discriminator key is correct for child schema on discriminator Fix #4790 --- lib/model.js | 1 + test/model.discriminator.test.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index f2f418a7fab..657725a9ddd 100644 --- a/lib/model.js +++ b/lib/model.js @@ -838,6 +838,7 @@ Model.discriminator = function discriminator(name, schema) { var id = schema.options.id; var keys = Object.keys(schema.options); + schema.options.discriminatorKey = baseSchema.options.discriminatorKey; for (var i = 0; i < keys.length; ++i) { var _key = keys[i]; diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 2597c309b1c..92ec539de43 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -364,7 +364,7 @@ describe('model', function() { var Model = mongoose.model('gh4339', schema); Model.discriminator('gh4339_0', new Schema({ test2: String - }, options)); + }, { typeKey: '$type' })); done(); }); From 9f6cd8bdfc10b0366e11a5f2fdc361c6489ef57a Mon Sep 17 00:00:00 2001 From: Anton Fedulov Date: Thu, 15 Dec 2016 18:30:45 +0200 Subject: [PATCH 1063/2240] Fix typo in docs --- lib/schema/string.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/string.js b/lib/schema/string.js index eae40b87096..d969280a9c6 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -57,7 +57,7 @@ SchemaString.prototype.constructor = SchemaString; * values: ['opening', 'open', 'closing', 'closed'], * message: 'enum validator failed for path `{PATH}` with value `{VALUE}`' * } - * var s = new Schema({ state: { type: String, enum: enu }) + * var s = new Schema({ state: { type: String, enum: enum }) * var M = db.model('M', s) * var m = new M({ state: 'invalid' }) * m.save(function (err) { From 0e218745f154c54e68488841c6109f47f5c33dfd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 16 Dec 2016 09:54:26 -0800 Subject: [PATCH 1064/2240] docs: remove live examples (which aren't so live) Fix #4794 --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 22a778af249..a694a914b4d 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,6 @@ Build your own Mongoose plugin through [generator-mongoose-plugin](https://githu View all 200+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors). Stand up and be counted as a [contributor](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md) too! -## Live Examples - - ## Installation First install [node.js](http://nodejs.org/) and [mongodb](https://www.mongodb.org/downloads). Then: From 5d6286f6370e8dfe5516d0974a6cbc4f53f307b6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 16 Dec 2016 10:25:43 -0800 Subject: [PATCH 1065/2240] chore: upgrade mongodb driver -> 2.2.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b6b006eaf96..927af55045a 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~0.5.4", "hooks-fixed": "1.2.0", "kareem": "1.1.5", - "mongodb": "2.2.15", + "mongodb": "2.2.16", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.0.0", From 1c87f002044fb5bd309dbf377fc900afcff0b718 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 16 Dec 2016 10:25:56 -0800 Subject: [PATCH 1066/2240] docs(compatibility): add 3.4 to compatibility guide --- docs/compatibility.jade | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/compatibility.jade b/docs/compatibility.jade index 5953967a684..b4dd447f5cf 100644 --- a/docs/compatibility.jade +++ b/docs/compatibility.jade @@ -17,3 +17,4 @@ block content * MongoDB Server 2.6.x: mongoose `~3.8.8`, `4.x` * MongoDB Server 3.0.x: mongoose `~3.8.22`, `4.x` * MongoDB Server 3.2.x: mongoose `>=4.3.0` + * MongoDB Server 3.4.x: mongoose `>=4.7.3` From c24e949930d76857c80f174bf666f2fb200eb1a6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 16 Dec 2016 10:35:39 -0800 Subject: [PATCH 1067/2240] chore: 4.7.3 --- History.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e04b8444697..94ac24e0f8d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.7.3 / 2016-12-16 +================== + * fix: upgrade mongodb driver -> 2.2.16 for several bug fixes and 3.4 support #4799 + * fix(model): ensure discriminator key is correct for child schema on discriminator #4790 + * fix(document): handle mark valid in subdocs correctly #4778 + * fix(query): check for objects consistently #4775 + 4.7.2 / 2016-12-07 ================== * test(populate): fix justOne test #4772 [cblanc](https://github.com/cblanc) diff --git a/package.json b/package.json index 927af55045a..006bd57bb76 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.3-pre", + "version": "4.7.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 7eb2332d92bcd9c3783a4277b57a1ecd57a33b7a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 16 Dec 2016 19:55:10 -0800 Subject: [PATCH 1068/2240] chore: now working on 4.7.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 006bd57bb76..7359aab0bc8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.3", + "version": "4.7.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4644a6ccf83990c2c2c1e575e0b00f854122c5e2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Dec 2016 15:35:11 -0700 Subject: [PATCH 1069/2240] test(query): repro #4805 --- test/query.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index 28a8fe1dd58..4a465322889 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1548,6 +1548,24 @@ describe('Query', function() { done(); }); + it('timestamps with $each (gh-4805)', function(done) { + var nestedSchema = new Schema({ value: Number }, { timestamps: true }); + var Test = db.model('gh4805', new Schema({ + arr: [nestedSchema] + }, { timestamps: true })); + + Test.update({}, { + $push: { + arr: { + $each: [{ value: 1 }] + } + } + }).exec(function(error) { + assert.ifError(error); + done(); + }); + }); + it('allows sort with count (gh-3914)', function(done) { var Post = db.model('gh3914_0', { title: String From e4a2725f752c2d1a442c116d1091834d6ae94827 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Dec 2016 15:35:16 -0700 Subject: [PATCH 1070/2240] fix(query): timestamps with $push + $each Fix #4805 --- lib/schema.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 7e28f588fe5..30a4a9fd797 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -896,8 +896,15 @@ function applyTimestampsToChildren(query) { timestamps = $path.schema.options.timestamps; createdAt = timestamps.createdAt || 'createdAt'; updatedAt = timestamps.updatedAt || 'updatedAt'; - update.$push[key][updatedAt] = now; - update.$push[key][createdAt] = now; + if (update.$push[key].$each) { + update.$push[key].$each.forEach(function(subdoc) { + subdoc[updatedAt] = now; + subdoc[createdAt] = now; + }); + } else { + update.$push[key][updatedAt] = now; + update.$push[key][createdAt] = now; + } } } } From 65e9681b6457938db0b54bb4f3b331b727bae995 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Dec 2016 14:41:08 -0800 Subject: [PATCH 1071/2240] chore: couple updates to issue template --- .github/ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index aade40646ff..a2eb2b92dc6 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -5,8 +5,8 @@ **What is the current behavior?** **If the current behavior is a bug, please provide the steps to reproduce.** - + **What is the expected behavior?** -**Please mention your node.js, mongoose and operating system version.** +**Please mention your node.js, mongoose and MongoDB version.** From 0f05fcc426e096a36d0a57b68a272cebbc68ac91 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Dec 2016 16:01:25 -0700 Subject: [PATCH 1072/2240] docs(guide): remove the odd Breaking Bad example Fix #4808 --- docs/guide.jade | 47 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/docs/guide.jade b/docs/guide.jade index 8b18ca90cac..b6642a07255 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -207,54 +207,45 @@ block content var Person = mongoose.model('Person', personSchema); // create a document - var bad = new Person({ - name: { first: 'Walter', last: 'White' } + var axl = new Person({ + name: { first: 'Axl', last: 'Rose' } }); :markdown - Suppose we want to log the full name of `bad`. We could do this manually like so: + Suppose you want to print out the person's full name. You could do it yourself: :js - console.log(bad.name.first + ' ' + bad.name.last); // Walter White + console.log(axl.name.first + ' ' + axl.name.last); // Axl Rose :markdown - Or we could define a [virtual property getter](./api.html#virtualtype_VirtualType-get) on our `personSchema` so we don't need to write out this string concatenation mess each time: + But concatenating the first and last name every time can get cumbersome. And what if you want to do some extra processing on the name, like [removing diacritics?](https://www.npmjs.com/package/diacritics). A [virtual property getter](./api.html#virtualtype_VirtualType-get) lets you define a `fullName` property that won't get persisted to MongoDB. :js - personSchema.virtual('name.full').get(function () { + personSchema.virtual('fullName').get(function () { return this.name.first + ' ' + this.name.last; }); :markdown - Now, when we access our virtual "name.full" property, our getter function will be invoked and the value returned: + Now, mongoose will call your getter function every time you access the `fullName` property: :js - console.log('%s is insane', bad.name.full); // Walter White is insane + console.log(axl.fullName); // Axl Rose :markdown - Note that if the resulting record is converted to an object or JSON, virtuals are not included by default. - Pass `virtuals : true` to either [toObject()](./api.html#document_Document-toObject) or to toJSON() to have them returned. + If you use `toJSON()` or `toObject()` (or use `JSON.stringify()` on a mongoose document) mongoose will *not* include virtuals by default. + Pass `{ virtuals: true }` to either [toObject()](./api.html#document_Document-toObject) or `toJSON()`. - It would also be nice to be able to set `this.name.first` and `this.name.last` by setting `this.name.full`. For example, if we wanted to change `bad`'s `name.first` and `name.last` to 'Breaking' and 'Bad' respectively, it'd be nice to just: + You can also add a custom setter to your virtual that will let you set both first name and last name via the `fullName` virtual. :js - bad.name.full = 'Breaking Bad'; - - :markdown - Mongoose lets you do this as well through its [virtual property setters](./api.html#virtualtype_VirtualType-set): - - :js - personSchema.virtual('name.full').set(function (name) { - var split = name.split(' '); - this.name.first = split[0]; - this.name.last = split[1]; - }); - - ... - - mad.name.full = 'Breaking Bad'; - console.log(mad.name.first); // Breaking - console.log(mad.name.last); // Bad + personSchema.virtual('fullName'). + get(function() { return this.name.first + ' ' + this.name.last; }). + set(function(v) { + this.name.first = v.substr(0, v.indexOf(' ')); + this.name.last = v.substr(v.indexOf(' ') + 1); + }); + + axl.fullName = 'William Rose'; // Now `axl.name.first` is "William" :markdown Virtual property setters are applied before other validation. So the example above would still work even if the `first` and `last` name fields were required. From 503688d75bf24d4d1d65158ef82ffc27466c1a33 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Dec 2016 16:58:14 -0700 Subject: [PATCH 1073/2240] style: fix lint --- lib/model.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 9f6bfc1dc6a..8d44b212de4 100644 --- a/lib/model.js +++ b/lib/model.js @@ -13,7 +13,6 @@ var utils = require('./utils'); var hasOwnProperty = utils.object.hasOwnProperty; var isMongooseObject = utils.isMongooseObject; var EventEmitter = require('events').EventEmitter; -var MongooseArray = require('./types/array'); var util = require('util'); var tick = utils.tick; From ccadb1a2cefeecd86343b342b7ac569844536abf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Dec 2016 16:58:37 -0700 Subject: [PATCH 1074/2240] test(document): repro #4800 --- test/document.test.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index d6efac32a74..f0c72f3a0a4 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3629,6 +3629,28 @@ describe('document', function() { done(); }); + it('toObject() with buffer and minimize (gh-4800)', function(done) { + var TestSchema = new mongoose.Schema({ buf: Buffer }, { + toObject: { + virtuals: true, + getters: true + } + }); + + var Test = db.model('gh4800', TestSchema); + + Test.create({ buf: new Buffer('abcd') }). + then(function(doc) { + return Test.findById(doc._id); + }). + then(function(doc) { + // Should not throw + require('util').inspect(doc); + done(); + }). + catch(done); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From 70854c1373adba183ee7e628493824cfe02b7c2a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 17 Dec 2016 20:41:06 -0700 Subject: [PATCH 1075/2240] fix(document): handle buffers correctly in minimize Fix #4800 --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index b5ee2b92db6..55eb6ceea78 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2275,7 +2275,7 @@ function minimize(obj) { key = keys[i]; val = obj[key]; - if (utils.isObject(val)) { + if (utils.isObject(val) && !Buffer.isBuffer(val)) { obj[key] = minimize(val); } From 4f3875d3b4ceb0162945777f3c44f79624dff9f9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Dec 2016 18:55:23 -0700 Subject: [PATCH 1076/2240] docs: use more consistent commas --- lib/model.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index 8d44b212de4..26a87f52eac 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2347,12 +2347,12 @@ Model.geoNear = function(near, options, callback) { * * // Find the max balance of all accounts * Users.aggregate( - * { $group: { _id: null, maxBalance: { $max: '$balance' }}} - * , { $project: { _id: 0, maxBalance: 1 }} - * , function (err, res) { - * if (err) return handleError(err); - * console.log(res); // [ { maxBalance: 98000 } ] - * }); + * { $group: { _id: null, maxBalance: { $max: '$balance' }}}, + * { $project: { _id: 0, maxBalance: 1 }}, + * function (err, res) { + * if (err) return handleError(err); + * console.log(res); // [ { maxBalance: 98000 } ] + * }); * * // Or use the aggregation pipeline builder. * Users.aggregate() From c4d23313529a3edd32136012dba7ef338732aaa0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Dec 2016 22:22:21 -0700 Subject: [PATCH 1077/2240] test(document): repro #4793 --- test/document.test.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index f0c72f3a0a4..d5998a280d3 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3651,6 +3651,35 @@ describe('document', function() { catch(done); }); + it('does not overwrite when setting nested (gh-4793)', function(done) { + var grandchildSchema = new mongoose.Schema(); + grandchildSchema.method({ + foo: function() { return 'bar'; } + }); + var Grandchild = db.model('gh4793_0', grandchildSchema); + + var childSchema = new mongoose.Schema({ + grandchild: grandchildSchema + }); + var Child = mongoose.model('gh4793_1', childSchema); + + var parentSchema = new mongoose.Schema({ + children: [childSchema] + }); + var Parent = mongoose.model('gh4793_2', parentSchema); + + var grandchild = new Grandchild(); + var child = new Child({grandchild: grandchild}); + + assert.equal(child.grandchild.foo(), 'bar'); + + var p = new Parent({children: [child]}); + + assert.equal(child.grandchild.foo(), 'bar'); + assert.equal(p.children[0].grandchild.foo(), 'bar'); + done(); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From 0f7fbc2f8c86542c66758feb5eff1ee04c9bbb19 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Dec 2016 22:22:34 -0700 Subject: [PATCH 1078/2240] fix(document): don't convert single nested docs to POJOs Fix #4793 --- lib/document.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 55eb6ceea78..41d66443174 100644 --- a/lib/document.js +++ b/lib/document.js @@ -587,12 +587,13 @@ Document.prototype.set = function(path, val, type, options) { if (pathtype === 'real' || pathtype === 'virtual') { // Check for setting single embedded schema to document (gh-3535) + var p = path[key]; if (this.schema.paths[pathName] && this.schema.paths[pathName].$isSingleNested && path[key] instanceof Document) { - path[key] = path[key].toObject({virtuals: false}); + p = p.toObject({ virtuals: false, transform: false }); } - this.set(prefix + key, path[key], constructing); + this.set(prefix + key, p, constructing); } else if (pathtype === 'nested' && path[key] instanceof Document) { this.set(prefix + key, path[key].toObject({transform: false}), constructing); From 09a1d72178eb9cb0873e457787e10e235cead07a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 19 Dec 2016 20:44:04 -0700 Subject: [PATCH 1079/2240] chore: release 4.7.4 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 94ac24e0f8d..1e8bcb3a90f 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.7.4 / 2016-12-21 +================== + * docs: fix typo #4810 [GEEKIAM](https://github.com/GEEKIAM) + * fix(query): timestamps with $push + $each #4805 + * fix(document): handle buffers correctly in minimize #4800 + * fix: don't disallow overwriting default and cast fns #4795 [pdspicer](https://github.com/pdspicer) + * fix(document): don't convert single nested docs to POJOs #4793 + * fix(connection): handle reconnect to replica set correctly #4972 [gfzabarino](https://github.com/gfzabarino) + 4.7.3 / 2016-12-16 ================== * fix: upgrade mongodb driver -> 2.2.16 for several bug fixes and 3.4 support #4799 diff --git a/package.json b/package.json index 7359aab0bc8..d28ed4408e3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.4-pre", + "version": "4.7.4", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From daa9f837e2596b0e8268d9a244c1ce471cccd3df Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Dec 2016 19:35:38 -0700 Subject: [PATCH 1080/2240] chore: now working on 4.7.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d28ed4408e3..6f32fc27321 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.4", + "version": "4.7.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 36d422bb8e55c114734d425b7cbaf2ca03b41e3f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Dec 2016 21:59:38 -0700 Subject: [PATCH 1081/2240] feat(aggregate): add eachAsync() to aggregate cursor Fix #4300 --- lib/aggregate.js | 61 +++++++++++++++++++++++++++++++++++++++--- test/aggregate.test.js | 41 ++++++++++++++++++++++++---- 2 files changed, 94 insertions(+), 8 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index bb24e88db15..b6550547660 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -541,7 +541,8 @@ Aggregate.prototype.exec = function(callback) { if (!_this._model.collection.buffer) { process.nextTick(function() { var cursor = _this._model.collection. - aggregate(_this._pipeline, options || {}); + aggregate(_this._pipeline, options || {}); + decorateCursor(cursor); resolve(cursor); callback && callback(null, cursor); }); @@ -549,14 +550,17 @@ Aggregate.prototype.exec = function(callback) { } _this._model.collection.emitter.once('queue', function() { var cursor = _this._model.collection. - aggregate(_this._pipeline, options || {}); + aggregate(_this._pipeline, options || {}); + decorateCursor(cursor); resolve(cursor); callback && callback(null, cursor); }); }); } - return this._model.collection. + var cursor = this._model.collection. aggregate(this._pipeline, this.options || {}); + decorateCursor(cursor); + return cursor; } return new Promise.ES6(function(resolve, reject) { @@ -590,6 +594,57 @@ Aggregate.prototype.exec = function(callback) { }); }; +/*! + * Add `eachAsync()` to aggregation cursors + */ + +function decorateCursor(cursor) { + cursor.eachAsync = function(fn, callback) { + var Promise = PromiseProvider.get(); + + var handleNextResult = function(doc, callback) { + var promise = fn(doc); + if (promise && typeof promise.then === 'function') { + promise.then( + function() { callback(null); }, + function(error) { callback(error); }); + } else { + callback(null); + } + }; + + var iterate = function(callback) { + return cursor.next(function(error, doc) { + if (error) { + return callback(error); + } + if (!doc) { + return callback(null); + } + handleNextResult(doc, function(error) { + if (error) { + return callback(error); + } + setTimeout(function() { + iterate(callback); + }, 0); + }); + }); + }; + + return new Promise.ES6(function(resolve, reject) { + iterate(function(error) { + if (error) { + callback && callback(error); + return reject(error); + } + callback && callback(null); + return resolve(); + }); + }); + }; +} + /** * Provides promise for aggregate. * diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 0ecca67c9c8..066511939bc 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -2,11 +2,11 @@ * Module dependencies */ -var start = require('./common'), - Aggregate = require('../lib/aggregate'), - mongoose = start.mongoose, - Schema = mongoose.Schema, - assert = require('power-assert'); +var start = require('./common'); +var Aggregate = require('../lib/aggregate'); +var mongoose = start.mongoose; +var Schema = mongoose.Schema; +var assert = require('power-assert'); /** * Test data @@ -683,6 +683,37 @@ describe('aggregate: ', function() { }); }); + it('cursor() eachAsync (gh-4300)', function(done) { + var db = start(); + + var MyModel = db.model('gh4300', { name: String }); + + var cur = 0; + var expectedNames = ['Axl', 'Slash']; + MyModel.create([{ name: 'Axl' }, { name: 'Slash' }]). + then(function() { + return MyModel.aggregate([{ $sort: { name: 1 } }]). + cursor(). + exec(). + eachAsync(function(doc) { + var _cur = cur; + assert.equal(doc.name, expectedNames[cur]); + return { + then: function(onResolve) { + setTimeout(function() { + assert.equal(_cur, cur++); + onResolve(); + }, 50); + } + }; + }). + then(function() { + done(); + }); + }). + catch(done); + }); + it('ability to add noCursorTimeout option (gh-4241)', function(done) { var db = start(); From 0ba9cd7f94e82e99f6822b364f82623626930016 Mon Sep 17 00:00:00 2001 From: John Paulino Date: Tue, 20 Dec 2016 22:54:02 -0800 Subject: [PATCH 1082/2240] Fix spelling mistake Change "qurery" to "query". --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 26a87f52eac..266eddfd2e0 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2240,7 +2240,7 @@ Model.mapReduce = function mapReduce(o, callback) { * }); * * @param {Object|Array} GeoJSON point or legacy coordinate pair [x,y] to search near - * @param {Object} options for the qurery + * @param {Object} options for the query * @param {Function} [callback] optional callback for the query * @return {Promise} * @see http://docs.mongodb.org/manual/core/2dsphere/ From b9d1968e60cea0b2f4586a54a5d62f6200ce67b2 Mon Sep 17 00:00:00 2001 From: Diego Del Rosso Date: Wed, 21 Dec 2016 14:41:33 -0200 Subject: [PATCH 1083/2240] Update schema.js propagate the strict option to a child schema. --- lib/schema.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index 30a4a9fd797..a5afbcf196a 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -618,6 +618,10 @@ Schema.interpretAsType = function(path, obj, options) { if (options.typeKey) { childSchemaOptions.typeKey = options.typeKey; } + //propagate 'strict' option to child schema + if(options.hasOwnProperty('strict')) { + childSchemaOptions.strict = options.strict; + } var childSchema = new Schema(cast, childSchemaOptions); childSchema.$implicitlyCreated = true; return new MongooseTypes.DocumentArray(path, childSchema, obj); From 655d34a61ae06e30230b85221d22748629105c89 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Dec 2016 22:51:15 -0700 Subject: [PATCH 1084/2240] docs(documents): add runValidators description to documents docs --- docs/documents.jade | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/documents.jade b/docs/documents.jade index 16d19c2874f..cec8b183dbd 100644 --- a/docs/documents.jade +++ b/docs/documents.jade @@ -32,7 +32,9 @@ block content res.send(tank); }); :markdown - The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model.findByIdAndRemove) [several](./api.html#model_Model.findOneAndUpdate) [variations](./api.html#model_Model.findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. _Note that `findAndUpdate/Remove` do not execute any hooks or validation before making the change in the database. If you need hooks and validation, first query for the document and then save it._ + The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model.findByIdAndRemove) [several](./api.html#model_Model.findOneAndUpdate) [variations](./api.html#model_Model.findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. + + _Note that `findAndUpdate/Remove` do *not* execute any hooks or validation before making the change in the database. You can use the [`runValidators` option](/docs/validation.html#update-validators) to access a limited subset of document validation. However, if you need hooks and full document validation, first query for the document and then `save()` it._ h3 Validating :markdown From e5153eb9b7dd19280b8c70e18b62927be8fae5f8 Mon Sep 17 00:00:00 2001 From: Diego Del Rosso Date: Thu, 22 Dec 2016 10:10:28 -0200 Subject: [PATCH 1085/2240] fixing space after 'if' --- lib/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index a5afbcf196a..954520c1280 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -619,7 +619,7 @@ Schema.interpretAsType = function(path, obj, options) { childSchemaOptions.typeKey = options.typeKey; } //propagate 'strict' option to child schema - if(options.hasOwnProperty('strict')) { + if (options.hasOwnProperty('strict')) { childSchemaOptions.strict = options.strict; } var childSchema = new Schema(cast, childSchemaOptions); From d294b2803fa1f40bf715191c2619e76762bf43e6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 23 Dec 2016 17:40:41 -0700 Subject: [PATCH 1086/2240] test(populate): repro #4817 --- test/model.populate.test.js | 77 +++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index a12b5bdfc12..970d69a69df 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4544,6 +4544,83 @@ describe('model: populate:', function() { catch(done); }); + it('handles populating with discriminators that may not have a ref (gh-4817)', function(done) { + var imagesSchema = new mongoose.Schema({ + name: { + type: String, + required: true + } + }); + var Image = db.model('gh4817', imagesSchema, 'images'); + + var fieldSchema = new mongoose.Schema({ + name: { + type: String, + required: true + } + }); + var Field = db.model('gh4817_0', fieldSchema, 'fields'); + + var imageFieldSchema = new mongoose.Schema({ + value: { + type: mongoose.Schema.Types.ObjectId, + ref: 'gh4817', + default: null + } + }); + var FieldImage = Field.discriminator('gh4817_1', imageFieldSchema); + + var textFieldSchema = new mongoose.Schema({ + value: { + type: Schema.Types.Mixed, + required: true, + default: {} + } + }); + var FieldText = Field.discriminator('gh4817_2', textFieldSchema); + + var objectSchema = new mongoose.Schema({ + name: { + type: String, + required: true + }, + fields: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'gh4817_0' + }] + }); + var ObjectModel = db.model('gh4817_3', objectSchema, 'objects'); + + Image.create({ name: 'testimg' }). + then(function(image) { + return FieldImage.create({ name: 'test', value: image._id }); + }). + then(function(fieldImage) { + return FieldText.create({ name: 'test', value: 'test' }). + then(function(fieldText) { + return [fieldImage, fieldText]; + }); + }). + then(function(fields) { + return ObjectModel.create({ fields: fields, name: 'test' }); + }). + then(function(obj) { + return ObjectModel.findOne({ _id: obj._id }).populate({ + path: 'fields', + populate: { + path: 'value' + } + }); + }). + then(function(obj) { + assert.equal(obj.fields.length, 2); + assert.equal(obj.fields[0].value.name, 'testimg'); + assert.equal(obj.fields[1].value, 'test'); + done(); + }). + catch(done); + }); + it('nested populate, virtual -> normal (gh-4631)', function(done) { var PersonSchema = new Schema({ name: String From 2cfe8f84e8e9c21b977ff115202b852c1bca5589 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 23 Dec 2016 17:45:59 -0700 Subject: [PATCH 1087/2240] fix(model): handles populating with discriminators that may not have a ref Fix #4817 --- lib/model.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 26a87f52eac..936f54bae89 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2710,6 +2710,7 @@ function populate(model, docs, options, callback) { if (subPopulate) { query.populate(subPopulate); } + query.exec(next.bind(this, mod, assignmentOpts)); } @@ -2980,7 +2981,7 @@ function getModelsMapForPopulate(model, docs, options) { modelNames = [virtual && virtual.options && virtual.options.ref]; isVirtual = true; } else { - modelNames = [model.modelName]; + modelNames = null; } } else { modelNames = [modelNameFromQuery]; // query options From 71974488beccbecf6b00d45dbf7c549e5b7ad9e6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 24 Dec 2016 14:25:07 -0700 Subject: [PATCH 1088/2240] fix(aggregate): remove unhandled rejection when using aggregate.then() Fix #4824 --- lib/aggregate.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index bb24e88db15..817f424f40c 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -603,15 +603,7 @@ Aggregate.prototype.exec = function(callback) { * @return {Promise} */ Aggregate.prototype.then = function(resolve, reject) { - var _this = this; - var Promise = PromiseProvider.get(); - var promise = new Promise.ES6(function(success, error) { - _this.exec(function(err, val) { - if (err) error(err); - else success(val); - }); - }); - return promise.then(resolve, reject); + return this.exec().then(resolve, reject); }; /*! From 1e1803025c41a5648f8b79dfc50cd01fec6dd4bd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 24 Dec 2016 14:36:53 -0700 Subject: [PATCH 1089/2240] test(document): repro #3575 --- test/document.modified.test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/document.modified.test.js b/test/document.modified.test.js index 13c02a983ef..2eecd53ca80 100644 --- a/test/document.modified.test.js +++ b/test/document.modified.test.js @@ -437,6 +437,34 @@ describe('document modified', function() { assert.ok(account.roles[0].users[0].isModified); done(); }); + + it('with discriminators (gh-3575)', function(done) { + var shapeSchema = new mongoose.Schema({}, {discriminatorKey: 'kind'}); + + var Shape = mongoose.model('gh3575', shapeSchema); + + var Circle = Shape.discriminator('gh3575_0', new mongoose.Schema({ + radius: { type: Number } + }, {discriminatorKey: 'kind'})); + + var fooSchema = new mongoose.Schema({ + bars: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'gh3575' + }] + }); + + var Foo = mongoose.model('Foo', fooSchema); + + var test = new Foo({}); + test.bars = [new Circle({}), new Circle({})]; + + assert.ok(test.populated('bars')); + assert.ok(test.bars[0]._id); + assert.ok(test.bars[1]._id); + + done(); + }); }); it('should support setting mixed paths by string (gh-1418)', function(done) { From 3e51f41708de3a1bf4f061d108fa90a0ba9dad72 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 24 Dec 2016 14:37:06 -0700 Subject: [PATCH 1090/2240] fix(document): handle setting array of discriminators Fix #3575 --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 41d66443174..7888f810735 100644 --- a/lib/document.js +++ b/lib/document.js @@ -731,7 +731,7 @@ Document.prototype.set = function(path, val, type, options) { val.length > 0 && val[0] instanceof Document && val[0].constructor.modelName && - schema.options.type[0].ref === val[0].constructor.modelName) { + schema.options.type[0].ref === (val[0].constructor.baseModelName || val[0].constructor.modelName)) { if (this.ownerDocument) { popOpts = { model: val[0].constructor }; this.ownerDocument().populated(this.$__fullPath(path), From 4cca61ee65827e08238843e8f1f837c93bce2d9d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 24 Dec 2016 16:56:31 -0700 Subject: [PATCH 1091/2240] perf: remove try/catch that kills optimizer Re: #4821 --- lib/schema/documentarray.js | 3 +-- lib/types/documentarray.js | 3 +++ test/document.strict.test.js | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index c1535e84919..70a16e4a1f6 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -242,9 +242,8 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { subdoc = new this.casterConstructor(null, value, true, selected, i); value[i] = subdoc.init(value[i]); } else { - try { + if (prev && (subdoc = prev.id(value[i]._id))) { subdoc = prev.id(value[i]._id); - } catch (e) { } if (prev && subdoc) { diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index 50efefba5f7..e68cac36aaf 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -147,6 +147,9 @@ MongooseDocumentArray.mixin = { } for (var i = 0, l = this.length; i < l; i++) { + if (!this[i]) { + continue; + } _id = this[i].get('_id'); if (_id === null || typeof _id === 'undefined') { diff --git a/test/document.strict.test.js b/test/document.strict.test.js index 3e819414155..49623056f61 100644 --- a/test/document.strict.test.js +++ b/test/document.strict.test.js @@ -436,7 +436,7 @@ describe('document: strict mode:', function() { }, {strict: 'throw'}); // Create the model - var Foo = mongoose.model('Foo', FooSchema); + var Foo = mongoose.model('gh2665', FooSchema); assert.doesNotThrow(function() { new Foo({name: mongoose.Types.ObjectId(), father: {name: {full: 'bacon'}}}); From f3e9400a7aa9f8e12b28c20fa49e41658c600e40 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 25 Dec 2016 13:55:47 -0700 Subject: [PATCH 1092/2240] perf(document): remove some reduce and forEach to speed up #4821 --- lib/document.js | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/lib/document.js b/lib/document.js index 7888f810735..022ea01d025 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1893,32 +1893,40 @@ Document.prototype.$__registerHooksFromSchema = function() { var _this = this; var q = _this.schema && _this.schema.callQueue; + var toWrapEl; + var len; + var i; + var pointCut; if (!q.length) { return _this; } // we are only interested in 'pre' hooks, and group by point-cut - var toWrap = q.reduce(function(seed, pair) { + var toWrap = { post: [] }; + var pair; + + for (i = 0; i < q.length; ++i) { + pair = q[i]; if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') { _this[pair[0]].apply(_this, pair[1]); - return seed; + continue; } var args = [].slice.call(pair[1]); - var pointCut = pair[0] === 'on' ? 'post' : args[0]; - if (!(pointCut in seed)) { - seed[pointCut] = {post: [], pre: []}; + pointCut = pair[0] === 'on' ? 'post' : args[0]; + if (!(pointCut in toWrap)) { + toWrap[pointCut] = {post: [], pre: []}; } if (pair[0] === 'post') { - seed[pointCut].post.push(args); + toWrap[pointCut].post.push(args); } else if (pair[0] === 'on') { - seed[pointCut].push(args); + toWrap[pointCut].push(args); } else { - seed[pointCut].pre.push(args); + toWrap[pointCut].pre.push(args); } - return seed; - }, {post: []}); + } // 'post' hooks are simpler + len = toWrap.post.length; toWrap.post.forEach(function(args) { _this.on.apply(_this, args); }); @@ -2012,14 +2020,21 @@ Document.prototype.$__registerHooksFromSchema = function() { return promise; }; - toWrap[pointCut].pre.forEach(function(args) { + toWrapEl = toWrap[pointCut]; + len = toWrapEl.pre.length; + var args; + for (i = 0; i < len; ++i) { + args = toWrapEl.pre[i]; args[0] = newName; _this.$pre.apply(_this, args); - }); - toWrap[pointCut].post.forEach(function(args) { + } + + len = toWrapEl.post.length; + for (i = 0; i < len; ++i) { + args = toWrapEl.post[i]; args[0] = newName; _this.$post.apply(_this, args); - }); + } }); return _this; }; From 7006b5ec86b19a5b1df8618b2116c8810f173d0f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 25 Dec 2016 14:01:14 -0700 Subject: [PATCH 1093/2240] perf(document): remove slow forEach Re: #4281 --- lib/document.js | 119 +++++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 56 deletions(-) diff --git a/lib/document.js b/lib/document.js index 022ea01d025..bb433f01a5b 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1896,7 +1896,9 @@ Document.prototype.$__registerHooksFromSchema = function() { var toWrapEl; var len; var i; + var j; var pointCut; + var keys; if (!q.length) { return _this; } @@ -1960,82 +1962,87 @@ Document.prototype.$__registerHooksFromSchema = function() { delete toWrap.set; } - Object.keys(toWrap).forEach(function(pointCut) { + keys = Object.keys(toWrap); + len = keys.length; + for (i = 0; i < len; ++i) { + pointCut = keys[i]; // this is so we can wrap everything into a promise; var newName = ('$__original_' + pointCut); if (!_this[pointCut]) { return; } _this[newName] = _this[pointCut]; - _this[pointCut] = function wrappedPointCut() { - var args = [].slice.call(arguments); - var lastArg = args.pop(); - var fn; - var originalError = new Error(); - var $results; - if (lastArg && typeof lastArg !== 'function') { - args.push(lastArg); - } else { - fn = lastArg; - } + _this[pointCut] = (function(_newName) { + return function wrappedPointCut() { + var args = [].slice.call(arguments); + var lastArg = args.pop(); + var fn; + var originalError = new Error(); + var $results; + if (lastArg && typeof lastArg !== 'function') { + args.push(lastArg); + } else { + fn = lastArg; + } - var promise = new Promise.ES6(function(resolve, reject) { - args.push(function(error) { - if (error) { - // gh-2633: since VersionError is very generic, take the - // stack trace of the original save() function call rather - // than the async trace - if (error instanceof VersionError) { - error.stack = originalError.stack; + var promise = new Promise.ES6(function(resolve, reject) { + args.push(function(error) { + if (error) { + // gh-2633: since VersionError is very generic, take the + // stack trace of the original save() function call rather + // than the async trace + if (error instanceof VersionError) { + error.stack = originalError.stack; + } + _this.$__handleReject(error); + reject(error); + return; } - _this.$__handleReject(error); - reject(error); - return; - } - // There may be multiple results and promise libs other than - // mpromise don't support passing multiple values to `resolve()` - $results = Array.prototype.slice.call(arguments, 1); - resolve.apply(promise, $results); - }); + // There may be multiple results and promise libs other than + // mpromise don't support passing multiple values to `resolve()` + $results = Array.prototype.slice.call(arguments, 1); + resolve.apply(promise, $results); + }); - _this[newName].apply(_this, args); - }); - if (fn) { - if (_this.constructor.$wrapCallback) { - fn = _this.constructor.$wrapCallback(fn); - } - return promise.then( - function() { - process.nextTick(function() { - fn.apply(null, [null].concat($results)); - }); - }, - function(error) { - process.nextTick(function() { - fn(error); + _this[_newName].apply(_this, args); + }); + if (fn) { + if (_this.constructor.$wrapCallback) { + fn = _this.constructor.$wrapCallback(fn); + } + return promise.then( + function() { + process.nextTick(function() { + fn.apply(null, [null].concat($results)); + }); + }, + function(error) { + process.nextTick(function() { + fn(error); + }); }); - }); - } - return promise; - }; + } + return promise; + }; + })(newName); toWrapEl = toWrap[pointCut]; - len = toWrapEl.pre.length; - var args; - for (i = 0; i < len; ++i) { - args = toWrapEl.pre[i]; + var _len = toWrapEl.pre.length; + args; + for (j = 0; j < _len; ++j) { + args = toWrapEl.pre[j]; args[0] = newName; _this.$pre.apply(_this, args); } - len = toWrapEl.post.length; - for (i = 0; i < len; ++i) { - args = toWrapEl.post[i]; + _len = toWrapEl.post.length; + for (j = 0; j < _len; ++j) { + args = toWrapEl.post[j]; args[0] = newName; _this.$post.apply(_this, args); } - }); + } return _this; }; From e568ac1de8f5790361de2ce4e714145a7c08d05a Mon Sep 17 00:00:00 2001 From: Billouboq Date: Mon, 26 Dec 2016 11:38:57 +0100 Subject: [PATCH 1094/2240] remove unecessary in --- lib/query.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/query.js b/lib/query.js index 489a7906ab0..09f8ff9b803 100644 --- a/lib/query.js +++ b/lib/query.js @@ -872,7 +872,7 @@ Query.prototype.setOptions = function(options, overwrite) { this._mongooseOptions = (options && utils.clone(options)) || {}; this.options = options || {}; - if ('populate' in options) { + if (options.populate) { this.populate(this._mongooseOptions); } return this; @@ -1025,11 +1025,11 @@ Query.prototype._optionsForExec = function(model) { return options; } - if (!('safe' in options) && model.schema.options.safe) { + if (!options.safe && model.schema.options.safe) { options.safe = model.schema.options.safe; } - if (!('readPreference' in options) && model.schema.options.read) { + if (!options.readPreference && model.schema.options.read) { options.readPreference = model.schema.options.read; } From e6f4c36ce4845a6dbf7e959eef56a5580fd4ae6c Mon Sep 17 00:00:00 2001 From: Billouboq Date: Mon, 26 Dec 2016 11:39:09 +0100 Subject: [PATCH 1095/2240] remove unused propertie --- lib/query.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 09f8ff9b803..e0f0df28ffe 100644 --- a/lib/query.js +++ b/lib/query.js @@ -984,7 +984,6 @@ Query.prototype._updateForExec = function() { } } - this._compiledUpdate = ret; return ret; }; From 94a3b89548bcaffd4732f4fdf5b9fe8de663a15e Mon Sep 17 00:00:00 2001 From: Billouboq Date: Mon, 26 Dec 2016 11:46:38 +0100 Subject: [PATCH 1096/2240] inline try functions --- lib/query.js | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/lib/query.js b/lib/query.js index e0f0df28ffe..01952e7cdc0 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1139,12 +1139,7 @@ Query.prototype.find = function(conditions, callback) { prepareDiscriminatorCriteria(this); - try { - this.cast(this.model); - this._castError = null; - } catch (err) { - this._castError = err; - } + tryCastFind(this); // if we don't have a callback, then just return the query object if (!callback) { @@ -1156,6 +1151,15 @@ Query.prototype.find = function(conditions, callback) { return this; }; +function tryCastFind(query) { + try { + query.cast(this.model); + query._castError = null; + } catch (err) { + query._castError = err; + } +} + /** * Merges another Query or conditions object into this one. * @@ -1349,12 +1353,7 @@ Query.prototype.findOne = function(conditions, projection, options, callback) { prepareDiscriminatorCriteria(this); - try { - this.cast(this.model); - this._castError = null; - } catch (err) { - this._castError = err; - } + tryCastFindOne(this); if (!callback) { // already merged in the conditions, don't need to send them in. @@ -1366,6 +1365,15 @@ Query.prototype.findOne = function(conditions, projection, options, callback) { return this; }; +function tryCastFindOne(query) { + try { + query.cast(query.model); + query._castError = null; + } catch (err) { + query._castError = err; + } +} + /** * Thunk around count() * @@ -2995,15 +3003,19 @@ Query.prototype.cursor = function cursor(opts) { this.setOptions(opts); } - try { - this.cast(this.model); - } catch (err) { - return (new QueryCursor(this, this.options))._markError(err); - } + tryCastCursor(query); return new QueryCursor(this, this.options); }; +function tryCastCursor(query) { + try { + query.cast(this.model); + } catch (err) { + return (new QueryCursor(query, query.options))._markError(err); + } +} + // the rest of these are basically to support older Mongoose syntax with mquery /** From ad34dd9a401395c10778e1bde75cdc27cdeaf3e3 Mon Sep 17 00:00:00 2001 From: Billouboq Date: Mon, 26 Dec 2016 11:49:43 +0100 Subject: [PATCH 1097/2240] remove unused parameter --- lib/query.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/query.js b/lib/query.js index 01952e7cdc0..30a72adff30 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1094,7 +1094,7 @@ Query.prototype._find = function(callback) { if (!options.populate) { return options.lean === true ? callback(null, docs) - : completeMany(_this.model, docs, fields, _this, null, callback); + : completeMany(_this.model, docs, fields, null, callback); } var pop = helpers.preparePopulationOptionsMQ(_this, options); @@ -1103,7 +1103,7 @@ Query.prototype._find = function(callback) { if (err) return callback(err); return options.lean === true ? callback(null, docs) - : completeMany(_this.model, docs, fields, _this, pop, callback); + : completeMany(_this.model, docs, fields, pop, callback); }); }; @@ -1222,7 +1222,7 @@ Query.prototype.merge = function(source) { * @param {Function} callback */ -function completeMany(model, docs, fields, self, pop, callback) { +function completeMany(model, docs, fields, pop, callback) { var arr = []; var count = docs.length; var len = count; @@ -1271,7 +1271,7 @@ Query.prototype._findOne = function(callback) { if (!options.populate) { return options.lean === true ? callback(null, doc) - : completeOne(_this.model, doc, null, projection, _this, null, callback); + : completeOne(_this.model, doc, null, projection, null, callback); } var pop = helpers.preparePopulationOptionsMQ(_this, options); @@ -1282,7 +1282,7 @@ Query.prototype._findOne = function(callback) { } return options.lean === true ? callback(null, doc) - : completeOne(_this.model, doc, null, projection, _this, pop, callback); + : completeOne(_this.model, doc, null, projection, pop, callback); }); }); }; @@ -1607,7 +1607,7 @@ Query.prototype.remove = function(cond, callback) { * @param {Function} callback */ -function completeOne(model, doc, res, fields, self, pop, callback) { +function completeOne(model, doc, res, fields, pop, callback) { var opts = pop ? {populated: pop} : undefined; @@ -1943,7 +1943,7 @@ Query.prototype._findAndModify = function(type, callback) { if (!options.populate) { return options.lean === true ? (opts.passRawResult ? callback(null, doc, res) : callback(null, doc)) - : completeOne(_this.model, doc, res, fields, _this, null, callback); + : completeOne(_this.model, doc, res, fields, null, callback); } var pop = helpers.preparePopulationOptionsMQ(_this, options); @@ -1955,7 +1955,7 @@ Query.prototype._findAndModify = function(type, callback) { return options.lean === true ? (opts.passRawResult ? callback(null, doc, res) : callback(null, doc)) - : completeOne(_this.model, doc, res, fields, _this, pop, callback); + : completeOne(_this.model, doc, res, fields, pop, callback); }); }; From 06f9d51f04ed8172d37fa638c835c513c11f82d9 Mon Sep 17 00:00:00 2001 From: Billouboq Date: Mon, 26 Dec 2016 14:29:32 +0100 Subject: [PATCH 1098/2240] reverse in removal, change try fn --- lib/query.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/query.js b/lib/query.js index 30a72adff30..66a016d9e9a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -872,7 +872,7 @@ Query.prototype.setOptions = function(options, overwrite) { this._mongooseOptions = (options && utils.clone(options)) || {}; this.options = options || {}; - if (options.populate) { + if ('populate' in options) { this.populate(this._mongooseOptions); } return this; @@ -984,6 +984,7 @@ Query.prototype._updateForExec = function() { } } + this._compiledUpdate = ret; return ret; }; @@ -1024,11 +1025,11 @@ Query.prototype._optionsForExec = function(model) { return options; } - if (!options.safe && model.schema.options.safe) { + if (!('safe' in options) && model.schema.options.safe) { options.safe = model.schema.options.safe; } - if (!options.readPreference && model.schema.options.read) { + if (!('readPreference' in options) && model.schema.options.read) { options.readPreference = model.schema.options.read; } @@ -1153,7 +1154,7 @@ Query.prototype.find = function(conditions, callback) { function tryCastFind(query) { try { - query.cast(this.model); + query.cast(query.model); query._castError = null; } catch (err) { query._castError = err; @@ -3003,16 +3004,21 @@ Query.prototype.cursor = function cursor(opts) { this.setOptions(opts); } - tryCastCursor(query); + var err = tryCastCursor(this); + var queryCursor = new QueryCursor(this, this.options); - return new QueryCursor(this, this.options); + if (err) { + return queryCursor._markError(err); + } else { + return queryCursor; + } }; function tryCastCursor(query) { try { - query.cast(this.model); + query.cast(query.model); } catch (err) { - return (new QueryCursor(query, query.options))._markError(err); + return err; } } From 7d48e7e9c78dd09f449340b2933bfc87b282f412 Mon Sep 17 00:00:00 2001 From: Billouboq Date: Mon, 26 Dec 2016 14:31:31 +0100 Subject: [PATCH 1099/2240] remove unused property --- lib/query.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 66a016d9e9a..35787ea846f 100644 --- a/lib/query.js +++ b/lib/query.js @@ -984,7 +984,6 @@ Query.prototype._updateForExec = function() { } } - this._compiledUpdate = ret; return ret; }; From d4bfb333874ffbc428fa77208bfa789048aa46ad Mon Sep 17 00:00:00 2001 From: Billouboq Date: Mon, 26 Dec 2016 14:41:32 +0100 Subject: [PATCH 1100/2240] reverse try fn --- lib/query.js | 51 +++++++++++++++++---------------------------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/lib/query.js b/lib/query.js index 35787ea846f..0a05c8d79e1 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1139,7 +1139,12 @@ Query.prototype.find = function(conditions, callback) { prepareDiscriminatorCriteria(this); - tryCastFind(this); + try { + this.cast(this.model); + this._castError = null; + } catch (err) { + this._castError = err; + } // if we don't have a callback, then just return the query object if (!callback) { @@ -1151,15 +1156,6 @@ Query.prototype.find = function(conditions, callback) { return this; }; -function tryCastFind(query) { - try { - query.cast(query.model); - query._castError = null; - } catch (err) { - query._castError = err; - } -} - /** * Merges another Query or conditions object into this one. * @@ -1353,7 +1349,12 @@ Query.prototype.findOne = function(conditions, projection, options, callback) { prepareDiscriminatorCriteria(this); - tryCastFindOne(this); + try { + this.cast(this.model); + this._castError = null; + } catch (err) { + this._castError = err; + } if (!callback) { // already merged in the conditions, don't need to send them in. @@ -1365,15 +1366,6 @@ Query.prototype.findOne = function(conditions, projection, options, callback) { return this; }; -function tryCastFindOne(query) { - try { - query.cast(query.model); - query._castError = null; - } catch (err) { - query._castError = err; - } -} - /** * Thunk around count() * @@ -3003,23 +2995,14 @@ Query.prototype.cursor = function cursor(opts) { this.setOptions(opts); } - var err = tryCastCursor(this); - var queryCursor = new QueryCursor(this, this.options); - - if (err) { - return queryCursor._markError(err); - } else { - return queryCursor; - } -}; - -function tryCastCursor(query) { try { - query.cast(query.model); + this.cast(this.model); } catch (err) { - return err; + return (new QueryCursor(this, this.options))._markError(err); } -} + + return new QueryCursor(this, this.options); +}; // the rest of these are basically to support older Mongoose syntax with mquery From 4b47b5d3abf31247eab605512b154964b37bc6ca Mon Sep 17 00:00:00 2001 From: Billouboq Date: Mon, 26 Dec 2016 14:49:01 +0100 Subject: [PATCH 1101/2240] fix insertedId error and change benchmark output --- benchmarks/benchjs/casting.js | 2 +- benchmarks/benchjs/delete.js | 4 ++-- benchmarks/benchjs/insert.js | 2 +- benchmarks/benchjs/multiop.js | 6 +++--- benchmarks/benchjs/population.js | 2 +- benchmarks/benchjs/update.js | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/benchmarks/benchjs/casting.js b/benchmarks/benchjs/casting.js index d5ca05d0141..1b9b3dbeb91 100644 --- a/benchmarks/benchjs/casting.js +++ b/benchmarks/benchjs/casting.js @@ -136,6 +136,6 @@ suite.add('Casting - Embedded Docs - 0 Docs', { out.ops = item.hz; outObj[item.name.replace(/\s/g, '')] = out; }); - console.log(JSON.stringify(outObj)); + console.dir(outObj, {depth: null, colors: true}); } }).run({async: true}); diff --git a/benchmarks/benchjs/delete.js b/benchmarks/benchjs/delete.js index 028ac6b34e7..3791ad3a5ad 100644 --- a/benchmarks/benchjs/delete.js +++ b/benchmarks/benchjs/delete.js @@ -61,7 +61,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { nData.likes = data.likes; nData.address = data.address; user.insert(nData, function(err, res) { - dIds.push(res[0]._id); + dIds.push(res.insertedIds[0]); --count || next(); }); } @@ -120,7 +120,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { out.ops = item.hz; outObj[item.name.replace(/\s/g, '')] = out; }); - console.log(JSON.stringify(outObj)); + console.dir(outObj, {depth: null, colors: true}); } }); function next() { diff --git a/benchmarks/benchjs/insert.js b/benchmarks/benchjs/insert.js index b2d257880b0..a8c15117304 100644 --- a/benchmarks/benchjs/insert.js +++ b/benchmarks/benchjs/insert.js @@ -169,7 +169,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { out.ops = item.hz; outObj[item.name.replace(/\s/g, '')] = out; }); - console.log(JSON.stringify(outObj)); + console.dir(outObj, {depth: null, colors: true}); } }).run({async: true}); }); diff --git a/benchmarks/benchjs/multiop.js b/benchmarks/benchjs/multiop.js index 8b121a19391..79fc73d38f7 100644 --- a/benchmarks/benchjs/multiop.js +++ b/benchmarks/benchjs/multiop.js @@ -126,7 +126,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { if (err) { throw err; } - dIds.push(res[0]._id); + dIds.push(res.insertedIds[0]); --count || next(); }); BlogPost.create(blogData, function(err, bp) { @@ -142,7 +142,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { if (err) { throw err; } - bdIds.push(res[0]._id); + bdIds.push(res.insertedIds[0]); --count || next(); }); } @@ -447,7 +447,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { out.ops = item.hz; outObj[item.name.replace(/\s/g, '')] = out; }); - console.log(JSON.stringify(outObj)); + console.dir(outObj, {depth: null, colors: true}); } }); function next() { diff --git a/benchmarks/benchjs/population.js b/benchmarks/benchjs/population.js index d7b7cb7608b..5942c8ac9f1 100644 --- a/benchmarks/benchjs/population.js +++ b/benchmarks/benchjs/population.js @@ -387,7 +387,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench-pop', function(err) { out.ops = item.hz; outObj[item.name.replace(/\s/g, '')] = out; }); - console.log(JSON.stringify(outObj)); + console.dir(outObj, {depth: null, colors: true}); } }); function next() { diff --git a/benchmarks/benchjs/update.js b/benchmarks/benchjs/update.js index 62bd971226b..3c32a9b20ef 100644 --- a/benchmarks/benchjs/update.js +++ b/benchmarks/benchjs/update.js @@ -115,7 +115,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { }); var nData = utils.clone(data); user.insert(nData, function(err, res) { - dIds.push(res[0]._id); + dIds.push(res.insertedIds[0]); --count || next(); }); BlogPost.create(blogData, function(err, bp) { @@ -132,7 +132,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { if (err) { throw err; } - bdIds.push(res[0]._id); + bdIds.push(res.insertedIds[0]); --count || next(); }); } @@ -329,7 +329,7 @@ mongoose.connect('mongodb://localhost/mongoose-bench', function(err) { out.ops = item.hz; outObj[item.name.replace(/\s/g, '')] = out; }); - console.log(JSON.stringify(outObj)); + console.dir(outObj, {depth: null, colors: true}); } }); function next() { From 08a0b618c765bbea96fc5357a4a36964c725cf57 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 26 Dec 2016 10:06:32 -0700 Subject: [PATCH 1102/2240] chore: release 4.7.5 --- History.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/History.md b/History.md index 1e8bcb3a90f..0a9fdf993f1 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.7.5 / 2016-12-26 +================== + * docs(model): fix spelling mistake #4828 [paulinoj](https://github.com/paulinoj) + * fix(aggregate): remove unhandled rejection when using aggregate.then() #4824 + * perf: remove try/catch that kills optimizer #4821 + * fix(model): handles populating with discriminators that may not have a ref #4817 + * fix(document): handle setting array of discriminators #3575 + 4.7.4 / 2016-12-21 ================== * docs: fix typo #4810 [GEEKIAM](https://github.com/GEEKIAM) From efad9bb8c0916b782c0d15f08d5abbe611cd8843 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 26 Dec 2016 10:07:38 -0700 Subject: [PATCH 1103/2240] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6f32fc27321..39b81a4121d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.5-pre", + "version": "4.7.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 90878d316be97dfe6a0b59cbb0bf06cafcb95fdb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 27 Dec 2016 08:29:43 -0700 Subject: [PATCH 1104/2240] chore: now working on 4.7.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 39b81a4121d..cf9be44bb6b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.5", + "version": "4.7.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From f5de5297f740be498ea59c57819fb4b4a4acba3a Mon Sep 17 00:00:00 2001 From: Timothy Soehnlin Date: Tue, 27 Dec 2016 12:22:41 -0500 Subject: [PATCH 1105/2240] Allowing callback to be optional This allows callback to be optional as `$__validate` assumes callback is defined and not optional. --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index bb433f01a5b..08719092a8f 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1232,7 +1232,7 @@ Document.prototype.validate = function(options, callback) { options = null; } - this.$__validate(callback); + this.$__validate(callback || function() {}); }; /*! From 6d83cd2a433119dc9b0552ec0fefe7a5585aa380 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 29 Dec 2016 16:41:46 -0700 Subject: [PATCH 1106/2240] refactor: more work re: refactoring registerHooksFromSchema --- lib/document.js | 8 ++- lib/model.js | 145 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 150 insertions(+), 3 deletions(-) diff --git a/lib/document.js b/lib/document.js index bb433f01a5b..809d2527560 100644 --- a/lib/document.js +++ b/lib/document.js @@ -37,7 +37,7 @@ var mpath = require('mpath'); * @api private */ -function Document(obj, fields, skipId) { +function Document(obj, fields, skipId, skipHooks) { this.$__ = new InternalCache; this.$__.emitter = new EventEmitter(); this.isNew = true; @@ -79,7 +79,9 @@ function Document(obj, fields, skipId) { }); } - this.$__registerHooksFromSchema(); + if (!skipHooks) { + this.$__registerHooksFromSchema(); + } } /*! @@ -313,6 +315,8 @@ Document.prototype.init = function(doc, opts, fn) { this.$__storeShard(); this.emit('init', this); + this.constructor.emit('init', this); + if (fn) { fn(null); } diff --git a/lib/model.js b/lib/model.js index 95f0a0d06d5..edb8d836d70 100644 --- a/lib/model.js +++ b/lib/model.js @@ -18,6 +18,7 @@ var tick = utils.tick; var parallel = require('async/parallel'); var PromiseProvider = require('./promise_provider'); +var Embedded; var VERSION_WHERE = 1, VERSION_INC = 2, @@ -44,7 +45,7 @@ var POJO_TO_OBJECT_OPTIONS = { */ function Model(doc, fields, skipId) { - Document.call(this, doc, fields, skipId); + Document.call(this, doc, fields, skipId, true); } /*! @@ -130,6 +131,7 @@ Model.prototype.$__handleSave = function(options, callback) { if (err) { _this.isNew = true; _this.emit('isNew', true); + _this.constructor.emit('isNew', true); callback(err); return; @@ -140,6 +142,7 @@ Model.prototype.$__handleSave = function(options, callback) { this.$__reset(); this.isNew = false; this.emit('isNew', false); + this.constructor.emit('isNew', false); // Make it possible to retry the insert this.$__.inserting = true; } else { @@ -176,6 +179,7 @@ Model.prototype.$__handleSave = function(options, callback) { } this.emit('isNew', false); + this.constructor.emit('isNew', false); } }; @@ -229,6 +233,7 @@ Model.prototype.$__save = function(options, callback) { } _this.emit('save', _this, numAffected); + _this.constructor.emit('save', _this, numAffected); callback(null, _this, numAffected); }); }; @@ -734,6 +739,7 @@ Model.prototype.remove = function remove(options, fn) { _this.collection.remove(where, options, function(err) { if (!err) { _this.emit('remove', _this); + _this.constructor.emit('remove', _this); resolve(_this); fn && fn(null, _this); return; @@ -1965,6 +1971,7 @@ Model.insertMany = function(arr, callback) { for (var i = 0; i < docs.length; ++i) { docs[i].isNew = false; docs[i].emit('isNew', false); + docs[i].constructor.emit('isNew', false); } callback && callback(null, docs); }); @@ -3266,6 +3273,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base) // apply methods and statics applyMethods(model, schema); applyStatics(model, schema); + applyHooks(model, schema); model.schema = model.prototype.schema; model.collection = model.prototype.collection; @@ -3299,6 +3307,141 @@ Model.compile = function compile(name, schema, collectionName, connection, base) return model; }; +/*! + * Register hooks for this model + * + * @param {Model} model + * @param {Schema} schema + */ + +function applyHooks(model, schema) { + Embedded = Embedded || require('./types/embedded'); + var Promise = PromiseProvider.get(); + + var q = schema && schema.callQueue; + var toWrapEl; + var len; + var i; + var j; + var pointCut; + var keys; + if (!q.length) { + return; + } + + // we are only interested in 'pre' hooks, and group by point-cut + var toWrap = { post: [] }; + var pair; + + for (i = 0; i < q.length; ++i) { + pair = q[i]; + if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') { + continue; + } + var args = [].slice.call(pair[1]); + pointCut = pair[0] === 'on' ? 'post' : args[0]; + if (!(pointCut in toWrap)) { + toWrap[pointCut] = {post: [], pre: []}; + } + if (pair[0] === 'post') { + toWrap[pointCut].post.push(args); + } else if (pair[0] === 'on') { + toWrap[pointCut].push(args); + } else { + toWrap[pointCut].pre.push(args); + } + } + + // 'post' hooks are simpler + len = toWrap.post.length; + toWrap.post.forEach(function(args) { + model.on.apply(model, args); + }); + delete toWrap.post; + + keys = Object.keys(toWrap); + len = keys.length; + for (i = 0; i < len; ++i) { + pointCut = keys[i]; + // this is so we can wrap everything into a promise; + var newName = ('$__original_' + pointCut); + if (!model.prototype[pointCut]) { + return; + } + model.prototype[newName] = model.prototype[pointCut]; + model.prototype[pointCut] = (function(_newName) { + return function wrappedPointCut() { + var _this = this; + var args = [].slice.call(arguments); + var lastArg = args.pop(); + var fn; + var originalError = new Error(); + var $results; + if (lastArg && typeof lastArg !== 'function') { + args.push(lastArg); + } else { + fn = lastArg; + } + + var promise = new Promise.ES6(function(resolve, reject) { + args.push(function(error) { + if (error) { + // gh-2633: since VersionError is very generic, take the + // stack trace of the original save() function call rather + // than the async trace + if (error instanceof VersionError) { + error.stack = originalError.stack; + } + _this.$__handleReject(error); + reject(error); + return; + } + + // There may be multiple results and promise libs other than + // mpromise don't support passing multiple values to `resolve()` + $results = Array.prototype.slice.call(arguments, 1); + resolve.apply(promise, $results); + }); + + _this[_newName].apply(_this, args); + }); + if (fn) { + if (this.constructor.$wrapCallback) { + fn = this.constructor.$wrapCallback(fn); + } + return promise.then( + function() { + process.nextTick(function() { + fn.apply(null, [null].concat($results)); + }); + }, + function(error) { + process.nextTick(function() { + fn(error); + }); + }); + } + return promise; + }; + })(newName); + + toWrapEl = toWrap[pointCut]; + var _len = toWrapEl.pre.length; + for (j = 0; j < _len; ++j) { + args = toWrapEl.pre[j]; + args[0] = newName; + model.prototype.$pre.apply(model.prototype, args); + } + + _len = toWrapEl.post.length; + for (j = 0; j < _len; ++j) { + args = toWrapEl.post[j]; + args[0] = newName; + model.prototype.$post.apply(model.prototype, args); + } + } +} + /*! * Register methods for this model * From a5150d6c5a6a763e89212ff41e3ada28eb526ba3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 29 Dec 2016 16:47:03 -0700 Subject: [PATCH 1107/2240] fix(document): don't skip pointCut if save not defined (like in browser doc) Fix #4841 --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 08719092a8f..1252f7a3fbe 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1969,7 +1969,7 @@ Document.prototype.$__registerHooksFromSchema = function() { // this is so we can wrap everything into a promise; var newName = ('$__original_' + pointCut); if (!_this[pointCut]) { - return; + continue; } _this[newName] = _this[pointCut]; _this[pointCut] = (function(_newName) { From deaa95b4b81213a2be46484eaf9cee1321cc3da7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Dec 2016 20:32:58 -0700 Subject: [PATCH 1108/2240] fix(model): allow passing non-array to insertMany Fix #4846 --- lib/model.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/model.js b/lib/model.js index 95f0a0d06d5..59ce712eb4d 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1930,6 +1930,10 @@ Model.insertMany = function(arr, callback) { callback = this.$wrapCallback(callback); } + if (!Array.isArray(arr)) { + arr = [arr]; + } + var toExecute = []; arr.forEach(function(doc) { toExecute.push(function(callback) { From 8f39e1b8741b89caa605d24ccca081b54fdfbd94 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Dec 2016 21:07:29 -0700 Subject: [PATCH 1109/2240] fix: handle refs correctly even if using browser driver Fix #4844 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cf9be44bb6b..76adbe6c553 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "license": "MIT", "dependencies": { "async": "2.1.4", - "bson": "~0.5.4", + "bson": "~1.0.1", "hooks-fixed": "1.2.0", "kareem": "1.1.5", "mongodb": "2.2.16", From f0aa82d4f4e4963efeb8b1332a55f01729f662f8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 31 Dec 2016 18:14:28 -0700 Subject: [PATCH 1110/2240] test(populate): repro #4843 --- test/model.populate.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 970d69a69df..10e72f207f2 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4621,6 +4621,32 @@ describe('model: populate:', function() { catch(done); }); + it('populate with no ref using Model.populate (gh-4843)', function(done) { + var schema = new Schema({ + parent: mongoose.Schema.Types.ObjectId, + name: String + }); + + var Person = db.model('gh4843', schema); + + Person.create({ name: 'Anakin' }). + then(function(parent) { + return Person.create({ name: 'Luke', parent: parent._id }); + }). + then(function(luke) { + return Person.findById(luke._id); + }). + then(function(luke) { + return Person.populate(luke, { path: 'parent', model: 'gh4843' }); + }). + then(function(luke) { + console.log('test', luke); + assert.equal(luke.parent.name, 'Anakin'); + done(); + }). + catch(done); + }); + it('nested populate, virtual -> normal (gh-4631)', function(done) { var PersonSchema = new Schema({ name: String From 62c8b08483055f7f610ab409067dd4c58b3241c9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 31 Dec 2016 18:14:31 -0700 Subject: [PATCH 1111/2240] fix(populate): use base model name if no discriminator for backwards compat Fix #4843 --- lib/model.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 59ce712eb4d..1e025860f07 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2985,7 +2985,9 @@ function getModelsMapForPopulate(model, docs, options) { modelNames = [virtual && virtual.options && virtual.options.ref]; isVirtual = true; } else { - modelNames = null; + // We may have a discriminator, in which case we don't want to + // populate using the base model by default + modelNames = discriminatorKey ? null : [model.modelName]; } } else { modelNames = [modelNameFromQuery]; // query options From 22552c528d4089bc9d493c50e21397b6817bfd47 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 31 Dec 2016 18:18:19 -0700 Subject: [PATCH 1112/2240] docs(populate): remove implicit Model.populate() example Re: #4843 --- lib/model.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index 1e025860f07..789a0b31159 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2526,8 +2526,8 @@ Model.geoSearch = function(conditions, options, callback) { * * User.populate(user, opts, function (err, user) { * console.log(user); - * }) - * }) + * }); + * }); * * // populates an array of objects * User.find(match, function (err, users) { @@ -2540,6 +2540,11 @@ Model.geoSearch = function(conditions, options, callback) { * // imagine a Weapon model exists with two saved documents: * // { _id: 389, name: 'whip' } * // { _id: 8921, name: 'boomerang' } + * // and this schema: + * // new Schema({ + * // name: String, + * // weapon: { type: ObjectId, ref: 'Weapon' } + * // }); * * var user = { name: 'Indiana Jones', weapon: 389 } * Weapon.populate(user, { path: 'weapon', model: 'Weapon' }, function (err, user) { @@ -2554,10 +2559,10 @@ Model.geoSearch = function(conditions, options, callback) { * console.log('%s uses a %s', users.name, user.weapon.name) * // Indiana Jones uses a whip * // Batman uses a boomerang - * }) - * }) + * }); + * }); * // Note that we didn't need to specify the Weapon model because - * // we were already using it's populate() method. + * // it is in the schema's ref * * @param {Document|Array} docs Either a single document or array of documents to populate. * @param {Object} options A hash of key/val (path, options) used for population. From d1492ceaa178abeb54aed83c86be8e7138d1cb8c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 1 Jan 2017 21:56:12 -0700 Subject: [PATCH 1113/2240] test(query): repro #4836 --- test/model.populate.test.js | 1 - test/query.middleware.test.js | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 10e72f207f2..f1c386e96bb 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4640,7 +4640,6 @@ describe('model: populate:', function() { return Person.populate(luke, { path: 'parent', model: 'gh4843' }); }). then(function(luke) { - console.log('test', luke); assert.equal(luke.parent.name, 'Anakin'); done(); }). diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 88536fcee55..868d01d2eaf 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -240,4 +240,26 @@ describe('query middleware', function() { }); }); }); + + it('error handlers with findOneAndUpdate and passRawResult (gh-4836)', function(done) { + var schema = new Schema({name: {type: String}}); + + var called = false; + var errorHandler = function(err, res, next) { + called = true; + next(); + }; + + schema.post('findOneAndUpdate', errorHandler); + + var Person = db.model('Person', schema); + + Person. + findOneAndUpdate({name: 'name'}, {}, {upsert: true, passRawResult: true}). + exec(function(error) { + assert.ifError(error); + assert.ok(!called); + done(); + }); + }); }); From 175ad2019b6482847c7f90e523aa85a3efbb6708 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 1 Jan 2017 22:01:43 -0700 Subject: [PATCH 1114/2240] fix(query): don't call error handler if passRawResult is true and no error occurred Fix #4836 --- lib/query.js | 19 +++++++++++++++---- package.json | 2 +- test/query.middleware.test.js | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/query.js b/lib/query.js index 0a05c8d79e1..2992da5698c 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1610,7 +1610,7 @@ function completeOne(model, doc, res, fields, pop, callback) { return callback(err); } if (res) { - return callback(null, casted, res); + return callback(null, casted, decorateResult(res)); } callback(null, casted); }); @@ -1831,6 +1831,17 @@ Query.prototype._findOneAndRemove = function(callback) { Query.base.findOneAndRemove.call(this, callback); }; +/*! + * ignore + */ + +function decorateResult(res) { + if (res) { + res._kareemIgnore = true; + } + return res; +} + /** * Override mquery.prototype._findAndModify to provide casting etc. * @@ -1923,7 +1934,7 @@ Query.prototype._findAndModify = function(type, callback) { if (!doc || (utils.isObject(doc) && Object.keys(doc).length === 0)) { if (opts.passRawResult) { - return callback(null, null, res); + return callback(null, null, decorateResult(res)); } return callback(null, null); } @@ -1934,7 +1945,7 @@ Query.prototype._findAndModify = function(type, callback) { if (!options.populate) { return options.lean === true - ? (opts.passRawResult ? callback(null, doc, res) : callback(null, doc)) + ? (opts.passRawResult ? callback(null, doc, decorateResult(res)) : callback(null, doc)) : completeOne(_this.model, doc, res, fields, null, callback); } @@ -1946,7 +1957,7 @@ Query.prototype._findAndModify = function(type, callback) { } return options.lean === true - ? (opts.passRawResult ? callback(null, doc, res) : callback(null, doc)) + ? (opts.passRawResult ? callback(null, doc, decorateResult(res)) : callback(null, doc)) : completeOne(_this.model, doc, res, fields, pop, callback); }); }; diff --git a/package.json b/package.json index 76adbe6c553..ca8ae475d60 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "2.1.4", "bson": "~1.0.1", "hooks-fixed": "1.2.0", - "kareem": "1.1.5", + "kareem": "1.2.0", "mongodb": "2.2.16", "mpath": "0.2.1", "mpromise": "0.5.5", diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 868d01d2eaf..1925f2235eb 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -262,4 +262,26 @@ describe('query middleware', function() { done(); }); }); + + it('error handlers with findOneAndUpdate error and passRawResult (gh-4836)', function(done) { + var schema = new Schema({name: {type: String}}); + + var called = false; + var errorHandler = function(err, res, next) { + called = true; + next(); + }; + + schema.post('findOneAndUpdate', errorHandler); + + var Person = db.model('Person', schema); + + Person. + findOneAndUpdate({}, {_id: 'test'}, {upsert: true, passRawResult: true}). + exec(function(error) { + assert.ok(error); + assert.ok(called); + done(); + }); + }); }); From 5a1129a2f980cacf643dd7ba17a0d5b22d6c4b71 Mon Sep 17 00:00:00 2001 From: David Wu Date: Sun, 1 Jan 2017 21:52:33 -0800 Subject: [PATCH 1115/2240] Fix warning from Bluebird: (node:56) Warning: a promise was created in a handler at app/node_modules/mongoose/lib/query.js:2313:18 but was not returned from it, see http://goo.gl/rRqMUw at new Promise (/app/node_modules/bluebird/js/release/promise.js:77:14) --- lib/query.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/query.js b/lib/query.js index 2992da5698c..d5f5cd02e88 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2321,6 +2321,7 @@ Query.prototype.exec = function exec(op, callback) { promise.then( function() { callback.apply(null, _results); + return null; }, function(error) { callback(error); From 7269a2eb464b166e547383c1bf81fa837b270f28 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 Jan 2017 11:25:57 -0700 Subject: [PATCH 1116/2240] refactor: remove __registerHooksFromSchema for top level docs Re: #2754 --- lib/document.js | 30 +++++++++++++++++++++++++- lib/model.js | 20 +++++++++++++++++- lib/schema/embedded.js | 8 ++++++- lib/types/embedded.js | 5 +++++ test/document.isselected.test.js | 19 ++++++++++------- test/document.test.js | 5 +++++ test/model.populate.test.js | 36 ++++++++++++++++---------------- test/types.document.test.js | 19 ++++++++++------- 8 files changed, 107 insertions(+), 35 deletions(-) diff --git a/lib/document.js b/lib/document.js index e3654fe9247..2a50d50ccb9 100644 --- a/lib/document.js +++ b/lib/document.js @@ -65,7 +65,12 @@ function Document(obj, fields, skipId, skipHooks) { if (obj instanceof Document) { this.isNew = obj.isNew; } - this.set(obj, undefined, true); + // Skip set hooks + if (this.$__original_set) { + this.$__original_set(obj, undefined, true); + } else { + this.set(obj, undefined, true); + } } if (!schema.options.strict && obj) { @@ -81,6 +86,8 @@ function Document(obj, fields, skipId, skipHooks) { if (!skipHooks) { this.$__registerHooksFromSchema(); + } else { + applyQueue(this); } } @@ -1302,6 +1309,7 @@ Document.prototype.$__validate = function(callback) { var err = _this.$__.validationError; _this.$__.validationError = undefined; _this.emit('validate', _this); + _this.constructor.emit('validate', _this); if (err) { for (var key in err.errors) { // Make sure cast errors persist @@ -1441,6 +1449,7 @@ Document.prototype.validateSync = function(pathsToValidate) { var err = _this.$__.validationError; _this.$__.validationError = undefined; _this.emit('validate', _this); + _this.constructor.emit('validate', _this); if (err) { for (var key in err.errors) { @@ -1883,6 +1892,25 @@ Document.prototype.$__getAllSubdocs = function() { return subDocs; }; +/*! + * Runs queued functions + */ + +function applyQueue(doc) { + var q = doc.schema && doc.schema.callQueue; + if (!q.length) { + return; + } + var pair; + + for (i = 0; i < q.length; ++i) { + pair = q[i]; + if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') { + doc[pair[0]].apply(doc, pair[1]); + } + } +} + /** * Executes methods queued from the Schema definition * diff --git a/lib/model.js b/lib/model.js index 93c1608a2d6..106a418e251 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3336,6 +3336,7 @@ function applyHooks(model, schema) { var j; var pointCut; var keys; + var newName; if (!q.length) { return; } @@ -3370,12 +3371,29 @@ function applyHooks(model, schema) { }); delete toWrap.post; + if (toWrap.set) { + // Set hooks also need to be sync re: gh-3479 + newName = '$__original_set'; + model.prototype[newName] = model.prototype.set; + if (toWrap.set.pre) { + toWrap.set.pre.forEach(function(args) { + model.prototype.$pre.apply(model.prototype, args); + }); + } + if (toWrap.set.post) { + toWrap.set.post.forEach(function(args) { + model.prototype.$post.apply(model.prototype, args); + }); + } + delete toWrap.set; + } + keys = Object.keys(toWrap); len = keys.length; for (i = 0; i < len; ++i) { pointCut = keys[i]; // this is so we can wrap everything into a promise; - var newName = ('$__original_' + pointCut); + newName = ('$__original_' + pointCut); if (!model.prototype[pointCut]) { return; } diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index f66437ff997..26305163b0e 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -4,6 +4,7 @@ * Module dependencies. */ +var EventEmitter = require('events').EventEmitter; var SchemaType = require('../schematype'); var Subdocument = require('../types/subdocument'); var castToNumber = require('./operators/helpers').castToNumber; @@ -22,7 +23,7 @@ module.exports = Embedded; */ function Embedded(schema, path, options) { - var _embedded = function(value, path, parent) { + var _embedded = function SingleNested(value, path, parent) { var _this = this; Subdocument.apply(this, arguments); this.$parent = parent; @@ -39,6 +40,7 @@ function Embedded(schema, path, options) { }; _embedded.prototype = Object.create(Subdocument.prototype); _embedded.prototype.$__setSchema(schema); + _embedded.prototype.constructor = _embedded; _embedded.schema = schema; _embedded.$isSingleNested = true; _embedded.prototype.$basePath = path; @@ -60,6 +62,10 @@ function Embedded(schema, path, options) { _embedded[i] = schema.statics[i]; } + for (var i in EventEmitter.prototype) { + _embedded[i] = EventEmitter.prototype[i]; + } + this.caster = _embedded; this.schema = schema; this.$isSingleNested = true; diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 6a2c3041411..d45b94e1356 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -5,6 +5,7 @@ */ var Document = require('../document_provider')(); +var EventEmitter = require('events').EventEmitter; var PromiseProvider = require('../promise_provider'); /** @@ -41,6 +42,10 @@ function EmbeddedDocument(obj, parentArr, skipId, fields, index) { EmbeddedDocument.prototype = Object.create(Document.prototype); EmbeddedDocument.prototype.constructor = EmbeddedDocument; +for (var i in EventEmitter.prototype) { + EmbeddedDocument[i] = EventEmitter.prototype[i]; +} + EmbeddedDocument.prototype.toBSON = function() { return this.toObject({ transform: false, virtuals: false }); }; diff --git a/test/document.isselected.test.js b/test/document.isselected.test.js index 4e6b8513b5e..3573c29cf65 100644 --- a/test/document.isselected.test.js +++ b/test/document.isselected.test.js @@ -2,13 +2,14 @@ * Module dependencies. */ -var start = require('./common'), - mongoose = start.mongoose, - assert = require('power-assert'), - Schema = mongoose.Schema, - ObjectId = Schema.ObjectId, - Document = require('../lib/document'), - DocumentObjectId = mongoose.Types.ObjectId; +var start = require('./common'); +var mongoose = start.mongoose; +var assert = require('power-assert'); +var EventEmitter = require('events').EventEmitter; +var Schema = mongoose.Schema; +var ObjectId = Schema.ObjectId; +var Document = require('../lib/document'); +var DocumentObjectId = mongoose.Types.ObjectId; /** * Test Document constructor. @@ -24,6 +25,10 @@ function TestDocument() { TestDocument.prototype.__proto__ = Document.prototype; +for (var i in EventEmitter.prototype) { + TestDocument[i] = EventEmitter.prototype[i]; +} + /** * Set a dummy schema to simulate compilation. */ diff --git a/test/document.test.js b/test/document.test.js index d5998a280d3..fbe089e5747 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -10,6 +10,7 @@ var Schema = mongoose.Schema; var ObjectId = Schema.ObjectId; var Document = require('../lib/document'); var DocumentObjectId = mongoose.Types.ObjectId; +var EventEmitter = require('events').EventEmitter; var SchemaType = mongoose.SchemaType; var ValidatorError = SchemaType.ValidatorError; var ValidationError = mongoose.Document.ValidationError; @@ -34,6 +35,10 @@ function TestDocument() { TestDocument.prototype.__proto__ = Document.prototype; +for (var i in EventEmitter.prototype) { + TestDocument[i] = EventEmitter.prototype[i]; +} + /** * Set a dummy schema to simulate compilation. */ diff --git a/test/model.populate.test.js b/test/model.populate.test.js index f1c386e96bb..434ac356b61 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3671,29 +3671,29 @@ describe('model: populate:', function() { async.series( [ - u1.save, - u2.save, - u3.save, + u1.save.bind(u1), + u2.save.bind(u2), + u3.save.bind(u3), - c1.save, - c2.save, - c3.save, + c1.save.bind(c1), + c2.save.bind(c2), + c3.save.bind(c3), - b1.save, - b2.save, - b3.save, + b1.save.bind(b1), + b2.save.bind(b2), + b3.save.bind(b3), - ce1.save, - ue1.save, - be1.save, + ce1.save.bind(ce1), + ue1.save.bind(ue1), + be1.save.bind(be1), - ce2.save, - ue2.save, - be2.save, + ce2.save.bind(ce2), + ue2.save.bind(ue2), + be2.save.bind(be2), - ce3.save, - ue3.save, - be3.save, + ce3.save.bind(ce3), + ue3.save.bind(ue3), + be3.save.bind(be3), function(next) { Event. diff --git a/test/types.document.test.js b/test/types.document.test.js index 1f5663867bb..0541d0390c6 100644 --- a/test/types.document.test.js +++ b/test/types.document.test.js @@ -3,13 +3,14 @@ * Module dependencies. */ -var assert = require('power-assert'), - start = require('./common'), - mongoose = start.mongoose, - EmbeddedDocument = require('../lib/types/embedded'), - DocumentArray = require('../lib/types/documentarray'), - Schema = mongoose.Schema, - ValidationError = mongoose.Document.ValidationError; +var assert = require('power-assert'); +var start = require('./common'); +var mongoose = start.mongoose; +var EmbeddedDocument = require('../lib/types/embedded'); +var EventEmitter = require('events').EventEmitter; +var DocumentArray = require('../lib/types/documentarray'); +var Schema = mongoose.Schema; +var ValidationError = mongoose.Document.ValidationError; /** * Setup. @@ -35,6 +36,10 @@ function Subdocument() { Subdocument.prototype.__proto__ = EmbeddedDocument.prototype; +for (var i in EventEmitter.prototype) { + Subdocument[i] = EventEmitter.prototype[i]; +} + /** * Set schema. */ From 315ac0690279416c3af2509a5da9562ca9096c0f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 Jan 2017 11:49:47 -0700 Subject: [PATCH 1117/2240] refactor: move applyHooks out of model --- lib/document.js | 2 +- lib/model.js | 187 +++---------------------------- lib/schema/embedded.js | 2 +- lib/services/model/applyHooks.js | 160 ++++++++++++++++++++++++++ 4 files changed, 177 insertions(+), 174 deletions(-) create mode 100644 lib/services/model/applyHooks.js diff --git a/lib/document.js b/lib/document.js index 2a50d50ccb9..1f61ec0303d 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1903,7 +1903,7 @@ function applyQueue(doc) { } var pair; - for (i = 0; i < q.length; ++i) { + for (var i = 0; i < q.length; ++i) { pair = q[i]; if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') { doc[pair[0]].apply(doc, pair[1]); diff --git a/lib/model.js b/lib/model.js index 106a418e251..f27443fc44b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2,23 +2,19 @@ * Module dependencies. */ +var Aggregate = require('./aggregate'); var Document = require('./document'); -var MongooseError = require('./error'); -var VersionError = MongooseError.VersionError; -var DivergentArrayError = MongooseError.DivergentArrayError; +var DivergentArrayError = require('./error').DivergentArrayError; +var EventEmitter = require('events').EventEmitter; +var OverwriteModelError = require('./error').OverwriteModelError; +var PromiseProvider = require('./promise_provider'); var Query = require('./query'); -var Aggregate = require('./aggregate'); var Schema = require('./schema'); -var utils = require('./utils'); -var hasOwnProperty = utils.object.hasOwnProperty; -var isMongooseObject = utils.isMongooseObject; -var EventEmitter = require('events').EventEmitter; -var util = require('util'); -var tick = utils.tick; - +var VersionError = require('./error').VersionError; +var applyHooks = require('./services/model/applyHooks'); var parallel = require('async/parallel'); -var PromiseProvider = require('./promise_provider'); -var Embedded; +var util = require('util'); +var utils = require('./utils'); var VERSION_WHERE = 1, VERSION_INC = 2, @@ -411,7 +407,7 @@ function handleAtomics(self, where, delta, data, value) { if (i === 0) { // $set - if (isMongooseObject(value)) { + if (utils.isMongooseObject(value)) { value = value.toObject({depopulate: 1, _isNested: true}); } else if (value.valueOf) { value = value.valueOf(); @@ -421,7 +417,7 @@ function handleAtomics(self, where, delta, data, value) { } function iter(mem) { - return isMongooseObject(mem) + return utils.isMongooseObject(mem) ? mem.toObject({depopulate: 1, _isNested: true}) : mem; } @@ -430,7 +426,7 @@ function handleAtomics(self, where, delta, data, value) { op = ops[i]; val = atomics[op]; - if (isMongooseObject(val)) { + if (utils.isMongooseObject(val)) { val = val.toObject({depopulate: true, transform: false, _isNested: true}); } else if (Array.isArray(val)) { val = val.map(iter); @@ -565,7 +561,7 @@ function checkDivergentArray(doc, path, array) { // would be similarily destructive as we never received all // elements of the array and potentially would overwrite data. var check = pop.options.match || - pop.options.options && hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted + pop.options.options && utils.object.hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted pop.options.options && pop.options.options.skip || // 0 is permitted pop.options.select && // deselected _id? (pop.options.select._id === 0 || @@ -884,7 +880,7 @@ Model.discriminator = function discriminator(name, schema) { throw new Error('Discriminator with name "' + name + '" already exists'); } if (this.db.models[name]) { - throw new MongooseError.OverwriteModelError(name); + throw new OverwriteModelError(name); } this.discriminators[name] = this.db.model(name, schema, this.collection.name); @@ -1022,7 +1018,7 @@ function _ensureIndexes(model, options, callback) { indexSingleStart(indexFields, options); - model.collection.ensureIndex(indexFields, options, tick(function(err, name) { + model.collection.ensureIndex(indexFields, options, utils.tick(function(err, name) { indexSingleDone(err, indexFields, options, name); if (err) { return done(err); @@ -3318,159 +3314,6 @@ Model.compile = function compile(name, schema, collectionName, connection, base) return model; }; -/*! - * Register hooks for this model - * - * @param {Model} model - * @param {Schema} schema - */ - -function applyHooks(model, schema) { - Embedded = Embedded || require('./types/embedded'); - var Promise = PromiseProvider.get(); - - var q = schema && schema.callQueue; - var toWrapEl; - var len; - var i; - var j; - var pointCut; - var keys; - var newName; - if (!q.length) { - return; - } - - // we are only interested in 'pre' hooks, and group by point-cut - var toWrap = { post: [] }; - var pair; - - for (i = 0; i < q.length; ++i) { - pair = q[i]; - if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') { - continue; - } - var args = [].slice.call(pair[1]); - pointCut = pair[0] === 'on' ? 'post' : args[0]; - if (!(pointCut in toWrap)) { - toWrap[pointCut] = {post: [], pre: []}; - } - if (pair[0] === 'post') { - toWrap[pointCut].post.push(args); - } else if (pair[0] === 'on') { - toWrap[pointCut].push(args); - } else { - toWrap[pointCut].pre.push(args); - } - } - - // 'post' hooks are simpler - len = toWrap.post.length; - toWrap.post.forEach(function(args) { - model.on.apply(model, args); - }); - delete toWrap.post; - - if (toWrap.set) { - // Set hooks also need to be sync re: gh-3479 - newName = '$__original_set'; - model.prototype[newName] = model.prototype.set; - if (toWrap.set.pre) { - toWrap.set.pre.forEach(function(args) { - model.prototype.$pre.apply(model.prototype, args); - }); - } - if (toWrap.set.post) { - toWrap.set.post.forEach(function(args) { - model.prototype.$post.apply(model.prototype, args); - }); - } - delete toWrap.set; - } - - keys = Object.keys(toWrap); - len = keys.length; - for (i = 0; i < len; ++i) { - pointCut = keys[i]; - // this is so we can wrap everything into a promise; - newName = ('$__original_' + pointCut); - if (!model.prototype[pointCut]) { - return; - } - model.prototype[newName] = model.prototype[pointCut]; - model.prototype[pointCut] = (function(_newName) { - return function wrappedPointCut() { - var _this = this; - var args = [].slice.call(arguments); - var lastArg = args.pop(); - var fn; - var originalError = new Error(); - var $results; - if (lastArg && typeof lastArg !== 'function') { - args.push(lastArg); - } else { - fn = lastArg; - } - - var promise = new Promise.ES6(function(resolve, reject) { - args.push(function(error) { - if (error) { - // gh-2633: since VersionError is very generic, take the - // stack trace of the original save() function call rather - // than the async trace - if (error instanceof VersionError) { - error.stack = originalError.stack; - } - _this.$__handleReject(error); - reject(error); - return; - } - - // There may be multiple results and promise libs other than - // mpromise don't support passing multiple values to `resolve()` - $results = Array.prototype.slice.call(arguments, 1); - resolve.apply(promise, $results); - }); - - _this[_newName].apply(_this, args); - }); - if (fn) { - if (this.constructor.$wrapCallback) { - fn = this.constructor.$wrapCallback(fn); - } - return promise.then( - function() { - process.nextTick(function() { - fn.apply(null, [null].concat($results)); - }); - }, - function(error) { - process.nextTick(function() { - fn(error); - }); - }); - } - return promise; - }; - })(newName); - - toWrapEl = toWrap[pointCut]; - var _len = toWrapEl.pre.length; - for (j = 0; j < _len; ++j) { - args = toWrapEl.pre[j]; - args[0] = newName; - model.prototype.$pre.apply(model.prototype, args); - } - - _len = toWrapEl.post.length; - for (j = 0; j < _len; ++j) { - args = toWrapEl.post[j]; - args[0] = newName; - model.prototype.$post.apply(model.prototype, args); - } - } -} - /*! * Register methods for this model * diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 26305163b0e..aa6b9592fde 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -62,7 +62,7 @@ function Embedded(schema, path, options) { _embedded[i] = schema.statics[i]; } - for (var i in EventEmitter.prototype) { + for (i in EventEmitter.prototype) { _embedded[i] = EventEmitter.prototype[i]; } diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js new file mode 100644 index 00000000000..16452a16db4 --- /dev/null +++ b/lib/services/model/applyHooks.js @@ -0,0 +1,160 @@ +'use strict'; + +var Embedded = require('../../types/embedded'); +var PromiseProvider = require('../../promise_provider'); +var VersionError = require('../../error').VersionError; + +module.exports = applyHooks; + +/*! + * Register hooks for this model + * + * @param {Model} model + * @param {Schema} schema + */ + +function applyHooks(model, schema) { + Embedded = Embedded || require('./types/embedded'); + var Promise = PromiseProvider.get(); + + var q = schema && schema.callQueue; + var toWrapEl; + var len; + var i; + var j; + var pointCut; + var keys; + var newName; + if (!q.length) { + return; + } + + // we are only interested in 'pre' hooks, and group by point-cut + var toWrap = { post: [] }; + var pair; + + for (i = 0; i < q.length; ++i) { + pair = q[i]; + if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') { + continue; + } + var args = [].slice.call(pair[1]); + pointCut = pair[0] === 'on' ? 'post' : args[0]; + if (!(pointCut in toWrap)) { + toWrap[pointCut] = {post: [], pre: []}; + } + if (pair[0] === 'post') { + toWrap[pointCut].post.push(args); + } else if (pair[0] === 'on') { + toWrap[pointCut].push(args); + } else { + toWrap[pointCut].pre.push(args); + } + } + + // 'post' hooks are simpler + len = toWrap.post.length; + toWrap.post.forEach(function(args) { + model.on.apply(model, args); + }); + delete toWrap.post; + + if (toWrap.set) { + // Set hooks also need to be sync re: gh-3479 + newName = '$__original_set'; + model.prototype[newName] = model.prototype.set; + if (toWrap.set.pre) { + toWrap.set.pre.forEach(function(args) { + model.prototype.$pre.apply(model.prototype, args); + }); + } + if (toWrap.set.post) { + toWrap.set.post.forEach(function(args) { + model.prototype.$post.apply(model.prototype, args); + }); + } + delete toWrap.set; + } + + keys = Object.keys(toWrap); + len = keys.length; + for (i = 0; i < len; ++i) { + pointCut = keys[i]; + // this is so we can wrap everything into a promise; + newName = ('$__original_' + pointCut); + if (!model.prototype[pointCut]) { + return; + } + model.prototype[newName] = model.prototype[pointCut]; + model.prototype[pointCut] = (function(_newName) { + return function wrappedPointCut() { + var _this = this; + var args = [].slice.call(arguments); + var lastArg = args.pop(); + var fn; + var originalError = new Error(); + var $results; + if (lastArg && typeof lastArg !== 'function') { + args.push(lastArg); + } else { + fn = lastArg; + } + + var promise = new Promise.ES6(function(resolve, reject) { + args.push(function(error) { + if (error) { + // gh-2633: since VersionError is very generic, take the + // stack trace of the original save() function call rather + // than the async trace + if (error instanceof VersionError) { + error.stack = originalError.stack; + } + _this.$__handleReject(error); + reject(error); + return; + } + + // There may be multiple results and promise libs other than + // mpromise don't support passing multiple values to `resolve()` + $results = Array.prototype.slice.call(arguments, 1); + resolve.apply(promise, $results); + }); + + _this[_newName].apply(_this, args); + }); + if (fn) { + if (this.constructor.$wrapCallback) { + fn = this.constructor.$wrapCallback(fn); + } + return promise.then( + function() { + process.nextTick(function() { + fn.apply(null, [null].concat($results)); + }); + }, + function(error) { + process.nextTick(function() { + fn(error); + }); + }); + } + return promise; + }; + })(newName); + + toWrapEl = toWrap[pointCut]; + var _len = toWrapEl.pre.length; + for (j = 0; j < _len; ++j) { + args = toWrapEl.pre[j]; + args[0] = newName; + model.prototype.$pre.apply(model.prototype, args); + } + + _len = toWrapEl.post.length; + for (j = 0; j < _len; ++j) { + args = toWrapEl.post[j]; + args[0] = newName; + model.prototype.$post.apply(model.prototype, args); + } + } +} From b75c2c9bb4940acb681d318fd3c144cebb2032b1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 Jan 2017 12:16:57 -0700 Subject: [PATCH 1118/2240] refactor: wip on using applyHooks for subdocs Re: #2754 --- lib/document.js | 6 +----- lib/schema/documentarray.js | 9 +++++++++ lib/schema/embedded.js | 5 +++++ lib/types/embedded.js | 2 ++ lib/types/subdocument.js | 1 + test/document.hooks.test.js | 13 +++++++------ 6 files changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/document.js b/lib/document.js index 1f61ec0303d..51fa6315a85 100644 --- a/lib/document.js +++ b/lib/document.js @@ -84,11 +84,7 @@ function Document(obj, fields, skipId, skipHooks) { }); } - if (!skipHooks) { - this.$__registerHooksFromSchema(); - } else { - applyQueue(this); - } + applyQueue(this); } /*! diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 70a16e4a1f6..cf7c431c0b4 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -6,9 +6,11 @@ var ArrayType = require('./array'); var CastError = require('../error/cast'); +var EventEmitter = require('events').EventEmitter; var MongooseDocumentArray = require('../types/documentarray'); var SchemaType = require('../schematype'); var Subdocument = require('../types/embedded'); +var applyHooks = require('../services/model/applyHooks'); var util = require('util'); /** @@ -30,6 +32,7 @@ function DocumentArray(key, schema, options) { EmbeddedDocument.prototype = Object.create(Subdocument.prototype); EmbeddedDocument.prototype.$__setSchema(schema); EmbeddedDocument.schema = schema; + EmbeddedDocument.prototype.constructor = EmbeddedDocument; // apply methods for (var i in schema.methods) { @@ -41,6 +44,12 @@ function DocumentArray(key, schema, options) { EmbeddedDocument[i] = schema.statics[i]; } + for (i in EventEmitter.prototype) { + EmbeddedDocument[i] = EventEmitter.prototype[i]; + } + + applyHooks(EmbeddedDocument, schema); + EmbeddedDocument.options = options; ArrayType.call(this, key, EmbeddedDocument, options); diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index aa6b9592fde..911900978ac 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -7,6 +7,7 @@ var EventEmitter = require('events').EventEmitter; var SchemaType = require('../schematype'); var Subdocument = require('../types/subdocument'); +var applyHooks = require('../services/model/applyHooks'); var castToNumber = require('./operators/helpers').castToNumber; var geospatial = require('./operators/geospatial'); @@ -30,11 +31,13 @@ function Embedded(schema, path, options) { if (parent) { parent.on('save', function() { _this.emit('save', _this); + _this.constructor.emit('save', _this); }); parent.on('isNew', function(val) { _this.isNew = val; _this.emit('isNew', val); + _this.constructor.emit('isNew', val); }); } }; @@ -66,6 +69,8 @@ function Embedded(schema, path, options) { _embedded[i] = EventEmitter.prototype[i]; } + applyHooks(_embedded, schema); + this.caster = _embedded; this.schema = schema; this.$isSingleNested = true; diff --git a/lib/types/embedded.js b/lib/types/embedded.js index d45b94e1356..2ce3dbdad0c 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -122,9 +122,11 @@ function registerRemoveListener(sub) { var owner = sub.ownerDocument(); function emitRemove() { + console.log('Emitting remove', sub, sub.constructor); owner.removeListener('save', emitRemove); owner.removeListener('remove', emitRemove); sub.emit('remove', sub); + sub.constructor.emit('remove', sub); owner = sub = null; } diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 0fef2dca35f..42cb50cf780 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -145,6 +145,7 @@ function registerRemoveListener(sub) { owner.removeListener('save', emitRemove); owner.removeListener('remove', emitRemove); sub.emit('remove', sub); + sub.constructor.emit('remove', sub); owner = sub = null; } diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js index 633a7386cea..d2e98fa431b 100644 --- a/test/document.hooks.test.js +++ b/test/document.hooks.test.js @@ -342,6 +342,7 @@ describe('document: hooks:', function() { }); it('post remove hooks on subdocuments work', function(done) { + console.log('------------'); var db = start(); var sub = new Schema({_id: Number}); var called = {pre: 0, post: 0}; @@ -768,6 +769,12 @@ describe('document: hooks:', function() { title: String }); + var calls = 0; + L3Schema.pre('save', function(next) { + ++calls; + return next(); + }); + var L2Schema = new Schema({ items: [L3Schema] }); @@ -776,12 +783,6 @@ describe('document: hooks:', function() { items: [L2Schema] }); - var calls = 0; - L3Schema.pre('save', function(next) { - ++calls; - return next(); - }); - var db = start(); var L1 = db.model('gh3281', L1Schema); From d7a2dc543bba2a6458d9445c3fe6222fbf79ab2e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 Jan 2017 16:40:25 -0700 Subject: [PATCH 1119/2240] refactor: use applyHooks for subdocs in node Re: #2754 --- lib/document.js | 2 +- lib/schema/documentarray.js | 1 + lib/services/model/applyHooks.js | 16 ++++++++++++++-- lib/types/embedded.js | 4 +++- test/document.hooks.test.js | 1 - test/model.test.js | 19 +++++-------------- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/lib/document.js b/lib/document.js index 51fa6315a85..1b70e041210 100644 --- a/lib/document.js +++ b/lib/document.js @@ -37,7 +37,7 @@ var mpath = require('mpath'); * @api private */ -function Document(obj, fields, skipId, skipHooks) { +function Document(obj, fields, skipId) { this.$__ = new InternalCache; this.$__.emitter = new EventEmitter(); this.isNew = true; diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index cf7c431c0b4..aa08d4e8f96 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -33,6 +33,7 @@ function DocumentArray(key, schema, options) { EmbeddedDocument.prototype.$__setSchema(schema); EmbeddedDocument.schema = schema; EmbeddedDocument.prototype.constructor = EmbeddedDocument; + EmbeddedDocument.$isArraySubdocument = true; // apply methods for (var i in schema.methods) { diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index 16452a16db4..c6fd2eb6880 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -1,6 +1,5 @@ 'use strict'; -var Embedded = require('../../types/embedded'); var PromiseProvider = require('../../promise_provider'); var VersionError = require('../../error').VersionError; @@ -14,7 +13,6 @@ module.exports = applyHooks; */ function applyHooks(model, schema) { - Embedded = Embedded || require('./types/embedded'); var Promise = PromiseProvider.get(); var q = schema && schema.callQueue; @@ -59,6 +57,20 @@ function applyHooks(model, schema) { }); delete toWrap.post; + // 'init' should be synchronous on subdocuments + if (toWrap.init && (model.$isSingleNested || model.$isArraySubdocument)) { + if (toWrap.init.pre) { + toWrap.init.pre.forEach(function(args) { + model.prototype.$pre.apply(model.prototype, args); + }); + } + if (toWrap.init.post) { + toWrap.init.post.forEach(function(args) { + model.prototype.$post.apply(model.prototype, args); + }); + } + delete toWrap.init; + } if (toWrap.set) { // Set hooks also need to be sync re: gh-3479 newName = '$__original_set'; diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 2ce3dbdad0c..0f5fe1ba4a5 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -104,9 +104,12 @@ EmbeddedDocument.prototype.populate = function() { EmbeddedDocument.prototype.save = function(fn) { var Promise = PromiseProvider.get(); + var _this = this; return new Promise.ES6(function(resolve) { fn && fn(); resolve(); + _this.emit('save', _this); + _this.constructor.emit('save', _this); }); }; @@ -122,7 +125,6 @@ function registerRemoveListener(sub) { var owner = sub.ownerDocument(); function emitRemove() { - console.log('Emitting remove', sub, sub.constructor); owner.removeListener('save', emitRemove); owner.removeListener('remove', emitRemove); sub.emit('remove', sub); diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js index d2e98fa431b..3b37aefd711 100644 --- a/test/document.hooks.test.js +++ b/test/document.hooks.test.js @@ -342,7 +342,6 @@ describe('document: hooks:', function() { }); it('post remove hooks on subdocuments work', function(done) { - console.log('------------'); var db = start(); var sub = new Schema({_id: Number}); var called = {pre: 0, post: 0}; diff --git a/test/model.test.js b/test/model.test.js index 41b2c004f00..fbefb7bcbc8 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -3851,27 +3851,18 @@ describe('Model', function() { title: String }); - var ParentSchema = new Schema({ - embeds: [EmbeddedSchema] - }); - EmbeddedSchema.post('save', function() { save = true; }); - // Don't know how to test those on a embedded document. - // EmbeddedSchema.post('init', function () { - // init = true; - // }); - - // EmbeddedSchema.post('remove', function () { - // remove = true; - // }); + var ParentSchema = new Schema({ + embeds: [EmbeddedSchema] + }); mongoose.model('Parent', ParentSchema); - var db = start(), - Parent = db.model('Parent'); + var db = start(); + var Parent = db.model('Parent'); var parent = new Parent(); From faf2c6ad8c83802ea47200cfa04fb4ebbec72405 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 Jan 2017 23:42:53 -0700 Subject: [PATCH 1120/2240] chore: release 4.7.6 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0a9fdf993f1..de774635bfc 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.7.6 / 2017-01-02 +================== + * fix(model): allow passing non-array to insertMany #4846 + * fix(populate): use base model name if no discriminator for backwards compat #4843 + * fix: allow internal validate callback to be optional #4842 [arciisine](https://github.com/arciisine) + * fix(document): don't skip pointCut if save not defined (like in browser doc) #4841 + * chore: improve benchmarks #4838 [billouboq](https://github.com/billouboq) + * perf: remove some unused parameters #4837 [billouboq](https://github.com/billouboq) + * fix(query): don't call error handler if passRawResult is true and no error occurred #4836 + 4.7.5 / 2016-12-26 ================== * docs(model): fix spelling mistake #4828 [paulinoj](https://github.com/paulinoj) diff --git a/package.json b/package.json index ca8ae475d60..26b705fd569 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.6-pre", + "version": "4.7.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 32208badad7c94da8848cb19d6a5ef5c0498c688 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Jan 2017 19:16:21 -0700 Subject: [PATCH 1121/2240] chore: now working on 4.7.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 26b705fd569..13cb64eec68 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.6", + "version": "4.7.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 2c020d120221e57007b06572a77b79c9d7dc6d1e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Jan 2017 20:03:30 -0700 Subject: [PATCH 1122/2240] chore: improve spelling re: #4858 --- lib/schematype.js | 1 + test/document.hooks.test.js | 2 +- test/document.test.js | 2 +- test/model.create.test.js | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/schematype.js b/lib/schematype.js index 3ca3423618b..a245a88a355 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -726,6 +726,7 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { return; } if (validator.length === 2) { + console.log('GZ', scope); var returnVal = validator.call(scope, value, function(ok, customMsg) { if (typeof returnVal === 'boolean') { return; diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js index 633a7386cea..82e9dacee97 100644 --- a/test/document.hooks.test.js +++ b/test/document.hooks.test.js @@ -485,7 +485,7 @@ describe('document: hooks:', function() { it('pre save hooks should run in parallel', function(done) { // we set the time out to be double that of the validator - 1 - // (so that running in serial will be greater then that) + // (so that running in serial will be greater than that) this.timeout(1000); var db = start(), count = 0; diff --git a/test/document.test.js b/test/document.test.js index d5998a280d3..e454266dea0 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -1373,7 +1373,7 @@ describe('document', function() { it('validator should run in parallel', function(done) { - // we set the time out to be double that of the validator - 1 (so that running in serial will be greater then that) + // we set the time out to be double that of the validator - 1 (so that running in serial will be greater than that) this.timeout(1000); var db = start(); var count = 0; diff --git a/test/model.create.test.js b/test/model.create.test.js index 256b14424ee..05acc313634 100644 --- a/test/model.create.test.js +++ b/test/model.create.test.js @@ -99,7 +99,7 @@ describe('model', function() { }); it('creates in parallel', function(done) { - // we set the time out to be double that of the validator - 1 (so that running in serial will be greater then that) + // we set the time out to be double that of the validator - 1 (so that running in serial will be greater than that) this.timeout(1000); var db = start(), countPre = 0, From 78b4477d08eb75bb7285047d0ee43e652946e345 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Jan 2017 22:22:32 -0700 Subject: [PATCH 1123/2240] chore: deprecate $__registerHooksFromSchema --- lib/browserDocument.js | 4 ++-- lib/document.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/browserDocument.js b/lib/browserDocument.js index 6c87d199629..f3ad129ec8c 100644 --- a/lib/browserDocument.js +++ b/lib/browserDocument.js @@ -56,8 +56,6 @@ function Document(obj, schema, fields, skipId, skipInit) { this.isNew = true; this.errors = undefined; - // var schema = this.schema; - if (typeof fields === 'boolean') { this.$__.strictMode = fields; fields = undefined; @@ -93,11 +91,13 @@ function Document(obj, schema, fields, skipId, skipInit) { /*! * Inherit from the NodeJS document */ + Document.prototype = Object.create(NodeJSDocument.prototype); Document.prototype.constructor = Document; /*! * Module exports. */ + Document.ValidationError = ValidationError; module.exports = exports = Document; diff --git a/lib/document.js b/lib/document.js index 1b70e041210..d335df2171c 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1907,11 +1907,12 @@ function applyQueue(doc) { } } -/** +/*! * Executes methods queued from the Schema definition * * @api private * @method $__registerHooksFromSchema + * @deprecated * @memberOf Document */ From ec63cd10c86acf758cbcd8325f6b7bc7878a6dca Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Jan 2017 22:27:13 -0700 Subject: [PATCH 1124/2240] refactor: move $__registerHooksFromSchema into browser doc Fix #2754 --- lib/browserDocument.js | 188 +++++++++++++++++++++++++++++++++++++++-- lib/document.js | 169 ------------------------------------ 2 files changed, 180 insertions(+), 177 deletions(-) diff --git a/lib/browserDocument.js b/lib/browserDocument.js index f3ad129ec8c..acf903afcca 100644 --- a/lib/browserDocument.js +++ b/lib/browserDocument.js @@ -2,14 +2,18 @@ * Module dependencies. */ -var NodeJSDocument = require('./document'), - EventEmitter = require('events').EventEmitter, - MongooseError = require('./error'), - Schema = require('./schema'), - ObjectId = require('./types/objectid'), - utils = require('./utils'), - ValidationError = MongooseError.ValidationError, - InternalCache = require('./internal'); +var NodeJSDocument = require('./document'); +var EventEmitter = require('events').EventEmitter; +var MongooseError = require('./error'); +var Schema = require('./schema'); +var ObjectId = require('./types/objectid'); +var utils = require('./utils'); +var ValidationError = MongooseError.ValidationError; +var InternalCache = require('./internal'); +var PromiseProvider = require('./promise_provider'); +var VersionError = require('./error').VersionError; + +var Embedded; /** * Document constructor. @@ -95,6 +99,174 @@ function Document(obj, schema, fields, skipId, skipInit) { Document.prototype = Object.create(NodeJSDocument.prototype); Document.prototype.constructor = Document; +/*! + * Executes methods queued from the Schema definition + * + * @api private + * @method $__registerHooksFromSchema + * @deprecated + * @memberOf Document + */ + +Document.prototype.$__registerHooksFromSchema = function() { + Embedded = Embedded || require('./types/embedded'); + var Promise = PromiseProvider.get(); + + var _this = this; + var q = _this.schema && _this.schema.callQueue; + var toWrapEl; + var len; + var i; + var j; + var pointCut; + var keys; + if (!q.length) { + return _this; + } + + // we are only interested in 'pre' hooks, and group by point-cut + var toWrap = { post: [] }; + var pair; + + for (i = 0; i < q.length; ++i) { + pair = q[i]; + if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') { + _this[pair[0]].apply(_this, pair[1]); + continue; + } + var args = [].slice.call(pair[1]); + pointCut = pair[0] === 'on' ? 'post' : args[0]; + if (!(pointCut in toWrap)) { + toWrap[pointCut] = {post: [], pre: []}; + } + if (pair[0] === 'post') { + toWrap[pointCut].post.push(args); + } else if (pair[0] === 'on') { + toWrap[pointCut].push(args); + } else { + toWrap[pointCut].pre.push(args); + } + } + + // 'post' hooks are simpler + len = toWrap.post.length; + toWrap.post.forEach(function(args) { + _this.on.apply(_this, args); + }); + delete toWrap.post; + + // 'init' should be synchronous on subdocuments + if (toWrap.init && _this instanceof Embedded) { + if (toWrap.init.pre) { + toWrap.init.pre.forEach(function(args) { + _this.$pre.apply(_this, args); + }); + } + if (toWrap.init.post) { + toWrap.init.post.forEach(function(args) { + _this.$post.apply(_this, args); + }); + } + delete toWrap.init; + } else if (toWrap.set) { + // Set hooks also need to be sync re: gh-3479 + if (toWrap.set.pre) { + toWrap.set.pre.forEach(function(args) { + _this.$pre.apply(_this, args); + }); + } + if (toWrap.set.post) { + toWrap.set.post.forEach(function(args) { + _this.$post.apply(_this, args); + }); + } + delete toWrap.set; + } + + keys = Object.keys(toWrap); + len = keys.length; + for (i = 0; i < len; ++i) { + pointCut = keys[i]; + // this is so we can wrap everything into a promise; + var newName = ('$__original_' + pointCut); + if (!_this[pointCut]) { + continue; + } + _this[newName] = _this[pointCut]; + _this[pointCut] = (function(_newName) { + return function wrappedPointCut() { + var args = [].slice.call(arguments); + var lastArg = args.pop(); + var fn; + var originalError = new Error(); + var $results; + if (lastArg && typeof lastArg !== 'function') { + args.push(lastArg); + } else { + fn = lastArg; + } + + var promise = new Promise.ES6(function(resolve, reject) { + args.push(function(error) { + if (error) { + // gh-2633: since VersionError is very generic, take the + // stack trace of the original save() function call rather + // than the async trace + if (error instanceof VersionError) { + error.stack = originalError.stack; + } + _this.$__handleReject(error); + reject(error); + return; + } + + // There may be multiple results and promise libs other than + // mpromise don't support passing multiple values to `resolve()` + $results = Array.prototype.slice.call(arguments, 1); + resolve.apply(promise, $results); + }); + + _this[_newName].apply(_this, args); + }); + if (fn) { + if (_this.constructor.$wrapCallback) { + fn = _this.constructor.$wrapCallback(fn); + } + return promise.then( + function() { + process.nextTick(function() { + fn.apply(null, [null].concat($results)); + }); + }, + function(error) { + process.nextTick(function() { + fn(error); + }); + }); + } + return promise; + }; + })(newName); + + toWrapEl = toWrap[pointCut]; + var _len = toWrapEl.pre.length; + args; + for (j = 0; j < _len; ++j) { + args = toWrapEl.pre[j]; + args[0] = newName; + _this.$pre.apply(_this, args); + } + + _len = toWrapEl.post.length; + for (j = 0; j < _len; ++j) { + args = toWrapEl.post[j]; + args[0] = newName; + _this.$post.apply(_this, args); + } + } + return _this; +}; + /*! * Module exports. */ diff --git a/lib/document.js b/lib/document.js index d335df2171c..f11d0a3037e 100644 --- a/lib/document.js +++ b/lib/document.js @@ -9,7 +9,6 @@ var Schema = require('./schema'); var ObjectExpectedError = require('./error/objectExpected'); var StrictModeError = require('./error/strict'); var ValidatorError = require('./schematype').ValidatorError; -var VersionError = require('./error').VersionError; var utils = require('./utils'); var clone = utils.clone; var isMongooseObject = utils.isMongooseObject; @@ -1907,174 +1906,6 @@ function applyQueue(doc) { } } -/*! - * Executes methods queued from the Schema definition - * - * @api private - * @method $__registerHooksFromSchema - * @deprecated - * @memberOf Document - */ - -Document.prototype.$__registerHooksFromSchema = function() { - Embedded = Embedded || require('./types/embedded'); - var Promise = PromiseProvider.get(); - - var _this = this; - var q = _this.schema && _this.schema.callQueue; - var toWrapEl; - var len; - var i; - var j; - var pointCut; - var keys; - if (!q.length) { - return _this; - } - - // we are only interested in 'pre' hooks, and group by point-cut - var toWrap = { post: [] }; - var pair; - - for (i = 0; i < q.length; ++i) { - pair = q[i]; - if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') { - _this[pair[0]].apply(_this, pair[1]); - continue; - } - var args = [].slice.call(pair[1]); - pointCut = pair[0] === 'on' ? 'post' : args[0]; - if (!(pointCut in toWrap)) { - toWrap[pointCut] = {post: [], pre: []}; - } - if (pair[0] === 'post') { - toWrap[pointCut].post.push(args); - } else if (pair[0] === 'on') { - toWrap[pointCut].push(args); - } else { - toWrap[pointCut].pre.push(args); - } - } - - // 'post' hooks are simpler - len = toWrap.post.length; - toWrap.post.forEach(function(args) { - _this.on.apply(_this, args); - }); - delete toWrap.post; - - // 'init' should be synchronous on subdocuments - if (toWrap.init && _this instanceof Embedded) { - if (toWrap.init.pre) { - toWrap.init.pre.forEach(function(args) { - _this.$pre.apply(_this, args); - }); - } - if (toWrap.init.post) { - toWrap.init.post.forEach(function(args) { - _this.$post.apply(_this, args); - }); - } - delete toWrap.init; - } else if (toWrap.set) { - // Set hooks also need to be sync re: gh-3479 - if (toWrap.set.pre) { - toWrap.set.pre.forEach(function(args) { - _this.$pre.apply(_this, args); - }); - } - if (toWrap.set.post) { - toWrap.set.post.forEach(function(args) { - _this.$post.apply(_this, args); - }); - } - delete toWrap.set; - } - - keys = Object.keys(toWrap); - len = keys.length; - for (i = 0; i < len; ++i) { - pointCut = keys[i]; - // this is so we can wrap everything into a promise; - var newName = ('$__original_' + pointCut); - if (!_this[pointCut]) { - continue; - } - _this[newName] = _this[pointCut]; - _this[pointCut] = (function(_newName) { - return function wrappedPointCut() { - var args = [].slice.call(arguments); - var lastArg = args.pop(); - var fn; - var originalError = new Error(); - var $results; - if (lastArg && typeof lastArg !== 'function') { - args.push(lastArg); - } else { - fn = lastArg; - } - - var promise = new Promise.ES6(function(resolve, reject) { - args.push(function(error) { - if (error) { - // gh-2633: since VersionError is very generic, take the - // stack trace of the original save() function call rather - // than the async trace - if (error instanceof VersionError) { - error.stack = originalError.stack; - } - _this.$__handleReject(error); - reject(error); - return; - } - - // There may be multiple results and promise libs other than - // mpromise don't support passing multiple values to `resolve()` - $results = Array.prototype.slice.call(arguments, 1); - resolve.apply(promise, $results); - }); - - _this[_newName].apply(_this, args); - }); - if (fn) { - if (_this.constructor.$wrapCallback) { - fn = _this.constructor.$wrapCallback(fn); - } - return promise.then( - function() { - process.nextTick(function() { - fn.apply(null, [null].concat($results)); - }); - }, - function(error) { - process.nextTick(function() { - fn(error); - }); - }); - } - return promise; - }; - })(newName); - - toWrapEl = toWrap[pointCut]; - var _len = toWrapEl.pre.length; - args; - for (j = 0; j < _len; ++j) { - args = toWrapEl.pre[j]; - args[0] = newName; - _this.$pre.apply(_this, args); - } - - _len = toWrapEl.post.length; - for (j = 0; j < _len; ++j) { - args = toWrapEl.post[j]; - args[0] = newName; - _this.$post.apply(_this, args); - } - } - return _this; -}; - Document.prototype.$__handleReject = function handleReject(err) { // emit on the Model if listening if (this.listeners('error').length) { From 344a2b715cc2f8524be2db271af4737a03eebcd7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Jan 2017 22:39:35 -0700 Subject: [PATCH 1125/2240] chore: remove vestigial log --- lib/schematype.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/schematype.js b/lib/schematype.js index a245a88a355..3ca3423618b 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -726,7 +726,6 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { return; } if (validator.length === 2) { - console.log('GZ', scope); var returnVal = validator.call(scope, value, function(ok, customMsg) { if (typeof returnVal === 'boolean') { return; From 76913e3ec807dc6d909c12e7f738a882e3f1f891 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Jan 2017 22:49:36 -0700 Subject: [PATCH 1126/2240] test(model): repro #3893 --- test/model.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index fbefb7bcbc8..86ac83e933b 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5222,6 +5222,32 @@ describe('Model', function() { }); }); + it('insertMany() ordered option (gh-3893)', function(done) { + var schema = new Schema({ + name: { type: String, unique: true } + }); + var Movie = db.model('gh3893', schema); + + var arr = [ + { name: 'Star Wars' }, + { name: 'Star Wars' }, + { name: 'The Empire Strikes Back' } + ]; + Movie.on('index', function(error) { + assert.ifError(error); + Movie.insertMany(arr, { ordered: false }, function(error) { + assert.equal(error.message.indexOf('E11000'), 0); + Movie.find({}).sort({ name: 1 }).exec(function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 2); + assert.equal(docs[0].name, 'Star Wars'); + assert.equal(docs[1].name, 'The Empire Strikes Back'); + done(); + }); + }); + }); + }); + it('insertMany() hooks (gh-3846)', function(done) { var schema = new Schema({ name: String From 55abe106fdc3d59058cd18c43058ac55e92e8766 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Jan 2017 22:52:53 -0700 Subject: [PATCH 1127/2240] feat(model): support options for insertMany Fix #3893 --- lib/model.js | 17 +++++++++++++---- lib/schematype.js | 1 - 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index f27443fc44b..22b76e17594 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1921,13 +1921,18 @@ Model.create = function create(doc, callback) { * Movies.insertMany(arr, function(error, docs) {}); * * @param {Array|Object|*} doc(s) + * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#insertMany) * @param {Function} [callback] callback * @return {Promise} * @api public */ -Model.insertMany = function(arr, callback) { +Model.insertMany = function(arr, options, callback) { var _this = this; + if (typeof options === 'function') { + callback = options; + options = null; + } if (callback) { callback = this.$wrapCallback(callback); } @@ -1963,7 +1968,7 @@ Model.insertMany = function(arr, callback) { } return doc.toObject(POJO_TO_OBJECT_OPTIONS); }); - _this.collection.insertMany(docObjects, function(error) { + _this.collection.insertMany(docObjects, options, function(error) { if (error) { callback && callback(error); return; @@ -3297,10 +3302,14 @@ Model.compile = function compile(name, schema, collectionName, connection, base) var kareemOptions = { useErrorHandlers: true }; model.$__insertMany = model.hooks.createWrapper('insertMany', model.insertMany, model, kareemOptions); - model.insertMany = function(arr, callback) { + model.insertMany = function(arr, options, callback) { var Promise = PromiseProvider.get(); + if (typeof options === 'function') { + callback = options; + options = null; + } return new Promise.ES6(function(resolve, reject) { - model.$__insertMany(arr, function(error, result) { + model.$__insertMany(arr, options, function(error, result) { if (error) { callback && callback(error); return reject(error); diff --git a/lib/schematype.js b/lib/schematype.js index a245a88a355..3ca3423618b 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -726,7 +726,6 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { return; } if (validator.length === 2) { - console.log('GZ', scope); var returnVal = validator.call(scope, value, function(ok, customMsg) { if (typeof returnVal === 'boolean') { return; From f47260b002c4accc6f2b77b8042012d352c81618 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 4 Jan 2017 19:16:01 -0700 Subject: [PATCH 1128/2240] chore: upgrade mongodb -> 2.2.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 13cb64eec68..a99829843cf 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.1", "hooks-fixed": "1.2.0", "kareem": "1.2.0", - "mongodb": "2.2.16", + "mongodb": "2.2.18", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.0.0", From e4fb16cdf0abd5b847df0b8979d019c64c5c86a9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 4 Jan 2017 19:59:19 -0700 Subject: [PATCH 1129/2240] chore: actually bump to 2.2.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a99829843cf..e05dce0f78a 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.1", "hooks-fixed": "1.2.0", "kareem": "1.2.0", - "mongodb": "2.2.18", + "mongodb": "2.2.19", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.0.0", From 61d665c120da616f25b3365605ee5b673ddfa3b8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Jan 2017 12:24:11 -0700 Subject: [PATCH 1130/2240] feat(types): support Decimal128 Fix #4759 --- lib/schema/decimal128.js | 166 ++++++++++++++++++++++++++++++++++++ lib/schema/index.js | 2 + lib/types/decimal128.js | 11 +++ lib/types/index.js | 1 + test/model.populate.test.js | 49 +++++++++++ test/schema.test.js | 15 ++++ 6 files changed, 244 insertions(+) create mode 100644 lib/schema/decimal128.js create mode 100644 lib/types/decimal128.js diff --git a/lib/schema/decimal128.js b/lib/schema/decimal128.js new file mode 100644 index 00000000000..3400e36ef63 --- /dev/null +++ b/lib/schema/decimal128.js @@ -0,0 +1,166 @@ +/* eslint no-empty: 1 */ + +/*! + * Module dependencies. + */ + +var SchemaType = require('../schematype'); +var CastError = SchemaType.CastError; +var Decimal128Type = require('../types/decimal128'); +var utils = require('../utils'); +var Document; + +/** + * Decimal128 SchemaType constructor. + * + * @param {String} key + * @param {Object} options + * @inherits SchemaType + * @api public + */ + +function Decimal128(key, options) { + SchemaType.call(this, key, options, 'Decimal128'); +} + +/** + * This schema type's name, to defend against minifiers that mangle + * function names. + * + * @api public + */ +Decimal128.schemaName = 'Decimal128'; + +/*! + * Inherits from SchemaType. + */ +Decimal128.prototype = Object.create(SchemaType.prototype); +Decimal128.prototype.constructor = Decimal128; + +/** + * Check if the given value satisfies a required validator. + * + * @param {Any} value + * @param {Document} doc + * @return {Boolean} + * @api public + */ + +Decimal128.prototype.checkRequired = function checkRequired(value, doc) { + if (SchemaType._isRef(this, value, doc, true)) { + return !!value; + } + return value instanceof Decimal128Type; +}; + +/** + * Casts to Decimal128 + * + * @param {Object} value + * @param {Object} doc + * @param {Boolean} init whether this is an initialization cast + * @api private + */ + +Decimal128.prototype.cast = function(value, doc, init) { + if (SchemaType._isRef(this, value, doc, init)) { + // wait! we may need to cast this to a document + + if (value === null || value === undefined) { + return value; + } + + // lazy load + Document || (Document = require('./../document')); + + if (value instanceof Document) { + value.$__.wasPopulated = true; + return value; + } + + // setting a populated path + if (value instanceof Decimal128Type) { + return value; + } else if (Buffer.isBuffer(value) || !utils.isObject(value)) { + throw new CastError('Decimal128', value, this.path); + } + + // Handle the case where user directly sets a populated + // path to a plain object; cast to the Model used in + // the population query. + var path = doc.$__fullPath(this.path); + var owner = doc.ownerDocument ? doc.ownerDocument() : doc; + var pop = owner.populated(path, true); + var ret = value; + if (!doc.$__.populated || + !doc.$__.populated[path] || + !doc.$__.populated[path].options || + !doc.$__.populated[path].options.options || + !doc.$__.populated[path].options.options.lean) { + ret = new pop.options.model(value); + ret.$__.wasPopulated = true; + } + + return ret; + } + + if (value === null || value === undefined) { + return value; + } + + if (value instanceof Decimal128Type) { + return value; + } + + if (typeof value === 'string') { + return Decimal128Type.fromString(value); + } + + if (Buffer.isBuffer(value)) { + return new Decimal128Type(value); + } + + throw new CastError('Decimal128', value, this.path); +}; + +/*! + * ignore + */ + +function handleSingle(val) { + return this.cast(val); +} + +Decimal128.prototype.$conditionalHandlers = + utils.options(SchemaType.prototype.$conditionalHandlers, { + $gt: handleSingle, + $gte: handleSingle, + $lt: handleSingle, + $lte: handleSingle + }); + +/** + * Casts contents for queries. + * + * @param {String} $conditional + * @param {any} [val] + * @api private + */ + +Decimal128.prototype.castForQuery = function($conditional, val) { + var handler; + if (arguments.length === 2) { + handler = this.$conditionalHandlers[$conditional]; + if (!handler) { + throw new Error('Can\'t use ' + $conditional + ' with ObjectId.'); + } + return handler.call(this, val); + } + return this.cast($conditional); +}; + +/*! + * Module exports. + */ + +module.exports = Decimal128; diff --git a/lib/schema/index.js b/lib/schema/index.js index f2935c15e2c..ed4b326b859 100644 --- a/lib/schema/index.js +++ b/lib/schema/index.js @@ -23,6 +23,8 @@ exports.ObjectId = require('./objectid'); exports.Mixed = require('./mixed'); +exports.Decimal128 = require('./decimal128'); + // alias exports.Oid = exports.ObjectId; diff --git a/lib/types/decimal128.js b/lib/types/decimal128.js new file mode 100644 index 00000000000..87791c63557 --- /dev/null +++ b/lib/types/decimal128.js @@ -0,0 +1,11 @@ +/** + * ObjectId type constructor + * + * ####Example + * + * var id = new mongoose.Types.ObjectId; + * + * @constructor ObjectId + */ + +module.exports = require('bson').Decimal128; diff --git a/lib/types/index.js b/lib/types/index.js index 0d01923df6c..3fdf2bd6758 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -10,6 +10,7 @@ exports.Document = // @deprecate exports.Embedded = require('./embedded'); exports.DocumentArray = require('./documentarray'); +exports.Decimal128 = require('./decimal128'); exports.ObjectId = require('./objectid'); exports.Subdocument = require('./subdocument'); diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 434ac356b61..ee0b17a768b 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4700,6 +4700,55 @@ describe('model: populate:', function() { }); }); + it('populate with Decimal128 as ref (gh-4759)', function(done) { + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + done(); + return; + } + + test(); + }); + + function test() { + var parentSchema = new Schema({ + name: String, + child: { + type: 'Decimal128', + ref: 'gh4759' + } + }); + + var childSchema = new Schema({ + _id: 'Decimal128', + name: String + }); + + var Child = db.model('gh4759', childSchema); + var Parent = db.model('gh4759_0', parentSchema); + + var decimal128 = childSchema.path('_id').cast('1.337e+3'); + Child.create({ name: 'Luke', _id: '1.337e+3' }). + then(function() { + return Parent.create({ name: 'Anakin', child: decimal128.bytes }); + }). + then(function(parent) { + return Parent.findById(parent._id).populate('child'); + }). + then(function(parent) { + assert.equal(parent.child.name, 'Luke'); + assert.equal(parent.child._id.toString(), '1337'); + done(); + }). + catch(done); + } + }); + it('virtual populate in single nested doc (gh-4715)', function(done) { var someModelSchema = new mongoose.Schema({ name: String diff --git a/test/schema.test.js b/test/schema.test.js index 1e822736175..13d01eef796 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1655,5 +1655,20 @@ describe('schema', function() { assert.deepEqual(schema.path('tags').getDefault().toObject(), [0]); done(); }); + + it('Decimal128 type (gh-4759)', function(done) { + var Decimal128 = mongoose.Schema.Types.Decimal128; + var schema = new Schema({ + num: Decimal128, + nums: ['Decimal128'] + }); + assert.ok(schema.path('num') instanceof Decimal128); + assert.ok(schema.path('nums').caster instanceof Decimal128); + + var casted = schema.path('num').cast('6.2e+23'); + assert.ok(casted instanceof mongoose.Types.Decimal128); + assert.equal(casted.toString(), '6.2E+23'); + done(); + }); }); }); From 7d1e0907f914fa1c1c570215204a1d54b17bcdee Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Jan 2017 22:01:07 -0700 Subject: [PATCH 1131/2240] feat(query): add collation method Fix #4839 --- lib/query.js | 17 +++++++++++++++++ test/query.test.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/lib/query.js b/lib/query.js index d5f5cd02e88..ba8b69afa53 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1235,6 +1235,23 @@ function completeMany(model, docs, fields, pop, callback) { } } +/** + * Adds a collation to this op (MongoDB 3.4 and up) + * + * @param {Object} value + * @return {Query} this + * @see MongoDB docs https://docs.mongodb.com/manual/reference/method/cursor.collation/#cursor.collation + * @api public + */ + +Query.prototype.collation = function(value) { + if (this.options == null) { + this.options = {}; + } + this.options.collation = value; + return this; +}; + /** * Thunk around findOne() * diff --git a/test/query.test.js b/test/query.test.js index 4a465322889..9a2bc406de5 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1489,6 +1489,40 @@ describe('Query', function() { db.close(done); }); + it('collation support (gh-4839)', function(done) { + var schema = new Schema({ + name: String + }); + + var MyModel = db.model('gh4839', schema); + var collation = { locale: 'en_US', strength: 1 }; + + MyModel.create([{ name: 'a' }, { name: 'A' }]). + then(function() { + return MyModel.find({ name: 'a' }).collation(collation); + }). + then(function(docs) { + assert.equal(docs.length, 2); + return MyModel.find({ name: 'a' }, null, { collation: collation }); + }). + then(function(docs) { + assert.equal(docs.length, 2); + return MyModel.find({ name: 'a' }, null, { collation: collation }). + sort({ _id: -1 }). + cursor(). + next(); + }). + then(function(doc) { + assert.equal(doc.name, 'A'); + return MyModel.find({ name: 'a' }); + }). + then(function(docs) { + assert.equal(docs.length, 1); + done(); + }). + catch(done); + }); + describe('gh-1950', function() { it('ignores sort when passed to count', function(done) { var Product = db.model('Product', 'Product_setOptions_test'); From 74fa0e88a8d3bbc984010c718987bfd377d95066 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Jan 2017 22:02:48 -0700 Subject: [PATCH 1132/2240] test: fix 3.4 tests --- test/collection.capped.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/collection.capped.test.js b/test/collection.capped.test.js index db76aca06b8..9650f121a28 100644 --- a/test/collection.capped.test.js +++ b/test/collection.capped.test.js @@ -63,7 +63,7 @@ describe('collections: capped:', function() { }); it('attempting to use existing non-capped collection as capped emits error', function(done) { db = start(); - var opts = {safe: true}; + var opts = {}; var conn = 'capped_existing_' + random(); db.on('open', function() { From e3cfe6f53d90eddb9774d4724ac656f2a72a67e8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Jan 2017 22:03:26 -0700 Subject: [PATCH 1133/2240] test: make #4839 tests only run on 3.4 --- test/query.test.js | 74 ++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index 9a2bc406de5..88e287bf3da 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1490,37 +1490,53 @@ describe('Query', function() { }); it('collation support (gh-4839)', function(done) { - var schema = new Schema({ - name: String + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + done(); + return; + } + + test(); }); - var MyModel = db.model('gh4839', schema); - var collation = { locale: 'en_US', strength: 1 }; - - MyModel.create([{ name: 'a' }, { name: 'A' }]). - then(function() { - return MyModel.find({ name: 'a' }).collation(collation); - }). - then(function(docs) { - assert.equal(docs.length, 2); - return MyModel.find({ name: 'a' }, null, { collation: collation }); - }). - then(function(docs) { - assert.equal(docs.length, 2); - return MyModel.find({ name: 'a' }, null, { collation: collation }). - sort({ _id: -1 }). - cursor(). - next(); - }). - then(function(doc) { - assert.equal(doc.name, 'A'); - return MyModel.find({ name: 'a' }); - }). - then(function(docs) { - assert.equal(docs.length, 1); - done(); - }). - catch(done); + function test() { + var schema = new Schema({ + name: String + }); + + var MyModel = db.model('gh4839', schema); + var collation = { locale: 'en_US', strength: 1 }; + + MyModel.create([{ name: 'a' }, { name: 'A' }]). + then(function() { + return MyModel.find({ name: 'a' }).collation(collation); + }). + then(function(docs) { + assert.equal(docs.length, 2); + return MyModel.find({ name: 'a' }, null, { collation: collation }); + }). + then(function(docs) { + assert.equal(docs.length, 2); + return MyModel.find({ name: 'a' }, null, { collation: collation }). + sort({ _id: -1 }). + cursor(). + next(); + }). + then(function(doc) { + assert.equal(doc.name, 'A'); + return MyModel.find({ name: 'a' }); + }). + then(function(docs) { + assert.equal(docs.length, 1); + done(); + }). + catch(done); + } }); describe('gh-1950', function() { From 8b4870c18c49c3bd1581c6a470ccf107addfb5f3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 Jan 2017 15:44:46 -0700 Subject: [PATCH 1134/2240] feat(schema): add saveErrorIfNotFound option and $where property Fix #4004, enables OCC plugins --- lib/error.js | 1 + lib/error/notFound.js | 41 ++++++++++++++++++++++++++++++++++++ lib/model.js | 33 ++++++++++++++++++++++++++++- test/document.test.js | 48 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 lib/error/notFound.js diff --git a/lib/error.js b/lib/error.js index b084e764c95..bee4d22017f 100644 --- a/lib/error.js +++ b/lib/error.js @@ -47,6 +47,7 @@ MongooseError.Messages = MongooseError.messages; */ MongooseError.CastError = require('./error/cast'); +MongooseError.DocumentNotFoundError = require('./error/notFound'); MongooseError.ValidationError = require('./error/validation'); MongooseError.ValidatorError = require('./error/validator'); MongooseError.VersionError = require('./error/version'); diff --git a/lib/error/notFound.js b/lib/error/notFound.js new file mode 100644 index 00000000000..24d608a9ff3 --- /dev/null +++ b/lib/error/notFound.js @@ -0,0 +1,41 @@ +'use strict'; + +/*! + * Module dependencies. + */ + +var MongooseError = require('../error.js'); +var util = require('util'); + +/*! + * OverwriteModel Error constructor. + * + * @inherits MongooseError + */ + +function DocumentNotFoundError(query) { + MongooseError.call(this, 'No document found for query "' + + util.inspect(query) + '"'); + + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack; + } + + this.name = 'DocumentNotFoundError'; + this.query = query; +} + +/*! + * Inherits from MongooseError. + */ + +DocumentNotFoundError.prototype = Object.create(MongooseError.prototype); +DocumentNotFoundError.prototype.constructor = MongooseError; + +/*! + * exports + */ + +module.exports = DocumentNotFoundError; diff --git a/lib/model.js b/lib/model.js index 22b76e17594..183bbccc1e3 100644 --- a/lib/model.js +++ b/lib/model.js @@ -4,6 +4,7 @@ var Aggregate = require('./aggregate'); var Document = require('./document'); +var DocumentNotFoundError = require('./error/notFound'); var DivergentArrayError = require('./error').DivergentArrayError; var EventEmitter = require('events').EventEmitter; var OverwriteModelError = require('./error').OverwriteModelError; @@ -80,6 +81,16 @@ Model.prototype.collection; Model.prototype.modelName; +/** + * Additional properties to attach to the query when calling `save()` and + * `isNew` is false. + * + * @api public + * @property $where + */ + +Model.prototype.$where; + /** * If this is a discriminator model, `baseModelName` is the name of * the base model. @@ -92,6 +103,9 @@ Model.prototype.baseModelName; Model.prototype.$__handleSave = function(options, callback) { var _this = this; + var i; + var keys; + var len; if (!options.safe && this.schema.options.safe) { options.safe = this.schema.options.safe; } @@ -155,17 +169,25 @@ Model.prototype.$__handleSave = function(options, callback) { } var where = this.$__where(delta[0]); - if (where instanceof Error) { callback(where); return; } + if (this.$where) { + keys = Object.keys(this.$where); + len = keys.length; + for (i = 0; i < len; ++i) { + where[keys[i]] = this.$where[keys[i]]; + } + } + this.collection.update(where, delta[1], options.safe, function(err, ret) { if (err) { callback(err); return; } + ret.$where = where; callback(null, ret); }); } else { @@ -228,6 +250,15 @@ Model.prototype.$__save = function(options, callback) { } } + if (_this.schema.options && + _this.schema.options.saveErrorIfNotFound && + numAffected <= 0) { + error = new DocumentNotFoundError(result.$where); + return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { + callback(error); + }); + } + _this.emit('save', _this, numAffected); _this.constructor.emit('save', _this, numAffected); callback(null, _this, numAffected); diff --git a/test/document.test.js b/test/document.test.js index b3717f709ad..436c1aa4447 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3634,6 +3634,54 @@ describe('document', function() { done(); }); + it('supports $where in pre save hook (gh-4004)', function(done) { + var Promise = global.Promise; + + var schema = new Schema({ + name: String + }, { timestamps: true, versionKey: null, saveErrorIfNotFound: true }); + + schema.pre('save', function(next) { + this.$where = { updatedAt: this.updatedAt }; + next(); + }); + + schema.post('save', function(error, res, next) { + if (error instanceof MongooseError.DocumentNotFoundError) { + error = new Error('Somebody else updated the document!'); + } + next(error); + }); + + var MyModel = db.model('gh4004', schema); + + MyModel.create({ name: 'test' }). + then(function() { + return Promise.all([ + MyModel.findOne(), + MyModel.findOne() + ]); + }). + then(function(docs) { + docs[0].name = 'test2'; + return Promise.all([ + docs[0].save(), + Promise.resolve(docs[1]) + ]); + }). + then(function(docs) { + docs[1].name = 'test3'; + return docs[1].save(); + }). + then(function() { + done(new Error('Should not get here')); + }). + catch(function(error) { + assert.equal(error.message, 'Somebody else updated the document!'); + done(); + }); + }); + it('toObject() with buffer and minimize (gh-4800)', function(done) { var TestSchema = new mongoose.Schema({ buf: Buffer }, { toObject: { From d152175748c7e8a762a55fbcae4206accbbb8292 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 Jan 2017 17:05:58 -0700 Subject: [PATCH 1135/2240] feat(query): add mongooseOptions to make plugins like #3366 not use internal state --- lib/query.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/query.js b/lib/query.js index ba8b69afa53..508ef7195f4 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1062,6 +1062,22 @@ Query.prototype.lean = function(v) { return this; }; +/** + * Getter/setter around the current mongoose-specific options for this query + * (populate, lean, etc.) + * + * @param {Object} options if specified, overwrites the current options + * @returns {Object} the options + * @api public + */ + +Query.prototype.mongooseOptions = function(v) { + if (arguments.length > 0) { + this._mongooseOptions = v; + } + return this._mongooseOptions; +}; + /** * Thunk around find() * From 6944f6d13f57b4c99a81cf900686ca533960f467 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 Jan 2017 18:19:27 -0700 Subject: [PATCH 1136/2240] chore: upgrade mquery -> 2.2.0 for #3997 --- lib/query.js | 4 ++++ package.json | 2 +- test/query.test.js | 8 -------- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/query.js b/lib/query.js index 508ef7195f4..c72c4881b67 100644 --- a/lib/query.js +++ b/lib/query.js @@ -84,6 +84,10 @@ function Query(conditions, options, model, collection) { Query.prototype._findOneAndRemove, this, kareemOptions); this._findOneAndUpdate = this.model.hooks.createWrapper('findOneAndUpdate', Query.prototype._findOneAndUpdate, this, kareemOptions); + this._updateMany = this.model.hooks.createWrapper('updateMany', + Query.prototype._updateMany, this, kareemOptions); + this._updateOne = this.model.hooks.createWrapper('updateOne', + Query.prototype._updateOne, this, kareemOptions); } } diff --git a/package.json b/package.json index e05dce0f78a..488297f7e5e 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.2.19", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "2.0.0", + "mquery": "2.2.0", "ms": "0.7.2", "muri": "1.1.1", "regexp-clone": "0.0.1", diff --git a/test/query.test.js b/test/query.test.js index 88e287bf3da..e9eb7706852 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -68,14 +68,6 @@ describe('Query', function() { done(); }); - it('["a","b","c"]', function(done) { - assert.throws(function() { - var query = new Query({}, {}, null, p1.collection); - query.select(['a', 'b', 'c']); - }, /Invalid select/); - done(); - }); - it('should not overwrite fields set in prior calls', function(done) { var query = new Query({}, {}, null, p1.collection); query.select('a'); From aa250d15667764ae4f88c488980a5667612f1822 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 Jan 2017 18:23:59 -0700 Subject: [PATCH 1137/2240] refactor(query): use helper for update --- lib/query.js | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/lib/query.js b/lib/query.js index c72c4881b67..0b9efabfd7c 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2222,6 +2222,14 @@ Query.prototype.update = function(conditions, doc, options, callback) { callback = undefined; } + return _update(this, 'update', conditions, doc, options, callback); +}; + +/*! + * Internal helper for update, updateMany, updateOne + */ + +function _update(query, op, conditions, doc, options, callback) { // make sure we don't send in the whole Document to merge() conditions = utils.toObject(conditions); @@ -2239,7 +2247,7 @@ Query.prototype.update = function(conditions, doc, options, callback) { // strict is an option used in the update checking, make sure it gets set if (options) { if ('strict' in options) { - this._mongooseOptions.strict = options.strict; + query._mongooseOptions.strict = options.strict; } } @@ -2248,21 +2256,21 @@ Query.prototype.update = function(conditions, doc, options, callback) { // order to validate // This could also be somebody calling update() or update({}). Probably not a // common use case, check for _update to make sure we don't do anything bad - if (!doc && this._update) { - doc = this._updateForExec(); + if (!doc && query._update) { + doc = query._updateForExec(); } if (mquery.canMerge(conditions)) { - this.merge(conditions); + query.merge(conditions); } // validate the selector part of the query - var castedQuery = castQuery(this); + var castedQuery = castQuery(query); if (castedQuery instanceof Error) { - this._castError = castedQuery; + query._castError = castedQuery; if (callback) { callback(castedQuery); - return this; + return query; } else if (!options || !options.dontThrowCastError) { throw castedQuery; } @@ -2275,39 +2283,42 @@ Query.prototype.update = function(conditions, doc, options, callback) { if (options && options.minimize) { $options.minimize = true; } - castedDoc = this._castUpdate(utils.clone(doc, $options), + castedDoc = query._castUpdate(utils.clone(doc, $options), options && options.overwrite); } catch (err) { - this._castError = castedQuery; + query._castError = castedQuery; if (callback) { callback(err); - return this; + return query; } else if (!options || !options.dontThrowCastError) { throw err; } } - castedDoc = setDefaultsOnInsert(this, this.schema, castedDoc, options); + castedDoc = setDefaultsOnInsert(query, query.schema, castedDoc, options); if (!castedDoc) { // Make sure promises know that this is still an update, see gh-2796 - this.op = 'update'; + query.op = op; callback && callback(null); - return this; + return query; } if (utils.isObject(options)) { - this.setOptions(options); + query.setOptions(options); } - if (!this._update) this._update = castedDoc; + if (!query._update) query._update = castedDoc; // Hooks if (callback) { - return this._execUpdate(callback); + if (op === 'update') { + return query._execUpdate(callback); + } + return query['_' + op](callback); } - return Query.base.update.call(this, castedQuery, castedDoc, options, callback); -}; + return Query.base[op].call(query, castedQuery, castedDoc, options, callback); +} /** * Executes the query From 635b2c0041bfb9db2d64db6994981db0ac682583 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 Jan 2017 18:33:21 -0700 Subject: [PATCH 1138/2240] refactor(model): move update into helper function re: #3997 --- lib/model.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index 183bbccc1e3..6b55320a491 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2115,9 +2115,17 @@ Model.hydrate = function(obj) { */ Model.update = function update(conditions, doc, options, callback) { - var mq = new this.Query({}, {}, this, this.collection); + return _update(this, conditions, doc, options, callback); +}; + +/*! + * ignore + */ + +function _update(model, conditions, doc, options, callback) { + var mq = new model.Query({}, {}, model, model.collection); if (callback) { - callback = this.$wrapCallback(callback); + callback = model.$wrapCallback(callback); } // gh-2406 // make local deep copy of conditions @@ -2128,19 +2136,19 @@ Model.update = function update(conditions, doc, options, callback) { } options = typeof options === 'function' ? options : utils.clone(options); - if (this.schema.options.versionKey && options && options.upsert) { + if (model.schema.options.versionKey && options && options.upsert) { if (options.overwrite) { - doc[this.schema.options.versionKey] = 0; + doc[model.schema.options.versionKey] = 0; } else { if (!doc.$setOnInsert) { doc.$setOnInsert = {}; } - doc.$setOnInsert[this.schema.options.versionKey] = 0; + doc.$setOnInsert[model.schema.options.versionKey] = 0; } } return mq.update(conditions, doc, options, callback); -}; +} /** * Executes a mapReduce command. From 1ddae9895f761dac33985b06b0a16f92a1e8b6a3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 Jan 2017 19:01:38 -0700 Subject: [PATCH 1139/2240] feat(query): add updateOne and updateMany Fix #3997 --- lib/model.js | 45 ++++++++- lib/query.js | 184 ++++++++++++++++++++++++++++++++++ lib/schema.js | 4 +- test/query.middleware.test.js | 65 ++++++++++++ 4 files changed, 294 insertions(+), 4 deletions(-) diff --git a/lib/model.js b/lib/model.js index 6b55320a491..01a0129d131 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2115,14 +2115,53 @@ Model.hydrate = function(obj) { */ Model.update = function update(conditions, doc, options, callback) { - return _update(this, conditions, doc, options, callback); + return _update(this, 'update', conditions, doc, options, callback); +}; + +/** + * Same as `update()`, except MongoDB will update _all_ documents that match + * `criteria` (as opposed to just the first one) regardless of the value of + * the `multi` option. + * + * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')` + * and `post('updateMany')` instead. + * + * @param {Object} conditions + * @param {Object} doc + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} + * @api public + */ + +Model.updateMany = function updateMany(conditions, doc, options, callback) { + return _update(this, 'updateMany', conditions, doc, options, callback); +}; + +/** + * Same as `update()`, except MongoDB will update _only_ the first document that + * matches `criteria` regardless of the value of the `multi` option. + * + * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')` + * and `post('updateMany')` instead. + * + * @param {Object} conditions + * @param {Object} doc + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} + * @api public + */ + +Model.updateOne = function updateOne(conditions, doc, options, callback) { + return _update(this, 'updateOne', conditions, doc, options, callback); }; /*! * ignore */ -function _update(model, conditions, doc, options, callback) { +function _update(model, op, conditions, doc, options, callback) { var mq = new model.Query({}, {}, model, model.collection); if (callback) { callback = model.$wrapCallback(callback); @@ -2147,7 +2186,7 @@ function _update(model, conditions, doc, options, callback) { } } - return mq.update(conditions, doc, options, callback); + return mq[op](conditions, doc, options, callback); } /** diff --git a/lib/query.js b/lib/query.js index 0b9efabfd7c..7660d621bc7 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2111,6 +2111,96 @@ Query.prototype._execUpdate = function(callback) { return this; }; +/** + * Internal thunk for .updateMany() + * + * @param {Function} callback + * @see Model.update #model_Model.update + * @api private + */ +Query.prototype._updateMany = function(callback) { + var schema = this.model.schema; + var doValidate; + var _this; + + var castedQuery = this._conditions; + var castedDoc = this._update; + var options = this.options; + + if (this._castError) { + callback(this._castError); + return this; + } + + if (this.options.runValidators) { + _this = this; + doValidate = updateValidators(this, schema, castedDoc, options); + var _callback = function(err) { + if (err) { + return callback(err); + } + + Query.base.updateMany.call(_this, castedQuery, castedDoc, options, callback); + }; + try { + doValidate(_callback); + } catch (err) { + process.nextTick(function() { + callback(err); + }); + } + return this; + } + + Query.base.updateMany.call(this, castedQuery, castedDoc, options, callback); + return this; +}; + +/** + * Internal thunk for .updateOne() + * + * @param {Function} callback + * @see Model.update #model_Model.update + * @api private + */ +Query.prototype._updateOne = function(callback) { + var schema = this.model.schema; + var doValidate; + var _this; + + var castedQuery = this._conditions; + var castedDoc = this._update; + var options = this.options; + + if (this._castError) { + callback(this._castError); + return this; + } + + if (this.options.runValidators) { + _this = this; + doValidate = updateValidators(this, schema, castedDoc, options); + var _callback = function(err) { + if (err) { + return callback(err); + } + + Query.base.updateOne.call(_this, castedQuery, castedDoc, options, callback); + }; + try { + doValidate(_callback); + } catch (err) { + process.nextTick(function() { + callback(err); + }); + } + return this; + } + + Query.base.updateOne.call(this, castedQuery, castedDoc, options, callback); + return this; +}; + /** * Declare and/or execute this query as an update() operation. * @@ -2225,12 +2315,106 @@ Query.prototype.update = function(conditions, doc, options, callback) { return _update(this, 'update', conditions, doc, options, callback); }; +/** + * Declare and/or execute this query as an updateMany() operation. Same as + * `update()`, except MongoDB will update _all_ documents that match + * `criteria` (as opposed to just the first one) regardless of the value of + * the `multi` option. + * + * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')` + * and `post('updateMany')` instead. + * + * @param {Object} [criteria] + * @param {Object} [doc] the update command + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} this + * @see Model.update #model_Model.update + * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/ + * @api public + */ + +Query.prototype.updateMany = function(conditions, doc, options, callback) { + if (typeof options === 'function') { + // .update(conditions, doc, callback) + callback = options; + options = null; + } else if (typeof doc === 'function') { + // .update(doc, callback); + callback = doc; + doc = conditions; + conditions = {}; + options = null; + } else if (typeof conditions === 'function') { + // .update(callback) + callback = conditions; + conditions = undefined; + doc = undefined; + options = undefined; + } else if (typeof conditions === 'object' && !doc && !options && !callback) { + // .update(doc) + doc = conditions; + conditions = undefined; + options = undefined; + callback = undefined; + } + + return _update(this, 'updateMany', conditions, doc, options, callback); +}; + +/** + * Declare and/or execute this query as an updateOne() operation. Same as + * `update()`, except MongoDB will update _only_ the first document that + * matches `criteria` regardless of the value of the `multi` option. + * + * **Note** updateOne will _not_ fire update middleware. Use `pre('updateOne')` + * and `post('updateOne')` instead. + * + * @param {Object} [criteria] + * @param {Object} [doc] the update command + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} this + * @see Model.update #model_Model.update + * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/ + * @api public + */ + +Query.prototype.updateOne = function(conditions, doc, options, callback) { + if (typeof options === 'function') { + // .update(conditions, doc, callback) + callback = options; + options = null; + } else if (typeof doc === 'function') { + // .update(doc, callback); + callback = doc; + doc = conditions; + conditions = {}; + options = null; + } else if (typeof conditions === 'function') { + // .update(callback) + callback = conditions; + conditions = undefined; + doc = undefined; + options = undefined; + } else if (typeof conditions === 'object' && !doc && !options && !callback) { + // .update(doc) + doc = conditions; + conditions = undefined; + options = undefined; + callback = undefined; + } + + return _update(this, 'updateOne', conditions, doc, options, callback); +}; + /*! * Internal helper for update, updateMany, updateOne */ function _update(query, op, conditions, doc, options, callback) { // make sure we don't send in the whole Document to merge() + query.op = op; conditions = utils.toObject(conditions); var oldCb = callback; diff --git a/lib/schema.js b/lib/schema.js index 30a4a9fd797..5f422289760 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -18,7 +18,9 @@ var IS_KAREEM_HOOK = { findOneAndUpdate: true, findOneAndRemove: true, insertMany: true, - update: true + update: true, + updateMany: true, + updateOne: true }; /** diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 1925f2235eb..a10007107c7 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -214,6 +214,71 @@ describe('query middleware', function() { }); }); + it('updateOne() (gh-3997)', function(done) { + var preCount = 0; + var postCount = 0; + + schema.pre('updateOne', function() { + ++preCount; + }); + + schema.post('updateOne', function() { + ++postCount; + }); + + initializeData(function(error) { + assert.ifError(error); + Author. + updateOne({}, { author: 'updatedOne' }). + exec(function(error) { + assert.ifError(error); + assert.equal(preCount, 1); + assert.equal(postCount, 1); + Author.find({ author: 'updatedOne' }, function(error, res) { + assert.ifError(error); + assert.equal(res.length, 1); + done(); + }); + }); + }); + }); + + it('updateMany() (gh-3997)', function(done) { + var preCount = 0; + var postCount = 0; + + schema.pre('updateMany', function() { + ++preCount; + }); + + schema.post('updateMany', function() { + ++postCount; + }); + + initializeData(function(error) { + assert.ifError(error); + + Author.create({ author: 'test' }, function(error) { + assert.ifError(error); + Author. + updateMany({}, { author: 'updatedMany' }). + exec(function(error) { + assert.ifError(error); + assert.equal(preCount, 1); + assert.equal(postCount, 1); + Author.find({}, function(error, res) { + assert.ifError(error); + assert.ok(res.length > 1); + res.forEach(function(doc) { + assert.equal(doc.author, 'updatedMany'); + }); + done(); + }); + }); + }); + }); + }); + it('error handlers (gh-2284)', function(done) { var testSchema = new Schema({ title: { type: String, unique: true } }); From 5617012b636880e30ca92e7b43ccd69164dfe5be Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Jan 2017 13:49:04 -0700 Subject: [PATCH 1140/2240] test(document): repro #3884 --- test/document.test.js | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 436c1aa4447..7ac5ccf7726 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3704,6 +3704,46 @@ describe('document', function() { catch(done); }); + it('runs validate hooks on single nested subdocs if not directly modified (gh-3884)', function(done) { + var childSchema = new Schema({ + name: { type: String }, + friends: [{ type: String }] + }); + var count = 0; + + childSchema.pre('validate', function(next) { + ++count; + next(); + }); + + var parentSchema = new Schema({ + name: { type: String }, + child: childSchema + }); + + var Parent = db.model('gh3884', parentSchema); + + var p = new Parent({ + name: 'Mufasa', + child: { + name: 'Simba', + friends: ['Pumbaa', 'Timon', 'Nala'] + } + }); + + p.save(). + then(function(p) { + assert.equal(count, 1); + p.child.friends.push('Rafiki'); + return p.save(); + }). + then(function() { + assert.equal(count, 2); + done(); + }). + catch(done); + }); + it('does not overwrite when setting nested (gh-4793)', function(done) { var grandchildSchema = new mongoose.Schema(); grandchildSchema.method({ From b9bb991fee43dda1b89f28217a52cabff80ebb98 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Jan 2017 13:50:06 -0700 Subject: [PATCH 1141/2240] fix(document): run validation on single nested docs if not directly modified Fix #3884 --- lib/document.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index f11d0a3037e..505f24619ab 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1246,6 +1246,8 @@ Document.prototype.validate = function(options, callback) { */ function _getPathsToValidate(doc) { + var i; + // only validate required fields when necessary var paths = Object.keys(doc.$__.activePaths.states.require).filter(function(path) { if (!doc.isSelected(path) && !doc.isModified(path)) { @@ -1262,9 +1264,21 @@ function _getPathsToValidate(doc) { paths = paths.concat(Object.keys(doc.$__.activePaths.states.modify)); paths = paths.concat(Object.keys(doc.$__.activePaths.states.default)); + var subdocs = doc.$__getAllSubdocs(); + var subdoc; + var len = subdocs.length; + for (i = 0; i < len; ++i) { + subdoc = subdocs[i]; + if (subdoc.$isSingleNested && + doc.isModified(subdoc.$basePath) && + !doc.isDirectModified(subdoc.$basePath)) { + paths.push(subdoc.$basePath); + } + } + // gh-661: if a whole array is modified, make sure to run validation on all // the children as well - for (var i = 0; i < paths.length; ++i) { + for (i = 0; i < paths.length; ++i) { var path = paths[i]; var val = doc.getValue(path); if (val && val.isMongooseArray && !Buffer.isBuffer(val) && !val.isMongooseDocumentArray) { From a66a8cadb27941a4010134c73f07c2a0e615a996 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Jan 2017 14:38:47 -0700 Subject: [PATCH 1142/2240] feat(model): use discriminator constructor based on discriminatorKey in create() Fix #3624 --- lib/model.js | 6 +++++- test/model.create.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 01a0129d131..61577814b45 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1862,6 +1862,7 @@ Model.findByIdAndRemove = function(id, options, callback) { Model.create = function create(doc, callback) { var args; var cb; + var discriminatorKey = this.schema.options.discriminatorKey; if (Array.isArray(doc)) { args = doc; @@ -1894,7 +1895,10 @@ Model.create = function create(doc, callback) { var toExecute = []; args.forEach(function(doc) { toExecute.push(function(callback) { - var toSave = doc instanceof _this ? doc : new _this(doc); + var Model = _this.discriminators && doc[discriminatorKey] ? + _this.discriminators[doc[discriminatorKey]] : + _this; + var toSave = doc instanceof Model ? doc : Model(doc); var callbackWrapper = function(error, doc) { if (error) { return callback(error); diff --git a/test/model.create.test.js b/test/model.create.test.js index 05acc313634..29dca1a2b34 100644 --- a/test/model.create.test.js +++ b/test/model.create.test.js @@ -143,6 +143,33 @@ describe('model', function() { }); }); + it('handles discriminators (gh-3624)', function(done) { + var shapeSchema = new Schema({ + name: String + }, { discriminatorKey: 'kind' }); + + var Shape = db.model('gh3624', shapeSchema); + + var Circle = Shape.discriminator('gh3624_0', + new Schema({ radius: Number })); + var Square = Shape.discriminator('gh3624_1', + new Schema({ side: Number })); + + var shapes = [ + { name: 'Test' }, + { kind: 'gh3624_0', radius: 5 }, + { kind: 'gh3624_1', side: 10 } + ]; + Shape.create(shapes, function(error, shapes) { + assert.ifError(error); + assert.ok(shapes[0] instanceof Shape); + assert.ok(shapes[1] instanceof Circle); + assert.equal(shapes[1].radius, 5); + assert.ok(shapes[2] instanceof Square); + assert.equal(shapes[2].side, 10); + done(); + }); + }); describe('callback is optional', function() { it('with one doc', function(done) { From c1ecd754418e827a0c99ffef6879bf873f803bd3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Jan 2017 14:44:51 -0700 Subject: [PATCH 1143/2240] docs(discriminators): add docs re: #3624 --- test/docs/discriminators.test.js | 34 ++++++++++++++++++++++++++++++++ test/model.create.test.js | 28 -------------------------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index b33bd150b9e..5e7acff41b6 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -240,4 +240,38 @@ describe('discriminator docs', function () { done(); // acquit:ignore:end }); + + /** + * When you use `Model.create()`, mongoose + */ + it('Using discriminators with `Model.create()`', function(done) { + var Schema = mongoose.Schema; + var shapeSchema = new Schema({ + name: String + }, { discriminatorKey: 'kind' }); + + var Shape = db.model('Shape', shapeSchema); + + var Circle = Shape.discriminator('Circle', + new Schema({ radius: Number })); + var Square = Shape.discriminator('Square', + new Schema({ side: Number })); + + var shapes = [ + { name: 'Test' }, + { kind: 'Circle', radius: 5 }, + { kind: 'Square', side: 10 } + ]; + Shape.create(shapes, function(error, shapes) { + assert.ifError(error); + assert.ok(shapes[0] instanceof Shape); + assert.ok(shapes[1] instanceof Circle); + assert.equal(shapes[1].radius, 5); + assert.ok(shapes[2] instanceof Square); + assert.equal(shapes[2].side, 10); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); }); diff --git a/test/model.create.test.js b/test/model.create.test.js index 29dca1a2b34..75aa09acd47 100644 --- a/test/model.create.test.js +++ b/test/model.create.test.js @@ -143,34 +143,6 @@ describe('model', function() { }); }); - it('handles discriminators (gh-3624)', function(done) { - var shapeSchema = new Schema({ - name: String - }, { discriminatorKey: 'kind' }); - - var Shape = db.model('gh3624', shapeSchema); - - var Circle = Shape.discriminator('gh3624_0', - new Schema({ radius: Number })); - var Square = Shape.discriminator('gh3624_1', - new Schema({ side: Number })); - - var shapes = [ - { name: 'Test' }, - { kind: 'gh3624_0', radius: 5 }, - { kind: 'gh3624_1', side: 10 } - ]; - Shape.create(shapes, function(error, shapes) { - assert.ifError(error); - assert.ok(shapes[0] instanceof Shape); - assert.ok(shapes[1] instanceof Circle); - assert.equal(shapes[1].radius, 5); - assert.ok(shapes[2] instanceof Square); - assert.equal(shapes[2].side, 10); - done(); - }); - }); - describe('callback is optional', function() { it('with one doc', function(done) { var p = B.create({title: 'optional callback'}); From c62237ad0ea859dac5f607a4785b3faf78239910 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Jan 2017 15:00:20 -0700 Subject: [PATCH 1144/2240] feat: pass collection as context to debug function Fix #3261 --- lib/drivers/node-mongodb-native/collection.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js index fd0da30cd2b..49cd41acfe9 100644 --- a/lib/drivers/node-mongodb-native/collection.js +++ b/lib/drivers/node-mongodb-native/collection.js @@ -108,14 +108,14 @@ function iter(i) { return; } - var collection = this.collection, - args = arguments, - _this = this, - debug = _this.conn.base.options.debug; + var collection = this.collection; + var args = arguments; + var _this = this; + var debug = _this.conn.base.options.debug; if (debug) { if (typeof debug === 'function') { - debug.apply(debug, + debug.apply(_this, [_this.name, i].concat(utils.args(args, 0, args.length - 1))); } else { this.$print(_this.name, i, args); From 5dd926fcf5c89377c7dcb18334fcb87963c11e4a Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Tue, 10 Jan 2017 00:44:20 -0500 Subject: [PATCH 1145/2240] feat(aggregate): add graphLookup() as part of aggregation pipeline options for mongodb 3.4 --- lib/aggregate.js | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 69bbf7d80d5..f0eaad48218 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -312,7 +312,36 @@ Aggregate.prototype.lookup = function(options) { }; /** - * Appends new custom $sample operator(s) to this aggregate pipeline. + * Appends new custom $graphLookup operator(s) to this aggregate pipeline, performing a recursive search on a collection. + * + * NOTE: graphLookup can only consume at most 100MB of memory, and does not allow disk use even if `{ allowDiskUse: true }` is specified. + * + * #### Examples: + * // Suppose we have a collection of courses, where a document might look like `{ _id: 0, name: 'Calculus', prerequisite: 'Trigonometry'}` and `{ _id: 0, name: 'Trigonometry', prerequisite: 'Algebra' }` + * aggregate.graphLookup({ from: 'courses', startWith: '$prerequisite', connectFromField: 'prerequisite', connectToField: 'name', as: 'prerequisites', maxDepth: 3 }) // this will recursively search the 'courses' collection up to 3 prerequisites + */ + +Aggregate.prototype.graphLookup = function(options) { + if (options) { + if (!utils.isObject(options)) { + throw new TypeError('Invalid graphLookup() argument. Must be an object.'); + } + + var cloneOptions = utils.merge({}, options); + var startWith = cloneOptions.startWith; + + if (startWith && typeof startWith === 'string') { + cloneOptions.startWith = cloneOptions.startWith.charAt(0) === '$' ? + cloneOptions.startWith : + '$' + cloneOptions.startWith; + } + + return this.append({ $graphLookup: cloneOptions }); + } +}; + +/** + * Appepnds new custom $sample operator(s) to this aggregate pipeline. * * ####Examples: * From 01cbf179d29fb2886d8887f05e0c8be3ee1b7c4f Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Tue, 10 Jan 2017 00:48:54 -0500 Subject: [PATCH 1146/2240] docs(aggregate): Add jsdoc for graphLookup() --- lib/aggregate.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/aggregate.js b/lib/aggregate.js index f0eaad48218..76f44fe09d0 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -319,6 +319,11 @@ Aggregate.prototype.lookup = function(options) { * #### Examples: * // Suppose we have a collection of courses, where a document might look like `{ _id: 0, name: 'Calculus', prerequisite: 'Trigonometry'}` and `{ _id: 0, name: 'Trigonometry', prerequisite: 'Algebra' }` * aggregate.graphLookup({ from: 'courses', startWith: '$prerequisite', connectFromField: 'prerequisite', connectToField: 'name', as: 'prerequisites', maxDepth: 3 }) // this will recursively search the 'courses' collection up to 3 prerequisites + * + * @see $graphLookup https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/#pipe._S_graphLookup + * @param {Object} options to $graphLookup as described in the above link + * @return {Aggregate} + * @api public */ Aggregate.prototype.graphLookup = function(options) { From 9d5f719f2dbe32ea272a9b6668dd52481aef276f Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Tue, 10 Jan 2017 01:03:11 -0500 Subject: [PATCH 1147/2240] fix(aggregate): return aggregation query from graphLookup even if no options are passed in so as to not break the promise chain --- lib/aggregate.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 76f44fe09d0..a72568a5373 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -327,12 +327,13 @@ Aggregate.prototype.lookup = function(options) { */ Aggregate.prototype.graphLookup = function(options) { + var cloneOptions = {}; if (options) { if (!utils.isObject(options)) { throw new TypeError('Invalid graphLookup() argument. Must be an object.'); } - var cloneOptions = utils.merge({}, options); + cloneOptions = utils.merge({}, options); var startWith = cloneOptions.startWith; if (startWith && typeof startWith === 'string') { @@ -341,8 +342,8 @@ Aggregate.prototype.graphLookup = function(options) { '$' + cloneOptions.startWith; } - return this.append({ $graphLookup: cloneOptions }); } + return this.append({ $graphLookup: cloneOptions }); }; /** From 075213f45a27891b2515d0bbe31cad24e98382b3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 11 Jan 2017 22:25:03 -0700 Subject: [PATCH 1148/2240] chore: upgrade mongodb -> 2.2.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e05dce0f78a..5a544c44d10 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.1", "hooks-fixed": "1.2.0", "kareem": "1.2.0", - "mongodb": "2.2.19", + "mongodb": "2.2.20", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.0.0", From ab680e4c15aba3a27bcb3625c2dabc96b22fe18e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 11 Jan 2017 22:46:17 -0700 Subject: [PATCH 1149/2240] test: repro #4866 --- test/aggregate.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 0ecca67c9c8..3dfc2a660fd 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -700,4 +700,19 @@ describe('aggregate: ', function() { done(); }); }); + + it('query by document (gh-4866)', function(done) { + var db = start(); + + var MyModel = db.model('gh4866', { + name: String + }); + + MyModel.create({ name: 'test' }). + then(function(doc) { return MyModel.aggregate([{ $match: doc }]); }). + then(function() { + done(); + }). + catch(done); + }); }); From dd8003b1b9dd89543ce5f52aa2c912f093a9bdde Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 11 Jan 2017 22:46:27 -0700 Subject: [PATCH 1150/2240] fix: add a toBSON to documents for easier querying Fix #4866 --- lib/document.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/document.js b/lib/document.js index 1252f7a3fbe..0d15ac0b89b 100644 --- a/lib/document.js +++ b/lib/document.js @@ -273,6 +273,19 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) { return doc; }; +/*! + * Converts to POJO when you use the document for querying + */ + +Document.prototype.toBSON = function() { + return this.toObject({ + transform: false, + virtuals: false, + _skipDepopulateTopLevel: true, + depopulate: true + }); +}; + /** * Initializes the document without setters or marking anything modified. * From ba3137b1d1e4ac0c55de18980af43523a4a16273 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Jan 2017 10:24:49 -0700 Subject: [PATCH 1151/2240] style: fix lint --- lib/aggregate.js | 10 +++--- lib/services/updateValidators.js | 2 +- test/model.test.js | 54 +++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index a72568a5373..28aa712a167 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -313,13 +313,13 @@ Aggregate.prototype.lookup = function(options) { /** * Appends new custom $graphLookup operator(s) to this aggregate pipeline, performing a recursive search on a collection. - * - * NOTE: graphLookup can only consume at most 100MB of memory, and does not allow disk use even if `{ allowDiskUse: true }` is specified. - * + * + * NOTE: graphLookup can only consume at most 100MB of memory, and does not allow disk use even if `{ allowDiskUse: true }` is specified. + * * #### Examples: * // Suppose we have a collection of courses, where a document might look like `{ _id: 0, name: 'Calculus', prerequisite: 'Trigonometry'}` and `{ _id: 0, name: 'Trigonometry', prerequisite: 'Algebra' }` * aggregate.graphLookup({ from: 'courses', startWith: '$prerequisite', connectFromField: 'prerequisite', connectToField: 'name', as: 'prerequisites', maxDepth: 3 }) // this will recursively search the 'courses' collection up to 3 prerequisites - * + * * @see $graphLookup https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/#pipe._S_graphLookup * @param {Object} options to $graphLookup as described in the above link * @return {Aggregate} @@ -335,7 +335,7 @@ Aggregate.prototype.graphLookup = function(options) { cloneOptions = utils.merge({}, options); var startWith = cloneOptions.startWith; - + if (startWith && typeof startWith === 'string') { cloneOptions.startWith = cloneOptions.startWith.charAt(0) === '$' ? cloneOptions.startWith : diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 162ea73e5c4..f0fe613504f 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -37,7 +37,7 @@ module.exports = function(query, schema, castedDoc, options) { for (var j = 0; j < numPaths; ++j) { var updatedPath = paths[j].replace('.$.', '.0.'); updatedPath = updatedPath.replace(/\.\$$/, '.0'); - if (keys[i] === '$set' || keys[i] === '$setOnInsert') { + if (keys[i] === '$set' || keys[i] === '$setOnInsert' || keys[i] === '$push') { updatedValues[updatedPath] = flat[paths[j]]; } else if (keys[i] === '$unset') { updatedValues[updatedPath] = undefined; diff --git a/test/model.test.js b/test/model.test.js index 86ac83e933b..c424f25cff6 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5223,29 +5223,45 @@ describe('Model', function() { }); it('insertMany() ordered option (gh-3893)', function(done) { - var schema = new Schema({ - name: { type: String, unique: true } + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + done(); + return; + } + + test(); }); - var Movie = db.model('gh3893', schema); - var arr = [ - { name: 'Star Wars' }, - { name: 'Star Wars' }, - { name: 'The Empire Strikes Back' } - ]; - Movie.on('index', function(error) { - assert.ifError(error); - Movie.insertMany(arr, { ordered: false }, function(error) { - assert.equal(error.message.indexOf('E11000'), 0); - Movie.find({}).sort({ name: 1 }).exec(function(error, docs) { - assert.ifError(error); - assert.equal(docs.length, 2); - assert.equal(docs[0].name, 'Star Wars'); - assert.equal(docs[1].name, 'The Empire Strikes Back'); - done(); + function test() { + var schema = new Schema({ + name: { type: String, unique: true } + }); + var Movie = db.model('gh3893', schema); + + var arr = [ + { name: 'Star Wars' }, + { name: 'Star Wars' }, + { name: 'The Empire Strikes Back' } + ]; + Movie.on('index', function(error) { + assert.ifError(error); + Movie.insertMany(arr, { ordered: false }, function(error) { + assert.equal(error.message.indexOf('E11000'), 0); + Movie.find({}).sort({ name: 1 }).exec(function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 2); + assert.equal(docs[0].name, 'Star Wars'); + assert.equal(docs[1].name, 'The Empire Strikes Back'); + done(); + }); }); }); - }); + } }); it('insertMany() hooks (gh-3846)', function(done) { From 5e7dafa39286b081d214a547cca801b165bc037c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Jan 2017 10:25:50 -0700 Subject: [PATCH 1152/2240] chore: remove stray code --- lib/services/updateValidators.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index f0fe613504f..162ea73e5c4 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -37,7 +37,7 @@ module.exports = function(query, schema, castedDoc, options) { for (var j = 0; j < numPaths; ++j) { var updatedPath = paths[j].replace('.$.', '.0.'); updatedPath = updatedPath.replace(/\.\$$/, '.0'); - if (keys[i] === '$set' || keys[i] === '$setOnInsert' || keys[i] === '$push') { + if (keys[i] === '$set' || keys[i] === '$setOnInsert') { updatedValues[updatedPath] = flat[paths[j]]; } else if (keys[i] === '$unset') { updatedValues[updatedPath] = undefined; From aa9b0c6a46b417057eb803df1abed92cd436d01b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Jan 2017 12:21:36 -0700 Subject: [PATCH 1153/2240] feat(query): support push and addToSet for update validators Fix #2933 --- lib/schematype.js | 6 ++-- lib/services/updateValidators.js | 62 ++++++++++++++++++++++++++++++-- test/docs/validation.test.js | 35 ++++++++++++++++-- 3 files changed, 95 insertions(+), 8 deletions(-) diff --git a/lib/schematype.js b/lib/schematype.js index 3ca3423618b..15d7d3ac9a3 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -686,9 +686,9 @@ SchemaType.prototype.select = function select(val) { */ SchemaType.prototype.doValidate = function(value, fn, scope) { - var err = false, - path = this.path, - count = this.validators.length; + var err = false; + var path = this.path; + var count = this.validators.length; if (!count) { return fn(null); diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 162ea73e5c4..ee7948aa310 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -21,15 +21,30 @@ var modifiedPaths = require('./common').modifiedPaths; */ module.exports = function(query, schema, castedDoc, options) { + var _keys; var keys = Object.keys(castedDoc || {}); var updatedKeys = {}; var updatedValues = {}; + var arrayAtomicUpdates = {}; var numKeys = keys.length; var hasDollarUpdate = false; var modified = {}; for (var i = 0; i < numKeys; ++i) { if (keys[i].charAt(0) === '$') { + if (keys[i] === '$push') { + _keys = Object.keys(castedDoc[keys[i]]); + for (var ii = 0; ii < _keys.length; ++ii) { + if (castedDoc[keys[i]][_keys[ii]].$each) { + arrayAtomicUpdates[_keys[ii]] = (arrayAtomicUpdates[_keys[ii]] || []). + concat(castedDoc[keys[i]][_keys[ii]].$each); + } else { + arrayAtomicUpdates[_keys[ii]] = (arrayAtomicUpdates[_keys[ii]] || []). + concat([castedDoc[keys[i]][_keys[ii]]]); + } + } + continue; + } modifiedPaths(castedDoc[keys[i]], '', modified); var flat = flatten(castedDoc[keys[i]]); var paths = Object.keys(flat); @@ -58,7 +73,7 @@ module.exports = function(query, schema, castedDoc, options) { var numUpdates = updates.length; var validatorsToExecute = []; var validationErrors = []; - function iter(i) { + function iter(i, v) { var schemaPath = schema._getSchema(updates[i]); if (schemaPath) { // gh-4305: `_getSchema()` will report all sub-fields of a 'Mixed' path @@ -68,7 +83,7 @@ module.exports = function(query, schema, castedDoc, options) { } validatorsToExecute.push(function(callback) { schemaPath.doValidate( - updatedValues[updates[i]], + v, function(err) { if (err) { err.path = updates[i]; @@ -82,7 +97,48 @@ module.exports = function(query, schema, castedDoc, options) { } } for (i = 0; i < numUpdates; ++i) { - iter(i); + iter(i, updatedValues[updates[i]]); + } + + var arrayUpdates = Object.keys(arrayAtomicUpdates); + var numArrayUpdates = arrayUpdates.length; + for (i = 0; i < numArrayUpdates; ++i) { + (function(i) { + var schemaPath = schema._getSchema(arrayUpdates[i]); + if (schemaPath.$isMongooseDocumentArray) { + validatorsToExecute.push(function(callback) { + schemaPath.doValidate( + arrayAtomicUpdates[arrayUpdates[i]], + function(err) { + if (err) { + err.path = arrayUpdates[i]; + validationErrors.push(err); + } + callback(null); + }, + options && options.context === 'query' ? query : null); + }); + } else { + schemaPath = schema._getSchema(arrayUpdates[i] + '.0'); + for (var j = 0; j < arrayAtomicUpdates[arrayUpdates[i]].length; ++j) { + (function(j) { + validatorsToExecute.push(function(callback) { + schemaPath.doValidate( + arrayAtomicUpdates[arrayUpdates[i]][j], + function(err) { + if (err) { + err.path = arrayUpdates[i]; + validationErrors.push(err); + } + callback(null); + }, + options && options.context === 'query' ? query : null, + { updateValidator: true }); + }); + })(j); + } + } + })(i); } return function(callback) { diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index dc13bb1f052..260b8891579 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -416,8 +416,9 @@ describe('validation docs', function() { /** * One final detail worth noting: update validators **only** run on `$set` - * and `$unset` operations. For instance, the below update will succeed, - * regardless of the value of `number`. + * and `$unset` operations (and `$push` and `$addToSet` in >= 4.8.0). + * For instance, the below update will succeed, regardless of the value of + * `number`, because update validators ignore `$inc`. */ it('Update Validators Only Run On Specified Paths', function(done) { @@ -437,4 +438,34 @@ describe('validation docs', function() { // acquit:ignore:end }); }); + + /** + * New in 4.8.0: update validators also run on `$push` and `$addToSet` + */ + + it('On $push and $addToSet', function(done) { + var testSchema = new Schema({ + numbers: [{ type: Number, max: 0 }], + docs: [{ + name: { type: String, required: true } + }] + }); + + var Test = db.model('TestPush', testSchema); + + var update = { + $push: { + numbers: 1, + docs: { name: null } + } + }; + var opts = { runValidators: true }; + Test.update({}, update, opts, function(error) { + assert.ok(error.errors['numbers']); + assert.ok(error.errors['docs']); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); }); From 370ac04704c29b1b1db18638f466133df04c4c65 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Jan 2017 12:25:11 -0700 Subject: [PATCH 1154/2240] chore: upgrade bson dep to match mongodb-core --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5a544c44d10..00437efd972 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "license": "MIT", "dependencies": { "async": "2.1.4", - "bson": "~1.0.1", + "bson": "~1.0.4", "hooks-fixed": "1.2.0", "kareem": "1.2.0", "mongodb": "2.2.20", From 066f12886624583d0a1053120e454004c8c710a1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Jan 2017 12:26:23 -0700 Subject: [PATCH 1155/2240] chore: upgrade mongodb -> 2.2.21 Fix #4867 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 00437efd972..67be03c4c5a 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "1.2.0", "kareem": "1.2.0", - "mongodb": "2.2.20", + "mongodb": "2.2.21", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.0.0", From 4efecd50257352b8ec0fe048f06ccddae8d28fb3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Jan 2017 12:38:09 -0700 Subject: [PATCH 1156/2240] fix(utils): don't crash if to[key] is null Fix #4881 --- lib/model.js | 2 +- lib/utils.js | 8 ++++---- test/collection.capped.test.js | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index 789a0b31159..c706213a1af 100644 --- a/lib/model.js +++ b/lib/model.js @@ -811,7 +811,7 @@ Model.discriminator = function discriminator(name, schema) { } function merge(schema, baseSchema) { - utils.merge(schema, baseSchema); + utils.merge(schema, baseSchema, { retainKeyOrder: true }); var obj = {}; obj[key] = { diff --git a/lib/utils.js b/lib/utils.js index 2b44bd617c6..f09c4343daa 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -390,10 +390,10 @@ exports.merge = function merge(to, from, options) { if (options.retainKeyOrder) { while (i < len) { key = keys[i++]; - if (typeof to[key] === 'undefined') { + if (to[key] == null) { to[key] = from[key]; } else if (exports.isObject(from[key])) { - merge(to[key], from[key]); + merge(to[key], from[key], options); } else if (options.overwrite) { to[key] = from[key]; } @@ -401,10 +401,10 @@ exports.merge = function merge(to, from, options) { } else { while (len--) { key = keys[len]; - if (typeof to[key] === 'undefined') { + if (to[key] == null) { to[key] = from[key]; } else if (exports.isObject(from[key])) { - merge(to[key], from[key]); + merge(to[key], from[key], options); } else if (options.overwrite) { to[key] = from[key]; } diff --git a/test/collection.capped.test.js b/test/collection.capped.test.js index db76aca06b8..9650f121a28 100644 --- a/test/collection.capped.test.js +++ b/test/collection.capped.test.js @@ -63,7 +63,7 @@ describe('collections: capped:', function() { }); it('attempting to use existing non-capped collection as capped emits error', function(done) { db = start(); - var opts = {safe: true}; + var opts = {}; var conn = 'capped_existing_' + random(); db.on('open', function() { From b412210dc7f434e3474813527c81f862faecfc4a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Jan 2017 20:51:06 -0700 Subject: [PATCH 1157/2240] test(populate): repro #4581 --- test/model.populate.test.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index f1c386e96bb..c20bc3d42d2 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4700,6 +4700,43 @@ describe('model: populate:', function() { }); }); + it('handles nested virtuals (gh-4851)', function(done) { + var AuthorSchema = new Schema({ name: String }); + + var BookSchema = new Schema({ + title: String, + author: { id: mongoose.Schema.Types.ObjectId } + }); + + BookSchema.virtual('author.doc', { + ref: 'Author', + foreignField: '_id', + localField: 'author.id', + justOne: true + }); + + var Author = db.model('Author', AuthorSchema); + var Book = db.model('Book', BookSchema); + + Author.create({ name: 'Val' }). + then(function(author) { + return Book.create({ + title: 'Professional AngularJS', + author: { id: author._id } + }); + }). + then(function(book) { + return Book.findById(book).populate('author.doc'); + }). + then(function(doc) { + assert.equal(doc.author.doc.name, 'Val'); + doc = doc.toObject({ virtuals: true }); + assert.equal(doc.author.doc.name, 'Val'); + done(); + }). + catch(done); + }); + it('virtual populate in single nested doc (gh-4715)', function(done) { var someModelSchema = new mongoose.Schema({ name: String From 0504ec6881b0872046a9b16885a51af4140c3278 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Jan 2017 20:51:26 -0700 Subject: [PATCH 1158/2240] fix(populate): handle nested virtuals in virtual populate Fix #4851 --- lib/schema.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index 30a4a9fd797..5defe4859c9 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1507,6 +1507,9 @@ Schema.prototype._getVirtual = function(name) { */ function _getVirtual(schema, name) { + if (schema.virtuals[name]) { + return schema.virtuals[name]; + } var parts = name.split('.'); var cur = ''; var nestedSchemaPath = ''; From 66d559b19a86c70e30a8f083d03eb22566571b7e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 15 Jan 2017 19:51:55 -0700 Subject: [PATCH 1159/2240] chore: release 4.7.7 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index de774635bfc..2477a60c8f7 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.7.7 / 2017-01-15 +================== + * fix(utils): don't crash if to[key] is null #4881 + * fix: upgrade mongodb -> 2.2.21 #4867 + * fix: add a toBSON to documents for easier querying #4866 + * fix: suppress bluebird warning #4854 [davidwu226](https://github.com/davidwu226) + * fix(populate): handle nested virtuals in virtual populate #4851 + 4.7.6 / 2017-01-02 ================== * fix(model): allow passing non-array to insertMany #4846 diff --git a/package.json b/package.json index 67be03c4c5a..4fb64490fc4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.7-pre", + "version": "4.7.7", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From f93e16755ce2d3516916988ea9329afd598be9b9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Jan 2017 10:30:34 -0700 Subject: [PATCH 1160/2240] chore: now working on 4.7.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4fb64490fc4..a24c23a9175 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.7", + "version": "4.7.8-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 596572ea42efba7c7e9abbb8093b5ca381388fb2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Jan 2017 10:45:42 -0700 Subject: [PATCH 1161/2240] fix: upgrade muri -> 1.2.0 Re: aheckmann/muri#9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a24c23a9175..e2ab79ca6e4 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "mpromise": "0.5.5", "mquery": "2.0.0", "ms": "0.7.2", - "muri": "1.1.1", + "muri": "1.2.0", "regexp-clone": "0.0.1", "sliced": "1.0.1" }, From 73769b4ebd0f258e1cf8dc0a1be74c2f602e4196 Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Mon, 16 Jan 2017 20:09:25 -0500 Subject: [PATCH 1162/2240] test(aggregate): Add graphLookup tests without exec --- .gitignore | 3 +++ lib/aggregate.js | 2 +- test/aggregate.test.js | 44 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c9eae254b4c..00dc9ca998a 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ npm-debug.log *.ntvs* *.njsproj *.sln + +# Visual STudio Code +.vscode diff --git a/lib/aggregate.js b/lib/aggregate.js index 28aa712a167..6424b383018 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -333,7 +333,7 @@ Aggregate.prototype.graphLookup = function(options) { throw new TypeError('Invalid graphLookup() argument. Must be an object.'); } - cloneOptions = utils.merge({}, options); + utils.mergeClone(cloneOptions, options); var startWith = cloneOptions.startWith; if (startWith && typeof startWith === 'string') { diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 6c240a719b3..1225fb0d823 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -377,6 +377,50 @@ describe('aggregate: ', function() { }); }); + describe('graphLookup', function() { + it('works', function(done) { + var aggregate = new Aggregate(); + aggregate.graphLookup({ + startWith: '$test', + from: 'sourceCollection', + connectFromField: 'testFromField', + connectToField: '_id' + }); + + assert.equal(aggregate._pipeline.length, 1); + assert.deepEqual(aggregate._pipeline[0].$graphLookup, { + startWith: '$test', + from: 'sourceCollection', + connectFromField: 'testFromField', + connectToField: '_id' + }); + done(); + }); + + it('automatically prepends $ to the startWith field', function(done) { + var aggregate = new Aggregate(); + aggregate.graphLookup({ + startWith: 'test' + }); + + assert.deepEqual(aggregate._pipeline[0].$graphLookup, { + startWith: '$test' + }); + done(); + }); + + it('Throws if no options are passed to graphLookup', function(done) { + var aggregate = new Aggregate(); + try { + aggregate.graphLookup('invalid options'); + done(new Error('Should have errored')); + } catch (error) { + assert.ok(error instanceof TypeError); + done(); + } + }); + }); + describe('exec', function() { var db; From 1ddadf82b080b80c0a332a9dde90a0e053e24d5f Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Mon, 16 Jan 2017 23:43:29 -0500 Subject: [PATCH 1163/2240] test(aggregate): add tests for graph lookup with exec --- test/aggregate.test.js | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 1225fb0d823..665dd4bf3fc 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -16,7 +16,8 @@ var EmployeeSchema = new Schema({ name: String, sal: Number, dept: String, - customers: [String] + customers: [String], + reportsTo: String }); mongoose.model('Employee', EmployeeSchema); @@ -25,9 +26,9 @@ function setupData(callback) { var saved = 0, emps = [ {name: 'Alice', sal: 18000, dept: 'sales', customers: ['Eve', 'Fred']}, - {name: 'Bob', sal: 15000, dept: 'sales', customers: ['Gary', 'Herbert', 'Isaac']}, - {name: 'Carol', sal: 14000, dept: 'r&d'}, - {name: 'Dave', sal: 14500, dept: 'r&d'} + {name: 'Bob', sal: 15000, dept: 'sales', customers: ['Gary', 'Herbert', 'Isaac'], reportsTo: 'Alice'}, + {name: 'Carol', sal: 14000, dept: 'r&d', reportsTo: 'Bob'}, + {name: 'Dave', sal: 14500, dept: 'r&d', reportsTo: 'Carol'} ], db = start(), Employee = db.model('Employee'); @@ -570,6 +571,33 @@ describe('aggregate: ', function() { }); }); + it('graphLookup', function(done) { + var aggregate = new Aggregate(); + + aggregate. + model(db.model('Employee')). + graphLookup({ + from: 'employees', + startWith: '$reportsTo', + connectFromField: 'reportsTo', + connectToField: 'name', + as: 'employeeHierarchy' + }). + exec(function(err, docs) { + if (err) { + return done(err); + } + var lowest = docs[3]; + assert.equal(lowest.employeeHierarchy.length, 3); + + // First result in array is max depth result + assert.equal(lowest.employeeHierarchy[0].name, 'Alice'); + assert.equal(lowest.employeeHierarchy[2].name, 'Carol'); + done(); + }); + + }); + it('complex pipeline', function(done) { var aggregate = new Aggregate(); From b14956008a282ca960a5bdd81cf29f36dc16c460 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Jan 2017 10:54:54 -0700 Subject: [PATCH 1164/2240] style: fix lint --- test/aggregate.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 665dd4bf3fc..2d72c1e8cf2 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -403,7 +403,7 @@ describe('aggregate: ', function() { aggregate.graphLookup({ startWith: 'test' }); - + assert.deepEqual(aggregate._pipeline[0].$graphLookup, { startWith: '$test' }); @@ -595,7 +595,7 @@ describe('aggregate: ', function() { assert.equal(lowest.employeeHierarchy[2].name, 'Carol'); done(); }); - + }); it('complex pipeline', function(done) { From 266076ebf405eb0380169ca47ed41ac492937812 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Jan 2017 11:09:41 -0700 Subject: [PATCH 1165/2240] refactor(model): move discriminator to its own file --- lib/model.js | 156 +--------------------------- lib/services/model/applyMethods.js | 34 ++++++ lib/services/model/applyStatics.js | 12 +++ lib/services/model/discriminator.js | 120 +++++++++++++++++++++ 4 files changed, 171 insertions(+), 151 deletions(-) create mode 100644 lib/services/model/applyMethods.js create mode 100644 lib/services/model/applyStatics.js create mode 100644 lib/services/model/discriminator.js diff --git a/lib/model.js b/lib/model.js index ac5cbcda62d..047fa44c508 100644 --- a/lib/model.js +++ b/lib/model.js @@ -7,12 +7,14 @@ var Document = require('./document'); var DocumentNotFoundError = require('./error/notFound'); var DivergentArrayError = require('./error').DivergentArrayError; var EventEmitter = require('events').EventEmitter; -var OverwriteModelError = require('./error').OverwriteModelError; var PromiseProvider = require('./promise_provider'); var Query = require('./query'); var Schema = require('./schema'); var VersionError = require('./error').VersionError; var applyHooks = require('./services/model/applyHooks'); +var applyMethods = require('./services/model/applyMethods'); +var applyStatics = require('./services/model/applyStatics'); +var discriminator = require('./services/model/discriminator'); var parallel = require('async/parallel'); var util = require('util'); var utils = require('./utils'); @@ -820,113 +822,8 @@ Model.prototype.model = function model(name) { * @api public */ -Model.discriminator = function discriminator(name, schema) { - var CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = { - toJSON: true, - toObject: true, - _id: true, - id: true - }; - - if (!(schema && schema.instanceOfSchema)) { - throw new Error('You must pass a valid discriminator Schema'); - } - - if (this.schema.discriminatorMapping && !this.schema.discriminatorMapping.isRoot) { - throw new Error('Discriminator "' + name + - '" can only be a discriminator of the root model'); - } - - var key = this.schema.options.discriminatorKey; - if (schema.path(key)) { - throw new Error('Discriminator "' + name + - '" cannot have field with name "' + key + '"'); - } - - function merge(schema, baseSchema) { - utils.merge(schema, baseSchema, { retainKeyOrder: true }); - - var obj = {}; - obj[key] = { - default: name, - set: function(newName) { - if (newName === name) { - return name; - } - throw new Error('Can\'t set discriminator key "' + key + '"'); - } - }; - obj[key][schema.options.typeKey] = String; - schema.add(obj); - schema.discriminatorMapping = {key: key, value: name, isRoot: false}; - - if (baseSchema.options.collection) { - schema.options.collection = baseSchema.options.collection; - } - - var toJSON = schema.options.toJSON; - var toObject = schema.options.toObject; - var _id = schema.options._id; - var id = schema.options.id; - - var keys = Object.keys(schema.options); - schema.options.discriminatorKey = baseSchema.options.discriminatorKey; - - for (var i = 0; i < keys.length; ++i) { - var _key = keys[i]; - if (!CUSTOMIZABLE_DISCRIMINATOR_OPTIONS[_key]) { - if (!utils.deepEqual(schema.options[_key], baseSchema.options[_key])) { - throw new Error('Can\'t customize discriminator option ' + _key + - ' (can only modify ' + - Object.keys(CUSTOMIZABLE_DISCRIMINATOR_OPTIONS).join(', ') + - ')'); - } - } - } - - schema.options = utils.clone(baseSchema.options); - if (toJSON) schema.options.toJSON = toJSON; - if (toObject) schema.options.toObject = toObject; - if (typeof _id !== 'undefined') { - schema.options._id = _id; - } - schema.options.id = id; - - schema.callQueue = baseSchema.callQueue.concat(schema.callQueue.slice(schema._defaultMiddleware.length)); - schema._requiredpaths = undefined; // reset just in case Schema#requiredPaths() was called on either schema - } - - // merges base schema into new discriminator schema and sets new type field. - merge(schema, this.schema); - - if (!this.discriminators) { - this.discriminators = {}; - } - - if (!this.schema.discriminatorMapping) { - this.schema.discriminatorMapping = {key: key, value: null, isRoot: true}; - } - - if (this.discriminators[name]) { - throw new Error('Discriminator with name "' + name + '" already exists'); - } - if (this.db.models[name]) { - throw new OverwriteModelError(name); - } - - this.discriminators[name] = this.db.model(name, schema, this.collection.name); - this.discriminators[name].prototype.__proto__ = this.prototype; - Object.defineProperty(this.discriminators[name], 'baseModelName', { - value: this.modelName, - configurable: true, - writable: false - }); - - // apply methods and statics - applyMethods(this.discriminators[name], schema); - applyStatics(this.discriminators[name], schema); - - return this.discriminators[name]; +Model.discriminator = function(name, schema) { + return discriminator(this, name, schema); }; // Model (class) features @@ -3405,49 +3302,6 @@ Model.compile = function compile(name, schema, collectionName, connection, base) return model; }; -/*! - * Register methods for this model - * - * @param {Model} model - * @param {Schema} schema - */ -var applyMethods = function(model, schema) { - function apply(method, schema) { - Object.defineProperty(model.prototype, method, { - get: function() { - var h = {}; - for (var k in schema.methods[method]) { - h[k] = schema.methods[method][k].bind(this); - } - return h; - }, - configurable: true - }); - } - for (var method in schema.methods) { - if (schema.tree.hasOwnProperty(method)) { - throw new Error('You have a method and a property in your schema both ' + - 'named "' + method + '"'); - } - if (typeof schema.methods[method] === 'function') { - model.prototype[method] = schema.methods[method]; - } else { - apply(method, schema); - } - } -}; - -/*! - * Register statics for this model - * @param {Model} model - * @param {Schema} schema - */ -var applyStatics = function(model, schema) { - for (var i in schema.statics) { - model[i] = schema.statics[i]; - } -}; - /*! * Register custom query methods for this model * diff --git a/lib/services/model/applyMethods.js b/lib/services/model/applyMethods.js new file mode 100644 index 00000000000..14c2e29607a --- /dev/null +++ b/lib/services/model/applyMethods.js @@ -0,0 +1,34 @@ +'use strict'; + +/*! + * Register methods for this model + * + * @param {Model} model + * @param {Schema} schema + */ + +module.exports = function applyMethods(model, schema) { + function apply(method, schema) { + Object.defineProperty(model.prototype, method, { + get: function() { + var h = {}; + for (var k in schema.methods[method]) { + h[k] = schema.methods[method][k].bind(this); + } + return h; + }, + configurable: true + }); + } + for (var method in schema.methods) { + if (schema.tree.hasOwnProperty(method)) { + throw new Error('You have a method and a property in your schema both ' + + 'named "' + method + '"'); + } + if (typeof schema.methods[method] === 'function') { + model.prototype[method] = schema.methods[method]; + } else { + apply(method, schema); + } + } +}; diff --git a/lib/services/model/applyStatics.js b/lib/services/model/applyStatics.js new file mode 100644 index 00000000000..1c24dbc18c7 --- /dev/null +++ b/lib/services/model/applyStatics.js @@ -0,0 +1,12 @@ +'use strict'; + +/*! + * Register statics for this model + * @param {Model} model + * @param {Schema} schema + */ +module.exports = function applyStatics(model, schema) { + for (var i in schema.statics) { + model[i] = schema.statics[i]; + } +}; diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js new file mode 100644 index 00000000000..54e71b8f4a6 --- /dev/null +++ b/lib/services/model/discriminator.js @@ -0,0 +1,120 @@ +'use strict'; + +var OverwriteModelError = require('../../error').OverwriteModelError; +var applyMethods = require('./applyMethods'); +var applyStatics = require('./applyStatics'); +var utils = require('../../utils'); + +var CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = { + toJSON: true, + toObject: true, + _id: true, + id: true +}; + +/*! + * ignore + */ + +module.exports = function discriminator(model, name, schema) { + if (!(schema && schema.instanceOfSchema)) { + throw new Error('You must pass a valid discriminator Schema'); + } + + if (model.schema.discriminatorMapping && + !model.schema.discriminatorMapping.isRoot) { + throw new Error('Discriminator "' + name + + '" can only be a discriminator of the root model'); + } + + var key = model.schema.options.discriminatorKey; + if (schema.path(key)) { + throw new Error('Discriminator "' + name + + '" cannot have field with name "' + key + '"'); + } + + function merge(schema, baseSchema) { + utils.merge(schema, baseSchema, { retainKeyOrder: true }); + + var obj = {}; + obj[key] = { + default: name, + set: function(newName) { + if (newName === name) { + return name; + } + throw new Error('Can\'t set discriminator key "' + key + '"'); + } + }; + obj[key][schema.options.typeKey] = String; + schema.add(obj); + schema.discriminatorMapping = {key: key, value: name, isRoot: false}; + + if (baseSchema.options.collection) { + schema.options.collection = baseSchema.options.collection; + } + + var toJSON = schema.options.toJSON; + var toObject = schema.options.toObject; + var _id = schema.options._id; + var id = schema.options.id; + + var keys = Object.keys(schema.options); + schema.options.discriminatorKey = baseSchema.options.discriminatorKey; + + for (var i = 0; i < keys.length; ++i) { + var _key = keys[i]; + if (!CUSTOMIZABLE_DISCRIMINATOR_OPTIONS[_key]) { + if (!utils.deepEqual(schema.options[_key], baseSchema.options[_key])) { + throw new Error('Can\'t customize discriminator option ' + _key + + ' (can only modify ' + + Object.keys(CUSTOMIZABLE_DISCRIMINATOR_OPTIONS).join(', ') + + ')'); + } + } + } + + schema.options = utils.clone(baseSchema.options); + if (toJSON) schema.options.toJSON = toJSON; + if (toObject) schema.options.toObject = toObject; + if (typeof _id !== 'undefined') { + schema.options._id = _id; + } + schema.options.id = id; + + schema.callQueue = baseSchema.callQueue.concat(schema.callQueue.slice(schema._defaultMiddleware.length)); + schema._requiredpaths = undefined; // reset just in case Schema#requiredPaths() was called on either schema + } + + // merges base schema into new discriminator schema and sets new type field. + merge(schema, model.schema); + + if (!model.discriminators) { + model.discriminators = {}; + } + + if (!model.schema.discriminatorMapping) { + model.schema.discriminatorMapping = {key: key, value: null, isRoot: true}; + } + + if (model.discriminators[name]) { + throw new Error('Discriminator with name "' + name + '" already exists'); + } + if (model.db.models[name]) { + throw new OverwriteModelError(name); + } + + model.discriminators[name] = model.db.model(name, schema, model.collection.name); + model.discriminators[name].prototype.__proto__ = model.prototype; + Object.defineProperty(model.discriminators[name], 'baseModelName', { + value: model.modelName, + configurable: true, + writable: false + }); + + // apply methods and statics + applyMethods(model.discriminators[name], schema); + applyStatics(model.discriminators[name], schema); + + return model.discriminators[name]; +}; From 4af01f19979eaedec2ac9c22852ce18c791606cd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Jan 2017 12:07:13 -0700 Subject: [PATCH 1166/2240] feat(discriminator): basic PoC for document array discriminators Re: #2723 #1856 --- lib/model.js | 21 ++++++- lib/schema/documentarray.js | 93 +++++++++++++++++++---------- lib/services/model/discriminator.js | 20 ------- test/model.discriminator.test.js | 53 ++++++++++++++++ 4 files changed, 136 insertions(+), 51 deletions(-) diff --git a/lib/model.js b/lib/model.js index 047fa44c508..b4e421816ea 100644 --- a/lib/model.js +++ b/lib/model.js @@ -7,6 +7,7 @@ var Document = require('./document'); var DocumentNotFoundError = require('./error/notFound'); var DivergentArrayError = require('./error').DivergentArrayError; var EventEmitter = require('events').EventEmitter; +var OverwriteModelError = require('./error').OverwriteModelError; var PromiseProvider = require('./promise_provider'); var Query = require('./query'); var Schema = require('./schema'); @@ -823,7 +824,25 @@ Model.prototype.model = function model(name) { */ Model.discriminator = function(name, schema) { - return discriminator(this, name, schema); + discriminator(this, name, schema); + if (this.db.models[name]) { + throw new OverwriteModelError(name); + } + + this.discriminators[name] = this.db.model(name, schema, this.collection.name); + var d = this.discriminators[name]; + d.prototype.__proto__ = this.prototype; + Object.defineProperty(d, 'baseModelName', { + value: this.modelName, + configurable: true, + writable: false + }); + + // apply methods and statics + applyMethods(d, schema); + applyStatics(d, schema); + + return d; }; // Model (class) features diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index aa08d4e8f96..58bd88691df 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -11,6 +11,7 @@ var MongooseDocumentArray = require('../types/documentarray'); var SchemaType = require('../schematype'); var Subdocument = require('../types/embedded'); var applyHooks = require('../services/model/applyHooks'); +var discriminator = require('../services/model/discriminator'); var util = require('util'); /** @@ -24,6 +25,45 @@ var util = require('util'); */ function DocumentArray(key, schema, options) { + var EmbeddedDocument = _createConstructor(schema, options); + + ArrayType.call(this, key, EmbeddedDocument, options); + + this.schema = schema; + this.$isMongooseDocumentArray = true; + var fn = this.defaultValue; + + if (!('defaultValue' in this) || fn !== void 0) { + this.default(function() { + var arr = fn.call(this); + if (!Array.isArray(arr)) { + arr = [arr]; + } + // Leave it up to `cast()` to convert this to a documentarray + return arr; + }); + } +} + +/** + * This schema type's name, to defend against minifiers that mangle + * function names. + * + * @api public + */ +DocumentArray.schemaName = 'DocumentArray'; + +/*! + * Inherits from ArrayType. + */ +DocumentArray.prototype = Object.create(ArrayType.prototype); +DocumentArray.prototype.constructor = DocumentArray; + +/*! + * Ignore + */ + +function _createConstructor(schema, options) { // compile an embedded document for this schema function EmbeddedDocument() { Subdocument.apply(this, arguments); @@ -53,37 +93,22 @@ function DocumentArray(key, schema, options) { EmbeddedDocument.options = options; - ArrayType.call(this, key, EmbeddedDocument, options); - - this.schema = schema; - this.$isMongooseDocumentArray = true; - var fn = this.defaultValue; - - if (!('defaultValue' in this) || fn !== void 0) { - this.default(function() { - var arr = fn.call(this); - if (!Array.isArray(arr)) { - arr = [arr]; - } - // Leave it up to `cast()` to convert this to a documentarray - return arr; - }); - } + return EmbeddedDocument; } -/** - * This schema type's name, to defend against minifiers that mangle - * function names. - * - * @api public - */ -DocumentArray.schemaName = 'DocumentArray'; - /*! - * Inherits from ArrayType. + * Ignore */ -DocumentArray.prototype = Object.create(ArrayType.prototype); -DocumentArray.prototype.constructor = DocumentArray; + +DocumentArray.prototype.discriminator = function(name, schema) { + discriminator(this.casterConstructor, name, schema); + + var EmbeddedDocument = _createConstructor(schema); + + this.casterConstructor.discriminators[name] = EmbeddedDocument; + + return this.casterConstructor.discriminators[name]; +}; /** * Performs local validations first, then validations on each embedded doc @@ -236,9 +261,17 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { if (!value[i]) { continue; } + + var Constructor = this.casterConstructor; + if (Constructor.discriminators && + typeof value[i][Constructor.schema.options.discriminatorKey] === 'string' && + Constructor.discriminators[value[i][Constructor.schema.options.discriminatorKey]]) { + Constructor = Constructor.discriminators[value[i][Constructor.schema.options.discriminatorKey]]; + } + // Check if the document has a different schema (re gh-3701) if ((value[i] instanceof Subdocument) && - value[i].schema !== this.casterConstructor.schema) { + value[i].schema !== Constructor.schema) { value[i] = value[i].toObject({ transform: false, virtuals: false }); } if (!(value[i] instanceof Subdocument) && value[i]) { @@ -249,7 +282,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { selected = true; } - subdoc = new this.casterConstructor(null, value, true, selected, i); + subdoc = new Constructor(null, value, true, selected, i); value[i] = subdoc.init(value[i]); } else { if (prev && (subdoc = prev.id(value[i]._id))) { @@ -265,7 +298,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { value[i] = subdoc; } else { try { - subdoc = new this.casterConstructor(value[i], value, undefined, + subdoc = new Constructor(value[i], value, undefined, undefined, i); // if set() is hooked it will have no return value // see gh-746 diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 54e71b8f4a6..52b36c4593d 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -1,8 +1,5 @@ 'use strict'; -var OverwriteModelError = require('../../error').OverwriteModelError; -var applyMethods = require('./applyMethods'); -var applyStatics = require('./applyStatics'); var utils = require('../../utils'); var CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = { @@ -100,21 +97,4 @@ module.exports = function discriminator(model, name, schema) { if (model.discriminators[name]) { throw new Error('Discriminator with name "' + name + '" already exists'); } - if (model.db.models[name]) { - throw new OverwriteModelError(name); - } - - model.discriminators[name] = model.db.model(name, schema, model.collection.name); - model.discriminators[name].prototype.__proto__ = model.prototype; - Object.defineProperty(model.discriminators[name], 'baseModelName', { - value: model.modelName, - configurable: true, - writable: false - }); - - // apply methods and statics - applyMethods(model.discriminators[name], schema); - applyStatics(model.discriminators[name], schema); - - return model.discriminators[name]; }; diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 92ec539de43..6653ec75d9e 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -378,6 +378,59 @@ describe('model', function() { done(); }); }); + + it('embedded in document arrays (gh-2723)', function(done) { + var eventSchema = new Schema({ message: String }, + { discriminatorKey: 'kind', _id: false }); + + var batchSchema = new Schema({ events: [eventSchema] }); + batchSchema.path('events').discriminator('Clicked', new Schema({ + element: String + }, { _id: false })); + batchSchema.path('events').discriminator('Purchased', new Schema({ + product: String + }, { _id: false })); + + var MyModel = db.model('gh2723', batchSchema); + var doc = { + events: [ + { kind: 'Clicked', element: 'Test' }, + { kind: 'Purchased', product: 'Test2' } + ] + }; + MyModel.create(doc). + then(function(doc) { + assert.equal(doc.events.length, 2); + assert.equal(doc.events[0].element, 'Test'); + assert.equal(doc.events[1].product, 'Test2'); + var obj = doc.toObject({ virtuals: false }); + delete obj._id; + assert.deepEqual(obj, { + __v: 0, + events: [ + { kind: 'Clicked', element: 'Test' }, + { kind: 'Purchased', product: 'Test2' } + ] + }); + done(); + }). + then(function() { + return MyModel.findOne({ + events: { + $elemMatch: { + kind: 'Clicked', + element: 'Test' + } + } + }, { 'events.$': 1 }); + }). + then(function(doc) { + assert.ok(doc); + assert.equal(doc.events.length, 1); + assert.equal(doc.events[0].element, 'Test'); + }). + catch(done); + }); }); }); }); From dc7207314df6a38df1deaf0f2ad5c129d3fc165b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Jan 2017 16:49:26 -0700 Subject: [PATCH 1167/2240] feat(aggregation): add collation helper re: #4839 --- lib/aggregate.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 6424b383018..9a049e4f00e 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -526,10 +526,7 @@ Aggregate.prototype.cursor = function(options) { * * ####Example: * - * var cursor = Model.aggregate(..).cursor({ batchSize: 1000 }).exec(); - * cursor.each(function(error, doc) { - * // use doc - * }); + * Model.aggregate(..).addCursorFlag('noCursorTimeout', true).exec(); * * @param {String} flag * @param {Boolean} value @@ -544,6 +541,26 @@ Aggregate.prototype.addCursorFlag = function(flag, value) { return this; }; +/** + * Adds a collation + * + * ####Example: + * + * Model.aggregate(..).collation({ locale: 'en_US', strength: 1 }).exec(); + * + * @param {Object} collation options + * @param {Boolean} value + * @see mongodb http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#aggregate + */ + +Aggregate.prototype.collation = function(collation) { + if (!this.options) { + this.options = {}; + } + this.options.collation = value; + return this; +}; + /** * Executes the aggregate pipeline on the currently bound Model. * From ddafeacbcf033dce4eae984ff6b3376c86ca9250 Mon Sep 17 00:00:00 2001 From: JT Date: Wed, 18 Jan 2017 22:27:12 -0800 Subject: [PATCH 1168/2240] Abstract away $in boilerplate when querying objectIds Normally, a query to find a key that matches multiple values would look like: ```js SomeModel.find({ _id: { $in: [id1, id2, id3] } }) ``` With this change, the nested `$in` part would no longer be necessary. ```js SomeModel.find({ _id: [id1, id2, id3] }) ``` --- lib/schema/objectid.js | 8 ++++++++ test/cast.test.js | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index 28858236893..23618ecb078 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -128,6 +128,14 @@ ObjectId.prototype.cast = function(value, doc, init) { return value; } + if (value instanceof Array) { + var values = []; + for (var i = 0; i < value.length; i++) { + values.push(this.cast(value[i], doc, init)); + } + return { $in: values }; + } + if (value._id) { if (value._id instanceof oid) { return value._id; diff --git a/test/cast.test.js b/test/cast.test.js index ac5947eb01d..d5d37b6c039 100644 --- a/test/cast.test.js +++ b/test/cast.test.js @@ -5,8 +5,16 @@ var Schema = require('../lib/schema'); var assert = require('power-assert'); var cast = require('../lib/cast'); +var ObjectId = require('bson').ObjectId; describe('cast: ', function() { + it('with an ObjectId', function(done) { + var schema = new Schema({x: Schema.Types.ObjectId}); + var ids = [new ObjectId(), new ObjectId()]; + assert.deepEqual(cast(schema, {x: ids}), { x: { $in: ids } }); + done(); + }); + describe('bitwise query operators: ', function() { it('with a number', function(done) { var schema = new Schema({x: Buffer}); From 824132e4bb49d5663ab72eab3246d069d02eee4d Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Thu, 19 Jan 2017 01:55:00 -0500 Subject: [PATCH 1169/2240] feat(aggregate): add facet pipeline operator --- lib/aggregate.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/aggregate.js b/lib/aggregate.js index 9a049e4f00e..e594209ab32 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -561,6 +561,16 @@ Aggregate.prototype.collation = function(collation) { return this; }; +/** + * Adds a faceted stage to the aggregation pipeline for sub-pipeline aggregations + * + * ####Example: + */ + +Aggregate.prototype.facet = function(options) { + return this.append({$facet: options}); +}; + /** * Executes the aggregate pipeline on the currently bound Model. * From 3e0af7c8f9200fd2ef09087b02fbaa21550200cc Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 19 Jan 2017 08:52:03 -0800 Subject: [PATCH 1170/2240] better approach; add more tests --- lib/cast.js | 10 ++++++++++ lib/schema/objectid.js | 8 -------- test/cast.test.js | 42 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index e9e0ada3339..ab9ce92fa5d 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -225,6 +225,16 @@ module.exports = function cast(schema, obj, options) { } } } + } else if (val.constructor.name === 'Array' && schematype.instance !== 'Buffer') { + var casted = []; + for (var valIndex = 0; valIndex < val.length; valIndex++) { + casted.push(schematype.castForQuery(val[valIndex])); + } + + var result = {}; + result[path] = { $in: casted }; + + return result; } else { obj[path] = schematype.castForQuery(val); } diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index 23618ecb078..28858236893 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -128,14 +128,6 @@ ObjectId.prototype.cast = function(value, doc, init) { return value; } - if (value instanceof Array) { - var values = []; - for (var i = 0; i < value.length; i++) { - values.push(this.cast(value[i], doc, init)); - } - return { $in: values }; - } - if (value._id) { if (value._id instanceof oid) { return value._id; diff --git a/test/cast.test.js b/test/cast.test.js index d5d37b6c039..af36b47a8b0 100644 --- a/test/cast.test.js +++ b/test/cast.test.js @@ -8,11 +8,43 @@ var cast = require('../lib/cast'); var ObjectId = require('bson').ObjectId; describe('cast: ', function() { - it('with an ObjectId', function(done) { - var schema = new Schema({x: Schema.Types.ObjectId}); - var ids = [new ObjectId(), new ObjectId()]; - assert.deepEqual(cast(schema, {x: ids}), { x: { $in: ids } }); - done(); + describe('when casting an array', function() { + it('casts array with ObjectIds to $in query', function(done) { + var schema = new Schema({x: Schema.Types.ObjectId}); + var ids = [new ObjectId(), new ObjectId()]; + assert.deepEqual(cast(schema, {x: ids}), { x: { $in: ids } }); + done(); + }); + + it('casts array with ObjectIds to $in query when values are strings', function(done) { + var schema = new Schema({x: Schema.Types.ObjectId}); + var ids = [new ObjectId(), new ObjectId()]; + assert.deepEqual(cast(schema, {x: ids.map(String)}), { x: { $in: ids } }); + done(); + }); + + it('throws when ObjectIds not valid', function(done) { + var schema = new Schema({x: Schema.Types.ObjectId}); + var ids = [123, 456, 'asfds']; + assert.throws(function() { + cast(schema, {x: ids}); + }, /Cast to ObjectId failed/); + done(); + }); + + it('casts array with Strings to $in query', function(done) { + var schema = new Schema({x: String}); + var strings = ['bleep', 'bloop']; + assert.deepEqual(cast(schema, {x: strings}), { x: { $in: strings } }); + done(); + }); + + it('casts array with Strings when necessary', function(done) { + var schema = new Schema({x: String}); + var strings = [123, 456]; + assert.deepEqual(cast(schema, {x: strings}), { x: { $in: strings.map(String) } }); + done(); + }); }); describe('bitwise query operators: ', function() { From 381ea9c8c64dbb4486dad3e57edb1e6419a16e80 Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 19 Jan 2017 08:57:00 -0800 Subject: [PATCH 1171/2240] add test for numbers array --- test/cast.test.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/cast.test.js b/test/cast.test.js index af36b47a8b0..cd41be8d519 100644 --- a/test/cast.test.js +++ b/test/cast.test.js @@ -45,6 +45,29 @@ describe('cast: ', function() { assert.deepEqual(cast(schema, {x: strings}), { x: { $in: strings.map(String) } }); done(); }); + + it('casts array with Numbers to $in query', function(done) { + var schema = new Schema({x: Number}); + var numbers = [42, 25]; + assert.deepEqual(cast(schema, {x: numbers}), { x: { $in: numbers } }); + done(); + }); + + it('casts array with Numbers to $in query when values are strings', function(done) { + var schema = new Schema({x: Number}); + var numbers = ['42', '25']; + assert.deepEqual(cast(schema, {x: numbers}), { x: { $in: numbers.map(Number) } }); + done(); + }); + + it('throws when Numbers not valid', function(done) { + var schema = new Schema({x: Number}); + var numbers = [123, 456, 'asfds']; + assert.throws(function() { + cast(schema, {x: numbers}); + }, /Cast to number failed for value "asfds"/); + done(); + }); }); describe('bitwise query operators: ', function() { From fbfe811d14af31b72f04ee37f5b052f864bb7b09 Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 19 Jan 2017 09:17:16 -0800 Subject: [PATCH 1172/2240] final fixes --- lib/cast.js | 7 ++----- test/cast.test.js | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index ab9ce92fa5d..773fb3b759d 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -225,16 +225,13 @@ module.exports = function cast(schema, obj, options) { } } } - } else if (val.constructor.name === 'Array' && schematype.instance !== 'Buffer') { + } else if (val.constructor.name === 'Array' && ['Buffer', 'Array'].indexOf(schematype.instance) === -1) { var casted = []; for (var valIndex = 0; valIndex < val.length; valIndex++) { casted.push(schematype.castForQuery(val[valIndex])); } - var result = {}; - result[path] = { $in: casted }; - - return result; + obj[path] = { $in: casted }; } else { obj[path] = schematype.castForQuery(val); } diff --git a/test/cast.test.js b/test/cast.test.js index cd41be8d519..26289e8822c 100644 --- a/test/cast.test.js +++ b/test/cast.test.js @@ -60,7 +60,7 @@ describe('cast: ', function() { done(); }); - it('throws when Numbers not valid', function(done) { + it('throws when Numbers are not valid', function(done) { var schema = new Schema({x: Number}); var numbers = [123, 456, 'asfds']; assert.throws(function() { From f302c7d046a1d2fc7420104a9d8d689af9ca4b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C5=BBaczek?= Date: Thu, 19 Jan 2017 23:53:56 +0100 Subject: [PATCH 1173/2240] Update Contributors Count --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a694a914b4d..e5fe25e9321 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Build your own Mongoose plugin through [generator-mongoose-plugin](https://githu ## Contributors -View all 200+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors). Stand up and be counted as a [contributor](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md) too! +View all 300+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors). Stand up and be counted as a [contributor](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md) too! ## Installation From 5140e62fd32cb169d2a3979c130f571c55d649ac Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Jan 2017 19:28:37 -0700 Subject: [PATCH 1174/2240] docs: explain selecting foreignField in populate virtuals Re: #4923 --- docs/populate.jade | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/populate.jade b/docs/populate.jade index cf4f1dd9428..bd78b74c23f 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -357,6 +357,25 @@ block content var BandSchema = new Schema({ name: String }, { toJSON: { virtuals: true } }); + + :markdown + If you're using populate projections, make sure `foreignField` is included + in the projection. + + :js + Band. + find({}). + populate({ path: 'members', select: 'name' }). + exec(function(error, bands) { + // Won't work, foreign field `band` is not selected in the projection + }); + + Band. + find({}). + populate({ path: 'members', select: 'name band' }). + exec(function(error, bands) { + // Works, foreign field `band` is selected + }); h3#next Next Up :markdown From e01527cb8f5e26a55b5403ad0399164dd16a40f5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Jan 2017 19:31:09 -0700 Subject: [PATCH 1175/2240] test(document): repro #4885 --- test/document.test.js | 18 ++++++++++++++++++ test/query.middleware.test.js | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index e454266dea0..420bbc70ae5 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2156,6 +2156,24 @@ describe('document', function() { }); }); + it('validate errors (gh-4885)', function(done) { + var testSchema = new Schema({ title: { type: String, required: true } }); + + var called = 0; + testSchema.post('validate', function(error, doc, next) { + ++called; + next(error); + }); + + var Test = db.model('gh4885', testSchema); + + Test.create({}, function(error) { + assert.ok(error); + assert.equal(called, 1); + done(); + }); + }); + it('handles non-errors', function(done) { var schema = new Schema({ name: { type: String, required: true } diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 1925f2235eb..952cac46ff4 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -241,6 +241,24 @@ describe('query middleware', function() { }); }); + it('error handlers for validate (gh-4885)', function(done) { + var testSchema = new Schema({ title: { type: String, required: true } }); + + var called = 0; + testSchema.post('validate', function(error, doc, next) { + ++called; + next(error); + }); + + var Test = db.model('gh4885', testSchema); + + Test.create({}, function(error) { + assert.ok(error); + assert.equal(called, 1); + done(); + }); + }); + it('error handlers with findOneAndUpdate and passRawResult (gh-4836)', function(done) { var schema = new Schema({name: {type: String}}); From 275053935e813065706827b2a64b91a7046da954 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Jan 2017 19:33:29 -0700 Subject: [PATCH 1176/2240] fix(document): ensure error handlers run for validate Fix #4885 --- lib/document.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/document.js b/lib/document.js index 0d15ac0b89b..2312102245c 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1328,10 +1328,11 @@ Document.prototype.$__validate = function(callback) { if (paths.length === 0) { process.nextTick(function() { - var err = _complete(); - if (err) { - callback(err); - return; + var error = _complete(); + if (error) { + return _this.schema.s.hooks.execPost('validate:error', _this, [ _this], { error: error }, function(error) { + callback(error); + }); } callback(); }); @@ -1341,10 +1342,11 @@ Document.prototype.$__validate = function(callback) { total = 0; var complete = function() { - var err = _complete(); - if (err) { - callback(err); - return; + var error = _complete(); + if (error) { + return _this.schema.s.hooks.execPost('validate:error', _this, [ _this], { error: error }, function(error) { + callback(error); + }); } callback(); }; From bef9d78fac2482a28e33c485842cb1f7fb05837f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Jan 2017 19:37:34 -0700 Subject: [PATCH 1177/2240] fix: handle authMechanism in query string #4900 --- lib/drivers/node-mongodb-native/connection.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 779be260415..9d8a9946972 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -295,6 +295,11 @@ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { o.auth.authSource = opts[name]; } break; + case 'authMechanism': + if (typeof o.auth.authMechanism === 'undefined') { + o.auth.authMechanism = opts[name]; + } + break; case 'retries': case 'reconnectWait': case 'rs_name': From a9b97f72359de7d84290ac3756542de21b3ea7b3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Jan 2017 19:51:32 -0700 Subject: [PATCH 1178/2240] docs(connections): add authMechanism to connections docs re: #4900 --- docs/connections.jade | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/connections.jade b/docs/connections.jade index 5d6c0f259f2..49c26c6d64c 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -104,6 +104,7 @@ block content * [connectTimeoutMS](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) * [authSource](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) * [retries](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + * [authMechanism](http://mongodb.github.io/node-mongodb-native/2.2/tutorials/connect/authenticating/) * [reconnectWait](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) * [rs_name](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) * [replicaSet](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) From 6f16c6b499521c7fed7febc555c297911e773023 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Jan 2017 19:54:01 -0700 Subject: [PATCH 1179/2240] docs(promise): add missing bracket Fix #4907 --- lib/promise.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/promise.js b/lib/promise.js index 72163ea9982..1e1ba6955e1 100644 --- a/lib/promise.js +++ b/lib/promise.js @@ -258,7 +258,7 @@ Promise.prototype.addErrback = Promise.prototype.onReject; * var ids = meetups.map(function (m) { * return m._id; * }); - * return People.find({ meetups: { $in: ids }).exec(); + * return People.find({ meetups: { $in: ids } }).exec(); * }).then(function (people) { * if (people.length < 10000) { * throw new Error('Too few people!!!'); From 7cd0a792c12230c57b9d86849d250be3c62113b3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Jan 2017 20:46:04 -0700 Subject: [PATCH 1180/2240] test(query): repro #4911 --- test/model.update.test.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 745b5798930..254f021d29e 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1067,6 +1067,30 @@ describe('model: update:', function() { }); }); + it('avoids nested paths if setting parent path (gh-4911)', function(done) { + var EmbeddedSchema = mongoose.Schema({ + embeddedField: String + }); + + var ParentSchema = mongoose.Schema({ + embedded: EmbeddedSchema + }); + + var Parent = db.model('gh4911', ParentSchema); + + var newDoc = { + _id: new mongoose.Types.ObjectId(), + embedded: null + }; + + var opts = { upsert: true, setDefaultsOnInsert: true }; + + Parent. + findOneAndUpdate({ _id: newDoc._id }, newDoc, opts). + then(function() { done(); }). + catch(done); + }); + it('doesnt set default on upsert if query sets it', function(done) { var s = new Schema({topping: {type: String, default: 'bacon'}, base: String}); var Breakfast = db.model('gh-860-1', s); From 806e5ed0ed9b25a3beed062cbe4f8167cdf4ae5d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Jan 2017 20:48:59 -0700 Subject: [PATCH 1181/2240] fix(query): don't set nested path default if setting parent path Fix #4911 --- lib/services/setDefaultsOnInsert.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/services/setDefaultsOnInsert.js b/lib/services/setDefaultsOnInsert.js index 36b87d776ee..5d9f3c0a119 100644 --- a/lib/services/setDefaultsOnInsert.js +++ b/lib/services/setDefaultsOnInsert.js @@ -72,7 +72,8 @@ module.exports = function(query, schema, castedDoc, options) { } var def = _schemaType.getDefault(null, true); - if (!modified[path + '.' + _path] && typeof def !== 'undefined') { + if (!isModified(modified, path + '.' + _path) && + typeof def !== 'undefined') { castedDoc = castedDoc || {}; castedDoc.$setOnInsert = castedDoc.$setOnInsert || {}; castedDoc.$setOnInsert[path + '.' + _path] = def; @@ -81,7 +82,7 @@ module.exports = function(query, schema, castedDoc, options) { }); } else { var def = schemaType.getDefault(null, true); - if (!modified[path] && typeof def !== 'undefined') { + if (!isModified(modified, path) && typeof def !== 'undefined') { castedDoc = castedDoc || {}; castedDoc.$setOnInsert = castedDoc.$setOnInsert || {}; castedDoc.$setOnInsert[path] = def; @@ -94,3 +95,18 @@ module.exports = function(query, schema, castedDoc, options) { return castedDoc; }; + +function isModified(modified, path) { + if (modified[path]) { + return true; + } + var sp = path.split('.'); + var cur = sp[0]; + for (var i = 0; i < sp.length; ++i) { + if (modified[cur]) { + return true; + } + cur += '.' + sp[i]; + } + return false; +} From 663ca4893da7300ae4808594f3a98cb3a36eb7e5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Jan 2017 21:32:32 -0700 Subject: [PATCH 1182/2240] fix(connection): ensure error handling is consistently async Fix #4905 --- lib/connection.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 69c470a8053..ec7e1e61ba9 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -289,10 +289,13 @@ Connection.prototype.open = function(host, database, port, options, callback) { _this._open(true, function(error) { callback && callback(error); if (error) { - reject(error); - if (!callback && !promise.$hasHandler) { - _this.emit('error', error); - } + // Error can be on same tick re: christkv/mongodb-core#157 + setImmediate(function() { + reject(error); + if (!callback && !promise.$hasHandler) { + _this.emit('error', error); + } + }); return; } resolve(); From 83cdb556dfc0d792bdb1558e85a2cceb92ca3542 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 22 Jan 2017 19:50:08 -0700 Subject: [PATCH 1183/2240] style(aggregate): fix lint --- lib/aggregate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 9a049e4f00e..511351a0752 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -557,7 +557,7 @@ Aggregate.prototype.collation = function(collation) { if (!this.options) { this.options = {}; } - this.options.collation = value; + this.options.collation = collation; return this; }; From c7049b8396f6edc37fb95d6dfd02da0f731ddc35 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 22 Jan 2017 23:09:08 -0700 Subject: [PATCH 1184/2240] test(populate): repro #4923 --- test/model.populate.test.js | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index c20bc3d42d2..3ce05d4c1d0 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4502,6 +4502,71 @@ describe('model: populate:', function() { }); }); + it('gh-4923', function(done) { + var ClusterSchema = new Schema({ + name: String + }); + var Cluster = db.model('gh4923', ClusterSchema); + + var ZoneSchema = new Schema({ + name: String, + clusters: { + type: [ObjectId], + ref: 'gh4923' + } + }); + var Zone = db.model('gh4923_1', ZoneSchema); + + var DocSchema = new Schema({ + activity: [{ + cluster: { + type: ObjectId, + ref: 'gh4923' + }, + intensity: Number + }] + }); + DocSchema.virtual('activity.zones', { + ref: 'gh4923_1', + localField: 'activity.cluster', + foreignField: 'clusters' + }); + DocSchema.set('toObject', {virtuals: true}); + DocSchema.set('toJSON', {virtuals: true}); + var Doc = db.model('gh4923_2', DocSchema); + + Cluster.create([{ name: 'c1' }, { name: 'c2' }, { name: 'c3' }]). + then(function(c) { + return Zone.create([ + { name: 'z1', clusters: [c[0]._id, c[1]._id, c[2]._id] }, + { name: 'z2', clusters: [c[0]._id, c[2]._id] } + ]).then(function() { return c; }); + }). + then(function(c) { + return Doc.create({ + activity: [ + { cluster: c[0]._id, intensity: 1 }, + { cluster: c[1]._id, intensity: 2 } + ] + }); + }). + then(function() { + return Doc. + findOne({}). + populate('activity.cluster'). + populate('activity.zones', 'name clusters'). + exec(function(error, res) { + assert.ifError(error); + // Fails if this `.toObject()` is returned, issue #4926 + res = res.toObject(); + assert.equal(res.activity[0].zones[0].name, 'z1'); + assert.equal(res.activity[1].zones[0].name, 'z1'); + done(); + }); + }). + catch(done); + }); + it('supports setting default options in schema (gh-4741)', function(done) { var sessionSchema = new Schema({ date: { type: Date }, From c27c294b4d0954b067f52036569c6b82e7d212e4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 22 Jan 2017 23:15:20 -0700 Subject: [PATCH 1185/2240] fix(populate): better handling for virtual populate under arrays Fix #4923 --- lib/model.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index c706213a1af..b37e99112d7 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2740,10 +2740,15 @@ function populate(model, docs, options, callback) { if (err) return callback(err); var options = mod.options; + var isVirtual = mod.isVirtual; + var justOne = mod.justOne; var _val; - var lean = options.options && options.options.lean, - len = vals.length, - rawOrder = {}, rawDocs = {}, key, val; + var lean = options.options && options.options.lean; + var len = vals.length; + var rawOrder = {}; + var rawDocs = {}; + var key; + var val; // optimization: // record the document positions as returned by @@ -2768,8 +2773,13 @@ function populate(model, docs, options, callback) { rawOrder[key] = [rawOrder[key], i]; } } else { - rawDocs[key] = val; - rawOrder[key] = i; + if (isVirtual && !justOne) { + rawDocs[key] = [val]; + rawOrder[key] = [i]; + } else { + rawDocs[key] = val; + rawOrder[key] = i; + } } } } else { From c53358034a5051d02925f7e6f16076c068f4c22e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 23 Jan 2017 22:43:13 -0700 Subject: [PATCH 1186/2240] chore: release 4.7.8 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2477a60c8f7..bb79039ea0e 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.7.8 / 2017-01-23 +================== + * fix(populate): better handling for virtual populate under arrays #4923 + * docs: upgrade contributors count #4918 [AdamZaczek](https://github.com/AdamZaczek) + * fix(query): don't set nested path default if setting parent path #4911 + * docs(promise): add missing bracket #4907 + * fix(connection): ensure error handling is consistently async #4905 + * fix: handle authMechanism in query string #4900 + * fix(document): ensure error handlers run for validate #4885 + 4.7.7 / 2017-01-15 ================== * fix(utils): don't crash if to[key] is null #4881 diff --git a/package.json b/package.json index e2ab79ca6e4..28878b8335b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.8-pre", + "version": "4.7.8", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 8bb9a92926a261a7c6d62db0ee416126b2183310 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 24 Jan 2017 21:21:52 -0700 Subject: [PATCH 1187/2240] chore: now working on 4.7.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28878b8335b..45dd2dc7016 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.8", + "version": "4.7.9-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From bfa84b3a64f117f4de72ff87a784beb95aeaf7cb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 25 Jan 2017 17:26:35 -0700 Subject: [PATCH 1188/2240] test: skip graphLookup tests unless 3.4 --- test/aggregate.test.js | 73 +++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 2d72c1e8cf2..17f37cc2535 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -379,6 +379,21 @@ describe('aggregate: ', function() { }); describe('graphLookup', function() { + before(function(done) { + var _this = this; + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + _this.skip(); + } + done(); + }); + }); + it('works', function(done) { var aggregate = new Aggregate(); aggregate.graphLookup({ @@ -572,30 +587,44 @@ describe('aggregate: ', function() { }); it('graphLookup', function(done) { - var aggregate = new Aggregate(); - - aggregate. - model(db.model('Employee')). - graphLookup({ - from: 'employees', - startWith: '$reportsTo', - connectFromField: 'reportsTo', - connectToField: 'name', - as: 'employeeHierarchy' - }). - exec(function(err, docs) { - if (err) { - return done(err); - } - var lowest = docs[3]; - assert.equal(lowest.employeeHierarchy.length, 3); + var _this = this; + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + _this.skip(); + } + test(); + }); - // First result in array is max depth result - assert.equal(lowest.employeeHierarchy[0].name, 'Alice'); - assert.equal(lowest.employeeHierarchy[2].name, 'Carol'); - done(); - }); + function test() { + var aggregate = new Aggregate(); + aggregate. + model(db.model('Employee')). + graphLookup({ + from: 'employees', + startWith: '$reportsTo', + connectFromField: 'reportsTo', + connectToField: 'name', + as: 'employeeHierarchy' + }). + exec(function(err, docs) { + if (err) { + return done(err); + } + var lowest = docs[3]; + assert.equal(lowest.employeeHierarchy.length, 3); + + // First result in array is max depth result + assert.equal(lowest.employeeHierarchy[0].name, 'Alice'); + assert.equal(lowest.employeeHierarchy[2].name, 'Carol'); + done(); + }); + } }); it('complex pipeline', function(done) { From 7e133e8de855c3d8169a0303284c84724025fdc6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 25 Jan 2017 19:47:07 -0700 Subject: [PATCH 1189/2240] test(populate): repro #2202 --- test/model.populate.test.js | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 1a58d855f43..e705572e505 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3217,6 +3217,51 @@ describe('model: populate:', function() { }); }); + it('fails if sorting with a doc array subprop (gh-2202)', function(done) { + var childSchema = new Schema({ name: String }); + var Child = db.model('gh2202', childSchema); + + var parentSchema = new Schema({ + children1: [{ + child: { + type: mongoose.Schema.Types.ObjectId, + ref: 'gh2202' + }, + test: Number + }], + children2: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'gh2202' + }] + }); + var Parent = db.model('gh2202_0', parentSchema); + + Child.create([{ name: 'test1' }, { name: 'test2' }], function(error, c) { + assert.ifError(error); + var doc = { + children1: [ + { child: c[0]._id, test: 1 }, + { child: c[1]._id, test: 2 } + ], + children2: [c[0]._id, c[1]._id] + }; + Parent.create(doc, function(error, doc) { + assert.ifError(error); + Parent.findById(doc).populate('children2').exec(function(error, doc) { + assert.ifError(error); + assert.equal(doc.children2[0].name, 'test1'); + Parent.findById(doc). + populate({ path: 'children1.child', options: { sort: '-name' } }). + exec(function(error) { + assert.notEqual(error.message.indexOf('subproperty of a document array'), + -1); + done(); + }); + }); + }); + }); + }); + it('handles toObject() (gh-3279)', function(done) { var teamSchema = new Schema({ members: [{ From 1062a1719be6dbb4a41b32b1aa7767aa48760cdb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 25 Jan 2017 19:47:23 -0700 Subject: [PATCH 1190/2240] fix(populate): return an error if sorting underneath a doc array Fix #2202 --- lib/model.js | 13 +++++++++++++ lib/schema.js | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index d9470240885..0241bbff97b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2664,6 +2664,11 @@ function populate(model, docs, options, callback) { } modelsMap = getModelsMapForPopulate(model, docs, options); + if (modelsMap instanceof Error) { + return setImmediate(function() { + callback(modelsMap); + }); + } var i, len = modelsMap.length, mod, match, select, vals = []; @@ -2958,6 +2963,14 @@ function getModelsMapForPopulate(model, docs, options) { var isVirtual = false; schema = model._getSchema(options.path); + var isUnderneathDocArray = schema && schema.$isUnderneathDocArray; + if (isUnderneathDocArray && + originalOptions && + originalOptions.options && + originalOptions.options.sort) { + return new Error('Cannot populate with `sort` on path ' + options.path + + ' because it is a subproperty of a document array'); + } if (schema && schema.caster) { schema = schema.caster; diff --git a/lib/schema.js b/lib/schema.js index acbfcc85c3c..8012bc8917d 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1654,12 +1654,23 @@ Schema.prototype._getSchema = function(path) { // If there is no foundschema.schema we are dealing with // a path like array.$ if (p !== parts.length && foundschema.schema) { + var ret; if (parts[p] === '$') { // comments.$.comments.$.title - return search(parts.slice(p + 1), foundschema.schema); + ret = search(parts.slice(p + 1), foundschema.schema); + if (ret) { + ret.$isUnderneathDocArray = ret.$isUnderneathDocArray || + !foundschema.schema.$isSingleNested; + } + return ret; } // this is the last path of the selector - return search(parts.slice(p), foundschema.schema); + ret = search(parts.slice(p), foundschema.schema); + if (ret) { + ret.$isUnderneathDocArray = ret.$isUnderneathDocArray || + !foundschema.schema.$isSingleNested; + } + return ret; } } From 7314bf91206c5ad81762817e1439e69abb706ce8 Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Wed, 25 Jan 2017 23:36:23 -0500 Subject: [PATCH 1191/2240] docs(Aggregate): Add documentation for facet operator --- lib/aggregate.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index e594209ab32..8fe39d0257c 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -562,9 +562,22 @@ Aggregate.prototype.collation = function(collation) { }; /** - * Adds a faceted stage to the aggregation pipeline for sub-pipeline aggregations + * Combines multiple aggregation pipelines * * ####Example: + * Model.aggregate(...) + * .facet({ + * books: [{ groupBy: '$author' }], + * price: [{ $bucketAuto: { groupBy: '$price', buckets: 2 } }] + * }) + * .exec(); + * + * // Output: { books: [...], price: [{...}, {...}] } + * + * @param {Object} facet options + * @return {Aggregate} this + * @see mongodb https://docs.mongodb.com/v3.4/reference/operator/aggregation/facet/ + * @api public */ Aggregate.prototype.facet = function(options) { From 243ab7ff8204e12973306718b04fdcaa240e0d65 Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Wed, 25 Jan 2017 23:40:42 -0500 Subject: [PATCH 1192/2240] chore(Aggregate): Make alerts/notes consistent in documentation --- lib/aggregate.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index a937d25c02e..c8f268c3fac 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -314,7 +314,7 @@ Aggregate.prototype.lookup = function(options) { /** * Appends new custom $graphLookup operator(s) to this aggregate pipeline, performing a recursive search on a collection. * - * NOTE: graphLookup can only consume at most 100MB of memory, and does not allow disk use even if `{ allowDiskUse: true }` is specified. + * Note that graphLookup can only consume at most 100MB of memory, and does not allow disk use even if `{ allowDiskUse: true }` is specified. * * #### Examples: * // Suppose we have a collection of courses, where a document might look like `{ _id: 0, name: 'Calculus', prerequisite: 'Trigonometry'}` and `{ _id: 0, name: 'Trigonometry', prerequisite: 'Algebra' }` @@ -562,7 +562,7 @@ Aggregate.prototype.collation = function(collation) { }; /** - * Combines multiple aggregation pipelines + * Combines multiple aggregation pipelines. * * ####Example: * Model.aggregate(...) @@ -576,7 +576,7 @@ Aggregate.prototype.collation = function(collation) { * * @param {Object} facet options * @return {Aggregate} this - * @see mongodb https://docs.mongodb.com/v3.4/reference/operator/aggregation/facet/ + * @see $facet https://docs.mongodb.com/v3.4/reference/operator/aggregation/facet/ * @api public */ From 64d8de288668ec0610252586ff3dab4320e32120 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 26 Jan 2017 12:41:21 -0700 Subject: [PATCH 1193/2240] feat(schema): add Decimal as alias for Decimal128 --- lib/schema/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/index.js b/lib/schema/index.js index ed4b326b859..dc2a5645928 100644 --- a/lib/schema/index.js +++ b/lib/schema/index.js @@ -23,7 +23,7 @@ exports.ObjectId = require('./objectid'); exports.Mixed = require('./mixed'); -exports.Decimal128 = require('./decimal128'); +exports.Decimal128 = exports.Decimal = require('./decimal128'); // alias From 6c67ce4b6055c37a088962d71802524694453928 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 26 Jan 2017 13:24:02 -0700 Subject: [PATCH 1194/2240] fix(document): correct handling for decimals in toObject --- lib/aggregate.js | 8 ++++---- lib/document.js | 6 ++++-- lib/model.js | 1 + lib/schema/embedded.js | 5 ++++- lib/types/array.js | 8 +++++++- lib/types/documentarray.js | 8 +++++++- lib/types/embedded.js | 8 +++++++- lib/types/subdocument.js | 8 +++++++- lib/utils.js | 10 +++++++++- 9 files changed, 50 insertions(+), 12 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index c8f268c3fac..8bb126b5b5f 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -562,8 +562,8 @@ Aggregate.prototype.collation = function(collation) { }; /** - * Combines multiple aggregation pipelines. - * + * Combines multiple aggregation pipelines. + * * ####Example: * Model.aggregate(...) * .facet({ @@ -571,9 +571,9 @@ Aggregate.prototype.collation = function(collation) { * price: [{ $bucketAuto: { groupBy: '$price', buckets: 2 } }] * }) * .exec(); - * + * * // Output: { books: [...], price: [{...}, {...}] } - * + * * @param {Object} facet options * @return {Aggregate} this * @see $facet https://docs.mongodb.com/v3.4/reference/operator/aggregation/facet/ diff --git a/lib/document.js b/lib/document.js index 03c507b4b5d..8d0e62b51c4 100644 --- a/lib/document.js +++ b/lib/document.js @@ -286,7 +286,8 @@ Document.prototype.toBSON = function() { transform: false, virtuals: false, _skipDepopulateTopLevel: true, - depopulate: true + depopulate: true, + flattenDecimals: false }); }; @@ -1958,7 +1959,8 @@ Document.prototype.$toObject = function(options, json) { var defaultOptions = { transform: true, json: json, - retainKeyOrder: this.schema.options.retainKeyOrder + retainKeyOrder: this.schema.options.retainKeyOrder, + flattenDecimals: true }; // _isNested will only be true if this is not the top level document, we diff --git a/lib/model.js b/lib/model.js index 0241bbff97b..3a88291fa4a 100644 --- a/lib/model.js +++ b/lib/model.js @@ -124,6 +124,7 @@ Model.prototype.$__handleSave = function(options, callback) { toObjectOptions.depopulate = 1; toObjectOptions._skipDepopulateTopLevel = true; toObjectOptions.transform = false; + toObjectOptions.flattenDecimals = false; var obj = this.toObject(toObjectOptions); diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 911900978ac..2ea88aaf19e 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -51,7 +51,10 @@ function Embedded(schema, path, options) { return this.toObject({ transform: false, retainKeyOrder: schema.options.retainKeyOrder, - virtuals: false + virtuals: false, + _skipDepopulateTopLevel: true, + depopulate: true, + flattenDecimals: false }); }; diff --git a/lib/types/array.js b/lib/types/array.js index 4c0ff12676e..3874078ee1c 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -55,7 +55,13 @@ MongooseArray.mixin = { * ignore */ toBSON: function() { - return this.toObject({ transform: false, virtuals: false }); + return this.toObject({ + transform: false, + virtuals: false, + _skipDepopulateTopLevel: true, + depopulate: true, + flattenDecimals: false + }); }, /** diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index e68cac36aaf..bc07a75b9b1 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -81,7 +81,13 @@ MongooseDocumentArray.mixin = { * ignore */ toBSON: function() { - return this.toObject({ transform: false, virtuals: false }); + return this.toObject({ + transform: false, + virtuals: false, + _skipDepopulateTopLevel: true, + depopulate: true, + flattenDecimals: false + }); }, /** diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 0f5fe1ba4a5..14f1628f40d 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -47,7 +47,13 @@ for (var i in EventEmitter.prototype) { } EmbeddedDocument.prototype.toBSON = function() { - return this.toObject({ transform: false, virtuals: false }); + return this.toObject({ + transform: false, + virtuals: false, + _skipDepopulateTopLevel: true, + depopulate: true, + flattenDecimals: false + }); }; /** diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 42cb50cf780..27534467285 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -18,7 +18,13 @@ function Subdocument(value, fields) { Subdocument.prototype = Object.create(Document.prototype); Subdocument.prototype.toBSON = function() { - return this.toObject({ transform: false, virtuals: false }); + return this.toObject({ + transform: false, + virtuals: false, + _skipDepopulateTopLevel: true, + depopulate: true, + flattenDecimals: false + }); }; /** diff --git a/lib/utils.js b/lib/utils.js index f09c4343daa..2af2995ba55 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -2,6 +2,7 @@ * Module dependencies. */ +var Decimal = require('./types/decimal128'); var ObjectId = require('./types/objectid'); var cloneRegExp = require('regexp-clone'); var sliced = require('sliced'); @@ -146,7 +147,8 @@ exports.deepEqual = function deepEqual(a, b) { return a.getTime() === b.getTime(); } - if (a instanceof ObjectId && b instanceof ObjectId) { + if ((a instanceof ObjectId && b instanceof ObjectId) || + (a instanceof Decimal && b instanceof Decimal)) { return a.toString() === b.toString(); } @@ -269,6 +271,12 @@ exports.clone = function clone(obj, options) { if (obj instanceof ObjectId) { return new ObjectId(obj.id); } + if (obj instanceof Decimal) { + if (options && options.flattenDecimals) { + return obj.toJSON(); + } + return Decimal.fromString(obj.toString()); + } if (!obj.constructor && exports.isObject(obj)) { // object created with Object.create(null) From 6f9bd23c51b501a6091480a229e022e74afd3692 Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Fri, 27 Jan 2017 13:54:31 -0500 Subject: [PATCH 1195/2240] test(Aggregate): Add test for facet operator --- test/aggregate.test.js | 292 ++++++++++++++++++++++++----------------- 1 file changed, 175 insertions(+), 117 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 17f37cc2535..c9dd89e2023 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -24,14 +24,14 @@ mongoose.model('Employee', EmployeeSchema); function setupData(callback) { var saved = 0, - emps = [ - {name: 'Alice', sal: 18000, dept: 'sales', customers: ['Eve', 'Fred']}, - {name: 'Bob', sal: 15000, dept: 'sales', customers: ['Gary', 'Herbert', 'Isaac'], reportsTo: 'Alice'}, - {name: 'Carol', sal: 14000, dept: 'r&d', reportsTo: 'Bob'}, - {name: 'Dave', sal: 14500, dept: 'r&d', reportsTo: 'Carol'} - ], - db = start(), - Employee = db.model('Employee'); + emps = [ + { name: 'Alice', sal: 18000, dept: 'sales', customers: ['Eve', 'Fred'] }, + { name: 'Bob', sal: 15000, dept: 'sales', customers: ['Gary', 'Herbert', 'Isaac'], reportsTo: 'Alice' }, + { name: 'Carol', sal: 14000, dept: 'r&d', reportsTo: 'Bob' }, + { name: 'Dave', sal: 14500, dept: 'r&d', reportsTo: 'Carol' } + ], + db = start(), + Employee = db.model('Employee'); emps.forEach(function(data) { var emp = new Employee(data); @@ -44,6 +44,27 @@ function setupData(callback) { }); } +/** + * Helper function to test operators that only work in MongoDB 3.4 and above (such as some aggregation pipeline operators) + * + * @param {Object} ctx, `this`, so that mocha tests can be skipped + * @param {Function} done + * @return {Void} + */ +function onlyTestMongo34(ctx, done) { + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + ctx.skip(); + } + done(); + }); +} + /** * Test. */ @@ -53,11 +74,11 @@ describe('aggregate: ', function() { it('(pipeline)', function(done) { var aggregate = new Aggregate(); - assert.equal(aggregate.append({$a: 1}, {$b: 2}, {$c: 3}), aggregate); - assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}]); + assert.equal(aggregate.append({ $a: 1 }, { $b: 2 }, { $c: 3 }), aggregate); + assert.deepEqual(aggregate._pipeline, [{ $a: 1 }, { $b: 2 }, { $c: 3 }]); - aggregate.append({$d: 4}, {$c: 5}); - assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}, {$d: 4}, {$c: 5}]); + aggregate.append({ $d: 4 }, { $c: 5 }); + assert.deepEqual(aggregate._pipeline, [{ $a: 1 }, { $b: 2 }, { $c: 3 }, { $d: 4 }, { $c: 5 }]); done(); }); @@ -65,11 +86,11 @@ describe('aggregate: ', function() { it('supports array as single argument', function(done) { var aggregate = new Aggregate(); - assert.equal(aggregate.append([{$a: 1}, {$b: 2}, {$c: 3}]), aggregate); - assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}]); + assert.equal(aggregate.append([{ $a: 1 }, { $b: 2 }, { $c: 3 }]), aggregate); + assert.deepEqual(aggregate._pipeline, [{ $a: 1 }, { $b: 2 }, { $c: 3 }]); - aggregate.append([{$d: 4}, {$c: 5}]); - assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}, {$d: 4}, {$c: 5}]); + aggregate.append([{ $d: 4 }, { $c: 5 }]); + assert.deepEqual(aggregate._pipeline, [{ $a: 1 }, { $b: 2 }, { $c: 3 }, { $d: 4 }, { $c: 5 }]); done(); }); @@ -79,19 +100,19 @@ describe('aggregate: ', function() { var regexp = /Arguments must be aggregate pipeline operators/; assert.throws(function() { - aggregate.append({$a: 1}, 'string'); + aggregate.append({ $a: 1 }, 'string'); }, regexp); assert.throws(function() { - aggregate.append({$a: 1}, ['array']); + aggregate.append({ $a: 1 }, ['array']); }, regexp); assert.throws(function() { - aggregate.append({$a: 1}, {a: 1}); + aggregate.append({ $a: 1 }, { a: 1 }); }, regexp); assert.throws(function() { - aggregate.append([{$a: 1}, {a: 1}]); + aggregate.append([{ $a: 1 }, { a: 1 }]); }, regexp); done(); @@ -118,8 +139,8 @@ describe('aggregate: ', function() { }); it('called from constructor', function(done) { - var aggregate = new Aggregate({$a: 1}, {$b: 2}, {$c: 3}); - assert.deepEqual(aggregate._pipeline, [{$a: 1}, {$b: 2}, {$c: 3}]); + var aggregate = new Aggregate({ $a: 1 }, { $b: 2 }, { $c: 3 }); + assert.deepEqual(aggregate._pipeline, [{ $a: 1 }, { $b: 2 }, { $c: 3 }]); done(); }); }); @@ -128,11 +149,11 @@ describe('aggregate: ', function() { it('(object)', function(done) { var aggregate = new Aggregate(); - assert.equal(aggregate.project({a: 1, b: 1, c: 0}), aggregate); - assert.deepEqual(aggregate._pipeline, [{$project: {a: 1, b: 1, c: 0}}]); + assert.equal(aggregate.project({ a: 1, b: 1, c: 0 }), aggregate); + assert.deepEqual(aggregate._pipeline, [{ $project: { a: 1, b: 1, c: 0 } }]); - aggregate.project({b: 1}); - assert.deepEqual(aggregate._pipeline, [{$project: {a: 1, b: 1, c: 0}}, {$project: {b: 1}}]); + aggregate.project({ b: 1 }); + assert.deepEqual(aggregate._pipeline, [{ $project: { a: 1, b: 1, c: 0 } }, { $project: { b: 1 } }]); done(); }); @@ -141,10 +162,10 @@ describe('aggregate: ', function() { var aggregate = new Aggregate(); aggregate.project(' a b -c '); - assert.deepEqual(aggregate._pipeline, [{$project: {a: 1, b: 1, c: 0}}]); + assert.deepEqual(aggregate._pipeline, [{ $project: { a: 1, b: 1, c: 0 } }]); aggregate.project('b'); - assert.deepEqual(aggregate._pipeline, [{$project: {a: 1, b: 1, c: 0}}, {$project: {b: 1}}]); + assert.deepEqual(aggregate._pipeline, [{ $project: { a: 1, b: 1, c: 0 } }, { $project: { b: 1 } }]); done(); }); @@ -172,11 +193,11 @@ describe('aggregate: ', function() { it('works', function(done) { var aggregate = new Aggregate(); - assert.equal(aggregate.group({a: 1, b: 2}), aggregate); - assert.deepEqual(aggregate._pipeline, [{$group: {a: 1, b: 2}}]); + assert.equal(aggregate.group({ a: 1, b: 2 }), aggregate); + assert.deepEqual(aggregate._pipeline, [{ $group: { a: 1, b: 2 } }]); - aggregate.group({c: 3}); - assert.deepEqual(aggregate._pipeline, [{$group: {a: 1, b: 2}}, {$group: {c: 3}}]); + aggregate.group({ c: 3 }); + assert.deepEqual(aggregate._pipeline, [{ $group: { a: 1, b: 2 } }, { $group: { c: 3 } }]); done(); }); @@ -187,10 +208,10 @@ describe('aggregate: ', function() { var aggregate = new Aggregate(); assert.equal(aggregate.skip(42), aggregate); - assert.deepEqual(aggregate._pipeline, [{$skip: 42}]); + assert.deepEqual(aggregate._pipeline, [{ $skip: 42 }]); aggregate.skip(42); - assert.deepEqual(aggregate._pipeline, [{$skip: 42}, {$skip: 42}]); + assert.deepEqual(aggregate._pipeline, [{ $skip: 42 }, { $skip: 42 }]); done(); }); @@ -201,10 +222,10 @@ describe('aggregate: ', function() { var aggregate = new Aggregate(); assert.equal(aggregate.limit(42), aggregate); - assert.deepEqual(aggregate._pipeline, [{$limit: 42}]); + assert.deepEqual(aggregate._pipeline, [{ $limit: 42 }]); aggregate.limit(42); - assert.deepEqual(aggregate._pipeline, [{$limit: 42}, {$limit: 42}]); + assert.deepEqual(aggregate._pipeline, [{ $limit: 42 }, { $limit: 42 }]); done(); }); @@ -215,14 +236,14 @@ describe('aggregate: ', function() { var aggregate = new Aggregate(); assert.equal(aggregate.unwind('field'), aggregate); - assert.deepEqual(aggregate._pipeline, [{$unwind: '$field'}]); + assert.deepEqual(aggregate._pipeline, [{ $unwind: '$field' }]); aggregate.unwind('a', 'b', 'c'); assert.deepEqual(aggregate._pipeline, [ - {$unwind: '$field'}, - {$unwind: '$a'}, - {$unwind: '$b'}, - {$unwind: '$c'} + { $unwind: '$field' }, + { $unwind: '$a' }, + { $unwind: '$b' }, + { $unwind: '$c' } ]); done(); @@ -233,11 +254,11 @@ describe('aggregate: ', function() { it('works', function(done) { var aggregate = new Aggregate(); - assert.equal(aggregate.match({a: 1}), aggregate); - assert.deepEqual(aggregate._pipeline, [{$match: {a: 1}}]); + assert.equal(aggregate.match({ a: 1 }), aggregate); + assert.deepEqual(aggregate._pipeline, [{ $match: { a: 1 } }]); - aggregate.match({b: 2}); - assert.deepEqual(aggregate._pipeline, [{$match: {a: 1}}, {$match: {b: 2}}]); + aggregate.match({ b: 2 }); + assert.deepEqual(aggregate._pipeline, [{ $match: { a: 1 } }, { $match: { b: 2 } }]); done(); }); @@ -247,11 +268,11 @@ describe('aggregate: ', function() { it('(object)', function(done) { var aggregate = new Aggregate(); - assert.equal(aggregate.sort({a: 1, b: 'asc', c: 'descending'}), aggregate); - assert.deepEqual(aggregate._pipeline, [{$sort: {a: 1, b: 1, c: -1}}]); + assert.equal(aggregate.sort({ a: 1, b: 'asc', c: 'descending' }), aggregate); + assert.deepEqual(aggregate._pipeline, [{ $sort: { a: 1, b: 1, c: -1 } }]); - aggregate.sort({b: 'desc'}); - assert.deepEqual(aggregate._pipeline, [{$sort: {a: 1, b: 1, c: -1}}, {$sort: {b: -1}}]); + aggregate.sort({ b: 'desc' }); + assert.deepEqual(aggregate._pipeline, [{ $sort: { a: 1, b: 1, c: -1 } }, { $sort: { b: -1 } }]); done(); }); @@ -260,10 +281,10 @@ describe('aggregate: ', function() { var aggregate = new Aggregate(); aggregate.sort(' a b -c '); - assert.deepEqual(aggregate._pipeline, [{$sort: {a: 1, b: 1, c: -1}}]); + assert.deepEqual(aggregate._pipeline, [{ $sort: { a: 1, b: 1, c: -1 } }]); aggregate.sort('b'); - assert.deepEqual(aggregate._pipeline, [{$sort: {a: 1, b: 1, c: -1}}, {$sort: {b: 1}}]); + assert.deepEqual(aggregate._pipeline, [{ $sort: { a: 1, b: 1, c: -1 } }, { $sort: { b: 1 } }]); done(); }); @@ -291,11 +312,11 @@ describe('aggregate: ', function() { it('works', function(done) { var aggregate = new Aggregate(); - assert.equal(aggregate.near({a: 1}), aggregate); - assert.deepEqual(aggregate._pipeline, [{$geoNear: {a: 1}}]); + assert.equal(aggregate.near({ a: 1 }), aggregate); + assert.deepEqual(aggregate._pipeline, [{ $geoNear: { a: 1 } }]); - aggregate.near({b: 2}); - assert.deepEqual(aggregate._pipeline, [{$geoNear: {a: 1}}, {$geoNear: {b: 2}}]); + aggregate.near({ b: 2 }); + assert.deepEqual(aggregate._pipeline, [{ $geoNear: { a: 1 } }, { $geoNear: { b: 2 } }]); done(); }); @@ -314,23 +335,23 @@ describe('aggregate: ', function() { aggregate._model = stub; - assert.equal(aggregate.near({a: 1}), aggregate); + assert.equal(aggregate.near({ a: 1 }), aggregate); // Run exec so we apply discriminator pipeline assert.throws(function() { aggregate.exec(); }, /Cannot read property 'aggregate' of undefined|Cannot call method 'aggregate' of undefined/); assert.deepEqual(aggregate._pipeline, - [{$geoNear: {a: 1, query: {__t: 'subschema'}}}]); + [{ $geoNear: { a: 1, query: { __t: 'subschema' } } }]); aggregate = new Aggregate(); aggregate._model = stub; - aggregate.near({b: 2, query: {x: 1}}); + aggregate.near({ b: 2, query: { x: 1 } }); assert.throws(function() { aggregate.exec(); }, /Cannot read property 'aggregate' of undefined|Cannot call method 'aggregate' of undefined/); assert.deepEqual(aggregate._pipeline, - [{$geoNear: {b: 2, query: {x: 1, __t: 'subschema'}}}]); + [{ $geoNear: { b: 2, query: { x: 1, __t: 'subschema' } } }]); done(); }); @@ -361,7 +382,7 @@ describe('aggregate: ', function() { aggregate.sample(3); assert.equal(aggregate._pipeline.length, 1); - assert.deepEqual(aggregate._pipeline[0].$sample, {size: 3}); + assert.deepEqual(aggregate._pipeline[0].$sample, { size: 3 }); done(); }); }); @@ -369,7 +390,7 @@ describe('aggregate: ', function() { describe('bind', function() { it('works', function(done) { var aggregate = new Aggregate(); - var model = {foo: 42}; + var model = { foo: 42 }; assert.equal(aggregate.model(model), aggregate); assert.equal(aggregate._model, model); @@ -378,62 +399,99 @@ describe('aggregate: ', function() { }); }); - describe('graphLookup', function() { + describe('Mongo 3.4 operators', function() { before(function(done) { - var _this = this; - start.mongodVersion(function(err, version) { - if (err) { - done(err); - return; - } - var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); - if (!mongo34) { - _this.skip(); - } - done(); - }); + onlyTestMongo34(this, done); }); - it('works', function(done) { - var aggregate = new Aggregate(); - aggregate.graphLookup({ - startWith: '$test', - from: 'sourceCollection', - connectFromField: 'testFromField', - connectToField: '_id' - }); + describe('graphLookup', function() { + it('works', function(done) { + var aggregate = new Aggregate(); + aggregate.graphLookup({ + startWith: '$test', + from: 'sourceCollection', + connectFromField: 'testFromField', + connectToField: '_id' + }); - assert.equal(aggregate._pipeline.length, 1); - assert.deepEqual(aggregate._pipeline[0].$graphLookup, { - startWith: '$test', - from: 'sourceCollection', - connectFromField: 'testFromField', - connectToField: '_id' + assert.equal(aggregate._pipeline.length, 1); + assert.deepEqual(aggregate._pipeline[0].$graphLookup, { + startWith: '$test', + from: 'sourceCollection', + connectFromField: 'testFromField', + connectToField: '_id' + }); + done(); }); - done(); - }); - it('automatically prepends $ to the startWith field', function(done) { - var aggregate = new Aggregate(); - aggregate.graphLookup({ - startWith: 'test' + it('automatically prepends $ to the startWith field', function(done) { + var aggregate = new Aggregate(); + aggregate.graphLookup({ + startWith: 'test' + }); + + assert.deepEqual(aggregate._pipeline[0].$graphLookup, { + startWith: '$test' + }); + done(); }); - assert.deepEqual(aggregate._pipeline[0].$graphLookup, { - startWith: '$test' + it('Throws if no options are passed to graphLookup', function(done) { + var aggregate = new Aggregate(); + try { + aggregate.graphLookup('invalid options'); + done(new Error('Should have errored')); + } catch (error) { + assert.ok(error instanceof TypeError); + done(); + } }); - done(); }); - it('Throws if no options are passed to graphLookup', function(done) { - var aggregate = new Aggregate(); - try { - aggregate.graphLookup('invalid options'); - done(new Error('Should have errored')); - } catch (error) { - assert.ok(error instanceof TypeError); + describe('facet', function() { + it('works', function(done) { + var aggregate = new Aggregate(); + + aggregate.facet({ + heights: [ + // This will group documents by their `height` property + { $group: { _id: '$height', count: { $sum: 1 } } }, + // This will sort by descending height + { $sort: { count: -1, _id: -1 } } + ], + players: [ + // This will group documents by their `firstName` property + { + $group: { _id: '$firstName', count: { $sum: 1 } } + }, + // This will sort documents by their firstName descending + { $sort: { count: -1, _id: -1 } } + ] + }); + + assert.equal(aggregate._pipeline.length, 1); + assert.deepEqual(aggregate._pipeline[0].$facet, { + heights: [ + // This will group documents by their `height` property + { $group: { _id: '$height', count: { $sum: 1 } } }, + // This will sort by descending height + { $sort: { count: -1, _id: -1 } } + ], + players: [ + // This will group documents by their `firstName` property + { + $group: { _id: '$firstName', count: { $sum: 1 } + } + }, + + // This will sort documents by their firstName descending + { + $sort: { count: -1, _id: -1 } + } + ] + }); done(); - } + }); }); }); @@ -456,7 +514,7 @@ describe('aggregate: ', function() { aggregate. model(db.model('Employee')). - project({sal: 1, sal_k: {$divide: ['$sal', 1000]}}). + project({ sal: 1, sal_k: { $divide: ['$sal', 1000] } }). exec(function(err, docs) { assert.ifError(err); docs.forEach(function(doc) { @@ -472,7 +530,7 @@ describe('aggregate: ', function() { aggregate. model(db.model('Employee')). - group({_id: '$dept'}). + group({ _id: '$dept' }). exec(function(err, docs) { var depts; assert.ifError(err); @@ -563,7 +621,7 @@ describe('aggregate: ', function() { aggregate. model(db.model('Employee')). - match({sal: {$gt: 15000}}). + match({ sal: { $gt: 15000 } }). exec(function(err, docs) { assert.ifError(err); assert.equal(docs.length, 1); @@ -632,9 +690,9 @@ describe('aggregate: ', function() { aggregate. model(db.model('Employee')). - match({sal: {$lt: 16000}}). + match({ sal: { $lt: 16000 } }). unwind('customers'). - project({emp: '$name', cust: '$customers'}). + project({ emp: '$name', cust: '$customers' }). sort('-cust'). skip(2). exec(function(err, docs) { @@ -662,7 +720,7 @@ describe('aggregate: ', function() { aggregate. model(db.model('Employee')). - match({sal: {$lt: 16000}}). + match({ sal: { $lt: 16000 } }). explain(function(err1, output) { assert.ifError(err1); assert.ok(output); @@ -724,7 +782,7 @@ describe('aggregate: ', function() { var mongo26_or_greater = version[0] > 2 || (version[0] === 2 && version[1] >= 6); var m = db.model('Employee'); - var match = {$match: {sal: {$gt: 15000}}}; + var match = { $match: { sal: { $gt: 15000 } } }; var pref = 'primaryPreferred'; var aggregate = m.aggregate(match).read(pref); if (mongo26_or_greater) { @@ -750,12 +808,12 @@ describe('aggregate: ', function() { it('cursor (gh-3160)', function(done) { var db = start(); - var MyModel = db.model('gh3160', {name: String}); + var MyModel = db.model('gh3160', { name: String }); MyModel.create({ name: 'test' }, function(error) { assert.ifError(error); MyModel. - aggregate([{$match: {name: 'test'}}, {$project:{name:'$name'}}]). + aggregate([{ $match: { name: 'test' } }, { $project: { name: '$name' } }]). allowDiskUse(true). cursor({ batchSize: 2500, async: true }). exec(function(error, cursor) { @@ -772,11 +830,11 @@ describe('aggregate: ', function() { it('cursor() without options (gh-3855)', function(done) { var db = start(); - var MyModel = db.model('gh3855', {name: String}); + var MyModel = db.model('gh3855', { name: String }); db.on('open', function() { var cursor = MyModel. - aggregate([{$match: {name: 'test'}}]). + aggregate([{ $match: { name: 'test' } }]). cursor(). exec(); assert.ok(cursor instanceof require('stream').Readable); @@ -823,7 +881,7 @@ describe('aggregate: ', function() { }); MyModel. - aggregate([{ $match: {name: 'test' } }]). + aggregate([{ $match: { name: 'test' } }]). addCursorFlag('noCursorTimeout', true). cursor({ async: true }). exec(function(error, cursor) { From d08f0d4ef3fd38446f9c4da60aaa6487d2db392c Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Fri, 27 Jan 2017 14:14:59 -0500 Subject: [PATCH 1196/2240] test(Aggregate): Add database call test for facet --- test/aggregate.test.js | 54 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index c9dd89e2023..550c765c34a 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -480,7 +480,8 @@ describe('aggregate: ', function() { players: [ // This will group documents by their `firstName` property { - $group: { _id: '$firstName', count: { $sum: 1 } + $group: { + _id: '$firstName', count: { $sum: 1 } } }, @@ -685,6 +686,57 @@ describe('aggregate: ', function() { } }); + it('facet', function(done) { + var _this = this; + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + _this.skip(); + } + test(); + }); + + function test() { + var aggregate = new Aggregate(); + + aggregate. + model(db.model('Employee')). + facet({ + departments: [ + { + $group: { _id: '$dept', count: { $sum: 1 } } + } + ], + employeesPerCustomer: [ + { $unwind: '$customers' }, + { $sortByCount: '$customers' } + ] + }). + exec(function(error, docs) { + if (error) { + return done(error); + } + assert.deepEqual(docs[0].departments, [ + { _id: 'r&d', count: 2 }, + { _id: 'sales', count: 2 } + ]); + + assert.deepEqual(docs[0].employeesPerCustomer, [ + { _id: 'Herbert', count: 1 }, + { _id: 'Gary', count: 1 }, + { _id: 'Isaac', count: 1 }, + { _id: 'Fred', count: 1 }, + { _id: 'Eve', count: 1 } + ]); + done(); + }); + } + }); + it('complex pipeline', function(done) { var aggregate = new Aggregate(); From 4776208d5b999b81788c7bf7e164a3c9976ee87c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 Jan 2017 15:04:33 -0700 Subject: [PATCH 1197/2240] test(aggregate): fix flakey test --- test/aggregate.test.js | 20 ++++++++++---------- test/model.populate.test.js | 12 +++++++++++- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 550c765c34a..b31e4616bfd 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -23,15 +23,15 @@ var EmployeeSchema = new Schema({ mongoose.model('Employee', EmployeeSchema); function setupData(callback) { - var saved = 0, - emps = [ - { name: 'Alice', sal: 18000, dept: 'sales', customers: ['Eve', 'Fred'] }, - { name: 'Bob', sal: 15000, dept: 'sales', customers: ['Gary', 'Herbert', 'Isaac'], reportsTo: 'Alice' }, - { name: 'Carol', sal: 14000, dept: 'r&d', reportsTo: 'Bob' }, - { name: 'Dave', sal: 14500, dept: 'r&d', reportsTo: 'Carol' } - ], - db = start(), - Employee = db.model('Employee'); + var saved = 0; + var emps = [ + { name: 'Alice', sal: 18000, dept: 'sales', customers: ['Eve', 'Fred'] }, + { name: 'Bob', sal: 15000, dept: 'sales', customers: ['Gary', 'Herbert', 'Isaac'], reportsTo: 'Alice' }, + { name: 'Carol', sal: 14000, dept: 'r&d', reportsTo: 'Bob' }, + { name: 'Dave', sal: 14500, dept: 'r&d', reportsTo: 'Carol' } + ]; + var db = start(); + var Employee = db.model('Employee'); emps.forEach(function(data) { var emp = new Employee(data); @@ -46,7 +46,7 @@ function setupData(callback) { /** * Helper function to test operators that only work in MongoDB 3.4 and above (such as some aggregation pipeline operators) - * + * * @param {Object} ctx, `this`, so that mocha tests can be skipped * @param {Function} done * @return {Void} diff --git a/test/model.populate.test.js b/test/model.populate.test.js index e705572e505..6938fa2ade8 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4602,8 +4602,18 @@ describe('model: populate:', function() { populate('activity.zones', 'name clusters'). exec(function(error, res) { assert.ifError(error); - // Fails if this `.toObject()` is returned, issue #4926 + // Fails if this `.toObject()` is omitted, issue #4926 res = res.toObject(); + var compare = function(a, b) { + if (a.name < b.name) { + return -1; + } else if (b.name < a.name) { + return 1; + } + return 0; + }; + res.activity[0].zones.sort(compare); + res.activity[1].zones.sort(compare); assert.equal(res.activity[0].zones[0].name, 'z1'); assert.equal(res.activity[1].zones[0].name, 'z1'); done(); From a9950955c8652d5bbc8f1bfcee51b6b78cfe3c6b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 Jan 2017 15:56:04 -0700 Subject: [PATCH 1198/2240] chore: upgrade mongodb -> 2.2.22 re: #4931 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 45dd2dc7016..8b3c0813285 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "1.2.0", "kareem": "1.2.0", - "mongodb": "2.2.21", + "mongodb": "2.2.22", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.0.0", From b4729f9ca670b35983916298ff5be2cf42eb3b58 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 Jan 2017 16:25:35 -0700 Subject: [PATCH 1199/2240] test(query): repro #4933 --- test/query.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index 4a465322889..bba2639086f 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1829,6 +1829,19 @@ describe('Query', function() { }); }); + it('$exists under $not (gh-4933)', function(done) { + var TestSchema = new Schema({ + test: String + }); + + var Test = db.model('gh4933', TestSchema); + + Test.findOne({ test: { $not: { $exists: true } } }, function(error) { + assert.ifError(error); + done(); + }); + }); + it('handles geoWithin with mongoose docs (gh-4392)', function(done) { var areaSchema = new Schema({ name: {type: String}, From 0c6165a0dc6deaccad784321c0bdae339827bc8d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 Jan 2017 16:26:46 -0700 Subject: [PATCH 1200/2240] fix(query): handle casting $exists under $not Fix #4933 --- lib/cast.js | 7 ------- lib/schematype.js | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index e9e0ada3339..70473c85a89 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -200,13 +200,6 @@ module.exports = function cast(schema, obj, options) { $cond = ks[k]; nested = val[$cond]; - if ($cond === '$exists') { - if (typeof nested !== 'boolean') { - throw new Error('$exists parameter must be Boolean'); - } - continue; - } - if ($cond === '$not') { if (nested && schematype && !schematype.caster) { _keys = Object.keys(nested); diff --git a/lib/schematype.js b/lib/schematype.js index 3ca3423618b..bdd4e33bf7c 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -879,6 +879,13 @@ SchemaType.prototype.$conditionalHandlers = { $in: handleArray, $ne: handleSingle, $nin: handleArray, + $exists: function(val) { + if (typeof val !== 'boolean') { + throw new Error('$exists parameter must be a boolean!'); + } + + return val; + }, $type: function(val) { if (typeof val !== 'number' && typeof val !== 'string') { throw new Error('$type parameter must be number or string'); From 39d05ac768af2711383253585d0e91bbd9afa822 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 Jan 2017 16:59:11 -0700 Subject: [PATCH 1201/2240] chore: release 4.7.9 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index bb79039ea0e..ac5fbe3a69d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +4.7.9 / 2017-01-27 +================== + * fix(query): handle casting $exists under $not #4933 + * chore: upgrade mongodb -> 2.2.22 re: #4931 + 4.7.8 / 2017-01-23 ================== * fix(populate): better handling for virtual populate under arrays #4923 diff --git a/package.json b/package.json index 8b3c0813285..4372f9db726 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.9-pre", + "version": "4.7.9", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ea379941aae2f77057a0d849aaaf7aa55b1efbd8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 Jan 2017 17:01:03 -0700 Subject: [PATCH 1202/2240] chore: now working on 4.7.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4372f9db726..642a5e1032d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.9", + "version": "4.7.10-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 3e76041dc2b608181586527f31d3796582893215 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Jan 2017 19:41:47 -0700 Subject: [PATCH 1203/2240] test(aggregate): make test more robust --- test/aggregate.test.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index b31e4616bfd..9a46b926a65 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -713,7 +713,8 @@ describe('aggregate: ', function() { ], employeesPerCustomer: [ { $unwind: '$customers' }, - { $sortByCount: '$customers' } + { $sortByCount: '$customers' }, + { $sort: { _id: 1 } } ] }). exec(function(error, docs) { @@ -726,11 +727,11 @@ describe('aggregate: ', function() { ]); assert.deepEqual(docs[0].employeesPerCustomer, [ - { _id: 'Herbert', count: 1 }, - { _id: 'Gary', count: 1 }, - { _id: 'Isaac', count: 1 }, + { _id: 'Eve', count: 1 }, { _id: 'Fred', count: 1 }, - { _id: 'Eve', count: 1 } + { _id: 'Gary', count: 1 }, + { _id: 'Herbert', count: 1 }, + { _id: 'Isaac', count: 1 } ]); done(); }); From b03d06c4a2a92268641d12d8a263a190b65163ad Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Jan 2017 20:15:00 -0700 Subject: [PATCH 1204/2240] chore: release 4.8.0 --- History.md | 19 +++++++++++++++++++ package.json | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ac5fbe3a69d..344c4edba1d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,22 @@ +4.8.0 / 2017-01-28 +================== + * feat(schema): add saveErrorIfNotFound option and $where property #4924 #4004 + * feat(query): add $in implicitly if passed an array #4912 [QuotableWater7](https://github.com/QuotableWater7) + * feat(aggregate): helper for $facet #4904 [varunjayaraman](https://github.com/varunjayaraman) + * feat(query): add collation method #4839 + * feat(schema): propogate strict option to implicit array subschemas #4831 [dkrosso](https://github.com/dkrosso) + * feat(aggregate): add helper for graphLookup #4819 [varunjayaraman](https://github.com/varunjayaraman) + * feat(types): support Decimal128 #4759 + * feat(aggregate): add eachAsync() to aggregate cursor #4300 + * feat(query): add updateOne and updateMany #3997 + * feat(model): support options for insertMany #3893 + * fix(document): run validation on single nested docs if not directly modified #3884 + * feat(model): use discriminator constructor based on discriminatorKey in create() #3624 + * feat: pass collection as context to debug function #3261 + * feat(query): support push and addToSet for update validators #2933 + * feat(types): add discriminator() function to doc arrays #2723 #1856 + * fix(populate): return an error if sorting underneath a doc array #2202 + 4.7.9 / 2017-01-27 ================== * fix(query): handle casting $exists under $not #4933 diff --git a/package.json b/package.json index 1c224873fdd..c22717bbb18 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.7.10-pre", + "version": "4.8.0", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 6b976e1da6129a4098f23011ed8efecb2cc5b225 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 Jan 2017 16:07:01 -0700 Subject: [PATCH 1205/2240] docs: add missing issue to 4.8.0 --- History.md | 1 + 1 file changed, 1 insertion(+) diff --git a/History.md b/History.md index 344c4edba1d..e4398cbfbf4 100644 --- a/History.md +++ b/History.md @@ -14,6 +14,7 @@ * feat(model): use discriminator constructor based on discriminatorKey in create() #3624 * feat: pass collection as context to debug function #3261 * feat(query): support push and addToSet for update validators #2933 + * perf(document): refactor registerHooksFromSchema so hooks are defined on doc prototype #2754 * feat(types): add discriminator() function to doc arrays #2723 #1856 * fix(populate): return an error if sorting underneath a doc array #2202 From 65e460b1c12324be11ff83cf1b9af5c164350ff6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 Jan 2017 16:07:20 -0700 Subject: [PATCH 1206/2240] chore: now working on 4.8.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c22717bbb18..372aa99fc07 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.0", + "version": "4.8.1-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c2b55e8d741891960577b6a62567a8dcfdbf29c3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 Jan 2017 17:34:54 -0700 Subject: [PATCH 1207/2240] fix(query): handle passing string to hint() Fix #4934 --- package.json | 2 +- test/query.test.js | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 372aa99fc07..463cebf33a6 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.2.22", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "2.2.0", + "mquery": "2.2.1", "ms": "0.7.2", "muri": "1.2.0", "regexp-clone": "0.0.1", diff --git a/test/query.test.js b/test/query.test.js index 06aa1627dd1..b81b946fb79 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1251,10 +1251,9 @@ describe('Query', function() { query2.hint({indexAttributeA: 1, indexAttributeB: -1}); assert.deepEqual(query2.options.hint, {indexAttributeA: 1, indexAttributeB: -1}); - assert.throws(function() { - var query3 = new Query({}, {}, null, p1.collection); - query3.hint('indexAttributeA'); - }, /Invalid hint./); + var query3 = new Query({}, {}, null, p1.collection); + query3.hint('indexAttributeA_1'); + assert.deepEqual(query3.options.hint, 'indexAttributeA_1'); done(); }); From 0bcc100600596f5fa59d25f89e8ed677e364ec13 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 Jan 2017 17:48:27 -0700 Subject: [PATCH 1208/2240] test(query): repro #4937 --- test/query.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index b81b946fb79..03d95f25f76 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1883,6 +1883,24 @@ describe('Query', function() { }); }); + it('$exists for arrays and embedded docs (gh-4937)', function(done) { + var subSchema = new Schema({ + name: String + }); + var TestSchema = new Schema({ + test: [String], + sub: subSchema + }); + + var Test = db.model('gh4937', TestSchema); + + var q = { test: { $exists: true }, sub: { $exists: false } }; + Test.findOne(q, function(error) { + assert.ifError(error); + done(); + }); + }); + it('handles geoWithin with mongoose docs (gh-4392)', function(done) { var areaSchema = new Schema({ name: {type: String}, From 3004993b9083ad413e16fbe81363f1bf7bf12fc0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 Jan 2017 17:49:48 -0700 Subject: [PATCH 1209/2240] fix(query): handle $exists for arrays and embedded docs Fix #4937 --- lib/schema/array.js | 3 +++ lib/schema/embedded.js | 3 +++ lib/schema/operators/exists.js | 9 +++++++++ lib/schematype.js | 9 ++------- 4 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 lib/schema/operators/exists.js diff --git a/lib/schema/array.js b/lib/schema/array.js index 06a708a8e73..b0035e89fa1 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -2,6 +2,7 @@ * Module dependencies. */ +var $exists = require('./operators/exists'); var SchemaType = require('../schematype'); var CastError = SchemaType.CastError; var Types = { @@ -297,6 +298,8 @@ handle.$size = handle.$minDistance = handle.$maxDistance = castToNumber; +handle.$exists = $exists; + handle.$eq = handle.$gt = handle.$gte = diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 2ea88aaf19e..ea705ca2db9 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -4,6 +4,7 @@ * Module dependencies. */ +var $exists = require('./operators/exists'); var EventEmitter = require('events').EventEmitter; var SchemaType = require('../schematype'); var Subdocument = require('../types/subdocument'); @@ -111,6 +112,8 @@ Embedded.prototype.$conditionalHandlers.$geoIntersects = Embedded.prototype.$conditionalHandlers.$minDistance = castToNumber; Embedded.prototype.$conditionalHandlers.$maxDistance = castToNumber; +Embedded.prototype.$conditionalHandlers.$exists = $exists; + /** * Casts contents * diff --git a/lib/schema/operators/exists.js b/lib/schema/operators/exists.js new file mode 100644 index 00000000000..11c5a66ae63 --- /dev/null +++ b/lib/schema/operators/exists.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports = function(val) { + if (typeof val !== 'boolean') { + throw new Error('$exists parameter must be a boolean!'); + } + + return val; +}; diff --git a/lib/schematype.js b/lib/schematype.js index 6e718e770f1..bf594bc6a4b 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -2,6 +2,7 @@ * Module dependencies. */ +var $exists = require('./schema/operators/exists'); var utils = require('./utils'); var MongooseError = require('./error'); var CastError = MongooseError.CastError; @@ -879,13 +880,7 @@ SchemaType.prototype.$conditionalHandlers = { $in: handleArray, $ne: handleSingle, $nin: handleArray, - $exists: function(val) { - if (typeof val !== 'boolean') { - throw new Error('$exists parameter must be a boolean!'); - } - - return val; - }, + $exists: $exists, $type: function(val) { if (typeof val !== 'number' && typeof val !== 'string') { throw new Error('$type parameter must be number or string'); From 58d68946eeff9f84a49257d12efe726e956aca52 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Jan 2017 19:01:27 -0700 Subject: [PATCH 1210/2240] chore: 4.8.1 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e4398cbfbf4..36a14f5c3c6 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +4.8.1 / 2017-01-30 +================== + * fix(query): handle $exists for arrays and embedded docs #4937 + * fix(query): handle passing string to hint() #4931 + 4.8.0 / 2017-01-28 ================== * feat(schema): add saveErrorIfNotFound option and $where property #4924 #4004 diff --git a/package.json b/package.json index 463cebf33a6..6d07a35631d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.1-pre", + "version": "4.8.1", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 9f446bb8fbcf7871c145aad1211bc98716976756 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Jan 2017 19:04:08 -0700 Subject: [PATCH 1211/2240] chore: add missing comment --- lib/schema/operators/exists.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/schema/operators/exists.js b/lib/schema/operators/exists.js index 11c5a66ae63..6716112e6b6 100644 --- a/lib/schema/operators/exists.js +++ b/lib/schema/operators/exists.js @@ -1,5 +1,9 @@ 'use strict'; +/*! + * ignore + */ + module.exports = function(val) { if (typeof val !== 'boolean') { throw new Error('$exists parameter must be a boolean!'); From 57db70195a699130a047480f432f0e4d7166c755 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Jan 2017 19:05:13 -0700 Subject: [PATCH 1212/2240] chore: now working on 4.8.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6d07a35631d..9625c93160b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.1", + "version": "4.8.2-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 3ce709bf45c8d69444106509f44efd19c47baac0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 31 Jan 2017 19:26:43 -0700 Subject: [PATCH 1213/2240] fix(query): allow passing Map to sort() Fix #4941 --- lib/query.js | 14 +------------- package.json | 2 +- test/query.test.js | 10 +++++++++- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/lib/query.js b/lib/query.js index 7660d621bc7..dea087ea2a8 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1553,23 +1553,11 @@ Query.prototype.distinct = function(field, conditions, callback) { */ Query.prototype.sort = function(arg) { - var nArg = {}; - if (arguments.length > 1) { throw new Error('sort() only takes 1 Argument'); } - if (Array.isArray(arg)) { - // time to deal with the terrible syntax - for (var i = 0; i < arg.length; i++) { - if (!Array.isArray(arg[i])) throw new Error('Invalid sort() argument.'); - nArg[arg[i][0]] = arg[i][1]; - } - } else { - nArg = arg; - } - - return Query.base.sort.call(this, nArg); + return Query.base.sort.call(this, arg); }; /** diff --git a/package.json b/package.json index 9625c93160b..3ce039a473c 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.2.22", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "2.2.1", + "mquery": "2.2.3", "ms": "0.7.2", "muri": "1.2.0", "regexp-clone": "0.0.1", diff --git a/test/query.test.js b/test/query.test.js index 03d95f25f76..fa919d90e24 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -725,6 +725,14 @@ describe('Query', function() { query = new Query({}, {}, null, p1.collection); query.sort({a: 1, c: -1, b: 'asc', e: 'descending', f: 'ascending'}); assert.deepEqual(query.options.sort, {a: 1, c: -1, b: 1, e: -1, f: 1}); + + if (typeof global.Map !== 'undefined') { + query = new Query({}, {}, null, p1.collection); + query.sort(new global.Map().set('a', 1).set('b', 2)); + assert.deepEqual(query.options.sort, + new global.Map().set('a', 1).set('b', 2)); + } + query = new Query({}, {}, null, p1.collection); var e; @@ -735,7 +743,7 @@ describe('Query', function() { } assert.ok(e, 'uh oh. no error was thrown'); - assert.equal(e.message, 'Invalid sort() argument.'); + assert.equal(e.message, 'Invalid sort() argument, must be array of arrays'); e = undefined; try { From 6650dbddc0c8b365ccebdfa5fd5c60c2d9775f7b Mon Sep 17 00:00:00 2001 From: ValYouW Date: Wed, 1 Feb 2017 13:16:37 +0200 Subject: [PATCH 1214/2240] Fix bug where updaing a Buffer to null it threw exception --- lib/schema/buffer.js | 3 ++- test/types.buffer.test.js | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js index e59de74e250..56490dea878 100644 --- a/lib/schema/buffer.js +++ b/lib/schema/buffer.js @@ -178,7 +178,8 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) { return handler.call(this, val); } val = $conditional; - return this.cast(val).toObject({ transform: false, virtuals: false }); + var casted = this.cast(val); + return casted ? casted.toObject({ transform: false, virtuals: false }) : casted; }; /*! diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js index 3254438bcc3..758cc390bc3 100644 --- a/test/types.buffer.test.js +++ b/test/types.buffer.test.js @@ -378,6 +378,21 @@ describe('types.buffer', function() { }); }); + it('can be updated to null', function(done) { + var db = start(), + User = db.model('UserBuffer', UserBuffer, 'usersbuffer_' + random()); + var user = new User({array: [null], required: new Buffer(1), serial: new Buffer(1)}); + user.save(function(err, doc) { + assert.ifError(err); + User.findOneAndUpdate({_id: doc.id}, {serial: null}, {new: true}, function(err, doc) { + db.close(); + assert.ifError(err); + assert.equal(doc.serial, null); + done(); + }); + }); + }); + describe('#toObject', function() { it('retains custom subtypes', function(done) { var buf = new MongooseBuffer(0); From bbd8da6f3d6a8aab3711121e50b05a1eff91a74d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 1 Feb 2017 21:44:53 -0700 Subject: [PATCH 1215/2240] fix(connection): upgrade muri -> 1.2.1 Re: aheckmann/muri#11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ce039a473c..c5140fce7ac 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "mpromise": "0.5.5", "mquery": "2.2.3", "ms": "0.7.2", - "muri": "1.2.0", + "muri": "1.2.1", "regexp-clone": "0.0.1", "sliced": "1.0.1" }, From 706486ebc7e08282a0d708a2c7959d1744437377 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 3 Feb 2017 11:31:50 -0700 Subject: [PATCH 1216/2240] test(query): repro #4927 --- test/query.middleware.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 176f83c8dc5..5d3cfa378b7 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -367,4 +367,31 @@ describe('query middleware', function() { done(); }); }); + + it('error handlers with error from pre hook (gh-4927)', function(done) { + var schema = new Schema({}); + var called = false; + + schema.pre('find', function(next) { + next(new Error('test')); + }); + + schema.post('find', function(res, next) { + called = true; + next(); + }); + + schema.post('find', function(error, res, next) { + assert.equal(error.message, 'test'); + next(new Error('test2')); + }); + + var Test = db.model('gh4927', schema); + + Test.find().exec(function(error) { + assert.equal(error.message, 'test2'); + assert.ok(!called); + done(); + }); + }); }); From 0e382693cb2d35a1871c2575b93108b4ab311e0e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 3 Feb 2017 11:32:45 -0700 Subject: [PATCH 1217/2240] fix(query): ensure consistent params in error handlers if pre hook errors Fix #4927 --- lib/query.js | 5 ++++- package.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index dea087ea2a8..7cdc7c7fb0e 100644 --- a/lib/query.js +++ b/lib/query.js @@ -71,7 +71,10 @@ function Query(conditions, options, model, collection) { } if (this.schema) { - var kareemOptions = { useErrorHandlers: true }; + var kareemOptions = { + useErrorHandlers: true, + numCallbackParams: 1 + }; this._count = this.model.hooks.createWrapper('count', Query.prototype._count, this, kareemOptions); this._execUpdate = this.model.hooks.createWrapper('update', diff --git a/package.json b/package.json index c5140fce7ac..1b22815aa0a 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "2.1.4", "bson": "~1.0.4", "hooks-fixed": "1.2.0", - "kareem": "1.2.0", + "kareem": "1.2.1", "mongodb": "2.2.22", "mpath": "0.2.1", "mpromise": "0.5.5", From f19b88f16e97b0ccc90f0462a130ab129bd9d0a8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 3 Feb 2017 13:07:38 -0700 Subject: [PATCH 1218/2240] fix(schema): return correct value from pre init hook re: #4928 --- lib/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 2f9e7275300..5dfa030c7f5 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1456,7 +1456,7 @@ Schema.prototype.virtual = function(name, options) { } if (this.ownerDocument) { next(); - return obj; + return this; } else { next(); } From 1631e60de9adb7328887dfdc9ec438c8535accb0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 3 Feb 2017 13:27:17 -0700 Subject: [PATCH 1219/2240] test(query): repro #4928 --- test/model.populate.test.js | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 6938fa2ade8..ab9acd30bbe 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4116,6 +4116,46 @@ describe('model: populate:', function() { }); }); + it('in embedded array (gh-4928)', function(done) { + var PersonSchema = new Schema({ + name: String, + authored: [Number] + }); + + var BlogPostSchema = new Schema({ + _id: Number, + title: String + }); + BlogPostSchema.virtual('author', { + ref: 'gh4928', + localField: '_id', + foreignField: 'authored', + justOne: true + }); + + var CollectionSchema = new Schema({ + blogPosts: [BlogPostSchema] + }); + + var Person = db.model('gh4928', PersonSchema); + var Collection = db.model('gh4928_0', CollectionSchema); + + Person.create({ name: 'Val', authored: 1 }). + then(function() { + return Collection.create({ + blogPosts: [{ _id: 1, title: 'Test' }] + }); + }). + then(function(c) { + return Collection.findById(c._id).populate('blogPosts.author'); + }). + then(function(c) { + assert.equal(c.blogPosts[0].author.name, 'Val'); + done(); + }). + catch(done); + }); + it('justOne option (gh-4263)', function(done) { var PersonSchema = new Schema({ name: String, From 2c4e5979cf14647177cd22d77732ab8e1b2eb18f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Feb 2017 23:04:32 -0700 Subject: [PATCH 1220/2240] test(document): repro #4935 --- test/document.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index fbc5bbe91bc..237c9b829e0 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3791,6 +3791,27 @@ describe('document', function() { done(); }); + it('setting to discriminator (gh-4935)', function(done) { + var Buyer = db.model('gh4935_0', new Schema({ + name: String, + vehicle: { type: Schema.Types.ObjectId, ref: 'gh4935' } + })); + var Vehicle = db.model('gh4935', new Schema({ name: String })); + var Car = Vehicle.discriminator('gh4935_1', new Schema({ + model: String + })); + + var eleanor = new Car({ name: 'Eleanor', model: 'Shelby Mustang GT' }); + var nick = new Buyer({ name: 'Nicolas', vehicle: eleanor }); + + assert.ok(!!nick.vehicle); + assert.ok(nick.vehicle === eleanor); + assert.ok(nick.vehicle instanceof Car); + assert.equal(nick.vehicle.name, 'Eleanor'); + + done(); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From 4b1bdb01aaeb57d2154a3a1887ea0543e8e9e8bd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Feb 2017 23:05:33 -0700 Subject: [PATCH 1221/2240] fix(document): handle setting discriminator doc Fix #4935 --- lib/document.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 8d0e62b51c4..022f14b0221 100644 --- a/lib/document.js +++ b/lib/document.js @@ -732,7 +732,7 @@ Document.prototype.set = function(path, val, type, options) { if (schema.options && schema.options.ref && val instanceof Document && - schema.options.ref === val.constructor.modelName) { + (schema.options.ref === val.constructor.modelName || schema.options.ref === val.constructor.baseModelName)) { if (this.ownerDocument) { this.ownerDocument().populated(this.$__fullPath(path), val._id, {model: val.constructor}); @@ -751,7 +751,7 @@ Document.prototype.set = function(path, val, type, options) { val.length > 0 && val[0] instanceof Document && val[0].constructor.modelName && - schema.options.type[0].ref === (val[0].constructor.baseModelName || val[0].constructor.modelName)) { + (schema.options.type[0].ref === val[0].constructor.baseModelName || schema.options.type[0].ref === val[0].constructor.modelName)) { if (this.ownerDocument) { popOpts = { model: val[0].constructor }; this.ownerDocument().populated(this.$__fullPath(path), From d20ae4e79aab3dadf43c40b8ec7ba1d138ae375c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 5 Feb 2017 14:17:09 -0700 Subject: [PATCH 1222/2240] test(discriminator): repro #4942 --- test/model.discriminator.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 6653ec75d9e..b64be1fbcf5 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -379,6 +379,25 @@ describe('model', function() { }); }); + it('with loadClass (gh-4942)', function(done) { + if (!global.Promise) { + // Skip if not using node >= 4 + this.skip(); + } + + // Dirty hack to make eslint stop complaining + var Shape = eval('class Shape extends mongoose.Model { }'); + var Circle = eval('class Circle extends Shape { }'); + mongoose.model(Shape, new Schema({ color: String })); + Shape.discriminator(Circle, new Schema({ radius: Number })); // <<< Throws here + + var circle = new Circle(); + + assert.ok(circle instanceof Circle); + assert.ok(circle instanceof Shape); + done(); + }); + it('embedded in document arrays (gh-2723)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From 85bbce54c0a1f08b75085f15715764bd430aea80 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 5 Feb 2017 14:17:32 -0700 Subject: [PATCH 1223/2240] fix(discriminator): handle subclassing with loadClass correctly Fix #4942 --- lib/model.js | 13 +++++++++++-- lib/schema.js | 4 +++- lib/services/model/discriminator.js | 11 ++++++++--- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index 3a88291fa4a..8b6acc7799f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -56,6 +56,7 @@ function Model(doc, fields, skipId) { */ Model.prototype.__proto__ = Document.prototype; +Model.prototype.$isMongooseModelPrototype = true; /** * Connection the model uses. @@ -830,8 +831,15 @@ Model.discriminator = function(name, schema) { throw new OverwriteModelError(name); } - this.discriminators[name] = this.db.model(name, schema, this.collection.name); - var d = this.discriminators[name]; + var _name; + if (typeof name === 'function') { + _name = utils.getFunctionName(name); + } else { + _name = name; + } + + this.discriminators[_name] = this.db.model(name, schema, this.collection.name); + var d = this.discriminators[_name]; d.prototype.__proto__ = this.prototype; Object.defineProperty(d, 'baseModelName', { value: this.modelName, @@ -3271,6 +3279,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base) model = name; name = model.name; schema.loadClass(model, true); + model.prototype.$isMongooseModelPrototype = true; } else { // generate new class model = function model(doc, fields, skipId) { diff --git a/lib/schema.js b/lib/schema.js index 5dfa030c7f5..c81d698b089 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1582,7 +1582,9 @@ Schema.prototype.remove = function(path) { * @param {Function} model */ Schema.prototype.loadClass = function(model, virtualsOnly) { - if (model === Object.prototype || model === Function.prototype) { + if (model === Object.prototype || + model === Function.prototype || + model.prototype.hasOwnProperty('$isMongooseModelPrototype')) { return this; } diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 52b36c4593d..b3337067372 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -18,6 +18,11 @@ module.exports = function discriminator(model, name, schema) { throw new Error('You must pass a valid discriminator Schema'); } + var _name = name; + if (typeof name === 'function') { + _name = utils.getFunctionName(name); + } + if (model.schema.discriminatorMapping && !model.schema.discriminatorMapping.isRoot) { throw new Error('Discriminator "' + name + @@ -35,10 +40,10 @@ module.exports = function discriminator(model, name, schema) { var obj = {}; obj[key] = { - default: name, + default: _name, set: function(newName) { - if (newName === name) { - return name; + if (newName === _name) { + return _name; } throw new Error('Can\'t set discriminator key "' + key + '"'); } From 490fee74e663895264d84f98e2d9d22aba9c691d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Feb 2017 11:42:15 -0700 Subject: [PATCH 1224/2240] chore: ignore model.discriminator.test for now --- .eslintignore | 1 + test/model.discriminator.test.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.eslintignore b/.eslintignore index 235bdcd4f7d..b1109fb5b0a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ docs/ bin/ test/triage/ +test/model.discriminator.test.js diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index b64be1fbcf5..cc094a1aa63 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -386,10 +386,10 @@ describe('model', function() { } // Dirty hack to make eslint stop complaining - var Shape = eval('class Shape extends mongoose.Model { }'); - var Circle = eval('class Circle extends Shape { }'); + class Shape extends mongoose.Model { }; + class Circle extends Shape { }; mongoose.model(Shape, new Schema({ color: String })); - Shape.discriminator(Circle, new Schema({ radius: Number })); // <<< Throws here + Shape.discriminator(Circle, new Schema({ radius: Number })); var circle = new Circle(); From a128bd0a861618d5226e97f76bff4042514cbef5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Feb 2017 21:43:53 -0700 Subject: [PATCH 1225/2240] test(update): repro #4953 --- test/model.update.test.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 254f021d29e..a0d680aa793 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2085,6 +2085,35 @@ describe('model: update:', function() { }); }); + it('addToSet (gh-4953)', function(done) { + var childSchema = new mongoose.Schema({ + name: { + type: String, + required: true + }, + lastName: { + type: String, + required: true + } + }); + + var parentSchema = new mongoose.Schema({ + children: [childSchema] + }); + + var Model = db.model('gh4953', parentSchema); + + var update = { + $addToSet: { children: { name: 'Test' } } + }; + var opts = { new: true, runValidators: true }; + Model.findOneAndUpdate({}, update, opts, function(error) { + assert.ok(error); + assert.ok(error.errors['children']); + done(); + }); + }); + it('overwrite with timestamps (gh-4054)', function(done) { var testSchema = new Schema({ user: String, From 4113f31ae3908d37e78b5d36f8cd1e19a772d09d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Feb 2017 21:44:09 -0700 Subject: [PATCH 1226/2240] fix(update): actually run validators on addToSet Fix #4953 --- lib/services/updateValidators.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index ee7948aa310..4c710ab4a9a 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -32,7 +32,7 @@ module.exports = function(query, schema, castedDoc, options) { for (var i = 0; i < numKeys; ++i) { if (keys[i].charAt(0) === '$') { - if (keys[i] === '$push') { + if (keys[i] === '$push' || keys[i] === '$addToSet') { _keys = Object.keys(castedDoc[keys[i]]); for (var ii = 0; ii < _keys.length; ++ii) { if (castedDoc[keys[i]][_keys[ii]].$each) { From 09932753ef4570b38460ccb56c84a92a6ed2ebdb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Feb 2017 23:13:22 -0800 Subject: [PATCH 1227/2240] chore: upgrade mocha --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b22815aa0a..30c21cdde6f 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "lodash": "4.16.6", "markdown": "0.3.1", "marked": "0.3.6", - "mocha": "3.1.2", + "mocha": "3.2.0", "mongoose-long": "0.1.1", "node-static": "0.7.7", "power-assert": "1.4.1", From 3d23e47e99c14b94fd3add53c5bf70b5fe5462a2 Mon Sep 17 00:00:00 2001 From: Ben James Date: Thu, 9 Feb 2017 20:16:10 +0000 Subject: [PATCH 1228/2240] Fix #4947 by ensuring class is created with new keyword --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 8b6acc7799f..f16f27cc5c6 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1823,7 +1823,7 @@ Model.create = function create(doc, callback) { var Model = _this.discriminators && doc[discriminatorKey] ? _this.discriminators[doc[discriminatorKey]] : _this; - var toSave = doc instanceof Model ? doc : Model(doc); + var toSave = doc instanceof Model ? doc : new Model(doc); var callbackWrapper = function(error, doc) { if (error) { return callback(error); From 24ddf18e6a40ea44640940f1259ef0f59f3052b1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Feb 2017 22:39:59 -0700 Subject: [PATCH 1229/2240] test: add strict mode --- test/model.discriminator.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index cc094a1aa63..7d260362000 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -380,6 +380,8 @@ describe('model', function() { }); it('with loadClass (gh-4942)', function(done) { + 'use strict'; + if (!global.Promise) { // Skip if not using node >= 4 this.skip(); From 370cbc05b290a76ad234b3611de0078712d519f6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Feb 2017 22:46:00 -0700 Subject: [PATCH 1230/2240] test: use eval() to avoid syntax errors --- test/model.discriminator.test.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 7d260362000..5b1e5711623 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -380,24 +380,24 @@ describe('model', function() { }); it('with loadClass (gh-4942)', function(done) { - 'use strict'; - if (!global.Promise) { // Skip if not using node >= 4 this.skip(); } - // Dirty hack to make eslint stop complaining - class Shape extends mongoose.Model { }; - class Circle extends Shape { }; - mongoose.model(Shape, new Schema({ color: String })); - Shape.discriminator(Circle, new Schema({ radius: Number })); + // Dirty hack to make eslint and node stop complaining + eval(` + class Shape extends mongoose.Model { }; + class Circle extends Shape { }; + mongoose.model(Shape, new Schema({ color: String })); + Shape.discriminator(Circle, new Schema({ radius: Number })); - var circle = new Circle(); + var circle = new Circle(); - assert.ok(circle instanceof Circle); - assert.ok(circle instanceof Shape); - done(); + assert.ok(circle instanceof Circle); + assert.ok(circle instanceof Shape); + done(); + `); }); it('embedded in document arrays (gh-2723)', function(done) { From b5ca6641acd365add832a93ee8c4bdc7af27ac1f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Feb 2017 22:48:51 -0700 Subject: [PATCH 1231/2240] test: fix 0.12 tests --- History.md | 10 ++++++++++ test/model.discriminator.test.js | 24 ++++++++++++------------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/History.md b/History.md index 36a14f5c3c6..ecce3ee129d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.8.2 / 2017-02-10 +================== + * fix(update): actually run validators on addToSet #4953 + * fix(update): improve buffer error handling #4944 [ValYouW](https://github.com/ValYouW) + * fix(discriminator): handle subclassing with loadClass correctly #4942 + * fix(query): allow passing Map to sort() #4941 + * fix(document): handle setting discriminator doc #4935 + * fix(schema): return correct value from pre init hook #4928 + * fix(query): ensure consistent params in error handlers if pre hook errors #4927 + 4.8.1 / 2017-01-30 ================== * fix(query): handle $exists for arrays and embedded docs #4937 diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 5b1e5711623..a25c48a3236 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -386,18 +386,18 @@ describe('model', function() { } // Dirty hack to make eslint and node stop complaining - eval(` - class Shape extends mongoose.Model { }; - class Circle extends Shape { }; - mongoose.model(Shape, new Schema({ color: String })); - Shape.discriminator(Circle, new Schema({ radius: Number })); - - var circle = new Circle(); - - assert.ok(circle instanceof Circle); - assert.ok(circle instanceof Shape); - done(); - `); + eval( + 'class Shape extends mongoose.Model { };\n' + + 'class Circle extends Shape { };\n' + + 'mongoose.model(Shape, new Schema({ color: String }));\n' + + 'Shape.discriminator(Circle, new Schema({ radius: Number }));\n\n' + + + 'var circle = new Circle();\n' + + + 'assert.ok(circle instanceof Circle);\n' + + 'assert.ok(circle instanceof Shape);\n' + + 'done();' + ); }); it('embedded in document arrays (gh-2723)', function(done) { From 7960369d4b3be65ea7ba73dd5ec554c3e98ff2f1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Feb 2017 22:52:28 -0700 Subject: [PATCH 1232/2240] test: fix tests again --- test/model.discriminator.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index a25c48a3236..30d6187fc66 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -380,6 +380,7 @@ describe('model', function() { }); it('with loadClass (gh-4942)', function(done) { + if (!global.Promise) { // Skip if not using node >= 4 this.skip(); @@ -387,6 +388,7 @@ describe('model', function() { // Dirty hack to make eslint and node stop complaining eval( + '"use strict";\n\n' + 'class Shape extends mongoose.Model { };\n' + 'class Circle extends Shape { };\n' + 'mongoose.model(Shape, new Schema({ color: String }));\n' + From f5770419190375c087b24457f1f931600b9b8a41 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Feb 2017 22:56:36 -0700 Subject: [PATCH 1233/2240] test: remove bad test --- test/model.discriminator.test.js | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 30d6187fc66..6653ec75d9e 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -379,29 +379,6 @@ describe('model', function() { }); }); - it('with loadClass (gh-4942)', function(done) { - - if (!global.Promise) { - // Skip if not using node >= 4 - this.skip(); - } - - // Dirty hack to make eslint and node stop complaining - eval( - '"use strict";\n\n' + - 'class Shape extends mongoose.Model { };\n' + - 'class Circle extends Shape { };\n' + - 'mongoose.model(Shape, new Schema({ color: String }));\n' + - 'Shape.discriminator(Circle, new Schema({ radius: Number }));\n\n' + - - 'var circle = new Circle();\n' + - - 'assert.ok(circle instanceof Circle);\n' + - 'assert.ok(circle instanceof Shape);\n' + - 'done();' - ); - }); - it('embedded in document arrays (gh-2723)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From 5dffa95b9a5813c279d7b14537180773f38592b5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Feb 2017 23:00:59 -0700 Subject: [PATCH 1234/2240] chore: release 4.8.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 30c21cdde6f..7134310afdf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.2-pre", + "version": "4.8.2", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4f98a0413403623367b9e7ad14cbdaaaa2f792cf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Feb 2017 23:03:32 -0700 Subject: [PATCH 1235/2240] chore: now working on 4.8.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7134310afdf..93a98294a55 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.2", + "version": "4.8.3-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 0251bf89e527567dfe5a1005da42587e70bdbf20 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Feb 2017 16:11:24 -0700 Subject: [PATCH 1236/2240] test(populate): repro #4959 --- test/model.populate.test.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index ab9acd30bbe..8a39af66f22 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4985,6 +4985,43 @@ describe('model: populate:', function() { catch(done); }); + it('select foreignField automatically (gh-4959)', function(done) { + var childSchema = new mongoose.Schema({ + name: String, + parentId: mongoose.Schema.Types.ObjectId + }); + + var Child = db.model('gh4959', childSchema); + + var parentSchema = new mongoose.Schema({ + name: String + }); + + parentSchema.virtual('detail', { + ref: 'gh4959', + localField: '_id', + foreignField: 'parentId', + justOne: true + }); + + var Parent = db.model('gh4959_0', parentSchema); + + Parent.create({ name: 'Test' }). + then(function(m) { + return Child.create({ name: 'test', parentId: m._id }); + }). + then(function() { + return Parent.find().populate({ path: 'detail', select: 'name' }); + }). + then(function(res) { + var m = res[0]; + assert.equal(m.detail.name, 'test'); + assert.ok(m.detail.parentId); + done(); + }). + catch(done); + }); + it('specify model in populate (gh-4264)', function(done) { var PersonSchema = new Schema({ name: String, From 0b8f391d91c24f988a02e248ae465bad90adff0d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Feb 2017 16:11:53 -0700 Subject: [PATCH 1237/2240] fix(populate): ensure foreign field is selected for virtual populate Fix #4959 --- lib/model.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/model.js b/lib/model.js index 8b6acc7799f..5076234f5b6 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2736,6 +2736,17 @@ function populate(model, docs, options, callback) { var subPopulate = mod.options.populate; var query = mod.Model.find(match, select, mod.options.options); + + /* If we're doing virtual populate and projection is inclusive and foreign + * field is not selected, automatically select it because mongoose needs it. + * If projection is exclusive and client explicitly unselected the foreign + * field, that's the client's fault. */ + if (mod.foreignField !== '_id' && query.selectedInclusively() && + !(mod.foreignField in query._fields)) { + query.select(mod.foreignField); + } + + // If we need to sub-populate, call populate recursively if (subPopulate) { query.populate(subPopulate); } From 6270101863efc3afdcd3a19f04cf5da86c962bb4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Feb 2017 16:21:23 -0700 Subject: [PATCH 1238/2240] docs(query): document some query callback params Fix #4949 --- lib/query.js | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/lib/query.js b/lib/query.js index 7cdc7c7fb0e..a8d30ec1af8 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1345,7 +1345,7 @@ Query.prototype._findOne = function(callback) { * * @param {Object|Query} [criteria] mongodb selector * @param {Object} [projection] optional fields to return - * @param {Function} [callback] + * @param {Function} [callback] optional params are (error, document) * @return {Query} this * @see findOne http://docs.mongodb.org/manual/reference/method/db.collection.findOne/ * @see Query.select #query_Query-select @@ -1449,7 +1449,7 @@ Query.prototype._count = function(callback) { * }) * * @param {Object} [criteria] mongodb selector - * @param {Function} [callback] + * @param {Function} [callback] optional params are (error, count) * @return {Query} this * @see count http://docs.mongodb.org/manual/reference/method/db.collection.count/ * @api public @@ -1491,7 +1491,7 @@ Query.prototype.count = function(conditions, callback) { * * @param {String} [field] * @param {Object|Query} [criteria] - * @param {Function} [callback] + * @param {Function} [callback] optional params are (error, arr) * @return {Query} this * @see distinct http://docs.mongodb.org/manual/reference/method/db.collection.distinct/ * @api public @@ -1591,8 +1591,9 @@ Query.prototype.sort = function(arg) { * query.remove() * * @param {Object|Query} [criteria] mongodb selector - * @param {Function} [callback] + * @param {Function} [callback] optional params are (error, writeOpResult) * @return {Query} this + * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult * @see remove http://docs.mongodb.org/manual/reference/method/db.collection.remove/ * @api public */ @@ -1699,8 +1700,9 @@ function prepareDiscriminatorCriteria(query) { * @param {Object|Query} [query] * @param {Object} [doc] * @param {Object} [options] - * @param {Function} [callback] + * @param {Function} [callback] optional params are (error, doc), _unless_ `passRawResult` is used, in which case params are (error, doc, writeOpResult) * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult * @return {Query} this * @api public */ @@ -1764,7 +1766,7 @@ Query.prototype.findOneAndUpdate = function(criteria, doc, options, callback) { return this._findOneAndUpdate(callback); }; -/** +/*! * Thunk around findOneAndUpdate() * * @param {Function} [callback] @@ -1807,7 +1809,7 @@ Query.prototype._findOneAndUpdate = function(callback) { * @memberOf Query * @param {Object} [conditions] * @param {Object} [options] - * @param {Function} [callback] + * @param {Function} [callback] optional params are (error, document) * @return {Query} this * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command * @api public @@ -1848,7 +1850,7 @@ Query.prototype.findOneAndRemove = function(conditions, options, callback) { return this; }; -/** +/*! * Thunk around findOneAndRemove() * * @param {Function} [callback] @@ -1870,7 +1872,7 @@ function decorateResult(res) { return res; } -/** +/*! * Override mquery.prototype._findAndModify to provide casting etc. * * @param {String} type - either "remove" or "update" @@ -2014,7 +2016,7 @@ Query.prototype._findAndModify = function(type, callback) { return this; }; -/** +/*! * Override mquery.prototype._mergeUpdate to handle mongoose objects in * updates. * @@ -2057,7 +2059,7 @@ function convertSortToArray(opts) { opts.sort = sort; } -/** +/*! * Internal thunk for .update() * * @param {Function} callback @@ -2102,7 +2104,7 @@ Query.prototype._execUpdate = function(callback) { return this; }; -/** +/*! * Internal thunk for .updateMany() * * @param {Function} callback @@ -2147,7 +2149,7 @@ Query.prototype._updateMany = function(callback) { return this; }; -/** +/*! * Internal thunk for .updateOne() * * @param {Function} callback @@ -2271,10 +2273,11 @@ Query.prototype._updateOne = function(callback) { * @param {Object} [criteria] * @param {Object} [doc] the update command * @param {Object} [options] - * @param {Function} [callback] + * @param {Function} [callback] optional, params are (error, writeOpResult) * @return {Query} this * @see Model.update #model_Model.update * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/ + * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult * @api public */ @@ -2318,10 +2321,11 @@ Query.prototype.update = function(conditions, doc, options, callback) { * @param {Object} [criteria] * @param {Object} [doc] the update command * @param {Object} [options] - * @param {Function} [callback] + * @param {Function} [callback] optional params are (error, writeOpResult) * @return {Query} this * @see Model.update #model_Model.update * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/ + * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult * @api public */ @@ -2364,10 +2368,11 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) { * @param {Object} [criteria] * @param {Object} [doc] the update command * @param {Object} [options] - * @param {Function} [callback] + * @param {Function} [callback] params are (error, writeOpResult) * @return {Query} this * @see Model.update #model_Model.update * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/ + * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult * @api public */ @@ -2507,7 +2512,7 @@ function _update(query, op, conditions, doc, options, callback) { * query.exec('find', callback); * * @param {String|Function} [operation] - * @param {Function} [callback] + * @param {Function} [callback] optional params depend on the function being called * @return {Promise} * @api public */ @@ -2625,7 +2630,7 @@ var numberOps = { $inc: 1 }; -/** +/*! * Casts obj for an update command. * * @param {Object} obj From eba8f632a6671278e7a90204be35bc40d81b6449 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Feb 2017 16:43:24 -0700 Subject: [PATCH 1239/2240] refactor: remove unnecessary conditionals --- lib/query.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index a8d30ec1af8..04c0760906a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1998,7 +1998,7 @@ Query.prototype._findAndModify = function(type, callback) { return callback(error); } _this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) { - return cb(error, res ? res.value : res, res); + return cb(error, res.value, res); })); }; @@ -2009,7 +2009,7 @@ Query.prototype._findAndModify = function(type, callback) { } } else { this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) { - return cb(error, res ? res.value : res, res); + return cb(error, res.value, res); })); } From 6afc60c9061670b16dfc537c72393cbd82ab8fca Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Feb 2017 17:06:00 -0700 Subject: [PATCH 1240/2240] test(query): repro #4925 --- test/model.findOneAndUpdate.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index d52d638717a..294f9b3c6c6 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1592,6 +1592,27 @@ describe('model: findByIdAndUpdate:', function() { }); }); + it('passes raw result if rawResult specified (gh-4925)', function(done) { + var testSchema = new mongoose.Schema({ + test: String + }); + + var TestModel = db.model('gh4925', testSchema); + var options = { upsert: true, new: true, rawResult: true }; + var update = { $set: { test: 'abc' } }; + + TestModel.findOneAndUpdate({}, update, options). + exec(function(error, res) { + assert.ifError(error); + assert.ok(res); + assert.ok(res.ok); + assert.equal(res.value.test, 'abc'); + assert.ok(res.value.id); + assert.equal(res.lastErrorObject.n, 1); + done(); + }); + }); + it('raw result as 3rd param w/ no result (gh-4023)', function(done) { var testSchema = new mongoose.Schema({ test: String From b8207aabd2528f56844f9f834670331cd02166a5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Feb 2017 17:06:23 -0700 Subject: [PATCH 1241/2240] feat(query): add rawResult option to hopefully replace passRawResult Fix #4925 --- lib/query.js | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/lib/query.js b/lib/query.js index 04c0760906a..246d4338ee6 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1307,7 +1307,7 @@ Query.prototype._findOne = function(callback) { if (!options.populate) { return options.lean === true ? callback(null, doc) - : completeOne(_this.model, doc, null, projection, null, callback); + : completeOne(_this.model, doc, null, {}, projection, null, callback); } var pop = helpers.preparePopulationOptionsMQ(_this, options); @@ -1318,7 +1318,7 @@ Query.prototype._findOne = function(callback) { } return options.lean === true ? callback(null, doc) - : completeOne(_this.model, doc, null, projection, pop, callback); + : completeOne(_this.model, doc, null, {}, projection, pop, callback); }); }); }; @@ -1628,7 +1628,7 @@ Query.prototype.remove = function(cond, callback) { * @param {Function} callback */ -function completeOne(model, doc, res, fields, pop, callback) { +function completeOne(model, doc, res, options, fields, pop, callback) { var opts = pop ? {populated: pop} : undefined; @@ -1638,7 +1638,12 @@ function completeOne(model, doc, res, fields, pop, callback) { if (err) { return callback(err); } - if (res) { + + if (options.rawResult) { + res.value = casted; + return callback(null, res); + } + if (options.passRawResult) { return callback(null, casted, decorateResult(res)); } callback(null, casted); @@ -1963,20 +1968,21 @@ Query.prototype._findAndModify = function(type, callback) { } if (!doc || (utils.isObject(doc) && Object.keys(doc).length === 0)) { + if (opts.rawResult) { + return callback(null, res); + } + // opts.passRawResult will be deprecated soon if (opts.passRawResult) { return callback(null, null, decorateResult(res)); } return callback(null, null); } - if (!opts.passRawResult) { - res = null; - } - if (!options.populate) { - return options.lean === true - ? (opts.passRawResult ? callback(null, doc, decorateResult(res)) : callback(null, doc)) - : completeOne(_this.model, doc, res, fields, null, callback); + if (options.lean === true) { + return _completeOneLean(doc, res, opts, callback); + } + return completeOne(_this.model, doc, res, opts, fields, null, callback); } var pop = helpers.preparePopulationOptionsMQ(_this, options); @@ -1986,9 +1992,10 @@ Query.prototype._findAndModify = function(type, callback) { return callback(err); } - return options.lean === true - ? (opts.passRawResult ? callback(null, doc, decorateResult(res)) : callback(null, doc)) - : completeOne(_this.model, doc, res, fields, pop, callback); + if (options.lean === true) { + return _completeOneLean(doc, res, opts, callback); + } + return completeOne(_this.model, doc, res, opts, fields, pop, callback); }); }; @@ -2016,6 +2023,20 @@ Query.prototype._findAndModify = function(type, callback) { return this; }; +/*! + * ignore + */ + +function _completeOneLean(doc, res, opts, callback) { + if (opts.rawResult) { + return callback(null, res); + } + if (opts.passRawResult) { + return callback(null, doc, decorateResult(res)); + } + return callback(null, doc); +} + /*! * Override mquery.prototype._mergeUpdate to handle mongoose objects in * updates. From 143b2517fb7e6af068c4728de18b80d4605c209b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Feb 2017 19:17:48 -0700 Subject: [PATCH 1242/2240] test(discriminator): repro #4965 --- test/model.discriminator.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 6653ec75d9e..42d95ef9514 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -368,6 +368,25 @@ describe('model', function() { done(); }); + it('applyPluginsToDiscriminators (gh-4965)', function(done) { + var schema = new Schema({ test: String }); + mongoose.set('applyPluginsToDiscriminators', true); + var called = 0; + mongoose.plugin(function() { + ++called; + }); + var Model = mongoose.model('gh4965', schema); + var childSchema = new Schema({ + test2: String + }); + Model.discriminator('gh4965_0', childSchema); + assert.equal(called, 2); + + mongoose.plugins = []; + mongoose.set('applyPluginsToDiscriminators', false); + done(); + }); + it('cloning with discriminator key (gh-4387)', function(done) { var employee = new Employee({ name: { first: 'Val', last: 'Karpov' } }); var clone = new employee.constructor(employee); From 8e93a859a791d5d1d50e89215d99f4b72ad48598 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Feb 2017 19:20:07 -0700 Subject: [PATCH 1243/2240] fix(discriminator): add applyPluginsToDiscriminators option Fix #4965 --- lib/services/model/discriminator.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index b3337067372..4504b524202 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -18,6 +18,10 @@ module.exports = function discriminator(model, name, schema) { throw new Error('You must pass a valid discriminator Schema'); } + if (model.base && model.base.options.applyPluginsToDiscriminators) { + model.base._applyPlugins(schema); + } + var _name = name; if (typeof name === 'function') { _name = utils.getFunctionName(name); From 631ed3ccd5e62f4dd8fd0c292b051b636fc949f9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 12 Feb 2017 18:32:31 -0700 Subject: [PATCH 1244/2240] test(update): repro #4960 --- test/model.update.test.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index a0d680aa793..c164127b6fd 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2201,6 +2201,40 @@ describe('model: update:', function() { }); }); + it('single nested under doc array with runValidators (gh-4960)', function(done) { + var ProductSchema = new Schema({ + name: String + }); + + var UserSchema = new Schema({ + sell: [{ + product: { type: ProductSchema, required: true } + }] + }); + + var User = db.model('gh4960', UserSchema); + + User.create({}). + then(function(user) { + return User.update({ + _id: user._id + }, { + sell: [{ + product: { + name: 'Product 1' + } + }] + }, { + runValidators: true + }); + }). + // Should not throw + then(function() { + done(); + }). + catch(done); + }); + it('single nested schema with geo (gh-4465)', function(done) { var addressSchema = new Schema({ geo: {type: [Number], index: '2dsphere'} From dadeb303c1453fbbbd079ac5cb9b1643afbbc298 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 12 Feb 2017 18:36:11 -0700 Subject: [PATCH 1245/2240] fix(update): properly cast array subdocs when casting update Fix #4960 --- lib/query.js | 2 +- lib/schema/array.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 04c0760906a..10ca29ecde2 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2487,7 +2487,7 @@ function _update(query, op, conditions, doc, options, callback) { query.setOptions(options); } - if (!query._update) query._update = castedDoc; + query._update = castedDoc; // Hooks if (callback) { diff --git a/lib/schema/array.js b/lib/schema/array.js index b0035e89fa1..1d0948bc2f4 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -214,6 +214,7 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { val = handler.call(this, value); } else { val = $conditional; + var Constructor = this.casterConstructor; var proto = this.casterConstructor.prototype; var method = proto && (proto.castForQuery || proto.cast); var caster = this.caster; @@ -225,11 +226,18 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { } if (method) { v = method.call(caster, v); + return v; + } + if (val != null) { + v = new Constructor(v); + return v; } return v; }); } else if (method) { val = method.call(caster, val); + } else if (val != null) { + val = new Constructor(val); } } From 04b8eccfbea740723b62981b1f5f8ec5a25070c2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 13 Feb 2017 21:51:33 -0700 Subject: [PATCH 1246/2240] test(document): repro #2185 --- test/document.test.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 237c9b829e0..76f8220c1a4 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3812,6 +3812,29 @@ describe('document', function() { done(); }); + it('handles errors in sync validators (gh-2185)', function(done) { + var schema = new Schema({ + name: { + type: String, + validate: function() { + throw new Error('woops!'); + } + } + }); + + var M = db.model('gh2185', schema); + + var error = (new M({ name: 'test' })).validateSync(); + assert.ok(error); + assert.equal(error.errors['name'].reason.message, 'woops!'); + + new M({ name: 'test'}).validate(function(error) { + assert.ok(error); + assert.equal(error.errors['name'].reason.message, 'woops!'); + done(); + }); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From 0fe98aa2b15f58fc0fe90752a4e185c51b8b1458 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 13 Feb 2017 21:51:40 -0700 Subject: [PATCH 1247/2240] fix(document): ensure errors in validators get caught Fix #2185 --- lib/error/validator.js | 1 + lib/schematype.js | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/error/validator.js b/lib/error/validator.js index 96a3ba1bf59..5850d12765c 100644 --- a/lib/error/validator.js +++ b/lib/error/validator.js @@ -30,6 +30,7 @@ function ValidatorError(properties) { this.kind = properties.type; this.path = properties.path; this.value = properties.value; + this.reason = properties.reason; } /*! diff --git a/lib/schematype.js b/lib/schematype.js index bf594bc6a4b..c227e102faa 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -714,6 +714,7 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { } var validator = v.validator; + var ok; var validatorProperties = utils.clone(v); validatorProperties.path = path; @@ -740,7 +741,13 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { validate(returnVal, validatorProperties); } } else { - validate(validator.call(scope, value), validatorProperties); + try { + ok = validator.call(scope, value); + } catch (error) { + ok = false; + validatorProperties.reason = error; + } + validate(ok, validatorProperties); } } }); @@ -795,13 +802,20 @@ SchemaType.prototype.doValidateSync = function(value, scope) { var validatorProperties = utils.clone(v); validatorProperties.path = path; validatorProperties.value = value; + var ok; if (validator instanceof RegExp) { validate(validator.test(value), validatorProperties); } else if (typeof validator === 'function') { // if not async validators if (validator.length !== 2) { - validate(validator.call(scope, value), validatorProperties); + try { + ok = validator.call(scope, value); + } catch (error) { + ok = false; + validatorProperties.reason = error; + } + validate(ok, validatorProperties); } } }); From 5e541a54d62ae0fdf373ef32940c630e411b6f78 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 14 Feb 2017 20:36:21 -0700 Subject: [PATCH 1248/2240] chore: upgrade mongodb -> 2.2.24 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 93a98294a55..4083ad9370b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "1.2.0", "kareem": "1.2.1", - "mongodb": "2.2.22", + "mongodb": "2.2.24", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.2.3", From 16f058ee41b8f723e80b92d6e73059768e226ce2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 15 Feb 2017 19:38:28 -0700 Subject: [PATCH 1249/2240] docs(connections): addd some details about callbacks Fix #4986 --- docs/connections.jade | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/connections.jade b/docs/connections.jade index 49c26c6d64c..587c0013529 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -91,7 +91,19 @@ block content // Good way to make sure mongoose never stops trying to reconnect mongoose.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } }); - + h3#callback Callback + :markdown + The `connect()` function also accepts a callback parameter and returns a [promise](http://mongoosejs.com/docs/promises.html). + :js + mongoose.connect(uri, options, function(error) { + // Check error in initial connection. There is no 2nd param to the callback. + }); + + // Or using promises + mongoose.connect(uri, options).then( + () => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ }, + err => { /** handle initial connection error } + ); h4#connection-string-options Connection String Options :markdown From cad0fe2d53bc9fdac079cc1d99c85577e4f9ab57 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 15 Feb 2017 21:08:26 -0700 Subject: [PATCH 1250/2240] chore: release 4.8.3 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ecce3ee129d..2c5c8b3b6b2 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,14 @@ +4.8.3 / 2017-02-15 +================== + * chore: upgrade mongodb driver -> 2.2.24 + * docs(connections): addd some details about callbacks #4986 + * fix: ensure class is created with new keyword #4972 #4947 [benhjames](https://github.com/benhjames) + * fix(discriminator): add applyPluginsToDiscriminators option #4965 + * fix(update): properly cast array subdocs when casting update #4960 + * fix(populate): ensure foreign field is selected for virtual populate #4959 + * docs(query): document some query callback params #4949 + * fix(document): ensure errors in validators get caught #2185 + 4.8.2 / 2017-02-10 ================== * fix(update): actually run validators on addToSet #4953 diff --git a/package.json b/package.json index 4083ad9370b..7a59eee9b40 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.3-pre", + "version": "4.8.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From aa347c93382ced7ae28d6a3dd0f1b7ad771060d5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 15 Feb 2017 21:11:27 -0700 Subject: [PATCH 1251/2240] chore: now working on 4.8.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a59eee9b40..c606461b931 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.3", + "version": "4.8.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c1ea050e3ae62542b11d231cee0307e03f2c13c6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Feb 2017 15:09:11 -0700 Subject: [PATCH 1252/2240] test(update): repro #4989 --- test/model.update.test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index c164127b6fd..4d4861b6fc5 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1924,6 +1924,37 @@ describe('model: update:', function() { }); }); + it('updates with timestamps with $set (gh-4989)', function(done) { + var TagSchema = new Schema({ + name: String, + tags: [{ + enum: ['test1', 'test2'], + type: String + }] + }, { timestamps: true }); + + var Tag = db.model('gh4989', TagSchema); + var tagId; + + Tag.remove({}). + then(function() { return Tag.create({ name: 'test' }); }). + then(function() { return Tag.findOne(); }). + then(function(tag) { + tagId = tag._id; + return Tag.update({ _id: tagId }, { + $set: { + tags: ['test1'] + } + }); + }). + then(function() { return Tag.findById(tagId); }). + then(function(res) { + assert.deepEqual(res.tags.toObject(), ['test1']); + done(); + }). + catch(done); + }); + it('update validators on single nested (gh-4332)', function(done) { var AreaSchema = new Schema({ a: String From e42c48d066896fba4cedc7239678a521f3f9e9f2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Feb 2017 15:10:37 -0700 Subject: [PATCH 1253/2240] fix(update): handle nested single embedded in update validators correctly Fix #4989 --- lib/query.js | 4 +++- lib/schema/embedded.js | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 10ca29ecde2..a72f9e642ad 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2487,7 +2487,9 @@ function _update(query, op, conditions, doc, options, callback) { query.setOptions(options); } - query._update = castedDoc; + if (!query._update) { + query._update = castedDoc; + } // Hooks if (callback) { diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index ea705ca2db9..d1e293fdceb 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -166,6 +166,7 @@ Embedded.prototype.castForQuery = function($conditional, val) { */ Embedded.prototype.doValidate = function(value, fn, scope) { + var Constructor = this.caster; SchemaType.prototype.doValidate.call(this, value, function(error) { if (error) { return fn(error); @@ -173,6 +174,9 @@ Embedded.prototype.doValidate = function(value, fn, scope) { if (!value) { return fn(null); } + if (!(value instanceof Constructor)) { + value = new Constructor(value); + } value.validate(fn, {__noPromise: true}); }, scope); }; From 7996e5e68a51832d39a1a5c94f8961f51d7c93dc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Feb 2017 15:20:15 -0700 Subject: [PATCH 1254/2240] Revert "refactor: remove unnecessary conditionals" This reverts commit eba8f632a6671278e7a90204be35bc40d81b6449. Fix #4990 --- lib/query.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index a72f9e642ad..ea70de84ba3 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1998,7 +1998,7 @@ Query.prototype._findAndModify = function(type, callback) { return callback(error); } _this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) { - return cb(error, res.value, res); + return cb(error, res ? res.value : res, res); })); }; @@ -2009,7 +2009,7 @@ Query.prototype._findAndModify = function(type, callback) { } } else { this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) { - return cb(error, res.value, res); + return cb(error, res ? res.value : res, res); })); } From 11b41df958943f8b8dbbae1c7b9bc9c15aacbf2b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Feb 2017 21:55:43 -0700 Subject: [PATCH 1255/2240] test(browser): repro #4987 --- test/browser.test.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 test/browser.test.js diff --git a/test/browser.test.js b/test/browser.test.js new file mode 100644 index 00000000000..3d2a8327bad --- /dev/null +++ b/test/browser.test.js @@ -0,0 +1,23 @@ +/** + * Module dependencies. + */ + +var Document = require('../lib/browserDocument'); +var Schema = require('../lib/schema'); + +/** + * Test. + */ +describe('browser', function() { + it('document works (gh-4987)', function(done) { + var schema = new Schema({ + name: {type: String, required: true}, + quest: {type: String, match: /Holy Grail/i, required: true}, + favoriteColor: {type: String, enum: ['Red', 'Blue'], required: true} + }); + + new Document({}, schema); + + done(); + }); +}); From 0a73939289bf5032e723183ab60dba9ae596cb69 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Feb 2017 21:57:09 -0700 Subject: [PATCH 1256/2240] fix(browser): make doc constructor not crash Fix #4987 --- lib/browserDocument.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/browserDocument.js b/lib/browserDocument.js index acf903afcca..d7734051418 100644 --- a/lib/browserDocument.js +++ b/lib/browserDocument.js @@ -99,6 +99,21 @@ function Document(obj, schema, fields, skipId, skipInit) { Document.prototype = Object.create(NodeJSDocument.prototype); Document.prototype.constructor = Document; +/*! + * Browser doc exposes the event emitter API + */ + +Document.$emitter = new EventEmitter(); + +utils.each( + ['on', 'once', 'emit', 'listeners', 'removeListener', 'setMaxListeners', + 'removeAllListeners', 'addListener'], + function(emitterFn) { + Document[emitterFn] = function() { + return Document.$emitter[emitterFn].apply(Document.$emitter, arguments); + }; + }); + /*! * Executes methods queued from the Schema definition * From 1d7e74e704206724c97231fa7ff90ae126d996ce Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Feb 2017 14:33:29 -0700 Subject: [PATCH 1257/2240] docs(discriminators): add hanging sentence --- test/docs/discriminators.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index 5e7acff41b6..8d18c3da9b2 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -242,7 +242,8 @@ describe('discriminator docs', function () { }); /** - * When you use `Model.create()`, mongoose + * When you use `Model.create()`, mongoose will pull the correct type from + * the discriminator key for you. */ it('Using discriminators with `Model.create()`', function(done) { var Schema = mongoose.Schema; From 0e99907964ca882353666b530c012a031e9bf405 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Feb 2017 14:58:11 -0700 Subject: [PATCH 1258/2240] docs(discriminators): explain embedded discriminators Fix #4997 --- lib/schema/documentarray.js | 4 +++ test/docs/discriminators.test.js | 62 ++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 58bd88691df..006fdabe10e 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -105,6 +105,10 @@ DocumentArray.prototype.discriminator = function(name, schema) { var EmbeddedDocument = _createConstructor(schema); + Object.defineProperty(EmbeddedDocument, 'name', { + value: name + }); + this.casterConstructor.discriminators[name] = EmbeddedDocument; return this.casterConstructor.discriminators[name]; diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index 8d18c3da9b2..c39a0cab69f 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -1,7 +1,11 @@ +'use strict'; + var assert = require('power-assert'); var async = require('async'); var mongoose = require('../../'); +var Schema = mongoose.Schema; + describe('discriminator docs', function () { var Event; var ClickedLinkEvent; @@ -275,4 +279,62 @@ describe('discriminator docs', function () { // acquit:ignore:end }); }); + + /** + * You can also define discriminators on embedded document arrays. + * Embedded discriminators are different because the different discriminator + * types are stored in the same document array (within a document) rather + * than the same collection. In other words, embedded discriminators let + * you store subdocuments matching different schemas in the same array. + */ + it('Embedded discriminators in arrays', function(done) { + var eventSchema = new Schema({ message: String }, + { discriminatorKey: 'kind', _id: false }); + + var batchSchema = new Schema({ events: [eventSchema] }); + + // `batchSchema.path('events')` gets the mongoose `DocumentArray` + var docArray = batchSchema.path('events'); + + // The `events` array can contain 2 different types of events, a + // 'clicked' event that requires an element id that was clicked... + var Clicked = docArray.discriminator('Clicked', new Schema({ + element: { + type: String, + required: true + } + }, { _id: false })); + + // ... and a 'purchased' event that requires the product that was purchased. + var Purchased = docArray.discriminator('Purchased', new Schema({ + product: { + type: String, + required: true + } + }, { _id: false })); + + var Batch = db.model('EventBatch', batchSchema); + + // Create a new batch of events with different kinds + var batch = { + events: [ + { kind: 'Clicked', element: '#hero' }, + { kind: 'Purchased', product: 'action-figure-1' } + ] + }; + + Batch.create(batch).then(function(doc) { + assert.equal(doc.events.length, 2); + + assert.equal(doc.events[0].element, '#hero'); + assert.ok(doc.events[0] instanceof Clicked); + // The constructor name will match the discriminator name + assert.equal(doc.events[0].constructor.name, 'Clicked'); + + assert.equal(doc.events[1].product, 'action-figure-1'); + assert.ok(doc.events[1] instanceof Purchased); + assert.equal(doc.events[1].constructor.name, 'Purchased'); + done(); + }); + }); }); From 500d747077248be8e3b05143b20b5ccf53d6a58d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Feb 2017 18:33:30 -0700 Subject: [PATCH 1259/2240] refactor(query): purify applyPaths and move it into helpers Re: #4991 --- lib/query.js | 90 +------------------------------------- lib/queryhelpers.js | 102 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 88 deletions(-) diff --git a/lib/query.js b/lib/query.js index ea70de84ba3..8aa091ab98f 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3054,94 +3054,8 @@ Query.prototype._castFields = function _castFields(fields) { */ Query.prototype._applyPaths = function applyPaths() { - // determine if query is selecting or excluding fields - - var fields = this._fields, - exclude, - keys, - ki; - - if (fields) { - keys = Object.keys(fields); - ki = keys.length; - - while (ki--) { - if (keys[ki][0] === '+') continue; - exclude = fields[keys[ki]] === 0; - break; - } - } - - // if selecting, apply default schematype select:true fields - // if excluding, apply schematype select:false fields - - var selected = [], - excluded = [], - seen = []; - - var analyzePath = function(path, type) { - if (typeof type.selected !== 'boolean') return; - - var plusPath = '+' + path; - if (fields && plusPath in fields) { - // forced inclusion - delete fields[plusPath]; - - // if there are other fields being included, add this one - // if no other included fields, leave this out (implied inclusion) - if (exclude === false && keys.length > 1 && !~keys.indexOf(path)) { - fields[path] = 1; - } - - return; - } - - // check for parent exclusions - var root = path.split('.')[0]; - if (~excluded.indexOf(root)) return; - - (type.selected ? selected : excluded).push(path); - }; - - var analyzeSchema = function(schema, prefix) { - prefix || (prefix = ''); - - // avoid recursion - if (~seen.indexOf(schema)) return; - seen.push(schema); - - schema.eachPath(function(path, type) { - if (prefix) path = prefix + '.' + path; - - analyzePath(path, type); - - // array of subdocs? - if (type.schema) { - analyzeSchema(type.schema, path); - } - }); - }; - - analyzeSchema(this.model.schema); - - switch (exclude) { - case true: - excluded.length && this.select('-' + excluded.join(' -')); - break; - case false: - if (this.model.schema && this.model.schema.paths['_id'] && - this.model.schema.paths['_id'].options && this.model.schema.paths['_id'].options.select === false) { - selected.push('-_id'); - } - selected.length && this.select(selected.join(' ')); - break; - case undefined: - // user didn't specify fields, implies returning all fields. - // only need to apply excluded fields - excluded.length && this.select('-' + excluded.join(' -')); - break; - } - seen = excluded = selected = keys = fields = null; + this._fields = this._fields || {}; + helpers.applyPaths(this._fields, this.model.schema); }; /** diff --git a/lib/queryhelpers.js b/lib/queryhelpers.js index 3e0b82d7d65..1d4ddc52290 100644 --- a/lib/queryhelpers.js +++ b/lib/queryhelpers.js @@ -66,6 +66,108 @@ exports.createModel = function createModel(model, doc, fields) { return new model(undefined, fields, true); }; +/*! + * ignore + */ + +exports.applyPaths = function applyPaths(fields, schema) { + // determine if query is selecting or excluding fields + + var exclude; + var keys; + var ki; + + if (fields) { + keys = Object.keys(fields); + ki = keys.length; + + while (ki--) { + if (keys[ki][0] === '+') continue; + exclude = fields[keys[ki]] === 0; + break; + } + } + + // if selecting, apply default schematype select:true fields + // if excluding, apply schematype select:false fields + + var selected = [], + excluded = [], + seen = []; + + var analyzePath = function(path, type) { + if (typeof type.selected !== 'boolean') return; + + var plusPath = '+' + path; + if (fields && plusPath in fields) { + // forced inclusion + delete fields[plusPath]; + + // if there are other fields being included, add this one + // if no other included fields, leave this out (implied inclusion) + if (exclude === false && keys.length > 1 && !~keys.indexOf(path)) { + fields[path] = 1; + } + + return; + } + + // check for parent exclusions + var root = path.split('.')[0]; + if (~excluded.indexOf(root)) return; + + (type.selected ? selected : excluded).push(path); + }; + + var analyzeSchema = function(schema, prefix) { + prefix || (prefix = ''); + + // avoid recursion + if (~seen.indexOf(schema)) return; + seen.push(schema); + + schema.eachPath(function(path, type) { + if (prefix) path = prefix + '.' + path; + + analyzePath(path, type); + + // array of subdocs? + if (type.schema) { + analyzeSchema(type.schema, path); + } + }); + }; + + analyzeSchema(schema); + + var i; + switch (exclude) { + case true: + for (i = 0; i < excluded.length; ++i) { + fields[excluded[i]] = 0; + } + break; + case false: + if (schema && + schema.paths['_id'] && + schema.paths['_id'].options && + schema.paths['_id'].options.select === false) { + fields._id = 0; + } + for (i = 0; i < selected.length; ++i) { + fields[selected[i]] = 1; + } + break; + case undefined: + // user didn't specify fields, implies returning all fields. + // only need to apply excluded fields + for (i = 0; i < excluded.length; ++i) { + fields[excluded[i]] = 0; + } + break; + } +}; + /*! * Set each path query option to lean * From 63aca58ab37ab3d3e91648da1ae45cc2d020ac4e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Feb 2017 18:13:56 -0700 Subject: [PATCH 1260/2240] test: fix tests on old node versions --- lib/schema/documentarray.js | 10 +++++++--- test/docs/discriminators.test.js | 3 --- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 006fdabe10e..732f01d919f 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -105,9 +105,13 @@ DocumentArray.prototype.discriminator = function(name, schema) { var EmbeddedDocument = _createConstructor(schema); - Object.defineProperty(EmbeddedDocument, 'name', { - value: name - }); + try { + Object.defineProperty(EmbeddedDocument, 'name', { + value: name + }); + } catch (error) { + // Ignore error, only happens on old versions of node + } this.casterConstructor.discriminators[name] = EmbeddedDocument; diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index c39a0cab69f..bf52870ea27 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -328,12 +328,9 @@ describe('discriminator docs', function () { assert.equal(doc.events[0].element, '#hero'); assert.ok(doc.events[0] instanceof Clicked); - // The constructor name will match the discriminator name - assert.equal(doc.events[0].constructor.name, 'Clicked'); assert.equal(doc.events[1].product, 'action-figure-1'); assert.ok(doc.events[1] instanceof Purchased); - assert.equal(doc.events[1].constructor.name, 'Purchased'); done(); }); }); From b94efe04ca1ab06406d4630065d02dccbdc193a3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Feb 2017 18:23:06 -0700 Subject: [PATCH 1261/2240] chore: release 4.8.4 --- History.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2c5c8b3b6b2..2edf1780817 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.8.4 / 2017-02-19 +================== + * docs(discriminators): explain embedded discriminators #4997 + * fix(query): fix TypeError when findOneAndUpdate errors #4990 + * fix(update): handle nested single embedded in update validators correctly #4989 + * fix(browser): make browser doc constructor not crash #4987 + 4.8.3 / 2017-02-15 ================== * chore: upgrade mongodb driver -> 2.2.24 diff --git a/package.json b/package.json index c606461b931..280fbd5c619 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.4-pre", + "version": "4.8.4", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From bf85411459084b80132a5f7b260c1602af23e9f5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Feb 2017 18:24:39 -0700 Subject: [PATCH 1262/2240] chore: now working on 4.8.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 280fbd5c619..7562f4e5f9c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.4", + "version": "4.8.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a66e139a600844447279a7bf56c7c6278a711386 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Feb 2017 17:10:27 -0700 Subject: [PATCH 1263/2240] fix(document): make isSelected much more robust Re: #4991 --- lib/document.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/document.js b/lib/document.js index 022f14b0221..991ffaa3799 100644 --- a/lib/document.js +++ b/lib/document.js @@ -629,9 +629,6 @@ Document.prototype.set = function(path, val, type, options) { } } - // ensure _strict is honored for obj props - // docschema = new Schema({ path: { nest: 'string' }}) - // doc.set('path', obj); var pathType = this.schema.pathType(path); if (pathType === 'nested' && val) { if (utils.isObject(val) && @@ -1179,10 +1176,10 @@ Document.prototype.isSelected = function isSelected(path) { return this.$__.selected._id !== 0; } - var paths = Object.keys(this.$__.selected), - i = paths.length, - inclusive = false, - cur; + var paths = Object.keys(this.$__.selected); + var i = paths.length; + var inclusive = null; + var cur; if (i === 1 && paths[0] === '_id') { // only _id was selected. @@ -1194,10 +1191,17 @@ Document.prototype.isSelected = function isSelected(path) { if (cur === '_id') { continue; } + if (this.$__.selected[cur] && this.$__.selected[cur].$meta) { + continue; + } inclusive = !!this.$__.selected[cur]; break; } + if (inclusive === null) { + return true; + } + if (path in this.$__.selected) { return inclusive; } @@ -1212,7 +1216,7 @@ Document.prototype.isSelected = function isSelected(path) { } if (cur.indexOf(pathDot) === 0) { - return inclusive; + return inclusive || cur !== pathDot; } if (pathDot.indexOf(cur + '.') === 0) { From ff006062eeccaf66a33758ff36bcaaed8895793f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Feb 2017 17:16:56 -0700 Subject: [PATCH 1264/2240] test(discriminator): repro #4991 --- test/model.discriminator.querying.test.js | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js index c24a302cf90..246590f090e 100644 --- a/test/model.discriminator.querying.test.js +++ b/test/model.discriminator.querying.test.js @@ -901,6 +901,37 @@ describe('model', function() { }); }); + it('hides fields when discriminated model has select (gh-4991)', function(done) { + var baseSchema = new mongoose.Schema({ + internal: { + test: [{ type: String }] + } + }); + + var Base = db.model('gh4991', baseSchema); + var discriminatorSchema = new mongoose.Schema({ + internal: { + password: { type: String, select: false } + } + }); + var Discriminator = Base.discriminator('gh4991_0', + discriminatorSchema); + + var obj = { + internal: { + test: ['abc'], + password: 'password' + } + }; + Discriminator.create(obj). + then(function(doc) { return Base.findById(doc._id); }). + then(function(doc) { + assert.ok(!doc.internal.password); + done(); + }). + catch(done); + }); + it('merges the first pipeline stages if applicable', function(done) { var aggregate = ImpressionEvent.aggregate([ {$match: {name: 'Test Event'}} From 9921d15b519483c92da8de4946794d47329b25f2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Feb 2017 17:17:59 -0700 Subject: [PATCH 1265/2240] fix(discriminators): remove fields not selected in child when querying by base model Fix #4991 --- lib/document.js | 7 +++++++ lib/model.js | 2 ++ lib/queryhelpers.js | 5 ++++- lib/schema/documentarray.js | 22 +++++++++++++++------- test/schema.select.test.js | 1 + 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/document.js b/lib/document.js index 991ffaa3799..f7e85b5b367 100644 --- a/lib/document.js +++ b/lib/document.js @@ -373,6 +373,13 @@ function init(self, obj, doc, prefix) { path = prefix + i; schema = self.schema.path(path); + // Should still work if not a model-level discriminator, but should not be + // necessary. This is *only* to catch the case where we queried using the + // base model and the discriminated model has a projection + if (self.schema.$isRootDiscriminator && !self.isSelected(path)) { + return; + } + if (!schema && utils.isObject(obj[i]) && (!obj[i].constructor || utils.getFunctionName(obj[i].constructor) === 'Object')) { // assume nested object diff --git a/lib/model.js b/lib/model.js index 0e0cfc9d36a..bff3b911d24 100644 --- a/lib/model.js +++ b/lib/model.js @@ -838,6 +838,8 @@ Model.discriminator = function(name, schema) { _name = name; } + schema.$isRootDiscriminator = true; + this.discriminators[_name] = this.db.model(name, schema, this.collection.name); var d = this.discriminators[_name]; d.prototype.__proto__ = this.prototype; diff --git a/lib/queryhelpers.js b/lib/queryhelpers.js index 1d4ddc52290..f31197f643f 100644 --- a/lib/queryhelpers.js +++ b/lib/queryhelpers.js @@ -60,7 +60,10 @@ exports.createModel = function createModel(model, doc, fields) { : null; if (key && doc[key] && model.discriminators && model.discriminators[doc[key]]) { - return new model.discriminators[doc[key]](undefined, fields, true); + var discriminator = model.discriminators[doc[key]]; + var _fields = utils.clone(fields); + exports.applyPaths(_fields, discriminator.schema); + return new model.discriminators[doc[key]](undefined, _fields, true); } return new model(undefined, fields, true); diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 732f01d919f..3b7a722bfc6 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -338,18 +338,26 @@ function scopePaths(array, fields, init) { return undefined; } - var path = array.path + '.', - keys = Object.keys(fields), - i = keys.length, - selected = {}, - hasKeys, - key; + var path = array.path + '.'; + var keys = Object.keys(fields); + var i = keys.length; + var selected = {}; + var hasKeys; + var key; + var sub; while (i--) { key = keys[i]; if (key.indexOf(path) === 0) { + sub = key.substring(path.length); + if (sub === '$') { + continue; + } + if (sub.indexOf('$.') === 0) { + sub = sub.substr(2); + } hasKeys || (hasKeys = true); - selected[key.substring(path.length)] = fields[key]; + selected[sub] = fields[key]; } } diff --git a/test/schema.select.test.js b/test/schema.select.test.js index c072679b7c9..3a480fb322c 100644 --- a/test/schema.select.test.js +++ b/test/schema.select.test.js @@ -162,6 +162,7 @@ describe('schema select option', function() { assert.equal(s.isSelected('thin'), true); assert.equal(s.isSelected('docs.name'), false); assert.equal(s.isSelected('docs.bool'), true); + assert.ok(s.isSelected('docs')); assert.strictEqual(undefined, s.name); assert.strictEqual(undefined, s.docs[0].name); assert.equal(s.thin, true); From fa4ebe7a31728e265dab1071e3c5fde297cd4222 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 21 Feb 2017 18:08:54 -0700 Subject: [PATCH 1266/2240] test(discriminators): repro first part of #5001 --- test/docs/discriminators.test.js | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index bf52870ea27..fc68a863dff 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -323,15 +323,27 @@ describe('discriminator docs', function () { ] }; - Batch.create(batch).then(function(doc) { - assert.equal(doc.events.length, 2); + Batch.create(batch). + then(function(doc) { + assert.equal(doc.events.length, 2); - assert.equal(doc.events[0].element, '#hero'); - assert.ok(doc.events[0] instanceof Clicked); + assert.equal(doc.events[0].element, '#hero'); + assert.ok(doc.events[0] instanceof Clicked); - assert.equal(doc.events[1].product, 'action-figure-1'); - assert.ok(doc.events[1] instanceof Purchased); - done(); - }); + assert.equal(doc.events[1].product, 'action-figure-1'); + assert.ok(doc.events[1] instanceof Purchased); + + doc.events.push({ kind: 'Purchased', product: 'action-figure-2' }); + return doc.save(); + }). + then(function(doc) { + assert.equal(doc.events.length, 3); + + assert.equal(doc.events[2].product, 'action-figure-2'); + assert.ok(doc.events[2] instanceof Purchased); + + done(); + }). + catch(done); }); }); From fa4e64f9cfffaa59be0198e8cdad0d5946c23248 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 21 Feb 2017 18:08:57 -0700 Subject: [PATCH 1267/2240] fix(discriminators): handle embedded discriminators in push() Re: #5001 --- lib/types/documentarray.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index bc07a75b9b1..b303e2592a2 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -120,7 +120,17 @@ MongooseDocumentArray.mixin = { value instanceof ObjectId || !utils.isObject(value)) { value = {_id: value}; } - return new this._schema.casterConstructor(value, this, undefined, undefined, index); + + var Constructor = this._schema.casterConstructor; + if (value && + Constructor.discriminators && + Constructor.schema.options.discriminatorKey && + typeof value[Constructor.schema.options.discriminatorKey] === 'string' && + Constructor.discriminators[value[Constructor.schema.options.discriminatorKey]]) { + Constructor = Constructor.discriminators[value[Constructor.schema.options.discriminatorKey]]; + } + + return new Constructor(value, this, undefined, undefined, index); }, /** From 4a100d7d6510d8bd0b1882f8dde33a9c66870358 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 21 Feb 2017 23:45:08 -0700 Subject: [PATCH 1268/2240] test(discriminator): repro #5001 part 2 --- test/model.discriminator.test.js | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 42d95ef9514..5df800732d5 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -398,6 +398,57 @@ describe('model', function() { }); }); + it('embedded discriminators with create() (gh-5001)', function(done) { + var eventSchema = new Schema({ message: String }, + { discriminatorKey: 'kind', _id: false }); + var batchSchema = new Schema({ events: [eventSchema] }); + var docArray = batchSchema.path('events'); + + var Clicked = docArray.discriminator('Clicked', new Schema({ + element: { + type: String, + required: true + } + }, { _id: false })); + + var Purchased = docArray.discriminator('Purchased', new Schema({ + product: { + type: String, + required: true + } + }, { _id: false })); + + var Batch = db.model('EventBatch', batchSchema); + + var batch = { + events: [ + { kind: 'Clicked', element: '#hero' } + ] + }; + + Batch.create(batch). + then(function(doc) { + assert.equal(doc.events.length, 1); + var newDoc = doc.events.create({ + kind: 'Purchased', + product: 'action-figure-1' + }); + assert.equal(newDoc.kind, 'Purchased'); + assert.equal(newDoc.product, 'action-figure-1'); + assert.ok(newDoc instanceof Purchased); + + doc.events.push(newDoc); + assert.equal(doc.events.length, 2); + assert.equal(doc.events[1].kind, 'Purchased'); + assert.equal(doc.events[1].product, 'action-figure-1'); + assert.ok(newDoc instanceof Purchased); + assert.ok(newDoc === doc.events[1]); + + done(); + }). + catch(done); + }); + it('embedded in document arrays (gh-2723)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From 2e254665c1a2647025a1974eeb9a9229c7493ca3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 21 Feb 2017 23:45:34 -0700 Subject: [PATCH 1269/2240] fix(discriminators): handle create() and push() for embedded discriminators Fix #5001 --- lib/schema/documentarray.js | 1 + lib/types/documentarray.js | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 3b7a722bfc6..c434d121a75 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -104,6 +104,7 @@ DocumentArray.prototype.discriminator = function(name, schema) { discriminator(this.casterConstructor, name, schema); var EmbeddedDocument = _createConstructor(schema); + EmbeddedDocument.baseCasterConstructor = this.casterConstructor; try { Object.defineProperty(EmbeddedDocument, 'name', { diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index b303e2592a2..1c485b5540a 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -99,7 +99,10 @@ MongooseDocumentArray.mixin = { */ _cast: function(value, index) { - if (value instanceof this._schema.casterConstructor) { + var Constructor = this._schema.casterConstructor; + if (value instanceof Constructor || + // Hack re: #5001, see #5005 + (value && value.constructor.baseCasterConstructor === Constructor)) { if (!(value.__parent && value.__parentArray)) { // value may have been created using array.create() value.__parent = this._parent; @@ -121,7 +124,6 @@ MongooseDocumentArray.mixin = { value = {_id: value}; } - var Constructor = this._schema.casterConstructor; if (value && Constructor.discriminators && Constructor.schema.options.discriminatorKey && @@ -231,7 +233,16 @@ MongooseDocumentArray.mixin = { */ create: function(obj) { - return new this._schema.casterConstructor(obj); + var Constructor = this._schema.casterConstructor; + if (obj && + Constructor.discriminators && + Constructor.schema.options.discriminatorKey && + typeof obj[Constructor.schema.options.discriminatorKey] === 'string' && + Constructor.discriminators[obj[Constructor.schema.options.discriminatorKey]]) { + Constructor = Constructor.discriminators[obj[Constructor.schema.options.discriminatorKey]]; + } + + return new Constructor(obj); }, /** From eb6b6860d787a1e2d17745fc12e4c9e6bb18f0b9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Feb 2017 19:03:55 -0700 Subject: [PATCH 1270/2240] test(querycursor): repro #4998 --- test/query.cursor.test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index 304295f85a8..bbc6cc9a6f4 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -341,4 +341,35 @@ describe('QueryCursor', function() { }); }); }); + + it('data before close (gh-4998)', function(done) { + var userSchema = new mongoose.Schema({ + name: String + }); + + var User = db.model('gh4998', userSchema); + var users = []; + for (var i = 0; i < 100; i++) { + users.push({ + _id: mongoose.Types.ObjectId(), + name: 'Bob' + (i < 10 ? '0' : '') + i + }); + } + + User.insertMany(users, function(error) { + assert.ifError(error); + + var stream = User.find({}).cursor(); + var docs = []; + + stream.on('data', function(doc) { + docs.push(doc); + }); + + stream.on('close', function() { + assert.equal(docs.length, 100); + done(); + }); + }); + }); }); From b3c99e65bb2d07556acee83f1f0fc5261551cccf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Feb 2017 19:04:06 -0700 Subject: [PATCH 1271/2240] fix(querycursor): ensure close emitted after last data event Fix #4998 --- lib/querycursor.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/querycursor.js b/lib/querycursor.js index da82a5b9452..7b4933516bb 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -61,12 +61,15 @@ QueryCursor.prototype._read = function() { } if (!doc) { _this.push(null); - return _this.cursor.close(function(error) { + _this.cursor.close(function(error) { if (error) { return _this.emit('error', error); } - _this.emit('close'); + setTimeout(function() { + _this.emit('close'); + }, 0); }); + return; } _this.push(doc); }); From ed0eb42bbdf5df3255ae1571e5791852851ae25e Mon Sep 17 00:00:00 2001 From: Frederico Ferreira Date: Thu, 23 Feb 2017 18:13:25 -0300 Subject: [PATCH 1272/2240] Add Dashbox new case We use mongoose in production Dashbox is a business intelligence tool from Softbox (BI). We use mongoose in production --- index.jade | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.jade b/index.jade index 796b3c59fa3..eb69d02a82a 100644 --- a/index.jade +++ b/index.jade @@ -120,6 +120,10 @@ html(lang='en') li a(href="https://sixplus.com") img(src="https://s3.amazonaws.com/bookalokal-assets/sixplus/sixplus-logo-horizontal-dark.png", alt="SixPlus") + li + a(href="http://www.softbox.com.br/en/produtos/detalhe/cat/dashbox/") + img(src="http://www.softbox.com.br/public/upload/categoriasprodutos/logo/logo-dashbox.png", alt="Dashbox") + p#footer Licensed under MIT. Copyright 2011 LearnBoost. script. document.body.className = 'load'; From b53501233eae80f28634081ecac5959a657e0507 Mon Sep 17 00:00:00 2001 From: Randy Houlahan Date: Fri, 24 Feb 2017 13:40:54 -0500 Subject: [PATCH 1273/2240] Check for empty schemaPath before accessing property $isMongooseDocumentArray TypeError: Cannot read property '$isMongooseDocumentArray' of undefined. Same issue as https://github.com/Automattic/mongoose/commit/8935a55bbe84c40d10becd32bb3fd5c317f2a1d7 --- lib/services/updateValidators.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 4c710ab4a9a..096a61a73a8 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -105,7 +105,7 @@ module.exports = function(query, schema, castedDoc, options) { for (i = 0; i < numArrayUpdates; ++i) { (function(i) { var schemaPath = schema._getSchema(arrayUpdates[i]); - if (schemaPath.$isMongooseDocumentArray) { + if (schemaPath && schemaPath.$isMongooseDocumentArray) { validatorsToExecute.push(function(callback) { schemaPath.doValidate( arrayAtomicUpdates[arrayUpdates[i]], From 721eeca4868220b9387bcb2b94e981ea5e79992f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 24 Feb 2017 12:16:15 -0700 Subject: [PATCH 1274/2240] chore: now working on 4.9.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7562f4e5f9c..2d021a5c730 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.5-pre", + "version": "4.9.0-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 5a6c87639ea9c339e7de6a22141abaebf0922076 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 24 Feb 2017 12:51:56 -0700 Subject: [PATCH 1275/2240] feat(schema): add a clone() function for schemas To make reusing discriminator schemas easier. Fix #4983 --- lib/model.js | 2 +- lib/schema.js | 16 +++++++-- lib/schema/documentarray.js | 2 +- lib/services/model/discriminator.js | 2 ++ test/docs/discriminators.test.js | 4 +-- test/model.discriminator.test.js | 51 ++++++++++++++++++++++++++--- test/model.hydrate.test.js | 2 +- 7 files changed, 67 insertions(+), 12 deletions(-) diff --git a/lib/model.js b/lib/model.js index bff3b911d24..be020034946 100644 --- a/lib/model.js +++ b/lib/model.js @@ -826,7 +826,7 @@ Model.prototype.model = function model(name) { */ Model.discriminator = function(name, schema) { - discriminator(this, name, schema); + schema = discriminator(this, name, schema); if (this.db.models[name]) { throw new OverwriteModelError(name); } diff --git a/lib/schema.js b/lib/schema.js index c81d698b089..5ae163db9da 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -84,9 +84,6 @@ function Schema(obj, options) { this.methods = {}; this.statics = {}; this.tree = {}; - this._requiredpaths = undefined; - this.discriminatorMapping = undefined; - this._indexedpaths = undefined; this.query = {}; this.childSchemas = []; @@ -338,6 +335,19 @@ Schema.prototype.paths; Schema.prototype.tree; +/** + * Returns a deep copy of the schema + * + * @return {Schema} the cloned schema + * @api public + */ + +Schema.prototype.clone = function() { + var s = Object.create(Schema.prototype); + utils.merge(s, this, { retainKeyOrder: true, hasOwnProperty: true }); + return s; +}; + /** * Returns default options for this schema, merged with `options`. * diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index c434d121a75..7b71cf022bc 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -101,7 +101,7 @@ function _createConstructor(schema, options) { */ DocumentArray.prototype.discriminator = function(name, schema) { - discriminator(this.casterConstructor, name, schema); + schema = discriminator(this.casterConstructor, name, schema); var EmbeddedDocument = _createConstructor(schema); EmbeddedDocument.baseCasterConstructor = this.casterConstructor; diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 4504b524202..c4345f27b47 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -106,4 +106,6 @@ module.exports = function discriminator(model, name, schema) { if (model.discriminators[name]) { throw new Error('Discriminator with name "' + name + '" already exists'); } + + return schema; }; diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index fc68a863dff..e43003f0eeb 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -189,12 +189,12 @@ describe('discriminator docs', function () { clickedLinkSchema); var event1 = new ClickedLinkEvent(); - event1.validate(function () { + event1.validate(function() { assert.equal(eventSchemaCalls, 1); assert.equal(clickedSchemaCalls, 1); var generic = new Event(); - generic.validate(function () { + generic.validate(function() { assert.equal(eventSchemaCalls, 2); assert.equal(clickedSchemaCalls, 1); // acquit:ignore:start diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 5df800732d5..3a4768a0f98 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -236,10 +236,9 @@ describe('model', function() { department: String }, { id: false }); - assert.doesNotThrow(function() { - var Person = db.model('gh2821', PersonSchema); - Person.discriminator('gh2821-Boss', BossSchema); - }); + // Should not throw + var Person = db.model('gh2821', PersonSchema); + Person.discriminator('gh2821-Boss', BossSchema); done(); }); @@ -449,6 +448,50 @@ describe('model', function() { catch(done); }); + it('supports clone() (gh-4983)', function(done) { + var childSchema = new Schema({ + name: String + }); + var childCalls = 0; + childSchema.pre('save', function(next) { + ++childCalls; + next(); + }); + + var personSchema = new Schema({ + name: String + }, { discriminatorKey: 'kind' }); + + var parentSchema = new Schema({ + children: [childSchema], + heir: childSchema + }); + var parentCalls = 0; + parentSchema.pre('save', function(next) { + ++parentCalls; + next(); + }); + + var Person = db.model('gh4983', personSchema); + var Parent = Person.discriminator('gh4983_0', parentSchema.clone()); + + var obj = { + name: 'Ned Stark', + heir: { name: 'Robb Stark' }, + children: [{ name: 'Jon Snow' }] + }; + Parent.create(obj, function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Ned Stark'); + assert.equal(doc.heir.name, 'Robb Stark'); + assert.equal(doc.children.length, 1); + assert.equal(doc.children[0].name, 'Jon Snow'); + assert.equal(childCalls, 2); + assert.equal(parentCalls, 1); + done(); + }); + }); + it('embedded in document arrays (gh-2723)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); diff --git a/test/model.hydrate.test.js b/test/model.hydrate.test.js index b5b3d91890d..41fd97a5fc3 100644 --- a/test/model.hydrate.test.js +++ b/test/model.hydrate.test.js @@ -77,7 +77,7 @@ describe('model', function() { var hydrated = B.hydrate({_id: '541085faedb2f28965d0e8e8', title: 'chair', type: 'C'}); assert.equal(hydrated.test, 'test'); - assert.ok(hydrated.schema === schemaC); + assert.deepEqual(hydrated.schema, schemaC); done(); }); }); From 889d31610dabfd492b53233a0943ac65aa553a4b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Feb 2017 20:47:51 -0700 Subject: [PATCH 1276/2240] chore: release 4.8.5 --- History.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2edf1780817..4ca8e44bf09 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.8.5 / 2017-02-25 +================== + * fix: check for empty schemaPath before accessing property $isMongooseDocumentArray #5017 [https://github.com/randyhoulahan](randyhoulahan) + * fix(discriminators): handle create() and push() for embedded discriminators #5001 + * fix(querycursor): ensure close emitted after last data event #4998 + * fix(discriminators): remove fields not selected in child when querying by base model #4991 + 4.8.4 / 2017-02-19 ================== * docs(discriminators): explain embedded discriminators #4997 diff --git a/package.json b/package.json index 7562f4e5f9c..3460db6fd30 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.5-pre", + "version": "4.8.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a5f91681bc9ffc0eb62145be8e8df4545a870fb6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Feb 2017 18:06:11 -0700 Subject: [PATCH 1277/2240] chore: now working on 4.8.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3460db6fd30..c57958d8416 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.5", + "version": "4.8.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 1e79a1c2781db30cd3133c27d4bf04d42c7e24ff Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Feb 2017 18:34:39 -0700 Subject: [PATCH 1278/2240] docs(validation): add isAsync option Re: #4290 --- test/docs/validation.test.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 260b8891579..42035e45def 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -156,6 +156,10 @@ describe('validation docs', function() { phone: { type: String, validate: { + // `isAsync` is not strictly necessary in mongoose 4.x, but relying + // on 2 argument validators being async is deprecated. Set the + // `isAsync` option to `true` to make deprecation warnings go away. + isAsync: true, validator: function(v, cb) { setTimeout(function() { cb(/\d{3}-\d{3}-\d{4}/.test(v)); From f2801f37c1763103ec91667e51a46a1943f0f2f2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Feb 2017 18:34:59 -0700 Subject: [PATCH 1279/2240] feat(schematype): support isAsync validator option and handle returning promises from validators Fix #4290 --- lib/schematype.js | 57 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/lib/schematype.js b/lib/schematype.js index c227e102faa..146c063f63b 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -727,19 +727,11 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { validate(true, validatorProperties); return; } - if (validator.length === 2) { - var returnVal = validator.call(scope, value, function(ok, customMsg) { - if (typeof returnVal === 'boolean') { - return; - } - if (customMsg) { - validatorProperties.message = customMsg; - } - validate(ok, validatorProperties); - }); - if (typeof returnVal === 'boolean') { - validate(returnVal, validatorProperties); - } + if (validatorProperties.isAsync) { + asyncValidate(validator, scope, value, validatorProperties, validate); + } else if (validator.length === 2 && !('isAsync' in validatorProperties)) { + legacyAsyncValidate(validator, scope, value, validatorProperties, + validate); } else { try { ok = validator.call(scope, value); @@ -747,12 +739,47 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { ok = false; validatorProperties.reason = error; } - validate(ok, validatorProperties); + if (ok && typeof ok.then === 'function') { + ok.then( + function(ok) { validate(ok, validatorProperties); }, + function(error) { + validatorProperties.reason = error; + ok = false; + validate(ok, validatorProperties); + }); + } else { + validate(ok, validatorProperties); + } } } }); }; +/*! + * Handle async validators + */ + +function asyncValidate(validator, scope, value, props, cb) { + var returnVal = validator.call(scope, value, function(ok, customMsg) { + if (typeof returnVal === 'boolean') { + return; + } + if (customMsg) { + props.message = customMsg; + } + cb(ok, props); + }); + if (typeof returnVal === 'boolean') { + cb(returnVal, props); + } +} + +var legacyAsyncValidate = require('util').deprecate(asyncValidate, + 'Implicit async custom validators (custom validators that take 2 ' + + 'arguments) are deprecated in mongoose >= 4.9.0. See ' + + 'http://mongoosejs.com/docs/validation.html#async-custom-validators for ' + + 'more info.'); + /** * Performs a validation of `value` using the validators declared for this SchemaType. * @@ -808,7 +835,7 @@ SchemaType.prototype.doValidateSync = function(value, scope) { validate(validator.test(value), validatorProperties); } else if (typeof validator === 'function') { // if not async validators - if (validator.length !== 2) { + if (validator.length !== 2 && !validatorProperties.isAsync) { try { ok = validator.call(scope, value); } catch (error) { From 7d34448cca694669d8cd2593fe72381065f01e53 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 1 Mar 2017 21:05:13 -0700 Subject: [PATCH 1280/2240] test(document): repro #5008 --- test/document.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 76f8220c1a4..e8faab4b4ac 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3835,6 +3835,33 @@ describe('document', function() { }); }); + it('nested docs toObject() clones (gh-5008)', function(done) { + var schema = new mongoose.Schema({ + sub: { + height: Number + } + }); + + var Model = db.model('gh5008', schema); + + var doc = new Model({ + sub: { + height: 3 + } + }); + + assert.equal(doc.sub.height, 3); + + var leanDoc = doc.sub.toObject(); + assert.equal(leanDoc.height, 3); + + doc.sub.height = 55; + assert.equal(doc.sub.height, 55); + assert.equal(leanDoc.height, 3); + + done(); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From 59c6d3ee90e2f332d81a955412af4c0a511ebe36 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 1 Mar 2017 21:05:35 -0700 Subject: [PATCH 1281/2240] fix(document): ensure nested docs' toObject() clones Fix #5008 --- lib/document.js | 3 +-- test/document.hooks.test.js | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/document.js b/lib/document.js index f7e85b5b367..8e9d88f3dd2 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1793,7 +1793,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { configurable: true, writable: false, value: function() { - return _this.get(path); + return utils.clone(_this.get(path), { retainKeyOrder: true }); } }); @@ -1915,7 +1915,6 @@ Document.prototype.$__getAllSubdocs = function() { seed = Object.keys(doc._doc).reduce(docReducer.bind(doc._doc), seed); }); } else if (val instanceof Document && val.$__isNested) { - val = val.toObject(); if (val) { seed = Object.keys(val).reduce(docReducer.bind(val), seed); } diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js index d6d9fc1715d..c73ff0ccd6c 100644 --- a/test/document.hooks.test.js +++ b/test/document.hooks.test.js @@ -715,9 +715,9 @@ describe('document: hooks:', function() { } }); - mongoose.model('gh-3284', parentSchema); - var db = start(); + db.model('gh-3284', parentSchema); + var Parent = db.model('gh-3284'); var parent = new Parent({ From a19145b036fa13c20ae2f8739abe43dac29d044a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 2 Mar 2017 18:08:58 -0700 Subject: [PATCH 1282/2240] docs(document): remove text that implies that transform is false by default Fix #5023 --- lib/document.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 8e9d88f3dd2..f374867c727 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2145,7 +2145,7 @@ Document.prototype.$toObject = function(options, json) { * // pass the transform as an inline option * doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true } * - * _Note: if you call `toObject` and pass any options, the transform declared in your schema options will __not__ be applied. To force its application pass `transform: true`_ + * If you want to skip transformations, use `transform: false`: * * if (!schema.options.toObject) schema.options.toObject = {}; * schema.options.toObject.hide = '_id'; @@ -2160,7 +2160,7 @@ Document.prototype.$toObject = function(options, json) { * * var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }); * doc.toObject(); // { secret: 47, name: 'Wreck-it Ralph' } - * doc.toObject({ hide: 'secret _id' }); // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' } + * doc.toObject({ hide: 'secret _id', transform: false });// { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' } * doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' } * * Transforms are applied _only to the document and are not applied to sub-documents_. From 2a3902d8695f0b67e58e166c4b0873237eb55b4d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Mar 2017 11:12:52 -0700 Subject: [PATCH 1283/2240] fix(applyHooks): dont wrap a function if it is already wrapped Fix #5019 --- lib/services/model/applyHooks.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index c6fd2eb6880..bf97f1bfed9 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -97,7 +97,9 @@ function applyHooks(model, schema) { if (!model.prototype[pointCut]) { return; } - model.prototype[newName] = model.prototype[pointCut]; + if (!model.prototype[pointCut].$originalFunction) { + model.prototype[newName] = model.prototype[pointCut]; + } model.prototype[pointCut] = (function(_newName) { return function wrappedPointCut() { var _this = this; @@ -153,6 +155,7 @@ function applyHooks(model, schema) { return promise; }; })(newName); + model.prototype[pointCut].$originalFunction = newName; toWrapEl = toWrap[pointCut]; var _len = toWrapEl.pre.length; From 341556123a230eade305f67eed93e1a71e0263c6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Mar 2017 11:22:24 -0700 Subject: [PATCH 1284/2240] fix(drivers): stop emitting timeouts as errors Fix #5026 --- lib/drivers/node-mongodb-native/connection.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 9d8a9946972..c6dd24a4d1c 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -166,8 +166,7 @@ function listen(conn) { conn.onOpen(); }); conn.db.on('timeout', function(err) { - var error = new Error(err && err.err || 'connection timeout'); - conn.emit('error', error); + conn.emit('timeout', err); }); conn.db.on('open', function(err, db) { if (STATES.disconnected === conn.readyState && db && db.databaseName) { From 7d5da83853e73344e3d6240b0fee56c8bc00826c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Mar 2017 11:26:42 -0700 Subject: [PATCH 1285/2240] feat(document): return this from `depopulate()` Fix #5027 --- lib/document.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/document.js b/lib/document.js index f374867c727..af9c9d339f4 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2502,6 +2502,7 @@ Document.prototype.populated = function(path, val, options) { * If the path was not populated, this is a no-op. * * @param {String} path + * @return {Document} this * @see Document.populate #document_Document-populate * @api public */ @@ -2513,6 +2514,7 @@ Document.prototype.depopulate = function(path) { } delete this.$__.populated[path]; this.set(path, populatedIds); + return this; }; From 95042dabf0938b0df6d670caef6c71b94b0fd919 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Mar 2017 11:50:17 -0700 Subject: [PATCH 1286/2240] test(validation): add some more tests re: isAsync Re #4290 --- test/docs/validation.test.js | 17 +++++++++++++++++ test/schema.validation.test.js | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 42035e45def..9565e383a9d 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -1,6 +1,8 @@ var assert = require('assert'); var mongoose = require('../../'); +var Promise = global.Promise || require('bluebird'); + describe('validation docs', function() { var db; var Schema = mongoose.Schema; @@ -168,6 +170,18 @@ describe('validation docs', function() { message: '{VALUE} is not a valid phone number!' }, required: [true, 'User phone number required'] + }, + name: { + type: String, + // You can also make a validator async by returning a promise. If you + // return a promise, do **not** specify the `isAsync` option. + validate: function(v) { + return new Promise(function(resolve, reject) { + setTimeout(function() { + resolve(false); + }, 5); + }); + } } }); @@ -176,10 +190,13 @@ describe('validation docs', function() { var error; user.phone = '555.0123'; + user.name = 'test'; user.validate(function(error) { assert.ok(error); assert.equal(error.errors['phone'].message, '555.0123 is not a valid phone number!'); + assert.equal(error.errors['name'].message, + 'Validator failed for path `name` with value `test`'); // acquit:ignore:start done(); // acquit:ignore:end diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index fc77b9e6594..c69954ef346 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -628,6 +628,31 @@ describe('schema', function() { }); }); + it('custom validators with isAsync = false', function(done) { + var validate = function(v, opts) { + // Make eslint not complain about unused vars + return !!(v && opts && false); + }; + + var schema = new Schema({ + x: { + type: String, + validate: { + isAsync: false, + validator: validate + } + } + }); + var M = mongoose.model('custom-validator-async-' + random(), schema); + + var m = new M({x: 'test'}); + + m.validate(function(err) { + assert.ok(err.errors['x']); + done(); + }); + }); + it('supports custom properties (gh-2132)', function(done) { var schema = new Schema({ x: { From 36d099c885cf54ed3e4dcf783f8dac6dba6d0d79 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 5 Mar 2017 15:23:26 -0700 Subject: [PATCH 1287/2240] chore: release 4.8.6 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 4ca8e44bf09..668945ba4a4 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +4.8.6 / 2017-03-05 +================== + * docs(document): remove text that implies that transform is false by default #5023 + * fix(applyHooks): dont wrap a function if it is already wrapped #5019 + * fix(document): ensure nested docs' toObject() clones #5008 + 4.8.5 / 2017-02-25 ================== * fix: check for empty schemaPath before accessing property $isMongooseDocumentArray #5017 [https://github.com/randyhoulahan](randyhoulahan) diff --git a/package.json b/package.json index c57958d8416..e0746af6cac 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.6-pre", + "version": "4.8.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 525f43fadaa8b8cd5df3b9f4553b43687b8145c2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 5 Mar 2017 15:24:55 -0700 Subject: [PATCH 1288/2240] chore: now working on 4.8.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e0746af6cac..decead2e992 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.6", + "version": "4.8.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From cded10884c4de69bb7e97fca1314f9b3d6459b9a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 5 Mar 2017 19:43:06 -0700 Subject: [PATCH 1289/2240] feat(query): add replaceOne() Re: #3998 --- lib/model.js | 19 ++++++++ lib/query.js | 99 ++++++++++++++++++++++++++++++++++++++- package.json | 2 +- test/model.update.test.js | 22 +++++++++ 4 files changed, 139 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index bff3b911d24..1d0b0e66968 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2088,6 +2088,25 @@ Model.updateOne = function updateOne(conditions, doc, options, callback) { return _update(this, 'updateOne', conditions, doc, options, callback); }; +/** + * Same as `update()`, except MongoDB replace the existing document with the + * given document (no atomic operators like `$set`). + * + * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')` + * and `post('updateMany')` instead. + * + * @param {Object} conditions + * @param {Object} doc + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} + * @api public + */ + +Model.replaceOne = function replaceOne(conditions, doc, options, callback) { + return _update(this, 'replaceOne', conditions, doc, options, callback); +}; + /*! * ignore */ diff --git a/lib/query.js b/lib/query.js index 8aa091ab98f..ab7095cea77 100644 --- a/lib/query.js +++ b/lib/query.js @@ -87,6 +87,8 @@ function Query(conditions, options, model, collection) { Query.prototype._findOneAndRemove, this, kareemOptions); this._findOneAndUpdate = this.model.hooks.createWrapper('findOneAndUpdate', Query.prototype._findOneAndUpdate, this, kareemOptions); + this._replaceOne = this.model.hooks.createWrapper('replaceOne', + Query.prototype._replaceOne, this, kareemOptions); this._updateMany = this.model.hooks.createWrapper('updateMany', Query.prototype._updateMany, this, kareemOptions); this._updateOne = this.model.hooks.createWrapper('updateOne', @@ -2194,6 +2196,51 @@ Query.prototype._updateOne = function(callback) { return this; }; +/*! + * Internal thunk for .replaceOne() + * + * @param {Function} callback + * @see Model.replaceOne #model_Model.replaceOne + * @api private + */ +Query.prototype._replaceOne = function(callback) { + var schema = this.model.schema; + var doValidate; + var _this; + + var castedQuery = this._conditions; + var castedDoc = this._update; + var options = this.options; + + if (this._castError) { + callback(this._castError); + return this; + } + + if (this.options.runValidators) { + _this = this; + doValidate = updateValidators(this, schema, castedDoc, options); + var _callback = function(err) { + if (err) { + return callback(err); + } + + Query.base.updateMany.call(_this, castedQuery, castedDoc, options, callback); + }; + try { + doValidate(_callback); + } catch (err) { + process.nextTick(function() { + callback(err); + }); + } + return this; + } + + Query.base.replaceOne.call(this, castedQuery, castedDoc, options, callback); + return this; +}; + /** * Declare and/or execute this query as an update() operation. * @@ -2404,8 +2451,56 @@ Query.prototype.updateOne = function(conditions, doc, options, callback) { return _update(this, 'updateOne', conditions, doc, options, callback); }; +/** + * Declare and/or execute this query as a replaceOne() operation. Same as + * `update()`, except MongoDB will replace the existing document and will + * not accept any atomic operators (`$set`, etc.) + * + * **Note** replaceOne will _not_ fire update middleware. Use `pre('replaceOne')` + * and `post('replaceOne')` instead. + * + * @param {Object} [criteria] + * @param {Object} [doc] the update command + * @param {Object} [options] + * @param {Function} [callback] optional params are (error, writeOpResult) + * @return {Query} this + * @see Model.update #model_Model.update + * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/ + * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult + * @api public + */ + +Query.prototype.replaceOne = function(conditions, doc, options, callback) { + if (typeof options === 'function') { + // .update(conditions, doc, callback) + callback = options; + options = null; + } else if (typeof doc === 'function') { + // .update(doc, callback); + callback = doc; + doc = conditions; + conditions = {}; + options = null; + } else if (typeof conditions === 'function') { + // .update(callback) + callback = conditions; + conditions = undefined; + doc = undefined; + options = undefined; + } else if (typeof conditions === 'object' && !doc && !options && !callback) { + // .update(doc) + doc = conditions; + conditions = undefined; + options = undefined; + callback = undefined; + } + + this.setOptions({ overwrite: true }); + return _update(this, 'replaceOne', conditions, doc, options, callback); +}; + /*! - * Internal helper for update, updateMany, updateOne + * Internal helper for update, updateMany, updateOne, replaceOne */ function _update(query, op, conditions, doc, options, callback) { @@ -2464,7 +2559,7 @@ function _update(query, op, conditions, doc, options, callback) { $options.minimize = true; } castedDoc = query._castUpdate(utils.clone(doc, $options), - options && options.overwrite); + (options && options.overwrite) || op === 'replaceOne'); } catch (err) { query._castError = castedQuery; if (callback) { diff --git a/package.json b/package.json index 2d021a5c730..f3ed987d8f0 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.2.24", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "2.2.3", + "mquery": "2.3.0", "ms": "0.7.2", "muri": "1.2.1", "regexp-clone": "0.0.1", diff --git a/test/model.update.test.js b/test/model.update.test.js index 4d4861b6fc5..f0cd826ff15 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1658,6 +1658,28 @@ describe('model: update:', function() { }); }); + it('replaceOne', function(done) { + var schema = mongoose.Schema({ name: String, age: Number }, { + versionKey: false + }); + var Model = db.model('gh3998_r1', schema); + + Model.create({ name: 'abc', age: 1 }, function(error, m) { + assert.ifError(error); + Model.replaceOne({ name: 'abc' }, { name: 'test' }).exec(function(err) { + assert.ifError(err); + Model.findById(m._id).exec(function(error, doc) { + assert.ifError(error); + assert.deepEqual(doc.toObject({ virtuals: false }), { + _id: m._id, + name: 'test' + }); + done(); + }); + }); + }); + }); + it('mixed nested type casting (gh-3337)', function(done) { var Schema = mongoose.Schema({attributes: {}}, {strict: true}); var Model = db.model('gh3337', Schema); From c17732c6db34e130a96fff4a050165c3872fb180 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Mar 2017 20:08:21 -0700 Subject: [PATCH 1290/2240] test(update): repro #5032 --- test/model.update.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 4d4861b6fc5..8bd7770f6da 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2359,6 +2359,23 @@ describe('model: update:', function() { done(); }); + it('findOneAndUpdate with nested arrays (gh-5032)', function(done) { + var schema = Schema({ + name: String, + inputs: [ [ String ] ] // Array of Arrays of Strings + }); + + var Activity = db.model('Test', schema); + + var q = { name: 'Host Discovery' }; + var u = { inputs: [['ipRange']] }; + var o = { upsert: true }; + Activity.findOneAndUpdate(q, u, o).exec(function(error) { + assert.ifError(error); + done(); + }); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From 7d69ceb57a2a3fa5cc05b372eb3d2b29c7ce6ea8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Mar 2017 20:08:33 -0700 Subject: [PATCH 1291/2240] fix(update): use correct method for casting nested arrays Fix #5032 --- lib/schema/array.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/schema/array.js b/lib/schema/array.js index 1d0948bc2f4..c2fcabd01ef 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -217,6 +217,9 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { var Constructor = this.casterConstructor; var proto = this.casterConstructor.prototype; var method = proto && (proto.castForQuery || proto.cast); + if (!method && Constructor.castForQuery) { + method = Constructor.castForQuery; + } var caster = this.caster; if (Array.isArray(val)) { From f30d834a6fd13eb61c41c76c400cc8da7e53e9c0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Mar 2017 21:54:11 -0700 Subject: [PATCH 1292/2240] test(document): repro #5047 --- test/document.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index e8faab4b4ac..1e3ff2683b5 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3835,6 +3835,20 @@ describe('document', function() { }); }); + it('allows hook as a schema key (gh-5047)', function(done) { + var schema = new mongoose.Schema({ + name: String, + hook: { type: String } + }); + + var Model = db.model('Model', schema); + + Model.create({ hook: 'test '}, function(error) { + assert.ifError(error); + done(); + }); + }); + it('nested docs toObject() clones (gh-5008)', function(done) { var schema = new mongoose.Schema({ sub: { From 6669f4188eb5f0ed563a11e2262d6b480d603116 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Mar 2017 21:57:22 -0700 Subject: [PATCH 1293/2240] fix(document): use $hook instead of hook Fix #5047 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index decead2e992..23c290280f2 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "async": "2.1.4", "bson": "~1.0.4", - "hooks-fixed": "1.2.0", + "hooks-fixed": "2.0.0", "kareem": "1.2.1", "mongodb": "2.2.24", "mpath": "0.2.1", From 3dba7b3f00d3075c1e0f3f13b202fa92c2fdfb93 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Mar 2017 22:59:24 -0700 Subject: [PATCH 1294/2240] test(populate): repro #5037 --- .../projection/isPathSelectedInclusive.js | 28 +++++++++++ test/model.populate.test.js | 50 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 lib/services/projection/isPathSelectedInclusive.js diff --git a/lib/services/projection/isPathSelectedInclusive.js b/lib/services/projection/isPathSelectedInclusive.js new file mode 100644 index 00000000000..7738e7c1d14 --- /dev/null +++ b/lib/services/projection/isPathSelectedInclusive.js @@ -0,0 +1,28 @@ +'use strict'; + +/*! + * ignore + */ + +module.exports = function isPathSelectedInclusive(fields, path) { + var chunks = path.split('.'); + var cur = ''; + var j; + var keys; + var numKeys; + for (var i = 0; i < chunks.length; ++i) { + cur += cur.length ? '.' : '' + chunks[i]; + if (fields[cur]) { + keys = Object.keys(fields); + numKeys = keys.length; + for (j = 0; j < numKeys; ++j) { + if (keys[i].indexOf(cur + '.') === 0 && keys[i].indexOf(path) !== 0) { + continue; + } + } + return true; + } + } + + return false; +}; diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 8a39af66f22..eba26d8bf88 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5022,6 +5022,56 @@ describe('model: populate:', function() { catch(done); }); + it('works if foreignField parent is selected (gh-5037)', function(done) { + var childSchema = new mongoose.Schema({ + name: String, + parent: { + id: mongoose.Schema.Types.ObjectId, + name: String + } + }); + + var Child = db.model('gh5037', childSchema); + + var parentSchema = new mongoose.Schema({ + name: String + }); + + parentSchema.virtual('detail', { + ref: 'gh5037', + localField: '_id', + foreignField: 'parent.id', + justOne: true + }); + + var Parent = db.model('gh5037_0', parentSchema); + + Parent.create({ name: 'Test' }). + then(function(m) { + return Child.create({ + name: 'test', + parent: { + id: m._id, + name: 'test2' + } + }); + }). + then(function() { + return Parent.find().populate({ + path: 'detail', + select: 'name parent' + }); + }). + then(function(res) { + var m = res[0]; + assert.equal(m.detail.name, 'test'); + assert.ok(m.detail.parent.id); + assert.equal(m.detail.parent.name, 'test2'); + done(); + }). + catch(done); + }); + it('specify model in populate (gh-4264)', function(done) { var PersonSchema = new Schema({ name: String, From 952eaca4fa5fca1d60589a100770c32d68411569 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Mar 2017 23:00:07 -0700 Subject: [PATCH 1295/2240] fix(populate): dont select foreign field if parent field is selected Fix #5037 --- lib/model.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index bff3b911d24..1472d9d7eef 100644 --- a/lib/model.js +++ b/lib/model.js @@ -16,6 +16,7 @@ var applyHooks = require('./services/model/applyHooks'); var applyMethods = require('./services/model/applyMethods'); var applyStatics = require('./services/model/applyStatics'); var discriminator = require('./services/model/discriminator'); +var isPathSelectedInclusive = require('./services/projection/isPathSelectedInclusive'); var parallel = require('async/parallel'); var util = require('util'); var utils = require('./utils'); @@ -2744,7 +2745,7 @@ function populate(model, docs, options, callback) { * If projection is exclusive and client explicitly unselected the foreign * field, that's the client's fault. */ if (mod.foreignField !== '_id' && query.selectedInclusively() && - !(mod.foreignField in query._fields)) { + !isPathSelectedInclusive(query._fields, mod.foreignField)) { query.select(mod.foreignField); } From 7c114acb8fe8497fcb5557bb4a68e8f831b5040f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Mar 2017 23:31:25 -0700 Subject: [PATCH 1296/2240] test(discriminator): repro #5009 --- test/model.discriminator.test.js | 49 ++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 5df800732d5..f373b0fc444 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -449,6 +449,55 @@ describe('model', function() { catch(done); }); + it('embedded discriminators with $push (gh-5009)', function(done) { + var eventSchema = new Schema({ message: String }, + { discriminatorKey: 'kind', _id: false }); + var batchSchema = new Schema({ events: [eventSchema] }); + var docArray = batchSchema.path('events'); + + var Clicked = docArray.discriminator('Clicked', new Schema({ + element: { + type: String, + required: true + } + }, { _id: false })); + + var Purchased = docArray.discriminator('Purchased', new Schema({ + product: { + type: String, + required: true + } + }, { _id: false })); + + var Batch = db.model('gh5009', batchSchema); + + var batch = { + events: [ + { kind: 'Clicked', element: '#hero' } + ] + }; + + Batch.create(batch). + then(function(doc) { + assert.equal(doc.events.length, 1); + return Batch.updateOne({ _id: doc._id }, { + $push: { + events: { kind: 'Clicked', element: '#button' } + } + }).then(() => doc); + }). + then(function(doc) { + return Batch.findOne({ _id: doc._id }); + }). + then(function(doc) { + assert.equal(doc.events.length, 2); + assert.equal(doc.events[1].element, '#button'); + assert.equal(doc.events[1].kind, 'Clicked'); + done(); + }). + catch(done); + }); + it('embedded in document arrays (gh-2723)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From 93905433bed068c0576d88a0346e1f5b511a2bd1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Mar 2017 23:31:44 -0700 Subject: [PATCH 1297/2240] fix(discriminator): handle array discriminators when casting $push Fix #5009 --- lib/schema/array.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/schema/array.js b/lib/schema/array.js index c2fcabd01ef..b5833620072 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -215,6 +215,15 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { } else { val = $conditional; var Constructor = this.casterConstructor; + + if (val && + Constructor.discriminators && + Constructor.schema.options.discriminatorKey && + typeof val[Constructor.schema.options.discriminatorKey] === 'string' && + Constructor.discriminators[val[Constructor.schema.options.discriminatorKey]]) { + Constructor = Constructor.discriminators[val[Constructor.schema.options.discriminatorKey]]; + } + var proto = this.casterConstructor.prototype; var method = proto && (proto.castForQuery || proto.cast); if (!method && Constructor.castForQuery) { From 0c995387ead288761d82bb73508ef1dd86207717 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 9 Mar 2017 21:02:52 -0700 Subject: [PATCH 1298/2240] style: remove unnecessary utils. Re: https://github.com/Automattic/mongoose/commit/59c6d3ee90e2f332d81a955412af4c0a511ebe36#commitcomment-21117266 --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index f374867c727..08e179bcb5e 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1793,7 +1793,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { configurable: true, writable: false, value: function() { - return utils.clone(_this.get(path), { retainKeyOrder: true }); + return clone(_this.get(path), { retainKeyOrder: true }); } }); From d55525142c117dc624752e706a2d449263b1144d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 9 Mar 2017 22:47:07 -0700 Subject: [PATCH 1299/2240] test(query): add coverage for the justOne option --- test/query.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index fa919d90e24..c73e84173d9 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1139,6 +1139,24 @@ describe('Query', function() { }); }, done).end(); }); + + it('justOne option', function(done) { + var db = start(); + var Test = db.model('Test_justOne', new Schema({ name: String })); + + Test.create([{ name: 'Eddard Stark' }, { name: 'Robb Stark' }], function(error) { + assert.ifError(error); + Test.remove({ name: /Stark/ }).setOptions({ justOne: false }).exec(function(error, res) { + assert.ifError(error); + assert.equal(res.result.n, 2); + Test.count({}, function(error, count) { + assert.ifError(error); + assert.equal(count, 0); + done(); + }); + }); + }); + }); }); describe('querying/updating with model instance containing embedded docs should work (#454)', function() { From a04960195b1d5a3ba92490229bf93aad16fc42f9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 9 Mar 2017 22:54:44 -0700 Subject: [PATCH 1300/2240] feat(query): add deleteOne and deleteMany re: #3998 --- lib/model.js | 81 ++++++++++++++++++++++++++++++++++++++++------ lib/query.js | 72 +++++++++++++++++++++++++++++++++++++++++ test/query.test.js | 42 ++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 9 deletions(-) diff --git a/lib/model.js b/lib/model.js index 26c9a6943f6..2b9cc24a7db 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1062,24 +1062,87 @@ Model.base; Model.discriminators; /** - * Removes documents from the collection. + * Removes the first document that matches `conditions` from the collection. + * To remove all documents that match `conditions`, set the `justOne` option + * to false. * * ####Example: * - * Comment.remove({ title: 'baby born from alien father' }, function (err) { + * Character.remove({ name: 'Eddard Stark' }, function (err) {}); * - * }); + * ####Note: + * + * This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, _no middleware (hooks) are executed_. + * + * @param {Object} conditions + * @param {Function} [callback] + * @return {Query} + * @api public + */ + +Model.remove = function remove(conditions, callback) { + if (typeof conditions === 'function') { + callback = conditions; + conditions = {}; + } + + // get the mongodb collection object + var mq = new this.Query(conditions, {}, this, this.collection); + + if (callback) { + callback = this.$wrapCallback(callback); + } + + return mq.remove(callback); +}; + +/** + * Deletes the first document that matches `conditions` from the collection. + * Behaves like `remove()`, but deletes at most one document regardless of the + * `justOne` option. + * + * ####Example: + * + * Character.deleteOne({ name: 'Eddard Stark' }, function (err) {}); * * ####Note: * - * To remove documents without waiting for a response from MongoDB, do not pass a `callback`, then call `exec` on the returned [Query](#query-js): + * Like `Model.remove()`, this function does **not** trigger `pre('remove')` or `post('remove')` hooks. * - * var query = Comment.remove({ _id: id }); - * query.exec(); + * @param {Object} conditions + * @param {Function} [callback] + * @return {Query} + * @api public + */ + +Model.deleteOne = function deleteOne(conditions, callback) { + if (typeof conditions === 'function') { + callback = conditions; + conditions = {}; + } + + // get the mongodb collection object + var mq = new this.Query(conditions, {}, this, this.collection); + + if (callback) { + callback = this.$wrapCallback(callback); + } + + return mq.deleteOne(callback); +}; + +/** + * Deletes the first document that matches `conditions` from the collection. + * Behaves like `remove()`, but deletes all documents that match `conditions` + * regardless of the `justOne` option. + * + * ####Example: + * + * Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, function (err) {}); * * ####Note: * - * This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, _no middleware (hooks) are executed_. + * Like `Model.remove()`, this function does **not** trigger `pre('remove')` or `post('remove')` hooks. * * @param {Object} conditions * @param {Function} [callback] @@ -1087,7 +1150,7 @@ Model.discriminators; * @api public */ -Model.remove = function remove(conditions, callback) { +Model.deleteMany = function deleteMany(conditions, callback) { if (typeof conditions === 'function') { callback = conditions; conditions = {}; @@ -1100,7 +1163,7 @@ Model.remove = function remove(conditions, callback) { callback = this.$wrapCallback(callback); } - return mq.remove(callback); + return mq.deleteMany(callback); }; /** diff --git a/lib/query.js b/lib/query.js index ab7095cea77..96f7facfa6e 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1618,6 +1618,78 @@ Query.prototype.remove = function(cond, callback) { return Query.base.remove.call(this, cond, callback); }; +/** + * Declare and/or execute this query as a `deleteOne()` operation. Works like + * remove, except it deletes at most one document regardless of the `justOne` + * option. + * + * ####Example + * + * Character.deleteOne({ name: 'Eddard Stark' }, callback) + * Character.deleteOne({ name: 'Eddard Stark' }).then(next) + * + * @param {Object|Query} [criteria] mongodb selector + * @param {Function} [callback] optional params are (error, writeOpResult) + * @return {Query} this + * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult + * @see remove http://docs.mongodb.org/manual/reference/method/db.collection.remove/ + * @api public + */ + +Query.prototype.deleteOne = function(cond, callback) { + if (typeof cond === 'function') { + callback = cond; + cond = null; + } + + var cb = typeof callback === 'function'; + + try { + this.cast(this.model); + } catch (err) { + if (cb) return process.nextTick(callback.bind(null, err)); + return this; + } + + return Query.base.deleteOne.call(this, cond, callback); +}; + +/** + * Declare and/or execute this query as a `deleteMany()` operation. Works like + * remove, except it deletes _every_ document that matches `criteria` in the + * collection, regardless of the value of `justOne`. + * + * ####Example + * + * Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, callback) + * Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }).then(next) + * + * @param {Object|Query} [criteria] mongodb selector + * @param {Function} [callback] optional params are (error, writeOpResult) + * @return {Query} this + * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult + * @see remove http://docs.mongodb.org/manual/reference/method/db.collection.remove/ + * @api public + */ + +Query.prototype.deleteMany = function(cond, callback) { + if (typeof cond === 'function') { + callback = cond; + cond = null; + } + + var cb = typeof callback === 'function'; + + try { + this.cast(this.model); + } catch (err) { + if (cb) return process.nextTick(callback.bind(null, err)); + return this; + } + + return Query.base.deleteMany.call(this, cond, callback); +}; + /*! * hydrates a document * diff --git a/test/query.test.js b/test/query.test.js index c73e84173d9..82b1c20e6b2 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1078,6 +1078,48 @@ describe('Query', function() { }); }); + describe('deleteOne/deleteMany', function() { + var db; + + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('handles deleteOne', function(done) { + var M = db.model('deleteOne', new Schema({ name: 'String' })); + M.create([{ name: 'Eddard Stark' }, { name: 'Robb Stark' }], function(error) { + assert.ifError(error); + M.deleteOne({ name: /Stark/ }, function(error) { + assert.ifError(error); + M.count({}, function(error, count) { + assert.ifError(error); + assert.equal(count, 1); + done(); + }); + }); + }); + }); + + it('handles deleteMany', function(done) { + var M = db.model('deleteMany', new Schema({ name: 'String' })); + M.create([{ name: 'Eddard Stark' }, { name: 'Robb Stark' }], function(error) { + assert.ifError(error); + M.deleteMany({ name: /Stark/ }, function(error) { + assert.ifError(error); + M.count({}, function(error, count) { + assert.ifError(error); + assert.equal(count, 0); + done(); + }); + }); + }); + }); + }); + describe('remove', function() { it('handles cast errors async', function(done) { var db = start(); From 4507487d8b872a5c4394a6abed940deeb9e4de9f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 9 Mar 2017 22:59:40 -0700 Subject: [PATCH 1301/2240] test: remove es6-only code from tests --- test/model.discriminator.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index f373b0fc444..ab00eb46535 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -484,7 +484,9 @@ describe('model', function() { $push: { events: { kind: 'Clicked', element: '#button' } } - }).then(() => doc); + }).then(function() { + return doc; + }); }). then(function(doc) { return Batch.findOne({ _id: doc._id }); From 0540c8abc79ac90a71b436c254e0cd083c4a1f36 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 9 Mar 2017 23:08:14 -0700 Subject: [PATCH 1302/2240] test: fix tests --- test/model.discriminator.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index f373b0fc444..ab00eb46535 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -484,7 +484,9 @@ describe('model', function() { $push: { events: { kind: 'Clicked', element: '#button' } } - }).then(() => doc); + }).then(function() { + return doc; + }); }). then(function(doc) { return Batch.findOne({ _id: doc._id }); From 057bd3f20312898c1f31704c0d6e7c46f7775f44 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Mar 2017 21:20:16 -0700 Subject: [PATCH 1303/2240] test(model): repro #5061 --- test/model.create.test.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/model.create.test.js b/test/model.create.test.js index 75aa09acd47..5b25327ab8c 100644 --- a/test/model.create.test.js +++ b/test/model.create.test.js @@ -15,7 +15,7 @@ var start = require('./common'), */ var schema = new Schema({ - title: String + title: { type: String, required: true } }); @@ -186,6 +186,15 @@ describe('model', function() { }).end(); }, done).end(); }); + + it('if callback is falsy, will ignore it (gh-5061)', function(done) { + B.create({ title: 'test' }, null). + then(function(doc) { + assert.equal(doc.title, 'test'); + done(); + }). + catch(done); + }); }); }); }); From e09a428b364084e0c583de410c4139c23546c245 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Mar 2017 21:20:20 -0700 Subject: [PATCH 1304/2240] fix(model): if last arg in spread is falsy, treat it as a callback Fix #5061 --- lib/model.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 1472d9d7eef..b2441c0f9f4 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1797,7 +1797,8 @@ Model.create = function create(doc, callback) { cb = callback; } else { var last = arguments[arguments.length - 1]; - if (typeof last === 'function') { + // Handle falsy callbacks re: #5061 + if (typeof last === 'function' || !last) { cb = last; args = utils.args(arguments, 0, arguments.length - 1); } else { From 0450b411fdb04b96bfba808236df912ab1559e1b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Mar 2017 15:15:05 -0700 Subject: [PATCH 1305/2240] feat(model): add rudimentary bulkWrite support Re: #3998 --- lib/model.js | 87 ++++++++++++++++++++++++++++++++++++++++++++++ test/model.test.js | 34 ++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/lib/model.js b/lib/model.js index 2b9cc24a7db..3506ec11ffc 100644 --- a/lib/model.js +++ b/lib/model.js @@ -15,6 +15,7 @@ var VersionError = require('./error').VersionError; var applyHooks = require('./services/model/applyHooks'); var applyMethods = require('./services/model/applyMethods'); var applyStatics = require('./services/model/applyStatics'); +var cast = require('./cast'); var discriminator = require('./services/model/discriminator'); var isPathSelectedInclusive = require('./services/projection/isPathSelectedInclusive'); var parallel = require('async/parallel'); @@ -2009,6 +2010,92 @@ Model.insertMany = function(arr, options, callback) { }); }; +/** + * Sends multiple `insertOne`, `updateOne`, `updateMany`, `replaceOne`, + * `deleteOne`, and/or `deleteMany` operations to the MongoDB server in one + * command. This is faster than sending multiple independent operations because + * with `bulkWrite()` there is only one round trip to the server. + * + * Mongoose will perform casting on all operations you provide. + * + * This function does **not** trigger any middleware. + * + * ####Example: + * + * var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }]; + * Movies.insertMany(arr, function(error, docs) {}); + * + * @param {Array} ops + * @param {Object} [options] + * @param {Function} [callback] callback `function(error, bulkWriteOpResult) {}` + * @return {Promise} resolves to a `BulkWriteOpResult` if the operation succeeds + * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~BulkWriteOpResult + * @api public + */ + +Model.bulkWrite = function(ops, options, callback) { + var Promise = PromiseProvider.get(); + var _this = this; + if (typeof options === 'function') { + callback = options; + options = null; + } + if (callback) { + callback = this.$wrapCallback(callback); + } + options = options || {}; + + var validations = ops.map(function(op) { + if (op['insertOne']) { + return function(callback) { + op['insertOne']['document'] = new _this(op['insertOne']['document']); + op['insertOne']['document'].validate({ __noPromise: true }, function(error) { + if (error) { + return callback(error); + } + callback(null); + }); + }; + } else if (op['updateOne']) { + return function(callback) { + try { + op['updateOne']['filter'] = cast(_this.schema, + op['updateOne']['filter']); + } catch (error) { + return callback(error); + } + + callback(null); + }; + } else { + return function(callback) { + callback(new Error('Invalid op passed to `bulkWrite()`')); + }; + } + }); + + var promise = new Promise.ES6(function(resolve, reject) { + parallel(validations, function(error) { + if (error) { + callback && callback(error); + return reject(error); + } + + _this.collection.bulkWrite(ops, options, function(error, res) { + if (error) { + callback && callback(error); + return reject(error); + } + + callback && callback(null, res); + resolve(res); + }); + }); + }); + + return promise; +}; + /** * Shortcut for creating a new Document from existing raw data, pre-saved in the DB. * The document returned has no paths marked as modified initially. diff --git a/test/model.test.js b/test/model.test.js index c424f25cff6..bb0a1028eb4 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5460,6 +5460,40 @@ describe('Model', function() { }); }); + it('bulkWrite casting (gh-3998)', function(done) { + var schema = new Schema({ + str: String, + num: Number + }); + + var M = db.model('gh3998', schema); + + var ops = [ + { + insertOne: { + document: { str: 1, num: '1' } + } + }, + { + updateOne: { + filter: { str: 1 }, + update: { + $set: { num: '2' } + } + } + } + ]; + M.bulkWrite(ops, function(error) { + assert.ifError(error); + M.findOne({}, function(error, doc) { + assert.ifError(error); + assert.equal(doc.str, '1'); + assert.equal(doc.num, '2'); + done(); + }); + }); + }); + it('marks array as modified when initializing non-array from db (gh-2442)', function(done) { var s1 = new Schema({ array: mongoose.Schema.Types.Mixed From 28f337730b4082ff54341cad870c44e031fda8e9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Mar 2017 17:42:12 -0700 Subject: [PATCH 1306/2240] refactor(query): expose castUpdate as a pure function internally --- lib/query.js | 284 ++---------------------------- lib/services/query/castUpdate.js | 289 +++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+), 272 deletions(-) create mode 100644 lib/services/query/castUpdate.js diff --git a/lib/query.js b/lib/query.js index 96f7facfa6e..39da3f0d534 100644 --- a/lib/query.js +++ b/lib/query.js @@ -5,8 +5,8 @@ var PromiseProvider = require('./promise_provider'); var QueryCursor = require('./querycursor'); var QueryStream = require('./querystream'); -var StrictModeError = require('./error/strict'); var cast = require('./cast'); +var castUpdate = require('./services/query/castUpdate'); var helpers = require('./queryhelpers'); var mquery = require('mquery'); var readPref = require('./drivers').ReadPreference; @@ -2763,42 +2763,6 @@ Query.prototype.catch = function(reject) { return this.exec().then(null, reject); }; -/** - * Finds the schema for `path`. This is different than - * calling `schema.path` as it also resolves paths with - * positional selectors (something.$.another.$.path). - * - * @param {String} path - * @api private - */ - -Query.prototype._getSchema = function _getSchema(path) { - return this.model._getSchema(path); -}; - -/*! - * These operators require casting docs - * to real Documents for Update operations. - */ - -var castOps = { - $push: 1, - $pushAll: 1, - $addToSet: 1, - $set: 1 -}; - -/*! - * These operators should be cast to numbers instead - * of their path schema type. - */ - -var numberOps = { - $pop: 1, - $unset: 1, - $inc: 1 -}; - /*! * Casts obj for an update command. * @@ -2808,242 +2772,18 @@ var numberOps = { */ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) { - if (!obj) { - return undefined; - } - - var ops = Object.keys(obj); - var i = ops.length; - var ret = {}; - var hasKeys; - var val; - var hasDollarKey = false; - - while (i--) { - var op = ops[i]; - // if overwrite is set, don't do any of the special $set stuff - if (op[0] !== '$' && !overwrite) { - // fix up $set sugar - if (!ret.$set) { - if (obj.$set) { - ret.$set = obj.$set; - } else { - ret.$set = {}; - } - } - ret.$set[op] = obj[op]; - ops.splice(i, 1); - if (!~ops.indexOf('$set')) ops.push('$set'); - } else if (op === '$set') { - if (!ret.$set) { - ret[op] = obj[op]; - } - } else { - ret[op] = obj[op]; - } - } - - // cast each value - i = ops.length; - - // if we get passed {} for the update, we still need to respect that when it - // is an overwrite scenario - if (overwrite) { - hasKeys = true; - } - - while (i--) { - op = ops[i]; - val = ret[op]; - hasDollarKey = hasDollarKey || op.charAt(0) === '$'; - if (val && - typeof val === 'object' && - (!overwrite || hasDollarKey)) { - hasKeys |= this._walkUpdatePath(val, op); - } else if (overwrite && ret && typeof ret === 'object') { - // if we are just using overwrite, cast the query and then we will - // *always* return the value, even if it is an empty object. We need to - // set hasKeys above because we need to account for the case where the - // user passes {} and wants to clobber the whole document - // Also, _walkUpdatePath expects an operation, so give it $set since that - // is basically what we're doing - this._walkUpdatePath(ret, '$set'); - } else { - var msg = 'Invalid atomic update value for ' + op + '. ' - + 'Expected an object, received ' + typeof val; - throw new Error(msg); - } - } - - return hasKeys && ret; -}; - -/** - * Walk each path of obj and cast its values - * according to its schema. - * - * @param {Object} obj - part of a query - * @param {String} op - the atomic operator ($pull, $set, etc) - * @param {String} pref - path prefix (internal only) - * @return {Bool} true if this path has keys to update - * @api private - */ - -Query.prototype._walkUpdatePath = function _walkUpdatePath(obj, op, pref) { - var prefix = pref ? pref + '.' : '', - keys = Object.keys(obj), - i = keys.length, - hasKeys = false, - schema, - key, - val; - - var useNestedStrict = this.schema.options.useNestedStrict; - - while (i--) { - key = keys[i]; - val = obj[key]; - - if (val && val.constructor.name === 'Object') { - // watch for embedded doc schemas - schema = this._getSchema(prefix + key); - if (schema && schema.caster && op in castOps) { - // embedded doc schema - hasKeys = true; - - if ('$each' in val) { - obj[key] = { - $each: this._castUpdateVal(schema, val.$each, op) - }; - - if (val.$slice != null) { - obj[key].$slice = val.$slice | 0; - } - - if (val.$sort) { - obj[key].$sort = val.$sort; - } - - if (!!val.$position || val.$position === 0) { - obj[key].$position = val.$position; - } - } else { - obj[key] = this._castUpdateVal(schema, val, op); - } - } else if (op === '$currentDate') { - // $currentDate can take an object - obj[key] = this._castUpdateVal(schema, val, op); - hasKeys = true; - } else if (op === '$set' && schema) { - obj[key] = this._castUpdateVal(schema, val, op); - hasKeys = true; - } else { - var pathToCheck = (prefix + key); - var v = this.model.schema._getPathType(pathToCheck); - var _strict = 'strict' in this._mongooseOptions ? - this._mongooseOptions.strict : - ((useNestedStrict && v.schema) || this.schema).options.strict; - if (v.pathType === 'undefined') { - if (_strict === 'throw') { - throw new StrictModeError(pathToCheck); - } else if (_strict) { - delete obj[key]; - continue; - } - } - - // gh-2314 - // we should be able to set a schema-less field - // to an empty object literal - hasKeys |= this._walkUpdatePath(val, op, prefix + key) || - (utils.isObject(val) && Object.keys(val).length === 0); - } - } else { - var checkPath = (key === '$each' || key === '$or' || key === '$and') ? - pref : prefix + key; - schema = this._getSchema(checkPath); - - var pathDetails = this.model.schema._getPathType(checkPath); - var isStrict = 'strict' in this._mongooseOptions ? - this._mongooseOptions.strict : - ((useNestedStrict && pathDetails.schema) || this.schema).options.strict; - - var skip = isStrict && - !schema && - !/real|nested/.test(pathDetails.pathType); - - if (skip) { - if (isStrict === 'throw') { - throw new StrictModeError(prefix + key); - } else { - delete obj[key]; - } - } else { - // gh-1845 temporary fix: ignore $rename. See gh-3027 for tracking - // improving this. - if (op === '$rename') { - hasKeys = true; - continue; - } - - hasKeys = true; - obj[key] = this._castUpdateVal(schema, val, op, key); - } - } - } - return hasKeys; -}; - -/** - * Casts `val` according to `schema` and atomic `op`. - * - * @param {Schema} schema - * @param {Object} val - * @param {String} op - the atomic operator ($pull, $set, etc) - * @param {String} [$conditional] - * @api private - */ - -Query.prototype._castUpdateVal = function _castUpdateVal(schema, val, op, $conditional) { - if (!schema) { - // non-existing schema path - return op in numberOps - ? Number(val) - : val; - } - - var cond = schema.caster && op in castOps && - (utils.isObject(val) || Array.isArray(val)); - if (cond) { - // Cast values for ops that add data to MongoDB. - // Ensures embedded documents get ObjectIds etc. - var tmp = schema.cast(val); - if (Array.isArray(val)) { - val = tmp; - } else if (Array.isArray(tmp)) { - val = tmp[0]; - } else { - val = tmp; - } - } - - if (op in numberOps) { - if (op === '$inc') { - return schema.castForQuery(val); - } - return Number(val); - } - if (op === '$currentDate') { - if (typeof val === 'object') { - return {$type: val.$type}; - } - return Boolean(val); - } - if (/^\$/.test($conditional)) { - return schema.castForQuery($conditional, val); + var strict; + if ('strict' in this._mongooseOptions) { + strict = this._mongooseOptions.strict; + } else if (this.schema && this.schema.options) { + strict = this.schema.options.strict; + } else { + strict = true; } - - return schema.castForQuery(val); + return castUpdate(this.schema, obj, { + overwrite: overwrite, + strict: strict + }); }; /*! diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js new file mode 100644 index 00000000000..6a0a80993fb --- /dev/null +++ b/lib/services/query/castUpdate.js @@ -0,0 +1,289 @@ +'use strict'; + +var StrictModeError = require('../../error/strict'); +var utils = require('../../utils'); + +/*! + * Casts an update op based on the given schema + * + * @param {Schema} schema + * @param {Object} obj + * @param {Object} options + * @param {Boolean} [options.overwrite] defaults to false + * @param {Boolean|String} [options.strict] defaults to true + * @return {Boolean} true iff the update is non-empty + */ + +module.exports = function castUpdate(schema, obj, options) { + if (!obj) { + return undefined; + } + + var ops = Object.keys(obj); + var i = ops.length; + var ret = {}; + var hasKeys; + var val; + var hasDollarKey = false; + var overwrite = options.overwrite; + + while (i--) { + var op = ops[i]; + // if overwrite is set, don't do any of the special $set stuff + if (op[0] !== '$' && !overwrite) { + // fix up $set sugar + if (!ret.$set) { + if (obj.$set) { + ret.$set = obj.$set; + } else { + ret.$set = {}; + } + } + ret.$set[op] = obj[op]; + ops.splice(i, 1); + if (!~ops.indexOf('$set')) ops.push('$set'); + } else if (op === '$set') { + if (!ret.$set) { + ret[op] = obj[op]; + } + } else { + ret[op] = obj[op]; + } + } + + // cast each value + i = ops.length; + + // if we get passed {} for the update, we still need to respect that when it + // is an overwrite scenario + if (overwrite) { + hasKeys = true; + } + + while (i--) { + op = ops[i]; + val = ret[op]; + hasDollarKey = hasDollarKey || op.charAt(0) === '$'; + if (val && + typeof val === 'object' && + (!overwrite || hasDollarKey)) { + hasKeys |= walkUpdatePath(schema, val, op, options.strict); + } else if (overwrite && ret && typeof ret === 'object') { + // if we are just using overwrite, cast the query and then we will + // *always* return the value, even if it is an empty object. We need to + // set hasKeys above because we need to account for the case where the + // user passes {} and wants to clobber the whole document + // Also, _walkUpdatePath expects an operation, so give it $set since that + // is basically what we're doing + walkUpdatePath(schema, ret, '$set', options.strict); + } else { + var msg = 'Invalid atomic update value for ' + op + '. ' + + 'Expected an object, received ' + typeof val; + throw new Error(msg); + } + } + + return hasKeys && ret; +}; + +/*! + * Walk each path of obj and cast its values + * according to its schema. + * + * @param {Schema} schema + * @param {Object} obj - part of a query + * @param {String} op - the atomic operator ($pull, $set, etc) + * @param {Boolean|String} strict + * @param {String} pref - path prefix (internal only) + * @return {Bool} true if this path has keys to update + * @api private + */ + +function walkUpdatePath(schema, obj, op, strict, pref) { + var prefix = pref ? pref + '.' : '', + keys = Object.keys(obj), + i = keys.length, + hasKeys = false, + schematype, + key, + val; + + var useNestedStrict = schema.options.useNestedStrict; + + while (i--) { + key = keys[i]; + val = obj[key]; + + if (val && val.constructor.name === 'Object') { + // watch for embedded doc schemas + schematype = schema._getSchema(prefix + key); + if (schematype && schematype.caster && op in castOps) { + // embedded doc schema + hasKeys = true; + + if ('$each' in val) { + obj[key] = { + $each: castUpdateVal(schematype, val.$each, op) + }; + + if (val.$slice != null) { + obj[key].$slice = val.$slice | 0; + } + + if (val.$sort) { + obj[key].$sort = val.$sort; + } + + if (!!val.$position || val.$position === 0) { + obj[key].$position = val.$position; + } + } else { + obj[key] = castUpdateVal(schematype, val, op); + } + } else if (op === '$currentDate') { + // $currentDate can take an object + obj[key] = castUpdateVal(schematype, val, op); + hasKeys = true; + } else if (op === '$set' && schematype) { + obj[key] = castUpdateVal(schematype, val, op); + hasKeys = true; + } else { + var pathToCheck = (prefix + key); + var v = schema._getPathType(pathToCheck); + var _strict = strict; + if (useNestedStrict && + v && + v.schema && + 'strict' in v.schema.options) { + _strict = v.schema.options.strict; + } + + if (v.pathType === 'undefined') { + if (_strict === 'throw') { + throw new StrictModeError(pathToCheck); + } else if (_strict) { + delete obj[key]; + continue; + } + } + + // gh-2314 + // we should be able to set a schema-less field + // to an empty object literal + hasKeys |= walkUpdatePath(schema, val, op, strict, prefix + key) || + (utils.isObject(val) && Object.keys(val).length === 0); + } + } else { + var checkPath = (key === '$each' || key === '$or' || key === '$and') ? + pref : prefix + key; + schematype = schema._getSchema(checkPath); + + var pathDetails = schema._getPathType(checkPath); + var isStrict = strict; + if (useNestedStrict && + pathDetails && + pathDetails.schema && + 'strict' in pathDetails.schema.options) { + isStrict = pathDetails.schema.options.strict; + } + + var skip = isStrict && + !schematype && + !/real|nested/.test(pathDetails.pathType); + + if (skip) { + if (isStrict === 'throw') { + throw new StrictModeError(prefix + key); + } else { + delete obj[key]; + } + } else { + // gh-1845 temporary fix: ignore $rename. See gh-3027 for tracking + // improving this. + if (op === '$rename') { + hasKeys = true; + continue; + } + + hasKeys = true; + obj[key] = castUpdateVal(schematype, val, op, key); + } + } + } + return hasKeys; +} + +/*! + * These operators should be cast to numbers instead + * of their path schema type. + */ + +var numberOps = { + $pop: 1, + $unset: 1, + $inc: 1 +}; + +/*! + * These operators require casting docs + * to real Documents for Update operations. + */ + +var castOps = { + $push: 1, + $pushAll: 1, + $addToSet: 1, + $set: 1 +}; + +/*! + * Casts `val` according to `schema` and atomic `op`. + * + * @param {SchemaType} schema + * @param {Object} val + * @param {String} op - the atomic operator ($pull, $set, etc) + * @param {String} [$conditional] + * @api private + */ + +function castUpdateVal(schema, val, op, $conditional) { + if (!schema) { + // non-existing schema path + return op in numberOps + ? Number(val) + : val; + } + + var cond = schema.caster && op in castOps && + (utils.isObject(val) || Array.isArray(val)); + if (cond) { + // Cast values for ops that add data to MongoDB. + // Ensures embedded documents get ObjectIds etc. + var tmp = schema.cast(val); + if (Array.isArray(val)) { + val = tmp; + } else if (Array.isArray(tmp)) { + val = tmp[0]; + } else { + val = tmp; + } + } + + if (op in numberOps) { + if (op === '$inc') { + return schema.castForQuery(val); + } + return Number(val); + } + if (op === '$currentDate') { + if (typeof val === 'object') { + return {$type: val.$type}; + } + return Boolean(val); + } + if (/^\$/.test($conditional)) { + return schema.castForQuery($conditional, val); + } + + return schema.castForQuery(val); +} From 166b475df00c918f2a6cd69432e1214b4ea40ebf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Mar 2017 18:18:26 -0700 Subject: [PATCH 1307/2240] fix(model): handle update casting for bulkWrite re: #3998 --- lib/model.js | 18 ++++++++++++++++++ test/model.test.js | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index 3506ec11ffc..432c87ce6e8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -16,6 +16,7 @@ var applyHooks = require('./services/model/applyHooks'); var applyMethods = require('./services/model/applyMethods'); var applyStatics = require('./services/model/applyStatics'); var cast = require('./cast'); +var castUpdate = require('./services/query/castUpdate'); var discriminator = require('./services/model/discriminator'); var isPathSelectedInclusive = require('./services/projection/isPathSelectedInclusive'); var parallel = require('async/parallel'); @@ -2061,6 +2062,23 @@ Model.bulkWrite = function(ops, options, callback) { try { op['updateOne']['filter'] = cast(_this.schema, op['updateOne']['filter']); + op['updateOne']['update'] = castUpdate(_this.schema, + op['updateOne']['update'], _this.schema.options.strict); + } catch (error) { + return callback(error); + } + + callback(null); + }; + } else if (op['updateMany']) { + return function(callback) { + try { + op['updateMany']['filter'] = cast(_this.schema, + op['updateMany']['filter']); + op['updateMany']['update'] = castUpdate(_this.schema, op['updateMany']['filter'], { + strict: _this.schema.options.strict, + overwrite: false + }); } catch (error) { return callback(error); } diff --git a/test/model.test.js b/test/model.test.js index bb0a1028eb4..815a121482e 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5487,8 +5487,8 @@ describe('Model', function() { assert.ifError(error); M.findOne({}, function(error, doc) { assert.ifError(error); - assert.equal(doc.str, '1'); - assert.equal(doc.num, '2'); + assert.strictEqual(doc.str, '1'); + assert.strictEqual(doc.num, 2); done(); }); }); From 6ab3b8c432e53cb15cb801b5fbf7d0673850e641 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Mar 2017 18:46:31 -0700 Subject: [PATCH 1308/2240] fix(model): handle remaining ops for #3998 --- lib/model.js | 37 +++++++++++++++++++++++++++++++++++++ test/model.test.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/lib/model.js b/lib/model.js index 432c87ce6e8..aefafca9c90 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2083,6 +2083,43 @@ Model.bulkWrite = function(ops, options, callback) { return callback(error); } + callback(null); + }; + } else if (op['replaceOne']) { + return function(callback) { + try { + op['replaceOne']['filter'] = cast(_this.schema, + op['replaceOne']['filter']); + op['replaceOne']['update'] = castUpdate(_this.schema, op['replaceOne']['filter'], { + strict: _this.schema.options.strict, + overwrite: true + }); + } catch (error) { + return callback(error); + } + + callback(null); + }; + } else if (op['deleteOne']) { + return function(callback) { + try { + op['deleteOne']['filter'] = cast(_this.schema, + op['deleteOne']['filter']); + } catch (error) { + return callback(error); + } + + callback(null); + }; + } else if (op['deleteMany']) { + return function(callback) { + try { + op['deleteMany']['filter'] = cast(_this.schema, + op['deleteMany']['filter']); + } catch (error) { + return callback(error); + } + callback(null); }; } else { diff --git a/test/model.test.js b/test/model.test.js index 815a121482e..ce809f8f2ad 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5494,6 +5494,49 @@ describe('Model', function() { }); }); + it('bulkWrite casting updateMany, deleteOne, deleteMany (gh-3998)', function(done) { + var schema = new Schema({ + str: String, + num: Number + }); + + var M = db.model('gh3998_0', schema); + + var ops = [ + { + insertOne: { + document: { str: 1, num: '1' } + } + }, + { + insertOne: { + document: { str: '1', num: '1' } + } + }, + { + updateMany: { + filter: { str: 1 }, + update: { + $set: { num: '2' } + } + } + }, + { + deleteMany: { + filter: { str: 1 } + } + } + ]; + M.bulkWrite(ops, function(error) { + assert.ifError(error); + M.count({}, function(error, count) { + assert.ifError(error); + assert.equal(count, 0); + done(); + }); + }); + }); + it('marks array as modified when initializing non-array from db (gh-2442)', function(done) { var s1 = new Schema({ array: mongoose.Schema.Types.Mixed From 4c25637909807c4857ddf00ecd08be34c2d9c140 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Mar 2017 18:50:51 -0700 Subject: [PATCH 1309/2240] fix(model): correct handling of replaceOne Fix #3998 --- lib/model.js | 14 +++++++++----- test/model.test.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index aefafca9c90..e8dc748a7f4 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2090,15 +2090,19 @@ Model.bulkWrite = function(ops, options, callback) { try { op['replaceOne']['filter'] = cast(_this.schema, op['replaceOne']['filter']); - op['replaceOne']['update'] = castUpdate(_this.schema, op['replaceOne']['filter'], { - strict: _this.schema.options.strict, - overwrite: true - }); } catch (error) { return callback(error); } - callback(null); + // set `skipId`, otherwise we get "_id field cannot be changed" + op['replaceOne']['replacement'] = + new _this(op['replaceOne']['replacement'], null, true); + op['replaceOne']['replacement'].validate({ __noPromise: true }, function(error) { + if (error) { + return callback(error); + } + callback(null); + }); }; } else if (op['deleteOne']) { return function(callback) { diff --git a/test/model.test.js b/test/model.test.js index ce809f8f2ad..2193a9f792d 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5537,6 +5537,38 @@ describe('Model', function() { }); }); + it('bulkWrite casting replaceOne (gh-3998)', function(done) { + var schema = new Schema({ + str: String, + num: Number + }); + + var M = db.model('gh3998_1', schema); + + var ops = [ + { + insertOne: { + document: { str: 1, num: '1' } + } + }, + { + replaceOne: { + filter: { str: 1 }, + replacement: { str: 2, num: '2' } + } + } + ]; + M.bulkWrite(ops, function(error) { + assert.ifError(error); + M.findOne({}, function(error, doc) { + assert.ifError(error); + assert.strictEqual(doc.str, '2'); + assert.strictEqual(doc.num, 2); + done(); + }); + }); + }); + it('marks array as modified when initializing non-array from db (gh-2442)', function(done) { var s1 = new Schema({ array: mongoose.Schema.Types.Mixed From eb47842ee9efd5f46c35d4cefe1c66f7c800e8bb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Mar 2017 18:56:34 -0700 Subject: [PATCH 1310/2240] docs(model): add actual bulkWrite example re: #3998 --- lib/model.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index e8dc748a7f4..9dea2f956c0 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2023,8 +2023,25 @@ Model.insertMany = function(arr, options, callback) { * * ####Example: * - * var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }]; - * Movies.insertMany(arr, function(error, docs) {}); + * Character.bulkWrite([ + * { + * insertOne: { + * document: { name: 'Eddard Stark' } + * } + * }, + * { + * updateOne: { + * filter: { name: 'Eddard Stark' }, + * // Mongoose inserts `$set` for you in the update below + * update: { title: 'Hand of the King' } + * } + * }, + * { + * deleteOne: { + * { name: 'Eddard Stark' } + * } + * } + * ]).then(handleResult); * * @param {Array} ops * @param {Object} [options] From 06d85096a2e9709e233d494f30e94c098ad740c4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Mar 2017 18:58:00 -0700 Subject: [PATCH 1311/2240] docs: improve bulkWrite docs --- lib/model.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 9dea2f956c0..2fbb2c86de4 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2026,7 +2026,10 @@ Model.insertMany = function(arr, options, callback) { * Character.bulkWrite([ * { * insertOne: { - * document: { name: 'Eddard Stark' } + * document: { + * name: 'Eddard Stark', + * title: 'Warden of the North' + * } * } * }, * { From 165de1c93d0a0fbfa34f0ef5800b8f753c3d9379 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Mar 2017 19:23:59 -0700 Subject: [PATCH 1312/2240] test(populate): repro #5036 --- test/model.populate.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index eba26d8bf88..de83e485779 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4704,6 +4704,19 @@ describe('model: populate:', function() { catch(done); }); + it('handles populate with 0 args (gh-5036)', function(done) { + var userSchema = new Schema({ + name: String + }); + + var User = db.model('gh5036', userSchema); + + User.findOne().populate().exec(function(error) { + assert.ifError(error); + done(); + }); + }); + it('handles populating with discriminators that may not have a ref (gh-4817)', function(done) { var imagesSchema = new mongoose.Schema({ name: { From 03e1062e37df2bafbb438a9d5a8178dbd336ed7a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Mar 2017 19:24:14 -0700 Subject: [PATCH 1313/2240] fix(populate): handle passing no args to query.populate Fix #5036 --- lib/query.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/query.js b/lib/query.js index 8aa091ab98f..2a7c2e211c4 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2943,6 +2943,10 @@ function castDoc(query, overwrite) { */ Query.prototype.populate = function() { + if (arguments.length === 0) { + return this; + } + var res = utils.populate.apply(null, arguments); var opts = this._mongooseOptions; From 5c221529e7d3b46a223f60d1c64d47c63dcae9f6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 12 Mar 2017 12:33:14 -0600 Subject: [PATCH 1314/2240] chore: release 4.8.7 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 668945ba4a4..cfaa639f05a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.8.7 / 2017-03-12 +================== + * fix(model): if last arg in spread is falsy, treat it as a callback #5061 + * fix(document): use $hook instead of hook to enable 'hook' as a path name #5047 + * fix(populate): dont select foreign field if parent field is selected #5037 + * fix(populate): handle passing no args to query.populate #5036 + * fix(update): use correct method for casting nested arrays #5032 + * fix(discriminator): handle array discriminators when casting $push #5009 + 4.8.6 / 2017-03-05 ================== * docs(document): remove text that implies that transform is false by default #5023 diff --git a/package.json b/package.json index 23c290280f2..09d1148a714 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.7-pre", + "version": "4.8.7", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From cdaad77c49764bd383f6c34e0db022e9e25bbec3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 12 Mar 2017 12:34:58 -0600 Subject: [PATCH 1315/2240] chore: now working on 4.8.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 09d1148a714..1cf820cd5c7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.8.7", + "version": "4.8.8-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e43cdf1a056cf934771a679c89069fc2ca40763b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 13 Mar 2017 17:20:22 -0600 Subject: [PATCH 1316/2240] chore: release 4.9.0 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index cfaa639f05a..2ccad1af0e3 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.9.0 / 2017-03-13 +================== + * feat(document): return this from `depopulate()` #5027 + * fix(drivers): stop emitting timeouts as errors #5026 + * feat(schema): add a clone() function for schemas #4983 + * feat(query): add rawResult option to replace passRawResult, deprecate passRawResult #4977 #4925 + * feat(schematype): support isAsync validator option and handle returning promises from validators, deprecate implicit async validators #4290 + * feat(query): add `replaceOne()`, `deleteOne()`, `deleteMany()` #3998 + * feat(model): add `bulkWrite()` #3998 + 4.8.7 / 2017-03-12 ================== * fix(model): if last arg in spread is falsy, treat it as a callback #5061 diff --git a/package.json b/package.json index 9685bbf3718..38006fb1bc1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.0-pre", + "version": "4.9.0", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e2e105bfe25332d7bb7d708e525e941302426542 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 13 Mar 2017 17:22:02 -0600 Subject: [PATCH 1317/2240] chore: now working on 4.9.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38006fb1bc1..640500b429c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.0", + "version": "4.9.1-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From eb7fbc928ca6406271374499fffcd6d9c36a7429 Mon Sep 17 00:00:00 2001 From: Sjors Snoeren Date: Tue, 14 Mar 2017 14:28:36 +0100 Subject: [PATCH 1318/2240] InsertMany behaves as expected for validation errors while ordered option is disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit InsertMany already did use the ordered option for unique constraint errors but didn’t for validation errors. As expected insertMany should behave likewise for validation errors. --- lib/model.js | 22 ++++++++++++++++------ test/model.test.js | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/lib/model.js b/lib/model.js index f1808a42074..9cf228fc1de 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1976,6 +1976,12 @@ Model.insertMany = function(arr, options, callback) { doc = new _this(doc); doc.validate({ __noPromise: true }, function(error) { if (error) { + // Option `ordered` signals that insert should be continued after reaching + // a failing insert. Therefore we delegate "null", meaning the validation + // failed. It's up to the next function to filter out all failed models + if (options['ordered'] === false) { + return callback(null, null); + } return callback(error); } callback(null, doc); @@ -1988,7 +1994,11 @@ Model.insertMany = function(arr, options, callback) { callback && callback(error); return; } - var docObjects = docs.map(function(doc) { + // We filter all failed pre-validations by removing nulls + var docAttributes = docs.filter(function(doc) { + return doc != null; + }); + var docObjects = docAttributes.map(function(doc) { if (doc.schema.options.versionKey) { doc[doc.schema.options.versionKey] = 0; } @@ -2002,12 +2012,12 @@ Model.insertMany = function(arr, options, callback) { callback && callback(error); return; } - for (var i = 0; i < docs.length; ++i) { - docs[i].isNew = false; - docs[i].emit('isNew', false); - docs[i].constructor.emit('isNew', false); + for (var i = 0; i < docAttributes.length; ++i) { + docAttributes[i].isNew = false; + docAttributes[i].emit('isNew', false); + docAttributes[i].constructor.emit('isNew', false); } - callback && callback(null, docs); + callback && callback(null, docAttributes); }); }); }; diff --git a/test/model.test.js b/test/model.test.js index 2193a9f792d..7b70c7ba624 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5222,7 +5222,7 @@ describe('Model', function() { }); }); - it('insertMany() ordered option (gh-3893)', function(done) { + it('insertMany() ordered option for constraint errors (gh-3893)', function(done) { start.mongodVersion(function(err, version) { if (err) { done(err); @@ -5264,6 +5264,45 @@ describe('Model', function() { } }); + it('insertMany() ordered option for validation errors (gh-5068)', function(done) { + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + done(); + return; + } + + test(); + }); + + function test() { + var schema = new Schema({ + name: { type: String, required: true } + }); + var Movie = db.model('gh5068', schema); + + var arr = [ + { name: 'Star Wars' }, + { foo: 'Star Wars' }, + { name: 'The Empire Strikes Back' } + ]; + Movie.insertMany(arr, { ordered: false }, function(error) { + assert.ifError(error); + Movie.find({}).sort({ name: 1 }).exec(function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 2); + assert.equal(docs[0].name, 'Star Wars'); + assert.equal(docs[1].name, 'The Empire Strikes Back'); + done(); + }); + }); + } + }); + it('insertMany() hooks (gh-3846)', function(done) { var schema = new Schema({ name: String From f4f9d0314acd7692aaf7f0f2650e9f537ce958a9 Mon Sep 17 00:00:00 2001 From: Sjors Snoeren Date: Tue, 14 Mar 2017 14:55:21 +0100 Subject: [PATCH 1319/2240] InsertMany now handles missing or malformed options object well --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 9cf228fc1de..ac874ff606c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1979,7 +1979,7 @@ Model.insertMany = function(arr, options, callback) { // Option `ordered` signals that insert should be continued after reaching // a failing insert. Therefore we delegate "null", meaning the validation // failed. It's up to the next function to filter out all failed models - if (options['ordered'] === false) { + if (options != null && typeof options === 'object' && options['ordered'] === false) { return callback(null, null); } return callback(error); From be89c60e295e8e30573a71b5d04562ab147c08ab Mon Sep 17 00:00:00 2001 From: Sjors Snoeren Date: Tue, 14 Mar 2017 15:13:12 +0100 Subject: [PATCH 1320/2240] InsertMany returns an empty array when all models are invalid --- lib/model.js | 5 +++++ test/model.test.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/lib/model.js b/lib/model.js index ac874ff606c..ede856bb1a8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1998,6 +1998,11 @@ Model.insertMany = function(arr, options, callback) { var docAttributes = docs.filter(function(doc) { return doc != null; }); + // Quickly escape while there aren't any valid docAttributes + if (docAttributes.length < 1) { + callback && callback(null, []); + return; + } var docObjects = docAttributes.map(function(doc) { if (doc.schema.options.versionKey) { doc[doc.schema.options.versionKey] = 0; diff --git a/test/model.test.js b/test/model.test.js index 7b70c7ba624..a0bd7eb49b9 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5303,6 +5303,41 @@ describe('Model', function() { } }); + it('insertMany() ordered option for single validation error', function(done) { + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + done(); + return; + } + + test(); + }); + + function test() { + var schema = new Schema({ + name: { type: String, required: true } + }); + var Movie = db.model('gh5068-2', schema); + + var arr = [ + { foo: 'Star Wars' }, + { foo: 'The Fast and the Furious' }, + ]; + Movie.insertMany(arr, { ordered: false }, function(error) { + assert.ifError(error); + Movie.find({}).sort({ name: 1 }).exec(function(error, docs) { + assert.equal(docs.length, 0); + done(); + }); + }); + } + }); + it('insertMany() hooks (gh-3846)', function(done) { var schema = new Schema({ name: String From d2eaff0f86c9ac8710850b575cc380e7e6a9ead5 Mon Sep 17 00:00:00 2001 From: Sjors Snoeren Date: Tue, 14 Mar 2017 15:15:15 +0100 Subject: [PATCH 1321/2240] Removes unused trailing comma in insertMany tests --- test/model.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.test.js b/test/model.test.js index a0bd7eb49b9..872a1865378 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5326,7 +5326,7 @@ describe('Model', function() { var arr = [ { foo: 'Star Wars' }, - { foo: 'The Fast and the Furious' }, + { foo: 'The Fast and the Furious' } ]; Movie.insertMany(arr, { ordered: false }, function(error) { assert.ifError(error); From 1d131f936eafe8c7a45690006ae52c7d21d5c96c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 14 Mar 2017 09:29:38 -0600 Subject: [PATCH 1322/2240] test(timestamps): repro #5045 --- test/model.update.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index ae01aae116f..6b58d4f6117 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2398,6 +2398,27 @@ describe('model: update:', function() { }); }); + it('findOneAndUpdate with timestamps (gh-5045)', function(done) { + var schema = new Schema({ + username: String, + isDeleted: Boolean + }, { timestamps: true }); + var User = db.model('gh5045', schema); + + User.findOneAndUpdate( + { username: 'test', isDeleted: false }, + { createdAt: '2017-03-06T14:08:59+00:00' }, + { new: true, setDefaultsOnInsert: true, upsert: true }, + function(error) { + assert.ifError(error); + User.updateOne({ username: 'test' }, { createdAt: new Date() }). + exec(function(error) { + assert.ifError(error); + done(); + }); + }); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From 113ad7d434c7eb217374f5ae866331fa2c369db0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 14 Mar 2017 09:31:01 -0600 Subject: [PATCH 1323/2240] fix(timestamps): dont set timestamps in update if user set it Fix #5045 --- lib/schema.js | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 5ae163db9da..58d1f2e85ce 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -842,17 +842,32 @@ Schema.prototype.setupTimestamp = function(timestamps) { next(); }); - var genUpdates = function(overwrite) { + var genUpdates = function(currentUpdate, overwrite) { var now = new Date(); var updates = {}; if (overwrite) { - updates[updatedAt] = now; - updates[createdAt] = now; + if (!currentUpdate[updatedAt]) { + updates[updatedAt] = now; + } + if (!currentUpdate[createdAt]) { + updates[createdAt] = now; + } return updates; } updates = { $set: {}, $setOnInsert: {} }; - updates.$set[updatedAt] = now; - updates.$setOnInsert[createdAt] = now; + currentUpdate = currentUpdate || {}; + currentUpdate.$set = currentUpdate.$set || {}; + currentUpdate.$setOnInsert = currentUpdate.$setOnInsert || {}; + if (!currentUpdate[updatedAt] && + !currentUpdate.$set[updatedAt] && + !currentUpdate.$setOnInsert[updatedAt]) { + updates.$set[updatedAt] = now; + } + if (!currentUpdate[createdAt] && + !currentUpdate.$set[createdAt] && + !currentUpdate.$setOnInsert[createdAt]) { + updates.$setOnInsert[createdAt] = now; + } return updates; }; @@ -869,14 +884,18 @@ Schema.prototype.setupTimestamp = function(timestamps) { this.pre('findOneAndUpdate', function(next) { var overwrite = this.options.overwrite; - this.findOneAndUpdate({}, genUpdates(overwrite), { overwrite: overwrite }); + this.findOneAndUpdate({}, genUpdates(this.getUpdate(), overwrite), { + overwrite: overwrite + }); applyTimestampsToChildren(this); next(); }); this.pre('update', function(next) { var overwrite = this.options.overwrite; - this.update({}, genUpdates(overwrite), { overwrite: overwrite }); + this.update({}, genUpdates(this.getUpdate(), overwrite), { + overwrite: overwrite + }); applyTimestampsToChildren(this); next(); }); From 606fc049431daa27d33ed8a5316ab0081819108f Mon Sep 17 00:00:00 2001 From: Bertolo Date: Wed, 15 Mar 2017 10:58:07 +0000 Subject: [PATCH 1324/2240] Update description said "documents" instead of "one document" --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index f1808a42074..2e5216a29f6 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2197,7 +2197,7 @@ Model.hydrate = function(obj) { }; /** - * Updates documents in the database without returning them. + * Updates one document in the database without returning it. * * ####Examples: * From 9105d8518c6a3f7bd8c052ce57795f140421b2f3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 15 Mar 2017 10:30:42 -0600 Subject: [PATCH 1325/2240] test(update): repro #5041 --- test/model.update.test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 6b58d4f6117..b801450f2e4 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2419,6 +2419,34 @@ describe('model: update:', function() { }); }); + it('doesnt double-call setters when updating an array (gh-5041)', function(done) { + var called = 0; + var UserSchema = new Schema({ + name: String, + foos: [{ + _id: false, + foo: { + type: Number, + get: function(val) { + return val.toString(); + }, + set: function(val) { + ++called; + return val; + } + } + }] + }); + + var User = db.model('gh5041', UserSchema); + + User.findOneAndUpdate({}, { foos: [ {foo: '13.57'} ] }, function(error) { + assert.ifError(error); + assert.equal(called, 1); + done(); + }); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From 0a8808547f9b04d38604337ed0b23b8779022aba Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 15 Mar 2017 10:31:45 -0600 Subject: [PATCH 1326/2240] fix(update): dont double-call setters on arrays Fix #5041 --- lib/services/query/castUpdate.js | 1 + test/model.update.test.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index 6a0a80993fb..e0176c27254 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -267,6 +267,7 @@ function castUpdateVal(schema, val, op, $conditional) { } else { val = tmp; } + return val; } if (op in numberOps) { diff --git a/test/model.update.test.js b/test/model.update.test.js index b801450f2e4..d9297e269c8 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2440,7 +2440,7 @@ describe('model: update:', function() { var User = db.model('gh5041', UserSchema); - User.findOneAndUpdate({}, { foos: [ {foo: '13.57'} ] }, function(error) { + User.findOneAndUpdate({}, { foos: [{ foo: '13.57' }] }, function(error) { assert.ifError(error); assert.equal(called, 1); done(); From 80b325c8e9935393cb23d38e3bc1be72a82241c3 Mon Sep 17 00:00:00 2001 From: Andreas Zoellner Date: Wed, 15 Mar 2017 11:22:31 -0700 Subject: [PATCH 1327/2240] fix(query): handle $type for arrays Fix #5079 --- lib/schema/array.js | 2 ++ lib/schema/operators/type.js | 13 +++++++++++++ lib/schematype.js | 9 ++------- 3 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 lib/schema/operators/type.js diff --git a/lib/schema/array.js b/lib/schema/array.js index b5833620072..dad5cf3b5d9 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -3,6 +3,7 @@ */ var $exists = require('./operators/exists'); +var $type = require('./operators/type'); var SchemaType = require('../schematype'); var CastError = SchemaType.CastError; var Types = { @@ -319,6 +320,7 @@ handle.$minDistance = handle.$maxDistance = castToNumber; handle.$exists = $exists; +handle.$type = $type; handle.$eq = handle.$gt = diff --git a/lib/schema/operators/type.js b/lib/schema/operators/type.js new file mode 100644 index 00000000000..c8e391ac2ae --- /dev/null +++ b/lib/schema/operators/type.js @@ -0,0 +1,13 @@ +'use strict'; + +/*! + * ignore + */ + +module.exports = function(val) { + if (typeof val !== 'number' && typeof val !== 'string') { + throw new Error('$type parameter must be number or string'); + } + + return val; +}; diff --git a/lib/schematype.js b/lib/schematype.js index 146c063f63b..b19ac365289 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -3,6 +3,7 @@ */ var $exists = require('./schema/operators/exists'); +var $type = require('./schema/operators/type'); var utils = require('./utils'); var MongooseError = require('./error'); var CastError = MongooseError.CastError; @@ -922,13 +923,7 @@ SchemaType.prototype.$conditionalHandlers = { $ne: handleSingle, $nin: handleArray, $exists: $exists, - $type: function(val) { - if (typeof val !== 'number' && typeof val !== 'string') { - throw new Error('$type parameter must be number or string'); - } - - return val; - } + $type: $type }; /** From dd3182fc2bc6fd3ac5cbd787793bfdf6d91a97d4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 16 Mar 2017 22:40:38 -0600 Subject: [PATCH 1328/2240] docs(validation): add some more detail re: isAsync --- test/docs/validation.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 9565e383a9d..194b4810df6 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -151,7 +151,9 @@ describe('validation docs', function() { * Even if you don't want to use asynchronous validators, be careful, * because mongoose 4 will assume that **all** functions that take 2 * arguments are asynchronous, like the - * [`validator.isEmail` function](https://www.npmjs.com/package/validator) + * [`validator.isEmail` function](https://www.npmjs.com/package/validator). + * This behavior is considered deprecated as of 4.9.0, and you can shut + * it off by specifying `isAsync: false` on your custom validator. */ it('Async Custom Validators', function(done) { var userSchema = new Schema({ From 4efe0dc95bb0ed55677da96714bb3a10f39502de Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 16 Mar 2017 22:46:51 -0600 Subject: [PATCH 1329/2240] test(timestamps): repro #5051 --- test/document.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 1e3ff2683b5..126bc00b53c 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3652,6 +3652,27 @@ describe('document', function() { done(); }); + it('timestamps with nested paths (gh-5051)', function(done) { + var schema = new Schema({ props: Object }, { + timestamps: { + createdAt: 'props.createdAt', + updatedAt: 'props.updatedAt' + } + }); + + var M = db.model('gh5051', schema); + var now = Date.now(); + M.create({}, function(error, doc) { + assert.ok(doc.props.createdAt); + assert.ok(doc.props.createdAt instanceof Date); + assert.ok(doc.props.createdAt.valueOf() >= now); + assert.ok(doc.props.updatedAt); + assert.ok(doc.props.updatedAt instanceof Date); + assert.ok(doc.props.updatedAt.valueOf() >= now); + done(); + }); + }); + it('supports $where in pre save hook (gh-4004)', function(done) { var Promise = global.Promise; From 1a5fffb214068da3c4bd1e416b520dadf86ad4fb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 16 Mar 2017 22:47:28 -0600 Subject: [PATCH 1330/2240] fix(timestamps): handle nested timestamp paths Fix #5051 --- lib/schema.js | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 58d1f2e85ce..32b14509560 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -819,10 +819,21 @@ Schema.prototype.setupTimestamp = function(timestamps) { var updatedAt = timestamps.updatedAt || 'updatedAt'; var schemaAdditions = {}; - schemaAdditions[updatedAt] = Date; + var parts = createdAt.split('.'); + var i; + var cur = schemaAdditions; + for (i = 0; i < parts.length; ++i) { + cur[parts[i]] = (i < parts.length - 1 ? + cur[parts[i]] || {} : + Date); + } - if (!this.paths[createdAt]) { - schemaAdditions[createdAt] = Date; + parts = updatedAt.split('.'); + cur = schemaAdditions; + for (i = 0; i < parts.length; ++i) { + cur[parts[i]] = (i < parts.length - 1 ? + cur[parts[i]] || {} : + Date); } this.add(schemaAdditions); @@ -831,12 +842,12 @@ Schema.prototype.setupTimestamp = function(timestamps) { var defaultTimestamp = new Date(); var auto_id = this._id && this._id.auto; - if (!this[createdAt] && this.isSelected(createdAt)) { - this[createdAt] = auto_id ? this._id.getTimestamp() : defaultTimestamp; + if (!this.get(createdAt) && this.isSelected(createdAt)) { + this.set(createdAt, auto_id ? this._id.getTimestamp() : defaultTimestamp); } if (this.isNew || this.isModified()) { - this[updatedAt] = this.isNew ? this[createdAt] : defaultTimestamp; + this.set(updatedAt, this.isNew ? this.get(createdAt) : defaultTimestamp); } next(); @@ -873,11 +884,11 @@ Schema.prototype.setupTimestamp = function(timestamps) { }; this.methods.initializeTimestamps = function() { - if (!this[createdAt]) { - this[createdAt] = new Date(); + if (!this.get(createdAt)) { + this.set(createdAt, new Date()); } - if (!this[updatedAt]) { - this[updatedAt] = new Date(); + if (!this.get(updatedAt)) { + this.set(updatedAt, new Date()); } return this; }; From 2a0df9a2311b8d197a85f0cbc319b6171effc0d1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Mar 2017 16:15:17 -0600 Subject: [PATCH 1331/2240] fix(connection): make connect return value consistent Fix #5006 --- lib/connection.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index ec7e1e61ba9..1cd17c4e44b 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -222,7 +222,9 @@ Connection.prototype.open = function(host, database, port, options, callback) { parsed = muri(host); } catch (err) { this.error(err, callback); - return this; + return new Promise.ES6(function(resolve, reject) { + reject(err); + }); } database = parsed.db; From 7d6c2594af889e6e2a47e8ae2c217171af778bf1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Mar 2017 16:24:32 -0600 Subject: [PATCH 1332/2240] test: add coverage for #5070 --- test/model.discriminator.test.js | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index cb49ca32840..e8b6704c620 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -543,6 +543,57 @@ describe('model', function() { catch(done); }); + it('embedded discriminators with $push + $each (gh-5070)', function(done) { + var eventSchema = new Schema({ message: String }, + { discriminatorKey: 'kind', _id: false }); + var batchSchema = new Schema({ events: [eventSchema] }); + var docArray = batchSchema.path('events'); + + var Clicked = docArray.discriminator('Clicked', new Schema({ + element: { + type: String, + required: true + } + }, { _id: false })); + + var Purchased = docArray.discriminator('Purchased', new Schema({ + product: { + type: String, + required: true + } + }, { _id: false })); + + var Batch = db.model('gh5070', batchSchema); + + var batch = { + events: [ + { kind: 'Clicked', element: '#hero' } + ] + }; + + Batch.create(batch). + then(function(doc) { + assert.equal(doc.events.length, 1); + return Batch.updateOne({ _id: doc._id }, { + $push: { + events: { $each: [{ kind: 'Clicked', element: '#button' }] } + } + }).then(function() { + return doc; + }); + }). + then(function(doc) { + return Batch.findOne({ _id: doc._id }); + }). + then(function(doc) { + assert.equal(doc.events.length, 2); + assert.equal(doc.events[1].element, '#button'); + assert.equal(doc.events[1].kind, 'Clicked'); + done(); + }). + catch(done); + }); + it('embedded in document arrays (gh-2723)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From fa2caf50a9c7c95a16e11f2aa95fa516b28cbce2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Mar 2017 16:54:10 -0600 Subject: [PATCH 1333/2240] fix(model): get promise each time save() is called rather than once Fix #5030 --- lib/services/model/applyHooks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index bf97f1bfed9..f07d49fb056 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -13,8 +13,6 @@ module.exports = applyHooks; */ function applyHooks(model, schema) { - var Promise = PromiseProvider.get(); - var q = schema && schema.callQueue; var toWrapEl; var len; @@ -102,6 +100,8 @@ function applyHooks(model, schema) { } model.prototype[pointCut] = (function(_newName) { return function wrappedPointCut() { + var Promise = PromiseProvider.get(); + var _this = this; var args = [].slice.call(arguments); var lastArg = args.pop(); From 79bf54af910a4a10901af115e7706cda9f7eef7a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Mar 2017 10:21:41 -0600 Subject: [PATCH 1334/2240] fix: upgrade driver -> 2.2.25 Fix #5033 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 640500b429c..ade7f7f65fc 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "2.0.0", "kareem": "1.2.1", - "mongodb": "2.2.24", + "mongodb": "2.2.25", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.3.0", From dae6192ccc7dc26219e1270ce664adc0ab26e3d9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Mar 2017 16:13:24 -0600 Subject: [PATCH 1335/2240] test: fix flakey test --- test/aggregate.test.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 9a46b926a65..8bcadf83aa6 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -679,8 +679,11 @@ describe('aggregate: ', function() { assert.equal(lowest.employeeHierarchy.length, 3); // First result in array is max depth result - assert.equal(lowest.employeeHierarchy[0].name, 'Alice'); - assert.equal(lowest.employeeHierarchy[2].name, 'Carol'); + var names = lowest.employeeHierarchy.map(function(doc) { + return doc.name; + }).sort(); + assert.equal(names[0], 'Alice'); + assert.equal(names[2], 'Carol'); done(); }); } From 249653b4d1431fc6c1fdd70f5ef50ec4a63bd8eb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Mar 2017 16:19:45 -0600 Subject: [PATCH 1336/2240] fix(populate): avoid duplicate ids in dynref queries Fix #5054 --- lib/model.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index ede856bb1a8..6ea5c2e75b0 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3107,7 +3107,7 @@ function populate(model, docs, options, callback) { assignVals({ originalModel: model, - rawIds: mod.ids, + rawIds: mod.allIds, localField: mod.localField, foreignField: mod.foreignField, rawDocs: rawDocs, @@ -3351,6 +3351,8 @@ function getModelsMapForPopulate(model, docs, options) { var k = modelNames.length; while (k--) { modelName = modelNames[k]; + var _doc = Array.isArray(doc) && refPath ? doc[k] : doc; + var _ret = Array.isArray(ret) && refPath ? ret[k] : ret; Model = originalOptions.model && originalOptions.model.modelName ? originalOptions.model : model.db.model(modelName); @@ -3374,8 +3376,9 @@ function getModelsMapForPopulate(model, docs, options) { available[modelName] = { Model: Model, options: currentOptions, - docs: [doc], - ids: [ret], + docs: [_doc], + ids: [_ret], + allIds: [ret], // Assume only 1 localField + foreignField localField: localField, foreignField: foreignField, @@ -3384,8 +3387,9 @@ function getModelsMapForPopulate(model, docs, options) { }; map.push(available[modelName]); } else { - available[modelName].docs.push(doc); - available[modelName].ids.push(ret); + available[modelName].docs.push(_doc); + available[modelName].ids.push(_ret); + available[modelName].allIds.push(ret); } } } From 8b50983231ed386f65852a1a87fcc21fa7ec2bba Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Mar 2017 21:06:50 -0600 Subject: [PATCH 1337/2240] fix(update): more complete handling for overwrite option Re: #3556 --- lib/query.js | 10 +++++++++- lib/services/query/hasDollarKeys.js | 12 ++++++++++++ test/model.update.test.js | 21 +++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 lib/services/query/hasDollarKeys.js diff --git a/lib/query.js b/lib/query.js index 2578c42bb63..684e822eaa8 100644 --- a/lib/query.js +++ b/lib/query.js @@ -7,6 +7,7 @@ var QueryCursor = require('./querycursor'); var QueryStream = require('./querystream'); var cast = require('./cast'); var castUpdate = require('./services/query/castUpdate'); +var hasDollarKeys = require('./services/query/hasDollarKeys'); var helpers = require('./queryhelpers'); var mquery = require('mquery'); var readPref = require('./drivers').ReadPreference; @@ -2177,7 +2178,14 @@ Query.prototype._execUpdate = function(callback) { if (this.options.runValidators) { _this = this; - doValidate = updateValidators(this, schema, castedDoc, options); + if (this.options.overwrite && !hasDollarKeys(castedDoc)) { + castedDoc = new _this.model(castedDoc, null, true); + doValidate = function(callback) { + castedDoc.validate(callback); + }; + } else { + doValidate = updateValidators(this, schema, castedDoc, options); + } var _callback = function(err) { if (err) { return callback(err); diff --git a/lib/services/query/hasDollarKeys.js b/lib/services/query/hasDollarKeys.js new file mode 100644 index 00000000000..2917a847ba6 --- /dev/null +++ b/lib/services/query/hasDollarKeys.js @@ -0,0 +1,12 @@ +'use strict'; + +module.exports = function(obj) { + var keys = Object.keys(obj); + var len = keys.length; + for (var i = 0; i < len; ++i) { + if (keys[i].charAt(0) === '$') { + return true; + } + } + return false; +}; diff --git a/test/model.update.test.js b/test/model.update.test.js index d9297e269c8..55a054ac17b 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2447,6 +2447,27 @@ describe('model: update:', function() { }); }); + it('overwrite doc with update validators (gh-3556)', function(done) { + var testSchema = new Schema({ + name: { + type: String, + required: true + }, + otherName: String + }); + var Test = db.model('gh3556', testSchema); + + var opts = { overwrite: true, runValidators: true }; + Test.update({}, { otherName: 'test' }, opts, function(error) { + assert.ok(error); + assert.ok(error.errors['name']); + Test.update({}, { $set: { otherName: 'test' } }, opts, function(error) { + assert.ifError(error); + done(); + }); + }); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From 8a7c67d06f52ef45bfc96ded77f9900209ba5f37 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Mar 2017 21:11:02 -0600 Subject: [PATCH 1338/2240] fix(query): handle overwrite findOneAndUpdate validation --- lib/query.js | 47 +++++++++++++++++------------ test/model.findOneAndUpdate.test.js | 21 +++++++++++++ 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/lib/query.js b/lib/query.js index 684e822eaa8..15c8540ab84 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1998,29 +1998,36 @@ Query.prototype._findAndModify = function(type, callback) { opts.remove = false; } - castedDoc = castDoc(this, opts.overwrite); - castedDoc = setDefaultsOnInsert(this, schema, castedDoc, opts); - if (!castedDoc) { - if (opts.upsert) { - // still need to do the upsert to empty doc - var doc = utils.clone(castedQuery); - delete doc._id; - castedDoc = {$set: doc}; - } else { - return this.findOne(callback); - } - } else if (castedDoc instanceof Error) { - return callback(castedDoc); + if (opts.overwrite && !hasDollarKeys(this._update)) { + castedDoc = new model(this._update, null, true); + doValidate = function(callback) { + castedDoc.validate(callback); + }; } else { - // In order to make MongoDB 2.6 happy (see - // https://jira.mongodb.org/browse/SERVER-12266 and related issues) - // if we have an actual update document but $set is empty, junk the $set. - if (castedDoc.$set && Object.keys(castedDoc.$set).length === 0) { - delete castedDoc.$set; + castedDoc = castDoc(this, opts.overwrite); + castedDoc = setDefaultsOnInsert(this, schema, castedDoc, opts); + if (!castedDoc) { + if (opts.upsert) { + // still need to do the upsert to empty doc + var doc = utils.clone(castedQuery); + delete doc._id; + castedDoc = {$set: doc}; + } else { + return this.findOne(callback); + } + } else if (castedDoc instanceof Error) { + return callback(castedDoc); + } else { + // In order to make MongoDB 2.6 happy (see + // https://jira.mongodb.org/browse/SERVER-12266 and related issues) + // if we have an actual update document but $set is empty, junk the $set. + if (castedDoc.$set && Object.keys(castedDoc.$set).length === 0) { + delete castedDoc.$set; + } } - } - doValidate = updateValidators(this, schema, castedDoc, opts); + doValidate = updateValidators(this, schema, castedDoc, opts); + } } this._applyPaths(); diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 294f9b3c6c6..96a0f5ffa11 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1809,6 +1809,27 @@ describe('model: findByIdAndUpdate:', function() { }); }); + it('overwrite doc with update validators (gh-3556)', function(done) { + var testSchema = new Schema({ + name: { + type: String, + required: true + }, + otherName: String + }); + var Test = db.model('gh3556', testSchema); + + var opts = { overwrite: true, runValidators: true }; + Test.findOneAndUpdate({}, { otherName: 'test' }, opts, function(error) { + assert.ok(error); + assert.ok(error.errors['name']); + Test.findOneAndUpdate({}, { $set: { otherName: 'test' } }, opts, function(error) { + assert.ifError(error); + done(); + }); + }); + }); + it('properly handles casting nested objects in update (gh-4724)', function(done) { var locationSchema = new Schema({ _id: false, From 90d9da7344fcc3109a74177bbdf09831efc57fa9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Mar 2017 11:13:50 -0600 Subject: [PATCH 1339/2240] chore: now working on 4.10.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ade7f7f65fc..c9f426ef322 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.1-pre", + "version": "4.10.0-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4f864cf5a8dbb843883a2c097b69038149938718 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Mar 2017 11:22:37 -0600 Subject: [PATCH 1340/2240] chore: release 4.9.1 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2ccad1af0e3..bc4228c70eb 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,14 @@ +4.9.1 / 2017-03-19 +================== + * fix(query): handle $type for arrays #5080 #5079 [zoellner](https://github.com/zoellner) + * fix(model): handle ordered param for `insertMany` validation errors #5072 [sjorssnoeren](https://github.com/sjorssnoeren) + * fix(populate): avoid duplicate ids in dynref queries #5054 + * fix(timestamps): dont set timestamps in update if user set it #5045 + * fix(update): dont double-call setters on arrays #5041 + * fix: upgrade driver -> 2.2.25 for jest fix #5033 + * fix(model): get promise each time save() is called rather than once #5030 + * fix(connection): make connect return value consistent #5006 + 4.9.0 / 2017-03-13 ================== * feat(document): return this from `depopulate()` #5027 diff --git a/package.json b/package.json index ade7f7f65fc..174409da98c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.1-pre", + "version": "4.9.1", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4abf0af175b275645d77f25e13bf231b3412d733 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Mar 2017 11:24:26 -0600 Subject: [PATCH 1341/2240] chore: now working on 4.9.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 174409da98c..64480c7d5d2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.1", + "version": "4.9.2-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From da870ed5ee5d950bee31ed0fd78064adc00cb8f4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Mar 2017 15:24:31 -0600 Subject: [PATCH 1342/2240] refactor(querycursor,aggregate): move eachAsync into helper Re: #4244 --- lib/aggregate.js | 44 +-------------------- lib/querycursor.js | 44 +-------------------- lib/services/cursor/eachAsync.js | 65 ++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 84 deletions(-) create mode 100644 lib/services/cursor/eachAsync.js diff --git a/lib/aggregate.js b/lib/aggregate.js index 8bb126b5b5f..acd1f814630 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -6,6 +6,7 @@ var util = require('util'); var utils = require('./utils'); var PromiseProvider = require('./promise_provider'); var Query = require('./query'); +var eachAsync = require('./services/cursor/eachAsync'); var read = Query.prototype.read; /** @@ -675,48 +676,7 @@ Aggregate.prototype.exec = function(callback) { function decorateCursor(cursor) { cursor.eachAsync = function(fn, callback) { - var Promise = PromiseProvider.get(); - - var handleNextResult = function(doc, callback) { - var promise = fn(doc); - if (promise && typeof promise.then === 'function') { - promise.then( - function() { callback(null); }, - function(error) { callback(error); }); - } else { - callback(null); - } - }; - - var iterate = function(callback) { - return cursor.next(function(error, doc) { - if (error) { - return callback(error); - } - if (!doc) { - return callback(null); - } - handleNextResult(doc, function(error) { - if (error) { - return callback(error); - } - setTimeout(function() { - iterate(callback); - }, 0); - }); - }); - }; - - return new Promise.ES6(function(resolve, reject) { - iterate(function(error) { - if (error) { - callback && callback(error); - return reject(error); - } - callback && callback(null); - return resolve(); - }); - }); + return eachAsync(function(cb) { return cursor.next(cb); }, fn, callback); }; } diff --git a/lib/querycursor.js b/lib/querycursor.js index 7b4933516bb..2a11f179787 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -4,6 +4,7 @@ var PromiseProvider = require('./promise_provider'); var Readable = require('stream').Readable; +var eachAsync = require('./services/cursor/eachAsync'); var helpers = require('./queryhelpers'); var util = require('util'); @@ -190,50 +191,9 @@ QueryCursor.prototype.next = function(callback) { */ QueryCursor.prototype.eachAsync = function(fn, callback) { - var Promise = PromiseProvider.get(); var _this = this; - var handleNextResult = function(doc, callback) { - var promise = fn(doc); - if (promise && typeof promise.then === 'function') { - promise.then( - function() { callback(null); }, - function(error) { callback(error); }); - } else { - callback(null); - } - }; - - var iterate = function(callback) { - return _next(_this, function(error, doc) { - if (error) { - return callback(error); - } - if (!doc) { - return callback(null); - } - handleNextResult(doc, function(error) { - if (error) { - return callback(error); - } - // Make sure to clear the stack re: gh-4697 - setTimeout(function() { - iterate(callback); - }, 0); - }); - }); - }; - - return new Promise.ES6(function(resolve, reject) { - iterate(function(error) { - if (error) { - callback && callback(error); - return reject(error); - } - callback && callback(null); - return resolve(); - }); - }); + return eachAsync(function(cb) { return _next(_this, cb); }, fn, callback); }; /*! diff --git a/lib/services/cursor/eachAsync.js b/lib/services/cursor/eachAsync.js new file mode 100644 index 00000000000..21ec03e7bf8 --- /dev/null +++ b/lib/services/cursor/eachAsync.js @@ -0,0 +1,65 @@ +'use strict'; + +/*! + * Module dependencies. + */ + +var PromiseProvider = require('../../promise_provider'); + +/** + * Execute `fn` for every document in the cursor. If `fn` returns a promise, + * will wait for the promise to resolve before iterating on to the next one. + * Returns a promise that resolves when done. + * + * @param {Function} fn + * @param {Function} [callback] executed when all docs have been processed + * @return {Promise} + * @api public + * @method eachAsync + */ + +module.exports = function eachAsync(next, fn, callback) { + var Promise = PromiseProvider.get(); + + var handleNextResult = function(doc, callback) { + var promise = fn(doc); + if (promise && typeof promise.then === 'function') { + promise.then( + function() { callback(null); }, + function(error) { callback(error); }); + } else { + callback(null); + } + }; + + var iterate = function(callback) { + return next(function(error, doc) { + if (error) { + return callback(error); + } + if (!doc) { + return callback(null); + } + handleNextResult(doc, function(error) { + if (error) { + return callback(error); + } + // Make sure to clear the stack re: gh-4697 + setTimeout(function() { + iterate(callback); + }, 0); + }); + }); + }; + + return new Promise.ES6(function(resolve, reject) { + iterate(function(error) { + if (error) { + callback && callback(error); + return reject(error); + } + callback && callback(null); + return resolve(); + }); + }); +}; From c78cc84d98983958871222cb115be5c0c27acc65 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Mar 2017 15:48:36 -0600 Subject: [PATCH 1343/2240] feat(cursor): add parallel option to eachAsync Fix #4244 --- lib/aggregate.js | 10 ++++-- lib/querycursor.js | 11 ++++-- lib/services/cursor/eachAsync.js | 58 +++++++++++++++++++++++++------- test/query.cursor.test.js | 25 ++++++++++++++ 4 files changed, 87 insertions(+), 17 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index acd1f814630..d006f10a268 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -675,8 +675,14 @@ Aggregate.prototype.exec = function(callback) { */ function decorateCursor(cursor) { - cursor.eachAsync = function(fn, callback) { - return eachAsync(function(cb) { return cursor.next(cb); }, fn, callback); + cursor.eachAsync = function(fn, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + opts = opts || {}; + + return eachAsync(function(cb) { return cursor.next(cb); }, fn, opts, callback); }; } diff --git a/lib/querycursor.js b/lib/querycursor.js index 2a11f179787..ce930233fea 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -184,16 +184,23 @@ QueryCursor.prototype.next = function(callback) { * Returns a promise that resolves when done. * * @param {Function} fn + * @param {Object} [options] + * @param {Number} [options.parallel] the number of promises to execute in parallel. Defaults to 1. * @param {Function} [callback] executed when all docs have been processed * @return {Promise} * @api public * @method eachAsync */ -QueryCursor.prototype.eachAsync = function(fn, callback) { +QueryCursor.prototype.eachAsync = function(fn, opts, callback) { var _this = this; + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + opts = opts || {}; - return eachAsync(function(cb) { return _next(_this, cb); }, fn, callback); + return eachAsync(function(cb) { return _next(_this, cb); }, fn, opts, callback); }; /*! diff --git a/lib/services/cursor/eachAsync.js b/lib/services/cursor/eachAsync.js index 21ec03e7bf8..9b1b8b6d500 100644 --- a/lib/services/cursor/eachAsync.js +++ b/lib/services/cursor/eachAsync.js @@ -5,21 +5,25 @@ */ var PromiseProvider = require('../../promise_provider'); +var async = require('async'); /** * Execute `fn` for every document in the cursor. If `fn` returns a promise, * will wait for the promise to resolve before iterating on to the next one. * Returns a promise that resolves when done. * + * @param {Function} next the thunk to call to get the next document * @param {Function} fn + * @param {Object} options * @param {Function} [callback] executed when all docs have been processed * @return {Promise} * @api public * @method eachAsync */ -module.exports = function eachAsync(next, fn, callback) { +module.exports = function eachAsync(next, fn, options, callback) { var Promise = PromiseProvider.get(); + var parallel = options.parallel || 1; var handleNextResult = function(doc, callback) { var promise = fn(doc); @@ -33,23 +37,51 @@ module.exports = function eachAsync(next, fn, callback) { }; var iterate = function(callback) { - return next(function(error, doc) { - if (error) { - return callback(error); - } - if (!doc) { - return callback(null); + if (parallel > 1) { + var tasks = []; + for (var i = 0; i < parallel; ++i) { + tasks.push(next); } - handleNextResult(doc, function(error) { + async.parallel(tasks, function(error, docs) { + var initialLength = docs.length; + docs = docs.filter(function(doc) { + return doc != null; + }); + var isDone = docs.length !== initialLength; + var tasks = docs.map(function(doc) { + return function(cb) { handleNextResult(doc, cb); }; + }); + async.parallel(tasks, function(error) { + if (error) { + return callback(error); + } + if (isDone) { + return callback(null); + } + setTimeout(function() { + iterate(callback); + }); + }); + }); + } else { + return next(function(error, doc) { if (error) { return callback(error); } - // Make sure to clear the stack re: gh-4697 - setTimeout(function() { - iterate(callback); - }, 0); + if (!doc) { + return callback(null); + } + handleNextResult(doc, function(error) { + if (error) { + return callback(error); + } + // Make sure to clear the stack re: gh-4697 + setTimeout(function() { + iterate(callback); + }, 0); + }); }); - }); + } }; return new Promise.ES6(function(resolve, reject) { diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index bbc6cc9a6f4..3cc4875f5a7 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -291,6 +291,31 @@ describe('QueryCursor', function() { done(); }).catch(done); }); + + it('parallelization', function(done) { + var cursor = Model.find().sort({ name: 1 }).cursor(); + + var names = []; + var startedAt = []; + var checkDoc = function(doc) { + names.push(doc.name); + startedAt.push(Date.now()); + return { + then: function(onResolve) { + setTimeout(function() { + onResolve(); + }, 100); + } + }; + }; + cursor.eachAsync(checkDoc, { parallel: 2 }).then(function() { + assert.ok(Date.now() - startedAt[1] > 100); + assert.equal(startedAt.length, 2); + assert.ok(startedAt[1] - startedAt[0] < 50); + assert.deepEqual(names.sort(), ['Axl', 'Slash']); + done(); + }).catch(done); + }); }); describe('#lean()', function() { From 091e12b427d5b842dcd7bfe63347106d03101d38 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Mar 2017 18:19:23 -0600 Subject: [PATCH 1344/2240] test(update): repro #5088 --- test/model.update.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index d9297e269c8..d304539a836 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2447,6 +2447,26 @@ describe('model: update:', function() { }); }); + it('does not fail if passing whole doc (gh-5088)', function(done) { + var schema = new Schema({ + username: String, + x: String + }, { timestamps: true }); + var User = db.model('gh5088', schema); + + User.create({ username: 'test' }). + then(function(user) { + user.x = 'test2'; + return User.findOneAndUpdate({ _id: user._id }, user, + { new: true }); + }). + then(function(user) { + assert.equal(user.x, 'test2'); + done(); + }). + catch(done); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From ea9ff079666a6b5403b0b6288179e594a6638dd9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Mar 2017 18:20:18 -0600 Subject: [PATCH 1345/2240] fix(update): avoid adding empty updates when updating timestamps Fix #5088 --- lib/schema.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 32b14509560..551a4573181 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -865,18 +865,15 @@ Schema.prototype.setupTimestamp = function(timestamps) { } return updates; } - updates = { $set: {}, $setOnInsert: {} }; + updates = { $set: {} }; currentUpdate = currentUpdate || {}; - currentUpdate.$set = currentUpdate.$set || {}; - currentUpdate.$setOnInsert = currentUpdate.$setOnInsert || {}; - if (!currentUpdate[updatedAt] && - !currentUpdate.$set[updatedAt] && - !currentUpdate.$setOnInsert[updatedAt]) { - updates.$set[updatedAt] = now; - } + + updates.$set[updatedAt] = now; + if (!currentUpdate[createdAt] && - !currentUpdate.$set[createdAt] && - !currentUpdate.$setOnInsert[createdAt]) { + (!currentUpdate.$set || !currentUpdate.$set[createdAt]) && + (!currentUpdate.$setOnInsert || !currentUpdate.$setOnInsert[createdAt])) { + updates.$setOnInsert = {}; updates.$setOnInsert[createdAt] = now; } From f17fe9136b913661bcad20c8b2ad0faf9e1b5cca Mon Sep 17 00:00:00 2001 From: Jiang-Xuan <645762213@qq.com> Date: Tue, 21 Mar 2017 09:22:44 +0800 Subject: [PATCH 1346/2240] Update guide.jade I guess `unpredictable` is right.Because i can't find it when i use bing online dictionary. --- docs/guide.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide.jade b/docs/guide.jade index b6642a07255..54d6f7fa33a 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -108,7 +108,7 @@ block content .important :markdown - Overwriting a default mongoose document method may lead to unpredictible results. See [this](./api.html#schema_Schema.reserved) for more details. + Overwriting a default mongoose document method may lead to unpredictable results. See [this](./api.html#schema_Schema.reserved) for more details. h3#statics Statics :markdown From 1d3a962d0141ee5f3e6b4f55e328792bd1021af3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 21 Mar 2017 19:57:45 -0600 Subject: [PATCH 1347/2240] fix(timestamps): handle overwriting createdAt+updatedAt consistently Re: #5088 #5045 --- lib/schema.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 551a4573181..4ec2379167a 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -870,12 +870,15 @@ Schema.prototype.setupTimestamp = function(timestamps) { updates.$set[updatedAt] = now; - if (!currentUpdate[createdAt] && - (!currentUpdate.$set || !currentUpdate.$set[createdAt]) && - (!currentUpdate.$setOnInsert || !currentUpdate.$setOnInsert[createdAt])) { - updates.$setOnInsert = {}; - updates.$setOnInsert[createdAt] = now; + if (currentUpdate[createdAt]) { + delete currentUpdate[createdAt]; } + if (currentUpdate.$set && currentUpdate.$set[createdAt]) { + delete currentUpdate.$set[createdAt]; + } + + updates.$setOnInsert = {}; + updates.$setOnInsert[createdAt] = now; return updates; }; From 432360e5c3b55cc3bfb689e602c06d3d25e0a5b1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Mar 2017 20:28:10 -0600 Subject: [PATCH 1348/2240] test(discriminator): repro #5098 --- test/model.discriminator.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index e8b6704c620..26bae1ab58b 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -492,6 +492,22 @@ describe('model', function() { }); }); + it('clone() allows reusing schemas (gh-5098)', function(done) { + var personSchema = new Schema({ + name: String + }, { discriminatorKey: 'kind' }); + + var parentSchema = new Schema({ + child: String + }); + + var Person = db.model('gh5098', personSchema); + var Parent = Person.discriminator('gh5098_0', parentSchema.clone()); + // Should not throw + var Parent2 = Person.discriminator('gh5098_1', parentSchema.clone()); + done(); + }); + it('embedded discriminators with $push (gh-5009)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From 51b8e8060e5b69406b9386be844deba00a1b2321 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Mar 2017 20:29:13 -0600 Subject: [PATCH 1349/2240] fix(schema): make clone() work with reusing discriminator schemas Fix #5098 --- lib/schema.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 4ec2379167a..27b97a91bf7 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -343,8 +343,11 @@ Schema.prototype.tree; */ Schema.prototype.clone = function() { - var s = Object.create(Schema.prototype); - utils.merge(s, this, { retainKeyOrder: true, hasOwnProperty: true }); + var s = new Schema(this.obj, this.options); + // Clone the call queue + s.callQueue = this.callQueue.map(function(f) { return f; }); + s.methods = utils.clone(this.methods); + s.statics = utils.clone(this.statics); return s; }; From b72eacaecf2a7c1762b45a79b530d0695040430b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 23 Mar 2017 13:47:46 -0600 Subject: [PATCH 1350/2240] refactor: move most test schemas into before hooks --- test/types.array.test.js | 31 +++++---- test/types.buffer.test.js | 31 +++++---- test/types.document.test.js | 97 +++++++++++++---------------- test/types.embeddeddocument.test.js | 36 ++++++----- test/types.subdocument.test.js | 36 ++++++----- test/versioning.test.js | 74 +++++++++++----------- 6 files changed, 155 insertions(+), 150 deletions(-) diff --git a/test/types.array.test.js b/test/types.array.test.js index bc451969150..c968aa1af72 100644 --- a/test/types.array.test.js +++ b/test/types.array.test.js @@ -11,24 +11,29 @@ var mongodb = require('mongodb'); var MongooseArray = mongoose.Types.Array; var collection = 'avengers_' + random(); -var User = new Schema({ - name: String, - pets: [Schema.ObjectId] -}); - -mongoose.model('User', User); - -var Pet = new Schema({ - name: String -}); - -mongoose.model('Pet', Pet); - /** * Test. */ describe('types array', function() { + var User; + var Pet; + + before(function() { + User = new Schema({ + name: String, + pets: [Schema.ObjectId] + }); + + mongoose.model('User', User); + + Pet = new Schema({ + name: String + }); + + mongoose.model('Pet', Pet); + }); + it('behaves and quacks like an Array', function(done) { var a = new MongooseArray; diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js index 758cc390bc3..d633d78795f 100644 --- a/test/types.buffer.test.js +++ b/test/types.buffer.test.js @@ -13,19 +13,6 @@ function valid(v) { return !v || v.length > 10; } -var subBuf = new Schema({ - name: String, - buf: {type: Buffer, validate: [valid, 'valid failed'], required: true} -}); - -var UserBuffer = new Schema({ - name: String, - serial: Buffer, - array: [Buffer], - required: {type: Buffer, required: true, index: true}, - sub: [subBuf] -}); - // Dont put indexed models on the default connection, it // breaks index.test.js tests on a "pure" default conn. // mongoose.model('UserBuffer', UserBuffer); @@ -35,6 +22,24 @@ var UserBuffer = new Schema({ */ describe('types.buffer', function() { + var subBuf; + var UserBuffer; + + before(function() { + subBuf = new Schema({ + name: String, + buf: {type: Buffer, validate: [valid, 'valid failed'], required: true} + }); + + UserBuffer = new Schema({ + name: String, + serial: Buffer, + array: [Buffer], + required: {type: Buffer, required: true, index: true}, + sub: [subBuf] + }); + }); + it('test that a mongoose buffer behaves and quacks like a buffer', function(done) { var a = new MongooseBuffer; diff --git a/test/types.document.test.js b/test/types.document.test.js index 0541d0390c6..29329778fbf 100644 --- a/test/types.document.test.js +++ b/test/types.document.test.js @@ -13,63 +13,56 @@ var Schema = mongoose.Schema; var ValidationError = mongoose.Document.ValidationError; /** - * Setup. - */ - -function Dummy() { - mongoose.Document.call(this, {}); -} -Dummy.prototype.__proto__ = mongoose.Document.prototype; -Dummy.prototype.$__setSchema(new Schema); - -function Subdocument() { - var arr = new DocumentArray; - arr._path = 'jsconf.ar'; - arr._parent = new Dummy; - arr[0] = this; - EmbeddedDocument.call(this, {}, arr); -} - -/** - * Inherits from EmbeddedDocument. - */ - -Subdocument.prototype.__proto__ = EmbeddedDocument.prototype; - -for (var i in EventEmitter.prototype) { - Subdocument[i] = EventEmitter.prototype[i]; -} - -/** - * Set schema. - */ - -Subdocument.prototype.$__setSchema(new Schema({ - test: {type: String, required: true}, - work: {type: String, validate: /^good/} -})); - -/** - * Schema. + * Test. */ -var RatingSchema = new Schema({ - stars: Number, - description: {source: {url: String, time: Date}} -}); - -var MovieSchema = new Schema({ - title: String, - ratings: [RatingSchema] -}); +describe('types.document', function() { + var Dummy; + var Subdocument; + var RatingSchema; + var MovieSchema; + + before(function() { + function _Dummy() { + mongoose.Document.call(this, {}); + } + Dummy = _Dummy; + Dummy.prototype.__proto__ = mongoose.Document.prototype; + Dummy.prototype.$__setSchema(new Schema); + + function _Subdocument() { + var arr = new DocumentArray; + arr._path = 'jsconf.ar'; + arr._parent = new Dummy; + arr[0] = this; + EmbeddedDocument.call(this, {}, arr); + } + Subdocument = _Subdocument; + + Subdocument.prototype.__proto__ = EmbeddedDocument.prototype; + + for (var i in EventEmitter.prototype) { + Subdocument[i] = EventEmitter.prototype[i]; + } + + Subdocument.prototype.$__setSchema(new Schema({ + test: {type: String, required: true}, + work: {type: String, validate: /^good/} + })); + + RatingSchema = new Schema({ + stars: Number, + description: {source: {url: String, time: Date}} + }); -mongoose.model('Movie', MovieSchema); + MovieSchema = new Schema({ + title: String, + ratings: [RatingSchema] + }); -/** - * Test. - */ + mongoose.model('Movie', MovieSchema); + }); -describe('types.document', function() { it('test that validate sets errors', function(done) { var a = new Subdocument(); a.set('test', ''); diff --git a/test/types.embeddeddocument.test.js b/test/types.embeddeddocument.test.js index d15f6de87b4..2859742047d 100644 --- a/test/types.embeddeddocument.test.js +++ b/test/types.embeddeddocument.test.js @@ -9,30 +9,32 @@ var assert = require('power-assert'), Schema = mongoose.Schema; /** - * Schema. + * Test. */ -var GrandChildSchema = new Schema({ - name: String -}); +describe('types.embeddeddocument', function() { + var GrandChildSchema; + var ChildSchema; + var ParentSchema; -var ChildSchema = new Schema({ - name: String, - children: [GrandChildSchema] -}); + before(function() { + GrandChildSchema = new Schema({ + name: String + }); -var ParentSchema = new Schema({ - name: String, - child: ChildSchema -}); + ChildSchema = new Schema({ + name: String, + children: [GrandChildSchema] + }); -mongoose.model('Parent-3589-Embedded', ParentSchema); + ParentSchema = new Schema({ + name: String, + child: ChildSchema + }); -/** - * Test. - */ + mongoose.model('Parent-3589-Embedded', ParentSchema); + }); -describe('types.embeddeddocument', function() { it('returns a proper ownerDocument (gh-3589)', function(done) { var Parent = mongoose.model('Parent-3589-Embedded'); var p = new Parent({ diff --git a/test/types.subdocument.test.js b/test/types.subdocument.test.js index 4bd4baa30b2..1ea6f09da80 100644 --- a/test/types.subdocument.test.js +++ b/test/types.subdocument.test.js @@ -9,30 +9,32 @@ var assert = require('power-assert'), Schema = mongoose.Schema; /** - * Schema. + * Test. */ -var GrandChildSchema = new Schema({ - name: String -}); +describe('types.subdocument', function() { + var GrandChildSchema; + var ChildSchema; + var ParentSchema; -var ChildSchema = new Schema({ - name: String, - child: GrandChildSchema -}); + before(function() { + GrandChildSchema = new Schema({ + name: String + }); -var ParentSchema = new Schema({ - name: String, - children: [ChildSchema] -}); + ChildSchema = new Schema({ + name: String, + child: GrandChildSchema + }); -mongoose.model('Parent-3589-Sub', ParentSchema); + ParentSchema = new Schema({ + name: String, + children: [ChildSchema] + }); -/** - * Test. - */ + mongoose.model('Parent-3589-Sub', ParentSchema); + }); -describe('types.subdocument', function() { it('returns a proper ownerDocument (gh-3589)', function(done) { var Parent = mongoose.model('Parent-3589-Sub'); var p = new Parent({ diff --git a/test/versioning.test.js b/test/versioning.test.js index bc6ef14c00b..f60976975b1 100644 --- a/test/versioning.test.js +++ b/test/versioning.test.js @@ -9,50 +9,48 @@ var start = require('./common'), Schema = mongoose.Schema, VersionError = mongoose.Error.VersionError; -/** - * Setup. - */ +describe('versioning', function() { + var db; + var Comments; + var BlogPost; -var Comments = new Schema(); + before(function() { + db = start(); -Comments.add({ - title: String, - date: Date, - comments: [Comments], - dontVersionMeEither: [] -}); + Comments = new Schema(); -var BlogPost = new Schema( - { - title: String, - date: Date, - meta: { + Comments.add({ + title: String, date: Date, - visitors: Number, - nested: [Comments], - numbers: [Number] - }, - mixed: {}, - numbers: [Number], - comments: [Comments], - arr: [], - dontVersionMe: [] - }, - { - collection: 'versioning_' + random(), - skipVersioning: { - dontVersionMe: true, - 'comments.dontVersionMeEither': true - } - }); - -mongoose.model('Versioning', BlogPost); + comments: [Comments], + dontVersionMeEither: [] + }); -describe('versioning', function() { - var db; + BlogPost = new Schema( + { + title: String, + date: Date, + meta: { + date: Date, + visitors: Number, + nested: [Comments], + numbers: [Number] + }, + mixed: {}, + numbers: [Number], + comments: [Comments], + arr: [], + dontVersionMe: [] + }, + { + collection: 'versioning_' + random(), + skipVersioning: { + dontVersionMe: true, + 'comments.dontVersionMeEither': true + } + }); - before(function() { - db = start(); + mongoose.model('Versioning', BlogPost); }); after(function(done) { From a160e4e3f889a8214c334e234cc8fdc4771c553d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 23 Mar 2017 14:02:28 -0600 Subject: [PATCH 1351/2240] refactor: move more schemas into before hooks --- test/model.stream.test.js | 24 +++---- test/model.test.js | 101 +++++++++++++------------- test/model.update.test.js | 117 ++++++++++++++++--------------- test/object.create.null.test.js | 23 +++--- test/promise_provider.test.js | 45 ++++++------ test/query.test.js | 40 ++++++----- test/query.toconstructor.test.js | 42 ++++++----- test/schema.onthefly.test.js | 19 ++--- test/schema.test.js | 14 ++-- test/schema.timestamps.test.js | 16 +++-- 10 files changed, 232 insertions(+), 209 deletions(-) diff --git a/test/model.stream.test.js b/test/model.stream.test.js index bcd29898692..6f70f58f7cd 100644 --- a/test/model.stream.test.js +++ b/test/model.stream.test.js @@ -13,20 +13,20 @@ var start = require('./common'), var names = ('Aaden Aaron Adrian Aditya Agustin Jim Bob Jonah Frank Sally Lucy').split(' '); -/** - * Setup. - */ - -var Person = new Schema({ - name: String -}); - -mongoose.model('PersonForStream', Person); -var collection = 'personforstream_' + random(); - describe('query stream:', function() { var db = start(); - var P = db.model('PersonForStream', collection); + var Person; + var collection = 'personforstream_' + random(); + var P; + + before(function() { + Person = new Schema({ + name: String + }); + + mongoose.model('PersonForStream', Person); + P = db.model('PersonForStream', collection); + }); before(function(done) { var people = names.map(function(name) { diff --git a/test/model.test.js b/test/model.test.js index 872a1865378..667eefd74b5 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -14,62 +14,65 @@ var start = require('./common'), EmbeddedDocument = mongoose.Types.Embedded, MongooseError = mongoose.Error; -/** - * Setup. - */ - -var Comments = new Schema; +describe('Model', function() { + var db; + var Test; + var Comments; + var BlogPost; + var bpSchema; + var collection; -Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments] -}); + before(function() { + Comments = new Schema; -var BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number - }, - published: Boolean, - mixed: {}, - numbers: [Number], - owners: [ObjectId], - comments: [Comments], - nested: {array: [Number]} -}); + Comments.add({ + title: String, + date: Date, + body: String, + comments: [Comments] + }); -BlogPost -.virtual('titleWithAuthor') -.get(function() { - return this.get('title') + ' by ' + this.get('author'); -}) -.set(function(val) { - var split = val.split(' by '); - this.set('title', split[0]); - this.set('author', split[1]); -}); + BlogPost = new Schema({ + title: String, + author: String, + slug: String, + date: Date, + meta: { + date: Date, + visitors: Number + }, + published: Boolean, + mixed: {}, + numbers: [Number], + owners: [ObjectId], + comments: [Comments], + nested: {array: [Number]} + }); -BlogPost.method('cool', function() { - return this; -}); + BlogPost + .virtual('titleWithAuthor') + .get(function() { + return this.get('title') + ' by ' + this.get('author'); + }) + .set(function(val) { + var split = val.split(' by '); + this.set('title', split[0]); + this.set('author', split[1]); + }); -BlogPost.static('woot', function() { - return this; -}); + BlogPost.method('cool', function() { + return this; + }); -mongoose.model('BlogPost', BlogPost); -var bpSchema = BlogPost; + BlogPost.static('woot', function() { + return this; + }); -var collection = 'blogposts_' + random(); + mongoose.model('BlogPost', BlogPost); + bpSchema = BlogPost; -describe('Model', function() { - var db, Test; + collection = 'blogposts_' + random(); + }); before(function() { db = start(); @@ -122,9 +125,7 @@ describe('Model', function() { }); }); }); -}); -describe('Model', function() { describe('constructor', function() { it('works without "new" keyword', function(done) { var B = mongoose.model('BlogPost'); diff --git a/test/model.update.test.js b/test/model.update.test.js index d304539a836..3311246d160 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -10,71 +10,72 @@ var start = require('./common'), ObjectId = Schema.Types.ObjectId, DocumentObjectId = mongoose.Types.ObjectId; -/** - * Setup. - */ - -var Comments = new Schema({}); - -Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments] -}); - -var BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number - }, - published: Boolean, - mixed: {}, - numbers: [Number], - owners: [ObjectId], - comments: [Comments] -}, {strict: false}); - -BlogPost.virtual('titleWithAuthor') -.get(function() { - return this.get('title') + ' by ' + this.get('author'); -}) -.set(function(val) { - var split = val.split(' by '); - this.set('title', split[0]); - this.set('author', split[1]); -}); +describe('model: update:', function() { + var post; + var title = 'Tobi ' + random(); + var author = 'Brian ' + random(); + var newTitle = 'Woot ' + random(); + var id0; + var id1; + var Comments; + var BlogPost; + var collection; + var strictSchema; + + before(function() { + Comments = new Schema({}); + + Comments.add({ + title: String, + date: Date, + body: String, + comments: [Comments] + }); -BlogPost.method('cool', function() { - return this; -}); + BlogPost = new Schema({ + title: String, + author: String, + slug: String, + date: Date, + meta: { + date: Date, + visitors: Number + }, + published: Boolean, + mixed: {}, + numbers: [Number], + owners: [ObjectId], + comments: [Comments] + }, {strict: false}); -BlogPost.static('woot', function() { - return this; -}); + BlogPost.virtual('titleWithAuthor') + .get(function() { + return this.get('title') + ' by ' + this.get('author'); + }) + .set(function(val) { + var split = val.split(' by '); + this.set('title', split[0]); + this.set('author', split[1]); + }); -mongoose.model('BlogPostForUpdates', BlogPost); + BlogPost.method('cool', function() { + return this; + }); -var collection = 'blogposts_' + random(); + BlogPost.static('woot', function() { + return this; + }); -var strictSchema = new Schema({name: String, x: {nested: String}}); -strictSchema.virtual('foo').get(function() { - return 'i am a virtual FOO!'; -}); -mongoose.model('UpdateStrictSchema', strictSchema); + mongoose.model('BlogPostForUpdates', BlogPost); + collection = 'blogposts_' + random(); -describe('model: update:', function() { - var post, - title = 'Tobi ' + random(), - author = 'Brian ' + random(), - newTitle = 'Woot ' + random(), - id0, - id1; + strictSchema = new Schema({name: String, x: {nested: String}}); + strictSchema.virtual('foo').get(function() { + return 'i am a virtual FOO!'; + }); + mongoose.model('UpdateStrictSchema', strictSchema); + }); before(function(done) { var db = start(), diff --git a/test/object.create.null.test.js b/test/object.create.null.test.js index 19e11b2ab6f..473427a95dc 100644 --- a/test/object.create.null.test.js +++ b/test/object.create.null.test.js @@ -7,20 +7,24 @@ var start = require('./common'), mongoose = start.mongoose, Schema = mongoose.Schema; -var schema = new Schema({ - a: String, - b: { - c: Number, - d: [{e: String}] - }, - f: {g: Date}, - h: {} -}); +var schema; describe('is compatible with object created using Object.create(null) (gh-1484)', function() { var db; var M; + before(function() { + schema = new Schema({ + a: String, + b: { + c: Number, + d: [{e: String}] + }, + f: {g: Date}, + h: {} + }); + }); + before(function() { db = start(); M = db.model('1484', schema); @@ -133,4 +137,3 @@ describe('is compatible with object created using Object.create(null) (gh-1484)' done(); }); }); - diff --git a/test/promise_provider.test.js b/test/promise_provider.test.js index 273f9fc9806..f60e36a995e 100644 --- a/test/promise_provider.test.js +++ b/test/promise_provider.test.js @@ -11,28 +11,33 @@ var PromiseProvider = require('../lib/promise_provider'); var Schema = require('../lib/schema'); var db; -var testSchema = new Schema({test: {type: String, required: true}}); -testSchema.pre('save', function(next) { - if (this.$__saveSucceeds === false) { - return next(new Error('fail')); - } - next(); -}); -testSchema.pre('validate', function(next) { - if (this.$__validateSucceeds === false) { - return next(new Error('validation failed')); - } - next(); -}); -testSchema.pre('findOne', function(next) { - if (this.$__findOneSucceeds === false) { - return next(new Error('findOne failed')); - } - next(); -}); -var MyModel; describe('ES6 promises: ', function() { + var testSchema; + var MyModel; + + before(function() { + testSchema = new Schema({test: {type: String, required: true}}); + testSchema.pre('save', function(next) { + if (this.$__saveSucceeds === false) { + return next(new Error('fail')); + } + next(); + }); + testSchema.pre('validate', function(next) { + if (this.$__validateSucceeds === false) { + return next(new Error('validation failed')); + } + next(); + }); + testSchema.pre('findOne', function(next) { + if (this.$__findOneSucceeds === false) { + return next(new Error('findOne failed')); + } + next(); + }); + }); + describe('native: ', function() { if (!global.Promise) { return; diff --git a/test/query.test.js b/test/query.test.js index 82b1c20e6b2..26c1ed430cf 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -10,32 +10,38 @@ var assert = require('power-assert'); var random = require('../lib/utils').random; var Query = require('../lib/query'); -var Comment = new Schema({ - text: String -}); - -var Product = new Schema({ - tags: {}, // mixed - array: Array, - ids: [Schema.ObjectId], - strings: [String], - numbers: [Number], - comments: [Comment] -}); - -mongoose.model('Product', Product); -mongoose.model('Comment', Comment); -var p1; - /** * Test. */ describe('Query', function() { + var Comment; + var Product; + var p1; + + before(function() { + Comment = new Schema({ + text: String + }); + + Product = new Schema({ + tags: {}, // mixed + array: Array, + ids: [Schema.ObjectId], + strings: [String], + numbers: [Number], + comments: [Comment] + }); + + mongoose.model('Product', Product); + mongoose.model('Comment', Comment); + }); + before(function() { var Prod = mongoose.model('Product'); p1 = new Prod(); }); + describe('constructor', function() { it('should not corrupt options', function(done) { var opts = {}; diff --git a/test/query.toconstructor.test.js b/test/query.toconstructor.test.js index 01a32bc3da8..74625561026 100644 --- a/test/query.toconstructor.test.js +++ b/test/query.toconstructor.test.js @@ -5,26 +5,32 @@ var start = require('./common'), random = require('../lib/utils').random, Query = require('../lib/query'); +describe('Query:', function() { + var Comment; + var Product; + var prodName; + var cName; + + before(function() { + Comment = new Schema({ + text: String + }); -var Comment = new Schema({ - text: String -}); - -var Product = new Schema({ - tags: {}, // mixed - array: Array, - ids: [Schema.ObjectId], - strings: [String], - numbers: [Number], - comments: [Comment], - title: String -}); -var prodName = 'Product' + random(); -var cName = 'Comment' + random(); -mongoose.model(prodName, Product); -mongoose.model(cName, Comment); + Product = new Schema({ + tags: {}, // mixed + array: Array, + ids: [Schema.ObjectId], + strings: [String], + numbers: [Number], + comments: [Comment], + title: String + }); + prodName = 'Product' + random(); + mongoose.model(prodName, Product); + cName = 'Comment' + random(); + mongoose.model(cName, Comment); + }); -describe('Query:', function() { describe('toConstructor', function() { var db; diff --git a/test/schema.onthefly.test.js b/test/schema.onthefly.test.js index 20910aa8df1..78bc6486850 100644 --- a/test/schema.onthefly.test.js +++ b/test/schema.onthefly.test.js @@ -5,19 +5,20 @@ var start = require('./common'), Schema = mongoose.Schema, ObjectId = Schema.ObjectId; -/** - * Setup. - */ +describe('schema.onthefly', function() { + var DecoratedSchema; + var collection; -var DecoratedSchema = new Schema({ - title: String -}, {strict: false}); + before(function() { + DecoratedSchema = new Schema({ + title: String + }, {strict: false}); -mongoose.model('Decorated', DecoratedSchema); + mongoose.model('Decorated', DecoratedSchema); -var collection = 'decorated_' + random(); + collection = 'decorated_' + random(); + }); -describe('schema.onthefly', function() { it('setting should cache the schema type and cast values appropriately', function(done) { var db = start(), Decorated = db.model('Decorated', collection); diff --git a/test/schema.test.js b/test/schema.test.js index 13d01eef796..b7b2dc7e970 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -29,19 +29,17 @@ function TestDocument() { TestDocument.prototype.__proto__ = Document.prototype; -/** - * Set a dummy schema to simulate compilation. - */ - -TestDocument.prototype.$__setSchema(new Schema({ - test: String -})); - /** * Test. */ describe('schema', function() { + before(function() { + TestDocument.prototype.$__setSchema(new Schema({ + test: String + })); + }); + describe('nested fields with same name', function() { var db, NestedModel; diff --git a/test/schema.timestamps.test.js b/test/schema.timestamps.test.js index 35a9f23d103..8d7842af84a 100644 --- a/test/schema.timestamps.test.js +++ b/test/schema.timestamps.test.js @@ -141,15 +141,17 @@ describe('schema options.timestamps', function() { }); describe('auto update createdAt and updatedAt when create/save/update document', function() { - var CatSchema = new Schema({ - name: String, - hobby: String - }, {timestamps: true}); - - var conn = start(); - var Cat = conn.model('Cat', CatSchema); + var CatSchema; + var conn; + var Cat; before(function(done) { + CatSchema = new Schema({ + name: String, + hobby: String + }, {timestamps: true}); + conn = start(); + Cat = conn.model('Cat', CatSchema); Cat.remove({}, done); }); From bbf6166a9016ac78ec767ad8f35f3256a03f50ef Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 23 Mar 2017 14:22:17 -0600 Subject: [PATCH 1352/2240] refactor: move more tests into before hooks --- test/model.field.selection.test.js | 71 ++++--- test/model.findAndRemoveOne.test.js | 103 ++++----- test/model.findOneAndUpdate.test.js | 107 +++++----- test/model.geonear.test.js | 22 +- test/model.geosearch.test.js | 28 +-- test/model.hydrate.test.js | 42 ++-- test/model.mapreduce.test.js | 64 +++--- test/model.populate.test.js | 79 ++++--- test/model.query.casting.test.js | 83 ++++---- test/model.querying.test.js | 319 ++++++++++++++-------------- 10 files changed, 469 insertions(+), 449 deletions(-) diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js index 2bca4f2a6c3..726600461d2 100644 --- a/test/model.field.selection.test.js +++ b/test/model.field.selection.test.js @@ -10,43 +10,46 @@ var start = require('./common'), ObjectId = Schema.Types.ObjectId, DocumentObjectId = mongoose.Types.ObjectId; -/** - * Setup. - */ - -var Comments = new Schema; - -Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments] -}); +describe('model field selection', function() { + var Comments; + var BlogPostB; + var modelName; + var collection; + + before(function() { + Comments = new Schema; + + Comments.add({ + title: String, + date: Date, + body: String, + comments: [Comments] + }); -var BlogPostB = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number - }, - published: Boolean, - mixed: {}, - numbers: [Number], - tags: [String], - sigs: [Buffer], - owners: [ObjectId], - comments: [Comments], - def: {type: String, default: 'kandinsky'} -}); + BlogPostB = new Schema({ + title: String, + author: String, + slug: String, + date: Date, + meta: { + date: Date, + visitors: Number + }, + published: Boolean, + mixed: {}, + numbers: [Number], + tags: [String], + sigs: [Buffer], + owners: [ObjectId], + comments: [Comments], + def: {type: String, default: 'kandinsky'} + }); -var modelName = 'model.select.blogpost'; -mongoose.model(modelName, BlogPostB); -var collection = 'blogposts_' + random(); + modelName = 'model.select.blogpost'; + mongoose.model(modelName, BlogPostB); + collection = 'blogposts_' + random(); + }); -describe('model field selection', function() { it('excluded fields should be undefined', function(done) { var db = start(), BlogPostB = db.model(modelName, collection), diff --git a/test/model.findAndRemoveOne.test.js b/test/model.findAndRemoveOne.test.js index d0e137b3e48..58008c5b281 100644 --- a/test/model.findAndRemoveOne.test.js +++ b/test/model.findAndRemoveOne.test.js @@ -11,62 +11,66 @@ var start = require('./common'), ObjectId = Schema.Types.ObjectId, DocumentObjectId = mongoose.Types.ObjectId; -/** - * Setup. - */ - -var Comments = new Schema; - -Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments] -}); +describe('model: findOneAndRemove:', function() { + var Comments; + var BlogPost; + var modelname; + var collection; + var strictSchema; + + before(function() { + Comments = new Schema; + + Comments.add({ + title: String, + date: Date, + body: String, + comments: [Comments] + }); -var BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number - }, - published: Boolean, - mixed: {}, - numbers: [Number], - owners: [ObjectId], - comments: [Comments] -}); + BlogPost = new Schema({ + title: String, + author: String, + slug: String, + date: Date, + meta: { + date: Date, + visitors: Number + }, + published: Boolean, + mixed: {}, + numbers: [Number], + owners: [ObjectId], + comments: [Comments] + }); -BlogPost.virtual('titleWithAuthor') - .get(function() { - return this.get('title') + ' by ' + this.get('author'); - }) - .set(function(val) { - var split = val.split(' by '); - this.set('title', split[0]); - this.set('author', split[1]); - }); + BlogPost.virtual('titleWithAuthor') + .get(function() { + return this.get('title') + ' by ' + this.get('author'); + }) + .set(function(val) { + var split = val.split(' by '); + this.set('title', split[0]); + this.set('author', split[1]); + }); -BlogPost.method('cool', function() { - return this; -}); + BlogPost.method('cool', function() { + return this; + }); -BlogPost.static('woot', function() { - return this; -}); + BlogPost.static('woot', function() { + return this; + }); -var modelname = 'RemoveOneBlogPost'; -mongoose.model(modelname, BlogPost); + modelname = 'RemoveOneBlogPost'; + mongoose.model(modelname, BlogPost); -var collection = 'removeoneblogposts_' + random(); + collection = 'removeoneblogposts_' + random(); -var strictSchema = new Schema({name: String}, {strict: true}); -mongoose.model('RemoveOneStrictSchema', strictSchema); + strictSchema = new Schema({name: String}, {strict: true}); + mongoose.model('RemoveOneStrictSchema', strictSchema); + }); -describe('model: findOneAndRemove:', function() { it('returns the original document', function(done) { var db = start(), M = db.model(modelname, collection), @@ -162,9 +166,7 @@ describe('model: findOneAndRemove:', function() { assert.ok(/First argument must not be a function/.test(err)); done(); }); -}); -describe('model: findByIdAndRemove:', function() { it('executed with only a callback throws', function(done) { var db = start(), M = db.model(modelname, collection), @@ -432,4 +434,3 @@ describe('model: findByIdAndRemove:', function() { }); }); }); - diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 294f9b3c6c6..271eebe8b3d 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -13,65 +13,70 @@ var ObjectId = Schema.Types.ObjectId; var DocumentObjectId = mongoose.Types.ObjectId; var _ = require('lodash'); -/** - * Setup. - */ - -var Comments = new Schema(); - -Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments] -}); +describe('model: findOneAndUpdate:', function() { + var Comments; + var BlogPost; + var modelname; + var collection; + var strictSchema; + var strictThrowSchema; + + before(function() { + Comments = new Schema(); + + Comments.add({ + title: String, + date: Date, + body: String, + comments: [Comments] + }); -var BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number - }, - published: Boolean, - mixed: {}, - numbers: [Number], - owners: [ObjectId], - comments: [Comments] -}); + BlogPost = new Schema({ + title: String, + author: String, + slug: String, + date: Date, + meta: { + date: Date, + visitors: Number + }, + published: Boolean, + mixed: {}, + numbers: [Number], + owners: [ObjectId], + comments: [Comments] + }); -BlogPost.virtual('titleWithAuthor') -.get(function() { - return this.get('title') + ' by ' + this.get('author'); -}) -.set(function(val) { - var split = val.split(' by '); - this.set('title', split[0]); - this.set('author', split[1]); -}); + BlogPost.virtual('titleWithAuthor') + .get(function() { + return this.get('title') + ' by ' + this.get('author'); + }) + .set(function(val) { + var split = val.split(' by '); + this.set('title', split[0]); + this.set('author', split[1]); + }); -BlogPost.method('cool', function() { - return this; -}); + BlogPost.method('cool', function() { + return this; + }); -BlogPost.static('woot', function() { - return this; -}); + BlogPost.static('woot', function() { + return this; + }); -var modelname = 'UpdateOneBlogPost'; -mongoose.model(modelname, BlogPost); + modelname = 'UpdateOneBlogPost'; + mongoose.model(modelname, BlogPost); -var collection = 'updateoneblogposts_' + random(); + collection = 'updateoneblogposts_' + random(); -var strictSchema = new Schema({name: String}, {strict: true}); -mongoose.model('UpdateOneStrictSchema', strictSchema); + strictSchema = new Schema({name: String}, {strict: true}); + mongoose.model('UpdateOneStrictSchema', strictSchema); -var strictThrowSchema = new Schema({name: String}, {strict: 'throw'}); -mongoose.model('UpdateOneStrictThrowSchema', strictThrowSchema); + strictThrowSchema = new Schema({name: String}, {strict: 'throw'}); + mongoose.model('UpdateOneStrictThrowSchema', strictThrowSchema); + }); -describe('model: findOneAndUpdate:', function() { it('WWW returns the edited document', function(done) { var db = start(), M = db.model(modelname, collection), @@ -535,9 +540,7 @@ describe('model: findOneAndUpdate:', function() { }); }); }); -}); -describe('model: findByIdAndUpdate:', function() { it('executing with just a callback throws', function(done) { var db = start(), M = db.model(modelname, collection), diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js index 2389bb07951..45e0f8d2afa 100644 --- a/test/model.geonear.test.js +++ b/test/model.geonear.test.js @@ -9,15 +9,6 @@ var start = require('./common'), * Setup */ -var schema = new Schema({ - coordinates: {type: [Number], index: '2dsphere'}, - type: String -}); - -function getModel(db) { - return db.model('GeoNear', schema, 'geonear' + random()); -} - var testLocations = { MONGODB_NYC_OFFICE: [-73.987732, 40.757471], BRYANT_PART_NY: [-73.983677, 40.753628], @@ -32,6 +23,19 @@ function metersToRadians(m) { } describe('model', function() { + var schema; + + function getModel(db) { + return db.model('GeoNear', schema, 'geonear' + random()); + } + + before(function() { + schema = new Schema({ + coordinates: {type: [Number], index: '2dsphere'}, + type: String + }); + }); + var mongo24_or_greater = false; before(function(done) { start.mongodVersion(function(err, version) { diff --git a/test/model.geosearch.test.js b/test/model.geosearch.test.js index a58ebb15090..65b082e1fe1 100644 --- a/test/model.geosearch.test.js +++ b/test/model.geosearch.test.js @@ -5,22 +5,22 @@ var start = require('./common'), random = require('../lib/utils').random, Schema = mongoose.Schema; -/** - * Setup - */ - -var schema = new Schema({ - pos: [Number], - complex: {}, - type: String -}); -schema.index({pos: 'geoHaystack', type: 1}, {bucketSize: 1}); +describe('model', function() { + var schema; -function getModel(db) { - return db.model('GeoSearch', schema, 'geosearch-' + random()); -} + function getModel(db) { + return db.model('GeoSearch', schema, 'geosearch-' + random()); + } + + before(function() { + schema = new Schema({ + pos: [Number], + complex: {}, + type: String + }); + schema.index({pos: 'geoHaystack', type: 1}, {bucketSize: 1}); + }); -describe('model', function() { describe('geoSearch', function() { it('works', function(done) { var db = start(); diff --git a/test/model.hydrate.test.js b/test/model.hydrate.test.js index 41fd97a5fc3..cd63088881b 100644 --- a/test/model.hydrate.test.js +++ b/test/model.hydrate.test.js @@ -8,34 +8,36 @@ var start = require('./common'), Schema = mongoose.Schema, DocumentObjectId = mongoose.Types.ObjectId; -/** - * Setup - */ - -var schemaB = new Schema({ - title: String, - type: String -}, {discriminatorKey: 'type'}); - -var schemaC = new Schema({ - test: { - type: String, - default: 'test' - } -}, {discriminatorKey: 'type'}); - - describe('model', function() { + var schemaB; + var schemaC; + + before(function() { + schemaB = new Schema({ + title: String, + type: String + }, {discriminatorKey: 'type'}); + + schemaC = new Schema({ + test: { + type: String, + default: 'test' + } + }, {discriminatorKey: 'type'}); + }); + describe('hydrate()', function() { var db; var B; var Breakfast; - var breakfastSchema = new Schema({ - food: {type: String, enum: ['bacon', 'eggs']} - }); + var breakfastSchema; before(function() { + breakfastSchema = new Schema({ + food: {type: String, enum: ['bacon', 'eggs']} + }); + db = start(); B = db.model('model-create', schemaB, 'gh-2637-1'); B.discriminator('C', schemaC); diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js index 14f69a90d54..abb7cfc03d3 100644 --- a/test/model.mapreduce.test.js +++ b/test/model.mapreduce.test.js @@ -10,40 +10,41 @@ var start = require('./common'), Schema = mongoose.Schema, ObjectId = Schema.Types.ObjectId; -/** - * Setup. - */ - -var Comments = new Schema(); - -Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments] -}); - -var BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number - }, - published: Boolean, - mixed: {}, - numbers: [Number], - owners: [ObjectId], - comments: [Comments] -}); +describe('model: mapreduce:', function() { + var Comments; + var BlogPost; + var collection; + + before(function() { + Comments = new Schema(); + + Comments.add({ + title: String, + date: Date, + body: String, + comments: [Comments] + }); + BlogPost = new Schema({ + title: String, + author: String, + slug: String, + date: Date, + meta: { + date: Date, + visitors: Number + }, + published: Boolean, + mixed: {}, + numbers: [Number], + owners: [ObjectId], + comments: [Comments] + }); -var collection = 'mapreduce_' + random(); -mongoose.model('MapReduce', BlogPost); + collection = 'mapreduce_' + random(); + mongoose.model('MapReduce', BlogPost); + }); -describe('model: mapreduce:', function() { it('works', function(done) { var db = start(), MR = db.model('MapReduce', collection); @@ -375,4 +376,3 @@ describe('model: mapreduce:', function() { }); }); }); - diff --git a/test/model.populate.test.js b/test/model.populate.test.js index de83e485779..f019c1ad78f 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -14,56 +14,55 @@ var ObjectId = Schema.ObjectId; var DocObjectId = mongoose.Types.ObjectId; /** - * Setup. - */ - -/** - * User schema. + * Tests. */ -var User = new Schema({ - name: String, - email: String, - gender: {type: String, enum: ['male', 'female'], default: 'male'}, - age: {type: Number, default: 21}, - blogposts: [{type: ObjectId, ref: 'RefBlogPost'}], - followers: [{type: ObjectId, ref: 'RefUser'}] -}); +describe('model: populate:', function() { + var User; + var Comment; + var BlogPost; + var posts; + var users; + + before(function() { + User = new Schema({ + name: String, + email: String, + gender: {type: String, enum: ['male', 'female'], default: 'male'}, + age: {type: Number, default: 21}, + blogposts: [{type: ObjectId, ref: 'RefBlogPost'}], + followers: [{type: ObjectId, ref: 'RefUser'}] + }); -/** - * Comment subdocument schema. - */ + /** + * Comment subdocument schema. + */ -var Comment = new Schema({ - asers: [{type: ObjectId, ref: 'RefUser'}], - _creator: {type: ObjectId, ref: 'RefUser'}, - content: String -}); + Comment = new Schema({ + asers: [{type: ObjectId, ref: 'RefUser'}], + _creator: {type: ObjectId, ref: 'RefUser'}, + content: String + }); -/** - * Blog post schema. - */ + /** + * Blog post schema. + */ -var BlogPost = new Schema({ - _creator: {type: ObjectId, ref: 'RefUser'}, - title: String, - comments: [Comment], - fans: [{type: ObjectId, ref: 'RefUser'}] -}); + BlogPost = new Schema({ + _creator: {type: ObjectId, ref: 'RefUser'}, + title: String, + comments: [Comment], + fans: [{type: ObjectId, ref: 'RefUser'}] + }); -var posts = 'blogposts_' + random(), + posts = 'blogposts_' + random(); users = 'users_' + random(); -mongoose.model('RefBlogPost', BlogPost); -mongoose.model('RefUser', User); -mongoose.model('RefAlternateUser', User); - - -/** - * Tests. - */ + mongoose.model('RefBlogPost', BlogPost); + mongoose.model('RefUser', User); + mongoose.model('RefAlternateUser', User); + }); -describe('model: populate:', function() { it('populating array of object', function(done) { var db = start(), BlogPost = db.model('RefBlogPost', posts), diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index 421df199d03..0809938c459 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -15,47 +15,52 @@ var DocumentObjectId = mongoose.Types.ObjectId; var ObjectId = mongoose.Schema.Types.ObjectId; var Schema = mongoose.Schema; -/** - * Setup. - */ - -var Comments = new Schema; - -Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments] -}); +describe('model query casting', function() { + var Comments; + var BlogPostB; + var collection; + var geoSchemaArray; + var geoSchemaObject; + var modelName; + + before(function() { + Comments = new Schema; + + Comments.add({ + title: String, + date: Date, + body: String, + comments: [Comments] + }); -var BlogPostB = new Schema({ - title: {$type: String}, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number - }, - published: Boolean, - mixed: {}, - numbers: [{$type: Number}], - tags: [String], - sigs: [Buffer], - owners: [ObjectId], - comments: [Comments], - def: {$type: String, default: 'kandinsky'} -}, {typeKey: '$type'}); - -var modelName = 'model.query.casting.blogpost'; -mongoose.model(modelName, BlogPostB); -var collection = 'blogposts_' + random(); - -var geoSchemaArray = new Schema({loc: {type: [Number], index: '2d'}}); -var geoSchemaObject = new Schema({loc: {long: Number, lat: Number}}); -geoSchemaObject.index({loc: '2d'}); + BlogPostB = new Schema({ + title: {$type: String}, + author: String, + slug: String, + date: Date, + meta: { + date: Date, + visitors: Number + }, + published: Boolean, + mixed: {}, + numbers: [{$type: Number}], + tags: [String], + sigs: [Buffer], + owners: [ObjectId], + comments: [Comments], + def: {$type: String, default: 'kandinsky'} + }, {typeKey: '$type'}); + + modelName = 'model.query.casting.blogpost'; + mongoose.model(modelName, BlogPostB); + collection = 'blogposts_' + random(); + + geoSchemaArray = new Schema({loc: {type: [Number], index: '2d'}}); + geoSchemaObject = new Schema({loc: {long: Number, lat: Number}}); + geoSchemaObject.index({loc: '2d'}); + }); -describe('model query casting', function() { it('works', function(done) { var db = start(), BlogPostB = db.model(modelName, collection), diff --git a/test/model.querying.test.js b/test/model.querying.test.js index 70c61caabdd..2066b9ef6ce 100644 --- a/test/model.querying.test.js +++ b/test/model.querying.test.js @@ -12,50 +12,54 @@ var start = require('./common'), DocumentObjectId = mongoose.Types.ObjectId, Query = require('../lib/query'); -/** - * Setup. - */ - -var Comments = new Schema; - -Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments] -}); - -var BlogPostB = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number - }, - published: Boolean, - mixed: {}, - numbers: [Number], - tags: [String], - sigs: [Buffer], - owners: [ObjectId], - comments: [Comments], - def: {type: String, default: 'kandinsky'} -}); - -mongoose.model('BlogPostB', BlogPostB); -var collection = 'blogposts_' + random(); - -var ModSchema = new Schema({ - num: Number, - str: String -}); -mongoose.model('Mod', ModSchema); +describe('model: querying:', function() { + var Comments; + var BlogPostB; + var collection; + var ModSchema; + var geoSchema; + + before(function() { + Comments = new Schema; + + Comments.add({ + title: String, + date: Date, + body: String, + comments: [Comments] + }); + + BlogPostB = new Schema({ + title: String, + author: String, + slug: String, + date: Date, + meta: { + date: Date, + visitors: Number + }, + published: Boolean, + mixed: {}, + numbers: [Number], + tags: [String], + sigs: [Buffer], + owners: [ObjectId], + comments: [Comments], + def: {type: String, default: 'kandinsky'} + }); + + mongoose.model('BlogPostB', BlogPostB); + collection = 'blogposts_' + random(); + + ModSchema = new Schema({ + num: Number, + str: String + }); + mongoose.model('Mod', ModSchema); -var geoSchema = new Schema({loc: {type: [Number], index: '2d'}}); + geoSchema = new Schema({loc: {type: [Number], index: '2d'}}); + }); -describe('model: querying:', function() { var mongo26_or_greater = false; before(function(done) { start.mongodVersion(function(err, version) { @@ -1942,9 +1946,7 @@ describe('model: querying:', function() { }); }); }); -}); -describe('buffers', function() { it('works with different methods and query types', function(done) { var db = start(), BufSchema = new Schema({name: String, block: Buffer}), @@ -2099,9 +2101,7 @@ describe('buffers', function() { } }); }); -}); -describe('backwards compatibility', function() { it('with previously existing null values in the db', function(done) { var db = start(), BlogPostB = db.model('BlogPostB', collection), @@ -2138,9 +2138,7 @@ describe('backwards compatibility', function() { }); }); }); -}); -describe('geo-spatial', function() { describe('2d', function() { it('$near (gh-309)', function(done) { var db = start(), @@ -2311,17 +2309,22 @@ describe('geo-spatial', function() { }); describe('2dsphere', function() { - // mongodb 2.4 + var schema2dsphere; + var geoSchema; + var geoMultiSchema; - var schema2dsphere = new Schema({loc: {type: [Number], index: '2dsphere'}}); + before(function() { + schema2dsphere = new Schema({loc: {type: [Number], index: '2dsphere'}}); - var geoSchema = new Schema({line: {type: {type: String}, coordinates: []}}); - geoSchema.index({line: '2dsphere'}); + geoSchema = new Schema({line: {type: {type: String}, coordinates: []}}); + geoSchema.index({line: '2dsphere'}); - var geoMultiSchema = new Schema({geom: [{type: {type: String}, coordinates: []}]}); - // see mongodb issue SERVER-8907 - // geoMultiSchema.index({ geom: '2dsphere' }); + geoMultiSchema = new Schema({geom: [{type: {type: String}, coordinates: []}]}); + // see mongodb issue SERVER-8907 + // geoMultiSchema.index({ geom: '2dsphere' }); + }); + // mongodb 2.4 var mongo24_or_greater = false; before(function(done) { start.mongodVersion(function(err, version) { @@ -2614,139 +2617,139 @@ describe('geo-spatial', function() { } }); }); -}); -describe('lean option:', function() { - it('find', function(done) { - var db = start(), - BlogPostB = db.model('BlogPostB', collection), - title = 'Wooooot ' + random(); + describe('lean', function() { + it('find', function(done) { + var db = start(), + BlogPostB = db.model('BlogPostB', collection), + title = 'Wooooot ' + random(); - var post = new BlogPostB(); - post.set('title', title); + var post = new BlogPostB(); + post.set('title', title); - post.save(function(err) { - assert.ifError(err); - BlogPostB.find({title: title}).lean().exec(function(err, docs) { + post.save(function(err) { assert.ifError(err); - assert.equal(docs.length, 1); - assert.strictEqual(docs[0] instanceof mongoose.Document, false); - BlogPostB.find({title: title}, null, {lean: true}, function(err, docs) { + BlogPostB.find({title: title}).lean().exec(function(err, docs) { assert.ifError(err); assert.equal(docs.length, 1); assert.strictEqual(docs[0] instanceof mongoose.Document, false); - db.close(); - done(); + BlogPostB.find({title: title}, null, {lean: true}, function(err, docs) { + assert.ifError(err); + assert.equal(docs.length, 1); + assert.strictEqual(docs[0] instanceof mongoose.Document, false); + db.close(); + done(); + }); }); }); }); - }); - it('findOne', function(done) { - var db = start(), - BlogPostB = db.model('BlogPostB', collection), - title = 'Wooooot ' + random(); + it('findOne', function(done) { + var db = start(), + BlogPostB = db.model('BlogPostB', collection), + title = 'Wooooot ' + random(); - var post = new BlogPostB(); - post.set('title', title); + var post = new BlogPostB(); + post.set('title', title); - post.save(function(err) { - assert.ifError(err); - BlogPostB.findOne({title: title}, null, {lean: true}, function(err, doc) { - db.close(); + post.save(function(err) { assert.ifError(err); - assert.ok(doc); - assert.strictEqual(false, doc instanceof mongoose.Document); - done(); + BlogPostB.findOne({title: title}, null, {lean: true}, function(err, doc) { + db.close(); + assert.ifError(err); + assert.ok(doc); + assert.strictEqual(false, doc instanceof mongoose.Document); + done(); + }); }); }); - }); - it('properly casts nested and/or queries (gh-676)', function(done) { - var sch = new Schema({ - num: Number, - subdoc: {title: String, num: Number} - }); - - var M = mongoose.model('andor' + random(), sch); - - var cond = { - $and: [ - {$or: [{num: '23'}, {'subdoc.num': '45'}]}, - {$and: [{'subdoc.title': 233}, {num: '345'}]} - ] - }; - var q = M.find(cond); - assert.equal(typeof q._conditions.$and[0].$or[0].num, 'number'); - assert.equal(typeof q._conditions.$and[0].$or[1]['subdoc.num'], 'number'); - assert.equal(typeof q._conditions.$and[1].$and[0]['subdoc.title'], 'string'); - assert.equal(typeof q._conditions.$and[1].$and[1].num, 'number'); - done(); - }); - it('properly casts deeply nested and/or queries (gh-676)', function(done) { - var sch = new Schema({ - num: Number, - subdoc: {title: String, num: Number} + it('properly casts nested and/or queries (gh-676)', function(done) { + var sch = new Schema({ + num: Number, + subdoc: {title: String, num: Number} + }); + + var M = mongoose.model('andor' + random(), sch); + + var cond = { + $and: [ + {$or: [{num: '23'}, {'subdoc.num': '45'}]}, + {$and: [{'subdoc.title': 233}, {num: '345'}]} + ] + }; + var q = M.find(cond); + assert.equal(typeof q._conditions.$and[0].$or[0].num, 'number'); + assert.equal(typeof q._conditions.$and[0].$or[1]['subdoc.num'], 'number'); + assert.equal(typeof q._conditions.$and[1].$and[0]['subdoc.title'], 'string'); + assert.equal(typeof q._conditions.$and[1].$and[1].num, 'number'); + done(); }); + it('properly casts deeply nested and/or queries (gh-676)', function(done) { + var sch = new Schema({ + num: Number, + subdoc: {title: String, num: Number} + }); - var M = mongoose.model('andor' + random(), sch); + var M = mongoose.model('andor' + random(), sch); - var cond = { - $and: [{$or: [{$and: [{$or: [{num: '12345'}, {'subdoc.num': '56789'}]}]}]}] - }; - var q = M.find(cond); - assert.equal(typeof q._conditions.$and[0].$or[0].$and[0].$or[0].num, 'number'); - assert.equal(typeof q._conditions.$and[0].$or[0].$and[0].$or[1]['subdoc.num'], 'number'); - done(); - }); + var cond = { + $and: [{$or: [{$and: [{$or: [{num: '12345'}, {'subdoc.num': '56789'}]}]}]}] + }; + var q = M.find(cond); + assert.equal(typeof q._conditions.$and[0].$or[0].$and[0].$or[0].num, 'number'); + assert.equal(typeof q._conditions.$and[0].$or[0].$and[0].$or[1]['subdoc.num'], 'number'); + done(); + }); - it('casts $elemMatch (gh-2199)', function(done) { - var db = start(); - var schema = new Schema({dates: [Date]}); - var Dates = db.model('Date', schema, 'dates'); + it('casts $elemMatch (gh-2199)', function(done) { + var db = start(); + var schema = new Schema({dates: [Date]}); + var Dates = db.model('Date', schema, 'dates'); - var array = ['2014-07-01T02:00:00.000Z', '2014-07-01T04:00:00.000Z']; - Dates.create({dates: array}, function(err) { - assert.ifError(err); - var elemMatch = {$gte: '2014-07-01T03:00:00.000Z'}; - Dates.findOne({}, {dates: {$elemMatch: elemMatch}}, function(err, doc) { + var array = ['2014-07-01T02:00:00.000Z', '2014-07-01T04:00:00.000Z']; + Dates.create({dates: array}, function(err) { assert.ifError(err); - assert.equal(doc.dates.length, 1); - assert.equal(doc.dates[0].getTime(), - new Date('2014-07-01T04:00:00.000Z').getTime()); - db.close(done); + var elemMatch = {$gte: '2014-07-01T03:00:00.000Z'}; + Dates.findOne({}, {dates: {$elemMatch: elemMatch}}, function(err, doc) { + assert.ifError(err); + assert.equal(doc.dates.length, 1); + assert.equal(doc.dates[0].getTime(), + new Date('2014-07-01T04:00:00.000Z').getTime()); + db.close(done); + }); }); }); - }); - describe('$eq', function() { - var mongo26 = false; + describe('$eq', function() { + var mongo26 = false; - before(function(done) { - start.mongodVersion(function(err, version) { - if (err) { - return done(err); - } - mongo26 = version[0] > 2 || (version[0] === 2 && version[1] >= 6); - done(); + before(function(done) { + start.mongodVersion(function(err, version) { + if (err) { + return done(err); + } + mongo26 = version[0] > 2 || (version[0] === 2 && version[1] >= 6); + done(); + }); }); - }); - it('casts $eq (gh-2752)', function(done) { - var db = start(); - var BlogPostB = db.model('BlogPostB', collection); + it('casts $eq (gh-2752)', function(done) { + var db = start(); + var BlogPostB = db.model('BlogPostB', collection); - BlogPostB.findOne( - {_id: {$eq: '000000000000000000000001'}, numbers: {$eq: [1, 2]}}, - function(err, doc) { - if (mongo26) { - assert.ifError(err); - } else { - assert.ok(err.toString().indexOf('MongoError') !== -1); - } + BlogPostB.findOne( + {_id: {$eq: '000000000000000000000001'}, numbers: {$eq: [1, 2]}}, + function(err, doc) { + if (mongo26) { + assert.ifError(err); + } else { + assert.ok(err.toString().indexOf('MongoError') !== -1); + } - assert.ok(!doc); - db.close(done); - }); + assert.ok(!doc); + db.close(done); + }); + }); }); }); }); From 608599ed25021b03ad0fc0cc327932d00d67b46e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 23 Mar 2017 16:09:31 -0600 Subject: [PATCH 1353/2240] refactor(model): make sharding into a plugin instead of core Fix #5105 --- .eslintignore | 1 + lib/document.js | 39 ------------------ lib/index.js | 3 +- lib/model.js | 15 +------ lib/plugins/sharding.js | 71 ++++++++++++++++++++++++++++++++ lib/schema.js | 7 ++++ package.json | 1 + test/connection.test.js | 58 -------------------------- test/document.unit.test.js | 6 ++- test/model.discriminator.test.js | 2 +- test/shard.test.js | 31 ++++---------- tools/sharded.js | 42 +++++++++++++++++++ 12 files changed, 137 insertions(+), 139 deletions(-) create mode 100644 lib/plugins/sharding.js create mode 100644 tools/sharded.js diff --git a/.eslintignore b/.eslintignore index b1109fb5b0a..cda1980998b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ docs/ bin/ test/triage/ test/model.discriminator.test.js +tools/ diff --git a/lib/document.js b/lib/document.js index 2118cca83d0..83d232d7c7e 100644 --- a/lib/document.js +++ b/lib/document.js @@ -328,7 +328,6 @@ Document.prototype.init = function(doc, opts, fn) { } init(this, doc, this._doc); - this.$__storeShard(); this.emit('init', this); this.constructor.emit('init', this); @@ -414,44 +413,6 @@ function init(self, obj, doc, prefix) { } } -/** - * Stores the current values of the shard keys. - * - * ####Note: - * - * _Shard key values do not / are not allowed to change._ - * - * @api private - * @method $__storeShard - * @memberOf Document - */ - -Document.prototype.$__storeShard = function() { - // backwards compat - var key = this.schema.options.shardKey || this.schema.options.shardkey; - if (!(key && utils.getFunctionName(key.constructor) === 'Object')) { - return; - } - - var orig = this.$__.shardval = {}, - paths = Object.keys(key), - len = paths.length, - val; - - for (var i = 0; i < len; ++i) { - val = this.getValue(paths[i]); - if (isMongooseObject(val)) { - orig[paths[i]] = val.toObject({depopulate: true, _isNested: true}); - } else if (val !== null && val !== undefined && val.valueOf && - // Explicitly don't take value of dates - (!val.constructor || utils.getFunctionName(val.constructor) !== 'Date')) { - orig[paths[i]] = val.valueOf(); - } else { - orig[paths[i]] = val; - } - } -}; - /*! * Set up middleware support */ diff --git a/lib/index.js b/lib/index.js index e0c644557e6..fa2316a40a4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -20,6 +20,7 @@ var querystring = require('querystring'); var Aggregate = require('./aggregate'); var PromiseProvider = require('./promise_provider'); +var shardingPlugin = require('./plugins/sharding'); /** * Mongoose constructor. @@ -32,7 +33,7 @@ var PromiseProvider = require('./promise_provider'); function Mongoose() { this.connections = []; - this.plugins = []; + this.plugins = [[shardingPlugin, {}]]; this.models = {}; this.modelSchemas = {}; // default global options diff --git a/lib/model.js b/lib/model.js index 6ea5c2e75b0..7d931c45503 100644 --- a/lib/model.js +++ b/lib/model.js @@ -224,7 +224,6 @@ Model.prototype.$__save = function(options, callback) { } _this.$__reset(); - _this.$__storeShard(); var numAffected = 0; if (result) { @@ -674,7 +673,7 @@ Model.prototype.increment = function increment() { }; /** - * Returns a query object which applies shardkeys if they exist. + * Returns a query object * * @api private * @method $__where @@ -684,22 +683,10 @@ Model.prototype.increment = function increment() { Model.prototype.$__where = function _where(where) { where || (where = {}); - var paths, - len; - if (!where._id) { where._id = this._doc._id; } - if (this.$__.shardval) { - paths = Object.keys(this.$__.shardval); - len = paths.length; - - for (var i = 0; i < len; ++i) { - where[paths[i]] = this.$__.shardval[paths[i]]; - } - } - if (this._doc._id == null) { return new Error('No _id found on document!'); } diff --git a/lib/plugins/sharding.js b/lib/plugins/sharding.js new file mode 100644 index 00000000000..4a2f85ea1fe --- /dev/null +++ b/lib/plugins/sharding.js @@ -0,0 +1,71 @@ +'use strict'; + +var utils = require('../utils'); + +module.exports = function shardingPlugin(schema) { + schema.post('init', function() { + storeShard.call(this); + return this; + }); + schema.pre('save', function(next) { + applyWhere.call(this); + next(); + }); + schema.post('save', function() { + storeShard.call(this); + }); +}; + +function applyWhere() { + var paths; + var len; + + if (this.$__.shardval) { + paths = Object.keys(this.$__.shardval); + len = paths.length; + + this.$where = this.$where || {}; + for (var i = 0; i < len; ++i) { + this.$where[paths[i]] = this.$__.shardval[paths[i]]; + } + } +} + +/*! + * Stores the current values of the shard keys. + * + * ####Note: + * + * _Shard key values do not / are not allowed to change._ + * + * @api private + * @method $__storeShard + * @memberOf Document + */ +module.exports.storeShard = storeShard; + +function storeShard() { + // backwards compat + var key = this.schema.options.shardKey || this.schema.options.shardkey; + if (!(key && utils.getFunctionName(key.constructor) === 'Object')) { + return; + } + + var orig = this.$__.shardval = {}, + paths = Object.keys(key), + len = paths.length, + val; + + for (var i = 0; i < len; ++i) { + val = this.getValue(paths[i]); + if (utils.isMongooseObject(val)) { + orig[paths[i]] = val.toObject({depopulate: true, _isNested: true}); + } else if (val !== null && val !== undefined && val.valueOf && + // Explicitly don't take value of dates + (!val.constructor || utils.getFunctionName(val.constructor) !== 'Date')) { + orig[paths[i]] = val.valueOf(); + } else { + orig[paths[i]] = val; + } + } +} diff --git a/lib/schema.js b/lib/schema.js index 27b97a91bf7..179c05efb94 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -86,6 +86,7 @@ function Schema(obj, options) { this.tree = {}; this.query = {}; this.childSchemas = []; + this.plugins = []; this.s = { hooks: new Kareem(), @@ -1179,6 +1180,12 @@ Schema.prototype.post = function(method, fn) { */ Schema.prototype.plugin = function(fn, opts) { + if (opts && + opts.deduplicate && + this.plugins.find(function(p) { return p.fn === fn; })) { + return this; + } + this.plugins.push({ fn: fn, opts: opts }); fn(this, opts); return this; }; diff --git a/package.json b/package.json index 64480c7d5d2..53d743a3ad6 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "marked": "0.3.6", "mocha": "3.2.0", "mongoose-long": "0.1.1", + "mongodb-topology-manager": "1.0.11", "node-static": "0.7.7", "power-assert": "1.4.1", "q": "1.4.1", diff --git a/test/connection.test.js b/test/connection.test.js index 2ddd6361da5..425b4fcb6e8 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -141,11 +141,6 @@ describe('connections:', function() { var mongod = 'mongodb://localhost:27017'; - var repl1 = process.env.MONGOOSE_SET_TEST_URI; - var repl2 = repl1.replace('mongodb://', '').split(','); - repl2.push(repl2.shift()); - repl2 = 'mongodb://' + repl2.join(','); - describe('with different host/port', function() { it('non-replica set', function(done) { var db = mongoose.createConnection(); @@ -195,59 +190,6 @@ describe('connections:', function() { }); }); }); - - it('replica set', function(done) { - var db = mongoose.createConnection(); - - db.openSet(repl1, function(err) { - if (err) { - return done(err); - } - - var hosts = db.hosts.slice(); - var db1 = db.db; - - db.close(function(err) { - if (err) { - return done(err); - } - - db.openSet(repl2, function(err) { - if (err) { - return done(err); - } - - db.hosts.forEach(function(host, i) { - assert.notEqual(host.port, hosts[i].port); - }); - assert.ok(db1 !== db.db); - - hosts = db.hosts.slice(); - var db2 = db.db; - - db.close(function(err) { - if (err) { - return done(err); - } - - db.openSet(repl1, function(err) { - if (err) { - return done(err); - } - - db.hosts.forEach(function(host, i) { - assert.notEqual(host.port, hosts[i].port); - }); - assert.ok(db2 !== db.db); - - db.close(); - done(); - }); - }); - }); - }); - }); - }); }); }); diff --git a/test/document.unit.test.js b/test/document.unit.test.js index 6f491d3a201..3f9748c0a6f 100644 --- a/test/document.unit.test.js +++ b/test/document.unit.test.js @@ -2,8 +2,10 @@ * Module dependencies. */ -var start = require('./common'); var assert = require('power-assert'); +var start = require('./common'); +var storeShard = require('../lib/plugins/sharding').storeShard; + var mongoose = start.mongoose; describe('sharding', function() { @@ -22,7 +24,7 @@ describe('sharding', function() { var currentTime = new Date(); d._doc = {date: currentTime}; - d.$__storeShard(); + storeShard.call(d); assert.equal(d.$__.shardval.date, currentTime); done(); }); diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 26bae1ab58b..6c102041ad3 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -315,7 +315,7 @@ describe('model', function() { }); it('merges callQueue with base queue defined before discriminator types callQueue', function(done) { - assert.equal(Employee.schema.callQueue.length, 5); + assert.equal(Employee.schema.callQueue.length, 8); // PersonSchema.post('save') assert.strictEqual(Employee.schema.callQueue[0], Person.schema.callQueue[0]); diff --git a/test/shard.test.js b/test/shard.test.js index 2dee21ecd19..ee69b986b46 100644 --- a/test/shard.test.js +++ b/test/shard.test.js @@ -14,11 +14,6 @@ if (!uri) { 'Sharding must already be enabled on your database', '\033[39m' ); - - // let expresso shut down this test - exports.r = function expressoHack() { - }; - return; } var schema = new Schema({ @@ -62,29 +57,17 @@ describe('shard', function() { cmd.shardcollection = db.name + '.' + collection; cmd.key = P.schema.options.shardkey; - P.db.db.executeDbAdminCommand(cmd, function(err, res) { + P.db.db.executeDbAdminCommand(cmd, function(err) { assert.ifError(err); - if (!(res && res.documents && res.documents[0] && res.documents[0].ok)) { - err = new Error('could not shard test collection ' - + collection + '\n' - + res.documents[0].errmsg + '\n' - + 'Make sure to use a different database than what ' - + 'is used for the MULTI_MONGOS_TEST'); - return done(err); - } - - db.db.admin(function(err, admin) { + db.db.admin().serverStatus(function(err, info) { + db.close(); assert.ifError(err); - admin.serverStatus(function(err, info) { - db.close(); - assert.ifError(err); - version = info.version.split('.').map(function(n) { - return parseInt(n, 10); - }); - greaterThan20x = version[0] > 2 || version[0] === 2 && version[0] > 0; - done(); + version = info.version.split('.').map(function(n) { + return parseInt(n, 10); }); + greaterThan20x = version[0] > 2 || version[0] === 2 && version[0] > 0; + done(); }); }); }); diff --git a/tools/sharded.js b/tools/sharded.js new file mode 100644 index 00000000000..92ec2f1a899 --- /dev/null +++ b/tools/sharded.js @@ -0,0 +1,42 @@ +'use strict'; + +const co = require('co'); + +co(function*() { + var Sharded = require('mongodb-topology-manager').Sharded; + + // Create new instance + var topology = new Sharded({ + mongod: 'mongod', + mongos: 'mongos' + }); + + yield topology.addShard([{ + options: { + bind_ip: 'localhost', port: 31000, dbpath: `${__dirname}/31000` + } + }], { replSet: 'rs1' }); + + yield topology.addConfigurationServers([{ + options: { + bind_ip: 'localhost', port: 35000, dbpath: `${__dirname}/35000` + } + }], { replSet: 'rs0' }); + + yield topology.addProxies([{ + bind_ip: 'localhost', port: 51000, configdb: 'localhost:35000' + }], { + binary: 'mongos' + }); + + // Start up topology + yield topology.start(); + + // Shard db + yield topology.enableSharding('test'); + + console.log('done'); +}).catch(error => { + console.error(error); + process.exit(-1); +}); From dc79ff6dd839b6c60795539ca40cc39c4372d915 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Mar 2017 16:09:37 -0600 Subject: [PATCH 1354/2240] test(querycursor): repro #5096 --- test/query.cursor.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index bbc6cc9a6f4..70617a408c1 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -168,6 +168,26 @@ describe('QueryCursor', function() { done(); }); }); + + it('with pre-find hooks (gh-5096)', function(done) { + var schema = new Schema({ name: String }); + var called = 0; + schema.pre('find', function(next) { + ++called; + next(); + }); + + var Model = db.model('gh5096', schema); + Model.create({ name: 'Test' }, function(error) { + assert.ifError(error); + Model.find().cursor().next(function(error, doc) { + assert.ifError(error); + assert.equal(called, 1); + assert.equal(doc.name, 'Test'); + done(); + }); + }); + }); }); it('as readable stream', function(done) { From 64b4eb10bdf42eae6ebb8fe1200c652f3a46de56 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Mar 2017 16:09:41 -0600 Subject: [PATCH 1355/2240] fix(querycursor): run pre find hooks with .cursor() Fix #5096 --- lib/query.js | 2 ++ lib/querycursor.js | 33 ++++++++++++++++++++------------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/lib/query.js b/lib/query.js index 2578c42bb63..d8b1029680b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3039,6 +3039,8 @@ Query.prototype.stream = util.deprecate(Query.prototype.stream, 'Mongoose: ' + * A QueryCursor exposes a [Streams3](https://strongloop.com/strongblog/whats-new-io-js-beta-streams3/)-compatible * interface, as well as a `.next()` function. * + * The `.cursor()` function triggers pre find hooks, but **not** post find hooks. + * * ####Example * * // There are 2 ways to use a cursor. First, as a stream: diff --git a/lib/querycursor.js b/lib/querycursor.js index 7b4933516bb..919c7d305e3 100644 --- a/lib/querycursor.js +++ b/lib/querycursor.js @@ -13,6 +13,9 @@ var util = require('util'); * in addition to several other mechanisms for loading documents from MongoDB * one at a time. * + * QueryCursors execute the model's pre find hooks, but **not** the model's + * post find hooks. + * * Unless you're an advanced user, do **not** instantiate this class directly. * Use [`Query#cursor()`](/docs/api.html#query_Query-cursor) instead. * @@ -34,16 +37,18 @@ function QueryCursor(query, options) { this._transforms = options.transform ? [options.transform] : []; var _this = this; var model = query.model; - model.collection.find(query._conditions, options, function(err, cursor) { - if (_this._error) { - cursor.close(function() {}); - _this.listeners('error').length > 0 && _this.emit('error', _this._error); - } - if (err) { - return _this.emit('error', err); - } - _this.cursor = cursor; - _this.emit('cursor', cursor); + model.hooks.execPre('find', query, function() { + model.collection.find(query._conditions, options, function(err, cursor) { + if (_this._error) { + cursor.close(function() {}); + _this.listeners('error').length > 0 && _this.emit('error', _this._error); + } + if (err) { + return _this.emit('error', err); + } + _this.cursor = cursor; + _this.emit('cursor', cursor); + }); }); } @@ -245,7 +250,9 @@ function _next(ctx, cb) { var callback = cb; if (ctx._transforms.length) { callback = function(err, doc) { - if (err || doc === null) return cb(err, doc); + if (err || doc === null) { + return cb(err, doc); + } cb(err, ctx._transforms.reduce(function(doc, fn) { return fn(doc); }, doc)); @@ -259,7 +266,7 @@ function _next(ctx, cb) { } if (ctx.cursor) { - ctx.cursor.next(function(error, doc) { + return ctx.cursor.next(function(error, doc) { if (error) { return callback(error); } @@ -291,7 +298,7 @@ function _next(ctx, cb) { }); } else { ctx.once('cursor', function() { - _next(ctx, callback); + _next(ctx, cb); }); } } From 2bbc59eb8dfe9aa9ea525946be850560e6073baa Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Mar 2017 17:08:26 -0600 Subject: [PATCH 1356/2240] test(document): repro #5085 --- test/document.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 126bc00b53c..1793bd7ce0a 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3870,6 +3870,32 @@ describe('document', function() { }); }); + it('post hooks on child subdocs run after save (gh-5085)', function(done) { + var ChildModelSchema = new mongoose.Schema({ + text: { + type: String + } + }); + ChildModelSchema.post('save', function(doc) { + doc.text = 'bar'; + }); + var ParentModelSchema = new mongoose.Schema({ + children: [ChildModelSchema] + }); + + var Model = db.model('gh5085', ParentModelSchema); + + Model.create({ children: [{ text: 'test' }] }, function(error) { + assert.ifError(error); + Model.findOne({}, function(error, doc) { + assert.ifError(error); + assert.equal(doc.children.length, 1); + assert.equal(doc.children[0].text, 'test'); + done(); + }); + }); + }); + it('nested docs toObject() clones (gh-5008)', function(done) { var schema = new mongoose.Schema({ sub: { From aae7c571933aa8622685e40149fd54d337b2b291 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Mar 2017 17:09:48 -0600 Subject: [PATCH 1357/2240] fix(document): ensure subdoc post save runs after parent save Fix #5085 --- lib/types/embedded.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 14f1628f40d..0295c856f1c 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -34,6 +34,10 @@ function EmbeddedDocument(obj, parentArr, skipId, fields, index) { this.on('isNew', function(val) { _this.isNew = val; }); + + _this.on('save', function() { + _this.constructor.emit('save', _this); + }); } /*! @@ -110,12 +114,9 @@ EmbeddedDocument.prototype.populate = function() { EmbeddedDocument.prototype.save = function(fn) { var Promise = PromiseProvider.get(); - var _this = this; return new Promise.ES6(function(resolve) { fn && fn(); resolve(); - _this.emit('save', _this); - _this.constructor.emit('save', _this); }); }; From 70c6fd9ea50a297451b52fbc9ee87ba32aa8fa4d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Mar 2017 17:25:09 -0600 Subject: [PATCH 1358/2240] fix(discriminator): handle class names consistently Fix #5104 --- lib/model.js | 15 ++++++--------- lib/schema/documentarray.js | 5 +++++ lib/services/model/discriminator.js | 11 +++-------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/lib/model.js b/lib/model.js index 6ea5c2e75b0..c5b071bb7b2 100644 --- a/lib/model.js +++ b/lib/model.js @@ -829,22 +829,19 @@ Model.prototype.model = function model(name) { */ Model.discriminator = function(name, schema) { + if (typeof name === 'function') { + name = utils.getFunctionName(name); + } + schema = discriminator(this, name, schema); if (this.db.models[name]) { throw new OverwriteModelError(name); } - var _name; - if (typeof name === 'function') { - _name = utils.getFunctionName(name); - } else { - _name = name; - } - schema.$isRootDiscriminator = true; - this.discriminators[_name] = this.db.model(name, schema, this.collection.name); - var d = this.discriminators[_name]; + this.discriminators[name] = this.db.model(name, schema, this.collection.name); + var d = this.discriminators[name]; d.prototype.__proto__ = this.prototype; Object.defineProperty(d, 'baseModelName', { value: this.modelName, diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 7b71cf022bc..8e88816fcef 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -13,6 +13,7 @@ var Subdocument = require('../types/embedded'); var applyHooks = require('../services/model/applyHooks'); var discriminator = require('../services/model/discriminator'); var util = require('util'); +var utils = require('../utils'); /** * SubdocsArray SchemaType constructor @@ -101,6 +102,10 @@ function _createConstructor(schema, options) { */ DocumentArray.prototype.discriminator = function(name, schema) { + if (typeof name === 'function') { + name = utils.getFunctionName(name); + } + schema = discriminator(this.casterConstructor, name, schema); var EmbeddedDocument = _createConstructor(schema); diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index c4345f27b47..c6b18da8f4a 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -22,11 +22,6 @@ module.exports = function discriminator(model, name, schema) { model.base._applyPlugins(schema); } - var _name = name; - if (typeof name === 'function') { - _name = utils.getFunctionName(name); - } - if (model.schema.discriminatorMapping && !model.schema.discriminatorMapping.isRoot) { throw new Error('Discriminator "' + name + @@ -44,10 +39,10 @@ module.exports = function discriminator(model, name, schema) { var obj = {}; obj[key] = { - default: _name, + default: name, set: function(newName) { - if (newName === _name) { - return _name; + if (newName === name) { + return name; } throw new Error('Can\'t set discriminator key "' + key + '"'); } From 2dd76ab803b809ab7be2b6881256a6527fd3e11c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 25 Mar 2017 17:41:47 -0600 Subject: [PATCH 1359/2240] fix(connection): throw error if username:password includes @ or : Re: #5091 --- lib/connection.js | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 1cd17c4e44b..c2cd448934a 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -177,6 +177,7 @@ Connection.prototype.config; Connection.prototype.open = function(host, database, port, options, callback) { var parsed; var Promise = PromiseProvider.get(); + var err; if (typeof database === 'string') { switch (arguments.length) { @@ -236,7 +237,7 @@ Connection.prototype.open = function(host, database, port, options, callback) { // make sure we can open if (STATES.disconnected !== this.readyState) { - var err = new Error('Trying to open unclosed connection.'); + err = new Error('Trying to open unclosed connection.'); err.state = this.readyState; this.error(err, callback); return new Promise.ES6(function(resolve, reject) { @@ -245,14 +246,16 @@ Connection.prototype.open = function(host, database, port, options, callback) { } if (!host) { - this.error(new Error('Missing hostname.'), callback); + err = new Error('Missing hostname.'); + this.error(err, callback); return new Promise.ES6(function(resolve, reject) { reject(err); }); } if (!database) { - this.error(new Error('Missing database name.'), callback); + err = new Error('Missing database name.'); + this.error(err, callback); return new Promise.ES6(function(resolve, reject) { reject(err); }); @@ -269,7 +272,23 @@ Connection.prototype.open = function(host, database, port, options, callback) { // Check hostname for user/pass } else if (/@/.test(host) && /:/.test(host.split('@')[0])) { host = host.split('@'); + if (host.length > 2) { + err = new Error('Username and password must be URI encoded if they ' + + 'contain "@", see http://bit.ly/2nRYRyq'); + this.error(err, callback); + return new Promise.ES6(function(resolve, reject) { + reject(err); + }); + } var auth = host.shift().split(':'); + if (auth.length > 2) { + err = new Error('Username and password must be URI encoded if they ' + + 'contain ":", see http://bit.ly/2nRYRyq'); + this.error(err, callback); + return new Promise.ES6(function(resolve, reject) { + reject(err); + }); + } host = host.pop(); this.user = auth[0]; this.pass = auth[1]; From 3d62d3558c15ec852bdeaab1a5138b1853b4f7cb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Mar 2017 17:30:03 -0600 Subject: [PATCH 1360/2240] feat(model): pass params to pre hooks Fix #5064 --- lib/model.js | 5 ++++- package.json | 2 +- test/model.test.js | 12 ++++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/model.js b/lib/model.js index c5b071bb7b2..598717b835a 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3609,7 +3609,10 @@ Model.compile = function compile(name, schema, collectionName, connection, base) model.Query.base = Query.base; applyQueryMethods(model, schema.query); - var kareemOptions = { useErrorHandlers: true }; + var kareemOptions = { + useErrorHandlers: true, + numCallbackParams: 1 + }; model.$__insertMany = model.hooks.createWrapper('insertMany', model.insertMany, model, kareemOptions); model.insertMany = function(arr, options, callback) { diff --git a/package.json b/package.json index 64480c7d5d2..04e5065af27 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "2.1.4", "bson": "~1.0.4", "hooks-fixed": "2.0.0", - "kareem": "1.2.1", + "kareem": "1.3.0", "mongodb": "2.2.25", "mpath": "0.2.1", "mpromise": "0.5.5", diff --git a/test/model.test.js b/test/model.test.js index 667eefd74b5..d9573c1802f 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5345,7 +5345,15 @@ describe('Model', function() { }); var calledPre = 0; var calledPost = 0; - schema.pre('insertMany', function(next) { + schema.pre('insertMany', function(next, docs) { + assert.equal(docs.length, 2); + assert.equal(docs[0].name, 'Star Wars'); + ++calledPre; + next(); + }); + schema.pre('insertMany', function(next, docs) { + assert.equal(docs.length, 2); + assert.equal(docs[0].name, 'Star Wars'); ++calledPre; next(); }); @@ -5358,7 +5366,7 @@ describe('Model', function() { Movie.insertMany(arr, function(error, docs) { assert.ifError(error); assert.equal(docs.length, 2); - assert.equal(calledPre, 1); + assert.equal(calledPre, 2); assert.equal(calledPost, 1); done(); }); From 53a9d826e24961e8f4798fff430182bb4041a48a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Mar 2017 17:34:53 -0600 Subject: [PATCH 1361/2240] test: dont run shard tests if uri not set --- test/shard.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/shard.test.js b/test/shard.test.js index ee69b986b46..9d11710668c 100644 --- a/test/shard.test.js +++ b/test/shard.test.js @@ -14,6 +14,8 @@ if (!uri) { 'Sharding must already be enabled on your database', '\033[39m' ); + + return; } var schema = new Schema({ From fcff38ef46b0bc91933c2f69d88439b15d0d9b39 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Mar 2017 17:39:33 -0600 Subject: [PATCH 1362/2240] chore: release 4.9.2 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index bc4228c70eb..546a94be95d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.9.2 / 2017-03-26 +================== + * fix(discriminator): handle class names consistently #5104 + * fix(schema): make clone() work with reusing discriminator schemas #5098 + * fix(querycursor): run pre find hooks with .cursor() #5096 + * fix(connection): throw error if username:password includes @ or : #5091 + * fix(timestamps): handle overwriting createdAt+updatedAt consistently #5088 + * fix(document): ensure subdoc post save runs after parent save #5085 + * docs(model): improve update docs #5076 [bertolo1988](https://github.com/bertolo1988) + 4.9.1 / 2017-03-19 ================== * fix(query): handle $type for arrays #5080 #5079 [zoellner](https://github.com/zoellner) diff --git a/package.json b/package.json index 64480c7d5d2..4ef945a2266 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.2-pre", + "version": "4.9.2", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 541294aaf68c007233c3c0b88eab40dcee26b51d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Mar 2017 17:46:23 -0600 Subject: [PATCH 1363/2240] chore: now working on 4.9.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4ef945a2266..60dcad944ec 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.2", + "version": "4.9.3-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 69676870587c1b7f18e4f4df2ab4ce6853e2c9f2 Mon Sep 17 00:00:00 2001 From: Julien Vanier Date: Tue, 28 Mar 2017 10:12:23 -0400 Subject: [PATCH 1364/2240] Avoid exception on constructor check I was pushing object created by `Object.create(null);` into an array so the prototype is `undefined` which causes `Cannot read property 'baseCasterConstructor' of undefined`. Check that the prototype is defined first. --- lib/types/documentarray.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/documentarray.js b/lib/types/documentarray.js index 1c485b5540a..475396c27af 100644 --- a/lib/types/documentarray.js +++ b/lib/types/documentarray.js @@ -102,7 +102,7 @@ MongooseDocumentArray.mixin = { var Constructor = this._schema.casterConstructor; if (value instanceof Constructor || // Hack re: #5001, see #5005 - (value && value.constructor.baseCasterConstructor === Constructor)) { + (value && value.constructor && value.constructor.baseCasterConstructor === Constructor)) { if (!(value.__parent && value.__parentArray)) { // value may have been created using array.create() value.__parent = this._parent; From 65f6178f467bc181a88a370262a963b02c85d0e2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 28 Mar 2017 18:47:57 -0600 Subject: [PATCH 1365/2240] docs(schematype): explain how to use `isAsync` with validate() Fix #5125 --- lib/schematype.js | 35 +++++++++++++++++++--------------- test/schema.validation.test.js | 28 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/lib/schematype.js b/lib/schematype.js index b19ac365289..258e980e224 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -406,21 +406,26 @@ SchemaType.prototype.get = function(fn) { * * Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first argument passed to the validator function is the value being validated. The second argument is a callback function that must called when you finish validating the value and passed either `true` or `false` to communicate either success or failure respectively. * - * schema.path('name').validate(function (value, respond) { - * doStuff(value, function () { - * ... - * respond(false); // validation failed - * }) - * }, '{PATH} failed validation.'); - * - * // or with dynamic message - * - * schema.path('name').validate(function (value, respond) { - * doStuff(value, function () { - * ... - * respond(false, 'this message gets to the validation error'); - * }); - * }, 'this message does not matter'); + * schema.path('name').validate({ + * isAsync: true, + * validator: function (value, respond) { + * doStuff(value, function () { + * ... + * respond(false); // validation failed + * }); + * }, + * message: 'Custom error message!' // Optional + * }); + * + * // Can also return a promise + * schema.path('name').validate({ + * isAsync: true, + * validator: function (value, respond) { + * return new Promise(resolve => { + * resolve(false); // validation failed + * }); + * } + * }); * * You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs. * diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index c69954ef346..b48cef24850 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -653,6 +653,34 @@ describe('schema', function() { }); }); + it('custom validators with isAsync and .validate() (gh-5125)', function(done) { + var validate = function(v, opts) { + // Make eslint not complain about unused vars + return !!(v && opts && false); + }; + + var schema = new Schema({ + x: { + type: String + } + }); + + schema.path('x').validate({ + isAsync: false, + validator: validate, + message: 'Custom error message!' + }); + var M = mongoose.model('gh5125', schema); + + var m = new M({x: 'test'}); + + m.validate(function(err) { + assert.ok(err.errors['x']); + assert.equal(err.errors['x'].message, 'Custom error message!'); + done(); + }); + }); + it('supports custom properties (gh-2132)', function(done) { var schema = new Schema({ x: { From eee1f04fd3503440d440503bb43576929c41df74 Mon Sep 17 00:00:00 2001 From: "K. Rodman Mannix" Date: Wed, 29 Mar 2017 13:30:03 +0000 Subject: [PATCH 1366/2240] document.js fixes for functions prepended with `$` --- lib/document.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 2118cca83d0..4635f787456 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1048,6 +1048,8 @@ Document.prototype.unmarkModified = function(path) { * doc.$ignore('foo'); * doc.save() // changes to foo will not be persisted and validators won't be run * + * @memberOf Document + * @method $ignore * @param {String} path the path to ignore * @api public */ @@ -1120,11 +1122,12 @@ Document.prototype.isModified = function(paths) { * * MyModel = mongoose.model('test', { name: { type: String, default: 'Val '} }); * var m = new MyModel(); - * m.$isDefault('name'); // true + * m.$isDefault('name'); // true * + * @memberOf Document + * @method $isDefault * @param {String} [path] * @return {Boolean} - * @method $isDefault * @api public */ From 0a032886490788a8d0b185ab60e0695b031f6e3d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Mar 2017 22:16:21 -0600 Subject: [PATCH 1367/2240] docs(discriminator): use message in discriminator docs re: #5113 --- test/docs/discriminators.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index e43003f0eeb..387a5c524ef 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -318,8 +318,8 @@ describe('discriminator docs', function () { // Create a new batch of events with different kinds var batch = { events: [ - { kind: 'Clicked', element: '#hero' }, - { kind: 'Purchased', product: 'action-figure-1' } + { kind: 'Clicked', element: '#hero', message: 'hello' }, + { kind: 'Purchased', product: 'action-figure-1', message: 'world' } ] }; @@ -328,9 +328,11 @@ describe('discriminator docs', function () { assert.equal(doc.events.length, 2); assert.equal(doc.events[0].element, '#hero'); + assert.equal(doc.events[0].message, 'hello'); assert.ok(doc.events[0] instanceof Clicked); assert.equal(doc.events[1].product, 'action-figure-1'); + assert.equal(doc.events[1].message, 'world'); assert.ok(doc.events[1] instanceof Purchased); doc.events.push({ kind: 'Purchased', product: 'action-figure-2' }); From 2d6bf66d17e6a78a992ccbeedb69be0cab543894 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Mar 2017 22:34:48 -0600 Subject: [PATCH 1368/2240] test(document): repro #5063 --- test/document.isselected.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/document.isselected.test.js b/test/document.isselected.test.js index 3573c29cf65..9d2846fdeb5 100644 --- a/test/document.isselected.test.js +++ b/test/document.isselected.test.js @@ -331,4 +331,29 @@ describe('document', function() { done(); }); + + it('isDirectSelected (gh-5063)', function(done) { + var selection = { + test: 1, + numbers: 1, + 'nested.deep': 1, + oids: 1 + }; + + var doc = new TestDocument(undefined, selection); + + doc.init({ + test: 'test', + numbers: [4, 5, 6, 7], + nested: { + deep: {x: 'a string'} + } + }); + + assert.ok(doc.isDirectSelected('nested.deep')); + assert.ok(!doc.isDirectSelected('nested.cool')); + assert.ok(!doc.isDirectSelected('nested')); + + done(); + }); }); From 04fb701cf7cebefdef08b6a5ea798152cdbc11d8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Mar 2017 22:35:13 -0600 Subject: [PATCH 1369/2240] feat(document): add isDirectSelected() to minimize isSelected() changes Fix #5063 --- lib/document.js | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/lib/document.js b/lib/document.js index 2118cca83d0..35a7121929a 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1237,6 +1237,65 @@ Document.prototype.isSelected = function isSelected(path) { return true; }; +/** + * Checks if `path` was explicitly selected. If no projection, always returns + * true. + * + * ####Example + * + * Thing.findOne().select('nested.name').exec(function (err, doc) { + * doc.isDirectSelected('nested.name') // true + * doc.isDirectSelected('nested.otherName') // false + * doc.isDirectSelected('nested') // false + * }) + * + * @param {String} path + * @return {Boolean} + * @api public + */ + +Document.prototype.isDirectSelected = function isDirectSelected(path) { + if (this.$__.selected) { + if (path === '_id') { + return this.$__.selected._id !== 0; + } + + var paths = Object.keys(this.$__.selected); + var i = paths.length; + var inclusive = null; + var cur; + + if (i === 1 && paths[0] === '_id') { + // only _id was selected. + return this.$__.selected._id === 0; + } + + while (i--) { + cur = paths[i]; + if (cur === '_id') { + continue; + } + if (this.$__.selected[cur] && this.$__.selected[cur].$meta) { + continue; + } + inclusive = !!this.$__.selected[cur]; + break; + } + + if (inclusive === null) { + return true; + } + + if (path in this.$__.selected) { + return inclusive; + } + + return !inclusive; + } + + return true; +}; + /** * Executes registered validation rules for this document. * From cede3b437408c3e591ec9a3fbd8c34a5cbece6d9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 31 Mar 2017 10:28:55 -0600 Subject: [PATCH 1370/2240] test(document): repro #5111 --- test/model.update.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 3311246d160..6212e43ced1 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2468,6 +2468,33 @@ describe('model: update:', function() { catch(done); }); + it('does not fail if passing whole doc (gh-5111)', function(done) { + var schema = new Schema({ + fieldOne: String + }, { strict: true }); + var Test = db.model('gh5111', schema); + + Test.create({ fieldOne: 'Test' }). + then(function() { + var data = { fieldOne: 'Test2', fieldTwo: 'Test3' }; + var opts = { + upsert: true, + runValidators: false, + strict: false + }; + return Test.update({}, data, opts); + }). + then(function() { + return Test.findOne(); + }). + then(function(doc) { + assert.equal(doc.fieldOne, 'Test2'); + assert.equal(doc.get('fieldTwo'), 'Test3'); + done(); + }). + catch(done); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From f4d7ad616bd7e80e67ee044225d2b0f0f5a8f32a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 31 Mar 2017 10:28:58 -0600 Subject: [PATCH 1371/2240] fix(document): copy non-objects to _doc when init() Re: #5111 --- lib/document.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/document.js b/lib/document.js index 35a7121929a..3d633f3faf8 100644 --- a/lib/document.js +++ b/lib/document.js @@ -387,6 +387,8 @@ function init(self, obj, doc, prefix) { doc[i] = {}; } init(self, obj[i], doc[i], path + '.'); + } else if (!schema) { + doc[i] = obj[i]; } else { if (obj[i] === null) { doc[i] = null; From 0a7be41a02752fcfc07ccd2425daa0f216f97a9e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 31 Mar 2017 16:49:10 -0600 Subject: [PATCH 1372/2240] docs(schematypes): explain some subtleties with arrays Fix #5059 --- docs/schematypes.jade | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index dbe2fb0f25d..d571844445d 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -231,6 +231,33 @@ block content var Empty2 = new Schema({ any: Array }); var Empty3 = new Schema({ any: [Schema.Types.Mixed] }); var Empty4 = new Schema({ any: [{}] }); + p + | Arrays implicitly have a default value of `[]` (empty array). + :js + var Toy = mongoose.model('Test', ToySchema); + console.log((new Toy()).toys); // [] + p + | To overwrite this default, you need to set the default value to `undefined` + :js + var ToySchema = new Schema({ + toys: { + type: [ToySchema], + default: undefined + } + }); + p + | If an array is marked as `required`, it must have at least one element. + :js + var ToySchema = new Schema({ + toys: { + type: [ToySchema], + required: true + } + }); + var Toy = mongoose.model('Toy', ToySchema); + Toy.create({ toys: [] }, function(error) { + console.log(error.errors['toys'].message); // Path "toys" is required. + }); h3#customtypes Creating Custom Types p | Mongoose can also be extended with custom SchemaTypes. Search the From ca59b9ca7b86830c02f25db47dda1a5b7f5cf97d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Apr 2017 00:14:22 -0600 Subject: [PATCH 1373/2240] test(populate): repro #5114 --- test/model.populate.test.js | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index f019c1ad78f..cb052b6d6a5 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3048,6 +3048,61 @@ describe('model: populate:', function() { }). catch(done); }); + + it('with non-arrays (gh-5114)', function(done) { + var LocationSchema = new Schema({ + name: String + }); + var UserSchema = new Schema({ + name: String, + locationRef: String, + locationIds: { + type: [{ + location: { + type: mongoose.Schema.Types.ObjectId, + refPath: 'locationRef' + } + }] + } + }); + + var Locations = db.model('gh5114', LocationSchema); + var Users = db.model('gh5114_0', UserSchema); + + var location1Id = new mongoose.Types.ObjectId(); + var location2Id = new mongoose.Types.ObjectId(); + + var location1 = { + _id: location1Id, + name: 'loc1' + }; + var location2 = { + _id: location2Id, + name: 'loc2' + }; + var user = { + locationRef: 'gh5114', + locationIds: [ + { location: location1Id }, + { location: location2Id } + ] + }; + + Locations.create([location1, location2]). + then(function() { + return Users.create(user); + }). + then(function() { + return Users.findOne().populate('locationIds.location'); + }). + then(function(doc) { + assert.equal(doc.locationIds.length, 2); + assert.equal(doc.locationIds[0].location.name, 'loc1'); + assert.equal(doc.locationIds[1].location.name, 'loc2'); + done(); + }). + catch(done); + }); }); describe('leaves Documents within Mixed properties alone (gh-1471)', function() { From 12425b52475502d324503b660959489e61cdee65 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Apr 2017 00:14:34 -0600 Subject: [PATCH 1374/2240] fix(populate): only apply refPath duplicate id optimization if not array Fix #5114 --- lib/model.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index aa77b556cef..a3492069fa8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3245,6 +3245,7 @@ function getModelsMapForPopulate(model, docs, options) { var originalOptions = utils.clone(options); var isVirtual = false; + var isRefPathArray = false; schema = model._getSchema(options.path); var isUnderneathDocArray = schema && schema.$isUnderneathDocArray; @@ -3271,7 +3272,8 @@ function getModelsMapForPopulate(model, docs, options) { if (refPath) { modelNames = utils.getValue(refPath, doc); - if (Array.isArray(modelNames)) { + isRefPathArray = Array.isArray(modelNames); + if (isRefPathArray) { modelNames = modelNames.filter(function(v) { return v != null; }); @@ -3348,8 +3350,8 @@ function getModelsMapForPopulate(model, docs, options) { var k = modelNames.length; while (k--) { modelName = modelNames[k]; - var _doc = Array.isArray(doc) && refPath ? doc[k] : doc; - var _ret = Array.isArray(ret) && refPath ? ret[k] : ret; + var _doc = Array.isArray(doc) && isRefPathArray ? doc[k] : doc; + var _ret = Array.isArray(ret) && isRefPathArray ? ret[k] : ret; Model = originalOptions.model && originalOptions.model.modelName ? originalOptions.model : model.db.model(modelName); From f6dd89f07602ea0c6fc62b25632428caa1e46460 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Apr 2017 23:25:13 -0600 Subject: [PATCH 1375/2240] docs(schematype): explain custom message with required function Fix #5123 --- lib/schema/array.js | 2 +- lib/schematype.js | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index dad5cf3b5d9..0eb902fac25 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -114,7 +114,7 @@ SchemaArray.prototype.constructor = SchemaArray; /** * Check if the given value satisfies a required validator. The given value - * must be not null nor undefined, and have a non-zero length. + * must be not null nor undefined, and have a positive length. * * @param {Any} value * @return {Boolean} diff --git a/lib/schematype.js b/lib/schematype.js index 258e980e224..83495f6ef09 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -506,6 +506,28 @@ SchemaType.prototype.validate = function(obj, message, type) { * * var s = new Schema({ born: { type: Date, required: '{PATH} is required!' }) * + * // or with a function + * + * var s = new Schema({ + * userId: ObjectId, + * username: { + * type: String, + * required: function() { return this.userId != null; } + * } + * }) + * + * // or with a function and a custom message + * var s = new Schema({ + * userId: ObjectId, + * username: { + * type: String, + * required: [ + * function() { return this.userId != null; }, + * 'username is required if id is specified' + * ] + * } + * }) + * * // or through the path API * * Schema.path('name').required(true); From 5eb869261f7519ebda36c87a7cbe6cd9edb139b6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Apr 2017 23:39:33 -0600 Subject: [PATCH 1376/2240] perf(populate): dont clone whole options every time Fix #5103 --- lib/model.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index a3492069fa8..01c8f70b13a 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3243,16 +3243,16 @@ function getModelsMapForPopulate(model, docs, options) { modelNameFromQuery = options.model && options.model.modelName || options.model, schema, refPath, Model, currentOptions, modelNames, modelName, discriminatorKey, modelForFindSchema; - var originalOptions = utils.clone(options); + var originalModel = options.model; var isVirtual = false; var isRefPathArray = false; schema = model._getSchema(options.path); var isUnderneathDocArray = schema && schema.$isUnderneathDocArray; if (isUnderneathDocArray && - originalOptions && - originalOptions.options && - originalOptions.options.sort) { + options && + options.options && + options.options.sort) { return new Error('Cannot populate with `sort` on path ' + options.path + ' because it is a subproperty of a document array'); } @@ -3352,8 +3352,8 @@ function getModelsMapForPopulate(model, docs, options) { modelName = modelNames[k]; var _doc = Array.isArray(doc) && isRefPathArray ? doc[k] : doc; var _ret = Array.isArray(ret) && isRefPathArray ? ret[k] : ret; - Model = originalOptions.model && originalOptions.model.modelName ? - originalOptions.model : + Model = originalModel && originalModel.modelName ? + originalModel : model.db.model(modelName); if (!available[modelName]) { From 86d6f732e985a49c1068a40ecba7df8ee576bc7e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Apr 2017 16:21:16 -0600 Subject: [PATCH 1377/2240] chore: release 4.9.3 --- History.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 546a94be95d..0c187c9d807 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,15 @@ +4.9.3 / 2017-04-02 +================== + * docs: document.js fixes for functions prepended with `$` #5131 [krmannix](https://github.com/krmannix) + * fix: Avoid exception on constructor check #5129 [monkbroc](https://github.com/monkbroc) + * docs(schematype): explain how to use `isAsync` with validate() #5125 + * docs(schematype): explain custom message with required function #5123 + * fix(populate): only apply refPath duplicate id optimization if not array #5114 + * fix(document): copy non-objects to doc when init() #5111 + * perf(populate): dont clone whole options every time #5103 + * feat(document): add isDirectSelected() to minimize isSelected() changes #5063 + * docs(schematypes): explain some subtleties with arrays #5059 + 4.9.2 / 2017-03-26 ================== * fix(discriminator): handle class names consistently #5104 diff --git a/package.json b/package.json index 60dcad944ec..f04e6d9d236 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.3-pre", + "version": "4.9.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 12cbd4bf427ad44c50352729856e0fe25882a23e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Apr 2017 16:22:50 -0600 Subject: [PATCH 1378/2240] chore: now working on 4.9.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f04e6d9d236..dd73aff8e5b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.3", + "version": "4.9.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c052e604b09f6f17113ad81f56a7031a264a747b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Apr 2017 21:49:49 -0600 Subject: [PATCH 1379/2240] test(query): add coverage for strict mode with findOneAndUpdate re: #5108 --- test/document.strict.test.js | 4 ++-- test/model.findOneAndUpdate.test.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/test/document.strict.test.js b/test/document.strict.test.js index 49623056f61..8470d59207b 100644 --- a/test/document.strict.test.js +++ b/test/document.strict.test.js @@ -298,7 +298,7 @@ describe('document: strict mode:', function() { var doc = s.toObject(); doc.notInSchema = true; - Strict.collection.insert(doc, {w: 1}, function(err) { + Strict.collection.insert(doc, function(err) { assert.ifError(err); Strict.findById(doc._id, function(err, doc) { @@ -306,7 +306,7 @@ describe('document: strict mode:', function() { assert.equal(doc._doc.bool, true); assert.equal(doc._doc.notInSchema, true); - Strict.update({_id: doc._id}, {$unset: {bool: 1, notInSchema: 1}}, {strict: false, w: 1}, + Strict.update({_id: doc._id}, {$unset: {bool: 1, notInSchema: 1}}, {strict: false}, function(err) { assert.ifError(err); diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 271eebe8b3d..467c7262635 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1781,6 +1781,22 @@ describe('model: findOneAndUpdate:', function() { }); }); + it('strict option (gh-5108)', function(done) { + var modelSchema = new Schema({ field: Number }, { strict: 'throw' }); + + var Model = db.model('gh5108', modelSchema); + Model.findOneAndUpdate({}, { field: 2, otherField: 3 }, { + upsert: true, + strict: false, + new: true + }).exec(function(error, doc) { + assert.ifError(error); + assert.equal(doc.field, 2); + assert.equal(doc.get('otherField'), 3); + done(); + }); + }); + it('should not apply schema transforms (gh-4574)', function(done) { var options = { toObject: { From 7f400a7c86771f656b5cc98ef8b7b1500f986629 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Apr 2017 21:54:35 -0600 Subject: [PATCH 1380/2240] docs(model): add strict option to docs re: #5108 --- lib/model.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/model.js b/lib/model.js index 01c8f70b13a..319bdb5da68 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1503,6 +1503,7 @@ Model.$where = function $where() { * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update * * * ####Examples: @@ -1616,6 +1617,8 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `select`: sets the document fields to return + * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update * * ####Examples: * @@ -1704,6 +1707,8 @@ Model.findByIdAndUpdate = function(id, update, options, callback) { * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0 * - `select`: sets the document fields to return + * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update * * ####Examples: * @@ -1780,6 +1785,8 @@ Model.findOneAndRemove = function(conditions, options, callback) { * * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `select`: sets the document fields to return + * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update * * ####Examples: * From ac61f99e38041b2a46b956974098e7f05e6d8b48 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Apr 2017 21:54:52 -0600 Subject: [PATCH 1381/2240] docs(query): add strict mode option for findOneAndUpdate re: #5108 --- lib/query.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/query.js b/lib/query.js index d8b1029680b..58c45f51469 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1779,6 +1779,8 @@ function prepareDiscriminatorCriteria(query) { * @param {Object|Query} [query] * @param {Object} [doc] * @param {Object} [options] + * @param {Boolean} [options.passRawResult] if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) * @param {Function} [callback] optional params are (error, doc), _unless_ `passRawResult` is used, in which case params are (error, doc, writeOpResult) * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult @@ -1888,6 +1890,8 @@ Query.prototype._findOneAndUpdate = function(callback) { * @memberOf Query * @param {Object} [conditions] * @param {Object} [options] + * @param {Boolean} [options.passRawResult] if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) * @param {Function} [callback] optional params are (error, document) * @return {Query} this * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command From 68a94d004f498c10af41ac7a64f6fc3f58110361 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 3 Apr 2017 14:16:30 -0600 Subject: [PATCH 1382/2240] feat(validation): include failed paths in error message and inspect output Fix #3064 --- lib/error/validation.js | 48 +++++++++++++++++++++++++++------- test/document.test.js | 4 +-- test/model.populate.test.js | 3 ++- test/model.test.js | 2 +- test/schema.validation.test.js | 10 +++---- test/types.buffer.test.js | 6 ++--- 6 files changed, 51 insertions(+), 22 deletions(-) diff --git a/lib/error/validation.js b/lib/error/validation.js index e3322d4942d..c70a5f61901 100644 --- a/lib/error/validation.js +++ b/lib/error/validation.js @@ -14,10 +14,13 @@ var MongooseError = require('../error.js'); function ValidationError(instance) { this.errors = {}; + this._message = ''; if (instance && instance.constructor.name === 'model') { - MongooseError.call(this, instance.constructor.modelName + ' validation failed'); + this._message = instance.constructor.modelName + ' validation failed'; + MongooseError.call(this, this._message); } else { - MongooseError.call(this, 'Validation failed'); + this._message = 'Validation failed'; + MongooseError.call(this, this._message); } if (Error.captureStackTrace) { Error.captureStackTrace(this); @@ -37,24 +40,49 @@ function ValidationError(instance) { ValidationError.prototype = Object.create(MongooseError.prototype); ValidationError.prototype.constructor = MongooseError; +Object.defineProperty(ValidationError.prototype, 'message', { + get: function() { + return this._message + ': ' + _generateMessage(this); + }, + enumerable: true +}); /** * Console.log helper */ ValidationError.prototype.toString = function() { - var ret = this.name + ': '; + return this.name + ': ' + _generateMessage(this); +}; + +/*! + * inspect helper + */ + +ValidationError.prototype.inspect = function() { + return Object.assign(new Error(this.message), this); +}; + +/*! + * ignore + */ + +function _generateMessage(err) { + var keys = Object.keys(err.errors || {}); + var len = keys.length; var msgs = []; + var key; - Object.keys(this.errors || {}).forEach(function(key) { - if (this === this.errors[key]) { - return; + for (var i = 0; i < len; ++i) { + key = keys[i]; + if (err === err.errors[key]) { + continue; } - msgs.push(String(this.errors[key])); - }, this); + msgs.push(key + ': ' + err.errors[key].message); + } - return ret + msgs.join(', '); -}; + return msgs.join(', '); +} /*! * Module exports diff --git a/test/document.test.js b/test/document.test.js index 1793bd7ce0a..053bce18c89 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -1272,7 +1272,7 @@ describe('document', function() { var m = new M({name: 'gh1109-2', arr: [1]}); assert.equal(called, false); m.save(function(err) { - assert.equal(String(err), 'ValidationError: BAM'); + assert.equal(String(err), 'ValidationError: arr: BAM'); assert.equal(called, true); m.arr.push(2); called = false; @@ -1301,7 +1301,7 @@ describe('document', function() { assert.equal(err.errors.arr.message, 'Path `arr` is required.'); m.arr.push({nice: true}); m.save(function(err) { - assert.equal(String(err), 'ValidationError: BAM'); + assert.equal(String(err), 'ValidationError: arr: BAM'); m.arr.push(95); m.save(function(err) { assert.ifError(err); diff --git a/test/model.populate.test.js b/test/model.populate.test.js index cb052b6d6a5..429b80fb5bc 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -2023,7 +2023,8 @@ describe('model: populate:', function() { }); comment.save(function(err) { - assert.equal('CommentWithRequiredField validation failed', err && err.message); + assert.ok(err); + assert.ok(err.message.indexOf('CommentWithRequiredField validation failed') === 0, err.message); assert.ok('num' in err.errors); assert.ok('str' in err.errors); assert.ok('user' in err.errors); diff --git a/test/model.test.js b/test/model.test.js index 667eefd74b5..b6dd6dc7052 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -1139,7 +1139,7 @@ describe('Model', function() { db.close(); assert.equal(err.errors.name.message, 'Name cannot be greater than 1 character for path "name" with value `hi`'); assert.equal(err.name, 'ValidationError'); - assert.equal(err.message, 'IntrospectionValidation validation failed'); + assert.ok(err.message.indexOf('IntrospectionValidation validation failed') !== -1, err.message); done(); }); }); diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index b48cef24850..74dda6b3a5c 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -1031,7 +1031,7 @@ describe('schema', function() { bad.foods = 'waffles'; bad.validate(function(error) { assert.ok(error); - var errorMessage = 'CastError: Cast to Object failed for value ' + + var errorMessage = 'foods: Cast to Object failed for value ' + '"waffles" at path "foods"'; assert.ok(error.toString().indexOf(errorMessage) !== -1, error.toString()); done(); @@ -1045,7 +1045,7 @@ describe('schema', function() { var bad = new Breakfast({}); bad.validate(function(error) { assert.ok(error); - var errorMessage = 'ValidationError: Path `description` is required.'; + var errorMessage = 'ValidationError: description: Path `description` is required.'; assert.equal(errorMessage, error.toString()); done(); }); @@ -1059,7 +1059,7 @@ describe('schema', function() { var error = bad.validateSync(); assert.ok(error); - var errorMessage = 'ValidationError: Path `description` is required.'; + var errorMessage = 'ValidationError: description: Path `description` is required.'; assert.equal(errorMessage, error.toString()); done(); }); @@ -1088,7 +1088,7 @@ describe('schema', function() { var bad = new Breakfast({}); bad.validate(function(error) { assert.ok(error); - var errorMessage = 'ValidationError: Path `description` is required.'; + var errorMessage = 'ValidationError: description: Path `description` is required.'; assert.equal(errorMessage, error.toString()); done(); }); @@ -1106,7 +1106,7 @@ describe('schema', function() { var Breakfast = mongoose.model('gh2832', breakfast, 'gh2832'); Breakfast.create({description: undefined}, function(error) { assert.ok(error); - var errorMessage = 'ValidationError: CastError: Cast to String failed for value "undefined" at path "description"'; + var errorMessage = 'ValidationError: description: Cast to String failed for value "undefined" at path "description"'; assert.equal(errorMessage, error.toString()); assert.ok(error.errors.description); assert.equal(error.errors.description.reason.toString(), 'Error: oops'); diff --git a/test/types.buffer.test.js b/test/types.buffer.test.js index d633d78795f..20944461077 100644 --- a/test/types.buffer.test.js +++ b/test/types.buffer.test.js @@ -69,7 +69,7 @@ describe('types.buffer', function() { }); t.validate(function(err) { - assert.equal(err.message, 'UserBuffer validation failed'); + assert.ok(err.message.indexOf('UserBuffer validation failed') === 0, err.message); assert.equal(err.errors.required.kind, 'required'); t.required = {x: [20]}; t.save(function(err) { @@ -83,11 +83,11 @@ describe('types.buffer', function() { t.sub.push({name: 'Friday Friday'}); t.save(function(err) { - assert.equal(err.message, 'UserBuffer validation failed'); + assert.ok(err.message.indexOf('UserBuffer validation failed') === 0, err.message); assert.equal(err.errors['sub.0.buf'].kind, 'required'); t.sub[0].buf = new Buffer('well well'); t.save(function(err) { - assert.equal(err.message, 'UserBuffer validation failed'); + assert.ok(err.message.indexOf('UserBuffer validation failed') === 0, err.message); assert.equal(err.errors['sub.0.buf'].kind, 'user defined'); assert.equal(err.errors['sub.0.buf'].message, 'valid failed'); From bc8abeaeb332d3614f702a40382d8a86358e74c6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 5 Apr 2017 17:36:41 -0600 Subject: [PATCH 1383/2240] docs(validation): add more detail re: #5119 --- test/docs/validation.test.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 194b4810df6..e2c4c994154 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -73,7 +73,10 @@ describe('validation docs', function() { }, drink: { type: String, - enum: ['Coffee', 'Tea'] + enum: ['Coffee', 'Tea'], + required: function() { + return this.bacon > 3; + } } }); var Breakfast = db.model('Breakfast', breakfastSchema); @@ -90,6 +93,12 @@ describe('validation docs', function() { assert.equal(error.errors['drink'].message, '`Milk` is not a valid enum value for path `drink`.'); + badBreakfast.bacon = 5; + badBreakfast.drink = null; + + error = badBreakfast.validateSync(); + assert.equal(error.errors['drink'].message, 'Path `drink` is required.'); + badBreakfast.bacon = null; error = badBreakfast.validateSync(); assert.equal(error.errors['bacon'].message, 'Why no bacon?'); From 551825e9c9217217b617aa2e7d78a21a05297fe7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 6 Apr 2017 11:19:51 -0600 Subject: [PATCH 1384/2240] test(query): repro #5130 --- test/model.discriminator.test.js | 54 ++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 26bae1ab58b..c53560cf0e9 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -610,6 +610,60 @@ describe('model', function() { catch(done); }); + it('embedded discriminators with $set (gh-5130)', function(done) { + var eventSchema = new Schema({ message: String }, + { discriminatorKey: 'kind' }); + var batchSchema = new Schema({ events: [eventSchema] }); + var docArray = batchSchema.path('events'); + + var Clicked = docArray.discriminator('Clicked', new Schema({ + element: { + type: String, + required: true + } + })); + + var Purchased = docArray.discriminator('Purchased', new Schema({ + product: { + type: String, + required: true + } + })); + + var Batch = db.model('gh5130', batchSchema); + + var batch = { + events: [ + { kind: 'Clicked', element: '#hero' } + ] + }; + + Batch.create(batch). + then(function(doc) { + assert.equal(doc.events.length, 1); + return Batch.updateOne({ _id: doc._id, 'events._id': doc.events[0]._id }, { + $set: { + 'events.$': { + message: 'updated', + kind: 'Clicked', + element: '#hero2' + } + } + }).then(function() { return doc; }); + }). + then(function(doc) { + return Batch.findOne({ _id: doc._id }); + }). + then(function(doc) { + assert.equal(doc.events.length, 1); + assert.equal(doc.events[0].message, 'updated'); + assert.equal(doc.events[0].element, '#hero2'); // <-- test failed + assert.equal(doc.events[0].kind, 'Clicked'); // <-- test failed + done(); + }). + catch(done); + }); + it('embedded in document arrays (gh-2723)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From 1452e1e8f2846d1d58328ffc7bbfa9d87bdfeee8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 6 Apr 2017 11:19:55 -0600 Subject: [PATCH 1385/2240] fix(query): cast .$ update to underlying array type Fix #5130 --- lib/schema.js | 4 ++++ lib/services/query/castUpdate.js | 2 +- test/query.test.js | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 27b97a91bf7..a5e72d3b18d 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1705,6 +1705,10 @@ Schema.prototype._getSchema = function(path) { if (p !== parts.length && foundschema.schema) { var ret; if (parts[p] === '$') { + if (p + 1 === parts.length) { + // comments.$ + return foundschema; + } // comments.$.comments.$.title ret = search(parts.slice(p + 1), foundschema.schema); if (ret) { diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index e0176c27254..53aed3fdf5c 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -171,7 +171,7 @@ function walkUpdatePath(schema, obj, op, strict, pref) { // we should be able to set a schema-less field // to an empty object literal hasKeys |= walkUpdatePath(schema, val, op, strict, prefix + key) || - (utils.isObject(val) && Object.keys(val).length === 0); + (utils.isObject(val) && Object.keys(val).length === 0); } } else { var checkPath = (key === '$each' || key === '$or' || key === '$and') ? diff --git a/test/query.test.js b/test/query.test.js index 26c1ed430cf..7de4713e3f7 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1722,8 +1722,8 @@ describe('Query', function() { {'answers._id': '507f1f77bcf86cd799439011'}, {$set: {'answers.$': answersUpdate}}); - assert.deepEqual(q.getUpdate().$set['answers.$'].stats, - {votes: 1, count: 3}); + assert.deepEqual(q.getUpdate().$set['answers.$'].stats.toObject(), + { votes: 1, count: 3 }); done(); }); From d869ea5d1a173ba2a679703adb2995fd8cb912c5 Mon Sep 17 00:00:00 2001 From: maa105 Date: Sat, 8 Apr 2017 05:07:05 +0300 Subject: [PATCH 1386/2240] fix blue bird "a promise was created in a handler but was not returned from it" if u use the default promise library it wont show. if u use bluebird it is smart enough to catch this warning namely: "Warning: a promise was created in a handler but was not returned from it, see http://goo.gl/rRqMUw" this will resolve this issue here. --- lib/query.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index 58c45f51469..efc5eebb817 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2740,13 +2740,14 @@ Query.prototype.exec = function exec(op, callback) { }); if (callback) { - promise.then( + return promise.then( function() { callback.apply(null, _results); - return null; + return Promise.ES6.resolve(_results); }, function(error) { callback(error); + return Promise.ES6.reject(error); }). catch(function(error) { // If we made it here, we must have an error in the callback re: From 816c132d8e59779b3d439870d856545e87e89f24 Mon Sep 17 00:00:00 2001 From: maa105 Date: Sat, 8 Apr 2017 05:36:10 +0300 Subject: [PATCH 1387/2240] Update query.js --- lib/query.js | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/query.js b/lib/query.js index efc5eebb817..ac60e5f899d 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2742,19 +2742,30 @@ Query.prototype.exec = function exec(op, callback) { if (callback) { return promise.then( function() { - callback.apply(null, _results); - return Promise.ES6.resolve(_results); + var err; + try { + callback.apply(null, _results); + } catch(err) { + // If we made it here, we must have an error in the callback re: + // gh-4500, so we need to emit. + setImmediate(function() { + _this.model.emit('error', err); + }); + } + return _results; }, function(error) { - callback(error); - return Promise.ES6.reject(error); - }). - catch(function(error) { - // If we made it here, we must have an error in the callback re: - // gh-4500, so we need to emit. - setImmediate(function() { - _this.model.emit('error', error); - }); + var err; + try { + callback(error); + } catch(err) { + // If we made it here, we must have an error in the callback re: + // gh-4500, so we need to emit. + setImmediate(function() { + _this.model.emit('error', err); + }); + } + throw error; }); } From 9d940b7b6968fb801c998f6d432400de92e9bc8b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Apr 2017 00:44:32 -0600 Subject: [PATCH 1388/2240] test(populate): repro #5128 --- test/model.populate.test.js | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index cb052b6d6a5..faa367bdbbe 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4976,6 +4976,45 @@ describe('model: populate:', function() { } }); + it('handles circular virtual -> regular (gh-5128)', function(done) { + var ASchema = new Schema({ + title: { type: String, required: true, trim : true }, + }); + + ASchema.virtual('brefs', { + ref: 'gh5128_0', + localField: '_id', + foreignField: 'arefs' + }); + + var BSchema = new Schema({ + arefs: [{ type: ObjectId, required: true, ref: 'gh5128' }], + }); + + var a = db.model('gh5128', ASchema); + var b = db.model('gh5128_0', BSchema); + + var id1 = new mongoose.Types.ObjectId(); + + a.create({ _id: id1, title: 'test' }). + then(function() { return b.create({ arefs: [id1] }); }). + then(function() { + return a.findOne({ _id: id1 }).populate([{ + path: 'brefs', // this gets populated + model: 'gh5128_0', + populate: [{ + path: 'arefs', // <---- this is returned as [ObjectId], not populated + model: 'gh5128' + }] + }]); + }). + then(function(doc) { + assert.equal(doc.brefs[0].arefs[0].title, 'test'); + done(); + }). + catch(done); + }); + it('handles nested virtuals (gh-4851)', function(done) { var AuthorSchema = new Schema({ name: String }); From ed12a258472a868818b529e91b222d9853e08ab7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Apr 2017 19:54:16 -0600 Subject: [PATCH 1389/2240] fix(populate): don't mutate populate result in place Fix #5128 --- lib/model.js | 7 ++++--- test/model.populate.test.js | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index 319bdb5da68..493b2ce21e6 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3062,10 +3062,11 @@ function populate(model, docs, options, callback) { if (Array.isArray(_val)) { var _valLength = _val.length; for (var j = 0; j < _valLength; ++j) { - if (_val[j] instanceof Document) { - _val[j] = _val[j]._id; + var __val = _val[j]; + if (__val instanceof Document) { + __val = __val._id; } - key = String(_val[j]); + key = String(__val); if (rawDocs[key]) { if (Array.isArray(rawDocs[key])) { rawDocs[key].push(val); diff --git a/test/model.populate.test.js b/test/model.populate.test.js index faa367bdbbe..759a65d3d29 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4978,7 +4978,7 @@ describe('model: populate:', function() { it('handles circular virtual -> regular (gh-5128)', function(done) { var ASchema = new Schema({ - title: { type: String, required: true, trim : true }, + title: { type: String, required: true, trim : true } }); ASchema.virtual('brefs', { @@ -4988,7 +4988,7 @@ describe('model: populate:', function() { }); var BSchema = new Schema({ - arefs: [{ type: ObjectId, required: true, ref: 'gh5128' }], + arefs: [{ type: ObjectId, required: true, ref: 'gh5128' }] }); var a = db.model('gh5128', ASchema); From 97be22fcae46874fcf6016b54ede3bd67ac1568a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 7 Apr 2017 20:37:09 -0600 Subject: [PATCH 1390/2240] chore: add setOnInsert to castOps --- lib/services/query/castUpdate.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index 53aed3fdf5c..012fd41cf8e 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -233,7 +233,8 @@ var castOps = { $push: 1, $pushAll: 1, $addToSet: 1, - $set: 1 + $set: 1, + $setOnInsert: 1 }; /*! From bf6148d219862bfe176b59cfd636a6fb9a7f2d2e Mon Sep 17 00:00:00 2001 From: maa105 Date: Sat, 8 Apr 2017 05:56:52 +0300 Subject: [PATCH 1391/2240] Update query.js --- lib/query.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/query.js b/lib/query.js index ac60e5f899d..93fc3adcb76 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2742,10 +2742,9 @@ Query.prototype.exec = function exec(op, callback) { if (callback) { return promise.then( function() { - var err; try { callback.apply(null, _results); - } catch(err) { + } catch (err) { // If we made it here, we must have an error in the callback re: // gh-4500, so we need to emit. setImmediate(function() { @@ -2755,10 +2754,9 @@ Query.prototype.exec = function exec(op, callback) { return _results; }, function(error) { - var err; try { callback(error); - } catch(err) { + } catch (err) { // If we made it here, we must have an error in the callback re: // gh-4500, so we need to emit. setImmediate(function() { From 12c129b162b60807cf8ee616a448da4b85437a24 Mon Sep 17 00:00:00 2001 From: clozanosanchez Date: Sat, 8 Apr 2017 18:24:36 +0200 Subject: [PATCH 1392/2240] Solves issue #5141, regression caused by #5098 --- lib/schema.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/schema.js b/lib/schema.js index a5e72d3b18d..c97e94fcd39 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -348,6 +348,7 @@ Schema.prototype.clone = function() { s.callQueue = this.callQueue.map(function(f) { return f; }); s.methods = utils.clone(this.methods); s.statics = utils.clone(this.statics); + s.s.hooks = utils.clone(this.s.hooks); return s; }; From eb3bb0adc9c23c5900faaf1a6fc8d196d5b4eb68 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Apr 2017 23:36:44 -0600 Subject: [PATCH 1393/2240] test(query): repro #5126 --- test/model.query.casting.test.js | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index 0809938c459..4a47bf88514 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -981,6 +981,46 @@ describe('model query casting', function() { }); }); + it('setOnInsert with custom type (gh-5126)', function(done) { + var db = start(); + + function Point(key, options) { + mongoose.SchemaType.call(this, key, options, 'Point'); + } + + mongoose.Schema.Types.Point = Point; + Point.prototype = Object.create(mongoose.SchemaType.prototype); + + var called = 0; + Point.prototype.cast = function(point) { + ++called; + if (point.type !== 'Point') { + throw new Error('Woops'); + } + + return point; + }; + + var testSchema = new mongoose.Schema({ name: String, test: Point }); + var Test = db.model('gh5126', testSchema); + + var u = { + $setOnInsert: { + name: 'a', + test: { + type: 'Point' + } + } + }; + Test.findOneAndUpdate({ name: 'a' }, u). + exec(function(error) { + assert.ifError(error); + assert.equal(called, 1); + done(); + }). + catch(done); + }); + it('_id = 0 (gh-4610)', function(done) { var db = start(); From 75a325f0a4f49184f889749fe3f55fdb352f289b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Apr 2017 23:36:48 -0600 Subject: [PATCH 1394/2240] fix(query): handle $setOnInsert consistent with $set Fix #5126 --- lib/services/query/castUpdate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index 012fd41cf8e..8811d0080dc 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -144,7 +144,7 @@ function walkUpdatePath(schema, obj, op, strict, pref) { // $currentDate can take an object obj[key] = castUpdateVal(schematype, val, op); hasKeys = true; - } else if (op === '$set' && schematype) { + } else if (op in castOps && schematype) { obj[key] = castUpdateVal(schematype, val, op); hasKeys = true; } else { From 7d78a7576ad0ff438fdf8af82089748b5274c64a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Apr 2017 00:14:49 -0600 Subject: [PATCH 1395/2240] feat(query): add PoC for runSetters option Re: #4569 --- lib/schema.js | 4 ++++ lib/schema/string.js | 3 +++ test/model.query.casting.test.js | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index a5e72d3b18d..bd0feb6d4a9 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -689,6 +689,10 @@ Schema.interpretAsType = function(path, obj, options) { 'You can only nest using refs or arrays.'); } + obj = utils.clone(obj); + if (!('runSetters' in obj)) { + obj.runSetters = options.runSetters; + } return new MongooseTypes[name](path, obj); }; diff --git a/lib/schema/string.js b/lib/schema/string.js index d969280a9c6..8c5d95fd233 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -506,6 +506,9 @@ SchemaString.prototype.castForQuery = function($conditional, val) { if (Object.prototype.toString.call(val) === '[object RegExp]') { return val; } + if (this.options && this.options.runSetters) { + return this.applySetters(val, null); + } return this.cast(val); }; diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index 4a47bf88514..6f3a195ba07 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -1021,6 +1021,26 @@ describe('model query casting', function() { catch(done); }); + it('lowercase in query (gh-4569)', function(done) { + var db = start(); + + var testSchema = new Schema({ + name: { type: String, lowercase: true } + }, { runSetters: true }); + + var Test = db.model('gh-4569', testSchema); + Test.create({ name: 'val' }). + then(function() { + return Test.findOne({ name: 'VAL' }); + }). + then(function(doc) { + assert.ok(doc); + assert.equal(doc.name, 'val'); + done(); + }). + catch(done); + }); + it('_id = 0 (gh-4610)', function(done) { var db = start(); From 3e66dedcd1ed6db913f0ff02fd6a2aed8ee6f148 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Apr 2017 12:31:02 -0600 Subject: [PATCH 1396/2240] =?UTF-8?q?Revert=20"fix=20blue=20bird=20"a=20pr?= =?UTF-8?q?omise=20was=20created=20in=20a=20handler=20but=20was=20not=20re?= =?UTF-8?q?turne=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/query.js | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/lib/query.js b/lib/query.js index 93fc3adcb76..58c45f51469 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2740,30 +2740,20 @@ Query.prototype.exec = function exec(op, callback) { }); if (callback) { - return promise.then( + promise.then( function() { - try { - callback.apply(null, _results); - } catch (err) { - // If we made it here, we must have an error in the callback re: - // gh-4500, so we need to emit. - setImmediate(function() { - _this.model.emit('error', err); - }); - } - return _results; + callback.apply(null, _results); + return null; }, function(error) { - try { - callback(error); - } catch (err) { - // If we made it here, we must have an error in the callback re: - // gh-4500, so we need to emit. - setImmediate(function() { - _this.model.emit('error', err); - }); - } - throw error; + callback(error); + }). + catch(function(error) { + // If we made it here, we must have an error in the callback re: + // gh-4500, so we need to emit. + setImmediate(function() { + _this.model.emit('error', error); + }); }); } From b9f7d54eb8326f24982c1b551bf2e6dda143625f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Apr 2017 13:08:42 -0600 Subject: [PATCH 1397/2240] docs(aggregate): fix typo Re: #5142 --- lib/aggregate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 8bb126b5b5f..623fbaa8737 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -171,7 +171,7 @@ Aggregate.prototype.project = function(arg) { * * ####Examples: * - * aggregate.match({ department: { $in: [ "sales", "engineering" } } }); + * aggregate.match({ department: { $in: [ "sales", "engineering" ] } }); * * @see $match http://docs.mongodb.org/manual/reference/aggregation/match/ * @method match From ed617b13af3915c7ade2e5817c6c46c7aedd452a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Apr 2017 13:14:50 -0600 Subject: [PATCH 1398/2240] fix(schema): clone query middleware correctly Fix #5153 #5141 --- lib/schema.js | 2 +- test/query.middleware.test.js | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index c97e94fcd39..908761060d4 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -348,7 +348,7 @@ Schema.prototype.clone = function() { s.callQueue = this.callQueue.map(function(f) { return f; }); s.methods = utils.clone(this.methods); s.statics = utils.clone(this.statics); - s.s.hooks = utils.clone(this.s.hooks); + s.s.hooks = this.s.hooks.clone(); return s; }; diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 5d3cfa378b7..8a58827673e 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -394,4 +394,29 @@ describe('query middleware', function() { done(); }); }); + + it('with clone() (gh-5153)', function(done) { + var schema = new Schema({}); + var calledPre = 0; + var calledPost = 0; + + schema.pre('find', function(next) { + ++calledPre; + next(); + }); + + schema.post('find', function(res, next) { + ++calledPost; + next(); + }); + + var Test = db.model('gh5153', schema.clone()); + + Test.find().exec(function(error) { + assert.ifError(error); + assert.equal(calledPre, 1); + assert.equal(calledPost, 1); + done(); + }); + }); }); From d4d2d0156613f6dfbc269d7a590e2b5b997963d3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Apr 2017 13:18:40 -0600 Subject: [PATCH 1399/2240] chore: release 4.9.4 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0c187c9d807..4a39472e44a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.9.4 / 2017-04-09 +================== + * fix(schema): clone query middleware correctly #5153 #5141 [clozanosanchez](https://github.com/clozanosanchez) + * docs(aggregate): fix typo #5142 + * fix(query): cast .$ update to underlying array type #5130 + * fix(populate): don't mutate populate result in place #5128 + * fix(query): handle $setOnInsert consistent with $set #5126 + * docs(query): add strict mode option for findOneAndUpdate #5108 + 4.9.3 / 2017-04-02 ================== * docs: document.js fixes for functions prepended with `$` #5131 [krmannix](https://github.com/krmannix) diff --git a/package.json b/package.json index dd73aff8e5b..8c80a9b5a66 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.4-pre", + "version": "4.9.4", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From b66be34d54a6a3cf538b90bf1b5296f123c688a8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Apr 2017 13:20:27 -0600 Subject: [PATCH 1400/2240] chore: now working on 4.9.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8c80a9b5a66..6d8841fac2b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.4", + "version": "4.9.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 173d72efba76b5881eb604f0cbfc4ff3cf849231 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Apr 2017 19:30:13 -0600 Subject: [PATCH 1401/2240] feat(query): add more fleshed out runSettersOnQuery re: #4569 --- lib/schema.js | 6 ++-- lib/schema/boolean.js | 4 +-- lib/schema/buffer.js | 2 +- lib/schema/date.js | 2 +- lib/schema/decimal128.js | 20 -------------- lib/schema/embedded.js | 4 +++ lib/schema/number.js | 2 +- lib/schema/objectid.js | 2 +- lib/schema/string.js | 6 ++-- lib/schematype.js | 47 ++++++++++++++++++++++++-------- test/model.query.casting.test.js | 16 ++++++++--- 11 files changed, 63 insertions(+), 48 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index bd0feb6d4a9..cd376b9a705 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -689,9 +689,9 @@ Schema.interpretAsType = function(path, obj, options) { 'You can only nest using refs or arrays.'); } - obj = utils.clone(obj); - if (!('runSetters' in obj)) { - obj.runSetters = options.runSetters; + obj = utils.clone(obj, { retainKeyOrder: true }); + if (!('runSettersOnQuery' in obj)) { + obj.runSettersOnQuery = options.runSettersOnQuery; } return new MongooseTypes[name](path, obj); }; diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js index 206d9fd98f5..5951dd0513d 100644 --- a/lib/schema/boolean.js +++ b/lib/schema/boolean.js @@ -90,10 +90,10 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val) { return handler.call(this, val); } - return this.cast(val); + return this._castForQuery(val); } - return this.cast($conditional); + return this._castForQuery($conditional); }; /*! diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js index 56490dea878..f7ca7588a36 100644 --- a/lib/schema/buffer.js +++ b/lib/schema/buffer.js @@ -178,7 +178,7 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val) { return handler.call(this, val); } val = $conditional; - var casted = this.cast(val); + var casted = this._castForQuery(val); return casted ? casted.toObject({ transform: false, virtuals: false }) : casted; }; diff --git a/lib/schema/date.js b/lib/schema/date.js index b7bcf227b33..9f97096b5ba 100644 --- a/lib/schema/date.js +++ b/lib/schema/date.js @@ -277,7 +277,7 @@ SchemaDate.prototype.castForQuery = function($conditional, val) { var handler; if (arguments.length !== 2) { - return this.cast($conditional); + return this._castForQuery($conditional); } handler = this.$conditionalHandlers[$conditional]; diff --git a/lib/schema/decimal128.js b/lib/schema/decimal128.js index 3400e36ef63..67e35df4830 100644 --- a/lib/schema/decimal128.js +++ b/lib/schema/decimal128.js @@ -139,26 +139,6 @@ Decimal128.prototype.$conditionalHandlers = $lte: handleSingle }); -/** - * Casts contents for queries. - * - * @param {String} $conditional - * @param {any} [val] - * @api private - */ - -Decimal128.prototype.castForQuery = function($conditional, val) { - var handler; - if (arguments.length === 2) { - handler = this.$conditionalHandlers[$conditional]; - if (!handler) { - throw new Error('Can\'t use ' + $conditional + ' with ObjectId.'); - } - return handler.call(this, val); - } - return this.cast($conditional); -}; - /*! * Module exports. */ diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index d1e293fdceb..9938563adc8 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -156,6 +156,10 @@ Embedded.prototype.castForQuery = function($conditional, val) { return val; } + if (this.options.runSetters) { + val = this._applySetters(val); + } + return new this.caster(val); }; diff --git a/lib/schema/number.js b/lib/schema/number.js index a91f6dda6df..e5b9bc7fa62 100644 --- a/lib/schema/number.js +++ b/lib/schema/number.js @@ -279,7 +279,7 @@ SchemaNumber.prototype.castForQuery = function($conditional, val) { } return handler.call(this, val); } - val = this.cast($conditional); + val = this._castForQuery($conditional); return val; }; diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index 28858236893..6f684191c90 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -184,7 +184,7 @@ ObjectId.prototype.castForQuery = function($conditional, val) { } return handler.call(this, val); } - return this.cast($conditional); + return this._castForQuery($conditional); }; /*! diff --git a/lib/schema/string.js b/lib/schema/string.js index 8c5d95fd233..dfd044ad2f8 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -506,10 +506,8 @@ SchemaString.prototype.castForQuery = function($conditional, val) { if (Object.prototype.toString.call(val) === '[object RegExp]') { return val; } - if (this.options && this.options.runSetters) { - return this.applySetters(val, null); - } - return this.cast(val); + + return this._castForQuery(val); }; /*! diff --git a/lib/schematype.js b/lib/schematype.js index 83495f6ef09..16078815796 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -622,20 +622,17 @@ SchemaType.prototype.getDefault = function(scope, init) { return ret; }; -/** - * Applies setters +/*! + * Applies setters without casting * - * @param {Object} value - * @param {Object} scope - * @param {Boolean} init * @api private */ -SchemaType.prototype.applySetters = function(value, scope, init, priorVal, options) { - var v = value, - setters = this.setters, - len = setters.length, - caster = this.caster; +SchemaType.prototype._applySetters = function(value, scope, init, priorVal) { + var v = value; + var setters = this.setters; + var len = setters.length; + var caster = this.caster; while (len--) { v = setters[len].call(scope, v, this); @@ -649,7 +646,22 @@ SchemaType.prototype.applySetters = function(value, scope, init, priorVal, optio v = newVal; } - if (v === null || v === undefined) { + return v; +}; + +/** + * Applies setters + * + * @param {Object} value + * @param {Object} scope + * @param {Boolean} init + * @api private + */ + +SchemaType.prototype.applySetters = function(value, scope, init, priorVal, options) { + var v = this._applySetters(value, scope, init, priorVal, options); + + if (v == null) { return v; } @@ -971,6 +983,19 @@ SchemaType.prototype.castForQuery = function($conditional, val) { return handler.call(this, val); } val = $conditional; + return this._castForQuery(val); +}; + +/*! + * Internal switch for runSetters + * + * @api private + */ + +SchemaType.prototype._castForQuery = function(val) { + if (this.options && this.options.runSettersOnQuery) { + return this.applySetters(val, null); + } return this.cast(val); }; diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index 6f3a195ba07..98e1d4fbdd1 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -1025,19 +1025,27 @@ describe('model query casting', function() { var db = start(); var testSchema = new Schema({ - name: { type: String, lowercase: true } - }, { runSetters: true }); + name: { type: String, lowercase: true }, + num: { type: Number, set: function(v) { return Math.floor(v); } } + }, { runSettersOnQuery: true }); var Test = db.model('gh-4569', testSchema); - Test.create({ name: 'val' }). + Test.create({ name: 'val', num: 3 }). then(function() { return Test.findOne({ name: 'VAL' }); }). then(function(doc) { assert.ok(doc); assert.equal(doc.name, 'val'); - done(); }). + then(function() { + return Test.findOne({ num: 3.14 }); + }). + then(function(doc) { + assert.ok(doc); + assert.equal(doc.name, 'val'); + }). + then(function() { done(); }). catch(done); }); From e05f5977f5609ff769ae6aa5cc9a051494b48663 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 10 Apr 2017 18:23:57 -0600 Subject: [PATCH 1402/2240] test(document): repro #5143 --- test/document.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 1793bd7ce0a..e3093391d2b 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3923,6 +3923,23 @@ describe('document', function() { done(); }); + it('toObject() with null (gh-5143)', function(done) { + var schema = new mongoose.Schema({ + customer: { + name: { type: String, required: false } + } + }); + + var Model = db.model('gh5143', schema); + + var model = new Model(); + model.customer = null; + assert.strictEqual(model.toObject().customer, null); + assert.strictEqual(model.toObject({ getters: true }).customer, null); + + done(); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From 0e5cbab216bf54f2358237e3b0cf8c666a91d0db Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 10 Apr 2017 18:24:49 -0600 Subject: [PATCH 1403/2240] fix(document): handle null/undefined gracefully in applyGetters() Fix #5143 --- lib/document.js | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/document.js b/lib/document.js index 9a982c4df6b..917910ac5d4 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2290,27 +2290,41 @@ function minimize(obj) { */ function applyGetters(self, json, type, options) { - var schema = self.schema, - paths = Object.keys(schema[type]), - i = paths.length, - path; + var schema = self.schema; + var paths = Object.keys(schema[type]); + var i = paths.length; + var path; + var cur = self._doc; + var v; + + if (!cur) { + return json; + } while (i--) { path = paths[i]; - var parts = path.split('.'), - plen = parts.length, - last = plen - 1, - branch = json, - part; + var parts = path.split('.'); + var plen = parts.length; + var last = plen - 1; + var branch = json; + var part; + cur = self._doc; for (var ii = 0; ii < plen; ++ii) { part = parts[ii]; + v = cur[part]; if (ii === last) { branch[part] = clone(self.get(path), options); + } else if (v == null) { + if (part in cur) { + branch[part] = v; + } + break; } else { branch = branch[part] || (branch[part] = {}); } + cur = v; } } From 0c0822279a4c2187e28bff14c271bb6237f3acc1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 10 Apr 2017 19:02:31 -0600 Subject: [PATCH 1404/2240] feat(aggregate): add mongoose-specific agg cursor Fix #5145 --- lib/aggregate.js | 8 ++++++-- test/aggregate.test.js | 13 +++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 623fbaa8737..10c2210730e 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -2,10 +2,11 @@ * Module dependencies */ -var util = require('util'); -var utils = require('./utils'); +var AggregationCursor = require('./cursor/AggregationCursor'); var PromiseProvider = require('./promise_provider'); var Query = require('./query'); +var util = require('util'); +var utils = require('./utils'); var read = Query.prototype.read; /** @@ -631,6 +632,9 @@ Aggregate.prototype.exec = function(callback) { callback && callback(null, cursor); }); }); + } else if (options.cursor.useMongooseAggCursor) { + delete options.cursor.useMongooseAggCursor; + return new AggregationCursor(this); } var cursor = this._model.collection. aggregate(this._pipeline, this.options || {}); diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 8bcadf83aa6..2350cadd017 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -898,6 +898,19 @@ describe('aggregate: ', function() { }); }); + it('cursor() with useMongooseAggCursor (gh-5145)', function(done) { + var db = start(); + + var MyModel = db.model('gh5145', { name: String }); + + var cursor = MyModel. + aggregate([{ $match: { name: 'test' } }]). + cursor({ useMongooseAggCursor: true }). + exec(); + assert.ok(cursor instanceof require('stream').Readable); + done(); + }); + it('cursor() eachAsync (gh-4300)', function(done) { var db = start(); From 894a5dd400643a4bf38042f5b1cf71c2b9156a6f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 10 Apr 2017 19:05:20 -0600 Subject: [PATCH 1405/2240] chore: add missing files --- lib/cursor/AggregationCursor.js | 282 ++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 lib/cursor/AggregationCursor.js diff --git a/lib/cursor/AggregationCursor.js b/lib/cursor/AggregationCursor.js new file mode 100644 index 00000000000..ce762b982b7 --- /dev/null +++ b/lib/cursor/AggregationCursor.js @@ -0,0 +1,282 @@ +/*! + * Module dependencies. + */ + +var PromiseProvider = require('../promise_provider'); +var Readable = require('stream').Readable; +var util = require('util'); + +/** + * An AggregationCursor is a concurrency primitive for processing aggregation + * results one document at a time. It is analogous to QueryCursor. + * + * An AggregationCursor fulfills the [Node.js streams3 API](https://strongloop.com/strongblog/whats-new-io-js-beta-streams3/), + * in addition to several other mechanisms for loading documents from MongoDB + * one at a time. + * + * Unless you're an advanced user, do **not** instantiate this class directly. + * Use [`Aggregate#cursor()`](/docs/api.html#aggregate_Aggregate-cursor) instead. + * + * @param {Aggregate} agg + * @param {Object} options + * @inherits Readable + * @event `cursor`: Emitted when the cursor is created + * @event `error`: Emitted when an error occurred + * @event `data`: Emitted when the stream is flowing and the next doc is ready + * @event `end`: Emitted when the stream is exhausted + * @api public + */ + +function AggregationCursor(agg) { + Readable.call(this, { objectMode: true }); + + this.cursor = null; + this.agg = agg; + this._transforms = []; + var _this = this; + var model = agg._model; + model.collection.aggregate(agg._pipeline, agg.options || {}, function(err, cursor) { + if (_this._error) { + cursor.close(function() {}); + _this.listeners('error').length > 0 && _this.emit('error', _this._error); + } + if (err) { + return _this.emit('error', err); + } + _this.cursor = cursor; + _this.emit('cursor', cursor); + }); +} + +util.inherits(AggregationCursor, Readable); + +/*! + * Necessary to satisfy the Readable API + */ + +AggregationCursor.prototype._read = function() { + var _this = this; + _next(this, function(error, doc) { + if (error) { + return _this.emit('error', error); + } + if (!doc) { + _this.push(null); + _this.cursor.close(function(error) { + if (error) { + return _this.emit('error', error); + } + setTimeout(function() { + _this.emit('close'); + }, 0); + }); + return; + } + _this.push(doc); + }); +}; + +/** + * Registers a transform function which subsequently maps documents retrieved + * via the streams interface or `.next()` + * + * ####Example + * + * // Map documents returned by `data` events + * Thing. + * find({ name: /^hello/ }). + * cursor(). + * map(function (doc) { + * doc.foo = "bar"; + * return doc; + * }) + * on('data', function(doc) { console.log(doc.foo); }); + * + * // Or map documents returned by `.next()` + * var cursor = Thing.find({ name: /^hello/ }). + * cursor(). + * map(function (doc) { + * doc.foo = "bar"; + * return doc; + * }); + * cursor.next(function(error, doc) { + * console.log(doc.foo); + * }); + * + * @param {Function} fn + * @return {QueryCursor} + * @api public + * @method map + */ + +AggregationCursor.prototype.map = function(fn) { + this._transforms.push(fn); + return this; +}; + +/*! + * Marks this cursor as errored + */ + +AggregationCursor.prototype._markError = function(error) { + this._error = error; + return this; +}; + +/** + * Marks this cursor as closed. Will stop streaming and subsequent calls to + * `next()` will error. + * + * @param {Function} callback + * @return {Promise} + * @api public + * @method close + * @emits close + * @see MongoDB driver cursor#close http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#close + */ + +AggregationCursor.prototype.close = function(callback) { + var Promise = PromiseProvider.get(); + var _this = this; + return new Promise.ES6(function(resolve, reject) { + _this.cursor.close(function(error) { + if (error) { + callback && callback(error); + reject(error); + return _this.listeners('error').length > 0 && + _this.emit('error', error); + } + _this.emit('close'); + resolve(); + callback && callback(); + }); + }); +}; + +/** + * Get the next document from this cursor. Will return `null` when there are + * no documents left. + * + * @param {Function} callback + * @return {Promise} + * @api public + * @method next + */ + +AggregationCursor.prototype.next = function(callback) { + var Promise = PromiseProvider.get(); + var _this = this; + return new Promise.ES6(function(resolve, reject) { + _next(_this, function(error, doc) { + if (error) { + callback && callback(error); + return reject(error); + } + callback && callback(null, doc); + resolve(doc); + }); + }); +}; + +/** + * Execute `fn` for every document in the cursor. If `fn` returns a promise, + * will wait for the promise to resolve before iterating on to the next one. + * Returns a promise that resolves when done. + * + * @param {Function} fn + * @param {Function} [callback] executed when all docs have been processed + * @return {Promise} + * @api public + * @method eachAsync + */ + +AggregationCursor.prototype.eachAsync = function(fn, callback) { + var Promise = PromiseProvider.get(); + var _this = this; + + var handleNextResult = function(doc, callback) { + var promise = fn(doc); + if (promise && typeof promise.then === 'function') { + promise.then( + function() { callback(null); }, + function(error) { callback(error); }); + } else { + callback(null); + } + }; + + var iterate = function(callback) { + return _next(_this, function(error, doc) { + if (error) { + return callback(error); + } + if (!doc) { + return callback(null); + } + handleNextResult(doc, function(error) { + if (error) { + return callback(error); + } + // Make sure to clear the stack re: gh-4697 + setTimeout(function() { + iterate(callback); + }, 0); + }); + }); + }; + + return new Promise.ES6(function(resolve, reject) { + iterate(function(error) { + if (error) { + callback && callback(error); + return reject(error); + } + callback && callback(null); + return resolve(); + }); + }); +}; + +/*! + * Get the next doc from the underlying cursor and mongooseify it + * (populate, etc.) + */ + +function _next(ctx, cb) { + var callback = cb; + if (ctx._transforms.length) { + callback = function(err, doc) { + if (err || doc === null) { + return cb(err, doc); + } + cb(err, ctx._transforms.reduce(function(doc, fn) { + return fn(doc); + }, doc)); + }; + } + + if (ctx._error) { + return process.nextTick(function() { + callback(ctx._error); + }); + } + + if (ctx.cursor) { + return ctx.cursor.next(function(error, doc) { + if (error) { + return callback(error); + } + if (!doc) { + return callback(null, null); + } + + callback(null, doc); + }); + } else { + ctx.once('cursor', function() { + _next(ctx, cb); + }); + } +} + +module.exports = AggregationCursor; From 52bb50f95de6344983c0996d98b10f8a881dc831 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 11 Apr 2017 23:31:19 -0600 Subject: [PATCH 1406/2240] test(model): repro #4945 --- test/model.mapreduce.test.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/model.mapreduce.test.js b/test/model.mapreduce.test.js index abb7cfc03d3..c445c73bba9 100644 --- a/test/model.mapreduce.test.js +++ b/test/model.mapreduce.test.js @@ -375,4 +375,27 @@ describe('model: mapreduce:', function() { db.close(done); }); }); + + it('resolveToObject (gh-4945)', function(done) { + var db = start(); + var MR = db.model('MapReduce', collection); + + var o = { + map: function() { + }, + reduce: function() { + return 'test'; + }, + verbose: false, + resolveToObject: true + }; + + MR.create({ title: 'test' }, function(error) { + assert.ifError(error); + MR.mapReduce(o).then(function(obj) { + assert.ok(obj.model); + db.close(done); + }).catch(done); + }); + }); }); From 7d8254b215a285e5647ee0a446bace5b783206bd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 11 Apr 2017 23:31:26 -0600 Subject: [PATCH 1407/2240] fix(model): add resolveToObject option for mapReduce with ES6 promises Fix #4945 --- lib/model.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index 493b2ce21e6..35bb745815c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2440,9 +2440,13 @@ function _update(model, op, conditions, doc, options, callback) { * }); * }) * - * // a promise is returned so you may instead write + * // `mapReduce()` returns a promise. However, ES6 promises can only + * // resolve to exactly one value, + * o.resolveToObject = true; * var promise = User.mapReduce(o); - * promise.then(function (model, stats) { + * promise.then(function (res) { + * var model = res.model; + * var stats = res.stats; * console.log('map reduce took %d ms', stats.processtime) * return model.find().where('value').gt(10).exec(); * }).then(function (docs) { @@ -2461,6 +2465,7 @@ Model.mapReduce = function mapReduce(o, callback) { if (callback) { callback = this.$wrapCallback(callback); } + var resolveToObject = o.resolveToObject; var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { if (!Model.mapReduce.schema) { @@ -2500,10 +2505,16 @@ Model.mapReduce = function mapReduce(o, callback) { model._mapreduce = true; callback && callback(null, model, stats); - return resolve(model, stats); + return resolveToObject ? resolve({ + model: model, + stats: stats + }) : resolve(model, stats); } callback && callback(null, ret, stats); + if (resolveToObject) { + return resolve({ model: ret, stats: stats }); + } resolve(ret, stats); }); }); From fce6716e5187ef23bda25bbd2d8e90e18a1c93be Mon Sep 17 00:00:00 2001 From: Sebastian Mayr Date: Thu, 13 Apr 2017 20:36:45 +0200 Subject: [PATCH 1408/2240] Fix casting of null values --- lib/schema/array.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index 0eb902fac25..7f680dcf32a 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -241,7 +241,7 @@ SchemaArray.prototype.castForQuery = function($conditional, value) { v = method.call(caster, v); return v; } - if (val != null) { + if (v != null) { v = new Constructor(v); return v; } From c25f258226cccb36031d50479d23fbc450501454 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 13 Apr 2017 18:11:21 -0600 Subject: [PATCH 1409/2240] test(query): repro #4136 --- test/model.findOneAndUpdate.test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 467c7262635..51aeb1bd861 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1781,6 +1781,17 @@ describe('model: findOneAndUpdate:', function() { }); }); + it('strictQuery option (gh-4136)', function(done) { + var modelSchema = new Schema({ field: Number }, { strictQuery: 'throw' }); + + var Model = db.model('gh4136', modelSchema); + Model.find({ nonexistingField: 1 }).exec(function(error) { + assert.ok(error); + assert.ok(error.message.indexOf('strictQuery') !== -1, error.message); + done(); + }); + }); + it('strict option (gh-5108)', function(done) { var modelSchema = new Schema({ field: Number }, { strict: 'throw' }); From 0a1ea284d880acc478ea2ea23123f56edce7791d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 13 Apr 2017 18:11:23 -0600 Subject: [PATCH 1410/2240] fix(query): add strictQuery option that throws when not querying on field not in schema Fix #4136 --- lib/cast.js | 3 +++ lib/query.js | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/cast.js b/lib/cast.js index 406c7d1c1d5..4ff8449dd54 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -179,6 +179,9 @@ module.exports = function cast(schema, obj, options) { } throw new StrictModeError(path, 'Path "' + path + '" is not in ' + 'schema, strict mode is `true`, and upsert is `true`.'); + } else if (options && options.strictQuery === 'throw') { + throw new StrictModeError(path, 'Path "' + path + '" is not in ' + + 'schema and strictQuery is true.'); } } else if (val === null || val === undefined) { obj[path] = null; diff --git a/lib/query.js b/lib/query.js index 58c45f51469..7da389ce858 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2919,7 +2919,9 @@ Query.prototype.cast = function(model, obj) { return cast(model.schema, obj, { upsert: this.options && this.options.upsert, strict: (this.options && this.options.strict) || - (model.schema.options && model.schema.options.strict) + (model.schema.options && model.schema.options.strict), + strictQuery: (this.options && this.options.strictQuery) || + (model.schema.options && model.schema.options.strictQuery) }); } catch (err) { // CastError, assign model From 761ea35ffd20e6fbc2b3d090f0c8f5e4f3942673 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 13 Apr 2017 22:34:19 -0600 Subject: [PATCH 1411/2240] test(update): repro #5164 --- test/model.update.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 6212e43ced1..7253b9db927 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2495,6 +2495,32 @@ describe('model: update:', function() { catch(done); }); + it('$pullAll with null (gh-5164)', function(done) { + var schema = new Schema({ + name: String, + arr: [{ name: String }] + }, { strict: true }); + var Test = db.model('gh5164', schema); + + var doc = new Test({ name: 'Test', arr: [null, {name: 'abc'}] }); + + doc.save(). + then(function(doc) { + return Test.update({ _id: doc._id }, { + $pullAll: { arr: [null] } + }); + }). + then(function() { + return Test.findById(doc); + }). + then(function(doc) { + assert.equal(doc.arr.length, 1); + assert.equal(doc.arr[0].name, 'abc'); + done(); + }). + catch(done); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From b85897b3cb5c32de7c7cf9701de200f85670eee3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 13 Apr 2017 23:06:55 -0600 Subject: [PATCH 1412/2240] fix(model): return saved docs when create() fails Fix #2190 --- lib/model.js | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/model.js b/lib/model.js index 35bb745815c..ce8754317ff 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1891,6 +1891,7 @@ Model.create = function create(doc, callback) { } var toExecute = []; + var firstError; args.forEach(function(doc) { toExecute.push(function(callback) { var Model = _this.discriminators && doc[discriminatorKey] ? @@ -1899,9 +1900,12 @@ Model.create = function create(doc, callback) { var toSave = doc instanceof Model ? doc : new Model(doc); var callbackWrapper = function(error, doc) { if (error) { - return callback(error); + if (!firstError) { + firstError = error; + } + return callback(null, { error: error }); } - callback(null, doc); + callback(null, { doc: doc }); }; // Hack to avoid getting a promise because of @@ -1914,12 +1918,20 @@ Model.create = function create(doc, callback) { }); }); - parallel(toExecute, function(error, savedDocs) { - if (error) { + parallel(toExecute, function(error, res) { + var savedDocs = []; + var len = res.length; + for (var i = 0; i < len; ++i) { + if (res[i].doc) { + savedDocs.push(res[i].doc); + } + } + + if (firstError) { if (cb) { - cb(error); + cb(firstError, savedDocs); } else { - reject(error); + reject(firstError); } return; } @@ -1930,8 +1942,7 @@ Model.create = function create(doc, callback) { } else { resolve.apply(promise, savedDocs); if (cb) { - savedDocs.unshift(null); - cb.apply(_this, savedDocs); + cb.apply(_this, [null].concat(savedDocs)); } } }); From c894753e1187f93101be5c17a6f4c91bbba80c68 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 14 Apr 2017 20:19:14 -0600 Subject: [PATCH 1413/2240] chore: remove old ES6 integration tests --- lib/schema.js | 3 +- test/harmony/.eslintrc.yml | 2 - test/harmony/document.test_.js | 210 --------------------------------- test/harmony/model.test_.js | 136 --------------------- test/harmony/query.test_.js | 117 ------------------ 5 files changed, 2 insertions(+), 466 deletions(-) delete mode 100644 test/harmony/.eslintrc.yml delete mode 100644 test/harmony/document.test_.js delete mode 100644 test/harmony/model.test_.js delete mode 100644 test/harmony/query.test_.js diff --git a/lib/schema.js b/lib/schema.js index 908761060d4..ae4b9d3f4bc 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1621,7 +1621,8 @@ Schema.prototype.remove = function(path) { }; /** - * Loads an ES6 class into a schema. Maps setters + getters, static methods, and instance methods to schema virtuals, statics, and methods. + * Loads an ES6 class into a schema. Maps setters + getters, static methods, and + * instance methods to schema virtuals, statics, and methods. * * @param {Function} model */ diff --git a/test/harmony/.eslintrc.yml b/test/harmony/.eslintrc.yml deleted file mode 100644 index 0dbaf3cb1b8..00000000000 --- a/test/harmony/.eslintrc.yml +++ /dev/null @@ -1,2 +0,0 @@ -env: - es6: true diff --git a/test/harmony/document.test_.js b/test/harmony/document.test_.js deleted file mode 100644 index 977037b7352..00000000000 --- a/test/harmony/document.test_.js +++ /dev/null @@ -1,210 +0,0 @@ -var start = require('../common'); -var mongoose = start.mongoose; -var Schema = mongoose.Schema; -var ValidationError = require('../../lib/error/validation'); -var co = require('co'); -var assert = require('power-assert'); - -/** - * Asynchronous document functions return - * [promises](https://www.npmjs.org/package/mpromise), and so are compatible - * with the [ES6 `yield` keyword](http://mzl.la/1gSa8Gu) and libraries like - * [co](https://www.npmjs.org/package/co). - * - * Note that the `yield` keyword is currently only supported in NodeJS 0.11.x - * with the `--harmony` flag. - */ -describe('Documents in ES6', function() { - var db; - var collectionNameCounter = 0; - - var getCollectionName = function() { - return 'harmony-documents-validate-' + (++collectionNameCounter); - }; - - beforeEach(function() { - db = start({noErrorListener: 1}); - }); - - afterEach(function(done) { - db.close(done); - }); - - it('validate() integrates with co and the yield keyword', function(done) { - co(function*() { - var schema = null; - var called = false; - var shouldSucceed = true; - var error; - - var validate = { - validator: function() { - called = true; - return shouldSucceed; - }, - message: 'BAM' - }; - - schema = new Schema({ - eggs: {type: String, required: true, validate: validate}, - bacon: {type: Boolean, required: true} - }); - - var M = db.model('validateSchema', schema, getCollectionName()); - var m = new M({eggs: 'Sunny side up', bacon: false}); - - try { - yield m.validate(); - } catch (e) { - error = e; - } - - assert.ok(!error); - assert.equal(called, true); - called = false; - - // The validator function above should now fail - shouldSucceed = false; - try { - yield m.validate(); - } catch (e) { - error = e; - } - - assert.ok(error); - assert.ok(error instanceof ValidationError); - - done(); - })(); - }); - - it('save() integrates with co and the yield keyword', function(done) { - co(function*() { - var error; - var schema = new Schema({ - description: {type: String, required: true} - }); - - var Breakfast = db.model('breakfast', schema, getCollectionName()); - - var goodBreakfast = new Breakfast({description: 'eggs & bacon'}); - - try { - yield goodBreakfast.save(); - } catch (e) { - error = e; - } - - assert.ifError(error); - var result; - try { - result = yield Breakfast.findOne().exec(); - } catch (e) { - error = e; - } - assert.ifError(error); - assert.equal(result.description, 'eggs & bacon'); - - // Should cause a validation error because `description` is required - var badBreakfast = new Breakfast({}); - try { - yield badBreakfast.save(); - } catch (e) { - error = e; - } - - assert.ok(error); - assert.ok(error instanceof ValidationError); - - done(); - })(); - }); - - it('populate() *requires* execPopulate() to work with the yield keyword', function(done) { - /** - * Because the `populate()` function supports chaining, it's difficult - * to determine when the chain is 'done'. Therefore, you need to call - * `execPopulate()` to use `populate()` with `yield`. - */ - co(function*() { - var error; - var breakfastCollectionName = getCollectionName(); - var foodCollectionName = getCollectionName(); - var breakfastSchema = new Schema({ - foods: [{type: mongoose.Schema.ObjectId, ref: foodCollectionName}] - }); - - var foodSchema = new Schema({ - name: String - }); - - var Food = db.model(foodCollectionName, foodSchema, foodCollectionName); - var Breakfast = db.model(breakfastCollectionName, breakfastSchema, breakfastCollectionName); - - var bacon = new Food({name: 'bacon'}); - var eggs = new Food({name: 'eggs'}); - var goodBreakfast = new Breakfast({foods: [bacon, eggs]}); - - try { - yield [bacon.save(), eggs.save(), goodBreakfast.save()]; - } catch (e) { - error = e; - } - - var result; - try { - result = yield Breakfast.findOne().exec(); - } catch (e) { - error = e; - } - assert.ifError(error); - assert.equal(result.foods.length, 2); - - try { - result = yield result.populate('foods').execPopulate(); - } catch (e) { - error = e; - } - assert.ifError(error); - assert.equal(result.foods.length, 2); - assert.equal(result.foods[0].name, 'bacon'); - assert.equal(result.foods[1].name, 'eggs'); - - done(); - })(); - }); - - it('update() works with co and yield', function(done) { - co(function*() { - var schema = new Schema({ - steak: String, - eggs: String - }); - - var Breakfast = db.model('breakfast', schema, getCollectionName()); - - var breakfast = new Breakfast({}); - var error; - - try { - yield breakfast.update({steak: 'Ribeye', eggs: 'Scrambled'}, {upsert: true}).exec(); - } catch (e) { - error = e; - } - - assert.ifError(error); - var result; - try { - result = yield Breakfast.findOne().exec(); - } catch (e) { - error = e; - } - assert.ifError(error); - assert.equal(breakfast._id.toString(), result._id.toString()); - assert.equal(result.steak, 'Ribeye'); - assert.equal(result.eggs, 'Scrambled'); - done(); - })(); - }); -}); - diff --git a/test/harmony/model.test_.js b/test/harmony/model.test_.js deleted file mode 100644 index 4a8464e7db8..00000000000 --- a/test/harmony/model.test_.js +++ /dev/null @@ -1,136 +0,0 @@ -/* global emit */ -var start = require('../common'); -var mongoose = start.mongoose; -var Schema = mongoose.Schema; -var co = require('co'); -var assert = require('power-assert'); - -/** - * Asynchronous functions on Model return - * [promises](https://www.npmjs.org/package/mpromise), and so are compatible - * with the [ES6 `yield` keyword](http://mzl.la/1gSa8Gu) and libraries like - * [co](https://www.npmjs.org/package/co). - * - * Note that the functions `find()`, `findOne()`, `findById()`, `count()`, - * `findOneAndUpdate()`, `remove()`, `distinct()`, `findByIdAndUpdate()`, - * `findOneAndRemove()`, `update()`, and `findByIdAndRemove()` return *Query* - * objects, and so you need to use `.exec()` to use these functions with - * `yield` as described above. - * - */ -describe('Models in ES6', function() { - var db; - var collectionNameCounter = 0; - - var getCollectionName = function() { - return 'harmony-models-validate-' + (++collectionNameCounter); - }; - - beforeEach(function() { - db = start(); - }); - - afterEach(function(done) { - db.close(done); - }); - - it('`create()` integrates with co and the yield keyword', function(done) { - co(function * () { - var schema = new Schema({ - eggs: {type: String, required: true}, - bacon: {type: Boolean, required: true} - }); - - var M = db.model('harmonyCreate', schema, getCollectionName()); - - var results; - try { - results = yield M.create([ - {eggs: 'sunny-side up', bacon: false}, - {eggs: 'scrambled', bacon: true}]); - } catch (e) { - return done(e); - } - - assert.equal(results.length, 2); - assert.equal(results[0].eggs, 'sunny-side up'); - assert.equal(results[1].eggs, 'scrambled'); - - done(); - })(); - }); - - it('`aggregate()` integrates with co and the yield keyword', function(done) { - co(function*() { - var schema = new Schema({ - eggs: {type: String, required: true}, - bacon: {type: Boolean, required: true} - }); - - var M = db.model('harmonyAggregate', schema, getCollectionName()); - - try { - yield M.create([ - {eggs: 'sunny-side up', bacon: false}, - {eggs: 'scrambled', bacon: true}]); - } catch (e) { - return done(e); - } - - var results; - try { - results = yield M.aggregate([ - {$group: {_id: '$bacon', eggs: {$first: '$eggs'}}}, - {$sort: {_id: 1}} - ]).exec(); - } catch (e) { - return done(e); - } - - assert.equal(results.length, 2); - assert.equal(results[0]._id, false); - assert.equal(results[0].eggs, 'sunny-side up'); - assert.equal(results[1]._id, true); - assert.equal(results[1].eggs, 'scrambled'); - - done(); - })(); - }); - - it('`mapReduce()` can also be used with co and yield', function(done) { - co(function*() { - var schema = new Schema({ - eggs: {type: String, required: true}, - bacon: {type: Boolean, required: true} - }); - - var M = db.model('harmonyMapreduce', schema, getCollectionName()); - - try { - yield M.create([ - {eggs: 'sunny-side up', bacon: false}, - {eggs: 'sunny-side up', bacon: true}, - {eggs: 'scrambled', bacon: true}]); - } catch (e) { - return done(e); - } - - var results; - try { - results = yield M.mapReduce({ - map: function() { emit(this.eggs, 1); }, - reduce: function(k, vals) { return vals.length; } - }); - } catch (e) { - return done(e); - } - - assert.equal(results.length, 2); - assert.ok(results[0]._id === 'sunny-side up' || results[1]._id === 'sunny-side up'); - assert.ok(results[0]._id === 'scrambled' || results[1]._id === 'scrambled'); - - done(); - })(); - }); -}); - diff --git a/test/harmony/query.test_.js b/test/harmony/query.test_.js deleted file mode 100644 index f637cad808c..00000000000 --- a/test/harmony/query.test_.js +++ /dev/null @@ -1,117 +0,0 @@ -var start = require('../common'); -var mongoose = start.mongoose; -var Schema = mongoose.Schema; -var co = require('co'); -var assert = require('power-assert'); - -/** - * Mongoose queries' .exec() function returns a - * [promise](https://www.npmjs.org/package/mpromise), and so its compatible - * with the [ES6 `yield` keyword](http://mzl.la/1gSa8Gu) and libraries like - * [co](https://www.npmjs.org/package/co). - * - * Note that the `yield` keyword is currently only supported in NodeJS 0.11.x - * with the `--harmony` flag. - */ -describe('Queries in ES6', function() { - var db; - var collectionNameCounter = 0; - - var getCollectionName = function() { - return 'harmony-queries' + (++collectionNameCounter); - }; - - beforeEach(function() { - db = start(); - }); - - afterEach(function(done) { - db.close(done); - }); - - it('`exec()` integrates with co and the yield keyword', function(done) { - co(function*() { - var schema = new Schema({ - eggs: {type: Number, required: true}, - bacon: {type: Number, required: true} - }); - - var Breakfast = db.model('BreakfastHarmony', schema, getCollectionName()); - - try { - yield Breakfast.create( - {eggs: 4, bacon: 2}, - {eggs: 3, bacon: 3}, - {eggs: 2, bacon: 4}); - } catch (e) { - return done(e); - } - - var result; - try { - result = yield Breakfast.findOne({eggs: 4}).exec(); - } catch (e) { - return done(e); - } - - assert.equal(result.bacon, 2); - - var results; - try { - results = yield Breakfast.find({eggs: {$gt: 2}}).sort({bacon: 1}).exec(); - } catch (e) { - return done(e); - } - - assert.equal(results.length, 2); - assert.equal(results[0].bacon, 2); - assert.equal(results[1].bacon, 3); - - var count; - try { - count = yield Breakfast.count({eggs: {$gt: 2}}).exec(); - } catch (e) { - return done(e); - } - - assert.equal(count, 2); - - done(); - })(); - }); - - it('can call `populate()` with `exec()`', function(done) { - co(function*() { - var bookSchema = new Schema({ - author: {type: mongoose.Schema.ObjectId, ref: 'AuthorHarmony'}, - title: String - }); - - var authorSchema = new Schema({ - name: String - }); - - var Book = db.model('BookHarmony', bookSchema, getCollectionName()); - var Author = db.model('AuthorHarmony', authorSchema, getCollectionName()); - - try { - var hugo = yield Author.create({name: 'Victor Hugo'}); - yield Book.create({author: hugo._id, title: 'Les Miserables'}); - } catch (e) { - return done(e); - } - - var result; - try { - result = yield Book.findOne({title: 'Les Miserables'}).populate('author').exec(); - } catch (e) { - return done(e); - } - - assert.equal(result.author.name, 'Victor Hugo'); - - done(); - })(); - }); -}); - From 1bdb17f4507b99dcfecc67860bfe49618f9c148d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 14 Apr 2017 20:22:15 -0600 Subject: [PATCH 1414/2240] chore: customize travis build --- .travis.yml | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 23b799dc7e2..88444bbe6ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,3 +13,6 @@ before_script: - tar -zxvf mongodb-linux-x86_64-2.6.11.tgz - mkdir -p ./data/db - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --nopreallocj --dbpath ./data/db --syslog --port 27017 +script: + - npm test + - npm run lint diff --git a/package.json b/package.json index 6d8841fac2b..4097f64e97d 100644 --- a/package.json +++ b/package.json @@ -71,8 +71,8 @@ "scripts": { "fix-lint": "eslint . --fix", "install-browser": "npm install `node format_deps.js`", + "lint": "eslint . --quiet", "test": "mocha test/*.test.js test/**/*.test.js", - "posttest": "eslint . --quiet", "test-cov": "istanbul cover --report text --report html _mocha test/*.test.js" }, "main": "./index.js", From 06099f8a9074edb85c1f7f29697ac62308bf2676 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 15 Apr 2017 22:58:01 -0600 Subject: [PATCH 1415/2240] docs(schema): add basic docs for loadClass() Re: #4668 --- test/docs/es6_gateway.test.js | 5 +++ test/docs/schemas.test.es6.js | 70 +++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 test/docs/es6_gateway.test.js create mode 100644 test/docs/schemas.test.es6.js diff --git a/test/docs/es6_gateway.test.js b/test/docs/es6_gateway.test.js new file mode 100644 index 00000000000..b0532ce1fd2 --- /dev/null +++ b/test/docs/es6_gateway.test.js @@ -0,0 +1,5 @@ +'use strict'; + +if (parseInt(process.versions.node.split('.')[0], 10) >= 4) { + require('./schemas.test.es6.js'); +} diff --git a/test/docs/schemas.test.es6.js b/test/docs/schemas.test.es6.js new file mode 100644 index 00000000000..6c0edd08639 --- /dev/null +++ b/test/docs/schemas.test.es6.js @@ -0,0 +1,70 @@ +var assert = require('assert'); +var mongoose = require('../../'); + +describe('Advanced Schemas', function () { + var db; + var Schema = mongoose.Schema; + + before(function() { + db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test'); + }); + + after(function(done) { + db.close(done); + }); + + /** + * Mongoose allows creating schemas from [ES6 classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes). + * The `loadClass()` function lets you pull in methods, + * statics, and virtuals from an ES6 class. A class method maps to a schema + * method, a static method maps to a schema static, and getters/setters map + * to virtuals. + */ + it('Creating from ES6 Classes Using `loadClass()`', function(done) { + const schema = new Schema({ firstName: String, lastName: String }); + + class PersonClass { + // `fullName` becomes a virtual + get fullName() { + return `${this.firstName} ${this.lastName}`; + } + + set fullName(v) { + const firstSpace = v.indexOf(' '); + this.firstName = v.split(' ')[0]; + this.lastName = firstSpace === -1 ? '' : v.substr(firstSpace + 1); + } + + // `getFullName()` becomes a document method + getFullName() { + return `${this.firstName} ${this.lastName}`; + } + + // `findByFullName()` becomes a static + static findByFullName(name) { + const firstSpace = name.indexOf(' '); + const firstName = name.split(' ')[0]; + const lastName = firstSpace === -1 ? '' : name.substr(firstSpace + 1); + return this.findOne({ firstName, lastName }); + } + } + + schema.loadClass(PersonClass); + var Person = db.model('Person', schema); + + Person.create({ firstName: 'Jon', lastName: 'Snow' }). + then(doc => { + assert.equal(doc.fullName, 'Jon Snow'); + doc.fullName = 'Jon Stark'; + assert.equal(doc.firstName, 'Jon'); + assert.equal(doc.lastName, 'Stark'); + return Person.findByFullName('Jon Snow'); + }). + then(doc => { + assert.equal(doc.fullName, 'Jon Snow'); + // acquit:ignore:start + done(); + // acquit:ignore:end + }); + }); +}); From fe428a9661ba7193f55e0960d70965653c0504dc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 16 Apr 2017 22:03:45 -0600 Subject: [PATCH 1416/2240] docs: add advanced schemas docs Fix #5157 --- docs/includes/nav.jade | 9 ++++++--- docs/source/acquit.js | 5 +++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/includes/nav.jade b/docs/includes/nav.jade index 2a102cb4d27..5f7afcc3ba2 100644 --- a/docs/includes/nav.jade +++ b/docs/includes/nav.jade @@ -22,6 +22,12 @@ ul a(href="./schematypes.html") span schema | types + li.custom-schema-types + a(href="./customschematypes.html") + | custom schema types + li.advanced-schemas + a(href="./advanced_schemas.html") + | advanced usage li a(href="./models.html") | models @@ -68,9 +74,6 @@ ul li a(href="./browser.html") | schemas in the browser - li - a(href="./customschematypes.html") - | custom schema types li a(href="./compatibility.html") | MongoDB Version Compatibility diff --git a/docs/source/acquit.js b/docs/source/acquit.js index ae4a68c02c3..91ede15c43e 100644 --- a/docs/source/acquit.js +++ b/docs/source/acquit.js @@ -30,6 +30,11 @@ var files = [ input: 'test/docs/validation.test.js', output: 'validation.html', title: 'Validation' + }, + { + input: 'test/docs/schemas.test.es6.js', + output: 'advanced_schemas.html', + title: 'Advanced Schemas' } ]; From 3b07f294630e529666cb90e2270f1553d99e24ad Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 16 Apr 2017 22:22:17 -0600 Subject: [PATCH 1417/2240] chore: fix build on node 4+5 --- test/docs/schemas.test.es6.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/docs/schemas.test.es6.js b/test/docs/schemas.test.es6.js index 6c0edd08639..152c176c3b7 100644 --- a/test/docs/schemas.test.es6.js +++ b/test/docs/schemas.test.es6.js @@ -1,3 +1,5 @@ +'use strict'; + var assert = require('assert'); var mongoose = require('../../'); From e5390b16cc9251687cbaf6f3712cf646fab3f854 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 16 Apr 2017 22:29:30 -0600 Subject: [PATCH 1418/2240] chore: release 4.9.5 --- History.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 4a39472e44a..7f3481e3e64 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.9.5 / 2017-04-16 +================== + * fix(query): correct $pullAll casting of null #5164 [Sebmaster](https://github.com/Sebmaster) + * docs: add advanced schemas docs for loadClass #5157 + * fix(document): handle null/undefined gracefully in applyGetters() #5143 + * fix(model): add resolveToObject option for mapReduce with ES6 promises #4945 + 4.9.4 / 2017-04-09 ================== * fix(schema): clone query middleware correctly #5153 #5141 [clozanosanchez](https://github.com/clozanosanchez) diff --git a/package.json b/package.json index 4097f64e97d..b6c7c1630cf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.5-pre", + "version": "4.9.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 88eff72ae5411d2d04da204ed579d1aa4cc7e483 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 16 Apr 2017 22:38:56 -0600 Subject: [PATCH 1419/2240] Revert "chore: remove old ES6 integration tests" This reverts commit c894753e1187f93101be5c17a6f4c91bbba80c68. --- lib/schema.js | 3 +- test/harmony/.eslintrc.yml | 2 + test/harmony/document.test_.js | 210 +++++++++++++++++++++++++++++++++ test/harmony/model.test_.js | 136 +++++++++++++++++++++ test/harmony/query.test_.js | 117 ++++++++++++++++++ 5 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 test/harmony/.eslintrc.yml create mode 100644 test/harmony/document.test_.js create mode 100644 test/harmony/model.test_.js create mode 100644 test/harmony/query.test_.js diff --git a/lib/schema.js b/lib/schema.js index ae4b9d3f4bc..908761060d4 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1621,8 +1621,7 @@ Schema.prototype.remove = function(path) { }; /** - * Loads an ES6 class into a schema. Maps setters + getters, static methods, and - * instance methods to schema virtuals, statics, and methods. + * Loads an ES6 class into a schema. Maps setters + getters, static methods, and instance methods to schema virtuals, statics, and methods. * * @param {Function} model */ diff --git a/test/harmony/.eslintrc.yml b/test/harmony/.eslintrc.yml new file mode 100644 index 00000000000..0dbaf3cb1b8 --- /dev/null +++ b/test/harmony/.eslintrc.yml @@ -0,0 +1,2 @@ +env: + es6: true diff --git a/test/harmony/document.test_.js b/test/harmony/document.test_.js new file mode 100644 index 00000000000..977037b7352 --- /dev/null +++ b/test/harmony/document.test_.js @@ -0,0 +1,210 @@ +var start = require('../common'); +var mongoose = start.mongoose; +var Schema = mongoose.Schema; +var ValidationError = require('../../lib/error/validation'); +var co = require('co'); +var assert = require('power-assert'); + +/** + * Asynchronous document functions return + * [promises](https://www.npmjs.org/package/mpromise), and so are compatible + * with the [ES6 `yield` keyword](http://mzl.la/1gSa8Gu) and libraries like + * [co](https://www.npmjs.org/package/co). + * + * Note that the `yield` keyword is currently only supported in NodeJS 0.11.x + * with the `--harmony` flag. + */ +describe('Documents in ES6', function() { + var db; + var collectionNameCounter = 0; + + var getCollectionName = function() { + return 'harmony-documents-validate-' + (++collectionNameCounter); + }; + + beforeEach(function() { + db = start({noErrorListener: 1}); + }); + + afterEach(function(done) { + db.close(done); + }); + + it('validate() integrates with co and the yield keyword', function(done) { + co(function*() { + var schema = null; + var called = false; + var shouldSucceed = true; + var error; + + var validate = { + validator: function() { + called = true; + return shouldSucceed; + }, + message: 'BAM' + }; + + schema = new Schema({ + eggs: {type: String, required: true, validate: validate}, + bacon: {type: Boolean, required: true} + }); + + var M = db.model('validateSchema', schema, getCollectionName()); + var m = new M({eggs: 'Sunny side up', bacon: false}); + + try { + yield m.validate(); + } catch (e) { + error = e; + } + + assert.ok(!error); + assert.equal(called, true); + called = false; + + // The validator function above should now fail + shouldSucceed = false; + try { + yield m.validate(); + } catch (e) { + error = e; + } + + assert.ok(error); + assert.ok(error instanceof ValidationError); + + done(); + })(); + }); + + it('save() integrates with co and the yield keyword', function(done) { + co(function*() { + var error; + var schema = new Schema({ + description: {type: String, required: true} + }); + + var Breakfast = db.model('breakfast', schema, getCollectionName()); + + var goodBreakfast = new Breakfast({description: 'eggs & bacon'}); + + try { + yield goodBreakfast.save(); + } catch (e) { + error = e; + } + + assert.ifError(error); + var result; + try { + result = yield Breakfast.findOne().exec(); + } catch (e) { + error = e; + } + assert.ifError(error); + assert.equal(result.description, 'eggs & bacon'); + + // Should cause a validation error because `description` is required + var badBreakfast = new Breakfast({}); + try { + yield badBreakfast.save(); + } catch (e) { + error = e; + } + + assert.ok(error); + assert.ok(error instanceof ValidationError); + + done(); + })(); + }); + + it('populate() *requires* execPopulate() to work with the yield keyword', function(done) { + /** + * Because the `populate()` function supports chaining, it's difficult + * to determine when the chain is 'done'. Therefore, you need to call + * `execPopulate()` to use `populate()` with `yield`. + */ + co(function*() { + var error; + var breakfastCollectionName = getCollectionName(); + var foodCollectionName = getCollectionName(); + var breakfastSchema = new Schema({ + foods: [{type: mongoose.Schema.ObjectId, ref: foodCollectionName}] + }); + + var foodSchema = new Schema({ + name: String + }); + + var Food = db.model(foodCollectionName, foodSchema, foodCollectionName); + var Breakfast = db.model(breakfastCollectionName, breakfastSchema, breakfastCollectionName); + + var bacon = new Food({name: 'bacon'}); + var eggs = new Food({name: 'eggs'}); + var goodBreakfast = new Breakfast({foods: [bacon, eggs]}); + + try { + yield [bacon.save(), eggs.save(), goodBreakfast.save()]; + } catch (e) { + error = e; + } + + var result; + try { + result = yield Breakfast.findOne().exec(); + } catch (e) { + error = e; + } + assert.ifError(error); + assert.equal(result.foods.length, 2); + + try { + result = yield result.populate('foods').execPopulate(); + } catch (e) { + error = e; + } + assert.ifError(error); + assert.equal(result.foods.length, 2); + assert.equal(result.foods[0].name, 'bacon'); + assert.equal(result.foods[1].name, 'eggs'); + + done(); + })(); + }); + + it('update() works with co and yield', function(done) { + co(function*() { + var schema = new Schema({ + steak: String, + eggs: String + }); + + var Breakfast = db.model('breakfast', schema, getCollectionName()); + + var breakfast = new Breakfast({}); + var error; + + try { + yield breakfast.update({steak: 'Ribeye', eggs: 'Scrambled'}, {upsert: true}).exec(); + } catch (e) { + error = e; + } + + assert.ifError(error); + var result; + try { + result = yield Breakfast.findOne().exec(); + } catch (e) { + error = e; + } + assert.ifError(error); + assert.equal(breakfast._id.toString(), result._id.toString()); + assert.equal(result.steak, 'Ribeye'); + assert.equal(result.eggs, 'Scrambled'); + done(); + })(); + }); +}); + diff --git a/test/harmony/model.test_.js b/test/harmony/model.test_.js new file mode 100644 index 00000000000..4a8464e7db8 --- /dev/null +++ b/test/harmony/model.test_.js @@ -0,0 +1,136 @@ +/* global emit */ +var start = require('../common'); +var mongoose = start.mongoose; +var Schema = mongoose.Schema; +var co = require('co'); +var assert = require('power-assert'); + +/** + * Asynchronous functions on Model return + * [promises](https://www.npmjs.org/package/mpromise), and so are compatible + * with the [ES6 `yield` keyword](http://mzl.la/1gSa8Gu) and libraries like + * [co](https://www.npmjs.org/package/co). + * + * Note that the functions `find()`, `findOne()`, `findById()`, `count()`, + * `findOneAndUpdate()`, `remove()`, `distinct()`, `findByIdAndUpdate()`, + * `findOneAndRemove()`, `update()`, and `findByIdAndRemove()` return *Query* + * objects, and so you need to use `.exec()` to use these functions with + * `yield` as described above. + * + */ +describe('Models in ES6', function() { + var db; + var collectionNameCounter = 0; + + var getCollectionName = function() { + return 'harmony-models-validate-' + (++collectionNameCounter); + }; + + beforeEach(function() { + db = start(); + }); + + afterEach(function(done) { + db.close(done); + }); + + it('`create()` integrates with co and the yield keyword', function(done) { + co(function * () { + var schema = new Schema({ + eggs: {type: String, required: true}, + bacon: {type: Boolean, required: true} + }); + + var M = db.model('harmonyCreate', schema, getCollectionName()); + + var results; + try { + results = yield M.create([ + {eggs: 'sunny-side up', bacon: false}, + {eggs: 'scrambled', bacon: true}]); + } catch (e) { + return done(e); + } + + assert.equal(results.length, 2); + assert.equal(results[0].eggs, 'sunny-side up'); + assert.equal(results[1].eggs, 'scrambled'); + + done(); + })(); + }); + + it('`aggregate()` integrates with co and the yield keyword', function(done) { + co(function*() { + var schema = new Schema({ + eggs: {type: String, required: true}, + bacon: {type: Boolean, required: true} + }); + + var M = db.model('harmonyAggregate', schema, getCollectionName()); + + try { + yield M.create([ + {eggs: 'sunny-side up', bacon: false}, + {eggs: 'scrambled', bacon: true}]); + } catch (e) { + return done(e); + } + + var results; + try { + results = yield M.aggregate([ + {$group: {_id: '$bacon', eggs: {$first: '$eggs'}}}, + {$sort: {_id: 1}} + ]).exec(); + } catch (e) { + return done(e); + } + + assert.equal(results.length, 2); + assert.equal(results[0]._id, false); + assert.equal(results[0].eggs, 'sunny-side up'); + assert.equal(results[1]._id, true); + assert.equal(results[1].eggs, 'scrambled'); + + done(); + })(); + }); + + it('`mapReduce()` can also be used with co and yield', function(done) { + co(function*() { + var schema = new Schema({ + eggs: {type: String, required: true}, + bacon: {type: Boolean, required: true} + }); + + var M = db.model('harmonyMapreduce', schema, getCollectionName()); + + try { + yield M.create([ + {eggs: 'sunny-side up', bacon: false}, + {eggs: 'sunny-side up', bacon: true}, + {eggs: 'scrambled', bacon: true}]); + } catch (e) { + return done(e); + } + + var results; + try { + results = yield M.mapReduce({ + map: function() { emit(this.eggs, 1); }, + reduce: function(k, vals) { return vals.length; } + }); + } catch (e) { + return done(e); + } + + assert.equal(results.length, 2); + assert.ok(results[0]._id === 'sunny-side up' || results[1]._id === 'sunny-side up'); + assert.ok(results[0]._id === 'scrambled' || results[1]._id === 'scrambled'); + + done(); + })(); + }); +}); + diff --git a/test/harmony/query.test_.js b/test/harmony/query.test_.js new file mode 100644 index 00000000000..f637cad808c --- /dev/null +++ b/test/harmony/query.test_.js @@ -0,0 +1,117 @@ +var start = require('../common'); +var mongoose = start.mongoose; +var Schema = mongoose.Schema; +var co = require('co'); +var assert = require('power-assert'); + +/** + * Mongoose queries' .exec() function returns a + * [promise](https://www.npmjs.org/package/mpromise), and so its compatible + * with the [ES6 `yield` keyword](http://mzl.la/1gSa8Gu) and libraries like + * [co](https://www.npmjs.org/package/co). + * + * Note that the `yield` keyword is currently only supported in NodeJS 0.11.x + * with the `--harmony` flag. + */ +describe('Queries in ES6', function() { + var db; + var collectionNameCounter = 0; + + var getCollectionName = function() { + return 'harmony-queries' + (++collectionNameCounter); + }; + + beforeEach(function() { + db = start(); + }); + + afterEach(function(done) { + db.close(done); + }); + + it('`exec()` integrates with co and the yield keyword', function(done) { + co(function*() { + var schema = new Schema({ + eggs: {type: Number, required: true}, + bacon: {type: Number, required: true} + }); + + var Breakfast = db.model('BreakfastHarmony', schema, getCollectionName()); + + try { + yield Breakfast.create( + {eggs: 4, bacon: 2}, + {eggs: 3, bacon: 3}, + {eggs: 2, bacon: 4}); + } catch (e) { + return done(e); + } + + var result; + try { + result = yield Breakfast.findOne({eggs: 4}).exec(); + } catch (e) { + return done(e); + } + + assert.equal(result.bacon, 2); + + var results; + try { + results = yield Breakfast.find({eggs: {$gt: 2}}).sort({bacon: 1}).exec(); + } catch (e) { + return done(e); + } + + assert.equal(results.length, 2); + assert.equal(results[0].bacon, 2); + assert.equal(results[1].bacon, 3); + + var count; + try { + count = yield Breakfast.count({eggs: {$gt: 2}}).exec(); + } catch (e) { + return done(e); + } + + assert.equal(count, 2); + + done(); + })(); + }); + + it('can call `populate()` with `exec()`', function(done) { + co(function*() { + var bookSchema = new Schema({ + author: {type: mongoose.Schema.ObjectId, ref: 'AuthorHarmony'}, + title: String + }); + + var authorSchema = new Schema({ + name: String + }); + + var Book = db.model('BookHarmony', bookSchema, getCollectionName()); + var Author = db.model('AuthorHarmony', authorSchema, getCollectionName()); + + try { + var hugo = yield Author.create({name: 'Victor Hugo'}); + yield Book.create({author: hugo._id, title: 'Les Miserables'}); + } catch (e) { + return done(e); + } + + var result; + try { + result = yield Book.findOne({title: 'Les Miserables'}).populate('author').exec(); + } catch (e) { + return done(e); + } + + assert.equal(result.author.name, 'Victor Hugo'); + + done(); + })(); + }); +}); + From 6b4da5b3e7983ffafaaadaa77ec6ee0daef3aed2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 16 Apr 2017 22:42:01 -0600 Subject: [PATCH 1420/2240] chore: dont ignore docs/*.html in gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 00dc9ca998a..c2a14d4b815 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ benchmarks/v8.log .DS_Store docs/*.json docs/source/_docs -docs/*.html tags test/triage/*.js /.idea From de18ce33d4229a96aaa4f6faee9fc68b359d0670 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 16 Apr 2017 22:42:17 -0600 Subject: [PATCH 1421/2240] chore: now working on 4.9.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b6c7c1630cf..91f6a531ddc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.5", + "version": "4.9.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From dbda564048778f43ae1618ecc214af2afdf1f2e3 Mon Sep 17 00:00:00 2001 From: Tom Zellman Date: Mon, 17 Apr 2017 16:43:50 -0400 Subject: [PATCH 1422/2240] Fix the bulkWrite::updateMany case, where the update option was inadvertently being wrapped by the filter option --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 35bb745815c..47ff7d0c0e5 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2115,7 +2115,7 @@ Model.bulkWrite = function(ops, options, callback) { try { op['updateMany']['filter'] = cast(_this.schema, op['updateMany']['filter']); - op['updateMany']['update'] = castUpdate(_this.schema, op['updateMany']['filter'], { + op['updateMany']['update'] = castUpdate(_this.schema, op['updateMany']['update'], { strict: _this.schema.options.strict, overwrite: false }); From 68d8d1572c4b50e206f065ae80be270f4eade16f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 17 Apr 2017 18:25:23 -0600 Subject: [PATCH 1423/2240] test(document): repro #5134 --- test/document.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index e3093391d2b..81259ce0864 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2054,6 +2054,25 @@ describe('document', function() { done(); }); + it('single embedded parent() (gh-5134)', function(done) { + var userSchema = new mongoose.Schema({ + name: String, + email: {type: String, required: true, match: /.+@.+/} + }, {_id: false, id: false}); + + var eventSchema = new mongoose.Schema({ + user: userSchema, + name: String + }); + + var Event = db.model('gh5134', eventSchema); + + var e = new Event({name: 'test', user: {}}); + assert.strictEqual(e.user.parent(), e.user.ownerDocument()); + + done(); + }); + it('single embedded schemas with markmodified (gh-2689)', function(done) { var userSchema = new mongoose.Schema({ name: String, From 551c0a703be38b402e17fe104f8d52203ae5930d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 17 Apr 2017 18:25:37 -0600 Subject: [PATCH 1424/2240] fix(document): add parent() function to subdocument to match array subdoc Fix #5134 --- lib/types/subdocument.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 27534467285..d788686dc00 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -102,6 +102,16 @@ Subdocument.prototype.ownerDocument = function() { return this.$__.ownerDocument; }; +/** + * Returns this sub-documents parent document. + * + * @api public + */ + +Subdocument.prototype.parent = function() { + return this.$parent; +}; + /** * Null-out this subdoc * From 7f6d459f72c08c3e72a77d6557d1ba1356940772 Mon Sep 17 00:00:00 2001 From: Miles Barr Date: Tue, 18 Apr 2017 08:48:23 -0700 Subject: [PATCH 1425/2240] Update schematype.js Fixed documentation for returning a promise from a validator to match documentation at http://mongoosejs.com/docs/validation.html. --- lib/schematype.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/schematype.js b/lib/schematype.js index 83495f6ef09..c79324432c6 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -419,9 +419,8 @@ SchemaType.prototype.get = function(fn) { * * // Can also return a promise * schema.path('name').validate({ - * isAsync: true, - * validator: function (value, respond) { - * return new Promise(resolve => { + * validator: function (value) { + * return new Promise(function (resolve, reject) { * resolve(false); // validation failed * }); * } From 0d460a84fb65d5ecf3e37fb4f743472df9dfd4e6 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Wed, 19 Apr 2017 11:27:03 +0700 Subject: [PATCH 1426/2240] Add alias schema option --- lib/schema.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index 908761060d4..d0cf6141711 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -127,6 +127,35 @@ function Schema(obj, options) { if (this.options.timestamps) { this.setupTimestamp(this.options.timestamps); } + + // Assign virtual properties based on alias option + aliasFields(this); +} + +/*! + * Create virtual properties with alias field + */ +function aliasFields(schema) { + // console.log(schema.paths); + for (var path in schema.paths) { + var prop = schema.paths[path].path; + var alias = schema.paths[path].options.alias; + + if (alias && 'string' === typeof alias && alias.length > 0) { + schema + .virtual(alias) + .get((function(p) { + return function() { + return this.get(p); + }; + })(prop)) + .set((function(p) { + return function(v) { + return this.set(p, v); + }; + })(prop)); + } + } } /*! From 115e85d64cd71fc5c4ddef32801ea497876b3b4e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 18 Apr 2017 23:17:50 -0600 Subject: [PATCH 1427/2240] test(model): repro #5147 --- test/model.discriminator.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index c53560cf0e9..0cf0d4954ed 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -508,6 +508,33 @@ describe('model', function() { done(); }); + it('copies query hooks (gh-5147)', function(done) { + var options = { discriminatorKey: 'kind' }; + + var eventSchema = new mongoose.Schema({ time: Date }, options); + var eventSchemaCalls = 0; + eventSchema.pre('findOneAndUpdate', function() { + ++eventSchemaCalls; + }); + + var Event = db.model('gh5147', eventSchema); + + var clickedEventSchema = new mongoose.Schema({ url: String }, options); + var clickedEventSchemaCalls = 0; + clickedEventSchema.pre('findOneAndUpdate', function() { + ++clickedEventSchemaCalls; + }); + var ClickedLinkEvent = Event.discriminator('gh5147_0', clickedEventSchema); + + ClickedLinkEvent.findOneAndUpdate({}, { time: new Date() }, {}). + exec(function(error) { + assert.ifError(error); + assert.equal(eventSchemaCalls, 1); + assert.equal(clickedEventSchemaCalls, 1); + done(); + }); + }); + it('embedded discriminators with $push (gh-5009)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From b13b09b07abadc1edc91b17cb59b460a689f95e6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 18 Apr 2017 23:19:26 -0600 Subject: [PATCH 1428/2240] fix(model): merge query hooks from discriminators Fix #5147 --- lib/services/model/discriminator.js | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index c6b18da8f4a..91bb0fce8ae 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -82,6 +82,7 @@ module.exports = function discriminator(model, name, schema) { schema.options._id = _id; } schema.options.id = id; + schema.s.hooks = model.schema.s.hooks.merge(schema.s.hooks); schema.callQueue = baseSchema.callQueue.concat(schema.callQueue.slice(schema._defaultMiddleware.length)); schema._requiredpaths = undefined; // reset just in case Schema#requiredPaths() was called on either schema diff --git a/package.json b/package.json index 91f6a531ddc..f1ba41e6843 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "2.1.4", "bson": "~1.0.4", "hooks-fixed": "2.0.0", - "kareem": "1.2.1", + "kareem": "1.4.0", "mongodb": "2.2.25", "mpath": "0.2.1", "mpromise": "0.5.5", From 3b91fb5769a72b4b9c998702f136f86ab80e03df Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Thu, 20 Apr 2017 07:45:52 +0700 Subject: [PATCH 1429/2240] Safe check null options --- lib/schema.js | 2 ++ test.js | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 test.js diff --git a/lib/schema.js b/lib/schema.js index d0cf6141711..019ce018c2b 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -138,6 +138,8 @@ function Schema(obj, options) { function aliasFields(schema) { // console.log(schema.paths); for (var path in schema.paths) { + if (!schema.paths[path].options) continue; + var prop = schema.paths[path].path; var alias = schema.paths[path].options.alias; diff --git a/test.js b/test.js new file mode 100644 index 00000000000..dcd9671216c --- /dev/null +++ b/test.js @@ -0,0 +1,20 @@ +var mongoose = require('./index'); + +var Schema = mongoose.Schema; +var TestSchema = new Schema({ + foo: { type: String, alias: 'Fap' }, + bar: { + baz: { type: String, alias: 'Fap' }, + kar: { type: String } + } +}); + +var Test = mongoose.model('Test', TestSchema); +var t = new Test({ + foo: 'hey', + bar: { + baz: 'sup' + } +}); + +console.log(t.Fap); \ No newline at end of file From b5fa384d4293a20d8caa36468ddd9230cee2f431 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 19 Apr 2017 22:30:49 -0600 Subject: [PATCH 1430/2240] fix: upgrade mongodb -> 2.2.26 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f1ba41e6843..dec2f5d90c8 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "2.0.0", "kareem": "1.4.0", - "mongodb": "2.2.25", + "mongodb": "2.2.26", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.3.0", From d467f05e1a8c0468281e94c619c39dcb293a6835 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 19 Apr 2017 22:49:41 -0600 Subject: [PATCH 1431/2240] test(document): repro #5162 --- test/document.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 81259ce0864..f26e9dfc64b 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3959,6 +3959,33 @@ describe('document', function() { done(); }); + it('handles array subdocs with single nested subdoc default (gh-5162)', function(done) { + var RatingsItemSchema = new mongoose.Schema({ + value: Number + }, { versionKey: false, _id: false }); + + var RatingsSchema = new mongoose.Schema({ + ratings: { + type: RatingsItemSchema, + default: { id: 1, value: 0 } + }, + _id: false + }); + + var RestaurantSchema = new mongoose.Schema({ + menu: { + type: [RatingsSchema] + } + }); + + var Restaurant = db.model('gh5162', RestaurantSchema); + + // Should not throw + var r = new Restaurant(); + assert.deepEqual(r.toObject().menu, []); + done(); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From 190374aea358e7e1152826b1e9ccf8b322ecb878 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 19 Apr 2017 22:51:05 -0600 Subject: [PATCH 1432/2240] fix(document): don't create a new array subdoc when creating schema array Fix #5162 --- lib/schema/array.js | 2 +- lib/types/array.js | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index 7f680dcf32a..f758e3ed969 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -63,7 +63,7 @@ function SchemaArray(key, cast, options, schemaOptions) { : cast; this.casterConstructor = caster; - if (typeof caster === 'function') { + if (typeof caster === 'function' && !caster.$isArraySubdocument) { this.caster = new caster(null, castOptions); } else { this.caster = caster; diff --git a/lib/types/array.js b/lib/types/array.js index 3874078ee1c..510ff1b0e33 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -119,10 +119,10 @@ MongooseArray.mixin = { if (!isDisc) { value = new Model(value); } - return this._schema.caster.cast(value, this._parent, true); + return this._schema.caster.applySetters(value, this._parent, true); } - return this._schema.caster.cast(value, this._parent, false); + return this._schema.caster.applySetters(value, this._parent, false); }, /** @@ -698,10 +698,6 @@ MongooseArray.mixin = { set: function set(i, val) { var value = this._cast(val, i); - value = this._schema.caster instanceof EmbeddedDocument ? - value : - this._schema.caster.applySetters(val, this._parent) - ; this[i] = value; this._markModified(i); return this; From bfd3b003a26c4e98df4564e1aa40a3a118ef8c25 Mon Sep 17 00:00:00 2001 From: Joey Hobbs Date: Wed, 19 Apr 2017 17:02:00 -0700 Subject: [PATCH 1433/2240] fix(document): repro and fix for gh-5189 Update parent references in embedded docs upon array assignment in document.set --- lib/document.js | 7 +++++++ test/document.modified.test.js | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/document.js b/lib/document.js index 917910ac5d4..8893c91f101 100644 --- a/lib/document.js +++ b/lib/document.js @@ -878,6 +878,13 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche if (val && val.isMongooseArray) { val._registerAtomic('$set', val); + // Update embedded document parent references (gh-5189) + if (val.isMongooseDocumentArray) { + val.forEach(function(item) { + item && item.__parentArray && (item.__parentArray = val); + }); + } + // Small hack for gh-1638: if we're overwriting the entire array, ignore // paths that were modified before the array overwrite this.$__.activePaths.forEach(function(modifiedPath) { diff --git a/test/document.modified.test.js b/test/document.modified.test.js index 2eecd53ca80..1f1ff26e24d 100644 --- a/test/document.modified.test.js +++ b/test/document.modified.test.js @@ -465,6 +465,28 @@ describe('document modified', function() { done(); }); + + it('updates embedded doc parents upon direct assignment (gh-5189)', function(done) { + var db = start(); + var familySchema = new Schema({ + children: [{name: {type: String, required: true}}] + }); + var Family = db.model('Family', familySchema); + Family.create({ + children: [ + {name: 'John'}, + {name: 'Mary'} + ] + }, function(err, family) { + family.set({children: family.children.slice(1)}); + family.children.forEach(function(child) { + child.set({name: 'Maryanne'}); + }); + + assert.equal(family.validateSync(), undefined); + done(); + }); + }); }); it('should support setting mixed paths by string (gh-1418)', function(done) { From 147e605bc299f28a67ec47b560372125020355a2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 21 Apr 2017 23:51:05 -0600 Subject: [PATCH 1434/2240] docs(model): fix replaceOne example for bulkWrite Fix #5168 --- lib/model.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index 35bb745815c..efdbfaa454e 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2034,12 +2034,14 @@ Model.insertMany = function(arr, options, callback) { /** * Sends multiple `insertOne`, `updateOne`, `updateMany`, `replaceOne`, * `deleteOne`, and/or `deleteMany` operations to the MongoDB server in one - * command. This is faster than sending multiple independent operations because - * with `bulkWrite()` there is only one round trip to the server. + * command. This is faster than sending multiple independent operations (like) + * if you use `create()`) because with `bulkWrite()` there is only one round + * trip to MongoDB. * * Mongoose will perform casting on all operations you provide. * - * This function does **not** trigger any middleware. + * This function does **not** trigger any middleware. If you need to trigger + * `save()` middleware for every document use [`create()`](http://mongoosejs.com/docs/api.html#model_Model.create) instead. * * ####Example: * @@ -2055,13 +2057,17 @@ Model.insertMany = function(arr, options, callback) { * { * updateOne: { * filter: { name: 'Eddard Stark' }, - * // Mongoose inserts `$set` for you in the update below + * // If you were using the MongoDB driver directly, you'd need to do + * // `update: { $set: { title: ... } }` but mongoose adds $set for + * // you. * update: { title: 'Hand of the King' } * } * }, * { * deleteOne: { - * { name: 'Eddard Stark' } + * { + * filter: { name: 'Eddard Stark' } + * } * } * } * ]).then(handleResult); From 12371327930b705b213f101a0ee1fc760f4e5852 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Apr 2017 00:09:12 -0600 Subject: [PATCH 1435/2240] test: repro #5175 --- .eslintignore | 1 + test/es6.test.js | 5 +++++ test/es6/all.test.es6.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 test/es6.test.js create mode 100644 test/es6/all.test.es6.js diff --git a/.eslintignore b/.eslintignore index b1109fb5b0a..1c61ae77558 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ docs/ bin/ test/triage/ test/model.discriminator.test.js +test/es6/ diff --git a/test/es6.test.js b/test/es6.test.js new file mode 100644 index 00000000000..545755b8825 --- /dev/null +++ b/test/es6.test.js @@ -0,0 +1,5 @@ +'use strict'; + +if (parseInt(process.versions.node.split('.')[0], 10) >= 4) { + require('./es6/all.test.es6.js'); +} diff --git a/test/es6/all.test.es6.js b/test/es6/all.test.es6.js new file mode 100644 index 00000000000..df398fec44b --- /dev/null +++ b/test/es6/all.test.es6.js @@ -0,0 +1,28 @@ +'use strict'; + +/** + * Module dependencies. + */ + +const assert = require('assert'); +const start = require('../common'); + +const mongoose = start.mongoose; + +describe('bug fixes', function() { + let db; + + before(function() { + db = start(); + }); + + it('discriminators with classes modifies class in place (gh-5175)', function(done) { + class Vehicle extends mongoose.Model { } + var V = mongoose.model(Vehicle, new mongoose.Schema()); + assert.ok(V === Vehicle); + class Car extends Vehicle { } + var C = Vehicle.discriminator(Car, new mongoose.Schema()); + assert.ok(C === Car); + done(); + }); +}); From a2addca1b383f102d889c8c340c3f5c51be0d780 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Apr 2017 00:09:27 -0600 Subject: [PATCH 1436/2240] fix(model): modify discriminator() class in place Fix #5175 --- lib/model.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index efdbfaa454e..8a3592de09d 100644 --- a/lib/model.js +++ b/lib/model.js @@ -829,8 +829,10 @@ Model.prototype.model = function model(name) { */ Model.discriminator = function(name, schema) { + var model; if (typeof name === 'function') { - name = utils.getFunctionName(name); + model = name; + name = utils.getFunctionName(model); } schema = discriminator(this, name, schema); @@ -840,7 +842,10 @@ Model.discriminator = function(name, schema) { schema.$isRootDiscriminator = true; - this.discriminators[name] = this.db.model(name, schema, this.collection.name); + if (!model) { + model = this.db.model(name, schema, this.collection.name); + } + this.discriminators[name] = model; var d = this.discriminators[name]; d.prototype.__proto__ = this.prototype; Object.defineProperty(d, 'baseModelName', { From 5de4c7430871af74c1456ea4d3ae41cbfd83d5c2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Apr 2017 21:10:16 -0600 Subject: [PATCH 1437/2240] feat(timestamps): support already defined timestamps Fix #4868 --- lib/schema.js | 20 ++++---- test/timestamps.test.js | 104 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 test/timestamps.test.js diff --git a/lib/schema.js b/lib/schema.js index 908761060d4..9c146444988 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -826,18 +826,22 @@ Schema.prototype.setupTimestamp = function(timestamps) { var parts = createdAt.split('.'); var i; var cur = schemaAdditions; - for (i = 0; i < parts.length; ++i) { - cur[parts[i]] = (i < parts.length - 1 ? - cur[parts[i]] || {} : - Date); + if (this.pathType(createdAt) === 'adhocOrUndefined') { + for (i = 0; i < parts.length; ++i) { + cur[parts[i]] = (i < parts.length - 1 ? + cur[parts[i]] || {} : + Date); + } } parts = updatedAt.split('.'); cur = schemaAdditions; - for (i = 0; i < parts.length; ++i) { - cur[parts[i]] = (i < parts.length - 1 ? - cur[parts[i]] || {} : - Date); + if (this.pathType(createdAt) === 'adhocOrUndefined') { + for (i = 0; i < parts.length; ++i) { + cur[parts[i]] = (i < parts.length - 1 ? + cur[parts[i]] || {} : + Date); + } } this.add(schemaAdditions); diff --git a/test/timestamps.test.js b/test/timestamps.test.js new file mode 100644 index 00000000000..f049ea95455 --- /dev/null +++ b/test/timestamps.test.js @@ -0,0 +1,104 @@ +'use strict'; + +var assert = require('assert'); +var start = require('./common'); + +var mongoose = start.mongoose; + +describe('timestamps', function() { + var db; + + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('does not override timestamp params defined in schema (gh-4868)', function(done) { + var startTime = Date.now(); + var schema = new mongoose.Schema({ + createdAt: { + type: Date, + select: false + }, + updatedAt: { + type: Date, + select: true + }, + name: String + }, { timestamps: true }); + var M = db.model('gh4868', schema); + + M.create({ name: 'Test' }, function(error) { + assert.ifError(error); + M.findOne({}, function(error, doc) { + assert.ifError(error); + assert.ok(!doc.createdAt); + assert.ok(doc.updatedAt); + assert.ok(doc.updatedAt.valueOf() >= startTime); + done(); + }); + }); + }); + + it('does not override nested timestamp params defined in schema (gh-4868)', function(done) { + var startTime = Date.now(); + var schema = new mongoose.Schema({ + ts: { + createdAt: { + type: Date, + select: false + }, + updatedAt: { + type: Date, + select: true + } + }, + name: String + }, { timestamps: { createdAt: 'ts.createdAt', updatedAt: 'ts.updatedAt' } }); + var M = db.model('gh4868_0', schema); + + M.create({ name: 'Test' }, function(error) { + assert.ifError(error); + M.findOne({}, function(error, doc) { + assert.ifError(error); + assert.ok(!doc.ts.createdAt); + assert.ok(doc.ts.updatedAt); + assert.ok(doc.ts.updatedAt.valueOf() >= startTime); + done(); + }); + }); + }); + + it('does not override timestamps in nested schema (gh-4868)', function(done) { + var startTime = Date.now(); + var tsSchema = new mongoose.Schema({ + createdAt: { + type: Date, + select: false + }, + updatedAt: { + type: Date, + select: true + } + }); + var schema = new mongoose.Schema({ + ts: tsSchema, + name: String + }, { timestamps: { createdAt: 'ts.createdAt', updatedAt: 'ts.updatedAt' } }); + var M = db.model('gh4868_1', schema); + + M.create({ name: 'Test' }, function(error) { + assert.ifError(error); + M.findOne({}, function(error, doc) { + assert.ifError(error); + assert.ok(!doc.ts.createdAt); + assert.ok(doc.ts.updatedAt); + assert.ok(doc.ts.updatedAt.valueOf() >= startTime); + done(); + }); + }); + }); +}); From cd6bd5d9b472c285fc0c3b328464da41b1004239 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Sun, 23 Apr 2017 16:40:30 +0700 Subject: [PATCH 1438/2240] Removed wrongly pushed file --- test.js | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 test.js diff --git a/test.js b/test.js deleted file mode 100644 index dcd9671216c..00000000000 --- a/test.js +++ /dev/null @@ -1,20 +0,0 @@ -var mongoose = require('./index'); - -var Schema = mongoose.Schema; -var TestSchema = new Schema({ - foo: { type: String, alias: 'Fap' }, - bar: { - baz: { type: String, alias: 'Fap' }, - kar: { type: String } - } -}); - -var Test = mongoose.model('Test', TestSchema); -var t = new Test({ - foo: 'hey', - bar: { - baz: 'sup' - } -}); - -console.log(t.Fap); \ No newline at end of file From 56b28a6fa774e83f5e509c974288b2cda4691072 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Sun, 23 Apr 2017 16:41:03 +0700 Subject: [PATCH 1439/2240] Throws on invalid schema alias option --- lib/schema.js | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 019ce018c2b..89448cbd01f 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -143,19 +143,23 @@ function aliasFields(schema) { var prop = schema.paths[path].path; var alias = schema.paths[path].options.alias; - if (alias && 'string' === typeof alias && alias.length > 0) { - schema - .virtual(alias) - .get((function(p) { - return function() { - return this.get(p); - }; - })(prop)) - .set((function(p) { - return function(v) { - return this.set(p, v); - }; - })(prop)); + if (alias) { + if ('string' === typeof alias && alias.length > 0) { + schema + .virtual(alias) + .get((function(p) { + return function() { + return this.get(p); + }; + })(prop)) + .set((function(p) { + return function(v) { + return this.set(p, v); + }; + })(prop)); + } else { + throw new Error('Invalid value for alias option on ' + prop + ', got ' + alias); + } } } } From 8ded28529a26d4c2df88bf78bd7d93e1a0d3421a Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Sun, 23 Apr 2017 16:41:37 +0700 Subject: [PATCH 1440/2240] Add schema alias option tests --- test/schema.alias.test.js | 105 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 test/schema.alias.test.js diff --git a/test/schema.alias.test.js b/test/schema.alias.test.js new file mode 100644 index 00000000000..2b81046e6d8 --- /dev/null +++ b/test/schema.alias.test.js @@ -0,0 +1,105 @@ + +/** + * Module dependencies. + */ + +var start = require('./common'), + mongoose = start.mongoose, + assert = require('power-assert'), + Schema = mongoose.Schema; + +describe('schema alias option', function() { + it('works with all basic schema types', function() { + var db = start(); + + var schema = new Schema({ + string: { type: String, alias: 'StringAlias' }, + number: { type: Number, alias: 'NumberAlias' }, + date: { type: Date, alias: 'DateAlias' }, + buffer: { type: Buffer, alias: 'BufferAlias' }, + boolean: { type: Boolean, alias: 'BooleanAlias' }, + mixed: { type: Schema.Types.Mixed, alias: 'MixedAlias' }, + objectId: { type: Schema.Types.ObjectId, alias: 'ObjectIdAlias'}, + array: { type: [], alias: 'ArrayAlias' } + }); + + var S = db.model('AliasSchemaType', schema); + S.create({ + string: 'hello', + number: 1, + date: new Date(), + buffer: Buffer.from('World'), + boolean: false, + mixed: [1, [], 'three', { four: 5 }], + objectId: new Schema.Types.ObjectId(), + array: ['a', 'b', 'c', 'd'] + }, function(err, s) { + assert.ifError(err); + + // Comparing with aliases + assert.equal(s.string, s.StringAlias); + assert.equal(s.number, s.NumberAlias); + assert.equal(s.date, s.DateAlias); + assert.equal(s.buffer, s.BufferAlias); + assert.equal(s.boolean, s.BooleanAlias); + assert.equal(s.mixed, s.MixedAlias); + assert.equal(s.objectId, s.ObjectIdAlias); + assert.equal(s.array, s.ArrayAlias); + }); + }); + + it('works with nested schema types', function() { + var db = start(); + + var schema = new Schema({ + nested: { + type: { + string: { type: String, alias: 'StringAlias' }, + number: { type: Number, alias: 'NumberAlias' }, + date: { type: Date, alias: 'DateAlias' }, + buffer: { type: Buffer, alias: 'BufferAlias' }, + boolean: { type: Boolean, alias: 'BooleanAlias' }, + mixed: { type: Schema.Types.Mixed, alias: 'MixedAlias' }, + objectId: { type: Schema.Types.ObjectId, alias: 'ObjectIdAlias'}, + array: { type: [], alias: 'ArrayAlias' } + }, + alias: 'NestedAlias' + } + }); + + var S = db.model('AliasNestedSchemaType', schema); + S.create({ + nested: { + string: 'hello', + number: 1, + date: new Date(), + buffer: Buffer.from('World'), + boolean: false, + mixed: [1, [], 'three', { four: 5 }], + objectId: new Schema.Types.ObjectId(), + array: ['a', 'b', 'c', 'd'] + } + }, function(err, s) { + assert.ifError(err); + + // Comparing with aliases + assert.equal(s.nested, s.NestedAlias); + assert.equal(s.nested.string, s.StringAlias); + assert.equal(s.nested.number, s.NumberAlias); + assert.equal(s.nested.date, s.DateAlias); + assert.equal(s.nested.buffer, s.BufferAlias); + assert.equal(s.nested.boolean, s.BooleanAlias); + assert.equal(s.nested.mixed, s.MixedAlias); + assert.equal(s.nested.objectId, s.ObjectIdAlias); + assert.equal(s.nested.array, s.ArrayAlias); + }); + }); + + it('throws when alias option is invalid', function() { + assert.throws(function() { + new Schema({ + foo: { type: String, alias: 456 } + }); + }); + }); +}); From 7976f4e2f8f3c282979de635fe75f9c6604dc6e6 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Sun, 23 Apr 2017 16:50:39 +0700 Subject: [PATCH 1441/2240] Replace Buffer.from with new Buffer in tests for backward compatability with older versions of node --- test/schema.alias.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/schema.alias.test.js b/test/schema.alias.test.js index 2b81046e6d8..f696e6f992d 100644 --- a/test/schema.alias.test.js +++ b/test/schema.alias.test.js @@ -28,7 +28,7 @@ describe('schema alias option', function() { string: 'hello', number: 1, date: new Date(), - buffer: Buffer.from('World'), + buffer: new Buffer('World'), boolean: false, mixed: [1, [], 'three', { four: 5 }], objectId: new Schema.Types.ObjectId(), @@ -73,7 +73,7 @@ describe('schema alias option', function() { string: 'hello', number: 1, date: new Date(), - buffer: Buffer.from('World'), + buffer: new Buffer('World'), boolean: false, mixed: [1, [], 'three', { four: 5 }], objectId: new Schema.Types.ObjectId(), From ca446b58265eacc9a150ab2a02899ab6d6447c97 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Apr 2017 19:56:28 -0600 Subject: [PATCH 1442/2240] chore: release 4.9.6 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 7f3481e3e64..0c7ef7e4e0a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,14 @@ +4.9.6 / 2017-04-23 +================== + * fix: update `parentArray` references when directly assigning document arrays #5192 [jhob](https://github.com/jhob) + * docs: improve schematype validator docs #5178 [milesbarr](https://github.com/milesbarr) + * fix(model): modify discriminator() class in place #5175 + * fix(model): handle bulkWrite updateMany casting #5172 [tzellman](https://github.com/tzellman) + * docs(model): fix replaceOne example for bulkWrite #5168 + * fix(document): don't create a new array subdoc when creating schema array #5162 + * fix(model): merge query hooks from discriminators #5147 + * fix(document): add parent() function to subdocument to match array subdoc #5134 + 4.9.5 / 2017-04-16 ================== * fix(query): correct $pullAll casting of null #5164 [Sebmaster](https://github.com/Sebmaster) diff --git a/package.json b/package.json index dec2f5d90c8..0513be60708 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.6-pre", + "version": "4.9.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4f2bd74156a0d5dcad26e0242b488a9ceb3b538b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Apr 2017 19:59:32 -0600 Subject: [PATCH 1443/2240] chore: now working on 4.9.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0513be60708..de290b331c0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.6", + "version": "4.9.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 908d209c1a2b8273549d8c2d7c71b9b3deee4e66 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 24 Apr 2017 20:53:22 -0600 Subject: [PATCH 1444/2240] fix: upgrade kareem to handle async pre hooks correctly Fix #5188 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index de290b331c0..9449d3cf94e 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "2.1.4", "bson": "~1.0.4", "hooks-fixed": "2.0.0", - "kareem": "1.4.0", + "kareem": "1.4.1", "mongodb": "2.2.26", "mpath": "0.2.1", "mpromise": "0.5.5", From ee4584de39bf7cd9f2000dc8c9b50a3fb6b3b743 Mon Sep 17 00:00:00 2001 From: Philip Hutchins Date: Wed, 26 Apr 2017 10:56:02 -0400 Subject: [PATCH 1445/2240] Updating documentation to not be contradictory --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index d54f5206146..d37e26b89ce 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1136,7 +1136,7 @@ Model.deleteOne = function deleteOne(conditions, callback) { }; /** - * Deletes the first document that matches `conditions` from the collection. + * Deletes all of the documents that match `conditions` from the collection. * Behaves like `remove()`, but deletes all documents that match `conditions` * regardless of the `justOne` option. * From 15809dffd31a1197beba4bc7fa79e11d7ad51357 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Apr 2017 10:54:00 -0600 Subject: [PATCH 1446/2240] docs: add details about unique not being a validator Fix #5179 --- docs/faq.jade | 38 ++++++++++++++++++++++++++++++ test/docs/validation.test.js | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/docs/faq.jade b/docs/faq.jade index 59bd3554e1a..9ca9d50f8de 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -30,6 +30,44 @@ block content doc.array[3] = 'changed'; doc.markModified('array'); doc.save(); + + hr#unique-doesnt-work + :markdown + **Q**. I declared a schema property as `unique` but I can still save duplicates. What gives? + + **A**. Mongoose doesn't handle `unique` on it's own, `{ name: { type: String, unique: true } }` + just a shorthand for creating a [MongoDB unique index on `name`](https://docs.mongodb.com/manual/core/index-unique/). + For example, if MongoDB doesn't already have a unique index on `name`, the below code will not error despite the fact that `unique` is true. + :js + var schema = new mongoose.Schema({ + name: { type: String, unique: true } + }); + var Model = db.model('Test', schema); + + Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) { + console.log(err); // No error, unless index was already built + }); + :markdown + However, if you wait for the index to build using the `Model.on('index')` event, attempts to save duplicates will correctly error. + :js + var schema = new mongoose.Schema({ + name: { type: String, unique: true } + }); + var Model = db.model('Test', schema); + + Model.on('index', function(err) { // <-- Wait for model's indexes to finish + assert.ifError(err); + Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) { + console.log(err); + }); + }); + :markdown + MongoDB persists indexes, so you only need to rebuild indexes if you're starting + with a fresh database or you ran `db.dropDatabase()`. In a production environment, + you should [create your indexes using the MongoDB shell])(https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/) + rather than relying on mongoose to do it for you. The `unique` option for schemas is + convenient for development and documentation, but mongoose is *not* an index management solution. + hr#date_changes :markdown **Q**. Why don't in-place modifications to date objects diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index e2c4c994154..33c9d36efcd 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -107,6 +107,51 @@ describe('validation docs', function() { // acquit:ignore:end }); + /** + * A common gotcha for beginners is that the `unique` option for schemas + * is *not* a validator. It's a convenient helper for building [MongoDB unique indexes](https://docs.mongodb.com/manual/core/index-unique/). + * See the [FAQ](/docs/faq.html) for more information. + */ + + it('The `unique` Option is Not a Validator', function(done) { + var uniqueUsernameSchema = new Schema({ + username: { + type: String, + unique: true + } + }); + var U1 = db.model('U1', uniqueUsernameSchema); + var U2 = db.model('U2', uniqueUsernameSchema); + // acquit:ignore:start + var remaining = 2; + // acquit:ignore:end + + var dup = [{ username: 'Val' }, { username: 'Val' }]; + U1.create(dup, function(error) { + // Will save successfully! + // acquit:ignore:start + assert.ifError(error); + --remaining || done(); + // acquit:ignore:end + }); + + // Need to wait for the index to finish building before saving, + // otherwise unique constraints may be violated. + U2.on('index', function(error) { + assert.ifError(error); + U2.create(dup, function(error) { + // Will error, but will *not* be a mongoose validation error, but + // a duplicate key error. + assert.ok(error); + assert.ok(!error.errors); + assert.ok(error.message.indexOf('duplicate key error') !== -1); + // acquit:ignore:start + --remaining || done(); + // acquit:ignore:end + }); + }); + }); + /** * If the built-in validators aren't enough, you can define custom validators * to suit your needs. From 4cc2a55dbd2fa070b9d94449ebcc1d307c9cf6f9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Apr 2017 22:55:49 -0600 Subject: [PATCH 1447/2240] test: repro #5171 --- test/schema.validation.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index b48cef24850..59732a9a079 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -681,6 +681,31 @@ describe('schema', function() { }); }); + it('custom validators with isAsync and promise (gh-5171)', function(done) { + var validate = function(v) { + return Promise.resolve(v === 'test'); + }; + + var schema = new Schema({ + x: { + type: String + } + }); + + schema.path('x').validate({ + isAsync: true, + validator: validate + }); + var M = mongoose.model('gh5171', schema); + + var m = new M({x: 'not test'}); + + m.validate(function(err) { + assert.ok(err.errors['x']); + done(); + }); + }); + it('supports custom properties (gh-2132)', function(done) { var schema = new Schema({ x: { From 9966920b08d7f7dd0952729b739b2eb807019b51 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Apr 2017 22:55:54 -0600 Subject: [PATCH 1448/2240] fix(validation): handle returning a promise with isAsync: true Fix #5171 --- lib/schematype.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/schematype.js b/lib/schematype.js index c79324432c6..e9e36972ae3 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -787,7 +787,12 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { */ function asyncValidate(validator, scope, value, props, cb) { + var called = false; var returnVal = validator.call(scope, value, function(ok, customMsg) { + if (called) { + return; + } + called = true; if (typeof returnVal === 'boolean') { return; } @@ -797,7 +802,27 @@ function asyncValidate(validator, scope, value, props, cb) { cb(ok, props); }); if (typeof returnVal === 'boolean') { + called = true; cb(returnVal, props); + } else if (returnVal && typeof returnVal.then === 'function') { + // Promise + returnVal.then( + function(ok) { + if (called) { + return; + } + called = true; + cb(ok, props); + }, + function(error) { + if (called) { + return; + } + called = true; + + props.reason = error; + cb(false, props); + }); } } From baedc21dfc707624f6cab2c202698132fb2b553e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Apr 2017 23:02:20 -0600 Subject: [PATCH 1449/2240] style: fix lint --- test/schema.validation.test.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 59732a9a079..997e9434738 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -2,16 +2,17 @@ * Module dependencies. */ -var start = require('./common'), - mongoose = start.mongoose, - assert = require('power-assert'), - Schema = mongoose.Schema, - ValidatorError = mongoose.Error.ValidatorError, - SchemaTypes = Schema.Types, - ObjectId = SchemaTypes.ObjectId, - Mixed = SchemaTypes.Mixed, - DocumentObjectId = mongoose.Types.ObjectId, - random = require('../lib/utils').random; +var start = require('./common'); +var mongoose = start.mongoose; +var assert = require('power-assert'); +var Schema = mongoose.Schema; +var ValidatorError = mongoose.Error.ValidatorError; +var SchemaTypes = Schema.Types; +var ObjectId = SchemaTypes.ObjectId; +var Mixed = SchemaTypes.Mixed; +var DocumentObjectId = mongoose.Types.ObjectId; +var random = require('../lib/utils').random; +var Promise = require('bluebird'); describe('schema', function() { describe('validation', function() { From e432de2fe04ddc7d8e5d7f1009d0ffe0a8f6199d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 28 Apr 2017 23:00:36 -0600 Subject: [PATCH 1450/2240] fix(schema): make remove a reserved name Fix #5197 --- lib/schema.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/schema.js b/lib/schema.js index 908761060d4..78e540eaa76 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -484,6 +484,7 @@ reserved.schema = reserved.set = reserved.toObject = reserved.validate = +reserved.remove = // hooks.js reserved._pres = reserved._posts = 1; From f204aa7e2776c9501b3d111c74e75e27be1c89e3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 29 Apr 2017 00:03:12 -0600 Subject: [PATCH 1451/2240] test(schema): repro #5199 --- test/model.indexes.test.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index 890a74656f3..b5406bf96dc 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -178,6 +178,38 @@ describe('model', function() { }); }); + it('nested embedded docs (gh-5199)', function(done) { + var db = start(); + + var SubSubSchema = mongoose.Schema({ + nested2: String + }); + + SubSubSchema.index({ nested2: 1 }); + + var SubSchema = mongoose.Schema({ + nested1: String, + subSub: SubSubSchema + }); + + SubSchema.index({ nested1: 1 }); + + var ContainerSchema = mongoose.Schema({ + nested0: String, + sub: SubSchema + }); + + ContainerSchema.index({ nested0: 1 }); + + assert.deepEqual(ContainerSchema.indexes().map(function(v) { return v[0]; }), [ + { 'sub.subSub.nested2': 1 }, + { 'sub.nested1': 1 }, + { 'nested0': 1 } + ]); + + done(); + }); + it('error should emit on the model', function(done) { var db = start(), schema = new Schema({name: {type: String}}), From 4771b05d261d45d4dc26e5611fe49a547f7d1668 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 29 Apr 2017 00:04:06 -0600 Subject: [PATCH 1452/2240] fix(schema): ensure correct path for deeply nested schema indexes Fix #5199 --- lib/schema.js | 12 ++++++++---- test/model.indexes.test.js | 2 -- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 78e540eaa76..3c4a297f199 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1365,13 +1365,15 @@ Schema.prototype.indexes = function() { 'use strict'; var indexes = []; - var seenPrefix = {}; + var schemaStack = []; var collectIndexes = function(schema, prefix) { - if (seenPrefix[prefix]) { + // Ignore infinitely nested schemas, if we've already seen this schema + // along this path there must be a cycle + if (schemaStack.indexOf(schema) !== -1) { return; } - seenPrefix[prefix] = true; + schemaStack.push(schema); prefix = prefix || ''; var key, path, index, field, isObject, options, type; @@ -1382,7 +1384,7 @@ Schema.prototype.indexes = function() { path = schema.paths[key]; if ((path instanceof MongooseTypes.DocumentArray) || path.$isSingleNested) { - collectIndexes(path.schema, key + '.'); + collectIndexes(path.schema, prefix + key + '.'); } else { index = path._index; @@ -1413,6 +1415,8 @@ Schema.prototype.indexes = function() { } } + schemaStack.pop(); + if (prefix) { fixSubIndexPaths(schema, prefix); } else { diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index b5406bf96dc..34b57ba7a4a 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -179,8 +179,6 @@ describe('model', function() { }); it('nested embedded docs (gh-5199)', function(done) { - var db = start(); - var SubSubSchema = mongoose.Schema({ nested2: String }); From 958bbb2da5b18cad49b80a3ddcf852930b6f3e29 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 29 Apr 2017 23:38:03 -0600 Subject: [PATCH 1453/2240] test(model): repro #5190 --- test/model.test.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index 667eefd74b5..d79a9918e49 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5569,6 +5569,18 @@ describe('Model', function() { }); }); + it('insertMany with Decimal (gh-5190)', function(done) { + var schema = new mongoose.Schema({ + amount : mongoose.Schema.Types.Decimal + }); + var Money = db.model('gh5190', schema); + + Money.insertMany([{ amount : '123.45' }], function(error) { + assert.ifError(error); + done(); + }); + }); + it('bulkWrite casting updateMany, deleteOne, deleteMany (gh-3998)', function(done) { var schema = new Schema({ str: String, From 773639adbde210945598fcd6cf11a65d418fe5f2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 29 Apr 2017 23:56:08 -0600 Subject: [PATCH 1454/2240] fix(model): handle Decimal type in insertMany correctly Fix #5190 --- lib/model.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/model.js b/lib/model.js index d37e26b89ce..ceca5367365 100644 --- a/lib/model.js +++ b/lib/model.js @@ -27,12 +27,6 @@ var VERSION_WHERE = 1, VERSION_INC = 2, VERSION_ALL = VERSION_WHERE | VERSION_INC; -var POJO_TO_OBJECT_OPTIONS = { - depopulate: true, - transform: false, - _skipDepopulateTopLevel: true -}; - /** * Model constructor * @@ -1945,6 +1939,17 @@ Model.create = function create(doc, callback) { return promise; }; +/*! + * ignore + */ + +var INSERT_MANY_CONVERT_OPTIONS = { + depopulate: true, + transform: false, + _skipDepopulateTopLevel: true, + flattenDecimals: false +}; + /** * Shortcut for validating an array of documents and inserting them into * MongoDB if they're all valid. This function is faster than `.create()` @@ -2017,10 +2022,11 @@ Model.insertMany = function(arr, options, callback) { doc[doc.schema.options.versionKey] = 0; } if (doc.initializeTimestamps) { - return doc.initializeTimestamps().toObject(POJO_TO_OBJECT_OPTIONS); + return doc.initializeTimestamps().toObject(INSERT_MANY_CONVERT_OPTIONS); } - return doc.toObject(POJO_TO_OBJECT_OPTIONS); + return doc.toObject(INSERT_MANY_CONVERT_OPTIONS); }); + _this.collection.insertMany(docObjects, options, function(error) { if (error) { callback && callback(error); From 1b2d1cd33f2ec6c93b709682e9c8680cb44106be Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 30 Apr 2017 20:16:52 -0600 Subject: [PATCH 1455/2240] test: fix #5190 tests for < 3.4 --- test/model.test.js | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/test/model.test.js b/test/model.test.js index d79a9918e49..2429b9f3549 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5570,15 +5570,31 @@ describe('Model', function() { }); it('insertMany with Decimal (gh-5190)', function(done) { - var schema = new mongoose.Schema({ - amount : mongoose.Schema.Types.Decimal - }); - var Money = db.model('gh5190', schema); + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + done(); + return; + } - Money.insertMany([{ amount : '123.45' }], function(error) { - assert.ifError(error); - done(); + test(); }); + + function test() { + var schema = new mongoose.Schema({ + amount : mongoose.Schema.Types.Decimal + }); + var Money = db.model('gh5190', schema); + + Money.insertMany([{ amount : '123.45' }], function(error) { + assert.ifError(error); + done(); + }); + } }); it('bulkWrite casting updateMany, deleteOne, deleteMany (gh-3998)', function(done) { From d29a1157836c5517babffa566f38b916e34fb7bd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 30 Apr 2017 20:24:26 -0600 Subject: [PATCH 1456/2240] chore: release 4.9.7 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0c7ef7e4e0a..bc1976a3caf 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.9.7 / 2017-04-30 +================== + * docs: fix typo #5204 [phutchins](https://github.com/phutchins) + * fix(schema): ensure correct path for deeply nested schema indexes #5199 + * fix(schema): make remove a reserved name #5197 + * fix(model): handle Decimal type in insertMany correctly #5190 + * fix: upgrade kareem to handle async pre hooks correctly #5188 + * docs: add details about unique not being a validator #5179 + * fix(validation): handle returning a promise with isAsync: true #5171 + 4.9.6 / 2017-04-23 ================== * fix: update `parentArray` references when directly assigning document arrays #5192 [jhob](https://github.com/jhob) diff --git a/package.json b/package.json index 9449d3cf94e..e5e97640d80 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.7-pre", + "version": "4.9.7", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From f93f65d0cd4713ac9340b73ec607b44e4005d665 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 30 Apr 2017 20:29:12 -0600 Subject: [PATCH 1457/2240] chore: now working on 4.9.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e5e97640d80..1927e1963cb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.7", + "version": "4.9.8-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a5f506953c92796674835e43e11c9635c89bcd69 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 1 May 2017 22:50:16 -0600 Subject: [PATCH 1458/2240] perf(schema): skip heavy getAllSubdocs if already saving Re: #5191 --- lib/schema.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 3c4a297f199..b3f70c9afd1 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -214,10 +214,16 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { hook: 'save', isAsync: true, fn: function(next, done) { + if (this.$__preSavingFromParent) { + done(); + next(); + return; + } + var _this = this; var subdocs = this.$__getAllSubdocs(); - if (!subdocs.length || this.$__preSavingFromParent) { + if (!subdocs.length) { done(); next(); return; From eddfe914ee663fd5ff80f981ab18372d8e3ddb9a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 2 May 2017 22:47:37 -0600 Subject: [PATCH 1459/2240] docs(subdocs): rewrite subdocs guide Fix #5217 --- docs/subdocs.jade | 126 ++++++++++++++++++++++++++++++---------------- 1 file changed, 83 insertions(+), 43 deletions(-) diff --git a/docs/subdocs.jade b/docs/subdocs.jade index 90a4306eca7..dbbc4c79f5e 100644 --- a/docs/subdocs.jade +++ b/docs/subdocs.jade @@ -3,47 +3,101 @@ extends layout block content h2 Sub Docs :markdown - [Sub-documents](./api.html#types-embedded-js) are docs with schemas of - their own which are elements of a parent document array: + Subdocuments are documents embedded in other documents. In Mongoose, this + means you can nest schemas in other schemas. Mongoose has two + distinct notions of subdocuments: arrays of subdocuments and single nested + subdocuments. :js var childSchema = new Schema({ name: 'string' }); var parentSchema = new Schema({ - children: [childSchema] - }) + // Array of subdocuments + children: [childSchema], + // Single nested subdocuments. Caveat: single nested subdocs only work + // in mongoose >= 4.2.0 + child: childSchema + }); :markdown - Sub-documents enjoy all the same features as normal - [documents](./api.html#document-js). The only difference is that they are + Subdocuments are similar to normal documents. Nested schemas can have + [middleware](http://mongoosejs.com/docs/middleware.html), [custom validation logic](http://mongoosejs.com/docs/middleware.html), + virtuals, and any other feature top-level schemas can use. The major + difference is that subdocuments are not saved individually, they are saved whenever their top-level parent document is saved. :js var Parent = mongoose.model('Parent', parentSchema); var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) parent.children[0].name = 'Matthew'; + + // `parent.children[0].save()` is a no-op, it triggers middleware but + // does **not** actually save the subdocument. You need to save the parent + // doc. parent.save(callback); :markdown - If an error occurs in a sub-document's middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap! + Subdocuments have `save` and `validate` [middleware](http://mongoosejs.com/docs/middleware.html) + just like top-level documents. Calling `save()` on the parent document triggers + the `save()` middleware for all its subdocuments, and the same for `validate()` + middleware. :js childSchema.pre('save', function (next) { - if ('invalid' == this.name) return next(new Error('#sadpanda')); + if ('invalid' == this.name) { + return next(new Error('#sadpanda')); + } next(); }); var parent = new Parent({ children: [{ name: 'invalid' }] }); parent.save(function (err) { console.log(err.message) // #sadpanda - }) + }); + + :markdown + Subdocuments' `pre('save')` and `pre('validate')` middleware execute + **before** the top-level document's `pre('save')` but **after** the + top-level document's `pre('validate')` middleware. This is because validating + before `save()` is actually a piece of built-in middleware. + + :js + // Below code will print out 1-4 in order + var childSchema = new mongoose.Schema({ name: 'string' }); + + childSchema.pre('validate', function(next) { + console.log('2'); + next(); + }); + + childSchema.pre('save', function(next) { + console.log('3'); + next(); + }); + + var parentSchema = new mongoose.Schema({ + child: childSchema, + }); + + parentSchema.pre('validate', function(next) { + console.log('1'); + next(); + }); + + parentSchema.pre('save', function(next) { + console.log('4'); + next(); + }); + h3 Finding a sub-document :markdown - Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. + Each subdocument has an `_id` by default. Mongoose document arrays have a + special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method + for searching a document array to find a document with a given `_id`. :js var doc = parent.children.id(_id); - h3 Adding sub-docs + h3 Adding sub-docs to arrays :markdown MongooseArray methods such as [push](./api.html#types_array_MongooseArray.push), @@ -71,50 +125,36 @@ block content :js var newdoc = parent.children.create({ name: 'Aaron' }); - h3 Removing docs + h3 Removing subdocs :markdown - Each sub-document has it's own - [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. + Each subdocument has it's own + [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. For + an array subdocument, this is equivalent to calling `.pull()` on the + subdocument. For a single nested subdocument, `remove()` is equivalent + to setting the subdocument to `null`. :js - var doc = parent.children.id(_id).remove(); + // Equivalent to `parent.children.pull(_id)` + parent.children.id(_id).remove(); + // Equivalent to `parent.child = null` + parent.child.remove(); parent.save(function (err) { if (err) return handleError(err); - console.log('the sub-doc was removed') + console.log('the subdocs were removed'); }); - h4#altsyntax Alternate declaration syntax + h4#altsyntax Alternate declaration syntax for arrays :markdown - If you don't need access to the sub-document schema instance, - you may also declare sub-docs by simply passing an object literal: + If you create a schema with an array of objects, mongoose will automatically + convert the object to a schema for you: :js var parentSchema = new Schema({ children: [{ name: 'string' }] - }) - - h4#single-embedded Single Embedded Subdocs - :markdown - **New in 4.2.0** - - You can also embed schemas without using arrays. - :js - var childSchema = new Schema({ name: 'string' }); - - var parentSchema = new Schema({ - child: childSchema }); - :markdown - A single embedded sub-document behaves similarly to an embedded array. - It only gets saved when the parent document gets saved and its pre/post - document middleware gets executed. - :js - childSchema.pre('save', function(next) { - console.log(this.name); // prints 'Leia' + // Equivalent + var parentSchema = new Schema({ + children: [new Schema({ name: 'string' })] }); - var Parent = mongoose.model('Parent', parentSchema); - var parent = new Parent({ child: { name: 'Luke' } }) - parent.child.name = 'Leia'; - parent.save(callback); // Triggers the pre middleware. - + h3#next Next Up :markdown Now that we've covered `Sub-documents`, let's take a look at From 4a817b8ab6b7ed88db20436298cf38163e3252d4 Mon Sep 17 00:00:00 2001 From: Vasyl Dorozhynskiy Date: Thu, 4 May 2017 14:44:06 +0300 Subject: [PATCH 1460/2240] Update model.js --- lib/model.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index ceca5367365..62e56f3b79a 100644 --- a/lib/model.js +++ b/lib/model.js @@ -637,7 +637,8 @@ Model.prototype.$__version = function(where, delta) { // $push $addToSet don't need the where clause set if (VERSION_WHERE === (VERSION_WHERE & this.$__.version)) { - where[key] = this.getValue(key); + var value = this.getValue(key); + if (value) where[key] = value; } if (VERSION_INC === (VERSION_INC & this.$__.version)) { From 65dc6c071fabcb66f9fa3c4b6f792e0b06031cdf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 May 2017 16:47:00 -0600 Subject: [PATCH 1461/2240] perf(document): make validate not re-compute all subdocs if in a subdoc Re: #5191 --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 8893c91f101..7d856f66d08 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1360,7 +1360,7 @@ function _getPathsToValidate(doc) { paths = paths.concat(Object.keys(doc.$__.activePaths.states.modify)); paths = paths.concat(Object.keys(doc.$__.activePaths.states.default)); - var subdocs = doc.$__getAllSubdocs(); + var subdocs = doc.ownerDocument ? [] : doc.$__getAllSubdocs(); var subdoc; var len = subdocs.length; for (i = 0; i < len; ++i) { From 6fb5802c6c1c3031cc1c00471de5805ac31274f0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 May 2017 14:10:19 -0600 Subject: [PATCH 1462/2240] fix(schema): throw error if first param to schema.plugin() is not a function Fix #5201 --- lib/schema.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index b3f70c9afd1..86a3cf06bd0 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1187,6 +1187,10 @@ Schema.prototype.post = function(method, fn) { */ Schema.prototype.plugin = function(fn, opts) { + if (typeof fn !== 'function') { + throw new Error('First param to `schema.plugin()` must be a function, ' + + 'got "' + (typeof fn) + '"'); + } fn(this, opts); return this; }; From f7264b771f55474131cf0acebb73aa0800cf9655 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 May 2017 15:43:24 -0600 Subject: [PATCH 1463/2240] test(document): repro #5208 --- test/document.test.js | 59 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index f26e9dfc64b..65b1ab3fdc5 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3986,6 +3986,65 @@ describe('document', function() { done(); }); + it('JSON.stringify nested errors (gh-5208)', function(done) { + var AdditionalContactSchema = new Schema({ + contactName: { + type: String, + required: true + }, + contactValue: { + type: String, + required: true + } + }); + + var ContactSchema = new Schema({ + name: { + type: String, + required: true + }, + email: { + type: String, + required: true + }, + additionalContacts: [AdditionalContactSchema] + }); + + var EmergencyContactSchema = new Schema({ + contactName: { + type: String, + required: true + }, + contact: ContactSchema + }); + + var EmergencyContact = + db.model('EmergencyContact', EmergencyContactSchema); + + var contact = new EmergencyContact({ + contactName: 'Electrical Service', + contact: { + name: 'John Smith', + email: 'john@gmail.com', + additionalContacts: [ + { + contactName: 'skype', + // Forgotten value + } + ] + } + }); + contact.validate(function(error) { + assert.ok(error); + assert.ok(error.errors['contact']); + assert.ok(error.errors['contact.additionalContacts.0.contactValue']); + + // This `JSON.stringify()` should not throw + assert.ok(JSON.stringify(error).indexOf('contactValue') !== -1); + done(); + }); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From a93c2ad97589995dc1505856a5f974d2f173b284 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 May 2017 15:43:56 -0600 Subject: [PATCH 1464/2240] fix(document): avoid circular JSON if error in doc array under single nested subdoc Fix #5208 --- lib/types/subdocument.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index d788686dc00..5ad19c4684d 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -71,7 +71,13 @@ Subdocument.prototype.$markValid = function(path) { }; Subdocument.prototype.invalidate = function(path, err, val) { - Document.prototype.invalidate.call(this, path, err, val); + // Hack: array subdocuments' validationError is equal to the owner doc's, + // so validating an array subdoc gives the top-level doc back. Temporary + // workaround for #5208 so we don't have circular errors. + if (err !== this.ownerDocument().$__.validationError) { + Document.prototype.invalidate.call(this, path, err, val); + } + if (this.$parent) { this.$parent.invalidate([this.$basePath, path].join('.'), err, val); } else if (err.kind === 'cast' || err.name === 'CastError') { From 549b73e4feee5ce6e0cbbd32534a50e050b91626 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 5 May 2017 15:49:05 -0600 Subject: [PATCH 1465/2240] style: fix lint --- test/document.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/document.test.js b/test/document.test.js index 65b1ab3fdc5..a5c83a5dc03 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4028,7 +4028,7 @@ describe('document', function() { email: 'john@gmail.com', additionalContacts: [ { - contactName: 'skype', + contactName: 'skype' // Forgotten value } ] From d1a8e280b1f2f3e52e1ce459c09a685c414350bb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 May 2017 18:34:57 -0600 Subject: [PATCH 1466/2240] test(document): repro #5206 --- test/document.test.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index a5c83a5dc03..2b8d8afe757 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3367,6 +3367,36 @@ describe('document', function() { }); }); + it('setting a nested path retains nested modified paths (gh-5206)', function(done) { + var testSchema = new mongoose.Schema({ + name: String, + surnames: { + docarray: [{ name: String }] + } + }); + + var Cat = db.model('gh5206', testSchema); + + var kitty = new Cat({ + name: 'Test', + surnames: { + docarray: [{ name: 'test1' }, { name: 'test2' }] + } + }); + + kitty.save(function(error) { + assert.ifError(error); + + kitty.surnames = { + docarray: [{ name: 'test1' }, { name: 'test2' }, { name: 'test3' }] + }; + + assert.deepEqual(kitty.modifiedPaths(), + ['surnames', 'surnames.docarray']); + done(); + }); + }); + it('toObject() does not depopulate top level (gh-3057)', function(done) { var Cat = db.model('gh3057', { name: String }); var Human = db.model('gh3057_0', { From b18360c74de3d0eb665422dc8b34351c829f3256 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 May 2017 18:39:39 -0600 Subject: [PATCH 1467/2240] fix(document): set intermediate empty objects for deeply nested undefined paths before path itself Fix #5206 --- lib/document.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 7d856f66d08..4f9ad2aa3f1 100644 --- a/lib/document.js +++ b/lib/document.js @@ -663,6 +663,18 @@ Document.prototype.set = function(path, val, type, options) { var schema; var parts = path.split('.'); + // gh-4578, if setting a deeply nested path that doesn't exist yet, create it + var cur = this._doc; + var curPath = ''; + for (i = 0; i < parts.length - 1; ++i) { + cur = cur[parts[i]]; + curPath += (curPath.length > 0 ? '.' : '') + parts[i]; + if (!cur) { + this.set(curPath, {}); + cur = this.getValue(curPath); + } + } + if (pathType === 'adhocOrUndefined' && strict) { // check for roots that are Mixed types var mixed; @@ -917,7 +929,7 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) { obj = obj[parts[i]]; } else { - this.set(cur, {}); + obj[parts[i]] = obj[parts[i]] || {}; obj = obj[parts[i]]; } } From 832ef19709e7139645ee0929b1363c88a4660a9f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 May 2017 19:13:26 -0600 Subject: [PATCH 1468/2240] perf: trim out some more unnecessary work re: #5191 --- lib/document.js | 35 +++++++++++++++++++++++------------ lib/schema/array.js | 2 ++ lib/schema/documentarray.js | 6 +++++- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/lib/document.js b/lib/document.js index 4f9ad2aa3f1..4fb46147d1b 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1372,15 +1372,17 @@ function _getPathsToValidate(doc) { paths = paths.concat(Object.keys(doc.$__.activePaths.states.modify)); paths = paths.concat(Object.keys(doc.$__.activePaths.states.default)); - var subdocs = doc.ownerDocument ? [] : doc.$__getAllSubdocs(); - var subdoc; - var len = subdocs.length; - for (i = 0; i < len; ++i) { - subdoc = subdocs[i]; - if (subdoc.$isSingleNested && - doc.isModified(subdoc.$basePath) && - !doc.isDirectModified(subdoc.$basePath)) { - paths.push(subdoc.$basePath); + if (!doc.ownerDocument) { + var subdocs = doc.$__getAllSubdocs(); + var subdoc; + var len = subdocs.length; + for (i = 0; i < len; ++i) { + subdoc = subdocs[i]; + if (subdoc.$isSingleNested && + doc.isModified(subdoc.$basePath) && + !doc.isDirectModified(subdoc.$basePath)) { + paths.push(subdoc.$basePath); + } } } @@ -1388,8 +1390,14 @@ function _getPathsToValidate(doc) { // the children as well for (i = 0; i < paths.length; ++i) { var path = paths[i]; + + var _pathType = doc.schema.path(path); + if (!_pathType || !_pathType.$isMongooseArray || _pathType.$isMongooseDocumentArray) { + continue; + } + var val = doc.getValue(path); - if (val && val.isMongooseArray && !Buffer.isBuffer(val) && !val.isMongooseDocumentArray) { + if (val) { var numElements = val.length; for (var j = 0; j < numElements; ++j) { paths.push(path + '.' + j); @@ -1443,7 +1451,7 @@ Document.prototype.$__validate = function(callback) { var paths = _getPathsToValidate(this); if (paths.length === 0) { - process.nextTick(function() { + return process.nextTick(function() { var error = _complete(); if (error) { return _this.schema.s.hooks.execPost('validate:error', _this, [ _this], { error: error }, function(error) { @@ -1497,7 +1505,10 @@ Document.prototype.$__validate = function(callback) { }); }; - paths.forEach(validatePath); + var numPaths = paths.length; + for (var i = 0; i < numPaths; ++i) { + validatePath(paths[i]); + } }; /** diff --git a/lib/schema/array.js b/lib/schema/array.js index f758e3ed969..b1ec0bae72e 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -74,6 +74,8 @@ function SchemaArray(key, cast, options, schemaOptions) { } } + this.$isMongooseArray = true; + SchemaType.call(this, key, options, 'Array'); var defaultArr; diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 8e88816fcef..ddf7339849b 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -132,7 +132,9 @@ DocumentArray.prototype.discriminator = function(name, schema) { DocumentArray.prototype.doValidate = function(array, fn, scope, options) { var _this = this; + var s1 = Date.now(); SchemaType.prototype.doValidate.call(this, array, function(err) { + //console.log('DoValidate', Date.now() - s1); if (err) { return fn(err); } @@ -155,9 +157,10 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { if (err) { error = err; } - --count || fn(error); + --count || (function() { /*console.log('Validate elements', Date.now() - s);*/ fn(error); })(); } + var s = Date.now(); for (var i = 0, len = count; i < len; ++i) { // sidestep sparse entries var doc = array[i]; @@ -181,6 +184,7 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { doc.validate({__noPromise: true}, callback); } } + //console.log('block time', Date.now() - s); }, scope); }; From 923b4d763775faf6db60699bf526126569586acc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 May 2017 21:21:00 -0600 Subject: [PATCH 1469/2240] perf(schema): remove unnecessary default middleware for subdocs Fix #5191 --- lib/index.js | 9 +++ lib/plugins/saveSubdocs.js | 35 +++++++++++ lib/plugins/validateBeforeSave.js | 45 +++++++++++++++ lib/schema.js | 90 ++--------------------------- lib/services/model/discriminator.js | 3 +- test/schema.test.js | 6 +- 6 files changed, 99 insertions(+), 89 deletions(-) create mode 100644 lib/plugins/saveSubdocs.js create mode 100644 lib/plugins/validateBeforeSave.js diff --git a/lib/index.js b/lib/index.js index e0c644557e6..1e3f60143ba 100644 --- a/lib/index.js +++ b/lib/index.js @@ -17,6 +17,8 @@ var Schema = require('./schema'), pkg = require('../package.json'); var querystring = require('querystring'); +var saveSubdocs = require('./plugins/saveSubdocs'); +var validateBeforeSave = require('./plugins/validateBeforeSave'); var Aggregate = require('./aggregate'); var PromiseProvider = require('./promise_provider'); @@ -364,6 +366,13 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) { } if (schema) { + // Reverse order because these both unshift() + if (!schema._plugins.saveSubdocs) { + schema.plugin(saveSubdocs); + } + if (!schema._plugins.validateBeforeSave) { + schema.plugin(validateBeforeSave); + } this._applyPlugins(schema); } diff --git a/lib/plugins/saveSubdocs.js b/lib/plugins/saveSubdocs.js new file mode 100644 index 00000000000..8f650bc0e2e --- /dev/null +++ b/lib/plugins/saveSubdocs.js @@ -0,0 +1,35 @@ +'use strict'; + +var each = require('async/each'); + +module.exports = function(schema) { + schema._plugins.saveSubdocs = true; + + schema.callQueue.unshift(['pre', ['save', function(next) { + if (this.ownerDocument) { + next(); + return; + } + + var _this = this; + var subdocs = this.$__getAllSubdocs(); + + if (!subdocs.length) { + next(); + return; + } + + each(subdocs, function(subdoc, cb) { + subdoc.save(function(err) { + cb(err); + }); + }, function(error) { + if (error) { + return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { + next(error); + }); + } + next(); + }); + }]]); +}; diff --git a/lib/plugins/validateBeforeSave.js b/lib/plugins/validateBeforeSave.js new file mode 100644 index 00000000000..6101a2561a1 --- /dev/null +++ b/lib/plugins/validateBeforeSave.js @@ -0,0 +1,45 @@ +'use strict'; + +module.exports = function(schema) { + schema._plugins.validateBeforeSave = true; + + schema.callQueue.unshift(['pre', ['save', function(next, options) { + var _this = this; + // Nested docs have their own presave + if (this.ownerDocument) { + return next(); + } + + var hasValidateBeforeSaveOption = options && + (typeof options === 'object') && + ('validateBeforeSave' in options); + + var shouldValidate; + if (hasValidateBeforeSaveOption) { + shouldValidate = !!options.validateBeforeSave; + } else { + shouldValidate = this.schema.options.validateBeforeSave; + } + + // Validate + if (shouldValidate) { + // HACK: use $__original_validate to avoid promises so bluebird doesn't + // complain + if (this.$__original_validate) { + this.$__original_validate({__noPromise: true}, function(error) { + return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { + next(error); + }); + }); + } else { + this.validate({__noPromise: true}, function(error) { + return _this.schema.s.hooks.execPost('save:error', _this, [ _this], { error: error }, function(error) { + next(error); + }); + }); + } + } else { + next(); + } + }]]); +} diff --git a/lib/schema.js b/lib/schema.js index 86a3cf06bd0..9b90b120986 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -86,6 +86,7 @@ function Schema(obj, options) { this.tree = {}; this.query = {}; this.childSchemas = []; + this._plugins = {}; this.s = { hooks: new Kareem(), @@ -107,9 +108,9 @@ function Schema(obj, options) { (!this.options.noId && this.options._id) && !_idSubDoc; if (auto_id) { - obj = {_id: {auto: true}}; - obj._id[this.options.typeKey] = Schema.ObjectId; - this.add(obj); + var _obj = {_id: {auto: true}}; + _obj._id[this.options.typeKey] = Schema.ObjectId; + this.add(_obj); } // ensure the documents receive an id getter unless disabled @@ -166,88 +167,6 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { enumerable: false, writable: false, value: [ - { - kind: 'pre', - hook: 'save', - fn: function(next, options) { - var _this = this; - // Nested docs have their own presave - if (this.ownerDocument) { - return next(); - } - - var hasValidateBeforeSaveOption = options && - (typeof options === 'object') && - ('validateBeforeSave' in options); - - var shouldValidate; - if (hasValidateBeforeSaveOption) { - shouldValidate = !!options.validateBeforeSave; - } else { - shouldValidate = this.schema.options.validateBeforeSave; - } - - // Validate - if (shouldValidate) { - // HACK: use $__original_validate to avoid promises so bluebird doesn't - // complain - if (this.$__original_validate) { - this.$__original_validate({__noPromise: true}, function(error) { - return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { - next(error); - }); - }); - } else { - this.validate({__noPromise: true}, function(error) { - return _this.schema.s.hooks.execPost('save:error', _this, [ _this], { error: error }, function(error) { - next(error); - }); - }); - } - } else { - next(); - } - } - }, - { - kind: 'pre', - hook: 'save', - isAsync: true, - fn: function(next, done) { - if (this.$__preSavingFromParent) { - done(); - next(); - return; - } - - var _this = this; - var subdocs = this.$__getAllSubdocs(); - - if (!subdocs.length) { - done(); - next(); - return; - } - - each(subdocs, function(subdoc, cb) { - subdoc.$__preSavingFromParent = true; - subdoc.save(function(err) { - cb(err); - }); - }, function(error) { - for (var i = 0; i < subdocs.length; ++i) { - delete subdocs[i].$__preSavingFromParent; - } - if (error) { - return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { - done(error); - }); - } - next(); - done(); - }); - } - }, { kind: 'pre', hook: 'validate', @@ -354,6 +273,7 @@ Schema.prototype.clone = function() { s.callQueue = this.callQueue.map(function(f) { return f; }); s.methods = utils.clone(this.methods); s.statics = utils.clone(this.statics); + s._plugins = utils.clone(this._plugins); s.s.hooks = this.s.hooks.clone(); return s; }; diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 91bb0fce8ae..95a7d01e39b 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -84,7 +84,8 @@ module.exports = function discriminator(model, name, schema) { schema.options.id = id; schema.s.hooks = model.schema.s.hooks.merge(schema.s.hooks); - schema.callQueue = baseSchema.callQueue.concat(schema.callQueue.slice(schema._defaultMiddleware.length)); + schema.callQueue = baseSchema.callQueue. + concat(schema.callQueue.slice(schema._defaultMiddleware.length)); schema._requiredpaths = undefined; // reset just in case Schema#requiredPaths() was called on either schema } diff --git a/test/schema.test.js b/test/schema.test.js index b7b2dc7e970..d76995a661e 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -772,15 +772,15 @@ describe('schema', function() { Tobi.pre('save', function() { }); - assert.equal(Tobi.callQueue.length, 5); + assert.equal(Tobi.callQueue.length, 3); Tobi.post('save', function() { }); - assert.equal(Tobi.callQueue.length, 6); + assert.equal(Tobi.callQueue.length, 4); Tobi.pre('save', function() { }); - assert.equal(Tobi.callQueue.length, 7); + assert.equal(Tobi.callQueue.length, 5); done(); }); }); From b81d42a03164b67a3eb3639cdc28fb716a19cf9c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 May 2017 21:26:06 -0600 Subject: [PATCH 1470/2240] style: fix lint --- lib/plugins/validateBeforeSave.js | 2 +- lib/schema/documentarray.js | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/plugins/validateBeforeSave.js b/lib/plugins/validateBeforeSave.js index 6101a2561a1..1100761d386 100644 --- a/lib/plugins/validateBeforeSave.js +++ b/lib/plugins/validateBeforeSave.js @@ -42,4 +42,4 @@ module.exports = function(schema) { next(); } }]]); -} +}; diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index ddf7339849b..8e88816fcef 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -132,9 +132,7 @@ DocumentArray.prototype.discriminator = function(name, schema) { DocumentArray.prototype.doValidate = function(array, fn, scope, options) { var _this = this; - var s1 = Date.now(); SchemaType.prototype.doValidate.call(this, array, function(err) { - //console.log('DoValidate', Date.now() - s1); if (err) { return fn(err); } @@ -157,10 +155,9 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { if (err) { error = err; } - --count || (function() { /*console.log('Validate elements', Date.now() - s);*/ fn(error); })(); + --count || fn(error); } - var s = Date.now(); for (var i = 0, len = count; i < len; ++i) { // sidestep sparse entries var doc = array[i]; @@ -184,7 +181,6 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { doc.validate({__noPromise: true}, callback); } } - //console.log('block time', Date.now() - s); }, scope); }; From df1893b98c4c9e8cd1c79935a73ac4fbcc796d37 Mon Sep 17 00:00:00 2001 From: Vasyl Dorozhynskiy Date: Sun, 7 May 2017 09:47:47 +0300 Subject: [PATCH 1471/2240] Update model.js - __v == 0 fix --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 62e56f3b79a..1ab0bcaad29 100644 --- a/lib/model.js +++ b/lib/model.js @@ -638,7 +638,7 @@ Model.prototype.$__version = function(where, delta) { // $push $addToSet don't need the where clause set if (VERSION_WHERE === (VERSION_WHERE & this.$__.version)) { var value = this.getValue(key); - if (value) where[key] = value; + if (value != null) where[key] = value; } if (VERSION_INC === (VERSION_INC & this.$__.version)) { From 29eea24d489415e87c0a573b0cc2ed84ebcb22e5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 May 2017 13:05:00 -0600 Subject: [PATCH 1472/2240] chore: release 4.9.8 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index bc1976a3caf..5e478f43ec7 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.9.8 / 2017-05-07 +================== + * docs(subdocs): rewrite subdocs guide #5217 + * fix(document): avoid circular JSON if error in doc array under single nested subdoc #5208 + * fix(document): set intermediate empty objects for deeply nested undefined paths before path itself #5206 + * fix(schema): throw error if first param to schema.plugin() is not a function #5201 + * perf(document): major speedup in validating subdocs (50x in some cases) #5191 + 4.9.7 / 2017-04-30 ================== * docs: fix typo #5204 [phutchins](https://github.com/phutchins) diff --git a/package.json b/package.json index 1927e1963cb..5db777c03c1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.8-pre", + "version": "4.9.8", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From f6c52ba839d7c0dbaca7292babbc8200e5fc02e8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 May 2017 13:07:35 -0600 Subject: [PATCH 1473/2240] chore: add missing docs --- lib/plugins/saveSubdocs.js | 4 ++++ lib/plugins/validateBeforeSave.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lib/plugins/saveSubdocs.js b/lib/plugins/saveSubdocs.js index 8f650bc0e2e..c51a8e117d1 100644 --- a/lib/plugins/saveSubdocs.js +++ b/lib/plugins/saveSubdocs.js @@ -2,6 +2,10 @@ var each = require('async/each'); +/*! + * ignore + */ + module.exports = function(schema) { schema._plugins.saveSubdocs = true; diff --git a/lib/plugins/validateBeforeSave.js b/lib/plugins/validateBeforeSave.js index 1100761d386..62734a56b1c 100644 --- a/lib/plugins/validateBeforeSave.js +++ b/lib/plugins/validateBeforeSave.js @@ -1,5 +1,9 @@ 'use strict'; +/*! + * ignore + */ + module.exports = function(schema) { schema._plugins.validateBeforeSave = true; From c40487b91f809e074de6984f32eeaf72e56ef54e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 May 2017 13:08:35 -0600 Subject: [PATCH 1474/2240] chore: now working on 4.9.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5db777c03c1..aa3dfee2023 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.8", + "version": "4.9.9-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 0b6ae53f7b561fe2f6f4f7fc14c7604e43ebe02e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 May 2017 19:15:40 -0600 Subject: [PATCH 1475/2240] refactor(connection): add _handleOpenArgs to abstract open() away from promises Re: #5229 --- lib/connection.js | 113 ++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 54 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index c2cd448934a..a98c79151e8 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -143,42 +143,15 @@ Connection.prototype.db; Connection.prototype.config; -/** - * Opens the connection to MongoDB. - * - * `options` is a hash with the following possible properties: - * - * config - passed to the connection config instance - * db - passed to the connection db instance - * server - passed to the connection server instance(s) - * replset - passed to the connection ReplSet instance - * user - username for authentication - * pass - password for authentication - * auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate) - * - * ####Notes: - * - * Mongoose forces the db option `forceServerObjectId` false and cannot be overridden. - * Mongoose defaults the server `auto_reconnect` options to true which can be overridden. - * See the node-mongodb-native driver instance for options that it understands. - * - * _Options passed take precedence over options included in connection strings._ - * - * @param {String} connection_string mongodb://uri or the host to which you are connecting - * @param {String} [database] database name - * @param {Number} [port] database port - * @param {Object} [options] options - * @param {Function} [callback] - * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native - * @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate - * @api public +/*! + * ignore */ -Connection.prototype.open = function(host, database, port, options, callback) { - var parsed; - var Promise = PromiseProvider.get(); +Connection.prototype._handleOpenArgs = function(host, database, port, options, callback) { var err; + var parsed; + if (typeof database === 'string') { switch (arguments.length) { case 2: @@ -221,11 +194,9 @@ Connection.prototype.open = function(host, database, port, options, callback) { try { parsed = muri(host); - } catch (err) { - this.error(err, callback); - return new Promise.ES6(function(resolve, reject) { - reject(err); - }); + } catch (error) { + this.error(error, callback); + throw error; } database = parsed.db; @@ -240,25 +211,19 @@ Connection.prototype.open = function(host, database, port, options, callback) { err = new Error('Trying to open unclosed connection.'); err.state = this.readyState; this.error(err, callback); - return new Promise.ES6(function(resolve, reject) { - reject(err); - }); + throw err; } if (!host) { err = new Error('Missing hostname.'); this.error(err, callback); - return new Promise.ES6(function(resolve, reject) { - reject(err); - }); + throw err; } if (!database) { err = new Error('Missing database name.'); this.error(err, callback); - return new Promise.ES6(function(resolve, reject) { - reject(err); - }); + throw err; } // authentication @@ -275,19 +240,13 @@ Connection.prototype.open = function(host, database, port, options, callback) { if (host.length > 2) { err = new Error('Username and password must be URI encoded if they ' + 'contain "@", see http://bit.ly/2nRYRyq'); - this.error(err, callback); - return new Promise.ES6(function(resolve, reject) { - reject(err); - }); + throw err; } var auth = host.shift().split(':'); if (auth.length > 2) { err = new Error('Username and password must be URI encoded if they ' + 'contain ":", see http://bit.ly/2nRYRyq'); - this.error(err, callback); - return new Promise.ES6(function(resolve, reject) { - reject(err); - }); + throw err; } host = host.pop(); this.user = auth[0]; @@ -305,6 +264,52 @@ Connection.prototype.open = function(host, database, port, options, callback) { this.host = host; this.port = port; + return callback; +}; + +/** + * Opens the connection to MongoDB. + * + * `options` is a hash with the following possible properties: + * + * config - passed to the connection config instance + * db - passed to the connection db instance + * server - passed to the connection server instance(s) + * replset - passed to the connection ReplSet instance + * user - username for authentication + * pass - password for authentication + * auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate) + * + * ####Notes: + * + * Mongoose forces the db option `forceServerObjectId` false and cannot be overridden. + * Mongoose defaults the server `auto_reconnect` options to true which can be overridden. + * See the node-mongodb-native driver instance for options that it understands. + * + * _Options passed take precedence over options included in connection strings._ + * + * @param {String} connection_string mongodb://uri or the host to which you are connecting + * @param {String} [database] database name + * @param {Number} [port] database port + * @param {Object} [options] options + * @param {Function} [callback] + * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native + * @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate + * @api public + */ + +Connection.prototype.open = function() { + var Promise = PromiseProvider.get(); + var callback; + + try { + callback = this._handleOpenArgs.apply(this, arguments); + } catch (error) { + return new Promise.ES6(function(resolve, reject) { + reject(error); + }); + } + var _this = this; var promise = new Promise.ES6(function(resolve, reject) { _this._open(true, function(error) { From 9f24e99e76436a6450911c8c0cacf5e17d7699ba Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 8 May 2017 18:20:29 -0600 Subject: [PATCH 1476/2240] test(document): repro #5215 --- test/document.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 2b8d8afe757..48e358dcfae 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4075,6 +4075,27 @@ describe('document', function() { }); }); + it('handles errors in subdoc pre validate (gh-5215)', function(done) { + var childSchema = new mongoose.Schema({}); + + childSchema.pre('validate', function(next) { + next(new Error('child pre validate')) + }); + + var parentSchema = new mongoose.Schema({ + child: childSchema + }); + + var Parent = db.model('gh5215', parentSchema); + + Parent.create({ child: {} }, function(error) { + assert.ok(error); + assert.ok(error.errors['child']); + assert.equal(error.errors['child'].message, 'child pre validate'); + done(); + }); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From eed8bcd1aeef21410d31d3245ca7467adf1bdc9b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 8 May 2017 18:21:25 -0600 Subject: [PATCH 1477/2240] fix(document): handle errors in subdoc pre validate Fix #5215 --- lib/schema/embedded.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index d1e293fdceb..5b20775c797 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -177,7 +177,7 @@ Embedded.prototype.doValidate = function(value, fn, scope) { if (!(value instanceof Constructor)) { value = new Constructor(value); } - value.validate(fn, {__noPromise: true}); + value.validate({__noPromise: true}, fn); }, scope); }; From 9986f0aaf3d93e4adf50af9b34141506e5e6f506 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 8 May 2017 18:25:17 -0600 Subject: [PATCH 1478/2240] docs(query): correct type for Query#regex() Fix #5230 --- lib/query.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 58c45f51469..56465a55e4b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -455,7 +455,7 @@ Query.prototype.toConstructor = function toConstructor() { * @method regex * @memberOf Query * @param {String} [path] - * @param {Number} val + * @param {String|RegExp} val * @api public */ From c55da9c566c5975b0155034dea99b72a8127f130 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 9 May 2017 18:53:26 -0600 Subject: [PATCH 1479/2240] test: repro #5222 --- test/model.update.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 7253b9db927..6dd9f355112 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -1978,6 +1978,23 @@ describe('model: update:', function() { catch(done); }); + it('lets $currentDate go through with updatedAt (gh-5222)', function(done) { + var testSchema = new Schema({ + name: String + }, { timestamps: true }); + + var Test = db.model('gh5222', testSchema); + + Test.create({ name: 'test' }, function(error) { + assert.ifError(error); + var u = { $currentDate: { updatedAt: true }, name: 'test2' }; + Test.update({}, u, function(error) { + assert.ifError(error); + done(); + }); + }); + }); + it('update validators on single nested (gh-4332)', function(done) { var AreaSchema = new Schema({ a: String From 9c053947b6354c49482ce603d1e4a95af4aec6a1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 9 May 2017 18:57:21 -0600 Subject: [PATCH 1480/2240] fix(schema): allow update with $currentDate for updatedAt to succeed Fix #5222 --- lib/schema.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 9b90b120986..22ff54efb2c 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -799,7 +799,9 @@ Schema.prototype.setupTimestamp = function(timestamps) { updates = { $set: {} }; currentUpdate = currentUpdate || {}; - updates.$set[updatedAt] = now; + if (!currentUpdate.$currentDate || !currentUpdate.$currentDate[updatedAt]) { + updates.$set[updatedAt] = now; + } if (currentUpdate[createdAt]) { delete currentUpdate[createdAt]; From edd0207947bedc49fc1bfeb24c36c79ad01e1c43 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 10 May 2017 17:24:22 -0600 Subject: [PATCH 1481/2240] test(connection): repro #5229 part 1 --- test/connection.test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/connection.test.js b/test/connection.test.js index 2ddd6361da5..c73eda03ff4 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -251,6 +251,17 @@ describe('connections:', function() { }); }); + describe('errors', function() { + it('.catch() means error does not get thrown (gh-5229)', function(done) { + var db = mongoose.createConnection(); + + db.open('fail connection').catch(function(error) { + assert.ok(error); + done(); + }); + }); + }); + describe('should accept separated args with options', function() { it('works', function(done) { var db = mongoose.createConnection('127.0.0.1', 'faker', 28000, {server: {auto_reconnect: true}}); From e74c9d3f11a86bcf4d597d99d9ab116ac9dc14b6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 10 May 2017 17:26:15 -0600 Subject: [PATCH 1482/2240] fix(connection): don't throw if .catch() on open() promise Re: #5229 --- lib/connection.js | 33 +++++++++++++++++++++++++++++++++ lib/index.js | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index a98c79151e8..efb610370e5 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -327,9 +327,42 @@ Connection.prototype.open = function() { resolve(); }); }); + + var _then = promise.then; + promise.then = function(resolve, reject) { + promise.$hasHandler = true; + return _then.call(promise, resolve, reject); + }; + return promise; }; +/*! + * ignore + */ + +Connection.prototype._openWithoutPromise = function() { + var callback; + + try { + callback = this._handleOpenArgs.apply(this, arguments); + } catch (error) { + // No need to do anything + } + + var _this = this; + this._open(true, function(error) { + callback && callback(error); + if (error && !callback) { + // Error can be on same tick re: christkv/mongodb-core#157 + setImmediate(function() { + _this.emit('error', error); + }); + return; + } + }); +}; + /** * Helper for `dropDatabase()`. * diff --git a/lib/index.js b/lib/index.js index 1e3f60143ba..c06d775b82b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -188,7 +188,7 @@ Mongoose.prototype.createConnection = function(uri, options) { (rsOption.replicaSet || rsOption.rs_name)) { conn.openSet.apply(conn, arguments).catch(function() {}); } else { - conn.open.apply(conn, arguments).catch(function() {}); + conn._openWithoutPromise.apply(conn, arguments); } } From 718299813cefee1ed809a2d389f66cd20b6722e8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 11 May 2017 22:33:30 -0600 Subject: [PATCH 1483/2240] test(document): repro #5216 --- test/document.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 48e358dcfae..9b1a2d2f3a0 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3919,6 +3919,27 @@ describe('document', function() { }); }); + it('save errors with callback and promise work (gh-5216)', function(done) { + var schema = new mongoose.Schema({}); + + var Model = db.model('gh5216', schema); + + var _id = new mongoose.Types.ObjectId(); + var doc1 = new Model({ _id: _id }); + var doc2 = new Model({ _id: _id }); + + Model.on('error', function(error) { + done(error); + }); + + doc1.save(). + then(function() { return doc2.save(function() {}); }). + catch(function(error) { + assert.ok(error); + done(); + }); + }); + it('post hooks on child subdocs run after save (gh-5085)', function(done) { var ChildModelSchema = new mongoose.Schema({ text: { From 0eda07a366c60c758166b17a160f1de4858895fe Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 11 May 2017 22:37:52 -0600 Subject: [PATCH 1484/2240] fix(document): don't emit model error if callback specified for consistency with docs Fix #5216 --- lib/model.js | 2 +- lib/services/model/applyHooks.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/model.js b/lib/model.js index 1ab0bcaad29..7af6cc744a9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -34,7 +34,7 @@ var VERSION_WHERE = 1, * * @param {Object} doc values with which to create the document * @inherits Document http://mongoosejs.com/docs/api.html#document-js - * @event `error`: If listening to this event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model. + * @event `error`: If listening to this event, 'error' is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model. * @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event. * @event `index-single-start`: Emitted when an individual index starts within `Model#ensureIndexes`. The fields and options being used to build the index are also passed with the event. * @event `index-single-done`: Emitted when an individual index finishes within `Model#ensureIndexes`. If an error occurred it is passed with the event. The fields, options, and index name are also passed. diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index f07d49fb056..cff9dd4e9b5 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -123,7 +123,9 @@ function applyHooks(model, schema) { if (error instanceof VersionError) { error.stack = originalError.stack; } - _this.$__handleReject(error); + if (!fn) { + _this.$__handleReject(error); + } reject(error); return; } @@ -140,8 +142,8 @@ function applyHooks(model, schema) { if (this.constructor.$wrapCallback) { fn = this.constructor.$wrapCallback(fn); } - return promise.then( - function() { + promise.then( + function(res) { process.nextTick(function() { fn.apply(null, [null].concat($results)); }); From be8a6e4f5434f279dd3e409a3e617253c26c791f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 12 May 2017 15:38:00 -0600 Subject: [PATCH 1485/2240] refactor(connection): move openSet args logic into separate function Re: #5229 --- lib/connection.js | 112 +++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 51 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index efb610370e5..dacf56f7127 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -401,57 +401,15 @@ Connection.prototype.dropDatabase = function(callback) { return promise; }; -/** - * Opens the connection to a replica set. - * - * ####Example: - * - * var db = mongoose.createConnection(); - * db.openSet("mongodb://user:pwd@localhost:27020,localhost:27021,localhost:27012/mydb"); - * - * The database name and/or auth need only be included in one URI. - * The `options` is a hash which is passed to the internal driver connection object. - * - * Valid `options` - * - * db - passed to the connection db instance - * server - passed to the connection server instance(s) - * replset - passed to the connection ReplSetServer instance - * user - username for authentication - * pass - password for authentication - * auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate) - * mongos - Boolean - if true, enables High Availability support for mongos - * - * _Options passed take precedence over options included in connection strings._ - * - * ####Notes: - * - * _If connecting to multiple mongos servers, set the `mongos` option to true._ - * - * conn.open('mongodb://mongosA:27501,mongosB:27501', { mongos: true }, cb); - * - * Mongoose forces the db option `forceServerObjectId` false and cannot be overridden. - * Mongoose defaults the server `auto_reconnect` options to true which can be overridden. - * See the node-mongodb-native driver instance for options that it understands. - * - * _Options passed take precedence over options included in connection strings._ - * - * @param {String} uris MongoDB connection string - * @param {String} [database] database name if not included in `uris` - * @param {Object} [options] passed to the internal driver - * @param {Function} [callback] - * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native - * @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate - * @api public +/*! + * ignore */ -Connection.prototype.openSet = function(uris, database, options, callback) { +Connection.prototype._handleOpenSetArgs = function(uris, database, options, callback) { if (!rgxProtocol.test(uris)) { uris = 'mongodb://' + uris; } - var Promise = PromiseProvider.get(); - switch (arguments.length) { case 3: switch (typeof database) { @@ -495,9 +453,7 @@ Connection.prototype.openSet = function(uris, database, options, callback) { parsed = muri(uris); } catch (err) { this.error(err, callback); - return new Promise.ES6(function(resolve, reject) { - reject(err); - }); + throw err; } if (!this.name) { @@ -511,9 +467,7 @@ Connection.prototype.openSet = function(uris, database, options, callback) { if (!this.name) { var err = new Error('No database name provided for replica set'); this.error(err, callback); - return new Promise.ES6(function(resolve, reject) { - reject(err); - }); + throw err; } // authentication @@ -531,6 +485,62 @@ Connection.prototype.openSet = function(uris, database, options, callback) { if (options && options.config) { this.config.autoIndex = options.config.autoIndex !== false; } +}; + +/** + * Opens the connection to a replica set. + * + * ####Example: + * + * var db = mongoose.createConnection(); + * db.openSet("mongodb://user:pwd@localhost:27020,localhost:27021,localhost:27012/mydb"); + * + * The database name and/or auth need only be included in one URI. + * The `options` is a hash which is passed to the internal driver connection object. + * + * Valid `options` + * + * db - passed to the connection db instance + * server - passed to the connection server instance(s) + * replset - passed to the connection ReplSetServer instance + * user - username for authentication + * pass - password for authentication + * auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate) + * mongos - Boolean - if true, enables High Availability support for mongos + * + * _Options passed take precedence over options included in connection strings._ + * + * ####Notes: + * + * _If connecting to multiple mongos servers, set the `mongos` option to true._ + * + * conn.open('mongodb://mongosA:27501,mongosB:27501', { mongos: true }, cb); + * + * Mongoose forces the db option `forceServerObjectId` false and cannot be overridden. + * Mongoose defaults the server `auto_reconnect` options to true which can be overridden. + * See the node-mongodb-native driver instance for options that it understands. + * + * _Options passed take precedence over options included in connection strings._ + * + * @param {String} uris MongoDB connection string + * @param {String} [database] database name if not included in `uris` + * @param {Object} [options] passed to the internal driver + * @param {Function} [callback] + * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native + * @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate + * @api public + */ + +Connection.prototype.openSet = function(uris, database, options, callback) { + var Promise = PromiseProvider.get(); + + try { + var callback = this._handleOpenSetArgs.apply(this, arguments); + } catch (err) { + return new Promise.ES6(function(resolve, reject) { + reject(err); + }); + } var _this = this; var emitted = false; From 2d459ec45af94bca0602b6b563f00d1ec763cb23 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 12 May 2017 15:42:12 -0600 Subject: [PATCH 1486/2240] refactor(connection): don't use promise for `createConnection()` Re: #5229 --- lib/connection.js | 27 +++++++++++++++++++++++++++ lib/index.js | 4 ++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index dacf56f7127..3e5607e83b7 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -487,6 +487,33 @@ Connection.prototype._handleOpenSetArgs = function(uris, database, options, call } }; +/*! + * ignore + */ + +Connection.prototype._openSetWithoutPromise = function(uris, database, options, callback) { + try { + var callback = this._handleOpenSetArgs.apply(this, arguments); + } catch (err) { + // Nothing to do, `_handleOpenSetArgs` calls callback if error occurred + return; + } + + var _this = this; + var emitted = false; + this._open(true, function(error) { + callback && callback(error); + if (error) { + if (!callback && !emitted) { + emitted = true; + _this.emit('error', error); + } + return; + } + resolve(); + }); +}; + /** * Opens the connection to a replica set. * diff --git a/lib/index.js b/lib/index.js index c06d775b82b..0fe12c3d4d0 100644 --- a/lib/index.js +++ b/lib/index.js @@ -183,10 +183,10 @@ Mongoose.prototype.createConnection = function(uri, options) { var rsOption = options && (options.replset || options.replSet); if (arguments.length) { if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) { - conn.openSet.apply(conn, arguments).catch(function() {}); + conn._openSetWithoutPromise.apply(conn, arguments); } else if (rsOption && (rsOption.replicaSet || rsOption.rs_name)) { - conn.openSet.apply(conn, arguments).catch(function() {}); + conn._openSetWithoutPromise.apply(conn, arguments); } else { conn._openWithoutPromise.apply(conn, arguments); } From 1f1673960db775d917e07ee28176063efd22eff3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 12 May 2017 15:44:55 -0600 Subject: [PATCH 1487/2240] style: fix lint --- lib/connection.js | 5 ++--- lib/services/model/applyHooks.js | 2 +- test/document.test.js | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 3e5607e83b7..2d1dc0f71c3 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -493,7 +493,7 @@ Connection.prototype._handleOpenSetArgs = function(uris, database, options, call Connection.prototype._openSetWithoutPromise = function(uris, database, options, callback) { try { - var callback = this._handleOpenSetArgs.apply(this, arguments); + callback = this._handleOpenSetArgs.apply(this, arguments); } catch (err) { // Nothing to do, `_handleOpenSetArgs` calls callback if error occurred return; @@ -510,7 +510,6 @@ Connection.prototype._openSetWithoutPromise = function(uris, database, options, } return; } - resolve(); }); }; @@ -562,7 +561,7 @@ Connection.prototype.openSet = function(uris, database, options, callback) { var Promise = PromiseProvider.get(); try { - var callback = this._handleOpenSetArgs.apply(this, arguments); + callback = this._handleOpenSetArgs.apply(this, arguments); } catch (err) { return new Promise.ES6(function(resolve, reject) { reject(err); diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index cff9dd4e9b5..0104df55540 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -143,7 +143,7 @@ function applyHooks(model, schema) { fn = this.constructor.$wrapCallback(fn); } promise.then( - function(res) { + function() { process.nextTick(function() { fn.apply(null, [null].concat($results)); }); diff --git a/test/document.test.js b/test/document.test.js index 9b1a2d2f3a0..d237d960c1f 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4100,7 +4100,7 @@ describe('document', function() { var childSchema = new mongoose.Schema({}); childSchema.pre('validate', function(next) { - next(new Error('child pre validate')) + next(new Error('child pre validate')); }); var parentSchema = new mongoose.Schema({ From d5da9caaa98773631378c0ddffd78fb0b85c9d73 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 12 May 2017 15:57:26 -0600 Subject: [PATCH 1488/2240] fix(connection): set $hasHandler on promises returned from openSet() Re: #5229 --- lib/connection.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 2d1dc0f71c3..0c7e138238f 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -328,6 +328,8 @@ Connection.prototype.open = function() { }); }); + // Monkey-patch `.then()` so if the promise is handled, we don't emit an + // `error` event. var _then = promise.then; promise.then = function(resolve, reject) { promise.$hasHandler = true; @@ -584,6 +586,15 @@ Connection.prototype.openSet = function(uris, database, options, callback) { resolve(); }); }); + + // Monkey-patch `.then()` so if the promise is handled, we don't emit an + // `error` event. + var _then = promise.then; + promise.then = function(resolve, reject) { + promise.$hasHandler = true; + return _then.call(promise, resolve, reject); + }; + return promise; }; From 5f0ce6e3697662e04629d9e012ad994cf5f14299 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 13 May 2017 17:32:54 -0600 Subject: [PATCH 1489/2240] chore: release 4.9.9 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 5e478f43ec7..928cc7fc8b1 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.9.9 / 2017-05-13 +================== + * docs: correct value for Query#regex() #5230 + * fix(connection): don't throw if .catch() on open() promise #5229 + * fix(schema): allow update with $currentDate for updatedAt to succeed #5222 + * fix(model): versioning doesn't fail if version key undefined #5221 [basileos](https://github.com/basileos) + * fix(document): don't emit model error if callback specified for consistency with docs #5216 + * fix(document): handle errors in subdoc pre validate #5215 + 4.9.8 / 2017-05-07 ================== * docs(subdocs): rewrite subdocs guide #5217 diff --git a/package.json b/package.json index aa3dfee2023..15c5163667a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.9-pre", + "version": "4.9.9", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 8a2cda8c3ef82124ecdf8c0bab780e2343c51352 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 13 May 2017 17:37:18 -0600 Subject: [PATCH 1490/2240] chore: now working on 4.9.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 15c5163667a..3a2b5f8fc99 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.9", + "version": "4.9.10-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 014cbbd095393e7b871f276822e3e6912930469f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 13 May 2017 18:54:06 -0600 Subject: [PATCH 1491/2240] refactor: consolidate _plugins and plugins --- lib/index.js | 23 +++++++++++++++-------- lib/plugins/saveSubdocs.js | 2 -- lib/plugins/validateBeforeSave.js | 2 -- lib/schema.js | 2 +- lib/services/model/discriminator.js | 1 + test/model.discriminator.test.js | 2 -- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/lib/index.js b/lib/index.js index 861fe8b1dac..e5720cc5c87 100644 --- a/lib/index.js +++ b/lib/index.js @@ -35,7 +35,6 @@ var shardingPlugin = require('./plugins/sharding'); function Mongoose() { this.connections = []; - this.plugins = [[shardingPlugin, {}]]; this.models = {}; this.modelSchemas = {}; // default global options @@ -46,6 +45,21 @@ function Mongoose() { conn.models = this.models; } +/*! + * ignore + */ + +Object.defineProperty(Mongoose.prototype, 'plugins', { + configurable: false, + enumerable: true, + writable: false, + value: [ + [saveSubdocs, { deduplicate: true }], + [validateBeforeSave, { deduplicate: true }], + [shardingPlugin, { deduplicate: true }] + ] +}); + /** * Expose connection states for user-land * @@ -367,13 +381,6 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) { } if (schema) { - // Reverse order because these both unshift() - if (!schema._plugins.saveSubdocs) { - schema.plugin(saveSubdocs); - } - if (!schema._plugins.validateBeforeSave) { - schema.plugin(validateBeforeSave); - } this._applyPlugins(schema); } diff --git a/lib/plugins/saveSubdocs.js b/lib/plugins/saveSubdocs.js index c51a8e117d1..ffb90b4d4a1 100644 --- a/lib/plugins/saveSubdocs.js +++ b/lib/plugins/saveSubdocs.js @@ -7,8 +7,6 @@ var each = require('async/each'); */ module.exports = function(schema) { - schema._plugins.saveSubdocs = true; - schema.callQueue.unshift(['pre', ['save', function(next) { if (this.ownerDocument) { next(); diff --git a/lib/plugins/validateBeforeSave.js b/lib/plugins/validateBeforeSave.js index 62734a56b1c..706cc0692b3 100644 --- a/lib/plugins/validateBeforeSave.js +++ b/lib/plugins/validateBeforeSave.js @@ -5,8 +5,6 @@ */ module.exports = function(schema) { - schema._plugins.validateBeforeSave = true; - schema.callQueue.unshift(['pre', ['save', function(next, options) { var _this = this; // Nested docs have their own presave diff --git a/lib/schema.js b/lib/schema.js index 439c678545a..c6207036230 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -273,7 +273,7 @@ Schema.prototype.clone = function() { s.callQueue = this.callQueue.map(function(f) { return f; }); s.methods = utils.clone(this.methods); s.statics = utils.clone(this.statics); - s._plugins = utils.clone(this._plugins); + s.plugins = Array.prototype.slice.call(this.plugins); s.s.hooks = this.s.hooks.clone(); return s; }; diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 95a7d01e39b..68f0ba8b7dc 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -84,6 +84,7 @@ module.exports = function discriminator(model, name, schema) { schema.options.id = id; schema.s.hooks = model.schema.s.hooks.merge(schema.s.hooks); + schema.plugins = Array.prototype.slice(baseSchema.plugins); schema.callQueue = baseSchema.callQueue. concat(schema.callQueue.slice(schema._defaultMiddleware.length)); schema._requiredpaths = undefined; // reset just in case Schema#requiredPaths() was called on either schema diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 61bd3df36da..147fd049571 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -316,8 +316,6 @@ describe('model', function() { it('merges callQueue with base queue defined before discriminator types callQueue', function(done) { assert.equal(Employee.schema.callQueue.length, 8); - // PersonSchema.post('save') - assert.strictEqual(Employee.schema.callQueue[0], Person.schema.callQueue[0]); // EmployeeSchema.pre('save') var queueIndex = Employee.schema.callQueue.length - 1; From 48cfb1c51138a328bc7180e7000f8309824dd705 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 13 May 2017 18:55:48 -0600 Subject: [PATCH 1492/2240] test(discriminator): add coverage for child schema pre validate --- test/model.discriminator.test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 147fd049571..427a19a4b83 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -451,6 +451,11 @@ describe('model', function() { name: String }); var childCalls = 0; + var childValidateCalls = 0; + childSchema.pre('validate', function(next) { + ++childValidateCalls; + next(); + }); childSchema.pre('save', function(next) { ++childCalls; next(); @@ -484,6 +489,7 @@ describe('model', function() { assert.equal(doc.heir.name, 'Robb Stark'); assert.equal(doc.children.length, 1); assert.equal(doc.children[0].name, 'Jon Snow'); + assert.equal(childValidateCalls, 2); assert.equal(childCalls, 2); assert.equal(parentCalls, 1); done(); From 9a19a82130d72ed723a147f2b1c0b4c7b02de2cd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 13 May 2017 18:59:43 -0600 Subject: [PATCH 1493/2240] chore: dont use .find() for ES5 compat --- lib/schema.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index c6207036230..c843c4eff02 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1115,9 +1115,12 @@ Schema.prototype.plugin = function(fn, opts) { } if (opts && - opts.deduplicate && - this.plugins.find(function(p) { return p.fn === fn; })) { - return this; + opts.deduplicate) { + for (var i = 0; i < this.plugins.length; ++i) { + if (this.plugins[i].fn === fn) { + return this; + } + } } this.plugins.push({ fn: fn, opts: opts }); From f83c9cc154ff8ca4dddace8f2ac4f1c691dfe943 Mon Sep 17 00:00:00 2001 From: Alexis Tyler Date: Sun, 14 May 2017 15:09:32 +0930 Subject: [PATCH 1494/2240] fix typo --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index a2eb2b92dc6..31302f24782 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -5,7 +5,7 @@ **What is the current behavior?** **If the current behavior is a bug, please provide the steps to reproduce.** - + **What is the expected behavior?** From 52c6b35186b1e17d117676af76e10b7beffb55d8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 14 May 2017 22:36:59 -0600 Subject: [PATCH 1495/2240] test(schema): repro unique index issue with primitive arrays re: #3347 --- test/model.indexes.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index 34b57ba7a4a..c130b125c82 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -208,6 +208,19 @@ describe('model', function() { done(); }); + it('primitive arrays (gh-3347)', function(done) { + var schema = new Schema({ + arr: [{ type: String, unique: true }] + }); + + var indexes = schema.indexes(); + assert.equal(indexes.length, 1); + assert.deepEqual(indexes[0][0], { arr: 1 }); + assert.ok(indexes[0][1].unique); + + done(); + }); + it('error should emit on the model', function(done) { var db = start(), schema = new Schema({name: {type: String}}), From 5908ef029214146aa2f93d5cd81b5bffadef8b3f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 14 May 2017 22:40:19 -0600 Subject: [PATCH 1496/2240] fix(schema): set unique indexes on primitive arrays Re: #3347 --- lib/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 671889dd491..0d039fff0bb 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1368,7 +1368,7 @@ Schema.prototype.indexes = function() { if ((path instanceof MongooseTypes.DocumentArray) || path.$isSingleNested) { collectIndexes(path.schema, prefix + key + '.'); } else { - index = path._index; + index = path._index || (path.caster && path.caster._index); if (index !== false && index !== null && index !== undefined) { field = {}; From 25c350f690bd6043b6f05537ce5a479bbb986d49 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 14 May 2017 22:40:44 -0600 Subject: [PATCH 1497/2240] fix(model): always emit 'index', even if no indexes Re: #3347 --- lib/model.js | 17 +++++++++-------- test/model.indexes.test.js | 13 +++++++------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/model.js b/lib/model.js index d65ea2df9e6..7e9f2666ed8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -929,14 +929,6 @@ Model.ensureIndexes = function ensureIndexes(options, callback) { function _ensureIndexes(model, options, callback) { var indexes = model.schema.indexes(); - if (!indexes.length) { - setImmediate(function() { - callback && callback(); - }); - return; - } - // Indexes are created one-by-one to support how MongoDB < 2.4 deals - // with background indexes. var done = function(err) { if (err && model.schema.options.emitIndexErrors) { @@ -946,6 +938,15 @@ function _ensureIndexes(model, options, callback) { callback && callback(err); }; + if (!indexes.length) { + setImmediate(function() { + done(); + }); + return; + } + // Indexes are created one-by-one to support how MongoDB < 2.4 deals + // with background indexes. + var indexSingleDone = function(err, fields, options, name) { model.emit('index-single-done', err, fields, options, name); }; diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index c130b125c82..7c0e7a89467 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -226,16 +226,17 @@ describe('model', function() { schema = new Schema({name: {type: String}}), Test = db.model('IndexError', schema, 'x' + random()); - Test.on('index', function(err) { - db.close(); - assert.ok(/E11000 duplicate key error/.test(err.message), err); - done(); - }); - Test.create({name: 'hi'}, {name: 'hi'}, function(err) { assert.strictEqual(err, null); Test.schema.index({name: 1}, {unique: true}); Test.schema.index({other: 1}); + + Test.on('index', function(err) { + db.close(); + assert.ok(/E11000 duplicate key error/.test(err.message), err); + done(); + }); + Test.init(); }); }); From 6987ba8c3ea721a59fc9b012615cbf344be78695 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 15 May 2017 17:38:26 -0600 Subject: [PATCH 1498/2240] fix(document): make nested doc keys not enumerable again Fix #5078 --- lib/document.js | 63 ++++++++++++++++++++++++++++--------------- test/document.test.js | 27 +++++++++++++++++++ 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/lib/document.js b/lib/document.js index 5369cfcf3a4..be05e95a3ff 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1767,25 +1767,44 @@ Document.prototype.$__dirty = function() { */ function compile(tree, proto, prefix, options) { - var keys = Object.keys(tree), - i = keys.length, - limb, - key; + var keys = Object.keys(tree); + var i = keys.length; + var len = keys.length; + var limb; + var key; - while (i--) { - key = keys[i]; - limb = tree[key]; - - defineKey(key, - ((utils.getFunctionName(limb.constructor) === 'Object' - && Object.keys(limb).length) - && (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type)) - ? limb - : null) - , proto - , prefix - , keys - , options); + if (options.retainKeyOrder) { + for (i = 0; i < len; ++i) { + key = keys[i]; + limb = tree[key]; + + defineKey(key, + ((utils.getFunctionName(limb.constructor) === 'Object' + && Object.keys(limb).length) + && (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type)) + ? limb + : null) + , proto + , prefix + , keys + , options); + } + } else { + while (i--) { + key = keys[i]; + limb = tree[key]; + + defineKey(key, + ((utils.getFunctionName(limb.constructor) === 'Object' + && Object.keys(limb).length) + && (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type)) + ? limb + : null) + , proto + , prefix + , keys + , options); + } } } @@ -1796,7 +1815,7 @@ function getOwnPropertyDescriptors(object) { Object.getOwnPropertyNames(object).forEach(function(key) { result[key] = Object.getOwnPropertyDescriptor(object, key); - result[key].enumerable = true; + result[key].enumerable = ['isNew', '$__', 'errors', '_doc'].indexOf(key) === -1; }); return result; @@ -1844,7 +1863,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { } Object.defineProperty(nested, 'toObject', { - enumerable: true, + enumerable: false, configurable: true, writable: false, value: function() { @@ -1853,7 +1872,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { }); Object.defineProperty(nested, 'toJSON', { - enumerable: true, + enumerable: false, configurable: true, writable: false, value: function() { @@ -1862,7 +1881,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { }); Object.defineProperty(nested, '$__isNested', { - enumerable: true, + enumerable: false, configurable: true, writable: false, value: true diff --git a/test/document.test.js b/test/document.test.js index 455d17352a9..3f46f040792 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4037,6 +4037,33 @@ describe('document', function() { done(); }); + it('iterating through nested doc keys (gh-5078)', function(done) { + var schema = new Schema({ + nested: { + test1: String, + test2: String + } + }, { retainKeyOrder: true }); + + schema.virtual('tests').get(function() { + return _.map(this.nested, function(v, key) { + return v; + }) + }); + + var M = db.model('gh5078', schema); + + var doc = new M({ nested: { test1: 'a', test2: 'b' } }); + + assert.deepEqual(doc.toObject({ virtuals: true }).tests, ['a', 'b']); + + // Should not throw + require('util').inspect(doc); + JSON.stringify(doc); + + done(); + }); + it('JSON.stringify nested errors (gh-5208)', function(done) { var AdditionalContactSchema = new Schema({ contactName: { From 636e922fd04981b94a131aa47b4fb925fa417308 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 15 May 2017 17:42:14 -0600 Subject: [PATCH 1499/2240] style: fix lint --- test/document.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index 3f46f040792..0419ee3d5b6 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4046,9 +4046,9 @@ describe('document', function() { }, { retainKeyOrder: true }); schema.virtual('tests').get(function() { - return _.map(this.nested, function(v, key) { + return _.map(this.nested, function(v) { return v; - }) + }); }); var M = db.model('gh5078', schema); From bdc1b9c73f706f2b234a13a9e3c3ce4d0bc4eb22 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 16 May 2017 12:56:53 -0600 Subject: [PATCH 1500/2240] docs(populate): add details re: justOne in virtual populate Re: #4263 --- docs/populate.jade | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/populate.jade b/docs/populate.jade index bd78b74c23f..3c6844189ab 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -330,7 +330,10 @@ block content BandSchema.virtual('members', { ref: 'Person', // The model to use localField: 'name', // Find people where `localField` - foreignField: 'band' // is equal to `foreignField` + foreignField: 'band', // is equal to `foreignField` + // If `justOne` is false, 'members' will be a single doc as opposed to + // an array. `justOne` is false by default. + justOne: false }); var Person = mongoose.model('Person', personSchema); From 76e5c2e87095b5e8cdfc2247656fb91b4698da53 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 16 May 2017 16:54:44 -0600 Subject: [PATCH 1501/2240] docs: remove dead plugins repo and add content links Re: #5247 --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index e5fe25e9321..8280d049fcb 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,7 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed ## Plugins -Check out the [plugins search site](http://plugins.mongoosejs.io/) to see hundreds of related modules from the community. - -Build your own Mongoose plugin through [generator-mongoose-plugin](https://github.com/huei90/generator-mongoose-plugin). +Check out the [plugins search site](http://plugins.mongoosejs.io/) to see hundreds of related modules from the community. Next, learn how to write your own plugin from the [docs](http://mongoosejs.com/docs/plugins.html) or [this blog post](http://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins). ## Contributors From 236c87ea5dc29db7158b9ae4278079dae9ad31e9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 16 May 2017 17:42:43 -0600 Subject: [PATCH 1502/2240] fix(model): skip index build if connecting after model init and autoIndex false Fix #5176 --- lib/model.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 7af6cc744a9..fc27b03aeb7 100644 --- a/lib/model.js +++ b/lib/model.js @@ -874,7 +874,7 @@ for (var i in EventEmitter.prototype) { Model.init = function init() { if ((this.schema.options.autoIndex) || - (this.schema.options.autoIndex === null && this.db.config.autoIndex)) { + (this.schema.options.autoIndex == null && this.db.config.autoIndex)) { this.ensureIndexes({ __noPromise: true, _automatic: true }); } @@ -967,6 +967,11 @@ function _ensureIndexes(model, options, callback) { }; var create = function() { + if (model.schema.options.autoIndex === false || + (model.schema.options.autoIndex == null && model.db.config.autoIndex === false)) { + return done(); + } + var index = indexes.shift(); if (!index) return done(); From 7393f10a3044400ef1a072ec7d9fff9d2ea4c1e9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 May 2017 11:57:24 -0600 Subject: [PATCH 1503/2240] test(document): repro #5250 --- test/document.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index d237d960c1f..a5186c34e46 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4037,6 +4037,23 @@ describe('document', function() { done(); }); + it('deeply nested virtual paths (gh-5250)', function(done) { + var TestSchema = new Schema({}); + TestSchema. + virtual('a.b.c'). + get(function() { + return this.v; + }). + set(function(value) { + this.v = value; + }); + + var TestModel = db.model('gh5250', TestSchema); + var t = new TestModel({'a.b.c': 5}); + assert.equal(t.a.b.c, 5); + done(); + }); + it('JSON.stringify nested errors (gh-5208)', function(done) { var AdditionalContactSchema = new Schema({ contactName: { From 4f78b3b449c3dbd3811cdb6da5c03596d8653cbd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 May 2017 11:57:31 -0600 Subject: [PATCH 1504/2240] fix(document): check for virtual before setting nested non-existent path Fix #5250 --- lib/document.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/document.js b/lib/document.js index 4fb46147d1b..0d19f861987 100644 --- a/lib/document.js +++ b/lib/document.js @@ -663,18 +663,6 @@ Document.prototype.set = function(path, val, type, options) { var schema; var parts = path.split('.'); - // gh-4578, if setting a deeply nested path that doesn't exist yet, create it - var cur = this._doc; - var curPath = ''; - for (i = 0; i < parts.length - 1; ++i) { - cur = cur[parts[i]]; - curPath += (curPath.length > 0 ? '.' : '') + parts[i]; - if (!cur) { - this.set(curPath, {}); - cur = this.getValue(curPath); - } - } - if (pathType === 'adhocOrUndefined' && strict) { // check for roots that are Mixed types var mixed; @@ -709,6 +697,18 @@ Document.prototype.set = function(path, val, type, options) { schema = this.$__path(path); } + // gh-4578, if setting a deeply nested path that doesn't exist yet, create it + var cur = this._doc; + var curPath = ''; + for (i = 0; i < parts.length - 1; ++i) { + cur = cur[parts[i]]; + curPath += (curPath.length > 0 ? '.' : '') + parts[i]; + if (!cur) { + this.set(curPath, {}); + cur = this.getValue(curPath); + } + } + var pathToMark; // When using the $set operator the path to the field must already exist. From ec7678627d0423c9a1a253b23e644de6477de04f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 May 2017 22:52:16 -0600 Subject: [PATCH 1505/2240] fix(connection): ensure callback arg to openSet() is handled properly Fix #5249 --- lib/connection.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 0c7e138238f..cf348f89cce 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -487,6 +487,8 @@ Connection.prototype._handleOpenSetArgs = function(uris, database, options, call if (options && options.config) { this.config.autoIndex = options.config.autoIndex !== false; } + + return callback; }; /*! From bb1f92a8c2638d19883991eacb834468aeb0887d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 May 2017 22:59:11 -0600 Subject: [PATCH 1506/2240] chore: release 4.9.10 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 928cc7fc8b1..732ebd21cc1 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +4.9.10 / 2017-05-17 +=================== + * fix(connection): ensure callback arg to openSet() is handled properly #5249 + * docs: remove dead plugins repo and add content links #5247 + * fix(model): skip index build if connecting after model init and autoIndex false #5176 + 4.9.9 / 2017-05-13 ================== * docs: correct value for Query#regex() #5230 diff --git a/package.json b/package.json index 3a2b5f8fc99..ce79d3a06a0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.10-pre", + "version": "4.9.10", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 07b12f0e165420e3a31201d89f6f01393f0eb166 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 17 May 2017 23:02:20 -0600 Subject: [PATCH 1507/2240] chore: now working on 4.9.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ce79d3a06a0..a1378f19b5f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.9.10", + "version": "4.9.11-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 373bb6fe40cdd7d64ea58ffaa009aeb1efab1ac3 Mon Sep 17 00:00:00 2001 From: clozanosanchez Date: Thu, 18 May 2017 16:24:45 +0200 Subject: [PATCH 1508/2240] Update clone method to include indexes --- lib/schema.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/schema.js b/lib/schema.js index 22ff54efb2c..8dce1252591 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -274,6 +274,7 @@ Schema.prototype.clone = function() { s.methods = utils.clone(this.methods); s.statics = utils.clone(this.statics); s._plugins = utils.clone(this._plugins); + s._indexes = utils.clone(this._indexes); s.s.hooks = this.s.hooks.clone(); return s; }; From 4bc7b3ee9bc81b4a818e1e94985217f0c32c0ffc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 18 May 2017 14:05:55 -0600 Subject: [PATCH 1509/2240] docs: add missing ignores to sharding plugin --- lib/plugins/sharding.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/plugins/sharding.js b/lib/plugins/sharding.js index 4a2f85ea1fe..1d5cf5944ec 100644 --- a/lib/plugins/sharding.js +++ b/lib/plugins/sharding.js @@ -2,6 +2,10 @@ var utils = require('../utils'); +/*! + * ignore + */ + module.exports = function shardingPlugin(schema) { schema.post('init', function() { storeShard.call(this); @@ -16,6 +20,10 @@ module.exports = function shardingPlugin(schema) { }); }; +/*! + * ignore + */ + function applyWhere() { var paths; var len; @@ -32,18 +40,15 @@ function applyWhere() { } /*! - * Stores the current values of the shard keys. - * - * ####Note: - * - * _Shard key values do not / are not allowed to change._ - * - * @api private - * @method $__storeShard - * @memberOf Document + * ignore */ + module.exports.storeShard = storeShard; +/*! + * ignore + */ + function storeShard() { // backwards compat var key = this.schema.options.shardKey || this.schema.options.shardkey; From 43752e8dfbfea880db61f87f13da0a3fbbe5de53 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 18 May 2017 14:26:27 -0600 Subject: [PATCH 1510/2240] chore: release 4.10.0 --- History.md | 16 ++++++++++++++++ package.json | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 732ebd21cc1..0a3eecb17f4 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,19 @@ +4.10.0 / 2017-05-18 +=================== + * fix(schema): update clone method to include indexes #5268 [clozanosanchez](https://github.com/clozanosanchez) + * feat(schema): support aliases #5184 [rocketspacer](https://github.com/rocketspacer) + * feat(aggregate): add mongoose-specific aggregation cursor option #5145 + * refactor(model): make sharding into a plugin instead of core #5105 + * fix(document): make nested doc mongoose internals not enumerable again #5078 + * feat(model): pass params to pre hooks #5064 + * feat(timestamps): support already defined timestamp paths in schema #4868 + * feat(query): add runSettersOnQuery option #4569 + * fix(query): add strictQuery option that throws when not querying on field not in schema #4136 + * fix(update): more complete handling for overwrite option with update validators #3556 + * feat: support `unique: true` in arrays via the mongoose-unique-array plugin #3347 + * feat(validation): include failed paths in error message and inspect output #3064 #2135 + * fix(model): return saved docs when create() fails #2190 + 4.9.10 / 2017-05-17 =================== * fix(connection): ensure callback arg to openSet() is handled properly #5249 diff --git a/package.json b/package.json index 83f4475c08e..f08d910d4b5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.0-pre", + "version": "4.10.0", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 274ed0fa17752f619e5e2b23169ad8a997b412eb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 18 May 2017 14:32:14 -0600 Subject: [PATCH 1511/2240] docs: add missing ignore --- lib/services/query/hasDollarKeys.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/services/query/hasDollarKeys.js b/lib/services/query/hasDollarKeys.js index 2917a847ba6..92b4408a349 100644 --- a/lib/services/query/hasDollarKeys.js +++ b/lib/services/query/hasDollarKeys.js @@ -1,5 +1,9 @@ 'use strict'; +/*! + * ignore + */ + module.exports = function(obj) { var keys = Object.keys(obj); var len = keys.length; From d951bedccd92c7499c9edd33d0f1de807d6b5322 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 18 May 2017 14:33:24 -0600 Subject: [PATCH 1512/2240] chore: now working on 4.10.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f08d910d4b5..fb27fc6b394 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.0", + "version": "4.10.1-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From f7cbbdcd2af0b58d5b24c18dec178f105d97ea55 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 19 May 2017 09:45:03 -0600 Subject: [PATCH 1513/2240] docs: list a couple intermediate changes in changelog Re: #3347 --- History.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/History.md b/History.md index 0a3eecb17f4..07b17be125a 100644 --- a/History.md +++ b/History.md @@ -11,6 +11,8 @@ * fix(query): add strictQuery option that throws when not querying on field not in schema #4136 * fix(update): more complete handling for overwrite option with update validators #3556 * feat: support `unique: true` in arrays via the mongoose-unique-array plugin #3347 + * fix(model): always emit 'index', even if no indexes #3347 + * fix(schema): set unique indexes on primitive arrays #3347 * feat(validation): include failed paths in error message and inspect output #3064 #2135 * fix(model): return saved docs when create() fails #2190 From 50386359d8439e46561265f9639e901d3acb285e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 May 2017 10:40:58 -0600 Subject: [PATCH 1514/2240] fix(schema): enforce that _id is never null Re: #5236 mongodb/node-mongodb-native#517 --- lib/model.js | 2 +- lib/schema/objectid.js | 3 +++ test/document.test.js | 10 ++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 27caf0f4dc0..05a068bad8e 100644 --- a/lib/model.js +++ b/lib/model.js @@ -126,7 +126,7 @@ Model.prototype.$__handleSave = function(options, callback) { var obj = this.toObject(toObjectOptions); - if (!utils.object.hasOwnProperty(obj || {}, '_id')) { + if ((obj || {})._id == null) { // documents must have an _id else mongoose won't know // what to update later if more changes are made. the user // wouldn't know what _id was generated by mongodb either diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index 6f684191c90..f0dd9fdc42a 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -196,6 +196,9 @@ function defaultId() { } function resetId(v) { + if (v == null) { + return new oid(); + } this.$__._id = null; return v; } diff --git a/test/document.test.js b/test/document.test.js index c8be117e84b..37af387e0fa 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4162,6 +4162,16 @@ describe('document', function() { }); }); + it('null _id (gh-5236)', function(done) { + var childSchema = new mongoose.Schema({}); + + var M = db.model('gh5236', childSchema); + + var m = new M({ _id: null }); + assert.ok(m._id); + done(); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From b38651636860d3021ba473d0d285aded700566bf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 May 2017 11:23:11 -0600 Subject: [PATCH 1515/2240] test(aggregate): repro #5258 --- test/aggregate.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 2350cadd017..8c994ae5ca0 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -974,4 +974,30 @@ describe('aggregate: ', function() { }). catch(done); }); + + it('sort by text score (gh-5258)', function(done) { + var db = start(); + + var mySchema = new Schema({ test: String }); + mySchema.index({ test: 'text' }); + var M = db.model('gh5258', mySchema); + + M.on('index', function(error) { + assert.ifError(error); + M.create([{ test: 'test test' }, { test: 'a test' }], function(error) { + assert.ifError(error); + var aggregate = M.aggregate(); + aggregate.match({ $text: { $search: 'test' } }); + aggregate.sort({ score: { $meta: 'textScore' } }); + + aggregate.exec(function(error, res) { + assert.ifError(error); + assert.equal(res.length, 2); + assert.equal(res[0].test, 'test test'); + assert.equal(res[1].test, 'a test'); + done(); + }); + }); + }); + }); }); From 6a2d405dee83a2984e32574e3f787bdaced54c7c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 May 2017 11:23:46 -0600 Subject: [PATCH 1516/2240] fix(aggregate): handle sorting by text score correctly Fix #5258 --- lib/aggregate.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/aggregate.js b/lib/aggregate.js index 10c2210730e..a93b3d4bb59 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -391,6 +391,11 @@ Aggregate.prototype.sort = function(arg) { if (arg.constructor.name === 'Object') { var desc = ['desc', 'descending', -1]; Object.keys(arg).forEach(function(field) { + // If sorting by text score, skip coercing into 1/-1 + if (arg[field] instanceof Object && arg[field].$meta) { + sort[field] = arg[field]; + return; + } sort[field] = desc.indexOf(arg[field]) === -1 ? 1 : -1; }); } else if (arguments.length === 1 && typeof arg === 'string') { From a6dd311ab9354615c01dfb7d8fe769a97edd6cef Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 May 2017 16:58:47 -0600 Subject: [PATCH 1517/2240] test(populate): repro #5240 --- test/model.populate.test.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index f6a1cfb8006..61bb5e0969f 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5053,6 +5053,40 @@ describe('model: populate:', function() { catch(done); }); + it('nested virtuals + doc.populate() (gh-5240)', function(done) { + var parentSchema = new Schema({ name: String }); + var childSchema = new Schema({ + parentId: mongoose.Schema.Types.ObjectId + }); + childSchema.virtual('parent', { + ref: 'gh5240', + localField: 'parentId', + foreignField: '_id', + justOne: true + }); + var teamSchema = new Schema({ people: [childSchema] }); + + var Parent = db.model('gh5240', parentSchema); + var Team = db.model('gh5240_0', teamSchema); + + Parent.create({ name: 'Darth Vader' }). + then(function(doc) { + return Team.create({ people: [{ parentId: doc._id }] }); + }). + then(function(team) { + return Team.findById(team._id); + }). + then(function(team) { + return team.populate('people.parent').execPopulate(); + }). + then(function(team) { + team = team.toObject({ virtuals: true }); + assert.equal(team.people[0].parent.name, 'Darth Vader'); + done(); + }). + catch(done); + }); + it('virtual populate in single nested doc (gh-4715)', function(done) { var someModelSchema = new mongoose.Schema({ name: String From dc6f8872740256a878ecc6bbcdbb1eb5dd83d1a6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 May 2017 16:59:30 -0600 Subject: [PATCH 1518/2240] fix(populate): handle doc.populate() with virtuals Fix #5240 --- lib/document.js | 1 + lib/model.js | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index c6d7b70ba98..6ede708aab2 100644 --- a/lib/document.js +++ b/lib/document.js @@ -311,6 +311,7 @@ Document.prototype.init = function(doc, opts, fn) { } this.isNew = false; + this.$init = true; // handle docs with populated paths // If doc._id is not null or undefined diff --git a/lib/model.js b/lib/model.js index 05a068bad8e..4f22827ba05 100644 --- a/lib/model.js +++ b/lib/model.js @@ -19,6 +19,7 @@ var cast = require('./cast'); var castUpdate = require('./services/query/castUpdate'); var discriminator = require('./services/model/discriminator'); var isPathSelectedInclusive = require('./services/projection/isPathSelectedInclusive'); +var mpath = require('mpath'); var parallel = require('async/parallel'); var util = require('util'); var utils = require('./utils'); @@ -3190,7 +3191,14 @@ function assignVals(o) { if (o.isVirtual && !o.justOne && !Array.isArray(rawIds[i])) { rawIds[i] = [rawIds[i]]; } - utils.setValue(o.path, rawIds[i], docs[i], setValue); + + if (o.isVirtual && docs[i].constructor.name === 'model' && docs[i].$init) { + // If virtual populate and doc is already init-ed, need to walk through + // the actual doc to set rather than setting `_doc` directly + mpath.set(o.path, rawIds[i], docs[i]); + } else { + utils.setValue(o.path, rawIds[i], docs[i], setValue); + } } } From 3474d8d487292e0e8ab41ed26de254ca76585bea Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 May 2017 20:17:57 -0600 Subject: [PATCH 1519/2240] chore: release 4.10.1 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 07b17be125a..5d5dd5a940f 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +4.10.1 / 2017-05-21 +=================== + * fix(aggregate): handle sorting by text score correctly #5258 + * fix(populate): handle doc.populate() with virtuals #5240 + * fix(schema): enforce that `_id` is never null #5236 + 4.10.0 / 2017-05-18 =================== * fix(schema): update clone method to include indexes #5268 [clozanosanchez](https://github.com/clozanosanchez) diff --git a/package.json b/package.json index fb27fc6b394..10104dbe78a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.1-pre", + "version": "4.10.1", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ca5e53ccb10bf00c5dacbf2d944ecd570d548162 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 May 2017 20:20:15 -0600 Subject: [PATCH 1520/2240] chore: now working on 4.10.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 10104dbe78a..6efcbe70cc3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.1", + "version": "4.10.2-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 84b3e28f8342241d671f8ed0c0f8a19bb1eccced Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 May 2017 22:04:34 -0600 Subject: [PATCH 1521/2240] docs: improve projection descriptions re: #1534 --- docs/populate.jade | 1 + lib/query.js | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/populate.jade b/docs/populate.jade index 3c6844189ab..2355abd2bb6 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -123,6 +123,7 @@ block content .populate({ path: 'fans', match: { age: { $gte: 21 }}, + // Explicitly exclude `_id`, see http://bit.ly/2aEfTdB select: 'name -_id', options: { limit: 5 } }) diff --git a/lib/query.js b/lib/query.js index 1fdd524256a..170acdc086b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -728,6 +728,10 @@ Query.prototype.toConstructor = function toConstructor() { * * When using string syntax, prefixing a path with `-` will flag that path as excluded. When a path does not have the `-` prefix, it is included. Lastly, if a path is prefixed with `+`, it forces inclusion of the path, which is useful for paths excluded at the [schema level](/docs/api.html#schematype_SchemaType-select). * + * A projection _must_ be either inclusive or exclusive. In other words, you must + * either list the fields to include (which excludes all others), or list the fields + * to exclude (which implies all other fields are included). The [`_id` field is the only exception because MongoDB includes it by default](https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/#suppress-id-field). + * * ####Example * * // include a and b, exclude other fields @@ -744,12 +748,6 @@ Query.prototype.toConstructor = function toConstructor() { * // force inclusion of field excluded at schema level * query.select('+path') * - * ####NOTE: - * - * Cannot be used with `distinct()`. - * - * _v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3._ - * * @method select * @memberOf Query * @param {Object|String} arg From b8263d6229007d049960cda5412b04108799a33a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 May 2017 22:53:52 -0600 Subject: [PATCH 1522/2240] fix: bump mquery for regexp vulnerability Fix #5275 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6efcbe70cc3..88463420b09 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.2.26", "mpath": "0.2.1", "mpromise": "0.5.5", - "mquery": "2.3.0", + "mquery": "2.3.1", "ms": "0.7.2", "muri": "1.2.1", "regexp-clone": "0.0.1", From f627ba5e4abbd60160c227d79164509bcc0ef88d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 May 2017 23:07:40 -0600 Subject: [PATCH 1523/2240] fix: bump ms -> 2.0.0 Fix #5275 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 88463420b09..09f78f2eafb 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.3.1", - "ms": "0.7.2", + "ms": "2.0.0", "muri": "1.2.1", "regexp-clone": "0.0.1", "sliced": "1.0.1" From 23efdcfb44be883a3499afe8606ff5fdb7d8ffd7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 May 2017 23:12:01 -0600 Subject: [PATCH 1524/2240] chore: release 4.10.2 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 5d5dd5a940f..7b9f42b1378 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +4.10.2 / 2017-05-22 +=================== + * fix: bump ms -> 2.0.0 and mquery -> 2.3.1 for minor security vulnerability #5275 + 4.10.1 / 2017-05-21 =================== * fix(aggregate): handle sorting by text score correctly #5258 diff --git a/package.json b/package.json index 09f78f2eafb..a2a46680ba7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.2-pre", + "version": "4.10.2", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 60df83ac0bb4a76ba6acf6a3138f2459adb24f96 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 May 2017 23:13:35 -0600 Subject: [PATCH 1525/2240] chore: now working on 4.10.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a2a46680ba7..45afbd21426 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.2", + "version": "4.10.3-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From dd21f01200ac4dcc93764116b55fe92c7542ad03 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 23 May 2017 23:51:47 -0600 Subject: [PATCH 1526/2240] chore: upgrade to mongodb 2.2.27 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 45afbd21426..c7557a62c2b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "2.0.0", "kareem": "1.4.1", - "mongodb": "2.2.26", + "mongodb": "2.2.27", "mpath": "0.2.1", "mpromise": "0.5.5", "mquery": "2.3.1", From a59c01f491ac280d259f5be5c2e15bc1727c7426 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 24 May 2017 00:09:09 -0600 Subject: [PATCH 1527/2240] chore: add repl start script --- tools/repl.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tools/repl.js diff --git a/tools/repl.js b/tools/repl.js new file mode 100644 index 00000000000..6d023a69cb2 --- /dev/null +++ b/tools/repl.js @@ -0,0 +1,36 @@ +'use strict'; + +const co = require('co'); + +co(function*() { + var ReplSet = require('mongodb-topology-manager').ReplSet; + + // Create new instance + var topology = new ReplSet('mongod', [{ + // mongod process options + options: { + bind_ip: 'localhost', port: 31000, dbpath: `${__dirname}/31000` + } + }, { + // mongod process options + options: { + bind_ip: 'localhost', port: 31001, dbpath: `${__dirname}/31001` + } + }, { + // Type of node + arbiterOnly: true, + // mongod process options + options: { + bind_ip: 'localhost', port: 31002, dbpath: `${__dirname}/31002` + } + }], { + replSet: 'rs' + }); + + yield topology.start(); + + console.log('done'); +}).catch(error => { + console.error(error); + process.exit(-1); +}); From 3f941769ac9205bae411e155161abc3c9aeb2b2c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 24 May 2017 18:13:52 -0600 Subject: [PATCH 1528/2240] test(document): repro #5282 --- test/document.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 37af387e0fa..1aa41409642 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4162,6 +4162,24 @@ describe('document', function() { }); }); + it('saving a doc with nested string array (gh-5282)', function(done) { + var testSchema = new mongoose.Schema({ + strs: [[String]] + }); + + var Test = db.model('gh5282', testSchema); + + var t = new Test({ + strs: [['a', 'b']] + }); + + t.save(function(error, t) { + assert.ifError(error); + assert.deepEqual(t.toObject().strs, [['a', 'b']]); + done(); + }); + }); + it('null _id (gh-5236)', function(done) { var childSchema = new mongoose.Schema({}); From 26e92e94b333f81a028133baab8d9c867638509d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 24 May 2017 18:14:16 -0600 Subject: [PATCH 1529/2240] fix(document): prevent infinite loop if validating nested array Fix #5282 --- lib/document.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 6ede708aab2..75de175440f 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1350,7 +1350,8 @@ function _getPathsToValidate(doc) { // gh-661: if a whole array is modified, make sure to run validation on all // the children as well - for (i = 0; i < paths.length; ++i) { + var len = paths.length; + for (i = 0; i < len; ++i) { var path = paths[i]; var _pathType = doc.schema.path(path); @@ -1368,7 +1369,8 @@ function _getPathsToValidate(doc) { } var flattenOptions = { skipArrays: true }; - for (i = 0; i < paths.length; ++i) { + len = paths.length; + for (i = 0; i < len; ++i) { var pathToCheck = paths[i]; if (doc.schema.nested[pathToCheck]) { var _v = doc.getValue(pathToCheck); From 9c7849b1c166b1e9448c7a68d00855dee4cf1736 Mon Sep 17 00:00:00 2001 From: nathanallen Date: Wed, 24 May 2017 19:55:37 -0700 Subject: [PATCH 1530/2240] fixes #5291 - reveal subtopics in sidebar on first click --- docs/api.jade | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/api.jade b/docs/api.jade index b7790a38fc3..0a7a95f6f60 100644 --- a/docs/api.jade +++ b/docs/api.jade @@ -279,14 +279,15 @@ html(lang='en') script(src="/docs/js/cookies.min.js") script. $(".toggle-item").click(function() { - if ($(this).hasClass('fa-caret-right')) { - $(this).removeClass('fa-caret-right'); - $(this).addClass('fa-caret-down'); - $(this).parent().addClass('displayed'); + var $parent = $(this).parent(), + $icon = $(this).find("i"); + + if($parent.hasClass('displayed')){ + $parent.removeClass('displayed'); + $icon.addClass("fa-caret-right").removeClass("fa-caret-down"); } else { - $(this).addClass('fa-caret-right'); - $(this).removeClass('fa-caret-down'); - $(this).parent().removeClass('displayed'); + $parent.addClass('displayed'); + $icon.removeClass("fa-caret-right").addClass("fa-caret-down"); } }); $(".module").on("click", ".showcode", function (e) { From 4f9d40ad829c5e7a2947e44a647f4d7d5b48015b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 25 May 2017 17:02:18 -0600 Subject: [PATCH 1531/2240] test(schema): repro #5227 --- test/es6/all.test.es6.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/es6/all.test.es6.js b/test/es6/all.test.es6.js index df398fec44b..ac03f17a69d 100644 --- a/test/es6/all.test.es6.js +++ b/test/es6/all.test.es6.js @@ -25,4 +25,26 @@ describe('bug fixes', function() { assert.ok(C === Car); done(); }); + + it('allows overwriting base class methods (gh-5227)', function(done) { + class BaseModel extends mongoose.Model { + getString() { + return 'parent'; + } + } + + class GH5227 extends BaseModel { + getString() { + return 'child'; + } + } + + const UserModel = mongoose.model(GH5227, new mongoose.Schema({})); + + const u = new UserModel({}); + + assert.equal(u.getString(), 'child'); + + done(); + }); }); From 3c60b4e97e1cbda9f2c7d7f13ac0ca69f5c3bf1c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 25 May 2017 17:02:35 -0600 Subject: [PATCH 1532/2240] fix(schema): load child class methods after base class methods to allow override Fix #5227 --- lib/document.js | 5 +++-- lib/model.js | 2 +- lib/schema.js | 8 ++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/document.js b/lib/document.js index 75de175440f..8def373db9a 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1317,6 +1317,7 @@ Document.prototype.validate = function(options, callback) { function _getPathsToValidate(doc) { var i; + var len; // only validate required fields when necessary var paths = Object.keys(doc.$__.activePaths.states.require).filter(function(path) { @@ -1337,7 +1338,7 @@ function _getPathsToValidate(doc) { if (!doc.ownerDocument) { var subdocs = doc.$__getAllSubdocs(); var subdoc; - var len = subdocs.length; + len = subdocs.length; for (i = 0; i < len; ++i) { subdoc = subdocs[i]; if (subdoc.$isSingleNested && @@ -1350,7 +1351,7 @@ function _getPathsToValidate(doc) { // gh-661: if a whole array is modified, make sure to run validation on all // the children as well - var len = paths.length; + len = paths.length; for (i = 0; i < len; ++i) { var path = paths[i]; diff --git a/lib/model.js b/lib/model.js index 4f22827ba05..04290136ff4 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3608,7 +3608,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base) if (typeof name === 'function' && name.prototype instanceof Model) { model = name; name = model.name; - schema.loadClass(model, true); + schema.loadClass(model, false); model.prototype.$isMongooseModelPrototype = true; } else { // generate new class diff --git a/lib/schema.js b/lib/schema.js index ad343561e53..c151af3e787 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1624,6 +1624,8 @@ Schema.prototype.loadClass = function(model, virtualsOnly) { return this; } + this.loadClass(Object.getPrototypeOf(model)); + // Add static methods if (!virtualsOnly) { Object.getOwnPropertyNames(model).forEach(function(name) { @@ -1631,7 +1633,9 @@ Schema.prototype.loadClass = function(model, virtualsOnly) { return; } var method = Object.getOwnPropertyDescriptor(model, name); - if (typeof method.value === 'function') this.static(name, method.value); + if (typeof method.value === 'function') { + this.static(name, method.value); + } }, this); } @@ -1654,7 +1658,7 @@ Schema.prototype.loadClass = function(model, virtualsOnly) { } }, this); - return (this.loadClass(Object.getPrototypeOf(model))); + return this; }; /*! From efb017f7628bd249804c441153e170830218f603 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 May 2017 13:29:24 -0600 Subject: [PATCH 1533/2240] fix(schema): correctly handle ref ObjectIds from different mongoose libs Fix #5259, Re: #2951 --- lib/schema/objectid.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index f0dd9fdc42a..ac91ab8be3c 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -97,6 +97,8 @@ ObjectId.prototype.cast = function(value, doc, init) { // setting a populated path if (value instanceof oid) { return value; + } else if ((value.constructor.name || '').toLowerCase() === 'objectid') { + return new oid(value.toHexString()); } else if (Buffer.isBuffer(value) || !utils.isObject(value)) { throw new CastError('ObjectId', value, this.path); } From c2520e19d76729bf88c6b215ccc62f224a501c85 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 26 May 2017 18:10:23 -0400 Subject: [PATCH 1534/2240] Tweak updateOne and replaceOne documentation notes It seems that the note about the hooks that are called after `updateMany` was copy+pasted into the `updateOne` and `replaceOne` documentation. It either does not apply, or the reference to `updateMany` needs to be updated to say `updateOne`/`replaceOne` --- lib/model.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index 04290136ff4..9b1b2539500 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2346,9 +2346,6 @@ Model.updateMany = function updateMany(conditions, doc, options, callback) { * Same as `update()`, except MongoDB will update _only_ the first document that * matches `criteria` regardless of the value of the `multi` option. * - * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')` - * and `post('updateMany')` instead. - * * @param {Object} conditions * @param {Object} doc * @param {Object} [options] @@ -2365,9 +2362,6 @@ Model.updateOne = function updateOne(conditions, doc, options, callback) { * Same as `update()`, except MongoDB replace the existing document with the * given document (no atomic operators like `$set`). * - * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')` - * and `post('updateMany')` instead. - * * @param {Object} conditions * @param {Object} doc * @param {Object} [options] From b01d9555009315bb5fc81ce59b6c8ddeb676b377 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 May 2017 16:51:39 -0600 Subject: [PATCH 1535/2240] docs: add description of alias option Fix #5287, re: #5184 --- docs/guide.jade | 24 +++++++++++++++++++++++- docs/schematypes.jade | 8 +++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/guide.jade b/docs/guide.jade index 54d6f7fa33a..5c07c7d4380 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -250,7 +250,29 @@ block content :markdown Virtual property setters are applied before other validation. So the example above would still work even if the `first` and `last` name fields were required. - Only non-virtual properties work as part of queries and for field selection. + Only non-virtual properties work as part of queries and for field selection. Since virtuals are not stored in MongoDB, you can't query with them. + + h5#aliases Aliases + :markdown + Aliases are a particular type of virtual where the getter and setter seamlessly get and set another property. This is handy for saving network bandwidth, so you can convert a short property name stored in the database into a longer name for code readability. + + :js + var personSchema = new Schema({ + n: { + type: String, + // Now accessing `name` will get you the value of `n`, and setting `n` will set the value of `name` + alias: 'name' + } + }); + + // Setting `name` will propagate to `n` + var person = new Person({ name: 'Val' }); + console.log(person); // { n: 'Val' } + console.log(person.toObject({ virtuals: true })); // { n: 'Val', name: 'Val' } + console.log(person.name); // "Val" + + person.name = 'Not Val'; + console.log(person); // { n: 'Not Val' } h3#options Options :markdown diff --git a/docs/schematypes.jade b/docs/schematypes.jade index d571844445d..9afbfb36f5c 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -112,13 +112,15 @@ block content * `validate: function, adds a [validator function](http://mongoosejs.com/docs/validation.html#built-in-validators) for this property * `get`: function, defines a custom getter for this property using [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). * `set`: function, defines a custom setter for this property using [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). + * `alias`: string, mongoose >= 4.10.0 only. Defines a [virtual](http://mongoosejs.com/docs/guide.html#virtuals) with the given name that gets/sets this path. :js var numberSchema = new Schema({ integerOnly: { type: Number, get: v => Math.round(v), - set: v => Math.round(v) + set: v => Math.round(v), + alias: 'i' } }); @@ -127,6 +129,10 @@ block content var doc = new Number(); doc.integerOnly = 2.001; doc.integerOnly; // 2 + doc.i; // 2 + doc.i = 3.001; + doc.integerOnly; // 3 + doc.i; // 3 h5 Indexes p From 405bfb36c1ffe88b04d90e59b90964d4deab7940 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 May 2017 17:02:25 -0600 Subject: [PATCH 1536/2240] test(timestamps): add test covering #4503 --- test/timestamps.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/timestamps.test.js b/test/timestamps.test.js index f049ea95455..84347e5733c 100644 --- a/test/timestamps.test.js +++ b/test/timestamps.test.js @@ -43,6 +43,26 @@ describe('timestamps', function() { }); }); + it('nested paths (gh-4503)', function(done) { + var startTime = Date.now(); + var schema = new mongoose.Schema({ + name: String + }, { timestamps: { createdAt: 'ts.c', updatedAt: 'ts.a' } }); + var M = db.model('gh4503', schema); + + M.create({ name: 'Test' }, function(error) { + assert.ifError(error); + M.findOne({}, function(error, doc) { + assert.ifError(error); + assert.ok(doc.ts.c); + assert.ok(doc.ts.c.valueOf() >= startTime); + assert.ok(doc.ts.a); + assert.ok(doc.ts.a.valueOf() >= startTime); + done(); + }); + }); + }); + it('does not override nested timestamp params defined in schema (gh-4868)', function(done) { var startTime = Date.now(); var schema = new mongoose.Schema({ From 56409b6b99e5923a232ece1e6616f4c2b85ffe94 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 27 May 2017 11:08:37 -0600 Subject: [PATCH 1537/2240] chore: release 4.10.3 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 7b9f42b1378..01d7c9d40c2 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.10.3 / 2017-05-27 +=================== + * docs: correct inconsistent references to updateOne and replaceOne #5297 [dhritzkiv](https://github.com/dhritzkiv) + * docs: fix dropdowns in docs #5292 [nathanallen](https://github.com/nathanallen) + * docs: add description of alias option #5287 + * fix(document): prevent infinite loop if validating nested array #5282 + * fix(schema): correctly handle ref ObjectIds from different mongoose libs #5259 + * fix(schema): load child class methods after base class methods to allow override #5227 + 4.10.2 / 2017-05-22 =================== * fix: bump ms -> 2.0.0 and mquery -> 2.3.1 for minor security vulnerability #5275 diff --git a/package.json b/package.json index c7557a62c2b..0f5fd67c749 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.3-pre", + "version": "4.10.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e5cad83b75684d80828f965a5332ca46c331d43d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 27 May 2017 11:16:21 -0600 Subject: [PATCH 1538/2240] chore: now working on 4.10.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f5fd67c749..daef40f3535 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.3", + "version": "4.10.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 75052328bf5f5544194f15137f1bf749e8125eae Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 27 May 2017 11:16:52 -0600 Subject: [PATCH 1539/2240] chore: ignore data dirs in tools/ --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c2a14d4b815..f80a38a9ab5 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,8 @@ bin/mongoose.min.js coverage npm-debug.log +tools/31* + # Visual Studio # ========= *.suo From 2a52245b3d3c8711ecbf0ad6331db35a3467fc5a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 27 May 2017 11:19:47 -0600 Subject: [PATCH 1540/2240] chore: now working on 4.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index daef40f3535..193e006df74 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.4-pre", + "version": "4.11.0-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e39e888a99688662f9bdab2bcac2c8c567f9f10d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 27 May 2017 12:32:15 -0600 Subject: [PATCH 1541/2240] chore: allow passing object to lean --- lib/query.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index 170acdc086b..37cfdbc5ce3 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1060,13 +1060,13 @@ Query.prototype._optionsForExec = function(model) { * * This is a [great](https://groups.google.com/forum/#!topic/mongoose-orm/u2_DzDydcnA/discussion) option in high-performance read-only scenarios, especially when combined with [stream](#query_Query-stream). * - * @param {Boolean} bool defaults to true + * @param {Boolean|Object} bool defaults to true * @return {Query} this * @api public */ Query.prototype.lean = function(v) { - this._mongooseOptions.lean = arguments.length ? !!v : true; + this._mongooseOptions.lean = arguments.length ? v : true; return this; }; From 71d452c05071b2529741556bdeca5dc4f73d22a7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 27 May 2017 12:49:01 -0600 Subject: [PATCH 1542/2240] refactor(schema): make id virtual not access doc internals Re: #5279 --- lib/document.js | 4 ++++ lib/schema.js | 9 +++------ lib/schema/objectid.js | 6 ++++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/document.js b/lib/document.js index 8def373db9a..27ff7f3bd9c 100644 --- a/lib/document.js +++ b/lib/document.js @@ -72,6 +72,8 @@ function Document(obj, fields, skipId) { } } + this.$__._id = this._id; + if (!schema.options.strict && obj) { var _this = this, keys = Object.keys(this._doc); @@ -333,6 +335,8 @@ Document.prototype.init = function(doc, opts, fn) { this.emit('init', this); this.constructor.emit('init', this); + this.$__._id = this._id; + if (fn) { fn(null); } diff --git a/lib/schema.js b/lib/schema.js index c151af3e787..16be9a0df15 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -170,14 +170,11 @@ function aliasFields(schema) { */ function idGetter() { - if (this.$__._id) { - return this.$__._id; + if (this._id != null) { + return String(this._id); } - this.$__._id = this._id == null - ? null - : String(this._id); - return this.$__._id; + return null; } /*! diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index ac91ab8be3c..a9a26a55ae4 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -199,9 +199,11 @@ function defaultId() { function resetId(v) { if (v == null) { - return new oid(); + var _v = new oid; + this.$__._id = _v; + return _v; } - this.$__._id = null; + this.$__._id = v; return v; } From 8bc4df61c3c21dff8e59b26d3f81cda764d01d32 Mon Sep 17 00:00:00 2001 From: Starfox64 Date: Sat, 27 May 2017 22:27:27 +0200 Subject: [PATCH 1543/2240] Add data dirs in tools/ to .npmignore --- .npmignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.npmignore b/.npmignore index 377d63fa438..7b1dc195fb7 100644 --- a/.npmignore +++ b/.npmignore @@ -14,3 +14,4 @@ index.jade bin/ karma.*.js format_deps.js +tools/31* From 759a2fa9d8579091049c6c5be1eb5681b9956e5f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 27 May 2017 14:42:23 -0600 Subject: [PATCH 1544/2240] refactor: handle non-boolean lean re: #5279 --- lib/query.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/query.js b/lib/query.js index 37cfdbc5ce3..636d1f57cd9 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1116,7 +1116,7 @@ Query.prototype._find = function(callback) { } if (!options.populate) { - return options.lean === true + return !!options.lean === true ? callback(null, docs) : completeMany(_this.model, docs, fields, null, callback); } @@ -1125,7 +1125,7 @@ Query.prototype._find = function(callback) { pop.__noPromise = true; _this.model.populate(docs, pop, function(err, docs) { if (err) return callback(err); - return options.lean === true + return !!options.lean === true ? callback(null, docs) : completeMany(_this.model, docs, fields, pop, callback); }); @@ -1306,7 +1306,7 @@ Query.prototype._findOne = function(callback) { } if (!options.populate) { - return options.lean === true + return !!options.lean === true ? callback(null, doc) : completeOne(_this.model, doc, null, {}, projection, null, callback); } @@ -1317,7 +1317,7 @@ Query.prototype._findOne = function(callback) { if (err) { return callback(err); } - return options.lean === true + return !!options.lean === true ? callback(null, doc) : completeOne(_this.model, doc, null, {}, projection, pop, callback); }); @@ -2063,7 +2063,7 @@ Query.prototype._findAndModify = function(type, callback) { } if (!options.populate) { - if (options.lean === true) { + if (!!options.lean === true) { return _completeOneLean(doc, res, opts, callback); } return completeOne(_this.model, doc, res, opts, fields, null, callback); @@ -2076,7 +2076,7 @@ Query.prototype._findAndModify = function(type, callback) { return callback(err); } - if (options.lean === true) { + if (!!options.lean === true) { return _completeOneLean(doc, res, opts, callback); } return completeOne(_this.model, doc, res, opts, fields, pop, callback); From cd86287d36ed7416e28891892bdc7e1f61f426f3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 29 May 2017 12:22:22 -0600 Subject: [PATCH 1545/2240] chore: dont store test data in same directory re: #5303 --- tools/repl.js | 6 +++--- tools/sharded.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/repl.js b/tools/repl.js index 6d023a69cb2..533892afddd 100644 --- a/tools/repl.js +++ b/tools/repl.js @@ -9,19 +9,19 @@ co(function*() { var topology = new ReplSet('mongod', [{ // mongod process options options: { - bind_ip: 'localhost', port: 31000, dbpath: `${__dirname}/31000` + bind_ip: 'localhost', port: 31000, dbpath: `~/data/db/31000` } }, { // mongod process options options: { - bind_ip: 'localhost', port: 31001, dbpath: `${__dirname}/31001` + bind_ip: 'localhost', port: 31001, dbpath: `~/data/db/31001` } }, { // Type of node arbiterOnly: true, // mongod process options options: { - bind_ip: 'localhost', port: 31002, dbpath: `${__dirname}/31002` + bind_ip: 'localhost', port: 31002, dbpath: `~/data/db/31002` } }], { replSet: 'rs' diff --git a/tools/sharded.js b/tools/sharded.js index 92ec2f1a899..9eab1352d21 100644 --- a/tools/sharded.js +++ b/tools/sharded.js @@ -13,13 +13,13 @@ co(function*() { yield topology.addShard([{ options: { - bind_ip: 'localhost', port: 31000, dbpath: `${__dirname}/31000` + bind_ip: 'localhost', port: 31000, dbpath: `~/data/db/31000` } }], { replSet: 'rs1' }); yield topology.addConfigurationServers([{ options: { - bind_ip: 'localhost', port: 35000, dbpath: `${__dirname}/35000` + bind_ip: 'localhost', port: 35000, dbpath: `~/data/db/35000` } }], { replSet: 'rs0' }); From f4b384ea58a5a940f8e498abaa3f2f767fcdbe4a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 29 May 2017 12:54:19 -0600 Subject: [PATCH 1546/2240] docs(query): add docs about runSettersOnQuery Fix #5300 --- docs/queries.jade | 24 ++++++++++++++++++++++++ lib/model.js | 33 +++++++++++++++++---------------- lib/query.js | 1 + 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/docs/queries.jade b/docs/queries.jade index 3ce822f70cd..f23f251460e 100644 --- a/docs/queries.jade +++ b/docs/queries.jade @@ -79,6 +79,30 @@ block content :markdown A full list of [Query helper functions can be found in the API docs](http://mongoosejs.com/docs/api.html#query-js). + h3#setters + :markdown + Setters are not executed by default in 4.x. For example, if you lowercase emails in your schema: + + :js + var personSchema = new Schema({ + email: { + type: String, + lowercase: true + } + }); + + :markdown + Mongoose will **not** automatically lowercase the email in your queries, so `Person.find({ email: 'Val@karpov.io' })` would return no results. + Use the `runSettersOnQuery` option to turn on this behavior: + + :js + var personSchema = new Schema({ + email: { + type: String, + lowercase: true + } + }, { runSettersOnQuery: true }); + h3#refs References to other documents :markdown There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [population](./populate.html) comes in. Read more about how to include documents from other collections in your query results [here](./api.html#query_Query-populate). diff --git a/lib/model.js b/lib/model.js index 9b1b2539500..86e791900fc 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1498,7 +1498,7 @@ Model.$where = function $where() { * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update - * + * - `runSettersOnQuery`: bool - if true, run all setters defined on the associated model's schema for all fields defined in the query and the update. * * ####Examples: * @@ -1525,13 +1525,13 @@ Model.$where = function $where() { * ####Note: * * Values are cast to their appropriate types when using the findAndModify helpers. - * However, the below are never executed. + * However, the below are not executed by default. * - * - defaults - * - setters + * - defaults. Use the `setDefaultsOnInsert` option to override. + * - setters. Use the `runSettersOnQuery` option to override. * - * `findAndModify` helpers support limited defaults and validation. You can - * enable these by setting the `setDefaultsOnInsert` and `runValidators` options, + * `findAndModify` helpers support limited validation. You can + * enable these by setting the `runValidators` options, * respectively. * * If you need full-fledged validation, use the traditional approach of first @@ -1613,6 +1613,7 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { * - `select`: sets the document fields to return * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update + * - `runSettersOnQuery`: bool - if true, run all setters defined on the associated model's schema for all fields defined in the query and the update. * * ####Examples: * @@ -1638,13 +1639,13 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { * ####Note: * * Values are cast to their appropriate types when using the findAndModify helpers. - * However, the below are never executed. + * However, the below are not executed by default. * - * - defaults - * - setters + * - defaults. Use the `setDefaultsOnInsert` option to override. + * - setters. Use the `runSettersOnQuery` option to override. * - * `findAndModify` helpers support limited defaults and validation. You can - * enable these by setting the `setDefaultsOnInsert` and `runValidators` options, + * `findAndModify` helpers support limited validation. You can + * enable these by setting the `runValidators` options, * respectively. * * If you need full-fledged validation, use the traditional approach of first @@ -1713,13 +1714,13 @@ Model.findByIdAndUpdate = function(id, update, options, callback) { * A.findOneAndRemove() // returns Query * * Values are cast to their appropriate types when using the findAndModify helpers. - * However, the below are never executed. + * However, the below are not executed by default. * - * - defaults - * - setters + * - defaults. Use the `setDefaultsOnInsert` option to override. + * - setters. Use the `runSettersOnQuery` option to override. * - * `findAndModify` helpers support limited defaults and validation. You can - * enable these by setting the `setDefaultsOnInsert` and `runValidators` options, + * `findAndModify` helpers support limited validation. You can + * enable these by setting the `runValidators` options, * respectively. * * If you need full-fledged validation, use the traditional approach of first diff --git a/lib/query.js b/lib/query.js index 170acdc086b..b9f50b1bea7 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1755,6 +1755,7 @@ function prepareDiscriminatorCriteria(query) { * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) * - `context` (string) if set to 'query' and `runValidators` is on, `this` will refer to the query in custom validator functions that update validation runs. Does nothing if `runValidators` is false. + * - `runSettersOnQuery`: bool - if true, run all setters defined on the associated model's schema for all fields defined in the query and the update. * * ####Callback Signature * function(error, doc) { From 5556c05fc39cef90ea34021f4912523cd2169a65 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 29 May 2017 13:05:25 -0600 Subject: [PATCH 1547/2240] chore: release 4.10.4 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 01d7c9d40c2..344786a3451 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +4.10.4 / 2017-05-29 +=================== + * chore: dont store test data in same directory #5303 + * chore: add data dirs to npmignore #5301 [Starfox64](https://github.com/Starfox64) + * docs(query): add docs about runSettersOnQuery #5300 + 4.10.3 / 2017-05-27 =================== * docs: correct inconsistent references to updateOne and replaceOne #5297 [dhritzkiv](https://github.com/dhritzkiv) diff --git a/package.json b/package.json index daef40f3535..5bfe2461e76 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.4-pre", + "version": "4.10.4", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 9403bc7d2bbdce8bedb84df3007a44ed6e7596a5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 29 May 2017 13:18:26 -0600 Subject: [PATCH 1548/2240] chore: now working on 4.10.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5bfe2461e76..501f3f9bcca 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.4", + "version": "4.10.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 8f02f2613cc2cdcd5710a2ee6f74929af97b008a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 31 May 2017 10:58:16 -0600 Subject: [PATCH 1549/2240] chore: fix doc build in master --- lib/model.js | 8 ++++---- lib/schema/embedded.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index 86e791900fc..aa8bb7d953c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3037,10 +3037,10 @@ function populate(model, docs, options, callback) { var subPopulate = mod.options.populate; var query = mod.Model.find(match, select, mod.options.options); - /* If we're doing virtual populate and projection is inclusive and foreign - * field is not selected, automatically select it because mongoose needs it. - * If projection is exclusive and client explicitly unselected the foreign - * field, that's the client's fault. */ + // If we're doing virtual populate and projection is inclusive and foreign + // field is not selected, automatically select it because mongoose needs it. + // If projection is exclusive and client explicitly unselected the foreign + // field, that's the client's fault. if (mod.foreignField !== '_id' && query.selectedInclusively() && !isPathSelectedInclusive(query._fields, mod.foreignField)) { query.select(mod.foreignField); diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 3ca711534b1..8f9c78502be 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -83,7 +83,7 @@ function Embedded(schema, path, options) { Embedded.prototype = Object.create(SchemaType.prototype); -/** +/*! * Special case for when users use a common location schema to represent * locations for use with $geoWithin. * https://docs.mongodb.org/manual/reference/operator/query/geoWithin/ @@ -92,7 +92,7 @@ Embedded.prototype = Object.create(SchemaType.prototype); * @api private */ -Embedded.prototype.$conditionalHandlers.$geoWithin = function(val) { +Embedded.prototype.$conditionalHandlers.$geoWithin = function handle$geoWithin(val) { return { $geometry: this.castForQuery(val.$geometry) }; }; From e4a4002a6a86c7da6a9b300e7e6899f67d19d3ec Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 31 May 2017 11:00:51 -0600 Subject: [PATCH 1550/2240] chore: add keys in npmignore and gitignore --- .gitignore | 2 ++ .npmignore | 1 + 2 files changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f80a38a9ab5..4ee09903957 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ tools/31* # Visual STudio Code .vscode + +*.key diff --git a/.npmignore b/.npmignore index 7b1dc195fb7..3d3193b1aa4 100644 --- a/.npmignore +++ b/.npmignore @@ -15,3 +15,4 @@ bin/ karma.*.js format_deps.js tools/31* +*.key From 5a22560c084569567582483a3afd4b6567138c94 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 31 May 2017 11:45:39 -0600 Subject: [PATCH 1551/2240] refactor: move querycursor under the cursor dir --- lib/{querycursor.js => cursor/QueryCursor.js} | 4 ++-- lib/query.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename lib/{querycursor.js => cursor/QueryCursor.js} (98%) diff --git a/lib/querycursor.js b/lib/cursor/QueryCursor.js similarity index 98% rename from lib/querycursor.js rename to lib/cursor/QueryCursor.js index 919c7d305e3..c196828bee5 100644 --- a/lib/querycursor.js +++ b/lib/cursor/QueryCursor.js @@ -2,9 +2,9 @@ * Module dependencies. */ -var PromiseProvider = require('./promise_provider'); +var PromiseProvider = require('../promise_provider'); var Readable = require('stream').Readable; -var helpers = require('./queryhelpers'); +var helpers = require('../queryhelpers'); var util = require('util'); /** diff --git a/lib/query.js b/lib/query.js index b9f50b1bea7..9137d95a9a1 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3,7 +3,7 @@ */ var PromiseProvider = require('./promise_provider'); -var QueryCursor = require('./querycursor'); +var QueryCursor = require('./cursor/QueryCursor'); var QueryStream = require('./querystream'); var cast = require('./cast'); var castUpdate = require('./services/query/castUpdate'); From 13721515be19dca600898e2bc8e1e2f31281279e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 1 Jun 2017 07:14:30 -0600 Subject: [PATCH 1552/2240] chore: improve contrib guide for building docs Fix #5312 --- .gitignore | 2 ++ CONTRIBUTING.md | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4ee09903957..754313052bc 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ tools/31* .vscode *.key + +docs/*.html diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 904aeef38a2..09988088b7e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,7 +49,13 @@ To contribute to the [API documentation](http://mongoosejs.com/docs/api.html) ju To contribute to the [guide](http://mongoosejs.com/docs/guide.html) or [quick start](http://mongoosejs.com/docs/index.html) docs, make your changes to the appropriate `.jade` files in the [docs](https://github.com/Automattic/mongoose/tree/master/docs) directory of the master branch and submit a pull request. Again, the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button might work for you here. -If you'd like to preview your documentation changes, first commit your changes to your local master branch, then execute `make docs` from the project root, which switches to the gh-pages branch, merges from the master branch and builds all the static pages for you. Now execute `node static.js` from the project root which will launch a local webserver where you can browse the documentation site locally. If all looks good, submit a [pull request](https://help.github.com/articles/using-pull-requests/) to the master branch with your changes. +If you'd like to preview your documentation changes, first commit your changes to your local master branch, then execute: + +* `make docclean` +* `make gendocs` +* `node static.js` + +Visit `http://localhost:8088` and you should see the docs with your local changes. Make sure you `git reset --hard` before commiting, because changes to `docs/*` should **not** be in PRs. ### Plugins website From 31165e6746ca6087e9d66cea2e0fda9c0cb01828 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 1 Jun 2017 10:52:35 -0600 Subject: [PATCH 1553/2240] fix(schema): remove default validate pre hook that was causing issues with jest Fix #4943 --- lib/schema.js | 10 ---------- lib/services/model/applyHooks.js | 2 ++ test/model.discriminator.test.js | 2 +- test/schema.test.js | 6 +++--- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index c151af3e787..7bcbe56808d 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -202,16 +202,6 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { enumerable: false, writable: false, value: [ - { - kind: 'pre', - hook: 'validate', - isAsync: true, - fn: function(next, done) { - // Hack to ensure that we always wrap validate() in a promise - next(); - done(); - } - }, { kind: 'pre', hook: 'remove', diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index 0104df55540..d7531f31af3 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -86,6 +86,8 @@ function applyHooks(model, schema) { delete toWrap.set; } + toWrap.validate = toWrap.validate || { pre: [], post: [] }; + keys = Object.keys(toWrap); len = keys.length; for (i = 0; i < len; ++i) { diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 427a19a4b83..932255230e3 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -315,7 +315,7 @@ describe('model', function() { }); it('merges callQueue with base queue defined before discriminator types callQueue', function(done) { - assert.equal(Employee.schema.callQueue.length, 8); + assert.equal(Employee.schema.callQueue.length, 7); // EmployeeSchema.pre('save') var queueIndex = Employee.schema.callQueue.length - 1; diff --git a/test/schema.test.js b/test/schema.test.js index d76995a661e..ef01283fd56 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -772,15 +772,15 @@ describe('schema', function() { Tobi.pre('save', function() { }); - assert.equal(Tobi.callQueue.length, 3); + assert.equal(Tobi.callQueue.length, 2); Tobi.post('save', function() { }); - assert.equal(Tobi.callQueue.length, 4); + assert.equal(Tobi.callQueue.length, 3); Tobi.pre('save', function() { }); - assert.equal(Tobi.callQueue.length, 5); + assert.equal(Tobi.callQueue.length, 4); done(); }); }); From a66bf52118befcb049365078c30d70b0cebf8290 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 2 Jun 2017 14:00:15 -0600 Subject: [PATCH 1554/2240] test(populate): repro #5311 --- test/model.populate.test.js | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 61bb5e0969f..993c6faab8a 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4698,7 +4698,7 @@ describe('model: populate:', function() { exec(function(error, res) { assert.ifError(error); // Fails if this `.toObject()` is omitted, issue #4926 - res = res.toObject(); + res = res.toObject({ virtuals: true }); var compare = function(a, b) { if (a.name < b.name) { return -1; @@ -5087,6 +5087,40 @@ describe('model: populate:', function() { catch(done); }); + it('virtuals + doc.populate() (gh-5311)', function(done) { + var parentSchema = new Schema({ name: String }); + var childSchema = new Schema({ + parentId: mongoose.Schema.Types.ObjectId + }); + childSchema.virtual('parent2', { + ref: 'gh5311', + localField: 'parentId', + foreignField: '_id', + justOne: true + }); + + var Parent = db.model('gh5311', parentSchema); + var Child = db.model('gh5311_0', childSchema); + + Parent.create({ name: 'Darth Vader' }). + then(function(doc) { + return Child.create({ parentId: doc._id }); + }). + then(function(c) { + return Child.findById(c._id); + }). + then(function(c) { + return c.populate('parent2').execPopulate(); + }). + then(function(c) { + c = c.toObject({ virtuals: true }); + + assert.equal(c.parent2.name, 'Darth Vader'); + done(); + }). + catch(done); + }); + it('virtual populate in single nested doc (gh-4715)', function(done) { var someModelSchema = new mongoose.Schema({ name: String From 8acce129423a2d51cfa093fd298c8b4e3b393d12 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 2 Jun 2017 14:02:11 -0600 Subject: [PATCH 1555/2240] chore: add node 8 to travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 88444bbe6ee..d888a519f81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: node_js sudo: false node_js: + - "8" - "7" - "6" - "5" From 2b29d2ab0341211435002d49a59b111d1aa52087 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 3 Jun 2017 11:47:24 -0400 Subject: [PATCH 1556/2240] chore: temporarily remove node 8 from travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d888a519f81..88444bbe6ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: node_js sudo: false node_js: - - "8" - "7" - "6" - "5" From 9ede6be103745b6505c48b23d70c51de8c0d00e1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 4 Jun 2017 17:11:05 -0600 Subject: [PATCH 1557/2240] test(update): repro #5269 --- test/model.update.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 8e8d4354453..5e03f09a7da 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2559,6 +2559,32 @@ describe('model: update:', function() { catch(done); }); + it('update validators with nested required (gh-5269)', function(done){ + var childSchema = new mongoose.Schema({ + d1: { + type: String, + required: true + }, + d2: { + type: String + } + }, { _id: false }); + + var parentSchema = new mongoose.Schema({ + d: childSchema + }); + + var Parent = db.model('gh5269', parentSchema); + + Parent.update({}, { d: { d2: 'test' } }, { runValidators: true }, function(error) { + assert.ok(error); + assert.ok(error.errors['d']); + assert.ok(error.errors['d'].message.indexOf('Path `d1` is required') !== -1, + error.errors['d'].message); + done(); + }); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From e7d24a5aaab3cda67339291a1582366c482bb9c7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 4 Jun 2017 17:11:09 -0600 Subject: [PATCH 1558/2240] fix(update): report update validator error if required path under single nested doc not set Fix #5269 --- lib/types/subdocument.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 5ad19c4684d..c214825300d 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -51,6 +51,7 @@ Subdocument.prototype.$isValid = function(path) { if (this.$parent) { return this.$parent.$isValid([this.$basePath, path].join('.')); } + return Document.prototype.$isValid.call(this, path); }; Subdocument.prototype.markModified = function(path) { From 3a7cfbc314daa11d5f01fbd59ef854bd85283c97 Mon Sep 17 00:00:00 2001 From: Paul Wijhenke Date: Mon, 5 Jun 2017 13:18:27 +0200 Subject: [PATCH 1559/2240] fix(test): possible sort-order test-failure --- test/aggregate.test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 8c994ae5ca0..5fe0c76a8bb 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -671,11 +671,13 @@ describe('aggregate: ', function() { connectToField: 'name', as: 'employeeHierarchy' }). + sort({name: 1}). exec(function(err, docs) { if (err) { return done(err); } var lowest = docs[3]; + assert.equal(lowest.name, 'Dave'); assert.equal(lowest.employeeHierarchy.length, 3); // First result in array is max depth result @@ -683,6 +685,7 @@ describe('aggregate: ', function() { return doc.name; }).sort(); assert.equal(names[0], 'Alice'); + assert.equal(names[1], 'Bob'); assert.equal(names[2], 'Carol'); done(); }); From 3d04d5e17dc998aac9992b0b69e322f543ab2209 Mon Sep 17 00:00:00 2001 From: Paul Wijhenke Date: Mon, 5 Jun 2017 13:31:08 +0200 Subject: [PATCH 1560/2240] Fix(ensureIndexes) manual call with !schema.options.autoIndex A manual call to ensureIndexes on a Model with !autoIndex would not create any indexes. Removed checks that were also done on the init() call. --- lib/model.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index aa8bb7d953c..edc6752dc4a 100644 --- a/lib/model.js +++ b/lib/model.js @@ -956,11 +956,6 @@ function _ensureIndexes(model, options, callback) { }; var create = function() { - if (model.schema.options.autoIndex === false || - (model.schema.options.autoIndex == null && model.db.config.autoIndex === false)) { - return done(); - } - var index = indexes.shift(); if (!index) return done(); From 893b1bfd63dd604d050c133e8bf0768cfe6e5e7b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 5 Jun 2017 10:13:36 -0600 Subject: [PATCH 1561/2240] fix(populate): handle init-ing nested virtuals properly Fix #5311 --- lib/document.js | 4 +--- lib/schema.js | 18 ++++++++++-------- package.json | 2 +- test/model.populate.test.js | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/document.js b/lib/document.js index 8def373db9a..b92726f420b 100644 --- a/lib/document.js +++ b/lib/document.js @@ -958,9 +958,7 @@ Document.prototype.get = function(path, type) { obj = adhoc.cast(obj); } - // Check if this path is populated - don't apply getters if it is, - // because otherwise its a nested object. See gh-3357 - if (schema && !this.populated(path)) { + if (schema) { obj = schema.applyGetters(obj, this); } diff --git a/lib/schema.js b/lib/schema.js index 7bcbe56808d..b0465d8a3ae 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -10,6 +10,7 @@ var MongooseTypes; var Kareem = require('kareem'); var each = require('async/each'); var SchemaType = require('./schematype'); +var mpath = require('mpath'); var IS_KAREEM_HOOK = { count: true, @@ -1463,22 +1464,23 @@ Schema.prototype.virtual = function(name, options) { } this.pre('init', function(next, obj) { - if (name in obj) { + if (mpath.has(name, obj)) { + var _v = mpath.get(name, obj); if (!this.$$populatedVirtuals) { this.$$populatedVirtuals = {}; } if (options.justOne) { - this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? - obj[name][0] : - obj[name]; + this.$$populatedVirtuals[name] = Array.isArray(_v) ? + _v[0] : + _v; } else { - this.$$populatedVirtuals[name] = Array.isArray(obj[name]) ? - obj[name] : - obj[name] == null ? [] : [obj[name]]; + this.$$populatedVirtuals[name] = Array.isArray(_v) ? + _v : + _v == null ? [] : [_v]; } - delete obj[name]; + mpath.unset(name, obj); } if (this.ownerDocument) { next(); diff --git a/package.json b/package.json index 501f3f9bcca..c26887e5ae6 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "hooks-fixed": "2.0.0", "kareem": "1.4.1", "mongodb": "2.2.27", - "mpath": "0.2.1", + "mpath": "0.3.0", "mpromise": "0.5.5", "mquery": "2.3.1", "ms": "2.0.0", diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 993c6faab8a..f6cdbf9def6 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5092,7 +5092,7 @@ describe('model: populate:', function() { var childSchema = new Schema({ parentId: mongoose.Schema.Types.ObjectId }); - childSchema.virtual('parent2', { + childSchema.virtual('parent', { ref: 'gh5311', localField: 'parentId', foreignField: '_id', @@ -5110,12 +5110,12 @@ describe('model: populate:', function() { return Child.findById(c._id); }). then(function(c) { - return c.populate('parent2').execPopulate(); + return c.populate('parent').execPopulate(); }). then(function(c) { c = c.toObject({ virtuals: true }); - assert.equal(c.parent2.name, 'Darth Vader'); + assert.equal(c.parent.name, 'Darth Vader'); done(); }). catch(done); From 4c80f6608f1f22df108e823c82839b3676fe13d2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 5 Jun 2017 10:23:29 -0600 Subject: [PATCH 1562/2240] style: fix lint --- test/model.update.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 5e03f09a7da..1c748545458 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2559,7 +2559,7 @@ describe('model: update:', function() { catch(done); }); - it('update validators with nested required (gh-5269)', function(done){ + it('update validators with nested required (gh-5269)', function(done) { var childSchema = new mongoose.Schema({ d1: { type: String, From e3c36a727e8857b4bb196c22d0b5c870ee4afe2b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 6 Jun 2017 18:26:04 -0600 Subject: [PATCH 1563/2240] chore: release 4.10.5 --- History.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 344786a3451..0674a03d38a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.10.5 / 2017-06-06 +=================== + * chore: improve contrib guide for building docs #5312 + * fix(populate): handle init-ing nested virtuals properly #5311 + * fix(update): report update validator error if required path under single nested doc not set + * fix(schema): remove default validate pre hook that was causing issues with jest #4943 + 4.10.4 / 2017-05-29 =================== * chore: dont store test data in same directory #5303 diff --git a/package.json b/package.json index c26887e5ae6..a6b755b726c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.5-pre", + "version": "4.10.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 8d2669e94d53b1b2a7e3f77f13b90f8da517c2d8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 6 Jun 2017 18:27:20 -0600 Subject: [PATCH 1564/2240] chore: now working on 4.10.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a6b755b726c..412dd80f6cf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.5", + "version": "4.10.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From fd970cfb519e7f797c808da5722569016c3ccc2f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 6 Jun 2017 22:24:43 -0600 Subject: [PATCH 1565/2240] test(document): repro #5313 --- test/document.test.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 1aa41409642..cb85ee3db73 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4190,6 +4190,36 @@ describe('document', function() { done(); }); + it('setting populated path with typeKey (gh-5313)', function(done) { + var personSchema = Schema( + { + name: {$type: String}, + favorite: { $type: Schema.Types.ObjectId, ref: 'gh5313' }, + books: [{ $type: Schema.Types.ObjectId, ref: 'gh5313' }] + }, { typeKey: '$type' }); + + var bookSchema = Schema({ + title: String + }); + + var Book = mongoose.model('gh5313', bookSchema); + var Person = mongoose.model('gh5313_0', personSchema); + + var book1 = new Book({ title: 'The Jungle Book' }); + var book2 = new Book({ title: '1984' }); + + var person = new Person({ + name: 'Bob', + favorite: book1, + books: [book1, book2] + }); + + assert.equal(person.books[0].title, 'The Jungle Book'); + assert.equal(person.books[1].title, '1984'); + + done(); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From fbd933b401e2a9301e56778d8ef434c6536c52d5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 6 Jun 2017 22:24:48 -0600 Subject: [PATCH 1566/2240] fix(document): handle setting populated path with custom typeKey in schema Fix #5313 --- lib/document.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/document.js b/lib/document.js index b92726f420b..a00d41da6fa 100644 --- a/lib/document.js +++ b/lib/document.js @@ -724,14 +724,14 @@ Document.prototype.set = function(path, val, type, options) { var popOpts; if (schema.options && - Array.isArray(schema.options.type) && - schema.options.type.length && - schema.options.type[0].ref && + Array.isArray(schema.options[this.schema.options.typeKey]) && + schema.options[this.schema.options.typeKey].length && + schema.options[this.schema.options.typeKey][0].ref && Array.isArray(val) && val.length > 0 && val[0] instanceof Document && val[0].constructor.modelName && - (schema.options.type[0].ref === val[0].constructor.baseModelName || schema.options.type[0].ref === val[0].constructor.modelName)) { + (schema.options[this.schema.options.typeKey][0].ref === val[0].constructor.baseModelName || schema.options[this.schema.options.typeKey][0].ref === val[0].constructor.modelName)) { if (this.ownerDocument) { popOpts = { model: val[0].constructor }; this.ownerDocument().populated(this.$__fullPath(path), From a47795b140a596f4187386e4d6876ed167e5a544 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 7 Jun 2017 17:43:14 -0600 Subject: [PATCH 1567/2240] fix(model): make ensureIndexes() run with autoIndex: false unless called internally Fix #5328 Re: #5176 --- lib/model.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index edc6752dc4a..41b9c03f9a4 100644 --- a/lib/model.js +++ b/lib/model.js @@ -956,17 +956,24 @@ function _ensureIndexes(model, options, callback) { }; var create = function() { + if (options && options._automatic) { + if (model.schema.options.autoIndex === false || + (model.schema.options.autoIndex == null && model.db.config.autoIndex === false)) { + return done(); + } + } + var index = indexes.shift(); if (!index) return done(); var indexFields = index[0]; - var options = index[1]; + var indexOptions = index[1]; _handleSafe(options); indexSingleStart(indexFields, options); - model.collection.ensureIndex(indexFields, options, utils.tick(function(err, name) { - indexSingleDone(err, indexFields, options, name); + model.collection.ensureIndex(indexFields, indexOptions, utils.tick(function(err, name) { + indexSingleDone(err, indexFields, indexOptions, name); if (err) { return done(err); } From 3f49bb89c71fd37694a032ea5bd308039d826ff1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 7 Jun 2017 17:48:42 -0600 Subject: [PATCH 1568/2240] style: fix lint --- test/document.test.js | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index cb85ee3db73..6d7299bf8c9 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4191,33 +4191,32 @@ describe('document', function() { }); it('setting populated path with typeKey (gh-5313)', function(done) { - var personSchema = Schema( - { - name: {$type: String}, - favorite: { $type: Schema.Types.ObjectId, ref: 'gh5313' }, - books: [{ $type: Schema.Types.ObjectId, ref: 'gh5313' }] - }, { typeKey: '$type' }); - - var bookSchema = Schema({ - title: String - }); + var personSchema = Schema({ + name: {$type: String}, + favorite: { $type: Schema.Types.ObjectId, ref: 'gh5313' }, + books: [{ $type: Schema.Types.ObjectId, ref: 'gh5313' }] + }, { typeKey: '$type' }); + + var bookSchema = Schema({ + title: String + }); - var Book = mongoose.model('gh5313', bookSchema); - var Person = mongoose.model('gh5313_0', personSchema); + var Book = mongoose.model('gh5313', bookSchema); + var Person = mongoose.model('gh5313_0', personSchema); - var book1 = new Book({ title: 'The Jungle Book' }); - var book2 = new Book({ title: '1984' }); + var book1 = new Book({ title: 'The Jungle Book' }); + var book2 = new Book({ title: '1984' }); - var person = new Person({ - name: 'Bob', - favorite: book1, - books: [book1, book2] - }); + var person = new Person({ + name: 'Bob', + favorite: book1, + books: [book1, book2] + }); - assert.equal(person.books[0].title, 'The Jungle Book'); - assert.equal(person.books[1].title, '1984'); + assert.equal(person.books[0].title, 'The Jungle Book'); + assert.equal(person.books[1].title, '1984'); - done(); + done(); }); it('modify multiple subdoc paths (gh-4405)', function(done) { From 716acdd7cd93e52065c417528ad52a429f4484bb Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 9 Jun 2017 01:23:36 +0700 Subject: [PATCH 1569/2240] Memorize aliases mapping on schema --- lib/schema.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 89448cbd01f..1b7b20f4f61 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -74,6 +74,7 @@ function Schema(obj, options) { this.obj = obj; this.paths = {}; + this.aliases = {}; this.subpaths = {}; this.virtuals = {}; this.singleNestedPaths = {}; @@ -136,7 +137,6 @@ function Schema(obj, options) { * Create virtual properties with alias field */ function aliasFields(schema) { - // console.log(schema.paths); for (var path in schema.paths) { if (!schema.paths[path].options) continue; @@ -145,6 +145,11 @@ function aliasFields(schema) { if (alias) { if ('string' === typeof alias && alias.length > 0) { + if (schema.aliases[alias]) + throw new Error('Duplicate alias, alias ' + alias + ' is used more than once'); + else + schema.aliases[alias] = prop; + schema .virtual(alias) .get((function(p) { From 893994952b86c021d63448d2476da5a69bea7bfc Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 9 Jun 2017 01:24:00 +0700 Subject: [PATCH 1570/2240] Add Model.translateAliases method --- lib/model.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/lib/model.js b/lib/model.js index 35bb745815c..7023784dfca 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1060,6 +1060,55 @@ Model.base; Model.discriminators; +/** + * Translate any aliases fields/conditions so the final query or document object is pure + * + * ####Example: + * + * Character + * .find(Character.translateAliases({ + * '名': 'Eddard Stark' // Alias for 'name' + * }) + * .exec(function(err, characters) {}) + * + * ####Note: + * Only translate arguments of object type anything else is returned raw + * + * @param {Object} raw fields/conditions that may contain aliased keys + * @return {Object} the translated 'pure' fields/conditions + */ +Model.translateAliases = function translateAliases(fields) { + var aliases = this.schema.aliases; + + if (typeof fields === 'object') { + // Fields is an object (query conditions or document fields) + for (var key in fields) { + if (aliases[key]) { + var value = fields[key]; + var propPath = aliases[key]; // 'pure' property path + var segments = propPath.split('.'); + + if (segments.length < 2) { + fields[propPath] = value; + } else { + var obj = fields[segments[0]] = {}; + for (var i = 1; i < segments.length - 1; ++i) { + obj = obj[segments[i]] = {}; + } + obj[segments[segments.length - 1]] = value; + } + + delete fields[key]; + } + } + + return fields; + } else { + // Don't know typeof fields + return fields; + } +}; + /** * Removes the first document that matches `conditions` from the collection. * To remove all documents that match `conditions`, set the `justOne` option From 41c44e7de70dc96ff9e69126cf2e50db5bed8105 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 9 Jun 2017 01:24:50 +0700 Subject: [PATCH 1571/2240] Unit test for Model.translateAliases --- test/model.translateAliases.test.js | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 test/model.translateAliases.test.js diff --git a/test/model.translateAliases.test.js b/test/model.translateAliases.test.js new file mode 100644 index 00000000000..dfc39fa24bf --- /dev/null +++ b/test/model.translateAliases.test.js @@ -0,0 +1,33 @@ +/** + * Test dependencies. + */ + +var start = require('./common'), + assert = require('power-assert'), + mongoose = start.mongoose; + +describe('model translate aliases', function() { + it('should translate correctly', function() { + var Character = mongoose.model('Character', new mongoose.Schema({ + name: { type: String, alias: '名' }, + bio: { + age: { type: Number, alias: '年齢' } + } + })); + + assert.deepEqual( + // Translate aliases + Character.translateAliases({ + '名': 'Stark', + '年齢': 30 + }), + // How translated aliases suppose to look like + { + name: 'Stark', + bio: { + age: 30 + } + } + ); + }); +}); From 3bed3cb6c2a76e52e342ef7aa0253c0c5c5d9fac Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 8 Jun 2017 12:48:14 -0600 Subject: [PATCH 1572/2240] test: add test coverage for mutating params --- test/model.test.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/model.test.js b/test/model.test.js index 0e25096867f..81c5edac06b 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5354,6 +5354,7 @@ describe('Model', function() { schema.pre('insertMany', function(next, docs) { assert.equal(docs.length, 2); assert.equal(docs[0].name, 'Star Wars'); + docs[0].name = 'A New Hope'; ++calledPre; next(); }); @@ -5368,7 +5369,12 @@ describe('Model', function() { assert.equal(docs.length, 2); assert.equal(calledPre, 2); assert.equal(calledPost, 1); - done(); + Movie.find({}).sort({ name: 1 }).exec(function(error, docs) { + assert.ifError(error); + assert.equal(docs[0].name, 'A New Hope'); + assert.equal(docs[1].name, 'The Empire Strikes Back'); + done(); + }); }); }); From cfb07493101a53f01095cd8cb6404d6963b910c0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 8 Jun 2017 12:52:11 -0600 Subject: [PATCH 1573/2240] test(model): add more coverage for runSettersOnQuery --- test/model.query.casting.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index 98e1d4fbdd1..4c7f834cfdd 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -1030,20 +1030,22 @@ describe('model query casting', function() { }, { runSettersOnQuery: true }); var Test = db.model('gh-4569', testSchema); - Test.create({ name: 'val', num: 3 }). + Test.create({ name: 'val', num: 2.02 }). then(function() { return Test.findOne({ name: 'VAL' }); }). then(function(doc) { assert.ok(doc); assert.equal(doc.name, 'val'); + assert.equal(doc.num, 2); }). then(function() { - return Test.findOne({ num: 3.14 }); + return Test.findOneAndUpdate({}, { num: 3.14 }, { new: true }); }). then(function(doc) { assert.ok(doc); assert.equal(doc.name, 'val'); + assert.equal(doc.num, 3); }). then(function() { done(); }). catch(done); From 75d67d221a61ab8cbac34d37b995525a5f49f9d0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 8 Jun 2017 21:06:03 -0600 Subject: [PATCH 1574/2240] test(document): repro #5294 --- test/document.test.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 6d7299bf8c9..0df51b4f593 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4219,6 +4219,28 @@ describe('document', function() { done(); }); + it('save twice with write concern (gh-5294)', function(done) { + var schema = new mongoose.Schema({ + name: String + }, { + safe: { + w: 'majority', + wtimeout: 1e4 + } + }); + + var M = db.model('gh5294', schema); + + M.create({ name: 'Test' }, function(error, doc) { + assert.ifError(error); + doc.name = 'test2'; + doc.save(function(error) { + assert.ifError(error); + done(); + }); + }); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From a07fc59e1afcd87a5cc1fcdd062eda5b9de6e935 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 8 Jun 2017 21:06:27 -0600 Subject: [PATCH 1575/2240] fix(model): clone options before inserting in save() Fix #5294 --- lib/model.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index 41b9c03f9a4..10b016ce769 100644 --- a/lib/model.js +++ b/lib/model.js @@ -114,6 +114,7 @@ Model.prototype.$__handleSave = function(options, callback) { if (typeof options.safe === 'boolean') { options.safe = null; } + var safe = options.safe ? utils.clone(options.safe, { retainKeyOrder: true }) : options.safe; if (this.isNew) { // send entire doc @@ -140,7 +141,7 @@ Model.prototype.$__handleSave = function(options, callback) { } this.$__version(true, obj); - this.collection.insert(obj, options.safe, function(err, ret) { + this.collection.insert(obj, safe, function(err, ret) { if (err) { _this.isNew = true; _this.emit('isNew', true); @@ -185,7 +186,7 @@ Model.prototype.$__handleSave = function(options, callback) { } } - this.collection.update(where, delta[1], options.safe, function(err, ret) { + this.collection.update(where, delta[1], safe, function(err, ret) { if (err) { callback(err); return; From e8057f1eb10c2cb3ea4637f8676085782e71a77f Mon Sep 17 00:00:00 2001 From: c0d0g3n Date: Fri, 9 Jun 2017 21:45:44 +0200 Subject: [PATCH 1576/2240] schema type boolean: strictBool option added --- lib/schema/boolean.js | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js index 5951dd0513d..c4b437b40fa 100644 --- a/lib/schema/boolean.js +++ b/lib/schema/boolean.js @@ -58,16 +58,29 @@ SchemaBoolean.prototype.cast = function(value) { if (value === null) { return value; } - if (value === '0') { - return false; - } - if (value === 'true') { - return true; - } - if (value === 'false') { - return false; + + if (!this.options.strictBool) { + // legacy mode + if (value === '0') { + return false; + } + if (value === 'true') { + return true; + } + if (value === 'false') { + return false; + } + return !!value; + } else { + // strict mode (throws if value is not a boolean, instead of converting) + if (value === true || value === 'true' || value === 1 || value === '1') { + return true; + } + if (value === false || value === 'false' || value === 0 || value === '0') { + return false; + } + throw new CastError('boolean', value, this.path); } - return !!value; }; SchemaBoolean.$conditionalHandlers = From 0fb09d98694b9a58231e8a87befb8134e8e26c6b Mon Sep 17 00:00:00 2001 From: c0d0g3n Date: Fri, 9 Jun 2017 21:57:14 +0200 Subject: [PATCH 1577/2240] schema type boolean: strictBool test added --- test/schema.boolean.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/schema.boolean.test.js b/test/schema.boolean.test.js index 37b93db9ba4..6b96a28142d 100644 --- a/test/schema.boolean.test.js +++ b/test/schema.boolean.test.js @@ -29,5 +29,21 @@ describe('schematype', function() { assert.strictEqual(true, m3.b); done(); }); + it('strictBool option (gh-5211)', function() { + console.log('chekc'); + var db = start(), + s1 = new Schema({b: {type: Boolean, strictBool: true}}), + M1 = db.model('StrictBoolTrue', s1); + db.close(); + + var m1 = new M1; + var strictValues = [true, false, 'true', 'false', 0, 1, '0', '1']; + var validatePromises = strictValues.map(function(value) { + m1.b = value; + return m1.validate(); + }); + + return global.Promise.all(validatePromises); + }); }); }); From d199bf2b0190bc8f9fe3dd3909eafdf8fe2b59d9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 9 Jun 2017 19:59:53 -0600 Subject: [PATCH 1578/2240] test(document): repro #5296 --- test/document.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 0df51b4f593..dec625daf68 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4241,6 +4241,25 @@ describe('document', function() { }); }); + it('undefined field with conditional required (gh-5296)', function(done) { + var schema = Schema({ + name: { + type: String, + maxlength: 63, + required: function() { + return false; + } + }, + }); + + var Model = db.model('gh5296', schema); + + Model.create({ name: undefined }, function(error) { + assert.ifError(error); + done(); + }); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From dde7c711c315ea2ffb8aa84d7e282b250aaba8bf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 9 Jun 2017 20:00:37 -0600 Subject: [PATCH 1579/2240] fix(document): handle conditional required with undefined props Fix #5296 --- lib/schematype.js | 2 +- test/document.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/schematype.js b/lib/schematype.js index 35703a03393..bba3c995a42 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -762,7 +762,7 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { if (validator instanceof RegExp) { validate(validator.test(value), validatorProperties); } else if (typeof validator === 'function') { - if (value === undefined && !_this.isRequired) { + if (value === undefined && validator !== _this.requiredValidator) { validate(true, validatorProperties); return; } diff --git a/test/document.test.js b/test/document.test.js index dec625daf68..1580f8ff59f 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4249,7 +4249,7 @@ describe('document', function() { required: function() { return false; } - }, + } }); var Model = db.model('gh5296', schema); From 19c7810c17cb61cff6df2ccaad1e96efedfd3249 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 10 Jun 2017 18:32:25 -0600 Subject: [PATCH 1580/2240] test(populate): repro #5331 --- test/model.populate.test.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index f6cdbf9def6..f60fcdf49fd 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5121,6 +5121,35 @@ describe('model: populate:', function() { catch(done); }); + it('empty virtual with Model.populate (gh-5331)', function(done) { + var myModelSchema = new Schema({ + virtualRefKey: {type: String, ref: 'gh5331'} + }); + myModelSchema.set('toJSON', {virtuals:true}); + myModelSchema.virtual('populatedVirtualRef', { + ref: 'gh5331', + localField: 'virtualRefKey', + foreignField: 'handle' + }); + + var otherModelSchema = new Schema({ + handle: String + }); + + var MyModel = db.model('gh5331_0', myModelSchema); + db.model('gh5331', otherModelSchema); + + MyModel.create({ virtualRefKey: 'test' }, function(error, doc) { + assert.ifError(error); + MyModel.populate(doc, 'populatedVirtualRef', function(error, doc) { + assert.ifError(error); + assert.ok(doc.populatedVirtualRef); + assert.ok(Array.isArray(doc.populatedVirtualRef)); + done(); + }); + }); + }); + it('virtual populate in single nested doc (gh-4715)', function(done) { var someModelSchema = new mongoose.Schema({ name: String From 1f45e9bba174c06b55334a8127a91d5bae3aaa04 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 10 Jun 2017 18:33:40 -0600 Subject: [PATCH 1581/2240] fix(populate): handle empty virtual populate with Model.populate Fix #5331 --- lib/model.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index 10b016ce769..d945099e0c1 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3187,10 +3187,14 @@ function assignVals(o) { } if (o.isVirtual && !o.justOne && !Array.isArray(rawIds[i])) { - rawIds[i] = [rawIds[i]]; + if (rawIds[i] == null) { + rawIds[i] = []; + } else { + rawIds[i] = [rawIds[i]]; + } } - if (o.isVirtual && docs[i].constructor.name === 'model' && docs[i].$init) { + if (o.isVirtual && docs[i].constructor.name === 'model') { // If virtual populate and doc is already init-ed, need to walk through // the actual doc to set rather than setting `_doc` directly mpath.set(o.path, rawIds[i], docs[i]); From 8455cd4c35103f91ef8d69642d8759a3c66824e0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 10 Jun 2017 22:57:49 -0600 Subject: [PATCH 1582/2240] test(error): repro #5309 --- test/errors.validation.test.js | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/test/errors.validation.test.js b/test/errors.validation.test.js index 38226c9d085..b713b6eafee 100644 --- a/test/errors.validation.test.js +++ b/test/errors.validation.test.js @@ -3,12 +3,13 @@ * Module dependencies. */ -var assert = require('power-assert'), - start = require('./common'), - mongoose = start.mongoose, - Schema = mongoose.Schema, - SchemaType = mongoose.SchemaType, - ValidatorError = SchemaType.ValidatorError; +var assert = require('power-assert'); +var start = require('./common'); +var mongoose = start.mongoose; +var Schema = mongoose.Schema; +var SchemaType = mongoose.SchemaType; +var ValidatorError = SchemaType.ValidatorError; +var ValidationError = require('../lib/error/validation'); describe('ValidationError', function() { describe('#infiniteRecursion', function() { @@ -222,4 +223,22 @@ describe('ValidationError', function() { done(); }); }); + + it('JSON.stringify() with message (gh-5309)', function(done) { + model.modelName = 'TestClass'; + var err = new ValidationError(new model()); + + err.errors = { + test: { message: 'Fail' } + }; + + var obj = JSON.parse(JSON.stringify(err)); + assert.ok(obj.message.indexOf('TestClass validation failed') !== -1, + obj.message); + assert.ok(obj.message.indexOf('test: Fail') !== -1, + obj.message); + done(); + + function model() {} + }); }); From 2376945fda84ad1b84751f45d28bd06db958114f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 10 Jun 2017 22:58:06 -0600 Subject: [PATCH 1583/2240] fix(error): add toJSON helper to ValidationError so `message` shows up with JSON.stringify Fix #5309 --- lib/error/validation.js | 11 ++++++++++- lib/utils.js | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/error/validation.js b/lib/error/validation.js index c70a5f61901..012b2b8dba0 100644 --- a/lib/error/validation.js +++ b/lib/error/validation.js @@ -3,6 +3,7 @@ */ var MongooseError = require('../error.js'); +var utils = require('../utils'); /** * Document Validation Error @@ -60,7 +61,15 @@ ValidationError.prototype.toString = function() { */ ValidationError.prototype.inspect = function() { - return Object.assign(new Error(this.message), this); + return utils.assign(new Error(this.message), this); +}; + +/*! + * Helper for JSON.stringify + */ + +ValidationError.prototype.toJSON = function() { + return utils.assign({}, this, { message: this.message }); }; /*! diff --git a/lib/utils.js b/lib/utils.js index 2af2995ba55..3dffd4d6ab8 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -289,6 +289,26 @@ exports.clone = function clone(obj, options) { }; var clone = exports.clone; +/*! + * TODO: replace with Object.assign() in 5.0 + */ + +exports.assign = function(target) { + for (var i = 1; i < arguments.length; ++i) { + var nextSource = arguments[i]; + + if (nextSource != null) { + for (var nextKey in nextSource) { + if (nextSource.hasOwnProperty(nextKey)) { + target[nextKey] = nextSource[nextKey]; + } + } + } + } + + return target; +}; + /*! * ignore */ From 38e7d9aa611a7b04aefe7d666f9b4c9ea425ff77 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Jun 2017 18:32:45 -0600 Subject: [PATCH 1584/2240] docs: add clarification about empty objects by default Re: #5310 --- docs/faq.jade | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/faq.jade b/docs/faq.jade index 9ca9d50f8de..6e45f2cc6b3 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -68,6 +68,34 @@ block content rather than relying on mongoose to do it for you. The `unique` option for schemas is convenient for development and documentation, but mongoose is *not* an index management solution. + hr#nested-properties + :markdown + **Q**. When I have a nested property in a schema, mongoose adds empty objects by default. Why? + :js + var schema = new mongoose.Schema({ + nested: { + prop: String + } + }); + var Model = db.model('Test', schema); + + // The below prints `{ _id: /* ... */, nested: {} }`, mongoose assigns + // `nested` to an empty object `{}` by default. + console.log(new Model()); + :markdown + **A**. This is a performance optimization. These empty objects are not saved + to the database, nor are they in the result `toObject()`, nor do they show + up in `JSON.stringify()` output unless you turn off the [`minimize` option](http://mongoosejs.com/docs/guide.html#minimize). + + The reason for this behavior is that Mongoose's change detection + and getters/setters are based on [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). + In order to support change detection on nested properties without incurring + the overhead of running `Object.defineProperty()` every time a document is created, + mongoose defines properties on the `Model` prototype when the model is compiled. + Because mongoose needs to define getters and setters for `nested.prop`, `nested` + must always be defined as an object on a mongoose document, even if `nested` + is undefined on the underlying [POJO](http://mongoosejs.com/docs/guide.html#minimize). + hr#date_changes :markdown **Q**. Why don't in-place modifications to date objects From 19bae2f989ec88fb52ade8f9cec83320f3137512 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Jun 2017 19:02:32 -0600 Subject: [PATCH 1585/2240] test(populate): repro #5334 --- test/model.populate.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index f60fcdf49fd..1376b3c294c 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5087,6 +5087,31 @@ describe('model: populate:', function() { catch(done); }); + it('no ref + cursor (gh-5334)', function(done) { + var parentSchema = new Schema({ + name: String, + child: mongoose.Schema.Types.ObjectId + }); + var childSchema = new Schema({ + name: String + }); + + var Parent = db.model('gh5334_0', parentSchema); + var Child = db.model('gh5334', childSchema); + + Child.create({ name: 'Luke' }, function(error, child) { + assert.ifError(error); + Parent.create({ name: 'Vader', child: child._id }, function(error) { + assert.ifError(error); + Parent.find().populate({ path: 'child', model: 'gh5334' }).cursor().next(function(error, doc) { + assert.ifError(error); + assert.equal(doc.child.name, 'Luke'); + done(); + }); + }); + }); + }); + it('virtuals + doc.populate() (gh-5311)', function(done) { var parentSchema = new Schema({ name: String }); var childSchema = new Schema({ From a2c0ab93c418131387b1202a7a65b57fbf30402e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Jun 2017 19:03:14 -0600 Subject: [PATCH 1586/2240] fix(cursor): handle custom model option for populate Fix #5334 --- lib/cursor/QueryCursor.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/cursor/QueryCursor.js b/lib/cursor/QueryCursor.js index c196828bee5..227e821db18 100644 --- a/lib/cursor/QueryCursor.js +++ b/lib/cursor/QueryCursor.js @@ -283,9 +283,6 @@ function _next(ctx, cb) { var pop = helpers.preparePopulationOptionsMQ(ctx.query, ctx.query._mongooseOptions); - pop.forEach(function(option) { - delete option.model; - }); pop.__noPromise = true; ctx.query.model.populate(doc, pop, function(err, doc) { if (err) { From 3a59174ec75b1e97d1281157270cce60786d64ed Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Jun 2017 19:10:09 -0600 Subject: [PATCH 1587/2240] fix: wait for all connections to close before resolving disconnect() promise Fix #5316 --- lib/index.js | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/index.js b/lib/index.js index e5720cc5c87..b81dbe6e91e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -269,26 +269,29 @@ Mongoose.prototype.connect.$hasSideEffects = true; */ Mongoose.prototype.disconnect = function(fn) { - var error; - this.connections.forEach(function(conn) { - conn.close(function(err) { - if (error) { - return; - } - if (err) { - error = err; - } - }); - }); + var _this = this; var Promise = PromiseProvider.get(); return new MongooseThenable(this, new Promise.ES6(function(resolve, reject) { - fn && fn(error); - if (error) { - reject(error); + var remaining = _this.connections.length; + if (remaining <= 0) { + fn && fn(); + resolve(); return; } - resolve(); + _this.connections.forEach(function(conn) { + conn.close(function(error) { + if (error) { + fn && fn(error); + reject(error); + return; + } + if (!--remaining) { + fn && fn(); + resolve(); + } + }); + }); })); }; Mongoose.prototype.disconnect.$hasSideEffects = true; From bca9b54d94b664f484d2428bcdca30966e74fb7b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Jun 2017 19:15:36 -0600 Subject: [PATCH 1588/2240] docs(populate): clarify that multiple populate() calls on same path overwrite Fix #5274 --- docs/populate.jade | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/populate.jade b/docs/populate.jade index 2355abd2bb6..5613cbe6619 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -114,6 +114,18 @@ block content .populate('fans') .populate('_creator') .exec() + :markdown + If you call `populate()` multiple times with the same path, only the last + one will take effect. + :js + // The 2nd `populate()` call below overwrites the first because they + // both populate 'fans'. + Story. + find(). + populate({ path: 'fans', select: 'name' }). + populate({ path: 'fans', select: 'email' }); + // The above is equivalent to: + Story.find().populate({ path: 'fans', select: 'email' }); h3 Query conditions and other options :markdown What if we wanted to populate our fans array based on their age, select just their names, and return at most, any 5 of them? @@ -259,7 +271,7 @@ block content exec(function(error, docs) { /* ... */ }); :markdown This is known as a "cross-database populate," because it enables you to - populate across MongoDB databases and even acrosss MongoDB instances. + populate across MongoDB databases and even across MongoDB instances. h3#dynamic-ref Dynamic References :markdown From c5dc5a296f868aec660b29895048e312fa7bcc06 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Jun 2017 19:19:51 -0600 Subject: [PATCH 1589/2240] feat: add `getPromiseConstructor()` to prevent need for `mongoose.Promise.ES6` Fix #5305 --- lib/index.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/index.js b/lib/index.js index b81dbe6e91e..269af64741e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -691,6 +691,19 @@ Object.defineProperty(Mongoose.prototype, 'Promise', { } }); +/** + * Returns the current ES6-style promise constructor. In Mongoose 4.x, + * equivalent to `mongoose.Promise.ES6`, but will change once we get rid + * of the `.ES6` bit. + * + * @method Promise + * @api public + */ + +Mongoose.prototype.getPromiseConstructor = function() { + return PromiseProvider.get().ES6; +}; + /** * Storage layer for mongoose promises * From f6c90768a09ea6f1f581cf71d6835001d3905e9b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Jun 2017 20:50:05 -0600 Subject: [PATCH 1590/2240] docs(populate): fix code style --- docs/populate.jade | 116 ++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/docs/populate.jade b/docs/populate.jade index 5613cbe6619..e1831466374 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -53,14 +53,14 @@ block content :markdown So far we haven't done anything much different. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator` using the query builder: :js - Story - .findOne({ title: 'Once upon a timex.' }) - .populate('_creator') - .exec(function (err, story) { - if (err) return handleError(err); - console.log('The creator is %s', story._creator.name); - // prints "The creator is Aaron" - }); + Story. + findOne({ title: 'Once upon a timex.' }). + populate('_creator'). + exec(function (err, story) { + if (err) return handleError(err); + console.log('The creator is %s', story._creator.name); + // prints "The creator is Aaron" + }); :markdown Populated paths are no longer set to their original `_id` , their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. @@ -85,35 +85,35 @@ block content :markdown What if we only want a few specific fields returned for the populated documents? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: :js - Story - .findOne({ title: /timex/i }) - .populate('_creator', 'name') // only return the Persons name - .exec(function (err, story) { - if (err) return handleError(err); + Story. + findOne({ title: /timex/i }). + populate('_creator', 'name'). // only return the Persons name + exec(function (err, story) { + if (err) return handleError(err); - console.log('The creator is %s', story._creator.name); - // prints "The creator is Aaron" + console.log('The creator is %s', story._creator.name); + // prints "The creator is Aaron" - console.log('The creators age is %s', story._creator.age); - // prints "The creators age is null' - }) + console.log('The creators age is %s', story._creator.age); + // prints "The creators age is null' + }) h3 Populating multiple paths :markdown What if we wanted to populate multiple paths at the same time? :js - Story - .find(...) - .populate('fans _creator') // space delimited path names - .exec() + Story. + find(...). + populate('fans _creator'). // space delimited path names + exec() .important :markdown In **mongoose >= 3.6**, we can pass a space delimited string of path names to populate. Before 3.6 you must execute the `populate()` method multiple times. :js - Story - .find(...) - .populate('fans') - .populate('_creator') - .exec() + Story. + find(...). + populate('fans'). + populate('_creator'). + exec() :markdown If you call `populate()` multiple times with the same path, only the last one will take effect. @@ -130,16 +130,16 @@ block content :markdown What if we wanted to populate our fans array based on their age, select just their names, and return at most, any 5 of them? :js - Story - .find(...) - .populate({ - path: 'fans', - match: { age: { $gte: 21 }}, - // Explicitly exclude `_id`, see http://bit.ly/2aEfTdB - select: 'name -_id', - options: { limit: 5 } - }) - .exec() + Story. + find(...). + populate({ + path: 'fans', + match: { age: { $gte: 21 }}, + // Explicitly exclude `_id`, see http://bit.ly/2aEfTdB + select: 'name -_id', + options: { limit: 5 } + }). + exec() h3 Refs to children :markdown We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' onto `aaron.stories`. @@ -151,23 +151,23 @@ block content :markdown This allows us to perform a `find` and `populate` combo: :js - Person - .findOne({ name: 'Aaron' }) - .populate('stories') // only works if we pushed refs to children - .exec(function (err, person) { - if (err) return handleError(err); - console.log(person); - }) + Person. + findOne({ name: 'Aaron' }). + populate('stories'). // only works if we pushed refs to children + exec(function (err, person) { + if (err) return handleError(err); + console.log(person); + }); .important :markdown It is debatable that we really want two sets of pointers as they may get out of sync. Instead we could skip populating and directly `find()` the stories we are interested in. :js - Story - .find({ _creator: aaron._id }) - .exec(function (err, stories) { - if (err) return handleError(err); - console.log('The stories are an array: ', stories); - }) + Story. + find({ _creator: aaron._id }). + exec(function (err, stories) { + if (err) return handleError(err); + console.log('The stories are an array: ', stories); + }); h3 Updating refs :markdown @@ -185,15 +185,15 @@ block content story.save(function (err) { if (err) return handleError(err); - Story - .findOne({ title: /timex/i }) - .populate({ path: '_creator', select: 'name' }) - .exec(function (err, story) { - if (err) return handleError(err); + Story. + findOne({ title: /timex/i }). + populate({ path: '_creator', select: 'name' }). + exec(function (err, story) { + if (err) return handleError(err); - console.log('The creator is %s', story._creator.name) - // prints "The creator is Guillermo" - }) + console.log('The creator is %s', story._creator.name) + // prints "The creator is Guillermo" + }); }) }) From 7a4428fba0c330c34e09d9309e94e601f2794010 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 12 Jun 2017 10:14:26 -0600 Subject: [PATCH 1591/2240] docs(aggregate): bump docs link version --- lib/aggregate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index a93b3d4bb59..6de8260221c 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -528,7 +528,7 @@ Aggregate.prototype.cursor = function(options) { }; /** - * Adds a [cursor flag](http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#addCursorFlag) + * Adds a [cursor flag](http://mongodb.github.io/node-mongodb-native/2.2/api/Cursor.html#addCursorFlag) * * ####Example: * @@ -536,7 +536,7 @@ Aggregate.prototype.cursor = function(options) { * * @param {String} flag * @param {Boolean} value - * @see mongodb http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#addCursorFlag + * @see mongodb http://mongodb.github.io/node-mongodb-native/2.2/api/Cursor.html#addCursorFlag */ Aggregate.prototype.addCursorFlag = function(flag, value) { From 83c692577d0f3b8b8136b289a9e5b51cc31caa2f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 12 Jun 2017 10:52:28 -0600 Subject: [PATCH 1592/2240] feat(cursor): add addCursorFlag() support to query and agg cursors Fix #4814 --- lib/cursor/AggregationCursor.js | 32 ++++++++++++++++++++++++++++++++ lib/cursor/QueryCursor.js | 32 ++++++++++++++++++++++++++++++++ test/query.cursor.test.js | 15 +++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/lib/cursor/AggregationCursor.js b/lib/cursor/AggregationCursor.js index ce762b982b7..ef8c37ef681 100644 --- a/lib/cursor/AggregationCursor.js +++ b/lib/cursor/AggregationCursor.js @@ -237,6 +237,38 @@ AggregationCursor.prototype.eachAsync = function(fn, callback) { }); }; +/** + * Adds a [cursor flag](http://mongodb.github.io/node-mongodb-native/2.2/api/Cursor.html#addCursorFlag). + * Useful for setting the `noCursorTimeout` and `tailable` flags. + * + * @param {String} flag + * @param {Boolean} value + * @return {AggregationCursor} this + * @api public + * @method addCursorFlag + */ + +AggregationCursor.prototype.addCursorFlag = function(flag, value) { + var _this = this; + _waitForCursor(this, function() { + _this.cursor.addCursorFlag(flag, value); + }); + return this; +}; + +/*! + * ignore + */ + +function _waitForCursor(ctx, cb) { + if (ctx.cursor) { + return cb(); + } + ctx.once('cursor', function() { + cb(); + }); +} + /*! * Get the next doc from the underlying cursor and mongooseify it * (populate, etc.) diff --git a/lib/cursor/QueryCursor.js b/lib/cursor/QueryCursor.js index 227e821db18..c3d1b110041 100644 --- a/lib/cursor/QueryCursor.js +++ b/lib/cursor/QueryCursor.js @@ -241,6 +241,25 @@ QueryCursor.prototype.eachAsync = function(fn, callback) { }); }; +/** + * Adds a [cursor flag](http://mongodb.github.io/node-mongodb-native/2.2/api/Cursor.html#addCursorFlag). + * Useful for setting the `noCursorTimeout` and `tailable` flags. + * + * @param {String} flag + * @param {Boolean} value + * @return {AggregationCursor} this + * @api public + * @method addCursorFlag + */ + +QueryCursor.prototype.addCursorFlag = function(flag, value) { + var _this = this; + _waitForCursor(this, function() { + _this.cursor.addCursorFlag(flag, value); + }); + return this; +}; + /*! * Get the next doc from the underlying cursor and mongooseify it * (populate, etc.) @@ -300,6 +319,19 @@ function _next(ctx, cb) { } } +/*! + * ignore + */ + +function _waitForCursor(ctx, cb) { + if (ctx.cursor) { + return cb(); + } + ctx.once('cursor', function() { + cb(); + }); +} + /*! * Convert a raw doc into a full mongoose doc. */ diff --git a/test/query.cursor.test.js b/test/query.cursor.test.js index 70617a408c1..a024d5febaa 100644 --- a/test/query.cursor.test.js +++ b/test/query.cursor.test.js @@ -362,6 +362,21 @@ describe('QueryCursor', function() { }); }); + it('addCursorFlag (gh-4814)', function(done) { + var userSchema = new mongoose.Schema({ + name: String + }); + + var User = db.model('gh4814', userSchema); + + var cursor = User.find().cursor().addCursorFlag('noCursorTimeout', true); + + cursor.on('cursor', function() { + assert.equal(cursor.cursor.s.cmd.noCursorTimeout, true); + done(); + }); + }); + it('data before close (gh-4998)', function(done) { var userSchema = new mongoose.Schema({ name: String From 37c6ca4eb34838e29c3b8856f7ed4604f2362fc9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 12 Jun 2017 18:49:36 -0600 Subject: [PATCH 1593/2240] chore: release 4.10.6 --- History.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0674a03d38a..46f4566c5aa 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,16 @@ +4.10.6 / 2017-06-12 +=================== + * fix(cursor): handle custom model option for populate #5334 + * fix(populate): handle empty virtual populate with Model.populate #5331 + * fix(model): make ensureIndexes() run with autoIndex: false unless called internally #5328 #5324 #5317 + * fix: wait for all connections to close before resolving disconnect() promise #5316 + * fix(document): handle setting populated path with custom typeKey in schema #5313 + * fix(error): add toJSON helper to ValidationError so `message` shows up with JSON.stringify #5309 + * feat: add `getPromiseConstructor()` to prevent need for `mongoose.Promise.ES6` #5305 + * fix(document): handle conditional required with undefined props #5296 + * fix(model): clone options before inserting in save() #5294 + * docs(populate): clarify that multiple populate() calls on same path overwrite #5274 + 4.10.5 / 2017-06-06 =================== * chore: improve contrib guide for building docs #5312 diff --git a/package.json b/package.json index 412dd80f6cf..f055a70f31b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.6-pre", + "version": "4.10.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 554b4387a083a7bc3193a586193e11060337f473 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 12 Jun 2017 18:55:24 -0600 Subject: [PATCH 1594/2240] chore: now working on 4.10.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f055a70f31b..f8aad6b1cbf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.6", + "version": "4.10.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a939fa17a8fab3a98c20a8bb7ec2a0c251375717 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Jun 2017 11:33:19 -0600 Subject: [PATCH 1595/2240] feat(connection): add `useMongooseUri` option to opt in to using MongoClient.connect() Fix #5304 --- lib/connection.js | 47 +++++++++++++++++++++++++++++++++++++++++ lib/index.js | 15 ++++++++++++- test/connection.test.js | 24 +++++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index cf348f89cce..e34387e1b0c 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -11,6 +11,7 @@ var STATES = require('./connectionstate'); var MongooseError = require('./error'); var muri = require('muri'); var PromiseProvider = require('./promise_provider'); +var mongodb = require('mongodb'); /*! * Protocol prefix regexp. @@ -693,6 +694,52 @@ Connection.prototype.onOpen = function(callback) { } }; +/** + * Opens the connection with a URI using `MongoClient.connect()`. + * + * @param {String} uri The URI to connect with. + * @param {Object} [options] Passed on to http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect + * @param {Function} [callback] + * @returns {Connection} this + * @api private + */ + +Connection.prototype.openUri = function(uri, options, callback) { + this.readyState = STATES.connecting; + this._closeCalled = false; + + if (typeof options === 'function') { + callback = options; + options = null; + } + + var Promise = PromiseProvider.get(); + var _this = this; + + if (options && options.useMongooseUri) { + options = utils.clone(options, { retainKeyOrder: true }); + delete options.useMongooseUri; + } + + return new Promise.ES6(function(resolve, reject) { + mongodb.MongoClient.connect(uri, options, function(error, db) { + if (error) { + _this.readyState = STATES.disconnected; + if (_this.listeners('error').length) { + _this.emit('error', error); + } + return reject(error); + } + _this.db = db; + _this.readyState = STATES.connected; + + callback && callback(); + resolve(_this); + _this.emit('open'); + }); + }); +}; + /** * Closes the connection * diff --git a/lib/index.js b/lib/index.js index 269af64741e..7f9b3be0d4a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -185,9 +185,10 @@ var checkReplicaSetInUri = function(uri) { * @param {Object} [options] options to pass to the driver * @param {Object} [options.config] mongoose-specific options * @param {Boolean} [options.config.autoIndex] set to false to disable automatic index creation for all models associated with this connection. + * @param {Boolean} [options.useMongooseUri] false by default, set to true to use new mongoose connection logic * @see Connection#open #connection_Connection-open * @see Connection#openSet #connection_Connection-openSet - * @return {Connection} the created Connection object + * @return {Connection|Promise} the created Connection object, or promise that resolves to the connection if `useMongooseUri` option specified. * @api public */ @@ -196,6 +197,11 @@ Mongoose.prototype.createConnection = function(uri, options) { this.connections.push(conn); var rsOption = options && (options.replset || options.replSet); + + if (options && options.useMongooseUri) { + return conn.openUri(uri, options); + } + if (arguments.length) { if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) { conn._openSetWithoutPromise.apply(conn, arguments); @@ -244,6 +250,7 @@ Mongoose.prototype.createConnection.$hasSideEffects = true; * * @param {String} uri(s) * @param {Object} [options] + * @param {Boolean} [options.useMongooseUri] false by default, set to true to use new mongoose connection logic * @param {Function} [callback] * @see Mongoose#createConnection #index_Mongoose-createConnection * @api public @@ -252,6 +259,12 @@ Mongoose.prototype.createConnection.$hasSideEffects = true; Mongoose.prototype.connect = function() { var conn = this.connection; + if ((arguments.length === 2 || arguments.length === 3) && + typeof arguments[0] === 'string' && + typeof arguments[1] === 'object' && + arguments[1].useMongooseUri === true) { + return conn.openUri(arguments[0], arguments[1], arguments[2]); + } if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) { return new MongooseThenable(this, conn.openSet.apply(conn, arguments)); } diff --git a/test/connection.test.js b/test/connection.test.js index de65bba7ea2..0c1d25c22c7 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -14,6 +14,30 @@ var muri = require('muri'); */ describe('connections:', function() { + describe('useMongooseUri/openUri (gh-5304)', function() { + it('with mongoose.connect()', function(done) { + var promise = mongoose.connect('mongodb://localhost:27017/mongoosetest', { useMongooseUri: true }); + assert.equal(promise.constructor.name, 'Promise'); + + promise.then(function(conn) { + assert.equal(conn.constructor.name, 'NativeConnection'); + + return mongoose.disconnect().then(() => done()); + }).catch(done); + }); + + it('with mongoose.createConnection()', function(done) { + var promise = mongoose.createConnection('mongodb://localhost:27017/mongoosetest', { useMongooseUri: true }); + assert.equal(promise.constructor.name, 'Promise'); + + promise.then(function(conn) { + assert.equal(conn.constructor.name, 'NativeConnection'); + + return mongoose.disconnect().then(() => done()); + }).catch(done); + }); + }); + it('should allow closing a closed connection', function(done) { var db = mongoose.createConnection(); From 730c941339d810bcac4a0b0f903f460ee4626422 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Jun 2017 11:43:03 -0600 Subject: [PATCH 1596/2240] docs(connections): add details re: useMongooseUri Re: #5304 --- docs/connections.jade | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index 587c0013529..ce98abe15b6 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -3,15 +3,18 @@ extends layout block content h2 Connections :markdown - We may connect to MongoDB by utilizing the `mongoose.connect()` method. + You can connect to MongoDB with the `mongoose.connect()` method. :js mongoose.connect('mongodb://localhost/myapp'); :markdown - This is the minimum needed to connect the `myapp` database running locally on the default port (27017). If the local connection fails then try using 127.0.0.1 instead of localhost. Sometimes issues may arise when the local hostname has been changed. + This is the minimum needed to connect the `myapp` database running locally + on the default port (27017). If the local connection fails then try using + 127.0.0.1 instead of localhost. Sometimes issues may arise when the local + hostname has been changed. - We may also specify several more parameters in the `uri` depending on your environment: + You can also specify several more parameters in the `uri`: :js mongoose.connect('mongodb://username:password@host:port/database?options...'); @@ -189,6 +192,25 @@ block content // passing the option in the URI works with single or replica sets var uri = 'mongodb://localhost/test?poolSize=4'; mongoose.createConnection(uri); + + h3#use-mongoose-uri + :markdown + Mongoose's default connection logic is deprecated as of 4.11.0. Please opt + in to the new connection logic using the `useMongooseUri` option, but + make sure you test your connections first if you're upgrading an existing + codebase! + :js + // Using `mongoose.connect`... + var promise = mongoose.connect('mongodb://localhost/myapp', { useMongooseUri: true, /* other options */ }); + // Or `createConnection` + var promise = mongoose.createConnection('mongodb://localhost/myapp', { useMongooseUri: true, /* other options */ }); + // Or, if you already have a connection + connection.openUri('mongodb://localhost/myapp', { /* options */ }); + :markdown + This deprecation is because the [MongoDB driver](https://www.npmjs.com/package/mongodb) + has deprecated an API that is critical to mongoose's connection logic to + support MongoDB 3.6, see [this github issue](https://github.com/Automattic/mongoose/issues/5304) + for more details. h3#next Next Up :markdown From 3e6ad92eaceb2a6d3798adcfcc790c9244e730b0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Jun 2017 11:47:44 -0600 Subject: [PATCH 1597/2240] feat(connection): formally deprecate open() and openSet() --- lib/connection.js | 9 +++++---- lib/index.js | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index e34387e1b0c..83ab1826fbf 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -12,6 +12,7 @@ var MongooseError = require('./error'); var muri = require('muri'); var PromiseProvider = require('./promise_provider'); var mongodb = require('mongodb'); +var util = require('util'); /*! * Protocol prefix regexp. @@ -299,7 +300,7 @@ Connection.prototype._handleOpenArgs = function(host, database, port, options, c * @api public */ -Connection.prototype.open = function() { +Connection.prototype.open = util.deprecate(function() { var Promise = PromiseProvider.get(); var callback; @@ -338,7 +339,7 @@ Connection.prototype.open = function() { }; return promise; -}; +}, '`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongooseUri` option if using `connect()` or `createConnection()`'); /*! * ignore @@ -562,7 +563,7 @@ Connection.prototype._openSetWithoutPromise = function(uris, database, options, * @api public */ -Connection.prototype.openSet = function(uris, database, options, callback) { +Connection.prototype.openSet = util.deprecate(function(uris, database, options, callback) { var Promise = PromiseProvider.get(); try { @@ -599,7 +600,7 @@ Connection.prototype.openSet = function(uris, database, options, callback) { }; return promise; -}; +}, '`openSet()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongooseUri` option if using `connect()` or `createConnection()`'); /** * error diff --git a/lib/index.js b/lib/index.js index 7f9b3be0d4a..1058d3af3ae 100644 --- a/lib/index.js +++ b/lib/index.js @@ -4,17 +4,17 @@ * Module dependencies. */ -var Schema = require('./schema'), - SchemaType = require('./schematype'), - VirtualType = require('./virtualtype'), - STATES = require('./connectionstate'), - Types = require('./types'), - Query = require('./query'), - Model = require('./model'), - Document = require('./document'), - utils = require('./utils'), - format = utils.toCollectionName, - pkg = require('../package.json'); +var Schema = require('./schema'); +var SchemaType = require('./schematype'); +var VirtualType = require('./virtualtype'); +var STATES = require('./connectionstate'); +var Types = require('./types'); +var Query = require('./query'); +var Model = require('./model'); +var Document = require('./document'); +var utils = require('./utils'); +var format = utils.toCollectionName; +var pkg = require('../package.json'); var querystring = require('querystring'); var saveSubdocs = require('./plugins/saveSubdocs'); From 50163d4b7384b89f83ffed7fb0f29e47d8323c57 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Jun 2017 11:49:37 -0600 Subject: [PATCH 1598/2240] style: fix lint --- test/connection.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/connection.test.js b/test/connection.test.js index 0c1d25c22c7..267261df71d 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -22,7 +22,7 @@ describe('connections:', function() { promise.then(function(conn) { assert.equal(conn.constructor.name, 'NativeConnection'); - return mongoose.disconnect().then(() => done()); + return mongoose.disconnect().then(function() { done(); }); }).catch(done); }); @@ -33,7 +33,7 @@ describe('connections:', function() { promise.then(function(conn) { assert.equal(conn.constructor.name, 'NativeConnection'); - return mongoose.disconnect().then(() => done()); + return mongoose.disconnect().then(function() { done(); }); }).catch(done); }); }); From 384bae6801ec1588028bc9b7c00d730b8c934b3b Mon Sep 17 00:00:00 2001 From: Caleb Anderson Date: Tue, 13 Jun 2017 14:32:52 -0500 Subject: [PATCH 1599/2240] Update guide.jade Change custom => customize for readability --- docs/guide.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide.jade b/docs/guide.jade index 5c07c7d4380..4d660780ba9 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -668,7 +668,7 @@ block content :markdown If set `timestamps`, mongoose assigns `createdAt` and `updatedAt` fields to your schema, the type assigned is [Date](http://mongoosejs.com/docs/api.html#schema-date-js). - By default, the name of two fields are `createdAt` and `updatedAt`, custom the field name by setting `timestamps.createdAt` and `timestamps.updatedAt`. + By default, the name of two fields are `createdAt` and `updatedAt`, customize the field name by setting `timestamps.createdAt` and `timestamps.updatedAt`. :js var thingSchema = new Schema({..}, { timestamps: { createdAt: 'created_at' } }); var Thing = mongoose.model('Thing', thingSchema); From 27e82db245192b7b36d7c09c9809fe41342f3b3e Mon Sep 17 00:00:00 2001 From: Igwe Kalu Date: Wed, 14 Jun 2017 00:27:12 +0200 Subject: [PATCH 1600/2240] Fix mutates user passed option map --- lib/drivers/node-mongodb-native/connection.js | 3 +- package.json | 1 + test/parse.options.test.js | 55 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/parse.options.test.js diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index c6dd24a4d1c..1c1c12b050f 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -245,7 +245,8 @@ NativeConnection.prototype.doClose = function(fn) { */ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { - var o = passed || {}; + var o = passed ? require('clone')(passed) : {}; + o.db || (o.db = {}); o.auth || (o.auth = {}); o.server || (o.server = {}); diff --git a/package.json b/package.json index f8aad6b1cbf..f1bed8d9b0d 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "dependencies": { "async": "2.1.4", "bson": "~1.0.4", + "clone": "^2.1.1", "hooks-fixed": "2.0.0", "kareem": "1.4.1", "mongodb": "2.2.27", diff --git a/test/parse.options.test.js b/test/parse.options.test.js new file mode 100644 index 00000000000..c06d4c81c08 --- /dev/null +++ b/test/parse.options.test.js @@ -0,0 +1,55 @@ +var mongoose = require( '../' ); +var assert = require( 'power-assert' ); + +describe( 'parseOptions', function () { + it( 'should not mutate user passed options map', function () { + var db = new mongoose.Connection(); + var now = Date.now(); + + var userPassedOptionsMap = Object.create( null, { + auth: { + value: {}, + enumerable: true + }, + prop_num: { + value: now, + enumerable: true + }, + prop_obj: { + value: {}, + enumerable: true + } + } ); + var ultimateOptionsMap = db.parseOptions( userPassedOptionsMap ); + + assert.notEqual( ultimateOptionsMap, userPassedOptionsMap ); + assert.deepStrictEqual( userPassedOptionsMap, Object.create( null, { + auth: { + value: {}, + enumerable: true + }, + prop_num: { + value: now, + enumerable: true + }, + prop_obj: { + value: {}, + enumerable: true + } + } ) ); + assert.notDeepStrictEqual( ultimateOptionsMap, Object.create( null, { + auth: { + value: {}, + enumerable: true + }, + prop_num: { + value: now, + enumerable: true + }, + prop_obj: { + value: {}, + enumerable: true + } + } ) ); + } ); +} ); \ No newline at end of file From 586dc9fd4bbd2dc7e94cf1205041c1b78f48097f Mon Sep 17 00:00:00 2001 From: Igwe Kalu Date: Wed, 14 Jun 2017 01:22:59 +0200 Subject: [PATCH 1601/2240] Fixed ESLINT errors --- test/parse.options.test.js | 104 ++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/test/parse.options.test.js b/test/parse.options.test.js index c06d4c81c08..c9e9bf38770 100644 --- a/test/parse.options.test.js +++ b/test/parse.options.test.js @@ -1,55 +1,55 @@ -var mongoose = require( '../' ); -var assert = require( 'power-assert' ); +var mongoose = require('../'); +var assert = require('power-assert'); -describe( 'parseOptions', function () { - it( 'should not mutate user passed options map', function () { - var db = new mongoose.Connection(); - var now = Date.now(); +describe('parseOptions', function() { + it('should not mutate user passed options map', function() { + var db = new mongoose.Connection(); + var now = Date.now(); - var userPassedOptionsMap = Object.create( null, { - auth: { - value: {}, - enumerable: true - }, - prop_num: { - value: now, - enumerable: true - }, - prop_obj: { - value: {}, - enumerable: true - } - } ); - var ultimateOptionsMap = db.parseOptions( userPassedOptionsMap ); + var userPassedOptionsMap = Object.create(null, { + auth: { + value: {}, + enumerable: true + }, + prop_num: { + value: now, + enumerable: true + }, + prop_obj: { + value: {}, + enumerable: true + } + }); + var ultimateOptionsMap = db.parseOptions(userPassedOptionsMap); - assert.notEqual( ultimateOptionsMap, userPassedOptionsMap ); - assert.deepStrictEqual( userPassedOptionsMap, Object.create( null, { - auth: { - value: {}, - enumerable: true - }, - prop_num: { - value: now, - enumerable: true - }, - prop_obj: { - value: {}, - enumerable: true - } - } ) ); - assert.notDeepStrictEqual( ultimateOptionsMap, Object.create( null, { - auth: { - value: {}, - enumerable: true - }, - prop_num: { - value: now, - enumerable: true - }, - prop_obj: { - value: {}, - enumerable: true - } - } ) ); - } ); -} ); \ No newline at end of file + assert.notEqual(ultimateOptionsMap, userPassedOptionsMap); + assert.deepStrictEqual(userPassedOptionsMap, Object.create(null, { + auth: { + value: {}, + enumerable: true + }, + prop_num: { + value: now, + enumerable: true + }, + prop_obj: { + value: {}, + enumerable: true + } + })); + assert.notDeepStrictEqual(ultimateOptionsMap, Object.create(null, { + auth: { + value: {}, + enumerable: true + }, + prop_num: { + value: now, + enumerable: true + }, + prop_obj: { + value: {}, + enumerable: true + } + })); + }); +}); \ No newline at end of file From fbeed2a1a534f56bc8c36c7488fad9c73edc0c37 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Jun 2017 19:07:41 -0600 Subject: [PATCH 1602/2240] fix: callback with this --- lib/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index 83ab1826fbf..901e29d47cd 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -734,7 +734,7 @@ Connection.prototype.openUri = function(uri, options, callback) { _this.db = db; _this.readyState = STATES.connected; - callback && callback(); + callback && callback(null, _this); resolve(_this); _this.emit('open'); }); From 9507813d9330d88ca0914792f7c304e4cbd98d10 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Jun 2017 22:51:01 -0600 Subject: [PATCH 1603/2240] chore: get rid of old docs file --- docs/releases | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 docs/releases diff --git a/docs/releases b/docs/releases deleted file mode 100644 index 347723e3149..00000000000 --- a/docs/releases +++ /dev/null @@ -1,11 +0,0 @@ -3.8.x -3.7.x -3.6.x -3.5.x -3.4.x -3.3.x -3.2.x -3.1.x -3.0.x -2.8.x -2.7.x From 7d49b3722b74c382f60c067d29290aba51a691f9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Jun 2017 22:53:50 -0600 Subject: [PATCH 1604/2240] chore: bump bluebird dep to latest for test --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f8aad6b1cbf..c47fdcb812c 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "acquit": "0.4.1", "acquit-ignore": "0.0.3", "benchmark": "2.1.2", - "bluebird": "3.4.6", + "bluebird": "3.5.0", "co": "4.6.0", "dox": "0.3.1", "eslint": "2.4.0", From fe0a629897e9c43edea4ed8e0b82b72d306f5448 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 14 Jun 2017 18:17:24 -0600 Subject: [PATCH 1605/2240] test(populate): repro #5336 --- test/model.populate.test.js | 92 +++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 1376b3c294c..388d77bbdc0 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5214,6 +5214,98 @@ describe('model: populate:', function() { catch(done); }); + it('virtuals with justOne false and foreign field not found (gh-5336)', function(done) { + var BandSchema = new mongoose.Schema({ + name: String, + active: Boolean + }); + + var Band = db.model('gh5336', BandSchema); + + var PersonSchema = new mongoose.Schema({ + name: String, + bands: [String] + }); + + PersonSchema.virtual('bandDetails', { + ref: 'gh5336', + localField: 'bands', + foreignField: 'name', + justOne: false + }); + var Person = db.model('gh5336_0', PersonSchema); + + var band = new Band({name: 'The Beatles', active: false}); + var person = new Person({ + name: 'George Harrison', + bands: ['The Beatles'] + }); + + person.save(). + then(function() { return band.save(); }). + then(function() { + return Person.findOne({ name: 'George Harrison' }); + }). + then(function(person) { + return person.populate({ + path: 'bandDetails', + match: { active: { $eq: true } } + }).execPopulate(); + }). + then(function(person) { + person = person.toObject({ virtuals: true }); + assert.deepEqual(person.bandDetails, []); + done(); + }). + catch(done); + }); + + it('virtuals with justOne true and foreign field not found (gh-5336)', function(done) { + var BandSchema = new mongoose.Schema({ + name: String, + active: Boolean + }); + + var Band = db.model('gh5336_10', BandSchema); + + var PersonSchema = new mongoose.Schema({ + name: String, + bands: [String] + }); + + PersonSchema.virtual('bandDetails', { + ref: 'gh5336_10', + localField: 'bands', + foreignField: 'name', + justOne: true + }); + var Person = db.model('gh5336_11', PersonSchema); + + var band = new Band({name: 'The Beatles', active: false}); + var person = new Person({ + name: 'George Harrison', + bands: ['The Beatles'] + }); + + person.save(). + then(function() { return band.save(); }). + then(function() { + return Person.findOne({ name: 'George Harrison' }); + }). + then(function(person) { + return person.populate({ + path: 'bandDetails', + match: { active: { $eq: true } } + }).execPopulate(); + }). + then(function(person) { + person = person.toObject({ virtuals: true }); + assert.strictEqual(person.bandDetails, null); + done(); + }). + catch(done); + }); + it('select foreignField automatically (gh-4959)', function(done) { var childSchema = new mongoose.Schema({ name: String, From e65dd63a5e8aab72b3edea6adf6019ecc43906d9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 14 Jun 2017 18:17:37 -0600 Subject: [PATCH 1606/2240] fix(populate): don't set populate virtual to ids when match fails Fix #5336 --- lib/schema.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index b0465d8a3ae..dcf56003cbd 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1502,11 +1502,28 @@ Schema.prototype.virtual = function(name, options) { } return null; }). - set(function(v) { + set(function(_v) { if (!this.$$populatedVirtuals) { this.$$populatedVirtuals = {}; } - this.$$populatedVirtuals[name] = v; + + if (options.justOne) { + this.$$populatedVirtuals[name] = Array.isArray(_v) ? + _v[0] : + _v; + + if (typeof this.$$populatedVirtuals[name] !== 'object') { + this.$$populatedVirtuals[name] = null; + } + } else { + this.$$populatedVirtuals[name] = Array.isArray(_v) ? + _v : + _v == null ? [] : [_v]; + + this.$$populatedVirtuals[name] = this.$$populatedVirtuals[name].filter(function(doc) { + return doc && typeof doc === 'object'; + }); + } }); } From 3319fd717873c102a209b3343d1a3873aea69733 Mon Sep 17 00:00:00 2001 From: Igwe Kalu Date: Thu, 15 Jun 2017 11:06:48 +0200 Subject: [PATCH 1607/2240] Removed dependency on external 'clone' module and used the one in 'lib/utils' --- lib/drivers/node-mongodb-native/connection.js | 2 +- package.json | 2 +- test/parse.options.test.js | 11 ++++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 1c1c12b050f..98228ae4da9 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -245,7 +245,7 @@ NativeConnection.prototype.doClose = function(fn) { */ NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { - var o = passed ? require('clone')(passed) : {}; + var o = passed ? require('../../utils').clone(passed) : {}; o.db || (o.db = {}); o.auth || (o.auth = {}); diff --git a/package.json b/package.json index f1bed8d9b0d..c9b4aebdd4f 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "dependencies": { "async": "2.1.4", "bson": "~1.0.4", - "clone": "^2.1.1", "hooks-fixed": "2.0.0", "kareem": "1.4.1", "mongodb": "2.2.27", @@ -31,6 +30,7 @@ "ms": "2.0.0", "muri": "1.2.1", "regexp-clone": "0.0.1", + "sinon": "~2.3.4", "sliced": "1.0.1" }, "devDependencies": { diff --git a/test/parse.options.test.js b/test/parse.options.test.js index c9e9bf38770..f24f6ccb37f 100644 --- a/test/parse.options.test.js +++ b/test/parse.options.test.js @@ -1,5 +1,7 @@ var mongoose = require('../'); var assert = require('power-assert'); +var sinon = require('sinon'); +var util = require('../lib/utils'); describe('parseOptions', function() { it('should not mutate user passed options map', function() { @@ -20,8 +22,13 @@ describe('parseOptions', function() { enumerable: true } }); - var ultimateOptionsMap = db.parseOptions(userPassedOptionsMap); + var ultimateOptionsMap; + sinon.spy(util, 'clone'); + + ultimateOptionsMap = db.parseOptions(userPassedOptionsMap); + + assert.ok(util.clone.calledWith(userPassedOptionsMap)); assert.notEqual(ultimateOptionsMap, userPassedOptionsMap); assert.deepStrictEqual(userPassedOptionsMap, Object.create(null, { auth: { @@ -51,5 +58,7 @@ describe('parseOptions', function() { enumerable: true } })); + + util.clone.restore(); }); }); \ No newline at end of file From b4e3fc46757b0ccb8754f4e254f03c139096c01f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 15 Jun 2017 14:05:58 -0600 Subject: [PATCH 1608/2240] docs(validation): show overriding custom validator error with 2nd cb arg Fix #5358 --- test/docs/validation.test.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 33c9d36efcd..5312c2a489e 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -220,10 +220,15 @@ describe('validation docs', function() { isAsync: true, validator: function(v, cb) { setTimeout(function() { - cb(/\d{3}-\d{3}-\d{4}/.test(v)); + var phoneRegex = /\d{3}-\d{3}-\d{4}/; + var msg = v + ' is not a valid phone number!'; + // First argument is a boolean, whether validator succeeded + // 2nd argument is an optional error message override + cb(phoneRegex.test(v), msg); }, 5); }, - message: '{VALUE} is not a valid phone number!' + // Default error message, overridden by 2nd argument to `cb()` above + message: 'Default error message' }, required: [true, 'User phone number required'] }, From 3bcf41271d78173fe58ea411ab2cb5ea3c0e70bd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 16 Jun 2017 15:59:22 -0600 Subject: [PATCH 1609/2240] chore: remove sinon dep re: #5357 --- package.json | 1 - test/parse.options.test.js | 8 +------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/package.json b/package.json index f2672096c22..c47fdcb812c 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "ms": "2.0.0", "muri": "1.2.1", "regexp-clone": "0.0.1", - "sinon": "~2.3.4", "sliced": "1.0.1" }, "devDependencies": { diff --git a/test/parse.options.test.js b/test/parse.options.test.js index f24f6ccb37f..a2a8d58c634 100644 --- a/test/parse.options.test.js +++ b/test/parse.options.test.js @@ -1,6 +1,5 @@ var mongoose = require('../'); var assert = require('power-assert'); -var sinon = require('sinon'); var util = require('../lib/utils'); describe('parseOptions', function() { @@ -24,11 +23,8 @@ describe('parseOptions', function() { }); var ultimateOptionsMap; - sinon.spy(util, 'clone'); - ultimateOptionsMap = db.parseOptions(userPassedOptionsMap); - assert.ok(util.clone.calledWith(userPassedOptionsMap)); assert.notEqual(ultimateOptionsMap, userPassedOptionsMap); assert.deepStrictEqual(userPassedOptionsMap, Object.create(null, { auth: { @@ -58,7 +54,5 @@ describe('parseOptions', function() { enumerable: true } })); - - util.clone.restore(); }); -}); \ No newline at end of file +}); From 659c80f78a12bfd8bcfe74dc1e9de591d2427915 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 16 Jun 2017 21:51:20 -0600 Subject: [PATCH 1610/2240] test(query): repro #5323 --- test/model.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index 81c5edac06b..8ce70ca44d8 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5611,6 +5611,32 @@ describe('Model', function() { } }); + it('remove with cast error (gh-5323)', function(done) { + var schema = new mongoose.Schema({ + name: String + }); + + var Model = db.model('gh5323', schema); + var arr = [ + { name: 'test-1' }, + { name: 'test-2' } + ]; + + Model.create(arr, function(error) { + assert.ifError(error); + Model.remove([], function(error) { + assert.ok(error); + assert.ok(error.message.indexOf('Query filter must be an object') !== -1, + error.message); + Model.find({}, function(error, docs) { + assert.ifError(error); + assert.equal(docs.length, 2); + done(); + }); + }); + }); + }); + it('bulkWrite casting updateMany, deleteOne, deleteMany (gh-3998)', function(done) { var schema = new Schema({ str: String, From ba06058bb93cf14b66b8a4651362e1049cb0beec Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 16 Jun 2017 21:51:52 -0600 Subject: [PATCH 1611/2240] fix(query): callback with cast error if remove and delete* args have a cast error Fix #5323 --- lib/cast.js | 23 +++++--- lib/model.js | 4 +- lib/query.js | 111 ++++++++++++++++++++++++++++--------- test/parse.options.test.js | 1 - 4 files changed, 100 insertions(+), 39 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index 4ff8449dd54..b26acebd2e5 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -4,6 +4,7 @@ var StrictModeError = require('./error/strict'); var Types = require('./schema/index'); +var util = require('util'); var utils = require('./utils'); var ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon']; @@ -17,15 +18,19 @@ var ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon']; * @api private */ module.exports = function cast(schema, obj, options) { - var paths = Object.keys(obj), - i = paths.length, - _keys, - any$conditionals, - schematype, - nested, - path, - type, - val; + if (Array.isArray(obj)) { + throw new Error('Query filter must be an object, got an array ', util.inspect(obj)); + } + + var paths = Object.keys(obj); + var i = paths.length; + var _keys; + var any$conditionals; + var schematype; + var nested; + var path; + var type; + var val; while (i--) { path = paths[i]; diff --git a/lib/model.js b/lib/model.js index d945099e0c1..adfec2fbf2f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1083,13 +1083,13 @@ Model.remove = function remove(conditions, callback) { } // get the mongodb collection object - var mq = new this.Query(conditions, {}, this, this.collection); + var mq = new this.Query({}, {}, this, this.collection); if (callback) { callback = this.$wrapCallback(callback); } - return mq.remove(callback); + return mq.remove(conditions, callback); }; /** diff --git a/lib/query.js b/lib/query.js index 9137d95a9a1..259d669788f 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1591,7 +1591,7 @@ Query.prototype.sort = function(arg) { * query.remove(fn) // executes * query.remove() * - * @param {Object|Query} [criteria] mongodb selector + * @param {Object|Query} [filter] mongodb selector * @param {Function} [callback] optional params are (error, writeOpResult) * @return {Query} this * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult @@ -1599,22 +1599,41 @@ Query.prototype.sort = function(arg) { * @api public */ -Query.prototype.remove = function(cond, callback) { - if (typeof cond === 'function') { - callback = cond; - cond = null; +Query.prototype.remove = function(filter, callback) { + if (typeof filter === 'function') { + callback = filter; + filter = null; } - var cb = typeof callback === 'function'; + filter = utils.toObject(filter, { retainKeyOrder: true }); try { - this.cast(this.model); + this.cast(this.model, filter); + this.merge(filter); } catch (err) { - if (cb) return process.nextTick(callback.bind(null, err)); + this._castError = err; + } + + prepareDiscriminatorCriteria(this); + + if (!callback) { + return Query.base.remove.call(this); + } + + return this._remove(callback); +}; + +/*! + * ignore + */ + +Query.prototype._remove = function(callback) { + if (this._castError) { + callback(this._castError); return this; } - return Query.base.remove.call(this, cond, callback); + return Query.base.remove.call(this, callback); }; /** @@ -1627,7 +1646,7 @@ Query.prototype.remove = function(cond, callback) { * Character.deleteOne({ name: 'Eddard Stark' }, callback) * Character.deleteOne({ name: 'Eddard Stark' }).then(next) * - * @param {Object|Query} [criteria] mongodb selector + * @param {Object|Query} [filter] mongodb selector * @param {Function} [callback] optional params are (error, writeOpResult) * @return {Query} this * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult @@ -1635,22 +1654,41 @@ Query.prototype.remove = function(cond, callback) { * @api public */ -Query.prototype.deleteOne = function(cond, callback) { - if (typeof cond === 'function') { - callback = cond; - cond = null; +Query.prototype.deleteOne = function(filter, callback) { + if (typeof filter === 'function') { + callback = filter; + filter = null; } - var cb = typeof callback === 'function'; + filter = utils.toObject(filter, { retainKeyOrder: true }); try { - this.cast(this.model); + this.cast(this.model, filter); + this.merge(filter); } catch (err) { - if (cb) return process.nextTick(callback.bind(null, err)); + this._castError = err; + } + + prepareDiscriminatorCriteria(this); + + if (!callback) { + return Query.base.deleteOne.call(this); + } + + return this._deleteOne.call(this, callback); +}; + +/*! + * ignore + */ + +Query.prototype._deleteOne = function(callback) { + if (this._castError) { + callback(this._castError); return this; } - return Query.base.deleteOne.call(this, cond, callback); + return Query.base.deleteOne.call(this, callback); }; /** @@ -1663,7 +1701,7 @@ Query.prototype.deleteOne = function(cond, callback) { * Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, callback) * Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }).then(next) * - * @param {Object|Query} [criteria] mongodb selector + * @param {Object|Query} [filter] mongodb selector * @param {Function} [callback] optional params are (error, writeOpResult) * @return {Query} this * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult @@ -1671,22 +1709,41 @@ Query.prototype.deleteOne = function(cond, callback) { * @api public */ -Query.prototype.deleteMany = function(cond, callback) { - if (typeof cond === 'function') { - callback = cond; - cond = null; +Query.prototype.deleteMany = function(filter, callback) { + if (typeof filter === 'function') { + callback = filter; + filter = null; } - var cb = typeof callback === 'function'; + filter = utils.toObject(filter, { retainKeyOrder: true }); try { - this.cast(this.model); + this.cast(this.model, filter); + this.merge(filter); } catch (err) { - if (cb) return process.nextTick(callback.bind(null, err)); + this._castError = err; + } + + prepareDiscriminatorCriteria(this); + + if (!callback) { + return Query.base.deleteMany.call(this); + } + + return this._deleteMany.call(this, callback); +}; + +/*! + * ignore + */ + +Query.prototype._deleteMany = function(callback) { + if (this._castError) { + callback(this._castError); return this; } - return Query.base.deleteMany.call(this, cond, callback); + return Query.base.deleteMany.call(this, callback); }; /*! diff --git a/test/parse.options.test.js b/test/parse.options.test.js index a2a8d58c634..b9975e168cf 100644 --- a/test/parse.options.test.js +++ b/test/parse.options.test.js @@ -1,6 +1,5 @@ var mongoose = require('../'); var assert = require('power-assert'); -var util = require('../lib/utils'); describe('parseOptions', function() { it('should not mutate user passed options map', function() { From d8cdb442e47ad6fd77ab301f40a0d6086fea3799 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Sun, 18 Jun 2017 19:19:09 +0700 Subject: [PATCH 1612/2240] Fix aliases translation logic --- lib/model.js | 15 +-------------- test/model.translateAliases.test.js | 4 +--- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/lib/model.js b/lib/model.js index 7023784dfca..bc5aca2d033 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1084,20 +1084,7 @@ Model.translateAliases = function translateAliases(fields) { // Fields is an object (query conditions or document fields) for (var key in fields) { if (aliases[key]) { - var value = fields[key]; - var propPath = aliases[key]; // 'pure' property path - var segments = propPath.split('.'); - - if (segments.length < 2) { - fields[propPath] = value; - } else { - var obj = fields[segments[0]] = {}; - for (var i = 1; i < segments.length - 1; ++i) { - obj = obj[segments[i]] = {}; - } - obj[segments[segments.length - 1]] = value; - } - + fields[aliases[key]] = fields[key]; delete fields[key]; } } diff --git a/test/model.translateAliases.test.js b/test/model.translateAliases.test.js index dfc39fa24bf..301b556f9fb 100644 --- a/test/model.translateAliases.test.js +++ b/test/model.translateAliases.test.js @@ -24,9 +24,7 @@ describe('model translate aliases', function() { // How translated aliases suppose to look like { name: 'Stark', - bio: { - age: 30 - } + 'bio.age': 30 } ); }); From aa6d05af5c1d907ba4181be993e10baf612ec755 Mon Sep 17 00:00:00 2001 From: c0d0g3n Date: Sun, 18 Jun 2017 20:01:54 +0200 Subject: [PATCH 1613/2240] strictBool test rewritten to support Node < 4 --- test/schema.boolean.test.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/test/schema.boolean.test.js b/test/schema.boolean.test.js index 6b96a28142d..acf05f5bb8b 100644 --- a/test/schema.boolean.test.js +++ b/test/schema.boolean.test.js @@ -29,21 +29,29 @@ describe('schematype', function() { assert.strictEqual(true, m3.b); done(); }); - it('strictBool option (gh-5211)', function() { - console.log('chekc'); + it('strictBool option (gh-5211)', function(done) { var db = start(), s1 = new Schema({b: {type: Boolean, strictBool: true}}), M1 = db.model('StrictBoolTrue', s1); db.close(); - var m1 = new M1; var strictValues = [true, false, 'true', 'false', 0, 1, '0', '1']; - var validatePromises = strictValues.map(function(value) { - m1.b = value; - return m1.validate(); + + var testsRemaining = strictValues.length; + strictValues.forEach(function (value) { + var doc = new M1; + doc.b = value; + doc.validate(function (error) { + if (error) { + // test fails as soon as one value fails + return done(error) + } + if (!--testsRemaining) { + return done() + } + }); }); - return global.Promise.all(validatePromises); }); }); }); From 2eda0d9da905cad32baea8232d2112c6b0901b14 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Jun 2017 17:09:30 -0600 Subject: [PATCH 1614/2240] chore: release 4.10.7 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 46f4566c5aa..71b68712bd0 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.10.7 / 2017-06-18 +=================== + * docs(validation): show overriding custom validator error with 2nd cb arg #5358 + * fix: `parseOption` mutates user passed option map #5357 [igwejk](https://github.com/igwejk) + * docs: fix guide.jade typo #5356 [CalebAnderson2014](https://github.com/CalebAnderson2014) + * fix(populate): don't set populate virtual to ids when match fails #5336 + * fix(query): callback with cast error if remove and delete* args have a cast error #5323 + 4.10.6 / 2017-06-12 =================== * fix(cursor): handle custom model option for populate #5334 diff --git a/package.json b/package.json index c47fdcb812c..10fa2c8a3d5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.7-pre", + "version": "4.10.7", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From eda82b02014130ed17c2fe8a09525b25b33590bc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Jun 2017 17:11:06 -0600 Subject: [PATCH 1615/2240] Revert "chore: get rid of old docs file" This reverts commit 9507813d9330d88ca0914792f7c304e4cbd98d10. --- docs/releases | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs/releases diff --git a/docs/releases b/docs/releases new file mode 100644 index 00000000000..347723e3149 --- /dev/null +++ b/docs/releases @@ -0,0 +1,11 @@ +3.8.x +3.7.x +3.6.x +3.5.x +3.4.x +3.3.x +3.2.x +3.1.x +3.0.x +2.8.x +2.7.x From f15ed55f4c63b7d4b7b9a4c6496dff22c91cee9d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Jun 2017 17:19:58 -0600 Subject: [PATCH 1616/2240] chore: now working on 4.10.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 10fa2c8a3d5..2edfdc6a8be 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.7", + "version": "4.10.8-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 69e286a831d885533380e69e6fff3e93318c6cb9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Jun 2017 18:36:33 -0600 Subject: [PATCH 1617/2240] feat(query): execute setters with query as context for `runSettersOnQuery` Fix #5339 --- lib/cast.js | 76 +++++++++++++++++++++++--------- lib/query.js | 4 +- lib/schematype.js | 14 +++++- lib/services/query/castUpdate.js | 37 +++++++++------- test/model.query.casting.test.js | 14 +++++- 5 files changed, 105 insertions(+), 40 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index b26acebd2e5..fc9a9a6719c 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -15,9 +15,10 @@ var ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon']; * @param {Schema} schema * @param {Object} obj Object to cast * @param {Object} options the query options + * @param {Query} context passed to setters * @api private */ -module.exports = function cast(schema, obj, options) { +module.exports = function cast(schema, obj, options, context) { if (Array.isArray(obj)) { throw new Error('Query filter must be an object, got an array ', util.inspect(obj)); } @@ -40,7 +41,7 @@ module.exports = function cast(schema, obj, options) { var k = val.length; while (k--) { - val[k] = cast(schema, val[k]); + val[k] = cast(schema, val[k], options, context); } } else if (path === '$where') { type = typeof val; @@ -55,7 +56,7 @@ module.exports = function cast(schema, obj, options) { continue; } else if (path === '$elemMatch') { - val = cast(schema, val); + val = cast(schema, val, options, context); } else { if (!schema) { // no casting for Mixed types @@ -88,7 +89,7 @@ module.exports = function cast(schema, obj, options) { remainingConds = {}; pathLastHalf = split.slice(j).join('.'); remainingConds[pathLastHalf] = val; - obj[path] = cast(schematype.caster.schema, remainingConds)[pathLastHalf]; + obj[path] = cast(schematype.caster.schema, remainingConds, options, context)[pathLastHalf]; } else { obj[path] = val; } @@ -117,10 +118,16 @@ module.exports = function cast(schema, obj, options) { var value = val[geo]; if (val.$maxDistance != null) { - val.$maxDistance = numbertype.castForQuery(val.$maxDistance); + val.$maxDistance = numbertype.castForQueryWrapper({ + val: val.$maxDistance, + context: context + }); } if (val.$minDistance != null) { - val.$minDistance = numbertype.castForQuery(val.$minDistance); + val.$minDistance = numbertype.castForQueryWrapper({ + val: val.$minDistance, + context: context + }); } if (geo === '$within') { @@ -142,10 +149,16 @@ module.exports = function cast(schema, obj, options) { value.$geometry && typeof value.$geometry.type === 'string' && Array.isArray(value.$geometry.coordinates)) { if (value.$maxDistance != null) { - value.$maxDistance = numbertype.castForQuery(value.$maxDistance); + value.$maxDistance = numbertype.castForQueryWrapper({ + val: value.$maxDistance, + context: context + }); } if (value.$minDistance != null) { - value.$minDistance = numbertype.castForQuery(value.$minDistance); + value.$minDistance = numbertype.castForQueryWrapper({ + val: value.$minDistance, + context: context + }); } if (utils.isMongooseObject(value.$geometry)) { value.$geometry = value.$geometry.toObject({ @@ -174,7 +187,7 @@ module.exports = function cast(schema, obj, options) { } } - _cast(value, numbertype); + _cast(value, numbertype, context); } } @@ -197,7 +210,10 @@ module.exports = function cast(schema, obj, options) { }); if (!any$conditionals) { - obj[path] = schematype.castForQuery(val); + obj[path] = schematype.castForQueryWrapper({ + val: val, + context: context + }); } else { var ks = Object.keys(val), $cond; @@ -213,28 +229,46 @@ module.exports = function cast(schema, obj, options) { _keys = Object.keys(nested); if (_keys.length && _keys[0].charAt(0) === '$') { for (var key in nested) { - nested[key] = schematype.castForQuery(key, nested[key]); + nested[key] = schematype.castForQueryWrapper({ + $conditional: key, + val: nested[key], + context: context + }); } } else { - val[$cond] = schematype.castForQuery($cond, nested); + val[$cond] = schematype.castForQueryWrapper({ + $conditional: $cond, + val: nested, + context: context + }); } continue; } - cast(schematype.caster ? schematype.caster.schema : schema, nested); + cast(schematype.caster ? schematype.caster.schema : schema, nested, options, context); } else { - val[$cond] = schematype.castForQuery($cond, nested); + val[$cond] = schematype.castForQueryWrapper({ + $conditional: $cond, + val: nested, + context: context + }); } } } } else if (val.constructor.name === 'Array' && ['Buffer', 'Array'].indexOf(schematype.instance) === -1) { var casted = []; for (var valIndex = 0; valIndex < val.length; valIndex++) { - casted.push(schematype.castForQuery(val[valIndex])); + casted.push(schematype.castForQueryWrapper({ + val: val[valIndex], + context: context + })); } obj[path] = { $in: casted }; } else { - obj[path] = schematype.castForQuery(val); + obj[path] = schematype.castForQueryWrapper({ + val: val, + context: context + }); } } } @@ -242,13 +276,13 @@ module.exports = function cast(schema, obj, options) { return obj; }; -function _cast(val, numbertype) { +function _cast(val, numbertype, context) { if (Array.isArray(val)) { val.forEach(function(item, i) { if (Array.isArray(item) || utils.isObject(item)) { - return _cast(item, numbertype); + return _cast(item, numbertype, context); } - val[i] = numbertype.castForQuery(item); + val[i] = numbertype.castForQueryWrapper({ val: item, context: context }); }); } else { var nearKeys = Object.keys(val); @@ -257,10 +291,10 @@ function _cast(val, numbertype) { var nkey = nearKeys[nearLen]; var item = val[nkey]; if (Array.isArray(item) || utils.isObject(item)) { - _cast(item, numbertype); + _cast(item, numbertype, context); val[nkey] = item; } else { - val[nkey] = numbertype.castForQuery(item); + val[nkey] = numbertype.castForQuery({ val: item, context: context }); } } } diff --git a/lib/query.js b/lib/query.js index b8b12d4e5d0..c3d5a204532 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2879,7 +2879,7 @@ Query.prototype._castUpdate = function _castUpdate(obj, overwrite) { return castUpdate(this.schema, obj, { overwrite: overwrite, strict: strict - }); + }, this); }; /*! @@ -2993,7 +2993,7 @@ Query.prototype.cast = function(model, obj) { (model.schema.options && model.schema.options.strict), strictQuery: (this.options && this.options.strictQuery) || (model.schema.options && model.schema.options.strictQuery) - }); + }, this); } catch (err) { // CastError, assign model if (typeof err.setModel === 'function') { diff --git a/lib/schematype.js b/lib/schematype.js index bba3c995a42..347a1508383 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -989,6 +989,18 @@ SchemaType.prototype.$conditionalHandlers = { $type: $type }; +/*! + * Wraps `castForQuery` to handle context + */ + +SchemaType.prototype.castForQueryWrapper = function(params) { + this.$$context = params.context; + if ('$conditional' in params) { + return this.castForQuery(params.$conditional, params.val); + } + return this.castForQuery(params.val); +}; + /** * Cast the given value with the given optional query operator. * @@ -1018,7 +1030,7 @@ SchemaType.prototype.castForQuery = function($conditional, val) { SchemaType.prototype._castForQuery = function(val) { if (this.options && this.options.runSettersOnQuery) { - return this.applySetters(val, null); + return this.applySetters(val, this.$$context); } return this.cast(val); }; diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index 8811d0080dc..3c0f0df0328 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -11,10 +11,11 @@ var utils = require('../../utils'); * @param {Object} options * @param {Boolean} [options.overwrite] defaults to false * @param {Boolean|String} [options.strict] defaults to true + * @param {Query} context passed to setters * @return {Boolean} true iff the update is non-empty */ -module.exports = function castUpdate(schema, obj, options) { +module.exports = function castUpdate(schema, obj, options, context) { if (!obj) { return undefined; } @@ -67,7 +68,7 @@ module.exports = function castUpdate(schema, obj, options) { if (val && typeof val === 'object' && (!overwrite || hasDollarKey)) { - hasKeys |= walkUpdatePath(schema, val, op, options.strict); + hasKeys |= walkUpdatePath(schema, val, op, options.strict, context); } else if (overwrite && ret && typeof ret === 'object') { // if we are just using overwrite, cast the query and then we will // *always* return the value, even if it is an empty object. We need to @@ -75,7 +76,7 @@ module.exports = function castUpdate(schema, obj, options) { // user passes {} and wants to clobber the whole document // Also, _walkUpdatePath expects an operation, so give it $set since that // is basically what we're doing - walkUpdatePath(schema, ret, '$set', options.strict); + walkUpdatePath(schema, ret, '$set', options.strict, context); } else { var msg = 'Invalid atomic update value for ' + op + '. ' + 'Expected an object, received ' + typeof val; @@ -94,12 +95,13 @@ module.exports = function castUpdate(schema, obj, options) { * @param {Object} obj - part of a query * @param {String} op - the atomic operator ($pull, $set, etc) * @param {Boolean|String} strict + * @param {Query} context * @param {String} pref - path prefix (internal only) * @return {Bool} true if this path has keys to update * @api private */ -function walkUpdatePath(schema, obj, op, strict, pref) { +function walkUpdatePath(schema, obj, op, strict, context, pref) { var prefix = pref ? pref + '.' : '', keys = Object.keys(obj), i = keys.length, @@ -123,7 +125,7 @@ function walkUpdatePath(schema, obj, op, strict, pref) { if ('$each' in val) { obj[key] = { - $each: castUpdateVal(schematype, val.$each, op) + $each: castUpdateVal(schematype, val.$each, op, context) }; if (val.$slice != null) { @@ -138,14 +140,14 @@ function walkUpdatePath(schema, obj, op, strict, pref) { obj[key].$position = val.$position; } } else { - obj[key] = castUpdateVal(schematype, val, op); + obj[key] = castUpdateVal(schematype, val, op, context); } } else if (op === '$currentDate') { // $currentDate can take an object - obj[key] = castUpdateVal(schematype, val, op); + obj[key] = castUpdateVal(schematype, val, op, context); hasKeys = true; } else if (op in castOps && schematype) { - obj[key] = castUpdateVal(schematype, val, op); + obj[key] = castUpdateVal(schematype, val, op, context); hasKeys = true; } else { var pathToCheck = (prefix + key); @@ -170,7 +172,7 @@ function walkUpdatePath(schema, obj, op, strict, pref) { // gh-2314 // we should be able to set a schema-less field // to an empty object literal - hasKeys |= walkUpdatePath(schema, val, op, strict, prefix + key) || + hasKeys |= walkUpdatePath(schema, val, op, strict, context, prefix + key) || (utils.isObject(val) && Object.keys(val).length === 0); } } else { @@ -206,7 +208,7 @@ function walkUpdatePath(schema, obj, op, strict, pref) { } hasKeys = true; - obj[key] = castUpdateVal(schematype, val, op, key); + obj[key] = castUpdateVal(schematype, val, op, key, context); } } } @@ -243,11 +245,12 @@ var castOps = { * @param {SchemaType} schema * @param {Object} val * @param {String} op - the atomic operator ($pull, $set, etc) - * @param {String} [$conditional] + * @param {String} $conditional + * @param {Query} context * @api private */ -function castUpdateVal(schema, val, op, $conditional) { +function castUpdateVal(schema, val, op, $conditional, context) { if (!schema) { // non-existing schema path return op in numberOps @@ -273,7 +276,7 @@ function castUpdateVal(schema, val, op, $conditional) { if (op in numberOps) { if (op === '$inc') { - return schema.castForQuery(val); + return schema.castForQueryWrapper({ val: val, context: context }); } return Number(val); } @@ -284,8 +287,12 @@ function castUpdateVal(schema, val, op, $conditional) { return Boolean(val); } if (/^\$/.test($conditional)) { - return schema.castForQuery($conditional, val); + return schema.castForQueryWrapper({ + $conditional: $conditional, + val: val, + context: context + }); } - return schema.castForQuery(val); + return schema.castForQueryWrapper({ val: val, context: context }); } diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index 4c7f834cfdd..ccd1484e3b5 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -1024,14 +1024,24 @@ describe('model query casting', function() { it('lowercase in query (gh-4569)', function(done) { var db = start(); + var contexts = []; + var testSchema = new Schema({ name: { type: String, lowercase: true }, - num: { type: Number, set: function(v) { return Math.floor(v); } } + num: { + type: Number, + set: function(v) { + contexts.push(this); + return Math.floor(v); + } + } }, { runSettersOnQuery: true }); var Test = db.model('gh-4569', testSchema); Test.create({ name: 'val', num: 2.02 }). then(function() { + assert.equal(contexts.length, 1); + assert.equal(contexts[0].constructor.name, 'model'); return Test.findOne({ name: 'VAL' }); }). then(function(doc) { @@ -1046,6 +1056,8 @@ describe('model query casting', function() { assert.ok(doc); assert.equal(doc.name, 'val'); assert.equal(doc.num, 3); + assert.equal(contexts.length, 2); + assert.equal(contexts[1].constructor.name, 'Query'); }). then(function() { done(); }). catch(done); From 1667bdb646549e31cce1afb2b7a717598bfcedd9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Jun 2017 19:19:22 -0600 Subject: [PATCH 1618/2240] feat(schema): allow setting custom error constructor for custom validators --- lib/schematype.js | 19 +++++++++++++++---- lib/types/embedded.js | 2 +- test/document.test.js | 29 +++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/schematype.js b/lib/schematype.js index bba3c995a42..8f2eb80c6ba 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -559,6 +559,13 @@ SchemaType.prototype.validate = function(obj, message, type) { */ SchemaType.prototype.required = function(required, message) { + var customOptions = {}; + if (typeof required === 'object') { + customOptions = required; + message = customOptions.message || message; + required = required.isRequired; + } + if (required === false) { this.validators = this.validators.filter(function(v) { return v.validator !== this.requiredValidator; @@ -589,11 +596,11 @@ SchemaType.prototype.required = function(required, message) { } var msg = message || MongooseError.messages.general.required; - this.validators.unshift({ + this.validators.unshift(utils.assign({}, customOptions, { validator: this.requiredValidator, message: msg, type: 'required' - }); + })); return this; }; @@ -741,7 +748,9 @@ SchemaType.prototype.doValidate = function(value, fn, scope) { if (ok === undefined || ok) { --count || fn(null); } else { - err = new ValidatorError(validatorProperties); + var ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError; + err = new ErrorConstructor(validatorProperties); + err.$isValidatorError = true; fn(err); } }; @@ -871,7 +880,9 @@ SchemaType.prototype.doValidateSync = function(value, scope) { return; } if (ok !== undefined && !ok) { - err = new ValidatorError(validatorProperties); + var ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError; + err = new ErrorConstructor(validatorProperties); + err.$isValidatorError = true; } }; diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 0295c856f1c..e559d65dfbf 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -211,7 +211,7 @@ EmbeddedDocument.prototype.inspect = function() { EmbeddedDocument.prototype.invalidate = function(path, err, val, first) { if (!this.__parent) { Document.prototype.invalidate.call(this, path, err, val); - if (err.name === 'ValidatorError') { + if (err.$isValidatorError) { return true; } throw err; diff --git a/test/document.test.js b/test/document.test.js index 1580f8ff59f..d5a786e4e55 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4162,6 +4162,35 @@ describe('document', function() { }); }); + it('custom error types (gh-4009)', function(done) { + var CustomError = function() {}; + + var testSchema = new mongoose.Schema({ + num: { + type: Number, + required: { + ErrorConstructor: CustomError + }, + min: 5 + } + }); + + var Test = db.model('gh4009', testSchema); + + Test.create({}, function(error) { + assert.ok(error); + assert.ok(error.errors['num']); + assert.ok(error.errors['num'] instanceof CustomError); + Test.create({ num: 1 }, function(error) { + assert.ok(error); + assert.ok(error.errors['num']); + assert.ok(error.errors['num'].constructor.name, 'ValidatorError'); + assert.ok(!(error.errors['num'] instanceof CustomError)); + done(); + }); + }); + }); + it('saving a doc with nested string array (gh-5282)', function(done) { var testSchema = new mongoose.Schema({ strs: [[String]] From 0ee8e216f97e6df73a847bed8c5623a341827c30 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Jun 2017 19:25:38 -0600 Subject: [PATCH 1619/2240] docs(schematype): add docs re: object form of required Re: #4009 --- lib/schematype.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/schematype.js b/lib/schematype.js index 8f2eb80c6ba..14729d195b7 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -545,7 +545,9 @@ SchemaType.prototype.validate = function(obj, message, type) { * the value is not null nor undefined). However, most built-in mongoose schema * types override the default `checkRequired` function: * - * @param {Boolean} required enable/disable the validator + * @param {Boolean|Function|Object} required enable/disable the validator, or function that returns required boolean, or options object + * @param {Boolean|Function} [options.isRequired] enable/disable the validator, or function that returns required boolean + * @param {Function} [options.ErrorConstructor] custom error constructor. The constructor receives 1 parameter, an object containing the validator properties. * @param {String} [message] optional custom error message * @return {SchemaType} this * @see Customized Error Messages #error_messages_MongooseError-messages From 766c305ad5ec1b8fede1d55c906b4d4b6f078cbc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Jun 2017 22:32:20 -0600 Subject: [PATCH 1620/2240] test(document): repro #5370 --- test/document.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index 1580f8ff59f..43c4632b601 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4186,8 +4186,10 @@ describe('document', function() { var M = db.model('gh5236', childSchema); var m = new M({ _id: null }); - assert.ok(m._id); - done(); + m.save(function(error, doc) { + assert.equal(doc._id, null); + done(); + }); }); it('setting populated path with typeKey (gh-5313)', function(done) { From e60886449fb6a572809b1de3a649f3177b68eb28 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 18 Jun 2017 22:32:34 -0600 Subject: [PATCH 1621/2240] fix(model): allow null as an _id Fix #5370, Re: #5236 --- lib/model.js | 2 +- lib/schema/objectid.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index adfec2fbf2f..5ecd27549e8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -128,7 +128,7 @@ Model.prototype.$__handleSave = function(options, callback) { var obj = this.toObject(toObjectOptions); - if ((obj || {})._id == null) { + if ((obj || {})._id === void 0) { // documents must have an _id else mongoose won't know // what to update later if more changes are made. the user // wouldn't know what _id was generated by mongodb either diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index ac91ab8be3c..951ddabb6fb 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -198,10 +198,10 @@ function defaultId() { } function resetId(v) { - if (v == null) { + if (v === void 0) { return new oid(); } - this.$__._id = null; + delete this.$__._id; return v; } From e6395d64c8da75d0cde6e89eaef785fce142cc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gianfranc=C3=B8=20Palumbo?= Date: Mon, 19 Jun 2017 08:09:21 +0100 Subject: [PATCH 1622/2240] docs(): fix small formatting typo on schematypes --- docs/schematypes.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index 9afbfb36f5c..3f880f1cf1b 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -109,7 +109,7 @@ block content * `required`: boolean or function, if true adds a [required validator](http://mongoosejs.com/docs/validation.html#built-in-validators) for this property * `default`: Any or function, sets a default value for the path. If the value is a function, the return value of the function is used as the default. * `select`: boolean, specifies default [projections](https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/) for queries - * `validate: function, adds a [validator function](http://mongoosejs.com/docs/validation.html#built-in-validators) for this property + * `validate`: function, adds a [validator function](http://mongoosejs.com/docs/validation.html#built-in-validators) for this property * `get`: function, defines a custom getter for this property using [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). * `set`: function, defines a custom setter for this property using [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). * `alias`: string, mongoose >= 4.10.0 only. Defines a [virtual](http://mongoosejs.com/docs/guide.html#virtuals) with the given name that gets/sets this path. From 4c9a017223c9cb4fd9e544cdbec62d9d7f6f3edb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 19 Jun 2017 11:19:10 -0600 Subject: [PATCH 1623/2240] test(query): repro #5351 --- test/query.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index 7de4713e3f7..552317d7af3 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1944,6 +1944,31 @@ describe('Query', function() { }); }); + it('runSettersOnQuery works with _id field (gh-5351)', function(done) { + var testSchema = new Schema({ + val: { type: String } + }, { runSettersOnQuery: true }); + + var Test = db.model('gh5351', testSchema); + Test.create({ val: 'A string' }). + then(function() { + return Test.findOne({}); + }). + then(function(doc) { + return Test.findOneAndUpdate({_id: doc._id}, { + $set: { + val: 'another string' + } + }, { new: true }); + }). + then(function(doc) { + assert.ok(doc); + assert.equal(doc.val, 'another string'); + }). + then(done). + catch(done); + }); + it('$exists under $not (gh-4933)', function(done) { var TestSchema = new Schema({ test: String From 48d64add5137599f75a9552d188376e3cf8e6f91 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 19 Jun 2017 11:19:44 -0600 Subject: [PATCH 1624/2240] fix(query): handle runSettersOnQuery in built-in _id setter --- lib/schema/objectid.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index 951ddabb6fb..3013558ebf3 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -198,10 +198,15 @@ function defaultId() { } function resetId(v) { + Document || (Document = require('./../document')); + if (v === void 0) { return new oid(); } - delete this.$__._id; + + if (this instanceof Document) { + delete this.$__._id; + } return v; } From 123e9b7b2c8db65a933c4a9ac4d033322edebb46 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Jun 2017 08:59:14 -0600 Subject: [PATCH 1625/2240] test(populate): repro #5364 --- test/model.populate.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 388d77bbdc0..30b66ae9f58 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5214,6 +5214,24 @@ describe('model: populate:', function() { catch(done); }); + it('populate with missing schema (gh-5364)', function(done) { + var Foo = db.model('gh5364', new mongoose.Schema({ + bar: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Bar' + }, + })); + + Foo.create({ bar: new mongoose.Types.ObjectId() }, function(error) { + assert.ifError(error); + Foo.find().populate('bar').exec(function(error) { + assert.ok(error); + assert.equal(error.name, 'MissingSchemaError'); + done(); + }); + }); + }); + it('virtuals with justOne false and foreign field not found (gh-5336)', function(done) { var BandSchema = new mongoose.Schema({ name: String, From 4509bf38abad0a9d9fe8e5b53ba7ab731229c1c2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Jun 2017 08:59:27 -0600 Subject: [PATCH 1626/2240] fix(populate): don't throw async uncaught exception if model not found in populate Fix #5364 --- lib/model.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/model.js b/lib/model.js index 5ecd27549e8..c7750dee63f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3338,7 +3338,12 @@ function getModelsMapForPopulate(model, docs, options) { modelForFindSchema = utils.getValue(discriminatorKey, doc); if (modelForFindSchema) { - modelForCurrentDoc = model.db.model(modelForFindSchema); + try { + modelForCurrentDoc = model.db.model(modelForFindSchema); + } catch (error) { + return error; + } + schemaForCurrentDoc = modelForCurrentDoc._getSchema(options.path); if (schemaForCurrentDoc && schemaForCurrentDoc.caster) { @@ -3403,9 +3408,13 @@ function getModelsMapForPopulate(model, docs, options) { modelName = modelNames[k]; var _doc = Array.isArray(doc) && isRefPathArray ? doc[k] : doc; var _ret = Array.isArray(ret) && isRefPathArray ? ret[k] : ret; - Model = originalModel && originalModel.modelName ? - originalModel : - model.db.model(modelName); + try { + Model = originalModel && originalModel.modelName ? + originalModel : + model.db.model(modelName); + } catch(error) { + return error; + } if (!available[modelName]) { currentOptions = { From 817c42ed7c898009354502c666622b36687bc919 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Jun 2017 09:27:08 -0600 Subject: [PATCH 1627/2240] fix(error): don't use custom getter for ValidationError message Fix #5359 --- lib/document.js | 2 +- lib/error/validation.js | 16 +++++++++------- lib/services/updateValidators.js | 2 +- test/errors.validation.test.js | 5 ++--- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/document.js b/lib/document.js index a00d41da6fa..eb3914adbf1 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1609,7 +1609,7 @@ Document.prototype.invalidate = function(path, err, val, kind) { return this.$__.validationError; } - this.$__.validationError.errors[path] = err; + this.$__.validationError.addError(path, err); return this.$__.validationError; }; diff --git a/lib/error/validation.js b/lib/error/validation.js index 012b2b8dba0..ce96d7aa79d 100644 --- a/lib/error/validation.js +++ b/lib/error/validation.js @@ -41,13 +41,6 @@ function ValidationError(instance) { ValidationError.prototype = Object.create(MongooseError.prototype); ValidationError.prototype.constructor = MongooseError; -Object.defineProperty(ValidationError.prototype, 'message', { - get: function() { - return this._message + ': ' + _generateMessage(this); - }, - enumerable: true -}); - /** * Console.log helper */ @@ -72,6 +65,15 @@ ValidationError.prototype.toJSON = function() { return utils.assign({}, this, { message: this.message }); }; +/*! + * add message + */ + +ValidationError.prototype.addError = function(path, error) { + this.errors[path] = error; + this.message = this._message + ': ' + _generateMessage(this); +}; + /*! * ignore */ diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 096a61a73a8..5bba9697727 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -146,7 +146,7 @@ module.exports = function(query, schema, castedDoc, options) { if (validationErrors.length) { var err = new ValidationError(null); for (var i = 0; i < validationErrors.length; ++i) { - err.errors[validationErrors[i].path] = validationErrors[i]; + err.addError(validationErrors[i].path, validationErrors[i]); } return callback(err); } diff --git a/test/errors.validation.test.js b/test/errors.validation.test.js index b713b6eafee..c446e75c2f8 100644 --- a/test/errors.validation.test.js +++ b/test/errors.validation.test.js @@ -228,15 +228,14 @@ describe('ValidationError', function() { model.modelName = 'TestClass'; var err = new ValidationError(new model()); - err.errors = { - test: { message: 'Fail' } - }; + err.addError('test', { message: 'Fail' }); var obj = JSON.parse(JSON.stringify(err)); assert.ok(obj.message.indexOf('TestClass validation failed') !== -1, obj.message); assert.ok(obj.message.indexOf('test: Fail') !== -1, obj.message); + done(); function model() {} From dfd44146be1274829348415875dd29b63da23f62 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 20 Jun 2017 09:30:29 -0600 Subject: [PATCH 1628/2240] style: fix lint --- lib/model.js | 2 +- test/model.populate.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index c7750dee63f..0a7bca6a40c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3412,7 +3412,7 @@ function getModelsMapForPopulate(model, docs, options) { Model = originalModel && originalModel.modelName ? originalModel : model.db.model(modelName); - } catch(error) { + } catch (error) { return error; } diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 30b66ae9f58..ae06e9cf371 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5219,7 +5219,7 @@ describe('model: populate:', function() { bar: { type: mongoose.Schema.Types.ObjectId, ref: 'Bar' - }, + } })); Foo.create({ bar: new mongoose.Types.ObjectId() }, function(error) { From 0545f029361479c57c880691ad3cc2bc7fd150c5 Mon Sep 17 00:00:00 2001 From: Varun Jayaraman Date: Tue, 20 Jun 2017 23:42:56 -0400 Subject: [PATCH 1629/2240] feat: add merge method to raw query update method --- lib/query.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/query.js b/lib/query.js index 259d669788f..7fd3520cf33 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2521,6 +2521,10 @@ Query.prototype.update = function(conditions, doc, options, callback) { callback = undefined; } + if (doc) { + this._mergeUpdate(doc); + } + return _update(this, 'update', conditions, doc, options, callback); }; From 10e0fbd41f1be2b90759226c00e371e8c70a6f2c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 14:02:33 -0600 Subject: [PATCH 1630/2240] test(document): repro #5347 --- test/document.test.js | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 43c4632b601..8259c33db2d 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4262,6 +4262,52 @@ describe('document', function() { }); }); + it('consistent context for nested docs (gh-5347)', function(done) { + var contexts = []; + var childSchema = new mongoose.Schema({ + phoneNumber: { + type: String, + required: function() { + contexts.push(this); + return this.notifications.isEnabled; + } + }, + notifications: { + isEnabled: { type: Boolean, required: true } + } + }); + + var parentSchema = new mongoose.Schema({ + name: String, + children: [childSchema] + }); + + var Parent = db.model('gh5347', parentSchema); + + Parent.create({ + name: 'test', + children: [ + { + phoneNumber: '123', + notifications: { + isEnabled: true + } + } + ] + }, function(error, doc) { + assert.ifError(error); + var child = doc.children.id(doc.children[0]._id); + child.phoneNumber = '345'; + doc.save(function(error, doc) { + assert.ifError(error); + assert.equal(contexts.length, 2); + assert.ok(contexts[0].toObject().notifications.isEnabled); + assert.ok(contexts[1].toObject().notifications.isEnabled); + done(); + }); + }); + }); + it('modify multiple subdoc paths (gh-4405)', function(done) { var ChildObjectSchema = new Schema({ childProperty1: String, From 6a571b28f424d05b5bb536d552efee8bda4cc62a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 14:03:15 -0600 Subject: [PATCH 1631/2240] fix(document): ensure consistent context for nested doc custom validators Fix #5347 --- lib/document.js | 14 +++++++++++--- lib/internal.js | 1 + lib/types/array.js | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/document.js b/lib/document.js index eb3914adbf1..9cce31a900d 100644 --- a/lib/document.js +++ b/lib/document.js @@ -845,7 +845,7 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche var _this = this; if (shouldModify) { - this.markModified(pathToMark, val); + this.markModified(pathToMark); // handle directly setting arrays (gh-1126) MongooseArray || (MongooseArray = require('./types/array')); @@ -996,11 +996,15 @@ Document.prototype.$__path = function(path) { * doc.save() // changes to mixed.type are now persisted * * @param {String} path the path to mark modified + * @param {Document} [scope] the scope to run validators with * @api public */ -Document.prototype.markModified = function(path) { +Document.prototype.markModified = function(path, scope) { this.$__.activePaths.modify(path); + if (scope != null && !this.ownerDocument) { + this.$__.pathsToScopes[path] = scope; + } }; /** @@ -1018,6 +1022,7 @@ Document.prototype.markModified = function(path) { Document.prototype.unmarkModified = function(path) { this.$__.activePaths.init(path); + delete this.$__.pathsToScopes[path]; }; /** @@ -1459,12 +1464,15 @@ Document.prototype.$__validate = function(callback) { } var val = _this.getValue(path); + var scope = path in _this.$__.pathsToScopes ? + _this.$__.pathsToScopes[path] : + _this; p.doValidate(val, function(err) { if (err) { _this.invalidate(path, err, undefined, true); } --total || complete(); - }, _this); + }, scope); }); }; diff --git a/lib/internal.js b/lib/internal.js index edf3338a268..df7d5aa8557 100644 --- a/lib/internal.js +++ b/lib/internal.js @@ -24,6 +24,7 @@ function InternalCache() { this.wasPopulated = false; // if this doc was the result of a population this.scope = undefined; this.activePaths = new ActiveRoster; + this.pathsToScopes = {}; // embedded docs this.ownerDocument = undefined; diff --git a/lib/types/array.js b/lib/types/array.js index 510ff1b0e33..4aff7bf9799 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -154,7 +154,7 @@ MongooseArray.mixin = { } } - parent.markModified(dirtyPath); + parent.markModified(dirtyPath, elem); } return this; From 8489948d56d361e372d18640b0ecc08ce0e22079 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 18:43:09 -0600 Subject: [PATCH 1632/2240] style: fix lint --- test/document.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/document.test.js b/test/document.test.js index 8259c33db2d..94a8de8cedb 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4298,7 +4298,7 @@ describe('document', function() { assert.ifError(error); var child = doc.children.id(doc.children[0]._id); child.phoneNumber = '345'; - doc.save(function(error, doc) { + doc.save(function(error) { assert.ifError(error); assert.equal(contexts.length, 2); assert.ok(contexts[0].toObject().notifications.isEnabled); From 1835bb714a4c80fc75319ff43388e5d7354fe0c2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 19:34:20 -0600 Subject: [PATCH 1633/2240] fix: correctly cast decimals in update Fix #5361 --- lib/query.js | 9 ++++----- lib/schema/decimal128.js | 6 +++++- lib/services/query/castUpdate.js | 1 - lib/types/embedded.js | 7 ++++++- lib/utils.js | 10 ++++++++-- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/query.js b/lib/query.js index 7fd3520cf33..95748e7a91a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -186,7 +186,10 @@ Query.prototype.toConstructor = function toConstructor() { p.op = this.op; p._conditions = utils.clone(this._conditions, { retainKeyOrder: true }); p._fields = utils.clone(this._fields); - p._update = utils.clone(this._update); + p._update = utils.clone(this._update, { + flattenDecimals: false, + retainKeyOrder: true + }); p._path = this._path; p._distinct = this._distinct; p._collection = this._collection; @@ -2521,10 +2524,6 @@ Query.prototype.update = function(conditions, doc, options, callback) { callback = undefined; } - if (doc) { - this._mergeUpdate(doc); - } - return _update(this, 'update', conditions, doc, options, callback); }; diff --git a/lib/schema/decimal128.js b/lib/schema/decimal128.js index 67e35df4830..0fba739cee0 100644 --- a/lib/schema/decimal128.js +++ b/lib/schema/decimal128.js @@ -104,10 +104,14 @@ Decimal128.prototype.cast = function(value, doc, init) { return ret; } - if (value === null || value === undefined) { + if (value == null) { return value; } + if (typeof value === 'object' && typeof value.$numberDecimal === 'string') { + return Decimal128Type.fromString(value.$numberDecimal); + } + if (value instanceof Decimal128Type) { return value; } diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index 8811d0080dc..af09fcc6527 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -286,6 +286,5 @@ function castUpdateVal(schema, val, op, $conditional) { if (/^\$/.test($conditional)) { return schema.castForQuery($conditional, val); } - return schema.castForQuery(val); } diff --git a/lib/types/embedded.js b/lib/types/embedded.js index 0295c856f1c..3f0beed26ca 100644 --- a/lib/types/embedded.js +++ b/lib/types/embedded.js @@ -196,7 +196,12 @@ EmbeddedDocument.prototype.update = function() { */ EmbeddedDocument.prototype.inspect = function() { - return this.toObject({ transform: false, retainKeyOrder: true, virtuals: false }); + return this.toObject({ + transform: false, + retainKeyOrder: true, + virtuals: false, + flattenDecimals: false + }); }; /** diff --git a/lib/utils.js b/lib/utils.js index 3dffd4d6ab8..fdb848d2091 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -861,7 +861,10 @@ exports.mergeClone = function(to, fromObj) { if (typeof to[key] === 'undefined') { // make sure to retain key order here because of a bug handling the $each // operator in mongodb 2.4.4 - to[key] = exports.clone(fromObj[key], {retainKeyOrder: 1}); + to[key] = exports.clone(fromObj[key], { + retainKeyOrder: 1, + flattenDecimals: false + }); } else { if (exports.isObject(fromObj[key])) { var obj = fromObj[key]; @@ -875,7 +878,10 @@ exports.mergeClone = function(to, fromObj) { } else { // make sure to retain key order here because of a bug handling the // $each operator in mongodb 2.4.4 - to[key] = exports.clone(fromObj[key], {retainKeyOrder: 1}); + to[key] = exports.clone(fromObj[key], { + retainKeyOrder: 1, + flattenDecimals: false + }); } } } From ed76294c5ab0cba59eb56e3a1cbfbcf201aa9d58 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 19:41:59 -0600 Subject: [PATCH 1634/2240] test: add coverage for #5361 --- test/model.update.test.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 1c748545458..2c5ec61895e 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2585,6 +2585,40 @@ describe('model: update:', function() { }); }); + it('update with Decimal type (gh-5361)', function(done) { + var schema = new mongoose.Schema({ + name: String, + pricing: [{ + _id: false, + program: String, + money: mongoose.Schema.Types.Decimal + }] + }); + + var Person = db.model('Person', schema); + + var data = { + name: 'Jack', + pricing: [ + { program: 'A', money: mongoose.Types.Decimal128.fromString('1.2') }, + { program: 'B', money: mongoose.Types.Decimal128.fromString('3.4') } + ] + }; + + Person.create(data). + then(function(data) { + var newData = { + name: 'Jack', + pricing: [ + { program: 'A', money: mongoose.Types.Decimal128.fromString('5.6') }, + { program: 'B', money: mongoose.Types.Decimal128.fromString('7.8') } + ] + }; + return Person.update({ name: 'Jack' }, newData); + }). + then(() => done(), done); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From c1990ac300d88a4eb6ee6aac9f8261c349469d08 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 19:55:35 -0600 Subject: [PATCH 1635/2240] style: fix lint --- test/model.update.test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 2c5ec61895e..425018e184d 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2589,9 +2589,9 @@ describe('model: update:', function() { var schema = new mongoose.Schema({ name: String, pricing: [{ - _id: false, - program: String, - money: mongoose.Schema.Types.Decimal + _id: false, + program: String, + money: mongoose.Schema.Types.Decimal }] }); @@ -2600,13 +2600,13 @@ describe('model: update:', function() { var data = { name: 'Jack', pricing: [ - { program: 'A', money: mongoose.Types.Decimal128.fromString('1.2') }, - { program: 'B', money: mongoose.Types.Decimal128.fromString('3.4') } + { program: 'A', money: mongoose.Types.Decimal128.fromString('1.2') }, + { program: 'B', money: mongoose.Types.Decimal128.fromString('3.4') } ] }; Person.create(data). - then(function(data) { + then(function() { var newData = { name: 'Jack', pricing: [ @@ -2616,7 +2616,7 @@ describe('model: update:', function() { }; return Person.update({ name: 'Jack' }, newData); }). - then(() => done(), done); + then(function() { done(); }, done); }); it('single embedded schema under document array (gh-4519)', function(done) { From ad909d8277399b63c24bad0dd97f91e58e9c75e8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 20:03:50 -0600 Subject: [PATCH 1636/2240] test: fix tests --- test/model.update.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 425018e184d..32b71084e95 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2595,7 +2595,7 @@ describe('model: update:', function() { }] }); - var Person = db.model('Person', schema); + var Person = db.model('gh5361', schema); var data = { name: 'Jack', From 6c0acaabcaf4223b27b05b34a9c178ed39a84c92 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 20:12:50 -0600 Subject: [PATCH 1637/2240] test: only run decimal update test on 3.4 or higher --- test/model.update.test.js | 70 ++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 32b71084e95..997bb60520f 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2586,37 +2586,53 @@ describe('model: update:', function() { }); it('update with Decimal type (gh-5361)', function(done) { - var schema = new mongoose.Schema({ - name: String, - pricing: [{ - _id: false, - program: String, - money: mongoose.Schema.Types.Decimal - }] + start.mongodVersion(function(err, version) { + if (err) { + done(err); + return; + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + done(); + return; + } + + test(); }); - var Person = db.model('gh5361', schema); + function test() { + var schema = new mongoose.Schema({ + name: String, + pricing: [{ + _id: false, + program: String, + money: mongoose.Schema.Types.Decimal + }] + }); - var data = { - name: 'Jack', - pricing: [ - { program: 'A', money: mongoose.Types.Decimal128.fromString('1.2') }, - { program: 'B', money: mongoose.Types.Decimal128.fromString('3.4') } - ] - }; + var Person = db.model('gh5361', schema); - Person.create(data). - then(function() { - var newData = { - name: 'Jack', - pricing: [ - { program: 'A', money: mongoose.Types.Decimal128.fromString('5.6') }, - { program: 'B', money: mongoose.Types.Decimal128.fromString('7.8') } - ] - }; - return Person.update({ name: 'Jack' }, newData); - }). - then(function() { done(); }, done); + var data = { + name: 'Jack', + pricing: [ + { program: 'A', money: mongoose.Types.Decimal128.fromString('1.2') }, + { program: 'B', money: mongoose.Types.Decimal128.fromString('3.4') } + ] + }; + + Person.create(data). + then(function() { + var newData = { + name: 'Jack', + pricing: [ + { program: 'A', money: mongoose.Types.Decimal128.fromString('5.6') }, + { program: 'B', money: mongoose.Types.Decimal128.fromString('7.8') } + ] + }; + return Person.update({ name: 'Jack' }, newData); + }). + then(function() { done(); }, done); + } }); it('single embedded schema under document array (gh-4519)', function(done) { From 6fd743a324224b67f488482d94be4e99436fb55f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 20:25:08 -0600 Subject: [PATCH 1638/2240] chore: release 4.10.8 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 71b68712bd0..693d2be699d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.10.8 / 2017-06-21 +=================== + * docs: fix small formatting typo on schematypes #5374 [gianpaj](https://github.com/gianpaj) + * fix(model): allow null as an _id #5370 + * fix(populate): don't throw async uncaught exception if model not found in populate #5364 + * fix: correctly cast decimals in update #5361 + * fix(error): don't use custom getter for ValidationError message #5359 + * fix(query): handle runSettersOnQuery in built-in _id setter #5351 + * fix(document): ensure consistent context for nested doc custom validators #5347 + 4.10.7 / 2017-06-18 =================== * docs(validation): show overriding custom validator error with 2nd cb arg #5358 diff --git a/package.json b/package.json index 2edfdc6a8be..a13f651cea0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.8-pre", + "version": "4.10.8", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 5356ee31d7c271ffdf710fa600b45e722bfd23b0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 21 Jun 2017 20:26:20 -0600 Subject: [PATCH 1639/2240] chore: now working on 4.10.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a13f651cea0..c662fd4008c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.10.8", + "version": "4.10.9-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 2aad9faaf982a4b43be5b44339683acdb9abcda0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 22 Jun 2017 09:55:13 -0600 Subject: [PATCH 1640/2240] chore: rename useMongooseUri -> useMongoClient --- docs/connections.jade | 6 +++--- lib/connection.js | 8 ++++---- lib/index.js | 10 +++++----- test/connection.test.js | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index ce98abe15b6..3fee1d0e4e5 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -196,14 +196,14 @@ block content h3#use-mongoose-uri :markdown Mongoose's default connection logic is deprecated as of 4.11.0. Please opt - in to the new connection logic using the `useMongooseUri` option, but + in to the new connection logic using the `useMongoClient` option, but make sure you test your connections first if you're upgrading an existing codebase! :js // Using `mongoose.connect`... - var promise = mongoose.connect('mongodb://localhost/myapp', { useMongooseUri: true, /* other options */ }); + var promise = mongoose.connect('mongodb://localhost/myapp', { useMongoClient: true, /* other options */ }); // Or `createConnection` - var promise = mongoose.createConnection('mongodb://localhost/myapp', { useMongooseUri: true, /* other options */ }); + var promise = mongoose.createConnection('mongodb://localhost/myapp', { useMongoClient: true, /* other options */ }); // Or, if you already have a connection connection.openUri('mongodb://localhost/myapp', { /* options */ }); :markdown diff --git a/lib/connection.js b/lib/connection.js index 901e29d47cd..e05e280ea7f 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -339,7 +339,7 @@ Connection.prototype.open = util.deprecate(function() { }; return promise; -}, '`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongooseUri` option if using `connect()` or `createConnection()`'); +}, '`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`'); /*! * ignore @@ -600,7 +600,7 @@ Connection.prototype.openSet = util.deprecate(function(uris, database, options, }; return promise; -}, '`openSet()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongooseUri` option if using `connect()` or `createConnection()`'); +}, '`openSet()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`'); /** * error @@ -717,9 +717,9 @@ Connection.prototype.openUri = function(uri, options, callback) { var Promise = PromiseProvider.get(); var _this = this; - if (options && options.useMongooseUri) { + if (options && options.useMongoClient) { options = utils.clone(options, { retainKeyOrder: true }); - delete options.useMongooseUri; + delete options.useMongoClient; } return new Promise.ES6(function(resolve, reject) { diff --git a/lib/index.js b/lib/index.js index 1058d3af3ae..9d9b8fe73fa 100644 --- a/lib/index.js +++ b/lib/index.js @@ -185,10 +185,10 @@ var checkReplicaSetInUri = function(uri) { * @param {Object} [options] options to pass to the driver * @param {Object} [options.config] mongoose-specific options * @param {Boolean} [options.config.autoIndex] set to false to disable automatic index creation for all models associated with this connection. - * @param {Boolean} [options.useMongooseUri] false by default, set to true to use new mongoose connection logic + * @param {Boolean} [options.useMongoClient] false by default, set to true to use new mongoose connection logic * @see Connection#open #connection_Connection-open * @see Connection#openSet #connection_Connection-openSet - * @return {Connection|Promise} the created Connection object, or promise that resolves to the connection if `useMongooseUri` option specified. + * @return {Connection|Promise} the created Connection object, or promise that resolves to the connection if `useMongoClient` option specified. * @api public */ @@ -198,7 +198,7 @@ Mongoose.prototype.createConnection = function(uri, options) { var rsOption = options && (options.replset || options.replSet); - if (options && options.useMongooseUri) { + if (options && options.useMongoClient) { return conn.openUri(uri, options); } @@ -250,7 +250,7 @@ Mongoose.prototype.createConnection.$hasSideEffects = true; * * @param {String} uri(s) * @param {Object} [options] - * @param {Boolean} [options.useMongooseUri] false by default, set to true to use new mongoose connection logic + * @param {Boolean} [options.useMongoClient] false by default, set to true to use new mongoose connection logic * @param {Function} [callback] * @see Mongoose#createConnection #index_Mongoose-createConnection * @api public @@ -262,7 +262,7 @@ Mongoose.prototype.connect = function() { if ((arguments.length === 2 || arguments.length === 3) && typeof arguments[0] === 'string' && typeof arguments[1] === 'object' && - arguments[1].useMongooseUri === true) { + arguments[1].useMongoClient === true) { return conn.openUri(arguments[0], arguments[1], arguments[2]); } if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) { diff --git a/test/connection.test.js b/test/connection.test.js index 267261df71d..2c45beb2388 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -14,9 +14,9 @@ var muri = require('muri'); */ describe('connections:', function() { - describe('useMongooseUri/openUri (gh-5304)', function() { + describe('useMongoClient/openUri (gh-5304)', function() { it('with mongoose.connect()', function(done) { - var promise = mongoose.connect('mongodb://localhost:27017/mongoosetest', { useMongooseUri: true }); + var promise = mongoose.connect('mongodb://localhost:27017/mongoosetest', { useMongoClient: true }); assert.equal(promise.constructor.name, 'Promise'); promise.then(function(conn) { @@ -27,7 +27,7 @@ describe('connections:', function() { }); it('with mongoose.createConnection()', function(done) { - var promise = mongoose.createConnection('mongodb://localhost:27017/mongoosetest', { useMongooseUri: true }); + var promise = mongoose.createConnection('mongodb://localhost:27017/mongoosetest', { useMongoClient: true }); assert.equal(promise.constructor.name, 'Promise'); promise.then(function(conn) { From 84d102a2ee6421db34bf84d08437bbd86f433352 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 22 Jun 2017 09:57:10 -0600 Subject: [PATCH 1641/2240] test: fix tests --- lib/cursor/QueryCursor.js | 2 +- lib/schema/objectid.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/cursor/QueryCursor.js b/lib/cursor/QueryCursor.js index 2976d79015b..7af480aeb2f 100644 --- a/lib/cursor/QueryCursor.js +++ b/lib/cursor/QueryCursor.js @@ -4,7 +4,7 @@ var PromiseProvider = require('../promise_provider'); var Readable = require('stream').Readable; -var eachAsync = require('./services/cursor/eachAsync'); +var eachAsync = require('../services/cursor/eachAsync'); var helpers = require('../queryhelpers'); var util = require('util'); diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index ddb8f83738b..6f7017a9c86 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -204,7 +204,6 @@ function resetId(v) { var _v = new oid; this.$__._id = _v; return _v; - return _v; } if (this instanceof Document) { From 85e7984d758c1acdf9a444524531244161fbdf85 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 24 Jun 2017 10:33:27 +0900 Subject: [PATCH 1642/2240] style: fix lint --- lib/schema/objectid.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index ddb8f83738b..6f7017a9c86 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -204,7 +204,6 @@ function resetId(v) { var _v = new oid; this.$__._id = _v; return _v; - return _v; } if (this instanceof Document) { From e390a9a8543418da4d15426fb7bb82cbbc65c8ee Mon Sep 17 00:00:00 2001 From: Peter Johnston Date: Fri, 23 Jun 2017 19:37:35 -0600 Subject: [PATCH 1643/2240] Small typo in lib/schema.js shema -> schema --- lib/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index dcf56003cbd..31a35e5b55c 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1083,7 +1083,7 @@ Schema.prototype.pre = function() { * console.log('this fired after a document was saved'); * }); * - * shema.post('find', function(docs) { + * schema.post('find', function(docs) { * console.log('this fired after you run a find query'); * }); * From bd0f95778746a4c29db91fbaeb54d090fa2d751b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 24 Jun 2017 10:43:11 +0900 Subject: [PATCH 1644/2240] test: fix tests --- lib/schema/objectid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index 6f7017a9c86..2f908023686 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -207,7 +207,7 @@ function resetId(v) { } if (this instanceof Document) { - delete this.$__._id; + this.$__._id = v; } return v; } From 664a6315e96c753ddc1305145d5fe21dce2ff07c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 25 Jun 2017 16:31:29 +0900 Subject: [PATCH 1645/2240] test: fix query stream test --- test/model.stream.test.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/model.stream.test.js b/test/model.stream.test.js index 6f70f58f7cd..1759b63121d 100644 --- a/test/model.stream.test.js +++ b/test/model.stream.test.js @@ -14,18 +14,19 @@ var start = require('./common'), var names = ('Aaden Aaron Adrian Aditya Agustin Jim Bob Jonah Frank Sally Lucy').split(' '); describe('query stream:', function() { - var db = start(); + var db; var Person; var collection = 'personforstream_' + random(); var P; before(function() { + db = start(); + Person = new Schema({ name: String }); - mongoose.model('PersonForStream', Person); - P = db.model('PersonForStream', collection); + P = db.model('PersonForStream', Person, collection); }); before(function(done) { From 5e855ea16ddb965704e4126bd64278b5a8a3506c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 25 Jun 2017 16:35:58 +0900 Subject: [PATCH 1646/2240] test: remove bad test --- test/model.stream.test.js | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/test/model.stream.test.js b/test/model.stream.test.js index 1759b63121d..5058a69eb91 100644 --- a/test/model.stream.test.js +++ b/test/model.stream.test.js @@ -169,45 +169,6 @@ describe('query stream:', function() { stream.on('error', cb); }); - it('errors', function(done) { - this.slow(300); - - var db = start({server: {auto_reconnect: false}}); - var P = db.model('PersonForStream', collection); - - var finished = 0; - var closed = 0; - var i = 0; - - var stream = P.find().batchSize(5).stream(); - - function cb(err) { - ++finished; - setTimeout(function() { - assert.ok(/destroyed/.test(err.message), err.message); - assert.equal(i, 5); - assert.equal(closed, 1); - assert.equal(finished, 1); - assert.equal(stream._destroyed, true); - assert.equal(stream.readable, false); - assert.equal(stream._cursor.isClosed(), true); - done(); - }, 100); - } - - stream.on('data', function() { - if (++i === 5) { - db.close(); - } - }); - - stream.on('close', function() { - closed++; - }); - - stream.on('error', cb); - }); - it('pipe', function(done) { var filename = '/tmp/_mongoose_stream_out.txt'; var out = fs.createWriteStream(filename); From c703010f2b42f7a124e64889111f8e767081f089 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 25 Jun 2017 18:38:56 +0900 Subject: [PATCH 1647/2240] chore: release 4.11.0 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 693d2be699d..fb9cb26f5e2 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,14 @@ +4.11.0 / 2017-06-25 +=================== + * feat(query): execute setters with query as context for `runSettersOnQuery` #5339 + * feat(model): add translateAliases function #5338 [rocketspacer](https://github.com/rocketspacer) + * feat(connection): add `useMongoClient` and `openUri` functions, deprecate current connect logic #5304 + * refactor(schema): make id virtual not access doc internals #5279 + * refactor: handle non-boolean lean #5279 + * feat(cursor): add addCursorFlag() support to query and agg cursors #4814 + * feat(cursor): add parallel option to eachAsync #4244 + * feat(schema): allow setting custom error constructor for custom validators #4009 + 4.10.8 / 2017-06-21 =================== * docs: fix small formatting typo on schematypes #5374 [gianpaj](https://github.com/gianpaj) diff --git a/package.json b/package.json index 1fe2a6b14e0..f1ac29f8902 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.0-pre", + "version": "4.11.0", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 3b44137278718654df65e2d2a5557ae0f0be1afa Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 25 Jun 2017 18:49:34 +0900 Subject: [PATCH 1648/2240] chore: now working on 4.11.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f1ac29f8902..fd2fc42fd5f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.0", + "version": "4.11.1-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 8cffe83e3e8fb5438928b94f0c1f64d014a5b24f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 26 Jun 2017 21:02:07 +0900 Subject: [PATCH 1649/2240] chore: dont rely on global.toString() Re: #5386 Re: mongodb/node-mongodb-native#1494 --- lib/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils.js b/lib/utils.js index fdb848d2091..18b7ae18174 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -502,7 +502,7 @@ exports.isObject = function(arg) { if (Buffer.isBuffer(arg)) { return true; } - return toString.call(arg) === '[object Object]'; + return Object.prototype.toString.call(arg) === '[object Object]'; }; /*! From 1692973ae261b708ea934779829e93e1a8568a7e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Jun 2017 10:16:33 +0900 Subject: [PATCH 1650/2240] test(document): repro #5388 --- test/document.test.js | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 26220f43543..7a84d1bb9e2 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4291,6 +4291,44 @@ describe('document', function() { }); }); + it('single nested subdoc post remove hooks (gh-5388)', function(done) { + var contentSchema = new Schema({ + blocks: [{ type: String }], + summary: { type: String } + }); + + var called = 0; + + contentSchema.post('remove', function() { + ++called; + }); + + var noteSchema = new Schema({ + body: { type: contentSchema } + }); + + var Note = db.model('gh5388', noteSchema); + + var note = new Note({ + title: 'Lorem Ipsum Dolor', + body: { + summary: 'Summary Test', + blocks: ['html'] + } + }); + + note.save(function(error) { + assert.ifError(error); + note.remove(function(error) { + assert.ifError(error); + setTimeout(function() { + assert.equal(called, 1); + done(); + }, 50); + }); + }); + }); + it('consistent context for nested docs (gh-5347)', function(done) { var contexts = []; var childSchema = new mongoose.Schema({ From 428b339c606a822c636d9cbe5b3a0af7d73af5aa Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Jun 2017 10:16:35 +0900 Subject: [PATCH 1651/2240] fix: emit remove on single nested subdocs when removing parent Fix #5388 --- lib/schema.js | 2 +- lib/types/subdocument.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 62543668cbc..ca137ff9050 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -218,7 +218,7 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { var subdocs = this.$__getAllSubdocs(); - if (!subdocs.length || this.$__preSavingFromParent) { + if (!subdocs.length) { done(); next(); return; diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index c214825300d..9eda328e48f 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -132,10 +132,11 @@ Subdocument.prototype.remove = function(options, callback) { options = null; } + registerRemoveListener(this); + // If removing entire doc, no need to remove subdoc if (!options || !options.noop) { this.$parent.set(this.$basePath, null); - registerRemoveListener(this); } if (typeof callback === 'function') { From e74cd5b03aad6fbf45533ebe521e22f7f4ae4938 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Jun 2017 10:22:38 +0900 Subject: [PATCH 1652/2240] style: fix lint --- lib/utils.js | 6 ------ test/document.test.js | 16 ++++++++-------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 18b7ae18174..71b79fde719 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -440,12 +440,6 @@ exports.merge = function merge(to, from, options) { } }; -/*! - * toString helper - */ - -var toString = Object.prototype.toString; - /*! * Applies toObject recursively. * diff --git a/test/document.test.js b/test/document.test.js index 7a84d1bb9e2..aa5cabcb5c8 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4293,8 +4293,8 @@ describe('document', function() { it('single nested subdoc post remove hooks (gh-5388)', function(done) { var contentSchema = new Schema({ - blocks: [{ type: String }], - summary: { type: String } + blocks: [{ type: String }], + summary: { type: String } }); var called = 0; @@ -4304,17 +4304,17 @@ describe('document', function() { }); var noteSchema = new Schema({ - body: { type: contentSchema } + body: { type: contentSchema } }); var Note = db.model('gh5388', noteSchema); var note = new Note({ - title: 'Lorem Ipsum Dolor', - body: { - summary: 'Summary Test', - blocks: ['html'] - } + title: 'Lorem Ipsum Dolor', + body: { + summary: 'Summary Test', + blocks: ['html'] + } }); note.save(function(error) { From 0860b2b3bfefe5dff12140ee6f597c4802e474de Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Jun 2017 19:09:47 +0900 Subject: [PATCH 1653/2240] test(query): repro #5350 --- test/model.query.casting.test.js | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index ccd1484e3b5..4111f1ec83b 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -1063,6 +1063,40 @@ describe('model query casting', function() { catch(done); }); + it('runSettersOnQuery as query option (gh-5350)', function(done) { + var db = start(); + + var contexts = []; + + var testSchema = new Schema({ + name: { type: String, lowercase: true }, + num: { + type: Number, + set: function(v) { + contexts.push(this); + return Math.floor(v); + } + } + }, { runSettersOnQuery: false }); + + var Test = db.model('gh5350', testSchema); + Test.create({ name: 'val', num: 2.02 }). + then(function() { + assert.equal(contexts.length, 1); + assert.equal(contexts[0].constructor.name, 'model'); + return Test.findOne({ name: 'VAL' }, { _id: 0 }, { + runSettersOnQuery: true + }); + }). + then(function(doc) { + assert.ok(doc); + assert.equal(doc.name, 'val'); + assert.equal(doc.num, 2); + }). + then(function() { done(); }). + catch(done); + }); + it('_id = 0 (gh-4610)', function(done) { var db = start(); From 4965da3ceb21c04e065cd5960ee06add2dec5c61 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Jun 2017 19:09:51 +0900 Subject: [PATCH 1654/2240] fix(query): support runSettersOnQuery as query option Fix #5350 --- lib/schematype.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/schematype.js b/lib/schematype.js index 7ff788ab83f..7acf1c6c85c 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -1042,7 +1042,16 @@ SchemaType.prototype.castForQuery = function($conditional, val) { */ SchemaType.prototype._castForQuery = function(val) { - if (this.options && this.options.runSettersOnQuery) { + var runSettersOnQuery = false; + if (this.$$context && + this.$$context.options && + 'runSettersOnQuery' in this.$$context.options) { + runSettersOnQuery = this.$$context.options.runSettersOnQuery; + } else if (this.options && 'runSettersOnQuery' in this.options) { + runSettersOnQuery = this.options.runSettersOnQuery; + } + + if (runSettersOnQuery) { return this.applySetters(val, this.$$context); } return this.cast(val); From ceb8d38866c26ffd57159b4b1f32f9c67dad37dd Mon Sep 17 00:00:00 2001 From: Zach Bjornson Date: Fri, 23 Jun 2017 18:14:16 -0700 Subject: [PATCH 1655/2240] bug(query): justOne is actually single, and it default to false Fixes #5396 --- lib/model.js | 46 ++++++++++++++++++++++++---------------------- lib/query.js | 4 ++-- test/query.test.js | 42 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/lib/model.js b/lib/model.js index 207e471cd83..00a0f6a737c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1058,22 +1058,22 @@ Model.base; Model.discriminators; /** - * Translate any aliases fields/conditions so the final query or document object is pure - * - * ####Example: - * - * Character - * .find(Character.translateAliases({ - * '名': 'Eddard Stark' // Alias for 'name' - * }) - * .exec(function(err, characters) {}) - * - * ####Note: - * Only translate arguments of object type anything else is returned raw - * - * @param {Object} raw fields/conditions that may contain aliased keys - * @return {Object} the translated 'pure' fields/conditions - */ + * Translate any aliases fields/conditions so the final query or document object is pure + * + * ####Example: + * + * Character + * .find(Character.translateAliases({ + * '名': 'Eddard Stark' // Alias for 'name' + * }) + * .exec(function(err, characters) {}) + * + * ####Note: + * Only translate arguments of object type anything else is returned raw + * + * @param {Object} raw fields/conditions that may contain aliased keys + * @return {Object} the translated 'pure' fields/conditions + */ Model.translateAliases = function translateAliases(fields) { var aliases = this.schema.aliases; @@ -1094,9 +1094,9 @@ Model.translateAliases = function translateAliases(fields) { }; /** - * Removes the first document that matches `conditions` from the collection. - * To remove all documents that match `conditions`, set the `justOne` option - * to false. + * Removes all documents that match `conditions` from the collection. + * To remove just the first document that matches `conditions`, set the `single` + * option to true. * * ####Example: * @@ -1104,7 +1104,9 @@ Model.translateAliases = function translateAliases(fields) { * * ####Note: * - * This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, _no middleware (hooks) are executed_. + * This method sends a remove command directly to MongoDB, no Mongoose documents + * are involved. Because no Mongoose documents are involved, _no middleware + * (hooks) are executed_. * * @param {Object} conditions * @param {Function} [callback] @@ -1131,7 +1133,7 @@ Model.remove = function remove(conditions, callback) { /** * Deletes the first document that matches `conditions` from the collection. * Behaves like `remove()`, but deletes at most one document regardless of the - * `justOne` option. + * `single` option. * * ####Example: * @@ -1166,7 +1168,7 @@ Model.deleteOne = function deleteOne(conditions, callback) { /** * Deletes all of the documents that match `conditions` from the collection. * Behaves like `remove()`, but deletes all documents that match `conditions` - * regardless of the `justOne` option. + * regardless of the `single` option. * * ####Example: * diff --git a/lib/query.js b/lib/query.js index de985ee93e0..9a4c24683b9 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1641,7 +1641,7 @@ Query.prototype._remove = function(callback) { /** * Declare and/or execute this query as a `deleteOne()` operation. Works like - * remove, except it deletes at most one document regardless of the `justOne` + * remove, except it deletes at most one document regardless of the `single` * option. * * ####Example @@ -1697,7 +1697,7 @@ Query.prototype._deleteOne = function(callback) { /** * Declare and/or execute this query as a `deleteMany()` operation. Works like * remove, except it deletes _every_ document that matches `criteria` in the - * collection, regardless of the value of `justOne`. + * collection, regardless of the value of `single`. * * ####Example * diff --git a/test/query.test.js b/test/query.test.js index 552317d7af3..27f12c74f81 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1188,13 +1188,13 @@ describe('Query', function() { }, done).end(); }); - it('justOne option', function(done) { + it('single option, default', function(done) { var db = start(); - var Test = db.model('Test_justOne', new Schema({ name: String })); + var Test = db.model('Test_single', new Schema({ name: String })); Test.create([{ name: 'Eddard Stark' }, { name: 'Robb Stark' }], function(error) { assert.ifError(error); - Test.remove({ name: /Stark/ }).setOptions({ justOne: false }).exec(function(error, res) { + Test.remove({ name: /Stark/ }).exec(function(error, res) { assert.ifError(error); assert.equal(res.result.n, 2); Test.count({}, function(error, count) { @@ -1205,6 +1205,42 @@ describe('Query', function() { }); }); }); + + it('single option, false', function(done) { + var db = start(); + var Test = db.model('Test_single', new Schema({ name: String })); + + Test.create([{ name: 'Eddard Stark' }, { name: 'Robb Stark' }], function(error) { + assert.ifError(error); + Test.remove({ name: /Stark/ }).setOptions({ single: false }).exec(function(error, res) { + assert.ifError(error); + assert.equal(res.result.n, 2); + Test.count({}, function(error, count) { + assert.ifError(error); + assert.equal(count, 0); + done(); + }); + }); + }); + }); + + it('single option, true', function(done) { + var db = start(); + var Test = db.model('Test_single', new Schema({ name: String })); + + Test.create([{ name: 'Eddard Stark' }, { name: 'Robb Stark' }], function(error) { + assert.ifError(error); + Test.remove({ name: /Stark/ }).setOptions({ single: true }).exec(function(error, res) { + assert.ifError(error); + assert.equal(res.result.n, 1); + Test.count({}, function(error, count) { + assert.ifError(error); + assert.equal(count, 1); + done(); + }); + }); + }); + }); }); describe('querying/updating with model instance containing embedded docs should work (#454)', function() { From 85153586d1992cc3a7001d3a248653a4ff9d2fef Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Jun 2017 20:00:08 -0700 Subject: [PATCH 1656/2240] test(document): repro #5363 --- test/document.test.js | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index aa5cabcb5c8..3bbbdd2f2ff 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4291,6 +4291,54 @@ describe('document', function() { }); }); + it('consistent setter context for single nested (gh-5363)', function(done) { + var contentSchema = new Schema({ + blocks: [{ type: String }], + summary: { type: String } + }); + + // Subdocument setter + var contexts = []; + contentSchema.path('blocks').set(function(srcBlocks) { + if (!this.ownerDocument().isNew) { + contexts.push(this.toObject()); + } + + return srcBlocks; + }); + + var noteSchema = new Schema({ + title: { type: String, required: true }, + body: { type: contentSchema } + }); + + var Note = db.model('gh5363', noteSchema); + + var note = new Note({ + title: 'Lorem Ipsum Dolor', + body: { + summary: 'Summary Test', + blocks: ['html'] + } + }); + + note.save(). + then(function(note) { + assert.equal(contexts.length, 0); + note.set('body', { + summary: 'New Summary', + blocks: ['gallery', 'html'] + }); + return note.save(); + }). + then(function() { + assert.equal(contexts.length, 1); + assert.deepEqual(contexts[0].blocks, ['html']); + done(); + }). + catch(done); + }); + it('single nested subdoc post remove hooks (gh-5388)', function(done) { var contentSchema = new Schema({ blocks: [{ type: String }], From 933c0c7a2ed8dbb636fb723328371771e41f112c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Jun 2017 20:00:12 -0700 Subject: [PATCH 1657/2240] fix(document): ensure consistent setter context for single nested Fix #5363 --- lib/schema/embedded.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 8f9c78502be..a0804f05409 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -121,14 +121,18 @@ Embedded.prototype.$conditionalHandlers.$exists = $exists; * @api private */ -Embedded.prototype.cast = function(val, doc, init) { +Embedded.prototype.cast = function(val, doc, init, priorVal) { if (val && val.$isSingleNested) { return val; } - var subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); + var subdoc; if (init) { + subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); subdoc.init(val); } else { + subdoc = priorVal && priorVal.$isSingleNested ? + priorVal : + new this.caster(priorVal, doc ? doc.$__.selected : void 0, doc); subdoc.set(val, undefined, true); } return subdoc; From d426023f1e7406867d52eaafd023fcd89fd69c5e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 30 Jun 2017 23:22:43 -0700 Subject: [PATCH 1658/2240] test: fix tests --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 38fccc6fede..b78c7963528 100644 --- a/lib/document.js +++ b/lib/document.js @@ -701,7 +701,7 @@ Document.prototype.set = function(path, val, type, options) { // if this doc is being constructed we should not trigger getters var priorVal = constructing ? undefined - : this.getValue(path); + : utils.clone(this.getValue(path)); if (!schema) { this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal); From 36123fdfaa62cbcc234bd66d4b00d37454f71d60 Mon Sep 17 00:00:00 2001 From: Frederico Silva Date: Sat, 1 Jul 2017 09:39:07 +0200 Subject: [PATCH 1659/2240] docs: populate virtuals fix justOne description --- docs/populate.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/populate.jade b/docs/populate.jade index e1831466374..1ec75f71db1 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -344,7 +344,7 @@ block content ref: 'Person', // The model to use localField: 'name', // Find people where `localField` foreignField: 'band', // is equal to `foreignField` - // If `justOne` is false, 'members' will be a single doc as opposed to + // If `justOne` is true, 'members' will be a single doc as opposed to // an array. `justOne` is false by default. justOne: false }); From 0a1094a87671da7851f5ce2bb33ec21409b148ac Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Jul 2017 18:22:46 -0600 Subject: [PATCH 1660/2240] test: fix tests --- lib/document.js | 6 +++--- lib/schema/embedded.js | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/document.js b/lib/document.js index b78c7963528..b936d912783 100644 --- a/lib/document.js +++ b/lib/document.js @@ -699,9 +699,9 @@ Document.prototype.set = function(path, val, type, options) { } // if this doc is being constructed we should not trigger getters - var priorVal = constructing - ? undefined - : utils.clone(this.getValue(path)); + var priorVal = constructing ? + undefined : + this.getValue(path); if (!schema) { this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal); diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index a0804f05409..525d64bb17e 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -125,16 +125,19 @@ Embedded.prototype.cast = function(val, doc, init, priorVal) { if (val && val.$isSingleNested) { return val; } + var subdoc; if (init) { subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); subdoc.init(val); } else { subdoc = priorVal && priorVal.$isSingleNested ? - priorVal : - new this.caster(priorVal, doc ? doc.$__.selected : void 0, doc); - subdoc.set(val, undefined, true); + new this.caster(priorVal.toObject(), doc ? doc.$__.selected : void 0, doc) : + new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); + + subdoc.set(val, undefined, false); } + return subdoc; }; From a66f618a3369b2aea52f2362409a4553fc37931d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Jul 2017 20:20:11 -0600 Subject: [PATCH 1661/2240] test(populate): repro #5377 --- test/model.populate.test.js | 68 +++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index ae06e9cf371..23900f73751 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3050,6 +3050,74 @@ describe('model: populate:', function() { catch(done); }); + it('array with empty refPath (gh-5377)', function(done) { + var modelASchema = new mongoose.Schema({ + name: String + }); + var ModelA = db.model('gh5377_a', modelASchema); + + var modelBSchema = new mongoose.Schema({ + name: String + }); + var ModelB = db.model('gh5377_b', modelBSchema); + + var ChildSchema = new mongoose.Schema({ + name: String, + toy: { + kind: { + type: String, + enum: ['gh5377_a', 'gh5377_b'] + }, + value: { + type: ObjectId, + refPath: 'children.toy.kind' + } + } + }); + + var ParentSchema = new mongoose.Schema({ + children: [ChildSchema] + }); + var Parent = db.model('gh5377', ParentSchema); + + ModelA.create({ name: 'model-A' }, function(error, toyA) { + assert.ifError(error); + ModelB.create({ name: 'model-B' }, function(error, toyB) { + assert.ifError(error); + Parent.create({ + children: [ + { + name: 'Child 1', + toy: { kind: 'gh5377_a', value: toyA._id } + }, + { + name: 'Child 2' + }, + { + name: 'Child 3', + toy: { kind: 'gh5377_b', value: toyB._id } + } + ] + }, function(error, doc) { + assert.ifError(error); + test(doc._id); + }); + }); + }); + + function test(id) { + Parent.findById(id, function(error, doc) { + assert.ifError(error); + doc.populate('children.toy.value').execPopulate().then(function(doc) { + assert.equal(doc.children[0].toy.value.name, 'model-A'); + assert.equal(doc.children[1].toy.value, null); + assert.equal(doc.children[2].toy.value.name, 'model-B'); + done(); + }).catch(done); + }); + } + }); + it('with non-arrays (gh-5114)', function(done) { var LocationSchema = new Schema({ name: String From 528f125aa37de0afe62c01efcc9967c730170e09 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Jul 2017 20:20:15 -0600 Subject: [PATCH 1662/2240] fix(populate): handle undefined refPath values in middle of array Fix #5377 --- lib/model.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/model.js b/lib/model.js index 207e471cd83..ba85ae551b0 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3360,11 +3360,6 @@ function getModelsMapForPopulate(model, docs, options) { if (refPath) { modelNames = utils.getValue(refPath, doc); isRefPathArray = Array.isArray(modelNames); - if (isRefPathArray) { - modelNames = modelNames.filter(function(v) { - return v != null; - }); - } } else { if (!modelNameFromQuery) { var modelForCurrentDoc = model; @@ -3442,6 +3437,9 @@ function getModelsMapForPopulate(model, docs, options) { var k = modelNames.length; while (k--) { modelName = modelNames[k]; + if (modelName == null) { + continue; + } var _doc = Array.isArray(doc) && isRefPathArray ? doc[k] : doc; var _ret = Array.isArray(ret) && isRefPathArray ? ret[k] : ret; try { From 81714c292bb62440f59d93089024e93550cf4f66 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 1 Jul 2017 20:31:35 -0600 Subject: [PATCH 1663/2240] style: fix lint --- test/model.populate.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 23900f73751..157caa52cea 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3090,9 +3090,9 @@ describe('model: populate:', function() { name: 'Child 1', toy: { kind: 'gh5377_a', value: toyA._id } }, - { - name: 'Child 2' - }, + { + name: 'Child 2' + }, { name: 'Child 3', toy: { kind: 'gh5377_b', value: toyB._id } From c868ee707c059e8af467c3f54e7864b0c3aa50c8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Jul 2017 00:25:28 -0600 Subject: [PATCH 1664/2240] test(update): repro #5086 --- test/model.update.test.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 997bb60520f..4d7668b0dc9 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2559,6 +2559,30 @@ describe('model: update:', function() { catch(done); }); + it('defaults with overwrite and no update validators (gh-5384)', function(done) { + var testSchema = new mongoose.Schema({ + name: String, + something: { type: Number, default: 2 } + }); + + var TestModel = db.model('gh5384', testSchema); + var options = { + overwrite: true, + upsert: true, + setDefaultsOnInsert: true + }; + + var update = { name: 'test' }; + TestModel.update({ name: 'a' }, update, options, function(error) { + assert.ifError(error); + TestModel.findOne({}, function(error, doc) { + assert.ifError(error); + assert.equal(doc.something, 2); + done(); + }); + }); + }); + it('update validators with nested required (gh-5269)', function(done) { var childSchema = new mongoose.Schema({ d1: { From f4551b939382f1ca1f98cbea342aae53edd95504 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Jul 2017 00:28:24 -0600 Subject: [PATCH 1665/2240] fix(update): handle update with defaults and overwrite but no update validators Fix #5384 Re: #4054 --- lib/query.js | 30 ++++++++++++++++++++++++----- lib/services/setDefaultsOnInsert.js | 5 +++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/lib/query.js b/lib/query.js index de985ee93e0..7dc7b754847 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2032,7 +2032,7 @@ Query.prototype._findAndModify = function(type, callback) { var schema = model.schema; var _this = this; var castedQuery; - var castedDoc; + var castedDoc = this._update; var fields; var opts; var doValidate; @@ -2048,6 +2048,11 @@ Query.prototype._findAndModify = function(type, callback) { this._mongooseOptions.strict = opts.strict; } + var isOverwriting = this.options.overwrite && !hasDollarKeys(castedDoc); + if (isOverwriting) { + castedDoc = new this.model(castedDoc, null, true); + } + if (type === 'remove') { opts.remove = true; } else { @@ -2061,8 +2066,7 @@ Query.prototype._findAndModify = function(type, callback) { opts.remove = false; } - if (opts.overwrite && !hasDollarKeys(this._update)) { - castedDoc = new model(this._update, null, true); + if (isOverwriting) { doValidate = function(callback) { castedDoc.validate(callback); }; @@ -2149,6 +2153,9 @@ Query.prototype._findAndModify = function(type, callback) { if (error) { return callback(error); } + if (castedDoc && castedDoc.toBSON) { + castedDoc = castedDoc.toBSON(); + } _this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) { return cb(error, res ? res.value : res, res); })); @@ -2160,6 +2167,9 @@ Query.prototype._findAndModify = function(type, callback) { callback(error); } } else { + if (castedDoc && castedDoc.toBSON) { + castedDoc = castedDoc.toBSON(); + } this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(function(error, res) { return cb(error, res ? res.value : res, res); })); @@ -2246,10 +2256,14 @@ Query.prototype._execUpdate = function(callback) { return this; } + var isOverwriting = this.options.overwrite && !hasDollarKeys(castedDoc); + if (isOverwriting) { + castedDoc = new this.model(castedDoc, null, true); + } + if (this.options.runValidators) { _this = this; - if (this.options.overwrite && !hasDollarKeys(castedDoc)) { - castedDoc = new _this.model(castedDoc, null, true); + if (isOverwriting) { doValidate = function(callback) { castedDoc.validate(callback); }; @@ -2261,6 +2275,9 @@ Query.prototype._execUpdate = function(callback) { return callback(err); } + if (castedDoc.toBSON) { + castedDoc = castedDoc.toBSON(); + } Query.base.update.call(_this, castedQuery, castedDoc, options, callback); }; try { @@ -2273,6 +2290,9 @@ Query.prototype._execUpdate = function(callback) { return this; } + if (castedDoc.toBSON) { + castedDoc = castedDoc.toBSON(); + } Query.base.update.call(this, castedQuery, castedDoc, options, callback); return this; }; diff --git a/lib/services/setDefaultsOnInsert.js b/lib/services/setDefaultsOnInsert.js index 5d9f3c0a119..e0939153cd2 100644 --- a/lib/services/setDefaultsOnInsert.js +++ b/lib/services/setDefaultsOnInsert.js @@ -56,6 +56,11 @@ module.exports = function(query, schema, castedDoc, options) { modified[path] = true; } + if (options && options.overwrite && !hasDollarUpdate) { + // Defaults will be set later + return castedDoc; + } + if (options.setDefaultsOnInsert) { schema.eachPath(function(path, schemaType) { if (path === '_id') { From 586effecb3d6bb0ad1106c92f8f90c65d0e52a2c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Jul 2017 10:20:40 -0600 Subject: [PATCH 1666/2240] docs(connection): improve docs re: createConnection promise Re: #5399 --- docs/connections.jade | 15 ++++++++++++--- test/document.test.js | 4 +++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index 3fee1d0e4e5..b72f5c541a0 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -193,7 +193,7 @@ block content var uri = 'mongodb://localhost/test?poolSize=4'; mongoose.createConnection(uri); - h3#use-mongoose-uri + h3#use-mongo-client :markdown Mongoose's default connection logic is deprecated as of 4.11.0. Please opt in to the new connection logic using the `useMongoClient` option, but @@ -201,9 +201,18 @@ block content codebase! :js // Using `mongoose.connect`... - var promise = mongoose.connect('mongodb://localhost/myapp', { useMongoClient: true, /* other options */ }); + var promise = mongoose.connect('mongodb://localhost/myapp', { + useMongoClient: true, + /* other options */ + }); // Or `createConnection` - var promise = mongoose.createConnection('mongodb://localhost/myapp', { useMongoClient: true, /* other options */ }); + var promise = mongoose.createConnection('mongodb://localhost/myapp', { + useMongoClient: true, + /* other options */ + }); + promise.then(function(db) { + /* Use `db`, for instance `db.model()` + }); // Or, if you already have a connection connection.openUri('mongodb://localhost/myapp', { /* options */ }); :markdown diff --git a/test/document.test.js b/test/document.test.js index 3bbbdd2f2ff..53453211d4e 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -508,7 +508,9 @@ describe('document', function() { describe('toObject', function() { var db; before(function() { - db = start(); + return start({ useMongoClient: true }).then(function(_db) { + db = _db; + }); }); after(function(done) { From b1e991727d91c76915e5c14e71b63a39f4fadf49 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Jul 2017 16:50:42 -0600 Subject: [PATCH 1667/2240] docs(connection): add link to openUri deprecation --- docs/connections.jade | 2 +- lib/connection.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index b72f5c541a0..6698b7b86c0 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -193,7 +193,7 @@ block content var uri = 'mongodb://localhost/test?poolSize=4'; mongoose.createConnection(uri); - h3#use-mongo-client + h3#use-mongo-client The `useMongoClient` Option :markdown Mongoose's default connection logic is deprecated as of 4.11.0. Please opt in to the new connection logic using the `useMongoClient` option, but diff --git a/lib/connection.js b/lib/connection.js index e05e280ea7f..533fda6bfb4 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -339,7 +339,7 @@ Connection.prototype.open = util.deprecate(function() { }; return promise; -}, '`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`'); +}, '`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/connections.html#use-mongo-client'); /*! * ignore @@ -600,7 +600,7 @@ Connection.prototype.openSet = util.deprecate(function(uris, database, options, }; return promise; -}, '`openSet()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`'); +}, '`openSet()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/connections.html#use-mongo-client'); /** * error From 6c025c89954226e8d321068992a0a623331faea9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Jul 2017 16:54:34 -0600 Subject: [PATCH 1668/2240] fix(connection): make sure to call onOpen in openUri() Fix #5404 --- lib/connection.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 533fda6bfb4..5a9a3fb57de 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -734,6 +734,12 @@ Connection.prototype.openUri = function(uri, options, callback) { _this.db = db; _this.readyState = STATES.connected; + for (var i in _this.collections) { + if (utils.object.hasOwnProperty(_this.collections, i)) { + _this.collections[i].onOpen(); + } + } + callback && callback(null, _this); resolve(_this); _this.emit('open'); From ca9c3052ec6ddff4188bb17d5deb0bc9fb49da2a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Jul 2017 17:01:02 -0600 Subject: [PATCH 1669/2240] docs(connection): add links to MongoClient.connect() --- docs/connections.jade | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/connections.jade b/docs/connections.jade index 6698b7b86c0..7ee467774db 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -215,6 +215,11 @@ block content }); // Or, if you already have a connection connection.openUri('mongodb://localhost/myapp', { /* options */ }); + :markdown + The parameters to `openUri()` are passed transparently to the + [underlying MongoDB driver's `MongoClient.connect()` function](http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect). + Please see the [driver documentation for this function](http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect) for options. + The same is true for `connect()` and `createConnection()` if `useMongoClient` is `true`. :markdown This deprecation is because the [MongoDB driver](https://www.npmjs.com/package/mongodb) has deprecated an API that is critical to mongoose's connection logic to From 98af8e830e5879c34cc079d8605199aaa8eef01d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Jul 2017 18:37:44 -0600 Subject: [PATCH 1670/2240] chore: release 4.11.1 --- History.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index fb9cb26f5e2..44c0607334f 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,15 @@ +4.11.1 / 2017-07-02 +=================== +* docs: populate virtuals fix justOne description #5427 [fredericosilva](https://github.com/fredericosilva) + * fix(connection): make sure to call onOpen in openUri() #5404 + * docs(query): justOne is actually single, and it default to false #5402 [zbjornson](https://github.com/zbjornson) + * docs: fix small typo in lib/schema.js #5398 #5396 [pjo336](https://github.com/pjo336) + * fix: emit remove on single nested subdocs when removing parent #5388 + * fix(update): handle update with defaults and overwrite but no update validators #5384 + * fix(populate): handle undefined refPath values in middle of array #5377 + * fix(document): ensure consistent setter context for single nested #5363 + * fix(query): support runSettersOnQuery as query option #5350 + 4.11.0 / 2017-06-25 =================== * feat(query): execute setters with query as context for `runSettersOnQuery` #5339 diff --git a/package.json b/package.json index fd2fc42fd5f..3332f799484 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.1-pre", + "version": "4.11.1", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4fc91312961bd4988bc72dbc00b8c22c6f7467bd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 2 Jul 2017 18:42:44 -0600 Subject: [PATCH 1671/2240] chore: now working on 4.11.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3332f799484..a2320a6acc6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.1", + "version": "4.11.2-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 62cb31c1d919d66f0449943ec5242d85f5f4ad93 Mon Sep 17 00:00:00 2001 From: Connor McFarlane Date: Mon, 3 Jul 2017 16:14:22 +0100 Subject: [PATCH 1672/2240] Fix comment typo in connect example Small fix but why not --- docs/connections.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/connections.jade b/docs/connections.jade index 7ee467774db..3488757f6d2 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -105,7 +105,7 @@ block content // Or using promises mongoose.connect(uri, options).then( () => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ }, - err => { /** handle initial connection error } + err => { /** handle initial connection error */ } ); h4#connection-string-options Connection String Options From 7587148e6818cda82b8b8edcd2059fcf56858344 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 3 Jul 2017 20:40:10 -0600 Subject: [PATCH 1673/2240] test(discriminator): repro #4629 --- test/model.discriminator.querying.test.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js index 246590f090e..793fd99e6d7 100644 --- a/test/model.discriminator.querying.test.js +++ b/test/model.discriminator.querying.test.js @@ -27,16 +27,22 @@ util.inherits(BaseSchema, Schema); var EventSchema = new BaseSchema(); var ImpressionEventSchema = new BaseSchema(); var ConversionEventSchema = new BaseSchema({revenue: Number}); +var SecretEventSchema = new BaseSchema({ secret: { type: String, select: false } }); describe('model', function() { describe('discriminator()', function() { - var db, BaseEvent, ImpressionEvent, ConversionEvent; + var db; + var BaseEvent; + var ImpressionEvent; + var ConversionEvent; + var SecretEvent; before(function() { db = start(); BaseEvent = db.model('model-discriminator-querying-event', EventSchema, 'model-discriminator-querying-' + random()); ImpressionEvent = BaseEvent.discriminator('model-discriminator-querying-impression', ImpressionEventSchema); ConversionEvent = BaseEvent.discriminator('model-discriminator-querying-conversion', ConversionEventSchema); + SecretEvent = BaseEvent.discriminator('model-discriminator-querying-secret', SecretEventSchema); }); afterEach(function(done) { @@ -375,6 +381,19 @@ describe('model', function() { }); describe('findOne', function() { + it('when selecting `select: false` field (gh-4629)', function(done) { + var s = new SecretEvent({ name: 'test', secret: 'test2' }); + s.save(function(error) { + assert.ifError(error); + SecretEvent.findById(s._id, '+secret', function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'test'); + assert.equal(doc.secret, 'test2'); + done(); + }); + }); + }); + it('hydrates correct model', function(done) { var baseEvent = new BaseEvent({name: 'Base event'}); var impressionEvent = new ImpressionEvent({name: 'Impression event'}); From cc3086962e1ebd267cecd5322927144200a73bbe Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 3 Jul 2017 20:40:20 -0600 Subject: [PATCH 1674/2240] fix(discriminator): ensure discriminator key doesn't count as user-selected field for projection Fix #4629 --- lib/model.js | 4 ++-- lib/services/model/discriminator.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index 85056bbf27c..df193084b21 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1260,7 +1260,7 @@ Model.find = function find(conditions, projection, options, callback) { mq.select(projection); mq.setOptions(options); if (this.schema.discriminatorMapping && mq.selectedInclusively()) { - mq.select(this.schema.options.discriminatorKey); + mq.select('+' + this.schema.options.discriminatorKey); } if (callback) { @@ -1391,7 +1391,7 @@ Model.findOne = function findOne(conditions, projection, options, callback) { mq.select(projection); mq.setOptions(options); if (this.schema.discriminatorMapping && mq.selectedInclusively()) { - mq.select(this.schema.options.discriminatorKey); + mq.select('+' + this.schema.options.discriminatorKey); } if (callback) { diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 68f0ba8b7dc..02cb65e1ce4 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -40,6 +40,7 @@ module.exports = function discriminator(model, name, schema) { var obj = {}; obj[key] = { default: name, + select: true, set: function(newName) { if (newName === name) { return name; From cd025d299aee949e198b04850f999986a5ecf7b6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 4 Jul 2017 12:57:03 -0600 Subject: [PATCH 1675/2240] docs: clarify that required validator will fail for empty strings Fix #5383 --- lib/schema/string.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/schema/string.js b/lib/schema/string.js index dfd044ad2f8..b9bf296e88d 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -378,7 +378,10 @@ SchemaString.prototype.match = function match(regExp, message) { }; /** - * Check if the given value satisfies a required validator. + * Check if the given value satisfies the `required` validator. The value is + * considered valid if it is a string (that is, not `null` or `undefined`) and + * has positive length. The `required` validator **will** fail for empty + * strings. * * @param {Any} value * @param {Document} doc From 2134d61a33428d8f19430e05c131cc605e6c4787 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 4 Jul 2017 13:28:08 -0600 Subject: [PATCH 1676/2240] fix(model): actual fix for #4629 --- lib/model.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/model.js b/lib/model.js index df193084b21..641e922999a 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1259,8 +1259,11 @@ Model.find = function find(conditions, projection, options, callback) { var mq = new this.Query({}, {}, this, this.collection); mq.select(projection); mq.setOptions(options); - if (this.schema.discriminatorMapping && mq.selectedInclusively()) { - mq.select('+' + this.schema.options.discriminatorKey); + if (this.schema.discriminatorMapping && + this.schema.discriminatorMapping.isRoot && + mq.selectedInclusively()) { + // Need to select discriminator key because original schema doesn't have it + mq.select(this.schema.options.discriminatorKey); } if (callback) { @@ -1390,8 +1393,10 @@ Model.findOne = function findOne(conditions, projection, options, callback) { var mq = new this.Query({}, {}, this, this.collection); mq.select(projection); mq.setOptions(options); - if (this.schema.discriminatorMapping && mq.selectedInclusively()) { - mq.select('+' + this.schema.options.discriminatorKey); + if (this.schema.discriminatorMapping && + this.schema.discriminatorMapping.isRoot && + mq.selectedInclusively()) { + mq.select(this.schema.options.discriminatorKey); } if (callback) { From 8789978d862602233662d09b5bba554149c48b3b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 4 Jul 2017 17:03:19 -0600 Subject: [PATCH 1677/2240] fix(schematype): clone default objects so default not shared across object instances unless `shared` specified Use the `shared` property if you need this behavior Fix #5407 Re: #1308 --- lib/schematype.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/schematype.js b/lib/schematype.js index 7acf1c6c85c..a1900ee1f93 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -621,6 +621,10 @@ SchemaType.prototype.getDefault = function(scope, init) { : this.defaultValue; if (ret !== null && ret !== undefined) { + if (typeof ret === 'object' && (!this.options || !this.options.shared)) { + ret = utils.clone(ret, { retainKeyOrder: true }); + } + var casted = this.cast(ret, scope, init); if (casted && casted.$isSingleNested) { casted.$parent = scope; From 9537aa05d32f5b804302daaee2919122cd177995 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 4 Jul 2017 17:34:36 -0600 Subject: [PATCH 1678/2240] test(update): repro #5413 --- test/model.update.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 4d7668b0dc9..8fa486f08a2 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2609,6 +2609,25 @@ describe('model: update:', function() { }); }); + it('with setOptions overwrite (gh-5413)', function(done) { + var schema = new mongoose.Schema({ + _id: String, + data: String + }, { timestamps: true }); + + var Model = db.model('gh5413', schema); + + Model. + where({ _id: 'test' }). + setOptions({ overwrite: true, upsert: true }). + update({ data: 'test2' }). + exec(). + then(function() { + done(); + }). + catch(done); + }); + it('update with Decimal type (gh-5361)', function(done) { start.mongodVersion(function(err, version) { if (err) { From 5e6013e3558d62e8b0d426b813e7fdf21a945650 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 4 Jul 2017 17:39:36 -0600 Subject: [PATCH 1679/2240] fix(timestamps): if overwrite is set and there's a $set, use $set instead of top-level update Fix #5413 --- lib/schema.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 52efddb8478..f8e82f2abf4 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -824,12 +824,18 @@ Schema.prototype.setupTimestamp = function(timestamps) { var genUpdates = function(currentUpdate, overwrite) { var now = new Date(); var updates = {}; + var _updates = updates; if (overwrite) { + if (currentUpdate && currentUpdate.$set) { + currentUpdate = currentUpdate.$set; + updates.$set = {}; + _updates = updates.$set; + } if (!currentUpdate[updatedAt]) { - updates[updatedAt] = now; + _updates[updatedAt] = now; } if (!currentUpdate[createdAt]) { - updates[createdAt] = now; + _updates[createdAt] = now; } return updates; } From 7413cdb2b61c2fdf92993b748d5c3ff589926116 Mon Sep 17 00:00:00 2001 From: Murali Ramachari Date: Wed, 5 Jul 2017 10:41:46 -0500 Subject: [PATCH 1680/2240] Load bundled driver first and then override Using expression in require doesn't work while packaging using Webpack --- lib/drivers/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/drivers/index.js b/lib/drivers/index.js index 5a842baea3b..a570a807545 100644 --- a/lib/drivers/index.js +++ b/lib/drivers/index.js @@ -5,7 +5,10 @@ var driver; if (typeof window === 'undefined') { - driver = require(global.MONGOOSE_DRIVER_PATH || './node-mongodb-native'); + driver = require('./node-mongodb-native'); + if (global.MONGOOSE_DRIVER_PATH) { + driver = require(global.MONGOOSE_DRIVER_PATH || './node-mongodb-native'); + } } else { driver = require('./browser'); } From ca22cd8179df3675966d23381e15e177b3c09f7f Mon Sep 17 00:00:00 2001 From: Murali Ramachari Date: Wed, 5 Jul 2017 12:03:29 -0500 Subject: [PATCH 1681/2240] Removing global.MONGOOSE_DRIVER_PATH double check --- lib/drivers/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/drivers/index.js b/lib/drivers/index.js index a570a807545..a6965824978 100644 --- a/lib/drivers/index.js +++ b/lib/drivers/index.js @@ -7,7 +7,7 @@ var driver; if (typeof window === 'undefined') { driver = require('./node-mongodb-native'); if (global.MONGOOSE_DRIVER_PATH) { - driver = require(global.MONGOOSE_DRIVER_PATH || './node-mongodb-native'); + driver = require(global.MONGOOSE_DRIVER_PATH); } } else { driver = require('./browser'); From 1092e04a247230c45d0e4140ff5b5be8eaf2fcbf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 5 Jul 2017 14:32:19 -0600 Subject: [PATCH 1682/2240] chore: bump muri -> 1.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a2320a6acc6..f47aa89d7fe 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "mpromise": "0.5.5", "mquery": "2.3.1", "ms": "2.0.0", - "muri": "1.2.1", + "muri": "1.2.2", "regexp-clone": "0.0.1", "sliced": "1.0.1" }, From 6106c3804a54883a249e6abf9277700a3ed6ee26 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 5 Jul 2017 18:48:36 -0600 Subject: [PATCH 1683/2240] fix: don't pass error arg twice to error handlers Fix #5405 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f47aa89d7fe..2ab4c8bfdc5 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "2.1.4", "bson": "~1.0.4", "hooks-fixed": "2.0.0", - "kareem": "1.4.1", + "kareem": "1.4.2", "mongodb": "2.2.27", "mpath": "0.3.0", "mpromise": "0.5.5", From bf2a98f250b1bfcb1428277183299c9cf507c18e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 6 Jul 2017 23:20:42 -0600 Subject: [PATCH 1684/2240] test(schema): repro #5416 --- test/schema.test.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index ef01283fd56..0b16b7cf4d1 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1591,6 +1591,18 @@ describe('schema', function() { done(); }); + it('arrays of mixed arrays (gh-5416)', function(done) { + var testSchema = new Schema({ + test: [Array] + }); + + assert.ok(testSchema.paths.test.casterConstructor !== Array); + assert.equal(testSchema.paths.test.casterConstructor, + mongoose.Schema.Types.Array); + + done(); + }); + describe('remove()', function() { before(function() { this.schema = new Schema({ From 8711c29b895fd71ba7cb049c29eac18a30994c82 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 6 Jul 2017 23:21:21 -0600 Subject: [PATCH 1685/2240] fix(schema): handle `type: [Array]` in schemas Fix #5416 --- lib/schema/array.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/schema/array.js b/lib/schema/array.js index b1ec0bae72e..e3d27430381 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -7,6 +7,7 @@ var $type = require('./operators/type'); var SchemaType = require('../schematype'); var CastError = SchemaType.CastError; var Types = { + Array: SchemaArray, Boolean: require('./boolean'), Date: require('./date'), Number: require('./number'), From 26bbb76b9a4a66c3114f5882f9754b9d4ae286a2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 7 Jul 2017 21:26:00 -0600 Subject: [PATCH 1686/2240] test(update): repro #5403 --- test/model.update.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 8fa486f08a2..f6d6090ce8f 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2559,6 +2559,27 @@ describe('model: update:', function() { catch(done); }); + it('$set array (gh-5403)', function(done) { + var Schema = new mongoose.Schema({ + colors: [{type: String}] + }); + + var Model = db.model('gh5403', Schema); + + Model.create({ colors: ['green'] }). + then(function() { + return Model.update({}, { $set: { colors: 'red' } }); + }). + then(function() { + return Model.collection.findOne(); + }). + then(function(doc) { + assert.deepEqual(doc.colors, ['red']); + done(); + }). + catch(done); + }); + it('defaults with overwrite and no update validators (gh-5384)', function(done) { var testSchema = new mongoose.Schema({ name: String, From 1613ef522fb44a2870041b8833bf2f3b36fc45a0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 7 Jul 2017 21:27:19 -0600 Subject: [PATCH 1687/2240] fix: enforce $set on an array must be an array Fix #5403 --- lib/schematype.js | 3 +++ lib/services/query/castUpdate.js | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/lib/schematype.js b/lib/schematype.js index a1900ee1f93..779588159d2 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -1015,6 +1015,9 @@ SchemaType.prototype.castForQueryWrapper = function(params) { if ('$conditional' in params) { return this.castForQuery(params.$conditional, params.val); } + if (params.$skipQueryCastForUpdate) { + return this._castForQuery(params.val); + } return this.castForQuery(params.val); }; diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index 3c0f0df0328..75c20032ac0 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -239,6 +239,15 @@ var castOps = { $setOnInsert: 1 }; +/*! + * ignore + */ + +var overwriteOps = { + $set: 1, + $setOnInsert: 1 +}; + /*! * Casts `val` according to `schema` and atomic `op`. * @@ -286,6 +295,7 @@ function castUpdateVal(schema, val, op, $conditional, context) { } return Boolean(val); } + if (/^\$/.test($conditional)) { return schema.castForQueryWrapper({ $conditional: $conditional, @@ -294,5 +304,13 @@ function castUpdateVal(schema, val, op, $conditional, context) { }); } + if (overwriteOps[op]) { + return schema.castForQueryWrapper({ + val: val, + context: context, + $skipQueryCastForUpdate: val != null + }); + } + return schema.castForQueryWrapper({ val: val, context: context }); } From 7d75f282651e6db101db7a1f1ccb69548daad977 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Jul 2017 16:40:56 -0600 Subject: [PATCH 1688/2240] test(update): repro #5430 --- test/model.update.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index f6d6090ce8f..63d65ae1bee 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2649,6 +2649,31 @@ describe('model: update:', function() { catch(done); }); + it('$push with updateValidators and top-level doc (gh-5430)', function(done) { + var notificationSchema = new mongoose.Schema({ + message: String + }); + + var Notification = db.model('gh5430_0', notificationSchema); + + var userSchema = new mongoose.Schema({ + notifications: [notificationSchema] + }); + + const User = db.model('gh5430', userSchema); + + User.update({}, { + $push: { + notifications: { + $each: [new Notification({ message: 'test' })] + } + } + }, { multi: true, runValidators: true }, function(error) { + assert.ifError(error); + done(); + }); + }); + it('update with Decimal type (gh-5361)', function(done) { start.mongodVersion(function(err, version) { if (err) { From 6750a7fdf252ee876b6c58d6c803ec9627910b80 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Jul 2017 17:11:32 -0600 Subject: [PATCH 1689/2240] fix(update): correctly cast document array in update validators with exec() Fix #5430 --- lib/schema/documentarray.js | 3 +++ test/model.update.test.js | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 8e88816fcef..6c5393940b8 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -146,6 +146,9 @@ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { if (options && options.updateValidator) { return fn(); } + if (!array.isMongooseDocumentArray) { + array = new MongooseDocumentArray(array, _this.path, scope); + } // handle sparse arrays, do not use array.forEach which does not // iterate over sparse elements yet reports array.length including diff --git a/test/model.update.test.js b/test/model.update.test.js index 63d65ae1bee..c779ee112fa 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2660,7 +2660,7 @@ describe('model: update:', function() { notifications: [notificationSchema] }); - const User = db.model('gh5430', userSchema); + var User = db.model('gh5430', userSchema); User.update({}, { $push: { @@ -2668,7 +2668,7 @@ describe('model: update:', function() { $each: [new Notification({ message: 'test' })] } } - }, { multi: true, runValidators: true }, function(error) { + }, { multi: true, runValidators: true }).exec(function(error) { assert.ifError(error); done(); }); From ff71ecec495ac4ce94e3859856ea66701bec1a0e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Jul 2017 18:25:55 -0600 Subject: [PATCH 1690/2240] test(connection): repro #5423 --- test/connection.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/connection.test.js b/test/connection.test.js index 2c45beb2388..8bbf1aa5a0e 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -36,6 +36,19 @@ describe('connections:', function() { return mongoose.disconnect().then(function() { done(); }); }).catch(done); }); + + it('with autoIndex (gh-5423)', function(done) { + var promise = mongoose.createConnection('mongodb://localhost:27017/mongoosetest', { + useMongoClient: true, + config: { autoIndex: false } + }); + + promise.then(function(conn) { + assert.strictEqual(conn.config.autoIndex, false); + assert.deepEqual(conn._connectionOptions, {}); + done(); + }).catch(done); + }); }); it('should allow closing a closed connection', function(done) { From 43873731dba094550185ee661f478c4468864f5b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Jul 2017 18:26:39 -0600 Subject: [PATCH 1691/2240] fix(connection): handle autoIndex with useMongoClient Fix #5423 --- lib/connection.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index 5a9a3fb57de..492c7e092ed 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -717,11 +717,17 @@ Connection.prototype.openUri = function(uri, options, callback) { var Promise = PromiseProvider.get(); var _this = this; - if (options && options.useMongoClient) { + if (options) { options = utils.clone(options, { retainKeyOrder: true }); delete options.useMongoClient; + if (options.config && options.config.autoIndex != null) { + this.config.autoIndex = options.config.autoIndex !== false; + delete options.config; + } } + this._connectionOptions = options; + return new Promise.ES6(function(resolve, reject) { mongodb.MongoClient.connect(uri, options, function(error, db) { if (error) { From 56c8c12a729902cc5686b1b9601ec49e5b2b4518 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Jul 2017 21:34:19 -0600 Subject: [PATCH 1692/2240] test(document): repro #5411 --- test/schema.validation.test.js | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 11cf40d9c93..7ba04f170ba 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -930,6 +930,52 @@ describe('schema', function() { }); }); + it('doesnt do double validation on document arrays underneath nested (gh-5411)', function(done) { + var callScope = []; + + function myValidator() { + callScope.push(this); + } + + var TestSchema = new Schema({ + nest1: { + nest2: { + nestarr: [new Schema({ + value: { + type: Boolean, + required: false, + validate: {validator: myValidator} + } + })] + } + } + }); + + var Test = mongoose.model('gh5411', TestSchema); + var testInstance = new Test({ + nest1: { + nest2: { + nestarr: [{ + value: true + }] + } + } + }); + + testInstance.nest1 = { + nest2: { + nestarr: [{ + value: false + }] + } + }; + + testInstance.validateSync(); + assert.equal(callScope.length, 1); + assert.strictEqual(callScope[0], testInstance.nest1.nest2.nestarr[0]); + done(); + }); + it('no double validation on set nested docarray (gh-4145)', function(done) { var calls = 0; var myValidator = function() { From e0b95b5aca82f8d03efaf452c0d267d3143db70a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Jul 2017 21:34:35 -0600 Subject: [PATCH 1693/2240] fix(document): don't double-validate deeply nested doc array elements Fix #5411 --- lib/services/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/common.js b/lib/services/common.js index e1413fcdd67..066c5a9855d 100644 --- a/lib/services/common.js +++ b/lib/services/common.js @@ -34,7 +34,7 @@ function flatten(update, path, options) { if (options && options.skipArrays && Array.isArray(val)) { continue; } - var flat = flatten(val, path + key); + var flat = flatten(val, path + key, options); for (var k in flat) { result[k] = flat[k]; } From 449514623f4bda2715b91958b07ae17b38e41da4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 10 Jul 2017 17:33:09 -0600 Subject: [PATCH 1694/2240] fix(connection): make openUri() return connection decorated with then() and catch() Fix #5404 --- lib/connection.js | 11 ++++++++++- test/connection.test.js | 34 +++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 492c7e092ed..63ef6146260 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -728,7 +728,7 @@ Connection.prototype.openUri = function(uri, options, callback) { this._connectionOptions = options; - return new Promise.ES6(function(resolve, reject) { + var promise = new Promise.ES6(function(resolve, reject) { mongodb.MongoClient.connect(uri, options, function(error, db) { if (error) { _this.readyState = STATES.disconnected; @@ -751,6 +751,15 @@ Connection.prototype.openUri = function(uri, options, callback) { _this.emit('open'); }); }); + + this.then = function(resolve, reject) { + return promise.then(resolve, reject); + }; + this.catch = function(reject) { + return promise.catch(reject); + }; + + return this; }; /** diff --git a/test/connection.test.js b/test/connection.test.js index 8bbf1aa5a0e..335a2019682 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -16,10 +16,12 @@ var muri = require('muri'); describe('connections:', function() { describe('useMongoClient/openUri (gh-5304)', function() { it('with mongoose.connect()', function(done) { - var promise = mongoose.connect('mongodb://localhost:27017/mongoosetest', { useMongoClient: true }); - assert.equal(promise.constructor.name, 'Promise'); + var conn = mongoose.connect('mongodb://localhost:27017/mongoosetest', { + useMongoClient: true + }); + assert.equal(conn.constructor.name, 'NativeConnection'); - promise.then(function(conn) { + conn.then(function(conn) { assert.equal(conn.constructor.name, 'NativeConnection'); return mongoose.disconnect().then(function() { done(); }); @@ -27,14 +29,28 @@ describe('connections:', function() { }); it('with mongoose.createConnection()', function(done) { - var promise = mongoose.createConnection('mongodb://localhost:27017/mongoosetest', { useMongoClient: true }); - assert.equal(promise.constructor.name, 'Promise'); + var conn = mongoose.createConnection('mongodb://localhost:27017/mongoosetest', { + useMongoClient: true + }); + assert.equal(conn.constructor.name, 'NativeConnection'); - promise.then(function(conn) { - assert.equal(conn.constructor.name, 'NativeConnection'); + var Test = conn.model('Test', new Schema({ name: String })); + assert.equal(Test.modelName, 'Test'); - return mongoose.disconnect().then(function() { done(); }); - }).catch(done); + var findPromise = Test.findOne(); + + assert.equal(typeof conn.catch, 'function'); + + conn. + then(function(conn) { + assert.equal(conn.constructor.name, 'NativeConnection'); + + return findPromise; + }). + then(function() { + return mongoose.disconnect().then(function() { done(); }); + }). + catch(done); }); it('with autoIndex (gh-5423)', function(done) { From 64689f8d2c769ba16ee1d104af5594ae342086ae Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 10 Jul 2017 19:00:12 -0600 Subject: [PATCH 1695/2240] test(document): repro #5389 --- test/document.test.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 53453211d4e..32fefff2346 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2870,6 +2870,39 @@ describe('document', function() { }); }); + it('validateSync works when setting array index nested (gh-5389)', function(done) { + var childSchema = new mongoose.Schema({ + _id: false, + name: String, + age: Number + }); + + var schema = new mongoose.Schema({ + name: String, + children: [childSchema] + }); + + var Model = db.model('gh5389', schema); + + Model. + create({ + name: 'test', + children: [ + { name: 'test-child', age: 24 } + ] + }). + then(function(doc) { + return Model.findById(doc._id); + }). + then(function(doc) { + doc.children[0] = { name: 'updated-child', age: 53 }; + var errors = doc.validateSync(); + assert.ok(!errors); + done(); + }). + catch(done); + }); + it('single embedded with defaults have $parent (gh-4115)', function(done) { var ChildSchema = new Schema({ name: { From fd811b7099ba58c772213aee1b64c74bb2c6cfb6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 10 Jul 2017 19:00:59 -0600 Subject: [PATCH 1696/2240] fix(document): don't crash if calling `validateSync()` after overwriting doc array index Fix #5389 --- lib/schema/documentarray.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 6c5393940b8..a50250746b8 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -226,6 +226,13 @@ DocumentArray.prototype.doValidateSync = function(array, scope) { continue; } + // If you set the array index directly, the doc might not yet be + // a full fledged mongoose subdoc, so make it into one. + if (!(doc instanceof Subdocument)) { + doc = array[i] = new this.casterConstructor(doc, array, undefined, + undefined, i); + } + var subdocValidateError = doc.validateSync(); if (subdocValidateError) { From 62aec9bd9b93011ff2823951aa7f45361ad318b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Ku=C5=BCy=C5=84ski?= Date: Tue, 11 Jul 2017 11:34:48 +0200 Subject: [PATCH 1697/2240] Proper handling of 'strict' option per query --- lib/query.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index 72bb4fe3a6c..80e7fd8ac98 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3012,8 +3012,8 @@ Query.prototype.cast = function(model, obj) { try { return cast(model.schema, obj, { upsert: this.options && this.options.upsert, - strict: (this.options && this.options.strict) || - (model.schema.options && model.schema.options.strict), + strict: (this.options && 'strict' in this.options) ? + this.options.strict : (model.schema.options && model.schema.options.strict), strictQuery: (this.options && this.options.strictQuery) || (model.schema.options && model.schema.options.strictQuery) }, this); From b69522344d43cced61c4feb3c9518e4d751d3e9f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 12 Jul 2017 14:25:56 -0700 Subject: [PATCH 1698/2240] test(document): repro #5406 --- test/document.test.js | 65 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 32fefff2346..86bba7213b7 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4374,6 +4374,71 @@ describe('document', function() { catch(done); }); + it('deeply nested subdocs and markModified (gh-5406)', function(done) { + var nestedValueSchema = new mongoose.Schema({ + _id: false, + value: Number + }); + var nestedPropertySchema = new mongoose.Schema({ + _id: false, + active: Boolean, + nestedValue: nestedValueSchema + }); + var nestedSchema = new mongoose.Schema({ + _id: false, + nestedProperty: nestedPropertySchema, + nestedTwoProperty: nestedPropertySchema + }); + var optionsSchema = new mongoose.Schema({ + _id: false, + nestedField: nestedSchema + }); + var TestSchema = new mongoose.Schema({ + fieldOne: String, + options: optionsSchema + }); + + var Test = db.model('gh5406', TestSchema); + + var doc = new Test({ + fieldOne: 'Test One', + options: { + nestedField: { + nestedProperty: { + active: true, + nestedValue: { + value: 42 + } + } + } + } + }); + + doc. + save(). + then(function(doc) { + doc.options.nestedField.nestedTwoProperty = { + active: true, + nestedValue: { + value: 1337 + } + }; + + assert.ok(doc.isModified('options')); + + return doc.save(); + }). + then(function(doc) { + return Test.findById(doc._id); + }). + then(function(doc) { + assert.equal(doc.options.nestedField.nestedTwoProperty.nestedValue.value, + 1337); + done(); + }). + catch(done); + }); + it('single nested subdoc post remove hooks (gh-5388)', function(done) { var contentSchema = new Schema({ blocks: [{ type: String }], From 9368df03650bde97aa8c35a96fd8aabbfacf6b4d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 12 Jul 2017 14:26:36 -0700 Subject: [PATCH 1699/2240] fix(document): reset down the nested subdocs when resetting parent doc Fix #5406 --- lib/document.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/document.js b/lib/document.js index b936d912783..fa290a7a376 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1689,6 +1689,17 @@ Document.prototype.$__reset = function reset() { } }); + this.$__.activePaths. + map('init', 'modify', function(i) { + return _this.getValue(i); + }). + filter(function(val) { + return val && val.$isSingleNested; + }). + forEach(function(doc) { + doc.$__reset(); + }); + // clear atomics this.$__dirty().forEach(function(dirt) { var type = dirt.value; From 9155b02dc054ad2a7b1197c3616cb0229ff28402 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 13 Jul 2017 12:09:50 -0700 Subject: [PATCH 1700/2240] chore: release 4.11.2 --- History.md | 16 ++++++++++++++++ package.json | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 44c0607334f..a436a4f5c54 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,19 @@ +4.11.2 / 2017-07-13 +=================== + * docs: fix comment typo in connect example #5435 [ConnorMcF](https://github.com/ConnorMcF) + * fix(update): correctly cast document array in update validators with exec() #5430 + * fix(connection): handle autoIndex with useMongoClient #5423 + * fix(schema): handle `type: [Array]` in schemas #5416 + * fix(timestamps): if overwrite is set and there's a $set, use $set instead of top-level update #5413 + * fix(document): don't double-validate deeply nested doc array elements #5411 + * fix(schematype): clone default objects so default not shared across object instances unless `shared` specified #5407 + * fix(document): reset down the nested subdocs when resetting parent doc #5406 + * fix: don't pass error arg twice to error handlers #5405 + * fix(connection): make openUri() return connection decorated with then() and catch() #5404 + * fix: enforce $set on an array must be an array #5403 + * fix(document): don't crash if calling `validateSync()` after overwriting doc array index #5389 + * fix(discriminator): ensure discriminator key doesn't count as user-selected field for projection #4629 + 4.11.1 / 2017-07-02 =================== * docs: populate virtuals fix justOne description #5427 [fredericosilva](https://github.com/fredericosilva) diff --git a/package.json b/package.json index 2ab4c8bfdc5..4cfe833eafe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.2-pre", + "version": "4.11.2", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From fb8549efbdee3dbaea9fb8a6bc207951ff794ed3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 13 Jul 2017 12:11:36 -0700 Subject: [PATCH 1701/2240] chore: now working on 4.11.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4cfe833eafe..028d5bbad7b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.2", + "version": "4.11.3-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 343b7a79651b4fe75e5e9b03d92659a76de323b3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 14 Jul 2017 14:03:53 -0700 Subject: [PATCH 1702/2240] fix(connection): remove .then() before resolving to prevent infinite recursion --- lib/connection.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 63ef6146260..8b0d3a4cab5 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -747,6 +747,8 @@ Connection.prototype.openUri = function(uri, options, callback) { } callback && callback(null, _this); + delete _this.then; + delete _this.catch; resolve(_this); _this.emit('open'); }); From 39d8123f658cc29a8385295a793c2a86fabab6cc Mon Sep 17 00:00:00 2001 From: Zach Bjornson Date: Fri, 14 Jul 2017 15:29:45 -0700 Subject: [PATCH 1703/2240] document nested array types --- docs/schematypes.jade | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index 3f880f1cf1b..f9c206e90ad 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -51,6 +51,8 @@ block content ofBoolean: [Boolean], ofMixed: [Schema.Types.Mixed], ofObjectId: [Schema.Types.ObjectId], + ofArrays: [[]] + ofArrayOfNumbbers: [[Number]] nested: { stuff: { type: String, lowercase: true, trim: true } } From 2b337ddcf6ac2b8357a4c23a1926f0a448826843 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 14 Jul 2017 16:52:08 -0700 Subject: [PATCH 1704/2240] chore: release 4.11.3 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index a436a4f5c54..3bcc782cc9c 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +4.11.3 / 2017-07-14 +=================== + * fix(connection): remove .then() before resolving to prevent infinite recursion #5471 + 4.11.2 / 2017-07-13 =================== * docs: fix comment typo in connect example #5435 [ConnorMcF](https://github.com/ConnorMcF) diff --git a/package.json b/package.json index 028d5bbad7b..639512f6de6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.3-pre", + "version": "4.11.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c9dc0ad7cd5c23bfad4620f275eba8d0cd92e5cb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 14 Jul 2017 16:53:18 -0700 Subject: [PATCH 1705/2240] chore: now working on 4.11.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 639512f6de6..a8b410f4d28 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.3", + "version": "4.11.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 1564d797e9d79e5cfc10cb525282739e3575f194 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 15 Jul 2017 21:17:46 -0700 Subject: [PATCH 1706/2240] test(query): repro #5448 --- test/model.discriminator.querying.test.js | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js index 793fd99e6d7..ad4da6febf8 100644 --- a/test/model.discriminator.querying.test.js +++ b/test/model.discriminator.querying.test.js @@ -394,6 +394,37 @@ describe('model', function() { }); }); + it('select: false in base schema (gh-5448)', function(done) { + var schema = new mongoose.Schema({ + foo: String, + hiddenColumn: { + type: String, + select: false, + } + }); + + var Foo = db.model('Foo', schema); + var Bar = Foo.discriminator('Bar', new mongoose.Schema({ + bar: String + })); + + var obj = { + foo: 'test', + hiddenColumn: 'Wanna see me?', + bar: 'test2' + }; + Bar.create(obj). + then(function() { return Foo.find().select('+hiddenColumn'); }). + then(function(docs) { + assert.equal(docs.length, 1); + assert.equal(docs[0].hiddenColumn, 'Wanna see me?'); + assert.equal(docs[0].foo, 'test'); + assert.equal(docs[0].bar, 'test2'); + done(); + }). + catch(done); + }); + it('hydrates correct model', function(done) { var baseEvent = new BaseEvent({name: 'Base event'}); var impressionEvent = new ImpressionEvent({name: 'Impression event'}); From f07c19b6488088fbc2a59e7b18464dd3086bb396 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 15 Jul 2017 21:22:19 -0700 Subject: [PATCH 1707/2240] fix(query): correct discriminator handling for schema `select: false` fields in schema Fix #5448 --- lib/query.js | 68 +++++++++++++++++++---- lib/queryhelpers.js | 4 +- test/model.discriminator.querying.test.js | 4 +- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/lib/query.js b/lib/query.js index 80e7fd8ac98..23fa67c9be9 100644 --- a/lib/query.js +++ b/lib/query.js @@ -759,6 +759,51 @@ Query.prototype.toConstructor = function toConstructor() { * @api public */ +Query.prototype.select = function select() { + var arg = arguments[0]; + if (!arg) return this; + var i; + var len; + + if (arguments.length !== 1) { + throw new Error('Invalid select: select only takes 1 argument'); + } + + this._validate('select'); + + var fields = this._fields || (this._fields = {}); + var userProvidedFields = this._userProvidedFields || (this._userProvidedFields = {}); + var type = typeof arg; + + if (('string' == type || Object.prototype.toString.call(arg) === '[object Arguments]') && + 'number' == typeof arg.length || Array.isArray(arg)) { + if ('string' == type) + arg = arg.split(/\s+/); + + for (i = 0, len = arg.length; i < len; ++i) { + var field = arg[i]; + if (!field) continue; + var include = '-' == field[0] ? 0 : 1; + if (include === 0) field = field.substring(1); + fields[field] = include; + userProvidedFields[field] = include; + } + + return this; + } + + if (utils.isObject(arg)) { + var keys = Object.keys(arg); + for (i = 0; i < keys.length; ++i) { + fields[keys[i]] = arg[keys[i]]; + userProvidedFields[keys[i]] = arg[keys[i]]; + } + return this; + } + + throw new TypeError('Invalid select() argument. Must be string or object.'); +}; + /** * _DEPRECATED_ Sets the slaveOk option. * @@ -1108,6 +1153,7 @@ Query.prototype._find = function(callback) { var fields = this._fieldsForExec(); var options = this._mongooseOptions; var _this = this; + var userProvidedFields = _this._userProvidedFields || {}; var cb = function(err, docs) { if (err) { @@ -1121,7 +1167,7 @@ Query.prototype._find = function(callback) { if (!options.populate) { return !!options.lean === true ? callback(null, docs) - : completeMany(_this.model, docs, fields, null, callback); + : completeMany(_this.model, docs, fields, userProvidedFields, null, callback); } var pop = helpers.preparePopulationOptionsMQ(_this, options); @@ -1130,7 +1176,7 @@ Query.prototype._find = function(callback) { if (err) return callback(err); return !!options.lean === true ? callback(null, docs) - : completeMany(_this.model, docs, fields, pop, callback); + : completeMany(_this.model, docs, fields, userProvidedFields, pop, callback); }); }; @@ -1245,7 +1291,7 @@ Query.prototype.merge = function(source) { * @param {Function} callback */ -function completeMany(model, docs, fields, pop, callback) { +function completeMany(model, docs, fields, userProvidedFields, pop, callback) { var arr = []; var count = docs.length; var len = count; @@ -1257,7 +1303,7 @@ function completeMany(model, docs, fields, pop, callback) { --count || callback(null, arr); } for (var i = 0; i < len; ++i) { - arr[i] = helpers.createModel(model, docs[i], fields); + arr[i] = helpers.createModel(model, docs[i], fields, userProvidedFields); arr[i].init(docs[i], opts, init); } } @@ -1297,6 +1343,7 @@ Query.prototype._findOne = function(callback) { var options = this._mongooseOptions; var projection = this._fieldsForExec(); + var userProvidedFields = this._userProvidedFields || {}; var _this = this; // don't pass in the conditions because we already merged them in @@ -1311,7 +1358,7 @@ Query.prototype._findOne = function(callback) { if (!options.populate) { return !!options.lean === true ? callback(null, doc) - : completeOne(_this.model, doc, null, {}, projection, null, callback); + : completeOne(_this.model, doc, null, {}, projection, userProvidedFields, null, callback); } var pop = helpers.preparePopulationOptionsMQ(_this, options); @@ -1322,7 +1369,7 @@ Query.prototype._findOne = function(callback) { } return !!options.lean === true ? callback(null, doc) - : completeOne(_this.model, doc, null, {}, projection, pop, callback); + : completeOne(_this.model, doc, null, {}, projection, userProvidedFields, pop, callback); }); }); }; @@ -1761,12 +1808,12 @@ Query.prototype._deleteMany = function(callback) { * @param {Function} callback */ -function completeOne(model, doc, res, options, fields, pop, callback) { +function completeOne(model, doc, res, options, fields, userProvidedFields, pop, callback) { var opts = pop ? {populated: pop} : undefined; - var casted = helpers.createModel(model, doc, fields); + var casted = helpers.createModel(model, doc, fields, userProvidedFields); casted.init(doc, opts, function(err) { if (err) { return callback(err); @@ -2098,6 +2145,7 @@ Query.prototype._findAndModify = function(type, callback) { } this._applyPaths(); + var userProvidedFields = this._userProvidedFields || {}; var options = this._mongooseOptions; @@ -2131,7 +2179,7 @@ Query.prototype._findAndModify = function(type, callback) { if (!!options.lean === true) { return _completeOneLean(doc, res, opts, callback); } - return completeOne(_this.model, doc, res, opts, fields, null, callback); + return completeOne(_this.model, doc, res, opts, fields, userProvidedFields, null, callback); } var pop = helpers.preparePopulationOptionsMQ(_this, options); @@ -2144,7 +2192,7 @@ Query.prototype._findAndModify = function(type, callback) { if (!!options.lean === true) { return _completeOneLean(doc, res, opts, callback); } - return completeOne(_this.model, doc, res, opts, fields, pop, callback); + return completeOne(_this.model, doc, res, opts, fields, userProvidedFields, pop, callback); }); }; diff --git a/lib/queryhelpers.js b/lib/queryhelpers.js index f31197f643f..c98d3037b60 100644 --- a/lib/queryhelpers.js +++ b/lib/queryhelpers.js @@ -50,7 +50,7 @@ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query, * * @return {Model} */ -exports.createModel = function createModel(model, doc, fields) { +exports.createModel = function createModel(model, doc, fields, userProvidedFields) { var discriminatorMapping = model.schema ? model.schema.discriminatorMapping : null; @@ -61,7 +61,7 @@ exports.createModel = function createModel(model, doc, fields) { if (key && doc[key] && model.discriminators && model.discriminators[doc[key]]) { var discriminator = model.discriminators[doc[key]]; - var _fields = utils.clone(fields); + var _fields = utils.clone(userProvidedFields); exports.applyPaths(_fields, discriminator.schema); return new model.discriminators[doc[key]](undefined, _fields, true); } diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js index ad4da6febf8..5811a2c1b69 100644 --- a/test/model.discriminator.querying.test.js +++ b/test/model.discriminator.querying.test.js @@ -398,8 +398,8 @@ describe('model', function() { var schema = new mongoose.Schema({ foo: String, hiddenColumn: { - type: String, - select: false, + type: String, + select: false } }); From 96f06c1705a14de88fb65b1057e8b3ae7876914c Mon Sep 17 00:00:00 2001 From: Talha Awan Date: Sun, 16 Jul 2017 15:52:09 +0500 Subject: [PATCH 1708/2240] update MongoDB joins info in introduction --- docs/populate.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/populate.jade b/docs/populate.jade index 1ec75f71db1..2b9efe3af2b 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -3,7 +3,7 @@ extends layout block content h2 Population :markdown - There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where population comes in. + MongoDB introduced left outer join ([$lookup](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/)) in version 3.2. Mongoose offered population before that, which is still an alternative to joins due to its ease of use. Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s). We may populate a single document, multiple documents, plain object, multiple plain objects, or all objects returned from a query. Let's look at some examples. :js From 988e6dc735cabc4fed57c13e5a317c1fa13b82eb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 16 Jul 2017 22:23:52 -0700 Subject: [PATCH 1709/2240] test(query): repro #5434 --- test/model.query.casting.test.js | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/model.query.casting.test.js b/test/model.query.casting.test.js index 4111f1ec83b..e9584588b55 100644 --- a/test/model.query.casting.test.js +++ b/test/model.query.casting.test.js @@ -1063,6 +1063,41 @@ describe('model query casting', function() { catch(done); }); + it('runSettersOnQuery only once on find (gh-5434)', function(done) { + var db = start(); + + var vs = []; + var UserSchema = new mongoose.Schema({ + name: String, + foo: { + type: Number, + get: function(val) { + return val.toString(); + }, + set: function(val) { + vs.push(val); + return val; + } + } + }, { runSettersOnQuery: true }); + + var Test = db.model('gh5434', UserSchema); + + Test.find({ foo: '123' }).exec(function(error) { + assert.ifError(error); + assert.equal(vs.length, 1); + assert.strictEqual(vs[0], '123'); + + vs = []; + Test.find({ foo: '123' }, function(error) { + assert.ifError(error); + assert.equal(vs.length, 1); + assert.strictEqual(vs[0], '123'); + done(); + }); + }); + }); + it('runSettersOnQuery as query option (gh-5350)', function(done) { var db = start(); From 29e33a6e94cf871bfd00003a0f3064e1e23a3a34 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 16 Jul 2017 22:25:57 -0700 Subject: [PATCH 1710/2240] fix(query): defer condition casting until final exec Fix #5434 --- lib/query.js | 23 ++++++++++++++++------- test/model.querying.test.js | 2 ++ test/query.test.js | 1 + 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/query.js b/lib/query.js index 23fa67c9be9..c0386042357 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1134,6 +1134,19 @@ Query.prototype.mongooseOptions = function(v) { return this._mongooseOptions; }; +/*! + * ignore + */ + +Query.prototype._castConditions = function() { + try { + this.cast(this.model); + this._castError = null; + } catch (err) { + this._castError = err; + } +}; + /** * Thunk around find() * @@ -1142,6 +1155,8 @@ Query.prototype.mongooseOptions = function(v) { * @api private */ Query.prototype._find = function(callback) { + this._castConditions(); + if (this._castError) { callback(this._castError); return this; @@ -1212,13 +1227,6 @@ Query.prototype.find = function(conditions, callback) { prepareDiscriminatorCriteria(this); - try { - this.cast(this.model); - this._castError = null; - } catch (err) { - this._castError = err; - } - // if we don't have a callback, then just return the query object if (!callback) { return Query.base.find.call(this); @@ -3176,6 +3184,7 @@ Query.prototype._applyPaths = function applyPaths() { Query.prototype.stream = function stream(opts) { this._applyPaths(); this._fields = this._castFields(this._fields); + this._castConditions(); return new QueryStream(this, opts); }; Query.prototype.stream = util.deprecate(Query.prototype.stream, 'Mongoose: ' + diff --git a/test/model.querying.test.js b/test/model.querying.test.js index 2066b9ef6ce..8d7696a3902 100644 --- a/test/model.querying.test.js +++ b/test/model.querying.test.js @@ -2678,6 +2678,7 @@ describe('model: querying:', function() { ] }; var q = M.find(cond); + q._castConditions(); assert.equal(typeof q._conditions.$and[0].$or[0].num, 'number'); assert.equal(typeof q._conditions.$and[0].$or[1]['subdoc.num'], 'number'); assert.equal(typeof q._conditions.$and[1].$and[0]['subdoc.title'], 'string'); @@ -2696,6 +2697,7 @@ describe('model: querying:', function() { $and: [{$or: [{$and: [{$or: [{num: '12345'}, {'subdoc.num': '56789'}]}]}]}] }; var q = M.find(cond); + q._castConditions(); assert.equal(typeof q._conditions.$and[0].$or[0].$and[0].$or[0].num, 'number'); assert.equal(typeof q._conditions.$and[0].$or[0].$and[0].$or[1]['subdoc.num'], 'number'); done(); diff --git a/test/query.test.js b/test/query.test.js index 27f12c74f81..71a99952191 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1918,6 +1918,7 @@ describe('Query', function() { } } }); + q._castConditions(); assert.ok(q._conditions.createdAt.$not.$gte instanceof Date); assert.ok(q._conditions.createdAt.$not.$lte instanceof Date); From 85cbf6e3d0e0f6898dcffbb433cae5946e79dd6c Mon Sep 17 00:00:00 2001 From: ValYouW Date: Mon, 17 Jul 2017 14:21:38 +0300 Subject: [PATCH 1711/2240] propagate runSettersOnQuery option to child schema --- lib/schema.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index f8e82f2abf4..9ced82ad2dc 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -594,6 +594,10 @@ Schema.interpretAsType = function(path, obj, options) { if (options.hasOwnProperty('strict')) { childSchemaOptions.strict = options.strict; } + //propagate 'runSettersOnQuery' option to child schema + if (options.hasOwnProperty('runSettersOnQuery')) { + childSchemaOptions.runSettersOnQuery = options.runSettersOnQuery; + } var childSchema = new Schema(cast, childSchemaOptions); childSchema.$implicitlyCreated = true; return new MongooseTypes.DocumentArray(path, childSchema, obj); From de3bc19efdb35c2ba028d1293a69123341bf29f3 Mon Sep 17 00:00:00 2001 From: ValYouW Date: Mon, 17 Jul 2017 15:36:08 +0300 Subject: [PATCH 1712/2240] eslint fix --- lib/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 9ced82ad2dc..051273c99cf 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -596,7 +596,7 @@ Schema.interpretAsType = function(path, obj, options) { } //propagate 'runSettersOnQuery' option to child schema if (options.hasOwnProperty('runSettersOnQuery')) { - childSchemaOptions.runSettersOnQuery = options.runSettersOnQuery; + childSchemaOptions.runSettersOnQuery = options.runSettersOnQuery; } var childSchema = new Schema(cast, childSchemaOptions); childSchema.$implicitlyCreated = true; From 49150c088766f6ca5460c1ce3702f951877e8d86 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 17 Jul 2017 17:48:17 -0700 Subject: [PATCH 1713/2240] docs: improve changes from #5475 --- docs/populate.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/populate.jade b/docs/populate.jade index 2b9efe3af2b..a6fe6ffd0b5 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -3,7 +3,7 @@ extends layout block content h2 Population :markdown - MongoDB introduced left outer join ([$lookup](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/)) in version 3.2. Mongoose offered population before that, which is still an alternative to joins due to its ease of use. + MongoDB has the join-like ([$lookup](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/)) aggregation operator in versions >= 3.2. Mongoose has a more powerful alternative called `populate()`, which lets you reference documents in other collections. Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s). We may populate a single document, multiple documents, plain object, multiple plain objects, or all objects returned from a query. Let's look at some examples. :js From 0f523320f45d22473e15d9a0a9fc3d9296c40408 Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 19 Jul 2017 11:02:33 +0200 Subject: [PATCH 1714/2240] Missing error handling. --- lib/services/cursor/eachAsync.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/services/cursor/eachAsync.js b/lib/services/cursor/eachAsync.js index 9b1b8b6d500..134e60ce99d 100644 --- a/lib/services/cursor/eachAsync.js +++ b/lib/services/cursor/eachAsync.js @@ -43,6 +43,9 @@ module.exports = function eachAsync(next, fn, options, callback) { tasks.push(next); } async.parallel(tasks, function(error, docs) { + if (error) { + return callback(error); + } var initialLength = docs.length; docs = docs.filter(function(doc) { return doc != null; From 5cd4e3c7c3f212e04ed157e1a877886aa8624954 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 19 Jul 2017 18:02:42 -0700 Subject: [PATCH 1715/2240] test: add repro for #5453 --- test/model.update.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index c779ee112fa..23d2404e778 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2724,6 +2724,20 @@ describe('model: update:', function() { } }); + it('strict false in query (gh-5453)', function(done) { + var schema = new mongoose.Schema({ + date: { type: Date, required: true } + }, { strict: true }); + + var Model = db.model('Model', schema); + var q = { $isolated: true }; + var u = { $set: { smth: 1 } }; + var o = { strict: false, upsert: true }; + Model.update(q, u, o).then(function() { + done(); + }).catch(done); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From 1d06bb6d3b4e328f87d024a96fe645f309f28fa3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 19 Jul 2017 18:14:29 -0700 Subject: [PATCH 1716/2240] test(update): repro #5477 part 1 --- test/model.update.test.js | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 23d2404e778..aacc6e806c5 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2729,7 +2729,7 @@ describe('model: update:', function() { date: { type: Date, required: true } }, { strict: true }); - var Model = db.model('Model', schema); + var Model = db.model('gh5453', schema); var q = { $isolated: true }; var u = { $set: { smth: 1 } }; var o = { strict: false, upsert: true }; @@ -2738,6 +2738,40 @@ describe('model: update:', function() { }).catch(done); }); + it('cast error in update conditions (gh-5477)', function(done) { + var schema = new mongoose.Schema({ + name: String + }, { strict: true }); + + var Model = db.model('gh5477', schema); + var q = { notAField: true }; + var u = { $set: { name: 'Test' } }; + var o = { upsert: true }; + + var outstanding = 3; + + Model.update(q, u, o, function(error) { + assert.ok(error); + assert.ok(error.message.indexOf('notAField') !== -1, error.message); + assert.ok(error.message.indexOf('upsert') !== -1, error.message); + --outstanding || done(); + }); + + Model.updateOne(q, u, o, function(error) { + assert.ok(error); + assert.ok(error.message.indexOf('notAField') !== -1, error.message); + assert.ok(error.message.indexOf('upsert') !== -1, error.message); + --outstanding || done(); + }); + + Model.updateMany(q, u, o, function(error) { + assert.ok(error); + assert.ok(error.message.indexOf('notAField') !== -1, error.message); + assert.ok(error.message.indexOf('upsert') !== -1, error.message); + --outstanding || done(); + }); + }); + it('single embedded schema under document array (gh-4519)', function(done) { var PermissionSchema = new mongoose.Schema({ read: { type: Boolean, required: true }, From 9407b50c8c0f4d94192cbe399f0d0467e91a31c6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 19 Jul 2017 18:14:33 -0700 Subject: [PATCH 1717/2240] fix(query): run _castConditions() correctly in update ops Re: #5477 --- lib/query.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index c0386042357..5b18c91eb4d 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2303,6 +2303,8 @@ Query.prototype._execUpdate = function(callback) { var doValidate; var _this; + this._castConditions(); + var castedQuery = this._conditions; var castedDoc = this._update; var options = this.options; @@ -2365,6 +2367,8 @@ Query.prototype._updateMany = function(callback) { var doValidate; var _this; + this._castConditions(); + var castedQuery = this._conditions; var castedDoc = this._update; var options = this.options; @@ -2410,6 +2414,8 @@ Query.prototype._updateOne = function(callback) { var doValidate; var _this; + this._castConditions(); + var castedQuery = this._conditions; var castedDoc = this._update; var options = this.options; @@ -3069,7 +3075,8 @@ Query.prototype.cast = function(model, obj) { return cast(model.schema, obj, { upsert: this.options && this.options.upsert, strict: (this.options && 'strict' in this.options) ? - this.options.strict : (model.schema.options && model.schema.options.strict), + this.options.strict : + (model.schema.options && model.schema.options.strict), strictQuery: (this.options && this.options.strictQuery) || (model.schema.options && model.schema.options.strictQuery) }, this); From 6e1eb2382a9054e68ecebb14a66d36f259bdba3a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 20 Jul 2017 15:33:57 -0700 Subject: [PATCH 1718/2240] test(middleware): repro #5466 --- lib/query.js | 5 +++-- test/document.test.js | 2 ++ test/query.middleware.test.js | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index 5b18c91eb4d..105dbb75813 100644 --- a/lib/query.js +++ b/lib/query.js @@ -74,7 +74,8 @@ function Query(conditions, options, model, collection) { if (this.schema) { var kareemOptions = { useErrorHandlers: true, - numCallbackParams: 1 + numCallbackParams: 1, + nullResultByDefault: true }; this._count = this.model.hooks.createWrapper('count', Query.prototype._count, this, kareemOptions); @@ -2902,7 +2903,7 @@ Query.prototype.exec = function exec(op, callback) { return null; }, function(error) { - callback(error); + callback(error, null); }). catch(function(error) { // If we made it here, we must have an error in the callback re: diff --git a/test/document.test.js b/test/document.test.js index 86bba7213b7..860593c8c9d 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -2166,10 +2166,12 @@ describe('document', function() { }); schema.post('save', function(error, doc, next) { + assert.ok(doc instanceof Model); next(new Error('Catch all')); }); schema.post('save', function(error, doc, next) { + assert.ok(doc instanceof Model); next(new Error('Catch all #2')); }); diff --git a/test/query.middleware.test.js b/test/query.middleware.test.js index 8a58827673e..cc9672de8b0 100644 --- a/test/query.middleware.test.js +++ b/test/query.middleware.test.js @@ -283,6 +283,8 @@ describe('query middleware', function() { var testSchema = new Schema({ title: { type: String, unique: true } }); testSchema.post('update', function(error, res, next) { + assert.ok(error); + assert.ok(!res); next(new Error('woops')); }); From 3ec67a5c60939eb8290421d1dab78a25f68d4191 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 20 Jul 2017 15:35:25 -0700 Subject: [PATCH 1719/2240] fix(middleware): ensure that error handlers for save get doc as 2nd param Fix #5466 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a8b410f4d28..17512e6a0d6 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "2.1.4", "bson": "~1.0.4", "hooks-fixed": "2.0.0", - "kareem": "1.4.2", + "kareem": "1.5.0", "mongodb": "2.2.27", "mpath": "0.3.0", "mpromise": "0.5.5", From 6c1bb55bcb521efca461480c80ee6cc9d8f92443 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 09:41:06 -0700 Subject: [PATCH 1720/2240] test: repro #5437 --- test/index.test.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/index.test.js b/test/index.test.js index 7b5a053672e..f0355b4c76b 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -70,8 +70,14 @@ describe('mongoose module:', function() { var called = 0; var calls = []; + var preSaveCalls = 0; mong.plugin(function(s) { calls.push(s); + + s.pre('save', function(next) { + ++preSaveCalls; + next(); + }); }); schema.plugin(function(s) { @@ -79,13 +85,19 @@ describe('mongoose module:', function() { called++; }); - mong.model('GlobalPlugins', schema); + var M = mong.model('GlobalPlugins', schema); assert.equal(called, 1); assert.equal(calls.length, 2); assert.equal(calls[0], schema); assert.equal(calls[1], subSchema); - done(); + + assert.equal(preSaveCalls, 0); + mong.connect(start.uri, { useMongoClient: true }); + M.create({ test: {} }, function(error) { + assert.equal(preSaveCalls, 2); + done(); + }); }); describe('disconnection of all connections', function() { From af73f649cdcfe00bc2d2cea64a68bed8b1f7c943 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 11:35:51 -0700 Subject: [PATCH 1721/2240] fix(schema): apply nested schema hooks when compiling parent so global plugin hooks work Fix #5437 --- lib/index.js | 29 +++++++++++++---------------- lib/schema.js | 10 ++++++++-- lib/schema/documentarray.js | 2 -- lib/schema/embedded.js | 2 -- lib/services/model/applyHooks.js | 8 ++++++++ test/index.test.js | 4 +++- test/schema.documentarray.test.js | 4 ++-- 7 files changed, 34 insertions(+), 25 deletions(-) diff --git a/lib/index.js b/lib/index.js index 9d9b8fe73fa..c6f9879784d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -12,6 +12,7 @@ var Types = require('./types'); var Query = require('./query'); var Model = require('./model'); var Document = require('./document'); +var applyHooks = require('./services/model/applyHooks'); var utils = require('./utils'); var format = utils.toCollectionName; var pkg = require('../package.json'); @@ -43,22 +44,18 @@ function Mongoose() { }; var conn = this.createConnection(); // default connection conn.models = this.models; -} -/*! - * ignore - */ - -Object.defineProperty(Mongoose.prototype, 'plugins', { - configurable: false, - enumerable: true, - writable: false, - value: [ - [saveSubdocs, { deduplicate: true }], - [validateBeforeSave, { deduplicate: true }], - [shardingPlugin, { deduplicate: true }] - ] -}); + Object.defineProperty(this, 'plugins', { + configurable: false, + enumerable: true, + writable: false, + value: [ + [saveSubdocs, { deduplicate: true }], + [validateBeforeSave, { deduplicate: true }], + [shardingPlugin, { deduplicate: true }] + ] + }); +} /** * Expose connection states for user-land @@ -488,7 +485,7 @@ Mongoose.prototype._applyPlugins = function(schema) { } schema.$globalPluginsApplied = true; for (i = 0, len = schema.childSchemas.length; i < len; ++i) { - this._applyPlugins(schema.childSchemas[i]); + this._applyPlugins(schema.childSchemas[i].schema); } }; Mongoose.prototype._applyPlugins.$hasSideEffects = true; diff --git a/lib/schema.js b/lib/schema.js index 051273c99cf..3071808f0e4 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -528,9 +528,15 @@ Schema.prototype.path = function(path, obj) { this.paths[path].schema.singleNestedPaths[key]; } - this.childSchemas.push(this.paths[path].schema); + this.childSchemas.push({ + schema: this.paths[path].schema, + model: this.paths[path].caster + }); } else if (this.paths[path].$isMongooseDocumentArray) { - this.childSchemas.push(this.paths[path].schema); + this.childSchemas.push({ + schema: this.paths[path].schema, + model: this.paths[path].casterConstructor + }); } return this; }; diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index a50250746b8..895ab2187d7 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -90,8 +90,6 @@ function _createConstructor(schema, options) { EmbeddedDocument[i] = EventEmitter.prototype[i]; } - applyHooks(EmbeddedDocument, schema); - EmbeddedDocument.options = options; return EmbeddedDocument; diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 525d64bb17e..7c74b445ca8 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -73,8 +73,6 @@ function Embedded(schema, path, options) { _embedded[i] = EventEmitter.prototype[i]; } - applyHooks(_embedded, schema); - this.caster = _embedded; this.schema = schema; this.$isSingleNested = true; diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index d7531f31af3..50f9eb7c3e3 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -13,6 +13,14 @@ module.exports = applyHooks; */ function applyHooks(model, schema) { + model.$appliedHooks = true; + for (var i = 0; i < schema.childSchemas.length; ++i) { + if (schema.childSchemas[i].model.$appliedHooks) { + continue; + } + applyHooks(schema.childSchemas[i].model, schema.childSchemas[i].schema); + } + var q = schema && schema.callQueue; var toWrapEl; var len; diff --git a/test/index.test.js b/test/index.test.js index f0355b4c76b..2081348f464 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -63,7 +63,7 @@ describe('mongoose module:', function() { it('declaring global plugins', function(done) { var mong = new Mongoose(); - var subSchema = new Schema(); + var subSchema = new Schema({}); var schema = new Schema({ test: [subSchema] }); @@ -95,7 +95,9 @@ describe('mongoose module:', function() { assert.equal(preSaveCalls, 0); mong.connect(start.uri, { useMongoClient: true }); M.create({ test: {} }, function(error) { + assert.ifError(error); assert.equal(preSaveCalls, 2); + mong.disconnect(); done(); }); }); diff --git a/test/schema.documentarray.test.js b/test/schema.documentarray.test.js index 191a57d702e..a69c704d54a 100644 --- a/test/schema.documentarray.test.js +++ b/test/schema.documentarray.test.js @@ -66,8 +66,8 @@ describe('schema.documentarray', function() { assert.equal(schema1.childSchemas.length, 1); assert.equal(schema2.childSchemas.length, 1); - assert.ok(schema1.childSchemas[0].$implicitlyCreated); - assert.ok(!schema2.childSchemas[0].$implicitlyCreated); + assert.ok(schema1.childSchemas[0].schema.$implicitlyCreated); + assert.ok(!schema2.childSchemas[0].schema.$implicitlyCreated); done(); }); }); From 77f4bc576184f1b481bd21d7f220ce4413c15399 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 11:41:25 -0700 Subject: [PATCH 1722/2240] style: fix lint --- lib/index.js | 1 - lib/schema/documentarray.js | 1 - lib/schema/embedded.js | 1 - lib/services/model/applyHooks.js | 17 +++++++++-------- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/index.js b/lib/index.js index c6f9879784d..c9a36c3e555 100644 --- a/lib/index.js +++ b/lib/index.js @@ -12,7 +12,6 @@ var Types = require('./types'); var Query = require('./query'); var Model = require('./model'); var Document = require('./document'); -var applyHooks = require('./services/model/applyHooks'); var utils = require('./utils'); var format = utils.toCollectionName; var pkg = require('../package.json'); diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 895ab2187d7..37df5c93f7e 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -10,7 +10,6 @@ var EventEmitter = require('events').EventEmitter; var MongooseDocumentArray = require('../types/documentarray'); var SchemaType = require('../schematype'); var Subdocument = require('../types/embedded'); -var applyHooks = require('../services/model/applyHooks'); var discriminator = require('../services/model/discriminator'); var util = require('util'); var utils = require('../utils'); diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 7c74b445ca8..7ed6f589a44 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -8,7 +8,6 @@ var $exists = require('./operators/exists'); var EventEmitter = require('events').EventEmitter; var SchemaType = require('../schematype'); var Subdocument = require('../types/subdocument'); -var applyHooks = require('../services/model/applyHooks'); var castToNumber = require('./operators/helpers').castToNumber; var geospatial = require('./operators/geospatial'); diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index 50f9eb7c3e3..55f41f36727 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -13,14 +13,6 @@ module.exports = applyHooks; */ function applyHooks(model, schema) { - model.$appliedHooks = true; - for (var i = 0; i < schema.childSchemas.length; ++i) { - if (schema.childSchemas[i].model.$appliedHooks) { - continue; - } - applyHooks(schema.childSchemas[i].model, schema.childSchemas[i].schema); - } - var q = schema && schema.callQueue; var toWrapEl; var len; @@ -29,6 +21,15 @@ function applyHooks(model, schema) { var pointCut; var keys; var newName; + + model.$appliedHooks = true; + for (i = 0; i < schema.childSchemas.length; ++i) { + if (schema.childSchemas[i].model.$appliedHooks) { + continue; + } + applyHooks(schema.childSchemas[i].model, schema.childSchemas[i].schema); + } + if (!q.length) { return; } From fe3897b4e2f294100f787ef380427389ccb3975f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 12:05:25 -0700 Subject: [PATCH 1723/2240] docs(middleware): clarify context for document, query, and model middleware Fix #5381 --- docs/middleware.jade | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/middleware.jade b/docs/middleware.jade index 9f8fc308338..6820563484a 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -6,9 +6,10 @@ block content Middleware (also called pre and post *hooks*) are functions which are passed control during execution of asynchronous functions. Middleware is specified on the schema level and is useful for writing [plugins](./plugins.html). - Mongoose 4.0 has 2 types - of middleware: document middleware and query middleware. + Mongoose 4.x has 3 types + of middleware: document middleware, model middleware, and query middleware. Document middleware is supported for the following document functions. + In document middleware functions, `this` refers to the document. * [init](./api.html#document_Document-init) * [validate](./api.html#document_Document-validate) @@ -16,16 +17,21 @@ block content * [remove](./api.html#model_Model-remove) Query middleware is supported for the following Model and Query functions. + In query middleware functions, `this` refers to the query. * [count](./api.html#query_Query-count) * [find](./api.html#query_Query-find) * [findOne](./api.html#query_Query-findOne) * [findOneAndRemove](./api.html#query_Query-findOneAndRemove) * [findOneAndUpdate](./api.html#query_Query-findOneAndUpdate) - * [insertMany](./api.html#model_Model.insertMany) * [update](./api.html#query_Query-update) + + Model middleware is supported for the following model functions. + In model middleware functions, `this` refers to the model. + + * [insertMany](./api.html#model_Model.insertMany) - Both document middleware and query middleware support pre and post hooks. + All middleware types support pre and post hooks. How pre and post hooks work is described in more detail below. **Note:** There is no query hook for `remove()`, only for documents. From b108182889ea3940e6734c600df223eee8615197 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 13:07:06 -0700 Subject: [PATCH 1724/2240] test(aggregate): repro agg cursor issue #5394 --- test/aggregate.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 5fe0c76a8bb..c34ed41a31b 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -911,9 +911,34 @@ describe('aggregate: ', function() { cursor({ useMongooseAggCursor: true }). exec(); assert.ok(cursor instanceof require('stream').Readable); + done(); }); + it('cursor() with useMongooseAggCursor works (gh-5145) (gh-5394)', function(done) { + var db = start(); + + var MyModel = db.model('gh5145', { name: String }); + + MyModel.create({ name: 'test' }, function(error) { + assert.ifError(error); + + var docs = []; + MyModel. + aggregate([{ $match: { name: 'test' } }]). + cursor({ useMongooseAggCursor: true }). + exec(). + eachAsync(function(doc) { + docs.push(doc); + }). + then(function() { + assert.equal(docs.length, 1); + assert.equal(docs[0].name, 'test'); + done(); + }); + }); + }); + it('cursor() eachAsync (gh-4300)', function(done) { var db = start(); From 0c2d99fc6f58d77a92d22b266eab301e2a171b8a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 13:08:18 -0700 Subject: [PATCH 1725/2240] fix(aggregate): don't rely on mongodb aggregate to put a cursor in the callback Fix #5394 --- lib/cursor/AggregationCursor.js | 31 +++++++++++++++++++------------ test/aggregate.test.js | 2 +- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/cursor/AggregationCursor.js b/lib/cursor/AggregationCursor.js index ef8c37ef681..a56d6a54d0c 100644 --- a/lib/cursor/AggregationCursor.js +++ b/lib/cursor/AggregationCursor.js @@ -33,23 +33,30 @@ function AggregationCursor(agg) { this.cursor = null; this.agg = agg; this._transforms = []; - var _this = this; var model = agg._model; - model.collection.aggregate(agg._pipeline, agg.options || {}, function(err, cursor) { - if (_this._error) { - cursor.close(function() {}); - _this.listeners('error').length > 0 && _this.emit('error', _this._error); - } - if (err) { - return _this.emit('error', err); - } - _this.cursor = cursor; - _this.emit('cursor', cursor); - }); + delete agg.options.cursor.useMongooseAggCursor; + + _init(model, this, agg); } util.inherits(AggregationCursor, Readable); +/*! + * ignore + */ + +function _init(model, c, agg) { + if (!model.collection.buffer) { + c.cursor = model.collection.aggregate(agg._pipeline, agg.options || {}); + c.emit('cursor', c.cursor); + } else { + model.collection.emitter.once('queue', function() { + c.cursor = model.collection.aggregate(agg._pipeline, agg.options || {}); + c.emit('cursor', c.cursor); + }); + } +} + /*! * Necessary to satisfy the Readable API */ diff --git a/test/aggregate.test.js b/test/aggregate.test.js index c34ed41a31b..5693e225b32 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -918,7 +918,7 @@ describe('aggregate: ', function() { it('cursor() with useMongooseAggCursor works (gh-5145) (gh-5394)', function(done) { var db = start(); - var MyModel = db.model('gh5145', { name: String }); + var MyModel = db.model('gh5394', { name: String }); MyModel.create({ name: 'test' }, function(error) { assert.ifError(error); From c2670a9f0b5fcfcafec9d7aaf73f4dfc3a0a87d8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 13:10:11 -0700 Subject: [PATCH 1726/2240] docs(aggregate): add useMongooseAggCursor docs Re: #5394 --- lib/aggregate.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index cfc824f8f6c..8d4b4f4ffcd 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -516,7 +516,9 @@ Aggregate.prototype.allowDiskUse = function(value) { * // use doc * }); * - * @param {Object} options set the cursor batch size + * @param {Object} options + * @param {Number} options.batchSize set the cursor batch size + * @param {Boolean} [options.useMongooseAggCursor] use experimental mongoose-specific aggregation cursor (for `eachAsync()` and other query cursor semantics) * @see mongodb http://mongodb.github.io/node-mongodb-native/2.0/api/AggregationCursor.html */ From 24fa1cc295b25cc240af55e1ad9168fbc89ac54d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 13:31:52 -0700 Subject: [PATCH 1727/2240] fix(query): ensure castConditions called for findOne and findOneAnd* Fix #5477 --- lib/query.js | 14 ++++++++++++++ lib/schema/embedded.js | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 105dbb75813..03b834e8038 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1343,6 +1343,8 @@ Query.prototype.collation = function(value) { */ Query.prototype._findOne = function(callback) { + this._castConditions(); + if (this._castError) { return callback(this._castError); } @@ -1971,6 +1973,12 @@ Query.prototype.findOneAndUpdate = function(criteria, doc, options, callback) { */ Query.prototype._findOneAndUpdate = function(callback) { + this._castConditions(); + + if (this._castError) { + return callback(this._castError); + } + this._findAndModify('update', callback); return this; }; @@ -2057,6 +2065,12 @@ Query.prototype.findOneAndRemove = function(conditions, options, callback) { * @api private */ Query.prototype._findOneAndRemove = function(callback) { + this._castConditions(); + + if (this._castError) { + return callback(this._castError); + } + Query.base.findOneAndRemove.call(this, callback); }; diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 7ed6f589a44..3161924b0e8 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -50,7 +50,7 @@ function Embedded(schema, path, options) { _embedded.prototype.toBSON = function() { return this.toObject({ transform: false, - retainKeyOrder: schema.options.retainKeyOrder, + retainKeyOrder: true, virtuals: false, _skipDepopulateTopLevel: true, depopulate: true, From f6e4dcec3252b2147261a329d94bd6b2154e167a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 18:15:18 -0700 Subject: [PATCH 1728/2240] fix(cursor): call next() in series when parallel option used Fix #5446 Re: https://github.com/Automattic/mongoose/pull/5298#issuecomment-313907256 Re: https://jira.mongodb.org/browse/NODE-926 --- lib/services/cursor/eachAsync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/cursor/eachAsync.js b/lib/services/cursor/eachAsync.js index 9b1b8b6d500..30d33e0ba79 100644 --- a/lib/services/cursor/eachAsync.js +++ b/lib/services/cursor/eachAsync.js @@ -42,7 +42,7 @@ module.exports = function eachAsync(next, fn, options, callback) { for (var i = 0; i < parallel; ++i) { tasks.push(next); } - async.parallel(tasks, function(error, docs) { + async.series(tasks, function(error, docs) { var initialLength = docs.length; docs = docs.filter(function(doc) { return doc != null; From 48da453744f9862bb6b75b9687c5846a3f3a67e0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 22 Jul 2017 18:58:06 -0700 Subject: [PATCH 1729/2240] test: fix tests re: #5486 --- lib/services/cursor/eachAsync.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/services/cursor/eachAsync.js b/lib/services/cursor/eachAsync.js index 9c9a2db75ac..4b2244e06bc 100644 --- a/lib/services/cursor/eachAsync.js +++ b/lib/services/cursor/eachAsync.js @@ -39,8 +39,26 @@ module.exports = function eachAsync(next, fn, options, callback) { var iterate = function(callback) { if (parallel > 1) { var tasks = []; + var finished = false; for (var i = 0; i < parallel; ++i) { - tasks.push(next); + tasks.push(function(cb) { + next(function(error, doc) { + if (finished) { + return cb(null, null); + } + + if (error) { + finished = true; + return cb(error); + } + if (!doc) { + finished = true; + return cb(null, null); + } + + return cb(null, doc); + }); + }); } async.series(tasks, function(error, docs) { if (error) { From 5ad4c9b81aac1c36a0c4329626036bb7efc9e2b4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Jul 2017 09:14:02 -0700 Subject: [PATCH 1730/2240] test(query): repro #5450 --- test/query.test.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index 71a99952191..957c78aed0a 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2019,6 +2019,29 @@ describe('Query', function() { }); }); + it('slice respects schema projections (gh-5450)', function(done) { + var gameSchema = Schema({ + name: String, + developer: { + type: String, + select: false + }, + arr: [Number] + }); + var Game = db.model('gh5450', gameSchema); + + Game.create({ name: 'Mass Effect', developer: 'BioWare', arr: [1, 2, 3] }, function(error) { + assert.ifError(error); + Game.findOne({ name: 'Mass Effect' }).slice({ arr: 1 }).exec(function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Mass Effect'); + assert.deepEqual(doc.toObject().arr, [1]); + assert.ok(!doc.developer); + done(); + }); + }); + }); + it('$exists for arrays and embedded docs (gh-4937)', function(done) { var subSchema = new Schema({ name: String From dcd3d96e78f67a06d4e94e522e8593fe012f8d2f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Jul 2017 09:14:12 -0700 Subject: [PATCH 1731/2240] fix(query): apply schema excluded paths if only projection is a $slice Fix #5450 --- lib/queryhelpers.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/queryhelpers.js b/lib/queryhelpers.js index c98d3037b60..868a0a20777 100644 --- a/lib/queryhelpers.js +++ b/lib/queryhelpers.js @@ -79,14 +79,21 @@ exports.applyPaths = function applyPaths(fields, schema) { var exclude; var keys; var ki; + var field; if (fields) { keys = Object.keys(fields); ki = keys.length; while (ki--) { - if (keys[ki][0] === '+') continue; - exclude = fields[keys[ki]] === 0; + if (keys[ki][0] === '+') { + continue; + } + field = fields[keys[ki]]; + if (typeof field === 'object' && field && field.$slice) { + continue; + } + exclude = field === 0; break; } } From ee1987eab5b5d47bc7bb2e6736d77d506970a92d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Jul 2017 10:36:02 -0700 Subject: [PATCH 1732/2240] chore: release 4.11.4 --- History.md | 19 +++++++++++++++++++ package.json | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 3bcc782cc9c..930baba3a67 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,22 @@ +4.11.4 / 2017-07-23 +=================== + * fix: handle next() errors in `eachAsync()` #5486 [lchenay](https://github.com/lchenay) + * fix(schema): propagate runSettersOnQuery option to implicitly created schemas #5479 [https://github.com/ValYouW] + * fix(query): run castConditions() correctly in update ops #5477 + * fix(query): ensure castConditions called for findOne and findOneAnd* #5477 + * docs: clarify relationship between $lookup and populate #5475 [TalhaAwan](https://github.com/TalhaAwan) + * test: add coverage for arrays of arrays [zbjornson](https://github.com/zbjornson) + * fix(middleware): ensure that error handlers for save get doc as 2nd param #5466 + * fix: handle strict: false correctly #5454 #5453 [wookieb](https://github.com/wookieb) + * fix(query): apply schema excluded paths if only projection is a $slice #5450 + * fix(query): correct discriminator handling for schema `select: false` fields in schema #5448 + * fix(cursor): call next() in series when parallel option used #5446 + * chore: load bundled driver first to avoid packaging problem #5443 [prototypeme](https://github.com/prototypeme) + * fix(query): defer condition casting until final exec #5434 + * fix(aggregate): don't rely on mongodb aggregate to put a cursor in the callback #5394 + * docs(aggregate): add useMongooseAggCursor docs #5394 + * docs(middleware): clarify context for document, query, and model middleware #5381 + 4.11.3 / 2017-07-14 =================== * fix(connection): remove .then() before resolving to prevent infinite recursion #5471 diff --git a/package.json b/package.json index 17512e6a0d6..3a4afc8e9c3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.4-pre", + "version": "4.11.4", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 9ab12389b5b4c47d46a2635655b2097bbd7ce823 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Jul 2017 10:37:18 -0700 Subject: [PATCH 1733/2240] chore: now working on 4.11.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a4afc8e9c3..d5cc565a0ca 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.4", + "version": "4.11.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From bd765b79fcc9794d615c8c42d0f49a4ace971136 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Jul 2017 10:54:59 -0700 Subject: [PATCH 1734/2240] docs(connection): clarify server/replset/mongos option deprecation with useMongoClient Fix #5442 --- docs/connections.jade | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/connections.jade b/docs/connections.jade index 3488757f6d2..2c6d9d6ec6c 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -220,10 +220,46 @@ block content [underlying MongoDB driver's `MongoClient.connect()` function](http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect). Please see the [driver documentation for this function](http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect) for options. The same is true for `connect()` and `createConnection()` if `useMongoClient` is `true`. + :markdown + You may see the following deprecation warning with `useMongoClient`: + + ``` + the server/replset/mongos options are deprecated, all their options are supported at the top level of the options object + ``` + + In older version of the MongoDB driver you had to specify distinct options for server connections, replica set connections, and mongos connections: + :js + mongoose.connect(myUri, { + server: { + socketOptions: { + socketTimeoutMS: 0, + keepAlive: true + }, + reconnectTries: 30 + }, + replset: { + socketOptions: { + socketTimeoutMS: 0, + keepAlive: true + }, + reconnectTries: 30 + } + }); + :markdown + With `useMongoClient` you can instead declare these options at the top level, without all that extra nesting. [Here's the list of all supported options](http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html). + :js + // Equivalent to the above code + mongoose.connect(myUri, { + socketTimeoutMS: 0, + keepAlive: true, + reconnectTries: 30 + }); + :markdown This deprecation is because the [MongoDB driver](https://www.npmjs.com/package/mongodb) has deprecated an API that is critical to mongoose's connection logic to support MongoDB 3.6, see [this github issue](https://github.com/Automattic/mongoose/issues/5304) + and [this blog post](http://thecodebarbarian.com/mongoose-4.11-use-mongo-client.html) for more details. h3#next Next Up From e47b34aedcba2a68ce085d1817d9ebfeff5d8cb9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Jul 2017 13:46:32 -0700 Subject: [PATCH 1735/2240] docs(connection): add mongos to example re: #5442 --- docs/connections.jade | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/connections.jade b/docs/connections.jade index 2c6d9d6ec6c..974edc9b04b 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -243,6 +243,13 @@ block content keepAlive: true }, reconnectTries: 30 + }, + mongos: { + socketOptions: { + socketTimeoutMS: 0, + keepAlive: true + }, + reconnectTries: 30 } }); :markdown From 6fe4f3d9cef68933ac8f66198d760a10210cb0b1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Jul 2017 13:55:42 -0700 Subject: [PATCH 1736/2240] test(query): repro #5455 --- test/model.findOneAndUpdate.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 97f5107c5a5..ed0a95037b1 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1173,19 +1173,21 @@ describe('model: findOneAndUpdate:', function() { var s = new Schema({ topping: {type: String, default: 'bacon'}, + numEggs: {type: Number, default: 3}, base: String - }); + }, { versionKey: null }); var Breakfast = db.model('fam-gh-860-1', s); var updateOptions = {upsert: true, setDefaultsOnInsert: true, new: true}; Breakfast.findOneAndUpdate( - {topping: 'sausage'}, + {topping: 'sausage', numEggs: 4}, {base: 'eggs'}, updateOptions, function(error, breakfast) { assert.ifError(error); assert.equal(breakfast.base, 'eggs'); assert.equal(breakfast.topping, 'sausage'); + assert.equal(breakfast.numEggs, 4); db.close(); done(); }); From 0356f61633631f67032709fbc5b36ad60b9c4c07 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 23 Jul 2017 13:59:46 -0700 Subject: [PATCH 1737/2240] fix(query): iterate over all condition keys for setDefaultsOnInsert Fix #5455 --- lib/services/setDefaultsOnInsert.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/services/setDefaultsOnInsert.js b/lib/services/setDefaultsOnInsert.js index e0939153cd2..26ead96d73d 100644 --- a/lib/services/setDefaultsOnInsert.js +++ b/lib/services/setDefaultsOnInsert.js @@ -34,7 +34,7 @@ module.exports = function(query, schema, castedDoc, options) { } var paths = Object.keys(query._conditions); - var numPaths = keys.length; + var numPaths = paths.length; for (i = 0; i < numPaths; ++i) { var path = paths[i]; var condition = query._conditions[path]; @@ -57,7 +57,8 @@ module.exports = function(query, schema, castedDoc, options) { } if (options && options.overwrite && !hasDollarUpdate) { - // Defaults will be set later + // Defaults will be set later, since we're overwriting we'll cast + // the whole update to a document return castedDoc; } From 11b63b2c1ce8052069e98b5c6de0de398473a5e3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 24 Jul 2017 17:45:02 -0700 Subject: [PATCH 1738/2240] test(query): repro #5467 --- test/query.test.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index 957c78aed0a..1ef6951afd0 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2019,6 +2019,42 @@ describe('Query', function() { }); }); + it('geojson underneath array (gh-5467)', function(done) { + var storySchema = new Schema({ + name: String, + gallery: [{ + src: String, + location: { + type: { type: String, enum: ['Point'] }, + coordinates: { type: [Number], default: void 0 } + }, + timestamp: Date + }] + }); + storySchema.index({ 'gallery.location': '2dsphere' }); + + var Story = db.model('gh5467', storySchema); + + var q = { + 'gallery.location': { + $near: { + $geometry: { + type: 'Point', + coordinates: [51.53377166666667, -0.1197471666666667] + }, + $maxDistance: 500 + } + } + }; + Story.once('index', function(error) { + assert.ifError(error); + Story.update(q, { name: 'test' }, { upsert: true }, function(error) { + assert.ifError(error); + done(); + }); + }); + }); + it('slice respects schema projections (gh-5450)', function(done) { var gameSchema = Schema({ name: String, From 4559cf4a3f87d6ba3bda29637c34af5cbf02cffa Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 24 Jul 2017 17:45:13 -0700 Subject: [PATCH 1739/2240] fix(query): don't throw StrictModeError if geo query with upsert Fix #5467 --- lib/cast.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/cast.js b/lib/cast.js index fc9a9a6719c..b7a02120190 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -188,6 +188,7 @@ module.exports = function cast(schema, obj, options, context) { } _cast(value, numbertype, context); + continue; } } From 408a20bb860acbb916dbb6f1437819099c4a98a8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 24 Jul 2017 17:46:55 -0700 Subject: [PATCH 1740/2240] style: fix lint --- test/query.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index 1ef6951afd0..249d27a2102 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2039,8 +2039,8 @@ describe('Query', function() { 'gallery.location': { $near: { $geometry: { - type: 'Point', - coordinates: [51.53377166666667, -0.1197471666666667] + type: 'Point', + coordinates: [51.53377166666667, -0.1197471666666667] }, $maxDistance: 500 } From 34c9379fca8f509810ac87903388403e211383d3 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 25 Jul 2017 09:29:07 +0200 Subject: [PATCH 1741/2240] Ensure a real parallel execution in asyncEach... ... keeping the fact that cursor.next() must be call once at time. --- lib/services/cursor/eachAsync.js | 79 ++++++++------------------------ 1 file changed, 20 insertions(+), 59 deletions(-) diff --git a/lib/services/cursor/eachAsync.js b/lib/services/cursor/eachAsync.js index 4b2244e06bc..408f05ffaa2 100644 --- a/lib/services/cursor/eachAsync.js +++ b/lib/services/cursor/eachAsync.js @@ -37,72 +37,33 @@ module.exports = function eachAsync(next, fn, options, callback) { }; var iterate = function(callback) { - if (parallel > 1) { - var tasks = []; - var finished = false; - for (var i = 0; i < parallel; ++i) { - tasks.push(function(cb) { - next(function(error, doc) { - if (finished) { - return cb(null, null); - } - - if (error) { - finished = true; - return cb(error); - } - if (!doc) { - finished = true; - return cb(null, null); - } - - return cb(null, doc); - }); - }); - } - async.series(tasks, function(error, docs) { - if (error) { - return callback(error); - } - var initialLength = docs.length; - docs = docs.filter(function(doc) { - return doc != null; - }); - var isDone = docs.length !== initialLength; - var tasks = docs.map(function(doc) { - return function(cb) { handleNextResult(doc, cb); }; - }); - async.parallel(tasks, function(error) { - if (error) { - return callback(error); - } - if (isDone) { - return callback(null); - } - setTimeout(function() { - iterate(callback); - }); - }); + var drained = false; + var nextQueue = async.queue(function(task, cb) { + if (drained) return cb(); + next(function(err, doc) { + if (err) return cb(err); + if (!doc) drained = true; + cb(null, doc); }); - } else { - return next(function(error, doc) { - if (error) { - return callback(error); - } - if (!doc) { - return callback(null); - } - handleNextResult(doc, function(error) { - if (error) { - return callback(error); - } + }, 1); + + var getAndRun = function(cb) { + nextQueue.push({}, function(err, doc) { + if (err) return cb(err); + if (!doc) return cb(); + handleNextResult(doc, function(err) { + if (err) return cb(err); // Make sure to clear the stack re: gh-4697 setTimeout(function() { - iterate(callback); + getAndRun(cb); }, 0); }); }); } + + async.times(parallel, function(n, cb) { + getAndRun(cb); + }, callback) }; return new Promise.ES6(function(resolve, reject) { From bd8e532277090250dcb3cc67a0b80cca3d676fbf Mon Sep 17 00:00:00 2001 From: lchenay Date: Tue, 25 Jul 2017 10:35:04 +0200 Subject: [PATCH 1742/2240] Fix lint --- lib/services/cursor/eachAsync.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/services/cursor/eachAsync.js b/lib/services/cursor/eachAsync.js index 408f05ffaa2..1f28db6c812 100644 --- a/lib/services/cursor/eachAsync.js +++ b/lib/services/cursor/eachAsync.js @@ -46,7 +46,7 @@ module.exports = function eachAsync(next, fn, options, callback) { cb(null, doc); }); }, 1); - + var getAndRun = function(cb) { nextQueue.push({}, function(err, doc) { if (err) return cb(err); @@ -55,15 +55,15 @@ module.exports = function eachAsync(next, fn, options, callback) { if (err) return cb(err); // Make sure to clear the stack re: gh-4697 setTimeout(function() { - getAndRun(cb); + getAndRun(cb); }, 0); }); }); - } + }; async.times(parallel, function(n, cb) { getAndRun(cb); - }, callback) + }, callback); }; return new Promise.ES6(function(resolve, reject) { From 6e02dbb384e62eaebb596682363ca6f28d85fcd8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 25 Jul 2017 10:16:06 -0700 Subject: [PATCH 1743/2240] test(document): repro #5473 --- test/document.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 860593c8c9d..9438861cd23 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4328,6 +4328,33 @@ describe('document', function() { }); }); + it('dotted virtuals in toObject (gh-5473)', function(done) { + var schema = new mongoose.Schema({}, { + toObject: { virtuals: true }, + toJSON: { virtuals: true } + }); + schema.virtual('test.a').get(function() { + return 1; + }); + schema.virtual('test.b').get(function() { + return 2; + }); + + var Model = mongoose.model('gh5473', schema); + + var m = new Model({}); + assert.deepEqual(m.toJSON().test, { + a: 1, + b: 2 + }); + assert.deepEqual(m.toObject().test, { + a: 1, + b: 2 + }); + assert.equal(m.toObject({ virtuals: false }).test, void 0); + done(); + }); + it('consistent setter context for single nested (gh-5363)', function(done) { var contentSchema = new Schema({ blocks: [{ type: String }], From 2ede28b1fe4db0895a4dcb19275adc8349dc8e24 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 25 Jul 2017 10:16:33 -0700 Subject: [PATCH 1744/2240] fix(document): handle dotted virtuals in toJSON output Fix #5473 --- lib/document.js | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/document.js b/lib/document.js index fa290a7a376..74d953ae898 100644 --- a/lib/document.js +++ b/lib/document.js @@ -9,6 +9,7 @@ var Schema = require('./schema'); var ObjectExpectedError = require('./error/objectExpected'); var StrictModeError = require('./error/strict'); var ValidatorError = require('./schematype').ValidatorError; +var VirtualType = require('./virtualtype'); var utils = require('./utils'); var clone = utils.clone; var isMongooseObject = utils.isMongooseObject; @@ -948,9 +949,13 @@ Document.prototype.get = function(path, type) { adhoc = Schema.interpretAsType(path, type, this.schema.options); } - var schema = this.$__path(path) || this.schema.virtualpath(path), - pieces = path.split('.'), - obj = this._doc; + var schema = this.$__path(path) || this.schema.virtualpath(path); + var pieces = path.split('.'); + var obj = this._doc; + + if (schema instanceof VirtualType) { + return schema.applyGetters(null, this); + } for (var i = 0, l = pieces.length; i < l; i++) { obj = obj === null || obj === void 0 @@ -2328,6 +2333,7 @@ function applyGetters(self, json, type, options) { var schema = self.schema; var paths = Object.keys(schema[type]); var i = paths.length; + var numPaths = i; var path; var cur = self._doc; var v; @@ -2336,6 +2342,26 @@ function applyGetters(self, json, type, options) { return json; } + if (type === 'virtuals') { + for (i = 0; i < numPaths; ++i) { + path = paths[i]; + parts = path.split('.'); + v = self.get(path); + if (v === void 0) { + continue; + } + plen = parts.length; + cur = json; + for (var j = 0; j < plen - 1; ++j) { + cur[parts[j]] = cur[parts[j]] || {}; + cur = cur[parts[j]]; + } + cur[parts[plen - 1]] = v; + } + + return json; + } + while (i--) { path = paths[i]; From 0f053f1a56875040b6c80b3ad46e2660ae945dee Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 26 Jul 2017 10:33:24 -0700 Subject: [PATCH 1745/2240] fix(model): make DocumentNotFoundError take precedence over VersionError Re: vkarpov15/mongoose-unique-array#2 --- lib/model.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/model.js b/lib/model.js index 641e922999a..bc437da2204 100644 --- a/lib/model.js +++ b/lib/model.js @@ -4,7 +4,7 @@ var Aggregate = require('./aggregate'); var Document = require('./document'); -var DocumentNotFoundError = require('./error/notFound'); +var DocumentNotFoundError = require('./error').DocumentNotFoundError; var DivergentArrayError = require('./error').DivergentArrayError; var EventEmitter = require('events').EventEmitter; var OverwriteModelError = require('./error').OverwriteModelError; @@ -234,6 +234,15 @@ Model.prototype.$__save = function(options, callback) { } } + if (_this.schema.options && + _this.schema.options.saveErrorIfNotFound && + numAffected <= 0) { + error = new DocumentNotFoundError(result.$where); + return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { + callback(error); + }); + } + // was this an update that required a version bump? if (_this.$__.version && !_this.$__.inserting) { var doIncrement = VERSION_INC === (VERSION_INC & _this.$__.version); @@ -253,15 +262,6 @@ Model.prototype.$__save = function(options, callback) { } } - if (_this.schema.options && - _this.schema.options.saveErrorIfNotFound && - numAffected <= 0) { - error = new DocumentNotFoundError(result.$where); - return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) { - callback(error); - }); - } - _this.emit('save', _this, numAffected); _this.constructor.emit('save', _this, numAffected); callback(null, _this, numAffected); From e659958fe80c5d03a7cb89a4e43804c1dd3ddda2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 26 Jul 2017 10:34:13 -0700 Subject: [PATCH 1746/2240] fix(error): allow overwriting DocumentNotFoundError message Re: vkarpov15/mongoose-unique-array#2 --- lib/error.js | 12 +++++++++++- lib/error/messages.js | 2 ++ lib/error/notFound.js | 13 +++++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/error.js b/lib/error.js index bee4d22017f..b0e8ff53f82 100644 --- a/lib/error.js +++ b/lib/error.js @@ -42,12 +42,22 @@ MongooseError.messages = require('./error/messages'); // backward compat MongooseError.Messages = MongooseError.messages; +/** + * This error will be called when `save()` fails because the underlying + * document was not found. The constructor takes one parameter, the + * conditions that mongoose passed to `update()` when trying to update + * the document. + * + * @api public + */ + +MongooseError.DocumentNotFoundError = require('./error/notFound'); + /*! * Expose subclasses */ MongooseError.CastError = require('./error/cast'); -MongooseError.DocumentNotFoundError = require('./error/notFound'); MongooseError.ValidationError = require('./error/validation'); MongooseError.ValidatorError = require('./error/validator'); MongooseError.VersionError = require('./error/version'); diff --git a/lib/error/messages.js b/lib/error/messages.js index 88ddf6e89f8..56950eb3cd1 100644 --- a/lib/error/messages.js +++ b/lib/error/messages.js @@ -23,6 +23,8 @@ var msg = module.exports = exports = {}; +msg.DocumentNotFoundError = null; + msg.general = {}; msg.general.default = 'Validator failed for path `{PATH}` with value `{VALUE}`'; msg.general.required = 'Path `{PATH}` is required.'; diff --git a/lib/error/notFound.js b/lib/error/notFound.js index 24d608a9ff3..b09d7319f8c 100644 --- a/lib/error/notFound.js +++ b/lib/error/notFound.js @@ -14,8 +14,17 @@ var util = require('util'); */ function DocumentNotFoundError(query) { - MongooseError.call(this, 'No document found for query "' + - util.inspect(query) + '"'); + var msg; + var messages = MongooseError.messages; + if (messages.DocumentNotFoundError != null) { + msg = typeof messages.DocumentNotFoundError === 'function' ? + messages.DocumentNotFoundError(query) : + messages.DocumentNotFoundError; + } else { + msg = 'No document found for query "' + util.inspect(query) + '"'; + } + + MongooseError.call(this, msg); if (Error.captureStackTrace) { Error.captureStackTrace(this); From 20cce65a0248080075d5c70697996a0643c03b1a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Jul 2017 09:53:27 -0700 Subject: [PATCH 1747/2240] docs: warn not to use arrow functions for statics and methods Fix #5458 --- docs/guide.jade | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/guide.jade b/docs/guide.jade index 4d660780ba9..553ee21371f 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -109,6 +109,9 @@ block content .important :markdown Overwriting a default mongoose document method may lead to unpredictable results. See [this](./api.html#schema_Schema.reserved) for more details. + .important + :markdown + Do **not** declare methods using ES6 arrow functions (`=>`). Arrow functions [explicitly prevent binding `this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_this), so your method will **not** have access to the document and the above examples will not work. h3#statics Statics :markdown @@ -125,6 +128,10 @@ block content console.log(animals); }); + .important + :markdown + Do **not** declare statics using ES6 arrow functions (`=>`). Arrow functions [explicitly prevent binding `this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_this), so the above examples will not work because of the value of `this`. + h3#query-helpers Query Helpers :markdown You can also add query helper functions, which are like instance methods From 9e4fd1f0dff8e48a8aa4f3c2b6f454c13a356658 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Jul 2017 10:15:58 -0700 Subject: [PATCH 1748/2240] test(populate): repro #5460 --- test/model.populate.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 157caa52cea..c7d932b89d0 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5300,6 +5300,25 @@ describe('model: populate:', function() { }); }); + it('populate with missing schema (gh-5460)', function(done) { + var refSchema = new mongoose.Schema({ + name: String + }); + + var Ref = db.model('gh5460', refSchema); + + var schema = new mongoose.Schema({ + ref: { type: mongoose.Schema.Types.ObjectId, ref: 'gh5460' } + }); + + var Model = db.model('gh5460_0', schema); + + var q = Model.find().read('secondaryPreferred').populate('ref'); + assert.equal(q._mongooseOptions.populate['ref'].options.readPreference.mode, + 'secondaryPreferred'); + done(); + }); + it('virtuals with justOne false and foreign field not found (gh-5336)', function(done) { var BandSchema = new mongoose.Schema({ name: String, From 46031246d92c8c3942635db5b24b55e475a753d9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Jul 2017 10:17:23 -0700 Subject: [PATCH 1749/2240] fix(populate): propagate readPreference from query to populate queries by default Fix #5460 --- lib/query.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 03b834e8038..24b4ebfe518 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3050,7 +3050,20 @@ Query.prototype.populate = function() { return this; } + var i; + var res = utils.populate.apply(null, arguments); + + // Propagate readPreference from parent query, unless one already specified + if (this.options && this.options.readPreference != null) { + for (i = 0; i < res.length; ++i) { + if (!res[i].options || res[i].options.readPreference == null) { + res[i].options = res[i].options || {}; + res[i].options.readPreference = this.options.readPreference; + } + } + } + var opts = this._mongooseOptions; if (!utils.isObject(opts.populate)) { @@ -3059,7 +3072,7 @@ Query.prototype.populate = function() { var pop = opts.populate; - for (var i = 0; i < res.length; ++i) { + for (i = 0; i < res.length; ++i) { var path = res[i].path; if (pop[path] && pop[path].populate && res[i].populate) { res[i].populate = pop[path].populate.concat(res[i].populate); From d16a7fa1add2e27a19994e02a9bb52cae1b7bc9d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Jul 2017 10:23:20 -0700 Subject: [PATCH 1750/2240] style: fix lint --- test/model.populate.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index c7d932b89d0..cd4a168abad 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5305,7 +5305,7 @@ describe('model: populate:', function() { name: String }); - var Ref = db.model('gh5460', refSchema); + db.model('gh5460', refSchema); var schema = new mongoose.Schema({ ref: { type: mongoose.Schema.Types.ObjectId, ref: 'gh5460' } From 845aca3c4b4b44211b8b5325bf0d50c10443d545 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 28 Jul 2017 19:38:51 -0700 Subject: [PATCH 1751/2240] docs(document): copy docs for save from model to doc Fix #5493 --- lib/document.js | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/document.js b/lib/document.js index 74d953ae898..020a3babe20 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1650,6 +1650,44 @@ Document.prototype.$markValid = function(path) { } }; +/** + * Saves this document. + * + * ####Example: + * + * product.sold = Date.now(); + * product.save(function (err, product, numAffected) { + * if (err) .. + * }) + * + * The callback will receive three parameters + * + * 1. `err` if an error occurred + * 2. `product` which is the saved `product` + * 3. `numAffected` will be 1 when the document was successfully persisted to MongoDB, otherwise 0. Unless you tweak mongoose's internals, you don't need to worry about checking this parameter for errors - checking `err` is sufficient to make sure your document was properly saved. + * + * As an extra measure of flow control, save will return a Promise. + * ####Example: + * product.save().then(function(product) { + * ... + * }); + * + * For legacy reasons, mongoose stores object keys in reverse order on initial + * save. That is, `{ a: 1, b: 2 }` will be saved as `{ b: 2, a: 1 }` in + * MongoDB. To override this behavior, set + * [the `toObject.retainKeyOrder` option](http://mongoosejs.com/docs/api.html#document_Document-toObject) + * to true on your schema. + * + * @param {Object} [options] options optional options + * @param {Object} [options.safe] overrides [schema's safe option](http://mongoosejs.com//docs/guide.html#safe) + * @param {Boolean} [options.validateBeforeSave] set to false to save without validating. + * @param {Function} [fn] optional callback + * @method save + * @return {Promise} Promise + * @api public + * @see middleware http://mongoosejs.com/docs/middleware.html + */ + /** * Checks if a path is invalid * From b71e319be8dde03111227e9e3f6023fad03f92d2 Mon Sep 17 00:00:00 2001 From: Talha Awan Date: Sat, 29 Jul 2017 16:23:38 +0500 Subject: [PATCH 1752/2240] fix: wrong reference link to $lookup --- docs/populate.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/populate.jade b/docs/populate.jade index a6fe6ffd0b5..8ef30d8d16a 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -3,7 +3,7 @@ extends layout block content h2 Population :markdown - MongoDB has the join-like ([$lookup](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/)) aggregation operator in versions >= 3.2. Mongoose has a more powerful alternative called `populate()`, which lets you reference documents in other collections. + MongoDB has the join-like [$lookup](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/) aggregation operator in versions >= 3.2. Mongoose has a more powerful alternative called `populate()`, which lets you reference documents in other collections. Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s). We may populate a single document, multiple documents, plain object, multiple plain objects, or all objects returned from a query. Let's look at some examples. :js From 3bace2d6e64c3b2f12df5dffeb761f5629aa609c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 29 Jul 2017 15:54:27 -0700 Subject: [PATCH 1753/2240] test(populate): repro #5468 --- test/model.populate.test.js | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index cd4a168abad..495809bf247 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5180,6 +5180,47 @@ describe('model: populate:', function() { }); }); + it('retains limit when using cursor (gh-5468)', function(done) { + var refSchema = new mongoose.Schema({ + _id: Number, + name: String + }, { versionKey: null }); + var Ref = db.model('gh5468', refSchema); + + var testSchema = new mongoose.Schema({ + _id: Number, + prevnxt: [{ type: Number, ref: 'gh5468' }] + }); + var Test = db.model('gh5468_0', testSchema); + + var docs = [1, 2, 3, 4, 5, 6].map(function(i) { + return { _id: i }; + }); + Ref.create(docs, function(error) { + assert.ifError(error); + var docs = [ + { _id: 1, prevnxt: [1, 2, 3] }, + { _id: 2, prevnxt: [4, 5, 6] } + ]; + Test.create(docs, function(error) { + assert.ifError(error); + + var cursor = Test. + find(). + populate({ path: 'prevnxt', options: { limit: 2 } }). + cursor(); + + cursor.on('data', function(doc) { + assert.equal(doc.prevnxt.length, 2); + }); + cursor.on('error', done); + cursor.on('end', function() { + done(); + }); + }); + }); + }); + it('virtuals + doc.populate() (gh-5311)', function(done) { var parentSchema = new Schema({ name: String }); var childSchema = new Schema({ From 4a28e919b218ca3db99fd1eaa06601f5417d558a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 29 Jul 2017 15:59:16 -0700 Subject: [PATCH 1754/2240] fix(populate): restore user-provided limit after mutating so cursor() works with populate limit Fix #5468 --- lib/model.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/model.js b/lib/model.js index bc437da2204..05d9dbbdbcb 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3105,6 +3105,10 @@ function populate(model, docs, options, callback) { } function next(options, assignmentOpts, err, valsFromDb) { + if (mod.options.options && mod.options.options.limit) { + mod.options.options.limit = assignmentOpts.originalLimit; + } + if (err) return callback(err); vals = vals.concat(valsFromDb); _assign(null, vals, options, assignmentOpts); From ee2f3ed190a2606aecea9d8594500617bee063c4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 30 Jul 2017 12:28:38 -0700 Subject: [PATCH 1755/2240] chore: release 4.11.5 --- History.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 930baba3a67..12beb8a61f8 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,16 @@ +4.11.5 / 2017-07-30 +=================== + * docs: fix link to $lookup #5516 [TalhaAwan](https://github.com/TalhaAwan) + * fix: better parallelization for eachAsync #5502 [lchenay](https://github.com/lchenay) + * docs(document): copy docs for save from model to doc #5493 + * fix(document): handle dotted virtuals in toJSON output #5473 + * fix(populate): restore user-provided limit after mutating so cursor() works with populate limit #5468 + * fix(query): don't throw StrictModeError if geo query with upsert #5467 + * fix(populate): propagate readPreference from query to populate queries by default #5460 + * docs: warn not to use arrow functions for statics and methods #5458 + * fix(query): iterate over all condition keys for setDefaultsOnInsert #5455 + * docs(connection): clarify server/replset/mongos option deprecation with useMongoClient #5442 + 4.11.4 / 2017-07-23 =================== * fix: handle next() errors in `eachAsync()` #5486 [lchenay](https://github.com/lchenay) diff --git a/package.json b/package.json index d5cc565a0ca..820d0c5dc87 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.5-pre", + "version": "4.11.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 33ca169d986e9be8b79e267374531d611cff1eed Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 30 Jul 2017 12:30:17 -0700 Subject: [PATCH 1756/2240] chore: now working on 4.11.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 820d0c5dc87..c74e50bfe82 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.5", + "version": "4.11.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a7df1594d7e973e3545f02b5615cc5f96f61e218 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 2 Aug 2017 21:12:06 -0700 Subject: [PATCH 1757/2240] fix(connection): emit reconnected and disconnected events correctly with useMongoClient Fix #5498 --- lib/connection.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 8b0d3a4cab5..d713fb58500 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -737,6 +737,14 @@ Connection.prototype.openUri = function(uri, options, callback) { } return reject(error); } + // Backwards compat for mongoose 4.x + db.on('reconnect', function() { + _this.emit('reconnected'); + }); + db.s.topology.on('close', function() { + _this.emit('disconnected'); + }); + _this.db = db; _this.readyState = STATES.connected; From 26bd8cf1336d2d6d569fd5de3816e041d9404bd1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 3 Aug 2017 09:35:10 -0700 Subject: [PATCH 1758/2240] test(populate): repro #5431 --- test/model.populate.test.js | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 495809bf247..8d12177ad7f 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5121,6 +5121,44 @@ describe('model: populate:', function() { catch(done); }); + it('nested virtuals if top-level prop doesnt exist (gh-5431)', function(done) { + var personSchema = new mongoose.Schema({ + name: String, + band: String + }); + var bandSchema = new mongoose.Schema({ + name: String, + data: { + field: String + } + }); + bandSchema.virtual('data.members', { + ref: 'gh5431', + localField: 'name', + foreignField: 'band', + justOne: false + }); + + bandSchema.set('toObject', { virtuals: true }); + + var Person = db.model('gh5431', personSchema); + var Band = db.model('gh5431_0', bandSchema); + + Band.create({ name: 'Motley Crue', data: {} }). + then(function() { + return Person.create({ name: 'Vince Neil', band: 'Motley Crue' }); + }). + then(function() { + return Band.findOne({}).populate('data.members'); + }). + then(function(band) { + assert.equal(band.data.members.length, 1); + assert.equal(band.data.members[0].name, 'Vince Neil'); + done(); + }). + catch(done); + }); + it('nested virtuals + doc.populate() (gh-5240)', function(done) { var parentSchema = new Schema({ name: String }); var childSchema = new Schema({ From a8c7c0532713219a20fafd12cc549292d4048314 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 3 Aug 2017 09:44:38 -0700 Subject: [PATCH 1759/2240] fix(populate): ensure nested virtual populate gets set even if top-level property is null Fix #5431 --- lib/model.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/model.js b/lib/model.js index 05d9dbbdbcb..119294134fb 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3246,6 +3246,14 @@ function assignVals(o) { // the actual doc to set rather than setting `_doc` directly mpath.set(o.path, rawIds[i], docs[i]); } else { + var parts = o.path.split('.'); + var cur = docs[i]; + for (var j = 0; j < parts.length - 1; ++j) { + if (cur[parts[j]] == null) { + cur[parts[j]] = {}; + } + cur = cur[parts[j]]; + } utils.setValue(o.path, rawIds[i], docs[i], setValue); } } From 9db4fdbb7b7218f5388a912622482aae5b3dd0d1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 3 Aug 2017 09:45:26 -0700 Subject: [PATCH 1760/2240] chore: add lock file --- package-lock.json | 3088 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3088 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000000..b2de963a358 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3088 @@ +{ + "name": "mongoose", + "version": "4.11.6-pre", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "accepts": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", + "dev": true, + "requires": { + "mime-types": "2.1.16", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", + "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==", + "dev": true + }, + "acorn-es7-plugin": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz", + "integrity": "sha1-8u4fMiipDurRJF+asZIusucdM2s=", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "acquit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/acquit/-/acquit-0.4.1.tgz", + "integrity": "sha1-hGur7RTm5JpkqgiFuYpbqaJHd70=", + "dev": true, + "requires": { + "commander": "2.5.0", + "esprima": "https://github.com/ariya/esprima/archive/85fc2f4b6ad109a86d80d9821f52b5b38d0105c0.tar.gz", + "marked": "0.3.5", + "underscore": "1.5.2" + }, + "dependencies": { + "marked": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.5.tgz", + "integrity": "sha1-QROhWsXXvKFYpargciRYe5+hW5Q=", + "dev": true + } + } + }, + "acquit-ignore": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/acquit-ignore/-/acquit-ignore-0.0.3.tgz", + "integrity": "sha1-U20adFyqaGf/oILwlJmvzjIn3vo=", + "dev": true + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "async": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz", + "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=", + "requires": { + "lodash": "4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + } + } + }, + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.25.0.tgz", + "integrity": "sha1-fdQrBGPHQunVKW3rPsZ6kyLa1yk=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-generator": "6.25.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.24.1", + "babel-runtime": "6.25.0", + "babel-template": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0", + "babylon": "6.17.4", + "convert-source-map": "1.5.0", + "debug": "2.6.8", + "json5": "0.5.1", + "lodash": "4.16.6", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.7", + "slash": "1.0.0", + "source-map": "0.5.6" + }, + "dependencies": { + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.25.0.tgz", + "integrity": "sha1-M6GvcNXyiQrrRlpKd5PB32qeqfw=", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.25.0", + "babel-types": "6.25.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.16.6", + "source-map": "0.5.6", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + } + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.25.0", + "babel-template": "6.25.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.25.0" + } + }, + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", + "dev": true, + "requires": { + "babel-runtime": "6.25.0", + "core-js": "2.4.1", + "regenerator-runtime": "0.10.5" + } + }, + "babel-register": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", + "integrity": "sha1-fhDhOi9xBlvfrVoXh7pFvKbe118=", + "dev": true, + "requires": { + "babel-core": "6.25.0", + "babel-runtime": "6.25.0", + "core-js": "2.4.1", + "home-or-tmp": "2.0.0", + "lodash": "4.16.6", + "mkdirp": "0.5.1", + "source-map-support": "0.4.15" + } + }, + "babel-runtime": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", + "integrity": "sha1-M7mOql1IK7AajRqmtDetKwGuxBw=", + "dev": true, + "requires": { + "core-js": "2.4.1", + "regenerator-runtime": "0.10.5" + } + }, + "babel-template": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.25.0.tgz", + "integrity": "sha1-ZlJBFmt8KqTGGdceGSlpVSsQwHE=", + "dev": true, + "requires": { + "babel-runtime": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0", + "babylon": "6.17.4", + "lodash": "4.16.6" + } + }, + "babel-traverse": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.25.0.tgz", + "integrity": "sha1-IldJfi/NGbie3BPEyROB+VEklvE=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.25.0", + "babel-types": "6.25.0", + "babylon": "6.17.4", + "debug": "2.6.8", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.16.6" + }, + "dependencies": { + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + } + } + }, + "babel-types": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.25.0.tgz", + "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=", + "dev": true, + "requires": { + "babel-runtime": "6.25.0", + "esutils": "2.0.2", + "lodash": "4.16.6", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.17.4", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.4.tgz", + "integrity": "sha512-kChlV+0SXkjE0vUn9OZ7pBMWRFd8uq3mZe8x1K6jhuNcAFAtEnjchFAqB+dYEXKyd+JpT6eppRR78QAr5gTsUw==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "benchmark": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.2.tgz", + "integrity": "sha1-BnbYLlYNgtLzF/gs8IWEg5Vae/4=", + "dev": true, + "requires": { + "lodash": "4.16.6", + "platform": "1.3.4" + } + }, + "bluebird": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "bson": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", + "integrity": "sha1-k8ENOeqltYQVy8QFLz5T5WKwtyw=" + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, + "call-signature": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/call-signature/-/call-signature-0.0.2.tgz", + "integrity": "sha1-qEq8glpV70yysCi9dOIFpluaSZY=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "cli-width": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", + "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "commander": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.5.0.tgz", + "integrity": "sha1-13e2pNhH1CPl1HXahkKUrB/1qp0=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.2.7", + "typedarray": "0.0.6" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", + "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "core-js": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.26" + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.1" + } + }, + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "diff-match-patch": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.0.tgz", + "integrity": "sha1-HMPIOkkNZ/ldkeOfatHy4Ia2MEg=", + "dev": true + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "dox": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/dox/-/dox-0.3.1.tgz", + "integrity": "sha1-38RsSojRvLFTp4Q3H5OtN2ukmXs=", + "dev": true, + "requires": { + "commander": "0.6.1", + "github-flavored-markdown": "1.0.1" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + } + } + }, + "eastasianwidth": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.1.1.tgz", + "integrity": "sha1-RNZW3p2kFWlEZzNTZfsxR7hXK3w=", + "dev": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "empower": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/empower/-/empower-1.2.3.tgz", + "integrity": "sha1-bw2nNEf07dg4/sXGAxOoi6XLhSs=", + "dev": true, + "requires": { + "core-js": "2.4.1", + "empower-core": "0.6.2" + } + }, + "empower-core": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-0.6.2.tgz", + "integrity": "sha1-Wt71ZgiOMfuoC6CjbfR9cJQWkUQ=", + "dev": true, + "requires": { + "call-signature": "0.0.2", + "core-js": "2.4.1" + } + }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", + "dev": true + }, + "es5-ext": { + "version": "0.10.26", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.26.tgz", + "integrity": "sha1-UbISilMbcMT2dkCTpzy+u4IYY3I=", + "dev": true, + "requires": { + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", + "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.26", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.26", + "es6-iterator": "2.0.1", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.26", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.26" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.26", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-2.4.0.tgz", + "integrity": "sha1-v7OO/Lf5mBiApyS8LmHSFAku46k=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.8", + "doctrine": "1.5.0", + "es6-map": "0.1.5", + "escope": "3.6.0", + "espree": "3.4.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "1.3.1", + "glob": "6.0.4", + "globals": "8.18.0", + "ignore": "2.2.19", + "inquirer": "0.12.0", + "is-my-json-valid": "2.16.0", + "is-resolvable": "1.0.0", + "js-yaml": "3.9.1", + "json-stable-stringify": "1.0.1", + "lodash": "4.16.6", + "mkdirp": "0.5.1", + "optionator": "0.8.2", + "path-is-absolute": "1.0.1", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "resolve": "1.4.0", + "shelljs": "0.5.3", + "strip-json-comments": "1.0.4", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + } + }, + "espree": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", + "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", + "dev": true, + "requires": { + "acorn": "5.1.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "https://github.com/ariya/esprima/archive/85fc2f4b6ad109a86d80d9821f52b5b38d0105c0.tar.gz", + "integrity": "sha1-toewHi8U14sGe4o8gEfmmHLXdow=", + "dev": true + }, + "espurify": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.7.0.tgz", + "integrity": "sha1-HFz2y8zDLm9jk4C9T5kfq5up0iY=", + "dev": true, + "requires": { + "core-js": "2.4.1" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", + "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.26" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "express": { + "version": "4.15.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", + "integrity": "sha1-urZdDwOqgMNYQIly/HAPkWlEtmI=", + "dev": true, + "requires": { + "accepts": "1.3.3", + "array-flatten": "1.1.1", + "content-disposition": "0.5.2", + "content-type": "1.0.2", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.7", + "depd": "1.1.1", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.0", + "finalhandler": "1.0.3", + "fresh": "0.5.0", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.1", + "path-to-regexp": "0.1.7", + "proxy-addr": "1.1.5", + "qs": "6.4.0", + "range-parser": "1.2.0", + "send": "0.15.3", + "serve-static": "1.12.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1", + "type-is": "1.6.15", + "utils-merge": "1.0.0", + "vary": "1.1.1" + }, + "dependencies": { + "debug": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "file-entry-cache": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-1.3.1.tgz", + "integrity": "sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=", + "dev": true, + "requires": { + "flat-cache": "1.2.2", + "object-assign": "4.1.1" + } + }, + "fileset": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-0.2.1.tgz", + "integrity": "sha1-WI74lzxmI7KnbfRlEFaWuWqsgGc=", + "dev": true, + "requires": { + "glob": "5.0.15", + "minimatch": "2.0.10" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "finalhandler": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", + "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk=", + "dev": true, + "requires": { + "debug": "2.6.7", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.1", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "flat-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", + "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "forwarded": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", + "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=", + "dev": true + }, + "fresh": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", + "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "gaze": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.3.4.tgz", + "integrity": "sha1-X5S92gr+U7xxCWm81vKCVI1gwnk=", + "dev": true, + "requires": { + "fileset": "0.1.8", + "minimatch": "0.2.14" + }, + "dependencies": { + "fileset": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-0.1.8.tgz", + "integrity": "sha1-UGuRqTluqn4y+0KoQHfHoMc2t0E=", + "dev": true, + "requires": { + "glob": "3.2.11", + "minimatch": "0.2.14" + } + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + }, + "dependencies": { + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "github-flavored-markdown": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/github-flavored-markdown/-/github-flavored-markdown-1.0.1.tgz", + "integrity": "sha1-kzYbh6McJXkNnIGht5ghSnN+qzg=", + "dev": true + }, + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globals": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz", + "integrity": "sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ=", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "handlebars": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", + "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.7.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "highlight.js": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-7.0.1.tgz", + "integrity": "sha1-QuRhuYoNPE+QzQtmg2TGXAi8bdA=", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "hooks-fixed": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.0.tgz", + "integrity": "sha1-oB2JTVKsf2WZu7H2PfycQR33DLo=" + }, + "http-errors": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", + "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=", + "dev": true, + "requires": { + "depd": "1.1.0", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + }, + "dependencies": { + "depd": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", + "dev": true + } + } + }, + "ignore": { + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-2.2.19.tgz", + "integrity": "sha1-TIRaYfflC0pBD2FWqqOLatleDI8=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.1.0", + "figures": "1.7.0", + "lodash": "4.16.6", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "ipaddr.js": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", + "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=", + "dev": true + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-my-json-valid": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", + "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true, + "requires": { + "tryit": "1.0.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "istanbul": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.4.tgz", + "integrity": "sha1-6M9xjf7bcTyDNKuf+t418QQtKlY=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "fileset": "0.2.1", + "handlebars": "4.0.10", + "js-yaml": "3.9.1", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "jasmine-growl-reporter": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/jasmine-growl-reporter/-/jasmine-growl-reporter-0.0.3.tgz", + "integrity": "sha1-uHrlUeNZ0orVIXdl6u9sB7dj9sg=", + "dev": true, + "requires": { + "growl": "1.7.0" + }, + "dependencies": { + "growl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz", + "integrity": "sha1-3i1mE20ALhErpw8/EMMc98NQsto=", + "dev": true + } + } + }, + "jasmine-node": { + "version": "1.14.5", + "resolved": "https://registry.npmjs.org/jasmine-node/-/jasmine-node-1.14.5.tgz", + "integrity": "sha1-GOg5e4VpJO53ADZmw3MbWupQw50=", + "dev": true, + "requires": { + "coffee-script": "1.12.7", + "gaze": "0.3.4", + "jasmine-growl-reporter": "0.0.3", + "jasmine-reporters": "1.0.2", + "mkdirp": "0.3.5", + "requirejs": "2.3.4", + "underscore": "1.5.2", + "walkdir": "0.0.11" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + } + } + }, + "jasmine-reporters": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-1.0.2.tgz", + "integrity": "sha1-q2E+1Zd9x0h+hbPBL2qOqNsq3jE=", + "dev": true, + "requires": { + "mkdirp": "0.3.5" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + } + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", + "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "kareem": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz", + "integrity": "sha1-4+QQHZ3P3imXadr0tNtk2JXRdEg=" + }, + "kerberos": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/kerberos/-/kerberos-0.0.17.tgz", + "integrity": "sha1-KaZ8CxJ7+lK907U7e4yGWamghPg=", + "dev": true, + "requires": { + "nan": "2.0.9" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lodash": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.6.tgz", + "integrity": "sha1-0iyaxmAojzhD4Wun0rXQbMon13c=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "markdown": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/markdown/-/markdown-0.3.1.tgz", + "integrity": "sha1-XZXBqGDRSFNSl4MqFX5L5Z6YgNQ=", + "dev": true + }, + "marked": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz", + "integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "mime": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", + "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=", + "dev": true + }, + "mime-db": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", + "integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg=", + "dev": true + }, + "mime-types": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", + "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=", + "dev": true, + "requires": { + "mime-db": "1.29.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.2.0.tgz", + "integrity": "sha1-fcT0XlCIB1FxpoiWgU5q6et6heM=", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.5", + "glob": "7.0.5", + "growl": "1.9.2", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "glob": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "mongodb": { + "version": "2.2.27", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.27.tgz", + "integrity": "sha1-NBIgNNtm2YO89qta2yaiSnD+9uY=", + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.11", + "readable-stream": "2.2.7" + } + }, + "mongodb-core": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.11.tgz", + "integrity": "sha1-HDh3bOsXSZepnCiGDu2QKNqbPho=", + "requires": { + "bson": "1.0.4", + "require_optional": "1.0.1" + } + }, + "mongodb-topology-manager": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/mongodb-topology-manager/-/mongodb-topology-manager-1.0.11.tgz", + "integrity": "sha1-GXDHRbhe36SAEQRaj+bQP2W1ofA=", + "dev": true, + "requires": { + "babel-core": "6.25.0", + "babel-polyfill": "6.23.0", + "bluebird": "3.5.0", + "co": "4.6.0", + "es6-promise": "3.2.1", + "kerberos": "0.0.17", + "mkdirp": "0.5.1", + "mongodb-core": "1.3.21", + "rimraf": "2.6.1" + }, + "dependencies": { + "bson": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz", + "integrity": "sha1-5louPHUH/63kEJvHV1p25Q+NqRU=", + "dev": true + }, + "mongodb-core": { + "version": "1.3.21", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.21.tgz", + "integrity": "sha1-/hKee+4rOybBQJ3gKrYNA/YpHMo=", + "dev": true, + "requires": { + "bson": "0.4.23", + "require_optional": "1.0.1" + } + } + } + }, + "mongoose-long": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/mongoose-long/-/mongoose-long-0.1.1.tgz", + "integrity": "sha1-zDLgWwz1DIXiWhk1nUOpNv6VBaM=", + "dev": true + }, + "mpath": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz", + "integrity": "sha1-elj3iem1/TyUUgY0FXlg8mvV70Q=" + }, + "mpromise": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz", + "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" + }, + "mquery": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.1.tgz", + "integrity": "sha1-mrNnSXFIAP8LtTpoHOS8TV8HyHs=", + "requires": { + "bluebird": "2.10.2", + "debug": "2.6.8", + "regexp-clone": "0.0.1", + "sliced": "0.0.5" + }, + "dependencies": { + "bluebird": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz", + "integrity": "sha1-AkpVFylTCIV/FPkfEQb8O1VfRGs=" + }, + "sliced": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", + "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "muri": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/muri/-/muri-1.2.2.tgz", + "integrity": "sha1-YxmBMmUNsIoEzHnM0A3Tia/SYxw=" + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + }, + "nan": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.0.9.tgz", + "integrity": "sha1-0Cp3D0Z3iELM65ThfKsx/8cjSgU=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "node-static": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/node-static/-/node-static-0.7.7.tgz", + "integrity": "sha1-kwgdg02b2dg3N3mN89o81TjokIo=", + "dev": true, + "requires": { + "colors": "1.1.2", + "mime": "1.3.6", + "optimist": "0.6.1" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "platform": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.4.tgz", + "integrity": "sha1-bw+xftqqSPIUQrOpdcBjEw8cPr0=", + "dev": true + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "power-assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/power-assert/-/power-assert-1.4.1.tgz", + "integrity": "sha1-SC7gmKmHfoz6ciQshJm5PyBwnE4=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "empower": "1.2.3", + "power-assert-formatter": "1.4.1", + "universal-deep-strict-equal": "1.2.2", + "xtend": "4.0.1" + } + }, + "power-assert-context-formatter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-context-formatter/-/power-assert-context-formatter-1.1.1.tgz", + "integrity": "sha1-7bo1LT7YpgMRTWZyZazOYNaJzN8=", + "dev": true, + "requires": { + "core-js": "2.4.1", + "power-assert-context-traversal": "1.1.1" + } + }, + "power-assert-context-reducer-ast": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.1.2.tgz", + "integrity": "sha1-SEqZ4m9Jc/+IMuXFzHVnAuYJQXQ=", + "dev": true, + "requires": { + "acorn": "4.0.13", + "acorn-es7-plugin": "1.1.7", + "core-js": "2.4.1", + "espurify": "1.7.0", + "estraverse": "4.2.0" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "power-assert-context-traversal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-context-traversal/-/power-assert-context-traversal-1.1.1.tgz", + "integrity": "sha1-iMq8oNE7Y1nwfT0+ivppkmRXftk=", + "dev": true, + "requires": { + "core-js": "2.4.1", + "estraverse": "4.2.0" + } + }, + "power-assert-formatter": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/power-assert-formatter/-/power-assert-formatter-1.4.1.tgz", + "integrity": "sha1-XcEl7VCj37HdomwZNH879Y7CiEo=", + "dev": true, + "requires": { + "core-js": "2.4.1", + "power-assert-context-formatter": "1.1.1", + "power-assert-context-reducer-ast": "1.1.2", + "power-assert-renderer-assertion": "1.1.1", + "power-assert-renderer-comparison": "1.1.1", + "power-assert-renderer-diagram": "1.1.2", + "power-assert-renderer-file": "1.1.1" + } + }, + "power-assert-renderer-assertion": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.1.1.tgz", + "integrity": "sha1-y/wOd+AIao+Wrz8djme57n4ozpg=", + "dev": true, + "requires": { + "power-assert-renderer-base": "1.1.1", + "power-assert-util-string-width": "1.1.1" + } + }, + "power-assert-renderer-base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-renderer-base/-/power-assert-renderer-base-1.1.1.tgz", + "integrity": "sha1-lqZQxv0F7hvB9mtUrWFELIs/Y+s=", + "dev": true + }, + "power-assert-renderer-comparison": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.1.1.tgz", + "integrity": "sha1-10Odl9hRVr5OMKAPL7WnJRTOPAg=", + "dev": true, + "requires": { + "core-js": "2.4.1", + "diff-match-patch": "1.0.0", + "power-assert-renderer-base": "1.1.1", + "stringifier": "1.3.0", + "type-name": "2.0.2" + } + }, + "power-assert-renderer-diagram": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.1.2.tgz", + "integrity": "sha1-ZV+PcRk1qbbVQbhjJ2VHF8Y3qYY=", + "dev": true, + "requires": { + "core-js": "2.4.1", + "power-assert-renderer-base": "1.1.1", + "power-assert-util-string-width": "1.1.1", + "stringifier": "1.3.0" + } + }, + "power-assert-renderer-file": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-renderer-file/-/power-assert-renderer-file-1.1.1.tgz", + "integrity": "sha1-o34rvReMys0E5427eckv40kzxec=", + "dev": true, + "requires": { + "power-assert-renderer-base": "1.1.1" + } + }, + "power-assert-util-string-width": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-util-string-width/-/power-assert-util-string-width-1.1.1.tgz", + "integrity": "sha1-vmWet5N/3S5smncmjar2S9W3xZI=", + "dev": true, + "requires": { + "eastasianwidth": "0.1.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "private": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", + "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "proxy-addr": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", + "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", + "dev": true, + "requires": { + "forwarded": "0.1.0", + "ipaddr.js": "1.4.0" + } + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + } + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + }, + "regexp-clone": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", + "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "2.0.0", + "semver": "5.4.1" + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } + } + }, + "requirejs": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.4.tgz", + "integrity": "sha512-qPD5gRrj6kGQ0ZySAJgqbArkaDqPMbQIT0zSZDkIv1mfA17w/tR2Faq5l2qqRf2CdQx6FWln9nUrgd2UDzb19A==", + "dev": true + }, + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true, + "requires": { + "glob": "7.1.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "send": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz", + "integrity": "sha1-UBP5+ZAj31DRvZiSwZ4979HVMwk=", + "dev": true, + "requires": { + "debug": "2.6.7", + "depd": "1.1.1", + "destroy": "1.0.4", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.0", + "fresh": "0.5.0", + "http-errors": "1.6.1", + "mime": "1.3.4", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + }, + "dependencies": { + "debug": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "dev": true + } + } + }, + "serve-static": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz", + "integrity": "sha1-n0uhni8wMMVH+K+ZEHg47DjVseI=", + "dev": true, + "requires": { + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "parseurl": "1.3.1", + "send": "0.15.3" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + }, + "shelljs": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", + "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "source-map-support": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", + "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=", + "dev": true, + "requires": { + "source-map": "0.5.6" + }, + "dependencies": { + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "stringifier": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz", + "integrity": "sha1-3vGDQvaTPbDy2/yaoCF1tEjBeVk=", + "dev": true, + "requires": { + "core-js": "2.4.1", + "traverse": "0.6.6", + "type-name": "2.0.2" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.16.6", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "tbd": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/tbd/-/tbd-0.6.4.tgz", + "integrity": "sha1-btWic3ZPhu0mjJYeG9TVyk0N5tQ=", + "dev": true, + "requires": { + "express": "4.15.3", + "jade": "0.26.3", + "jasmine-node": "1.14.5" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.16" + } + }, + "type-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/type-name/-/type-name-2.0.2.tgz", + "integrity": "sha1-7+fUEj2KxSr/9/QMfk3sUmYAj7Q=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.0.tgz", + "integrity": "sha1-8CHji6LKdAhg9b1caVwqgXNF8Ow=", + "dev": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "underscore": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.5.2.tgz", + "integrity": "sha1-EzXF5PXm0zu7SwBrqMhqAPVW3gg=", + "dev": true + }, + "universal-deep-strict-equal": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/universal-deep-strict-equal/-/universal-deep-strict-equal-1.2.2.tgz", + "integrity": "sha1-DaSsL3PP95JMgfpN4BjKViyisKc=", + "dev": true, + "requires": { + "array-filter": "1.0.0", + "indexof": "0.0.1", + "object-keys": "1.0.11" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "dev": true + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + }, + "validator": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-5.4.0.tgz", + "integrity": "sha1-RCDdyf3CCU2QS4UwPhtKE4+E5x4=", + "dev": true + }, + "vary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", + "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=", + "dev": true + }, + "walkdir": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz", + "integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } +} From 12126bf33af65b2035069f5e0c9e34a2ba3e7b87 Mon Sep 17 00:00:00 2001 From: andresattler Date: Fri, 4 Aug 2017 21:47:28 +1200 Subject: [PATCH 1761/2240] fix: limiting number of async operations per time in insertMany --- lib/model.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 119294134fb..8681a3fcb46 100644 --- a/lib/model.js +++ b/lib/model.js @@ -21,6 +21,7 @@ var discriminator = require('./services/model/discriminator'); var isPathSelectedInclusive = require('./services/projection/isPathSelectedInclusive'); var mpath = require('mpath'); var parallel = require('async/parallel'); +var parallelLimit = require('async/parallelLimit') var util = require('util'); var utils = require('./utils'); @@ -2056,7 +2057,7 @@ Model.insertMany = function(arr, options, callback) { }); }); - parallel(toExecute, function(error, docs) { + parallelLimit(toExecute, 1000, function(error, docs) { if (error) { callback && callback(error); return; From a364c1ff47cb67a76c91473128594365ce137ed6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 5 Aug 2017 07:04:30 -0700 Subject: [PATCH 1762/2240] test(document): repro #5506 --- test/document.test.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 9438861cd23..d268889bd49 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4355,6 +4355,40 @@ describe('document', function() { done(); }); + it('dotted virtuals in toObject (gh-5506)', function(done) { + var childSchema = new Schema({ + name: String, + _id: false + }); + var parentSchema = new Schema({ + child: { + type: childSchema, + default: {} + } + }); + + var Parent = db.model('gh5506', parentSchema); + + var p = new Parent({ child: { name: 'myName' } }); + + p.save(). + then(function() { + return Parent.findOne(); + }). + then(function(doc) { + doc.child = {}; + return doc.save(); + }). + then(function() { + return Parent.findOne(); + }). + then(function(doc) { + assert.deepEqual(doc.toObject().child, {}); + done(); + }). + catch(done); + }); + it('consistent setter context for single nested (gh-5363)', function(done) { var contentSchema = new Schema({ blocks: [{ type: String }], From d39ba28921a1b4efdce178e8b6bb1d1cf9e46f7c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 5 Aug 2017 07:04:45 -0700 Subject: [PATCH 1763/2240] fix(document): clear single nested doc when setting to empty object Fix #5506 --- lib/document.js | 1 + lib/schema/embedded.js | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/document.js b/lib/document.js index 020a3babe20..7c57a0788c7 100644 --- a/lib/document.js +++ b/lib/document.js @@ -747,6 +747,7 @@ Document.prototype.set = function(path, val, type, options) { } didPopulate = true; } + val = schema.applySetters(val, this, false, priorVal); if (!didPopulate && this.$__.populated) { diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 3161924b0e8..4ada6d38edc 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -128,9 +128,15 @@ Embedded.prototype.cast = function(val, doc, init, priorVal) { subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); subdoc.init(val); } else { - subdoc = priorVal && priorVal.$isSingleNested ? - new this.caster(priorVal.toObject(), doc ? doc.$__.selected : void 0, doc) : - new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); + if (Object.keys(val).length === 0) { + return new this.caster({}, doc ? doc.$__.selected : void 0, doc); + } + + if (priorVal && priorVal.$isSingleNested) { + subdoc = new this.caster(priorVal.toObject(), doc ? doc.$__.selected : void 0, doc); + } else { + subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); + } subdoc.set(val, undefined, false); } From 71639e392a18b4a52860a5f9ca2420d52fdd4ef9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 5 Aug 2017 11:43:43 -0700 Subject: [PATCH 1764/2240] refactor(document): get rid of hacky usage of bind() --- lib/document.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/document.js b/lib/document.js index 7c57a0788c7..0a2bf0ce2d1 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2037,14 +2037,16 @@ Document.prototype.$__getAllSubdocs = function() { DocumentArray || (DocumentArray = require('./types/documentarray')); Embedded = Embedded || require('./types/embedded'); - function docReducer(seed, path) { - var val = this[path]; + function docReducer(doc, seed, path) { + var val = doc[path]; if (val instanceof Embedded) { seed.push(val); } if (val && val.$isSingleNested) { - seed = Object.keys(val._doc).reduce(docReducer.bind(val._doc), seed); + seed = Object.keys(val._doc).reduce(function(seed, path) { + return docReducer(val._doc, seed, path); + }, seed); seed.push(val); } if (val && val.isMongooseDocumentArray) { @@ -2055,17 +2057,24 @@ Document.prototype.$__getAllSubdocs = function() { if (doc instanceof Embedded) { seed.push(doc); } - seed = Object.keys(doc._doc).reduce(docReducer.bind(doc._doc), seed); + seed = Object.keys(doc._doc).reduce(function(seed, path) { + return docReducer(doc._doc, seed, path); + }, seed); }); } else if (val instanceof Document && val.$__isNested) { if (val) { - seed = Object.keys(val).reduce(docReducer.bind(val), seed); + seed = Object.keys(val).reduce(function(seed, path) { + return docReducer(val, seed, path); + }, seed); } } return seed; } - var subDocs = Object.keys(this._doc).reduce(docReducer.bind(this), []); + var _this = this; + var subDocs = Object.keys(this._doc).reduce(function(seed, path) { + return docReducer(_this, seed, path); + }, []); return subDocs; }; From 729ad628b1df13b8963ed0f596616ec44cffdf81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Sattler?= Date: Sun, 6 Aug 2017 12:23:20 +1200 Subject: [PATCH 1765/2240] Update model.js --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 8681a3fcb46..44e9f9a0154 100644 --- a/lib/model.js +++ b/lib/model.js @@ -21,7 +21,7 @@ var discriminator = require('./services/model/discriminator'); var isPathSelectedInclusive = require('./services/projection/isPathSelectedInclusive'); var mpath = require('mpath'); var parallel = require('async/parallel'); -var parallelLimit = require('async/parallelLimit') +var parallelLimit = require('async/parallelLimit'); var util = require('util'); var utils = require('./utils'); From 31a639069735cb03f26c4f4bb6a9fc721d99195f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 6 Aug 2017 13:06:39 -0700 Subject: [PATCH 1766/2240] fix(browserDocument): prevent stack overflow caused by double-wrapping embedded doc save() in jest Fix #5513 --- lib/browserDocument.js | 4 ++++ lib/services/model/applyHooks.js | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/browserDocument.js b/lib/browserDocument.js index d7734051418..9d03294832e 100644 --- a/lib/browserDocument.js +++ b/lib/browserDocument.js @@ -207,6 +207,9 @@ Document.prototype.$__registerHooksFromSchema = function() { if (!_this[pointCut]) { continue; } + if (_this[pointCut].$isWrapped) { + continue; + } _this[newName] = _this[pointCut]; _this[pointCut] = (function(_newName) { return function wrappedPointCut() { @@ -262,6 +265,7 @@ Document.prototype.$__registerHooksFromSchema = function() { return promise; }; })(newName); + _this[pointCut].$isWrapped = true; toWrapEl = toWrap[pointCut]; var _len = toWrapEl.pre.length; diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index 55f41f36727..f046ac2b20d 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -104,7 +104,10 @@ function applyHooks(model, schema) { // this is so we can wrap everything into a promise; newName = ('$__original_' + pointCut); if (!model.prototype[pointCut]) { - return; + continue; + } + if (model.prototype[pointCut].$isWrapped) { + continue; } if (!model.prototype[pointCut].$originalFunction) { model.prototype[newName] = model.prototype[pointCut]; @@ -169,6 +172,7 @@ function applyHooks(model, schema) { }; })(newName); model.prototype[pointCut].$originalFunction = newName; + model.prototype[pointCut].$isWrapped = true; toWrapEl = toWrap[pointCut]; var _len = toWrapEl.pre.length; From d1f6e275010f014f1c4c1f4cbe1b9df1f73c3a64 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 7 Aug 2017 07:25:45 -0700 Subject: [PATCH 1767/2240] refactor(model): dont hardcode 1000 re: #5529 --- lib/model.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 44e9f9a0154..c594c6d73db 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2033,6 +2033,10 @@ Model.insertMany = function(arr, options, callback) { if (callback) { callback = this.$wrapCallback(callback); } + var limit = options && options.limit; + if (typeof limit !== 'number') { + limit = 1000; + } if (!Array.isArray(arr)) { arr = [arr]; @@ -2057,7 +2061,7 @@ Model.insertMany = function(arr, options, callback) { }); }); - parallelLimit(toExecute, 1000, function(error, docs) { + parallelLimit(toExecute, limit, function(error, docs) { if (error) { callback && callback(error); return; From 93e771ce5678c20da3a8dd08a4b77de8a1380446 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 7 Aug 2017 07:32:49 -0700 Subject: [PATCH 1768/2240] fix: upgrade mongodb -> 2.2.30 Fix #5517 --- package-lock.json | 28 +++++++++++++++------------- package.json | 2 +- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index b2de963a358..40b1995e2f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1996,22 +1996,24 @@ } }, "mongodb": { - "version": "2.2.27", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.27.tgz", - "integrity": "sha1-NBIgNNtm2YO89qta2yaiSnD+9uY=", + "version": "2.2.30", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.30.tgz", + "integrity": "sha1-jM2AH2dsgXIEDC8rR+lgKg1WNKs=", "requires": { "es6-promise": "3.2.1", - "mongodb-core": "2.1.11", + "mongodb-core": "2.1.14", "readable-stream": "2.2.7" - } - }, - "mongodb-core": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.11.tgz", - "integrity": "sha1-HDh3bOsXSZepnCiGDu2QKNqbPho=", - "requires": { - "bson": "1.0.4", - "require_optional": "1.0.1" + }, + "dependencies": { + "mongodb-core": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.14.tgz", + "integrity": "sha1-E8uidkImtb49GJkq8Mljzl6g8P0=", + "requires": { + "bson": "1.0.4", + "require_optional": "1.0.1" + } + } } }, "mongodb-topology-manager": { diff --git a/package.json b/package.json index c74e50bfe82..50d60a50f67 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "2.0.0", "kareem": "1.5.0", - "mongodb": "2.2.27", + "mongodb": "2.2.30", "mpath": "0.3.0", "mpromise": "0.5.5", "mquery": "2.3.1", From b6340c8c3adfbebc17235e55bd9913c95e6a55cd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 7 Aug 2017 07:50:25 -0700 Subject: [PATCH 1769/2240] chore: release 4.11.6 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 12beb8a61f8..d5f2f2ee6a1 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.11.6 / 2017-08-07 +=================== + * fix: limiting number of async operations per time in insertMany #5529 [andresattler](https://github.com/andresattler) + * fix: upgrade mongodb -> 2.2.30 #5517 + * fix(browserDocument): prevent stack overflow caused by double-wrapping embedded doc save() in jest #5513 + * fix(document): clear single nested doc when setting to empty object #5506 + * fix(connection): emit reconnected and disconnected events correctly with useMongoClient #5498 + * fix(populate): ensure nested virtual populate gets set even if top-level property is null #5431 + 4.11.5 / 2017-07-30 =================== * docs: fix link to $lookup #5516 [TalhaAwan](https://github.com/TalhaAwan) diff --git a/package.json b/package.json index 50d60a50f67..933e44960b2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.6-pre", + "version": "4.11.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From d3b6c1f86c951cd3f05d6b28d3e4a0aded703e41 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 7 Aug 2017 07:52:02 -0700 Subject: [PATCH 1770/2240] chore: now working on 4.11.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 933e44960b2..9349f33b510 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.6", + "version": "4.11.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ea518d77c5c7fc9b6f713ce7415ee42403d3369f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 7 Aug 2017 15:17:52 -0700 Subject: [PATCH 1771/2240] fix(error): set name before stack trace Fix #5533 --- lib/error/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/error/validation.js b/lib/error/validation.js index ce96d7aa79d..e51af657fdd 100644 --- a/lib/error/validation.js +++ b/lib/error/validation.js @@ -23,12 +23,12 @@ function ValidationError(instance) { this._message = 'Validation failed'; MongooseError.call(this, this._message); } + this.name = 'ValidationError'; if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { this.stack = new Error().stack; } - this.name = 'ValidationError'; if (instance) { instance.errors = this.errors; } From 3fc488927765ceaeefff111ea39fb8078b5ed7f2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 7 Aug 2017 15:23:13 -0700 Subject: [PATCH 1772/2240] fix(error): always set name before stack Fix #5533 --- lib/error/browserMissingSchema.js | 2 +- lib/error/cast.js | 2 +- lib/error/disconnected.js | 2 +- lib/error/divergentArray.js | 2 +- lib/error/missingSchema.js | 2 +- lib/error/notFound.js | 2 +- lib/error/objectExpected.js | 2 +- lib/error/overwriteModel.js | 2 +- lib/error/strict.js | 2 +- lib/error/validator.js | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/error/browserMissingSchema.js b/lib/error/browserMissingSchema.js index 1c7892e1f5b..cbf5e0e151a 100644 --- a/lib/error/browserMissingSchema.js +++ b/lib/error/browserMissingSchema.js @@ -14,8 +14,8 @@ function MissingSchemaError() { var msg = 'Schema hasn\'t been registered for document.\n' + 'Use mongoose.Document(name, schema)'; MongooseError.call(this, msg); - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); this.name = 'MissingSchemaError'; + Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); } /*! diff --git a/lib/error/cast.js b/lib/error/cast.js index f200a9d7534..59e6c180736 100644 --- a/lib/error/cast.js +++ b/lib/error/cast.js @@ -22,13 +22,13 @@ function CastError(type, value, path, reason) { } MongooseError.call(this, 'Cast to ' + type + ' failed for value ' + stringValue + ' at path "' + path + '"'); + this.name = 'CastError'; if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { this.stack = new Error().stack; } this.stringValue = stringValue; - this.name = 'CastError'; this.kind = type; this.value = value; this.path = path; diff --git a/lib/error/disconnected.js b/lib/error/disconnected.js index b4eece1cac1..a8c3e12f5a0 100644 --- a/lib/error/disconnected.js +++ b/lib/error/disconnected.js @@ -17,12 +17,12 @@ function DisconnectedError(connectionString) { MongooseError.call(this, 'Ran out of retries trying to reconnect to "' + connectionString + '". Try setting `server.reconnectTries` and ' + '`server.reconnectInterval` to something higher.'); + this.name = 'DisconnectedError'; if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { this.stack = new Error().stack; } - this.name = 'DisconnectedError'; } /*! diff --git a/lib/error/divergentArray.js b/lib/error/divergentArray.js index 1cbaa25f95e..3702f8bcc32 100644 --- a/lib/error/divergentArray.js +++ b/lib/error/divergentArray.js @@ -23,8 +23,8 @@ function DivergentArrayError(paths) { // TODO write up a docs page (FAQ) and link to it MongooseError.call(this, msg); - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); this.name = 'DivergentArrayError'; + Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); } /*! diff --git a/lib/error/missingSchema.js b/lib/error/missingSchema.js index 25eabfa5289..1870c24531d 100644 --- a/lib/error/missingSchema.js +++ b/lib/error/missingSchema.js @@ -15,8 +15,8 @@ function MissingSchemaError(name) { var msg = 'Schema hasn\'t been registered for model "' + name + '".\n' + 'Use mongoose.model(name, schema)'; MongooseError.call(this, msg); - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); this.name = 'MissingSchemaError'; + Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); } /*! diff --git a/lib/error/notFound.js b/lib/error/notFound.js index b09d7319f8c..f63f8f1bacb 100644 --- a/lib/error/notFound.js +++ b/lib/error/notFound.js @@ -26,13 +26,13 @@ function DocumentNotFoundError(query) { MongooseError.call(this, msg); + this.name = 'DocumentNotFoundError'; if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { this.stack = new Error().stack; } - this.name = 'DocumentNotFoundError'; this.query = query; } diff --git a/lib/error/objectExpected.js b/lib/error/objectExpected.js index fa863bcb4a5..eb764fc2df3 100644 --- a/lib/error/objectExpected.js +++ b/lib/error/objectExpected.js @@ -16,12 +16,12 @@ var MongooseError = require('../error.js'); function ObjectExpectedError(path, val) { MongooseError.call(this, 'Tried to set nested object field `' + path + '` to primitive value `' + val + '` and strict mode is set to throw.'); + this.name = 'ObjectExpectedError'; if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { this.stack = new Error().stack; } - this.name = 'ObjectExpectedError'; this.path = path; } diff --git a/lib/error/overwriteModel.js b/lib/error/overwriteModel.js index c14ae7ffc36..fad00d24061 100644 --- a/lib/error/overwriteModel.js +++ b/lib/error/overwriteModel.js @@ -13,8 +13,8 @@ var MongooseError = require('../error.js'); function OverwriteModelError(name) { MongooseError.call(this, 'Cannot overwrite `' + name + '` model once compiled.'); - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); this.name = 'OverwriteModelError'; + Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); } /*! diff --git a/lib/error/strict.js b/lib/error/strict.js index 2eb3ad66e18..e0e94eded7b 100644 --- a/lib/error/strict.js +++ b/lib/error/strict.js @@ -17,12 +17,12 @@ function StrictModeError(path, msg) { msg = msg || 'Field `' + path + '` is not in schema and strict ' + 'mode is set to throw.'; MongooseError.call(this, msg); + this.name = 'StrictModeError'; if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { this.stack = new Error().stack; } - this.name = 'StrictModeError'; this.path = path; } diff --git a/lib/error/validator.js b/lib/error/validator.js index 5850d12765c..d05ea491471 100644 --- a/lib/error/validator.js +++ b/lib/error/validator.js @@ -20,13 +20,13 @@ function ValidatorError(properties) { var message = this.formatMessage(msg, properties); MongooseError.call(this, message); + this.name = 'ValidatorError'; if (Error.captureStackTrace) { Error.captureStackTrace(this); } else { this.stack = new Error().stack; } this.properties = properties; - this.name = 'ValidatorError'; this.kind = properties.type; this.path = properties.path; this.value = properties.value; From 1b98177808a36ec9ae232adf34a4b96e10443c09 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 8 Aug 2017 07:43:24 -0700 Subject: [PATCH 1773/2240] test(schema): repro #5521 --- test/schema.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 0b16b7cf4d1..5fcad95fc82 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1666,6 +1666,22 @@ describe('schema', function() { done(); }); + it('type: childSchema (gh-5521)', function(done) { + var childSchema = new mongoose.Schema({ + name: String + }, { _id: false }); + + var schema = new mongoose.Schema({ + children: [{ type: childSchema }] + }); + + var Model = mongoose.model('gh5521', schema); + + var doc = new Model({ children: [{ name: 'test' }] }); + assert.deepEqual(doc.toObject().children, [{ name: 'test' }]); + done(); + }); + it('Decimal128 type (gh-4759)', function(done) { var Decimal128 = mongoose.Schema.Types.Decimal128; var schema = new Schema({ From b382c24c32f93b270a26f2cb806a90ee6d286192 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 8 Aug 2017 07:43:28 -0700 Subject: [PATCH 1774/2240] fix(schema): handle creating arrays of single nested using type key Fix #5521 --- lib/schema.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index 3071808f0e4..04976b9d074 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -579,6 +579,11 @@ Schema.interpretAsType = function(path, obj, options) { if (cast && cast.instanceOfSchema) { return new MongooseTypes.DocumentArray(path, cast, obj); } + if (cast && + cast[options.typeKey] && + cast[options.typeKey].instanceOfSchema) { + return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj); + } if (Array.isArray(cast)) { return new MongooseTypes.Array(path, Schema.interpretAsType(path, cast, options), obj); From 2b816ea5f9531a9f9d3a7376a479c9667d2596f0 Mon Sep 17 00:00:00 2001 From: Eric Thomas Date: Tue, 8 Aug 2017 14:00:04 -0600 Subject: [PATCH 1775/2240] Fix property name --- docs/schematypes.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index f9c206e90ad..5f0c13b6759 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -52,7 +52,7 @@ block content ofMixed: [Schema.Types.Mixed], ofObjectId: [Schema.Types.ObjectId], ofArrays: [[]] - ofArrayOfNumbbers: [[Number]] + ofArrayOfNumbers: [[Number]] nested: { stuff: { type: String, lowercase: true, trim: true } } From 970c8b141bbf54211fa1160fcfbb344931dc1d64 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 9 Aug 2017 06:57:23 -0700 Subject: [PATCH 1776/2240] test(document): repro #5523 --- test/document.test.js | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index d268889bd49..7dcd7ed7a03 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4389,6 +4389,59 @@ describe('document', function() { catch(done); }); + it('modifying array with existing ids (gh-5523)', function(done) { + var friendSchema = new mongoose.Schema( + { + _id: String, + name: String, + age: Number, + dob: Date + }, + { _id: false }); + + var socialSchema = new mongoose.Schema( + { + friends: [friendSchema] + }, + { _id: false }); + + var userSchema = new mongoose.Schema({ + social: { + type: socialSchema, + required: true + } + }); + + var User = db.model('gh5523', userSchema); + + var user = new User({ + social: { + friends: [ + { _id: 'val', age: 28 } + ] + } + }); + + user.social.friends = [{ _id: 'val', name: 'Val' }]; + + assert.deepEqual(user.toObject().social.friends[0], { + _id: 'val', + name: 'Val' + }); + + user.save(function(error) { + assert.ifError(error); + User.findOne({ _id: user._id }, function(error, doc) { + assert.ifError(error); + assert.deepEqual(user.toObject().social.friends[0], { + _id: 'val', + name: 'Val' + }); + done(); + }); + }); + }); + it('consistent setter context for single nested (gh-5363)', function(done) { var contentSchema = new Schema({ blocks: [{ type: String }], From f42876aad44c27355ea3520138735fbad2eb8af1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 9 Aug 2017 07:00:02 -0700 Subject: [PATCH 1777/2240] fix(document): ensure overwriting a doc array cleans out individual docs Fix #5523 --- lib/document.js | 1 + lib/schema/documentarray.js | 12 ++++++------ test/document.test.js | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/document.js b/lib/document.js index 0a2bf0ce2d1..c8160ec4c73 100644 --- a/lib/document.js +++ b/lib/document.js @@ -491,6 +491,7 @@ Document.prototype.update = function update() { */ Document.prototype.set = function(path, val, type, options) { + //console.log('set', path, val, this, new Error().stack) if (type && utils.getFunctionName(type.constructor) === 'Object') { options = type; type = undefined; diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 37df5c93f7e..5138f2d5f00 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -249,9 +249,10 @@ DocumentArray.prototype.doValidateSync = function(array, scope) { */ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { - var selected, - subdoc, - i; + var selected; + var subdoc; + var i; + var _opts = { transform: false, virtuals: false }; if (!Array.isArray(value)) { // gh-2442 mark whole array as modified if we're initializing a doc from @@ -310,9 +311,8 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { subdoc = prev.id(value[i]._id); } - if (prev && subdoc) { - // handle resetting doc with existing id but differing data - // doc.array = [{ doc: 'val' }] + if (prev && subdoc && utils.deepEqual(subdoc.toObject(_opts), value[i])) { + // handle resetting doc with existing id and same data subdoc.set(value[i]); // if set() is hooked it will have no return value // see gh-746 diff --git a/test/document.test.js b/test/document.test.js index 7dcd7ed7a03..4c9cb25a35a 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4433,7 +4433,7 @@ describe('document', function() { assert.ifError(error); User.findOne({ _id: user._id }, function(error, doc) { assert.ifError(error); - assert.deepEqual(user.toObject().social.friends[0], { + assert.deepEqual(doc.toObject().social.friends[0], { _id: 'val', name: 'Val' }); From c1de420f34b1cbdce888d7481b412080a77070b0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 10 Aug 2017 11:34:32 -0700 Subject: [PATCH 1778/2240] fix: add warning about running jest in jsdom environment Fix #5532 Re: #5513 Re: #4943 --- lib/index.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/index.js b/lib/index.js index c9a36c3e555..d686912c772 100644 --- a/lib/index.js +++ b/lib/index.js @@ -858,3 +858,13 @@ MongooseThenable.prototype.catch = function(onRejected) { */ var mongoose = module.exports = exports = new Mongoose; + +/*! + * ignore + */ + +if (typeof jest !== 'undefined' && typeof window !== 'undefined') { + console.warn('You are running mongoose with jest in the jsdom environment. ' + + 'You probably do not want to do this. Switch to the node environment: ' + + 'https://facebook.github.io/jest/docs/configuration.html#testenvironment-string'); +} From eae4fd3541f9ecb3a22c6d1db7a14f711fa4c9e7 Mon Sep 17 00:00:00 2001 From: David Wu Date: Sat, 12 Aug 2017 06:26:38 -0700 Subject: [PATCH 1779/2240] Fix toJson() when apply to a virtual populate -- missing a clone() call. --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index c8160ec4c73..4d6200da3e3 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2395,7 +2395,7 @@ function applyGetters(self, json, type, options) { for (i = 0; i < numPaths; ++i) { path = paths[i]; parts = path.split('.'); - v = self.get(path); + v = clone(self.get(path), options); if (v === void 0) { continue; } From 708764c39129ede4361ba38de056d37fe8af46d9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Aug 2017 11:51:15 -0700 Subject: [PATCH 1780/2240] fix: upgrade mongodb -> 2.2.31 to support user/pass options Fix #5419 --- lib/connection.js | 9 +++++++++ package-lock.json | 30 ++++++++++++++---------------- package.json | 2 +- tools/auth.js | 30 ++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 tools/auth.js diff --git a/lib/connection.js b/lib/connection.js index d713fb58500..09b49c5a445 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -724,6 +724,15 @@ Connection.prototype.openUri = function(uri, options, callback) { this.config.autoIndex = options.config.autoIndex !== false; delete options.config; } + + // Backwards compat + if (options.user || options.pass) { + options.auth = options.auth || {}; + options.auth.user = options.user; + options.auth.password = options.pass; + delete options.user; + delete options.pass; + } } this._connectionOptions = options; diff --git a/package-lock.json b/package-lock.json index 40b1995e2f5..500075eba35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.11.6-pre", + "version": "4.11.7-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1996,24 +1996,22 @@ } }, "mongodb": { - "version": "2.2.30", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.30.tgz", - "integrity": "sha1-jM2AH2dsgXIEDC8rR+lgKg1WNKs=", + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.31.tgz", + "integrity": "sha1-GUBEXGYeGSF7s7+CRdmFSq71SNs=", "requires": { "es6-promise": "3.2.1", - "mongodb-core": "2.1.14", + "mongodb-core": "2.1.15", "readable-stream": "2.2.7" - }, - "dependencies": { - "mongodb-core": { - "version": "2.1.14", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.14.tgz", - "integrity": "sha1-E8uidkImtb49GJkq8Mljzl6g8P0=", - "requires": { - "bson": "1.0.4", - "require_optional": "1.0.1" - } - } + } + }, + "mongodb-core": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.15.tgz", + "integrity": "sha1-hB9TuH//9MdFgYnDXIroJ+EWl2Q=", + "requires": { + "bson": "1.0.4", + "require_optional": "1.0.1" } }, "mongodb-topology-manager": { diff --git a/package.json b/package.json index 9349f33b510..ffc5f0ed131 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "2.0.0", "kareem": "1.5.0", - "mongodb": "2.2.30", + "mongodb": "2.2.31", "mpath": "0.3.0", "mpromise": "0.5.5", "mquery": "2.3.1", diff --git a/tools/auth.js b/tools/auth.js new file mode 100644 index 00000000000..bb724e824c7 --- /dev/null +++ b/tools/auth.js @@ -0,0 +1,30 @@ +'use strict'; + +const Server = require('mongodb-topology-manager').Server; +const co = require('co'); +const mongodb = require('mongodb'); + +co(function*() { + // Create new instance + var server = new Server('mongod', { + auth: null, + dbpath: '~/data/db/27017' + }); + + // Purge the directory + yield server.purge(); + + // Start process + yield server.start(); + + const db = yield mongodb.MongoClient.connect('mongodb://localhost:27017/admin'); + + yield db.addUser('passwordIsTaco', 'taco', { + roles: ['dbOwner'] + }); + + console.log('done'); +}).catch(error => { + console.error(error); + process.exit(-1); +}); From ee9b20147b046931e6bf26d4dbf392e8177b2d32 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Aug 2017 11:56:23 -0700 Subject: [PATCH 1781/2240] chore: use absolute paths for launchers --- tools/auth.js | 2 +- tools/repl.js | 6 +++--- tools/sharded.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/auth.js b/tools/auth.js index bb724e824c7..967f5e1f8b9 100644 --- a/tools/auth.js +++ b/tools/auth.js @@ -8,7 +8,7 @@ co(function*() { // Create new instance var server = new Server('mongod', { auth: null, - dbpath: '~/data/db/27017' + dbpath: '/data/db/27017' }); // Purge the directory diff --git a/tools/repl.js b/tools/repl.js index 533892afddd..ca3b6de5618 100644 --- a/tools/repl.js +++ b/tools/repl.js @@ -9,19 +9,19 @@ co(function*() { var topology = new ReplSet('mongod', [{ // mongod process options options: { - bind_ip: 'localhost', port: 31000, dbpath: `~/data/db/31000` + bind_ip: 'localhost', port: 31000, dbpath: `/data/db/31000` } }, { // mongod process options options: { - bind_ip: 'localhost', port: 31001, dbpath: `~/data/db/31001` + bind_ip: 'localhost', port: 31001, dbpath: `/data/db/31001` } }, { // Type of node arbiterOnly: true, // mongod process options options: { - bind_ip: 'localhost', port: 31002, dbpath: `~/data/db/31002` + bind_ip: 'localhost', port: 31002, dbpath: `/data/db/31002` } }], { replSet: 'rs' diff --git a/tools/sharded.js b/tools/sharded.js index 9eab1352d21..0883c31b454 100644 --- a/tools/sharded.js +++ b/tools/sharded.js @@ -13,13 +13,13 @@ co(function*() { yield topology.addShard([{ options: { - bind_ip: 'localhost', port: 31000, dbpath: `~/data/db/31000` + bind_ip: 'localhost', port: 31000, dbpath: `/data/db/31000` } }], { replSet: 'rs1' }); yield topology.addConfigurationServers([{ options: { - bind_ip: 'localhost', port: 35000, dbpath: `~/data/db/35000` + bind_ip: 'localhost', port: 35000, dbpath: `/data/db/35000` } }], { replSet: 'rs0' }); From 9e97444060813300ed620f4a8f3b82893249ceb1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Aug 2017 13:08:48 -0700 Subject: [PATCH 1782/2240] test(document): repro #5470 --- test/document.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 4c9cb25a35a..fa1c56b3883 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4389,6 +4389,31 @@ describe('document', function() { catch(done); }); + it('parent props not in child (gh-5470)', function(done) { + var employeeSchema = new mongoose.Schema({ + name: { + first: String, + last: String + }, + department: String + }); + var Employee = mongoose.model('Test', employeeSchema); + + var employee = new Employee({ + name: { + first: 'Ron', + last: 'Swanson' + }, + department: 'Parks and Recreation' + }); + var ownPropertyNames = Object.getOwnPropertyNames(employee.name); + + assert.ok(ownPropertyNames.indexOf('department') === -1, ownPropertyNames.join(',')); + assert.ok(ownPropertyNames.indexOf('first') !== -1, ownPropertyNames.join(',')); + assert.ok(ownPropertyNames.indexOf('last') !== -1, ownPropertyNames.join(',')); + done(); + }); + it('modifying array with existing ids (gh-5523)', function(done) { var friendSchema = new mongoose.Schema( { From 14d7ca39d9763f4a8ac66c3afe070e548cb69ea1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Aug 2017 13:09:21 -0700 Subject: [PATCH 1783/2240] fix(document): make nested docs no longer inherit parent doc's schema props Fix #5470 --- lib/document.js | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/document.js b/lib/document.js index c8160ec4c73..b76effe20a6 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1885,6 +1885,11 @@ function getOwnPropertyDescriptors(object) { Object.getOwnPropertyNames(object).forEach(function(key) { result[key] = Object.getOwnPropertyDescriptor(object, key); + // Assume these are schema paths, ignore them re: #5470 + if (result[key].get) { + delete result[key]; + return; + } result[key].enumerable = ['isNew', '$__', 'errors', '_doc'].indexOf(key) === -1; }); @@ -1910,27 +1915,19 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { } if (!this.$__.getters[path]) { - var nested = Object.create(Object.getPrototypeOf(this), getOwnPropertyDescriptors(this)); + var nested = Object.create(Document.prototype, getOwnPropertyDescriptors(this)); // save scope for nested getters/setters if (!prefix) { nested.$__.scope = this; } - // shadow inherited getters from sub-objects so - // thing.nested.nested.nested... doesn't occur (gh-366) - var i = 0, - len = keys.length; - - for (; i < len; ++i) { - // over-write the parents getter without triggering it - Object.defineProperty(nested, keys[i], { - enumerable: false, // It doesn't show up. - writable: true, // We can set it later. - configurable: true, // We can Object.defineProperty again. - value: undefined // It shadows its parent. - }); - } + Object.defineProperty(nested, 'schema', { + enumerable: false, + configurable: true, + writable: false, + value: prototype.schema + }); Object.defineProperty(nested, 'toObject', { enumerable: false, From cded3f81dcc2c1f91d6f7bef02dc1c381a7a221f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Aug 2017 13:27:43 -0700 Subject: [PATCH 1784/2240] test(populate): repro #5542 --- test/model.populate.test.js | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 8d12177ad7f..1e01d0ccc2c 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5527,6 +5527,49 @@ describe('model: populate:', function() { catch(done); }); + it('virtual populate toJSON output (gh-5542)', function(done) { + var AuthorSchema = new mongoose.Schema({ + name: String + }, { + toObject: { virtuals: true }, + toJSON: { virtuals: true } + }); + + var BookSchema = new mongoose.Schema({ + title: String, + author: { type: ObjectId, ref: 'gh5542' } + }); + + AuthorSchema.virtual('books', { + ref: 'gh5542_0', + localField: '_id', + foreignField: 'author', + justOne: true + }); + + var Author = db.model('gh5542', AuthorSchema) + var Book = db.model('gh5542_0', BookSchema) + + var author = new Author({ name: 'Bob' }); + author.save(). + then(function(author) { + var book = new Book({ name: 'Book', author: author._id }); + return book.save(); + }). + then(function() { + return Author.findOne({}) + .populate({ path: 'books', select: 'title' }) + .exec(); + }). + then(function(author) { + const json = author.toJSON(); + assert.deepEqual(Object.getOwnPropertyNames(json.books), + ['_id', 'author']); + done(); + }). + catch(done); + }); + it('works if foreignField parent is selected (gh-5037)', function(done) { var childSchema = new mongoose.Schema({ name: String, From 9da4b0df22861d2553ff1bfc4837ce2e6b13e6c4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 12 Aug 2017 15:49:24 -0700 Subject: [PATCH 1785/2240] style: fix lint --- test/model.populate.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 1e01d0ccc2c..ad8b882f17e 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5547,8 +5547,8 @@ describe('model: populate:', function() { justOne: true }); - var Author = db.model('gh5542', AuthorSchema) - var Book = db.model('gh5542_0', BookSchema) + var Author = db.model('gh5542', AuthorSchema); + var Book = db.model('gh5542_0', BookSchema); var author = new Author({ name: 'Bob' }); author.save(). @@ -5562,10 +5562,10 @@ describe('model: populate:', function() { .exec(); }). then(function(author) { - const json = author.toJSON(); + var json = author.toJSON(); assert.deepEqual(Object.getOwnPropertyNames(json.books), ['_id', 'author']); - done(); + done(); }). catch(done); }); From 1aedb30bcd323821d5c89c04a26282da873e9dd2 Mon Sep 17 00:00:00 2001 From: Julian Claus Date: Sun, 13 Aug 2017 10:44:27 +0200 Subject: [PATCH 1786/2240] fix: added type boolean to options documentation --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index d686912c772..b54e8b97568 100644 --- a/lib/index.js +++ b/lib/index.js @@ -74,7 +74,7 @@ Mongoose.prototype.STATES = STATES; * mongoose.set('debug', function(collectionName, methodName, arg1, arg2...) {}); // use custom function to log collection methods + arguments * * @param {String} key - * @param {String|Function} value + * @param {String|Function|Boolean} value * @api public */ From f09109a87882f198d5dc483df02cd7f5865f7203 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 14 Aug 2017 07:08:43 -0700 Subject: [PATCH 1787/2240] chore: release 4.11.7 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index d5f2f2ee6a1..ef86974c7fb 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.11.7 / 2017-08-14 +=================== + * fix: correct properties when calling toJSON() on populated virtual #5544 #5442 [davidwu226](https://github.com/davidwu226) + * docs: fix spelling #5535 [et](https://github.com/et) + * fix(error): always set name before stack #5533 + * fix: add warning about running jest in jsdom environment #5532 #5513 #4943 + * fix(document): ensure overwriting a doc array cleans out individual docs #5523 + * fix(schema): handle creating arrays of single nested using type key #5521 + * fix: upgrade mongodb -> 2.2.31 to support user/pass options #5419 + 4.11.6 / 2017-08-07 =================== * fix: limiting number of async operations per time in insertMany #5529 [andresattler](https://github.com/andresattler) diff --git a/package.json b/package.json index ffc5f0ed131..3f33970b4d8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.7-pre", + "version": "4.11.7", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e2d16fd040f25cda881890db9c73a2ff24c133a1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 14 Aug 2017 07:10:28 -0700 Subject: [PATCH 1788/2240] chore: now working on 4.11.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f33970b4d8..d06dfe4fdb3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.7", + "version": "4.11.8-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 45c0c1e6c8ca2a1c75186572dcd8c705ed25837a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 16 Aug 2017 15:57:19 -0700 Subject: [PATCH 1789/2240] docs(populate): remove confusing leading `_` from populate examples Re: https://mongoosejsteam.slack.com/archives/C2CA1AWQP/p1502921015000379 --- docs/populate.jade | 100 ++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 64 deletions(-) diff --git a/docs/populate.jade b/docs/populate.jade index 8ef30d8d16a..2be09b382e8 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -7,26 +7,26 @@ block content Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s). We may populate a single document, multiple documents, plain object, multiple plain objects, or all objects returned from a query. Let's look at some examples. :js - var mongoose = require('mongoose') - , Schema = mongoose.Schema + var mongoose = require('mongoose'); + var Schema = mongoose.Schema; var personSchema = Schema({ - _id : Number, - name : String, - age : Number, - stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] + _id: Number, + name: String, + age: Number, + stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }] }); var storySchema = Schema({ - _creator : { type: Number, ref: 'Person' }, - title : String, - fans : [{ type: Number, ref: 'Person' }] + author: { type: Number, ref: 'Person' }, + title: String, + fans: [{ type: Number, ref: 'Person' }] }); - var Story = mongoose.model('Story', storySchema); + var Story = mongoose.model('Story', storySchema); var Person = mongoose.model('Person', personSchema); :markdown - So far we've created two [Models](./models.html). Our `Person` model has its `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose which model to use during population, in our case the `Story` model. All `_id`s we store here must be document `_id`s from the `Story` model. We also declared the `Story` `_creator` property as a `Number`, the same type as the `_id` used in the `personSchema`. It is important to match the type of `_id` to the type of ref. + So far we've created two [Models](./models.html). Our `Person` model has its `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose which model to use during population, in our case the `Story` model. All `_id`s we store here must be document `_id`s from the `Story` model. We also declared the `Story` `author` property as a `Number`, the same type as the `_id` used in the `personSchema`. It is important to match the type of `_id` to the type of ref. .important :markdown **Note**: `ObjectId`, `Number`, `String`, and `Buffer` are valid for use as refs. @@ -34,14 +34,14 @@ block content :markdown Saving refs to other documents works the same way you normally save properties, just assign the `_id` value: :js - var aaron = new Person({ _id: 0, name: 'Aaron', age: 100 }); + var author = new Person({ _id: 0, name: 'Ian Fleming', age: 50 }); - aaron.save(function (err) { + author.save(function (err) { if (err) return handleError(err); var story1 = new Story({ - title: "Once upon a timex.", - _creator: aaron._id // assign the _id from the person + title: 'Casino Royale', + author: author._id // assign the _id from the person }); story1.save(function (err) { @@ -51,15 +51,15 @@ block content }); h3 Population :markdown - So far we haven't done anything much different. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator` using the query builder: + So far we haven't done anything much different. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `author` using the query builder: :js Story. - findOne({ title: 'Once upon a timex.' }). - populate('_creator'). + findOne({ title: 'Casino Royale' }). + populate('author'). exec(function (err, story) { if (err) return handleError(err); - console.log('The creator is %s', story._creator.name); - // prints "The creator is Aaron" + console.log('The author is %s', story.creator.name); + // prints "The author is Ian Fleming" }); :markdown Populated paths are no longer set to their original `_id` , their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. @@ -72,12 +72,12 @@ block content :markdown In Mongoose >= 4.0, you can manually populate a field as well. :js - Story.findOne({ title: 'Once upon a timex.' }, function(error, story) { + Story.findOne({ title: 'Casino Royale' }, function(error, story) { if (error) { return handleError(error); } - story._creator = aaron; - console.log(story._creator.name); // prints "Aaron" + story.author = author; + console.log(story.author.name); // prints "Ian Fleming" }); :markdown Note that this only works for single refs. You currently **can't** manually populate an array of refs. @@ -87,15 +87,15 @@ block content :js Story. findOne({ title: /timex/i }). - populate('_creator', 'name'). // only return the Persons name + populate('author', 'name'). // only return the Persons name exec(function (err, story) { if (err) return handleError(err); - console.log('The creator is %s', story._creator.name); - // prints "The creator is Aaron" + console.log('The author is %s', story.author.name); + // prints "The author is Ian Fleming" - console.log('The creators age is %s', story._creator.age); - // prints "The creators age is null' + console.log('The authors age is %s', story.author.age); + // prints "The authors age is null' }) h3 Populating multiple paths :markdown @@ -103,7 +103,7 @@ block content :js Story. find(...). - populate('fans _creator'). // space delimited path names + populate('fans author'). // space delimited path names exec() .important :markdown @@ -112,7 +112,7 @@ block content Story. find(...). populate('fans'). - populate('_creator'). + populate('author'). exec() :markdown If you call `populate()` multiple times with the same path, only the last @@ -142,17 +142,17 @@ block content exec() h3 Refs to children :markdown - We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' onto `aaron.stories`. + We may find however, if we use the `author` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' onto `author.stories`. - There are two perspectives here. First, it's nice to have `aaron` know which stories are his. + There are two perspectives here. First, you may want the `author` know which stories are theirs. Usually, your schema should resolve one-to-many relationships by having a parent pointer in the 'many' side. But, if you have a good reason to want an array of child pointers, you can `push()` documents onto the array as shown below. :js - aaron.stories.push(story1); - aaron.save(callback); + author.stories.push(story1); + author.save(callback); :markdown This allows us to perform a `find` and `populate` combo: :js Person. - findOne({ name: 'Aaron' }). + findOne({ name: 'Ian Fleming' }). populate('stories'). // only works if we pushed refs to children exec(function (err, person) { if (err) return handleError(err); @@ -163,40 +163,12 @@ block content It is debatable that we really want two sets of pointers as they may get out of sync. Instead we could skip populating and directly `find()` the stories we are interested in. :js Story. - find({ _creator: aaron._id }). + find({ author: author._id }). exec(function (err, stories) { if (err) return handleError(err); console.log('The stories are an array: ', stories); }); - h3 Updating refs - :markdown - Now that we have a `story` we realized that the `_creator` was incorrect. We can update refs the same as any other property through Mongoose's internal casting: - :js - var guille = new Person({ name: 'Guillermo' }); - guille.save(function (err) { - if (err) return handleError(err); - - story._creator = guille; - console.log(story._creator.name); - // prints "Guillermo" in mongoose >= 3.6 - // see https://github.com/Automattic/mongoose/wiki/3.6-release-notes - - story.save(function (err) { - if (err) return handleError(err); - - Story. - findOne({ title: /timex/i }). - populate({ path: '_creator', select: 'name' }). - exec(function (err, story) { - if (err) return handleError(err); - - console.log('The creator is %s', story._creator.name) - // prints "The creator is Guillermo" - }); - }) - }) - .important :markdown The documents returned from [query population](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents unless the [lean](./api.html#query_Query-lean) option is specified. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. From 80e350348868a4e9bc9ca2c406a8dd922908cbab Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 17 Aug 2017 16:30:24 -0700 Subject: [PATCH 1790/2240] fix(connection): expose parsed uri fields (host, port, dbname) when using openUri() Fix #5556 --- lib/connection.js | 16 ++++++++++++++++ test/connection.test.js | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 09b49c5a445..9c03dc9123b 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -709,6 +709,20 @@ Connection.prototype.openUri = function(uri, options, callback) { this.readyState = STATES.connecting; this._closeCalled = false; + try { + var parsed = muri(uri); + this.name = parsed.db; + this.host = parsed.hosts[0].host || parsed.hosts[0].ipc; + this.port = parsed.hosts[0].port || 27017; + if (parsed.auth) { + this.user = parsed.auth.user; + this.pass = parsed.auth.pass; + } + } catch (error) { + this.error(error, callback); + throw error; + } + if (typeof options === 'function') { callback = options; options = null; @@ -732,6 +746,8 @@ Connection.prototype.openUri = function(uri, options, callback) { options.auth.password = options.pass; delete options.user; delete options.pass; + this.user = options.auth.user; + this.pass = options.auth.password; } } diff --git a/test/connection.test.js b/test/connection.test.js index 335a2019682..96d3fd14abc 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -23,6 +23,9 @@ describe('connections:', function() { conn.then(function(conn) { assert.equal(conn.constructor.name, 'NativeConnection'); + assert.equal(conn.host, 'localhost'); + assert.equal(conn.port, 27017); + assert.equal(conn.name, 'mongoosetest'); return mongoose.disconnect().then(function() { done(); }); }).catch(done); @@ -44,6 +47,9 @@ describe('connections:', function() { conn. then(function(conn) { assert.equal(conn.constructor.name, 'NativeConnection'); + assert.equal(conn.host, 'localhost'); + assert.equal(conn.port, 27017); + assert.equal(conn.name, 'mongoosetest'); return findPromise; }). From 591aebd2e45fb1368b50571cc35c40266d92ccce Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 19 Aug 2017 09:18:09 -0700 Subject: [PATCH 1791/2240] test(aggregate): repro #5522 --- test/aggregate.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 5693e225b32..d17946a1754 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -862,6 +862,14 @@ describe('aggregate: ', function() { }); }); }); + + it('readPref from schema (gh-5522)', function(done) { + var schema = new Schema({ name: String }, { read: 'secondary' }); + var M = db.model('gh5522', schema); + var a = M.aggregate(); + assert.equal(a.options.readPreference.mode, 'secondary'); + done(); + }); }); it('cursor (gh-3160)', function(done) { From 6bd9d15b28328633f7d7f16fca901dbcfe8ccd26 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 19 Aug 2017 09:24:23 -0700 Subject: [PATCH 1792/2240] fix(aggregate): pull read preference from schema by default Fix #5522 --- lib/aggregate.js | 7 ++++++- test/aggregate.test.js | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 8d4b4f4ffcd..eaa20587c51 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -44,7 +44,7 @@ var read = Query.prototype.read; function Aggregate() { this._pipeline = []; this._model = undefined; - this.options = undefined; + this.options = {}; if (arguments.length === 1 && util.isArray(arguments[0])) { this.append.apply(this, arguments[0]); @@ -63,6 +63,11 @@ function Aggregate() { Aggregate.prototype.model = function(model) { this._model = model; + if (this.options.readPreference == null && + model.schema && + model.schema.options.read != null) { + this.options.readPreference = model.schema.options.read; + } return this; }; diff --git a/test/aggregate.test.js b/test/aggregate.test.js index d17946a1754..2af32acb83c 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -868,6 +868,11 @@ describe('aggregate: ', function() { var M = db.model('gh5522', schema); var a = M.aggregate(); assert.equal(a.options.readPreference.mode, 'secondary'); + + a.read('secondaryPreferred'); + + assert.equal(a.options.readPreference.mode, 'secondaryPreferred'); + done(); }); }); From 27e194df5972525bd736eba112db020c89adfe8b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 19 Aug 2017 09:29:02 -0700 Subject: [PATCH 1793/2240] refactor(query): avoid unnecessary call into mquery for setting query read pref Re: #5552 --- lib/query.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 24b4ebfe518..7b12c4dc634 100644 --- a/lib/query.js +++ b/lib/query.js @@ -881,7 +881,8 @@ Query.prototype.select = function select() { Query.prototype.read = function read(pref, tags) { // first cast into a ReadPreference object to support tags var read = readPref.call(readPref, pref, tags); - return Query.base.read.call(this, read); + this.options.readPreference = read; + return this; }; /** From a0ebd071e12a7854defd4befeca85be836dde128 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 19 Aug 2017 09:53:00 -0700 Subject: [PATCH 1794/2240] docs(populate): remove Number ref from populate docs --- docs/populate.jade | 80 +++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/docs/populate.jade b/docs/populate.jade index 2be09b382e8..7427aadff4e 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -11,30 +11,41 @@ block content var Schema = mongoose.Schema; var personSchema = Schema({ - _id: Number, + _id: Schema.Types.ObjectId, name: String, age: Number, stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }] }); var storySchema = Schema({ - author: { type: Number, ref: 'Person' }, + author: { type: Schema.Types.ObjectId, ref: 'Person' }, title: String, - fans: [{ type: Number, ref: 'Person' }] + fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }] }); var Story = mongoose.model('Story', storySchema); var Person = mongoose.model('Person', personSchema); :markdown - So far we've created two [Models](./models.html). Our `Person` model has its `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose which model to use during population, in our case the `Story` model. All `_id`s we store here must be document `_id`s from the `Story` model. We also declared the `Story` `author` property as a `Number`, the same type as the `_id` used in the `personSchema`. It is important to match the type of `_id` to the type of ref. + So far we've created two [Models](./models.html). Our `Person` model has + its `stories` field set to an array of `ObjectId`s. The `ref` option is + what tells Mongoose which model to use during population, in our case + the `Story` model. All `_id`s we store here must be document `_id`s from + the `Story` model. .important :markdown - **Note**: `ObjectId`, `Number`, `String`, and `Buffer` are valid for use as refs. + **Note**: `ObjectId`, `Number`, `String`, and `Buffer` are valid for use + as refs. However, you should use `ObjectId` unless you are an advanced + user and have a good reason for doing so. h3 Saving refs :markdown - Saving refs to other documents works the same way you normally save properties, just assign the `_id` value: + Saving refs to other documents works the same way you normally save + properties, just assign the `_id` value: :js - var author = new Person({ _id: 0, name: 'Ian Fleming', age: 50 }); + var author = new Person({ + _id: new mongoose.Types.ObjectId(), + name: 'Ian Fleming', + age: 50 + }); author.save(function (err) { if (err) return handleError(err); @@ -62,12 +73,18 @@ block content // prints "The author is Ian Fleming" }); :markdown - Populated paths are no longer set to their original `_id` , their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. + Populated paths are no longer set to their original `_id` , their value + is replaced with the mongoose document returned from the database by + performing a separate query before returning the results. - Arrays of refs work the same way. Just call the [populate](./api.html#query_Query-populate) method on the query and an array of documents will be returned _in place_ of the original `_id`s. + Arrays of refs work the same way. Just call the + [populate](./api.html#query_Query-populate) method on the query and an + array of documents will be returned _in place_ of the original `_id`s. .important :markdown - **Note**: mongoose >= 3.6 exposes the original `_ids` used during population through the [document#populated()](./api.html#document_Document-populated) method. + **Note**: mongoose >= 3.6 exposes the original `_ids` used during + population through the + [document#populated()](./api.html#document_Document-populated) method. h3 Setting Populated Fields :markdown In Mongoose >= 4.0, you can manually populate a field as well. @@ -80,13 +97,17 @@ block content console.log(story.author.name); // prints "Ian Fleming" }); :markdown - Note that this only works for single refs. You currently **can't** manually populate an array of refs. + Note that this only works for single refs. You currently **can't** + manually populate an array of refs. h3 Field selection :markdown - What if we only want a few specific fields returned for the populated documents? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: + What if we only want a few specific fields returned for the populated + documents? This can be accomplished by passing the usual + [field name syntax](./api.html#query_Query-select) as the second argument + to the populate method: :js Story. - findOne({ title: /timex/i }). + findOne({ title: /casino royale/i }). populate('author', 'name'). // only return the Persons name exec(function (err, story) { if (err) return handleError(err); @@ -100,14 +121,6 @@ block content h3 Populating multiple paths :markdown What if we wanted to populate multiple paths at the same time? - :js - Story. - find(...). - populate('fans author'). // space delimited path names - exec() - .important - :markdown - In **mongoose >= 3.6**, we can pass a space delimited string of path names to populate. Before 3.6 you must execute the `populate()` method multiple times. :js Story. find(...). @@ -128,7 +141,8 @@ block content Story.find().populate({ path: 'fans', select: 'email' }); h3 Query conditions and other options :markdown - What if we wanted to populate our fans array based on their age, select just their names, and return at most, any 5 of them? + What if we wanted to populate our fans array based on their age, select + just their names, and return at most, any 5 of them? :js Story. find(...). @@ -142,9 +156,15 @@ block content exec() h3 Refs to children :markdown - We may find however, if we use the `author` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' onto `author.stories`. + We may find however, if we use the `author` object, we are unable to get a + list of the stories. This is because no `story` objects were ever 'pushed' + onto `author.stories`. - There are two perspectives here. First, you may want the `author` know which stories are theirs. Usually, your schema should resolve one-to-many relationships by having a parent pointer in the 'many' side. But, if you have a good reason to want an array of child pointers, you can `push()` documents onto the array as shown below. + There are two perspectives here. First, you may want the `author` know + which stories are theirs. Usually, your schema should resolve + one-to-many relationships by having a parent pointer in the 'many' side. + But, if you have a good reason to want an array of child pointers, you + can `push()` documents onto the array as shown below. :js author.stories.push(story1); author.save(callback); @@ -160,7 +180,9 @@ block content }); .important :markdown - It is debatable that we really want two sets of pointers as they may get out of sync. Instead we could skip populating and directly `find()` the stories we are interested in. + It is debatable that we really want two sets of pointers as they may get + out of sync. Instead we could skip populating and directly `find()` the + stories we are interested in. :js Story. find({ author: author._id }). @@ -171,7 +193,13 @@ block content .important :markdown - The documents returned from [query population](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents unless the [lean](./api.html#query_Query-lean) option is specified. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. + The documents returned from + [query population](./api.html#query_Query-populate) become fully + functional, `remove`able, `save`able documents unless the + [lean](./api.html#query_Query-lean) option is specified. Do not confuse + them with [sub docs](./subdocs.html). Take caution when calling its + remove method because you'll be removing it from the database, not just + the array. h3#populate_an_existing_mongoose_document Populating an existing document :markdown From 2d131477ba2cbbe7983f698f94e46f483e899ca4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 19 Aug 2017 18:40:18 -0700 Subject: [PATCH 1795/2240] chore: add ability to start mongod in tests re: #5524 --- .gitignore | 1 + .npmignore | 1 + test/common.js | 41 +++++++++++++++++++++++++++++------------ 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 754313052bc..6e433ac3b97 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ test/triage/*.js bin/mongoose.min.js coverage npm-debug.log +data/ tools/31* diff --git a/.npmignore b/.npmignore index 3d3193b1aa4..8f66a38af64 100644 --- a/.npmignore +++ b/.npmignore @@ -16,3 +16,4 @@ karma.*.js format_deps.js tools/31* *.key +data/ diff --git a/test/common.js b/test/common.js index 9cd8d5b853b..eccc54429a3 100644 --- a/test/common.js +++ b/test/common.js @@ -4,12 +4,14 @@ Error.stackTraceLimit = 10; -var mongoose = require('../'), - Collection = mongoose.Collection, - assert = require('power-assert'), - queryCount = 0, - opened = 0, - closed = 0; +var Server = require('mongodb-topology-manager').Server; +var mongoose = require('../'); +var Collection = mongoose.Collection; +var assert = require('power-assert'); +var queryCount = 0; +var opened = 0; +var closed = 0; +var server; if (process.env.D === '1') { mongoose.set('debug', true); @@ -156,13 +158,28 @@ function dropDBs(done) { }); } +if (process.env.START_MONGOD) { + before(function() { + server = new Server('mongod', { + port: 27017, + dbpath: './data/db', + storageEngine: 'mmapv1' + }); + + return server.purge(). + then(function() { + return server.start(); + }); + }); + + after(function() { + this.timeout(15000); + + return server.stop(); + }); +} + before(function(done) { this.timeout(10 * 1000); dropDBs(done); }); -after(function(done) { - // DropDBs can be extraordinarily slow on 3.2 - //this.timeout(120 * 1000); - //dropDBs(done); - done(); -}); From 36bdf04828d38fbd46027a844a74a75f52ca4b15 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Aug 2017 18:40:12 -0700 Subject: [PATCH 1796/2240] test: add test coverage for stopping/starting mongod --- test/common.js | 12 +++---- test/connection.test.js | 74 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/test/common.js b/test/common.js index eccc54429a3..ca22376ee58 100644 --- a/test/common.js +++ b/test/common.js @@ -160,12 +160,6 @@ function dropDBs(done) { if (process.env.START_MONGOD) { before(function() { - server = new Server('mongod', { - port: 27017, - dbpath: './data/db', - storageEngine: 'mmapv1' - }); - return server.purge(). then(function() { return server.start(); @@ -183,3 +177,9 @@ before(function(done) { this.timeout(10 * 1000); dropDBs(done); }); + +module.exports.server = server = new Server('mongod', { + port: 27017, + dbpath: './data/db', + storageEngine: 'mmapv1' +}); diff --git a/test/connection.test.js b/test/connection.test.js index 96d3fd14abc..cba44ddfe34 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -2,12 +2,14 @@ * Module dependencies. */ -var start = require('./common'); var assert = require('power-assert'); +var muri = require('muri'); +var random = require('../lib/utils').random; +var server = require('./common').server; +var start = require('./common'); + var mongoose = start.mongoose; var Schema = mongoose.Schema; -var random = require('../lib/utils').random; -var muri = require('muri'); /** * Test. @@ -71,6 +73,72 @@ describe('connections:', function() { done(); }).catch(done); }); + + it('events (gh-5498) (gh-5524)', function(done) { + this.timeout(25000); + if (!process.env.START_MONGOD) { + this.skip(); + } + + var conn = mongoose.connect('mongodb://localhost:27017/mongoosetest', { + useMongoClient: true + }); + + var numConnected = 0; + var numDisconnected = 0; + var numReconnected = 0; + conn.on('connected', function() { + ++numConnected; + }); + conn.on('disconnected', function() { + ++numDisconnected; + }); + conn.on('reconnected', function() { + ++numReconnected; + }); + + var stopped = false; + conn. + then(function() { + assert.equal(numConnected, 1); + return server.stop(); + }). + then(function() { + stopped = true; + return new Promise(function(resolve) { + setTimeout(function() { resolve(); }, 50); + }); + }). + then(function() { + assert.equal(numDisconnected, 1); + assert.equal(numReconnected, 0); + }). + then(function() { + return server.start(); + }). + then(function() { + stopped = false; + return new Promise(function(resolve) { + setTimeout(function() { resolve(); }, 2000); + }); + }). + then(function() { + assert.equal(numDisconnected, 1); + assert.equal(numReconnected, 1); + done(); + }). + catch(finish); + + function finish(err) { + if (stopped) { + server.start(). + then(function() { done(err); }). + catch(done); + } else { + done(err); + } + } + }); }); it('should allow closing a closed connection', function(done) { From ca66d56575321a5a71335a764830ba393029c999 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Aug 2017 18:41:03 -0700 Subject: [PATCH 1797/2240] chore(travis): make tests start own mongod in travis --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 88444bbe6ee..d9d70486f6e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,6 @@ before_script: - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.11.tgz - tar -zxvf mongodb-linux-x86_64-2.6.11.tgz - mkdir -p ./data/db - - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --nopreallocj --dbpath ./data/db --syslog --port 27017 script: - - npm test + - env START_MONGOD=1 npm test - npm run lint From 608d0aea44cc76bb5eb7f4461e1dcc6360116f7b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Aug 2017 18:47:32 -0700 Subject: [PATCH 1798/2240] style: fix lint --- test/connection.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/connection.test.js b/test/connection.test.js index cba44ddfe34..5d17691b233 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -2,6 +2,7 @@ * Module dependencies. */ +var Promise = require('bluebird'); var assert = require('power-assert'); var muri = require('muri'); var random = require('../lib/utils').random; From 75941257694d8a0cfb98f393adc4bf00d05b9d9f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Aug 2017 19:03:56 -0700 Subject: [PATCH 1799/2240] test: improve tests re: #5524 --- .travis.yml | 6 ++++-- test/common.js | 23 +++++++++-------------- test/connection.test.js | 37 +++++++++++++++++++------------------ 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/.travis.yml b/.travis.yml index d9d70486f6e..a95635ca18e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,9 @@ node_js: before_script: - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.11.tgz - tar -zxvf mongodb-linux-x86_64-2.6.11.tgz - - mkdir -p ./data/db + - mkdir -p ./data/db/27017 + - mkdir -p ./data/db/27000 + - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --nopreallocj --dbpath ./data/db/27017 --syslog --port 27017 script: - - env START_MONGOD=1 npm test + - npm test - npm run lint diff --git a/test/common.js b/test/common.js index ca22376ee58..b1ceca6fd9d 100644 --- a/test/common.js +++ b/test/common.js @@ -158,20 +158,15 @@ function dropDBs(done) { }); } -if (process.env.START_MONGOD) { - before(function() { - return server.purge(). - then(function() { - return server.start(); - }); - }); +before(function() { + return server.purge(); +}); - after(function() { - this.timeout(15000); +after(function() { + this.timeout(15000); - return server.stop(); - }); -} + return server.stop(); +}); before(function(done) { this.timeout(10 * 1000); @@ -179,7 +174,7 @@ before(function(done) { }); module.exports.server = server = new Server('mongod', { - port: 27017, - dbpath: './data/db', + port: 27000, + dbpath: './data/db/27000', storageEngine: 'mmapv1' }); diff --git a/test/connection.test.js b/test/connection.test.js index 5d17691b233..08fff3fd09a 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -77,29 +77,30 @@ describe('connections:', function() { it('events (gh-5498) (gh-5524)', function(done) { this.timeout(25000); - if (!process.env.START_MONGOD) { - this.skip(); - } - - var conn = mongoose.connect('mongodb://localhost:27017/mongoosetest', { - useMongoClient: true - }); + var conn; + var stopped = false; var numConnected = 0; var numDisconnected = 0; var numReconnected = 0; - conn.on('connected', function() { - ++numConnected; - }); - conn.on('disconnected', function() { - ++numDisconnected; - }); - conn.on('reconnected', function() { - ++numReconnected; - }); + server.start(). + then(function() { + conn = mongoose.connect('mongodb://localhost:27000/mongoosetest', { + useMongoClient: true + }); - var stopped = false; - conn. + conn.on('connected', function() { + ++numConnected; + }); + conn.on('disconnected', function() { + ++numDisconnected; + }); + conn.on('reconnected', function() { + ++numReconnected; + }); + + return conn; + }). then(function() { assert.equal(numConnected, 1); return server.stop(); From f96351ff638ff0c541d638311ad3aaaad78c6f14 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Aug 2017 19:22:58 -0700 Subject: [PATCH 1800/2240] test: fix tests in node 10 --- test/query.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index 249d27a2102..e7638e85686 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -735,8 +735,8 @@ describe('Query', function() { if (typeof global.Map !== 'undefined') { query = new Query({}, {}, null, p1.collection); query.sort(new global.Map().set('a', 1).set('b', 2)); - assert.deepEqual(query.options.sort, - new global.Map().set('a', 1).set('b', 2)); + assert.deepEqual(query.options.sort.toJSON(), + new global.Map().set('a', 1).set('b', 2).toJSON()); } query = new Query({}, {}, null, p1.collection); From 15e4fedd5a28e0d36b97553e8181f28ef442bdc1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Aug 2017 19:29:50 -0700 Subject: [PATCH 1801/2240] test: remove deep equality check --- test/query.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index e7638e85686..67956ecfe65 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -735,8 +735,8 @@ describe('Query', function() { if (typeof global.Map !== 'undefined') { query = new Query({}, {}, null, p1.collection); query.sort(new global.Map().set('a', 1).set('b', 2)); - assert.deepEqual(query.options.sort.toJSON(), - new global.Map().set('a', 1).set('b', 2).toJSON()); + assert.equal(query.options.sort.get('a'), 1); + assert.equal(query.options.sort.get('b'), 2); } query = new Query({}, {}, null, p1.collection); From c04f2475ce0a4ee03e5bcb08b1e790f93c1e261a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 21 Aug 2017 21:24:00 -0700 Subject: [PATCH 1802/2240] chore: bump lock file --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 500075eba35..ef3088804d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.11.7-pre", + "version": "4.11.8-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From 0c3016fe9ce71bfd185dd4d45ac071d2b3c0f966 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 21 Aug 2017 22:08:32 -0700 Subject: [PATCH 1803/2240] test(model): repro #5548 --- lib/plugins/idGetter.js | 26 ++++++++++++++++++++++++++ test/model.test.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 lib/plugins/idGetter.js diff --git a/lib/plugins/idGetter.js b/lib/plugins/idGetter.js new file mode 100644 index 00000000000..186aceb55c3 --- /dev/null +++ b/lib/plugins/idGetter.js @@ -0,0 +1,26 @@ +'use strict'; + +/*! + * ignore + */ + +module.exports = function(schema) { + // ensure the documents receive an id getter unless disabled + var autoIdGetter = !schema.paths['id'] && + (!schema.options.noVirtualId && schema.options.id); + if (autoIdGetter) { + schema.virtual('id').get(idGetter); + } +}; + +/*! + * Returns this documents _id cast to a string. + */ + +function idGetter() { + if (this._id != null) { + return String(this._id); + } + + return null; +} diff --git a/test/model.test.js b/test/model.test.js index 8ce70ca44d8..cf94c96ea92 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5512,6 +5512,34 @@ describe('Model', function() { }); }); + it('disabling id getter with .set() (gh-5548)', function(done) { + var ChildSchema = new mongoose.Schema({ + name: String, + _id: false + }); + + ChildSchema.set('id', false); + + var ParentSchema = new mongoose.Schema({ + child: { + type: ChildSchema, + default: {} + } + }, { id: false }); + + var Parent = db.model('gh5548', ParentSchema); + + var doc = new Parent({ child: { name: 'test' } }); + assert.ok(!doc.id); + assert.ok(!doc.child.id); + + var obj = doc.toObject({ virtuals: true }); + assert.ok(!('id' in obj)); + assert.ok(!('id' in obj.child)); + + done(); + }); + it('creates new array when initializing from existing doc (gh-4449)', function(done) { var TodoSchema = new mongoose.Schema({ title: String From 97c9f40ed900400c530340415b8c4d7732b2ba90 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 21 Aug 2017 22:08:34 -0700 Subject: [PATCH 1804/2240] fix(model): allow setting `id` property after schema was created Re: #5548 --- lib/index.js | 4 +++- lib/schema.js | 19 ------------------ test/document.test.js | 3 +++ test/model.field.selection.test.js | 2 +- test/schema.test.js | 32 ++---------------------------- test/types.documentarray.test.js | 24 ++++++++++++---------- 6 files changed, 23 insertions(+), 61 deletions(-) diff --git a/lib/index.js b/lib/index.js index d686912c772..2fc6ae65f49 100644 --- a/lib/index.js +++ b/lib/index.js @@ -16,6 +16,7 @@ var utils = require('./utils'); var format = utils.toCollectionName; var pkg = require('../package.json'); +var idGetter = require('./plugins/idGetter'); var querystring = require('querystring'); var saveSubdocs = require('./plugins/saveSubdocs'); var validateBeforeSave = require('./plugins/validateBeforeSave'); @@ -51,7 +52,8 @@ function Mongoose() { value: [ [saveSubdocs, { deduplicate: true }], [validateBeforeSave, { deduplicate: true }], - [shardingPlugin, { deduplicate: true }] + [shardingPlugin, { deduplicate: true }], + [idGetter, { deduplicate: true }] ] }); } diff --git a/lib/schema.js b/lib/schema.js index 04976b9d074..e673e0b6ac7 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -115,13 +115,6 @@ function Schema(obj, options) { this.add(_obj); } - // ensure the documents receive an id getter unless disabled - var autoid = !this.paths['id'] && - (!this.options.noVirtualId && this.options.id); - if (autoid) { - this.virtual('id').get(idGetter); - } - for (var i = 0; i < this._defaultMiddleware.length; ++i) { var m = this._defaultMiddleware[i]; this[m.kind](m.hook, !!m.isAsync, m.fn); @@ -171,18 +164,6 @@ function aliasFields(schema) { } } -/*! - * Returns this documents _id cast to a string. - */ - -function idGetter() { - if (this._id != null) { - return String(this._id); - } - - return null; -} - /*! * Inherit from EventEmitter. */ diff --git a/test/document.test.js b/test/document.test.js index 4c9cb25a35a..4cde7e707fb 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -19,6 +19,8 @@ var EmbeddedDocument = require('../lib/types/embedded'); var Query = require('../lib/query'); var validator = require('validator'); +var idGetter = require('../lib/plugins/idGetter'); + var _ = require('lodash'); /** @@ -69,6 +71,7 @@ var schema = new Schema({ em: [em], date: Date }); +schema.plugin(idGetter); TestDocument.prototype.$__setSchema(schema); schema.virtual('nested.agePlus2').get(function() { diff --git a/test/model.field.selection.test.js b/test/model.field.selection.test.js index 726600461d2..903f7988f9c 100644 --- a/test/model.field.selection.test.js +++ b/test/model.field.selection.test.js @@ -177,7 +177,7 @@ describe('model field selection', function() { assert.equal(found[0].comments[0].title, ':)'); assert.strictEqual(undefined, found[0].comments[0]._id); // gh-590 - assert.strictEqual(null, found[0].comments[0].id); + assert.ok(!found[0].comments[0].id); done(); }); }); diff --git a/test/schema.test.js b/test/schema.test.js index 5fcad95fc82..b4141fe7528 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -735,35 +735,6 @@ describe('schema', function() { assert.equal(schema.path('_id'), undefined); done(); }); - - it('auto id', function(done) { - var schema = new Schema({ - name: String - }); - assert.ok(schema.virtualpath('id') instanceof mongoose.VirtualType); - - schema = new Schema({ - name: String - }, {id: true}); - assert.ok(schema.virtualpath('id') instanceof mongoose.VirtualType); - - schema = new Schema({ - name: String - }, {id: false}); - assert.equal(schema.virtualpath('id'), undefined); - - // old options - schema = new Schema({ - name: String - }, {noVirtualId: false}); - assert.ok(schema.virtualpath('id') instanceof mongoose.VirtualType); - - schema = new Schema({ - name: String - }, {noVirtualId: true}); - assert.equal(schema.virtualpath('id'), undefined); - done(); - }); }); describe('hooks', function() { @@ -1455,6 +1426,7 @@ describe('schema', function() { docs: [{x: [{y: String}]}], mixed: {} }); + schema.virtual('myVirtual').get(function() { return 42; }); }); describe('when called on an explicit real path', function() { @@ -1470,7 +1442,7 @@ describe('schema', function() { }); describe('when called on a virtual', function() { it('returns virtual', function(done) { - assert.equal(schema.pathType('id'), 'virtual'); + assert.equal(schema.pathType('myVirtual'), 'virtual'); done(); }); }); diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js index b5197ae0512..4d9b3712095 100644 --- a/test/types.documentarray.test.js +++ b/test/types.documentarray.test.js @@ -2,16 +2,18 @@ * Module dependencies. */ -var start = require('./common'), - mongoose = require('./common').mongoose, - random = require('../lib/utils').random, - setValue = require('../lib/utils').setValue, - MongooseDocumentArray = mongoose.Types.DocumentArray, - EmbeddedDocument = require('../lib/types/embedded'), - DocumentArray = require('../lib/types/documentarray'), - Schema = mongoose.Schema, - assert = require('power-assert'), - collection = 'types.documentarray_' + random(); +var start = require('./common'); +var mongoose = require('./common').mongoose; +var random = require('../lib/utils').random; +var setValue = require('../lib/utils').setValue; +var MongooseDocumentArray = mongoose.Types.DocumentArray; +var EmbeddedDocument = require('../lib/types/embedded'); +var DocumentArray = require('../lib/types/documentarray'); +var Schema = mongoose.Schema; +var assert = require('power-assert'); +var collection = 'types.documentarray_' + random(); + +var idGetter = require('../lib/plugins/idGetter'); /** * Setup. @@ -36,6 +38,8 @@ function TestDoc(schema) { title: {type: String} }); + (schema || SubSchema).plugin(idGetter); + Subdocument.prototype.$__setSchema(schema || SubSchema); return Subdocument; From aeb6915c63b6badfe2f6f23fa6409b96c460ba81 Mon Sep 17 00:00:00 2001 From: efkan Date: Tue, 22 Aug 2017 13:29:31 +0300 Subject: [PATCH 1805/2240] Adding warning regarding ObjectId usage Let me save a lot of time our civilization :) Sometimes we can try to generate an ObjectId or wrap an ObjectId key in somewhere in our code by using 'mongoose.Schema.ObjectId'. Then we can spend minutes or hours to realize about what happened. Thanks to this warning many developers may save time. --- lib/schema/objectid.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index 2f908023686..133e13c41c0 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -20,6 +20,9 @@ var SchemaType = require('../schematype'), */ function ObjectId(key, options) { + if ((typeof key === 'string' && key.length === 24) || typeof key === 'undefined') { + console.warn('To create a new ObjectId please try `Mongoose.Types.ObjectId` instead of using `Mongoose.Schema.ObjectId` definition.'); + } SchemaType.call(this, key, options, 'ObjectID'); } From b220e269ec7c12d48c7e570149191c4f1d5e6572 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 22 Aug 2017 09:50:31 -0700 Subject: [PATCH 1806/2240] fix(model): defer idGetter until schema is compiled Fix #5548 --- lib/document.js | 2 ++ lib/index.js | 4 +--- lib/schema/objectid.js | 4 +++- test/document.test.js | 4 +--- test/model.update.test.js | 9 +++++---- test/schema.alias.test.js | 4 ++-- test/types.documentarray.test.js | 4 ---- 7 files changed, 14 insertions(+), 17 deletions(-) diff --git a/lib/document.js b/lib/document.js index 4d6200da3e3..cc95ef5358c 100644 --- a/lib/document.js +++ b/lib/document.js @@ -24,6 +24,7 @@ var MongooseArray; var Embedded; var flatten = require('./services/common').flatten; var mpath = require('mpath'); +var idGetter = require('./plugins/idGetter'); /** * Document constructor. @@ -1994,6 +1995,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { */ Document.prototype.$__setSchema = function(schema) { + schema.plugin(idGetter, { deduplicate: true }); compile(schema.tree, this, undefined, schema.options); this.schema = schema; }; diff --git a/lib/index.js b/lib/index.js index b8c59fc48c7..b54e8b97568 100644 --- a/lib/index.js +++ b/lib/index.js @@ -16,7 +16,6 @@ var utils = require('./utils'); var format = utils.toCollectionName; var pkg = require('../package.json'); -var idGetter = require('./plugins/idGetter'); var querystring = require('querystring'); var saveSubdocs = require('./plugins/saveSubdocs'); var validateBeforeSave = require('./plugins/validateBeforeSave'); @@ -52,8 +51,7 @@ function Mongoose() { value: [ [saveSubdocs, { deduplicate: true }], [validateBeforeSave, { deduplicate: true }], - [shardingPlugin, { deduplicate: true }], - [idGetter, { deduplicate: true }] + [shardingPlugin, { deduplicate: true }] ] }); } diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index 133e13c41c0..1dbc23e2678 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -21,7 +21,9 @@ var SchemaType = require('../schematype'), function ObjectId(key, options) { if ((typeof key === 'string' && key.length === 24) || typeof key === 'undefined') { - console.warn('To create a new ObjectId please try `Mongoose.Types.ObjectId` instead of using `Mongoose.Schema.ObjectId` definition.'); + console.warn('To create a new ObjectId please try ' + + '`Mongoose.Types.ObjectId` instead of using ' + + '`Mongoose.Schema.ObjectId`.'); } SchemaType.call(this, key, options, 'ObjectID'); } diff --git a/test/document.test.js b/test/document.test.js index 4cde7e707fb..6cba7e29118 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -19,8 +19,6 @@ var EmbeddedDocument = require('../lib/types/embedded'); var Query = require('../lib/query'); var validator = require('validator'); -var idGetter = require('../lib/plugins/idGetter'); - var _ = require('lodash'); /** @@ -71,7 +69,7 @@ var schema = new Schema({ em: [em], date: Date }); -schema.plugin(idGetter); + TestDocument.prototype.$__setSchema(schema); schema.virtual('nested.agePlus2').get(function() { diff --git a/test/model.update.test.js b/test/model.update.test.js index aacc6e806c5..81a4b886ba3 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -466,14 +466,15 @@ describe('model: update:', function() { }); it('handles $pull with obj literal (gh-542)', function(done) { - var db = start(), - BlogPost = db.model('BlogPostForUpdates', collection); + var db = start(); + var BlogPost = db.model('BlogPostForUpdates', collection); - BlogPost.findById(post, function(err, last) { + + BlogPost.findById(post, function(err, doc) { assert.ifError(err); var update = { - $pull: {comments: {_id: last.comments[0].id}} + $pull: {comments: {_id: doc.comments[0].id}} }; BlogPost.update({_id: post._id}, update, function(err) { diff --git a/test/schema.alias.test.js b/test/schema.alias.test.js index f696e6f992d..a47bc44a018 100644 --- a/test/schema.alias.test.js +++ b/test/schema.alias.test.js @@ -31,7 +31,7 @@ describe('schema alias option', function() { buffer: new Buffer('World'), boolean: false, mixed: [1, [], 'three', { four: 5 }], - objectId: new Schema.Types.ObjectId(), + objectId: new mongoose.Types.ObjectId(), array: ['a', 'b', 'c', 'd'] }, function(err, s) { assert.ifError(err); @@ -76,7 +76,7 @@ describe('schema alias option', function() { buffer: new Buffer('World'), boolean: false, mixed: [1, [], 'three', { four: 5 }], - objectId: new Schema.Types.ObjectId(), + objectId: new mongoose.Types.ObjectId(), array: ['a', 'b', 'c', 'd'] } }, function(err, s) { diff --git a/test/types.documentarray.test.js b/test/types.documentarray.test.js index 4d9b3712095..0a9cc16052d 100644 --- a/test/types.documentarray.test.js +++ b/test/types.documentarray.test.js @@ -13,8 +13,6 @@ var Schema = mongoose.Schema; var assert = require('power-assert'); var collection = 'types.documentarray_' + random(); -var idGetter = require('../lib/plugins/idGetter'); - /** * Setup. */ @@ -38,8 +36,6 @@ function TestDoc(schema) { title: {type: String} }); - (schema || SubSchema).plugin(idGetter); - Subdocument.prototype.$__setSchema(schema || SubSchema); return Subdocument; From a153d23ff3ef6f21164daec87d8601f76393d411 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 23 Aug 2017 19:26:15 -0700 Subject: [PATCH 1807/2240] chore: release 4.11.8 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ef86974c7fb..aca9f903cbd 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.11.8 / 2017-08-23 +=================== + * feat: add warning about using schema ObjectId as type ObjectId #5571 [efkan](https://github.com/efkan) + * fix(schema): allow setting `id` property after schema was created #5570 #5548 + * docs(populate): remove confusing _ from populate docs #5560 + * fix(connection): expose parsed uri fields (host, port, dbname) when using openUri() #5556 + * docs: added type boolean to options documentation #5547 [ndabAP](https://github.com/ndabAP) + * test: add test coverage for stopping/starting server #5524 + * fix(aggregate): pull read preference from schema by default #5522 + 4.11.7 / 2017-08-14 =================== * fix: correct properties when calling toJSON() on populated virtual #5544 #5442 [davidwu226](https://github.com/davidwu226) diff --git a/package.json b/package.json index d06dfe4fdb3..d9939b4611e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.8-pre", + "version": "4.11.8", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 45e36abe28f367792e8dd7931bff13c1cace10dd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 23 Aug 2017 19:28:21 -0700 Subject: [PATCH 1808/2240] chore: now working on 4.11.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d9939b4611e..1f0301f3d0f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.8", + "version": "4.11.9-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From b728cc7c93bd706c6b83ac338feab4b5949c372d Mon Sep 17 00:00:00 2001 From: dmric Date: Thu, 24 Aug 2017 10:57:32 +0300 Subject: [PATCH 1809/2240] Use story schema defined key author instead of creator. --- docs/populate.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/populate.jade b/docs/populate.jade index 7427aadff4e..34174d5f47e 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -69,7 +69,7 @@ block content populate('author'). exec(function (err, story) { if (err) return handleError(err); - console.log('The author is %s', story.creator.name); + console.log('The author is %s', story.author.name); // prints "The author is Ian Fleming" }); :markdown From 3e701940dad7d363500f4dbd55bb386c77360399 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 24 Aug 2017 19:41:21 -0700 Subject: [PATCH 1810/2240] fix(error): avoid using arguments.callee because that breaks strict mode Fix #5572 --- lib/error/browserMissingSchema.js | 6 +++++- lib/error/divergentArray.js | 6 +++++- lib/error/missingSchema.js | 6 +++++- lib/error/overwriteModel.js | 6 +++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/error/browserMissingSchema.js b/lib/error/browserMissingSchema.js index cbf5e0e151a..898915596db 100644 --- a/lib/error/browserMissingSchema.js +++ b/lib/error/browserMissingSchema.js @@ -15,7 +15,11 @@ function MissingSchemaError() { + 'Use mongoose.Document(name, schema)'; MongooseError.call(this, msg); this.name = 'MissingSchemaError'; - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack; + } } /*! diff --git a/lib/error/divergentArray.js b/lib/error/divergentArray.js index 3702f8bcc32..473f7dc446f 100644 --- a/lib/error/divergentArray.js +++ b/lib/error/divergentArray.js @@ -24,7 +24,11 @@ function DivergentArrayError(paths) { MongooseError.call(this, msg); this.name = 'DivergentArrayError'; - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack; + } } /*! diff --git a/lib/error/missingSchema.js b/lib/error/missingSchema.js index 1870c24531d..a2445b40364 100644 --- a/lib/error/missingSchema.js +++ b/lib/error/missingSchema.js @@ -16,7 +16,11 @@ function MissingSchemaError(name) { + 'Use mongoose.model(name, schema)'; MongooseError.call(this, msg); this.name = 'MissingSchemaError'; - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack; + } } /*! diff --git a/lib/error/overwriteModel.js b/lib/error/overwriteModel.js index fad00d24061..85c29c8c935 100644 --- a/lib/error/overwriteModel.js +++ b/lib/error/overwriteModel.js @@ -14,7 +14,11 @@ var MongooseError = require('../error.js'); function OverwriteModelError(name) { MongooseError.call(this, 'Cannot overwrite `' + name + '` model once compiled.'); this.name = 'OverwriteModelError'; - Error.captureStackTrace && Error.captureStackTrace(this, arguments.callee); + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack; + } } /*! From e2790f6609d13206221a066932c34f682d4e3c0b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 25 Aug 2017 09:31:35 -0700 Subject: [PATCH 1811/2240] fix(browser): rely on browser entrypoint to decide whether to use BrowserDocument or NodeDocument Fix #5480 --- lib/browser.js | 5 ++++- lib/document_provider.js | 11 ++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/browser.js b/lib/browser.js index a787539caf3..53605e516b3 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -1,7 +1,10 @@ /* eslint-env browser */ +var DocumentProvider = require('./document_provider.js'); var PromiseProvider = require('./promise_provider'); +DocumentProvider.setBrowser(true); + /** * The Mongoose [Promise](#promise_Promise) constructor. * @@ -114,7 +117,7 @@ exports.utils = require('./utils.js'); * @method Document * @api public */ -exports.Document = require('./document_provider.js')(); +exports.Document = DocumentProvider(); /*! * Module exports. diff --git a/lib/document_provider.js b/lib/document_provider.js index 10087cc94d8..738b7d7cf56 100644 --- a/lib/document_provider.js +++ b/lib/document_provider.js @@ -8,14 +8,23 @@ var Document = require('./document.js'); var BrowserDocument = require('./browserDocument.js'); +var isBrowser = false; + /** * Returns the Document constructor for the current context * * @api private */ module.exports = function() { - if (typeof window !== 'undefined' && typeof document !== 'undefined' && document === window.document) { + if (isBrowser) { return BrowserDocument; } return Document; }; + +/*! + * ignore + */ +module.exports.setBrowser = function(flag) { + isBrowser = flag; +}; From 26d96026ef7dd8e16009b67a992c534f0826244f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 26 Aug 2017 19:18:06 -0700 Subject: [PATCH 1812/2240] test(query): repro #5551 --- test/model.findOneAndUpdate.test.js | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index ed0a95037b1..ea6f3561263 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -12,6 +12,8 @@ var Schema = mongoose.Schema; var ObjectId = Schema.Types.ObjectId; var DocumentObjectId = mongoose.Types.ObjectId; var _ = require('lodash'); +var uuid = require('uuid'); +var uuidParse = require('uuid-parse'); describe('model: findOneAndUpdate:', function() { var Comments; @@ -1862,6 +1864,43 @@ describe('model: findOneAndUpdate:', function() { }); }); + it('setting subtype when saving (gh-5551)', function(done) { + function toUUID(string) { + if (!string) {return null;} + if (Buffer.isBuffer(string) || Buffer.isBuffer(string.buffer)) { + return string; + } + var buffer = uuidParse.parse(string); + return new mongoose.Types.Buffer(buffer).toObject(0x04); + } + + var UserSchema = new mongoose.Schema({ + name: String, + foo: { + type: mongoose.Schema.Types.Buffer, + set: toUUID + } + }); + + var User = db.model('gh5551', UserSchema); + + user = {name: 'upsert', foo: uuid.v4()}; + var opts = { + upsert: true, + setDefaultsOnInsert: true, + runSettersOnQuery: true, + new: true + }; + User.findOneAndUpdate({}, user, opts).exec(function(error, doc) { + assert.ifError(error); + User.collection.findOne({ _id: doc._id }, function(error, doc) { + assert.ifError(error); + assert.equal(doc.foo.sub_type, 4); + done(); + }); + }); + }); + it('properly handles casting nested objects in update (gh-4724)', function(done) { var locationSchema = new Schema({ _id: false, From c434ca95b75be717c5ea4d2baa3333ca2913f6b2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 26 Aug 2017 19:18:22 -0700 Subject: [PATCH 1813/2240] fix(query): enforce binary subtype always propagates to mongodb Fix #5551 --- lib/types/buffer.js | 13 +++++++++++++ package-lock.json | 8 +++++++- package.json | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/types/buffer.js b/lib/types/buffer.js index 8be67c80a5e..9d7d4f26bf5 100644 --- a/lib/types/buffer.js +++ b/lib/types/buffer.js @@ -203,6 +203,19 @@ MongooseBuffer.mixin.toObject = function(options) { return new Binary(this, subtype); }; +/** + * Converts this buffer for storage in MongoDB, including subtype + * + * @return {Binary} + * @api public + * @method toBSON + * @receiver MongooseBuffer + */ + +MongooseBuffer.mixin.toBSON = function() { + return new Binary(this, this._subtype || 0); +}; + /** * Determines if this buffer is equals to `other` buffer * diff --git a/package-lock.json b/package-lock.json index ef3088804d0..2817225881f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.11.8-pre", + "version": "4.11.9-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3012,6 +3012,12 @@ "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", "dev": true }, + "uuid-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.0.0.tgz", + "integrity": "sha1-9GV3F2JLDkuIrzb5jYlYmlu+5Wk=", + "dev": true + }, "validator": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/validator/-/validator-5.4.0.tgz", diff --git a/package.json b/package.json index 1f0301f3d0f..a16067aceae 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "tbd": "0.6.4", "uglify-js": "2.7.0", "uuid": "2.0.3", + "uuid-parse": "1.0.0", "validator": "5.4.0" }, "browserDependencies": { From 402462e140e646a42adcecb9531830b193cfa6a0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 26 Aug 2017 19:22:30 -0700 Subject: [PATCH 1814/2240] style: fix lint --- test/model.findOneAndUpdate.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index ea6f3561263..b407992a0d3 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1884,7 +1884,7 @@ describe('model: findOneAndUpdate:', function() { var User = db.model('gh5551', UserSchema); - user = {name: 'upsert', foo: uuid.v4()}; + var user = { name: 'upsert', foo: uuid.v4() }; var opts = { upsert: true, setDefaultsOnInsert: true, From 7569dd49974882b74403f0ded0e9dbd93b2afefc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 26 Aug 2017 19:29:18 -0700 Subject: [PATCH 1815/2240] test: fix tests on 0.x --- test/model.findOneAndUpdate.test.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index b407992a0d3..9b6fa02a6bb 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -13,7 +13,6 @@ var ObjectId = Schema.Types.ObjectId; var DocumentObjectId = mongoose.Types.ObjectId; var _ = require('lodash'); var uuid = require('uuid'); -var uuidParse = require('uuid-parse'); describe('model: findOneAndUpdate:', function() { var Comments; @@ -1865,8 +1864,16 @@ describe('model: findOneAndUpdate:', function() { }); it('setting subtype when saving (gh-5551)', function(done) { + if (parseInt(process.version.substr(1).split('.')[0], 10) < 4) { + // Don't run on node 0.x because of `const` issues + this.skip(); + } + + var uuidParse = require('uuid-parse'); function toUUID(string) { - if (!string) {return null;} + if (!string) { + return null; + } if (Buffer.isBuffer(string) || Buffer.isBuffer(string.buffer)) { return string; } From 3c598403aa6d122de9c8c48b77fbe5f47fe8090a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 26 Aug 2017 23:06:30 -0700 Subject: [PATCH 1816/2240] docs(schematypes): fix spacing re: #5567 --- docs/schematypes.jade | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index 5f0c13b6759..2cceb02ad2b 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -3,25 +3,25 @@ extends layout block content h2 SchemaTypes p - | SchemaTypes handle definition of path + | SchemaTypes handle definition of path  a(href="./api.html#schematype_SchemaType-default") defaults - |, + |,  a(href="./api.html#schematype_SchemaType-validate") validation - |, + |,  a(href="./api.html#schematype_SchemaType-get") getters - |, + |,  a(href="./api.html#schematype_SchemaType-set") setters - |, + |,  a(href="./api.html#schematype_SchemaType-select") field selection defaults - | for + | for  a(href="./api.html#query-js") queries - | and other general characteristics for + | and other general characteristics for  a(href="./api.html#schema-string-js") Strings | and a(href="./api.html#schema-number-js") Numbers |. Check out their respective API documentation for more detail. p - | Following are all valid + | Following are all valid  a(href="./api.html#schema_Schema.Types") Schema Types |. :markdown From c0eb6ff27697891c99b48ae4fbe61e146b2d6a38 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 27 Aug 2017 16:50:31 -0700 Subject: [PATCH 1817/2240] fix(query): only skip castForQuery for mongoose arrays Fix #5536 --- lib/services/query/castUpdate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index 75c20032ac0..9417e71be18 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -308,7 +308,7 @@ function castUpdateVal(schema, val, op, $conditional, context) { return schema.castForQueryWrapper({ val: val, context: context, - $skipQueryCastForUpdate: val != null + $skipQueryCastForUpdate: val != null && schema.$isMongooseArray }); } From e5c9a6d80a849cb1377b87397f77c31aad5ab3ea Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 27 Aug 2017 17:11:18 -0700 Subject: [PATCH 1818/2240] chore: release 4.11.9 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index aca9f903cbd..6ac66f4a9c3 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.11.9 / 2017-08-27 +=================== + * fix(error): avoid using arguments.callee because that breaks strict mode #5572 + * docs(schematypes): fix spacing #5567 + * fix(query): enforce binary subtype always propagates to mongodb #5551 + * fix(query): only skip castForQuery for mongoose arrays #5536 + * fix(browser): rely on browser entrypoint to decide whether to use BrowserDocument or NodeDocument #5480 + 4.11.8 / 2017-08-23 =================== * feat: add warning about using schema ObjectId as type ObjectId #5571 [efkan](https://github.com/efkan) diff --git a/package.json b/package.json index a16067aceae..01d6362a99e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.9-pre", + "version": "4.11.9", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 6ee8552a8680c79d572471dd74fa834a541262ec Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 27 Aug 2017 17:13:40 -0700 Subject: [PATCH 1819/2240] chore: now working on 4.11.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 01d6362a99e..8ea1e157f1c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.9", + "version": "4.11.10-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 2a16f2aa066d2c75c29514d784a4334fe6e6ec8e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 27 Aug 2017 18:34:06 -0700 Subject: [PATCH 1820/2240] chore: now working on 4.12.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ea1e157f1c..a5d04e107d9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.10-pre", + "version": "4.12.0-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 6bd317208680e024b9d5fe2ba20dbdb8fcce0e12 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 27 Aug 2017 18:53:23 -0700 Subject: [PATCH 1821/2240] fix(collection): use createIndex() instead of deprecated ensureIndex() Fix #3280 --- docs/guide.jade | 6 +++--- lib/collection.js | 8 ++++++++ lib/drivers/node-mongodb-native/collection.js | 14 +++++++++++--- lib/model.js | 19 +++++++++---------- test/common.js | 1 + 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/docs/guide.jade b/docs/guide.jade index 553ee21371f..aad9d101234 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -166,8 +166,8 @@ block content .important :markdown - When your application starts up, Mongoose automatically calls `ensureIndex` for each defined index in your schema. - Mongoose will call `ensureIndex` for each index sequentially, and emit an 'index' event on the model when all the `ensureIndex` calls succeeded or when there was an error. + When your application starts up, Mongoose automatically calls [`createIndex`](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex) for each defined index in your schema. + Mongoose will call `createIndex` for each index sequentially, and emit an 'index' event on the model when all the `createIndex` calls succeeded or when there was an error. While nice for development, it is recommended this behavior be disabled in production since index creation can cause a [significant performance impact](http://docs.mongodb.org/manual/core/indexes/#index-creation-operations). Disable the behavior by setting the `autoIndex` option of your schema to `false`, or globally on the connection by setting the option `config.autoIndex` to `false`. :js @@ -317,7 +317,7 @@ block content h4#autoIndex option: autoIndex :markdown - At application startup, Mongoose sends an `ensureIndex` command for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model.ensureIndexes) method on your model. + At application startup, Mongoose sends a [`createIndex` command](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex) for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model.ensureIndexes) method on your model. :js var schema = new Schema({..}, { autoIndex: false }); var Clock = mongoose.model('Clock', schema); diff --git a/lib/collection.js b/lib/collection.js index e550ec2da58..f13721c6113 100644 --- a/lib/collection.js +++ b/lib/collection.js @@ -139,6 +139,14 @@ Collection.prototype.ensureIndex = function() { throw new Error('Collection#ensureIndex unimplemented by driver'); }; +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.createIndex = function() { + throw new Error('Collection#ensureIndex unimplemented by driver'); +}; + /** * Abstract method that drivers must implement. */ diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js index 49cd41acfe9..6c9f20b89f9 100644 --- a/lib/drivers/node-mongodb-native/collection.js +++ b/lib/drivers/node-mongodb-native/collection.js @@ -2,9 +2,10 @@ * Module dependencies. */ -var MongooseCollection = require('../../collection'), - Collection = require('mongodb').Collection, - utils = require('../../utils'); +var MongooseCollection = require('../../collection'); +var Collection = require('mongodb').Collection; +var util = require('util'); +var utils = require('../../utils'); /** * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) collection implementation. @@ -151,6 +152,13 @@ for (var i in Collection.prototype) { iter(i); } +/*! + * ignore + */ + +Collection.prototype.ensureIndex = util.deprecate(Collection.prototype.ensureIndex, + '`ensureIndex()` is deprecated in Mongoose >= 4.12.0, use `createIndex()` instead'); + /** * Debug print helper * diff --git a/lib/model.js b/lib/model.js index c594c6d73db..01c7d55b9a9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -865,18 +865,19 @@ for (var i in EventEmitter.prototype) { Model.init = function init() { if ((this.schema.options.autoIndex) || (this.schema.options.autoIndex == null && this.db.config.autoIndex)) { - this.ensureIndexes({ __noPromise: true, _automatic: true }); + this.createIndexes({ __noPromise: true, _automatic: true }); } this.schema.emit('init', this); }; /** - * Sends `ensureIndex` commands to mongo for each index declared in the schema. + * Sends `createIndex` commands to mongo for each index declared in the schema. + * The `createIndex` commands are sent in series. * * ####Example: * - * Event.ensureIndexes(function (err) { + * Event.createIndexes(function (err) { * if (err) return handleError(err); * }); * @@ -893,22 +894,20 @@ Model.init = function init() { * * _NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution._ * - * The `ensureIndex` commands are not sent in parallel. This is to avoid the `MongoError: cannot add index with a background operation in progress` error. See [this ticket](https://github.com/Automattic/mongoose/issues/1365) for more information. - * * @param {Object} [options] internal options * @param {Function} [cb] optional callback * @return {Promise} * @api public */ -Model.ensureIndexes = function ensureIndexes(options, callback) { +Model.createIndexes = Model.ensureIndexes = function createIndexes(options, callback) { if (typeof options === 'function') { callback = options; options = null; } if (options && options.__noPromise) { - _ensureIndexes(this, options, callback); + _createIndexes(this, options, callback); return; } @@ -919,7 +918,7 @@ Model.ensureIndexes = function ensureIndexes(options, callback) { var _this = this; var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { - _ensureIndexes(_this, options || {}, function(error) { + _createIndexes(_this, options || {}, function(error) { if (error) { callback && callback(error); reject(error); @@ -930,7 +929,7 @@ Model.ensureIndexes = function ensureIndexes(options, callback) { }); }; -function _ensureIndexes(model, options, callback) { +function _createIndexes(model, options, callback) { var indexes = model.schema.indexes(); var done = function(err) { @@ -974,7 +973,7 @@ function _ensureIndexes(model, options, callback) { indexSingleStart(indexFields, options); - model.collection.ensureIndex(indexFields, indexOptions, utils.tick(function(err, name) { + model.collection.createIndex(indexFields, indexOptions, utils.tick(function(err, name) { indexSingleDone(err, indexFields, indexOptions, name); if (err) { return done(err); diff --git a/test/common.js b/test/common.js index b1ceca6fd9d..041ac8d25ab 100644 --- a/test/common.js +++ b/test/common.js @@ -22,6 +22,7 @@ if (process.env.D === '1') { */ [ + 'createIndex', 'ensureIndex', 'findAndModify', 'findOne', From 9c487909a21a128dae8ed434cf3bd4630129d64e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 28 Aug 2017 17:06:08 -0700 Subject: [PATCH 1822/2240] fix: remove jest warning No longer necessary because we removed the check that switched between node doc and browser doc based on presence of `window` Re: https://github.com/Automattic/mongoose/commit/c1de420f34b1cbdce888d7481b412080a77070b0#commitcomment-23791131 Re: #5480 --- lib/index.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/index.js b/lib/index.js index b54e8b97568..e76a57eb436 100644 --- a/lib/index.js +++ b/lib/index.js @@ -858,13 +858,3 @@ MongooseThenable.prototype.catch = function(onRejected) { */ var mongoose = module.exports = exports = new Mongoose; - -/*! - * ignore - */ - -if (typeof jest !== 'undefined' && typeof window !== 'undefined') { - console.warn('You are running mongoose with jest in the jsdom environment. ' + - 'You probably do not want to do this. Switch to the node environment: ' + - 'https://facebook.github.io/jest/docs/configuration.html#testenvironment-string'); -} From 3801abbec59209a1b6a1ebcde0f55fe965194119 Mon Sep 17 00:00:00 2001 From: Kevin Burke Date: Mon, 28 Aug 2017 18:39:22 -0700 Subject: [PATCH 1823/2240] Spell "Jason Bourne" correctly I assume you are referring to Jason Bourne, the fictional film and book star, and not Jason Borne, Austin-based digital artist. See https://en.wikipedia.org/wiki/Jason_Bourne. --- docs/2.7.x/docs/updating-documents.html | 14 +++++------ docs/2.8.x/docs/updating-documents.html | 14 +++++------ docs/3.0.x/docs/api.html | 32 ++++++++++++------------- docs/3.0.x/docs/source/_docs | 12 +++++----- docs/3.1.x/docs/api.html | 32 ++++++++++++------------- docs/3.1.x/docs/source/_docs | 12 +++++----- docs/3.2.x/docs/api.html | 32 ++++++++++++------------- docs/3.2.x/docs/source/_docs | 12 +++++----- docs/3.3.x/docs/api.html | 32 ++++++++++++------------- docs/3.3.x/docs/source/_docs | 12 +++++----- docs/3.4.x/docs/api.html | 32 ++++++++++++------------- docs/3.4.x/docs/source/_docs | 12 +++++----- docs/3.5.x/docs/api.html | 32 ++++++++++++------------- docs/3.5.x/docs/source/_docs | 12 +++++----- docs/api.html | 32 ++++++++++++------------- lib/model.js | 26 ++++++++++---------- 16 files changed, 175 insertions(+), 175 deletions(-) diff --git a/docs/2.7.x/docs/updating-documents.html b/docs/2.7.x/docs/updating-documents.html index 8d7209e1c3b..9982420f703 100644 --- a/docs/2.7.x/docs/updating-documents.html +++ b/docs/2.7.x/docs/updating-documents.html @@ -211,7 +211,7 @@

Model.update

Updates all documents matching conditions using the update clause. All update values are casted to their appropriate types before being sent.

-
var conditions = { name: 'borne' }
+
var conditions = { name: 'bourne' }
   , update = { $inc: { visits: 1 }}
   , options = { multi: true };
 
@@ -226,15 +226,15 @@ 

Model.update

Note: for backwards compatibility, all top-level update keys that are not $atomic operation names are treated as $set operations. Example:

-
var query = { name: 'borne' };
-Model.update(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.update(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
 
-Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
 
-

This helps prevent accidentally overwriting all of your document(s) with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting all of your document(s) with { name: 'jason bourne' }.

Also note: although values are casted to their appropriate types when using update, the following are not applied:

@@ -247,8 +247,8 @@

Model.update

If you want those features, please use the following convention rather than update:

-
Model.findOne({ name: 'borne' }, function (err, doc){
-  doc.name = 'jason borne';
+
Model.findOne({ name: 'bourne' }, function (err, doc){
+  doc.name = 'jason bourne';
   doc.visits.$inc();
   doc.save();
 });
diff --git a/docs/2.8.x/docs/updating-documents.html b/docs/2.8.x/docs/updating-documents.html
index 3dffd345fb9..704f824880b 100644
--- a/docs/2.8.x/docs/updating-documents.html
+++ b/docs/2.8.x/docs/updating-documents.html
@@ -211,7 +211,7 @@ 

Model.update

Updates all documents matching conditions using the update clause. All update values are casted to their appropriate types before being sent.

-
var conditions = { name: 'borne' }
+
var conditions = { name: 'bourne' }
   , update = { $inc: { visits: 1 }}
   , options = { multi: true };
 
@@ -226,15 +226,15 @@ 

Model.update

Note: for backwards compatibility, all top-level update keys that are not $atomic operation names are treated as $set operations. Example:

-
var query = { name: 'borne' };
-Model.update(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.update(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
 
-Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
 
-

This helps prevent accidentally overwriting all of your document(s) with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting all of your document(s) with { name: 'jason bourne' }.

Also note: although values are casted to their appropriate types when using update, the following are not applied:

@@ -247,8 +247,8 @@

Model.update

If you want those features, please use the following convention rather than update:

-
Model.findOne({ name: 'borne' }, function (err, doc){
-  doc.name = 'jason borne';
+
Model.findOne({ name: 'bourne' }, function (err, doc){
+  doc.name = 'jason bourne';
   doc.visits.$inc();
   doc.save();
 });
diff --git a/docs/3.0.x/docs/api.html b/docs/3.0.x/docs/api.html
index 1db5b1f7e65..303b43badfb 100644
--- a/docs/3.0.x/docs/api.html
+++ b/docs/3.0.x/docs/api.html
@@ -2417,13 +2417,13 @@ 

Note:

Example:

-
var query = { name: 'borne' };
-Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2438,9 +2438,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findByIdAndUpdate(id, [update], [options], [callback])

Issues a mongodb findAndModify update command by a documents id.

show code
Model.findByIdAndUpdate = function (id, update, options, callback) {
   var args;
@@ -2499,12 +2499,12 @@ 

Note:

Example:

-
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
+
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
+Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2521,7 +2521,7 @@

Note:

Model.findById(id, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findOneAndRemove(conditions, [options], [callback])

Issue a mongodb findAndModify remove command.

show code
Model.findOneAndRemove = function (conditions, options, callback) {
   if (1 === arguments.length && 'function' == typeof conditions) {
@@ -2705,13 +2705,13 @@ 

Note:

Example:

-
var query = { name: 'borne' };
-Model.update(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.update(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

Note:

@@ -2732,9 +2732,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.mapReduce(o, callback)

Executes a mapReduce command.

show code
Model.mapReduce = function mapReduce (o, callback) {
   if ('function' != typeof callback) throw new Error('missing callback');
diff --git a/docs/3.0.x/docs/source/_docs b/docs/3.0.x/docs/source/_docs
index 483b17b58c8..5c04c3f9caa 100644
--- a/docs/3.0.x/docs/source/_docs
+++ b/docs/3.0.x/docs/source/_docs
@@ -5394,9 +5394,9 @@
       }
     ],
     "description": {
-      "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -5467,9 +5467,9 @@ } ], "description": { - "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command by a documents id.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -5687,9 +5687,9 @@ } ], "description": { - "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Updates documents in the database without returning them.

", - "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, diff --git a/docs/3.1.x/docs/api.html b/docs/3.1.x/docs/api.html index 61cc402fddb..d2e85e03477 100644 --- a/docs/3.1.x/docs/api.html +++ b/docs/3.1.x/docs/api.html @@ -2436,13 +2436,13 @@

Note:

Example:

-
var query = { name: 'borne' };
-Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2457,9 +2457,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findByIdAndUpdate(id, [update], [options], [callback])

Issues a mongodb findAndModify update command by a documents id.

show code
Model.findByIdAndUpdate = function (id, update, options, callback) {
   var args;
@@ -2518,12 +2518,12 @@ 

Note:

Example:

-
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
+
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
+Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2540,7 +2540,7 @@

Note:

Model.findById(id, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findOneAndRemove(conditions, [options], [callback])

Issue a mongodb findAndModify remove command.

show code
Model.findOneAndRemove = function (conditions, options, callback) {
   if (1 === arguments.length && 'function' == typeof conditions) {
@@ -2724,13 +2724,13 @@ 

Note:

Example:

-
var query = { name: 'borne' };
-Model.update(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.update(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

Note:

@@ -2751,9 +2751,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.mapReduce(o, callback)

Executes a mapReduce command.

show code
Model.mapReduce = function mapReduce (o, callback) {
   if ('function' != typeof callback) throw new Error('missing callback');
diff --git a/docs/3.1.x/docs/source/_docs b/docs/3.1.x/docs/source/_docs
index b127ff2902f..83ace4453b4 100644
--- a/docs/3.1.x/docs/source/_docs
+++ b/docs/3.1.x/docs/source/_docs
@@ -5398,9 +5398,9 @@
       }
     ],
     "description": {
-      "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -5471,9 +5471,9 @@ } ], "description": { - "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command by a documents id.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -5691,9 +5691,9 @@ } ], "description": { - "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Updates documents in the database without returning them.

", - "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, diff --git a/docs/3.2.x/docs/api.html b/docs/3.2.x/docs/api.html index 43af3458afe..00d58196856 100644 --- a/docs/3.2.x/docs/api.html +++ b/docs/3.2.x/docs/api.html @@ -2481,13 +2481,13 @@

Note:

Example:

-
var query = { name: 'borne' };
-Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2502,9 +2502,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findByIdAndUpdate(id, [update], [options], [callback])

Issues a mongodb findAndModify update command by a documents id.

show code
Model.findByIdAndUpdate = function (id, update, options, callback) {
   var args;
@@ -2563,12 +2563,12 @@ 

Note:

Example:

-
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
+
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
+Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2585,7 +2585,7 @@

Note:

Model.findById(id, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findOneAndRemove(conditions, [options], [callback])

Issue a mongodb findAndModify remove command.

show code
Model.findOneAndRemove = function (conditions, options, callback) {
   if (1 === arguments.length && 'function' == typeof conditions) {
@@ -2769,13 +2769,13 @@ 

Note:

Example:

-
var query = { name: 'borne' };
-Model.update(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.update(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

Note:

@@ -2796,9 +2796,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.mapReduce(o, callback)

Executes a mapReduce command.

show code
Model.mapReduce = function mapReduce (o, callback) {
   if ('function' != typeof callback) throw new Error('missing callback');
diff --git a/docs/3.2.x/docs/source/_docs b/docs/3.2.x/docs/source/_docs
index 2b19e8db161..15ff84dd103 100644
--- a/docs/3.2.x/docs/source/_docs
+++ b/docs/3.2.x/docs/source/_docs
@@ -5416,9 +5416,9 @@
       }
     ],
     "description": {
-      "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -5489,9 +5489,9 @@ } ], "description": { - "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command by a documents id.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -5709,9 +5709,9 @@ } ], "description": { - "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Updates documents in the database without returning them.

", - "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, diff --git a/docs/3.3.x/docs/api.html b/docs/3.3.x/docs/api.html index 0f55a1ecbd8..5e09f19eda7 100644 --- a/docs/3.3.x/docs/api.html +++ b/docs/3.3.x/docs/api.html @@ -2519,13 +2519,13 @@

Note:

Example:

-
var query = { name: 'borne' };
-Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2540,9 +2540,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findByIdAndUpdate(id, [update], [options], [callback])

Issues a mongodb findAndModify update command by a documents id.

show code
Model.findByIdAndUpdate = function (id, update, options, callback) {
   var args;
@@ -2601,12 +2601,12 @@ 

Note:

Example:

-
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
+
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
+Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2623,7 +2623,7 @@

Note:

Model.findById(id, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findOneAndRemove(conditions, [options], [callback])

Issue a mongodb findAndModify remove command.

show code
Model.findOneAndRemove = function (conditions, options, callback) {
   if (1 === arguments.length && 'function' == typeof conditions) {
@@ -2807,13 +2807,13 @@ 

Note:

Example:

-
var query = { name: 'borne' };
-Model.update(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.update(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

Note:

@@ -2834,9 +2834,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.mapReduce(o, callback)

Executes a mapReduce command.

show code
Model.mapReduce = function mapReduce (o, callback) {
   if ('function' != typeof callback) throw new Error('missing callback');
diff --git a/docs/3.3.x/docs/source/_docs b/docs/3.3.x/docs/source/_docs
index 628139bb801..0cbd0c62375 100644
--- a/docs/3.3.x/docs/source/_docs
+++ b/docs/3.3.x/docs/source/_docs
@@ -5453,9 +5453,9 @@
       }
     ],
     "description": {
-      "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -5526,9 +5526,9 @@ } ], "description": { - "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command by a documents id.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -5746,9 +5746,9 @@ } ], "description": { - "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Updates documents in the database without returning them.

", - "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, diff --git a/docs/3.4.x/docs/api.html b/docs/3.4.x/docs/api.html index 53740ed405f..04f4d664846 100644 --- a/docs/3.4.x/docs/api.html +++ b/docs/3.4.x/docs/api.html @@ -2611,13 +2611,13 @@

Note:

Example:

-
var query = { name: 'borne' };
-Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2632,9 +2632,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findByIdAndUpdate(id, [update], [options], [callback])

Issues a mongodb findAndModify update command by a documents id.

show code
Model.findByIdAndUpdate = function (id, update, options, callback) {
   var args;
@@ -2693,12 +2693,12 @@ 

Note:

Example:

-
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
+
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
+Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2715,7 +2715,7 @@

Note:

Model.findById(id, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findOneAndRemove(conditions, [options], [callback])

Issue a mongodb findAndModify remove command.

show code
Model.findOneAndRemove = function (conditions, options, callback) {
   if (1 === arguments.length && 'function' == typeof conditions) {
@@ -2899,13 +2899,13 @@ 

Note:

Example:

-
var query = { name: 'borne' };
-Model.update(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.update(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

Note:

@@ -2926,9 +2926,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.mapReduce(o, callback)

Executes a mapReduce command.

show code
Model.mapReduce = function mapReduce (o, callback) {
   if ('function' != typeof callback) throw new Error('missing callback');
diff --git a/docs/3.4.x/docs/source/_docs b/docs/3.4.x/docs/source/_docs
index f30bb740efb..dfe5f715d8b 100644
--- a/docs/3.4.x/docs/source/_docs
+++ b/docs/3.4.x/docs/source/_docs
@@ -5758,9 +5758,9 @@
       }
     ],
     "description": {
-      "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -5831,9 +5831,9 @@ } ], "description": { - "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command by a documents id.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -6051,9 +6051,9 @@ } ], "description": { - "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Updates documents in the database without returning them.

", - "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, diff --git a/docs/3.5.x/docs/api.html b/docs/3.5.x/docs/api.html index 9bb76bb0a0f..f1a8b78d29d 100644 --- a/docs/3.5.x/docs/api.html +++ b/docs/3.5.x/docs/api.html @@ -2598,13 +2598,13 @@

Note:

Example:

-
var query = { name: 'borne' };
-Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2619,9 +2619,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findByIdAndUpdate(id, [update], [options], [callback])

Issues a mongodb findAndModify update command by a documents id.

show code
Model.findByIdAndUpdate = function (id, update, options, callback) {
   var args;
@@ -2680,12 +2680,12 @@ 

Note:

Example:

-
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
+
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
+Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2702,7 +2702,7 @@

Note:

Model.findById(id, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findOneAndRemove(conditions, [options], [callback])

Issue a mongodb findAndModify remove command.

show code
Model.findOneAndRemove = function (conditions, options, callback) {
   if (1 === arguments.length && 'function' == typeof conditions) {
@@ -2886,13 +2886,13 @@ 

Note:

Example:

-
var query = { name: 'borne' };
-Model.update(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.update(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

Note:

@@ -2913,9 +2913,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.mapReduce(o, callback)

Executes a mapReduce command.

show code
Model.mapReduce = function mapReduce (o, callback) {
   if ('function' != typeof callback) throw new Error('missing callback');
diff --git a/docs/3.5.x/docs/source/_docs b/docs/3.5.x/docs/source/_docs
index 6f04de5db44..dc02c37fd99 100644
--- a/docs/3.5.x/docs/source/_docs
+++ b/docs/3.5.x/docs/source/_docs
@@ -6106,9 +6106,9 @@
       }
     ],
     "description": {
-      "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -6179,9 +6179,9 @@ } ], "description": { - "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Issues a mongodb findAndModify update command by a documents id.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, @@ -6405,9 +6405,9 @@ } ], "description": { - "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
  • strict (boolean) overrides the strict option for this update
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", + "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
  • strict (boolean) overrides the strict option for this update
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
", "summary": "

Updates documents in the database without returning them.

", - "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
  • strict (boolean) overrides the strict option for this update
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" + "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
  • strict (boolean) overrides the strict option for this update
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'bourne' };\nModel.update(query, { name: 'jason bourne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason bourne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'bourne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason bourne';\n  doc.save(callback);\n})\n
" }, "isPrivate": false, "ignore": false, diff --git a/docs/api.html b/docs/api.html index deb2b859ad6..c599529a500 100644 --- a/docs/api.html +++ b/docs/api.html @@ -2520,13 +2520,13 @@

Note:

Example:

-
var query = { name: 'borne' };
-Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2541,9 +2541,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findByIdAndUpdate(id, [update], [options], [callback])

Issues a mongodb findAndModify update command by a documents id.

show code
Model.findByIdAndUpdate = function (id, update, options, callback) {
   var args;
@@ -2602,12 +2602,12 @@ 

Note:

Example:

-
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
+
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
+Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting your document with { name: 'jason bourne' }.

Note:

@@ -2624,7 +2624,7 @@

Note:

Model.findById(id, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.findOneAndRemove(conditions, [options], [callback])

Issue a mongodb findAndModify remove command.

show code
Model.findOneAndRemove = function (conditions, options, callback) {
   if (1 === arguments.length && 'function' == typeof conditions) {
@@ -2808,13 +2808,13 @@ 

Note:

Example:

-
var query = { name: 'borne' };
-Model.update(query, { name: 'jason borne' }, options, callback)
+
var query = { name: 'bourne' };
+Model.update(query, { name: 'jason bourne' }, options, callback)
 
 // is sent as
-Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
-

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

+

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason bourne' }.

Note:

@@ -2835,9 +2835,9 @@

Note:

If you need those features, use the traditional approach of first retrieving the document.

-
Model.findOne({ name: 'borne' }, function (err, doc) {
+
Model.findOne({ name: 'bourne' }, function (err, doc) {
   if (err) ..
-  doc.name = 'jason borne';
+  doc.name = 'jason bourne';
   doc.save(callback);
 })

Model.mapReduce(o, callback)

Executes a mapReduce command.

show code
Model.mapReduce = function mapReduce (o, callback) {
   if ('function' != typeof callback) throw new Error('missing callback');
diff --git a/lib/model.js b/lib/model.js
index c594c6d73db..b48f35249cc 100644
--- a/lib/model.js
+++ b/lib/model.js
@@ -1562,12 +1562,12 @@ Model.$where = function $where() {
  * ####Example:
  *
  *     var query = { name: 'borne' };
- *     Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
+ *     Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
  *
  *     // is sent as
- *     Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
+ *     Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
  *
- * This helps prevent accidentally overwriting your document with `{ name: 'jason borne' }`.
+ * This helps prevent accidentally overwriting your document with `{ name: 'jason bourne' }`.
  *
  * ####Note:
  *
@@ -1586,7 +1586,7 @@ Model.$where = function $where() {
  *
  *     Model.findById(id, function (err, doc) {
  *       if (err) ..
- *       doc.name = 'jason borne';
+ *       doc.name = 'jason bourne';
  *       doc.save(callback);
  *     });
  *
@@ -1676,12 +1676,12 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) {
  *
  * ####Example:
  *
- *     Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
+ *     Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)
  *
  *     // is sent as
- *     Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
+ *     Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
  *
- * This helps prevent accidentally overwriting your document with `{ name: 'jason borne' }`.
+ * This helps prevent accidentally overwriting your document with `{ name: 'jason bourne' }`.
  *
  * ####Note:
  *
@@ -1700,7 +1700,7 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) {
  *
  *     Model.findById(id, function (err, doc) {
  *       if (err) ..
- *       doc.name = 'jason borne';
+ *       doc.name = 'jason bourne';
  *       doc.save(callback);
  *     });
  *
@@ -1775,7 +1775,7 @@ Model.findByIdAndUpdate = function(id, update, options, callback) {
  *
  *     Model.findById(id, function (err, doc) {
  *       if (err) ..
- *       doc.name = 'jason borne';
+ *       doc.name = 'jason bourne';
  *       doc.save(callback);
  *     });
  *
@@ -2325,13 +2325,13 @@ Model.hydrate = function(obj) {
  * ####Example:
  *
  *     var query = { name: 'borne' };
- *     Model.update(query, { name: 'jason borne' }, options, callback)
+ *     Model.update(query, { name: 'jason bourne' }, options, callback)
  *
  *     // is sent as
- *     Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+ *     Model.update(query, { $set: { name: 'jason bourne' }}, options, callback)
  *     // if overwrite option is false. If overwrite is true, sent without the $set wrapper.
  *
- * This helps prevent accidentally overwriting all documents in your collection with `{ name: 'jason borne' }`.
+ * This helps prevent accidentally overwriting all documents in your collection with `{ name: 'jason bourne' }`.
  *
  * ####Note:
  *
@@ -2356,7 +2356,7 @@ Model.hydrate = function(obj) {
  *
  *     Model.findOne({ name: 'borne' }, function (err, doc) {
  *       if (err) ..
- *       doc.name = 'jason borne';
+ *       doc.name = 'jason bourne';
  *       doc.save(callback);
  *     })
  *

From 83ca68dc295ad809157cd79588747d66758c7c28 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Tue, 29 Aug 2017 10:05:28 -0700
Subject: [PATCH 1824/2240] docs(document): describe usage of `.set()`

Fix #5576
---
 docs/documents.jade | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/docs/documents.jade b/docs/documents.jade
index cec8b183dbd..8600d820395 100644
--- a/docs/documents.jade
+++ b/docs/documents.jade
@@ -9,7 +9,8 @@ block content
     There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on [querying](./queries.html) for detail.
   h3 Updating
   :markdown
-    There are a number of ways to update documents. We'll first look at a traditional approach using [findById](./api.html#model_Model.findById):
+    There are a number of ways to update documents. We'll first look at a
+    traditional approach using [findById](./api.html#model_Model.findById):
   :js
     Tank.findById(id, function (err, tank) {
       if (err) return handleError(err);
@@ -21,7 +22,24 @@ block content
       });
     });
   :markdown
-    This approach involves first retrieving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model.update) is right for us:
+    You can also use [`.set()`](http://mongoosejs.com/docs/api.html#document_Document-set)
+    to modify documents. Under the hood, `tank.size = 'large';` becomes `tank.set({ size: 'large' })`.
+  :js
+    Tank.findById(id, function (err, tank) {
+      if (err) return handleError(err);
+
+      tank.set({ size: 'large' });
+      tank.save(function (err, updatedTank) {
+        if (err) return handleError(err);
+        res.send(updatedTank);
+      });
+    });
+  :markdown
+    This approach involves first retrieving the document from Mongo, then
+    issuing an update command (triggered by calling `save`). However, if we
+    don't need the document returned in our application and merely want to
+    update a property in the database directly,
+    [Model#update](./api.html#model_Model.update) is right for us:
   :js
     Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);
   :markdown
@@ -40,6 +58,17 @@ block content
   :markdown
     Documents are validated before they are saved. Read the [api](./api.html#document_Document-validate) docs or the [validation](./validation.html) chapter for detail.
 
+  h3 Overwriting
+  :markdown
+    You can overwrite an entire document using `.set()`. This is handy if you
+    want to change what document is being saved in [middleware](http://mongoosejs.com/docs/middleware.html).
+  :js
+    Tank.findById(id, function (err, tank) {
+      if (err) return handleError(err);
+      // Now `otherTank` is a copy of `tank`
+      otherTank.set(tank);
+    });
+
   h3#next Next Up
   :markdown
     Now that we've covered `Documents`, let's take a look at [Sub-documents](/docs/subdocs.html).

From 93ff2528f80b939864fd389272eabb118857d408 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Wed, 30 Aug 2017 20:33:26 -0700
Subject: [PATCH 1825/2240] fix(schema): hide schema objectid warning for
 non-hex strings of length 24

Fix #5587
Re: #5571
---
 lib/schema/objectid.js | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js
index 1dbc23e2678..c75d82dfbb5 100644
--- a/lib/schema/objectid.js
+++ b/lib/schema/objectid.js
@@ -20,10 +20,14 @@ var SchemaType = require('../schematype'),
  */
 
 function ObjectId(key, options) {
-  if ((typeof key === 'string' && key.length === 24) || typeof key === 'undefined') {
-    console.warn('To create a new ObjectId please try ' +
+  var isKeyHexStr = typeof key === 'string' && /^a-f0-9$/i.test(key);
+  var suppressWarning = options && options.suppressWarning;
+  if ((isKeyHexStr || typeof key === 'undefined') && !suppressWarning) {
+    console.warn('mongoose: To create a new ObjectId please try ' +
       '`Mongoose.Types.ObjectId` instead of using ' +
-      '`Mongoose.Schema.ObjectId`.');
+      '`Mongoose.Schema.ObjectId`. Set the `suppressWarning` option if ' +
+      'you\'re trying to create a hex char path in your schema.');
+    console.trace();
   }
   SchemaType.call(this, key, options, 'ObjectID');
 }

From 83faed2298be9dccf4a2b46ba75c347f108577aa Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 31 Aug 2017 21:20:18 -0700
Subject: [PATCH 1826/2240] test: repro #5591

---
 test/docs/discriminators.test.js | 33 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js
index 387a5c524ef..549f17fc6e7 100644
--- a/test/docs/discriminators.test.js
+++ b/test/docs/discriminators.test.js
@@ -207,10 +207,7 @@ describe('discriminator docs', function () {
   /**
    * A discriminator's fields are the union of the base schema's fields and
    * the discriminator schema's fields, and the discriminator schema's fields
-   * take precedence. This behavior gets quirky when you have a custom `_id`
-   * field. A schema gets an `_id` field by default, so the base schema's
-   * `_id` field will get overridden by the discriminator schema's default
-   * `_id` field.
+   * take precedence. There is one exception: the default `_id` field.
    *
    * You can work around this by setting the `_id` option to false in the
    * discriminator schema as shown below.
@@ -218,28 +215,28 @@ describe('discriminator docs', function () {
   it('Handling custom _id fields', function (done) {
     var options = {discriminatorKey: 'kind'};
 
-    // Base schema has a String _id...
+    // Base schema has a String `_id` and a Date `time`...
     var eventSchema = new mongoose.Schema({_id: String, time: Date},
       options);
     var Event = mongoose.model('BaseEvent', eventSchema);
 
-    var clickedLinkSchema = new mongoose.Schema({url: String}, options);
+    var clickedLinkSchema = new mongoose.Schema({
+      url: String,
+      time: String
+    }, options);
+    // But the discriminator schema has a String `time`, and an implicitly added
+    // ObjectId `_id`.
+    assert.ok(clickedLinkSchema.path('_id'));
+    assert.equal(clickedLinkSchema.path('_id').instance, 'ObjectID');
     var ClickedLinkEvent = Event.discriminator('ChildEventBad',
       clickedLinkSchema);
 
-    var event1 = new ClickedLinkEvent();
-    // Woops, clickedLinkSchema overwrote the custom _id
-    assert.ok(event1._id instanceof mongoose.Types.ObjectId);
-
-    // But if you set `_id` option to false...
-    clickedLinkSchema = new mongoose.Schema({url: String},
-      {discriminatorKey: 'kind', _id: false});
-    ClickedLinkEvent = Event.discriminator('ChildEventGood',
-      clickedLinkSchema);
+    var event1 = new ClickedLinkEvent({ _id: 'custom id', time: '4pm' });
+    // Woops, clickedLinkSchema overwrites the `time` path, but **not**
+    // the `_id` path because that was implicitly added.
+    assert.ok(typeof event1._id === 'string');
+    assert.ok(typeof event1.time === 'string');
 
-    // The custom _id from the base schema comes through
-    var event2 = new ClickedLinkEvent({_id: 'test'});
-    assert.ok(event2._id.toString() === event2._id);
     // acquit:ignore:start
     done();
     // acquit:ignore:end

From 9fa31d3369a68e141f738ec73b3226ac5768dbd2 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 31 Aug 2017 21:20:22 -0700
Subject: [PATCH 1827/2240] fix(discriminator): prevent implicit discriminator
 schema _id from clobbering base schema custom _id

Fix #5591
---
 lib/services/model/discriminator.js | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js
index 02cb65e1ce4..63e5a3cdea0 100644
--- a/lib/services/model/discriminator.js
+++ b/lib/services/model/discriminator.js
@@ -35,6 +35,14 @@ module.exports = function discriminator(model, name, schema) {
   }
 
   function merge(schema, baseSchema) {
+    if (baseSchema.paths._id &&
+        baseSchema.paths._id.options &&
+        !baseSchema.paths._id.options.auto) {
+      var originalSchema = schema;
+      utils.merge(schema, originalSchema, { retainKeyOrder: true });
+      delete schema.paths._id;
+      delete schema.tree._id;
+    }
     utils.merge(schema, baseSchema, { retainKeyOrder: true });
 
     var obj = {};

From e6863ea445481deb573db822c29ac456310be4d0 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 31 Aug 2017 21:50:24 -0700
Subject: [PATCH 1828/2240] test(schema): repro #5607

---
 test/schema.test.js | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/test/schema.test.js b/test/schema.test.js
index b4141fe7528..72888bcea35 100644
--- a/test/schema.test.js
+++ b/test/schema.test.js
@@ -1668,5 +1668,21 @@ describe('schema', function() {
       assert.equal(casted.toString(), '6.2E+23');
       done();
     });
+
+    it('clone() copies validators declared with validate() (gh-5607)', function(done) {
+      var schema = new Schema({
+        num: Number
+      });
+
+      schema.path('num').validate(function(v) {
+        return v === 42;
+      });
+
+      var clone = schema.clone();
+      assert.equal(clone.path('num').validators.length, 1);
+      assert.ok(clone.path('num').validators[0].validator(42));
+      assert.ok(!clone.path('num').validators[0].validator(41));
+      done();
+    });
   });
 });

From 768f9101f9d2146452bd7a2346e4d57237f82d7d Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Thu, 31 Aug 2017 21:50:28 -0700
Subject: [PATCH 1829/2240] fix(schema): ensure validators declared with
 `.validate()` get copied with clone()

Fix #5607
---
 lib/schema.js | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/lib/schema.js b/lib/schema.js
index e673e0b6ac7..27a138028f6 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -277,7 +277,7 @@ Schema.prototype.tree;
  */
 
 Schema.prototype.clone = function() {
-  var s = new Schema(this.obj, this.options);
+  var s = new Schema(this.paths, this.options);
   // Clone the call queue
   s.callQueue = this.callQueue.map(function(f) { return f; });
   s.methods = utils.clone(this.methods);
@@ -531,6 +531,10 @@ Schema.prototype.path = function(path, obj) {
  */
 
 Schema.interpretAsType = function(path, obj, options) {
+  if (obj instanceof SchemaType) {
+    return obj;
+  }
+
   if (obj.constructor) {
     var constructorName = utils.getFunctionName(obj.constructor);
     if (constructorName !== 'Object') {

From 0c16722833034106f8248e698e8c46ffb8301a49 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 1 Sep 2017 09:22:05 -0700
Subject: [PATCH 1830/2240] test(document): repro #5569

---
 test/document.test.js | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/test/document.test.js b/test/document.test.js
index 6cba7e29118..6fc165e4a3e 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -4594,6 +4594,44 @@ describe('document', function() {
       });
     });
 
+    it('single nested conditional required scope (gh-5569)', function(done) {
+      var scopes = [];
+
+      var ThingSchema = new mongoose.Schema({
+        undefinedDisallowed: {
+          type: String,
+          required: function() {
+            scopes.push(this);
+            return this.undefinedDisallowed === undefined;
+          },
+          default: null
+        }
+      });
+
+      var SuperDocumentSchema = new mongoose.Schema({
+        thing: {
+          type: ThingSchema,
+          default: function() { return {}; }
+        }
+      });
+
+      var SuperDocument = db.model('gh5569', SuperDocumentSchema);
+
+      var doc = new SuperDocument();
+      doc.thing.undefinedDisallowed = null;
+
+      doc.save(function(error) {
+        assert.ifError(error);
+        doc = new SuperDocument();
+        doc.thing.undefinedDisallowed = undefined;
+        doc.save(function(error) {
+          assert.ok(error);
+          assert.ok(error.errors['thing.undefinedDisallowed']);
+          done();
+        });
+      });
+    });
+
     it('consistent context for nested docs (gh-5347)', function(done) {
       var contexts = [];
       var childSchema = new mongoose.Schema({

From 3949fcc00ec6dc102bb7db64f918a8e9ca24e72e Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 1 Sep 2017 09:22:11 -0700
Subject: [PATCH 1831/2240] fix(document): ensure correct scope in single
 nested validators

Fix #5569
---
 lib/types/subdocument.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js
index 9eda328e48f..72b9419aaf7 100644
--- a/lib/types/subdocument.js
+++ b/lib/types/subdocument.js
@@ -60,7 +60,7 @@ Subdocument.prototype.markModified = function(path) {
     if (this.$parent.isDirectModified(this.$basePath)) {
       return;
     }
-    this.$parent.markModified([this.$basePath, path].join('.'));
+    this.$parent.markModified([this.$basePath, path].join('.'), this);
   }
 };
 

From 0d01dcd1aef31acf570995befacbd9028ee8ad29 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 1 Sep 2017 20:46:22 -0700
Subject: [PATCH 1832/2240] test(document): repro #5504

---
 test/document.test.js | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/test/document.test.js b/test/document.test.js
index 6fc165e4a3e..c43bebf3989 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -4594,6 +4594,32 @@ describe('document', function() {
       });
     });
 
+    it('push populated doc onto empty array triggers manual population (gh-5504)', function(done) {
+      var ReferringSchema = new Schema({
+        reference: [{
+          type: Schema.Types.ObjectId,
+          ref: 'gh5504'
+        }]
+      });
+
+      var Referrer = db.model('gh5504', ReferringSchema);
+
+      var referenceA = new Referrer();
+      var referenceB = new Referrer();
+
+      referrerA = new Referrer({reference: [referenceA]});
+      referrerB = new Referrer();
+
+      referrerA.reference.push(referenceB);
+      assert.ok(referrerA.reference[0] instanceof Referrer);
+      assert.ok(referrerA.reference[1] instanceof Referrer);
+
+      referrerB.reference.push(referenceB);
+      assert.ok(referrerB.reference[0] instanceof Referrer);
+
+      done();
+    });
+
     it('single nested conditional required scope (gh-5569)', function(done) {
       var scopes = [];
 

From 60331797ac20cac3f615b0b23aa785285efa1750 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 1 Sep 2017 20:46:26 -0700
Subject: [PATCH 1833/2240] fix(document): make push()-ing a doc onto an empty
 array act as manual population

Fix #5504
---
 lib/types/array.js | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/lib/types/array.js b/lib/types/array.js
index 4aff7bf9799..e4723492258 100644
--- a/lib/types/array.js
+++ b/lib/types/array.js
@@ -306,9 +306,29 @@ MongooseArray.mixin = {
    */
 
   push: function() {
+    var firstArg = arguments[0];
+    var ref = this._schema.caster.options && this._schema.caster.options.ref;
+    if (this.length === 0 &&
+        arguments.length) {
+      var allSubdocs = true;
+      for (var i = 0; i < arguments.length; ++i) {
+        var arg = arguments[i];
+        var model = arg.constructor;
+        allSubdocs = arg instanceof Document &&
+          ref &&
+          (model.modelName === ref || model.baseModelName === ref);
+        if (!allSubdocs) {
+          break;
+        }
+      }
+
+      if (allSubdocs) {
+        this._parent.populated(this._path, [], { model: arguments[0].constructor });
+      }
+    }
     var values = [].map.call(arguments, this._mapCast, this);
     values = this._schema.applySetters(values, this._parent, undefined,
-        undefined, {skipDocumentArrayCast: true});
+        undefined, { skipDocumentArrayCast: true });
     var ret = [].push.apply(this, values);
 
     // $pushAll might be fibbed (could be $push). But it makes it easier to

From 8bbf8a9ac70adb42508fa4978d82c411d9af1ab8 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Fri, 1 Sep 2017 20:56:35 -0700
Subject: [PATCH 1834/2240] style: fix lint

---
 lib/types/array.js    | 1 -
 test/document.test.js | 4 ++--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/lib/types/array.js b/lib/types/array.js
index e4723492258..b6efac4f77a 100644
--- a/lib/types/array.js
+++ b/lib/types/array.js
@@ -306,7 +306,6 @@ MongooseArray.mixin = {
    */
 
   push: function() {
-    var firstArg = arguments[0];
     var ref = this._schema.caster.options && this._schema.caster.options.ref;
     if (this.length === 0 &&
         arguments.length) {
diff --git a/test/document.test.js b/test/document.test.js
index c43bebf3989..51db052ac97 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -4607,8 +4607,8 @@ describe('document', function() {
       var referenceA = new Referrer();
       var referenceB = new Referrer();
 
-      referrerA = new Referrer({reference: [referenceA]});
-      referrerB = new Referrer();
+      var referrerA = new Referrer({reference: [referenceA]});
+      var referrerB = new Referrer();
 
       referrerA.reference.push(referenceB);
       assert.ok(referrerA.reference[0] instanceof Referrer);

From ce586e4c02df18078adcc5585c1486b8ff833d17 Mon Sep 17 00:00:00 2001
From: Valeri Karpov 
Date: Sat, 2 Sep 2017 12:07:29 -0700
Subject: [PATCH 1835/2240] docs: add KeenIO for tracking

---
 docs/3.0.x/docs/api.html                      |  6444 ------
 docs/3.0.x/docs/api.jade                      |   508 -
 docs/3.0.x/docs/contributing.html             |    11 -
 docs/3.0.x/docs/contributing.jade             |    22 -
 docs/3.0.x/docs/css/default.css               |   135 -
 docs/3.0.x/docs/css/guide.css                 |   283 -
 docs/3.0.x/docs/documents.html                |    20 -
 docs/3.0.x/docs/documents.jade                |    38 -
 docs/3.0.x/docs/faq.html                      |    31 -
 docs/3.0.x/docs/faq.jade                      |    63 -
 docs/3.0.x/docs/guide.html                    |   133 -
 docs/3.0.x/docs/guide.jade                    |   364 -
 docs/3.0.x/docs/helpers/filters.js            |    20 -
 docs/3.0.x/docs/helpers/highlight.js          |    11 -
 docs/3.0.x/docs/helpers/href.js               |     5 -
 docs/3.0.x/docs/helpers/klass.js              |     5 -
 docs/3.0.x/docs/helpers/linktype.js           |    50 -
 docs/3.0.x/docs/images/apps/grab              |    39 -
 docs/3.0.x/docs/images/apps/urls              |    21 -
 docs/3.0.x/docs/images/square_bg.png          |   Bin 2217 -> 0 bytes
 docs/3.0.x/docs/includes/googleanalytics.jade |    10 -
 docs/3.0.x/docs/includes/nav.jade             |    53 -
 docs/3.0.x/docs/index.html                    |    36 -
 docs/3.0.x/docs/index.jade                    |   119 -
 docs/3.0.x/docs/js/zepto.min.js               |     2 -
 docs/3.0.x/docs/layout.jade                   |    25 -
 docs/3.0.x/docs/middleware.html               |    29 -
 docs/3.0.x/docs/middleware.jade               |    71 -
 docs/3.0.x/docs/migration.html                |    38 -
 docs/3.0.x/docs/migration.jade                |   272 -
 docs/3.0.x/docs/models.html                   |    32 -
 docs/3.0.x/docs/models.jade                   |    57 -
 docs/3.0.x/docs/plugins.html                  |    33 -
 docs/3.0.x/docs/plugins.jade                  |    38 -
 docs/3.0.x/docs/populate.html                 |    98 -
 docs/3.0.x/docs/populate.jade                 |   145 -
 docs/3.0.x/docs/prior.html                    |     9 -
 docs/3.0.x/docs/prior.jade                    |     8 -
 docs/3.0.x/docs/queries.html                  |    41 -
 docs/3.0.x/docs/queries.jade                  |    59 -
 docs/3.0.x/docs/releases                      |     1 -
 docs/3.0.x/docs/schematypes.html              |    67 -
 docs/3.0.x/docs/schematypes.jade              |   142 -
 docs/3.0.x/docs/source/_docs                  | 15928 --------------
 docs/3.0.x/docs/source/api.js                 |   220 -
 docs/3.0.x/docs/source/home.js                |    19 -
 docs/3.0.x/docs/source/index.js               |    18 -
 docs/3.0.x/docs/source/prior.js               |    13 -
 docs/3.0.x/docs/subdocs.html                  |    48 -
 docs/3.0.x/docs/subdocs.jade                  |    80 -
 docs/3.0.x/docs/validation.html               |    36 -
 docs/3.0.x/docs/validation.jade               |    54 -
 docs/3.0.x/index.html                         |   238 -
 docs/3.0.x/static.js                          |    17 -
 docs/3.1.x/docs/api.html                      |  6720 ------
 docs/3.1.x/docs/api.jade                      |   508 -
 docs/3.1.x/docs/contributing.html             |    11 -
 docs/3.1.x/docs/contributing.jade             |    22 -
 docs/3.1.x/docs/css/default.css               |   135 -
 docs/3.1.x/docs/css/guide.css                 |   283 -
 docs/3.1.x/docs/documents.html                |    20 -
 docs/3.1.x/docs/documents.jade                |    42 -
 docs/3.1.x/docs/faq.html                      |    31 -
 docs/3.1.x/docs/faq.jade                      |    63 -
 docs/3.1.x/docs/guide.html                    |   170 -
 docs/3.1.x/docs/guide.jade                    |   428 -
 docs/3.1.x/docs/helpers/filters.js            |    20 -
 docs/3.1.x/docs/helpers/highlight.js          |    11 -
 docs/3.1.x/docs/helpers/href.js               |     5 -
 docs/3.1.x/docs/helpers/klass.js              |     5 -
 docs/3.1.x/docs/helpers/linktype.js           |    50 -
 docs/3.1.x/docs/images/apps/grab              |    39 -
 docs/3.1.x/docs/images/apps/urls              |    21 -
 docs/3.1.x/docs/images/square_bg.png          |   Bin 2217 -> 0 bytes
 docs/3.1.x/docs/includes/googleanalytics.jade |    10 -
 docs/3.1.x/docs/includes/nav.jade             |    53 -
 docs/3.1.x/docs/index.html                    |    36 -
 docs/3.1.x/docs/index.jade                    |   119 -
 docs/3.1.x/docs/js/zepto.min.js               |     2 -
 docs/3.1.x/docs/layout.jade                   |    25 -
 docs/3.1.x/docs/middleware.html               |    29 -
 docs/3.1.x/docs/middleware.jade               |    74 -
 docs/3.1.x/docs/migration.html                |    38 -
 docs/3.1.x/docs/migration.jade                |   272 -
 docs/3.1.x/docs/models.html                   |    32 -
 docs/3.1.x/docs/models.jade                   |    61 -
 docs/3.1.x/docs/plugins.html                  |    33 -
 docs/3.1.x/docs/plugins.jade                  |    42 -
 docs/3.1.x/docs/populate.html                 |   104 -
 docs/3.1.x/docs/populate.jade                 |   164 -
 docs/3.1.x/docs/prior.html                    |     9 -
 docs/3.1.x/docs/prior.jade                    |     8 -
 docs/3.1.x/docs/queries.html                  |    41 -
 docs/3.1.x/docs/queries.jade                  |    62 -
 docs/3.1.x/docs/releases                      |     2 -
 docs/3.1.x/docs/schematypes.html              |    67 -
 docs/3.1.x/docs/schematypes.jade              |   146 -
 docs/3.1.x/docs/source/_docs                  | 16169 --------------
 docs/3.1.x/docs/source/api.js                 |   220 -
 docs/3.1.x/docs/source/home.js                |    19 -
 docs/3.1.x/docs/source/index.js               |    18 -
 docs/3.1.x/docs/source/prior.js               |    13 -
 docs/3.1.x/docs/subdocs.html                  |    49 -
 docs/3.1.x/docs/subdocs.jade                  |    84 -
 docs/3.1.x/docs/validation.html               |    37 -
 docs/3.1.x/docs/validation.jade               |    58 -
 docs/3.1.x/index.html                         |   238 -
 docs/3.1.x/static.js                          |    17 -
 docs/3.2.x/docs/api.html                      |  6828 ------
 docs/3.2.x/docs/api.jade                      |   507 -
 docs/3.2.x/docs/connections.html              |    27 -
 docs/3.2.x/docs/connections.jade              |    65 -
 docs/3.2.x/docs/contributing.html             |     9 -
 docs/3.2.x/docs/contributing.jade             |     8 -
 docs/3.2.x/docs/css/default.css               |   135 -
 docs/3.2.x/docs/css/guide.css                 |   281 -
 docs/3.2.x/docs/css/style.css                 |   207 -
 docs/3.2.x/docs/documents.html                |    20 -
 docs/3.2.x/docs/documents.jade                |    42 -
 docs/3.2.x/docs/faq.html                      |    31 -
 docs/3.2.x/docs/faq.jade                      |    63 -
 docs/3.2.x/docs/guide.html                    |   187 -
 docs/3.2.x/docs/guide.jade                    |   450 -
 docs/3.2.x/docs/helpers/filters.js            |    20 -
 docs/3.2.x/docs/helpers/highlight.js          |    11 -
 docs/3.2.x/docs/helpers/href.js               |     5 -
 docs/3.2.x/docs/helpers/klass.js              |     5 -
 docs/3.2.x/docs/helpers/linktype.js           |    50 -
 docs/3.2.x/docs/images/apps/attictv.png       |   Bin 42666 -> 0 bytes
 docs/3.2.x/docs/images/apps/bozuko.png        |   Bin 37827 -> 0 bytes
 docs/3.2.x/docs/images/apps/calllist.png      |   Bin 33502 -> 0 bytes
 docs/3.2.x/docs/images/apps/cldfy.png         |   Bin 9773 -> 0 bytes
 docs/3.2.x/docs/images/apps/clickdummy.png    |   Bin 34210 -> 0 bytes
 docs/3.2.x/docs/images/apps/cyborgvision.png  |   Bin 42616 -> 0 bytes
 docs/3.2.x/docs/images/apps/furbabyrescue.png |   Bin 49891 -> 0 bytes
 docs/3.2.x/docs/images/apps/geeklist.png      |   Bin 27911 -> 0 bytes
 docs/3.2.x/docs/images/apps/grab              |    71 -
 .../docs/images/apps/growthegamegolf.png      |   Bin 43441 -> 0 bytes
 docs/3.2.x/docs/images/apps/kyyti.png         |   Bin 41966 -> 0 bytes
 docs/3.2.x/docs/images/apps/learnboost.png    |   Bin 31434 -> 0 bytes
 docs/3.2.x/docs/images/apps/linkr.png         |   Bin 6428 -> 0 bytes
 docs/3.2.x/docs/images/apps/lists.png         |   Bin 697 -> 0 bytes
 docs/3.2.x/docs/images/apps/localresponse.png |   Bin 26423 -> 0 bytes
 docs/3.2.x/docs/images/apps/nextdays.png      |   Bin 35067 -> 0 bytes
 docs/3.2.x/docs/images/apps/nimblequiz.png    |   Bin 20990 -> 0 bytes
 docs/3.2.x/docs/images/apps/nuorder.png       |   Bin 38163 -> 0 bytes
 docs/3.2.x/docs/images/apps/scottyapp.png     |   Bin 118416 -> 0 bytes
 docs/3.2.x/docs/images/apps/seelio.png        |   Bin 24005 -> 0 bytes
 docs/3.2.x/docs/images/apps/selectvids.png    |   Bin 42214 -> 0 bytes
 docs/3.2.x/docs/images/apps/sharelatex.png    |   Bin 19707 -> 0 bytes
 docs/3.2.x/docs/images/apps/shoejitsu.png     |   Bin 35092 -> 0 bytes
 docs/3.2.x/docs/images/apps/skim.png          |   Bin 43580 -> 0 bytes
 docs/3.2.x/docs/images/apps/stachify.png      |   Bin 27783 -> 0 bytes
 docs/3.2.x/docs/images/apps/storify.png       |   Bin 55982 -> 0 bytes
 docs/3.2.x/docs/images/apps/todaylaunch.png   |   Bin 33233 -> 0 bytes
 docs/3.2.x/docs/images/apps/treinosmart.png   |   Bin 26723 -> 0 bytes
 docs/3.2.x/docs/images/apps/upcload.png       |   Bin 37792 -> 0 bytes
 docs/3.2.x/docs/images/apps/urls              |    27 -
 docs/3.2.x/docs/images/apps/wavo.png          |   Bin 54906 -> 0 bytes
 docs/3.2.x/docs/images/square_bg.png          |   Bin 2217 -> 0 bytes
 docs/3.2.x/docs/includes/googleanalytics.jade |    10 -
 docs/3.2.x/docs/includes/nav.jade             |    55 -
 docs/3.2.x/docs/index.html                    |    36 -
 docs/3.2.x/docs/index.jade                    |   119 -
 docs/3.2.x/docs/js/zepto.min.js               |     2 -
 docs/3.2.x/docs/layout.jade                   |    25 -
 docs/3.2.x/docs/middleware.html               |    29 -
 docs/3.2.x/docs/middleware.jade               |    74 -
 docs/3.2.x/docs/migration.html                |    40 -
 docs/3.2.x/docs/migration.jade                |   280 -
 docs/3.2.x/docs/models.html                   |    32 -
 docs/3.2.x/docs/models.jade                   |    61 -
 docs/3.2.x/docs/plugins.html                  |    33 -
 docs/3.2.x/docs/plugins.jade                  |    42 -
 docs/3.2.x/docs/populate.html                 |   104 -
 docs/3.2.x/docs/populate.jade                 |   164 -
 docs/3.2.x/docs/prior.html                    |     9 -
 docs/3.2.x/docs/prior.jade                    |     8 -
 docs/3.2.x/docs/queries.html                  |    41 -
 docs/3.2.x/docs/queries.jade                  |    62 -
 docs/3.2.x/docs/releases                      |     2 -
 docs/3.2.x/docs/schematypes.html              |    67 -
 docs/3.2.x/docs/schematypes.jade              |   146 -
 docs/3.2.x/docs/source/_docs                  | 16201 --------------
 docs/3.2.x/docs/source/api.js                 |   220 -
 docs/3.2.x/docs/source/home.js                |    19 -
 docs/3.2.x/docs/source/index.js               |    19 -
 docs/3.2.x/docs/source/prior.js               |    13 -
 docs/3.2.x/docs/subdocs.html                  |    49 -
 docs/3.2.x/docs/subdocs.jade                  |    84 -
 docs/3.2.x/docs/validation.html               |    37 -
 docs/3.2.x/docs/validation.jade               |    58 -
 docs/3.2.x/index.html                         |    20 -
 docs/3.2.x/static.js                          |    17 -
 docs/3.3.x/docs/api.html                      |  6883 ------
 docs/3.3.x/docs/api.jade                      |   517 -
 docs/3.3.x/docs/connections.html              |    27 -
 docs/3.3.x/docs/connections.jade              |    65 -
 docs/3.3.x/docs/contributing.html             |     9 -
 docs/3.3.x/docs/contributing.jade             |     8 -
 docs/3.3.x/docs/css/default.css               |   135 -
 docs/3.3.x/docs/css/guide.css                 |   326 -
 docs/3.3.x/docs/css/style.css                 |   225 -
 docs/3.3.x/docs/documents.html                |    20 -
 docs/3.3.x/docs/documents.jade                |    42 -
 docs/3.3.x/docs/faq.html                      |    31 -
 docs/3.3.x/docs/faq.jade                      |    63 -
 docs/3.3.x/docs/guide.html                    |   188 -
 docs/3.3.x/docs/guide.jade                    |   457 -
 docs/3.3.x/docs/helpers/filters.js            |    20 -
 docs/3.3.x/docs/helpers/highlight.js          |    11 -
 docs/3.3.x/docs/helpers/href.js               |     5 -
 docs/3.3.x/docs/helpers/klass.js              |     5 -
 docs/3.3.x/docs/helpers/linktype.js           |    50 -
 docs/3.3.x/docs/images/apps/attictv.png       |   Bin 42666 -> 0 bytes
 docs/3.3.x/docs/images/apps/bozuko.png        |   Bin 37827 -> 0 bytes
 docs/3.3.x/docs/images/apps/calllist.png      |   Bin 33502 -> 0 bytes
 docs/3.3.x/docs/images/apps/cldfy.png         |   Bin 9773 -> 0 bytes
 docs/3.3.x/docs/images/apps/clickdummy.png    |   Bin 34210 -> 0 bytes
 docs/3.3.x/docs/images/apps/cyborgvision.png  |   Bin 42616 -> 0 bytes
 docs/3.3.x/docs/images/apps/dashku.png        |   Bin 25043 -> 0 bytes
 .../docs/images/apps/firstimpression.png      |   Bin 32241 -> 0 bytes
 docs/3.3.x/docs/images/apps/furbabyrescue.png |   Bin 49891 -> 0 bytes
 docs/3.3.x/docs/images/apps/geeklist.png      |   Bin 27911 -> 0 bytes
 docs/3.3.x/docs/images/apps/grab              |    71 -
 .../docs/images/apps/growthegamegolf.png      |   Bin 43441 -> 0 bytes
 docs/3.3.x/docs/images/apps/h_bozuko.jpg      |   Bin 11928 -> 0 bytes
 docs/3.3.x/docs/images/apps/h_geeklist.png    |   Bin 3482 -> 0 bytes
 docs/3.3.x/docs/images/apps/h_learnboost.png  |   Bin 12727 -> 0 bytes
 docs/3.3.x/docs/images/apps/h_mcds.png        |   Bin 3904 -> 0 bytes
 docs/3.3.x/docs/images/apps/h_shoejitsu.png   |   Bin 12695 -> 0 bytes
 docs/3.3.x/docs/images/apps/h_storify.jpg     |   Bin 14291 -> 0 bytes
 docs/3.3.x/docs/images/apps/kyyti.png         |   Bin 41966 -> 0 bytes
 docs/3.3.x/docs/images/apps/learnboost.png    |   Bin 31434 -> 0 bytes
 docs/3.3.x/docs/images/apps/linkr.png         |   Bin 6428 -> 0 bytes
 docs/3.3.x/docs/images/apps/lists.png         |   Bin 697 -> 0 bytes
 docs/3.3.x/docs/images/apps/localresponse.png |   Bin 26423 -> 0 bytes
 docs/3.3.x/docs/images/apps/mcdonalds.png     |   Bin 57481 -> 0 bytes
 docs/3.3.x/docs/images/apps/muffle.png        |   Bin 26658 -> 0 bytes
 docs/3.3.x/docs/images/apps/nextdays.png      |   Bin 35067 -> 0 bytes
 docs/3.3.x/docs/images/apps/nimblequiz.png    |   Bin 20990 -> 0 bytes
 docs/3.3.x/docs/images/apps/nuorder.png       |   Bin 38163 -> 0 bytes
 docs/3.3.x/docs/images/apps/scottyapp.png     |   Bin 118416 -> 0 bytes
 docs/3.3.x/docs/images/apps/seelio.png        |   Bin 24005 -> 0 bytes
 docs/3.3.x/docs/images/apps/selectvids.png    |   Bin 42214 -> 0 bytes
 docs/3.3.x/docs/images/apps/sharelatex.png    |   Bin 19707 -> 0 bytes
 docs/3.3.x/docs/images/apps/shoejitsu.png     |   Bin 35092 -> 0 bytes
 docs/3.3.x/docs/images/apps/skim.png          |   Bin 43580 -> 0 bytes
 docs/3.3.x/docs/images/apps/squadsheet.png    |   Bin 37071 -> 0 bytes
 docs/3.3.x/docs/images/apps/stachify.png      |   Bin 27783 -> 0 bytes
 docs/3.3.x/docs/images/apps/storify.png       |   Bin 55982 -> 0 bytes
 docs/3.3.x/docs/images/apps/todaylaunch.png   |   Bin 33233 -> 0 bytes
 docs/3.3.x/docs/images/apps/treinosmart.png   |   Bin 26723 -> 0 bytes
 docs/3.3.x/docs/images/apps/upcload.png       |   Bin 37792 -> 0 bytes
 docs/3.3.x/docs/images/apps/urls              |    34 -
 docs/3.3.x/docs/images/apps/veriwalk.png      |   Bin 28311 -> 0 bytes
 docs/3.3.x/docs/images/apps/wavo.png          |   Bin 54906 -> 0 bytes
 docs/3.3.x/docs/images/apps/zootify.png       |   Bin 44707 -> 0 bytes
 docs/3.3.x/docs/images/square_bg.png          |   Bin 2217 -> 0 bytes
 docs/3.3.x/docs/includes/googleanalytics.jade |    10 -
 docs/3.3.x/docs/includes/nav.jade             |    55 -
 docs/3.3.x/docs/index.html                    |    36 -
 docs/3.3.x/docs/index.jade                    |   119 -
 docs/3.3.x/docs/js/cookies.min.js             |     4 -
 docs/3.3.x/docs/js/zepto.min.js               |     2 -
 docs/3.3.x/docs/layout.jade                   |    25 -
 docs/3.3.x/docs/middleware.html               |    29 -
 docs/3.3.x/docs/middleware.jade               |    74 -
 docs/3.3.x/docs/migration.html                |    40 -
 docs/3.3.x/docs/migration.jade                |   280 -
 docs/3.3.x/docs/models.html                   |    32 -
 docs/3.3.x/docs/models.jade                   |    61 -
 docs/3.3.x/docs/plugins.html                  |    33 -
 docs/3.3.x/docs/plugins.jade                  |    42 -
 docs/3.3.x/docs/populate.html                 |   104 -
 docs/3.3.x/docs/populate.jade                 |   164 -
 docs/3.3.x/docs/prior.html                    |     9 -
 docs/3.3.x/docs/prior.jade                    |     8 -
 docs/3.3.x/docs/production.html               |     9 -
 docs/3.3.x/docs/production.jade               |    11 -
 docs/3.3.x/docs/queries.html                  |    41 -
 docs/3.3.x/docs/queries.jade                  |    62 -
 docs/3.3.x/docs/releases                      |     5 -
 docs/3.3.x/docs/schematypes.html              |    67 -
 docs/3.3.x/docs/schematypes.jade              |   146 -
 docs/3.3.x/docs/source/_docs                  | 16292 --------------
 docs/3.3.x/docs/source/api.js                 |   220 -
 docs/3.3.x/docs/source/home.js                |     7 -
 docs/3.3.x/docs/source/index.js               |    20 -
 docs/3.3.x/docs/source/prior.js               |    13 -
 docs/3.3.x/docs/source/production.js          |    17 -
 docs/3.3.x/docs/subdocs.html                  |    49 -
 docs/3.3.x/docs/subdocs.jade                  |    84 -
 docs/3.3.x/docs/validation.html               |    37 -
 docs/3.3.x/docs/validation.jade               |    58 -
 docs/3.3.x/docs/website.js                    |    48 -
 docs/3.3.x/index.html                         |    20 -
 docs/3.3.x/static.js                          |    17 -
 docs/3.4.x/docs/api.html                      |  6999 ------
 docs/3.4.x/docs/connections.html              |    27 -
 docs/3.4.x/docs/contributing.html             |     9 -
 docs/3.4.x/docs/css/default.css               |   135 -
 docs/3.4.x/docs/css/guide.css                 |   326 -
 docs/3.4.x/docs/css/style.css                 |   225 -
 docs/3.4.x/docs/documents.html                |    20 -
 docs/3.4.x/docs/faq.html                      |    31 -
 docs/3.4.x/docs/guide.html                    |   190 -
 docs/3.4.x/docs/helpers/filters.js            |    20 -
 docs/3.4.x/docs/helpers/highlight.js          |    11 -
 docs/3.4.x/docs/helpers/href.js               |     5 -
 docs/3.4.x/docs/helpers/klass.js              |     5 -
 docs/3.4.x/docs/helpers/linktype.js           |    50 -
 docs/3.4.x/docs/images/apps/attictv.png       |   Bin 42666 -> 0 bytes
 docs/3.4.x/docs/images/apps/bozuko.png        |   Bin 37827 -> 0 bytes
 docs/3.4.x/docs/images/apps/calllist.png      |   Bin 33502 -> 0 bytes
 docs/3.4.x/docs/images/apps/cldfy.png         |   Bin 9773 -> 0 bytes
 docs/3.4.x/docs/images/apps/clickdummy.png    |   Bin 34210 -> 0 bytes
 docs/3.4.x/docs/images/apps/cyborgvision.png  |   Bin 42616 -> 0 bytes
 docs/3.4.x/docs/images/apps/dashku.png        |   Bin 25043 -> 0 bytes
 .../docs/images/apps/firstimpression.png      |   Bin 32241 -> 0 bytes
 docs/3.4.x/docs/images/apps/furbabyrescue.png |   Bin 49891 -> 0 bytes
 docs/3.4.x/docs/images/apps/geeklist.png      |   Bin 27911 -> 0 bytes
 docs/3.4.x/docs/images/apps/grab              |    71 -
 .../docs/images/apps/growthegamegolf.png      |   Bin 43441 -> 0 bytes
 docs/3.4.x/docs/images/apps/h_bozuko.jpg      |   Bin 11928 -> 0 bytes
 docs/3.4.x/docs/images/apps/h_geeklist.png    |   Bin 3482 -> 0 bytes
 docs/3.4.x/docs/images/apps/h_learnboost.png  |   Bin 12727 -> 0 bytes
 docs/3.4.x/docs/images/apps/h_mcds.png        |   Bin 3904 -> 0 bytes
 docs/3.4.x/docs/images/apps/h_shoejitsu.png   |   Bin 12695 -> 0 bytes
 docs/3.4.x/docs/images/apps/h_storify.jpg     |   Bin 14291 -> 0 bytes
 docs/3.4.x/docs/images/apps/kyyti.png         |   Bin 41966 -> 0 bytes
 docs/3.4.x/docs/images/apps/learnboost.png    |   Bin 31434 -> 0 bytes
 docs/3.4.x/docs/images/apps/linkr.png         |   Bin 6428 -> 0 bytes
 docs/3.4.x/docs/images/apps/lists.png         |   Bin 697 -> 0 bytes
 docs/3.4.x/docs/images/apps/localresponse.png |   Bin 26423 -> 0 bytes
 docs/3.4.x/docs/images/apps/mcdonalds.png     |   Bin 57481 -> 0 bytes
 docs/3.4.x/docs/images/apps/muffle.png        |   Bin 26658 -> 0 bytes
 docs/3.4.x/docs/images/apps/nextdays.png      |   Bin 35067 -> 0 bytes
 docs/3.4.x/docs/images/apps/nimblequiz.png    |   Bin 20990 -> 0 bytes
 docs/3.4.x/docs/images/apps/nuorder.png       |   Bin 38163 -> 0 bytes
 docs/3.4.x/docs/images/apps/scottyapp.png     |   Bin 118416 -> 0 bytes
 docs/3.4.x/docs/images/apps/seelio.png        |   Bin 24005 -> 0 bytes
 docs/3.4.x/docs/images/apps/selectvids.png    |   Bin 42214 -> 0 bytes
 docs/3.4.x/docs/images/apps/sharelatex.png    |   Bin 19707 -> 0 bytes
 docs/3.4.x/docs/images/apps/shoejitsu.png     |   Bin 35092 -> 0 bytes
 docs/3.4.x/docs/images/apps/skim.png          |   Bin 43580 -> 0 bytes
 docs/3.4.x/docs/images/apps/squadsheet.png    |   Bin 37071 -> 0 bytes
 docs/3.4.x/docs/images/apps/stachify.png      |   Bin 27783 -> 0 bytes
 docs/3.4.x/docs/images/apps/storify.png       |   Bin 55982 -> 0 bytes
 docs/3.4.x/docs/images/apps/todaylaunch.png   |   Bin 33233 -> 0 bytes
 docs/3.4.x/docs/images/apps/treinosmart.png   |   Bin 26723 -> 0 bytes
 docs/3.4.x/docs/images/apps/upcload.png       |   Bin 37792 -> 0 bytes
 docs/3.4.x/docs/images/apps/urls              |    34 -
 docs/3.4.x/docs/images/apps/veriwalk.png      |   Bin 28311 -> 0 bytes
 docs/3.4.x/docs/images/apps/wavo.png          |   Bin 54906 -> 0 bytes
 docs/3.4.x/docs/images/apps/zootify.png       |   Bin 44707 -> 0 bytes
 docs/3.4.x/docs/images/square_bg.png          |   Bin 2217 -> 0 bytes
 docs/3.4.x/docs/includes/googleanalytics.jade |    10 -
 docs/3.4.x/docs/includes/nav.jade             |    55 -
 docs/3.4.x/docs/index.html                    |    41 -
 docs/3.4.x/docs/js/cookies.min.js             |     4 -
 docs/3.4.x/docs/js/zepto.min.js               |     2 -
 docs/3.4.x/docs/middleware.html               |    29 -
 docs/3.4.x/docs/migration.html                |    40 -
 docs/3.4.x/docs/models.html                   |    31 -
 docs/3.4.x/docs/plugins.html                  |    33 -
 docs/3.4.x/docs/populate.html                 |   104 -
 docs/3.4.x/docs/prior.html                    |     9 -
 docs/3.4.x/docs/production.html               |     9 -
 docs/3.4.x/docs/queries.html                  |    41 -
 docs/3.4.x/docs/releases                      |     6 -
 docs/3.4.x/docs/schematypes.html              |    67 -
 docs/3.4.x/docs/source/_docs                  | 16713 --------------
 docs/3.4.x/docs/source/api.js                 |   220 -
 docs/3.4.x/docs/source/home.js                |     7 -
 docs/3.4.x/docs/source/index.js               |    20 -
 docs/3.4.x/docs/source/prior.js               |    13 -
 docs/3.4.x/docs/source/production.js          |    17 -
 docs/3.4.x/docs/subdocs.html                  |    49 -
 docs/3.4.x/docs/validation.html               |    37 -
 docs/3.4.x/docs/website.js                    |    48 -
 docs/3.4.x/index.html                         |    20 -
 docs/3.4.x/static.js                          |    17 -
 docs/3.5.x/docs/api.html                      |  7225 ------
 docs/3.5.x/docs/connections.html              |    32 -
 docs/3.5.x/docs/contributing.html             |     9 -
 docs/3.5.x/docs/css/api.css                   |   244 -
 docs/3.5.x/docs/css/default.css               |   135 -
 docs/3.5.x/docs/css/guide.css                 |   332 -
 docs/3.5.x/docs/css/style.css                 |   255 -
 docs/3.5.x/docs/documents.html                |    20 -
 docs/3.5.x/docs/faq.html                      |    31 -
 docs/3.5.x/docs/guide.html                    |   200 -
 docs/3.5.x/docs/helpers/filters.js            |    20 -
 docs/3.5.x/docs/helpers/highlight.js          |    11 -
 docs/3.5.x/docs/helpers/href.js               |     8 -
 docs/3.5.x/docs/helpers/klass.js              |     5 -
 docs/3.5.x/docs/helpers/linktype.js           |    50 -
 docs/3.5.x/docs/images/apps/attictv.png       |   Bin 42666 -> 0 bytes
 docs/3.5.x/docs/images/apps/bozuko.png        |   Bin 37827 -> 0 bytes
 docs/3.5.x/docs/images/apps/calllist.png      |   Bin 33502 -> 0 bytes
 docs/3.5.x/docs/images/apps/cldfy.png         |   Bin 9773 -> 0 bytes
 docs/3.5.x/docs/images/apps/clickdummy.png    |   Bin 34210 -> 0 bytes
 docs/3.5.x/docs/images/apps/cyborgvision.png  |   Bin 42616 -> 0 bytes
 docs/3.5.x/docs/images/apps/dashku.png        |   Bin 25043 -> 0 bytes
 .../docs/images/apps/firstimpression.png      |   Bin 32241 -> 0 bytes
 docs/3.5.x/docs/images/apps/furbabyrescue.png |   Bin 49891 -> 0 bytes
 docs/3.5.x/docs/images/apps/geeklist.png      |   Bin 27911 -> 0 bytes
 docs/3.5.x/docs/images/apps/grab              |    71 -
 .../docs/images/apps/growthegamegolf.png      |   Bin 43441 -> 0 bytes
 docs/3.5.x/docs/images/apps/h_bozuko.jpg      |   Bin 11928 -> 0 bytes
 docs/3.5.x/docs/images/apps/h_geeklist.png    |   Bin 3482 -> 0 bytes
 docs/3.5.x/docs/images/apps/h_learnboost.png  |   Bin 12727 -> 0 bytes
 docs/3.5.x/docs/images/apps/h_mcds.png        |   Bin 3904 -> 0 bytes
 docs/3.5.x/docs/images/apps/h_shoejitsu.png   |   Bin 12695 -> 0 bytes
 docs/3.5.x/docs/images/apps/h_storify.jpg     |   Bin 14291 -> 0 bytes
 docs/3.5.x/docs/images/apps/knack.png         |   Bin 29572 -> 0 bytes
 docs/3.5.x/docs/images/apps/kyyti.png         |   Bin 41966 -> 0 bytes
 docs/3.5.x/docs/images/apps/learnboost.png    |   Bin 31434 -> 0 bytes
 docs/3.5.x/docs/images/apps/linkr.png         |   Bin 6428 -> 0 bytes
 docs/3.5.x/docs/images/apps/lists.png         |   Bin 697 -> 0 bytes
 docs/3.5.x/docs/images/apps/localresponse.png |   Bin 26423 -> 0 bytes
 docs/3.5.x/docs/images/apps/mcdonalds.png     |   Bin 57481 -> 0 bytes
 docs/3.5.x/docs/images/apps/moveline.png      |   Bin 30271 -> 0 bytes
 docs/3.5.x/docs/images/apps/muffle.png        |   Bin 26658 -> 0 bytes
 docs/3.5.x/docs/images/apps/mybrickbuilds.png |   Bin 42263 -> 0 bytes
 docs/3.5.x/docs/images/apps/nextdays.png      |   Bin 35067 -> 0 bytes
 docs/3.5.x/docs/images/apps/nimblequiz.png    |   Bin 20990 -> 0 bytes
 docs/3.5.x/docs/images/apps/nuorder.png       |   Bin 38163 -> 0 bytes
 docs/3.5.x/docs/images/apps/panemerkille.png  |   Bin 26344 -> 0 bytes
 docs/3.5.x/docs/images/apps/pictorious.png    |   Bin 45953 -> 0 bytes
 docs/3.5.x/docs/images/apps/scottyapp.png     |   Bin 118416 -> 0 bytes
 docs/3.5.x/docs/images/apps/seelio.png        |   Bin 24005 -> 0 bytes
 docs/3.5.x/docs/images/apps/selectvids.png    |   Bin 42214 -> 0 bytes
 docs/3.5.x/docs/images/apps/sharelatex.png    |   Bin 19707 -> 0 bytes
 docs/3.5.x/docs/images/apps/shoejitsu.png     |   Bin 35092 -> 0 bytes
 docs/3.5.x/docs/images/apps/skim.png          |   Bin 43580 -> 0 bytes
 docs/3.5.x/docs/images/apps/squadsheet.png    |   Bin 37071 -> 0 bytes
 docs/3.5.x/docs/images/apps/stachify.png      |   Bin 27783 -> 0 bytes
 docs/3.5.x/docs/images/apps/storify.png       |   Bin 55982 -> 0 bytes
 docs/3.5.x/docs/images/apps/todaylaunch.png   |   Bin 33233 -> 0 bytes
 docs/3.5.x/docs/images/apps/treinosmart.png   |   Bin 26723 -> 0 bytes
 docs/3.5.x/docs/images/apps/upcload.png       |   Bin 37792 -> 0 bytes
 docs/3.5.x/docs/images/apps/urls              |    39 -
 docs/3.5.x/docs/images/apps/veriwalk.png      |   Bin 28311 -> 0 bytes
 docs/3.5.x/docs/images/apps/wavo.png          |   Bin 54906 -> 0 bytes
 docs/3.5.x/docs/images/apps/zootify.png       |   Bin 44707 -> 0 bytes
 docs/3.5.x/docs/images/square_bg.png          |   Bin 2217 -> 0 bytes
 docs/3.5.x/docs/includes/googleanalytics.jade |    10 -
 docs/3.5.x/docs/includes/nav.jade             |    55 -
 docs/3.5.x/docs/index.html                    |    43 -
 docs/3.5.x/docs/js/cookies.min.js             |     4 -
 docs/3.5.x/docs/js/zepto.min.js               |     2 -
 docs/3.5.x/docs/middleware.html               |    40 -
 docs/3.5.x/docs/migration.html                |    40 -
 docs/3.5.x/docs/models.html                   |    30 -
 docs/3.5.x/docs/plugins.html                  |    33 -
 docs/3.5.x/docs/populate.html                 |   104 -
 docs/3.5.x/docs/prior.html                    |     9 -
 docs/3.5.x/docs/production.html               |     9 -
 docs/3.5.x/docs/queries.html                  |    41 -
 docs/3.5.x/docs/schematypes.html              |    67 -
 docs/3.5.x/docs/source/_docs                  | 18108 ----------------
 docs/3.5.x/docs/source/api.js                 |   223 -
 docs/3.5.x/docs/source/home.js                |     7 -
 docs/3.5.x/docs/source/index.js               |    20 -
 docs/3.5.x/docs/source/prior.js               |    13 -
 docs/3.5.x/docs/source/production.js          |    17 -
 docs/3.5.x/docs/subdocs.html                  |    49 -
 docs/3.5.x/docs/validation.html               |    37 -
 docs/3.5.x/index.html                         |    20 -
 docs/3.5.x/static.js                          |    17 -
 docs/api.html                                 | 15277 ++++++++-----
 docs/api.jade                                 |     2 +-
 docs/contributing.html                        |    33 +-
 docs/documents.html                           |    63 +-
 docs/faq.html                                 |   150 +-
 docs/guide.html                               |   322 +-
 docs/guide.jade                               |     2 +-
 docs/includes/googleanalytics.jade            |    10 -
 docs/includes/keen.jade                       |    18 +
 docs/index.html                               |    69 +-
 docs/index.jade                               |     2 +-
 docs/layout.jade                              |     2 +-
 docs/middleware.html                          |   205 +-
 docs/migration.html                           |    77 +-
 docs/models.html                              |    55 +-
 docs/plugins.html                             |    44 +-
 docs/populate.html                            |   355 +-
 docs/prior.html                               |    33 +-
 docs/queries.html                             |   102 +-
 docs/redirect.jade                            |     2 +-
 docs/schematypes.html                         |   130 +-
 docs/subdocs.html                             |   145 +-
 docs/validation.html                          |   474 +-
 index.html                                    |    35 +-
 index.jade                                    |     2 +-
 497 files changed, 11600 insertions(+), 167457 deletions(-)
 delete mode 100644 docs/3.0.x/docs/api.html
 delete mode 100644 docs/3.0.x/docs/api.jade
 delete mode 100644 docs/3.0.x/docs/contributing.html
 delete mode 100644 docs/3.0.x/docs/contributing.jade
 delete mode 100644 docs/3.0.x/docs/css/default.css
 delete mode 100644 docs/3.0.x/docs/css/guide.css
 delete mode 100644 docs/3.0.x/docs/documents.html
 delete mode 100644 docs/3.0.x/docs/documents.jade
 delete mode 100644 docs/3.0.x/docs/faq.html
 delete mode 100644 docs/3.0.x/docs/faq.jade
 delete mode 100644 docs/3.0.x/docs/guide.html
 delete mode 100644 docs/3.0.x/docs/guide.jade
 delete mode 100644 docs/3.0.x/docs/helpers/filters.js
 delete mode 100644 docs/3.0.x/docs/helpers/highlight.js
 delete mode 100644 docs/3.0.x/docs/helpers/href.js
 delete mode 100644 docs/3.0.x/docs/helpers/klass.js
 delete mode 100644 docs/3.0.x/docs/helpers/linktype.js
 delete mode 100755 docs/3.0.x/docs/images/apps/grab
 delete mode 100644 docs/3.0.x/docs/images/apps/urls
 delete mode 100644 docs/3.0.x/docs/images/square_bg.png
 delete mode 100644 docs/3.0.x/docs/includes/googleanalytics.jade
 delete mode 100644 docs/3.0.x/docs/includes/nav.jade
 delete mode 100644 docs/3.0.x/docs/index.html
 delete mode 100644 docs/3.0.x/docs/index.jade
 delete mode 100644 docs/3.0.x/docs/js/zepto.min.js
 delete mode 100644 docs/3.0.x/docs/layout.jade
 delete mode 100644 docs/3.0.x/docs/middleware.html
 delete mode 100644 docs/3.0.x/docs/middleware.jade
 delete mode 100644 docs/3.0.x/docs/migration.html
 delete mode 100644 docs/3.0.x/docs/migration.jade
 delete mode 100644 docs/3.0.x/docs/models.html
 delete mode 100644 docs/3.0.x/docs/models.jade
 delete mode 100644 docs/3.0.x/docs/plugins.html
 delete mode 100644 docs/3.0.x/docs/plugins.jade
 delete mode 100644 docs/3.0.x/docs/populate.html
 delete mode 100644 docs/3.0.x/docs/populate.jade
 delete mode 100644 docs/3.0.x/docs/prior.html
 delete mode 100644 docs/3.0.x/docs/prior.jade
 delete mode 100644 docs/3.0.x/docs/queries.html
 delete mode 100644 docs/3.0.x/docs/queries.jade
 delete mode 100644 docs/3.0.x/docs/releases
 delete mode 100644 docs/3.0.x/docs/schematypes.html
 delete mode 100644 docs/3.0.x/docs/schematypes.jade
 delete mode 100644 docs/3.0.x/docs/source/_docs
 delete mode 100644 docs/3.0.x/docs/source/api.js
 delete mode 100644 docs/3.0.x/docs/source/home.js
 delete mode 100644 docs/3.0.x/docs/source/index.js
 delete mode 100644 docs/3.0.x/docs/source/prior.js
 delete mode 100644 docs/3.0.x/docs/subdocs.html
 delete mode 100644 docs/3.0.x/docs/subdocs.jade
 delete mode 100644 docs/3.0.x/docs/validation.html
 delete mode 100644 docs/3.0.x/docs/validation.jade
 delete mode 100644 docs/3.0.x/index.html
 delete mode 100644 docs/3.0.x/static.js
 delete mode 100644 docs/3.1.x/docs/api.html
 delete mode 100644 docs/3.1.x/docs/api.jade
 delete mode 100644 docs/3.1.x/docs/contributing.html
 delete mode 100644 docs/3.1.x/docs/contributing.jade
 delete mode 100644 docs/3.1.x/docs/css/default.css
 delete mode 100644 docs/3.1.x/docs/css/guide.css
 delete mode 100644 docs/3.1.x/docs/documents.html
 delete mode 100644 docs/3.1.x/docs/documents.jade
 delete mode 100644 docs/3.1.x/docs/faq.html
 delete mode 100644 docs/3.1.x/docs/faq.jade
 delete mode 100644 docs/3.1.x/docs/guide.html
 delete mode 100644 docs/3.1.x/docs/guide.jade
 delete mode 100644 docs/3.1.x/docs/helpers/filters.js
 delete mode 100644 docs/3.1.x/docs/helpers/highlight.js
 delete mode 100644 docs/3.1.x/docs/helpers/href.js
 delete mode 100644 docs/3.1.x/docs/helpers/klass.js
 delete mode 100644 docs/3.1.x/docs/helpers/linktype.js
 delete mode 100755 docs/3.1.x/docs/images/apps/grab
 delete mode 100644 docs/3.1.x/docs/images/apps/urls
 delete mode 100644 docs/3.1.x/docs/images/square_bg.png
 delete mode 100644 docs/3.1.x/docs/includes/googleanalytics.jade
 delete mode 100644 docs/3.1.x/docs/includes/nav.jade
 delete mode 100644 docs/3.1.x/docs/index.html
 delete mode 100644 docs/3.1.x/docs/index.jade
 delete mode 100644 docs/3.1.x/docs/js/zepto.min.js
 delete mode 100644 docs/3.1.x/docs/layout.jade
 delete mode 100644 docs/3.1.x/docs/middleware.html
 delete mode 100644 docs/3.1.x/docs/middleware.jade
 delete mode 100644 docs/3.1.x/docs/migration.html
 delete mode 100644 docs/3.1.x/docs/migration.jade
 delete mode 100644 docs/3.1.x/docs/models.html
 delete mode 100644 docs/3.1.x/docs/models.jade
 delete mode 100644 docs/3.1.x/docs/plugins.html
 delete mode 100644 docs/3.1.x/docs/plugins.jade
 delete mode 100644 docs/3.1.x/docs/populate.html
 delete mode 100644 docs/3.1.x/docs/populate.jade
 delete mode 100644 docs/3.1.x/docs/prior.html
 delete mode 100644 docs/3.1.x/docs/prior.jade
 delete mode 100644 docs/3.1.x/docs/queries.html
 delete mode 100644 docs/3.1.x/docs/queries.jade
 delete mode 100644 docs/3.1.x/docs/releases
 delete mode 100644 docs/3.1.x/docs/schematypes.html
 delete mode 100644 docs/3.1.x/docs/schematypes.jade
 delete mode 100644 docs/3.1.x/docs/source/_docs
 delete mode 100644 docs/3.1.x/docs/source/api.js
 delete mode 100644 docs/3.1.x/docs/source/home.js
 delete mode 100644 docs/3.1.x/docs/source/index.js
 delete mode 100644 docs/3.1.x/docs/source/prior.js
 delete mode 100644 docs/3.1.x/docs/subdocs.html
 delete mode 100644 docs/3.1.x/docs/subdocs.jade
 delete mode 100644 docs/3.1.x/docs/validation.html
 delete mode 100644 docs/3.1.x/docs/validation.jade
 delete mode 100644 docs/3.1.x/index.html
 delete mode 100644 docs/3.1.x/static.js
 delete mode 100644 docs/3.2.x/docs/api.html
 delete mode 100644 docs/3.2.x/docs/api.jade
 delete mode 100644 docs/3.2.x/docs/connections.html
 delete mode 100644 docs/3.2.x/docs/connections.jade
 delete mode 100644 docs/3.2.x/docs/contributing.html
 delete mode 100644 docs/3.2.x/docs/contributing.jade
 delete mode 100644 docs/3.2.x/docs/css/default.css
 delete mode 100644 docs/3.2.x/docs/css/guide.css
 delete mode 100644 docs/3.2.x/docs/css/style.css
 delete mode 100644 docs/3.2.x/docs/documents.html
 delete mode 100644 docs/3.2.x/docs/documents.jade
 delete mode 100644 docs/3.2.x/docs/faq.html
 delete mode 100644 docs/3.2.x/docs/faq.jade
 delete mode 100644 docs/3.2.x/docs/guide.html
 delete mode 100644 docs/3.2.x/docs/guide.jade
 delete mode 100644 docs/3.2.x/docs/helpers/filters.js
 delete mode 100644 docs/3.2.x/docs/helpers/highlight.js
 delete mode 100644 docs/3.2.x/docs/helpers/href.js
 delete mode 100644 docs/3.2.x/docs/helpers/klass.js
 delete mode 100644 docs/3.2.x/docs/helpers/linktype.js
 delete mode 100644 docs/3.2.x/docs/images/apps/attictv.png
 delete mode 100644 docs/3.2.x/docs/images/apps/bozuko.png
 delete mode 100644 docs/3.2.x/docs/images/apps/calllist.png
 delete mode 100644 docs/3.2.x/docs/images/apps/cldfy.png
 delete mode 100644 docs/3.2.x/docs/images/apps/clickdummy.png
 delete mode 100644 docs/3.2.x/docs/images/apps/cyborgvision.png
 delete mode 100644 docs/3.2.x/docs/images/apps/furbabyrescue.png
 delete mode 100644 docs/3.2.x/docs/images/apps/geeklist.png
 delete mode 100755 docs/3.2.x/docs/images/apps/grab
 delete mode 100644 docs/3.2.x/docs/images/apps/growthegamegolf.png
 delete mode 100644 docs/3.2.x/docs/images/apps/kyyti.png
 delete mode 100644 docs/3.2.x/docs/images/apps/learnboost.png
 delete mode 100644 docs/3.2.x/docs/images/apps/linkr.png
 delete mode 100644 docs/3.2.x/docs/images/apps/lists.png
 delete mode 100644 docs/3.2.x/docs/images/apps/localresponse.png
 delete mode 100644 docs/3.2.x/docs/images/apps/nextdays.png
 delete mode 100644 docs/3.2.x/docs/images/apps/nimblequiz.png
 delete mode 100644 docs/3.2.x/docs/images/apps/nuorder.png
 delete mode 100644 docs/3.2.x/docs/images/apps/scottyapp.png
 delete mode 100644 docs/3.2.x/docs/images/apps/seelio.png
 delete mode 100644 docs/3.2.x/docs/images/apps/selectvids.png
 delete mode 100644 docs/3.2.x/docs/images/apps/sharelatex.png
 delete mode 100644 docs/3.2.x/docs/images/apps/shoejitsu.png
 delete mode 100644 docs/3.2.x/docs/images/apps/skim.png
 delete mode 100644 docs/3.2.x/docs/images/apps/stachify.png
 delete mode 100644 docs/3.2.x/docs/images/apps/storify.png
 delete mode 100644 docs/3.2.x/docs/images/apps/todaylaunch.png
 delete mode 100644 docs/3.2.x/docs/images/apps/treinosmart.png
 delete mode 100644 docs/3.2.x/docs/images/apps/upcload.png
 delete mode 100644 docs/3.2.x/docs/images/apps/urls
 delete mode 100644 docs/3.2.x/docs/images/apps/wavo.png
 delete mode 100644 docs/3.2.x/docs/images/square_bg.png
 delete mode 100644 docs/3.2.x/docs/includes/googleanalytics.jade
 delete mode 100644 docs/3.2.x/docs/includes/nav.jade
 delete mode 100644 docs/3.2.x/docs/index.html
 delete mode 100644 docs/3.2.x/docs/index.jade
 delete mode 100644 docs/3.2.x/docs/js/zepto.min.js
 delete mode 100644 docs/3.2.x/docs/layout.jade
 delete mode 100644 docs/3.2.x/docs/middleware.html
 delete mode 100644 docs/3.2.x/docs/middleware.jade
 delete mode 100644 docs/3.2.x/docs/migration.html
 delete mode 100644 docs/3.2.x/docs/migration.jade
 delete mode 100644 docs/3.2.x/docs/models.html
 delete mode 100644 docs/3.2.x/docs/models.jade
 delete mode 100644 docs/3.2.x/docs/plugins.html
 delete mode 100644 docs/3.2.x/docs/plugins.jade
 delete mode 100644 docs/3.2.x/docs/populate.html
 delete mode 100644 docs/3.2.x/docs/populate.jade
 delete mode 100644 docs/3.2.x/docs/prior.html
 delete mode 100644 docs/3.2.x/docs/prior.jade
 delete mode 100644 docs/3.2.x/docs/queries.html
 delete mode 100644 docs/3.2.x/docs/queries.jade
 delete mode 100644 docs/3.2.x/docs/releases
 delete mode 100644 docs/3.2.x/docs/schematypes.html
 delete mode 100644 docs/3.2.x/docs/schematypes.jade
 delete mode 100644 docs/3.2.x/docs/source/_docs
 delete mode 100644 docs/3.2.x/docs/source/api.js
 delete mode 100644 docs/3.2.x/docs/source/home.js
 delete mode 100644 docs/3.2.x/docs/source/index.js
 delete mode 100644 docs/3.2.x/docs/source/prior.js
 delete mode 100644 docs/3.2.x/docs/subdocs.html
 delete mode 100644 docs/3.2.x/docs/subdocs.jade
 delete mode 100644 docs/3.2.x/docs/validation.html
 delete mode 100644 docs/3.2.x/docs/validation.jade
 delete mode 100644 docs/3.2.x/index.html
 delete mode 100644 docs/3.2.x/static.js
 delete mode 100644 docs/3.3.x/docs/api.html
 delete mode 100644 docs/3.3.x/docs/api.jade
 delete mode 100644 docs/3.3.x/docs/connections.html
 delete mode 100644 docs/3.3.x/docs/connections.jade
 delete mode 100644 docs/3.3.x/docs/contributing.html
 delete mode 100644 docs/3.3.x/docs/contributing.jade
 delete mode 100644 docs/3.3.x/docs/css/default.css
 delete mode 100644 docs/3.3.x/docs/css/guide.css
 delete mode 100644 docs/3.3.x/docs/css/style.css
 delete mode 100644 docs/3.3.x/docs/documents.html
 delete mode 100644 docs/3.3.x/docs/documents.jade
 delete mode 100644 docs/3.3.x/docs/faq.html
 delete mode 100644 docs/3.3.x/docs/faq.jade
 delete mode 100644 docs/3.3.x/docs/guide.html
 delete mode 100644 docs/3.3.x/docs/guide.jade
 delete mode 100644 docs/3.3.x/docs/helpers/filters.js
 delete mode 100644 docs/3.3.x/docs/helpers/highlight.js
 delete mode 100644 docs/3.3.x/docs/helpers/href.js
 delete mode 100644 docs/3.3.x/docs/helpers/klass.js
 delete mode 100644 docs/3.3.x/docs/helpers/linktype.js
 delete mode 100644 docs/3.3.x/docs/images/apps/attictv.png
 delete mode 100644 docs/3.3.x/docs/images/apps/bozuko.png
 delete mode 100644 docs/3.3.x/docs/images/apps/calllist.png
 delete mode 100644 docs/3.3.x/docs/images/apps/cldfy.png
 delete mode 100644 docs/3.3.x/docs/images/apps/clickdummy.png
 delete mode 100644 docs/3.3.x/docs/images/apps/cyborgvision.png
 delete mode 100644 docs/3.3.x/docs/images/apps/dashku.png
 delete mode 100644 docs/3.3.x/docs/images/apps/firstimpression.png
 delete mode 100644 docs/3.3.x/docs/images/apps/furbabyrescue.png
 delete mode 100644 docs/3.3.x/docs/images/apps/geeklist.png
 delete mode 100755 docs/3.3.x/docs/images/apps/grab
 delete mode 100644 docs/3.3.x/docs/images/apps/growthegamegolf.png
 delete mode 100644 docs/3.3.x/docs/images/apps/h_bozuko.jpg
 delete mode 100644 docs/3.3.x/docs/images/apps/h_geeklist.png
 delete mode 100644 docs/3.3.x/docs/images/apps/h_learnboost.png
 delete mode 100644 docs/3.3.x/docs/images/apps/h_mcds.png
 delete mode 100644 docs/3.3.x/docs/images/apps/h_shoejitsu.png
 delete mode 100644 docs/3.3.x/docs/images/apps/h_storify.jpg
 delete mode 100644 docs/3.3.x/docs/images/apps/kyyti.png
 delete mode 100644 docs/3.3.x/docs/images/apps/learnboost.png
 delete mode 100644 docs/3.3.x/docs/images/apps/linkr.png
 delete mode 100644 docs/3.3.x/docs/images/apps/lists.png
 delete mode 100644 docs/3.3.x/docs/images/apps/localresponse.png
 delete mode 100644 docs/3.3.x/docs/images/apps/mcdonalds.png
 delete mode 100644 docs/3.3.x/docs/images/apps/muffle.png
 delete mode 100644 docs/3.3.x/docs/images/apps/nextdays.png
 delete mode 100644 docs/3.3.x/docs/images/apps/nimblequiz.png
 delete mode 100644 docs/3.3.x/docs/images/apps/nuorder.png
 delete mode 100644 docs/3.3.x/docs/images/apps/scottyapp.png
 delete mode 100644 docs/3.3.x/docs/images/apps/seelio.png
 delete mode 100644 docs/3.3.x/docs/images/apps/selectvids.png
 delete mode 100644 docs/3.3.x/docs/images/apps/sharelatex.png
 delete mode 100644 docs/3.3.x/docs/images/apps/shoejitsu.png
 delete mode 100644 docs/3.3.x/docs/images/apps/skim.png
 delete mode 100644 docs/3.3.x/docs/images/apps/squadsheet.png
 delete mode 100644 docs/3.3.x/docs/images/apps/stachify.png
 delete mode 100644 docs/3.3.x/docs/images/apps/storify.png
 delete mode 100644 docs/3.3.x/docs/images/apps/todaylaunch.png
 delete mode 100644 docs/3.3.x/docs/images/apps/treinosmart.png
 delete mode 100644 docs/3.3.x/docs/images/apps/upcload.png
 delete mode 100644 docs/3.3.x/docs/images/apps/urls
 delete mode 100644 docs/3.3.x/docs/images/apps/veriwalk.png
 delete mode 100644 docs/3.3.x/docs/images/apps/wavo.png
 delete mode 100644 docs/3.3.x/docs/images/apps/zootify.png
 delete mode 100644 docs/3.3.x/docs/images/square_bg.png
 delete mode 100644 docs/3.3.x/docs/includes/googleanalytics.jade
 delete mode 100644 docs/3.3.x/docs/includes/nav.jade
 delete mode 100644 docs/3.3.x/docs/index.html
 delete mode 100644 docs/3.3.x/docs/index.jade
 delete mode 100644 docs/3.3.x/docs/js/cookies.min.js
 delete mode 100644 docs/3.3.x/docs/js/zepto.min.js
 delete mode 100644 docs/3.3.x/docs/layout.jade
 delete mode 100644 docs/3.3.x/docs/middleware.html
 delete mode 100644 docs/3.3.x/docs/middleware.jade
 delete mode 100644 docs/3.3.x/docs/migration.html
 delete mode 100644 docs/3.3.x/docs/migration.jade
 delete mode 100644 docs/3.3.x/docs/models.html
 delete mode 100644 docs/3.3.x/docs/models.jade
 delete mode 100644 docs/3.3.x/docs/plugins.html
 delete mode 100644 docs/3.3.x/docs/plugins.jade
 delete mode 100644 docs/3.3.x/docs/populate.html
 delete mode 100644 docs/3.3.x/docs/populate.jade
 delete mode 100644 docs/3.3.x/docs/prior.html
 delete mode 100644 docs/3.3.x/docs/prior.jade
 delete mode 100644 docs/3.3.x/docs/production.html
 delete mode 100644 docs/3.3.x/docs/production.jade
 delete mode 100644 docs/3.3.x/docs/queries.html
 delete mode 100644 docs/3.3.x/docs/queries.jade
 delete mode 100644 docs/3.3.x/docs/releases
 delete mode 100644 docs/3.3.x/docs/schematypes.html
 delete mode 100644 docs/3.3.x/docs/schematypes.jade
 delete mode 100644 docs/3.3.x/docs/source/_docs
 delete mode 100644 docs/3.3.x/docs/source/api.js
 delete mode 100644 docs/3.3.x/docs/source/home.js
 delete mode 100644 docs/3.3.x/docs/source/index.js
 delete mode 100644 docs/3.3.x/docs/source/prior.js
 delete mode 100644 docs/3.3.x/docs/source/production.js
 delete mode 100644 docs/3.3.x/docs/subdocs.html
 delete mode 100644 docs/3.3.x/docs/subdocs.jade
 delete mode 100644 docs/3.3.x/docs/validation.html
 delete mode 100644 docs/3.3.x/docs/validation.jade
 delete mode 100644 docs/3.3.x/docs/website.js
 delete mode 100644 docs/3.3.x/index.html
 delete mode 100644 docs/3.3.x/static.js
 delete mode 100644 docs/3.4.x/docs/api.html
 delete mode 100644 docs/3.4.x/docs/connections.html
 delete mode 100644 docs/3.4.x/docs/contributing.html
 delete mode 100644 docs/3.4.x/docs/css/default.css
 delete mode 100644 docs/3.4.x/docs/css/guide.css
 delete mode 100644 docs/3.4.x/docs/css/style.css
 delete mode 100644 docs/3.4.x/docs/documents.html
 delete mode 100644 docs/3.4.x/docs/faq.html
 delete mode 100644 docs/3.4.x/docs/guide.html
 delete mode 100644 docs/3.4.x/docs/helpers/filters.js
 delete mode 100644 docs/3.4.x/docs/helpers/highlight.js
 delete mode 100644 docs/3.4.x/docs/helpers/href.js
 delete mode 100644 docs/3.4.x/docs/helpers/klass.js
 delete mode 100644 docs/3.4.x/docs/helpers/linktype.js
 delete mode 100644 docs/3.4.x/docs/images/apps/attictv.png
 delete mode 100644 docs/3.4.x/docs/images/apps/bozuko.png
 delete mode 100644 docs/3.4.x/docs/images/apps/calllist.png
 delete mode 100644 docs/3.4.x/docs/images/apps/cldfy.png
 delete mode 100644 docs/3.4.x/docs/images/apps/clickdummy.png
 delete mode 100644 docs/3.4.x/docs/images/apps/cyborgvision.png
 delete mode 100644 docs/3.4.x/docs/images/apps/dashku.png
 delete mode 100644 docs/3.4.x/docs/images/apps/firstimpression.png
 delete mode 100644 docs/3.4.x/docs/images/apps/furbabyrescue.png
 delete mode 100644 docs/3.4.x/docs/images/apps/geeklist.png
 delete mode 100755 docs/3.4.x/docs/images/apps/grab
 delete mode 100644 docs/3.4.x/docs/images/apps/growthegamegolf.png
 delete mode 100644 docs/3.4.x/docs/images/apps/h_bozuko.jpg
 delete mode 100644 docs/3.4.x/docs/images/apps/h_geeklist.png
 delete mode 100644 docs/3.4.x/docs/images/apps/h_learnboost.png
 delete mode 100644 docs/3.4.x/docs/images/apps/h_mcds.png
 delete mode 100644 docs/3.4.x/docs/images/apps/h_shoejitsu.png
 delete mode 100644 docs/3.4.x/docs/images/apps/h_storify.jpg
 delete mode 100644 docs/3.4.x/docs/images/apps/kyyti.png
 delete mode 100644 docs/3.4.x/docs/images/apps/learnboost.png
 delete mode 100644 docs/3.4.x/docs/images/apps/linkr.png
 delete mode 100644 docs/3.4.x/docs/images/apps/lists.png
 delete mode 100644 docs/3.4.x/docs/images/apps/localresponse.png
 delete mode 100644 docs/3.4.x/docs/images/apps/mcdonalds.png
 delete mode 100644 docs/3.4.x/docs/images/apps/muffle.png
 delete mode 100644 docs/3.4.x/docs/images/apps/nextdays.png
 delete mode 100644 docs/3.4.x/docs/images/apps/nimblequiz.png
 delete mode 100644 docs/3.4.x/docs/images/apps/nuorder.png
 delete mode 100644 docs/3.4.x/docs/images/apps/scottyapp.png
 delete mode 100644 docs/3.4.x/docs/images/apps/seelio.png
 delete mode 100644 docs/3.4.x/docs/images/apps/selectvids.png
 delete mode 100644 docs/3.4.x/docs/images/apps/sharelatex.png
 delete mode 100644 docs/3.4.x/docs/images/apps/shoejitsu.png
 delete mode 100644 docs/3.4.x/docs/images/apps/skim.png
 delete mode 100644 docs/3.4.x/docs/images/apps/squadsheet.png
 delete mode 100644 docs/3.4.x/docs/images/apps/stachify.png
 delete mode 100644 docs/3.4.x/docs/images/apps/storify.png
 delete mode 100644 docs/3.4.x/docs/images/apps/todaylaunch.png
 delete mode 100644 docs/3.4.x/docs/images/apps/treinosmart.png
 delete mode 100644 docs/3.4.x/docs/images/apps/upcload.png
 delete mode 100644 docs/3.4.x/docs/images/apps/urls
 delete mode 100644 docs/3.4.x/docs/images/apps/veriwalk.png
 delete mode 100644 docs/3.4.x/docs/images/apps/wavo.png
 delete mode 100644 docs/3.4.x/docs/images/apps/zootify.png
 delete mode 100644 docs/3.4.x/docs/images/square_bg.png
 delete mode 100644 docs/3.4.x/docs/includes/googleanalytics.jade
 delete mode 100644 docs/3.4.x/docs/includes/nav.jade
 delete mode 100644 docs/3.4.x/docs/index.html
 delete mode 100644 docs/3.4.x/docs/js/cookies.min.js
 delete mode 100644 docs/3.4.x/docs/js/zepto.min.js
 delete mode 100644 docs/3.4.x/docs/middleware.html
 delete mode 100644 docs/3.4.x/docs/migration.html
 delete mode 100644 docs/3.4.x/docs/models.html
 delete mode 100644 docs/3.4.x/docs/plugins.html
 delete mode 100644 docs/3.4.x/docs/populate.html
 delete mode 100644 docs/3.4.x/docs/prior.html
 delete mode 100644 docs/3.4.x/docs/production.html
 delete mode 100644 docs/3.4.x/docs/queries.html
 delete mode 100644 docs/3.4.x/docs/releases
 delete mode 100644 docs/3.4.x/docs/schematypes.html
 delete mode 100644 docs/3.4.x/docs/source/_docs
 delete mode 100644 docs/3.4.x/docs/source/api.js
 delete mode 100644 docs/3.4.x/docs/source/home.js
 delete mode 100644 docs/3.4.x/docs/source/index.js
 delete mode 100644 docs/3.4.x/docs/source/prior.js
 delete mode 100644 docs/3.4.x/docs/source/production.js
 delete mode 100644 docs/3.4.x/docs/subdocs.html
 delete mode 100644 docs/3.4.x/docs/validation.html
 delete mode 100644 docs/3.4.x/docs/website.js
 delete mode 100644 docs/3.4.x/index.html
 delete mode 100644 docs/3.4.x/static.js
 delete mode 100644 docs/3.5.x/docs/api.html
 delete mode 100644 docs/3.5.x/docs/connections.html
 delete mode 100644 docs/3.5.x/docs/contributing.html
 delete mode 100644 docs/3.5.x/docs/css/api.css
 delete mode 100644 docs/3.5.x/docs/css/default.css
 delete mode 100644 docs/3.5.x/docs/css/guide.css
 delete mode 100644 docs/3.5.x/docs/css/style.css
 delete mode 100644 docs/3.5.x/docs/documents.html
 delete mode 100644 docs/3.5.x/docs/faq.html
 delete mode 100644 docs/3.5.x/docs/guide.html
 delete mode 100644 docs/3.5.x/docs/helpers/filters.js
 delete mode 100644 docs/3.5.x/docs/helpers/highlight.js
 delete mode 100644 docs/3.5.x/docs/helpers/href.js
 delete mode 100644 docs/3.5.x/docs/helpers/klass.js
 delete mode 100644 docs/3.5.x/docs/helpers/linktype.js
 delete mode 100644 docs/3.5.x/docs/images/apps/attictv.png
 delete mode 100644 docs/3.5.x/docs/images/apps/bozuko.png
 delete mode 100644 docs/3.5.x/docs/images/apps/calllist.png
 delete mode 100644 docs/3.5.x/docs/images/apps/cldfy.png
 delete mode 100644 docs/3.5.x/docs/images/apps/clickdummy.png
 delete mode 100644 docs/3.5.x/docs/images/apps/cyborgvision.png
 delete mode 100644 docs/3.5.x/docs/images/apps/dashku.png
 delete mode 100644 docs/3.5.x/docs/images/apps/firstimpression.png
 delete mode 100644 docs/3.5.x/docs/images/apps/furbabyrescue.png
 delete mode 100644 docs/3.5.x/docs/images/apps/geeklist.png
 delete mode 100755 docs/3.5.x/docs/images/apps/grab
 delete mode 100644 docs/3.5.x/docs/images/apps/growthegamegolf.png
 delete mode 100644 docs/3.5.x/docs/images/apps/h_bozuko.jpg
 delete mode 100644 docs/3.5.x/docs/images/apps/h_geeklist.png
 delete mode 100644 docs/3.5.x/docs/images/apps/h_learnboost.png
 delete mode 100644 docs/3.5.x/docs/images/apps/h_mcds.png
 delete mode 100644 docs/3.5.x/docs/images/apps/h_shoejitsu.png
 delete mode 100644 docs/3.5.x/docs/images/apps/h_storify.jpg
 delete mode 100644 docs/3.5.x/docs/images/apps/knack.png
 delete mode 100644 docs/3.5.x/docs/images/apps/kyyti.png
 delete mode 100644 docs/3.5.x/docs/images/apps/learnboost.png
 delete mode 100644 docs/3.5.x/docs/images/apps/linkr.png
 delete mode 100644 docs/3.5.x/docs/images/apps/lists.png
 delete mode 100644 docs/3.5.x/docs/images/apps/localresponse.png
 delete mode 100644 docs/3.5.x/docs/images/apps/mcdonalds.png
 delete mode 100644 docs/3.5.x/docs/images/apps/moveline.png
 delete mode 100644 docs/3.5.x/docs/images/apps/muffle.png
 delete mode 100644 docs/3.5.x/docs/images/apps/mybrickbuilds.png
 delete mode 100644 docs/3.5.x/docs/images/apps/nextdays.png
 delete mode 100644 docs/3.5.x/docs/images/apps/nimblequiz.png
 delete mode 100644 docs/3.5.x/docs/images/apps/nuorder.png
 delete mode 100644 docs/3.5.x/docs/images/apps/panemerkille.png
 delete mode 100644 docs/3.5.x/docs/images/apps/pictorious.png
 delete mode 100644 docs/3.5.x/docs/images/apps/scottyapp.png
 delete mode 100644 docs/3.5.x/docs/images/apps/seelio.png
 delete mode 100644 docs/3.5.x/docs/images/apps/selectvids.png
 delete mode 100644 docs/3.5.x/docs/images/apps/sharelatex.png
 delete mode 100644 docs/3.5.x/docs/images/apps/shoejitsu.png
 delete mode 100644 docs/3.5.x/docs/images/apps/skim.png
 delete mode 100644 docs/3.5.x/docs/images/apps/squadsheet.png
 delete mode 100644 docs/3.5.x/docs/images/apps/stachify.png
 delete mode 100644 docs/3.5.x/docs/images/apps/storify.png
 delete mode 100644 docs/3.5.x/docs/images/apps/todaylaunch.png
 delete mode 100644 docs/3.5.x/docs/images/apps/treinosmart.png
 delete mode 100644 docs/3.5.x/docs/images/apps/upcload.png
 delete mode 100644 docs/3.5.x/docs/images/apps/urls
 delete mode 100644 docs/3.5.x/docs/images/apps/veriwalk.png
 delete mode 100644 docs/3.5.x/docs/images/apps/wavo.png
 delete mode 100644 docs/3.5.x/docs/images/apps/zootify.png
 delete mode 100644 docs/3.5.x/docs/images/square_bg.png
 delete mode 100644 docs/3.5.x/docs/includes/googleanalytics.jade
 delete mode 100644 docs/3.5.x/docs/includes/nav.jade
 delete mode 100644 docs/3.5.x/docs/index.html
 delete mode 100644 docs/3.5.x/docs/js/cookies.min.js
 delete mode 100644 docs/3.5.x/docs/js/zepto.min.js
 delete mode 100644 docs/3.5.x/docs/middleware.html
 delete mode 100644 docs/3.5.x/docs/migration.html
 delete mode 100644 docs/3.5.x/docs/models.html
 delete mode 100644 docs/3.5.x/docs/plugins.html
 delete mode 100644 docs/3.5.x/docs/populate.html
 delete mode 100644 docs/3.5.x/docs/prior.html
 delete mode 100644 docs/3.5.x/docs/production.html
 delete mode 100644 docs/3.5.x/docs/queries.html
 delete mode 100644 docs/3.5.x/docs/schematypes.html
 delete mode 100644 docs/3.5.x/docs/source/_docs
 delete mode 100644 docs/3.5.x/docs/source/api.js
 delete mode 100644 docs/3.5.x/docs/source/home.js
 delete mode 100644 docs/3.5.x/docs/source/index.js
 delete mode 100644 docs/3.5.x/docs/source/prior.js
 delete mode 100644 docs/3.5.x/docs/source/production.js
 delete mode 100644 docs/3.5.x/docs/subdocs.html
 delete mode 100644 docs/3.5.x/docs/validation.html
 delete mode 100644 docs/3.5.x/index.html
 delete mode 100644 docs/3.5.x/static.js
 delete mode 100644 docs/includes/googleanalytics.jade
 create mode 100644 docs/includes/keen.jade

diff --git a/docs/3.0.x/docs/api.html b/docs/3.0.x/docs/api.html
deleted file mode 100644
index 1db5b1f7e65..00000000000
--- a/docs/3.0.x/docs/api.html
+++ /dev/null
@@ -1,6444 +0,0 @@
-Mongoose API v3.0.3Fork me on GitHub
  • index.js

    Mongoose()

    Mongoose constructor.

    show code
    function Mongoose () {
    -  this.connections = [];
    -  this.plugins = [];
    -  this.models = {};
    -  this.modelSchemas = {};
    -  this.options = {};
    -  this.createConnection(); // default connection
    -};

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.


    Mongoose#set(key, value)

    Sets mongoose options

    show code
    Mongoose.prototype.set = function (key, value) {
    -  if (arguments.length == 1)
    -    return this.options[key];
    -  this.options[key] = value;
    -  return this;
    -};

    Parameters:

    Example:

    - -
    mongoose.set('test', value) // sets the 'test' option to `value`

    Mongoose#get(key)

    Gets mongoose options

    Parameters:

    Example:

    - -
    mongoose.get('test') // returns the 'test' value

    Mongoose#createConnection([uri])

    Creates a Connection instance.

    show code
    Mongoose.prototype.createConnection = function () {
    -  var conn = new Connection(this);
    -  this.connections.push(conn);
    -
    -  if (arguments.length) {
    -    if (rgxReplSet.test(arguments[0])) {
    -      conn.openSet.apply(conn, arguments);
    -    } else {
    -      conn.open.apply(conn, arguments);
    -    }
    -  }
    -
    -  return conn;
    -};

    Parameters:

    • [uri] <String> a mongodb:// URI

    Returns:

    Example:

    - -
    // with mongodb:// URI
    -db = mongoose.createConnection('mongodb://localhost:port/database');
    -
    -// replica sets
    -db = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
    -
    -// with [host, database_name[, port] signature
    -db = mongoose.createConnection('localhost', 'database', port)
    -
    -// initialize now, connect later
    -db = mongoose.createConnection();
    -db.open('localhost', 'database', port);

    Mongoose#connect()

    Opens the default mongoose connection.

    show code
    Mongoose.prototype.connect = function () {
    -  var conn = this.connection;
    -
    -  if (rgxReplSet.test(arguments[0])) {
    -    conn.openSet.apply(conn, arguments);
    -  } else {
    -    conn.open.apply(conn, arguments);
    -  }
    -
    -  return this;
    -};

    Returns:

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


    Mongoose#disconnect([fn])

    Disconnects all connections.

    show code
    Mongoose.prototype.disconnect = function (fn) {
    -  var count = this.connections.length
    -    , error
    -
    -  this.connections.forEach(function(conn){
    -    conn.close(function(err){
    -      if (error) return;
    -
    -      if (err) {
    -        error = err;
    -        if (fn) return fn(err);
    -        throw err;
    -      }
    -
    -      if (fn)
    -        --count || fn();
    -    });
    -  });
    -  return this;
    -};

    Parameters:

    • [fn] <Function> called after all connection close.

    Returns:


    Mongoose#model(name, [schema], [collection], [skipInit])

    Defines a model or retrieves it.

    show code
    Mongoose.prototype.model = function (name, schema, collection, skipInit) {
    -  // normalize collection
    -  if (!(schema instanceof Schema)) {
    -    collection = schema;
    -    schema = false;
    -  }
    -
    -  if ('boolean' === typeof collection) {
    -    skipInit = collection;
    -    collection = null;
    -  }
    -
    -  // look up models for the collection
    -  if (!this.modelSchemas[name]) {
    -    if (!schema && name in SchemaDefaults) {
    -      schema = SchemaDefaults[name];
    -    }
    -
    -    if (schema) {
    -      this.modelSchemas[name] = schema;
    -      for (var i = 0, l = this.plugins.length; i < l; i++) {
    -        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
    -      }
    -    } else {
    -      throw new Error('Schema hasn\'t been registered for model "' + name + '".
    -'
    -                    + 'Use mongoose.model(name, schema)');
    -    }
    -  }
    -
    -  if (!this.models[name]) {
    -    schema || (schema = this.modelSchemas[name]);
    -    collection || (collection = schema.set('collection') || format(name));
    -
    -    var model = Model.compile(name
    -                        , this.modelSchemas[name]
    -                        , collection
    -                        , this.connection
    -                        , this);
    -
    -    if (!skipInit) model.init();
    -
    -    this.models[name] = model;
    -  }
    -
    -  return this.models[name];
    -};

    Parameters:

    • name <String> model name
    • [schema] <Schema>
    • [collection] <String> name (optional, induced from model name)
    • [skipInit] <Boolean> whether to skip initialization (defaults to false)

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -
    -// define an Actor model with this mongoose instance
    -mongoose.model('Actor', new Schema({ name: String }));
    -
    -// create a new connection
    -var conn = mongoose.createConnection(..);
    -
    -// retrieve the Actor model
    -var Actor = conn.model('Actor');
    - -

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    - -

    Example:

    - -
    var schema = new Schema({ name: String });
    -schema.set('collection', 'actor');

    Mongoose#plugin(fn, [opts])

    Declares a global plugin executed on all Schemas.

    show code
    Mongoose.prototype.plugin = function (fn, opts) {
    -  this.plugins.push([fn, opts]);
    -  return this;
    -};

    Parameters:

    Returns:

    Equivalent to calling .plugin(fn) on each Schema you create.


    module.exports

    The exports object is an instance of Mongoose.

    show code
    module.exports = exports = new Mongoose;
    -var mongoose = module.exports;

    mongoose.Collection

    The Mongoose Collection constructor

    show code
    mongoose.Collection = Collection;

    mongoose.Connection

    The Mongoose Connection constructor

    show code
    mongoose.Connection = Connection;

    mongoose.version

    Mongoose version

    show code
    mongoose.version = JSON.parse(
    -  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
    -).version;

    mongoose.Mongoose

    The Mongoose constructor

    show code
    mongoose.Mongoose = Mongoose;

    The exports of the mongoose module is an instance of this class.

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -var mongoose2 = new mongoose.Mongoose();

    mongoose.Schema

    The Mongoose Schema constructor

    show code
    mongoose.Schema = Schema;

    Example:

    - -
    var mongoose = require('mongoose');
    -var Schema = mongoose.Schema;
    -var CatSchema = new Schema(..);

    mongoose.SchemaType

    The Mongoose SchemaType constructor.

    show code
    mongoose.SchemaType = SchemaType;

    mongoose.SchemaTypes

    The various Mongoose SchemaTypes.

    show code
    mongoose.SchemaTypes = Schema.Types;

    Note:

    - -

    Alias of mongoose.Schema.Types for backwards compatibility.


    mongoose.VirtualType

    The Mongoose VirtualType constructor.

    show code
    mongoose.VirtualType = VirtualType;

    mongoose.Types

    The various Mongoose Types.

    show code
    mongoose.Types = Types;

    Example:

    - -
    var mongoose = require('mongoose');
    -var array = mongoose.Types.Array;
    - -

    Types:

    - -
      -
    • Array
    • -
    • Buffer
    • -
    • Document
    • -
    • Embedded
    • -
    • DocumentArray
    • -
    • ObjectId
    • -
    - -

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    - -
    var ObjectId = mongoose.Types.ObjectId;
    -var id1 = new ObjectId;

    mongoose.Query

    The Mongoose Query constructor.

    show code
    mongoose.Query = Query;

    mongoose.Promise

    The Mongoose Promise constructor.

    show code
    mongoose.Promise = Promise;

    mongoose.Model

    The Mongoose Model constructor.

    show code
    mongoose.Model = Model;

    mongoose.Document

    The Mongoose Document constructor.

    show code
    mongoose.Document = Document;

    mongoose.Error

    The MongooseError constructor.

    show code
    mongoose.Error = require('./error');

    mongoose.mongo

    The node-mongodb-native driver Mongoose uses.

    show code
    mongoose.mongo = require('mongodb');

    Mongoose#connection

    The default connection of the mongoose module.

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -mongoose.connect(...);
    -mongoose.connection.on('error', cb);
    - -

    This is the connection used by default for every model created using mongoose.model.

    Returns:


  • collection.js

    Collection(name, conn, opts)

    Abstract Collection constructor

    show code
    function Collection (name, conn, opts) {
    -  this.name = name;
    -  this.conn = conn;
    -  this.buffer = true;
    -  this.queue = [];
    -
    -  if ('number' == typeof opts) opts = { size: opts };
    -  this.opts = opts || {};
    -
    -  if (STATES.connected == this.conn.readyState) {
    -    this.onOpen();
    -  }
    -};

    Parameters:

    • name <String> name of the collection
    • conn <Connection> A MongooseConnection instance
    • opts <Object> optional collection options

    This is the base class that drivers inherit from and implement.


    Collection#onOpen()

    Called when the database connects

    show code
    Collection.prototype.onOpen = function () {
    -  var self = this;
    -  this.buffer = false;
    -  self.doQueue();
    -};

    Collection#onClose()

    Called when the database disconnects

    show code
    Collection.prototype.onClose = function () {
    -  this.buffer = true;
    -};

    Collection#addQueue(name, args)

    Queues a method for later execution when its
    database connection opens.

    show code
    Collection.prototype.addQueue = function (name, args) {
    -  this.queue.push([name, args]);
    -  return this;
    -};

    Parameters:

    • name <String> name of the method to queue
    • args <Array> arguments to pass to the method when executed

    Collection#doQueue()

    Executes all queued methods and clears the queue.

    show code
    Collection.prototype.doQueue = function () {
    -  for (var i = 0, l = this.queue.length; i < l; i++){
    -    this[this.queue[i][0]].apply(this, this.queue[i][1]);
    -  }
    -  this.queue = [];
    -  return this;
    -};

    Collection#ensureIndex()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.ensureIndex = function(){
    -  throw new Error('Collection#ensureIndex unimplemented by driver');
    -};

    Collection#findAndModify()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findAndModify = function(){
    -  throw new Error('Collection#findAndModify unimplemented by driver');
    -};

    Collection#findOne()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findOne = function(){
    -  throw new Error('Collection#findOne unimplemented by driver');
    -};

    Collection#find()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.find = function(){
    -  throw new Error('Collection#find unimplemented by driver');
    -};

    Collection#insert()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.insert = function(){
    -  throw new Error('Collection#insert unimplemented by driver');
    -};

    Collection#save()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.save = function(){
    -  throw new Error('Collection#save unimplemented by driver');
    -};

    Collection#update()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.update = function(){
    -  throw new Error('Collection#update unimplemented by driver');
    -};

    Collection#getIndexes()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.getIndexes = function(){
    -  throw new Error('Collection#getIndexes unimplemented by driver');
    -};

    Collection#mapReduce()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.mapReduce = function(){
    -  throw new Error('Collection#mapReduce unimplemented by driver');
    -};

    Collection#conn

    The Connection instance


    Collection#name

    The collection name


  • connection.js

    Connection(base)

    Connection constructor

    show code
    function Connection (base) {
    -  this.base = base;
    -  this.collections = {};
    -  this.models = {};
    -  this.replica = false;
    -  this.host = null;
    -  this.port = null;
    -  this.user = null;
    -  this.pass = null;
    -  this.name = null;
    -  this.options = null;
    -  this._readyState = STATES.disconnected;
    -  this._closeCalled = false;
    -  this._hasOpened = false;
    -};

    Parameters:

    Events:

    • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

    • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

    • open: Emitted after we connected and onOpen is executed on all of this connections models.

    • disconnecting: Emitted when connection.close() was executed.

    • disconnected: Emitted after getting disconnected from the db.

    • close: Emitted after we disconnected and onClose executed on all of this connections models.

    • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

    • error: Emitted when an error occurs on this connection.

    • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

    For practical reasons, a Connection equals a Db.


    Connection#open(connection_string, [database], [port], [options], [callback])

    Opens the connection to MongoDB.

    show code
    Connection.prototype.open = function (host, database, port, options, callback) {
    -  var self = this
    -    , uri;
    -
    -  if ('string' === typeof database) {
    -    switch (arguments.length) {
    -      case 2:
    -        port = 27017;
    -      case 3:
    -        switch (typeof port) {
    -          case 'function':
    -            callback = port, port = 27017;
    -            break;
    -          case 'object':
    -            options = port, port = 27017;
    -            break;
    -        }
    -        break;
    -      case 4:
    -        if ('function' === typeof options)
    -          callback = options, options = {};
    -    }
    -  } else {
    -    switch (typeof database) {
    -      case 'function':
    -        callback = database, database = undefined;
    -        break;
    -      case 'object':
    -        options = database;
    -        database = undefined;
    -        callback = port;
    -        break;
    -    }
    -
    -    if (!rgxProtocol.test(host)) {
    -      host = 'mongodb://' + host;
    -    }
    -
    -    uri = url.parse(host);
    -    host = uri.hostname;
    -    port = uri.port || 27017;
    -    database = uri.pathname && uri.pathname.replace(/\//g, '');
    -  }
    -
    -  this.options = this.defaultOptions(options);
    -
    -  // make sure we can open
    -  if (STATES.disconnected !== this.readyState) {
    -    var err = new Error('Trying to open unclosed connection.');
    -    err.state = this.readyState;
    -    this.error(err, callback);
    -    return this;
    -  }
    -
    -  if (!host) {
    -    this.error(new Error('Missing connection hostname.'), callback);
    -    return this;
    -  }
    -
    -  if (!database) {
    -    this.error(new Error('Missing connection database.'), callback);
    -    return this;
    -  }
    -
    -  // handle authentication
    -  if (uri && uri.auth) {
    -    var auth = uri.auth.split(':');
    -    this.user = auth[0];
    -    this.pass = auth[1];
    -
    -  // Check hostname for user/pass
    -  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
    -    host = host.split('@');
    -    var auth = host.shift().split(':');
    -    host = host.pop();
    -    this.user = auth[0];
    -    this.pass = auth[1];
    -
    -  // user/pass options
    -  } else if (options && options.user && options.pass) {
    -    this.user = options.user;
    -    this.pass = options.pass;
    -
    -  } else {
    -    this.user = this.pass = undefined;
    -  }
    -
    -  this.name = database;
    -  this.host = host;
    -  this.port = port;
    -
    -  this._open(callback);
    -  return this;
    -};

    Parameters:

    • connection_string <String> mongodb://uri or the host to which you are connecting
    • [database] <String> database name
    • [port] <Number> database port
    • [options] <Object> options
    • [callback] <Function>

    options is a hash with the following possible properties:

    - -
    db      - passed to the connection db instance
    -server  - passed to the connection server instance(s)
    -replset - passed to the connection ReplSetServer instance
    -user    - username for authentication
    -pass    - password for authentication
    - -

    Notes:

    - -

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.


    Connection#openSet(uris, [database], [options], [callback])

    Connects to a replica set.

    show code
    Connection.prototype.openSet = function (uris, database, options, callback) {
    -  var uris = uris.split(',')
    -    , self = this;
    -
    -  switch (arguments.length) {
    -    case 3:
    -      this.name = database;
    -      if ('function' === typeof options) callback = options, options = {};
    -      break;
    -    case 2:
    -      switch (typeof database) {
    -        case 'string':
    -          this.name = database;
    -        case 'function':
    -          callback = database, database = null;
    -          break;
    -        case 'object':
    -          options = database, database = null;
    -          break;
    -      }
    -  }
    -
    -  this.options = options = this.defaultOptions(options);
    -
    -  if (uris.length < 2) {
    -    this.error(new Error('Please provide comma-separated URIs'), callback);
    -    return this;
    -  }
    -
    -  this.replica = true;
    -  this.host = [];
    -  this.port = [];
    -
    -  uris.forEach(function (uri) {
    -    // handle missing protocols
    -    if (!rgxProtocol.test(uri))
    -      uri = 'mongodb://' + uri;
    -
    -    var uri = url.parse(uri);
    -
    -    self.host.push(uri.hostname);
    -    self.port.push(uri.port || 27017);
    -
    -    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
    -      self.name = uri.pathname.replace(/\//g, '');
    -
    -    if (!self.user && uri.auth) {
    -      var auth = uri.auth.split(':');
    -      self.user = auth[0];
    -      self.pass = auth[1];
    -    }
    -  });
    -
    -  if (!this.name) {
    -    this.error(new Error('No database name provided for replica set'), callback);
    -    return this;
    -  }
    -
    -  this._open(callback);
    -  return this;
    -};

    Parameters:

    • uris <String> comma-separated mongodb:// `URI`s
    • [database] <String> database name if not included in `uris`
    • [options] <Object> passed to the internal driver
    • [callback] <Function>

    Example:

    - -
    var db = mongoose.createConnection();
    -db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
    - -

    The database name and/or auth need only be included in one URI.
    The options are passed to the internal driver connection object.


    Connection#error(err, callback)

    error

    show code
    Connection.prototype.error = function (err, callback) {
    -  if (callback) return callback(err);
    -  this.emit('error', err);
    -}

    Parameters:

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.


    Connection#_open(callback)

    Handles opening the connection with the appropriate method based on connection type.

    show code
    Connection.prototype._open = function (callback) {
    -  this.readyState = STATES.connecting;
    -  this._closeCalled = false;
    -
    -  var self = this;
    -
    -  var method = this.replica
    -    ? 'doOpenSet'
    -    : 'doOpen';
    -
    -  // open connection
    -  this[method](function (err) {
    -    if (err) {
    -      self.readyState = STATES.disconnected;
    -      if (self._hasOpened) {
    -        if (callback) callback(err);
    -      } else {
    -        self.error(err, callback);
    -      }
    -      return;
    -    }
    -
    -    self.onOpen();
    -    callback && callback();
    -  });
    -}

    Parameters:


    Connection#onOpen()

    Called when the connection is opened

    show code
    Connection.prototype.onOpen = function () {
    -  var self = this;
    -
    -  function open () {
    -    self.readyState = STATES.connected;
    -
    -    // avoid having the collection subscribe to our event emitter
    -    // to prevent 0.3 warning
    -    for (var i in self.collections)
    -      self.collections[i].onOpen();
    -
    -    self.emit('open');
    -  };
    -
    -  // re-authenticate
    -  if (self.user && self.pass)
    -    self.db.authenticate(self.user, self.pass, open);
    -  else
    -    open();
    -};

    Connection#close([callback])

    Closes the connection

    show code
    Connection.prototype.close = function (callback) {
    -  var self = this;
    -  this._closeCalled = true;
    -
    -  switch (this.readyState){
    -    case 0: // disconnected
    -      callback && callback();
    -      break;
    -
    -    case 1: // connected
    -      this.readyState = STATES.disconnecting;
    -      this.doClose(function(err){
    -        if (err){
    -          self.error(err, callback);
    -        } else {
    -          self.onClose();
    -          callback && callback();
    -        }
    -      });
    -      break;
    -
    -    case 2: // connecting
    -      this.once('open', function(){
    -        self.close(callback);
    -      });
    -      break;
    -
    -    case 3: // disconnecting
    -      if (!callback) break;
    -      this.once('close', function () {
    -        callback();
    -      });
    -      break;
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Connection#onClose()

    Called when the connection closes

    show code
    Connection.prototype.onClose = function () {
    -  this.readyState = STATES.disconnected;
    -
    -  // avoid having the collection subscribe to our event emitter
    -  // to prevent 0.3 warning
    -  for (var i in this.collections)
    -    this.collections[i].onClose();
    -
    -  this.emit('close');
    -};

    Connection#collection(name, [options])

    Retrieves a collection, creating it if not cached.

    show code
    Connection.prototype.collection = function (name, options) {
    -  if (!(name in this.collections))
    -    this.collections[name] = new Collection(name, this, options);
    -  return this.collections[name];
    -};

    Parameters:

    • name <String> of the collection
    • [options] <Object> optional collection options

    Returns:


    Connection#model(name, [schema], [collection])

    Defines or retrieves a model.

    show code
    Connection.prototype.model = function (name, schema, collection) {
    -  if (!this.models[name]) {
    -    var model = this.base.model(name, schema, collection, true)
    -      , Model
    -
    -    if (this != model.prototype.db) {
    -      // subclass model using this connection and collection name
    -      Model = function Model (doc, fields, skipId) {
    -        if (!(this instanceof Model))
    -          return new Model(doc, fields, skipId);
    -        model.call(this, doc, fields, skipId);
    -      };
    -
    -      Model.__proto__ = model;
    -      Model.prototype.__proto__ = model.prototype;
    -      Model.db = Model.prototype.db = this;
    -
    -      // collection name discovery
    -      if ('string' === typeof schema) {
    -        collection = schema;
    -      }
    -
    -      if (!collection) {
    -        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
    -      }
    -
    -      var s = 'string' != typeof schema
    -        ? schema
    -        : model.prototype.schema;
    -
    -      Model.prototype.collection = this.collection(collection, s && s.options.capped);
    -      Model.collection = Model.prototype.collection;
    -      Model.init();
    -    }
    -
    -    this.models[name] = Model || model;
    -  }
    -
    -  return this.models[name];
    -};

    Parameters:

    • name <String> the model name
    • [schema] <Schema> a schema. necessary when defining a model
    • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

    Returns:

    • <Model> The compiled model
    var mongoose = require('mongoose');
    -var db = mongoose.createConnection(..);
    -db.model('Venue', new Schema(..));
    -var Ticket = db.model('Ticket', new Schema(..));
    -var Venue = db.model('Venue');

    Connection#setProfiling(level, [ms], callback)

    Set profiling level.

    show code
    Connection.prototype.setProfiling = function (level, ms, callback) {
    -  if (STATES.connected !== this.readyState) {
    -    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
    -  }
    -
    -  if (!callback) callback = ms, ms = 100;
    -
    -  var cmd = {};
    -
    -  switch (level) {
    -    case 0:
    -    case 'off':
    -      cmd.profile = 0;
    -      break;
    -    case 1:
    -    case 'slow':
    -      cmd.profile = 1;
    -      if ('number' !== typeof ms) {
    -        ms = parseInt(ms, 10);
    -        if (isNaN(ms)) ms = 100;
    -      }
    -      cmd.slowms = ms;
    -      break;
    -    case 2:
    -    case 'all':
    -      cmd.profile = 2;
    -      break;
    -    default:
    -      return callback(new Error('Invalid profiling level: '+ level));
    -  }
    -
    -  this.db.executeDbCommand(cmd, function (err, resp) {
    -    if (err) return callback(err);
    -
    -    var doc = resp.documents[0];
    -
    -    err = 1 === doc.ok
    -      ? null
    -      : new Error('Could not set profiling level to: '+ level)
    -
    -    callback(err, doc);
    -  });
    -};

    Parameters:

    • level <Number, String> either off (0), slow (1), or all (2)
    • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
    • callback <Function>

    Connection#defaultOptions(options)

    Prepares default connection options.

    show code
    Connection.prototype.defaultOptions = function (options) {
    -  var o = options || {};
    -
    -  o.server = o.server || {};
    -
    -  if (!('auto_reconnect' in o.server)) {
    -    o.server.auto_reconnect = true;
    -  }
    -
    -  o.db = o.db || {};
    -  o.db.forceServerObjectId = false;
    -
    -  return o;
    -}

    Parameters:


    Connection#db

    The mongodb.Db instance, set when the connection is opened


    Connection#collections

    A hash of the collections associated with this connection


    Connection#readyState

    Connection ready state

    - -
      -
    • 0 = disconnected
    • -
    • 1 = connected
    • -
    • 2 = connecting
    • -
    • 3 = disconnecting
    • -
    - -

    Each state change emits its associated event name.

    - -

    Example

    - -
    conn.on('connected', callback);
    -conn.on('disconnected', callback);

  • document.js

    Document(obj, [fields], [skipId])

    Document constructor.

    show code
    function Document (obj, fields, skipId) {
    -  // node <0.4.3 bug
    -  if (!this._events) this._events = {};
    -  this.setMaxListeners(0);
    -
    -  if ('boolean' === typeof fields) {
    -    this._strictMode = fields;
    -    this._selected = fields = undefined;
    -  } else {
    -    this._strictMode = this.schema.options && this.schema.options.strict;
    -    this._selected = fields;
    -  }
    -
    -  this.isNew = true;
    -  this.errors = undefined;
    -  this._shardval = undefined;
    -  this._saveError = undefined;
    -  this._validationError = undefined;
    -  this._adhocPaths = undefined;
    -  this._removing = undefined;
    -  this._inserting = undefined;
    -  this.__version = undefined;
    -  this.__getters = {};
    -  this.__id = undefined;
    -
    -  this._activePaths = new ActiveRoster;
    -
    -  var required = this.schema.requiredPaths();
    -  for (var i = 0; i < required.length; ++i) {
    -    this._activePaths.require(required[i]);
    -  }
    -
    -  this._doc = this._buildDoc(obj, fields, skipId);
    -  if (obj) this.set(obj, undefined, true);
    -  this._registerHooks();
    -};

    Parameters:

    • obj <Object> the values to set
    • [fields] <Object> the fields which were selected in the query returning this document
    • [skipId] <Boolean> bool, should we auto create an ObjectId _id

    Events:

    • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

    • save: Emitted when the document is successfully saved


    Document#_buildDoc(obj, [fields], [skipId])

    Builds the default doc structure

    show code
    Document.prototype._buildDoc = function (obj, fields, skipId) {
    -  var doc = {}
    -    , self = this
    -    , exclude
    -    , keys
    -    , key
    -    , ki
    -
    -  // determine if this doc is a result of a query with
    -  // excluded fields
    -  if (fields && 'Object' === fields.constructor.name) {
    -    keys = Object.keys(fields);
    -    ki = keys.length;
    -
    -    while (ki--) {
    -      if ('_id' !== keys[ki]) {
    -        exclude = 0 === fields[keys[ki]];
    -        break;
    -      }
    -    }
    -  }
    -
    -  var paths = Object.keys(this.schema.paths)
    -    , plen = paths.length
    -    , ii = 0
    -
    -  for (; ii < plen; ++ii) {
    -    var p = paths[ii];
    -
    -    if ('_id' == p) {
    -      if (skipId) continue;
    -      if (obj && '_id' in obj) continue;
    -    }
    -
    -    var type = this.schema.paths[p]
    -      , path = p.split('.')
    -      , len = path.length
    -      , last = len-1
    -      , doc_ = doc
    -      , i = 0
    -
    -    for (; i < len; ++i) {
    -      var piece = path[i]
    -        , def
    -
    -      if (i === last) {
    -        if (fields) {
    -          if (exclude) {
    -            // apply defaults to all non-excluded fields
    -            if (p in fields) continue;
    -
    -            def = type.getDefault(self, true);
    -            if ('undefined' !== typeof def) {
    -              doc_[piece] = def;
    -              self._activePaths.default(p);
    -            }
    -
    -          } else if (p in fields) {
    -            // selected field
    -            def = type.getDefault(self, true);
    -            if ('undefined' !== typeof def) {
    -              doc_[piece] = def;
    -              self._activePaths.default(p);
    -            }
    -          }
    -        } else {
    -          def = type.getDefault(self, true);
    -          if ('undefined' !== typeof def) {
    -            doc_[piece] = def;
    -            self._activePaths.default(p);
    -          }
    -        }
    -      } else {
    -        doc_ = doc_[piece] || (doc_[piece] = {});
    -      }
    -    }
    -  };
    -
    -  return doc;
    -};

    Parameters:

    Returns:


    Document#init(doc, fn)

    Initializes the document without setters or marking anything modified.

    show code
    Document.prototype.init = function (doc, fn) {
    -  this.isNew = false;
    -
    -  init(this, doc, this._doc);
    -  this._storeShard();
    -
    -  this.emit('init');
    -  if (fn) fn(null);
    -  return this;
    -};

    Parameters:

    Called internally after a document is returned from mongodb.


    Document#_storeShard()

    Stores the current values of the shard keys.

    show code
    Document.prototype._storeShard = function _storeShard () {
    -  // backwards compat
    -  var key = this.schema.options.shardKey || this.schema.options.shardkey;
    -  if (!(key && 'Object' == key.constructor.name)) return;
    -
    -  var orig = this._shardval = {}
    -    , paths = Object.keys(key)
    -    , len = paths.length
    -    , val
    -
    -  for (var i = 0; i < len; ++i) {
    -    val = this.getValue(paths[i]);
    -    if (isMongooseObject(val)) {
    -      orig[paths[i]] = val.toObject({ depopulate: true })
    -    } else if (null != val && val.valueOf) {
    -      orig[paths[i]] = val.valueOf();
    -    } else {
    -      orig[paths[i]] = val;
    -    }
    -  }
    -}

    Note:

    - -

    Shard key values do not / are not allowed to change.


    Document#update(doc, options, callback)

    Sends an update command with this document _id as the query selector.

    show code
    Document.prototype.update = function update () {
    -  var args = utils.args(arguments);
    -  args.unshift({_id: this._id});
    -  this.constructor.update.apply(this.constructor, args);
    -}

    Parameters:

    Returns:

    Example:

    - -
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
    - -

    Valid options:

    - -
      -
    • safe safe mode (defaults to value set in schema (true))
    • -
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • -

    Document#set(path, val, [type])

    Sets the value of a path, or many paths.

    show code
    Document.prototype.set = function (path, val, type) {
    -  var constructing = true === type
    -    , adhoc = type && true !== type
    -    , adhocs
    -
    -  if (adhoc) {
    -    adhocs = this._adhocPaths || (this._adhocPaths = {});
    -    adhocs[path] = Schema.interpretAsType(path, type);
    -  }
    -
    -  if ('string' !== typeof path) {
    -    // new Document({ key: val })
    -
    -    if (null === path || undefined === path) {
    -      var _ = path;
    -      path = val;
    -      val = _;
    -
    -    } else {
    -      var prefix = val
    -        ? val + '.'
    -        : '';
    -
    -      if (path instanceof Document) path = path._doc;
    -
    -      var keys = Object.keys(path)
    -        , i = keys.length
    -        , pathtype
    -        , key
    -
    -      while (i--) {
    -        key = keys[i];
    -        if (null != path[key] && 'Object' === path[key].constructor.name
    -          && !(this._path(prefix + key) instanceof MixedSchema)) {
    -          this.set(path[key], prefix + key, constructing);
    -        } else if (this._strictMode) {
    -          pathtype = this.schema.pathType(prefix + key);
    -          if ('real' === pathtype || 'virtual' === pathtype) {
    -            this.set(prefix + key, path[key], constructing);
    -          } else if ('throw' == this._strictMode) {
    -            throw new Error("Field `" + key + "` is not in schema.");
    -          }
    -        } else if (undefined !== path[key]) {
    -          this.set(prefix + key, path[key], constructing);
    -        }
    -      }
    -
    -      return this;
    -    }
    -  }
    -
    -  // ensure _strict is honored for obj props
    -  // docschema = new Schema({ path: { nest: 'string' }})
    -  // doc.set('path', obj);
    -  var pathType = this.schema.pathType(path);
    -  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
    -    this.set(val, path, constructing);
    -    return this;
    -  }
    -
    -  var schema;
    -  if ('adhocOrUndefined' == pathType && this._strictMode) {
    -    return this;
    -  } else if ('virtual' == pathType) {
    -    schema = this.schema.virtualpath(path);
    -    schema.applySetters(val, this);
    -    return this;
    -  } else {
    -    schema = this._path(path);
    -  }
    -
    -  var parts = path.split('.')
    -    , pathToMark
    -
    -  // When using the $set operator the path to the field must already exist.
    -  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
    -
    -  if (parts.length <= 1) {
    -    pathToMark = path;
    -  } else {
    -    for (var i = 0; i < parts.length; ++i) {
    -      var part = parts[i];
    -      var subpath = parts.slice(0, i).concat(part).join('.');
    -      if (this.isDirectModified(subpath) // earlier prefixes that are already
    -                                         // marked as dirty have precedence
    -          || this.get(subpath) === null) {
    -        pathToMark = subpath;
    -        break;
    -      }
    -    }
    -
    -    if (!pathToMark) pathToMark = path;
    -  }
    -
    -  if (!schema || null === val || undefined === val) {
    -    this._set(pathToMark, path, constructing, parts, schema, val);
    -    return this;
    -  }
    -
    -  var self = this;
    -
    -  // if this doc is being constructed we should not
    -  // trigger getters.
    -  var priorVal = constructing
    -    ? undefined
    -    : this.get(path);
    -
    -  var shouldSet = this.try(function(){
    -    val = schema.applySetters(val, self, false, priorVal);
    -  });
    -
    -  if (shouldSet) {
    -    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
    -  }
    -
    -  return this;
    -}

    Parameters:

    Example:

    - -
    // path, value
    -doc.set(path, value)
    -
    -// object
    -doc.set({
    -    path  : value
    -  , path2 : {
    -       path  : value
    -    }
    -})
    -
    -// only-the-fly cast to number
    -doc.set(path, value, Number)
    -
    -// only-the-fly cast to string
    -doc.set(path, value, String)

    Document#_set()

    Handles the actual setting of the value and marking the path modified if appropriate.

    show code
    Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {
    -  if (this.isNew) {
    -    this.markModified(pathToMark);
    -  } else {
    -
    -    priorVal || (priorVal = this.get(path));
    -
    -    if (!this.isDirectModified(pathToMark)) {
    -      if (undefined === val && !this.isSelected(path)) {
    -        // special case:
    -        // when a path is not selected in a query its initial
    -        // value will be undefined.
    -        this.markModified(pathToMark, priorVal);
    -      } else if (undefined === val && path in this._activePaths.states.default) {
    -        // do nothing
    -        // unsetting the default value which was never saved
    -      } else if (!deepEqual(val, priorVal)) {
    -        this.markModified(pathToMark, priorVal);
    -      } else if (!constructing &&
    -                 null != val &&
    -                 path in this._activePaths.states.default &&
    -                 deepEqual(val, schema.getDefault(this, constructing))) {
    -        // special case:
    -        // a path with a default was $unset on the server
    -        // and the user is setting it to the same value again
    -        this.markModified(pathToMark, priorVal);
    -      }
    -    }
    -  }
    -
    -  var obj = this._doc
    -    , i = 0
    -    , l = parts.length
    -
    -  for (; i < l; i++) {
    -    var next = i + 1
    -      , last = next === l;
    -
    -    if (last) {
    -      obj[parts[i]] = val;
    -    } else {
    -      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
    -        obj = obj[parts[i]];
    -      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
    -        obj = obj[parts[i]];
    -      } else {
    -        obj = obj[parts[i]] = {};
    -      }
    -    }
    -  }
    -};

    Document#getValue(path)

    Gets a raw value from a path (no getters)

    show code
    Document.prototype.getValue = function (path) {
    -  var parts = path.split('.')
    -    , obj = this._doc
    -    , part;
    -
    -  for (var i = 0, l = parts.length; i < l; i++) {
    -    part = parts[i];
    -    obj = obj.getValue
    -        ? obj.getValue(part) // If we have an embedded array document member
    -        : obj[part];
    -    if (!obj) return obj;
    -  }
    -
    -  return obj;
    -}

    Parameters:


    Document#setValue(path, value)

    Sets a raw value for a path (no casting, setters, transformations)

    show code
    Document.prototype.setValue = function (path, val) {
    -  var parts = path.split('.')
    -    , obj = this._doc;
    -
    -  for (var i = 0, len = parts.length-1; i < len; i++) {
    -    obj = obj[parts[i]];
    -  }
    -
    -  obj[parts[len]] = val;
    -  return this;
    -};

    Parameters:


    Document#get(path, [type])

    Returns the value of a path.

    show code
    Document.prototype.get = function (path, type) {
    -  var adhocs;
    -  if (type) {
    -    adhocs = this._adhocPaths || (this._adhocPaths = {});
    -    adhocs[path] = Schema.interpretAsType(path, type);
    -  }
    -
    -  var schema = this._path(path) || this.schema.virtualpath(path)
    -    , pieces = path.split('.')
    -    , obj = this._doc;
    -
    -  for (var i = 0, l = pieces.length; i < l; i++) {
    -    obj = null == obj ? null : obj[pieces[i]];
    -  }
    -
    -  if (schema) {
    -    obj = schema.applyGetters(obj, this);
    -  }
    -
    -  return obj;
    -};

    Parameters:

    Example

    - -
    // path
    -doc.get('age') // 47
    -
    -// dynamic casting to a string
    -doc.get('age', String) // "47"

    Document#_path(path)

    Returns the schematype for the given path.

    show code
    Document.prototype._path = function (path) {
    -  var adhocs = this._adhocPaths
    -    , adhocType = adhocs && adhocs[path];
    -
    -  if (adhocType) {
    -    return adhocType;
    -  } else {
    -    return this.schema.path(path);
    -  }
    -};

    Parameters:


    Document#markModified(path)

    Marks the path as having pending changes to write to the db.

    show code
    Document.prototype.markModified = function (path) {
    -  this._activePaths.modify(path);
    -};

    Parameters:

    • path <String> the path to mark modified

    Very helpful when using Mixed types.

    - -

    Example:

    - -
    doc.mixed.type = 'changed';
    -doc.markModified('mixed.type');
    -doc.save() // changes to mixed.type are now persisted

    Document#try(fn, scope)

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    show code
    Document.prototype.try = function (fn, scope) {
    -  var res;
    -  try {
    -    fn.call(scope);
    -    res = true;
    -  } catch (e) {
    -    this._error(e);
    -    res = false;
    -  }
    -  return res;
    -};

    Parameters:

    • fn <Function> function to execute
    • scope <Object> the scope with which to call fn

    Document#modifiedPaths()

    Returns the list of paths that have been modified.

    show code
    Document.prototype.modifiedPaths = function () {
    -  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
    -
    -  return directModifiedPaths.reduce(function (list, path) {
    -    var parts = path.split('.');
    -    return list.concat(parts.reduce(function (chains, part, i) {
    -      return chains.concat(parts.slice(0, i).concat(part).join('.'));
    -    }, []));
    -  }, []);
    -};

    Returns:


    Document#isModified([path])

    Returns true if this document was modified, else false.

    show code
    Document.prototype.isModified = function (path) {
    -  return path
    -    ? !!~this.modifiedPaths().indexOf(path)
    -    : this._activePaths.some('modify');
    -};

    Parameters:

    Returns:

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    - -

    Example

    - -
    doc.set('documents.0.title', 'changed');
    -doc.isModified()                    // true
    -doc.isModified('documents')         // true
    -doc.isModified('documents.0.title') // true
    -doc.isDirectModified('documents')   // false

    Document#isDirectModified(path)

    Returns true if path was directly set and modified, else false.

    show code
    Document.prototype.isDirectModified = function (path) {
    -  return (path in this._activePaths.states.modify);
    -};

    Parameters:

    Returns:

    Example

    - -
    doc.set('documents.0.title', 'changed');
    -doc.isDirectModified('documents.0.title') // true
    -doc.isDirectModified('documents') // false

    Document#isInit(path)

    Checks if path was initialized.

    show code
    Document.prototype.isInit = function (path) {
    -  return (path in this._activePaths.states.init);
    -};

    Parameters:

    Returns:


    Document#isSelected(path)

    Checks if path was selected in the source query which initialized this document.

    show code
    Document.prototype.isSelected = function isSelected (path) {
    -  if (this._selected) {
    -
    -    if ('_id' === path) {
    -      return 0 !== this._selected._id;
    -    }
    -
    -    var paths = Object.keys(this._selected)
    -      , i = paths.length
    -      , inclusive = false
    -      , cur
    -
    -    if (1 === i && '_id' === paths[0]) {
    -      // only _id was selected.
    -      return 0 === this._selected._id;
    -    }
    -
    -    while (i--) {
    -      cur = paths[i];
    -      if ('_id' == cur) continue;
    -      inclusive = !! this._selected[cur];
    -      break;
    -    }
    -
    -    if (path in this._selected) {
    -      return inclusive;
    -    }
    -
    -    i = paths.length;
    -    var pathDot = path + '.';
    -
    -    while (i--) {
    -      cur = paths[i];
    -      if ('_id' == cur) continue;
    -
    -      if (0 === cur.indexOf(pathDot)) {
    -        return inclusive;
    -      }
    -
    -      if (0 === pathDot.indexOf(cur)) {
    -        return inclusive;
    -      }
    -    }
    -
    -    return ! inclusive;
    -  }
    -
    -  return true;
    -}

    Parameters:

    Returns:

    Example

    - -
    Thing.findOne().select('name').exec(function (err, doc) {
    -   doc.isSelected('name') // true
    -   doc.isSelected('age')  // false
    -})

    Document#validate(cb)

    Executes registered validation rules for this document.

    show code
    Document.prototype.validate = function (cb) {
    -  var self = this
    -
    -  // only validate required fields when necessary
    -  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
    -    if (!self.isSelected(path) && !self.isModified(path)) return false;
    -    return true;
    -  });
    -
    -  paths = paths.concat(Object.keys(this._activePaths.states.init));
    -  paths = paths.concat(Object.keys(this._activePaths.states.modify));
    -
    -  if (0 === paths.length) {
    -    complete();
    -    return this;
    -  }
    -
    -  var validating = {}
    -    , total = 0;
    -
    -  paths.forEach(validatePath);
    -  return this;
    -
    -  function validatePath (path) {
    -    if (validating[path]) return;
    -
    -    validating[path] = true;
    -    total++;
    -
    -    process.nextTick(function(){
    -      var p = self.schema.path(path);
    -      if (!p) return --total || complete();
    -
    -      p.doValidate(self.getValue(path), function (err) {
    -        if (err) self.invalidate(path, err, true);
    -        --total || complete();
    -      }, self);
    -    });
    -  }
    -
    -  function complete () {
    -    var err = self._validationError;
    -    self._validationError = undefined;
    -    cb(err);
    -  }
    -};

    Parameters:

    • cb <Function> called after validation completes, passing an error if one occurred

    Note:

    - -

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    - -

    Example:

    - -
    doc.validate(function (err) {
    -  if (err) handleError(err);
    -  else // validation passed
    -});

    Document#invalidate(path, err)

    Marks a path as invalid, causing validation to fail.

    show code
    Document.prototype.invalidate = function (path, err) {
    -  if (!this._validationError) {
    -    this._validationError = new ValidationError(this);
    -  }
    -
    -  if (!err || 'string' === typeof err) {
    -    err = new ValidatorError(path, err);
    -  }
    -
    -  this._validationError.errors[path] = err;
    -}

    Parameters:

    • path <String> the field to invalidate
    • err <String, Error> the error which states the reason `path` was invalid

    Document#_reset()

    Resets the internal modified state of this document.

    show code
    Document.prototype._reset = function reset () {
    -  var self = this;
    -  DocumentArray || (DocumentArray = require('./types/documentarray'));
    -
    -  this._activePaths
    -  .map('init', 'modify', function (i) {
    -    return self.getValue(i);
    -  })
    -  .filter(function (val) {
    -    return (val && val instanceof DocumentArray && val.length);
    -  })
    -  .forEach(function (array) {
    -    array.forEach(function (doc) {
    -      doc._reset();
    -    });
    -  });
    -
    -  // clear atomics
    -  this._dirty().forEach(function (dirt) {
    -    var type = dirt.value;
    -    if (type && type._atomics) {
    -      type._atomics = {};
    -    }
    -  });
    -
    -  // Clear 'modify'('dirty') cache
    -  this._activePaths.clear('modify');
    -  this._validationError = undefined;
    -  this.errors = undefined;
    -  var self = this;
    -  this.schema.requiredPaths().forEach(function (path) {
    -    self._activePaths.require(path);
    -  });
    -
    -  return this;
    -}

    Returns:


    Document#_dirty()

    Returns this documents dirty paths / vals.

    show code
    Document.prototype._dirty = function _dirty () {
    -  var self = this;
    -
    -  var all = this._activePaths.map('modify', function (path) {
    -    return { path: path
    -           , value: self.getValue(path)
    -           , schema: self._path(path) };
    -  });
    -
    -  // Sort dirty paths in a flat hierarchy.
    -  all.sort(function (a, b) {
    -    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
    -  });
    -
    -  // Ignore "foo.a" if "foo" is dirty already.
    -  var minimal = []
    -    , lastPath
    -    , top;
    -
    -  all.forEach(function (item, i) {
    -    if (item.path.indexOf(lastPath) !== 0) {
    -      lastPath = item.path + '.';
    -      minimal.push(item);
    -      top = item;
    -    } else {
    -      if (!(item.value && top.value)) return;
    -
    -      // special case for top level MongooseArrays
    -      if (top.value._atomics && top.value.hasAtomics()) {
    -        // the `top` array itself and a sub path of `top` are being modified.
    -        // the only way to honor all of both modifications is through a $set
    -        // of entire array.
    -        top.value._atomics = {};
    -        top.value._atomics.$set = top.value;
    -      }
    -    }
    -  });
    -
    -  top = lastPath = null;
    -  return minimal;
    -}

    Document#_setSchema(schema)

    Assigns/compiles schema into this documents prototype.

    show code
    Document.prototype._setSchema = function (schema) {
    -  compile(schema.tree, this);
    -  this.schema = schema;
    -}

    Parameters:


    Document#_registerHooks()

    Register default hooks

    show code
    Document.prototype._registerHooks = function _registerHooks () {
    -  if (!this.save) return;
    -
    -  DocumentArray || (DocumentArray = require('./types/documentarray'));
    -
    -  this.pre('save', function (next) {
    -    // we keep the error semaphore to make sure we don't
    -    // call `save` unnecessarily (we only need 1 error)
    -    var subdocs = 0
    -      , error = false
    -      , self = this;
    -
    -    // check for DocumentArrays
    -    var arrays = this._activePaths
    -    .map('init', 'modify', function (i) {
    -      return self.getValue(i);
    -    })
    -    .filter(function (val) {
    -      return (val && val instanceof DocumentArray && val.length);
    -    });
    -
    -    if (!arrays.length)
    -      return next();
    -
    -    arrays.forEach(function (array) {
    -      subdocs += array.length;
    -      array.forEach(function (value) {
    -        if (error) return;
    -
    -        value.save(function (err) {
    -          if (error) return;
    -
    -          if (err) {
    -            error = true;
    -            self._validationError = undefined;
    -            return next(err);
    -          }
    -
    -          --subdocs || next();
    -        });
    -      });
    -    });
    -  }, function (err) {
    -    // emit on the Model if listening
    -    if (this.constructor.listeners('error').length) {
    -      this.constructor.emit('error', err);
    -    } else {
    -      // emit on the connection
    -      if (!this.db.listeners('error').length) {
    -        err.stack = 'No listeners detected, throwing. '
    -                  + 'Consider adding an error listener to your connection.
    -'
    -                  + err.stack
    -      }
    -      this.db.emit('error', err);
    -    }
    -  }).pre('save', function checkForExistingErrors (next) {
    -    // if any doc.set() calls failed
    -    if (this._saveError) {
    -      next(this._saveError);
    -      this._saveError = null;
    -    } else {
    -      next();
    -    }
    -  }).pre('save', function validation (next) {
    -    return this.validate(next);
    -  });
    -
    -  // add user defined queues
    -  this._doQueue();
    -};

    Document#_error(err)

    Registers an error

    show code
    Document.prototype._error = function (err) {
    -  this._saveError = err;
    -  return this;
    -};

    Parameters:


    Document#_doQueue()

    Executes methods queued from the Schema definition

    show code
    Document.prototype._doQueue = function () {
    -  var q = this.schema && this.schema.callQueue;
    -  if (q) {
    -    for (var i = 0, l = q.length; i < l; i++) {
    -      this[q[i][0]].apply(this, q[i][1]);
    -    }
    -  }
    -  return this;
    -};

    Document#toObject([options])

    Converts this document into a plain javascript object

    show code
    Document.prototype.toObject = function (options) {
    -  // When internally saving this document we always pass options,
    -  // bypassing the custom schema options.
    -  if (!(options && 'Object' == options.constructor.name)) {
    -    options = this.schema.options.toObject
    -      ? clone(this.schema.options.toObject)
    -      : {};
    -  }
    -
    -  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
    -
    -  var ret = clone(this._doc, options);
    -
    -  if (options.virtuals || options.getters && false !== options.virtuals) {
    -    applyGetters(this, ret, 'virtuals', options);
    -  }
    -
    -  if (options.getters) {
    -    applyGetters(this, ret, 'paths', options);
    -  }
    -
    -  return ret;
    -};

    Parameters:

    Returns:

    Options:

    - -
      -
    • getters apply all getters (path and virtual getters)
    • -
    • virtuals apply virtual getters (can override getters option)
    • -
    • minimize remove empty objects (defaults to true)
    • -
    - -

    Example of only applying path getters

    - -
    doc.toObject({ getters: true, virtuals: false })
    - -

    Example of only applying virtual getters

    - -
    doc.toObject({ virtuals: true })
    - -

    Example of applying both path and virtual getters

    - -
    doc.toObject({ getters: true })

    Document#toJSON(options)

    The return value of this method is used in calls to JSON.stringify(doc).

    show code
    Document.prototype.toJSON = function (options) {
    -  // check for object type since an array of documents
    -  // being stringified passes array indexes instead
    -  // of options objects. JSON.stringify([doc, doc])
    -  if (!(options && 'Object' == options.constructor.name)) {
    -    options = this.schema.options.toJSON
    -      ? clone(this.schema.options.toJSON)
    -      : {};
    -  }
    -  options.json = true;
    -  return this.toObject(options);
    -};

    Parameters:

    • options <Object> same options as Document#toObject

    Returns:


    Document#inspect()

    Helper for console.log

    show code
    Document.prototype.inspect = function (options) {
    -  var opts = options && 'Object' == options.constructor.name
    -    ? options
    -    : undefined
    -  return inspect(this.toObject(opts));
    -};

    Document#toString()

    Helper for console.log


    Document#equals(doc)

    Returns true if the Document stores the same data as doc.

    show code
    Document.prototype.equals = function (doc) {
    -  var tid = this.get('_id');
    -  var docid = doc.get('_id');
    -  return tid.equals
    -    ? tid.equals(docid)
    -    : tid === docid;
    -};

    Parameters:

    Returns:

    Documents are considered equal when they have matching _ids.


    Document#errors

    Hash containing current validation errors.


    Document#id

    The string version of this documents _id.

    - -

    Note:

    - -

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    - -
    new Schema({ name: String }, { id: false });

    Document#isNew

    Boolean flag specifying if the document is new.


    Document#schema

    The documents schema.


  • drivers/node-mongodb-native/collection.js

    NativeCollection()

    A node-mongodb-native collection implementation.

    show code
    function NativeCollection () {
    -  this.collection = null;
    -  MongooseCollection.apply(this, arguments);
    -}

    Inherits:

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


    NativeCollection#onOpen()

    Called when the connection opens.

    show code
    NativeCollection.prototype.onOpen = function () {
    -  var self = this;
    -
    -  if (this.collection) {
    -    return MongooseCollection.prototype.onOpen.call(self);
    -  }
    -
    -  if (!self.opts.size) {
    -    // non-capped
    -    return self.conn.db.collection(self.name, callback);
    -  }
    -
    -  // capped
    -  return self.conn.db.collection(self.name, function (err, c) {
    -    if (err) return callback(err);
    -
    -    // discover if this collection exists and if it is capped
    -    c.options(function (err, exists) {
    -      if (err) return callback(err);
    -
    -      if (exists) {
    -        if (exists.capped) {
    -          callback(null, c);
    -        } else {
    -          var msg = 'A non-capped collection exists with this name.
    -
    -'
    -                  + ' To use this collection as a capped collection, please '
    -                  + 'first convert it.
    -'
    -                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
    -          err = new Error(msg);
    -          callback(err);
    -        }
    -      } else {
    -        // create
    -        var opts = utils.clone(self.opts);
    -        opts.capped = true;
    -        self.conn.db.createCollection(self.name, opts, callback);
    -      }
    -    });
    -  });
    -
    -  function callback (err, collection) {
    -    if (err) {
    -      // likely a strict mode error
    -      self.conn.emit('error', err);
    -    } else {
    -      self.collection = collection;
    -      MongooseCollection.prototype.onOpen.call(self);
    -    }
    -  };
    -};

    NativeCollection#onClose()

    Called when the connection closes

    show code
    NativeCollection.prototype.onClose = function () {
    -  MongooseCollection.prototype.onClose.call(this);
    -};

    NativeCollection#getIndexes(callback)

    Retreives information about this collections indexes.

    Parameters:


  • drivers/node-mongodb-native/connection.js

    NativeConnection()

    A node-mongodb-native connection implementation.

    show code
    function NativeConnection() {
    -  MongooseConnection.apply(this, arguments);
    -};

    Inherits:


    NativeConnection#doOpen(fn)

    Opens the connection to MongoDB.

    show code
    NativeConnection.prototype.doOpen = function (fn) {
    -  var server
    -    , self = this;
    -
    -  if (!this.db) {
    -    server = new mongo.Server(this.host, Number(this.port), this.options.server);
    -    this.db = new mongo.Db(this.name, server, this.options.db);
    -  }
    -
    -  this.db.open(function (err) {
    -    if (err) return fn(err);
    -    fn();
    -    listen(self);
    -  });
    -
    -  return this;
    -};
    -
    -function listen (conn) {
    -  if (conn._listening) return;
    -  conn._listening = true;
    -
    -  conn.db.on('close', function(){
    -    if (conn._closeCalled) return;
    -
    -    // the driver never emits an `open` event. auto_reconnect still
    -    // emits a `close` event but since we never get another
    -    // `open` we can't emit close
    -    if (conn.db.serverConfig.autoReconnect) {
    -      conn.readyState = STATES.disconnected;
    -      conn.emit('close');
    -      return;
    -    }
    -    conn.onClose();
    -  });
    -  conn.db.on('error', function(err){
    -    conn.emit('error', err);
    -  });
    -  conn.db.on('timeout', function(err){
    -    var error = new Error(err && err.err || 'connection timeout');
    -    conn.emit('error', error);
    -  });
    -  conn.db.on('open', function (err, db) {
    -    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
    -      conn.readyState = STATES.connected;
    -      conn.emit('reconnected')
    -    }
    -  })
    -}

    Parameters:

    Returns:


    NativeConnection#doOpenSet(fn)

    Opens a connection to a MongoDB ReplicaSet.

    show code
    NativeConnection.prototype.doOpenSet = function (fn) {
    -  if (!this.db) {
    -    var servers = []
    -      , ports = this.port
    -      , self = this
    -
    -    this.host.forEach(function (host, i) {
    -      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
    -    });
    -
    -    var server = new ReplSetServers(servers, this.options.replset);
    -    this.db = new mongo.Db(this.name, server, this.options.db);
    -
    -    this.db.on('fullsetup', function () {
    -      self.emit('fullsetup')
    -    });
    -  }
    -
    -  this.db.open(function (err) {
    -    if (err) return fn(err);
    -    fn();
    -    listen(self);
    -  });
    -
    -  return this;
    -};

    Parameters:

    Returns:

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


    NativeConnection#doClose(fn)

    Closes the connection

    show code
    NativeConnection.prototype.doClose = function (fn) {
    -  this.db.close();
    -  if (fn) fn();
    -  return this;
    -}

    Parameters:

    Returns:


  • error.js

    MongooseError()

    Mongoose error

    show code
    function MongooseError (msg) {
    -  Error.call(this);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.message = msg;
    -  this.name = 'MongooseError';
    -};

    Inherits:


  • errors/cast.js

    CastError(type, value)

    Casting Error constructor.

    show code
    function CastError (type, value) {
    -  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'CastError';
    -  this.type = type;
    -  this.value = value;
    -};

    Parameters:

    Inherits:


  • errors/document.js

    DocumentError(msg)

    Document Error

    show code
    function DocumentError (msg) {
    -  MongooseError.call(this, msg);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'DocumentError';
    -};

    Parameters:

    Inherits:


  • errors/validation.js

    ValidationError(instance)

    Document Validation Error

    show code
    function ValidationError (instance) {
    -  MongooseError.call(this, "Validation failed");
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'ValidationError';
    -  this.errors = instance.errors = {};
    -};

    Parameters:

    Inherits:


    ValidationError#toString()

    Console.log helper

    show code
    ValidationError.prototype.toString = function () {
    -  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
    -    return String(this.errors[key]);
    -  }, this).join(', ');
    -};

  • errors/validator.js

    ValidatorError(path, msg)

    Schema validator error

    show code
    function ValidatorError (path, type) {
    -  var msg = type
    -    ? '"' + type + '" '
    -    : '';
    -  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'ValidatorError';
    -  this.path = path;
    -  this.type = type;
    -};

    Parameters:

    Inherits:


  • model.js

    Model(doc)

    Model constructor

    show code
    function Model (doc, fields, skipId) {
    -  Document.call(this, doc, fields, skipId);
    -};

    Parameters:

    • doc <Object> values to with which to create the document

    Inherits:

    Events:

    • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

    • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


    Model#_getPopulationKeys(query)

    Returns what paths can be populated

    show code
    Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
    -  if (!(query && query.options.populate)) return;
    -
    -  var names = Object.keys(query.options.populate)
    -    , n = names.length
    -    , name
    -    , paths = {}
    -    , hasKeys
    -    , schema
    -
    -  while (n--) {
    -    name = names[n];
    -    schema = this.schema.path(name);
    -    hasKeys = true;
    -
    -    if (!schema) {
    -      // if the path is not recognized, it's potentially embedded docs
    -      // walk path atoms from right to left to find a matching path
    -      var pieces = name.split('.')
    -        , i = pieces.length;
    -
    -      while (i--) {
    -        var path = pieces.slice(0, i).join('.')
    -          , pathSchema = this.schema.path(path);
    -
    -        // loop until we find an array schema
    -        if (pathSchema && pathSchema.caster) {
    -          if (!paths[path]) {
    -            paths[path] = { sub: {} };
    -          }
    -
    -          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
    -          hasKeys || (hasKeys = true);
    -          break;
    -        }
    -      }
    -    } else {
    -      paths[name] = query.options.populate[name];
    -      hasKeys || (hasKeys = true);
    -    }
    -  }
    -
    -  return hasKeys && paths;
    -};

    Parameters:

    Returns:


    Model#_populate(schema, oid, query, fn)

    Populates an object

    show code
    Model.prototype._populate = function populate (schema, oid, query, fn) {
    -  if (!Array.isArray(oid)) {
    -    var conditions = query.conditions || {};
    -    conditions._id = oid;
    -
    -    return this
    -    .db.model(query.model || schema.options.ref)
    -    .findOne(conditions, query.fields, query.options, fn);
    -  }
    -
    -  if (!oid.length) {
    -    return fn(null, oid);
    -  }
    -
    -  var model = this.db.model(query.model || schema.caster.options.ref)
    -    , conditions = query && query.conditions || {};
    -
    -  conditions._id || (conditions._id = { $in: oid });
    -
    -  model.find(conditions, query.fields, query.options, function (err, docs) {
    -    if (err) return fn(err);
    -
    -    // user specified sort order?
    -    if (query.options && query.options.sort) {
    -      return fn(null, docs);
    -    }
    -
    -    // put back in original id order (using a hash reduces complexity from n*n to 2n)
    -    var docHash = {};
    -    docs.forEach(function (doc) {
    -      docHash[doc._id] = doc;
    -    });
    -
    -    var arr = [];
    -    oid.forEach(function (id) {
    -      if (id in docHash) arr.push(docHash[id]);
    -    });
    -
    -    fn(null, arr);
    -  });
    -};

    Parameters:

    • schema <SchemaType> type for the oid
    • oid <Object> object id or array of object ids
    • query <Object> object specifying query conditions, fields, and options
    • fn <Function>

    Model#init(doc, query, fn)

    Performs auto-population of relations.

    show code
    Model.prototype.init = function init (doc, query, fn) {
    -  if ('function' == typeof query) {
    -    fn = query;
    -    query = null;
    -  }
    -
    -  var populate = this._getPopulationKeys(query);
    -
    -  if (!populate) {
    -    return Document.prototype.init.call(this, doc, fn);
    -  }
    -
    -  // population from other models is necessary
    -  var self = this;
    -
    -  init(doc, '', function (err) {
    -    if (err) return fn(err);
    -    Document.prototype.init.call(self, doc, fn);
    -  });
    -
    -  return this;
    -
    -  function init (obj, prefix, fn) {
    -    prefix = prefix || '';
    -
    -    var keys = Object.keys(obj)
    -      , len = keys.length;
    -
    -    return next();
    -
    -    function next () {
    -      if (--len < 0) return fn();
    -
    -      var i = keys[len]
    -        , path = prefix + i
    -        , schema = self.schema.path(path)
    -        , total = 0
    -        , inline = false
    -        , poppath
    -
    -      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
    -        // assume nested object
    -        return init(obj[i], path + '.', next);
    -      }
    -
    -      if (!(obj[i] && schema && populate[path])) return next();
    -
    -      // this query object is re-used and passed around. we clone
    -      // it to prevent query condition contamination between
    -      // one populate call to the next.
    -      poppath = utils.clone(populate[path]);
    -
    -      if (poppath.sub) {
    -        obj[i].forEach(function (subobj) {
    -          inline = true;
    -
    -          var pkeys = Object.keys(poppath.sub)
    -            , pi = pkeys.length
    -            , key
    -
    -          while (pi--) {
    -            key = pkeys[pi];
    -
    -            if (subobj[key]) (function (key) {
    -              total++;
    -              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
    -              function done (err, doc) {
    -                if (err) return error(err);
    -                subobj[key] = doc;
    -                if (--total < 1 && !inline) {
    -                  next();
    -                }
    -              }
    -            })(key);
    -          }
    -        });
    -
    -        inline = false;
    -
    -        if (0 === total) return next();
    -
    -      } else {
    -        self._populate(schema, obj[i], poppath, function (err, doc) {
    -          if (err) return error(err);
    -          obj[i] = doc;
    -          next();
    -        });
    -      }
    -    };
    -  };
    -
    -  function error (err) {
    -    if (error.err) return;
    -    fn(error.err = err);
    -  }
    -};

    Parameters:

    • doc <Object> document returned by mongo
    • query <Query> query that originated the initialization
    • fn <Function>

    Model#save([fn])

    Saves this document.

    show code
    Model.prototype.save = function save (fn) {
    -  var promise = new Promise(fn)
    -    , complete = handleSave(promise, this)
    -    , options = {}
    -
    -  if (this.schema.options.safe) {
    -    options.safe = this.schema.options.safe;
    -  }
    -
    -  if (this.isNew) {
    -    // send entire doc
    -    var obj = this.toObject({ depopulate: 1 });
    -    this._version(true, obj);
    -    this.collection.insert(obj, options, complete);
    -    this._reset();
    -    this.isNew = false;
    -    this.emit('isNew', false);
    -    // Make it possible to retry the insert
    -    this._inserting = true;
    -
    -  } else {
    -    // Make sure we don't treat it as a new object on error,
    -    // since it already exists
    -    this._inserting = false;
    -
    -    var delta = this._delta();
    -    if (delta) {
    -      var where = this._where(delta[0]);
    -      this.collection.update(where, delta[1], options, complete);
    -    } else {
    -      complete(null);
    -    }
    -
    -    this._reset();
    -    this.emit('isNew', false);
    -  }
    -};

    Parameters:

    Example:

    - -
    product.sold = Date.now();
    -product.save(function (err, product) {
    -  if (err) ..
    -})
    - -

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    - -
    var db = mongoose.createConnection(..);
    -var schema = new Schema(..);
    -var Product = db.model('Product', schema);
    -
    -db.on('error', handleError);
    - -

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    - -
    Product.on('error', handleError);

    Model#_delta()

    Produces a special query document of the modified properties used in updates.

    show code
    Model.prototype._delta = function _delta () {
    -  var dirty = this._dirty();
    -  if (!dirty.length) return;
    -
    -  var self = this
    -    , where = {}
    -    , delta = {}
    -    , len = dirty.length
    -    , d = 0
    -    , val
    -    , obj
    -
    -  for (; d < len; ++d) {
    -    var data = dirty[d]
    -    var value = data.value
    -    var schema = data.schema
    -
    -    if (undefined === value) {
    -      operand(self, where, delta, data, 1, '$unset');
    -
    -    } else if (null === value) {
    -      operand(self, where, delta, data, null);
    -
    -    } else if (value._path && value._atomics) {
    -      handleAtomics(self, where, delta, data, value);
    -
    -    } else if (value._path && Buffer.isBuffer(value)) {
    -      // MongooseBuffer
    -      value = value.toObject();
    -      operand(self, where, delta, data, value);
    -
    -    } else {
    -      value = utils.clone(value);
    -      operand(self, where, delta, data, value);
    -    }
    -  }
    -
    -  if (this.__version) {
    -    this._version(where, delta);
    -  }
    -
    -  return [where, delta];
    -}

    Model#_version()

    Appends versioning to the where and update clauses.

    show code
    Model.prototype._version = function _version (where, delta) {
    -  var key = this.schema.options.versionKey;
    -
    -  if (true === where) {
    -    // this is an insert
    -    if (key) this.setValue(key, delta[key] = 0);
    -    return;
    -  }
    -
    -  // updates
    -
    -  // only apply versioning if our versionKey was selected. else
    -  // there is no way to select the correct version. we could fail
    -  // fast here and force them to include the versionKey but
    -  // thats a bit intrusive. can we do this automatically?
    -  // TODO fail fast option?
    -  if (!this.isSelected(key)) {
    -    return;
    -  }
    -
    -  // $push $addToSet don't need the where clause set
    -  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
    -    where[key] = this.getValue(key);
    -  }
    -
    -  if (VERSION_INC === (VERSION_INC & this.__version)) {
    -    delta.$inc || (delta.$inc = {});
    -    delta.$inc[key] = 1;
    -  }
    -}

    Model#increment()

    Signal that we desire an increment of this documents version.

    show code
    Model.prototype.increment = function increment () {
    -  this.__version = VERSION_ALL;
    -  return this;
    -}

    Model#_where()

    Returns a query object which applies shardkeys if they exist.

    show code
    Model.prototype._where = function _where (where) {
    -  where || (where = {});
    -
    -  var paths
    -    , len
    -
    -  if (this._shardval) {
    -    paths = Object.keys(this._shardval)
    -    len = paths.length
    -
    -    for (var i = 0; i < len; ++i) {
    -      where[paths[i]] = this._shardval[paths[i]];
    -    }
    -  }
    -
    -  where._id = this._doc._id;
    -  return where;
    -}

    Model#remove([fn])

    Removes this document from the db.

    show code
    Model.prototype.remove = function remove (fn) {
    -  if (this._removing) return this;
    -
    -  var promise = this._removing = new Promise(fn)
    -    , where = this._where()
    -    , self = this
    -    , options = {}
    -
    -  if (this.schema.options.safe) {
    -    options.safe = this.schema.options.safe;
    -  }
    -
    -  this.collection.remove(where, options, tick(function (err) {
    -    if (err) {
    -      promise.error(err);
    -      promise = self = self._removing = where = options = null;
    -      return;
    -    }
    -    self.emit('remove', self);
    -    promise.complete();
    -    promise = self = where = options = null;
    -  }));
    -
    -  return this;
    -};

    Parameters:

    Example:

    - -
    product.remove(function (err, product) {
    -  if (err) return handleError(err);
    -  Product.findById(product._id, function (err, product) {
    -    console.log(product) // null
    -  })
    -})

    Model#_registerHooks()

    Register hooks override

    show code
    Model.prototype._registerHooks = function registerHooks () {
    -  Document.prototype._registerHooks.call(this);
    -};

    Model#model(name)

    Returns another Model instance.

    show code
    Model.prototype.model = function model (name) {
    -  return this.db.model(name);
    -};

    Parameters:

    Example:

    - -
    var doc = new Tank;
    -doc.model('User').findById(id, callback);

    Model#$where(argument)

    Creates a Query and specifies a $where condition.

    Parameters:

    • argument <String, Function> is a javascript string or anonymous function

    Returns:

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    - -
    Blog.$where('this.comments.length &gt; 5');

    Model.init()

    Called when the model compiles.

    show code
    Model.init = function init () {
    -  if (this.schema.options.autoIndex)
    -    this.ensureIndexes();
    -
    -  this.schema.emit('init', this);
    -};

    Model.ensureIndexes([cb])

    Sends ensureIndex commands to mongo for each index declared in the schema.

    show code
    Model.ensureIndexes = function ensureIndexes (cb) {
    -  var indexes = this.schema.indexes();
    -  if (!indexes.length) {
    -    return cb && cb();
    -  }
    -
    -  var self = this
    -    , safe = self.schema.options.safe
    -    , count = indexes.length
    -    , error
    -
    -  indexes.forEach(function (index) {
    -    var options = index[1];
    -    options.safe = safe;
    -    self.collection.ensureIndex(index[0], options, tick(function (err) {
    -      if (err) error = err;
    -      if (--count) return;
    -
    -      self.emit('index', error);
    -      cb && cb(error);
    -    }));
    -  });
    -}

    Parameters:

    After completion, an index event is emitted on this Model passing an error if one occurred.


    Model.remove(conditions, [callback])

    Removes documents from the collection.

    show code
    Model.remove = function remove (conditions, callback) {
    -  if ('function' === typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -  }
    -
    -  var query = new Query(conditions).bind(this, 'remove');
    -
    -  if ('undefined' === typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.remove(callback);
    -};

    Parameters:

    Returns:

    Note:

    - -

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    - -
    Comment.remove({ _id: id }).exec();

    Model.find(conditions, [fields], [options], [callback])

    Finds documents

    show code
    Model.find = function find (conditions, fields, options, callback) {
    -  if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof fields) {
    -    callback = fields;
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof options) {
    -    callback = options;
    -    options = null;
    -  }
    -
    -  var query = new Query(conditions, options);
    -  query.bind(this, 'find');
    -  query.select(fields);
    -
    -  if ('undefined' === typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.find(callback);
    -};

    Parameters:

    Returns:

    Examples:

    - -
    // retrieve only certain keys
    -MyModel.find({ name: /john/i }, 'name friends', function () { })
    -
    -// pass options
    -MyModel.find({ name: /john/i }, null, { skip: 10 } )

    Model._applyNamedScope(query)

    Merges the current named scope query into query.

    show code
    Model._applyNamedScope = function _applyNamedScope (query) {
    -  var cQuery = this._cumulativeQuery;
    -
    -  if (cQuery) {
    -    merge(query._conditions, cQuery._conditions);
    -    if (query._fields && cQuery._fields)
    -      merge(query._fields, cQuery._fields);
    -    if (query.options && cQuery.options)
    -      merge(query.options, cQuery.options);
    -    delete this._cumulativeQuery;
    -  }
    -
    -  return query;
    -}

    Parameters:

    Returns:


    Model.findById(id, [fields], [options], [callback])

    Finds a single document by id.

    show code
    Model.findById = function findById (id, fields, options, callback) {
    -  return this.findOne({ _id: id }, fields, options, callback);
    -};

    Parameters:

    Returns:

    The id is cast to an ObjectId before sending the command.

    - -

    Example:

    - -
    Adventure.findById(id, callback);

    Model.findOne(conditions, [fields], [options], [callback])

    Finds one document.

    show code
    Model.findOne = function findOne (conditions, fields, options, callback) {
    -  if ('function' == typeof options) {
    -    // TODO Handle all 3 of the following scenarios
    -    // Hint: Only some of these scenarios are possible if cQuery is present
    -    // Scenario: findOne(conditions, fields, callback);
    -    // Scenario: findOne(fields, options, callback);
    -    // Scenario: findOne(conditions, options, callback);
    -    callback = options;
    -    options = null;
    -  } else if ('function' == typeof fields) {
    -    // TODO Handle all 2 of the following scenarios
    -    // Scenario: findOne(conditions, callback)
    -    // Scenario: findOne(fields, callback)
    -    // Scenario: findOne(options, callback);
    -    callback = fields;
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -    fields = null;
    -    options = null;
    -  }
    -
    -  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.findOne(callback);
    -};

    Parameters:

    Returns:

    The conditions are cast to their respective SchemaTypes before the command is sent.

    - -

    Example:

    - -
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

    Model.count(conditions, [callback])

    Counts number of matching documents in a database collection.

    show code
    Model.count = function count (conditions, callback) {
    -  if ('function' === typeof conditions)
    -    callback = conditions, conditions = {};
    -
    -  var query = new Query(conditions).bind(this, 'count');
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.count(callback);
    -};

    Parameters:

    Returns:

    Example:

    - -
    Adventure.count({ type: 'jungle' }, function (err, count) {
    -  if (err) ..
    -  console.log('there are %d jungle adventures', count);
    -});

    Model.distinct(field, [conditions], [callback])

    Executes a DISTINCT command

    show code
    Model.distinct = function distinct (field, conditions, callback) {
    -  var query = new Query(conditions).bind(this, 'distinct');
    -  if ('undefined' == typeof callback) {
    -    query._distinctArg = field;
    -    return query;
    -  }
    -
    -  this._applyNamedScope(query);
    -  return query.distinct(field, callback);
    -};

    Parameters:

    Returns:


    Model.where(path, [val])

    Creates a Query, applies the passed conditions, and returns the Query.

    show code
    Model.where = function where (path, val) {
    -  var q = new Query().bind(this, 'find');
    -  return q.where.apply(q, arguments);
    -};

    Parameters:

    Returns:

    For example, instead of writing:

    - -
    User.find({age: {$gte: 21, $lte: 65}}, callback);
    - -

    we can instead write:

    - -
    User.where('age').gte(21).lte(65).exec(callback);
    - -

    Since the Query class also supports where you can continue chaining

    - -
    User
    -.where('age').gte(21).lte(65)
    -.where('name', /^b/i)
    -... etc

    Model.findOneAndUpdate([conditions], [update], [options], [callback])

    Issues a mongodb findAndModify update command.

    show code
    Model.findOneAndUpdate = function (conditions, update, options, callback) {
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = null;
    -  }
    -  else if (1 === arguments.length) {
    -    if ('function' == typeof conditions) {
    -      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
    -
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(update)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate()
    -';
    -      throw new TypeError(msg)
    -    }
    -    update = conditions;
    -    conditions = undefined;
    -  }
    -
    -  var fields;
    -  if (options && options.fields) {
    -    fields = options.fields;
    -    options.fields = undefined;
    -  }
    -
    -  var query = new Query(conditions);
    -  query.setOptions(options);
    -  query.select(fields);
    -  query.bind(this, 'findOneAndUpdate', update);
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.findOneAndUpdate(callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findOneAndUpdate(conditions, update, options, callback) // executes
    -A.findOneAndUpdate(conditions, update, options)  // returns Query
    -A.findOneAndUpdate(conditions, update, callback) // executes
    -A.findOneAndUpdate(conditions, update)           // returns Query
    -A.findOneAndUpdate()                             // returns Query
    - -

    Note:

    - -

    All top level update keys which are not atomic operation names are treated as set operations:

    - -

    Example:

    - -
    var query = { name: 'borne' };
    -Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
    -
    -// is sent as
    -Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
    - -

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    - -

    Note:

    - -

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    - -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    - -

    If you need those features, use the traditional approach of first retrieving the document.

    - -
    Model.findOne({ name: 'borne' }, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.findByIdAndUpdate(id, [update], [options], [callback])

    Issues a mongodb findAndModify update command by a documents id.

    show code
    Model.findByIdAndUpdate = function (id, update, options, callback) {
    -  var args;
    -
    -  if (1 === arguments.length) {
    -    if ('function' == typeof id) {
    -      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
    -
    -'
    -                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
    -'
    -                + '  ' + this.modelName + '.findByIdAndUpdate(id)
    -'
    -                + '  ' + this.modelName + '.findByIdAndUpdate()
    -';
    -      throw new TypeError(msg)
    -    }
    -    return this.findOneAndUpdate({_id: id }, undefined);
    -  }
    -
    -  args = utils.args(arguments, 1);
    -  args.unshift({ _id: id });
    -  return this.findOneAndUpdate.apply(this, args);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findByIdAndUpdate(id, update, options, callback) // executes
    -A.findByIdAndUpdate(id, update, options)  // returns Query
    -A.findByIdAndUpdate(id, update, callback) // executes
    -A.findByIdAndUpdate(id, update)           // returns Query
    -A.findByIdAndUpdate()                     // returns Query
    - -

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    - -

    Note:

    - -

    All top level update keys which are not atomic operation names are treated as set operations:

    - -

    Example:

    - -
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
    -
    -// is sent as
    -Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
    - -

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    - -

    Note:

    - -

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    - -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    - -

    If you need those features, use the traditional approach of first retrieving the document.

    - -
    Model.findById(id, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.findOneAndRemove(conditions, [options], [callback])

    Issue a mongodb findAndModify remove command.

    show code
    Model.findOneAndRemove = function (conditions, options, callback) {
    -  if (1 === arguments.length && 'function' == typeof conditions) {
    -    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
    -
    -'
    -              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
    -'
    -              + '  ' + this.modelName + '.findOneAndRemove(conditions)
    -'
    -              + '  ' + this.modelName + '.findOneAndRemove()
    -';
    -    throw new TypeError(msg)
    -  }
    -
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = undefined;
    -  }
    -
    -  var fields;
    -  if (options) {
    -    fields = options.select;
    -    options.select = undefined;
    -  }
    -
    -  var query = new Query(conditions);
    -  query.setOptions(options);
    -  query.select(fields);
    -  query.bind(this, 'findOneAndRemove');
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.findOneAndRemove(callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    - -

    Executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findOneAndRemove(conditions, options, callback) // executes
    -A.findOneAndRemove(conditions, options)  // return Query
    -A.findOneAndRemove(conditions, callback) // executes
    -A.findOneAndRemove(conditions) // returns Query
    -A.findOneAndRemove()           // returns Query

    Model.findByIdAndRemove(id, [options], [callback])

    Issue a mongodb findAndModify remove command by a documents id.

    show code
    Model.findByIdAndRemove = function (id, options, callback) {
    -  if (1 === arguments.length && 'function' == typeof id) {
    -    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
    -
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove(id)
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove()
    -';
    -    throw new TypeError(msg)
    -  }
    -
    -  return this.findOneAndRemove({ _id: id }, options, callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    - -

    Executes immediately if callback is passed, else a Query object is returned.

    - -

    Options:

    - -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findByIdAndRemove(id, options, callback) // executes
    -A.findByIdAndRemove(id, options)  // return Query
    -A.findByIdAndRemove(id, callback) // executes
    -A.findByIdAndRemove(id) // returns Query
    -A.findByIdAndRemove()           // returns Query

    Model.create(doc, fn)

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    show code
    Model.create = function create (doc, fn) {
    -  if (1 === arguments.length) {
    -    return 'function' === typeof doc && doc(null);
    -  }
    -
    -  var self = this
    -    , docs = [null]
    -    , promise
    -    , count
    -    , args
    -
    -  if (Array.isArray(doc)) {
    -    args = doc;
    -  } else {
    -    args = utils.args(arguments, 0, arguments.length - 1);
    -    fn = arguments[arguments.length - 1];
    -  }
    -
    -  if (0 === args.length) return fn(null);
    -
    -  promise = new Promise(fn);
    -  count = args.length;
    -
    -  args.forEach(function (arg, i) {
    -    var doc = new self(arg);
    -    docs[i+1] = doc;
    -    doc.save(function (err) {
    -      if (err) return promise.error(err);
    -      --count || fn.apply(null, docs);
    -    });
    -  });
    -
    -  // TODO
    -  // utilize collection.insertAll for batch processing?
    -};

    Parameters:

    Example:

    - -
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
    -  if (err) // ...
    -});
    -
    -var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
    -Candy.create(array, function (err, jellybean, snickers) {
    -  if (err) // ...
    -});

    Model.update(conditions, update, [options], [callback])

    Updates documents in the database without returning them.

    show code
    Model.update = function update (conditions, doc, options, callback) {
    -  if (arguments.length < 4) {
    -    if ('function' === typeof options) {
    -      // Scenario: update(conditions, doc, callback)
    -      callback = options;
    -      options = null;
    -    } else if ('function' === typeof doc) {
    -      // Scenario: update(doc, callback);
    -      callback = doc;
    -      doc = conditions;
    -      conditions = {};
    -      options = null;
    -    }
    -  }
    -
    -  var query = new Query(conditions, options).bind(this, 'update', doc);
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.update(doc, callback);
    -};

    Parameters:

    Returns:

    Examples:

    - -
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
    -MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
    -  if (err) return handleError(err);
    -  console.log('The number of updated documents was %d', numberAffected);
    -  console.log('The raw response from Mongo was ', raw);
    -});
    - -

    Valid options:

    - -
      -
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • -
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • -
    • multi (boolean) whether multiple documents should be updated (false)
    • -
    - -

    All update values are cast to their appropriate SchemaTypes before being sent.

    - -

    The callback function receives (err, numberAffected, rawResponse).

    - -
      -
    • err is the error if any occurred
    • -
    • numberAffected is the count of updated documents Mongo reported
    • -
    • rawResponse is the full response from Mongo
    • -
    - -

    Note:

    - -

    All top level keys which are not atomic operation names are treated as set operations:

    - -

    Example:

    - -
    var query = { name: 'borne' };
    -Model.update(query, { name: 'jason borne' }, options, callback)
    -
    -// is sent as
    -Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
    - -

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    - -

    Note:

    - -

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    - -
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
    - -

    Note:

    - -

    Although values are casted to their appropriate types when using update, the following are not applied:

    - -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    - -

    If you need those features, use the traditional approach of first retrieving the document.

    - -
    Model.findOne({ name: 'borne' }, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.mapReduce(o, callback)

    Executes a mapReduce command.

    show code
    Model.mapReduce = function mapReduce (o, callback) {
    -  if ('function' != typeof callback) throw new Error('missing callback');
    -
    -  var self = this;
    -
    -  if (!Model.mapReduce.schema) {
    -    var opts = { noId: true, noVirtualId: true, strict: false }
    -    Model.mapReduce.schema = new Schema({}, opts);
    -  }
    -
    -  if (!o.out) o.out = { inline: 1 };
    -
    -  o.map = String(o.map);
    -  o.reduce = String(o.reduce);
    -
    -  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
    -    if (err) return callback(err);
    -
    -    if (ret.findOne && ret.mapReduce) {
    -      // returned a collection, convert to Model
    -      var model = Model.compile(
    -          '_mapreduce_' + ret.collectionName
    -        , Model.mapReduce.schema
    -        , ret.collectionName
    -        , self.db
    -        , self.base);
    -
    -      model._mapreduce = true;
    -
    -      return callback(err, model, stats);
    -    }
    -
    -    callback(err, ret, stats);
    -  });
    -}

    Parameters:

    • o <Object> an object specifying map-reduce options
    • callback <Function>

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    - -

    Example:

    - -
    var o = {};
    -o.map = function () { emit(this.name, 1) }
    -o.reduce = function (k, vals) { return vals.length }
    -User.mapReduce(o, function (err, results) {
    -  console.log(results)
    -})
    - -

    Other options:

    - -
      -
    • query {Object} query filter object.
    • -
    • limit {Number} max number of documents
    • -
    • keeptemp {Boolean, default:false} keep temporary data
    • -
    • finalize {Function} finalize function
    • -
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • -
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • -
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • -
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • -
    - -

    * out options:

    - -
      -
    • {inline:1} the results are returned in an array
    • -
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • -
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • -
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • -
    - -

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    - -

    Example:

    - -
    var o = {};
    -o.map = function () { emit(this.name, 1) }
    -o.reduce = function (k, vals) { return vals.length }
    -o.out = { replace: 'createdCollectionNameForResults' }
    -o.verbose = true;
    -User.mapReduce(o, function (err, model, stats) {
    -  console.log('map reduce took %d ms', stats.processtime)
    -  model.find().where('value').gt(10).exec(function (err, docs) {
    -    console.log(docs);
    -  });
    -})

    Model#base

    Base Mongoose instance the model uses.


    Model#collection

    Collection the model uses.


    Model#db

    Database instance the model uses.


    Model#schema

    Schema the model uses.


    Model#modelName

    The name of the model


    Model#collection

    Collection the model uses.


    Model#db

    Connection the model uses.


  • namedscope.js

    NamedScope#decorate(target, getters)

    Decorate

    show code
    NamedScope.prototype.decorate = function (target, getters) {
    -  var name = this.name
    -    , block = this.block
    -    , query = this.query;
    -  if (block) {
    -    if (block.length === 0) {
    -      Object.defineProperty(target, name, {
    -        get: getters.block0(block)
    -      });
    -    } else {
    -      target[name] = getters.blockN(block);
    -    }
    -  } else {
    -    Object.defineProperty(target, name, {
    -      get: getters.basic(query)
    -    });
    -  }
    -};
    -
    -NamedScope.prototype.compile = function (model) {
    -  var allScopes = this.scopesByName
    -    , scope;
    -  for (var k in allScopes) {
    -    scope = allScopes[k];
    -    scope.decorate(model, {
    -      block0: function (block) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          block.call(cquery);
    -          return this;
    -        };
    -      },
    -      blockN: function (block) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          block.apply(cquery, arguments);
    -          return this;
    -        };
    -      },
    -      basic: function (query) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          cquery.find(query);
    -          return this;
    -        };
    -      }
    -    });
    -  }
    -};
    -
    -module.exports = NamedScope;

    Parameters:


  • promise.js

    Promise(back)

    Promise constructor.

    show code
    function Promise (back) {
    -  this.emitted = {};
    -  if ('function' == typeof back)
    -    this.addBack(back);
    -};

    Parameters:

    • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

    Events:

    • err: Emits when the promise resolves to an error.

    • complete: Emits when the promise resolves sucessfully.


    Promise#on(event, callback)

    Adds listener to the event.

    show code
    Promise.prototype.on = function (event, callback) {
    -  if (this.emitted[event])
    -    callback.apply(this, this.emitted[event]);
    -  else
    -    EventEmitter.prototype.on.call(this, event, callback);
    -
    -  return this;
    -};

    Parameters:

    Returns:

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


    Promise#emit()

    Keeps track of emitted events to run them on on.

    show code
    Promise.prototype.emit = function (event) {
    -  // ensures a promise can't be complete() or error() twice
    -  if (event == 'err' || event == 'complete'){
    -    if (this.emitted.err || this.emitted.complete) {
    -      return this;
    -    }
    -    this.emitted[event] = util.args(arguments, 1);
    -  }
    -
    -  return EventEmitter.prototype.emit.apply(this, arguments);
    -};

    Promise#complete()

    Shortcut for emitting the complete event.

    show code
    Promise.prototype.complete = function () {
    -  var args = util.args(arguments);
    -  return this.emit.apply(this, ['complete'].concat(args));
    -};

    Promise#error()

    Shortcut for emitting the err event.

    show code
    Promise.prototype.error = function (err) {
    -  if (!(err instanceof Error)) err = new Error(err);
    -  return this.emit('err', err);
    -};

    Returns:


    Promise#addCallback()

    Shortcut for .on('complete', fn).

    show code
    Promise.prototype.addCallback = function (fn) {
    -  return this.on('complete', fn);
    -};

    Returns:


    Promise#addErrback()

    Shortcut for .on('err', fn).

    show code
    Promise.prototype.addErrback = function (fn) {
    -  return this.on('err', fn);
    -};

    Returns:


    Promise#addBack(fn)

    Adds a single function that's both a callback and errback.

    show code
    Promise.prototype.addBack = function (fn) {
    -  this.on('err', function(err){
    -    fn.call(this, err);
    -  });
    -
    -  this.on('complete', function(){
    -    var args = util.args(arguments);
    -    fn.apply(this, [null].concat(args));
    -  });
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Promise#resolve(err, val)

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    show code
    Promise.prototype.resolve = function (err, val) {
    -  if (err) return this.error(err);
    -  return this.complete(val);
    -};

    Parameters:

    • err <Error> optional error or null
    • val <Object> value to complete the promise with

  • query.js

    Query(criteria, options)

    Query constructor used for building queries.

    show code
    function Query (criteria, options) {
    -  this.setOptions(options, true);
    -  this._conditions = {};
    -  this._updateArg = {};
    -  if (criteria) this.find(criteria);
    -}

    Parameters:

    Example:

    - -
    var query = Model.find();
    -query.where('age').gte(21).exec(callback);

    Query#setOptions(options)

    Sets query options.

    show code
    Query.prototype.setOptions = function (options, overwrite) {
    -  // overwrite is internal use only
    -  if (overwrite) {
    -    options = this.options = options || {};
    -    this.safe = options.safe
    -
    -    // normalize population options
    -    var pop = this.options.populate;
    -    this.options.populate = {};
    -
    -    if (pop && Array.isArray(pop)) {
    -      for (var i = 0, l = pop.length; i < l; i++) {
    -        this.options.populate[pop[i]] = {};
    -      }
    -    }
    -
    -    return this;
    -  }
    -
    -  if (!(options && 'Object' == options.constructor.name))
    -    return this;
    -
    -  if ('safe' in options)
    -    this.safe = options.safe;
    -
    -  // set arbitrary options
    -  var methods = Object.keys(options)
    -    , i = methods.length
    -    , method
    -
    -  while (i--) {
    -    method = methods[i];
    -
    -    // use methods if exist (safer option manipulation)
    -    if ('function' == typeof this[method]) {
    -      var args = Array.isArray(options[method])
    -        ? options[method]
    -        : [options[method]];
    -      this[method].apply(this, args)
    -    } else {
    -      this.options[method] = options[method];
    -    }
    -  }
    -  return this;
    -}

    Parameters:

    Options:

    - - - -

    * denotes a query helper method is also available


    Query#bind(model, op, updateArg)

    Binds this query to a model.

    show code
    Query.prototype.bind = function bind (model, op, updateArg) {
    -  this.model = model;
    -  this.op = op;
    -
    -  if (model._mapreduce) this.options.lean = true;
    -
    -  if (op == 'update' || op == 'findOneAndUpdate') {
    -    merge(this._updateArg, updateArg || {});
    -  }
    -
    -  return this;
    -};

    Parameters:

    • model <Model> the model to which the query is bound
    • op <String> the operation to execute
    • updateArg <Object> used in update methods

    Returns:


    Query#exec([operation], [callback])

    Executes the query

    show code
    Query.prototype.exec = function exec (op, callback) {
    -  var promise = new Promise();
    -
    -  switch (typeof op) {
    -    case 'function':
    -      callback = op;
    -      op = null;
    -      break;
    -    case 'string':
    -      this.op = op;
    -      break;
    -  }
    -
    -  if (callback) promise.addBack(callback);
    -
    -  if (!this.op) {
    -    promise.complete();
    -    return promise;
    -  }
    -
    -  if ('update' == this.op) {
    -    this[this.op](this._updateArg, promise.resolve.bind(promise));
    -    return promise;
    -  }
    -
    -  if ('distinct' == this.op) {
    -    this.distinct(this._distinctArg, promise.resolve.bind(promise));
    -    return promise;
    -  }
    -
    -  this[this.op](promise.resolve.bind(promise));
    -  return promise;
    -};

    Parameters:

    Returns:

    Examples

    - -
    query.exec();
    -query.exec(callback);
    -query.exec('update');
    -query.exec('find', callback);

    Query#find([criteria], [callback])

    Finds documents.

    show code
    Query.prototype.find = function (criteria, callback) {
    -  this.op = 'find';
    -  if ('function' === typeof criteria) {
    -    callback = criteria;
    -    criteria = {};
    -  } else if (criteria instanceof Query) {
    -    // TODO Merge options, too
    -    merge(this._conditions, criteria._conditions);
    -  } else if (criteria instanceof Document) {
    -    merge(this._conditions, criteria.toObject());
    -  } else if (criteria && 'Object' === criteria.constructor.name) {
    -    merge(this._conditions, criteria);
    -  }
    -  if (!callback) return this;
    -  return this.execFind(callback);
    -};

    Parameters:

    Returns:

    When no callback is passed, the query is not executed.

    - -

    Example

    - -
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)

    Query#cast(model, [obj])

    Casts this query to the schema of model

    show code
    Query.prototype.cast = function (model, obj) {
    -  obj || (obj= this._conditions);
    -
    -  var schema = model.schema
    -    , paths = Object.keys(obj)
    -    , i = paths.length
    -    , any$conditionals
    -    , schematype
    -    , nested
    -    , path
    -    , type
    -    , val;
    -
    -  while (i--) {
    -    path = paths[i];
    -    val = obj[path];
    -
    -    if ('$or' === path || '$nor' === path) {
    -      var k = val.length
    -        , orComponentQuery;
    -
    -      while (k--) {
    -        orComponentQuery = new Query(val[k]);
    -        orComponentQuery.cast(model);
    -        val[k] = orComponentQuery._conditions;
    -      }
    -
    -    } else if (path === '$where') {
    -      type = typeof val;
    -
    -      if ('string' !== type && 'function' !== type) {
    -        throw new Error("Must have a string or function for $where");
    -      }
    -
    -      if ('function' === type) {
    -        obj[path] = val.toString();
    -      }
    -
    -      continue;
    -
    -    } else {
    -
    -      if (!schema) {
    -        // no casting for Mixed types
    -        continue;
    -      }
    -
    -      schematype = schema.path(path);
    -
    -      if (!schematype) {
    -        // Handle potential embedded array queries
    -        var split = path.split('.')
    -          , j = split.length
    -          , pathFirstHalf
    -          , pathLastHalf
    -          , remainingConds
    -          , castingQuery;
    -
    -        // Find the part of the var path that is a path of the Schema
    -        while (j--) {
    -          pathFirstHalf = split.slice(0, j).join('.');
    -          schematype = schema.path(pathFirstHalf);
    -          if (schematype) break;
    -        }
    -
    -        // If a substring of the input path resolves to an actual real path...
    -        if (schematype) {
    -          // Apply the casting; similar code for $elemMatch in schema/array.js
    -          if (schematype.caster && schematype.caster.schema) {
    -            remainingConds = {};
    -            pathLastHalf = split.slice(j).join('.');
    -            remainingConds[pathLastHalf] = val;
    -            castingQuery = new Query(remainingConds);
    -            castingQuery.cast(schematype.caster);
    -            obj[path] = castingQuery._conditions[pathLastHalf];
    -          } else {
    -            obj[path] = val;
    -          }
    -        }
    -
    -      } else if (val === null || val === undefined) {
    -        continue;
    -      } else if ('Object' === val.constructor.name) {
    -
    -        any$conditionals = Object.keys(val).some(function (k) {
    -          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
    -        });
    -
    -        if (!any$conditionals) {
    -          obj[path] = schematype.castForQuery(val);
    -        } else {
    -
    -          var ks = Object.keys(val)
    -            , k = ks.length
    -            , $cond;
    -
    -          while (k--) {
    -            $cond = ks[k];
    -            nested = val[$cond];
    -
    -            if ('$exists' === $cond) {
    -              if ('boolean' !== typeof nested) {
    -                throw new Error("$exists parameter must be Boolean");
    -              }
    -              continue;
    -            }
    -
    -            if ('$type' === $cond) {
    -              if ('number' !== typeof nested) {
    -                throw new Error("$type parameter must be Number");
    -              }
    -              continue;
    -            }
    -
    -            if ('$not' === $cond) {
    -              this.cast(model, nested);
    -            } else {
    -              val[$cond] = schematype.castForQuery($cond, nested);
    -            }
    -          }
    -        }
    -      } else {
    -        obj[path] = schematype.castForQuery(val);
    -      }
    -    }
    -  }
    -
    -  return obj;
    -};

    Parameters:

    Returns:

    Note

    - -

    If obj is present, it is cast instead of this query.


    Query#_optionsForExec(model)

    Returns default options.

    show code
    Query.prototype._optionsForExec = function (model) {
    -  var options = utils.clone(this.options, { retainKeyOrder: true });
    -  delete options.populate;
    -  if (! ('safe' in options)) options.safe = model.schema.options.safe;
    -  return options;
    -};

    Parameters:


    Query#_applyPaths()

    Applies schematype selected options to this query.

    show code
    Query.prototype._applyPaths = function applyPaths () {
    -  // determine if query is selecting or excluding fields
    -
    -  var fields = this._fields
    -    , exclude
    -    , keys
    -    , ki
    -
    -  if (fields) {
    -    keys = Object.keys(fields);
    -    ki = keys.length;
    -
    -    while (ki--) {
    -      if ('+' == keys[ki][0]) continue;
    -      exclude = 0 === fields[keys[ki]];
    -      break;
    -    }
    -  }
    -
    -  // if selecting, apply default schematype select:true fields
    -  // if excluding, apply schematype select:false fields
    -
    -  var selected = []
    -    , excluded = []
    -    , seen = [];
    -
    -  analyzeSchema(this.model.schema);
    -
    -  switch (exclude) {
    -    case true:
    -      excluded.length && this.select('-' + excluded.join(' -'));
    -      break;
    -    case false:
    -      selected.length && this.select(selected.join(' '));
    -      break;
    -    case undefined:
    -      // user didn't specify fields, implies returning all fields.
    -      // only need to apply excluded fields
    -      excluded.length && this.select('-' + excluded.join(' -'));
    -      break;
    -  }
    -
    -  return seen = excluded = selected = keys = fields = null;
    -
    -  function analyzeSchema (schema, prefix) {
    -    prefix || (prefix = '');
    -
    -    // avoid recursion
    -    if (~seen.indexOf(schema)) return;
    -    seen.push(schema);
    -
    -    schema.eachPath(function (path, type) {
    -      if (prefix) path = prefix + '.' + path;
    -
    -      // array of subdocs?
    -      if (type.schema) {
    -        analyzeSchema(type.schema, path);
    -      }
    -
    -      analyzePath(path, type);
    -    });
    -  }
    -
    -  function analyzePath (path, type) {
    -    if ('boolean' != typeof type.selected) return;
    -
    -    if (fields && ('+' + path) in fields) {
    -      // forced inclusion
    -      delete fields['+' + path];
    -
    -      // if there are other fields being included, add this one
    -      // if no other included fields, leave this out (implied inclusion)
    -      if (false === exclude && keys.length > 1) {
    -        fields[path] = 1;
    -      }
    -
    -      return
    -    };
    -
    -    ;(type.selected ? selected : excluded).push(path);
    -  }
    -}

    Query#$where(js)

    Specifies a $where condition

    Parameters:

    Returns:

    Use $where when you need to select documents using a JavaScript expression.

    - -

    Example

    - -
    query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
    -
    -query.$where(function () {
    -  return this.comments.length &gt; 10 || this.name.length &gt; 5;
    -})

    Query#where([path], [val])

    Specifies a path for use with chaining.

    show code
    Query.prototype.where = function (path, val) {
    -  if (!arguments.length) return this;
    -
    -  if ('string' != typeof path) {
    -    throw new TypeError('path must be a string');
    -  }
    -
    -  this._currPath = path;
    -
    -  if (2 === arguments.length) {
    -    this._conditions[path] = val;
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    // instead of writing:
    -User.find({age: {$gte: 21, $lte: 65}}, callback);
    -
    -// we can instead write:
    -User.where('age').gte(21).lte(65);
    -
    -// Moreover, you can also chain a bunch of these together:
    -
    -User
    -.where('age').gte(21).lte(65)
    -.where('name', /^b/i)
    -.where('friends').slice(10)
    -.exec(callback)

    Query#equals(val)

    Specifies the complementary comparison value for paths specified with where()

    show code
    Query.prototype.equals = function equals (val) {
    -  var path = this._currPath;
    -  if (!path) throw new Error('equals() must be used after where()');
    -  this._conditions[path] = val;
    -  return this;
    -}

    Parameters:

    Returns:

    Example

    - -
    User.where('age').equals(49);
    -
    -// is the same as
    -
    -User.where('age', 49);

    Query#or(array)

    Specifies arguments for an $or condition.

    show code
    Query.prototype.or = function or (array) {
    -  var or = this._conditions.$or || (this._conditions.$or = []);
    -  if (!Array.isArray(array)) array = [array];
    -  or.push.apply(or, array);
    -  return this;
    -}

    Parameters:

    • array <Array> array of conditions

    Returns:

    Example

    - -
    query.or([{ color: 'red' }, { status: 'emergency' }])

    Query#nor(array)

    Specifies arguments for a $nor condition.

    show code
    Query.prototype.nor = function nor (array) {
    -  var nor = this._conditions.$nor || (this._conditions.$nor = []);
    -  if (!Array.isArray(array)) array = [array];
    -  nor.push.apply(nor, array);
    -  return this;
    -}

    Parameters:

    • array <Array> array of conditions

    Returns:

    Example

    - -
    query.nor([{ color: 'green' }, { status: 'ok' }])

    Query#gt(path, val)

    Specifies a $gt query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.

    - -

    Example

    - -
    Thing.find().where('age').gt(21)
    -
    -// or
    -Thing.find().gt('age', 21)

    Query#gte(path, val)

    Specifies a $gte query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#lt(path, val)

    Specifies a $lt query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#lte(path, val)

    Specifies a $lte query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#ne(path, val)

    Specifies a $ne query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#in(path, val)

    Specifies an $in query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#nin(path, val)

    Specifies an $nin query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#all(path, val)

    Specifies an $all query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#size(path, val)

    Specifies an $size query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#regex(path, val)

    Specifies a $regex query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#maxDistance(path, val)

    Specifies a $maxDistance query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#near(path, val)

    Specifies a $near condition

    show code
    Query.prototype.near = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$near = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#nearSphere(path, val)

    Specifies a $nearSphere condition.

    show code
    Query.prototype.nearSphere = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$nearSphere = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#mod(path, val)

    Specifies a $mod condition

    show code
    Query.prototype.mod = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$mod = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#exists(path, val)

    Specifies an $exists condition

    show code
    Query.prototype.exists = function (path, val) {
    -  if (arguments.length === 0) {
    -    path = this._currPath
    -    val = true;
    -  } else if (arguments.length === 1) {
    -    if ('boolean' === typeof path) {
    -      val = path;
    -      path = this._currPath;
    -    } else {
    -      val = true;
    -    }
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$exists'] = val;
    -  return this;
    -};

    Parameters:

    Returns:


    Query#elemMatch(path, criteria)

    Specifies an $elemMatch condition

    show code
    Query.prototype.elemMatch = function (path, criteria) {
    -  var block;
    -  if ('Object' === path.constructor.name) {
    -    criteria = path;
    -    path = this._currPath;
    -  } else if ('function' === typeof path) {
    -    block = path;
    -    path = this._currPath;
    -  } else if ('Object' === criteria.constructor.name) {
    -  } else if ('function' === typeof criteria) {
    -    block = criteria;
    -  } else {
    -    throw new Error("Argument error");
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  if (block) {
    -    criteria = new Query();
    -    block(criteria);
    -    conds['$elemMatch'] = criteria._conditions;
    -  } else {
    -    conds['$elemMatch'] = criteria;
    -  }
    -  return this;
    -};
    -
    -// Spatial queries

    Parameters:

    Returns:

    Example

    - -
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
    -
    -query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
    -
    -query.elemMatch('comment', function (elem) {
    -  elem.where('author').equals('autobot');
    -  elem.where('votes').gte(5);
    -})
    -
    -query.where('comment').elemMatch(function (elem) {
    -  elem.where('author').equals('autobot');
    -  elem.where('votes').gte(5);
    -})

    Query#box(path, val)

    Specifies a $box condition

    show code
    Query.prototype.box = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$box': [val.ll, val.ur]  };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var lowerLeft = [40.73083, -73.99756]
    -var upperRight= [40.741404,  -73.988135]
    -query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

    Query#center(path, val, [opts])

    Specifies a $center condition

    show code
    Query.prototype.center = function (path, val, opts) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$center': [val.center, val.radius]  };
    -
    -  // copy any options
    -  if (opts && 'Object' == opts.constructor.name) {
    -    utils.options(opts, conds.$within);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var area = { center: [50, 50], radius: 10 }
    -query.where('loc').within.center(area)

    Query#centerSphere(path, val)

    Specifies a $centerSphere condition

    show code
    Query.prototype.centerSphere = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var area = { center: [50, 50], radius: 10 }
    -query.where('loc').within.centerSphere(area)

    Query#polygon(path, val)

    Specifies a $polygon condition

    show code
    Query.prototype.polygon = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$polygon': val };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
    -query.where('loc').within.polygon(polyA)
    -
    -// or
    -var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
    -query.where('loc').within.polygon(polyB)

    Query#select(arg)

    Specifies which document fields to include or exclude

    show code
    Query.prototype.select = function select (arg) {
    -  if (!arg) return this;
    -
    -  var fields = this._fields || (this._fields = {});
    -
    -  if ('Object' === arg.constructor.name) {
    -    Object.keys(arg).forEach(function (field) {
    -      fields[field] = arg[field];
    -    });
    -  } else if (1 === arguments.length && 'string' == typeof arg) {
    -    arg.split(/\s+/).forEach(function (field) {
    -      if (!field) return;
    -      var include = '-' == field[0] ? 0 : 1;
    -      if (include === 0) field = field.substring(1);
    -      fields[field] = include;
    -    });
    -  } else {
    -    throw new TypeError('Invalid select() argument. Must be a string or object.');
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    - -

    Example

    - -
    // include a and b, exclude c
    -query.select('a b -c');
    -
    -// or you may use object notation, useful when
    -// you have keys already prefixed with a "-"
    -query.select({a: 1, b: 1, c: 0});
    -
    -// force inclusion of field excluded at schema level
    -query.select('+path')

    Query#slice(path, val)

    Specifies a $slice condition

    show code
    Query.prototype.slice = function (path, val) {
    -  if (arguments.length === 1) {
    -      val = path;
    -      path = this._currPath
    -  } else if (arguments.length === 2) {
    -    if ('number' === typeof path) {
    -      val = [path, val];
    -      path = this._currPath;
    -    }
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var myFields = this._fields || (this._fields = {});
    -  myFields[path] = { '$slice': val };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    query.slice('comments', 5)
    -query.slice('comments', -5)
    -query.slice('comments', [10, 5])
    -query.where('comments').slice(5)
    -query.where('comments').slice([-10, 5])

    Query#sort(arg)

    Sets the sort order

    show code
    Query.prototype.sort = function (arg) {
    -  if (!arg) return this;
    -
    -  var sort = this.options.sort || (this.options.sort = []);
    -
    -  if ('Object' === arg.constructor.name) {
    -    Object.keys(arg).forEach(function (field) {
    -      push(sort, field, arg[field]);
    -    });
    -  } else if (1 === arguments.length && 'string' == typeof arg) {
    -    arg.split(/\s+/).forEach(function (field) {
    -      if (!field) return;
    -      var ascend = '-' == field[0] ? -1 : 1;
    -      if (ascend === -1) field = field.substring(1);
    -      push(sort, field, ascend);
    -    });
    -  } else {
    -    throw new TypeError('Invalid sort() argument. Must be a string or object.');
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    - -

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    - -

    Example

    - -
    // these are equivalent
    -query.sort({ field: 'asc', test: -1 });
    -query.sort('field -test');

    Query#limit(val)

    Specifies the limit option.

    Parameters:

    Example

    - -
    Kitten.find().limit(20)

    Query#skip(val)

    Specifies the skip option.

    Parameters:

    Example

    - -
    Kitten.find().skip(100).limit(20)

    Query#maxscan(val)

    Specifies the maxscan option.

    Parameters:

    Example

    - -
    Kitten.find().maxscan(100)

    Query#batchSize(val)

    Specifies the batchSize option.

    Parameters:

    Example

    - -
    Kitten.find().batchSize(100)

    Query#comment(val)

    Specifies the comment option.

    Parameters:

    Example

    - -
    Kitten.findOne(condition).comment('login query')

    Query#snapshot()

    Specifies this query as a snapshot query.

    show code
    Query.prototype.snapshot = function () {
    -  this.options.snapshot = true;
    -  return this;
    -};

    Returns:

    Example

    - -
    Kitten.find().snapshot()

    Query#hint(val)

    Sets query hints.

    show code
    Query.prototype.hint = function (val) {
    -  if (!val) return this;
    -
    -  var hint = this.options.hint || (this.options.hint = {});
    -
    -  if ('Object' === val.constructor.name) {
    -    // must keep object keys in order so don't use Object.keys()
    -    for (var k in val) {
    -      hint[k] = val[k];
    -    }
    -  } else {
    -    throw new TypeError('Invalid hint. ' + val);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Model.find().hint({ indexA: 1, indexB: -1})

    Query#slaveOk(v)

    Sets the slaveOk option.

    show code
    Query.prototype.slaveOk = function (v) {
    -  this.options.slaveOk = arguments.length ? !!v : true;
    -  return this;
    -}

    Parameters:

    Returns:

    Example:

    - -
    new Query().slaveOk() // true
    -new Query().slaveOk(true)
    -new Query().slaveOk(false)

    Query#lean(v)

    Sets the lean option.

    show code
    Query.prototype.lean = function (v) {
    -  this.options.lean = arguments.length ? !!v : true;
    -  return this;
    -}

    Parameters:

    Returns:

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    - -

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    - -

    Example:

    - -
    new Query().lean() // true
    -new Query().lean(true)
    -new Query().lean(false)
    -
    -Model.find().lean().exec();
    -
    -var leanStream = Model.find().lean().stream();

    Query#tailable(v)

    Sets tailable option.

    show code
    Query.prototype.tailable = function (v) {
    -  this.options.tailable = arguments.length ? !!v : true;
    -  return this;
    -};

    Parameters:

    Example

    - -
    Kitten.find().tailable() &lt;== true
    -Kitten.find().tailable(true)
    -Kitten.find().tailable(false)

    Query#execFind(callback)

    Executes the query as a find() operation.

    show code
    Query.prototype.execFind = function (callback) {
    -  var model = this.model
    -    , promise = new Promise(callback);
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    promise.error(err);
    -    return this;
    -  }
    -
    -  // apply default schematype path selections
    -  this._applyPaths();
    -
    -  var self = this
    -    , castQuery = this._conditions
    -    , options = this._optionsForExec(model)
    -
    -  var fields = utils.clone(options.fields = this._fields);
    -
    -  model.collection.find(castQuery, options, function (err, cursor) {
    -    if (err) return promise.error(err);
    -    cursor.toArray(tick(cb));
    -  });
    -
    -  function cb (err, docs) {
    -    if (err) return promise.error(err);
    -
    -    if (true === options.lean)
    -      return promise.complete(docs);
    -
    -    var arr = []
    -      , count = docs.length;
    -
    -    if (!count) return promise.complete([]);
    -
    -    for (var i = 0, l = docs.length; i < l; i++) {
    -      arr[i] = new model(undefined, fields, true);
    -      arr[i].init(docs[i], self, function (err) {
    -        if (err) return promise.error(err);
    -        --count || promise.complete(arr);
    -      });
    -    }
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Query#findOne(callback)

    Executes the query as a findOne() operation.

    show code
    Query.prototype.findOne = function (callback) {
    -  this.op = 'findOne';
    -
    -  if (!callback) return this;
    -
    -  var model = this.model;
    -  var promise = new Promise(callback);
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    promise.error(err);
    -    return this;
    -  }
    -
    -  // apply default schematype path selections
    -  this._applyPaths();
    -
    -  var self = this
    -    , castQuery = this._conditions
    -    , options = this._optionsForExec(model)
    -
    -  var fields = utils.clone(options.fields = this._fields);
    -
    -  model.collection.findOne(castQuery, options, tick(function (err, doc) {
    -    if (err) return promise.error(err);
    -    if (!doc) return promise.complete(null);
    -
    -    if (true === options.lean) return promise.complete(doc);
    -
    -    var casted = new model(undefined, fields, true);
    -    casted.init(doc, self, function (err) {
    -      if (err) return promise.error(err);
    -      promise.complete(casted);
    -    });
    -  }));
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Kitten.where('color', 'white').findOne(function (err, kitten) {
    -  if (err) return handleError(err);
    -
    -  // kitten may be null if no document matched
    -  if (kitten) {
    -    ...
    -  }
    -})

    Query#count(callback)

    Exectues the query as a count() operation.

    show code
    Query.prototype.count = function (callback) {
    -  this.op = 'count';
    -  var model = this.model;
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    return callback(err);
    -  }
    -
    -  var castQuery = this._conditions;
    -  model.collection.count(castQuery, tick(callback));
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Kitten.where('color', 'black').count(function (err, count) {
    -  if (err) return handleError(err);
    -  console.log('there are %d black kittens', count);
    -})

    Query#distinct(field, callback)

    Executes this query as a distict() operation.

    show code
    Query.prototype.distinct = function (field, callback) {
    -  this.op = 'distinct';
    -  var model = this.model;
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    return callback(err);
    -  }
    -
    -  var castQuery = this._conditions;
    -  model.collection.distinct(field, castQuery, tick(callback));
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Query#update(doc, callback)

    Executes this query as an update() operation.

    show code
    Query.prototype.update = function update (doc, callback) {
    -  this.op = 'update';
    -  this._updateArg = doc;
    -
    -  var model = this.model
    -    , options = this._optionsForExec(model)
    -    , fn = 'function' == typeof callback
    -    , castedQuery
    -    , castedDoc
    -
    -  castedQuery = castQuery(this);
    -  if (castedQuery instanceof Error) {
    -    if (fn) {
    -      process.nextTick(callback.bind(null, castedQuery));
    -      return this;
    -    }
    -    throw castedQuery;
    -  }
    -
    -  castedDoc = castDoc(this);
    -  if (!castedDoc) {
    -    fn && process.nextTick(callback.bind(null, null, 0));
    -    return this;
    -  }
    -
    -  if (castedDoc instanceof Error) {
    -    if (fn) {
    -      process.nextTick(callback.bind(null, castedDoc));
    -      return this;
    -    }
    -    throw castedDoc;
    -  }
    -
    -  if (!fn) {
    -    delete options.safe;
    -  }
    -
    -  model.collection.update(castedQuery, castedDoc, options, tick(callback));
    -  return this;
    -};

    Parameters:

    Returns:

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    - -

    Example

    - -
    Model.update({..}, { title: 'remove words' }, ...)
    - -

    becomes

    - -
    Model.update({..}, { $set: { title: 'remove words' }}, ...)
    - -

    Note

    - -

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


    Query#_castUpdate(obj)

    Casts obj for an update command.

    show code
    Query.prototype._castUpdate = function _castUpdate (obj) {
    -  var ops = Object.keys(obj)
    -    , i = ops.length
    -    , ret = {}
    -    , hasKeys
    -    , val
    -
    -  while (i--) {
    -    var op = ops[i];
    -    if ('$' !== op[0]) {
    -      // fix up $set sugar
    -      if (!ret.$set) {
    -        if (obj.$set) {
    -          ret.$set = obj.$set;
    -        } else {
    -          ret.$set = {};
    -        }
    -      }
    -      ret.$set[op] = obj[op];
    -      ops.splice(i, 1);
    -      if (!~ops.indexOf('$set')) ops.push('$set');
    -    } else if ('$set' === op) {
    -      if (!ret.$set) {
    -        ret[op] = obj[op];
    -      }
    -    } else {
    -      ret[op] = obj[op];
    -    }
    -  }
    -
    -  // cast each value
    -  i = ops.length;
    -
    -  while (i--) {
    -    op = ops[i];
    -    val = ret[op];
    -    if ('Object' === val.constructor.name) {
    -      hasKeys |= this._walkUpdatePath(val, op);
    -    } else {
    -      var msg = 'Invalid atomic update value for ' + op + '. '
    -              + 'Expected an object, received ' + typeof val;
    -      throw new Error(msg);
    -    }
    -  }
    -
    -  return hasKeys && ret;
    -}

    Parameters:

    Returns:

    • <Object> obj after casting its values

    Query#_walkUpdatePath(obj, op, pref)

    Walk each path of obj and cast its values
    according to its schema.

    show code
    Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
    -  var strict = this.model.schema.options.strict
    -    , prefix = pref ? pref + '.' : ''
    -    , keys = Object.keys(obj)
    -    , i = keys.length
    -    , hasKeys = false
    -    , schema
    -    , key
    -    , val
    -
    -  while (i--) {
    -    key = keys[i];
    -    val = obj[key];
    -
    -    if (val && 'Object' === val.constructor.name) {
    -      // watch for embedded doc schemas
    -      schema = this._getSchema(prefix + key);
    -      if (schema && schema.caster && op in castOps) {
    -        // embedded doc schema
    -
    -        if (strict && !schema) {
    -          // path is not in our strict schema
    -          if ('throw' == strict) {
    -            throw new Error('Field `' + key + '` is not in schema.');
    -          } else {
    -            // ignore paths not specified in schema
    -            delete obj[key];
    -          }
    -        } else {
    -          hasKeys = true;
    -          if ('$each' in val) {
    -            obj[key] = {
    -                $each: this._castUpdateVal(schema, val.$each, op)
    -            }
    -          } else {
    -            obj[key] = this._castUpdateVal(schema, val, op);
    -          }
    -        }
    -      } else {
    -        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
    -      }
    -    } else {
    -      schema = '$each' === key
    -        ? this._getSchema(pref)
    -        : this._getSchema(prefix + key);
    -
    -      var skip = strict &&
    -                 !schema &&
    -                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
    -
    -      if (skip) {
    -        if ('throw' == strict) {
    -          throw new Error('Field `' + prefix + key + '` is not in schema.');
    -        } else {
    -          delete obj[key];
    -        }
    -      } else {
    -        hasKeys = true;
    -        obj[key] = this._castUpdateVal(schema, val, op, key);
    -      }
    -    }
    -  }
    -  return hasKeys;
    -}

    Parameters:

    • obj <Object> - part of a query
    • op <String> - the atomic operator ($pull, $set, etc)
    • pref <String> - path prefix (internal only)

    Returns:

    • <Bool> true if this path has keys to update

    Query#_castUpdateVal(schema, val, op, [$conditional])

    Casts val according to schema and atomic op.

    show code
    Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
    -  if (!schema) {
    -    // non-existing schema path
    -    return op in numberOps
    -      ? Number(val)
    -      : val
    -  }
    -
    -  if (schema.caster && op in castOps &&
    -    ('Object' === val.constructor.name || Array.isArray(val))) {
    -    // Cast values for ops that add data to MongoDB.
    -    // Ensures embedded documents get ObjectIds etc.
    -    var tmp = schema.cast(val);
    -
    -    if (Array.isArray(val)) {
    -      val = tmp;
    -    } else {
    -      val = tmp[0];
    -    }
    -  }
    -
    -  if (op in numberOps) return Number(val);
    -  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
    -  return schema.castForQuery(val)
    -}

    Parameters:


    Query#_getSchema(path)

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    show code
    Query.prototype._getSchema = function _getSchema (path) {
    -  var schema = this.model.schema
    -    , pathschema = schema.path(path);
    -
    -  if (pathschema)
    -    return pathschema;
    -
    -  // look for arrays
    -  return (function search (parts, schema) {
    -    var p = parts.length + 1
    -      , foundschema
    -      , trypath
    -
    -    while (p--) {
    -      trypath = parts.slice(0, p).join('.');
    -      foundschema = schema.path(trypath);
    -      if (foundschema) {
    -        if (foundschema.caster) {
    -
    -          // array of Mixed?
    -          if (foundschema.caster instanceof Types.Mixed) {
    -            return foundschema.caster;
    -          }
    -
    -          // Now that we found the array, we need to check if there
    -          // are remaining document paths to look up for casting.
    -          // Also we need to handle array.$.path since schema.path
    -          // doesn't work for that.
    -          if (p !== parts.length) {
    -            if ('$' === parts[p]) {
    -              // comments.$.comments.$.title
    -              return search(parts.slice(p+1), foundschema.schema);
    -            } else {
    -              // this is the last path of the selector
    -              return search(parts.slice(p), foundschema.schema);
    -            }
    -          }
    -        }
    -        return foundschema;
    -      }
    -    }
    -  })(path.split('.'), schema)
    -}

    Parameters:


    Query#remove(callback)

    Executes this query as a remove() operation.

    show code
    Query.prototype.remove = function (callback) {
    -  this.op = 'remove';
    -
    -  var model = this.model
    -    , options = this._optionsForExec(model)
    -    , cb = 'function' == typeof callback
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    if (cb) return callback(err);
    -    throw err;
    -  }
    -
    -  if (!cb) {
    -    delete options.safe;
    -  }
    -
    -  var castQuery = this._conditions;
    -  model.collection.remove(castQuery, options, tick(callback));
    -  return this;
    -};

    Parameters:

    Example

    - -
    Cassette.where('artist').equals('Anne Murray').remove(callback)

    Query#findOneAndUpdate([query], [doc], [options], [callback])

    Issues a mongodb findAndModify update command.

    show code
    Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
    -  this.op = 'findOneAndUpdate';
    -
    -  switch (arguments.length) {
    -    case 3:
    -      if ('function' == typeof options)
    -        callback = options, options = {};
    -      break;
    -    case 2:
    -      if ('function' == typeof doc) {
    -        callback = doc;
    -        doc = query;
    -        query = undefined;
    -      }
    -      options = undefined;
    -      break;
    -    case 1:
    -      if ('function' == typeof query) {
    -        callback = query;
    -        query = options = doc = undefined;
    -      } else {
    -        doc = query;
    -        query = options = undefined;
    -      }
    -  }
    -
    -  // apply query
    -  if (query) {
    -    if ('Object' === query.constructor.name) {
    -      merge(this._conditions, query);
    -    } else if (query instanceof Query) {
    -      merge(this._conditions, query._conditions);
    -    } else if (query instanceof Document) {
    -      merge(this._conditions, query.toObject());
    -    }
    -  }
    -
    -  // apply doc
    -  if (doc) {
    -    merge(this._updateArg, doc);
    -  }
    -
    -  // apply options
    -  options && this.setOptions(options);
    -
    -  if (!callback) return this;
    -
    -  return this._findAndModify('update', callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Available options

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    - -

    Examples

    - -
    query.findOneAndUpdate(conditions, update, options, callback) // executes
    -query.findOneAndUpdate(conditions, update, options)  // returns Query
    -query.findOneAndUpdate(conditions, update, callback) // executes
    -query.findOneAndUpdate(conditions, update)           // returns Query
    -query.findOneAndUpdate(callback)                     // executes
    -query.findOneAndUpdate()                             // returns Query

    Query#findOneAndRemove([conditions], [options], [callback])

    Issues a mongodb findAndModify remove command.

    show code
    Query.prototype.findOneAndRemove = function (conditions, options, callback) {
    -  this.op = 'findOneAndRemove';
    -
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = undefined;
    -  } else if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = undefined;
    -  }
    -
    -  // apply conditions
    -  if (conditions) {
    -    if ('Object' === conditions.constructor.name) {
    -      merge(this._conditions, conditions);
    -    } else if (conditions instanceof Query) {
    -      merge(this._conditions, conditions._conditions);
    -    } else if (conditions instanceof Document) {
    -      merge(this._conditions, conditions.toObject());
    -    }
    -  }
    -
    -  // apply options
    -  options && this.setOptions(options);
    -
    -  if (!callback) return this;
    -
    -  return this._findAndModify('remove', callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    - -

    Available options

    - -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    - -

    Examples

    - -
    A.where().findOneAndRemove(conditions, options, callback) // executes
    -A.where().findOneAndRemove(conditions, options)  // return Query
    -A.where().findOneAndRemove(conditions, callback) // executes
    -A.where().findOneAndRemove(conditions) // returns Query
    -A.where().findOneAndRemove(callback)   // executes
    -A.where().findOneAndRemove()           // returns Query

    Query#_findAndModify(type, callback)

    _findAndModify

    show code
    Query.prototype._findAndModify = function (type, callback) {
    -  var model = this.model
    -    , promise = new Promise(callback)
    -    , self = this
    -    , castedQuery
    -    , castedDoc
    -    , fields
    -    , sort
    -    , opts
    -
    -  castedQuery = castQuery(this);
    -  if (castedQuery instanceof Error) {
    -    process.nextTick(promise.error.bind(promise, castedQuery));
    -    return promise;
    -  }
    -
    -  opts = this._optionsForExec(model);
    -
    -  if ('remove' == type) {
    -    opts.remove = true;
    -  } else {
    -    if (!('new' in opts)) opts.new = true;
    -    if (!('upsert' in opts)) opts.upsert = false;
    -
    -    castedDoc = castDoc(this);
    -    if (!castedDoc) {
    -      if (opts.upsert) {
    -        // still need to do the upsert to empty doc
    -        castedDoc = { $set: {} };
    -      } else {
    -        return this.findOne(callback);
    -      }
    -    } else if (castedDoc instanceof Error) {
    -      process.nextTick(promise.error.bind(promise, castedDoc));
    -      return promise;
    -    }
    -  }
    -
    -  if (this._fields) {
    -    fields = utils.clone(opts.fields = this._fields);
    -  }
    -
    -  // the driver needs a default
    -  sort = opts.sort || [];
    -
    -  model
    -  .collection
    -  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
    -    if (err) return promise.error(err);
    -    if (!doc) return promise.complete(null);
    -
    -    if (true === opts.lean) {
    -      return promise.complete(doc);
    -    }
    -
    -    var casted = new model(undefined, fields, true);
    -    casted.init(doc, self, function (err) {
    -      if (err) return promise.error(err);
    -      promise.complete(casted);
    -    });
    -  }));
    -
    -  return promise;
    -}

    Parameters:


    Query#populate(path, [fields], [model], [conditions], [options])

    Specifies paths which should be populated with other documents.

    show code
    Query.prototype.populate = function (path, fields, model, conditions, options) {
    -  if ('string' !== typeof model) {
    -    options = conditions;
    -    conditions = model;
    -    model = undefined;
    -  }
    -  // The order of fields/conditions args is opposite Model.find but
    -  // necessary to keep backward compatibility (fields could be
    -  // an array, string, or object literal).
    -  this.options.populate[path] =
    -    new PopulateOptions(fields, conditions, options, model);
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    - -

    Example:

    - -
    Kitten.findOne().populate('owner').exec(function (err, kitten) {
    -  console.log(kitten.owner.name) // Max
    -})

    Query#stream()

    Returns a stream interface

    show code
    Query.prototype.stream = function stream () {
    -  return new QueryStream(this);
    -}
    -
    -// helpers

    Returns:

    Example

    - -
    // follows the nodejs stream api
    -Thing.find({ name: /^hello/ }).stream().pipe(res)
    -
    -// manual streaming
    -var stream = Thing.find({ name: /^hello/ }).stream();
    -
    -stream.on('data', function (doc) {
    -  // do something with the mongoose document
    -}).on('error', function (err) {
    -  // handle the error
    -}).on('close', function () {
    -  // the stream is closed
    -});

    Query#within

    Syntax sugar for expressive queries.

    - -

    Example

    - -
    query.within.box()
    -query.within.center()

    Returns:


  • querystream.js

    QueryStream(query)

    Provides a ReadStream interface for Queries.

    show code
    function QueryStream (query) {
    -  Stream.call(this);
    -
    -  this.query = query;
    -  this.readable = true;
    -  this.paused = false;
    -  this._cursor = null;
    -  this._destroyed = null;
    -  this._fields = null;
    -  this._ticks = 0;
    -  this._inline = T_INIT;
    -
    -  // give time to hook up events
    -  var self = this;
    -  process.nextTick(function () {
    -    self._init();
    -  });
    -}

    Parameters:

    Inherits:

    Events:

    • data: emits a single Mongoose document

    • error: emits when an error occurs during streaming. This will emit before the close event.

    • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

    var stream = Model.find().stream();
    -
    -stream.on('data', function (doc) {
    -  // do something with the mongoose document
    -}).on('error', function (err) {
    -  // handle the error
    -}).on('close', function () {
    -  // the stream is closed
    -});
    - -

    The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

    - -
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

    QueryStream#_init()

    Initializes the query.

    show code
    QueryStream.prototype._init = function () {
    -  if (this._destroyed) return;
    -
    -  var query = this.query
    -    , model = query.model
    -    , options = query._optionsForExec(model)
    -    , self = this
    -
    -  try {
    -    query.cast(model);
    -  } catch (err) {
    -    return self.destroy(err);
    -  }
    -
    -  self._fields = utils.clone(options.fields = query._fields);
    -
    -  model.collection.find(query._conditions, options, function (err, cursor) {
    -    if (err) return self.destroy(err);
    -    self._cursor = cursor;
    -    self._next();
    -  });
    -}

    QueryStream#_next()

    Trampoline for pulling the next doc from cursor.

    show code
    QueryStream.prototype._next = function () {
    -  // avoid stack overflows with large result sets.
    -  // trampoline instead of recursion.
    -  var fn;
    -  while (fn = this.__next()) fn.call(this);
    -}

    QueryStream#__next()

    Pulls the next doc from the cursor.

    show code
    QueryStream.prototype.__next = function () {
    -  if (this.paused || this._destroyed) return;
    -
    -  var self = this;
    -  self._inline = T_INIT;
    -
    -  self._cursor.nextObject(function (err, doc) {
    -    self._onNextObject(err, doc);
    -  });
    -
    -  // if onNextObject() was already called in this tick
    -  // return ourselves to the trampoline.
    -  if (T_CONT === this._inline) {
    -    return this.__next;
    -  } else {
    -    // onNextObject() hasn't fired yet. tell onNextObject
    -    // that its ok to call _next b/c we are not within
    -    // the trampoline anymore.
    -    this._inline = T_IDLE;
    -  }
    -}

    QueryStream#_onNextObject(err, doc)

    Transforms raw docs returned from the cursor into a model instance.

    show code
    QueryStream.prototype._onNextObject = function (err, doc) {
    -  if (err) return this.destroy(err);
    -
    -  // when doc is null we hit the end of the cursor
    -  if (!doc) {
    -    return this.destroy();
    -  }
    -
    -  if (this.query.options && this.query.options.lean === true)  {
    -    this.emit('data', doc);
    -    this._next();
    -    return;
    -  }
    -
    -  var instance = new this.query.model(undefined, this._fields);
    -
    -  // skip _id for pre-init hooks
    -  delete instance._doc._id;
    -
    -  var self = this;
    -  instance.init(doc, this.query, function (err) {
    -    if (err) return self.destroy(err);
    -    self.emit('data', instance);
    -
    -    // trampoline management
    -    if (T_IDLE === self._inline) {
    -      // no longer in trampoline. restart it.
    -      self._next();
    -    } else
    -      // in a trampoline. tell __next that its
    -      // ok to continue jumping.
    -      self._inline = T_CONT;
    -  });
    -}

    Parameters:


    QueryStream#pause()

    Pauses this stream.

    show code
    QueryStream.prototype.pause = function () {
    -  this.paused = true;
    -}

    QueryStream#resume()

    Resumes this stream.

    show code
    QueryStream.prototype.resume = function () {
    -  this.paused = false;
    -  this._next();
    -}

    QueryStream#destroy([err])

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    show code
    QueryStream.prototype.destroy = function (err) {
    -  if (this._destroyed) return;
    -  this._destroyed = true;
    -  this.readable = false;
    -
    -  if (this._cursor) {
    -    this._cursor.close();
    -  }
    -
    -  if (err) {
    -    this.emit('error', err);
    -  }
    -
    -  this.emit('close');
    -}

    Parameters:


    QueryStream#pipe()

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    See:

    Example:

    - -
    query.stream().pipe(writeStream [, options])
    - -

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    - -
    var format = new ArrayFormatter;
    -Events.find().stream().pipe(format).pipe(res);
    - -

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


    QueryStream#paused

    Flag stating whether or not this stream is paused.


    QueryStream#readable

    Flag stating whether or not this stream is readable.


  • schema/array.js

    SchemaArray(key, cast, options)

    Array SchemaType constructor

    show code
    function SchemaArray (key, cast, options) {
    -  if (cast) {
    -    var castOptions = {};
    -
    -    if ('Object' === cast.constructor.name) {
    -      if (cast.type) {
    -        // support { type: Woot }
    -        castOptions = cast;
    -        cast = cast.type;
    -        delete castOptions.type;
    -      } else {
    -        cast = Mixed;
    -      }
    -    }
    -
    -    var caster = cast.name in Types ? Types[cast.name] : cast;
    -    this.casterConstructor = caster;
    -    this.caster = new caster(null, castOptions);
    -  }
    -
    -  SchemaType.call(this, key, options);
    -
    -  var self = this
    -    , defaultArr
    -    , fn;
    -
    -  if (this.defaultValue) {
    -    defaultArr = this.defaultValue;
    -    fn = 'function' == typeof defaultArr;
    -  }
    -
    -  this.default(function(){
    -    var arr = fn ? defaultArr() : defaultArr || [];
    -    return new MongooseArray(arr, self.path, this);
    -  });
    -};

    Parameters:

    Inherits:


    SchemaArray#checkRequired(value)

    Check required

    show code
    SchemaArray.prototype.checkRequired = function (value) {
    -  return !!(value && value.length);
    -};

    Parameters:


    SchemaArray#applyGetters(value, scope)

    Overrides the getters application for the population special-case

    show code
    SchemaArray.prototype.applyGetters = function (value, scope) {
    -  if (this.caster.options && this.caster.options.ref) {
    -    // means the object id was populated
    -    return value;
    -  }
    -
    -  return SchemaType.prototype.applyGetters.call(this, value, scope);
    -};

    Parameters:


    SchemaArray#cast(value, doc, init)

    Casts contents

    show code
    SchemaArray.prototype.cast = function (value, doc, init) {
    -  if (Array.isArray(value)) {
    -    if (!(value instanceof MongooseArray)) {
    -      value = new MongooseArray(value, this.path, doc);
    -    }
    -
    -    if (this.caster) {
    -      try {
    -        for (var i = 0, l = value.length; i < l; i++) {
    -          value[i] = this.caster.cast(value[i], doc, init);
    -        }
    -      } catch (e) {
    -        // rethrow
    -        throw new CastError(e.type, value);
    -      }
    -    }
    -
    -    return value;
    -  } else {
    -    return this.cast([value], doc, init);
    -  }
    -};

    Parameters:

    • value <Object>
    • doc <Document> document that triggers the casting
    • init <Boolean> whether this is an initialization cast

    SchemaArray#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaArray.prototype.castForQuery = function ($conditional, value) {
    -  var handler
    -    , val;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Array.");
    -    val = handler.call(this, value);
    -  } else {
    -    val = $conditional;
    -    var proto = this.casterConstructor.prototype;
    -    var method = proto.castForQuery || proto.cast;
    -    if (Array.isArray(val)) {
    -      val = val.map(function (v) {
    -        if (method) v = method.call(proto, v);
    -        return isMongooseObject(v)
    -          ? v.toObject()
    -          : v;
    -      });
    -    } else if (method) {
    -      val = method.call(proto, val);
    -    }
    -  }
    -  return val && isMongooseObject(val)
    -    ? val.toObject()
    -    : val;
    -};

    Parameters:


  • schema/boolean.js

    SchemaBoolean(path, options)

    Boolean SchemaType constructor.

    show code
    function SchemaBoolean (path, options) {
    -  SchemaType.call(this, path, options);
    -};

    Parameters:

    Inherits:


    SchemaBoolean#checkRequired()

    Required validator

    show code
    SchemaBoolean.prototype.checkRequired = function (value) {
    -  return value === true || value === false;
    -};

    SchemaBoolean#cast(value)

    Casts to boolean

    show code
    SchemaBoolean.prototype.cast = function (value) {
    -  if (value === null) return value;
    -  if (value === '0') return false;
    -  return !!value;
    -};

    Parameters:


    SchemaBoolean#castForQuery($conditional, val)

    Casts contents for queries.

    show code
    SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (2 === arguments.length) {
    -    handler = SchemaBoolean.$conditionalHandlers[$conditional];
    -
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Boolean.");
    -
    -    return handler.call(this, val);
    -  }
    -
    -  return this.cast($conditional);
    -};

    Parameters:


  • schema/buffer.js

    SchemaBuffer(key, cast)

    Buffer SchemaType constructor

    show code
    function SchemaBuffer (key, options) {
    -  SchemaType.call(this, key, options, 'Buffer');
    -};

    Parameters:

    Inherits:


    SchemaBuffer#checkRequired()

    Check required

    show code
    SchemaBuffer.prototype.checkRequired = function (value) {
    -  return !!(value && value.length);
    -};

    SchemaBuffer#cast(value, doc, init)

    Casts contents

    show code
    SchemaBuffer.prototype.cast = function (value, doc, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  if (Buffer.isBuffer(value)) {
    -    if (!(value instanceof MongooseBuffer)) {
    -      value = new MongooseBuffer(value, [this.path, doc]);
    -    }
    -
    -    return value;
    -  } else if (value instanceof Binary) {
    -    return new MongooseBuffer(value.value(true), [this.path, doc]);
    -  }
    -
    -  if ('string' === typeof value || Array.isArray(value)) {
    -    return new MongooseBuffer(value, [this.path, doc]);
    -  }
    -
    -  throw new CastError('buffer', value);
    -};

    Parameters:


    SchemaBuffer#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Buffer.");
    -    return handler.call(this, val);
    -  } else {
    -    val = $conditional;
    -    return this.cast(val).toObject();
    -  }
    -};

    Parameters:


  • schema/date.js

    SchemaDate(key, options)

    Date SchemaType constructor.

    show code
    function SchemaDate (key, options) {
    -  SchemaType.call(this, key, options);
    -};

    Parameters:

    Inherits:


    SchemaDate#checkRequired()

    Required validator for date

    show code
    SchemaDate.prototype.checkRequired = function (value) {
    -  return value instanceof Date;
    -};

    SchemaDate#cast(value)

    Casts to date

    show code
    SchemaDate.prototype.cast = function (value) {
    -  if (value === null || value === '')
    -    return null;
    -
    -  if (value instanceof Date)
    -    return value;
    -
    -  var date;
    -
    -  // support for timestamps
    -  if (value instanceof Number || 'number' == typeof value 
    -      || String(value) == Number(value))
    -    date = new Date(Number(value));
    -
    -  // support for date strings
    -  else if (value.toString)
    -    date = new Date(value.toString());
    -
    -  if (date.toString() != 'Invalid Date')
    -    return date;
    -
    -  throw new CastError('date', value);
    -};

    Parameters:


    SchemaDate#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaDate.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -
    -  if (2 !== arguments.length) {
    -    return this.cast($conditional);
    -  }
    -
    -  handler = this.$conditionalHandlers[$conditional];
    -
    -  if (!handler) {
    -    throw new Error("Can't use " + $conditional + " with Date.");
    -  }
    -
    -  return handler.call(this, val);
    -};

    Parameters:


  • schema/documentarray.js

    DocumentArray(key, schema, options)

    SubdocsArray SchemaType constructor

    show code
    function DocumentArray (key, schema, options) {
    -  // compile an embedded document for this schema
    -  // TODO Move this into parent model compilation for performance improvement?
    -  function EmbeddedDocument () {
    -    Subdocument.apply(this, arguments);
    -  };
    -
    -  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
    -  EmbeddedDocument.prototype._setSchema(schema);
    -  EmbeddedDocument.schema = schema;
    -
    -  // apply methods
    -  for (var i in schema.methods) {
    -    EmbeddedDocument.prototype[i] = schema.methods[i];
    -  }
    -
    -  // apply statics
    -  for (var i in schema.statics)
    -    EmbeddedDocument[i] = schema.statics[i];
    -
    -  EmbeddedDocument.options = options;
    -  this.schema = schema;
    -
    -  ArrayType.call(this, key, EmbeddedDocument, options);
    -
    -  this.schema = schema;
    -  var path = this.path;
    -  var fn = this.defaultValue;
    -
    -  this.default(function(){
    -    var arr = fn.call(this);
    -    if (!Array.isArray(arr)) arr = [arr];
    -    return new MongooseDocumentArray(arr, path, this);
    -  });
    -};

    Parameters:

    Inherits:


    DocumentArray#doValidate()

    Performs local validations first, then validations on each embedded doc

    show code
    DocumentArray.prototype.doValidate = function (array, fn, scope) {
    -  var self = this;
    -  SchemaType.prototype.doValidate.call(this, array, function(err){
    -    if (err) return fn(err);
    -
    -    var count = array && array.length
    -      , error = false;
    -
    -    if (!count) return fn();
    -
    -    array.forEach(function(doc, index){
    -      doc.validate(function(err){
    -        if (err && !error){
    -          // rewrite they key
    -          err.key = self.key + '.' + index + '.' + err.key;
    -          fn(err);
    -          error = true;
    -        } else {
    -          --count || fn();
    -        }
    -      });
    -    });
    -  }, scope);
    -};

    DocumentArray#cast(value, document)

    Casts contents

    show code
    DocumentArray.prototype.cast = function (value, doc, init, prev) {
    -  var subdoc
    -    , i
    -
    -  if (Array.isArray(value)) {
    -    if (!(value instanceof MongooseDocumentArray)) {
    -      value = new MongooseDocumentArray(value, this.path, doc);
    -    }
    -
    -    i = value.length;
    -
    -    while (i--) {
    -      if (!(value[i] instanceof Subdocument)) {
    -        if (init) {
    -          subdoc = new this.casterConstructor(null, value, true);
    -          value[i] = subdoc.init(value[i]);
    -        } else {
    -          if (prev && (subdoc = prev.id(value[i]._id))) {
    -            // handle resetting doc with existing id but differing data
    -            // doc.array = [{ doc: 'val' }]
    -            subdoc.set(value[i]);
    -          } else {
    -            subdoc = new this.casterConstructor(value[i], value);
    -          }
    -
    -          // if set() is hooked it will have no return value
    -          // see gh-746
    -          value[i] = subdoc;
    -        }
    -      }
    -    }
    -
    -    return value;
    -  } else {
    -    return this.cast([value], doc, init, prev);
    -  }
    -
    -  throw new CastError('documentarray', value);
    -};

    Parameters:


  • schema/mixed.js

    Mixed(path, options)

    Mixed SchemaType constructor.

    show code
    function Mixed (path, options) {
    -  // make sure empty array defaults are handled
    -  if (options &&
    -      options.default &&
    -      Array.isArray(options.default) &&
    -      0 === options.default.length) {
    -    options.default = Array;
    -  }
    -
    -  SchemaType.call(this, path, options);
    -};

    Parameters:

    Inherits:


    Mixed#checkRequired()

    Required validator

    show code
    Mixed.prototype.checkRequired = function (val) {
    -  return true;
    -};

    Mixed#cast(value)

    Casts val for Mixed.

    show code
    Mixed.prototype.cast = function (val) {
    -  return val;
    -};

    Parameters:

    this is a no-op


    Mixed#castForQuery($cond, [val])

    Casts contents for queries.

    show code
    Mixed.prototype.castForQuery = function ($cond, val) {
    -  if (arguments.length === 2) return val;
    -  return $cond;
    -};

    Parameters:


  • schema/number.js

    SchemaNumber(key, options)

    Number SchemaType constructor.

    show code
    function SchemaNumber (key, options) {
    -  SchemaType.call(this, key, options, 'Number');
    -};

    Parameters:

    Inherits:


    SchemaNumber#checkRequired()

    Required validator for number

    show code
    SchemaNumber.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return typeof value == 'number' || value instanceof Number;
    -  }
    -};

    SchemaNumber#min(value, message)

    Sets a maximum number validator.

    show code
    SchemaNumber.prototype.min = function (value, message) {
    -  if (this.minValidator)
    -    this.validators = this.validators.filter(function(v){
    -      return v[1] != 'min';
    -    });
    -  if (value != null)
    -    this.validators.push([function(v){
    -      return v === null || v >= value;
    -    }, 'min']);
    -  return this;
    -};

    Parameters:

    Example:

    - -
    var s = new Schema({ n: { type: Number, min: 10 })
    -var M = db.model('M', s)
    -var m = new M({ n: 9 })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.n = 10;
    -  m.save() // success
    -})

    SchemaNumber#max(maximum, message)

    Sets a maximum number validator.

    show code
    SchemaNumber.prototype.max = function (value, message) {
    -  if (this.maxValidator)
    -    this.validators = this.validators.filter(function(v){
    -      return v[1] != 'max';
    -    });
    -  if (value != null)
    -    this.validators.push([this.maxValidator = function(v){
    -      return v === null || v <= value;
    -    }, 'max']);
    -  return this;
    -};

    Parameters:

    Example:

    - -
    var s = new Schema({ n: { type: Number, max: 10 })
    -var M = db.model('M', s)
    -var m = new M({ n: 11 })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.n = 10;
    -  m.save() // success
    -})

    SchemaNumber#cast(value, doc, init)

    Casts to number

    show code
    SchemaNumber.prototype.cast = function (value, doc, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  if (!isNaN(value)){
    -    if (null === value) return value;
    -    if ('' === value) return null;
    -    if ('string' == typeof value) value = Number(value);
    -    if (value instanceof Number) return value
    -    if ('number' == typeof value) return value;
    -    if (value.toString && !Array.isArray(value) &&
    -        value.toString() == Number(value)) {
    -      return new Number(value)
    -    }
    -  }
    -
    -  throw new CastError('number', value);
    -};

    Parameters:


    SchemaNumber#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaNumber.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Number.");
    -    return handler.call(this, val);
    -  } else {
    -    val = this.cast($conditional);
    -    return val == null ? val : val
    -  }
    -};

    Parameters:


  • schema/objectid.js

    ObjectId(key, options)

    ObjectId SchemaType constructor.

    show code
    function ObjectId (key, options) {
    -  SchemaType.call(this, key, options, 'ObjectID');
    -};

    Parameters:

    Inherits:


    ObjectId#checkRequired()

    Check required

    show code
    ObjectId.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return value instanceof oid;
    -  }
    -};

    ObjectId#cast(value, scope, init)

    Casts to ObjectId

    show code
    ObjectId.prototype.cast = function (value, scope, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  if (value === null) return value;
    -
    -  if (value instanceof oid)
    -    return value;
    -
    -  if (value._id && value._id instanceof oid)
    -    return value._id;
    -
    -  if (value.toString)
    -    return oid.fromString(value.toString());
    -
    -  throw new CastError('object id', value);
    -};

    Parameters:


    ObjectId#castForQuery($conditional, [val])

    Casts contents for queries.

    show code
    ObjectId.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with ObjectId.");
    -    return handler.call(this, val);
    -  } else {
    -    return this.cast($conditional);
    -  }
    -};

    Parameters:


    ObjectId#auto(turnOn)

    Adds an auto-generated ObjectId default if turnOn is true.

    show code
    ObjectId.prototype.auto = function (turnOn) {
    -  if (turnOn) {
    -    this.default(defaultId);
    -    this.set(resetId)
    -  }
    -};

    Parameters:

    • turnOn <Boolean> auto generated ObjectId defaults

  • schema/string.js

    SchemaString(key, options)

    String SchemaType constructor.

    show code
    function SchemaString (key, options) {
    -  this.enumValues = [];
    -  this.regExp = null;
    -  SchemaType.call(this, key, options, 'String');
    -};

    Parameters:

    Inherits:


    SchemaString#enum([args...])

    Adds enumeration values and a coinciding validator.

    show code
    SchemaString.prototype.enum = function () {
    -  var len = arguments.length;
    -  if (!len || undefined === arguments[0] || false === arguments[0]) {
    -    if (this.enumValidator){
    -      this.enumValidator = false;
    -      this.validators = this.validators.filter(function(v){
    -        return v[1] != 'enum';
    -      });
    -    }
    -    return;
    -  }
    -
    -  for (var i = 0; i < len; i++) {
    -    if (undefined !== arguments[i]) {
    -      this.enumValues.push(this.cast(arguments[i]));
    -    }
    -  }
    -
    -  if (!this.enumValidator) {
    -    var values = this.enumValues;
    -    this.enumValidator = function(v){
    -      return undefined === v || ~values.indexOf(v);
    -    };
    -    this.validators.push([this.enumValidator, 'enum']);
    -  }
    -};

    Parameters:

    • [args...] <String> enumeration values

    Example:

    - -
    var states = 'opening open closing closed'.split(' ')
    -var s = new Schema({ state: { type: String, enum: states })
    -var M = db.model('M', s)
    -var m = new M({ state: 'invalid' })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.state = 'open'
    -  m.save() // success
    -})

    SchemaString#lowercase()

    Adds a lowercase setter.

    show code
    SchemaString.prototype.lowercase = function () {
    -  return this.set(function (v) {
    -    return v.toLowerCase();
    -  });
    -};

    Example:

    - -
    var s = new Schema({ email: { type: String, lowercase: true }})
    -var M = db.model('M', s);
    -var m = new M({ email: 'SomeEmail@example.COM' });
    -console.log(m.email) // someemail@example.com
    -

    SchemaString#uppercase()

    Adds an uppercase setter.

    show code
    SchemaString.prototype.uppercase = function () {
    -  return this.set(function (v) {
    -    return v.toUpperCase();
    -  });
    -};

    Example:

    - -
    var s = new Schema({ caps: { type: String, uppercase: true }})
    -var M = db.model('M', s);
    -var m = new M({ caps: 'an example' });
    -console.log(m.caps) // AN EXAMPLE

    SchemaString#trim()

    Adds a trim setter.

    show code
    SchemaString.prototype.trim = function () {
    -  return this.set(function (v) {
    -    return v.trim();
    -  });
    -};

    The string value will be trimmed when set.

    - -

    Example:

    - -
    var s = new Schema({ name: { type: String, trim: true }})
    -var M = db.model('M', s)
    -var string = ' some name '
    -console.log(string.length) // 11
    -var m = new M({ name: string })
    -console.log(m.name.length) // 9

    SchemaString#match(regExp)

    Sets a regexp validator.

    show code
    SchemaString.prototype.match = function match (regExp) {
    -  this.validators.push([function(v){
    -    return null != v && '' !== v
    -      ? regExp.test(v)
    -      : true
    -  }, 'regexp']);
    -};

    Parameters:

    • regExp <RegExp> regular expression to test against

    Any value that does not pass regExp.test(val) will fail validation.

    - -

    Example:

    - -
    var s = new Schema({ name: { type: String, match: /^a/ }})
    -var M = db.model('M', s)
    -var m = new M({ name: 'invalid' })
    -m.validate(function (err) {
    -  console.error(err) // validation error
    -  m.name = 'apples'
    -  m.validate(function (err) {
    -    assert.ok(err) // success
    -  })
    -})

    SchemaString#checkRequired(value)

    Check required

    show code
    SchemaString.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return (value instanceof String || typeof value == 'string') && value.length;
    -  }
    -};

    Parameters:


    SchemaString#cast()

    Casts to String

    show code
    SchemaString.prototype.cast = function (value, scope, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -  if (value === null) return value;
    -  if ('undefined' !== typeof value && value.toString) return value.toString();
    -  throw new CastError('string', value);
    -};

    SchemaString#castForQuery($conditional, [val])

    Casts contents for queries.

    show code
    SchemaString.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with String.");
    -    return handler.call(this, val);
    -  } else {
    -    val = $conditional;
    -    if (val instanceof RegExp) return val;
    -    return this.cast(val);
    -  }
    -};

    Parameters:


  • schema.js

    Schema(definition)

    Schema constructor.

    show code
    function Schema (obj, options) {
    -  if (!(this instanceof Schema))
    -    return new Schema(obj, options);
    -
    -  this.paths = {};
    -  this.subpaths = {};
    -  this.virtuals = {};
    -  this.nested = {};
    -  this.inherits = {};
    -  this.callQueue = [];
    -  this._indexes = [];
    -  this.methods = {};
    -  this.statics = {};
    -  this.tree = {};
    -  this._requiredpaths = undefined;
    -
    -  // set options
    -  this.options = utils.options({
    -      safe: true
    -    , strict: true
    -    , capped: false // { size, max, autoIndexId }
    -    , versionKey: '__v'
    -    , minimize: true
    -    , autoIndex: true
    -    , shardKey: null
    -    // the following are only applied at construction time
    -    , noId: false // deprecated, use { _id: false }
    -    , _id: true
    -    , noVirtualId: false // deprecated, use { id: false }
    -    , id: true
    -  }, options);
    -
    -  // build paths
    -  if (obj) {
    -    this.add(obj);
    -  }
    -
    -  // ensure the documents get an auto _id unless disabled
    -  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
    -  if (auto_id) {
    -    this.add({ _id: {type: Schema.ObjectId, auto: true} });
    -  }
    -
    -  // ensure the documents receive an id getter unless disabled
    -  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
    -  if (autoid) {
    -    this.virtual('id').get(idGetter);
    -  }
    -
    -  // versioning not directly added to schema b/c we only want
    -  // it in the top level document, not embedded ones.
    -};

    Parameters:

    Events:

    • init: Emitted after the schema is compiled into a Model.

    Example:

    - -
    var child = new Schema({ name: String });
    -var schema = new Schema({ name: String, age: Number, children: [child] });
    -var Tree = mongoose.model('Tree', schema);
    -
    -// setting schema options
    -new Schema({ name: String }, { _id: false, autoIndex: false })
    - -

    Options:

    - -
      -
    • safe: bool - defaults to true.
    • -
    • strict: bool - defaults to true
    • -
    • capped: bool - defaults to false
    • -
    • versionKey: bool - defaults to "__v"
    • -
    • shardKey: bool - defaults to null
    • -
    • autoIndex: bool - defaults to true
    • -
    • _id: bool - defaults to true
    • -
    • id: bool - defaults to true
    • -
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • -
    - -

    Note:

    - -

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


    Schema#add(obj, prefix)

    Adds key path / schema type pairs to this schema.

    show code
    Schema.prototype.add = function add (obj, prefix) {
    -  prefix = prefix || '';
    -  for (var i in obj) {
    -    if (null == obj[i]) {
    -      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
    -    }
    -
    -    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
    -      if (Object.keys(obj[i]).length) {
    -        // nested object { last: { name: String }}
    -        this.nested[prefix + i] = true;
    -        this.add(obj[i], prefix + i + '.');
    -      }
    -      else
    -        this.path(prefix + i, obj[i]); // mixed type
    -    } else
    -      this.path(prefix + i, obj[i]);
    -  }
    -};

    Parameters:

    Example:

    - -
    var ToySchema = new Schema;
    -ToySchema.add({ name: 'string', color: 'string', price: 'number' });

    Schema#path(path, constructor)

    Gets/sets schema paths.

    show code
    Schema.prototype.path = function (path, obj) {
    -  if (obj == undefined) {
    -    if (this.paths[path]) return this.paths[path];
    -    if (this.subpaths[path]) return this.subpaths[path];
    -
    -    // subpaths?
    -    return /\.\d+\.?$/.test(path)
    -      ? getPositionalPath(this, path)
    -      : undefined;
    -  }
    -
    -  // some path names conflict with document methods
    -  if (reserved[path]) {
    -    throw new Error("`" + path + "` may not be used as a schema pathname");
    -  }
    -
    -  // update the tree
    -  var subpaths = path.split(/\./)
    -    , last = subpaths.pop()
    -    , branch = this.tree;
    -
    -  subpaths.forEach(function(path) {
    -    if (!branch[path]) branch[path] = {};
    -    branch = branch[path];
    -  });
    -
    -  branch[last] = utils.clone(obj);
    -
    -  this.paths[path] = Schema.interpretAsType(path, obj);
    -  return this;
    -};

    Parameters:

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    - -

    Example

    - -
    schema.path('name') // returns a SchemaType
    -schema.path('name', Number) // changes the schemaType of `name` to Number

    Schema#eachPath(fn)

    Iterates the schemas paths similar to Array#forEach.

    show code
    Schema.prototype.eachPath = function (fn) {
    -  var keys = Object.keys(this.paths)
    -    , len = keys.length;
    -
    -  for (var i = 0; i < len; ++i) {
    -    fn(keys[i], this.paths[keys[i]]);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    The callback is passed the pathname and schemaType as arguments on each iteration.


    Schema#requiredPaths()

    Returns an Array of path strings that are required by this schema.

    show code
    Schema.prototype.requiredPaths = function requiredPaths () {
    -  if (this._requiredpaths) return this._requiredpaths;
    -
    -  var paths = Object.keys(this.paths)
    -    , i = paths.length
    -    , ret = [];
    -
    -  while (i--) {
    -    var path = paths[i];
    -    if (this.paths[path].isRequired) ret.push(path);
    -  }
    -
    -  return this._requiredpaths = ret;
    -}

    Returns:


    Schema#pathType(path)

    Returns the pathType of path for this schema.

    show code
    Schema.prototype.pathType = function (path) {
    -  if (path in this.paths) return 'real';
    -  if (path in this.virtuals) return 'virtual';
    -  if (path in this.nested) return 'nested';
    -  if (path in this.subpaths) return 'real';
    -
    -  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
    -    return 'real';
    -  } else {
    -    return 'adhocOrUndefined'
    -  }
    -};

    Parameters:

    Returns:

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


    Schema#queue(name, args)

    Adds a method call to the queue.

    show code
    Schema.prototype.queue = function(name, args){
    -  this.callQueue.push([name, args]);
    -  return this;
    -};

    Parameters:

    • name <String> name of the document method to call later
    • args <Array> arguments to pass to the method

    Schema#pre(method, callback)

    Defines a pre hook for the document.

    show code
    Schema.prototype.pre = function(){
    -  return this.queue('pre', arguments);
    -};

    Parameters:

    Example

    - -
    var toySchema = new Schema(..);
    -
    -toySchema.pre('save', function (next) {
    -  if (!this.created) this.created = new Date;
    -  next();
    -})
    -
    -toySchema.pre('validate', function (next) {
    -  if (this.name != 'Woody') this.name = 'Woody';
    -  next();
    -})

    Schema#post(method, fn)

    Defines a post hook for the document.

    show code
    Schema.prototype.post = function(method, fn){
    -  return this.queue('on', arguments);
    -};

    Parameters:

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    - -
    var schema = new Schema(..);
    -schema.post('save', function () {
    -  console.log('this fired after a document was saved');
    -});
    -
    -var Model = mongoose.model('Model', schema);
    -
    -var m = new Model(..);
    -m.save(function (err) {
    -  console.log('this fires after the `post` hook');
    -});

    Schema#plugin(plugin, opts)

    Registers a plugin for this schema.

    show code
    Schema.prototype.plugin = function (fn, opts) {
    -  fn(this, opts);
    -  return this;
    -};

    Parameters:


    Schema#method(method, [fn])

    Adds an instance method to documents constructed from Models compiled from this schema.

    show code
    Schema.prototype.method = function (name, fn) {
    -  if ('string' != typeof name)
    -    for (var i in name)
    -      this.methods[i] = name[i];
    -  else
    -    this.methods[name] = fn;
    -  return this;
    -};

    Parameters:

    Example

    - -
    var schema = kittySchema = new Schema(..);
    -
    -schema.methods.meow = function () {
    -  console.log('meeeeeoooooooooooow');
    -})
    -
    -var Kitty = mongoose.model('Kitty', schema);
    -
    -var fizz = new Kitty;
    -fizz.meow(); // meeeeeooooooooooooow
    - -

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    - -
    schema.method({
    -    purr: function () {}
    -  , scratch: function () {}
    -});
    -
    -// later
    -fizz.purr();
    -fizz.scratch();

    Schema#static(name, fn)

    Adds static "class" methods to Models compiled from this schema.

    show code
    Schema.prototype.static = function(name, fn) {
    -  if ('string' != typeof name)
    -    for (var i in name)
    -      this.statics[i] = name[i];
    -  else
    -    this.statics[name] = fn;
    -  return this;
    -};

    Parameters:

    Example

    - -
    var schema = new Schema(..);
    -schema.static('findByName', function (name, callback) {
    -  return this.find({ name: name }, callback);
    -});
    -
    -var Drink = mongoose.model('Drink', schema);
    -Drink.findByName('sanpellegrino', function (err, drinks) {
    -  //
    -});
    - -

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


    Schema#index(fields, [options])

    Defines an index (most likely compound) for this schema.

    show code
    Schema.prototype.index = function (fields, options) {
    -  options || (options = {});
    -
    -  if (options.expires)
    -    utils.expires(options);
    -
    -  this._indexes.push([fields, options]);
    -  return this;
    -};

    Parameters:

    Example

    - -
    schema.index({ first: 1, last: -1 })

    Schema#set(key, [value])

    Sets/gets a schema option.

    show code
    Schema.prototype.set = function (key, value) {
    -  if (arguments.length == 1)
    -    return this.options[key];
    -  this.options[key] = value;
    -  return this;
    -};

    Parameters:

    • key <String> option name
    • [value] <Object> if not passed, the current option value is returned

    Schema#indexes()

    Compiles indexes from fields and schema-level indexes

    show code
    Schema.prototype.indexes = function () {
    -  var indexes = []
    -    , seenSchemas = [];
    -
    -  collectIndexes(this);
    -
    -  return indexes;
    -
    -  function collectIndexes (schema, prefix) {
    -    if (~seenSchemas.indexOf(schema)) return;
    -    seenSchemas.push(schema);
    -
    -    var index;
    -    var paths = schema.paths;
    -    prefix = prefix || '';
    -
    -    for (var i in paths) {
    -      if (paths[i]) {
    -        if (paths[i] instanceof Types.DocumentArray) {
    -          collectIndexes(paths[i].schema, i + '.');
    -        } else {
    -          index = paths[i]._index;
    -
    -          if (index !== false && index !== null){
    -            var field = {};
    -            field[prefix + i] = '2d' === index ? index : 1;
    -            var options = 'Object' === index.constructor.name ? index : {};
    -            if (!('background' in options)) options.background = true;
    -            indexes.push([field, options]);
    -          }
    -        }
    -      }
    -    }
    -
    -    if (prefix) {
    -      fixSubIndexPaths(schema, prefix);
    -    } else {
    -      schema._indexes.forEach(function (index) {
    -        if (!('background' in index[1])) index[1].background = true;
    -      });
    -      indexes = indexes.concat(schema._indexes);
    -    }
    -  }

    Schema#virtual(name, [options])

    Creates a virtual type with the given name.

    show code
    Schema.prototype.virtual = function (name, options) {
    -  var virtuals = this.virtuals;
    -  var parts = name.split('.');
    -  return virtuals[name] = parts.reduce(function (mem, part, i) {
    -    mem[part] || (mem[part] = (i === parts.length-1)
    -                            ? new VirtualType(options)
    -                            : {});
    -    return mem[part];
    -  }, this.tree);
    -};

    Parameters:

    Returns:


    Schema#virtualpath(name)

    Returns the virtual type with the given name.

    show code
    Schema.prototype.virtualpath = function (name) {
    -  return this.virtuals[name];
    -};

    Parameters:

    Returns:


    Schema#namedScope()

    These still haven't been fixed. Once they're working we'll make them public again.

    show code
    Schema.prototype.namedScope = function (name, fn) {
    -  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
    -    , newScope = Object.create(namedScopes)
    -    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
    -  allScopes[name] = newScope;
    -  newScope.name = name;
    -  newScope.block = fn;
    -  newScope.query = new Query();
    -  newScope.decorate(namedScopes, {
    -    block0: function (block) {
    -      return function () {
    -        block.call(this.query);
    -        return this;
    -      };
    -    },
    -    blockN: function (block) {
    -      return function () {
    -        block.apply(this.query, arguments);
    -        return this;
    -      };
    -    },
    -    basic: function (query) {
    -      return function () {
    -        this.query.find(query);
    -        return this;
    -      };
    -    }
    -  });
    -  return newScope;
    -};

    Schema.reserved

    Reserved document keys.

    show code
    Schema.reserved = Object.create(null);
    -var reserved = Schema.reserved;
    -reserved.on =
    -reserved.db =
    -reserved.init =
    -reserved.isNew =
    -reserved.errors =
    -reserved.schema =
    -reserved.options =
    -reserved.modelName =
    -reserved.collection = 1;

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    - -
    on, db, init, isNew, errors, schema, options, modelName, collection

    Schema.interpretAsType(path, obj)

    Converts type arguments into Mongoose Types.

    show code
    Schema.interpretAsType = function (path, obj) {
    -  if (obj.constructor.name != 'Object')
    -    obj = { type: obj };
    -
    -  // Get the type making sure to allow keys named "type"
    -  // and default to mixed if not specified.
    -  // { type: { type: String, default: 'freshcut' } }
    -  var type = obj.type && !obj.type.type
    -    ? obj.type
    -    : {};
    -
    -  if ('Object' == type.constructor.name || 'mixed' == type) {
    -    return new Types.Mixed(path, obj);
    -  }
    -
    -  if (Array.isArray(type) || Array == type || 'array' == type) {
    -    // if it was specified through { type } look for `cast`
    -    var cast = (Array == type || 'array' == type)
    -      ? obj.cast
    -      : type[0];
    -
    -    if (cast instanceof Schema) {
    -      return new Types.DocumentArray(path, cast, obj);
    -    }
    -
    -    if ('string' == typeof cast) {
    -      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
    -    } else if (cast && (!cast.type || cast.type.type)
    -                    && 'Object' == cast.constructor.name
    -                    && Object.keys(cast).length) {
    -      return new Types.DocumentArray(path, new Schema(cast), obj);
    -    }
    -
    -    return new Types.Array(path, cast || Types.Mixed, obj);
    -  }
    -
    -  var name = 'string' == typeof type
    -    ? type
    -    : type.name;
    -
    -  if (name) {
    -    name = name.charAt(0).toUpperCase() + name.substring(1);
    -  }
    -
    -  if (undefined == Types[name]) {
    -    throw new TypeError('Undefined type at `' + path +
    -        '`
    -  Did you try nesting Schemas? ' +
    -        'You can only nest using refs or arrays.');
    -  }
    -
    -  return new Types[name](path, obj);
    -};

    Parameters:


    Schema.Types

    The various Mongoose Schema Types.

    show code
    Schema.Types = require('./schema/index');

    Example:

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -var ObjectId = mongoose.Schema.Types.ObjectId;
    - -

    Types:

    - -
      -
    • String
    • -
    • Number
    • -
    • Boolean | Bool
    • -
    • Array
    • -
    • Buffer
    • -
    • Date
    • -
    • ObjectId | Oid
    • -
    • Mixed
    • -
    - -

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    - -
    var Mixed = mongoose.Schema.Types.Mixed;
    -new mongoose.Schema({ _user: Mixed })

    Schema#tree

    Schema as a tree

    - -

    Example:

    - -
    {
    -    '_id'     : ObjectId
    -  , 'nested'  : {
    -        'key' : String
    -    }
    -}

    Schema#paths

    Schema as flat paths

    - -

    Example:

    - -
    {
    -    '_id'        : SchemaType,
    -  , 'nested.key' : SchemaType,
    -}

  • schemadefault.js

    exports#system.profile

    Default model for querying the system.profiles collection.


  • schematype.js

    SchemaType(path, [options], [instance])

    SchemaType constructor

    show code
    function SchemaType (path, options, instance) {
    -  this.path = path;
    -  this.instance = instance;
    -  this.validators = [];
    -  this.setters = [];
    -  this.getters = [];
    -  this.options = options;
    -  this._index = null;
    -  this.selected;
    -
    -  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
    -    // { unique: true, index: true }
    -    if ('index' == i && this._index) continue;
    -
    -    var opts = Array.isArray(options[i])
    -      ? options[i]
    -      : [options[i]];
    -
    -    this[i].apply(this, opts);
    -  }
    -};

    Parameters:


    SchemaType#default(val)

    Sets a default value for this SchemaType.

    show code
    SchemaType.prototype.default = function (val) {
    -  if (1 === arguments.length) {
    -    this.defaultValue = typeof val === 'function'
    -      ? val
    -      : this.cast(val);
    -    return this;
    -  } else if (arguments.length > 1) {
    -    this.defaultValue = utils.args(arguments);
    -  }
    -  return this.defaultValue;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var schema = new Schema({ n: { type: Number, default: 10 })
    -var M = db.model('M', schema)
    -var m = new M;
    -console.log(m.n) // 10
    - -

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    - -

    Example:

    - -
    // values are cast:
    -var schema = new Schema({ aNumber: Number, default: "4.815162342" })
    -var M = db.model('M', schema)
    -var m = new M;
    -console.log(m.aNumber) // 4.815162342
    -
    -// default unique objects for Mixed types:
    -var schema = new Schema({ mixed: Schema.Types.Mixed });
    -schema.path('mixed').default(function () {
    -  return {};
    -});
    -
    -// if we don't use a function to return object literals for Mixed defaults,
    -// each document will receive a reference to the same object literal creating
    -// a "shared" object instance:
    -var schema = new Schema({ mixed: Schema.Types.Mixed });
    -schema.path('mixed').default({});
    -var M = db.model('M', schema);
    -var m1 = new M;
    -m1.mixed.added = 1;
    -console.log(m1.mixed); // { added: 1 }
    -var m2 = new M;
    -console.log(m2.mixed); // { added: 1 }

    SchemaType#index(options)

    Declares the index options for this schematype.

    show code
    SchemaType.prototype.index = function (options) {
    -  this._index = options;
    -  utils.expires(this._index);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var s = new Schema({ name: { type: String, index: true })
    -var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
    -Schema.path('my.path').index(true);
    -Schema.path('my.path').index({ expires: 60 });
    -Schema.path('my.path').index({ unique: true, sparse: true });
    - -

    NOTE:

    - -

    Indexes are created in the background by default. Specify background: false to override.

    - -

    Direction doesn't matter for single key indexes


    SchemaType#unique(bool)

    Declares an unique index.

    show code
    SchemaType.prototype.unique = function (bool) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    -
    -  this._index.unique = bool;
    -  return this;
    -};

    Parameters:

    Returns:

    Examples:

    - -
    var s = new Schema({ name: { type: String, unique: true })
    -Schema.path('name').index({ unique: true });

    SchemaType#sparse(bool)

    Declares a sparse index.

    show code
    SchemaType.prototype.sparse = function (bool) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    -
    -  this._index.sparse = bool;
    -  return this;
    -};

    Parameters:

    Returns:

    Examples:

    - -
    var s = new Schema({ name: { type: String, sparse: true })
    -Schema.path('name').index({ sparse: true });

    SchemaType#expires(when)

    Declares a TTL index (rounded to the nearest second) for Date types only.

    show code
    SchemaType.prototype.expires = function (when) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    -
    -  this._index.expires = when;
    -  utils.expires(this._index);
    -  return this;
    -};

    Parameters:

    Returns:

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    - -

    Example:

    - -
    // expire in 24 hours
    -new Schema({..}, { expires: 60*60*24 });
    - -

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    - -

    Example:

    - -
    // expire in 24 hours
    -new Schema({..}, { expires: '24h' });
    -
    -// expire in 1.5 hours
    -new Schema({..}, { expires: '1.5h' });
    -
    -// expire in 7 days
    -var schema = new Schema({..});
    -schema.expires('7d');

    SchemaType#set(fn)

    Adds a setter to this schematype.

    show code
    SchemaType.prototype.set = function (fn) {
    -  if ('function' != typeof fn)
    -    throw new Error('A setter must be a function.');
    -  this.setters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    function capitalize (val) {
    -  if ('string' != typeof val) val = '';
    -  return val.charAt(0).toUpperCase() + val.substring(1);
    -}
    -
    -var s = new Schema({ name: { type: String, set: capitalize })
    -// or
    -Schema.path('name').set(capitalize);

    SchemaType#get(fn)

    Adds a getter to this schematype.

    show code
    SchemaType.prototype.get = function (fn) {
    -  if ('function' != typeof fn)
    -    throw new Error('A getter must be a function.');
    -  this.getters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    function dob (val) {
    -  if (!val) return val;
    -  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
    -}
    -
    -var s = new Schema({ born: { type: Date, get: dob })
    -// or
    -Schema.path('name').get(dob);

    SchemaType#validate(obj, [error])

    Adds validator(s) for this document path.

    show code
    SchemaType.prototype.validate = function (obj, error) {
    -  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
    -    this.validators.push([obj, error]);
    -    return this;
    -  }
    -
    -  var i = arguments.length
    -    , arg
    -
    -  while (i--) {
    -    arg = arguments[i];
    -    if (!(arg && 'Object' == arg.constructor.name)) {
    -      var msg = 'Invalid validator. Received (' + typeof arg + ') '
    -        + arg
    -        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
    -
    -      throw new Error(msg);
    -    }
    -    this.validate(arg.validator, arg.msg);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Validators must return Boolean. Returning false is interpreted as validation failure.

    - -

    Examples:

    - -
    function validator () { ... }
    -
    -var single = [validator, 'failed']
    -new Schema({ name: { type: String, validate: single }});
    -
    -var many = [
    -    { validator: validator, msg: 'uh oh' }
    -  , { validator: fn, msg: 'failed' }
    -]
    -new Schema({ name: { type: String, validate: many }});
    -
    -// or utilizing SchemaType methods directly:
    -
    -var schema = new Schema({ name: 'string' });
    -schema.path('name').validate(validator, 'validation failed');
    - -

    Asynchronous validation:

    - -

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    - -
    schema.path('name').validate(function (value, respond) {
    -  doStuff(value, function () {
    -    ...
    -    respond(false); // validation failed
    -  })
    - }, 'my error type');
    - -

    Validation occurs pre('save') or whenever you manually execute document#validate.

    - -

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    - -
    var conn = mongoose.createConnection(..);
    -conn.on('error', handleError);
    -
    -var Product = conn.model('Product', yourSchema);
    -var dvd = new Product(..);
    -dvd.save(); // emits error on the `conn` above
    - -

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    - -
    // registering an error listener on the Model lets us handle errors more locally
    -Product.on('error', handleError);

    SchemaType#required(required)

    Adds a required validator to this schematype.

    show code
    SchemaType.prototype.required = function (required) {
    -  var self = this;
    -
    -  function __checkRequired (v) {
    -    // in here, `this` refers to the validating document.
    -    // no validation when this path wasn't selected in the query.
    -    if ('isSelected' in this &&
    -        !this.isSelected(self.path) &&
    -        !this.isModified(self.path)) return true;
    -    return self.checkRequired(v);
    -  }
    -
    -  if (false === required) {
    -    this.isRequired = false;
    -    this.validators = this.validators.filter(function (v) {
    -      return v[0].name !== '__checkRequired';
    -    });
    -  } else {
    -    this.isRequired = true;
    -    this.validators.push([__checkRequired, 'required']);
    -  }
    -
    -  return this;
    -};

    Parameters:

    • required <Boolean> enable/disable the validator

    Returns:

    Example:

    - -
    var s = new Schema({ born: { type: Date, required: true })
    -// or
    -Schema.path('name').required(true);

    SchemaType#getDefault(scope, init)

    Gets the default value

    show code
    SchemaType.prototype.getDefault = function (scope, init) {
    -  var ret = 'function' === typeof this.defaultValue
    -    ? this.defaultValue.call(scope)
    -    : this.defaultValue;
    -
    -  if (null !== ret && undefined !== ret) {
    -    return this.cast(ret, scope, init);
    -  } else {
    -    return ret;
    -  }
    -};

    Parameters:

    • scope <Object> the scope which callback are executed
    • init <Boolean>

    SchemaType#applySetters(value, scope, init)

    Applies setters

    show code
    SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  var v = value
    -    , setters = this.setters
    -    , len = setters.length
    -
    -  if (!len) {
    -    if (null === v || undefined === v) return v;
    -    return init
    -      ? v // if we just initialized we dont recast
    -      : this.cast(v, scope, init, priorVal)
    -  }
    -
    -  while (len--) {
    -    v = setters[len].call(scope, v, this);
    -  }
    -
    -  if (null === v || undefined === v) return v;
    -
    -  // do not cast until all setters are applied #665
    -  v = this.cast(v, scope, init, priorVal);
    -
    -  return v;
    -};

    Parameters:


    SchemaType#applyGetters(value, scope)

    Applies getters to a value

    show code
    SchemaType.prototype.applyGetters = function (value, scope) {
    -  if (SchemaType._isRef(this, value, true)) return value;
    -
    -  var v = value
    -    , getters = this.getters
    -    , len = getters.length;
    -
    -  if (!len) {
    -    return v;
    -  }
    -
    -  while (len--) {
    -    v = getters[len].call(scope, v, this);
    -  }
    -
    -  return v;
    -};

    Parameters:


    SchemaType#select(val)

    Sets default select() behavior for this path.

    show code
    SchemaType.prototype.select = function select (val) {
    -  this.selected = !! val;
    -}

    Parameters:

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    - -

    Example:

    - -
    T = db.model('T', new Schema({ x: { type: String, select: true }}));
    -T.find(..); // field x will always be selected ..
    -// .. unless overridden;
    -T.find().select('-x').exec(callback);

    SchemaType#doValidate(value, callback, scope)

    Performs a validation of value using the validators declared for this SchemaType.

    show code
    SchemaType.prototype.doValidate = function (value, fn, scope) {
    -  var err = false
    -    , path = this.path
    -    , count = this.validators.length;
    -
    -  if (!count) return fn(null);
    -
    -  function validate (val, msg) {
    -    if (err) return;
    -    if (val === undefined || val) {
    -      --count || fn(null);
    -    } else {
    -      fn(err = new ValidatorError(path, msg));
    -    }
    -  }
    -
    -  this.validators.forEach(function (v) {
    -    var validator = v[0]
    -      , message   = v[1];
    -
    -    if (validator instanceof RegExp) {
    -      validate(validator.test(value), message);
    -    } else if ('function' === typeof validator) {
    -      if (2 === validator.length) {
    -        validator.call(scope, value, function (val) {
    -          validate(val, message);
    -        });
    -      } else {
    -        validate(validator.call(scope, value), message);
    -      }
    -    }
    -  });
    -};

    Parameters:


    SchemaType._isRef(self, value, init)

    Determines if value is a valid Reference.

    show code
    SchemaType._isRef = function (self, value, init) {
    -  if (init && self.options && self.options.ref) {
    -    if (null == value) return true;
    -    if (value._id && value._id.constructor.name === self.instance) return true;
    -  }
    -
    -  return false;
    -}

    Parameters:

    Returns:


  • types/array.js

    MongooseArray(values, path, doc)

    Mongoose Array constructor.

    show code
    function MongooseArray (values, path, doc) {
    -  var arr = [];
    -  arr.push.apply(arr, values);
    -  arr.__proto__ = MongooseArray.prototype;
    -
    -  arr._atomics = {};
    -  arr.validators = [];
    -  arr._path = path;
    -
    -  if (doc) {
    -    arr._parent = doc;
    -    arr._schema = doc.schema.path(path);
    -  }
    -
    -  return arr;
    -};

    Parameters:

    Inherits:

    NOTE:

    - -

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


    MongooseArray#_cast(value)

    Casts a member based on this arrays schema.

    show code
    MongooseArray.prototype._cast = function (value) {
    -  var cast = this._schema.caster.cast
    -    , doc = this._parent;
    -
    -  return cast.call(null, value, doc);
    -};

    Parameters:

    Returns:

    • <value> the casted value

    MongooseArray#_markModified(embeddedDoc, embeddedPath)

    Marks this array as modified.

    show code
    MongooseArray.prototype._markModified = function (embeddedDoc, embeddedPath) {
    -  var parent = this._parent
    -    , dirtyPath;
    -
    -  if (parent) {
    -    if (arguments.length) {
    -      // If an embedded doc bubbled up the change
    -      dirtyPath = [this._path, this.indexOf(embeddedDoc), embeddedPath].join('.');
    -    } else {
    -      dirtyPath = this._path;
    -    }
    -    parent.markModified(dirtyPath);
    -  }
    -
    -  return this;
    -};

    Parameters:

    • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
    • embeddedPath <String> the path which changed in the embeddedDoc

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


    MongooseArray#_registerAtomic(op, val)

    Register an atomic operation with the parent.

    show code
    MongooseArray.prototype._registerAtomic = function (op, val) {
    -  if ('$set' == op) {
    -    // $set takes precedence over all other ops.
    -    // mark entire array modified.
    -    this._atomics = { $set: val };
    -    this._markModified();
    -    return this;
    -  }
    -
    -  var atomics = this._atomics;
    -
    -  // reset pop/shift after save
    -  if ('$pop' == op && !('$pop' in atomics)) {
    -    var self = this;
    -    this._parent.once('save', function () {
    -      self._popped = self._shifted = null;
    -    });
    -  }
    -
    -  if (this._atomics.$set) {
    -    return this;
    -  }
    -
    -  // check for impossible $atomic combos (Mongo denies more than one
    -  // $atomic op on a single path
    -  if (Object.keys(atomics).length && !(op in atomics)) {
    -    // a different op was previously registered.
    -    // save the entire thing.
    -    this._atomics = { $set: this };
    -    this._markModified();
    -    return this;
    -  }
    -
    -  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
    -    atomics[op] || (atomics[op] = []);
    -    atomics[op] = atomics[op].concat(val);
    -  } else if (op === '$pullDocs') {
    -    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
    -      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
    -    selector['$in'] = selector['$in'].concat(val);
    -  } else {
    -    atomics[op] = val;
    -  }
    -
    -  this._markModified();
    -  return this;
    -};

    Parameters:


    MongooseArray#hasAtomics()

    Returns the number of pending atomic operations to send to the db for this array.

    show code
    MongooseArray.prototype.hasAtomics = function hasAtomics () {
    -  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
    -    return 0;
    -  }
    -
    -  return Object.keys(this._atomics).length;
    -}

    Returns:


    MongooseArray#push([args...])

    Wraps Array#push with proper change tracking.

    show code
    MongooseArray.prototype.push = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , ret = [].push.apply(this, values);
    -
    -  // $pushAll might be fibbed (could be $push). But it makes it easier to
    -  // handle what could have been $push, $pushAll combos
    -  this._registerAtomic('$pushAll', values);
    -  return ret;
    -};

    Parameters:


    MongooseArray#nonAtomicPush([args...])

    Pushes items to the array non-atomically.

    show code
    MongooseArray.prototype.nonAtomicPush = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , ret = [].push.apply(this, values);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -};

    Parameters:

    • [args...] <any>

    NOTE:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#$pop()

    Pops the array atomically at most one time per document save().

    NOTE:

    - -

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    - -
    doc.array = [1,2,3];
    -
    - var popped = doc.array.$pop();
    - console.log(popped); // 3
    - console.log(doc.array); // [1,2]
    -
    - // no affect
    - popped = doc.array.$pop();
    - console.log(doc.array); // [1,2]
    -
    - doc.save(function (err) {
    -   if (err) return handleError(err);
    -
    -   // we saved, now $pop works again
    -   popped = doc.array.$pop();
    -   console.log(popped); // 2
    -   console.log(doc.array); // [1]
    - })

    MongooseArray#pop()

    Wraps Array#pop with proper change tracking.

    show code
    MongooseArray.prototype.pop = function () {
    -  var ret = [].pop.call(this);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -};

    Note:

    - -

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#$shift()

    Atomically shifts the array at most one time per document save().

    NOTE:

    - -

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    - -
    doc.array = [1,2,3];
    -
    - var shifted = doc.array.$shift();
    - console.log(shifted); // 1
    - console.log(doc.array); // [2,3]
    -
    - // no affect
    - shifted = doc.array.$shift();
    - console.log(doc.array); // [2,3]
    -
    - doc.save(function (err) {
    -   if (err) return handleError(err);
    -
    -   // we saved, now $shift works again
    -   shifted = doc.array.$shift();
    -   console.log(shifted ); // 2
    -   console.log(doc.array); // [3]
    - })

    MongooseArray#shift()

    Wraps Array#shift with proper change tracking.

    show code
    MongooseArray.prototype.shift = function () {
    -  var ret = [].shift.call(this);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -};

    Example:

    - -
    doc.array = [2,3];
    -var res = doc.array.shift();
    -console.log(res) // 2
    -console.log(doc.array) // [3]
    - -

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#remove([args...])

    Removes items from an array atomically

    show code
    MongooseArray.prototype.remove = function () {
    -  var args = [].map.call(arguments, this._cast, this);
    -  if (args.length == 1)
    -    this.pull(args[0]);
    -  else
    -    this.pull.apply(this, args);
    -  return args;
    -};

    Parameters:

    • [args...] <Object> values to remove

    Examples:

    - -
    doc.array.remove(ObjectId)
    -doc.array.remove('tag 1', 'tag 2')

    MongooseArray#pull([args...])

    Pulls items from the array atomically.

    show code
    MongooseArray.prototype.pull = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , cur = this._parent.get(this._path)
    -    , i = cur.length
    -    , mem;
    -
    -  while (i--) {
    -    mem = cur[i];
    -    if (mem instanceof EmbeddedDocument) {
    -      if (values.some(function (v) { return v.equals(mem); } )) {
    -        [].splice.call(cur, i, 1);
    -      }
    -    } else if (~cur.indexOf.call(values, mem)) {
    -      [].splice.call(cur, i, 1);
    -    }
    -  }
    -
    -  if (values[0] instanceof EmbeddedDocument) {
    -    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
    -  } else {
    -    this._registerAtomic('$pullAll', values);
    -  }
    -
    -  return this;
    -};

    Parameters:

    • [args...] <any>

    MongooseArray#splice()

    Wraps Array#splice with proper change tracking.

    show code
    MongooseArray.prototype.splice = function () {
    -  if (arguments.length) {
    -    var ret = [].splice.apply(this, arguments);
    -    this._registerAtomic('$set', this);
    -  }
    -  return ret;
    -};

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#unshift()

    Wraps Array#unshift with proper change tracking.

    show code
    MongooseArray.prototype.unshift = function () {
    -  var values = [].map.call(arguments, this._cast, this);
    -  [].unshift.apply(this, values);
    -  this._registerAtomic('$set', this);
    -  return this.length;
    -};

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#sort()

    Wraps Array#sort with proper change tracking.

    show code
    MongooseArray.prototype.sort = function () {
    -  var ret = [].sort.apply(this, arguments);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -}

    NOTE:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#addToSet([args...])

    Adds values to the array if not already present.

    show code
    MongooseArray.prototype.addToSet = function addToSet () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , added = []
    -    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
    -             values[0] instanceof Date ? 'date' :
    -             '';
    -
    -  values.forEach(function (v) {
    -    var found;
    -    switch (type) {
    -      case 'doc':
    -        found = this.some(function(doc){ return doc.equals(v) });
    -        break;
    -      case 'date':
    -        var val = +v;
    -        found = this.some(function(d){ return +d === val });
    -        break;
    -      default:
    -        found = ~this.indexOf(v);
    -    }
    -
    -    if (!found) {
    -      [].push.call(this, v);
    -      this._registerAtomic('$addToSet', v);
    -      [].push.call(added, v);
    -    }
    -  }, this);
    -
    -  return added;
    -};

    Parameters:

    • [args...] <any>

    Returns:

    • <Array> the values that were added

    Example:

    - -
    console.log(doc.array) // [2,3,4]
    -var added = doc.array.addToSet(4,5);
    -console.log(doc.array) // [2,3,4,5]
    -console.log(added)     // [5]

    MongooseArray#toObject(options)

    Returns a native js Array.

    show code
    MongooseArray.prototype.toObject = function (options) {
    -  if (options && options.depopulate && this[0] instanceof Document) {
    -    return this.map(function (doc) {
    -      return doc._id;
    -    });
    -  }
    -
    -  // return this.slice()?
    -  return this.map(function (doc) {
    -    return doc;
    -  });
    -};

    Parameters:

    Returns:


    MongooseArray#inspect()

    Helper for console.log

    show code
    MongooseArray.prototype.inspect = function () {
    -  return '[' + this.map(function (doc) {
    -    return ' ' + doc;
    -  }) + ' ]';
    -};

    MongooseArray#indexOf(obj)

    Return the index of obj or -1 if not found.

    show code
    MongooseArray.prototype.indexOf = function indexOf (obj) {
    -  if (obj instanceof ObjectId) obj = obj.toString();
    -  for (var i = 0, len = this.length; i < len; ++i) {
    -    if (obj == this[i])
    -      return i;
    -  }
    -  return -1;
    -};

    Parameters:

    • obj <Object> the item to look for

    Returns:


    MongooseArray#_parent

    Parent owner document


    MongooseArray#_atomics

    Stores a queue of atomic operations to perform


  • types/buffer.js

    MongooseBuffer(value, encode, offset)

    Mongoose Buffer constructor.

    show code
    function MongooseBuffer (value, encode, offset) {
    -  var length = arguments.length;
    -  var val;
    -
    -  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
    -    val = 0;
    -  } else {
    -    val = value;
    -  }
    -
    -  var encoding;
    -  var path;
    -  var doc;
    -
    -  if (Array.isArray(encode)) {
    -    // internal casting
    -    path = encode[0];
    -    doc = encode[1];
    -  } else {
    -    encoding = encode;
    -  }
    -
    -  var buf = new Buffer(val, encoding, offset);
    -  buf.__proto__ = MongooseBuffer.prototype;
    -
    -  // make sure these internal props don't show up in Object.keys()
    -  Object.defineProperties(buf, {
    -      validators: { value: [] }
    -    , _path: { value: path }
    -    , _parent: { value: doc }
    -  });
    -
    -  if (doc && "string" === typeof path) {
    -    Object.defineProperty(buf, '_schema', {
    -        value: doc.schema.path(path)
    -    });
    -  }
    -
    -  return buf;
    -};

    Parameters:

    Inherits:

    Values always have to be passed to the constructor to initialize.


    MongooseBuffer#_markModified()

    Marks this buffer as modified.

    show code
    MongooseBuffer.prototype._markModified = function () {
    -  var parent = this._parent;
    -
    -  if (parent) {
    -    parent.markModified(this._path);
    -  }
    -  return this;
    -};

    MongooseBuffer#write()

    Writes the buffer.

    show code
    MongooseBuffer.prototype.write = function () {
    -  var written = Buffer.prototype.write.apply(this, arguments);
    -
    -  if (written > 0) {
    -    this._markModified();
    -  }
    -
    -  return written;
    -};

    MongooseBuffer#copy(target)

    Copies the buffer.

    show code
    MongooseBuffer.prototype.copy = function (target) {
    -  var ret = Buffer.prototype.copy.apply(this, arguments);
    -
    -  if (target instanceof MongooseBuffer) {
    -    target._markModified();
    -  }
    -
    -  return ret;
    -};

    Parameters:

    Returns:

    Note:

    - -

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


    MongooseBuffer#toObject([subtype])

    Converts this buffer to its Binary type representation.

    show code
    MongooseBuffer.prototype.toObject = function (subtype) {
    -  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
    -  return new Binary(this, subtype);
    -};

    Parameters:

    • [subtype] <Hex>

    Returns:

    SubTypes:

    - -
      -
    • 0x00: Binary/Generic
    • -
    • 0x01: Function
    • -
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • -
    • 0x03: UUID
    • -
    • 0x04: MD5
    • -
    • 0x80: User Defined
    • -

    MongooseBuffer#_parent

    Parent owner document


  • types/documentarray.js

    MongooseDocumentArray(values, path, doc)

    DocumentArray constructor

    show code
    function MongooseDocumentArray (values, path, doc) {
    -  var arr = [];
    -
    -  // Values always have to be passed to the constructor to initialize, since
    -  // otherwise MongooseArray#push will mark the array as modified to the parent.
    -  arr.push.apply(arr, values);
    -  arr.__proto__ = MongooseDocumentArray.prototype;
    -
    -  arr._atomics = {};
    -  arr.validators = [];
    -  arr._path = path;
    -
    -  if (doc) {
    -    arr._parent = doc;
    -    arr._schema = doc.schema.path(path);
    -    doc.on('save', arr.notify('save'));
    -    doc.on('isNew', arr.notify('isNew'));
    -  }
    -
    -  return arr;
    -};

    Parameters:

    Inherits:


    MongooseDocumentArray#_cast()

    Overrides MongooseArray#cast

    show code
    MongooseDocumentArray.prototype._cast = function (value) {
    -  var doc = new this._schema.casterConstructor(value, this);
    -  return doc;
    -};

    MongooseDocumentArray#id(id)

    Searches array items for the first document with a matching id.

    show code
    MongooseDocumentArray.prototype.id = function (id) {
    -  var casted
    -    , _id;
    -
    -  try {
    -    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
    -  } catch (e) {
    -    casted = null;
    -  }
    -
    -  for (var i = 0, l = this.length; i < l; i++) {
    -    _id = this[i].get('_id');
    -    if (!(_id instanceof ObjectId)) {
    -      if (String(id) == _id)
    -        return this[i];
    -    } else {
    -      if (casted == _id)
    -        return this[i];
    -    }
    -  }
    -
    -  return null;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var embeddedDoc = m.array.id(some_id);

    MongooseDocumentArray#toObject()

    Returns a native js Array of plain js objects

    show code
    MongooseDocumentArray.prototype.toObject = function () {
    -  return this.map(function (doc) {
    -    return doc && doc.toObject() || null;
    -  });
    -};

    Returns:

    NOTE:

    - -

    Each sub-document is converted to a plain object by calling its #toObject method.


    MongooseDocumentArray#inspect()

    Helper for console.log

    show code
    MongooseDocumentArray.prototype.inspect = function () {
    -  return '[' + this.map(function (doc) {
    -    if (doc) {
    -      return doc.inspect
    -        ? doc.inspect()
    -        : util.inspect(doc)
    -    }
    -    return 'null'
    -  }).join('
    -') + ']';
    -};

    MongooseDocumentArray#create(obj)

    Creates a subdocument casted to this schema.

    show code
    MongooseDocumentArray.prototype.create = function (obj) {
    -  return new this._schema.casterConstructor(obj);
    -}

    Parameters:

    • obj <Object> the value to cast to this arrays SubDocument schema

    This is the same subdocument constructor used for casting.


    MongooseDocumentArray#notify(event)

    Creates a fn that notifies all child docs of event.

    show code
    MongooseDocumentArray.prototype.notify = function notify (event) {
    -  var self = this;
    -  return function notify (val) {
    -    var i = self.length;
    -    while (i--) {
    -      self[i].emit(event, val);
    -    }
    -  }
    -}

    Parameters:

    Returns:


  • types/embedded.js

    EmbeddedDocument(obj, parentArr, skipId)

    EmbeddedDocument constructor.

    show code
    function EmbeddedDocument (obj, parentArr, skipId) {
    -  if (parentArr) {
    -    this.__parentArray = parentArr;
    -    this.__parent = parentArr._parent;
    -  } else {
    -    this.__parentArray = undefined;
    -    this.__parent = undefined;
    -  }
    -
    -  Document.call(this, obj, undefined, skipId);
    -
    -  var self = this;
    -  this.on('isNew', function (val) {
    -    self.isNew = val;
    -  });
    -};

    Parameters:

    Inherits:


    EmbeddedDocument#markModified(path)

    Marks the embedded doc modified.

    show code
    EmbeddedDocument.prototype.markModified = function (path) {
    -  if (!this.__parentArray) return;
    -
    -  this._activePaths.modify(path);
    -
    -  if (this.isNew) {
    -    // Mark the WHOLE parent array as modified
    -    // if this is a new document (i.e., we are initializing
    -    // a document),
    -    this.__parentArray._markModified();
    -  } else
    -    this.__parentArray._markModified(this, path);
    -};

    Parameters:

    • path <String> the path which changed

    Example:

    - -
    var doc = blogpost.comments.id(hexstring);
    -doc.mixed.type = 'changed';
    -doc.markModified('mixed.type');

    EmbeddedDocument#save([fn])

    Used as a stub for hooks.js

    show code
    EmbeddedDocument.prototype.save = function(fn) {
    -  if (fn)
    -    fn(null);
    -  return this;
    -};

    Parameters:

    Returns:

    NOTE:

    - -

    This is a no-op. Does not actually save the doc to the db.


    EmbeddedDocument#remove([fn])

    Removes the subdocument from its parent array.

    show code
    EmbeddedDocument.prototype.remove = function (fn) {
    -  if (!this.__parentArray) return this;
    -
    -  var _id;
    -  if (!this.willRemove) {
    -    _id = this._doc._id;
    -    if (!_id) {
    -      throw new Error('For your own good, Mongoose does not know ' + 
    -                      'how to remove an EmbeddedDocument that has no _id');
    -    }
    -    this.__parentArray.pull({ _id: _id });
    -    this.willRemove = true;
    -  }
    -
    -  if (fn)
    -    fn(null);
    -
    -  return this;
    -};

    Parameters:


    EmbeddedDocument#update()

    Override #update method of parent documents.

    show code
    EmbeddedDocument.prototype.update = function () {
    -  throw new Error('The #update method is not available on EmbeddedDocuments');
    -}

    EmbeddedDocument#inspect()

    Helper for console.log

    show code
    EmbeddedDocument.prototype.inspect = function () {
    -  return inspect(this.toObject());
    -};

    EmbeddedDocument#invalidate(path, err)

    Marks a path as invalid, causing validation to fail.

    show code
    EmbeddedDocument.prototype.invalidate = function (path, err, first) {
    -  if (!this.__parent) return false;
    -  var index = this.__parentArray.indexOf(this);
    -  var parentPath = this.__parentArray._path;
    -  var fullPath = [parentPath, index, path].join('.');
    -  this.__parent.invalidate(fullPath, err);
    -  if (first)
    -    this._validationError = ownerDocument(this)._validationError;
    -  return true;
    -}

    Parameters:

    • path <String> the field to invalidate
    • err <String, Error> error which states the reason `path` was invalid

    Returns:


    EmbeddedDocument#ownerDocument()

    Returns the top level document of this sub-document.

    show code
    EmbeddedDocument.prototype.ownerDocument = function () {
    -  return ownerDocument(this);
    -}

    Returns:


    EmbeddedDocument#parent()

    Returns this sub-documents parent document.

    show code
    EmbeddedDocument.prototype.parent = function () {
    -  return this.__parent;
    -}

    EmbeddedDocument#parentArray()

    Returns this sub-documents parent array.

    show code
    EmbeddedDocument.prototype.parentArray = function () {
    -  return this.__parentArray;
    -}

  • types/objectid.js

    ObjectId()

    ObjectId type constructor

    Example

    - -
    var id = new mongoose.Types.ObjectId;

    ObjectId.fromString(str)

    Creates an ObjectId from str

    show code
    ObjectId.fromString;

    Parameters:

    Returns:


    ObjectId.toString(oid)

    Converts oid to a string.

    show code
    ObjectId.toString;

    Parameters:

    Returns:


  • utils.js

    exports.toCollectionName(name)

    Produces a collection name from model name.

    show code
    exports.toCollectionName = function (name) {
    -  if ('system.profile' === name) return name;
    -  if ('system.indexes' === name) return name;
    -  return pluralize(name.toLowerCase());
    -};

    Parameters:

    Returns:


    exports.pluralization

    Pluralization rules.

    show code
    exports.pluralization = [
    -  [/(m)an$/gi, '$1en'],
    -  [/(pe)rson$/gi, '$1ople'],
    -  [/(child)$/gi, '$1ren'],
    -  [/^(ox)$/gi, '$1en'],
    -  [/(ax|test)is$/gi, '$1es'],
    -  [/(octop|vir)us$/gi, '$1i'],
    -  [/(alias|status)$/gi, '$1es'],
    -  [/(bu)s$/gi, '$1ses'],
    -  [/(buffal|tomat|potat)o$/gi, '$1oes'],
    -  [/([ti])um$/gi, '$1a'],
    -  [/sis$/gi, 'ses'],
    -  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
    -  [/(hive)$/gi, '$1s'],
    -  [/([^aeiouy]|qu)y$/gi, '$1ies'],
    -  [/(x|ch|ss|sh)$/gi, '$1es'],
    -  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
    -  [/([m|l])ouse$/gi, '$1ice'],
    -  [/(quiz)$/gi, '$1zes'],
    -  [/s$/gi, 's'],
    -  [/$/gi, 's']
    -];
    -var rules = exports.pluralization;

    These rules are applied while processing the argument to toCollectionName.


    exports.uncountables

    Uncountable words.

    show code
    exports.uncountables = [
    -  'advice',
    -  'energy',
    -  'excretion',
    -  'digestion',
    -  'cooperation',
    -  'health',
    -  'justice',
    -  'labour',
    -  'machinery',
    -  'equipment',
    -  'information',
    -  'pollution',
    -  'sewage',
    -  'paper',
    -  'money',
    -  'species',
    -  'series',
    -  'rain',
    -  'rice',
    -  'fish',
    -  'sheep',
    -  'moose',
    -  'deer',
    -  'news'
    -];
    -var uncountables = exports.uncountables;

    These words are applied while processing the argument to toCollectionName.


    exports.deepEqual(a, b)

    Determines if a and b are deep equal.

    show code
    exports.deepEqual = function deepEqual (a, b) {
    -  if (a === b) return true;
    -
    -  if (a instanceof Date && b instanceof Date)
    -    return a.getTime() === b.getTime();
    -
    -  if (a instanceof ObjectId && b instanceof ObjectId) {
    -    return a.toString() === b.toString();
    -  }
    -
    -  if (typeof a !== 'object' && typeof b !== 'object')
    -    return a == b;
    -
    -  if (a === null || b === null || a === undefined || b === undefined)
    -    return false
    -
    -  if (a.prototype !== b.prototype) return false;
    -
    -  // Handle MongooseNumbers
    -  if (a instanceof Number && b instanceof Number) {
    -    return a.valueOf() === b.valueOf();
    -  }
    -
    -  if (Buffer.isBuffer(a)) {
    -    if (!Buffer.isBuffer(b)) return false;
    -    if (a.length !== b.length) return false;
    -    for (var i = 0, len = a.length; i < len; ++i) {
    -      if (a[i] !== b[i]) return false;
    -    }
    -    return true;
    -  }
    -
    -  if (isMongooseObject(a)) a = a.toObject();
    -  if (isMongooseObject(b)) b = b.toObject();
    -
    -  try {
    -    var ka = Object.keys(a),
    -        kb = Object.keys(b),
    -        key, i;
    -  } catch (e) {//happens when one is a string literal and the other isn't
    -    return false;
    -  }
    -
    -  // having the same number of owned properties (keys incorporates
    -  // hasOwnProperty)
    -  if (ka.length != kb.length)
    -    return false;
    -
    -  //the same set of keys (although not necessarily the same order),
    -  ka.sort();
    -  kb.sort();
    -
    -  //~~~cheap key test
    -  for (i = ka.length - 1; i >= 0; i--) {
    -    if (ka[i] != kb[i])
    -      return false;
    -  }
    -
    -  //equivalent values for every corresponding key, and
    -  //~~~possibly expensive deep test
    -  for (i = ka.length - 1; i >= 0; i--) {
    -    key = ka[i];
    -    if (!deepEqual(a[key], b[key])) return false;
    -  }
    -
    -  return true;
    -};

    Parameters:

    • a <any> a value to compare to `b`
    • b <any> a value to compare to `a`

    Returns:

    Modified from node/lib/assert.js


    exports.clone(obj, options)

    Object clone with Mongoose natives support.

    show code
    exports.clone = function clone (obj, options) {
    -  if (obj === undefined || obj === null)
    -    return obj;
    -
    -  if (Array.isArray(obj))
    -    return cloneArray(obj, options);
    -
    -  if (isMongooseObject(obj)) {
    -    if (options && options.json && 'function' === typeof obj.toJSON) {
    -      return obj.toJSON(options);
    -    } else {
    -      return obj.toObject(options);
    -    }
    -  }
    -
    -  if ('Object' === obj.constructor.name)
    -    return cloneObject(obj, options);
    -
    -  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
    -    return new obj.constructor(+obj);
    -
    -  if ('RegExp' === obj.constructor.name)
    -    return new RegExp(obj.source);
    -
    -  if (obj instanceof ObjectId) {
    -    return new ObjectId(obj.id);
    -  }
    -
    -  if (obj.valueOf)
    -    return obj.valueOf();
    -};
    -var clone = exports.clone;

    Parameters:

    Returns:

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.


    exports.options(defaults, options)

    Copies and merges options with defaults.

    show code
    exports.options = function (defaults, options) {
    -  var keys = Object.keys(defaults)
    -    , i = keys.length
    -    , k ;
    -
    -  options = options || {};
    -
    -  while (i--) {
    -    k = keys[i];
    -    if (!(k in options)) {
    -      options[k] = defaults[k];
    -    }
    -  }
    -
    -  return options;
    -};

    Parameters:

    Returns:


    exports.random()

    Generates a random string

    show code
    exports.random = function () {
    -  return Math.random().toString().substr(3);
    -};

    exports.merge(to, from)

    Merges from into to without overwriting existing properties.

    show code
    exports.merge = function merge (to, from) {
    -  var keys = Object.keys(from)
    -    , i = keys.length
    -    , key
    -
    -  while (i--) {
    -    key = keys[i];
    -    if ('undefined' === typeof to[key]) {
    -      to[key] = from[key];
    -    } else {
    -      merge(to[key], from[key]);
    -    }
    -  }
    -};

    Parameters:


    exports.args()

    A faster Array.prototype.slice.call(arguments) alternative

    show code
    exports.args = function (args, slice, sliceEnd) {
    -  var ret = [];
    -  var start = slice || 0;
    -  var end = 3 === arguments.length
    -    ? sliceEnd
    -    : args.length;
    -
    -  for (var i = start; i < end; ++i) {
    -    ret[i - start] = args[i];
    -  }
    -
    -  return ret;
    -}

    exports.tick(callback)

    process.nextTick helper.

    show code
    exports.tick = function tick (callback) {
    -  if ('function' !== typeof callback) return;
    -  return function () {
    -    try {
    -      callback.apply(this, arguments);
    -    } catch (err) {
    -      // only nextTick on err to get out of
    -      // the event loop and avoid state corruption.
    -      process.nextTick(function () {
    -        throw err;
    -      });
    -    }
    -  }
    -}

    Parameters:

    Wraps callback in a try/catch + nextTick.

    - -

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


    exports.isMongooseObject(v)

    Returns if v is a mongoose object that has a toObject() method we can use.

    show code
    exports.isMongooseObject = function (v) {
    -  Document || (Document = require('./document'));
    -  MongooseArray || (MongooseArray = require('./types').Array);
    -  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
    -
    -  return v instanceof Document ||
    -         v instanceof MongooseArray ||
    -         v instanceof MongooseBuffer
    -}
    -var isMongooseObject = exports.isMongooseObject;

    Parameters:

    This is for compatibility with libs like Date.js which do foolish things to Natives.


    exports.expires(object)

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    show code
    exports.expires = function expires (object) {
    -  if (!(object && 'Object' == object.constructor.name)) return;
    -  if (!('expires' in object)) return;
    -
    -  var when;
    -  if ('string' != typeof object.expires) {
    -    when = object.expires;
    -  } else {
    -    when = Math.round(ms(object.expires) / 1000);
    -  }
    -  object.expiresAfterSeconds = when;
    -  delete object.expires;
    -}

    Parameters:


  • virtualtype.js

    VirtualType()

    VirtualType constructor

    show code
    function VirtualType (options) {
    -  this.getters = [];
    -  this.setters = [];
    -  this.options = options || {};
    -}

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    - -

    Example:

    - -
    var fullname = schema.virtual('fullname');
    -fullname instanceof mongoose.VirtualType // true

    VirtualType#get(fn)

    Defines a getter.

    show code
    VirtualType.prototype.get = function (fn) {
    -  this.getters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var virtual = schema.virtual('fullname');
    -virtual.get(function () {
    -  return this.name.first + ' ' + this.name.last;
    -});

    VirtualType#set(fn)

    Defines a setter.

    show code
    VirtualType.prototype.set = function (fn) {
    -  this.setters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var virtual = schema.virtual('fullname');
    -virtual.set(function (v) {
    -  var parts = v.split(' ');
    -  this.name.first = parts[0];
    -  this.name.last = parts[1];
    -});

    VirtualType#applyGetters(value, scope)

    Applies getters to value using optional scope.

    show code
    VirtualType.prototype.applyGetters = function (value, scope) {
    -  var v = value;
    -  for (var l = this.getters.length - 1; l >= 0; l--){
    -    v = this.getters[l].call(scope, v);
    -  }
    -  return v;
    -};

    Parameters:

    Returns:

    • <any> the value after applying all getters

    VirtualType#applySetters(value, scope)

    Applies setters to value using optional scope.

    show code
    VirtualType.prototype.applySetters = function (value, scope) {
    -  var v = value;
    -  for (var l = this.setters.length - 1; l >= 0; l--){
    -    this.setters[l].call(scope, v);
    -  }
    -  return v;
    -};

    Parameters:

    Returns:

    • <any> the value after applying all setters

diff --git a/docs/3.0.x/docs/api.jade b/docs/3.0.x/docs/api.jade deleted file mode 100644 index 91e18ee6293..00000000000 --- a/docs/3.0.x/docs/api.jade +++ /dev/null @@ -1,508 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose API v#{package.version} - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - style. - body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; - } - a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; - } - a:hover { - opacity: 0.8; - } - #wrap { - } - h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; - } - pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; - } - code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Monaco; - } - pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; - } - h3 { - padding: 20px 15px; - margin-left: -15px; - } - h3 code { - font-weight: normal; - } - hr { - height: 1px; - border: 0 none; - padding: 0; - margin: 60px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) - } - .doclinks hr { - margin: 10px 0; - } - li { - list-style: square; - } - #header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; - } - #header h1 { - margin-top: 0; - margin-bottom: 0; - } - #header h1 a { - text-decoration: none; - } - #header .mongoose { - font-size: 50px; - font-weight: 100; - color: #fff; - text-shadow: 6px 4px 5px #777, -2px 0px 2px white; - letter-spacing: -7px; - } - #links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - } - #links hr { - margin: 32px 0; - } - #content { - padding: 0; - margin: 0 0 30px 230px; - overflow-x: hidden; - } - #content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; - } - #content .controls:hover { - opacity: .9; - } - #content p { - word-wrap: break-word; - } - #content > ul { - margin: 0; - padding: 0; - } - .private { - display: none; - } - .section { - font-size: 15px; - } - .doclinks li.private a:before, - .doclinks .module.private a:before, - .doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; - } - #content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; - } - .module { - list-style: none; - padding: 30px 0 30px 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; - } - .module > * { - max-width: 700px; - } - .item:last-child { - margin-bottom: 90px; - } - .item:last-child > hr { - display: none; - } - .item h3 a { - color: #333; - text-decoration: none; - } - .property h3 span { - color: #444; - } - .description { - margin-top: 25px; - } - .sourcecode { - display: none; - } - .showcode { - font-size: 12px; - cursor: pointer; - display: none; - } - .load .showcode { - display: block; - } - .types a { - text-decoration: none; - } - @media only screen and (device-width: 768px) { - - } - @media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links hr { - display: none; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - .controls { display: none; } - } - body.api - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - hr - .doclinks - each item in docs - .file(class=item.hasPublic ? '' : 'private') - a.section(href='#' + item.title.replace(/[\.\/#]/g, '-'))= item.title - ul - each method in item.methods - if method.ctx && !method.ignore - li(class= method.isPrivate ? 'private' : '') - case method.ctx.type - when 'method' - id = method.ctx.constructor + '-' + method.ctx.name - when 'function' - id = method.ctx.name - default - id = '' - url = href(klass(item.title) + '_' + id) - a(href='#' + url)= method.ctx.name - each stat in item.statics - if stat.ctx && !stat.ignore - li(class= stat.isPrivate ? 'private' : '') - case stat.ctx.type - when 'method' - id = stat.ctx.receiver + '-' + stat.ctx.name - when 'property' - id = stat.ctx.receiver + '-' + stat.ctx.name - when 'function' - id = stat.ctx.name - url = href(klass(item.title) + '_' + id) - a(href='#' + url)= stat.ctx.name - each property in item.props - if property.ctx && !property.ignore - li(class= property.isPrivate ? 'private' : '') - construct = property.ctx.receiver || property.ctx.constructor - link = href(construct) + '-' + href(property.ctx.name) - url = href(klass(item.title) + '_' + link) - a(href='#' + url)= property.ctx.name - #content - .controls - label - input(type='checkbox') - | private - ul - each item in docs - li.module(class=item.hasPublic ? '' : 'private') - a(href=github + package.version + '/' + item.title, id=item.title.replace(/[\.\/#]/g, '-'))= item.title - each method in item.methods - div.item.method(class= method.isPrivate ? 'private' : 'public') - if method.ctx - case method.ctx.type - when 'method' - id = method.ctx.constructor + '-' + method.ctx.name - text = method.ctx.constructor + '#' + method.ctx.name - when 'function' - id = method.ctx.name - text = method.ctx.name - default - text = '' - url = href(klass(item.title) + '_' + text) - h3(id= url) - a(href= '#' + url) - = text - | ( - each tag, i in method.params - code= tag.name - if i+1 < method.params.length - | , - | ) - else - - // console.log('\nmissing method name', method); - h3 MISSING method name - != method.description.summary - if method.code - span.showcode show code - .sourcecode - != hl(method.code) - if method.params.length - .params - h4 Parameters: - ul - each tag in method.params - li - code= tag.name - if tag.types && tag.types.length - span.types - | < - each type, i in tag.types - != linktype(type) - if i+1 < tag.types.length - | , - | > - span= tag.description - if method.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in method.return.types - != linktype(type) - if i+1 < method.return.types.length - | , - | > - span= method.return.description - if method.inherits - .inherits - h4 Inherits: - ul - li - != method.inherits - if method.events && method.events.length - .events - h4 Events: - ul - each event in method.events - li - != event.string - if method.see.length - .see - h4 See: - ul.see - each see in method.see - li - url = see.url || see.local - a(href=url, title=see.title || see.local)= see.title || see.url || see.local - div.description - != method.description.body - hr(class= method.isPrivate ? 'private' : '') - each stat in item.statics - div.item.static(class= stat.isPrivate ? 'private' : 'public') - if stat.ctx - case stat.ctx.type - when 'method' - id = stat.ctx.receiver + '-' + stat.ctx.name - text = stat.ctx.receiver + '.' + stat.ctx.name - when 'property' - id = stat.ctx.receiver + '-' + stat.ctx.name - text = stat.ctx.receiver + '.' + stat.ctx.name - when 'function' - id = stat.ctx.name - text = stat.ctx.name - default - text = '' - url = href(klass(item.title) + '_' + id) - h3(id= url) - a(href= '#' + url) - = text - if 'property' != stat.ctx.type - | ( - each tag, i in stat.params - code= tag.name - if i+1 < stat.params.length - | , - | ) - else - - // console.log('\nmissing static name', stat); - h3 MISSING stat name - != stat.description.summary - if stat.code - span.showcode show code - .sourcecode - != hl(stat.code) - if stat.params.length - .params - h4 Parameters: - ul - each tag in stat.params - li - - if (!tag.name) - - // console.log(tag) - code= tag.name - if tag.types && tag.types.length - span.types - | < - each type, i in tag.types - != linktype(type) - if i+1 < tag.types.length - | , - | > - span= tag.description - if stat.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in stat.return.types - != linktype(type) - if i+1 < stat.return.types.length - | , - | > - span= stat.return.description - if stat.inherits - .inherits - h4 Inherits: - ul - li - != stat.inherits - if stat.see.length - .see - h4 See: - ul.see - each see in stat.see - li - url = see.url || see.local - a(href=url, title=see.title || see.local)= see.title || see.url || see.local - != stat.description.body - hr(class= stat.isPrivate ? 'private' : '') - each property in item.props - div.item.property(class= property.ignore || property.isPrivate ? 'private' : 'public') - construct = property.ctx.receiver || property.ctx.constructor - link = href(construct) + '-' + href(property.ctx.name) - url = href(klass(item.title) + '_' + link) - h3(id = url) - a(href= '#' + url) - = construct + '#' - span= property.ctx.name - != property.description.full - if property.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in property.return.types - != linktype(type) - if i+1 < property.return.types.length - | , - | > - span= property.return.description - hr(class= property.isPrivate ? 'private' : '') - script. - document.body.className = 'load'; - include includes/googleanalytics - script(src="/docs/js/zepto.min.js") - script. - $(".module").on("click", ".showcode", function (e) { - $(this).closest(".item").find(".sourcecode").first().toggle(); - }); - $("#content .controls input").on("click", function (e) { - $(".private").toggle() - }) diff --git a/docs/3.0.x/docs/contributing.html b/docs/3.0.x/docs/contributing.html deleted file mode 100644 index 21db8a903d0..00000000000 --- a/docs/3.0.x/docs/contributing.html +++ /dev/null @@ -1,11 +0,0 @@ -Mongoose Contributing v3.0.3Fork me on GitHub

Contributing

Bugfixes

  • Before starting to write code, look for existing tickets or create one for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch.
  • Fork the repo or for small documentation changes, navigate to the source on github and click the Edit button.
  • Write inline documentation for new methods or class members.
  • Write tests and make sure they pass (execute make test from the cmd line to run the test suite).
  • Follow the general coding style of the rest of the project (comma first, etc).

Documentation

To contribute to the API documentation just make your changes to the inline documentation of the appropriate source code in the master branch and submit a pull request. You might also use the github Edit button.

- -

To contribute to the guide or quick start docs, make your changes to the appropriate .jade files in the docs directory of the master branch and submit a pull request. Again, the Edit button might work for you here.

Plugins

The plugins site is also an open source project that you can get involved with. Feel free to fork and improve it as well!

diff --git a/docs/3.0.x/docs/contributing.jade b/docs/3.0.x/docs/contributing.jade deleted file mode 100644 index eb6cc091510..00000000000 --- a/docs/3.0.x/docs/contributing.jade +++ /dev/null @@ -1,22 +0,0 @@ -extends layout - -block content - h2 Contributing - - h3 Bugfixes - :markdown - - Before starting to write code, look for existing [tickets](https://github.com/learnboost/mongoose/issues) or [create one](https://github.com/learnboost/mongoose/issues/new) for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. - - Fork the [repo](https://github.com/learnboost/mongoose) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. - - Write inline documentation for new methods or class members. - - Write tests and make sure they pass (execute `make test` from the cmd line to run the test suite). - - Follow the general coding style of the rest of the project (comma first, etc). - - h3 Documentation - :markdown - To contribute to the [API documentation](./api.html) just make your changes to the inline documentation of the appropriate [source code](https://github.com/LearnBoost/mongoose/tree/master/lib) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. - - To contribute to the [guide](./guide.html) or [quick start](./index.html) docs, make your changes to the appropriate `.jade` files in the [docs](https://github.com/LearnBoost/mongoose/tree/master/docs) directory of the master branch and submit a pull request. Again, the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button might work for you here. - - h3 Plugins - :markdown - The [plugins](http://plugins.mongoosejs.com/) site is also an [open source project](https://github.com/aheckmann/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! diff --git a/docs/3.0.x/docs/css/default.css b/docs/3.0.x/docs/css/default.css deleted file mode 100644 index ccb22728ed3..00000000000 --- a/docs/3.0.x/docs/css/default.css +++ /dev/null @@ -1,135 +0,0 @@ -/* - -Original style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ - -pre code { - display: block; padding: 0.5em; - background: #F0F0F0; -} - -pre code, -pre .ruby .subst, -pre .tag .title, -pre .lisp .title, -pre .clojure .built_in, -pre .nginx .title { - color: black; -} - -pre .string, -pre .title, -pre .constant, -pre .parent, -pre .tag .value, -pre .rules .value, -pre .rules .value .number, -pre .preprocessor, -pre .ruby .symbol, -pre .ruby .symbol .string, -pre .ruby .symbol .keyword, -pre .ruby .symbol .keymethods, -pre .instancevar, -pre .aggregate, -pre .template_tag, -pre .django .variable, -pre .smalltalk .class, -pre .addition, -pre .flow, -pre .stream, -pre .bash .variable, -pre .apache .tag, -pre .apache .cbracket, -pre .tex .command, -pre .tex .special, -pre .erlang_repl .function_or_atom, -pre .markdown .header { - color: #800; -} - -pre .comment, -pre .annotation, -pre .template_comment, -pre .diff .header, -pre .chunk, -pre .markdown .blockquote { - color: #888; -} - -pre .number, -pre .date, -pre .regexp, -pre .literal, -pre .smalltalk .symbol, -pre .smalltalk .char, -pre .go .constant, -pre .change, -pre .markdown .bullet, -pre .markdown .link_url { - color: #080; -} - -pre .label, -pre .javadoc, -pre .ruby .string, -pre .decorator, -pre .filter .argument, -pre .localvars, -pre .array, -pre .attr_selector, -pre .important, -pre .pseudo, -pre .pi, -pre .doctype, -pre .deletion, -pre .envvar, -pre .shebang, -pre .apache .sqbracket, -pre .nginx .built_in, -pre .tex .formula, -pre .erlang_repl .reserved, -pre .input_number, -pre .markdown .link_label, -pre .vhdl .attribute, -pre .clojure .attribute { - color: #88F -} - -pre .keyword, -pre .id, -pre .phpdoc, -pre .title, -pre .built_in, -pre .aggregate, -pre .css .tag, -pre .javadoctag, -pre .phpdoc, -pre .yardoctag, -pre .smalltalk .class, -pre .winutils, -pre .bash .variable, -pre .apache .tag, -pre .go .typename, -pre .tex .command, -pre .markdown .strong, -pre .request, -pre .status { - font-weight: bold; -} - -pre .markdown .emphasis { - font-style: italic; -} - -pre .nginx .built_in { - font-weight: normal; -} - -pre .coffeescript .javascript, -pre .xml .css, -pre .xml .javascript, -pre .xml .vbscript, -pre .tex .formula { - opacity: 0.5; -} diff --git a/docs/3.0.x/docs/css/guide.css b/docs/3.0.x/docs/css/guide.css deleted file mode 100644 index 51a5046fc24..00000000000 --- a/docs/3.0.x/docs/css/guide.css +++ /dev/null @@ -1,283 +0,0 @@ -html, body, #content { - height: 100%; -} -.module { - min-height: 100%; - box-sizing: border-box; -} -body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; -} -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; -} -code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Monaco; - /*text-shadow: 1px 2px 2px #555;*/ -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -h2 { - margin-top: 0; -} -h3 { padding-top: 35px; } -h3 code { - font-weight: normal; -} -hr { - display: none; - height: 1px; - border: 0 none; - padding: 0; - margin: 90px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) -} -.doclinks hr { - margin: 10px 0; -} -li { - list-style: square; -} -#header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -#header .mongoose { - font-size: 50px; - font-weight: 100; - color: #fff; - text-shadow: 6px 4px 5px #777, -2px 0px 2px white; - letter-spacing: -7px; -} -#links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; -} -#links .schematypes span { - display: none; -} -#content { - padding: 0; - margin: 0 0 0 230px; - overflow-x: hidden; -} -#content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -#content .controls:hover { - opacity: .9; -} -#content p { - word-wrap: break-word; -} -#content > ul { - margin: 0; - padding: 0; -} -.private { - display: none; -} -.doclinks li.private a:before, -.doclinks .module.private a:before, -.doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; -} -#content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; -} -.module { - list-style: none; - padding: 30px 0 0 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; -} -.module > * { - max-width: 700px; -} -.item { - margin-bottom: 175px; -} -.item h3 a { - color: #333; - text-decoration: none; -} -.property h3 span { - color: #444; -} -.description { - margin-top: 25px; -} -.sourcecode { - display: none; -} -.showcode { - font-size: 12px; - cursor: pointer; - display: none; -} -.load .showcode { - display: block; -} -.types a { - text-decoration: none; -} -li.guide ul { - padding-left: 16px; -} - -@media only screen and (device-width: 768px) { - -} -@media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - html, body, #content { - height: auto; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - #links li.guide { - display: block; - width: 390px; - margin-bottom: 15px; - } - #links li.guide > a { - display: none; - } - #links li ul li { - width: 44%; - text-align: left; - } - #links li ul li ul li { - width: 95%; - } - #links .plugins, - #links .changelog { - display: none; - } - #links .schematypes span { - display: inline; - } - #links .double { - width: 332px; - } - #links .double > ul { - display: inline; - float: right; - } - #links .double > ul li { - width: 155px; - } -} diff --git a/docs/3.0.x/docs/documents.html b/docs/3.0.x/docs/documents.html deleted file mode 100644 index 34268b2a98f..00000000000 --- a/docs/3.0.x/docs/documents.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose Documents v3.0.3Fork me on GitHub

Documents

Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

Retreiving

There are many ways to retreive documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

Updating

There are a number of ways to update documents. We'll first look at a traditional approach using findById:

Tank.findById(id, function (err, tank) {
-  if (err) return handleError(err);
-  
-  tank.size = 'large';
-  tank.save(function (err) {
-    if (err) return handleError(err);
-    res.send(tank);
-  });
-});

This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

If we do need the document returned in our application there is another, often better, option:

Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
-  if (err) return handleError(err);
-  res.send(tank);
-});

The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

Validating

Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

diff --git a/docs/3.0.x/docs/documents.jade b/docs/3.0.x/docs/documents.jade deleted file mode 100644 index 825224a4dc1..00000000000 --- a/docs/3.0.x/docs/documents.jade +++ /dev/null @@ -1,38 +0,0 @@ -extends layout - -block content - h2 Documents - :markdown - Mongoose [documents](./api.html#document-js) represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its [Model](./models.html). - h3 Retreiving - :markdown - There are many ways to retreive documents from MongoDB. We won't cover that in this section. See the chapter on [querying](./queries.html) for detail. - h3 Updating - :markdown - There are a number of ways to update documents. We'll first look at a traditional approach using [findById](./api.html#model_Model-findById): - :js - Tank.findById(id, function (err, tank) { - if (err) return handleError(err); - - tank.size = 'large'; - tank.save(function (err) { - if (err) return handleError(err); - res.send(tank); - }); - }); - :markdown - This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model-update) is right for us: - :js - Tank.update({ _id: id }, { $set: { size: 'large' }}, callback); - :markdown - If we do need the document returned in our application there is another, often [better](./api.html#model_Model-findByIdAndUpdate), option: - :js - Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) { - if (err) return handleError(err); - res.send(tank); - }); - :markdown - The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model-findByIdAndRemove) [several](./api.html#model_Model-findOneAndUpdate) [variations](./api.html#model_Model-findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. - h3 Validating - :markdown - Documents are validated before they are saved. Read the [api](./api.html#document_Document-validate) docs or the [validation](./validation.html) chapter for detail. diff --git a/docs/3.0.x/docs/faq.html b/docs/3.0.x/docs/faq.html deleted file mode 100644 index d5047a5de84..00000000000 --- a/docs/3.0.x/docs/faq.html +++ /dev/null @@ -1,31 +0,0 @@ -Mongoose FAQ v3.0.3Fork me on GitHub

FAQ

Q. Why don't my changes to arrays get saved when I update an element directly?

doc.array[3] = 'changed';
-doc.save();

A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

doc.markModified('array');
-doc.save();

Q. Why doesn't mongoose allow me to directly assign schemas to paths?

var userSchema = new Schema({ name: String });
-new Schema({ user: userSchema })

A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

doc.user.save();  // ?
-doc.user.remove();// ?
-doc.save()

We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


Q. How can I enable debugging?

- -

A. Set the debug option to true:

mongoose.set('debug', true)

Q. My save() callback never executes. What am I doing wrong?

- -

A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

// if connecting on the default mongoose connection
-mongoose.connect(..);
-mongoose.connection.on('error', handleError);
-
-// if connecting on a separate connection
-var conn = mongoose.createConnection(..);
-conn.on('error', handleError);
-

Something to add?

- -

If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


diff --git a/docs/3.0.x/docs/faq.jade b/docs/3.0.x/docs/faq.jade deleted file mode 100644 index 07abc7ea928..00000000000 --- a/docs/3.0.x/docs/faq.jade +++ /dev/null @@ -1,63 +0,0 @@ -extends layout - -block append style - style. - hr { - display: block; - margin: 30px 0; - } - -block content - h2 FAQ - :markdown - **Q**. Why don't my changes to arrays get saved when I update an element directly? - :js - doc.array[3] = 'changed'; - doc.save(); - :markdown - **A**. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving. - :js - doc.markModified('array'); - doc.save(); - hr - :markdown - **Q**. Why doesn't mongoose allow me to directly assign schemas to paths? - :js - var userSchema = new Schema({ name: String }); - new Schema({ user: userSchema }) - :markdown - **A**. Schemas have a one-to-one mapping with documents. Documents have `save` and `remove` methods along with their own `pre` and `post` hooks which would lead to code like the following: - :js - doc.user.save(); // ? - doc.user.remove();// ? - doc.save() - :markdown - We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling `save` on a sub-document is a no-op and exists only to support `pre` save hooks). In the future this is likely to be revisited. - hr - :markdown - **Q**. How can I enable debugging? - - **A**. Set the `debug` option to `true`: - :js - mongoose.set('debug', true) - hr - :markdown - **Q**. My `save()` callback never executes. What am I doing wrong? - - **A**. All `collection` actions (insert, remove, queries, etc) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. - :js - // if connecting on the default mongoose connection - mongoose.connect(..); - mongoose.connection.on('error', handleError); - - // if connecting on a separate connection - var conn = mongoose.createConnection(..); - conn.on('error', handleError); - - hr - :markdown - **Something to add?** - - If you'd like to contribute to this page, please [visit it](https://github.com/learnboost/mongoose/tree/master/docs/faq.jade) on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request. - br - diff --git a/docs/3.0.x/docs/guide.html b/docs/3.0.x/docs/guide.html deleted file mode 100644 index 6823194546b..00000000000 --- a/docs/3.0.x/docs/guide.html +++ /dev/null @@ -1,133 +0,0 @@ -Mongoose Schemas v3.0.3Fork me on GitHub

Schemas

If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

Defining your schema

Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

var blogSchema = new Schema({
-  title:  String,
-  author: String,
-  body:   String,
-  comments: [{ body: String, date: Date }],
-  date: { type: Date, default: Date.now },
-  hidden: Boolean,
-  meta: {
-    votes: Number,
-    favs:  Number
-  }
-})

If you want to add additional keys later, use the Schema#add method.

-Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above). For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType.

The permitted SchemaTypes are

  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • ObjectId
  • Array
Read more about them here.

Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

Pluggable

Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

Instance methods

Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

Defining an instance method is easy.

var animalSchema = new Schema({ name: String, type: String });
-
-animalSchema.methods.findSimilarTypes = function (cb) {
-  return this.model('Animal').find({ type: this.type }, cb);
-}

Now all of our animal instances have a findSimilarTypes method available to it.

var Animal = mongoose.model('Animal', animalSchema);
-var dog = new Animal({ type: 'dog' })
-
-dog.findSimilarTypes(function (err, dogs) {
-  console.log(dogs) // woof
-})

Statics

-Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

animalSchema.statics.findByName = function (name, cb) {
-  this.find({ name: new RegExp(name, 'i'), cb);
-}
-
-var Animal = mongoose.model('Animal', animalSchema);
-Animal.findByName('fido', function (err, animals) {
-  console.log(animals);
-})

Indexes

Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

animalSchema.index({ name: 1, type: -1 });

When your application starts up, Mongoose automatically calls ensureIndex for each defined index. This behavior can be disabled by setting the autoIndex option of your schema to false.

animalSchema.set('autoIndex', false)
-// or
-new Schema({..}, { autoIndex: false })

See also the Model#ensureIndexes method.

Virtuals

Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

var personSchema = new Schema({
-  name: {
-    first: String,
-    last: String
-  }
-});
-
-var Person = mongoose.model('Person', personSchema);
-
-var bad = new Person({
-    name: { first: 'Walter', last: 'White' }
-});

Suppose we want to log the full name of bad. We could do this manually like so:

console.log(bad.name.first + ' ' + bad.name.last); // Walter White

Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

personSchema.virtual('name.full').get(function () {
-  return this.name.first + ' ' + this.name.last;
-})

Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

console.log('%s is insane', bad.name.full) // Walter White is insane

It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

bad.name.full = 'Breaking Bad';

Mongoose let's you do this as well through its virtual attribute setters:

personSchema.virtual('name.full').set(function (name) {
-  var split = name.split(' ');
-  this.name.first = split[0];
-  this.name.last = split[1];
-})
-
-...
-
-mad.name.full = 'Breaking Bad';
-console.log(mad.name.first) // Breaking

If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

Options

Schemas have a few configurable options which can be passed to the constructor or set directly:

new Schema({..}, options);
-
-// or
-
-var schema = new Schema({..});
-schema.set(option, value);
-

Valid options:

- -

option: safe

This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

var safe = true;
-new Schema({ .. }, { safe: safe })
-

By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. -By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

- -

There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

var safe = { w: "majority", wtimeout: 10000 };
-new Schema({ .. }, { safe: safe })
-

option: strict

The strict option, (enabled by default), ensures that values added to our model instance that were not specified in our schema do not get saved to the db. -NOTE: do not set to false unless you have good reason.

var thingSchema = new Schema({..})
-var Thing = db.model('Thing', schemaSchema);
-var thing = new Thing({ iAmNotInTheSchema: true });
-thing.save() // iAmNotInTheSchema is not saved to the db
-
-// set to false..
-var thingSchema = new Schema({..}, { strict: false });
-var thing = new Thing({ iAmNotInTheSchema: true });
-thing.save() // iAmNotInTheSchema is now saved to the db!!
-

This value can be overridden at the model instance level by passing a second boolean argument:

var Thing = db.model('Thing');
-var thing = new Thing(doc, true);  // enables strict mode
-var thing = new Thing(doc, false); // disables strict mode
-

The strict option may also be set to "throw" which will cause errors to be produced instead of ignoring the bad data.

NOTE: in mongoose v2 the default was false.

option: shardKey

The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
-

Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

option: capped

Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

new Schema({..}, { capped: 1024 })

The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true })
-

option: versionKey

The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

var schema = new Schema({ name: 'string' });
-var Thing = db.model('Thing', schema);
-var thing = new Thing({ name: 'mongoose v3' });
-thing.save(); // { __v: 0, name: 'mongoose v3' }
-
-// customized versionKey
-new Schema({..}, { versionKey: '_somethingElse' })
-var Thing = db.model('Thing', schema);
-var thing = new Thing({ name: 'mongoose v3' });
-thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
-

Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

new Schema({..}, { versionKey: false })
-var Thing = db.model('Thing', schema);
-var thing = new Thing({ name: 'no versioning please' });
-thing.save(); // { name: 'no versioning please' }
-

option: autoIndex

At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

var schema = new Schema({..}, { autoIndex: false })
-var Clock = db.model('Clock', schema);
-Clock.ensureIndexes(callback);
-

option: _id

Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

- -

Pass this option during schema construction to prevent documents from getting an auto _id created.

// default behavior
-var schema = new Schema({ name: String });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
-
-// disabled _id
-var schema = new Schema({ name: String }, { _id: false });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p); // { name: 'mongodb.org' }
-

option: id

Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

// default behavior
-var schema = new Schema({ name: String });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p.id); // '50341373e894ad16347efe01'
-
-// disabled id
-var schema = new Schema({ name: String }, { id: false });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p.id); // undefined
-
diff --git a/docs/3.0.x/docs/guide.jade b/docs/3.0.x/docs/guide.jade deleted file mode 100644 index b855bb34f9a..00000000000 --- a/docs/3.0.x/docs/guide.jade +++ /dev/null @@ -1,364 +0,0 @@ -extends layout - -block content - h2 Schemas - :markdown - If you haven't yet done so, please take a minute to read the [quickstart](./index.html) to get an idea of how Mongoose works. - :markdown - If you are migrating from 2.x to 3.x please take a moment to read the [migration guide](./migration.html). - :markdown - This page covers `Schema` [definition](#definition), [plugins](#plugins), instance [methods](#methods), [statics](#statics), [indexes](#indexes), [virtuals](#virtuals) and [options](#options). Let's start with `Schema` definition. - h3#definition Defining your schema - p - | Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection. - :js - var blogSchema = new Schema({ - title: String, - author: String, - body: String, - comments: [{ body: String, date: Date }], - date: { type: Date, default: Date.now }, - hidden: Boolean, - meta: { - votes: Number, - favs: Number - } - }) - p - em - | If you want to add additional keys later, use the - a(href="./api.html#schema_Schema-add") Schema#add - | method. - p - | Each key in our - code blogSchema - | defines a property in our documents which will be cast to its associated - a(href="./api.html#schematype_SchemaType") SchemaType - |. Keys may also be assigned nested objects containing further key/type definitions - em (e.g. the `meta` property above). - | For example, we've defined a - code title - | which will be cast to the - a(href="./api.html#schema-string-js") String - | SchemaType and - code date - | which will be cast to a - code Date - | SchemaType. - p - | The permitted SchemaTypes are - ul - li String - li Number - li Date - li Buffer - li Boolean - li Mixed - li ObjectId - li Array - | Read more about them - a(href="./schematypes.html") here - | . - p - | Schemas not only define the structure of your document and casting of properties, they also define document - a(href="#methods") instance methods - |, static - a(href="#statics") Model methods - |, - a(href="#indexes") compound indexes - | and document lifecycle hooks called - a(href="./middleware.html") middleware - |. - h3#plugins Pluggable - p - | Schemas are - a(href="./plugins.html") pluggable - | which allows us to package up reusable features into - a(href="http://plugins.mongoosejs.com") plugins - | that can be shared with the community or just between your projects. - h3#methods Instance methods - p - a(href="./models.html") Models - | are just fancy - code constructor - | functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are - a(href="./documents.html") documents - |. - p - | Defining an instance method is easy. - :js - var animalSchema = new Schema({ name: String, type: String }); - - animalSchema.methods.findSimilarTypes = function (cb) { - return this.model('Animal').find({ type: this.type }, cb); - } - p - | Now all of our - code animal - | instances have a - code findSimilarTypes - | method available to it. - :js - var Animal = mongoose.model('Animal', animalSchema); - var dog = new Animal({ type: 'dog' }) - - dog.findSimilarTypes(function (err, dogs) { - console.log(dogs) // woof - }) - h3#statics Statics - p - | Adding static constructor methods to Models is simple as well. Continuing with our - code animalSchema - |: - :js - animalSchema.statics.findByName = function (name, cb) { - this.find({ name: new RegExp(name, 'i'), cb); - } - - var Animal = mongoose.model('Animal', animalSchema); - Animal.findByName('fido', function (err, animals) { - console.log(animals); - }) - h3#indexes Indexes - p - a(href="http://www.mongodb.org/display/DOCS/Indexes") Indexes - | can be defined - a(href="./api.html#schematype_SchemaType-index") at - | - a(href="./api.html#schematype_SchemaType-unique") the - | - a(href="./api.html#schematype_SchemaType-sparse") path - | - a(href="./api.html#schematype_SchemaType-expires") level - | or the - code schema - | level. Defining indexes at the schema level is necessary when defining - a(href="http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys", target="_blank") compound indexes - |. - :js - animalSchema.index({ name: 1, type: -1 }); - p - | When your application starts up, Mongoose automatically calls - code ensureIndex - | for each defined index. This behavior can be disabled by setting the - code autoIndex - | option of your schema to false. - :js - animalSchema.set('autoIndex', false) - // or - new Schema({..}, { autoIndex: false }) - p - | See also the - a(href="./api.html#model_Model-ensureIndexes") - code Model#ensureIndexes - | method. - - h3#virtuals Virtuals - :markdown - [Virtual](./api.html#schema_Schema-virtual) attributes are attributes that are convenient to have around but that do not get persisted to MongoDB. - :js - var personSchema = new Schema({ - name: { - first: String, - last: String - } - }); - - var Person = mongoose.model('Person', personSchema); - - var bad = new Person({ - name: { first: 'Walter', last: 'White' } - }); - :markdown - Suppose we want to log the full name of `bad`. We could do this manually like so: - :js - console.log(bad.name.first + ' ' + bad.name.last); // Walter White - :markdown - Or we could add a `virtual` attribute [getter](./api.html#virtualtype_VirtualType-get) to our `personSchema` so we don't need to write out this string concatenation mess each time: - :js - personSchema.virtual('name.full').get(function () { - return this.name.first + ' ' + this.name.last; - }) - :markdown - Now, when we access our virtual full name property, our getter function will be invoked and the value returned: - :js - console.log('%s is insane', bad.name.full) // Walter White is insane - :markdown - It would also be nice to be able to set `this.name.first` and `this.name.last` by setting `this.name.full`. For example, if we wanted to change `bad`'s `name.first` and `name.last` to 'Breaking' and 'Bad' respectively, it'd be nice to just: - :js - bad.name.full = 'Breaking Bad'; - :markdown - Mongoose lets you do this as well through its virtual attribute [setters](./api.html#virtualtype_VirtualType-set): - :js - personSchema.virtual('name.full').set(function (name) { - var split = name.split(' '); - this.name.first = split[0]; - this.name.last = split[1]; - }) - - ... - - mad.name.full = 'Breaking Bad'; - console.log(mad.name.first) // Breaking - :markdown - If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you. - - h3#options Options - :markdown - `Schema`s have a few configurable options which can be passed to the constructor or `set` directly: - :js - new Schema({..}, options); - - // or - - var schema = new Schema({..}); - schema.set(option, value); - - :markdown - Valid options: - - - [safe](#safe) - - [strict](#strict) - - [capped](#capped) - - [versionKey](#versionKey) - - [shardKey](#shardKey) - - [autoIndex](#autoIndex) - - [_id](#_id) - - [id](#id) - - h4#safe option: safe - :markdown - This option is passed to MongoDB with all operations and specifies if errors should be returned to our callbacks as well as tune write behavior. - - :js - var safe = true; - new Schema({ .. }, { safe: safe }) - - :markdown - By default this is set to `true` for all schemas which guarentees that any occurring error gets passed back to our callback. - By setting `safe` to something else like `{ j: 1, w: 2, wtimeout: 10000 }` we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback. - - There are other write concerns like `{ w: "majority" }` too. See the MongoDB [docs](http://www.mongodb.org/display/DOCS/getLastError+Command) for more details. - - :js - var safe = { w: "majority", wtimeout: 10000 }; - new Schema({ .. }, { safe: safe }) - - h4#strict option: strict - :markdown - The strict option, (enabled by default), ensures that values added to our model instance that were not specified in our schema do not get saved to the db. - _NOTE: do not set to false unless you have good reason._ - - :js - var thingSchema = new Schema({..}) - var Thing = db.model('Thing', schemaSchema); - var thing = new Thing({ iAmNotInTheSchema: true }); - thing.save() // iAmNotInTheSchema is not saved to the db - - // set to false.. - var thingSchema = new Schema({..}, { strict: false }); - var thing = new Thing({ iAmNotInTheSchema: true }); - thing.save() // iAmNotInTheSchema is now saved to the db!! - - :markdown - This value can be overridden at the model instance level by passing a second boolean argument: - - :js - var Thing = db.model('Thing'); - var thing = new Thing(doc, true); // enables strict mode - var thing = new Thing(doc, false); // disables strict mode - - :markdown - The `strict` option may also be set to `"throw"` which will cause errors to be produced instead of ignoring the bad data. - - :markdown - _NOTE: in mongoose v2 the default was false._ - - h4#shardKey option: shardKey - :markdown - The `shardKey` option is used when we have a [sharded MongoDB architecture](http://www.mongodb.org/display/DOCS/Sharding+Introduction). Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set. - - :js - new Schema({ .. }, { shardkey: { tag: 1, name: 1 }}) - - :markdown - _Note that Mongoose does not send the `shardcollection` command for you. You must configure your shards yourself._ - - h4#capped option: capped - :markdown - Mongoose supports MongoDBs [capped](http://www.mongodb.org/display/DOCS/Capped+Collections) collections. To specify the underlying MongoDB collection be `capped`, set the `capped` option to the maximum size of the collection in [bytes](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-size.). - :js - new Schema({..}, { capped: 1024 }) - :markdown - The `capped` option may also be set to an object if you want to pass additional options like [max](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-max) or [autoIndexId](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-autoIndexId). In this case you must explicitly pass the `size` option which is required. - :js - new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true }) - - h4#versionKey option: versionKey - :markdown - The `versionKey` is a property set on each document when first created by Mongoose. This keys value contains the internal [revision](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning) of the document. The name of this document property is configurable. The default is `__v`. If this conflicts with your application you can configure as such: - :js - var schema = new Schema({ name: 'string' }); - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'mongoose v3' }); - thing.save(); // { __v: 0, name: 'mongoose v3' } - - // customized versionKey - new Schema({..}, { versionKey: '_somethingElse' }) - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'mongoose v3' }); - thing.save(); // { _somethingElse: 0, name: 'mongoose v3' } - - :markdown - Document versioning can also be disabled by setting the `versionKey` to false. _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning)._ - :js - new Schema({..}, { versionKey: false }) - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'no versioning please' }); - thing.save(); // { name: 'no versioning please' } - - h4#autoIndex option: autoIndex - :markdown - At application startup, Mongoose sends an `ensureIndex` command for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model-ensureIndexes) method on your model. - :js - var schema = new Schema({..}, { autoIndex: false }) - var Clock = db.model('Clock', schema); - Clock.ensureIndexes(callback); - - h4#_id option: _id - :markdown - Mongoose assigns each of your schemas an `_id` field by default if one is not passed into the [Schema](/docs/api.html#schema-js) constructor. The type assiged is an [ObjectId](/docs/api.html#schema_Schema-Types) to coincide with MongoDBs default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option. - - Pass this option during schema construction to prevent documents from getting an auto `_id` created. - :js - // default behavior - var schema = new Schema({ name: String }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' } - - // disabled _id - var schema = new Schema({ name: String }, { _id: false }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p); // { name: 'mongodb.org' } - - h4#id option: id - :markdown - Mongoose assigns each of your schemas an `id` virtual getter by default which returns the documents `_id` field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an `id` getter added to your schema, you may disable it passing this option at schema construction time. - :js - // default behavior - var schema = new Schema({ name: String }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p.id); // '50341373e894ad16347efe01' - - // disabled id - var schema = new Schema({ name: String }, { id: false }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p.id); // undefined - -script. -document.body.className = 'load'; -include includes/googleanalytics diff --git a/docs/3.0.x/docs/helpers/filters.js b/docs/3.0.x/docs/helpers/filters.js deleted file mode 100644 index 33546a7e805..00000000000 --- a/docs/3.0.x/docs/helpers/filters.js +++ /dev/null @@ -1,20 +0,0 @@ - -var hl = require('highlight.js') - -module.exports = exports = function (jade) { - // add highlighting filter to jade - - jade.filters.js = function (str) { - str = str.replace(/\\n/g, '\n'); - var ret = hl.highlight('javascript', str).value; - var code = '
' + ret.replace(/\n/g, '\\n') + '
'; - return code; - } - - jade.filters.bash = function (str) { - var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; - var code = '
' + ret + '
'; - return code - } - -} diff --git a/docs/3.0.x/docs/helpers/highlight.js b/docs/3.0.x/docs/helpers/highlight.js deleted file mode 100644 index 8aca9b9e222..00000000000 --- a/docs/3.0.x/docs/helpers/highlight.js +++ /dev/null @@ -1,11 +0,0 @@ - -var h = require('highlight.js') - -function hl (str) { - str = str.replace(/\\n/g, '\n'); - var ret = h.highlight('javascript', str).value; - var code = '
' + ret+ '
'; - return code; -} - -module.exports = hl; diff --git a/docs/3.0.x/docs/helpers/href.js b/docs/3.0.x/docs/helpers/href.js deleted file mode 100644 index e7299b1cf0d..00000000000 --- a/docs/3.0.x/docs/helpers/href.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str, char) { - if ('string' != typeof str) return str; - return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); -} diff --git a/docs/3.0.x/docs/helpers/klass.js b/docs/3.0.x/docs/helpers/klass.js deleted file mode 100644 index 0c4a865b43b..00000000000 --- a/docs/3.0.x/docs/helpers/klass.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str) { - var parts = str.replace(/\.js$/, '').split('/'); - return parts.join('_'); -} diff --git a/docs/3.0.x/docs/helpers/linktype.js b/docs/3.0.x/docs/helpers/linktype.js deleted file mode 100644 index 997e740f671..00000000000 --- a/docs/3.0.x/docs/helpers/linktype.js +++ /dev/null @@ -1,50 +0,0 @@ - -var types = {}; -types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; -types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' -types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' -types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' -types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' -types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' -types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' -types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' -types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' -types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' - -// mongoose -types.ObjectId = '#types_objectid_ObjectId'; -types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; -types.MongooseArray = '#types_array_MongooseArray'; -types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; -types.Query = '#query-js'; -types.QueryStream = '#querystream_QueryStream'; -types.Document = '#document_Document'; -types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; -types.Document = '#document_Document'; -types.Model = '#model_Model'; -types.Connection = '#connection_Connection'; -types.Collection = '#collection_Collection'; -types.Schema = '#schema_Schema'; -types.Promise = '#promise_Promise'; -types.Mongoose = '#index_Mongoose'; -types.MongooseError = '#error_MongooseError'; -types.Type = '#schematype_SchemaType'; // ? -types.SchemaType = '#schematype_SchemaType'; -types.SchemaArray = '#schema_array_SchemaArray'; -types.Mixed = '#schema_mixed_Mixed'; -types.VirtualType = '#virtualtype_VirtualType'; -types.MongooseBuffer = '#types_buffer_MongooseBuffer'; -types.Buffer = 'http://nodejs.org/api/buffer.html'; - -module.exports= function (type) { - if (types[type]) { - return '' + type + ''; - } - return '' + type + ''; -} - -module.exports.types = types; -module.exports.type = function (str) { - if (types[str]) return types[str]; - return str; -} diff --git a/docs/3.0.x/docs/images/apps/grab b/docs/3.0.x/docs/images/apps/grab deleted file mode 100755 index ca314e9e858..00000000000 --- a/docs/3.0.x/docs/images/apps/grab +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -#make sure firefox launches in the bottom right corner of the window - -# read URLs from a data file in a loop -#regex='([^[:space:]]+)[[:space:]]*(.*)' -regex='([^[:space:]]+)[|]([^|]+)[|](.*)' - -func() { - [[ $1 =~ $regex ]] - url=${BASH_REMATCH[1]} - # remove middle space, lowercase - name=`echo ${BASH_REMATCH[2]} | tr -d '[[:space:]]' | tr '[A-Z]' '[a-z]'` - desc=${BASH_REMATCH[3]} - - # send URL to the firefox session - # firefox --width 1030 --height 768 $url & - /Applications/Firefox.app/Contents/MacOS/firefox --width 1030 --height 768 $url & - echo started firefox with $url - echo preparing screencapture ... - - # take a picture after waiting a bit for the load to finish - sleep 6 - # gm import -window root -crop 1004x768+414+228 -resize 500x350 $name.png - screencapture -wo $name.png - gm convert $name.png -crop 1004x768+0+80 -resize 200x140 $name.png - echo grabbed screenshot $name.png -} - -if [ $1 ] -then - func "$1 $2" -else - while read line - do - func $line - done < urls -fi - diff --git a/docs/3.0.x/docs/images/apps/urls b/docs/3.0.x/docs/images/apps/urls deleted file mode 100644 index ca924705938..00000000000 --- a/docs/3.0.x/docs/images/apps/urls +++ /dev/null @@ -1,21 +0,0 @@ -https://www.learnboost.com|LearnBoost|is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students. -http://storify.com/|Storify|lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative. -https://clickdummy.com|ClickDummy|is a rapid mockup prototyping application for designers and dummies. -http://scottyapp.com|Scotty App|allows you to create data driven backends for your apps in minutes instead of weeks. -http://geekli.st|Geeklist|is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found. -https://bozuko.com|Bozuko|is an exciting customer rewards program. -http://calllistapp.com|Call List|helps you maintain a todo list for people you need to call. -http://www.gtggolf.com|Grow The Game Golf|lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more. -http://nextdays.com/|nextdays|lets you share plans with friends and discover what is happening around you. -http://linkr.cc|Linkr|is a service for saving links for reading later. -http://www.attictv.com/|AtticTV|is Music Television (MTV) for the web. -https://localresponse.com|LocalResponse|helps marketers respond to real-time consumer intent. -http://selectvids.com|Select Vids|is a collection of amazing, funny, and creative videos for you to discover. -https://cldfy.com/|cldfy|delivers mail to your app. -http://www.sharelatex.com|ShareLatex|is a real-time LaTeX collaboration tool. -http://apps.newleafdigital.com/lists|Lists|is a service for saving links for reading later. -http://cyborgvisionapp.com/|Cyborg Vision|uses real-time facial recognition to identify your friends and show their information. -https://wavo.me/|Wavo|lets you express yourself through the songs you love. -http://seelio.com/|seelio|is a stage for college students to distinguish themselves and connect with companies. -http://todaylaunch.com/|TodayLaunch|is a free dashboard for your social media accounts. -http://st.achify.com/|Stachify| diff --git a/docs/3.0.x/docs/images/square_bg.png b/docs/3.0.x/docs/images/square_bg.png deleted file mode 100644 index f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.0.3Fork me on GitHub

Getting Started

First be sure you have MongoDB and Nodejs installed.

Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. -The first thing we need to do is include mongoose in our project and open a connection.

var mongoose = require('mongoose')
-  , db = mongoose.createConnection('localhost', 'test');

We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

db.on('error', console.error.bind(console, 'connection error:'));
-db.once('open', function () {
-  // yay!
-});

Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

var kittySchema = new mongoose.Schema({
-    name: String
-})

So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a model.

var Kitten = db.model('Kitten', kittySchema)

A model is a class with which we construct documents. -In this case, each document will be a kitten with properties and behaviors as declared in our schema. -Let's create a kitten document representing the little guy we just met on the sidewalk outside:

var silence = new Kitten({ name: 'Silence' })
-console.log(silence.name) // 'Silence'

Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

kittySchema.methods.speak = function () {
-  var greeting = this.name
-    ? 'Meow name is ' + this.name
-    : 'I don't have a name'
-  console.log(greeting);
-}
-
-var Kitten = db.model('Kitten', kittySchema)

Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

var fluffy = new Kitten({ name: 'fluffy' });
-fluffy.speak() // "Meow name is fluffy"

We have talking kittens! But we still haven't saved anything to MongoDB. -Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

fluffy.save(function (err) {
-  if (err) // TODO handle the error
-  console.log('meow')
-});

Say time goes by and we want to display all the kittens we've seen. -We can access all of the kitten documents through our Kitten model.

Kitten.find(function (err, kittens) {
-  if (err) // TODO handle err
-  console.log(kittens)
-})

We just logged all of the kittens in our db to the console. -If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax.

Kitten.find({ name: /fluff/i }, callback)

This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback.

Congratulations

That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or api docs for more.

diff --git a/docs/3.0.x/docs/index.jade b/docs/3.0.x/docs/index.jade deleted file mode 100644 index 3d0c597da6b..00000000000 --- a/docs/3.0.x/docs/index.jade +++ /dev/null @@ -1,119 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose Quick Start v#{package.version} - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - link(href='css/guide.css', rel='stylesheet', type='text/css') - style. - body.api - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - #content - .module - h2 Getting Started - p - em - | First be sure you have - a(href="http://www.mongodb.org/downloads") MongoDB - | and - a(href="http://nodejs.org/") Nodejs - | installed. - p - | Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. - | The first thing we need to do is include mongoose in our project and open a connection. - :js - var mongoose = require('mongoose') - , db = mongoose.createConnection('localhost', 'test'); - p We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs: - :js - db.on('error', console.error.bind(console, 'connection error:')); - db.once('open', function () { - // yay! - }); - p Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback. - p - | With Mongoose, everything is derived from a - a(href="./api.html#schema_Schema") Schema - | . Let's get a reference to it and define our kittens. - :js - var kittySchema = new mongoose.Schema({ - name: String - }) - p - | So far so good. We've got a schema with one property, - code name - | , which will be a - code String - | . The next step is compiling our schema into a - a(href="./api.html#model_Model") model - | . - :js - var Kitten = db.model('Kitten', kittySchema) - p - | A model is a class with which we construct documents. - | In this case, each document will be a kitten with properties and behaviors as declared in our schema. - | Let's create a kitten document representing the little guy we just met on the sidewalk outside: - :js - var silence = new Kitten({ name: 'Silence' }) - console.log(silence.name) // 'Silence' - p Kittens can meow, so let's take a look at how to add "speak" functionality to our documents: - :js - kittySchema.methods.speak = function () { - var greeting = this.name - ? 'Meow name is ' + this.name - : 'I don't have a name' - console.log(greeting); - } - - var Kitten = db.model('Kitten', kittySchema) - p - | Functions added to the - code methods - | property of a schema get compiled into the Model prototype and exposed on each document instance: - :js - var fluffy = new Kitten({ name: 'fluffy' }); - fluffy.speak() // "Meow name is fluffy" - p - | We have talking kittens! But we still haven't saved anything to MongoDB. - | Each document can be saved to the database by calling its - code save - | method. The first argument to the callback will be an error if any occured. - :js - fluffy.save(function (err) { - if (err) // TODO handle the error - console.log('meow') - }); - p - | Say time goes by and we want to display all the kittens we've seen. - | We can access all of the kitten documents through our Kitten model. - :js - Kitten.find(function (err, kittens) { - if (err) // TODO handle err - console.log(kittens) - }) - p - | We just logged all of the kittens in our db to the console. - | If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax. - :js - Kitten.find({ name: /fluff/i }, callback) - p - | This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback. - h3 Congratulations - p - | That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the - a(href="guide.html") guide - | , or - a(href="api.html") api docs - | for more. - script. - document.body.className = 'load'; - include includes/googleanalytics diff --git a/docs/3.0.x/docs/js/zepto.min.js b/docs/3.0.x/docs/js/zepto.min.js deleted file mode 100644 index 428f84a28c5..00000000000 --- a/docs/3.0.x/docs/js/zepto.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */ -(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.0.x/docs/layout.jade b/docs/3.0.x/docs/layout.jade deleted file mode 100644 index 6585074f210..00000000000 --- a/docs/3.0.x/docs/layout.jade +++ /dev/null @@ -1,25 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose #{title} v#{package.version} - block style - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - link(href='css/guide.css', rel='stylesheet', type='text/css') - body - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - #content - .module - block content - script. - document.body.className = 'load'; - include includes/googleanalytics diff --git a/docs/3.0.x/docs/middleware.html b/docs/3.0.x/docs/middleware.html deleted file mode 100644 index 269aba2b32c..00000000000 --- a/docs/3.0.x/docs/middleware.html +++ /dev/null @@ -1,29 +0,0 @@ -Mongoose Middleware v3.0.3Fork me on GitHub

Middleware

Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

-There are two types of middleware, serial and parallel.

Serial

Serial middleware are executed one after another, when each middleware calls next

var schema = new Schema(..);
-schema.pre('save', function (next) {
-  // do stuff
-  next();
-});

Parallel

Parallel middleware offer more fine-grained flow control.

var schema = new Schema(..);
-schema.pre('save', true, function (next, done) {
-  // calling next kicks off the next middleware in parallel
-  next();
-  doAsync(done);
-});

The hooked method, in this case save, will not be executed until done is called by each middleware.

Use Cases

Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

  • complex validation
  • removing dependent documents
    • (removing a user removes all his blogposts)
  • asynchronous defaults
  • asynchronous tasks that a certain action triggers
    • triggering custom events
    • notifications

Error handling

If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

schema.pre('save', function (next) {
-  var err = new Error('something went wrong');
-  next(err);
-});
-
-// later...
-
-myModel.save(function (err) {
-  console.log(err.message) // something went wrong
-});
-
diff --git a/docs/3.0.x/docs/middleware.jade b/docs/3.0.x/docs/middleware.jade deleted file mode 100644 index 716d03831b4..00000000000 --- a/docs/3.0.x/docs/middleware.jade +++ /dev/null @@ -1,71 +0,0 @@ -extends layout - -block content - h2 Middleware - p - | Middleware are functions which are passed control of flow during execution of - a(href="./api.html#document_Document-init") init - |, - a(href="./api.html#document_Document-validate") validate - |, - a(href="./api.html#model_Model-save") save - | and - a(href="./api.html#model_Model-remove") remove - | methods. - p - | There are two types of middleware, serial and parallel. - h4 Serial - p - | Serial middleware are executed one after another, when each middleware calls - code next - :js - var schema = new Schema(..); - schema.pre('save', function (next) { - // do stuff - next(); - }); - h4 Parallel - p - | Parallel middleware offer more fine-grained flow control. - :js - var schema = new Schema(..); - schema.pre('save', true, function (next, done) { - // calling next kicks off the next middleware in parallel - next(); - doAsync(done); - }); - p - | The hooked method, in this case - code save - |, will not be executed until - code done - | is called by each middleware. - h4 Use Cases - p - | Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas: - ul - li complex validation - li - | removing dependent documents - ul - li (removing a user removes all his blogposts) - li asynchronous defaults - li asynchronous tasks that a certain action triggers - ul - li triggering custom events - li notifications - h4 Error handling - :markdown - If any middleware calls `next` or `done` with an `Error` instance, the flow is interrupted, and the error is passed to the callback. - :js - schema.pre('save', function (next) { - var err = new Error('something went wrong'); - next(err); - }); - - // later... - - myModel.save(function (err) { - console.log(err.message) // something went wrong - }); - diff --git a/docs/3.0.x/docs/migration.html b/docs/3.0.x/docs/migration.html deleted file mode 100644 index 0a053078374..00000000000 --- a/docs/3.0.x/docs/migration.html +++ /dev/null @@ -1,38 +0,0 @@ -Mongoose Migration Guide v3.0.3Fork me on GitHub

Migrating from 2.x to 3.x

Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

Query clean-up

Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

- -

Here are the removed methods are their still existing aliases:

RemovedAlternative
query.runquery.exec
query.$orquery.or
query.$norquery.nor
query.$gtquery.gt
query.$gtequery.gte
query.$ltquery.lt
query.$ltequery.lte
query.$nequery.ne
query.$inquery.in
query.$ninquery.nin
query.$allquery.all
query.$regexquery.regex
query.$sizequery.size
query.$maxDistancequery.maxDistance
query.$modquery.mod
query.$nearquery.near
query.$existsquery.exists
query.$elemMatchquery.elemMatch
query.$withinquery.within
query.$boxquery.box
query.$centerquery.center
query.$centerSpherequery.centerSphere
query.$slicequery.slice
query.notEqualToquery.ne
query.whereinquery.within
query.ascquery.sort *
query.descquery.sort *
query.fieldsquery.select *

query#asc

The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

query#desc

The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

query#sort

The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

query#fields

The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

- -

Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

Connecting to ReplicaSets

To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

Schemas

  • are now strict by default.
  • Arrays of object literal now creates document arrays instead of arrays of Mixed.
  • Indexes are now created in background by default.
  • Index errors are now emitted on their model instead of the connection. See issue #984.

Arrays

  • pop is now fixed causing a $set of the entire array.
  • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
  • shift is now fixed causing a $set of the entire array.
  • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
  • $unshift was removed, use unshift instead.
  • $addToSet was removed, use addToSet instead.
  • $pushAll was removed, use push instead.
  • $pull was removed, use pull instead.
  • $pullAll was removed, use pull instead.
  • doAtomics was changed to the hasAtomics private method

Number type

The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

- -

With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

- -
  • $inc
  • $increment
  • $decrement
- -

If you really want this behavior back, include the mongoose-number module in your project.

- -

A good alternative is to start using the new findAndModify helpers. -Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

var inventorySchema = new Schema({ productCount: Number });
-...
-Inventory.findById(id, function (err, inventory) {
-  if (err) return handleError(err);
-  inventory.productCount.$decrement(7);
-  inventory.save(function (err) {
-    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
-    if (err) return handleError(err);
-    res.send(inventory.productCount); // 3
-  });
-});

With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
-  if (err) return handleError(err);
-  res.send(inventory.productCount); // 3
-});

The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

Documents

getter casting

Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

setter order

Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This changes allows more flexible processing of values in setters. See issue #665 and pull #924.

Subdocuments

  • subdoc.parent was changed from a property to a method. See issue #928.
  • subdoc.parentArray was changed from a property to a method. See issue #928.

String match validator

The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

Versioning

Documents are now transparently versioned. Read the in depth details here.

diff --git a/docs/3.0.x/docs/migration.jade b/docs/3.0.x/docs/migration.jade deleted file mode 100644 index 3fca606562a..00000000000 --- a/docs/3.0.x/docs/migration.jade +++ /dev/null @@ -1,272 +0,0 @@ -extends layout - -block append style - style. - table td { - padding-right: 15px; - } - -block content - h2 Migrating from 2.x to 3.x - :markdown - Migrating from Mongoose 2.x to 3.x brings with it [several changes](https://github.com/LearnBoost/mongoose/blob/master/History.md) to be aware of: - - h3 Query clean-up - :markdown - Many methods of the [Query](./api.html#query-js) API were nothing but aliases and have been [removed](https://github.com/LearnBoost/mongoose/commit/1149804c) in an effort to keep Mongoose clean and focused on there being as close to [one way](http://www.python.org/dev/peps/pep-0020/) of doing things as possible. If you really love all that extra noise, you can bring most of it back with [this module](https://github.com/aheckmann/mongoose-v2-compat). - - Here are the removed methods are their still existing aliases: - table - thead - tr(style='text-align:left') - th Removed - th Alternative - tbody - tr - td - code query.run - td - code query.exec - tr - td - code query.$or - td - code query.or - tr - td - code query.$nor - td - code query.nor - tr - td - code query.$gt - td - code query.gt - tr - td - code query.$gte - td - code query.gte - tr - td - code query.$lt - td - code query.lt - tr - td - code query.$lte - td - code query.lte - tr - td - code query.$ne - td - code query.ne - tr - td - code query.$in - td - code query.in - tr - td - code query.$nin - td - code query.nin - tr - td - code query.$all - td - code query.all - tr - td - code query.$regex - td - code query.regex - tr - td - code query.$size - td - code query.size - tr - td - code query.$maxDistance - td - code query.maxDistance - tr - td - code query.$mod - td - code query.mod - tr - td - code query.$near - td - code query.near - tr - td - code query.$exists - td - code query.exists - tr - td - code query.$elemMatch - td - code query.elemMatch - tr - td - code query.$within - td - code query.within - tr - td - code query.$box - td - code query.box - tr - td - code query.$center - td - code query.center - tr - td - code query.$centerSphere - td - code query.centerSphere - tr - td - code query.$slice - td - code query.slice - tr - td - code query.notEqualTo - td - code query.ne - tr - td - code query.wherein - td - code query.within - tr - td - code query.asc - td - code - | query.sort - a(href="#asc") * - tr - td - code query.desc - td - code - | query.sort - a(href="#desc") * - tr - td - code query.fields - td - code - | query.select - a(href="#fields") * - - h4#asc query#asc - :markdown - The `asc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#desc query#desc - :markdown - The `desc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#sort query#sort - :markdown - The [sort](./api.html#query_Query-sort) method of [Queries](./api.html#query-js) now accepts slightly different arguments. Read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#fields query#fields - :markdown - The `fields` method of [Query](./api.html#query-js) has been removed, it being mostly an alias for the [select](./api.html#query_Query-select) method anyway. The `select` method has slightly different arguments so read the [docs](./api.html#query_Query-select) to make sure your application is all set. - - Because of the change to the `fields` method, the field selection argument for [query.populate](./api.html#query_Query-populate) and model methods like [findById](./api.html#model_Model-findById), [find](./api.html#model_Model-find), etc, is slightly different as well (no longer accepts arrays for example), so read the [docs](./api.html#query_Query-select) to make sure your application is all set. - - h3 Connecting to ReplicaSets - :markdown - To connect to a [ReplicaSet](http://www.mongodb.org/display/DOCS/Replica+Sets) you no longer use the separate `connectSet` or `createSetConnection` methods. Both [mongoose.connect](./api.html#index_Mongoose-connect) and [mongoose.createConnection](./api.html#index_Mongoose-createConnection) are now smart enough to just do the right thing with your connection string. If you really want to bring `connectSet` and `createSetConnection` back use [this module](https://github.com/aheckmann/mongoose-v2-compat). - - h3 Schemas - :markdown - - are now [strict](./guide.html#strict) by default. - - Arrays of [object literal](./subdocs.html#altsyntax) now creates document arrays instead of arrays of [Mixed](./schematypes.html#mixed). - - Indexes are now created in [background](./guide.html#autoIndex) by default. - - Index errors are now emitted on their model instead of the connection. See issue [#984](https://github.com/LearnBoost/mongoose/issues/984). - - h3#arrays Arrays - :markdown - - [pop](./api.html#types_array_MongooseArray-pop) is now fixed causing a $set of the entire array. - - [$pop](./api.html#types_array_MongooseArray-%24pop) is now fixed and behaves just as MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the last element of the array. - - [shift](./api.html#types_array_MongooseArray-shift) is now fixed causing a $set of the entire array. - - [$shift](./api.html#types_array_MongooseArray-%24shift) is now fixed and behaves just as a [MongoDB $pop -1](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the first element of array. - - `$unshift` was removed, use [unshift](./api.html#types_array_MongooseArray-unshift) instead. - - `$addToSet` was removed, use [addToSet](./api.html#types_array_MongooseArray-addToSet) instead. - - `$pushAll` was removed, use [push](./api.html#types_array_MongooseArray-push) instead. - - `$pull` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. - - `$pullAll` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. - - `doAtomics` was changed to the [hasAtomics](./api.html#types_array_MongooseArray-hasAtomics) private method - - h3#mongoosenumber Number type - :markdown - The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused [too many problems](https://groups.google.com/d/msg/mongoose-orm/syKlN2xL1EE/FfRFhEFj4KcJ) when doing comparisons and had other bad side-effects. - - With it out of the picture, the following helper methods of MongooseNumbers are now also gone: - - - $inc - - $increment - - $decrement - - If you really want this behavior back, include the [mongoose-number](https://github.com/aheckmann/mongoose-number) module in your project. - - A good alternative is to start using the new [findAndModify](./api.html#model_Model-findOneAndUpdate) [helpers](./api.html#model_Model-findOneAndRemove). - Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber: - :js - var inventorySchema = new Schema({ productCount: Number }); - ... - Inventory.findById(id, function (err, inventory) { - if (err) return handleError(err); - inventory.productCount.$decrement(7); - inventory.save(function (err) { - // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback); - if (err) return handleError(err); - res.send(inventory.productCount); // 3 - }); - }); - :markdown - With MongooseNumber out of the picture, we'll instead use the [Account.findByIdAndUpdate](./api.html#model_Model-findByIdAndUpdate) helper: - :js - Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) { - if (err) return handleError(err); - res.send(inventory.productCount); // 3 - }); - :markdown - The `findByIdAndUpdate` helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases. - - h3#documents Documents - :markdown - - `doc#commit` is now removed, use [doc.markModified](./api.html#document_Document-markModified) instead - - [doc#modifiedPaths](./api.html#document_Document-modifiedPaths) is now a method not a getter - - `doc.modified` is now removed, use [doc.isModified](./api.html#document_Document-isModified) instead - - h4#gettercasting getter casting - :markdown - Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue [#820](https://github.com/LearnBoost/mongoose/issues/820) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). - - h4#setterorder setter order - :markdown - Values being set no longer cast until _after_ all setters have been applied. Previously the value returned from each setter was cast _before_ passing it on to the next setter. This changes allows more flexible processing of values in setters. See issue [#665](https://github.com/learnboost/mongoose/issues/665) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). - - h3#subdocs Subdocuments - :markdown - - `subdoc.parent` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parent). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). - - `subdoc.parentArray` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parentArray). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). - - h3#stringmatch String match validator - :markdown - The String SchemaType [match](./api.html#schema_string_SchemaString-match) validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the [required](./api.html#schematype_SchemaType-required) validator as well. See issue [#934](https://github.com/LearnBoost/mongoose/issues/934) and pull request [#935](https://github.com/LearnBoost/mongoose/pull/935). - - h3#version Versioning - :markdown - Documents are now transparently versioned. Read the in depth details [here](http://aaronheckmann.posterous.com/tag/versioning). diff --git a/docs/3.0.x/docs/models.html b/docs/3.0.x/docs/models.html deleted file mode 100644 index c6314be54af..00000000000 --- a/docs/3.0.x/docs/models.html +++ /dev/null @@ -1,32 +0,0 @@ -Mongoose Models v3.0.3Fork me on GitHub

Models

Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

Compiling your first model

var schema = new Schema({ name: 'string', size: 'string' });
-var Tank = mongoose.model('Tank', schema);
-
-// or, if you are using separate connections
-var db = mongoose.createConnection(..);
-var Tank = db.model('Tank', schema);
-

Constructing documents

Documents are instances of our model. Creating them and saving to the database is easy:

var Tank = db.model('Tank', yourSchema);
-
-var small = new Tank({ size: 'small' });
-small.save(function (err) {
-  if (err) return handleError(err);
-  // saved!
-})
-
-// or
-
-Tank.create({ size: 'small' }, function (err) {
-  if (err) return handleError(err);
-  // saved!
-})
-

Querying

Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

See the chapter on querying for more details on how to use the Query api.

Removing

Models have a static remove method available for removing all documents matching conditions.

Tank.remove({ size: 'large' }, function (err) {
-  if (err) return handleError(err);
-  // removed!
-});

Updating

Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

Yet more

The API docs cover many additional methods available like count, mapReduce, and more.

diff --git a/docs/3.0.x/docs/models.jade b/docs/3.0.x/docs/models.jade deleted file mode 100644 index ace22950e08..00000000000 --- a/docs/3.0.x/docs/models.jade +++ /dev/null @@ -1,57 +0,0 @@ -extends layout - -block content - h2 Models - :markdown - [Models](./api.html#model-js) are fancy constructors compiled from our `Schema` definitions. Instances of these models represent [documents](./documents.html) which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models. - - h3 Compiling your first model - :js - var schema = new Schema({ name: 'string', size: 'string' }); - var Tank = mongoose.model('Tank', schema); - - // or, if you are using separate connections - var db = mongoose.createConnection(..); - var Tank = db.model('Tank', schema); - - h3 Constructing documents - :markdown - [Documents](./documents.html) are instances of our model. Creating them and saving to the database is easy: - :js - var Tank = db.model('Tank', yourSchema); - - var small = new Tank({ size: 'small' }); - small.save(function (err) { - if (err) return handleError(err); - // saved! - }) - - // or - - Tank.create({ size: 'small' }, function (err) { - if (err) return handleError(err); - // saved! - }) - - h3 Querying - :markdown - Finding documents is easy with Mongoose, which supports the [rich](http://www.mongodb.org/display/DOCS/Advanced+Queries) query syntax of MongoDB. Documents can be retreived using each `models` [find](./api.html#model_Model-find), [findById](./api.html#model_Model-findById), [findOne](./api.html#model_Model-findOne), or [where](./api.html#model_Model-where) static methods. - - :js - Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback); - :markdown - See the chapter on [querying](./queries.html) for more details on how to use the [Query](./api.html#query-js) api. - h3 Removing - :markdown - Models have a static `remove` method available for removing all documents matching `conditions`. - :js - Tank.remove({ size: 'large' }, function (err) { - if (err) return handleError(err); - // removed! - }); - h3 Updating - :markdown - Each `model` has its own `update` method for modifying documents in the database without returning them to your application. See the [API](./api.html#model_Model-update) docs for more detail. - h3 Yet more - :markdown - The [API docs](./api.html#model_Model) cover many additional methods available like [count](./api.html#model_Model-count), [mapReduce](./api.html#model_Model-mapReduce), and more. diff --git a/docs/3.0.x/docs/plugins.html b/docs/3.0.x/docs/plugins.html deleted file mode 100644 index 4f13420e6d3..00000000000 --- a/docs/3.0.x/docs/plugins.html +++ /dev/null @@ -1,33 +0,0 @@ -Mongoose Plugins v3.0.3Fork me on GitHub

Plugins

Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

- -

Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

// lastMod.js
-module.exports = exports = function lastModifiedPlugin (schema, options) {
-  schema.add({ lastMod: Date })
-  
-  schema.pre('save', function (next) {
-    this.lastMod = new Date
-    next()
-  })
-  
-  if (options && options.index) {
-    schema.path('lastMod').index(options.index)
-  }
-}
-
-// game-schema.js
-var lastMod = require('./lastMod');
-var Game = new Schema({ ... });
-Game.plugin(lastMod, { index: true });
-
-// player-schema.js
-var lastMod = require('./lastMod');
-var Player = new Schema({ ... });
-Player.plugin(lastMod);

We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

Community!

Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

diff --git a/docs/3.0.x/docs/plugins.jade b/docs/3.0.x/docs/plugins.jade deleted file mode 100644 index ab2ab5359a9..00000000000 --- a/docs/3.0.x/docs/plugins.jade +++ /dev/null @@ -1,38 +0,0 @@ -extends layout - -block content - h2 Plugins - :markdown - Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature. - - Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each `Schema`: - - :js - // lastMod.js - module.exports = exports = function lastModifiedPlugin (schema, options) { - schema.add({ lastMod: Date }) - - schema.pre('save', function (next) { - this.lastMod = new Date - next() - }) - - if (options && options.index) { - schema.path('lastMod').index(options.index) - } - } - - // game-schema.js - var lastMod = require('./lastMod'); - var Game = new Schema({ ... }); - Game.plugin(lastMod, { index: true }); - - // player-schema.js - var lastMod = require('./lastMod'); - var Player = new Schema({ ... }); - Player.plugin(lastMod); - :markdown - We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code. - h3 Community! - :markdown - Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. diff --git a/docs/3.0.x/docs/populate.html b/docs/3.0.x/docs/populate.html deleted file mode 100644 index 35a3a8807e5..00000000000 --- a/docs/3.0.x/docs/populate.html +++ /dev/null @@ -1,98 +0,0 @@ -Mongoose Query Population v3.0.3Fork me on GitHub

Query Population

There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

- -

ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

var mongoose = require('mongoose')
-  , Schema = mongoose.Schema
-  
-var PersonSchema = new Schema({
-  name    : String,
-  age     : Number,
-  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
-});
-
-var StorySchema = new Schema({
-  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
-  title    : String,
-  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
-});
-
-var Story  = mongoose.model('Story', StorySchema);
-var Person = mongoose.model('Person', PersonSchema);

So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

Saving refs

Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

var aaron = new Person({ name: 'Aaron', age: 100 });
-
-aaron.save(function (err) {
-  if (err) return handleError(err);
-  
-  var story1 = new Story({
-    title: "Once upon a timex.",
-    _creator: aaron._id    // assign an ObjectId
-  });
-  
-  story1.save(function (err) {
-    if (err) return handleError(err);
-    // thats it!
-  });
-})

Population

So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

Story
-.findOne({ title: /timex/ })
-.populate('_creator')
-.exec(function (err, story) {
-  if (err) return handleError(err);
-  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
-})
-

Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

- -

Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

Field selection

What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

Story
-.findOne({ title: /timex/i })
-.populate('_creator', 'name') // only return the Persons name
-.exec(function (err, story) {
-  if (err) return handleError(err);
-  
-  console.log('The creator is %s', story._creator.name);
-  // prints "The creator is Aaron"
-  
-  console.log('The creators age is %s', story._creator.age);
-  // prints "The creators age is null'
-})

Query conditions for populate

What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

Story
-.find(...)
-.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

Refs to children

We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

- -

There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

aaron.stories.push(story1);
-aaron.save();

This allows us to perform a find and populate combo:

Person
-.findOne({ name: 'Aaron' })
-.populate('stories') // only works if we pushed refs to children
-.exec(function (err, person) {
-  if (err) return handleError(err);
-  console.log(person);
-})

However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

Story
-.find({ _creator: aaron._id })
-.populate('_creator') // not really necessary
-.exec(function (err, stories) {
-  if (err) return handleError(err);
-  console.log('The stories are an array: ', stories);
-})
-

Updating refs

Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

var guille = new Person({ name: 'Guillermo' });
-guille.save(function (err) {
-  if (err) return handleError(err);
-  
-  story._creator = guille; // or guille._id
-  
-  story.save(function (err) {
-    if (err) return handleError(err);
-    
-    Story
-    .findOne({ title: /timex/i })
-    .populate('_creator', ['name'])
-    .exec(function (err, story) {
-      if (err) return handleError(err);
-      
-      console.log('The creator is %s', story._creator.name)
-      // prints "The creator is Guillermo"
-    })
-  })
-})

NOTE:

The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

diff --git a/docs/3.0.x/docs/populate.jade b/docs/3.0.x/docs/populate.jade deleted file mode 100644 index 593fb4cdce4..00000000000 --- a/docs/3.0.x/docs/populate.jade +++ /dev/null @@ -1,145 +0,0 @@ -extends layout - -block content - h2 Query Population - :markdown - There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. - - `ObjectIds` can refer to another document in a collection within our database and be `populate()`d when querying: - :js - var mongoose = require('mongoose') - , Schema = mongoose.Schema - - var PersonSchema = new Schema({ - name : String, - age : Number, - stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] - }); - - var StorySchema = new Schema({ - _creator : { type: Schema.Types.ObjectId, ref: 'Person' }, - title : String, - fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }] - }); - - var Story = mongoose.model('Story', StorySchema); - var Person = mongoose.model('Person', PersonSchema); - :markdown - So far we've created two `models`. Our `Person` model has it's `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose in which model to look, in our case the `Story` model. All `_id`s we store here must be document _ids from the `Story` model. We also added a `_creator` `ObjectId` to our `Story` schema which refers to a single `Person`. - h3 Saving refs - :markdown - Saving refs to other documents works the same way you normally save objectids, just assign an `ObjectId`: - :js - var aaron = new Person({ name: 'Aaron', age: 100 }); - - aaron.save(function (err) { - if (err) return handleError(err); - - var story1 = new Story({ - title: "Once upon a timex.", - _creator: aaron._id // assign an ObjectId - }); - - story1.save(function (err) { - if (err) return handleError(err); - // thats it! - }); - }) - h3 Population - :markdown - So far we haven't done anything special. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator`: - :js - Story - .findOne({ title: /timex/ }) - .populate('_creator') - .exec(function (err, story) { - if (err) return handleError(err); - console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron" - }) - - :markdown - Populated paths are no longer set to their original `ObjectId`s, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. - - Arrays of `ObjectId` refs work the same way. Just call the [populate](./api.html#query_Query-populate) method on the query and an array of documents will be returned _in place_ of the `ObjectIds`. - - h3 Field selection - :markdown - What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: - :js - Story - .findOne({ title: /timex/i }) - .populate('_creator', 'name') // only return the Persons name - .exec(function (err, story) { - if (err) return handleError(err); - - console.log('The creator is %s', story._creator.name); - // prints "The creator is Aaron" - - console.log('The creators age is %s', story._creator.age); - // prints "The creators age is null' - }) - h3 Query conditions for populate - :markdown - What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them? - :js - Story - .find(...) - .populate('fans', null, { age: { $gte: 21 }}, { limit: 5 }) - :markdown - Done. `Conditions` and `options` for populate queries are passed as the third and fourth arguments respectively. - h3 Refs to children - :markdown - We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' on to `aaron.stories`. - - There are two perspectives to this story. First, it's nice to have `aaron` know which are his stories. - :js - aaron.stories.push(story1); - aaron.save(); - :markdown - This allows us to perform a `find` and `populate` combo: - :js - Person - .findOne({ name: 'Aaron' }) - .populate('stories') // only works if we pushed refs to children - .exec(function (err, person) { - if (err) return handleError(err); - console.log(person); - }) - :markdown - However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely `find()` the documents we are interested in. - :js - Story - .find({ _creator: aaron._id }) - .populate('_creator') // not really necessary - .exec(function (err, stories) { - if (err) return handleError(err); - console.log('The stories are an array: ', stories); - }) - - h3 Updating refs - :markdown - Now that we have a `story` we realized that the `_creator` was incorrect. We can update `ObjectId` refs the same as any other property through the magic of Mongoose's internal casting: - :js - var guille = new Person({ name: 'Guillermo' }); - guille.save(function (err) { - if (err) return handleError(err); - - story._creator = guille; // or guille._id - - story.save(function (err) { - if (err) return handleError(err); - - Story - .findOne({ title: /timex/i }) - .populate('_creator', ['name']) - .exec(function (err, story) { - if (err) return handleError(err); - - console.log('The creator is %s', story._creator.name) - // prints "The creator is Guillermo" - }) - }) - }) - h4 NOTE: - :markdown - The documents returned from calling [populate](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. diff --git a/docs/3.0.x/docs/prior.html b/docs/3.0.x/docs/prior.html deleted file mode 100644 index 919a0008e27..00000000000 --- a/docs/3.0.x/docs/prior.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose v3.0.3Fork me on GitHub

Prior Release Documentation

diff --git a/docs/3.0.x/docs/prior.jade b/docs/3.0.x/docs/prior.jade deleted file mode 100644 index 1ef7d088a72..00000000000 --- a/docs/3.0.x/docs/prior.jade +++ /dev/null @@ -1,8 +0,0 @@ -extends layout - -block content - h2 Prior Release Documentation - ul - each release in releases - li - a(href=release.url)= release.version diff --git a/docs/3.0.x/docs/queries.html b/docs/3.0.x/docs/queries.html deleted file mode 100644 index b2efeab7ac4..00000000000 --- a/docs/3.0.x/docs/queries.html +++ /dev/null @@ -1,41 +0,0 @@ -Mongoose Queries v3.0.3Fork me on GitHub

Queries

Documents can be retrieved through several static helper methods of models.

Any model method which involves specifying query conditions can be executed two ways:

- -

When a callback function:

- -
  • is passed, the operation will be executed immediately with the results passed to the callback.
  • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
- -

Let's take a look at what happens when passing a callback:

var Person = db.model('Person', yourSchema);
-
-// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
-Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
-  if (err) return handleError(err);
-  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
-})

Here we see that the query was executed immediately and the results passed to our callback. -Now let's look at what happens when no callback is passed:

// find each person with a last name matching 'Ghost'
-var query = Person.findOne({ 'name.last': 'Ghost' });
-
-// selecting the `name` and `occupation` fields
-query.select('name occupation');
-
-// execute the query at a later time
-query.exec(function (err, person) {
-  if (err) return handleError(err);
-  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
-})

An instance of Query was returned which allows us to build up our query. Taking this example further:

Person
-.find({ occupation: /host/ })
-.where('name.last').equals('Ghost')
-.where('age').gt(17).lt(66)
-.where('likes').in(['vaporizing', 'talking'])
-.limit(10)
-.sort('-occupation')
-.select('name occupation')
-.exec(callback);
-

References to other documents

There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

Streaming

Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

diff --git a/docs/3.0.x/docs/queries.jade b/docs/3.0.x/docs/queries.jade deleted file mode 100644 index 488452d2cf5..00000000000 --- a/docs/3.0.x/docs/queries.jade +++ /dev/null @@ -1,59 +0,0 @@ -extends layout - -block content - h2 Queries - :markdown - Documents can be retrieved through several static helper methods of [models](./models.html). - :markdown - Any [model](./api.html#model_Model) method which [involves](./api.html#model_Model-find) [specifying](./api.html#model_Model-findById) [query](./api.html#model_Model-count) [conditions](./api.html#model_Model-update) can be executed two ways: - - When a `callback` function: - - - is passed, the operation will be executed immediately with the results passed to the callback. - - is not passed, an instance of [Query](./api.html#query-js) is returned, which provides a special `QueryBuilder` interface for you. - - Let's take a look at what happens when passing a `callback`: - :js - var Person = db.model('Person', yourSchema); - - // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields - Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { - if (err) return handleError(err); - console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. - }) - :markdown - Here we see that the query was executed immediately and the results passed to our callback. - Now let's look at what happens when no `callback` is passed: - :js - // find each person with a last name matching 'Ghost' - var query = Person.findOne({ 'name.last': 'Ghost' }); - - // selecting the `name` and `occupation` fields - query.select('name occupation'); - - // execute the query at a later time - query.exec(function (err, person) { - if (err) return handleError(err); - console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. - }) - :markdown - An instance of [Query](./api.html#query-js) was returned which allows us to build up our query. Taking this example further: - :js - Person - .find({ occupation: /host/ }) - .where('name.last').equals('Ghost') - .where('age').gt(17).lt(66) - .where('likes').in(['vaporizing', 'talking']) - .limit(10) - .sort('-occupation') - .select('name occupation') - .exec(callback); - - h3#refs References to other documents - :markdown - There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. Read more [here](./populate.html). - - h3 Streaming - :markdown - Queries can be [streamed](http://nodejs.org/api/stream.html) from MongoDB to your application as well. Simply call the query's [stream](./api.html#query_Query-stream) method instead of [exec](./api.html#query_Query-exec) to return an instance of [QueryStream](./api.html#query_Query-stream). - diff --git a/docs/3.0.x/docs/releases b/docs/3.0.x/docs/releases deleted file mode 100644 index e17ae757977..00000000000 --- a/docs/3.0.x/docs/releases +++ /dev/null @@ -1 +0,0 @@ -2.7.x diff --git a/docs/3.0.x/docs/schematypes.html b/docs/3.0.x/docs/schematypes.html deleted file mode 100644 index 6e57f877b45..00000000000 --- a/docs/3.0.x/docs/schematypes.html +++ /dev/null @@ -1,67 +0,0 @@ -Mongoose SchemaTypes v3.0.3Fork me on GitHub

SchemaTypes

SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

Following are all valid Schema Types.

  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • ObjectId
  • Array

Example

var schema = new Schema({
-  name:    String,
-  binary:  Buffer,
-  living:  Boolean,
-  updated: { type: Date, default: Date.now },
-  age:     { type: Number, min: 18, max: 65 },
-  mixed:   Schema.Types.Mixed,
-  _someId: Schema.Types.ObjectId,
-  array:      [],
-  ofString:   [String],
-  ofNumber:   [Number],
-  ofDates:    [Date],
-  ofBuffer:   [Buffer],
-  ofBoolean:  [Boolean],
-  ofMixed:    [Schema.Types.Mixed],
-  ofObjectId: [Schema.Types.ObjectId],
-  nested: {
-    stuff: { type: String, lowercase: true, trim: true }
-  }
-})
-
-// example use
-
-var Thing = mongoose.model('Thing', schema);
-
-var m = new Thing;
-m.name = 'Statue of Liberty';
-m.age = 125;
-m.updated = new Date;
-m.binary = new Buffer(0);
-m.living = false;
-m.mixed = {[ any: { thing: 'i want' } ]};
-m.markModified('mixed');
-m._someId = new mongoose.Types.ObjectId;
-m.array.push(1);
-m.ofString.push("strings!");
-m.ofNumber.unshift(1,2,3,4);
-m.ofDates.addToSet(new Date);
-m.ofBuffer.pop();
-m.ofMixed = [1, [], 'three', { four: 5 }];
-m.nested.stuff = 'good';
-m.save(callback);
-

Usage notes:

Mixed

An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

var Any = new Schema({ any: {} });
-var Any = new Schema({ any: Schema.Types.Mixed });

Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

person.anything = { x: [3, 4, { y: "changed" }] };
-person.markModified('anything');
-person.save(); // anything will now get saved

ObjectIds

To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

var mongoose = require('mongoose');
-var ObjectId = mongoose.Schema.Types.ObjectId;
-var Car = new Schema({ driver: ObjectId });
-// or just Schema.ObjectId for backwards compatibility with v2

Arrays

Provide creation of arrays of SchemaTypes or Sub-Documents.

var ToySchema = new Schema({ name: String });
-var ToyBox = new Schema({
-  toys: [ToySchema],
-  buffers: [Buffer],
-  string:  [String],
-  numbers: [Number]
-  // ... etc
-});

Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

var Empty1 = new Schema({ any: [] });
-var Empty2 = new Schema({ any: Array });
-var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
-var Empty4 = new Schema({ any: [{}] });

Creating Custom Types

Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

diff --git a/docs/3.0.x/docs/schematypes.jade b/docs/3.0.x/docs/schematypes.jade deleted file mode 100644 index c787a25fdc9..00000000000 --- a/docs/3.0.x/docs/schematypes.jade +++ /dev/null @@ -1,142 +0,0 @@ -extends layout - -block content - h2 SchemaTypes - p - | SchemaTypes handle definition of path - a(href="./api.html#schematype_SchemaType-default") defaults - |, - a(href="./api.html#schematype_SchemaType-validate") validation - |, - a(href="./api.html#schematype_SchemaType-get") getters - |, - a(href="./api.html#schematype_SchemaType-set") setters - |, - a(href="./api.html#schematype_SchemaType-select") field selection defaults - | for - a(href="./api.html#query-js") queries - | and other general characteristics for - a(href="./api.html#schema-string-js") Strings - | and - a(href="./api.html#schema-number-js") Numbers - |. Check out their respective API documentation for more detail. - p - | Following are all valid - a(href="./api.html#schema_Schema-Types") Schema Types - |. - ul - li String - li Number - li Date - li Buffer - li Boolean - li Mixed - li ObjectId - li Array - h4 Example - :js - var schema = new Schema({ - name: String, - binary: Buffer, - living: Boolean, - updated: { type: Date, default: Date.now }, - age: { type: Number, min: 18, max: 65 }, - mixed: Schema.Types.Mixed, - _someId: Schema.Types.ObjectId, - array: [], - ofString: [String], - ofNumber: [Number], - ofDates: [Date], - ofBuffer: [Buffer], - ofBoolean: [Boolean], - ofMixed: [Schema.Types.Mixed], - ofObjectId: [Schema.Types.ObjectId], - nested: { - stuff: { type: String, lowercase: true, trim: true } - } - }) - - // example use - - var Thing = mongoose.model('Thing', schema); - - var m = new Thing; - m.name = 'Statue of Liberty'; - m.age = 125; - m.updated = new Date; - m.binary = new Buffer(0); - m.living = false; - m.mixed = {[ any: { thing: 'i want' } ]}; - m.markModified('mixed'); - m._someId = new mongoose.Types.ObjectId; - m.array.push(1); - m.ofString.push("strings!"); - m.ofNumber.unshift(1,2,3,4); - m.ofDates.addToSet(new Date); - m.ofBuffer.pop(); - m.ofMixed = [1, [], 'three', { four: 5 }]; - m.nested.stuff = 'good'; - m.save(callback); - - h3 Usage notes: - h4#mixed Mixed - p An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent: - :js - var Any = new Schema({ any: {} }); - var Any = new Schema({ any: Schema.Types.Mixed }); - p - | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the - code .markModified(path) - | method of the document passing the path to the Mixed type you just changed. - :js - person.anything = { x: [3, 4, { y: "changed" }] }; - person.markModified('anything'); - person.save(); // anything will now get saved - h4#objectids ObjectIds - p - | To specify a type of ObjectId, use - code Schema.Types.ObjectId - | in your declaration. - :js - var mongoose = require('mongoose'); - var ObjectId = mongoose.Schema.Types.ObjectId; - var Car = new Schema({ driver: ObjectId }); - // or just Schema.ObjectId for backwards compatibility with v2 - h4#arrays Arrays - p - | Provide creation of arrays of - a(href="./api.html#schema_Schema-Types") SchemaTypes - | or - a(href="./subdocs.html") Sub-Documents - |. - :js - var ToySchema = new Schema({ name: String }); - var ToyBox = new Schema({ - toys: [ToySchema], - buffers: [Buffer], - string: [String], - numbers: [Number] - // ... etc - }); - p - | Note: specifying an empty array is equivalent to - code Mixed - |. The following all create arrays of - code Mixed - |: - :js - var Empty1 = new Schema({ any: [] }); - var Empty2 = new Schema({ any: Array }); - var Empty3 = new Schema({ any: [Schema.Types.Mixed] }); - var Empty4 = new Schema({ any: [{}] }); - h3#customtypes Creating Custom Types - p - | Mongoose can also be extended with custom SchemaTypes. Search the - a(href="http://plugins.mongoosejs.com") plugins - | site for compatible types like - a(href="https://github.com/aheckmann/mongoose-long") mongoose-long - | and - a(href="https://github.com/aheckmann/mongoose-number") other - | - a(href="https://github.com/bnoguchi/mongoose-types") types - |. diff --git a/docs/3.0.x/docs/source/_docs b/docs/3.0.x/docs/source/_docs deleted file mode 100644 index 483b17b58c8..00000000000 --- a/docs/3.0.x/docs/source/_docs +++ /dev/null @@ -1,15928 +0,0 @@ - -### lib/collection.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var STATES = require('./connectionstate')", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "require('./connectionstate')", - "string": "STATES" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the collection" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "conn", - "description": "A MongooseConnection instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "optional collection options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Abstract Collection constructor

\n\n

This is the base class that drivers inherit from and implement.

", - "summary": "

Abstract Collection constructor

", - "body": "

This is the base class that drivers inherit from and implement.

" - }, - "isPrivate": false, - "ignore": false, - "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", - "ctx": { - "type": "function", - "name": "Collection", - "string": "Collection()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "name" - } - ], - "description": { - "full": "

The collection name

", - "summary": "

The collection name

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.name;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "conn" - } - ], - "description": { - "full": "

The Connection instance

", - "summary": "

The Connection instance

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.conn;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the database connects

", - "summary": "

Called when the database connects

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onOpen", - "string": "Collection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the database disconnects

", - "summary": "

Called when the database disconnects

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onClose", - "string": "Collection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the method to queue" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method when executed" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Queues a method for later execution when its
database connection opens.

", - "summary": "

Queues a method for later execution when its
database connection opens.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "addQueue", - "string": "Collection.prototype.addQueue()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Executes all queued methods and clears the queue.

", - "summary": "

Executes all queued methods and clears the queue.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "doQueue", - "string": "Collection.prototype.doQueue()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "ensureIndex", - "string": "Collection.prototype.ensureIndex()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findAndModify", - "string": "Collection.prototype.findAndModify()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findOne", - "string": "Collection.prototype.findOne()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "find", - "string": "Collection.prototype.find()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "insert", - "string": "Collection.prototype.insert()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "save", - "string": "Collection.prototype.save()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "update", - "string": "Collection.prototype.update()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "getIndexes", - "string": "Collection.prototype.getIndexes()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "mapReduce", - "string": "Collection.prototype.mapReduce()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = Collection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Collection", - "string": "module.exports" - } - } -] -### lib/connection.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , assert =require('assert')", - "ctx": { - "type": "declaration", - "name": "url", - "value": "require('url')", - "string": "url" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Protocol prefix regexp.

", - "summary": "

Protocol prefix regexp.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", - "ctx": { - "type": "declaration", - "name": "rgxProtocol", - "value": "/^(?:.)+:\\/\\//", - "string": "rgxProtocol" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "a mongoose instance" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." - }, - { - "type": "event", - "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." - }, - { - "type": "event", - "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." - }, - { - "type": "event", - "string": "`disconnecting`: Emitted when `connection.close()` was executed." - }, - { - "type": "event", - "string": "`disconnected`: Emitted after getting disconnected from the db." - }, - { - "type": "event", - "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." - }, - { - "type": "event", - "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." - }, - { - "type": "event", - "string": "`error`: Emitted when an error occurs on this connection." - }, - { - "type": "event", - "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Connection constructor

\n\n

For practical reasons, a Connection equals a Db.

", - "summary": "

Connection constructor

", - "body": "

For practical reasons, a Connection equals a Db.

" - }, - "isPrivate": false, - "ignore": false, - "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", - "ctx": { - "type": "function", - "name": "Connection", - "string": "Connection()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from EventEmitter

", - "summary": "

Inherit from EventEmitter

", - "body": "" - }, - "ignore": true, - "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Connection", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Connection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readyState" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Connection ready state

\n\n
    \n
  • 0 = disconnected
  • \n
  • 1 = connected
  • \n
  • 2 = connecting
  • \n
  • 3 = disconnecting
  • \n
\n\n

Each state change emits its associated event name.

\n\n

Example

\n\n
conn.on('connected', callback);\nconn.on('disconnected', callback);\n
", - "summary": "

Connection ready state

", - "body": "
    \n
  • 0 = disconnected
  • \n
  • 1 = connected
  • \n
  • 2 = connecting
  • \n
  • 3 = disconnecting
  • \n
\n\n

Each state change emits its associated event name.

\n\n

Example

\n\n
conn.on('connected', callback);\nconn.on('disconnected', callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" - }, - { - "tags": [ - { - "type": "property", - "string": "collections" - } - ], - "description": { - "full": "

A hash of the collections associated with this connection

", - "summary": "

A hash of the collections associated with this connection

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collections;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

The mongodb.Db instance, set when the connection is opened

", - "summary": "

The mongodb.Db instance, set when the connection is opened

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.db;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "connection_string", - "description": "mongodb://uri or the host to which you are connecting" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[port]", - "description": "database port" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Opens the connection to MongoDB.

\n\n

options is a hash with the following possible properties:

\n\n
db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
\n\n

Notes:

\n\n

Mongoose forces the db option forceServerObjectId false and cannot be overridden.
Mongoose defaults the server auto_reconnect options to true which can be overridden.
See the node-mongodb-native driver instance for options that it understands.

", - "summary": "

Opens the connection to MongoDB.

", - "body": "

options is a hash with the following possible properties:

\n\n
db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
\n\n

Notes:

\n\n

Mongoose forces the db option forceServerObjectId false and cannot be overridden.
Mongoose defaults the server auto_reconnect options to true which can be overridden.
See the node-mongodb-native driver instance for options that it understands.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n uri = url.parse(host);\n host = uri.hostname;\n port = uri.port || 27017;\n database = uri.pathname && uri.pathname.replace(/\\//g, '');\n }\n\n this.options = this.defaultOptions(options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing connection hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing connection database.'), callback);\n return this;\n }\n\n // handle authentication\n if (uri && uri.auth) {\n var auth = uri.auth.split(':');\n this.user = auth[0];\n this.pass = auth[1];\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n // user/pass options\n } else if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "open", - "string": "Connection.prototype.open()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "uris", - "description": "comma-separated mongodb:// `URI`s" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name if not included in `uris`" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "passed to the internal driver" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Connects to a replica set.

\n\n

Example:

\n\n
var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
\n\n

The database name and/or auth need only be included in one URI.
The options are passed to the internal driver connection object.

", - "summary": "

Connects to a replica set.

", - "body": "

Example:

\n\n
var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
\n\n

The database name and/or auth need only be included in one URI.
The options are passed to the internal driver connection object.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n var uris = uris.split(',')\n , self = this;\n\n switch (arguments.length) {\n case 3:\n this.name = database;\n if ('function' === typeof options) callback = options, options = {};\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n this.options = options = this.defaultOptions(options);\n\n if (uris.length < 2) {\n this.error(new Error('Please provide comma-separated URIs'), callback);\n return this;\n }\n\n this.replica = true;\n this.host = [];\n this.port = [];\n\n uris.forEach(function (uri) {\n // handle missing protocols\n if (!rgxProtocol.test(uri))\n uri = 'mongodb://' + uri;\n\n var uri = url.parse(uri);\n\n self.host.push(uri.hostname);\n self.port.push(uri.port || 27017);\n\n if (!self.name && uri.pathname && uri.pathname.replace(/\\//g, ''))\n self.name = uri.pathname.replace(/\\//g, '');\n\n if (!self.user && uri.auth) {\n var auth = uri.auth.split(':');\n self.user = auth[0];\n self.pass = auth[1];\n }\n });\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "openSet", - "string": "Connection.prototype.openSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "optional" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

error

\n\n

Graceful error handling, passes error to callback
if available, else emits error on the connection.

", - "summary": "

error

", - "body": "

Graceful error handling, passes error to callback
if available, else emits error on the connection.

" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "error", - "string": "Connection.prototype.error()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Handles opening the connection with the appropriate method based on connection type.

", - "summary": "

Handles opening the connection with the appropriate method based on connection type.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "_open", - "string": "Connection.prototype._open()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the connection is opened

", - "summary": "

Called when the connection is opened

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onOpen", - "string": "Connection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "self" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Closes the connection

", - "summary": "

Closes the connection

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "close", - "string": "Connection.prototype.close()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the connection closes

", - "summary": "

Called when the connection closes

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onClose", - "string": "Connection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "of the collection" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional collection options" - }, - { - "type": "return", - "types": [ - "Collection" - ], - "description": "collection instance" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Retrieves a collection, creating it if not cached.

", - "summary": "

Retrieves a collection, creating it if not cached.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "collection", - "string": "Connection.prototype.collection()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "the model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "a schema. necessary when defining a model" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name of mongodb collection (optional) if not given it will be induced from model name" - }, - { - "type": "see", - "local": "Mongoose#model #index_Mongoose-model", - "visibility": "Mongoose#model" - }, - { - "type": "return", - "types": [ - "Model" - ], - "description": "The compiled model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines or retrieves a model.

\n\n
var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
", - "summary": "

Defines or retrieves a model.

", - "body": "
var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.model = function (name, schema, collection) {\n if (!this.models[name]) {\n var model = this.base.model(name, schema, collection, true)\n , Model\n\n if (this != model.prototype.db) {\n // subclass model using this connection and collection name\n Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model))\n return new Model(doc, fields, skipId);\n model.call(this, doc, fields, skipId);\n };\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = this;\n\n // collection name discovery\n if ('string' === typeof schema) {\n collection = schema;\n }\n\n if (!collection) {\n collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);\n }\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n Model.prototype.collection = this.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n }\n\n this.models[name] = Model || model;\n }\n\n return this.models[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "model", - "string": "Connection.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "level", - "description": "either off (0), slow (1), or all (2)" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[ms]", - "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Set profiling level.

", - "summary": "

Set profiling level.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "setProfiling", - "string": "Connection.prototype.setProfiling()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Prepares default connection options.

", - "summary": "

Prepares default connection options.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.defaultOptions = function (options) {\n var o = options || {};\n\n o.server = o.server || {};\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n o.db = o.db || {};\n o.db.forceServerObjectId = false;\n\n return o;\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "defaultOptions", - "string": "Connection.prototype.defaultOptions()" - } - }, - { - "tags": [], - "description": { - "full": "

Noop.

", - "summary": "

Noop.

", - "body": "" - }, - "ignore": true, - "code": "function noop () {}", - "ctx": { - "type": "function", - "name": "noop", - "string": "noop()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", - "ctx": { - "type": "property", - "receiver": "Connection", - "name": "STATES", - "value": "STATES", - "string": "Connection.STATES" - } - } -] -### lib/connectionstate.js -[ - { - "tags": [], - "description": { - "full": "

Connection states

", - "summary": "

Connection states

", - "body": "" - }, - "ignore": true, - "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "module.exports = exports = Object.create(null)", - "string": "STATES" - } - } -] -### lib/document.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the values to set" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "the fields which were selected in the query returning this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "bool, should we auto create an ObjectId _id" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." - }, - { - "type": "event", - "string": "`save`: Emitted when the document is successfully saved" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Document constructor.

", - "summary": "

Document constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", - "ctx": { - "type": "function", - "name": "Document", - "string": "Document()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from EventEmitter.

", - "summary": "

Inherit from EventEmitter.

", - "body": "" - }, - "ignore": true, - "code": "Document.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Document.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "schema" - } - ], - "description": { - "full": "

The documents schema.

", - "summary": "

The documents schema.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.schema;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "isNew" - } - ], - "description": { - "full": "

Boolean flag specifying if the document is new.

", - "summary": "

Boolean flag specifying if the document is new.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isNew;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "local": "Schema options /docs/guide.html#options", - "visibility": "Schema" - }, - { - "type": "property", - "string": "id" - } - ], - "description": { - "full": "

The string version of this documents _id.

\n\n

Note:

\n\n

This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

\n\n
new Schema({ name: String }, { id: false });\n
", - "summary": "

The string version of this documents _id.

", - "body": "

Note:

\n\n

This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

\n\n
new Schema({ name: String }, { id: false });\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.id;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "errors" - } - ], - "description": { - "full": "

Hash containing current validation errors.

", - "summary": "

Hash containing current validation errors.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.errors;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Builds the default doc structure

", - "summary": "

Builds the default doc structure

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_buildDoc", - "string": "Document.prototype._buildDoc()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Initializes the document without setters or marking anything modified.

\n\n

Called internally after a document is returned from mongodb.

", - "summary": "

Initializes the document without setters or marking anything modified.

", - "body": "

Called internally after a document is returned from mongodb.

" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init');\n if (fn) fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "init", - "string": "Document.prototype.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "self", - "description": "document instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "raw mongodb doc" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "object we are initializing" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Init helper.

", - "summary": "

Init helper.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", - "ctx": { - "type": "function", - "name": "init", - "string": "init()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Stores the current values of the shard keys.

\n\n

Note:

\n\n

Shard key values do not / are not allowed to change.

", - "summary": "

Stores the current values of the shard keys.

", - "body": "

Note:

\n\n

Shard key values do not / are not allowed to change.

" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_storeShard", - "string": "Document.prototype._storeShard()" - } - }, - { - "tags": [], - "description": { - "full": "

Set up middleware support

", - "summary": "

Set up middleware support

", - "body": "" - }, - "ignore": true, - "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sends an update command with this document _id as the query selector.

\n\n

Example:

\n\n
weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
\n\n

Valid options:

\n\n
    \n
  • safe safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
", - "summary": "

Sends an update command with this document _id as the query selector.

", - "body": "

Example:

\n\n
weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
\n\n

Valid options:

\n\n
    \n
  • safe safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "update", - "string": "Document.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "path", - "description": "path or object of key/vals to set" - }, - { - "type": "param", - "types": [ - "Any" - ], - "name": "val", - "description": "the value to set" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for \"on-the-fly\" attributes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets the value of a path, or many paths.

\n\n

Example:

\n\n
// path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
", - "summary": "

Sets the value of a path, or many paths.

", - "body": "

Example:

\n\n
// path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.set = function (path, val, type) {\n var constructing = true === type\n , adhoc = type && true !== type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n if (null != path[key] && 'Object' === path[key].constructor.name\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n pathtype = this.schema.pathType(prefix + key);\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "set", - "string": "Document.prototype.set()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Handles the actual setting of the value and marking the path modified if appropriate.

", - "summary": "

Handles the actual setting of the value and marking the path modified if appropriate.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {\n if (this.isNew) {\n this.markModified(pathToMark);\n } else {\n\n priorVal || (priorVal = this.get(path));\n\n if (!this.isDirectModified(pathToMark)) {\n if (undefined === val && !this.isSelected(path)) {\n // special case:\n // when a path is not selected in a query its initial\n // value will be undefined.\n this.markModified(pathToMark, priorVal);\n } else if (undefined === val && path in this._activePaths.states.default) {\n // do nothing\n // unsetting the default value which was never saved\n } else if (!deepEqual(val, priorVal)) {\n this.markModified(pathToMark, priorVal);\n } else if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // special case:\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n this.markModified(pathToMark, priorVal);\n }\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_set", - "string": "Document.prototype._set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Gets a raw value from a path (no getters)

", - "summary": "

Gets a raw value from a path (no getters)

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "getValue", - "string": "Document.prototype.getValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Sets a raw value for a path (no casting, setters, transformations)

", - "summary": "

Sets a raw value for a path (no casting, setters, transformations)

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "setValue", - "string": "Document.prototype.setValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for on-the-fly attributes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns the value of a path.

\n\n

Example

\n\n
// path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
", - "summary": "

Returns the value of a path.

", - "body": "

Example

\n\n
// path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "get", - "string": "Document.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns the schematype for the given path.

", - "summary": "

Returns the schematype for the given path.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_path", - "string": "Document.prototype._path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to mark modified" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Marks the path as having pending changes to write to the db.

\n\n

Very helpful when using Mixed types.

\n\n

Example:

\n\n
doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
", - "summary": "

Marks the path as having pending changes to write to the db.

", - "body": "

Very helpful when using Mixed types.

\n\n

Example:

\n\n
doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "markModified", - "string": "Document.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "function to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope with which to call fn" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

", - "summary": "

Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "try", - "string": "Document.prototype.try()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns the list of paths that have been modified.

", - "summary": "

Returns the list of paths that have been modified.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "modifiedPaths", - "string": "Document.prototype.modifiedPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns true if this document was modified, else false.

\n\n

If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

\n\n

Example

\n\n
doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
", - "summary": "

Returns true if this document was modified, else false.

", - "body": "

If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

\n\n

Example

\n\n
doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isModified", - "string": "Document.prototype.isModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns true if path was directly set and modified, else false.

\n\n

Example

\n\n
doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
", - "summary": "

Returns true if path was directly set and modified, else false.

", - "body": "

Example

\n\n
doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isDirectModified", - "string": "Document.prototype.isDirectModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Checks if path was initialized.

", - "summary": "

Checks if path was initialized.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isInit", - "string": "Document.prototype.isInit()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Checks if path was selected in the source query which initialized this document.

\n\n

Example

\n\n
Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
", - "summary": "

Checks if path was selected in the source query which initialized this document.

", - "body": "

Example

\n\n
Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isSelected", - "string": "Document.prototype.isSelected()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "cb", - "description": "called after validation completes, passing an error if one occurred" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes registered validation rules for this document.

\n\n

Note:

\n\n

This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

\n\n

Example:

\n\n
doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
", - "summary": "

Executes registered validation rules for this document.

", - "body": "

Note:

\n\n

This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

\n\n

Example:

\n\n
doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n cb(err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "validate", - "string": "Document.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "the error which states the reason `path` was invalid" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Marks a path as invalid, causing validation to fail.

", - "summary": "

Marks a path as invalid, causing validation to fail.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "invalidate", - "string": "Document.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

Resets the internal modified state of this document.

", - "summary": "

Resets the internal modified state of this document.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return (val && val instanceof DocumentArray && val.length);\n })\n .forEach(function (array) {\n array.forEach(function (doc) {\n doc._reset();\n });\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_reset", - "string": "Document.prototype._reset()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns this documents dirty paths / vals.

", - "summary": "

Returns this documents dirty paths / vals.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_dirty", - "string": "Document.prototype._dirty()" - } - }, - { - "tags": [], - "description": { - "full": "

Compiles schemas.

", - "summary": "

Compiles schemas.

", - "body": "" - }, - "ignore": true, - "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", - "ctx": { - "type": "function", - "name": "compile", - "string": "compile()" - } - }, - { - "tags": [], - "description": { - "full": "

Defines the accessor named prop on the incoming prototype.

", - "summary": "

Defines the accessor named prop on the incoming prototype.

", - "body": "" - }, - "ignore": true, - "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(v, path);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", - "ctx": { - "type": "function", - "name": "define", - "string": "define()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Assigns/compiles schema into this documents prototype.

", - "summary": "

Assigns/compiles schema into this documents prototype.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_setSchema", - "string": "Document.prototype._setSchema()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Register default hooks

", - "summary": "

Register default hooks

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return (val && val instanceof DocumentArray && val.length);\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n subdocs += array.length;\n array.forEach(function (value) {\n if (error) return;\n\n value.save(function (err) {\n if (error) return;\n\n if (err) {\n error = true;\n self._validationError = undefined;\n return next(err);\n }\n\n --subdocs || next();\n });\n });\n });\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_registerHooks", - "string": "Document.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Registers an error

", - "summary": "

Registers an error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_error", - "string": "Document.prototype._error()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Executes methods queued from the Schema definition

", - "summary": "

Executes methods queued from the Schema definition

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_doQueue", - "string": "Document.prototype._doQueue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "js object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Converts this document into a plain javascript object

\n\n

Options:

\n\n
    \n
  • getters apply all getters (path and virtual getters)
  • \n
  • virtuals apply virtual getters (can override getters option)
  • \n
  • minimize remove empty objects (defaults to true)
  • \n
\n\n

Example of only applying path getters

\n\n
doc.toObject({ getters: true, virtuals: false })\n
\n\n

Example of only applying virtual getters

\n\n
doc.toObject({ virtuals: true })\n
\n\n

Example of applying both path and virtual getters

\n\n
doc.toObject({ getters: true })\n
", - "summary": "

Converts this document into a plain javascript object

", - "body": "

Options:

\n\n
    \n
  • getters apply all getters (path and virtual getters)
  • \n
  • virtuals apply virtual getters (can override getters option)
  • \n
  • minimize remove empty objects (defaults to true)
  • \n
\n\n

Example of only applying path getters

\n\n
doc.toObject({ getters: true, virtuals: false })\n
\n\n

Example of only applying virtual getters

\n\n
doc.toObject({ virtuals: true })\n
\n\n

Example of applying both path and virtual getters

\n\n
doc.toObject({ getters: true })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toObject", - "string": "Document.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "json", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "either `virtuals` or `paths`" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "`json`" - } - ], - "description": { - "full": "

Applies virtuals properties to json.

", - "summary": "

Applies virtuals properties to json.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", - "ctx": { - "type": "function", - "name": "applyGetters", - "string": "applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "same options as Document#toObject" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "see", - "local": "Document#toObject", - "visibility": "Document#toObject" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The return value of this method is used in calls to JSON.stringify(doc).

", - "summary": "

The return value of this method is used in calls to JSON.stringify(doc).

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toJSON", - "string": "Document.prototype.toJSON()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "inspect", - "string": "Document.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "toString" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toString = Document.prototype.inspect;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "toString", - "value": "Document.prototype.inspect", - "string": "Document.prototypetoString" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "a document to compare" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns true if the Document stores the same data as doc.

\n\n

Documents are considered equal when they have matching _ids.

", - "summary": "

Returns true if the Document stores the same data as doc.

", - "body": "

Documents are considered equal when they have matching _ids.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "equals", - "string": "Document.prototype.equals()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", - "ctx": { - "type": "property", - "receiver": "Document", - "name": "ValidationError", - "value": "ValidationError", - "string": "Document.ValidationError" - } - } -] -### lib/drivers/node-mongodb-native/binary.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require('mongodb').BSONPure.Binary", - "string": "Binary" - } - } -] -### lib/drivers/node-mongodb-native/collection.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", - "ctx": { - "type": "declaration", - "name": "MongooseCollection", - "value": "require('../../collection')", - "string": "MongooseCollection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Collection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

A node-mongodb-native collection implementation.

\n\n

All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

", - "summary": "

A node-mongodb-native collection implementation.

", - "body": "

All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

" - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", - "ctx": { - "type": "function", - "name": "NativeCollection", - "string": "NativeCollection()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from abstract Collection.

", - "summary": "

Inherit from abstract Collection.

", - "body": "" - }, - "ignore": true, - "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "__proto__", - "value": "MongooseCollection.prototype", - "string": "NativeCollection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the connection opens.

", - "summary": "

Called when the connection opens.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onOpen", - "string": "NativeCollection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the connection closes

", - "summary": "

Called when the connection closes

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onClose", - "string": "NativeCollection.prototype.onClose()" - } - }, - { - "tags": [], - "description": { - "full": "

Copy the collection methods and make them subject to queues

", - "summary": "

Copy the collection methods and make them subject to queues

", - "body": "" - }, - "ignore": true, - "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" - }, - { - "tags": [], - "description": { - "full": "

Debug print helper

", - "summary": "

Debug print helper

", - "body": "" - }, - "ignore": true, - "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", - "ctx": { - "type": "function", - "name": "print", - "string": "print()" - } - }, - { - "tags": [], - "description": { - "full": "

Debug print helper

", - "summary": "

Debug print helper

", - "body": "" - }, - "ignore": true, - "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n } else if ('Date' === x[key].constructor.name) {\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", - "ctx": { - "type": "function", - "name": "format", - "string": "format()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "method", - "string": "getIndexes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Retreives information about this collections indexes.

", - "summary": "

Retreives information about this collections indexes.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "getIndexes", - "value": "NativeCollection.prototype.indexInformation", - "string": "NativeCollection.prototypegetIndexes" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeCollection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeCollection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/connection.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", - "ctx": { - "type": "declaration", - "name": "MongooseConnection", - "value": "require('../../connection')", - "string": "MongooseConnection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Connection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

A node-mongodb-native connection implementation.

", - "summary": "

A node-mongodb-native connection implementation.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", - "ctx": { - "type": "function", - "name": "NativeConnection", - "string": "NativeConnection()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from Connection.

", - "summary": "

Inherits from Connection.

", - "body": "" - }, - "ignore": true, - "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeConnection", - "name": "__proto__", - "value": "MongooseConnection.prototype", - "string": "NativeConnection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Opens the connection to MongoDB.

", - "summary": "

Opens the connection to MongoDB.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, Number(this.port), this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpen", - "string": "NativeConnection.prototype.doOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - } - ], - "description": { - "full": "

Opens a connection to a MongoDB ReplicaSet.

\n\n

See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

", - "summary": "

Opens a connection to a MongoDB ReplicaSet.

", - "body": "

See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , ports = this.port\n , self = this\n\n this.host.forEach(function (host, i) {\n servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));\n });\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpenSet", - "string": "NativeConnection.prototype.doOpenSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Closes the connection

", - "summary": "

Closes the connection

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doClose", - "string": "NativeConnection.prototype.doClose()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeConnection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeConnection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/objectid.js -[ - { - "tags": [ - { - "type": "constructor", - "string": "NodeMongoDbObjectId" - }, - { - "type": "see", - "local": "ObjectId", - "visibility": "ObjectId" - } - ], - "description": { - "full": "

node-mongodb-native ObjectId

", - "summary": "

node-mongodb-native ObjectId

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require('mongodb').BSONPure.ObjectID", - "string": "ObjectId" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", - "ctx": { - "type": "declaration", - "name": "ObjectIdToString", - "value": "ObjectId.toString.bind(ObjectId)", - "string": "ObjectIdToString" - } - } -] -### lib/error.js -[ - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" - } - ], - "description": { - "full": "

Mongoose error

", - "summary": "

Mongoose error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", - "ctx": { - "type": "function", - "name": "MongooseError", - "string": "MongooseError()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from Error.

", - "summary": "

Inherits from Error.

", - "body": "" - }, - "ignore": true, - "code": "MongooseError.prototype.__proto__ = Error.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseError", - "name": "__proto__", - "value": "Error.prototype", - "string": "MongooseError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseError", - "string": "module.exports" - } - } -] -### lib/errors/cast.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casting Error constructor.

", - "summary": "

Casting Error constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", - "ctx": { - "type": "function", - "name": "CastError", - "string": "CastError()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseError.

", - "summary": "

Inherits from MongooseError.

", - "body": "" - }, - "ignore": true, - "code": "CastError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "CastError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "CastError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

exports

", - "summary": "

exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = CastError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "CastError", - "string": "module.exports" - } - } -] -### lib/errors/document.js -[ - { - "tags": [], - "description": { - "full": "

Module requirements

", - "summary": "

Module requirements

", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Document Error

", - "summary": "

Document Error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", - "ctx": { - "type": "function", - "name": "DocumentError", - "string": "DocumentError()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseError.

", - "summary": "

Inherits from MongooseError.

", - "body": "" - }, - "ignore": true, - "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "DocumentError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = DocumentError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = DocumentError", - "string": "module.exports" - } - } -] -### lib/errors/validation.js -[ - { - "tags": [], - "description": { - "full": "

Module requirements

", - "summary": "

Module requirements

", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "instance", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

Document Validation Error

", - "summary": "

Document Validation Error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", - "ctx": { - "type": "function", - "name": "ValidationError", - "string": "ValidationError()" - } - }, - { - "tags": [], - "description": { - "full": "

Console.log helper

", - "summary": "

Console.log helper

", - "body": "" - }, - "ignore": false, - "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", - "ctx": { - "type": "method", - "constructor": "ValidationError", - "name": "toString", - "string": "ValidationError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseError.

", - "summary": "

Inherits from MongooseError.

", - "body": "" - }, - "ignore": true, - "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidationError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidationError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports

", - "summary": "

Module exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = ValidationError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = ValidationError", - "string": "module.exports" - } - } -] -### lib/errors/validator.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Schema validator error

", - "summary": "

Schema validator error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", - "ctx": { - "type": "function", - "name": "ValidatorError", - "string": "ValidatorError()" - } - }, - { - "tags": [], - "description": { - "full": "

toString helper

", - "summary": "

toString helper

", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", - "ctx": { - "type": "method", - "constructor": "ValidatorError", - "name": "toString", - "string": "ValidatorError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseError

", - "summary": "

Inherits from MongooseError

", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidatorError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidatorError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

exports

", - "summary": "

exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ValidatorError", - "string": "module.exports" - } - } -] -### lib/index.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Mongoose constructor.

\n\n

The exports object of the mongoose module is an instance of this class.
Most apps will only use this one instance.

", - "summary": "

Mongoose constructor.

", - "body": "

The exports object of the mongoose module is an instance of this class.
Most apps will only use this one instance.

" - }, - "isPrivate": false, - "ignore": false, - "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", - "ctx": { - "type": "function", - "name": "Mongoose", - "string": "Mongoose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets mongoose options

\n\n

Example:

\n\n
mongoose.set('test', value) // sets the 'test' option to `value`\n
", - "summary": "

Sets mongoose options

", - "body": "

Example:

\n\n
mongoose.set('test', value) // sets the 'test' option to `value`\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "set", - "string": "Mongoose.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "method", - "string": "get" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Gets mongoose options

\n\n

Example:

\n\n
mongoose.get('test') // returns the 'test' value\n
", - "summary": "

Gets mongoose options

", - "body": "

Example:

\n\n
mongoose.get('test') // returns the 'test' value\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.get = Mongoose.prototype.set;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "get", - "value": "Mongoose.prototype.set", - "string": "Mongoose.prototypeget" - } - }, - { - "tags": [], - "description": { - "full": "

ReplSet connection string check.

", - "summary": "

ReplSet connection string check.

", - "body": "" - }, - "ignore": true, - "code": "var rgxReplSet = /^.+,.+$/;", - "ctx": { - "type": "declaration", - "name": "rgxReplSet", - "value": "/^.+,.+$/", - "string": "rgxReplSet" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[uri]", - "description": "a mongodb:// URI" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "the created Connection object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Creates a Connection instance.

\n\n

Example:

\n\n
// with mongodb:// URI\ndb = mongoose.createConnection('mongodb://localhost:port/database');\n\n// replica sets\ndb = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port);\n
", - "summary": "

Creates a Connection instance.

", - "body": "

Example:

\n\n
// with mongodb:// URI\ndb = mongoose.createConnection('mongodb://localhost:port/database');\n\n// replica sets\ndb = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "createConnection", - "string": "Mongoose.prototype.createConnection()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Mongoose#createConnection", - "visibility": "Mongoose#createConnection" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - } - ], - "description": { - "full": "

Opens the default mongoose connection.

\n\n

If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

", - "summary": "

Opens the default mongoose connection.

", - "body": "

If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "connect", - "string": "Mongoose.prototype.connect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "called after all connection close." - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Disconnects all connections.

", - "summary": "

Disconnects all connections.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "disconnect", - "string": "Mongoose.prototype.disconnect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name (optional, induced from model name)" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipInit]", - "description": "whether to skip initialization (defaults to false)" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a model or retrieves it.

\n\n

Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
\n\n

When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

\n\n

Example:

\n\n
var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
", - "summary": "

Defines a model or retrieves it.

", - "body": "

Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
\n\n

When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

\n\n

Example:

\n\n
var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n // normalize collection\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // look up models for the collection\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n this.modelSchemas[name] = schema;\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n } else {\n throw new Error('Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)');\n }\n }\n\n if (!this.models[name]) {\n schema || (schema = this.modelSchemas[name]);\n collection || (collection = schema.set('collection') || format(name));\n\n var model = Model.compile(name\n , this.modelSchemas[name]\n , collection\n , this.connection\n , this);\n\n if (!skipInit) model.init();\n\n this.models[name] = model;\n }\n\n return this.models[name];\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "model", - "string": "Mongoose.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "plugin callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "optional options" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares a global plugin executed on all Schemas.

\n\n

Equivalent to calling .plugin(fn) on each Schema you create.

", - "summary": "

Declares a global plugin executed on all Schemas.

", - "body": "

Equivalent to calling .plugin(fn) on each Schema you create.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "plugin", - "string": "Mongoose.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "connection" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The default connection of the mongoose module.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
\n\n

This is the connection used by default for every model created using mongoose.model.

", - "summary": "

The default connection of the mongoose module.

", - "body": "

Example:

\n\n
var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
\n\n

This is the connection used by default for every model created using mongoose.model.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" - }, - { - "tags": [], - "description": { - "full": "

Driver depentend APIs

", - "summary": "

Driver depentend APIs

", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

Connection

", - "summary": "

Connection

", - "body": "" - }, - "ignore": true, - "code": "var Connection = require(driver + '/connection');", - "ctx": { - "type": "declaration", - "name": "Connection", - "value": "require(driver + '/connection')", - "string": "Connection" - } - }, - { - "tags": [], - "description": { - "full": "

Collection

", - "summary": "

Collection

", - "body": "" - }, - "ignore": true, - "code": "var Collection = require(driver + '/collection');", - "ctx": { - "type": "declaration", - "name": "Collection", - "value": "require(driver + '/collection')", - "string": "Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The exports object is an instance of Mongoose.

", - "summary": "

The exports object is an instance of Mongoose.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = new Mongoose", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Collection constructor

", - "summary": "

The Mongoose Collection constructor

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Collection = Collection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Collection", - "value": "Collection", - "string": "mongoose.Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Connection constructor

", - "summary": "

The Mongoose Connection constructor

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Connection = Connection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Connection", - "value": "Connection", - "string": "mongoose.Connection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Mongoose version

", - "summary": "

Mongoose version

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "version", - "value": "JSON.parse(", - "string": "mongoose.version" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose constructor

\n\n

The exports of the mongoose module is an instance of this class.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
", - "summary": "

The Mongoose constructor

", - "body": "

The exports of the mongoose module is an instance of this class.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Mongoose = Mongoose;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Mongoose", - "value": "Mongoose", - "string": "mongoose.Mongoose" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Schema constructor

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
", - "summary": "

The Mongoose Schema constructor

", - "body": "

Example:

\n\n
var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Schema = Schema;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Schema", - "value": "Schema", - "string": "mongoose.Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose SchemaType constructor.

", - "summary": "

The Mongoose SchemaType constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaType = SchemaType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaType", - "value": "SchemaType", - "string": "mongoose.SchemaType" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Schema.SchemaTypes #schema_Schema-Types", - "visibility": "Schema.SchemaTypes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The various Mongoose SchemaTypes.

\n\n

Note:

\n\n

Alias of mongoose.Schema.Types for backwards compatibility.

", - "summary": "

The various Mongoose SchemaTypes.

", - "body": "

Note:

\n\n

Alias of mongoose.Schema.Types for backwards compatibility.

" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaTypes = Schema.Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaTypes", - "value": "Schema.Types", - "string": "mongoose.SchemaTypes" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose VirtualType constructor.

", - "summary": "

The Mongoose VirtualType constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.VirtualType = VirtualType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "VirtualType", - "value": "VirtualType", - "string": "mongoose.VirtualType" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The various Mongoose Types.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
\n\n

Types:

\n\n
    \n
  • Array
  • \n
  • Buffer
  • \n
  • Document
  • \n
  • Embedded
  • \n
  • DocumentArray
  • \n
  • ObjectId
  • \n
\n\n

Using this exposed access to the ObjectId type, we can construct ids on demand.

\n\n
var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
", - "summary": "

The various Mongoose Types.

", - "body": "

Example:

\n\n
var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
\n\n

Types:

\n\n
    \n
  • Array
  • \n
  • Buffer
  • \n
  • Document
  • \n
  • Embedded
  • \n
  • DocumentArray
  • \n
  • ObjectId
  • \n
\n\n

Using this exposed access to the ObjectId type, we can construct ids on demand.

\n\n
var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Types = Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Types", - "value": "Types", - "string": "mongoose.Types" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Query constructor.

", - "summary": "

The Mongoose Query constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Query = Query;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Query", - "value": "Query", - "string": "mongoose.Query" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Promise constructor.

", - "summary": "

The Mongoose Promise constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Promise = Promise;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Promise", - "value": "Promise", - "string": "mongoose.Promise" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Model constructor.

", - "summary": "

The Mongoose Model constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Model = Model;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Model", - "value": "Model", - "string": "mongoose.Model" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Document constructor.

", - "summary": "

The Mongoose Document constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Document = Document;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Document", - "value": "Document", - "string": "mongoose.Document" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The MongooseError constructor.

", - "summary": "

The MongooseError constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Error = require('./error');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Error", - "value": "require('./error')", - "string": "mongoose.Error" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The node-mongodb-native driver Mongoose uses.

", - "summary": "

The node-mongodb-native driver Mongoose uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.mongo = require('mongodb');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "mongo", - "value": "require('mongodb')", - "string": "mongoose.mongo" - } - } -] -### lib/model.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('./document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "values to with which to create the document" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "event", - "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." - }, - { - "type": "event", - "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Model constructor

", - "summary": "

Model constructor

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", - "ctx": { - "type": "function", - "name": "Model", - "string": "Model()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from Document.

", - "summary": "

Inherits from Document.

", - "body": "" - }, - "ignore": true, - "code": "Model.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "Model", - "name": "__proto__", - "value": "Document.prototype", - "string": "Model.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

Connection the model uses.

", - "summary": "

Connection the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.db;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "collection" - } - ], - "description": { - "full": "

Collection the model uses.

", - "summary": "

Collection the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.collection;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "modelName" - } - ], - "description": { - "full": "

The name of the model

", - "summary": "

The name of the model

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.modelName;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "object" - }, - { - "type": "return", - "types": [ - "Object", - "undefined" - ], - "description": "population paths" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns what paths can be populated

", - "summary": "

Returns what paths can be populated

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_getPopulationKeys", - "string": "Model.prototype._getPopulationKeys()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "schema", - "description": "type for the oid" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "oid", - "description": "object id or array of object ids" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "query", - "description": "object specifying query conditions, fields, and options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Populates an object

", - "summary": "

Populates an object

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_populate", - "string": "Model.prototype._populate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "query that originated the initialization" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Performs auto-population of relations.

", - "summary": "

Performs auto-population of relations.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "init", - "string": "Model.prototype.init()" - } - }, - { - "tags": [], - "description": { - "full": "

Handles doc.save() callbacks

", - "summary": "

Handles doc.save() callbacks

", - "body": "" - }, - "ignore": true, - "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new Error('No matching document found.'));\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", - "ctx": { - "type": "function", - "name": "handleSave", - "string": "handleSave()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "title": "middleware", - "url": "http://mongoosejs.com/docs/middleware.html", - "visibility": "http://mongoosejs.com/docs/middleware.html" - } - ], - "description": { - "full": "

Saves this document.

\n\n

Example:

\n\n
product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
\n\n

The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

\n\n
var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
\n\n

However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

\n\n
Product.on('error', handleError);\n
", - "summary": "

Saves this document.

", - "body": "

Example:

\n\n
product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
\n\n

The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

\n\n
var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
\n\n

However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

\n\n
Product.on('error', handleError);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n complete(null);\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "save", - "string": "Model.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Mixed" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[operation]", - "description": "" - } - ], - "description": { - "full": "

Apply the operation to the delta (update) clause as
well as track versioning for our where clause.

", - "summary": "

Apply the operation to the delta (update) clause as
well as track versioning for our where clause.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", - "ctx": { - "type": "function", - "name": "operand", - "string": "operand()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "val", - "description": "" - } - ], - "description": { - "full": "

Compiles an update and where clause for a val with _atomics.

", - "summary": "

Compiles an update and where clause for a val with _atomics.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", - "ctx": { - "type": "function", - "name": "handleAtomics", - "string": "handleAtomics()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Produces a special query document of the modified properties used in updates.

", - "summary": "

Produces a special query document of the modified properties used in updates.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_delta", - "string": "Model.prototype._delta()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Appends versioning to the where and update clauses.

", - "summary": "

Appends versioning to the where and update clauses.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_version", - "string": "Model.prototype._version()" - } - }, - { - "tags": [ - { - "type": "see", - "title": "versionKeys", - "url": "http://mongoosejs.com/docs/guide.html#versionKey", - "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Signal that we desire an increment of this documents version.

", - "summary": "

Signal that we desire an increment of this documents version.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "increment", - "string": "Model.prototype.increment()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns a query object which applies shardkeys if they exist.

", - "summary": "

Returns a query object which applies shardkeys if they exist.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_where", - "string": "Model.prototype._where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Removes this document from the db.

\n\n

Example:

\n\n
product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
", - "summary": "

Removes this document from the db.

", - "body": "

Example:

\n\n
product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) return this;\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "remove", - "string": "Model.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Register hooks override

", - "summary": "

Register hooks override

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_registerHooks", - "string": "Model.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns another Model instance.

\n\n

Example:

\n\n
var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
", - "summary": "

Returns another Model instance.

", - "body": "

Example:

\n\n
var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "model", - "string": "Model.prototype.model()" - } - }, - { - "tags": [ - { - "type": "TODO", - "string": "determine if this is still necessary" - } - ], - "description": { - "full": "

Give the constructor the ability to emit events.

", - "summary": "

Give the constructor the ability to emit events.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the model compiles.

", - "summary": "

Called when the model compiles.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.init = function init () {\n if (this.schema.options.autoIndex)\n this.ensureIndexes();\n\n this.schema.emit('init', this);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "init", - "string": "Model.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[cb]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sends ensureIndex commands to mongo for each index declared in the schema.

\n\n

After completion, an index event is emitted on this Model passing an error if one occurred.

", - "summary": "

Sends ensureIndex commands to mongo for each index declared in the schema.

", - "body": "

After completion, an index event is emitted on this Model passing an error if one occurred.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "ensureIndexes", - "string": "Model.ensureIndexes()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "schema" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Schema the model uses.

", - "summary": "

Schema the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.schema;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Database instance the model uses.

", - "summary": "

Database instance the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.db;" - }, - { - "tags": [ - { - "type": "property", - "string": "collection" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Collection the model uses.

", - "summary": "

Collection the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.collection;" - }, - { - "tags": [ - { - "type": "property", - "string": "base" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Base Mongoose instance the model uses.

", - "summary": "

Base Mongoose instance the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.base;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Removes documents from the collection.

\n\n

Note:

\n\n

To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.remove({ _id: id }).exec();\n
", - "summary": "

Removes documents from the collection.

", - "body": "

Note:

\n\n

To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.remove({ _id: id }).exec();\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "remove", - "string": "Model.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Finds documents

\n\n

Examples:

\n\n
// retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
", - "summary": "

Finds documents

", - "body": "

Examples:

\n\n
// retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "find", - "string": "Model.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Merges the current named scope query into query.

", - "summary": "

Merges the current named scope query into query.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "_applyNamedScope", - "string": "Model._applyNamedScope()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "objectid, or a value that can be casted to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Finds a single document by id.

\n\n

The id is cast to an ObjectId before sending the command.

\n\n

Example:

\n\n
Adventure.findById(id, callback);\n
", - "summary": "

Finds a single document by id.

", - "body": "

The id is cast to an ObjectId before sending the command.

\n\n

Example:

\n\n
Adventure.findById(id, callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findById", - "string": "Model.findById()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Finds one document.

\n\n

The conditions are cast to their respective SchemaTypes before the command is sent.

\n\n

Example:

\n\n
Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
", - "summary": "

Finds one document.

", - "body": "

The conditions are cast to their respective SchemaTypes before the command is sent.

\n\n

Example:

\n\n
Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n // TODO Handle all 3 of the following scenarios\n // Hint: Only some of these scenarios are possible if cQuery is present\n // Scenario: findOne(conditions, fields, callback);\n // Scenario: findOne(fields, options, callback);\n // Scenario: findOne(conditions, options, callback);\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n // TODO Handle all 2 of the following scenarios\n // Scenario: findOne(conditions, callback)\n // Scenario: findOne(fields, callback)\n // Scenario: findOne(options, callback);\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOne", - "string": "Model.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Counts number of matching documents in a database collection.

\n\n

Example:

\n\n
Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
", - "summary": "

Counts number of matching documents in a database collection.

", - "body": "

Example:

\n\n
Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "count", - "string": "Model.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes a DISTINCT command

", - "summary": "

Executes a DISTINCT command

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "distinct", - "string": "Model.distinct()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "optional value" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Creates a Query, applies the passed conditions, and returns the Query.

\n\n

For example, instead of writing:

\n\n
User.find({age: {$gte: 21, $lte: 65}}, callback);\n
\n\n

we can instead write:

\n\n
User.where('age').gte(21).lte(65).exec(callback);\n
\n\n

Since the Query class also supports where you can continue chaining

\n\n
User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
", - "summary": "

Creates a Query, applies the passed conditions, and returns the Query.

", - "body": "

For example, instead of writing:

\n\n
User.find({age: {$gte: 21, $lte: 65}}, callback);\n
\n\n

we can instead write:

\n\n
User.where('age').gte(21).lte(65).exec(callback);\n
\n\n

Since the Query class also supports where you can continue chaining

\n\n
User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "where", - "string": "Model.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "argument", - "description": "is a javascript string or anonymous function" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "memberOf", - "parent": "Model" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Query.$where #query_Query-%24where", - "visibility": "Query.$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Creates a Query and specifies a $where condition.

\n\n

Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

\n\n
Blog.$where('this.comments.length > 5');\n
", - "summary": "

Creates a Query and specifies a $where condition.

", - "body": "

Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

\n\n
Blog.$where('this.comments.length > 5');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", - "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndUpdate", - "string": "Model.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "an ObjectId or string that can be cast to one." - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", - "visibility": "Model.findOneAndUpdate" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", - "summary": "

Issues a mongodb findAndModify update command by a documents id.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndUpdate", - "string": "Model.findByIdAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issue a mongodb findAndModify remove command.

\n\n

Finds a matching document, removes it, passing the found document (if any) to the callback.

\n\n

Executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
", - "summary": "

Issue a mongodb findAndModify remove command.

", - "body": "

Finds a matching document, removes it, passing the found document (if any) to the callback.

\n\n

Executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndRemove", - "string": "Model.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "id", - "description": "ObjectId or string that can be cast to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", - "visibility": "Model.findOneAndRemove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - } - ], - "description": { - "full": "

Issue a mongodb findAndModify remove command by a documents id.

\n\n

Finds a matching document, removes it, passing the found document (if any) to the callback.

\n\n

Executes immediately if callback is passed, else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
", - "summary": "

Issue a mongodb findAndModify remove command by a documents id.

", - "body": "

Finds a matching document, removes it, passing the found document (if any) to the callback.

\n\n

Executes immediately if callback is passed, else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndRemove", - "string": "Model.findByIdAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array", - "Object..." - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Shortcut for creating a new Document that is automatically saved to the db if valid.

\n\n

Example:

\n\n
Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
", - "summary": "

Shortcut for creating a new Document that is automatically saved to the db if valid.

", - "body": "

Example:

\n\n
Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "create", - "string": "Model.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "update", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", - "summary": "

Updates documents in the database without returning them.

", - "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "update", - "string": "Model.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "o", - "description": "an object specifying map-reduce options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/MapReduce", - "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes a mapReduce command.

\n\n

o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

\n\n

Example:

\n\n
var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
\n\n

Other options:

\n\n
    \n
  • query {Object} query filter object.
  • \n
  • limit {Number} max number of documents
  • \n
  • keeptemp {Boolean, default:false} keep temporary data
  • \n
  • finalize {Function} finalize function
  • \n
  • scope {Object} scope variables exposed to map/reduce/finalize during execution
  • \n
  • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
  • \n
  • verbose {Boolean, default:false} provide statistics on job execution time.
  • \n
  • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
  • \n
\n\n

* out options:

\n\n
    \n
  • {inline:1} the results are returned in an array
  • \n
  • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
  • \n
  • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
  • \n
  • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
  • \n
\n\n

If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

\n\n

Example:

\n\n
var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
", - "summary": "

Executes a mapReduce command.

", - "body": "

o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

\n\n

Example:

\n\n
var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
\n\n

Other options:

\n\n
    \n
  • query {Object} query filter object.
  • \n
  • limit {Number} max number of documents
  • \n
  • keeptemp {Boolean, default:false} keep temporary data
  • \n
  • finalize {Function} finalize function
  • \n
  • scope {Object} scope variables exposed to map/reduce/finalize during execution
  • \n
  • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
  • \n
  • verbose {Boolean, default:false} provide statistics on job execution time.
  • \n
  • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
  • \n
\n\n

* out options:

\n\n
    \n
  • {inline:1} the results are returned in an array
  • \n
  • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
  • \n
  • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
  • \n
  • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
  • \n
\n\n

If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

\n\n

Example:

\n\n
var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "mapReduce", - "string": "Model.mapReduce()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "collectionName", - "description": "" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "connection", - "description": "" - }, - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "mongoose instance" - } - ], - "description": { - "full": "

Compiler utility.

", - "summary": "

Compiler utility.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "compile", - "string": "Model.compile()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Model;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Model", - "string": "module.exports" - } - } -] -### lib/namedscope.js -[ - { - "tags": [ - { - "type": "param", - "types": [ - "NamedScope" - ], - "name": "target", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "getters", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Decorate

", - "summary": "

Decorate

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", - "ctx": { - "type": "method", - "constructor": "NamedScope", - "name": "decorate", - "string": "NamedScope.prototype.decorate()" - } - } -] -### lib/promise.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", - "ctx": { - "type": "declaration", - "name": "util", - "value": "require('./utils')", - "string": "util" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "back", - "description": "a callback+errback that accepts `fn(err, ...){}` as signature" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`err`: Emits when the promise resolves to an error." - }, - { - "type": "event", - "string": "`complete`: Emits when the promise resolves sucessfully." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Promise constructor.

", - "summary": "

Promise constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", - "ctx": { - "type": "function", - "name": "Promise", - "string": "Promise()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from EventEmitter.

", - "summary": "

Inherits from EventEmitter.

", - "body": "" - }, - "ignore": true, - "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Promise", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Promise.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Event" - ], - "name": "event", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds listener to the event.

\n\n

If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

", - "summary": "

Adds listener to the event.

", - "body": "

If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "on", - "string": "Promise.prototype.on()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Keeps track of emitted events to run them on on.

", - "summary": "

Keeps track of emitted events to run them on on.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "emit", - "string": "Promise.prototype.emit()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Shortcut for emitting the complete event.

", - "summary": "

Shortcut for emitting the complete event.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "complete", - "string": "Promise.prototype.complete()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

Shortcut for emitting the err event.

", - "summary": "

Shortcut for emitting the err event.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "error", - "string": "Promise.prototype.error()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Shortcut for .on('complete', fn).

", - "summary": "

Shortcut for .on('complete', fn).

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addCallback", - "string": "Promise.prototype.addCallback()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Shortcut for .on('err', fn).

", - "summary": "

Shortcut for .on('err', fn).

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addErrback", - "string": "Promise.prototype.addErrback()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

Adds a single function that's both a callback and errback.

", - "summary": "

Adds a single function that's both a callback and errback.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addBack", - "string": "Promise.prototype.addBack()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "optional error or null" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "value to complete the promise with" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sugar for handling cases where you may be resolving to either an error condition or a success condition.

", - "summary": "

Sugar for handling cases where you may be resolving to either an error condition or a success condition.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "resolve", - "string": "Promise.prototype.resolve()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = Promise;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Promise", - "string": "module.exports" - } - } -] -### lib/query.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "criteria", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Query constructor used for building queries.

\n\n

Example:

\n\n
var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
", - "summary": "

Query constructor used for building queries.

", - "body": "

Example:

\n\n
var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n if (criteria) this.find(criteria);\n}", - "ctx": { - "type": "function", - "name": "Query", - "string": "Query()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets query options.

\n\n

Options:

\n\n\n\n

* denotes a query helper method is also available

", - "summary": "

Sets query options.

", - "body": "

Options:

\n\n\n\n

* denotes a query helper method is also available

" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "setOptions", - "string": "Query.prototype.setOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "the model to which the query is bound" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "the operation to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "updateArg", - "description": "used in update methods" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Binds this query to a model.

", - "summary": "

Binds this query to a model.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "bind", - "string": "Query.prototype.bind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "[operation]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes the query

\n\n

Examples

\n\n
query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
", - "summary": "

Executes the query

", - "body": "

Examples

\n\n
query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exec", - "string": "Query.prototype.exec()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[criteria]", - "description": "mongodb selector" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Finds documents.

\n\n

When no callback is passed, the query is not executed.

\n\n

Example

\n\n
query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
", - "summary": "

Finds documents.

", - "body": "

When no callback is passed, the query is not executed.

\n\n

Example

\n\n
query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "find", - "string": "Query.prototype.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[obj]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Casts this query to the schema of model

\n\n

Note

\n\n

If obj is present, it is cast instead of this query.

", - "summary": "

Casts this query to the schema of model

", - "body": "

Note

\n\n

If obj is present, it is cast instead of this query.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "cast", - "string": "Query.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns default options.

", - "summary": "

Returns default options.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n if (! ('safe' in options)) options.safe = model.schema.options.safe;\n return options;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_optionsForExec", - "string": "Query.prototype._optionsForExec()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Applies schematype selected options to this query.

", - "summary": "

Applies schematype selected options to this query.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_applyPaths", - "string": "Query.prototype._applyPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "js", - "description": "javascript string or function" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $where condition

\n\n

Use $where when you need to select documents using a JavaScript expression.

\n\n

Example

\n\n
query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
", - "summary": "

Specifies a $where condition

", - "body": "

Use $where when you need to select documents using a JavaScript expression.

\n\n

Example

\n\n
query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a path for use with chaining.

\n\n

Example

\n\n
// instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
", - "summary": "

Specifies a path for use with chaining.

", - "body": "

Example

\n\n
// instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "where", - "string": "Query.prototype.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the complementary comparison value for paths specified with where()

\n\n

Example

\n\n
User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
", - "summary": "

Specifies the complementary comparison value for paths specified with where()

", - "body": "

Example

\n\n
User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "equals", - "string": "Query.prototype.equals()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies arguments for an $or condition.

\n\n

Example

\n\n
query.or([{ color: 'red' }, { status: 'emergency' }])\n
", - "summary": "

Specifies arguments for an $or condition.

", - "body": "

Example

\n\n
query.or([{ color: 'red' }, { status: 'emergency' }])\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "or", - "string": "Query.prototype.or()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies arguments for a $nor condition.

\n\n

Example

\n\n
query.nor([{ color: 'green' }, { status: 'ok' }])\n
", - "summary": "

Specifies arguments for a $nor condition.

", - "body": "

Example

\n\n
query.nor([{ color: 'green' }, { status: 'ok' }])\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nor", - "string": "Query.prototype.nor()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "gt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $gt query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

\n\n

Example

\n\n
Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
", - "summary": "

Specifies a $gt query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

\n\n

Example

\n\n
Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "gte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $gte query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $gte query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $lt query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $lt query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $lte query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $lte query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "ne" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $ne query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $ne query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "in" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $in query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies an $in query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "nin" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $nin query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies an $nin query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "all" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $all query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies an $all query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "size" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $size query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies an $size query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "regex" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $regex query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $regex query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxDistance" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $maxDistance query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $maxDistance query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

\n\n
Thing.where('type').nin(array)\n
", - "summary": "

gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

", - "body": "
Thing.where('type').nin(array)\n
" - }, - "ignore": true, - "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $near condition

", - "summary": "

Specifies a $near condition

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "near", - "string": "Query.prototype.near()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $nearSphere condition.

", - "summary": "

Specifies a $nearSphere condition.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nearSphere", - "string": "Query.prototype.nearSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $mod condition

", - "summary": "

Specifies a $mod condition

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "mod", - "string": "Query.prototype.mod()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $exists condition

", - "summary": "

Specifies an $exists condition

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exists", - "string": "Query.prototype.exists()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object", - "Function" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "Function" - ], - "name": "criteria", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $elemMatch condition

\n\n

Example

\n\n
query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
", - "summary": "

Specifies an $elemMatch condition

", - "body": "

Example

\n\n
query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "elemMatch", - "string": "Query.prototype.elemMatch()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "within" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Syntax sugar for expressive queries.

\n\n

Example

\n\n
query.within.box()\nquery.within.center()\n
", - "summary": "

Syntax sugar for expressive queries.

", - "body": "

Example

\n\n
query.within.box()\nquery.within.center()\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "see", - "local": "Query#within #query_Query-within", - "visibility": "Query#within" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $box condition

\n\n

Example

\n\n
var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
", - "summary": "

Specifies a $box condition

", - "body": "

Example

\n\n
var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "box", - "string": "Query.prototype.box()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "options e.g. { $uniqueDocs: true }" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $center condition

\n\n

Example

\n\n
var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
", - "summary": "

Specifies a $center condition

", - "body": "

Example

\n\n
var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "center", - "string": "Query.prototype.center()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $centerSphere condition

\n\n

Example

\n\n
var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
", - "summary": "

Specifies a $centerSphere condition

", - "body": "

Example

\n\n
var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "centerSphere", - "string": "Query.prototype.centerSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Array", - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $polygon condition

\n\n

Example

\n\n
var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
", - "summary": "

Specifies a $polygon condition

", - "body": "

Example

\n\n
var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "polygon", - "string": "Query.prototype.polygon()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "local": "SchemaType", - "visibility": "SchemaType" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies which document fields to include or exclude

\n\n

When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

\n\n

Example

\n\n
// include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
", - "summary": "

Specifies which document fields to include or exclude

", - "body": "

When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

\n\n

Example

\n\n
// include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "select", - "string": "Query.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "number of elements to slice" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", - "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $slice condition

\n\n

Example

\n\n
query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
", - "summary": "

Specifies a $slice condition

", - "body": "

Example

\n\n
query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slice", - "string": "Query.prototype.slice()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets the sort order

\n\n

If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

\n\n

If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

\n\n

Example

\n\n
// these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
", - "summary": "

Sets the sort order

", - "body": "

If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

\n\n

If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

\n\n

Example

\n\n
// these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "sort", - "string": "Query.prototype.sort()" - } - }, - { - "tags": [], - "description": { - "full": "

@ignore

", - "summary": "

@ignore

", - "body": "" - }, - "ignore": true, - "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", - "ctx": { - "type": "function", - "name": "push", - "string": "push()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "limit" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the limit option.

\n\n

Example

\n\n
Kitten.find().limit(20)\n
", - "summary": "

Specifies the limit option.

", - "body": "

Example

\n\n
Kitten.find().limit(20)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "skip" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the skip option.

\n\n

Example

\n\n
Kitten.find().skip(100).limit(20)\n
", - "summary": "

Specifies the skip option.

", - "body": "

Example

\n\n
Kitten.find().skip(100).limit(20)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxscan" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the maxscan option.

\n\n

Example

\n\n
Kitten.find().maxscan(100)\n
", - "summary": "

Specifies the maxscan option.

", - "body": "

Example

\n\n
Kitten.find().maxscan(100)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "batchSize" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the batchSize option.

\n\n

Example

\n\n
Kitten.find().batchSize(100)\n
", - "summary": "

Specifies the batchSize option.

", - "body": "

Example

\n\n
Kitten.find().batchSize(100)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "comment" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the comment option.

\n\n

Example

\n\n
Kitten.findOne(condition).comment('login query')\n
", - "summary": "

Specifies the comment option.

", - "body": "

Example

\n\n
Kitten.findOne(condition).comment('login query')\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

limit, skip, maxscan, batchSize, comment

\n\n

Sets these associated options.

\n\n
query.comment('feed query');\n
", - "summary": "

limit, skip, maxscan, batchSize, comment

", - "body": "

Sets these associated options.

\n\n
query.comment('feed query');\n
" - }, - "ignore": true, - "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies this query as a snapshot query.

\n\n

Example

\n\n
Kitten.find().snapshot()\n
", - "summary": "

Specifies this query as a snapshot query.

", - "body": "

Example

\n\n
Kitten.find().snapshot()\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "snapshot", - "string": "Query.prototype.snapshot()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "a hint object" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets query hints.

\n\n

Example

\n\n
Model.find().hint({ indexA: 1, indexB: -1})\n
", - "summary": "

Sets query hints.

", - "body": "

Example

\n\n
Model.find().hint({ indexA: 1, indexB: -1})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "hint", - "string": "Query.prototype.hint()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets the slaveOk option.

\n\n

Example:

\n\n
new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
", - "summary": "

Sets the slaveOk option.

", - "body": "

Example:

\n\n
new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slaveOk", - "string": "Query.prototype.slaveOk()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets the lean option.

\n\n

Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

\n\n

This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

\n\n

Example:

\n\n
new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
", - "summary": "

Sets the lean option.

", - "body": "

Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

\n\n

This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

\n\n

Example:

\n\n
new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "lean", - "string": "Query.prototype.lean()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", - "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets tailable option.

\n\n

Example

\n\n
Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
", - "summary": "

Sets tailable option.

", - "body": "

Example

\n\n
Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "tailable", - "string": "Query.prototype.tailable()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Executes the query as a find() operation.

", - "summary": "

Executes the query as a find() operation.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n\n var fields = utils.clone(options.fields = this._fields);\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "execFind", - "string": "Query.prototype.execFind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes the query as a findOne() operation.

\n\n

Example

\n\n
Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
", - "summary": "

Executes the query as a findOne() operation.

", - "body": "

Example

\n\n
Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n\n var fields = utils.clone(options.fields = this._fields);\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOne", - "string": "Query.prototype.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Exectues the query as a count() operation.

\n\n

Example

\n\n
Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
", - "summary": "

Exectues the query as a count() operation.

", - "body": "

Example

\n\n
Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "count", - "string": "Query.prototype.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes this query as a distict() operation.

", - "summary": "

Executes this query as a distict() operation.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "distinct", - "string": "Query.prototype.distinct()" - } - }, - { - "tags": [], - "description": { - "full": "

These operators require casting docs
to real Documents for Update operations.

", - "summary": "

These operators require casting docs
to real Documents for Update operations.

", - "body": "" - }, - "ignore": true, - "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", - "ctx": { - "type": "declaration", - "name": "castOps", - "value": "{", - "string": "castOps" - } - }, - { - "tags": [], - "description": { - "full": "

These operators should be cast to numbers instead
of their path schema type.

", - "summary": "

These operators should be cast to numbers instead
of their path schema type.

", - "body": "" - }, - "ignore": true, - "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", - "ctx": { - "type": "declaration", - "name": "numberOps", - "value": "{", - "string": "numberOps" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "the update conditions" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes this query as an update() operation.

\n\n

All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

\n\n

Example

\n\n
Model.update({..}, { title: 'remove words' }, ...)\n
\n\n

becomes

\n\n
Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
\n\n

Note

\n\n

Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

", - "summary": "

Executes this query as an update() operation.

", - "body": "

All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

\n\n

Example

\n\n
Model.update({..}, { title: 'remove words' }, ...)\n
\n\n

becomes

\n\n
Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
\n\n

Note

\n\n

Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n delete options.safe;\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "update", - "string": "Query.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "obj after casting its values" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts obj for an update command.

", - "summary": "

Casts obj for an update command.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdate", - "string": "Query.prototype._castUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "- part of a query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "- path prefix (internal only)" - }, - { - "type": "return", - "types": [ - "Bool" - ], - "description": "true if this path has keys to update" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Walk each path of obj and cast its values
according to its schema.

", - "summary": "

Walk each path of obj and cast its values
according to its schema.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_walkUpdatePath", - "string": "Query.prototype._walkUpdatePath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[$conditional]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts val according to schema and atomic op.

", - "summary": "

Casts val according to schema and atomic op.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdateVal", - "string": "Query.prototype._castUpdateVal()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Finds the schema for path. This is different than
calling schema.path as it also resolves paths with
positional selectors (something.$.another.$.path).

", - "summary": "

Finds the schema for path. This is different than
calling schema.path as it also resolves paths with
positional selectors (something.$.another.$.path).

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_getSchema", - "string": "Query.prototype._getSchema()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes this query as a remove() operation.

\n\n

Example

\n\n
Cassette.where('artist').equals('Anne Murray').remove(callback)\n
", - "summary": "

Executes this query as a remove() operation.

", - "body": "

Example

\n\n
Cassette.where('artist').equals('Anne Murray').remove(callback)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n delete options.safe;\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "remove", - "string": "Query.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[query]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[doc]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Available options

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Examples

\n\n
query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
", - "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Available options

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Examples

\n\n
query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndUpdate", - "string": "Query.prototype.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issues a mongodb findAndModify remove command.

\n\n

Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

\n\n

Available options

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Examples

\n\n
A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
", - "summary": "

Issues a mongodb findAndModify remove command.

", - "body": "

Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

\n\n

Available options

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Examples

\n\n
A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndRemove", - "string": "Query.prototype.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "- either \"remove\" or \"update\"" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

_findAndModify

", - "summary": "

_findAndModify

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n if (this._fields) {\n fields = utils.clone(opts.fields = this._fields);\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_findAndModify", - "string": "Query.prototype._findAndModify()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Model" - ], - "name": "[model]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "see", - "local": "population ./populate.html", - "visibility": "population" - }, - { - "type": "see", - "local": "Query#select #query_Query-select", - "visibility": "Query#select" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies paths which should be populated with other documents.

\n\n

Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

\n\n

Example:

\n\n
Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
", - "summary": "

Specifies paths which should be populated with other documents.

", - "body": "

Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

\n\n

Example:

\n\n
Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "populate", - "string": "Query.prototype.populate()" - } - }, - { - "tags": [], - "description": { - "full": "

Populate options constructor

", - "summary": "

Populate options constructor

", - "body": "" - }, - "ignore": true, - "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", - "ctx": { - "type": "function", - "name": "PopulateOptions", - "string": "PopulateOptions()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "QueryStream" - ], - "description": "" - }, - { - "type": "see", - "local": "QueryStream", - "visibility": "QueryStream" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns a stream interface

\n\n

Example

\n\n
// follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
", - "summary": "

Returns a stream interface

", - "body": "

Example

\n\n
// follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "stream", - "string": "Query.prototype.stream()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

castDoc

", - "summary": "

castDoc

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castDoc", - "string": "castDoc()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

castQuery

", - "summary": "

castQuery

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castQuery", - "string": "castQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Exports.

", - "summary": "

Exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Query", - "string": "module.exports" - } - } -] -### lib/querystream.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", - "ctx": { - "type": "declaration", - "name": "Stream", - "value": "require('stream').Stream", - "string": "Stream" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS Stream http://nodejs.org/api/stream.html" - }, - { - "type": "event", - "string": "`data`: emits a single Mongoose document" - }, - { - "type": "event", - "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." - }, - { - "type": "event", - "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Provides a ReadStream interface for Queries.

\n\n
var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
\n\n

The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

\n\n
Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
", - "summary": "

Provides a ReadStream interface for Queries.

", - "body": "
var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
\n\n

The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

\n\n
Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._ticks = 0;\n this._inline = T_INIT;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", - "ctx": { - "type": "function", - "name": "QueryStream", - "string": "QueryStream()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from Stream

", - "summary": "

Inherit from Stream

", - "body": "" - }, - "ignore": true, - "code": "QueryStream.prototype.__proto__ = Stream.prototype;", - "ctx": { - "type": "property", - "constructor": "QueryStream", - "name": "__proto__", - "value": "Stream.prototype", - "string": "QueryStream.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readable" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Flag stating whether or not this stream is readable.

", - "summary": "

Flag stating whether or not this stream is readable.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.readable;" - }, - { - "tags": [ - { - "type": "property", - "string": "paused" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Flag stating whether or not this stream is paused.

", - "summary": "

Flag stating whether or not this stream is paused.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Initializes the query.

", - "summary": "

Initializes the query.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(options.fields = query._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_init", - "string": "QueryStream.prototype._init()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#__next #querystream_QueryStream-__next", - "visibility": "QueryStream#__next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Trampoline for pulling the next doc from cursor.

", - "summary": "

Trampoline for pulling the next doc from cursor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._next = function () {\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n var fn;\n while (fn = this.__next()) fn.call(this);\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_next", - "string": "QueryStream.prototype._next()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#_next #querystream_QueryStream-_next", - "visibility": "QueryStream#_next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Pulls the next doc from the cursor.

", - "summary": "

Pulls the next doc from the cursor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed) return;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return this.__next;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "__next", - "string": "QueryStream.prototype.__next()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error", - "null" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Transforms raw docs returned from the cursor into a model instance.

", - "summary": "

Transforms raw docs returned from the cursor into a model instance.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._onNextObject = function (err, doc) {\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n return this.destroy();\n }\n\n if (this.query.options && this.query.options.lean === true) {\n this.emit('data', doc);\n this._next();\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields);\n\n // skip _id for pre-init hooks\n delete instance._doc._id;\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_onNextObject", - "string": "QueryStream.prototype._onNextObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Pauses this stream.

", - "summary": "

Pauses this stream.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "pause", - "string": "QueryStream.prototype.pause()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Resumes this stream.

", - "summary": "

Resumes this stream.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n this._next();\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "resume", - "string": "QueryStream.prototype.resume()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "[err]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Destroys the stream, closing the underlying cursor. No more events will be emitted.

", - "summary": "

Destroys the stream, closing the underlying cursor. No more events will be emitted.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "destroy", - "string": "QueryStream.prototype.destroy()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "pipe" - }, - { - "type": "memberOf", - "parent": "QueryStream" - }, - { - "type": "see", - "title": "NodeJS", - "url": "http://nodejs.org/api/stream.html", - "visibility": "http://nodejs.org/api/stream.html" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

\n\n

Example:

\n\n
query.stream().pipe(writeStream [, options])\n
\n\n

This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

\n\n
var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
\n\n

As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

", - "summary": "

Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

", - "body": "

Example:

\n\n
query.stream().pipe(writeStream [, options])\n
\n\n

This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

\n\n
var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
\n\n

As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

Module exports

", - "summary": "

Module exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = QueryStream", - "string": "module.exports" - } - } -] -### lib/schema/array.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Array SchemaType constructor

", - "summary": "

Array SchemaType constructor

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "SchemaArray", - "string": "SchemaArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaArray", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Check required

", - "summary": "

Check required

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "checkRequired", - "string": "SchemaArray.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Overrides the getters application for the population special-case

", - "summary": "

Overrides the getters application for the population special-case

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "applyGetters", - "string": "SchemaArray.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents

", - "summary": "

Casts contents

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "cast", - "string": "SchemaArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "castForQuery", - "string": "SchemaArray.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

@ignore

", - "summary": "

@ignore

", - "body": "" - }, - "ignore": true, - "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': castToNumber\n , '$gte': castToNumber\n , '$lt': castToNumber\n , '$lte': castToNumber\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", - "ctx": { - "type": "function", - "name": "castToNumber", - "string": "castToNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaArray", - "string": "module.exports" - } - } -] -### lib/schema/boolean.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Boolean SchemaType constructor.

", - "summary": "

Boolean SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaBoolean", - "string": "SchemaBoolean()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBoolean", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBoolean.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Required validator

", - "summary": "

Required validator

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "checkRequired", - "string": "SchemaBoolean.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to boolean

", - "summary": "

Casts to boolean

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "cast", - "string": "SchemaBoolean.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", - "ctx": { - "type": "function", - "name": "handleArray", - "string": "handleArray()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Boolean.\");\n\n return handler.call(this, val);\n }\n\n return this.cast($conditional);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "castForQuery", - "string": "SchemaBoolean.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBoolean;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBoolean", - "string": "module.exports" - } - } -] -### lib/schema/buffer.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Buffer SchemaType constructor

", - "summary": "

Buffer SchemaType constructor

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", - "ctx": { - "type": "function", - "name": "SchemaBuffer", - "string": "SchemaBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBuffer", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBuffer.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Check required

", - "summary": "

Check required

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "checkRequired", - "string": "SchemaBuffer.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents

", - "summary": "

Casts contents

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "cast", - "string": "SchemaBuffer.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "castForQuery", - "string": "SchemaBuffer.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBuffer;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBuffer", - "string": "module.exports" - } - } -] -### lib/schema/date.js -[ - { - "tags": [], - "description": { - "full": "

Module requirements.

", - "summary": "

Module requirements.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Date SchemaType constructor.

", - "summary": "

Date SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaDate", - "string": "SchemaDate()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaDate", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaDate.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Required validator for date

", - "summary": "

Required validator for date

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "checkRequired", - "string": "SchemaDate.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to date

", - "summary": "

Casts to date

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "cast", - "string": "SchemaDate.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Date Query casting.

", - "summary": "

Date Query casting.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "castForQuery", - "string": "SchemaDate.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaDate;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaDate", - "string": "module.exports" - } - } -] -### lib/schema/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaArray" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

SubdocsArray SchemaType constructor

", - "summary": "

SubdocsArray SchemaType constructor

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentArray (key, schema, options) {\n // compile an embedded document for this schema\n // TODO Move this into parent model compilation for performance improvement?\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n };\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "DocumentArray", - "string": "DocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from ArrayType.

", - "summary": "

Inherits from ArrayType.

", - "body": "" - }, - "ignore": true, - "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentArray", - "name": "__proto__", - "value": "ArrayType.prototype", - "string": "DocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Performs local validations first, then validations on each embedded doc

", - "summary": "

Performs local validations first, then validations on each embedded doc

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n SchemaType.prototype.doValidate.call(this, array, function(err){\n if (err) return fn(err);\n\n var count = array && array.length\n , error = false;\n\n if (!count) return fn();\n\n array.forEach(function(doc, index){\n doc.validate(function(err){\n if (err && !error){\n // rewrite they key\n err.key = self.key + '.' + index + '.' + err.key;\n fn(err);\n error = true;\n } else {\n --count || fn();\n }\n });\n });\n }, scope);\n};", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "doValidate", - "string": "DocumentArray.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "document", - "description": "that triggers the casting" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents

", - "summary": "

Casts contents

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var subdoc\n , i\n\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument)) {\n if (init) {\n subdoc = new this.casterConstructor(null, value, true);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init, prev);\n }\n\n throw new CastError('documentarray', value);\n};", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "cast", - "string": "DocumentArray.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = DocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "DocumentArray", - "string": "module.exports" - } - } -] -### lib/schema/index.js -[ - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "String", - "value": "require('./string')", - "string": "exports.String" - } - } -] -### lib/schema/mixed.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Mixed SchemaType constructor.

", - "summary": "

Mixed SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "Mixed", - "string": "Mixed()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "Mixed", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "Mixed.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Required validator

", - "summary": "

Required validator

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "checkRequired", - "string": "Mixed.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts val for Mixed.

\n\n

this is a no-op

", - "summary": "

Casts val for Mixed.

", - "body": "

this is a no-op

" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "cast", - "string": "Mixed.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$cond", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "castForQuery", - "string": "Mixed.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = Mixed;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Mixed", - "string": "module.exports" - } - } -] -### lib/schema/number.js -[ - { - "tags": [], - "description": { - "full": "

Module requirements.

", - "summary": "

Module requirements.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Number SchemaType constructor.

", - "summary": "

Number SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", - "ctx": { - "type": "function", - "name": "SchemaNumber", - "string": "SchemaNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaNumber", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaNumber.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Required validator for number

", - "summary": "

Required validator for number

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "checkRequired", - "string": "SchemaNumber.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "value", - "description": "minimum number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets a maximum number validator.

\n\n

Example:

\n\n
var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
", - "summary": "

Sets a maximum number validator.

", - "body": "

Example:

\n\n
var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "min", - "string": "SchemaNumber.prototype.min()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "maximum", - "description": "number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets a maximum number validator.

\n\n

Example:

\n\n
var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
", - "summary": "

Sets a maximum number validator.

", - "body": "

Example:

\n\n
var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "max", - "string": "SchemaNumber.prototype.max()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "value to cast" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to number

", - "summary": "

Casts to number

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "cast", - "string": "SchemaNumber.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "castForQuery", - "string": "SchemaNumber.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaNumber;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaNumber", - "string": "module.exports" - } - } -] -### lib/schema/objectid.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

ObjectId SchemaType constructor.

", - "summary": "

ObjectId SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", - "ctx": { - "type": "function", - "name": "ObjectId", - "string": "ObjectId()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "ObjectId", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "ObjectId.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Check required

", - "summary": "

Check required

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "checkRequired", - "string": "ObjectId.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to ObjectId

", - "summary": "

Casts to ObjectId

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "cast", - "string": "ObjectId.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "castForQuery", - "string": "ObjectId.prototype.castForQuery()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "turnOn", - "description": "auto generated ObjectId defaults" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Adds an auto-generated ObjectId default if turnOn is true.

", - "summary": "

Adds an auto-generated ObjectId default if turnOn is true.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "auto", - "string": "ObjectId.prototype.auto()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", - "ctx": { - "type": "function", - "name": "defaultId", - "string": "defaultId()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = ObjectId;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ObjectId", - "string": "module.exports" - } - } -] -### lib/schema/string.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

String SchemaType constructor.

", - "summary": "

String SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", - "ctx": { - "type": "function", - "name": "SchemaString", - "string": "SchemaString()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaString", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaString.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[args...]", - "description": "enumeration values" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds enumeration values and a coinciding validator.

\n\n

Example:

\n\n
var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
", - "summary": "

Adds enumeration values and a coinciding validator.

", - "body": "

Example:

\n\n
var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "enum", - "string": "SchemaString.prototype.enum()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a lowercase setter.

\n\n

Example:

\n\n
var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
", - "summary": "

Adds a lowercase setter.

", - "body": "

Example:

\n\n
var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v) {\n return v.toLowerCase();\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "lowercase", - "string": "SchemaString.prototype.lowercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds an uppercase setter.

\n\n

Example:

\n\n
var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
", - "summary": "

Adds an uppercase setter.

", - "body": "

Example:

\n\n
var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v) {\n return v.toUpperCase();\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "uppercase", - "string": "SchemaString.prototype.uppercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a trim setter.

\n\n

The string value will be trimmed when set.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
", - "summary": "

Adds a trim setter.

", - "body": "

The string value will be trimmed when set.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v) {\n return v.trim();\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "trim", - "string": "SchemaString.prototype.trim()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp" - ], - "name": "regExp", - "description": "regular expression to test against" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets a regexp validator.

\n\n

Any value that does not pass regExp.test(val) will fail validation.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
", - "summary": "

Sets a regexp validator.

", - "body": "

Any value that does not pass regExp.test(val) will fail validation.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "match", - "string": "SchemaString.prototype.match()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "null", - "undefined" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Check required

", - "summary": "

Check required

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "checkRequired", - "string": "SchemaString.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to String

", - "summary": "

Casts to String

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "cast", - "string": "SchemaString.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "castForQuery", - "string": "SchemaString.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaString;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaString", - "string": "module.exports" - } - } -] -### lib/schema.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "definition", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted after the schema is compiled into a `Model`." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Schema constructor.

\n\n

Example:

\n\n
var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
\n\n

Options:

\n\n
    \n
  • safe: bool - defaults to true.
  • \n
  • strict: bool - defaults to true
  • \n
  • capped: bool - defaults to false
  • \n
  • versionKey: bool - defaults to \"__v\"
  • \n
  • shardKey: bool - defaults to null
  • \n
  • autoIndex: bool - defaults to true
  • \n
  • _id: bool - defaults to true
  • \n
  • id: bool - defaults to true
  • \n
  • minimize: bool - controls document#toObject behavior when called manually - defaults to true
  • \n
\n\n

Note:

\n\n

When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

", - "summary": "

Schema constructor.

", - "body": "

Example:

\n\n
var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
\n\n

Options:

\n\n
    \n
  • safe: bool - defaults to true.
  • \n
  • strict: bool - defaults to true
  • \n
  • capped: bool - defaults to false
  • \n
  • versionKey: bool - defaults to \"__v\"
  • \n
  • shardKey: bool - defaults to null
  • \n
  • autoIndex: bool - defaults to true
  • \n
  • _id: bool - defaults to true
  • \n
  • id: bool - defaults to true
  • \n
  • minimize: bool - controls document#toObject behavior when called manually - defaults to true
  • \n
\n\n

Note:

\n\n

When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

" - }, - "isPrivate": false, - "ignore": false, - "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n // set options\n this.options = utils.options({\n safe: true\n , strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", - "ctx": { - "type": "function", - "name": "Schema", - "string": "Schema()" - } - }, - { - "tags": [], - "description": { - "full": "

Returns this documents _id cast to a string.

", - "summary": "

Returns this documents _id cast to a string.

", - "body": "" - }, - "ignore": true, - "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", - "ctx": { - "type": "function", - "name": "idGetter", - "string": "idGetter()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from EventEmitter.

", - "summary": "

Inherit from EventEmitter.

", - "body": "" - }, - "ignore": true, - "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Schema", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Schema.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "paths" - } - ], - "description": { - "full": "

Schema as flat paths

\n\n

Example:

\n\n
{\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
", - "summary": "

Schema as flat paths

", - "body": "

Example:

\n\n
{\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.paths;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "tree" - } - ], - "description": { - "full": "

Schema as a tree

\n\n

Example:

\n\n
{\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
", - "summary": "

Schema as a tree

", - "body": "

Example:

\n\n
{\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.tree;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "prefix", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds key path / schema type pairs to this schema.

\n\n

Example:

\n\n
var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
", - "summary": "

Adds key path / schema type pairs to this schema.

", - "body": "

Example:

\n\n
var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n }\n else\n this.path(prefix + i, obj[i]); // mixed type\n } else\n this.path(prefix + i, obj[i]);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "add", - "string": "Schema.prototype.add()" - } - }, - { - "tags": [], - "description": { - "full": "

Reserved document keys.

\n\n

Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

\n\n
 on, db, init, isNew, errors, schema, options, modelName, collection\n
", - "summary": "

Reserved document keys.

", - "body": "

Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

\n\n
 on, db, init, isNew, errors, schema, options, modelName, collection\n
" - }, - "ignore": false, - "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "reserved", - "value": "Object.create(null)", - "string": "Schema.reserved" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "constructor", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Gets/sets schema paths.

\n\n

Sets a path (if arity 2)
Gets a path (if arity 1)

\n\n

Example

\n\n
schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
", - "summary": "

Gets/sets schema paths.

", - "body": "

Sets a path (if arity 2)
Gets a path (if arity 1)

\n\n

Example

\n\n
schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(path) {\n if (!branch[path]) branch[path] = {};\n branch = branch[path];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "path", - "string": "Schema.prototype.path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "constructor" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Converts type arguments into Mongoose Types.

", - "summary": "

Converts type arguments into Mongoose Types.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", - "ctx": { - "type": "method", - "receiver": "Schema", - "name": "interpretAsType", - "string": "Schema.interpretAsType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback function" - }, - { - "type": "return", - "types": [ - "Schema" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Iterates the schemas paths similar to Array#forEach.

\n\n

The callback is passed the pathname and schemaType as arguments on each iteration.

", - "summary": "

Iterates the schemas paths similar to Array#forEach.

", - "body": "

The callback is passed the pathname and schemaType as arguments on each iteration.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "eachPath", - "string": "Schema.prototype.eachPath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - } - ], - "description": { - "full": "

Returns an Array of path strings that are required by this schema.

", - "summary": "

Returns an Array of path strings that are required by this schema.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "requiredPaths", - "string": "Schema.prototype.requiredPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns the pathType of path for this schema.

\n\n

Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

", - "summary": "

Returns the pathType of path for this schema.

", - "body": "

Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pathType", - "string": "Schema.prototype.pathType()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", - "ctx": { - "type": "function", - "name": "getPositionalPath", - "string": "getPositionalPath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the document method to call later" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Adds a method call to the queue.

", - "summary": "

Adds a method call to the queue.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "queue", - "string": "Schema.prototype.queue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a pre hook for the document.

\n\n

Example

\n\n
var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
", - "summary": "

Defines a pre hook for the document.

", - "body": "

Example

\n\n
var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pre", - "string": "Schema.prototype.pre()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "name of the method to hook" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a post hook for the document.

\n\n

Post hooks fire on the event emitted from document instances of Models compiled from this schema.

\n\n
var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
", - "summary": "

Defines a post hook for the document.

", - "body": "

Post hooks fire on the event emitted from document instances of Models compiled from this schema.

\n\n
var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "post", - "string": "Schema.prototype.post()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "plugin", - "description": "callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "" - }, - { - "type": "see", - "local": "plugins", - "visibility": "plugins" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Registers a plugin for this schema.

", - "summary": "

Registers a plugin for this schema.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "plugin", - "string": "Schema.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "method", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds an instance method to documents constructed from Models compiled from this schema.

\n\n

Example

\n\n
var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
\n\n

If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

\n\n
schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
", - "summary": "

Adds an instance method to documents constructed from Models compiled from this schema.

", - "body": "

Example

\n\n
var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
\n\n

If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

\n\n
schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "method", - "string": "Schema.prototype.method()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds static \"class\" methods to Models compiled from this schema.

\n\n

Example

\n\n
var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
\n\n

If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

", - "summary": "

Adds static \"class\" methods to Models compiled from this schema.

", - "body": "

Example

\n\n
var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
\n\n

If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "static", - "string": "Schema.prototype.static()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines an index (most likely compound) for this schema.

\n\n

Example

\n\n
schema.index({ first: 1, last: -1 })\n
", - "summary": "

Defines an index (most likely compound) for this schema.

", - "body": "

Example

\n\n
schema.index({ first: 1, last: -1 })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "index", - "string": "Schema.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "option name" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[value]", - "description": "if not passed, the current option value is returned" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets/gets a schema option.

", - "summary": "

Sets/gets a schema option.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "set", - "string": "Schema.prototype.set()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Compiles indexes from fields and schema-level indexes

", - "summary": "

Compiles indexes from fields and schema-level indexes

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "indexes", - "string": "Schema.prototype.indexes()" - } - }, - { - "tags": [], - "description": { - "full": "

Checks for indexes added to subdocs using Schema.index().
These indexes need their paths prefixed properly.

\n\n

schema._indexes = [ [indexObj, options], [indexObj, options] ..]

", - "summary": "

Checks for indexes added to subdocs using Schema.index().
These indexes need their paths prefixed properly.

", - "body": "

schema._indexes = [ [indexObj, options], [indexObj, options] ..]

" - }, - "ignore": true, - "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", - "ctx": { - "type": "function", - "name": "fixSubIndexPaths", - "string": "fixSubIndexPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

Creates a virtual type with the given name.

", - "summary": "

Creates a virtual type with the given name.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options)\n : {});\n return mem[part];\n }, this.tree);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtual", - "string": "Schema.prototype.virtual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

Returns the virtual type with the given name.

", - "summary": "

Returns the virtual type with the given name.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtualpath", - "string": "Schema.prototype.virtualpath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

These still haven't been fixed. Once they're working we'll make them public again.

", - "summary": "

These still haven't been fixed. Once they're working we'll make them public again.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "namedScope", - "string": "Schema.prototype.namedScope()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Schema", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The various Mongoose Schema Types.

\n\n

Example:

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
\n\n

Types:

\n\n
    \n
  • String
  • \n
  • Number
  • \n
  • Boolean | Bool
  • \n
  • Array
  • \n
  • Buffer
  • \n
  • Date
  • \n
  • ObjectId | Oid
  • \n
  • Mixed
  • \n
\n\n

Using this exposed access to the Mixed SchemaType, we can use them in our schema.

\n\n
var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
", - "summary": "

The various Mongoose Schema Types.

", - "body": "

Example:

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
\n\n

Types:

\n\n
    \n
  • String
  • \n
  • Number
  • \n
  • Boolean | Bool
  • \n
  • Array
  • \n
  • Buffer
  • \n
  • Date
  • \n
  • ObjectId | Oid
  • \n
  • Mixed
  • \n
\n\n

Using this exposed access to the Mixed SchemaType, we can use them in our schema.

\n\n
var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.Types = require('./schema/index');", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "Types", - "value": "require('./schema/index')", - "string": "Schema.Types" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" - } -] -### lib/schemadefault.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "property", - "string": "system.profile" - }, - { - "type": "receiver", - "string": "exports" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Default model for querying the system.profiles collection.

", - "summary": "

Default model for querying the system.profiles collection.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" - } -] -### lib/schematype.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');\nvar CastError = require('./errors/cast')\nvar ValidatorError = require('./errors/validator')", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[instance]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

SchemaType constructor

", - "summary": "

SchemaType constructor

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", - "ctx": { - "type": "function", - "name": "SchemaType", - "string": "SchemaType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function", - "any" - ], - "name": "val", - "description": "the default value" - }, - { - "type": "return", - "types": [ - "defaultValue" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets a default value for this SchemaType.

\n\n

Example:

\n\n
var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
\n\n

Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

\n\n

Example:

\n\n
// values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
", - "summary": "

Sets a default value for this SchemaType.

", - "body": "

Example:

\n\n
var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
\n\n

Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

\n\n

Example:

\n\n
// values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "default", - "string": "SchemaType.prototype.default()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "Boolean" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares the index options for this schematype.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
\n\n

NOTE:

\n\n

Indexes are created in the background by default. Specify background: false to override.

\n\n

Direction doesn't matter for single key indexes

", - "summary": "

Declares the index options for this schematype.

", - "body": "

Example:

\n\n
var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
\n\n

NOTE:

\n\n

Indexes are created in the background by default. Specify background: false to override.

\n\n

Direction doesn't matter for single key indexes

" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "index", - "string": "SchemaType.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares an unique index.

\n\n

Examples:

\n\n
var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
", - "summary": "

Declares an unique index.

", - "body": "

Examples:

\n\n
var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "unique", - "string": "SchemaType.prototype.unique()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares a sparse index.

\n\n

Examples:

\n\n
var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
", - "summary": "

Declares a sparse index.

", - "body": "

Examples:

\n\n
var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "sparse", - "string": "SchemaType.prototype.sparse()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "when", - "description": "" - }, - { - "type": "added", - "string": "3.0.0" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares a TTL index (rounded to the nearest second) for Date types only.

\n\n

This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
This index type is only compatible with Date types.

\n\n

Example:

\n\n
// expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
\n\n

expires utilizes the ms module from guille allowing us to use a friendlier syntax:

\n\n

Example:

\n\n
// expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
", - "summary": "

Declares a TTL index (rounded to the nearest second) for Date types only.

", - "body": "

This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
This index type is only compatible with Date types.

\n\n

Example:

\n\n
// expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
\n\n

expires utilizes the ms module from guille allowing us to use a friendlier syntax:

\n\n

Example:

\n\n
// expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "expires", - "string": "SchemaType.prototype.expires()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a setter to this schematype.

\n\n

Example:

\n\n
function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\nvar s = new Schema({ name: { type: String, set: capitalize })\n// or\nSchema.path('name').set(capitalize);\n
", - "summary": "

Adds a setter to this schematype.

", - "body": "

Example:

\n\n
function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\nvar s = new Schema({ name: { type: String, set: capitalize })\n// or\nSchema.path('name').set(capitalize);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "set", - "string": "SchemaType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a getter to this schematype.

\n\n

Example:

\n\n
function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\nvar s = new Schema({ born: { type: Date, get: dob })\n// or\nSchema.path('name').get(dob);\n
", - "summary": "

Adds a getter to this schematype.

", - "body": "

Example:

\n\n
function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\nvar s = new Schema({ born: { type: Date, get: dob })\n// or\nSchema.path('name').get(dob);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "get", - "string": "SchemaType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp", - "Function", - "Object" - ], - "name": "obj", - "description": "validator" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[error]", - "description": "optional error message" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds validator(s) for this document path.

\n\n

Validators must return Boolean. Returning false is interpreted as validation failure.

\n\n

Examples:

\n\n
function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
\n\n

Asynchronous validation:

\n\n

Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

\n\n
schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
\n\n

Validation occurs pre('save') or whenever you manually execute document#validate.

\n\n

If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

\n\n
var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
\n\n

If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

\n\n
// registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
", - "summary": "

Adds validator(s) for this document path.

", - "body": "

Validators must return Boolean. Returning false is interpreted as validation failure.

\n\n

Examples:

\n\n
function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
\n\n

Asynchronous validation:

\n\n

Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

\n\n
schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
\n\n

Validation occurs pre('save') or whenever you manually execute document#validate.

\n\n

If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

\n\n
var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
\n\n

If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

\n\n
// registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "validate", - "string": "SchemaType.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "required", - "description": "enable/disable the validator" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a required validator to this schematype.

\n\n

Example:

\n\n
var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
", - "summary": "

Adds a required validator to this schematype.

", - "body": "

Example:

\n\n
var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "required", - "string": "SchemaType.prototype.required()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope which callback are executed" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Gets the default value

", - "summary": "

Gets the default value

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "getDefault", - "string": "SchemaType.prototype.getDefault()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Applies setters

", - "summary": "

Applies setters

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applySetters", - "string": "SchemaType.prototype.applySetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Applies getters to a value

", - "summary": "

Applies getters to a value

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applyGetters", - "string": "SchemaType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets default select() behavior for this path.

\n\n

Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

\n\n

Example:

\n\n
T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
", - "summary": "

Sets default select() behavior for this path.

", - "body": "

Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

\n\n

Example:

\n\n
T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "select", - "string": "SchemaType.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Performs a validation of value using the validators declared for this SchemaType.

", - "summary": "

Performs a validation of value using the validators declared for this SchemaType.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "doValidate", - "string": "SchemaType.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Determines if value is a valid Reference.

", - "summary": "

Determines if value is a valid Reference.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", - "ctx": { - "type": "method", - "receiver": "SchemaType", - "name": "_isRef", - "string": "SchemaType._isRef()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = SchemaType", - "string": "module.exports" - } - } -] -### lib/statemachine.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

StateMachine represents a minimal interface for the
constructors it builds via StateMachine.ctor(...).

", - "summary": "

StateMachine represents a minimal interface for the
constructors it builds via StateMachine.ctor(...).

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", - "ctx": { - "type": "declaration", - "name": "StateMachine", - "value": "module.exports = exports = function StateMachine () {", - "string": "StateMachine" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "subclass constructor" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

StateMachine.ctor('state1', 'state2', ...)
A factory method for subclassing StateMachine.
The arguments are a list of states. For each state,
the constructor's prototype gets state transition
methods named after each state. These transition methods
place their path argument into the given state.

", - "summary": "

StateMachine.ctor('state1', 'state2', ...)
A factory method for subclassing StateMachine.
The arguments are a list of states. For each state,
the constructor's prototype gets state transition
methods named after each state. These transition methods
place their path argument into the given state.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", - "ctx": { - "type": "method", - "receiver": "StateMachine", - "name": "ctor", - "string": "StateMachine.ctor()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

This function is wrapped by the state change functions

\n\n
    \n
  • require(path)
  • \n
  • modify(path)
  • \n
  • init(path)
  • \n
", - "summary": "

This function is wrapped by the state change functions

", - "body": "
    \n
  • require(path)
  • \n
  • modify(path)
  • \n
  • init(path)
  • \n
" - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_changeState", - "string": "StateMachine.prototype._changeState()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "clear", - "string": "StateMachine.prototype.clear()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "that we want to check for." - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

Checks to see if at least one path is in the states passed in via arguments
e.g., this.some('required', 'inited')

", - "summary": "

Checks to see if at least one path is in the states passed in via arguments
e.g., this.some('required', 'inited')

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "some", - "string": "StateMachine.prototype.some()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "iterMethod", - "description": "is either 'forEach' or 'map'" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

This function builds the functions that get assigned to forEach and map,
since both of those methods share a lot of the same logic.

", - "summary": "

This function builds the functions that get assigned to forEach and map,
since both of those methods share a lot of the same logic.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_iter", - "string": "StateMachine.prototype._iter()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

Iterates over the paths that belong to one of the parameter states.

\n\n

The function profile can look like

\n\n

this.forEach(state1, fn); // iterates over all paths in state1
this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
this.forEach(fn); // iterates over all paths in all states

", - "summary": "

Iterates over the paths that belong to one of the parameter states.

", - "body": "

The function profile can look like

\n\n

this.forEach(state1, fn); // iterates over all paths in state1
this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
this.forEach(fn); // iterates over all paths in all states

" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "forEach", - "string": "StateMachine.prototype.forEach()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

Maps over the paths that belong to one of the parameter states.

\n\n

The function profile can look like

\n\n

this.forEach(state1, fn); // iterates over all paths in state1
this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
this.forEach(fn); // iterates over all paths in all states

", - "summary": "

Maps over the paths that belong to one of the parameter states.

", - "body": "

The function profile can look like

\n\n

this.forEach(state1, fn); // iterates over all paths in state1
this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
this.forEach(fn); // iterates over all paths in all states

" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "map", - "string": "StateMachine.prototype.map()" - } - } -] -### lib/types/array.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", - "ctx": { - "type": "declaration", - "name": "EmbeddedDocument", - "value": "require('./embedded')", - "string": "EmbeddedDocument" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Array" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

Mongoose Array constructor.

\n\n

NOTE:

\n\n

Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

", - "summary": "

Mongoose Array constructor.

", - "body": "

NOTE:

\n\n

Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseArray", - "string": "MongooseArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from Array

", - "summary": "

Inherit from Array

", - "body": "" - }, - "ignore": true, - "code": "MongooseArray.prototype = new Array;", - "ctx": { - "type": "property", - "receiver": "MongooseArray", - "name": "prototype", - "value": "new Array", - "string": "MongooseArray.prototype" - } - }, - { - "tags": [ - { - "type": "property", - "string": "_atomics" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Stores a queue of atomic operations to perform

", - "summary": "

Stores a queue of atomic operations to perform

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._atomics;" - }, - { - "tags": [ - { - "type": "property", - "string": "_parent" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Parent owner document

", - "summary": "

Parent owner document

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._parent;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "return", - "types": [ - "value" - ], - "description": "the casted value" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts a member based on this arrays schema.

", - "summary": "

Casts a member based on this arrays schema.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_cast", - "string": "MongooseArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "EmbeddedDocument" - ], - "name": "embeddedDoc", - "description": "the embedded doc that invoked this method on the Array" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "embeddedPath", - "description": "the path which changed in the embeddedDoc" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Marks this array as modified.

\n\n

If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

", - "summary": "

Marks this array as modified.

", - "body": "

If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._markModified = function (embeddedDoc, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n if (arguments.length) {\n // If an embedded doc bubbled up the change\n dirtyPath = [this._path, this.indexOf(embeddedDoc), embeddedPath].join('.');\n } else {\n dirtyPath = this._path;\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_markModified", - "string": "MongooseArray.prototype._markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "op", - "description": "operation" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Register an atomic operation with the parent.

", - "summary": "

Register an atomic operation with the parent.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n this._markModified();\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n if (this._atomics.$set) {\n return this;\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n this._markModified();\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n this._markModified();\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_registerAtomic", - "string": "MongooseArray.prototype._registerAtomic()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - } - ], - "description": { - "full": "

Returns the number of pending atomic operations to send to the db for this array.

", - "summary": "

Returns the number of pending atomic operations to send to the db for this array.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "hasAtomics", - "string": "MongooseArray.prototype.hasAtomics()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#push with proper change tracking.

", - "summary": "

Wraps Array#push with proper change tracking.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "push", - "string": "MongooseArray.prototype.push()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Pushes items to the array non-atomically.

\n\n

NOTE:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Pushes items to the array non-atomically.

", - "body": "

NOTE:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "nonAtomicPush", - "string": "MongooseArray.prototype.nonAtomicPush()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "$pop" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

Pops the array atomically at most one time per document save().

\n\n

NOTE:

\n\n

Calling this mulitple times on an array before saving sends the same command as calling it once.
This update is implemented using the MongoDB $pop method which enforces this restriction.

\n\n
 doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
", - "summary": "

Pops the array atomically at most one time per document save().

", - "body": "

NOTE:

\n\n

Calling this mulitple times on an array before saving sends the same command as calling it once.
This update is implemented using the MongoDB $pop method which enforces this restriction.

\n\n
 doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" - }, - { - "tags": [ - { - "type": "see", - "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", - "visibility": "MongooseArray#$pop" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#pop with proper change tracking.

\n\n

Note:

\n\n

marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#pop with proper change tracking.

", - "body": "

Note:

\n\n

marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pop", - "string": "MongooseArray.prototype.pop()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "method", - "string": "$shift" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

Atomically shifts the array at most one time per document save().

\n\n

NOTE:

\n\n

Calling this mulitple times on an array before saving sends the same command as calling it once.
This update is implemented using the MongoDB $pop method which enforces this restriction.

\n\n
 doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
", - "summary": "

Atomically shifts the array at most one time per document save().

", - "body": "

NOTE:

\n\n

Calling this mulitple times on an array before saving sends the same command as calling it once.
This update is implemented using the MongoDB $pop method which enforces this restriction.

\n\n
 doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#shift with proper change tracking.

\n\n

Example:

\n\n
doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
\n\n

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#shift with proper change tracking.

", - "body": "

Example:

\n\n
doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
\n\n

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "shift", - "string": "MongooseArray.prototype.shift()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "values to remove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Removes items from an array atomically

\n\n

Examples:

\n\n
doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
", - "summary": "

Removes items from an array atomically

", - "body": "

Examples:

\n\n
doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "remove", - "string": "MongooseArray.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Pulls items from the array atomically.

", - "summary": "

Pulls items from the array atomically.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pull", - "string": "MongooseArray.prototype.pull()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#splice with proper change tracking.

\n\n

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#splice with proper change tracking.

", - "body": "

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.splice = function () {\n if (arguments.length) {\n var ret = [].splice.apply(this, arguments);\n this._registerAtomic('$set', this);\n }\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "splice", - "string": "MongooseArray.prototype.splice()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#unshift with proper change tracking.

\n\n

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#unshift with proper change tracking.

", - "body": "

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n return this.length;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "unshift", - "string": "MongooseArray.prototype.unshift()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#sort with proper change tracking.

\n\n

NOTE:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#sort with proper change tracking.

", - "body": "

NOTE:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "sort", - "string": "MongooseArray.prototype.sort()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "the values that were added" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds values to the array if not already present.

\n\n

Example:

\n\n
console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
", - "summary": "

Adds values to the array if not already present.

", - "body": "

Example:

\n\n
console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "addToSet", - "string": "MongooseArray.prototype.addToSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns a native js Array.

", - "summary": "

Returns a native js Array.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "toObject", - "string": "MongooseArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "inspect", - "string": "MongooseArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the item to look for" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Return the index of obj or -1 if not found.

", - "summary": "

Return the index of obj or -1 if not found.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "indexOf", - "string": "MongooseArray.prototype.indexOf()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = MongooseArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = MongooseArray", - "string": "module.exports" - } - } -] -### lib/types/buffer.js -[ - { - "tags": [], - "description": { - "full": "

Access driver.

", - "summary": "

Access driver.

", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Binary = require(driver + '/binary');", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require(driver + '/binary')", - "string": "Binary" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "encode", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "offset", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Buffer" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

Mongoose Buffer constructor.

\n\n

Values always have to be passed to the constructor to initialize.

", - "summary": "

Mongoose Buffer constructor.

", - "body": "

Values always have to be passed to the constructor to initialize.

" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", - "ctx": { - "type": "function", - "name": "MongooseBuffer", - "string": "MongooseBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from Buffer.

", - "summary": "

Inherit from Buffer.

", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.prototype = new Buffer(0);", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "prototype", - "value": "new Buffer(0)", - "string": "MongooseBuffer.prototype" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "_parent" - } - ], - "description": { - "full": "

Parent owner document

", - "summary": "

Parent owner document

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._parent;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Marks this buffer as modified.

", - "summary": "

Marks this buffer as modified.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "_markModified", - "string": "MongooseBuffer.prototype._markModified()" - } - }, - { - "tags": [], - "description": { - "full": "

Writes the buffer.

", - "summary": "

Writes the buffer.

", - "body": "" - }, - "ignore": false, - "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "write", - "string": "MongooseBuffer.prototype.write()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "MongooseBuffer" - ], - "description": "" - }, - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "target", - "description": "" - } - ], - "description": { - "full": "

Copies the buffer.

\n\n

Note:

\n\n

Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

", - "summary": "

Copies the buffer.

", - "body": "

Note:

\n\n

Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "copy", - "string": "MongooseBuffer.prototype.copy()" - } - }, - { - "tags": [], - "description": { - "full": "

Compile other Buffer methods marking this buffer as modified.

", - "summary": "

Compile other Buffer methods marking this buffer as modified.

", - "body": "" - }, - "ignore": true, - "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://bsonspec.org/#/specification", - "visibility": "http://bsonspec.org/#/specification" - }, - { - "type": "param", - "types": [ - "Hex" - ], - "name": "[subtype]", - "description": "" - }, - { - "type": "return", - "types": [ - "Binary" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Converts this buffer to its Binary type representation.

\n\n

SubTypes:

\n\n
    \n
  • 0x00: Binary/Generic
  • \n
  • 0x01: Function
  • \n
  • 0x02: Binary (Deprecated, 0x00 is new default)
  • \n
  • 0x03: UUID
  • \n
  • 0x04: MD5
  • \n
  • 0x80: User Defined
  • \n
", - "summary": "

Converts this buffer to its Binary type representation.

", - "body": "

SubTypes:

\n\n
    \n
  • 0x00: Binary/Generic
  • \n
  • 0x01: Function
  • \n
  • 0x02: Binary (Deprecated, 0x00 is new default)
  • \n
  • 0x03: UUID
  • \n
  • 0x04: MD5
  • \n
  • 0x80: User Defined
  • \n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "toObject", - "string": "MongooseBuffer.prototype.toObject()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "Binary", - "value": "Binary", - "string": "MongooseBuffer.Binary" - } - } -] -### lib/types/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", - "ctx": { - "type": "declaration", - "name": "MongooseArray", - "value": "require('./array')", - "string": "MongooseArray" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to this array" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "MongooseDocumentArray" - ], - "description": "" - }, - { - "type": "inherits", - "string": "MongooseArray" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

DocumentArray constructor

", - "summary": "

DocumentArray constructor

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseDocumentArray", - "string": "MongooseDocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseArray

", - "summary": "

Inherits from MongooseArray

", - "body": "" - }, - "ignore": true, - "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseDocumentArray", - "name": "__proto__", - "value": "MongooseArray.prototype", - "string": "MongooseDocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Overrides MongooseArray#cast

", - "summary": "

Overrides MongooseArray#cast

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype._cast = function (value) {\n var doc = new this._schema.casterConstructor(value, this);\n return doc;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "_cast", - "string": "MongooseDocumentArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "EmbeddedDocument", - "null" - ], - "description": "the subdocuent or null if not found." - }, - { - "type": "param", - "types": [ - "ObjectId", - "String", - "Number", - "Buffer" - ], - "name": "id", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Searches array items for the first document with a matching id.

\n\n

Example:

\n\n
var embeddedDoc = m.array.id(some_id);\n
", - "summary": "

Searches array items for the first document with a matching id.

", - "body": "

Example:

\n\n
var embeddedDoc = m.array.id(some_id);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "id", - "string": "MongooseDocumentArray.prototype.id()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns a native js Array of plain js objects

\n\n

NOTE:

\n\n

Each sub-document is converted to a plain object by calling its #toObject method.

", - "summary": "

Returns a native js Array of plain js objects

", - "body": "

NOTE:

\n\n

Each sub-document is converted to a plain object by calling its #toObject method.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "toObject", - "string": "MongooseDocumentArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "inspect", - "string": "MongooseDocumentArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the value to cast to this arrays SubDocument schema" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Creates a subdocument casted to this schema.

\n\n

This is the same subdocument constructor used for casting.

", - "summary": "

Creates a subdocument casted to this schema.

", - "body": "

This is the same subdocument constructor used for casting.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "create", - "string": "MongooseDocumentArray.prototype.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Creates a fn that notifies all child docs of event.

", - "summary": "

Creates a fn that notifies all child docs of event.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n self[i].emit(event, val);\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "notify", - "string": "MongooseDocumentArray.prototype.notify()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseDocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseDocumentArray", - "string": "module.exports" - } - } -] -### lib/types/embedded.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Document = require('../document')\n , inspect = require('util').inspect;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('../document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "js object returned from the db" - }, - { - "type": "param", - "types": [ - "MongooseDocumentArray" - ], - "name": "parentArr", - "description": "the parent array of this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "skipId", - "description": "" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

EmbeddedDocument constructor.

", - "summary": "

EmbeddedDocument constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function EmbeddedDocument (obj, parentArr, skipId) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, undefined, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", - "ctx": { - "type": "function", - "name": "EmbeddedDocument", - "string": "EmbeddedDocument()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from Document

", - "summary": "

Inherit from Document

", - "body": "" - }, - "ignore": true, - "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "EmbeddedDocument", - "name": "__proto__", - "value": "Document.prototype", - "string": "EmbeddedDocument.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path which changed" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Marks the embedded doc modified.

\n\n

Example:

\n\n
var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
", - "summary": "

Marks the embedded doc modified.

", - "body": "

Example:

\n\n
var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "markModified", - "string": "EmbeddedDocument.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "return", - "types": [ - "EmbeddedDocument" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Used as a stub for hooks.js

\n\n

NOTE:

\n\n

This is a no-op. Does not actually save the doc to the db.

", - "summary": "

Used as a stub for hooks.js

", - "body": "

NOTE:

\n\n

This is a no-op. Does not actually save the doc to the db.

" - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "save", - "string": "EmbeddedDocument.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Removes the subdocument from its parent array.

", - "summary": "

Removes the subdocument from its parent array.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "remove", - "string": "EmbeddedDocument.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Override #update method of parent documents.

", - "summary": "

Override #update method of parent documents.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "update", - "string": "EmbeddedDocument.prototype.update()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "inspect", - "string": "EmbeddedDocument.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "error which states the reason `path` was invalid" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Marks a path as invalid, causing validation to fail.

", - "summary": "

Marks a path as invalid, causing validation to fail.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "invalidate", - "string": "EmbeddedDocument.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

Returns the top level document of this sub-document.

", - "summary": "

Returns the top level document of this sub-document.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "ownerDocument", - "string": "EmbeddedDocument.prototype.ownerDocument()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

Returns the top level document of this sub-document.

", - "summary": "

Returns the top level document of this sub-document.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", - "ctx": { - "type": "function", - "name": "ownerDocument", - "string": "ownerDocument()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns this sub-documents parent document.

", - "summary": "

Returns this sub-documents parent document.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parent", - "string": "EmbeddedDocument.prototype.parent()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns this sub-documents parent array.

", - "summary": "

Returns this sub-documents parent array.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parentArray", - "string": "EmbeddedDocument.prototype.parentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = EmbeddedDocument;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "EmbeddedDocument", - "string": "module.exports" - } - } -] -### lib/types/index.js -[ - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "Array", - "value": "require('./array')", - "string": "exports.Array" - } - } -] -### lib/types/objectid.js -[ - { - "tags": [], - "description": { - "full": "

Access driver.

", - "summary": "

Access driver.

", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [ - { - "type": "constructor", - "string": "ObjectId" - } - ], - "description": { - "full": "

ObjectId type constructor

\n\n

Example

\n\n
var id = new mongoose.Types.ObjectId;\n
", - "summary": "

ObjectId type constructor

", - "body": "

Example

\n\n
var id = new mongoose.Types.ObjectId;\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require(driver + '/objectid')", - "string": "ObjectId" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "str", - "description": "" - }, - { - "type": "static", - "string": "fromString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "ObjectId" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Creates an ObjectId from str

", - "summary": "

Creates an ObjectId from str

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.fromString;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId" - ], - "name": "oid", - "description": "ObjectId instance" - }, - { - "type": "static", - "string": "toString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Converts oid to a string.

", - "summary": "

Converts oid to a string.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.toString;" - } -] -### lib/utils.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , MongooseBuffer\n , MongooseArray\n , Document", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "a model name" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "a collection name" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Produces a collection name from model name.

", - "summary": "

Produces a collection name from model name.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "toCollectionName", - "string": "exports.toCollectionName()" - } - }, - { - "tags": [], - "description": { - "full": "

Pluralization rules.

\n\n

These rules are applied while processing the argument to toCollectionName.

", - "summary": "

Pluralization rules.

", - "body": "

These rules are applied while processing the argument to toCollectionName.

" - }, - "ignore": false, - "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "pluralization", - "value": "[", - "string": "exports.pluralization" - } - }, - { - "tags": [], - "description": { - "full": "

Uncountable words.

\n\n

These words are applied while processing the argument to toCollectionName.

", - "summary": "

Uncountable words.

", - "body": "

These words are applied while processing the argument to toCollectionName.

" - }, - "ignore": false, - "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news'\n];\nvar uncountables = exports.uncountables;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "uncountables", - "value": "[", - "string": "exports.uncountables" - } - }, - { - "tags": [ - { - "type": "author", - "string": "TJ Holowaychuk (extracted from _ext.js_)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "string", - "description": "to pluralize" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Pluralize function.

", - "summary": "

Pluralize function.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", - "ctx": { - "type": "function", - "name": "pluralize", - "string": "pluralize()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "listener", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Add once to EventEmitter if absent

", - "summary": "

Add once to EventEmitter if absent

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", - "ctx": { - "type": "declaration", - "name": "Events", - "value": "EventEmitter", - "string": "Events" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from EventEmitter.

", - "summary": "

Inherit from EventEmitter.

", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Events", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Events.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

Add once.

", - "summary": "

Add once.

", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", - "ctx": { - "type": "method", - "constructor": "Events", - "name": "once", - "string": "Events.prototype.once()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "a", - "description": "a value to compare to `b`" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "b", - "description": "a value to compare to `a`" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Determines if a and b are deep equal.

\n\n

Modified from node/lib/assert.js

", - "summary": "

Determines if a and b are deep equal.

", - "body": "

Modified from node/lib/assert.js

" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "deepEqual", - "string": "exports.deepEqual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the object to clone" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the cloned object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Object clone with Mongoose natives support.

\n\n

Creates a minimal data Object.
It does not clone empty Arrays, empty Objects, and undefined values.
This makes the data payload sent to MongoDB as minimal as possible.

", - "summary": "

Object clone with Mongoose natives support.

", - "body": "

Creates a minimal data Object.
It does not clone empty Arrays, empty Objects, and undefined values.
This makes the data payload sent to MongoDB as minimal as possible.

" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId) {\n return new ObjectId(obj.id);\n }\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "clone", - "string": "exports.clone()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", - "ctx": { - "type": "function", - "name": "cloneObject", - "string": "cloneObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "defaults", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the merged object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Copies and merges options with defaults.

", - "summary": "

Copies and merges options with defaults.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "options", - "string": "exports.options()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Generates a random string

", - "summary": "

Generates a random string

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "random", - "string": "exports.random()" - } - }, - { - "tags": [], - "description": { - "full": "

TODO remove

", - "summary": "

TODO remove

", - "body": "" - }, - "ignore": true, - "code": "exports.inGroupsOf = function inGroupsOf (card, arr, fn) {\n var group = [];\n for (var i = 0, l = arr.length; i < l; i++) {\n if (i && i % card === 0) {\n fn.apply(this, group);\n group.length = 0;\n }\n group.push(arr[i]);\n }\n fn.apply(this, group);\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "inGroupsOf", - "string": "exports.inGroupsOf()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "to", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "from", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Merges from into to without overwriting existing properties.

", - "summary": "

Merges from into to without overwriting existing properties.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n merge(to[key], from[key]);\n }\n }\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "merge", - "string": "exports.merge()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

A faster Array.prototype.slice.call(arguments) alternative

", - "summary": "

A faster Array.prototype.slice.call(arguments) alternative

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.args = function (args, slice, sliceEnd) {\n var ret = [];\n var start = slice || 0;\n var end = 3 === arguments.length\n ? sliceEnd\n : args.length;\n\n for (var i = start; i < end; ++i) {\n ret[i - start] = args[i];\n }\n\n return ret;\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "args", - "string": "exports.args()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

process.nextTick helper.

\n\n

Wraps callback in a try/catch + nextTick.

\n\n

node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

", - "summary": "

process.nextTick helper.

", - "body": "

Wraps callback in a try/catch + nextTick.

\n\n

node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "tick", - "string": "exports.tick()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "v", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns if v is a mongoose object that has a toObject() method we can use.

\n\n

This is for compatibility with libs like Date.js which do foolish things to Natives.

", - "summary": "

Returns if v is a mongoose object that has a toObject() method we can use.

", - "body": "

This is for compatibility with libs like Date.js which do foolish things to Natives.

" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isMongooseObject", - "string": "exports.isMongooseObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "object", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

", - "summary": "

Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expiresAfterSeconds = when;\n delete object.expires;\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "expires", - "string": "exports.expires()" - } - } -] -### lib/virtualtype.js -[ - { - "tags": [ - { - "type": "parma", - "string": "{Object} options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

VirtualType constructor

\n\n

This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

\n\n

Example:

\n\n
var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
", - "summary": "

VirtualType constructor

", - "body": "

This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

\n\n

Example:

\n\n
var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "function VirtualType (options) {\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", - "ctx": { - "type": "function", - "name": "VirtualType", - "string": "VirtualType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a getter.

\n\n

Example:

\n\n
var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
", - "summary": "

Defines a getter.

", - "body": "

Example:

\n\n
var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "get", - "string": "VirtualType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a setter.

\n\n

Example:

\n\n
var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
", - "summary": "

Defines a setter.

", - "body": "

Example:

\n\n
var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "set", - "string": "VirtualType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all getters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Applies getters to value using optional scope.

", - "summary": "

Applies getters to value using optional scope.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--){\n v = this.getters[l].call(scope, v);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applyGetters", - "string": "VirtualType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all setters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Applies setters to value using optional scope.

", - "summary": "

Applies setters to value using optional scope.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--){\n this.setters[l].call(scope, v);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applySetters", - "string": "VirtualType.prototype.applySetters()" - } - }, - { - "tags": [], - "description": { - "full": "

exports

", - "summary": "

exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = VirtualType;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "VirtualType", - "string": "module.exports" - } - } -] diff --git a/docs/3.0.x/docs/source/api.js b/docs/3.0.x/docs/source/api.js deleted file mode 100644 index 8fd87f0035b..00000000000 --- a/docs/3.0.x/docs/source/api.js +++ /dev/null @@ -1,220 +0,0 @@ -/*! - * Module dependencies - */ - -var fs = require('fs'); -var link = require('../helpers/linktype'); -var hl = require('highlight.js') -var md = require('markdown') - -module.exports = { - docs: [] - , github: 'https://github.com/LearnBoost/mongoose/tree/' - , title: 'API docs' -} - -var out = module.exports.docs; - -var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); -parse(docs); -order(out); - -function parse (docs) { - docs.split(/^### /gm).forEach(function (chunk) { - if (!(chunk = chunk.trim())) return; - - chunk = chunk.split(/^([^\n]+)\n/); - - var title = chunk[1]; - - if (!title || !(title = title.trim())) - throw new Error('missing title'); - - title = title.replace(/^lib\//, ''); - - var json = JSON.parse(chunk[2]); - - var props = []; - var methods = []; - var statics = []; - var constructor = null; - - json.forEach(function (comment) { - if (comment.description) - highlight(comment.description); - - var prop = false; - comment.params = []; - comment.see = []; - - var i = comment.tags.length; - while (i--) { - var tag = comment.tags[i]; - switch (tag.type) { - case 'property': - prop = true; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - props.unshift(comment); - break; - case 'method': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'method'; - comment.code = ''; - break; - case 'memberOf': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.constructor = tag.parent; - break; - case 'static': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - comment.ctx.type = 'method'; - break; - case 'receiver': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.receiver = tag.string; - break; - case 'constructor': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'function'; - comment.code = ''; - break; - case 'inherits': - if (/http/.test(tag.string)) { - var result = tag.string.split(' '); - var href = result.pop(); - var title = result.join(' '); - comment.inherits = '' + title + ''; - } else { - comment.inherits = link(tag.string); - } - comment.tags.splice(i, 1); - break; - case 'param': - comment.params.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'return': - comment.return = tag; - comment.tags.splice(i, 1); - break; - case 'see': - if (tag.local) { - var parts = tag.local.split(' '); - if (1 === parts.length) { - tag.url = link.type(parts[0]); - tag.title = parts[0]; - } else { - tag.url = parts.pop(); - tag.title = parts.join(' '); - } - } - comment.see.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'event': - var str = tag.string.replace(/\\n/g, '\n'); - tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); - comment.events || (comment.events = []); - comment.events.unshift(tag); - comment.tags.splice(i, 1); - } - } - - if (!prop) { - methods.push(comment); - } - }); - - methods = methods.filter(ignored); - props = props.filter(ignored); - - function ignored (method) { - if (method.ignore) return false; - return true; - } - - if (0 === methods.length + props.length) return; - - // add constructor to properties too - methods.some(function (method) { - if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { - props.forEach(function (prop) { - prop.ctx.constructor = method.ctx.constructor; - }); - return true; - } - return false; - }); - - var len = methods.length; - while (len--) { - method = methods[len]; - if (method.ctx && method.ctx.receiver) { - var stat = methods.splice(len, 1)[0]; - statics.unshift(stat); - } - } - - out.push({ - title: title - , methods: methods - , props: props - , statics: statics - , hasPublic: hasPublic(methods, props, statics) - }); - }); -} - -function hasPublic () { - for (var i = 0; i < arguments.length; ++i) { - var arr = arguments[i]; - for (var j = 0; j < arr.length; ++j) { - var item = arr[j]; - if (!item.ignore && !item.isPrivate) return true; - } - } - return false; -} - -// add "class='language'" to our
 elements
-function highlight (o) {
-  o.full = fix(o.full);
-  o.summary = fix(o.summary);
-  o.body = fix(o.body);
-}
-
-function fix (str) {
-  return str.replace(/(
)([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
-
-    // parse out the ```language
-    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
-
-    if ('js' == code[1] || !code[1]) {
-      code[1] = 'javascript';
-    }
-
-    return $1
-          + hl.highlight(code[1], code[2]).value.trim()
-          + $3;
-  });
-}
-
-function order (docs) {
-  // want index first
-  for (var i = 0; i < docs.length; ++i) {
-    if ('index.js' == docs[i].title) {
-      docs.unshift(docs.splice(i, 1)[0]);
-    }
-  }
-}
diff --git a/docs/3.0.x/docs/source/home.js b/docs/3.0.x/docs/source/home.js
deleted file mode 100644
index 557f27b966b..00000000000
--- a/docs/3.0.x/docs/source/home.js
+++ /dev/null
@@ -1,19 +0,0 @@
-
-var fs = require('fs')
-var package = require('./../../package.json')
-var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
-
-var imgs = [];
-
-images.forEach(function (line) {
-  line = line.trim();
-  if (!line) return;
-  line = line.split('|');
-  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
-});
-
-module.exports = {
-    package: package
-  , images: imgs
-  , title: 'ODM'
-}
diff --git a/docs/3.0.x/docs/source/index.js b/docs/3.0.x/docs/source/index.js
deleted file mode 100644
index d54229720a1..00000000000
--- a/docs/3.0.x/docs/source/index.js
+++ /dev/null
@@ -1,18 +0,0 @@
-
-exports['index.jade'] = require('./home')
-exports['docs/api.jade'] = require('./api')
-exports['docs/index.jade'] = { title: 'Getting Started' }
-exports['docs/prior.jade'] = require('./prior')
-exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
-exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
-exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
-exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
-exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
-exports['docs/models.jade'] = { guide: true, title: 'Models' }
-exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
-exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
-exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
-exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
-exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
-exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
-exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
diff --git a/docs/3.0.x/docs/source/prior.js b/docs/3.0.x/docs/source/prior.js
deleted file mode 100644
index 2e03811d215..00000000000
--- a/docs/3.0.x/docs/source/prior.js
+++ /dev/null
@@ -1,13 +0,0 @@
-var fs = require('fs')
-var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
-releases = releases.split('\n').filter(Boolean);
-
-module.exports = exports = {
-    title: ''
-  , releases: releases.map(function (version) {
-      return {
-          url: version + '/'
-        , version: version
-      }
-    })
-}
diff --git a/docs/3.0.x/docs/subdocs.html b/docs/3.0.x/docs/subdocs.html
deleted file mode 100644
index 183675028fe..00000000000
--- a/docs/3.0.x/docs/subdocs.html
+++ /dev/null
@@ -1,48 +0,0 @@
-Mongoose SubDocuments v3.0.3Fork me on GitHub

Sub Docs

Sub-documents are docs with schemas of their own which are elements of a parents document array:

var childSchema = new Schema({ name: 'string' });
-
-var parentSchema = new Schema({
-  children: [childSchema]
-})
-

Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

var Parent = db.model('Parent', parentSchema);
-var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
-parent.children[0].name = 'Matthew';
-parent.save(callback);
-

If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

childSchema.pre('save', function (next) {
-  if ('invalid' == this.name) return next(new Error('#sadpanda'));
-  next();
-});
-
-var parent = new Parent({ children: [{ name: 'invalid' }] });
-parent.save(function (err) {
-  console.log(err.message) // #sadpanda
-})
-

Finding a sub-document

Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

var doc = parent.children.id(id);
-

Adding sub-docs

MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

var Parent = db.model('Parent');
-var parent = new Parent;
-
-// create a comment
-post.children.push({ name: 'Liesl' });
-var doc = post.children[0];
-console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
-doc.isNew; // true
-
-post.save(function (err) {
-  if (err) return handleError(err)
-  console.log('Success!');
-});

Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

var newdoc = post.children.create({ name: 'Aaron' });
-

Removing docs

Each sub-document has it's own remove method.

var doc = parent.children.id(id).remove();
-parent.save(function (err) {
-  if (err) return handleError(err);
-  console.log('the sub-doc was removed')
-});
-

Alternate declaration syntax

New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

var parentSchema = new Schema({
-  children: [{ name: 'string' }]
-})
diff --git a/docs/3.0.x/docs/subdocs.jade b/docs/3.0.x/docs/subdocs.jade deleted file mode 100644 index a3988b34993..00000000000 --- a/docs/3.0.x/docs/subdocs.jade +++ /dev/null @@ -1,80 +0,0 @@ -extends layout - -block content - h2 Sub Docs - :markdown - [Sub-documents](./api.html#types-embedded-js) are docs with schemas of their own which are elements of a parents document array: - :js - var childSchema = new Schema({ name: 'string' }); - - var parentSchema = new Schema({ - children: [childSchema] - }) - - :markdown - Sub-documents enjoy all the same features as normal [documents](./api.html#document-js). The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved. - :js - var Parent = db.model('Parent', parentSchema); - var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) - parent.children[0].name = 'Matthew'; - parent.save(callback); - - :markdown - If an error occurs in a sub-documents' middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap! - - :js - childSchema.pre('save', function (next) { - if ('invalid' == this.name) return next(new Error('#sadpanda')); - next(); - }); - - var parent = new Parent({ children: [{ name: 'invalid' }] }); - parent.save(function (err) { - console.log(err.message) // #sadpanda - }) - - h3 Finding a sub-document - :markdown - Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. - :js - var doc = parent.children.id(id); - - h3 Adding sub-docs - :markdown - MongooseArray methods such as [push](./api.html#types_array_MongooseArray-push), [unshift](./api.html#types_array_MongooseArray-unshift), [addToSet](./api.html#types_array_MongooseArray-addToSet), and others cast arguments to their proper types transparently: - :js - var Parent = db.model('Parent'); - var parent = new Parent; - - // create a comment - post.children.push({ name: 'Liesl' }); - var doc = post.children[0]; - console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' } - doc.isNew; // true - - post.save(function (err) { - if (err) return handleError(err) - console.log('Success!'); - }); - :markdown - Sub-docs may also be created without adding them to the array by using the [create](./api.html#types_documentarray_MongooseDocumentArray-create) method of MongooseArrays. - :js - var newdoc = post.children.create({ name: 'Aaron' }); - - h3 Removing docs - :markdown - Each sub-document has it's own [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. - :js - var doc = parent.children.id(id).remove(); - parent.save(function (err) { - if (err) return handleError(err); - console.log('the sub-doc was removed') - }); - - h4#altsyntax Alternate declaration syntax - :markdown - _New in v3_ If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal: - :js - var parentSchema = new Schema({ - children: [{ name: 'string' }] - }) diff --git a/docs/3.0.x/docs/validation.html b/docs/3.0.x/docs/validation.html deleted file mode 100644 index 4f500d9dd37..00000000000 --- a/docs/3.0.x/docs/validation.html +++ /dev/null @@ -1,36 +0,0 @@ -Mongoose Validation v3.0.3Fork me on GitHub

Validation

Before we get into the specifics of validation syntax, please keep the following rules in mind:

- -
  • Validation is defined in the SchemaType
  • Validation is an internal piece of middleware
  • Validation occurs when a document attempts to be saved, after defaults have been applied
  • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
  • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

Built in validators

Mongoose has several built in validators.

- -

Custom validators

Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

Validation errors

Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

var toySchema = new Schema({
-  color: String,
-  name: String
-});
-
-var Toy = db.model('Toy', toySchema);
-
-Toy.schema.path('color').validate(function (value) {
-  return /blue|green|white|red|orange|periwinkel/i.test(value);
-}, 'Invalid color');
-
-var toy = new Toy({ color: 'grease'});
-
-toy.save(function (err) {
-  // err.errors.color is a ValidatorError object
-  
-  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
-  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
-  console.log(err.errors.color.type) // prints "Invalid color"
-  console.log(err.errors.color.path) // prints "color"
-  console.log(err.name) // prints "ValidationError"
-  console.log(err.message) // prints "Validation failed"
-});
-

After a validation error, the document will also have the same errors property available:

toy.errors.color.message === err.errors.color.message
diff --git a/docs/3.0.x/docs/validation.jade b/docs/3.0.x/docs/validation.jade deleted file mode 100644 index a085ea49df7..00000000000 --- a/docs/3.0.x/docs/validation.jade +++ /dev/null @@ -1,54 +0,0 @@ -extends layout - -block content - h2 Validation - :markdown - Before we get into the specifics of validation syntax, please keep the following rules in mind: - - - Validation is defined in the [SchemaType](./schematypes.html) - - Validation is an internal piece of [middleware](./middleware.html) - - Validation occurs when a document attempts to be [saved](./api.html#model_Model-save), after defaults have been applied - - Validation is asynchronously recursive: when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed. If an error happens, your Model#save callback receives it - - Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, `"min"` is the identifier for the error triggered when a number doesn't meet the [minimum value](./api.html#schema_number_SchemaNumber-min). The path and value that triggered the error can be accessed in the `ValidationError` object - h3 Built in validators - :markdown - Mongoose has several built in validators. - - - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. - - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. - - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum) and [match](./api.html#schema_string_SchemaString-match) validators. - h3 Custom validators - :markdown - Custom validation is declared by passing a validation `function` and an error type to your `SchemaType`s validate method. Read the [API](./api.html#schematype_SchemaType-validate) docs for details on custom validators, async validators, and more. - h3 Validation errors - :markdown - Errors returned after failed validation contain an `errors` object holding the actual `ValidatorErrors`. Each [ValidatorError](./api.html#errors-validation-js) has a `type` and `path` property providing us with a little more error handling flexibility. - :js - var toySchema = new Schema({ - color: String, - name: String - }); - - var Toy = db.model('Toy', toySchema); - - Toy.schema.path('color').validate(function (value) { - return /blue|green|white|red|orange|periwinkel/i.test(value); - }, 'Invalid color'); - - var toy = new Toy({ color: 'grease'}); - - toy.save(function (err) { - // err.errors.color is a ValidatorError object - - console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color' - console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color' - console.log(err.errors.color.type) // prints "Invalid color" - console.log(err.errors.color.path) // prints "color" - console.log(err.name) // prints "ValidationError" - console.log(err.message) // prints "Validation failed" - }); - - :markdown - After a validation error, the document will also have the same `errors` property available: - :js - toy.errors.color.message === err.errors.color.message diff --git a/docs/3.0.x/index.html b/docs/3.0.x/index.html deleted file mode 100644 index 28c55db30f1..00000000000 --- a/docs/3.0.x/index.html +++ /dev/null @@ -1,238 +0,0 @@ -Mongoose ODM v3.0.3Fork me on GitHub

Elegant MongoDB object modeling for Node.js

Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

var mongoose = require('mongoose');
-var db = mongoose.createConnection('localhost', 'test');
-
-var schema = mongoose.Schema({ name: 'string' });
-var Cat = db.model('Cat', schema);
-
-var kitty = new Cat({ name: 'Zildjian' });
-kitty.save(function (err) {
-  if (err) // ...
-  res.end('meow');
-});

Installation

$ npm install mongoose

Getting Started

Support

diff --git a/docs/3.0.x/static.js b/docs/3.0.x/static.js deleted file mode 100644 index fc0e722dd4e..00000000000 --- a/docs/3.0.x/static.js +++ /dev/null @@ -1,17 +0,0 @@ - -var static = require('node-static'); -var server = new static.Server('.', { cache: 0 }); - -require('http').createServer(function (req, res) { - req.on('end', function () { - server.serve(req, res, function (err) { - if (err) { - console.error(err, req.url); - res.writeHead(err.status, err.headers); - res.end(); - } - }); - }); -}).listen(8088); - -console.error('now listening on localhost:8088'); diff --git a/docs/3.1.x/docs/api.html b/docs/3.1.x/docs/api.html deleted file mode 100644 index 61cc402fddb..00000000000 --- a/docs/3.1.x/docs/api.html +++ /dev/null @@ -1,6720 +0,0 @@ -Mongoose API v3.1.2Fork me on GitHub
  • index.js

    Mongoose()

    Mongoose constructor.

    show code
    function Mongoose () {
    -  this.connections = [];
    -  this.plugins = [];
    -  this.models = {};
    -  this.modelSchemas = {};
    -  this.options = {};
    -  this.createConnection(); // default connection
    -};

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.


    Mongoose#set(key, value)

    Sets mongoose options

    show code
    Mongoose.prototype.set = function (key, value) {
    -  if (arguments.length == 1)
    -    return this.options[key];
    -  this.options[key] = value;
    -  return this;
    -};

    Parameters:

    Example:

    - -
    mongoose.set('test', value) // sets the 'test' option to `value`

    Mongoose#get(key)

    Gets mongoose options

    Parameters:

    Example:

    - -
    mongoose.get('test') // returns the 'test' value

    Mongoose#createConnection([uri])

    Creates a Connection instance.

    show code
    Mongoose.prototype.createConnection = function () {
    -  var conn = new Connection(this);
    -  this.connections.push(conn);
    -
    -  if (arguments.length) {
    -    if (rgxReplSet.test(arguments[0])) {
    -      conn.openSet.apply(conn, arguments);
    -    } else {
    -      conn.open.apply(conn, arguments);
    -    }
    -  }
    -
    -  return conn;
    -};

    Parameters:

    • [uri] <String> a mongodb:// URI

    Returns:

    Example:

    - -
    // with mongodb:// URI
    -db = mongoose.createConnection('mongodb://localhost:port/database');
    -
    -// replica sets
    -db = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
    -
    -// with [host, database_name[, port] signature
    -db = mongoose.createConnection('localhost', 'database', port)
    -
    -// initialize now, connect later
    -db = mongoose.createConnection();
    -db.open('localhost', 'database', port);

    Mongoose#connect()

    Opens the default mongoose connection.

    show code
    Mongoose.prototype.connect = function () {
    -  var conn = this.connection;
    -
    -  if (rgxReplSet.test(arguments[0])) {
    -    conn.openSet.apply(conn, arguments);
    -  } else {
    -    conn.open.apply(conn, arguments);
    -  }
    -
    -  return this;
    -};

    Returns:

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


    Mongoose#disconnect([fn])

    Disconnects all connections.

    show code
    Mongoose.prototype.disconnect = function (fn) {
    -  var count = this.connections.length
    -    , error
    -
    -  this.connections.forEach(function(conn){
    -    conn.close(function(err){
    -      if (error) return;
    -
    -      if (err) {
    -        error = err;
    -        if (fn) return fn(err);
    -        throw err;
    -      }
    -
    -      if (fn)
    -        --count || fn();
    -    });
    -  });
    -  return this;
    -};

    Parameters:

    • [fn] <Function> called after all connection close.

    Returns:


    Mongoose#model(name, [schema], [collection], [skipInit])

    Defines a model or retrieves it.

    show code
    Mongoose.prototype.model = function (name, schema, collection, skipInit) {
    -  // normalize collection
    -  if (!(schema instanceof Schema)) {
    -    collection = schema;
    -    schema = false;
    -  }
    -
    -  if ('boolean' === typeof collection) {
    -    skipInit = collection;
    -    collection = null;
    -  }
    -
    -  // look up models for the collection
    -  if (!this.modelSchemas[name]) {
    -    if (!schema && name in SchemaDefaults) {
    -      schema = SchemaDefaults[name];
    -    }
    -
    -    if (schema) {
    -      this.modelSchemas[name] = schema;
    -      for (var i = 0, l = this.plugins.length; i < l; i++) {
    -        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
    -      }
    -    } else {
    -      throw new Error('Schema hasn\'t been registered for model "' + name + '".
    -'
    -                    + 'Use mongoose.model(name, schema)');
    -    }
    -  }
    -
    -  if (!this.models[name]) {
    -    schema || (schema = this.modelSchemas[name]);
    -    collection || (collection = schema.set('collection') || format(name));
    -
    -    var model = Model.compile(name
    -                        , this.modelSchemas[name]
    -                        , collection
    -                        , this.connection
    -                        , this);
    -
    -    if (!skipInit) model.init();
    -
    -    this.models[name] = model;
    -  }
    -
    -  return this.models[name];
    -};

    Parameters:

    • name <String> model name
    • [schema] <Schema>
    • [collection] <String> name (optional, induced from model name)
    • [skipInit] <Boolean> whether to skip initialization (defaults to false)

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -
    -// define an Actor model with this mongoose instance
    -mongoose.model('Actor', new Schema({ name: String }));
    -
    -// create a new connection
    -var conn = mongoose.createConnection(..);
    -
    -// retrieve the Actor model
    -var Actor = conn.model('Actor');
    - -

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    - -

    Example:

    - -
    var schema = new Schema({ name: String });
    -schema.set('collection', 'actor');

    Mongoose#plugin(fn, [opts])

    Declares a global plugin executed on all Schemas.

    show code
    Mongoose.prototype.plugin = function (fn, opts) {
    -  this.plugins.push([fn, opts]);
    -  return this;
    -};

    Parameters:

    Returns:

    Equivalent to calling .plugin(fn) on each Schema you create.


    module.exports

    The exports object is an instance of Mongoose.

    show code
    module.exports = exports = new Mongoose;
    -var mongoose = module.exports;

    mongoose.Collection

    The Mongoose Collection constructor

    show code
    mongoose.Collection = Collection;

    mongoose.Connection

    The Mongoose Connection constructor

    show code
    mongoose.Connection = Connection;

    mongoose.version

    Mongoose version

    show code
    mongoose.version = JSON.parse(
    -  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
    -).version;

    mongoose.Mongoose

    The Mongoose constructor

    show code
    mongoose.Mongoose = Mongoose;

    The exports of the mongoose module is an instance of this class.

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -var mongoose2 = new mongoose.Mongoose();

    mongoose.Schema

    The Mongoose Schema constructor

    show code
    mongoose.Schema = Schema;

    Example:

    - -
    var mongoose = require('mongoose');
    -var Schema = mongoose.Schema;
    -var CatSchema = new Schema(..);

    mongoose.SchemaType

    The Mongoose SchemaType constructor.

    show code
    mongoose.SchemaType = SchemaType;

    mongoose.SchemaTypes

    The various Mongoose SchemaTypes.

    show code
    mongoose.SchemaTypes = Schema.Types;

    Note:

    - -

    Alias of mongoose.Schema.Types for backwards compatibility.


    mongoose.VirtualType

    The Mongoose VirtualType constructor.

    show code
    mongoose.VirtualType = VirtualType;

    mongoose.Types

    The various Mongoose Types.

    show code
    mongoose.Types = Types;

    Example:

    - -
    var mongoose = require('mongoose');
    -var array = mongoose.Types.Array;
    - -

    Types:

    - -
      -
    • Array
    • -
    • Buffer
    • -
    • Document
    • -
    • Embedded
    • -
    • DocumentArray
    • -
    • ObjectId
    • -
    - -

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    - -
    var ObjectId = mongoose.Types.ObjectId;
    -var id1 = new ObjectId;

    mongoose.Query

    The Mongoose Query constructor.

    show code
    mongoose.Query = Query;

    mongoose.Promise

    The Mongoose Promise constructor.

    show code
    mongoose.Promise = Promise;

    mongoose.Model

    The Mongoose Model constructor.

    show code
    mongoose.Model = Model;

    mongoose.Document

    The Mongoose Document constructor.

    show code
    mongoose.Document = Document;

    mongoose.Error

    The MongooseError constructor.

    show code
    mongoose.Error = require('./error');

    mongoose.mongo

    The node-mongodb-native driver Mongoose uses.

    show code
    mongoose.mongo = require('mongodb');

    Mongoose#connection

    The default connection of the mongoose module.

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -mongoose.connect(...);
    -mongoose.connection.on('error', cb);
    - -

    This is the connection used by default for every model created using mongoose.model.

    Returns:


  • collection.js

    Collection(name, conn, opts)

    Abstract Collection constructor

    show code
    function Collection (name, conn, opts) {
    -  this.name = name;
    -  this.conn = conn;
    -  this.buffer = true;
    -  this.queue = [];
    -
    -  if ('number' == typeof opts) opts = { size: opts };
    -  this.opts = opts || {};
    -
    -  if (STATES.connected == this.conn.readyState) {
    -    this.onOpen();
    -  }
    -};

    Parameters:

    • name <String> name of the collection
    • conn <Connection> A MongooseConnection instance
    • opts <Object> optional collection options

    This is the base class that drivers inherit from and implement.


    Collection#onOpen()

    Called when the database connects

    show code
    Collection.prototype.onOpen = function () {
    -  var self = this;
    -  this.buffer = false;
    -  self.doQueue();
    -};

    Collection#onClose()

    Called when the database disconnects

    show code
    Collection.prototype.onClose = function () {
    -  this.buffer = true;
    -};

    Collection#addQueue(name, args)

    Queues a method for later execution when its
    database connection opens.

    show code
    Collection.prototype.addQueue = function (name, args) {
    -  this.queue.push([name, args]);
    -  return this;
    -};

    Parameters:

    • name <String> name of the method to queue
    • args <Array> arguments to pass to the method when executed

    Collection#doQueue()

    Executes all queued methods and clears the queue.

    show code
    Collection.prototype.doQueue = function () {
    -  for (var i = 0, l = this.queue.length; i < l; i++){
    -    this[this.queue[i][0]].apply(this, this.queue[i][1]);
    -  }
    -  this.queue = [];
    -  return this;
    -};

    Collection#ensureIndex()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.ensureIndex = function(){
    -  throw new Error('Collection#ensureIndex unimplemented by driver');
    -};

    Collection#findAndModify()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findAndModify = function(){
    -  throw new Error('Collection#findAndModify unimplemented by driver');
    -};

    Collection#findOne()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findOne = function(){
    -  throw new Error('Collection#findOne unimplemented by driver');
    -};

    Collection#find()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.find = function(){
    -  throw new Error('Collection#find unimplemented by driver');
    -};

    Collection#insert()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.insert = function(){
    -  throw new Error('Collection#insert unimplemented by driver');
    -};

    Collection#save()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.save = function(){
    -  throw new Error('Collection#save unimplemented by driver');
    -};

    Collection#update()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.update = function(){
    -  throw new Error('Collection#update unimplemented by driver');
    -};

    Collection#getIndexes()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.getIndexes = function(){
    -  throw new Error('Collection#getIndexes unimplemented by driver');
    -};

    Collection#mapReduce()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.mapReduce = function(){
    -  throw new Error('Collection#mapReduce unimplemented by driver');
    -};

    Collection#conn

    The Connection instance


    Collection#name

    The collection name


  • connection.js

    Connection(base)

    Connection constructor

    show code
    function Connection (base) {
    -  this.base = base;
    -  this.collections = {};
    -  this.models = {};
    -  this.replica = false;
    -  this.host = null;
    -  this.port = null;
    -  this.user = null;
    -  this.pass = null;
    -  this.name = null;
    -  this.options = null;
    -  this._readyState = STATES.disconnected;
    -  this._closeCalled = false;
    -  this._hasOpened = false;
    -};

    Parameters:

    Events:

    • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

    • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

    • open: Emitted after we connected and onOpen is executed on all of this connections models.

    • disconnecting: Emitted when connection.close() was executed.

    • disconnected: Emitted after getting disconnected from the db.

    • close: Emitted after we disconnected and onClose executed on all of this connections models.

    • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

    • error: Emitted when an error occurs on this connection.

    • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

    For practical reasons, a Connection equals a Db.


    Connection#open(connection_string, [database], [port], [options], [callback])

    Opens the connection to MongoDB.

    show code
    Connection.prototype.open = function (host, database, port, options, callback) {
    -  var self = this
    -    , uri;
    -
    -  if ('string' === typeof database) {
    -    switch (arguments.length) {
    -      case 2:
    -        port = 27017;
    -      case 3:
    -        switch (typeof port) {
    -          case 'function':
    -            callback = port, port = 27017;
    -            break;
    -          case 'object':
    -            options = port, port = 27017;
    -            break;
    -        }
    -        break;
    -      case 4:
    -        if ('function' === typeof options)
    -          callback = options, options = {};
    -    }
    -  } else {
    -    switch (typeof database) {
    -      case 'function':
    -        callback = database, database = undefined;
    -        break;
    -      case 'object':
    -        options = database;
    -        database = undefined;
    -        callback = port;
    -        break;
    -    }
    -
    -    if (!rgxProtocol.test(host)) {
    -      host = 'mongodb://' + host;
    -    }
    -
    -    uri = url.parse(host);
    -    host = uri.hostname;
    -    port = uri.port || 27017;
    -    database = uri.pathname && uri.pathname.replace(/\//g, '');
    -  }
    -
    -  this.options = this.defaultOptions(options);
    -
    -  // make sure we can open
    -  if (STATES.disconnected !== this.readyState) {
    -    var err = new Error('Trying to open unclosed connection.');
    -    err.state = this.readyState;
    -    this.error(err, callback);
    -    return this;
    -  }
    -
    -  if (!host) {
    -    this.error(new Error('Missing connection hostname.'), callback);
    -    return this;
    -  }
    -
    -  if (!database) {
    -    this.error(new Error('Missing connection database.'), callback);
    -    return this;
    -  }
    -
    -  // handle authentication
    -  if (uri && uri.auth) {
    -    var auth = uri.auth.split(':');
    -    this.user = auth[0];
    -    this.pass = auth[1];
    -
    -  // Check hostname for user/pass
    -  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
    -    host = host.split('@');
    -    var auth = host.shift().split(':');
    -    host = host.pop();
    -    this.user = auth[0];
    -    this.pass = auth[1];
    -
    -  // user/pass options
    -  } else if (options && options.user && options.pass) {
    -    this.user = options.user;
    -    this.pass = options.pass;
    -
    -  } else {
    -    this.user = this.pass = undefined;
    -  }
    -
    -  this.name = database;
    -  this.host = host;
    -  this.port = port;
    -
    -  this._open(callback);
    -  return this;
    -};

    Parameters:

    • connection_string <String> mongodb://uri or the host to which you are connecting
    • [database] <String> database name
    • [port] <Number> database port
    • [options] <Object> options
    • [callback] <Function>

    options is a hash with the following possible properties:

    - -
    db      - passed to the connection db instance
    -server  - passed to the connection server instance(s)
    -replset - passed to the connection ReplSetServer instance
    -user    - username for authentication
    -pass    - password for authentication
    - -

    Notes:

    - -

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.


    Connection#openSet(uris, [database], [options], [callback])

    Connects to a replica set.

    show code
    Connection.prototype.openSet = function (uris, database, options, callback) {
    -  var uris = uris.split(',')
    -    , self = this;
    -
    -  switch (arguments.length) {
    -    case 3:
    -      this.name = database;
    -      if ('function' === typeof options) callback = options, options = {};
    -      break;
    -    case 2:
    -      switch (typeof database) {
    -        case 'string':
    -          this.name = database;
    -        case 'function':
    -          callback = database, database = null;
    -          break;
    -        case 'object':
    -          options = database, database = null;
    -          break;
    -      }
    -  }
    -
    -  this.options = options = this.defaultOptions(options);
    -
    -  if (uris.length < 2) {
    -    this.error(new Error('Please provide comma-separated URIs'), callback);
    -    return this;
    -  }
    -
    -  this.replica = true;
    -  this.host = [];
    -  this.port = [];
    -
    -  uris.forEach(function (uri) {
    -    // handle missing protocols
    -    if (!rgxProtocol.test(uri))
    -      uri = 'mongodb://' + uri;
    -
    -    var uri = url.parse(uri);
    -
    -    self.host.push(uri.hostname);
    -    self.port.push(uri.port || 27017);
    -
    -    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
    -      self.name = uri.pathname.replace(/\//g, '');
    -
    -    if (!self.user && uri.auth) {
    -      var auth = uri.auth.split(':');
    -      self.user = auth[0];
    -      self.pass = auth[1];
    -    }
    -  });
    -
    -  if (!this.name) {
    -    this.error(new Error('No database name provided for replica set'), callback);
    -    return this;
    -  }
    -
    -  this._open(callback);
    -  return this;
    -};

    Parameters:

    • uris <String> comma-separated mongodb:// `URI`s
    • [database] <String> database name if not included in `uris`
    • [options] <Object> passed to the internal driver
    • [callback] <Function>

    Example:

    - -
    var db = mongoose.createConnection();
    -db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
    - -

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    - -

    Valid options

    - -
    db      - passed to the connection db instance
    -server  - passed to the connection server instance(s)
    -replset - passed to the connection ReplSetServer instance
    -user    - username for authentication
    -pass    - password for authentication

    Connection#error(err, callback)

    error

    show code
    Connection.prototype.error = function (err, callback) {
    -  if (callback) return callback(err);
    -  this.emit('error', err);
    -}

    Parameters:

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.


    Connection#_open(callback)

    Handles opening the connection with the appropriate method based on connection type.

    show code
    Connection.prototype._open = function (callback) {
    -  this.readyState = STATES.connecting;
    -  this._closeCalled = false;
    -
    -  var self = this;
    -
    -  var method = this.replica
    -    ? 'doOpenSet'
    -    : 'doOpen';
    -
    -  // open connection
    -  this[method](function (err) {
    -    if (err) {
    -      self.readyState = STATES.disconnected;
    -      if (self._hasOpened) {
    -        if (callback) callback(err);
    -      } else {
    -        self.error(err, callback);
    -      }
    -      return;
    -    }
    -
    -    self.onOpen();
    -    callback && callback();
    -  });
    -}

    Parameters:


    Connection#onOpen()

    Called when the connection is opened

    show code
    Connection.prototype.onOpen = function () {
    -  var self = this;
    -
    -  function open () {
    -    self.readyState = STATES.connected;
    -
    -    // avoid having the collection subscribe to our event emitter
    -    // to prevent 0.3 warning
    -    for (var i in self.collections)
    -      self.collections[i].onOpen();
    -
    -    self.emit('open');
    -  };
    -
    -  // re-authenticate
    -  if (self.user && self.pass)
    -    self.db.authenticate(self.user, self.pass, open);
    -  else
    -    open();
    -};

    Connection#close([callback])

    Closes the connection

    show code
    Connection.prototype.close = function (callback) {
    -  var self = this;
    -  this._closeCalled = true;
    -
    -  switch (this.readyState){
    -    case 0: // disconnected
    -      callback && callback();
    -      break;
    -
    -    case 1: // connected
    -      this.readyState = STATES.disconnecting;
    -      this.doClose(function(err){
    -        if (err){
    -          self.error(err, callback);
    -        } else {
    -          self.onClose();
    -          callback && callback();
    -        }
    -      });
    -      break;
    -
    -    case 2: // connecting
    -      this.once('open', function(){
    -        self.close(callback);
    -      });
    -      break;
    -
    -    case 3: // disconnecting
    -      if (!callback) break;
    -      this.once('close', function () {
    -        callback();
    -      });
    -      break;
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Connection#onClose()

    Called when the connection closes

    show code
    Connection.prototype.onClose = function () {
    -  this.readyState = STATES.disconnected;
    -
    -  // avoid having the collection subscribe to our event emitter
    -  // to prevent 0.3 warning
    -  for (var i in this.collections)
    -    this.collections[i].onClose();
    -
    -  this.emit('close');
    -};

    Connection#collection(name, [options])

    Retrieves a collection, creating it if not cached.

    show code
    Connection.prototype.collection = function (name, options) {
    -  if (!(name in this.collections))
    -    this.collections[name] = new Collection(name, this, options);
    -  return this.collections[name];
    -};

    Parameters:

    • name <String> of the collection
    • [options] <Object> optional collection options

    Returns:


    Connection#model(name, [schema], [collection])

    Defines or retrieves a model.

    show code
    Connection.prototype.model = function (name, schema, collection) {
    -  if (!this.models[name]) {
    -    var model = this.base.model(name, schema, collection, true)
    -      , Model
    -
    -    if (this != model.prototype.db) {
    -      // subclass model using this connection and collection name
    -      Model = function Model (doc, fields, skipId) {
    -        if (!(this instanceof Model))
    -          return new Model(doc, fields, skipId);
    -        model.call(this, doc, fields, skipId);
    -      };
    -
    -      Model.__proto__ = model;
    -      Model.prototype.__proto__ = model.prototype;
    -      Model.db = Model.prototype.db = this;
    -
    -      // collection name discovery
    -      if ('string' === typeof schema) {
    -        collection = schema;
    -      }
    -
    -      if (!collection) {
    -        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
    -      }
    -
    -      var s = 'string' != typeof schema
    -        ? schema
    -        : model.prototype.schema;
    -
    -      Model.prototype.collection = this.collection(collection, s && s.options.capped);
    -      Model.collection = Model.prototype.collection;
    -      Model.init();
    -    }
    -
    -    this.models[name] = Model || model;
    -  }
    -
    -  return this.models[name];
    -};

    Parameters:

    • name <String> the model name
    • [schema] <Schema> a schema. necessary when defining a model
    • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

    Returns:

    • <Model> The compiled model
    var mongoose = require('mongoose');
    -var db = mongoose.createConnection(..);
    -db.model('Venue', new Schema(..));
    -var Ticket = db.model('Ticket', new Schema(..));
    -var Venue = db.model('Venue');

    Connection#setProfiling(level, [ms], callback)

    Set profiling level.

    show code
    Connection.prototype.setProfiling = function (level, ms, callback) {
    -  if (STATES.connected !== this.readyState) {
    -    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
    -  }
    -
    -  if (!callback) callback = ms, ms = 100;
    -
    -  var cmd = {};
    -
    -  switch (level) {
    -    case 0:
    -    case 'off':
    -      cmd.profile = 0;
    -      break;
    -    case 1:
    -    case 'slow':
    -      cmd.profile = 1;
    -      if ('number' !== typeof ms) {
    -        ms = parseInt(ms, 10);
    -        if (isNaN(ms)) ms = 100;
    -      }
    -      cmd.slowms = ms;
    -      break;
    -    case 2:
    -    case 'all':
    -      cmd.profile = 2;
    -      break;
    -    default:
    -      return callback(new Error('Invalid profiling level: '+ level));
    -  }
    -
    -  this.db.executeDbCommand(cmd, function (err, resp) {
    -    if (err) return callback(err);
    -
    -    var doc = resp.documents[0];
    -
    -    err = 1 === doc.ok
    -      ? null
    -      : new Error('Could not set profiling level to: '+ level)
    -
    -    callback(err, doc);
    -  });
    -};

    Parameters:

    • level <Number, String> either off (0), slow (1), or all (2)
    • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
    • callback <Function>

    Connection#defaultOptions(options)

    Prepares default connection options.

    show code
    Connection.prototype.defaultOptions = function (options) {
    -  var o = options || {};
    -
    -  o.server = o.server || {};
    -
    -  if (!('auto_reconnect' in o.server)) {
    -    o.server.auto_reconnect = true;
    -  }
    -
    -  o.db = o.db || {};
    -  o.db.forceServerObjectId = false;
    -
    -  return o;
    -}

    Parameters:


    Connection#db

    The mongodb.Db instance, set when the connection is opened


    Connection#collections

    A hash of the collections associated with this connection


    Connection#readyState

    Connection ready state

    - -
      -
    • 0 = disconnected
    • -
    • 1 = connected
    • -
    • 2 = connecting
    • -
    • 3 = disconnecting
    • -
    - -

    Each state change emits its associated event name.

    - -

    Example

    - -
    conn.on('connected', callback);
    -conn.on('disconnected', callback);

  • document.js

    Document(obj, [fields], [skipId])

    Document constructor.

    show code
    function Document (obj, fields, skipId) {
    -  // node <0.4.3 bug
    -  if (!this._events) this._events = {};
    -  this.setMaxListeners(0);
    -
    -  if ('boolean' === typeof fields) {
    -    this._strictMode = fields;
    -    this._selected = fields = undefined;
    -  } else {
    -    this._strictMode = this.schema.options && this.schema.options.strict;
    -    this._selected = fields;
    -  }
    -
    -  this.isNew = true;
    -  this.errors = undefined;
    -  this._shardval = undefined;
    -  this._saveError = undefined;
    -  this._validationError = undefined;
    -  this._adhocPaths = undefined;
    -  this._removing = undefined;
    -  this._inserting = undefined;
    -  this.__version = undefined;
    -  this.__getters = {};
    -  this.__id = undefined;
    -
    -  this._activePaths = new ActiveRoster;
    -
    -  var required = this.schema.requiredPaths();
    -  for (var i = 0; i < required.length; ++i) {
    -    this._activePaths.require(required[i]);
    -  }
    -
    -  this._doc = this._buildDoc(obj, fields, skipId);
    -  if (obj) this.set(obj, undefined, true);
    -  this._registerHooks();
    -};

    Parameters:

    • obj <Object> the values to set
    • [fields] <Object> the fields which were selected in the query returning this document
    • [skipId] <Boolean> bool, should we auto create an ObjectId _id

    Events:

    • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

    • save: Emitted when the document is successfully saved


    Document#_buildDoc(obj, [fields], [skipId])

    Builds the default doc structure

    show code
    Document.prototype._buildDoc = function (obj, fields, skipId) {
    -  var doc = {}
    -    , self = this
    -    , exclude
    -    , keys
    -    , key
    -    , ki
    -
    -  // determine if this doc is a result of a query with
    -  // excluded fields
    -  if (fields && 'Object' === fields.constructor.name) {
    -    keys = Object.keys(fields);
    -    ki = keys.length;
    -
    -    while (ki--) {
    -      if ('_id' !== keys[ki]) {
    -        exclude = 0 === fields[keys[ki]];
    -        break;
    -      }
    -    }
    -  }
    -
    -  var paths = Object.keys(this.schema.paths)
    -    , plen = paths.length
    -    , ii = 0
    -
    -  for (; ii < plen; ++ii) {
    -    var p = paths[ii];
    -
    -    if ('_id' == p) {
    -      if (skipId) continue;
    -      if (obj && '_id' in obj) continue;
    -    }
    -
    -    var type = this.schema.paths[p]
    -      , path = p.split('.')
    -      , len = path.length
    -      , last = len-1
    -      , doc_ = doc
    -      , i = 0
    -
    -    for (; i < len; ++i) {
    -      var piece = path[i]
    -        , def
    -
    -      if (i === last) {
    -        if (fields) {
    -          if (exclude) {
    -            // apply defaults to all non-excluded fields
    -            if (p in fields) continue;
    -
    -            def = type.getDefault(self, true);
    -            if ('undefined' !== typeof def) {
    -              doc_[piece] = def;
    -              self._activePaths.default(p);
    -            }
    -
    -          } else if (p in fields) {
    -            // selected field
    -            def = type.getDefault(self, true);
    -            if ('undefined' !== typeof def) {
    -              doc_[piece] = def;
    -              self._activePaths.default(p);
    -            }
    -          }
    -        } else {
    -          def = type.getDefault(self, true);
    -          if ('undefined' !== typeof def) {
    -            doc_[piece] = def;
    -            self._activePaths.default(p);
    -          }
    -        }
    -      } else {
    -        doc_ = doc_[piece] || (doc_[piece] = {});
    -      }
    -    }
    -  };
    -
    -  return doc;
    -};

    Parameters:

    Returns:


    Document#init(doc, fn)

    Initializes the document without setters or marking anything modified.

    show code
    Document.prototype.init = function (doc, fn) {
    -  this.isNew = false;
    -
    -  init(this, doc, this._doc);
    -  this._storeShard();
    -
    -  this.emit('init');
    -  if (fn) fn(null);
    -  return this;
    -};

    Parameters:

    Called internally after a document is returned from mongodb.


    Document#_storeShard()

    Stores the current values of the shard keys.

    show code
    Document.prototype._storeShard = function _storeShard () {
    -  // backwards compat
    -  var key = this.schema.options.shardKey || this.schema.options.shardkey;
    -  if (!(key && 'Object' == key.constructor.name)) return;
    -
    -  var orig = this._shardval = {}
    -    , paths = Object.keys(key)
    -    , len = paths.length
    -    , val
    -
    -  for (var i = 0; i < len; ++i) {
    -    val = this.getValue(paths[i]);
    -    if (isMongooseObject(val)) {
    -      orig[paths[i]] = val.toObject({ depopulate: true })
    -    } else if (null != val && val.valueOf) {
    -      orig[paths[i]] = val.valueOf();
    -    } else {
    -      orig[paths[i]] = val;
    -    }
    -  }
    -}

    Note:

    - -

    Shard key values do not / are not allowed to change.


    Document#update(doc, options, callback)

    Sends an update command with this document _id as the query selector.

    show code
    Document.prototype.update = function update () {
    -  var args = utils.args(arguments);
    -  args.unshift({_id: this._id});
    -  this.constructor.update.apply(this.constructor, args);
    -}

    Parameters:

    Returns:

    Example:

    - -
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
    - -

    Valid options:

    - -
      -
    • safe safe mode (defaults to value set in schema (true))
    • -
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • -

    Document#set(path, val, [type])

    Sets the value of a path, or many paths.

    show code
    Document.prototype.set = function (path, val, type) {
    -  var constructing = true === type
    -    , adhoc = type && true !== type
    -    , adhocs
    -
    -  if (adhoc) {
    -    adhocs = this._adhocPaths || (this._adhocPaths = {});
    -    adhocs[path] = Schema.interpretAsType(path, type);
    -  }
    -
    -  if ('string' !== typeof path) {
    -    // new Document({ key: val })
    -
    -    if (null === path || undefined === path) {
    -      var _ = path;
    -      path = val;
    -      val = _;
    -
    -    } else {
    -      var prefix = val
    -        ? val + '.'
    -        : '';
    -
    -      if (path instanceof Document) path = path._doc;
    -
    -      var keys = Object.keys(path)
    -        , i = keys.length
    -        , pathtype
    -        , key
    -
    -      while (i--) {
    -        key = keys[i];
    -        if (null != path[key] && 'Object' === path[key].constructor.name
    -          && !(this._path(prefix + key) instanceof MixedSchema)) {
    -          this.set(path[key], prefix + key, constructing);
    -        } else if (this._strictMode) {
    -          pathtype = this.schema.pathType(prefix + key);
    -          if ('real' === pathtype || 'virtual' === pathtype) {
    -            this.set(prefix + key, path[key], constructing);
    -          } else if ('throw' == this._strictMode) {
    -            throw new Error("Field `" + key + "` is not in schema.");
    -          }
    -        } else if (undefined !== path[key]) {
    -          this.set(prefix + key, path[key], constructing);
    -        }
    -      }
    -
    -      return this;
    -    }
    -  }
    -
    -  // ensure _strict is honored for obj props
    -  // docschema = new Schema({ path: { nest: 'string' }})
    -  // doc.set('path', obj);
    -  var pathType = this.schema.pathType(path);
    -  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
    -    this.setValue(path, null);
    -    this.set(val, path, constructing);
    -    return this;
    -  }
    -
    -  var schema;
    -  if ('adhocOrUndefined' == pathType && this._strictMode) {
    -    return this;
    -  } else if ('virtual' == pathType) {
    -    schema = this.schema.virtualpath(path);
    -    schema.applySetters(val, this);
    -    return this;
    -  } else {
    -    schema = this._path(path);
    -  }
    -
    -  var parts = path.split('.')
    -    , pathToMark
    -
    -  // When using the $set operator the path to the field must already exist.
    -  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
    -
    -  if (parts.length <= 1) {
    -    pathToMark = path;
    -  } else {
    -    for (var i = 0; i < parts.length; ++i) {
    -      var part = parts[i];
    -      var subpath = parts.slice(0, i).concat(part).join('.');
    -      if (this.isDirectModified(subpath) // earlier prefixes that are already
    -                                         // marked as dirty have precedence
    -          || this.get(subpath) === null) {
    -        pathToMark = subpath;
    -        break;
    -      }
    -    }
    -
    -    if (!pathToMark) pathToMark = path;
    -  }
    -
    -  if (!schema || null === val || undefined === val) {
    -    this._set(pathToMark, path, constructing, parts, schema, val);
    -    return this;
    -  }
    -
    -  var self = this;
    -
    -  // if this doc is being constructed we should not
    -  // trigger getters.
    -  var priorVal = constructing
    -    ? undefined
    -    : this.get(path);
    -
    -  var shouldSet = this.try(function(){
    -    val = schema.applySetters(val, self, false, priorVal);
    -  });
    -
    -  if (shouldSet) {
    -    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
    -  }
    -
    -  return this;
    -}

    Parameters:

    Example:

    - -
    // path, value
    -doc.set(path, value)
    -
    -// object
    -doc.set({
    -    path  : value
    -  , path2 : {
    -       path  : value
    -    }
    -})
    -
    -// only-the-fly cast to number
    -doc.set(path, value, Number)
    -
    -// only-the-fly cast to string
    -doc.set(path, value, String)

    Document#_set()

    Handles the actual setting of the value and marking the path modified if appropriate.

    show code
    Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {
    -  if (this.isNew) {
    -    this.markModified(pathToMark);
    -  } else {
    -
    -    priorVal || (priorVal = this.get(path));
    -
    -    if (!this.isDirectModified(pathToMark)) {
    -      if (undefined === val && !this.isSelected(path)) {
    -        // special case:
    -        // when a path is not selected in a query its initial
    -        // value will be undefined.
    -        this.markModified(pathToMark, priorVal);
    -      } else if (undefined === val && path in this._activePaths.states.default) {
    -        // do nothing
    -        // unsetting the default value which was never saved
    -      } else if (!deepEqual(val, priorVal)) {
    -        this.markModified(pathToMark, priorVal);
    -      } else if (!constructing &&
    -                 null != val &&
    -                 path in this._activePaths.states.default &&
    -                 deepEqual(val, schema.getDefault(this, constructing))) {
    -        // special case:
    -        // a path with a default was $unset on the server
    -        // and the user is setting it to the same value again
    -        this.markModified(pathToMark, priorVal);
    -      }
    -    }
    -  }
    -
    -  var obj = this._doc
    -    , i = 0
    -    , l = parts.length
    -
    -  for (; i < l; i++) {
    -    var next = i + 1
    -      , last = next === l;
    -
    -    if (last) {
    -      obj[parts[i]] = val;
    -    } else {
    -      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
    -        obj = obj[parts[i]];
    -      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
    -        obj = obj[parts[i]];
    -      } else {
    -        obj = obj[parts[i]] = {};
    -      }
    -    }
    -  }
    -};

    Document#getValue(path)

    Gets a raw value from a path (no getters)

    show code
    Document.prototype.getValue = function (path) {
    -  var parts = path.split('.')
    -    , obj = this._doc
    -    , part;
    -
    -  for (var i = 0, l = parts.length; i < l; i++) {
    -    part = parts[i];
    -    obj = obj.getValue
    -        ? obj.getValue(part) // If we have an embedded array document member
    -        : obj[part];
    -    if (!obj) return obj;
    -  }
    -
    -  return obj;
    -}

    Parameters:


    Document#setValue(path, value)

    Sets a raw value for a path (no casting, setters, transformations)

    show code
    Document.prototype.setValue = function (path, val) {
    -  var parts = path.split('.')
    -    , obj = this._doc;
    -
    -  for (var i = 0, len = parts.length-1; i < len; i++) {
    -    obj = obj[parts[i]];
    -  }
    -
    -  obj[parts[len]] = val;
    -  return this;
    -};

    Parameters:


    Document#get(path, [type])

    Returns the value of a path.

    show code
    Document.prototype.get = function (path, type) {
    -  var adhocs;
    -  if (type) {
    -    adhocs = this._adhocPaths || (this._adhocPaths = {});
    -    adhocs[path] = Schema.interpretAsType(path, type);
    -  }
    -
    -  var schema = this._path(path) || this.schema.virtualpath(path)
    -    , pieces = path.split('.')
    -    , obj = this._doc;
    -
    -  for (var i = 0, l = pieces.length; i < l; i++) {
    -    obj = null == obj ? null : obj[pieces[i]];
    -  }
    -
    -  if (schema) {
    -    obj = schema.applyGetters(obj, this);
    -  }
    -
    -  return obj;
    -};

    Parameters:

    Example

    - -
    // path
    -doc.get('age') // 47
    -
    -// dynamic casting to a string
    -doc.get('age', String) // "47"

    Document#_path(path)

    Returns the schematype for the given path.

    show code
    Document.prototype._path = function (path) {
    -  var adhocs = this._adhocPaths
    -    , adhocType = adhocs && adhocs[path];
    -
    -  if (adhocType) {
    -    return adhocType;
    -  } else {
    -    return this.schema.path(path);
    -  }
    -};

    Parameters:


    Document#markModified(path)

    Marks the path as having pending changes to write to the db.

    show code
    Document.prototype.markModified = function (path) {
    -  this._activePaths.modify(path);
    -};

    Parameters:

    • path <String> the path to mark modified

    Very helpful when using Mixed types.

    - -

    Example:

    - -
    doc.mixed.type = 'changed';
    -doc.markModified('mixed.type');
    -doc.save() // changes to mixed.type are now persisted

    Document#try(fn, scope)

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    show code
    Document.prototype.try = function (fn, scope) {
    -  var res;
    -  try {
    -    fn.call(scope);
    -    res = true;
    -  } catch (e) {
    -    this._error(e);
    -    res = false;
    -  }
    -  return res;
    -};

    Parameters:

    • fn <Function> function to execute
    • scope <Object> the scope with which to call fn

    Document#modifiedPaths()

    Returns the list of paths that have been modified.

    show code
    Document.prototype.modifiedPaths = function () {
    -  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
    -
    -  return directModifiedPaths.reduce(function (list, path) {
    -    var parts = path.split('.');
    -    return list.concat(parts.reduce(function (chains, part, i) {
    -      return chains.concat(parts.slice(0, i).concat(part).join('.'));
    -    }, []));
    -  }, []);
    -};

    Returns:


    Document#isModified([path])

    Returns true if this document was modified, else false.

    show code
    Document.prototype.isModified = function (path) {
    -  return path
    -    ? !!~this.modifiedPaths().indexOf(path)
    -    : this._activePaths.some('modify');
    -};

    Parameters:

    Returns:

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    - -

    Example

    - -
    doc.set('documents.0.title', 'changed');
    -doc.isModified()                    // true
    -doc.isModified('documents')         // true
    -doc.isModified('documents.0.title') // true
    -doc.isDirectModified('documents')   // false

    Document#isDirectModified(path)

    Returns true if path was directly set and modified, else false.

    show code
    Document.prototype.isDirectModified = function (path) {
    -  return (path in this._activePaths.states.modify);
    -};

    Parameters:

    Returns:

    Example

    - -
    doc.set('documents.0.title', 'changed');
    -doc.isDirectModified('documents.0.title') // true
    -doc.isDirectModified('documents') // false

    Document#isInit(path)

    Checks if path was initialized.

    show code
    Document.prototype.isInit = function (path) {
    -  return (path in this._activePaths.states.init);
    -};

    Parameters:

    Returns:


    Document#isSelected(path)

    Checks if path was selected in the source query which initialized this document.

    show code
    Document.prototype.isSelected = function isSelected (path) {
    -  if (this._selected) {
    -
    -    if ('_id' === path) {
    -      return 0 !== this._selected._id;
    -    }
    -
    -    var paths = Object.keys(this._selected)
    -      , i = paths.length
    -      , inclusive = false
    -      , cur
    -
    -    if (1 === i && '_id' === paths[0]) {
    -      // only _id was selected.
    -      return 0 === this._selected._id;
    -    }
    -
    -    while (i--) {
    -      cur = paths[i];
    -      if ('_id' == cur) continue;
    -      inclusive = !! this._selected[cur];
    -      break;
    -    }
    -
    -    if (path in this._selected) {
    -      return inclusive;
    -    }
    -
    -    i = paths.length;
    -    var pathDot = path + '.';
    -
    -    while (i--) {
    -      cur = paths[i];
    -      if ('_id' == cur) continue;
    -
    -      if (0 === cur.indexOf(pathDot)) {
    -        return inclusive;
    -      }
    -
    -      if (0 === pathDot.indexOf(cur)) {
    -        return inclusive;
    -      }
    -    }
    -
    -    return ! inclusive;
    -  }
    -
    -  return true;
    -}

    Parameters:

    Returns:

    Example

    - -
    Thing.findOne().select('name').exec(function (err, doc) {
    -   doc.isSelected('name') // true
    -   doc.isSelected('age')  // false
    -})

    Document#validate(cb)

    Executes registered validation rules for this document.

    show code
    Document.prototype.validate = function (cb) {
    -  var self = this
    -
    -  // only validate required fields when necessary
    -  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
    -    if (!self.isSelected(path) && !self.isModified(path)) return false;
    -    return true;
    -  });
    -
    -  paths = paths.concat(Object.keys(this._activePaths.states.init));
    -  paths = paths.concat(Object.keys(this._activePaths.states.modify));
    -
    -  if (0 === paths.length) {
    -    complete();
    -    return this;
    -  }
    -
    -  var validating = {}
    -    , total = 0;
    -
    -  paths.forEach(validatePath);
    -  return this;
    -
    -  function validatePath (path) {
    -    if (validating[path]) return;
    -
    -    validating[path] = true;
    -    total++;
    -
    -    process.nextTick(function(){
    -      var p = self.schema.path(path);
    -      if (!p) return --total || complete();
    -
    -      p.doValidate(self.getValue(path), function (err) {
    -        if (err) self.invalidate(path, err, true);
    -        --total || complete();
    -      }, self);
    -    });
    -  }
    -
    -  function complete () {
    -    var err = self._validationError;
    -    self._validationError = undefined;
    -    cb(err);
    -  }
    -};

    Parameters:

    • cb <Function> called after validation completes, passing an error if one occurred

    Note:

    - -

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    - -

    Example:

    - -
    doc.validate(function (err) {
    -  if (err) handleError(err);
    -  else // validation passed
    -});

    Document#invalidate(path, err)

    Marks a path as invalid, causing validation to fail.

    show code
    Document.prototype.invalidate = function (path, err) {
    -  if (!this._validationError) {
    -    this._validationError = new ValidationError(this);
    -  }
    -
    -  if (!err || 'string' === typeof err) {
    -    err = new ValidatorError(path, err);
    -  }
    -
    -  this._validationError.errors[path] = err;
    -}

    Parameters:

    • path <String> the field to invalidate
    • err <String, Error> the error which states the reason `path` was invalid

    Document#_reset()

    Resets the internal modified state of this document.

    show code
    Document.prototype._reset = function reset () {
    -  var self = this;
    -  DocumentArray || (DocumentArray = require('./types/documentarray'));
    -
    -  this._activePaths
    -  .map('init', 'modify', function (i) {
    -    return self.getValue(i);
    -  })
    -  .filter(function (val) {
    -    return (val && val instanceof DocumentArray && val.length);
    -  })
    -  .forEach(function (array) {
    -    array.forEach(function (doc) {
    -      doc._reset();
    -    });
    -  });
    -
    -  // clear atomics
    -  this._dirty().forEach(function (dirt) {
    -    var type = dirt.value;
    -    if (type && type._atomics) {
    -      type._atomics = {};
    -    }
    -  });
    -
    -  // Clear 'modify'('dirty') cache
    -  this._activePaths.clear('modify');
    -  this._validationError = undefined;
    -  this.errors = undefined;
    -  var self = this;
    -  this.schema.requiredPaths().forEach(function (path) {
    -    self._activePaths.require(path);
    -  });
    -
    -  return this;
    -}

    Returns:


    Document#_dirty()

    Returns this documents dirty paths / vals.

    show code
    Document.prototype._dirty = function _dirty () {
    -  var self = this;
    -
    -  var all = this._activePaths.map('modify', function (path) {
    -    return { path: path
    -           , value: self.getValue(path)
    -           , schema: self._path(path) };
    -  });
    -
    -  // Sort dirty paths in a flat hierarchy.
    -  all.sort(function (a, b) {
    -    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
    -  });
    -
    -  // Ignore "foo.a" if "foo" is dirty already.
    -  var minimal = []
    -    , lastPath
    -    , top;
    -
    -  all.forEach(function (item, i) {
    -    if (item.path.indexOf(lastPath) !== 0) {
    -      lastPath = item.path + '.';
    -      minimal.push(item);
    -      top = item;
    -    } else {
    -      if (!(item.value && top.value)) return;
    -
    -      // special case for top level MongooseArrays
    -      if (top.value._atomics && top.value.hasAtomics()) {
    -        // the `top` array itself and a sub path of `top` are being modified.
    -        // the only way to honor all of both modifications is through a $set
    -        // of entire array.
    -        top.value._atomics = {};
    -        top.value._atomics.$set = top.value;
    -      }
    -    }
    -  });
    -
    -  top = lastPath = null;
    -  return minimal;
    -}

    Document#_setSchema(schema)

    Assigns/compiles schema into this documents prototype.

    show code
    Document.prototype._setSchema = function (schema) {
    -  compile(schema.tree, this);
    -  this.schema = schema;
    -}

    Parameters:


    Document#_registerHooks()

    Register default hooks

    show code
    Document.prototype._registerHooks = function _registerHooks () {
    -  if (!this.save) return;
    -
    -  DocumentArray || (DocumentArray = require('./types/documentarray'));
    -
    -  this.pre('save', function (next) {
    -    // we keep the error semaphore to make sure we don't
    -    // call `save` unnecessarily (we only need 1 error)
    -    var subdocs = 0
    -      , error = false
    -      , self = this;
    -
    -    // check for DocumentArrays
    -    var arrays = this._activePaths
    -    .map('init', 'modify', function (i) {
    -      return self.getValue(i);
    -    })
    -    .filter(function (val) {
    -      return (val && val instanceof DocumentArray && val.length);
    -    });
    -
    -    if (!arrays.length)
    -      return next();
    -
    -    arrays.forEach(function (array) {
    -      subdocs += array.length;
    -      array.forEach(function (value) {
    -        if (error) return;
    -
    -        value.save(function (err) {
    -          if (error) return;
    -
    -          if (err) {
    -            error = true;
    -            self._validationError = undefined;
    -            return next(err);
    -          }
    -
    -          --subdocs || next();
    -        });
    -      });
    -    });
    -  }, function (err) {
    -    // emit on the Model if listening
    -    if (this.constructor.listeners('error').length) {
    -      this.constructor.emit('error', err);
    -    } else {
    -      // emit on the connection
    -      if (!this.db.listeners('error').length) {
    -        err.stack = 'No listeners detected, throwing. '
    -                  + 'Consider adding an error listener to your connection.
    -'
    -                  + err.stack
    -      }
    -      this.db.emit('error', err);
    -    }
    -  }).pre('save', function checkForExistingErrors (next) {
    -    // if any doc.set() calls failed
    -    if (this._saveError) {
    -      next(this._saveError);
    -      this._saveError = null;
    -    } else {
    -      next();
    -    }
    -  }).pre('save', function validation (next) {
    -    return this.validate(next);
    -  });
    -
    -  // add user defined queues
    -  this._doQueue();
    -};

    Document#_error(err)

    Registers an error

    show code
    Document.prototype._error = function (err) {
    -  this._saveError = err;
    -  return this;
    -};

    Parameters:


    Document#_doQueue()

    Executes methods queued from the Schema definition

    show code
    Document.prototype._doQueue = function () {
    -  var q = this.schema && this.schema.callQueue;
    -  if (q) {
    -    for (var i = 0, l = q.length; i < l; i++) {
    -      this[q[i][0]].apply(this, q[i][1]);
    -    }
    -  }
    -  return this;
    -};

    Document#toObject([options])

    Converts this document into a plain javascript object

    show code
    Document.prototype.toObject = function (options) {
    -  // When internally saving this document we always pass options,
    -  // bypassing the custom schema options.
    -  if (!(options && 'Object' == options.constructor.name)) {
    -    options = this.schema.options.toObject
    -      ? clone(this.schema.options.toObject)
    -      : {};
    -  }
    -
    -  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
    -
    -  var ret = clone(this._doc, options);
    -
    -  if (options.virtuals || options.getters && false !== options.virtuals) {
    -    applyGetters(this, ret, 'virtuals', options);
    -  }
    -
    -  if (options.getters) {
    -    applyGetters(this, ret, 'paths', options);
    -  }
    -
    -  return ret;
    -};

    Parameters:

    Returns:

    Options:

    - -
      -
    • getters apply all getters (path and virtual getters)
    • -
    • virtuals apply virtual getters (can override getters option)
    • -
    • minimize remove empty objects (defaults to true)
    • -
    - -

    Example of only applying path getters

    - -
    doc.toObject({ getters: true, virtuals: false })
    - -

    Example of only applying virtual getters

    - -
    doc.toObject({ virtuals: true })
    - -

    Example of applying both path and virtual getters

    - -
    doc.toObject({ getters: true })
    - -

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    - -
    schema.set('toObject', { virtuals: true })
    - -

    See schema options for details.


    Document#toJSON(options)

    The return value of this method is used in calls to JSON.stringify(doc).

    show code
    Document.prototype.toJSON = function (options) {
    -  // check for object type since an array of documents
    -  // being stringified passes array indexes instead
    -  // of options objects. JSON.stringify([doc, doc])
    -  if (!(options && 'Object' == options.constructor.name)) {
    -    options = this.schema.options.toJSON
    -      ? clone(this.schema.options.toJSON)
    -      : {};
    -  }
    -  options.json = true;
    -  return this.toObject(options);
    -};

    Parameters:

    • options <Object> same options as `Document#toObject`

    Returns:

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    - -
    schema.set('toJSON', { virtuals: true })
    - -

    See schema options for details.


    Document#inspect()

    Helper for console.log

    show code
    Document.prototype.inspect = function (options) {
    -  var opts = options && 'Object' == options.constructor.name
    -    ? options
    -    : undefined
    -  return inspect(this.toObject(opts));
    -};

    Document#toString()

    Helper for console.log


    Document#equals(doc)

    Returns true if the Document stores the same data as doc.

    show code
    Document.prototype.equals = function (doc) {
    -  var tid = this.get('_id');
    -  var docid = doc.get('_id');
    -  return tid.equals
    -    ? tid.equals(docid)
    -    : tid === docid;
    -};

    Parameters:

    Returns:

    Documents are considered equal when they have matching _ids.


    Document#errors

    Hash containing current validation errors.


    Document#id

    The string version of this documents _id.

    - -

    Note:

    - -

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    - -
    new Schema({ name: String }, { id: false });

    Document#isNew

    Boolean flag specifying if the document is new.


    Document#schema

    The documents schema.


  • drivers/node-mongodb-native/collection.js

    NativeCollection()

    A node-mongodb-native collection implementation.

    show code
    function NativeCollection () {
    -  this.collection = null;
    -  MongooseCollection.apply(this, arguments);
    -}

    Inherits:

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


    NativeCollection#onOpen()

    Called when the connection opens.

    show code
    NativeCollection.prototype.onOpen = function () {
    -  var self = this;
    -
    -  if (this.collection) {
    -    return MongooseCollection.prototype.onOpen.call(self);
    -  }
    -
    -  if (!self.opts.size) {
    -    // non-capped
    -    return self.conn.db.collection(self.name, callback);
    -  }
    -
    -  // capped
    -  return self.conn.db.collection(self.name, function (err, c) {
    -    if (err) return callback(err);
    -
    -    // discover if this collection exists and if it is capped
    -    c.options(function (err, exists) {
    -      if (err) return callback(err);
    -
    -      if (exists) {
    -        if (exists.capped) {
    -          callback(null, c);
    -        } else {
    -          var msg = 'A non-capped collection exists with this name.
    -
    -'
    -                  + ' To use this collection as a capped collection, please '
    -                  + 'first convert it.
    -'
    -                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
    -          err = new Error(msg);
    -          callback(err);
    -        }
    -      } else {
    -        // create
    -        var opts = utils.clone(self.opts);
    -        opts.capped = true;
    -        self.conn.db.createCollection(self.name, opts, callback);
    -      }
    -    });
    -  });
    -
    -  function callback (err, collection) {
    -    if (err) {
    -      // likely a strict mode error
    -      self.conn.emit('error', err);
    -    } else {
    -      self.collection = collection;
    -      MongooseCollection.prototype.onOpen.call(self);
    -    }
    -  };
    -};

    NativeCollection#onClose()

    Called when the connection closes

    show code
    NativeCollection.prototype.onClose = function () {
    -  MongooseCollection.prototype.onClose.call(this);
    -};

    NativeCollection#getIndexes(callback)

    Retreives information about this collections indexes.

    Parameters:


  • drivers/node-mongodb-native/connection.js

    NativeConnection()

    A node-mongodb-native connection implementation.

    show code
    function NativeConnection() {
    -  MongooseConnection.apply(this, arguments);
    -};

    Inherits:


    NativeConnection#doOpen(fn)

    Opens the connection to MongoDB.

    show code
    NativeConnection.prototype.doOpen = function (fn) {
    -  var server
    -    , self = this;
    -
    -  if (!this.db) {
    -    server = new mongo.Server(this.host, Number(this.port), this.options.server);
    -    this.db = new mongo.Db(this.name, server, this.options.db);
    -  }
    -
    -  this.db.open(function (err) {
    -    if (err) return fn(err);
    -    fn();
    -    listen(self);
    -  });
    -
    -  return this;
    -};
    -
    -function listen (conn) {
    -  if (conn._listening) return;
    -  conn._listening = true;
    -
    -  conn.db.on('close', function(){
    -    if (conn._closeCalled) return;
    -
    -    // the driver never emits an `open` event. auto_reconnect still
    -    // emits a `close` event but since we never get another
    -    // `open` we can't emit close
    -    if (conn.db.serverConfig.autoReconnect) {
    -      conn.readyState = STATES.disconnected;
    -      conn.emit('close');
    -      return;
    -    }
    -    conn.onClose();
    -  });
    -  conn.db.on('error', function(err){
    -    conn.emit('error', err);
    -  });
    -  conn.db.on('timeout', function(err){
    -    var error = new Error(err && err.err || 'connection timeout');
    -    conn.emit('error', error);
    -  });
    -  conn.db.on('open', function (err, db) {
    -    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
    -      conn.readyState = STATES.connected;
    -      conn.emit('reconnected')
    -    }
    -  })
    -}

    Parameters:

    Returns:


    NativeConnection#doOpenSet(fn)

    Opens a connection to a MongoDB ReplicaSet.

    show code
    NativeConnection.prototype.doOpenSet = function (fn) {
    -  if (!this.db) {
    -    var servers = []
    -      , ports = this.port
    -      , self = this
    -
    -    this.host.forEach(function (host, i) {
    -      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
    -    });
    -
    -    var server = new ReplSetServers(servers, this.options.replset);
    -    this.db = new mongo.Db(this.name, server, this.options.db);
    -
    -    this.db.on('fullsetup', function () {
    -      self.emit('fullsetup')
    -    });
    -  }
    -
    -  this.db.open(function (err) {
    -    if (err) return fn(err);
    -    fn();
    -    listen(self);
    -  });
    -
    -  return this;
    -};

    Parameters:

    Returns:

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


    NativeConnection#doClose(fn)

    Closes the connection

    show code
    NativeConnection.prototype.doClose = function (fn) {
    -  this.db.close();
    -  if (fn) fn();
    -  return this;
    -}

    Parameters:

    Returns:


  • error.js

    MongooseError()

    Mongoose error

    show code
    function MongooseError (msg) {
    -  Error.call(this);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.message = msg;
    -  this.name = 'MongooseError';
    -};

    Inherits:


  • errors/cast.js

    CastError(type, value)

    Casting Error constructor.

    show code
    function CastError (type, value) {
    -  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'CastError';
    -  this.type = type;
    -  this.value = value;
    -};

    Parameters:

    Inherits:


  • errors/document.js

    DocumentError(msg)

    Document Error

    show code
    function DocumentError (msg) {
    -  MongooseError.call(this, msg);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'DocumentError';
    -};

    Parameters:

    Inherits:


  • errors/validation.js

    ValidationError(instance)

    Document Validation Error

    show code
    function ValidationError (instance) {
    -  MongooseError.call(this, "Validation failed");
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'ValidationError';
    -  this.errors = instance.errors = {};
    -};

    Parameters:

    Inherits:


    ValidationError#toString()

    Console.log helper

    show code
    ValidationError.prototype.toString = function () {
    -  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
    -    return String(this.errors[key]);
    -  }, this).join(', ');
    -};

  • errors/validator.js

    ValidatorError(path, msg)

    Schema validator error

    show code
    function ValidatorError (path, type) {
    -  var msg = type
    -    ? '"' + type + '" '
    -    : '';
    -  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'ValidatorError';
    -  this.path = path;
    -  this.type = type;
    -};

    Parameters:

    Inherits:


  • model.js

    Model(doc)

    Model constructor

    show code
    function Model (doc, fields, skipId) {
    -  Document.call(this, doc, fields, skipId);
    -};

    Parameters:

    • doc <Object> values to with which to create the document

    Inherits:

    Events:

    • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

    • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


    Model#_getPopulationKeys(query)

    Returns what paths can be populated

    show code
    Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
    -  if (!(query && query.options.populate)) return;
    -
    -  var names = Object.keys(query.options.populate)
    -    , n = names.length
    -    , name
    -    , paths = {}
    -    , hasKeys
    -    , schema
    -
    -  while (n--) {
    -    name = names[n];
    -    schema = this.schema.path(name);
    -    hasKeys = true;
    -
    -    if (!schema) {
    -      // if the path is not recognized, it's potentially embedded docs
    -      // walk path atoms from right to left to find a matching path
    -      var pieces = name.split('.')
    -        , i = pieces.length;
    -
    -      while (i--) {
    -        var path = pieces.slice(0, i).join('.')
    -          , pathSchema = this.schema.path(path);
    -
    -        // loop until we find an array schema
    -        if (pathSchema && pathSchema.caster) {
    -          if (!paths[path]) {
    -            paths[path] = { sub: {} };
    -          }
    -
    -          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
    -          hasKeys || (hasKeys = true);
    -          break;
    -        }
    -      }
    -    } else {
    -      paths[name] = query.options.populate[name];
    -      hasKeys || (hasKeys = true);
    -    }
    -  }
    -
    -  return hasKeys && paths;
    -};

    Parameters:

    Returns:


    Model#_populate(schema, oid, query, fn)

    Populates an object

    show code
    Model.prototype._populate = function populate (schema, oid, query, fn) {
    -  if (!Array.isArray(oid)) {
    -    var conditions = query.conditions || {};
    -    conditions._id = oid;
    -
    -    return this
    -    .db.model(query.model || schema.options.ref)
    -    .findOne(conditions, query.fields, query.options, fn);
    -  }
    -
    -  if (!oid.length) {
    -    return fn(null, oid);
    -  }
    -
    -  var model = this.db.model(query.model || schema.caster.options.ref)
    -    , conditions = query && query.conditions || {};
    -
    -  conditions._id || (conditions._id = { $in: oid });
    -
    -  model.find(conditions, query.fields, query.options, function (err, docs) {
    -    if (err) return fn(err);
    -
    -    // user specified sort order?
    -    if (query.options && query.options.sort) {
    -      return fn(null, docs);
    -    }
    -
    -    // put back in original id order (using a hash reduces complexity from n*n to 2n)
    -    var docHash = {};
    -    docs.forEach(function (doc) {
    -      docHash[doc._id] = doc;
    -    });
    -
    -    var arr = [];
    -    oid.forEach(function (id) {
    -      if (id in docHash) arr.push(docHash[id]);
    -    });
    -
    -    fn(null, arr);
    -  });
    -};

    Parameters:

    • schema <SchemaType> type for the oid
    • oid <Object> object id or array of object ids
    • query <Object> object specifying query conditions, fields, and options
    • fn <Function>

    Model#init(doc, query, fn)

    Performs auto-population of relations.

    show code
    Model.prototype.init = function init (doc, query, fn) {
    -  if ('function' == typeof query) {
    -    fn = query;
    -    query = null;
    -  }
    -
    -  var populate = this._getPopulationKeys(query);
    -
    -  if (!populate) {
    -    return Document.prototype.init.call(this, doc, fn);
    -  }
    -
    -  // population from other models is necessary
    -  var self = this;
    -
    -  init(doc, '', function (err) {
    -    if (err) return fn(err);
    -    Document.prototype.init.call(self, doc, fn);
    -  });
    -
    -  return this;
    -
    -  function init (obj, prefix, fn) {
    -    prefix = prefix || '';
    -
    -    var keys = Object.keys(obj)
    -      , len = keys.length;
    -
    -    return next();
    -
    -    function next () {
    -      if (--len < 0) return fn();
    -
    -      var i = keys[len]
    -        , path = prefix + i
    -        , schema = self.schema.path(path)
    -        , total = 0
    -        , inline = false
    -        , poppath
    -
    -      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
    -        // assume nested object
    -        return init(obj[i], path + '.', next);
    -      }
    -
    -      if (!(obj[i] && schema && populate[path])) return next();
    -
    -      // this query object is re-used and passed around. we clone
    -      // it to prevent query condition contamination between
    -      // one populate call to the next.
    -      poppath = utils.clone(populate[path]);
    -
    -      if (poppath.sub) {
    -        obj[i].forEach(function (subobj) {
    -          inline = true;
    -
    -          var pkeys = Object.keys(poppath.sub)
    -            , pi = pkeys.length
    -            , key
    -
    -          while (pi--) {
    -            key = pkeys[pi];
    -
    -            if (subobj[key]) (function (key) {
    -              total++;
    -              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
    -              function done (err, doc) {
    -                if (err) return error(err);
    -                subobj[key] = doc;
    -                if (--total < 1 && !inline) {
    -                  next();
    -                }
    -              }
    -            })(key);
    -          }
    -        });
    -
    -        inline = false;
    -
    -        if (0 === total) return next();
    -
    -      } else {
    -        self._populate(schema, obj[i], poppath, function (err, doc) {
    -          if (err) return error(err);
    -          obj[i] = doc;
    -          next();
    -        });
    -      }
    -    };
    -  };
    -
    -  function error (err) {
    -    if (error.err) return;
    -    fn(error.err = err);
    -  }
    -};

    Parameters:

    • doc <Object> document returned by mongo
    • query <Query> query that originated the initialization
    • fn <Function>

    Model#save([fn])

    Saves this document.

    show code
    Model.prototype.save = function save (fn) {
    -  var promise = new Promise(fn)
    -    , complete = handleSave(promise, this)
    -    , options = {}
    -
    -  if (this.schema.options.safe) {
    -    options.safe = this.schema.options.safe;
    -  }
    -
    -  if (this.isNew) {
    -    // send entire doc
    -    var obj = this.toObject({ depopulate: 1 });
    -    this._version(true, obj);
    -    this.collection.insert(obj, options, complete);
    -    this._reset();
    -    this.isNew = false;
    -    this.emit('isNew', false);
    -    // Make it possible to retry the insert
    -    this._inserting = true;
    -
    -  } else {
    -    // Make sure we don't treat it as a new object on error,
    -    // since it already exists
    -    this._inserting = false;
    -
    -    var delta = this._delta();
    -    if (delta) {
    -      var where = this._where(delta[0]);
    -      this.collection.update(where, delta[1], options, complete);
    -    } else {
    -      complete(null);
    -    }
    -
    -    this._reset();
    -    this.emit('isNew', false);
    -  }
    -};

    Parameters:

    Example:

    - -
    product.sold = Date.now();
    -product.save(function (err, product) {
    -  if (err) ..
    -})
    - -

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    - -
    var db = mongoose.createConnection(..);
    -var schema = new Schema(..);
    -var Product = db.model('Product', schema);
    -
    -db.on('error', handleError);
    - -

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    - -
    Product.on('error', handleError);

    Model#_delta()

    Produces a special query document of the modified properties used in updates.

    show code
    Model.prototype._delta = function _delta () {
    -  var dirty = this._dirty();
    -  if (!dirty.length) return;
    -
    -  var self = this
    -    , where = {}
    -    , delta = {}
    -    , len = dirty.length
    -    , d = 0
    -    , val
    -    , obj
    -
    -  for (; d < len; ++d) {
    -    var data = dirty[d]
    -    var value = data.value
    -    var schema = data.schema
    -
    -    if (undefined === value) {
    -      operand(self, where, delta, data, 1, '$unset');
    -
    -    } else if (null === value) {
    -      operand(self, where, delta, data, null);
    -
    -    } else if (value._path && value._atomics) {
    -      handleAtomics(self, where, delta, data, value);
    -
    -    } else if (value._path && Buffer.isBuffer(value)) {
    -      // MongooseBuffer
    -      value = value.toObject();
    -      operand(self, where, delta, data, value);
    -
    -    } else {
    -      value = utils.clone(value);
    -      operand(self, where, delta, data, value);
    -    }
    -  }
    -
    -  if (this.__version) {
    -    this._version(where, delta);
    -  }
    -
    -  return [where, delta];
    -}

    Model#_version()

    Appends versioning to the where and update clauses.

    show code
    Model.prototype._version = function _version (where, delta) {
    -  var key = this.schema.options.versionKey;
    -
    -  if (true === where) {
    -    // this is an insert
    -    if (key) this.setValue(key, delta[key] = 0);
    -    return;
    -  }
    -
    -  // updates
    -
    -  // only apply versioning if our versionKey was selected. else
    -  // there is no way to select the correct version. we could fail
    -  // fast here and force them to include the versionKey but
    -  // thats a bit intrusive. can we do this automatically?
    -  // TODO fail fast option?
    -  if (!this.isSelected(key)) {
    -    return;
    -  }
    -
    -  // $push $addToSet don't need the where clause set
    -  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
    -    where[key] = this.getValue(key);
    -  }
    -
    -  if (VERSION_INC === (VERSION_INC & this.__version)) {
    -    delta.$inc || (delta.$inc = {});
    -    delta.$inc[key] = 1;
    -  }
    -}

    Model#increment()

    Signal that we desire an increment of this documents version.

    show code
    Model.prototype.increment = function increment () {
    -  this.__version = VERSION_ALL;
    -  return this;
    -}

    Model#_where()

    Returns a query object which applies shardkeys if they exist.

    show code
    Model.prototype._where = function _where (where) {
    -  where || (where = {});
    -
    -  var paths
    -    , len
    -
    -  if (this._shardval) {
    -    paths = Object.keys(this._shardval)
    -    len = paths.length
    -
    -    for (var i = 0; i < len; ++i) {
    -      where[paths[i]] = this._shardval[paths[i]];
    -    }
    -  }
    -
    -  where._id = this._doc._id;
    -  return where;
    -}

    Model#remove([fn])

    Removes this document from the db.

    show code
    Model.prototype.remove = function remove (fn) {
    -  if (this._removing) return this;
    -
    -  var promise = this._removing = new Promise(fn)
    -    , where = this._where()
    -    , self = this
    -    , options = {}
    -
    -  if (this.schema.options.safe) {
    -    options.safe = this.schema.options.safe;
    -  }
    -
    -  this.collection.remove(where, options, tick(function (err) {
    -    if (err) {
    -      promise.error(err);
    -      promise = self = self._removing = where = options = null;
    -      return;
    -    }
    -    self.emit('remove', self);
    -    promise.complete();
    -    promise = self = where = options = null;
    -  }));
    -
    -  return this;
    -};

    Parameters:

    Example:

    - -
    product.remove(function (err, product) {
    -  if (err) return handleError(err);
    -  Product.findById(product._id, function (err, product) {
    -    console.log(product) // null
    -  })
    -})

    Model#_registerHooks()

    Register hooks override

    show code
    Model.prototype._registerHooks = function registerHooks () {
    -  Document.prototype._registerHooks.call(this);
    -};

    Model#model(name)

    Returns another Model instance.

    show code
    Model.prototype.model = function model (name) {
    -  return this.db.model(name);
    -};

    Parameters:

    Example:

    - -
    var doc = new Tank;
    -doc.model('User').findById(id, callback);

    Model#$where(argument)

    Creates a Query and specifies a $where condition.

    Parameters:

    • argument <String, Function> is a javascript string or anonymous function

    Returns:

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    - -
    Blog.$where('this.comments.length &gt; 5');

    Model.init()

    Called when the model compiles.

    show code
    Model.init = function init () {
    -  if (this.schema.options.autoIndex)
    -    this.ensureIndexes();
    -
    -  this.schema.emit('init', this);
    -};

    Model.ensureIndexes([cb])

    Sends ensureIndex commands to mongo for each index declared in the schema.

    show code
    Model.ensureIndexes = function ensureIndexes (cb) {
    -  var indexes = this.schema.indexes();
    -  if (!indexes.length) {
    -    return cb && cb();
    -  }
    -
    -  var self = this
    -    , safe = self.schema.options.safe
    -    , count = indexes.length
    -    , error
    -
    -  indexes.forEach(function (index) {
    -    var options = index[1];
    -    options.safe = safe;
    -    self.collection.ensureIndex(index[0], options, tick(function (err) {
    -      if (err) error = err;
    -      if (--count) return;
    -
    -      self.emit('index', error);
    -      cb && cb(error);
    -    }));
    -  });
    -}

    Parameters:

    After completion, an index event is emitted on this Model passing an error if one occurred.


    Model.remove(conditions, [callback])

    Removes documents from the collection.

    show code
    Model.remove = function remove (conditions, callback) {
    -  if ('function' === typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -  }
    -
    -  var query = new Query(conditions).bind(this, 'remove');
    -
    -  if ('undefined' === typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.remove(callback);
    -};

    Parameters:

    Returns:

    Note:

    - -

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    - -
    Comment.remove({ _id: id }).exec();

    Model.find(conditions, [fields], [options], [callback])

    Finds documents

    show code
    Model.find = function find (conditions, fields, options, callback) {
    -  if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof fields) {
    -    callback = fields;
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof options) {
    -    callback = options;
    -    options = null;
    -  }
    -
    -  var query = new Query(conditions, options);
    -  query.bind(this, 'find');
    -  query.select(fields);
    -
    -  if ('undefined' === typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.find(callback);
    -};

    Parameters:

    Returns:

    Examples:

    - -
    // retrieve only certain keys
    -MyModel.find({ name: /john/i }, 'name friends', function () { })
    -
    -// pass options
    -MyModel.find({ name: /john/i }, null, { skip: 10 } )

    Model._applyNamedScope(query)

    Merges the current named scope query into query.

    show code
    Model._applyNamedScope = function _applyNamedScope (query) {
    -  var cQuery = this._cumulativeQuery;
    -
    -  if (cQuery) {
    -    merge(query._conditions, cQuery._conditions);
    -    if (query._fields && cQuery._fields)
    -      merge(query._fields, cQuery._fields);
    -    if (query.options && cQuery.options)
    -      merge(query.options, cQuery.options);
    -    delete this._cumulativeQuery;
    -  }
    -
    -  return query;
    -}

    Parameters:

    Returns:


    Model.findById(id, [fields], [options], [callback])

    Finds a single document by id.

    show code
    Model.findById = function findById (id, fields, options, callback) {
    -  return this.findOne({ _id: id }, fields, options, callback);
    -};

    Parameters:

    Returns:

    The id is cast to an ObjectId before sending the command.

    - -

    Example:

    - -
    Adventure.findById(id, callback);

    Model.findOne(conditions, [fields], [options], [callback])

    Finds one document.

    show code
    Model.findOne = function findOne (conditions, fields, options, callback) {
    -  if ('function' == typeof options) {
    -    // TODO Handle all 3 of the following scenarios
    -    // Hint: Only some of these scenarios are possible if cQuery is present
    -    // Scenario: findOne(conditions, fields, callback);
    -    // Scenario: findOne(fields, options, callback);
    -    // Scenario: findOne(conditions, options, callback);
    -    callback = options;
    -    options = null;
    -  } else if ('function' == typeof fields) {
    -    // TODO Handle all 2 of the following scenarios
    -    // Scenario: findOne(conditions, callback)
    -    // Scenario: findOne(fields, callback)
    -    // Scenario: findOne(options, callback);
    -    callback = fields;
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -    fields = null;
    -    options = null;
    -  }
    -
    -  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.findOne(callback);
    -};

    Parameters:

    Returns:

    The conditions are cast to their respective SchemaTypes before the command is sent.

    - -

    Example:

    - -
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

    Model.count(conditions, [callback])

    Counts number of matching documents in a database collection.

    show code
    Model.count = function count (conditions, callback) {
    -  if ('function' === typeof conditions)
    -    callback = conditions, conditions = {};
    -
    -  var query = new Query(conditions).bind(this, 'count');
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.count(callback);
    -};

    Parameters:

    Returns:

    Example:

    - -
    Adventure.count({ type: 'jungle' }, function (err, count) {
    -  if (err) ..
    -  console.log('there are %d jungle adventures', count);
    -});

    Model.distinct(field, [conditions], [callback])

    Executes a DISTINCT command

    show code
    Model.distinct = function distinct (field, conditions, callback) {
    -  var query = new Query(conditions).bind(this, 'distinct');
    -  if ('undefined' == typeof callback) {
    -    query._distinctArg = field;
    -    return query;
    -  }
    -
    -  this._applyNamedScope(query);
    -  return query.distinct(field, callback);
    -};

    Parameters:

    Returns:


    Model.where(path, [val])

    Creates a Query, applies the passed conditions, and returns the Query.

    show code
    Model.where = function where (path, val) {
    -  var q = new Query().bind(this, 'find');
    -  return q.where.apply(q, arguments);
    -};

    Parameters:

    Returns:

    For example, instead of writing:

    - -
    User.find({age: {$gte: 21, $lte: 65}}, callback);
    - -

    we can instead write:

    - -
    User.where('age').gte(21).lte(65).exec(callback);
    - -

    Since the Query class also supports where you can continue chaining

    - -
    User
    -.where('age').gte(21).lte(65)
    -.where('name', /^b/i)
    -... etc

    Model.findOneAndUpdate([conditions], [update], [options], [callback])

    Issues a mongodb findAndModify update command.

    show code
    Model.findOneAndUpdate = function (conditions, update, options, callback) {
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = null;
    -  }
    -  else if (1 === arguments.length) {
    -    if ('function' == typeof conditions) {
    -      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
    -
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(update)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate()
    -';
    -      throw new TypeError(msg)
    -    }
    -    update = conditions;
    -    conditions = undefined;
    -  }
    -
    -  var fields;
    -  if (options && options.fields) {
    -    fields = options.fields;
    -    options.fields = undefined;
    -  }
    -
    -  var query = new Query(conditions);
    -  query.setOptions(options);
    -  query.select(fields);
    -  query.bind(this, 'findOneAndUpdate', update);
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.findOneAndUpdate(callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findOneAndUpdate(conditions, update, options, callback) // executes
    -A.findOneAndUpdate(conditions, update, options)  // returns Query
    -A.findOneAndUpdate(conditions, update, callback) // executes
    -A.findOneAndUpdate(conditions, update)           // returns Query
    -A.findOneAndUpdate()                             // returns Query
    - -

    Note:

    - -

    All top level update keys which are not atomic operation names are treated as set operations:

    - -

    Example:

    - -
    var query = { name: 'borne' };
    -Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
    -
    -// is sent as
    -Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
    - -

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    - -

    Note:

    - -

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    - -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    - -

    If you need those features, use the traditional approach of first retrieving the document.

    - -
    Model.findOne({ name: 'borne' }, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.findByIdAndUpdate(id, [update], [options], [callback])

    Issues a mongodb findAndModify update command by a documents id.

    show code
    Model.findByIdAndUpdate = function (id, update, options, callback) {
    -  var args;
    -
    -  if (1 === arguments.length) {
    -    if ('function' == typeof id) {
    -      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
    -
    -'
    -                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
    -'
    -                + '  ' + this.modelName + '.findByIdAndUpdate(id)
    -'
    -                + '  ' + this.modelName + '.findByIdAndUpdate()
    -';
    -      throw new TypeError(msg)
    -    }
    -    return this.findOneAndUpdate({_id: id }, undefined);
    -  }
    -
    -  args = utils.args(arguments, 1);
    -  args.unshift({ _id: id });
    -  return this.findOneAndUpdate.apply(this, args);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findByIdAndUpdate(id, update, options, callback) // executes
    -A.findByIdAndUpdate(id, update, options)  // returns Query
    -A.findByIdAndUpdate(id, update, callback) // executes
    -A.findByIdAndUpdate(id, update)           // returns Query
    -A.findByIdAndUpdate()                     // returns Query
    - -

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    - -

    Note:

    - -

    All top level update keys which are not atomic operation names are treated as set operations:

    - -

    Example:

    - -
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
    -
    -// is sent as
    -Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
    - -

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    - -

    Note:

    - -

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    - -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    - -

    If you need those features, use the traditional approach of first retrieving the document.

    - -
    Model.findById(id, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.findOneAndRemove(conditions, [options], [callback])

    Issue a mongodb findAndModify remove command.

    show code
    Model.findOneAndRemove = function (conditions, options, callback) {
    -  if (1 === arguments.length && 'function' == typeof conditions) {
    -    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
    -
    -'
    -              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
    -'
    -              + '  ' + this.modelName + '.findOneAndRemove(conditions)
    -'
    -              + '  ' + this.modelName + '.findOneAndRemove()
    -';
    -    throw new TypeError(msg)
    -  }
    -
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = undefined;
    -  }
    -
    -  var fields;
    -  if (options) {
    -    fields = options.select;
    -    options.select = undefined;
    -  }
    -
    -  var query = new Query(conditions);
    -  query.setOptions(options);
    -  query.select(fields);
    -  query.bind(this, 'findOneAndRemove');
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.findOneAndRemove(callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    - -

    Executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findOneAndRemove(conditions, options, callback) // executes
    -A.findOneAndRemove(conditions, options)  // return Query
    -A.findOneAndRemove(conditions, callback) // executes
    -A.findOneAndRemove(conditions) // returns Query
    -A.findOneAndRemove()           // returns Query

    Model.findByIdAndRemove(id, [options], [callback])

    Issue a mongodb findAndModify remove command by a documents id.

    show code
    Model.findByIdAndRemove = function (id, options, callback) {
    -  if (1 === arguments.length && 'function' == typeof id) {
    -    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
    -
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove(id)
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove()
    -';
    -    throw new TypeError(msg)
    -  }
    -
    -  return this.findOneAndRemove({ _id: id }, options, callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    - -

    Executes immediately if callback is passed, else a Query object is returned.

    - -

    Options:

    - -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findByIdAndRemove(id, options, callback) // executes
    -A.findByIdAndRemove(id, options)  // return Query
    -A.findByIdAndRemove(id, callback) // executes
    -A.findByIdAndRemove(id) // returns Query
    -A.findByIdAndRemove()           // returns Query

    Model.create(doc, fn)

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    show code
    Model.create = function create (doc, fn) {
    -  if (1 === arguments.length) {
    -    return 'function' === typeof doc && doc(null);
    -  }
    -
    -  var self = this
    -    , docs = [null]
    -    , promise
    -    , count
    -    , args
    -
    -  if (Array.isArray(doc)) {
    -    args = doc;
    -  } else {
    -    args = utils.args(arguments, 0, arguments.length - 1);
    -    fn = arguments[arguments.length - 1];
    -  }
    -
    -  if (0 === args.length) return fn(null);
    -
    -  promise = new Promise(fn);
    -  count = args.length;
    -
    -  args.forEach(function (arg, i) {
    -    var doc = new self(arg);
    -    docs[i+1] = doc;
    -    doc.save(function (err) {
    -      if (err) return promise.error(err);
    -      --count || fn.apply(null, docs);
    -    });
    -  });
    -
    -  // TODO
    -  // utilize collection.insertAll for batch processing?
    -};

    Parameters:

    Example:

    - -
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
    -  if (err) // ...
    -});
    -
    -var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
    -Candy.create(array, function (err, jellybean, snickers) {
    -  if (err) // ...
    -});

    Model.update(conditions, update, [options], [callback])

    Updates documents in the database without returning them.

    show code
    Model.update = function update (conditions, doc, options, callback) {
    -  if (arguments.length < 4) {
    -    if ('function' === typeof options) {
    -      // Scenario: update(conditions, doc, callback)
    -      callback = options;
    -      options = null;
    -    } else if ('function' === typeof doc) {
    -      // Scenario: update(doc, callback);
    -      callback = doc;
    -      doc = conditions;
    -      conditions = {};
    -      options = null;
    -    }
    -  }
    -
    -  var query = new Query(conditions, options).bind(this, 'update', doc);
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.update(doc, callback);
    -};

    Parameters:

    Returns:

    Examples:

    - -
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
    -MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
    -  if (err) return handleError(err);
    -  console.log('The number of updated documents was %d', numberAffected);
    -  console.log('The raw response from Mongo was ', raw);
    -});
    - -

    Valid options:

    - -
      -
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • -
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • -
    • multi (boolean) whether multiple documents should be updated (false)
    • -
    - -

    All update values are cast to their appropriate SchemaTypes before being sent.

    - -

    The callback function receives (err, numberAffected, rawResponse).

    - -
      -
    • err is the error if any occurred
    • -
    • numberAffected is the count of updated documents Mongo reported
    • -
    • rawResponse is the full response from Mongo
    • -
    - -

    Note:

    - -

    All top level keys which are not atomic operation names are treated as set operations:

    - -

    Example:

    - -
    var query = { name: 'borne' };
    -Model.update(query, { name: 'jason borne' }, options, callback)
    -
    -// is sent as
    -Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
    - -

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    - -

    Note:

    - -

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    - -
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
    - -

    Note:

    - -

    Although values are casted to their appropriate types when using update, the following are not applied:

    - -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    - -

    If you need those features, use the traditional approach of first retrieving the document.

    - -
    Model.findOne({ name: 'borne' }, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.mapReduce(o, callback)

    Executes a mapReduce command.

    show code
    Model.mapReduce = function mapReduce (o, callback) {
    -  if ('function' != typeof callback) throw new Error('missing callback');
    -
    -  var self = this;
    -
    -  if (!Model.mapReduce.schema) {
    -    var opts = { noId: true, noVirtualId: true, strict: false }
    -    Model.mapReduce.schema = new Schema({}, opts);
    -  }
    -
    -  if (!o.out) o.out = { inline: 1 };
    -
    -  o.map = String(o.map);
    -  o.reduce = String(o.reduce);
    -
    -  if (o.query) {
    -    var q = new Query(o.query);
    -    q.cast(this);
    -    o.query = q._conditions;
    -    q = undefined;
    -  }
    -
    -  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
    -    if (err) return callback(err);
    -
    -    if (ret.findOne && ret.mapReduce) {
    -      // returned a collection, convert to Model
    -      var model = Model.compile(
    -          '_mapreduce_' + ret.collectionName
    -        , Model.mapReduce.schema
    -        , ret.collectionName
    -        , self.db
    -        , self.base);
    -
    -      model._mapreduce = true;
    -
    -      return callback(err, model, stats);
    -    }
    -
    -    callback(err, ret, stats);
    -  });
    -}

    Parameters:

    • o <Object> an object specifying map-reduce options
    • callback <Function>

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    - -

    Example:

    - -
    var o = {};
    -o.map = function () { emit(this.name, 1) }
    -o.reduce = function (k, vals) { return vals.length }
    -User.mapReduce(o, function (err, results) {
    -  console.log(results)
    -})
    - -

    Other options:

    - -
      -
    • query {Object} query filter object.
    • -
    • limit {Number} max number of documents
    • -
    • keeptemp {Boolean, default:false} keep temporary data
    • -
    • finalize {Function} finalize function
    • -
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • -
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • -
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • -
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • -
    - -

    * out options:

    - -
      -
    • {inline:1} the results are returned in an array
    • -
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • -
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • -
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • -
    - -

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    - -

    Example:

    - -
    var o = {};
    -o.map = function () { emit(this.name, 1) }
    -o.reduce = function (k, vals) { return vals.length }
    -o.out = { replace: 'createdCollectionNameForResults' }
    -o.verbose = true;
    -User.mapReduce(o, function (err, model, stats) {
    -  console.log('map reduce took %d ms', stats.processtime)
    -  model.find().where('value').gt(10).exec(function (err, docs) {
    -    console.log(docs);
    -  });
    -})

    Model.aggregate(array, [options], callback)

    Executes an aggregate command on this models collection.

    show code
    Model.aggregate = function aggregate () {
    -  return this.collection.aggregate.apply(this.collection, arguments);
    -}

    Parameters:

    Example:

    - -
    // find the max age of all users
    -Users.aggregate(
    -    { $group: { _id: null, maxAge: { $max: '$age' }}}
    -  , { $project: { _id: 0, maxAge: 1 }}
    -  , function (err, res) {
    -  if (err) return handleError(err);
    -  console.log(res); // [ { maxAge: 98 } ]
    -});
    - -

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    - -

    NOTE: this requires running MongoDB >= 2.1


    Model#base

    Base Mongoose instance the model uses.


    Model#collection

    Collection the model uses.


    Model#db

    Database instance the model uses.


    Model#schema

    Schema the model uses.


    Model#modelName

    The name of the model


    Model#collection

    Collection the model uses.


    Model#db

    Connection the model uses.


  • namedscope.js

    NamedScope#decorate(target, getters)

    Decorate

    show code
    NamedScope.prototype.decorate = function (target, getters) {
    -  var name = this.name
    -    , block = this.block
    -    , query = this.query;
    -  if (block) {
    -    if (block.length === 0) {
    -      Object.defineProperty(target, name, {
    -        get: getters.block0(block)
    -      });
    -    } else {
    -      target[name] = getters.blockN(block);
    -    }
    -  } else {
    -    Object.defineProperty(target, name, {
    -      get: getters.basic(query)
    -    });
    -  }
    -};
    -
    -NamedScope.prototype.compile = function (model) {
    -  var allScopes = this.scopesByName
    -    , scope;
    -  for (var k in allScopes) {
    -    scope = allScopes[k];
    -    scope.decorate(model, {
    -      block0: function (block) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          block.call(cquery);
    -          return this;
    -        };
    -      },
    -      blockN: function (block) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          block.apply(cquery, arguments);
    -          return this;
    -        };
    -      },
    -      basic: function (query) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          cquery.find(query);
    -          return this;
    -        };
    -      }
    -    });
    -  }
    -};
    -
    -module.exports = NamedScope;

    Parameters:


  • promise.js

    Promise(back)

    Promise constructor.

    show code
    function Promise (back) {
    -  this.emitted = {};
    -  if ('function' == typeof back)
    -    this.addBack(back);
    -};

    Parameters:

    • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

    Events:

    • err: Emits when the promise resolves to an error.

    • complete: Emits when the promise resolves sucessfully.


    Promise#on(event, callback)

    Adds listener to the event.

    show code
    Promise.prototype.on = function (event, callback) {
    -  if (this.emitted[event])
    -    callback.apply(this, this.emitted[event]);
    -  else
    -    EventEmitter.prototype.on.call(this, event, callback);
    -
    -  return this;
    -};

    Parameters:

    Returns:

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


    Promise#emit()

    Keeps track of emitted events to run them on on.

    show code
    Promise.prototype.emit = function (event) {
    -  // ensures a promise can't be complete() or error() twice
    -  if (event == 'err' || event == 'complete'){
    -    if (this.emitted.err || this.emitted.complete) {
    -      return this;
    -    }
    -    this.emitted[event] = util.args(arguments, 1);
    -  }
    -
    -  return EventEmitter.prototype.emit.apply(this, arguments);
    -};

    Promise#complete()

    Shortcut for emitting the complete event.

    show code
    Promise.prototype.complete = function () {
    -  var args = util.args(arguments);
    -  return this.emit.apply(this, ['complete'].concat(args));
    -};

    Promise#error()

    Shortcut for emitting the err event.

    show code
    Promise.prototype.error = function (err) {
    -  if (!(err instanceof Error)) err = new Error(err);
    -  return this.emit('err', err);
    -};

    Returns:


    Promise#addCallback()

    Shortcut for .on('complete', fn).

    show code
    Promise.prototype.addCallback = function (fn) {
    -  return this.on('complete', fn);
    -};

    Returns:


    Promise#addErrback()

    Shortcut for .on('err', fn).

    show code
    Promise.prototype.addErrback = function (fn) {
    -  return this.on('err', fn);
    -};

    Returns:


    Promise#addBack(fn)

    Adds a single function that's both a callback and errback.

    show code
    Promise.prototype.addBack = function (fn) {
    -  this.on('err', function(err){
    -    fn.call(this, err);
    -  });
    -
    -  this.on('complete', function(){
    -    var args = util.args(arguments);
    -    fn.apply(this, [null].concat(args));
    -  });
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Promise#resolve(err, val)

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    show code
    Promise.prototype.resolve = function (err, val) {
    -  if (err) return this.error(err);
    -  return this.complete(val);
    -};

    Parameters:

    • err <Error> optional error or null
    • val <Object> value to complete the promise with

  • query.js

    Query(criteria, options)

    Query constructor used for building queries.

    show code
    function Query (criteria, options) {
    -  this.setOptions(options, true);
    -  this._conditions = {};
    -  this._updateArg = {};
    -  this._fields = undefined;
    -  if (criteria) this.find(criteria);
    -}

    Parameters:

    Example:

    - -
    var query = Model.find();
    -query.where('age').gte(21).exec(callback);

    Query#setOptions(options)

    Sets query options.

    show code
    Query.prototype.setOptions = function (options, overwrite) {
    -  // overwrite is internal use only
    -  if (overwrite) {
    -    options = this.options = options || {};
    -    this.safe = options.safe
    -
    -    // normalize population options
    -    var pop = this.options.populate;
    -    this.options.populate = {};
    -
    -    if (pop && Array.isArray(pop)) {
    -      for (var i = 0, l = pop.length; i < l; i++) {
    -        this.options.populate[pop[i]] = {};
    -      }
    -    }
    -
    -    return this;
    -  }
    -
    -  if (!(options && 'Object' == options.constructor.name))
    -    return this;
    -
    -  if ('safe' in options)
    -    this.safe = options.safe;
    -
    -  // set arbitrary options
    -  var methods = Object.keys(options)
    -    , i = methods.length
    -    , method
    -
    -  while (i--) {
    -    method = methods[i];
    -
    -    // use methods if exist (safer option manipulation)
    -    if ('function' == typeof this[method]) {
    -      var args = Array.isArray(options[method])
    -        ? options[method]
    -        : [options[method]];
    -      this[method].apply(this, args)
    -    } else {
    -      this.options[method] = options[method];
    -    }
    -  }
    -  return this;
    -}

    Parameters:

    Options:

    - - - -

    * denotes a query helper method is also available


    Query#bind(model, op, updateArg)

    Binds this query to a model.

    show code
    Query.prototype.bind = function bind (model, op, updateArg) {
    -  this.model = model;
    -  this.op = op;
    -
    -  if (model._mapreduce) this.options.lean = true;
    -
    -  if (op == 'update' || op == 'findOneAndUpdate') {
    -    merge(this._updateArg, updateArg || {});
    -  }
    -
    -  return this;
    -};

    Parameters:

    • model <Model> the model to which the query is bound
    • op <String> the operation to execute
    • updateArg <Object> used in update methods

    Returns:


    Query#exec([operation], [callback])

    Executes the query

    show code
    Query.prototype.exec = function exec (op, callback) {
    -  var promise = new Promise();
    -
    -  switch (typeof op) {
    -    case 'function':
    -      callback = op;
    -      op = null;
    -      break;
    -    case 'string':
    -      this.op = op;
    -      break;
    -  }
    -
    -  if (callback) promise.addBack(callback);
    -
    -  if (!this.op) {
    -    promise.complete();
    -    return promise;
    -  }
    -
    -  if ('update' == this.op) {
    -    this[this.op](this._updateArg, promise.resolve.bind(promise));
    -    return promise;
    -  }
    -
    -  if ('distinct' == this.op) {
    -    this.distinct(this._distinctArg, promise.resolve.bind(promise));
    -    return promise;
    -  }
    -
    -  this[this.op](promise.resolve.bind(promise));
    -  return promise;
    -};

    Parameters:

    Returns:

    Examples

    - -
    query.exec();
    -query.exec(callback);
    -query.exec('update');
    -query.exec('find', callback);

    Query#find([criteria], [callback])

    Finds documents.

    show code
    Query.prototype.find = function (criteria, callback) {
    -  this.op = 'find';
    -  if ('function' === typeof criteria) {
    -    callback = criteria;
    -    criteria = {};
    -  } else if (criteria instanceof Query) {
    -    // TODO Merge options, too
    -    merge(this._conditions, criteria._conditions);
    -  } else if (criteria instanceof Document) {
    -    merge(this._conditions, criteria.toObject());
    -  } else if (criteria && 'Object' === criteria.constructor.name) {
    -    merge(this._conditions, criteria);
    -  }
    -  if (!callback) return this;
    -  return this.execFind(callback);
    -};

    Parameters:

    Returns:

    When no callback is passed, the query is not executed.

    - -

    Example

    - -
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)

    Query#cast(model, [obj])

    Casts this query to the schema of model

    show code
    Query.prototype.cast = function (model, obj) {
    -  obj || (obj= this._conditions);
    -
    -  var schema = model.schema
    -    , paths = Object.keys(obj)
    -    , i = paths.length
    -    , any$conditionals
    -    , schematype
    -    , nested
    -    , path
    -    , type
    -    , val;
    -
    -  while (i--) {
    -    path = paths[i];
    -    val = obj[path];
    -
    -    if ('$or' === path || '$nor' === path) {
    -      var k = val.length
    -        , orComponentQuery;
    -
    -      while (k--) {
    -        orComponentQuery = new Query(val[k]);
    -        orComponentQuery.cast(model);
    -        val[k] = orComponentQuery._conditions;
    -      }
    -
    -    } else if (path === '$where') {
    -      type = typeof val;
    -
    -      if ('string' !== type && 'function' !== type) {
    -        throw new Error("Must have a string or function for $where");
    -      }
    -
    -      if ('function' === type) {
    -        obj[path] = val.toString();
    -      }
    -
    -      continue;
    -
    -    } else {
    -
    -      if (!schema) {
    -        // no casting for Mixed types
    -        continue;
    -      }
    -
    -      schematype = schema.path(path);
    -
    -      if (!schematype) {
    -        // Handle potential embedded array queries
    -        var split = path.split('.')
    -          , j = split.length
    -          , pathFirstHalf
    -          , pathLastHalf
    -          , remainingConds
    -          , castingQuery;
    -
    -        // Find the part of the var path that is a path of the Schema
    -        while (j--) {
    -          pathFirstHalf = split.slice(0, j).join('.');
    -          schematype = schema.path(pathFirstHalf);
    -          if (schematype) break;
    -        }
    -
    -        // If a substring of the input path resolves to an actual real path...
    -        if (schematype) {
    -          // Apply the casting; similar code for $elemMatch in schema/array.js
    -          if (schematype.caster && schematype.caster.schema) {
    -            remainingConds = {};
    -            pathLastHalf = split.slice(j).join('.');
    -            remainingConds[pathLastHalf] = val;
    -            castingQuery = new Query(remainingConds);
    -            castingQuery.cast(schematype.caster);
    -            obj[path] = castingQuery._conditions[pathLastHalf];
    -          } else {
    -            obj[path] = val;
    -          }
    -        }
    -
    -      } else if (val === null || val === undefined) {
    -        continue;
    -      } else if ('Object' === val.constructor.name) {
    -
    -        any$conditionals = Object.keys(val).some(function (k) {
    -          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
    -        });
    -
    -        if (!any$conditionals) {
    -          obj[path] = schematype.castForQuery(val);
    -        } else {
    -
    -          var ks = Object.keys(val)
    -            , k = ks.length
    -            , $cond;
    -
    -          while (k--) {
    -            $cond = ks[k];
    -            nested = val[$cond];
    -
    -            if ('$exists' === $cond) {
    -              if ('boolean' !== typeof nested) {
    -                throw new Error("$exists parameter must be Boolean");
    -              }
    -              continue;
    -            }
    -
    -            if ('$type' === $cond) {
    -              if ('number' !== typeof nested) {
    -                throw new Error("$type parameter must be Number");
    -              }
    -              continue;
    -            }
    -
    -            if ('$not' === $cond) {
    -              this.cast(model, nested);
    -            } else {
    -              val[$cond] = schematype.castForQuery($cond, nested);
    -            }
    -          }
    -        }
    -      } else {
    -        obj[path] = schematype.castForQuery(val);
    -      }
    -    }
    -  }
    -
    -  return obj;
    -};

    Parameters:

    Returns:

    Note

    - -

    If obj is present, it is cast instead of this query.


    Query#_optionsForExec(model)

    Returns default options.

    show code
    Query.prototype._optionsForExec = function (model) {
    -  var options = utils.clone(this.options, { retainKeyOrder: true });
    -  delete options.populate;
    -
    -  if (!('batchSize' in options))
    -    options.batchSize = 1000;
    -
    -  if (!('safe' in options))
    -    options.safe = model.schema.options.safe;
    -
    -  if (!('readPreference' in options) && model.schema.options.read)
    -    options.readPreference = model.schema.options.read;
    -
    -  return options;
    -};

    Parameters:


    Query#_applyPaths()

    Applies schematype selected options to this query.

    show code
    Query.prototype._applyPaths = function applyPaths () {
    -  // determine if query is selecting or excluding fields
    -
    -  var fields = this._fields
    -    , exclude
    -    , keys
    -    , ki
    -
    -  if (fields) {
    -    keys = Object.keys(fields);
    -    ki = keys.length;
    -
    -    while (ki--) {
    -      if ('+' == keys[ki][0]) continue;
    -      exclude = 0 === fields[keys[ki]];
    -      break;
    -    }
    -  }
    -
    -  // if selecting, apply default schematype select:true fields
    -  // if excluding, apply schematype select:false fields
    -
    -  var selected = []
    -    , excluded = []
    -    , seen = [];
    -
    -  analyzeSchema(this.model.schema);
    -
    -  switch (exclude) {
    -    case true:
    -      excluded.length && this.select('-' + excluded.join(' -'));
    -      break;
    -    case false:
    -      selected.length && this.select(selected.join(' '));
    -      break;
    -    case undefined:
    -      // user didn't specify fields, implies returning all fields.
    -      // only need to apply excluded fields
    -      excluded.length && this.select('-' + excluded.join(' -'));
    -      break;
    -  }
    -
    -  return seen = excluded = selected = keys = fields = null;
    -
    -  function analyzeSchema (schema, prefix) {
    -    prefix || (prefix = '');
    -
    -    // avoid recursion
    -    if (~seen.indexOf(schema)) return;
    -    seen.push(schema);
    -
    -    schema.eachPath(function (path, type) {
    -      if (prefix) path = prefix + '.' + path;
    -
    -      // array of subdocs?
    -      if (type.schema) {
    -        analyzeSchema(type.schema, path);
    -      }
    -
    -      analyzePath(path, type);
    -    });
    -  }
    -
    -  function analyzePath (path, type) {
    -    if ('boolean' != typeof type.selected) return;
    -
    -    if (fields && ('+' + path) in fields) {
    -      // forced inclusion
    -      delete fields['+' + path];
    -
    -      // if there are other fields being included, add this one
    -      // if no other included fields, leave this out (implied inclusion)
    -      if (false === exclude && keys.length > 1) {
    -        fields[path] = 1;
    -      }
    -
    -      return
    -    };
    -
    -    ;(type.selected ? selected : excluded).push(path);
    -  }
    -}

    Query#$where(js)

    Specifies a $where condition

    Parameters:

    Returns:

    Use $where when you need to select documents using a JavaScript expression.

    - -

    Example

    - -
    query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
    -
    -query.$where(function () {
    -  return this.comments.length &gt; 10 || this.name.length &gt; 5;
    -})

    Query#where([path], [val])

    Specifies a path for use with chaining.

    show code
    Query.prototype.where = function (path, val) {
    -  if (!arguments.length) return this;
    -
    -  if ('string' != typeof path) {
    -    throw new TypeError('path must be a string');
    -  }
    -
    -  this._currPath = path;
    -
    -  if (2 === arguments.length) {
    -    this._conditions[path] = val;
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    // instead of writing:
    -User.find({age: {$gte: 21, $lte: 65}}, callback);
    -
    -// we can instead write:
    -User.where('age').gte(21).lte(65);
    -
    -// Moreover, you can also chain a bunch of these together:
    -
    -User
    -.where('age').gte(21).lte(65)
    -.where('name', /^b/i)
    -.where('friends').slice(10)
    -.exec(callback)

    Query#equals(val)

    Specifies the complementary comparison value for paths specified with where()

    show code
    Query.prototype.equals = function equals (val) {
    -  var path = this._currPath;
    -  if (!path) throw new Error('equals() must be used after where()');
    -  this._conditions[path] = val;
    -  return this;
    -}

    Parameters:

    Returns:

    Example

    - -
    User.where('age').equals(49);
    -
    -// is the same as
    -
    -User.where('age', 49);

    Query#or(array)

    Specifies arguments for an $or condition.

    show code
    Query.prototype.or = function or (array) {
    -  var or = this._conditions.$or || (this._conditions.$or = []);
    -  if (!Array.isArray(array)) array = [array];
    -  or.push.apply(or, array);
    -  return this;
    -}

    Parameters:

    • array <Array> array of conditions

    Returns:

    Example

    - -
    query.or([{ color: 'red' }, { status: 'emergency' }])

    Query#nor(array)

    Specifies arguments for a $nor condition.

    show code
    Query.prototype.nor = function nor (array) {
    -  var nor = this._conditions.$nor || (this._conditions.$nor = []);
    -  if (!Array.isArray(array)) array = [array];
    -  nor.push.apply(nor, array);
    -  return this;
    -}

    Parameters:

    • array <Array> array of conditions

    Returns:

    Example

    - -
    query.nor([{ color: 'green' }, { status: 'ok' }])

    Query#gt(path, val)

    Specifies a $gt query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.

    - -

    Example

    - -
    Thing.find().where('age').gt(21)
    -
    -// or
    -Thing.find().gt('age', 21)

    Query#gte(path, val)

    Specifies a $gte query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#lt(path, val)

    Specifies a $lt query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#lte(path, val)

    Specifies a $lte query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#ne(path, val)

    Specifies a $ne query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#in(path, val)

    Specifies an $in query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#nin(path, val)

    Specifies an $nin query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#all(path, val)

    Specifies an $all query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#size(path, val)

    Specifies an $size query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#regex(path, val)

    Specifies a $regex query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#maxDistance(path, val)

    Specifies a $maxDistance query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#near(path, val)

    Specifies a $near condition

    show code
    Query.prototype.near = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$near = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#nearSphere(path, val)

    Specifies a $nearSphere condition.

    show code
    Query.prototype.nearSphere = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$nearSphere = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#mod(path, val)

    Specifies a $mod condition

    show code
    Query.prototype.mod = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$mod = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#exists(path, val)

    Specifies an $exists condition

    show code
    Query.prototype.exists = function (path, val) {
    -  if (arguments.length === 0) {
    -    path = this._currPath
    -    val = true;
    -  } else if (arguments.length === 1) {
    -    if ('boolean' === typeof path) {
    -      val = path;
    -      path = this._currPath;
    -    } else {
    -      val = true;
    -    }
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$exists'] = val;
    -  return this;
    -};

    Parameters:

    Returns:


    Query#elemMatch(path, criteria)

    Specifies an $elemMatch condition

    show code
    Query.prototype.elemMatch = function (path, criteria) {
    -  var block;
    -  if ('Object' === path.constructor.name) {
    -    criteria = path;
    -    path = this._currPath;
    -  } else if ('function' === typeof path) {
    -    block = path;
    -    path = this._currPath;
    -  } else if ('Object' === criteria.constructor.name) {
    -  } else if ('function' === typeof criteria) {
    -    block = criteria;
    -  } else {
    -    throw new Error("Argument error");
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  if (block) {
    -    criteria = new Query();
    -    block(criteria);
    -    conds['$elemMatch'] = criteria._conditions;
    -  } else {
    -    conds['$elemMatch'] = criteria;
    -  }
    -  return this;
    -};
    -
    -// Spatial queries

    Parameters:

    Returns:

    Example

    - -
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
    -
    -query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
    -
    -query.elemMatch('comment', function (elem) {
    -  elem.where('author').equals('autobot');
    -  elem.where('votes').gte(5);
    -})
    -
    -query.where('comment').elemMatch(function (elem) {
    -  elem.where('author').equals('autobot');
    -  elem.where('votes').gte(5);
    -})

    Query#box(path, val)

    Specifies a $box condition

    show code
    Query.prototype.box = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$box': [val.ll, val.ur]  };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var lowerLeft = [40.73083, -73.99756]
    -var upperRight= [40.741404,  -73.988135]
    -query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

    Query#center(path, val, [opts])

    Specifies a $center condition

    show code
    Query.prototype.center = function (path, val, opts) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$center': [val.center, val.radius]  };
    -
    -  // copy any options
    -  if (opts && 'Object' == opts.constructor.name) {
    -    utils.options(opts, conds.$within);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var area = { center: [50, 50], radius: 10 }
    -query.where('loc').within.center(area)

    Query#centerSphere(path, val)

    Specifies a $centerSphere condition

    show code
    Query.prototype.centerSphere = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var area = { center: [50, 50], radius: 10 }
    -query.where('loc').within.centerSphere(area)

    Query#polygon(path, val)

    Specifies a $polygon condition

    show code
    Query.prototype.polygon = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$polygon': val };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
    -query.where('loc').within.polygon(polyA)
    -
    -// or
    -var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
    -query.where('loc').within.polygon(polyB)

    Query#select(arg)

    Specifies which document fields to include or exclude

    show code
    Query.prototype.select = function select (arg) {
    -  if (!arg) return this;
    -
    -  var fields = this._fields || (this._fields = {});
    -
    -  if ('Object' === arg.constructor.name) {
    -    Object.keys(arg).forEach(function (field) {
    -      fields[field] = arg[field];
    -    });
    -  } else if (1 === arguments.length && 'string' == typeof arg) {
    -    arg.split(/\s+/).forEach(function (field) {
    -      if (!field) return;
    -      var include = '-' == field[0] ? 0 : 1;
    -      if (include === 0) field = field.substring(1);
    -      fields[field] = include;
    -    });
    -  } else {
    -    throw new TypeError('Invalid select() argument. Must be a string or object.');
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    - -

    Example

    - -
    // include a and b, exclude c
    -query.select('a b -c');
    -
    -// or you may use object notation, useful when
    -// you have keys already prefixed with a "-"
    -query.select({a: 1, b: 1, c: 0});
    -
    -// force inclusion of field excluded at schema level
    -query.select('+path')
    - -

    NOTE:

    - -

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


    Query#slice(path, val)

    Specifies a $slice condition

    show code
    Query.prototype.slice = function (path, val) {
    -  if (arguments.length === 1) {
    -      val = path;
    -      path = this._currPath
    -  } else if (arguments.length === 2) {
    -    if ('number' === typeof path) {
    -      val = [path, val];
    -      path = this._currPath;
    -    }
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var myFields = this._fields || (this._fields = {});
    -  myFields[path] = { '$slice': val };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    query.slice('comments', 5)
    -query.slice('comments', -5)
    -query.slice('comments', [10, 5])
    -query.where('comments').slice(5)
    -query.where('comments').slice([-10, 5])

    Query#sort(arg)

    Sets the sort order

    show code
    Query.prototype.sort = function (arg) {
    -  if (!arg) return this;
    -
    -  var sort = this.options.sort || (this.options.sort = []);
    -
    -  if ('Object' === arg.constructor.name) {
    -    Object.keys(arg).forEach(function (field) {
    -      push(sort, field, arg[field]);
    -    });
    -  } else if (1 === arguments.length && 'string' == typeof arg) {
    -    arg.split(/\s+/).forEach(function (field) {
    -      if (!field) return;
    -      var ascend = '-' == field[0] ? -1 : 1;
    -      if (ascend === -1) field = field.substring(1);
    -      push(sort, field, ascend);
    -    });
    -  } else {
    -    throw new TypeError('Invalid sort() argument. Must be a string or object.');
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    - -

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    - -

    Example

    - -
    // these are equivalent
    -query.sort({ field: 'asc', test: -1 });
    -query.sort('field -test');

    Query#limit(val)

    Specifies the limit option.

    Parameters:

    Example

    - -
    Kitten.find().limit(20)

    Query#skip(val)

    Specifies the skip option.

    Parameters:

    Example

    - -
    Kitten.find().skip(100).limit(20)

    Query#maxscan(val)

    Specifies the maxscan option.

    Parameters:

    Example

    - -
    Kitten.find().maxscan(100)

    Query#batchSize(val)

    Specifies the batchSize option.

    Parameters:

    Example

    - -
    Kitten.find().batchSize(100)

    Query#comment(val)

    Specifies the comment option.

    Parameters:

    Example

    - -
    Kitten.findOne(condition).comment('login query')

    Query#snapshot()

    Specifies this query as a snapshot query.

    show code
    Query.prototype.snapshot = function () {
    -  this.options.snapshot = true;
    -  return this;
    -};

    Returns:

    Example

    - -
    Kitten.find().snapshot()

    Query#hint(val)

    Sets query hints.

    show code
    Query.prototype.hint = function (val) {
    -  if (!val) return this;
    -
    -  var hint = this.options.hint || (this.options.hint = {});
    -
    -  if ('Object' === val.constructor.name) {
    -    // must keep object keys in order so don't use Object.keys()
    -    for (var k in val) {
    -      hint[k] = val[k];
    -    }
    -  } else {
    -    throw new TypeError('Invalid hint. ' + val);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Model.find().hint({ indexA: 1, indexB: -1})

    Query#slaveOk(v)

    Sets the slaveOk option.

    show code
    Query.prototype.slaveOk = function (v) {
    -  this.options.slaveOk = arguments.length ? !!v : true;
    -  return this;
    -}

    Parameters:

    Returns:

    Example:

    - -
    new Query().slaveOk() // true
    -new Query().slaveOk(true)
    -new Query().slaveOk(false)

    Query#read(pref, [tags])

    Sets the readPreference option for the query.

    show code
    Query.prototype.read = function (pref, tags) {
    -  this.options.readPreference = utils.readPref(pref, tags);
    -  return this;
    -}

    Parameters:

    • pref <String> one of the listed preference options or their aliases
    • [tags] <Array> optional tags for this query

    Returns:

    Example:

    - -
    new Query().read('primary')
    -new Query().read('p')  // same as primary
    -
    -new Query().read('primaryPreferred')
    -new Query().read('pp') // same as primaryPreferred
    -
    -new Query().read('secondary')
    -new Query().read('s')  // same as secondary
    -
    -new Query().read('secondaryPreferred')
    -new Query().read('sp') // same as secondaryPreferred
    -
    -new Query().read('nearest')
    -new Query().read('n')  // same as nearest
    -
    -// with tags
    -new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
    - -

    Preferences:

    - -
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
    -secondary            Read from secondary if available, otherwise error.
    -primaryPreferred     Read from primary if available, otherwise a secondary.
    -secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
    -nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
    - -

    Aliases

    - -
    p   primary
    -pp  primaryPreferred
    -s   secondary
    -sp  secondaryPreferred
    -n   nearest
    - -

    Read more about how to use read preferrences here and here.


    Query#lean(v)

    Sets the lean option.

    show code
    Query.prototype.lean = function (v) {
    -  this.options.lean = arguments.length ? !!v : true;
    -  return this;
    -}

    Parameters:

    Returns:

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    - -

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    - -

    Example:

    - -
    new Query().lean() // true
    -new Query().lean(true)
    -new Query().lean(false)
    -
    -Model.find().lean().exec();
    -
    -var leanStream = Model.find().lean().stream();

    Query#tailable(v)

    Sets tailable option.

    show code
    Query.prototype.tailable = function (v) {
    -  this.options.tailable = arguments.length ? !!v : true;
    -  return this;
    -};

    Parameters:

    Example

    - -
    Kitten.find().tailable() &lt;== true
    -Kitten.find().tailable(true)
    -Kitten.find().tailable(false)

    Query#execFind(callback)

    Executes the query as a find() operation.

    show code
    Query.prototype.execFind = function (callback) {
    -  var model = this.model
    -    , promise = new Promise(callback);
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    promise.error(err);
    -    return this;
    -  }
    -
    -  // apply default schematype path selections
    -  this._applyPaths();
    -
    -  var self = this
    -    , castQuery = this._conditions
    -    , options = this._optionsForExec(model)
    -    , fields = utils.clone(this._fields)
    -
    -  options.fields = this._castFields(fields);
    -  if (options.fields instanceof Error) {
    -    promise.error(options.fields);
    -    return this;
    -  }
    -
    -  model.collection.find(castQuery, options, function (err, cursor) {
    -    if (err) return promise.error(err);
    -    cursor.toArray(tick(cb));
    -  });
    -
    -  function cb (err, docs) {
    -    if (err) return promise.error(err);
    -
    -    if (true === options.lean)
    -      return promise.complete(docs);
    -
    -    var arr = []
    -      , count = docs.length;
    -
    -    if (!count) return promise.complete([]);
    -
    -    for (var i = 0, l = docs.length; i < l; i++) {
    -      arr[i] = new model(undefined, fields, true);
    -      arr[i].init(docs[i], self, function (err) {
    -        if (err) return promise.error(err);
    -        --count || promise.complete(arr);
    -      });
    -    }
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Query#findOne(callback)

    Executes the query as a findOne() operation.

    show code
    Query.prototype.findOne = function (callback) {
    -  this.op = 'findOne';
    -
    -  if (!callback) return this;
    -
    -  var model = this.model;
    -  var promise = new Promise(callback);
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    promise.error(err);
    -    return this;
    -  }
    -
    -  // apply default schematype path selections
    -  this._applyPaths();
    -
    -  var self = this
    -    , castQuery = this._conditions
    -    , options = this._optionsForExec(model)
    -    , fields = utils.clone(this._fields)
    -
    -  options.fields = this._castFields(fields);
    -  if (options.fields instanceof Error) {
    -    promise.error(options.fields);
    -    return this;
    -  }
    -
    -  model.collection.findOne(castQuery, options, tick(function (err, doc) {
    -    if (err) return promise.error(err);
    -    if (!doc) return promise.complete(null);
    -
    -    if (true === options.lean) return promise.complete(doc);
    -
    -    var casted = new model(undefined, fields, true);
    -    casted.init(doc, self, function (err) {
    -      if (err) return promise.error(err);
    -      promise.complete(casted);
    -    });
    -  }));
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Kitten.where('color', 'white').findOne(function (err, kitten) {
    -  if (err) return handleError(err);
    -
    -  // kitten may be null if no document matched
    -  if (kitten) {
    -    ...
    -  }
    -})

    Query#count(callback)

    Exectues the query as a count() operation.

    show code
    Query.prototype.count = function (callback) {
    -  this.op = 'count';
    -  var model = this.model;
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    return callback(err);
    -  }
    -
    -  var castQuery = this._conditions;
    -  model.collection.count(castQuery, tick(callback));
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Kitten.where('color', 'black').count(function (err, count) {
    -  if (err) return handleError(err);
    -  console.log('there are %d black kittens', count);
    -})

    Query#distinct(field, callback)

    Executes this query as a distict() operation.

    show code
    Query.prototype.distinct = function (field, callback) {
    -  this.op = 'distinct';
    -  var model = this.model;
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    return callback(err);
    -  }
    -
    -  var castQuery = this._conditions;
    -  model.collection.distinct(field, castQuery, tick(callback));
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Query#update(doc, callback)

    Executes this query as an update() operation.

    show code
    Query.prototype.update = function update (doc, callback) {
    -  this.op = 'update';
    -  this._updateArg = doc;
    -
    -  var model = this.model
    -    , options = this._optionsForExec(model)
    -    , fn = 'function' == typeof callback
    -    , castedQuery
    -    , castedDoc
    -
    -  castedQuery = castQuery(this);
    -  if (castedQuery instanceof Error) {
    -    if (fn) {
    -      process.nextTick(callback.bind(null, castedQuery));
    -      return this;
    -    }
    -    throw castedQuery;
    -  }
    -
    -  castedDoc = castDoc(this);
    -  if (!castedDoc) {
    -    fn && process.nextTick(callback.bind(null, null, 0));
    -    return this;
    -  }
    -
    -  if (castedDoc instanceof Error) {
    -    if (fn) {
    -      process.nextTick(callback.bind(null, castedDoc));
    -      return this;
    -    }
    -    throw castedDoc;
    -  }
    -
    -  if (!fn) {
    -    delete options.safe;
    -  }
    -
    -  model.collection.update(castedQuery, castedDoc, options, tick(callback));
    -  return this;
    -};

    Parameters:

    Returns:

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    - -

    Example

    - -
    Model.update({..}, { title: 'remove words' }, ...)
    - -

    becomes

    - -
    Model.update({..}, { $set: { title: 'remove words' }}, ...)
    - -

    Note

    - -

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


    Query#_castUpdate(obj)

    Casts obj for an update command.

    show code
    Query.prototype._castUpdate = function _castUpdate (obj) {
    -  var ops = Object.keys(obj)
    -    , i = ops.length
    -    , ret = {}
    -    , hasKeys
    -    , val
    -
    -  while (i--) {
    -    var op = ops[i];
    -    if ('$' !== op[0]) {
    -      // fix up $set sugar
    -      if (!ret.$set) {
    -        if (obj.$set) {
    -          ret.$set = obj.$set;
    -        } else {
    -          ret.$set = {};
    -        }
    -      }
    -      ret.$set[op] = obj[op];
    -      ops.splice(i, 1);
    -      if (!~ops.indexOf('$set')) ops.push('$set');
    -    } else if ('$set' === op) {
    -      if (!ret.$set) {
    -        ret[op] = obj[op];
    -      }
    -    } else {
    -      ret[op] = obj[op];
    -    }
    -  }
    -
    -  // cast each value
    -  i = ops.length;
    -
    -  while (i--) {
    -    op = ops[i];
    -    val = ret[op];
    -    if ('Object' === val.constructor.name) {
    -      hasKeys |= this._walkUpdatePath(val, op);
    -    } else {
    -      var msg = 'Invalid atomic update value for ' + op + '. '
    -              + 'Expected an object, received ' + typeof val;
    -      throw new Error(msg);
    -    }
    -  }
    -
    -  return hasKeys && ret;
    -}

    Parameters:

    Returns:

    • <Object> obj after casting its values

    Query#_walkUpdatePath(obj, op, pref)

    Walk each path of obj and cast its values
    according to its schema.

    show code
    Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
    -  var strict = this.model.schema.options.strict
    -    , prefix = pref ? pref + '.' : ''
    -    , keys = Object.keys(obj)
    -    , i = keys.length
    -    , hasKeys = false
    -    , schema
    -    , key
    -    , val
    -
    -  while (i--) {
    -    key = keys[i];
    -    val = obj[key];
    -
    -    if (val && 'Object' === val.constructor.name) {
    -      // watch for embedded doc schemas
    -      schema = this._getSchema(prefix + key);
    -      if (schema && schema.caster && op in castOps) {
    -        // embedded doc schema
    -
    -        if (strict && !schema) {
    -          // path is not in our strict schema
    -          if ('throw' == strict) {
    -            throw new Error('Field `' + key + '` is not in schema.');
    -          } else {
    -            // ignore paths not specified in schema
    -            delete obj[key];
    -          }
    -        } else {
    -          hasKeys = true;
    -          if ('$each' in val) {
    -            obj[key] = {
    -                $each: this._castUpdateVal(schema, val.$each, op)
    -            }
    -          } else {
    -            obj[key] = this._castUpdateVal(schema, val, op);
    -          }
    -        }
    -      } else {
    -        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
    -      }
    -    } else {
    -      schema = '$each' === key
    -        ? this._getSchema(pref)
    -        : this._getSchema(prefix + key);
    -
    -      var skip = strict &&
    -                 !schema &&
    -                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
    -
    -      if (skip) {
    -        if ('throw' == strict) {
    -          throw new Error('Field `' + prefix + key + '` is not in schema.');
    -        } else {
    -          delete obj[key];
    -        }
    -      } else {
    -        hasKeys = true;
    -        obj[key] = this._castUpdateVal(schema, val, op, key);
    -      }
    -    }
    -  }
    -  return hasKeys;
    -}

    Parameters:

    • obj <Object> - part of a query
    • op <String> - the atomic operator ($pull, $set, etc)
    • pref <String> - path prefix (internal only)

    Returns:

    • <Bool> true if this path has keys to update

    Query#_castUpdateVal(schema, val, op, [$conditional])

    Casts val according to schema and atomic op.

    show code
    Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
    -  if (!schema) {
    -    // non-existing schema path
    -    return op in numberOps
    -      ? Number(val)
    -      : val
    -  }
    -
    -  if (schema.caster && op in castOps &&
    -    ('Object' === val.constructor.name || Array.isArray(val))) {
    -    // Cast values for ops that add data to MongoDB.
    -    // Ensures embedded documents get ObjectIds etc.
    -    var tmp = schema.cast(val);
    -
    -    if (Array.isArray(val)) {
    -      val = tmp;
    -    } else {
    -      val = tmp[0];
    -    }
    -  }
    -
    -  if (op in numberOps) return Number(val);
    -  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
    -  return schema.castForQuery(val)
    -}

    Parameters:


    Query#_getSchema(path)

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    show code
    Query.prototype._getSchema = function _getSchema (path) {
    -  var schema = this.model.schema
    -    , pathschema = schema.path(path);
    -
    -  if (pathschema)
    -    return pathschema;
    -
    -  // look for arrays
    -  return (function search (parts, schema) {
    -    var p = parts.length + 1
    -      , foundschema
    -      , trypath
    -
    -    while (p--) {
    -      trypath = parts.slice(0, p).join('.');
    -      foundschema = schema.path(trypath);
    -      if (foundschema) {
    -        if (foundschema.caster) {
    -
    -          // array of Mixed?
    -          if (foundschema.caster instanceof Types.Mixed) {
    -            return foundschema.caster;
    -          }
    -
    -          // Now that we found the array, we need to check if there
    -          // are remaining document paths to look up for casting.
    -          // Also we need to handle array.$.path since schema.path
    -          // doesn't work for that.
    -          if (p !== parts.length) {
    -            if ('$' === parts[p]) {
    -              // comments.$.comments.$.title
    -              return search(parts.slice(p+1), foundschema.schema);
    -            } else {
    -              // this is the last path of the selector
    -              return search(parts.slice(p), foundschema.schema);
    -            }
    -          }
    -        }
    -        return foundschema;
    -      }
    -    }
    -  })(path.split('.'), schema)
    -}

    Parameters:


    Query#_castFields(fields)

    Casts selected field arguments for field selection with mongo 2.2

    show code
    Query.prototype._castFields = function _castFields (fields) {
    -  var selected
    -    , elemMatchKeys
    -    , keys
    -    , key
    -    , out
    -    , i
    -
    -  if (fields) {
    -    keys = Object.keys(fields);
    -    elemMatchKeys = [];
    -    i = keys.length;
    -
    -    // collect $elemMatch args
    -    while (i--) {
    -      key = keys[i];
    -      if (fields[key].$elemMatch) {
    -        selected || (selected = {});
    -        selected[key] = fields[key];
    -        elemMatchKeys.push(key);
    -      }
    -    }
    -  }
    -
    -  if (selected) {
    -    // they passed $elemMatch, cast em
    -    try {
    -      out = this.cast(this.model, selected);
    -    } catch (err) {
    -      return err;
    -    }
    -
    -    // apply the casted field args
    -    i = elemMatchKeys.length;
    -    while (i--) {
    -      key = elemMatchKeys[i];
    -      fields[key] = out[key];
    -    }
    -  }
    -
    -  return fields;
    -}

    Parameters:

    query.select({ ids: { $elemMatch: { $in: [hexString] }})

    Query#remove(callback)

    Executes this query as a remove() operation.

    show code
    Query.prototype.remove = function (callback) {
    -  this.op = 'remove';
    -
    -  var model = this.model
    -    , options = this._optionsForExec(model)
    -    , cb = 'function' == typeof callback
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    if (cb) return callback(err);
    -    throw err;
    -  }
    -
    -  if (!cb) {
    -    delete options.safe;
    -  }
    -
    -  var castQuery = this._conditions;
    -  model.collection.remove(castQuery, options, tick(callback));
    -  return this;
    -};

    Parameters:

    Example

    - -
    Cassette.where('artist').equals('Anne Murray').remove(callback)

    Query#findOneAndUpdate([query], [doc], [options], [callback])

    Issues a mongodb findAndModify update command.

    show code
    Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
    -  this.op = 'findOneAndUpdate';
    -
    -  switch (arguments.length) {
    -    case 3:
    -      if ('function' == typeof options)
    -        callback = options, options = {};
    -      break;
    -    case 2:
    -      if ('function' == typeof doc) {
    -        callback = doc;
    -        doc = query;
    -        query = undefined;
    -      }
    -      options = undefined;
    -      break;
    -    case 1:
    -      if ('function' == typeof query) {
    -        callback = query;
    -        query = options = doc = undefined;
    -      } else {
    -        doc = query;
    -        query = options = undefined;
    -      }
    -  }
    -
    -  // apply query
    -  if (query) {
    -    if ('Object' === query.constructor.name) {
    -      merge(this._conditions, query);
    -    } else if (query instanceof Query) {
    -      merge(this._conditions, query._conditions);
    -    } else if (query instanceof Document) {
    -      merge(this._conditions, query.toObject());
    -    }
    -  }
    -
    -  // apply doc
    -  if (doc) {
    -    merge(this._updateArg, doc);
    -  }
    -
    -  // apply options
    -  options && this.setOptions(options);
    -
    -  if (!callback) return this;
    -
    -  return this._findAndModify('update', callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Available options

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    - -

    Examples

    - -
    query.findOneAndUpdate(conditions, update, options, callback) // executes
    -query.findOneAndUpdate(conditions, update, options)  // returns Query
    -query.findOneAndUpdate(conditions, update, callback) // executes
    -query.findOneAndUpdate(conditions, update)           // returns Query
    -query.findOneAndUpdate(callback)                     // executes
    -query.findOneAndUpdate()                             // returns Query

    Query#findOneAndRemove([conditions], [options], [callback])

    Issues a mongodb findAndModify remove command.

    show code
    Query.prototype.findOneAndRemove = function (conditions, options, callback) {
    -  this.op = 'findOneAndRemove';
    -
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = undefined;
    -  } else if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = undefined;
    -  }
    -
    -  // apply conditions
    -  if (conditions) {
    -    if ('Object' === conditions.constructor.name) {
    -      merge(this._conditions, conditions);
    -    } else if (conditions instanceof Query) {
    -      merge(this._conditions, conditions._conditions);
    -    } else if (conditions instanceof Document) {
    -      merge(this._conditions, conditions.toObject());
    -    }
    -  }
    -
    -  // apply options
    -  options && this.setOptions(options);
    -
    -  if (!callback) return this;
    -
    -  return this._findAndModify('remove', callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    - -

    Available options

    - -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    - -

    Examples

    - -
    A.where().findOneAndRemove(conditions, options, callback) // executes
    -A.where().findOneAndRemove(conditions, options)  // return Query
    -A.where().findOneAndRemove(conditions, callback) // executes
    -A.where().findOneAndRemove(conditions) // returns Query
    -A.where().findOneAndRemove(callback)   // executes
    -A.where().findOneAndRemove()           // returns Query

    Query#_findAndModify(type, callback)

    _findAndModify

    show code
    Query.prototype._findAndModify = function (type, callback) {
    -  var model = this.model
    -    , promise = new Promise(callback)
    -    , self = this
    -    , castedQuery
    -    , castedDoc
    -    , fields
    -    , sort
    -    , opts
    -
    -  castedQuery = castQuery(this);
    -  if (castedQuery instanceof Error) {
    -    process.nextTick(promise.error.bind(promise, castedQuery));
    -    return promise;
    -  }
    -
    -  opts = this._optionsForExec(model);
    -
    -  if ('remove' == type) {
    -    opts.remove = true;
    -  } else {
    -    if (!('new' in opts)) opts.new = true;
    -    if (!('upsert' in opts)) opts.upsert = false;
    -
    -    castedDoc = castDoc(this);
    -    if (!castedDoc) {
    -      if (opts.upsert) {
    -        // still need to do the upsert to empty doc
    -        castedDoc = { $set: {} };
    -      } else {
    -        return this.findOne(callback);
    -      }
    -    } else if (castedDoc instanceof Error) {
    -      process.nextTick(promise.error.bind(promise, castedDoc));
    -      return promise;
    -    }
    -  }
    -
    -  if (this._fields) {
    -    fields = utils.clone(this._fields)
    -    opts.fields = this._castFields(fields);
    -    if (opts.fields instanceof Error) {
    -      process.nextTick(promise.error.bind(promise, opts.fields));
    -      return promise;
    -    }
    -  }
    -
    -  // the driver needs a default
    -  sort = opts.sort || [];
    -
    -  model
    -  .collection
    -  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
    -    if (err) return promise.error(err);
    -    if (!doc) return promise.complete(null);
    -
    -    if (true === opts.lean) {
    -      return promise.complete(doc);
    -    }
    -
    -    var casted = new model(undefined, fields, true);
    -    casted.init(doc, self, function (err) {
    -      if (err) return promise.error(err);
    -      promise.complete(casted);
    -    });
    -  }));
    -
    -  return promise;
    -}

    Parameters:


    Query#populate(path, [fields], [model], [conditions], [options])

    Specifies paths which should be populated with other documents.

    show code
    Query.prototype.populate = function (path, fields, model, conditions, options) {
    -  if ('string' !== typeof model) {
    -    options = conditions;
    -    conditions = model;
    -    model = undefined;
    -  }
    -  // The order of fields/conditions args is opposite Model.find but
    -  // necessary to keep backward compatibility (fields could be
    -  // an array, string, or object literal).
    -  this.options.populate[path] =
    -    new PopulateOptions(fields, conditions, options, model);
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    - -

    Example:

    - -
    Kitten.findOne().populate('owner').exec(function (err, kitten) {
    -  console.log(kitten.owner.name) // Max
    -})

    Query#stream()

    Returns a stream interface

    show code
    Query.prototype.stream = function stream () {
    -  return new QueryStream(this);
    -}
    -
    -// helpers

    Returns:

    Example

    - -
    // follows the nodejs stream api
    -Thing.find({ name: /^hello/ }).stream().pipe(res)
    -
    -// manual streaming
    -var stream = Thing.find({ name: /^hello/ }).stream();
    -
    -stream.on('data', function (doc) {
    -  // do something with the mongoose document
    -}).on('error', function (err) {
    -  // handle the error
    -}).on('close', function () {
    -  // the stream is closed
    -});

    Query#within

    Syntax sugar for expressive queries.

    - -

    Example

    - -
    query.within.box()
    -query.within.center()

    Returns:


  • querystream.js

    QueryStream(query)

    Provides a ReadStream interface for Queries.

    show code
    function QueryStream (query) {
    -  Stream.call(this);
    -
    -  this.query = query;
    -  this.readable = true;
    -  this.paused = false;
    -  this._cursor = null;
    -  this._destroyed = null;
    -  this._fields = null;
    -  this._buffer = null;
    -  this._inline = T_INIT;
    -
    -  // give time to hook up events
    -  var self = this;
    -  process.nextTick(function () {
    -    self._init();
    -  });
    -}

    Parameters:

    Inherits:

    Events:

    • data: emits a single Mongoose document

    • error: emits when an error occurs during streaming. This will emit before the close event.

    • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

    var stream = Model.find().stream();
    -
    -stream.on('data', function (doc) {
    -  // do something with the mongoose document
    -}).on('error', function (err) {
    -  // handle the error
    -}).on('close', function () {
    -  // the stream is closed
    -});
    - -

    The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

    - -
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

    QueryStream#_init()

    Initializes the query.

    show code
    QueryStream.prototype._init = function () {
    -  if (this._destroyed) return;
    -
    -  var query = this.query
    -    , model = query.model
    -    , options = query._optionsForExec(model)
    -    , self = this
    -
    -  try {
    -    query.cast(model);
    -  } catch (err) {
    -    return self.destroy(err);
    -  }
    -
    -  self._fields = utils.clone(query._fields);
    -  options.fields = query._castFields(self._fields);
    -
    -  model.collection.find(query._conditions, options, function (err, cursor) {
    -    if (err) return self.destroy(err);
    -    self._cursor = cursor;
    -    self._next();
    -  });
    -}

    QueryStream#_next()

    Trampoline for pulling the next doc from cursor.

    show code
    QueryStream.prototype._next = function _next () {
    -  if (this.paused || this._destroyed) return;
    -
    -  if (this._buffer && this._buffer.length) {
    -    var arg;
    -    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
    -      this._onNextObject.apply(this, arg);
    -    }
    -  }
    -
    -  // account for possible nextObjects calling user code
    -  if (this.paused || this._destroyed) return;
    -
    -  // avoid stack overflows with large result sets.
    -  // trampoline instead of recursion.
    -  var fn;
    -  while (this.__next()) {}
    -}

    QueryStream#__next()

    Pulls the next doc from the cursor.

    show code
    QueryStream.prototype.__next = function () {
    -  if (this.paused || this._destroyed) return;
    -
    -  var self = this;
    -  self._inline = T_INIT;
    -
    -  self._cursor.nextObject(function cursorcb (err, doc) {
    -    self._onNextObject(err, doc);
    -  });
    -
    -  // if onNextObject() was already called in this tick
    -  // return ourselves to the trampoline.
    -  if (T_CONT === this._inline) {
    -    return true;
    -  } else {
    -    // onNextObject() hasn't fired yet. tell onNextObject
    -    // that its ok to call _next b/c we are not within
    -    // the trampoline anymore.
    -    this._inline = T_IDLE;
    -  }
    -}

    QueryStream#_onNextObject(err, doc)

    Transforms raw docs returned from the cursor into a model instance.

    show code
    QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
    -  if (this._destroyed) return;
    -
    -  if (this.paused) {
    -    this._buffer || (this._buffer = []);
    -    this._buffer.push([err, doc]);
    -    return;
    -  }
    -
    -  if (err) return this.destroy(err);
    -
    -  // when doc is null we hit the end of the cursor
    -  if (!doc) {
    -    this.emit('end');
    -    return this.destroy();
    -  }
    -
    -  if (this.query.options && this.query.options.lean === true)  {
    -    this.emit('data', doc);
    -
    -    // trampoline management
    -    if (T_IDLE === this._inline) {
    -      // no longer in trampoline. restart it.
    -      this._next();
    -    } else {
    -      // in a trampoline. tell __next that its
    -      // ok to continue jumping.
    -      this._inline = T_CONT;
    -    }
    -    return;
    -  }
    -
    -  var instance = new this.query.model(undefined, this._fields, true);
    -
    -  var self = this;
    -  instance.init(doc, this.query, function (err) {
    -    if (err) return self.destroy(err);
    -    self.emit('data', instance);
    -
    -    // trampoline management
    -    if (T_IDLE === self._inline) {
    -      // no longer in trampoline. restart it.
    -      self._next();
    -    } else
    -      // in a trampoline. tell __next that its
    -      // ok to continue jumping.
    -      self._inline = T_CONT;
    -  });
    -}

    Parameters:


    QueryStream#pause()

    Pauses this stream.

    show code
    QueryStream.prototype.pause = function () {
    -  this.paused = true;
    -}

    QueryStream#resume()

    Resumes this stream.

    show code
    QueryStream.prototype.resume = function () {
    -  this.paused = false;
    -  this._next();
    -}

    QueryStream#destroy([err])

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    show code
    QueryStream.prototype.destroy = function (err) {
    -  if (this._destroyed) return;
    -  this._destroyed = true;
    -  this.readable = false;
    -
    -  if (this._cursor) {
    -    this._cursor.close();
    -  }
    -
    -  if (err) {
    -    this.emit('error', err);
    -  }
    -
    -  this.emit('close');
    -}

    Parameters:


    QueryStream#pipe()

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    See:

    Example:

    - -
    query.stream().pipe(writeStream [, options])
    - -

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    - -
    var format = new ArrayFormatter;
    -Events.find().stream().pipe(format).pipe(res);
    - -

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


    QueryStream#paused

    Flag stating whether or not this stream is paused.


    QueryStream#readable

    Flag stating whether or not this stream is readable.


  • schema/array.js

    SchemaArray(key, cast, options)

    Array SchemaType constructor

    show code
    function SchemaArray (key, cast, options) {
    -  if (cast) {
    -    var castOptions = {};
    -
    -    if ('Object' === cast.constructor.name) {
    -      if (cast.type) {
    -        // support { type: Woot }
    -        castOptions = cast;
    -        cast = cast.type;
    -        delete castOptions.type;
    -      } else {
    -        cast = Mixed;
    -      }
    -    }
    -
    -    var caster = cast.name in Types ? Types[cast.name] : cast;
    -    this.casterConstructor = caster;
    -    this.caster = new caster(null, castOptions);
    -  }
    -
    -  SchemaType.call(this, key, options);
    -
    -  var self = this
    -    , defaultArr
    -    , fn;
    -
    -  if (this.defaultValue) {
    -    defaultArr = this.defaultValue;
    -    fn = 'function' == typeof defaultArr;
    -  }
    -
    -  this.default(function(){
    -    var arr = fn ? defaultArr() : defaultArr || [];
    -    return new MongooseArray(arr, self.path, this);
    -  });
    -};

    Parameters:

    Inherits:


    SchemaArray#checkRequired(value)

    Check required

    show code
    SchemaArray.prototype.checkRequired = function (value) {
    -  return !!(value && value.length);
    -};

    Parameters:


    SchemaArray#applyGetters(value, scope)

    Overrides the getters application for the population special-case

    show code
    SchemaArray.prototype.applyGetters = function (value, scope) {
    -  if (this.caster.options && this.caster.options.ref) {
    -    // means the object id was populated
    -    return value;
    -  }
    -
    -  return SchemaType.prototype.applyGetters.call(this, value, scope);
    -};

    Parameters:


    SchemaArray#cast(value, doc, init)

    Casts contents

    show code
    SchemaArray.prototype.cast = function (value, doc, init) {
    -  if (Array.isArray(value)) {
    -    if (!(value instanceof MongooseArray)) {
    -      value = new MongooseArray(value, this.path, doc);
    -    }
    -
    -    if (this.caster) {
    -      try {
    -        for (var i = 0, l = value.length; i < l; i++) {
    -          value[i] = this.caster.cast(value[i], doc, init);
    -        }
    -      } catch (e) {
    -        // rethrow
    -        throw new CastError(e.type, value);
    -      }
    -    }
    -
    -    return value;
    -  } else {
    -    return this.cast([value], doc, init);
    -  }
    -};

    Parameters:

    • value <Object>
    • doc <Document> document that triggers the casting
    • init <Boolean> whether this is an initialization cast

    SchemaArray#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaArray.prototype.castForQuery = function ($conditional, value) {
    -  var handler
    -    , val;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Array.");
    -    val = handler.call(this, value);
    -  } else {
    -    val = $conditional;
    -    var proto = this.casterConstructor.prototype;
    -    var method = proto.castForQuery || proto.cast;
    -    if (Array.isArray(val)) {
    -      val = val.map(function (v) {
    -        if (method) v = method.call(proto, v);
    -        return isMongooseObject(v)
    -          ? v.toObject()
    -          : v;
    -      });
    -    } else if (method) {
    -      val = method.call(proto, val);
    -    }
    -  }
    -  return val && isMongooseObject(val)
    -    ? val.toObject()
    -    : val;
    -};

    Parameters:


  • schema/boolean.js

    SchemaBoolean(path, options)

    Boolean SchemaType constructor.

    show code
    function SchemaBoolean (path, options) {
    -  SchemaType.call(this, path, options);
    -};

    Parameters:

    Inherits:


    SchemaBoolean#checkRequired()

    Required validator

    show code
    SchemaBoolean.prototype.checkRequired = function (value) {
    -  return value === true || value === false;
    -};

    SchemaBoolean#cast(value)

    Casts to boolean

    show code
    SchemaBoolean.prototype.cast = function (value) {
    -  if (value === null) return value;
    -  if (value === '0') return false;
    -  return !!value;
    -};

    Parameters:


    SchemaBoolean#castForQuery($conditional, val)

    Casts contents for queries.

    show code
    SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (2 === arguments.length) {
    -    handler = SchemaBoolean.$conditionalHandlers[$conditional];
    -
    -    if (handler) {
    -      return handler.call(this, val);
    -    }
    -
    -    return this.cast(val);
    -  }
    -
    -  return this.cast($conditional);
    -};

    Parameters:


  • schema/buffer.js

    SchemaBuffer(key, cast)

    Buffer SchemaType constructor

    show code
    function SchemaBuffer (key, options) {
    -  SchemaType.call(this, key, options, 'Buffer');
    -};

    Parameters:

    Inherits:


    SchemaBuffer#checkRequired()

    Check required

    show code
    SchemaBuffer.prototype.checkRequired = function (value) {
    -  return !!(value && value.length);
    -};

    SchemaBuffer#cast(value, doc, init)

    Casts contents

    show code
    SchemaBuffer.prototype.cast = function (value, doc, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  if (Buffer.isBuffer(value)) {
    -    if (!(value instanceof MongooseBuffer)) {
    -      value = new MongooseBuffer(value, [this.path, doc]);
    -    }
    -
    -    return value;
    -  } else if (value instanceof Binary) {
    -    return new MongooseBuffer(value.value(true), [this.path, doc]);
    -  }
    -
    -  if ('string' === typeof value || Array.isArray(value)) {
    -    return new MongooseBuffer(value, [this.path, doc]);
    -  }
    -
    -  throw new CastError('buffer', value);
    -};

    Parameters:


    SchemaBuffer#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Buffer.");
    -    return handler.call(this, val);
    -  } else {
    -    val = $conditional;
    -    return this.cast(val).toObject();
    -  }
    -};

    Parameters:


  • schema/date.js

    SchemaDate(key, options)

    Date SchemaType constructor.

    show code
    function SchemaDate (key, options) {
    -  SchemaType.call(this, key, options);
    -};

    Parameters:

    Inherits:


    SchemaDate#checkRequired()

    Required validator for date

    show code
    SchemaDate.prototype.checkRequired = function (value) {
    -  return value instanceof Date;
    -};

    SchemaDate#cast(value)

    Casts to date

    show code
    SchemaDate.prototype.cast = function (value) {
    -  if (value === null || value === '')
    -    return null;
    -
    -  if (value instanceof Date)
    -    return value;
    -
    -  var date;
    -
    -  // support for timestamps
    -  if (value instanceof Number || 'number' == typeof value 
    -      || String(value) == Number(value))
    -    date = new Date(Number(value));
    -
    -  // support for date strings
    -  else if (value.toString)
    -    date = new Date(value.toString());
    -
    -  if (date.toString() != 'Invalid Date')
    -    return date;
    -
    -  throw new CastError('date', value);
    -};

    Parameters:


    SchemaDate#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaDate.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -
    -  if (2 !== arguments.length) {
    -    return this.cast($conditional);
    -  }
    -
    -  handler = this.$conditionalHandlers[$conditional];
    -
    -  if (!handler) {
    -    throw new Error("Can't use " + $conditional + " with Date.");
    -  }
    -
    -  return handler.call(this, val);
    -};

    Parameters:


  • schema/documentarray.js

    DocumentArray(key, schema, options)

    SubdocsArray SchemaType constructor

    show code
    function DocumentArray (key, schema, options) {
    -
    -  // compile an embedded document for this schema
    -  function EmbeddedDocument () {
    -    Subdocument.apply(this, arguments);
    -  }
    -
    -  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
    -  EmbeddedDocument.prototype._setSchema(schema);
    -  EmbeddedDocument.schema = schema;
    -
    -  // apply methods
    -  for (var i in schema.methods) {
    -    EmbeddedDocument.prototype[i] = schema.methods[i];
    -  }
    -
    -  // apply statics
    -  for (var i in schema.statics)
    -    EmbeddedDocument[i] = schema.statics[i];
    -
    -  EmbeddedDocument.options = options;
    -  this.schema = schema;
    -
    -  ArrayType.call(this, key, EmbeddedDocument, options);
    -
    -  this.schema = schema;
    -  var path = this.path;
    -  var fn = this.defaultValue;
    -
    -  this.default(function(){
    -    var arr = fn.call(this);
    -    if (!Array.isArray(arr)) arr = [arr];
    -    return new MongooseDocumentArray(arr, path, this);
    -  });
    -};

    Parameters:

    Inherits:


    DocumentArray#doValidate()

    Performs local validations first, then validations on each embedded doc

    show code
    DocumentArray.prototype.doValidate = function (array, fn, scope) {
    -  var self = this;
    -  SchemaType.prototype.doValidate.call(this, array, function(err){
    -    if (err) return fn(err);
    -
    -    var count = array && array.length
    -      , error = false;
    -
    -    if (!count) return fn();
    -
    -    array.forEach(function(doc, index){
    -      doc.validate(function(err){
    -        if (err && !error){
    -          // rewrite they key
    -          err.key = self.key + '.' + index + '.' + err.key;
    -          fn(err);
    -          error = true;
    -        } else {
    -          --count || fn();
    -        }
    -      });
    -    });
    -  }, scope);
    -};

    DocumentArray#cast(value, document)

    Casts contents

    show code
    DocumentArray.prototype.cast = function (value, doc, init, prev) {
    -  var selected
    -    , subdoc
    -    , i
    -
    -  if (!Array.isArray(value)) {
    -    return this.cast([value], doc, init, prev);
    -  }
    -
    -  if (!(value instanceof MongooseDocumentArray)) {
    -    value = new MongooseDocumentArray(value, this.path, doc);
    -  }
    -
    -  i = value.length;
    -
    -  while (i--) {
    -    if (!(value[i] instanceof Subdocument)) {
    -      if (init) {
    -        selected || (selected = scopePaths(this, doc._selected, init));
    -        subdoc = new this.casterConstructor(null, value, true, selected);
    -        value[i] = subdoc.init(value[i]);
    -      } else {
    -        if (prev && (subdoc = prev.id(value[i]._id))) {
    -          // handle resetting doc with existing id but differing data
    -          // doc.array = [{ doc: 'val' }]
    -          subdoc.set(value[i]);
    -        } else {
    -          subdoc = new this.casterConstructor(value[i], value);
    -        }
    -
    -        // if set() is hooked it will have no return value
    -        // see gh-746
    -        value[i] = subdoc;
    -      }
    -    }
    -  }
    -
    -  return value;
    -}

    Parameters:


  • schema/mixed.js

    Mixed(path, options)

    Mixed SchemaType constructor.

    show code
    function Mixed (path, options) {
    -  // make sure empty array defaults are handled
    -  if (options &&
    -      options.default &&
    -      Array.isArray(options.default) &&
    -      0 === options.default.length) {
    -    options.default = Array;
    -  }
    -
    -  SchemaType.call(this, path, options);
    -};

    Parameters:

    Inherits:


    Mixed#checkRequired()

    Required validator

    show code
    Mixed.prototype.checkRequired = function (val) {
    -  return true;
    -};

    Mixed#cast(value)

    Casts val for Mixed.

    show code
    Mixed.prototype.cast = function (val) {
    -  return val;
    -};

    Parameters:

    this is a no-op


    Mixed#castForQuery($cond, [val])

    Casts contents for queries.

    show code
    Mixed.prototype.castForQuery = function ($cond, val) {
    -  if (arguments.length === 2) return val;
    -  return $cond;
    -};

    Parameters:


  • schema/number.js

    SchemaNumber(key, options)

    Number SchemaType constructor.

    show code
    function SchemaNumber (key, options) {
    -  SchemaType.call(this, key, options, 'Number');
    -};

    Parameters:

    Inherits:


    SchemaNumber#checkRequired()

    Required validator for number

    show code
    SchemaNumber.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return typeof value == 'number' || value instanceof Number;
    -  }
    -};

    SchemaNumber#min(value, message)

    Sets a maximum number validator.

    show code
    SchemaNumber.prototype.min = function (value, message) {
    -  if (this.minValidator)
    -    this.validators = this.validators.filter(function(v){
    -      return v[1] != 'min';
    -    });
    -  if (value != null)
    -    this.validators.push([function(v){
    -      return v === null || v >= value;
    -    }, 'min']);
    -  return this;
    -};

    Parameters:

    Example:

    - -
    var s = new Schema({ n: { type: Number, min: 10 })
    -var M = db.model('M', s)
    -var m = new M({ n: 9 })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.n = 10;
    -  m.save() // success
    -})

    SchemaNumber#max(maximum, message)

    Sets a maximum number validator.

    show code
    SchemaNumber.prototype.max = function (value, message) {
    -  if (this.maxValidator)
    -    this.validators = this.validators.filter(function(v){
    -      return v[1] != 'max';
    -    });
    -  if (value != null)
    -    this.validators.push([this.maxValidator = function(v){
    -      return v === null || v <= value;
    -    }, 'max']);
    -  return this;
    -};

    Parameters:

    Example:

    - -
    var s = new Schema({ n: { type: Number, max: 10 })
    -var M = db.model('M', s)
    -var m = new M({ n: 11 })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.n = 10;
    -  m.save() // success
    -})

    SchemaNumber#cast(value, doc, init)

    Casts to number

    show code
    SchemaNumber.prototype.cast = function (value, doc, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  if (!isNaN(value)){
    -    if (null === value) return value;
    -    if ('' === value) return null;
    -    if ('string' == typeof value) value = Number(value);
    -    if (value instanceof Number) return value
    -    if ('number' == typeof value) return value;
    -    if (value.toString && !Array.isArray(value) &&
    -        value.toString() == Number(value)) {
    -      return new Number(value)
    -    }
    -  }
    -
    -  throw new CastError('number', value);
    -};

    Parameters:


    SchemaNumber#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaNumber.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Number.");
    -    return handler.call(this, val);
    -  } else {
    -    val = this.cast($conditional);
    -    return val == null ? val : val
    -  }
    -};

    Parameters:


  • schema/objectid.js

    ObjectId(key, options)

    ObjectId SchemaType constructor.

    show code
    function ObjectId (key, options) {
    -  SchemaType.call(this, key, options, 'ObjectID');
    -};

    Parameters:

    Inherits:


    ObjectId#checkRequired()

    Check required

    show code
    ObjectId.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return value instanceof oid;
    -  }
    -};

    ObjectId#cast(value, scope, init)

    Casts to ObjectId

    show code
    ObjectId.prototype.cast = function (value, scope, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  if (value === null) return value;
    -
    -  if (value instanceof oid)
    -    return value;
    -
    -  if (value._id && value._id instanceof oid)
    -    return value._id;
    -
    -  if (value.toString)
    -    return oid.fromString(value.toString());
    -
    -  throw new CastError('object id', value);
    -};

    Parameters:


    ObjectId#castForQuery($conditional, [val])

    Casts contents for queries.

    show code
    ObjectId.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with ObjectId.");
    -    return handler.call(this, val);
    -  } else {
    -    return this.cast($conditional);
    -  }
    -};

    Parameters:


    ObjectId#auto(turnOn)

    Adds an auto-generated ObjectId default if turnOn is true.

    show code
    ObjectId.prototype.auto = function (turnOn) {
    -  if (turnOn) {
    -    this.default(defaultId);
    -    this.set(resetId)
    -  }
    -};

    Parameters:

    • turnOn <Boolean> auto generated ObjectId defaults

  • schema/string.js

    SchemaString(key, options)

    String SchemaType constructor.

    show code
    function SchemaString (key, options) {
    -  this.enumValues = [];
    -  this.regExp = null;
    -  SchemaType.call(this, key, options, 'String');
    -};

    Parameters:

    Inherits:


    SchemaString#enum([args...])

    Adds enumeration values and a coinciding validator.

    show code
    SchemaString.prototype.enum = function () {
    -  var len = arguments.length;
    -  if (!len || undefined === arguments[0] || false === arguments[0]) {
    -    if (this.enumValidator){
    -      this.enumValidator = false;
    -      this.validators = this.validators.filter(function(v){
    -        return v[1] != 'enum';
    -      });
    -    }
    -    return;
    -  }
    -
    -  for (var i = 0; i < len; i++) {
    -    if (undefined !== arguments[i]) {
    -      this.enumValues.push(this.cast(arguments[i]));
    -    }
    -  }
    -
    -  if (!this.enumValidator) {
    -    var values = this.enumValues;
    -    this.enumValidator = function(v){
    -      return undefined === v || ~values.indexOf(v);
    -    };
    -    this.validators.push([this.enumValidator, 'enum']);
    -  }
    -};

    Parameters:

    • [args...] <String> enumeration values

    Example:

    - -
    var states = 'opening open closing closed'.split(' ')
    -var s = new Schema({ state: { type: String, enum: states })
    -var M = db.model('M', s)
    -var m = new M({ state: 'invalid' })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.state = 'open'
    -  m.save() // success
    -})

    SchemaString#lowercase()

    Adds a lowercase setter.

    show code
    SchemaString.prototype.lowercase = function () {
    -  return this.set(function (v) {
    -    return v.toLowerCase();
    -  });
    -};

    Example:

    - -
    var s = new Schema({ email: { type: String, lowercase: true }})
    -var M = db.model('M', s);
    -var m = new M({ email: 'SomeEmail@example.COM' });
    -console.log(m.email) // someemail@example.com
    -

    SchemaString#uppercase()

    Adds an uppercase setter.

    show code
    SchemaString.prototype.uppercase = function () {
    -  return this.set(function (v) {
    -    return v.toUpperCase();
    -  });
    -};

    Example:

    - -
    var s = new Schema({ caps: { type: String, uppercase: true }})
    -var M = db.model('M', s);
    -var m = new M({ caps: 'an example' });
    -console.log(m.caps) // AN EXAMPLE

    SchemaString#trim()

    Adds a trim setter.

    show code
    SchemaString.prototype.trim = function () {
    -  return this.set(function (v) {
    -    return v.trim();
    -  });
    -};

    The string value will be trimmed when set.

    - -

    Example:

    - -
    var s = new Schema({ name: { type: String, trim: true }})
    -var M = db.model('M', s)
    -var string = ' some name '
    -console.log(string.length) // 11
    -var m = new M({ name: string })
    -console.log(m.name.length) // 9

    SchemaString#match(regExp)

    Sets a regexp validator.

    show code
    SchemaString.prototype.match = function match (regExp) {
    -  this.validators.push([function(v){
    -    return null != v && '' !== v
    -      ? regExp.test(v)
    -      : true
    -  }, 'regexp']);
    -};

    Parameters:

    • regExp <RegExp> regular expression to test against

    Any value that does not pass regExp.test(val) will fail validation.

    - -

    Example:

    - -
    var s = new Schema({ name: { type: String, match: /^a/ }})
    -var M = db.model('M', s)
    -var m = new M({ name: 'invalid' })
    -m.validate(function (err) {
    -  console.error(err) // validation error
    -  m.name = 'apples'
    -  m.validate(function (err) {
    -    assert.ok(err) // success
    -  })
    -})

    SchemaString#checkRequired(value)

    Check required

    show code
    SchemaString.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return (value instanceof String || typeof value == 'string') && value.length;
    -  }
    -};

    Parameters:


    SchemaString#cast()

    Casts to String

    show code
    SchemaString.prototype.cast = function (value, scope, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -  if (value === null) return value;
    -  if ('undefined' !== typeof value && value.toString) return value.toString();
    -  throw new CastError('string', value);
    -};

    SchemaString#castForQuery($conditional, [val])

    Casts contents for queries.

    show code
    SchemaString.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with String.");
    -    return handler.call(this, val);
    -  } else {
    -    val = $conditional;
    -    if (val instanceof RegExp) return val;
    -    return this.cast(val);
    -  }
    -};

    Parameters:


  • schema.js

    Schema(definition)

    Schema constructor.

    show code
    function Schema (obj, options) {
    -  if (!(this instanceof Schema))
    -    return new Schema(obj, options);
    -
    -  this.paths = {};
    -  this.subpaths = {};
    -  this.virtuals = {};
    -  this.nested = {};
    -  this.inherits = {};
    -  this.callQueue = [];
    -  this._indexes = [];
    -  this.methods = {};
    -  this.statics = {};
    -  this.tree = {};
    -  this._requiredpaths = undefined;
    -
    -  this.options = this.defaultOptions(options);
    -
    -  // build paths
    -  if (obj) {
    -    this.add(obj);
    -  }
    -
    -  // ensure the documents get an auto _id unless disabled
    -  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
    -  if (auto_id) {
    -    this.add({ _id: {type: Schema.ObjectId, auto: true} });
    -  }
    -
    -  // ensure the documents receive an id getter unless disabled
    -  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
    -  if (autoid) {
    -    this.virtual('id').get(idGetter);
    -  }
    -
    -  // versioning not directly added to schema b/c we only want
    -  // it in the top level document, not embedded ones.
    -};

    Parameters:

    Events:

    • init: Emitted after the schema is compiled into a Model.

    Example:

    - -
    var child = new Schema({ name: String });
    -var schema = new Schema({ name: String, age: Number, children: [child] });
    -var Tree = mongoose.model('Tree', schema);
    -
    -// setting schema options
    -new Schema({ name: String }, { _id: false, autoIndex: false })
    - -

    Options:

    - -
      -
    • safe: bool - defaults to true.
    • -
    • read: string
    • -
    • strict: bool - defaults to true
    • -
    • capped: bool - defaults to false
    • -
    • versionKey: bool - defaults to "__v"
    • -
    • shardKey: bool - defaults to null
    • -
    • autoIndex: bool - defaults to true
    • -
    • _id: bool - defaults to true
    • -
    • id: bool - defaults to true
    • -
    • toObject - object - no default
    • -
    • toJSON - object - no default
    • -
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • -
    - -

    Note:

    - -

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


    Schema#defaultOptions(options)

    Returns default options for this schema, merged with options.

    show code
    Schema.prototype.defaultOptions = function (options) {
    -  options = utils.options({
    -      safe: true
    -    , strict: true
    -    , capped: false // { size, max, autoIndexId }
    -    , versionKey: '__v'
    -    , minimize: true
    -    , autoIndex: true
    -    , shardKey: null
    -    , read: null
    -    // the following are only applied at construction time
    -    , noId: false // deprecated, use { _id: false }
    -    , _id: true
    -    , noVirtualId: false // deprecated, use { id: false }
    -    , id: true
    -  }, options);
    -
    -  if (options.read)
    -    options.read = utils.readPref(options.read);
    -
    -  return options;
    -}

    Parameters:

    Returns:


    Schema#add(obj, prefix)

    Adds key path / schema type pairs to this schema.

    show code
    Schema.prototype.add = function add (obj, prefix) {
    -  prefix = prefix || '';
    -  for (var i in obj) {
    -    if (null == obj[i]) {
    -      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
    -    }
    -
    -    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
    -      if (Object.keys(obj[i]).length) {
    -        // nested object { last: { name: String }}
    -        this.nested[prefix + i] = true;
    -        this.add(obj[i], prefix + i + '.');
    -      }
    -      else
    -        this.path(prefix + i, obj[i]); // mixed type
    -    } else
    -      this.path(prefix + i, obj[i]);
    -  }
    -};

    Parameters:

    Example:

    - -
    var ToySchema = new Schema;
    -ToySchema.add({ name: 'string', color: 'string', price: 'number' });

    Schema#path(path, constructor)

    Gets/sets schema paths.

    show code
    Schema.prototype.path = function (path, obj) {
    -  if (obj == undefined) {
    -    if (this.paths[path]) return this.paths[path];
    -    if (this.subpaths[path]) return this.subpaths[path];
    -
    -    // subpaths?
    -    return /\.\d+\.?$/.test(path)
    -      ? getPositionalPath(this, path)
    -      : undefined;
    -  }
    -
    -  // some path names conflict with document methods
    -  if (reserved[path]) {
    -    throw new Error("`" + path + "` may not be used as a schema pathname");
    -  }
    -
    -  // update the tree
    -  var subpaths = path.split(/\./)
    -    , last = subpaths.pop()
    -    , branch = this.tree;
    -
    -  subpaths.forEach(function(path) {
    -    if (!branch[path]) branch[path] = {};
    -    branch = branch[path];
    -  });
    -
    -  branch[last] = utils.clone(obj);
    -
    -  this.paths[path] = Schema.interpretAsType(path, obj);
    -  return this;
    -};

    Parameters:

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    - -

    Example

    - -
    schema.path('name') // returns a SchemaType
    -schema.path('name', Number) // changes the schemaType of `name` to Number

    Schema#eachPath(fn)

    Iterates the schemas paths similar to Array#forEach.

    show code
    Schema.prototype.eachPath = function (fn) {
    -  var keys = Object.keys(this.paths)
    -    , len = keys.length;
    -
    -  for (var i = 0; i < len; ++i) {
    -    fn(keys[i], this.paths[keys[i]]);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    The callback is passed the pathname and schemaType as arguments on each iteration.


    Schema#requiredPaths()

    Returns an Array of path strings that are required by this schema.

    show code
    Schema.prototype.requiredPaths = function requiredPaths () {
    -  if (this._requiredpaths) return this._requiredpaths;
    -
    -  var paths = Object.keys(this.paths)
    -    , i = paths.length
    -    , ret = [];
    -
    -  while (i--) {
    -    var path = paths[i];
    -    if (this.paths[path].isRequired) ret.push(path);
    -  }
    -
    -  return this._requiredpaths = ret;
    -}

    Returns:


    Schema#pathType(path)

    Returns the pathType of path for this schema.

    show code
    Schema.prototype.pathType = function (path) {
    -  if (path in this.paths) return 'real';
    -  if (path in this.virtuals) return 'virtual';
    -  if (path in this.nested) return 'nested';
    -  if (path in this.subpaths) return 'real';
    -
    -  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
    -    return 'real';
    -  } else {
    -    return 'adhocOrUndefined'
    -  }
    -};

    Parameters:

    Returns:

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


    Schema#queue(name, args)

    Adds a method call to the queue.

    show code
    Schema.prototype.queue = function(name, args){
    -  this.callQueue.push([name, args]);
    -  return this;
    -};

    Parameters:

    • name <String> name of the document method to call later
    • args <Array> arguments to pass to the method

    Schema#pre(method, callback)

    Defines a pre hook for the document.

    show code
    Schema.prototype.pre = function(){
    -  return this.queue('pre', arguments);
    -};

    Parameters:

    Example

    - -
    var toySchema = new Schema(..);
    -
    -toySchema.pre('save', function (next) {
    -  if (!this.created) this.created = new Date;
    -  next();
    -})
    -
    -toySchema.pre('validate', function (next) {
    -  if (this.name != 'Woody') this.name = 'Woody';
    -  next();
    -})

    Schema#post(method, fn)

    Defines a post hook for the document.

    show code
    Schema.prototype.post = function(method, fn){
    -  return this.queue('on', arguments);
    -};

    Parameters:

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    - -
    var schema = new Schema(..);
    -schema.post('save', function () {
    -  console.log('this fired after a document was saved');
    -});
    -
    -var Model = mongoose.model('Model', schema);
    -
    -var m = new Model(..);
    -m.save(function (err) {
    -  console.log('this fires after the `post` hook');
    -});

    Schema#plugin(plugin, opts)

    Registers a plugin for this schema.

    show code
    Schema.prototype.plugin = function (fn, opts) {
    -  fn(this, opts);
    -  return this;
    -};

    Parameters:


    Schema#method(method, [fn])

    Adds an instance method to documents constructed from Models compiled from this schema.

    show code
    Schema.prototype.method = function (name, fn) {
    -  if ('string' != typeof name)
    -    for (var i in name)
    -      this.methods[i] = name[i];
    -  else
    -    this.methods[name] = fn;
    -  return this;
    -};

    Parameters:

    Example

    - -
    var schema = kittySchema = new Schema(..);
    -
    -schema.methods.meow = function () {
    -  console.log('meeeeeoooooooooooow');
    -})
    -
    -var Kitty = mongoose.model('Kitty', schema);
    -
    -var fizz = new Kitty;
    -fizz.meow(); // meeeeeooooooooooooow
    - -

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    - -
    schema.method({
    -    purr: function () {}
    -  , scratch: function () {}
    -});
    -
    -// later
    -fizz.purr();
    -fizz.scratch();

    Schema#static(name, fn)

    Adds static "class" methods to Models compiled from this schema.

    show code
    Schema.prototype.static = function(name, fn) {
    -  if ('string' != typeof name)
    -    for (var i in name)
    -      this.statics[i] = name[i];
    -  else
    -    this.statics[name] = fn;
    -  return this;
    -};

    Parameters:

    Example

    - -
    var schema = new Schema(..);
    -schema.static('findByName', function (name, callback) {
    -  return this.find({ name: name }, callback);
    -});
    -
    -var Drink = mongoose.model('Drink', schema);
    -Drink.findByName('sanpellegrino', function (err, drinks) {
    -  //
    -});
    - -

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


    Schema#index(fields, [options])

    Defines an index (most likely compound) for this schema.

    show code
    Schema.prototype.index = function (fields, options) {
    -  options || (options = {});
    -
    -  if (options.expires)
    -    utils.expires(options);
    -
    -  this._indexes.push([fields, options]);
    -  return this;
    -};

    Parameters:

    Example

    - -
    schema.index({ first: 1, last: -1 })

    Schema#set(key, [value])

    Sets/gets a schema option.

    show code
    Schema.prototype.set = function (key, value, tags) {
    -  if (arguments.length == 1)
    -    return this.options[key];
    -
    -  this.options[key] = 'read' == key
    -    ? utils.readPref(value, tags)
    -    : value;
    -
    -  return this;
    -};

    Parameters:

    • key <String> option name
    • [value] <Object> if not passed, the current option value is returned

    Schema#indexes()

    Compiles indexes from fields and schema-level indexes

    show code
    Schema.prototype.indexes = function () {
    -  var indexes = []
    -    , seenSchemas = [];
    -
    -  collectIndexes(this);
    -
    -  return indexes;
    -
    -  function collectIndexes (schema, prefix) {
    -    if (~seenSchemas.indexOf(schema)) return;
    -    seenSchemas.push(schema);
    -
    -    var index;
    -    var paths = schema.paths;
    -    prefix = prefix || '';
    -
    -    for (var i in paths) {
    -      if (paths[i]) {
    -        if (paths[i] instanceof Types.DocumentArray) {
    -          collectIndexes(paths[i].schema, i + '.');
    -        } else {
    -          index = paths[i]._index;
    -
    -          if (index !== false && index !== null){
    -            var field = {};
    -            field[prefix + i] = '2d' === index ? index : 1;
    -            var options = 'Object' === index.constructor.name ? index : {};
    -            if (!('background' in options)) options.background = true;
    -            indexes.push([field, options]);
    -          }
    -        }
    -      }
    -    }
    -
    -    if (prefix) {
    -      fixSubIndexPaths(schema, prefix);
    -    } else {
    -      schema._indexes.forEach(function (index) {
    -        if (!('background' in index[1])) index[1].background = true;
    -      });
    -      indexes = indexes.concat(schema._indexes);
    -    }
    -  }

    Schema#virtual(name, [options])

    Creates a virtual type with the given name.

    show code
    Schema.prototype.virtual = function (name, options) {
    -  var virtuals = this.virtuals;
    -  var parts = name.split('.');
    -  return virtuals[name] = parts.reduce(function (mem, part, i) {
    -    mem[part] || (mem[part] = (i === parts.length-1)
    -                            ? new VirtualType(options, name)
    -                            : {});
    -    return mem[part];
    -  }, this.tree);
    -};

    Parameters:

    Returns:


    Schema#virtualpath(name)

    Returns the virtual type with the given name.

    show code
    Schema.prototype.virtualpath = function (name) {
    -  return this.virtuals[name];
    -};

    Parameters:

    Returns:


    Schema#namedScope()

    These still haven't been fixed. Once they're working we'll make them public again.

    show code
    Schema.prototype.namedScope = function (name, fn) {
    -  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
    -    , newScope = Object.create(namedScopes)
    -    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
    -  allScopes[name] = newScope;
    -  newScope.name = name;
    -  newScope.block = fn;
    -  newScope.query = new Query();
    -  newScope.decorate(namedScopes, {
    -    block0: function (block) {
    -      return function () {
    -        block.call(this.query);
    -        return this;
    -      };
    -    },
    -    blockN: function (block) {
    -      return function () {
    -        block.apply(this.query, arguments);
    -        return this;
    -      };
    -    },
    -    basic: function (query) {
    -      return function () {
    -        this.query.find(query);
    -        return this;
    -      };
    -    }
    -  });
    -  return newScope;
    -};

    Schema.reserved

    Reserved document keys.

    show code
    Schema.reserved = Object.create(null);
    -var reserved = Schema.reserved;
    -reserved.on =
    -reserved.db =
    -reserved.init =
    -reserved.isNew =
    -reserved.errors =
    -reserved.schema =
    -reserved.options =
    -reserved.modelName =
    -reserved.collection = 1;

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    - -
    on, db, init, isNew, errors, schema, options, modelName, collection

    Schema.interpretAsType(path, obj)

    Converts type arguments into Mongoose Types.

    show code
    Schema.interpretAsType = function (path, obj) {
    -  if (obj.constructor.name != 'Object')
    -    obj = { type: obj };
    -
    -  // Get the type making sure to allow keys named "type"
    -  // and default to mixed if not specified.
    -  // { type: { type: String, default: 'freshcut' } }
    -  var type = obj.type && !obj.type.type
    -    ? obj.type
    -    : {};
    -
    -  if ('Object' == type.constructor.name || 'mixed' == type) {
    -    return new Types.Mixed(path, obj);
    -  }
    -
    -  if (Array.isArray(type) || Array == type || 'array' == type) {
    -    // if it was specified through { type } look for `cast`
    -    var cast = (Array == type || 'array' == type)
    -      ? obj.cast
    -      : type[0];
    -
    -    if (cast instanceof Schema) {
    -      return new Types.DocumentArray(path, cast, obj);
    -    }
    -
    -    if ('string' == typeof cast) {
    -      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
    -    } else if (cast && (!cast.type || cast.type.type)
    -                    && 'Object' == cast.constructor.name
    -                    && Object.keys(cast).length) {
    -      return new Types.DocumentArray(path, new Schema(cast), obj);
    -    }
    -
    -    return new Types.Array(path, cast || Types.Mixed, obj);
    -  }
    -
    -  var name = 'string' == typeof type
    -    ? type
    -    : type.name;
    -
    -  if (name) {
    -    name = name.charAt(0).toUpperCase() + name.substring(1);
    -  }
    -
    -  if (undefined == Types[name]) {
    -    throw new TypeError('Undefined type at `' + path +
    -        '`
    -  Did you try nesting Schemas? ' +
    -        'You can only nest using refs or arrays.');
    -  }
    -
    -  return new Types[name](path, obj);
    -};

    Parameters:


    Schema.Types

    The various Mongoose Schema Types.

    show code
    Schema.Types = require('./schema/index');

    Example:

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -var ObjectId = mongoose.Schema.Types.ObjectId;
    - -

    Types:

    - -
      -
    • String
    • -
    • Number
    • -
    • Boolean | Bool
    • -
    • Array
    • -
    • Buffer
    • -
    • Date
    • -
    • ObjectId | Oid
    • -
    • Mixed
    • -
    - -

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    - -
    var Mixed = mongoose.Schema.Types.Mixed;
    -new mongoose.Schema({ _user: Mixed })

    Schema#tree

    Schema as a tree

    - -

    Example:

    - -
    {
    -    '_id'     : ObjectId
    -  , 'nested'  : {
    -        'key' : String
    -    }
    -}

    Schema#paths

    Schema as flat paths

    - -

    Example:

    - -
    {
    -    '_id'        : SchemaType,
    -  , 'nested.key' : SchemaType,
    -}

  • schemadefault.js

    exports#system.profile

    Default model for querying the system.profiles collection.


  • schematype.js

    SchemaType(path, [options], [instance])

    SchemaType constructor

    show code
    function SchemaType (path, options, instance) {
    -  this.path = path;
    -  this.instance = instance;
    -  this.validators = [];
    -  this.setters = [];
    -  this.getters = [];
    -  this.options = options;
    -  this._index = null;
    -  this.selected;
    -
    -  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
    -    // { unique: true, index: true }
    -    if ('index' == i && this._index) continue;
    -
    -    var opts = Array.isArray(options[i])
    -      ? options[i]
    -      : [options[i]];
    -
    -    this[i].apply(this, opts);
    -  }
    -};

    Parameters:


    SchemaType#default(val)

    Sets a default value for this SchemaType.

    show code
    SchemaType.prototype.default = function (val) {
    -  if (1 === arguments.length) {
    -    this.defaultValue = typeof val === 'function'
    -      ? val
    -      : this.cast(val);
    -    return this;
    -  } else if (arguments.length > 1) {
    -    this.defaultValue = utils.args(arguments);
    -  }
    -  return this.defaultValue;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var schema = new Schema({ n: { type: Number, default: 10 })
    -var M = db.model('M', schema)
    -var m = new M;
    -console.log(m.n) // 10
    - -

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    - -

    Example:

    - -
    // values are cast:
    -var schema = new Schema({ aNumber: Number, default: "4.815162342" })
    -var M = db.model('M', schema)
    -var m = new M;
    -console.log(m.aNumber) // 4.815162342
    -
    -// default unique objects for Mixed types:
    -var schema = new Schema({ mixed: Schema.Types.Mixed });
    -schema.path('mixed').default(function () {
    -  return {};
    -});
    -
    -// if we don't use a function to return object literals for Mixed defaults,
    -// each document will receive a reference to the same object literal creating
    -// a "shared" object instance:
    -var schema = new Schema({ mixed: Schema.Types.Mixed });
    -schema.path('mixed').default({});
    -var M = db.model('M', schema);
    -var m1 = new M;
    -m1.mixed.added = 1;
    -console.log(m1.mixed); // { added: 1 }
    -var m2 = new M;
    -console.log(m2.mixed); // { added: 1 }

    SchemaType#index(options)

    Declares the index options for this schematype.

    show code
    SchemaType.prototype.index = function (options) {
    -  this._index = options;
    -  utils.expires(this._index);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var s = new Schema({ name: { type: String, index: true })
    -var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
    -Schema.path('my.path').index(true);
    -Schema.path('my.path').index({ expires: 60 });
    -Schema.path('my.path').index({ unique: true, sparse: true });
    - -

    NOTE:

    - -

    Indexes are created in the background by default. Specify background: false to override.

    - -

    Direction doesn't matter for single key indexes


    SchemaType#unique(bool)

    Declares an unique index.

    show code
    SchemaType.prototype.unique = function (bool) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    -
    -  this._index.unique = bool;
    -  return this;
    -};

    Parameters:

    Returns:

    Examples:

    - -
    var s = new Schema({ name: { type: String, unique: true })
    -Schema.path('name').index({ unique: true });

    SchemaType#sparse(bool)

    Declares a sparse index.

    show code
    SchemaType.prototype.sparse = function (bool) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    -
    -  this._index.sparse = bool;
    -  return this;
    -};

    Parameters:

    Returns:

    Examples:

    - -
    var s = new Schema({ name: { type: String, sparse: true })
    -Schema.path('name').index({ sparse: true });

    SchemaType#expires(when)

    Declares a TTL index (rounded to the nearest second) for Date types only.

    show code
    SchemaType.prototype.expires = function (when) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    -
    -  this._index.expires = when;
    -  utils.expires(this._index);
    -  return this;
    -};

    Parameters:

    Returns:

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    - -

    Example:

    - -
    // expire in 24 hours
    -new Schema({..}, { expires: 60*60*24 });
    - -

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    - -

    Example:

    - -
    // expire in 24 hours
    -new Schema({..}, { expires: '24h' });
    -
    -// expire in 1.5 hours
    -new Schema({..}, { expires: '1.5h' });
    -
    -// expire in 7 days
    -var schema = new Schema({..});
    -schema.expires('7d');

    SchemaType#set(fn)

    Adds a setter to this schematype.

    show code
    SchemaType.prototype.set = function (fn) {
    -  if ('function' != typeof fn)
    -    throw new Error('A setter must be a function.');
    -  this.setters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    function capitalize (val) {
    -  if ('string' != typeof val) val = '';
    -  return val.charAt(0).toUpperCase() + val.substring(1);
    -}
    -
    -// defining within the schema
    -var s = new Schema({ name: { type: String, set: capitalize }})
    -
    -// or by retreiving its SchemaType
    -var s = new Schema({ name: String })
    -s.path('name').set(capitalize)
    - -

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    - -

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    - -

    You can set up email lower case normalization easily via a Mongoose setter.

    - -
    function toLower (v) {
    -  return v.toLowerCase();
    -}
    -
    -var UserSchema = new Schema({
    -  email: { type: String, set: toLower }
    -})
    -
    -var User = db.model('User', UserSchema)
    -
    -var user = new User({email: 'AVENUE@Q.COM'})
    -console.log(user.email); // 'avenue@q.com'
    -
    -// or
    -var user = new User
    -user.email = 'Avenue@Q.com'
    -console.log(user.email) // 'avenue@q.com'
    -
    - -

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    - -

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    - -
    new Schema({ email: { type: String, lowercase: true }})

    SchemaType#get(fn)

    Adds a getter to this schematype.

    show code
    SchemaType.prototype.get = function (fn) {
    -  if ('function' != typeof fn)
    -    throw new Error('A getter must be a function.');
    -  this.getters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    function dob (val) {
    -  if (!val) return val;
    -  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
    -}
    -
    -// defining within the schema
    -var s = new Schema({ born: { type: Date, get: dob })
    -
    -// or by retreiving its SchemaType
    -var s = new Schema({ born: Date })
    -s.path('born').get(dob)
    - -

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    - -

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    - -
    function obfuscate (cc) {
    -  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
    -}
    -
    -var AccountSchema = new Schema({
    -  creditCardNumber: { type: String, get: obfuscate }
    -});
    -
    -var Account = db.model('Account', AccountSchema);
    -
    -Account.findById(id, function (err, found) {
    -  console.log(found.creditCardNumber); // '****-****-****-1234'
    -});

    SchemaType#validate(obj, [error])

    Adds validator(s) for this document path.

    show code
    SchemaType.prototype.validate = function (obj, error) {
    -  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
    -    this.validators.push([obj, error]);
    -    return this;
    -  }
    -
    -  var i = arguments.length
    -    , arg
    -
    -  while (i--) {
    -    arg = arguments[i];
    -    if (!(arg && 'Object' == arg.constructor.name)) {
    -      var msg = 'Invalid validator. Received (' + typeof arg + ') '
    -        + arg
    -        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
    -
    -      throw new Error(msg);
    -    }
    -    this.validate(arg.validator, arg.msg);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Validators must return Boolean. Returning false is interpreted as validation failure.

    - -

    Examples:

    - -
    function validator () { ... }
    -
    -var single = [validator, 'failed']
    -new Schema({ name: { type: String, validate: single }});
    -
    -var many = [
    -    { validator: validator, msg: 'uh oh' }
    -  , { validator: fn, msg: 'failed' }
    -]
    -new Schema({ name: { type: String, validate: many }});
    -
    -// or utilizing SchemaType methods directly:
    -
    -var schema = new Schema({ name: 'string' });
    -schema.path('name').validate(validator, 'validation failed');
    - -

    Asynchronous validation:

    - -

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    - -
    schema.path('name').validate(function (value, respond) {
    -  doStuff(value, function () {
    -    ...
    -    respond(false); // validation failed
    -  })
    - }, 'my error type');
    - -

    Validation occurs pre('save') or whenever you manually execute document#validate.

    - -

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    - -
    var conn = mongoose.createConnection(..);
    -conn.on('error', handleError);
    -
    -var Product = conn.model('Product', yourSchema);
    -var dvd = new Product(..);
    -dvd.save(); // emits error on the `conn` above
    - -

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    - -
    // registering an error listener on the Model lets us handle errors more locally
    -Product.on('error', handleError);

    SchemaType#required(required)

    Adds a required validator to this schematype.

    show code
    SchemaType.prototype.required = function (required) {
    -  var self = this;
    -
    -  function __checkRequired (v) {
    -    // in here, `this` refers to the validating document.
    -    // no validation when this path wasn't selected in the query.
    -    if ('isSelected' in this &&
    -        !this.isSelected(self.path) &&
    -        !this.isModified(self.path)) return true;
    -    return self.checkRequired(v);
    -  }
    -
    -  if (false === required) {
    -    this.isRequired = false;
    -    this.validators = this.validators.filter(function (v) {
    -      return v[0].name !== '__checkRequired';
    -    });
    -  } else {
    -    this.isRequired = true;
    -    this.validators.push([__checkRequired, 'required']);
    -  }
    -
    -  return this;
    -};

    Parameters:

    • required <Boolean> enable/disable the validator

    Returns:

    Example:

    - -
    var s = new Schema({ born: { type: Date, required: true })
    -// or
    -Schema.path('name').required(true);

    SchemaType#getDefault(scope, init)

    Gets the default value

    show code
    SchemaType.prototype.getDefault = function (scope, init) {
    -  var ret = 'function' === typeof this.defaultValue
    -    ? this.defaultValue.call(scope)
    -    : this.defaultValue;
    -
    -  if (null !== ret && undefined !== ret) {
    -    return this.cast(ret, scope, init);
    -  } else {
    -    return ret;
    -  }
    -};

    Parameters:

    • scope <Object> the scope which callback are executed
    • init <Boolean>

    SchemaType#applySetters(value, scope, init)

    Applies setters

    show code
    SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  var v = value
    -    , setters = this.setters
    -    , len = setters.length
    -
    -  if (!len) {
    -    if (null === v || undefined === v) return v;
    -    return init
    -      ? v // if we just initialized we dont recast
    -      : this.cast(v, scope, init, priorVal)
    -  }
    -
    -  while (len--) {
    -    v = setters[len].call(scope, v, this);
    -  }
    -
    -  if (null === v || undefined === v) return v;
    -
    -  // do not cast until all setters are applied #665
    -  v = this.cast(v, scope, init, priorVal);
    -
    -  return v;
    -};

    Parameters:


    SchemaType#applyGetters(value, scope)

    Applies getters to a value

    show code
    SchemaType.prototype.applyGetters = function (value, scope) {
    -  if (SchemaType._isRef(this, value, true)) return value;
    -
    -  var v = value
    -    , getters = this.getters
    -    , len = getters.length;
    -
    -  if (!len) {
    -    return v;
    -  }
    -
    -  while (len--) {
    -    v = getters[len].call(scope, v, this);
    -  }
    -
    -  return v;
    -};

    Parameters:


    SchemaType#select(val)

    Sets default select() behavior for this path.

    show code
    SchemaType.prototype.select = function select (val) {
    -  this.selected = !! val;
    -}

    Parameters:

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    - -

    Example:

    - -
    T = db.model('T', new Schema({ x: { type: String, select: true }}));
    -T.find(..); // field x will always be selected ..
    -// .. unless overridden;
    -T.find().select('-x').exec(callback);

    SchemaType#doValidate(value, callback, scope)

    Performs a validation of value using the validators declared for this SchemaType.

    show code
    SchemaType.prototype.doValidate = function (value, fn, scope) {
    -  var err = false
    -    , path = this.path
    -    , count = this.validators.length;
    -
    -  if (!count) return fn(null);
    -
    -  function validate (val, msg) {
    -    if (err) return;
    -    if (val === undefined || val) {
    -      --count || fn(null);
    -    } else {
    -      fn(err = new ValidatorError(path, msg));
    -    }
    -  }
    -
    -  this.validators.forEach(function (v) {
    -    var validator = v[0]
    -      , message   = v[1];
    -
    -    if (validator instanceof RegExp) {
    -      validate(validator.test(value), message);
    -    } else if ('function' === typeof validator) {
    -      if (2 === validator.length) {
    -        validator.call(scope, value, function (val) {
    -          validate(val, message);
    -        });
    -      } else {
    -        validate(validator.call(scope, value), message);
    -      }
    -    }
    -  });
    -};

    Parameters:


    SchemaType._isRef(self, value, init)

    Determines if value is a valid Reference.

    show code
    SchemaType._isRef = function (self, value, init) {
    -  if (init && self.options && self.options.ref) {
    -    if (null == value) return true;
    -    if (value._id && value._id.constructor.name === self.instance) return true;
    -  }
    -
    -  return false;
    -}

    Parameters:

    Returns:


  • types/array.js

    MongooseArray(values, path, doc)

    Mongoose Array constructor.

    show code
    function MongooseArray (values, path, doc) {
    -  var arr = [];
    -  arr.push.apply(arr, values);
    -  arr.__proto__ = MongooseArray.prototype;
    -
    -  arr._atomics = {};
    -  arr.validators = [];
    -  arr._path = path;
    -
    -  if (doc) {
    -    arr._parent = doc;
    -    arr._schema = doc.schema.path(path);
    -  }
    -
    -  return arr;
    -};

    Parameters:

    Inherits:

    NOTE:

    - -

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


    MongooseArray#_cast(value)

    Casts a member based on this arrays schema.

    show code
    MongooseArray.prototype._cast = function (value) {
    -  var cast = this._schema.caster.cast
    -    , doc = this._parent;
    -
    -  return cast.call(null, value, doc);
    -};

    Parameters:

    Returns:

    • <value> the casted value

    MongooseArray#_markModified(embeddedDoc, embeddedPath)

    Marks this array as modified.

    show code
    MongooseArray.prototype._markModified = function (embeddedDoc, embeddedPath) {
    -  var parent = this._parent
    -    , dirtyPath;
    -
    -  if (parent) {
    -    if (arguments.length) {
    -      // If an embedded doc bubbled up the change
    -      dirtyPath = [this._path, this.indexOf(embeddedDoc), embeddedPath].join('.');
    -    } else {
    -      dirtyPath = this._path;
    -    }
    -    parent.markModified(dirtyPath);
    -  }
    -
    -  return this;
    -};

    Parameters:

    • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
    • embeddedPath <String> the path which changed in the embeddedDoc

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


    MongooseArray#_registerAtomic(op, val)

    Register an atomic operation with the parent.

    show code
    MongooseArray.prototype._registerAtomic = function (op, val) {
    -  if ('$set' == op) {
    -    // $set takes precedence over all other ops.
    -    // mark entire array modified.
    -    this._atomics = { $set: val };
    -    this._markModified();
    -    return this;
    -  }
    -
    -  var atomics = this._atomics;
    -
    -  // reset pop/shift after save
    -  if ('$pop' == op && !('$pop' in atomics)) {
    -    var self = this;
    -    this._parent.once('save', function () {
    -      self._popped = self._shifted = null;
    -    });
    -  }
    -
    -  if (this._atomics.$set) {
    -    return this;
    -  }
    -
    -  // check for impossible $atomic combos (Mongo denies more than one
    -  // $atomic op on a single path
    -  if (Object.keys(atomics).length && !(op in atomics)) {
    -    // a different op was previously registered.
    -    // save the entire thing.
    -    this._atomics = { $set: this };
    -    this._markModified();
    -    return this;
    -  }
    -
    -  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
    -    atomics[op] || (atomics[op] = []);
    -    atomics[op] = atomics[op].concat(val);
    -  } else if (op === '$pullDocs') {
    -    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
    -      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
    -    selector['$in'] = selector['$in'].concat(val);
    -  } else {
    -    atomics[op] = val;
    -  }
    -
    -  this._markModified();
    -  return this;
    -};

    Parameters:


    MongooseArray#hasAtomics()

    Returns the number of pending atomic operations to send to the db for this array.

    show code
    MongooseArray.prototype.hasAtomics = function hasAtomics () {
    -  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
    -    return 0;
    -  }
    -
    -  return Object.keys(this._atomics).length;
    -}

    Returns:


    MongooseArray#push([args...])

    Wraps Array#push with proper change tracking.

    show code
    MongooseArray.prototype.push = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , ret = [].push.apply(this, values);
    -
    -  // $pushAll might be fibbed (could be $push). But it makes it easier to
    -  // handle what could have been $push, $pushAll combos
    -  this._registerAtomic('$pushAll', values);
    -  return ret;
    -};

    Parameters:


    MongooseArray#nonAtomicPush([args...])

    Pushes items to the array non-atomically.

    show code
    MongooseArray.prototype.nonAtomicPush = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , ret = [].push.apply(this, values);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -};

    Parameters:

    • [args...] <any>

    NOTE:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#$pop()

    Pops the array atomically at most one time per document save().

    NOTE:

    - -

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    - -
    doc.array = [1,2,3];
    -
    - var popped = doc.array.$pop();
    - console.log(popped); // 3
    - console.log(doc.array); // [1,2]
    -
    - // no affect
    - popped = doc.array.$pop();
    - console.log(doc.array); // [1,2]
    -
    - doc.save(function (err) {
    -   if (err) return handleError(err);
    -
    -   // we saved, now $pop works again
    -   popped = doc.array.$pop();
    -   console.log(popped); // 2
    -   console.log(doc.array); // [1]
    - })

    MongooseArray#pop()

    Wraps Array#pop with proper change tracking.

    show code
    MongooseArray.prototype.pop = function () {
    -  var ret = [].pop.call(this);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -};

    Note:

    - -

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#$shift()

    Atomically shifts the array at most one time per document save().

    NOTE:

    - -

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    - -
    doc.array = [1,2,3];
    -
    - var shifted = doc.array.$shift();
    - console.log(shifted); // 1
    - console.log(doc.array); // [2,3]
    -
    - // no affect
    - shifted = doc.array.$shift();
    - console.log(doc.array); // [2,3]
    -
    - doc.save(function (err) {
    -   if (err) return handleError(err);
    -
    -   // we saved, now $shift works again
    -   shifted = doc.array.$shift();
    -   console.log(shifted ); // 2
    -   console.log(doc.array); // [3]
    - })

    MongooseArray#shift()

    Wraps Array#shift with proper change tracking.

    show code
    MongooseArray.prototype.shift = function () {
    -  var ret = [].shift.call(this);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -};

    Example:

    - -
    doc.array = [2,3];
    -var res = doc.array.shift();
    -console.log(res) // 2
    -console.log(doc.array) // [3]
    - -

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#remove([args...])

    Removes items from an array atomically

    show code
    MongooseArray.prototype.remove = function () {
    -  var args = [].map.call(arguments, this._cast, this);
    -  if (args.length == 1)
    -    this.pull(args[0]);
    -  else
    -    this.pull.apply(this, args);
    -  return args;
    -};

    Parameters:

    • [args...] <Object> values to remove

    Examples:

    - -
    doc.array.remove(ObjectId)
    -doc.array.remove('tag 1', 'tag 2')

    MongooseArray#pull([args...])

    Pulls items from the array atomically.

    show code
    MongooseArray.prototype.pull = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , cur = this._parent.get(this._path)
    -    , i = cur.length
    -    , mem;
    -
    -  while (i--) {
    -    mem = cur[i];
    -    if (mem instanceof EmbeddedDocument) {
    -      if (values.some(function (v) { return v.equals(mem); } )) {
    -        [].splice.call(cur, i, 1);
    -      }
    -    } else if (~cur.indexOf.call(values, mem)) {
    -      [].splice.call(cur, i, 1);
    -    }
    -  }
    -
    -  if (values[0] instanceof EmbeddedDocument) {
    -    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
    -  } else {
    -    this._registerAtomic('$pullAll', values);
    -  }
    -
    -  return this;
    -};

    Parameters:

    • [args...] <any>

    MongooseArray#splice()

    Wraps Array#splice with proper change tracking.

    show code
    MongooseArray.prototype.splice = function () {
    -  if (arguments.length) {
    -    var ret = [].splice.apply(this, arguments);
    -    this._registerAtomic('$set', this);
    -  }
    -  return ret;
    -};

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#unshift()

    Wraps Array#unshift with proper change tracking.

    show code
    MongooseArray.prototype.unshift = function () {
    -  var values = [].map.call(arguments, this._cast, this);
    -  [].unshift.apply(this, values);
    -  this._registerAtomic('$set', this);
    -  return this.length;
    -};

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#sort()

    Wraps Array#sort with proper change tracking.

    show code
    MongooseArray.prototype.sort = function () {
    -  var ret = [].sort.apply(this, arguments);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -}

    NOTE:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#addToSet([args...])

    Adds values to the array if not already present.

    show code
    MongooseArray.prototype.addToSet = function addToSet () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , added = []
    -    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
    -             values[0] instanceof Date ? 'date' :
    -             '';
    -
    -  values.forEach(function (v) {
    -    var found;
    -    switch (type) {
    -      case 'doc':
    -        found = this.some(function(doc){ return doc.equals(v) });
    -        break;
    -      case 'date':
    -        var val = +v;
    -        found = this.some(function(d){ return +d === val });
    -        break;
    -      default:
    -        found = ~this.indexOf(v);
    -    }
    -
    -    if (!found) {
    -      [].push.call(this, v);
    -      this._registerAtomic('$addToSet', v);
    -      [].push.call(added, v);
    -    }
    -  }, this);
    -
    -  return added;
    -};

    Parameters:

    • [args...] <any>

    Returns:

    • <Array> the values that were added

    Example:

    - -
    console.log(doc.array) // [2,3,4]
    -var added = doc.array.addToSet(4,5);
    -console.log(doc.array) // [2,3,4,5]
    -console.log(added)     // [5]

    MongooseArray#toObject(options)

    Returns a native js Array.

    show code
    MongooseArray.prototype.toObject = function (options) {
    -  if (options && options.depopulate && this[0] instanceof Document) {
    -    return this.map(function (doc) {
    -      return doc._id;
    -    });
    -  }
    -
    -  // return this.slice()?
    -  return this.map(function (doc) {
    -    return doc;
    -  });
    -};

    Parameters:

    Returns:


    MongooseArray#inspect()

    Helper for console.log

    show code
    MongooseArray.prototype.inspect = function () {
    -  return '[' + this.map(function (doc) {
    -    return ' ' + doc;
    -  }) + ' ]';
    -};

    MongooseArray#indexOf(obj)

    Return the index of obj or -1 if not found.

    show code
    MongooseArray.prototype.indexOf = function indexOf (obj) {
    -  if (obj instanceof ObjectId) obj = obj.toString();
    -  for (var i = 0, len = this.length; i < len; ++i) {
    -    if (obj == this[i])
    -      return i;
    -  }
    -  return -1;
    -};

    Parameters:

    • obj <Object> the item to look for

    Returns:


    MongooseArray#_parent

    Parent owner document


    MongooseArray#_atomics

    Stores a queue of atomic operations to perform


  • types/buffer.js

    MongooseBuffer(value, encode, offset)

    Mongoose Buffer constructor.

    show code
    function MongooseBuffer (value, encode, offset) {
    -  var length = arguments.length;
    -  var val;
    -
    -  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
    -    val = 0;
    -  } else {
    -    val = value;
    -  }
    -
    -  var encoding;
    -  var path;
    -  var doc;
    -
    -  if (Array.isArray(encode)) {
    -    // internal casting
    -    path = encode[0];
    -    doc = encode[1];
    -  } else {
    -    encoding = encode;
    -  }
    -
    -  var buf = new Buffer(val, encoding, offset);
    -  buf.__proto__ = MongooseBuffer.prototype;
    -
    -  // make sure these internal props don't show up in Object.keys()
    -  Object.defineProperties(buf, {
    -      validators: { value: [] }
    -    , _path: { value: path }
    -    , _parent: { value: doc }
    -  });
    -
    -  if (doc && "string" === typeof path) {
    -    Object.defineProperty(buf, '_schema', {
    -        value: doc.schema.path(path)
    -    });
    -  }
    -
    -  return buf;
    -};

    Parameters:

    Inherits:

    Values always have to be passed to the constructor to initialize.


    MongooseBuffer#_markModified()

    Marks this buffer as modified.

    show code
    MongooseBuffer.prototype._markModified = function () {
    -  var parent = this._parent;
    -
    -  if (parent) {
    -    parent.markModified(this._path);
    -  }
    -  return this;
    -};

    MongooseBuffer#write()

    Writes the buffer.

    show code
    MongooseBuffer.prototype.write = function () {
    -  var written = Buffer.prototype.write.apply(this, arguments);
    -
    -  if (written > 0) {
    -    this._markModified();
    -  }
    -
    -  return written;
    -};

    MongooseBuffer#copy(target)

    Copies the buffer.

    show code
    MongooseBuffer.prototype.copy = function (target) {
    -  var ret = Buffer.prototype.copy.apply(this, arguments);
    -
    -  if (target instanceof MongooseBuffer) {
    -    target._markModified();
    -  }
    -
    -  return ret;
    -};

    Parameters:

    Returns:

    Note:

    - -

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


    MongooseBuffer#toObject([subtype])

    Converts this buffer to its Binary type representation.

    show code
    MongooseBuffer.prototype.toObject = function (subtype) {
    -  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
    -  return new Binary(this, subtype);
    -};

    Parameters:

    • [subtype] <Hex>

    Returns:

    SubTypes:

    - -
      -
    • 0x00: Binary/Generic
    • -
    • 0x01: Function
    • -
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • -
    • 0x03: UUID
    • -
    • 0x04: MD5
    • -
    • 0x80: User Defined
    • -

    MongooseBuffer#_parent

    Parent owner document


  • types/documentarray.js

    MongooseDocumentArray(values, path, doc)

    DocumentArray constructor

    show code
    function MongooseDocumentArray (values, path, doc) {
    -  var arr = [];
    -
    -  // Values always have to be passed to the constructor to initialize, since
    -  // otherwise MongooseArray#push will mark the array as modified to the parent.
    -  arr.push.apply(arr, values);
    -  arr.__proto__ = MongooseDocumentArray.prototype;
    -
    -  arr._atomics = {};
    -  arr.validators = [];
    -  arr._path = path;
    -
    -  if (doc) {
    -    arr._parent = doc;
    -    arr._schema = doc.schema.path(path);
    -    doc.on('save', arr.notify('save'));
    -    doc.on('isNew', arr.notify('isNew'));
    -  }
    -
    -  return arr;
    -};

    Parameters:

    Inherits:


    MongooseDocumentArray#_cast()

    Overrides MongooseArray#cast

    show code
    MongooseDocumentArray.prototype._cast = function (value) {
    -  var doc = new this._schema.casterConstructor(value, this);
    -  return doc;
    -};

    MongooseDocumentArray#id(id)

    Searches array items for the first document with a matching id.

    show code
    MongooseDocumentArray.prototype.id = function (id) {
    -  var casted
    -    , _id;
    -
    -  try {
    -    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
    -  } catch (e) {
    -    casted = null;
    -  }
    -
    -  for (var i = 0, l = this.length; i < l; i++) {
    -    _id = this[i].get('_id');
    -    if (!(_id instanceof ObjectId)) {
    -      if (String(id) == _id)
    -        return this[i];
    -    } else {
    -      if (casted == _id)
    -        return this[i];
    -    }
    -  }
    -
    -  return null;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var embeddedDoc = m.array.id(some_id);

    MongooseDocumentArray#toObject()

    Returns a native js Array of plain js objects

    show code
    MongooseDocumentArray.prototype.toObject = function () {
    -  return this.map(function (doc) {
    -    return doc && doc.toObject() || null;
    -  });
    -};

    Returns:

    NOTE:

    - -

    Each sub-document is converted to a plain object by calling its #toObject method.


    MongooseDocumentArray#inspect()

    Helper for console.log

    show code
    MongooseDocumentArray.prototype.inspect = function () {
    -  return '[' + this.map(function (doc) {
    -    if (doc) {
    -      return doc.inspect
    -        ? doc.inspect()
    -        : util.inspect(doc)
    -    }
    -    return 'null'
    -  }).join('
    -') + ']';
    -};

    MongooseDocumentArray#create(obj)

    Creates a subdocument casted to this schema.

    show code
    MongooseDocumentArray.prototype.create = function (obj) {
    -  return new this._schema.casterConstructor(obj);
    -}

    Parameters:

    • obj <Object> the value to cast to this arrays SubDocument schema

    This is the same subdocument constructor used for casting.


    MongooseDocumentArray#notify(event)

    Creates a fn that notifies all child docs of event.

    show code
    MongooseDocumentArray.prototype.notify = function notify (event) {
    -  var self = this;
    -  return function notify (val) {
    -    var i = self.length;
    -    while (i--) {
    -      self[i].emit(event, val);
    -    }
    -  }
    -}

    Parameters:

    Returns:


  • types/embedded.js

    EmbeddedDocument(obj, parentArr, skipId)

    EmbeddedDocument constructor.

    show code
    function EmbeddedDocument (obj, parentArr, skipId, fields) {
    -  if (parentArr) {
    -    this.__parentArray = parentArr;
    -    this.__parent = parentArr._parent;
    -  } else {
    -    this.__parentArray = undefined;
    -    this.__parent = undefined;
    -  }
    -
    -  Document.call(this, obj, fields, skipId);
    -
    -  var self = this;
    -  this.on('isNew', function (val) {
    -    self.isNew = val;
    -  });
    -};

    Parameters:

    Inherits:


    EmbeddedDocument#markModified(path)

    Marks the embedded doc modified.

    show code
    EmbeddedDocument.prototype.markModified = function (path) {
    -  if (!this.__parentArray) return;
    -
    -  this._activePaths.modify(path);
    -
    -  if (this.isNew) {
    -    // Mark the WHOLE parent array as modified
    -    // if this is a new document (i.e., we are initializing
    -    // a document),
    -    this.__parentArray._markModified();
    -  } else
    -    this.__parentArray._markModified(this, path);
    -};

    Parameters:

    • path <String> the path which changed

    Example:

    - -
    var doc = blogpost.comments.id(hexstring);
    -doc.mixed.type = 'changed';
    -doc.markModified('mixed.type');

    EmbeddedDocument#save([fn])

    Used as a stub for hooks.js

    show code
    EmbeddedDocument.prototype.save = function(fn) {
    -  if (fn)
    -    fn(null);
    -  return this;
    -};

    Parameters:

    Returns:

    NOTE:

    - -

    This is a no-op. Does not actually save the doc to the db.


    EmbeddedDocument#remove([fn])

    Removes the subdocument from its parent array.

    show code
    EmbeddedDocument.prototype.remove = function (fn) {
    -  if (!this.__parentArray) return this;
    -
    -  var _id;
    -  if (!this.willRemove) {
    -    _id = this._doc._id;
    -    if (!_id) {
    -      throw new Error('For your own good, Mongoose does not know ' + 
    -                      'how to remove an EmbeddedDocument that has no _id');
    -    }
    -    this.__parentArray.pull({ _id: _id });
    -    this.willRemove = true;
    -  }
    -
    -  if (fn)
    -    fn(null);
    -
    -  return this;
    -};

    Parameters:


    EmbeddedDocument#update()

    Override #update method of parent documents.

    show code
    EmbeddedDocument.prototype.update = function () {
    -  throw new Error('The #update method is not available on EmbeddedDocuments');
    -}

    EmbeddedDocument#inspect()

    Helper for console.log

    show code
    EmbeddedDocument.prototype.inspect = function () {
    -  return inspect(this.toObject());
    -};

    EmbeddedDocument#invalidate(path, err)

    Marks a path as invalid, causing validation to fail.

    show code
    EmbeddedDocument.prototype.invalidate = function (path, err, first) {
    -  if (!this.__parent) return false;
    -  var index = this.__parentArray.indexOf(this);
    -  var parentPath = this.__parentArray._path;
    -  var fullPath = [parentPath, index, path].join('.');
    -  this.__parent.invalidate(fullPath, err);
    -  if (first)
    -    this._validationError = ownerDocument(this)._validationError;
    -  return true;
    -}

    Parameters:

    • path <String> the field to invalidate
    • err <String, Error> error which states the reason `path` was invalid

    Returns:


    EmbeddedDocument#ownerDocument()

    Returns the top level document of this sub-document.

    show code
    EmbeddedDocument.prototype.ownerDocument = function () {
    -  return ownerDocument(this);
    -}

    Returns:


    EmbeddedDocument#parent()

    Returns this sub-documents parent document.

    show code
    EmbeddedDocument.prototype.parent = function () {
    -  return this.__parent;
    -}

    EmbeddedDocument#parentArray()

    Returns this sub-documents parent array.

    show code
    EmbeddedDocument.prototype.parentArray = function () {
    -  return this.__parentArray;
    -}

  • types/objectid.js

    ObjectId()

    ObjectId type constructor

    Example

    - -
    var id = new mongoose.Types.ObjectId;

    ObjectId.fromString(str)

    Creates an ObjectId from str

    show code
    ObjectId.fromString;

    Parameters:

    Returns:


    ObjectId.toString(oid)

    Converts oid to a string.

    show code
    ObjectId.toString;

    Parameters:

    Returns:


  • utils.js

    exports.toCollectionName(name)

    Produces a collection name from model name.

    show code
    exports.toCollectionName = function (name) {
    -  if ('system.profile' === name) return name;
    -  if ('system.indexes' === name) return name;
    -  return pluralize(name.toLowerCase());
    -};

    Parameters:

    Returns:


    exports.pluralization

    Pluralization rules.

    show code
    exports.pluralization = [
    -  [/(m)an$/gi, '$1en'],
    -  [/(pe)rson$/gi, '$1ople'],
    -  [/(child)$/gi, '$1ren'],
    -  [/^(ox)$/gi, '$1en'],
    -  [/(ax|test)is$/gi, '$1es'],
    -  [/(octop|vir)us$/gi, '$1i'],
    -  [/(alias|status)$/gi, '$1es'],
    -  [/(bu)s$/gi, '$1ses'],
    -  [/(buffal|tomat|potat)o$/gi, '$1oes'],
    -  [/([ti])um$/gi, '$1a'],
    -  [/sis$/gi, 'ses'],
    -  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
    -  [/(hive)$/gi, '$1s'],
    -  [/([^aeiouy]|qu)y$/gi, '$1ies'],
    -  [/(x|ch|ss|sh)$/gi, '$1es'],
    -  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
    -  [/([m|l])ouse$/gi, '$1ice'],
    -  [/(quiz)$/gi, '$1zes'],
    -  [/s$/gi, 's'],
    -  [/$/gi, 's']
    -];
    -var rules = exports.pluralization;

    These rules are applied while processing the argument to toCollectionName.


    exports.uncountables

    Uncountable words.

    show code
    exports.uncountables = [
    -  'advice',
    -  'energy',
    -  'excretion',
    -  'digestion',
    -  'cooperation',
    -  'health',
    -  'justice',
    -  'labour',
    -  'machinery',
    -  'equipment',
    -  'information',
    -  'pollution',
    -  'sewage',
    -  'paper',
    -  'money',
    -  'species',
    -  'series',
    -  'rain',
    -  'rice',
    -  'fish',
    -  'sheep',
    -  'moose',
    -  'deer',
    -  'news'
    -];
    -var uncountables = exports.uncountables;

    These words are applied while processing the argument to toCollectionName.


    exports.deepEqual(a, b)

    Determines if a and b are deep equal.

    show code
    exports.deepEqual = function deepEqual (a, b) {
    -  if (a === b) return true;
    -
    -  if (a instanceof Date && b instanceof Date)
    -    return a.getTime() === b.getTime();
    -
    -  if (a instanceof ObjectId && b instanceof ObjectId) {
    -    return a.toString() === b.toString();
    -  }
    -
    -  if (typeof a !== 'object' && typeof b !== 'object')
    -    return a == b;
    -
    -  if (a === null || b === null || a === undefined || b === undefined)
    -    return false
    -
    -  if (a.prototype !== b.prototype) return false;
    -
    -  // Handle MongooseNumbers
    -  if (a instanceof Number && b instanceof Number) {
    -    return a.valueOf() === b.valueOf();
    -  }
    -
    -  if (Buffer.isBuffer(a)) {
    -    if (!Buffer.isBuffer(b)) return false;
    -    if (a.length !== b.length) return false;
    -    for (var i = 0, len = a.length; i < len; ++i) {
    -      if (a[i] !== b[i]) return false;
    -    }
    -    return true;
    -  }
    -
    -  if (isMongooseObject(a)) a = a.toObject();
    -  if (isMongooseObject(b)) b = b.toObject();
    -
    -  try {
    -    var ka = Object.keys(a),
    -        kb = Object.keys(b),
    -        key, i;
    -  } catch (e) {//happens when one is a string literal and the other isn't
    -    return false;
    -  }
    -
    -  // having the same number of owned properties (keys incorporates
    -  // hasOwnProperty)
    -  if (ka.length != kb.length)
    -    return false;
    -
    -  //the same set of keys (although not necessarily the same order),
    -  ka.sort();
    -  kb.sort();
    -
    -  //~~~cheap key test
    -  for (i = ka.length - 1; i >= 0; i--) {
    -    if (ka[i] != kb[i])
    -      return false;
    -  }
    -
    -  //equivalent values for every corresponding key, and
    -  //~~~possibly expensive deep test
    -  for (i = ka.length - 1; i >= 0; i--) {
    -    key = ka[i];
    -    if (!deepEqual(a[key], b[key])) return false;
    -  }
    -
    -  return true;
    -};

    Parameters:

    • a <any> a value to compare to `b`
    • b <any> a value to compare to `a`

    Returns:

    Modified from node/lib/assert.js


    exports.clone(obj, options)

    Object clone with Mongoose natives support.

    show code
    exports.clone = function clone (obj, options) {
    -  if (obj === undefined || obj === null)
    -    return obj;
    -
    -  if (Array.isArray(obj))
    -    return cloneArray(obj, options);
    -
    -  if (isMongooseObject(obj)) {
    -    if (options && options.json && 'function' === typeof obj.toJSON) {
    -      return obj.toJSON(options);
    -    } else {
    -      return obj.toObject(options);
    -    }
    -  }
    -
    -  if ('Object' === obj.constructor.name)
    -    return cloneObject(obj, options);
    -
    -  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
    -    return new obj.constructor(+obj);
    -
    -  if ('RegExp' === obj.constructor.name)
    -    return new RegExp(obj.source);
    -
    -  if (obj instanceof ObjectId) {
    -    return new ObjectId(obj.id);
    -  }
    -
    -  if (obj.valueOf)
    -    return obj.valueOf();
    -};
    -var clone = exports.clone;

    Parameters:

    Returns:

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.


    exports.options(defaults, options)

    Copies and merges options with defaults.

    show code
    exports.options = function (defaults, options) {
    -  var keys = Object.keys(defaults)
    -    , i = keys.length
    -    , k ;
    -
    -  options = options || {};
    -
    -  while (i--) {
    -    k = keys[i];
    -    if (!(k in options)) {
    -      options[k] = defaults[k];
    -    }
    -  }
    -
    -  return options;
    -};

    Parameters:

    Returns:


    exports.random()

    Generates a random string

    show code
    exports.random = function () {
    -  return Math.random().toString().substr(3);
    -};

    exports.merge(to, from)

    Merges from into to without overwriting existing properties.

    show code
    exports.merge = function merge (to, from) {
    -  var keys = Object.keys(from)
    -    , i = keys.length
    -    , key
    -
    -  while (i--) {
    -    key = keys[i];
    -    if ('undefined' === typeof to[key]) {
    -      to[key] = from[key];
    -    } else {
    -      merge(to[key], from[key]);
    -    }
    -  }
    -};

    Parameters:


    exports.args()

    A faster Array.prototype.slice.call(arguments) alternative

    show code
    exports.args = function (args, slice, sliceEnd) {
    -  var ret = [];
    -  var start = slice || 0;
    -  var end = 3 === arguments.length
    -    ? sliceEnd
    -    : args.length;
    -
    -  for (var i = start; i < end; ++i) {
    -    ret[i - start] = args[i];
    -  }
    -
    -  return ret;
    -}

    exports.tick(callback)

    process.nextTick helper.

    show code
    exports.tick = function tick (callback) {
    -  if ('function' !== typeof callback) return;
    -  return function () {
    -    try {
    -      callback.apply(this, arguments);
    -    } catch (err) {
    -      // only nextTick on err to get out of
    -      // the event loop and avoid state corruption.
    -      process.nextTick(function () {
    -        throw err;
    -      });
    -    }
    -  }
    -}

    Parameters:

    Wraps callback in a try/catch + nextTick.

    - -

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


    exports.isMongooseObject(v)

    Returns if v is a mongoose object that has a toObject() method we can use.

    show code
    exports.isMongooseObject = function (v) {
    -  Document || (Document = require('./document'));
    -  MongooseArray || (MongooseArray = require('./types').Array);
    -  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
    -
    -  return v instanceof Document ||
    -         v instanceof MongooseArray ||
    -         v instanceof MongooseBuffer
    -}
    -var isMongooseObject = exports.isMongooseObject;

    Parameters:

    This is for compatibility with libs like Date.js which do foolish things to Natives.


    exports.expires(object)

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    show code
    exports.expires = function expires (object) {
    -  if (!(object && 'Object' == object.constructor.name)) return;
    -  if (!('expires' in object)) return;
    -
    -  var when;
    -  if ('string' != typeof object.expires) {
    -    when = object.expires;
    -  } else {
    -    when = Math.round(ms(object.expires) / 1000);
    -  }
    -  object.expiresAfterSeconds = when;
    -  delete object.expires;
    -}
    -
    -exports.readPref = function readPref (pref, tags) {
    -  if (Array.isArray(pref)) {
    -    tags = pref[1];
    -    pref = pref[0];
    -  }
    -
    -  switch (pref) {
    -    case 'p':
    -      pref = 'primary';
    -      break;
    -    case 'pp':
    -      pref = 'primaryPrefered';
    -      break;
    -    case 's':
    -      pref = 'secondary';
    -      break;
    -    case 'sp':
    -      pref = 'secondaryPrefered';
    -      break;
    -    case 'n':
    -      pref = 'nearest';
    -      break;
    -  }
    -
    -  return new ReadPref(pref, tags);
    -}

    Parameters:


  • virtualtype.js

    VirtualType()

    VirtualType constructor

    show code
    function VirtualType (options, name) {
    -  this.path = name;
    -  this.getters = [];
    -  this.setters = [];
    -  this.options = options || {};
    -}

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    - -

    Example:

    - -
    var fullname = schema.virtual('fullname');
    -fullname instanceof mongoose.VirtualType // true

    VirtualType#get(fn)

    Defines a getter.

    show code
    VirtualType.prototype.get = function (fn) {
    -  this.getters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var virtual = schema.virtual('fullname');
    -virtual.get(function () {
    -  return this.name.first + ' ' + this.name.last;
    -});

    VirtualType#set(fn)

    Defines a setter.

    show code
    VirtualType.prototype.set = function (fn) {
    -  this.setters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var virtual = schema.virtual('fullname');
    -virtual.set(function (v) {
    -  var parts = v.split(' ');
    -  this.name.first = parts[0];
    -  this.name.last = parts[1];
    -});

    VirtualType#applyGetters(value, scope)

    Applies getters to value using optional scope.

    show code
    VirtualType.prototype.applyGetters = function (value, scope) {
    -  var v = value;
    -  for (var l = this.getters.length - 1; l >= 0; l--) {
    -    v = this.getters[l].call(scope, v, this);
    -  }
    -  return v;
    -};

    Parameters:

    Returns:

    • <any> the value after applying all getters

    VirtualType#applySetters(value, scope)

    Applies setters to value using optional scope.

    show code
    VirtualType.prototype.applySetters = function (value, scope) {
    -  var v = value;
    -  for (var l = this.setters.length - 1; l >= 0; l--) {
    -    v = this.setters[l].call(scope, v, this);
    -  }
    -  return v;
    -};

    Parameters:

    Returns:

    • <any> the value after applying all setters

diff --git a/docs/3.1.x/docs/api.jade b/docs/3.1.x/docs/api.jade deleted file mode 100644 index 91e18ee6293..00000000000 --- a/docs/3.1.x/docs/api.jade +++ /dev/null @@ -1,508 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose API v#{package.version} - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - style. - body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; - } - a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; - } - a:hover { - opacity: 0.8; - } - #wrap { - } - h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; - } - pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; - } - code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Monaco; - } - pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; - } - h3 { - padding: 20px 15px; - margin-left: -15px; - } - h3 code { - font-weight: normal; - } - hr { - height: 1px; - border: 0 none; - padding: 0; - margin: 60px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) - } - .doclinks hr { - margin: 10px 0; - } - li { - list-style: square; - } - #header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; - } - #header h1 { - margin-top: 0; - margin-bottom: 0; - } - #header h1 a { - text-decoration: none; - } - #header .mongoose { - font-size: 50px; - font-weight: 100; - color: #fff; - text-shadow: 6px 4px 5px #777, -2px 0px 2px white; - letter-spacing: -7px; - } - #links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - } - #links hr { - margin: 32px 0; - } - #content { - padding: 0; - margin: 0 0 30px 230px; - overflow-x: hidden; - } - #content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; - } - #content .controls:hover { - opacity: .9; - } - #content p { - word-wrap: break-word; - } - #content > ul { - margin: 0; - padding: 0; - } - .private { - display: none; - } - .section { - font-size: 15px; - } - .doclinks li.private a:before, - .doclinks .module.private a:before, - .doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; - } - #content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; - } - .module { - list-style: none; - padding: 30px 0 30px 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; - } - .module > * { - max-width: 700px; - } - .item:last-child { - margin-bottom: 90px; - } - .item:last-child > hr { - display: none; - } - .item h3 a { - color: #333; - text-decoration: none; - } - .property h3 span { - color: #444; - } - .description { - margin-top: 25px; - } - .sourcecode { - display: none; - } - .showcode { - font-size: 12px; - cursor: pointer; - display: none; - } - .load .showcode { - display: block; - } - .types a { - text-decoration: none; - } - @media only screen and (device-width: 768px) { - - } - @media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links hr { - display: none; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - .controls { display: none; } - } - body.api - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - hr - .doclinks - each item in docs - .file(class=item.hasPublic ? '' : 'private') - a.section(href='#' + item.title.replace(/[\.\/#]/g, '-'))= item.title - ul - each method in item.methods - if method.ctx && !method.ignore - li(class= method.isPrivate ? 'private' : '') - case method.ctx.type - when 'method' - id = method.ctx.constructor + '-' + method.ctx.name - when 'function' - id = method.ctx.name - default - id = '' - url = href(klass(item.title) + '_' + id) - a(href='#' + url)= method.ctx.name - each stat in item.statics - if stat.ctx && !stat.ignore - li(class= stat.isPrivate ? 'private' : '') - case stat.ctx.type - when 'method' - id = stat.ctx.receiver + '-' + stat.ctx.name - when 'property' - id = stat.ctx.receiver + '-' + stat.ctx.name - when 'function' - id = stat.ctx.name - url = href(klass(item.title) + '_' + id) - a(href='#' + url)= stat.ctx.name - each property in item.props - if property.ctx && !property.ignore - li(class= property.isPrivate ? 'private' : '') - construct = property.ctx.receiver || property.ctx.constructor - link = href(construct) + '-' + href(property.ctx.name) - url = href(klass(item.title) + '_' + link) - a(href='#' + url)= property.ctx.name - #content - .controls - label - input(type='checkbox') - | private - ul - each item in docs - li.module(class=item.hasPublic ? '' : 'private') - a(href=github + package.version + '/' + item.title, id=item.title.replace(/[\.\/#]/g, '-'))= item.title - each method in item.methods - div.item.method(class= method.isPrivate ? 'private' : 'public') - if method.ctx - case method.ctx.type - when 'method' - id = method.ctx.constructor + '-' + method.ctx.name - text = method.ctx.constructor + '#' + method.ctx.name - when 'function' - id = method.ctx.name - text = method.ctx.name - default - text = '' - url = href(klass(item.title) + '_' + text) - h3(id= url) - a(href= '#' + url) - = text - | ( - each tag, i in method.params - code= tag.name - if i+1 < method.params.length - | , - | ) - else - - // console.log('\nmissing method name', method); - h3 MISSING method name - != method.description.summary - if method.code - span.showcode show code - .sourcecode - != hl(method.code) - if method.params.length - .params - h4 Parameters: - ul - each tag in method.params - li - code= tag.name - if tag.types && tag.types.length - span.types - | < - each type, i in tag.types - != linktype(type) - if i+1 < tag.types.length - | , - | > - span= tag.description - if method.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in method.return.types - != linktype(type) - if i+1 < method.return.types.length - | , - | > - span= method.return.description - if method.inherits - .inherits - h4 Inherits: - ul - li - != method.inherits - if method.events && method.events.length - .events - h4 Events: - ul - each event in method.events - li - != event.string - if method.see.length - .see - h4 See: - ul.see - each see in method.see - li - url = see.url || see.local - a(href=url, title=see.title || see.local)= see.title || see.url || see.local - div.description - != method.description.body - hr(class= method.isPrivate ? 'private' : '') - each stat in item.statics - div.item.static(class= stat.isPrivate ? 'private' : 'public') - if stat.ctx - case stat.ctx.type - when 'method' - id = stat.ctx.receiver + '-' + stat.ctx.name - text = stat.ctx.receiver + '.' + stat.ctx.name - when 'property' - id = stat.ctx.receiver + '-' + stat.ctx.name - text = stat.ctx.receiver + '.' + stat.ctx.name - when 'function' - id = stat.ctx.name - text = stat.ctx.name - default - text = '' - url = href(klass(item.title) + '_' + id) - h3(id= url) - a(href= '#' + url) - = text - if 'property' != stat.ctx.type - | ( - each tag, i in stat.params - code= tag.name - if i+1 < stat.params.length - | , - | ) - else - - // console.log('\nmissing static name', stat); - h3 MISSING stat name - != stat.description.summary - if stat.code - span.showcode show code - .sourcecode - != hl(stat.code) - if stat.params.length - .params - h4 Parameters: - ul - each tag in stat.params - li - - if (!tag.name) - - // console.log(tag) - code= tag.name - if tag.types && tag.types.length - span.types - | < - each type, i in tag.types - != linktype(type) - if i+1 < tag.types.length - | , - | > - span= tag.description - if stat.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in stat.return.types - != linktype(type) - if i+1 < stat.return.types.length - | , - | > - span= stat.return.description - if stat.inherits - .inherits - h4 Inherits: - ul - li - != stat.inherits - if stat.see.length - .see - h4 See: - ul.see - each see in stat.see - li - url = see.url || see.local - a(href=url, title=see.title || see.local)= see.title || see.url || see.local - != stat.description.body - hr(class= stat.isPrivate ? 'private' : '') - each property in item.props - div.item.property(class= property.ignore || property.isPrivate ? 'private' : 'public') - construct = property.ctx.receiver || property.ctx.constructor - link = href(construct) + '-' + href(property.ctx.name) - url = href(klass(item.title) + '_' + link) - h3(id = url) - a(href= '#' + url) - = construct + '#' - span= property.ctx.name - != property.description.full - if property.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in property.return.types - != linktype(type) - if i+1 < property.return.types.length - | , - | > - span= property.return.description - hr(class= property.isPrivate ? 'private' : '') - script. - document.body.className = 'load'; - include includes/googleanalytics - script(src="/docs/js/zepto.min.js") - script. - $(".module").on("click", ".showcode", function (e) { - $(this).closest(".item").find(".sourcecode").first().toggle(); - }); - $("#content .controls input").on("click", function (e) { - $(".private").toggle() - }) diff --git a/docs/3.1.x/docs/contributing.html b/docs/3.1.x/docs/contributing.html deleted file mode 100644 index 0cf42a44ec6..00000000000 --- a/docs/3.1.x/docs/contributing.html +++ /dev/null @@ -1,11 +0,0 @@ -Mongoose Contributing v3.1.2Fork me on GitHub

Contributing

Bugfixes

  • Before starting to write code, look for existing tickets or create one for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch.
  • Fork the repo or for small documentation changes, navigate to the source on github and click the Edit button.
  • Write inline documentation for new methods or class members.
  • Write tests and make sure they pass (execute make test from the cmd line to run the test suite).
  • Follow the general coding style of the rest of the project (comma first, etc).

Documentation

To contribute to the API documentation just make your changes to the inline documentation of the appropriate source code in the master branch and submit a pull request. You might also use the github Edit button.

- -

To contribute to the guide or quick start docs, make your changes to the appropriate .jade files in the docs directory of the master branch and submit a pull request. Again, the Edit button might work for you here.

Plugins

The plugins site is also an open source project that you can get involved with. Feel free to fork and improve it as well!

diff --git a/docs/3.1.x/docs/contributing.jade b/docs/3.1.x/docs/contributing.jade deleted file mode 100644 index eb6cc091510..00000000000 --- a/docs/3.1.x/docs/contributing.jade +++ /dev/null @@ -1,22 +0,0 @@ -extends layout - -block content - h2 Contributing - - h3 Bugfixes - :markdown - - Before starting to write code, look for existing [tickets](https://github.com/learnboost/mongoose/issues) or [create one](https://github.com/learnboost/mongoose/issues/new) for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. - - Fork the [repo](https://github.com/learnboost/mongoose) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. - - Write inline documentation for new methods or class members. - - Write tests and make sure they pass (execute `make test` from the cmd line to run the test suite). - - Follow the general coding style of the rest of the project (comma first, etc). - - h3 Documentation - :markdown - To contribute to the [API documentation](./api.html) just make your changes to the inline documentation of the appropriate [source code](https://github.com/LearnBoost/mongoose/tree/master/lib) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. - - To contribute to the [guide](./guide.html) or [quick start](./index.html) docs, make your changes to the appropriate `.jade` files in the [docs](https://github.com/LearnBoost/mongoose/tree/master/docs) directory of the master branch and submit a pull request. Again, the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button might work for you here. - - h3 Plugins - :markdown - The [plugins](http://plugins.mongoosejs.com/) site is also an [open source project](https://github.com/aheckmann/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! diff --git a/docs/3.1.x/docs/css/default.css b/docs/3.1.x/docs/css/default.css deleted file mode 100644 index ccb22728ed3..00000000000 --- a/docs/3.1.x/docs/css/default.css +++ /dev/null @@ -1,135 +0,0 @@ -/* - -Original style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ - -pre code { - display: block; padding: 0.5em; - background: #F0F0F0; -} - -pre code, -pre .ruby .subst, -pre .tag .title, -pre .lisp .title, -pre .clojure .built_in, -pre .nginx .title { - color: black; -} - -pre .string, -pre .title, -pre .constant, -pre .parent, -pre .tag .value, -pre .rules .value, -pre .rules .value .number, -pre .preprocessor, -pre .ruby .symbol, -pre .ruby .symbol .string, -pre .ruby .symbol .keyword, -pre .ruby .symbol .keymethods, -pre .instancevar, -pre .aggregate, -pre .template_tag, -pre .django .variable, -pre .smalltalk .class, -pre .addition, -pre .flow, -pre .stream, -pre .bash .variable, -pre .apache .tag, -pre .apache .cbracket, -pre .tex .command, -pre .tex .special, -pre .erlang_repl .function_or_atom, -pre .markdown .header { - color: #800; -} - -pre .comment, -pre .annotation, -pre .template_comment, -pre .diff .header, -pre .chunk, -pre .markdown .blockquote { - color: #888; -} - -pre .number, -pre .date, -pre .regexp, -pre .literal, -pre .smalltalk .symbol, -pre .smalltalk .char, -pre .go .constant, -pre .change, -pre .markdown .bullet, -pre .markdown .link_url { - color: #080; -} - -pre .label, -pre .javadoc, -pre .ruby .string, -pre .decorator, -pre .filter .argument, -pre .localvars, -pre .array, -pre .attr_selector, -pre .important, -pre .pseudo, -pre .pi, -pre .doctype, -pre .deletion, -pre .envvar, -pre .shebang, -pre .apache .sqbracket, -pre .nginx .built_in, -pre .tex .formula, -pre .erlang_repl .reserved, -pre .input_number, -pre .markdown .link_label, -pre .vhdl .attribute, -pre .clojure .attribute { - color: #88F -} - -pre .keyword, -pre .id, -pre .phpdoc, -pre .title, -pre .built_in, -pre .aggregate, -pre .css .tag, -pre .javadoctag, -pre .phpdoc, -pre .yardoctag, -pre .smalltalk .class, -pre .winutils, -pre .bash .variable, -pre .apache .tag, -pre .go .typename, -pre .tex .command, -pre .markdown .strong, -pre .request, -pre .status { - font-weight: bold; -} - -pre .markdown .emphasis { - font-style: italic; -} - -pre .nginx .built_in { - font-weight: normal; -} - -pre .coffeescript .javascript, -pre .xml .css, -pre .xml .javascript, -pre .xml .vbscript, -pre .tex .formula { - opacity: 0.5; -} diff --git a/docs/3.1.x/docs/css/guide.css b/docs/3.1.x/docs/css/guide.css deleted file mode 100644 index 51a5046fc24..00000000000 --- a/docs/3.1.x/docs/css/guide.css +++ /dev/null @@ -1,283 +0,0 @@ -html, body, #content { - height: 100%; -} -.module { - min-height: 100%; - box-sizing: border-box; -} -body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; -} -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; -} -code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Monaco; - /*text-shadow: 1px 2px 2px #555;*/ -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -h2 { - margin-top: 0; -} -h3 { padding-top: 35px; } -h3 code { - font-weight: normal; -} -hr { - display: none; - height: 1px; - border: 0 none; - padding: 0; - margin: 90px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) -} -.doclinks hr { - margin: 10px 0; -} -li { - list-style: square; -} -#header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -#header .mongoose { - font-size: 50px; - font-weight: 100; - color: #fff; - text-shadow: 6px 4px 5px #777, -2px 0px 2px white; - letter-spacing: -7px; -} -#links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; -} -#links .schematypes span { - display: none; -} -#content { - padding: 0; - margin: 0 0 0 230px; - overflow-x: hidden; -} -#content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -#content .controls:hover { - opacity: .9; -} -#content p { - word-wrap: break-word; -} -#content > ul { - margin: 0; - padding: 0; -} -.private { - display: none; -} -.doclinks li.private a:before, -.doclinks .module.private a:before, -.doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; -} -#content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; -} -.module { - list-style: none; - padding: 30px 0 0 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; -} -.module > * { - max-width: 700px; -} -.item { - margin-bottom: 175px; -} -.item h3 a { - color: #333; - text-decoration: none; -} -.property h3 span { - color: #444; -} -.description { - margin-top: 25px; -} -.sourcecode { - display: none; -} -.showcode { - font-size: 12px; - cursor: pointer; - display: none; -} -.load .showcode { - display: block; -} -.types a { - text-decoration: none; -} -li.guide ul { - padding-left: 16px; -} - -@media only screen and (device-width: 768px) { - -} -@media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - html, body, #content { - height: auto; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - #links li.guide { - display: block; - width: 390px; - margin-bottom: 15px; - } - #links li.guide > a { - display: none; - } - #links li ul li { - width: 44%; - text-align: left; - } - #links li ul li ul li { - width: 95%; - } - #links .plugins, - #links .changelog { - display: none; - } - #links .schematypes span { - display: inline; - } - #links .double { - width: 332px; - } - #links .double > ul { - display: inline; - float: right; - } - #links .double > ul li { - width: 155px; - } -} diff --git a/docs/3.1.x/docs/documents.html b/docs/3.1.x/docs/documents.html deleted file mode 100644 index e2f6ef40cbd..00000000000 --- a/docs/3.1.x/docs/documents.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose Documents v3.1.2Fork me on GitHub

Documents

Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

Retrieving

There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

Updating

There are a number of ways to update documents. We'll first look at a traditional approach using findById:

Tank.findById(id, function (err, tank) {
-  if (err) return handleError(err);
-  
-  tank.size = 'large';
-  tank.save(function (err) {
-    if (err) return handleError(err);
-    res.send(tank);
-  });
-});

This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

If we do need the document returned in our application there is another, often better, option:

Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
-  if (err) return handleError(err);
-  res.send(tank);
-});

The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

Validating

Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

Next Up

Now that we've covered Documents, let's take a look at Sub-documents.

diff --git a/docs/3.1.x/docs/documents.jade b/docs/3.1.x/docs/documents.jade deleted file mode 100644 index 67134e821b3..00000000000 --- a/docs/3.1.x/docs/documents.jade +++ /dev/null @@ -1,42 +0,0 @@ -extends layout - -block content - h2 Documents - :markdown - Mongoose [documents](./api.html#document-js) represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its [Model](./models.html). - h3 Retrieving - :markdown - There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on [querying](./queries.html) for detail. - h3 Updating - :markdown - There are a number of ways to update documents. We'll first look at a traditional approach using [findById](./api.html#model_Model-findById): - :js - Tank.findById(id, function (err, tank) { - if (err) return handleError(err); - - tank.size = 'large'; - tank.save(function (err) { - if (err) return handleError(err); - res.send(tank); - }); - }); - :markdown - This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model-update) is right for us: - :js - Tank.update({ _id: id }, { $set: { size: 'large' }}, callback); - :markdown - If we do need the document returned in our application there is another, often [better](./api.html#model_Model-findByIdAndUpdate), option: - :js - Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) { - if (err) return handleError(err); - res.send(tank); - }); - :markdown - The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model-findByIdAndRemove) [several](./api.html#model_Model-findOneAndUpdate) [variations](./api.html#model_Model-findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. - h3 Validating - :markdown - Documents are validated before they are saved. Read the [api](./api.html#document_Document-validate) docs or the [validation](./validation.html) chapter for detail. - - h3#next Next Up - :markdown - Now that we've covered `Documents`, let's take a look at [Sub-documents](/docs/subdocs.html). diff --git a/docs/3.1.x/docs/faq.html b/docs/3.1.x/docs/faq.html deleted file mode 100644 index 5d97705475c..00000000000 --- a/docs/3.1.x/docs/faq.html +++ /dev/null @@ -1,31 +0,0 @@ -Mongoose FAQ v3.1.2Fork me on GitHub

FAQ

Q. Why don't my changes to arrays get saved when I update an element directly?

doc.array[3] = 'changed';
-doc.save();

A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

doc.markModified('array');
-doc.save();

Q. Why doesn't mongoose allow me to directly assign schemas to paths?

var userSchema = new Schema({ name: String });
-new Schema({ user: userSchema })

A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

doc.user.save();  // ?
-doc.user.remove();// ?
-doc.save()

We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


Q. How can I enable debugging?

- -

A. Set the debug option to true:

mongoose.set('debug', true)

Q. My save() callback never executes. What am I doing wrong?

- -

A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

// if connecting on the default mongoose connection
-mongoose.connect(..);
-mongoose.connection.on('error', handleError);
-
-// if connecting on a separate connection
-var conn = mongoose.createConnection(..);
-conn.on('error', handleError);
-

Something to add?

- -

If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


diff --git a/docs/3.1.x/docs/faq.jade b/docs/3.1.x/docs/faq.jade deleted file mode 100644 index 07abc7ea928..00000000000 --- a/docs/3.1.x/docs/faq.jade +++ /dev/null @@ -1,63 +0,0 @@ -extends layout - -block append style - style. - hr { - display: block; - margin: 30px 0; - } - -block content - h2 FAQ - :markdown - **Q**. Why don't my changes to arrays get saved when I update an element directly? - :js - doc.array[3] = 'changed'; - doc.save(); - :markdown - **A**. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving. - :js - doc.markModified('array'); - doc.save(); - hr - :markdown - **Q**. Why doesn't mongoose allow me to directly assign schemas to paths? - :js - var userSchema = new Schema({ name: String }); - new Schema({ user: userSchema }) - :markdown - **A**. Schemas have a one-to-one mapping with documents. Documents have `save` and `remove` methods along with their own `pre` and `post` hooks which would lead to code like the following: - :js - doc.user.save(); // ? - doc.user.remove();// ? - doc.save() - :markdown - We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling `save` on a sub-document is a no-op and exists only to support `pre` save hooks). In the future this is likely to be revisited. - hr - :markdown - **Q**. How can I enable debugging? - - **A**. Set the `debug` option to `true`: - :js - mongoose.set('debug', true) - hr - :markdown - **Q**. My `save()` callback never executes. What am I doing wrong? - - **A**. All `collection` actions (insert, remove, queries, etc) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. - :js - // if connecting on the default mongoose connection - mongoose.connect(..); - mongoose.connection.on('error', handleError); - - // if connecting on a separate connection - var conn = mongoose.createConnection(..); - conn.on('error', handleError); - - hr - :markdown - **Something to add?** - - If you'd like to contribute to this page, please [visit it](https://github.com/learnboost/mongoose/tree/master/docs/faq.jade) on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request. - br - diff --git a/docs/3.1.x/docs/guide.html b/docs/3.1.x/docs/guide.html deleted file mode 100644 index a0e25e89e90..00000000000 --- a/docs/3.1.x/docs/guide.html +++ /dev/null @@ -1,170 +0,0 @@ -Mongoose Schemas v3.1.2Fork me on GitHub

Schemas

If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

Defining your schema

Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

var blogSchema = new Schema({
-  title:  String,
-  author: String,
-  body:   String,
-  comments: [{ body: String, date: Date }],
-  date: { type: Date, default: Date.now },
-  hidden: Boolean,
-  meta: {
-    votes: Number,
-    favs:  Number
-  }
-})

If you want to add additional keys later, use the Schema#add method.

-Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. -Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

The permitted SchemaTypes are

  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • ObjectId
  • Array
Read more about them here.

Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

Pluggable

Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

Instance methods

Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

Defining an instance method is easy.

var animalSchema = new Schema({ name: String, type: String });
-
-animalSchema.methods.findSimilarTypes = function (cb) {
-  return this.model('Animal').find({ type: this.type }, cb);
-}

Now all of our animal instances have a findSimilarTypes method available to it.

var Animal = mongoose.model('Animal', animalSchema);
-var dog = new Animal({ type: 'dog' })
-
-dog.findSimilarTypes(function (err, dogs) {
-  console.log(dogs) // woof
-})

Statics

-Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

animalSchema.statics.findByName = function (name, cb) {
-  this.find({ name: new RegExp(name, 'i'), cb);
-}
-
-var Animal = mongoose.model('Animal', animalSchema);
-Animal.findByName('fido', function (err, animals) {
-  console.log(animals);
-})

Indexes

Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

animalSchema.index({ name: 1, type: -1 });

When your application starts up, Mongoose automatically calls ensureIndex for each defined index. This behavior can be disabled by setting the autoIndex option of your schema to false.

animalSchema.set('autoIndex', false)
-// or
-new Schema({..}, { autoIndex: false })

See also the Model#ensureIndexes method.

Virtuals

Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

var personSchema = new Schema({
-  name: {
-    first: String,
-    last: String
-  }
-});
-
-var Person = mongoose.model('Person', personSchema);
-
-var bad = new Person({
-    name: { first: 'Walter', last: 'White' }
-});

Suppose we want to log the full name of bad. We could do this manually like so:

console.log(bad.name.first + ' ' + bad.name.last); // Walter White

Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

personSchema.virtual('name.full').get(function () {
-  return this.name.first + ' ' + this.name.last;
-})

Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

console.log('%s is insane', bad.name.full) // Walter White is insane

It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

bad.name.full = 'Breaking Bad';

Mongoose let's you do this as well through its virtual attribute setters:

personSchema.virtual('name.full').set(function (name) {
-  var split = name.split(' ');
-  this.name.first = split[0];
-  this.name.last = split[1];
-})
-
-...
-
-mad.name.full = 'Breaking Bad';
-console.log(mad.name.first) // Breaking

If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

Options

Schemas have a few configurable options which can be passed to the constructor or set directly:

new Schema({..}, options);
-
-// or
-
-var schema = new Schema({..});
-schema.set(option, value);
-

Valid options:

- -

option: autoIndex

At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

var schema = new Schema({..}, { autoIndex: false })
-var Clock = db.model('Clock', schema);
-Clock.ensureIndexes(callback);
-

option: capped

Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

new Schema({..}, { capped: 1024 })

The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true })
-

option: id

Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

// default behavior
-var schema = new Schema({ name: String });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p.id); // '50341373e894ad16347efe01'
-
-// disabled id
-var schema = new Schema({ name: String }, { id: false });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p.id); // undefined
-

option: _id

Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

- -

Pass this option during schema construction to prevent documents from getting an auto _id created.

// default behavior
-var schema = new Schema({ name: String });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
-
-// disabled _id
-var schema = new Schema({ name: String }, { _id: false });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p); // { name: 'mongodb.org' }
-

option: read

Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

var schema = new Schema({..}, { read: 'primary' })            // also aliased as 'p'
-var schema = new Schema({..}, { read: 'primaryPreferred' })   // aliased as 'pp'
-var schema = new Schema({..}, { read: 'secondary' })          // aliased as 's'
-var schema = new Schema({..}, { read: 'secondaryPreferred' }) // aliased as 'sp'
-var schema = new Schema({..}, { read: 'nearest' })            // aliased as 'n'
-

The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'pp'.

- -

The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

- -

NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

// pings the replset members periodically to track network latency
-// now `nearest` works as intended
-var options = { replset: { strategy: 'ping' }};
-mongoose.connect(uri, options);
-
-var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
-mongoose.model('JellyBean', schema);
-

option: safe

This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

var safe = true;
-new Schema({ .. }, { safe: safe })
-

By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. -By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

- -

There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

var safe = { w: "majority", wtimeout: 10000 };
-new Schema({ .. }, { safe: safe })
-

option: shardKey

The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
-

Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

option: strict

The strict option, (enabled by default), ensures that values added to our model instance that were not specified in our schema do not get saved to the db. -NOTE: do not set to false unless you have good reason.

var thingSchema = new Schema({..})
-var Thing = db.model('Thing', schemaSchema);
-var thing = new Thing({ iAmNotInTheSchema: true });
-thing.save() // iAmNotInTheSchema is not saved to the db
-
-// set to false..
-var thingSchema = new Schema({..}, { strict: false });
-var thing = new Thing({ iAmNotInTheSchema: true });
-thing.save() // iAmNotInTheSchema is now saved to the db!!
-

This value can be overridden at the model instance level by passing a second boolean argument:

var Thing = db.model('Thing');
-var thing = new Thing(doc, true);  // enables strict mode
-var thing = new Thing(doc, false); // disables strict mode
-

The strict option may also be set to "throw" which will cause errors to be produced instead of ignoring the bad data.

NOTE: in mongoose v2 the default was false.

option: toJSON

Exactly the same as the toObject option but only applies when the documents toJSON method is called.

var schema = new Schema({ name: String });
-schema.path('name').get(function (v) {
-  return v + ' is my name';
-});
-schema.set('toJSON', { getters: true });
-var M = mongoose.model('Person', schema);
-var m = new M({ name: 'Max Headroom' });
-console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
-console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
-// since we know toJSON is called whenever a js object is stringified:
-console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
-

option: toObject

Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

var schema = new Schema({ name: String });
-schema.path('name').get(function (v) {
-  return v + ' is my name';
-});
-schema.set('toObject', { getters: true });
-var M = mongoose.model('Person', schema);
-var m = new M({ name: 'Max Headroom' });
-console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
-

option: versionKey

The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

var schema = new Schema({ name: 'string' });
-var Thing = db.model('Thing', schema);
-var thing = new Thing({ name: 'mongoose v3' });
-thing.save(); // { __v: 0, name: 'mongoose v3' }
-
-// customized versionKey
-new Schema({..}, { versionKey: '_somethingElse' })
-var Thing = db.model('Thing', schema);
-var thing = new Thing({ name: 'mongoose v3' });
-thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
-

Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

new Schema({..}, { versionKey: false })
-var Thing = db.model('Thing', schema);
-var thing = new Thing({ name: 'no versioning please' });
-thing.save(); // { name: 'no versioning please' }
-
-

Next Up

Now that we've covered Schemas, let's take a look at SchemaTypes.

diff --git a/docs/3.1.x/docs/guide.jade b/docs/3.1.x/docs/guide.jade deleted file mode 100644 index bc9c539aad8..00000000000 --- a/docs/3.1.x/docs/guide.jade +++ /dev/null @@ -1,428 +0,0 @@ -extends layout - -block content - h2 Schemas - :markdown - If you haven't yet done so, please take a minute to read the [quickstart](./index.html) to get an idea of how Mongoose works. - :markdown - If you are migrating from 2.x to 3.x please take a moment to read the [migration guide](./migration.html). - :markdown - This page covers `Schema` [definition](#definition), [plugins](#plugins), instance [methods](#methods), [statics](#statics), [indexes](#indexes), [virtuals](#virtuals) and [options](#options). Let's start with `Schema` definition. - h3#definition Defining your schema - p - | Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection. - :js - var blogSchema = new Schema({ - title: String, - author: String, - body: String, - comments: [{ body: String, date: Date }], - date: { type: Date, default: Date.now }, - hidden: Boolean, - meta: { - votes: Number, - favs: Number - } - }) - p - em - | If you want to add additional keys later, use the - a(href="./api.html#schema_Schema-add") Schema#add - | method. - p - | Each key in our - code blogSchema - | defines a property in our documents which will be cast to its associated - a(href="./api.html#schematype_SchemaType") SchemaType - |. For example, we've defined a - code title - | which will be cast to the - a(href="./api.html#schema-string-js") String - | SchemaType and - code date - | which will be cast to a - code Date - | SchemaType. - | Keys may also be assigned nested objects containing further key/type definitions - em (e.g. the `meta` property above). - p - | The permitted SchemaTypes are - ul - li String - li Number - li Date - li Buffer - li Boolean - li Mixed - li ObjectId - li Array - | Read more about them - a(href="./schematypes.html") here - | . - p - | Schemas not only define the structure of your document and casting of properties, they also define document - a(href="#methods") instance methods - |, static - a(href="#statics") Model methods - |, - a(href="#indexes") compound indexes - | and document lifecycle hooks called - a(href="./middleware.html") middleware - |. - h3#plugins Pluggable - p - | Schemas are - a(href="./plugins.html") pluggable - | which allows us to package up reusable features into - a(href="http://plugins.mongoosejs.com") plugins - | that can be shared with the community or just between your projects. - h3#methods Instance methods - p - a(href="./models.html") Models - | are just fancy - code constructor - | functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are - a(href="./documents.html") documents - |. - p - | Defining an instance method is easy. - :js - var animalSchema = new Schema({ name: String, type: String }); - - animalSchema.methods.findSimilarTypes = function (cb) { - return this.model('Animal').find({ type: this.type }, cb); - } - p - | Now all of our - code animal - | instances have a - code findSimilarTypes - | method available to it. - :js - var Animal = mongoose.model('Animal', animalSchema); - var dog = new Animal({ type: 'dog' }) - - dog.findSimilarTypes(function (err, dogs) { - console.log(dogs) // woof - }) - h3#statics Statics - p - | Adding static constructor methods to Models is simple as well. Continuing with our - code animalSchema - |: - :js - animalSchema.statics.findByName = function (name, cb) { - this.find({ name: new RegExp(name, 'i'), cb); - } - - var Animal = mongoose.model('Animal', animalSchema); - Animal.findByName('fido', function (err, animals) { - console.log(animals); - }) - h3#indexes Indexes - p - a(href="http://www.mongodb.org/display/DOCS/Indexes") Indexes - | can be defined - a(href="./api.html#schematype_SchemaType-index") at - | - a(href="./api.html#schematype_SchemaType-unique") the - | - a(href="./api.html#schematype_SchemaType-sparse") path - | - a(href="./api.html#schematype_SchemaType-expires") level - | or the - code schema - | level. Defining indexes at the schema level is necessary when defining - a(href="http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys", target="_blank") compound indexes - |. - :js - animalSchema.index({ name: 1, type: -1 }); - p - | When your application starts up, Mongoose automatically calls - code ensureIndex - | for each defined index. This behavior can be disabled by setting the - code autoIndex - | option of your schema to false. - :js - animalSchema.set('autoIndex', false) - // or - new Schema({..}, { autoIndex: false }) - p - | See also the - a(href="./api.html#model_Model-ensureIndexes") - code Model#ensureIndexes - | method. - - h3#virtuals Virtuals - :markdown - [Virtual](./api.html#schema_Schema-virtual) attributes are attributes that are convenient to have around but that do not get persisted to MongoDB. - :js - var personSchema = new Schema({ - name: { - first: String, - last: String - } - }); - - var Person = mongoose.model('Person', personSchema); - - var bad = new Person({ - name: { first: 'Walter', last: 'White' } - }); - :markdown - Suppose we want to log the full name of `bad`. We could do this manually like so: - :js - console.log(bad.name.first + ' ' + bad.name.last); // Walter White - :markdown - Or we could add a `virtual` attribute [getter](./api.html#virtualtype_VirtualType-get) to our `personSchema` so we don't need to write out this string concatenation mess each time: - :js - personSchema.virtual('name.full').get(function () { - return this.name.first + ' ' + this.name.last; - }) - :markdown - Now, when we access our virtual full name property, our getter function will be invoked and the value returned: - :js - console.log('%s is insane', bad.name.full) // Walter White is insane - :markdown - It would also be nice to be able to set `this.name.first` and `this.name.last` by setting `this.name.full`. For example, if we wanted to change `bad`'s `name.first` and `name.last` to 'Breaking' and 'Bad' respectively, it'd be nice to just: - :js - bad.name.full = 'Breaking Bad'; - :markdown - Mongoose lets you do this as well through its virtual attribute [setters](./api.html#virtualtype_VirtualType-set): - :js - personSchema.virtual('name.full').set(function (name) { - var split = name.split(' '); - this.name.first = split[0]; - this.name.last = split[1]; - }) - - ... - - mad.name.full = 'Breaking Bad'; - console.log(mad.name.first) // Breaking - :markdown - If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you. - - h3#options Options - :markdown - `Schema`s have a few configurable options which can be passed to the constructor or `set` directly: - :js - new Schema({..}, options); - - // or - - var schema = new Schema({..}); - schema.set(option, value); - - :markdown - Valid options: - - - [autoIndex](#autoIndex) - - [capped](#capped) - - [id](#id) - - [_id](#_id) - - [read](#read) - - [safe](#safe) - - [shardKey](#shardKey) - - [strict](#strict) - - [toJSON](#toJSON) - - [toObject](#toObject) - - [versionKey](#versionKey) - - h4#autoIndex option: autoIndex - :markdown - At application startup, Mongoose sends an `ensureIndex` command for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model-ensureIndexes) method on your model. - :js - var schema = new Schema({..}, { autoIndex: false }) - var Clock = db.model('Clock', schema); - Clock.ensureIndexes(callback); - - h4#capped option: capped - :markdown - Mongoose supports MongoDBs [capped](http://www.mongodb.org/display/DOCS/Capped+Collections) collections. To specify the underlying MongoDB collection be `capped`, set the `capped` option to the maximum size of the collection in [bytes](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-size.). - :js - new Schema({..}, { capped: 1024 }) - :markdown - The `capped` option may also be set to an object if you want to pass additional options like [max](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-max) or [autoIndexId](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-autoIndexId). In this case you must explicitly pass the `size` option which is required. - :js - new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true }) - - h4#id option: id - :markdown - Mongoose assigns each of your schemas an `id` virtual getter by default which returns the documents `_id` field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an `id` getter added to your schema, you may disable it passing this option at schema construction time. - :js - // default behavior - var schema = new Schema({ name: String }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p.id); // '50341373e894ad16347efe01' - - // disabled id - var schema = new Schema({ name: String }, { id: false }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p.id); // undefined - - h4#_id option: _id - :markdown - Mongoose assigns each of your schemas an `_id` field by default if one is not passed into the [Schema](/docs/api.html#schema-js) constructor. The type assiged is an [ObjectId](/docs/api.html#schema_Schema-Types) to coincide with MongoDBs default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option. - - Pass this option during schema construction to prevent documents from getting an auto `_id` created. - :js - // default behavior - var schema = new Schema({ name: String }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' } - - // disabled _id - var schema = new Schema({ name: String }, { _id: false }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p); // { name: 'mongodb.org' } - - h4#read option: read - :markdown - Allows setting [query#read](/docs/api.html#query_Query-read) options at the schema level, providing us a way to apply default [ReadPreferences](http://docs.mongodb.org/manual/applications/replication/#replica-set-read-preference) to all queries derived from a model. - - :js - var schema = new Schema({..}, { read: 'primary' }) // also aliased as 'p' - var schema = new Schema({..}, { read: 'primaryPreferred' }) // aliased as 'pp' - var schema = new Schema({..}, { read: 'secondary' }) // aliased as 's' - var schema = new Schema({..}, { read: 'secondaryPreferred' }) // aliased as 'sp' - var schema = new Schema({..}, { read: 'nearest' }) // aliased as 'n' - - :markdown - The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'pp'. - - The read option also allows us to specify _tag sets_. These tell the [driver](https://github.com/mongodb/node-mongodb-native/) from which members of the replica-set it should attempt to read. Read more about tag sets [here](http://docs.mongodb.org/manual/applications/replication/#tag-sets) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences). - - _NOTE: if you specify the read pref 'nearest', you must also pass the [strategy](http://mongodb.github.com/node-mongodb-native/api-generated/replset.html?highlight=strategy) option when connecting or your reads will not behave predictably:_ - - :js - // pings the replset members periodically to track network latency - // now `nearest` works as intended - var options = { replset: { strategy: 'ping' }}; - mongoose.connect(uri, options); - - var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] }); - mongoose.model('JellyBean', schema); - - h4#safe option: safe - :markdown - This option is passed to MongoDB with all operations, and specifies if errors should be returned to our callbacks as well as tune write behavior. - - :js - var safe = true; - new Schema({ .. }, { safe: safe }) - - :markdown - By default this is set to `true` for all schemas which guarentees that any occurring error gets passed back to our callback. - By setting `safe` to something else like `{ j: 1, w: 2, wtimeout: 10000 }` we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback. - - There are other write concerns like `{ w: "majority" }` too. See the MongoDB [docs](http://www.mongodb.org/display/DOCS/getLastError+Command) for more details. - - :js - var safe = { w: "majority", wtimeout: 10000 }; - new Schema({ .. }, { safe: safe }) - - h4#shardKey option: shardKey - :markdown - The `shardKey` option is used when we have a [sharded MongoDB architecture](http://www.mongodb.org/display/DOCS/Sharding+Introduction). Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set. - - :js - new Schema({ .. }, { shardkey: { tag: 1, name: 1 }}) - - :markdown - _Note that Mongoose does not send the `shardcollection` command for you. You must configure your shards yourself._ - - h4#strict option: strict - :markdown - The strict option, (enabled by default), ensures that values added to our model instance that were not specified in our schema do not get saved to the db. - _NOTE: do not set to false unless you have good reason._ - - :js - var thingSchema = new Schema({..}) - var Thing = db.model('Thing', schemaSchema); - var thing = new Thing({ iAmNotInTheSchema: true }); - thing.save() // iAmNotInTheSchema is not saved to the db - - // set to false.. - var thingSchema = new Schema({..}, { strict: false }); - var thing = new Thing({ iAmNotInTheSchema: true }); - thing.save() // iAmNotInTheSchema is now saved to the db!! - - :markdown - This value can be overridden at the model instance level by passing a second boolean argument: - - :js - var Thing = db.model('Thing'); - var thing = new Thing(doc, true); // enables strict mode - var thing = new Thing(doc, false); // disables strict mode - - :markdown - The `strict` option may also be set to `"throw"` which will cause errors to be produced instead of ignoring the bad data. - - :markdown - _NOTE: in mongoose v2 the default was false._ - - h4#toJSON option: toJSON - :markdown - Exactly the same as the [toObject](#toObject) option but only applies when the documents `toJSON` method is called. - :js - var schema = new Schema({ name: String }); - schema.path('name').get(function (v) { - return v + ' is my name'; - }); - schema.set('toJSON', { getters: true }); - var M = mongoose.model('Person', schema); - var m = new M({ name: 'Max Headroom' }); - console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' } - console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } - // since we know toJSON is called whenever a js object is stringified: - console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" } - - h4#toObject option: toObject - :markdown - Documents have a [toObject](/docs/api.html#document_Document-toObject) method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default. - :js - var schema = new Schema({ name: String }); - schema.path('name').get(function (v) { - return v + ' is my name'; - }); - schema.set('toObject', { getters: true }); - var M = mongoose.model('Person', schema); - var m = new M({ name: 'Max Headroom' }); - console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } - - h4#versionKey option: versionKey - :markdown - The `versionKey` is a property set on each document when first created by Mongoose. This keys value contains the internal [revision](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning) of the document. The name of this document property is configurable. The default is `__v`. If this conflicts with your application you can configure as such: - :js - var schema = new Schema({ name: 'string' }); - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'mongoose v3' }); - thing.save(); // { __v: 0, name: 'mongoose v3' } - - // customized versionKey - new Schema({..}, { versionKey: '_somethingElse' }) - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'mongoose v3' }); - thing.save(); // { _somethingElse: 0, name: 'mongoose v3' } - - :markdown - Document versioning can also be disabled by setting the `versionKey` to false. _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning)._ - :js - new Schema({..}, { versionKey: false }) - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'no versioning please' }); - thing.save(); // { name: 'no versioning please' } - - - h3#next Next Up - :markdown - Now that we've covered `Schemas`, let's take a look at [SchemaTypes](/docs/schematypes.html). - -script. -document.body.className = 'load'; -include includes/googleanalytics diff --git a/docs/3.1.x/docs/helpers/filters.js b/docs/3.1.x/docs/helpers/filters.js deleted file mode 100644 index 33546a7e805..00000000000 --- a/docs/3.1.x/docs/helpers/filters.js +++ /dev/null @@ -1,20 +0,0 @@ - -var hl = require('highlight.js') - -module.exports = exports = function (jade) { - // add highlighting filter to jade - - jade.filters.js = function (str) { - str = str.replace(/\\n/g, '\n'); - var ret = hl.highlight('javascript', str).value; - var code = '
' + ret.replace(/\n/g, '\\n') + '
'; - return code; - } - - jade.filters.bash = function (str) { - var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; - var code = '
' + ret + '
'; - return code - } - -} diff --git a/docs/3.1.x/docs/helpers/highlight.js b/docs/3.1.x/docs/helpers/highlight.js deleted file mode 100644 index 8aca9b9e222..00000000000 --- a/docs/3.1.x/docs/helpers/highlight.js +++ /dev/null @@ -1,11 +0,0 @@ - -var h = require('highlight.js') - -function hl (str) { - str = str.replace(/\\n/g, '\n'); - var ret = h.highlight('javascript', str).value; - var code = '
' + ret+ '
'; - return code; -} - -module.exports = hl; diff --git a/docs/3.1.x/docs/helpers/href.js b/docs/3.1.x/docs/helpers/href.js deleted file mode 100644 index e7299b1cf0d..00000000000 --- a/docs/3.1.x/docs/helpers/href.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str, char) { - if ('string' != typeof str) return str; - return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); -} diff --git a/docs/3.1.x/docs/helpers/klass.js b/docs/3.1.x/docs/helpers/klass.js deleted file mode 100644 index 0c4a865b43b..00000000000 --- a/docs/3.1.x/docs/helpers/klass.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str) { - var parts = str.replace(/\.js$/, '').split('/'); - return parts.join('_'); -} diff --git a/docs/3.1.x/docs/helpers/linktype.js b/docs/3.1.x/docs/helpers/linktype.js deleted file mode 100644 index 997e740f671..00000000000 --- a/docs/3.1.x/docs/helpers/linktype.js +++ /dev/null @@ -1,50 +0,0 @@ - -var types = {}; -types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; -types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' -types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' -types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' -types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' -types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' -types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' -types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' -types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' -types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' - -// mongoose -types.ObjectId = '#types_objectid_ObjectId'; -types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; -types.MongooseArray = '#types_array_MongooseArray'; -types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; -types.Query = '#query-js'; -types.QueryStream = '#querystream_QueryStream'; -types.Document = '#document_Document'; -types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; -types.Document = '#document_Document'; -types.Model = '#model_Model'; -types.Connection = '#connection_Connection'; -types.Collection = '#collection_Collection'; -types.Schema = '#schema_Schema'; -types.Promise = '#promise_Promise'; -types.Mongoose = '#index_Mongoose'; -types.MongooseError = '#error_MongooseError'; -types.Type = '#schematype_SchemaType'; // ? -types.SchemaType = '#schematype_SchemaType'; -types.SchemaArray = '#schema_array_SchemaArray'; -types.Mixed = '#schema_mixed_Mixed'; -types.VirtualType = '#virtualtype_VirtualType'; -types.MongooseBuffer = '#types_buffer_MongooseBuffer'; -types.Buffer = 'http://nodejs.org/api/buffer.html'; - -module.exports= function (type) { - if (types[type]) { - return '' + type + ''; - } - return '' + type + ''; -} - -module.exports.types = types; -module.exports.type = function (str) { - if (types[str]) return types[str]; - return str; -} diff --git a/docs/3.1.x/docs/images/apps/grab b/docs/3.1.x/docs/images/apps/grab deleted file mode 100755 index ca314e9e858..00000000000 --- a/docs/3.1.x/docs/images/apps/grab +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -#make sure firefox launches in the bottom right corner of the window - -# read URLs from a data file in a loop -#regex='([^[:space:]]+)[[:space:]]*(.*)' -regex='([^[:space:]]+)[|]([^|]+)[|](.*)' - -func() { - [[ $1 =~ $regex ]] - url=${BASH_REMATCH[1]} - # remove middle space, lowercase - name=`echo ${BASH_REMATCH[2]} | tr -d '[[:space:]]' | tr '[A-Z]' '[a-z]'` - desc=${BASH_REMATCH[3]} - - # send URL to the firefox session - # firefox --width 1030 --height 768 $url & - /Applications/Firefox.app/Contents/MacOS/firefox --width 1030 --height 768 $url & - echo started firefox with $url - echo preparing screencapture ... - - # take a picture after waiting a bit for the load to finish - sleep 6 - # gm import -window root -crop 1004x768+414+228 -resize 500x350 $name.png - screencapture -wo $name.png - gm convert $name.png -crop 1004x768+0+80 -resize 200x140 $name.png - echo grabbed screenshot $name.png -} - -if [ $1 ] -then - func "$1 $2" -else - while read line - do - func $line - done < urls -fi - diff --git a/docs/3.1.x/docs/images/apps/urls b/docs/3.1.x/docs/images/apps/urls deleted file mode 100644 index ca924705938..00000000000 --- a/docs/3.1.x/docs/images/apps/urls +++ /dev/null @@ -1,21 +0,0 @@ -https://www.learnboost.com|LearnBoost|is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students. -http://storify.com/|Storify|lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative. -https://clickdummy.com|ClickDummy|is a rapid mockup prototyping application for designers and dummies. -http://scottyapp.com|Scotty App|allows you to create data driven backends for your apps in minutes instead of weeks. -http://geekli.st|Geeklist|is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found. -https://bozuko.com|Bozuko|is an exciting customer rewards program. -http://calllistapp.com|Call List|helps you maintain a todo list for people you need to call. -http://www.gtggolf.com|Grow The Game Golf|lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more. -http://nextdays.com/|nextdays|lets you share plans with friends and discover what is happening around you. -http://linkr.cc|Linkr|is a service for saving links for reading later. -http://www.attictv.com/|AtticTV|is Music Television (MTV) for the web. -https://localresponse.com|LocalResponse|helps marketers respond to real-time consumer intent. -http://selectvids.com|Select Vids|is a collection of amazing, funny, and creative videos for you to discover. -https://cldfy.com/|cldfy|delivers mail to your app. -http://www.sharelatex.com|ShareLatex|is a real-time LaTeX collaboration tool. -http://apps.newleafdigital.com/lists|Lists|is a service for saving links for reading later. -http://cyborgvisionapp.com/|Cyborg Vision|uses real-time facial recognition to identify your friends and show their information. -https://wavo.me/|Wavo|lets you express yourself through the songs you love. -http://seelio.com/|seelio|is a stage for college students to distinguish themselves and connect with companies. -http://todaylaunch.com/|TodayLaunch|is a free dashboard for your social media accounts. -http://st.achify.com/|Stachify| diff --git a/docs/3.1.x/docs/images/square_bg.png b/docs/3.1.x/docs/images/square_bg.png deleted file mode 100644 index f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.1.2Fork me on GitHub

Getting Started

First be sure you have MongoDB and Nodejs installed.

Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. -The first thing we need to do is include mongoose in our project and open a connection.

var mongoose = require('mongoose')
-  , db = mongoose.createConnection('localhost', 'test');

We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

db.on('error', console.error.bind(console, 'connection error:'));
-db.once('open', function () {
-  // yay!
-});

Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

var kittySchema = new mongoose.Schema({
-    name: String
-})

So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a model.

var Kitten = db.model('Kitten', kittySchema)

A model is a class with which we construct documents. -In this case, each document will be a kitten with properties and behaviors as declared in our schema. -Let's create a kitten document representing the little guy we just met on the sidewalk outside:

var silence = new Kitten({ name: 'Silence' })
-console.log(silence.name) // 'Silence'

Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

kittySchema.methods.speak = function () {
-  var greeting = this.name
-    ? 'Meow name is ' + this.name
-    : 'I don't have a name'
-  console.log(greeting);
-}
-
-var Kitten = db.model('Kitten', kittySchema)

Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

var fluffy = new Kitten({ name: 'fluffy' });
-fluffy.speak() // "Meow name is fluffy"

We have talking kittens! But we still haven't saved anything to MongoDB. -Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

fluffy.save(function (err) {
-  if (err) // TODO handle the error
-  console.log('meow')
-});

Say time goes by and we want to display all the kittens we've seen. -We can access all of the kitten documents through our Kitten model.

Kitten.find(function (err, kittens) {
-  if (err) // TODO handle err
-  console.log(kittens)
-})

We just logged all of the kittens in our db to the console. -If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax.

Kitten.find({ name: /fluff/i }, callback)

This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback.

Congratulations

That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or api docs for more.

diff --git a/docs/3.1.x/docs/index.jade b/docs/3.1.x/docs/index.jade deleted file mode 100644 index 3d0c597da6b..00000000000 --- a/docs/3.1.x/docs/index.jade +++ /dev/null @@ -1,119 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose Quick Start v#{package.version} - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - link(href='css/guide.css', rel='stylesheet', type='text/css') - style. - body.api - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - #content - .module - h2 Getting Started - p - em - | First be sure you have - a(href="http://www.mongodb.org/downloads") MongoDB - | and - a(href="http://nodejs.org/") Nodejs - | installed. - p - | Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. - | The first thing we need to do is include mongoose in our project and open a connection. - :js - var mongoose = require('mongoose') - , db = mongoose.createConnection('localhost', 'test'); - p We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs: - :js - db.on('error', console.error.bind(console, 'connection error:')); - db.once('open', function () { - // yay! - }); - p Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback. - p - | With Mongoose, everything is derived from a - a(href="./api.html#schema_Schema") Schema - | . Let's get a reference to it and define our kittens. - :js - var kittySchema = new mongoose.Schema({ - name: String - }) - p - | So far so good. We've got a schema with one property, - code name - | , which will be a - code String - | . The next step is compiling our schema into a - a(href="./api.html#model_Model") model - | . - :js - var Kitten = db.model('Kitten', kittySchema) - p - | A model is a class with which we construct documents. - | In this case, each document will be a kitten with properties and behaviors as declared in our schema. - | Let's create a kitten document representing the little guy we just met on the sidewalk outside: - :js - var silence = new Kitten({ name: 'Silence' }) - console.log(silence.name) // 'Silence' - p Kittens can meow, so let's take a look at how to add "speak" functionality to our documents: - :js - kittySchema.methods.speak = function () { - var greeting = this.name - ? 'Meow name is ' + this.name - : 'I don't have a name' - console.log(greeting); - } - - var Kitten = db.model('Kitten', kittySchema) - p - | Functions added to the - code methods - | property of a schema get compiled into the Model prototype and exposed on each document instance: - :js - var fluffy = new Kitten({ name: 'fluffy' }); - fluffy.speak() // "Meow name is fluffy" - p - | We have talking kittens! But we still haven't saved anything to MongoDB. - | Each document can be saved to the database by calling its - code save - | method. The first argument to the callback will be an error if any occured. - :js - fluffy.save(function (err) { - if (err) // TODO handle the error - console.log('meow') - }); - p - | Say time goes by and we want to display all the kittens we've seen. - | We can access all of the kitten documents through our Kitten model. - :js - Kitten.find(function (err, kittens) { - if (err) // TODO handle err - console.log(kittens) - }) - p - | We just logged all of the kittens in our db to the console. - | If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax. - :js - Kitten.find({ name: /fluff/i }, callback) - p - | This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback. - h3 Congratulations - p - | That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the - a(href="guide.html") guide - | , or - a(href="api.html") api docs - | for more. - script. - document.body.className = 'load'; - include includes/googleanalytics diff --git a/docs/3.1.x/docs/js/zepto.min.js b/docs/3.1.x/docs/js/zepto.min.js deleted file mode 100644 index 428f84a28c5..00000000000 --- a/docs/3.1.x/docs/js/zepto.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */ -(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.1.x/docs/layout.jade b/docs/3.1.x/docs/layout.jade deleted file mode 100644 index 6585074f210..00000000000 --- a/docs/3.1.x/docs/layout.jade +++ /dev/null @@ -1,25 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose #{title} v#{package.version} - block style - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - link(href='css/guide.css', rel='stylesheet', type='text/css') - body - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - #content - .module - block content - script. - document.body.className = 'load'; - include includes/googleanalytics diff --git a/docs/3.1.x/docs/middleware.html b/docs/3.1.x/docs/middleware.html deleted file mode 100644 index 9fc90aaab6f..00000000000 --- a/docs/3.1.x/docs/middleware.html +++ /dev/null @@ -1,29 +0,0 @@ -Mongoose Middleware v3.1.2Fork me on GitHub

Middleware

Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

-There are two types of middleware, serial and parallel.

Serial

Serial middleware are executed one after another, when each middleware calls next

var schema = new Schema(..);
-schema.pre('save', function (next) {
-  // do stuff
-  next();
-});

Parallel

Parallel middleware offer more fine-grained flow control.

var schema = new Schema(..);
-schema.pre('save', true, function (next, done) {
-  // calling next kicks off the next middleware in parallel
-  next();
-  doAsync(done);
-});

The hooked method, in this case save, will not be executed until done is called by each middleware.

Use Cases

Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

  • complex validation
  • removing dependent documents
    • (removing a user removes all his blogposts)
  • asynchronous defaults
  • asynchronous tasks that a certain action triggers
    • triggering custom events
    • notifications

Error handling

If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

schema.pre('save', function (next) {
-  var err = new Error('something went wrong');
-  next(err);
-});
-
-// later...
-
-myModel.save(function (err) {
-  console.log(err.message) // something went wrong
-});
-

Next Up

Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

diff --git a/docs/3.1.x/docs/middleware.jade b/docs/3.1.x/docs/middleware.jade deleted file mode 100644 index b9e9e9eca94..00000000000 --- a/docs/3.1.x/docs/middleware.jade +++ /dev/null @@ -1,74 +0,0 @@ -extends layout - -block content - h2 Middleware - p - | Middleware are functions which are passed control of flow during execution of - a(href="./api.html#document_Document-init") init - |, - a(href="./api.html#document_Document-validate") validate - |, - a(href="./api.html#model_Model-save") save - | and - a(href="./api.html#model_Model-remove") remove - | methods. - p - | There are two types of middleware, serial and parallel. - h4 Serial - p - | Serial middleware are executed one after another, when each middleware calls - code next - :js - var schema = new Schema(..); - schema.pre('save', function (next) { - // do stuff - next(); - }); - h4 Parallel - p - | Parallel middleware offer more fine-grained flow control. - :js - var schema = new Schema(..); - schema.pre('save', true, function (next, done) { - // calling next kicks off the next middleware in parallel - next(); - doAsync(done); - }); - p - | The hooked method, in this case - code save - |, will not be executed until - code done - | is called by each middleware. - h4 Use Cases - p - | Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas: - ul - li complex validation - li - | removing dependent documents - ul - li (removing a user removes all his blogposts) - li asynchronous defaults - li asynchronous tasks that a certain action triggers - ul - li triggering custom events - li notifications - h4 Error handling - :markdown - If any middleware calls `next` or `done` with an `Error` instance, the flow is interrupted, and the error is passed to the callback. - :js - schema.pre('save', function (next) { - var err = new Error('something went wrong'); - next(err); - }); - - // later... - - myModel.save(function (err) { - console.log(err.message) // something went wrong - }); - - h3#next Next Up - :markdown - Now that we've covered `middleware`, let's take a look at Mongoose's approach to faking JOINs with its query [population](/docs/populate.html) helper. diff --git a/docs/3.1.x/docs/migration.html b/docs/3.1.x/docs/migration.html deleted file mode 100644 index 7b08121b51f..00000000000 --- a/docs/3.1.x/docs/migration.html +++ /dev/null @@ -1,38 +0,0 @@ -Mongoose Migration Guide v3.1.2Fork me on GitHub

Migrating from 2.x to 3.x

Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

Query clean-up

Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

- -

Here are the removed methods are their still existing aliases:

RemovedAlternative
query.runquery.exec
query.$orquery.or
query.$norquery.nor
query.$gtquery.gt
query.$gtequery.gte
query.$ltquery.lt
query.$ltequery.lte
query.$nequery.ne
query.$inquery.in
query.$ninquery.nin
query.$allquery.all
query.$regexquery.regex
query.$sizequery.size
query.$maxDistancequery.maxDistance
query.$modquery.mod
query.$nearquery.near
query.$existsquery.exists
query.$elemMatchquery.elemMatch
query.$withinquery.within
query.$boxquery.box
query.$centerquery.center
query.$centerSpherequery.centerSphere
query.$slicequery.slice
query.notEqualToquery.ne
query.whereinquery.within
query.ascquery.sort *
query.descquery.sort *
query.fieldsquery.select *

query#asc

The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

query#desc

The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

query#sort

The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

query#fields

The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

- -

Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

Connecting to ReplicaSets

To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

Schemas

  • are now strict by default.
  • Arrays of object literal now creates document arrays instead of arrays of Mixed.
  • Indexes are now created in background by default.
  • Index errors are now emitted on their model instead of the connection. See issue #984.

Arrays

  • pop is now fixed causing a $set of the entire array.
  • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
  • shift is now fixed causing a $set of the entire array.
  • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
  • $unshift was removed, use unshift instead.
  • $addToSet was removed, use addToSet instead.
  • $pushAll was removed, use push instead.
  • $pull was removed, use pull instead.
  • $pullAll was removed, use pull instead.
  • doAtomics was changed to the hasAtomics private method

Number type

The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

- -

With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

- -
  • $inc
  • $increment
  • $decrement
- -

If you really want this behavior back, include the mongoose-number module in your project.

- -

A good alternative is to start using the new findAndModify helpers. -Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

var inventorySchema = new Schema({ productCount: Number });
-...
-Inventory.findById(id, function (err, inventory) {
-  if (err) return handleError(err);
-  inventory.productCount.$decrement(7);
-  inventory.save(function (err) {
-    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
-    if (err) return handleError(err);
-    res.send(inventory.productCount); // 3
-  });
-});

With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
-  if (err) return handleError(err);
-  res.send(inventory.productCount); // 3
-});

The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

Documents

getter casting

Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

setter order

Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This changes allows more flexible processing of values in setters. See issue #665 and pull #924.

Subdocuments

  • subdoc.parent was changed from a property to a method. See issue #928.
  • subdoc.parentArray was changed from a property to a method. See issue #928.

String match validator

The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

Versioning

Documents are now transparently versioned. Read the in depth details here.

diff --git a/docs/3.1.x/docs/migration.jade b/docs/3.1.x/docs/migration.jade deleted file mode 100644 index 3fca606562a..00000000000 --- a/docs/3.1.x/docs/migration.jade +++ /dev/null @@ -1,272 +0,0 @@ -extends layout - -block append style - style. - table td { - padding-right: 15px; - } - -block content - h2 Migrating from 2.x to 3.x - :markdown - Migrating from Mongoose 2.x to 3.x brings with it [several changes](https://github.com/LearnBoost/mongoose/blob/master/History.md) to be aware of: - - h3 Query clean-up - :markdown - Many methods of the [Query](./api.html#query-js) API were nothing but aliases and have been [removed](https://github.com/LearnBoost/mongoose/commit/1149804c) in an effort to keep Mongoose clean and focused on there being as close to [one way](http://www.python.org/dev/peps/pep-0020/) of doing things as possible. If you really love all that extra noise, you can bring most of it back with [this module](https://github.com/aheckmann/mongoose-v2-compat). - - Here are the removed methods are their still existing aliases: - table - thead - tr(style='text-align:left') - th Removed - th Alternative - tbody - tr - td - code query.run - td - code query.exec - tr - td - code query.$or - td - code query.or - tr - td - code query.$nor - td - code query.nor - tr - td - code query.$gt - td - code query.gt - tr - td - code query.$gte - td - code query.gte - tr - td - code query.$lt - td - code query.lt - tr - td - code query.$lte - td - code query.lte - tr - td - code query.$ne - td - code query.ne - tr - td - code query.$in - td - code query.in - tr - td - code query.$nin - td - code query.nin - tr - td - code query.$all - td - code query.all - tr - td - code query.$regex - td - code query.regex - tr - td - code query.$size - td - code query.size - tr - td - code query.$maxDistance - td - code query.maxDistance - tr - td - code query.$mod - td - code query.mod - tr - td - code query.$near - td - code query.near - tr - td - code query.$exists - td - code query.exists - tr - td - code query.$elemMatch - td - code query.elemMatch - tr - td - code query.$within - td - code query.within - tr - td - code query.$box - td - code query.box - tr - td - code query.$center - td - code query.center - tr - td - code query.$centerSphere - td - code query.centerSphere - tr - td - code query.$slice - td - code query.slice - tr - td - code query.notEqualTo - td - code query.ne - tr - td - code query.wherein - td - code query.within - tr - td - code query.asc - td - code - | query.sort - a(href="#asc") * - tr - td - code query.desc - td - code - | query.sort - a(href="#desc") * - tr - td - code query.fields - td - code - | query.select - a(href="#fields") * - - h4#asc query#asc - :markdown - The `asc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#desc query#desc - :markdown - The `desc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#sort query#sort - :markdown - The [sort](./api.html#query_Query-sort) method of [Queries](./api.html#query-js) now accepts slightly different arguments. Read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#fields query#fields - :markdown - The `fields` method of [Query](./api.html#query-js) has been removed, it being mostly an alias for the [select](./api.html#query_Query-select) method anyway. The `select` method has slightly different arguments so read the [docs](./api.html#query_Query-select) to make sure your application is all set. - - Because of the change to the `fields` method, the field selection argument for [query.populate](./api.html#query_Query-populate) and model methods like [findById](./api.html#model_Model-findById), [find](./api.html#model_Model-find), etc, is slightly different as well (no longer accepts arrays for example), so read the [docs](./api.html#query_Query-select) to make sure your application is all set. - - h3 Connecting to ReplicaSets - :markdown - To connect to a [ReplicaSet](http://www.mongodb.org/display/DOCS/Replica+Sets) you no longer use the separate `connectSet` or `createSetConnection` methods. Both [mongoose.connect](./api.html#index_Mongoose-connect) and [mongoose.createConnection](./api.html#index_Mongoose-createConnection) are now smart enough to just do the right thing with your connection string. If you really want to bring `connectSet` and `createSetConnection` back use [this module](https://github.com/aheckmann/mongoose-v2-compat). - - h3 Schemas - :markdown - - are now [strict](./guide.html#strict) by default. - - Arrays of [object literal](./subdocs.html#altsyntax) now creates document arrays instead of arrays of [Mixed](./schematypes.html#mixed). - - Indexes are now created in [background](./guide.html#autoIndex) by default. - - Index errors are now emitted on their model instead of the connection. See issue [#984](https://github.com/LearnBoost/mongoose/issues/984). - - h3#arrays Arrays - :markdown - - [pop](./api.html#types_array_MongooseArray-pop) is now fixed causing a $set of the entire array. - - [$pop](./api.html#types_array_MongooseArray-%24pop) is now fixed and behaves just as MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the last element of the array. - - [shift](./api.html#types_array_MongooseArray-shift) is now fixed causing a $set of the entire array. - - [$shift](./api.html#types_array_MongooseArray-%24shift) is now fixed and behaves just as a [MongoDB $pop -1](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the first element of array. - - `$unshift` was removed, use [unshift](./api.html#types_array_MongooseArray-unshift) instead. - - `$addToSet` was removed, use [addToSet](./api.html#types_array_MongooseArray-addToSet) instead. - - `$pushAll` was removed, use [push](./api.html#types_array_MongooseArray-push) instead. - - `$pull` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. - - `$pullAll` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. - - `doAtomics` was changed to the [hasAtomics](./api.html#types_array_MongooseArray-hasAtomics) private method - - h3#mongoosenumber Number type - :markdown - The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused [too many problems](https://groups.google.com/d/msg/mongoose-orm/syKlN2xL1EE/FfRFhEFj4KcJ) when doing comparisons and had other bad side-effects. - - With it out of the picture, the following helper methods of MongooseNumbers are now also gone: - - - $inc - - $increment - - $decrement - - If you really want this behavior back, include the [mongoose-number](https://github.com/aheckmann/mongoose-number) module in your project. - - A good alternative is to start using the new [findAndModify](./api.html#model_Model-findOneAndUpdate) [helpers](./api.html#model_Model-findOneAndRemove). - Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber: - :js - var inventorySchema = new Schema({ productCount: Number }); - ... - Inventory.findById(id, function (err, inventory) { - if (err) return handleError(err); - inventory.productCount.$decrement(7); - inventory.save(function (err) { - // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback); - if (err) return handleError(err); - res.send(inventory.productCount); // 3 - }); - }); - :markdown - With MongooseNumber out of the picture, we'll instead use the [Account.findByIdAndUpdate](./api.html#model_Model-findByIdAndUpdate) helper: - :js - Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) { - if (err) return handleError(err); - res.send(inventory.productCount); // 3 - }); - :markdown - The `findByIdAndUpdate` helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases. - - h3#documents Documents - :markdown - - `doc#commit` is now removed, use [doc.markModified](./api.html#document_Document-markModified) instead - - [doc#modifiedPaths](./api.html#document_Document-modifiedPaths) is now a method not a getter - - `doc.modified` is now removed, use [doc.isModified](./api.html#document_Document-isModified) instead - - h4#gettercasting getter casting - :markdown - Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue [#820](https://github.com/LearnBoost/mongoose/issues/820) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). - - h4#setterorder setter order - :markdown - Values being set no longer cast until _after_ all setters have been applied. Previously the value returned from each setter was cast _before_ passing it on to the next setter. This changes allows more flexible processing of values in setters. See issue [#665](https://github.com/learnboost/mongoose/issues/665) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). - - h3#subdocs Subdocuments - :markdown - - `subdoc.parent` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parent). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). - - `subdoc.parentArray` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parentArray). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). - - h3#stringmatch String match validator - :markdown - The String SchemaType [match](./api.html#schema_string_SchemaString-match) validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the [required](./api.html#schematype_SchemaType-required) validator as well. See issue [#934](https://github.com/LearnBoost/mongoose/issues/934) and pull request [#935](https://github.com/LearnBoost/mongoose/pull/935). - - h3#version Versioning - :markdown - Documents are now transparently versioned. Read the in depth details [here](http://aaronheckmann.posterous.com/tag/versioning). diff --git a/docs/3.1.x/docs/models.html b/docs/3.1.x/docs/models.html deleted file mode 100644 index 9f4819a6ba5..00000000000 --- a/docs/3.1.x/docs/models.html +++ /dev/null @@ -1,32 +0,0 @@ -Mongoose Models v3.1.2Fork me on GitHub

Models

Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

Compiling your first model

var schema = new Schema({ name: 'string', size: 'string' });
-var Tank = mongoose.model('Tank', schema);
-
-// or, if you are using separate connections
-var db = mongoose.createConnection(..);
-var Tank = db.model('Tank', schema);
-

Constructing documents

Documents are instances of our model. Creating them and saving to the database is easy:

var Tank = db.model('Tank', yourSchema);
-
-var small = new Tank({ size: 'small' });
-small.save(function (err) {
-  if (err) return handleError(err);
-  // saved!
-})
-
-// or
-
-Tank.create({ size: 'small' }, function (err) {
-  if (err) return handleError(err);
-  // saved!
-})
-

Querying

Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

See the chapter on querying for more details on how to use the Query api.

Removing

Models have a static remove method available for removing all documents matching conditions.

Tank.remove({ size: 'large' }, function (err) {
-  if (err) return handleError(err);
-  // removed!
-});

Updating

Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

Yet more

The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

Next Up

Now that we've covered Models, let's take a look at querying.

diff --git a/docs/3.1.x/docs/models.jade b/docs/3.1.x/docs/models.jade deleted file mode 100644 index 09aa8736c2e..00000000000 --- a/docs/3.1.x/docs/models.jade +++ /dev/null @@ -1,61 +0,0 @@ -extends layout - -block content - h2 Models - :markdown - [Models](./api.html#model-js) are fancy constructors compiled from our `Schema` definitions. Instances of these models represent [documents](./documents.html) which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models. - - h3 Compiling your first model - :js - var schema = new Schema({ name: 'string', size: 'string' }); - var Tank = mongoose.model('Tank', schema); - - // or, if you are using separate connections - var db = mongoose.createConnection(..); - var Tank = db.model('Tank', schema); - - h3 Constructing documents - :markdown - [Documents](./documents.html) are instances of our model. Creating them and saving to the database is easy: - :js - var Tank = db.model('Tank', yourSchema); - - var small = new Tank({ size: 'small' }); - small.save(function (err) { - if (err) return handleError(err); - // saved! - }) - - // or - - Tank.create({ size: 'small' }, function (err) { - if (err) return handleError(err); - // saved! - }) - - h3 Querying - :markdown - Finding documents is easy with Mongoose, which supports the [rich](http://www.mongodb.org/display/DOCS/Advanced+Queries) query syntax of MongoDB. Documents can be retreived using each `models` [find](./api.html#model_Model-find), [findById](./api.html#model_Model-findById), [findOne](./api.html#model_Model-findOne), or [where](./api.html#model_Model-where) static methods. - - :js - Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback); - :markdown - See the chapter on [querying](./queries.html) for more details on how to use the [Query](./api.html#query-js) api. - h3 Removing - :markdown - Models have a static `remove` method available for removing all documents matching `conditions`. - :js - Tank.remove({ size: 'large' }, function (err) { - if (err) return handleError(err); - // removed! - }); - h3 Updating - :markdown - Each `model` has its own `update` method for modifying documents in the database without returning them to your application. See the [API](./api.html#model_Model-update) docs for more detail. - h3 Yet more - :markdown - The [API docs](./api.html#model_Model) cover many additional methods available like [count](./api.html#model_Model-count), [mapReduce](./api.html#model_Model-mapReduce), [aggregate](./api.html#model_Model-aggregate), and more. - - h3#next Next Up - :markdown - Now that we've covered `Models`, let's take a look at [querying](/docs/queries.html). diff --git a/docs/3.1.x/docs/plugins.html b/docs/3.1.x/docs/plugins.html deleted file mode 100644 index 72482e14fc8..00000000000 --- a/docs/3.1.x/docs/plugins.html +++ /dev/null @@ -1,33 +0,0 @@ -Mongoose Plugins v3.1.2Fork me on GitHub

Plugins

Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

- -

Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

// lastMod.js
-module.exports = exports = function lastModifiedPlugin (schema, options) {
-  schema.add({ lastMod: Date })
-  
-  schema.pre('save', function (next) {
-    this.lastMod = new Date
-    next()
-  })
-  
-  if (options && options.index) {
-    schema.path('lastMod').index(options.index)
-  }
-}
-
-// game-schema.js
-var lastMod = require('./lastMod');
-var Game = new Schema({ ... });
-Game.plugin(lastMod, { index: true });
-
-// player-schema.js
-var lastMod = require('./lastMod');
-var Player = new Schema({ ... });
-Player.plugin(lastMod);

We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

Community!

Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

Next Up

Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

diff --git a/docs/3.1.x/docs/plugins.jade b/docs/3.1.x/docs/plugins.jade deleted file mode 100644 index 24e7c9ab86d..00000000000 --- a/docs/3.1.x/docs/plugins.jade +++ /dev/null @@ -1,42 +0,0 @@ -extends layout - -block content - h2 Plugins - :markdown - Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature. - - Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each `Schema`: - - :js - // lastMod.js - module.exports = exports = function lastModifiedPlugin (schema, options) { - schema.add({ lastMod: Date }) - - schema.pre('save', function (next) { - this.lastMod = new Date - next() - }) - - if (options && options.index) { - schema.path('lastMod').index(options.index) - } - } - - // game-schema.js - var lastMod = require('./lastMod'); - var Game = new Schema({ ... }); - Game.plugin(lastMod, { index: true }); - - // player-schema.js - var lastMod = require('./lastMod'); - var Player = new Schema({ ... }); - Player.plugin(lastMod); - :markdown - We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code. - h3 Community! - :markdown - Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. - - h3#next Next Up - :markdown - Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help [contribute](/docs/contributing.html) to the continuing development of Mongoose itself. diff --git a/docs/3.1.x/docs/populate.html b/docs/3.1.x/docs/populate.html deleted file mode 100644 index 45ecc5fca6a..00000000000 --- a/docs/3.1.x/docs/populate.html +++ /dev/null @@ -1,104 +0,0 @@ -Mongoose Query Population v3.1.2Fork me on GitHub

Query Population

There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

- -

ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

var mongoose = require('mongoose')
-  , Schema = mongoose.Schema
-  
-var PersonSchema = new Schema({
-  name    : String,
-  age     : Number,
-  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
-});
-
-var StorySchema = new Schema({
-  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
-  title    : String,
-  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
-});
-
-var Story  = mongoose.model('Story', StorySchema);
-var Person = mongoose.model('Person', PersonSchema);

So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

Saving refs

Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

var aaron = new Person({ name: 'Aaron', age: 100 });
-
-aaron.save(function (err) {
-  if (err) return handleError(err);
-  
-  var story1 = new Story({
-    title: "Once upon a timex.",
-    _creator: aaron._id    // assign an ObjectId
-  });
-  
-  story1.save(function (err) {
-    if (err) return handleError(err);
-    // thats it!
-  });
-})

Population

So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

Story
-.findOne({ title: /timex/ })
-.populate('_creator')
-.exec(function (err, story) {
-  if (err) return handleError(err);
-  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
-})
-

Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

- -

Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

Field selection

What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

Story
-.findOne({ title: /timex/i })
-.populate('_creator', 'name') // only return the Persons name
-.exec(function (err, story) {
-  if (err) return handleError(err);
-  
-  console.log('The creator is %s', story._creator.name);
-  // prints "The creator is Aaron"
-  
-  console.log('The creators age is %s', story._creator.age);
-  // prints "The creators age is null'
-})

Query conditions for populate

What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

Story
-.find(...)
-.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

Refs to children

We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

- -

There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

aaron.stories.push(story1);
-aaron.save();

This allows us to perform a find and populate combo:

Person
-.findOne({ name: 'Aaron' })
-.populate('stories') // only works if we pushed refs to children
-.exec(function (err, person) {
-  if (err) return handleError(err);
-  console.log(person);
-})

However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

Story
-.find({ _creator: aaron._id })
-.populate('_creator') // not really necessary
-.exec(function (err, stories) {
-  if (err) return handleError(err);
-  console.log('The stories are an array: ', stories);
-})
-

Updating refs

Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

var guille = new Person({ name: 'Guillermo' });
-guille.save(function (err) {
-  if (err) return handleError(err);
-  
-  story._creator = guille; // or guille._id
-  
-  story.save(function (err) {
-    if (err) return handleError(err);
-    
-    Story
-    .findOne({ title: /timex/i })
-    .populate('_creator', 'name')
-    .exec(function (err, story) {
-      if (err) return handleError(err);
-      
-      console.log('The creator is %s', story._creator.name)
-      // prints "The creator is Guillermo"
-    })
-  })
-})
-

NOTE:

The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

NOTE:

Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

// this works
-Story.findOne(..).populate('_creator', 'name age').exec(..);
-
-// this doesn't
-Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
-

See the migration guide for more detail.

Next Up

Now that we've covered query population, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

diff --git a/docs/3.1.x/docs/populate.jade b/docs/3.1.x/docs/populate.jade deleted file mode 100644 index fcfaf1a437a..00000000000 --- a/docs/3.1.x/docs/populate.jade +++ /dev/null @@ -1,164 +0,0 @@ -extends layout - -block content - h2 Query Population - :markdown - There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. - - `ObjectIds` can refer to another document in a collection within our database and be `populate()`d when querying: - :js - var mongoose = require('mongoose') - , Schema = mongoose.Schema - - var PersonSchema = new Schema({ - name : String, - age : Number, - stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] - }); - - var StorySchema = new Schema({ - _creator : { type: Schema.Types.ObjectId, ref: 'Person' }, - title : String, - fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }] - }); - - var Story = mongoose.model('Story', StorySchema); - var Person = mongoose.model('Person', PersonSchema); - :markdown - So far we've created two `models`. Our `Person` model has it's `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose in which model to look, in our case the `Story` model. All `_id`s we store here must be document _ids from the `Story` model. We also added a `_creator` `ObjectId` to our `Story` schema which refers to a single `Person`. - h3 Saving refs - :markdown - Saving refs to other documents works the same way you normally save objectids, just assign an `ObjectId`: - :js - var aaron = new Person({ name: 'Aaron', age: 100 }); - - aaron.save(function (err) { - if (err) return handleError(err); - - var story1 = new Story({ - title: "Once upon a timex.", - _creator: aaron._id // assign an ObjectId - }); - - story1.save(function (err) { - if (err) return handleError(err); - // thats it! - }); - }) - h3 Population - :markdown - So far we haven't done anything special. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator`: - :js - Story - .findOne({ title: /timex/ }) - .populate('_creator') - .exec(function (err, story) { - if (err) return handleError(err); - console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron" - }) - - :markdown - Populated paths are no longer set to their original `ObjectId`s, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. - - Arrays of `ObjectId` refs work the same way. Just call the [populate](./api.html#query_Query-populate) method on the query and an array of documents will be returned _in place_ of the `ObjectIds`. - - h3 Field selection - :markdown - What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: - :js - Story - .findOne({ title: /timex/i }) - .populate('_creator', 'name') // only return the Persons name - .exec(function (err, story) { - if (err) return handleError(err); - - console.log('The creator is %s', story._creator.name); - // prints "The creator is Aaron" - - console.log('The creators age is %s', story._creator.age); - // prints "The creators age is null' - }) - h3 Query conditions for populate - :markdown - What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them? - :js - Story - .find(...) - .populate('fans', null, { age: { $gte: 21 }}, { limit: 5 }) - :markdown - Done. `Conditions` and `options` for populate queries are passed as the third and fourth arguments respectively. - h3 Refs to children - :markdown - We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' on to `aaron.stories`. - - There are two perspectives to this story. First, it's nice to have `aaron` know which are his stories. - :js - aaron.stories.push(story1); - aaron.save(); - :markdown - This allows us to perform a `find` and `populate` combo: - :js - Person - .findOne({ name: 'Aaron' }) - .populate('stories') // only works if we pushed refs to children - .exec(function (err, person) { - if (err) return handleError(err); - console.log(person); - }) - :markdown - However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely `find()` the documents we are interested in. - :js - Story - .find({ _creator: aaron._id }) - .populate('_creator') // not really necessary - .exec(function (err, stories) { - if (err) return handleError(err); - console.log('The stories are an array: ', stories); - }) - - h3 Updating refs - :markdown - Now that we have a `story` we realized that the `_creator` was incorrect. We can update `ObjectId` refs the same as any other property through the magic of Mongoose's internal casting: - :js - var guille = new Person({ name: 'Guillermo' }); - guille.save(function (err) { - if (err) return handleError(err); - - story._creator = guille; // or guille._id - - story.save(function (err) { - if (err) return handleError(err); - - Story - .findOne({ title: /timex/i }) - .populate('_creator', 'name') - .exec(function (err, story) { - if (err) return handleError(err); - - console.log('The creator is %s', story._creator.name) - // prints "The creator is Guillermo" - }) - }) - }) - - h4 NOTE: - :markdown - The documents returned from calling [populate](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. - - h4 NOTE: - :markdown - _Field selection_ in v3 is slightly different than v2. Arrays of fields are no longer accepted. - - :js - // this works - Story.findOne(..).populate('_creator', 'name age').exec(..); - - // this doesn't - Story.findOne(..).populate('_creator', ['name', 'age']).exec(..); - - :markdown - See the [migration guide](./migration.html#fields) for more detail. - - h3#next Next Up - :markdown - Now that we've covered query population, let's take a look at how we can break pieces of our functionality out into reusable and shareable [plugins](/docs/plugins.html). diff --git a/docs/3.1.x/docs/prior.html b/docs/3.1.x/docs/prior.html deleted file mode 100644 index c7fa6215c3c..00000000000 --- a/docs/3.1.x/docs/prior.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose v3.1.2Fork me on GitHub

Prior Release Documentation

diff --git a/docs/3.1.x/docs/prior.jade b/docs/3.1.x/docs/prior.jade deleted file mode 100644 index 1ef7d088a72..00000000000 --- a/docs/3.1.x/docs/prior.jade +++ /dev/null @@ -1,8 +0,0 @@ -extends layout - -block content - h2 Prior Release Documentation - ul - each release in releases - li - a(href=release.url)= release.version diff --git a/docs/3.1.x/docs/queries.html b/docs/3.1.x/docs/queries.html deleted file mode 100644 index 11dd7c0816c..00000000000 --- a/docs/3.1.x/docs/queries.html +++ /dev/null @@ -1,41 +0,0 @@ -Mongoose Queries v3.1.2Fork me on GitHub

Queries

Documents can be retrieved through several static helper methods of models.

Any model method which involves specifying query conditions can be executed two ways:

- -

When a callback function:

- -
  • is passed, the operation will be executed immediately with the results passed to the callback.
  • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
- -

Let's take a look at what happens when passing a callback:

var Person = db.model('Person', yourSchema);
-
-// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
-Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
-  if (err) return handleError(err);
-  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
-})

Here we see that the query was executed immediately and the results passed to our callback. -Now let's look at what happens when no callback is passed:

// find each person with a last name matching 'Ghost'
-var query = Person.findOne({ 'name.last': 'Ghost' });
-
-// selecting the `name` and `occupation` fields
-query.select('name occupation');
-
-// execute the query at a later time
-query.exec(function (err, person) {
-  if (err) return handleError(err);
-  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
-})

An instance of Query was returned which allows us to build up our query. Taking this example further:

Person
-.find({ occupation: /host/ })
-.where('name.last').equals('Ghost')
-.where('age').gt(17).lt(66)
-.where('likes').in(['vaporizing', 'talking'])
-.limit(10)
-.sort('-occupation')
-.select('name occupation')
-.exec(callback);
-

References to other documents

There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

Streaming

Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

Next Up

Now that we've covered Queries, let's take a look at validation.

diff --git a/docs/3.1.x/docs/queries.jade b/docs/3.1.x/docs/queries.jade deleted file mode 100644 index 68c529efe25..00000000000 --- a/docs/3.1.x/docs/queries.jade +++ /dev/null @@ -1,62 +0,0 @@ -extends layout - -block content - h2 Queries - :markdown - Documents can be retrieved through several static helper methods of [models](./models.html). - :markdown - Any [model](./api.html#model_Model) method which [involves](./api.html#model_Model-find) [specifying](./api.html#model_Model-findById) [query](./api.html#model_Model-count) [conditions](./api.html#model_Model-update) can be executed two ways: - - When a `callback` function: - - - is passed, the operation will be executed immediately with the results passed to the callback. - - is not passed, an instance of [Query](./api.html#query-js) is returned, which provides a special `QueryBuilder` interface for you. - - Let's take a look at what happens when passing a `callback`: - :js - var Person = db.model('Person', yourSchema); - - // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields - Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { - if (err) return handleError(err); - console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. - }) - :markdown - Here we see that the query was executed immediately and the results passed to our callback. - Now let's look at what happens when no `callback` is passed: - :js - // find each person with a last name matching 'Ghost' - var query = Person.findOne({ 'name.last': 'Ghost' }); - - // selecting the `name` and `occupation` fields - query.select('name occupation'); - - // execute the query at a later time - query.exec(function (err, person) { - if (err) return handleError(err); - console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. - }) - :markdown - An instance of [Query](./api.html#query-js) was returned which allows us to build up our query. Taking this example further: - :js - Person - .find({ occupation: /host/ }) - .where('name.last').equals('Ghost') - .where('age').gt(17).lt(66) - .where('likes').in(['vaporizing', 'talking']) - .limit(10) - .sort('-occupation') - .select('name occupation') - .exec(callback); - - h3#refs References to other documents - :markdown - There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. Read more [here](./populate.html). - - h3 Streaming - :markdown - Queries can be [streamed](http://nodejs.org/api/stream.html) from MongoDB to your application as well. Simply call the query's [stream](./api.html#query_Query-stream) method instead of [exec](./api.html#query_Query-exec) to return an instance of [QueryStream](./api.html#querystream_QueryStream). - - h3#next Next Up - :markdown - Now that we've covered `Queries`, let's take a look at [validation](/docs/validation.html). diff --git a/docs/3.1.x/docs/releases b/docs/3.1.x/docs/releases deleted file mode 100644 index cd9fcd27bd1..00000000000 --- a/docs/3.1.x/docs/releases +++ /dev/null @@ -1,2 +0,0 @@ -2.8.x -2.7.x diff --git a/docs/3.1.x/docs/schematypes.html b/docs/3.1.x/docs/schematypes.html deleted file mode 100644 index 76b695770c7..00000000000 --- a/docs/3.1.x/docs/schematypes.html +++ /dev/null @@ -1,67 +0,0 @@ -Mongoose SchemaTypes v3.1.2Fork me on GitHub

SchemaTypes

SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

Following are all valid Schema Types.

  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • ObjectId
  • Array

Example

var schema = new Schema({
-  name:    String,
-  binary:  Buffer,
-  living:  Boolean,
-  updated: { type: Date, default: Date.now },
-  age:     { type: Number, min: 18, max: 65 },
-  mixed:   Schema.Types.Mixed,
-  _someId: Schema.Types.ObjectId,
-  array:      [],
-  ofString:   [String],
-  ofNumber:   [Number],
-  ofDates:    [Date],
-  ofBuffer:   [Buffer],
-  ofBoolean:  [Boolean],
-  ofMixed:    [Schema.Types.Mixed],
-  ofObjectId: [Schema.Types.ObjectId],
-  nested: {
-    stuff: { type: String, lowercase: true, trim: true }
-  }
-})
-
-// example use
-
-var Thing = mongoose.model('Thing', schema);
-
-var m = new Thing;
-m.name = 'Statue of Liberty';
-m.age = 125;
-m.updated = new Date;
-m.binary = new Buffer(0);
-m.living = false;
-m.mixed = {[ any: { thing: 'i want' } ]};
-m.markModified('mixed');
-m._someId = new mongoose.Types.ObjectId;
-m.array.push(1);
-m.ofString.push("strings!");
-m.ofNumber.unshift(1,2,3,4);
-m.ofDates.addToSet(new Date);
-m.ofBuffer.pop();
-m.ofMixed = [1, [], 'three', { four: 5 }];
-m.nested.stuff = 'good';
-m.save(callback);
-

Usage notes:

Mixed

An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

var Any = new Schema({ any: {} });
-var Any = new Schema({ any: Schema.Types.Mixed });

Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

person.anything = { x: [3, 4, { y: "changed" }] };
-person.markModified('anything');
-person.save(); // anything will now get saved

ObjectIds

To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

var mongoose = require('mongoose');
-var ObjectId = mongoose.Schema.Types.ObjectId;
-var Car = new Schema({ driver: ObjectId });
-// or just Schema.ObjectId for backwards compatibility with v2

Arrays

Provide creation of arrays of SchemaTypes or Sub-Documents.

var ToySchema = new Schema({ name: String });
-var ToyBox = new Schema({
-  toys: [ToySchema],
-  buffers: [Buffer],
-  string:  [String],
-  numbers: [Number]
-  // ... etc
-});

Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

var Empty1 = new Schema({ any: [] });
-var Empty2 = new Schema({ any: Array });
-var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
-var Empty4 = new Schema({ any: [{}] });

Creating Custom Types

Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

Next Up

Now that we've covered SchemaTypes, let's take a look at Documents.

diff --git a/docs/3.1.x/docs/schematypes.jade b/docs/3.1.x/docs/schematypes.jade deleted file mode 100644 index b36574175f4..00000000000 --- a/docs/3.1.x/docs/schematypes.jade +++ /dev/null @@ -1,146 +0,0 @@ -extends layout - -block content - h2 SchemaTypes - p - | SchemaTypes handle definition of path - a(href="./api.html#schematype_SchemaType-default") defaults - |, - a(href="./api.html#schematype_SchemaType-validate") validation - |, - a(href="./api.html#schematype_SchemaType-get") getters - |, - a(href="./api.html#schematype_SchemaType-set") setters - |, - a(href="./api.html#schematype_SchemaType-select") field selection defaults - | for - a(href="./api.html#query-js") queries - | and other general characteristics for - a(href="./api.html#schema-string-js") Strings - | and - a(href="./api.html#schema-number-js") Numbers - |. Check out their respective API documentation for more detail. - p - | Following are all valid - a(href="./api.html#schema_Schema-Types") Schema Types - |. - ul - li String - li Number - li Date - li Buffer - li Boolean - li Mixed - li ObjectId - li Array - h4 Example - :js - var schema = new Schema({ - name: String, - binary: Buffer, - living: Boolean, - updated: { type: Date, default: Date.now }, - age: { type: Number, min: 18, max: 65 }, - mixed: Schema.Types.Mixed, - _someId: Schema.Types.ObjectId, - array: [], - ofString: [String], - ofNumber: [Number], - ofDates: [Date], - ofBuffer: [Buffer], - ofBoolean: [Boolean], - ofMixed: [Schema.Types.Mixed], - ofObjectId: [Schema.Types.ObjectId], - nested: { - stuff: { type: String, lowercase: true, trim: true } - } - }) - - // example use - - var Thing = mongoose.model('Thing', schema); - - var m = new Thing; - m.name = 'Statue of Liberty'; - m.age = 125; - m.updated = new Date; - m.binary = new Buffer(0); - m.living = false; - m.mixed = {[ any: { thing: 'i want' } ]}; - m.markModified('mixed'); - m._someId = new mongoose.Types.ObjectId; - m.array.push(1); - m.ofString.push("strings!"); - m.ofNumber.unshift(1,2,3,4); - m.ofDates.addToSet(new Date); - m.ofBuffer.pop(); - m.ofMixed = [1, [], 'three', { four: 5 }]; - m.nested.stuff = 'good'; - m.save(callback); - - h3 Usage notes: - h4#mixed Mixed - p An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent: - :js - var Any = new Schema({ any: {} }); - var Any = new Schema({ any: Schema.Types.Mixed }); - p - | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the - code .markModified(path) - | method of the document passing the path to the Mixed type you just changed. - :js - person.anything = { x: [3, 4, { y: "changed" }] }; - person.markModified('anything'); - person.save(); // anything will now get saved - h4#objectids ObjectIds - p - | To specify a type of ObjectId, use - code Schema.Types.ObjectId - | in your declaration. - :js - var mongoose = require('mongoose'); - var ObjectId = mongoose.Schema.Types.ObjectId; - var Car = new Schema({ driver: ObjectId }); - // or just Schema.ObjectId for backwards compatibility with v2 - h4#arrays Arrays - p - | Provide creation of arrays of - a(href="./api.html#schema_Schema-Types") SchemaTypes - | or - a(href="./subdocs.html") Sub-Documents - |. - :js - var ToySchema = new Schema({ name: String }); - var ToyBox = new Schema({ - toys: [ToySchema], - buffers: [Buffer], - string: [String], - numbers: [Number] - // ... etc - }); - p - | Note: specifying an empty array is equivalent to - code Mixed - |. The following all create arrays of - code Mixed - |: - :js - var Empty1 = new Schema({ any: [] }); - var Empty2 = new Schema({ any: Array }); - var Empty3 = new Schema({ any: [Schema.Types.Mixed] }); - var Empty4 = new Schema({ any: [{}] }); - h3#customtypes Creating Custom Types - p - | Mongoose can also be extended with custom SchemaTypes. Search the - a(href="http://plugins.mongoosejs.com") plugins - | site for compatible types like - a(href="https://github.com/aheckmann/mongoose-long") mongoose-long - | and - a(href="https://github.com/aheckmann/mongoose-number") other - | - a(href="https://github.com/bnoguchi/mongoose-types") types - |. - - h3#next Next Up - :markdown - Now that we've covered `SchemaTypes`, let's take a look at [Documents](/docs/documents.html). diff --git a/docs/3.1.x/docs/source/_docs b/docs/3.1.x/docs/source/_docs deleted file mode 100644 index b127ff2902f..00000000000 --- a/docs/3.1.x/docs/source/_docs +++ /dev/null @@ -1,16169 +0,0 @@ - -### lib/collection.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var STATES = require('./connectionstate')", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "require('./connectionstate')", - "string": "STATES" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the collection" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "conn", - "description": "A MongooseConnection instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "optional collection options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Abstract Collection constructor

\n\n

This is the base class that drivers inherit from and implement.

", - "summary": "

Abstract Collection constructor

", - "body": "

This is the base class that drivers inherit from and implement.

" - }, - "isPrivate": false, - "ignore": false, - "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", - "ctx": { - "type": "function", - "name": "Collection", - "string": "Collection()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "name" - } - ], - "description": { - "full": "

The collection name

", - "summary": "

The collection name

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.name;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "conn" - } - ], - "description": { - "full": "

The Connection instance

", - "summary": "

The Connection instance

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.conn;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the database connects

", - "summary": "

Called when the database connects

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onOpen", - "string": "Collection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the database disconnects

", - "summary": "

Called when the database disconnects

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onClose", - "string": "Collection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the method to queue" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method when executed" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Queues a method for later execution when its
database connection opens.

", - "summary": "

Queues a method for later execution when its
database connection opens.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "addQueue", - "string": "Collection.prototype.addQueue()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Executes all queued methods and clears the queue.

", - "summary": "

Executes all queued methods and clears the queue.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "doQueue", - "string": "Collection.prototype.doQueue()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "ensureIndex", - "string": "Collection.prototype.ensureIndex()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findAndModify", - "string": "Collection.prototype.findAndModify()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findOne", - "string": "Collection.prototype.findOne()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "find", - "string": "Collection.prototype.find()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "insert", - "string": "Collection.prototype.insert()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "save", - "string": "Collection.prototype.save()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "update", - "string": "Collection.prototype.update()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "getIndexes", - "string": "Collection.prototype.getIndexes()" - } - }, - { - "tags": [], - "description": { - "full": "

Abstract method that drivers must implement.

", - "summary": "

Abstract method that drivers must implement.

", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "mapReduce", - "string": "Collection.prototype.mapReduce()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = Collection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Collection", - "string": "module.exports" - } - } -] -### lib/connection.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , assert =require('assert')", - "ctx": { - "type": "declaration", - "name": "url", - "value": "require('url')", - "string": "url" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Protocol prefix regexp.

", - "summary": "

Protocol prefix regexp.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", - "ctx": { - "type": "declaration", - "name": "rgxProtocol", - "value": "/^(?:.)+:\\/\\//", - "string": "rgxProtocol" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "a mongoose instance" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." - }, - { - "type": "event", - "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." - }, - { - "type": "event", - "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." - }, - { - "type": "event", - "string": "`disconnecting`: Emitted when `connection.close()` was executed." - }, - { - "type": "event", - "string": "`disconnected`: Emitted after getting disconnected from the db." - }, - { - "type": "event", - "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." - }, - { - "type": "event", - "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." - }, - { - "type": "event", - "string": "`error`: Emitted when an error occurs on this connection." - }, - { - "type": "event", - "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Connection constructor

\n\n

For practical reasons, a Connection equals a Db.

", - "summary": "

Connection constructor

", - "body": "

For practical reasons, a Connection equals a Db.

" - }, - "isPrivate": false, - "ignore": false, - "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", - "ctx": { - "type": "function", - "name": "Connection", - "string": "Connection()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from EventEmitter

", - "summary": "

Inherit from EventEmitter

", - "body": "" - }, - "ignore": true, - "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Connection", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Connection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readyState" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Connection ready state

\n\n
    \n
  • 0 = disconnected
  • \n
  • 1 = connected
  • \n
  • 2 = connecting
  • \n
  • 3 = disconnecting
  • \n
\n\n

Each state change emits its associated event name.

\n\n

Example

\n\n
conn.on('connected', callback);\nconn.on('disconnected', callback);\n
", - "summary": "

Connection ready state

", - "body": "
    \n
  • 0 = disconnected
  • \n
  • 1 = connected
  • \n
  • 2 = connecting
  • \n
  • 3 = disconnecting
  • \n
\n\n

Each state change emits its associated event name.

\n\n

Example

\n\n
conn.on('connected', callback);\nconn.on('disconnected', callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" - }, - { - "tags": [ - { - "type": "property", - "string": "collections" - } - ], - "description": { - "full": "

A hash of the collections associated with this connection

", - "summary": "

A hash of the collections associated with this connection

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collections;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

The mongodb.Db instance, set when the connection is opened

", - "summary": "

The mongodb.Db instance, set when the connection is opened

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.db;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "connection_string", - "description": "mongodb://uri or the host to which you are connecting" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[port]", - "description": "database port" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Opens the connection to MongoDB.

\n\n

options is a hash with the following possible properties:

\n\n
db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
\n\n

Notes:

\n\n

Mongoose forces the db option forceServerObjectId false and cannot be overridden.
Mongoose defaults the server auto_reconnect options to true which can be overridden.
See the node-mongodb-native driver instance for options that it understands.

", - "summary": "

Opens the connection to MongoDB.

", - "body": "

options is a hash with the following possible properties:

\n\n
db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
\n\n

Notes:

\n\n

Mongoose forces the db option forceServerObjectId false and cannot be overridden.
Mongoose defaults the server auto_reconnect options to true which can be overridden.
See the node-mongodb-native driver instance for options that it understands.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n uri = url.parse(host);\n host = uri.hostname;\n port = uri.port || 27017;\n database = uri.pathname && uri.pathname.replace(/\\//g, '');\n }\n\n this.options = this.defaultOptions(options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing connection hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing connection database.'), callback);\n return this;\n }\n\n // handle authentication\n if (uri && uri.auth) {\n var auth = uri.auth.split(':');\n this.user = auth[0];\n this.pass = auth[1];\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n // user/pass options\n } else if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "open", - "string": "Connection.prototype.open()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "uris", - "description": "comma-separated mongodb:// `URI`s" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name if not included in `uris`" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "passed to the internal driver" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Connects to a replica set.

\n\n

Example:

\n\n
var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
\n\n

The database name and/or auth need only be included in one URI.
The options is a hash which is passed to the internal driver connection object.

\n\n

Valid options

\n\n
db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
", - "summary": "

Connects to a replica set.

", - "body": "

Example:

\n\n
var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
\n\n

The database name and/or auth need only be included in one URI.
The options is a hash which is passed to the internal driver connection object.

\n\n

Valid options

\n\n
db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n var uris = uris.split(',')\n , self = this;\n\n switch (arguments.length) {\n case 3:\n this.name = database;\n if ('function' === typeof options) callback = options, options = {};\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n this.options = options = this.defaultOptions(options);\n\n if (uris.length < 2) {\n this.error(new Error('Please provide comma-separated URIs'), callback);\n return this;\n }\n\n this.replica = true;\n this.host = [];\n this.port = [];\n\n uris.forEach(function (uri) {\n // handle missing protocols\n if (!rgxProtocol.test(uri))\n uri = 'mongodb://' + uri;\n\n var uri = url.parse(uri);\n\n self.host.push(uri.hostname);\n self.port.push(uri.port || 27017);\n\n if (!self.name && uri.pathname && uri.pathname.replace(/\\//g, ''))\n self.name = uri.pathname.replace(/\\//g, '');\n\n if (!self.user && uri.auth) {\n var auth = uri.auth.split(':');\n self.user = auth[0];\n self.pass = auth[1];\n }\n });\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "openSet", - "string": "Connection.prototype.openSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "optional" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

error

\n\n

Graceful error handling, passes error to callback
if available, else emits error on the connection.

", - "summary": "

error

", - "body": "

Graceful error handling, passes error to callback
if available, else emits error on the connection.

" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "error", - "string": "Connection.prototype.error()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Handles opening the connection with the appropriate method based on connection type.

", - "summary": "

Handles opening the connection with the appropriate method based on connection type.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "_open", - "string": "Connection.prototype._open()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the connection is opened

", - "summary": "

Called when the connection is opened

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onOpen", - "string": "Connection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "self" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Closes the connection

", - "summary": "

Closes the connection

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "close", - "string": "Connection.prototype.close()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the connection closes

", - "summary": "

Called when the connection closes

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onClose", - "string": "Connection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "of the collection" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional collection options" - }, - { - "type": "return", - "types": [ - "Collection" - ], - "description": "collection instance" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Retrieves a collection, creating it if not cached.

", - "summary": "

Retrieves a collection, creating it if not cached.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "collection", - "string": "Connection.prototype.collection()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "the model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "a schema. necessary when defining a model" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name of mongodb collection (optional) if not given it will be induced from model name" - }, - { - "type": "see", - "local": "Mongoose#model #index_Mongoose-model", - "visibility": "Mongoose#model" - }, - { - "type": "return", - "types": [ - "Model" - ], - "description": "The compiled model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines or retrieves a model.

\n\n
var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
", - "summary": "

Defines or retrieves a model.

", - "body": "
var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.model = function (name, schema, collection) {\n if (!this.models[name]) {\n var model = this.base.model(name, schema, collection, true)\n , Model\n\n if (this != model.prototype.db) {\n // subclass model using this connection and collection name\n Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model))\n return new Model(doc, fields, skipId);\n model.call(this, doc, fields, skipId);\n };\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = this;\n\n // collection name discovery\n if ('string' === typeof schema) {\n collection = schema;\n }\n\n if (!collection) {\n collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);\n }\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n Model.prototype.collection = this.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n }\n\n this.models[name] = Model || model;\n }\n\n return this.models[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "model", - "string": "Connection.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "level", - "description": "either off (0), slow (1), or all (2)" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[ms]", - "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Set profiling level.

", - "summary": "

Set profiling level.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "setProfiling", - "string": "Connection.prototype.setProfiling()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Prepares default connection options.

", - "summary": "

Prepares default connection options.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.defaultOptions = function (options) {\n var o = options || {};\n\n o.server = o.server || {};\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n o.db = o.db || {};\n o.db.forceServerObjectId = false;\n\n return o;\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "defaultOptions", - "string": "Connection.prototype.defaultOptions()" - } - }, - { - "tags": [], - "description": { - "full": "

Noop.

", - "summary": "

Noop.

", - "body": "" - }, - "ignore": true, - "code": "function noop () {}", - "ctx": { - "type": "function", - "name": "noop", - "string": "noop()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", - "ctx": { - "type": "property", - "receiver": "Connection", - "name": "STATES", - "value": "STATES", - "string": "Connection.STATES" - } - } -] -### lib/connectionstate.js -[ - { - "tags": [], - "description": { - "full": "

Connection states

", - "summary": "

Connection states

", - "body": "" - }, - "ignore": true, - "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "module.exports = exports = Object.create(null)", - "string": "STATES" - } - } -] -### lib/document.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the values to set" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "the fields which were selected in the query returning this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "bool, should we auto create an ObjectId _id" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." - }, - { - "type": "event", - "string": "`save`: Emitted when the document is successfully saved" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Document constructor.

", - "summary": "

Document constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", - "ctx": { - "type": "function", - "name": "Document", - "string": "Document()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from EventEmitter.

", - "summary": "

Inherit from EventEmitter.

", - "body": "" - }, - "ignore": true, - "code": "Document.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Document.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "schema" - } - ], - "description": { - "full": "

The documents schema.

", - "summary": "

The documents schema.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.schema;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "isNew" - } - ], - "description": { - "full": "

Boolean flag specifying if the document is new.

", - "summary": "

Boolean flag specifying if the document is new.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isNew;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "local": "Schema options /docs/guide.html#options", - "visibility": "Schema" - }, - { - "type": "property", - "string": "id" - } - ], - "description": { - "full": "

The string version of this documents _id.

\n\n

Note:

\n\n

This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

\n\n
new Schema({ name: String }, { id: false });\n
", - "summary": "

The string version of this documents _id.

", - "body": "

Note:

\n\n

This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

\n\n
new Schema({ name: String }, { id: false });\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.id;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "errors" - } - ], - "description": { - "full": "

Hash containing current validation errors.

", - "summary": "

Hash containing current validation errors.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.errors;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Builds the default doc structure

", - "summary": "

Builds the default doc structure

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_buildDoc", - "string": "Document.prototype._buildDoc()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Initializes the document without setters or marking anything modified.

\n\n

Called internally after a document is returned from mongodb.

", - "summary": "

Initializes the document without setters or marking anything modified.

", - "body": "

Called internally after a document is returned from mongodb.

" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init');\n if (fn) fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "init", - "string": "Document.prototype.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "self", - "description": "document instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "raw mongodb doc" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "object we are initializing" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Init helper.

", - "summary": "

Init helper.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", - "ctx": { - "type": "function", - "name": "init", - "string": "init()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Stores the current values of the shard keys.

\n\n

Note:

\n\n

Shard key values do not / are not allowed to change.

", - "summary": "

Stores the current values of the shard keys.

", - "body": "

Note:

\n\n

Shard key values do not / are not allowed to change.

" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_storeShard", - "string": "Document.prototype._storeShard()" - } - }, - { - "tags": [], - "description": { - "full": "

Set up middleware support

", - "summary": "

Set up middleware support

", - "body": "" - }, - "ignore": true, - "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sends an update command with this document _id as the query selector.

\n\n

Example:

\n\n
weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
\n\n

Valid options:

\n\n
    \n
  • safe safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
", - "summary": "

Sends an update command with this document _id as the query selector.

", - "body": "

Example:

\n\n
weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
\n\n

Valid options:

\n\n
    \n
  • safe safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "update", - "string": "Document.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "path", - "description": "path or object of key/vals to set" - }, - { - "type": "param", - "types": [ - "Any" - ], - "name": "val", - "description": "the value to set" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for \"on-the-fly\" attributes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets the value of a path, or many paths.

\n\n

Example:

\n\n
// path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
", - "summary": "

Sets the value of a path, or many paths.

", - "body": "

Example:

\n\n
// path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.set = function (path, val, type) {\n var constructing = true === type\n , adhoc = type && true !== type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n if (null != path[key] && 'Object' === path[key].constructor.name\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n pathtype = this.schema.pathType(prefix + key);\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "set", - "string": "Document.prototype.set()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Handles the actual setting of the value and marking the path modified if appropriate.

", - "summary": "

Handles the actual setting of the value and marking the path modified if appropriate.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {\n if (this.isNew) {\n this.markModified(pathToMark);\n } else {\n\n priorVal || (priorVal = this.get(path));\n\n if (!this.isDirectModified(pathToMark)) {\n if (undefined === val && !this.isSelected(path)) {\n // special case:\n // when a path is not selected in a query its initial\n // value will be undefined.\n this.markModified(pathToMark, priorVal);\n } else if (undefined === val && path in this._activePaths.states.default) {\n // do nothing\n // unsetting the default value which was never saved\n } else if (!deepEqual(val, priorVal)) {\n this.markModified(pathToMark, priorVal);\n } else if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // special case:\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n this.markModified(pathToMark, priorVal);\n }\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_set", - "string": "Document.prototype._set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Gets a raw value from a path (no getters)

", - "summary": "

Gets a raw value from a path (no getters)

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "getValue", - "string": "Document.prototype.getValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Sets a raw value for a path (no casting, setters, transformations)

", - "summary": "

Sets a raw value for a path (no casting, setters, transformations)

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "setValue", - "string": "Document.prototype.setValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for on-the-fly attributes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns the value of a path.

\n\n

Example

\n\n
// path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
", - "summary": "

Returns the value of a path.

", - "body": "

Example

\n\n
// path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "get", - "string": "Document.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns the schematype for the given path.

", - "summary": "

Returns the schematype for the given path.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_path", - "string": "Document.prototype._path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to mark modified" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Marks the path as having pending changes to write to the db.

\n\n

Very helpful when using Mixed types.

\n\n

Example:

\n\n
doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
", - "summary": "

Marks the path as having pending changes to write to the db.

", - "body": "

Very helpful when using Mixed types.

\n\n

Example:

\n\n
doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "markModified", - "string": "Document.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "function to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope with which to call fn" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

", - "summary": "

Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "try", - "string": "Document.prototype.try()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns the list of paths that have been modified.

", - "summary": "

Returns the list of paths that have been modified.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "modifiedPaths", - "string": "Document.prototype.modifiedPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns true if this document was modified, else false.

\n\n

If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

\n\n

Example

\n\n
doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
", - "summary": "

Returns true if this document was modified, else false.

", - "body": "

If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

\n\n

Example

\n\n
doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isModified", - "string": "Document.prototype.isModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns true if path was directly set and modified, else false.

\n\n

Example

\n\n
doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
", - "summary": "

Returns true if path was directly set and modified, else false.

", - "body": "

Example

\n\n
doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isDirectModified", - "string": "Document.prototype.isDirectModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Checks if path was initialized.

", - "summary": "

Checks if path was initialized.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isInit", - "string": "Document.prototype.isInit()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Checks if path was selected in the source query which initialized this document.

\n\n

Example

\n\n
Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
", - "summary": "

Checks if path was selected in the source query which initialized this document.

", - "body": "

Example

\n\n
Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isSelected", - "string": "Document.prototype.isSelected()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "cb", - "description": "called after validation completes, passing an error if one occurred" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes registered validation rules for this document.

\n\n

Note:

\n\n

This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

\n\n

Example:

\n\n
doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
", - "summary": "

Executes registered validation rules for this document.

", - "body": "

Note:

\n\n

This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

\n\n

Example:

\n\n
doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n cb(err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "validate", - "string": "Document.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "the error which states the reason `path` was invalid" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Marks a path as invalid, causing validation to fail.

", - "summary": "

Marks a path as invalid, causing validation to fail.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "invalidate", - "string": "Document.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

Resets the internal modified state of this document.

", - "summary": "

Resets the internal modified state of this document.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return (val && val instanceof DocumentArray && val.length);\n })\n .forEach(function (array) {\n array.forEach(function (doc) {\n doc._reset();\n });\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_reset", - "string": "Document.prototype._reset()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns this documents dirty paths / vals.

", - "summary": "

Returns this documents dirty paths / vals.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_dirty", - "string": "Document.prototype._dirty()" - } - }, - { - "tags": [], - "description": { - "full": "

Compiles schemas.

", - "summary": "

Compiles schemas.

", - "body": "" - }, - "ignore": true, - "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", - "ctx": { - "type": "function", - "name": "compile", - "string": "compile()" - } - }, - { - "tags": [], - "description": { - "full": "

Defines the accessor named prop on the incoming prototype.

", - "summary": "

Defines the accessor named prop on the incoming prototype.

", - "body": "" - }, - "ignore": true, - "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", - "ctx": { - "type": "function", - "name": "define", - "string": "define()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Assigns/compiles schema into this documents prototype.

", - "summary": "

Assigns/compiles schema into this documents prototype.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_setSchema", - "string": "Document.prototype._setSchema()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Register default hooks

", - "summary": "

Register default hooks

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return (val && val instanceof DocumentArray && val.length);\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n subdocs += array.length;\n array.forEach(function (value) {\n if (error) return;\n\n value.save(function (err) {\n if (error) return;\n\n if (err) {\n error = true;\n self._validationError = undefined;\n return next(err);\n }\n\n --subdocs || next();\n });\n });\n });\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_registerHooks", - "string": "Document.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Registers an error

", - "summary": "

Registers an error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_error", - "string": "Document.prototype._error()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Executes methods queued from the Schema definition

", - "summary": "

Executes methods queued from the Schema definition

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_doQueue", - "string": "Document.prototype._doQueue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "js object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Converts this document into a plain javascript object

\n\n

Options:

\n\n
    \n
  • getters apply all getters (path and virtual getters)
  • \n
  • virtuals apply virtual getters (can override getters option)
  • \n
  • minimize remove empty objects (defaults to true)
  • \n
\n\n

Example of only applying path getters

\n\n
doc.toObject({ getters: true, virtuals: false })\n
\n\n

Example of only applying virtual getters

\n\n
doc.toObject({ virtuals: true })\n
\n\n

Example of applying both path and virtual getters

\n\n
doc.toObject({ getters: true })\n
\n\n

To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

\n\n
schema.set('toObject', { virtuals: true })\n
\n\n

See schema options for details.

", - "summary": "

Converts this document into a plain javascript object

", - "body": "

Options:

\n\n
    \n
  • getters apply all getters (path and virtual getters)
  • \n
  • virtuals apply virtual getters (can override getters option)
  • \n
  • minimize remove empty objects (defaults to true)
  • \n
\n\n

Example of only applying path getters

\n\n
doc.toObject({ getters: true, virtuals: false })\n
\n\n

Example of only applying virtual getters

\n\n
doc.toObject({ virtuals: true })\n
\n\n

Example of applying both path and virtual getters

\n\n
doc.toObject({ getters: true })\n
\n\n

To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

\n\n
schema.set('toObject', { virtuals: true })\n
\n\n

See schema options for details.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toObject", - "string": "Document.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "json", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "either `virtuals` or `paths`" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "`json`" - } - ], - "description": { - "full": "

Applies virtuals properties to json.

", - "summary": "

Applies virtuals properties to json.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", - "ctx": { - "type": "function", - "name": "applyGetters", - "string": "applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "same options as `Document#toObject`" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "see", - "local": "Document#toObject #document_Document-toObject", - "visibility": "Document#toObject" - }, - { - "type": "", - "string": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The return value of this method is used in calls to JSON.stringify(doc).

\n\n

This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

\n\n
schema.set('toJSON', { virtuals: true })\n
\n\n

See schema options for details.

", - "summary": "

The return value of this method is used in calls to JSON.stringify(doc).

", - "body": "

This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

\n\n
schema.set('toJSON', { virtuals: true })\n
\n\n

See schema options for details.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toJSON", - "string": "Document.prototype.toJSON()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "inspect", - "string": "Document.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "toString" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toString = Document.prototype.inspect;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "toString", - "value": "Document.prototype.inspect", - "string": "Document.prototypetoString" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "a document to compare" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns true if the Document stores the same data as doc.

\n\n

Documents are considered equal when they have matching _ids.

", - "summary": "

Returns true if the Document stores the same data as doc.

", - "body": "

Documents are considered equal when they have matching _ids.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "equals", - "string": "Document.prototype.equals()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", - "ctx": { - "type": "property", - "receiver": "Document", - "name": "ValidationError", - "value": "ValidationError", - "string": "Document.ValidationError" - } - } -] -### lib/drivers/node-mongodb-native/binary.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require('mongodb').BSONPure.Binary", - "string": "Binary" - } - } -] -### lib/drivers/node-mongodb-native/collection.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", - "ctx": { - "type": "declaration", - "name": "MongooseCollection", - "value": "require('../../collection')", - "string": "MongooseCollection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Collection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

A node-mongodb-native collection implementation.

\n\n

All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

", - "summary": "

A node-mongodb-native collection implementation.

", - "body": "

All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

" - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", - "ctx": { - "type": "function", - "name": "NativeCollection", - "string": "NativeCollection()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from abstract Collection.

", - "summary": "

Inherit from abstract Collection.

", - "body": "" - }, - "ignore": true, - "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "__proto__", - "value": "MongooseCollection.prototype", - "string": "NativeCollection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the connection opens.

", - "summary": "

Called when the connection opens.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onOpen", - "string": "NativeCollection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the connection closes

", - "summary": "

Called when the connection closes

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onClose", - "string": "NativeCollection.prototype.onClose()" - } - }, - { - "tags": [], - "description": { - "full": "

Copy the collection methods and make them subject to queues

", - "summary": "

Copy the collection methods and make them subject to queues

", - "body": "" - }, - "ignore": true, - "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" - }, - { - "tags": [], - "description": { - "full": "

Debug print helper

", - "summary": "

Debug print helper

", - "body": "" - }, - "ignore": true, - "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", - "ctx": { - "type": "function", - "name": "print", - "string": "print()" - } - }, - { - "tags": [], - "description": { - "full": "

Debug print helper

", - "summary": "

Debug print helper

", - "body": "" - }, - "ignore": true, - "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n } else if ('Date' === x[key].constructor.name) {\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", - "ctx": { - "type": "function", - "name": "format", - "string": "format()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "method", - "string": "getIndexes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Retreives information about this collections indexes.

", - "summary": "

Retreives information about this collections indexes.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "getIndexes", - "value": "NativeCollection.prototype.indexInformation", - "string": "NativeCollection.prototypegetIndexes" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeCollection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeCollection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/connection.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", - "ctx": { - "type": "declaration", - "name": "MongooseConnection", - "value": "require('../../connection')", - "string": "MongooseConnection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Connection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

A node-mongodb-native connection implementation.

", - "summary": "

A node-mongodb-native connection implementation.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", - "ctx": { - "type": "function", - "name": "NativeConnection", - "string": "NativeConnection()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from Connection.

", - "summary": "

Inherits from Connection.

", - "body": "" - }, - "ignore": true, - "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeConnection", - "name": "__proto__", - "value": "MongooseConnection.prototype", - "string": "NativeConnection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Opens the connection to MongoDB.

", - "summary": "

Opens the connection to MongoDB.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, Number(this.port), this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpen", - "string": "NativeConnection.prototype.doOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - } - ], - "description": { - "full": "

Opens a connection to a MongoDB ReplicaSet.

\n\n

See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

", - "summary": "

Opens a connection to a MongoDB ReplicaSet.

", - "body": "

See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , ports = this.port\n , self = this\n\n this.host.forEach(function (host, i) {\n servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));\n });\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpenSet", - "string": "NativeConnection.prototype.doOpenSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Closes the connection

", - "summary": "

Closes the connection

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doClose", - "string": "NativeConnection.prototype.doClose()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeConnection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeConnection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/objectid.js -[ - { - "tags": [ - { - "type": "constructor", - "string": "NodeMongoDbObjectId" - }, - { - "type": "see", - "local": "ObjectId", - "visibility": "ObjectId" - } - ], - "description": { - "full": "

node-mongodb-native ObjectId

", - "summary": "

node-mongodb-native ObjectId

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require('mongodb').BSONPure.ObjectID", - "string": "ObjectId" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", - "ctx": { - "type": "declaration", - "name": "ObjectIdToString", - "value": "ObjectId.toString.bind(ObjectId)", - "string": "ObjectIdToString" - } - } -] -### lib/error.js -[ - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" - } - ], - "description": { - "full": "

Mongoose error

", - "summary": "

Mongoose error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", - "ctx": { - "type": "function", - "name": "MongooseError", - "string": "MongooseError()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from Error.

", - "summary": "

Inherits from Error.

", - "body": "" - }, - "ignore": true, - "code": "MongooseError.prototype.__proto__ = Error.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseError", - "name": "__proto__", - "value": "Error.prototype", - "string": "MongooseError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseError", - "string": "module.exports" - } - } -] -### lib/errors/cast.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casting Error constructor.

", - "summary": "

Casting Error constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", - "ctx": { - "type": "function", - "name": "CastError", - "string": "CastError()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseError.

", - "summary": "

Inherits from MongooseError.

", - "body": "" - }, - "ignore": true, - "code": "CastError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "CastError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "CastError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

exports

", - "summary": "

exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = CastError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "CastError", - "string": "module.exports" - } - } -] -### lib/errors/document.js -[ - { - "tags": [], - "description": { - "full": "

Module requirements

", - "summary": "

Module requirements

", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Document Error

", - "summary": "

Document Error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", - "ctx": { - "type": "function", - "name": "DocumentError", - "string": "DocumentError()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseError.

", - "summary": "

Inherits from MongooseError.

", - "body": "" - }, - "ignore": true, - "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "DocumentError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = DocumentError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = DocumentError", - "string": "module.exports" - } - } -] -### lib/errors/validation.js -[ - { - "tags": [], - "description": { - "full": "

Module requirements

", - "summary": "

Module requirements

", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "instance", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

Document Validation Error

", - "summary": "

Document Validation Error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", - "ctx": { - "type": "function", - "name": "ValidationError", - "string": "ValidationError()" - } - }, - { - "tags": [], - "description": { - "full": "

Console.log helper

", - "summary": "

Console.log helper

", - "body": "" - }, - "ignore": false, - "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", - "ctx": { - "type": "method", - "constructor": "ValidationError", - "name": "toString", - "string": "ValidationError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseError.

", - "summary": "

Inherits from MongooseError.

", - "body": "" - }, - "ignore": true, - "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidationError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidationError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports

", - "summary": "

Module exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = ValidationError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = ValidationError", - "string": "module.exports" - } - } -] -### lib/errors/validator.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Schema validator error

", - "summary": "

Schema validator error

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", - "ctx": { - "type": "function", - "name": "ValidatorError", - "string": "ValidatorError()" - } - }, - { - "tags": [], - "description": { - "full": "

toString helper

", - "summary": "

toString helper

", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", - "ctx": { - "type": "method", - "constructor": "ValidatorError", - "name": "toString", - "string": "ValidatorError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseError

", - "summary": "

Inherits from MongooseError

", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidatorError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidatorError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

exports

", - "summary": "

exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ValidatorError", - "string": "module.exports" - } - } -] -### lib/index.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Mongoose constructor.

\n\n

The exports object of the mongoose module is an instance of this class.
Most apps will only use this one instance.

", - "summary": "

Mongoose constructor.

", - "body": "

The exports object of the mongoose module is an instance of this class.
Most apps will only use this one instance.

" - }, - "isPrivate": false, - "ignore": false, - "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", - "ctx": { - "type": "function", - "name": "Mongoose", - "string": "Mongoose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets mongoose options

\n\n

Example:

\n\n
mongoose.set('test', value) // sets the 'test' option to `value`\n
", - "summary": "

Sets mongoose options

", - "body": "

Example:

\n\n
mongoose.set('test', value) // sets the 'test' option to `value`\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "set", - "string": "Mongoose.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "method", - "string": "get" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Gets mongoose options

\n\n

Example:

\n\n
mongoose.get('test') // returns the 'test' value\n
", - "summary": "

Gets mongoose options

", - "body": "

Example:

\n\n
mongoose.get('test') // returns the 'test' value\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.get = Mongoose.prototype.set;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "get", - "value": "Mongoose.prototype.set", - "string": "Mongoose.prototypeget" - } - }, - { - "tags": [], - "description": { - "full": "

ReplSet connection string check.

", - "summary": "

ReplSet connection string check.

", - "body": "" - }, - "ignore": true, - "code": "var rgxReplSet = /^.+,.+$/;", - "ctx": { - "type": "declaration", - "name": "rgxReplSet", - "value": "/^.+,.+$/", - "string": "rgxReplSet" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[uri]", - "description": "a mongodb:// URI" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "the created Connection object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Creates a Connection instance.

\n\n

Example:

\n\n
// with mongodb:// URI\ndb = mongoose.createConnection('mongodb://localhost:port/database');\n\n// replica sets\ndb = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port);\n
", - "summary": "

Creates a Connection instance.

", - "body": "

Example:

\n\n
// with mongodb:// URI\ndb = mongoose.createConnection('mongodb://localhost:port/database');\n\n// replica sets\ndb = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "createConnection", - "string": "Mongoose.prototype.createConnection()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Mongoose#createConnection", - "visibility": "Mongoose#createConnection" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - } - ], - "description": { - "full": "

Opens the default mongoose connection.

\n\n

If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

", - "summary": "

Opens the default mongoose connection.

", - "body": "

If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "connect", - "string": "Mongoose.prototype.connect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "called after all connection close." - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Disconnects all connections.

", - "summary": "

Disconnects all connections.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "disconnect", - "string": "Mongoose.prototype.disconnect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name (optional, induced from model name)" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipInit]", - "description": "whether to skip initialization (defaults to false)" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a model or retrieves it.

\n\n

Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
\n\n

When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

\n\n

Example:

\n\n
var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
", - "summary": "

Defines a model or retrieves it.

", - "body": "

Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
\n\n

When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

\n\n

Example:

\n\n
var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n // normalize collection\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // look up models for the collection\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n this.modelSchemas[name] = schema;\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n } else {\n throw new Error('Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)');\n }\n }\n\n if (!this.models[name]) {\n schema || (schema = this.modelSchemas[name]);\n collection || (collection = schema.set('collection') || format(name));\n\n var model = Model.compile(name\n , this.modelSchemas[name]\n , collection\n , this.connection\n , this);\n\n if (!skipInit) model.init();\n\n this.models[name] = model;\n }\n\n return this.models[name];\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "model", - "string": "Mongoose.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "plugin callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "optional options" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares a global plugin executed on all Schemas.

\n\n

Equivalent to calling .plugin(fn) on each Schema you create.

", - "summary": "

Declares a global plugin executed on all Schemas.

", - "body": "

Equivalent to calling .plugin(fn) on each Schema you create.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "plugin", - "string": "Mongoose.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "connection" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The default connection of the mongoose module.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
\n\n

This is the connection used by default for every model created using mongoose.model.

", - "summary": "

The default connection of the mongoose module.

", - "body": "

Example:

\n\n
var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
\n\n

This is the connection used by default for every model created using mongoose.model.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" - }, - { - "tags": [], - "description": { - "full": "

Driver depentend APIs

", - "summary": "

Driver depentend APIs

", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

Connection

", - "summary": "

Connection

", - "body": "" - }, - "ignore": true, - "code": "var Connection = require(driver + '/connection');", - "ctx": { - "type": "declaration", - "name": "Connection", - "value": "require(driver + '/connection')", - "string": "Connection" - } - }, - { - "tags": [], - "description": { - "full": "

Collection

", - "summary": "

Collection

", - "body": "" - }, - "ignore": true, - "code": "var Collection = require(driver + '/collection');", - "ctx": { - "type": "declaration", - "name": "Collection", - "value": "require(driver + '/collection')", - "string": "Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The exports object is an instance of Mongoose.

", - "summary": "

The exports object is an instance of Mongoose.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = new Mongoose", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Collection constructor

", - "summary": "

The Mongoose Collection constructor

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Collection = Collection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Collection", - "value": "Collection", - "string": "mongoose.Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Connection constructor

", - "summary": "

The Mongoose Connection constructor

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Connection = Connection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Connection", - "value": "Connection", - "string": "mongoose.Connection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Mongoose version

", - "summary": "

Mongoose version

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "version", - "value": "JSON.parse(", - "string": "mongoose.version" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose constructor

\n\n

The exports of the mongoose module is an instance of this class.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
", - "summary": "

The Mongoose constructor

", - "body": "

The exports of the mongoose module is an instance of this class.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Mongoose = Mongoose;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Mongoose", - "value": "Mongoose", - "string": "mongoose.Mongoose" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Schema constructor

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
", - "summary": "

The Mongoose Schema constructor

", - "body": "

Example:

\n\n
var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Schema = Schema;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Schema", - "value": "Schema", - "string": "mongoose.Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose SchemaType constructor.

", - "summary": "

The Mongoose SchemaType constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaType = SchemaType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaType", - "value": "SchemaType", - "string": "mongoose.SchemaType" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Schema.SchemaTypes #schema_Schema-Types", - "visibility": "Schema.SchemaTypes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The various Mongoose SchemaTypes.

\n\n

Note:

\n\n

Alias of mongoose.Schema.Types for backwards compatibility.

", - "summary": "

The various Mongoose SchemaTypes.

", - "body": "

Note:

\n\n

Alias of mongoose.Schema.Types for backwards compatibility.

" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaTypes = Schema.Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaTypes", - "value": "Schema.Types", - "string": "mongoose.SchemaTypes" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose VirtualType constructor.

", - "summary": "

The Mongoose VirtualType constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.VirtualType = VirtualType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "VirtualType", - "value": "VirtualType", - "string": "mongoose.VirtualType" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The various Mongoose Types.

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
\n\n

Types:

\n\n
    \n
  • Array
  • \n
  • Buffer
  • \n
  • Document
  • \n
  • Embedded
  • \n
  • DocumentArray
  • \n
  • ObjectId
  • \n
\n\n

Using this exposed access to the ObjectId type, we can construct ids on demand.

\n\n
var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
", - "summary": "

The various Mongoose Types.

", - "body": "

Example:

\n\n
var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
\n\n

Types:

\n\n
    \n
  • Array
  • \n
  • Buffer
  • \n
  • Document
  • \n
  • Embedded
  • \n
  • DocumentArray
  • \n
  • ObjectId
  • \n
\n\n

Using this exposed access to the ObjectId type, we can construct ids on demand.

\n\n
var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Types = Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Types", - "value": "Types", - "string": "mongoose.Types" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Query constructor.

", - "summary": "

The Mongoose Query constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Query = Query;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Query", - "value": "Query", - "string": "mongoose.Query" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Promise constructor.

", - "summary": "

The Mongoose Promise constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Promise = Promise;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Promise", - "value": "Promise", - "string": "mongoose.Promise" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Model constructor.

", - "summary": "

The Mongoose Model constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Model = Model;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Model", - "value": "Model", - "string": "mongoose.Model" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The Mongoose Document constructor.

", - "summary": "

The Mongoose Document constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Document = Document;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Document", - "value": "Document", - "string": "mongoose.Document" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The MongooseError constructor.

", - "summary": "

The MongooseError constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Error = require('./error');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Error", - "value": "require('./error')", - "string": "mongoose.Error" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The node-mongodb-native driver Mongoose uses.

", - "summary": "

The node-mongodb-native driver Mongoose uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.mongo = require('mongodb');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "mongo", - "value": "require('mongodb')", - "string": "mongoose.mongo" - } - } -] -### lib/model.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('./document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "values to with which to create the document" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "event", - "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." - }, - { - "type": "event", - "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Model constructor

", - "summary": "

Model constructor

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", - "ctx": { - "type": "function", - "name": "Model", - "string": "Model()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from Document.

", - "summary": "

Inherits from Document.

", - "body": "" - }, - "ignore": true, - "code": "Model.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "Model", - "name": "__proto__", - "value": "Document.prototype", - "string": "Model.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

Connection the model uses.

", - "summary": "

Connection the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.db;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "collection" - } - ], - "description": { - "full": "

Collection the model uses.

", - "summary": "

Collection the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.collection;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "modelName" - } - ], - "description": { - "full": "

The name of the model

", - "summary": "

The name of the model

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.modelName;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "object" - }, - { - "type": "return", - "types": [ - "Object", - "undefined" - ], - "description": "population paths" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns what paths can be populated

", - "summary": "

Returns what paths can be populated

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_getPopulationKeys", - "string": "Model.prototype._getPopulationKeys()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "schema", - "description": "type for the oid" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "oid", - "description": "object id or array of object ids" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "query", - "description": "object specifying query conditions, fields, and options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Populates an object

", - "summary": "

Populates an object

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_populate", - "string": "Model.prototype._populate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "query that originated the initialization" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Performs auto-population of relations.

", - "summary": "

Performs auto-population of relations.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "init", - "string": "Model.prototype.init()" - } - }, - { - "tags": [], - "description": { - "full": "

Handles doc.save() callbacks

", - "summary": "

Handles doc.save() callbacks

", - "body": "" - }, - "ignore": true, - "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new Error('No matching document found.'));\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", - "ctx": { - "type": "function", - "name": "handleSave", - "string": "handleSave()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "title": "middleware", - "url": "http://mongoosejs.com/docs/middleware.html", - "visibility": "http://mongoosejs.com/docs/middleware.html" - } - ], - "description": { - "full": "

Saves this document.

\n\n

Example:

\n\n
product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
\n\n

The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

\n\n
var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
\n\n

However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

\n\n
Product.on('error', handleError);\n
", - "summary": "

Saves this document.

", - "body": "

Example:

\n\n
product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
\n\n

The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

\n\n
var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
\n\n

However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

\n\n
Product.on('error', handleError);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n complete(null);\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "save", - "string": "Model.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Mixed" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[operation]", - "description": "" - } - ], - "description": { - "full": "

Apply the operation to the delta (update) clause as
well as track versioning for our where clause.

", - "summary": "

Apply the operation to the delta (update) clause as
well as track versioning for our where clause.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", - "ctx": { - "type": "function", - "name": "operand", - "string": "operand()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "val", - "description": "" - } - ], - "description": { - "full": "

Compiles an update and where clause for a val with _atomics.

", - "summary": "

Compiles an update and where clause for a val with _atomics.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", - "ctx": { - "type": "function", - "name": "handleAtomics", - "string": "handleAtomics()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Produces a special query document of the modified properties used in updates.

", - "summary": "

Produces a special query document of the modified properties used in updates.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_delta", - "string": "Model.prototype._delta()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Appends versioning to the where and update clauses.

", - "summary": "

Appends versioning to the where and update clauses.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_version", - "string": "Model.prototype._version()" - } - }, - { - "tags": [ - { - "type": "see", - "title": "versionKeys", - "url": "http://mongoosejs.com/docs/guide.html#versionKey", - "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Signal that we desire an increment of this documents version.

", - "summary": "

Signal that we desire an increment of this documents version.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "increment", - "string": "Model.prototype.increment()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns a query object which applies shardkeys if they exist.

", - "summary": "

Returns a query object which applies shardkeys if they exist.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_where", - "string": "Model.prototype._where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Removes this document from the db.

\n\n

Example:

\n\n
product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
", - "summary": "

Removes this document from the db.

", - "body": "

Example:

\n\n
product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) return this;\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "remove", - "string": "Model.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Register hooks override

", - "summary": "

Register hooks override

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_registerHooks", - "string": "Model.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns another Model instance.

\n\n

Example:

\n\n
var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
", - "summary": "

Returns another Model instance.

", - "body": "

Example:

\n\n
var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "model", - "string": "Model.prototype.model()" - } - }, - { - "tags": [ - { - "type": "TODO", - "string": "determine if this is still necessary" - } - ], - "description": { - "full": "

Give the constructor the ability to emit events.

", - "summary": "

Give the constructor the ability to emit events.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Called when the model compiles.

", - "summary": "

Called when the model compiles.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.init = function init () {\n if (this.schema.options.autoIndex)\n this.ensureIndexes();\n\n this.schema.emit('init', this);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "init", - "string": "Model.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[cb]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sends ensureIndex commands to mongo for each index declared in the schema.

\n\n

After completion, an index event is emitted on this Model passing an error if one occurred.

", - "summary": "

Sends ensureIndex commands to mongo for each index declared in the schema.

", - "body": "

After completion, an index event is emitted on this Model passing an error if one occurred.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "ensureIndexes", - "string": "Model.ensureIndexes()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "schema" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Schema the model uses.

", - "summary": "

Schema the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.schema;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Database instance the model uses.

", - "summary": "

Database instance the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.db;" - }, - { - "tags": [ - { - "type": "property", - "string": "collection" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Collection the model uses.

", - "summary": "

Collection the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.collection;" - }, - { - "tags": [ - { - "type": "property", - "string": "base" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Base Mongoose instance the model uses.

", - "summary": "

Base Mongoose instance the model uses.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.base;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Removes documents from the collection.

\n\n

Note:

\n\n

To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.remove({ _id: id }).exec();\n
", - "summary": "

Removes documents from the collection.

", - "body": "

Note:

\n\n

To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.remove({ _id: id }).exec();\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "remove", - "string": "Model.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Finds documents

\n\n

Examples:

\n\n
// retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
", - "summary": "

Finds documents

", - "body": "

Examples:

\n\n
// retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "find", - "string": "Model.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Merges the current named scope query into query.

", - "summary": "

Merges the current named scope query into query.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "_applyNamedScope", - "string": "Model._applyNamedScope()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "objectid, or a value that can be casted to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Finds a single document by id.

\n\n

The id is cast to an ObjectId before sending the command.

\n\n

Example:

\n\n
Adventure.findById(id, callback);\n
", - "summary": "

Finds a single document by id.

", - "body": "

The id is cast to an ObjectId before sending the command.

\n\n

Example:

\n\n
Adventure.findById(id, callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findById", - "string": "Model.findById()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Finds one document.

\n\n

The conditions are cast to their respective SchemaTypes before the command is sent.

\n\n

Example:

\n\n
Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
", - "summary": "

Finds one document.

", - "body": "

The conditions are cast to their respective SchemaTypes before the command is sent.

\n\n

Example:

\n\n
Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n // TODO Handle all 3 of the following scenarios\n // Hint: Only some of these scenarios are possible if cQuery is present\n // Scenario: findOne(conditions, fields, callback);\n // Scenario: findOne(fields, options, callback);\n // Scenario: findOne(conditions, options, callback);\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n // TODO Handle all 2 of the following scenarios\n // Scenario: findOne(conditions, callback)\n // Scenario: findOne(fields, callback)\n // Scenario: findOne(options, callback);\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOne", - "string": "Model.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Counts number of matching documents in a database collection.

\n\n

Example:

\n\n
Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
", - "summary": "

Counts number of matching documents in a database collection.

", - "body": "

Example:

\n\n
Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "count", - "string": "Model.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes a DISTINCT command

", - "summary": "

Executes a DISTINCT command

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "distinct", - "string": "Model.distinct()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "optional value" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Creates a Query, applies the passed conditions, and returns the Query.

\n\n

For example, instead of writing:

\n\n
User.find({age: {$gte: 21, $lte: 65}}, callback);\n
\n\n

we can instead write:

\n\n
User.where('age').gte(21).lte(65).exec(callback);\n
\n\n

Since the Query class also supports where you can continue chaining

\n\n
User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
", - "summary": "

Creates a Query, applies the passed conditions, and returns the Query.

", - "body": "

For example, instead of writing:

\n\n
User.find({age: {$gte: 21, $lte: 65}}, callback);\n
\n\n

we can instead write:

\n\n
User.where('age').gte(21).lte(65).exec(callback);\n
\n\n

Since the Query class also supports where you can continue chaining

\n\n
User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "where", - "string": "Model.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "argument", - "description": "is a javascript string or anonymous function" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "memberOf", - "parent": "Model" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Query.$where #query_Query-%24where", - "visibility": "Query.$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Creates a Query and specifies a $where condition.

\n\n

Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

\n\n
Blog.$where('this.comments.length > 5');\n
", - "summary": "

Creates a Query and specifies a $where condition.

", - "body": "

Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

\n\n
Blog.$where('this.comments.length > 5');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", - "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndUpdate", - "string": "Model.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "an ObjectId or string that can be cast to one." - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", - "visibility": "Model.findOneAndUpdate" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issues a mongodb findAndModify update command by a documents id.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", - "summary": "

Issues a mongodb findAndModify update command by a documents id.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Note:

\n\n

All top level update keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

\n\n

Note:

\n\n

Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndUpdate", - "string": "Model.findByIdAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issue a mongodb findAndModify remove command.

\n\n

Finds a matching document, removes it, passing the found document (if any) to the callback.

\n\n

Executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
", - "summary": "

Issue a mongodb findAndModify remove command.

", - "body": "

Finds a matching document, removes it, passing the found document (if any) to the callback.

\n\n

Executes immediately if callback is passed else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndRemove", - "string": "Model.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "id", - "description": "ObjectId or string that can be cast to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", - "visibility": "Model.findOneAndRemove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - } - ], - "description": { - "full": "

Issue a mongodb findAndModify remove command by a documents id.

\n\n

Finds a matching document, removes it, passing the found document (if any) to the callback.

\n\n

Executes immediately if callback is passed, else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
", - "summary": "

Issue a mongodb findAndModify remove command by a documents id.

", - "body": "

Finds a matching document, removes it, passing the found document (if any) to the callback.

\n\n

Executes immediately if callback is passed, else a Query object is returned.

\n\n

Options:

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
  • select: sets the document fields to return
  • \n
\n\n

Examples:

\n\n
A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndRemove", - "string": "Model.findByIdAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array", - "Object..." - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Shortcut for creating a new Document that is automatically saved to the db if valid.

\n\n

Example:

\n\n
Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
", - "summary": "

Shortcut for creating a new Document that is automatically saved to the db if valid.

", - "body": "

Example:

\n\n
Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "create", - "string": "Model.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "update", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Updates documents in the database without returning them.

\n\n

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
", - "summary": "

Updates documents in the database without returning them.

", - "body": "

Examples:

\n\n
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
\n\n

Valid options:

\n\n
    \n
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • \n
  • upsert (boolean) whether to create the doc if it doesn't match (false)
  • \n
  • multi (boolean) whether multiple documents should be updated (false)
  • \n
\n\n

All update values are cast to their appropriate SchemaTypes before being sent.

\n\n

The callback function receives (err, numberAffected, rawResponse).

\n\n
    \n
  • err is the error if any occurred
  • \n
  • numberAffected is the count of updated documents Mongo reported
  • \n
  • rawResponse is the full response from Mongo
  • \n
\n\n

Note:

\n\n

All top level keys which are not atomic operation names are treated as set operations:

\n\n

Example:

\n\n
var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
\n\n

This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

\n\n

Note:

\n\n

To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

\n\n
Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
\n\n

Note:

\n\n

Although values are casted to their appropriate types when using update, the following are not applied:

\n\n
    \n
  • defaults
  • \n
  • setters
  • \n
  • validators
  • \n
  • middleware
  • \n
\n\n

If you need those features, use the traditional approach of first retrieving the document.

\n\n
Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "update", - "string": "Model.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "o", - "description": "an object specifying map-reduce options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/MapReduce", - "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes a mapReduce command.

\n\n

o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

\n\n

Example:

\n\n
var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
\n\n

Other options:

\n\n
    \n
  • query {Object} query filter object.
  • \n
  • limit {Number} max number of documents
  • \n
  • keeptemp {Boolean, default:false} keep temporary data
  • \n
  • finalize {Function} finalize function
  • \n
  • scope {Object} scope variables exposed to map/reduce/finalize during execution
  • \n
  • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
  • \n
  • verbose {Boolean, default:false} provide statistics on job execution time.
  • \n
  • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
  • \n
\n\n

* out options:

\n\n
    \n
  • {inline:1} the results are returned in an array
  • \n
  • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
  • \n
  • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
  • \n
  • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
  • \n
\n\n

If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

\n\n

Example:

\n\n
var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
", - "summary": "

Executes a mapReduce command.

", - "body": "

o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

\n\n

Example:

\n\n
var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
\n\n

Other options:

\n\n
    \n
  • query {Object} query filter object.
  • \n
  • limit {Number} max number of documents
  • \n
  • keeptemp {Boolean, default:false} keep temporary data
  • \n
  • finalize {Function} finalize function
  • \n
  • scope {Object} scope variables exposed to map/reduce/finalize during execution
  • \n
  • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
  • \n
  • verbose {Boolean, default:false} provide statistics on job execution time.
  • \n
  • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
  • \n
\n\n

* out options:

\n\n
    \n
  • {inline:1} the results are returned in an array
  • \n
  • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
  • \n
  • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
  • \n
  • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
  • \n
\n\n

If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

\n\n

Example:

\n\n
var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "mapReduce", - "string": "Model.mapReduce()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "an array of pipeline commands" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "aggregation", - "url": "http://docs.mongodb.org/manual/applications/aggregation/", - "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", - "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes an aggregate command on this models collection.

\n\n

Example:

\n\n
// find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
\n\n

NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

\n\n

NOTE: this requires running MongoDB >= 2.1

", - "summary": "

Executes an aggregate command on this models collection.

", - "body": "

Example:

\n\n
// find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
\n\n

NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

\n\n

NOTE: this requires running MongoDB >= 2.1

" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "aggregate", - "string": "Model.aggregate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "collectionName", - "description": "" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "connection", - "description": "" - }, - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "mongoose instance" - } - ], - "description": { - "full": "

Compiler utility.

", - "summary": "

Compiler utility.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "compile", - "string": "Model.compile()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Model;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Model", - "string": "module.exports" - } - } -] -### lib/namedscope.js -[ - { - "tags": [ - { - "type": "param", - "types": [ - "NamedScope" - ], - "name": "target", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "getters", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Decorate

", - "summary": "

Decorate

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", - "ctx": { - "type": "method", - "constructor": "NamedScope", - "name": "decorate", - "string": "NamedScope.prototype.decorate()" - } - } -] -### lib/promise.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", - "ctx": { - "type": "declaration", - "name": "util", - "value": "require('./utils')", - "string": "util" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "back", - "description": "a callback+errback that accepts `fn(err, ...){}` as signature" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`err`: Emits when the promise resolves to an error." - }, - { - "type": "event", - "string": "`complete`: Emits when the promise resolves sucessfully." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Promise constructor.

", - "summary": "

Promise constructor.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", - "ctx": { - "type": "function", - "name": "Promise", - "string": "Promise()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from EventEmitter.

", - "summary": "

Inherits from EventEmitter.

", - "body": "" - }, - "ignore": true, - "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Promise", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Promise.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Event" - ], - "name": "event", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds listener to the event.

\n\n

If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

", - "summary": "

Adds listener to the event.

", - "body": "

If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "on", - "string": "Promise.prototype.on()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Keeps track of emitted events to run them on on.

", - "summary": "

Keeps track of emitted events to run them on on.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "emit", - "string": "Promise.prototype.emit()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Shortcut for emitting the complete event.

", - "summary": "

Shortcut for emitting the complete event.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "complete", - "string": "Promise.prototype.complete()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

Shortcut for emitting the err event.

", - "summary": "

Shortcut for emitting the err event.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "error", - "string": "Promise.prototype.error()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Shortcut for .on('complete', fn).

", - "summary": "

Shortcut for .on('complete', fn).

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addCallback", - "string": "Promise.prototype.addCallback()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Shortcut for .on('err', fn).

", - "summary": "

Shortcut for .on('err', fn).

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addErrback", - "string": "Promise.prototype.addErrback()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

Adds a single function that's both a callback and errback.

", - "summary": "

Adds a single function that's both a callback and errback.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addBack", - "string": "Promise.prototype.addBack()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "optional error or null" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "value to complete the promise with" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sugar for handling cases where you may be resolving to either an error condition or a success condition.

", - "summary": "

Sugar for handling cases where you may be resolving to either an error condition or a success condition.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "resolve", - "string": "Promise.prototype.resolve()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = Promise;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Promise", - "string": "module.exports" - } - } -] -### lib/query.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "criteria", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Query constructor used for building queries.

\n\n

Example:

\n\n
var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
", - "summary": "

Query constructor used for building queries.

", - "body": "

Example:

\n\n
var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n if (criteria) this.find(criteria);\n}", - "ctx": { - "type": "function", - "name": "Query", - "string": "Query()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets query options.

\n\n

Options:

\n\n\n\n

* denotes a query helper method is also available

", - "summary": "

Sets query options.

", - "body": "

Options:

\n\n\n\n

* denotes a query helper method is also available

" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "setOptions", - "string": "Query.prototype.setOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "the model to which the query is bound" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "the operation to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "updateArg", - "description": "used in update methods" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Binds this query to a model.

", - "summary": "

Binds this query to a model.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "bind", - "string": "Query.prototype.bind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "[operation]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes the query

\n\n

Examples

\n\n
query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
", - "summary": "

Executes the query

", - "body": "

Examples

\n\n
query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exec", - "string": "Query.prototype.exec()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[criteria]", - "description": "mongodb selector" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Finds documents.

\n\n

When no callback is passed, the query is not executed.

\n\n

Example

\n\n
query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
", - "summary": "

Finds documents.

", - "body": "

When no callback is passed, the query is not executed.

\n\n

Example

\n\n
query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "find", - "string": "Query.prototype.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[obj]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Casts this query to the schema of model

\n\n

Note

\n\n

If obj is present, it is cast instead of this query.

", - "summary": "

Casts this query to the schema of model

", - "body": "

Note

\n\n

If obj is present, it is cast instead of this query.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "cast", - "string": "Query.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns default options.

", - "summary": "

Returns default options.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('batchSize' in options))\n options.batchSize = 1000;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_optionsForExec", - "string": "Query.prototype._optionsForExec()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Applies schematype selected options to this query.

", - "summary": "

Applies schematype selected options to this query.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_applyPaths", - "string": "Query.prototype._applyPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "js", - "description": "javascript string or function" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $where condition

\n\n

Use $where when you need to select documents using a JavaScript expression.

\n\n

Example

\n\n
query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
", - "summary": "

Specifies a $where condition

", - "body": "

Use $where when you need to select documents using a JavaScript expression.

\n\n

Example

\n\n
query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a path for use with chaining.

\n\n

Example

\n\n
// instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
", - "summary": "

Specifies a path for use with chaining.

", - "body": "

Example

\n\n
// instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "where", - "string": "Query.prototype.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the complementary comparison value for paths specified with where()

\n\n

Example

\n\n
User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
", - "summary": "

Specifies the complementary comparison value for paths specified with where()

", - "body": "

Example

\n\n
User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "equals", - "string": "Query.prototype.equals()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies arguments for an $or condition.

\n\n

Example

\n\n
query.or([{ color: 'red' }, { status: 'emergency' }])\n
", - "summary": "

Specifies arguments for an $or condition.

", - "body": "

Example

\n\n
query.or([{ color: 'red' }, { status: 'emergency' }])\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "or", - "string": "Query.prototype.or()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies arguments for a $nor condition.

\n\n

Example

\n\n
query.nor([{ color: 'green' }, { status: 'ok' }])\n
", - "summary": "

Specifies arguments for a $nor condition.

", - "body": "

Example

\n\n
query.nor([{ color: 'green' }, { status: 'ok' }])\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nor", - "string": "Query.prototype.nor()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "gt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $gt query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

\n\n

Example

\n\n
Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
", - "summary": "

Specifies a $gt query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

\n\n

Example

\n\n
Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "gte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $gte query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $gte query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $lt query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $lt query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $lte query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $lte query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "ne" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $ne query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $ne query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "in" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $in query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies an $in query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "nin" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $nin query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies an $nin query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "all" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $all query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies an $all query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "size" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $size query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies an $size query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "regex" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $regex query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $regex query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxDistance" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $maxDistance query condition.

\n\n

When called with one argument, the most recent path passed to where() is used.

", - "summary": "

Specifies a $maxDistance query condition.

", - "body": "

When called with one argument, the most recent path passed to where() is used.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

\n\n
Thing.where('type').nin(array)\n
", - "summary": "

gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

", - "body": "
Thing.where('type').nin(array)\n
" - }, - "ignore": true, - "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $near condition

", - "summary": "

Specifies a $near condition

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "near", - "string": "Query.prototype.near()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $nearSphere condition.

", - "summary": "

Specifies a $nearSphere condition.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nearSphere", - "string": "Query.prototype.nearSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $mod condition

", - "summary": "

Specifies a $mod condition

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "mod", - "string": "Query.prototype.mod()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $exists condition

", - "summary": "

Specifies an $exists condition

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exists", - "string": "Query.prototype.exists()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object", - "Function" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "Function" - ], - "name": "criteria", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies an $elemMatch condition

\n\n

Example

\n\n
query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
", - "summary": "

Specifies an $elemMatch condition

", - "body": "

Example

\n\n
query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "elemMatch", - "string": "Query.prototype.elemMatch()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "within" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Syntax sugar for expressive queries.

\n\n

Example

\n\n
query.within.box()\nquery.within.center()\n
", - "summary": "

Syntax sugar for expressive queries.

", - "body": "

Example

\n\n
query.within.box()\nquery.within.center()\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "see", - "local": "Query#within #query_Query-within", - "visibility": "Query#within" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $box condition

\n\n

Example

\n\n
var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
", - "summary": "

Specifies a $box condition

", - "body": "

Example

\n\n
var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "box", - "string": "Query.prototype.box()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "options e.g. { $uniqueDocs: true }" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $center condition

\n\n

Example

\n\n
var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
", - "summary": "

Specifies a $center condition

", - "body": "

Example

\n\n
var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "center", - "string": "Query.prototype.center()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $centerSphere condition

\n\n

Example

\n\n
var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
", - "summary": "

Specifies a $centerSphere condition

", - "body": "

Example

\n\n
var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "centerSphere", - "string": "Query.prototype.centerSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Array", - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $polygon condition

\n\n

Example

\n\n
var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
", - "summary": "

Specifies a $polygon condition

", - "body": "

Example

\n\n
var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "polygon", - "string": "Query.prototype.polygon()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "local": "SchemaType", - "visibility": "SchemaType" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies which document fields to include or exclude

\n\n

When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

\n\n

Example

\n\n
// include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
\n\n

NOTE:

\n\n

v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

", - "summary": "

Specifies which document fields to include or exclude

", - "body": "

When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

\n\n

Example

\n\n
// include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
\n\n

NOTE:

\n\n

v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "select", - "string": "Query.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "number of elements to slice" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", - "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies a $slice condition

\n\n

Example

\n\n
query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
", - "summary": "

Specifies a $slice condition

", - "body": "

Example

\n\n
query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slice", - "string": "Query.prototype.slice()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets the sort order

\n\n

If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

\n\n

If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

\n\n

Example

\n\n
// these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
", - "summary": "

Sets the sort order

", - "body": "

If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

\n\n

If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

\n\n

Example

\n\n
// these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "sort", - "string": "Query.prototype.sort()" - } - }, - { - "tags": [], - "description": { - "full": "

@ignore

", - "summary": "

@ignore

", - "body": "" - }, - "ignore": true, - "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", - "ctx": { - "type": "function", - "name": "push", - "string": "push()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "limit" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the limit option.

\n\n

Example

\n\n
Kitten.find().limit(20)\n
", - "summary": "

Specifies the limit option.

", - "body": "

Example

\n\n
Kitten.find().limit(20)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "skip" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the skip option.

\n\n

Example

\n\n
Kitten.find().skip(100).limit(20)\n
", - "summary": "

Specifies the skip option.

", - "body": "

Example

\n\n
Kitten.find().skip(100).limit(20)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxscan" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the maxscan option.

\n\n

Example

\n\n
Kitten.find().maxscan(100)\n
", - "summary": "

Specifies the maxscan option.

", - "body": "

Example

\n\n
Kitten.find().maxscan(100)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "batchSize" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the batchSize option.

\n\n

Example

\n\n
Kitten.find().batchSize(100)\n
", - "summary": "

Specifies the batchSize option.

", - "body": "

Example

\n\n
Kitten.find().batchSize(100)\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "comment" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies the comment option.

\n\n

Example

\n\n
Kitten.findOne(condition).comment('login query')\n
", - "summary": "

Specifies the comment option.

", - "body": "

Example

\n\n
Kitten.findOne(condition).comment('login query')\n
" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

limit, skip, maxscan, batchSize, comment

\n\n

Sets these associated options.

\n\n
query.comment('feed query');\n
", - "summary": "

limit, skip, maxscan, batchSize, comment

", - "body": "

Sets these associated options.

\n\n
query.comment('feed query');\n
" - }, - "ignore": true, - "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies this query as a snapshot query.

\n\n

Example

\n\n
Kitten.find().snapshot()\n
", - "summary": "

Specifies this query as a snapshot query.

", - "body": "

Example

\n\n
Kitten.find().snapshot()\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "snapshot", - "string": "Query.prototype.snapshot()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "a hint object" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets query hints.

\n\n

Example

\n\n
Model.find().hint({ indexA: 1, indexB: -1})\n
", - "summary": "

Sets query hints.

", - "body": "

Example

\n\n
Model.find().hint({ indexA: 1, indexB: -1})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "hint", - "string": "Query.prototype.hint()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets the slaveOk option.

\n\n

Example:

\n\n
new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
", - "summary": "

Sets the slaveOk option.

", - "body": "

Example:

\n\n
new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slaveOk", - "string": "Query.prototype.slaveOk()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "one of the listed preference options or their aliases" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "[tags]", - "description": "optional tags for this query" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", - "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets the readPreference option for the query.

\n\n

Example:

\n\n
new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
\n\n

Preferences:

\n\n
primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
\n\n

Aliases

\n\n
p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
\n\n

Read more about how to use read preferrences here and here.

", - "summary": "

Sets the readPreference option for the query.

", - "body": "

Example:

\n\n
new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
\n\n

Preferences:

\n\n
primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
\n\n

Aliases

\n\n
p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
\n\n

Read more about how to use read preferrences here and here.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "read", - "string": "Query.prototype.read()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets the lean option.

\n\n

Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

\n\n

This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

\n\n

Example:

\n\n
new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
", - "summary": "

Sets the lean option.

", - "body": "

Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

\n\n

This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

\n\n

Example:

\n\n
new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "lean", - "string": "Query.prototype.lean()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", - "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets tailable option.

\n\n

Example

\n\n
Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
", - "summary": "

Sets tailable option.

", - "body": "

Example

\n\n
Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "tailable", - "string": "Query.prototype.tailable()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Executes the query as a find() operation.

", - "summary": "

Executes the query as a find() operation.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "execFind", - "string": "Query.prototype.execFind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes the query as a findOne() operation.

\n\n

Example

\n\n
Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
", - "summary": "

Executes the query as a findOne() operation.

", - "body": "

Example

\n\n
Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOne", - "string": "Query.prototype.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Exectues the query as a count() operation.

\n\n

Example

\n\n
Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
", - "summary": "

Exectues the query as a count() operation.

", - "body": "

Example

\n\n
Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "count", - "string": "Query.prototype.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes this query as a distict() operation.

", - "summary": "

Executes this query as a distict() operation.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "distinct", - "string": "Query.prototype.distinct()" - } - }, - { - "tags": [], - "description": { - "full": "

These operators require casting docs
to real Documents for Update operations.

", - "summary": "

These operators require casting docs
to real Documents for Update operations.

", - "body": "" - }, - "ignore": true, - "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", - "ctx": { - "type": "declaration", - "name": "castOps", - "value": "{", - "string": "castOps" - } - }, - { - "tags": [], - "description": { - "full": "

These operators should be cast to numbers instead
of their path schema type.

", - "summary": "

These operators should be cast to numbers instead
of their path schema type.

", - "body": "" - }, - "ignore": true, - "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", - "ctx": { - "type": "declaration", - "name": "numberOps", - "value": "{", - "string": "numberOps" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "the update conditions" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes this query as an update() operation.

\n\n

All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

\n\n

Example

\n\n
Model.update({..}, { title: 'remove words' }, ...)\n
\n\n

becomes

\n\n
Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
\n\n

Note

\n\n

Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

", - "summary": "

Executes this query as an update() operation.

", - "body": "

All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

\n\n

Example

\n\n
Model.update({..}, { title: 'remove words' }, ...)\n
\n\n

becomes

\n\n
Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
\n\n

Note

\n\n

Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n delete options.safe;\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "update", - "string": "Query.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "obj after casting its values" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts obj for an update command.

", - "summary": "

Casts obj for an update command.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdate", - "string": "Query.prototype._castUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "- part of a query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "- path prefix (internal only)" - }, - { - "type": "return", - "types": [ - "Bool" - ], - "description": "true if this path has keys to update" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Walk each path of obj and cast its values
according to its schema.

", - "summary": "

Walk each path of obj and cast its values
according to its schema.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_walkUpdatePath", - "string": "Query.prototype._walkUpdatePath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[$conditional]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts val according to schema and atomic op.

", - "summary": "

Casts val according to schema and atomic op.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdateVal", - "string": "Query.prototype._castUpdateVal()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Finds the schema for path. This is different than
calling schema.path as it also resolves paths with
positional selectors (something.$.another.$.path).

", - "summary": "

Finds the schema for path. This is different than
calling schema.path as it also resolves paths with
positional selectors (something.$.another.$.path).

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_getSchema", - "string": "Query.prototype._getSchema()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "https://github.com/LearnBoost/mongoose/issues/1091", - "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" - }, - { - "type": "see", - "title": "", - "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", - "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts selected field arguments for field selection with mongo 2.2

\n\n
query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
", - "summary": "

Casts selected field arguments for field selection with mongo 2.2

", - "body": "
query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castFields", - "string": "Query.prototype._castFields()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Executes this query as a remove() operation.

\n\n

Example

\n\n
Cassette.where('artist').equals('Anne Murray').remove(callback)\n
", - "summary": "

Executes this query as a remove() operation.

", - "body": "

Example

\n\n
Cassette.where('artist').equals('Anne Murray').remove(callback)\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n delete options.safe;\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "remove", - "string": "Query.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[query]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[doc]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issues a mongodb findAndModify update command.

\n\n

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Available options

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Examples

\n\n
query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
", - "summary": "

Issues a mongodb findAndModify update command.

", - "body": "

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

\n\n

Available options

\n\n
    \n
  • new: bool - true to return the modified document rather than the original. defaults to true
  • \n
  • upsert: bool - creates the object if it doesn't exist. defaults to false.
  • \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Examples

\n\n
query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndUpdate", - "string": "Query.prototype.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Issues a mongodb findAndModify remove command.

\n\n

Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

\n\n

Available options

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Examples

\n\n
A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
", - "summary": "

Issues a mongodb findAndModify remove command.

", - "body": "

Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

\n\n

Available options

\n\n
    \n
  • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
  • \n
\n\n

Examples

\n\n
A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndRemove", - "string": "Query.prototype.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "- either \"remove\" or \"update\"" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

_findAndModify

", - "summary": "

_findAndModify

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_findAndModify", - "string": "Query.prototype._findAndModify()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Model" - ], - "name": "[model]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "see", - "local": "population ./populate.html", - "visibility": "population" - }, - { - "type": "see", - "local": "Query#select #query_Query-select", - "visibility": "Query#select" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Specifies paths which should be populated with other documents.

\n\n

Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

\n\n

Example:

\n\n
Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
", - "summary": "

Specifies paths which should be populated with other documents.

", - "body": "

Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

\n\n

Example:

\n\n
Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "populate", - "string": "Query.prototype.populate()" - } - }, - { - "tags": [], - "description": { - "full": "

Populate options constructor

", - "summary": "

Populate options constructor

", - "body": "" - }, - "ignore": true, - "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", - "ctx": { - "type": "function", - "name": "PopulateOptions", - "string": "PopulateOptions()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "QueryStream" - ], - "description": "" - }, - { - "type": "see", - "local": "QueryStream", - "visibility": "QueryStream" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns a stream interface

\n\n

Example

\n\n
// follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
", - "summary": "

Returns a stream interface

", - "body": "

Example

\n\n
// follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "stream", - "string": "Query.prototype.stream()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

castDoc

", - "summary": "

castDoc

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castDoc", - "string": "castDoc()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

castQuery

", - "summary": "

castQuery

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castQuery", - "string": "castQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Exports.

", - "summary": "

Exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Query", - "string": "module.exports" - } - } -] -### lib/querystream.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", - "ctx": { - "type": "declaration", - "name": "Stream", - "value": "require('stream').Stream", - "string": "Stream" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS Stream http://nodejs.org/api/stream.html" - }, - { - "type": "event", - "string": "`data`: emits a single Mongoose document" - }, - { - "type": "event", - "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." - }, - { - "type": "event", - "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Provides a ReadStream interface for Queries.

\n\n
var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
\n\n

The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

\n\n
Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
", - "summary": "

Provides a ReadStream interface for Queries.

", - "body": "
var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
\n\n

The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

\n\n
Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", - "ctx": { - "type": "function", - "name": "QueryStream", - "string": "QueryStream()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from Stream

", - "summary": "

Inherit from Stream

", - "body": "" - }, - "ignore": true, - "code": "QueryStream.prototype.__proto__ = Stream.prototype;", - "ctx": { - "type": "property", - "constructor": "QueryStream", - "name": "__proto__", - "value": "Stream.prototype", - "string": "QueryStream.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readable" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Flag stating whether or not this stream is readable.

", - "summary": "

Flag stating whether or not this stream is readable.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.readable;" - }, - { - "tags": [ - { - "type": "property", - "string": "paused" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Flag stating whether or not this stream is paused.

", - "summary": "

Flag stating whether or not this stream is paused.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Initializes the query.

", - "summary": "

Initializes the query.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_init", - "string": "QueryStream.prototype._init()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#__next #querystream_QueryStream-__next", - "visibility": "QueryStream#__next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Trampoline for pulling the next doc from cursor.

", - "summary": "

Trampoline for pulling the next doc from cursor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) return;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // account for possible nextObjects calling user code\n if (this.paused || this._destroyed) return;\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n var fn;\n while (this.__next()) {}\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_next", - "string": "QueryStream.prototype._next()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#_next #querystream_QueryStream-_next", - "visibility": "QueryStream#_next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Pulls the next doc from the cursor.

", - "summary": "

Pulls the next doc from the cursor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed) return;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "__next", - "string": "QueryStream.prototype.__next()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error", - "null" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Transforms raw docs returned from the cursor into a model instance.

", - "summary": "

Transforms raw docs returned from the cursor into a model instance.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && this.query.options.lean === true) {\n this.emit('data', doc);\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_onNextObject", - "string": "QueryStream.prototype._onNextObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Pauses this stream.

", - "summary": "

Pauses this stream.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "pause", - "string": "QueryStream.prototype.pause()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Resumes this stream.

", - "summary": "

Resumes this stream.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n this._next();\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "resume", - "string": "QueryStream.prototype.resume()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "[err]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Destroys the stream, closing the underlying cursor. No more events will be emitted.

", - "summary": "

Destroys the stream, closing the underlying cursor. No more events will be emitted.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "destroy", - "string": "QueryStream.prototype.destroy()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "pipe" - }, - { - "type": "memberOf", - "parent": "QueryStream" - }, - { - "type": "see", - "title": "NodeJS", - "url": "http://nodejs.org/api/stream.html", - "visibility": "http://nodejs.org/api/stream.html" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

\n\n

Example:

\n\n
query.stream().pipe(writeStream [, options])\n
\n\n

This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

\n\n
var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
\n\n

As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

", - "summary": "

Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

", - "body": "

Example:

\n\n
query.stream().pipe(writeStream [, options])\n
\n\n

This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

\n\n
var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
\n\n

As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

" - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

Module exports

", - "summary": "

Module exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = QueryStream", - "string": "module.exports" - } - } -] -### lib/schema/array.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Array SchemaType constructor

", - "summary": "

Array SchemaType constructor

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "SchemaArray", - "string": "SchemaArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaArray", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Check required

", - "summary": "

Check required

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "checkRequired", - "string": "SchemaArray.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Overrides the getters application for the population special-case

", - "summary": "

Overrides the getters application for the population special-case

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "applyGetters", - "string": "SchemaArray.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents

", - "summary": "

Casts contents

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "cast", - "string": "SchemaArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "castForQuery", - "string": "SchemaArray.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

@ignore

", - "summary": "

@ignore

", - "body": "" - }, - "ignore": true, - "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': castToNumber\n , '$gte': castToNumber\n , '$lt': castToNumber\n , '$lte': castToNumber\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", - "ctx": { - "type": "function", - "name": "castToNumber", - "string": "castToNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaArray", - "string": "module.exports" - } - } -] -### lib/schema/boolean.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Boolean SchemaType constructor.

", - "summary": "

Boolean SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaBoolean", - "string": "SchemaBoolean()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBoolean", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBoolean.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Required validator

", - "summary": "

Required validator

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "checkRequired", - "string": "SchemaBoolean.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to boolean

", - "summary": "

Casts to boolean

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "cast", - "string": "SchemaBoolean.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", - "ctx": { - "type": "function", - "name": "handleArray", - "string": "handleArray()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "castForQuery", - "string": "SchemaBoolean.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBoolean;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBoolean", - "string": "module.exports" - } - } -] -### lib/schema/buffer.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Buffer SchemaType constructor

", - "summary": "

Buffer SchemaType constructor

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", - "ctx": { - "type": "function", - "name": "SchemaBuffer", - "string": "SchemaBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBuffer", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBuffer.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Check required

", - "summary": "

Check required

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "checkRequired", - "string": "SchemaBuffer.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents

", - "summary": "

Casts contents

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "cast", - "string": "SchemaBuffer.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "castForQuery", - "string": "SchemaBuffer.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBuffer;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBuffer", - "string": "module.exports" - } - } -] -### lib/schema/date.js -[ - { - "tags": [], - "description": { - "full": "

Module requirements.

", - "summary": "

Module requirements.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Date SchemaType constructor.

", - "summary": "

Date SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaDate", - "string": "SchemaDate()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaDate", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaDate.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Required validator for date

", - "summary": "

Required validator for date

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "checkRequired", - "string": "SchemaDate.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to date

", - "summary": "

Casts to date

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "cast", - "string": "SchemaDate.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Date Query casting.

", - "summary": "

Date Query casting.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "castForQuery", - "string": "SchemaDate.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaDate;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaDate", - "string": "module.exports" - } - } -] -### lib/schema/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaArray" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

SubdocsArray SchemaType constructor

", - "summary": "

SubdocsArray SchemaType constructor

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "DocumentArray", - "string": "DocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from ArrayType.

", - "summary": "

Inherits from ArrayType.

", - "body": "" - }, - "ignore": true, - "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentArray", - "name": "__proto__", - "value": "ArrayType.prototype", - "string": "DocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Performs local validations first, then validations on each embedded doc

", - "summary": "

Performs local validations first, then validations on each embedded doc

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n SchemaType.prototype.doValidate.call(this, array, function(err){\n if (err) return fn(err);\n\n var count = array && array.length\n , error = false;\n\n if (!count) return fn();\n\n array.forEach(function(doc, index){\n doc.validate(function(err){\n if (err && !error){\n // rewrite they key\n err.key = self.key + '.' + index + '.' + err.key;\n fn(err);\n error = true;\n } else {\n --count || fn();\n }\n });\n });\n }, scope);\n};", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "doValidate", - "string": "DocumentArray.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "document", - "description": "that triggers the casting" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents

", - "summary": "

Casts contents

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument)) {\n if (init) {\n selected || (selected = scopePaths(this, doc._selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "cast", - "string": "DocumentArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "DocumentArray" - ], - "name": "array", - "description": "- the array to scope `fields` paths" - }, - { - "type": "param", - "types": [ - "Object", - "undefined" - ], - "name": "fields", - "description": "- the root fields selected in the query" - }, - { - "type": "param", - "types": [ - "Boolean", - "undefined" - ], - "name": "init", - "description": "- if we are being created part of a query result" - } - ], - "description": { - "full": "

Scopes paths selected in a query to this array.
Necessary for proper default application of subdocument values.

", - "summary": "

Scopes paths selected in a query to this array.
Necessary for proper default application of subdocument values.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return selected;\n}", - "ctx": { - "type": "function", - "name": "scopePaths", - "string": "scopePaths()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = DocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "DocumentArray", - "string": "module.exports" - } - } -] -### lib/schema/index.js -[ - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "String", - "value": "require('./string')", - "string": "exports.String" - } - } -] -### lib/schema/mixed.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Mixed SchemaType constructor.

", - "summary": "

Mixed SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "Mixed", - "string": "Mixed()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "Mixed", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "Mixed.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Required validator

", - "summary": "

Required validator

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "checkRequired", - "string": "Mixed.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts val for Mixed.

\n\n

this is a no-op

", - "summary": "

Casts val for Mixed.

", - "body": "

this is a no-op

" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "cast", - "string": "Mixed.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$cond", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "castForQuery", - "string": "Mixed.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = Mixed;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Mixed", - "string": "module.exports" - } - } -] -### lib/schema/number.js -[ - { - "tags": [], - "description": { - "full": "

Module requirements.

", - "summary": "

Module requirements.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Number SchemaType constructor.

", - "summary": "

Number SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", - "ctx": { - "type": "function", - "name": "SchemaNumber", - "string": "SchemaNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaNumber", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaNumber.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Required validator for number

", - "summary": "

Required validator for number

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "checkRequired", - "string": "SchemaNumber.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "value", - "description": "minimum number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets a maximum number validator.

\n\n

Example:

\n\n
var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
", - "summary": "

Sets a maximum number validator.

", - "body": "

Example:

\n\n
var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "min", - "string": "SchemaNumber.prototype.min()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "maximum", - "description": "number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets a maximum number validator.

\n\n

Example:

\n\n
var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
", - "summary": "

Sets a maximum number validator.

", - "body": "

Example:

\n\n
var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "max", - "string": "SchemaNumber.prototype.max()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "value to cast" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to number

", - "summary": "

Casts to number

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "cast", - "string": "SchemaNumber.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "castForQuery", - "string": "SchemaNumber.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaNumber;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaNumber", - "string": "module.exports" - } - } -] -### lib/schema/objectid.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

ObjectId SchemaType constructor.

", - "summary": "

ObjectId SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", - "ctx": { - "type": "function", - "name": "ObjectId", - "string": "ObjectId()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "ObjectId", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "ObjectId.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Check required

", - "summary": "

Check required

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "checkRequired", - "string": "ObjectId.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to ObjectId

", - "summary": "

Casts to ObjectId

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "cast", - "string": "ObjectId.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "castForQuery", - "string": "ObjectId.prototype.castForQuery()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "turnOn", - "description": "auto generated ObjectId defaults" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Adds an auto-generated ObjectId default if turnOn is true.

", - "summary": "

Adds an auto-generated ObjectId default if turnOn is true.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "auto", - "string": "ObjectId.prototype.auto()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", - "ctx": { - "type": "function", - "name": "defaultId", - "string": "defaultId()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = ObjectId;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ObjectId", - "string": "module.exports" - } - } -] -### lib/schema/string.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

String SchemaType constructor.

", - "summary": "

String SchemaType constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", - "ctx": { - "type": "function", - "name": "SchemaString", - "string": "SchemaString()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from SchemaType.

", - "summary": "

Inherits from SchemaType.

", - "body": "" - }, - "ignore": true, - "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaString", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaString.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[args...]", - "description": "enumeration values" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds enumeration values and a coinciding validator.

\n\n

Example:

\n\n
var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
", - "summary": "

Adds enumeration values and a coinciding validator.

", - "body": "

Example:

\n\n
var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "enum", - "string": "SchemaString.prototype.enum()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a lowercase setter.

\n\n

Example:

\n\n
var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
", - "summary": "

Adds a lowercase setter.

", - "body": "

Example:

\n\n
var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v) {\n return v.toLowerCase();\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "lowercase", - "string": "SchemaString.prototype.lowercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds an uppercase setter.

\n\n

Example:

\n\n
var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
", - "summary": "

Adds an uppercase setter.

", - "body": "

Example:

\n\n
var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v) {\n return v.toUpperCase();\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "uppercase", - "string": "SchemaString.prototype.uppercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a trim setter.

\n\n

The string value will be trimmed when set.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
", - "summary": "

Adds a trim setter.

", - "body": "

The string value will be trimmed when set.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v) {\n return v.trim();\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "trim", - "string": "SchemaString.prototype.trim()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp" - ], - "name": "regExp", - "description": "regular expression to test against" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets a regexp validator.

\n\n

Any value that does not pass regExp.test(val) will fail validation.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
", - "summary": "

Sets a regexp validator.

", - "body": "

Any value that does not pass regExp.test(val) will fail validation.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "match", - "string": "SchemaString.prototype.match()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "null", - "undefined" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Check required

", - "summary": "

Check required

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "checkRequired", - "string": "SchemaString.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts to String

", - "summary": "

Casts to String

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "cast", - "string": "SchemaString.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts contents for queries.

", - "summary": "

Casts contents for queries.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "castForQuery", - "string": "SchemaString.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaString;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaString", - "string": "module.exports" - } - } -] -### lib/schema.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "definition", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted after the schema is compiled into a `Model`." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Schema constructor.

\n\n

Example:

\n\n
var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
\n\n

Options:

\n\n
    \n
  • safe: bool - defaults to true.
  • \n
  • read: string
  • \n
  • strict: bool - defaults to true
  • \n
  • capped: bool - defaults to false
  • \n
  • versionKey: bool - defaults to \"__v\"
  • \n
  • shardKey: bool - defaults to null
  • \n
  • autoIndex: bool - defaults to true
  • \n
  • _id: bool - defaults to true
  • \n
  • id: bool - defaults to true
  • \n
  • toObject - object - no default
  • \n
  • toJSON - object - no default
  • \n
  • minimize: bool - controls document#toObject behavior when called manually - defaults to true
  • \n
\n\n

Note:

\n\n

When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

", - "summary": "

Schema constructor.

", - "body": "

Example:

\n\n
var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
\n\n

Options:

\n\n
    \n
  • safe: bool - defaults to true.
  • \n
  • read: string
  • \n
  • strict: bool - defaults to true
  • \n
  • capped: bool - defaults to false
  • \n
  • versionKey: bool - defaults to \"__v\"
  • \n
  • shardKey: bool - defaults to null
  • \n
  • autoIndex: bool - defaults to true
  • \n
  • _id: bool - defaults to true
  • \n
  • id: bool - defaults to true
  • \n
  • toObject - object - no default
  • \n
  • toJSON - object - no default
  • \n
  • minimize: bool - controls document#toObject behavior when called manually - defaults to true
  • \n
\n\n

Note:

\n\n

When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

" - }, - "isPrivate": false, - "ignore": false, - "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", - "ctx": { - "type": "function", - "name": "Schema", - "string": "Schema()" - } - }, - { - "tags": [], - "description": { - "full": "

Returns this documents _id cast to a string.

", - "summary": "

Returns this documents _id cast to a string.

", - "body": "" - }, - "ignore": true, - "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", - "ctx": { - "type": "function", - "name": "idGetter", - "string": "idGetter()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from EventEmitter.

", - "summary": "

Inherit from EventEmitter.

", - "body": "" - }, - "ignore": true, - "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Schema", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Schema.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "paths" - } - ], - "description": { - "full": "

Schema as flat paths

\n\n

Example:

\n\n
{\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
", - "summary": "

Schema as flat paths

", - "body": "

Example:

\n\n
{\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.paths;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "tree" - } - ], - "description": { - "full": "

Schema as a tree

\n\n

Example:

\n\n
{\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
", - "summary": "

Schema as a tree

", - "body": "

Example:

\n\n
{\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.tree;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns default options for this schema, merged with options.

", - "summary": "

Returns default options for this schema, merged with options.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.defaultOptions = function (options) {\n options = utils.options({\n safe: true\n , strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "defaultOptions", - "string": "Schema.prototype.defaultOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "prefix", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds key path / schema type pairs to this schema.

\n\n

Example:

\n\n
var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
", - "summary": "

Adds key path / schema type pairs to this schema.

", - "body": "

Example:

\n\n
var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n }\n else\n this.path(prefix + i, obj[i]); // mixed type\n } else\n this.path(prefix + i, obj[i]);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "add", - "string": "Schema.prototype.add()" - } - }, - { - "tags": [], - "description": { - "full": "

Reserved document keys.

\n\n

Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

\n\n
 on, db, init, isNew, errors, schema, options, modelName, collection\n
", - "summary": "

Reserved document keys.

", - "body": "

Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

\n\n
 on, db, init, isNew, errors, schema, options, modelName, collection\n
" - }, - "ignore": false, - "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "reserved", - "value": "Object.create(null)", - "string": "Schema.reserved" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "constructor", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Gets/sets schema paths.

\n\n

Sets a path (if arity 2)
Gets a path (if arity 1)

\n\n

Example

\n\n
schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
", - "summary": "

Gets/sets schema paths.

", - "body": "

Sets a path (if arity 2)
Gets a path (if arity 1)

\n\n

Example

\n\n
schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(path) {\n if (!branch[path]) branch[path] = {};\n branch = branch[path];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "path", - "string": "Schema.prototype.path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "constructor" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Converts type arguments into Mongoose Types.

", - "summary": "

Converts type arguments into Mongoose Types.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", - "ctx": { - "type": "method", - "receiver": "Schema", - "name": "interpretAsType", - "string": "Schema.interpretAsType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback function" - }, - { - "type": "return", - "types": [ - "Schema" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Iterates the schemas paths similar to Array#forEach.

\n\n

The callback is passed the pathname and schemaType as arguments on each iteration.

", - "summary": "

Iterates the schemas paths similar to Array#forEach.

", - "body": "

The callback is passed the pathname and schemaType as arguments on each iteration.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "eachPath", - "string": "Schema.prototype.eachPath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - } - ], - "description": { - "full": "

Returns an Array of path strings that are required by this schema.

", - "summary": "

Returns an Array of path strings that are required by this schema.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "requiredPaths", - "string": "Schema.prototype.requiredPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns the pathType of path for this schema.

\n\n

Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

", - "summary": "

Returns the pathType of path for this schema.

", - "body": "

Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pathType", - "string": "Schema.prototype.pathType()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", - "ctx": { - "type": "function", - "name": "getPositionalPath", - "string": "getPositionalPath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the document method to call later" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Adds a method call to the queue.

", - "summary": "

Adds a method call to the queue.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "queue", - "string": "Schema.prototype.queue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a pre hook for the document.

\n\n

Example

\n\n
var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
", - "summary": "

Defines a pre hook for the document.

", - "body": "

Example

\n\n
var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pre", - "string": "Schema.prototype.pre()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "name of the method to hook" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a post hook for the document.

\n\n

Post hooks fire on the event emitted from document instances of Models compiled from this schema.

\n\n
var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
", - "summary": "

Defines a post hook for the document.

", - "body": "

Post hooks fire on the event emitted from document instances of Models compiled from this schema.

\n\n
var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "post", - "string": "Schema.prototype.post()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "plugin", - "description": "callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "" - }, - { - "type": "see", - "local": "plugins", - "visibility": "plugins" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Registers a plugin for this schema.

", - "summary": "

Registers a plugin for this schema.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "plugin", - "string": "Schema.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "method", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds an instance method to documents constructed from Models compiled from this schema.

\n\n

Example

\n\n
var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
\n\n

If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

\n\n
schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
", - "summary": "

Adds an instance method to documents constructed from Models compiled from this schema.

", - "body": "

Example

\n\n
var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
\n\n

If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

\n\n
schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "method", - "string": "Schema.prototype.method()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds static \"class\" methods to Models compiled from this schema.

\n\n

Example

\n\n
var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
\n\n

If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

", - "summary": "

Adds static \"class\" methods to Models compiled from this schema.

", - "body": "

Example

\n\n
var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
\n\n

If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "static", - "string": "Schema.prototype.static()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines an index (most likely compound) for this schema.

\n\n

Example

\n\n
schema.index({ first: 1, last: -1 })\n
", - "summary": "

Defines an index (most likely compound) for this schema.

", - "body": "

Example

\n\n
schema.index({ first: 1, last: -1 })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "index", - "string": "Schema.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "option name" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[value]", - "description": "if not passed, the current option value is returned" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets/gets a schema option.

", - "summary": "

Sets/gets a schema option.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.set = function (key, value, tags) {\n if (arguments.length == 1)\n return this.options[key];\n\n this.options[key] = 'read' == key\n ? utils.readPref(value, tags)\n : value;\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "set", - "string": "Schema.prototype.set()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Compiles indexes from fields and schema-level indexes

", - "summary": "

Compiles indexes from fields and schema-level indexes

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "indexes", - "string": "Schema.prototype.indexes()" - } - }, - { - "tags": [], - "description": { - "full": "

Checks for indexes added to subdocs using Schema.index().
These indexes need their paths prefixed properly.

\n\n

schema._indexes = [ [indexObj, options], [indexObj, options] ..]

", - "summary": "

Checks for indexes added to subdocs using Schema.index().
These indexes need their paths prefixed properly.

", - "body": "

schema._indexes = [ [indexObj, options], [indexObj, options] ..]

" - }, - "ignore": true, - "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", - "ctx": { - "type": "function", - "name": "fixSubIndexPaths", - "string": "fixSubIndexPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

Creates a virtual type with the given name.

", - "summary": "

Creates a virtual type with the given name.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtual", - "string": "Schema.prototype.virtual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

Returns the virtual type with the given name.

", - "summary": "

Returns the virtual type with the given name.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtualpath", - "string": "Schema.prototype.virtualpath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

These still haven't been fixed. Once they're working we'll make them public again.

", - "summary": "

These still haven't been fixed. Once they're working we'll make them public again.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "namedScope", - "string": "Schema.prototype.namedScope()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Schema", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

The various Mongoose Schema Types.

\n\n

Example:

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
\n\n

Types:

\n\n
    \n
  • String
  • \n
  • Number
  • \n
  • Boolean | Bool
  • \n
  • Array
  • \n
  • Buffer
  • \n
  • Date
  • \n
  • ObjectId | Oid
  • \n
  • Mixed
  • \n
\n\n

Using this exposed access to the Mixed SchemaType, we can use them in our schema.

\n\n
var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
", - "summary": "

The various Mongoose Schema Types.

", - "body": "

Example:

\n\n

Example:

\n\n
var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
\n\n

Types:

\n\n
    \n
  • String
  • \n
  • Number
  • \n
  • Boolean | Bool
  • \n
  • Array
  • \n
  • Buffer
  • \n
  • Date
  • \n
  • ObjectId | Oid
  • \n
  • Mixed
  • \n
\n\n

Using this exposed access to the Mixed SchemaType, we can use them in our schema.

\n\n
var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.Types = require('./schema/index');", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "Types", - "value": "require('./schema/index')", - "string": "Schema.Types" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" - } -] -### lib/schemadefault.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "property", - "string": "system.profile" - }, - { - "type": "receiver", - "string": "exports" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Default model for querying the system.profiles collection.

", - "summary": "

Default model for querying the system.profiles collection.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" - } -] -### lib/schematype.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');\nvar CastError = require('./errors/cast')\nvar ValidatorError = require('./errors/validator')", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[instance]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

SchemaType constructor

", - "summary": "

SchemaType constructor

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", - "ctx": { - "type": "function", - "name": "SchemaType", - "string": "SchemaType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function", - "any" - ], - "name": "val", - "description": "the default value" - }, - { - "type": "return", - "types": [ - "defaultValue" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets a default value for this SchemaType.

\n\n

Example:

\n\n
var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
\n\n

Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

\n\n

Example:

\n\n
// values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
", - "summary": "

Sets a default value for this SchemaType.

", - "body": "

Example:

\n\n
var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
\n\n

Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

\n\n

Example:

\n\n
// values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "default", - "string": "SchemaType.prototype.default()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "Boolean" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares the index options for this schematype.

\n\n

Example:

\n\n
var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
\n\n

NOTE:

\n\n

Indexes are created in the background by default. Specify background: false to override.

\n\n

Direction doesn't matter for single key indexes

", - "summary": "

Declares the index options for this schematype.

", - "body": "

Example:

\n\n
var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
\n\n

NOTE:

\n\n

Indexes are created in the background by default. Specify background: false to override.

\n\n

Direction doesn't matter for single key indexes

" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "index", - "string": "SchemaType.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares an unique index.

\n\n

Examples:

\n\n
var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
", - "summary": "

Declares an unique index.

", - "body": "

Examples:

\n\n
var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "unique", - "string": "SchemaType.prototype.unique()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares a sparse index.

\n\n

Examples:

\n\n
var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
", - "summary": "

Declares a sparse index.

", - "body": "

Examples:

\n\n
var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "sparse", - "string": "SchemaType.prototype.sparse()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "when", - "description": "" - }, - { - "type": "added", - "string": "3.0.0" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Declares a TTL index (rounded to the nearest second) for Date types only.

\n\n

This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
This index type is only compatible with Date types.

\n\n

Example:

\n\n
// expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
\n\n

expires utilizes the ms module from guille allowing us to use a friendlier syntax:

\n\n

Example:

\n\n
// expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
", - "summary": "

Declares a TTL index (rounded to the nearest second) for Date types only.

", - "body": "

This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
This index type is only compatible with Date types.

\n\n

Example:

\n\n
// expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
\n\n

expires utilizes the ms module from guille allowing us to use a friendlier syntax:

\n\n

Example:

\n\n
// expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "expires", - "string": "SchemaType.prototype.expires()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a setter to this schematype.

\n\n

Example:

\n\n
function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
\n\n

Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

\n\n

Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

\n\n

You can set up email lower case normalization easily via a Mongoose setter.

\n\n
function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
\n\n

As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

\n\n

NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

\n\n
new Schema({ email: { type: String, lowercase: true }})\n
", - "summary": "

Adds a setter to this schematype.

", - "body": "

Example:

\n\n
function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
\n\n

Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

\n\n

Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

\n\n

You can set up email lower case normalization easily via a Mongoose setter.

\n\n
function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
\n\n

As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

\n\n

NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

\n\n
new Schema({ email: { type: String, lowercase: true }})\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "set", - "string": "SchemaType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a getter to this schematype.

\n\n

Example:

\n\n
function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
\n\n

Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

\n\n

Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

\n\n
function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
", - "summary": "

Adds a getter to this schematype.

", - "body": "

Example:

\n\n
function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
\n\n

Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

\n\n

Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

\n\n
function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "get", - "string": "SchemaType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp", - "Function", - "Object" - ], - "name": "obj", - "description": "validator" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[error]", - "description": "optional error message" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds validator(s) for this document path.

\n\n

Validators must return Boolean. Returning false is interpreted as validation failure.

\n\n

Examples:

\n\n
function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
\n\n

Asynchronous validation:

\n\n

Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

\n\n
schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
\n\n

Validation occurs pre('save') or whenever you manually execute document#validate.

\n\n

If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

\n\n
var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
\n\n

If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

\n\n
// registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
", - "summary": "

Adds validator(s) for this document path.

", - "body": "

Validators must return Boolean. Returning false is interpreted as validation failure.

\n\n

Examples:

\n\n
function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
\n\n

Asynchronous validation:

\n\n

Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

\n\n
schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
\n\n

Validation occurs pre('save') or whenever you manually execute document#validate.

\n\n

If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

\n\n
var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
\n\n

If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

\n\n
// registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "validate", - "string": "SchemaType.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "required", - "description": "enable/disable the validator" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds a required validator to this schematype.

\n\n

Example:

\n\n
var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
", - "summary": "

Adds a required validator to this schematype.

", - "body": "

Example:

\n\n
var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "required", - "string": "SchemaType.prototype.required()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope which callback are executed" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Gets the default value

", - "summary": "

Gets the default value

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "getDefault", - "string": "SchemaType.prototype.getDefault()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Applies setters

", - "summary": "

Applies setters

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applySetters", - "string": "SchemaType.prototype.applySetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Applies getters to a value

", - "summary": "

Applies getters to a value

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applyGetters", - "string": "SchemaType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Sets default select() behavior for this path.

\n\n

Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

\n\n

Example:

\n\n
T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
", - "summary": "

Sets default select() behavior for this path.

", - "body": "

Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

\n\n

Example:

\n\n
T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "select", - "string": "SchemaType.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Performs a validation of value using the validators declared for this SchemaType.

", - "summary": "

Performs a validation of value using the validators declared for this SchemaType.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "doValidate", - "string": "SchemaType.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Determines if value is a valid Reference.

", - "summary": "

Determines if value is a valid Reference.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", - "ctx": { - "type": "method", - "receiver": "SchemaType", - "name": "_isRef", - "string": "SchemaType._isRef()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = SchemaType", - "string": "module.exports" - } - } -] -### lib/statemachine.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

StateMachine represents a minimal interface for the
constructors it builds via StateMachine.ctor(...).

", - "summary": "

StateMachine represents a minimal interface for the
constructors it builds via StateMachine.ctor(...).

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", - "ctx": { - "type": "declaration", - "name": "StateMachine", - "value": "module.exports = exports = function StateMachine () {", - "string": "StateMachine" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "subclass constructor" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

StateMachine.ctor('state1', 'state2', ...)
A factory method for subclassing StateMachine.
The arguments are a list of states. For each state,
the constructor's prototype gets state transition
methods named after each state. These transition methods
place their path argument into the given state.

", - "summary": "

StateMachine.ctor('state1', 'state2', ...)
A factory method for subclassing StateMachine.
The arguments are a list of states. For each state,
the constructor's prototype gets state transition
methods named after each state. These transition methods
place their path argument into the given state.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", - "ctx": { - "type": "method", - "receiver": "StateMachine", - "name": "ctor", - "string": "StateMachine.ctor()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

This function is wrapped by the state change functions

\n\n
    \n
  • require(path)
  • \n
  • modify(path)
  • \n
  • init(path)
  • \n
", - "summary": "

This function is wrapped by the state change functions

", - "body": "
    \n
  • require(path)
  • \n
  • modify(path)
  • \n
  • init(path)
  • \n
" - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_changeState", - "string": "StateMachine.prototype._changeState()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "clear", - "string": "StateMachine.prototype.clear()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "that we want to check for." - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

Checks to see if at least one path is in the states passed in via arguments
e.g., this.some('required', 'inited')

", - "summary": "

Checks to see if at least one path is in the states passed in via arguments
e.g., this.some('required', 'inited')

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "some", - "string": "StateMachine.prototype.some()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "iterMethod", - "description": "is either 'forEach' or 'map'" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

This function builds the functions that get assigned to forEach and map,
since both of those methods share a lot of the same logic.

", - "summary": "

This function builds the functions that get assigned to forEach and map,
since both of those methods share a lot of the same logic.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_iter", - "string": "StateMachine.prototype._iter()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

Iterates over the paths that belong to one of the parameter states.

\n\n

The function profile can look like

\n\n

this.forEach(state1, fn); // iterates over all paths in state1
this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
this.forEach(fn); // iterates over all paths in all states

", - "summary": "

Iterates over the paths that belong to one of the parameter states.

", - "body": "

The function profile can look like

\n\n

this.forEach(state1, fn); // iterates over all paths in state1
this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
this.forEach(fn); // iterates over all paths in all states

" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "forEach", - "string": "StateMachine.prototype.forEach()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

Maps over the paths that belong to one of the parameter states.

\n\n

The function profile can look like

\n\n

this.forEach(state1, fn); // iterates over all paths in state1
this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
this.forEach(fn); // iterates over all paths in all states

", - "summary": "

Maps over the paths that belong to one of the parameter states.

", - "body": "

The function profile can look like

\n\n

this.forEach(state1, fn); // iterates over all paths in state1
this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
this.forEach(fn); // iterates over all paths in all states

" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "map", - "string": "StateMachine.prototype.map()" - } - } -] -### lib/types/array.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", - "ctx": { - "type": "declaration", - "name": "EmbeddedDocument", - "value": "require('./embedded')", - "string": "EmbeddedDocument" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Array" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

Mongoose Array constructor.

\n\n

NOTE:

\n\n

Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

", - "summary": "

Mongoose Array constructor.

", - "body": "

NOTE:

\n\n

Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseArray", - "string": "MongooseArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from Array

", - "summary": "

Inherit from Array

", - "body": "" - }, - "ignore": true, - "code": "MongooseArray.prototype = new Array;", - "ctx": { - "type": "property", - "receiver": "MongooseArray", - "name": "prototype", - "value": "new Array", - "string": "MongooseArray.prototype" - } - }, - { - "tags": [ - { - "type": "property", - "string": "_atomics" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Stores a queue of atomic operations to perform

", - "summary": "

Stores a queue of atomic operations to perform

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._atomics;" - }, - { - "tags": [ - { - "type": "property", - "string": "_parent" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Parent owner document

", - "summary": "

Parent owner document

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._parent;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "return", - "types": [ - "value" - ], - "description": "the casted value" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Casts a member based on this arrays schema.

", - "summary": "

Casts a member based on this arrays schema.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_cast", - "string": "MongooseArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "EmbeddedDocument" - ], - "name": "embeddedDoc", - "description": "the embedded doc that invoked this method on the Array" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "embeddedPath", - "description": "the path which changed in the embeddedDoc" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Marks this array as modified.

\n\n

If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

", - "summary": "

Marks this array as modified.

", - "body": "

If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._markModified = function (embeddedDoc, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n if (arguments.length) {\n // If an embedded doc bubbled up the change\n dirtyPath = [this._path, this.indexOf(embeddedDoc), embeddedPath].join('.');\n } else {\n dirtyPath = this._path;\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_markModified", - "string": "MongooseArray.prototype._markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "op", - "description": "operation" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Register an atomic operation with the parent.

", - "summary": "

Register an atomic operation with the parent.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n this._markModified();\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n if (this._atomics.$set) {\n return this;\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n this._markModified();\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n this._markModified();\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_registerAtomic", - "string": "MongooseArray.prototype._registerAtomic()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - } - ], - "description": { - "full": "

Returns the number of pending atomic operations to send to the db for this array.

", - "summary": "

Returns the number of pending atomic operations to send to the db for this array.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "hasAtomics", - "string": "MongooseArray.prototype.hasAtomics()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#push with proper change tracking.

", - "summary": "

Wraps Array#push with proper change tracking.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "push", - "string": "MongooseArray.prototype.push()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Pushes items to the array non-atomically.

\n\n

NOTE:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Pushes items to the array non-atomically.

", - "body": "

NOTE:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "nonAtomicPush", - "string": "MongooseArray.prototype.nonAtomicPush()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "$pop" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

Pops the array atomically at most one time per document save().

\n\n

NOTE:

\n\n

Calling this mulitple times on an array before saving sends the same command as calling it once.
This update is implemented using the MongoDB $pop method which enforces this restriction.

\n\n
 doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
", - "summary": "

Pops the array atomically at most one time per document save().

", - "body": "

NOTE:

\n\n

Calling this mulitple times on an array before saving sends the same command as calling it once.
This update is implemented using the MongoDB $pop method which enforces this restriction.

\n\n
 doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" - }, - { - "tags": [ - { - "type": "see", - "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", - "visibility": "MongooseArray#$pop" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#pop with proper change tracking.

\n\n

Note:

\n\n

marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#pop with proper change tracking.

", - "body": "

Note:

\n\n

marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pop", - "string": "MongooseArray.prototype.pop()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "method", - "string": "$shift" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

Atomically shifts the array at most one time per document save().

\n\n

NOTE:

\n\n

Calling this mulitple times on an array before saving sends the same command as calling it once.
This update is implemented using the MongoDB $pop method which enforces this restriction.

\n\n
 doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
", - "summary": "

Atomically shifts the array at most one time per document save().

", - "body": "

NOTE:

\n\n

Calling this mulitple times on an array before saving sends the same command as calling it once.
This update is implemented using the MongoDB $pop method which enforces this restriction.

\n\n
 doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#shift with proper change tracking.

\n\n

Example:

\n\n
doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
\n\n

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#shift with proper change tracking.

", - "body": "

Example:

\n\n
doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
\n\n

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "shift", - "string": "MongooseArray.prototype.shift()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "values to remove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Removes items from an array atomically

\n\n

Examples:

\n\n
doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
", - "summary": "

Removes items from an array atomically

", - "body": "

Examples:

\n\n
doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "remove", - "string": "MongooseArray.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Pulls items from the array atomically.

", - "summary": "

Pulls items from the array atomically.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pull", - "string": "MongooseArray.prototype.pull()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#splice with proper change tracking.

\n\n

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#splice with proper change tracking.

", - "body": "

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.splice = function () {\n if (arguments.length) {\n var ret = [].splice.apply(this, arguments);\n this._registerAtomic('$set', this);\n }\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "splice", - "string": "MongooseArray.prototype.splice()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#unshift with proper change tracking.

\n\n

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#unshift with proper change tracking.

", - "body": "

Note:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n return this.length;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "unshift", - "string": "MongooseArray.prototype.unshift()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Wraps Array#sort with proper change tracking.

\n\n

NOTE:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

", - "summary": "

Wraps Array#sort with proper change tracking.

", - "body": "

NOTE:

\n\n

marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "sort", - "string": "MongooseArray.prototype.sort()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "the values that were added" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Adds values to the array if not already present.

\n\n

Example:

\n\n
console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
", - "summary": "

Adds values to the array if not already present.

", - "body": "

Example:

\n\n
console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "addToSet", - "string": "MongooseArray.prototype.addToSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns a native js Array.

", - "summary": "

Returns a native js Array.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "toObject", - "string": "MongooseArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "inspect", - "string": "MongooseArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the item to look for" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Return the index of obj or -1 if not found.

", - "summary": "

Return the index of obj or -1 if not found.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "indexOf", - "string": "MongooseArray.prototype.indexOf()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = MongooseArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = MongooseArray", - "string": "module.exports" - } - } -] -### lib/types/buffer.js -[ - { - "tags": [], - "description": { - "full": "

Access driver.

", - "summary": "

Access driver.

", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Binary = require(driver + '/binary');", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require(driver + '/binary')", - "string": "Binary" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "encode", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "offset", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Buffer" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

Mongoose Buffer constructor.

\n\n

Values always have to be passed to the constructor to initialize.

", - "summary": "

Mongoose Buffer constructor.

", - "body": "

Values always have to be passed to the constructor to initialize.

" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", - "ctx": { - "type": "function", - "name": "MongooseBuffer", - "string": "MongooseBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from Buffer.

", - "summary": "

Inherit from Buffer.

", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.prototype = new Buffer(0);", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "prototype", - "value": "new Buffer(0)", - "string": "MongooseBuffer.prototype" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "_parent" - } - ], - "description": { - "full": "

Parent owner document

", - "summary": "

Parent owner document

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._parent;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Marks this buffer as modified.

", - "summary": "

Marks this buffer as modified.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "_markModified", - "string": "MongooseBuffer.prototype._markModified()" - } - }, - { - "tags": [], - "description": { - "full": "

Writes the buffer.

", - "summary": "

Writes the buffer.

", - "body": "" - }, - "ignore": false, - "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "write", - "string": "MongooseBuffer.prototype.write()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "MongooseBuffer" - ], - "description": "" - }, - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "target", - "description": "" - } - ], - "description": { - "full": "

Copies the buffer.

\n\n

Note:

\n\n

Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

", - "summary": "

Copies the buffer.

", - "body": "

Note:

\n\n

Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "copy", - "string": "MongooseBuffer.prototype.copy()" - } - }, - { - "tags": [], - "description": { - "full": "

Compile other Buffer methods marking this buffer as modified.

", - "summary": "

Compile other Buffer methods marking this buffer as modified.

", - "body": "" - }, - "ignore": true, - "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://bsonspec.org/#/specification", - "visibility": "http://bsonspec.org/#/specification" - }, - { - "type": "param", - "types": [ - "Hex" - ], - "name": "[subtype]", - "description": "" - }, - { - "type": "return", - "types": [ - "Binary" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Converts this buffer to its Binary type representation.

\n\n

SubTypes:

\n\n
    \n
  • 0x00: Binary/Generic
  • \n
  • 0x01: Function
  • \n
  • 0x02: Binary (Deprecated, 0x00 is new default)
  • \n
  • 0x03: UUID
  • \n
  • 0x04: MD5
  • \n
  • 0x80: User Defined
  • \n
", - "summary": "

Converts this buffer to its Binary type representation.

", - "body": "

SubTypes:

\n\n
    \n
  • 0x00: Binary/Generic
  • \n
  • 0x01: Function
  • \n
  • 0x02: Binary (Deprecated, 0x00 is new default)
  • \n
  • 0x03: UUID
  • \n
  • 0x04: MD5
  • \n
  • 0x80: User Defined
  • \n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "toObject", - "string": "MongooseBuffer.prototype.toObject()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "Binary", - "value": "Binary", - "string": "MongooseBuffer.Binary" - } - } -] -### lib/types/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", - "ctx": { - "type": "declaration", - "name": "MongooseArray", - "value": "require('./array')", - "string": "MongooseArray" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to this array" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "MongooseDocumentArray" - ], - "description": "" - }, - { - "type": "inherits", - "string": "MongooseArray" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

DocumentArray constructor

", - "summary": "

DocumentArray constructor

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseDocumentArray", - "string": "MongooseDocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherits from MongooseArray

", - "summary": "

Inherits from MongooseArray

", - "body": "" - }, - "ignore": true, - "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseDocumentArray", - "name": "__proto__", - "value": "MongooseArray.prototype", - "string": "MongooseDocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Overrides MongooseArray#cast

", - "summary": "

Overrides MongooseArray#cast

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype._cast = function (value) {\n var doc = new this._schema.casterConstructor(value, this);\n return doc;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "_cast", - "string": "MongooseDocumentArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "EmbeddedDocument", - "null" - ], - "description": "the subdocuent or null if not found." - }, - { - "type": "param", - "types": [ - "ObjectId", - "String", - "Number", - "Buffer" - ], - "name": "id", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Searches array items for the first document with a matching id.

\n\n

Example:

\n\n
var embeddedDoc = m.array.id(some_id);\n
", - "summary": "

Searches array items for the first document with a matching id.

", - "body": "

Example:

\n\n
var embeddedDoc = m.array.id(some_id);\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "id", - "string": "MongooseDocumentArray.prototype.id()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns a native js Array of plain js objects

\n\n

NOTE:

\n\n

Each sub-document is converted to a plain object by calling its #toObject method.

", - "summary": "

Returns a native js Array of plain js objects

", - "body": "

NOTE:

\n\n

Each sub-document is converted to a plain object by calling its #toObject method.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "toObject", - "string": "MongooseDocumentArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "inspect", - "string": "MongooseDocumentArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the value to cast to this arrays SubDocument schema" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Creates a subdocument casted to this schema.

\n\n

This is the same subdocument constructor used for casting.

", - "summary": "

Creates a subdocument casted to this schema.

", - "body": "

This is the same subdocument constructor used for casting.

" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "create", - "string": "MongooseDocumentArray.prototype.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Creates a fn that notifies all child docs of event.

", - "summary": "

Creates a fn that notifies all child docs of event.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n self[i].emit(event, val);\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "notify", - "string": "MongooseDocumentArray.prototype.notify()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseDocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseDocumentArray", - "string": "module.exports" - } - } -] -### lib/types/embedded.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var Document = require('../document')\n , inspect = require('util').inspect;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('../document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "js object returned from the db" - }, - { - "type": "param", - "types": [ - "MongooseDocumentArray" - ], - "name": "parentArr", - "description": "the parent array of this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "skipId", - "description": "" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

EmbeddedDocument constructor.

", - "summary": "

EmbeddedDocument constructor.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", - "ctx": { - "type": "function", - "name": "EmbeddedDocument", - "string": "EmbeddedDocument()" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from Document

", - "summary": "

Inherit from Document

", - "body": "" - }, - "ignore": true, - "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "EmbeddedDocument", - "name": "__proto__", - "value": "Document.prototype", - "string": "EmbeddedDocument.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path which changed" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Marks the embedded doc modified.

\n\n

Example:

\n\n
var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
", - "summary": "

Marks the embedded doc modified.

", - "body": "

Example:

\n\n
var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "markModified", - "string": "EmbeddedDocument.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "return", - "types": [ - "EmbeddedDocument" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Used as a stub for hooks.js

\n\n

NOTE:

\n\n

This is a no-op. Does not actually save the doc to the db.

", - "summary": "

Used as a stub for hooks.js

", - "body": "

NOTE:

\n\n

This is a no-op. Does not actually save the doc to the db.

" - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "save", - "string": "EmbeddedDocument.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Removes the subdocument from its parent array.

", - "summary": "

Removes the subdocument from its parent array.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "remove", - "string": "EmbeddedDocument.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Override #update method of parent documents.

", - "summary": "

Override #update method of parent documents.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "update", - "string": "EmbeddedDocument.prototype.update()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Helper for console.log

", - "summary": "

Helper for console.log

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "inspect", - "string": "EmbeddedDocument.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "error which states the reason `path` was invalid" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Marks a path as invalid, causing validation to fail.

", - "summary": "

Marks a path as invalid, causing validation to fail.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "invalidate", - "string": "EmbeddedDocument.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

Returns the top level document of this sub-document.

", - "summary": "

Returns the top level document of this sub-document.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "ownerDocument", - "string": "EmbeddedDocument.prototype.ownerDocument()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

Returns the top level document of this sub-document.

", - "summary": "

Returns the top level document of this sub-document.

", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", - "ctx": { - "type": "function", - "name": "ownerDocument", - "string": "ownerDocument()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns this sub-documents parent document.

", - "summary": "

Returns this sub-documents parent document.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parent", - "string": "EmbeddedDocument.prototype.parent()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Returns this sub-documents parent array.

", - "summary": "

Returns this sub-documents parent array.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parentArray", - "string": "EmbeddedDocument.prototype.parentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "module.exports = EmbeddedDocument;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "EmbeddedDocument", - "string": "module.exports" - } - } -] -### lib/types/index.js -[ - { - "tags": [], - "description": { - "full": "

Module exports.

", - "summary": "

Module exports.

", - "body": "" - }, - "ignore": true, - "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "Array", - "value": "require('./array')", - "string": "exports.Array" - } - } -] -### lib/types/objectid.js -[ - { - "tags": [], - "description": { - "full": "

Access driver.

", - "summary": "

Access driver.

", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [ - { - "type": "constructor", - "string": "ObjectId" - } - ], - "description": { - "full": "

ObjectId type constructor

\n\n

Example

\n\n
var id = new mongoose.Types.ObjectId;\n
", - "summary": "

ObjectId type constructor

", - "body": "

Example

\n\n
var id = new mongoose.Types.ObjectId;\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require(driver + '/objectid')", - "string": "ObjectId" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "str", - "description": "" - }, - { - "type": "static", - "string": "fromString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "ObjectId" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Creates an ObjectId from str

", - "summary": "

Creates an ObjectId from str

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.fromString;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId" - ], - "name": "oid", - "description": "ObjectId instance" - }, - { - "type": "static", - "string": "toString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Converts oid to a string.

", - "summary": "

Converts oid to a string.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.toString;" - } -] -### lib/utils.js -[ - { - "tags": [], - "description": { - "full": "

Module dependencies.

", - "summary": "

Module dependencies.

", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , MongooseBuffer\n , MongooseArray\n , Document", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "a model name" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "a collection name" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Produces a collection name from model name.

", - "summary": "

Produces a collection name from model name.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "toCollectionName", - "string": "exports.toCollectionName()" - } - }, - { - "tags": [], - "description": { - "full": "

Pluralization rules.

\n\n

These rules are applied while processing the argument to toCollectionName.

", - "summary": "

Pluralization rules.

", - "body": "

These rules are applied while processing the argument to toCollectionName.

" - }, - "ignore": false, - "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "pluralization", - "value": "[", - "string": "exports.pluralization" - } - }, - { - "tags": [], - "description": { - "full": "

Uncountable words.

\n\n

These words are applied while processing the argument to toCollectionName.

", - "summary": "

Uncountable words.

", - "body": "

These words are applied while processing the argument to toCollectionName.

" - }, - "ignore": false, - "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news'\n];\nvar uncountables = exports.uncountables;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "uncountables", - "value": "[", - "string": "exports.uncountables" - } - }, - { - "tags": [ - { - "type": "author", - "string": "TJ Holowaychuk (extracted from _ext.js_)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "string", - "description": "to pluralize" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Pluralize function.

", - "summary": "

Pluralize function.

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", - "ctx": { - "type": "function", - "name": "pluralize", - "string": "pluralize()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "listener", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Add once to EventEmitter if absent

", - "summary": "

Add once to EventEmitter if absent

", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", - "ctx": { - "type": "declaration", - "name": "Events", - "value": "EventEmitter", - "string": "Events" - } - }, - { - "tags": [], - "description": { - "full": "

Inherit from EventEmitter.

", - "summary": "

Inherit from EventEmitter.

", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Events", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Events.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

Add once.

", - "summary": "

Add once.

", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", - "ctx": { - "type": "method", - "constructor": "Events", - "name": "once", - "string": "Events.prototype.once()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "a", - "description": "a value to compare to `b`" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "b", - "description": "a value to compare to `a`" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Determines if a and b are deep equal.

\n\n

Modified from node/lib/assert.js

", - "summary": "

Determines if a and b are deep equal.

", - "body": "

Modified from node/lib/assert.js

" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "deepEqual", - "string": "exports.deepEqual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the object to clone" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the cloned object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Object clone with Mongoose natives support.

\n\n

Creates a minimal data Object.
It does not clone empty Arrays, empty Objects, and undefined values.
This makes the data payload sent to MongoDB as minimal as possible.

", - "summary": "

Object clone with Mongoose natives support.

", - "body": "

Creates a minimal data Object.
It does not clone empty Arrays, empty Objects, and undefined values.
This makes the data payload sent to MongoDB as minimal as possible.

" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId) {\n return new ObjectId(obj.id);\n }\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "clone", - "string": "exports.clone()" - } - }, - { - "tags": [], - "description": { - "full": "

ignore

", - "summary": "

ignore

", - "body": "" - }, - "ignore": true, - "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", - "ctx": { - "type": "function", - "name": "cloneObject", - "string": "cloneObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "defaults", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the merged object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Copies and merges options with defaults.

", - "summary": "

Copies and merges options with defaults.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "options", - "string": "exports.options()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Generates a random string

", - "summary": "

Generates a random string

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "random", - "string": "exports.random()" - } - }, - { - "tags": [], - "description": { - "full": "

TODO remove

", - "summary": "

TODO remove

", - "body": "" - }, - "ignore": true, - "code": "exports.inGroupsOf = function inGroupsOf (card, arr, fn) {\n var group = [];\n for (var i = 0, l = arr.length; i < l; i++) {\n if (i && i % card === 0) {\n fn.apply(this, group);\n group.length = 0;\n }\n group.push(arr[i]);\n }\n fn.apply(this, group);\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "inGroupsOf", - "string": "exports.inGroupsOf()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "to", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "from", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Merges from into to without overwriting existing properties.

", - "summary": "

Merges from into to without overwriting existing properties.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n merge(to[key], from[key]);\n }\n }\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "merge", - "string": "exports.merge()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

A faster Array.prototype.slice.call(arguments) alternative

", - "summary": "

A faster Array.prototype.slice.call(arguments) alternative

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.args = function (args, slice, sliceEnd) {\n var ret = [];\n var start = slice || 0;\n var end = 3 === arguments.length\n ? sliceEnd\n : args.length;\n\n for (var i = start; i < end; ++i) {\n ret[i - start] = args[i];\n }\n\n return ret;\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "args", - "string": "exports.args()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

process.nextTick helper.

\n\n

Wraps callback in a try/catch + nextTick.

\n\n

node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

", - "summary": "

process.nextTick helper.

", - "body": "

Wraps callback in a try/catch + nextTick.

\n\n

node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "tick", - "string": "exports.tick()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "v", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Returns if v is a mongoose object that has a toObject() method we can use.

\n\n

This is for compatibility with libs like Date.js which do foolish things to Natives.

", - "summary": "

Returns if v is a mongoose object that has a toObject() method we can use.

", - "body": "

This is for compatibility with libs like Date.js which do foolish things to Natives.

" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isMongooseObject", - "string": "exports.isMongooseObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "object", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

", - "summary": "

Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expiresAfterSeconds = when;\n delete object.expires;\n}\n\nexports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "expires", - "string": "exports.expires()" - } - } -] -### lib/virtualtype.js -[ - { - "tags": [ - { - "type": "parma", - "string": "{Object} options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

VirtualType constructor

\n\n

This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

\n\n

Example:

\n\n
var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
", - "summary": "

VirtualType constructor

", - "body": "

This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

\n\n

Example:

\n\n
var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", - "ctx": { - "type": "function", - "name": "VirtualType", - "string": "VirtualType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a getter.

\n\n

Example:

\n\n
var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
", - "summary": "

Defines a getter.

", - "body": "

Example:

\n\n
var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "get", - "string": "VirtualType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Defines a setter.

\n\n

Example:

\n\n
var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
", - "summary": "

Defines a setter.

", - "body": "

Example:

\n\n
var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "set", - "string": "VirtualType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all getters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Applies getters to value using optional scope.

", - "summary": "

Applies getters to value using optional scope.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applyGetters", - "string": "VirtualType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all setters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

Applies setters to value using optional scope.

", - "summary": "

Applies setters to value using optional scope.

", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applySetters", - "string": "VirtualType.prototype.applySetters()" - } - }, - { - "tags": [], - "description": { - "full": "

exports

", - "summary": "

exports

", - "body": "" - }, - "ignore": true, - "code": "module.exports = VirtualType;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "VirtualType", - "string": "module.exports" - } - } -] diff --git a/docs/3.1.x/docs/source/api.js b/docs/3.1.x/docs/source/api.js deleted file mode 100644 index 8fd87f0035b..00000000000 --- a/docs/3.1.x/docs/source/api.js +++ /dev/null @@ -1,220 +0,0 @@ -/*! - * Module dependencies - */ - -var fs = require('fs'); -var link = require('../helpers/linktype'); -var hl = require('highlight.js') -var md = require('markdown') - -module.exports = { - docs: [] - , github: 'https://github.com/LearnBoost/mongoose/tree/' - , title: 'API docs' -} - -var out = module.exports.docs; - -var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); -parse(docs); -order(out); - -function parse (docs) { - docs.split(/^### /gm).forEach(function (chunk) { - if (!(chunk = chunk.trim())) return; - - chunk = chunk.split(/^([^\n]+)\n/); - - var title = chunk[1]; - - if (!title || !(title = title.trim())) - throw new Error('missing title'); - - title = title.replace(/^lib\//, ''); - - var json = JSON.parse(chunk[2]); - - var props = []; - var methods = []; - var statics = []; - var constructor = null; - - json.forEach(function (comment) { - if (comment.description) - highlight(comment.description); - - var prop = false; - comment.params = []; - comment.see = []; - - var i = comment.tags.length; - while (i--) { - var tag = comment.tags[i]; - switch (tag.type) { - case 'property': - prop = true; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - props.unshift(comment); - break; - case 'method': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'method'; - comment.code = ''; - break; - case 'memberOf': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.constructor = tag.parent; - break; - case 'static': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - comment.ctx.type = 'method'; - break; - case 'receiver': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.receiver = tag.string; - break; - case 'constructor': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'function'; - comment.code = ''; - break; - case 'inherits': - if (/http/.test(tag.string)) { - var result = tag.string.split(' '); - var href = result.pop(); - var title = result.join(' '); - comment.inherits = '' + title + ''; - } else { - comment.inherits = link(tag.string); - } - comment.tags.splice(i, 1); - break; - case 'param': - comment.params.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'return': - comment.return = tag; - comment.tags.splice(i, 1); - break; - case 'see': - if (tag.local) { - var parts = tag.local.split(' '); - if (1 === parts.length) { - tag.url = link.type(parts[0]); - tag.title = parts[0]; - } else { - tag.url = parts.pop(); - tag.title = parts.join(' '); - } - } - comment.see.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'event': - var str = tag.string.replace(/\\n/g, '\n'); - tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); - comment.events || (comment.events = []); - comment.events.unshift(tag); - comment.tags.splice(i, 1); - } - } - - if (!prop) { - methods.push(comment); - } - }); - - methods = methods.filter(ignored); - props = props.filter(ignored); - - function ignored (method) { - if (method.ignore) return false; - return true; - } - - if (0 === methods.length + props.length) return; - - // add constructor to properties too - methods.some(function (method) { - if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { - props.forEach(function (prop) { - prop.ctx.constructor = method.ctx.constructor; - }); - return true; - } - return false; - }); - - var len = methods.length; - while (len--) { - method = methods[len]; - if (method.ctx && method.ctx.receiver) { - var stat = methods.splice(len, 1)[0]; - statics.unshift(stat); - } - } - - out.push({ - title: title - , methods: methods - , props: props - , statics: statics - , hasPublic: hasPublic(methods, props, statics) - }); - }); -} - -function hasPublic () { - for (var i = 0; i < arguments.length; ++i) { - var arr = arguments[i]; - for (var j = 0; j < arr.length; ++j) { - var item = arr[j]; - if (!item.ignore && !item.isPrivate) return true; - } - } - return false; -} - -// add "class='language'" to our
 elements
-function highlight (o) {
-  o.full = fix(o.full);
-  o.summary = fix(o.summary);
-  o.body = fix(o.body);
-}
-
-function fix (str) {
-  return str.replace(/(
)([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
-
-    // parse out the ```language
-    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
-
-    if ('js' == code[1] || !code[1]) {
-      code[1] = 'javascript';
-    }
-
-    return $1
-          + hl.highlight(code[1], code[2]).value.trim()
-          + $3;
-  });
-}
-
-function order (docs) {
-  // want index first
-  for (var i = 0; i < docs.length; ++i) {
-    if ('index.js' == docs[i].title) {
-      docs.unshift(docs.splice(i, 1)[0]);
-    }
-  }
-}
diff --git a/docs/3.1.x/docs/source/home.js b/docs/3.1.x/docs/source/home.js
deleted file mode 100644
index 557f27b966b..00000000000
--- a/docs/3.1.x/docs/source/home.js
+++ /dev/null
@@ -1,19 +0,0 @@
-
-var fs = require('fs')
-var package = require('./../../package.json')
-var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
-
-var imgs = [];
-
-images.forEach(function (line) {
-  line = line.trim();
-  if (!line) return;
-  line = line.split('|');
-  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
-});
-
-module.exports = {
-    package: package
-  , images: imgs
-  , title: 'ODM'
-}
diff --git a/docs/3.1.x/docs/source/index.js b/docs/3.1.x/docs/source/index.js
deleted file mode 100644
index d54229720a1..00000000000
--- a/docs/3.1.x/docs/source/index.js
+++ /dev/null
@@ -1,18 +0,0 @@
-
-exports['index.jade'] = require('./home')
-exports['docs/api.jade'] = require('./api')
-exports['docs/index.jade'] = { title: 'Getting Started' }
-exports['docs/prior.jade'] = require('./prior')
-exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
-exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
-exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
-exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
-exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
-exports['docs/models.jade'] = { guide: true, title: 'Models' }
-exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
-exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
-exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
-exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
-exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
-exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
-exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
diff --git a/docs/3.1.x/docs/source/prior.js b/docs/3.1.x/docs/source/prior.js
deleted file mode 100644
index 2e03811d215..00000000000
--- a/docs/3.1.x/docs/source/prior.js
+++ /dev/null
@@ -1,13 +0,0 @@
-var fs = require('fs')
-var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
-releases = releases.split('\n').filter(Boolean);
-
-module.exports = exports = {
-    title: ''
-  , releases: releases.map(function (version) {
-      return {
-          url: version + '/'
-        , version: version
-      }
-    })
-}
diff --git a/docs/3.1.x/docs/subdocs.html b/docs/3.1.x/docs/subdocs.html
deleted file mode 100644
index 626749164c2..00000000000
--- a/docs/3.1.x/docs/subdocs.html
+++ /dev/null
@@ -1,49 +0,0 @@
-Mongoose SubDocuments v3.1.2Fork me on GitHub

Sub Docs

Sub-documents are docs with schemas of their own which are elements of a parents document array:

var childSchema = new Schema({ name: 'string' });
-
-var parentSchema = new Schema({
-  children: [childSchema]
-})
-

Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

var Parent = db.model('Parent', parentSchema);
-var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
-parent.children[0].name = 'Matthew';
-parent.save(callback);
-

If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

childSchema.pre('save', function (next) {
-  if ('invalid' == this.name) return next(new Error('#sadpanda'));
-  next();
-});
-
-var parent = new Parent({ children: [{ name: 'invalid' }] });
-parent.save(function (err) {
-  console.log(err.message) // #sadpanda
-})
-

Finding a sub-document

Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

var doc = parent.children.id(id);
-

Adding sub-docs

MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

var Parent = db.model('Parent');
-var parent = new Parent;
-
-// create a comment
-post.children.push({ name: 'Liesl' });
-var doc = post.children[0];
-console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
-doc.isNew; // true
-
-post.save(function (err) {
-  if (err) return handleError(err)
-  console.log('Success!');
-});

Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

var newdoc = post.children.create({ name: 'Aaron' });
-

Removing docs

Each sub-document has it's own remove method.

var doc = parent.children.id(id).remove();
-parent.save(function (err) {
-  if (err) return handleError(err);
-  console.log('the sub-doc was removed')
-});
-

Alternate declaration syntax

New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

var parentSchema = new Schema({
-  children: [{ name: 'string' }]
-})
-

Next Up

Now that we've covered Sub-documents, let's take a look at Models.

diff --git a/docs/3.1.x/docs/subdocs.jade b/docs/3.1.x/docs/subdocs.jade deleted file mode 100644 index 81b63ec2647..00000000000 --- a/docs/3.1.x/docs/subdocs.jade +++ /dev/null @@ -1,84 +0,0 @@ -extends layout - -block content - h2 Sub Docs - :markdown - [Sub-documents](./api.html#types-embedded-js) are docs with schemas of their own which are elements of a parents document array: - :js - var childSchema = new Schema({ name: 'string' }); - - var parentSchema = new Schema({ - children: [childSchema] - }) - - :markdown - Sub-documents enjoy all the same features as normal [documents](./api.html#document-js). The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved. - :js - var Parent = db.model('Parent', parentSchema); - var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) - parent.children[0].name = 'Matthew'; - parent.save(callback); - - :markdown - If an error occurs in a sub-documents' middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap! - - :js - childSchema.pre('save', function (next) { - if ('invalid' == this.name) return next(new Error('#sadpanda')); - next(); - }); - - var parent = new Parent({ children: [{ name: 'invalid' }] }); - parent.save(function (err) { - console.log(err.message) // #sadpanda - }) - - h3 Finding a sub-document - :markdown - Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. - :js - var doc = parent.children.id(id); - - h3 Adding sub-docs - :markdown - MongooseArray methods such as [push](./api.html#types_array_MongooseArray-push), [unshift](./api.html#types_array_MongooseArray-unshift), [addToSet](./api.html#types_array_MongooseArray-addToSet), and others cast arguments to their proper types transparently: - :js - var Parent = db.model('Parent'); - var parent = new Parent; - - // create a comment - post.children.push({ name: 'Liesl' }); - var doc = post.children[0]; - console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' } - doc.isNew; // true - - post.save(function (err) { - if (err) return handleError(err) - console.log('Success!'); - }); - :markdown - Sub-docs may also be created without adding them to the array by using the [create](./api.html#types_documentarray_MongooseDocumentArray-create) method of MongooseArrays. - :js - var newdoc = post.children.create({ name: 'Aaron' }); - - h3 Removing docs - :markdown - Each sub-document has it's own [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. - :js - var doc = parent.children.id(id).remove(); - parent.save(function (err) { - if (err) return handleError(err); - console.log('the sub-doc was removed') - }); - - h4#altsyntax Alternate declaration syntax - :markdown - _New in v3_ If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal: - :js - var parentSchema = new Schema({ - children: [{ name: 'string' }] - }) - - h3#next Next Up - :markdown - Now that we've covered `Sub-documents`, let's take a look at [Models](/docs/models.html). diff --git a/docs/3.1.x/docs/validation.html b/docs/3.1.x/docs/validation.html deleted file mode 100644 index e63f1112399..00000000000 --- a/docs/3.1.x/docs/validation.html +++ /dev/null @@ -1,37 +0,0 @@ -Mongoose Validation v3.1.2Fork me on GitHub

Validation

Before we get into the specifics of validation syntax, please keep the following rules in mind:

- -
  • Validation is defined in the SchemaType
  • Validation is an internal piece of middleware
  • Validation occurs when a document attempts to be saved, after defaults have been applied
  • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
  • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

Built in validators

Mongoose has several built in validators.

- -

Custom validators

Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

Validation errors

Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

var toySchema = new Schema({
-  color: String,
-  name: String
-});
-
-var Toy = db.model('Toy', toySchema);
-
-Toy.schema.path('color').validate(function (value) {
-  return /blue|green|white|red|orange|periwinkel/i.test(value);
-}, 'Invalid color');
-
-var toy = new Toy({ color: 'grease'});
-
-toy.save(function (err) {
-  // err.errors.color is a ValidatorError object
-  
-  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
-  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
-  console.log(err.errors.color.type) // prints "Invalid color"
-  console.log(err.errors.color.path) // prints "color"
-  console.log(err.name) // prints "ValidationError"
-  console.log(err.message) // prints "Validation failed"
-});
-

After a validation error, the document will also have the same errors property available:

toy.errors.color.message === err.errors.color.message
-

Next Up

Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

diff --git a/docs/3.1.x/docs/validation.jade b/docs/3.1.x/docs/validation.jade deleted file mode 100644 index 5b267bf95a5..00000000000 --- a/docs/3.1.x/docs/validation.jade +++ /dev/null @@ -1,58 +0,0 @@ -extends layout - -block content - h2 Validation - :markdown - Before we get into the specifics of validation syntax, please keep the following rules in mind: - - - Validation is defined in the [SchemaType](./schematypes.html) - - Validation is an internal piece of [middleware](./middleware.html) - - Validation occurs when a document attempts to be [saved](./api.html#model_Model-save), after defaults have been applied - - Validation is asynchronously recursive: when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed. If an error happens, your Model#save callback receives it - - Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, `"min"` is the identifier for the error triggered when a number doesn't meet the [minimum value](./api.html#schema_number_SchemaNumber-min). The path and value that triggered the error can be accessed in the `ValidationError` object - h3 Built in validators - :markdown - Mongoose has several built in validators. - - - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. - - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. - - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum) and [match](./api.html#schema_string_SchemaString-match) validators. - h3 Custom validators - :markdown - Custom validation is declared by passing a validation `function` and an error type to your `SchemaType`s validate method. Read the [API](./api.html#schematype_SchemaType-validate) docs for details on custom validators, async validators, and more. - h3 Validation errors - :markdown - Errors returned after failed validation contain an `errors` object holding the actual `ValidatorErrors`. Each [ValidatorError](./api.html#errors-validation-js) has a `type` and `path` property providing us with a little more error handling flexibility. - :js - var toySchema = new Schema({ - color: String, - name: String - }); - - var Toy = db.model('Toy', toySchema); - - Toy.schema.path('color').validate(function (value) { - return /blue|green|white|red|orange|periwinkel/i.test(value); - }, 'Invalid color'); - - var toy = new Toy({ color: 'grease'}); - - toy.save(function (err) { - // err.errors.color is a ValidatorError object - - console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color' - console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color' - console.log(err.errors.color.type) // prints "Invalid color" - console.log(err.errors.color.path) // prints "color" - console.log(err.name) // prints "ValidationError" - console.log(err.message) // prints "Validation failed" - }); - - :markdown - After a validation error, the document will also have the same `errors` property available: - :js - toy.errors.color.message === err.errors.color.message - - h3#next Next Up - :markdown - Now that we've covered `validation`, let's take a look at how you might handle advanced validation with Mongoose's [middleware](/docs/middleware.html). diff --git a/docs/3.1.x/index.html b/docs/3.1.x/index.html deleted file mode 100644 index a582e9ec15a..00000000000 --- a/docs/3.1.x/index.html +++ /dev/null @@ -1,238 +0,0 @@ -Mongoose ODM v3.1.2Fork me on GitHub

Elegant MongoDB object modeling for Node.js

Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

var mongoose = require('mongoose');
-var db = mongoose.createConnection('localhost', 'test');
-
-var schema = mongoose.Schema({ name: 'string' });
-var Cat = db.model('Cat', schema);
-
-var kitty = new Cat({ name: 'Zildjian' });
-kitty.save(function (err) {
-  if (err) // ...
-  res.end('meow');
-});

Installation

$ npm install mongoose

Getting Started

Support

diff --git a/docs/3.1.x/static.js b/docs/3.1.x/static.js deleted file mode 100644 index fc0e722dd4e..00000000000 --- a/docs/3.1.x/static.js +++ /dev/null @@ -1,17 +0,0 @@ - -var static = require('node-static'); -var server = new static.Server('.', { cache: 0 }); - -require('http').createServer(function (req, res) { - req.on('end', function () { - server.serve(req, res, function (err) { - if (err) { - console.error(err, req.url); - res.writeHead(err.status, err.headers); - res.end(); - } - }); - }); -}).listen(8088); - -console.error('now listening on localhost:8088'); diff --git a/docs/3.2.x/docs/api.html b/docs/3.2.x/docs/api.html deleted file mode 100644 index 43af3458afe..00000000000 --- a/docs/3.2.x/docs/api.html +++ /dev/null @@ -1,6828 +0,0 @@ -Mongoose API v3.2.2Fork me on GitHub
  • index.js

    Mongoose()

    Mongoose constructor.

    show code
    function Mongoose () {
    -  this.connections = [];
    -  this.plugins = [];
    -  this.models = {};
    -  this.modelSchemas = {};
    -  this.options = {};
    -  this.createConnection(); // default connection
    -};

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.


    Mongoose#set(key, value)

    Sets mongoose options

    show code
    Mongoose.prototype.set = function (key, value) {
    -  if (arguments.length == 1)
    -    return this.options[key];
    -  this.options[key] = value;
    -  return this;
    -};

    Parameters:

    Example:

    - -
    mongoose.set('test', value) // sets the 'test' option to `value`

    Mongoose#get(key)

    Gets mongoose options

    Parameters:

    Example:

    - -
    mongoose.get('test') // returns the 'test' value

    Mongoose#createConnection([uri], [options])

    Creates a Connection instance.

    show code
    Mongoose.prototype.createConnection = function () {
    -  var conn = new Connection(this);
    -  this.connections.push(conn);
    -
    -  if (arguments.length) {
    -    if (rgxReplSet.test(arguments[0])) {
    -      conn.openSet.apply(conn, arguments);
    -    } else {
    -      conn.open.apply(conn, arguments);
    -    }
    -  }
    -
    -  return conn;
    -};

    Parameters:

    • [uri] <String> a mongodb:// URI
    • [options] <Object> options to pass to the driver

    Returns:

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    - -

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    - -

    Example:

    - -
    // with mongodb:// URI
    -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
    -
    -// and options
    -var opts = { db: { native_parser: true }}
    -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
    -
    -// replica sets
    -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
    -
    -// and options
    -var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
    -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
    -
    -// with [host, database_name[, port] signature
    -db = mongoose.createConnection('localhost', 'database', port)
    -
    -// and options
    -var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
    -db = mongoose.createConnection('localhost', 'database', port, opts)
    -
    -// initialize now, connect later
    -db = mongoose.createConnection();
    -db.open('localhost', 'database', port, [opts]);

    Mongoose#connect()

    Opens the default mongoose connection.

    show code
    Mongoose.prototype.connect = function () {
    -  var conn = this.connection;
    -
    -  if (rgxReplSet.test(arguments[0])) {
    -    conn.openSet.apply(conn, arguments);
    -  } else {
    -    conn.open.apply(conn, arguments);
    -  }
    -
    -  return this;
    -};

    Returns:

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


    Mongoose#disconnect([fn])

    Disconnects all connections.

    show code
    Mongoose.prototype.disconnect = function (fn) {
    -  var count = this.connections.length
    -    , error
    -
    -  this.connections.forEach(function(conn){
    -    conn.close(function(err){
    -      if (error) return;
    -
    -      if (err) {
    -        error = err;
    -        if (fn) return fn(err);
    -        throw err;
    -      }
    -
    -      if (fn)
    -        --count || fn();
    -    });
    -  });
    -  return this;
    -};

    Parameters:

    • [fn] <Function> called after all connection close.

    Returns:


    Mongoose#model(name, [schema], [collection], [skipInit])

    Defines a model or retrieves it.

    show code
    Mongoose.prototype.model = function (name, schema, collection, skipInit) {
    -  // normalize collection
    -  if (!(schema instanceof Schema)) {
    -    collection = schema;
    -    schema = false;
    -  }
    -
    -  if ('boolean' === typeof collection) {
    -    skipInit = collection;
    -    collection = null;
    -  }
    -
    -  // look up models for the collection
    -  if (!this.modelSchemas[name]) {
    -    if (!schema && name in SchemaDefaults) {
    -      schema = SchemaDefaults[name];
    -    }
    -
    -    if (schema) {
    -      this.modelSchemas[name] = schema;
    -      for (var i = 0, l = this.plugins.length; i < l; i++) {
    -        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
    -      }
    -    } else {
    -      throw new Error('Schema hasn\'t been registered for model "' + name + '".
    -'
    -                    + 'Use mongoose.model(name, schema)');
    -    }
    -  }
    -
    -  if (!this.models[name]) {
    -    schema || (schema = this.modelSchemas[name]);
    -    collection || (collection = schema.set('collection') || format(name));
    -
    -    var model = Model.compile(name
    -                        , this.modelSchemas[name]
    -                        , collection
    -                        , this.connection
    -                        , this);
    -
    -    if (!skipInit) model.init();
    -
    -    this.models[name] = model;
    -  }
    -
    -  return this.models[name];
    -};

    Parameters:

    • name <String> model name
    • [schema] <Schema>
    • [collection] <String> name (optional, induced from model name)
    • [skipInit] <Boolean> whether to skip initialization (defaults to false)

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -
    -// define an Actor model with this mongoose instance
    -mongoose.model('Actor', new Schema({ name: String }));
    -
    -// create a new connection
    -var conn = mongoose.createConnection(..);
    -
    -// retrieve the Actor model
    -var Actor = conn.model('Actor');
    - -

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    - -

    Example:

    - -
    var schema = new Schema({ name: String });
    -schema.set('collection', 'actor');

    Mongoose#plugin(fn, [opts])

    Declares a global plugin executed on all Schemas.

    show code
    Mongoose.prototype.plugin = function (fn, opts) {
    -  this.plugins.push([fn, opts]);
    -  return this;
    -};

    Parameters:

    Returns:

    Equivalent to calling .plugin(fn) on each Schema you create.


    module.exports

    The exports object is an instance of Mongoose.

    show code
    module.exports = exports = new Mongoose;
    -var mongoose = module.exports;

    mongoose.Collection

    The Mongoose Collection constructor

    show code
    mongoose.Collection = Collection;

    mongoose.Connection

    The Mongoose Connection constructor

    show code
    mongoose.Connection = Connection;

    mongoose.version

    Mongoose version

    show code
    mongoose.version = JSON.parse(
    -  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
    -).version;

    mongoose.Mongoose

    The Mongoose constructor

    show code
    mongoose.Mongoose = Mongoose;

    The exports of the mongoose module is an instance of this class.

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -var mongoose2 = new mongoose.Mongoose();

    mongoose.Schema

    The Mongoose Schema constructor

    show code
    mongoose.Schema = Schema;

    Example:

    - -
    var mongoose = require('mongoose');
    -var Schema = mongoose.Schema;
    -var CatSchema = new Schema(..);

    mongoose.SchemaType

    The Mongoose SchemaType constructor.

    show code
    mongoose.SchemaType = SchemaType;

    mongoose.SchemaTypes

    The various Mongoose SchemaTypes.

    show code
    mongoose.SchemaTypes = Schema.Types;

    Note:

    - -

    Alias of mongoose.Schema.Types for backwards compatibility.


    mongoose.VirtualType

    The Mongoose VirtualType constructor.

    show code
    mongoose.VirtualType = VirtualType;

    mongoose.Types

    The various Mongoose Types.

    show code
    mongoose.Types = Types;

    Example:

    - -
    var mongoose = require('mongoose');
    -var array = mongoose.Types.Array;
    - -

    Types:

    - -
      -
    • Array
    • -
    • Buffer
    • -
    • Document
    • -
    • Embedded
    • -
    • DocumentArray
    • -
    • ObjectId
    • -
    - -

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    - -
    var ObjectId = mongoose.Types.ObjectId;
    -var id1 = new ObjectId;

    mongoose.Query

    The Mongoose Query constructor.

    show code
    mongoose.Query = Query;

    mongoose.Promise

    The Mongoose Promise constructor.

    show code
    mongoose.Promise = Promise;

    mongoose.Model

    The Mongoose Model constructor.

    show code
    mongoose.Model = Model;

    mongoose.Document

    The Mongoose Document constructor.

    show code
    mongoose.Document = Document;

    mongoose.Error

    The MongooseError constructor.

    show code
    mongoose.Error = require('./error');

    mongoose.mongo

    The node-mongodb-native driver Mongoose uses.

    show code
    mongoose.mongo = require('mongodb');

    Mongoose#connection

    The default connection of the mongoose module.

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -mongoose.connect(...);
    -mongoose.connection.on('error', cb);
    - -

    This is the connection used by default for every model created using mongoose.model.

    Returns:


  • collection.js

    Collection(name, conn, opts)

    Abstract Collection constructor

    show code
    function Collection (name, conn, opts) {
    -  this.name = name;
    -  this.conn = conn;
    -  this.buffer = true;
    -  this.queue = [];
    -
    -  if ('number' == typeof opts) opts = { size: opts };
    -  this.opts = opts || {};
    -
    -  if (STATES.connected == this.conn.readyState) {
    -    this.onOpen();
    -  }
    -};

    Parameters:

    • name <String> name of the collection
    • conn <Connection> A MongooseConnection instance
    • opts <Object> optional collection options

    This is the base class that drivers inherit from and implement.


    Collection#onOpen()

    Called when the database connects

    show code
    Collection.prototype.onOpen = function () {
    -  var self = this;
    -  this.buffer = false;
    -  self.doQueue();
    -};

    Collection#onClose()

    Called when the database disconnects

    show code
    Collection.prototype.onClose = function () {
    -  this.buffer = true;
    -};

    Collection#addQueue(name, args)

    Queues a method for later execution when its
    database connection opens.

    show code
    Collection.prototype.addQueue = function (name, args) {
    -  this.queue.push([name, args]);
    -  return this;
    -};

    Parameters:

    • name <String> name of the method to queue
    • args <Array> arguments to pass to the method when executed

    Collection#doQueue()

    Executes all queued methods and clears the queue.

    show code
    Collection.prototype.doQueue = function () {
    -  for (var i = 0, l = this.queue.length; i < l; i++){
    -    this[this.queue[i][0]].apply(this, this.queue[i][1]);
    -  }
    -  this.queue = [];
    -  return this;
    -};

    Collection#ensureIndex()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.ensureIndex = function(){
    -  throw new Error('Collection#ensureIndex unimplemented by driver');
    -};

    Collection#findAndModify()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findAndModify = function(){
    -  throw new Error('Collection#findAndModify unimplemented by driver');
    -};

    Collection#findOne()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findOne = function(){
    -  throw new Error('Collection#findOne unimplemented by driver');
    -};

    Collection#find()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.find = function(){
    -  throw new Error('Collection#find unimplemented by driver');
    -};

    Collection#insert()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.insert = function(){
    -  throw new Error('Collection#insert unimplemented by driver');
    -};

    Collection#save()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.save = function(){
    -  throw new Error('Collection#save unimplemented by driver');
    -};

    Collection#update()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.update = function(){
    -  throw new Error('Collection#update unimplemented by driver');
    -};

    Collection#getIndexes()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.getIndexes = function(){
    -  throw new Error('Collection#getIndexes unimplemented by driver');
    -};

    Collection#mapReduce()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.mapReduce = function(){
    -  throw new Error('Collection#mapReduce unimplemented by driver');
    -};

    Collection#conn

    The Connection instance


    Collection#name

    The collection name


  • connection.js

    Connection(base)

    Connection constructor

    show code
    function Connection (base) {
    -  this.base = base;
    -  this.collections = {};
    -  this.models = {};
    -  this.replica = false;
    -  this.host = null;
    -  this.port = null;
    -  this.user = null;
    -  this.pass = null;
    -  this.name = null;
    -  this.options = null;
    -  this._readyState = STATES.disconnected;
    -  this._closeCalled = false;
    -  this._hasOpened = false;
    -};

    Parameters:

    Events:

    • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

    • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

    • open: Emitted after we connected and onOpen is executed on all of this connections models.

    • disconnecting: Emitted when connection.close() was executed.

    • disconnected: Emitted after getting disconnected from the db.

    • close: Emitted after we disconnected and onClose executed on all of this connections models.

    • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

    • error: Emitted when an error occurs on this connection.

    • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

    For practical reasons, a Connection equals a Db.


    Connection#open(connection_string, [database], [port], [options], [callback])

    Opens the connection to MongoDB.

    show code
    Connection.prototype.open = function (host, database, port, options, callback) {
    -  var self = this
    -    , uri;
    -
    -  if ('string' === typeof database) {
    -    switch (arguments.length) {
    -      case 2:
    -        port = 27017;
    -      case 3:
    -        switch (typeof port) {
    -          case 'function':
    -            callback = port, port = 27017;
    -            break;
    -          case 'object':
    -            options = port, port = 27017;
    -            break;
    -        }
    -        break;
    -      case 4:
    -        if ('function' === typeof options)
    -          callback = options, options = {};
    -    }
    -  } else {
    -    switch (typeof database) {
    -      case 'function':
    -        callback = database, database = undefined;
    -        break;
    -      case 'object':
    -        options = database;
    -        database = undefined;
    -        callback = port;
    -        break;
    -    }
    -
    -    if (!rgxProtocol.test(host)) {
    -      host = 'mongodb://' + host;
    -    }
    -
    -    uri = url.parse(host);
    -    host = uri.hostname;
    -    port = uri.port || 27017;
    -    database = uri.pathname && uri.pathname.replace(/\//g, '');
    -  }
    -
    -  this.options = this.defaultOptions(options);
    -
    -  // make sure we can open
    -  if (STATES.disconnected !== this.readyState) {
    -    var err = new Error('Trying to open unclosed connection.');
    -    err.state = this.readyState;
    -    this.error(err, callback);
    -    return this;
    -  }
    -
    -  if (!host) {
    -    this.error(new Error('Missing connection hostname.'), callback);
    -    return this;
    -  }
    -
    -  if (!database) {
    -    this.error(new Error('Missing connection database.'), callback);
    -    return this;
    -  }
    -
    -  // handle authentication
    -  if (uri && uri.auth) {
    -    var auth = uri.auth.split(':');
    -    this.user = auth[0];
    -    this.pass = auth[1];
    -
    -  // Check hostname for user/pass
    -  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
    -    host = host.split('@');
    -    var auth = host.shift().split(':');
    -    host = host.pop();
    -    this.user = auth[0];
    -    this.pass = auth[1];
    -
    -  // user/pass options
    -  } else if (options && options.user && options.pass) {
    -    this.user = options.user;
    -    this.pass = options.pass;
    -
    -  } else {
    -    this.user = this.pass = undefined;
    -  }
    -
    -  this.name = database;
    -  this.host = host;
    -  this.port = port;
    -
    -  this._open(callback);
    -  return this;
    -};

    Parameters:

    • connection_string <String> mongodb://uri or the host to which you are connecting
    • [database] <String> database name
    • [port] <Number> database port
    • [options] <Object> options
    • [callback] <Function>

    options is a hash with the following possible properties:

    - -
    db      - passed to the connection db instance
    -server  - passed to the connection server instance(s)
    -replset - passed to the connection ReplSet instance
    -user    - username for authentication
    -pass    - password for authentication
    - -

    Notes:

    - -

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.


    Connection#openSet(uris, [database], [options], [callback])

    Connects to a replica set.

    show code
    Connection.prototype.openSet = function (uris, database, options, callback) {
    -  var uris = uris.split(',')
    -    , self = this;
    -
    -  switch (arguments.length) {
    -    case 3:
    -      this.name = database;
    -      if ('function' === typeof options) callback = options, options = {};
    -      break;
    -    case 2:
    -      switch (typeof database) {
    -        case 'string':
    -          this.name = database;
    -        case 'function':
    -          callback = database, database = null;
    -          break;
    -        case 'object':
    -          options = database, database = null;
    -          break;
    -      }
    -  }
    -
    -  this.options = options = this.defaultOptions(options);
    -
    -  if (uris.length < 2) {
    -    this.error(new Error('Please provide comma-separated URIs'), callback);
    -    return this;
    -  }
    -
    -  this.replica = true;
    -  this.host = [];
    -  this.port = [];
    -
    -  uris.forEach(function (uri) {
    -    // handle missing protocols
    -    if (!rgxProtocol.test(uri))
    -      uri = 'mongodb://' + uri;
    -
    -    var uri = url.parse(uri);
    -
    -    self.host.push(uri.hostname);
    -    self.port.push(uri.port || 27017);
    -
    -    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
    -      self.name = uri.pathname.replace(/\//g, '');
    -
    -    if (!self.user && uri.auth) {
    -      var auth = uri.auth.split(':');
    -      self.user = auth[0];
    -      self.pass = auth[1];
    -    }
    -  });
    -
    -  if (!this.name) {
    -    this.error(new Error('No database name provided for replica set'), callback);
    -    return this;
    -  }
    -
    -  this._open(callback);
    -  return this;
    -};

    Parameters:

    • uris <String> comma-separated mongodb:// `URI`s
    • [database] <String> database name if not included in `uris`
    • [options] <Object> passed to the internal driver
    • [callback] <Function>

    Example:

    - -
    var db = mongoose.createConnection();
    -db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
    - -

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    - -

    Valid options

    - -
    db      - passed to the connection db instance
    -server  - passed to the connection server instance(s)
    -replset - passed to the connection ReplSetServer instance
    -user    - username for authentication
    -pass    - password for authentication

    Connection#error(err, callback)

    error

    show code
    Connection.prototype.error = function (err, callback) {
    -  if (callback) return callback(err);
    -  this.emit('error', err);
    -}

    Parameters:

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.


    Connection#_open(callback)

    Handles opening the connection with the appropriate method based on connection type.

    show code
    Connection.prototype._open = function (callback) {
    -  this.readyState = STATES.connecting;
    -  this._closeCalled = false;
    -
    -  var self = this;
    -
    -  var method = this.replica
    -    ? 'doOpenSet'
    -    : 'doOpen';
    -
    -  // open connection
    -  this[method](function (err) {
    -    if (err) {
    -      self.readyState = STATES.disconnected;
    -      if (self._hasOpened) {
    -        if (callback) callback(err);
    -      } else {
    -        self.error(err, callback);
    -      }
    -      return;
    -    }
    -
    -    self.onOpen();
    -    callback && callback();
    -  });
    -}

    Parameters:


    Connection#onOpen()

    Called when the connection is opened

    show code
    Connection.prototype.onOpen = function () {
    -  var self = this;
    -
    -  function open () {
    -    self.readyState = STATES.connected;
    -
    -    // avoid having the collection subscribe to our event emitter
    -    // to prevent 0.3 warning
    -    for (var i in self.collections)
    -      self.collections[i].onOpen();
    -
    -    self.emit('open');
    -  };
    -
    -  // re-authenticate
    -  if (self.user && self.pass)
    -    self.db.authenticate(self.user, self.pass, open);
    -  else
    -    open();
    -};

    Connection#close([callback])

    Closes the connection

    show code
    Connection.prototype.close = function (callback) {
    -  var self = this;
    -  this._closeCalled = true;
    -
    -  switch (this.readyState){
    -    case 0: // disconnected
    -      callback && callback();
    -      break;
    -
    -    case 1: // connected
    -      this.readyState = STATES.disconnecting;
    -      this.doClose(function(err){
    -        if (err){
    -          self.error(err, callback);
    -        } else {
    -          self.onClose();
    -          callback && callback();
    -        }
    -      });
    -      break;
    -
    -    case 2: // connecting
    -      this.once('open', function(){
    -        self.close(callback);
    -      });
    -      break;
    -
    -    case 3: // disconnecting
    -      if (!callback) break;
    -      this.once('close', function () {
    -        callback();
    -      });
    -      break;
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Connection#onClose()

    Called when the connection closes

    show code
    Connection.prototype.onClose = function () {
    -  this.readyState = STATES.disconnected;
    -
    -  // avoid having the collection subscribe to our event emitter
    -  // to prevent 0.3 warning
    -  for (var i in this.collections)
    -    this.collections[i].onClose();
    -
    -  this.emit('close');
    -};

    Connection#collection(name, [options])

    Retrieves a collection, creating it if not cached.

    show code
    Connection.prototype.collection = function (name, options) {
    -  if (!(name in this.collections))
    -    this.collections[name] = new Collection(name, this, options);
    -  return this.collections[name];
    -};

    Parameters:

    • name <String> of the collection
    • [options] <Object> optional collection options

    Returns:


    Connection#model(name, [schema], [collection])

    Defines or retrieves a model.

    show code
    Connection.prototype.model = function (name, schema, collection) {
    -  if (!this.models[name]) {
    -    var model = this.base.model(name, schema, collection, true)
    -      , Model
    -
    -    if (this != model.prototype.db) {
    -      // subclass model using this connection and collection name
    -      Model = function Model (doc, fields, skipId) {
    -        if (!(this instanceof Model))
    -          return new Model(doc, fields, skipId);
    -        model.call(this, doc, fields, skipId);
    -      };
    -
    -      Model.__proto__ = model;
    -      Model.prototype.__proto__ = model.prototype;
    -      Model.db = Model.prototype.db = this;
    -
    -      // collection name discovery
    -      if ('string' === typeof schema) {
    -        collection = schema;
    -      }
    -
    -      if (!collection) {
    -        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
    -      }
    -
    -      var s = 'string' != typeof schema
    -        ? schema
    -        : model.prototype.schema;
    -
    -      Model.prototype.collection = this.collection(collection, s && s.options.capped);
    -      Model.collection = Model.prototype.collection;
    -      Model.init();
    -    }
    -
    -    this.models[name] = Model || model;
    -  }
    -
    -  return this.models[name];
    -};

    Parameters:

    • name <String> the model name
    • [schema] <Schema> a schema. necessary when defining a model
    • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

    Returns:

    • <Model> The compiled model
    var mongoose = require('mongoose');
    -var db = mongoose.createConnection(..);
    -db.model('Venue', new Schema(..));
    -var Ticket = db.model('Ticket', new Schema(..));
    -var Venue = db.model('Venue');

    Connection#setProfiling(level, [ms], callback)

    Set profiling level.

    show code
    Connection.prototype.setProfiling = function (level, ms, callback) {
    -  if (STATES.connected !== this.readyState) {
    -    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
    -  }
    -
    -  if (!callback) callback = ms, ms = 100;
    -
    -  var cmd = {};
    -
    -  switch (level) {
    -    case 0:
    -    case 'off':
    -      cmd.profile = 0;
    -      break;
    -    case 1:
    -    case 'slow':
    -      cmd.profile = 1;
    -      if ('number' !== typeof ms) {
    -        ms = parseInt(ms, 10);
    -        if (isNaN(ms)) ms = 100;
    -      }
    -      cmd.slowms = ms;
    -      break;
    -    case 2:
    -    case 'all':
    -      cmd.profile = 2;
    -      break;
    -    default:
    -      return callback(new Error('Invalid profiling level: '+ level));
    -  }
    -
    -  this.db.executeDbCommand(cmd, function (err, resp) {
    -    if (err) return callback(err);
    -
    -    var doc = resp.documents[0];
    -
    -    err = 1 === doc.ok
    -      ? null
    -      : new Error('Could not set profiling level to: '+ level)
    -
    -    callback(err, doc);
    -  });
    -};

    Parameters:

    • level <Number, String> either off (0), slow (1), or all (2)
    • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
    • callback <Function>

    Connection#defaultOptions(options)

    Prepares default connection options.

    show code
    Connection.prototype.defaultOptions = function (options) {
    -  var o = options || {};
    -
    -  o.server = o.server || {};
    -
    -  if (!('auto_reconnect' in o.server)) {
    -    o.server.auto_reconnect = true;
    -  }
    -
    -  o.db || (o.db = {});
    -  o.db.forceServerObjectId = false;
    -
    -  // TODO default to true once the driver is fixed
    -  if (!('safe' in o.db)) o.db.safe = false;
    -
    -  return o;
    -}

    Parameters:


    Connection#db

    The mongodb.Db instance, set when the connection is opened


    Connection#collections

    A hash of the collections associated with this connection


    Connection#readyState

    Connection ready state

    - -
      -
    • 0 = disconnected
    • -
    • 1 = connected
    • -
    • 2 = connecting
    • -
    • 3 = disconnecting
    • -
    - -

    Each state change emits its associated event name.

    - -

    Example

    - -
    conn.on('connected', callback);
    -conn.on('disconnected', callback);

  • document.js

    Document(obj, [fields], [skipId])

    Document constructor.

    show code
    function Document (obj, fields, skipId) {
    -  // node <0.4.3 bug
    -  if (!this._events) this._events = {};
    -  this.setMaxListeners(0);
    -
    -  if ('boolean' === typeof fields) {
    -    this._strictMode = fields;
    -    this._selected = fields = undefined;
    -  } else {
    -    this._strictMode = this.schema.options && this.schema.options.strict;
    -    this._selected = fields;
    -  }
    -
    -  this.isNew = true;
    -  this.errors = undefined;
    -  this._shardval = undefined;
    -  this._saveError = undefined;
    -  this._validationError = undefined;
    -  this._adhocPaths = undefined;
    -  this._removing = undefined;
    -  this._inserting = undefined;
    -  this.__version = undefined;
    -  this.__getters = {};
    -  this.__id = undefined;
    -
    -  this._activePaths = new ActiveRoster;
    -
    -  var required = this.schema.requiredPaths();
    -  for (var i = 0; i < required.length; ++i) {
    -    this._activePaths.require(required[i]);
    -  }
    -
    -  this._doc = this._buildDoc(obj, fields, skipId);
    -  if (obj) this.set(obj, undefined, true);
    -  this._registerHooks();
    -};

    Parameters:

    • obj <Object> the values to set
    • [fields] <Object> the fields which were selected in the query returning this document
    • [skipId] <Boolean> bool, should we auto create an ObjectId _id

    Events:

    • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

    • save: Emitted when the document is successfully saved


    Document#_buildDoc(obj, [fields], [skipId])

    Builds the default doc structure

    show code
    Document.prototype._buildDoc = function (obj, fields, skipId) {
    -  var doc = {}
    -    , self = this
    -    , exclude
    -    , keys
    -    , key
    -    , ki
    -
    -  // determine if this doc is a result of a query with
    -  // excluded fields
    -  if (fields && 'Object' === fields.constructor.name) {
    -    keys = Object.keys(fields);
    -    ki = keys.length;
    -
    -    while (ki--) {
    -      if ('_id' !== keys[ki]) {
    -        exclude = 0 === fields[keys[ki]];
    -        break;
    -      }
    -    }
    -  }
    -
    -  var paths = Object.keys(this.schema.paths)
    -    , plen = paths.length
    -    , ii = 0
    -
    -  for (; ii < plen; ++ii) {
    -    var p = paths[ii];
    -
    -    if ('_id' == p) {
    -      if (skipId) continue;
    -      if (obj && '_id' in obj) continue;
    -    }
    -
    -    var type = this.schema.paths[p]
    -      , path = p.split('.')
    -      , len = path.length
    -      , last = len-1
    -      , doc_ = doc
    -      , i = 0
    -
    -    for (; i < len; ++i) {
    -      var piece = path[i]
    -        , def
    -
    -      if (i === last) {
    -        if (fields) {
    -          if (exclude) {
    -            // apply defaults to all non-excluded fields
    -            if (p in fields) continue;
    -
    -            def = type.getDefault(self, true);
    -            if ('undefined' !== typeof def) {
    -              doc_[piece] = def;
    -              self._activePaths.default(p);
    -            }
    -
    -          } else if (p in fields) {
    -            // selected field
    -            def = type.getDefault(self, true);
    -            if ('undefined' !== typeof def) {
    -              doc_[piece] = def;
    -              self._activePaths.default(p);
    -            }
    -          }
    -        } else {
    -          def = type.getDefault(self, true);
    -          if ('undefined' !== typeof def) {
    -            doc_[piece] = def;
    -            self._activePaths.default(p);
    -          }
    -        }
    -      } else {
    -        doc_ = doc_[piece] || (doc_[piece] = {});
    -      }
    -    }
    -  };
    -
    -  return doc;
    -};

    Parameters:

    Returns:


    Document#init(doc, fn)

    Initializes the document without setters or marking anything modified.

    show code
    Document.prototype.init = function (doc, fn) {
    -  this.isNew = false;
    -
    -  init(this, doc, this._doc);
    -  this._storeShard();
    -
    -  this.emit('init');
    -  if (fn) fn(null);
    -  return this;
    -};

    Parameters:

    Called internally after a document is returned from mongodb.


    Document#_storeShard()

    Stores the current values of the shard keys.

    show code
    Document.prototype._storeShard = function _storeShard () {
    -  // backwards compat
    -  var key = this.schema.options.shardKey || this.schema.options.shardkey;
    -  if (!(key && 'Object' == key.constructor.name)) return;
    -
    -  var orig = this._shardval = {}
    -    , paths = Object.keys(key)
    -    , len = paths.length
    -    , val
    -
    -  for (var i = 0; i < len; ++i) {
    -    val = this.getValue(paths[i]);
    -    if (isMongooseObject(val)) {
    -      orig[paths[i]] = val.toObject({ depopulate: true })
    -    } else if (null != val && val.valueOf) {
    -      orig[paths[i]] = val.valueOf();
    -    } else {
    -      orig[paths[i]] = val;
    -    }
    -  }
    -}

    Note:

    - -

    Shard key values do not / are not allowed to change.


    Document#update(doc, options, callback)

    Sends an update command with this document _id as the query selector.

    show code
    Document.prototype.update = function update () {
    -  var args = utils.args(arguments);
    -  args.unshift({_id: this._id});
    -  this.constructor.update.apply(this.constructor, args);
    -}

    Parameters:

    Returns:

    Example:

    - -
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
    - -

    Valid options:

    - -
      -
    • safe safe mode (defaults to value set in schema (true))
    • -
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • -

    Document#set(path, val, [type])

    Sets the value of a path, or many paths.

    show code
    Document.prototype.set = function (path, val, type) {
    -  var constructing = true === type
    -    , adhoc = type && true !== type
    -    , adhocs
    -
    -  if (adhoc) {
    -    adhocs = this._adhocPaths || (this._adhocPaths = {});
    -    adhocs[path] = Schema.interpretAsType(path, type);
    -  }
    -
    -  if ('string' !== typeof path) {
    -    // new Document({ key: val })
    -
    -    if (null === path || undefined === path) {
    -      var _ = path;
    -      path = val;
    -      val = _;
    -
    -    } else {
    -      var prefix = val
    -        ? val + '.'
    -        : '';
    -
    -      if (path instanceof Document) path = path._doc;
    -
    -      var keys = Object.keys(path)
    -        , i = keys.length
    -        , pathtype
    -        , key
    -
    -      while (i--) {
    -        key = keys[i];
    -        if (null != path[key] && 'Object' === path[key].constructor.name
    -          && !(this._path(prefix + key) instanceof MixedSchema)) {
    -          this.set(path[key], prefix + key, constructing);
    -        } else if (this._strictMode) {
    -          pathtype = this.schema.pathType(prefix + key);
    -          if ('real' === pathtype || 'virtual' === pathtype) {
    -            this.set(prefix + key, path[key], constructing);
    -          } else if ('throw' == this._strictMode) {
    -            throw new Error("Field `" + key + "` is not in schema.");
    -          }
    -        } else if (undefined !== path[key]) {
    -          this.set(prefix + key, path[key], constructing);
    -        }
    -      }
    -
    -      return this;
    -    }
    -  }
    -
    -  // ensure _strict is honored for obj props
    -  // docschema = new Schema({ path: { nest: 'string' }})
    -  // doc.set('path', obj);
    -  var pathType = this.schema.pathType(path);
    -  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
    -    this.setValue(path, null);
    -    this.set(val, path, constructing);
    -    return this;
    -  }
    -
    -  var schema;
    -  if ('adhocOrUndefined' == pathType && this._strictMode) {
    -    return this;
    -  } else if ('virtual' == pathType) {
    -    schema = this.schema.virtualpath(path);
    -    schema.applySetters(val, this);
    -    return this;
    -  } else {
    -    schema = this._path(path);
    -  }
    -
    -  var parts = path.split('.')
    -    , pathToMark
    -
    -  // When using the $set operator the path to the field must already exist.
    -  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
    -
    -  if (parts.length <= 1) {
    -    pathToMark = path;
    -  } else {
    -    for (var i = 0; i < parts.length; ++i) {
    -      var part = parts[i];
    -      var subpath = parts.slice(0, i).concat(part).join('.');
    -      if (this.isDirectModified(subpath) // earlier prefixes that are already
    -                                         // marked as dirty have precedence
    -          || this.get(subpath) === null) {
    -        pathToMark = subpath;
    -        break;
    -      }
    -    }
    -
    -    if (!pathToMark) pathToMark = path;
    -  }
    -
    -  if (!schema || null === val || undefined === val) {
    -    this._set(pathToMark, path, constructing, parts, schema, val);
    -    return this;
    -  }
    -
    -  var self = this;
    -
    -  // if this doc is being constructed we should not
    -  // trigger getters.
    -  var priorVal = constructing
    -    ? undefined
    -    : this.get(path);
    -
    -  var shouldSet = this.try(function(){
    -    val = schema.applySetters(val, self, false, priorVal);
    -  });
    -
    -  if (shouldSet) {
    -    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
    -  }
    -
    -  return this;
    -}

    Parameters:

    Example:

    - -
    // path, value
    -doc.set(path, value)
    -
    -// object
    -doc.set({
    -    path  : value
    -  , path2 : {
    -       path  : value
    -    }
    -})
    -
    -// only-the-fly cast to number
    -doc.set(path, value, Number)
    -
    -// only-the-fly cast to string
    -doc.set(path, value, String)

    Document#_set()

    Handles the actual setting of the value and marking the path modified if appropriate.

    show code
    Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {
    -  if (this.isNew) {
    -    this.markModified(pathToMark);
    -  } else {
    -
    -    priorVal || (priorVal = this.get(path));
    -
    -    if (!this.isDirectModified(pathToMark)) {
    -      if (undefined === val && !this.isSelected(path)) {
    -        // special case:
    -        // when a path is not selected in a query its initial
    -        // value will be undefined.
    -        this.markModified(pathToMark, priorVal);
    -      } else if (undefined === val && path in this._activePaths.states.default) {
    -        // do nothing
    -        // unsetting the default value which was never saved
    -      } else if (!deepEqual(val, priorVal)) {
    -        this.markModified(pathToMark, priorVal);
    -      } else if (!constructing &&
    -                 null != val &&
    -                 path in this._activePaths.states.default &&
    -                 deepEqual(val, schema.getDefault(this, constructing))) {
    -        // special case:
    -        // a path with a default was $unset on the server
    -        // and the user is setting it to the same value again
    -        this.markModified(pathToMark, priorVal);
    -      }
    -    }
    -  }
    -
    -  var obj = this._doc
    -    , i = 0
    -    , l = parts.length
    -
    -  for (; i < l; i++) {
    -    var next = i + 1
    -      , last = next === l;
    -
    -    if (last) {
    -      obj[parts[i]] = val;
    -    } else {
    -      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
    -        obj = obj[parts[i]];
    -      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
    -        obj = obj[parts[i]];
    -      } else {
    -        obj = obj[parts[i]] = {};
    -      }
    -    }
    -  }
    -};

    Document#getValue(path)

    Gets a raw value from a path (no getters)

    show code
    Document.prototype.getValue = function (path) {
    -  var parts = path.split('.')
    -    , obj = this._doc
    -    , part;
    -
    -  for (var i = 0, l = parts.length; i < l; i++) {
    -    part = parts[i];
    -    obj = obj.getValue
    -        ? obj.getValue(part) // If we have an embedded array document member
    -        : obj[part];
    -    if (!obj) return obj;
    -  }
    -
    -  return obj;
    -}

    Parameters:


    Document#setValue(path, value)

    Sets a raw value for a path (no casting, setters, transformations)

    show code
    Document.prototype.setValue = function (path, val) {
    -  var parts = path.split('.')
    -    , obj = this._doc;
    -
    -  for (var i = 0, len = parts.length-1; i < len; i++) {
    -    obj = obj[parts[i]];
    -  }
    -
    -  obj[parts[len]] = val;
    -  return this;
    -};

    Parameters:


    Document#get(path, [type])

    Returns the value of a path.

    show code
    Document.prototype.get = function (path, type) {
    -  var adhocs;
    -  if (type) {
    -    adhocs = this._adhocPaths || (this._adhocPaths = {});
    -    adhocs[path] = Schema.interpretAsType(path, type);
    -  }
    -
    -  var schema = this._path(path) || this.schema.virtualpath(path)
    -    , pieces = path.split('.')
    -    , obj = this._doc;
    -
    -  for (var i = 0, l = pieces.length; i < l; i++) {
    -    obj = null == obj ? null : obj[pieces[i]];
    -  }
    -
    -  if (schema) {
    -    obj = schema.applyGetters(obj, this);
    -  }
    -
    -  return obj;
    -};

    Parameters:

    Example

    - -
    // path
    -doc.get('age') // 47
    -
    -// dynamic casting to a string
    -doc.get('age', String) // "47"

    Document#_path(path)

    Returns the schematype for the given path.

    show code
    Document.prototype._path = function (path) {
    -  var adhocs = this._adhocPaths
    -    , adhocType = adhocs && adhocs[path];
    -
    -  if (adhocType) {
    -    return adhocType;
    -  } else {
    -    return this.schema.path(path);
    -  }
    -};

    Parameters:


    Document#markModified(path)

    Marks the path as having pending changes to write to the db.

    show code
    Document.prototype.markModified = function (path) {
    -  this._activePaths.modify(path);
    -};

    Parameters:

    • path <String> the path to mark modified

    Very helpful when using Mixed types.

    - -

    Example:

    - -
    doc.mixed.type = 'changed';
    -doc.markModified('mixed.type');
    -doc.save() // changes to mixed.type are now persisted

    Document#try(fn, scope)

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    show code
    Document.prototype.try = function (fn, scope) {
    -  var res;
    -  try {
    -    fn.call(scope);
    -    res = true;
    -  } catch (e) {
    -    this._error(e);
    -    res = false;
    -  }
    -  return res;
    -};

    Parameters:

    • fn <Function> function to execute
    • scope <Object> the scope with which to call fn

    Document#modifiedPaths()

    Returns the list of paths that have been modified.

    show code
    Document.prototype.modifiedPaths = function () {
    -  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
    -
    -  return directModifiedPaths.reduce(function (list, path) {
    -    var parts = path.split('.');
    -    return list.concat(parts.reduce(function (chains, part, i) {
    -      return chains.concat(parts.slice(0, i).concat(part).join('.'));
    -    }, []));
    -  }, []);
    -};

    Returns:


    Document#isModified([path])

    Returns true if this document was modified, else false.

    show code
    Document.prototype.isModified = function (path) {
    -  return path
    -    ? !!~this.modifiedPaths().indexOf(path)
    -    : this._activePaths.some('modify');
    -};

    Parameters:

    Returns:

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    - -

    Example

    - -
    doc.set('documents.0.title', 'changed');
    -doc.isModified()                    // true
    -doc.isModified('documents')         // true
    -doc.isModified('documents.0.title') // true
    -doc.isDirectModified('documents')   // false

    Document#isDirectModified(path)

    Returns true if path was directly set and modified, else false.

    show code
    Document.prototype.isDirectModified = function (path) {
    -  return (path in this._activePaths.states.modify);
    -};

    Parameters:

    Returns:

    Example

    - -
    doc.set('documents.0.title', 'changed');
    -doc.isDirectModified('documents.0.title') // true
    -doc.isDirectModified('documents') // false

    Document#isInit(path)

    Checks if path was initialized.

    show code
    Document.prototype.isInit = function (path) {
    -  return (path in this._activePaths.states.init);
    -};

    Parameters:

    Returns:


    Document#isSelected(path)

    Checks if path was selected in the source query which initialized this document.

    show code
    Document.prototype.isSelected = function isSelected (path) {
    -  if (this._selected) {
    -
    -    if ('_id' === path) {
    -      return 0 !== this._selected._id;
    -    }
    -
    -    var paths = Object.keys(this._selected)
    -      , i = paths.length
    -      , inclusive = false
    -      , cur
    -
    -    if (1 === i && '_id' === paths[0]) {
    -      // only _id was selected.
    -      return 0 === this._selected._id;
    -    }
    -
    -    while (i--) {
    -      cur = paths[i];
    -      if ('_id' == cur) continue;
    -      inclusive = !! this._selected[cur];
    -      break;
    -    }
    -
    -    if (path in this._selected) {
    -      return inclusive;
    -    }
    -
    -    i = paths.length;
    -    var pathDot = path + '.';
    -
    -    while (i--) {
    -      cur = paths[i];
    -      if ('_id' == cur) continue;
    -
    -      if (0 === cur.indexOf(pathDot)) {
    -        return inclusive;
    -      }
    -
    -      if (0 === pathDot.indexOf(cur)) {
    -        return inclusive;
    -      }
    -    }
    -
    -    return ! inclusive;
    -  }
    -
    -  return true;
    -}

    Parameters:

    Returns:

    Example

    - -
    Thing.findOne().select('name').exec(function (err, doc) {
    -   doc.isSelected('name') // true
    -   doc.isSelected('age')  // false
    -})

    Document#validate(cb)

    Executes registered validation rules for this document.

    show code
    Document.prototype.validate = function (cb) {
    -  var self = this
    -
    -  // only validate required fields when necessary
    -  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
    -    if (!self.isSelected(path) && !self.isModified(path)) return false;
    -    return true;
    -  });
    -
    -  paths = paths.concat(Object.keys(this._activePaths.states.init));
    -  paths = paths.concat(Object.keys(this._activePaths.states.modify));
    -  paths = paths.concat(Object.keys(this._activePaths.states.default));
    -
    -  if (0 === paths.length) {
    -    complete();
    -    return this;
    -  }
    -
    -  var validating = {}
    -    , total = 0;
    -
    -  paths.forEach(validatePath);
    -  return this;
    -
    -  function validatePath (path) {
    -    if (validating[path]) return;
    -
    -    validating[path] = true;
    -    total++;
    -
    -    process.nextTick(function(){
    -      var p = self.schema.path(path);
    -      if (!p) return --total || complete();
    -
    -      p.doValidate(self.getValue(path), function (err) {
    -        if (err) self.invalidate(path, err, true);
    -        --total || complete();
    -      }, self);
    -    });
    -  }
    -
    -  function complete () {
    -    var err = self._validationError;
    -    self._validationError = undefined;
    -    cb(err);
    -  }
    -};

    Parameters:

    • cb <Function> called after validation completes, passing an error if one occurred

    Note:

    - -

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    - -

    Example:

    - -
    doc.validate(function (err) {
    -  if (err) handleError(err);
    -  else // validation passed
    -});

    Document#invalidate(path, err)

    Marks a path as invalid, causing validation to fail.

    show code
    Document.prototype.invalidate = function (path, err) {
    -  if (!this._validationError) {
    -    this._validationError = new ValidationError(this);
    -  }
    -
    -  if (!err || 'string' === typeof err) {
    -    err = new ValidatorError(path, err);
    -  }
    -
    -  this._validationError.errors[path] = err;
    -}

    Parameters:

    • path <String> the field to invalidate
    • err <String, Error> the error which states the reason `path` was invalid

    Document#_reset()

    Resets the internal modified state of this document.

    show code
    Document.prototype._reset = function reset () {
    -  var self = this;
    -  DocumentArray || (DocumentArray = require('./types/documentarray'));
    -
    -  this._activePaths
    -  .map('init', 'modify', function (i) {
    -    return self.getValue(i);
    -  })
    -  .filter(function (val) {
    -    return val && val instanceof DocumentArray && val.length;
    -  })
    -  .forEach(function (array) {
    -    var i = array.length;
    -    while (i--) {
    -      var doc = array[i];
    -      if (!doc) continue;
    -      doc._reset();
    -    }
    -  });
    -
    -  // clear atomics
    -  this._dirty().forEach(function (dirt) {
    -    var type = dirt.value;
    -    if (type && type._atomics) {
    -      type._atomics = {};
    -    }
    -  });
    -
    -  // Clear 'modify'('dirty') cache
    -  this._activePaths.clear('modify');
    -  this._validationError = undefined;
    -  this.errors = undefined;
    -  var self = this;
    -  this.schema.requiredPaths().forEach(function (path) {
    -    self._activePaths.require(path);
    -  });
    -
    -  return this;
    -}

    Returns:


    Document#_dirty()

    Returns this documents dirty paths / vals.

    show code
    Document.prototype._dirty = function _dirty () {
    -  var self = this;
    -
    -  var all = this._activePaths.map('modify', function (path) {
    -    return { path: path
    -           , value: self.getValue(path)
    -           , schema: self._path(path) };
    -  });
    -
    -  // Sort dirty paths in a flat hierarchy.
    -  all.sort(function (a, b) {
    -    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
    -  });
    -
    -  // Ignore "foo.a" if "foo" is dirty already.
    -  var minimal = []
    -    , lastPath
    -    , top;
    -
    -  all.forEach(function (item, i) {
    -    if (item.path.indexOf(lastPath) !== 0) {
    -      lastPath = item.path + '.';
    -      minimal.push(item);
    -      top = item;
    -    } else {
    -      if (!(item.value && top.value)) return;
    -
    -      // special case for top level MongooseArrays
    -      if (top.value._atomics && top.value.hasAtomics()) {
    -        // the `top` array itself and a sub path of `top` are being modified.
    -        // the only way to honor all of both modifications is through a $set
    -        // of entire array.
    -        top.value._atomics = {};
    -        top.value._atomics.$set = top.value;
    -      }
    -    }
    -  });
    -
    -  top = lastPath = null;
    -  return minimal;
    -}

    Document#_setSchema(schema)

    Assigns/compiles schema into this documents prototype.

    show code
    Document.prototype._setSchema = function (schema) {
    -  compile(schema.tree, this);
    -  this.schema = schema;
    -}

    Parameters:


    Document#_registerHooks()

    Register default hooks

    show code
    Document.prototype._registerHooks = function _registerHooks () {
    -  if (!this.save) return;
    -
    -  DocumentArray || (DocumentArray = require('./types/documentarray'));
    -
    -  this.pre('save', function (next) {
    -    // we keep the error semaphore to make sure we don't
    -    // call `save` unnecessarily (we only need 1 error)
    -    var subdocs = 0
    -      , error = false
    -      , self = this;
    -
    -    // check for DocumentArrays
    -    var arrays = this._activePaths
    -    .map('init', 'modify', function (i) {
    -      return self.getValue(i);
    -    })
    -    .filter(function (val) {
    -      return val && val instanceof DocumentArray && val.length;
    -    });
    -
    -    if (!arrays.length)
    -      return next();
    -
    -    arrays.forEach(function (array) {
    -      if (error) return;
    -
    -      // handle sparse arrays by using for loop vs array.forEach
    -      // which skips the sparse elements
    -
    -      var len = array.length
    -      subdocs += len;
    -
    -      for (var i = 0; i < len; ++i) {
    -        if (error) break;
    -
    -        var doc = array[i];
    -        if (!doc) {
    -          --subdocs || next();
    -          continue;
    -        }
    -
    -        doc.save(handleSave);
    -      }
    -    });
    -
    -    function handleSave (err) {
    -      if (error) return;
    -
    -      if (err) {
    -        self._validationError = undefined;
    -        return next(error = err);
    -      }
    -
    -      --subdocs || next();
    -    }
    -
    -  }, function (err) {
    -    // emit on the Model if listening
    -    if (this.constructor.listeners('error').length) {
    -      this.constructor.emit('error', err);
    -    } else {
    -      // emit on the connection
    -      if (!this.db.listeners('error').length) {
    -        err.stack = 'No listeners detected, throwing. '
    -                  + 'Consider adding an error listener to your connection.
    -'
    -                  + err.stack
    -      }
    -      this.db.emit('error', err);
    -    }
    -  }).pre('save', function checkForExistingErrors (next) {
    -    // if any doc.set() calls failed
    -    if (this._saveError) {
    -      next(this._saveError);
    -      this._saveError = null;
    -    } else {
    -      next();
    -    }
    -  }).pre('save', function validation (next) {
    -    return this.validate(next);
    -  });
    -
    -  // add user defined queues
    -  this._doQueue();
    -};

    Document#_error(err)

    Registers an error

    show code
    Document.prototype._error = function (err) {
    -  this._saveError = err;
    -  return this;
    -};

    Parameters:


    Document#_doQueue()

    Executes methods queued from the Schema definition

    show code
    Document.prototype._doQueue = function () {
    -  var q = this.schema && this.schema.callQueue;
    -  if (q) {
    -    for (var i = 0, l = q.length; i < l; i++) {
    -      this[q[i][0]].apply(this, q[i][1]);
    -    }
    -  }
    -  return this;
    -};

    Document#toObject([options])

    Converts this document into a plain javascript object

    show code
    Document.prototype.toObject = function (options) {
    -  // When internally saving this document we always pass options,
    -  // bypassing the custom schema options.
    -  if (!(options && 'Object' == options.constructor.name)) {
    -    options = this.schema.options.toObject
    -      ? clone(this.schema.options.toObject)
    -      : {};
    -  }
    -
    -  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
    -
    -  var ret = clone(this._doc, options);
    -
    -  if (options.virtuals || options.getters && false !== options.virtuals) {
    -    applyGetters(this, ret, 'virtuals', options);
    -  }
    -
    -  if (options.getters) {
    -    applyGetters(this, ret, 'paths', options);
    -  }
    -
    -  return ret;
    -};

    Parameters:

    Returns:

    Options:

    - -
      -
    • getters apply all getters (path and virtual getters)
    • -
    • virtuals apply virtual getters (can override getters option)
    • -
    • minimize remove empty objects (defaults to true)
    • -
    - -

    Example of only applying path getters

    - -
    doc.toObject({ getters: true, virtuals: false })
    - -

    Example of only applying virtual getters

    - -
    doc.toObject({ virtuals: true })
    - -

    Example of applying both path and virtual getters

    - -
    doc.toObject({ getters: true })
    - -

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    - -
    schema.set('toObject', { virtuals: true })
    - -

    See schema options for details.


    Document#toJSON(options)

    The return value of this method is used in calls to JSON.stringify(doc).

    show code
    Document.prototype.toJSON = function (options) {
    -  // check for object type since an array of documents
    -  // being stringified passes array indexes instead
    -  // of options objects. JSON.stringify([doc, doc])
    -  if (!(options && 'Object' == options.constructor.name)) {
    -    options = this.schema.options.toJSON
    -      ? clone(this.schema.options.toJSON)
    -      : {};
    -  }
    -  options.json = true;
    -  return this.toObject(options);
    -};

    Parameters:

    • options <Object> same options as `Document#toObject`

    Returns:

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    - -
    schema.set('toJSON', { virtuals: true })
    - -

    See schema options for details.


    Document#inspect()

    Helper for console.log

    show code
    Document.prototype.inspect = function (options) {
    -  var opts = options && 'Object' == options.constructor.name
    -    ? options
    -    : undefined
    -  return inspect(this.toObject(opts));
    -};

    Document#toString()

    Helper for console.log


    Document#equals(doc)

    Returns true if the Document stores the same data as doc.

    show code
    Document.prototype.equals = function (doc) {
    -  var tid = this.get('_id');
    -  var docid = doc.get('_id');
    -  return tid.equals
    -    ? tid.equals(docid)
    -    : tid === docid;
    -};

    Parameters:

    Returns:

    Documents are considered equal when they have matching _ids.


    Document#errors

    Hash containing current validation errors.


    Document#id

    The string version of this documents _id.

    - -

    Note:

    - -

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    - -
    new Schema({ name: String }, { id: false });

    Document#isNew

    Boolean flag specifying if the document is new.


    Document#schema

    The documents schema.


  • drivers/node-mongodb-native/collection.js

    NativeCollection()

    A node-mongodb-native collection implementation.

    show code
    function NativeCollection () {
    -  this.collection = null;
    -  MongooseCollection.apply(this, arguments);
    -}

    Inherits:

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


    NativeCollection#onOpen()

    Called when the connection opens.

    show code
    NativeCollection.prototype.onOpen = function () {
    -  var self = this;
    -
    -  if (this.collection) {
    -    return MongooseCollection.prototype.onOpen.call(self);
    -  }
    -
    -  if (!self.opts.size) {
    -    // non-capped
    -    return self.conn.db.collection(self.name, callback);
    -  }
    -
    -  // capped
    -  return self.conn.db.collection(self.name, function (err, c) {
    -    if (err) return callback(err);
    -
    -    // discover if this collection exists and if it is capped
    -    c.options(function (err, exists) {
    -      if (err) return callback(err);
    -
    -      if (exists) {
    -        if (exists.capped) {
    -          callback(null, c);
    -        } else {
    -          var msg = 'A non-capped collection exists with this name.
    -
    -'
    -                  + ' To use this collection as a capped collection, please '
    -                  + 'first convert it.
    -'
    -                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
    -          err = new Error(msg);
    -          callback(err);
    -        }
    -      } else {
    -        // create
    -        var opts = utils.clone(self.opts);
    -        opts.capped = true;
    -        self.conn.db.createCollection(self.name, opts, callback);
    -      }
    -    });
    -  });
    -
    -  function callback (err, collection) {
    -    if (err) {
    -      // likely a strict mode error
    -      self.conn.emit('error', err);
    -    } else {
    -      self.collection = collection;
    -      MongooseCollection.prototype.onOpen.call(self);
    -    }
    -  };
    -};

    NativeCollection#onClose()

    Called when the connection closes

    show code
    NativeCollection.prototype.onClose = function () {
    -  MongooseCollection.prototype.onClose.call(this);
    -};

    NativeCollection#getIndexes(callback)

    Retreives information about this collections indexes.

    Parameters:


  • drivers/node-mongodb-native/connection.js

    NativeConnection()

    A node-mongodb-native connection implementation.

    show code
    function NativeConnection() {
    -  MongooseConnection.apply(this, arguments);
    -};

    Inherits:


    NativeConnection#doOpen(fn)

    Opens the connection to MongoDB.

    show code
    NativeConnection.prototype.doOpen = function (fn) {
    -  var server
    -    , self = this;
    -
    -  if (!this.db) {
    -    server = new mongo.Server(this.host, Number(this.port), this.options.server);
    -    this.db = new mongo.Db(this.name, server, this.options.db);
    -  }
    -
    -  this.db.open(function (err) {
    -    if (err) return fn(err);
    -    fn();
    -    listen(self);
    -  });
    -
    -  return this;
    -};
    -
    -function listen (conn) {
    -  if (conn._listening) return;
    -  conn._listening = true;
    -
    -  conn.db.on('close', function(){
    -    if (conn._closeCalled) return;
    -
    -    // the driver never emits an `open` event. auto_reconnect still
    -    // emits a `close` event but since we never get another
    -    // `open` we can't emit close
    -    if (conn.db.serverConfig.autoReconnect) {
    -      conn.readyState = STATES.disconnected;
    -      conn.emit('close');
    -      return;
    -    }
    -    conn.onClose();
    -  });
    -  conn.db.on('error', function(err){
    -    conn.emit('error', err);
    -  });
    -  conn.db.on('timeout', function(err){
    -    var error = new Error(err && err.err || 'connection timeout');
    -    conn.emit('error', error);
    -  });
    -  conn.db.on('open', function (err, db) {
    -    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
    -      conn.readyState = STATES.connected;
    -      conn.emit('reconnected')
    -    }
    -  })
    -}

    Parameters:

    Returns:


    NativeConnection#doOpenSet(fn)

    Opens a connection to a MongoDB ReplicaSet.

    show code
    NativeConnection.prototype.doOpenSet = function (fn) {
    -  if (!this.db) {
    -    var servers = []
    -      , ports = this.port
    -      , self = this
    -
    -    this.host.forEach(function (host, i) {
    -      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
    -    });
    -
    -    var server = new ReplSetServers(servers, this.options.replset);
    -    this.db = new mongo.Db(this.name, server, this.options.db);
    -
    -    this.db.on('fullsetup', function () {
    -      self.emit('fullsetup')
    -    });
    -  }
    -
    -  this.db.open(function (err) {
    -    if (err) return fn(err);
    -    fn();
    -    listen(self);
    -  });
    -
    -  return this;
    -};

    Parameters:

    Returns:

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


    NativeConnection#doClose(fn)

    Closes the connection

    show code
    NativeConnection.prototype.doClose = function (fn) {
    -  this.db.close();
    -  if (fn) fn();
    -  return this;
    -}

    Parameters:

    Returns:


  • error.js

    MongooseError()

    Mongoose error

    show code
    function MongooseError (msg) {
    -  Error.call(this);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.message = msg;
    -  this.name = 'MongooseError';
    -};

    Inherits:


  • errors/cast.js

    CastError(type, value)

    Casting Error constructor.

    show code
    function CastError (type, value) {
    -  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'CastError';
    -  this.type = type;
    -  this.value = value;
    -};

    Parameters:

    Inherits:


  • errors/document.js

    DocumentError(msg)

    Document Error

    show code
    function DocumentError (msg) {
    -  MongooseError.call(this, msg);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'DocumentError';
    -};

    Parameters:

    Inherits:


  • errors/validation.js

    ValidationError(instance)

    Document Validation Error

    show code
    function ValidationError (instance) {
    -  MongooseError.call(this, "Validation failed");
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'ValidationError';
    -  this.errors = instance.errors = {};
    -};

    Parameters:

    Inherits:


    ValidationError#toString()

    Console.log helper

    show code
    ValidationError.prototype.toString = function () {
    -  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
    -    return String(this.errors[key]);
    -  }, this).join(', ');
    -};

  • errors/validator.js

    ValidatorError(path, msg)

    Schema validator error

    show code
    function ValidatorError (path, type) {
    -  var msg = type
    -    ? '"' + type + '" '
    -    : '';
    -  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'ValidatorError';
    -  this.path = path;
    -  this.type = type;
    -};

    Parameters:

    Inherits:


  • model.js

    Model(doc)

    Model constructor

    show code
    function Model (doc, fields, skipId) {
    -  Document.call(this, doc, fields, skipId);
    -};

    Parameters:

    • doc <Object> values to with which to create the document

    Inherits:

    Events:

    • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

    • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


    Model#_getPopulationKeys(query)

    Returns what paths can be populated

    show code
    Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
    -  if (!(query && query.options.populate)) return;
    -
    -  var names = Object.keys(query.options.populate)
    -    , n = names.length
    -    , name
    -    , paths = {}
    -    , hasKeys
    -    , schema
    -
    -  while (n--) {
    -    name = names[n];
    -    schema = this.schema.path(name);
    -    hasKeys = true;
    -
    -    if (!schema) {
    -      // if the path is not recognized, it's potentially embedded docs
    -      // walk path atoms from right to left to find a matching path
    -      var pieces = name.split('.')
    -        , i = pieces.length;
    -
    -      while (i--) {
    -        var path = pieces.slice(0, i).join('.')
    -          , pathSchema = this.schema.path(path);
    -
    -        // loop until we find an array schema
    -        if (pathSchema && pathSchema.caster) {
    -          if (!paths[path]) {
    -            paths[path] = { sub: {} };
    -          }
    -
    -          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
    -          hasKeys || (hasKeys = true);
    -          break;
    -        }
    -      }
    -    } else {
    -      paths[name] = query.options.populate[name];
    -      hasKeys || (hasKeys = true);
    -    }
    -  }
    -
    -  return hasKeys && paths;
    -};

    Parameters:

    Returns:


    Model#_populate(schema, oid, query, fn)

    Populates an object

    show code
    Model.prototype._populate = function populate (schema, oid, query, fn) {
    -  if (!Array.isArray(oid)) {
    -    var conditions = query.conditions || {};
    -    conditions._id = oid;
    -
    -    return this
    -    .db.model(query.model || schema.options.ref)
    -    .findOne(conditions, query.fields, query.options, fn);
    -  }
    -
    -  if (!oid.length) {
    -    return fn(null, oid);
    -  }
    -
    -  var model = this.db.model(query.model || schema.caster.options.ref)
    -    , conditions = query && query.conditions || {};
    -
    -  conditions._id || (conditions._id = { $in: oid });
    -
    -  model.find(conditions, query.fields, query.options, function (err, docs) {
    -    if (err) return fn(err);
    -
    -    // user specified sort order?
    -    if (query.options && query.options.sort) {
    -      return fn(null, docs);
    -    }
    -
    -    // put back in original id order (using a hash reduces complexity from n*n to 2n)
    -    var docHash = {};
    -    docs.forEach(function (doc) {
    -      docHash[doc._id] = doc;
    -    });
    -
    -    var arr = [];
    -    oid.forEach(function (id) {
    -      if (id in docHash) arr.push(docHash[id]);
    -    });
    -
    -    fn(null, arr);
    -  });
    -};

    Parameters:

    • schema <SchemaType> type for the oid
    • oid <Object> object id or array of object ids
    • query <Object> object specifying query conditions, fields, and options
    • fn <Function>

    Model#init(doc, query, fn)

    Performs auto-population of relations.

    show code
    Model.prototype.init = function init (doc, query, fn) {
    -  if ('function' == typeof query) {
    -    fn = query;
    -    query = null;
    -  }
    -
    -  var populate = this._getPopulationKeys(query);
    -
    -  if (!populate) {
    -    return Document.prototype.init.call(this, doc, fn);
    -  }
    -
    -  // population from other models is necessary
    -  var self = this;
    -
    -  init(doc, '', function (err) {
    -    if (err) return fn(err);
    -    Document.prototype.init.call(self, doc, fn);
    -  });
    -
    -  return this;
    -
    -  function init (obj, prefix, fn) {
    -    prefix = prefix || '';
    -
    -    var keys = Object.keys(obj)
    -      , len = keys.length;
    -
    -    return next();
    -
    -    function next () {
    -      if (--len < 0) return fn();
    -
    -      var i = keys[len]
    -        , path = prefix + i
    -        , schema = self.schema.path(path)
    -        , total = 0
    -        , inline = false
    -        , poppath
    -
    -      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
    -        // assume nested object
    -        return init(obj[i], path + '.', next);
    -      }
    -
    -      if (!(obj[i] && schema && populate[path])) return next();
    -
    -      // this query object is re-used and passed around. we clone
    -      // it to prevent query condition contamination between
    -      // one populate call to the next.
    -      poppath = utils.clone(populate[path]);
    -
    -      if (poppath.sub) {
    -        obj[i].forEach(function (subobj) {
    -          inline = true;
    -
    -          var pkeys = Object.keys(poppath.sub)
    -            , pi = pkeys.length
    -            , key
    -
    -          while (pi--) {
    -            key = pkeys[pi];
    -
    -            if (subobj[key]) (function (key) {
    -              total++;
    -              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
    -              function done (err, doc) {
    -                if (err) return error(err);
    -                subobj[key] = doc;
    -                if (--total < 1 && !inline) {
    -                  next();
    -                }
    -              }
    -            })(key);
    -          }
    -        });
    -
    -        inline = false;
    -
    -        if (0 === total) return next();
    -
    -      } else {
    -        self._populate(schema, obj[i], poppath, function (err, doc) {
    -          if (err) return error(err);
    -          obj[i] = doc;
    -          next();
    -        });
    -      }
    -    };
    -  };
    -
    -  function error (err) {
    -    if (error.err) return;
    -    fn(error.err = err);
    -  }
    -};

    Parameters:

    • doc <Object> document returned by mongo
    • query <Query> query that originated the initialization
    • fn <Function>

    Model#save([fn])

    Saves this document.

    show code
    Model.prototype.save = function save (fn) {
    -  var promise = new Promise(fn)
    -    , complete = handleSave(promise, this)
    -    , options = {}
    -
    -  if (this.schema.options.safe) {
    -    options.safe = this.schema.options.safe;
    -  }
    -
    -  if (this.isNew) {
    -    // send entire doc
    -    var obj = this.toObject({ depopulate: 1 });
    -    this._version(true, obj);
    -    this.collection.insert(obj, options, complete);
    -    this._reset();
    -    this.isNew = false;
    -    this.emit('isNew', false);
    -    // Make it possible to retry the insert
    -    this._inserting = true;
    -
    -  } else {
    -    // Make sure we don't treat it as a new object on error,
    -    // since it already exists
    -    this._inserting = false;
    -
    -    var delta = this._delta();
    -    if (delta) {
    -      var where = this._where(delta[0]);
    -      this.collection.update(where, delta[1], options, complete);
    -    } else {
    -      complete(null);
    -    }
    -
    -    this._reset();
    -    this.emit('isNew', false);
    -  }
    -};

    Parameters:

    Example:

    - -
    product.sold = Date.now();
    -product.save(function (err, product) {
    -  if (err) ..
    -})
    - -

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    - -
    var db = mongoose.createConnection(..);
    -var schema = new Schema(..);
    -var Product = db.model('Product', schema);
    -
    -db.on('error', handleError);
    - -

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    - -
    Product.on('error', handleError);

    Model#_delta()

    Produces a special query document of the modified properties used in updates.

    show code
    Model.prototype._delta = function _delta () {
    -  var dirty = this._dirty();
    -  if (!dirty.length) return;
    -
    -  var self = this
    -    , where = {}
    -    , delta = {}
    -    , len = dirty.length
    -    , d = 0
    -    , val
    -    , obj
    -
    -  for (; d < len; ++d) {
    -    var data = dirty[d]
    -    var value = data.value
    -    var schema = data.schema
    -
    -    if (undefined === value) {
    -      operand(self, where, delta, data, 1, '$unset');
    -
    -    } else if (null === value) {
    -      operand(self, where, delta, data, null);
    -
    -    } else if (value._path && value._atomics) {
    -      handleAtomics(self, where, delta, data, value);
    -
    -    } else if (value._path && Buffer.isBuffer(value)) {
    -      // MongooseBuffer
    -      value = value.toObject();
    -      operand(self, where, delta, data, value);
    -
    -    } else {
    -      value = utils.clone(value);
    -      operand(self, where, delta, data, value);
    -    }
    -  }
    -
    -  if (this.__version) {
    -    this._version(where, delta);
    -  }
    -
    -  return [where, delta];
    -}

    Model#_version()

    Appends versioning to the where and update clauses.

    show code
    Model.prototype._version = function _version (where, delta) {
    -  var key = this.schema.options.versionKey;
    -
    -  if (true === where) {
    -    // this is an insert
    -    if (key) this.setValue(key, delta[key] = 0);
    -    return;
    -  }
    -
    -  // updates
    -
    -  // only apply versioning if our versionKey was selected. else
    -  // there is no way to select the correct version. we could fail
    -  // fast here and force them to include the versionKey but
    -  // thats a bit intrusive. can we do this automatically?
    -  // TODO fail fast option?
    -  if (!this.isSelected(key)) {
    -    return;
    -  }
    -
    -  // $push $addToSet don't need the where clause set
    -  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
    -    where[key] = this.getValue(key);
    -  }
    -
    -  if (VERSION_INC === (VERSION_INC & this.__version)) {
    -    delta.$inc || (delta.$inc = {});
    -    delta.$inc[key] = 1;
    -  }
    -}

    Model#increment()

    Signal that we desire an increment of this documents version.

    show code
    Model.prototype.increment = function increment () {
    -  this.__version = VERSION_ALL;
    -  return this;
    -}

    Model#_where()

    Returns a query object which applies shardkeys if they exist.

    show code
    Model.prototype._where = function _where (where) {
    -  where || (where = {});
    -
    -  var paths
    -    , len
    -
    -  if (this._shardval) {
    -    paths = Object.keys(this._shardval)
    -    len = paths.length
    -
    -    for (var i = 0; i < len; ++i) {
    -      where[paths[i]] = this._shardval[paths[i]];
    -    }
    -  }
    -
    -  where._id = this._doc._id;
    -  return where;
    -}

    Model#remove([fn])

    Removes this document from the db.

    show code
    Model.prototype.remove = function remove (fn) {
    -  if (this._removing) return this;
    -
    -  var promise = this._removing = new Promise(fn)
    -    , where = this._where()
    -    , self = this
    -    , options = {}
    -
    -  if (this.schema.options.safe) {
    -    options.safe = this.schema.options.safe;
    -  }
    -
    -  this.collection.remove(where, options, tick(function (err) {
    -    if (err) {
    -      promise.error(err);
    -      promise = self = self._removing = where = options = null;
    -      return;
    -    }
    -    self.emit('remove', self);
    -    promise.complete();
    -    promise = self = where = options = null;
    -  }));
    -
    -  return this;
    -};

    Parameters:

    Example:

    - -
    product.remove(function (err, product) {
    -  if (err) return handleError(err);
    -  Product.findById(product._id, function (err, product) {
    -    console.log(product) // null
    -  })
    -})

    Model#_registerHooks()

    Register hooks override

    show code
    Model.prototype._registerHooks = function registerHooks () {
    -  Document.prototype._registerHooks.call(this);
    -};

    Model#model(name)

    Returns another Model instance.

    show code
    Model.prototype.model = function model (name) {
    -  return this.db.model(name);
    -};

    Parameters:

    Example:

    - -
    var doc = new Tank;
    -doc.model('User').findById(id, callback);

    Model#$where(argument)

    Creates a Query and specifies a $where condition.

    Parameters:

    • argument <String, Function> is a javascript string or anonymous function

    Returns:

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    - -
    Blog.$where('this.comments.length &gt; 5');

    Model.init()

    Called when the model compiles.

    show code
    Model.init = function init () {
    -  if (this.schema.options.autoIndex)
    -    this.ensureIndexes();
    -
    -  this.schema.emit('init', this);
    -};

    Model.ensureIndexes([cb])

    Sends ensureIndex commands to mongo for each index declared in the schema.

    show code
    Model.ensureIndexes = function ensureIndexes (cb) {
    -  var indexes = this.schema.indexes();
    -  if (!indexes.length) {
    -    return cb && cb();
    -  }
    -
    -  var self = this
    -    , safe = self.schema.options.safe
    -    , count = indexes.length
    -    , error
    -
    -  indexes.forEach(function (index) {
    -    var options = index[1];
    -    options.safe = safe;
    -    self.collection.ensureIndex(index[0], options, tick(function (err) {
    -      if (err) error = err;
    -      if (--count) return;
    -
    -      self.emit('index', error);
    -      cb && cb(error);
    -    }));
    -  });
    -}

    Parameters:

    After completion, an index event is emitted on this Model passing an error if one occurred.

    - -

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    - -

    Example:

    - -
    Event.ensureIndexes(function (err) {
    -  if (err) return handleError(err);
    -});

    Model.remove(conditions, [callback])

    Removes documents from the collection.

    show code
    Model.remove = function remove (conditions, callback) {
    -  if ('function' === typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -  }
    -
    -  var query = new Query(conditions).bind(this, 'remove');
    -
    -  if ('undefined' === typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.remove(callback);
    -};

    Parameters:

    Returns:

    Note:

    - -

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    - -
    Comment.remove({ _id: id }).exec();

    Model.find(conditions, [fields], [options], [callback])

    Finds documents

    show code
    Model.find = function find (conditions, fields, options, callback) {
    -  if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof fields) {
    -    callback = fields;
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof options) {
    -    callback = options;
    -    options = null;
    -  }
    -
    -  var query = new Query(conditions, options);
    -  query.bind(this, 'find');
    -  query.select(fields);
    -
    -  if ('undefined' === typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.find(callback);
    -};

    Parameters:

    Returns:

    Examples:

    - -
    // retrieve only certain keys
    -MyModel.find({ name: /john/i }, 'name friends', function () { })
    -
    -// pass options
    -MyModel.find({ name: /john/i }, null, { skip: 10 } )

    Model._applyNamedScope(query)

    Merges the current named scope query into query.

    show code
    Model._applyNamedScope = function _applyNamedScope (query) {
    -  var cQuery = this._cumulativeQuery;
    -
    -  if (cQuery) {
    -    merge(query._conditions, cQuery._conditions);
    -    if (query._fields && cQuery._fields)
    -      merge(query._fields, cQuery._fields);
    -    if (query.options && cQuery.options)
    -      merge(query.options, cQuery.options);
    -    delete this._cumulativeQuery;
    -  }
    -
    -  return query;
    -}

    Parameters:

    Returns:


    Model.findById(id, [fields], [options], [callback])

    Finds a single document by id.

    show code
    Model.findById = function findById (id, fields, options, callback) {
    -  return this.findOne({ _id: id }, fields, options, callback);
    -};

    Parameters:

    Returns:

    The id is cast to an ObjectId before sending the command.

    - -

    Example:

    - -
    Adventure.findById(id, callback);

    Model.findOne(conditions, [fields], [options], [callback])

    Finds one document.

    show code
    Model.findOne = function findOne (conditions, fields, options, callback) {
    -  if ('function' == typeof options) {
    -    // TODO Handle all 3 of the following scenarios
    -    // Hint: Only some of these scenarios are possible if cQuery is present
    -    // Scenario: findOne(conditions, fields, callback);
    -    // Scenario: findOne(fields, options, callback);
    -    // Scenario: findOne(conditions, options, callback);
    -    callback = options;
    -    options = null;
    -  } else if ('function' == typeof fields) {
    -    // TODO Handle all 2 of the following scenarios
    -    // Scenario: findOne(conditions, callback)
    -    // Scenario: findOne(fields, callback)
    -    // Scenario: findOne(options, callback);
    -    callback = fields;
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -    fields = null;
    -    options = null;
    -  }
    -
    -  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.findOne(callback);
    -};

    Parameters:

    Returns:

    The conditions are cast to their respective SchemaTypes before the command is sent.

    - -

    Example:

    - -
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

    Model.count(conditions, [callback])

    Counts number of matching documents in a database collection.

    show code
    Model.count = function count (conditions, callback) {
    -  if ('function' === typeof conditions)
    -    callback = conditions, conditions = {};
    -
    -  var query = new Query(conditions).bind(this, 'count');
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.count(callback);
    -};

    Parameters:

    Returns:

    Example:

    - -
    Adventure.count({ type: 'jungle' }, function (err, count) {
    -  if (err) ..
    -  console.log('there are %d jungle adventures', count);
    -});

    Model.distinct(field, [conditions], [callback])

    Executes a DISTINCT command

    show code
    Model.distinct = function distinct (field, conditions, callback) {
    -  var query = new Query(conditions).bind(this, 'distinct');
    -  if ('undefined' == typeof callback) {
    -    query._distinctArg = field;
    -    return query;
    -  }
    -
    -  this._applyNamedScope(query);
    -  return query.distinct(field, callback);
    -};

    Parameters:

    Returns:


    Model.where(path, [val])

    Creates a Query, applies the passed conditions, and returns the Query.

    show code
    Model.where = function where (path, val) {
    -  var q = new Query().bind(this, 'find');
    -  return q.where.apply(q, arguments);
    -};

    Parameters:

    Returns:

    For example, instead of writing:

    - -
    User.find({age: {$gte: 21, $lte: 65}}, callback);
    - -

    we can instead write:

    - -
    User.where('age').gte(21).lte(65).exec(callback);
    - -

    Since the Query class also supports where you can continue chaining

    - -
    User
    -.where('age').gte(21).lte(65)
    -.where('name', /^b/i)
    -... etc

    Model.findOneAndUpdate([conditions], [update], [options], [callback])

    Issues a mongodb findAndModify update command.

    show code
    Model.findOneAndUpdate = function (conditions, update, options, callback) {
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = null;
    -  }
    -  else if (1 === arguments.length) {
    -    if ('function' == typeof conditions) {
    -      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
    -
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(update)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate()
    -';
    -      throw new TypeError(msg)
    -    }
    -    update = conditions;
    -    conditions = undefined;
    -  }
    -
    -  var fields;
    -  if (options && options.fields) {
    -    fields = options.fields;
    -    options.fields = undefined;
    -  }
    -
    -  var query = new Query(conditions);
    -  query.setOptions(options);
    -  query.select(fields);
    -  query.bind(this, 'findOneAndUpdate', update);
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.findOneAndUpdate(callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findOneAndUpdate(conditions, update, options, callback) // executes
    -A.findOneAndUpdate(conditions, update, options)  // returns Query
    -A.findOneAndUpdate(conditions, update, callback) // executes
    -A.findOneAndUpdate(conditions, update)           // returns Query
    -A.findOneAndUpdate()                             // returns Query
    - -

    Note:

    - -

    All top level update keys which are not atomic operation names are treated as set operations:

    - -

    Example:

    - -
    var query = { name: 'borne' };
    -Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
    -
    -// is sent as
    -Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
    - -

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    - -

    Note:

    - -

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    - -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    - -

    If you need those features, use the traditional approach of first retrieving the document.

    - -
    Model.findOne({ name: 'borne' }, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.findByIdAndUpdate(id, [update], [options], [callback])

    Issues a mongodb findAndModify update command by a documents id.

    show code
    Model.findByIdAndUpdate = function (id, update, options, callback) {
    -  var args;
    -
    -  if (1 === arguments.length) {
    -    if ('function' == typeof id) {
    -      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
    -
    -'
    -                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
    -'
    -                + '  ' + this.modelName + '.findByIdAndUpdate(id)
    -'
    -                + '  ' + this.modelName + '.findByIdAndUpdate()
    -';
    -      throw new TypeError(msg)
    -    }
    -    return this.findOneAndUpdate({_id: id }, undefined);
    -  }
    -
    -  args = utils.args(arguments, 1);
    -  args.unshift({ _id: id });
    -  return this.findOneAndUpdate.apply(this, args);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findByIdAndUpdate(id, update, options, callback) // executes
    -A.findByIdAndUpdate(id, update, options)  // returns Query
    -A.findByIdAndUpdate(id, update, callback) // executes
    -A.findByIdAndUpdate(id, update)           // returns Query
    -A.findByIdAndUpdate()                     // returns Query
    - -

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    - -

    Note:

    - -

    All top level update keys which are not atomic operation names are treated as set operations:

    - -

    Example:

    - -
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
    -
    -// is sent as
    -Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
    - -

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    - -

    Note:

    - -

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    - -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    - -

    If you need those features, use the traditional approach of first retrieving the document.

    - -
    Model.findById(id, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.findOneAndRemove(conditions, [options], [callback])

    Issue a mongodb findAndModify remove command.

    show code
    Model.findOneAndRemove = function (conditions, options, callback) {
    -  if (1 === arguments.length && 'function' == typeof conditions) {
    -    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
    -
    -'
    -              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
    -'
    -              + '  ' + this.modelName + '.findOneAndRemove(conditions)
    -'
    -              + '  ' + this.modelName + '.findOneAndRemove()
    -';
    -    throw new TypeError(msg)
    -  }
    -
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = undefined;
    -  }
    -
    -  var fields;
    -  if (options) {
    -    fields = options.select;
    -    options.select = undefined;
    -  }
    -
    -  var query = new Query(conditions);
    -  query.setOptions(options);
    -  query.select(fields);
    -  query.bind(this, 'findOneAndRemove');
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.findOneAndRemove(callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    - -

    Executes immediately if callback is passed else a Query object is returned.

    - -

    Options:

    - -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findOneAndRemove(conditions, options, callback) // executes
    -A.findOneAndRemove(conditions, options)  // return Query
    -A.findOneAndRemove(conditions, callback) // executes
    -A.findOneAndRemove(conditions) // returns Query
    -A.findOneAndRemove()           // returns Query

    Model.findByIdAndRemove(id, [options], [callback])

    Issue a mongodb findAndModify remove command by a documents id.

    show code
    Model.findByIdAndRemove = function (id, options, callback) {
    -  if (1 === arguments.length && 'function' == typeof id) {
    -    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
    -
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove(id)
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove()
    -';
    -    throw new TypeError(msg)
    -  }
    -
    -  return this.findOneAndRemove({ _id: id }, options, callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    - -

    Executes immediately if callback is passed, else a Query object is returned.

    - -

    Options:

    - -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    - -

    Examples:

    - -
    A.findByIdAndRemove(id, options, callback) // executes
    -A.findByIdAndRemove(id, options)  // return Query
    -A.findByIdAndRemove(id, callback) // executes
    -A.findByIdAndRemove(id) // returns Query
    -A.findByIdAndRemove()           // returns Query

    Model.create(doc, fn)

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    show code
    Model.create = function create (doc, fn) {
    -  if (1 === arguments.length) {
    -    return 'function' === typeof doc && doc(null);
    -  }
    -
    -  var self = this
    -    , docs = [null]
    -    , promise
    -    , count
    -    , args
    -
    -  if (Array.isArray(doc)) {
    -    args = doc;
    -  } else {
    -    args = utils.args(arguments, 0, arguments.length - 1);
    -    fn = arguments[arguments.length - 1];
    -  }
    -
    -  if (0 === args.length) return fn(null);
    -
    -  promise = new Promise(fn);
    -  count = args.length;
    -
    -  args.forEach(function (arg, i) {
    -    var doc = new self(arg);
    -    docs[i+1] = doc;
    -    doc.save(function (err) {
    -      if (err) return promise.error(err);
    -      --count || fn.apply(null, docs);
    -    });
    -  });
    -
    -  // TODO
    -  // utilize collection.insertAll for batch processing?
    -};

    Parameters:

    Example:

    - -
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
    -  if (err) // ...
    -});
    -
    -var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
    -Candy.create(array, function (err, jellybean, snickers) {
    -  if (err) // ...
    -});

    Model.update(conditions, update, [options], [callback])

    Updates documents in the database without returning them.

    show code
    Model.update = function update (conditions, doc, options, callback) {
    -  if (arguments.length < 4) {
    -    if ('function' === typeof options) {
    -      // Scenario: update(conditions, doc, callback)
    -      callback = options;
    -      options = null;
    -    } else if ('function' === typeof doc) {
    -      // Scenario: update(doc, callback);
    -      callback = doc;
    -      doc = conditions;
    -      conditions = {};
    -      options = null;
    -    }
    -  }
    -
    -  var query = new Query(conditions, options).bind(this, 'update', doc);
    -
    -  if ('undefined' == typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.update(doc, callback);
    -};

    Parameters:

    Returns:

    Examples:

    - -
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
    -MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
    -  if (err) return handleError(err);
    -  console.log('The number of updated documents was %d', numberAffected);
    -  console.log('The raw response from Mongo was ', raw);
    -});
    - -

    Valid options:

    - -
      -
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • -
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • -
    • multi (boolean) whether multiple documents should be updated (false)
    • -
    - -

    All update values are cast to their appropriate SchemaTypes before being sent.

    - -

    The callback function receives (err, numberAffected, rawResponse).

    - -
      -
    • err is the error if any occurred
    • -
    • numberAffected is the count of updated documents Mongo reported
    • -
    • rawResponse is the full response from Mongo
    • -
    - -

    Note:

    - -

    All top level keys which are not atomic operation names are treated as set operations:

    - -

    Example:

    - -
    var query = { name: 'borne' };
    -Model.update(query, { name: 'jason borne' }, options, callback)
    -
    -// is sent as
    -Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
    - -

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    - -

    Note:

    - -

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    - -
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
    - -

    Note:

    - -

    Although values are casted to their appropriate types when using update, the following are not applied:

    - -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    - -

    If you need those features, use the traditional approach of first retrieving the document.

    - -
    Model.findOne({ name: 'borne' }, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.mapReduce(o, callback)

    Executes a mapReduce command.

    show code
    Model.mapReduce = function mapReduce (o, callback) {
    -  if ('function' != typeof callback) throw new Error('missing callback');
    -
    -  var self = this;
    -
    -  if (!Model.mapReduce.schema) {
    -    var opts = { noId: true, noVirtualId: true, strict: false }
    -    Model.mapReduce.schema = new Schema({}, opts);
    -  }
    -
    -  if (!o.out) o.out = { inline: 1 };
    -
    -  o.map = String(o.map);
    -  o.reduce = String(o.reduce);
    -
    -  if (o.query) {
    -    var q = new Query(o.query);
    -    q.cast(this);
    -    o.query = q._conditions;
    -    q = undefined;
    -  }
    -
    -  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
    -    if (err) return callback(err);
    -
    -    if (ret.findOne && ret.mapReduce) {
    -      // returned a collection, convert to Model
    -      var model = Model.compile(
    -          '_mapreduce_' + ret.collectionName
    -        , Model.mapReduce.schema
    -        , ret.collectionName
    -        , self.db
    -        , self.base);
    -
    -      model._mapreduce = true;
    -
    -      return callback(err, model, stats);
    -    }
    -
    -    callback(err, ret, stats);
    -  });
    -}

    Parameters:

    • o <Object> an object specifying map-reduce options
    • callback <Function>

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    - -

    Example:

    - -
    var o = {};
    -o.map = function () { emit(this.name, 1) }
    -o.reduce = function (k, vals) { return vals.length }
    -User.mapReduce(o, function (err, results) {
    -  console.log(results)
    -})
    - -

    Other options:

    - -
      -
    • query {Object} query filter object.
    • -
    • limit {Number} max number of documents
    • -
    • keeptemp {Boolean, default:false} keep temporary data
    • -
    • finalize {Function} finalize function
    • -
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • -
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • -
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • -
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • -
    - -

    * out options:

    - -
      -
    • {inline:1} the results are returned in an array
    • -
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • -
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • -
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • -
    - -

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    - -

    Example:

    - -
    var o = {};
    -o.map = function () { emit(this.name, 1) }
    -o.reduce = function (k, vals) { return vals.length }
    -o.out = { replace: 'createdCollectionNameForResults' }
    -o.verbose = true;
    -User.mapReduce(o, function (err, model, stats) {
    -  console.log('map reduce took %d ms', stats.processtime)
    -  model.find().where('value').gt(10).exec(function (err, docs) {
    -    console.log(docs);
    -  });
    -})

    Model.aggregate(array, [options], callback)

    Executes an aggregate command on this models collection.

    show code
    Model.aggregate = function aggregate () {
    -  return this.collection.aggregate.apply(this.collection, arguments);
    -}

    Parameters:

    Example:

    - -
    // find the max age of all users
    -Users.aggregate(
    -    { $group: { _id: null, maxAge: { $max: '$age' }}}
    -  , { $project: { _id: 0, maxAge: 1 }}
    -  , function (err, res) {
    -  if (err) return handleError(err);
    -  console.log(res); // [ { maxAge: 98 } ]
    -});
    - -

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    - -

    NOTE: this requires running MongoDB >= 2.1


    Model#base

    Base Mongoose instance the model uses.


    Model#collection

    Collection the model uses.


    Model#db

    Database instance the model uses.


    Model#schema

    Schema the model uses.


    Model#modelName

    The name of the model


    Model#collection

    Collection the model uses.


    Model#db

    Connection the model uses.


  • namedscope.js

    NamedScope#decorate(target, getters)

    Decorate

    show code
    NamedScope.prototype.decorate = function (target, getters) {
    -  var name = this.name
    -    , block = this.block
    -    , query = this.query;
    -  if (block) {
    -    if (block.length === 0) {
    -      Object.defineProperty(target, name, {
    -        get: getters.block0(block)
    -      });
    -    } else {
    -      target[name] = getters.blockN(block);
    -    }
    -  } else {
    -    Object.defineProperty(target, name, {
    -      get: getters.basic(query)
    -    });
    -  }
    -};
    -
    -NamedScope.prototype.compile = function (model) {
    -  var allScopes = this.scopesByName
    -    , scope;
    -  for (var k in allScopes) {
    -    scope = allScopes[k];
    -    scope.decorate(model, {
    -      block0: function (block) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          block.call(cquery);
    -          return this;
    -        };
    -      },
    -      blockN: function (block) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          block.apply(cquery, arguments);
    -          return this;
    -        };
    -      },
    -      basic: function (query) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          cquery.find(query);
    -          return this;
    -        };
    -      }
    -    });
    -  }
    -};
    -
    -module.exports = NamedScope;

    Parameters:


  • promise.js

    Promise(back)

    Promise constructor.

    show code
    function Promise (back) {
    -  this.emitted = {};
    -  if ('function' == typeof back)
    -    this.addBack(back);
    -};

    Parameters:

    • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

    Events:

    • err: Emits when the promise resolves to an error.

    • complete: Emits when the promise resolves sucessfully.


    Promise#on(event, callback)

    Adds listener to the event.

    show code
    Promise.prototype.on = function (event, callback) {
    -  if (this.emitted[event])
    -    callback.apply(this, this.emitted[event]);
    -  else
    -    EventEmitter.prototype.on.call(this, event, callback);
    -
    -  return this;
    -};

    Parameters:

    Returns:

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


    Promise#emit()

    Keeps track of emitted events to run them on on.

    show code
    Promise.prototype.emit = function (event) {
    -  // ensures a promise can't be complete() or error() twice
    -  if (event == 'err' || event == 'complete'){
    -    if (this.emitted.err || this.emitted.complete) {
    -      return this;
    -    }
    -    this.emitted[event] = util.args(arguments, 1);
    -  }
    -
    -  return EventEmitter.prototype.emit.apply(this, arguments);
    -};

    Promise#complete()

    Shortcut for emitting the complete event.

    show code
    Promise.prototype.complete = function () {
    -  var args = util.args(arguments);
    -  return this.emit.apply(this, ['complete'].concat(args));
    -};

    Promise#error()

    Shortcut for emitting the err event.

    show code
    Promise.prototype.error = function (err) {
    -  if (!(err instanceof Error)) err = new Error(err);
    -  return this.emit('err', err);
    -};

    Returns:


    Promise#addCallback()

    Shortcut for .on('complete', fn).

    show code
    Promise.prototype.addCallback = function (fn) {
    -  return this.on('complete', fn);
    -};

    Returns:


    Promise#addErrback()

    Shortcut for .on('err', fn).

    show code
    Promise.prototype.addErrback = function (fn) {
    -  return this.on('err', fn);
    -};

    Returns:


    Promise#addBack(fn)

    Adds a single function that's both a callback and errback.

    show code
    Promise.prototype.addBack = function (fn) {
    -  this.on('err', function(err){
    -    fn.call(this, err);
    -  });
    -
    -  this.on('complete', function(){
    -    var args = util.args(arguments);
    -    fn.apply(this, [null].concat(args));
    -  });
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Promise#resolve(err, val)

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    show code
    Promise.prototype.resolve = function (err, val) {
    -  if (err) return this.error(err);
    -  return this.complete(val);
    -};

    Parameters:

    • err <Error> optional error or null
    • val <Object> value to complete the promise with

  • query.js

    Query(criteria, options)

    Query constructor used for building queries.

    show code
    function Query (criteria, options) {
    -  this.setOptions(options, true);
    -  this._conditions = {};
    -  this._updateArg = {};
    -  this._fields = undefined;
    -  if (criteria) this.find(criteria);
    -}

    Parameters:

    Example:

    - -
    var query = Model.find();
    -query.where('age').gte(21).exec(callback);

    Query#setOptions(options)

    Sets query options.

    show code
    Query.prototype.setOptions = function (options, overwrite) {
    -  // overwrite is internal use only
    -  if (overwrite) {
    -    options = this.options = options || {};
    -    this.safe = options.safe
    -
    -    // normalize population options
    -    var pop = this.options.populate;
    -    this.options.populate = {};
    -
    -    if (pop && Array.isArray(pop)) {
    -      for (var i = 0, l = pop.length; i < l; i++) {
    -        this.options.populate[pop[i]] = {};
    -      }
    -    }
    -
    -    return this;
    -  }
    -
    -  if (!(options && 'Object' == options.constructor.name))
    -    return this;
    -
    -  if ('safe' in options)
    -    this.safe = options.safe;
    -
    -  // set arbitrary options
    -  var methods = Object.keys(options)
    -    , i = methods.length
    -    , method
    -
    -  while (i--) {
    -    method = methods[i];
    -
    -    // use methods if exist (safer option manipulation)
    -    if ('function' == typeof this[method]) {
    -      var args = Array.isArray(options[method])
    -        ? options[method]
    -        : [options[method]];
    -      this[method].apply(this, args)
    -    } else {
    -      this.options[method] = options[method];
    -    }
    -  }
    -  return this;
    -}

    Parameters:

    Options:

    - - - -

    * denotes a query helper method is also available


    Query#bind(model, op, updateArg)

    Binds this query to a model.

    show code
    Query.prototype.bind = function bind (model, op, updateArg) {
    -  this.model = model;
    -  this.op = op;
    -
    -  if (model._mapreduce) this.options.lean = true;
    -
    -  if (op == 'update' || op == 'findOneAndUpdate') {
    -    merge(this._updateArg, updateArg || {});
    -  }
    -
    -  return this;
    -};

    Parameters:

    • model <Model> the model to which the query is bound
    • op <String> the operation to execute
    • updateArg <Object> used in update methods

    Returns:


    Query#exec([operation], [callback])

    Executes the query

    show code
    Query.prototype.exec = function exec (op, callback) {
    -  var promise = new Promise();
    -
    -  switch (typeof op) {
    -    case 'function':
    -      callback = op;
    -      op = null;
    -      break;
    -    case 'string':
    -      this.op = op;
    -      break;
    -  }
    -
    -  if (callback) promise.addBack(callback);
    -
    -  if (!this.op) {
    -    promise.complete();
    -    return promise;
    -  }
    -
    -  if ('update' == this.op) {
    -    this[this.op](this._updateArg, promise.resolve.bind(promise));
    -    return promise;
    -  }
    -
    -  if ('distinct' == this.op) {
    -    this.distinct(this._distinctArg, promise.resolve.bind(promise));
    -    return promise;
    -  }
    -
    -  this[this.op](promise.resolve.bind(promise));
    -  return promise;
    -};

    Parameters:

    Returns:

    Examples

    - -
    query.exec();
    -query.exec(callback);
    -query.exec('update');
    -query.exec('find', callback);

    Query#find([criteria], [callback])

    Finds documents.

    show code
    Query.prototype.find = function (criteria, callback) {
    -  this.op = 'find';
    -  if ('function' === typeof criteria) {
    -    callback = criteria;
    -    criteria = {};
    -  } else if (criteria instanceof Query) {
    -    // TODO Merge options, too
    -    merge(this._conditions, criteria._conditions);
    -  } else if (criteria instanceof Document) {
    -    merge(this._conditions, criteria.toObject());
    -  } else if (criteria && 'Object' === criteria.constructor.name) {
    -    merge(this._conditions, criteria);
    -  }
    -  if (!callback) return this;
    -  return this.execFind(callback);
    -};

    Parameters:

    Returns:

    When no callback is passed, the query is not executed.

    - -

    Example

    - -
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)

    Query#cast(model, [obj])

    Casts this query to the schema of model

    show code
    Query.prototype.cast = function (model, obj) {
    -  obj || (obj= this._conditions);
    -
    -  var schema = model.schema
    -    , paths = Object.keys(obj)
    -    , i = paths.length
    -    , any$conditionals
    -    , schematype
    -    , nested
    -    , path
    -    , type
    -    , val;
    -
    -  while (i--) {
    -    path = paths[i];
    -    val = obj[path];
    -
    -    if ('$or' === path || '$nor' === path) {
    -      var k = val.length
    -        , orComponentQuery;
    -
    -      while (k--) {
    -        orComponentQuery = new Query(val[k]);
    -        orComponentQuery.cast(model);
    -        val[k] = orComponentQuery._conditions;
    -      }
    -
    -    } else if (path === '$where') {
    -      type = typeof val;
    -
    -      if ('string' !== type && 'function' !== type) {
    -        throw new Error("Must have a string or function for $where");
    -      }
    -
    -      if ('function' === type) {
    -        obj[path] = val.toString();
    -      }
    -
    -      continue;
    -
    -    } else {
    -
    -      if (!schema) {
    -        // no casting for Mixed types
    -        continue;
    -      }
    -
    -      schematype = schema.path(path);
    -
    -      if (!schematype) {
    -        // Handle potential embedded array queries
    -        var split = path.split('.')
    -          , j = split.length
    -          , pathFirstHalf
    -          , pathLastHalf
    -          , remainingConds
    -          , castingQuery;
    -
    -        // Find the part of the var path that is a path of the Schema
    -        while (j--) {
    -          pathFirstHalf = split.slice(0, j).join('.');
    -          schematype = schema.path(pathFirstHalf);
    -          if (schematype) break;
    -        }
    -
    -        // If a substring of the input path resolves to an actual real path...
    -        if (schematype) {
    -          // Apply the casting; similar code for $elemMatch in schema/array.js
    -          if (schematype.caster && schematype.caster.schema) {
    -            remainingConds = {};
    -            pathLastHalf = split.slice(j).join('.');
    -            remainingConds[pathLastHalf] = val;
    -            castingQuery = new Query(remainingConds);
    -            castingQuery.cast(schematype.caster);
    -            obj[path] = castingQuery._conditions[pathLastHalf];
    -          } else {
    -            obj[path] = val;
    -          }
    -        }
    -
    -      } else if (val === null || val === undefined) {
    -        continue;
    -      } else if ('Object' === val.constructor.name) {
    -
    -        any$conditionals = Object.keys(val).some(function (k) {
    -          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
    -        });
    -
    -        if (!any$conditionals) {
    -          obj[path] = schematype.castForQuery(val);
    -        } else {
    -
    -          var ks = Object.keys(val)
    -            , k = ks.length
    -            , $cond;
    -
    -          while (k--) {
    -            $cond = ks[k];
    -            nested = val[$cond];
    -
    -            if ('$exists' === $cond) {
    -              if ('boolean' !== typeof nested) {
    -                throw new Error("$exists parameter must be Boolean");
    -              }
    -              continue;
    -            }
    -
    -            if ('$type' === $cond) {
    -              if ('number' !== typeof nested) {
    -                throw new Error("$type parameter must be Number");
    -              }
    -              continue;
    -            }
    -
    -            if ('$not' === $cond) {
    -              this.cast(model, nested);
    -            } else {
    -              val[$cond] = schematype.castForQuery($cond, nested);
    -            }
    -          }
    -        }
    -      } else {
    -        obj[path] = schematype.castForQuery(val);
    -      }
    -    }
    -  }
    -
    -  return obj;
    -};

    Parameters:

    Returns:

    Note

    - -

    If obj is present, it is cast instead of this query.


    Query#_optionsForExec(model)

    Returns default options.

    show code
    Query.prototype._optionsForExec = function (model) {
    -  var options = utils.clone(this.options, { retainKeyOrder: true });
    -  delete options.populate;
    -
    -  if (!('safe' in options))
    -    options.safe = model.schema.options.safe;
    -
    -  if (!('readPreference' in options) && model.schema.options.read)
    -    options.readPreference = model.schema.options.read;
    -
    -  return options;
    -};

    Parameters:


    Query#_applyPaths()

    Applies schematype selected options to this query.

    show code
    Query.prototype._applyPaths = function applyPaths () {
    -  // determine if query is selecting or excluding fields
    -
    -  var fields = this._fields
    -    , exclude
    -    , keys
    -    , ki
    -
    -  if (fields) {
    -    keys = Object.keys(fields);
    -    ki = keys.length;
    -
    -    while (ki--) {
    -      if ('+' == keys[ki][0]) continue;
    -      exclude = 0 === fields[keys[ki]];
    -      break;
    -    }
    -  }
    -
    -  // if selecting, apply default schematype select:true fields
    -  // if excluding, apply schematype select:false fields
    -
    -  var selected = []
    -    , excluded = []
    -    , seen = [];
    -
    -  analyzeSchema(this.model.schema);
    -
    -  switch (exclude) {
    -    case true:
    -      excluded.length && this.select('-' + excluded.join(' -'));
    -      break;
    -    case false:
    -      selected.length && this.select(selected.join(' '));
    -      break;
    -    case undefined:
    -      // user didn't specify fields, implies returning all fields.
    -      // only need to apply excluded fields
    -      excluded.length && this.select('-' + excluded.join(' -'));
    -      break;
    -  }
    -
    -  return seen = excluded = selected = keys = fields = null;
    -
    -  function analyzeSchema (schema, prefix) {
    -    prefix || (prefix = '');
    -
    -    // avoid recursion
    -    if (~seen.indexOf(schema)) return;
    -    seen.push(schema);
    -
    -    schema.eachPath(function (path, type) {
    -      if (prefix) path = prefix + '.' + path;
    -
    -      // array of subdocs?
    -      if (type.schema) {
    -        analyzeSchema(type.schema, path);
    -      }
    -
    -      analyzePath(path, type);
    -    });
    -  }
    -
    -  function analyzePath (path, type) {
    -    if ('boolean' != typeof type.selected) return;
    -
    -    if (fields && ('+' + path) in fields) {
    -      // forced inclusion
    -      delete fields['+' + path];
    -
    -      // if there are other fields being included, add this one
    -      // if no other included fields, leave this out (implied inclusion)
    -      if (false === exclude && keys.length > 1) {
    -        fields[path] = 1;
    -      }
    -
    -      return
    -    };
    -
    -    ;(type.selected ? selected : excluded).push(path);
    -  }
    -}

    Query#$where(js)

    Specifies a $where condition

    Parameters:

    Returns:

    Use $where when you need to select documents using a JavaScript expression.

    - -

    Example

    - -
    query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
    -
    -query.$where(function () {
    -  return this.comments.length &gt; 10 || this.name.length &gt; 5;
    -})

    Query#where([path], [val])

    Specifies a path for use with chaining.

    show code
    Query.prototype.where = function (path, val) {
    -  if (!arguments.length) return this;
    -
    -  if ('string' != typeof path) {
    -    throw new TypeError('path must be a string');
    -  }
    -
    -  this._currPath = path;
    -
    -  if (2 === arguments.length) {
    -    this._conditions[path] = val;
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    // instead of writing:
    -User.find({age: {$gte: 21, $lte: 65}}, callback);
    -
    -// we can instead write:
    -User.where('age').gte(21).lte(65);
    -
    -// Moreover, you can also chain a bunch of these together:
    -
    -User
    -.where('age').gte(21).lte(65)
    -.where('name', /^b/i)
    -.where('friends').slice(10)
    -.exec(callback)

    Query#equals(val)

    Specifies the complementary comparison value for paths specified with where()

    show code
    Query.prototype.equals = function equals (val) {
    -  var path = this._currPath;
    -  if (!path) throw new Error('equals() must be used after where()');
    -  this._conditions[path] = val;
    -  return this;
    -}

    Parameters:

    Returns:

    Example

    - -
    User.where('age').equals(49);
    -
    -// is the same as
    -
    -User.where('age', 49);

    Query#or(array)

    Specifies arguments for an $or condition.

    show code
    Query.prototype.or = function or (array) {
    -  var or = this._conditions.$or || (this._conditions.$or = []);
    -  if (!Array.isArray(array)) array = [array];
    -  or.push.apply(or, array);
    -  return this;
    -}

    Parameters:

    • array <Array> array of conditions

    Returns:

    Example

    - -
    query.or([{ color: 'red' }, { status: 'emergency' }])

    Query#nor(array)

    Specifies arguments for a $nor condition.

    show code
    Query.prototype.nor = function nor (array) {
    -  var nor = this._conditions.$nor || (this._conditions.$nor = []);
    -  if (!Array.isArray(array)) array = [array];
    -  nor.push.apply(nor, array);
    -  return this;
    -}

    Parameters:

    • array <Array> array of conditions

    Returns:

    Example

    - -
    query.nor([{ color: 'green' }, { status: 'ok' }])

    Query#gt(path, val)

    Specifies a $gt query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.

    - -

    Example

    - -
    Thing.find().where('age').gt(21)
    -
    -// or
    -Thing.find().gt('age', 21)

    Query#gte(path, val)

    Specifies a $gte query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#lt(path, val)

    Specifies a $lt query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#lte(path, val)

    Specifies a $lte query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#ne(path, val)

    Specifies a $ne query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#in(path, val)

    Specifies an $in query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#nin(path, val)

    Specifies an $nin query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#all(path, val)

    Specifies an $all query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#size(path, val)

    Specifies an $size query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#regex(path, val)

    Specifies a $regex query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#maxDistance(path, val)

    Specifies a $maxDistance query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#near(path, val)

    Specifies a $near condition

    show code
    Query.prototype.near = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$near = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#nearSphere(path, val)

    Specifies a $nearSphere condition.

    show code
    Query.prototype.nearSphere = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$nearSphere = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#mod(path, val)

    Specifies a $mod condition

    show code
    Query.prototype.mod = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$mod = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#exists(path, val)

    Specifies an $exists condition

    show code
    Query.prototype.exists = function (path, val) {
    -  if (arguments.length === 0) {
    -    path = this._currPath
    -    val = true;
    -  } else if (arguments.length === 1) {
    -    if ('boolean' === typeof path) {
    -      val = path;
    -      path = this._currPath;
    -    } else {
    -      val = true;
    -    }
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$exists'] = val;
    -  return this;
    -};

    Parameters:

    Returns:


    Query#elemMatch(path, criteria)

    Specifies an $elemMatch condition

    show code
    Query.prototype.elemMatch = function (path, criteria) {
    -  var block;
    -  if ('Object' === path.constructor.name) {
    -    criteria = path;
    -    path = this._currPath;
    -  } else if ('function' === typeof path) {
    -    block = path;
    -    path = this._currPath;
    -  } else if ('Object' === criteria.constructor.name) {
    -  } else if ('function' === typeof criteria) {
    -    block = criteria;
    -  } else {
    -    throw new Error("Argument error");
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  if (block) {
    -    criteria = new Query();
    -    block(criteria);
    -    conds['$elemMatch'] = criteria._conditions;
    -  } else {
    -    conds['$elemMatch'] = criteria;
    -  }
    -  return this;
    -};
    -
    -// Spatial queries

    Parameters:

    Returns:

    Example

    - -
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
    -
    -query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
    -
    -query.elemMatch('comment', function (elem) {
    -  elem.where('author').equals('autobot');
    -  elem.where('votes').gte(5);
    -})
    -
    -query.where('comment').elemMatch(function (elem) {
    -  elem.where('author').equals('autobot');
    -  elem.where('votes').gte(5);
    -})

    Query#box(path, val)

    Specifies a $box condition

    show code
    Query.prototype.box = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$box': [val.ll, val.ur]  };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var lowerLeft = [40.73083, -73.99756]
    -var upperRight= [40.741404,  -73.988135]
    -query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

    Query#center(path, val, [opts])

    Specifies a $center condition

    show code
    Query.prototype.center = function (path, val, opts) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$center': [val.center, val.radius]  };
    -
    -  // copy any options
    -  if (opts && 'Object' == opts.constructor.name) {
    -    utils.options(opts, conds.$within);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var area = { center: [50, 50], radius: 10 }
    -query.where('loc').within.center(area)

    Query#centerSphere(path, val)

    Specifies a $centerSphere condition

    show code
    Query.prototype.centerSphere = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var area = { center: [50, 50], radius: 10 }
    -query.where('loc').within.centerSphere(area)

    Query#polygon(path, val)

    Specifies a $polygon condition

    show code
    Query.prototype.polygon = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$polygon': val };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
    -query.where('loc').within.polygon(polyA)
    -
    -// or
    -var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
    -query.where('loc').within.polygon(polyB)

    Query#select(arg)

    Specifies which document fields to include or exclude

    show code
    Query.prototype.select = function select (arg) {
    -  if (!arg) return this;
    -
    -  var fields = this._fields || (this._fields = {});
    -
    -  if ('Object' === arg.constructor.name) {
    -    Object.keys(arg).forEach(function (field) {
    -      fields[field] = arg[field];
    -    });
    -  } else if (1 === arguments.length && 'string' == typeof arg) {
    -    arg.split(/\s+/).forEach(function (field) {
    -      if (!field) return;
    -      var include = '-' == field[0] ? 0 : 1;
    -      if (include === 0) field = field.substring(1);
    -      fields[field] = include;
    -    });
    -  } else {
    -    throw new TypeError('Invalid select() argument. Must be a string or object.');
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    - -

    Example

    - -
    // include a and b, exclude c
    -query.select('a b -c');
    -
    -// or you may use object notation, useful when
    -// you have keys already prefixed with a "-"
    -query.select({a: 1, b: 1, c: 0});
    -
    -// force inclusion of field excluded at schema level
    -query.select('+path')
    - -

    NOTE:

    - -

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


    Query#slice(path, val)

    Specifies a $slice condition

    show code
    Query.prototype.slice = function (path, val) {
    -  if (arguments.length === 1) {
    -      val = path;
    -      path = this._currPath
    -  } else if (arguments.length === 2) {
    -    if ('number' === typeof path) {
    -      val = [path, val];
    -      path = this._currPath;
    -    }
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var myFields = this._fields || (this._fields = {});
    -  myFields[path] = { '$slice': val };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    query.slice('comments', 5)
    -query.slice('comments', -5)
    -query.slice('comments', [10, 5])
    -query.where('comments').slice(5)
    -query.where('comments').slice([-10, 5])

    Query#sort(arg)

    Sets the sort order

    show code
    Query.prototype.sort = function (arg) {
    -  if (!arg) return this;
    -
    -  var sort = this.options.sort || (this.options.sort = []);
    -
    -  if ('Object' === arg.constructor.name) {
    -    Object.keys(arg).forEach(function (field) {
    -      push(sort, field, arg[field]);
    -    });
    -  } else if (1 === arguments.length && 'string' == typeof arg) {
    -    arg.split(/\s+/).forEach(function (field) {
    -      if (!field) return;
    -      var ascend = '-' == field[0] ? -1 : 1;
    -      if (ascend === -1) field = field.substring(1);
    -      push(sort, field, ascend);
    -    });
    -  } else {
    -    throw new TypeError('Invalid sort() argument. Must be a string or object.');
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    - -

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    - -

    Example

    - -
    // these are equivalent
    -query.sort({ field: 'asc', test: -1 });
    -query.sort('field -test');

    Query#limit(val)

    Specifies the limit option.

    Parameters:

    Example

    - -
    Kitten.find().limit(20)

    Query#skip(val)

    Specifies the skip option.

    Parameters:

    Example

    - -
    Kitten.find().skip(100).limit(20)

    Query#maxscan(val)

    Specifies the maxscan option.

    Parameters:

    Example

    - -
    Kitten.find().maxscan(100)

    Query#batchSize(val)

    Specifies the batchSize option.

    Parameters:

    Example

    - -
    Kitten.find().batchSize(100)

    Query#comment(val)

    Specifies the comment option.

    Parameters:

    Example

    - -
    Kitten.findOne(condition).comment('login query')

    Query#snapshot()

    Specifies this query as a snapshot query.

    show code
    Query.prototype.snapshot = function () {
    -  this.options.snapshot = true;
    -  return this;
    -};

    Returns:

    Example

    - -
    Kitten.find().snapshot()

    Query#hint(val)

    Sets query hints.

    show code
    Query.prototype.hint = function (val) {
    -  if (!val) return this;
    -
    -  var hint = this.options.hint || (this.options.hint = {});
    -
    -  if ('Object' === val.constructor.name) {
    -    // must keep object keys in order so don't use Object.keys()
    -    for (var k in val) {
    -      hint[k] = val[k];
    -    }
    -  } else {
    -    throw new TypeError('Invalid hint. ' + val);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Model.find().hint({ indexA: 1, indexB: -1})

    Query#slaveOk(v)

    Sets the slaveOk option.

    show code
    Query.prototype.slaveOk = function (v) {
    -  this.options.slaveOk = arguments.length ? !!v : true;
    -  return this;
    -}

    Parameters:

    Returns:

    Example:

    - -
    new Query().slaveOk() // true
    -new Query().slaveOk(true)
    -new Query().slaveOk(false)

    Query#read(pref, [tags])

    Sets the readPreference option for the query.

    show code
    Query.prototype.read = function (pref, tags) {
    -  this.options.readPreference = utils.readPref(pref, tags);
    -  return this;
    -}

    Parameters:

    • pref <String> one of the listed preference options or their aliases
    • [tags] <Array> optional tags for this query

    Returns:

    Example:

    - -
    new Query().read('primary')
    -new Query().read('p')  // same as primary
    -
    -new Query().read('primaryPreferred')
    -new Query().read('pp') // same as primaryPreferred
    -
    -new Query().read('secondary')
    -new Query().read('s')  // same as secondary
    -
    -new Query().read('secondaryPreferred')
    -new Query().read('sp') // same as secondaryPreferred
    -
    -new Query().read('nearest')
    -new Query().read('n')  // same as nearest
    -
    -// with tags
    -new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
    - -

    Preferences:

    - -
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
    -secondary            Read from secondary if available, otherwise error.
    -primaryPreferred     Read from primary if available, otherwise a secondary.
    -secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
    -nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
    - -

    Aliases

    - -
    p   primary
    -pp  primaryPreferred
    -s   secondary
    -sp  secondaryPreferred
    -n   nearest
    - -

    Read more about how to use read preferrences here and here.


    Query#lean(v)

    Sets the lean option.

    show code
    Query.prototype.lean = function (v) {
    -  this.options.lean = arguments.length ? !!v : true;
    -  return this;
    -}

    Parameters:

    Returns:

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    - -

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    - -

    Example:

    - -
    new Query().lean() // true
    -new Query().lean(true)
    -new Query().lean(false)
    -
    -Model.find().lean().exec();
    -
    -var leanStream = Model.find().lean().stream();

    Query#tailable(v)

    Sets tailable option.

    show code
    Query.prototype.tailable = function (v) {
    -  this.options.tailable = arguments.length ? !!v : true;
    -  return this;
    -};

    Parameters:

    Example

    - -
    Kitten.find().tailable() &lt;== true
    -Kitten.find().tailable(true)
    -Kitten.find().tailable(false)

    Query#execFind(callback)

    Executes the query as a find() operation.

    show code
    Query.prototype.execFind = function (callback) {
    -  var model = this.model
    -    , promise = new Promise(callback);
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    promise.error(err);
    -    return this;
    -  }
    -
    -  // apply default schematype path selections
    -  this._applyPaths();
    -
    -  var self = this
    -    , castQuery = this._conditions
    -    , options = this._optionsForExec(model)
    -    , fields = utils.clone(this._fields)
    -
    -  options.fields = this._castFields(fields);
    -  if (options.fields instanceof Error) {
    -    promise.error(options.fields);
    -    return this;
    -  }
    -
    -  model.collection.find(castQuery, options, function (err, cursor) {
    -    if (err) return promise.error(err);
    -    cursor.toArray(tick(cb));
    -  });
    -
    -  function cb (err, docs) {
    -    if (err) return promise.error(err);
    -
    -    if (true === options.lean)
    -      return promise.complete(docs);
    -
    -    var arr = []
    -      , count = docs.length;
    -
    -    if (!count) return promise.complete([]);
    -
    -    for (var i = 0, l = docs.length; i < l; i++) {
    -      arr[i] = new model(undefined, fields, true);
    -      arr[i].init(docs[i], self, function (err) {
    -        if (err) return promise.error(err);
    -        --count || promise.complete(arr);
    -      });
    -    }
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Query#findOne(callback)

    Executes the query as a findOne() operation.

    show code
    Query.prototype.findOne = function (callback) {
    -  this.op = 'findOne';
    -
    -  if (!callback) return this;
    -
    -  var model = this.model;
    -  var promise = new Promise(callback);
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    promise.error(err);
    -    return this;
    -  }
    -
    -  // apply default schematype path selections
    -  this._applyPaths();
    -
    -  var self = this
    -    , castQuery = this._conditions
    -    , options = this._optionsForExec(model)
    -    , fields = utils.clone(this._fields)
    -
    -  options.fields = this._castFields(fields);
    -  if (options.fields instanceof Error) {
    -    promise.error(options.fields);
    -    return this;
    -  }
    -
    -  model.collection.findOne(castQuery, options, tick(function (err, doc) {
    -    if (err) return promise.error(err);
    -    if (!doc) return promise.complete(null);
    -
    -    if (true === options.lean) return promise.complete(doc);
    -
    -    var casted = new model(undefined, fields, true);
    -    casted.init(doc, self, function (err) {
    -      if (err) return promise.error(err);
    -      promise.complete(casted);
    -    });
    -  }));
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Kitten.where('color', 'white').findOne(function (err, kitten) {
    -  if (err) return handleError(err);
    -
    -  // kitten may be null if no document matched
    -  if (kitten) {
    -    ...
    -  }
    -})

    Query#count(callback)

    Exectues the query as a count() operation.

    show code
    Query.prototype.count = function (callback) {
    -  this.op = 'count';
    -  var model = this.model;
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    return callback(err);
    -  }
    -
    -  var castQuery = this._conditions;
    -  model.collection.count(castQuery, tick(callback));
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Kitten.where('color', 'black').count(function (err, count) {
    -  if (err) return handleError(err);
    -  console.log('there are %d black kittens', count);
    -})

    Query#distinct(field, callback)

    Executes this query as a distict() operation.

    show code
    Query.prototype.distinct = function (field, callback) {
    -  this.op = 'distinct';
    -  var model = this.model;
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    return callback(err);
    -  }
    -
    -  var castQuery = this._conditions;
    -  model.collection.distinct(field, castQuery, tick(callback));
    -
    -  return this;
    -};

    Parameters:

    Returns:


    Query#update(doc, callback)

    Executes this query as an update() operation.

    show code
    Query.prototype.update = function update (doc, callback) {
    -  this.op = 'update';
    -  this._updateArg = doc;
    -
    -  var model = this.model
    -    , options = this._optionsForExec(model)
    -    , fn = 'function' == typeof callback
    -    , castedQuery
    -    , castedDoc
    -
    -  castedQuery = castQuery(this);
    -  if (castedQuery instanceof Error) {
    -    if (fn) {
    -      process.nextTick(callback.bind(null, castedQuery));
    -      return this;
    -    }
    -    throw castedQuery;
    -  }
    -
    -  castedDoc = castDoc(this);
    -  if (!castedDoc) {
    -    fn && process.nextTick(callback.bind(null, null, 0));
    -    return this;
    -  }
    -
    -  if (castedDoc instanceof Error) {
    -    if (fn) {
    -      process.nextTick(callback.bind(null, castedDoc));
    -      return this;
    -    }
    -    throw castedDoc;
    -  }
    -
    -  if (!fn) {
    -    delete options.safe;
    -  }
    -
    -  model.collection.update(castedQuery, castedDoc, options, tick(callback));
    -  return this;
    -};

    Parameters:

    Returns:

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    - -

    Example

    - -
    Model.update({..}, { title: 'remove words' }, ...)
    - -

    becomes

    - -
    Model.update({..}, { $set: { title: 'remove words' }}, ...)
    - -

    Note

    - -

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


    Query#_castUpdate(obj)

    Casts obj for an update command.

    show code
    Query.prototype._castUpdate = function _castUpdate (obj) {
    -  var ops = Object.keys(obj)
    -    , i = ops.length
    -    , ret = {}
    -    , hasKeys
    -    , val
    -
    -  while (i--) {
    -    var op = ops[i];
    -    if ('$' !== op[0]) {
    -      // fix up $set sugar
    -      if (!ret.$set) {
    -        if (obj.$set) {
    -          ret.$set = obj.$set;
    -        } else {
    -          ret.$set = {};
    -        }
    -      }
    -      ret.$set[op] = obj[op];
    -      ops.splice(i, 1);
    -      if (!~ops.indexOf('$set')) ops.push('$set');
    -    } else if ('$set' === op) {
    -      if (!ret.$set) {
    -        ret[op] = obj[op];
    -      }
    -    } else {
    -      ret[op] = obj[op];
    -    }
    -  }
    -
    -  // cast each value
    -  i = ops.length;
    -
    -  while (i--) {
    -    op = ops[i];
    -    val = ret[op];
    -    if ('Object' === val.constructor.name) {
    -      hasKeys |= this._walkUpdatePath(val, op);
    -    } else {
    -      var msg = 'Invalid atomic update value for ' + op + '. '
    -              + 'Expected an object, received ' + typeof val;
    -      throw new Error(msg);
    -    }
    -  }
    -
    -  return hasKeys && ret;
    -}

    Parameters:

    Returns:

    • <Object> obj after casting its values

    Query#_walkUpdatePath(obj, op, pref)

    Walk each path of obj and cast its values
    according to its schema.

    show code
    Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
    -  var strict = this.model.schema.options.strict
    -    , prefix = pref ? pref + '.' : ''
    -    , keys = Object.keys(obj)
    -    , i = keys.length
    -    , hasKeys = false
    -    , schema
    -    , key
    -    , val
    -
    -  while (i--) {
    -    key = keys[i];
    -    val = obj[key];
    -
    -    if (val && 'Object' === val.constructor.name) {
    -      // watch for embedded doc schemas
    -      schema = this._getSchema(prefix + key);
    -      if (schema && schema.caster && op in castOps) {
    -        // embedded doc schema
    -
    -        if (strict && !schema) {
    -          // path is not in our strict schema
    -          if ('throw' == strict) {
    -            throw new Error('Field `' + key + '` is not in schema.');
    -          } else {
    -            // ignore paths not specified in schema
    -            delete obj[key];
    -          }
    -        } else {
    -          hasKeys = true;
    -          if ('$each' in val) {
    -            obj[key] = {
    -                $each: this._castUpdateVal(schema, val.$each, op)
    -            }
    -          } else {
    -            obj[key] = this._castUpdateVal(schema, val, op);
    -          }
    -        }
    -      } else {
    -        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
    -      }
    -    } else {
    -      schema = '$each' === key
    -        ? this._getSchema(pref)
    -        : this._getSchema(prefix + key);
    -
    -      var skip = strict &&
    -                 !schema &&
    -                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
    -
    -      if (skip) {
    -        if ('throw' == strict) {
    -          throw new Error('Field `' + prefix + key + '` is not in schema.');
    -        } else {
    -          delete obj[key];
    -        }
    -      } else {
    -        hasKeys = true;
    -        obj[key] = this._castUpdateVal(schema, val, op, key);
    -      }
    -    }
    -  }
    -  return hasKeys;
    -}

    Parameters:

    • obj <Object> - part of a query
    • op <String> - the atomic operator ($pull, $set, etc)
    • pref <String> - path prefix (internal only)

    Returns:

    • <Bool> true if this path has keys to update

    Query#_castUpdateVal(schema, val, op, [$conditional])

    Casts val according to schema and atomic op.

    show code
    Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
    -  if (!schema) {
    -    // non-existing schema path
    -    return op in numberOps
    -      ? Number(val)
    -      : val
    -  }
    -
    -  if (schema.caster && op in castOps &&
    -    ('Object' === val.constructor.name || Array.isArray(val))) {
    -    // Cast values for ops that add data to MongoDB.
    -    // Ensures embedded documents get ObjectIds etc.
    -    var tmp = schema.cast(val);
    -
    -    if (Array.isArray(val)) {
    -      val = tmp;
    -    } else {
    -      val = tmp[0];
    -    }
    -  }
    -
    -  if (op in numberOps) return Number(val);
    -  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
    -  return schema.castForQuery(val)
    -}

    Parameters:


    Query#_getSchema(path)

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    show code
    Query.prototype._getSchema = function _getSchema (path) {
    -  var schema = this.model.schema
    -    , pathschema = schema.path(path);
    -
    -  if (pathschema)
    -    return pathschema;
    -
    -  // look for arrays
    -  return (function search (parts, schema) {
    -    var p = parts.length + 1
    -      , foundschema
    -      , trypath
    -
    -    while (p--) {
    -      trypath = parts.slice(0, p).join('.');
    -      foundschema = schema.path(trypath);
    -      if (foundschema) {
    -        if (foundschema.caster) {
    -
    -          // array of Mixed?
    -          if (foundschema.caster instanceof Types.Mixed) {
    -            return foundschema.caster;
    -          }
    -
    -          // Now that we found the array, we need to check if there
    -          // are remaining document paths to look up for casting.
    -          // Also we need to handle array.$.path since schema.path
    -          // doesn't work for that.
    -          if (p !== parts.length) {
    -            if ('$' === parts[p]) {
    -              // comments.$.comments.$.title
    -              return search(parts.slice(p+1), foundschema.schema);
    -            } else {
    -              // this is the last path of the selector
    -              return search(parts.slice(p), foundschema.schema);
    -            }
    -          }
    -        }
    -        return foundschema;
    -      }
    -    }
    -  })(path.split('.'), schema)
    -}

    Parameters:


    Query#_castFields(fields)

    Casts selected field arguments for field selection with mongo 2.2

    show code
    Query.prototype._castFields = function _castFields (fields) {
    -  var selected
    -    , elemMatchKeys
    -    , keys
    -    , key
    -    , out
    -    , i
    -
    -  if (fields) {
    -    keys = Object.keys(fields);
    -    elemMatchKeys = [];
    -    i = keys.length;
    -
    -    // collect $elemMatch args
    -    while (i--) {
    -      key = keys[i];
    -      if (fields[key].$elemMatch) {
    -        selected || (selected = {});
    -        selected[key] = fields[key];
    -        elemMatchKeys.push(key);
    -      }
    -    }
    -  }
    -
    -  if (selected) {
    -    // they passed $elemMatch, cast em
    -    try {
    -      out = this.cast(this.model, selected);
    -    } catch (err) {
    -      return err;
    -    }
    -
    -    // apply the casted field args
    -    i = elemMatchKeys.length;
    -    while (i--) {
    -      key = elemMatchKeys[i];
    -      fields[key] = out[key];
    -    }
    -  }
    -
    -  return fields;
    -}

    Parameters:

    query.select({ ids: { $elemMatch: { $in: [hexString] }})

    Query#remove(callback)

    Executes this query as a remove() operation.

    show code
    Query.prototype.remove = function (callback) {
    -  this.op = 'remove';
    -
    -  var model = this.model
    -    , options = this._optionsForExec(model)
    -    , cb = 'function' == typeof callback
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    if (cb) return callback(err);
    -    throw err;
    -  }
    -
    -  if (!cb) {
    -    delete options.safe;
    -  }
    -
    -  var castQuery = this._conditions;
    -  model.collection.remove(castQuery, options, tick(callback));
    -  return this;
    -};

    Parameters:

    Example

    - -
    Cassette.where('artist').equals('Anne Murray').remove(callback)

    Query#findOneAndUpdate([query], [doc], [options], [callback])

    Issues a mongodb findAndModify update command.

    show code
    Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
    -  this.op = 'findOneAndUpdate';
    -
    -  switch (arguments.length) {
    -    case 3:
    -      if ('function' == typeof options)
    -        callback = options, options = {};
    -      break;
    -    case 2:
    -      if ('function' == typeof doc) {
    -        callback = doc;
    -        doc = query;
    -        query = undefined;
    -      }
    -      options = undefined;
    -      break;
    -    case 1:
    -      if ('function' == typeof query) {
    -        callback = query;
    -        query = options = doc = undefined;
    -      } else {
    -        doc = query;
    -        query = options = undefined;
    -      }
    -  }
    -
    -  // apply query
    -  if (query) {
    -    if ('Object' === query.constructor.name) {
    -      merge(this._conditions, query);
    -    } else if (query instanceof Query) {
    -      merge(this._conditions, query._conditions);
    -    } else if (query instanceof Document) {
    -      merge(this._conditions, query.toObject());
    -    }
    -  }
    -
    -  // apply doc
    -  if (doc) {
    -    merge(this._updateArg, doc);
    -  }
    -
    -  // apply options
    -  options && this.setOptions(options);
    -
    -  if (!callback) return this;
    -
    -  return this._findAndModify('update', callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - -

    Available options

    - -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    - -

    Examples

    - -
    query.findOneAndUpdate(conditions, update, options, callback) // executes
    -query.findOneAndUpdate(conditions, update, options)  // returns Query
    -query.findOneAndUpdate(conditions, update, callback) // executes
    -query.findOneAndUpdate(conditions, update)           // returns Query
    -query.findOneAndUpdate(callback)                     // executes
    -query.findOneAndUpdate()                             // returns Query

    Query#findOneAndRemove([conditions], [options], [callback])

    Issues a mongodb findAndModify remove command.

    show code
    Query.prototype.findOneAndRemove = function (conditions, options, callback) {
    -  this.op = 'findOneAndRemove';
    -
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = undefined;
    -  } else if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = undefined;
    -  }
    -
    -  // apply conditions
    -  if (conditions) {
    -    if ('Object' === conditions.constructor.name) {
    -      merge(this._conditions, conditions);
    -    } else if (conditions instanceof Query) {
    -      merge(this._conditions, conditions._conditions);
    -    } else if (conditions instanceof Document) {
    -      merge(this._conditions, conditions.toObject());
    -    }
    -  }
    -
    -  // apply options
    -  options && this.setOptions(options);
    -
    -  if (!callback) return this;
    -
    -  return this._findAndModify('remove', callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    - -

    Available options

    - -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    - -

    Examples

    - -
    A.where().findOneAndRemove(conditions, options, callback) // executes
    -A.where().findOneAndRemove(conditions, options)  // return Query
    -A.where().findOneAndRemove(conditions, callback) // executes
    -A.where().findOneAndRemove(conditions) // returns Query
    -A.where().findOneAndRemove(callback)   // executes
    -A.where().findOneAndRemove()           // returns Query

    Query#_findAndModify(type, callback)

    _findAndModify

    show code
    Query.prototype._findAndModify = function (type, callback) {
    -  var model = this.model
    -    , promise = new Promise(callback)
    -    , self = this
    -    , castedQuery
    -    , castedDoc
    -    , fields
    -    , sort
    -    , opts
    -
    -  castedQuery = castQuery(this);
    -  if (castedQuery instanceof Error) {
    -    process.nextTick(promise.error.bind(promise, castedQuery));
    -    return promise;
    -  }
    -
    -  opts = this._optionsForExec(model);
    -
    -  if ('remove' == type) {
    -    opts.remove = true;
    -  } else {
    -    if (!('new' in opts)) opts.new = true;
    -    if (!('upsert' in opts)) opts.upsert = false;
    -
    -    castedDoc = castDoc(this);
    -    if (!castedDoc) {
    -      if (opts.upsert) {
    -        // still need to do the upsert to empty doc
    -        castedDoc = { $set: {} };
    -      } else {
    -        return this.findOne(callback);
    -      }
    -    } else if (castedDoc instanceof Error) {
    -      process.nextTick(promise.error.bind(promise, castedDoc));
    -      return promise;
    -    }
    -  }
    -
    -  if (this._fields) {
    -    fields = utils.clone(this._fields)
    -    opts.fields = this._castFields(fields);
    -    if (opts.fields instanceof Error) {
    -      process.nextTick(promise.error.bind(promise, opts.fields));
    -      return promise;
    -    }
    -  }
    -
    -  // the driver needs a default
    -  sort = opts.sort || [];
    -
    -  model
    -  .collection
    -  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
    -    if (err) return promise.error(err);
    -    if (!doc) return promise.complete(null);
    -
    -    if (true === opts.lean) {
    -      return promise.complete(doc);
    -    }
    -
    -    var casted = new model(undefined, fields, true);
    -    casted.init(doc, self, function (err) {
    -      if (err) return promise.error(err);
    -      promise.complete(casted);
    -    });
    -  }));
    -
    -  return promise;
    -}

    Parameters:


    Query#populate(path, [fields], [model], [conditions], [options])

    Specifies paths which should be populated with other documents.

    show code
    Query.prototype.populate = function (path, fields, model, conditions, options) {
    -  if ('string' !== typeof model) {
    -    options = conditions;
    -    conditions = model;
    -    model = undefined;
    -  }
    -  // The order of fields/conditions args is opposite Model.find but
    -  // necessary to keep backward compatibility (fields could be
    -  // an array, string, or object literal).
    -  this.options.populate[path] =
    -    new PopulateOptions(fields, conditions, options, model);
    -
    -  return this;
    -};

    Parameters:

    Returns:

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    - -

    Example:

    - -
    Kitten.findOne().populate('owner').exec(function (err, kitten) {
    -  console.log(kitten.owner.name) // Max
    -})

    Query#stream()

    Returns a stream interface

    show code
    Query.prototype.stream = function stream () {
    -  return new QueryStream(this);
    -}
    -
    -// helpers

    Returns:

    Example

    - -
    // follows the nodejs stream api
    -Thing.find({ name: /^hello/ }).stream().pipe(res)
    -
    -// manual streaming
    -var stream = Thing.find({ name: /^hello/ }).stream();
    -
    -stream.on('data', function (doc) {
    -  // do something with the mongoose document
    -}).on('error', function (err) {
    -  // handle the error
    -}).on('close', function () {
    -  // the stream is closed
    -});

    Query#within

    Syntax sugar for expressive queries.

    - -

    Example

    - -
    query.within.box()
    -query.within.center()

    Returns:


  • querystream.js

    QueryStream(query)

    Provides a ReadStream interface for Queries.

    show code
    function QueryStream (query) {
    -  Stream.call(this);
    -
    -  this.query = query;
    -  this.readable = true;
    -  this.paused = false;
    -  this._cursor = null;
    -  this._destroyed = null;
    -  this._fields = null;
    -  this._buffer = null;
    -  this._inline = T_INIT;
    -  this._running = false;
    -
    -  // give time to hook up events
    -  var self = this;
    -  process.nextTick(function () {
    -    self._init();
    -  });
    -}

    Parameters:

    Inherits:

    Events:

    • data: emits a single Mongoose document

    • error: emits when an error occurs during streaming. This will emit before the close event.

    • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

    var stream = Model.find().stream();
    -
    -stream.on('data', function (doc) {
    -  // do something with the mongoose document
    -}).on('error', function (err) {
    -  // handle the error
    -}).on('close', function () {
    -  // the stream is closed
    -});
    - -

    The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

    - -
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

    QueryStream#_init()

    Initializes the query.

    show code
    QueryStream.prototype._init = function () {
    -  if (this._destroyed) return;
    -
    -  var query = this.query
    -    , model = query.model
    -    , options = query._optionsForExec(model)
    -    , self = this
    -
    -  try {
    -    query.cast(model);
    -  } catch (err) {
    -    return self.destroy(err);
    -  }
    -
    -  self._fields = utils.clone(query._fields);
    -  options.fields = query._castFields(self._fields);
    -
    -  model.collection.find(query._conditions, options, function (err, cursor) {
    -    if (err) return self.destroy(err);
    -    self._cursor = cursor;
    -    self._next();
    -  });
    -}

    QueryStream#_next()

    Trampoline for pulling the next doc from cursor.

    show code
    QueryStream.prototype._next = function _next () {
    -  if (this.paused || this._destroyed) {
    -    return this._running = false;
    -  }
    -
    -  this._running = true;
    -
    -  if (this._buffer && this._buffer.length) {
    -    var arg;
    -    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
    -      this._onNextObject.apply(this, arg);
    -    }
    -  }
    -
    -  // avoid stack overflows with large result sets.
    -  // trampoline instead of recursion.
    -  while (this.__next()) {}
    -}

    QueryStream#__next()

    Pulls the next doc from the cursor.

    show code
    QueryStream.prototype.__next = function () {
    -  if (this.paused || this._destroyed)
    -    return this._running = false;
    -
    -  var self = this;
    -  self._inline = T_INIT;
    -
    -  self._cursor.nextObject(function cursorcb (err, doc) {
    -    self._onNextObject(err, doc);
    -  });
    -
    -  // if onNextObject() was already called in this tick
    -  // return ourselves to the trampoline.
    -  if (T_CONT === this._inline) {
    -    return true;
    -  } else {
    -    // onNextObject() hasn't fired yet. tell onNextObject
    -    // that its ok to call _next b/c we are not within
    -    // the trampoline anymore.
    -    this._inline = T_IDLE;
    -  }
    -}

    QueryStream#_onNextObject(err, doc)

    Transforms raw docs returned from the cursor into a model instance.

    show code
    QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
    -  if (this._destroyed) return;
    -
    -  if (this.paused) {
    -    this._buffer || (this._buffer = []);
    -    this._buffer.push([err, doc]);
    -    return this._running = false;
    -  }
    -
    -  if (err) return this.destroy(err);
    -
    -  // when doc is null we hit the end of the cursor
    -  if (!doc) {
    -    this.emit('end');
    -    return this.destroy();
    -  }
    -
    -  if (this.query.options && true === this.query.options.lean)  {
    -    this.emit('data', doc);
    -
    -    // trampoline management
    -    if (T_IDLE === this._inline) {
    -      // no longer in trampoline. restart it.
    -      this._next();
    -    } else {
    -      // in a trampoline. tell __next that its
    -      // ok to continue jumping.
    -      this._inline = T_CONT;
    -    }
    -    return;
    -  }
    -
    -  var instance = new this.query.model(undefined, this._fields, true);
    -
    -  var self = this;
    -  instance.init(doc, this.query, function (err) {
    -    if (err) return self.destroy(err);
    -    self.emit('data', instance);
    -
    -    // trampoline management
    -    if (T_IDLE === self._inline) {
    -      // no longer in trampoline. restart it.
    -      self._next();
    -    } else
    -      // in a trampoline. tell __next that its
    -      // ok to continue jumping.
    -      self._inline = T_CONT;
    -  });
    -}

    Parameters:


    QueryStream#pause()

    Pauses this stream.

    show code
    QueryStream.prototype.pause = function () {
    -  this.paused = true;
    -}

    QueryStream#resume()

    Resumes this stream.

    show code
    QueryStream.prototype.resume = function () {
    -  this.paused = false;
    -
    -  if (!this._cursor) {
    -    // cannot start if not initialized
    -    return;
    -  }
    -
    -  // are we within the trampoline?
    -  if (T_INIT === this._inline) {
    -    return;
    -  }
    -
    -  if (!this._running) {
    -    // outside QueryStream control, need manual restart
    -    return this._next();
    -  }
    -}

    QueryStream#destroy([err])

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    show code
    QueryStream.prototype.destroy = function (err) {
    -  if (this._destroyed) return;
    -  this._destroyed = true;
    -  this._running = false;
    -  this.readable = false;
    -
    -  if (this._cursor) {
    -    this._cursor.close();
    -  }
    -
    -  if (err) {
    -    this.emit('error', err);
    -  }
    -
    -  this.emit('close');
    -}

    Parameters:


    QueryStream#pipe()

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    See:

    Example:

    - -
    query.stream().pipe(writeStream [, options])
    - -

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    - -
    var format = new ArrayFormatter;
    -Events.find().stream().pipe(format).pipe(res);
    - -

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


    QueryStream#paused

    Flag stating whether or not this stream is paused.


    QueryStream#readable

    Flag stating whether or not this stream is readable.


  • schema/array.js

    SchemaArray(key, cast, options)

    Array SchemaType constructor

    show code
    function SchemaArray (key, cast, options) {
    -  if (cast) {
    -    var castOptions = {};
    -
    -    if ('Object' === cast.constructor.name) {
    -      if (cast.type) {
    -        // support { type: Woot }
    -        castOptions = cast;
    -        cast = cast.type;
    -        delete castOptions.type;
    -      } else {
    -        cast = Mixed;
    -      }
    -    }
    -
    -    var caster = cast.name in Types ? Types[cast.name] : cast;
    -    this.casterConstructor = caster;
    -    this.caster = new caster(null, castOptions);
    -  }
    -
    -  SchemaType.call(this, key, options);
    -
    -  var self = this
    -    , defaultArr
    -    , fn;
    -
    -  if (this.defaultValue) {
    -    defaultArr = this.defaultValue;
    -    fn = 'function' == typeof defaultArr;
    -  }
    -
    -  this.default(function(){
    -    var arr = fn ? defaultArr() : defaultArr || [];
    -    return new MongooseArray(arr, self.path, this);
    -  });
    -};

    Parameters:

    Inherits:


    SchemaArray#checkRequired(value)

    Check required

    show code
    SchemaArray.prototype.checkRequired = function (value) {
    -  return !!(value && value.length);
    -};

    Parameters:


    SchemaArray#applyGetters(value, scope)

    Overrides the getters application for the population special-case

    show code
    SchemaArray.prototype.applyGetters = function (value, scope) {
    -  if (this.caster.options && this.caster.options.ref) {
    -    // means the object id was populated
    -    return value;
    -  }
    -
    -  return SchemaType.prototype.applyGetters.call(this, value, scope);
    -};

    Parameters:


    SchemaArray#cast(value, doc, init)

    Casts contents

    show code
    SchemaArray.prototype.cast = function (value, doc, init) {
    -  if (Array.isArray(value)) {
    -    if (!(value instanceof MongooseArray)) {
    -      value = new MongooseArray(value, this.path, doc);
    -    }
    -
    -    if (this.caster) {
    -      try {
    -        for (var i = 0, l = value.length; i < l; i++) {
    -          value[i] = this.caster.cast(value[i], doc, init);
    -        }
    -      } catch (e) {
    -        // rethrow
    -        throw new CastError(e.type, value);
    -      }
    -    }
    -
    -    return value;
    -  } else {
    -    return this.cast([value], doc, init);
    -  }
    -};

    Parameters:

    • value <Object>
    • doc <Document> document that triggers the casting
    • init <Boolean> whether this is an initialization cast

    SchemaArray#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaArray.prototype.castForQuery = function ($conditional, value) {
    -  var handler
    -    , val;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Array.");
    -    val = handler.call(this, value);
    -  } else {
    -    val = $conditional;
    -    var proto = this.casterConstructor.prototype;
    -    var method = proto.castForQuery || proto.cast;
    -    if (Array.isArray(val)) {
    -      val = val.map(function (v) {
    -        if (method) v = method.call(proto, v);
    -        return isMongooseObject(v)
    -          ? v.toObject()
    -          : v;
    -      });
    -    } else if (method) {
    -      val = method.call(proto, val);
    -    }
    -  }
    -  return val && isMongooseObject(val)
    -    ? val.toObject()
    -    : val;
    -};

    Parameters:


  • schema/boolean.js

    SchemaBoolean(path, options)

    Boolean SchemaType constructor.

    show code
    function SchemaBoolean (path, options) {
    -  SchemaType.call(this, path, options);
    -};

    Parameters:

    Inherits:


    SchemaBoolean#checkRequired()

    Required validator

    show code
    SchemaBoolean.prototype.checkRequired = function (value) {
    -  return value === true || value === false;
    -};

    SchemaBoolean#cast(value)

    Casts to boolean

    show code
    SchemaBoolean.prototype.cast = function (value) {
    -  if (value === null) return value;
    -  if (value === '0') return false;
    -  return !!value;
    -};

    Parameters:


    SchemaBoolean#castForQuery($conditional, val)

    Casts contents for queries.

    show code
    SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (2 === arguments.length) {
    -    handler = SchemaBoolean.$conditionalHandlers[$conditional];
    -
    -    if (handler) {
    -      return handler.call(this, val);
    -    }
    -
    -    return this.cast(val);
    -  }
    -
    -  return this.cast($conditional);
    -};

    Parameters:


  • schema/buffer.js

    SchemaBuffer(key, cast)

    Buffer SchemaType constructor

    show code
    function SchemaBuffer (key, options) {
    -  SchemaType.call(this, key, options, 'Buffer');
    -};

    Parameters:

    Inherits:


    SchemaBuffer#checkRequired()

    Check required

    show code
    SchemaBuffer.prototype.checkRequired = function (value) {
    -  return !!(value && value.length);
    -};

    SchemaBuffer#cast(value, doc, init)

    Casts contents

    show code
    SchemaBuffer.prototype.cast = function (value, doc, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  if (Buffer.isBuffer(value)) {
    -    if (!(value instanceof MongooseBuffer)) {
    -      value = new MongooseBuffer(value, [this.path, doc]);
    -    }
    -
    -    return value;
    -  } else if (value instanceof Binary) {
    -    return new MongooseBuffer(value.value(true), [this.path, doc]);
    -  }
    -
    -  if ('string' === typeof value || Array.isArray(value)) {
    -    return new MongooseBuffer(value, [this.path, doc]);
    -  }
    -
    -  throw new CastError('buffer', value);
    -};

    Parameters:


    SchemaBuffer#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Buffer.");
    -    return handler.call(this, val);
    -  } else {
    -    val = $conditional;
    -    return this.cast(val).toObject();
    -  }
    -};

    Parameters:


  • schema/date.js

    SchemaDate(key, options)

    Date SchemaType constructor.

    show code
    function SchemaDate (key, options) {
    -  SchemaType.call(this, key, options);
    -};

    Parameters:

    Inherits:


    SchemaDate#checkRequired()

    Required validator for date

    show code
    SchemaDate.prototype.checkRequired = function (value) {
    -  return value instanceof Date;
    -};

    SchemaDate#cast(value)

    Casts to date

    show code
    SchemaDate.prototype.cast = function (value) {
    -  if (value === null || value === '')
    -    return null;
    -
    -  if (value instanceof Date)
    -    return value;
    -
    -  var date;
    -
    -  // support for timestamps
    -  if (value instanceof Number || 'number' == typeof value 
    -      || String(value) == Number(value))
    -    date = new Date(Number(value));
    -
    -  // support for date strings
    -  else if (value.toString)
    -    date = new Date(value.toString());
    -
    -  if (date.toString() != 'Invalid Date')
    -    return date;
    -
    -  throw new CastError('date', value);
    -};

    Parameters:


    SchemaDate#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaDate.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -
    -  if (2 !== arguments.length) {
    -    return this.cast($conditional);
    -  }
    -
    -  handler = this.$conditionalHandlers[$conditional];
    -
    -  if (!handler) {
    -    throw new Error("Can't use " + $conditional + " with Date.");
    -  }
    -
    -  return handler.call(this, val);
    -};

    Parameters:


  • schema/documentarray.js

    DocumentArray(key, schema, options)

    SubdocsArray SchemaType constructor

    show code
    function DocumentArray (key, schema, options) {
    -
    -  // compile an embedded document for this schema
    -  function EmbeddedDocument () {
    -    Subdocument.apply(this, arguments);
    -  }
    -
    -  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
    -  EmbeddedDocument.prototype._setSchema(schema);
    -  EmbeddedDocument.schema = schema;
    -
    -  // apply methods
    -  for (var i in schema.methods) {
    -    EmbeddedDocument.prototype[i] = schema.methods[i];
    -  }
    -
    -  // apply statics
    -  for (var i in schema.statics)
    -    EmbeddedDocument[i] = schema.statics[i];
    -
    -  EmbeddedDocument.options = options;
    -  this.schema = schema;
    -
    -  ArrayType.call(this, key, EmbeddedDocument, options);
    -
    -  this.schema = schema;
    -  var path = this.path;
    -  var fn = this.defaultValue;
    -
    -  this.default(function(){
    -    var arr = fn.call(this);
    -    if (!Array.isArray(arr)) arr = [arr];
    -    return new MongooseDocumentArray(arr, path, this);
    -  });
    -};

    Parameters:

    Inherits:


    DocumentArray#doValidate()

    Performs local validations first, then validations on each embedded doc

    show code
    DocumentArray.prototype.doValidate = function (array, fn, scope) {
    -  var self = this;
    -
    -  SchemaType.prototype.doValidate.call(this, array, function (err) {
    -    if (err) return fn(err);
    -
    -    var count = array && array.length
    -      , error;
    -
    -    if (!count) return fn();
    -
    -    // handle sparse arrays, do not use array.forEach which does not
    -    // iterate over sparse elements yet reports array.length including
    -    // them :(
    -
    -    for (var i = 0, len = count; i < len; ++i) {
    -      // sidestep sparse entries
    -      var doc = array[i];
    -      if (!doc) {
    -        --count || fn();
    -        continue;
    -      }
    -
    -      ;(function (i) {
    -        doc.validate(function (err) {
    -          if (err && !error) {
    -            // rewrite the key
    -            err.key = self.key + '.' + i + '.' + err.key;
    -            return fn(error = err);
    -          }
    -          --count || fn();
    -        });
    -      })(i);
    -    }
    -  }, scope);
    -};

    DocumentArray#cast(value, document)

    Casts contents

    show code
    DocumentArray.prototype.cast = function (value, doc, init, prev) {
    -  var selected
    -    , subdoc
    -    , i
    -
    -  if (!Array.isArray(value)) {
    -    return this.cast([value], doc, init, prev);
    -  }
    -
    -  if (!(value instanceof MongooseDocumentArray)) {
    -    value = new MongooseDocumentArray(value, this.path, doc);
    -  }
    -
    -  i = value.length;
    -
    -  while (i--) {
    -    if (!(value[i] instanceof Subdocument) && value[i]) {
    -      if (init) {
    -        selected || (selected = scopePaths(this, doc._selected, init));
    -        subdoc = new this.casterConstructor(null, value, true, selected);
    -        value[i] = subdoc.init(value[i]);
    -      } else {
    -        if (prev && (subdoc = prev.id(value[i]._id))) {
    -          // handle resetting doc with existing id but differing data
    -          // doc.array = [{ doc: 'val' }]
    -          subdoc.set(value[i]);
    -        } else {
    -          subdoc = new this.casterConstructor(value[i], value);
    -        }
    -
    -        // if set() is hooked it will have no return value
    -        // see gh-746
    -        value[i] = subdoc;
    -      }
    -    }
    -  }
    -
    -  return value;
    -}

    Parameters:


  • schema/mixed.js

    Mixed(path, options)

    Mixed SchemaType constructor.

    show code
    function Mixed (path, options) {
    -  // make sure empty array defaults are handled
    -  if (options &&
    -      options.default &&
    -      Array.isArray(options.default) &&
    -      0 === options.default.length) {
    -    options.default = Array;
    -  }
    -
    -  SchemaType.call(this, path, options);
    -};

    Parameters:

    Inherits:


    Mixed#checkRequired()

    Required validator

    show code
    Mixed.prototype.checkRequired = function (val) {
    -  return true;
    -};

    Mixed#cast(value)

    Casts val for Mixed.

    show code
    Mixed.prototype.cast = function (val) {
    -  return val;
    -};

    Parameters:

    this is a no-op


    Mixed#castForQuery($cond, [val])

    Casts contents for queries.

    show code
    Mixed.prototype.castForQuery = function ($cond, val) {
    -  if (arguments.length === 2) return val;
    -  return $cond;
    -};

    Parameters:


  • schema/number.js

    SchemaNumber(key, options)

    Number SchemaType constructor.

    show code
    function SchemaNumber (key, options) {
    -  SchemaType.call(this, key, options, 'Number');
    -};

    Parameters:

    Inherits:


    SchemaNumber#checkRequired()

    Required validator for number

    show code
    SchemaNumber.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return typeof value == 'number' || value instanceof Number;
    -  }
    -};

    SchemaNumber#min(value, message)

    Sets a maximum number validator.

    show code
    SchemaNumber.prototype.min = function (value, message) {
    -  if (this.minValidator)
    -    this.validators = this.validators.filter(function(v){
    -      return v[1] != 'min';
    -    });
    -  if (value != null)
    -    this.validators.push([function(v){
    -      return v === null || v >= value;
    -    }, 'min']);
    -  return this;
    -};

    Parameters:

    Example:

    - -
    var s = new Schema({ n: { type: Number, min: 10 })
    -var M = db.model('M', s)
    -var m = new M({ n: 9 })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.n = 10;
    -  m.save() // success
    -})

    SchemaNumber#max(maximum, message)

    Sets a maximum number validator.

    show code
    SchemaNumber.prototype.max = function (value, message) {
    -  if (this.maxValidator)
    -    this.validators = this.validators.filter(function(v){
    -      return v[1] != 'max';
    -    });
    -  if (value != null)
    -    this.validators.push([this.maxValidator = function(v){
    -      return v === null || v <= value;
    -    }, 'max']);
    -  return this;
    -};

    Parameters:

    Example:

    - -
    var s = new Schema({ n: { type: Number, max: 10 })
    -var M = db.model('M', s)
    -var m = new M({ n: 11 })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.n = 10;
    -  m.save() // success
    -})

    SchemaNumber#cast(value, doc, init)

    Casts to number

    show code
    SchemaNumber.prototype.cast = function (value, doc, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  if (!isNaN(value)){
    -    if (null === value) return value;
    -    if ('' === value) return null;
    -    if ('string' == typeof value) value = Number(value);
    -    if (value instanceof Number) return value
    -    if ('number' == typeof value) return value;
    -    if (value.toString && !Array.isArray(value) &&
    -        value.toString() == Number(value)) {
    -      return new Number(value)
    -    }
    -  }
    -
    -  throw new CastError('number', value);
    -};

    Parameters:


    SchemaNumber#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaNumber.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Number.");
    -    return handler.call(this, val);
    -  } else {
    -    val = this.cast($conditional);
    -    return val == null ? val : val
    -  }
    -};

    Parameters:


  • schema/objectid.js

    ObjectId(key, options)

    ObjectId SchemaType constructor.

    show code
    function ObjectId (key, options) {
    -  SchemaType.call(this, key, options, 'ObjectID');
    -};

    Parameters:

    Inherits:


    ObjectId#checkRequired()

    Check required

    show code
    ObjectId.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return value instanceof oid;
    -  }
    -};

    ObjectId#cast(value, scope, init)

    Casts to ObjectId

    show code
    ObjectId.prototype.cast = function (value, scope, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  if (value === null) return value;
    -
    -  if (value instanceof oid)
    -    return value;
    -
    -  if (value._id && value._id instanceof oid)
    -    return value._id;
    -
    -  if (value.toString)
    -    return oid.fromString(value.toString());
    -
    -  throw new CastError('object id', value);
    -};

    Parameters:


    ObjectId#castForQuery($conditional, [val])

    Casts contents for queries.

    show code
    ObjectId.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with ObjectId.");
    -    return handler.call(this, val);
    -  } else {
    -    return this.cast($conditional);
    -  }
    -};

    Parameters:


    ObjectId#auto(turnOn)

    Adds an auto-generated ObjectId default if turnOn is true.

    show code
    ObjectId.prototype.auto = function (turnOn) {
    -  if (turnOn) {
    -    this.default(defaultId);
    -    this.set(resetId)
    -  }
    -};

    Parameters:

    • turnOn <Boolean> auto generated ObjectId defaults

  • schema/string.js

    SchemaString(key, options)

    String SchemaType constructor.

    show code
    function SchemaString (key, options) {
    -  this.enumValues = [];
    -  this.regExp = null;
    -  SchemaType.call(this, key, options, 'String');
    -};

    Parameters:

    Inherits:


    SchemaString#enum([args...])

    Adds enumeration values and a coinciding validator.

    show code
    SchemaString.prototype.enum = function () {
    -  var len = arguments.length;
    -  if (!len || undefined === arguments[0] || false === arguments[0]) {
    -    if (this.enumValidator){
    -      this.enumValidator = false;
    -      this.validators = this.validators.filter(function(v){
    -        return v[1] != 'enum';
    -      });
    -    }
    -    return;
    -  }
    -
    -  for (var i = 0; i < len; i++) {
    -    if (undefined !== arguments[i]) {
    -      this.enumValues.push(this.cast(arguments[i]));
    -    }
    -  }
    -
    -  if (!this.enumValidator) {
    -    var values = this.enumValues;
    -    this.enumValidator = function(v){
    -      return undefined === v || ~values.indexOf(v);
    -    };
    -    this.validators.push([this.enumValidator, 'enum']);
    -  }
    -};

    Parameters:

    • [args...] <String> enumeration values

    Example:

    - -
    var states = 'opening open closing closed'.split(' ')
    -var s = new Schema({ state: { type: String, enum: states })
    -var M = db.model('M', s)
    -var m = new M({ state: 'invalid' })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.state = 'open'
    -  m.save() // success
    -})

    SchemaString#lowercase()

    Adds a lowercase setter.

    show code
    SchemaString.prototype.lowercase = function () {
    -  return this.set(function (v, self) {
    -    if ('string' != typeof v) v = self.cast(v)
    -    if (v) return v.toLowerCase();
    -    return v;
    -  });
    -};

    Example:

    - -
    var s = new Schema({ email: { type: String, lowercase: true }})
    -var M = db.model('M', s);
    -var m = new M({ email: 'SomeEmail@example.COM' });
    -console.log(m.email) // someemail@example.com
    -

    SchemaString#uppercase()

    Adds an uppercase setter.

    show code
    SchemaString.prototype.uppercase = function () {
    -  return this.set(function (v, self) {
    -    if ('string' != typeof v) v = self.cast(v)
    -    if (v) return v.toUpperCase();
    -    return v;
    -  });
    -};

    Example:

    - -
    var s = new Schema({ caps: { type: String, uppercase: true }})
    -var M = db.model('M', s);
    -var m = new M({ caps: 'an example' });
    -console.log(m.caps) // AN EXAMPLE

    SchemaString#trim()

    Adds a trim setter.

    show code
    SchemaString.prototype.trim = function () {
    -  return this.set(function (v, self) {
    -    if ('string' != typeof v) v = self.cast(v)
    -    if (v) return v.trim();
    -    return v;
    -  });
    -};

    The string value will be trimmed when set.

    - -

    Example:

    - -
    var s = new Schema({ name: { type: String, trim: true }})
    -var M = db.model('M', s)
    -var string = ' some name '
    -console.log(string.length) // 11
    -var m = new M({ name: string })
    -console.log(m.name.length) // 9

    SchemaString#match(regExp)

    Sets a regexp validator.

    show code
    SchemaString.prototype.match = function match (regExp) {
    -  this.validators.push([function(v){
    -    return null != v && '' !== v
    -      ? regExp.test(v)
    -      : true
    -  }, 'regexp']);
    -};

    Parameters:

    • regExp <RegExp> regular expression to test against

    Any value that does not pass regExp.test(val) will fail validation.

    - -

    Example:

    - -
    var s = new Schema({ name: { type: String, match: /^a/ }})
    -var M = db.model('M', s)
    -var m = new M({ name: 'invalid' })
    -m.validate(function (err) {
    -  console.error(err) // validation error
    -  m.name = 'apples'
    -  m.validate(function (err) {
    -    assert.ok(err) // success
    -  })
    -})

    SchemaString#checkRequired(value)

    Check required

    show code
    SchemaString.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return (value instanceof String || typeof value == 'string') && value.length;
    -  }
    -};

    Parameters:


    SchemaString#cast()

    Casts to String

    show code
    SchemaString.prototype.cast = function (value, scope, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -  if (value === null) return value;
    -  if ('undefined' !== typeof value && value.toString) return value.toString();
    -  throw new CastError('string', value);
    -};

    SchemaString#castForQuery($conditional, [val])

    Casts contents for queries.

    show code
    SchemaString.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with String.");
    -    return handler.call(this, val);
    -  } else {
    -    val = $conditional;
    -    if (val instanceof RegExp) return val;
    -    return this.cast(val);
    -  }
    -};

    Parameters:


  • schema.js

    Schema(definition)

    Schema constructor.

    show code
    function Schema (obj, options) {
    -  if (!(this instanceof Schema))
    -    return new Schema(obj, options);
    -
    -  this.paths = {};
    -  this.subpaths = {};
    -  this.virtuals = {};
    -  this.nested = {};
    -  this.inherits = {};
    -  this.callQueue = [];
    -  this._indexes = [];
    -  this.methods = {};
    -  this.statics = {};
    -  this.tree = {};
    -  this._requiredpaths = undefined;
    -
    -  this.options = this.defaultOptions(options);
    -
    -  // build paths
    -  if (obj) {
    -    this.add(obj);
    -  }
    -
    -  // ensure the documents get an auto _id unless disabled
    -  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
    -  if (auto_id) {
    -    this.add({ _id: {type: Schema.ObjectId, auto: true} });
    -  }
    -
    -  // ensure the documents receive an id getter unless disabled
    -  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
    -  if (autoid) {
    -    this.virtual('id').get(idGetter);
    -  }
    -
    -  // versioning not directly added to schema b/c we only want
    -  // it in the top level document, not embedded ones.
    -};

    Parameters:

    Events:

    • init: Emitted after the schema is compiled into a Model.

    Example:

    - -
    var child = new Schema({ name: String });
    -var schema = new Schema({ name: String, age: Number, children: [child] });
    -var Tree = mongoose.model('Tree', schema);
    -
    -// setting schema options
    -new Schema({ name: String }, { _id: false, autoIndex: false })
    - -

    Options:

    - -
      -
    • safe: bool - defaults to true.
    • -
    • read: string
    • -
    • strict: bool - defaults to true
    • -
    • capped: bool - defaults to false
    • -
    • versionKey: bool - defaults to "__v"
    • -
    • shardKey: bool - defaults to null
    • -
    • autoIndex: bool - defaults to true
    • -
    • _id: bool - defaults to true
    • -
    • id: bool - defaults to true
    • -
    • toObject - object - no default
    • -
    • toJSON - object - no default
    • -
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • -
    - -

    Note:

    - -

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


    Schema#defaultOptions(options)

    Returns default options for this schema, merged with options.

    show code
    Schema.prototype.defaultOptions = function (options) {
    -  options = utils.options({
    -      safe: true
    -    , strict: true
    -    , capped: false // { size, max, autoIndexId }
    -    , versionKey: '__v'
    -    , minimize: true
    -    , autoIndex: true
    -    , shardKey: null
    -    , read: null
    -    // the following are only applied at construction time
    -    , noId: false // deprecated, use { _id: false }
    -    , _id: true
    -    , noVirtualId: false // deprecated, use { id: false }
    -    , id: true
    -  }, options);
    -
    -  if (options.read)
    -    options.read = utils.readPref(options.read);
    -
    -  return options;
    -}

    Parameters:

    Returns:


    Schema#add(obj, prefix)

    Adds key path / schema type pairs to this schema.

    show code
    Schema.prototype.add = function add (obj, prefix) {
    -  prefix = prefix || '';
    -  for (var i in obj) {
    -    if (null == obj[i]) {
    -      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
    -    }
    -
    -    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
    -      if (Object.keys(obj[i]).length) {
    -        // nested object { last: { name: String }}
    -        this.nested[prefix + i] = true;
    -        this.add(obj[i], prefix + i + '.');
    -      }
    -      else
    -        this.path(prefix + i, obj[i]); // mixed type
    -    } else
    -      this.path(prefix + i, obj[i]);
    -  }
    -};

    Parameters:

    Example:

    - -
    var ToySchema = new Schema;
    -ToySchema.add({ name: 'string', color: 'string', price: 'number' });

    Schema#path(path, constructor)

    Gets/sets schema paths.

    show code
    Schema.prototype.path = function (path, obj) {
    -  if (obj == undefined) {
    -    if (this.paths[path]) return this.paths[path];
    -    if (this.subpaths[path]) return this.subpaths[path];
    -
    -    // subpaths?
    -    return /\.\d+\.?$/.test(path)
    -      ? getPositionalPath(this, path)
    -      : undefined;
    -  }
    -
    -  // some path names conflict with document methods
    -  if (reserved[path]) {
    -    throw new Error("`" + path + "` may not be used as a schema pathname");
    -  }
    -
    -  // update the tree
    -  var subpaths = path.split(/\./)
    -    , last = subpaths.pop()
    -    , branch = this.tree;
    -
    -  subpaths.forEach(function(path) {
    -    if (!branch[path]) branch[path] = {};
    -    branch = branch[path];
    -  });
    -
    -  branch[last] = utils.clone(obj);
    -
    -  this.paths[path] = Schema.interpretAsType(path, obj);
    -  return this;
    -};

    Parameters:

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    - -

    Example

    - -
    schema.path('name') // returns a SchemaType
    -schema.path('name', Number) // changes the schemaType of `name` to Number

    Schema#eachPath(fn)

    Iterates the schemas paths similar to Array#forEach.

    show code
    Schema.prototype.eachPath = function (fn) {
    -  var keys = Object.keys(this.paths)
    -    , len = keys.length;
    -
    -  for (var i = 0; i < len; ++i) {
    -    fn(keys[i], this.paths[keys[i]]);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Returns:

    The callback is passed the pathname and schemaType as arguments on each iteration.


    Schema#requiredPaths()

    Returns an Array of path strings that are required by this schema.

    show code
    Schema.prototype.requiredPaths = function requiredPaths () {
    -  if (this._requiredpaths) return this._requiredpaths;
    -
    -  var paths = Object.keys(this.paths)
    -    , i = paths.length
    -    , ret = [];
    -
    -  while (i--) {
    -    var path = paths[i];
    -    if (this.paths[path].isRequired) ret.push(path);
    -  }
    -
    -  return this._requiredpaths = ret;
    -}

    Returns:


    Schema#pathType(path)

    Returns the pathType of path for this schema.

    show code
    Schema.prototype.pathType = function (path) {
    -  if (path in this.paths) return 'real';
    -  if (path in this.virtuals) return 'virtual';
    -  if (path in this.nested) return 'nested';
    -  if (path in this.subpaths) return 'real';
    -
    -  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
    -    return 'real';
    -  } else {
    -    return 'adhocOrUndefined'
    -  }
    -};

    Parameters:

    Returns:

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


    Schema#queue(name, args)

    Adds a method call to the queue.

    show code
    Schema.prototype.queue = function(name, args){
    -  this.callQueue.push([name, args]);
    -  return this;
    -};

    Parameters:

    • name <String> name of the document method to call later
    • args <Array> arguments to pass to the method

    Schema#pre(method, callback)

    Defines a pre hook for the document.

    show code
    Schema.prototype.pre = function(){
    -  return this.queue('pre', arguments);
    -};

    Parameters:

    Example

    - -
    var toySchema = new Schema(..);
    -
    -toySchema.pre('save', function (next) {
    -  if (!this.created) this.created = new Date;
    -  next();
    -})
    -
    -toySchema.pre('validate', function (next) {
    -  if (this.name != 'Woody') this.name = 'Woody';
    -  next();
    -})

    Schema#post(method, fn)

    Defines a post hook for the document.

    show code
    Schema.prototype.post = function(method, fn){
    -  return this.queue('on', arguments);
    -};

    Parameters:

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    - -
    var schema = new Schema(..);
    -schema.post('save', function () {
    -  console.log('this fired after a document was saved');
    -});
    -
    -var Model = mongoose.model('Model', schema);
    -
    -var m = new Model(..);
    -m.save(function (err) {
    -  console.log('this fires after the `post` hook');
    -});

    Schema#plugin(plugin, opts)

    Registers a plugin for this schema.

    show code
    Schema.prototype.plugin = function (fn, opts) {
    -  fn(this, opts);
    -  return this;
    -};

    Parameters:


    Schema#method(method, [fn])

    Adds an instance method to documents constructed from Models compiled from this schema.

    show code
    Schema.prototype.method = function (name, fn) {
    -  if ('string' != typeof name)
    -    for (var i in name)
    -      this.methods[i] = name[i];
    -  else
    -    this.methods[name] = fn;
    -  return this;
    -};

    Parameters:

    Example

    - -
    var schema = kittySchema = new Schema(..);
    -
    -schema.methods.meow = function () {
    -  console.log('meeeeeoooooooooooow');
    -})
    -
    -var Kitty = mongoose.model('Kitty', schema);
    -
    -var fizz = new Kitty;
    -fizz.meow(); // meeeeeooooooooooooow
    - -

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    - -
    schema.method({
    -    purr: function () {}
    -  , scratch: function () {}
    -});
    -
    -// later
    -fizz.purr();
    -fizz.scratch();

    Schema#static(name, fn)

    Adds static "class" methods to Models compiled from this schema.

    show code
    Schema.prototype.static = function(name, fn) {
    -  if ('string' != typeof name)
    -    for (var i in name)
    -      this.statics[i] = name[i];
    -  else
    -    this.statics[name] = fn;
    -  return this;
    -};

    Parameters:

    Example

    - -
    var schema = new Schema(..);
    -schema.static('findByName', function (name, callback) {
    -  return this.find({ name: name }, callback);
    -});
    -
    -var Drink = mongoose.model('Drink', schema);
    -Drink.findByName('sanpellegrino', function (err, drinks) {
    -  //
    -});
    - -

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


    Schema#index(fields, [options])

    Defines an index (most likely compound) for this schema.

    show code
    Schema.prototype.index = function (fields, options) {
    -  options || (options = {});
    -
    -  if (options.expires)
    -    utils.expires(options);
    -
    -  this._indexes.push([fields, options]);
    -  return this;
    -};

    Parameters:

    Example

    - -
    schema.index({ first: 1, last: -1 })

    Schema#set(key, [value])

    Sets/gets a schema option.

    show code
    Schema.prototype.set = function (key, value, tags) {
    -  if (arguments.length == 1)
    -    return this.options[key];
    -
    -  this.options[key] = 'read' == key
    -    ? utils.readPref(value, tags)
    -    : value;
    -
    -  return this;
    -};

    Parameters:

    • key <String> option name
    • [value] <Object> if not passed, the current option value is returned

    Schema#indexes()

    Compiles indexes from fields and schema-level indexes

    show code
    Schema.prototype.indexes = function () {
    -  var indexes = []
    -    , seenSchemas = [];
    -
    -  collectIndexes(this);
    -
    -  return indexes;
    -
    -  function collectIndexes (schema, prefix) {
    -    if (~seenSchemas.indexOf(schema)) return;
    -    seenSchemas.push(schema);
    -
    -    var index;
    -    var paths = schema.paths;
    -    prefix = prefix || '';
    -
    -    for (var i in paths) {
    -      if (paths[i]) {
    -        if (paths[i] instanceof Types.DocumentArray) {
    -          collectIndexes(paths[i].schema, i + '.');
    -        } else {
    -          index = paths[i]._index;
    -
    -          if (index !== false && index !== null){
    -            var field = {};
    -            field[prefix + i] = '2d' === index ? index : 1;
    -            var options = 'Object' === index.constructor.name ? index : {};
    -            if (!('background' in options)) options.background = true;
    -            indexes.push([field, options]);
    -          }
    -        }
    -      }
    -    }
    -
    -    if (prefix) {
    -      fixSubIndexPaths(schema, prefix);
    -    } else {
    -      schema._indexes.forEach(function (index) {
    -        if (!('background' in index[1])) index[1].background = true;
    -      });
    -      indexes = indexes.concat(schema._indexes);
    -    }
    -  }

    Schema#virtual(name, [options])

    Creates a virtual type with the given name.

    show code
    Schema.prototype.virtual = function (name, options) {
    -  var virtuals = this.virtuals;
    -  var parts = name.split('.');
    -  return virtuals[name] = parts.reduce(function (mem, part, i) {
    -    mem[part] || (mem[part] = (i === parts.length-1)
    -                            ? new VirtualType(options, name)
    -                            : {});
    -    return mem[part];
    -  }, this.tree);
    -};

    Parameters:

    Returns:


    Schema#virtualpath(name)

    Returns the virtual type with the given name.

    show code
    Schema.prototype.virtualpath = function (name) {
    -  return this.virtuals[name];
    -};

    Parameters:

    Returns:


    Schema#namedScope()

    These still haven't been fixed. Once they're working we'll make them public again.

    show code
    Schema.prototype.namedScope = function (name, fn) {
    -  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
    -    , newScope = Object.create(namedScopes)
    -    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
    -  allScopes[name] = newScope;
    -  newScope.name = name;
    -  newScope.block = fn;
    -  newScope.query = new Query();
    -  newScope.decorate(namedScopes, {
    -    block0: function (block) {
    -      return function () {
    -        block.call(this.query);
    -        return this;
    -      };
    -    },
    -    blockN: function (block) {
    -      return function () {
    -        block.apply(this.query, arguments);
    -        return this;
    -      };
    -    },
    -    basic: function (query) {
    -      return function () {
    -        this.query.find(query);
    -        return this;
    -      };
    -    }
    -  });
    -  return newScope;
    -};

    Schema.reserved

    Reserved document keys.

    show code
    Schema.reserved = Object.create(null);
    -var reserved = Schema.reserved;
    -reserved.on =
    -reserved.db =
    -reserved.init =
    -reserved.isNew =
    -reserved.errors =
    -reserved.schema =
    -reserved.options =
    -reserved.modelName =
    -reserved.collection = 1;

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    - -
    on, db, init, isNew, errors, schema, options, modelName, collection
    - -

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    - -
    var schema = new Schema(..);
    - schema.methods.init = function () {} // potentially breaking

    Schema.interpretAsType(path, obj)

    Converts type arguments into Mongoose Types.

    show code
    Schema.interpretAsType = function (path, obj) {
    -  if (obj.constructor.name != 'Object')
    -    obj = { type: obj };
    -
    -  // Get the type making sure to allow keys named "type"
    -  // and default to mixed if not specified.
    -  // { type: { type: String, default: 'freshcut' } }
    -  var type = obj.type && !obj.type.type
    -    ? obj.type
    -    : {};
    -
    -  if ('Object' == type.constructor.name || 'mixed' == type) {
    -    return new Types.Mixed(path, obj);
    -  }
    -
    -  if (Array.isArray(type) || Array == type || 'array' == type) {
    -    // if it was specified through { type } look for `cast`
    -    var cast = (Array == type || 'array' == type)
    -      ? obj.cast
    -      : type[0];
    -
    -    if (cast instanceof Schema) {
    -      return new Types.DocumentArray(path, cast, obj);
    -    }
    -
    -    if ('string' == typeof cast) {
    -      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
    -    } else if (cast && (!cast.type || cast.type.type)
    -                    && 'Object' == cast.constructor.name
    -                    && Object.keys(cast).length) {
    -      return new Types.DocumentArray(path, new Schema(cast), obj);
    -    }
    -
    -    return new Types.Array(path, cast || Types.Mixed, obj);
    -  }
    -
    -  var name = 'string' == typeof type
    -    ? type
    -    : type.name;
    -
    -  if (name) {
    -    name = name.charAt(0).toUpperCase() + name.substring(1);
    -  }
    -
    -  if (undefined == Types[name]) {
    -    throw new TypeError('Undefined type at `' + path +
    -        '`
    -  Did you try nesting Schemas? ' +
    -        'You can only nest using refs or arrays.');
    -  }
    -
    -  return new Types[name](path, obj);
    -};

    Parameters:


    Schema.Types

    The various Mongoose Schema Types.

    show code
    Schema.Types = require('./schema/index');

    Example:

    - -

    Example:

    - -
    var mongoose = require('mongoose');
    -var ObjectId = mongoose.Schema.Types.ObjectId;
    - -

    Types:

    - -
      -
    • String
    • -
    • Number
    • -
    • Boolean | Bool
    • -
    • Array
    • -
    • Buffer
    • -
    • Date
    • -
    • ObjectId | Oid
    • -
    • Mixed
    • -
    - -

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    - -
    var Mixed = mongoose.Schema.Types.Mixed;
    -new mongoose.Schema({ _user: Mixed })

    Schema#tree

    Schema as a tree

    - -

    Example:

    - -
    {
    -    '_id'     : ObjectId
    -  , 'nested'  : {
    -        'key' : String
    -    }
    -}

    Schema#paths

    Schema as flat paths

    - -

    Example:

    - -
    {
    -    '_id'        : SchemaType,
    -  , 'nested.key' : SchemaType,
    -}

  • schemadefault.js

    exports#system.profile

    Default model for querying the system.profiles collection.


  • schematype.js

    SchemaType(path, [options], [instance])

    SchemaType constructor

    show code
    function SchemaType (path, options, instance) {
    -  this.path = path;
    -  this.instance = instance;
    -  this.validators = [];
    -  this.setters = [];
    -  this.getters = [];
    -  this.options = options;
    -  this._index = null;
    -  this.selected;
    -
    -  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
    -    // { unique: true, index: true }
    -    if ('index' == i && this._index) continue;
    -
    -    var opts = Array.isArray(options[i])
    -      ? options[i]
    -      : [options[i]];
    -
    -    this[i].apply(this, opts);
    -  }
    -};

    Parameters:


    SchemaType#default(val)

    Sets a default value for this SchemaType.

    show code
    SchemaType.prototype.default = function (val) {
    -  if (1 === arguments.length) {
    -    this.defaultValue = typeof val === 'function'
    -      ? val
    -      : this.cast(val);
    -    return this;
    -  } else if (arguments.length > 1) {
    -    this.defaultValue = utils.args(arguments);
    -  }
    -  return this.defaultValue;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var schema = new Schema({ n: { type: Number, default: 10 })
    -var M = db.model('M', schema)
    -var m = new M;
    -console.log(m.n) // 10
    - -

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    - -

    Example:

    - -
    // values are cast:
    -var schema = new Schema({ aNumber: Number, default: "4.815162342" })
    -var M = db.model('M', schema)
    -var m = new M;
    -console.log(m.aNumber) // 4.815162342
    -
    -// default unique objects for Mixed types:
    -var schema = new Schema({ mixed: Schema.Types.Mixed });
    -schema.path('mixed').default(function () {
    -  return {};
    -});
    -
    -// if we don't use a function to return object literals for Mixed defaults,
    -// each document will receive a reference to the same object literal creating
    -// a "shared" object instance:
    -var schema = new Schema({ mixed: Schema.Types.Mixed });
    -schema.path('mixed').default({});
    -var M = db.model('M', schema);
    -var m1 = new M;
    -m1.mixed.added = 1;
    -console.log(m1.mixed); // { added: 1 }
    -var m2 = new M;
    -console.log(m2.mixed); // { added: 1 }

    SchemaType#index(options)

    Declares the index options for this schematype.

    show code
    SchemaType.prototype.index = function (options) {
    -  this._index = options;
    -  utils.expires(this._index);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var s = new Schema({ name: { type: String, index: true })
    -var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
    -Schema.path('my.path').index(true);
    -Schema.path('my.path').index({ expires: 60 });
    -Schema.path('my.path').index({ unique: true, sparse: true });
    - -

    NOTE:

    - -

    Indexes are created in the background by default. Specify background: false to override.

    - -

    Direction doesn't matter for single key indexes


    SchemaType#unique(bool)

    Declares an unique index.

    show code
    SchemaType.prototype.unique = function (bool) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    -
    -  this._index.unique = bool;
    -  return this;
    -};

    Parameters:

    Returns:

    Examples:

    - -
    var s = new Schema({ name: { type: String, unique: true })
    -Schema.path('name').index({ unique: true });

    SchemaType#sparse(bool)

    Declares a sparse index.

    show code
    SchemaType.prototype.sparse = function (bool) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    -
    -  this._index.sparse = bool;
    -  return this;
    -};

    Parameters:

    Returns:

    Examples:

    - -
    var s = new Schema({ name: { type: String, sparse: true })
    -Schema.path('name').index({ sparse: true });

    SchemaType#expires(when)

    Declares a TTL index (rounded to the nearest second) for Date types only.

    show code
    SchemaType.prototype.expires = function (when) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    -
    -  this._index.expires = when;
    -  utils.expires(this._index);
    -  return this;
    -};

    Parameters:

    Returns:

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    - -

    Example:

    - -
    // expire in 24 hours
    -new Schema({..}, { expires: 60*60*24 });
    - -

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    - -

    Example:

    - -
    // expire in 24 hours
    -new Schema({..}, { expires: '24h' });
    -
    -// expire in 1.5 hours
    -new Schema({..}, { expires: '1.5h' });
    -
    -// expire in 7 days
    -var schema = new Schema({..});
    -schema.expires('7d');

    SchemaType#set(fn)

    Adds a setter to this schematype.

    show code
    SchemaType.prototype.set = function (fn) {
    -  if ('function' != typeof fn)
    -    throw new Error('A setter must be a function.');
    -  this.setters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    function capitalize (val) {
    -  if ('string' != typeof val) val = '';
    -  return val.charAt(0).toUpperCase() + val.substring(1);
    -}
    -
    -// defining within the schema
    -var s = new Schema({ name: { type: String, set: capitalize }})
    -
    -// or by retreiving its SchemaType
    -var s = new Schema({ name: String })
    -s.path('name').set(capitalize)
    - -

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    - -

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    - -

    You can set up email lower case normalization easily via a Mongoose setter.

    - -
    function toLower (v) {
    -  return v.toLowerCase();
    -}
    -
    -var UserSchema = new Schema({
    -  email: { type: String, set: toLower }
    -})
    -
    -var User = db.model('User', UserSchema)
    -
    -var user = new User({email: 'AVENUE@Q.COM'})
    -console.log(user.email); // 'avenue@q.com'
    -
    -// or
    -var user = new User
    -user.email = 'Avenue@Q.com'
    -console.log(user.email) // 'avenue@q.com'
    -
    - -

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    - -

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    - -
    new Schema({ email: { type: String, lowercase: true }})

    SchemaType#get(fn)

    Adds a getter to this schematype.

    show code
    SchemaType.prototype.get = function (fn) {
    -  if ('function' != typeof fn)
    -    throw new Error('A getter must be a function.');
    -  this.getters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    function dob (val) {
    -  if (!val) return val;
    -  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
    -}
    -
    -// defining within the schema
    -var s = new Schema({ born: { type: Date, get: dob })
    -
    -// or by retreiving its SchemaType
    -var s = new Schema({ born: Date })
    -s.path('born').get(dob)
    - -

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    - -

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    - -
    function obfuscate (cc) {
    -  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
    -}
    -
    -var AccountSchema = new Schema({
    -  creditCardNumber: { type: String, get: obfuscate }
    -});
    -
    -var Account = db.model('Account', AccountSchema);
    -
    -Account.findById(id, function (err, found) {
    -  console.log(found.creditCardNumber); // '****-****-****-1234'
    -});

    SchemaType#validate(obj, [error])

    Adds validator(s) for this document path.

    show code
    SchemaType.prototype.validate = function (obj, error) {
    -  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
    -    this.validators.push([obj, error]);
    -    return this;
    -  }
    -
    -  var i = arguments.length
    -    , arg
    -
    -  while (i--) {
    -    arg = arguments[i];
    -    if (!(arg && 'Object' == arg.constructor.name)) {
    -      var msg = 'Invalid validator. Received (' + typeof arg + ') '
    -        + arg
    -        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
    -
    -      throw new Error(msg);
    -    }
    -    this.validate(arg.validator, arg.msg);
    -  }
    -
    -  return this;
    -};

    Parameters:

    Validators must return Boolean. Returning false is interpreted as validation failure.

    - -

    Examples:

    - -
    function validator () { ... }
    -
    -var single = [validator, 'failed']
    -new Schema({ name: { type: String, validate: single }});
    -
    -var many = [
    -    { validator: validator, msg: 'uh oh' }
    -  , { validator: fn, msg: 'failed' }
    -]
    -new Schema({ name: { type: String, validate: many }});
    -
    -// or utilizing SchemaType methods directly:
    -
    -var schema = new Schema({ name: 'string' });
    -schema.path('name').validate(validator, 'validation failed');
    - -

    Asynchronous validation:

    - -

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    - -
    schema.path('name').validate(function (value, respond) {
    -  doStuff(value, function () {
    -    ...
    -    respond(false); // validation failed
    -  })
    - }, 'my error type');
    - -

    Validation occurs pre('save') or whenever you manually execute document#validate.

    - -

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    - -
    var conn = mongoose.createConnection(..);
    -conn.on('error', handleError);
    -
    -var Product = conn.model('Product', yourSchema);
    -var dvd = new Product(..);
    -dvd.save(); // emits error on the `conn` above
    - -

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    - -
    // registering an error listener on the Model lets us handle errors more locally
    -Product.on('error', handleError);

    SchemaType#required(required)

    Adds a required validator to this schematype.

    show code
    SchemaType.prototype.required = function (required) {
    -  var self = this;
    -
    -  function __checkRequired (v) {
    -    // in here, `this` refers to the validating document.
    -    // no validation when this path wasn't selected in the query.
    -    if ('isSelected' in this &&
    -        !this.isSelected(self.path) &&
    -        !this.isModified(self.path)) return true;
    -    return self.checkRequired(v);
    -  }
    -
    -  if (false === required) {
    -    this.isRequired = false;
    -    this.validators = this.validators.filter(function (v) {
    -      return v[0].name !== '__checkRequired';
    -    });
    -  } else {
    -    this.isRequired = true;
    -    this.validators.push([__checkRequired, 'required']);
    -  }
    -
    -  return this;
    -};

    Parameters:

    • required <Boolean> enable/disable the validator

    Returns:

    Example:

    - -
    var s = new Schema({ born: { type: Date, required: true })
    -// or
    -Schema.path('name').required(true);

    SchemaType#getDefault(scope, init)

    Gets the default value

    show code
    SchemaType.prototype.getDefault = function (scope, init) {
    -  var ret = 'function' === typeof this.defaultValue
    -    ? this.defaultValue.call(scope)
    -    : this.defaultValue;
    -
    -  if (null !== ret && undefined !== ret) {
    -    return this.cast(ret, scope, init);
    -  } else {
    -    return ret;
    -  }
    -};

    Parameters:

    • scope <Object> the scope which callback are executed
    • init <Boolean>

    SchemaType#applySetters(value, scope, init)

    Applies setters

    show code
    SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -
    -  var v = value
    -    , setters = this.setters
    -    , len = setters.length
    -
    -  if (!len) {
    -    if (null === v || undefined === v) return v;
    -    return init
    -      ? v // if we just initialized we dont recast
    -      : this.cast(v, scope, init, priorVal)
    -  }
    -
    -  while (len--) {
    -    v = setters[len].call(scope, v, this);
    -  }
    -
    -  if (null === v || undefined === v) return v;
    -
    -  // do not cast until all setters are applied #665
    -  v = this.cast(v, scope, init, priorVal);
    -
    -  return v;
    -};

    Parameters:


    SchemaType#applyGetters(value, scope)

    Applies getters to a value

    show code
    SchemaType.prototype.applyGetters = function (value, scope) {
    -  if (SchemaType._isRef(this, value, true)) return value;
    -
    -  var v = value
    -    , getters = this.getters
    -    , len = getters.length;
    -
    -  if (!len) {
    -    return v;
    -  }
    -
    -  while (len--) {
    -    v = getters[len].call(scope, v, this);
    -  }
    -
    -  return v;
    -};

    Parameters:


    SchemaType#select(val)

    Sets default select() behavior for this path.

    show code
    SchemaType.prototype.select = function select (val) {
    -  this.selected = !! val;
    -}

    Parameters:

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    - -

    Example:

    - -
    T = db.model('T', new Schema({ x: { type: String, select: true }}));
    -T.find(..); // field x will always be selected ..
    -// .. unless overridden;
    -T.find().select('-x').exec(callback);

    SchemaType#doValidate(value, callback, scope)

    Performs a validation of value using the validators declared for this SchemaType.

    show code
    SchemaType.prototype.doValidate = function (value, fn, scope) {
    -  var err = false
    -    , path = this.path
    -    , count = this.validators.length;
    -
    -  if (!count) return fn(null);
    -
    -  function validate (val, msg) {
    -    if (err) return;
    -    if (val === undefined || val) {
    -      --count || fn(null);
    -    } else {
    -      fn(err = new ValidatorError(path, msg));
    -    }
    -  }
    -
    -  this.validators.forEach(function (v) {
    -    var validator = v[0]
    -      , message   = v[1];
    -
    -    if (validator instanceof RegExp) {
    -      validate(validator.test(value), message);
    -    } else if ('function' === typeof validator) {
    -      if (2 === validator.length) {
    -        validator.call(scope, value, function (val) {
    -          validate(val, message);
    -        });
    -      } else {
    -        validate(validator.call(scope, value), message);
    -      }
    -    }
    -  });
    -};

    Parameters:


    SchemaType._isRef(self, value, init)

    Determines if value is a valid Reference.

    show code
    SchemaType._isRef = function (self, value, init) {
    -  if (init && self.options && self.options.ref) {
    -    if (null == value) return true;
    -    if (value._id && value._id.constructor.name === self.instance) return true;
    -  }
    -
    -  return false;
    -}

    Parameters:

    Returns:


  • types/array.js

    MongooseArray(values, path, doc)

    Mongoose Array constructor.

    show code
    function MongooseArray (values, path, doc) {
    -  var arr = [];
    -  arr.push.apply(arr, values);
    -  arr.__proto__ = MongooseArray.prototype;
    -
    -  arr._atomics = {};
    -  arr.validators = [];
    -  arr._path = path;
    -
    -  if (doc) {
    -    arr._parent = doc;
    -    arr._schema = doc.schema.path(path);
    -  }
    -
    -  return arr;
    -};

    Parameters:

    Inherits:

    NOTE:

    - -

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


    MongooseArray#_cast(value)

    Casts a member based on this arrays schema.

    show code
    MongooseArray.prototype._cast = function (value) {
    -  var cast = this._schema.caster.cast
    -    , doc = this._parent;
    -
    -  return cast.call(null, value, doc);
    -};

    Parameters:

    Returns:

    • <value> the casted value

    MongooseArray#_markModified(embeddedDoc, embeddedPath)

    Marks this array as modified.

    show code
    MongooseArray.prototype._markModified = function (elem, embeddedPath) {
    -  var parent = this._parent
    -    , dirtyPath;
    -
    -  if (parent) {
    -    dirtyPath = this._path;
    -
    -    if (arguments.length) {
    -      if (null != embeddedPath) {
    -        // an embedded doc bubbled up the change
    -        dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
    -      } else {
    -        // directly set an index
    -        dirtyPath = dirtyPath + '.' + elem;
    -      }
    -
    -    }
    -    parent.markModified(dirtyPath);
    -  }
    -
    -  return this;
    -};

    Parameters:

    • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
    • embeddedPath <String> the path which changed in the embeddedDoc

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


    MongooseArray#_registerAtomic(op, val)

    Register an atomic operation with the parent.

    show code
    MongooseArray.prototype._registerAtomic = function (op, val) {
    -  if ('$set' == op) {
    -    // $set takes precedence over all other ops.
    -    // mark entire array modified.
    -    this._atomics = { $set: val };
    -    this._markModified();
    -    return this;
    -  }
    -
    -  var atomics = this._atomics;
    -
    -  // reset pop/shift after save
    -  if ('$pop' == op && !('$pop' in atomics)) {
    -    var self = this;
    -    this._parent.once('save', function () {
    -      self._popped = self._shifted = null;
    -    });
    -  }
    -
    -  if (this._atomics.$set) {
    -    return this;
    -  }
    -
    -  // check for impossible $atomic combos (Mongo denies more than one
    -  // $atomic op on a single path
    -  if (Object.keys(atomics).length && !(op in atomics)) {
    -    // a different op was previously registered.
    -    // save the entire thing.
    -    this._atomics = { $set: this };
    -    this._markModified();
    -    return this;
    -  }
    -
    -  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
    -    atomics[op] || (atomics[op] = []);
    -    atomics[op] = atomics[op].concat(val);
    -  } else if (op === '$pullDocs') {
    -    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
    -      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
    -    selector['$in'] = selector['$in'].concat(val);
    -  } else {
    -    atomics[op] = val;
    -  }
    -
    -  this._markModified();
    -  return this;
    -};

    Parameters:


    MongooseArray#hasAtomics()

    Returns the number of pending atomic operations to send to the db for this array.

    show code
    MongooseArray.prototype.hasAtomics = function hasAtomics () {
    -  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
    -    return 0;
    -  }
    -
    -  return Object.keys(this._atomics).length;
    -}

    Returns:


    MongooseArray#push([args...])

    Wraps Array#push with proper change tracking.

    show code
    MongooseArray.prototype.push = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , ret = [].push.apply(this, values);
    -
    -  // $pushAll might be fibbed (could be $push). But it makes it easier to
    -  // handle what could have been $push, $pushAll combos
    -  this._registerAtomic('$pushAll', values);
    -  return ret;
    -};

    Parameters:


    MongooseArray#nonAtomicPush([args...])

    Pushes items to the array non-atomically.

    show code
    MongooseArray.prototype.nonAtomicPush = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , ret = [].push.apply(this, values);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -};

    Parameters:

    • [args...] <any>

    NOTE:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#$pop()

    Pops the array atomically at most one time per document save().

    NOTE:

    - -

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    - -
    doc.array = [1,2,3];
    -
    - var popped = doc.array.$pop();
    - console.log(popped); // 3
    - console.log(doc.array); // [1,2]
    -
    - // no affect
    - popped = doc.array.$pop();
    - console.log(doc.array); // [1,2]
    -
    - doc.save(function (err) {
    -   if (err) return handleError(err);
    -
    -   // we saved, now $pop works again
    -   popped = doc.array.$pop();
    -   console.log(popped); // 2
    -   console.log(doc.array); // [1]
    - })

    MongooseArray#pop()

    Wraps Array#pop with proper change tracking.

    show code
    MongooseArray.prototype.pop = function () {
    -  var ret = [].pop.call(this);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -};

    Note:

    - -

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#$shift()

    Atomically shifts the array at most one time per document save().

    NOTE:

    - -

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    - -
    doc.array = [1,2,3];
    -
    - var shifted = doc.array.$shift();
    - console.log(shifted); // 1
    - console.log(doc.array); // [2,3]
    -
    - // no affect
    - shifted = doc.array.$shift();
    - console.log(doc.array); // [2,3]
    -
    - doc.save(function (err) {
    -   if (err) return handleError(err);
    -
    -   // we saved, now $shift works again
    -   shifted = doc.array.$shift();
    -   console.log(shifted ); // 2
    -   console.log(doc.array); // [3]
    - })

    MongooseArray#shift()

    Wraps Array#shift with proper change tracking.

    show code
    MongooseArray.prototype.shift = function () {
    -  var ret = [].shift.call(this);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -};

    Example:

    - -
    doc.array = [2,3];
    -var res = doc.array.shift();
    -console.log(res) // 2
    -console.log(doc.array) // [3]
    - -

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#remove([args...])

    Removes items from an array atomically

    show code
    MongooseArray.prototype.remove = function () {
    -  var args = [].map.call(arguments, this._cast, this);
    -  if (args.length == 1)
    -    this.pull(args[0]);
    -  else
    -    this.pull.apply(this, args);
    -  return args;
    -};

    Parameters:

    • [args...] <Object> values to remove

    Examples:

    - -
    doc.array.remove(ObjectId)
    -doc.array.remove('tag 1', 'tag 2')

    MongooseArray#pull([args...])

    Pulls items from the array atomically.

    show code
    MongooseArray.prototype.pull = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , cur = this._parent.get(this._path)
    -    , i = cur.length
    -    , mem;
    -
    -  while (i--) {
    -    mem = cur[i];
    -    if (mem instanceof EmbeddedDocument) {
    -      if (values.some(function (v) { return v.equals(mem); } )) {
    -        [].splice.call(cur, i, 1);
    -      }
    -    } else if (~cur.indexOf.call(values, mem)) {
    -      [].splice.call(cur, i, 1);
    -    }
    -  }
    -
    -  if (values[0] instanceof EmbeddedDocument) {
    -    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
    -  } else {
    -    this._registerAtomic('$pullAll', values);
    -  }
    -
    -  return this;
    -};

    Parameters:

    • [args...] <any>

    MongooseArray#splice()

    Wraps Array#splice with proper change tracking and casting.

    show code
    MongooseArray.prototype.splice = function splice () {
    -  var ret, vals, i;
    -
    -  if (arguments.length) {
    -    vals = [];
    -    for (i = 0; i < arguments.length; ++i) {
    -      vals[i] = i < 2
    -        ? arguments[i]
    -        : this._cast(arguments[i]);
    -    }
    -    ret = [].splice.apply(this, vals);
    -    this._registerAtomic('$set', this);
    -  }
    -
    -  return ret;
    -}

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#unshift()

    Wraps Array#unshift with proper change tracking.

    show code
    MongooseArray.prototype.unshift = function () {
    -  var values = [].map.call(arguments, this._cast, this);
    -  [].unshift.apply(this, values);
    -  this._registerAtomic('$set', this);
    -  return this.length;
    -};

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#sort()

    Wraps Array#sort with proper change tracking.

    show code
    MongooseArray.prototype.sort = function () {
    -  var ret = [].sort.apply(this, arguments);
    -  this._registerAtomic('$set', this);
    -  return ret;
    -}

    NOTE:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#addToSet([args...])

    Adds values to the array if not already present.

    show code
    MongooseArray.prototype.addToSet = function addToSet () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , added = []
    -    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
    -             values[0] instanceof Date ? 'date' :
    -             '';
    -
    -  values.forEach(function (v) {
    -    var found;
    -    switch (type) {
    -      case 'doc':
    -        found = this.some(function(doc){ return doc.equals(v) });
    -        break;
    -      case 'date':
    -        var val = +v;
    -        found = this.some(function(d){ return +d === val });
    -        break;
    -      default:
    -        found = ~this.indexOf(v);
    -    }
    -
    -    if (!found) {
    -      [].push.call(this, v);
    -      this._registerAtomic('$addToSet', v);
    -      [].push.call(added, v);
    -    }
    -  }, this);
    -
    -  return added;
    -};

    Parameters:

    • [args...] <any>

    Returns:

    • <Array> the values that were added

    Example:

    - -
    console.log(doc.array) // [2,3,4]
    -var added = doc.array.addToSet(4,5);
    -console.log(doc.array) // [2,3,4,5]
    -console.log(added)     // [5]

    MongooseArray#set()

    Sets the casted val at index i and marks the array modified.

    show code
    MongooseArray.prototype.set = function set (i, val) {
    -  this[i] = this._cast(val);
    -  this._markModified(i);
    -  return this;
    -}

    Returns:

    Example:

    - -
    // given documents based on the following
    -var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
    -
    -var doc = new Doc({ array: [2,3,4] })
    -
    -console.log(doc.array) // [2,3,4]
    -
    -doc.array.set(1,"5");
    -console.log(doc.array); // [2,5,4] // properly cast to number
    -doc.save() // the change is saved
    -
    -// VS not using array#set
    -doc.array[1] = "5";
    -console.log(doc.array); // [2,"5",4] // no casting
    -doc.save() // change is not saved

    MongooseArray#toObject(options)

    Returns a native js Array.

    show code
    MongooseArray.prototype.toObject = function (options) {
    -  if (options && options.depopulate && this[0] instanceof Document) {
    -    return this.map(function (doc) {
    -      return doc._id;
    -    });
    -  }
    -
    -  // return this.slice()?
    -  return this.map(function (doc) {
    -    return doc;
    -  });
    -};

    Parameters:

    Returns:


    MongooseArray#inspect()

    Helper for console.log

    show code
    MongooseArray.prototype.inspect = function () {
    -  return '[' + this.map(function (doc) {
    -    return ' ' + doc;
    -  }) + ' ]';
    -};

    MongooseArray#indexOf(obj)

    Return the index of obj or -1 if not found.

    show code
    MongooseArray.prototype.indexOf = function indexOf (obj) {
    -  if (obj instanceof ObjectId) obj = obj.toString();
    -  for (var i = 0, len = this.length; i < len; ++i) {
    -    if (obj == this[i])
    -      return i;
    -  }
    -  return -1;
    -};

    Parameters:

    • obj <Object> the item to look for

    Returns:


    MongooseArray#_parent

    Parent owner document


    MongooseArray#_atomics

    Stores a queue of atomic operations to perform


  • types/buffer.js

    MongooseBuffer(value, encode, offset)

    Mongoose Buffer constructor.

    show code
    function MongooseBuffer (value, encode, offset) {
    -  var length = arguments.length;
    -  var val;
    -
    -  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
    -    val = 0;
    -  } else {
    -    val = value;
    -  }
    -
    -  var encoding;
    -  var path;
    -  var doc;
    -
    -  if (Array.isArray(encode)) {
    -    // internal casting
    -    path = encode[0];
    -    doc = encode[1];
    -  } else {
    -    encoding = encode;
    -  }
    -
    -  var buf = new Buffer(val, encoding, offset);
    -  buf.__proto__ = MongooseBuffer.prototype;
    -
    -  // make sure these internal props don't show up in Object.keys()
    -  Object.defineProperties(buf, {
    -      validators: { value: [] }
    -    , _path: { value: path }
    -    , _parent: { value: doc }
    -  });
    -
    -  if (doc && "string" === typeof path) {
    -    Object.defineProperty(buf, '_schema', {
    -        value: doc.schema.path(path)
    -    });
    -  }
    -
    -  return buf;
    -};

    Parameters:

    Inherits:

    Values always have to be passed to the constructor to initialize.


    MongooseBuffer#_markModified()

    Marks this buffer as modified.

    show code
    MongooseBuffer.prototype._markModified = function () {
    -  var parent = this._parent;
    -
    -  if (parent) {
    -    parent.markModified(this._path);
    -  }
    -  return this;
    -};

    MongooseBuffer#write()

    Writes the buffer.

    show code
    MongooseBuffer.prototype.write = function () {
    -  var written = Buffer.prototype.write.apply(this, arguments);
    -
    -  if (written > 0) {
    -    this._markModified();
    -  }
    -
    -  return written;
    -};

    MongooseBuffer#copy(target)

    Copies the buffer.

    show code
    MongooseBuffer.prototype.copy = function (target) {
    -  var ret = Buffer.prototype.copy.apply(this, arguments);
    -
    -  if (target instanceof MongooseBuffer) {
    -    target._markModified();
    -  }
    -
    -  return ret;
    -};

    Parameters:

    Returns:

    Note:

    - -

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


    MongooseBuffer#toObject([subtype])

    Converts this buffer to its Binary type representation.

    show code
    MongooseBuffer.prototype.toObject = function (subtype) {
    -  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
    -  return new Binary(this, subtype);
    -};

    Parameters:

    • [subtype] <Hex>

    Returns:

    SubTypes:

    - -
      -
    • 0x00: Binary/Generic
    • -
    • 0x01: Function
    • -
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • -
    • 0x03: UUID
    • -
    • 0x04: MD5
    • -
    • 0x80: User Defined
    • -

    MongooseBuffer#_parent

    Parent owner document


  • types/documentarray.js

    MongooseDocumentArray(values, path, doc)

    DocumentArray constructor

    show code
    function MongooseDocumentArray (values, path, doc) {
    -  var arr = [];
    -
    -  // Values always have to be passed to the constructor to initialize, since
    -  // otherwise MongooseArray#push will mark the array as modified to the parent.
    -  arr.push.apply(arr, values);
    -  arr.__proto__ = MongooseDocumentArray.prototype;
    -
    -  arr._atomics = {};
    -  arr.validators = [];
    -  arr._path = path;
    -
    -  if (doc) {
    -    arr._parent = doc;
    -    arr._schema = doc.schema.path(path);
    -    doc.on('save', arr.notify('save'));
    -    doc.on('isNew', arr.notify('isNew'));
    -  }
    -
    -  return arr;
    -};

    Parameters:

    Inherits:


    MongooseDocumentArray#_cast()

    Overrides MongooseArray#cast

    show code
    MongooseDocumentArray.prototype._cast = function (value) {
    -  if (value instanceof this._schema.casterConstructor)
    -    return value;
    -
    -  return new this._schema.casterConstructor(value, this);
    -};

    MongooseDocumentArray#id(id)

    Searches array items for the first document with a matching id.

    show code
    MongooseDocumentArray.prototype.id = function (id) {
    -  var casted
    -    , _id;
    -
    -  try {
    -    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
    -  } catch (e) {
    -    casted = null;
    -  }
    -
    -  for (var i = 0, l = this.length; i < l; i++) {
    -    _id = this[i].get('_id');
    -    if (!(_id instanceof ObjectId)) {
    -      if (String(id) == _id)
    -        return this[i];
    -    } else {
    -      if (casted == _id)
    -        return this[i];
    -    }
    -  }
    -
    -  return null;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var embeddedDoc = m.array.id(some_id);

    MongooseDocumentArray#toObject()

    Returns a native js Array of plain js objects

    show code
    MongooseDocumentArray.prototype.toObject = function () {
    -  return this.map(function (doc) {
    -    return doc && doc.toObject() || null;
    -  });
    -};

    Returns:

    NOTE:

    - -

    Each sub-document is converted to a plain object by calling its #toObject method.


    MongooseDocumentArray#inspect()

    Helper for console.log

    show code
    MongooseDocumentArray.prototype.inspect = function () {
    -  return '[' + this.map(function (doc) {
    -    if (doc) {
    -      return doc.inspect
    -        ? doc.inspect()
    -        : util.inspect(doc)
    -    }
    -    return 'null'
    -  }).join('
    -') + ']';
    -};

    MongooseDocumentArray#create(obj)

    Creates a subdocument casted to this schema.

    show code
    MongooseDocumentArray.prototype.create = function (obj) {
    -  return new this._schema.casterConstructor(obj);
    -}

    Parameters:

    • obj <Object> the value to cast to this arrays SubDocument schema

    This is the same subdocument constructor used for casting.


    MongooseDocumentArray#notify(event)

    Creates a fn that notifies all child docs of event.

    show code
    MongooseDocumentArray.prototype.notify = function notify (event) {
    -  var self = this;
    -  return function notify (val) {
    -    var i = self.length;
    -    while (i--) {
    -      if (!self[i]) continue;
    -      self[i].emit(event, val);
    -    }
    -  }
    -}

    Parameters:

    Returns:


  • types/embedded.js

    EmbeddedDocument(obj, parentArr, skipId)

    EmbeddedDocument constructor.

    show code
    function EmbeddedDocument (obj, parentArr, skipId, fields) {
    -  if (parentArr) {
    -    this.__parentArray = parentArr;
    -    this.__parent = parentArr._parent;
    -  } else {
    -    this.__parentArray = undefined;
    -    this.__parent = undefined;
    -  }
    -
    -  Document.call(this, obj, fields, skipId);
    -
    -  var self = this;
    -  this.on('isNew', function (val) {
    -    self.isNew = val;
    -  });
    -};

    Parameters:

    Inherits:


    EmbeddedDocument#markModified(path)

    Marks the embedded doc modified.

    show code
    EmbeddedDocument.prototype.markModified = function (path) {
    -  if (!this.__parentArray) return;
    -
    -  this._activePaths.modify(path);
    -
    -  if (this.isNew) {
    -    // Mark the WHOLE parent array as modified
    -    // if this is a new document (i.e., we are initializing
    -    // a document),
    -    this.__parentArray._markModified();
    -  } else
    -    this.__parentArray._markModified(this, path);
    -};

    Parameters:

    • path <String> the path which changed

    Example:

    - -
    var doc = blogpost.comments.id(hexstring);
    -doc.mixed.type = 'changed';
    -doc.markModified('mixed.type');

    EmbeddedDocument#save([fn])

    Used as a stub for hooks.js

    show code
    EmbeddedDocument.prototype.save = function(fn) {
    -  if (fn)
    -    fn(null);
    -  return this;
    -};

    Parameters:

    Returns:

    NOTE:

    - -

    This is a no-op. Does not actually save the doc to the db.


    EmbeddedDocument#remove([fn])

    Removes the subdocument from its parent array.

    show code
    EmbeddedDocument.prototype.remove = function (fn) {
    -  if (!this.__parentArray) return this;
    -
    -  var _id;
    -  if (!this.willRemove) {
    -    _id = this._doc._id;
    -    if (!_id) {
    -      throw new Error('For your own good, Mongoose does not know ' + 
    -                      'how to remove an EmbeddedDocument that has no _id');
    -    }
    -    this.__parentArray.pull({ _id: _id });
    -    this.willRemove = true;
    -  }
    -
    -  if (fn)
    -    fn(null);
    -
    -  return this;
    -};

    Parameters:


    EmbeddedDocument#update()

    Override #update method of parent documents.

    show code
    EmbeddedDocument.prototype.update = function () {
    -  throw new Error('The #update method is not available on EmbeddedDocuments');
    -}

    EmbeddedDocument#inspect()

    Helper for console.log

    show code
    EmbeddedDocument.prototype.inspect = function () {
    -  return inspect(this.toObject());
    -};

    EmbeddedDocument#invalidate(path, err)

    Marks a path as invalid, causing validation to fail.

    show code
    EmbeddedDocument.prototype.invalidate = function (path, err, first) {
    -  if (!this.__parent) return false;
    -  var index = this.__parentArray.indexOf(this);
    -  var parentPath = this.__parentArray._path;
    -  var fullPath = [parentPath, index, path].join('.');
    -  this.__parent.invalidate(fullPath, err);
    -  if (first)
    -    this._validationError = ownerDocument(this)._validationError;
    -  return true;
    -}

    Parameters:

    • path <String> the field to invalidate
    • err <String, Error> error which states the reason `path` was invalid

    Returns:


    EmbeddedDocument#ownerDocument()

    Returns the top level document of this sub-document.

    show code
    EmbeddedDocument.prototype.ownerDocument = function () {
    -  return ownerDocument(this);
    -}

    Returns:


    EmbeddedDocument#parent()

    Returns this sub-documents parent document.

    show code
    EmbeddedDocument.prototype.parent = function () {
    -  return this.__parent;
    -}

    EmbeddedDocument#parentArray()

    Returns this sub-documents parent array.

    show code
    EmbeddedDocument.prototype.parentArray = function () {
    -  return this.__parentArray;
    -}

  • types/objectid.js

    ObjectId()

    ObjectId type constructor

    Example

    - -
    var id = new mongoose.Types.ObjectId;

    ObjectId.fromString(str)

    Creates an ObjectId from str

    show code
    ObjectId.fromString;

    Parameters:

    Returns:


    ObjectId.toString(oid)

    Converts oid to a string.

    show code
    ObjectId.toString;

    Parameters:

    Returns:


  • utils.js

    exports.toCollectionName(name)

    Produces a collection name from model name.

    show code
    exports.toCollectionName = function (name) {
    -  if ('system.profile' === name) return name;
    -  if ('system.indexes' === name) return name;
    -  return pluralize(name.toLowerCase());
    -};

    Parameters:

    Returns:


    exports.pluralization

    Pluralization rules.

    show code
    exports.pluralization = [
    -  [/(m)an$/gi, '$1en'],
    -  [/(pe)rson$/gi, '$1ople'],
    -  [/(child)$/gi, '$1ren'],
    -  [/^(ox)$/gi, '$1en'],
    -  [/(ax|test)is$/gi, '$1es'],
    -  [/(octop|vir)us$/gi, '$1i'],
    -  [/(alias|status)$/gi, '$1es'],
    -  [/(bu)s$/gi, '$1ses'],
    -  [/(buffal|tomat|potat)o$/gi, '$1oes'],
    -  [/([ti])um$/gi, '$1a'],
    -  [/sis$/gi, 'ses'],
    -  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
    -  [/(hive)$/gi, '$1s'],
    -  [/([^aeiouy]|qu)y$/gi, '$1ies'],
    -  [/(x|ch|ss|sh)$/gi, '$1es'],
    -  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
    -  [/([m|l])ouse$/gi, '$1ice'],
    -  [/(quiz)$/gi, '$1zes'],
    -  [/s$/gi, 's'],
    -  [/$/gi, 's']
    -];
    -var rules = exports.pluralization;

    These rules are applied while processing the argument to toCollectionName.


    exports.uncountables

    Uncountable words.

    show code
    exports.uncountables = [
    -  'advice',
    -  'energy',
    -  'excretion',
    -  'digestion',
    -  'cooperation',
    -  'health',
    -  'justice',
    -  'labour',
    -  'machinery',
    -  'equipment',
    -  'information',
    -  'pollution',
    -  'sewage',
    -  'paper',
    -  'money',
    -  'species',
    -  'series',
    -  'rain',
    -  'rice',
    -  'fish',
    -  'sheep',
    -  'moose',
    -  'deer',
    -  'news'
    -];
    -var uncountables = exports.uncountables;

    These words are applied while processing the argument to toCollectionName.


    exports.deepEqual(a, b)

    Determines if a and b are deep equal.

    show code
    exports.deepEqual = function deepEqual (a, b) {
    -  if (a === b) return true;
    -
    -  if (a instanceof Date && b instanceof Date)
    -    return a.getTime() === b.getTime();
    -
    -  if (a instanceof ObjectId && b instanceof ObjectId) {
    -    return a.toString() === b.toString();
    -  }
    -
    -  if (typeof a !== 'object' && typeof b !== 'object')
    -    return a == b;
    -
    -  if (a === null || b === null || a === undefined || b === undefined)
    -    return false
    -
    -  if (a.prototype !== b.prototype) return false;
    -
    -  // Handle MongooseNumbers
    -  if (a instanceof Number && b instanceof Number) {
    -    return a.valueOf() === b.valueOf();
    -  }
    -
    -  if (Buffer.isBuffer(a)) {
    -    if (!Buffer.isBuffer(b)) return false;
    -    if (a.length !== b.length) return false;
    -    for (var i = 0, len = a.length; i < len; ++i) {
    -      if (a[i] !== b[i]) return false;
    -    }
    -    return true;
    -  }
    -
    -  if (isMongooseObject(a)) a = a.toObject();
    -  if (isMongooseObject(b)) b = b.toObject();
    -
    -  try {
    -    var ka = Object.keys(a),
    -        kb = Object.keys(b),
    -        key, i;
    -  } catch (e) {//happens when one is a string literal and the other isn't
    -    return false;
    -  }
    -
    -  // having the same number of owned properties (keys incorporates
    -  // hasOwnProperty)
    -  if (ka.length != kb.length)
    -    return false;
    -
    -  //the same set of keys (although not necessarily the same order),
    -  ka.sort();
    -  kb.sort();
    -
    -  //~~~cheap key test
    -  for (i = ka.length - 1; i >= 0; i--) {
    -    if (ka[i] != kb[i])
    -      return false;
    -  }
    -
    -  //equivalent values for every corresponding key, and
    -  //~~~possibly expensive deep test
    -  for (i = ka.length - 1; i >= 0; i--) {
    -    key = ka[i];
    -    if (!deepEqual(a[key], b[key])) return false;
    -  }
    -
    -  return true;
    -};

    Parameters:

    • a <any> a value to compare to `b`
    • b <any> a value to compare to `a`

    Returns:

    Modified from node/lib/assert.js


    exports.clone(obj, options)

    Object clone with Mongoose natives support.

    show code
    exports.clone = function clone (obj, options) {
    -  if (obj === undefined || obj === null)
    -    return obj;
    -
    -  if (Array.isArray(obj))
    -    return cloneArray(obj, options);
    -
    -  if (isMongooseObject(obj)) {
    -    if (options && options.json && 'function' === typeof obj.toJSON) {
    -      return obj.toJSON(options);
    -    } else {
    -      return obj.toObject(options);
    -    }
    -  }
    -
    -  if ('Object' === obj.constructor.name)
    -    return cloneObject(obj, options);
    -
    -  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
    -    return new obj.constructor(+obj);
    -
    -  if ('RegExp' === obj.constructor.name)
    -    return new RegExp(obj.source);
    -
    -  if (obj instanceof ObjectId) {
    -    return new ObjectId(obj.id);
    -  }
    -
    -  if (obj.valueOf)
    -    return obj.valueOf();
    -};
    -var clone = exports.clone;

    Parameters:

    Returns:

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.


    exports.options(defaults, options)

    Copies and merges options with defaults.

    show code
    exports.options = function (defaults, options) {
    -  var keys = Object.keys(defaults)
    -    , i = keys.length
    -    , k ;
    -
    -  options = options || {};
    -
    -  while (i--) {
    -    k = keys[i];
    -    if (!(k in options)) {
    -      options[k] = defaults[k];
    -    }
    -  }
    -
    -  return options;
    -};

    Parameters:

    Returns:


    exports.random()

    Generates a random string

    show code
    exports.random = function () {
    -  return Math.random().toString().substr(3);
    -};

    exports.merge(to, from)

    Merges from into to without overwriting existing properties.

    show code
    exports.merge = function merge (to, from) {
    -  var keys = Object.keys(from)
    -    , i = keys.length
    -    , key
    -
    -  while (i--) {
    -    key = keys[i];
    -    if ('undefined' === typeof to[key]) {
    -      to[key] = from[key];
    -    } else {
    -      merge(to[key], from[key]);
    -    }
    -  }
    -};

    Parameters:


    exports.args

    A faster Array.prototype.slice.call(arguments) alternative

    show code
    exports.args = sliced;

    exports.tick(callback)

    process.nextTick helper.

    show code
    exports.tick = function tick (callback) {
    -  if ('function' !== typeof callback) return;
    -  return function () {
    -    try {
    -      callback.apply(this, arguments);
    -    } catch (err) {
    -      // only nextTick on err to get out of
    -      // the event loop and avoid state corruption.
    -      process.nextTick(function () {
    -        throw err;
    -      });
    -    }
    -  }
    -}

    Parameters:

    Wraps callback in a try/catch + nextTick.

    - -

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


    exports.isMongooseObject(v)

    Returns if v is a mongoose object that has a toObject() method we can use.

    show code
    exports.isMongooseObject = function (v) {
    -  Document || (Document = require('./document'));
    -  MongooseArray || (MongooseArray = require('./types').Array);
    -  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
    -
    -  return v instanceof Document ||
    -         v instanceof MongooseArray ||
    -         v instanceof MongooseBuffer
    -}
    -var isMongooseObject = exports.isMongooseObject;

    Parameters:

    This is for compatibility with libs like Date.js which do foolish things to Natives.


    exports.expires(object)

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    show code
    exports.expires = function expires (object) {
    -  if (!(object && 'Object' == object.constructor.name)) return;
    -  if (!('expires' in object)) return;
    -
    -  var when;
    -  if ('string' != typeof object.expires) {
    -    when = object.expires;
    -  } else {
    -    when = Math.round(ms(object.expires) / 1000);
    -  }
    -  object.expireAfterSeconds = when;
    -  delete object.expires;
    -}
    -
    -exports.readPref = function readPref (pref, tags) {
    -  if (Array.isArray(pref)) {
    -    tags = pref[1];
    -    pref = pref[0];
    -  }
    -
    -  switch (pref) {
    -    case 'p':
    -      pref = 'primary';
    -      break;
    -    case 'pp':
    -      pref = 'primaryPrefered';
    -      break;
    -    case 's':
    -      pref = 'secondary';
    -      break;
    -    case 'sp':
    -      pref = 'secondaryPrefered';
    -      break;
    -    case 'n':
    -      pref = 'nearest';
    -      break;
    -  }
    -
    -  return new ReadPref(pref, tags);
    -}

    Parameters:


  • virtualtype.js

    VirtualType()

    VirtualType constructor

    show code
    function VirtualType (options, name) {
    -  this.path = name;
    -  this.getters = [];
    -  this.setters = [];
    -  this.options = options || {};
    -}

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    - -

    Example:

    - -
    var fullname = schema.virtual('fullname');
    -fullname instanceof mongoose.VirtualType // true

    VirtualType#get(fn)

    Defines a getter.

    show code
    VirtualType.prototype.get = function (fn) {
    -  this.getters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var virtual = schema.virtual('fullname');
    -virtual.get(function () {
    -  return this.name.first + ' ' + this.name.last;
    -});

    VirtualType#set(fn)

    Defines a setter.

    show code
    VirtualType.prototype.set = function (fn) {
    -  this.setters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var virtual = schema.virtual('fullname');
    -virtual.set(function (v) {
    -  var parts = v.split(' ');
    -  this.name.first = parts[0];
    -  this.name.last = parts[1];
    -});

    VirtualType#applyGetters(value, scope)

    Applies getters to value using optional scope.

    show code
    VirtualType.prototype.applyGetters = function (value, scope) {
    -  var v = value;
    -  for (var l = this.getters.length - 1; l >= 0; l--) {
    -    v = this.getters[l].call(scope, v, this);
    -  }
    -  return v;
    -};

    Parameters:

    Returns:

    • <any> the value after applying all getters

    VirtualType#applySetters(value, scope)

    Applies setters to value using optional scope.

    show code
    VirtualType.prototype.applySetters = function (value, scope) {
    -  var v = value;
    -  for (var l = this.setters.length - 1; l >= 0; l--) {
    -    v = this.setters[l].call(scope, v, this);
    -  }
    -  return v;
    -};

    Parameters:

    Returns:

    • <any> the value after applying all setters

diff --git a/docs/3.2.x/docs/api.jade b/docs/3.2.x/docs/api.jade deleted file mode 100644 index ba62159ba13..00000000000 --- a/docs/3.2.x/docs/api.jade +++ /dev/null @@ -1,507 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose API v#{package.version} - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - style. - body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; - } - a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; - } - a:hover { - opacity: 0.8; - } - #wrap { - } - h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; - } - pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; - } - code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Monaco; - } - pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; - } - h3 { - padding: 20px 15px; - margin-left: -15px; - } - h3 code { - font-weight: normal; - } - hr { - height: 1px; - border: 0 none; - padding: 0; - margin: 60px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) - } - .doclinks hr { - margin: 10px 0; - } - li { - list-style: square; - } - #header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; - } - #header h1 { - margin-top: 0; - margin-bottom: 0; - } - #header h1 a { - text-decoration: none; - } - #header .mongoose { - font-size: 48px; - font-weight: 100; - color: #fff; - letter-spacing: -5px; - } - #links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - } - #links hr { - margin: 32px 0; - } - #content { - padding: 0; - margin: 0 0 30px 230px; - overflow-x: hidden; - } - #content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; - } - #content .controls:hover { - opacity: .9; - } - #content p { - word-wrap: break-word; - } - #content > ul { - margin: 0; - padding: 0; - } - .private { - display: none; - } - .section { - font-size: 15px; - } - .doclinks li.private a:before, - .doclinks .module.private a:before, - .doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; - } - #content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; - } - .module { - list-style: none; - padding: 30px 0 30px 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; - } - .module > * { - max-width: 700px; - } - .item:last-child { - margin-bottom: 90px; - } - .item:last-child > hr { - display: none; - } - .item h3 a { - color: #333; - text-decoration: none; - } - .property h3 span { - color: #444; - } - .description { - margin-top: 25px; - } - .sourcecode { - display: none; - } - .showcode { - font-size: 12px; - cursor: pointer; - display: none; - } - .load .showcode { - display: block; - } - .types a { - text-decoration: none; - } - @media only screen and (device-width: 768px) { - - } - @media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links hr { - display: none; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - .controls { display: none; } - } - body.api - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - hr - .doclinks - each item in docs - .file(class=item.hasPublic ? '' : 'private') - a.section(href='#' + item.title.replace(/[\.\/#]/g, '-'))= item.title - ul - each method in item.methods - if method.ctx && !method.ignore - li(class= method.isPrivate ? 'private' : '') - case method.ctx.type - when 'method' - id = method.ctx.constructor + '-' + method.ctx.name - when 'function' - id = method.ctx.name - default - id = '' - url = href(klass(item.title) + '_' + id) - a(href='#' + url)= method.ctx.name - each stat in item.statics - if stat.ctx && !stat.ignore - li(class= stat.isPrivate ? 'private' : '') - case stat.ctx.type - when 'method' - id = stat.ctx.receiver + '-' + stat.ctx.name - when 'property' - id = stat.ctx.receiver + '-' + stat.ctx.name - when 'function' - id = stat.ctx.name - url = href(klass(item.title) + '_' + id) - a(href='#' + url)= stat.ctx.name - each property in item.props - if property.ctx && !property.ignore - li(class= property.isPrivate ? 'private' : '') - construct = property.ctx.receiver || property.ctx.constructor - link = href(construct) + '-' + href(property.ctx.name) - url = href(klass(item.title) + '_' + link) - a(href='#' + url)= property.ctx.name - #content - .controls - label - input(type='checkbox') - | private - ul - each item in docs - li.module(class=item.hasPublic ? '' : 'private') - a(href=github + package.version + '/' + item.title, id=item.title.replace(/[\.\/#]/g, '-'))= item.title - each method in item.methods - div.item.method(class= method.isPrivate ? 'private' : 'public') - if method.ctx - case method.ctx.type - when 'method' - id = method.ctx.constructor + '-' + method.ctx.name - text = method.ctx.constructor + '#' + method.ctx.name - when 'function' - id = method.ctx.name - text = method.ctx.name - default - text = '' - url = href(klass(item.title) + '_' + text) - h3(id= url) - a(href= '#' + url) - = text - | ( - each tag, i in method.params - code= tag.name - if i+1 < method.params.length - | , - | ) - else - - // console.log('\nmissing method name', method); - h3 MISSING method name - != method.description.summary - if method.code - span.showcode show code - .sourcecode - != hl(method.code) - if method.params.length - .params - h4 Parameters: - ul - each tag in method.params - li - code= tag.name - if tag.types && tag.types.length - span.types - | < - each type, i in tag.types - != linktype(type) - if i+1 < tag.types.length - | , - | > - span= tag.description - if method.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in method.return.types - != linktype(type) - if i+1 < method.return.types.length - | , - | > - span= method.return.description - if method.inherits - .inherits - h4 Inherits: - ul - li - != method.inherits - if method.events && method.events.length - .events - h4 Events: - ul - each event in method.events - li - != event.string - if method.see.length - .see - h4 See: - ul.see - each see in method.see - li - url = see.url || see.local - a(href=url, title=see.title || see.local)= see.title || see.url || see.local - div.description - != method.description.body - hr(class= method.isPrivate ? 'private' : '') - each stat in item.statics - div.item.static(class= stat.isPrivate ? 'private' : 'public') - if stat.ctx - case stat.ctx.type - when 'method' - id = stat.ctx.receiver + '-' + stat.ctx.name - text = stat.ctx.receiver + '.' + stat.ctx.name - when 'property' - id = stat.ctx.receiver + '-' + stat.ctx.name - text = stat.ctx.receiver + '.' + stat.ctx.name - when 'function' - id = stat.ctx.name - text = stat.ctx.name - default - text = '' - url = href(klass(item.title) + '_' + id) - h3(id= url) - a(href= '#' + url) - = text - if 'property' != stat.ctx.type - | ( - each tag, i in stat.params - code= tag.name - if i+1 < stat.params.length - | , - | ) - else - - // console.log('\nmissing static name', stat); - h3 MISSING stat name - != stat.description.summary - if stat.code - span.showcode show code - .sourcecode - != hl(stat.code) - if stat.params.length - .params - h4 Parameters: - ul - each tag in stat.params - li - - if (!tag.name) - - // console.log(tag) - code= tag.name - if tag.types && tag.types.length - span.types - | < - each type, i in tag.types - != linktype(type) - if i+1 < tag.types.length - | , - | > - span= tag.description - if stat.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in stat.return.types - != linktype(type) - if i+1 < stat.return.types.length - | , - | > - span= stat.return.description - if stat.inherits - .inherits - h4 Inherits: - ul - li - != stat.inherits - if stat.see.length - .see - h4 See: - ul.see - each see in stat.see - li - url = see.url || see.local - a(href=url, title=see.title || see.local)= see.title || see.url || see.local - != stat.description.body - hr(class= stat.isPrivate ? 'private' : '') - each property in item.props - div.item.property(class= property.ignore || property.isPrivate ? 'private' : 'public') - construct = property.ctx.receiver || property.ctx.constructor - link = href(construct) + '-' + href(property.ctx.name) - url = href(klass(item.title) + '_' + link) - h3(id = url) - a(href= '#' + url) - = construct + '#' - span= property.ctx.name - != property.description.full - if property.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in property.return.types - != linktype(type) - if i+1 < property.return.types.length - | , - | > - span= property.return.description - hr(class= property.isPrivate ? 'private' : '') - script. - document.body.className = 'load'; - include includes/googleanalytics - script(src="/docs/js/zepto.min.js") - script. - $(".module").on("click", ".showcode", function (e) { - $(this).closest(".item").find(".sourcecode").first().toggle(); - }); - $("#content .controls input").on("click", function (e) { - $(".private").toggle() - }) diff --git a/docs/3.2.x/docs/connections.html b/docs/3.2.x/docs/connections.html deleted file mode 100644 index 6d47687b51e..00000000000 --- a/docs/3.2.x/docs/connections.html +++ /dev/null @@ -1,27 +0,0 @@ -Mongoose Connecting to MongoDB v3.2.2Fork me on GitHub

Connections

We may connect to MongoDB by utilizing the mongoose.connect() method.

mongoose.connect('mongodb://localhost/myapp');
-

This is the minimum needed to connect the myapp database running locally on the default port (27017). We may also specify several more parameters in the uri depending on your environment:

mongoose.connect('mongodb://username:password@host:port/database');
-

Options

The connect method also accepts an options object which will be passed on to the underlying driver.

mongoose.connect(uri, options);
-

The following option keys are available:

- -
 db      - passed to the connection db instance
- server  - passed to the connection server instance(s)
- replset - passed to the connection ReplSet instance
- user    - username for authentication (if not specified in uri)
- pass    - password for authentication (if not specified in uri)
- -

See the driver for more information about available options.

- -

Note: The server option auto_reconnect is defaulted to true.

- -

Note: The db option forceServerObjectId is set to false and cannot be overridden.

ReplicaSet Connections

The same method is used to connect to a replica set but instead of passing a single uri we pass a comma delimited list of uris.

mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]);
-

NOTE: The database need only be specified in one of the uris.

Multiple connections

So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize mongoose.createConnection() which accepts all the arguments already discussed and returns a fresh connection for you.

var conn = mongoose.createConnection('uri,uri,uri...', options);
-

Connection pools

Each connection, whether created with mongoose.connect or mongoose.createConnection are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options:

mongoose.createConnection(uri, { server: { poolSize: 10 }});
-

Next Up

Now that we've covered connections, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

diff --git a/docs/3.2.x/docs/connections.jade b/docs/3.2.x/docs/connections.jade deleted file mode 100644 index 5e67abc8a4b..00000000000 --- a/docs/3.2.x/docs/connections.jade +++ /dev/null @@ -1,65 +0,0 @@ -extends layout - -block content - h2 Connections - :markdown - We may connect to MongoDB by utilizing the `mongoose.connect()` method. - - :js - mongoose.connect('mongodb://localhost/myapp'); - - :markdown - This is the minimum needed to connect the `myapp` database running locally on the default port (27017). We may also specify several more parameters in the `uri` depending on your environment: - - :js - mongoose.connect('mongodb://username:password@host:port/database'); - - h3 Options - :markdown - The `connect` method also accepts an `options` object which will be passed on to the underlying driver. - - :js - mongoose.connect(uri, options); - - :markdown - The following option keys are available: - - db - passed to the connection db instance - server - passed to the connection server instance(s) - replset - passed to the connection ReplSet instance - user - username for authentication (if not specified in uri) - pass - password for authentication (if not specified in uri) - - See the [driver](https://github.com/mongodb/node-mongodb-native) for more information about available options. - - _Note: The server option `auto_reconnect` is defaulted to true._ - - _Note: The db option `forceServerObjectId` is set to false and cannot be overridden._ - - h3 ReplicaSet Connections - :markdown - The same method is used to connect to a replica set but instead of passing a single `uri` we pass a comma delimited list of `uri`s. - - :js - mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]); - - :markdown - _NOTE: The `database` need only be specified in one of the `uri`s._ - - h3 Multiple connections - :markdown - So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize `mongoose.createConnection()` which accepts all the arguments already discussed and returns a fresh connection for you. - - :js - var conn = mongoose.createConnection('uri,uri,uri...', options); - - h3 Connection pools - :markdown - Each `connection`, whether created with `mongoose.connect` or `mongoose.createConnection` are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options: - - :js - mongoose.createConnection(uri, { server: { poolSize: 10 }}); - - h3#next Next Up - :markdown - Now that we've covered `connections`, let's take a look at how we can break pieces of our functionality out into reusable and shareable [plugins](/docs/plugins.html). diff --git a/docs/3.2.x/docs/contributing.html b/docs/3.2.x/docs/contributing.html deleted file mode 100644 index 70f372138b1..00000000000 --- a/docs/3.2.x/docs/contributing.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose Contributing v3.2.2Fork me on GitHub

Contributing

Please read all about contributing here.

diff --git a/docs/3.2.x/docs/contributing.jade b/docs/3.2.x/docs/contributing.jade deleted file mode 100644 index 48d9a658aaf..00000000000 --- a/docs/3.2.x/docs/contributing.jade +++ /dev/null @@ -1,8 +0,0 @@ -extends layout - -block content - h2 Contributing - - :markdown - Please read all about contributing [here](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md). - diff --git a/docs/3.2.x/docs/css/default.css b/docs/3.2.x/docs/css/default.css deleted file mode 100644 index ccb22728ed3..00000000000 --- a/docs/3.2.x/docs/css/default.css +++ /dev/null @@ -1,135 +0,0 @@ -/* - -Original style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ - -pre code { - display: block; padding: 0.5em; - background: #F0F0F0; -} - -pre code, -pre .ruby .subst, -pre .tag .title, -pre .lisp .title, -pre .clojure .built_in, -pre .nginx .title { - color: black; -} - -pre .string, -pre .title, -pre .constant, -pre .parent, -pre .tag .value, -pre .rules .value, -pre .rules .value .number, -pre .preprocessor, -pre .ruby .symbol, -pre .ruby .symbol .string, -pre .ruby .symbol .keyword, -pre .ruby .symbol .keymethods, -pre .instancevar, -pre .aggregate, -pre .template_tag, -pre .django .variable, -pre .smalltalk .class, -pre .addition, -pre .flow, -pre .stream, -pre .bash .variable, -pre .apache .tag, -pre .apache .cbracket, -pre .tex .command, -pre .tex .special, -pre .erlang_repl .function_or_atom, -pre .markdown .header { - color: #800; -} - -pre .comment, -pre .annotation, -pre .template_comment, -pre .diff .header, -pre .chunk, -pre .markdown .blockquote { - color: #888; -} - -pre .number, -pre .date, -pre .regexp, -pre .literal, -pre .smalltalk .symbol, -pre .smalltalk .char, -pre .go .constant, -pre .change, -pre .markdown .bullet, -pre .markdown .link_url { - color: #080; -} - -pre .label, -pre .javadoc, -pre .ruby .string, -pre .decorator, -pre .filter .argument, -pre .localvars, -pre .array, -pre .attr_selector, -pre .important, -pre .pseudo, -pre .pi, -pre .doctype, -pre .deletion, -pre .envvar, -pre .shebang, -pre .apache .sqbracket, -pre .nginx .built_in, -pre .tex .formula, -pre .erlang_repl .reserved, -pre .input_number, -pre .markdown .link_label, -pre .vhdl .attribute, -pre .clojure .attribute { - color: #88F -} - -pre .keyword, -pre .id, -pre .phpdoc, -pre .title, -pre .built_in, -pre .aggregate, -pre .css .tag, -pre .javadoctag, -pre .phpdoc, -pre .yardoctag, -pre .smalltalk .class, -pre .winutils, -pre .bash .variable, -pre .apache .tag, -pre .go .typename, -pre .tex .command, -pre .markdown .strong, -pre .request, -pre .status { - font-weight: bold; -} - -pre .markdown .emphasis { - font-style: italic; -} - -pre .nginx .built_in { - font-weight: normal; -} - -pre .coffeescript .javascript, -pre .xml .css, -pre .xml .javascript, -pre .xml .vbscript, -pre .tex .formula { - opacity: 0.5; -} diff --git a/docs/3.2.x/docs/css/guide.css b/docs/3.2.x/docs/css/guide.css deleted file mode 100644 index 69fe3f84a8e..00000000000 --- a/docs/3.2.x/docs/css/guide.css +++ /dev/null @@ -1,281 +0,0 @@ -html, body, #content { - height: 100%; -} -.module { - min-height: 100%; - box-sizing: border-box; -} -body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; -} -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; -} -code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Monaco; - /*text-shadow: 1px 2px 2px #555;*/ -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -h2 { - margin-top: 0; -} -h3 { padding-top: 35px; } -h3 code { - font-weight: normal; -} -hr { - display: none; - height: 1px; - border: 0 none; - padding: 0; - margin: 90px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) -} -.doclinks hr { - margin: 10px 0; -} -li { - list-style: square; -} -#header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -#header .mongoose { - font-size: 48px; - font-weight: 100; - color: #fff; - letter-spacing: -5px; -} -#links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; -} -#links .schematypes span { - display: none; -} -#content { - padding: 0; - margin: 0 0 0 230px; -} -#content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -#content .controls:hover { - opacity: .9; -} -#content p { - word-wrap: break-word; -} -#content > ul { - margin: 0; - padding: 0; -} -.private { - display: none; -} -.doclinks li.private a:before, -.doclinks .module.private a:before, -.doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; -} -#content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; -} -.module { - list-style: none; - padding: 30px 0 0 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; -} -.module > * { - max-width: 700px; -} -.item { - margin-bottom: 175px; -} -.item h3 a { - color: #333; - text-decoration: none; -} -.property h3 span { - color: #444; -} -.description { - margin-top: 25px; -} -.sourcecode { - display: none; -} -.showcode { - font-size: 12px; - cursor: pointer; - display: none; -} -.load .showcode { - display: block; -} -.types a { - text-decoration: none; -} -li.guide ul { - padding-left: 16px; -} - -@media only screen and (device-width: 768px) { - -} -@media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - html, body, #content { - height: auto; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - #links li.guide { - display: block; - width: 390px; - margin-bottom: 15px; - } - #links li.guide > a { - display: none; - } - #links li ul li { - width: 44%; - text-align: left; - } - #links li ul li ul li { - width: 95%; - } - #links .plugins, - #links .changelog { - display: none; - } - #links .schematypes span { - display: inline; - } - #links .double { - width: 332px; - } - #links .double > ul { - display: inline; - float: right; - } - #links .double > ul li { - width: 155px; - } -} diff --git a/docs/3.2.x/docs/css/style.css b/docs/3.2.x/docs/css/style.css deleted file mode 100644 index 7f7362cf306..00000000000 --- a/docs/3.2.x/docs/css/style.css +++ /dev/null @@ -1,207 +0,0 @@ -body { - font-family: 'Open Sans', Helvetica, Arial, FreeSans; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; -} -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { - width: 600px; - margin: 0 auto; - position:relative; -} -li { - list-style: square; -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: #eee; - padding: 5px; - border-radius: 3px; -} -code { - color: #333; - font-size: 11px; - font-family: Monaco; -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -#header { - text-align: center; - padding-top: 40px; -} -#header, h2, h3, .tagline, .blurb { - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -h2 { - margin: 30px 0; -} -h2 a { - font-size: 11px; - position: relative; - bottom: 4px; -} -#header .mongoose { - font-size: 146px; - font-weight: 100; - text-indent: -23px; -} -.load #header .mongoose { - letter-spacing: -14px; -} -.tagline { - color: #333; - font-size: 25px; - text-shadow: 1px 1px #f8f8f8; - text-align: center; -} -.blurb { - text-align: center; - font-style: oblique; - font-size: 12px; - margin-bottom: 20px; -} -.tagline a, .blurb a { - text-decoration: none; - color: #800; -} -#links { - margin: 30px 10px 46px; - text-align: center; - position: relative; -} -#links ul { - margin: 0; - padding: 0; -} -#links li { - display: inline-block; - margin: 0 15px; - background-color: #FEFEFE; -} -#links a { - background: #444; - padding: 9px 0px; - border-radius: 3px; - color: white; - width: 180px; - display: inline-block; - text-decoration: none; - text-transform: lowercase; - text-shadow: 1px 1px 7px #222; -} -#production ul { - padding: 0; -} -#production li { - list-style: none; - overflow: hidden; - display: inline-block; - height: 133px; -} -#production img { - width: 180px; - margin: 10px; -} -#production a { - -webkit-transition-property: opacity; - -moz-transition-property: opacity; - -o-transition-property: opacity; - transition-property: opacity; - -webkit-transition-duration: 0.25s; - -moz-transition-duration: 0.25s; - -o-transition-duration: 0.25s; - transition-duration: 0.25s; - opacity: 0.7; -} -#production a:hover { - opacity: 1.0; -} -#footer { - text-align: center; - font-size: 12px; - margin-bottom: 20px; -} -@media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header { - padding-top: 12px; - } - #header .mongoose { - text-align: center; - font-size: 65px; - font-weight: 100; - letter-spacing: -7px; - } - .load #header .mongoose { - letter-spacing: -7px; - } - .tagline { - text-align: center; - font-size: 14px; - } - .tagline a { - text-decoration: none; - } - .blurb { - font-size: 16px; - text-align: justify; - margin-top: 25px; - } - #links { - margin-bottom: 40px; - } - #links li { - padding: 8px 2px; - margin: 0 12px; - } - #links a { - background: #444; - padding: 7px 34px; - font-size: 15px; - } - #docs { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - #wrap { - width: auto; - padding: 0 5px; - } - #production li { - margin-bottom: 8px; - } - #production a { - opacity: 1; - } - #production img { - width: 100%; - } - .addyourown, .addyourown a { - width: 100%; - } -} diff --git a/docs/3.2.x/docs/documents.html b/docs/3.2.x/docs/documents.html deleted file mode 100644 index 92a9a1fccaa..00000000000 --- a/docs/3.2.x/docs/documents.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose Documents v3.2.2Fork me on GitHub

Documents

Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

Retrieving

There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

Updating

There are a number of ways to update documents. We'll first look at a traditional approach using findById:

Tank.findById(id, function (err, tank) {
-  if (err) return handleError(err);
-  
-  tank.size = 'large';
-  tank.save(function (err) {
-    if (err) return handleError(err);
-    res.send(tank);
-  });
-});

This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

If we do need the document returned in our application there is another, often better, option:

Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
-  if (err) return handleError(err);
-  res.send(tank);
-});

The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

Validating

Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

Next Up

Now that we've covered Documents, let's take a look at Sub-documents.

diff --git a/docs/3.2.x/docs/documents.jade b/docs/3.2.x/docs/documents.jade deleted file mode 100644 index 67134e821b3..00000000000 --- a/docs/3.2.x/docs/documents.jade +++ /dev/null @@ -1,42 +0,0 @@ -extends layout - -block content - h2 Documents - :markdown - Mongoose [documents](./api.html#document-js) represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its [Model](./models.html). - h3 Retrieving - :markdown - There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on [querying](./queries.html) for detail. - h3 Updating - :markdown - There are a number of ways to update documents. We'll first look at a traditional approach using [findById](./api.html#model_Model-findById): - :js - Tank.findById(id, function (err, tank) { - if (err) return handleError(err); - - tank.size = 'large'; - tank.save(function (err) { - if (err) return handleError(err); - res.send(tank); - }); - }); - :markdown - This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model-update) is right for us: - :js - Tank.update({ _id: id }, { $set: { size: 'large' }}, callback); - :markdown - If we do need the document returned in our application there is another, often [better](./api.html#model_Model-findByIdAndUpdate), option: - :js - Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) { - if (err) return handleError(err); - res.send(tank); - }); - :markdown - The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model-findByIdAndRemove) [several](./api.html#model_Model-findOneAndUpdate) [variations](./api.html#model_Model-findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. - h3 Validating - :markdown - Documents are validated before they are saved. Read the [api](./api.html#document_Document-validate) docs or the [validation](./validation.html) chapter for detail. - - h3#next Next Up - :markdown - Now that we've covered `Documents`, let's take a look at [Sub-documents](/docs/subdocs.html). diff --git a/docs/3.2.x/docs/faq.html b/docs/3.2.x/docs/faq.html deleted file mode 100644 index c4a4511086b..00000000000 --- a/docs/3.2.x/docs/faq.html +++ /dev/null @@ -1,31 +0,0 @@ -Mongoose FAQ v3.2.2Fork me on GitHub

FAQ

Q. Why don't my changes to arrays get saved when I update an element directly?

doc.array[3] = 'changed';
-doc.save();

A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

doc.markModified('array');
-doc.save();

Q. Why doesn't mongoose allow me to directly assign schemas to paths?

var userSchema = new Schema({ name: String });
-new Schema({ user: userSchema })

A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

doc.user.save();  // ?
-doc.user.remove();// ?
-doc.save()

We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


Q. How can I enable debugging?

- -

A. Set the debug option to true:

mongoose.set('debug', true)

Q. My save() callback never executes. What am I doing wrong?

- -

A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

// if connecting on the default mongoose connection
-mongoose.connect(..);
-mongoose.connection.on('error', handleError);
-
-// if connecting on a separate connection
-var conn = mongoose.createConnection(..);
-conn.on('error', handleError);
-

Something to add?

- -

If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


diff --git a/docs/3.2.x/docs/faq.jade b/docs/3.2.x/docs/faq.jade deleted file mode 100644 index 07abc7ea928..00000000000 --- a/docs/3.2.x/docs/faq.jade +++ /dev/null @@ -1,63 +0,0 @@ -extends layout - -block append style - style. - hr { - display: block; - margin: 30px 0; - } - -block content - h2 FAQ - :markdown - **Q**. Why don't my changes to arrays get saved when I update an element directly? - :js - doc.array[3] = 'changed'; - doc.save(); - :markdown - **A**. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving. - :js - doc.markModified('array'); - doc.save(); - hr - :markdown - **Q**. Why doesn't mongoose allow me to directly assign schemas to paths? - :js - var userSchema = new Schema({ name: String }); - new Schema({ user: userSchema }) - :markdown - **A**. Schemas have a one-to-one mapping with documents. Documents have `save` and `remove` methods along with their own `pre` and `post` hooks which would lead to code like the following: - :js - doc.user.save(); // ? - doc.user.remove();// ? - doc.save() - :markdown - We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling `save` on a sub-document is a no-op and exists only to support `pre` save hooks). In the future this is likely to be revisited. - hr - :markdown - **Q**. How can I enable debugging? - - **A**. Set the `debug` option to `true`: - :js - mongoose.set('debug', true) - hr - :markdown - **Q**. My `save()` callback never executes. What am I doing wrong? - - **A**. All `collection` actions (insert, remove, queries, etc) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. - :js - // if connecting on the default mongoose connection - mongoose.connect(..); - mongoose.connection.on('error', handleError); - - // if connecting on a separate connection - var conn = mongoose.createConnection(..); - conn.on('error', handleError); - - hr - :markdown - **Something to add?** - - If you'd like to contribute to this page, please [visit it](https://github.com/learnboost/mongoose/tree/master/docs/faq.jade) on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request. - br - diff --git a/docs/3.2.x/docs/guide.html b/docs/3.2.x/docs/guide.html deleted file mode 100644 index c76f95bb639..00000000000 --- a/docs/3.2.x/docs/guide.html +++ /dev/null @@ -1,187 +0,0 @@ -Mongoose Schemas v3.2.2Fork me on GitHub

Schemas

If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

Defining your schema

Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

var blogSchema = new Schema({
-  title:  String,
-  author: String,
-  body:   String,
-  comments: [{ body: String, date: Date }],
-  date: { type: Date, default: Date.now },
-  hidden: Boolean,
-  meta: {
-    votes: Number,
-    favs:  Number
-  }
-});

If you want to add additional keys later, use the Schema#add method.

-Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. -Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

The permitted SchemaTypes are

  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • ObjectId
  • Array
Read more about them here.

Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

Pluggable

Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

Instance methods

Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

Defining an instance method is easy.

var animalSchema = new Schema({ name: String, type: String });
-
-animalSchema.methods.findSimilarTypes = function (cb) {
-  return this.model('Animal').find({ type: this.type }, cb);
-}

Now all of our animal instances have a findSimilarTypes method available to it.

var Animal = mongoose.model('Animal', animalSchema);
-var dog = new Animal({ type: 'dog' });
-
-dog.findSimilarTypes(function (err, dogs) {
-  console.log(dogs); // woof
-});

Statics

-Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

animalSchema.statics.findByName = function (name, cb) {
-  this.find({ name: new RegExp(name, 'i') }, cb);
-}
-
-var Animal = mongoose.model('Animal', animalSchema);
-Animal.findByName('fido', function (err, animals) {
-  console.log(animals);
-});

Indexes

Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

animalSchema.index({ name: 1, type: -1 });
-

When your application starts up, Mongoose automatically calls ensureIndex for each defined index. It is recommended this behavior be disabled in production by setting the autoIndex option of your schema to false.

animalSchema.set('autoIndex', false);
-// or
-new Schema({..}, { autoIndex: false });
-

See also the Model#ensureIndexes method for more details.

Virtuals

Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

var personSchema = new Schema({
-  name: {
-    first: String,
-    last: String
-  }
-});
-
-var Person = mongoose.model('Person', personSchema);
-
-var bad = new Person({
-    name: { first: 'Walter', last: 'White' }
-});

Suppose we want to log the full name of bad. We could do this manually like so:

console.log(bad.name.first + ' ' + bad.name.last); // Walter White

Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

personSchema.virtual('name.full').get(function () {
-  return this.name.first + ' ' + this.name.last;
-});

Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

console.log('%s is insane', bad.name.full); // Walter White is insane

It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

bad.name.full = 'Breaking Bad';

Mongoose let's you do this as well through its virtual attribute setters:

personSchema.virtual('name.full').set(function (name) {
-  var split = name.split(' ');
-  this.name.first = split[0];
-  this.name.last = split[1];
-});
-
-...
-
-mad.name.full = 'Breaking Bad';
-console.log(mad.name.first); // Breaking

If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

Options

Schemas have a few configurable options which can be passed to the constructor or set directly:

new Schema({..}, options);
-
-// or
-
-var schema = new Schema({..});
-schema.set(option, value);
-

Valid options:

- -

option: autoIndex

At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

var schema = new Schema({..}, { autoIndex: false });
-var Clock = db.model('Clock', schema);
-Clock.ensureIndexes(callback);
-

option: capped

Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

new Schema({..}, { capped: 1024 });

The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });
-

option: id

Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

// default behavior
-var schema = new Schema({ name: String });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p.id); // '50341373e894ad16347efe01'
-
-// disabled id
-var schema = new Schema({ name: String }, { id: false });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p.id); // undefined
-

option: _id

Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

- -

Pass this option during schema construction to prevent documents from getting an auto _id created.

// default behavior
-var schema = new Schema({ name: String });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
-
-// disabled _id
-var schema = new Schema({ name: String }, { _id: false });
-var Page = db.model('Page', schema);
-var p = new Page({ name: 'mongodb.org' });
-console.log(p); // { name: 'mongodb.org' }
-

option: read

Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

var schema = new Schema({..}, { read: 'primary' });            // also aliased as 'p'
-var schema = new Schema({..}, { read: 'primaryPreferred' });   // aliased as 'pp'
-var schema = new Schema({..}, { read: 'secondary' });          // aliased as 's'
-var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp'
-var schema = new Schema({..}, { read: 'nearest' });            // aliased as 'n'
-

The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'.

- -

The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

- -

NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

// pings the replset members periodically to track network latency
-// now `nearest` works as intended
-var options = { replset: { strategy: 'ping' }};
-mongoose.connect(uri, options);
-
-var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
-mongoose.model('JellyBean', schema);
-

option: safe

This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

var safe = true;
-new Schema({ .. }, { safe: safe });
-

By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. -By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

- -

There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

var safe = { w: "majority", wtimeout: 10000 };
-new Schema({ .. }, { safe: safe });
-

option: shardKey

The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
-

Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

option: strict

The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.

var thingSchema = new Schema({..})
-var Thing = db.model('Thing', schemaSchema);
-var thing = new Thing({ iAmNotInTheSchema: true });
-thing.save(); // iAmNotInTheSchema is not saved to the db
-
-// set to false..
-var thingSchema = new Schema({..}, { strict: false });
-var thing = new Thing({ iAmNotInTheSchema: true });
-thing.save(); // iAmNotInTheSchema is now saved to the db!!
-

This also affects the use of doc.set() to set a property value.

var thingSchema = new Schema({..})
-var Thing = db.model('Thing', schemaSchema);
-var thing = new Thing;
-thing.set('iAmNotInTheSchema', true);
-thing.save(); // iAmNotInTheSchema is not saved to the db
-

This value can be overridden at the model instance level by passing a second boolean argument:

var Thing = db.model('Thing');
-var thing = new Thing(doc, true);  // enables strict mode
-var thing = new Thing(doc, false); // disables strict mode
-

The strict option may also be set to "throw" which will cause errors to be produced instead of dropping the bad data.

NOTE: do not set to false unless you have good reason.

- -

NOTE: in mongoose v2 the default was false.

- -

NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.

var thingSchema = new Schema({..})
-var Thing = db.model('Thing', schemaSchema);
-var thing = new Thing;
-thing.iAmNotInTheSchema = true;
-thing.save(); // iAmNotInTheSchema is never saved to the db
-

option: toJSON

Exactly the same as the toObject option but only applies when the documents toJSON method is called.

var schema = new Schema({ name: String });
-schema.path('name').get(function (v) {
-  return v + ' is my name';
-});
-schema.set('toJSON', { getters: true, virtuals: false });
-var M = mongoose.model('Person', schema);
-var m = new M({ name: 'Max Headroom' });
-console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
-console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
-// since we know toJSON is called whenever a js object is stringified:
-console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
-

option: toObject

Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

- -

To have all virtuals show up in your console.log output, set the toObject option to { getters: true }:

var schema = new Schema({ name: String });
-schema.path('name').get(function (v) {
-  return v + ' is my name';
-});
-schema.set('toObject', { getters: true });
-var M = mongoose.model('Person', schema);
-var m = new M({ name: 'Max Headroom' });
-console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
-

option: versionKey

The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

var schema = new Schema({ name: 'string' });
-var Thing = db.model('Thing', schema);
-var thing = new Thing({ name: 'mongoose v3' });
-thing.save(); // { __v: 0, name: 'mongoose v3' }
-
-// customized versionKey
-new Schema({..}, { versionKey: '_somethingElse' })
-var Thing = db.model('Thing', schema);
-var thing = new Thing({ name: 'mongoose v3' });
-thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
-

Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

new Schema({..}, { versionKey: false });
-var Thing = db.model('Thing', schema);
-var thing = new Thing({ name: 'no versioning please' });
-thing.save(); // { name: 'no versioning please' }
-
-

Next Up

Now that we've covered Schemas, let's take a look at SchemaTypes.

diff --git a/docs/3.2.x/docs/guide.jade b/docs/3.2.x/docs/guide.jade deleted file mode 100644 index cb793d34455..00000000000 --- a/docs/3.2.x/docs/guide.jade +++ /dev/null @@ -1,450 +0,0 @@ -extends layout - -block content - h2 Schemas - :markdown - If you haven't yet done so, please take a minute to read the [quickstart](./index.html) to get an idea of how Mongoose works. - :markdown - If you are migrating from 2.x to 3.x please take a moment to read the [migration guide](./migration.html). - :markdown - This page covers `Schema` [definition](#definition), [plugins](#plugins), instance [methods](#methods), [statics](#statics), [indexes](#indexes), [virtuals](#virtuals) and [options](#options). Let's start with `Schema` definition. - h3#definition Defining your schema - p - | Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection. - :js - var blogSchema = new Schema({ - title: String, - author: String, - body: String, - comments: [{ body: String, date: Date }], - date: { type: Date, default: Date.now }, - hidden: Boolean, - meta: { - votes: Number, - favs: Number - } - }); - p - em - | If you want to add additional keys later, use the - a(href="./api.html#schema_Schema-add") Schema#add - | method. - p - | Each key in our - code blogSchema - | defines a property in our documents which will be cast to its associated - a(href="./api.html#schematype_SchemaType") SchemaType - |. For example, we've defined a - code title - | which will be cast to the - a(href="./api.html#schema-string-js") String - | SchemaType and - code date - | which will be cast to a - code Date - | SchemaType. - | Keys may also be assigned nested objects containing further key/type definitions - em (e.g. the `meta` property above). - p - | The permitted SchemaTypes are - ul - li String - li Number - li Date - li Buffer - li Boolean - li Mixed - li ObjectId - li Array - | Read more about them - a(href="./schematypes.html") here - | . - p - | Schemas not only define the structure of your document and casting of properties, they also define document - a(href="#methods") instance methods - |, static - a(href="#statics") Model methods - |, - a(href="#indexes") compound indexes - | and document lifecycle hooks called - a(href="./middleware.html") middleware - |. - h3#plugins Pluggable - p - | Schemas are - a(href="./plugins.html") pluggable - | which allows us to package up reusable features into - a(href="http://plugins.mongoosejs.com") plugins - | that can be shared with the community or just between your projects. - h3#methods Instance methods - p - a(href="./models.html") Models - | are just fancy - code constructor - | functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are - a(href="./documents.html") documents - |. - p - | Defining an instance method is easy. - :js - var animalSchema = new Schema({ name: String, type: String }); - - animalSchema.methods.findSimilarTypes = function (cb) { - return this.model('Animal').find({ type: this.type }, cb); - } - p - | Now all of our - code animal - | instances have a - code findSimilarTypes - | method available to it. - :js - var Animal = mongoose.model('Animal', animalSchema); - var dog = new Animal({ type: 'dog' }); - - dog.findSimilarTypes(function (err, dogs) { - console.log(dogs); // woof - }); - h3#statics Statics - p - | Adding static constructor methods to Models is simple as well. Continuing with our - code animalSchema - |: - :js - animalSchema.statics.findByName = function (name, cb) { - this.find({ name: new RegExp(name, 'i') }, cb); - } - - var Animal = mongoose.model('Animal', animalSchema); - Animal.findByName('fido', function (err, animals) { - console.log(animals); - }); - h3#indexes Indexes - p - a(href="http://www.mongodb.org/display/DOCS/Indexes") Indexes - | can be defined - a(href="./api.html#schematype_SchemaType-index") at - | - a(href="./api.html#schematype_SchemaType-unique") the - | - a(href="./api.html#schematype_SchemaType-sparse") path - | - a(href="./api.html#schematype_SchemaType-expires") level - | or the - code schema - | level. Defining indexes at the schema level is necessary when defining - a(href="http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys", target="_blank") compound indexes - |. - :js - animalSchema.index({ name: 1, type: -1 }); - - :markdown - When your application starts up, Mongoose automatically calls `ensureIndex` for each defined index. It is recommended this behavior be disabled in production by setting the `autoIndex` option of your schema to `false`. - - :js - animalSchema.set('autoIndex', false); - // or - new Schema({..}, { autoIndex: false }); - - p - | See also the - a(href="./api.html#model_Model-ensureIndexes") - code Model#ensureIndexes - | method for more details. - - h3#virtuals Virtuals - :markdown - [Virtual](./api.html#schema_Schema-virtual) attributes are attributes that are convenient to have around but that do not get persisted to MongoDB. - :js - var personSchema = new Schema({ - name: { - first: String, - last: String - } - }); - - var Person = mongoose.model('Person', personSchema); - - var bad = new Person({ - name: { first: 'Walter', last: 'White' } - }); - :markdown - Suppose we want to log the full name of `bad`. We could do this manually like so: - :js - console.log(bad.name.first + ' ' + bad.name.last); // Walter White - :markdown - Or we could add a `virtual` attribute [getter](./api.html#virtualtype_VirtualType-get) to our `personSchema` so we don't need to write out this string concatenation mess each time: - :js - personSchema.virtual('name.full').get(function () { - return this.name.first + ' ' + this.name.last; - }); - :markdown - Now, when we access our virtual full name property, our getter function will be invoked and the value returned: - :js - console.log('%s is insane', bad.name.full); // Walter White is insane - :markdown - It would also be nice to be able to set `this.name.first` and `this.name.last` by setting `this.name.full`. For example, if we wanted to change `bad`'s `name.first` and `name.last` to 'Breaking' and 'Bad' respectively, it'd be nice to just: - :js - bad.name.full = 'Breaking Bad'; - :markdown - Mongoose lets you do this as well through its virtual attribute [setters](./api.html#virtualtype_VirtualType-set): - :js - personSchema.virtual('name.full').set(function (name) { - var split = name.split(' '); - this.name.first = split[0]; - this.name.last = split[1]; - }); - - ... - - mad.name.full = 'Breaking Bad'; - console.log(mad.name.first); // Breaking - :markdown - If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you. - - h3#options Options - :markdown - `Schema`s have a few configurable options which can be passed to the constructor or `set` directly: - :js - new Schema({..}, options); - - // or - - var schema = new Schema({..}); - schema.set(option, value); - - :markdown - Valid options: - - - [autoIndex](#autoIndex) - - [capped](#capped) - - [id](#id) - - [_id](#_id) - - [read](#read) - - [safe](#safe) - - [shardKey](#shardKey) - - [strict](#strict) - - [toJSON](#toJSON) - - [toObject](#toObject) - - [versionKey](#versionKey) - - h4#autoIndex option: autoIndex - :markdown - At application startup, Mongoose sends an `ensureIndex` command for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model-ensureIndexes) method on your model. - :js - var schema = new Schema({..}, { autoIndex: false }); - var Clock = db.model('Clock', schema); - Clock.ensureIndexes(callback); - - h4#capped option: capped - :markdown - Mongoose supports MongoDBs [capped](http://www.mongodb.org/display/DOCS/Capped+Collections) collections. To specify the underlying MongoDB collection be `capped`, set the `capped` option to the maximum size of the collection in [bytes](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-size.). - :js - new Schema({..}, { capped: 1024 }); - :markdown - The `capped` option may also be set to an object if you want to pass additional options like [max](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-max) or [autoIndexId](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-autoIndexId). In this case you must explicitly pass the `size` option which is required. - :js - new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } }); - - h4#id option: id - :markdown - Mongoose assigns each of your schemas an `id` virtual getter by default which returns the documents `_id` field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an `id` getter added to your schema, you may disable it passing this option at schema construction time. - :js - // default behavior - var schema = new Schema({ name: String }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p.id); // '50341373e894ad16347efe01' - - // disabled id - var schema = new Schema({ name: String }, { id: false }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p.id); // undefined - - h4#_id option: _id - :markdown - Mongoose assigns each of your schemas an `_id` field by default if one is not passed into the [Schema](/docs/api.html#schema-js) constructor. The type assiged is an [ObjectId](/docs/api.html#schema_Schema-Types) to coincide with MongoDBs default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option. - - Pass this option during schema construction to prevent documents from getting an auto `_id` created. - :js - // default behavior - var schema = new Schema({ name: String }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' } - - // disabled _id - var schema = new Schema({ name: String }, { _id: false }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p); // { name: 'mongodb.org' } - - h4#read option: read - :markdown - Allows setting [query#read](/docs/api.html#query_Query-read) options at the schema level, providing us a way to apply default [ReadPreferences](http://docs.mongodb.org/manual/applications/replication/#replica-set-read-preference) to all queries derived from a model. - - :js - var schema = new Schema({..}, { read: 'primary' }); // also aliased as 'p' - var schema = new Schema({..}, { read: 'primaryPreferred' }); // aliased as 'pp' - var schema = new Schema({..}, { read: 'secondary' }); // aliased as 's' - var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp' - var schema = new Schema({..}, { read: 'nearest' }); // aliased as 'n' - - :markdown - The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'. - - The read option also allows us to specify _tag sets_. These tell the [driver](https://github.com/mongodb/node-mongodb-native/) from which members of the replica-set it should attempt to read. Read more about tag sets [here](http://docs.mongodb.org/manual/applications/replication/#tag-sets) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences). - - _NOTE: if you specify the read pref 'nearest', you must also pass the [strategy](http://mongodb.github.com/node-mongodb-native/api-generated/replset.html?highlight=strategy) option when connecting or your reads will not behave predictably:_ - - :js - // pings the replset members periodically to track network latency - // now `nearest` works as intended - var options = { replset: { strategy: 'ping' }}; - mongoose.connect(uri, options); - - var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] }); - mongoose.model('JellyBean', schema); - - h4#safe option: safe - :markdown - This option is passed to MongoDB with all operations and specifies if errors should be returned to our callbacks as well as tune write behavior. - - :js - var safe = true; - new Schema({ .. }, { safe: safe }); - - :markdown - By default this is set to `true` for all schemas which guarentees that any occurring error gets passed back to our callback. - By setting `safe` to something else like `{ j: 1, w: 2, wtimeout: 10000 }` we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback. - - There are other write concerns like `{ w: "majority" }` too. See the MongoDB [docs](http://www.mongodb.org/display/DOCS/getLastError+Command) for more details. - - :js - var safe = { w: "majority", wtimeout: 10000 }; - new Schema({ .. }, { safe: safe }); - - h4#shardKey option: shardKey - :markdown - The `shardKey` option is used when we have a [sharded MongoDB architecture](http://www.mongodb.org/display/DOCS/Sharding+Introduction). Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set. - - :js - new Schema({ .. }, { shardkey: { tag: 1, name: 1 }}) - - :markdown - _Note that Mongoose does not send the `shardcollection` command for you. You must configure your shards yourself._ - - h4#strict option: strict - :markdown - The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db. - - :js - var thingSchema = new Schema({..}) - var Thing = db.model('Thing', schemaSchema); - var thing = new Thing({ iAmNotInTheSchema: true }); - thing.save(); // iAmNotInTheSchema is not saved to the db - - // set to false.. - var thingSchema = new Schema({..}, { strict: false }); - var thing = new Thing({ iAmNotInTheSchema: true }); - thing.save(); // iAmNotInTheSchema is now saved to the db!! - - :markdown - This also affects the use of `doc.set()` to set a property value. - - :js - var thingSchema = new Schema({..}) - var Thing = db.model('Thing', schemaSchema); - var thing = new Thing; - thing.set('iAmNotInTheSchema', true); - thing.save(); // iAmNotInTheSchema is not saved to the db - - :markdown - This value can be overridden at the model instance level by passing a second boolean argument: - - :js - var Thing = db.model('Thing'); - var thing = new Thing(doc, true); // enables strict mode - var thing = new Thing(doc, false); // disables strict mode - - :markdown - The `strict` option may also be set to `"throw"` which will cause errors to be produced instead of dropping the bad data. - - :markdown - _NOTE: do not set to false unless you have good reason._ - - _NOTE: in mongoose v2 the default was false._ - - _NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option._ - - :js - var thingSchema = new Schema({..}) - var Thing = db.model('Thing', schemaSchema); - var thing = new Thing; - thing.iAmNotInTheSchema = true; - thing.save(); // iAmNotInTheSchema is never saved to the db - - h4#toJSON option: toJSON - :markdown - Exactly the same as the [toObject](#toObject) option but only applies when the documents `toJSON` method is called. - :js - var schema = new Schema({ name: String }); - schema.path('name').get(function (v) { - return v + ' is my name'; - }); - schema.set('toJSON', { getters: true, virtuals: false }); - var M = mongoose.model('Person', schema); - var m = new M({ name: 'Max Headroom' }); - console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' } - console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } - // since we know toJSON is called whenever a js object is stringified: - console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" } - - h4#toObject option: toObject - :markdown - Documents have a [toObject](/docs/api.html#document_Document-toObject) method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default. - - To have all virtuals show up in your `console.log` output, set the `toObject` option to `{ getters: true }`: - - :js - var schema = new Schema({ name: String }); - schema.path('name').get(function (v) { - return v + ' is my name'; - }); - schema.set('toObject', { getters: true }); - var M = mongoose.model('Person', schema); - var m = new M({ name: 'Max Headroom' }); - console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } - - h4#versionKey option: versionKey - :markdown - The `versionKey` is a property set on each document when first created by Mongoose. This keys value contains the internal [revision](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning) of the document. The name of this document property is configurable. The default is `__v`. If this conflicts with your application you can configure as such: - :js - var schema = new Schema({ name: 'string' }); - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'mongoose v3' }); - thing.save(); // { __v: 0, name: 'mongoose v3' } - - // customized versionKey - new Schema({..}, { versionKey: '_somethingElse' }) - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'mongoose v3' }); - thing.save(); // { _somethingElse: 0, name: 'mongoose v3' } - - :markdown - Document versioning can also be disabled by setting the `versionKey` to false. _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning)._ - :js - new Schema({..}, { versionKey: false }); - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'no versioning please' }); - thing.save(); // { name: 'no versioning please' } - - - h3#next Next Up - :markdown - Now that we've covered `Schemas`, let's take a look at [SchemaTypes](/docs/schematypes.html). - -script. -document.body.className = 'load'; -include includes/googleanalytics diff --git a/docs/3.2.x/docs/helpers/filters.js b/docs/3.2.x/docs/helpers/filters.js deleted file mode 100644 index 33546a7e805..00000000000 --- a/docs/3.2.x/docs/helpers/filters.js +++ /dev/null @@ -1,20 +0,0 @@ - -var hl = require('highlight.js') - -module.exports = exports = function (jade) { - // add highlighting filter to jade - - jade.filters.js = function (str) { - str = str.replace(/\\n/g, '\n'); - var ret = hl.highlight('javascript', str).value; - var code = '
' + ret.replace(/\n/g, '\\n') + '
'; - return code; - } - - jade.filters.bash = function (str) { - var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; - var code = '
' + ret + '
'; - return code - } - -} diff --git a/docs/3.2.x/docs/helpers/highlight.js b/docs/3.2.x/docs/helpers/highlight.js deleted file mode 100644 index 8aca9b9e222..00000000000 --- a/docs/3.2.x/docs/helpers/highlight.js +++ /dev/null @@ -1,11 +0,0 @@ - -var h = require('highlight.js') - -function hl (str) { - str = str.replace(/\\n/g, '\n'); - var ret = h.highlight('javascript', str).value; - var code = '
' + ret+ '
'; - return code; -} - -module.exports = hl; diff --git a/docs/3.2.x/docs/helpers/href.js b/docs/3.2.x/docs/helpers/href.js deleted file mode 100644 index e7299b1cf0d..00000000000 --- a/docs/3.2.x/docs/helpers/href.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str, char) { - if ('string' != typeof str) return str; - return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); -} diff --git a/docs/3.2.x/docs/helpers/klass.js b/docs/3.2.x/docs/helpers/klass.js deleted file mode 100644 index 0c4a865b43b..00000000000 --- a/docs/3.2.x/docs/helpers/klass.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str) { - var parts = str.replace(/\.js$/, '').split('/'); - return parts.join('_'); -} diff --git a/docs/3.2.x/docs/helpers/linktype.js b/docs/3.2.x/docs/helpers/linktype.js deleted file mode 100644 index 997e740f671..00000000000 --- a/docs/3.2.x/docs/helpers/linktype.js +++ /dev/null @@ -1,50 +0,0 @@ - -var types = {}; -types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; -types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' -types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' -types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' -types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' -types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' -types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' -types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' -types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' -types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' - -// mongoose -types.ObjectId = '#types_objectid_ObjectId'; -types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; -types.MongooseArray = '#types_array_MongooseArray'; -types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; -types.Query = '#query-js'; -types.QueryStream = '#querystream_QueryStream'; -types.Document = '#document_Document'; -types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; -types.Document = '#document_Document'; -types.Model = '#model_Model'; -types.Connection = '#connection_Connection'; -types.Collection = '#collection_Collection'; -types.Schema = '#schema_Schema'; -types.Promise = '#promise_Promise'; -types.Mongoose = '#index_Mongoose'; -types.MongooseError = '#error_MongooseError'; -types.Type = '#schematype_SchemaType'; // ? -types.SchemaType = '#schematype_SchemaType'; -types.SchemaArray = '#schema_array_SchemaArray'; -types.Mixed = '#schema_mixed_Mixed'; -types.VirtualType = '#virtualtype_VirtualType'; -types.MongooseBuffer = '#types_buffer_MongooseBuffer'; -types.Buffer = 'http://nodejs.org/api/buffer.html'; - -module.exports= function (type) { - if (types[type]) { - return '' + type + ''; - } - return '' + type + ''; -} - -module.exports.types = types; -module.exports.type = function (str) { - if (types[str]) return types[str]; - return str; -} diff --git a/docs/3.2.x/docs/images/apps/attictv.png b/docs/3.2.x/docs/images/apps/attictv.png deleted file mode 100644 index 1327f0bd858cf6f002a077a9aafba1217ce38e9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42666 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 Cl*SPN diff --git a/docs/3.2.x/docs/images/apps/calllist.png b/docs/3.2.x/docs/images/apps/calllist.png deleted file mode 100644 index 824fa428eb2de2a237b37ada591cc7056d68f399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33502 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 $5C9j=SSd5$;KOc+eQQ2^5$rlF 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 diff --git a/docs/3.2.x/docs/images/apps/cldfy.png b/docs/3.2.x/docs/images/apps/cldfy.png deleted file mode 100644 index c44ca3525daa7b847ab2869d44a00ebae852646d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9773 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 AJOBUy diff --git a/docs/3.2.x/docs/images/apps/clickdummy.png b/docs/3.2.x/docs/images/apps/clickdummy.png deleted file mode 100644 index 773ce3ec638a72dd3eb7ab6d103dade3874fa53e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34210 zcmV)(K#RYLP)=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81ZA(c+K~#9!?frR>W!ZVyiT%#G%iA+w zE>*eJUe#5-0=)wbl7O0o1|R`0BZ`D1k8F{U0wTq0EY*t&iCFu z_pIM{zWqDm5B}f}G=LC-AP5M<5X-V~9EZOse^LIYTI}EZz27@@Wvw+rhy#Cn(08=f z0Q(6~nHjeg#%&Ar;rzLTwc6k~goHG3TUd6@A(?ARV<&Ft&f zuOE6~084)*2}#T7yywAq3+PZZ9l62sH!S>b;H?ChtDNQji3Hv3` zK7@+r&s2Ese1UKLs7axa<8S?~zr}?M7qBdgKmOxCCW<125L~)+iCV43r#|&5zVxLp zp_Jmvl`C|+T`bGuOJDjDQ&ZFYkN@ib$=~{S`t&`)6DKtP_D#Xx`J&?O8-m;G@b72kd524$+OHIn__2kot;LDFpS9MTynV_p65|2m+5ud z1Yw9q(C>B#!f4+y*iMcoo_GRFM69f=5vd3vB)NP6#}c&K9l|i8SSpcoEbgzY9yrda znPZ$geUi#(u0NvG4n4}yKirL|_^#3`2MkFmYIO{39>S$>Jv z?_s+Is+AJWc8gZ4H9(B)Nt1UapL)$De7+h#gFpLmgUh$u2&J*zBCXDGwAP$EcaGOy zdyRkekNy$WYL!Z*lFAkH^YhHi%<$T4ukpR_eUGny{p&pQ%rh)3Eb!usFLLqXMgI5y zhriE@r`u>P_`m#jlK6l5U||}HIhdW){Fi?y`Jeq|*r>tR-x7T3bxo(Q z2_yJ_{juO5{+8mu`HJKdPisychfWV(e_nHH4!-fWAP5Zw8Mgs@ZOo$r;iCfdeq(zO z*<|Qlpj@7yR4j4)>1WYe)9ZBzLyhCOI624gwt$ott@;i>dh@M)$ELL=Uo2ru&E|HK zCoW#XbzKA+X<0}qu^oqQr;Q&dbkJjEW!12|d##DqhvRV)@Mm&=T5x`YrYrLZiE zYPE{vIBaZe&}=sOxu5$v`gcA+h%l}@kPRkFnqyUg9gorrV5lyjP|{aElH|5e3K6Mk@2#^m_H0sKJ#?;yZGsI8+wnghp(ptili_U3)& z7Z%C64wh{*Q7*HwzKN4}@jVaAvXK%t*VpiZfPus|e%}3V2S3uxPFHESTR67OPOXOH z=BQRDacvvV@6+%5^t;`7v-hEfLeT5Bxpws$PNBrx^&Kh`6C9gg#L^*~o7)6Y#DPUX zzt^SH=@0}VlhrB(*Wt#^8}xd8yuQcE{rhx#UBW2ZjTi!G_aeUbredjTqoXc8PZNb^ z@KOk7W@eF=1O+#5-sC&q`3`^g@BUpZ%i_yl{xT~oD|EYEHa0fc+1cUCU;Z+`@f*Lv zCqD5B-h1yoHa9o<-uJ%8x4->u{^sBOpY!GS&hWgt%75}DgA6~cOEw$u@4T$Icmh_p z4Kl253!(_N8qn;5=L^<$H1#%Y)*(`w)olnuLA|XB0(kG1APnK^J;7!jgn0aH(Lwt3 zL~FNKorl$IJxCD(HZ}|!v$eH_l#+?bDar+x)wOjrS@pb#HHqTDaYdoewGXb496v&U zQUj_xI={WNP+3adY}DfKwe(#ntyEszZ#~ob0_&?QY;CL&MG?o2&tr**_4Up4nEasG z7}S6D)mL}TQfru+u=)4DP~e#pb$Y!n|C|5pE>$B!SU*XvQM z)tH!=px5h>&*$+x56|-BMEk8(lN=^J(@hy=$b zH9a391$_?+IcW6^TNNn?Ln!1mVJNUH==5QtXxJym2G@aK`h?;OpVa*4zc2a0RWX*0 zdN6?c@MVs}YMLH(Y=^a2KTP>3*6mT|Iu`z)$;cmX-w;IVqu!4F%TZXa zKkUAbx{VLB-F^Ff<&{_TURa}JTIkvWr431Z)D!7o|CxtVsqWU|n9o^*;fJcK-Gg^N zsZbS3i!}&6KHnis><4rk( z>}HLusYZ`~9zRRo*O_q*NYmU1@aTB4b)?W*Wnh2Mw-L4^LdtktqjSm3PMa~R zND)PmVX>sZvMemij1>e*YkbeA*=)1Dxy|O<7PYM!-FBD24`X3dXMjn>n-z~M0SI9> zb`r~>2f7eF6JcJm7XA*%-&n`_AQ!$l{T7!sXp`2w9V!kLj zUXT=R2qS3w3P04imSn1EbFAW0ohVYMPQcVL)bug*_L1mNz1^9u{tNnXbvtN8PHDP zC^?w5Rz{l@!=^}JQzY6G9c#OE%C%$NK(x3$>E9pE+fdG*VAnr(wB8D7NMJ5zwfQhC}F@UQfnqk^Bm~Gx0@uHL&iXn&D zhHMcjVkp8ej2GVceT7bl9a%_efq+OUe9t5Be8M0g3d3|Wm5PYeFk+A(Ml9S9b9Z8J z3Nvt=6fuh!VT?sTE0tr3P&#R3$P8oz@x| zNi18TR5XB-$WWBTp;QQgWhsOeBZeAKr=-YHiZbHPG1!-QC3J?$X^o0M3#}1EgZW8` zv~4UWGzcREwo-=dB@DUNP^&lD+}a@wBS<%v46CHjDnoLu%&C%)*ZKW{%#1k2V69bBYIkBR2V@OXnE2cUKfmRCN4`{bK)OPA@Z|u;hH|TYG z1VL!#7`HgUftVU3r>Yp}=2PU)u%a?kKgKDe#7NjZtA<5&`@qB$ z0JMtCT0{{<#$`oE5hxpJ+XyMJi42VJh4W!TBx) z>d0Asn6iH$$zFoeu2!-_<&aQ3ES%_=^;62GRGpzvnHuj%$F8O_GaC_jgxGV4p6A6f z1}Tsx15RYAP(Uryq!eJ=g2|~Fnya_z`#$JWa-zhiw*gk9GKX76dnn}Y(TGHCo~*$b zem>#RlT$ib7Zs`WBu{P;k*Y^WH5~G=xUpy1Piu9w zWyt3yUfAS>*vlVh?C+U(lu~SMZ4rjX^+g>pm87|XE3j?J&wTRJyl{MiDDnnxKZE#~0jp(*wMr2rk&m<%h6-dUM$FzsQ3Ps0Arclc5yp}+B{E}b0v90E zfaOjF<7B0G9a?ILVk8P2A@l&)lk+b*{IZ(Bw5?=MGDbaV#Y2mcGYSlnL{^L#k%|`* zkf0(`o?od5OLv$rZSe1Yc8dSoe_!PI;w2Ur7icz{^!t4l78hB*{!Px#+~ek|izQ&9 zqzD3mWt(=}J<07go9(6?W|4kEN}*5~`tEsN%G)}Q@gYi1Dc|?gXRhnwI8N+<*Gqvh zm&+lgOgBFW0+cdxPY{H-4m@+p#`BGAt5vLl@-=zaP@Ls0Mc>ziQlPbr6$wBpr)2j@ z$B3apsDYLV5IVz?o3{;Lov2jR00>i7D@Go4!gghVH8THF>#H!XB2o|7HZ!hRI8Fdk zC0a5Awo1iqr4&QPZDkQ-K*@w0W~GE496$**5V1TwYHG;V69U6x8Vo@Ti4sOMP?2HX zM5M4)G|=B`Ez*THSPftNIl*Fin}6`TJ4`LS$o#^*aR!{4A__xFr7~wvPEZIHmrnSE zk)Y=ZW-FRrXiks|O9A&btOEh`qYAQd9EW1Dm;y)w$Vse8p-@OSq|s=Y6BEN1=ks}l z5O}^%6jKAoaVVF|^!t5+ARx%NL=UDXs1)NvRzau)wx!AE1S-8 zm{PHfk!3SdDaQ!?0z}L=i%NGWtQkY9=P0C-cxh=0@O5HUKv0b-1!+5;HM+N$(O9kVtXgB&`hLXiTYBO`p1 z5!Q?yt`#_5DWG!D>UezT+ut@qqt;lKZPM*X5X@ri1L^*N2Frq(iHMGG zQOFOO=rWtVx5UQ-Ivghnd7g*wdx;_g%d)U7gUCuLI-O2hH$jGE!Q1UN z0&=rpb|y{I|4LX#fp=}E+Y-QWt0`>J)^D#6&ZjPQW$^|10_eYW+^4pI_+1d?Ivo} z0acNSj1jLy%1S9sV)=<-*T7bWT^t;!gTL9$HfQk@r^RNG<6rBFLC1b_a1MvB&)=WIISL-+lW31FMB5dmi81LRv%zlc6@qH)X zl~zb0SY2D^cmDBz%FfP?5hTS()8oJH-(70N8fXd;dYF~UQjB;|B2_zQ5F_Cn;!`~} zU}_yh>p&wp&}0fE#-J!Hoz~Y%6GekI4Xa}i$Oz&CpjT01q%;3hi6ow~iUZj|W)UMR zV?k2u%DfOoW>QOwi!3cJAb{1iHQs*nPqC!W zb|W8Kvd5p`0~Y}Ulvxt}lTro(+CX?S2Fk%graWu%J$WzLluTQR6*gN(E6wC&mDm5$ z&r>WEDVHm$S8)O?wr!{KiW;Lb9bXcvk==BivNt+4pvB`;q%2N4e>pgPP2U4iAZgQR zfgsX46_}HDRkCaYVh{sumI|47Q#mEAtJAh3odw!>&Exin=ak65LK;?3#P+jf4fFut zN9<&o`HbwL$eb0Xk72k)Ti8)Fj2K}|-c)Rvlv1+1a-W;u_p-|=~+h&br{+Yd$LR`Y>(nStqfJ3_B4qaBNHJWRKdUjvj7ju=+zl zRLB=7l}ZRHQ%bS9xd}kO-%o7>iA^BN$RT@9CjR$7UcSS3mv>OMi?VFAw2k_7h-=Co zqhsbzre5}M_PH27oU+u>JQf4nP3DYB6*|e!v2iWCKIp{JGahHQ&#cBNUH%c9QHJ7= zE>mX1hU<+OnYC7w%O$?>i+`D8$7WNx$PN=-b6g^2^x5%IgVvgv*<+l)^wg07^#4>! z7zS)_ZIUY#DODyY7K>cEbcyBVWmZ>LDHe+;rSN^9cDuc2JBi6EQA9>cadWf5Mze#k zJhY6R2gL(PfN2?Q|2V452vOc$CuKpzNTWl*D0ZJvdQ5*~n1o@^*bzkCHJR}<8Na5c zUcJ#`W2;7Gaw;`C+Q!i<)^JM^KhQ({=wuQLj)iRx_VvCG4RC_sM5(3h7<#kVPS`WWSBEgD8Z0scfUDhKBPvq3>zdy zAyTI>oN;~~j5n>8h15Yc5*9A0Di0B!Jj@-Au!zIjT#y>i3+VQ|0mVQ?>4=R?6rn~Y z_7{lp@FlCQlTvd2{CQSaR|&(Aa=C2k#4KwN1k`G^A%kGH3`C5qQ8qTZ35awiaA-(# zHW)|33=9V`#hMv3iE>V<@wODDNL-FkI`&&kJf35gDLLO&>S!8wmA?+uZ_VlbbT+N)AM4Dtj6|3VPUz=wP%l zCb3s?0wx-pD2lK$R_ML5T_<*cBsFBBYEJm~te5C$qK0G)iGR~Bk5Z*l74!p_%yFia zqSb1p;~Ga9#<5kSEYH9O7Q0qx&C5?m{IyRhRvUs(KMgy52srB!-grl{(J^z{ZVDz!CID-y0r$&?8kBjb!u13IeM zS6buwKE1w|Dxd6LU@RP3gBBVujM4;F9|n5dym_7Pe)kQQ7Ec)aKp4_&H7Vo^IF3WJ z)ud9HNcH`vPoH6Rb%p!)mpOChEVbGWpZ)CT`8R*^$MpJr%H=Yi*T->Oip3&pYpYC5 zOcDeEi;Ii6ZjKjTc!@XP{2@1QUQgXSI-M@A^{GtVnr7b<1=rB5oJUeGi<;AuE_ z5zfpj-d%y8f6h>rckaWfIrwX@!?oK6C_neA;>krrRetwh2;N^atlIRX=9LQ&2Jo>9 zn$OK@`XM}jMldm{DY;N<2r32m((8(MZU|;(G(Y&U-DHkRr%^y|CH)vm4$^x zKKNjh#l;hJ+HF3#`aU;qT;uH7^StoFi)^f~@y&03jZ&%1)YLSe`OMGrr+@k_0b`Neh1Rq<_ zSQea}2hRgfK_&Kc3qxpn@Z2fQ{Vl<%wv8fB$QOViErGaX5KQ^UZez zQ?pPlL8Yka2ZGxxf*W=C)LBit3#BT|RbvS%o};t{fA4QD@Z2c}-`D&H|Hs?>$N%Rh z}Rb%k6m$H|kYxq9^jE?s<*e4&6+ij|f7R4Nr-dhrz+%{ogM~ zODC9{o2S!h1HxFQZHG>$vyb)ufD(Igf?=f+mJJMhmu)vihM0Fw_Itejf0$-`^-aNV z{etFy{YA}tHw1S#1$nLML~wUo@bk}VHfpe36a4;H1@kkSQ!~)_p}P$`O}MlOGgF$c zy(Kuaq}gf-UOcO5b>Qxfpts;Mg(vwV%^`a2syi zhaY|*IB`s~wk>%6k|Ok>?ZKxmDQ4<|H?F|hCCEEa>kd=Qo~QZ7+YXD9E-L8IYDe_? znuYn}NGms}s}BHt_LngLB4u&}s2GjxAkv^!>NKX*Fkkk#HBwX4(|q9zzZ$z+SZM&1 zZQDpG@jQ=QE|p#Baso%nT)E&{Q15_ySrA0<)wfJ$$Y#&H z_s_m+sF@XOuYw4^@)qQ5!FCgD8>Y&FMmzDn1IGcS1qD~o^Wn9RX&fc_{cj2CT}?4> zDAsm!ka#aCUwtc}?@#jd2^*(0$E8arnVX*^TU_SVHBw-^`x=0&SOdYSwE=9 zO*3rUPSuuRT)y2H5R&J6J)B~r+4iz^N~O|JKS?=?+iSCEFz$w_gNoks z3qyixt7rZJLs=KKHo1KVK|BIX0uMTUQzwb4NNf##76MzWL?*KNh?xp&lboyKDZX(Nmep`aXR9ZTPbfN`$$yES?wyT|M|B?#&6M zzFDzD(2%MnaiU7{a13mzk5&@RPNFeV@tp}$O2RNe#_3l^HAcya5Je%DWv4+kX+mEe z@1Af$hvuKmfsQ~2ARG`@ybKcKS(o{%y_lKJ4(px7%+4Ig_kHS(9p>g1@w`5b#tw^%rvYd-YAi0DW@~GWg@sexyLS_QvQbNci}CJRki`+tB{f{CAp-em|jpl}I-bqF?L^7Ej3;N6CqzXlus6-@p-G`|Mr zSE2r|!J2{DzXA3nx_$$_@isJWq5U@E*mDRghr0g;V&N6U{LAR~e-HWGZ=tUK0lK@1 zy!dN~*{2U&1FbcV<8bQKDZsE*$<0HXo166e{eu@WF-`COaajA3IOJs@+gP;s;sEp> zJoqrQXARRS#Tb|TK`=0NkNlhrFa2eVF?l!3s1ZXnYQM2RAiO5a7puON*(_`gppxJe zg%B#OZNmP5_3>pRTM9H&q$L2wtW38;P!w*EhcT38d%eHX%QuxG(tfX)9JdOwEpC!qON z===bp23S)NY(f4K$e3O7YUrISh|otq{WnnW{~kK*f!9Dxo-BD-<@8jW&yihbH{_(aW(wTNFPHP3rBt* zcPULa*+7y<3L$V^7vB#up2=~gjE~(Q8H0$EX!x1m5@VxEy)Z^8TH=%SSW1RmX-Gm_ zwFyx~5Df|6M{tX9FQ5Cr+GW z<^FAM-@b~J64!B!dKo}<4RsJXKtWiC(z6hCz@7&GE_gRg-Nsj-_;Dy)1b^MIT-DFP z_CLdyCy|v`uo4DR1&Hn%=n!GK=-ebk9{T>b5rt#uweKU(eGYZ~UlLsZSEy(Ib{x;K z&$`EI*olb=wAS?deWEBLm&;M9RG65o((86Rhd~PK?uRpsncA#_ymoe zE#AL!h0UD?j%^MU&`8TB3_QBs9&Rod8%}M6loWCSi25Bm){k%E7?tceezm7QdI&%JH^vd_p^_$4jaeC7qr?I`x(&DN8 z_k&?st57JUR{dV5$z&-aR}9I?f%?|O&s)2cBSW9GM(K#FSFSKSJIkG$H<({s!g7n8 zSej#MYMM^FN3od0^ZLB;#&=jcb(WF?L&tlm&zUR@X*Ku=sq!9G`eTu~*K^Rb(m|(I}VW-)o*KCq2O)xuC#g-C3@Ufgc zt}S@ytvA_f^qHET;q;lapcFw6GBH_ZVsZ*8CEZq?AHMZ21BZ{tr~pdkoIxf@5ZIy8 zamqp?poWnm(xa(zAB}!3ES$u3bM(3$jvqI&MY%Fbqfw(+EYWE;D`ve;#B3y)KcLPNUau zqI>Tk&%c1W{B6Xh@*CnP;&+{#m-WKEU?-tVf`n3vB5!<(UbjvS>EzOfCI7 z?N)=Z7je8Da{R&r-3YzjraC)E&av6v-sWRJ_cL_bO`<5^`i+~s z_`=7LN`VtmDil~*zDupy=0tUYwY628T#;IBi>EF=#p?1c>OIXXFFwZ)zxQ1NVe{hR z30$FB->Fe57b#XI$T<$zu3qKLg^NfOmhDn5m)LIk6pBSczsIdx_c?X?1dV2!eBR}~ zA7A0Ai|4T{VKRse1gG6#nDI%3g9ylQFqIwwZy{s1Av9V@>{KArafT0VJSd0J;n6Tw zYt7xeH)u8M6pAHo-Mm7l(@Jw!EiRs7b>$v~(gZWLHKMzh5$m_ny%xgBA)GwX)V-)3g!7@M1G1c8rj&C%(!ICbhgw{Ksg zQkg&l*RNmZ#EG+9y7aOA_G9odo1H?b)HZT_;T)@L>$r}Ci;D;aN-G2sJ0Fn`wvb}L z3XE4)YIb(E>2`bc{D>2a^X%+w(QGv71sWap(b72H^;=E+FyhXw8{{Wvxb(z%Zrr%e z)XXtviw;{`ThtpZgpl<6UFvm(<@D)xI^4WR6uBuUPNYS9?fl8qc{Jv}uwSKhyj)=+=zO)N_ijC$&BY@w8*I&++z z%{A`cUnRJ^g6mj#eGl8djS!kJG-I(Wi~7zc^;$d+tyo=M!?tXs(0G2pty_1}D~pq) z&6Z`MBE`82=V@$jvb9r3NDIfY@H`*evH9T2`>7ZA&dxScnuFPK9D*>wcAPW;+F;&; z7(QuRCco{j*bhBcQ?{30Lu+H4uq+GPu}Cu7+tPAC4l-R!tq&Io@&F|W0-ku{8S?oe z_4*dGv-4Cc6Krp-6GjpD@86+1HN$ju7Q7~+JdG$$AfI{-_5Qcfx8BBj`4>^Q-a+I` zh;tt|>PHnJ&wU&wW|7rnM4dYN-j&$S0Ak?+dgU5o@;Kt`$Iv$fdgVH*U5C~V^6bYE zj!SiFmg%Wk@`Vz)Tn^tiYUEO>LaWuF+il~zIqu!N$dme6lIC!29fRoE%34!nXNZX;1xA23IVx_|QGpD%n z{`&-x!m@3ojJSR4Ca&Y)xGtwop5*@WT?(ZNFTe0H-hKNmydc8!JY<}ctM7Se4NqKr zlF3q$)s=g!Zfv16mw{1+p<_#TB6^qvsr5xEoZ`YiGfTq&V_1hiSJKwY}>4@ z7TD6Z5lIda4CN5=;H-fUQYI&-s8*)|n4Ug{=k>UA=Q?2+GC4U-7zPL-Xt(RE)Z4fp z|3wPLGP83hXiv-&_&xez#O$lTLbI_0woAEGX661JtX7wkKl2;hU%kituY8Jnt3kOu zNg`9(SUUX#JM&LcES5k>R!a*MCZ@4gmub|u34;LJvY4EhGMXH%+1}Y? zYHBu4b>ndS_#(%TF9LAl8>GOTdBM{s)Rz@>M#z-iS;JJ^#$kb$+cB@IgJb?}Z zh}~O?#R|UHCWuU2g=OWKn8-6ZF+n$gQ%j3PQ9!rd#*Z}9QP7tgmk~KYtwG?^CO{ICgB7yle5nl`AZsIL*cLXAmfMY7J&*XXy2M9Gg8x zyS{_Um6@5E;?h&kP^pyJ-rOKptWYlIS>M>8IyKEywMr0#96L6{salO@r_aLNakjTM zaPlScu8puQh?baMU**cx8|X}G&g9hJEwqoZtq4HK)GI>AJeZWyB(W9JiZ2VX2Dx{R zsEo!?IF5@YErP&9YsKc~DpFe9zIByczQF9<607U?xqIgtx9(hLtG2`Ym*3>}y<2ST zY_qnu%=H^r5SGpC>^z-rn=2o@!)9%pt=cv{-vcK{uh*g3?a=77SX*1>#;vO?uP)PQ zHRuEZYis7x^iHQmp-|-B@-41>@D6LM%WQ40Q?G5|x;b{XH}JhaD=T+~b4-ny-x1^x^rE)awvcW&LHRGsC?i|0^EF*`epZCMmcB?`G5xqN|gsX(bb!R+iT>+37@0?oP8 zC%Jz88tqOGDJ|yb=ed9H4w05zIDZzjrc^9YtMAbBJiLC7TD{KP+#FgdPM$u)iN)h6 z1Q#z}q`9-n{k3(_ifh-dV&%##F3e%s4yVtar{D;#T)l>n4rk7s!Rr|x7#ZK#wC_J5 zOe&wDf5xb7+cu8lV%sJ~l1y*RNpcMh@xPD9nqpZt<;oB?Fwy~igux#5nC2B>zu|ug?c_3AGY5;!3;@Se+ zGOSpXWcky>nt9uGxp?Ukoo0iLt!>uV*Ezm;f>O?6eQTS*_o!57IX*qf%G#Qt(A_@$ zPMfY5a`ECt`mGu_Z!cpM5?l29CZf$;)h1IFtyUrJcAI9i!TRPl=gyrsId0K3nhj2! zImgswh5IXOXkcq|6VDGR6$@w;(P%bVU0VkM%lGcGzPW>rLT=u?$@H-~rYFj@+g;9_ zIfoAWc%Dxb1$5d?w6uBh(i8MLP2PO#ZKh|B;W+jXuqTKhGgW}zG>UCEG8;dW@hJDc5hKCmFf06)ayG`t23NA^91$! z4jUUQ96!D|58IT}wh==qv{pwUj8-e|-F8X;)ZYuwt}U~_8+4MdTmUaz6T051q} zY}@euXnK8*Lb1d%Pd~-g>o=L4nPc<*4y)^1Xat2qo^H2GE|*72=yc7g{N3+=9{?4F zCgGge;I=UC`9a_lC}X%3La@EH!8`B1OU`xa_4-IlruSWZaP=A>C=_yZI~^?B!F6o9 zy&m~|5v`32cp~p<1Ubhc3`67KXGuKYH<#{M=AMrq5mGXL{5V2dxXB`?_bSBd#KE>^yga4I^eKk= zGHo2KQsS^BRD)z|X~MptHL+M+Tq5*Zyfk$TNyJXQ&HUUfonDXmW5-xsT}PmBU6&{U zv?v&xfFYYIf5?U~1a+q9OntPuqp#I!rK_uxSnLF!5_^mu)X4Zj#*fCC`b9?bq=%Z? z2tf&h&_&G~)T10Q7LsNo-_G)TRSx!{NZ} z(TFS4kjNs)F2#}<#;u_bdwk!s48yk+!nmObu=T#M|Ir{ta*@f1=ky_zZ$s;MXpec3 zIkrCR{g7 z&w9|PMuOS0rsgqj|(CX}7aT8b6ZxJ-u`_gUox#77d9(y>A;2(%F(XWfkINMl+A6ZQDmGl z+iiqpr8lV#=U&RXgpXO=y@ow<>YHrp!x0m^4y~9XB<$6m?T$o64TrA|kmj%^(p~#8 zGHF=#pD?QxAu0vR7 zk2p8YBgT zk-`h(bf-h_nJb_pWdv`77$f@dv~@ky(_fTFDv!R1Sq<0V@}T%amJAdQCq~}=5zHlw z`Ft+D%Ojg$Iw{64Ob=a6kWE6DXzCKdeOypeGN2)#*3kF*_`x6{-i1ZUU-|Sjb5k~+ zukk`f!Ie1n;LR|$-3Vc9I#Hx)_Z6-qDYzz%L<3f=F9}1Ps&JDv*=~mXi*MGsa!;j- zmNc7Va=&1F$)-J6xh$WRAy<#6u1!+LBpRgQivz`;?*u`RW+#;K1t!UcWH)j5g@la# zo;A#6?~2RDnrBnnB=tstA)5^`oAGcj74Cx&{)5VJFr^+K2g!+@S<^k@a*_zjD75G) z&B>Fea4e|R8+cwHX*sAUV0w0zV$NaZ{tEeW8Cyym*QVR)((Crfm&zQUouOXaq3`*z zW=9YPAqa~~sYI{eHQv2(P*ygvL>TxuZjOQz@@uc;cxIu8*6{AV9&3$|xhV(77RI+L zCvhwYB2B9s;W!p2W-PAV?P9qWvy(QBPK0d>TuV?XO6tv!3#am2z2{NNOD-(A94o+I zc~$Vc8vz~PWw21mZL>zc)k4Ift=Ux4L#sOe>w}a|yUpEucZmH@;=~44nkdV%B)08P zC=}uh;3g_;XJWMebbAq~NJkDs(!X*x*>haa=B4 zdg|fRcperp7)|`2-PXgE}rA4pb=h*xL#c~0m zAm`fn)rj?#`zUGQ_4|}3s#K*wS{9{B1zQU0wK}%zGUv{7_vSTf^*TWiq-l_})&zcl z<+$Xmkev3}+~|RZRwH10D`IU8gk`M$$EuR4f@Hm+sI?=cC2%gd*ip#Jn&QSCg|sDp zpa?_AIf4_j7SqK(8yf+|oS^DBXuwesc?;Uw9cC|e!sZdjd}rNylNjAGDzb+y`9gt( zg~b%G`~5Din~P6sqiVEmJH5iISS(U1mCO~w!dy=!rNsA*lb;{>X>M8Db_^m2L9tN8 zaU8-hz_wj{-%Ekm0Ck>1T&LacAf=#MtrCV|n$ya*Z91I}<#IW7qpnnj-9QrefuyZ! zwVM9E7dRhX(YyW*``I3Rh6y1Ed_N5j-rQWH*K6atHd0#no=3e=r`BxK@Aa5HcHCq% zhuCx1BJ@4_o*$q3c?yLBlamvO^)))3uCZq*h2y$38#R32PwxjYaA2Gwr4V#H$p^RU zJh^D(i;~ownKJjy-`;|g(@=2*mVyaO;}(tcci8Dsvf<=}9>fp{lPR(7!;C9v?ZC;3 zQC9418Zf@Tu4whA_5kVFGgpWhF_KJ#5a;g9Xr*|F96p)iI1ba(Gnrpz4)tESeE6ui zq!f$A1KKqCt0pI_N7m zS;~yfq+ZL6Ch=a%Xo+uihF3-a4bS37t5rOe8-o~z6-^Eo+guK4;xV*l*CmC2Q68}z z)lv>^GjiVj}Llh?}-i99abjp4v&^`ynB-DP9SImRlatw zgwRo{RXS>|k1>YYDB;9NF>c-iA2eI(I7>*JW+ln?Jg6^@lo>co@fG}k?+4ftet9|~ z>=}OE+-_=QlpqKw7K;=L#Y43jY52qSfO-hOb`0pX)AasYoBQ%Am5Dtw9X`^I9A(*! z6T2&90c%7aPli({6ymkp9RaudI2~oiVF)pHX~M=B@3J1-+2cL6ZMbMTDm@+Pvayc^ zB~`E_mVR3)23JGrM8p`@;eOckBhZ@f)I%&G_)M-xea$3tmQvE`bZ{J#XnAgK{?Le_ zG<>%fanIAdUW(|iuj2WB?Dj6`^?IB-Wgk6a997YWd7RbUXP=0nib;B=;Y%OM@FMz= z5Z#U2%j)8gTL zt7hUNlW{kAoNnj)6#>lWj=tAf_ro{iKdRfgz-aCUzUId6o3|}#K>|&wD)r(z1hV7B*T}b2J-XF<1I=qom?ozd<-nAmLM38l; z{0K1P&rK1J%#tV#CucP$W@7^sMmzJ_^T)Yxyh>lXwCw^dS)^yV1jd_&Na-S!aP|rR@yt zYZ*$HSgVu6`#~{dghfpH$mI)6&mN1lu|t;c;mu5^m#AxFd&9mSr+d-j2T^kDcB)KO zccaFb4+UAXqSiyqAqlTlV_YsCq~x5;krj{W#6*Ep$EN7m1$LYXw(LooR*}ARiDDp5 zHhRcAL?`)(#URa$QAftW8dsD8VXkCN>!M9^K2$Wgg)6Bit+YK6x2GdR=?r2BlrWi2 zRHQ&fNEKmWRLIh{%;g%E#gNDDXbf-GtvDl}3>!Ij+mv*IV3{@)#Mx%lu2_CMA+j1B zt852e^ht@rfM&DtklT9n8it2&`*DtCcS-zke9xoX?L4#^+&IBy03`MAQL$I3iCR=5 zLJ^^o``XE#v|<2gGC7r#L(m{amh}-yt}&^NJ5D+$Q&*=KaAdTWalHh2h^dCDDPyhY zfPqpe0w|OcCR+`L0*UzdfmcRyP$&N~h%>s&Vk9mk=oan z>foYr@-s+h0>UvskZfAY4JCqk2FP{nO_c?JSeLJ}Z7?v*=?t0HBjXvC9g;&eTXVOK zMMIjA!%!?`h>_AU&c?aGvTB8RScCCd88(73vJS)Z936MEfn(*TWF<603vA+hmJ>25 z;xR-~l%}b-ESr4Z{fP?R`DrLo6w&wkShh2i#qdFkau$iK8DI+-gTOIR4gl&P%9M2z z9lkX~WaNZQ;|Dc2)>bkoBF#WE_zb84BBWrN&LwkFr)*Ag8=J>s^|hFku+})LG0Adnd)C zl*Aji*XyCRW@2IjAiV}4xi=#zqc=)fQqb*n==J+dX4)NSyN+u71N1NvredFZd;gT) znX$)6MRNB=RvUT%+-MQY0%P}UFE%IhTUJWX>X`OfIy<%a=|n4G8d+Ic6SKWux&*E}9v`MdzEaP*|rjw z^5kBMY^+5>^^zN$5D1J%d2(!ZM%=y?z&|C1qE|7JTzgyWLKM zek{wP)oR7JEd*#S3~@#BEk>IRsoIh6*#k?2jgs`WR7*ta^Sg5iJ9e>1RC( zi)o2dzYdLAkX%J(*rU;r46|3m^BFzr^&#M1g4icf-snN1HMUj*=|ADF3&#u>?5fp|GXEiHSJc5`<_Bhz$ZV^#gCCH%SxR% zae}3#CBPu{i!Z%Ixm=-8J&)DfF?VNpUwOd%eCLDcaH|Ij?j*flZ#>?|84v_eXOmNr{$kJ%IF&|0(J?1O;()EsDy zMB`+&6GGrl%nV28#e#f#LZl}3G1Ex3B`ReP%(jh)fQbNi5WALWGGYhG6bPh1C#gt@ z)tzC8@_i!TLj?gk3K42pFFvYHmjY}la3wgFFxO>Ci%?ob!er%0fJ&q%nr3>U8sA)H zuFh3TnT+j9VF5V_MH>pXNG-1_wjM^#vt32PO(J~$V6;}8@J{Iq}Z)A z)FU`E&X6=fnyjaU*`utGyPFau!B(c(%x;ee%_+qn2Pz_&e{6ry83VOYF<&>v?Iknb zT~_||5Yb5{!eJYR5Q5UgB%U9jBqU@~0Ac(s0XmtuDF_2_M*oJ%V;Zw&sl`)RyK}x| ziilm`jV^nDaD&AWXqogg9yzj;7Fr>q2%#baBtoDq3*zL}8f{WdMt%ICPtfiXw%g!) zSW$?jb$a)8h|!crF?_g|V8Vt{PEv6#+?-436zDnyy3)auj?t{f`g{?ulSUe2pHf7j zBJ_Ne*N4EvRS|hxQ_f3f^MXQr3v&=@LTxUyFBe>ss$P#c38t7k@DLrk^m6o4$E1G7 zHZlyu@s2Bvu#%gv6F5jtcJr>05i;$J;MAxJcGwW7)4sFYsS+ZUIgCuk#rP7-&r=_4(RLeVw)<_uz_r<5K=42hO<0LU@*NyxBD zk!G(bw?tK}O`9V|h2-qeVsPSX3B!S&aXWGDA)%E)G8M*`Zwhqmb|9n$!sJ$pEE`8h z_+dz-6w;EoI>OZ&OK2huzJ?(FCk2#j!AwqYydas%J2?3~{al%*TcK$c=}DImVUR*a z>0)akiG(0hioo{?dtHKV7v1aNggzx1QOOG?@{*!$HrbCfkuq!VTD#=}J^Ej*$=uUA z@S@Giu(1U?kvp-elp^j^n0wxbsBK2R7COmYt4Foj3{IXArXnSwvE?<@Mkq1{p#*W_ zK7}%rEwgxH^jJyU2u8GHneB{$dxQjMo)3CAWY!>tN)ZDgjny{oGD!e2I2a^G#&spw zNFt$AzFrHHg(7bW%C=zAkxb+y(zU^L=sFIT?P5vSv=&n>D~@&1QX++g)EZ%%fEgV{ zM4^vRVJskyT1AIJfXu8D9y@U&L}_$#_GDc`#zAO?l^L@9W_mCjgp8A%WvIlcbKqcy zOp40^jHOjHDn0enSG0!Y)KA&pfnYL_r7|pHtc^<%2IHDC$meU2Y&SQRVG(0$sWEFN zQaKxA+1H63V=(%`2Qi!>I!4%3bCvL~sX->|vViGK#V5Z;nhxdY37Ga`6a1Q<>H zSO%appcW<#k?pCx0|gQH!d0LcxZjBPlq7oFxgYfi*YL>=}h<=716zAi<;q5|)LqY@}u6o-_?! zDmU!fjNvs;0VzI6ltxQE&^II-D)epwB$Itlp*91Erh-n?N(0DERr{n03Yj@eHHv7U z_KyK?ybDK$D~Y2-4Y3%>F)%8UBtsf`p5Rq-m*kLuG9-s3lqsG^6hRcB!w{t+bQGb& z5IYP*NQGq;gOW61hGI8Qn+mpReFLy6S%75g(>QV+%NU79DS0kZ0}tumX{1ufcyZLo zifARwiJXyDM2sE@SCIJZ3}g&*5-32+*n>22q6;GeU&zAz4QLK}^f&?=UTEOew$aR!noGIEWIfhba%Kq>qX{CIvr zqzMy$A`O0|@j`HHffYvhI>eI!feP@YPk<&Q&Xtvtd3Gx+WPAh&fj|udO$-A9jKTw% z9y}uP!d2!3*Fqv>gs>7BGgeu|YcCS2C554u2^{Fe{agJc+ zMBDNWy4nuSp#<{kP-6@PB?5jWgR*F#ru05-`9;4q%51_#b zxJx^h(J!ZM9-w6v>^@a?;bkUvScq)>F+BMYdzKwTtlLjw-J=L1WmL7=s7@t1rNoJz zOk*gCD~)E#jqiqzge1hm7ZxEBB}UY>*%^w#FIp>97{w}LBa1i^Trp7KWe-|`k#TG( zu%tOyA|VNdg^xujr17jBS;p}xh!c%YmQBl0`jMB0-p|?&_EN(SX^E2OW3*#g-hafn zI1mXkP?;)(GOW`mbr{3<4E2>^&k|%B;vTfdUcPm0WEguvWQIg#*s1-%c%ZLl-!ila zL#rkZd}ptEhZ@_sI(yhivh8V|9qr)B?z3UMFP7MAO~wS#j34Q^F=kGDF=jt^X?qy> zHH`!6(TtJf>J8Or7{EuyHvIbD`#P|_9MsNUV>$qi$FJP3H|#Ou-S{GQ*E;~-2g2}S z>g}p34)xAn_4evEbpsjmn|V?1`Oa{Ude5H5xwH(8ZLh)UakCm%dAGtq?*ht^zDN9s z2HQDijJxU{kn1oj-;J+upiTCmH5=Q`SQn)I-IB6>?Oy9adFTthM=x<7efCk72krkL z->V1p8s5)W?66~dkU1QMSM!66?QxWY0QsoeI?Qu;1jN{{gQME0$59@2Y>yjw4(llS zIL7uD`#C5FM$hc!0h=AvF48ozx#Ko_bU@?U(uZJc_ImapV>@g=iNoJGFX6rV+G}3p zWsm*Wd9>c>-@Vpszp?yz+t0nqeqP+;ioI7ON-281-jK)aUa<^^EqejPgZ};?Z9nMP z#<|5mYG3=cW5p>ev+nH4vwpvyy0wqCb5v^vAKrc*McWVh{y}RdrA*g9TkO3W?e%&n zrP9oNX`K3yDQvW}jK)eNHlAdFq`!}9WsDj$YX}=CWcJb+Cz=TrYcU2Y>&J(Dk5b0< zliaV-?RF`ZN<;B1+4WD>Z&V4BUB`6YGRq~zz`i!TZlmuF>tzP*W_};q1M_=YFR`a( zs>_F1($N!qKg2z%{S3o!X#JBi7BP}LpA)3W=LBE)WDXT*zH>RC(bWhEt_`P;TijZU z@WVJQP`t1`Pjh_6;>48TgB8W+UvcsKif_CV(DvbD=WVvOBZMn?VqS9fZpd~=)9%5g zGd8b2VR7wl$h)^AlQLeysdU~yKkRa0yA?sF2Llw7WpWdF#nzt(W>gw3S|$@Mkku5f?H_^Abf$vP88P{<2De#YXh>mj{B zW7&ci&)d9vBg9u=Tc)1U;8+G}x}K(7Fi8fC9ahlpX$m<~wZA2dON=FqO-Bj{!Z`R# zns%!dNwp++^0dv}`yt=?AUx7_dR+UN+@q4c+z9rOF%r_EH577!UwF~s?rOxV&p7nD z3TX>m2XeOH_G(C@2TR8!TEX$EWPMvvsYq(|h_!aWXFl!_c$)JI7Hdt#$Id%Mfu`Bh zOcVsqpSRFj@a1oMJaO9MwWn;JJ8kpXmlPc@cFC}ym=_c*!A8wkjOS-8{_vZ9)*IoF zF$f-x@649bXAjc$eq|i5JNi6J+O>dRc*W)QOBR3hgMhOO7D{QRCL}uzMX4LP20lXm=IOJ}l0ftG*luR@WmUTTpSV6fur655S|g zwby=Tqb`%OODmPV(;)T#0j}N&`O1$192+J}lH*m0C19<7`C^~_r zm={cz1XC43!G)O#bKmpwrlD5j6zzLmLpHiFkE*IXsGrei2VILc`hB7-nJvQgHN~mp zk|5OFxF2ELFf%EbtqA6(CB>ZJ-g-p2A}L5gyRW%&C#2)Snd26&El^TWj1#!!9YG-n z$0jASRY|X>skJo|MZxT(WO`CEQxW7Gm@ElgS5Php@;Sl$ti`jZEo@=-yw=v-S&z8A z7V)*W1JnU9{GjWd-J^rveVF|meMh|d>Z`k^kR%33PAyBqL{U;}E9Pe;5`krz3jlTe zTngxVhBP0qN}3(TWJS{IXc}Ej$%T3cW~+j7PS6W9rJSJFR#;M?G)z|n%bUuu2B9WY zP|67`8>Y*W7cbddxfxRLYC1kl7NFS$6=`-liL7yWEz^TMf7G&H`$_hdgp@~7gzx)l zT)Jh!OhphxkaxlJq1{tVRU}blSluwxu0g&q(%69i`8<00dir^c=3~TqpZ*>UE8y$bB3`=W@Y*vD)v~1C zR&+g0E+=q-%l9Id@0mWvX^=*L6JtJ)U4C)61L31UhzFrE_I{Nfq?1QsMIOZPa?}g( zAme(Nu^mQ}HBSB*@VuHRg4G>`j0Ecq#qlZ06N?tt?nJzGJEYUmw0oLcYl`*lh$ztX zJOHt$ddBxi-|fh$+L7A z1lns*N3m#+yS<|Vtad=?d@$EjRx&@n_jPn@B0KnKoA6kVTk8>^!t5! zy&m0emoN-bN~I?GN~J=zTIK51tE{iDr>Ev#6R1p1;abq@^f+;12}=kzHZ~|vR4Enn zC>61~vO>4#v3TMXla&(p@86@*Y!7Y1;IBDeM}3c^ltWn-53{)syP*f$T?T)%8o0xt zy2v*06Iwnhxno?hM=Oo98Yh4;Gc&{FG=y!!G>+_`t3r=EU_Tet7>@#kOQ-p#A5udXsVbDY;+`vjXCn@mlXxORJ)+36}f zJ9SFs60KH;sp=%_YpXc<64i+kn_FAV&K?I9vb9}fZhns1)+Sp!wGU;Z9>&+{aRb#) zBa3>Na-b98UX2$D1!iYwSy)&|Py8?pDVIu27V@dh!?G;O{JEUg1KYU z)OR-d&Kqy=xnKGMn``%3T|dDGSFX@#b(pa8^m-oUa*=xA^Xe2z1>Z|Q_j}aqHQs&a zEo!wLYPA}TMxC9V9onrH^?HqNr$eV>SS-);@O=;0b$H>0=O{>@&033&XY<$p#=nQ- z*fg6B!Z7587hd4K_uix5?+-QzICbVMUZ+V*NzR=;gCOMWxpNd;i(cO|iJ7HD2q+dy zwCme6x;`I&?pa#RZ8kQyn3$Yl`QB~LJ@E{kP8&B@Am=)4Z|@*2!TP=1codmCK1s9H zVR~v7DFo3&$PI_tj7I^Ihwb}O`hA>sh(~qhdDyWXO2$Yk`MyuNT;^YX`CoAR?eEj< z^;vIr@Vq|0=hNx5+1lD72>dv2lX*XkGldV-k49rMGc(I4U;7lc?O<7!(FpXm@S5v% zyItny76<~LC!V;-@BGg1@Y}!r+g!bRbs&%nLA$ZTSHJo`zOuOZ#5qdEB8v<2y#1pe z(rkCQaqSANZWkd0joLQ-=may>3U7S->p1x`^K-|zdE*1Nw>N3DJ7tGC9eU-blyy=8t|f zBuEP(xN+@j`q}q-eE+-OK?;%Hl|8g5TRYsleIx#Uch`cgt-#eQS5i6aQOe`w)At+O zVNT$~);+4R?iTpM;JzUo=+Gmd_Ndcoer0sU46FNZ5s7D6O&b%%_gN{iF&_h)Uv(3%~!ti6`IZF zq1ItfmyqP;ZnsOX-)Cxin&o>N+_;^&=m&*5G*_+gqEQJA0mm zg#{)jC%Jp~ZW=%`s)g818V62@nHiAycx3@+FF4rCx$(m)W7XwAE??xi=bmMIbCZw1 zSS1QWq?F|HIr{A;U;WxQ2>0WcZ5!X~v$efrsJH^xbxiiXNU*rH5UbDs{FcM0!4Kst zl~nY7pH{2M#KZ*oeD1OF$-eK?ZnY>Bi<~`s9@our_wLsq~J&L6qDp2%#ecW7*YIXJ}YOar~90oD= z)k=-N?E5~=W|OI@DGG(cff@cDwuE8C*7i28>vG|Vi-cjw%F48*uPrul~5)gQjMql7s(DemDAefm9 z@q9@+Z?tM}yj|kPx*gvW|8NJvVVx{T?H8kUg%EiCF5h|M4S+N`#gA+UP=sNWDi!uC z)#+nA|NI1&ZGk3EvLJCB8|%+GwSdC~lV!_+>e?uZsMqV9SXwkUm&!N*_=rmogf!|k zT-W8ynX|N7EjBkdhbCmkq-nJptgk!dixUX7P8h*XQ=&sdF-|Y|grT62)7)8giL~JE zx=ppDi9&&8Yu2_MDwPn&(G>Fv$AX?Om@Fv@xd#hjJ&cdfVb!sFwKeJRK~M(d825O zBFB+tK_sxG#*#V{Xl43}qA}MC>{A{Tu=dJ^F>d|$YvV9QDaAkir~i~c_=7(fOT|X} zJV=fDC=qpgt<_%RdepIH+v#?@>Fv1LvX|rQo~%@sx3AahnI#Fb<^j%(Frq}E3q8KK7Mvh`3M-&EV4UXe7IXOYI*(6^m zu+{1j>4?edB!1sxYGwu%h9ESJMjO|bG+J$h6a-O(W!VTR2&2#l@KTbq1xo2S6G!mC zbKb8U6c;eA&co(_5<+m{!Udju^2uGBe^{hHOm>b3ZTDg8KkU1;T8%f}cw^7I=tq%m z-w3{BVQaM-j_WX4ts>*}^HNIV{1=C0=5je4+on(~;yMmF*QHo0k|$>YxrJ2jYGI|=T3U>b#`1@YmUz^F+Ex0%-M5;Mafs*ZI|7{nbMuM$+D&Hx+KZUgx)e`?tA#`SPJy%0s!G*Xwnpw3wWnN&dI zF0Py7)~#FPPgVqB7%(|Gi2!^*05t7Rn^K`bqh2SMH%7?X_6Ax?x~)2Q{0{e5R_U}o zZr@p^TCL#wA=T<6Tbr9qR;LIm%Mg&a=KK`G7kt1I|k zAKP|VUS1wQ9w}H|zQfk~3gt?LcC!&*%9D+)7}zbe)~v6t40)~IyL&s0juS!qo zY@s5JANZ(H?b1~ByB%)axQ_1!1a74|wmr8%&n+Y}VVHKE1&C^CyU+#D8k|;z`T0ux;q~x`g{g z?`6xVf74+F)T3|*|1gWzI(2t%Hk)I|83aCw-QM#CZZu&SvT}cgPPdC~TZS!+*mW?N zHjI+N588A)AN8z{wk$6%Q>)b;&5kkp^7QmHQd-Q+%wSo@tMlONG2r}rj=2bMp1-qNt%rsr{hFp+3_5e8}#FjM0;4lb)2E^ zFng1EGPaIVihuG?{t18dM}PG2b4t@K4043+KbK@JhCdIi!-G5YKCJVn)oQV|wY6_P zfg!EbVK(x_i4zC`m5B)i(C_pYiQfsg*TqmF%nF)XTXP)QTr_N$K7J0{J zvQp&MomDE8l5qi#?`Br9lam>TrrU1dIPOq}jGv}Rw1-ir9_83Z_frT#y6>`B(|+7IGPB}6H7kJ>n__(NgO_p5D>-}+&h*gQefMf<5k6E zDdNtG!*lE%d~lK-b#&gA!`pH%RV|1+Fy<^e-nhX$fGb8~Yzj!mmsXLe?WQn7@JLWIl% z+57p-zg*5H3Il|S(9&ohf-uDMeWFN_sA;v(@81#3#3tHBEI}CyIL9jS<(U$ zMb8WI0(Gchv;z%%XU?3VTAiZX?U9c&2KKxNUYK4u%s`$5Bc#S*;#=F%RQ__pr`y59>QL?w!4WE~}y)r-|FI z|HnPHqgdMq85iu{Psf7Kzc$A&{p=j&f=uCVIOcLcWHm@~?OvCE@<;c$dB1z$nC!ke$sP`kfB2140l6zPV3M zMMROtc5+lIRdR(gm5C{e#R|pp1f|jhxqN|Qsew;DXSyW#)N@tVb|RvT zGeolH*;sJ#+H0@r?BtTuE4eT+xz%Uz+_Y$H4Y5Zj4EyHn5j-t~G~TrcgcPyCZ~SSg zwH`_oJ>1TNW%wI)DL#sXU5^9#4l77MOy3W)W)J%QLE5v2)vj662<=*rM}w?y+}Lr& z|4HgZksi~=@EGi9j5~Fbe>QocS~Yp2dc7XaW)rP7p68R#=XW)(V(DwobTF~2M-~Z_ z&kyR)@}MQ@>v3k$d(`riW|_~{A14rh7_v|lWi9CA;zNd{@c7xIS=ILxz7tmJ7k}{= z`P}C|N2}FBO3Cm3?(ed)VjS7>`8>}*|2&@O(dl#uf`DSNn5tTrmzOzn<_wvvapMMm_=kVU=Rf~>a=9FD zzx_5^Yv$+YdF{2=Xti3LJ9myJpL{ZH!*Lv5dg&$B*Vn05t33DIb6mJ^ft{TljvYIO zl#)+>`qP{^ae}F-DbAif%jL_L8Arj60th}VZO>sg;8Dl0*Za0@$E@$LM{z=l^MwMg z>!zxBX~p+@3t`yeF)5GBuknBosR}>o)3)t2h-#E#gUKyy+Y*ozi^bTd z&fN83Nr~gSrOA>Bf>NoNdJ_*=Yl$Ug%I&}&zEWCi zY}@9SfBBc0nVI4H-~T?BFJI>R_3OO;`s;lE``_oSx87oVdz-i4ew(MCewsp|K(E)s zbzS=Xe!3XRW$sF;G)GjqTuxobgCJmfdisGpA0MV1rQg+I0*nq*j*@z5;Plz^Gqu1}?N1Af6Xacnm*p`LY@6qk{sMTu5Hl{VjQibEk zW^i*kynY{HSx7YN8{3>adxkI!X*U~$N+Zx%wnIMWP^;I`2uh{WcwZ^4H7~vN60g1X z8rQF1r&g;mGc&_`@4d&xix>H|U;8y~+_;fyPOe|SPOH_T*=#aBJx!@pLMg>pzVa2$ zpFdBnR^#T)n|Pkb#KZ*sexH0k&o{pDjTEz!>jm}$>W3|lA~^0<_eg;G2t9&Lu#rO{ zUqEX`rBWdXqS)b2P-lze;>diyfMYoUmjh`0D51$!tN6Z;lu)iz2||xZS(NfFonD80 zvBXSulG^rmW;_xBnI@uh%9bj}R6p#bkAgc72=eooy2T?QXYA zv2>b#zsIrTbAY10Q!|uQYl@{Z#bVyb$vGE42r1 z<9#rc+!$JwHh1{>zK_<1EefNEVyTR43pO^l2UoXgD3wYGVQ!)d0-q?-xH&hD;a6y7 zI07LpT-QcvhytI!=MT-ZSSq8VkT6o@^CqfLNDIr7gkgYfJ84Q%OG-07AyQepIyH^g zZJFd2nRUzMawx6HVJjV3&G%vmM64$O> zBM1U!XJ>I;m#3b33MnPu`qsCYn3!OGex8Me1w)?VJhobEW@ct+Hk*9wTi+s|&+`kv z@Czn%^v)ez*X8)}Go$_V^o=9z%IhA^$<&`LM^PltL**5CrsliHdTV zvUNMH^kh!iL9OZa($-?t=RmF9sMpfZ*>QC`!#RtE5cs~gYg`b}@9&)&r`>8o4CrZq zmDU;H@9*kA+s5X`+E_L@fuq3lht{FdXzXjWOrDKJ4A1j;=bd*DLNGBg!86Z1!}aUe zdGg68dGpOT0l0npHnwfk?RL3(^=c|;)oLbb+O1o+n4X@dTCK9Vxyj|rm(9&ey&k!o zNx$hhPI^yYrBeCGwMBcCqjVnJtG%Q0;o6_g8-$7t!d}HLlhbG$``I53)AxR38mj>l z!{dA;cl<+)aqMs7SgFLoH#IfI;^HE{@6+venVOoS+wF4i-o0JMzj19OGDsqT?=^^| z&S5s=aBFdN_ewvEJM%$+w4b5zFj|+#G4D~^z+uLJ*fsko=XKE7_MGd>FTcE{wVoMm z2uuv{@KwRFDl1kC9>qy|)UgI1rF-~6ZNbsGu|KSJ`lDL2pX9NPEB}8ee7F9qg5?MR O0000=x}o)VD=23xZGidKsJj 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

&}XJ7y^uLKL|l(=^=~M7SI1ZoeQx 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

  • =%;dw+7Gj;ztgtqi9oTuJy)0mq^bk|_@7Fm)N^J8WXe`*qAEXnm7xZWn&;%&Uc zbEMaJ5t$}Ce-YVi6gOlXS>F}bsJsx0O6bQOvO_;c1)@6$h;S6Zw;vGUXxTwQ zgyR!#l+|P$L|A?HdO(B~{b<$a(RL03B0LZzL;xuNC4Facd?FrJgRs36DhKU)nyp5bxgh!5%byJ#?N0A~z`E|_n5zNdXf}_*;u225S z&tor!rOU)Lju8LD|t`H8LLZYTH>T0p!6JAaR`P=3aH}R92Pm z)z0wyQf%=!jo<%1L4<;>@9pcd8AfZA);KT03WGZR5H6g-Ac#91M5Hh?GkB8=cwvO! zn8d8VhMqi*b4}_~NAQA>G{1>zMyT2QP@8>(wWz~~@aHB7-}ET8eE}TD^HQd7H4y?Jscic?lb6U>dk~85O}k5 z_(vWk%M3H~4JOlH`g{?Q6b< zxO1D-S)%#F#Lqv=)LY(+P!4Hhq=hUmUgc_r^FwT=sY#8NhHhsaFATtCn9K~ZPnCmG zI8Y&Enr)er_IhGFG7*kKv$x@ZMkkFF!^7&1RGlTZX>@YlRhJXPMD@G2Q`S}ezM{#g z1Z1?G(LPrP;?aLgA-AP27A4Duv-@Wv93Pv}vV$@aR^gT4u=xf~MMZFaw}WsV)FYy| zJOb@m%p(usyA0_-qft>E?I4mNBFo6X{5j;zG5nLKFRe!o!{2KX-PhvOjU~@Ng zx?;iV!t#_EiJ4ts`qB4LKXzYnPtt+bm{gOenjr9y0tYW zu%EJne*a!|4R7=w-Uxtu0MdT9YRlqaCU) zL0FQ_PN{;LB0q8#pKNqyw8FN6^iIEK|8v=Gl_%boA-$xnqoy1nk7NckY36 zJo)64T)ldA+d*_U-TL)T+OMW?jFwGIOz^GW`mNl&d6P6vhq2yYF%w}4B9sSFrv&7E zgKp{~oo+G!KR`%{6dLC&A}rJJS_Pswa9X1Y{02dzM$*rV7-lI58tnoLr8U+Hgj8TP z()#$Gz^{9xgPh!NAy2#wb>tk%#VAE#-VH)z)F^ZhPZmOft*A7>YD}IDcL!?>>1GF^ z!0LicQV4_e$}CPILuEY(0)*#bqBeu8cgUamP3FJpT_`W)^tp)MmjhPTvTaL3r`S7je#U;=~CK9XiD4KmU0i zdgvkYJm>uR^F^dzmf@TuiXxnIBi?jFmSr@XO=f0hsMTsrPEPXFQ%?=QpCrj$h6LEo zMEFLfGp?fl_Pb*!5At5Id?^VgHw5(vtMkHaYC#48Xnv<9aQ)(K2$moLu7 z2A!vfpoS}T2O$gJk3}HS2;m4q1yN~}-Ac4k2!oKN+GNUXNw!>KB_>U<#-IWZL{7Z6 zjxi}yM?3~yi}rS*B+jEZ^x> z!$MeE$8g0N!;J`r@I8(^@eWpAeHDG<8eUi=u5p8{U10RIH%zkQ*v6c)rz*7@6JfPu zj8o>HK7E?Ezy0k+9=$_`@IO`0?X><2QaI&p!Jsk3IGnGcz-+tgP_hgAelb z(@*ol3omTT!UV;H8Is3+1x$q1p?rK7-Ir|mU{bJs2pYxera}*=$ggmmOtTKvodbj;?Bn?x;1b1DGeN7d#F)h$~GI@r8Nni;yQmi6193@kk40Wms- z{;HrguZij_96ecQi~79M_(iG`EA@*DpV*IPxT;JGa! z7@hojYVqlW@l#!f?z11i;IiQ&COA()!5wJWN~qk!C=7o^XF-|+nhLYVt5Zb?HEel&7OF# z9b+#h!fJ;-P>zfM{CeR?%LEu-5=64_N(0i9#G9IE<_MV+7~>A-y@}UK!SVYz)2o4@1mqbImg^# zO%N)Q)F34UszAbO0Y(=zK)PJ@)6N<9e8#jh3PPLPqJb7|B`F!8!si&Ue+O=yOJ9dmDNr<9|Znw+%^XIvG z_3DrvL`uoR!U8KRD_ps91>g7C+}z~OojVv~xOM9mgTa6_O}TO71`7)dSZld);|5Yn zZr{F*)|!ot4Q}7Q&F1DN>+9=8C1Uv4v12SQE*66}=II`1Xs^x~`(+~3x-iv_G7%p1 z@;#_Ei&%$vPy_%8mtw6!gkUmnWS;MFJa-uZsq#x3NVA1Cki$!k;ittQc(C0ZgUxbHamr7xgYZll|E z8txNCKaHi;va}{V;yVUU7La#KDZjeN7hjoS{brMmr4>3$cd&yF!Yd}fVf&6z{kz(Q zEL&%lds(Kud$H}^|5KmR;I5YX@USzcbI*Xtprt8oo=_wCqD6syLN!;`qZaBwXL63-J|^*bsQ>LAZy3( zAGU)PcN?2g;65^K$b{{Qnp}0Hv*Mq#SBr^^l*ixW@erY0n@Xf4bp;5Q%t>u3VrOx z3SxR5GEJr&owa2my@B1hhI2mB&#_^E>8;`&dJO3e$X|ULH+cjPP4mrfBM)li$KQ!w z{}|Dv!n*}|T6p07Kr=PtvveoLlf|YcEF>xPORJJ92Q8SG#BWTn@yat~YwJi=Xny1B zQgxmfWnhsb<$LYxawl+~5JeJ{z09$rlW(`OH^2GK{F8t3Px$6<{^sFlmFiVdZdR{K zg{iJ)v&j$s;1BXW-}60u$9H@OCr_T_%p}F#AVMh4 zAG?jsU0}sgCc*;kcbCgy>6iE+^6-X5#gkx$ZL?ZBHd1j(G?&NlBB0IoJfwnmgAEO;6DGX@i6TK3S zam@3*4&K1tAi~iJKWuCVGwE(+Z-4vSxqSIDk3IGnzwsNtLA%}N^y$+y8VzP%1`{nPjKbR6{e@B`QQgXNEn9v>wo>PSz21+ z-S2)kK@jk{&wY+KjyZewER9Bk*Is*#X0yqok3P!v>(_besi(G?l81eiTY)JD0TJE> zR(zf5j44!jtSZjDHU;e*HrHg`MLLUJ8iy9}!+_qcE;@E3fkW#M&r4Ayx(b67+wI}L{3YT~|2~cOF~Y+O9Bpa1h5 zJ9dm#tHqE0=#TP|k9>r=xj7zv^ie+bsZa5J-}im|=5PKcr%#{ekw+fkAN`|$#M06d z7cXAq2Y>Jf`Ot?x#4E47g6DZiDQPyF{JB5(=U87~C(AN^7}h`v5+U-RH3Eb!Fcx^-?Si!)6NjfEACRubP$sI+@`Nw~AvMZ}+!b`6P{df|xxreA&UJ}_5|}JO=LY9V z!myy)so|^q&7Ry|_!(o<(H_`^?h}Hf~dI`>=ci z)9oNmz8mYc(3h^`j=hcAm5YcQ*RWX;1EI43_tY1uO(>+A!(O?G$tCv8d#O+QD6bIS zv=PyHe-AA!d9#?fy#zJ}TY}*Ph=oL+Bjp+BN)Z*J!c*tZ|oMQ~^rA<~I+8;QaaXtgWr_OTY9>G#U+l@+W_iBS(&K>((uP@fUxQTOr(?9*weErvdJ%9Nx|7CvVSAK<8Uwsv8Eh{T4oH%iUpZ(dNC5~f$`lo-I z`|rP>jg1X{{^x(5Z~Vq@;+CLiv82n$A| zL{Ru4gg|);B{bbQM=M2CQw3&1mRJcP5Lph!V)KlZZkJ2bhxvFM^Ymw)qSx<_FMV6^ z3L%QL%B%rvCG5U?_hMOotNM4zMgiBe@;46WdRsW~uGnJF7$3LiUqZh0DpnVPT;kQs z$P3r7TH~xm36NK>BCcOA79Xu~K&#p0ZQt}woO$gv`cFPd;N0Ga@0~z|L*09amGbc6 z!<;&GYTHDco10^4X=(WP0QkAKaDAX~fg?8%3+Ut!_94}R*32Y% z3f=XL)l4DkMZARRcx=`!;IZLCx~4}j_K5nH%xQ9yk>v$3bZ4UnIN~_x&PGAleAw0T z6K@Oh;fl_fG^YXLBputArQGx*{?qCzzwxn;k?+WSB9Op+Ca0w=LXLRON}ph*^A~el z;fEo{1PDTcS~y%_w8=3##|cYqsz%sq6xC==yu6IfGoY}b4WsRx#oEGJ7(@lTpmPSC zAXP11?q?)sOsy5g4te3yCBE%F@8QIitMsp5r?<5~sBuT;tKlnkMb2OVxPMtc%hd%Tno_z92E?l_42S4~h=H}*@nVI1S ze&7d~o}T9Er=RBL&6^xQew@GYH~t1kjvV31C!b__d6^R@PVl|o`@J~lICSU`|Nh_q zd)nij5-~%6E zb90m5`mNvE1|=C~TOYmuaS-7+PHGfHSmoIm2N51bp}G_2{J@JIo>ar28EZgvOB3VD z61=pG(;913p%!HzH#F)sKx9}av05T;Xr#J?L*Se&B2|Pys_I^=^R_Mdp+;>r4DZ2O z%Ud3Qf?I2A*c!z6)?CuRm2+}y_bFaL@3x^N$+|3&##_YJ5?Fu6Fly?^-L`un( zD_3~&#TS{MpJ!@niZBdWUS8(n#f#j&eS4U3>F0j#=U7}^Bn(4t-@eUH{nSr!^5jWw z-@eU9KJt;_gnswC-_4~Kw67V9rz8LDronk zxHdz*N0-xOwv? zKlWokRuCeLoGB_b1_~AA^5x6J{1nC*u3fuEv)Sb4&6~XR(n|~m1B4Lt`+aWSyvcLV zJ-02Pd?h$lyFwI%W?%mDmxn9=bI&~oF#OHct5=6kw)ORO*4EaB_fyp~x?@x@jyDoS zcwo!aAHr+YY<;gw0@0ya8jrlGV2uInW*4{gWkg;u#}hc>BqQz$FadNy*#IFdI_Z&Y zY+_tQ5%(d6Y>8>2ad84^&cHfS98I7F%mSOhEdyR90@_Cq+!J_Ut;OBrIqeA|tPr!c zT8*`}wc*4v#ta>Hd%@1fC&~Hq=lRF~_#Y2JeE`os`z$ZL^wPEiJ=|?28%_2ydiEJ_ zXFO&E*yhV=UwV0k{wuE*sn946@-oTFWb=wV zweck1_uk87`M&veF~=W*e}1>WGO|(ss+iJ)CG2 z`}kNw`5kDqed7gyeJ@SG|4(WoL?(E?Rkz}B5mx?>s-4$fdzEwN9->~aGZ^&wqkQeD77Bq$bDVR8?KX{e8!?Cx^#)i= z8U>g%r*-5gG@A$~sCkpLqA7?i)@i~Zr`~i3Y3Ouv{4_>M$X3_MH#ezIPar1dNIHuo zy__CfU_vN%4@0qo0C+~=P1Hb+5T|(_^;VmHXLAT28YSD??Ybw3aMZ_94OSH(f|+OTuZ-_l65|g$Az5Dr*t2 ztDFz!|0tH78L9-=D2YtLCCtdH6cMT%+aZ+J!-(r37 zCYkS3j|VuQ1GFhrC;_Zes8S8!4nWOEs^akNO2#;;JXCWE+3#(G1>Gyd?ygLPI|1c( zWFj2V`BzglVYJTD#y1trdSa?4SAno$OmN+>ESok}$uXCfTGAK06T za4+`69ml2=?q09Ulb`%JANasGqqXLlXPzQ0a~1wkxvB+auY;AdAJU2}Su$YtP9L2blJyO;ut~k%LWL2g zw@#MDw6H^jY+Al*6#n&?;(Xx)o1sErC{i30UhOoA$*y0#3q*Ra5P@AmggXJ{#+e95 zW36G!`ZKOFjbe|6Ww@b=R88b+#~3~k!Iru*au^)vyc#VVHxN|!G=4w8U1g&n!UHiY zmSZDCLHd0D{A(zs__lBRHXeWC30{2udDco*^bg|N>2yYFfrCEBJKhqn3-r3ID=7+nzalzGW2W@+vzd59aEdB z)2;_>T7wOI8u#B%GgQPI9lXouQE5y_u}iE`I2dabyGI8&0R`Wc9~3Z^(keCTupOO` zhmS1qrbqH!RVuIA2}aeW>KbB*+})&U72c&d2YA~sCzZ-kkfW&*eLBVvSSFsc#%{wS zVYdWq^dSEK>+VdSB&)6i|GW2Xxo1{pZQWJf)f><>bVGxLEo>y&Ryd@wBODX5{b3>| zCStzKX#Sd+`3olIgYA*=$i}u1#vl+NB(Zci0(xKQu03nX%JuDcKD>NcFS9bUs%VfI z({QL>pGK@lRey~*=&-@WTGXsrXh|`W0WRP z(MO|Dsi1;@cGgAS%iy;>LZv8Vb4;C>$E`N#tnVPgHfE)SA$+9UA(Vn*MxZH=`Zjn% z5lrMMpFTlmyN127g5`7&QZfsaP!xn@ODT>CxQXC$7&4R2A(hsPwWEk;zoSQwvb?;E z=Xt&Fb@uF8&R=+nd@k2#2O%QfT^9%@CZ{-k>I55WtK7NwS$DLABS+@2+fC}t7E@Cd zc6J)%b6M7_>u8#eVOm_gc#hSj`z)=jq3JrIQcP4PnVXvli)wK_s-Oixy*)pj^}`Vl6}MQ+`=PQB%D z?%d<7E!}5rW3$_6`XRr3p-9TqsBUZ_rKC`t;E8kR@I43D4={DfwX2^}o|$K=T z;dvhC&!0yKL9tk*P$=|H-yFxmah&K~f)JZg4C@yESrG%-un z8{9n4^V`H-hQsd0RJa;}@MAr;L;q%rTuhLd2 ze(;0;!qtyI;{NgmZl}&$Z@taM-~ATPKl3<^md}|J3%vi~&*^j=EZxF(ZBpq1hUW86 z|M(JxsRh3O@4wHlFTKlOz4#JefBp~nou?n8(X{#f=U-rBql%TX=+w7)@gIK7`3p~R z>f~{x-{$seoB#TQ|HiFPuduRO#dg}f`s!<(ee!7*j?bf%;>i3_?Aiuzy!A_JTN@lb z@hIQ>?!UwHT<+bwNyiOwTRWUQ{|(MPa*PvmM|rTcgzee<&;R~E2*TYx(jZ_t2oXkE zTzAW2KS?}u^#O^A*=M(`KQz$b{wz6zCF=@Rh(r$5wO7s_V01`b$>-yA3Q@LQulKjn z1)_lFT8HeB46fr)|M)UHet?|U}ud8J^8ZFIx5n4GMzc>g|+oITHXzxO8;D;1{8d2}i9goy}!3>6S4 z$&tAem`1>@Yaj9Jn~Pkz@)4?d`_G^Ngf&eIUtGZt(_FfInW;*N?_Rjb|9$bValC-Jxdop6+Hx;;b&+>Iyv85>!S7?}Ivv{{ z3Rn(<2nR!oCQtI>zzH!O9G_&xCuOleCAm5DgJkj=y>F?OtV`3hUT00#H7Lh4&AyYo zVRDii?`E?}I-Tw@V76^XYx3^;y)6Xp^&5~c&{QGSNkaK8pwg*xshCNdhIv74yh)9y@iE z@WyAfst+9>}UVR-?hvl^@Ta6F+o6QG=zDvutdG()O!cIq|${zreuM5%;^Vr6BSPN&1Ke)SI5uU?_k zY2*1J`Fw`2J^Qjg-mXf_+HuPsx1tHzaI8Eow|SX;hNvu&dr zI)0qlDFIlHf(Ug@@54)k6hnc;L0GX@m#+0=?L#6S#&VLKP)W6?uB4nK{t}n<{6dMk zJkRUJ0o&Qx>CHmTX0vx?AYQ+BT#wtWHkDL53Pj+#QS2v8Ltk*n+@g>yv9to|q?>Ef9n&Y+boZvzet_PGd}!*pW85 z35)I94jtP^Nr~6-qfn=!i-UA$zon(6zQmzP>?jTrK8X0}rfIUeyo9dntgI~erq;W+ zcRjnkK+7t`&~;qb!?G-bAYk3Ldl5ZM($5v5u$1E;Qn2f6L%yuP2=XxTNt`Vr_r`4j<0!@ozW?80n zXo%4DTuj64^Ww)Nd9tzYi=Ond)0$C;o*{CQoiFY%gLRFPlXQ%FzSoPd6>rSr1CLs* z)|*+<>2yyAh>(z$fLuC?vEK`^sR^W!MKdjQU(ohEY}ckC1lwy(d>`_fgYrF^^?+0u zkT!K1H4n#ESSrL`-=J+uYK@ze=Uoil$Mjt4*O$N24l zp!D4(l5N}Ex^=6sGsGuU!)y}|K0_hGq?63Dtll4JXg$Zc|N=uQ?=xlE{NEsSS4<7L5&wt4a-~2X>jb%Ri z-}>hBRLUi4wH@qwjYcQr`1}lQCuE{h1QqbpS6}AcUta2k&Ph(8 zC`G&7>Ah=miD6mR07R&E1F;fj7RW6IdMZy>a3(1E+-r< zCmtLOeHWs%Z5z+?_5}$Q0zHmSBD!hI*v&_wj5NOT(M7a`bUGeJ5aPDC(WFUsW)=~& z*jQdAH>oi5CR;lW2ub#6iTu~+5Mh9*Z$Z&w?!;NV2lue+S=`Ap7^z9n6{a~y*>g~C zhvxQX?_NuMTs!PKGQi1`C%Ja*+Q{!Y79t!36i9TDSq1U#BSRH0_&o zO3#qVH}I5Cb8Q3LvS`&iy-pGDgZ6ajgx_uKjByxHPDs%k6_aJVo46>`>)-yL|BaPO z5hNUUp67Ar#-{{fh}Jz0R;X@ga(koQ&)zuqt6F1^s-jajL5&bihuIs(4 z2K&*q2!XCCl+&WU5n@>xjHwEmP)M~EMPgPNTHPb@FsRem5tJ%9goFpxZKm^r(xgVq z_NlH1Y}OrwY2i8{ozNs*Dp6mr()#2E%GAiTbL1v`bT3*8dW|-ckT5!@N7syQs9hB$ zv>(wilv2HS9A+C$*Y<}92R+Ym10F=I`+z)6!|p^e6O#~O+yQ)lS5CXr?h7F8dT!5` z&~CT8&wB_FUCpd*ZPBdnvP$s_CUy3FFUqDVOtjuE*Us z0;<1wi@6t`L!XwUudgFL7hk1G&MZS%Qw4ub>PM$*3=zeal_3->7BdSLhQEa@RPbGBuC1Y48dS(G3fxAm! z>~m2mi4MgBOl%uC07TgHB9DLwV>DtEba!ANFB}2)4b(L*&G5K%#z{~x{ynVDziqaO z8^wWU4MlWFkxP*+r%_H5&y!@P^5Cvv7$Ko=l9`=BSshF%m=qbdx0?7tNK2#%rDT2< zQh9@FLuaaN(Fh%cCTXm$a$AMWEX+i^(i0^#nUNe_jN z(k=9C2GP!0?tdvG7)#9=9C6;^#48i6{S7>i;ktyVH z+BI^GMV#p=>QX~{>?HQ5mtcJdO;4eOM~ENiA?}?@4eJ!~)#kqUPueE#81Ww*6qM_g z4PkZ$>l#-UW1VB=46;6Pu&xn0M{hd(dgh>5hr8@|34Z;BBJ6PG{NX^1tT13~Igl>qi1FT#~&H$?e zftDxCpT&1q@VzyPN6M_OKcMdV1ddC4Ws%NmNVv7e%tRC4o4{8(nipW6I7!Env_AR> z&2FLs73KLJuX^v;yU+IBR7<^?G(H9#gyG_Ar}2!kUztMnjY{$JgONG<>Jt0Q*)#ep zhS!yNKKab3y5e8oNQ&B9*F)MyAbxYUVT^6m{Oq_j`^ohrCYujk46e^R6l3{uwUMR3TZS2s)*9|-?MY|Kyal!Ezs&f(rnVFgC z&5nKFATeu-)2C0XzALFJ>;)tU|g4wl7rC9lPPUfaaWl;4PLx^%+B*v55TN~IDPFJ9!$H{WD+b#x6+r zDyyTUPGC;p+6uR^jgd*=wwmO17sm++L<&8f#cwrGo{JK3kk9D;_gyJ*#NIuIlu_2+ z7hZUQ_uhMtMx)X5TMXJpoIQJ14Kq{{l-m=aAQ7Z(SXoS#_UcLmJJ@rKxQ`rN>n3zT zjI1lEb5E~s?ucIFK7gE2b$#V+)16_)>YNNXF~&A=BblF{=kdoMr&_I2uh;vQ9lZ-` zB$s2uQnAE=`{Nu3?Ebs=$gZ zXbUL_d6aHyBtp+tHbcb^kY4|i6|lClGev^9*R9m)D_DC zdZTqxPI81ju=o47$TrDmE0s#G0}Xc2B&MD8CJ#Ozcb?>o`LJ~jD;rkVU=Y7%vq`(% z?!_h;_N|8_A&kKu{w+Z{aX3&;(}y4-U7bfFA>jcU>sJvXJfv+#L4--$#JVppFCQvI z(Jf81)Ul2-|3yhCB>JIP}9O zA;JTE_&C(QQjrmpY|lYJxnZ3m>DnKkv`y@L5@*hwQA1AzWWBy65u4-Y2fh@A(|M_Yu0Iq7eN$huu7UK@j%JVmXm5qJ3MRoUUFZbPmEuj#Baa z$OC_aFpPW`eh*d*QQez%L01Pqh;jk;yzMYt=MmrFKz0`UfSloOBAJm8VZ21>p}CsY zV`yTEbLfaTP?i)N|F_S3dx*M{Wyw0@&06vWV;6sN1c4~hUhf?r2JYhk5aA)^q*6MD zE@*dr3`5fCD6Eu@sSCmoG)>TIMa#sTrC~cEx-QW*f$fCkvO2CCpy>uGP;{J-Vj;S` z;|C!@pwM(3!_Xp6anF_kwi9BR8lLB)kSHb4q{MOQ>J{CG(WIc!axpCpU1~UPl)5a& zyFw+%q@#6z;4AzO;0JrZ!9#t|xU7re^g6~^5UsmTGz_B`A;O?PtYK1+fw4#MxZhx12Q52no$;nC z8I3O1J^2oYg7oB&vTk(2UZ~LnK!jl!B6W?w{PVNSs{HXc=Xvp^TfFeXF#_AA zGMPj89{=mFud?vy41e~WId0zAqBK=NdNvQLE^|{U);8NrPiJvE9(NWyTsS+y%4&ln zb47M)Eo$2yCr=ewueLe4P~^e=9cE{9{QA=>Cl*RH8y%ExQp)HoE;abk%Xj&UKYxrP z1&y`~Qx%KLSJo*{XUU~>mex8f9LeAWaOwReZm-(>=l}3H+tnt1pjh9uDVNhM9Lw{` zl@)&UuZ#Sr|M(<18PI42+_<;HW2YvVsAOo@J9u8e&ASa2PL`OP$*@svVh0+tCCTl@ zHk&JTUU_E)8QWeS9I%WphYfpv&!8Re+=oGD$+F%@3_uA3p__z4A`OdTd5T=V2uhL4 zWXR`pNG;058ir9?r&yrg?O;7eia19G& z%ueU9+W{A!n&HB^DZcxi1&&Nu{NlrPDwA0>sc?KnxtwL;SdpVg3e3&s5K{8^V->Dm ztCGrRa2huGi5!3Ytz+b}Iwy`7nVQV96NQN;zWkiCkptE&+?kXtvfY}pcJ55n6SJoQ^S-^Kf^Vc%1nJ$rV;^SsJn?4-eq^Oj{r z%MsTn2m;EvERSY0)Wd+!Ha4j_4*7{PPe1((xonQP`579GHWG#F+Xy2|!Gxc^`vH$X zdJ>^qq%{eeK^O#7H`cg(`AW12`;vY^u$wy&hM)?8Kh{e;$~GgNSh2HgNMM8goMl32 z_<@IIngoH55E3Dx4XLi{IIfG;jh+`nfl7tZx;*gEbpy}y(X>d8>&Cu<;W`_-Nf<_Q zlu9_n{HQF_L39rV0t~~%_g$pi^?K`joS%A+_%-xoP&Xe=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81fB;EEK~#9!?EPn~ZdrQYiTzgCd%y2{ za=58()xDK-byo*=tD9sun^6oJQk3*zBnyND!yfpXVSn&^G6%2(10GxUz<>>yV;k@o zhD?n}C2B~DWQ$F*6Fa90T~#;K%_pBX?XcGJhi9#|_qkQ1MjBEhYjhgbRrj7Z?7j9{ zPxwFo=l`f*|Mg!F#GkHh>ADVM4MkD%AAbJBPyds)i5mR*{r>x3=kxw`-t%wr9slM( z_V;dS2%t~|41quh3PL_FvLvCuwD3N^OFurXT~I)v|Nr;D*Zi6BFI14P4ucmAzApZ# zGtVi6_#)L`cSx^MXRo)v){s9}zCZn0oqgTI?;l?NnZJ*p64Lv_@NyWgm1+)fh6h;LK ztEo!Gs4x@;j0U9@Myt4gW$S5Lj}LM^N`cmLWmTc6j6x|z2mu$sxj@}Ie0pXc zj8S+GP3tgPp^c{NJX%9h7>t6&(y?qDMWLCD3`Q%O*3&c|rJyV|3h-X;odC{+OG@xRlJdI&1y*DIxZ!+;_T7A1W~{;c7_@Mph6-sA`WeRlP<25l5&p(%_a1dr=H zZ6}+f?L1{=SW_CU0-XyKg`z@Zv|>^k+EU?5O=Y3bimKEoqw(>%b>4F_bIgOMLk@;K znt)aE8D^zGTR9ZLgY%w6rnl+M|`m`@phu6orKrj8=5s;k2jFhJ{k- zpjfu@IYpr{aUGQgt>oX`z#<0^E^pN91 zW7Cc0tsfU#1vyPAstP_nguG$WM(sDRQsVm32GE0jkv9F=KRekLO6MmX2B#+-9`RVo z!uQ@n4PF?6Y|P}+(>i+QIh+Bze*H6o2UN-4Yp=XyiroR_d6hA|)^ z(@JGn9T`H9aHzD3Nu?*e?c=}c)SPaWe+cFPe2YvVbTGE!YZ^5 zsNk_iqoOx#J5TGOZUS`+U2<36W0mSRiyYyHA3)kjeGDDWBnD|4id7|Em~6s;N@2sm zN)KWuR0zZuWv>!E@)^P7)4_|oA%tW#qm{}BsSoA!Al}V+PDpWeI@t012cMe`TZmrC zpWMQ|{hNftHz5Sv{%hzbe+sqp>>x>yjh8oPvIe0y7X9(*H*$aeAIjGTKfTfF*Uu-9 zCpYy_N*wwdB!*7fV6~zR9nN`B8e3?L2JbxH2gYTA51y(FY^+&OFk5uEE>MguD-*HY zN`XV+oLE{PeEfS&2%gpj7PX^k19cmy+j#h5xa32S{KW@+D-BJ?2<1e22T6eg(r5LC_w0xBhoY2OS#KOV4T-P3PUuAbs=SWwY}1lhdS zfHeVA8UR`sXj=z`cr>E|qf(5T(tr=R_`Rc2)3y$WMI+Y#blGLAQW&}F*|H{qHqLnr zP%j;IhvX=w#EzYVSsiHGK-kSbbel#;a1hlqeg>!$Lakxx~9qB`_WL8Yw`&?n}pyQ z81})}C+{jAFL?{O-(&;^q2qAd50JL((FYzVq{E&({V<84|Etb<3Ztni!>F>PF)2!YV3jnJyjExudYri^Xf{d`yU)pigLpCNQoHRiz19qguJf z)(4igql*W?J5K=0LenA})p<$Wos$59h!i>J(Mn;h>`3PootLm`xpdjeJLltaq+SZ&pC-CW5eX0GuE|#pebn|<_8a(Or>Mol@TX@<^{c%7{=@>Z>s*|ih|YERgRC3v9^%UeDF28**-k?SD;)&;m@GR;Nu}s`OwQH_!w$N zn?F1p!RG_4lzvaBl%GaA0MR(4oJL+3GAvtY32`(5s~y%TR>zgVm*RU4 z5U4xP%EY1qn8vfHJ&RhtqADeMu3L{*UN&JX-#ID`+5}qXs9OoGIu|`eE1p29fYE{$ zc@(Y-be$x^1cO#VHm6p!UGz+q#TtbV9@oKi*2TOiu(Dz)3kmgf20#RAcAdwCfH9hs zGBjRtk!9`W^R=R|;)=S6P#LSSFvQzK{{VE_I4Zklm2!^&-jLx#9mI|1z$hPre`ye*oU0%m}~x5^O$2??)A?oul6U zEUGyrXbYQ9<9A*{DI@nbyNAB@Il^cgF8>gwG>k0xo1bGbzc1m!&Q(^gei%?3eCKyC ztLLzfe3X-0uhZTCHsR7IDb~)@`M$n2SUN z%&5MO5Dk-SC3!|^w3b7ptwtM#3Q~tKg(l!>T?~nwe6IIUl$xN#)1VZ}2*BWdh(Lhs zPfsAU9upJnWi8=Z0JN9)ES;luP}%}x6&BUQs@ZObq4f?i{_oA>4= z#?)d*b3I|`QSxSuuZ?F;j>o{`3^1oN?@1nNh+yTjGdxsb5VsEwXo4gI;5*0DPd~$7 z{i}bKrfE1mJ!NfejdSPDvAerVS(fbY@5{Xm4`2E&-{SYa3)LoSJC-1=cf`IGwDeQk2wfizON9ecyG2zAk5n*y+5XQEs!`EQ6g<_0)=Qp5O!EZh- zhUnxPdhhEn+D1R}VJ71hMka8u_kHj+X8jTNzV(|l-Y~iPF;3?V?aj|&%oUoqzl8A% z)a4a|^QZ=v%Z~ZNNwSV&TpF}i)XNrQ4caK`MTd8ii!PQfJLVi#2C>vytNaXu54f0E z`h@T)Fg5`K8f!FFC8(F{yyO{av&7fpp=|=*D#=aa=UAg~UXp90HNi`QjqeX^GM+wG zl#NwX)zwsNt!T$a}UDvU`zRs`w%74i> zzxhr6)Bp5;#m>$Szx>Pp8P{&Si_Hgr5c4P{R`C2QsLP*>YZ42GO6U6vN@t(}r3ktp zT>cBtHK_0Yzftu8tX#}%LIM~zo+hk4iaNOl-2$Z*!8z3QT{%cyjaoh+=nF9{1HE<` z``9Pp{#(qar_?h?v-JVoo$t}S{fFr3EzHwDL1)J-mJaWvW}srFys{c&l_aW4i-THr zbP*HH234tCOw(Ex#C2l9(F*Tnp}Y@$4Jo0SR-?71C?x-BJC`B;^ggW>#!58eI`KH6 zl@L^Eutw85*<;#B-68}<=i;I8J=mXZd#uYS4V@3vO~9s2_g>2v{~QJ(4N_=3^Lhg& z#`r_(hsu^5bVN;(1y=@~S2;Ax-eu@Dvd0-H9<4=z~0BaP@sK_?}aitxxu9 z@st!rK|#gg;UQoA;urblU;brYe)%O%PEPm-|KJ~R_wHRzPEJ`Y<``qMAwZL3|K#by z?Jp4y-atL}Db)6}F##v8hH@R&ugG1x z1!{gzLaU><=#FnO-+cjH2E5X=_g|+zxGw0=`ct?r(2g#m)}O%K|1xU*G2F(}crO{{ zqV@z8C<{$lTC|3`bvfi-HXa`|N{2xmOr1HuG5C&lFhHvwD)h!2EUtxj0W|m^Ij(a< z(58Q1@ZjR#dl#a&QD_uxJS3%+f}&D^;3SEcy&JRT97^;ddFuj&1MgI-W2D6&9Et1| z1k;BQE8P7i9-!wD%kN=B6(N1EQlTvtn&JUcI(eZ%4Q25D{*Z<aCYuyGYtt(}b-iHAFTzy3j~`993RCfW7A-nKU{;q`BJP)13rV4}A_0r>S;pj-1Y`sVE}?h5fyj|b zj|SmgkX#}f=_b}$3M<~CbN%|C344|Nxv*drg5bp}xoqn6HcfPeDrfTQp%00XLjN#T zZ_NaG5Vs_s6X9DOt%**AGI3w&d;0GS1M83uMaVZJRn|U;P1kt#`iB2R^hzs~iQ!WI z41eY`R4fKL=NOMi92^{Q|NcEf2%Map@W+4rWt?+3=V;qD7R*!(8T!MT7k=ki)Du5O zSiLBDTJ$g~bn@Nap^WVffHLT-KLTr)VRlbENQ(EA>hF8w3OxG5pbcUAuH5+i4!9-i z-j`6byXeIpzM0WG_{AY6`KQI(Zp+f%gjE$v+{nA(V<9DE@B%Wy@jd zxqhI9`_)PzFNIGJ|7aZ%s7O_*O5uoE8^mMuyQ<%SO2^YozX|)wala8`?$lfBXmR=w zroW^>Ko78X&mi7=4^H2QVoJUDwuW9J|5**cZr}k22dlsEFt9#DxD%?XqH~TLH*WBE z{?6a!i6@@m=FOYjxN#$T3gHO(0Xp2@d*n|Aj|wirxbZ&6n}qQ;;o9%Py|2OY2=(X> zq9W}y1P{dob?#-t_20wK?x0p5BZLsc(YPTVd>eK27IaJ0+N1Ja$JYsKj}o5#In?X{ z>aBl_eiGKQLQ0HHf>mF^PE`1cLHB|Ky zERWExi6BC}W>cXqyh^A~38p|@_%Q6eARcJ-5{zDgwabKR6XqX9X)E`$^CD{T0F=Q! z@fQg@FZCX{SiztFFpPGxy*RT*AwGu?&afDUugMJS!9f|Wa^fo|50jqp@V$vKkPqY_ zf6T8RqN5q=SGj=P1339ta;{>XO=Tk}5ldlVR46u9*-)P=&A>B|s5`(^kd~VXeGyS{w6qzv^`i(mL@BSgY_krYQCXC7dFZ(vZl_H_5(BrFb4k*CyuMW6qqYg5GpwfmeL5CZO@L}-|+z314602o5> zD4!1Hz$oRlQ0XEcI?geKh+g zII{{59jG&~PY9?#?K^@Ro-VnESQJ(&V6CRIVt8H5QzV%W866#0aB;h2dqq4&Wfg^n zLa9gz@gc@>gM@id>^p-*#w+&^S%tLH5^m{%S4kVPPuO$9n1v@ z(W_($`WpSft%bN~xz2Ldo#(b4ZLpVK$b`baZWFgw{ImD{h7ZBzQ?F5(4e(x)V{bI% zuXPVs4wmc8qN;R=$jN#Lpo8lD(;2Axq0N*RD+Wnt!oEJPAJ(28J`nHc8UC~%9ruNg z-#-j49`+JEF_< zCJ8F$If)bW-UA|ws0WpM;7p^=V8wE-qOwIko0iC54%w{fP^mM2mkj&hg3=}*Z2X6F zoU{-AwA|_8RniPYiovEmZ{*DT z&#ucEEdPD)s_*I>zEXuqJdYojYwP-!oDn=vAWF+rD zT{`N{u{JVH3K-c~fK&r^t&mtBc5M&iN@p#XJdi-9O=X_b*+tD8Xz(!l-}M_s#f{p> z)~dHIfu6JVu$3AhVZ#UV-l#Th$N{J@2&no89l?gY%j3V|=1T`Pf29KL2mVJ#U@;6g z;6ppM|LBK8!r|W~JpVm3&i=EKv5Ma#VWPZFM}sAV%#aV;u((N31288Vy+~lp2+{Cc zm3nCX`{SEY=Y06j-tYSzfx@C=_kFAU)n~5SA=T+Hebv3W4dO zqiLkzw=&j@3Pm|GSS5wQQK7LWn#lx_<(AAGa;Tg{Wr*#e=i_sQx_@NDjxrT1y%{|i zyh{Ev^j0?rg5wA9U0*;-IYT(JKz;J~Fi-fQc71WXPXoGjryk3^&x-UD*pb^qab0?qTRNyu6TKt{8gi zvl}e9@Yk-k$&D=h&+WYua# z7SKo^pSW71LNSiqtMi)$7gh}#&*o~u?y6;6n0ztG`)CE$1Ft-?#*aR;o9?f_f%opG zKlSHd6WM#8_xx!e(C?Ce<@bbtt-t;=xK{N(fA?>G0spP9bC~Cc_xq)K=tX}P-#hf$ zoH-cpvq=9|eg-?^%-<1n4imk3VPaB_gmp&u9_is9i&9Jq%emDO?}hFlvFg8iA^*eA z|A2q~BwO(B(zXeI>L1^8(J6nm)hEfYx3~kdlrkuzma*&#%>5I=P&4JugX}Eiw&Xn|{*uIOllw*=PA%f9r4Y zwXc1RU;DLR%ehm!*7V=W06bizN}r#8H>{sL{Jjs~bNYQ+lMn(w{^LK+kN^0O^Q*u5 zt9<1vU&+@RLdf2Ec)!EnXSKh<8VtYdhkodX_=R8i1wQ}z&+||I$v?^W6hau>tHVV# zymalu`*^=+=OgN4-sk(h_k89vpW&x}`ltD|U;8z_@P#k@iT9M&@!@-Vzwdp&*QB2p zUU-4O`8WS2pa1;l`KSN%pXT>I{7ikO8>#o~pZ9xS&N-fZ@=5;MU;AtMHFjb|#45ev z=;(+)`lCPM;NSqQb$+AVm|=T+8?7~Ks}nq$u3j=4PiR#~a4m~v!^+Bp)9Dmr;O?FK zxcC6lf~ExLCx7xMDT;#6fBy5dZJQUO>pGOyJpRO!)bkmu>+8&?QmyjHaC z@7}zQr{Mg~2H$`C9Ugt`DwQ>~onthrsOu$xKv9k;tdIfUe(S9a8#?Fm{j_b%=H@1! z_{1mp!$15(-hA`Td~lMdR9dsMy-h%~u{NRepz(ChQ4|##$2-@q6I(#?y*lTps*0cc zxu4@}U;A3V*JR1ly>4u7v$ir}JejbVPdPoAQcYISDo~aMMNxrwBvy0qBAk5V`gLhB zedv%n=U7=;;YWVtNBI2bKhL+n{p~aN6he@D+C9(a+61(vSxOtOu?1Euj!#ZmU0WCB zzp_AU&7JGlI6j@e@4-1dJmfF`<-g2Vzxq|a_O-9Q?|rVXZ{XU7$?6)T@rbVND6GMj z6^rRHx9{8|@xzASaqr$ee(I-winX;hIT+Di=2My6)N;AZ2O~YaYO==9{roSm|KJW+ zFF!)#9J7-t=g(i{`t=*sizypB+ia|_;V9W0!~gE@{TD3iE+4#P70a^BR(!EooH-cI zIgBm&_$NO}6&&T-I(Ws!oi%RUe!%Sbkgjdm+}h&T{_9`O*P5(AiWj~2G)?J<>rG~hI^P3Gc-potbzKueV7Xl8>&afx zdy3HtKl5`x&))rgUVh<8Zr#4isM2U{xPAK`^OJqP_3iJX;`=h=c@S1CmrE9l1=iYZ z1k!ap|H?=C$9VDnpYWZpf0HZEeSnb(yz=sMeC3b7O4~H7t*;S`;pkw>2R`@$ z|JVQX|B<7UIV#>$Qb_5#j=HY#-skU4#wR^vP(1zoORSF+k6e9<;5wdr@+zPI;^$dg z-)3WV!olGIZ@qPs$DeqT-JLCd=QsZ`cke$q0=;?IIbUHoj zI-R2!uTd`+1n=0}+oKIIKR)5R-})xE_m0`!T;r1Wgy1grX?U98Q3f<0IaD^9}a)_gPM-G_SwGShvhtPt&w?izTM0sI2DT@POIz z0khc*ZA$9poNMolxc1K5=wi(C&pgR;vEbxndL|4r#!%OF-n_HfjMLN8GpL_;j`eav z(=6#+%kA5@IXF6@(4N)xO>SJf#_{n!v-u1WBIrYbVa~E#E}2fJIgCkb8A9Ot^>_Hr zx7HY~Z4$aAo7-DxIv(7Az&meOTzltjn$~gki7N!HIX;6=H&Dg8$T=U zmk&4_bG=F=8GjeJ6jwc?D6*Z-{AP@n9>-g%Z~Yc$!tCcb(Z+*y=O9+ zoH+;f3~4TYNz*i(oSdAAy#W?C-r?{4AO7>)GOD%3xi)6l&?;Sd{_! zEIrWCXp}utvN#XN`Twu~$N!zKZ77P8wrQ}ozD4nAkRn&_)=&$pY&;Kqb$H!c|br%&pZRaS; zf)GQpuIsQx!RJ0(addQ)*J>EUN*k=p*7WrB^i1dnfyHvk|LO1j?+KB+gw_x|N*n6s z5~ZN7n={WTd8W4Q?|*2}hS%}hx4y<3-~KvfRY3?8Wg+iv8o92x`9`CWkPf`)+Sbbj z-5_U4&#a9@hW?~`O5gi?zx5jwRuh8cIfOvlb#YTG%Ce-c7ows2xiO3RjHd10!-Y#B zcJh{g(tZBH@BePxe@#?s7voTt64e3!w*i0UV2y$yQ<*>4Iyy(@?~Cl;RUqT{L(M|61Q&MI%8=c{``keIEZEt zgJgHe{`}B~KE%$>4uA14{zZju4fqAXK(sYlK;~`{nJ=$`PrZSS?2S($cg^9xYyw|4%hGD zr1jzZ1@VMG`?EjG%E}6V{jdLZE?l_qC*IS0+m^$766Qat?_=m4KmPHLv$3(k&;8ub zv0N^5#PNRL_weUE42TRr+k4NeufEFe?r#1}^`HIb8{y+uxA>{&b~!jWpzAtzc6Qzu zqSM2_`xDU0r2q4;`gs^}NEiEO^)t*l9^TOZef&I}1O5AOuYaER^l$qP+kg(6k-D`rrI6|L9-*K26i$x(?s9 zc<1om$-Dy}*grhsM?d*7{@4HW|0x^mtAFkb^}aXApDkVI&-(NJyIjYg^z-k+_5FKs zpM!o6Tl>H=hCgm`z`>pGGrvDZYlGGX=izt0ag$&D?a#BA&mnl)wjnr&cMj(rRx2)V zSWI!s>tFvIzxhws_}B-YiC<<04JVmr4#;78zowVIvrd*np;3D9PgLbUy zZ&U62&I5tqeQw-Q@jjJKLRld<+bA9TmxIUqu5TY1)JwAU(gLkM%t-Fz-lVNM%)R;^ z5~b302)){SPn0^zhAOqSGN5?M$7`mij{CO{+223pbT(zWnBlc%eS4eT-SZiQI669E zxm=*Np{hoVMk6MZ6{@O2E5&$Z*jTODShrL*5WJJ2EZ*f!lOW?nHuZybCWL4#V*(vy zc7;ysGu+<8dqYPURpq2PtyBKTdx8%!iT7tdC#`W>^DwAaDQyRa{^1sh{=b{1K^GIa za1Ogs8CHr|Kd6s5y!B1I4;XF06#T)Pr~LLe?yRbtFNZod8iqYXjXc=LMDz#j%h!(NReiRox5tLGD}h!4S@o2KA1gT8Vr_{r1!NuBCw_KiNa`uHWqD+vn-~R@$z4d*L7c-m+T)gr)Pdxh^o0|`~_3mx1-?+iO`}deHmk?kwT48Nt zgYB&ycDA=zU7Ju@!?-l8PBdHV6_?MCn3Nrzt3{(Ju6JRJ_#BdsRx&_79tVlePBF;amr*olVKSo#hSUmy~PUwCuI?|tu(&GmJD;N@p| z<=Lm`x{k$S!S#1^6vKM+j(ZW1nYSa1xkA|1b(BH!b>e!DYTLe zEDutnT!&JfY=XEkv^F@`#m|mj0EG`?MZHV33=>BS7ia+8Kq9|W$efB02rkKg>U>zV zwIun_Bz&oWy7qkGOYd@W+)x_0w|B^_?I>1PdGW;$@YvNSST2{`xqX+LH*a$P{(XU$ zZIL^N+NNQ8dV+Tyi^Z6#6n>cs(p$Z=v&Q-Dk}DS{Y^*3u(H{o6&Tu9KAwe9ZiXulIltp2qs$l?4oaPinzccO|QKFH2SH;eyG!ZIy5+?8LMTa+| zP@N+L2iBsL#ruw~Y3SOTwyp^Q?A*b;>mjxfWG2Gr-Z}5Z9ZLu;gDGDQ-&BQg$X(Y1Sz)`hfF zIyo#xDMA=n)ZB3B=~|C50d2~>$$Cv(sV?in$^lY?!dVIvf$40{7ryuvZtWj(ZhM!- ze1={f^W<|carx?#Os7+BT))okJGVJGJwb+VdZ|IQEv>cErt4dl^$hPfC=1JCA%(`3 z(TJ1j5fAp)xbbeu?)HQy9^K&b#Wk#XsG~8rN1v5U4MAhP@a&v-4BnALq+BVF&)XW? zw^7G??$;-XQ8H=5k|XKIE2TmE97YW*^(r0^?;Ks%idPFE(#wgFfr~YpfGt$WBY+7q z+2-@_Ecx6UQeqjRr>;E0=fCm|+NS2?Pi^qSFYK_nwn|xAu^bpA zYDsbTLj{-^4WxKpX%n0L>2Kgn{GLkveS2lHw3#X&G)md%b_3qE1n=S@($Tu~rYeM3 zy;Z%{BF3)aO#ai83&rxwbRr)_b2g|DAAkd;F{Z>6BYAyr&_T{^;-OYb^etTQc-Nls zl0JS`y6zr<@pQf~urc_&)k(#RFFwls&mXgQv`Zi4C4aY<%Wtaki$2n4Nl9X7){D4V-%s2 z2C}?YJaRP7szpa5rGgY5F$Pl_3RO^4D}chDn-q+S6iOMs@J`L|zkW*HbZo9o`1l82 zU{aNwoSg87U;aAYwS3~4Z9etVIX2fiWf)e72dO}tGFnwhawRY7(D5**erXBKT)$qS z7pHjg@kjXbx2`d-J6?SGRUUuh8SdP=&0BAMpQEEg+O~n<>70mA=LA^ECbN;6pQ`xV zI~VwwU-)@m`M}F8>ze7w5p~nhHZ}EZ&W(4j^VYlfxN&>R=Ej)ajf&L?tgl+O)<=vd zGVWMw6Q8Be%m*!WiT;4cJs`$TrmZIaQ?_M6qk@iJBIb)R^tM`I3mu2eIJC08#&5hI zN&IcR?*PgWFrXS)2V<~Bi83Wc(2Q2L<+GErb=!6P&NpuIFJC*REK4r#Z1I6-pQLG8 z2!VI++$Xq>k3Y4^r(U|i&gMGRsLJDFWh1IH^W`M*9iT8NL`a@Nsk58c^$D^Z024zS z`Fzb;+I7w=l$PHcgSAB*nivn&fbW%KTb0nL$gYg4;&PY++E`Q^)|gP15Mtuzo0!yD z6q>Ge_|TzDfvqMOTTzTEY>0_xSL2%{s#7@Mp+dl@3at$$SIQlot7*GN)-5RLBpg$S z7eslqlIv2r(I(lmOTYsDOg`! zi*$6yY`#D#&4)ksaX#@EKF;R)3Po99>KA$C96Q&RtWOl|tJPFxpB8 z7W0kZJ-Uk{oCk=R)&^r!2%IK<$-&d6hzAesYGn!D^AG-;-{V(*>kp}$mPap~<7a>5 z6BwoV{`H&Oxwpsh@evUlD54C&}x7xoh{jm z{!ttUVl)~HxEO*($xv>0H& zh|HtTaBa@SG79JMAx$QdHN5obqdfn@OU!2{?Cm{Z852lj3}rRKw2mg!c;8Z0C7o+o zE*2ad+>iYWlC$n!c$Al3eueR-dE**;d-rLUHAP`TDXcQI z-f?>|=idG?H{LzqV;_8sM=y==z5xuz_WM9-jfud*P~2ol-582T>tsxmllh79XeczxY)i?CtT%=Xd$x7tgV|CYZOJw3vW}5K*2!uJb5qPZ{4`X-r*6S`shcuI|a+S%- zD%E%uTNHiR=sZok#CKipf)uY7feSAWPpiIOqX)@<2y)+T+hT0V%4CJYdhR|r;N;{4 zV-%~a6NttF&WK_KK-*89ri&+vf{eVDS0U58%N1;^q30sr)$ z{A0fPjc?)!v~A0Bxy-CyF%DfaWz1)q6KmN&I$=IvV(cqC|IE3(FI1e%mkV}-f?EoI zQ$f&ZEqMdOLZHDXZdNqD1oKeI{A`U}AyI(Wkj6YItp(a_T?|obuCve zo#*`aCV%+HU!z_w`Qq2U$?0^;552G(55rc-{BZkz~j(ITtpsRgL7%4ONgeTw-N}i zjUk)O3}Nwb!twXs3&!2lq~yHoTD%j>YK)Q)#h9qd=n1~TbxYbhfFGkHbkn(prk>N* zwQPDLiMBC@A~>>cu^r851FNG0Fy+Ae%$2t}hkXwpnt1XN&*E|M+jvc8>q$|K>mEcmCiD zfaeFF-{nVMxxo7Bh|(HD=%T9{RGO70;BrXP&&-H7*`>tG0Y%*WUQnB0@W!B>k#SH# zWZP5OL8%DlhWL7<0GS5e8)H$%#zT_Gj{}rTYm}<87+2r8lMu7S5tHOk>y(@ZeAf=> z2+(y7=RC$}jJ6a-DHZEn{q@m1N!V7FB{s(3&Ug5jOt+mhXn8O2b#SQ~4_bTiD!~!7 zCiqA%4}Hi7V6>qq3%V|F@1Uk>3+9Uj)A<6lWjdR)x3|ai^oT$dgTPDQzH@Ov;U>=lRG-KSpRKWo0eqMMOHj!x)YCineWVuA?YQ zwAPur?Y-x_Z(ZZ}zPQQHedZ;$x2l{=sR$Q4FCK#Axyh+@E|BI3ZM)QRw@dkdz^Ss zywO_A3^}cEt%MmWZAhJlReI7`)4o903DV-F5r!kD_DF#vt z2@ygKxkl2%fkM~lFiGV6j|atYvF!1Hv{d z;}LgmDWu0e*dYDO9xGLBt;JKsuqe?mf?%uS zVZ0-RW%8FX{)^~CjQfI;7(7)^gNzMDV`Pw+ikry0>}kAnadG-$nQXwc5fhZG@zZ%PiWK*-5+2z==}mp#R>X(qwjiHp?_ z(6l*O?3{$IMk}TZPv;HBL)Uh!t*%fS!`}US%#M$#YzgBDT6y*k_Lwggh)Q??IEtd= zgRg#!7hil?q7tR3s)~T-_~@8F{KL<3@4+36Ed-@f8;q+FZE(!zGhBqxrRF5}QI;hk zD3(iso}0Sn;OLOAfA4MHy}id%S1)k&>P6O8D^@DaxpOO&g^r=4jzCB(3cHrpwWi$3#3l=0Pi=-VF1N9BxO?F9Py{PKFr534oGkCyU2O?S=r>C_ef8E}wqoJR7SM zX-RaQ@L!4|$B?e;qVh+N^(Ra^gY3cz%pp!ZT5;1GNrFkCO01a13b#sKYRJrv;QQRd zcj8G@L_}1IJ!4E6T*%>&eCL3-Fo22GfQOYyhpn{XN|DJ5M=8$Olfxk}BLO@PynIiH z+$bUZ37JsfNsEc=rWBZ9=ui+EJiYS9@aJs1W&#CzPnvLe*BTB_7L;X0yg1fHe!QKM`p7vT`(FU$Q zdY;*A&ZEp`nnrH^P`ByFnLjW>(}@?nUfl#e-C@F@l8tMLis zNJh~|q$@EkY=~~JC<;FFp~v~;(-YQKM-*it493t~;Z)=bzV`wkFrtJjv1;v7&LN1B zj{_nFi#Kt@rUTRF7&?U$GK4)HxX3KUN9sn@D2gG95cIsrvgk59Ppy1DbUGc8_i5K8 z#+4$DKZ->ri!o&`L}vUwZP>^RCFVEIwb@f>BL_mfjl{4n7S!bW#p9&|k&Mkyhb!e3 zNugYl?k?v*Mi;zw^O&Q#aBSv_DWg%v+S&#$y!0Vu zuIXHtL%+54O}2KnF*eEy#qVkAmN#DeZrseWZdEm*8jYFFW^`?XR&rlH$UJbl4~Maa zdRfc$M|inyTjt9Ji^UwPHQ#>ily`32Lw-Rppc!0W$L{4WX%;xhfc<}C>yL|txcX;Xf zr@3@#m&YI7PN6 z<$nfada|d{spcZrlPCo`*E<}}wQ?YpiUh}mzZdz?DV0RR+}SW7h6vh3x<~{OgsJQ^ zxZzcW9ThYOM>NYN%Vo{+e8&3PHsxrCKXJvqk5c7erwO4rsbzh1NWa$t97ix0p2EU!F&feX7M#>PnKoT2L& zddHk0q-e%_hM}p_8Ur!Uv$4pW4pG1bi;nDqAT9#$I*gT`5&Ph9O7O6|v(5eKNWy^7 zMX;-PRVik7v2!nnCa%H7E-7*z&`OcUTC6GhYO|7<-$!Cy*ESFoMKzY533?usim`m+ z_K1a#)Q>>QKIA)H4+e-kjU#KbMUMwphT9UHLxt4eK%|=V8os%a$_lDF@t<4IB=c3)+xi$yyD>G9;ee& zmWu_8`IOMKy#3bej7K9bT)0YMEi0oEt2C$cIi5h*Itp8|zPigNe(1;fz=uD|Xgs2{ zlCRbChSy&E9(V7)8|ywIZ=VV?WKtWbJb*KnJi&olf$|CmeOQ#Vd=YEYHVer&kQ_156O_`J(0d=R zQX`Vd)R3W9_RixZO^;Mi&E-Lx@lN0YPveckl7$ zTQ~UYf8~d{`o#GN>qq0|h5j#IHnt%fBZY168RnAN;|KD*!rWy^IOA#3zwOWc4M~f!Cm`kydFpLKFo$+`A+Av?tSuW=&CGdVaMB~vY_L3x^ zCUA6o%>Kb1P1~UrRHdaXO2$P=Srq7?I6gjQ|M-OUjZOBC3V!{ceSyFIH-Cclje)>M zWFsQ22QKwMB%1F4^+B4B!r)*kllrTr?>Eq5bP>Z61WR|F zc$5Ka)0hHdt%OoOpj-#E=$OPMbj(M~;eAKj%xRWOoOcm&Eu$-z=jsCBH9@ELO@VX0 z_Y{%dBA?UXx)!uFFeP?xTGOG%t29cb;5YSwsDb*5bf{@%@V26^OHPg+aOd`Ik>_k1 zR##VXtzvaNMvW&NO-~5{PUj0A>^)$%Sn&KyAL7$L_LIE)%8Q)a-b5>;C>NuF<$S?| zySJ(9Io4V^97@n9YYZl0du37Jf(NbW+>%0-oZsGN?@$hN-PBlZsN06FQ<$QpEDPGM zrER-R+$^kSbu?zRD%suGU}J5aYBXjvUg2cElGKPL6!WA_5CIqM(ILdW7(Jv`gK}ST8A|od`H_h!oDOPblec<_1| z74M_cMdwJB({wO|aa&N76-7Cb=Au}8Fvehu3D%}OM9?}@6g`%n@)#Yf`%yreM2;lE zvE+l8+P2c-={STE$LDtu-!a>ZYSK5(NYntj!mUMwZeP zY^`mxJlAmd{%w}^l6w#KIXs-Qx;n!72CZByw(1zB12LB+<`W{OkwPqmN$Ne3y_`Zx z6&cs5W`fG1&hddEO&!uoNTxWuPDo-TxY9`6?wur_ML9+lYb6w?W^Exiq(rK`+cg(Cey_dQ;t|W_ayswZm?)taFSe)S9d5(NdUTL z#>w#>qm^CmU;7qoJCC!scbE0`buc3e9cVfTokJB7>g)tUb*_`}CRV7Giq&@|IgYUw zZHpfEjSWNu&^jjRrfmA8qkv7+!e$9Y`6~nj) zk*iSBwH-(MdlW`-?%X*JkB%9QM@%La-U-1_X~p5;A*&l3eEKt=;)Um)7Fc&t)3c-m zz-X6E9P{8fIyzukFK}IepffUMt$2=QU30K^ALCmlBN6gmDm{YN%$Ey%2vn7X zp{bhOwrz&1r_(9R#e!}$Vmz8KDk_w=%x81(nq}89uWKfw3A?)&*gv?-@#&QLvZW{r zy4K|gBo}d&l7^*B7cm&!C)O!sx1_MP7uJviVF#>Vun}E569em9?r$Q0sLvyauqU}; zM9KoyXo6CTgFElQ)-LPY7nmR3B=v1nqZO9bD*Jcd+2yOx09IMw@-FX6q=iu(O?8ZrnxDukH zF+%T}c6@`=nOT^^NO>E54(c=nTCOCQo zO(iknfmT(XK$H$j^x{6ycAjcHVrzSwyLa#6T+O-j=Q)4=JX$N-T6!h+_wTc@wZ+f; zrT>UmUVZ`BIZ>i_0+UPO*HbTR=JPqrrlTmwY;NsRlogA`Tz=mOG+%C7HYO8{Hk>Y& z)QctTJ)o*8Uf(~&>58qb9lEYz-qevf-1p`?=jghQQCVhfFb~WY3sxs9Y}ksb8ViV^ z90w0LIIAy%?2*>x|iP}aE*E*~bR7;;}NK)D29__tL zVFIQouvIC=LM84s1dB=aktBi;dM;A>cOK)L9m&6~U3lBq;Jk@`P z8$gE8YeeN{rTAUF_?Hw*bqv*l(ll+yeA?iehRw|_yhmVDrKlHm_C$|A`3yh!=^x_R zr=P-m$D(PNPv@K*9?>it)>c>Poaf%&0Zr$@S}=yq?Q@i6CH0=zHc+<>r}G(TMWK!K zRj;g5JJ0N7ff}uGVRZ$qHM7MuGGR3)Hj8ylgE5B5WFn#(r>AJGn2g6VyJR+_tWL0| zU{uJQ3R9FE&t{CvijB1uLMU0(9rHyU3wJpt&2V;-#UZJ&=wiU9>WzL%#1ny2MYuOt ziQ_r5XIMiKp6%l@iM@l8W*(f6O&=y&LW#TEu4XYmB51?i>)&Df{AJd6E^+KSn%NzK z_Z;uvpt6dh8gcvDYb>XCS>3#V_nyhdIlNw_sTWvE9^Cpqqp`&Gr-!$gEgD9nf~F0W zg=Thqm!dG79^FUL(bhA%x}_Kuw5^vJ5U9MtB>Xh_Af-Ht5II6fL24NPCo3+Vvz51m zBoGG5M@mR!@}8}{CLsrvAApW+msy-G#O4{LqdZk&1oSiH#No$kw^uy4cfifthm2R( z+1WjhF_we=zzIB(v8cq&R*grUAV`H5V6itBH zVo6aHOvYm_UV4O!m#%Vrv>&fi*u{0%VHOL@qQEFk>x2%nG9F6-&?=T)OWjCASP{cH zs}0V3tS#7FTSXxWuvQvt0@bL%d&l14K26s$Z#U_*W>k$)K-)DmT}jil1P}GH#YL)n z?#T~AGk3nFYZ_^tH3n_HaNZb7uoCxz#VdtM6O?pcRZl;5*o-cPq?!-~uhJ0;iS-&c zi&B;VSQF_Von!x`Sr&Bl9KV=SYRzK*8s4|e58lR_ zf~Gbs!c8WX#@cnPHMsha0*|W$I*6rirZ*|7g8Jk-r8U&^eGGxFF0c_0RZ&MY82*(i^PsY6T%1i9-ZgX&Oz;rt2b_XoE+R@*DTTP% zV!?DVV}wVyn)z~p)|ydS#*orsjm27v(VC6b6^>4iBY#OtG!YEJz;e-W|G_Dr9V`=}ri&{m@nbjKKx(KIpi zk_M>Q3!!6H8k5l?3$yhxqd;%Mx=lz_>e}m>yl3Zdi27WIPZNAps&vQe&#`J!(o3(4 z2go(Ccqi14p4VmiFv|DE)A+5puEx0zV@Hx~n^eak(!x#7IYJ~tTB{h1OSaXRQCZ;H zhO#Ibt*oH5K$K5E`!tU~ah0xVIX#_o|Na3-M^ois>6qM$4lO;gj=9V?>=n`>)%^jy;|m@Q?WESox#N)6-5nBCoVP!jS= z-}<2K*N4oHGS3X{?s%j_ zFVQ#>$u5MRVDsynAz~j% zYT%Mw!9+{1qF3qzSJAH>yyuKoQeXTt@%s{ikPtAyl}9gfFqO5MH)+(DqHY?Vf8hn5 zeePLGZJ5qaI5<4!_;kVk{sFh%y~%@psZrdzb(`%Q8(e<$GLw}xe6Z~9o?|o_b8vLb z#^xr^Jo_T=y!{%-#|Ig$@pziH!>C4-L5!yDTAJudCZiFhwakKJ8bdqp9U(Sq9i2>> zFP3PfC`-%s`YO_Q?oa``*alqMg5_cvMdpO6;(cIyb6pNb)cTR<*dL6nGiD6dmMCq6 zy*=#dj%%56O-MRtHll%pP^!1P-{5rrrXUR7qtMuD%+{r+SlfOKQ%(RyyPR=&{~h*ky^d?+aKhNE6N2K( z^FPRB{TwL8>|~!iZ+)2}k^{9?tZqHV=B4NGuI0_I{~qEQn=9N#-FZhP})d%Wedht#dtizcQT{U``BL|y!5_X z8z-(xXuCOHV|8tXx88n}WxZsjswk|0Jg)6%qkNCl%cR-q!nrM0S4ZSI^8@lGLqNnN zO)x1^cU>1pK1fKcP`T$kI8UckEC|Pbe;4I*&eSn75iij+bdT?b#BlYI*CXM9Q3hj5 z%F!z8yH{c*ct|x5>|A=5ci;Rn53YYT6U(&Hm}$lX zoV)rwyN|sDO5_;PigL2Xcy*U+&1X5j|NR((Sk6E866YR$38ihUaB8aYCX>zccnmkc z_qm8fXo7c)S9jUI^bF-_4V1!GtK4|wOSonx9efH_w>0Zpm&H4(B6j(el+}vR31Y*P zd~Wor$pgluy6alHrjEH;l_i6QRq&JxCGR{GwDu}cmWuJXqV*1sVm6&~e0;>SFTB9c z_ByzZqoX4h%bEvw?(y~;-{aPuI~*P#F`G?k+YVcl)Jw7Y5BBbJ|K2@TCKG<(BOhja zYaQnmtE+1~@#M4IzkiFSUgXx|^k7}*X=W5rvt*Prej~=$hP*_XX z!qZPZ%kj}ZuI*SGjoFxtnb!^T#Ud7x6`c!oA<%X*$Nafxu2PK(T+@=IcKZJBge3N% zeF(DV&2olo+Nje-KAaZWqsSxWRs#?$#Hm5R+KASERJU= zEwSWivdYGVr$A{AAKd1~_rJn;vci>TKEilqlZ#J$gww;@;FgRx&ar**S^A| z@c5OheBhN=aLYq3otyC1J2$y;>o&7_4MAZnu~}0I)!sWMqY=+M^+<+igZFf;gj>cG zm?Cl7Ob+`)h;)DFX`2O2Q;W7(S&G12&I@~OW#xR%L3?%^a+*ftF~oLJff`+wwNG(W zZbJ7VOT(n0@+ig8-n$&X`!(j}80F?X{?d<9lw+#3^VGBZ5&QRy*S687U@<$!2hZx- zHj|BAria(1UZEYMl}$`h5dz%1^*zG;Hg#ioaHC-J;tL$^-$rRmRg75Qegsog_^#vD zTVKP?-=$HCee0R5eTwmTjkV2-94`;hroK_x~AzcT2ok! zwFTC;1O=@VS)pn);?<9Qgv*!D@$}_On9sbx?Yjs3&S$^OKmN_nGCf_UCTIz}LZEY= zot+KNZA&kDGR)pNeAl2b*fIhZvF4`YjEtf!>4WxRd?r8Nf+ zZliFlu5YutevStLG?5;z$?@d&?qv?^2L#`8dT@iidpA(DjH{BOs2HtmppeA8u!_~q zUAeAq!NI+EVq?B^X_>-eiwSF+7f~o4+_}bRG-7pai;bN}*uOc67BO~!F|_CcIQU4x zPdIuAX=HAhrE?yhdy)Fxb*i>o84MFbfKFHdV(H?Dm=Kdk-?6?i;(Rxjkf5*>h2_fC zE3B`rp@C+(;M(`!bh)s=Ojk=G}@_4b== z@0{n-~j=&M~P9eAne?V2dht z=Jm~VBGu_d9yS6QR3oXW*dpc+Q8hodMkm^n_6DOzJ&7>(*7b32wq7bq<0N^*SV=~B zG?FZOlGyC+RV9a-k&>^H zZd8x5rTHOQU^*5QhqEzK-q*HEy!VvFDpfJU1D77X!p7Dn))=&RxaFLqy*r$o9`ej{ zFY?2m`cV!K9`N1oeTxul7Y7G>OlNaO<1v$QCzWhlfDarU9f zPWEqdy7w0NI%+tnLBo5WIVGCQcs!;shNjTewP?qVSGTd%n5L~+obFQ@PuDe6<5jBh zCX3^nqNy7#4N5|Zwyni8lq0l_7OP8EHMO$3Tq)PuLU2(@-3qBtCl&9Z=vo3d;=xFX zWF!(Q)lu07S1&+oHn%rf-&oJ;BW>MK6(vf0=BHDxUz_pZfy~@fNF{nQUSYnhMVPs& z7>yKFwGwA@)GQZsE}TEd!QLKCQxDp1dyv362VI~nORDjzjGtQyE4L_$TntRmb7CD_ zx$+p+8p^`S9E-TqLV&G}Res@TewbT#9`jcZ!kW+_!gq|sf%?T`yy z+E@yuv1JvlKwxwGGHgfnLIS5J2VDE!7cpUhvX-DasHam0R`eqP0wHv?u0eYZMx$C!pp(V- z^i4F*<8h=((ZXt#wqA+Rd#&FzGQn#f3#(DZBzGvr+J_Dls-ZbNAZ%_@7>iL_z=5U) z=NOlkQDr%~xzEY;RK(qaz~4<%voe{Wv=!lOFP~pp#oFqG@wlX_j96#aF`G|u!DEvY zDM*u+)--J!CpCFiS0)&(S=4o&kYufmA){uoSg^UV!MXDnKpDzXffA@Z&dw!-z(-$w zj$itZ|090&AN>~h_YPPYRs5x&{sdRAo)g-eC(rXB_V1(-aY+H)7#+i;L2fu;dx+{l zIwnyBBNeS(RLBHuX*DKQ5QF3tN|~s9-pK}2DofO4rMEb0OGlZR6oR1?5AIy2o*i-N z%JZ0F#L0u(bf>o%kH?W_pcqfKQChKBoT8K?U}@_)qsbO4YrD*k*D0$)rWSP_zMXP( z`x{ITZ?JXoS=Kf$GFjchUwn}VH@-sfZT@V6Oj<3hpccLIhs2g;Q9@ZV**K2^mWxxy ztE<>@MB6N=CL648U1a~J#pt+KQ@X6JAX5lsL&OZa7-s3b;F;|iHY*A0E=wwbUp^<0#@Bl@>!9O{{2}hS_{dsi7=JG)89@ZDkAD zPq8=t+__zLch6yLN$_>wz8rukn^aYXpZN4gxOicc*WS3sqZfC1^_3?ntd3NVn3@M2 zwKZa2c`*3+khHZJE3_45ViXg@*JOy&UiS%w%KhO3k5MR}-I^3cTC{RKt2DAm)2w8f zfax;bVL0n7xyFM#Z*zR_yR2_+v%Y(Uo%4@zc>9~QjTG04(F)aMli&jzo4c&O`ZJ(4 zwirtf#$+8+OfWV|ZMshSdVNPXzt6pE`-CeWVSW25=evkI}T}G32%JCW@c(!*QVPo^BC1ESZ5In2v+n90;ZvIe|d3NxPRvK-p zxHeJG1(kXII`hkPpI4;OS_3(vFo@&RU`-!q^@Y@(Xe@f9u(f0M;68eLJICBEc-pRG z%@$l*UFEIGgxO+>H5%e{C>3Pts!@uK(TGc%Ym}o^iuE0~Ha5@-4)^b4fTM#0l!vvo z4Zw4Hd?YhAkX~yIsKP)n%$G~njA2|Bv`r(DN=DPQ9d#ozJC9#|oYjpr2$n)8N!7S* zl^BntH}=X4SNXsTj|)f4d3@;dgsC(?P#6~Uoq{2Sr}02!T2hEgCPFnLjj0QP5Zb6( zL7YjVvW~5NWYw}+rJ_ibzceYH>?aGQ0!kWsp_LYL)uA4BK==Y z)+op8G{;A=4w1r5=^Zv{T_Tr9l8UG0SaT86eSyz2^Y4v z@pgn>S)nWntmMlSR-si(*Ui~G*kgTdjm?cs7K<6}av?=r6Igi1sFa*ywwO~@G7i}k zmPK3Bwq0&?+SuHbxq}!AJ*50YVmS=e%2R+cUarH zLLe|b_XNjxzl+sSt!&0z$gx~bWua>62Qao^ORTajL zBSIEkcT!Xt&}!0*2BkFCnuxA=LWosbt))#iSkOL7UdkpZCV?<*n9NRb$Hy$Z^sRJF z&Hm9LC#R=8_xKYWo=iDf)+}8^*R&YdF{%nS#$#4TBPOE>T`|JNVxLB{vbN4*vE=aJ zfTn3;I2NdvOUkmuD56wQOVhNBs**A)pof^B8e^!NNDo&~RTbyXox_?!%wJNRNiwU+ zK%~4ihCC_vAolVL%b;&RrENhsgs#^C4hoF!4K_%NaPXeCmKi5)y8tiy%@(7qFO|mH zfx>n^kaNqyPiD?$vR|ZEr`dX`XBHO$8#Q33YD`fO+>+VRZAOy~*0wIPy7d^{{2r6I zQD>)z9N&MPNhz|4wF}g{m#IeL;^(s&-oMT2_G7H9pXb7(FR-@04Zvhgy4H>kAJ8n1 zSsSm?EKg{bCyd4$Jo?m!SzdY?tu@tn9jz2cM-S*0CyYkxtZYa^cXITA!`t7XG!h!t z<(THula$qjwXKUx@2^tWQTCuuz4(I=LmQ>w_Knwg>l?ov(IlClVT)3dyr@5GbpODU zwylnA<=#qqpvx1ZLWsIq3}@0wmD!e>uJp8v1>C;Na&^k0o8n@x`X7IV4p_GZ zooT4B==Cw7>$tML&C6G>Fe)oXo7>zxI^n44P& z<7z~wG@T34*f`3z8=c%Wji1|R;gp&6t3?ahmA);AmLz>$y zGg8uc+%4jR6DZPpjDA`3g_CWXRG=~JllJwqO2s8Qu!DpRI0-{ z6B(q^7oD2hWkWnPiPaMySW0yIkO&;pgX?UZdjeC8*uMBIhj*8ZR<i8JMF6f2J6aX#b$iiyaU!-~i) zlke4d6lPU1-CM9x8&*bRR*F>?&4Poa*rgwy9Jk*78lJ%7bf1yYS@} z!fKYMhrIKx-=kdFrW~!~gJUs2VmZA}X2swM>=jzjIHMU))t$_LRB$cHZtKT&J|Au zSra6nZbHYRUf_JkN;RU<3LoSC*2h9{M6Z&{d0`8leeM}X;}z+cM1fw#`x#x=#{Cl; zkBo`y)ZtwUt>WS+h4wn<1F4Zq#JEjN#5GcKY7-HSB#orB&73Oli(Dj>e58nZA-U7f zcFy%Ueb&_p1RP40gYLI33ss5YMoO$C+3MOkZh1oR9VP@qrmB0o*)5WMr%{^b^rpm~ zrXSp5Oo6o{I@i+8?_q4ks3?UYSubguxsVXsB>^XsNo~QBz$_Nvj5Ul`HW;s1+S3`! zt|93&t&I)ZOyvH8$2Ip+-m|)5&}y|Ok|{;-3*78Ph>nHAH&eRBaqJUMv*KhhjWLA? z8K=sBg!?po0uD-)O1c)Mme{hQC`SZC?#W0spHvmk-X^zO#=>8St*}Z_jDd2Du68Ld zY%|&TFwbtE=k(T1x^R>G^^$qlvg{gM@XXqp>$h&OQW$o&x43LAE1M#|cDk6Ow83=^ z2M2o+B9$d=*I~6`c5=e9uJO(@DJ{Wy7K8GiL;QPdEjprkNdP;In?QL9mwcMPCsdOV zXEXZF0OUX$zx9G_g+}W#6FUHG?L2MPSF)7VgwzozGvnIa;N!bCP7IZy=2>uTAgL)r zY-y-uqOQjRN_cNF(|6SM0tB|uG2xrZp{N(MT|-ybESIMQ*G46Fo8>iiv^rXs6vZSq z`y^c>oh<>;!sUgKD~+R%)8rkGDY_gE5ugld5T?tUIMqxfZcUY3Sz8}HYQDD+iJ8tt zfJ6~&$Pzwjpl+lbL=tD>SIPCI(QCOVt6D;F%Iw`K<4H}mxz5E8e}Grpmi9OQ1?uiC zj=GxD-bWb=0&uBj=lVR3rG(R@zZ zIf`;bVG7EstvGAJd{K!zPug4pVZT3q{~D7_?2e@H^? zvh%Kqg&d9d9Zl2HHZ{$1E^32a8;N9O_ODH1z}93B=0iY7%1RqY)XG6Aq%v)y>l_q! zj1p_2WARd{G9H=4tBFk6I5a2Qao-Ud2yGkpbQC=Zh%{&n70_DZ*EshhbdJt9xTv0P zt(796wRqov3j;-yq$nR`sTPVo&aJuA!zY9Dr((&FRJq) zLi6^d4J=*1LzB$^az10ZoC1on8dF38tq^sPtgSHRDDs&+nvhlJ;=z>v3#p<3MVB3NL5o;#uyO!~2mC16>`ecPlX^b*>1MO+c;qfhw3;5>Ex4D0O%E7_Dj1EBRQ#)JRm_o<7 zCO$HX10GG&G-#!H`l+XR{>7Jg;e{7@@`)$d+FZpLFY1axHe%3H#a3n=-(G-lFSVVZ zLcprn#i$F6E{3!Nl<$>6(r|9yN-ZO?39J?ABvnqVUHJj&joSDq6Idx@u2w47-~SC1^@8QDIFNLr>yc-q94^#$Iwbf!Tov5;jo!WJcI zI&0UpVl~nfq*PByOiNwF@JyOpy0(qdonqOw74>v&5_T>KhcDX9`=ELp{vJVF}Rh9r^7OM9u0;ehgZ7lDf|Fg>2b+Bzyc z!r|?EOq9mWm-wKljONNyPvBkP{(}b;+EN-rsYGqX#xY`ARea#;3pC2}<#%4^;N%#* z=i=rTmmayu?xT;ewmN2gbCdHIFQKiW8cW~%#^x4V+dGtHMccF(qcAqa=)mLwlk$9I zgjxuIsqlUUlUf&u>h-j!(4tg*2EfRb@R++Q<?tTEVXL{W~grXU1Q(=BKgbK1Hg5Orv^ROz+S zy)JDWK-oDF?drNtn8U6`n}VVkVGE0m6ND53K6I{)^l6#Ks$(y?Rwhzs5~Ac$g%dC8 zlHPAG;+C7d24e-%Yz!hTJtJNrff6Aa6qEZxbYbwF#dQvOB!PM3IkP`^O)4lKM{8tULO^r@iWL8+Dp%)F8fsTEDN_M6?!(UI zQNuzZ7X=Ywlba%i=mQE);LL<7=~K5@BYVxKp`f}S_m;%C6WHO0l#n!mSOTV~4w5(~ zxlrPwM+u}+U)C1bq8ijWeAN39*ivShg^VvJ<%SFg$JZ;>=QgfQ@oP9^ZH=`Qx)RG~ z(ssg;5-y+~>_3Z&O;! z=GGR^|GjhV!O5tG5F!;r8S=oWL8#O; zEm{SdC9D~Z1Sb(~@(vfdOj$HyK=DXxnP(qDu9NUN98<8~u74}YA){SGgs&XR{fDNMUHRL??GMXwQR-mMqz;ii$v zi|QH9J}S~1rLq)~wZoq8w2@Wp88Cf=KJnBB%BWt7eXAv+gm0mj#MF`>>QjFkWixm`6#GAOZ4KnI->5g9!e;@obbK{%}mCJwIY zVj~i1SkJ?7c0bD_gigE^eNwNj!Bz$9=hs=kaGra|Q@-~4cX;~pRbIGo1?wE8(X6em zF`qB#vSdtw){eplZ1C7|$;&_R1H4oy@EzU@f@jJ~hKCj-y5Mn*jE|G#zruHmz7`d| zw=qTRb`0_R6xf(Gi9#MlVF_Ndf3%=%jyb=5kxY5fI?jQNL+L|6$DFLE{P(r7B&Xve zU1b=)igyr0o@;4J^@Y{E2a=13J>^EpsL z^jFbhA}CNXTBR7TVTzHkbc4sa8W;N&hDsXVJB+o0F2zY_UiE2t~p;g2@!K5Z6*V5^LcA}FTfCrP2nc~Q{&GRd~ z`XisB*xaG{@|XCR-~1BW9~&{jQ)@7Yr))yNwVjACsEW#XO244Iuz^__iRaT5rWj%D zNDwz|q?XaOR7x|dO0*6b6LLLCX(ix8Gze|1e$N(5M%6g#DMSJ0wvD>6iq0#(^!4jJ z``896D`RxYtB ztwM&1l{PZM%bHwb4+w>#iwUa_D)xBy4JImj6uBskDJqI;4Le#9OE`Kwpiz4RE5K7N(gzx{2#b^jXA z+cm01K${X>Xc}A6){PMGbf63k)yA0Wu}i4QL|Sl7nMc8?s94^#4Zf>m{%B*aRb(JV zVC)Ws!K)0~Uku|+Hb%KK1~2&UN} zN&i&GYe_5s6^lPA;_yBS6$nBjo=)K7KBtphqK&^ZdDHvY$tN?%Bkds$%+!(EpfG4V zV!VEi(Rjk;t5?}Mf1ambdWi>jZ*%nSyR-+#jHfl5c7$&|O<0N@8$noG#a%haQV0BO z7Kg3OqxT{=O&MEKm4fh*<_<0#P)Xa8iE*U$hvqbAj)%Hw zy&aWe-@VK{f`BHQQBar*el4ER8%egtN$qjWH(9@95CBnadD1#DcV~;4@tvli7<#p z*~fuB!#YujV$L$kT84KL$EPJln;r#|eN@H%lUU#zBzi#!vC2!uRYf^`tu;lNlAnmR zJ9Q@BOG&wj(>>)-Ntau_nA0rh5{`9UEL_Q!G1j6xN9*RaZ7s4b1d3uLbd-pZ4+~@3 zir#1{@+JH~L|M#awNwNWQt{E}`E~=F9lH}#(I*{v0NZtHm zj(AM&d?dE1#59gp%Jm&*DkhvJT0og}8fyYd5sbr`M(!)bkX7}wt5FJ5tVV8EjGtq% zEQCN=RjjS8vn(v93cQBaObBBaRU{n=PffKeRoJL`r76ldroqNmQK3hmG!Y6__@D%o zi>RKE9c4dhBXuqD#G)@C^z<%v`5A(n(X{+sAzP<;Nsyh;=Ai*eJ4XGE^&wXe0YE$9^4- zH1HSecqH=y)XD&$Ihp39VCWUAsws`mnL%cC88s1&nlvlN@VyAERgqJBsSx` zaHUhhsEkQ!8==TVu=H_qDjELPD&12Nk*NYhuP72Z6)01HD(Rf342k>Gl7?SONGGfY zqYEaJb+oqB%Y}drRtCJtfSMs)LigBz2sBMCWJ+yOg`smEl+7)?!degr-Kc(|l;o-X zTy^IIUFT_?7pbP5xAy&%_jm`zW@|~M};N>S-os?0gQ|k39QgDV7a05QFn8{s# z3Z%jv+gd@<5osrJ&q~y)2Sz}No^1>d?XVOdyq5thN=La#@dP1mFe!YCjt@9->2d6^ zN;{`nMm^gof7nW~%xH~@#Xu87E*mS-%9tq2ucP}NkP9PnqpiupWC<2clR+g8E+bJe z)(~QiBM^kD9Ed&Eu^|ZIZOQvYmS3z{i_)&2%9QCGX)`8@fhP@dRFQ&^l5h|>n?9h3 zNqk3|(~zuY_OhwI(zbCrkiuDq4S_;cv2N3M2PQ~2RpOhr6*@WO!>Q7wCaoBaMNubC(aje3jrrzE={VB&3lG zN@_+%_MS-~odlJUJuOIT=1yrN$#=GH(TMg%773wG4(_qDu@YT|V9Y5NmLf_Yx`d!b zqCGa-FhoxR;2oi@@!f*9ZSxERtrbNf(4Nr5#}s852h#YAWJsYcH5?7<@k!27_f_Fs z6brJ^jF;L4G43WdxWo&ULlec56DlDIY$=JoN+XctJ$v1Aw@9k*Ui5rP^Fef+3fphk z)N`VBhwhBTz7gK>zRT2Sh!pa!4_*4)!;=SR`VQw55!C4qQN-X)+2MSEPHHhj%`1uj zrL%FgvLcCdCn9BC+cGPr7(0`qYz+Al9Y*wEBM=bRQ)`V6v9~)!&Rj&zgmrBtp@_zV zddbL_001h0NklZYTx1@py{*WdU)x?E#AYgpghX7Bp9sFzD-wqQIO(K^q` zspqqQ_)VUAY?tx4q=(MC{5%qy)))(h49%tpL3!~IofF~l$f1_doy5&bps!QVz^6E99C-QIw1( z>x@>`DXVez8rBxMp(&BZjMYNY(>e+=q{GtF#Ctk?$P1Dzi%JhKD<`H&P9_g`5pgb) zWB*KV9(4Vsf5Z#*WI%z5V-YEmE)#a%E8e9EODfs0%-roaa5_|R4tUJy`pOVC%rb87HXPX$G#(+sIaZHMo@_F-n-w6_tr#?l226~;Me#CH0tOnAU zX%5?vexai{TI$uv&Gd@M^NF#o@7qr0!3ZMeLPO%4CBvb@kPVtT8pR_xmyC^ELnd%$ z;+qs%m5!s4y$yPT9K@Wi=J&?!X>UmQh*TGMR8#8XSik+qibWE`#KJkC1lveA+L z5>KIRHh`V?w2iQobyN>Ya}ZVN2(A^S@rYI_t$E{nZ}Oe*yvd8Neu97W5C1R|F69_ zd9viV^ZY*U9_w3k-)gS{3p=rJL4%~&&F1uw!{&5rbeOiWIY_OmE_0gyVD4i!X1eI2 zgXS`3W0GlFvX(W~BNAwW6q_VKps*BBK&@Gom09^R-x4ntUv%(@msy2cG9l7>tgYQF zD=Q=7MfmgZpZjn9eqEhzP$Rk9#z;TVJDVIaQRmfL-DGW=+JH>S<77jv`qfQgSr>rB1lepep4q_%oYvMSm>!&^SL1U!q zs;bdIe1I*E6P&eV<1xlURq0uJgi;YoMKoa9##)N$lqmE&qtO)tzf*WnWC_k!W?CE{ ze|n9Zcg76%_ZaUD`0fw>TgHQ{y!)%4GR`uj5R_#(qme7i5+wyUZr$TQ{nan{7ys-# zq>0DsYLYaOVn#X8On5abNUNjvuAzr+*7d_lg$>!Nz}2>^viKS#AP|RmEoLatqM?F4 zfZd#BCmVkBP7Opm98pF1O{t7J(r5=1q^S8 zI_GoYgo^n1qszSU#?SfYcm9;WdGoL6^giR_3qAhwfB*OBO4n;vlPxTe%GY04TGH*$ z@zyV|(Cv2k9z*KylA<=z|p-iGx;5!P|3W_M{8-g+@N2d?$QoF&frU1vrd z!=W01W{Vd!sDZ1EGH*aPC~yZ`a_zsQDf(z8x93Y~^j3?sO}%t=$nb1bv;#wNw(1Lk zt;yrXeSK3k|8}FBH)@fXz2t*kLCs>$ZYHpGq`O%;?16{sfQ?7v(G?GZbrBIU7=Z&8lkYY2k+khRT%e4Kt!p5GM%{QH^=!V=k`F`nBeO-?}NLqOP%tB3D;MdchV-5`>CMmy}fv zjWf$!ki=<%sR~S~v2~(i6ekE3aplUVT={gH(Kur~+Tm-j|0(MmE4=mN|CRm0t_OZF z25Q|uNfOGcs3I%g`a69+4<^O-AkSRb6$wJ-jlXsCHuQ6B;aB9Du>?NRP}jQZp}OiO8rh_EA6nskzKoxIjf&KKabrAZxSgq9ZWbK# zsRABxLd@(XQ5)(WJImHkI>s1GS)hw4I-gJ#6Lgi=>Xw~hof@O5ii~19qAD_k^}G^6 z9krjOaWpoSt5H#GHOtjefoBf&Ko7nqI}C$aS!fU_g1`qK10{)~n7G|1N@9{wQI#cw z;h4eR2&qD%D5>E<{pXbrSNqWmgnyO_h~k)})vD9#4^mrH<3?}DR*XehgDpMkc^CxV z4yg>uw z+xle7#%JWHs*)rMiNlD$_|e<^FaPl;+}$43X_>W#AR7wkXcmMP2WrSc0B<&J#Gy=x zI$K+pvme*wN*!=G)G55RcjAIWGvYLe3_hzh2a75(l1_=3YL(rnW`I zA)bhO_weeMn&G;N8WFo*I%&Xyo4z!Y{h;W_N5M^1)7X|}oe~k%<*IcWdmRB6b=2J7 zJE;BJ_P*2sXzVTz+tchC4t&}H2LQvm((LVfgl{P&Q6vbF1g=T;tA&&5U`G&cCgjeB zSf^%b(LxHWP#CKa`fv(^n0-DVB&j5O`$NCVS0&ka%-AVLS;_Kzi`A7S4%Z=AYrK&u z;yMYh#9E6A{n$iRgh@0~c~^6mP0*D_c&!R;{O5znr;Rw{FxC?XwG)N0@abpQ`Sm*= zu(!L-sk0@|efhuQ^tmr_`8RLy&aZz44o^Xr`1GSD+M~5cTM3k}jnOsZZJH+RjVJu* z&G-5A#$EpGPrk|5UVhrUmW7Af4C4k!+tpbTZsuH>xsYdBk*-dbboGL44m@W=3WZ%v1qa*Tjlu=MV=v+ks0=%H1U1WZ86(%R2|sSb-ci1SGgL}rs<1PVO{He zuOUDv?U^$+f%u+yCh= z_>=E#^TY4G&eCGf2WVwbtJ!tVQ(aTuyssu3`mlFU;vq(7qwN~b4hYIzV05ilMSVJJ z&yluTHK4#@6gZ!&b6_kr*{Y4a*Z;WM^q8du9P+|2)0<{(h7QMraQRPe_aWHLgtGR_ zn}Y#q?4w2?4@2-X6X+(e)~x0S0{q}J>#bzAU4ui6#<&lDQIkkI%2Fd`Q9Bg8TXb=8 z5v?_Y!2qQc7cN|2I-PR!=1o9w_UsuDf~%i>h7f{t=gwh_;o7xp2q8Fs{yce6aO3** z`+(~_2!NTPi=R7pj)jFj*|Z?basnktVy}bCAfEZ`!?=YClUdH$ES;t{OvA_!M+u$I zoX;|Dz~UUUGzzb~dm*lBIR59J|1wFEu(oJfSXgIuZG)xc75>rhf6cr6>z_uzt+O+1 zFCn~&)@UGsQWV;F9t^y;Vw;-%-bofuo;U!#p2fBr>M=WWy;D1a4)RB9acHUp>pBr3 zBk#tRft!I>5wwW=r|9+jb>Yq5RXZ@s4`r+ztv&Fu`#yf?wx9dk-T(Q|9dn<*KZkZ& z7mkqXZJe9VCaD)VU&gz!vB79GBFi$AQuKN~zWL2>va_?pwQJW%)0Ed=e;sWMH?ChN zj$^*@jc<@;8P~2|qtof|t#5sc!C=6R>(?oYV&-e~|0t z$uS>2lpez=rq%8qdHBztKRX+|mtT68#-sVwSD$&{JvC`I_3$3|J=2u?9`i$wXwEq% z*@S$W<8!3~cmE2x~tCOxQPI_KEi+nc4312Y5l!QJnRv`5|JILF1qw1&rA^V`1n!;T*$X4a}y zwr|n-{S)oMiF5b`KiCd9sSkc1rqFuWwGaOPVfR0LzlRCTz^cCkGfaW-#d5i zu)n`QyLX=Flx2C}pdZd#%JZB{moCk&&$5g+-+Xg6UR71`^Pm5GHWp=B^3$LGboR_V z&w1mGH)j0_g5Y!gZG`dTk3VK}b946WR;$JO`ugWSbD&m=`}+OhHOD#kIWN#-jz9SM zhn;`ixre=*2d_W;{T>{z!!&sh&XJ%T8cg}{iTSued9Z``CH=vDTl?V`_ptV)b6@oM z?_!6u)-o6j0O)i&v%W`B#NOT>o12@AMkAC`eEZwqW_fw}bAtb*mHQ~;4qosklL~Vwe;Q0q7|6v06sDXLZPVlG|lw!xFM#>^dH(#*|D33S7Cq!3yP`rWUP;Pz=NHC zaPl5yML6yYe^BTi)}O}UKhDna+iJ&|uwPUSJ#K#qo zyyt_@I_jeNNE<`vP)r|f970|6Vhn%R?RP!F{w`VrC;70|?7>*c-br_ z=*L_7e;>E<|I*r%vIPF2{chUh=60YfgRYKdKV;LKzx?qVj3$}KiIS2)shTD?B90=W zno_K(&E3290kE5+!FqAGpfy{>B9Vo98)te@JT*Y6>m;m(~+ z?(Xbik!-B?m`fcuwkGt>yug>9djYL0ZwG0O)`qI8tLTjNxT>|T-tc&PT&M%@TQdb` zAk1|-c~b&8qbo2z6H^7UCX)$fOic|7s1jnv@M^4~GKName9{gg;aHjL@cV!GN3^@W zBaOS(mcjl6XFT+cXmGb`uZau-5Ak1W%F+_yh(+$PZ!NwII0$e-L}nn*OH?(*8BLg` zq@9k(baIYKO&8n|l0XPwv{e>>psF-xyhCVDMw&s;(u(J&UR@XL&k`^iq>a_fN z?6e21wxuu3GFnqiM+|qixOVj>H||ZS>U5>tfwn&5waI=Cl`l3m){;hwejF1(&@BlrzvUT>BmHERE}?L^0UAA4{Y8UaOYmea5QDH-QvQ=I{i3eI2@8? z8N<I5 zxYHtt0wf-cLWLeEAe&4X?M!Hiif&X8gbJ=Tz(}udqM*8{~e8iXz6PW@~Rmdu@f~ zrBwzy_ZW|+I9H(^7#!KOBJD2I>GipN`z|WHMX4Rv?u^K_W1&CC4}b4D*4MhcUuFy@ z6`jbU(iq(qOtK8C3j(DWWfhfmjI)AamSY5z#;@uPMy+Y;(xJ}X7f^G+g>ga}Cq!{b zpcG-Ch~tI1%}JlA4GH>k$K|T9au_ib4sG(%2vk zDk({82>zgf2o(k!1Zd+a-NFDA9(`QefFvo|y1hx-U*^Jv3w-e2yG*B3o_+phdh-h& zi_01$5{s>CCzQu2RuCr%{a%NQ>wP+D$uQSwCnzlpD@$Pol{KVM#JKS9u|zP)E3AXn zew%h0^V!xeU;WD0`GfC$k0_44J6}j#AdsO%Ru+?G9`;DeCysgGtJBnz-wysIbUGaj zq85tK<3)ubaTFdPVt}704uUXd{pnZezxPYhc)}zrkwL)Tc+6*;j=6RlX)0t0VIZ;E zvN%7->)&{dR<}nI3F3AOEkeeHB~DV7mgji+g=aW%=4rlsW`&oYK2KRygu)_&2xltv zbb>81gmV-&psy`#T$TlsN~3i_H`FY-0omvpH$S_^Pd?b>&b^!{@XSfQK%kG|{kFz& z>D`a`rPJxy|O1xgAJSSJ-yT9owFlPXlS+aadZ1S5md z1;W@`Wq~LN=*s{bS^{HcwS++&VoQyh7Kl(GL|DTpSyYsgbozY!(MQa$t#jt|DL(o5 zGOjFn@s(F;wYxZDJg~Dh1YwM`7F|x!#guld!-eObCyYL(x4lPRl#Hh(yHia%)m$HI z5+zYJP(&CgrpDleV~{%*yKS_S$S~yGsST3Q1L-*dijXjhDFcNWO_0a1mxDM7YFgeW zHz{kua1e&d({f2k7=*K3LLZh$=jjC6t7lk0{S?=3j}UT7nk01M2xlBux3-9-qaBCH zpdtoFgFUuyY_jpkKOjvbc6XlTXTSc4G##_Hy3C1_r}_3bevi17LKqS#i?V`BYX*0= zsmcN=BykiGMlorpLrX<0tj3%@aRSPWQX9t8oKc~9`-2a-Hz~QhyT_%EKVg58Qy9x( zXI&J9blNS_Ryu>dNrHf4nlTvMLsTQyQq6K3LbK1upMAz#zq-t&t0S@!l!TU$6xyN< z$EwLufnsiM0X8=g&R~lYmuXC3JvX|p2n3K9Xk8(j8h0hZDFP{xaYPtJC>zjolEP~8 zk+=DZqNLq+9)LkfjP$s~=$iH*^gE^5&1U7nXzRV17Fw+~D;pcU_3QUA#e}m9Df`=- z+`YBJ$uno`pr6228X1P@szf4*R7`0nq^*<_r%xg*40iXh7AoUWO}3^2DPd|1xi+-Y z7?WE{Yf(}#DJm)lUw-aIzWx0_rqoS2bY0OWBthE2r;19q5UB-oFJjt2s`c->WX}Sms?jq=GyhEe0Xb%n_Ii=49AF2 z5=u!RrAOqe|1WgKyT5poz1x?$Ft0iD@_DXb8}XB0U**%=WA>+(UbjV>mz0&k7>88Q ziqs*HxF@$b4*2fxf1Pi9?M32NO498R1vLVDlk)GNkeZ1LXPg((!=3y06x4j#R-w`m z8HY^nWo+NsVQcFq!xN`yEiDjsI|M2uv<4{@DvF4c7%?3)neGuuUj^u-#5suwBHVP! z(tMBCUV4^~Ke<9axyOl<8^|!A(wZm?siqUJ#^}Hs^Tt<=Tj3EDv6gPPMV?P7OHHaI z69I_;r(jT+*t#4WM2RT zQb=@lRKb8WQsjZCt2!GvOusu&6U}(6CU3Ml0S-m~^hKV3;W>o-h}(AuWLZuU2!bfV zX+!K3G8OFa51CAIDy{j+kNyfPO74v&+_|^M%JK>?K7EdV`rX$!yV1iG6EYca>*glc zH@6XCh%u0~J8TbztX+7X*2)=zDDi!j3K7J}{!%?*JXEMP8Z#XtS{+WETIZ<~^ZZd5 zQBE@kcW<$~pRqZr*tY>LY@v}*`x;bETdy0^fQ)?^4 zVZ`3TiC`?ZFN*PKetH^J~kjU%1HGr=I8H3$G9^rUXGuIk<+&N6?-_ zD9@uVl^_a3gbFE&F{?Ow@kL5&X?J_Hy9-FAC@1@r*@z%W>V8(<7AvQeMM*g=FxsP! zM3JJEhG=8R$KHs}tV7p;)viV=S9mb-rGAHv)kR);=_S&nMK!pK%?ni8LA85`C`34~ zV$0|lf{_h0dU`~`sIi0^C>TNWoCC6x*$Zy~$?(Qug(8V1N{_(_(llj#v5(Ugx-8IH zK|an=${XKlw?!C*y!GbK$b_QPZt;7sJi|Z#r+>iuLJMarc6Nstp}4m{W|9@ekzra% z2pq%F9@DI>Cw@f`c{g2{q#SH)W(JI4jb(T9D*5Ohog|=_Cd5g?+QtSO%Q?>&OW_m+ z33mr${=@(F20#1xFZlHC9`mUpiZpk22NY$=`bwWDYLO&ebmcHwppeAU6T(M_v3rj= z@=_^JtDrSAMkV90HIA+K@(h_~Lr?y0Jbz*1nij^PT}3|4*tv6yo0opWFW&eO?|t+M zJL3su&BB`~K`;H!oIiJ#-5>lZFa6OESX^9Sx^)$-ClPI6{;>{>CzgqmHfgIvyT620 z5~T!D*uqo=!|h$N;Vv@lQB?)nxSDFL@W9a8Vys_g<0zsG3x-+A-bAxqdj7&ndv>Kj zNrZ8f4wMuubYjk}FL3&)b68W7kM1D~3#A2PklijsF=3}u1CSq4FkIo8dydki6tv=$ zG>&S-xLRBq_?#NltAVvK&S2}fg1~a_!UeLOP2TzNSEQ|!^wb)GNU&v!O)9PpucLw1 z{5<{T1(H_6v?%FC0srI=U*nY*zQpQcmu$Sx{y3x1n*DJ}J}p`7by!~6U~iPsn_D31 z%(1YvL{$__$0L&7Jgsi;fP~Om#)EC*v_+J(XDHf(!8W(Y6P6bGbkl%#yGw6=0Tl+Q zyub_weE6HUdF%iEHT$Cp#=Gl>WO~9?|Hwmmq=Ll<3$2g2< zJQ_!94qF-a@9r?%8-NlX5wR$d#^dKsNB1a;dqi{dbmmvk+GE!qX5ckN#s21P-v8-; z=JLDm@QV*WVLvahLSa3r6&awjlKjI@*u42a^2yt8@h5-wXLLeuKwDFKI3;Z`WeygE z43H>K`jfOU#bkyJY^#F(yPI78@G`?(qOD<4S*(DiZpvaOMWHdeBB(WxqO|N~n!8iW zNE;#r8jBJFV=59MX~zLU6fqx%oI0_Fv?Y4FOCTLehDc`+RSCL+IKfGEti>phLLS*5 z5kk;PQ~KQ=MOlznx`s}1GguW{~z{vz$^(a&5VFdy6Qr%yrvr!neP(Myox~&YevL zJGaTMZgFovB0 z>2%si94?5FQHpG>qiY22APVU&tsrLbouJE-(e93iAFaH8+iv$L=hv}CLA%|j7;aOR zBL@3>IIHQmQj#PC8L~af7-c!FRzMmmib69r4krV8bBmlj^Arn<>ulfJ#7;|EGQbMK zU^Hf2>`_c|KhciSWT5CR^hwf$veM-Flt?MsNm?VL=Zvy8)(ILGT4OAMt&MXD5=$5+ zES)&Z{x3g3*E|=l+4=D>HqHpT{SN=~pZ}15^qp^E9k?<_I>>f!GZ_wXP7*~4t@&j_ z6=16h>q>$+@e8fdOm}y<`R?1?x_XP{`8M-wtH@-IJ65sL@9@I;HE!L!&8^LCwx*ip z_JmF>8Rr@$6`Ap@w}m!LOGAL57sW^{-PF6#@9bujIzUEUhzzRTBS^c5N@MmbA5RKA z=$~>iL=hZeD+vDWzxj7;tZk6zIdL2l1cB#St}$TybA14cBF9=dfAR#{Xc}N#AFpVz zVm{A!SkU-Dys*ld!tj zBMQ8Kx@9f#WQ22yupAOsL)z`G_mZd>!VaR7lsv?XvoLlenhp#=$^_#c&=+nDQEAOE@x!mQMFJ0io zsWU9CtfPVii>Cy(NbZe>+}$6uJyZZ=NK$8v&qxR&CPj{R7EOb~-hfvdE}q`tzx%Tv^7XI0}Lxt<5T+0Sr+M19^$$Gm*D^WOx7-tb0Iw~NLK1F4uH6xQzrE|P=>LiP6r%+)R z5gQ01oDjG`VuOaR8Zf4I@*GJn2)_Q(*SP%g6>i_zA_{B5dSE&ku|J-&zPid}Jf^Cu z8lT9MIffzJ-nvV-)5TO3?RE#{4A(ceSX)~~3Mi|RwAEoUxJM;I7W!Sb@7^Wtq$uGS zPBjawr|7TLF1wlvYPsF_3_E#FyVGTwjhPw`znP>h*4CZ^U~ltNs+|%Ow7s_}Oo--| z5kcfBz=WL9)Z#2o2&B=-ARx zr7fZ;JdRvov}SZ~7d^U%(VDCjjP@ruQ<HLKTo3O?zR9PQT-cEt3cdHH4{!vP4fa zLh0YF(FJiNX~_^{EJan3CK2Cy^+o>0fBii+PONxza3MSnwDWxLB9JvdxkRc6qYagl z1g#DV2bFigWOp{%x_lW^RJ25FV{-C=v{Hd!`Bg^K>tDsz$I=AA992?(TNQcNlH+@~A_iZDu0SkDBi1nsm< zS(NM#hg^L6X?E^zQW%fWjgqR~_zL-=g2|&`J~fNlMh2_ekij=DRkw zcAUwYjdtQelZ`<%1nV^*G|u6woKC24Hb93d+xuHg#`|y*n{8y%2Rx{d5@pH zbA=PD%amEc`@eh}>0onnlh3YSXD^$wUm3I$^pb?Y7Fgkk0(C6G81L=!^Z)oi)2fCn zojQkIyg*h!J}npxH7Zbu$S}XwCa6^nQ%rGz2f?lcxJqNooKP6nH&%ImbrB;3cZL}@ z40z$&W+8(l-<>Xp( zE{$0XC8<)RD<{~MlILD|jsNCf{`ah(IgQB+?4)G6JHa?dC^gjda-t@YX(+0X(}J?p z_f}We7M*h}FD(*A4dt$PjTvi+qG)Do4DRhPEiKEdD|GwwIA@VUVV$Mj>G1Tk&v;;E zW4v3k=2=d=JrEKl1!Yyua#nOz62>WU7*LkgY@2IP{ZtUp>$VBPkipIt6#->gAf#k> zYn#jOyhD|b=(Jm$JA0ZSNeNmV0+}LEK0hZ=es?GfP!eM_Dh#mJ5=u2AA3+FI+9pvO znEimV$k6$Sq_s#Gr$hmuHF2xUd?)3ZlMDRj!y8N{Iptu;u2UdkIGLaVXr~cYYW7RR zxGL#~DXlc7-3mX4!}Ykfw>RMb`M>@XFP&JV9Xi6WO##;cDE~psXi`#@Az`doKhtM! zagI1i!08#Fv8^e`Bm$Kv%Ds|Pr%v*Z|MB<9huf6Gapvh~ICc6oVH{%deA}K$%d1yX z3a@erMU*TM#(nngy-#uZ3Kw7gGPy39PN#(34hWczhvd@?haik&x^sQn-44<^(y+zi z+zQj_2-~qN%`H+@nru2|_wKIG5H^OpRmD;q^L#fZ5^&;~7kKT@{|81^u)eay()wCG whXlGP$ae-f8DTr^8b7(lCBC0Q=*aE=16;i#IUr-jPyhe`07*qoM6N<$f_F}Cwg3PC diff --git a/docs/3.2.x/docs/images/apps/geeklist.png b/docs/3.2.x/docs/images/apps/geeklist.png deleted file mode 100644 index c6579c12f6f37e10ab1a3f667e33f70fbdc87173..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27911 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 /dev/null - then - echo waiting for manual firefox shutdown... - fi - - while true; do - if ps ax | grep -v grep | grep firefox > /dev/null - then - sleep 1 - else - break - fi - done - echo firefox shutdown detected -} - -if test -z "$1" -then - while read line - do - func $line - done < urls -else - func $1 "$2" -fi - diff --git a/docs/3.2.x/docs/images/apps/growthegamegolf.png b/docs/3.2.x/docs/images/apps/growthegamegolf.png deleted file mode 100644 index a8d6e9fb7493ce38c487cb2f31416838fe063bb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43441 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 ^!Ew8_;FrDA-Jwjzfp_2R2 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 diff --git a/docs/3.2.x/docs/images/apps/learnboost.png b/docs/3.2.x/docs/images/apps/learnboost.png deleted file mode 100644 index a6c33c8bd41f9806ab255e4afe5e0187c65810fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31434 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 diff --git a/docs/3.2.x/docs/images/apps/linkr.png b/docs/3.2.x/docs/images/apps/linkr.png deleted file mode 100644 index 62dc5f6c51174c77fdc4356a7f442e95cf8fb6ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6428 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 diff --git a/docs/3.2.x/docs/images/apps/lists.png b/docs/3.2.x/docs/images/apps/lists.png deleted file mode 100644 index a0f48c63b1eb40fa7cab3c8384ed97834c621e21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 697 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
  • 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 T655ph=X$5122!n4wvPBe3)j3P diff --git a/docs/3.2.x/docs/images/apps/nextdays.png b/docs/3.2.x/docs/images/apps/nextdays.png deleted file mode 100644 index 9ca96fe961a84f3df23513aa4ceeef52bddbf91c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35067 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

    w5Dis*m_y7@7D1e4 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 diff --git a/docs/3.2.x/docs/images/apps/nuorder.png b/docs/3.2.x/docs/images/apps/nuorder.png deleted file mode 100644 index da4cf597aae0b92aff5c13b2638ec7edc997705d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38163 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 Ef(FYGSO5S3 diff --git a/docs/3.2.x/docs/images/apps/scottyapp.png b/docs/3.2.x/docs/images/apps/scottyapp.png deleted file mode 100644 index d5142f34601224e550deb71b93313497f5720cf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118416 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 Dx(}}{ diff --git a/docs/3.2.x/docs/images/apps/seelio.png b/docs/3.2.x/docs/images/apps/seelio.png deleted file mode 100644 index e3e7a8e65abae0ad30c3db0a00782d8b1d54ce9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24005 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 diff --git a/docs/3.2.x/docs/images/apps/selectvids.png b/docs/3.2.x/docs/images/apps/selectvids.png deleted file mode 100644 index 9ba693a6a156164f547eb4b615afaa43a2475a81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42214 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 KMNUMnLSTZ(DAHH} diff --git a/docs/3.2.x/docs/images/apps/sharelatex.png b/docs/3.2.x/docs/images/apps/sharelatex.png deleted file mode 100644 index e3ef6dd25e1f81de2a170ede0e3a3665fe98b80d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19707 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 w+RWv0lh6Ai#~9=x}o)VD=23xZGidKsJj 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

    UgJe6f|Y=Yr! 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 M07*qoM6N<$f<=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81fB;EEK~#9!?EQDNW!Zh-iG6lB=iGc> zey?)ss?NEQ0RqI3AixYUiW*5AdPy3|mWPXywJeXlMx#Y*#b-jTrW5ww{$uZR?zvSBfFK}(1@-QJ_1?Yr+!KHK_x=5T z;$t8Cm;(?3@;s*~3Y5}BQN&y8t@R)4(*ODoE_{uT+zqeA4e!6%>l^iTi?lB z>(BmjE=WWnyexG94k1Ks8^4_p%)I~YTGsmGeXU)GQ{q3sp}*;+ztbo1*7^^>oP&kA zHmyXmy`N%@LrB3~zrpU#7~}j#T5FCS>@ggUxw<*_Oe8$B=RJKI_-_ z8E2+4Vyput1rE?k(rrdu+ZysM9O~P$-eQdZ2$pk>6Gs=g{a^>{B!#uK+cA6NjAvim z;I5O)L}Xqe)I~ z9L+{VGl>|CGfd&Y!DN5L?`{p4wg3P0*G-I3s@y+`Dz!nR$Zx_vbIw&#iOk)qp5a5&Q3&}wM*#|73o#5WqhAa9^!_YHPiZZ6*Q=l_YD ze#voot6fmt zwKqn|o4Ne0^{p*yEgydGDSq(%r&(HB`BOXYCqDfg|My>g4C^E(j`a8kfBPdelH^bA z_*d6=_}l;8@36IR5CT>g+syS^6otjusbv&tNnRL)5NvJ_Sl=2?8N)fpk+nV#-hGg9 zTClk@<~{P+Ltvl#3CM5_C(^|hCj0M`qP zu@HYUbL?BX=DOwKytOk<4J-W??PkQGwI0L0F?)j)(T>4Q{p5-N<};b%EPY zF7q!w{v;3Hc>sVDhZng0#4@LkE%I+a@f^SUTTgQL=@tIMkKE7e7q%%1%fXc%d0~0x zrK|kE|Lx=a_kZUj+_?1ubgYUnCyKh@XNx>JsdXC@!!mIr9FMf#Cr4HS8 z!cTqp9v*$_0$+Uc{98=%ZC*kMHnv7w+bS45cb;#HWBbQgZ(P_6$A`fvex%vYa28=M(IzmqUYbH=GRwFHo+8So}PhP4iB9H);h@{51@y*%~O z6{Hkc>+Q0oxfVwb^y#z`jCE}8jQG@JuQM2CeCR!=Nn*{~Qimu~j3)(B3JxrF>30(H z!eE4;-)*qA)J2BqM3x(_Z0vJjxl6B|u)Q~a%L)HBE-59y|LA!>`_&5=3)a<=dbRDU z#GjbHzHyuSw&iDE>q!~w5Kb zJ4o3jt&V^7`o0ea)GkH{fm9lG^xhx-d-a_?aOVNqt(Y%8b%6)&IDnE8B_+?jdW~1l zZ}FeJ>l7b+=P9;!$87G5xcBxoP90vLFqXnt?m4~6!*?Iz>h*no?YEy|WueV~@~+#M z@3;8a??2CL7qdnf zbNteO_CBBQu`iOzp=7igOOy?FRGx7S;*0)rEpRaX^nM~MiQg6 zMl0oiho2~l&{`8GF?0PkT1ocD#mw=&00^-zA&^pi!yh3faD&DWLhx^X?>UlKadl&# z|I`2Y30lpFEHjKIIlKE4{_sn$kwl71>-%JR!I8B-QKY!OJ;GYczx_lT0bIR4U~6~8 zYv;E(xYA`jDY$fP7lh#P=PuDqG?%XJA%x)bUp>c_jeTCbu;rs!QhdXB^IPkWznpXQ z+7YLZ&GYiv7ICDQ?=@KHw~$JBt(_L^>`hphYY}U~Xq>V)GOR4L&{}%)RtRvGG`Eb$ zDH6#-H|DCbWW((1=H!$TB(b8~>f)>=X+(&S!`j>#kTe^#VuiB~Cj|S036sKcV9}pr zkz0(hM3F)(NtPE_Yq3Irb&Lk~>#MJCa?Rv1%A4r$j*E4!(q(0$#@51I2yoTw^82&f zm-rjFAzaJUIdjf4gLPiUyrnI^y~{ahC62=@O}2J3wgwihl#d8Hh$4+OhBP-wA;SH4 z80*kV(nunbNFsz_f0$yO4*{3hCu^Ojm9MkPXRo!y8b`0&pvVd)xxrdT9BYiRo)&~4 zD-2Pj(UK~(>YNMoLwdrH0DL>d)@+jT z8*F!j&-16TW=tui6k5wa#lyd~-dcaQmUE6QD`pwP7>hCAoB|Qw40z_P_13yYR*f+P zN&7l;%e%pc`NlfaImh<31@h562=~WUk6(L#v%bnVRI|0e1%LeSz3K7zo&M2h{9Pqvf+?Gp56og<1AkrY)Bdy*QY6m;4VgJD)V zhIPEDgiKB>YGU2&%J3Ms9Dn((5v}9?i$GJDIac#fg^wD{auJ(B8>;^hg z80%;znhTe<*qd1HIKF_=iiK{1R1z)WcRu|p58Zo+ zFdFA*Ef7-DZfM#`#MSG2JpJk>@3?CX5ow-&@iP5>n_fGj(~KF7bF6bTn-R~yvcbC^ zKF)kYGuKae<=hruc;eijxK81%^=Eg@Fowf1&IV*fK`Uu-aQ+06ob~-{w4x@)T6#&J zR??%$c6io3hQn4VQ|BD*PJ>fN<{6Jt3I`TJJJ$5t3A_7a*0)BCFf1-~c;xPbT)wtP z(u$dDC%p2qVQHboiGw``qaq|5BVImxoqoSfHl8rq%6tNGeUCJ^NZ~*#+6_${DMpi= z1FL-&Ix*)jZgSu42bgdA?Cbt0MMsK-ev9iHdmuI4rsjpSTO`ex`GpppHzJN5S!B7R zXf_j^fks1dd1IGhnlnxdni4Lq=bSvcz~26dFFbvj{G0U6-dcaQR~4>xPS8E@EXN;y zjYia>Fgb@8&fv_Di@O(a&H{>9$MhQu>`yk?pX_t)EB7*7za1egNvvtaio*E9lRBwr zC98aev5vx6nu)GTCgVskNj-!_D@kE2T6z3@ni*eBh9k`_aU==I^=jL~SR$*XKdq8N|F}^S>cZ%p)%)i zFi!Kg5|ZC#tCq(Q$oMKr=L$}E=i4)bm~k@8+6n{+2kGDlHd~@}g};^qUborb%)x#$ zNBECZ9RD>N)6|nd^+0&2ArZBv05_lO^gCto&YPV>x!GG*)OX*~*4CWi$r|~1ExdZO z$9;1g$cJlh7ME`-LEX)tea*kW(Y|JOJKI~x&3sS1$xcH?{%h`kwsXeUJqO2kQSHdL zi^XSY;#Ryr`q1h|sK`@j*#seRuE3apLKI~&qClwzLTH>bSQ|b^AcR871W#}o&KW=; zWrPqBIE!&f$ExFKP_+t&oQMTCd!jZ!x>U^km%(x4E0Pz47inr4g@rO$#WkZn@C5{;NOxl>bXabXvzql0}>?7*8%!6hnj* zASBW$l4OlWV=dU#+ZZzjAyKkHt9cwL60&SemhT{hq>(I<#B*4iF;4ez7$Vi9887;M z6zf=5AkZ}9C6sDm%!stu3V9Sk6wMK-K48i6>z?q13^!Va&)Ya0dA^4=*-ZU#;QH{Y z1j0?2>EE7_wDyLLY{f8BDeeG`6P_q>G902L@|s+B7KaQ( zTAGCp=Y-#PxGv`e1ZMEBCC*y^JM7E}TWwq4Cj_vk6TW+gwOB&#sdmgt$ynjp#z8Xy z;S9D&i6cR~5g~6e#*j|PK==~tGKS+z6h-QZwRr?BJHh#sSX+?gTR7*4bcaaKQFfUq z%rJD5XriPqc(=}kN2CxULI{aKPah-z-h>lE;xJg3`tuPIr8)=^VV$8cqoDMqH~Vxa zFomEnV+u10#}a_@S_K)tP}thVW*c z5Y=%&PS2q{KU8&{UL%BU-Sqs+>#dj>iEz^YX8ImMSd{zs1TJU4>%{bU;WH0R+kD@cDQal!==WW%|Fs7@xFC$^IIKJo@rrg0U5 zfs%-8PL-=PYx$wuCu{qcnZFHF5wb0td)fenl+YJGUDwT#E(ThEk=bPr=fKPMp( zPGHQCaeA3{^B7vUX*G{99$&b16c$iJ~rr-KR7egizr} zdS^ToyZ}fUBV>X@U`d%WR}WA)mtoB?5UN6{Cb8~&)6Ayi`5+u)D!~K-tvg7SV9cZn zBut-I&8%`EY%2t!vXn&4AuSo|#@KAlBN6_!s1s$-iK5aH&TF5lezZK8ti`2ECbD7A zk|`&7v#YFeDa}P!+A^itD7@(=s26*cTEXC)oQ9yK_hDSciY_q7)b}ZUId9U1IvYf2 z*XcEg2xg(2(N@#SIi=LC#~9t#ZDjctll(f)O$$}>Vvot>D$V8*BHc!`4l$lw1quo? zq%iwLdVyFkV9f+$CRj5@=r&R|kRq9JM5Tx@LIuX~$v%NYsRSt$;Hqd;r27b&fN((@ zxXQ_o^<0RI-NyRTC9*WC2#pIJAY=@x-dYbI9} zoe2b2bG${FGbxEvOf`zDw1*3tEijU^Vb>)g294lqQKV4ATCPxb|~zS zQp^aUE6w309l?xhd&0Ik&K4+{pmZx#hE2exK4dE!L{Z5UhCJWLIvaeG(j;r4R1+y8 z92R3o6gHhcr^*y6?dF?FpKxAf0IJ$X;E7?JVRyzb--KA*@Lf@BVR=IYt70fuo$su< zRNIH}l2-&N?cXa6UR87EMJ=4Fg6T62XA2Zy!!ZJ5)iaj1)E=b<^D^JLU|N<<6I|)r z1x9q!tCL9290Koum1bIPSyQmPy@%4VZ@3nOZxm@vQPlEDjwtd#)%A@%P>OyhsU95; z(!4-P$zV9aAeiqp5%>x|DI}4WejBC8^W3)>O=7h6pKWfB=ye;_xh3(Nw{O;y>>7=D znMn80vdJV{rzm!-7)Y9KAVo})tPn+WAOu;q?rnRsM;tAqRR?d94X`#tOO4iTOg;+X zKae6qR?LByTrxq*2BmKU4y}72G+u*@aKa&FLZs(WGR9d$QS4z|UYSo)YP9O2RWlHa zAvZ&;&1z0+De+4|IyH;RZK}s9>LyY!tM*guuRn+T!bRM#4TyV;54K|l%@GLue^4Z+&J>gTRTWW ztQD&(eRg(t+1=0SG-A+-(?{p|++$}wV>pQ7n0G#Oj7EI3nWx8-s}yELD>+OQb!asX zQ&=Kmq^bcWrHMIVC=j}rDYo>8X=Jv`l6x`L_uSC zGeFB`kZKNRQ?zcPRm(eaW{kBNQpCj3yw?KGlAC?3EyDLCN;S}`jg-D$k+lSOK-{L>wkngZugN$#YE*Zm0GQI_@~i7Zc>&~YSs=OV%b=<(nzg>t7VCk1Zylh@(Ac= zvw_x%`|di-V4N{YbJEPx?ZhapXhw?RIOp(zK9jVdb!5p)edidAG7y3!(sVir%L`4c z17{q0VQDoJ-uJeXT;ACCWeagc^ffA0wa)?UGqi8ea)(IbdE#gRrP`#~I(ad`Imb9% zM~DQidc@Hp!b!4xi#*>!H&&6#n>xl#g5>hiDHme>LTHpss)yx*>EktX9<;?ALMWUw z7&AnOh$xyzi3BI0$cLCB4Nkld*{TrHa?WDxn8KzA=a5w%qwX+^njcYWgIRmHdaeST zE!f_Bh0E8zfYge?e|eI%UtL50`wNIzA*8^Wsc%v3%azRLd^D-@Wv9n-Oidb5V$v$4 za!FT#@Pzb9wes!>AUM%wqED1L6&FIMuFm+iXqzaV`kI+Wjj&yL9ezI`kWN&g-O}Ij zXKSkO-K3doOGwGw+`>#P&YNP?0B3z~v$?qzb8{vA%o=A4^W5}BV=b%8U*C^0#?tLH zSXu7zjh6POqcApOIJt;*8I5EWC7ZMwN63mD@@yMxb0+C!T8#*$+Qji9ASlcLYf`js zk?48SkewD%BW0_4pi(HTh$>Ytg+i#<-yLI6s)dwsxPUPZ=aY%Dfdfo2#F$ZN^%xQ9 zE=o1jW4R!PNL6g4n_!vrl-I_9%P z=(m;CzI-rM`p91y7A`}pCBq2tnxiCYS!uEOAB95t)U(y&*zsP99sL*N%AkwX1CG7pyHb zNs%yWAb8%L{7DY zRAIJ8=5r~fL@g6l!uuXdHc%p%aKhmzeDtfLk050%us*;&c^Q`$$Pe94qdCX@xBoSs zc;TPZ-by(2j~ck=E_oy8*Pfy{F^~Ss4|_kOG?i3ozWB%+!yKNxgjj6hZd(YT%QC7J z%$XW-O^Mkt^(VX&?fq;^Dd!z!__ywdl+038`?i%nQ&jnq;4C{NNb5%%*;3*L6Hd6P z4^&HfltM(5&c6$eH?lgr8`FAuQLwW!;%b_*xjW&|YM-s`5mBre4Kva-XKOD*X&4SB zjMJP}L!z{z*A|S^oU0rAWNA+BV7`+OH=A^u^E4X~i}MXGT-m1GXd;CpHHI`TNRpWO zjwUZGSz)<+bqC`d)>;}#gf;%|%*`9RZH3kmN(gkTd5F9iVC)3pEJ8qGhK$DNNRk62 z@f=FGXvrhw#TI$KOPXDwnH)jNh$LPj%eN`)m`HU{qUj?+I0OnMo0J(?DT0PTqC&_J zXAvUtnQYo9h2hM}m75}xWpuOdZ|G)Ym4;iUFk|w3 z7h^`=#%(gOO|bsX6rPP11PCUq6Lf{;V>aNHw}k*NnKOTHG(XY zb|Tc0TbqRlQ_vnRqbP>n!PZ^xU^}qZkeiX$M!`vxLL+5@QVA*~6TL<$ur3Yol&J|- z^CoZ(iYq&~y$LcmKwJe0go9pd4SU8>{7-9$QH~g9u+~Kwi~abEnBRQ?GK=`R`>_Ah z7jR#_0=*dV&`Y?-FF|H;=XWq)I){Guk<#!0VXG)^#UFK8O3jI{BL!rY{}A3(6=mkS z%zWFaM!`+}iV~Pu?L2&513FeU@6`#FgjV_>qVk(8b+kYk4wl?tNs;F{U;N5hQVR!` zdPG`s;nFrIk1aD8O*pzXM_dn^M$;%!*|EHgBr4^JH@+dvDy471S(7lRn#-Y-tiF5m zy7_%w6yqwJ97i4ro9DX}#Q;lAmTzLoXha8sB=4acZLd9wZB)F3lo}yA;USmt^OEr1 z0Op^33HSec479|>$`h9oxXj?5zKr<&S1^xXz+Kr#{MemvsE7T(ehSh8 zS`oZ<9lJF_G&N$FW509(`xov-{^41~>)Rn^;i~NM6tovYqm-J#Cjd+0tfEz}By<%_ z$B^+4CYCFS$VqJJKL}OjDMT3_b`B>@1xYEBfkKwx!l}7dno?y5*yk&3Fc!=BqQI6; zQROR5)u57!LkIedQ;*bb#}UR@loHH!8~j%_WG5-$d{Y7?!R9=KPG$jv^+ zj2XKNG~5BAXbvf3l6Vbc_A3)g3eAj02ne4P45i!CIuC;B zWU>G-Y@%fYC8O#QIXvSSmsVMKA!eDfIt?YO2Pvc=n(ttfkR6r+5ow%Mn3u0%|JTPU ze)mP#9C;tYI(Tgx@!>l#KXo_iH(r2oj@!$y|HXSy|MbgnX%F#^L&QJ%0Om92{Y_}A zVDcGCJe3GxS?8DmV@zL_rco`I;YugoR`*#{FcDj2!2RXf>T|CNY&ZuOawN6rRe*Pt zK8~wG%w=w)^yB<}a@BcEp)aCR$5XwbwBqhFhrZLa{>?Flbp=_mg)#f+yiXD@5Jg>| zfsUKRZXRPN6ve);hae-?%P18S>wb_X7BPePydkPlD<{x7U)*F}M%_7`g_sAXkOFdxefBE$$;-IQyNFW@=%081#=!|q z6vP_y`!A9IcYla|eG7ZAi@oa@`i1L=%^@g7eD4vYl@!1Ak`H0N{{+oE`yj7bZBTqO~iL10UPJxBU6g1F7b%M0e;NBv zzJOV3!r%W8(K}8c6HW0~{}o&xLMyb4FG55}Nz~hpKhH_S;j5UVif9@H3auLc z7%~u(wG=kP2DGm%ozmcA2vk)n3koSh9fDG%AO8aRKYI+j+{XR=4$yA=4rhD4Eo3d`PCiY7#R?;_UE!S#u*Dr;N~01!ueruI7CZ=P}o>O zJHpO)5WOb41OQgip=tKmOJRqQ);rlkfc33YclX9bF+BI&1+HA#Ce~hyy!7G*n_DA} z9i6AqjKCGs5OC=)RKUaX$;c_u*N$7#vydf2O&#}ohviZSSMU?z%|Uwu4cw|rx0}cD zks0e9UYmuw?E>oxvV5Jw>=LOt5C2e24;2?lO*;4+G0pv!Dx0a+5YudG9gZO?DOAr= zhj(R!K>PT(D-ce2Kf@LvKnaPE2?`w|TPkF{OIv=r9NZ*{V47=P$G$O>8FOvW2W2nFLp^#><2q`eHZ;<_0zf19%*AU|z7fD2W5*UacYXtBElN6ib4~UKBf7l^sa19Fg|M}&52#l$O*&5N21Vs_)HQ>veb>Jz zb0B`-^^A9k%$?1C-`Y!CTcA{o6yC{=^z_24GeJ8PI9rex+gLmCNjBN2h|kTi$SjDLiT!iyW2yAOu}?+&}zg8%wMxc}u*#FsB(KmG!lQiu=U;gfmJ!B?-4 zKYIKuPdytBy^7PIAuJ_*xMVj zwYAS(cOB&mpMQyGpM8V5xeiy?w^&|mbM302-4X2X4Va8_<`+6V^3Y)}UEb!M?>I@8 zXS7>URg5%+k=HWaA=Fw$qiT7NX}Hz|Xhx|m>Jz_1;Gm{uykqXF=|xipxwV%b3|~X* zRt4Es%9o~2u}v+eK0qx>a%27TlrqEbfY}!{(}`&gp~_I#4KSgIWI|ykK2b-E#iFFg zT?rWxxfWWrJ-|^YU*};blqgh-1y@j7(iMRO{E&X|5b00eNA3#5bJvI;y#yC_a2IyL z8h?57O`4CKAbV{K``AU?)qTeQ{yE|goW}k6hbdmX45wF6XI6<$Eu)v($V68$rsm;= z3PO?RhQZE={#=L2B;(4JZKU$Cr>}hVb)2(Yy}HG1H&xt+Yf553#t~bE--H zN>kLT_uS3Tw{phI1S4fQcv>uVt1oR`N|xso#lYL*Dn`pDQZ-Skjgrlv9im{vMU9< zZ(_+>O@ye`Gdn3MKJ_yCUq6ZXFW!sL3HD1DaR+*Ew2v(;v^DNv4-qNikKD^(I6)p? zB7Wcyjibwm2an;bL1NOC!cvyR=}A?Gh_@X0@ToL~6)AK>h{bw2U?U!m7) zA%tW+8uGyXCwbzlXX$hj4jfz}ZbUwxfZ#(v@DQz5M4lCNx(y!UIL2B&^x>HKg?3fvO`9?)V{c~exnwNsvbfa{VJXO(s>S@NnGvuP9NNqSw#IaYWu$RmzDt5KqdYbDL~=~Cr~c2W^B1W$#-$iD zMyWQ2vClpSC;+(N|3JY6;|c^0V}?YshY*s??9TWp^=Ov}_M7W9VP}l{%){&h=lXqGNcYTE$a=9@g!w$cR-_&aPHhy zUO#({rKLF@{nB$BKfXqz(V*38lII0S4zB=?Bu>~Aj$_AH`PrYHV`ZgJv*n@nM~*IV z{{zQaS)IokgKLIvBF-TtEUnCiZXb5Wfv&s5(|cX-8&%t`@+DlAwe}`hnd6Ym&OQ-S z6Rf6vru(cHR^9qbHycNh=rFBPfY5=kC8Ba-rSBtBcWP%Kpmj-7V+c{pZ8#D7&oX0L zDVbnhL1D*e)%HyloIy%og(svAu82koi4zIV6(o8Q>r!Ghk5WyH9TKa4panY(4bQ~N z1o6YCNPp@3F$y@|r*ZEAl7kCKCuqOzREPo*B6Px|FP&gG9CP`~CWj9$^V-=fEX;RV zS)Swfe*bY^eCZ8}+;Zs95*IIRu(Z(S+O;hlhSR4HvAwg$#`PUe96!L);vBtxgKoFQ zWSr9OBz`VkNJv_1dFa7Y{yL1C5e)tw%c}cIr3r5!Tp?V@euu1~tpgVUO6Yj$aF_Mr zqVh$mv|YsjZsxJy*yV8=#C#jUq=5-%YuwOMbkQcB#AcoWi_S_otb*qgZpr9V*% z%h#|rL9b75VTnaT6RReLonTC04ws>218d8!BC?tnErkN71N1|qWQ=tal*Js2Z4ckc8|N<3 zZa4XvpZXw|E^g3FnzR=Zl-8`RE)qwINA5h%rOWFqug>x3fA)h!ktT{2%PS@G`WYJ* zR}Jed{URm3`Qs{xO_^Mqmb6YITQy&yBI0nbtJH+7n9Cz<%bh-;?*!uY{fWw&?6MfBWB^~y6+V|yNbJ?Y$hGHjqf=hrpl0R> zp+kLyLCY2npRiLh@flqi`E#niSXRJEUwa{R=tGr&Gvsc!@>i@2Z9Xe=Sd@?=q!3)W zw26*jVZMuVkfu4~QO0DF^Y~X@VlW)jXv7$6x&6#x=K39$7U#%{0&4}GP75g|Cr=)t z*K5)1HR<=-%*}Vn^MZD}!TtB2^c7?!)Z5vB@pDsT`HiMuy^~>C6HDj-)N4R+$m=)R-ws(llS=56FUp%LYmz&dIc4I`x}3s}eB>!qtI5*IFSS-> z4V3+9Whi}(DC_|1aX>G4JjqBymE!fB;$@d4wGdCk3aD|OACGOxZ?<) z|H3nzJAaKxYlKwfxd9=_O~Ltd>%8~f_tEROSy}FL>clEX4lQ%?!~r6$c>nwFN6Ruv z2{=b1iGvSPFG6BUxYc{p%uh*Z9z!;j($mVhDIw0v8CT)ErjUAd(l=0+G7e65r;18RsY4Bgs{Dr8^nWNN zt>6VSx6xy2Zs;J97Xy@xd^2gO1BBXl6!AA%PmfheRgIDnmK;SyVaG@r6NwI6+t-nL zhfXI!BABEZ#yGBB+u~!t`2~(0TVehBHoH3`^1NVizE2}bc;?x2Y;W(ABoQC{-iLYS znb$aZ;sEpWJ+?RZSX}H8$1#8IqaQ#B4`H^}g$BkUKu}T?b$flbz-KB|OX)i`kHn2R zgVNbAo#(2_LV3^Y`@SJ^RF4+95*rnG2WDX)weOeFDdFm^L(ARP;36W_aENKs=c*w> zMHjcW7p|pjpk$1aZ6e)9s#cKJx+2grX=8EVve1e%MxiTZO!>QHikg;iC1FZP#UySY;Eo# za4anLdG?vJI0Pq7ta9nnb>9AtyLjh2??y{Szu)G}nZrEt&>5P|22Vcq3g7pAkB}sB zxMqI=)=oQultk)EgTAE4D(W-!wPtcaB{$6o*qSfqrj|;@bQMOd#4(8(FkhMRcEJpq zEll!(6^|>cJJ)41wVPFb?Nn+H&(*#^eV$XptadH8@Y3DZNv1uYWPlWVyVcsvXT4n! z%omH&Ewt>^0)vtnN9uju0WP>DGWHi2nB?l)^DxsOIvOjub+L*4! z22;1CWW3V%3FcZYGFgVn?Jdp_<J%x@4Uq|6e2hvU@qL{XX$?}}v`t8r~#v2#8>#oy0^URCffA8(I+im{v z(~t7wKl(lNdmS!b-az0`^NNcXud%;BqS@ZHxr41vIB@u zn40Nv1SIi1c`;;?t>b`3yiBaS6$4hK0ixaxR7~BQii2--=<6Lvrmobjy!3E%0q64B z>}as_m245~c_Q6MtE7rj*}yVP za4_QJ@k2cG>`T1#>N%1mCeo5#r-PD$&CPAz{P)STRsA$&ap)0!b}&i6V|vwdb*NcvQ~E$@e@MV@Y6 zt|GQ@W)&RV-4Koq&T=&qqvRleHH~Nihhvg$1Oeya_lW0O&)Ag03;{u; zd!Y&14H81!;A@n`P~9@;@jP}Cvg#p&E_`eJ`chIdKi9=t-@5VC$s@GeEl!_0#^uXb z>2^C5#&F+#xAWl-y$`JfOUpf+^^=#H%{FT*r;$>zCi^&-V_gVCJ6jW`Wv->}D^)R1 zzfBdp_t#MSsM3PUv`7YpF5_Ox$iK9MS>3YS4u8KC*lBVtkAIsTVfBR2bAGb>!%!<0oG+`)us_GhmIe3^9#IrRYi_w|Eot{id1w|K1vRd)&M`mN<^KClbL7w}%S&^#n@yrfbNg+_u+EU@89(&l_o5>W)*@X4 zq`)%4xiJWbbp}y{#$`yH$SI>j)6*0+k?3X^yzXRHFdEt1+?lS@R2Cza-RXF(4)mR-$~aLMFu zX1}g3_Uln6Hx(3aW`9tE_x#_Yrl@M@}m|ixO#csjU7pzUB^y7e6{q*FM2cDrhAA0jj^WVL;3&j^ABP%=gmNGLJG1uij|?)l8du zBeCg4+`NRlVPB$(T+R9hFtyBF{YW#ht64egyMI)$5Z;WLX1yE)G^0hN)MUkwyx5~K z6N+L)q&pf$nssR%V|W*B$2lqCg}!w@oN3xl`r9w?r!EB>iu+Y z<)yW5VV%X8fmgp~1kPiPq>PF6JV~+~;2B`-h&10qsRpr{LxiS{zJRG6=p}TrD?55u zC9JcO&)S^AO^`A|ix!rG!i*|-hzOd?1;>%9y9GFxA%v!|1JaRTG#V4dj#jfnmOHwk zqqQ+PgTX%ScG*t8w1s3%!}*7qWd-9=ijtCUw^foTRp-7Lb0V~@ake4`Aq3-bN|qOB zrLfM@YBs`g!#9N>O>^=*r`>9J$zNSpIR#1h$XX-vP0A26iMku(W2K!x$~I^gmy)O!Q=vi@j0elNvQ6jbG1Y!!OSd6VQ=l+9soK` zH$uz&w0htI-@Gh|mx=YfkL5c&4LR!&10?lxR>Dt=Iw?nyyU;r??qG z?VQ7i0xc7iY=kiYJ~Uj|5wY%uDm;OoCYmFH-&3~y1V^GfJpRmM?Cxfa)0DNCX!ZI9=vCfgDIY}Jjuynf} zthJmvd5CA9dyQ_V!*Do4>xiA*Jyw<%7>_5MI(3+f7dOa@oGi_`zPUpbMGS{yzVCyN zaN*)rCTZp~=Ekr;7_+*%KpbnXT-_jv6-r0sc}AnrU~hLon&ou6ExO%=(`VME{=<|y zDQ|1(up5^%9ABc5tdK-=M7kZ=tz@KHWZ;G+gdmA}zHZy)?2q1HFgaUk=jnlNX09sv zD;>hX*VMAN(9)yvmC!+B3L4b9LnB^8$u>gxWL%zaVFENf(Mw4D42#U{`F8Gc)8BJD z!3j|{#>5uhyb4Xk5ZX8FvN=LDK?)}MHcBQ$s)I3Ogpe4U;_JP=(_GjL;f#mAOYKcC zH^Ev-5_j0%ewj2iw3?FfWWwIwkXEb3;loReMiZ`I-(`7ak*A+MOSjX+*n%TR)_CdV zOW>d|1yQ7Fw_5Csh72cT(l@Sg)?c=)ohWb6SjBu$TP#qlZSco zsh7#Jf|Dl?gp9wJ^xJy_Hn#_?uWzE2VrOrkZl}e;gUdYo{Oj!P26)P1kKtfQmK8{) z>Gc|1zO==`LvyUI_2_n+RbHtc5T4R%IY-bknXH3zG~zz9{?bf3vG(05;X7BbKR(Ae zyGo?`WOfroQE3#VT4dSvup6J~n_?2hcZ0I!~T zw}_+VFtNyyn>}(fq#3V4Xvme@5pgsZe1RgU;ZS8}bF@rw!q*fiEXJe=K#9a_4IvRC zW|D8widS&1K%zrZ(KC!fU>Krglfq3ncKk3WPp)F^D9mD^to#k|bhvb%8v~DNOGBvL+hg1UtI}-uIq^IA@X4k>>@kpS{AV6KlkY zCd+dMgNd(|sUciv3@H)(1m$Oql&AsUu5wm#SLLhKAj})$?7`4&#!Dp8oR4nhD_ApO zG`WP3F(QQMr|^`r!${c2cY%KapsPOEvO$up66tvl2X~p*62;Jm`BXw2ub@I({=)8& znQdad;JcVRFm@0E6TYvgwc}7X?i&DDOcluSUCsSSD1jy|wox)BR&!Mo1Y=Vi1yUrT zeWb+N6itiV>;VcXBNi4ULbNa@#<*C%)9O4HFgh+<8v8CQ`z7w*GD51vNJ zGVJOJeQ}{Xt>G343kw~LGqZ#|O^yc_Ck*tIWh3iZ%`m&Zj!bu6IL1-m3o=)rP)zK) z2a)Oy#!RS+xuhhCRw&Fqh1sJjeiFC7-q0Y3q8^R-AS#UNDvDjwY%_EQ_ldtGUP8+@ z0?6$?S-yo3F_G**fR5*8NUVER%*ELZA)Ee2Sq~TYBXPa-Gd4r2#1nzd{8QGxWHZ)1 zax=u&W%&1evQc31=2>C((4tE@B~{26>4L*vr4vL2`zY1@xpUVz`^F{a=X)rn*xubI z)|xyo*xMg6KiA>TJ5F-${5qr2h&0VvUS8nkSI%+w-KWU&l&jZv*xBCaw%ZP|wY5i< z7Dx@vMuJv~(P+ZT$|9RvJLpJ~bIqXMKTd-w&abY=1{+&@P(IHjD_1XH>z zBW=b`7^UMN;C#)#Pvpfnv4p6?!(YSfagMauCCzpaD2yF39G^$Y1WAHn0@y$ki%6M} zg)=O|_ ztC@PvX1+N=DC~D(aH1<6eBq0YytMO@zc3TBV%Ilc0IxZSDlnrG0wr5`(oq<4e_WwZ z0WR+gsI+g!=B9JC>#_FdUp&jDOB*y>o3xq@hQkpH3w??rCrJ{nT-)N%;Z>f0@pa-@ zBZXjlXTV@EAW1Z5&t9a_h;hR4%(Jf&#}VyT6Jg-ml}+a6dt_O`m8+YK#~D$qICx-* z!C=UtgDb4A&EHIqr5c#h|I{~d?uKnkN4VTxgckl@3!?>^?oCH{6Cg{?EUV?_ouM%M zNa5>c;%KfCN`io$ix<(VOPXE7x%8%Uyw#U(B&$LC4oLHLj7^a)sAB{_RtpIS>G_&*?{Ji0kG($zmy5Wq!h&j8O0QC zf(j;GX1sZ%gbpT^!ID$9<8k=5F<5*PXrX+0s4K9>qeevt8w(+L_~AP^aA1++#}5+6 zz6%FJ5Jifj@LAqwE8!y_eiu;`l?@Onikwcj&B9zCrTt8aJS&iDDuoMU(aN_3eg4_k zkxFvg=|jGQp@2BjND+oB-9V&e=6L!Z6-H~CNSg+{r`-eneb%}~63tBuz5>BdVJo$~ z!%V)j+;hNL#S27HkD?fnWjjQw2g3Im6Cxr>4j@$nXR{zg!}$t@lr^OBExa^XvTU2Q z*u**GqfNr&aw0uP94!FC!$QI=aD*n-bD`<7Auo1uSfpt9Y;!>CP8-FSO@^mxwuGy@ zvZZ{e9yBh)*ohxpDI#z=#^op{$k;>EK?>itb2Q%P%GFJ}-4;n4(e3yGA}JE~2N^|f z=yW2K@-}^*=U5BNOLHtQ_XE^k;94d6K`@zQjK&ipt(fn3+1lQx-*5W??xKaWmN-!i z$0^MuVQ#LAwYKJfPLp^KK6s`Yj8b-U8V$!>y|T~B+T4`P>+Lh0Wp{5#Q5cM|NGVuc z?1Y+$X?Jm-GngWCoAIJY%HqSV#`-Y{QYJMxN-d&Q&9k&p0TweAr`%br;6m^59-QdA&AEq!>l zutTg%k*LZsw`5pbpmi%`aGh@{soF>xQ;zRdx)p}O_>inpF<3!iQ>2YiG9r@AX{#8Q zW9$f_+DNH+;rXlV?d=l9lF1~a+v%`B7;)Rl!)))2dG(bmy#4KG*xcL(A<(7{F0EaSq34G@xMBVucFpVielTCFx0E?fqo==Zve#v{7jHir(b@Z58+v9~`& z3di#D0!vGCBuUI`uV0|sZ8ILHq?42^H!LspD2(HdGsk%L`PbOp8L+mt!1bM7MuUve zXhhP8&`OdQ8Hh67>wB7+^3NwtgLl-_~FxjJV9B2RQcDQjB_(0EB0}=@S~oA zR`UQ7-(j*en_S&&ay5Mtvi8>HOwz5uM50C$5bF*IKPJwHjtk;wk-`ir2uhl7qLSrX zo;74%>{mCTlkYLROFG+e~z6F%? z}Q1*Nrh?h$Ml~$3)|ZxvdmHxj?K+|u3g(kNQW^g zt&Ri=UVrTpd0L>9p8=jElINa(1)Ssc*RQZ~eT&g>!qsbAY;NtburS99FTBd$U_zE> zoIQJi!C=BO&%90)DO4osbXw>r;f-^b5km07i)T4^?lNazzsUCXfYBty7|VqV8{~Px z?%p0(uWT|&Gftjd(|4 z>nV;OoFy*?6lO$WQxEHi=ZRF?Khd(?4kbrTcQMsKo<+23qjd{wePaq^Mi?_e=?+3F z;>eGl)4ENwaU=jwJLLH`lk7?eu-y7fi>k4fzteu`4b8uu*dmWr0~wOb#_{FTy`WE0&5GbH9qPg;;Orcu{l;6v`UaJ_T{f- z?Sae4i!l#8aGEo>A0bH;&ZZzGSyqt5F{`Uf++{2}(tP*_=ZWG7DFi2vA7YYa#EpnU zhgVo$Uc?e+!IeIOlnjR>ZoBQMPjD6m`+F0%ws%-wp5tBbyw__yDaZ?hmV&`>#L=T` zoH(|Ilrr?`a$%H#BZ(C4c8klGH)*$9967qeiDL)RTA`FbhK{6fz4P!Hc6TRitnYK` zwp9vKptPA9L{qD)#vD^JkE40wcoF9elYATJ9L;1Yu)vM5693;M+eE1rk!q5J$y!A* zqRLG;N2EIeQ&&P{yty?_FOr+>sZaD>z#4iA-Sj>}BRPOlEpJ1n*D!WmIdV!yM9~}q zLE%OecAwI3@T0yoWxvWW9Vkv45#Dfhzl%Vk1NO2|}IiP7R3^PQhNz`f(?@zdIaT%o)%|^grNr4+>#FuxF z$CtSGo>Ns)O*9ia%_av9EP!*gk_3BY2hnd4UE4<-p5wv$&v%881=f z118yZvSN=`^AG|b*3F9{QPcw*xf!FSk32acnWWb#RFgPrlf?60poLB>WfSi@O1O+L zCh;m#M2yobSUV=tU5e~GP1@foW0WSQ&@|#TwCZ48PMTiB+9AI8sizUGdX-f7PL@N6 z$Y-WSj4_$7;nrP>e5ZP9RbvBJGKQoM;GXtO64lL*WE0C&j$Ok`c_GX3UJgS#O?;P`5Fx;N;WEkA z15&m?2oFbhI7X9e7&AfZE;x^BaLN!z9kgmtzogC4FlzSvprjD3oscnHbp>3bQwL@^A>5pj98h&*gI|LPRv9Ws+zCA+?W&6a%zu zp;RXzFn!TcS=dyD8D%*)&*4jCL#{)hh*TRT5}Y+Y$>$107-uX4o~wL7)}&aIhX+(n z@(ilHu((*jS_gGz6=4O8azryhL^0--Yq+d{{TzGlI!qku_$so~g#8KZq&|UmZ40-) zj~f*TVXwciG=!qPl3OGUMq*rj8(;6kOJX#UhI=*JHCyl^WkeH5+>O;lk_^q zq~Hpy&6uQD8H~=86@%$4bOhEKvb;2tJ(+laBLGdy<$MuXnq4PN*BOm2Fc_T;3BOx= zc~dHM_8U(wgOFI02AH$Q10f`_?jvR7o1>Y%fF;T?Hm8-W;c#TdE`^!UNWz#hAt=Y~ zD%q%k%vAN65CWxQ?}NC)hi!uoQ@G5}=f7I%v>Wiq$*K{Ph!pC~fiPy*K_2?dzHp7` zeRtquiHJ04h5pbz2}@{YtT_|Ydd{os%fN(FfL;}xf1d{{<-;c*6FqmdlWTA4VM)%~`MBzH8JD%>0vQQt_E9TyvtYN_N7KYod;0x$RMnH<1VpmxNkAOf`{5%M2CF1s z5#~=#`tPW z>x>^ZY9`2lXcj_~X8V+rZg1Ef;BzBIJ|WU=a^p3)7mOpEbF`Yr$+9gb>9y~M{GJC9 zPH{vbJ6t}f@F=2a9w{`r8BmxZjd&I7G72;FkPYKOe@ZrpbRT0UDAx+Mrw&C$Wp&>y z{GeV6>!%)t5sc2DWr7w>4-2=$;7jNbhQt@*_*1MAg@2>U6WrBMviLusOoo#n)+H)FNV`9$g*u80CDn7&R{wPHY@fhoj7Y#teyDDRzimI=mwGM zljq-2y8f1zo=!%pp##bY9X7P3b zGtA^FQ_5Djs|pPjOd|oL*)B?sDCeSEmxB<#BD1VaoW+bx?_GF)zKG0G6#Jyv2Bn4; zfNCs$r|J4zUb<`(IHea?`pBL*TuxqW2ZwC}NV0qzoTCw~5=DI+kfs|TC6VlS+`d#* z)^w(uMVXlk5_W3z1k4i#NrVy!*5&>OR*73OlKo!9mqE#NBXCQ%F=9w{lY#3`1`6z`&l7BGvZ+l9I9B{F1_+Y!y-0XTARrEb}NwSiG5)SRRxQVo#V|VyEgVBYM zM=_MO<+JlYxbd5Ba`yFY1fZB?8&f}}rX%W}P{l0HQn)cn8jlYX+J~%N;TgkBs&I8l z(B;0p`RU%|JZ3f344^QagjQ`L)$yoWJHTP95`#Ar0nS;n?7GKN$tFp%im?-HKKKUr z<3eUOOYOIV5qP`R=_8Cl?Sx zG8mr=ggABSoAHW2a~UyCuh#M^ev4T5h;)xpdWEV%095U6X3eS6@0j{@zRC3%NUJ`u zCL}?tLMJ!9n-znU=Hv~&%A2u9{c|N_BGtv%Fc=V-*M7&FG0qJDz6?9wx)MV&!}|0!J%V{#_xRbstBr29m45kljzqHk=R~kWO(NYLjR8Du; zPsO(OhC5(qZb#i$s$4N4$;>{5*$)Xp6?`0%_e$vLyLTjv)3?YL>w)mWfKP|(Wtw((}&`GaT0KY$!;s> zyprcNbKW|`bm*=pZlClD&b-V0pvurQikUDi)DKt@)AT|pa{^lSyxHUu@>F8-7%AFp z?tGO_V~vH*+c~uIeeCSNOsw0ye)%^^vy@0Lv(!IKtX8o$CyD21#0v-^xVHHi`{Q%u zsYFRR8x^Yv`pw!C%y#l{GiN+C1ii4RYnmIb+qoGAu(j7vXFmTuW5-xmR5Ji&=zMQ& zMx(JzW_AICa~VmpfYu$d$v#>(Ny7*;XHzD{wctD6`eqaaQ_6*5hBMisN?SODjKcUY zZ*~=Sg3Yg@RfkwD_{ItKp_MqSEy#)?m4jU4G>0R16UtFo^+D^i%`EHTvY;VC)|L{f zTg?re+Uowh_5P~i*mj!bmm&$KmckgpXkyvfzs|F-{d3;9`U&nn{-2UWb6nqfnJb%L z;*O&~%hk;n=(UftH~gn8_U^=(35|GxH?Dq~`R*Bn&|KU6GD1j36YJ}_Z6MI{o|act z4TrojL@Q>lqkKNIReLolQsy3NQK;&(@UN|XKE0jOaJInLa}>sd2CYpg?2wi`NUY~5 z%mfFt8iy#%m^|M?N4}n=l^mh4L(**hCbRigUb;k1I${0G@Bk?taOZ((NwN~48`B5i zTV>|KB&nWc_1n2}NTdqM=yIQ>S!F|;N&g5%&D^NBew^lU4We|$>vIByz?w+~jW3Tc zs+#I@jF#`w>#PkmB)<2Rv0eyl?!Cz7-itWrc;>bLm2xiOT<0XOUHmws$ri)Ob#RUg z*FF<8n8w(QH^e8aJK)Es`Fm%b3#MdE2ZZR^jlRGvRh7(81}*{*l%|#|pF_FNX{*j@ z)T-vYxLMQ6RSf30)2c(Kd6>cYB5Af+!9yDHGK0wlv}~bum!cT^!Zc^-v~HuB9AtCn z(V#h)fIF(J(WbI@D4DDS_n5U_I(ywcZhWdCEI@NSV)*nO`=&dVVa$`lp}Jd z`30&2%%&DX6iM6|VG=03l$X`R_chMGm3_TiUfl_uo{Kl1x>#YccHo;Ss5x+&JS{`L zy6 zAI_h7Qn&t^`WU5S?53nWRrSW(qG?J|?4nfD7qqB0Qnq|KY^lblpnR%ct}Z;ZYQLi9 z>({kN%@?Q?OAUpK0cXiw?h{O9Xt3{t#sSEu!`;b!WXcs)M-M{LPaHK^=-oM;%Uv^5>rH8=qlU}P>XN?Z zXxB}l$}tbymnK!^rBC-${ylBq6Rxg0w#C>HqwE^p#!>p+I~a{GSJ#~+OBGWHq3Cta z&~Bc ziL}s}uT(*0!f)!6l!a2$=HYTmFts~8!?>kc7f8rigE0lhIE*ov!e^eNs0pGViUqNX zgZZYABtEj@3XZJ4o5L&b4o8_v@S7PUn1^9ljuS3a8X8OhR+iUMGP$5kqLurwwSLg$ z^~@SoQzNME8?4>*U3NNwz^VUO~!)cI#+$ zCzMRWcP(+WKoTv25R4{QNwe!H*(8qUXf)Qy^F6HLmS5UB-!gd`X064;g+&k($7^1l zhQTrdUH1N`HOL}h&tcK*bFV>DGl5}Fy#;-4+%+`>)uZsFQQeONxIJN-t#2!(eETpe_K|GIiQ@m zHbbo8VPx4RMh=nE_kWVo7o(JkHb0?AP2nWfn#wg1Or?5k%HL@@vu%0oz^;@-5v{X< z337_u`nqTlp;bZ@Ezs-tN#Yh-H*gk=^+RRiNP9$Rk)cEbXLAa6ajJn5?Z6oI<1>r7 zdK06-y)37qI&`6|K^a8>Gk`4wwfoZDB^H*j_uvAk{5e4zAG4`f)vyV zwls(QZ)3+e8=4_ViINdYb5w$~L@LHw$IjL^&%gFGo7dMlc61e~6uDHKI(a+I#vJ(|BMMC%rqP+& zERV8=V`f0gjlaS7;B^=i;ar4L8l@sE69khW@u#SPX#^=SfT$Dmlwn-`zq(efsgKGO zDm7BsaIG3gR+a_V%WCVP>+rXmB7W0+i|s*5uYHJ-M1WfS(&eJ1I|cMdNM#u_rMcw=V|E1{7@36{L}kinQC!nN2Nf2T?NTU(WnQO=GQwTDrT z1+zBw{b~VUs_Gd+t2S{oU*UI3H9w8a)*{=bhOSHrQ5`EU44uw#dhLT@V5N^NjmKjq zlO3`=qi{J^m`eK~1;h{u#fei#dHnG{Cr+P0Pe$x-ZIc_r;-P~~CO(_1rD8H!N9zt! z#AwxldUOmMCQBJ|Q&8jv=Oju+G#d*v8-AGPU^wK(=U?KF{@@RI@ZpDe*Sp`r*3Ld@ zrimg|BP8EBJxz0#7w@3mTBOyS=lbH0&{MG;M-{5`U^F1W-GS2Qz5xzKz+%O)e^g2gLq8`8UKmQ7M-E{}=e(!sT zM;)$jzCe~*;y6M|;UiAvU75*X*JpW8eU&m`QsysQ#XPPut;*Vok|E0d`K)|Okqwz} zjY#$BHct>mof^T{_esUDb*z>5^Bv>KWp?(SCNK6d&Je4$Ti?g1#_|dme9jPCpUwpH zVO!zRsBtt;r00XJ@2Xb)zTHY(#c`_e?2SjPG)w7{_{L@9$tKPn!5G72l2*qTddd`9 z2%<1*tiE5JBpf}k%+?#P`yLKO&UkMNDUM;SBh4l>8eImXZ3<(NvY;pm@+`wx-w`p1 z+q7FPlDL7jjx5jE+1=$={_#KI_kZ{I=*%x*oa5Z9Z;+>BlBB__FTcWYIHcL=GZ^lo zBR^=ySkDxVWQFu-})u~(l7i1Yb*D2@$%CQ2m2&R5?Z8A zYp$JjOd<5nBic+_SPQHKleN@JpTd@Jaix1yBRuQnI@AA zVOuQCALqqqpW}c0Z~g&xGUD2BpMU%h{~`I#b$;qE{{pw2csE-+TfS3Zqe&FU)BA5j z`6xbTVC|F{Jl4yj0Blu8T(CEK72_soC8qU)GiFd3wURXA6h8OEFda>i(ng&3f;>H7Gl=369ws&`V=9$O1bonBeE??p5m8(4T z;Da=pEutvqJ@5Y>9(?3MjvqgUF_yD$oaK-H;8Q&N>`N3y&Qni6!y|8d*pDp8CRimg znP6q{G}0DC+t2fJ-~Rxe_PZGEZ1eJquk+L=e~W9czr;`e^;(iYu#R!#vlR=Y6-^;5o2;D*^U53M}ksp-W`?xYS+Dd8%^(d%IhneSF8WrJpXl<_SN3enSCLYahf zHQbB8q24Yne0Ran?j|Y+Sc(MWCgk~^?_N%03dVC&2flWDsaLjvLr8&?meFLJ#rZkn zC}v_tAU&`=lA;RH7DY~BECNZV-NP6|nhohLEUfu5Zy^JOUVsJf+oY z((Coe^PKISJtpad$#}%|tu3B-@(Cv65k+B;QZkwhF(zk!u+Q4TRTk#wkkZ#zG?JKB zyG4;_Y+k#l2&Vxo&B>2Cz+qSjb@|83!nQ9e($$G!ODCWTfmS0#1HZO zV~_D0AO8%W`2A1v`;R@#Fa96@E+74KAH}s7+5O6IF>LPBKKLLy>454oIQuxs@=+QK zN0A|8KDqQ6?C>H2MX|S!Ui}E2cl~t=n}Mv?!PL$S!gnp4Yh^?n|4!5Px5gM#xW=@)%nNuI(4o_0pTEtL zNX?PN%P7?(&939fQK~}}>V%C=Lsq;752+H#Q{-nAxDpPbV3O_t5GOHdI;tMQI4%5) zI|q%V$--QpR;xp#BSzyPSJ(H6TL}kGonpMXj&qQYCq90nAkQ-L!jB(&@|mX?>T4eBn{FR?IKX({8oET1-*! z=;uDi>#x1encI(Z`O1XlrIYk~YvfyRFuZn=i~E{Cdh7}Q!uxI`OEVt&o(~W!NPhb> zeEH=o{K|j(%jj&#hkpDgSpCr7WBc46k_tuCTS8}N=^Z&twzrPp1hR7gX-CBE276Dw zPIhS**^%hE_u!nvS_9I~M53nnt?BDZOgT^VakN0EbsUgn*$&pGB=M3b{*p3kxgO_o z#^X!G@e*2fneRVDzV#VWGyG1|^S5oOU-)Ye{Jm~sJd@d!|S~d(TG=QH;<8< z0ddr0Jh?;?FVIX5`g&~LAj`MI;1@yJ*tu$uTn(VFufz89B!}KlBppH+%-&1nmp+f(zf87%ot?+G zNv}JvwEq3h(x zk88kC?b^a?mbGg?F1lT0QP=H}*Tx7%UT(yg=9FZ}ff z|6Ub4su-d)t7O$ur_(%%5)sCwB=It%(K+IH4r4|n@mdA9_R-mbM!XU_-VOa!*IFpJ zM3{@xjSI{-9POZG4{J4p{auo%$$w{jZ#5ygp&Po@4h?lGAUa^WgVzed~FIN`3gZ3aBt; zh#C~6^f{WzG7ih$;CUw5HJpP^`vg)Z?2le0%Qi`pWvorv89e3t5=R~Ke3#+q4Tk9@ zvV5B)UZf~?DT;j>(Hhd7x}_OI6RoTk`-Q?h}HaSmfG?N*1Ky-ggBPP@bU-afXFv17TcSYcsdnT_k$ zxxR6gOP4Nl;`C|K$%HExuJE4szLQq7iB^Kq`Ij)`aXX zc8VcqP8{dZ!3E@`!5@A3IX?H*=XvRG{~h)>uk+(S{nI2zA7KCLGwkoYN?TmO?!ChJ zja~L$9I+iIbeoRhj-*#8taGGUiWXUz^--_CsC#(jzurt9PpuQ;_~7ldTP<{)kmfnV$(V7PdJR#vzVtZ_EdXplEM!rsJk;qo;mS;oP&0}S@}`OS}gj3O)ep7(x$kN((4>2-Q+Zf}uhDMemz?8p%o z=I2P$j8>z;WISU1+Ev!CU1nqbGM6u3Vg1@BS(bC<(pB!c|8Cy%?sw5{wHOU{nCxB0 zXZj7!jIky|wdOF!QcQMOJA9IbqbGTOW6W2de}itTL5||-H?A>GQ?@s+^UM=pVShX# zYRoZr_z_(547>Z_noTcd<5OZ}1YvrWD1{*MJ+}uz8$bVQ=s|-f=ropD>Yk$8T_cYD_}$zX##x3jVIq^1-dC|c>8K=?pW=YrTC{U? z+C4_&0dc=a+-@@*j#x4oJDZy7`G*U{ek?e0>#vyTJXw@K@Z*#|yEq?m__c7kz1Uu%_kH5$pSGQSS zoaaCLg}=nl{k8ub-E1+;QW{Z0|M0sQCLQuCE!vMLFoNWTUF=IalU&m1^+8Bhm+mKy z?_p>6b+!jDkhvi`Rwz|Y&9WYX;>wwZCD?G9Ek{@e!`H~NEsu$F6ACjT%Xg|M*8cD% zUlA#FV6MP-W%6+b4s>g-S{|dUAn>pQYjawSqcq|rMx*m|+ox&7%jEekjcC>TA2RW6 zBn5utEdnJI#^cL0lY^w$7Fu?Q<39U?Youw4mQ6a1)6Dfx&~2|Wo@AUmcZrJ^zk+pe zdWSzb_#CXBb&nP|iHOM9#xI7q9%z|~iu zrP*vUf9!Tt(&5CJJ2-ax?G&ROE?&66r=NVC4?cK`kN(BK%m;qr=V*2NIBPM$D9dQ+ zh|bFW42J{k&IS4(=+Js-5Brr1eC2mGVc{Ty{Qg<=cM1kMsR*w|1Wlwf0on2UqsL zs=#u$?9#K>;8{P8d{f@--LKGXpQhitoAKl-&Bhwe7GXk_3$J$8hj z`Kh0v-D)w(G71NUbBrbf=2|gZ&tBuo3+Fj?$5B@AxC@(QI0H5>$cH=F$u{HNA^RH{ z-~Y&+{LlvbWR@Ui5Ew_e#c>c?4kSE zn@sqf-}?7_{9pe%fAc^8-|&GS{0N5+yo05MJGj2}0-L+fGf8)dVu4m6YE@PQT2m1= zl;)QWf5ZOpRmuUEE|eTwTY^bznxcl+y49C<;pT&%1!tYljCR{+FlNLgy-Hz*bXuqU z2rAt{ph6>rsA3GCjV*u%#tw<2d6aB1$*uu0bDcX`Ubq8e9Zx>632yCUSV-@iO$j@hY!4y z<;A<$*m{o5ofjCV8|VnMRvsi;`j@pT!78fdN@z;mKMAl9S8iDg3EL7ge`_!8rxS%i z@XjHnCe1d;iXEEqT1fl|ACij}Q8MN1 zX(su1zwt5dn(K1U?RV0dTjHpQh=e6BQnYo<<(B8a@I{W_c8dA=c@Ig!VXQ+6P;wTU zEfE+~5b2m!vxn|>*}HOy<&{IM9X`sx`_13t$;ZCT!d##CK75pq{n3~B<^TEr%U!3A z^S}G~pXI&>9-!UrfwM^K(YTFHmt#kcu(-HHzt?4NFd#2{!-e_&9IGoUY;0{Y7)_AU zLteJ`M{JH0Zf_q)+_geuFXQ{(`EK%tWd76%;#LQxBZP{OItt-&a6)orV}qzDka1K! zoJ4ChjwgQaU-Ia=OZ=6;@$=|k{bkbiJxq~s@Pj|j_{3xAg+&q(@%D%A<^0v_eDcdr zaB^ddw>|g(E29zZcAM_vB8S)B#meG6tZzQU=FSV``3721%W+JNRBsa18##o}%K9Bq znqq+hoC~uQ%WZG%rGEae-TU{-`~^TGSz)ewFG=jj-)8wX&KZ(u4yhWxdQX+Z2W3@+ zR3-z$J&@iw2W3QuD!Gvoz8gyDMy6qMR4<6+7{cmIG$n7khx|_v2?_uHiQI-#`fz22X_89K%;D+lw z{>k6wkACA{l8*-*yzNf*1_P8z6 zcDojSnKFoXqD|GfVcO6QrXHT1(JZC*Xv7CmoW8a57^SoAkT~HOryCT-h$!lj#7iXc zvIhwY-yhaTBK#6J);EVzRVg$D8A>&fD#n;Gsn}s-`zcNx{V;dmbvrM9`7u8Ci9f)a zl=nXT0Pp+Yhd6TNC_DRmOa!>`m~$_^#Dfn$MA;Bp%6jtA9}8!_RqQ|+MYGu^ZuK~N z&%>-7KE|*A*2j73$*0M8hnzWioC8NsvUKPq?->mE=nrjh@!}iY`S81V>8p?OvETR& zzVyl^WSsD}`|jo)cb`U@31_o}ANc4`aMxXTarnR*<21t>L!+Tc;sm8U)ZBM15$uik z5YAxo6t{H&Mq6xNeU&GkxWMsa2U%L}arTR!;IYS^rPc26wh#Zg5XJIQA0;JC9g&W< z84a$nc+ZE?lh?^Mo;100s?#>zl9^Ha49t(R+1@`s%<2XED-ebchg zAixP)jb%SP9pC!jTJKnDng}Ik8XeRN^_-ZtJ18OO&Ss$*nI(xEOeRCJe88a-r+DHs zpW)iZI{ik2qlb@^rx|NnFaA99 zUwoYNXU}q|o3Ot(;OhEie&shl$^Yk9|9|}b|MvgJkNoHlGuLY{NhfUWZnC+vP89ip znMw+b^C9PkR@iKW8*U?Q%G|MgxMSR;p))Q$_dHv>V@A2#PFymmkPLi0<1 z{jV??jQCgo?%y-cGwwWd5+eoc+q-O!Gmab>lJ0ELY_-XZicnZ~&i^55_za0y#1;_JIqSoA42>X-3`N@=O7tMW?GIFr@hwmV!8*N2(5y z?xSQB2+{aXd}20m>Z<@nB`K`+T0$s|M&n$LGZv`}ws&7(ZRtKv-+MnhI~#oFi(lsA zwW}0P!0Q*77{_QlW`3d1`ua7t&%R2t*C%OpP(mUsp$niuNFT1nISi7_6r|aNrNw2g ztZ(qiPyPYJ{avIK99mhV)r`Rz)~{UP@`dx<|IYVd(+PGmLN6@P=q+%j*XPukJF(Vq z{*@Ove|dwy_=6wdhu;4#ny1e&PE$6vEc4wic|Kt<7!bu8B|{@;%Aq+9H`+$nj3ON{ zdi61M9MfDo#`5t2uYCSd;z%>v-D0>uAnEz+cpPa4SH6VZd6bs8j+^Y_Tod#XB2oy| zMmEpD@EK%dgxS7=T=ktgq9h?|w>aeBom*S%@9w~%Lo6L$Vdd~)4&8e%jZT|a&wUo; z5T$fg&OBQq?zM(>4pA~iU>@sg3>3aop(jd$_$~<9>Z*$e{)QxtHM*@+SeucV0Y$M( zq8Etcg@C6iaMifuY4PgRtn$f0|7S{??|Cyrw`n&IGBhK0_RsVEKlouj`P(1ocR&3( z4lXb8L+^V#sgQi~E6=mPwZmD=?8Fd$tTCzCTCDM{>*EW20VeG+{Wmp*{a7Bih zY(r6yPb_(nk>!TP1B*QP&Uzplgq2%V0`6C#^*mtznLM66tb(J z`v}=Vh(#Yci(14B53%*T1JV)mTw{DDuo%Mks(|wW-Ke`3XDxXT-l}=Ga-qWu}sL)EwcO~ zSz+1PSz@7o8}I(!5Au;8{vwZl?(@8M;S&9|HTDKW2K#%Er3fb(j)q)#^%WwSaNxiJ zE`0tE$j)D&p_&+BDO`bZhBO_~z5gK|`9J?RTv^}Xv9CNqI+;|qu~3Thmo9Ve$~vnn z%k<~_{N`_bj6(-j`Jo^GC{di?oFyMm*uHw1N5Aw%ws!XT$shY+(ng03(WE6Ltww{z zxgNve9>dW#aiamkVL~B`@3bW-@(GwRs!;4c^Avg|roFU4I=+suIY-xeEOZ;Za&?cZ z*Veh?-uu|!d;|0Huh5JoQp|fGqD_M@v4zbQn4Iy>9xwjeXPMvDB)t{T5zhKha~vt6 zewS9eIrRku%&)ByCkf}zJ&tv|C{>mRyP7!_GT~NKj6u*G)QqQUIAz$s-$xB2RhkjE z@X}g$NX?k294={d+O6YsS|=&Yh`qt{B=I86<`J@dmqaLXw;MoYaW!ttIfJvgpW9|K zK%!KW;pi+-1 z?D?y>BIm%$JiShv{>BFB>#wo>#;fR9lQO_LM?RTg(v(_Yni=X9FUwV?C`>7u%OWN$n zCUL8cbB=zeNu(5)wypsNsrM6R&eQIu97Iv_OI5$^xr-kCMYah>V;Il0$fUDZ{+FKD2# zkq}4?&-uRZ{oW^NAP719;3{u_ z?=GiLo#In}_7~`-I$o#{x{hvG#G1fRBNvev-83lF>I~d{nw?vi*2sT$wERi>$YbK9 zr(aVN^NQ82EK;=a)X=vdnRWDg?{JORsx?PY10+NBz{0PVRsv= zSip*Pa1~*nBPgB9}GGZ=b~p|=JY zWHVJdy-o7jWipv@ls{y)USYOY<@2w84&5}7ag68sM1hZrLcGHRlp!Ip-^dxoRaeHlxuIrJlOj4?u{O50ehZmnd z&-t^b=(U@ydR^S<#ph>0tNusEa8|)^yUw0i{w~?}sLPMA(g0O*UlyLnWEVD*$ zaF1gCJi}o~yLS`YtfVJ0BBo8>J)qk^L$y+4=l(5z_rt$sfAs;M_{38zT)apS!~}Yt z^Dn+cEKKsbMa**-Ks#Ors32t6@6l;Csn5*d^*ZDPT$r0=zGzaEU20Cu=Kdio>s$Qj z=fB}IS1$9$7hYp&aTYTkBHNNyyUS1h*U$LX`yX-b&I;%n&wctO7M2!KaZI;2BxBp; zoD73OpHiW~{OlYEK^TO1{*WLTB4tDzNxJ)Sim$b45N;&r?PR)NVHAqn%|f<$eqoi3xP5XRHvI( zmt%&_CatYKtWuGg^Jj621s-nx5EZvlCdlZSt|2r%X+(>6 za5o^1F*GM7<&Lg>$;tlmY( zbcNn<4PAHegC@Fe6R814oI}b1wpk|#)-la8n&!|Q+@+XVCK|f9{w|~5a$VE0tUR9I z1fX?rfRo8EW`f_`ynT-c z8#@T0V`sBG_wviU{!hNjsfBqg!$b%uWHZDnV(rGSiTxg(VihH9qS&BR8E33k$I4`h ziRrfT7*G8XaS$T#iT3Ve4EqSTk3aN~VMr8)?6e2`mtWoC%x;FS{2NKH-{V`~`VQCL zzlP_!7^aD?r>HU^uxy*j$r_g~J;m#9{0Y^uWp=l>*?IT?9gW!a5K%;b_mI5@>x|7! z{U&5)000r$Nkl#=qJKKqR>pFO`!ECV8MfF?cq+Yh+$>s2y_!L!d_VdB(Tw0x2J;;BSVK@7Tq zZdvG-L!nf~v2$EloMm&rMSn2h`rQ>C?e6pKAHRjB>1^-qk+UtHzj&I^$RLX~Uisn| zSzK74UMZ2YO=1M)LY{-I6`Gs((PhN``a?dteur!CUqfjoV^g!7IlIg=&tB&8l`AYR zodd%r7CO=S7YKWYxCfh9kM7gEdxv)O9{aYzsVlS0FU%7~AGgx-wM3>9ucv9WZcHq5=hQSF-t7*{atLkj%AMgq*C?rQQB4^gn?yLaQ$68eo|+ zd^%pRPu7{E>u(bTEi_>fMZHuaqNOv2NWm)+mRU$ZFr5Q*|A5lcSyn#0%KE)KoOXQ@(Te!5Dwm`B&Z9}d{Mcbkc&vrL`4NWXDFduNN#9g-{L z(DGScd+{sd@MEwj9QmV730B9SVl zHdaJQpRJYa5C$|`ZLYm{jT<-au-zK6({(A_UBz9$&78Nw(0PQYPY?w^}!0)-+7zRPY}Y5<|97)^7A}*zW`|A)3&!?HW@01VM|FstMF6&X6aCb5HCrG|fh-2wl_D=AsO? zSxpY!KSUCtA?OcRQ9#z2#`CsQ;G#i=+^nyJsqXKcvzZLoZ~K)F_9?cNG+ z{m<{Amuo!t`8Rp`$`z(BTq0X4p>8RHZj;%$Sw5dHqGE*~O77fWBa9+WFU_+sH;t|$ z9yJF%_0;oBPEL|>Yz)Idszga?Q~ zX=xhEHV9*d2-<|5ZB{q>{QUMIW7TmgGjmK%O)@pN$eHt(=r;BVdM$i+i0&v34pzu! z%hV^%^5rkR0kNWcu*X|}_ieuY-5>DUo3Hb!S6(AZ5zM80jyJ#jI+KQl+vw8j_4#1n zGkxwfbIYgM+WQ46Ze!~vkEvqQpgEyr*+;IBqcO@j9rs#jNh()H#40-4_A$B0DAV;1 zU>Le)rUxfe*tv@z>>v;+!Zr!AxfkSo&_lT6s(A`24CQ|wIhIbixktd{| z1nE2K_8MjQR1Bt>AsqJ6yL;UF@IG5Bw+WTTGoOBi$%Q3i;JH^`VRCMPncrQ*bwjcO zDy1yt`V3B~im*1(Oq<`m^Df`|*>AY`%rpGezx)?GeenXhYK_kJBew3`z|b@-#{!`- zJy|7Rs9-o2G79nfJxWDErdp*~ETw(l0lFrbu2t}deQv+|D>m*w;Qe>5va^3cpaeNf zr=GJo90tfZ=G;;pQ;+Gj`*^!;iscMKw~;|Wt!UBd?Gvtf1bZ8V?FLh4F3{ZH;rzK% z6dVn`P~*adFEduIqQ?^1Y2Y4gak%yXwRInR(BhZh{{iRoHkOk`oxP0bhn#-uBEy}1 zRChpQV~@O<;Y(lr8j1l2t?NmZTa0dqQ46XhP;E3h#5SvFTGDfWQvNYA$QWJxk?iC7 z`)Tlf!ipz88FW7m<9t$wAyS#RjAioV*G)3UL~@c;LLnNN{2n8%v}Ao69HI%0C>kX7 z0xk8NMQ6lnNSc{a&Uf0pp<;-YfobL#9yHm!{yv@cRYWWpE0;L?;-?Xs4k|_$2DOPv zKKrRF^t*iw(;`=?QmNH&eTi-rm|a*#Y8fi~2kdSml``iLdJv41;Vw$N2mLLTJn^%wjE+ zQIU&nSO_Ih?f?>Z47E}Lkum8W_8Fg> zVCnhGES^8Z=HAb2uGYWCXIM@iHDLH z1#BsE`*Y--FGYlvNMq>P{={CA%(d%|7WHT(DS*CJknc~bDOeb@syGeWj1cqUv83v}Ef>zKl4GqK4 zuq=&Sxj?yEKr?h|lM^(1J^s^w_>X+>;YUaj^Ot}9SA6A9zr^&@pQN^Qj?VTLgKiTU zMmTmB83mw1nvG3dZIN;zOFomK-|rDLw#is9TOa53mp{eg{478E?R6f0^blP@JJR^v z#YKjVP9iz)brHHwtl21h+@VAlArmu`1nv;KP{PWV2?8JKdnm6@5Np`QDKwRc^n%dm zS3ms;tww{xy(WvbGHTf7#j|r5PJyoSDGyq>?l^;?%hdb=W2Gv61^L=ITl>EzlnpYL zej=qRkE+zf3G_Y&9A}a^R`_XQ_eg1*)+qd-iJ|AQ%n}1{J4KS6SU$xGUoa7*sz2PC z@PrK`jz@5kL@u6K!Y2(ziI>x;`CS|ZR)VyNek4~H;`pSDg1A_rL}JN#1hr2M7o<{H zW(G~u31W?&FzAGWaZM**E*{(1D}hoHB|`!~K*SOiTI9y6=`5$vO@k2yRv0#hrDNI- z>o;z4*y#}I22M7|UZ=-*|Hpr0Hk;-0%daqX<{Tw=K!0x!`~gDgSmrEpcaz?rLA|ns zQj%_`&HY<9$;%Ge!WcQH!1CfOhUH-B8e5y2{N2xQ^3m!pfBxwu>N69#?H+F5r#LZ- zX^!*gV2xURmc_-h3|ehOWMJ4i`u#R>Fl690=y!YMr!JujK^#f8S65iuZ(;&;ATU*O6+#e&c-%GbQGxX;sphLL5~g zVl-hRrN_|Q#WIQr;Sfe$Y^#JH>|+^Y1W`ZvyID&48OO$I#}J$JAviLbdcyAvV>C4? z6%wluU9&K?{84NW$UafnO|+B>(9-3T81+S{@OZa;UvNujwV#$dTN5OY;vD;Re zSjPCxU4}~XgWq1~vLEyMnNLs`B7s5%ipcHZwmW#PpFH`>McSKdxWjIiqExA%nI_RtVpuj_w}lJ>tilAHZYsz#P26^q_ddKu z53rsFw!0B{&cjXS1u^fAZ+}c$ePqv*% zr2`is48}4xeK$lm9RQ-xC+v6dIz2j_A(8YbSL*1tLwA3V^*i^tbLTFtNbu4tU&PQL z9J*wR=~K<^ae97=X(OU@(7+Gc_?C_+WRSfk?|uKj)9E%j{nRrop1VkPa+b(*(X%=1 z(inq&pCF1@Ut8zy`Zgb}N_G#LeDRrO^5Y)ls@TOM)7BDa=ci~lc9@u|Fz621UEgB* z^enkb7NLdYtQtl>gN#*zj<)j%O(#>GW^8H^CzEAHDgxhQdvk;D{mnP|?hk&1Lre;UH zaXFHckL2U2?#U0^gi!}g2*Rj?R6eeMfUYN|+@lnI(%&7Y*TTr0O{M!eW(GdV!w{GW z(4H7SY@_Q%O4baK9O8#fVkD+fPDAHJDgb(Fh9**Ar8u_wPh}q>1xY514DAH)UPIR< z8K+LH6jmm~Sbc^};3ISm-}4fsY8<0vgo<_StixDgj7(_)&2X51;T4pX#TuW+$d<_! z#tHl;p5LRCx}e*JM!i-+7PHvgMl(z_UB?e+@g(Fk4oXQrdgpESKDy4i7hh)L^f@y1 zDdJeMvvPy_+#-9syHu+cG+pN~*4g(3Rog$wxy0<$1P&F}9t6~<=Fl@OaJ!hzM>N|l%CnP1szV&RI935Ig#e9UK#6fg z!tz$cXldG3=*RJ-u4NH%@?bJVKDl{fg<<4R6#dehN|VQ)WFy6`lIU6vP17+9bPK}X&PvHq6$?pGVnOEMM$YYQb|nP!OCRu-2qV;Btk#e zO>SaslqpMXKP@Xs6vznOuy6{+qiuY5h?U9GXf)_{x<`r!$I!_+X&=0%Cq7ps+D3uG zw34Qw!N4aHI@zq9x{r(G^OMkNg{I>L0kKjHJ8cYI!w(~@OctHQeXx+v;rl*;AK+xO z7`jFj1V?guDI=6pXu5%s&0||OVKhL>AwoO(y~MxwYy9!|N3Y|@H;n(#J|5r6$F@p( zIy6y0N{N~3y`F@jX&RYKCh<$YapPv(?R1U~Ee+THKYWZ)B!BE_g*dLb9=-AL?MFlW zesDMPmm*CF{NIFs$Icfg_Ma{X#mD|v{0GXrAAd(Yw%?OmiQn7$c>jN(`h0BR@q5Sp z*xC7m=j{LW_&=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81R4_?IK~#9!?Y(!fWyg8g`RhL6rkCS{ zHxV;~Fu(u=Nq__hFoaPlu4K!lbr3Cy z3bdF5M3E8!5Fm0IU@$qnoZq|or0)IW-284hHw-|p*;T;2drqIP`}?}T?k{$WFMa7t z8bAnv=XvCG=;aPe@$pnp{cGX zc`fbszSs*-Q#VhVk42MDJJPP&w>r|)jze7|y3z-8ES2D9m1fhbXIKq%ZeN-(X+Q9^ zZWx^w@bqACg@z#)?fN-bT(#DS(g(GDXoNRNHKjXv(eSP1N8JM~xff{jilW2BXxYPv z@H)W{5fu^p(Yan3UL;&2w5c@%!xhR4m#FD$Yh0uBE$YOp?VD}`Z;qMMJ4ZZxkv0f_#YU{Q8rd2!5>NSH`{<{D1S5aq5PS)m^!Mo=73uudcQ4+SO|{5&JFW{xu>erL4S*(yvZ9 zl;K4wwYWxK=|oF7QQ-ATyJj@#2G=OGYkc>^G*4=2+RZ$XgYICn4h+I}UAM&#cxCMc z#v2tC&`&$9Cd8W^(GX=f?-%E0FuQ?oMs;|!LazLGqZ4UQeWe-<3Zm}YS|PYBU+=Yi zh0mpIFK244QA#xxRiZ8gt>{pO(YQi3(qK@f*M;lNp8Vb7bTby{UW?Wmv)RLPN1ILz zr7$gvSUf>Ik-#(!gpid<3m5E%pb09!~v${%hc$j1|S%q7&Rcocu zG$?EuG`hyrR<=iLvYzI`)f)iFl7+%B3{1@Km92@VX8W1A+nW#T&p=C560Woa=o zfun>_M5SH%*`NlwpT0F6+a`UB$~^6!^}`^8fEAT?&2TlN0z7o=I7d$2#<>fZ`141f zU}a^6d_GSQ1RcK}~m{|V18*!}Npftkkg=re$)ryaU=v%*~9qqcE6U}ff|L&D`?Z(w?H3@2; z9lhlwlLrp-2Y>XZT)1$7AEx-K(a}-vzWZ+W@892Y^~z*3T)uRfcr3=-A9$Fj9{(#` z$LVOL=p+kwqFpn1t*lkOz-sJIzkO?0dYN?XEOWh1;z8hA{=QW|wboS!U*lF%{&0L^ zl9@wC`NKc{6JCG)^&cvx061~t1QQbzm0Xg>|AHVOl}vHhU3U>E#lq?ar|*7COA~1; z=4xvTZ$i6Hb)$+oQ6_A&{xxH`DCXcOxJETEN5QqFj@e`XqR_6Lg|l2_ZRNdN3miLn zE02BuNv>VJ8mTjHWHC*X)2B}(gdhllmj9I*+Y;J849~xz1YO1Z1up5!28SOd^ zMif}B>ULw7k1`3O`XJs6T%+`>{mnwO-*xDgAiO`^9yT@VdeG zX2LSdFZLj#HHlP;tIO+=EKhHANhXt=Jb4nOR9AYB5CWw@7zUPYfQ&af9-_>A=Qhc~l8q+XvBd+dIiQ11jw-#Qf zNP=$r)~%BJM&ddMc!S2ZsUM>{Q6>Fm_zjPYkUVfFL#9J|cbi-;j}U^RM~`y<{r6*< z<{s`Y|GTlV!K05p%GTCa9ZV@Dr%s(hN?FkzTH(>mJf}*|MQVZ&yYW$Ua;y!a49YXz zZU4K)^^KxkuT0Y`u1!7P;j=KdDd^KYTPPHW`okS2QZh{f1vO_N|+p zszT>x$gXOFoz5)fbbROSkYkO@?lnpwlYa zEv~gRd?WhyX3}nt@?9%44rb37Y?+yvVS0MHPWS0njtqkybvYb(&--3VD>0%Qc-@MH zQQ-}uZ&Bd&0_$ebZV>%zA4E7ng>Mi=2*I&q$1qK^XA^RTF`8JS+O3G4N;ejks1v^1 zmA&06+)6j;cJlQ@qbRiN1iM$-b=zmN_TyTBx(LCL0QbcK| z8N6nL-w9qbMY+>T9tD0YSe+J`sPLjPXeZjW6{WP+d*g|CbBZA)M-CrC=rGr!u0!pZ zxBOm+x|G@QRrDRFl{j*(iiUIjDHIJ&aK=YScd;J9HR(bd2UR zu`&Z|-dF!FWp9`M-)dk43Xo_hW#?%fCLWCp4KZ>1ojCE@lM`zZZ{H_bEFf}O08|;j zHgxM`Q*XBYMv;F9?W}88Ze~0E;L%R>9ArEFl(sqFq1C3;L9Lnn)MuFZ#809tD|VeQ zQe*nml~tOO(Ki+ZjOc(}VN#Sbj9wH~X3>DH0`>(Si&hM0X9ra*aAb0lgoJrB#;P5w z9*$75DhWh|^_m~q88X?(E6+3b#P>?sef4JEZmn9aXconJHHbm($Li9pqpMZv#!=S~ zyk4D{?eLERt7XnNx-`*hUs)D1nL-Et-ntbIs#-#IX|*=c{Ee|BcMc_aC7op{U*t7k zv7)tr(r99N0hKTC1%(o= zmdRwy=IlrJ+va==DXVi#hz7=}KCcsO6j+_MA6WgL0#}2@UwgLYR|LVvO(< z648<=+L<~ViQ9~J?clW=_$UM3Y{wW>-=cW7qrz)9iKBY9qndT2`h1$fYX+-jbZsSc zqNb=~0Y8%l)j0Vp(`?T#Eg&W&C#FW($me-|H^V8{!%&K~T#kb8lW|>QL4XPZo?KXB zIvHmskzhP#qkX~or2tI!5v*90FqlLtGoG|}82vAzr+7p*D!HmE7B}C8U?=({A9^jZvTQTJ4y#?CS;B9q|5(S#T-$~S0&L!t6FAhZobqt?-Vtnk&*~BL791K z{4Jp`QiBe6p31JL!LkLfEo=T_F{m8MCTc$)uoEmQyg{2Go3+!*{Q1L*Yd>*egQRDh zuyd$WWHn5VkMNc|j}!P+{7MuDpmb0v~FOK>X9|N=64A-K%)c|-JtA!*GeN) z#bXh+qgBOOr&XAlCzL4d7}X;{g@Cof8h)@rP(D(Ws@~nNU!Y&pVU%y9c;=hIYJ?jV z*M9Yke&F>&yLRGbFMTsxy=ZDdF-#0QhA^!cU*x`yDPTf*c5~1Hf=z2y`)y?l_g$O+R>D=|H9Ww>#%8E-F1WrnWKDCh^l4G9!fLOV^C#~ z@S;wRMtoXLvj4x~+O9-CyEX(0NC8Te=A}l9P;{wfl<=j5vXWbptF+cAp=xEAQYUp4 zMxYT=R75qQb*V{>MwK2*K!v-N1`MMtONERos$x{=_zq8F5ByNaP=Tr_>9xw(AmX2H zhJ4&TdE^!bcH%lx}?;W zm?dN(S@MqSst&FcnOu?cH&%(8g1BW6kH<(QVib!Gj_Wc$I!ruf*B~fM3|DP5bfZ)U zN|&}EQF2!Vs(kR8qSAN`v6|W5yBWMz^*aqnBkX1Yi;eK2!i>_lR!tIrI?IwJ; zQL^orpj*1N&H1i4@5)6QVA?=X*$u)~IVgWvnxuNqZa|qiO3WlnuoqS~`TAq8@Wk00 zT)4i9L}8#v+9spJ2^?QBJDTJJ_us}t_uawBP_m8)q3EP)Wat`akJ4x(+;Py^$IU)dv6r3-TD-Ipd$NnMJXGhe00SXp+eE5T(4}7)c_@iDJk4#rdV9r;Gg`?SNYZxud$mggnEeb zLhF^3C~cxq2x;I4KECU7eQlS2^Jh=6k#_j>2j0f91CteTsg@~f@hLwuN}N$qzLlZ{ zUo>?9MP-VcWq%)}<7<%S;hSx0ely|iNo}nyRRe74w_$)~g-UNZEJ}wvLTGUUEme)q zp=)-E&>!J@9-sTl5BT;|7swU8a92=@pp=!Tyf7mJAW%L+NP<9N8Yc6bMSklGPx9U8 zF7s+KjqRG3qhM7ny$pmb-SXb`2K7WdkJdoA6>6Se!kS^QKlift=hB`VWL z@qsk!cQ^P(ZKGe>b%NX2580{#N-JkAC?QQSEwpK%4GCr_T49)ASm?^X78o{28(~-o z!ve#=^*qj9nCClBzKY`(k=n;J1VTtm11wV#w+#e7f&i@og22NtG_iOb+l~Q(7hb=? zXaDdo$mSiSVId70!>}+63n@$giSS=TT1aUE0u`w0j?tjxHVedSN*AIja#3vQ&Dv}i zXxM2|w40#K`rj(5H_9T>t0gOn65UN{M!QzHMxkA~G`;7$&N5PYr$ZgXuo0$>kOo3Z zgi(sX_55&WC^L#_fN7#jj3P{%?>_z#|Ho(ljK#Gb3@I_KIF_A2NQo4Zm>oxBkW8k+ z%PdWSWrWP>IC&f=kB}16FuAg@!3!5|AS{VC1V{rzh74ks7)448X_y!?v`Sa4QdJ*D z)Ey#|7rkCA%(6lQTvmIdsqGUZP7XyTe zmKuZs%BN(n1*xivw;>5Pqf(%thV9KAzVw|JxU{%QERjUX7=AvFX<7^o*{C2uNJ%P| zD6M4RIu1@TPY`%0<)cub<5;%M+HQg0`uw*!eey6fQ)8ij1Zu>#vehi~i)bM#%C}({ zrRd-2c@VvdMvVi$Cw-+_n{t$Jh`($*aNYE`R}rU8h2HvBUI?0e+mCUhRe$@TommT{ zULFG>8zxRk`9_642`x+@Ku8TzqFo1p2t}^)@ar)5;n62v=Iq5Kq%`n+mrN#$KvT#& z#4H=rvJnCd0%Fo2>v$9jc`VBYVW52%DGglLB^I-hhRIW}E%2}Z742vB7y&nO$}HIoghaX@%(eKDbV`4()fT zPAh*uxVEZOVT`@9R%z9$Yg2}kRECpX3JFSvTD1ux2ue8|)#L~vOdQAI2QOa1N~AFT z9Gfef2nBZ@n&I{%a~#<}!`4oYvC%R1O;0c}GQ!gOCSQ5%`=oOP;&zOyYujuW9Ku~F zKq((TfZzMdlZ=m~_#c1zLs+I6?gSsAhmE4N#mVSP%kt$v{Ug5n$Tym{AMWNF9ZwJ(IgXy3 z3BCVHK`x72Swya{Kq)<-cA|E2vbDrlYxKw{-j978@8}7%2z^rat1n=E?_1zFVYPSy zVOdo-Q4kQ^dI#P+-$#%d03`}x~H@c|Cc z&5=qb5rIYs6KUBX1$P`j%-c>KWpitbOfJilXV3HKYgf3jokgKB3=5&bbv^#*n@{uJ z`|sq;>03aBYqC&f6R|3p7-Z$V+r~JlrsnDfB9?zQiYU!!rO4g zV|DHba%&yq>BkA~emmZKKLV*?D*K}65==~y92w!}g zQoD1u>R01fw0jnXLE3rT&F;8RfG`juK#1^WA}uspdExe`LD(^ZVi6gOBLpbru`s{J z^@VjZxg7aIkrVsI_-{V>A?| zQU1=sX&x9GMhe*We7?7p=08e7?!!Mp;`(JoCSA|45v)o5?j-HZ&rKbCbt_u^ClykL z@~=jC4yuqx2`Hp@aEk?e$0J`T;%Py8C(VTm3%IUFu25h&Ve_dEyqgbv@$e8q7;sW3!YdbU;5aU^c&rqVSoXrp zP%f6?T_0t}5G@>h&3p&lnk}W2T)cRZlUJ`2kH<;G=DW1<3 zcrrPJj>Qp5p-UndPBGM78pNGidiUy2i4t}L)F08ghd~;Z?@D+_=`aD`MdZ`SSRBK$ zkjf9!R+EC%s1Kgc%us@huV15>Pjh^Dh(iZwc>jCfO(Kkody?9z;$$5c36x%Y`Bg zkKlg%uc0QUQ1L`KDYrJTzwrg+jjMed5ju@)t3|JE&bJVpPzqrf;CVQ?9FITwGN1d}lSpCk-jhc;aQqI z@1NoLEw>O$q)Pc3ih_VZX#zJOC>BW&uzxtlg|!`|G(#(v89MI@o@Rb=mC5M|Y&(XO z0xc<7&_bM4plX<-x?}We4Qa<9j#FfJH_eS3*RgGzp`jsCsU$HwRyn04{7zz;20wW0 zXCtP104z;eWq0k1Zts*U3Xn$82I!ax`Y~ z*3lHhra|6^V{sdQY=kR`(Co_}gdh=GmPb7qbO6eVaG{( zYe&Xt*9eq@0)y~B&qMhhGL-_~qqwt6VS5M5nxN=-T)%RI?>_n*U;C?gab$*FdD#eH$L%9WX;4wEb zhQ7QKiU5F80lx2XV{wIVKKcUtXD8XtgDTJp3rW~%E}5> za)c8nPcS+*hU2)nu1h=~BN2~>cMk%tQy}fS2wRdj@&s|8`Nah;UAl;q%aO3E{*2l_ z1zO{jR{0^*;CMXFW4l?tw6?{qsRYlbv;3XI`xrIDAx@eGfA81N!s@@5X241pR8=~uNT(&iK$`!=7DJ@Z3}=k$K_vKTV}|p9-aD;sWE=`pv|yp zvi|G;h=25%pGKro{QBuz7?qN<)8nkX^FHo2G-IQq#9}diZDJfxhv~^NDf#`yb^hJT zCcm(Mnh#HnvFrQ%%B3Z)rG`WI0L>Yrn}w_AobRTMG_#Lu4Jtq=Mc_N3i4ahphgT?& z8cvbl&2Z_$RlfJci#+wpRhBk0_<^{5G}} z7@kjhbA#38Rpz&{OJvYm+49}7>j8Gg=fsbw3VV;r{WO4;A&98Cs$|9*`tZJUr zP!6xvDrAmo;9=R!-a2co*HSDNdG6U~*xKA+Vq%i|L+&|J{a<>|{Zo|#XrS%Q)HQv{12|#;j?Sl|_ zMF(7$VkV6t!H(PPY^B-S%CM8pv6Xcw1OlbObsciW0?D|IG%YM)AaVufW~VtiH^a%3 z$Jsx%5AsDs(P4UGlDFS-g8Og19pP(|i5L@;;~*p_CdQeK#|V^9GL=GU!O?wVOpheE zvartE-f}ve=t`5#WLa5QVtZ@57P+?OzJVkF=`iIsm&>ufzQ)MN2#G|3rKKfSmX_Gs z+GKNclZAx^Ha9kyoSek>JeC$0DU{B@YN{v-f$`c)u(8H}THoQ3^=&+*7&c8lIXlTe zJ#mO1pBiP!_4xD6-O6`Q?4GvXH_fazq4F&PAE^~yHbZ7@ z4a+u(C1PxC?C{dri)?P~lFoUo@8&5w9y-u?zDKTDKxl;$lKAi_D!-0Il1wH^jExXv z((J6SVS1YVGqZ?z3aJ%Nb_h#q^0_Q-5b(}Z$646i<}WW_A)ieHf^^;|lXEzFKC3Y_qty%;?Avep6YsHwK8ZqiDiIA$;E_kw`E)I?9b}*U07by!7%bC?WAZkIAu7 z?!NmB`Fx()efv0n{yd)NRe~J_MxAvAKsZHYHqF-LH2-3LmFLnqetc$}+lP`&$83J# z&@4BKE_TfUTx+gRUTJ1+i($jSSDNo`W!Ul+$mM&s{CGdJ>pUlFYPkfC4zf%5qVpcR2rBsnsKjG1h$ZIH?5 zadJhj&ad#yE0>wy$g#eY!}E3N)DW28&XP^9?lv>y;?UCGT?ggS~L1c{R9lk*ijUQk&O6H+1tJew_`H0+OA711o~2l(iU&Jk$M zlIt>Rm7)rO4bLNP$jYS81OWjMFSX|bMWsketFjYqdOp5V#CEqkUwzVH+@hqrwzNvM z3jt^x6QOmOh@>^rFu_!i57_a+bonx=p&{JT&K8Ts_WD$mf{`(T!^gR2 zD9-;fH^YwSbE!~dspv6gR&6Qi^7+1{a(gPlr=~}F*Vr&p2y7vE|HKGDWpbNRaL-Vp zvclg!l;Go&qr8|YFk(vXA5Ael@goN~eq=w7y}E>9S{O>>2TthOmIB9dxp4Uk)1zZdrxM`!JpRIKoSk3cw!<^{ zxjeT_PjJ9A5VlFtbJ=zCtY*?&-`L`|ebcP(?y#KR#V}+gPS7&Ib$za^Y%w)4Nh&6> zOi9u6_}X`#W-A-iIm?Ah&)`mT2&EgPW%;)jlM=biWABu23k28+tV6N>R$ z?M$Zk8kQ z7=hLpLhym9v5J!|?fHyYCLf)d-~&@*l@)!;w)i{84wCf)c0Hd_%jADOvY%`a5R=uF zAHtPB(BTRXU<$#{&COQn3w&nZWL>{DJRetSo=stRM8eU;6f3|b4M zkZ1y?#)d-$ba{MxU_Vo zgjLnS7A0J{mymPAFnIo%XSnnIA7<>}VHN_3T3*6QU&i%ap3CNmn+8+yIA$z{GnzzO zNha>OkCiJIIse*g9N#xlIn`a4Rsii5k@*}?X9|4w`UXLLhZi$>ZcW8GnM|jAGdVFzP;^;e+hBcThg`mZ?-g-fk66qm9*^NT1rl)!X&6im$N13Q zNBG8L&r?We*q^kS+BZSmws_{+GGBl09Bb(u@4xppwDL&Gfc5oFHXVm=T)oUru}Cr& z!wmvP;uhOEhrFxMNLDs8T)e)_U8fE)Iy}Vm^b`jYao+uoGkoXSE0KuOZ_c;Yn&F`o z+09*E|BG*8jZI<>4I?d^m=U9}l3{Yw#XHukr^Nakao;ZK}NOe0iWg%Eg3;VOm5rm-))O8)3ceh2u2^<4yzRSMU25kbJY zf=j|M@U_O(nvu0objbz*K`B!9m4eHVVIW1QC>N9>CM79jn@pfE(>p9BlKh`HR*4Bg zHc&W$BEFR&B_%oEH_|W7SmkUMya%&e)YaSRI=2$Ahje^7F zqKmP+g~(oy}~Koa5vAiq)+Q@pz1wWn+{~&arr` zvQtzhy6#?VYL|~)zZEO)xb0T<9Xv!TnZ)x0&YgP=?c_MPZ<2}qGq~Di(_dj{YlVGN zQ=GW_E*#gvaf&Qly@Z$9sZ+kou1Mp>r-?6KN6j5YjZfm6p(RLYMIw_%F5W;c-5{7d zin{Y&isf+cVxHvU4aj9t2M^Yw<#ooQ$@9Pu$ZqVCNW>T!N^$0nQ*3Rl z@kif$ifhXoXc5LExh1(X5szV721+Z01luhzKflEEocjySl>K#x_Do zzWvN4R(JBOtZ#AbP>y^d$AQC#D(2eCBqsERcbnzbC|0%l&N3u^cAMgEf|0~Q5($f2 z4j*K3agn^U0m(c{DSW@c%)}^j2WE+z0>9{ySzksKvdD(}4r+hNwPob$aw%`iDO#8AS<4J2#34xZ=n z`lah!onPbXwfS&<)S=qjv7C*08Lb${cO90mUt#(Bl|4+9&hAv6W%FrXUtg+^CN0g{ zmi^n4MAoG2@d1P(#bq;fUG96sH_ar4#<1{mJYD5IR6=zqoE-kOHw3}f!Q^4_j#->MkZDj|;vU%^l$M77F^H-Pn zi4VPl!$;;=SX|@V>uGii9=2r>j}7zaOY{90M zOlc6aOf1vDk`fcxwE~=RlY}ifbK(fgTUjoxZDW}R8|fTYEJ-4jVk47ddug4u%?%c} z(iHMV-g?h1{PHjV4YUY7$ycr}aQ@;v#||Ihq5Dol;B)lIK0f~5d-?1i{S{l8B4*sg z(Spm%JACF74>38C*1| zGx&t-RNq}bkG%YPU0%Ab5z~ZWbZud}DLLP*E9$y@3?T&CR|GqGjtvj`Kr<#=ftCBzM+2Gh@R%}2;^r=n=lSn22!TL^y z<;^Yf`6Bn+ahQ*N{GE)C4`an`P@4U-6FhMLU7-vbD6|yJ9XZU<@F;)&{j>bVb64?l zn|$UyxA6-<^GT-m?E^#bmb-7`kN^Cos_d%UuZ;aKF*o@ zPJgIlPzMG9} z=bZ0~GAM9zd5W1FT9}w|J3MLJ@bDZ5#QQV;|V1;-(-Oh_g%;z<(1 z;`q_SBoc8BUb@QS<_?*>gX?)1Xof9=4}R!APTzAI_?q$=RpBbHN(@&vQHIZ~gv5+l z{KBUm;?tjeHwO>R0Scj9(6J_7)ZSL_Rui#tM^H-Rcy3ips9wlXN84(qp{UfWBr%nq z>n03P$pjSDNhXCLW?M~7mYwvCPP6t?LQv*;h=dHENfDl>8wBV;^WKN=<9!bW*ztIH#TelwG9qw6 z1=a9=(b^c;PtJGkfGw?WaQVhk>Bt^c35YWc11XzdR$tvMYT-d$4s4|^)aQ{1Ow-`5 z6Gs^z9c~$E+ATiqCYER;{zTEK8h3%VC)V^h7M=9OwyCYnoK}_XzeWKUhKaNj;h}>X zglUB$j%5-6g?zqrmv(sWlaK;oSfoa#n4rjw<*Q7PBsDw=hJ~=>B*!f5WRm>OE?&`L z%re;C-QdX=Ut(l5$;8wY(lkpmL{vS&LWT!;AwYW&1jG^vP+k}suRYKPNE2k3V6~Ts zoyDL|rIo`kn=eps9OmZc_}~XWh%V)4eB&G6V10d^BS(&~zP^s*IGCnMDwSevY>egQ zWkyFw5kerPWOHi^r|5(UTBT>M>oPJr%JkF}OG`_5UZ~$Wu1mpj8E-K;+J#$3E#1P4 zE^3Ot`xhmjJ1Q)*(?{hkTL_S*6|UleMwQNv(n=xGn6`&>UHm|y5CqD{4+4tC0}KuD6hQxePfc!~CUX{%qr$oIZSn{m19ncl;>H@rg>5 zY1v+`l`0)JtU}@78eXmHl$EL#thPDdx*S3v!o!`l5UBDoG$K4fF9=lWmLfn%Ow+{uL-3 ze0hO8-f=h6$B&kfl4zkz*PvOTgYdcz(++nMDJxOIWpTYMu~)pl4O@9TSvTqcl^c4)>vO( z=hatV1wuwzSXihqR=IvF=is37pj$;rM48Nk%+Ve+yk>P;hn#7Co*3PVJcBJjgJ2C>mV^UgcD?Y7$(85v=5ago{CS!~CID>H}?B0PS^^$2_q<@@Ns2OXXoVptN(wlPbG3u~pYZ5zX~Kq*Y6P<}Z1 zonnq+A;a#@7Dcy+781vEN$+godp;V09ZMnu4F#X2-A$Za4k;z^c|FEM0z|Ag{`(*1WD(+JfW$1UI$i{vsHa=A2xT#g_Ja9t0lSRj+m zkj-ZC{qVkwVQsLM$&$`)6z$fX0A z%L04pHY7w%G_I7GmKmPm6a?6@7;yonYmpd9q0*(>IB8kokFDvF)I z))(>UqmL2<0r`BMmtJ~_7himlot+(i|M!0%*LC^a=RU_z|MXAu)vtaPr4+?tkuQGn zi)?Og5>F&pSX^XtV}nE@fl`WiJWiodD24ZX+?by)9R!^tYH4OpZG~&Q2;wN7_ExlO zTTCfE1bL0KO*IP3n5DPPH2=FN2jJkE@7@g=v}u2xLs)2!|jsOd>TI zD&M=S= zE{T|3ITqC^lk&xi6op&oMl)M;*c`#T8CM0kW| zZkLPS|0d_pEwL`rjLA5z<8aqo-^ncxe++3S2vk7o;3>ZIg@4cWg^PHuhcqOKM4X2{ z_zB+r;h(}vB=J3u-NlPM_4PmC{9nDm;SCodz_M-bIP)&FJ&Wfnv`qCd$3=D*{J4VxLt?RPBq7G2ANoSW1KrZWSdJnu(Y*gDx zq3c6L!k2sDl^7_B65MX`M~SH#RQP)4Md3HwttwSjHC$zF+a?~5W7{@T zO7i(UbBB&_`mVb;_hJ^L!CT(;R!-h}8?ji7L?VIKnnIz#kz*&g_105tt=&K=#ar)x zfVsKD#1rxGiY=`v7K_|^+nt;^aUA7j7#khs-S7JV)6+A=<6%9e6oo>8Gxxleb1!`# zC$~jBX7k{?9%guW7|XJ-EUV;6Hn{g~_w&qOeS_7VJi@OrJ(v76jdu8MoJ;K#$;OG) zEZ(QF%}An62%!1IipT)%M51mcT&uP^Fyoi2oOuM~_=Op!<=DHe-tZEc~oW_Wlw44yOM;bC94#rWhj3yX_L zDL8!iFvVh#g@pySwzd(%!jOVgYKWPA2Z_hyT)%$3qI4cTdX$mTaZ*ELC})>=JkI#! z43=e+OeToO<9MDIo>G!XVVE(r&eajV?0*q8gz0utL^Wl$8}M%6bz53Z)Lz?(Y8C1x zy0zbSJK-Aj`^fniP!(lmDcfpmYm3i+{`35^fA-IC9EYFznV;eI+iz!nVHqP(BrKEd zoitB9^%TGT+rQ1~>MB7HaPs6yKKjv*vbM2>NqDElGtWHBcOQG6vuDp@+cw2wk)fd> zW@ct^GRqv@KTI}XZ8FY!F;Jz89UAT9@G#%8KwAC?6 zQU^i^48!33`SU#X*kjyv*If(^4e`h$kFc_`O5i(KfFT5zUVoL<9hXz5PVq~>^h-F7 z!y}J8!dJigRSLUH+;V6P-w$x}1%B~=`uh|L1=iQsky0`-F~Rr0|9$@Qk;_=tIPrwd z>dFGXj`4Fp_jBBL-+f%aex27}f1L{#&SMCLX&H#X=hFGt7#^QtZf*{vlpcBh{CQq} z=|y~}ut)LMv|pv0ZON?$wHGn$W|ud6@^_*^lxJ^NspMlcKCE`M-n5xYCHa+K`4w)t z~5`c^7vugLI$NYSFbPf?9)#Y zXc!tA3hSMFjaOcN2}^pQHATlEoz3y|(@(Lzvr8(KqF5~Q>Z`A^y0(mz8tn!M(;ybJ zdHRV*SzKCXa&nT@)m5JU!4o7bNo;I{-Ibk6fL>_DDdQN;G}+Ar=qK5xpGg#T0<>~; zwF{)|7S~R+>x5f3xb{oCX1KP_`L0x=GNBUj7|S;jctrttDvFkB2f&(n{8mq5et z@CZp$Gji-GSI+HLc%UjuH7|`s8l-N~%mUbJyjC-K&9VZ!?cX3*=ytU0#q8RMYx#Gt zv}-mFNp0co$;hJpS$`!Ok*8*C)TWiRUY_x^zFEQshb}XV-hZqbu8u1KK!P zO=;HxUX;-AD6kqQMZbM3e;>uO-7l_<@H&-FmZpAjZDs^8n*p!$4p-ufB);d6%Q~du zVHB(`XkQ_uM5FKn2UBQbhD3W#ctx=e zZy^eD8R9!jyz@N|a@$>}DQ43Iu8V1!#8X4WQYpx7<87~j3NN5-`Kn$<7SANHkPocyPQB&*8388&GOO` z+uPgq#6dGNGt03{^Ps;{rcTSPe$dKZGuVUreo*i_?U?<*doyU&30@S~?HQv+)DS|D zPG?wNTE-88j(}T&D>_)8{VYKcVAwX>zw}EGvuh*6QD_Q&fi>3ocZq+;&wKwZ$2pFw zTmrbaD5bb~@dCv{0T4*TKm`Gy+1cJp?jGCu4DreeOSS<>&ua7y<%yjFFKU zes}tJSxC(DQ2rszb(CTVQR!;7{mfbuF2M{zx^F3!$1ZBdS{nrPPRkq#{k%1Djp zT)s;58s@0Ah74jGA5>_=pghyPwABr+Zxro%VVY)ri^?=+>+MW6oWUemURva(7hkAz zuIx#iY1a2jq+U&(#%KK&QA#{&c1o>~tgWpgWsQze)7NHxfv6tkD8D-mNULw#!7Ib; zH=LsuR%3fnqKEsTT@>2Z;@K_jI`yqxe_H2!H#`gFaqS0o6!^8jTPxo}G?_frY_dTIcfFCN5+>Dz zaLrbyer4&X<&BEGZHH^G{d=?LK{rm=C`C4Y)EGZK^cF)xSZG|Db6%2zYHTJ8Q>egB-MS%53N-c;t$Iy|63tLUOjD+^B4Z`uubJ9ts8S0K138j6UfJI8l z{sRXvOe69)gN#$^ru5_R>ar1CGIwc2Bs8pLj47zPIp z9H``GPnXhBrIZ{#e3+4u5wzB&lRn&=qv&g02|tWN)W#LI*$Np|N$W z>jb|Qyg}16D!d9~>`_ug{atXqbfQ%;41;7cStsYNuCB7UxXAAAF1Bq~`qFb;R!8EL z!rT#E4N6pzsMU9aSdIHJANRZCcY|v$a9f$mZ$?BxyCPdPSeE&us2Z*Y)j6e9UFf=$ zl2j^HIV!(ae7YICMJ1G>)J`YGy4Ao$Rp`pkYT@)dp`v(oTYc9_EbPX#+sVt{FYTJS z4F<)G?abJ1%(Xg9L$$2F8gEvDAYgNIv$Eaq?CdZxF~Oljhj3k&-BO6SVHlND3I|oR z4iAk(>z?$NeoV5>R>eV>cpG8%QwABn-cA|rSIirPdAya0UTfVh=UY%LK4~1-$WUQX5TmdZn|TXk>1_eW@ct;piEJQpUGr6fBt;s zQpMVBO$b3Mm11~!cwlXoOArLiOixoR=aq$q?QB)rBQr&BQCAQb;W!)t|Wzj0|%XcuMN+up(Fc`jS4OWgnV zx8D@&5J0h5WOH+q-Q8V+AgG*@elwWDbzM%KJjqbPW@}@;?RMI4`-AR(CuOzU_M(Jw z_X@AyiG8za7bPaGC1aF1_xhE~%#4q4|9$u2dfrWAkU_=EG%HFeT-Rl8ZjJ}vaUYk? zy;`SuM+x`t1(#kXU$a4s62H}|y(S(Gi|{`Wd#jx9bN&lv0FB$wxmdaku3@CK3tmzWWS!pT3>T=UySbyVG=q>t#UO z(XOBTgif(rQQ$Qbxdtf)-AvjI0@uFq`tZBn-VuV<;oWhEjvi-hdX}x-3>zDpWV2aZ z*R7lfRb#iH6uMe}(McW7;rqHPwQ9bm{GF&Ck|rA8(>xha%FxuCOeC3{oM3i(ionTp z^}>1b`S4ogzKAv;-Q>+Gjs36v-OOtCpEItVaBo@fBM;rD+Xa%938j=K2z-Pz85$jB zcx;?_Jb_`D;Y1Tv`A}Bm#2OECg-OEyg^yH)A1cT4Q=RBxKT27GW%xDyEB#T^YhB?r z&-d|Mhg>?%&h{owAs-&%*21CF&EU7IKS)@$cy?p=ALK-i(!Xw$=0+3q&8A(i@XU5h zQT{u0wh0o+VGPs4bsbg~!dsP;Qq421Yj=b2K?tvM2Y07$%5THJtIQ(mnMc%bNVU(U zl*DYCcdV2>y2pw>B8E}ob?TJ2wmWLuV{@qx=1W${yh}O_v zL%s6ff$!tF9(kE3o=A{Nrf`admM1AjiJ*F zS|;f5FzQ@3I}q<~r+#)*r=6bC3%oMSX778ADi{>LW|WWOi6q6MLoOfQF>UOT(VNVA z(PZX|@@g1FFib3~{=}lig?aw%zxphH^Kbq496Wpk(=gcG-QlzU z{GYPCIA0MZ-zYi19j-qNx<^C6k8tX?TiICO0U?;2-cKT#tiTQ_`eyYbTZ)4$4&(b9b`C53Fhxg1#fU;XqIHR40Lqjg_Y|0yf$QidXg4obR5 zeau!ZoVpF8;axN4l$9MMv~D@BTe*(8cGu`txoss{1ir^cG2qd($v>Qx%rMR3;#r=1 zVI50ApaN3EBh1Y1BNk6!+cCx_#@N}~uAB{A#Gz3vE& z@ng-}=!SL`9iy=U2=gX zR=8eDJ0-qTD9E0jw3)fKyyBatMW8f}<5YBkW=GCczH9Qn?8m5MK0pdliJT2o$P7xW zO5V5DVJ=9WwWHd>_7RjcvjtT9CZr@Dv++HzFPXKKB}51jD&L6&p}D&JK~3jMOz!(W z`CNPD`)0`0gAj!V-M1emcrDGfA>jIZ-DF9=FN-u`WomSW+Lf)|JgaLb1mSKJ`bSi# zyBHFwB}ys+-!Ew%x(;4-uM)LQ@A0+^N=J;=^jB0wJc-bH@9xtBk=xO(SS(O179znG zLXgX5N`IFztB2QZi5h<0%eObHZ$C`%>TXopD<){5YHqCcsg>t`Wn$K<4-JE>btvms z9O9H^e-*C&QdDkK5+XcGGkhniZIwSPwO`9*wGNG1t5=yRtGZCNlg*CkY$R$_rL>>A zy$oWM)xIBiz4X7E^23B{t2!-nzAM%rU72D)xNFqvzO_tJnXpY7s!U)}RVd3awAQ7G zT5h}4rWEY)m55recWrwimy|7M)!Yv1MVPX&pypt=RtjaWaXbACO4RmxjY4gQYZQ3B z#y0iZzkYCS*Z)q@z%B3j4xfdWIttlPr-q|+?J8ZPfHyU@QmvzF!bHL_5{VWinHoS= zSNwYUtzN7uKd%oXsa4Rc?N)JZ?Ko@Zoo!6Ksa5E@aRRo=Mr-w~+X1c>dk5LKsPMW8 zsEpdbR`42e?S^*cy6yTVJIR_AzW^2AZT+OI>;`RI-?iLXhEp40SemT0aLe&gm5=KB zS(WKT?Z2g0Wh+#rtZx-*%xk zdpzHbX01+2jVLik3yTqr5j5}vu(1KJwM8-()g^Cv#T2qa6O!mk#iGw z;F}VwuuEVV2yKSpDg+pT8}68fi54-G0JKLuzeRrRC>k)`JW}}x?U3A^r&mi=qiEPp z-01~gC)!1g9PVZeJHhL>4s^)*Zby`EIywk@e7_=0w*=}P*YLM8VqkzaER?jtND!DY zFrgr9gjV4WA>$}1unKFKZjnHmNI*#o-%4Q>R!WvT*)!gqXxA&QgQwkK{Wg7vg!I!; zR3dcpJoZwecu~6@pl-t^nis|J#!F}+Km{miA+=vo9dzktCxIp~lL)_v&;bI77uGA> zrG-GK07U1+szKx0&seM6 z5Xwgq@`4#S^%3!3NjLBYU9Z=9*Q|~dLTpAM zYPY7aS{RLgcUyW5QfmdPlSy$<4y@KTrdk7mX!u=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81fB;EEK~#9!?EQDJZP|U_iG5bs>BO5~ zew`BmQ@yMTk-_c zqC^suKmn8p5+GtX8lAge_j~=)&G+OTR`MTf-*fNl_Zk2xiiE^osK&eJoE_F)d;Qk> zh41hC6aV;^e>ngkz!-zI7OgZ%lJIVOxBYQ#`qy3-C!a)$ASD3t|K4rywm*JN2oPU? zV-nu+N5H=;ApiEY_TBzbwh&@Jl=y@1Ng&|;$#Z_kQ~3Bm0V0HO&-2E{F*BYEo!_5I z)js#T?YpoA@2INk5C6vPER|A{zIecvi?PHR4Qd&&d7jEmibOWl-iqVOT0gusQs zZ*5Nj!PgJw{FO&HSWWf2Lh@~zcMc&XLWpm>qJ$9Qao^^<_&vbgzfGnyj4@FZ;@ush>#zV9r* z{*5uevoqyFZ-IbW-|> z%>Lep^B2$3>-EUAV*hZ2 zlmewRN^4RH*WS9##^x$QN}6)PqN-V6Ut>C3&>!@0&NG`F;e;XtMVb_%na*EK&#% zf)D~yN(dmNz&T3@kftft+E%^r@!V4{-&%{c-M}Qk^=jE}ou;r*C`g z?>H?idNP@EY?+_@d-C@m^$@<>-fjQ7nmGQyz{!r)eyM{G1Og$1rNo4H3Vom6*1p~6 z-^;PbpMNjM{!yR%`?=4*Nn`Ve{d|9jV-p03d$`3#8xa&jpoJ6=1VXgJL3>hrrFVCW zciX>hP2BbOi6t*M77QWoGG0#3j3OMucd6+Av0769ZGXN${IL-t5Zy;7?bs&KQp#oI z^v($C@6Eb+yJ2&Tg?T5_>e!q0$Et;I{nJwCJ=MgwKlM9q$L}_LOK->@Gyi=i#@T2jtwRu1h%S}-Mj_fg8(T`1mCxI zlmKQrp^@s;BGLxDT6K~TD2j|To9nIp<=dEnTE+#05J)L-i#g6%k}RXCD!gqF5fp^d z8U$Dajszi3Cg*Z7LLg-PJL}{mSqv{V)>B!B05Yveb#$+~s-oWAgZ5dD`y9f_>M7EM z{LB_o$7>m57>_4NDHsk{P)go8_XPy+@utQ(htvr=$(C@6`Fuw39&0U&`2vDRN=Xos zywgP`3A4&j8pk^?hoGdS-|L;YibKFT3n8GCMo0+=tXtqhwLFHmd#^%(An-=aC>W%{SiQ)1Uq{*RRhRPnx^> zw7HQpTupiI%^ie*htIFk?_?ZKN_s^`q9x9I_QwmZUwsqI94X=a`SbL9edeUC36nVE#x6>g@)4O(?5CYTLoU>;(*;-%6c~8?c%;$4V)1Z@tqSK)$3fyeY!8e~L zct@HQBx#Bif+Wvz)-oF%;k;u%DR7+*$MB@!!8(tWA_~59bh`x?&uw6vIXVP_b%-n> zG;80x0>2wIjgAnK< zVS8M%JuV}_PC%{|=Z6Jb!ved%PyPBEQ6EkcWVeINb3#?)rc;7*pcTb?oR^4@?7&7`!;h31Y)-9D#KivHRPLTRv;FdgGeg==b(EF)bzi%^>2r_f9Y zKEwq;or<{}JBn0-D>b5BtlzHW2r01EbB>0!UI)?yoF`NzBq>-!@E+GRyytyS@iTwn zFCp_H#^p}zjuQh!Dv8z_ghXkDwH|9?6g&iwN|Wa)T5Ha&^*O(>!qKec>du7AXNKH= zc9p})g8fO=4uC)@MV6){QX-s3N=1?ioQo?@mZq$)u2R)C-ut@-S8IjVF;Y31Oc)>T zkxEcHK}cxIIZ_BRrAU*6+6b(36bKTf$ye48A)o`yCS&p}AzK|l2qcMSQ8vsMC25)< zg`_b}dryU#EGUd3SO=m)HX{&%v6rac1}O@w1^YX@)OAfD;Cu{#&dr?Oa7daaG(nK) z6r~ly3zSw!B@yj{M4|{Gus1X8%?uui)^SA)0(NE%Qftv>0_S7YzLTfSYK!m=ArsOpWouZFsQ4_?vZ0$Nl(i*IBnNYYC~~CMn4^8{ z^Z=-Os3O&Kow$#LkKL&1?A+BVUdz# zDFTmi4Z+mdDxg$OQsgvA+$z0y$fA#HCzu)xQ1e;4g}ZoH6Y$Qq>P5gh(@s{2)+u;T zXaYEouzsm>2^2|^AgrOO8|I6e;5`8_1RS7($NPXvB*6#jMct}VV5$ZoCC=1H;phxj zsgZ1tOIA850@$8ZNFlhi+F@E7ZjVcHW#eSYQe4x}FN$`Blq4G)xT-Ooe?|}%@9D-c%(X+$Vao1GpjxFR5R@6^gHpm$vg^Dnx<@RoI&b@s$7t0 z&Djg*SuHDe59WYG$cTarA<*k~Gvy4-4O7kA<$S$<2}|pQX%LJI!l}5c$aRf5>pyxqcPIMJRedT zPd@~Pc|wsWgn(2FLIq{xmxHH>W2F0h;(HI*}|&z%8;dHIQbJIQ;a~+JB*xijhYA^Y4ai;dDWsCR{$Vf&kv!KH}#7B<5)-jrW1sWQ=JHTbmmcS%x%00(B_&G$qXE)OB;pGc8(m^4O>k7@JZqrnss^JI}&NROzWh%D{V^5@OH$VW0VU zhKk+=tkslKQshP4fwU&clI2i)>zM8y0S0RuthYGt@gdMy&$w(@>!#G!F{^BAw}1;C z-@4JgF^sNULFEPAGiT_W*@|Gf6GZ@}H7jS&GdtMB)HQjp&#^Z$_`uXy=F=&|sv^xY z);Bh|apOAP2WsmuHc*6stt(`whfWf7(ZSSZ)FOhTwk0lTCSIV0hzR0Y#k@9jvV^iR z(Fi(PBZEf>NR-47nAQsr5-k-nc+66@3DnNuZTvXs=5+InPM*?O z$M(S(-$Ksav05HH=!7sD#go#E;4CZ_1f`*=m%D`!pue40&RLI6WV`bUoVzn*xVh40 z*v+}VJEp7+A%OAGh!sRn)NDSXEElY;uCg*5FrUpR7Zt&Jf{>WnK!DkN2J^QmQ9`h} zv56qsDMhEpB!v(#rh=v8-=hW=x$U zTU(`>MK9UumSs7tZDNff?{t=Z2?WRzb`SRPuf4{jk3Gh0KF2hM#e9yjp1jiqYoaZn zHH-O->2yj{8+-^zrOApuvw2C8CTJxo>xOw{2*B7xlyBWc#V4&x(t3e24M>5M5+eeo z^QbI~>JJ`KS7gp(158?HhR``mWgrwGnCS4R4O^=N(nMohVX)SnXp3=mh=P!11k*&1 zR9zE{jr!M84x$F3-@Z`@#PWjcYdLitA4Z-!rqfB5Agx}Jk|v7#&#m5pvohB6=ItXE zvm+9%NLIGUiUO??f{c?U)hS1_3Dy{Ns_1sQcjX93A&@F=p-M`UL{l1vlPM{ls_`HK zrGZYjN0z0Srbf-?=&HsGL9vexFWnz;j>yB5%BP3nAj_ zYK`UGgOBl-{zre7fBsK@m7U!KG8E?@eS-hNkA0B8^MCyZ_^Kh3kY*jc_o%GLpZ>Ey z#XtImzsrknT*m`_nX)&YVn$=uSJqhTuOgMiny4ByRf!e`qu}B9e}o_Wksso-pZgqp zuil`n8?1-zqd5*iH;qn^UIOob|3^souk-b1pNFCV4?pu4|1#UxUgD)UZ!)`aV+ku4 z#vr7`FBU9r-b4yPv$@IRAN?NQ`_M&Rdi@&bw>J3y{o`L{|L~CP+BNE`ii|N;$+@)^ zR#sLx+}R=R^hk;>lj)qgtf;L6sp<4Kky!`1Fl1V?xzfd2&uY&h+6B@%Ph&mX2V>m! zHq)kNVJt$Yq^YLYjcR7Lm|<k*1V3FkBl_8-vQmNGZrtjq{#G z-LP{wp)roPw_prG3MflRG-yp&I4JUHUz}1>0-SiIPHR((g=KHQj2@9=e>;%qxN|HP zhN`hR=Q$WJSnC%gS}g@bDM2SsIJ?&4>SD%9uScyrR87Uv*C0^MCm-^EFsY>#HV zc4LQ2moG6s+~;6C=gCLzXFUs?+1lXd_19Tl-(=(57JCPWTz=#+_OHFj{Ps5IFJ44y zP5;7qvi^Ymoo&K!mGc)bvUB@3z4Z+)T)4=^3+K7HeLy)*`0z(RPF2m>zIB8B{R1+s z*;-rW{QVE0bV6k;&0;}iELGiLkQlGXx+|#83WBHxO%^rfjs3eOW}HhgccRW$&;{sn zifa})0gZDg0$320L8MXt55^EeKx<9ZoZ_PEd`y4!J}{kERJDnAhx5yo{@4-@!AI57 zdC1b`^bfrr)J=4gv@xM$bK#zeN=Yi{bz`t4#yReU<_e)v39QyR7dHol5V*R1gtbvp z*9RRoRys%tN(-jGLIi~qmT@^ldV?q6(mCgXry#DH|7?m+QI^e$h?_=j+%xbqFO$4i}YkaLL z`GJQXARDZ6?d505q~-Z%p2a6QKmWh@U$MV?i~ApbfTKyt%{N}Aw|0iLl~tzWBN|iF zUpveG-Yq`*(U0(@FFL;O2Y(2eba>;NzsvvkSAK)RpijTwZ+B1=caeFF-xy=5j76vv zX~3K2kPoR`t7*-mDy)KYa7t?MTyyKOxf04o22l>F0kFu!d9Mtf}_8aWo zzJ+j(-}+~tW^nOIe*1HuJ z(L*JYy1zn}51Cgpo_X;Vf}An48F_!eBM)BWH-Gc9eBdJ=;|rhrH1|FEF|NJ&4W3?I z;n63b;`W=*vvvP_DeHzuAA6LlDwk`n4}nQpQZC}|zBJrJiEU=g4j=^2rVyN!GO8kL zYowd&AS8A+rMZ0@tiwvdjvwKrkG>TYQb=rTS0Lm4HaE_*xp^VJ?GOmlIaC#5WdLnz z>@ubSOeYf#4i5++urgd>xUza8AjBBfy;=aI_sEMEL8{|S5#-%+5q-HzNwk*H7HGG% zJWtSC#ov@_{mF3)iZ}K+W6{JYloXpsduN;`xETm0zYdI!Xbr02t(_1rbre2 zOtaZZSuGN}Sql@8lCtqkOUtaZG&W#ejGM$5N?3AW1tpgMY2Blfo+C*HbcP!|{NRJ^ z?%v=V&wdqzz?E}WMa9>?`4R@n!L>IT4%d0&k^2D&GOmED8)xwKl&jaTV@=H)Z(LzC zn^P|4SRcS!);BkK&!rXq?l1l~Y#&Z3GR1ozzRc~L*V&(x_y7-FJWDTyH{W=JANc-1 z!NK)cK_!g#cPR3V2OfTey`5X^?`?BydzU};<3G;t{>$Ism20>8Ge7(9u)4NF(^TBP zb({Mhew>ZfK3SGAo=vGtLsoQoPLQvM7}M{t#!TjdOaS0{Ba(C{Bh2mJIloj=NS(A zF#s0=!h3YDOL68bW_z3F+EtP~r#O2SNk9aTcNS+It_k?Y6Ko(@k9Qss97@FWRV5`# zNaVak?Cc}<4iS5Ys1ThjO2%Vm(+M|k-k>QLXj4-j?J=7i#h{-QF>*hdaBF9WTRS`K z9vrZHaKLyr@EJmKm0H8&XX7Gy!6~xdHFN1q00%kLcz;#TxVr^ zlcYC?-J@cMz8Sd3(xQ?{&o`pp9#{L+^wgk!R3_~-xh)2wf7@R5&x9N{Wnc;yOdn(*tt^2@yXwN3g( zj!IIxot)8lLf-un&Kkb_wP$$w`ERhkwodSl{$RlF&JK&RLWY59kM{=feEG}Yz%)=4IdxrARTWCLlTPas6hhm&-EMomluMT` z#npN`yHo2O3<(5elHfz2zI~hQ+_~2K(;YlO;~g$l07w z*D?MuTf}I!)=Ox}WHLc`$9k`zlW69(VKy4k>kpUnaZ#2n&TCGZrbsC%t1^ZX=JO~J zr@UDDULe|&KwmuASjWn+gEchJRhEkHMs%V@= z5ztC7olaTQmicIgkOH-`f|8P>@q~b&-^nm_$)ZY8QZSx1SOjHNk>ycE6~NKK0bl*f zm$-3rn<5cNsW45=WISe=C)jevsGOma6yH=-b&Vjfn9nKl9HkUZ(@=Ce%;xim8Zd^r z(rlewN5~mRhhv-*ND+=VKc=%I(k#&HYechx6dAj_yIi|=joEC55P~yj&ak$&#%wmD zXd~+Yv)PO^O=+5j!^1-+lL@ogoq{1mT%~2F143X%BbuYbrGYD@L?;Qx1_s>@{ceF& z3ga58P-E-~fx7ocnnbAgRJNU{P1hIx)oG?VuJ zv~zYbozY9PQ!%>M_ScsFwT8qj~^h8A#L1;2Quo78>FW@7ZwT-qP`GgDI9!g5)LDP2@6(Xt? zDG^CRa1JjdWn(~U3_8L*LLdl%RuUHk#svmN61{1Sr250wRuMU6srxBb>2#Ay`>i#WfYCYVbbXL1OUMTW?{EVK^Lecz8sXWjye}gA_%I z@!PDe^$0=WY<$sDf{+0z16pS&nPH9Nt+(Fd=;&y9UGF_dM@NxmAgm(T&dfg7wQAyb}IOi$bRbEPo z>-PwGO3)H9nE(-ZskNq?=afPq0>}`VMM3~?n&qmm>IQRkMB#iyKGY4=4MVMw#++;j z$GaZ)XtR0E)oc4pHR*U)Da#Yu6RjneF7%NyMr7x+8OEBp^@h-*T{{?A6GV;41M}Sy zVJu~1C|2`UkFybuEufHs%C+ze01w6o3MFU)^oJ`LyFj_X%K9e9`e4x;kYyQ3?s1e$ z#A*l;79fs!hTdj?2`Mo_kY*V=jcC!qV2GDwg zDhiZNa0up&Wpj|@L*Uj?Nwgp=q`#W}xU>(6Z%-$YmZx7Y)qdJ||fhZtIf(R7-E@m>0 z@4IPOG$q}l%V4mIae{+`gQyKG7I!4-9p|z5;5mQ(JTghBd|W&V9fd@z6qTOvnfbcL zmDTb&d=()eb~Yo)izT}JcvnK1zU290L8sG&pwa1hyz3%58EHAEtQ)G*(pXR4-9&a~5d2aofXGwTLiwGKJ?>_T z^^T5Spm2&JMV^5Fyzop-RHZCa>LAf{an#h|L{$htmgkhcb&|7>A!4ia|v<*pjKyiwKR22m>P4P|Z0d3vD z>DnqXO_tAo47R<;juBOvy}b!a>th_>a@7(-Fr8L_r(0yybwjV$qiGtZ(+>Sq+!%DMn~W7cDBcEVF5~tR@WBGml0QR zaR&w{5U4nUFyda*L`p&D%q5H}2z5j7cS8xbdV-Zq^5&tXa*(KKnAKhod>j)k16si1 z9yvP4{krSk-Y~8#wH3%LV`c+&z1{mYGeft*5I*L@|fkkBq(~6EW7+c@fhhsLz&@v2WS%!0tqoX6Lx*;g& z7ZUH{E@O7K84QMTNA30Cu0mfl|yl9F19xw2OBLMhLJrNcgiKTqjt| z%eUqvsiaq=n9A`Rug&=6V;!z+*Mv0T`|itm^DugiMvDk&+~{hqAJn|CYwp0B1q3R1 zYGaw#1|cL$3#{`v+d`&;;mBl-TYh60c z@!lvPID~+ewPJa#Mt8ZYy36qsQxlyWjfb^!?ZbQ2jUCFxjIyjyQcxO;_kpspgz>Z` zv5tk@ex(i#1usr0Pa8$zw?bRUA#b^=Xa1T z9DCvrqSehUjjOSyiK>F}rvxMBhi57y5#W{NPk-<%c^254I==S$gsnl!pZV|^zWBn3 z&t6?{-)4`qD>;K+if=441G$#`y?=2ls-xo0F%EbNEu$B$6$}Y&GFV&`tZArB$@=Og zJf5@OqGX116}4Hgv-die&wrS;?mBte0pU=gVeV7Tu071dmp;zCJS0mx^t+oBNy=}3 z{TH~t^Lh*S0q^1ji=LsoXG6^4@pL)~HU&Y35*mC!m5*NoL8pB78 zBP5-Zm(bL(eFI$d1X%~;S^2gJ&v#VU!WctY-g$1_+82M@L6@G7&C;P^Vgx zC6ueHP%h}22qh0b;BAd-8mh8n_wbO-b7v{bl7syN8dIZ`j)^ZvM|8R!E?vAtuh);z z<7vggw8HqXtk$&BNm(Cu+GLgp_R5m9g$+l;BGDQt1=c#UG)JRb_h`(UUM%L+jfvg} zDdR2`JjOPJAX!nO3=7K)3}(C zW<9~jK9451xPJRZs(MW0Jnwn%lcdV=>}#K6(Nv6Phg`e)9L?GVdfoG+(s1R*3wTv9 zI(myN?XuE8!_nv(D(RBygtu2=ty=;l1K1)U;eJ})`5x0!!&_Ue{FXuD90(S zF{vr=3p?}W-@o#;YH7KhW-mIO5qaD~0HmX;4VjckADGn%-R4xT0vXIwYzkZ$d z_4Q@EB5u|$#zI0DDQd>kN!*RNFhnHjDD}jpg-XD z_HC@Oj3;AgDPf$4(PYkjXIDs+#9B`Xo{MW8!fJ;bJBO5&VP(+eaO7i(s}FSY44r6# z_Y_&mY+f>-m!!Q6?;K@mqyJlIyb7p1?iRFeRUrg*S&=A(bC$ZP$+8shU4$V!htO(C zlYh+gaO_b!*5*#=Z_6}g;?U;VIpq`JJPMcUSLQB##WmMHPc0tkP ztgWx2lp+L=QgXQx4u*Y>4oC6%e6%HuF{EvthP(PNNXBn4oy{onoIG#2g|wy(n-hS8 zX-#b$d7@bBXLrC==JPp?F?eekWI8fbxPS>Uhr|TI;k+RLgCb*AR}|A*taWm##<4SM z_~IA#dH7-nMWEmB<IFwVzPT%pCnwW$vwglPO~5$jU`YnkS9 zH|5%_=FM5n6T^a3wszDXwFJCFyCd@b_7Y11X!4YWR&;uORJVg~-Eq}uLZcPgpwIT` zhzm-wGF(}%o*U~M%R!7_S&3GX)j^jVx1(yK+646AqdvMe?9s_n_6|nT(DpG?FHJOy zvPLP%Y*A6y4S8O$C}#*fP2HesOVz}L{mC>Ys&qOjX}3d`YKFr;T5C*GlV>T`nq}bZ zn7XE_YwYb8FuN~PmnHe2PslQq(vhr8#QxUCakx8U(KtG(qPN*2Ph(K8EK8vhTvC+L;S$K1A!Jw0{(oJ#3<6Ma3Zc=eLo0Dacxk4vt zgv0xQXp154O>0smS?%Vy!#&J+LPw=cM2EVm(5a#<7l;;C9RS+~Nt99uC$Y|=m8J@U zQ~(l;cSvh7brc-cU!~h;sk$BS_#+E?Wdlt>iO|L{;!N1u+By-2Qw;dEbtt)@F+;Ra zREH&R~pL3SpXN z6h({&jVJrKmaithBgxXU)%I+my3AGY9#3|vSpyGWqJ{f@*R;nTd#u$WT7<=XQQkp1 zF2r$==?~9DI(7@5Ue()Q-uC$f<`RE>r{lkUdpk_ym}u*sB6+Xdyv@b^om4=L0sMFF z<8gldcQRggT=W$7<8)WU+y1)qG2S+&-*J0q1lD&v`r*4zp%OwwR>{+ZYp3HF(JLjF ztINCX-S)?+1vp^|`R?=)yxZPwfB5ZNCMuoKZu}nGw^PPXA9vbl`F%fyxcB+r>e_cf zPVe#g?gx7t-uw&e}5%>1K{a(iI?Z@8hIqyZ$|Lw-`Tj^VO zjln&};+^{a_P*S6yx#T>elLA{r*Zl=O)SdlZaM_#@Qp!eNpK#aWJ`e`pI#;jzN!$X z+SbrZJW*OIsIk zXjukLOrjDe5O8QyU!B7`*9P2T-pa9F>#W6x7-tYfFUfJ=j?+8i@ez*}+Hs6SDq~HL zHgG9hf;`=(4Mgf7Lz+d8lWpDaTB{hjZpi_TpA{km$axd&YaL+Gc+*<3U z+gyr>RXcWwIBP-3WxuU+G0{q?_&%EEj^AAy>ryQit_2n#m0G@oYmq`C1$^lXU!c<;G8!GCG%RKndC|iM&)V7=(luCB@ZKjLia@%0 z##g`bBB>G--7aQcGOZi>-3+Bt=2gv^bLZGx>GIXDeU10L?}Kct4oK3BS6_IJg_BGU z_vsFL42J`5Z}0JmkADJZYHVHcrQiKBy4U5Q2Onhr`V9_dW7Y=i92_37b^Z*~qa*VE zka{)-ozc{Dw$5JW(TDHH`@pp;uQQpI1ZVLguvpCLc7}LkS=ktJ>*j5SYpayg5w(*D zZ&}$mgRAC9ov@fs$$CRvRYGta9ZfiQ`7)EyK6&2f>8GE<`@r7r4X)qZ!8SE2%}Io0 zQP&Jtx-8~3BEVv?;Ns|A_a0_@m@nVd@3XKKDHR z;gBNFxpn(GdETd~N>^9gB^Fh3e$yy4cZo7f{-;MR>pw$5y^zqiZL!6Cig3j0R~6h($@ z8k(kJQ8}cP%&%UFq}H2fIJdRIXfma)9lcyK8&7%V#TOW^45?}pp(Tx_t}BFq?VVd} zoVi4jYNn$R;cew@)GjXEs1F+qZ$UY^<*_=*G{9 zl*|_;=gyts#g|^D=;qW-Bz$=7wbyv^eeWgj3U+SHBgANa25UXj*%VLCcyFJ@$g^0? zX^dxHH#~TLlUvvKx%|*W+}^%{_h6cu@pK*q<2&3j?pCFQ!0g^atg%NU^2_&=Zf>09C|4zQ9WnF6)m5Bpzz1ft1=iFw&NCbg zBcIe@NTMa<(HICUs)j_0h|8A(XB|puiXvlgZ=W=a^&wU_wpd#kVoV*cYa1q$Nv!p! zB;8IIsWgLrkGfoNCNTdjaAR#!iqRW{xTL=M1 z2YVcirgSNk*ds_V$nHbPB4fCeIS;+Rz*Hs23%5V;HQgfitYGZ^YoGmUG7A3BCRbsa6P~SY2NQ@3?jICXMwB`h6N} z=yW>Z9eexxbUI!7y1&7utbyb3p=tQw7YX}i!x+oVEoerHm$2(7wCiDk`s0vpl zH*Vf!xUz<`1}R1C?_h`wo+QgrN-#P+L?t;fkBAhh2tMlTd7dxp-o=~=OI;hXJa6gw<9)2PAOzmKHVCEB zN@1N{2Bn znkLdYw)T(r4j~kIo)LmavB}sy_2HW=e7!d#`$7-#pt7bVCriqDF zT1RG;#u&6#I2S02yv^6P)OACmHFeXFWf76=S}2T?vhDkE?K(l0#zK^)iM&opOMa22 zI^MrceLc=w5G`$zY!kn%b1li(4L#78A{3}9aCsy zI^O$Oyb^(T9;M@ZtLi$=C2^AS3Q$)O{(npgSJxF(>~rZLl`zaC?8ux$_qpq=A=Sd!4nFP0)(_A9#R738sffs3d3a<_&Hi z9*|`c>jk}D#?jH7)qaQCc@m{58^h%X9%g!QgLy4@`UCI78pC2S#)*`p+cz0arZ^+` z`1gGec!PC;*Is^}vT@vc>l(w24bnuBq#ecwJIEwsV`G)=?Oopg^hX)?Vnv{@J@XB; z1SeH>*&NI`#NgVkK~%9X1;{h<%>+RM+Q^C8lfn4p*)9Z(EcDaRAu_n{9`qzTT} zeD&+!pqCa{>2S_6na{~oMyeG-DpuCkSQ!o&6e-U<_aa(A-tBO(e;DiWNzdVUPIs_^ zZ5lQ<)==IuGlGvi{Ul}8u)F;hFTQexyvXV11*J7S{r;zUPABxU9%Zwj=yjQl zCWtiSqaXet-g(A{dwk>hmlzI*Bxw?9I`{S%uB|f}$8(K$bUGP(M+ZFo$P-*Ve+KUZ zZ@l&*w|9@|b_+rv>gJs;Drmf~sI1`Pxr^NY&;`EmJD*1@&8?js);BiMDl(cYG-=`? z>+}96AEm4tc5Ynf)i)5AJeo-7OeExma*?IO6E&h@wB_=8c=|93HW#EFXB!Lu{?D zQ8$!?s>A899CQUb|ZVVupFXj{>4KKfTorfNK99&6lEQRi{wz5uT8b(J)q)Ec`XpilkZKMZF zpx5n?8H7 zmar(^lJVgoySv*o zK~gT}Xe3F$i?flGttuDH$^{SJ{}?;BZ?U(t!|mHU47+J$1re~nyTfpEi+-ArW(9k@ zw@_&ZtrAxILxQkey?(1LFHzC$^-*s}LX`JVrK)y28XXnugWYRdf=QS&X$D9vp%c2q8Ip_AF@< zJvO_02jp2w)flpt;OyM_vnVMe9prqD1j?$S+w0+d+!|-IdAwI$v%0a#px4DY%V>0j zb+PK}Vm3o18QwO?B*j_Nsu+Q-tu5xW2~`y-K!dYPW-~h7K6#qb>2}ddVvLDIV^u|6 zl?b62tPBwT*v%}^NyOYZV+jNnvjsv$FWtPX=ykhviVpL|0%sd)6IU&*Bze&xO*M=8 z9G&Jgiy32qLOoMW@H+#ySExJlJQpC`q-ZF^*ohU^1K0Ejm%%v<;*2gtg5r@RqWy zfk15rBG7P>Gntx&2)Uk;b=^eXDrH!;b6#kG-hLK3u3iAWE=bNAy6(B zI2ZG3%BmzuQU?72)-_n`m`!KoMG_(e2Xf#oYoV z&elw43(lT9Pnzg^s#5n9jJmEc#_rEu45s3=g6|0 zB+*M_ziLc7fgO2KM18cXmgd$mC6H_jtt%DnBkLTA)|6F=l!`3NFinl~k*UPGmbP9h zvQ)DuD~ckr7dmUHn3^7qz$I-zelg|2J?d&h-)-tk;c;Pl7$ zJFaYcn)--S_c`v<@|ve&N5}U&HaM4c;FqV0dtc|&^-fN|`?|-+Ea{F;jny4^uD4zL zbfE6|T1$ia_&%q2r+{Tl=j}m0A)>S7ohZCP1cLkCaM?XZ71 z<RnDB2!ievNG(q$yN!**p~P!K?F~bnnAB<2>?oFvpIvo5GA9p-ZYlA zjSV_^P6+=3dXzb-S)@1y_=2nZhN=gqurILbSEx$p!xqpz)_pf^H@8>?hpL73J?sM zIT7Czndy!XYH3d2e&9*FD*@&^?9E+wzQ?uU_o=s^40B6Ha@PPXKfkSycMaAtkYAkg z-JR;=N%!u~Q9sG@7I&O`oL?U9Js9^IhI{t^czjOBHQs61zms;Hw-Da>McunocfH>> z4@Ss44*OQm628OV{#B0sR_C6Mn&`J@a0w}S{&#&?Vw>?SyqaKwQdC59nKs< zNcz15+ZcvC8&JB>bZwNB`7VC zD#D*-@Eq>%aCEqhYijVZE=I4LvcA@1V{^dDphM9~(22$xOF1t&npPZ)8v+HDl?2=H zSbxS7!zr4`gy&qq_`p}LH+=0zWJM1lX82_~@ZN`WQVlO%tC-A0OA!Q8I6nM9&ZDc) z&l9@2LQ28@-1FI2XLzX?^b|$rNp%#oy0Pth5Nu@$7Y9)=5Rw~{is!d$#{dY#?F8hl(Fj2FzS zhT2BqAVA&38W@Pki{-s%rJwUBp8i=X+ps7X2x49HH{X1NG|ec>2=_R4voGcgy4?=% zd+Pl-=Xmjj7nn{aF;JYP%;$5QbDTYQj`zLyDU?=}Wyy2j_y%=dw;Wi3qA19+ocDj= z16XT$;f3cpJUB$_nEj`dgu1NS=M7xEbcrXQd@?Smr!!B5xOdLCP84~bk|c`7xW)w; z%l3+}tm7voI2T$%E>OB<%{x}X0_1swbcEmuA(qpMs#(i&mvk6zULeUjIA@UpQmygc zakzJj>EQvvIy$-LiHA0L>U|IK_~Vzj@A5eY!$HJrIp1E-6TBr@$7H(Tty?3${`^}! z|J;?xYAB=7%Mi(pGa>1A;!5p&z`H z4okt_#IZh5Tt1r+geS>UB#vM`S(-$+xDeqMJy3Aci?bHtT&QFTXls zQW^%GYzeXW+Bdf8cO}!xa(1)FQ|~#;XFvZYwO3?`rYmxkan#1)Lqr%vH@O6*TNe3* zfAUYi4!!sA<3II5ymzc`ZSmsEFL5-PEK`<^i*>gfV|eemr^ve<2ypSf`}oGQ&ma@c z-oZgESDdCi@X*5ut?xVqLiZB?ehK)e1O4l7>gni?oj#QoyZUZC<0OhbjuhVTG~vlPm10v<#E>IyvMt+ zBo{u`FHK`eWjxmeL85ev>2V0D>8xym%BZUaLIkYycw-qK9Wb99qDA1+r2(J(_fP`4*xFj-{`)WT=YDL!4}EBpE8lp9 z`uZe3M;nz6BG4%$>+4CZuU&iQ^MPo`;X2Icpg>muO zf)6yc;J3bbmDNGYg+%b=BOC0EYOY?Nk>v?R8?dddL#fz@5JF42B$<~DU;O&3Je_}@ z#jSt~9tC`&X$U?^64*Pr6QMt^FFXqTfA2wJVFHI!IW(K%OGGLLd5fZ@O|)Se(YNd zhL*8dy#NxeP*Nd8EG(k6LaV6Lhaj=SVr;;+TXLcmT4@3v5j_1YAtP?Fjkg#dFe2bW zpkB;L(k@cyNcry^lkox7V$9Z1@MAytKECghPqVVpWoK{9=l{{ay+AOy?B@ zhj*Zp6d^p;HYfpWy$%mPaE7NI-Q>Xs&r)OxL$qI{jAmt!f-INxyHO>y3X&i>FaqfX zS_-mMlcoaG(l>?>pIavqoyJ81VwGEQO4${7q=3dq_KzHgR6eHT}F-%}U)N5A|H_Qy3+r6{eaf})yBbdvJMbx)BG*;t*Th2qWa z2})?v7JM1fl)8yYP|n5r=>iEN(0uuulwaRn(*BDO5ci!U{ju+(`TW6Omt+IaNaK~5~YbC1VPn6 zV=NasibwkyiF6#+o`c4+UrTP6b1FSSDveSJE;xj@T;9<9yFdMYzUPxaz+1Ox{QZCU zyL|J7D;$kycpo$P(j+6*noQ@MyLf@|!9II?J1nZ2?Y)x2*;^bPO}KeupJaB6&7{p% zlM&YJ2{g51H1c=^34vU;On@TR7)+D4rZ$ji&3sXF43LQ|8@g2^+p@C9G>O7Tl~X!g zh;*%yl2@S^ylQ$#i55A;hBa!y=89P)p0CZ20XjUS%|?c<6z3qzJ67fjmX~Yls?EM@C#nz#C0Sy1okLwbL+3C4 zH0p^5aBtoq|C67f`TW-r-ov7Vc^R2zCJRKCMiEFO0k>M|_G2{ZKvyh2pXDd|%8R;AwVlv5JYRxt8Zkfnld zp&9maw1C5^rf%ZP&pVn0c_e zYH;3jX(Qohe()il{?PmR%x}KLKl{v=86O_8+ATPgP3<10#h{!EGpIdwobP_?Qb22zW(3V&8WC^Tx z1-3bMV@jlwh?qctRGg@hAv$KII3Db_g6gsRBZTOcQi56CaBJVtD>VIXf|3E}9irV$ z9C4d>2$TeE3`HUt_9DxA@U4C=91clnF>QoEXwyT3^8_bIB&>E4loZ^$J!4un3|9)a zcjlyN%6lHa%yZ9N;mqbbR;@CA@p_wH8&gsjmEzjY0)c|y2_lknAFI`Anv-V*)*7m6 zK`=5{|}TEy~5|Z;8;xptA&Wk^CGaBMe<=4LaYTRCB|3;p7U#6E?v6BXFmT1&p&&ek3M{f z2RGl(#`-!d8>{pO1JrPnChrl-1sM&h6Uhwf-EAi05w*(E!SdQ`&-3~-pG7ntA7VjB z#IY_c5I9T|>x-vS5`=6q{;fjP5+5g8MREjjoGQ^$>Z?eYoFR|Y9O7tas5aRf?766hpJ zV_m@Da6-gnq5v)gjA>}<@dpu!MxEP2tPYUpws1FhV5LupnO+1S{k{(&HdbKJL-xCi_*~gj;)e@t-YML!!N;!##>q3IR%kRFI|d4OhmYeVi~+ z)r*0^+B%M=3o@GLH5Sc>elJoLO7tzF|h%>tV+S_{kwn zWwx_zQ>k6_AHr6tl+Ty%LD1p)-WUO-sF@6(H2Ty~2C2JQ85+&M_ z(5(=+jsp`sNQn!9s`kv9z@j#Eb49lsi7Q%5ia?;Yp0ajKD^H$ijElBRmS}|3%;z_hK?eh2sFO_C2hM*SOKKs|H`G3b+i@ClmVd4}}kPf`Ew zb0m-7kKZ3*U%Y~R_&!2e<8JS@lUU*oN04ZQQn=gu=#M-}^Bcbdhm&s^Y}VqK>h1Jy zNA&9|83!*bo!uUzNJ`_Hq{PpM{8GM|!k`^cm~XhDCa#|Kw7NtzPfOlXdF z5wkhk2l~SE*g#WsHLh9VpufQm*YP5>Rb5-gJTK{Y9Ge3eFXGCsQr+tFaT0fn_=E~e z@W=k4xSC5PPb@SE-ENA`71hi$Dx+(++e=wni5@%GvS=JHC~?L2OZ6+VC3>uZSqobi zZ6+QvvN4to81G4B6hs>WH;yU}XAV!`@@5fNZ*eNSK*YVVHi7M{e(wmoy@y&~ z!M}DL^})vxo2!IbiD(1R!TVE16r)C$*c6O0-mD2z)uC_6~%k5b(hVFY@6h?jzNj z+C^_iQdf8}At-_F3`kT8l!TBVR02tgt0Qqh)>I@e5LCfRZwpY-02I+FAQ7Nor7yYv zaza@_)dYN))9-pR6(_Mgo|q`yagIe0h!EpB#|E2HBGOm3JF0AVCgDA6gOov6b8}}F z-Q9UKzK>Vm6HE0(%M~q#<#amfyzyK=tT8TdVXZ(4fgLP{NjctMaT7#)?2j!KM) z&Il=DVbCl~(ONBOjM5+Z1f3uL6#M%z7SZeX7#$u_3qkm^KTN07p>7(&eOt&hXMcZ> z{HMN;;cyVy5#Rr4q`!9cs zDc#%=aO7FaqHdVZtEJwoTJKEcK8;>2@1slhsDbClg8hZ%Jx)VX^Ws6n>$8A?=&7KF zVDLh)wc6*WzVE|4@SevBGG+h9HB2=lpU(-6L-bZbB!sdiR1T1+B*Xd==OlVKq%jUR z8dGFB>-}}|yn~>OEBz_hfRxd2?e`RGI@%pJXc7fMLvLs)8$-D`j{LT;2PsgAB1u|q zTp^fEDw>v_N3?MqDWU@+PX$_m)`BF7lU8d!C1!3M$Hc;>Zh z{q}Je5CMu@adxW{7a~)~XOa+96l|pgc`oP$L9cM6O3>|OlufJ@HD1(6A?Re9EY-}W z1|ei?KhzXOPL^s`S5`TH?i{^dLGaKK6`SFR$!v|^|!M-F>^m+xICm*K%*n9ck z{U`qudc8h>{;&QO{ttie|HK0iKf=-BA^+pQ^p|=58?UmnyF(&1uf6&TN-93}Q$NXP zfAiP*EC0cN$VWc$34Y<$wZ(t@pZ=$ud-#z%#NeLpT0snM2^j?>;IPh+r5fQK{Z!*!MrABI735jk4oXx> z8q<(v(FmO`46je&ww7F(TYmetW$rvjR$yC9l_!u0M=Aq_ufREUXNZ>ytrBYE=+zc{ zgY0;OF_C0C&5?=1&Bjm~#-llEI>R&->w^K-d6ZBTd6(MEBJ`t;3kXDvMM#Blu?(_S z9-Vljtf|QljLs78OuRkmU*1#z3l+0c1cc5jnhUXjNN*N8oLAAxCsV zR00){YDp)JMtm>Vcwk-{v=lV1W<0H!*N#Ca<>@CL;v-Kz!AieFWtWOR7Qjkn(7SAXf3c;V|`XLEgn;5>`T zl+pe^-~Y)U;MacnA93T&H@WfFb*lNC*IsymfAN{m@TJdxo(`C|FbH;t0Ca3INyK&yb%0jb-_wf1y!*dLqa(jsIa2uldD-nD2a zb6bkM4SP5`g=AJmy|&v;xc^eYbY8{Cwv^6CWg3($>aaBQgZGFaD73%-nb;7c;vpbJoV5e{>1wp=F-+CgHF!W zSl-wh;k2MAI%G6lc;Dk3UcSh`eD)h0RVf-6Pp4R8u`M+b#PZACzT>n1^w-%se}2h6 z-_$jxZs>Nq{Mb+aB+q~2IllI#-^E$8tXR94&!LSQrD?`sWtGqT+OKl<`~~E(J6H&8 zWBB6dKTn<)T)ccAzx3bye@K#q(cuwa`^r~PZB6&x?c1bDL|2t`Ym9?L!lP$X&I~)4X2z96jguu(nPm{qSdUWC zmI%h`CB`&s3#upElCo2Y=sc?2Lm2|?~{DeZE+N3v4?f8A&pyi&?|Uy==~i7-oWJif z|G|Is*ZI5u_21?zU-}Y9qcMN(=l%lEeDy1g$741&H~HP){%y3@Bxy=k6qNHh`#ZZ- zW%=!y2#<})G}8zz5y6w?0&5HcNs%aO8_|rZ)_5Dywa&%mtKZQiO0qRf@Bt1c23#P~ z3Tr+6BBh&q4reuOi3N098aV`y7J;cXTzmCJ?tlC-RN6;oDGrYe;2MLH8X+`(Hl=lf zA<`6Y6?Iu*W+ldX4yF^5G|m-`3|)6vH7dKsmGAxG8YyfK6jL zyVXEgAPDFrdZoMsp#@Saq;4rGrC=}wQ6yLsefmiP-fJX|MYSMJ9ZCg6qN1@bB~nMv zo)!uvq8%bti#cntYEf;9@5R*)83JWv*cp4Qbrd>~B#KU|DKbGfOUN@tq6MjrD|6)p zD?Q72Zkd-2rSTv=vnuXBSsHioey;f7gXekg{IMP0eb zia#B(+RF&e(zHCZog#08kFntAU-h^v4wo)p;HeM3pZQ`zH_PdFJIlGbx-z8v=^tlx>l_D%hiu=v!N%GOfA#18Di7U% ziNE&O{~A@@@bmxS&-3J?kMj5<4{+`F9{qlg+c$2|>-E@NTj6LjqO2l4>R`~ntG3Ly zRHd|zTXmAEJL+i@qG73|jP#amk@%w#3pTny17iKELlB8maD6!C9s5h<}KigOGHg1pc;CvhgB=mhW9c7=Q$WP zG$t_YsTQ&?kn-4x5hL|V1eEs_3i`d2Ttg?78)97mMbW^4?OWk;y#*%9I@cn1_51mB`QuS)0QkYreeJRI&X{)**o0fd*1&TAN{^R!&koWyS(_!SJ-;& zL!`y4Jb3>F9(&?Zs;cJto3HQ>|Jz@rY%D#ccyhHMI8U$F<lXJ<(kEGN>x`}`q-aBr3LSO?+19}qubEMr4*3<|W zNQ(@iG}Uy@WHP~8gUmCGHO%IRn5JZ2I_esR9mmD>4zFFCFrMtTWxN!r3TzEC9=mUq zt%2tAFHEUQ*vvb0GDj0U#ygrskobrZQmrMO1dmQ3cLER^vr8De~XDHQ>4|;@7hmr{U@gk~hG=^$XqNSsg zr?_T;tSdUf;OmkLmoD)qKlRgm<=I#M|Ly&Euw_Sn=ZSqXkH7vt@5&ogpGd*DhSlDf$*_%6 z_GvH}jhSrM`R1?u8n66`&AZp`$!1VL<44r6P#=$s5CBUWDyRIpvVZcQMkoB7Mi=AjWAynrlqy z<+d~(@ehCDWArZH!c7zv*H8~aDwPP=mCU1vssaD6i)*CP-i%fn?MkYiAaD)6yqqix zMc{%XB~dNHbM3Sjr3q>^MrnpC1%+_Xra&2k=Qy}wl}audB?E*G7-cbo;SQ1l*A=*E zrY9l>!-R%c<;>Xy0xtsTu-6;0zO&2s-`(TP@fuTgpKg*;ZB&?RTO5@VRsed~%Wz$J zIP(z(8c~2NghiTajdENHtto`IDVVm;RXP@Qc!0G+f*aal-9+G0tqPL3pb}Yfm;{sr zg(g+n5|j*}EdDA^3z9;UCJ@XV% zrHXJpQbKB;z^#P5dGTG2OwDki)uffj%uIxIeV44r+1ktb?t6E5?WLEfwPvU|F3+7@ zB=kLEU7<)*rq4dhFiyF7cbznyVt#ItkALMG{P0iy0CLUj`4=$JG@kEL@f{{7+nhRa zoX>sc)4cY>@8e#%$n(!VP3kzTt!!ZW9fC)wss7lAp-Xm-!Qgu?ai$q7jY2X?a(qRMQwwdb-?YRZA5hX`FEw~tGEsLqf3(fHjUMl8#pGq{Fmep-P*C?EQ5JXa zxdPuaNDN7mQy7CTa-34c&5Hs?qcM&jkQNHzdiY*syCS|us2r6Q42E6$-7Sn!)T=&b zPca^6eDUdH9G{-XA*9F!^-7gWr9!7a;MVFru5NG88xBw?G7TA&kQf(VYDT>TrOTn5 z5O~66X>!WSkftedmXYR~B+p5tBFQy*Q6RNtib==88qNrWV{kn?U#JE?Mmr4p3DOt} zt?{w--nh_g4iuRxsQQw2%^}V;D|<0+RHe~uP^}AmFQyU*i;fl!g@#dFu$5?bhB?(J zWV16ONHmqILp^kvnTp5?MUg^(Ftnh@AfOS{FuK4|kjG>4c#LNhBJiwvq%P39AkGWi z$pxNz;xVRrwYksA?MGS$Z zm$l6;(w%ia`ScN%8Yg*tw#nWg<7PIAS8w8nRnjCT4g&72?GUFa#};RK;cMSykU(Q% z0;LsMZr85sSOVL`M4PYw+%K^H^fO%k;rBQ)8M2@DXdF9@^nwrVj7M(_A<5DlrEDD$ zdV-4YS`3V^;l1KXE-X%h>(U>MIn`>jcXb=7C56iHT%Q=1wO)$vB-HCu?Dk?@B)UB9 zB2Ut&I8>a1wh!y#0LH8dTxlo9^%<0`A+$YJ$rWDclLL8PkmWhqI3)`Wd6JW737JwP zDx_>6I0T_j6iF)DSb+cyD$hyNjB#TBL0Lqq=LQ&Kq2P7T z#q~WFk1lcU!e_X1_cB*6Uqa@hthoe^fN^Tr=@+Q7GuWv3C<5?e-+g zS6|`vKmP-KSw?oOGm;+!eB;wE@a}snnC>3E7&dlBG}C}BHKH1MOtz}j>ovORnCaOG za#axLxdojVjfrDSmZM!4Z9I$-WX6yv!=5)uHa*YAPM^eGLlp&Ut8en`$DZQEk!dsz zSvKI*u?04goJ+g+xVN^&)buRH$|h$XKf$TSB-2lyAwPSB{$uluHm;KQy8P(P_rR|* z{p4}FY2Z@LcKz= zJH`*{q)CPlf=VD+Y6VE8Nd__doiRxQg)&IjK^YikHe$?20oS@?5-l)VpbEp>sbhTn z>wh2mImxYeF4gP$_tzjB)2xR$j*I8| zHnnjCNvaw3Mz}$M>)WU)T%X7d2}4DzC`i(Tc$}b=u>}6YMP?y|792VLan3#ctK>>> z=l%DvHM)aqAV-51RH6!na8S~)H&BcVXf_+nOieL4eT32OJv`4xmRt;QaHNapTMv?r z%^_(%U~XxS>h1tnWvuPQj1o<HhJOWPqDGK&G%os$j;Ut zUmE8;_riIk7jojs7x6y+EU$n2PuRTrI@!V;XqR(Gr+Dk_E8M+(jj4rWOwPmu|&e zx;~~q5>#sejl~uG`j1#&UZ*KT@^naUG+yB1Vwi17=5xtPN3%DAy?%yt9KQ9fA8_UB zDxdq}mzb#9Nwz}{+IpKvVXP&a=U`9>M^LE-w9*t$OPr{V&?!6nBkJ`C&l9Y6hM2x) zm>SYJx9mb=5T;~70uqT*nog>4!YZdmU8a|g@Ycn*xpnP^Z9QYC*6RH7FaIh=Ya$<> zc=2a!w=hn~(wtl=8nr5oM%A|Tr3JP;{=(-u|LhB7c|kHxX|$RwJ^n1cZkHeoi7GYA z{B))LcZuRXlyRc;AD8k0boqVuQQi0X^5;KAr_-U?sDDVa_>mjK8n@U&(;CQ&GKyHl zEkc09GJoVzUoO$YV2;m|_$>jOx7+$-G?r!5alE`xzBnfd+pakTFM&$+ZaLBN`iYLct zQ8E&Yt(mmS8ISr@{3-GxqZ$SH(qTA`8D=T%YLh7P$efg^h2!jW@6g@bwE(%&MoS7x zc!4gJM{H-P*VVj#C&P^@ymh%lmRTN)ZKo&jP zGCwy76&KwZB3(O&I+%0FQo2V&0GE}rLG`5f0JO_M{;$o#?rXU?9*7|Wde=!jvgu}YdN%ElC-Z+R7g zW5H;nq`^j6_f7{l^b#(r;v(gjK36NWBf;IhyZRAk20x8EWv zVw_2j^G6q$m|yO-W2&obNGF`6I<7>~xJS;pf}T)+)|T;nl0 zGsUHM-X)46M%$xO7s_LLZVoN1%FK;hH&|X>rYJ0%R65q-D+nW+laowMO*6l=h!+OD zfB7;=lHmCsj&z7B5$7L&oMx+S2~wr{%SUbuDdnLRm(m5&F$96Yl?8LH$c81y<@o6( z^1`4B+crexNXLfrVVa|p96!{w!U$EQ><$t(dZ`^m3EO%M0%%mKeB$$8;`3kp85S3p zh$k#3 zw~Z1WaR$TKvnir6fGR!OyIfvq^FWgAr+=aO*L}C?Ou~QfoBuoanwHV5y9#R7RE! z2wa;M_s8*}je-!MkreMV6K9gx= zFQzCALKH};3BL0NS;>A}%5vtlE-lqcj=XYVR1kdUO$x`MDkY&(OvRv;4@pTo9%h97 zs|W#OZF%+nQ|IC5zWkFnhL9GbVU$5QRtB?Cl`Kp~9ABKG-EK28KhNy+Ec>_bknD9B zTfIihDD-@CmD3+5h)k2_1rt@Dz0sI)l2h}1jHgj(W*Rkq;g^4%7ry!ncwWV}h>bmw zl(LvC*Yl9VZV%xFgvU=~8V$xb-ovclfiyw*K1fMtcaMAPLxiglLL-%;S)XC%_<8*H zER(Y**uQ<9WZc8aQe4lY)~cYAm>_T%V`r|)kXRmum|8*P({p!2KKUk&|@w7F{kvZHiew^afOUTf} zd;ApHdpAh(0ug$UWSDV^2|eUi2iY4z`S`~A0soRibxm<_Y+76wkPAV6APZ_he(W6H zW5+1|^lxCCV1y{;b4tANB?jp^M3o7SKmB!{{QS@1 z_+iO~7KcXV!{Lxxt!DfEhj*vZ!bMKaQ;lk*(!h;Nh^(xIv?3kn^af+JbZJg6a{93^ zGJpIGI6iJvp|K?B+`del7evA#s8kS^UtVXQ~?Y7IrM4Ra_$IGYi+$vY@+~!`` z!8lc1Kji(D4Kh^<%2&h2gPT-&EP z)8?~JEfS>}LTN$?ld|As%VT$>2y(&L7fj99IpU_3r$hvT)Uef#`{E$p))ENIu+J8L+;$V&V^M4|AXe}ZCZ4pS63pLvGp*~g(! z6r0;PQABZX9rwf{#k~!j$4}Z0TdhK|vyY5Iinp)go&-tUj z#yK*F`{GmRoepL&!W0GW*FK5+_-W$*_Fuv3_J=mZN7fjY&>{)^IsD)RMu+$kz`>Xy zNjf4|l0v0;G61i_)Iyz)ec{V&yz>f14RJlFIf7c`A(bJVm}c_mIs9OU+1Ul6qhBLz zpRxV?!<56GEcbI&8#x|n|D|kUCn`-Q&pprb{w^jR(ONo>JAItH8~ZFg_B`_^AIJAY zl-3k!jxttnw>EPW=?1J`eVhH=Ez)?*_Wqdfzk8dt+dk)yH}Jxm)oXPfyll*|W`HSt zq|%5qM2%deYrvCKLYMAdpXsL0+1VN9TP<3X3%IUBmd9LK>!6VqYHteiIHBP>G+mbf zm-$+qc$7e)INGkzthkH^BUY|1lk8}+?H={n7DZS=`VJ;7s5>rh#ifO0vT$*9gi{M} zdVK~7)LV55m6K+gdplc}7ZNA-kODmXzk*95nAO)a*EudpZl@m z?v9}n`fLwU8nboQw)goT{>>j#3tg7ZoWt=deBzUzU~YbvKmYT;Kzk9D?MJJGsH`C0 z>k=GWK=+44zw~AFP6r%`w>WLN_Q&RNrrOA33#h#=vRT7OiB2sJ&i}&4ab_nGGi{uv zr6!op0F$Kz|I=T(&UB8=^`b$MGqQVU)%U8AZSmL)ilZ8q*3IofWcj;^b&_g(k~>%4V)gcQ(!oBi$O$SD((xJe_Nhb> zDlZuA@8C#i%r4TbxP;wJ)>islxw*$%*LQjA`YzXQ?b6xqv$j28buVUnbI8`(nC^a# zC;~#!!qF~{29xJBYLir=1~N;i1uh$V+gAD8Sf%(PODUA$*wh3Ql?cak85WwM$}qm+ z$b1drA*;9d=?!vBkrUObIDTLu=|-W2!_A!`opC{$=j6gC!O+$KK91*5XvO9IluO$q zn{OM##6*?<`EULPU;mjelV@Evwz_C73H&OK3`pXHB#te#UkH5HCD*VsOv#jHX?_MH zJ+^jt@g2={t4*cRLIKTIiwhSXr`2rWU%tcSR{sIt6oWXnK=6g~dy@Jzf zp!fTz{VuW+VMb$gnqiDadLC+PA6c)Gzxke3B77hcRGv6X>+7HU@f*XD4zK>;2mHYw z{WbUY6mMR-Mjnruo1G$;l75`xhE2jsooc0ml%CZT$`x7*oJxym_9%X1k~m2j?R8Ow zrgicHwPVlHUOJB(cy`!?Ee_(!?)2H-%9swS)PssuH;e~VqBc%WM3Tk|-vzH$LrT}ye$ruM zSn#9GgnO~z-L-vU*W>x8=E(+Q;=-}WUJPBw;8&pP6hxjNbPaKDn~j^-xpZZP<&7Rj zyXCtyq-kpPddo&sp|w>vNAcY0MV`BGn$_Jt3d!W`9Ba!fv}+NydJBWVa|5QPr)b>S zMqXR7-NJ)P!*ft+M)AGZDQ>Tz*0#w0jo>Fa zu|DML>Q$&tRWaCp`fxO&b?h92?KQ^3K9%|evvZ3)@rkeS>f3KIrB+!TN=D-W=SE$e zsEG`!XsxNt9;d(8!Pf>cb&@;nFY!m;{|nM0Cl`XK>T~AtBiy-s2U#fEfuLOt=%K+C zB#gLn_Xh6LDO}ec6xnD%=ouW>L#cv^dXs8YLFFm6rb{H-EXkOA!-VBdhnZ##Ur74> z5i2`GT-Rf}qiOn*mgmt>nsks-#iQbAl0tHEYe?c$8INPe3h2dLxv`5Jq|8PYaDA@q z4)7)g|M(kAL=_K3M4S)k?`QnkpS{E7H4FB19LEYe7>(;WDD9N3XG<#pI6B$j?|tqW zoJxaN-o4Fu6mxrdozC7a+gscG$}j%{Gsn+R3a1l(;p2oC&NCX1aHK;RMU007lmPS1 z&*26>xhmk3PebU_?e+-1@&ZA%!e}%iJUVNs#XtKQGOf{Rf}Cnm`Q{fGjfTkQ&*N7r z6!VJo=q!m*1k$DQ%`c#}W;h<fuJx}Ay4THT@(~qf#W#T zW|lbi^e1UA9OcgYZ}G;PZ;;YrR8$xYbNc-*-R%`j*0FvX!o6RIWBDLf@R$!p5MvB^ zUN9I8a2yMkGhSd(sX>76hxB?q_E#=a(OqH_(XNLaIerG=h9$S%`bQ`Ol}3}OTBF-@ zdE>n`_6O@^S%TvV9=ou}&Q^~!QJ^&Ks^qbARgNtkhn2lPz0nx$R%y?l!5@#9s8(3%4%ixw+3Af~8E1H{Hd}ighRU!$$k-fd zq$4oWMY$fihRd6MHWG(S3wCyP06|e0Hg|_41vDxZcE%YO*E{qwkDE8Q>2`BOA!tRC zI2ZiIYh6alFV*a=D1|Ot-EFRSMkK-j&LJUc{%D1;)h3x7QtNj( zJ>6z`zsGKxaQea%xPi;=&NdE)-1X^=Qnm`oUT2KnPw+jLy;z||j#fQ9H^2`flosUq zh)$w-dv%|*P~duu_6MwQrR;QlZrt3aUX%2VWIu5ZpQpjXB8<_cET@C#`>3KI2tphw zS?i|!;kRGqGtZpGr$DKKUbk;2*h$8>Uw#YU3;4xf`FqqS=P+7Rq#1XvU8mpc(WuvX z^VJ_Bft{TlhTSe(YwO&(eVcx_OM7C1rKKg};fR}8t}yEL5!$f1yvoM<8lC+;)>c-S zpPS>g?|+|aQ~{+Kbh~UUukuU3{%id4AO0bCuHRs5bA!FDZQ{Xz@Bj5*^WATKi(mT> z{wKWtqaSkd_1C$3;|9;Z_#!7yo+9vn8u=UnC@+nsa*Yj~5L8I0ttk&(oXmf+vlTTp$I-Q+e#`_(rjTX~0ZJLv9 z_9u^X<;pE4rmiw`at32O9&FMor4H4z4>k(eX|Lnh7o273A%;h(f;=}2M`PxXoaV;u z8=N{a#ni%avO<+UfKX&H(s7WEb#m$tN60|Xt{c1}qB|}~HFWk<#<3+x83dVfSlQ4R z>EJuiaxy5OP<@0M5a*hmI3+*y2Q(;EkZ8De;|@|v&YgP#S*g+3UFXS#X~wk)s>e=} zWFt--UBm;9pE$xRZ(JrD_o)Uh%X>qPOixgkK7&N#`E@3z=czYabbATgYj-e3k8x30 zU|pV~(gY(U<18ii1W8wMdpALe(9Vbiwhe!90F}}`TIR5X7 zC{FM^>l8IgQvT|tA2L5X$>+cJjYIHWRH;xDIp6x@KW27z&f3Y9?^G#8tybe_fBu`i z^~USG_1YU&{X;*Y$9HkFAYO0zUu&olb{NxATw(<&Up1fXtPQ9AQ(MLla2D-ngLH zDLA*-fIR2cJ8w{FH1R7H6d}U%N)ETe^Fk&jXVF?S9`smS-JFe$O>pw~6g_7LKd6)E8e_7eE4qCUy+}DE5vW&EZHArDmz(R;p*-tV~G|hI6 z=g*&`S&z_8NS4GnzK`R&6j?$ky-1z|p2s*#sXHl)^Hc1NGcMoT;^x(R2%uRDaHWkT zN_%9fW>_fpRA$@U4>S`F?)?ypQ}V-C_lNY}exKAhJo(sJoHQXD45%$EK@ee7&cf6L zLK)5;KS2}){N;Clz%b5u?Bo>9DCG8ff>KazOtG}I#EF?YD;>rDZkMd+S>Ar3Sg83d zO?d1MV^XEq>cyl$tXza^q1oo(*_K7-!F?-LaNx^n+r9}SDcIWU6G+KK%zxa#1^VVDJ?{{c48@&GNtEF!Ucz%E?6r;hAG)X_C-~4EF zZ7FwdRXxmMks<|jW5e5bx}2Y@(o$WPZ{FnSh37EFlz=WpAO-c-GzgC@&)M1D;M%QQ zv`$X3R847B+cXb4##$SndmKRns`y*{q%lqa5p zE(~E55L6;IH`jUWvB$`Bh0Zea%(4MJBP@Za$Z&&73Cc56Y7->JWwhHP3SAysY%kTuO_bppbmvC%*hKNVrFB}Xd%ZKi|WJYlD-S=3&bBBdyoij)0X#_5Y0%0J} zQ-=Fp#+hbeZh^_kNw&8)n4O+tZEH+-7-NtOM?D;q4r-`&bc{MToh+M(&v1TrU84m-n?M(8nJk8mBIu@dBk zAO>6WZ+-m0IOP zQR9&tW1J-Ph9ldNFa}2)7%^G^S)9Z5%>id-Lps;4P@O$aquC-a3bZK*8%_M6Mw%7Y zTQ5(Uo0~%omKmh0q@F`Q-6EW>AO<}=KcPO^V5%X}qJqjYKI$^Ykmeb#ZXXcsiruq;$I-oLY;)pwIJX0+Rj)E9*H*VeQq@F7ID?kLx!iyL(+!p4e2f zOoN7*W-XO8>opo`NZnOdy-{cmv~sJ}kRs2Czt&p zDucB^;%h@zIC#=0&J}4IbLZ9_(&3Pzl``tDu)N%1ud~IcpFYR4pZX?mzWO8XTz!w} zGf#8<)-6sPUF7NKpCL_CHdb%)NB{QsiHm}UGV047N4ct>+#S2 z5B~+zHJ?*QX6UfbvALtH-n+}K>(}|6fBm~S6E3f9j4{HhrYy9ooLQJ-bv#4~c=5Ss zaUbDt^XSPpf+WjPT5}L%%z-q0nH7vOxUxPbj1_M6%LsEFtmNJP5a8oiXv6OA7D7U$+8`Agm1Pz}UT6xfSm}>14DD8%nVAVzR#q@$eF$_EWf(LiY0Qy6qd29rx6fofAdLJHB4G|wM9_G`M#sTu zM3QAlWvBo{*JZNNW@BrY&fX5jD583eUawETKOjkB97i%9j~R{=;&_*}odK7-Df-9+ z3xP{-&tcf_G57QrkbZ^7FFeK7cP=tqxxzxT%4{v7HapGi{50{P$7^q2!|lZ6$&e)1 zM6QR|aJaVF!D-G?6d6CdxXd%pCQQ$K6zp6G3S~gJ)<*)1e+OISm@?-S0%B#zDe`EBB#3Z@VlWONA2Lc37Uu%+XGu$N*L@P9 zc_bvnU`Ub#*L4X4Tbvmn9t{zW%Md{nMu4PNud}?Y*xTM^yyu%=ShYL?$VDj-#kr$d9?_J{LtV^83>TYsqXK-+gfnZ`{mf3|RvNUIR zdxL&=565-TdCpdEM1K^ci-H6Pq=PIwQT<+zUbjP@=ZAuF*1k-ZE~f%h6bzCcz3v`L zX&hsydL9mfOer!2xw7Beb!|GD6$OR1e%gD3ge+C`Z{Fppk6ZbijlF%IIDMM!EI=zo zmSt2b5piD7Ni@4%#h{;~3&V0hW@4s=%nS0y5?yD4acpVHzx3<>h?oEP_qlm*gKKy9 zm|gGkvCn>q=fC#%Ise69V!zwtop&zr-leyh3UW4gH<+59VqgNoFe38(2Y7uyVPgnj zFpAmQ-L*s?MWbC?e1d0y&5-IvBsvmD{r`a@t<$gA}# zt;reIH`l2(=WxQBEuNJkD+=P#7%zydTTzyvDTtF4Pry<$Ac#{2{epPC&-T7mJJb(A zpd;VI5rSqlB-fhFPS1L9lpEu)-Rwv-QvL$5y|iBqKO5gVU+0AW4i z{mWOFYqdF7uhGh5rY1sqz8#9Lc869z=ld_?*Cv=%h9{5BQwe;us8D1X)90RJ5U1R{ zv%!&tDduL{hw?dDu4o>A5*#@Ifyk=Ekm z+M91Ncj64~xhZO)$9S;AnNuxl6HBC-gCRTI68AegADDn2yfCbov@YAY##q%5tt}$- zVDtEaZ+$!*k4`@&iARK9M4n|O%`zd&a>A%ap$b%9pfzM^LMRmZpd{A#n$`W3L3*$$ zv?U;6I59gxAO+1@g{}QAn|oHI+GumX<>@#j^qj*D``~vwxMrF)eAi)ZbC;>R_i%iV zoz4i1$5uy@A7I9?#pnU(vb(>}{{AkW=a(FJ_0aJmN`G=F+ug!GKPd!xQJUCeHLEll zp~~m0t@p))kxgqDCIzw7_@0lWz;P6=BQXw044qD&ZntOK=*gI#u|Dd9&28@9T<3{1 zragzOE#Lf|RD2}r_n}}h$ErGDfX z(*G&tbBwWWNr5Y9ReV~ZM=Nls`!0cFjl>5E?)74}dNxGIaY9zuJaaf4g0%KzT3IUS z^xQOC+db~x+92-j<17YDPfZclW=S&#ME)U{OlxFjlNHQC#IV0FN;!O`w3Ug^H;}U_zg@ zt%6+NueUIoisv%hD4`y{vy=l zy3X|MEPAWMiL*yIUKcbjoFF+mO?RnA(YcEm4te#B%NRFe;=%&MR1pvQ_(eq5DB2S? zrP|*gFrtPNNs=@#>qaZl6u1tpdPEplPmm+WP7rt=>sK!lO`oK>WO+ItDW7A2iVMe^ zK2y~SjmRT#1)dOij>HvK1~T#l6~BTmESt^xI~T;`nDKaw>-+Wvg;r@Ks?YMolZO5M zJzA|A^~MastCC~~>C^pNJK$tl($f7KJBS$iP^3W~o@S#YA?Fh9Hsd(Kl@4({!t+Cnbm(`x#G?VOE0C@r$ra1}l(thaIoqP2yY#Z&p<)Kcpn!=+ zg=*v=0-w&_9*%&=7H7D*wnb8=P@ZS8NEmI^0rT8?89t(^us<9z)0||!RcF1^qbCPt z-E$vdd|(dhI+BX(5CuWmo-O553q_$7>I1m5gC{IY!=C#-efOXK0qaedo8+J~Y3a^3 z%{m|+**^zu)Zx!*Q&>A}M_PR?VX4k4hiHBVcV&ZTpLv|E&0W6p@@wpF?(*d?eu|I1 za1P&(IQH@9aX9SP4dveDK83o{Q=Uk?N>_EM`JXj@yK?q9Es;T>?JvI98--VK#&)?g?wyn zFxpxMG)_=q5G!h)An+>;a-Tt}tQNCtmEQ9#$Cof&^(f*Yt^uhPCuZBM?e`fb83you z-=4)7asv=W}$Sl1;{4*3oqu~zD^mNQ1;`?Yd9ZXH@hdD!Su zLFU2lAcQ~}O|BH{>&x7}d5NP7(-<>>*9=(v_;W}c=9NLZ9$Oo`OrJc4UYI6JGp<~E zgIc{#V}6F_^jAoWg3)M9G*RQ3&pgBN{e7ZJg{WG^b$#-DKyPc!Y69yzp6B970Wu`R z!>?8tjtkzobcgl3%cMz6p4oRZ8V=ao+Tn-o5a)|uU}AFeC#6yb&-bX*sIC)`*X1+w_nts2BbX|PUBg?Y#l+%YBzzT6bYKSKu&;WXHa~w>P z@1Lxq9LXA^8N~@{nh=E%y7YphObL=SMY#$`O2QzZR;v?_#@3HR2+#&)G}3Vi90^%U z(cdM=3Qo2ol+uhxG13T*HUe-xl#mQYV``p*NXPW{GOE=GB_tcW9q#RqtkkII*^Mgh zgCVm#KSZm3aQh1k)gZ7syb?~#PZ8$@-C<1Vxd_+6lY-E9sfRxGz@_SYxV~?-l^pBd z6lp;tbeXP(?2S|IZtYR81WZp(vOh}b4adYuR@OfUC%>^>$Af676vBz9Hs+9Son*9y z%CJO4>DZ#)3#dgNnaS`X&Fo?u0pxki?e}l;{+l=1-P*?weU6@<=kaGx5jC3h z3l9;7q&tfJ?R{=uyu!V!SLyC;)9rNu!Sqa)KO1KkS-Wz~h5B zuLqyH*4ABhwpquQ5T^-RIM#wJ^jT_GafGm&#&N8Wn(JESLDxkHE2vhO`vXKJ?3`n= z7BM~9V4_`Petw2H*KF@~xp8Ot5L#{y=aTl1ht3l)rF>_} z(U-y;rh7))&Y3X=U1(;G%u!^D?tX`b*=fQcBuP?KQQ(JuX~X6q9BHMOjHbw}@dEn( zS`k>AG>u{P&Ni?7<=b?+BeYiN&WMfGJ-Yh|CtrAq6o)+Bp|ib=gn7N zWjr2}r<&g07%2qX>mBm6c<7BhvR#`i%^=QkTua4NLSS&wjwIIwnNp0hf__>sxwJ@o zdX}QF9SllI6Qyi-NSTKhz)yEQ)K4h~jn<&?;841sp4;wBo);uC!E+pPZHZIja6zV4 zx#9uuw{e`<`!xcUCuGSOfmIl{i_Ad_ZS9${lA49Fj+6z^OAVEZM-cfq!eu-flPT=? zbtKY}+oqj2pJLJdk(HEN%8`z1hL8)B{{W9WLw{*UxvWKb2Nf9SD3uC zYcrOwFQg>T6>(Aoy741 zj84(%fGp{t@)4*6qjP&`>C(fzw5Ij~9~{YOG(zWgePmgR?|Vem5Z80SvqEKV~xo|;d(w2Lophl;si$s^7248TA)-}t{6}X z;vy%`69#e0ZnsCTH(;jSqE(G>qY7t_gbYRr-8iKer=^ptIouQ<`o0fse?yk#bVo6v zXBTZhPEgv=AI0nlL%kB%7pD)Ewho`AE3H%|0;?RD=Y*k0ty;kk?3^Gk6j~N216h`p zun%(xYtcp$ROj)k^BDXCCrd!sqT2OA_!zf_8&08%G5L6lY`l%usRa@mf!3C|<_A83 z?~{&`5@T$LM=|wA4W)9lvMtpE7hN2C5Tgx_u+C3uUa)#|lWHSEtAfsUmtJSY+MP{? zqY=iybmVZn?bB`s6ar2@bB5E;Um(j;mai_;-`b&74WUS=I@Y#AJN9{lAyW2 z!;jq<8bMq@ZY+#EQ;HaYrJ`Nwb*D=R#$o#r4%?r3Uf2O-xd4kiXEYuWCze2z=L%sI{rx?nN)5;J zNqhTlCK*|8& z)(}n)bXt0xV|gpakd}3fR*LDlDLT6y;?bBij!Ul)D^Y3;s8ZD(tr1#NZPckWY8075 zpU>G^-R0`rHyQTFIIcsj9uWl|6gji4fWS2j`$OhVEHdu(xbxmk*00_}?ez&Um}bbR z-^a_W9b1aV^#s*=l{`t=THkx<9l4KMl*2S+!+i9Y)Ze zoZ;ywA7|y>EpFaj;pC}PRKpNm6x_ajn>0zS)KB>mR9=uIiH#(}7KCYLxyzz7qffKc zD$xZIo!wp1c+AYq93OlB<47slxP61S-@QbZ9~doa#z{hwa6d>{Jzs5LoGVfd zqfE0uOz_-3g)tOLqgC;tDDkM@J3a4faFK2WH=4oVU{q12p=H1* zH?vX7y6lSkQ+pvjr1UK!yPS8JvS7&zRYqIGcpOuySLp6_(Ro3=X**qLjnbNNoU*mi zBag>SPK3BBg(5|`9#gYTCT3dHTNN(9bA_3uBg~&T!5e?_H*~LDqY=8yPPPc5fJ&>% z-o^%Mr^k%r(w?7Tb7hM>Hr(6nFfzIvFKBd`?i*pqi~ON?@<`5ie;l*E-$6=;LKS@O zXMTZ?KYf<}>wojl`IZ0RH~Ec!^y|ET?JiTT8habd?2Q%Y&p*z1(B;|L8yArEmQqH#dg-FaPmxF;IYTaU8)bue{9S zsdJoIn&a}Nci7(T-p|X+gH%e8(!D=b#*h~3Fp52Dy8WolA#o$2gAZ_WCSN zPf-aYYa5+q2VjL z{?ZBXD{~-2TX&V*5u?g9M_SuyD|1w8*p}TaAtXo_JMUHxrNUZSA9o`JNs^=U92Y^} z?~@d^lP3U?EAs6Qciy-~W2Q;F?y-IAF0L04Hfp$0h#v;jDv~E(d=~9BkX}eH*2t)W z&SM7qea61W=609L;u6C5QI#s23OcO@JDn~Y8r*6Vtu`^*9w+Izuu`hdPh$f>DScSB zM9-c*!}{7X+q=75yLFpi{>rC0cII(zUU{D~tHvCbaTXJ=U7r8sXYox+KX+-?YdrP* zC&<%`V++&#_y6)=^I-jB2S&2&>01Qt!HKE$!vMjD3+;zfsZvghahe{InuL@L$1&Uc z9j4nh)zV7Q8^*wcnw{aZwid07jK&_QsTvsx-~PB5yg^d1gu~uwFnxoSMH;&m|AEKt3 zFwsKiis`v|W@n~ZINo9LnWveUnPvUb+YC0>*}T0%bE-{LtFpH_g!VimIp(E5{XV_D zF0EQXE6W%sDUR>rH5zQJ_NmQQ5xuOOA!(FwP=#S{bpyu{cpexn$r39SD}O3~jQcZD zgpl05yUeGbJWjn<lZ@>OJpZNTj$j1X-dE;HqUHBMvPgCTIG>IAXdMvN3 zaCC8+Yd7xl!qeyZfBx?8arERVs-Z_J1IDT1!V^zX*&Gr1g3HSrG~5yUMUAQHX&SW( zfAR85?CoqHE_}Nw9>yI>BOd|`{-o=JN+~zvf>5oRlX@-;~lte44m5973 z2%~^zHMEP^anRDSetFv1X>@6soEM65k}?>LNYjiYvp`K{z>8W)ziEf2Wjow%URfdx zN*;LG2EI=>QHSh4gnOuPe((WWtFmUW7^=e9P14)gA#}h@G}u|$qFSp_env-p+?VR0yPBM&Xv}%B0r{~erF_|iG$2AI>G8YU8 zD&Aqro+c@-bg5P&3N^y<9X!v)4QvPVgEjykQVEe#^76|s^WE=!_fT(jbA648nFT)f zv8Ny(^WB%e&)obXCMyU%mv`T~$jrhLX)H=k`rDw|C2lyZkV?Q9n9LJSg69 z@beG;-cGEY2avW0Fb#PaS#o9T9i?sA>o^kM_b~`6m8vavODMX=LcX&+Cr&bke-*uD!~|Q+G$GU@Tp@< zoIHL6*qmQuuCw?@96^C&_bb z8SNMzJO4Oe`s&a8zWVT)BJ^3~X%ga_8o?5|Abi2VM`!;p925zVb4j=aFT(?I{~9;#F&Y_{#SQ z{D3^qP+GIOy@l&IWLd_$moA}{VlWzW_x3G>F)SQA#f2p1tv6mH#pf%Z{|rBP`6Y&< zA>aD5e^-JmBsZ_U$DLc(5yG&wu|>bz;Rhx3`hcOim(NQX z4Pl6qhFY_UNODFyT?V+gQZm@sL5=GW`V4ma2;q{BGd$lg)_r7D!ACOJ2$*Uwka+=4 zH>TF8u%C<>4l^3<28&Ba==U~gO-uUwIq^V|X9dIlh2m*>cKU@U1coh#V zqAbe}y%@AH6y-^l8_2Vq2R@R*kvOGch%UJUmb~P!v3if+|ATFM{XThK@bCWY&*=7g z7+rQCw6;?9#_~F{EJKwOal1GVBtdPv@c?mp5FxDU$H8JYhn=v)Tm!>T(~Ua#%m*XL zg8~pAOuM8MRz0K05kj)9N|vOtE!g6)J#1@>2eigZFrxho&kG3Zv*^NLRDpCHz@iln zI)sN%6#?%%4`fn5 z&QYn17RDePk1v1aYs|F*-n#f6&p!7IFa6bDaBpJ^;W~D3Weg@M5w*fp4vbdj0t-<-Tr+DKn>*}M50>^R5^PItOK%QlG z=w%GD+#FH0Mxz?By|a6`h+WrxDB3-|=nspZZM1oY^-)E(u{PkOLMYD)$ve9bLz$OG?wOATi@gDH}BBd?~{yU zluv&Z=1U%pBb$0%iRJqJH@>2`aBRgb9Jpi&)CXicv({OMFe z4j!Zdbdj;&8SoE&@n_lVj0io6Uv2Q&&z@!F&P^t!7np9>xN-dkC(fQ@Vse75%?-M} zAq$H~m~7YC*x2M#pZpZ7H!iZev2CM*<8kWP5--2}3TMuqB^!?!CMlusf^&!yMzQ){+ZTv$LCiqC)HbG-EJZ*le3J@P_v z?un1_sNooa zr4Ao(Q?%ANWmEwUS$PLga>}8h#w7?EMD1Bz3S_QuT zywE2d_mPg|#OV`+M)9%ASD2oh;Q#b{|Ay4_IpjPa6!6l{c?zu&%76qr&(eo!u_8-VBq?8Aihqj%%OsM{bOR$?-v& z@YauB;+;=_nqTU_gH`j3+1=ac=f3_m+#q0gbDhpOAqoSYdj3;< z_A?*n%Eh<2eCaYuf4Hmks73#iu19I}ey~VC_zWo}VHlQPA;x-2IFc;Oc~DyxEPYmK z{eaA=Jmj}1r7%+B1XZLP(z*2(z zcLnOMVQpHXiJUu97&=K-OVnQYJ}^#D6JUm_o+7{&OLpW zW5=dAHrGH8MyPRy7kGHSOFkMA)ayL|+!=0MSz~>>i*!pROlkkVYnQHZ?CcU}E}UWI z)?MQ97=<0^fnhWp)7kCOm~2w7PLP#@-;a(MhlH4e)?3aSZ(n30e2nfeVQF!WzxnpJ zaH0msP8_q!8lI%z>+tfMuX63yGLJv?0#avOzj>SUXHL-X_1WIsMC0hc|igA1HEeS*cKN7>!kVK5y1)C>P7 zZK6lDZa;V_eZW|h%r6}!kU5E#j0QtHrOy&vFCg$7JH)Ivtj1PJaoyV5!Vg29eDX;= zFXa8}YfR2Gsrw1-r%#i_DU~Qd8^w=aeS^sL`0CGo3D5I*_07x7&rEXb=1ul`Bl0Yz z*X^=!;u!g@8bPZ?U)Ctp-XV7SU=0;TL6)S9dOa$Y5UCB3CuyHtqPyK;<@y@kVM1%V zh4dWy-2t^i^Zchz)2dhSRe^Q{G&p1y3P*xcEFGQU*Z;$xuQWj7KAitRTxWd_Q2&A5fHnebbY(^!puD{!{2mJs`?oVwM7?Cu-z{ zA(V#iy!0}&GqY@N?;(Nx-F+q}XFw?$)f#Bc-CNgKJ$01lo;uH4Z@tOfkyF&0E!4d& za;2G@p5%=;-lU&No_^wSbP@B?-@L)6KK&`?rULf1M`)eVXitH(-g~YFNl559boM$l z8ZC-Eq19}VB{|J{g?o2yv$MU05*}yIo@Kl9HjkY-&Fbkc!Y{4^hb{z@}sve zJs?o_(HrD{>~-+}IgW!YmB<~VX}2fv%otL`sS~H|35{Yr7~#5-d-v{f`ux*Ov>RmU znEl;t_V;#~nOop%U;hTuap?}fMS);)vQE3*MAeJZqS@eiF47S^^Yr61n+@K4=Y4AR z3YExbuR9=)$Ncd7FR`_Lnx^zw-YfXa*KSY^6pfZXj1~ZClF;pR=-%zqv>r52!U7OfQAFYkS;$e-$@s^URB9@j@F3{J^(*S3;sNXvaa+8k{+GmQ$a4 zp7v~ufA_n8L7HUbc}lml$9r$R%O}3{B0(6EX9ZFS!YHItt&pV|yF0rGX_%d#X1X;; zy;6U$OhcsE!&}95UH;4e^1t9e`=|f(KF3!GyiyLaC~^#fdbLWDjHyJ`Qgs3x*CVPm z4srRO=Mx6LrMi|yYfL%-ieN{{))1;Q|7Wp$lewL%=n zC~f$)U;YN2-F2ccVqh zB3dnk>mz+1Q)-9xc6yF{6-1hr0$hq@ zJYrPB8x99n!m4>BaeTO_2ED!&`2vQ6`yGNbO>yLX+T{lq%m;7T7(*P74+%mCmnwgq zm%zY0&qBI@7XWdV5-9?|W}OT`P% zbuidsHp?v1_J9L_I3p2)Bu(h`d-va$bkW+dvAKoO2FH;UMNSeQ3=|K#S{kDZgyXWY zv1uC&QrhQIKJIrfUu9-`ifpX;%kREQmMbcOz?hs%mv3{(Bm?p^Vc6?XsGL0YSX>FC3-p@$7F7f=lb}b&-&eU9M^J#40e#}NJA8bm=+XyPP5f0J9Q7g zj~`=aEFO~If7DB~i_usTk+j&HJTFMQUAx$f!4VcJ?nsF!Js8S%P6NDz@z} z?7)zRr{qdmk!D;Q@1?MyJ!8ZJf(G|L>)`XHu$?Pqtk|~QeD`r(;{MG5_h%TQR2VV( z06%5F_NDjUFZuN5!%tX$_&w!WffrT~^%{Ho8J%9tSAJ$1*A$3C^YP~v+1l!I_1chR zW5oJi&eUX$YRhFbP`rL=7u7h)a4@1VQU8#V*`sR=Z628$KWf%sJ0jXj(C8HDxaAAM@&%+s zI^`s_lzr4%p^X8Nmnst$rs}vJvXp>7?B{Dcw0hKapZfGbuO3Rq--oY46-XfuXD^Rf zsSkaQ)mXZp<`_Qwzx|}=^wZWC4{Z=0J{<1hNzV@lYikNRpV9)qVChb_ps&Ywv6f(se;t z<&U5eFn?m2_2qR`p^0h{K^T&ZGlUd42t3z87mB1P$kL3c8q%I>vAeT}bSZu0KVoBu z62J2(i?4?l0Qa#y^1e8M?X^o}8Hx|3Ny^h#;v7z7wJ{|o-*z#iwmoUY!C>nnW&u3- z(tezVq5XRfU>u@6MSuKfnL}@JZOj9I_U~U$JnH&T(|cv9kfj&*qw^1u$;9vlbCZx2^BHhRksJjn;D(uZP%c;J~>a*S156b`}&{8&*b z1pECVS&}j?3YzUnBm#B7)zF6NsRoOS4R$VXU^U;Y`k^Wmsz}-2@>sjEOlzt^Pz{le zLr|>}*6a9zhcR&Kv6CD2B{BZ(gt z68})~Erj6u_3K={a^=IT=Kk~h@M;ndEY5@BSNY!`wYVQ#(1$0Tc;HXW{gm!+XYt*y zO|-VqhY#gj4}FjO|KEqc|A$t{zt4^R6h9*@F6o1hLhA=@Js-Hq^0YcQSi}Q6raXrp zf_yx9Ggh;f4}a!IeSw329UyFtp;?V+G-_4^O{r3k%wuu3Wx44Gw<;xT8y)t$F;Y7B z<%UWOSrmCp&NT6S7wOtAo$Gl>*EviHbzud(^E@ZdQi8~*--+4T*eegk`!{JYs6rj4 zh(b!{7w0*B?#%sfout`^UX3hMp#Oik{&v51vH_ z!@`F?`$NUv!73N`H=H=gWIlX7n6g@g@WYe=H_z@sxBYk5|5vV`uD$Y;uEUV^ zz$yDs*je^=w%Oa+vO^`$p*1y2Bo%j8w`fmJ zlEou#+`L7m6qD@g6~tPKp0HxE$AI za&qeLBF5icKlVD1FH)+&^MVhdXp`|6Ed-ShoUs3I{3cy;8C%K%00000NkvXXu0mjf DnZfGr diff --git a/docs/3.2.x/docs/images/apps/todaylaunch.png b/docs/3.2.x/docs/images/apps/todaylaunch.png deleted file mode 100644 index f75fba3bda92d1387dc24b7cb6d5eaa648fff69e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33233 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 KMNUMnLSTZ9^9~09 diff --git a/docs/3.2.x/docs/images/apps/upcload.png b/docs/3.2.x/docs/images/apps/upcload.png deleted file mode 100644 index 4199712ee7ca626e6f2b45800fce43336a6da398..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37792 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 C;!Mongoose Quick Start v3.2.2Fork me on GitHub

    Getting Started

    First be sure you have MongoDB and Nodejs installed.

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. -The first thing we need to do is include mongoose in our project and open a connection.

    var mongoose = require('mongoose')
    -  , db = mongoose.createConnection('localhost', 'test');

    We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    db.on('error', console.error.bind(console, 'connection error:'));
    -db.once('open', function () {
    -  // yay!
    -});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = new mongoose.Schema({
    -    name: String
    -})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a model.

    var Kitten = db.model('Kitten', kittySchema)

    A model is a class with which we construct documents. -In this case, each document will be a kitten with properties and behaviors as declared in our schema. -Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    -console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    kittySchema.methods.speak = function () {
    -  var greeting = this.name
    -    ? "Meow name is " + this.name
    -    : "I don't have a name"
    -  console.log(greeting);
    -}
    -
    -var Kitten = db.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    -fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. -Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err) {
    -  if (err) // TODO handle the error
    -  console.log('meow')
    -});

    Say time goes by and we want to display all the kittens we've seen. -We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    -  if (err) // TODO handle err
    -  console.log(kittens)
    -})

    We just logged all of the kittens in our db to the console. -If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax.

    Kitten.find({ name: /fluff/i }, callback)

    This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or api docs for more.

    \ No newline at end of file diff --git a/docs/3.2.x/docs/index.jade b/docs/3.2.x/docs/index.jade deleted file mode 100644 index 49a6b0e808e..00000000000 --- a/docs/3.2.x/docs/index.jade +++ /dev/null @@ -1,119 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose Quick Start v#{package.version} - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - link(href='css/guide.css', rel='stylesheet', type='text/css') - style. - body.api - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - #content - .module - h2 Getting Started - p - em - | First be sure you have - a(href="http://www.mongodb.org/downloads") MongoDB - | and - a(href="http://nodejs.org/") Nodejs - | installed. - p - | Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. - | The first thing we need to do is include mongoose in our project and open a connection. - :js - var mongoose = require('mongoose') - , db = mongoose.createConnection('localhost', 'test'); - p We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs: - :js - db.on('error', console.error.bind(console, 'connection error:')); - db.once('open', function () { - // yay! - }); - p Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback. - p - | With Mongoose, everything is derived from a - a(href="./api.html#schema_Schema") Schema - | . Let's get a reference to it and define our kittens. - :js - var kittySchema = new mongoose.Schema({ - name: String - }) - p - | So far so good. We've got a schema with one property, - code name - | , which will be a - code String - | . The next step is compiling our schema into a - a(href="./api.html#model_Model") model - | . - :js - var Kitten = db.model('Kitten', kittySchema) - p - | A model is a class with which we construct documents. - | In this case, each document will be a kitten with properties and behaviors as declared in our schema. - | Let's create a kitten document representing the little guy we just met on the sidewalk outside: - :js - var silence = new Kitten({ name: 'Silence' }) - console.log(silence.name) // 'Silence' - p Kittens can meow, so let's take a look at how to add "speak" functionality to our documents: - :js - kittySchema.methods.speak = function () { - var greeting = this.name - ? "Meow name is " + this.name - : "I don't have a name" - console.log(greeting); - } - - var Kitten = db.model('Kitten', kittySchema) - p - | Functions added to the - code methods - | property of a schema get compiled into the Model prototype and exposed on each document instance: - :js - var fluffy = new Kitten({ name: 'fluffy' }); - fluffy.speak() // "Meow name is fluffy" - p - | We have talking kittens! But we still haven't saved anything to MongoDB. - | Each document can be saved to the database by calling its - code save - | method. The first argument to the callback will be an error if any occured. - :js - fluffy.save(function (err) { - if (err) // TODO handle the error - console.log('meow') - }); - p - | Say time goes by and we want to display all the kittens we've seen. - | We can access all of the kitten documents through our Kitten model. - :js - Kitten.find(function (err, kittens) { - if (err) // TODO handle err - console.log(kittens) - }) - p - | We just logged all of the kittens in our db to the console. - | If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax. - :js - Kitten.find({ name: /fluff/i }, callback) - p - | This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback. - h3 Congratulations - p - | That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the - a(href="guide.html") guide - | , or - a(href="api.html") api docs - | for more. - script. - document.body.className = 'load'; - include includes/googleanalytics diff --git a/docs/3.2.x/docs/js/zepto.min.js b/docs/3.2.x/docs/js/zepto.min.js deleted file mode 100644 index 428f84a28c5..00000000000 --- a/docs/3.2.x/docs/js/zepto.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */ -(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.2.x/docs/layout.jade b/docs/3.2.x/docs/layout.jade deleted file mode 100644 index 6585074f210..00000000000 --- a/docs/3.2.x/docs/layout.jade +++ /dev/null @@ -1,25 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose #{title} v#{package.version} - block style - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - link(href='css/guide.css', rel='stylesheet', type='text/css') - body - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - #content - .module - block content - script. - document.body.className = 'load'; - include includes/googleanalytics diff --git a/docs/3.2.x/docs/middleware.html b/docs/3.2.x/docs/middleware.html deleted file mode 100644 index 1b5636ea640..00000000000 --- a/docs/3.2.x/docs/middleware.html +++ /dev/null @@ -1,29 +0,0 @@ -Mongoose Middleware v3.2.2Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

    -There are two types of middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next

    var schema = new Schema(..);
    -schema.pre('save', function (next) {
    -  // do stuff
    -  next();
    -});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    -schema.pre('save', true, function (next, done) {
    -  // calling next kicks off the next middleware in parallel
    -  next();
    -  doAsync(done);
    -});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    -  var err = new Error('something went wrong');
    -  next(err);
    -});
    -
    -// later...
    -
    -myModel.save(function (err) {
    -  console.log(err.message) // something went wrong
    -});
    -

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    diff --git a/docs/3.2.x/docs/middleware.jade b/docs/3.2.x/docs/middleware.jade deleted file mode 100644 index b9e9e9eca94..00000000000 --- a/docs/3.2.x/docs/middleware.jade +++ /dev/null @@ -1,74 +0,0 @@ -extends layout - -block content - h2 Middleware - p - | Middleware are functions which are passed control of flow during execution of - a(href="./api.html#document_Document-init") init - |, - a(href="./api.html#document_Document-validate") validate - |, - a(href="./api.html#model_Model-save") save - | and - a(href="./api.html#model_Model-remove") remove - | methods. - p - | There are two types of middleware, serial and parallel. - h4 Serial - p - | Serial middleware are executed one after another, when each middleware calls - code next - :js - var schema = new Schema(..); - schema.pre('save', function (next) { - // do stuff - next(); - }); - h4 Parallel - p - | Parallel middleware offer more fine-grained flow control. - :js - var schema = new Schema(..); - schema.pre('save', true, function (next, done) { - // calling next kicks off the next middleware in parallel - next(); - doAsync(done); - }); - p - | The hooked method, in this case - code save - |, will not be executed until - code done - | is called by each middleware. - h4 Use Cases - p - | Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas: - ul - li complex validation - li - | removing dependent documents - ul - li (removing a user removes all his blogposts) - li asynchronous defaults - li asynchronous tasks that a certain action triggers - ul - li triggering custom events - li notifications - h4 Error handling - :markdown - If any middleware calls `next` or `done` with an `Error` instance, the flow is interrupted, and the error is passed to the callback. - :js - schema.pre('save', function (next) { - var err = new Error('something went wrong'); - next(err); - }); - - // later... - - myModel.save(function (err) { - console.log(err.message) // something went wrong - }); - - h3#next Next Up - :markdown - Now that we've covered `middleware`, let's take a look at Mongoose's approach to faking JOINs with its query [population](/docs/populate.html) helper. diff --git a/docs/3.2.x/docs/migration.html b/docs/3.2.x/docs/migration.html deleted file mode 100644 index 6a18a146953..00000000000 --- a/docs/3.2.x/docs/migration.html +++ /dev/null @@ -1,40 +0,0 @@ -Mongoose Migration Guide v3.2.2Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    - -

    Here are the removed methods are their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    - -

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    • are now strict by default.
    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    - -

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    - -
    • $inc
    • $increment
    • $decrement
    - -

    If you really want this behavior back, include the mongoose-number module in your project.

    - -

    A good alternative is to start using the new findAndModify helpers. -Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    -...
    -Inventory.findById(id, function (err, inventory) {
    -  if (err) return handleError(err);
    -  inventory.productCount.$decrement(7);
    -  inventory.save(function (err) {
    -    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    -    if (err) return handleError(err);
    -    res.send(inventory.productCount); // 3
    -  });
    -});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    -  if (err) return handleError(err);
    -  res.send(inventory.productCount); // 3
    -});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This change allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    More Info

    Related blog posts:

    - -
    diff --git a/docs/3.2.x/docs/migration.jade b/docs/3.2.x/docs/migration.jade deleted file mode 100644 index 988c6964f85..00000000000 --- a/docs/3.2.x/docs/migration.jade +++ /dev/null @@ -1,280 +0,0 @@ -extends layout - -block append style - style. - table td { - padding-right: 15px; - } - -block content - h2 Migrating from 2.x to 3.x - :markdown - Migrating from Mongoose 2.x to 3.x brings with it [several changes](https://github.com/LearnBoost/mongoose/blob/master/History.md) to be aware of: - - h3 Query clean-up - :markdown - Many methods of the [Query](./api.html#query-js) API were nothing but aliases and have been [removed](https://github.com/LearnBoost/mongoose/commit/1149804c) in an effort to keep Mongoose clean and focused on there being as close to [one way](http://www.python.org/dev/peps/pep-0020/) of doing things as possible. If you really love all that extra noise, you can bring most of it back with [this module](https://github.com/aheckmann/mongoose-v2-compat). - - Here are the removed methods are their still existing aliases: - table - thead - tr(style='text-align:left') - th Removed - th Alternative - tbody - tr - td - code query.run - td - code query.exec - tr - td - code query.$or - td - code query.or - tr - td - code query.$nor - td - code query.nor - tr - td - code query.$gt - td - code query.gt - tr - td - code query.$gte - td - code query.gte - tr - td - code query.$lt - td - code query.lt - tr - td - code query.$lte - td - code query.lte - tr - td - code query.$ne - td - code query.ne - tr - td - code query.$in - td - code query.in - tr - td - code query.$nin - td - code query.nin - tr - td - code query.$all - td - code query.all - tr - td - code query.$regex - td - code query.regex - tr - td - code query.$size - td - code query.size - tr - td - code query.$maxDistance - td - code query.maxDistance - tr - td - code query.$mod - td - code query.mod - tr - td - code query.$near - td - code query.near - tr - td - code query.$exists - td - code query.exists - tr - td - code query.$elemMatch - td - code query.elemMatch - tr - td - code query.$within - td - code query.within - tr - td - code query.$box - td - code query.box - tr - td - code query.$center - td - code query.center - tr - td - code query.$centerSphere - td - code query.centerSphere - tr - td - code query.$slice - td - code query.slice - tr - td - code query.notEqualTo - td - code query.ne - tr - td - code query.wherein - td - code query.within - tr - td - code query.asc - td - code - | query.sort - a(href="#asc") * - tr - td - code query.desc - td - code - | query.sort - a(href="#desc") * - tr - td - code query.fields - td - code - | query.select - a(href="#fields") * - - h4#asc query#asc - :markdown - The `asc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#desc query#desc - :markdown - The `desc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#sort query#sort - :markdown - The [sort](./api.html#query_Query-sort) method of [Queries](./api.html#query-js) now accepts slightly different arguments. Read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#fields query#fields - :markdown - The `fields` method of [Query](./api.html#query-js) has been removed, it being mostly an alias for the [select](./api.html#query_Query-select) method anyway. The `select` method has slightly different arguments so read the [docs](./api.html#query_Query-select) to make sure your application is all set. - - Because of the change to the `fields` method, the field selection argument for [query.populate](./api.html#query_Query-populate) and model methods like [findById](./api.html#model_Model-findById), [find](./api.html#model_Model-find), etc, is slightly different as well (no longer accepts arrays for example), so read the [docs](./api.html#query_Query-select) to make sure your application is all set. - - h3 Connecting to ReplicaSets - :markdown - To connect to a [ReplicaSet](http://www.mongodb.org/display/DOCS/Replica+Sets) you no longer use the separate `connectSet` or `createSetConnection` methods. Both [mongoose.connect](./api.html#index_Mongoose-connect) and [mongoose.createConnection](./api.html#index_Mongoose-createConnection) are now smart enough to just do the right thing with your connection string. If you really want to bring `connectSet` and `createSetConnection` back use [this module](https://github.com/aheckmann/mongoose-v2-compat). - - h3 Schemas - :markdown - - are now [strict](./guide.html#strict) by default. - - Arrays of [object literal](./subdocs.html#altsyntax) now creates document arrays instead of arrays of [Mixed](./schematypes.html#mixed). - - Indexes are now created in [background](./guide.html#autoIndex) by default. - - Index errors are now emitted on their model instead of the connection. See issue [#984](https://github.com/LearnBoost/mongoose/issues/984). - - h3#arrays Arrays - :markdown - - [pop](./api.html#types_array_MongooseArray-pop) is now fixed causing a $set of the entire array. - - [$pop](./api.html#types_array_MongooseArray-%24pop) is now fixed and behaves just as MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the last element of the array. - - [shift](./api.html#types_array_MongooseArray-shift) is now fixed causing a $set of the entire array. - - [$shift](./api.html#types_array_MongooseArray-%24shift) is now fixed and behaves just as a [MongoDB $pop -1](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the first element of array. - - `$unshift` was removed, use [unshift](./api.html#types_array_MongooseArray-unshift) instead. - - `$addToSet` was removed, use [addToSet](./api.html#types_array_MongooseArray-addToSet) instead. - - `$pushAll` was removed, use [push](./api.html#types_array_MongooseArray-push) instead. - - `$pull` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. - - `$pullAll` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. - - `doAtomics` was changed to the [hasAtomics](./api.html#types_array_MongooseArray-hasAtomics) private method - - h3#mongoosenumber Number type - :markdown - The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused [too many problems](https://groups.google.com/d/msg/mongoose-orm/syKlN2xL1EE/FfRFhEFj4KcJ) when doing comparisons and had other bad side-effects. - - With it out of the picture, the following helper methods of MongooseNumbers are now also gone: - - - $inc - - $increment - - $decrement - - If you really want this behavior back, include the [mongoose-number](https://github.com/aheckmann/mongoose-number) module in your project. - - A good alternative is to start using the new [findAndModify](./api.html#model_Model-findOneAndUpdate) [helpers](./api.html#model_Model-findOneAndRemove). - Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber: - :js - var inventorySchema = new Schema({ productCount: Number }); - ... - Inventory.findById(id, function (err, inventory) { - if (err) return handleError(err); - inventory.productCount.$decrement(7); - inventory.save(function (err) { - // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback); - if (err) return handleError(err); - res.send(inventory.productCount); // 3 - }); - }); - :markdown - With MongooseNumber out of the picture, we'll instead use the [Account.findByIdAndUpdate](./api.html#model_Model-findByIdAndUpdate) helper: - :js - Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) { - if (err) return handleError(err); - res.send(inventory.productCount); // 3 - }); - :markdown - The `findByIdAndUpdate` helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases. - - h3#documents Documents - :markdown - - `doc#commit` is now removed, use [doc.markModified](./api.html#document_Document-markModified) instead - - [doc#modifiedPaths](./api.html#document_Document-modifiedPaths) is now a method not a getter - - `doc.modified` is now removed, use [doc.isModified](./api.html#document_Document-isModified) instead - - h4#gettercasting getter casting - :markdown - Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue [#820](https://github.com/LearnBoost/mongoose/issues/820) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). - - h4#setterorder setter order - :markdown - Values being set no longer cast until _after_ all setters have been applied. Previously the value returned from each setter was cast _before_ passing it on to the next setter. This change allows more flexible processing of values in setters. See issue [#665](https://github.com/learnboost/mongoose/issues/665) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). - - h3#subdocs Subdocuments - :markdown - - `subdoc.parent` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parent). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). - - `subdoc.parentArray` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parentArray). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). - - h3#stringmatch String match validator - :markdown - The String SchemaType [match](./api.html#schema_string_SchemaString-match) validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the [required](./api.html#schematype_SchemaType-required) validator as well. See issue [#934](https://github.com/LearnBoost/mongoose/issues/934) and pull request [#935](https://github.com/LearnBoost/mongoose/pull/935). - - h3#version Versioning - :markdown - Documents are now transparently versioned. Read the in depth details [here](http://aaronheckmann.posterous.com/tag/versioning). - - h3#moreinfo More Info - :markdown - Related blog posts: - - - [Mongoose v3 released](http://aaronheckmann.posterous.com/mongoose-v3-released) - - [API changes](http://aaronheckmann.posterous.com/mongoose-v3-part-3-api-changes) - - [FindAndModify](http://aaronheckmann.posterous.com/mongoose-v3-part-2-findandmodify) diff --git a/docs/3.2.x/docs/models.html b/docs/3.2.x/docs/models.html deleted file mode 100644 index 645951f6d96..00000000000 --- a/docs/3.2.x/docs/models.html +++ /dev/null @@ -1,32 +0,0 @@ -Mongoose Models v3.2.2Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var schema = new Schema({ name: 'string', size: 'string' });
    -var Tank = mongoose.model('Tank', schema);
    -
    -// or, if you are using separate connections
    -var db = mongoose.createConnection(..);
    -var Tank = db.model('Tank', schema);
    -

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = db.model('Tank', yourSchema);
    -
    -var small = new Tank({ size: 'small' });
    -small.save(function (err) {
    -  if (err) return handleError(err);
    -  // saved!
    -})
    -
    -// or
    -
    -Tank.create({ size: 'small' }, function (err) {
    -  if (err) return handleError(err);
    -  // saved!
    -})
    -

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    -  if (err) return handleError(err);
    -  // removed!
    -});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at Documents.

    diff --git a/docs/3.2.x/docs/models.jade b/docs/3.2.x/docs/models.jade deleted file mode 100644 index 105ef327803..00000000000 --- a/docs/3.2.x/docs/models.jade +++ /dev/null @@ -1,61 +0,0 @@ -extends layout - -block content - h2 Models - :markdown - [Models](./api.html#model-js) are fancy constructors compiled from our `Schema` definitions. Instances of these models represent [documents](./documents.html) which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models. - - h3 Compiling your first model - :js - var schema = new Schema({ name: 'string', size: 'string' }); - var Tank = mongoose.model('Tank', schema); - - // or, if you are using separate connections - var db = mongoose.createConnection(..); - var Tank = db.model('Tank', schema); - - h3 Constructing documents - :markdown - [Documents](./documents.html) are instances of our model. Creating them and saving to the database is easy: - :js - var Tank = db.model('Tank', yourSchema); - - var small = new Tank({ size: 'small' }); - small.save(function (err) { - if (err) return handleError(err); - // saved! - }) - - // or - - Tank.create({ size: 'small' }, function (err) { - if (err) return handleError(err); - // saved! - }) - - h3 Querying - :markdown - Finding documents is easy with Mongoose, which supports the [rich](http://www.mongodb.org/display/DOCS/Advanced+Queries) query syntax of MongoDB. Documents can be retreived using each `models` [find](./api.html#model_Model-find), [findById](./api.html#model_Model-findById), [findOne](./api.html#model_Model-findOne), or [where](./api.html#model_Model-where) static methods. - - :js - Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback); - :markdown - See the chapter on [querying](./queries.html) for more details on how to use the [Query](./api.html#query-js) api. - h3 Removing - :markdown - Models have a static `remove` method available for removing all documents matching `conditions`. - :js - Tank.remove({ size: 'large' }, function (err) { - if (err) return handleError(err); - // removed! - }); - h3 Updating - :markdown - Each `model` has its own `update` method for modifying documents in the database without returning them to your application. See the [API](./api.html#model_Model-update) docs for more detail. - h3 Yet more - :markdown - The [API docs](./api.html#model_Model) cover many additional methods available like [count](./api.html#model_Model-count), [mapReduce](./api.html#model_Model-mapReduce), [aggregate](./api.html#model_Model-aggregate), and more. - - h3#next Next Up - :markdown - Now that we've covered `Models`, let's take a look at [Documents](/docs/documents.html). diff --git a/docs/3.2.x/docs/plugins.html b/docs/3.2.x/docs/plugins.html deleted file mode 100644 index 05010cb615d..00000000000 --- a/docs/3.2.x/docs/plugins.html +++ /dev/null @@ -1,33 +0,0 @@ -Mongoose Plugins v3.2.2Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    - -

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    -module.exports = exports = function lastModifiedPlugin (schema, options) {
    -  schema.add({ lastMod: Date })
    -  
    -  schema.pre('save', function (next) {
    -    this.lastMod = new Date
    -    next()
    -  })
    -  
    -  if (options && options.index) {
    -    schema.path('lastMod').index(options.index)
    -  }
    -}
    -
    -// game-schema.js
    -var lastMod = require('./lastMod');
    -var Game = new Schema({ ... });
    -Game.plugin(lastMod, { index: true });
    -
    -// player-schema.js
    -var lastMod = require('./lastMod');
    -var Player = new Schema({ ... });
    -Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    diff --git a/docs/3.2.x/docs/plugins.jade b/docs/3.2.x/docs/plugins.jade deleted file mode 100644 index 4930fd8a46e..00000000000 --- a/docs/3.2.x/docs/plugins.jade +++ /dev/null @@ -1,42 +0,0 @@ -extends layout - -block content - h2 Plugins - :markdown - Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature. - - Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each `Schema`: - - :js - // lastMod.js - module.exports = exports = function lastModifiedPlugin (schema, options) { - schema.add({ lastMod: Date }) - - schema.pre('save', function (next) { - this.lastMod = new Date - next() - }) - - if (options && options.index) { - schema.path('lastMod').index(options.index) - } - } - - // game-schema.js - var lastMod = require('./lastMod'); - var Game = new Schema({ ... }); - Game.plugin(lastMod, { index: true }); - - // player-schema.js - var lastMod = require('./lastMod'); - var Player = new Schema({ ... }); - Player.plugin(lastMod); - :markdown - We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code. - h3 Community! - :markdown - Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. - - h3#next Next Up - :markdown - Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help [contribute](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md) to the continuing development of Mongoose itself. diff --git a/docs/3.2.x/docs/populate.html b/docs/3.2.x/docs/populate.html deleted file mode 100644 index c02800225c4..00000000000 --- a/docs/3.2.x/docs/populate.html +++ /dev/null @@ -1,104 +0,0 @@ -Mongoose Query Population v3.2.2Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    - -

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    -  , Schema = mongoose.Schema
    -  
    -var PersonSchema = new Schema({
    -  name    : String,
    -  age     : Number,
    -  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    -});
    -
    -var StorySchema = new Schema({
    -  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    -  title    : String,
    -  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    -});
    -
    -var Story  = mongoose.model('Story', StorySchema);
    -var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    -
    -aaron.save(function (err) {
    -  if (err) return handleError(err);
    -  
    -  var story1 = new Story({
    -    title: "Once upon a timex.",
    -    _creator: aaron._id    // assign an ObjectId
    -  });
    -  
    -  story1.save(function (err) {
    -    if (err) return handleError(err);
    -    // thats it!
    -  });
    -})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    -.findOne({ title: /timex/ })
    -.populate('_creator')
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    -})
    -

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    - -

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    -.findOne({ title: /timex/i })
    -.populate('_creator', 'name') // only return the Persons name
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  
    -  console.log('The creator is %s', story._creator.name);
    -  // prints "The creator is Aaron"
    -  
    -  console.log('The creators age is %s', story._creator.age);
    -  // prints "The creators age is null'
    -})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    -.find(...)
    -.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    - -

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    -aaron.save();

    This allows us to perform a find and populate combo:

    Person
    -.findOne({ name: 'Aaron' })
    -.populate('stories') // only works if we pushed refs to children
    -.exec(function (err, person) {
    -  if (err) return handleError(err);
    -  console.log(person);
    -})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    -.find({ _creator: aaron._id })
    -.populate('_creator') // not really necessary
    -.exec(function (err, stories) {
    -  if (err) return handleError(err);
    -  console.log('The stories are an array: ', stories);
    -})
    -

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    -guille.save(function (err) {
    -  if (err) return handleError(err);
    -  
    -  story._creator = guille; // or guille._id
    -  
    -  story.save(function (err) {
    -    if (err) return handleError(err);
    -    
    -    Story
    -    .findOne({ title: /timex/i })
    -    .populate('_creator', 'name')
    -    .exec(function (err, story) {
    -      if (err) return handleError(err);
    -      
    -      console.log('The creator is %s', story._creator.name)
    -      // prints "The creator is Guillermo"
    -    })
    -  })
    -})
    -

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    -Story.findOne(..).populate('_creator', 'name age').exec(..);
    -
    -// this doesn't
    -Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
    -

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at connections.

    diff --git a/docs/3.2.x/docs/populate.jade b/docs/3.2.x/docs/populate.jade deleted file mode 100644 index 5443bbbcc28..00000000000 --- a/docs/3.2.x/docs/populate.jade +++ /dev/null @@ -1,164 +0,0 @@ -extends layout - -block content - h2 Query Population - :markdown - There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. - - `ObjectIds` can refer to another document in a collection within our database and be `populate()`d when querying: - :js - var mongoose = require('mongoose') - , Schema = mongoose.Schema - - var PersonSchema = new Schema({ - name : String, - age : Number, - stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] - }); - - var StorySchema = new Schema({ - _creator : { type: Schema.Types.ObjectId, ref: 'Person' }, - title : String, - fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }] - }); - - var Story = mongoose.model('Story', StorySchema); - var Person = mongoose.model('Person', PersonSchema); - :markdown - So far we've created two `models`. Our `Person` model has it's `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose in which model to look, in our case the `Story` model. All `_id`s we store here must be document _ids from the `Story` model. We also added a `_creator` `ObjectId` to our `Story` schema which refers to a single `Person`. - h3 Saving refs - :markdown - Saving refs to other documents works the same way you normally save objectids, just assign an `ObjectId`: - :js - var aaron = new Person({ name: 'Aaron', age: 100 }); - - aaron.save(function (err) { - if (err) return handleError(err); - - var story1 = new Story({ - title: "Once upon a timex.", - _creator: aaron._id // assign an ObjectId - }); - - story1.save(function (err) { - if (err) return handleError(err); - // thats it! - }); - }) - h3 Population - :markdown - So far we haven't done anything special. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator`: - :js - Story - .findOne({ title: /timex/ }) - .populate('_creator') - .exec(function (err, story) { - if (err) return handleError(err); - console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron" - }) - - :markdown - Populated paths are no longer set to their original `ObjectId`s, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. - - Arrays of `ObjectId` refs work the same way. Just call the [populate](./api.html#query_Query-populate) method on the query and an array of documents will be returned _in place_ of the `ObjectIds`. - - h3 Field selection - :markdown - What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: - :js - Story - .findOne({ title: /timex/i }) - .populate('_creator', 'name') // only return the Persons name - .exec(function (err, story) { - if (err) return handleError(err); - - console.log('The creator is %s', story._creator.name); - // prints "The creator is Aaron" - - console.log('The creators age is %s', story._creator.age); - // prints "The creators age is null' - }) - h3 Query conditions for populate - :markdown - What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them? - :js - Story - .find(...) - .populate('fans', null, { age: { $gte: 21 }}, { limit: 5 }) - :markdown - Done. `Conditions` and `options` for populate queries are passed as the third and fourth arguments respectively. - h3 Refs to children - :markdown - We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' on to `aaron.stories`. - - There are two perspectives to this story. First, it's nice to have `aaron` know which are his stories. - :js - aaron.stories.push(story1); - aaron.save(); - :markdown - This allows us to perform a `find` and `populate` combo: - :js - Person - .findOne({ name: 'Aaron' }) - .populate('stories') // only works if we pushed refs to children - .exec(function (err, person) { - if (err) return handleError(err); - console.log(person); - }) - :markdown - However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely `find()` the documents we are interested in. - :js - Story - .find({ _creator: aaron._id }) - .populate('_creator') // not really necessary - .exec(function (err, stories) { - if (err) return handleError(err); - console.log('The stories are an array: ', stories); - }) - - h3 Updating refs - :markdown - Now that we have a `story` we realized that the `_creator` was incorrect. We can update `ObjectId` refs the same as any other property through the magic of Mongoose's internal casting: - :js - var guille = new Person({ name: 'Guillermo' }); - guille.save(function (err) { - if (err) return handleError(err); - - story._creator = guille; // or guille._id - - story.save(function (err) { - if (err) return handleError(err); - - Story - .findOne({ title: /timex/i }) - .populate('_creator', 'name') - .exec(function (err, story) { - if (err) return handleError(err); - - console.log('The creator is %s', story._creator.name) - // prints "The creator is Guillermo" - }) - }) - }) - - h4 NOTE: - :markdown - The documents returned from calling [populate](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. - - h4 NOTE: - :markdown - _Field selection_ in v3 is slightly different than v2. Arrays of fields are no longer accepted. - - :js - // this works - Story.findOne(..).populate('_creator', 'name age').exec(..); - - // this doesn't - Story.findOne(..).populate('_creator', ['name', 'age']).exec(..); - - :markdown - See the [migration guide](./migration.html#fields) for more detail. - - h3#next Next Up - :markdown - Now that we've covered query population, let's take a look at [connections](/docs/connections.html). diff --git a/docs/3.2.x/docs/prior.html b/docs/3.2.x/docs/prior.html deleted file mode 100644 index c585504f8bf..00000000000 --- a/docs/3.2.x/docs/prior.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose v3.2.2Fork me on GitHub

    Prior Release Documentation

    diff --git a/docs/3.2.x/docs/prior.jade b/docs/3.2.x/docs/prior.jade deleted file mode 100644 index 1ef7d088a72..00000000000 --- a/docs/3.2.x/docs/prior.jade +++ /dev/null @@ -1,8 +0,0 @@ -extends layout - -block content - h2 Prior Release Documentation - ul - each release in releases - li - a(href=release.url)= release.version diff --git a/docs/3.2.x/docs/queries.html b/docs/3.2.x/docs/queries.html deleted file mode 100644 index 6f115e9f1bf..00000000000 --- a/docs/3.2.x/docs/queries.html +++ /dev/null @@ -1,41 +0,0 @@ -Mongoose Queries v3.2.2Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    - -

    When a callback function:

    - -
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    - -

    Let's take a look at what happens when passing a callback:

    var Person = db.model('Person', yourSchema);
    -
    -// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    -Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    -  if (err) return handleError(err);
    -  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    Here we see that the query was executed immediately and the results passed to our callback. -Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    -var query = Person.findOne({ 'name.last': 'Ghost' });
    -
    -// selecting the `name` and `occupation` fields
    -query.select('name occupation');
    -
    -// execute the query at a later time
    -query.exec(function (err, person) {
    -  if (err) return handleError(err);
    -  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    -.find({ occupation: /host/ })
    -.where('name.last').equals('Ghost')
    -.where('age').gt(17).lt(66)
    -.where('likes').in(['vaporizing', 'talking'])
    -.limit(10)
    -.sort('-occupation')
    -.select('name occupation')
    -.exec(callback);
    -

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    diff --git a/docs/3.2.x/docs/queries.jade b/docs/3.2.x/docs/queries.jade deleted file mode 100644 index 68c529efe25..00000000000 --- a/docs/3.2.x/docs/queries.jade +++ /dev/null @@ -1,62 +0,0 @@ -extends layout - -block content - h2 Queries - :markdown - Documents can be retrieved through several static helper methods of [models](./models.html). - :markdown - Any [model](./api.html#model_Model) method which [involves](./api.html#model_Model-find) [specifying](./api.html#model_Model-findById) [query](./api.html#model_Model-count) [conditions](./api.html#model_Model-update) can be executed two ways: - - When a `callback` function: - - - is passed, the operation will be executed immediately with the results passed to the callback. - - is not passed, an instance of [Query](./api.html#query-js) is returned, which provides a special `QueryBuilder` interface for you. - - Let's take a look at what happens when passing a `callback`: - :js - var Person = db.model('Person', yourSchema); - - // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields - Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { - if (err) return handleError(err); - console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. - }) - :markdown - Here we see that the query was executed immediately and the results passed to our callback. - Now let's look at what happens when no `callback` is passed: - :js - // find each person with a last name matching 'Ghost' - var query = Person.findOne({ 'name.last': 'Ghost' }); - - // selecting the `name` and `occupation` fields - query.select('name occupation'); - - // execute the query at a later time - query.exec(function (err, person) { - if (err) return handleError(err); - console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. - }) - :markdown - An instance of [Query](./api.html#query-js) was returned which allows us to build up our query. Taking this example further: - :js - Person - .find({ occupation: /host/ }) - .where('name.last').equals('Ghost') - .where('age').gt(17).lt(66) - .where('likes').in(['vaporizing', 'talking']) - .limit(10) - .sort('-occupation') - .select('name occupation') - .exec(callback); - - h3#refs References to other documents - :markdown - There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. Read more [here](./populate.html). - - h3 Streaming - :markdown - Queries can be [streamed](http://nodejs.org/api/stream.html) from MongoDB to your application as well. Simply call the query's [stream](./api.html#query_Query-stream) method instead of [exec](./api.html#query_Query-exec) to return an instance of [QueryStream](./api.html#querystream_QueryStream). - - h3#next Next Up - :markdown - Now that we've covered `Queries`, let's take a look at [validation](/docs/validation.html). diff --git a/docs/3.2.x/docs/releases b/docs/3.2.x/docs/releases deleted file mode 100644 index cd9fcd27bd1..00000000000 --- a/docs/3.2.x/docs/releases +++ /dev/null @@ -1,2 +0,0 @@ -2.8.x -2.7.x diff --git a/docs/3.2.x/docs/schematypes.html b/docs/3.2.x/docs/schematypes.html deleted file mode 100644 index 068dad8eea1..00000000000 --- a/docs/3.2.x/docs/schematypes.html +++ /dev/null @@ -1,67 +0,0 @@ -Mongoose SchemaTypes v3.2.2Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    -  name:    String,
    -  binary:  Buffer,
    -  living:  Boolean,
    -  updated: { type: Date, default: Date.now },
    -  age:     { type: Number, min: 18, max: 65 },
    -  mixed:   Schema.Types.Mixed,
    -  _someId: Schema.Types.ObjectId,
    -  array:      [],
    -  ofString:   [String],
    -  ofNumber:   [Number],
    -  ofDates:    [Date],
    -  ofBuffer:   [Buffer],
    -  ofBoolean:  [Boolean],
    -  ofMixed:    [Schema.Types.Mixed],
    -  ofObjectId: [Schema.Types.ObjectId],
    -  nested: {
    -    stuff: { type: String, lowercase: true, trim: true }
    -  }
    -})
    -
    -// example use
    -
    -var Thing = mongoose.model('Thing', schema);
    -
    -var m = new Thing;
    -m.name = 'Statue of Liberty';
    -m.age = 125;
    -m.updated = new Date;
    -m.binary = new Buffer(0);
    -m.living = false;
    -m.mixed = {[ any: { thing: 'i want' } ]};
    -m.markModified('mixed');
    -m._someId = new mongoose.Types.ObjectId;
    -m.array.push(1);
    -m.ofString.push("strings!");
    -m.ofNumber.unshift(1,2,3,4);
    -m.ofDates.addToSet(new Date);
    -m.ofBuffer.pop();
    -m.ofMixed = [1, [], 'three', { four: 5 }];
    -m.nested.stuff = 'good';
    -m.save(callback);
    -

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    -var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    -person.markModified('anything');
    -person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    -var ObjectId = mongoose.Schema.Types.ObjectId;
    -var Car = new Schema({ driver: ObjectId });
    -// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    -var ToyBox = new Schema({
    -  toys: [ToySchema],
    -  buffers: [Buffer],
    -  string:  [String],
    -  numbers: [Number]
    -  // ... etc
    -});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    -var Empty2 = new Schema({ any: Array });
    -var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    -var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Models.

    diff --git a/docs/3.2.x/docs/schematypes.jade b/docs/3.2.x/docs/schematypes.jade deleted file mode 100644 index afa3c3276fe..00000000000 --- a/docs/3.2.x/docs/schematypes.jade +++ /dev/null @@ -1,146 +0,0 @@ -extends layout - -block content - h2 SchemaTypes - p - | SchemaTypes handle definition of path - a(href="./api.html#schematype_SchemaType-default") defaults - |, - a(href="./api.html#schematype_SchemaType-validate") validation - |, - a(href="./api.html#schematype_SchemaType-get") getters - |, - a(href="./api.html#schematype_SchemaType-set") setters - |, - a(href="./api.html#schematype_SchemaType-select") field selection defaults - | for - a(href="./api.html#query-js") queries - | and other general characteristics for - a(href="./api.html#schema-string-js") Strings - | and - a(href="./api.html#schema-number-js") Numbers - |. Check out their respective API documentation for more detail. - p - | Following are all valid - a(href="./api.html#schema_Schema-Types") Schema Types - |. - ul - li String - li Number - li Date - li Buffer - li Boolean - li Mixed - li ObjectId - li Array - h4 Example - :js - var schema = new Schema({ - name: String, - binary: Buffer, - living: Boolean, - updated: { type: Date, default: Date.now }, - age: { type: Number, min: 18, max: 65 }, - mixed: Schema.Types.Mixed, - _someId: Schema.Types.ObjectId, - array: [], - ofString: [String], - ofNumber: [Number], - ofDates: [Date], - ofBuffer: [Buffer], - ofBoolean: [Boolean], - ofMixed: [Schema.Types.Mixed], - ofObjectId: [Schema.Types.ObjectId], - nested: { - stuff: { type: String, lowercase: true, trim: true } - } - }) - - // example use - - var Thing = mongoose.model('Thing', schema); - - var m = new Thing; - m.name = 'Statue of Liberty'; - m.age = 125; - m.updated = new Date; - m.binary = new Buffer(0); - m.living = false; - m.mixed = {[ any: { thing: 'i want' } ]}; - m.markModified('mixed'); - m._someId = new mongoose.Types.ObjectId; - m.array.push(1); - m.ofString.push("strings!"); - m.ofNumber.unshift(1,2,3,4); - m.ofDates.addToSet(new Date); - m.ofBuffer.pop(); - m.ofMixed = [1, [], 'three', { four: 5 }]; - m.nested.stuff = 'good'; - m.save(callback); - - h3 Usage notes: - h4#mixed Mixed - p An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent: - :js - var Any = new Schema({ any: {} }); - var Any = new Schema({ any: Schema.Types.Mixed }); - p - | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the - code .markModified(path) - | method of the document passing the path to the Mixed type you just changed. - :js - person.anything = { x: [3, 4, { y: "changed" }] }; - person.markModified('anything'); - person.save(); // anything will now get saved - h4#objectids ObjectIds - p - | To specify a type of ObjectId, use - code Schema.Types.ObjectId - | in your declaration. - :js - var mongoose = require('mongoose'); - var ObjectId = mongoose.Schema.Types.ObjectId; - var Car = new Schema({ driver: ObjectId }); - // or just Schema.ObjectId for backwards compatibility with v2 - h4#arrays Arrays - p - | Provide creation of arrays of - a(href="./api.html#schema_Schema-Types") SchemaTypes - | or - a(href="./subdocs.html") Sub-Documents - |. - :js - var ToySchema = new Schema({ name: String }); - var ToyBox = new Schema({ - toys: [ToySchema], - buffers: [Buffer], - string: [String], - numbers: [Number] - // ... etc - }); - p - | Note: specifying an empty array is equivalent to - code Mixed - |. The following all create arrays of - code Mixed - |: - :js - var Empty1 = new Schema({ any: [] }); - var Empty2 = new Schema({ any: Array }); - var Empty3 = new Schema({ any: [Schema.Types.Mixed] }); - var Empty4 = new Schema({ any: [{}] }); - h3#customtypes Creating Custom Types - p - | Mongoose can also be extended with custom SchemaTypes. Search the - a(href="http://plugins.mongoosejs.com") plugins - | site for compatible types like - a(href="https://github.com/aheckmann/mongoose-long") mongoose-long - | and - a(href="https://github.com/aheckmann/mongoose-number") other - | - a(href="https://github.com/bnoguchi/mongoose-types") types - |. - - h3#next Next Up - :markdown - Now that we've covered `SchemaTypes`, let's take a look at [Models](/docs/models.html). diff --git a/docs/3.2.x/docs/source/_docs b/docs/3.2.x/docs/source/_docs deleted file mode 100644 index 2b19e8db161..00000000000 --- a/docs/3.2.x/docs/source/_docs +++ /dev/null @@ -1,16201 +0,0 @@ - -### lib/collection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var STATES = require('./connectionstate')", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "require('./connectionstate')", - "string": "STATES" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the collection" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "conn", - "description": "A MongooseConnection instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "optional collection options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", - "summary": "

    Abstract Collection constructor

    ", - "body": "

    This is the base class that drivers inherit from and implement.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", - "ctx": { - "type": "function", - "name": "Collection", - "string": "Collection()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "name" - } - ], - "description": { - "full": "

    The collection name

    ", - "summary": "

    The collection name

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.name;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "conn" - } - ], - "description": { - "full": "

    The Connection instance

    ", - "summary": "

    The Connection instance

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.conn;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the database connects

    ", - "summary": "

    Called when the database connects

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onOpen", - "string": "Collection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the database disconnects

    ", - "summary": "

    Called when the database disconnects

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onClose", - "string": "Collection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the method to queue" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method when executed" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Queues a method for later execution when its
    database connection opens.

    ", - "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "addQueue", - "string": "Collection.prototype.addQueue()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes all queued methods and clears the queue.

    ", - "summary": "

    Executes all queued methods and clears the queue.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "doQueue", - "string": "Collection.prototype.doQueue()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "ensureIndex", - "string": "Collection.prototype.ensureIndex()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findAndModify", - "string": "Collection.prototype.findAndModify()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findOne", - "string": "Collection.prototype.findOne()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "find", - "string": "Collection.prototype.find()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "insert", - "string": "Collection.prototype.insert()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "save", - "string": "Collection.prototype.save()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "update", - "string": "Collection.prototype.update()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "getIndexes", - "string": "Collection.prototype.getIndexes()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "mapReduce", - "string": "Collection.prototype.mapReduce()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Collection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Collection", - "string": "module.exports" - } - } -] -### lib/connection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , assert =require('assert')", - "ctx": { - "type": "declaration", - "name": "url", - "value": "require('url')", - "string": "url" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Protocol prefix regexp.

    ", - "summary": "

    Protocol prefix regexp.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", - "ctx": { - "type": "declaration", - "name": "rgxProtocol", - "value": "/^(?:.)+:\\/\\//", - "string": "rgxProtocol" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "a mongoose instance" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." - }, - { - "type": "event", - "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." - }, - { - "type": "event", - "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." - }, - { - "type": "event", - "string": "`disconnecting`: Emitted when `connection.close()` was executed." - }, - { - "type": "event", - "string": "`disconnected`: Emitted after getting disconnected from the db." - }, - { - "type": "event", - "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." - }, - { - "type": "event", - "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." - }, - { - "type": "event", - "string": "`error`: Emitted when an error occurs on this connection." - }, - { - "type": "event", - "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", - "summary": "

    Connection constructor

    ", - "body": "

    For practical reasons, a Connection equals a Db.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", - "ctx": { - "type": "function", - "name": "Connection", - "string": "Connection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter

    ", - "summary": "

    Inherit from EventEmitter

    ", - "body": "" - }, - "ignore": true, - "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Connection", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Connection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readyState" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", - "summary": "

    Connection ready state

    ", - "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" - }, - { - "tags": [ - { - "type": "property", - "string": "collections" - } - ], - "description": { - "full": "

    A hash of the collections associated with this connection

    ", - "summary": "

    A hash of the collections associated with this connection

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collections;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

    The mongodb.Db instance, set when the connection is opened

    ", - "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.db;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "connection_string", - "description": "mongodb://uri or the host to which you are connecting" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[port]", - "description": "database port" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    ", - "summary": "

    Opens the connection to MongoDB.

    ", - "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n uri = url.parse(host);\n host = uri.hostname;\n port = uri.port || 27017;\n database = uri.pathname && uri.pathname.replace(/\\//g, '');\n }\n\n this.options = this.defaultOptions(options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing connection hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing connection database.'), callback);\n return this;\n }\n\n // handle authentication\n if (uri && uri.auth) {\n var auth = uri.auth.split(':');\n this.user = auth[0];\n this.pass = auth[1];\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n // user/pass options\n } else if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "open", - "string": "Connection.prototype.open()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "uris", - "description": "comma-separated mongodb:// `URI`s" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name if not included in `uris`" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "passed to the internal driver" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connects to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    ", - "summary": "

    Connects to a replica set.

    ", - "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n var uris = uris.split(',')\n , self = this;\n\n switch (arguments.length) {\n case 3:\n this.name = database;\n if ('function' === typeof options) callback = options, options = {};\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n this.options = options = this.defaultOptions(options);\n\n if (uris.length < 2) {\n this.error(new Error('Please provide comma-separated URIs'), callback);\n return this;\n }\n\n this.replica = true;\n this.host = [];\n this.port = [];\n\n uris.forEach(function (uri) {\n // handle missing protocols\n if (!rgxProtocol.test(uri))\n uri = 'mongodb://' + uri;\n\n var uri = url.parse(uri);\n\n self.host.push(uri.hostname);\n self.port.push(uri.port || 27017);\n\n if (!self.name && uri.pathname && uri.pathname.replace(/\\//g, ''))\n self.name = uri.pathname.replace(/\\//g, '');\n\n if (!self.user && uri.auth) {\n var auth = uri.auth.split(':');\n self.user = auth[0];\n self.pass = auth[1];\n }\n });\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "openSet", - "string": "Connection.prototype.openSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "optional" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", - "summary": "

    error

    ", - "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "error", - "string": "Connection.prototype.error()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", - "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "_open", - "string": "Connection.prototype._open()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection is opened

    ", - "summary": "

    Called when the connection is opened

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onOpen", - "string": "Connection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "self" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Closes the connection

    ", - "summary": "

    Closes the connection

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "close", - "string": "Connection.prototype.close()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection closes

    ", - "summary": "

    Called when the connection closes

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onClose", - "string": "Connection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "of the collection" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional collection options" - }, - { - "type": "return", - "types": [ - "Collection" - ], - "description": "collection instance" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Retrieves a collection, creating it if not cached.

    ", - "summary": "

    Retrieves a collection, creating it if not cached.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "collection", - "string": "Connection.prototype.collection()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "the model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "a schema. necessary when defining a model" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name of mongodb collection (optional) if not given it will be induced from model name" - }, - { - "type": "see", - "local": "Mongoose#model #index_Mongoose-model", - "visibility": "Mongoose#model" - }, - { - "type": "return", - "types": [ - "Model" - ], - "description": "The compiled model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    ", - "summary": "

    Defines or retrieves a model.

    ", - "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.model = function (name, schema, collection) {\n if (!this.models[name]) {\n var model = this.base.model(name, schema, collection, true)\n , Model\n\n if (this != model.prototype.db) {\n // subclass model using this connection and collection name\n Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model))\n return new Model(doc, fields, skipId);\n model.call(this, doc, fields, skipId);\n };\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = this;\n\n // collection name discovery\n if ('string' === typeof schema) {\n collection = schema;\n }\n\n if (!collection) {\n collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);\n }\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n Model.prototype.collection = this.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n }\n\n this.models[name] = Model || model;\n }\n\n return this.models[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "model", - "string": "Connection.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "level", - "description": "either off (0), slow (1), or all (2)" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[ms]", - "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Set profiling level.

    ", - "summary": "

    Set profiling level.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "setProfiling", - "string": "Connection.prototype.setProfiling()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Prepares default connection options.

    ", - "summary": "

    Prepares default connection options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.defaultOptions = function (options) {\n var o = options || {};\n\n o.server = o.server || {};\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n o.db || (o.db = {});\n o.db.forceServerObjectId = false;\n\n // TODO default to true once the driver is fixed\n if (!('safe' in o.db)) o.db.safe = false;\n\n return o;\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "defaultOptions", - "string": "Connection.prototype.defaultOptions()" - } - }, - { - "tags": [], - "description": { - "full": "

    Noop.

    ", - "summary": "

    Noop.

    ", - "body": "" - }, - "ignore": true, - "code": "function noop () {}", - "ctx": { - "type": "function", - "name": "noop", - "string": "noop()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", - "ctx": { - "type": "property", - "receiver": "Connection", - "name": "STATES", - "value": "STATES", - "string": "Connection.STATES" - } - } -] -### lib/connectionstate.js -[ - { - "tags": [], - "description": { - "full": "

    Connection states

    ", - "summary": "

    Connection states

    ", - "body": "" - }, - "ignore": true, - "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "module.exports = exports = Object.create(null)", - "string": "STATES" - } - } -] -### lib/document.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the values to set" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "the fields which were selected in the query returning this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "bool, should we auto create an ObjectId _id" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." - }, - { - "type": "event", - "string": "`save`: Emitted when the document is successfully saved" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Document constructor.

    ", - "summary": "

    Document constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", - "ctx": { - "type": "function", - "name": "Document", - "string": "Document()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Document.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Document.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "schema" - } - ], - "description": { - "full": "

    The documents schema.

    ", - "summary": "

    The documents schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.schema;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "isNew" - } - ], - "description": { - "full": "

    Boolean flag specifying if the document is new.

    ", - "summary": "

    Boolean flag specifying if the document is new.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isNew;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "local": "Schema options /docs/guide.html#options", - "visibility": "Schema" - }, - { - "type": "property", - "string": "id" - } - ], - "description": { - "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", - "summary": "

    The string version of this documents _id.

    ", - "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.id;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "errors" - } - ], - "description": { - "full": "

    Hash containing current validation errors.

    ", - "summary": "

    Hash containing current validation errors.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.errors;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Builds the default doc structure

    ", - "summary": "

    Builds the default doc structure

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_buildDoc", - "string": "Document.prototype._buildDoc()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", - "summary": "

    Initializes the document without setters or marking anything modified.

    ", - "body": "

    Called internally after a document is returned from mongodb.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init');\n if (fn) fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "init", - "string": "Document.prototype.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "self", - "description": "document instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "raw mongodb doc" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "object we are initializing" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Init helper.

    ", - "summary": "

    Init helper.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", - "ctx": { - "type": "function", - "name": "init", - "string": "init()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", - "summary": "

    Stores the current values of the shard keys.

    ", - "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_storeShard", - "string": "Document.prototype._storeShard()" - } - }, - { - "tags": [], - "description": { - "full": "

    Set up middleware support

    ", - "summary": "

    Set up middleware support

    ", - "body": "" - }, - "ignore": true, - "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    ", - "summary": "

    Sends an update command with this document _id as the query selector.

    ", - "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "update", - "string": "Document.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "path", - "description": "path or object of key/vals to set" - }, - { - "type": "param", - "types": [ - "Any" - ], - "name": "val", - "description": "the value to set" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for \"on-the-fly\" attributes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    ", - "summary": "

    Sets the value of a path, or many paths.

    ", - "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.set = function (path, val, type) {\n var constructing = true === type\n , adhoc = type && true !== type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n if (null != path[key] && 'Object' === path[key].constructor.name\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n pathtype = this.schema.pathType(prefix + key);\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "set", - "string": "Document.prototype.set()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", - "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {\n if (this.isNew) {\n this.markModified(pathToMark);\n } else {\n\n priorVal || (priorVal = this.get(path));\n\n if (!this.isDirectModified(pathToMark)) {\n if (undefined === val && !this.isSelected(path)) {\n // special case:\n // when a path is not selected in a query its initial\n // value will be undefined.\n this.markModified(pathToMark, priorVal);\n } else if (undefined === val && path in this._activePaths.states.default) {\n // do nothing\n // unsetting the default value which was never saved\n } else if (!deepEqual(val, priorVal)) {\n this.markModified(pathToMark, priorVal);\n } else if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // special case:\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n this.markModified(pathToMark, priorVal);\n }\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_set", - "string": "Document.prototype._set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Gets a raw value from a path (no getters)

    ", - "summary": "

    Gets a raw value from a path (no getters)

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "getValue", - "string": "Document.prototype.getValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", - "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "setValue", - "string": "Document.prototype.setValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for on-the-fly attributes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", - "summary": "

    Returns the value of a path.

    ", - "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "get", - "string": "Document.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns the schematype for the given path.

    ", - "summary": "

    Returns the schematype for the given path.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_path", - "string": "Document.prototype._path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to mark modified" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", - "summary": "

    Marks the path as having pending changes to write to the db.

    ", - "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "markModified", - "string": "Document.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "function to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope with which to call fn" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", - "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "try", - "string": "Document.prototype.try()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the list of paths that have been modified.

    ", - "summary": "

    Returns the list of paths that have been modified.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "modifiedPaths", - "string": "Document.prototype.modifiedPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", - "summary": "

    Returns true if this document was modified, else false.

    ", - "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isModified", - "string": "Document.prototype.isModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", - "summary": "

    Returns true if path was directly set and modified, else false.

    ", - "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isDirectModified", - "string": "Document.prototype.isDirectModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Checks if path was initialized.

    ", - "summary": "

    Checks if path was initialized.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isInit", - "string": "Document.prototype.isInit()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", - "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", - "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isSelected", - "string": "Document.prototype.isSelected()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "cb", - "description": "called after validation completes, passing an error if one occurred" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", - "summary": "

    Executes registered validation rules for this document.

    ", - "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n paths = paths.concat(Object.keys(this._activePaths.states.default));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n cb(err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "validate", - "string": "Document.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "the error which states the reason `path` was invalid" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks a path as invalid, causing validation to fail.

    ", - "summary": "

    Marks a path as invalid, causing validation to fail.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "invalidate", - "string": "Document.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Resets the internal modified state of this document.

    ", - "summary": "

    Resets the internal modified state of this document.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n })\n .forEach(function (array) {\n var i = array.length;\n while (i--) {\n var doc = array[i];\n if (!doc) continue;\n doc._reset();\n }\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_reset", - "string": "Document.prototype._reset()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns this documents dirty paths / vals.

    ", - "summary": "

    Returns this documents dirty paths / vals.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_dirty", - "string": "Document.prototype._dirty()" - } - }, - { - "tags": [], - "description": { - "full": "

    Compiles schemas.

    ", - "summary": "

    Compiles schemas.

    ", - "body": "" - }, - "ignore": true, - "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", - "ctx": { - "type": "function", - "name": "compile", - "string": "compile()" - } - }, - { - "tags": [], - "description": { - "full": "

    Defines the accessor named prop on the incoming prototype.

    ", - "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", - "body": "" - }, - "ignore": true, - "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", - "ctx": { - "type": "function", - "name": "define", - "string": "define()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Assigns/compiles schema into this documents prototype.

    ", - "summary": "

    Assigns/compiles schema into this documents prototype.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_setSchema", - "string": "Document.prototype._setSchema()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register default hooks

    ", - "summary": "

    Register default hooks

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n if (error) return;\n\n // handle sparse arrays by using for loop vs array.forEach\n // which skips the sparse elements\n\n var len = array.length\n subdocs += len;\n\n for (var i = 0; i < len; ++i) {\n if (error) break;\n\n var doc = array[i];\n if (!doc) {\n --subdocs || next();\n continue;\n }\n\n doc.save(handleSave);\n }\n });\n\n function handleSave (err) {\n if (error) return;\n\n if (err) {\n self._validationError = undefined;\n return next(error = err);\n }\n\n --subdocs || next();\n }\n\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_registerHooks", - "string": "Document.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Registers an error

    ", - "summary": "

    Registers an error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_error", - "string": "Document.prototype._error()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes methods queued from the Schema definition

    ", - "summary": "

    Executes methods queued from the Schema definition

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_doQueue", - "string": "Document.prototype._doQueue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "js object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Converts this document into a plain javascript object

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", - "summary": "

    Converts this document into a plain javascript object

    ", - "body": "

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    See schema options for details.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toObject", - "string": "Document.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "json", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "either `virtuals` or `paths`" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "`json`" - } - ], - "description": { - "full": "

    Applies virtuals properties to json.

    ", - "summary": "

    Applies virtuals properties to json.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", - "ctx": { - "type": "function", - "name": "applyGetters", - "string": "applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "same options as `Document#toObject`" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "see", - "local": "Document#toObject #document_Document-toObject", - "visibility": "Document#toObject" - }, - { - "type": "", - "string": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    \n\n

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", - "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", - "body": "

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toJSON", - "string": "Document.prototype.toJSON()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "inspect", - "string": "Document.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "toString" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toString = Document.prototype.inspect;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "toString", - "value": "Document.prototype.inspect", - "string": "Document.prototypetoString" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "a document to compare" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", - "summary": "

    Returns true if the Document stores the same data as doc.

    ", - "body": "

    Documents are considered equal when they have matching _ids.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "equals", - "string": "Document.prototype.equals()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", - "ctx": { - "type": "property", - "receiver": "Document", - "name": "ValidationError", - "value": "ValidationError", - "string": "Document.ValidationError" - } - } -] -### lib/drivers/node-mongodb-native/binary.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require('mongodb').BSONPure.Binary", - "string": "Binary" - } - } -] -### lib/drivers/node-mongodb-native/collection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", - "ctx": { - "type": "declaration", - "name": "MongooseCollection", - "value": "require('../../collection')", - "string": "MongooseCollection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Collection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", - "summary": "

    A node-mongodb-native collection implementation.

    ", - "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", - "ctx": { - "type": "function", - "name": "NativeCollection", - "string": "NativeCollection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from abstract Collection.

    ", - "summary": "

    Inherit from abstract Collection.

    ", - "body": "" - }, - "ignore": true, - "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "__proto__", - "value": "MongooseCollection.prototype", - "string": "NativeCollection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection opens.

    ", - "summary": "

    Called when the connection opens.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onOpen", - "string": "NativeCollection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection closes

    ", - "summary": "

    Called when the connection closes

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onClose", - "string": "NativeCollection.prototype.onClose()" - } - }, - { - "tags": [], - "description": { - "full": "

    Copy the collection methods and make them subject to queues

    ", - "summary": "

    Copy the collection methods and make them subject to queues

    ", - "body": "" - }, - "ignore": true, - "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" - }, - { - "tags": [], - "description": { - "full": "

    Debug print helper

    ", - "summary": "

    Debug print helper

    ", - "body": "" - }, - "ignore": true, - "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", - "ctx": { - "type": "function", - "name": "print", - "string": "print()" - } - }, - { - "tags": [], - "description": { - "full": "

    Debug print helper

    ", - "summary": "

    Debug print helper

    ", - "body": "" - }, - "ignore": true, - "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if ('Date' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", - "ctx": { - "type": "function", - "name": "format", - "string": "format()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "method", - "string": "getIndexes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Retreives information about this collections indexes.

    ", - "summary": "

    Retreives information about this collections indexes.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "getIndexes", - "value": "NativeCollection.prototype.indexInformation", - "string": "NativeCollection.prototypegetIndexes" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeCollection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeCollection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/connection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", - "ctx": { - "type": "declaration", - "name": "MongooseConnection", - "value": "require('../../connection')", - "string": "MongooseConnection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Connection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A node-mongodb-native connection implementation.

    ", - "summary": "

    A node-mongodb-native connection implementation.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", - "ctx": { - "type": "function", - "name": "NativeConnection", - "string": "NativeConnection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Connection.

    ", - "summary": "

    Inherits from Connection.

    ", - "body": "" - }, - "ignore": true, - "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeConnection", - "name": "__proto__", - "value": "MongooseConnection.prototype", - "string": "NativeConnection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Opens the connection to MongoDB.

    ", - "summary": "

    Opens the connection to MongoDB.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, Number(this.port), this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpen", - "string": "NativeConnection.prototype.doOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - } - ], - "description": { - "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", - "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", - "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , ports = this.port\n , self = this\n\n this.host.forEach(function (host, i) {\n servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));\n });\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpenSet", - "string": "NativeConnection.prototype.doOpenSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Closes the connection

    ", - "summary": "

    Closes the connection

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doClose", - "string": "NativeConnection.prototype.doClose()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeConnection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeConnection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/objectid.js -[ - { - "tags": [ - { - "type": "constructor", - "string": "NodeMongoDbObjectId" - }, - { - "type": "see", - "local": "ObjectId", - "visibility": "ObjectId" - } - ], - "description": { - "full": "

    node-mongodb-native ObjectId

    ", - "summary": "

    node-mongodb-native ObjectId

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require('mongodb').BSONPure.ObjectID", - "string": "ObjectId" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", - "ctx": { - "type": "declaration", - "name": "ObjectIdToString", - "value": "ObjectId.toString.bind(ObjectId)", - "string": "ObjectIdToString" - } - } -] -### lib/error.js -[ - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" - } - ], - "description": { - "full": "

    Mongoose error

    ", - "summary": "

    Mongoose error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", - "ctx": { - "type": "function", - "name": "MongooseError", - "string": "MongooseError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Error.

    ", - "summary": "

    Inherits from Error.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseError.prototype.__proto__ = Error.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseError", - "name": "__proto__", - "value": "Error.prototype", - "string": "MongooseError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseError", - "string": "module.exports" - } - } -] -### lib/errors/cast.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casting Error constructor.

    ", - "summary": "

    Casting Error constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", - "ctx": { - "type": "function", - "name": "CastError", - "string": "CastError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "CastError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "CastError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "CastError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = CastError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "CastError", - "string": "module.exports" - } - } -] -### lib/errors/document.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements

    ", - "summary": "

    Module requirements

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Document Error

    ", - "summary": "

    Document Error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", - "ctx": { - "type": "function", - "name": "DocumentError", - "string": "DocumentError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "DocumentError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = DocumentError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = DocumentError", - "string": "module.exports" - } - } -] -### lib/errors/validation.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements

    ", - "summary": "

    Module requirements

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "instance", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

    Document Validation Error

    ", - "summary": "

    Document Validation Error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", - "ctx": { - "type": "function", - "name": "ValidationError", - "string": "ValidationError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Console.log helper

    ", - "summary": "

    Console.log helper

    ", - "body": "" - }, - "ignore": false, - "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", - "ctx": { - "type": "method", - "constructor": "ValidationError", - "name": "toString", - "string": "ValidationError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidationError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidationError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports

    ", - "summary": "

    Module exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = ValidationError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = ValidationError", - "string": "module.exports" - } - } -] -### lib/errors/validator.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Schema validator error

    ", - "summary": "

    Schema validator error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", - "ctx": { - "type": "function", - "name": "ValidatorError", - "string": "ValidatorError()" - } - }, - { - "tags": [], - "description": { - "full": "

    toString helper

    ", - "summary": "

    toString helper

    ", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", - "ctx": { - "type": "method", - "constructor": "ValidatorError", - "name": "toString", - "string": "ValidatorError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError

    ", - "summary": "

    Inherits from MongooseError

    ", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidatorError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidatorError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ValidatorError", - "string": "module.exports" - } - } -] -### lib/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", - "summary": "

    Mongoose constructor.

    ", - "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", - "ctx": { - "type": "function", - "name": "Mongoose", - "string": "Mongoose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", - "summary": "

    Sets mongoose options

    ", - "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "set", - "string": "Mongoose.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "method", - "string": "get" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", - "summary": "

    Gets mongoose options

    ", - "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.get = Mongoose.prototype.set;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "get", - "value": "Mongoose.prototype.set", - "string": "Mongoose.prototypeget" - } - }, - { - "tags": [], - "description": { - "full": "

    ReplSet connection string check.

    ", - "summary": "

    ReplSet connection string check.

    ", - "body": "" - }, - "ignore": true, - "code": "var rgxReplSet = /^.+,.+$/;", - "ctx": { - "type": "declaration", - "name": "rgxReplSet", - "value": "/^.+,.+$/", - "string": "rgxReplSet" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[uri]", - "description": "a mongodb:// URI" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options to pass to the driver" - }, - { - "type": "see", - "local": "Connection#open #connection_Connection-open", - "visibility": "Connection#open" - }, - { - "type": "see", - "local": "Connection#openSet #connection_Connection-openSet", - "visibility": "Connection#openSet" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "the created Connection object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Connection instance.

    \n\n

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    ", - "summary": "

    Creates a Connection instance.

    ", - "body": "

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "createConnection", - "string": "Mongoose.prototype.createConnection()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Mongoose#createConnection #index_Mongoose-createConnection", - "visibility": "Mongoose#createConnection" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - } - ], - "description": { - "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    ", - "summary": "

    Opens the default mongoose connection.

    ", - "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "connect", - "string": "Mongoose.prototype.connect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "called after all connection close." - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Disconnects all connections.

    ", - "summary": "

    Disconnects all connections.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "disconnect", - "string": "Mongoose.prototype.disconnect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name (optional, induced from model name)" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipInit]", - "description": "whether to skip initialization (defaults to false)" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    ", - "summary": "

    Defines a model or retrieves it.

    ", - "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n // normalize collection\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // look up models for the collection\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n this.modelSchemas[name] = schema;\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n } else {\n throw new Error('Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)');\n }\n }\n\n if (!this.models[name]) {\n schema || (schema = this.modelSchemas[name]);\n collection || (collection = schema.set('collection') || format(name));\n\n var model = Model.compile(name\n , this.modelSchemas[name]\n , collection\n , this.connection\n , this);\n\n if (!skipInit) model.init();\n\n this.models[name] = model;\n }\n\n return this.models[name];\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "model", - "string": "Mongoose.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "plugin callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "optional options" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", - "summary": "

    Declares a global plugin executed on all Schemas.

    ", - "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "plugin", - "string": "Mongoose.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "connection" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", - "summary": "

    The default connection of the mongoose module.

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" - }, - { - "tags": [], - "description": { - "full": "

    Driver depentend APIs

    ", - "summary": "

    Driver depentend APIs

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

    Connection

    ", - "summary": "

    Connection

    ", - "body": "" - }, - "ignore": true, - "code": "var Connection = require(driver + '/connection');", - "ctx": { - "type": "declaration", - "name": "Connection", - "value": "require(driver + '/connection')", - "string": "Connection" - } - }, - { - "tags": [], - "description": { - "full": "

    Collection

    ", - "summary": "

    Collection

    ", - "body": "" - }, - "ignore": true, - "code": "var Collection = require(driver + '/collection');", - "ctx": { - "type": "declaration", - "name": "Collection", - "value": "require(driver + '/collection')", - "string": "Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The exports object is an instance of Mongoose.

    ", - "summary": "

    The exports object is an instance of Mongoose.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = new Mongoose", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Collection constructor

    ", - "summary": "

    The Mongoose Collection constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Collection = Collection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Collection", - "value": "Collection", - "string": "mongoose.Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Connection constructor

    ", - "summary": "

    The Mongoose Connection constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Connection = Connection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Connection", - "value": "Connection", - "string": "mongoose.Connection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Mongoose version

    ", - "summary": "

    Mongoose version

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "version", - "value": "JSON.parse(", - "string": "mongoose.version" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", - "summary": "

    The Mongoose constructor

    ", - "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Mongoose = Mongoose;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Mongoose", - "value": "Mongoose", - "string": "mongoose.Mongoose" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", - "summary": "

    The Mongoose Schema constructor

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Schema = Schema;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Schema", - "value": "Schema", - "string": "mongoose.Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose SchemaType constructor.

    ", - "summary": "

    The Mongoose SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaType = SchemaType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaType", - "value": "SchemaType", - "string": "mongoose.SchemaType" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Schema.SchemaTypes #schema_Schema-Types", - "visibility": "Schema.SchemaTypes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", - "summary": "

    The various Mongoose SchemaTypes.

    ", - "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaTypes = Schema.Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaTypes", - "value": "Schema.Types", - "string": "mongoose.SchemaTypes" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose VirtualType constructor.

    ", - "summary": "

    The Mongoose VirtualType constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.VirtualType = VirtualType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "VirtualType", - "value": "VirtualType", - "string": "mongoose.VirtualType" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", - "summary": "

    The various Mongoose Types.

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Types = Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Types", - "value": "Types", - "string": "mongoose.Types" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Query constructor.

    ", - "summary": "

    The Mongoose Query constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Query = Query;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Query", - "value": "Query", - "string": "mongoose.Query" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Promise constructor.

    ", - "summary": "

    The Mongoose Promise constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Promise = Promise;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Promise", - "value": "Promise", - "string": "mongoose.Promise" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Model constructor.

    ", - "summary": "

    The Mongoose Model constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Model = Model;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Model", - "value": "Model", - "string": "mongoose.Model" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Document constructor.

    ", - "summary": "

    The Mongoose Document constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Document = Document;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Document", - "value": "Document", - "string": "mongoose.Document" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The MongooseError constructor.

    ", - "summary": "

    The MongooseError constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Error = require('./error');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Error", - "value": "require('./error')", - "string": "mongoose.Error" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The node-mongodb-native driver Mongoose uses.

    ", - "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.mongo = require('mongodb');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "mongo", - "value": "require('mongodb')", - "string": "mongoose.mongo" - } - } -] -### lib/model.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('./document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "values to with which to create the document" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "event", - "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." - }, - { - "type": "event", - "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Model constructor

    ", - "summary": "

    Model constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", - "ctx": { - "type": "function", - "name": "Model", - "string": "Model()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Document.

    ", - "summary": "

    Inherits from Document.

    ", - "body": "" - }, - "ignore": true, - "code": "Model.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "Model", - "name": "__proto__", - "value": "Document.prototype", - "string": "Model.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

    Connection the model uses.

    ", - "summary": "

    Connection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.db;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "collection" - } - ], - "description": { - "full": "

    Collection the model uses.

    ", - "summary": "

    Collection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.collection;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "modelName" - } - ], - "description": { - "full": "

    The name of the model

    ", - "summary": "

    The name of the model

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.modelName;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "object" - }, - { - "type": "return", - "types": [ - "Object", - "undefined" - ], - "description": "population paths" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns what paths can be populated

    ", - "summary": "

    Returns what paths can be populated

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_getPopulationKeys", - "string": "Model.prototype._getPopulationKeys()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "schema", - "description": "type for the oid" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "oid", - "description": "object id or array of object ids" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "query", - "description": "object specifying query conditions, fields, and options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Populates an object

    ", - "summary": "

    Populates an object

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_populate", - "string": "Model.prototype._populate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "query that originated the initialization" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs auto-population of relations.

    ", - "summary": "

    Performs auto-population of relations.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "init", - "string": "Model.prototype.init()" - } - }, - { - "tags": [], - "description": { - "full": "

    Handles doc.save() callbacks

    ", - "summary": "

    Handles doc.save() callbacks

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new Error('No matching document found.'));\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", - "ctx": { - "type": "function", - "name": "handleSave", - "string": "handleSave()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "title": "middleware", - "url": "http://mongoosejs.com/docs/middleware.html", - "visibility": "http://mongoosejs.com/docs/middleware.html" - } - ], - "description": { - "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", - "summary": "

    Saves this document.

    ", - "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n complete(null);\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "save", - "string": "Model.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Mixed" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[operation]", - "description": "" - } - ], - "description": { - "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", - "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", - "ctx": { - "type": "function", - "name": "operand", - "string": "operand()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "val", - "description": "" - } - ], - "description": { - "full": "

    Compiles an update and where clause for a val with _atomics.

    ", - "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", - "ctx": { - "type": "function", - "name": "handleAtomics", - "string": "handleAtomics()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Produces a special query document of the modified properties used in updates.

    ", - "summary": "

    Produces a special query document of the modified properties used in updates.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_delta", - "string": "Model.prototype._delta()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Appends versioning to the where and update clauses.

    ", - "summary": "

    Appends versioning to the where and update clauses.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_version", - "string": "Model.prototype._version()" - } - }, - { - "tags": [ - { - "type": "see", - "title": "versionKeys", - "url": "http://mongoosejs.com/docs/guide.html#versionKey", - "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Signal that we desire an increment of this documents version.

    ", - "summary": "

    Signal that we desire an increment of this documents version.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "increment", - "string": "Model.prototype.increment()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns a query object which applies shardkeys if they exist.

    ", - "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_where", - "string": "Model.prototype._where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", - "summary": "

    Removes this document from the db.

    ", - "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) return this;\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "remove", - "string": "Model.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register hooks override

    ", - "summary": "

    Register hooks override

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_registerHooks", - "string": "Model.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", - "summary": "

    Returns another Model instance.

    ", - "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "model", - "string": "Model.prototype.model()" - } - }, - { - "tags": [ - { - "type": "TODO", - "string": "determine if this is still necessary" - } - ], - "description": { - "full": "

    Give the constructor the ability to emit events.

    ", - "summary": "

    Give the constructor the ability to emit events.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the model compiles.

    ", - "summary": "

    Called when the model compiles.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.init = function init () {\n if (this.schema.options.autoIndex)\n this.ensureIndexes();\n\n this.schema.emit('init', this);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "init", - "string": "Model.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[cb]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    ", - "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", - "body": "

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "ensureIndexes", - "string": "Model.ensureIndexes()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "schema" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Schema the model uses.

    ", - "summary": "

    Schema the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.schema;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Database instance the model uses.

    ", - "summary": "

    Database instance the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.db;" - }, - { - "tags": [ - { - "type": "property", - "string": "collection" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Collection the model uses.

    ", - "summary": "

    Collection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.collection;" - }, - { - "tags": [ - { - "type": "property", - "string": "base" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Base Mongoose instance the model uses.

    ", - "summary": "

    Base Mongoose instance the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.base;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes documents from the collection.

    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    ", - "summary": "

    Removes documents from the collection.

    ", - "body": "

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "remove", - "string": "Model.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds documents

    \n\n

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    ", - "summary": "

    Finds documents

    ", - "body": "

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "find", - "string": "Model.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Merges the current named scope query into query.

    ", - "summary": "

    Merges the current named scope query into query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "_applyNamedScope", - "string": "Model._applyNamedScope()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "objectid, or a value that can be casted to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds a single document by id.

    \n\n

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    ", - "summary": "

    Finds a single document by id.

    ", - "body": "

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findById", - "string": "Model.findById()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    ", - "summary": "

    Finds one document.

    ", - "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n // TODO Handle all 3 of the following scenarios\n // Hint: Only some of these scenarios are possible if cQuery is present\n // Scenario: findOne(conditions, fields, callback);\n // Scenario: findOne(fields, options, callback);\n // Scenario: findOne(conditions, options, callback);\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n // TODO Handle all 2 of the following scenarios\n // Scenario: findOne(conditions, callback)\n // Scenario: findOne(fields, callback)\n // Scenario: findOne(options, callback);\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOne", - "string": "Model.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", - "summary": "

    Counts number of matching documents in a database collection.

    ", - "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "count", - "string": "Model.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes a DISTINCT command

    ", - "summary": "

    Executes a DISTINCT command

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "distinct", - "string": "Model.distinct()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "optional value" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", - "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", - "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "where", - "string": "Model.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "argument", - "description": "is a javascript string or anonymous function" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "memberOf", - "parent": "Model" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Query.$where #query_Query-%24where", - "visibility": "Query.$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    ", - "summary": "

    Creates a Query and specifies a $where condition.

    ", - "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Issues a mongodb findAndModify update command.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndUpdate", - "string": "Model.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "an ObjectId or string that can be cast to one." - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", - "visibility": "Model.findOneAndUpdate" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndUpdate", - "string": "Model.findByIdAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", - "summary": "

    Issue a mongodb findAndModify remove command.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndRemove", - "string": "Model.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "id", - "description": "ObjectId or string that can be cast to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", - "visibility": "Model.findOneAndRemove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - } - ], - "description": { - "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", - "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndRemove", - "string": "Model.findByIdAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array", - "Object..." - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", - "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", - "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "create", - "string": "Model.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "update", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Updates documents in the database without returning them.

    ", - "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "update", - "string": "Model.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "o", - "description": "an object specifying map-reduce options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/MapReduce", - "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", - "summary": "

    Executes a mapReduce command.

    ", - "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "mapReduce", - "string": "Model.mapReduce()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "an array of pipeline commands" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "aggregation", - "url": "http://docs.mongodb.org/manual/applications/aggregation/", - "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", - "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes an aggregate command on this models collection.

    \n\n

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    ", - "summary": "

    Executes an aggregate command on this models collection.

    ", - "body": "

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "aggregate", - "string": "Model.aggregate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "collectionName", - "description": "" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "connection", - "description": "" - }, - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "mongoose instance" - } - ], - "description": { - "full": "

    Compiler utility.

    ", - "summary": "

    Compiler utility.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "compile", - "string": "Model.compile()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Model;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Model", - "string": "module.exports" - } - } -] -### lib/namedscope.js -[ - { - "tags": [ - { - "type": "param", - "types": [ - "NamedScope" - ], - "name": "target", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "getters", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Decorate

    ", - "summary": "

    Decorate

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", - "ctx": { - "type": "method", - "constructor": "NamedScope", - "name": "decorate", - "string": "NamedScope.prototype.decorate()" - } - } -] -### lib/promise.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", - "ctx": { - "type": "declaration", - "name": "util", - "value": "require('./utils')", - "string": "util" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "back", - "description": "a callback+errback that accepts `fn(err, ...){}` as signature" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`err`: Emits when the promise resolves to an error." - }, - { - "type": "event", - "string": "`complete`: Emits when the promise resolves sucessfully." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Promise constructor.

    ", - "summary": "

    Promise constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", - "ctx": { - "type": "function", - "name": "Promise", - "string": "Promise()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from EventEmitter.

    ", - "summary": "

    Inherits from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Promise", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Promise.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Event" - ], - "name": "event", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds listener to the event.

    \n\n

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", - "summary": "

    Adds listener to the event.

    ", - "body": "

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "on", - "string": "Promise.prototype.on()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Keeps track of emitted events to run them on on.

    ", - "summary": "

    Keeps track of emitted events to run them on on.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "emit", - "string": "Promise.prototype.emit()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for emitting the complete event.

    ", - "summary": "

    Shortcut for emitting the complete event.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "complete", - "string": "Promise.prototype.complete()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

    Shortcut for emitting the err event.

    ", - "summary": "

    Shortcut for emitting the err event.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "error", - "string": "Promise.prototype.error()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for .on('complete', fn).

    ", - "summary": "

    Shortcut for .on('complete', fn).

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addCallback", - "string": "Promise.prototype.addCallback()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for .on('err', fn).

    ", - "summary": "

    Shortcut for .on('err', fn).

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addErrback", - "string": "Promise.prototype.addErrback()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

    Adds a single function that's both a callback and errback.

    ", - "summary": "

    Adds a single function that's both a callback and errback.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addBack", - "string": "Promise.prototype.addBack()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "optional error or null" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "value to complete the promise with" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", - "summary": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "resolve", - "string": "Promise.prototype.resolve()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Promise;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Promise", - "string": "module.exports" - } - } -] -### lib/query.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "criteria", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", - "summary": "

    Query constructor used for building queries.

    ", - "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n if (criteria) this.find(criteria);\n}", - "ctx": { - "type": "function", - "name": "Query", - "string": "Query()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", - "summary": "

    Sets query options.

    ", - "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "setOptions", - "string": "Query.prototype.setOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "the model to which the query is bound" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "the operation to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "updateArg", - "description": "used in update methods" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Binds this query to a model.

    ", - "summary": "

    Binds this query to a model.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "bind", - "string": "Query.prototype.bind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "[operation]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", - "summary": "

    Executes the query

    ", - "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exec", - "string": "Query.prototype.exec()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[criteria]", - "description": "mongodb selector" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", - "summary": "

    Finds documents.

    ", - "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "find", - "string": "Query.prototype.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[obj]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", - "summary": "

    Casts this query to the schema of model

    ", - "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "cast", - "string": "Query.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns default options.

    ", - "summary": "

    Returns default options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_optionsForExec", - "string": "Query.prototype._optionsForExec()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies schematype selected options to this query.

    ", - "summary": "

    Applies schematype selected options to this query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_applyPaths", - "string": "Query.prototype._applyPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "js", - "description": "javascript string or function" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", - "summary": "

    Specifies a $where condition

    ", - "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", - "summary": "

    Specifies a path for use with chaining.

    ", - "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "where", - "string": "Query.prototype.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", - "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", - "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "equals", - "string": "Query.prototype.equals()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", - "summary": "

    Specifies arguments for an $or condition.

    ", - "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "or", - "string": "Query.prototype.or()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", - "summary": "

    Specifies arguments for a $nor condition.

    ", - "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nor", - "string": "Query.prototype.nor()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "gt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", - "summary": "

    Specifies a $gt query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "gte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $gte query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $lt query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $lte query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "ne" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $ne query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "in" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $in query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "nin" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $nin query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "all" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $all query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "size" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $size query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "regex" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $regex query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxDistance" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $maxDistance query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", - "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", - "body": "
    Thing.where('type').nin(array)\n
    " - }, - "ignore": true, - "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $near condition

    ", - "summary": "

    Specifies a $near condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "near", - "string": "Query.prototype.near()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $nearSphere condition.

    ", - "summary": "

    Specifies a $nearSphere condition.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nearSphere", - "string": "Query.prototype.nearSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $mod condition

    ", - "summary": "

    Specifies a $mod condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "mod", - "string": "Query.prototype.mod()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $exists condition

    ", - "summary": "

    Specifies an $exists condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exists", - "string": "Query.prototype.exists()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object", - "Function" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "Function" - ], - "name": "criteria", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", - "summary": "

    Specifies an $elemMatch condition

    ", - "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "elemMatch", - "string": "Query.prototype.elemMatch()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "within" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Syntax sugar for expressive queries.

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    ", - "summary": "

    Syntax sugar for expressive queries.

    ", - "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "see", - "local": "Query#within #query_Query-within", - "visibility": "Query#within" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", - "summary": "

    Specifies a $box condition

    ", - "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "box", - "string": "Query.prototype.box()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "options e.g. { $uniqueDocs: true }" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", - "summary": "

    Specifies a $center condition

    ", - "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "center", - "string": "Query.prototype.center()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", - "summary": "

    Specifies a $centerSphere condition

    ", - "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "centerSphere", - "string": "Query.prototype.centerSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Array", - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", - "summary": "

    Specifies a $polygon condition

    ", - "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "polygon", - "string": "Query.prototype.polygon()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "local": "SchemaType", - "visibility": "SchemaType" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    ", - "summary": "

    Specifies which document fields to include or exclude

    ", - "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "select", - "string": "Query.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "number of elements to slice" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", - "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", - "summary": "

    Specifies a $slice condition

    ", - "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slice", - "string": "Query.prototype.slice()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", - "summary": "

    Sets the sort order

    ", - "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "sort", - "string": "Query.prototype.sort()" - } - }, - { - "tags": [], - "description": { - "full": "

    @ignore

    ", - "summary": "

    @ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", - "ctx": { - "type": "function", - "name": "push", - "string": "push()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "limit" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", - "summary": "

    Specifies the limit option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "skip" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", - "summary": "

    Specifies the skip option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxscan" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", - "summary": "

    Specifies the maxscan option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "batchSize" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", - "summary": "

    Specifies the batchSize option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "comment" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", - "summary": "

    Specifies the comment option.

    ", - "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", - "summary": "

    limit, skip, maxscan, batchSize, comment

    ", - "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " - }, - "ignore": true, - "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", - "summary": "

    Specifies this query as a snapshot query.

    ", - "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "snapshot", - "string": "Query.prototype.snapshot()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "a hint object" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", - "summary": "

    Sets query hints.

    ", - "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "hint", - "string": "Query.prototype.hint()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", - "summary": "

    Sets the slaveOk option.

    ", - "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slaveOk", - "string": "Query.prototype.slaveOk()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "one of the listed preference options or their aliases" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "[tags]", - "description": "optional tags for this query" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", - "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the readPreference option for the query.

    \n\n

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    ", - "summary": "

    Sets the readPreference option for the query.

    ", - "body": "

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "read", - "string": "Query.prototype.read()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", - "summary": "

    Sets the lean option.

    ", - "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "lean", - "string": "Query.prototype.lean()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", - "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", - "summary": "

    Sets tailable option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "tailable", - "string": "Query.prototype.tailable()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes the query as a find() operation.

    ", - "summary": "

    Executes the query as a find() operation.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "execFind", - "string": "Query.prototype.execFind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", - "summary": "

    Executes the query as a findOne() operation.

    ", - "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOne", - "string": "Query.prototype.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", - "summary": "

    Exectues the query as a count() operation.

    ", - "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "count", - "string": "Query.prototype.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as a distict() operation.

    ", - "summary": "

    Executes this query as a distict() operation.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "distinct", - "string": "Query.prototype.distinct()" - } - }, - { - "tags": [], - "description": { - "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", - "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", - "body": "" - }, - "ignore": true, - "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", - "ctx": { - "type": "declaration", - "name": "castOps", - "value": "{", - "string": "castOps" - } - }, - { - "tags": [], - "description": { - "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", - "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", - "body": "" - }, - "ignore": true, - "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", - "ctx": { - "type": "declaration", - "name": "numberOps", - "value": "{", - "string": "numberOps" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "the update conditions" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", - "summary": "

    Executes this query as an update() operation.

    ", - "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n delete options.safe;\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "update", - "string": "Query.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "obj after casting its values" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts obj for an update command.

    ", - "summary": "

    Casts obj for an update command.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdate", - "string": "Query.prototype._castUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "- part of a query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "- path prefix (internal only)" - }, - { - "type": "return", - "types": [ - "Bool" - ], - "description": "true if this path has keys to update" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", - "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_walkUpdatePath", - "string": "Query.prototype._walkUpdatePath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[$conditional]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts val according to schema and atomic op.

    ", - "summary": "

    Casts val according to schema and atomic op.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdateVal", - "string": "Query.prototype._castUpdateVal()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_getSchema", - "string": "Query.prototype._getSchema()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "https://github.com/LearnBoost/mongoose/issues/1091", - "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" - }, - { - "type": "see", - "title": "", - "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", - "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts selected field arguments for field selection with mongo 2.2

    \n\n
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    ", - "summary": "

    Casts selected field arguments for field selection with mongo 2.2

    ", - "body": "
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castFields", - "string": "Query.prototype._castFields()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", - "summary": "

    Executes this query as a remove() operation.

    ", - "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n delete options.safe;\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "remove", - "string": "Query.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[query]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[doc]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", - "summary": "

    Issues a mongodb findAndModify update command.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndUpdate", - "string": "Query.prototype.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", - "summary": "

    Issues a mongodb findAndModify remove command.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndRemove", - "string": "Query.prototype.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "- either \"remove\" or \"update\"" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    _findAndModify

    ", - "summary": "

    _findAndModify

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_findAndModify", - "string": "Query.prototype._findAndModify()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Model" - ], - "name": "[model]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "see", - "local": "population ./populate.html", - "visibility": "population" - }, - { - "type": "see", - "local": "Query#select #query_Query-select", - "visibility": "Query#select" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    ", - "summary": "

    Specifies paths which should be populated with other documents.

    ", - "body": "

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "populate", - "string": "Query.prototype.populate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Populate options constructor

    ", - "summary": "

    Populate options constructor

    ", - "body": "" - }, - "ignore": true, - "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", - "ctx": { - "type": "function", - "name": "PopulateOptions", - "string": "PopulateOptions()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "QueryStream" - ], - "description": "" - }, - { - "type": "see", - "local": "QueryStream", - "visibility": "QueryStream" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a stream interface

    \n\n

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    ", - "summary": "

    Returns a stream interface

    ", - "body": "

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "stream", - "string": "Query.prototype.stream()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    castDoc

    ", - "summary": "

    castDoc

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castDoc", - "string": "castDoc()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    castQuery

    ", - "summary": "

    castQuery

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castQuery", - "string": "castQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Exports.

    ", - "summary": "

    Exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Query", - "string": "module.exports" - } - } -] -### lib/querystream.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", - "ctx": { - "type": "declaration", - "name": "Stream", - "value": "require('stream').Stream", - "string": "Stream" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS Stream http://nodejs.org/api/stream.html" - }, - { - "type": "event", - "string": "`data`: emits a single Mongoose document" - }, - { - "type": "event", - "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." - }, - { - "type": "event", - "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Provides a ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    ", - "summary": "

    Provides a ReadStream interface for Queries.

    ", - "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n this._running = false;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", - "ctx": { - "type": "function", - "name": "QueryStream", - "string": "QueryStream()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Stream

    ", - "summary": "

    Inherit from Stream

    ", - "body": "" - }, - "ignore": true, - "code": "QueryStream.prototype.__proto__ = Stream.prototype;", - "ctx": { - "type": "property", - "constructor": "QueryStream", - "name": "__proto__", - "value": "Stream.prototype", - "string": "QueryStream.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readable" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Flag stating whether or not this stream is readable.

    ", - "summary": "

    Flag stating whether or not this stream is readable.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.readable;" - }, - { - "tags": [ - { - "type": "property", - "string": "paused" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Flag stating whether or not this stream is paused.

    ", - "summary": "

    Flag stating whether or not this stream is paused.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Initializes the query.

    ", - "summary": "

    Initializes the query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_init", - "string": "QueryStream.prototype._init()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#__next #querystream_QueryStream-__next", - "visibility": "QueryStream#__next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Trampoline for pulling the next doc from cursor.

    ", - "summary": "

    Trampoline for pulling the next doc from cursor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) {\n return this._running = false;\n }\n\n this._running = true;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n while (this.__next()) {}\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_next", - "string": "QueryStream.prototype._next()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#_next #querystream_QueryStream-_next", - "visibility": "QueryStream#_next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Pulls the next doc from the cursor.

    ", - "summary": "

    Pulls the next doc from the cursor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed)\n return this._running = false;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "__next", - "string": "QueryStream.prototype.__next()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error", - "null" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", - "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return this._running = false;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && true === this.query.options.lean) {\n this.emit('data', doc);\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_onNextObject", - "string": "QueryStream.prototype._onNextObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pauses this stream.

    ", - "summary": "

    Pauses this stream.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "pause", - "string": "QueryStream.prototype.pause()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Resumes this stream.

    ", - "summary": "

    Resumes this stream.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n\n if (!this._cursor) {\n // cannot start if not initialized\n return;\n }\n\n // are we within the trampoline?\n if (T_INIT === this._inline) {\n return;\n }\n\n if (!this._running) {\n // outside QueryStream control, need manual restart\n return this._next();\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "resume", - "string": "QueryStream.prototype.resume()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "[err]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", - "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this._running = false;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "destroy", - "string": "QueryStream.prototype.destroy()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "pipe" - }, - { - "type": "memberOf", - "parent": "QueryStream" - }, - { - "type": "see", - "title": "NodeJS", - "url": "http://nodejs.org/api/stream.html", - "visibility": "http://nodejs.org/api/stream.html" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", - "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", - "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    Module exports

    ", - "summary": "

    Module exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = QueryStream", - "string": "module.exports" - } - } -] -### lib/schema/array.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Array SchemaType constructor

    ", - "summary": "

    Array SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "SchemaArray", - "string": "SchemaArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaArray", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "checkRequired", - "string": "SchemaArray.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Overrides the getters application for the population special-case

    ", - "summary": "

    Overrides the getters application for the population special-case

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "applyGetters", - "string": "SchemaArray.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "cast", - "string": "SchemaArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "castForQuery", - "string": "SchemaArray.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    @ignore

    ", - "summary": "

    @ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': SchemaArray.prototype.castForQuery\n , '$gte': SchemaArray.prototype.castForQuery\n , '$lt': SchemaArray.prototype.castForQuery\n , '$lte': SchemaArray.prototype.castForQuery\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", - "ctx": { - "type": "function", - "name": "castToNumber", - "string": "castToNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaArray", - "string": "module.exports" - } - } -] -### lib/schema/boolean.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Boolean SchemaType constructor.

    ", - "summary": "

    Boolean SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaBoolean", - "string": "SchemaBoolean()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBoolean", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBoolean.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator

    ", - "summary": "

    Required validator

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "checkRequired", - "string": "SchemaBoolean.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to boolean

    ", - "summary": "

    Casts to boolean

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "cast", - "string": "SchemaBoolean.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", - "ctx": { - "type": "function", - "name": "handleArray", - "string": "handleArray()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "castForQuery", - "string": "SchemaBoolean.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBoolean;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBoolean", - "string": "module.exports" - } - } -] -### lib/schema/buffer.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Buffer SchemaType constructor

    ", - "summary": "

    Buffer SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", - "ctx": { - "type": "function", - "name": "SchemaBuffer", - "string": "SchemaBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBuffer", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBuffer.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "checkRequired", - "string": "SchemaBuffer.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "cast", - "string": "SchemaBuffer.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "castForQuery", - "string": "SchemaBuffer.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBuffer;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBuffer", - "string": "module.exports" - } - } -] -### lib/schema/date.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements.

    ", - "summary": "

    Module requirements.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Date SchemaType constructor.

    ", - "summary": "

    Date SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaDate", - "string": "SchemaDate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaDate", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaDate.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator for date

    ", - "summary": "

    Required validator for date

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "checkRequired", - "string": "SchemaDate.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to date

    ", - "summary": "

    Casts to date

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "cast", - "string": "SchemaDate.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Date Query casting.

    ", - "summary": "

    Date Query casting.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "castForQuery", - "string": "SchemaDate.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaDate;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaDate", - "string": "module.exports" - } - } -] -### lib/schema/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaArray" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    SubdocsArray SchemaType constructor

    ", - "summary": "

    SubdocsArray SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "DocumentArray", - "string": "DocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from ArrayType.

    ", - "summary": "

    Inherits from ArrayType.

    ", - "body": "" - }, - "ignore": true, - "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentArray", - "name": "__proto__", - "value": "ArrayType.prototype", - "string": "DocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs local validations first, then validations on each embedded doc

    ", - "summary": "

    Performs local validations first, then validations on each embedded doc

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n\n SchemaType.prototype.doValidate.call(this, array, function (err) {\n if (err) return fn(err);\n\n var count = array && array.length\n , error;\n\n if (!count) return fn();\n\n // handle sparse arrays, do not use array.forEach which does not\n // iterate over sparse elements yet reports array.length including\n // them :(\n\n for (var i = 0, len = count; i < len; ++i) {\n // sidestep sparse entries\n var doc = array[i];\n if (!doc) {\n --count || fn();\n continue;\n }\n\n ;(function (i) {\n doc.validate(function (err) {\n if (err && !error) {\n // rewrite the key\n err.key = self.key + '.' + i + '.' + err.key;\n return fn(error = err);\n }\n --count || fn();\n });\n })(i);\n }\n }, scope);\n};", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "doValidate", - "string": "DocumentArray.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "document", - "description": "that triggers the casting" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument) && value[i]) {\n if (init) {\n selected || (selected = scopePaths(this, doc._selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "cast", - "string": "DocumentArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "DocumentArray" - ], - "name": "array", - "description": "- the array to scope `fields` paths" - }, - { - "type": "param", - "types": [ - "Object", - "undefined" - ], - "name": "fields", - "description": "- the root fields selected in the query" - }, - { - "type": "param", - "types": [ - "Boolean", - "undefined" - ], - "name": "init", - "description": "- if we are being created part of a query result" - } - ], - "description": { - "full": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", - "summary": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , hasKeys\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n hasKeys || (hasKeys = true);\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return hasKeys && selected || undefined;\n}", - "ctx": { - "type": "function", - "name": "scopePaths", - "string": "scopePaths()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = DocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "DocumentArray", - "string": "module.exports" - } - } -] -### lib/schema/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "String", - "value": "require('./string')", - "string": "exports.String" - } - } -] -### lib/schema/mixed.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Mixed SchemaType constructor.

    ", - "summary": "

    Mixed SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "Mixed", - "string": "Mixed()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "Mixed", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "Mixed.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator

    ", - "summary": "

    Required validator

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "checkRequired", - "string": "Mixed.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", - "summary": "

    Casts val for Mixed.

    ", - "body": "

    this is a no-op

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "cast", - "string": "Mixed.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$cond", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "castForQuery", - "string": "Mixed.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Mixed;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Mixed", - "string": "module.exports" - } - } -] -### lib/schema/number.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements.

    ", - "summary": "

    Module requirements.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Number SchemaType constructor.

    ", - "summary": "

    Number SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", - "ctx": { - "type": "function", - "name": "SchemaNumber", - "string": "SchemaNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaNumber", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaNumber.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator for number

    ", - "summary": "

    Required validator for number

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "checkRequired", - "string": "SchemaNumber.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "value", - "description": "minimum number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", - "summary": "

    Sets a maximum number validator.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "min", - "string": "SchemaNumber.prototype.min()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "maximum", - "description": "number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", - "summary": "

    Sets a maximum number validator.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "max", - "string": "SchemaNumber.prototype.max()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "value to cast" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to number

    ", - "summary": "

    Casts to number

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "cast", - "string": "SchemaNumber.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "castForQuery", - "string": "SchemaNumber.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaNumber;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaNumber", - "string": "module.exports" - } - } -] -### lib/schema/objectid.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    ObjectId SchemaType constructor.

    ", - "summary": "

    ObjectId SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", - "ctx": { - "type": "function", - "name": "ObjectId", - "string": "ObjectId()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "ObjectId", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "ObjectId.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "checkRequired", - "string": "ObjectId.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to ObjectId

    ", - "summary": "

    Casts to ObjectId

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "cast", - "string": "ObjectId.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "castForQuery", - "string": "ObjectId.prototype.castForQuery()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "turnOn", - "description": "auto generated ObjectId defaults" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", - "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "auto", - "string": "ObjectId.prototype.auto()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", - "ctx": { - "type": "function", - "name": "defaultId", - "string": "defaultId()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = ObjectId;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ObjectId", - "string": "module.exports" - } - } -] -### lib/schema/string.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    String SchemaType constructor.

    ", - "summary": "

    String SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", - "ctx": { - "type": "function", - "name": "SchemaString", - "string": "SchemaString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaString", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaString.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[args...]", - "description": "enumeration values" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", - "summary": "

    Adds enumeration values and a coinciding validator.

    ", - "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "enum", - "string": "SchemaString.prototype.enum()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", - "summary": "

    Adds a lowercase setter.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toLowerCase();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "lowercase", - "string": "SchemaString.prototype.lowercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", - "summary": "

    Adds an uppercase setter.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toUpperCase();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "uppercase", - "string": "SchemaString.prototype.uppercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", - "summary": "

    Adds a trim setter.

    ", - "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.trim();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "trim", - "string": "SchemaString.prototype.trim()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp" - ], - "name": "regExp", - "description": "regular expression to test against" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", - "summary": "

    Sets a regexp validator.

    ", - "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "match", - "string": "SchemaString.prototype.match()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "null", - "undefined" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "checkRequired", - "string": "SchemaString.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to String

    ", - "summary": "

    Casts to String

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "cast", - "string": "SchemaString.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "castForQuery", - "string": "SchemaString.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaString;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaString", - "string": "module.exports" - } - } -] -### lib/schema.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "definition", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted after the schema is compiled into a `Model`." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", - "summary": "

    Schema constructor.

    ", - "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", - "ctx": { - "type": "function", - "name": "Schema", - "string": "Schema()" - } - }, - { - "tags": [], - "description": { - "full": "

    Returns this documents _id cast to a string.

    ", - "summary": "

    Returns this documents _id cast to a string.

    ", - "body": "" - }, - "ignore": true, - "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", - "ctx": { - "type": "function", - "name": "idGetter", - "string": "idGetter()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Schema", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Schema.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "paths" - } - ], - "description": { - "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", - "summary": "

    Schema as flat paths

    ", - "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.paths;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "tree" - } - ], - "description": { - "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", - "summary": "

    Schema as a tree

    ", - "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.tree;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns default options for this schema, merged with options.

    ", - "summary": "

    Returns default options for this schema, merged with options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.defaultOptions = function (options) {\n options = utils.options({\n safe: true\n , strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "defaultOptions", - "string": "Schema.prototype.defaultOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "prefix", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", - "summary": "

    Adds key path / schema type pairs to this schema.

    ", - "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n }\n else\n this.path(prefix + i, obj[i]); // mixed type\n } else\n this.path(prefix + i, obj[i]);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "add", - "string": "Schema.prototype.add()" - } - }, - { - "tags": [], - "description": { - "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    ", - "summary": "

    Reserved document keys.

    ", - "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    " - }, - "ignore": false, - "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "reserved", - "value": "Object.create(null)", - "string": "Schema.reserved" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "constructor", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", - "summary": "

    Gets/sets schema paths.

    ", - "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(path) {\n if (!branch[path]) branch[path] = {};\n branch = branch[path];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "path", - "string": "Schema.prototype.path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "constructor" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts type arguments into Mongoose Types.

    ", - "summary": "

    Converts type arguments into Mongoose Types.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", - "ctx": { - "type": "method", - "receiver": "Schema", - "name": "interpretAsType", - "string": "Schema.interpretAsType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback function" - }, - { - "type": "return", - "types": [ - "Schema" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", - "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", - "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "eachPath", - "string": "Schema.prototype.eachPath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns an Array of path strings that are required by this schema.

    ", - "summary": "

    Returns an Array of path strings that are required by this schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "requiredPaths", - "string": "Schema.prototype.requiredPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", - "summary": "

    Returns the pathType of path for this schema.

    ", - "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pathType", - "string": "Schema.prototype.pathType()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", - "ctx": { - "type": "function", - "name": "getPositionalPath", - "string": "getPositionalPath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the document method to call later" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Adds a method call to the queue.

    ", - "summary": "

    Adds a method call to the queue.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "queue", - "string": "Schema.prototype.queue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", - "summary": "

    Defines a pre hook for the document.

    ", - "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pre", - "string": "Schema.prototype.pre()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "name of the method to hook" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", - "summary": "

    Defines a post hook for the document.

    ", - "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "post", - "string": "Schema.prototype.post()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "plugin", - "description": "callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "" - }, - { - "type": "see", - "local": "plugins", - "visibility": "plugins" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Registers a plugin for this schema.

    ", - "summary": "

    Registers a plugin for this schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "plugin", - "string": "Schema.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "method", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", - "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", - "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "method", - "string": "Schema.prototype.method()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", - "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", - "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "static", - "string": "Schema.prototype.static()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", - "summary": "

    Defines an index (most likely compound) for this schema.

    ", - "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "index", - "string": "Schema.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "option name" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[value]", - "description": "if not passed, the current option value is returned" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets/gets a schema option.

    ", - "summary": "

    Sets/gets a schema option.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.set = function (key, value, tags) {\n if (arguments.length == 1)\n return this.options[key];\n\n this.options[key] = 'read' == key\n ? utils.readPref(value, tags)\n : value;\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "set", - "string": "Schema.prototype.set()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Compiles indexes from fields and schema-level indexes

    ", - "summary": "

    Compiles indexes from fields and schema-level indexes

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "indexes", - "string": "Schema.prototype.indexes()" - } - }, - { - "tags": [], - "description": { - "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", - "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", - "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " - }, - "ignore": true, - "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", - "ctx": { - "type": "function", - "name": "fixSubIndexPaths", - "string": "fixSubIndexPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

    Creates a virtual type with the given name.

    ", - "summary": "

    Creates a virtual type with the given name.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtual", - "string": "Schema.prototype.virtual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the virtual type with the given name.

    ", - "summary": "

    Returns the virtual type with the given name.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtualpath", - "string": "Schema.prototype.virtualpath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", - "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "namedScope", - "string": "Schema.prototype.namedScope()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Schema", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose Schema Types.

    \n\n

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", - "summary": "

    The various Mongoose Schema Types.

    ", - "body": "

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.Types = require('./schema/index');", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "Types", - "value": "require('./schema/index')", - "string": "Schema.Types" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" - } -] -### lib/schemadefault.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "property", - "string": "system.profile" - }, - { - "type": "receiver", - "string": "exports" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Default model for querying the system.profiles collection.

    ", - "summary": "

    Default model for querying the system.profiles collection.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" - } -] -### lib/schematype.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');\nvar CastError = require('./errors/cast')\nvar ValidatorError = require('./errors/validator')", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[instance]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    SchemaType constructor

    ", - "summary": "

    SchemaType constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", - "ctx": { - "type": "function", - "name": "SchemaType", - "string": "SchemaType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function", - "any" - ], - "name": "val", - "description": "the default value" - }, - { - "type": "return", - "types": [ - "defaultValue" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", - "summary": "

    Sets a default value for this SchemaType.

    ", - "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "default", - "string": "SchemaType.prototype.default()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "Boolean" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", - "summary": "

    Declares the index options for this schematype.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "index", - "string": "SchemaType.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares an unique index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    ", - "summary": "

    Declares an unique index.

    ", - "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "unique", - "string": "SchemaType.prototype.unique()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a sparse index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", - "summary": "

    Declares a sparse index.

    ", - "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "sparse", - "string": "SchemaType.prototype.sparse()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "when", - "description": "" - }, - { - "type": "added", - "string": "3.0.0" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    ", - "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", - "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "expires", - "string": "SchemaType.prototype.expires()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    ", - "summary": "

    Adds a setter to this schematype.

    ", - "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "set", - "string": "SchemaType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    ", - "summary": "

    Adds a getter to this schematype.

    ", - "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "get", - "string": "SchemaType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp", - "Function", - "Object" - ], - "name": "obj", - "description": "validator" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[error]", - "description": "optional error message" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", - "summary": "

    Adds validator(s) for this document path.

    ", - "body": "

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "validate", - "string": "SchemaType.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "required", - "description": "enable/disable the validator" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", - "summary": "

    Adds a required validator to this schematype.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "required", - "string": "SchemaType.prototype.required()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope which callback are executed" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Gets the default value

    ", - "summary": "

    Gets the default value

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "getDefault", - "string": "SchemaType.prototype.getDefault()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies setters

    ", - "summary": "

    Applies setters

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applySetters", - "string": "SchemaType.prototype.applySetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies getters to a value

    ", - "summary": "

    Applies getters to a value

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applyGetters", - "string": "SchemaType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", - "summary": "

    Sets default select() behavior for this path.

    ", - "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "select", - "string": "SchemaType.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", - "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "doValidate", - "string": "SchemaType.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determines if value is a valid Reference.

    ", - "summary": "

    Determines if value is a valid Reference.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", - "ctx": { - "type": "method", - "receiver": "SchemaType", - "name": "_isRef", - "string": "SchemaType._isRef()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = SchemaType", - "string": "module.exports" - } - } -] -### lib/statemachine.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", - "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", - "ctx": { - "type": "declaration", - "name": "StateMachine", - "value": "module.exports = exports = function StateMachine () {", - "string": "StateMachine" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "subclass constructor" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", - "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", - "ctx": { - "type": "method", - "receiver": "StateMachine", - "name": "ctor", - "string": "StateMachine.ctor()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", - "summary": "

    This function is wrapped by the state change functions

    ", - "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_changeState", - "string": "StateMachine.prototype._changeState()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "clear", - "string": "StateMachine.prototype.clear()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "that we want to check for." - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", - "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "some", - "string": "StateMachine.prototype.some()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "iterMethod", - "description": "is either 'forEach' or 'map'" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", - "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_iter", - "string": "StateMachine.prototype._iter()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", - "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", - "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "forEach", - "string": "StateMachine.prototype.forEach()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", - "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", - "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "map", - "string": "StateMachine.prototype.map()" - } - } -] -### lib/types/array.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", - "ctx": { - "type": "declaration", - "name": "EmbeddedDocument", - "value": "require('./embedded')", - "string": "EmbeddedDocument" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Array" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", - "summary": "

    Mongoose Array constructor.

    ", - "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseArray", - "string": "MongooseArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Array

    ", - "summary": "

    Inherit from Array

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseArray.prototype = new Array;", - "ctx": { - "type": "property", - "receiver": "MongooseArray", - "name": "prototype", - "value": "new Array", - "string": "MongooseArray.prototype" - } - }, - { - "tags": [ - { - "type": "property", - "string": "_atomics" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Stores a queue of atomic operations to perform

    ", - "summary": "

    Stores a queue of atomic operations to perform

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._atomics;" - }, - { - "tags": [ - { - "type": "property", - "string": "_parent" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Parent owner document

    ", - "summary": "

    Parent owner document

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._parent;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "return", - "types": [ - "value" - ], - "description": "the casted value" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts a member based on this arrays schema.

    ", - "summary": "

    Casts a member based on this arrays schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_cast", - "string": "MongooseArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "EmbeddedDocument" - ], - "name": "embeddedDoc", - "description": "the embedded doc that invoked this method on the Array" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "embeddedPath", - "description": "the path which changed in the embeddedDoc" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", - "summary": "

    Marks this array as modified.

    ", - "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._markModified = function (elem, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n dirtyPath = this._path;\n\n if (arguments.length) {\n if (null != embeddedPath) {\n // an embedded doc bubbled up the change\n dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;\n } else {\n // directly set an index\n dirtyPath = dirtyPath + '.' + elem;\n }\n\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_markModified", - "string": "MongooseArray.prototype._markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "op", - "description": "operation" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register an atomic operation with the parent.

    ", - "summary": "

    Register an atomic operation with the parent.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n this._markModified();\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n if (this._atomics.$set) {\n return this;\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n this._markModified();\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n this._markModified();\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_registerAtomic", - "string": "MongooseArray.prototype._registerAtomic()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", - "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "hasAtomics", - "string": "MongooseArray.prototype.hasAtomics()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#push with proper change tracking.

    ", - "summary": "

    Wraps Array#push with proper change tracking.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "push", - "string": "MongooseArray.prototype.push()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Pushes items to the array non-atomically.

    ", - "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "nonAtomicPush", - "string": "MongooseArray.prototype.nonAtomicPush()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "$pop" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", - "summary": "

    Pops the array atomically at most one time per document save().

    ", - "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" - }, - { - "tags": [ - { - "type": "see", - "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", - "visibility": "MongooseArray#$pop" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#pop with proper change tracking.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pop", - "string": "MongooseArray.prototype.pop()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "method", - "string": "$shift" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", - "summary": "

    Atomically shifts the array at most one time per document save().

    ", - "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#shift with proper change tracking.

    ", - "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "shift", - "string": "MongooseArray.prototype.shift()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "values to remove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes items from an array atomically

    \n\n

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    ", - "summary": "

    Removes items from an array atomically

    ", - "body": "

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "remove", - "string": "MongooseArray.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pulls items from the array atomically.

    ", - "summary": "

    Pulls items from the array atomically.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pull", - "string": "MongooseArray.prototype.pull()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#splice with proper change tracking and casting.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#splice with proper change tracking and casting.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.splice = function splice () {\n var ret, vals, i;\n\n if (arguments.length) {\n vals = [];\n for (i = 0; i < arguments.length; ++i) {\n vals[i] = i < 2\n ? arguments[i]\n : this._cast(arguments[i]);\n }\n ret = [].splice.apply(this, vals);\n this._registerAtomic('$set', this);\n }\n\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "splice", - "string": "MongooseArray.prototype.splice()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#unshift with proper change tracking.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n return this.length;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "unshift", - "string": "MongooseArray.prototype.unshift()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#sort with proper change tracking.

    ", - "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "sort", - "string": "MongooseArray.prototype.sort()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "the values that were added" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", - "summary": "

    Adds values to the array if not already present.

    ", - "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "addToSet", - "string": "MongooseArray.prototype.addToSet()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the casted val at index i and marks the array modified.

    \n\n

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    ", - "summary": "

    Sets the casted val at index i and marks the array modified.

    ", - "body": "

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.set = function set (i, val) {\n this[i] = this._cast(val);\n this._markModified(i);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "set", - "string": "MongooseArray.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a native js Array.

    ", - "summary": "

    Returns a native js Array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "toObject", - "string": "MongooseArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "inspect", - "string": "MongooseArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the item to look for" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Return the index of obj or -1 if not found.

    ", - "summary": "

    Return the index of obj or -1 if not found.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "indexOf", - "string": "MongooseArray.prototype.indexOf()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = MongooseArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = MongooseArray", - "string": "module.exports" - } - } -] -### lib/types/buffer.js -[ - { - "tags": [], - "description": { - "full": "

    Access driver.

    ", - "summary": "

    Access driver.

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Binary = require(driver + '/binary');", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require(driver + '/binary')", - "string": "Binary" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "encode", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "offset", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Buffer" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", - "summary": "

    Mongoose Buffer constructor.

    ", - "body": "

    Values always have to be passed to the constructor to initialize.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", - "ctx": { - "type": "function", - "name": "MongooseBuffer", - "string": "MongooseBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Buffer.

    ", - "summary": "

    Inherit from Buffer.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.prototype = new Buffer(0);", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "prototype", - "value": "new Buffer(0)", - "string": "MongooseBuffer.prototype" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "_parent" - } - ], - "description": { - "full": "

    Parent owner document

    ", - "summary": "

    Parent owner document

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._parent;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Marks this buffer as modified.

    ", - "summary": "

    Marks this buffer as modified.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "_markModified", - "string": "MongooseBuffer.prototype._markModified()" - } - }, - { - "tags": [], - "description": { - "full": "

    Writes the buffer.

    ", - "summary": "

    Writes the buffer.

    ", - "body": "" - }, - "ignore": false, - "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "write", - "string": "MongooseBuffer.prototype.write()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "MongooseBuffer" - ], - "description": "" - }, - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "target", - "description": "" - } - ], - "description": { - "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", - "summary": "

    Copies the buffer.

    ", - "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "copy", - "string": "MongooseBuffer.prototype.copy()" - } - }, - { - "tags": [], - "description": { - "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", - "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", - "body": "" - }, - "ignore": true, - "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://bsonspec.org/#/specification", - "visibility": "http://bsonspec.org/#/specification" - }, - { - "type": "param", - "types": [ - "Hex" - ], - "name": "[subtype]", - "description": "" - }, - { - "type": "return", - "types": [ - "Binary" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", - "summary": "

    Converts this buffer to its Binary type representation.

    ", - "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "toObject", - "string": "MongooseBuffer.prototype.toObject()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "Binary", - "value": "Binary", - "string": "MongooseBuffer.Binary" - } - } -] -### lib/types/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", - "ctx": { - "type": "declaration", - "name": "MongooseArray", - "value": "require('./array')", - "string": "MongooseArray" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to this array" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "MongooseDocumentArray" - ], - "description": "" - }, - { - "type": "inherits", - "string": "MongooseArray" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    DocumentArray constructor

    ", - "summary": "

    DocumentArray constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseDocumentArray", - "string": "MongooseDocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseArray

    ", - "summary": "

    Inherits from MongooseArray

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseDocumentArray", - "name": "__proto__", - "value": "MongooseArray.prototype", - "string": "MongooseDocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Overrides MongooseArray#cast

    ", - "summary": "

    Overrides MongooseArray#cast

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype._cast = function (value) {\n if (value instanceof this._schema.casterConstructor)\n return value;\n\n return new this._schema.casterConstructor(value, this);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "_cast", - "string": "MongooseDocumentArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "EmbeddedDocument", - "null" - ], - "description": "the subdocuent or null if not found." - }, - { - "type": "param", - "types": [ - "ObjectId", - "String", - "Number", - "Buffer" - ], - "name": "id", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Searches array items for the first document with a matching id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", - "summary": "

    Searches array items for the first document with a matching id.

    ", - "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "id", - "string": "MongooseDocumentArray.prototype.id()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", - "summary": "

    Returns a native js Array of plain js objects

    ", - "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "toObject", - "string": "MongooseDocumentArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "inspect", - "string": "MongooseDocumentArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the value to cast to this arrays SubDocument schema" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", - "summary": "

    Creates a subdocument casted to this schema.

    ", - "body": "

    This is the same subdocument constructor used for casting.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "create", - "string": "MongooseDocumentArray.prototype.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Creates a fn that notifies all child docs of event.

    ", - "summary": "

    Creates a fn that notifies all child docs of event.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n if (!self[i]) continue;\n self[i].emit(event, val);\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "notify", - "string": "MongooseDocumentArray.prototype.notify()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseDocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseDocumentArray", - "string": "module.exports" - } - } -] -### lib/types/embedded.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Document = require('../document')\n , inspect = require('util').inspect;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('../document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "js object returned from the db" - }, - { - "type": "param", - "types": [ - "MongooseDocumentArray" - ], - "name": "parentArr", - "description": "the parent array of this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "skipId", - "description": "" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    EmbeddedDocument constructor.

    ", - "summary": "

    EmbeddedDocument constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", - "ctx": { - "type": "function", - "name": "EmbeddedDocument", - "string": "EmbeddedDocument()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Document

    ", - "summary": "

    Inherit from Document

    ", - "body": "" - }, - "ignore": true, - "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "EmbeddedDocument", - "name": "__proto__", - "value": "Document.prototype", - "string": "EmbeddedDocument.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path which changed" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", - "summary": "

    Marks the embedded doc modified.

    ", - "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "markModified", - "string": "EmbeddedDocument.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "return", - "types": [ - "EmbeddedDocument" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", - "summary": "

    Used as a stub for hooks.js

    ", - "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "save", - "string": "EmbeddedDocument.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes the subdocument from its parent array.

    ", - "summary": "

    Removes the subdocument from its parent array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "remove", - "string": "EmbeddedDocument.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Override #update method of parent documents.

    ", - "summary": "

    Override #update method of parent documents.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "update", - "string": "EmbeddedDocument.prototype.update()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "inspect", - "string": "EmbeddedDocument.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "error which states the reason `path` was invalid" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks a path as invalid, causing validation to fail.

    ", - "summary": "

    Marks a path as invalid, causing validation to fail.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "invalidate", - "string": "EmbeddedDocument.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the top level document of this sub-document.

    ", - "summary": "

    Returns the top level document of this sub-document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "ownerDocument", - "string": "EmbeddedDocument.prototype.ownerDocument()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the top level document of this sub-document.

    ", - "summary": "

    Returns the top level document of this sub-document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", - "ctx": { - "type": "function", - "name": "ownerDocument", - "string": "ownerDocument()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns this sub-documents parent document.

    ", - "summary": "

    Returns this sub-documents parent document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parent", - "string": "EmbeddedDocument.prototype.parent()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns this sub-documents parent array.

    ", - "summary": "

    Returns this sub-documents parent array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parentArray", - "string": "EmbeddedDocument.prototype.parentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = EmbeddedDocument;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "EmbeddedDocument", - "string": "module.exports" - } - } -] -### lib/types/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "Array", - "value": "require('./array')", - "string": "exports.Array" - } - } -] -### lib/types/objectid.js -[ - { - "tags": [], - "description": { - "full": "

    Access driver.

    ", - "summary": "

    Access driver.

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [ - { - "type": "constructor", - "string": "ObjectId" - } - ], - "description": { - "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", - "summary": "

    ObjectId type constructor

    ", - "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require(driver + '/objectid')", - "string": "ObjectId" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "str", - "description": "" - }, - { - "type": "static", - "string": "fromString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "ObjectId" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Creates an ObjectId from str

    ", - "summary": "

    Creates an ObjectId from str

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.fromString;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId" - ], - "name": "oid", - "description": "ObjectId instance" - }, - { - "type": "static", - "string": "toString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts oid to a string.

    ", - "summary": "

    Converts oid to a string.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.toString;" - } -] -### lib/utils.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , sliced = require('sliced')\n , MongooseBuffer\n , MongooseArray\n , Document", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "a model name" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "a collection name" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Produces a collection name from model name.

    ", - "summary": "

    Produces a collection name from model name.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "toCollectionName", - "string": "exports.toCollectionName()" - } - }, - { - "tags": [], - "description": { - "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", - "summary": "

    Pluralization rules.

    ", - "body": "

    These rules are applied while processing the argument to toCollectionName.

    " - }, - "ignore": false, - "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "pluralization", - "value": "[", - "string": "exports.pluralization" - } - }, - { - "tags": [], - "description": { - "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", - "summary": "

    Uncountable words.

    ", - "body": "

    These words are applied while processing the argument to toCollectionName.

    " - }, - "ignore": false, - "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news'\n];\nvar uncountables = exports.uncountables;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "uncountables", - "value": "[", - "string": "exports.uncountables" - } - }, - { - "tags": [ - { - "type": "author", - "string": "TJ Holowaychuk (extracted from _ext.js_)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "string", - "description": "to pluralize" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Pluralize function.

    ", - "summary": "

    Pluralize function.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", - "ctx": { - "type": "function", - "name": "pluralize", - "string": "pluralize()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "listener", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Add once to EventEmitter if absent

    ", - "summary": "

    Add once to EventEmitter if absent

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", - "ctx": { - "type": "declaration", - "name": "Events", - "value": "EventEmitter", - "string": "Events" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Events", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Events.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Add once.

    ", - "summary": "

    Add once.

    ", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", - "ctx": { - "type": "method", - "constructor": "Events", - "name": "once", - "string": "Events.prototype.once()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "a", - "description": "a value to compare to `b`" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "b", - "description": "a value to compare to `a`" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", - "summary": "

    Determines if a and b are deep equal.

    ", - "body": "

    Modified from node/lib/assert.js

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "deepEqual", - "string": "exports.deepEqual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the object to clone" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the cloned object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Object clone with Mongoose natives support.

    \n\n

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.

    ", - "summary": "

    Object clone with Mongoose natives support.

    ", - "body": "

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId) {\n return new ObjectId(obj.id);\n }\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "clone", - "string": "exports.clone()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", - "ctx": { - "type": "function", - "name": "cloneObject", - "string": "cloneObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "defaults", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the merged object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Copies and merges options with defaults.

    ", - "summary": "

    Copies and merges options with defaults.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "options", - "string": "exports.options()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Generates a random string

    ", - "summary": "

    Generates a random string

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "random", - "string": "exports.random()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "to", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "from", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Merges from into to without overwriting existing properties.

    ", - "summary": "

    Merges from into to without overwriting existing properties.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n merge(to[key], from[key]);\n }\n }\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "merge", - "string": "exports.merge()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", - "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.args = sliced;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "args", - "value": "sliced", - "string": "exports.args" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", - "summary": "

    process.nextTick helper.

    ", - "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "tick", - "string": "exports.tick()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "v", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", - "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", - "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isMongooseObject", - "string": "exports.isMongooseObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "object", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", - "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expireAfterSeconds = when;\n delete object.expires;\n}\n\nexports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "expires", - "string": "exports.expires()" - } - } -] -### lib/virtualtype.js -[ - { - "tags": [ - { - "type": "parma", - "string": "{Object} options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", - "summary": "

    VirtualType constructor

    ", - "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", - "ctx": { - "type": "function", - "name": "VirtualType", - "string": "VirtualType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", - "summary": "

    Defines a getter.

    ", - "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "get", - "string": "VirtualType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", - "summary": "

    Defines a setter.

    ", - "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "set", - "string": "VirtualType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all getters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Applies getters to value using optional scope.

    ", - "summary": "

    Applies getters to value using optional scope.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applyGetters", - "string": "VirtualType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all setters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Applies setters to value using optional scope.

    ", - "summary": "

    Applies setters to value using optional scope.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applySetters", - "string": "VirtualType.prototype.applySetters()" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = VirtualType;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "VirtualType", - "string": "module.exports" - } - } -] diff --git a/docs/3.2.x/docs/source/api.js b/docs/3.2.x/docs/source/api.js deleted file mode 100644 index 8fd87f0035b..00000000000 --- a/docs/3.2.x/docs/source/api.js +++ /dev/null @@ -1,220 +0,0 @@ -/*! - * Module dependencies - */ - -var fs = require('fs'); -var link = require('../helpers/linktype'); -var hl = require('highlight.js') -var md = require('markdown') - -module.exports = { - docs: [] - , github: 'https://github.com/LearnBoost/mongoose/tree/' - , title: 'API docs' -} - -var out = module.exports.docs; - -var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); -parse(docs); -order(out); - -function parse (docs) { - docs.split(/^### /gm).forEach(function (chunk) { - if (!(chunk = chunk.trim())) return; - - chunk = chunk.split(/^([^\n]+)\n/); - - var title = chunk[1]; - - if (!title || !(title = title.trim())) - throw new Error('missing title'); - - title = title.replace(/^lib\//, ''); - - var json = JSON.parse(chunk[2]); - - var props = []; - var methods = []; - var statics = []; - var constructor = null; - - json.forEach(function (comment) { - if (comment.description) - highlight(comment.description); - - var prop = false; - comment.params = []; - comment.see = []; - - var i = comment.tags.length; - while (i--) { - var tag = comment.tags[i]; - switch (tag.type) { - case 'property': - prop = true; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - props.unshift(comment); - break; - case 'method': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'method'; - comment.code = ''; - break; - case 'memberOf': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.constructor = tag.parent; - break; - case 'static': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - comment.ctx.type = 'method'; - break; - case 'receiver': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.receiver = tag.string; - break; - case 'constructor': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'function'; - comment.code = ''; - break; - case 'inherits': - if (/http/.test(tag.string)) { - var result = tag.string.split(' '); - var href = result.pop(); - var title = result.join(' '); - comment.inherits = '' + title + ''; - } else { - comment.inherits = link(tag.string); - } - comment.tags.splice(i, 1); - break; - case 'param': - comment.params.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'return': - comment.return = tag; - comment.tags.splice(i, 1); - break; - case 'see': - if (tag.local) { - var parts = tag.local.split(' '); - if (1 === parts.length) { - tag.url = link.type(parts[0]); - tag.title = parts[0]; - } else { - tag.url = parts.pop(); - tag.title = parts.join(' '); - } - } - comment.see.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'event': - var str = tag.string.replace(/\\n/g, '\n'); - tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); - comment.events || (comment.events = []); - comment.events.unshift(tag); - comment.tags.splice(i, 1); - } - } - - if (!prop) { - methods.push(comment); - } - }); - - methods = methods.filter(ignored); - props = props.filter(ignored); - - function ignored (method) { - if (method.ignore) return false; - return true; - } - - if (0 === methods.length + props.length) return; - - // add constructor to properties too - methods.some(function (method) { - if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { - props.forEach(function (prop) { - prop.ctx.constructor = method.ctx.constructor; - }); - return true; - } - return false; - }); - - var len = methods.length; - while (len--) { - method = methods[len]; - if (method.ctx && method.ctx.receiver) { - var stat = methods.splice(len, 1)[0]; - statics.unshift(stat); - } - } - - out.push({ - title: title - , methods: methods - , props: props - , statics: statics - , hasPublic: hasPublic(methods, props, statics) - }); - }); -} - -function hasPublic () { - for (var i = 0; i < arguments.length; ++i) { - var arr = arguments[i]; - for (var j = 0; j < arr.length; ++j) { - var item = arr[j]; - if (!item.ignore && !item.isPrivate) return true; - } - } - return false; -} - -// add "class='language'" to our
     elements
    -function highlight (o) {
    -  o.full = fix(o.full);
    -  o.summary = fix(o.summary);
    -  o.body = fix(o.body);
    -}
    -
    -function fix (str) {
    -  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    -
    -    // parse out the ```language
    -    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    -
    -    if ('js' == code[1] || !code[1]) {
    -      code[1] = 'javascript';
    -    }
    -
    -    return $1
    -          + hl.highlight(code[1], code[2]).value.trim()
    -          + $3;
    -  });
    -}
    -
    -function order (docs) {
    -  // want index first
    -  for (var i = 0; i < docs.length; ++i) {
    -    if ('index.js' == docs[i].title) {
    -      docs.unshift(docs.splice(i, 1)[0]);
    -    }
    -  }
    -}
    diff --git a/docs/3.2.x/docs/source/home.js b/docs/3.2.x/docs/source/home.js
    deleted file mode 100644
    index 557f27b966b..00000000000
    --- a/docs/3.2.x/docs/source/home.js
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -
    -var fs = require('fs')
    -var package = require('./../../package.json')
    -var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    -
    -var imgs = [];
    -
    -images.forEach(function (line) {
    -  line = line.trim();
    -  if (!line) return;
    -  line = line.split('|');
    -  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    -});
    -
    -module.exports = {
    -    package: package
    -  , images: imgs
    -  , title: 'ODM'
    -}
    diff --git a/docs/3.2.x/docs/source/index.js b/docs/3.2.x/docs/source/index.js
    deleted file mode 100644
    index 7eaf8a85b18..00000000000
    --- a/docs/3.2.x/docs/source/index.js
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -
    -exports['index.jade'] = require('./home')
    -exports['docs/api.jade'] = require('./api')
    -exports['docs/index.jade'] = { title: 'Getting Started' }
    -exports['docs/prior.jade'] = require('./prior')
    -exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    -exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    -exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    -exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    -exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    -exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    -exports['docs/models.jade'] = { guide: true, title: 'Models' }
    -exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    -exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    -exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    -exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    -exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    -exports['docs/connections.jade'] = { guide: true, title: 'Connecting to MongoDB' }
    -exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.2.x/docs/source/prior.js b/docs/3.2.x/docs/source/prior.js
    deleted file mode 100644
    index 2e03811d215..00000000000
    --- a/docs/3.2.x/docs/source/prior.js
    +++ /dev/null
    @@ -1,13 +0,0 @@
    -var fs = require('fs')
    -var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    -releases = releases.split('\n').filter(Boolean);
    -
    -module.exports = exports = {
    -    title: ''
    -  , releases: releases.map(function (version) {
    -      return {
    -          url: version + '/'
    -        , version: version
    -      }
    -    })
    -}
    diff --git a/docs/3.2.x/docs/subdocs.html b/docs/3.2.x/docs/subdocs.html
    deleted file mode 100644
    index 7535ca7272f..00000000000
    --- a/docs/3.2.x/docs/subdocs.html
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -Mongoose SubDocuments v3.2.2Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    -
    -var parentSchema = new Schema({
    -  children: [childSchema]
    -})
    -

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = db.model('Parent', parentSchema);
    -var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    -parent.children[0].name = 'Matthew';
    -parent.save(callback);
    -

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    -  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    -  next();
    -});
    -
    -var parent = new Parent({ children: [{ name: 'invalid' }] });
    -parent.save(function (err) {
    -  console.log(err.message) // #sadpanda
    -})
    -

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    -

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = db.model('Parent');
    -var parent = new Parent;
    -
    -// create a comment
    -post.children.push({ name: 'Liesl' });
    -var doc = post.children[0];
    -console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    -doc.isNew; // true
    -
    -post.save(function (err) {
    -  if (err) return handleError(err)
    -  console.log('Success!');
    -});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    -

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    -parent.save(function (err) {
    -  if (err) return handleError(err);
    -  console.log('the sub-doc was removed')
    -});
    -

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    -  children: [{ name: 'string' }]
    -})
    -

    Next Up

    Now that we've covered Sub-documents, let's take a look at querying.

    diff --git a/docs/3.2.x/docs/subdocs.jade b/docs/3.2.x/docs/subdocs.jade deleted file mode 100644 index 9e568e3ab74..00000000000 --- a/docs/3.2.x/docs/subdocs.jade +++ /dev/null @@ -1,84 +0,0 @@ -extends layout - -block content - h2 Sub Docs - :markdown - [Sub-documents](./api.html#types-embedded-js) are docs with schemas of their own which are elements of a parents document array: - :js - var childSchema = new Schema({ name: 'string' }); - - var parentSchema = new Schema({ - children: [childSchema] - }) - - :markdown - Sub-documents enjoy all the same features as normal [documents](./api.html#document-js). The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved. - :js - var Parent = db.model('Parent', parentSchema); - var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) - parent.children[0].name = 'Matthew'; - parent.save(callback); - - :markdown - If an error occurs in a sub-documents' middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap! - - :js - childSchema.pre('save', function (next) { - if ('invalid' == this.name) return next(new Error('#sadpanda')); - next(); - }); - - var parent = new Parent({ children: [{ name: 'invalid' }] }); - parent.save(function (err) { - console.log(err.message) // #sadpanda - }) - - h3 Finding a sub-document - :markdown - Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. - :js - var doc = parent.children.id(id); - - h3 Adding sub-docs - :markdown - MongooseArray methods such as [push](./api.html#types_array_MongooseArray-push), [unshift](./api.html#types_array_MongooseArray-unshift), [addToSet](./api.html#types_array_MongooseArray-addToSet), and others cast arguments to their proper types transparently: - :js - var Parent = db.model('Parent'); - var parent = new Parent; - - // create a comment - post.children.push({ name: 'Liesl' }); - var doc = post.children[0]; - console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' } - doc.isNew; // true - - post.save(function (err) { - if (err) return handleError(err) - console.log('Success!'); - }); - :markdown - Sub-docs may also be created without adding them to the array by using the [create](./api.html#types_documentarray_MongooseDocumentArray-create) method of MongooseArrays. - :js - var newdoc = post.children.create({ name: 'Aaron' }); - - h3 Removing docs - :markdown - Each sub-document has it's own [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. - :js - var doc = parent.children.id(id).remove(); - parent.save(function (err) { - if (err) return handleError(err); - console.log('the sub-doc was removed') - }); - - h4#altsyntax Alternate declaration syntax - :markdown - _New in v3_ If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal: - :js - var parentSchema = new Schema({ - children: [{ name: 'string' }] - }) - - h3#next Next Up - :markdown - Now that we've covered `Sub-documents`, let's take a look at [querying](/docs/queries.html). diff --git a/docs/3.2.x/docs/validation.html b/docs/3.2.x/docs/validation.html deleted file mode 100644 index 5ca01b7fb7e..00000000000 --- a/docs/3.2.x/docs/validation.html +++ /dev/null @@ -1,37 +0,0 @@ -Mongoose Validation v3.2.2Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    - -
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    - -

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    -  color: String,
    -  name: String
    -});
    -
    -var Toy = db.model('Toy', toySchema);
    -
    -Toy.schema.path('color').validate(function (value) {
    -  return /blue|green|white|red|orange|periwinkel/i.test(value);
    -}, 'Invalid color');
    -
    -var toy = new Toy({ color: 'grease'});
    -
    -toy.save(function (err) {
    -  // err.errors.color is a ValidatorError object
    -  
    -  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    -  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    -  console.log(err.errors.color.type) // prints "Invalid color"
    -  console.log(err.errors.color.path) // prints "color"
    -  console.log(err.name) // prints "ValidationError"
    -  console.log(err.message) // prints "Validation failed"
    -});
    -

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    -

    Next Up

    Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

    diff --git a/docs/3.2.x/docs/validation.jade b/docs/3.2.x/docs/validation.jade deleted file mode 100644 index 5b267bf95a5..00000000000 --- a/docs/3.2.x/docs/validation.jade +++ /dev/null @@ -1,58 +0,0 @@ -extends layout - -block content - h2 Validation - :markdown - Before we get into the specifics of validation syntax, please keep the following rules in mind: - - - Validation is defined in the [SchemaType](./schematypes.html) - - Validation is an internal piece of [middleware](./middleware.html) - - Validation occurs when a document attempts to be [saved](./api.html#model_Model-save), after defaults have been applied - - Validation is asynchronously recursive: when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed. If an error happens, your Model#save callback receives it - - Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, `"min"` is the identifier for the error triggered when a number doesn't meet the [minimum value](./api.html#schema_number_SchemaNumber-min). The path and value that triggered the error can be accessed in the `ValidationError` object - h3 Built in validators - :markdown - Mongoose has several built in validators. - - - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. - - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. - - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum) and [match](./api.html#schema_string_SchemaString-match) validators. - h3 Custom validators - :markdown - Custom validation is declared by passing a validation `function` and an error type to your `SchemaType`s validate method. Read the [API](./api.html#schematype_SchemaType-validate) docs for details on custom validators, async validators, and more. - h3 Validation errors - :markdown - Errors returned after failed validation contain an `errors` object holding the actual `ValidatorErrors`. Each [ValidatorError](./api.html#errors-validation-js) has a `type` and `path` property providing us with a little more error handling flexibility. - :js - var toySchema = new Schema({ - color: String, - name: String - }); - - var Toy = db.model('Toy', toySchema); - - Toy.schema.path('color').validate(function (value) { - return /blue|green|white|red|orange|periwinkel/i.test(value); - }, 'Invalid color'); - - var toy = new Toy({ color: 'grease'}); - - toy.save(function (err) { - // err.errors.color is a ValidatorError object - - console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color' - console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color' - console.log(err.errors.color.type) // prints "Invalid color" - console.log(err.errors.color.path) // prints "color" - console.log(err.name) // prints "ValidationError" - console.log(err.message) // prints "Validation failed" - }); - - :markdown - After a validation error, the document will also have the same `errors` property available: - :js - toy.errors.color.message === err.errors.color.message - - h3#next Next Up - :markdown - Now that we've covered `validation`, let's take a look at how you might handle advanced validation with Mongoose's [middleware](/docs/middleware.html). diff --git a/docs/3.2.x/index.html b/docs/3.2.x/index.html deleted file mode 100644 index 3568a23d128..00000000000 --- a/docs/3.2.x/index.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose ODM v3.2.2Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

    var mongoose = require('mongoose');
    -var db = mongoose.createConnection('localhost', 'test');
    -
    -var schema = mongoose.Schema({ name: 'string' });
    -var Cat = db.model('Cat', schema);
    -
    -var kitty = new Cat({ name: 'Zildjian' });
    -kitty.save(function (err) {
    -  if (err) // ...
    -  res.end('meow');
    -});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    Production - (add your project)

    • LearnBoost is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students.
    • Storify lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative.
    • ClickDummy is a rapid mockup prototyping application for designers and dummies.
    • Scotty App allows you to create data driven backends for your apps in minutes instead of weeks.
    • Geeklist is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found.
    • Bozuko is an exciting customer rewards program.
    • Call List helps you maintain a todo list for people you need to call.
    • Grow The Game Golf lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more.
    • nextdays lets you share plans with friends and discover what is happening around you.
    • AtticTV is Music Television (MTV) for the web.
    • LocalResponse helps marketers respond to real-time consumer intent.
    • Select Vids is a collection of amazing, funny, and creative videos for you to discover.
    • cldfy delivers mail to your app.
    • ShareLatex is a real-time LaTeX collaboration tool.
    • Cyborg Vision uses real-time facial recognition to identify your friends and show their information.
    • Wavo lets you express yourself through the songs you love.
    • seelio is a stage for college students to distinguish themselves and connect with companies.
    • TodayLaunch is a free dashboard for your social media accounts.
    • Stachify
    • Skim is a playful way to meet new people.
    • NuORDER online fashion wholesale for brands and buyers.
    • UPcload helps you find clothes that fit you when shopping online.
    • TreinoSmart is a system for gym and physical trainers.
    • ShoeJitsu let's you shop, compare, and share fashion.
    • Kyyti is a meeting place for rides.
    • Nimble Quiz allows you to quickly create and manage simple multiple choice quizzes.
    • Fur Baby Rescue provides a temporary, safe home for cats, dogs, puppies and kittens.
    diff --git a/docs/3.2.x/static.js b/docs/3.2.x/static.js deleted file mode 100644 index fc0e722dd4e..00000000000 --- a/docs/3.2.x/static.js +++ /dev/null @@ -1,17 +0,0 @@ - -var static = require('node-static'); -var server = new static.Server('.', { cache: 0 }); - -require('http').createServer(function (req, res) { - req.on('end', function () { - server.serve(req, res, function (err) { - if (err) { - console.error(err, req.url); - res.writeHead(err.status, err.headers); - res.end(); - } - }); - }); -}).listen(8088); - -console.error('now listening on localhost:8088'); diff --git a/docs/3.3.x/docs/api.html b/docs/3.3.x/docs/api.html deleted file mode 100644 index 0f55a1ecbd8..00000000000 --- a/docs/3.3.x/docs/api.html +++ /dev/null @@ -1,6883 +0,0 @@ -Mongoose API v3.3.1Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      -  this.connections = [];
      -  this.plugins = [];
      -  this.models = {};
      -  this.modelSchemas = {};
      -  this.options = {};
      -  this.createConnection(); // default connection
      -};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      -  if (arguments.length == 1)
      -    return this.options[key];
      -  this.options[key] = value;
      -  return this;
      -};

      Parameters:

      Example:

      - -
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      - -
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri], [options])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      -  var conn = new Connection(this);
      -  this.connections.push(conn);
      -
      -  if (arguments.length) {
      -    if (rgxReplSet.test(arguments[0])) {
      -      conn.openSet.apply(conn, arguments);
      -    } else {
      -      conn.open.apply(conn, arguments);
      -    }
      -  }
      -
      -  return conn;
      -};

      Parameters:

      • [uri] <String> a mongodb:// URI
      • [options] <Object> options to pass to the driver

      Returns:

      Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

      - -

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

      - -

      Example:

      - -
      // with mongodb:// URI
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
      -
      -// and options
      -var opts = { db: { native_parser: true }}
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
      -
      -// replica sets
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
      -
      -// and options
      -var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
      -
      -// with [host, database_name[, port] signature
      -db = mongoose.createConnection('localhost', 'database', port)
      -
      -// and options
      -var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
      -db = mongoose.createConnection('localhost', 'database', port, opts)
      -
      -// initialize now, connect later
      -db = mongoose.createConnection();
      -db.open('localhost', 'database', port, [opts]);

      Mongoose#connect()

      Opens the default mongoose connection.

      show code
      Mongoose.prototype.connect = function () {
      -  var conn = this.connection;
      -
      -  if (rgxReplSet.test(arguments[0])) {
      -    conn.openSet.apply(conn, arguments);
      -  } else {
      -    conn.open.apply(conn, arguments);
      -  }
      -
      -  return this;
      -};

      Returns:

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


      Mongoose#disconnect([fn])

      Disconnects all connections.

      show code
      Mongoose.prototype.disconnect = function (fn) {
      -  var count = this.connections.length
      -    , error
      -
      -  this.connections.forEach(function(conn){
      -    conn.close(function(err){
      -      if (error) return;
      -
      -      if (err) {
      -        error = err;
      -        if (fn) return fn(err);
      -        throw err;
      -      }
      -
      -      if (fn)
      -        --count || fn();
      -    });
      -  });
      -  return this;
      -};

      Parameters:

      • [fn] <Function> called after all connection close.

      Returns:


      Mongoose#model(name, [schema], [collection], [skipInit])

      Defines a model or retrieves it.

      show code
      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
      -  // normalize collection
      -  if (!(schema instanceof Schema)) {
      -    collection = schema;
      -    schema = false;
      -  }
      -
      -  if ('boolean' === typeof collection) {
      -    skipInit = collection;
      -    collection = null;
      -  }
      -
      -  // look up models for the collection
      -  if (!this.modelSchemas[name]) {
      -    if (!schema && name in SchemaDefaults) {
      -      schema = SchemaDefaults[name];
      -    }
      -
      -    if (schema) {
      -      this.modelSchemas[name] = schema;
      -      for (var i = 0, l = this.plugins.length; i < l; i++) {
      -        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
      -      }
      -    } else {
      -      throw new Error('Schema hasn\'t been registered for model "' + name + '".
      -'
      -                    + 'Use mongoose.model(name, schema)');
      -    }
      -  }
      -
      -  if (!this.models[name]) {
      -    schema || (schema = this.modelSchemas[name]);
      -    collection || (collection = schema.set('collection') || format(name));
      -
      -    var model = Model.compile(name
      -                        , this.modelSchemas[name]
      -                        , collection
      -                        , this.connection
      -                        , this);
      -
      -    if (!skipInit) model.init();
      -
      -    this.models[name] = model;
      -  }
      -
      -  return this.models[name];
      -};

      Parameters:

      • name <String> model name
      • [schema] <Schema>
      • [collection] <String> name (optional, induced from model name)
      • [skipInit] <Boolean> whether to skip initialization (defaults to false)

      Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -
      -// define an Actor model with this mongoose instance
      -mongoose.model('Actor', new Schema({ name: String }));
      -
      -// create a new connection
      -var conn = mongoose.createConnection(..);
      -
      -// retrieve the Actor model
      -var Actor = conn.model('Actor');
      - -

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

      - -

      Example:

      - -
      var schema = new Schema({ name: String });
      -schema.set('collection', 'actor');

      Mongoose#plugin(fn, [opts])

      Declares a global plugin executed on all Schemas.

      show code
      Mongoose.prototype.plugin = function (fn, opts) {
      -  this.plugins.push([fn, opts]);
      -  return this;
      -};

      Parameters:

      Returns:

      Equivalent to calling .plugin(fn) on each Schema you create.


      module.exports

      The exports object is an instance of Mongoose.

      show code
      module.exports = exports = new Mongoose;
      -var mongoose = module.exports;

      mongoose.Collection

      The Mongoose Collection constructor

      show code
      mongoose.Collection = Collection;

      mongoose.Connection

      The Mongoose Connection constructor

      show code
      mongoose.Connection = Connection;

      mongoose.version

      Mongoose version

      show code
      mongoose.version = JSON.parse(
      -  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      -).version;

      mongoose.Mongoose

      The Mongoose constructor

      show code
      mongoose.Mongoose = Mongoose;

      The exports of the mongoose module is an instance of this class.

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -var mongoose2 = new mongoose.Mongoose();

      mongoose.Schema

      The Mongoose Schema constructor

      show code
      mongoose.Schema = Schema;

      Example:

      - -
      var mongoose = require('mongoose');
      -var Schema = mongoose.Schema;
      -var CatSchema = new Schema(..);

      mongoose.SchemaType

      The Mongoose SchemaType constructor.

      show code
      mongoose.SchemaType = SchemaType;

      mongoose.SchemaTypes

      The various Mongoose SchemaTypes.

      show code
      mongoose.SchemaTypes = Schema.Types;

      Note:

      - -

      Alias of mongoose.Schema.Types for backwards compatibility.


      mongoose.VirtualType

      The Mongoose VirtualType constructor.

      show code
      mongoose.VirtualType = VirtualType;

      mongoose.Types

      The various Mongoose Types.

      show code
      mongoose.Types = Types;

      Example:

      - -
      var mongoose = require('mongoose');
      -var array = mongoose.Types.Array;
      - -

      Types:

      - -
        -
      • Array
      • -
      • Buffer
      • -
      • Document
      • -
      • Embedded
      • -
      • DocumentArray
      • -
      • ObjectId
      • -
      - -

      Using this exposed access to the ObjectId type, we can construct ids on demand.

      - -
      var ObjectId = mongoose.Types.ObjectId;
      -var id1 = new ObjectId;

      mongoose.Query

      The Mongoose Query constructor.

      show code
      mongoose.Query = Query;

      mongoose.Promise

      The Mongoose Promise constructor.

      show code
      mongoose.Promise = Promise;

      mongoose.Model

      The Mongoose Model constructor.

      show code
      mongoose.Model = Model;

      mongoose.Document

      The Mongoose Document constructor.

      show code
      mongoose.Document = Document;

      mongoose.Error

      The MongooseError constructor.

      show code
      mongoose.Error = require('./error');

      mongoose.mongo

      The node-mongodb-native driver Mongoose uses.

      show code
      mongoose.mongo = require('mongodb');

      Mongoose#connection

      The default connection of the mongoose module.

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -mongoose.connect(...);
      -mongoose.connection.on('error', cb);
      - -

      This is the connection used by default for every model created using mongoose.model.

      Returns:


    • collection.js

      Collection(name, conn, opts)

      Abstract Collection constructor

      show code
      function Collection (name, conn, opts) {
      -  this.name = name;
      -  this.conn = conn;
      -  this.buffer = true;
      -  this.queue = [];
      -
      -  if ('number' == typeof opts) opts = { size: opts };
      -  this.opts = opts || {};
      -
      -  if (STATES.connected == this.conn.readyState) {
      -    this.onOpen();
      -  }
      -};

      Parameters:

      • name <String> name of the collection
      • conn <Connection> A MongooseConnection instance
      • opts <Object> optional collection options

      This is the base class that drivers inherit from and implement.


      Collection#onOpen()

      Called when the database connects

      show code
      Collection.prototype.onOpen = function () {
      -  var self = this;
      -  this.buffer = false;
      -  self.doQueue();
      -};

      Collection#onClose()

      Called when the database disconnects

      show code
      Collection.prototype.onClose = function () {
      -  this.buffer = true;
      -};

      Collection#addQueue(name, args)

      Queues a method for later execution when its
      database connection opens.

      show code
      Collection.prototype.addQueue = function (name, args) {
      -  this.queue.push([name, args]);
      -  return this;
      -};

      Parameters:

      • name <String> name of the method to queue
      • args <Array> arguments to pass to the method when executed

      Collection#doQueue()

      Executes all queued methods and clears the queue.

      show code
      Collection.prototype.doQueue = function () {
      -  for (var i = 0, l = this.queue.length; i < l; i++){
      -    this[this.queue[i][0]].apply(this, this.queue[i][1]);
      -  }
      -  this.queue = [];
      -  return this;
      -};

      Collection#ensureIndex()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.ensureIndex = function(){
      -  throw new Error('Collection#ensureIndex unimplemented by driver');
      -};

      Collection#findAndModify()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findAndModify = function(){
      -  throw new Error('Collection#findAndModify unimplemented by driver');
      -};

      Collection#findOne()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findOne = function(){
      -  throw new Error('Collection#findOne unimplemented by driver');
      -};

      Collection#find()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.find = function(){
      -  throw new Error('Collection#find unimplemented by driver');
      -};

      Collection#insert()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.insert = function(){
      -  throw new Error('Collection#insert unimplemented by driver');
      -};

      Collection#save()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.save = function(){
      -  throw new Error('Collection#save unimplemented by driver');
      -};

      Collection#update()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.update = function(){
      -  throw new Error('Collection#update unimplemented by driver');
      -};

      Collection#getIndexes()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.getIndexes = function(){
      -  throw new Error('Collection#getIndexes unimplemented by driver');
      -};

      Collection#mapReduce()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.mapReduce = function(){
      -  throw new Error('Collection#mapReduce unimplemented by driver');
      -};

      Collection#conn

      The Connection instance


      Collection#name

      The collection name


    • connection.js

      Connection(base)

      Connection constructor

      show code
      function Connection (base) {
      -  this.base = base;
      -  this.collections = {};
      -  this.models = {};
      -  this.replica = false;
      -  this.host = null;
      -  this.port = null;
      -  this.user = null;
      -  this.pass = null;
      -  this.name = null;
      -  this.options = null;
      -  this._readyState = STATES.disconnected;
      -  this._closeCalled = false;
      -  this._hasOpened = false;
      -};

      Parameters:

      Events:

      • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

      • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

      • open: Emitted after we connected and onOpen is executed on all of this connections models.

      • disconnecting: Emitted when connection.close() was executed.

      • disconnected: Emitted after getting disconnected from the db.

      • close: Emitted after we disconnected and onClose executed on all of this connections models.

      • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

      • error: Emitted when an error occurs on this connection.

      • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

      For practical reasons, a Connection equals a Db.


      Connection#open(connection_string, [database], [port], [options], [callback])

      Opens the connection to MongoDB.

      show code
      Connection.prototype.open = function (host, database, port, options, callback) {
      -  var self = this
      -    , uri;
      -
      -  if ('string' === typeof database) {
      -    switch (arguments.length) {
      -      case 2:
      -        port = 27017;
      -      case 3:
      -        switch (typeof port) {
      -          case 'function':
      -            callback = port, port = 27017;
      -            break;
      -          case 'object':
      -            options = port, port = 27017;
      -            break;
      -        }
      -        break;
      -      case 4:
      -        if ('function' === typeof options)
      -          callback = options, options = {};
      -    }
      -  } else {
      -    switch (typeof database) {
      -      case 'function':
      -        callback = database, database = undefined;
      -        break;
      -      case 'object':
      -        options = database;
      -        database = undefined;
      -        callback = port;
      -        break;
      -    }
      -
      -    if (!rgxProtocol.test(host)) {
      -      host = 'mongodb://' + host;
      -    }
      -
      -    uri = url.parse(host);
      -    host = uri.hostname;
      -    port = uri.port || 27017;
      -    database = uri.pathname && uri.pathname.replace(/\//g, '');
      -  }
      -
      -  this.options = this.defaultOptions(options);
      -
      -  // make sure we can open
      -  if (STATES.disconnected !== this.readyState) {
      -    var err = new Error('Trying to open unclosed connection.');
      -    err.state = this.readyState;
      -    this.error(err, callback);
      -    return this;
      -  }
      -
      -  if (!host) {
      -    this.error(new Error('Missing hostname.'), callback);
      -    return this;
      -  }
      -
      -  if (!database) {
      -    this.error(new Error('Missing database name.'), callback);
      -    return this;
      -  }
      -
      -  // handle authentication
      -  if (uri && uri.auth) {
      -    var auth = uri.auth.split(':');
      -    this.user = auth[0];
      -    this.pass = auth[1];
      -
      -  // Check hostname for user/pass
      -  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
      -    host = host.split('@');
      -    var auth = host.shift().split(':');
      -    host = host.pop();
      -    this.user = auth[0];
      -    this.pass = auth[1];
      -
      -  // user/pass options
      -  } else if (options && options.user && options.pass) {
      -    this.user = options.user;
      -    this.pass = options.pass;
      -
      -  } else {
      -    this.user = this.pass = undefined;
      -  }
      -
      -  this.name = database;
      -  this.host = host;
      -  this.port = port;
      -
      -  this._open(callback);
      -  return this;
      -};

      Parameters:

      • connection_string <String> mongodb://uri or the host to which you are connecting
      • [database] <String> database name
      • [port] <Number> database port
      • [options] <Object> options
      • [callback] <Function>

      options is a hash with the following possible properties:

      - -
      db      - passed to the connection db instance
      -server  - passed to the connection server instance(s)
      -replset - passed to the connection ReplSet instance
      -user    - username for authentication
      -pass    - password for authentication
      - -

      Notes:

      - -

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.


      Connection#openSet(uris, [database], [options], [callback])

      Connects to a replica set.

      show code
      Connection.prototype.openSet = function (uris, database, options, callback) {
      -  var uris = uris.split(',')
      -    , self = this;
      -
      -  switch (arguments.length) {
      -    case 3:
      -      switch (typeof database) {
      -        case 'string':
      -          this.name = database;
      -          break;
      -        case 'object':
      -          callback = options;
      -          options = database;
      -          database = null;
      -          break;
      -      }
      -
      -      if ('function' === typeof options) {
      -        callback = options;
      -        options = {};
      -      }
      -      break;
      -    case 2:
      -      switch (typeof database) {
      -        case 'string':
      -          this.name = database;
      -          break;
      -        case 'function':
      -          callback = database, database = null;
      -          break;
      -        case 'object':
      -          options = database, database = null;
      -          break;
      -      }
      -  }
      -
      -  this.options = options = this.defaultOptions(options);
      -
      -  if (uris.length < 2) {
      -    this.error(new Error('Please provide comma-separated URIs'), callback);
      -    return this;
      -  }
      -
      -  this.replica = true;
      -  this.host = [];
      -  this.port = [];
      -
      -  uris.forEach(function (uri) {
      -    // handle missing protocols
      -    if (!rgxProtocol.test(uri))
      -      uri = 'mongodb://' + uri;
      -
      -    var uri = url.parse(uri);
      -
      -    self.host.push(uri.hostname);
      -    self.port.push(uri.port || 27017);
      -
      -    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
      -      self.name = uri.pathname.replace(/\//g, '');
      -
      -    if (!self.user && uri.auth) {
      -      var auth = uri.auth.split(':');
      -      self.user = auth[0];
      -      self.pass = auth[1];
      -    }
      -  });
      -
      -  if (!this.name) {
      -    this.error(new Error('No database name provided for replica set'), callback);
      -    return this;
      -  }
      -
      -  this._open(callback);
      -  return this;
      -};

      Parameters:

      • uris <String> comma-separated mongodb:// `URI`s
      • [database] <String> database name if not included in `uris`
      • [options] <Object> passed to the internal driver
      • [callback] <Function>

      Example:

      - -
      var db = mongoose.createConnection();
      -db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
      - -

      The database name and/or auth need only be included in one URI.
      The options is a hash which is passed to the internal driver connection object.

      - -

      Valid options

      - -
      db      - passed to the connection db instance
      -server  - passed to the connection server instance(s)
      -replset - passed to the connection ReplSetServer instance
      -user    - username for authentication
      -pass    - password for authentication

      Connection#error(err, callback)

      error

      show code
      Connection.prototype.error = function (err, callback) {
      -  if (callback) return callback(err);
      -  this.emit('error', err);
      -}

      Parameters:

      Graceful error handling, passes error to callback
      if available, else emits error on the connection.


      Connection#_open(callback)

      Handles opening the connection with the appropriate method based on connection type.

      show code
      Connection.prototype._open = function (callback) {
      -  this.readyState = STATES.connecting;
      -  this._closeCalled = false;
      -
      -  var self = this;
      -
      -  var method = this.replica
      -    ? 'doOpenSet'
      -    : 'doOpen';
      -
      -  // open connection
      -  this[method](function (err) {
      -    if (err) {
      -      self.readyState = STATES.disconnected;
      -      if (self._hasOpened) {
      -        if (callback) callback(err);
      -      } else {
      -        self.error(err, callback);
      -      }
      -      return;
      -    }
      -
      -    self.onOpen();
      -    callback && callback();
      -  });
      -}

      Parameters:


      Connection#onOpen()

      Called when the connection is opened

      show code
      Connection.prototype.onOpen = function () {
      -  var self = this;
      -
      -  function open () {
      -    self.readyState = STATES.connected;
      -
      -    // avoid having the collection subscribe to our event emitter
      -    // to prevent 0.3 warning
      -    for (var i in self.collections)
      -      self.collections[i].onOpen();
      -
      -    self.emit('open');
      -  };
      -
      -  // re-authenticate
      -  if (self.user && self.pass)
      -    self.db.authenticate(self.user, self.pass, open);
      -  else
      -    open();
      -};

      Connection#close([callback])

      Closes the connection

      show code
      Connection.prototype.close = function (callback) {
      -  var self = this;
      -  this._closeCalled = true;
      -
      -  switch (this.readyState){
      -    case 0: // disconnected
      -      callback && callback();
      -      break;
      -
      -    case 1: // connected
      -      this.readyState = STATES.disconnecting;
      -      this.doClose(function(err){
      -        if (err){
      -          self.error(err, callback);
      -        } else {
      -          self.onClose();
      -          callback && callback();
      -        }
      -      });
      -      break;
      -
      -    case 2: // connecting
      -      this.once('open', function(){
      -        self.close(callback);
      -      });
      -      break;
      -
      -    case 3: // disconnecting
      -      if (!callback) break;
      -      this.once('close', function () {
      -        callback();
      -      });
      -      break;
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Connection#onClose()

      Called when the connection closes

      show code
      Connection.prototype.onClose = function () {
      -  this.readyState = STATES.disconnected;
      -
      -  // avoid having the collection subscribe to our event emitter
      -  // to prevent 0.3 warning
      -  for (var i in this.collections)
      -    this.collections[i].onClose();
      -
      -  this.emit('close');
      -};

      Connection#collection(name, [options])

      Retrieves a collection, creating it if not cached.

      show code
      Connection.prototype.collection = function (name, options) {
      -  if (!(name in this.collections))
      -    this.collections[name] = new Collection(name, this, options);
      -  return this.collections[name];
      -};

      Parameters:

      • name <String> of the collection
      • [options] <Object> optional collection options

      Returns:


      Connection#model(name, [schema], [collection])

      Defines or retrieves a model.

      show code
      Connection.prototype.model = function (name, schema, collection) {
      -  if (!this.models[name]) {
      -    var model = this.base.model(name, schema, collection, true)
      -      , Model
      -
      -    if (this != model.prototype.db) {
      -      // subclass model using this connection and collection name
      -      Model = function Model (doc, fields, skipId) {
      -        if (!(this instanceof Model))
      -          return new Model(doc, fields, skipId);
      -        model.call(this, doc, fields, skipId);
      -      };
      -
      -      Model.__proto__ = model;
      -      Model.prototype.__proto__ = model.prototype;
      -      Model.db = Model.prototype.db = this;
      -
      -      // collection name discovery
      -      if ('string' === typeof schema) {
      -        collection = schema;
      -      }
      -
      -      if (!collection) {
      -        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
      -      }
      -
      -      var s = 'string' != typeof schema
      -        ? schema
      -        : model.prototype.schema;
      -
      -      Model.prototype.collection = this.collection(collection, s && s.options.capped);
      -      Model.collection = Model.prototype.collection;
      -      Model.init();
      -    }
      -
      -    this.models[name] = Model || model;
      -  }
      -
      -  return this.models[name];
      -};

      Parameters:

      • name <String> the model name
      • [schema] <Schema> a schema. necessary when defining a model
      • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

      Returns:

      • <Model> The compiled model
      var mongoose = require('mongoose');
      -var db = mongoose.createConnection(..);
      -db.model('Venue', new Schema(..));
      -var Ticket = db.model('Ticket', new Schema(..));
      -var Venue = db.model('Venue');

      Connection#setProfiling(level, [ms], callback)

      Set profiling level.

      show code
      Connection.prototype.setProfiling = function (level, ms, callback) {
      -  if (STATES.connected !== this.readyState) {
      -    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
      -  }
      -
      -  if (!callback) callback = ms, ms = 100;
      -
      -  var cmd = {};
      -
      -  switch (level) {
      -    case 0:
      -    case 'off':
      -      cmd.profile = 0;
      -      break;
      -    case 1:
      -    case 'slow':
      -      cmd.profile = 1;
      -      if ('number' !== typeof ms) {
      -        ms = parseInt(ms, 10);
      -        if (isNaN(ms)) ms = 100;
      -      }
      -      cmd.slowms = ms;
      -      break;
      -    case 2:
      -    case 'all':
      -      cmd.profile = 2;
      -      break;
      -    default:
      -      return callback(new Error('Invalid profiling level: '+ level));
      -  }
      -
      -  this.db.executeDbCommand(cmd, function (err, resp) {
      -    if (err) return callback(err);
      -
      -    var doc = resp.documents[0];
      -
      -    err = 1 === doc.ok
      -      ? null
      -      : new Error('Could not set profiling level to: '+ level)
      -
      -    callback(err, doc);
      -  });
      -};

      Parameters:

      • level <Number, String> either off (0), slow (1), or all (2)
      • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
      • callback <Function>

      Connection#defaultOptions(options)

      Prepares default connection options.

      show code
      Connection.prototype.defaultOptions = function (options) {
      -  var o = options || {};
      -
      -  o.server = o.server || {};
      -
      -  if (!('auto_reconnect' in o.server)) {
      -    o.server.auto_reconnect = true;
      -  }
      -
      -  o.db || (o.db = {});
      -  o.db.forceServerObjectId = false;
      -
      -  // TODO default to true once the driver is fixed
      -  if (!('safe' in o.db)) o.db.safe = false;
      -
      -  return o;
      -}

      Parameters:


      Connection#db

      The mongodb.Db instance, set when the connection is opened


      Connection#collections

      A hash of the collections associated with this connection


      Connection#readyState

      Connection ready state

      - -
        -
      • 0 = disconnected
      • -
      • 1 = connected
      • -
      • 2 = connecting
      • -
      • 3 = disconnecting
      • -
      - -

      Each state change emits its associated event name.

      - -

      Example

      - -
      conn.on('connected', callback);
      -conn.on('disconnected', callback);

    • document.js

      Document(obj, [fields], [skipId])

      Document constructor.

      show code
      function Document (obj, fields, skipId) {
      -  // node <0.4.3 bug
      -  if (!this._events) this._events = {};
      -  this.setMaxListeners(0);
      -
      -  if ('boolean' === typeof fields) {
      -    this._strictMode = fields;
      -    this._selected = fields = undefined;
      -  } else {
      -    this._strictMode = this.schema.options && this.schema.options.strict;
      -    this._selected = fields;
      -  }
      -
      -  this.isNew = true;
      -  this.errors = undefined;
      -  this._shardval = undefined;
      -  this._saveError = undefined;
      -  this._validationError = undefined;
      -  this._adhocPaths = undefined;
      -  this._removing = undefined;
      -  this._inserting = undefined;
      -  this.__version = undefined;
      -  this.__getters = {};
      -  this.__id = undefined;
      -
      -  this._activePaths = new ActiveRoster;
      -
      -  var required = this.schema.requiredPaths();
      -  for (var i = 0; i < required.length; ++i) {
      -    this._activePaths.require(required[i]);
      -  }
      -
      -  this._doc = this._buildDoc(obj, fields, skipId);
      -  if (obj) this.set(obj, undefined, true);
      -  this._registerHooks();
      -};

      Parameters:

      • obj <Object> the values to set
      • [fields] <Object> the fields which were selected in the query returning this document
      • [skipId] <Boolean> bool, should we auto create an ObjectId _id

      Events:

      • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

      • save: Emitted when the document is successfully saved


      Document#_buildDoc(obj, [fields], [skipId])

      Builds the default doc structure

      show code
      Document.prototype._buildDoc = function (obj, fields, skipId) {
      -  var doc = {}
      -    , self = this
      -    , exclude
      -    , keys
      -    , key
      -    , ki
      -
      -  // determine if this doc is a result of a query with
      -  // excluded fields
      -  if (fields && 'Object' === fields.constructor.name) {
      -    keys = Object.keys(fields);
      -    ki = keys.length;
      -
      -    while (ki--) {
      -      if ('_id' !== keys[ki]) {
      -        exclude = 0 === fields[keys[ki]];
      -        break;
      -      }
      -    }
      -  }
      -
      -  var paths = Object.keys(this.schema.paths)
      -    , plen = paths.length
      -    , ii = 0
      -
      -  for (; ii < plen; ++ii) {
      -    var p = paths[ii];
      -
      -    if ('_id' == p) {
      -      if (skipId) continue;
      -      if (obj && '_id' in obj) continue;
      -    }
      -
      -    var type = this.schema.paths[p]
      -      , path = p.split('.')
      -      , len = path.length
      -      , last = len-1
      -      , doc_ = doc
      -      , i = 0
      -
      -    for (; i < len; ++i) {
      -      var piece = path[i]
      -        , def
      -
      -      if (i === last) {
      -        if (fields) {
      -          if (exclude) {
      -            // apply defaults to all non-excluded fields
      -            if (p in fields) continue;
      -
      -            def = type.getDefault(self, true);
      -            if ('undefined' !== typeof def) {
      -              doc_[piece] = def;
      -              self._activePaths.default(p);
      -            }
      -
      -          } else if (p in fields) {
      -            // selected field
      -            def = type.getDefault(self, true);
      -            if ('undefined' !== typeof def) {
      -              doc_[piece] = def;
      -              self._activePaths.default(p);
      -            }
      -          }
      -        } else {
      -          def = type.getDefault(self, true);
      -          if ('undefined' !== typeof def) {
      -            doc_[piece] = def;
      -            self._activePaths.default(p);
      -          }
      -        }
      -      } else {
      -        doc_ = doc_[piece] || (doc_[piece] = {});
      -      }
      -    }
      -  };
      -
      -  return doc;
      -};

      Parameters:

      Returns:


      Document#init(doc, fn)

      Initializes the document without setters or marking anything modified.

      show code
      Document.prototype.init = function (doc, fn) {
      -  this.isNew = false;
      -
      -  init(this, doc, this._doc);
      -  this._storeShard();
      -
      -  this.emit('init');
      -  if (fn) fn(null);
      -  return this;
      -};

      Parameters:

      Called internally after a document is returned from mongodb.


      Document#_storeShard()

      Stores the current values of the shard keys.

      show code
      Document.prototype._storeShard = function _storeShard () {
      -  // backwards compat
      -  var key = this.schema.options.shardKey || this.schema.options.shardkey;
      -  if (!(key && 'Object' == key.constructor.name)) return;
      -
      -  var orig = this._shardval = {}
      -    , paths = Object.keys(key)
      -    , len = paths.length
      -    , val
      -
      -  for (var i = 0; i < len; ++i) {
      -    val = this.getValue(paths[i]);
      -    if (isMongooseObject(val)) {
      -      orig[paths[i]] = val.toObject({ depopulate: true })
      -    } else if (null != val && val.valueOf) {
      -      orig[paths[i]] = val.valueOf();
      -    } else {
      -      orig[paths[i]] = val;
      -    }
      -  }
      -}

      Note:

      - -

      Shard key values do not / are not allowed to change.


      Document#update(doc, options, callback)

      Sends an update command with this document _id as the query selector.

      show code
      Document.prototype.update = function update () {
      -  var args = utils.args(arguments);
      -  args.unshift({_id: this._id});
      -  this.constructor.update.apply(this.constructor, args);
      -}

      Parameters:

      Returns:

      Example:

      - -
      weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
      - -

      Valid options:

      - -
        -
      • safe safe mode (defaults to value set in schema (true))
      • -
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • -

      Document#set(path, val, [type], [options])

      Sets the value of a path, or many paths.

      show code
      Document.prototype.set = function (path, val, type, options) {
      -  if (type && 'Object' == type.constructor.name) {
      -    options = type;
      -    type = undefined;
      -  }
      -
      -  var merge = options && options.merge
      -    , adhoc = type && true !== type
      -    , constructing = true === type
      -    , adhocs
      -
      -  if (adhoc) {
      -    adhocs = this._adhocPaths || (this._adhocPaths = {});
      -    adhocs[path] = Schema.interpretAsType(path, type);
      -  }
      -
      -  if ('string' !== typeof path) {
      -    // new Document({ key: val })
      -
      -    if (null === path || undefined === path) {
      -      var _ = path;
      -      path = val;
      -      val = _;
      -
      -    } else {
      -      var prefix = val
      -        ? val + '.'
      -        : '';
      -
      -      if (path instanceof Document) path = path._doc;
      -
      -      var keys = Object.keys(path)
      -        , i = keys.length
      -        , pathtype
      -        , key
      -
      -      while (i--) {
      -        key = keys[i];
      -        if (null != path[key] && 'Object' === path[key].constructor.name
      -          && !(this._path(prefix + key) instanceof MixedSchema)) {
      -          this.set(path[key], prefix + key, constructing);
      -        } else if (this._strictMode) {
      -          pathtype = this.schema.pathType(prefix + key);
      -          if ('real' === pathtype || 'virtual' === pathtype) {
      -            this.set(prefix + key, path[key], constructing);
      -          } else if ('throw' == this._strictMode) {
      -            throw new Error("Field `" + key + "` is not in schema.");
      -          }
      -        } else if (undefined !== path[key]) {
      -          this.set(prefix + key, path[key], constructing);
      -        }
      -      }
      -
      -      return this;
      -    }
      -  }
      -
      -  // ensure _strict is honored for obj props
      -  // docschema = new Schema({ path: { nest: 'string' }})
      -  // doc.set('path', obj);
      -  var pathType = this.schema.pathType(path);
      -  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
      -    if (!merge) this.setValue(path, null);
      -    this.set(val, path, constructing);
      -    return this;
      -  }
      -
      -  var schema;
      -  if ('adhocOrUndefined' == pathType && this._strictMode) {
      -    return this;
      -  } else if ('virtual' == pathType) {
      -    schema = this.schema.virtualpath(path);
      -    schema.applySetters(val, this);
      -    return this;
      -  } else {
      -    schema = this._path(path);
      -  }
      -
      -  var parts = path.split('.')
      -    , pathToMark
      -
      -  // When using the $set operator the path to the field must already exist.
      -  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
      -
      -  if (parts.length <= 1) {
      -    pathToMark = path;
      -  } else {
      -    for (var i = 0; i < parts.length; ++i) {
      -      var part = parts[i];
      -      var subpath = parts.slice(0, i).concat(part).join('.');
      -      if (this.isDirectModified(subpath) // earlier prefixes that are already
      -                                         // marked as dirty have precedence
      -          || this.get(subpath) === null) {
      -        pathToMark = subpath;
      -        break;
      -      }
      -    }
      -
      -    if (!pathToMark) pathToMark = path;
      -  }
      -
      -  if (!schema || null === val || undefined === val) {
      -    this._set(pathToMark, path, constructing, parts, schema, val);
      -    return this;
      -  }
      -
      -  var self = this;
      -
      -  // if this doc is being constructed we should not
      -  // trigger getters.
      -  var priorVal = constructing
      -    ? undefined
      -    : this.get(path);
      -
      -  var shouldSet = this.try(function(){
      -    val = schema.applySetters(val, self, false, priorVal);
      -  });
      -
      -  if (shouldSet) {
      -    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
      -  }
      -
      -  return this;
      -}

      Parameters:

      • path <String, Object> path or object of key/vals to set
      • val <Any> the value to set
      • [type] <Schema, String, Number, Buffer, etc..> optionally specify a type for "on-the-fly" attributes
      • [options] <Object> optionally specify options that modify the behavior of the set

      Example:

      - -
      // path, value
      -doc.set(path, value)
      -
      -// object
      -doc.set({
      -    path  : value
      -  , path2 : {
      -       path  : value
      -    }
      -})
      -
      -// only-the-fly cast to number
      -doc.set(path, value, Number)
      -
      -// only-the-fly cast to string
      -doc.set(path, value, String)

      Document#_shouldModify()

      Determine if we should mark this change as modified.

      show code
      Document.prototype._shouldModify = function (
      -    pathToMark, path, constructing, parts, schema, val, priorVal) {
      -
      -  if (this.isNew) return true;
      -  if (this.isDirectModified(pathToMark)) return false;
      -
      -  if (undefined === val && !this.isSelected(path)) {
      -    // when a path is not selected in a query, its initial
      -    // value will be undefined.
      -    return true;
      -  }
      -
      -  if (undefined === val && path in this._activePaths.states.default) {
      -    // we're just unsetting the default value which was never saved
      -    return false;
      -  }
      -
      -  if (!deepEqual(val, priorVal || this.get(path))) {
      -    return true;
      -  }
      -
      -  if (!constructing &&
      -      null != val &&
      -      path in this._activePaths.states.default &&
      -      deepEqual(val, schema.getDefault(this, constructing))) {
      -    // a path with a default was $unset on the server
      -    // and the user is setting it to the same value again
      -    return true;
      -  }
      -
      -  return false;
      -}

      Returns:


      Document#_set()

      Handles the actual setting of the value and marking the path modified if appropriate.

      show code
      Document.prototype._set = function (
      -    pathToMark, path, constructing, parts, schema, val, priorVal) {
      -
      -  var shouldModify = this._shouldModify.apply(this, arguments);
      -
      -  if (shouldModify) {
      -    this.markModified(pathToMark, val);
      -
      -    // handle directly setting arrays (gh-1126)
      -    MongooseArray || (MongooseArray = require('./types/array'));
      -    if (val instanceof MongooseArray) {
      -      val._registerAtomic('$set', val);
      -    }
      -  }
      -
      -  var obj = this._doc
      -    , i = 0
      -    , l = parts.length
      -
      -  for (; i < l; i++) {
      -    var next = i + 1
      -      , last = next === l;
      -
      -    if (last) {
      -      obj[parts[i]] = val;
      -    } else {
      -      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
      -        obj = obj[parts[i]];
      -      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
      -        obj = obj[parts[i]];
      -      } else {
      -        obj = obj[parts[i]] = {};
      -      }
      -    }
      -  }
      -}

      Document#getValue(path)

      Gets a raw value from a path (no getters)

      show code
      Document.prototype.getValue = function (path) {
      -  var parts = path.split('.')
      -    , obj = this._doc
      -    , part;
      -
      -  for (var i = 0, l = parts.length; i < l; i++) {
      -    part = parts[i];
      -    obj = obj.getValue
      -        ? obj.getValue(part) // If we have an embedded array document member
      -        : obj[part];
      -    if (!obj) return obj;
      -  }
      -
      -  return obj;
      -}

      Parameters:


      Document#setValue(path, value)

      Sets a raw value for a path (no casting, setters, transformations)

      show code
      Document.prototype.setValue = function (path, val) {
      -  var parts = path.split('.')
      -    , obj = this._doc;
      -
      -  for (var i = 0, len = parts.length-1; i < len; i++) {
      -    obj = obj[parts[i]];
      -  }
      -
      -  obj[parts[len]] = val;
      -  return this;
      -};

      Parameters:


      Document#get(path, [type])

      Returns the value of a path.

      show code
      Document.prototype.get = function (path, type) {
      -  var adhocs;
      -  if (type) {
      -    adhocs = this._adhocPaths || (this._adhocPaths = {});
      -    adhocs[path] = Schema.interpretAsType(path, type);
      -  }
      -
      -  var schema = this._path(path) || this.schema.virtualpath(path)
      -    , pieces = path.split('.')
      -    , obj = this._doc;
      -
      -  for (var i = 0, l = pieces.length; i < l; i++) {
      -    obj = null == obj ? null : obj[pieces[i]];
      -  }
      -
      -  if (schema) {
      -    obj = schema.applyGetters(obj, this);
      -  }
      -
      -  return obj;
      -};

      Parameters:

      Example

      - -
      // path
      -doc.get('age') // 47
      -
      -// dynamic casting to a string
      -doc.get('age', String) // "47"

      Document#_path(path)

      Returns the schematype for the given path.

      show code
      Document.prototype._path = function (path) {
      -  var adhocs = this._adhocPaths
      -    , adhocType = adhocs && adhocs[path];
      -
      -  if (adhocType) {
      -    return adhocType;
      -  } else {
      -    return this.schema.path(path);
      -  }
      -};

      Parameters:


      Document#markModified(path)

      Marks the path as having pending changes to write to the db.

      show code
      Document.prototype.markModified = function (path) {
      -  this._activePaths.modify(path);
      -}

      Parameters:

      • path <String> the path to mark modified

      Very helpful when using Mixed types.

      - -

      Example:

      - -
      doc.mixed.type = 'changed';
      -doc.markModified('mixed.type');
      -doc.save() // changes to mixed.type are now persisted

      Document#try(fn, scope)

      Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

      show code
      Document.prototype.try = function (fn, scope) {
      -  var res;
      -  try {
      -    fn.call(scope);
      -    res = true;
      -  } catch (e) {
      -    this._error(e);
      -    res = false;
      -  }
      -  return res;
      -};

      Parameters:

      • fn <Function> function to execute
      • scope <Object> the scope with which to call fn

      Document#modifiedPaths()

      Returns the list of paths that have been modified.

      show code
      Document.prototype.modifiedPaths = function () {
      -  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
      -
      -  return directModifiedPaths.reduce(function (list, path) {
      -    var parts = path.split('.');
      -    return list.concat(parts.reduce(function (chains, part, i) {
      -      return chains.concat(parts.slice(0, i).concat(part).join('.'));
      -    }, []));
      -  }, []);
      -};

      Returns:


      Document#isModified([path])

      Returns true if this document was modified, else false.

      show code
      Document.prototype.isModified = function (path) {
      -  return path
      -    ? !!~this.modifiedPaths().indexOf(path)
      -    : this._activePaths.some('modify');
      -};

      Parameters:

      Returns:

      If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

      - -

      Example

      - -
      doc.set('documents.0.title', 'changed');
      -doc.isModified()                    // true
      -doc.isModified('documents')         // true
      -doc.isModified('documents.0.title') // true
      -doc.isDirectModified('documents')   // false

      Document#isDirectModified(path)

      Returns true if path was directly set and modified, else false.

      show code
      Document.prototype.isDirectModified = function (path) {
      -  return (path in this._activePaths.states.modify);
      -};

      Parameters:

      Returns:

      Example

      - -
      doc.set('documents.0.title', 'changed');
      -doc.isDirectModified('documents.0.title') // true
      -doc.isDirectModified('documents') // false

      Document#isInit(path)

      Checks if path was initialized.

      show code
      Document.prototype.isInit = function (path) {
      -  return (path in this._activePaths.states.init);
      -};

      Parameters:

      Returns:


      Document#isSelected(path)

      Checks if path was selected in the source query which initialized this document.

      show code
      Document.prototype.isSelected = function isSelected (path) {
      -  if (this._selected) {
      -
      -    if ('_id' === path) {
      -      return 0 !== this._selected._id;
      -    }
      -
      -    var paths = Object.keys(this._selected)
      -      , i = paths.length
      -      , inclusive = false
      -      , cur
      -
      -    if (1 === i && '_id' === paths[0]) {
      -      // only _id was selected.
      -      return 0 === this._selected._id;
      -    }
      -
      -    while (i--) {
      -      cur = paths[i];
      -      if ('_id' == cur) continue;
      -      inclusive = !! this._selected[cur];
      -      break;
      -    }
      -
      -    if (path in this._selected) {
      -      return inclusive;
      -    }
      -
      -    i = paths.length;
      -    var pathDot = path + '.';
      -
      -    while (i--) {
      -      cur = paths[i];
      -      if ('_id' == cur) continue;
      -
      -      if (0 === cur.indexOf(pathDot)) {
      -        return inclusive;
      -      }
      -
      -      if (0 === pathDot.indexOf(cur)) {
      -        return inclusive;
      -      }
      -    }
      -
      -    return ! inclusive;
      -  }
      -
      -  return true;
      -}

      Parameters:

      Returns:

      Example

      - -
      Thing.findOne().select('name').exec(function (err, doc) {
      -   doc.isSelected('name') // true
      -   doc.isSelected('age')  // false
      -})

      Document#validate(cb)

      Executes registered validation rules for this document.

      show code
      Document.prototype.validate = function (cb) {
      -  var self = this
      -
      -  // only validate required fields when necessary
      -  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
      -    if (!self.isSelected(path) && !self.isModified(path)) return false;
      -    return true;
      -  });
      -
      -  paths = paths.concat(Object.keys(this._activePaths.states.init));
      -  paths = paths.concat(Object.keys(this._activePaths.states.modify));
      -  paths = paths.concat(Object.keys(this._activePaths.states.default));
      -
      -  if (0 === paths.length) {
      -    complete();
      -    return this;
      -  }
      -
      -  var validating = {}
      -    , total = 0;
      -
      -  paths.forEach(validatePath);
      -  return this;
      -
      -  function validatePath (path) {
      -    if (validating[path]) return;
      -
      -    validating[path] = true;
      -    total++;
      -
      -    process.nextTick(function(){
      -      var p = self.schema.path(path);
      -      if (!p) return --total || complete();
      -
      -      p.doValidate(self.getValue(path), function (err) {
      -        if (err) self.invalidate(path, err, true);
      -        --total || complete();
      -      }, self);
      -    });
      -  }
      -
      -  function complete () {
      -    var err = self._validationError;
      -    self._validationError = undefined;
      -    cb(err);
      -  }
      -};

      Parameters:

      • cb <Function> called after validation completes, passing an error if one occurred

      Note:

      - -

      This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

      - -

      Example:

      - -
      doc.validate(function (err) {
      -  if (err) handleError(err);
      -  else // validation passed
      -});

      Document#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      Document.prototype.invalidate = function (path, err) {
      -  if (!this._validationError) {
      -    this._validationError = new ValidationError(this);
      -  }
      -
      -  if (!err || 'string' === typeof err) {
      -    err = new ValidatorError(path, err);
      -  }
      -
      -  this._validationError.errors[path] = err;
      -}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> the error which states the reason `path` was invalid

      Document#_reset()

      Resets the internal modified state of this document.

      show code
      Document.prototype._reset = function reset () {
      -  var self = this;
      -  DocumentArray || (DocumentArray = require('./types/documentarray'));
      -
      -  this._activePaths
      -  .map('init', 'modify', function (i) {
      -    return self.getValue(i);
      -  })
      -  .filter(function (val) {
      -    return val && val instanceof DocumentArray && val.length;
      -  })
      -  .forEach(function (array) {
      -    var i = array.length;
      -    while (i--) {
      -      var doc = array[i];
      -      if (!doc) continue;
      -      doc._reset();
      -    }
      -  });
      -
      -  // clear atomics
      -  this._dirty().forEach(function (dirt) {
      -    var type = dirt.value;
      -    if (type && type._atomics) {
      -      type._atomics = {};
      -    }
      -  });
      -
      -  // Clear 'modify'('dirty') cache
      -  this._activePaths.clear('modify');
      -  this._validationError = undefined;
      -  this.errors = undefined;
      -  var self = this;
      -  this.schema.requiredPaths().forEach(function (path) {
      -    self._activePaths.require(path);
      -  });
      -
      -  return this;
      -}

      Returns:


      Document#_dirty()

      Returns this documents dirty paths / vals.

      show code
      Document.prototype._dirty = function _dirty () {
      -  var self = this;
      -
      -  var all = this._activePaths.map('modify', function (path) {
      -    return { path: path
      -           , value: self.getValue(path)
      -           , schema: self._path(path) };
      -  });
      -
      -  // Sort dirty paths in a flat hierarchy.
      -  all.sort(function (a, b) {
      -    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
      -  });
      -
      -  // Ignore "foo.a" if "foo" is dirty already.
      -  var minimal = []
      -    , lastPath
      -    , top;
      -
      -  all.forEach(function (item, i) {
      -    if (item.path.indexOf(lastPath) !== 0) {
      -      lastPath = item.path + '.';
      -      minimal.push(item);
      -      top = item;
      -    } else {
      -      if (!(item.value && top.value)) return;
      -
      -      // special case for top level MongooseArrays
      -      if (top.value._atomics && top.value.hasAtomics()) {
      -        // the `top` array itself and a sub path of `top` are being modified.
      -        // the only way to honor all of both modifications is through a $set
      -        // of entire array.
      -        top.value._atomics = {};
      -        top.value._atomics.$set = top.value;
      -      }
      -    }
      -  });
      -
      -  top = lastPath = null;
      -  return minimal;
      -}

      Document#_setSchema(schema)

      Assigns/compiles schema into this documents prototype.

      show code
      Document.prototype._setSchema = function (schema) {
      -  compile(schema.tree, this);
      -  this.schema = schema;
      -}

      Parameters:


      Document#_registerHooks()

      Register default hooks

      show code
      Document.prototype._registerHooks = function _registerHooks () {
      -  if (!this.save) return;
      -
      -  DocumentArray || (DocumentArray = require('./types/documentarray'));
      -
      -  this.pre('save', function (next) {
      -    // we keep the error semaphore to make sure we don't
      -    // call `save` unnecessarily (we only need 1 error)
      -    var subdocs = 0
      -      , error = false
      -      , self = this;
      -
      -    // check for DocumentArrays
      -    var arrays = this._activePaths
      -    .map('init', 'modify', function (i) {
      -      return self.getValue(i);
      -    })
      -    .filter(function (val) {
      -      return val && val instanceof DocumentArray && val.length;
      -    });
      -
      -    if (!arrays.length)
      -      return next();
      -
      -    arrays.forEach(function (array) {
      -      if (error) return;
      -
      -      // handle sparse arrays by using for loop vs array.forEach
      -      // which skips the sparse elements
      -
      -      var len = array.length
      -      subdocs += len;
      -
      -      for (var i = 0; i < len; ++i) {
      -        if (error) break;
      -
      -        var doc = array[i];
      -        if (!doc) {
      -          --subdocs || next();
      -          continue;
      -        }
      -
      -        doc.save(handleSave);
      -      }
      -    });
      -
      -    function handleSave (err) {
      -      if (error) return;
      -
      -      if (err) {
      -        self._validationError = undefined;
      -        return next(error = err);
      -      }
      -
      -      --subdocs || next();
      -    }
      -
      -  }, function (err) {
      -    // emit on the Model if listening
      -    if (this.constructor.listeners('error').length) {
      -      this.constructor.emit('error', err);
      -    } else {
      -      // emit on the connection
      -      if (!this.db.listeners('error').length) {
      -        err.stack = 'No listeners detected, throwing. '
      -                  + 'Consider adding an error listener to your connection.
      -'
      -                  + err.stack
      -      }
      -      this.db.emit('error', err);
      -    }
      -  }).pre('save', function checkForExistingErrors (next) {
      -    // if any doc.set() calls failed
      -    if (this._saveError) {
      -      next(this._saveError);
      -      this._saveError = null;
      -    } else {
      -      next();
      -    }
      -  }).pre('save', function validation (next) {
      -    return this.validate(next);
      -  });
      -
      -  // add user defined queues
      -  this._doQueue();
      -};

      Document#_error(err)

      Registers an error

      show code
      Document.prototype._error = function (err) {
      -  this._saveError = err;
      -  return this;
      -};

      Parameters:


      Document#_doQueue()

      Executes methods queued from the Schema definition

      show code
      Document.prototype._doQueue = function () {
      -  var q = this.schema && this.schema.callQueue;
      -  if (q) {
      -    for (var i = 0, l = q.length; i < l; i++) {
      -      this[q[i][0]].apply(this, q[i][1]);
      -    }
      -  }
      -  return this;
      -};

      Document#toObject([options])

      Converts this document into a plain javascript object

      show code
      Document.prototype.toObject = function (options) {
      -  // When internally saving this document we always pass options,
      -  // bypassing the custom schema options.
      -  if (!(options && 'Object' == options.constructor.name)) {
      -    options = this.schema.options.toObject
      -      ? clone(this.schema.options.toObject)
      -      : {};
      -  }
      -
      -  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
      -
      -  var ret = clone(this._doc, options);
      -
      -  if (options.virtuals || options.getters && false !== options.virtuals) {
      -    applyGetters(this, ret, 'virtuals', options);
      -  }
      -
      -  if (options.getters) {
      -    applyGetters(this, ret, 'paths', options);
      -  }
      -
      -  return ret;
      -};

      Parameters:

      Returns:

      Options:

      - -
        -
      • getters apply all getters (path and virtual getters)
      • -
      • virtuals apply virtual getters (can override getters option)
      • -
      • minimize remove empty objects (defaults to true)
      • -
      - -

      Example of only applying path getters

      - -
      doc.toObject({ getters: true, virtuals: false })
      - -

      Example of only applying virtual getters

      - -
      doc.toObject({ virtuals: true })
      - -

      Example of applying both path and virtual getters

      - -
      doc.toObject({ getters: true })
      - -

      To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

      - -
      schema.set('toObject', { virtuals: true })
      - -

      See schema options for details.


      Document#toJSON(options)

      The return value of this method is used in calls to JSON.stringify(doc).

      show code
      Document.prototype.toJSON = function (options) {
      -  // check for object type since an array of documents
      -  // being stringified passes array indexes instead
      -  // of options objects. JSON.stringify([doc, doc])
      -  if (!(options && 'Object' == options.constructor.name)) {
      -    options = this.schema.options.toJSON
      -      ? clone(this.schema.options.toJSON)
      -      : {};
      -  }
      -  options.json = true;
      -  return this.toObject(options);
      -};

      Parameters:

      • options <Object> same options as `Document#toObject`

      Returns:

      This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

      - -
      schema.set('toJSON', { virtuals: true })
      - -

      See schema options for details.


      Document#inspect()

      Helper for console.log

      show code
      Document.prototype.inspect = function (options) {
      -  var opts = options && 'Object' == options.constructor.name
      -    ? options
      -    : undefined
      -  return inspect(this.toObject(opts));
      -};

      Document#toString()

      Helper for console.log


      Document#equals(doc)

      Returns true if the Document stores the same data as doc.

      show code
      Document.prototype.equals = function (doc) {
      -  var tid = this.get('_id');
      -  var docid = doc.get('_id');
      -  return tid.equals
      -    ? tid.equals(docid)
      -    : tid === docid;
      -};

      Parameters:

      Returns:

      Documents are considered equal when they have matching _ids.


      Document#errors

      Hash containing current validation errors.


      Document#id

      The string version of this documents _id.

      - -

      Note:

      - -

      This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

      - -
      new Schema({ name: String }, { id: false });

      Document#isNew

      Boolean flag specifying if the document is new.


      Document#schema

      The documents schema.


    • drivers/node-mongodb-native/collection.js

      NativeCollection()

      A node-mongodb-native collection implementation.

      show code
      function NativeCollection () {
      -  this.collection = null;
      -  MongooseCollection.apply(this, arguments);
      -}

      Inherits:

      All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


      NativeCollection#onOpen()

      Called when the connection opens.

      show code
      NativeCollection.prototype.onOpen = function () {
      -  var self = this;
      -
      -  if (this.collection) {
      -    return MongooseCollection.prototype.onOpen.call(self);
      -  }
      -
      -  if (!self.opts.size) {
      -    // non-capped
      -    return self.conn.db.collection(self.name, callback);
      -  }
      -
      -  // capped
      -  return self.conn.db.collection(self.name, function (err, c) {
      -    if (err) return callback(err);
      -
      -    // discover if this collection exists and if it is capped
      -    c.options(function (err, exists) {
      -      if (err) return callback(err);
      -
      -      if (exists) {
      -        if (exists.capped) {
      -          callback(null, c);
      -        } else {
      -          var msg = 'A non-capped collection exists with this name.
      -
      -'
      -                  + ' To use this collection as a capped collection, please '
      -                  + 'first convert it.
      -'
      -                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
      -          err = new Error(msg);
      -          callback(err);
      -        }
      -      } else {
      -        // create
      -        var opts = utils.clone(self.opts);
      -        opts.capped = true;
      -        self.conn.db.createCollection(self.name, opts, callback);
      -      }
      -    });
      -  });
      -
      -  function callback (err, collection) {
      -    if (err) {
      -      // likely a strict mode error
      -      self.conn.emit('error', err);
      -    } else {
      -      self.collection = collection;
      -      MongooseCollection.prototype.onOpen.call(self);
      -    }
      -  };
      -};

      NativeCollection#onClose()

      Called when the connection closes

      show code
      NativeCollection.prototype.onClose = function () {
      -  MongooseCollection.prototype.onClose.call(this);
      -};

      NativeCollection#getIndexes(callback)

      Retreives information about this collections indexes.

      Parameters:


    • drivers/node-mongodb-native/connection.js

      NativeConnection()

      A node-mongodb-native connection implementation.

      show code
      function NativeConnection() {
      -  MongooseConnection.apply(this, arguments);
      -};

      Inherits:


      NativeConnection#doOpen(fn)

      Opens the connection to MongoDB.

      show code
      NativeConnection.prototype.doOpen = function (fn) {
      -  var server
      -    , self = this;
      -
      -  if (!this.db) {
      -    server = new mongo.Server(this.host, Number(this.port), this.options.server);
      -    this.db = new mongo.Db(this.name, server, this.options.db);
      -  }
      -
      -  this.db.open(function (err) {
      -    if (err) return fn(err);
      -    fn();
      -    listen(self);
      -  });
      -
      -  return this;
      -};
      -
      -function listen (conn) {
      -  if (conn._listening) return;
      -  conn._listening = true;
      -
      -  conn.db.on('close', function(){
      -    if (conn._closeCalled) return;
      -
      -    // the driver never emits an `open` event. auto_reconnect still
      -    // emits a `close` event but since we never get another
      -    // `open` we can't emit close
      -    if (conn.db.serverConfig.autoReconnect) {
      -      conn.readyState = STATES.disconnected;
      -      conn.emit('close');
      -      return;
      -    }
      -    conn.onClose();
      -  });
      -  conn.db.on('error', function(err){
      -    conn.emit('error', err);
      -  });
      -  conn.db.on('timeout', function(err){
      -    var error = new Error(err && err.err || 'connection timeout');
      -    conn.emit('error', error);
      -  });
      -  conn.db.on('open', function (err, db) {
      -    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
      -      conn.readyState = STATES.connected;
      -      conn.emit('reconnected')
      -    }
      -  })
      -}

      Parameters:

      Returns:


      NativeConnection#doOpenSet(fn)

      Opens a connection to a MongoDB ReplicaSet.

      show code
      NativeConnection.prototype.doOpenSet = function (fn) {
      -  if (!this.db) {
      -    var servers = []
      -      , ports = this.port
      -      , self = this
      -
      -    this.host.forEach(function (host, i) {
      -      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
      -    });
      -
      -    var server = new ReplSetServers(servers, this.options.replset);
      -    this.db = new mongo.Db(this.name, server, this.options.db);
      -
      -    this.db.on('fullsetup', function () {
      -      self.emit('fullsetup')
      -    });
      -  }
      -
      -  this.db.open(function (err) {
      -    if (err) return fn(err);
      -    fn();
      -    listen(self);
      -  });
      -
      -  return this;
      -};

      Parameters:

      Returns:

      See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


      NativeConnection#doClose(fn)

      Closes the connection

      show code
      NativeConnection.prototype.doClose = function (fn) {
      -  this.db.close();
      -  if (fn) fn();
      -  return this;
      -}

      Parameters:

      Returns:


    • error.js

      MongooseError()

      Mongoose error

      show code
      function MongooseError (msg) {
      -  Error.call(this);
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.message = msg;
      -  this.name = 'MongooseError';
      -};

      Inherits:


    • errors/cast.js

      CastError(type, value)

      Casting Error constructor.

      show code
      function CastError (type, value) {
      -  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'CastError';
      -  this.type = type;
      -  this.value = value;
      -};

      Parameters:

      Inherits:


    • errors/document.js

      DocumentError(msg)

      Document Error

      show code
      function DocumentError (msg) {
      -  MongooseError.call(this, msg);
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'DocumentError';
      -};

      Parameters:

      Inherits:


    • errors/validation.js

      ValidationError(instance)

      Document Validation Error

      show code
      function ValidationError (instance) {
      -  MongooseError.call(this, "Validation failed");
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'ValidationError';
      -  this.errors = instance.errors = {};
      -};

      Parameters:

      Inherits:


      ValidationError#toString()

      Console.log helper

      show code
      ValidationError.prototype.toString = function () {
      -  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
      -    return String(this.errors[key]);
      -  }, this).join(', ');
      -};

    • errors/validator.js

      ValidatorError(path, msg)

      Schema validator error

      show code
      function ValidatorError (path, type) {
      -  var msg = type
      -    ? '"' + type + '" '
      -    : '';
      -  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'ValidatorError';
      -  this.path = path;
      -  this.type = type;
      -};

      Parameters:

      Inherits:


    • model.js

      Model(doc)

      Model constructor

      show code
      function Model (doc, fields, skipId) {
      -  Document.call(this, doc, fields, skipId);
      -};

      Parameters:

      • doc <Object> values to with which to create the document

      Inherits:

      Events:

      • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

      • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


      Model#_getPopulationKeys(query)

      Returns what paths can be populated

      show code
      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
      -  if (!(query && query.options.populate)) return;
      -
      -  var names = Object.keys(query.options.populate)
      -    , n = names.length
      -    , name
      -    , paths = {}
      -    , hasKeys
      -    , schema
      -
      -  while (n--) {
      -    name = names[n];
      -    schema = this.schema.path(name);
      -    hasKeys = true;
      -
      -    if (!schema) {
      -      // if the path is not recognized, it's potentially embedded docs
      -      // walk path atoms from right to left to find a matching path
      -      var pieces = name.split('.')
      -        , i = pieces.length;
      -
      -      while (i--) {
      -        var path = pieces.slice(0, i).join('.')
      -          , pathSchema = this.schema.path(path);
      -
      -        // loop until we find an array schema
      -        if (pathSchema && pathSchema.caster) {
      -          if (!paths[path]) {
      -            paths[path] = { sub: {} };
      -          }
      -
      -          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
      -          hasKeys || (hasKeys = true);
      -          break;
      -        }
      -      }
      -    } else {
      -      paths[name] = query.options.populate[name];
      -      hasKeys || (hasKeys = true);
      -    }
      -  }
      -
      -  return hasKeys && paths;
      -};

      Parameters:

      Returns:


      Model#_populate(schema, oid, query, fn)

      Populates an object

      show code
      Model.prototype._populate = function populate (schema, oid, query, fn) {
      -  if (!Array.isArray(oid)) {
      -    var conditions = query.conditions || {};
      -    conditions._id = oid;
      -
      -    return this
      -    .db.model(query.model || schema.options.ref)
      -    .findOne(conditions, query.fields, query.options, fn);
      -  }
      -
      -  if (!oid.length) {
      -    return fn(null, oid);
      -  }
      -
      -  var model = this.db.model(query.model || schema.caster.options.ref)
      -    , conditions = query && query.conditions || {};
      -
      -  conditions._id || (conditions._id = { $in: oid });
      -
      -  model.find(conditions, query.fields, query.options, function (err, docs) {
      -    if (err) return fn(err);
      -
      -    // user specified sort order?
      -    if (query.options && query.options.sort) {
      -      return fn(null, docs);
      -    }
      -
      -    // put back in original id order (using a hash reduces complexity from n*n to 2n)
      -    var docHash = {};
      -    docs.forEach(function (doc) {
      -      docHash[doc._id] = doc;
      -    });
      -
      -    var arr = [];
      -    oid.forEach(function (id) {
      -      if (id in docHash) arr.push(docHash[id]);
      -    });
      -
      -    fn(null, arr);
      -  });
      -};

      Parameters:

      • schema <SchemaType> type for the oid
      • oid <Object> object id or array of object ids
      • query <Object> object specifying query conditions, fields, and options
      • fn <Function>

      Model#init(doc, query, fn)

      Performs auto-population of relations.

      show code
      Model.prototype.init = function init (doc, query, fn) {
      -  if ('function' == typeof query) {
      -    fn = query;
      -    query = null;
      -  }
      -
      -  var populate = this._getPopulationKeys(query);
      -
      -  if (!populate) {
      -    return Document.prototype.init.call(this, doc, fn);
      -  }
      -
      -  // population from other models is necessary
      -  var self = this;
      -
      -  init(doc, '', function (err) {
      -    if (err) return fn(err);
      -    Document.prototype.init.call(self, doc, fn);
      -  });
      -
      -  return this;
      -
      -  function init (obj, prefix, fn) {
      -    prefix = prefix || '';
      -
      -    var keys = Object.keys(obj)
      -      , len = keys.length;
      -
      -    return next();
      -
      -    function next () {
      -      if (--len < 0) return fn();
      -
      -      var i = keys[len]
      -        , path = prefix + i
      -        , schema = self.schema.path(path)
      -        , total = 0
      -        , inline = false
      -        , poppath
      -
      -      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
      -        // assume nested object
      -        return init(obj[i], path + '.', next);
      -      }
      -
      -      if (!(obj[i] && schema && populate[path])) return next();
      -
      -      // this query object is re-used and passed around. we clone
      -      // it to prevent query condition contamination between
      -      // one populate call to the next.
      -      poppath = utils.clone(populate[path]);
      -
      -      if (poppath.sub) {
      -        obj[i].forEach(function (subobj) {
      -          inline = true;
      -
      -          var pkeys = Object.keys(poppath.sub)
      -            , pi = pkeys.length
      -            , key
      -
      -          while (pi--) {
      -            key = pkeys[pi];
      -
      -            if (subobj[key]) (function (key) {
      -              total++;
      -              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
      -              function done (err, doc) {
      -                if (err) return error(err);
      -                subobj[key] = doc;
      -                if (--total < 1 && !inline) {
      -                  next();
      -                }
      -              }
      -            })(key);
      -          }
      -        });
      -
      -        inline = false;
      -
      -        if (0 === total) return next();
      -
      -      } else {
      -        self._populate(schema, obj[i], poppath, function (err, doc) {
      -          if (err) return error(err);
      -          obj[i] = doc;
      -          next();
      -        });
      -      }
      -    };
      -  };
      -
      -  function error (err) {
      -    if (error.err) return;
      -    fn(error.err = err);
      -  }
      -};

      Parameters:

      • doc <Object> document returned by mongo
      • query <Query> query that originated the initialization
      • fn <Function>

      Model#save([fn])

      Saves this document.

      show code
      Model.prototype.save = function save (fn) {
      -  var promise = new Promise(fn)
      -    , complete = handleSave(promise, this)
      -    , options = {}
      -
      -  if (this.schema.options.safe) {
      -    options.safe = this.schema.options.safe;
      -  }
      -
      -  if (this.isNew) {
      -    // send entire doc
      -    var obj = this.toObject({ depopulate: 1 });
      -    this._version(true, obj);
      -    this.collection.insert(obj, options, complete);
      -    this._reset();
      -    this.isNew = false;
      -    this.emit('isNew', false);
      -    // Make it possible to retry the insert
      -    this._inserting = true;
      -
      -  } else {
      -    // Make sure we don't treat it as a new object on error,
      -    // since it already exists
      -    this._inserting = false;
      -
      -    var delta = this._delta();
      -    if (delta) {
      -      var where = this._where(delta[0]);
      -      this.collection.update(where, delta[1], options, complete);
      -    } else {
      -      process.nextTick(function () {
      -        complete(null);
      -      })
      -    }
      -
      -    this._reset();
      -    this.emit('isNew', false);
      -  }
      -};

      Parameters:

      Example:

      - -
      product.sold = Date.now();
      -product.save(function (err, product) {
      -  if (err) ..
      -})
      - -

      The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      - -
      var db = mongoose.createConnection(..);
      -var schema = new Schema(..);
      -var Product = db.model('Product', schema);
      -
      -db.on('error', handleError);
      - -

      However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

      - -
      Product.on('error', handleError);

      Model#_delta()

      Produces a special query document of the modified properties used in updates.

      show code
      Model.prototype._delta = function _delta () {
      -  var dirty = this._dirty();
      -  if (!dirty.length) return;
      -
      -  var self = this
      -    , where = {}
      -    , delta = {}
      -    , len = dirty.length
      -    , d = 0
      -    , val
      -    , obj
      -
      -  for (; d < len; ++d) {
      -    var data = dirty[d]
      -    var value = data.value
      -    var schema = data.schema
      -
      -    if (undefined === value) {
      -      operand(self, where, delta, data, 1, '$unset');
      -
      -    } else if (null === value) {
      -      operand(self, where, delta, data, null);
      -
      -    } else if (value._path && value._atomics) {
      -      handleAtomics(self, where, delta, data, value);
      -
      -    } else if (value._path && Buffer.isBuffer(value)) {
      -      // MongooseBuffer
      -      value = value.toObject();
      -      operand(self, where, delta, data, value);
      -
      -    } else {
      -      value = utils.clone(value);
      -      operand(self, where, delta, data, value);
      -    }
      -  }
      -
      -  if (this.__version) {
      -    this._version(where, delta);
      -  }
      -
      -  return [where, delta];
      -}

      Model#_version()

      Appends versioning to the where and update clauses.

      show code
      Model.prototype._version = function _version (where, delta) {
      -  var key = this.schema.options.versionKey;
      -
      -  if (true === where) {
      -    // this is an insert
      -    if (key) this.setValue(key, delta[key] = 0);
      -    return;
      -  }
      -
      -  // updates
      -
      -  // only apply versioning if our versionKey was selected. else
      -  // there is no way to select the correct version. we could fail
      -  // fast here and force them to include the versionKey but
      -  // thats a bit intrusive. can we do this automatically?
      -  // TODO fail fast option?
      -  if (!this.isSelected(key)) {
      -    return;
      -  }
      -
      -  // $push $addToSet don't need the where clause set
      -  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
      -    where[key] = this.getValue(key);
      -  }
      -
      -  if (VERSION_INC === (VERSION_INC & this.__version)) {
      -    delta.$inc || (delta.$inc = {});
      -    delta.$inc[key] = 1;
      -  }
      -}

      Model#increment()

      Signal that we desire an increment of this documents version.

      show code
      Model.prototype.increment = function increment () {
      -  this.__version = VERSION_ALL;
      -  return this;
      -}

      Model#_where()

      Returns a query object which applies shardkeys if they exist.

      show code
      Model.prototype._where = function _where (where) {
      -  where || (where = {});
      -
      -  var paths
      -    , len
      -
      -  if (this._shardval) {
      -    paths = Object.keys(this._shardval)
      -    len = paths.length
      -
      -    for (var i = 0; i < len; ++i) {
      -      where[paths[i]] = this._shardval[paths[i]];
      -    }
      -  }
      -
      -  where._id = this._doc._id;
      -  return where;
      -}

      Model#remove([fn])

      Removes this document from the db.

      show code
      Model.prototype.remove = function remove (fn) {
      -  if (this._removing) return this;
      -
      -  var promise = this._removing = new Promise(fn)
      -    , where = this._where()
      -    , self = this
      -    , options = {}
      -
      -  if (this.schema.options.safe) {
      -    options.safe = this.schema.options.safe;
      -  }
      -
      -  this.collection.remove(where, options, tick(function (err) {
      -    if (err) {
      -      promise.error(err);
      -      promise = self = self._removing = where = options = null;
      -      return;
      -    }
      -    self.emit('remove', self);
      -    promise.complete();
      -    promise = self = where = options = null;
      -  }));
      -
      -  return this;
      -};

      Parameters:

      Example:

      - -
      product.remove(function (err, product) {
      -  if (err) return handleError(err);
      -  Product.findById(product._id, function (err, product) {
      -    console.log(product) // null
      -  })
      -})

      Model#_registerHooks()

      Register hooks override

      show code
      Model.prototype._registerHooks = function registerHooks () {
      -  Document.prototype._registerHooks.call(this);
      -};

      Model#model(name)

      Returns another Model instance.

      show code
      Model.prototype.model = function model (name) {
      -  return this.db.model(name);
      -};

      Parameters:

      Example:

      - -
      var doc = new Tank;
      -doc.model('User').findById(id, callback);

      Model#$where(argument)

      Creates a Query and specifies a $where condition.

      Parameters:

      • argument <String, Function> is a javascript string or anonymous function

      Returns:

      Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      - -
      Blog.$where('this.comments.length &gt; 5');

      Model.init()

      Called when the model compiles.

      show code
      Model.init = function init () {
      -  if (this.schema.options.autoIndex)
      -    this.ensureIndexes();
      -
      -  this.schema.emit('init', this);
      -};

      Model.ensureIndexes([cb])

      Sends ensureIndex commands to mongo for each index declared in the schema.

      show code
      Model.ensureIndexes = function ensureIndexes (cb) {
      -  var indexes = this.schema.indexes();
      -  if (!indexes.length) {
      -    return cb && cb();
      -  }
      -
      -  var self = this
      -    , safe = self.schema.options.safe
      -    , count = indexes.length
      -    , error
      -
      -  indexes.forEach(function (index) {
      -    var options = index[1];
      -    options.safe = safe;
      -    self.collection.ensureIndex(index[0], options, tick(function (err) {
      -      if (err) error = err;
      -      if (--count) return;
      -
      -      self.emit('index', error);
      -      cb && cb(error);
      -    }));
      -  });
      -}

      Parameters:

      After completion, an index event is emitted on this Model passing an error if one occurred.

      - -

      NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

      - -

      Example:

      - -
      Event.ensureIndexes(function (err) {
      -  if (err) return handleError(err);
      -});

      Model.remove(conditions, [callback])

      Removes documents from the collection.

      show code
      Model.remove = function remove (conditions, callback) {
      -  if ('function' === typeof conditions) {
      -    callback = conditions;
      -    conditions = {};
      -  }
      -
      -  var query = new Query(conditions).bind(this, 'remove');
      -
      -  if ('undefined' === typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.remove(callback);
      -};

      Parameters:

      Returns:

      Note:

      - -

      To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      - -
      Comment.remove({ _id: id }).exec();

      Model.find(conditions, [fields], [options], [callback])

      Finds documents

      show code
      Model.find = function find (conditions, fields, options, callback) {
      -  if ('function' == typeof conditions) {
      -    callback = conditions;
      -    conditions = {};
      -    fields = null;
      -    options = null;
      -  } else if ('function' == typeof fields) {
      -    callback = fields;
      -    fields = null;
      -    options = null;
      -  } else if ('function' == typeof options) {
      -    callback = options;
      -    options = null;
      -  }
      -
      -  var query = new Query(conditions, options);
      -  query.bind(this, 'find');
      -  query.select(fields);
      -
      -  if ('undefined' === typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.find(callback);
      -};

      Parameters:

      Returns:

      Examples:

      - -
      // retrieve only certain keys
      -MyModel.find({ name: /john/i }, 'name friends', function () { })
      -
      -// pass options
      -MyModel.find({ name: /john/i }, null, { skip: 10 } )

      Model._applyNamedScope(query)

      Merges the current named scope query into query.

      show code
      Model._applyNamedScope = function _applyNamedScope (query) {
      -  var cQuery = this._cumulativeQuery;
      -
      -  if (cQuery) {
      -    merge(query._conditions, cQuery._conditions);
      -    if (query._fields && cQuery._fields)
      -      merge(query._fields, cQuery._fields);
      -    if (query.options && cQuery.options)
      -      merge(query.options, cQuery.options);
      -    delete this._cumulativeQuery;
      -  }
      -
      -  return query;
      -}

      Parameters:

      Returns:


      Model.findById(id, [fields], [options], [callback])

      Finds a single document by id.

      show code
      Model.findById = function findById (id, fields, options, callback) {
      -  return this.findOne({ _id: id }, fields, options, callback);
      -};

      Parameters:

      Returns:

      The id is cast to an ObjectId before sending the command.

      - -

      Example:

      - -
      Adventure.findById(id, callback);

      Model.findOne(conditions, [fields], [options], [callback])

      Finds one document.

      show code
      Model.findOne = function findOne (conditions, fields, options, callback) {
      -  if ('function' == typeof options) {
      -    // TODO Handle all 3 of the following scenarios
      -    // Hint: Only some of these scenarios are possible if cQuery is present
      -    // Scenario: findOne(conditions, fields, callback);
      -    // Scenario: findOne(fields, options, callback);
      -    // Scenario: findOne(conditions, options, callback);
      -    callback = options;
      -    options = null;
      -  } else if ('function' == typeof fields) {
      -    // TODO Handle all 2 of the following scenarios
      -    // Scenario: findOne(conditions, callback)
      -    // Scenario: findOne(fields, callback)
      -    // Scenario: findOne(options, callback);
      -    callback = fields;
      -    fields = null;
      -    options = null;
      -  } else if ('function' == typeof conditions) {
      -    callback = conditions;
      -    conditions = {};
      -    fields = null;
      -    options = null;
      -  }
      -
      -  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.findOne(callback);
      -};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      - -

      Example:

      - -
      Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

      Model.count(conditions, [callback])

      Counts number of matching documents in a database collection.

      show code
      Model.count = function count (conditions, callback) {
      -  if ('function' === typeof conditions)
      -    callback = conditions, conditions = {};
      -
      -  var query = new Query(conditions).bind(this, 'count');
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.count(callback);
      -};

      Parameters:

      Returns:

      Example:

      - -
      Adventure.count({ type: 'jungle' }, function (err, count) {
      -  if (err) ..
      -  console.log('there are %d jungle adventures', count);
      -});

      Model.distinct(field, [conditions], [callback])

      Executes a DISTINCT command

      show code
      Model.distinct = function distinct (field, conditions, callback) {
      -  var query = new Query(conditions).bind(this, 'distinct');
      -  if ('undefined' == typeof callback) {
      -    query._distinctArg = field;
      -    return query;
      -  }
      -
      -  this._applyNamedScope(query);
      -  return query.distinct(field, callback);
      -};

      Parameters:

      Returns:


      Model.where(path, [val])

      Creates a Query, applies the passed conditions, and returns the Query.

      show code
      Model.where = function where (path, val) {
      -  var q = new Query().bind(this, 'find');
      -  return q.where.apply(q, arguments);
      -};

      Parameters:

      Returns:

      For example, instead of writing:

      - -
      User.find({age: {$gte: 21, $lte: 65}}, callback);
      - -

      we can instead write:

      - -
      User.where('age').gte(21).lte(65).exec(callback);
      - -

      Since the Query class also supports where you can continue chaining

      - -
      User
      -.where('age').gte(21).lte(65)
      -.where('name', /^b/i)
      -... etc

      Model.findOneAndUpdate([conditions], [update], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Model.findOneAndUpdate = function (conditions, update, options, callback) {
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = null;
      -  }
      -  else if (1 === arguments.length) {
      -    if ('function' == typeof conditions) {
      -      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
      -
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(update)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate()
      -';
      -      throw new TypeError(msg)
      -    }
      -    update = conditions;
      -    conditions = undefined;
      -  }
      -
      -  var fields;
      -  if (options && options.fields) {
      -    fields = options.fields;
      -    options.fields = undefined;
      -  }
      -
      -  var query = new Query(conditions);
      -  query.setOptions(options);
      -  query.select(fields);
      -  query.bind(this, 'findOneAndUpdate', update);
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.findOneAndUpdate(callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findOneAndUpdate(conditions, update, options, callback) // executes
      -A.findOneAndUpdate(conditions, update, options)  // returns Query
      -A.findOneAndUpdate(conditions, update, callback) // executes
      -A.findOneAndUpdate(conditions, update)           // returns Query
      -A.findOneAndUpdate()                             // returns Query
      - -

      Note:

      - -

      All top level update keys which are not atomic operation names are treated as set operations:

      - -

      Example:

      - -
      var query = { name: 'borne' };
      -Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
      -
      -// is sent as
      -Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
      - -

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      - -

      Note:

      - -

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      - -
        -
      • defaults
      • -
      • setters
      • -
      • validators
      • -
      • middleware
      • -
      - -

      If you need those features, use the traditional approach of first retrieving the document.

      - -
      Model.findOne({ name: 'borne' }, function (err, doc) {
      -  if (err) ..
      -  doc.name = 'jason borne';
      -  doc.save(callback);
      -})

      Model.findByIdAndUpdate(id, [update], [options], [callback])

      Issues a mongodb findAndModify update command by a documents id.

      show code
      Model.findByIdAndUpdate = function (id, update, options, callback) {
      -  var args;
      -
      -  if (1 === arguments.length) {
      -    if ('function' == typeof id) {
      -      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
      -
      -'
      -                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      -'
      -                + '  ' + this.modelName + '.findByIdAndUpdate(id)
      -'
      -                + '  ' + this.modelName + '.findByIdAndUpdate()
      -';
      -      throw new TypeError(msg)
      -    }
      -    return this.findOneAndUpdate({_id: id }, undefined);
      -  }
      -
      -  args = utils.args(arguments, 1);
      -  args.unshift({ _id: id });
      -  return this.findOneAndUpdate.apply(this, args);
      -}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findByIdAndUpdate(id, update, options, callback) // executes
      -A.findByIdAndUpdate(id, update, options)  // returns Query
      -A.findByIdAndUpdate(id, update, callback) // executes
      -A.findByIdAndUpdate(id, update)           // returns Query
      -A.findByIdAndUpdate()                     // returns Query
      - -

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      - -

      Note:

      - -

      All top level update keys which are not atomic operation names are treated as set operations:

      - -

      Example:

      - -
      Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
      -
      -// is sent as
      -Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
      - -

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      - -

      Note:

      - -

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      - -
        -
      • defaults
      • -
      • setters
      • -
      • validators
      • -
      • middleware
      • -
      - -

      If you need those features, use the traditional approach of first retrieving the document.

      - -
      Model.findById(id, function (err, doc) {
      -  if (err) ..
      -  doc.name = 'jason borne';
      -  doc.save(callback);
      -})

      Model.findOneAndRemove(conditions, [options], [callback])

      Issue a mongodb findAndModify remove command.

      show code
      Model.findOneAndRemove = function (conditions, options, callback) {
      -  if (1 === arguments.length && 'function' == typeof conditions) {
      -    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
      -
      -'
      -              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      -'
      -              + '  ' + this.modelName + '.findOneAndRemove(conditions)
      -'
      -              + '  ' + this.modelName + '.findOneAndRemove()
      -';
      -    throw new TypeError(msg)
      -  }
      -
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = undefined;
      -  }
      -
      -  var fields;
      -  if (options) {
      -    fields = options.select;
      -    options.select = undefined;
      -  }
      -
      -  var query = new Query(conditions);
      -  query.setOptions(options);
      -  query.select(fields);
      -  query.bind(this, 'findOneAndRemove');
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.findOneAndRemove(callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      - -

      Executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findOneAndRemove(conditions, options, callback) // executes
      -A.findOneAndRemove(conditions, options)  // return Query
      -A.findOneAndRemove(conditions, callback) // executes
      -A.findOneAndRemove(conditions) // returns Query
      -A.findOneAndRemove()           // returns Query

      Model.findByIdAndRemove(id, [options], [callback])

      Issue a mongodb findAndModify remove command by a documents id.

      show code
      Model.findByIdAndRemove = function (id, options, callback) {
      -  if (1 === arguments.length && 'function' == typeof id) {
      -    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
      -
      -'
      -              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      -'
      -              + '  ' + this.modelName + '.findByIdAndRemove(id)
      -'
      -              + '  ' + this.modelName + '.findByIdAndRemove()
      -';
      -    throw new TypeError(msg)
      -  }
      -
      -  return this.findOneAndRemove({ _id: id }, options, callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      - -

      Executes immediately if callback is passed, else a Query object is returned.

      - -

      Options:

      - -
        -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findByIdAndRemove(id, options, callback) // executes
      -A.findByIdAndRemove(id, options)  // return Query
      -A.findByIdAndRemove(id, callback) // executes
      -A.findByIdAndRemove(id) // returns Query
      -A.findByIdAndRemove()           // returns Query

      Model.create(doc, fn)

      Shortcut for creating a new Document that is automatically saved to the db if valid.

      show code
      Model.create = function create (doc, fn) {
      -  if (1 === arguments.length) {
      -    return 'function' === typeof doc && doc(null);
      -  }
      -
      -  var self = this
      -    , docs = [null]
      -    , promise
      -    , count
      -    , args
      -
      -  if (Array.isArray(doc)) {
      -    args = doc;
      -  } else {
      -    args = utils.args(arguments, 0, arguments.length - 1);
      -    fn = arguments[arguments.length - 1];
      -  }
      -
      -  if (0 === args.length) return fn(null);
      -
      -  promise = new Promise(fn);
      -  count = args.length;
      -
      -  args.forEach(function (arg, i) {
      -    var doc = new self(arg);
      -    docs[i+1] = doc;
      -    doc.save(function (err) {
      -      if (err) return promise.error(err);
      -      --count || fn.apply(null, docs);
      -    });
      -  });
      -
      -  // TODO
      -  // utilize collection.insertAll for batch processing?
      -};

      Parameters:

      Example:

      - -
      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
      -  if (err) // ...
      -});
      -
      -var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      -Candy.create(array, function (err, jellybean, snickers) {
      -  if (err) // ...
      -});

      Model.update(conditions, update, [options], [callback])

      Updates documents in the database without returning them.

      show code
      Model.update = function update (conditions, doc, options, callback) {
      -  if (arguments.length < 4) {
      -    if ('function' === typeof options) {
      -      // Scenario: update(conditions, doc, callback)
      -      callback = options;
      -      options = null;
      -    } else if ('function' === typeof doc) {
      -      // Scenario: update(doc, callback);
      -      callback = doc;
      -      doc = conditions;
      -      conditions = {};
      -      options = null;
      -    }
      -  }
      -
      -  var query = new Query(conditions, options).bind(this, 'update', doc);
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.update(doc, callback);
      -};

      Parameters:

      Returns:

      Examples:

      - -
      MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
      -MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
      -  if (err) return handleError(err);
      -  console.log('The number of updated documents was %d', numberAffected);
      -  console.log('The raw response from Mongo was ', raw);
      -});
      - -

      Valid options:

      - -
        -
      • safe (boolean) safe mode (defaults to value set in schema (true))
      • -
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • -
      • multi (boolean) whether multiple documents should be updated (false)
      • -
      - -

      All update values are cast to their appropriate SchemaTypes before being sent.

      - -

      The callback function receives (err, numberAffected, rawResponse).

      - -
        -
      • err is the error if any occurred
      • -
      • numberAffected is the count of updated documents Mongo reported
      • -
      • rawResponse is the full response from Mongo
      • -
      - -

      Note:

      - -

      All top level keys which are not atomic operation names are treated as set operations:

      - -

      Example:

      - -
      var query = { name: 'borne' };
      -Model.update(query, { name: 'jason borne' }, options, callback)
      -
      -// is sent as
      -Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
      - -

      This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

      - -

      Note:

      - -

      To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      - -
      Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
      - -

      Note:

      - -

      Although values are casted to their appropriate types when using update, the following are not applied:

      - -
        -
      • defaults
      • -
      • setters
      • -
      • validators
      • -
      • middleware
      • -
      - -

      If you need those features, use the traditional approach of first retrieving the document.

      - -
      Model.findOne({ name: 'borne' }, function (err, doc) {
      -  if (err) ..
      -  doc.name = 'jason borne';
      -  doc.save(callback);
      -})

      Model.mapReduce(o, callback)

      Executes a mapReduce command.

      show code
      Model.mapReduce = function mapReduce (o, callback) {
      -  if ('function' != typeof callback) throw new Error('missing callback');
      -
      -  var self = this;
      -
      -  if (!Model.mapReduce.schema) {
      -    var opts = { noId: true, noVirtualId: true, strict: false }
      -    Model.mapReduce.schema = new Schema({}, opts);
      -  }
      -
      -  if (!o.out) o.out = { inline: 1 };
      -
      -  o.map = String(o.map);
      -  o.reduce = String(o.reduce);
      -
      -  if (o.query) {
      -    var q = new Query(o.query);
      -    q.cast(this);
      -    o.query = q._conditions;
      -    q = undefined;
      -  }
      -
      -  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
      -    if (err) return callback(err);
      -
      -    if (ret.findOne && ret.mapReduce) {
      -      // returned a collection, convert to Model
      -      var model = Model.compile(
      -          '_mapreduce_' + ret.collectionName
      -        , Model.mapReduce.schema
      -        , ret.collectionName
      -        , self.db
      -        , self.base);
      -
      -      model._mapreduce = true;
      -
      -      return callback(err, model, stats);
      -    }
      -
      -    callback(err, ret, stats);
      -  });
      -}

      Parameters:

      • o <Object> an object specifying map-reduce options
      • callback <Function>

      o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

      - -

      Example:

      - -
      var o = {};
      -o.map = function () { emit(this.name, 1) }
      -o.reduce = function (k, vals) { return vals.length }
      -User.mapReduce(o, function (err, results) {
      -  console.log(results)
      -})
      - -

      Other options:

      - -
        -
      • query {Object} query filter object.
      • -
      • limit {Number} max number of documents
      • -
      • keeptemp {Boolean, default:false} keep temporary data
      • -
      • finalize {Function} finalize function
      • -
      • scope {Object} scope variables exposed to map/reduce/finalize during execution
      • -
      • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
      • -
      • verbose {Boolean, default:false} provide statistics on job execution time.
      • -
      • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
      • -
      - -

      * out options:

      - -
        -
      • {inline:1} the results are returned in an array
      • -
      • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
      • -
      • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
      • -
      • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
      • -
      - -

      If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

      - -

      Example:

      - -
      var o = {};
      -o.map = function () { emit(this.name, 1) }
      -o.reduce = function (k, vals) { return vals.length }
      -o.out = { replace: 'createdCollectionNameForResults' }
      -o.verbose = true;
      -User.mapReduce(o, function (err, model, stats) {
      -  console.log('map reduce took %d ms', stats.processtime)
      -  model.find().where('value').gt(10).exec(function (err, docs) {
      -    console.log(docs);
      -  });
      -})

      Model.aggregate(array, [options], callback)

      Executes an aggregate command on this models collection.

      show code
      Model.aggregate = function aggregate () {
      -  return this.collection.aggregate.apply(this.collection, arguments);
      -}

      Parameters:

      Example:

      - -
      // find the max age of all users
      -Users.aggregate(
      -    { $group: { _id: null, maxAge: { $max: '$age' }}}
      -  , { $project: { _id: 0, maxAge: 1 }}
      -  , function (err, res) {
      -  if (err) return handleError(err);
      -  console.log(res); // [ { maxAge: 98 } ]
      -});
      - -

      NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

      - -

      NOTE: this requires running MongoDB >= 2.1


      Model#base

      Base Mongoose instance the model uses.


      Model#collection

      Collection the model uses.


      Model#db

      Database instance the model uses.


      Model#schema

      Schema the model uses.


      Model#modelName

      The name of the model


      Model#collection

      Collection the model uses.


      Model#db

      Connection the model uses.


    • namedscope.js

      NamedScope#decorate(target, getters)

      Decorate

      show code
      NamedScope.prototype.decorate = function (target, getters) {
      -  var name = this.name
      -    , block = this.block
      -    , query = this.query;
      -  if (block) {
      -    if (block.length === 0) {
      -      Object.defineProperty(target, name, {
      -        get: getters.block0(block)
      -      });
      -    } else {
      -      target[name] = getters.blockN(block);
      -    }
      -  } else {
      -    Object.defineProperty(target, name, {
      -      get: getters.basic(query)
      -    });
      -  }
      -};
      -
      -NamedScope.prototype.compile = function (model) {
      -  var allScopes = this.scopesByName
      -    , scope;
      -  for (var k in allScopes) {
      -    scope = allScopes[k];
      -    scope.decorate(model, {
      -      block0: function (block) {
      -        return function () {
      -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      -          block.call(cquery);
      -          return this;
      -        };
      -      },
      -      blockN: function (block) {
      -        return function () {
      -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      -          block.apply(cquery, arguments);
      -          return this;
      -        };
      -      },
      -      basic: function (query) {
      -        return function () {
      -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      -          cquery.find(query);
      -          return this;
      -        };
      -      }
      -    });
      -  }
      -};
      -
      -module.exports = NamedScope;

      Parameters:


    • promise.js

      Promise(back)

      Promise constructor.

      show code
      function Promise (back) {
      -  this.emitted = {};
      -  if ('function' == typeof back)
      -    this.addBack(back);
      -};

      Parameters:

      • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

      Events:

      • err: Emits when the promise resolves to an error.

      • complete: Emits when the promise resolves sucessfully.


      Promise#on(event, callback)

      Adds listener to the event.

      show code
      Promise.prototype.on = function (event, callback) {
      -  if (this.emitted[event])
      -    callback.apply(this, this.emitted[event]);
      -  else
      -    EventEmitter.prototype.on.call(this, event, callback);
      -
      -  return this;
      -};

      Parameters:

      Returns:

      If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


      Promise#emit()

      Keeps track of emitted events to run them on on.

      show code
      Promise.prototype.emit = function (event) {
      -  // ensures a promise can't be complete() or error() twice
      -  if (event == 'err' || event == 'complete'){
      -    if (this.emitted.err || this.emitted.complete) {
      -      return this;
      -    }
      -    this.emitted[event] = util.args(arguments, 1);
      -  }
      -
      -  return EventEmitter.prototype.emit.apply(this, arguments);
      -};

      Promise#complete()

      Shortcut for emitting the complete event.

      show code
      Promise.prototype.complete = function () {
      -  var args = util.args(arguments);
      -  return this.emit.apply(this, ['complete'].concat(args));
      -};

      Promise#error()

      Shortcut for emitting the err event.

      show code
      Promise.prototype.error = function (err) {
      -  if (!(err instanceof Error)) err = new Error(err);
      -  return this.emit('err', err);
      -};

      Returns:


      Promise#addCallback()

      Shortcut for .on('complete', fn).

      show code
      Promise.prototype.addCallback = function (fn) {
      -  return this.on('complete', fn);
      -};

      Returns:


      Promise#addErrback()

      Shortcut for .on('err', fn).

      show code
      Promise.prototype.addErrback = function (fn) {
      -  return this.on('err', fn);
      -};

      Returns:


      Promise#addBack(fn)

      Adds a single function that's both a callback and errback.

      show code
      Promise.prototype.addBack = function (fn) {
      -  this.on('err', function(err){
      -    fn.call(this, err);
      -  });
      -
      -  this.on('complete', function(){
      -    var args = util.args(arguments);
      -    fn.apply(this, [null].concat(args));
      -  });
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Promise#resolve(err, val)

      Sugar for handling cases where you may be resolving to either an error condition or a success condition.

      show code
      Promise.prototype.resolve = function (err, val) {
      -  if (err) return this.error(err);
      -  return this.complete(val);
      -};

      Parameters:

      • err <Error> optional error or null
      • val <Object> value to complete the promise with

    • query.js

      Query(criteria, options)

      Query constructor used for building queries.

      show code
      function Query (criteria, options) {
      -  this.setOptions(options, true);
      -  this._conditions = {};
      -  this._updateArg = {};
      -  this._fields = undefined;
      -  if (criteria) this.find(criteria);
      -}

      Parameters:

      Example:

      - -
      var query = Model.find();
      -query.where('age').gte(21).exec(callback);

      Query#setOptions(options)

      Sets query options.

      show code
      Query.prototype.setOptions = function (options, overwrite) {
      -  // overwrite is internal use only
      -  if (overwrite) {
      -    options = this.options = options || {};
      -    this.safe = options.safe
      -
      -    // normalize population options
      -    var pop = this.options.populate;
      -    this.options.populate = {};
      -
      -    if (pop && Array.isArray(pop)) {
      -      for (var i = 0, l = pop.length; i < l; i++) {
      -        this.options.populate[pop[i]] = {};
      -      }
      -    }
      -
      -    return this;
      -  }
      -
      -  if (!(options && 'Object' == options.constructor.name))
      -    return this;
      -
      -  if ('safe' in options)
      -    this.safe = options.safe;
      -
      -  // set arbitrary options
      -  var methods = Object.keys(options)
      -    , i = methods.length
      -    , method
      -
      -  while (i--) {
      -    method = methods[i];
      -
      -    // use methods if exist (safer option manipulation)
      -    if ('function' == typeof this[method]) {
      -      var args = Array.isArray(options[method])
      -        ? options[method]
      -        : [options[method]];
      -      this[method].apply(this, args)
      -    } else {
      -      this.options[method] = options[method];
      -    }
      -  }
      -  return this;
      -}

      Parameters:

      Options:

      - - - -

      * denotes a query helper method is also available


      Query#bind(model, op, updateArg)

      Binds this query to a model.

      show code
      Query.prototype.bind = function bind (model, op, updateArg) {
      -  this.model = model;
      -  this.op = op;
      -
      -  if (model._mapreduce) this.options.lean = true;
      -
      -  if (op == 'update' || op == 'findOneAndUpdate') {
      -    merge(this._updateArg, updateArg || {});
      -  }
      -
      -  return this;
      -};

      Parameters:

      • model <Model> the model to which the query is bound
      • op <String> the operation to execute
      • updateArg <Object> used in update methods

      Returns:


      Query#exec([operation], [callback])

      Executes the query

      show code
      Query.prototype.exec = function exec (op, callback) {
      -  var promise = new Promise();
      -
      -  switch (typeof op) {
      -    case 'function':
      -      callback = op;
      -      op = null;
      -      break;
      -    case 'string':
      -      this.op = op;
      -      break;
      -  }
      -
      -  if (callback) promise.addBack(callback);
      -
      -  if (!this.op) {
      -    promise.complete();
      -    return promise;
      -  }
      -
      -  if ('update' == this.op) {
      -    this[this.op](this._updateArg, promise.resolve.bind(promise));
      -    return promise;
      -  }
      -
      -  if ('distinct' == this.op) {
      -    this.distinct(this._distinctArg, promise.resolve.bind(promise));
      -    return promise;
      -  }
      -
      -  this[this.op](promise.resolve.bind(promise));
      -  return promise;
      -};

      Parameters:

      Returns:

      Examples

      - -
      query.exec();
      -query.exec(callback);
      -query.exec('update');
      -query.exec('find', callback);

      Query#find([criteria], [callback])

      Finds documents.

      show code
      Query.prototype.find = function (criteria, callback) {
      -  this.op = 'find';
      -  if ('function' === typeof criteria) {
      -    callback = criteria;
      -    criteria = {};
      -  } else if (criteria instanceof Query) {
      -    // TODO Merge options, too
      -    merge(this._conditions, criteria._conditions);
      -  } else if (criteria instanceof Document) {
      -    merge(this._conditions, criteria.toObject());
      -  } else if (criteria && 'Object' === criteria.constructor.name) {
      -    merge(this._conditions, criteria);
      -  }
      -  if (!callback) return this;
      -  return this.execFind(callback);
      -};

      Parameters:

      Returns:

      When no callback is passed, the query is not executed.

      - -

      Example

      - -
      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

      Query#cast(model, [obj])

      Casts this query to the schema of model

      show code
      Query.prototype.cast = function (model, obj) {
      -  obj || (obj= this._conditions);
      -
      -  var schema = model.schema
      -    , paths = Object.keys(obj)
      -    , i = paths.length
      -    , any$conditionals
      -    , schematype
      -    , nested
      -    , path
      -    , type
      -    , val;
      -
      -  while (i--) {
      -    path = paths[i];
      -    val = obj[path];
      -
      -    if ('$or' === path || '$nor' === path) {
      -      var k = val.length
      -        , orComponentQuery;
      -
      -      while (k--) {
      -        orComponentQuery = new Query(val[k]);
      -        orComponentQuery.cast(model);
      -        val[k] = orComponentQuery._conditions;
      -      }
      -
      -    } else if (path === '$where') {
      -      type = typeof val;
      -
      -      if ('string' !== type && 'function' !== type) {
      -        throw new Error("Must have a string or function for $where");
      -      }
      -
      -      if ('function' === type) {
      -        obj[path] = val.toString();
      -      }
      -
      -      continue;
      -
      -    } else {
      -
      -      if (!schema) {
      -        // no casting for Mixed types
      -        continue;
      -      }
      -
      -      schematype = schema.path(path);
      -
      -      if (!schematype) {
      -        // Handle potential embedded array queries
      -        var split = path.split('.')
      -          , j = split.length
      -          , pathFirstHalf
      -          , pathLastHalf
      -          , remainingConds
      -          , castingQuery;
      -
      -        // Find the part of the var path that is a path of the Schema
      -        while (j--) {
      -          pathFirstHalf = split.slice(0, j).join('.');
      -          schematype = schema.path(pathFirstHalf);
      -          if (schematype) break;
      -        }
      -
      -        // If a substring of the input path resolves to an actual real path...
      -        if (schematype) {
      -          // Apply the casting; similar code for $elemMatch in schema/array.js
      -          if (schematype.caster && schematype.caster.schema) {
      -            remainingConds = {};
      -            pathLastHalf = split.slice(j).join('.');
      -            remainingConds[pathLastHalf] = val;
      -            castingQuery = new Query(remainingConds);
      -            castingQuery.cast(schematype.caster);
      -            obj[path] = castingQuery._conditions[pathLastHalf];
      -          } else {
      -            obj[path] = val;
      -          }
      -        }
      -
      -      } else if (val === null || val === undefined) {
      -        continue;
      -      } else if ('Object' === val.constructor.name) {
      -
      -        any$conditionals = Object.keys(val).some(function (k) {
      -          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
      -        });
      -
      -        if (!any$conditionals) {
      -          obj[path] = schematype.castForQuery(val);
      -        } else {
      -
      -          var ks = Object.keys(val)
      -            , k = ks.length
      -            , $cond;
      -
      -          while (k--) {
      -            $cond = ks[k];
      -            nested = val[$cond];
      -
      -            if ('$exists' === $cond) {
      -              if ('boolean' !== typeof nested) {
      -                throw new Error("$exists parameter must be Boolean");
      -              }
      -              continue;
      -            }
      -
      -            if ('$type' === $cond) {
      -              if ('number' !== typeof nested) {
      -                throw new Error("$type parameter must be Number");
      -              }
      -              continue;
      -            }
      -
      -            if ('$not' === $cond) {
      -              this.cast(model, nested);
      -            } else {
      -              val[$cond] = schematype.castForQuery($cond, nested);
      -            }
      -          }
      -        }
      -      } else {
      -        obj[path] = schematype.castForQuery(val);
      -      }
      -    }
      -  }
      -
      -  return obj;
      -};

      Parameters:

      Returns:

      Note

      - -

      If obj is present, it is cast instead of this query.


      Query#_optionsForExec(model)

      Returns default options.

      show code
      Query.prototype._optionsForExec = function (model) {
      -  var options = utils.clone(this.options, { retainKeyOrder: true });
      -  delete options.populate;
      -
      -  if (!('safe' in options))
      -    options.safe = model.schema.options.safe;
      -
      -  if (!('readPreference' in options) && model.schema.options.read)
      -    options.readPreference = model.schema.options.read;
      -
      -  return options;
      -};

      Parameters:


      Query#_applyPaths()

      Applies schematype selected options to this query.

      show code
      Query.prototype._applyPaths = function applyPaths () {
      -  // determine if query is selecting or excluding fields
      -
      -  var fields = this._fields
      -    , exclude
      -    , keys
      -    , ki
      -
      -  if (fields) {
      -    keys = Object.keys(fields);
      -    ki = keys.length;
      -
      -    while (ki--) {
      -      if ('+' == keys[ki][0]) continue;
      -      exclude = 0 === fields[keys[ki]];
      -      break;
      -    }
      -  }
      -
      -  // if selecting, apply default schematype select:true fields
      -  // if excluding, apply schematype select:false fields
      -
      -  var selected = []
      -    , excluded = []
      -    , seen = [];
      -
      -  analyzeSchema(this.model.schema);
      -
      -  switch (exclude) {
      -    case true:
      -      excluded.length && this.select('-' + excluded.join(' -'));
      -      break;
      -    case false:
      -      selected.length && this.select(selected.join(' '));
      -      break;
      -    case undefined:
      -      // user didn't specify fields, implies returning all fields.
      -      // only need to apply excluded fields
      -      excluded.length && this.select('-' + excluded.join(' -'));
      -      break;
      -  }
      -
      -  return seen = excluded = selected = keys = fields = null;
      -
      -  function analyzeSchema (schema, prefix) {
      -    prefix || (prefix = '');
      -
      -    // avoid recursion
      -    if (~seen.indexOf(schema)) return;
      -    seen.push(schema);
      -
      -    schema.eachPath(function (path, type) {
      -      if (prefix) path = prefix + '.' + path;
      -
      -      // array of subdocs?
      -      if (type.schema) {
      -        analyzeSchema(type.schema, path);
      -      }
      -
      -      analyzePath(path, type);
      -    });
      -  }
      -
      -  function analyzePath (path, type) {
      -    if ('boolean' != typeof type.selected) return;
      -
      -    if (fields && ('+' + path) in fields) {
      -      // forced inclusion
      -      delete fields['+' + path];
      -
      -      // if there are other fields being included, add this one
      -      // if no other included fields, leave this out (implied inclusion)
      -      if (false === exclude && keys.length > 1) {
      -        fields[path] = 1;
      -      }
      -
      -      return
      -    };
      -
      -    ;(type.selected ? selected : excluded).push(path);
      -  }
      -}

      Query#$where(js)

      Specifies a $where condition

      Parameters:

      Returns:

      Use $where when you need to select documents using a JavaScript expression.

      - -

      Example

      - -
      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
      -
      -query.$where(function () {
      -  return this.comments.length &gt; 10 || this.name.length &gt; 5;
      -})

      Query#where([path], [val])

      Specifies a path for use with chaining.

      show code
      Query.prototype.where = function (path, val) {
      -  if (!arguments.length) return this;
      -
      -  if ('string' != typeof path) {
      -    throw new TypeError('path must be a string');
      -  }
      -
      -  this._currPath = path;
      -
      -  if (2 === arguments.length) {
      -    this._conditions[path] = val;
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      // instead of writing:
      -User.find({age: {$gte: 21, $lte: 65}}, callback);
      -
      -// we can instead write:
      -User.where('age').gte(21).lte(65);
      -
      -// Moreover, you can also chain a bunch of these together:
      -
      -User
      -.where('age').gte(21).lte(65)
      -.where('name', /^b/i)
      -.where('friends').slice(10)
      -.exec(callback)

      Query#equals(val)

      Specifies the complementary comparison value for paths specified with where()

      show code
      Query.prototype.equals = function equals (val) {
      -  var path = this._currPath;
      -  if (!path) throw new Error('equals() must be used after where()');
      -  this._conditions[path] = val;
      -  return this;
      -}

      Parameters:

      Returns:

      Example

      - -
      User.where('age').equals(49);
      -
      -// is the same as
      -
      -User.where('age', 49);

      Query#or(array)

      Specifies arguments for an $or condition.

      show code
      Query.prototype.or = function or (array) {
      -  var or = this._conditions.$or || (this._conditions.$or = []);
      -  if (!Array.isArray(array)) array = [array];
      -  or.push.apply(or, array);
      -  return this;
      -}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      - -
      query.or([{ color: 'red' }, { status: 'emergency' }])

      Query#nor(array)

      Specifies arguments for a $nor condition.

      show code
      Query.prototype.nor = function nor (array) {
      -  var nor = this._conditions.$nor || (this._conditions.$nor = []);
      -  if (!Array.isArray(array)) array = [array];
      -  nor.push.apply(nor, array);
      -  return this;
      -}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      - -
      query.nor([{ color: 'green' }, { status: 'ok' }])

      Query#gt(path, val)

      Specifies a $gt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.

      - -

      Example

      - -
      Thing.find().where('age').gt(21)
      -
      -// or
      -Thing.find().gt('age', 21)

      Query#gte(path, val)

      Specifies a $gte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lt(path, val)

      Specifies a $lt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lte(path, val)

      Specifies a $lte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#ne(path, val)

      Specifies a $ne query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#in(path, val)

      Specifies an $in query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#nin(path, val)

      Specifies an $nin query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#all(path, val)

      Specifies an $all query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#size(path, val)

      Specifies an $size query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#regex(path, val)

      Specifies a $regex query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#maxDistance(path, val)

      Specifies a $maxDistance query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#near(path, val)

      Specifies a $near condition

      show code
      Query.prototype.near = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath
      -  } else if (arguments.length === 2 && !Array.isArray(val)) {
      -    val = utils.args(arguments);
      -    path = this._currPath;
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds.$near = val;
      -  return this;
      -}

      Parameters:

      Returns:


      Query#nearSphere(path, val)

      Specifies a $nearSphere condition.

      show code
      Query.prototype.nearSphere = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath
      -  } else if (arguments.length === 2 && !Array.isArray(val)) {
      -    val = utils.args(arguments);
      -    path = this._currPath;
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds.$nearSphere = val;
      -  return this;
      -}

      Parameters:

      Returns:


      Query#mod(path, val)

      Specifies a $mod condition

      show code
      Query.prototype.mod = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath
      -  } else if (arguments.length === 2 && !Array.isArray(val)) {
      -    val = utils.args(arguments);
      -    path = this._currPath;
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds.$mod = val;
      -  return this;
      -}

      Parameters:

      Returns:


      Query#exists(path, val)

      Specifies an $exists condition

      show code
      Query.prototype.exists = function (path, val) {
      -  if (arguments.length === 0) {
      -    path = this._currPath
      -    val = true;
      -  } else if (arguments.length === 1) {
      -    if ('boolean' === typeof path) {
      -      val = path;
      -      path = this._currPath;
      -    } else {
      -      val = true;
      -    }
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$exists'] = val;
      -  return this;
      -};

      Parameters:

      Returns:


      Query#elemMatch(path, criteria)

      Specifies an $elemMatch condition

      show code
      Query.prototype.elemMatch = function (path, criteria) {
      -  var block;
      -  if ('Object' === path.constructor.name) {
      -    criteria = path;
      -    path = this._currPath;
      -  } else if ('function' === typeof path) {
      -    block = path;
      -    path = this._currPath;
      -  } else if ('Object' === criteria.constructor.name) {
      -  } else if ('function' === typeof criteria) {
      -    block = criteria;
      -  } else {
      -    throw new Error("Argument error");
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  if (block) {
      -    criteria = new Query();
      -    block(criteria);
      -    conds['$elemMatch'] = criteria._conditions;
      -  } else {
      -    conds['$elemMatch'] = criteria;
      -  }
      -  return this;
      -};
      -
      -// Spatial queries

      Parameters:

      Returns:

      Example

      - -
      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
      -
      -query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
      -
      -query.elemMatch('comment', function (elem) {
      -  elem.where('author').equals('autobot');
      -  elem.where('votes').gte(5);
      -})
      -
      -query.where('comment').elemMatch(function (elem) {
      -  elem.where('author').equals('autobot');
      -  elem.where('votes').gte(5);
      -})

      Query#box(path, val)

      Specifies a $box condition

      show code
      Query.prototype.box = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$box': [val.ll, val.ur]  };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var lowerLeft = [40.73083, -73.99756]
      -var upperRight= [40.741404,  -73.988135]
      -query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

      Query#center(path, val, [opts])

      Specifies a $center condition

      show code
      Query.prototype.center = function (path, val, opts) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$center': [val.center, val.radius]  };
      -
      -  // copy any options
      -  if (opts && 'Object' == opts.constructor.name) {
      -    utils.options(opts, conds.$within);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var area = { center: [50, 50], radius: 10 }
      -query.where('loc').within.center(area)

      Query#centerSphere(path, val)

      Specifies a $centerSphere condition

      show code
      Query.prototype.centerSphere = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var area = { center: [50, 50], radius: 10 }
      -query.where('loc').within.centerSphere(area)

      Query#polygon(path, val)

      Specifies a $polygon condition

      show code
      Query.prototype.polygon = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$polygon': val };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      -query.where('loc').within.polygon(polyA)
      -
      -// or
      -var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      -query.where('loc').within.polygon(polyB)

      Query#select(arg)

      Specifies which document fields to include or exclude

      show code
      Query.prototype.select = function select (arg) {
      -  if (!arg) return this;
      -
      -  var fields = this._fields || (this._fields = {});
      -
      -  if ('Object' === arg.constructor.name) {
      -    Object.keys(arg).forEach(function (field) {
      -      fields[field] = arg[field];
      -    });
      -  } else if (1 === arguments.length && 'string' == typeof arg) {
      -    arg.split(/\s+/).forEach(function (field) {
      -      if (!field) return;
      -      var include = '-' == field[0] ? 0 : 1;
      -      if (include === 0) field = field.substring(1);
      -      fields[field] = include;
      -    });
      -  } else {
      -    throw new TypeError('Invalid select() argument. Must be a string or object.');
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

      - -

      Example

      - -
      // include a and b, exclude c
      -query.select('a b -c');
      -
      -// or you may use object notation, useful when
      -// you have keys already prefixed with a "-"
      -query.select({a: 1, b: 1, c: 0});
      -
      -// force inclusion of field excluded at schema level
      -query.select('+path')
      - -

      NOTE:

      - -

      v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


      Query#slice(path, val)

      Specifies a $slice condition

      show code
      Query.prototype.slice = function (path, val) {
      -  if (arguments.length === 1) {
      -      val = path;
      -      path = this._currPath
      -  } else if (arguments.length === 2) {
      -    if ('number' === typeof path) {
      -      val = [path, val];
      -      path = this._currPath;
      -    }
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var myFields = this._fields || (this._fields = {});
      -  myFields[path] = { '$slice': val };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      query.slice('comments', 5)
      -query.slice('comments', -5)
      -query.slice('comments', [10, 5])
      -query.where('comments').slice(5)
      -query.where('comments').slice([-10, 5])

      Query#sort(arg)

      Sets the sort order

      show code
      Query.prototype.sort = function (arg) {
      -  if (!arg) return this;
      -
      -  var sort = this.options.sort || (this.options.sort = []);
      -
      -  if ('Object' === arg.constructor.name) {
      -    Object.keys(arg).forEach(function (field) {
      -      push(sort, field, arg[field]);
      -    });
      -  } else if (1 === arguments.length && 'string' == typeof arg) {
      -    arg.split(/\s+/).forEach(function (field) {
      -      if (!field) return;
      -      var ascend = '-' == field[0] ? -1 : 1;
      -      if (ascend === -1) field = field.substring(1);
      -      push(sort, field, ascend);
      -    });
      -  } else {
      -    throw new TypeError('Invalid sort() argument. Must be a string or object.');
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

      - -

      If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

      - -

      Example

      - -
      // these are equivalent
      -query.sort({ field: 'asc', test: -1 });
      -query.sort('field -test');

      Query#limit(val)

      Specifies the limit option.

      Parameters:

      Example

      - -
      Kitten.find().limit(20)

      Query#skip(val)

      Specifies the skip option.

      Parameters:

      Example

      - -
      Kitten.find().skip(100).limit(20)

      Query#maxscan(val)

      Specifies the maxscan option.

      Parameters:

      Example

      - -
      Kitten.find().maxscan(100)

      Query#batchSize(val)

      Specifies the batchSize option.

      Parameters:

      Example

      - -
      Kitten.find().batchSize(100)

      Query#comment(val)

      Specifies the comment option.

      Parameters:

      Example

      - -
      Kitten.findOne(condition).comment('login query')

      Query#snapshot()

      Specifies this query as a snapshot query.

      show code
      Query.prototype.snapshot = function () {
      -  this.options.snapshot = true;
      -  return this;
      -};

      Returns:

      Example

      - -
      Kitten.find().snapshot()

      Query#hint(val)

      Sets query hints.

      show code
      Query.prototype.hint = function (val) {
      -  if (!val) return this;
      -
      -  var hint = this.options.hint || (this.options.hint = {});
      -
      -  if ('Object' === val.constructor.name) {
      -    // must keep object keys in order so don't use Object.keys()
      -    for (var k in val) {
      -      hint[k] = val[k];
      -    }
      -  } else {
      -    throw new TypeError('Invalid hint. ' + val);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      Model.find().hint({ indexA: 1, indexB: -1})

      Query#slaveOk(v)

      Sets the slaveOk option.

      show code
      Query.prototype.slaveOk = function (v) {
      -  this.options.slaveOk = arguments.length ? !!v : true;
      -  return this;
      -}

      Parameters:

      Returns:

      Example:

      - -
      new Query().slaveOk() // true
      -new Query().slaveOk(true)
      -new Query().slaveOk(false)

      Query#read(pref, [tags])

      Sets the readPreference option for the query.

      show code
      Query.prototype.read = function (pref, tags) {
      -  this.options.readPreference = utils.readPref(pref, tags);
      -  return this;
      -}

      Parameters:

      • pref <String> one of the listed preference options or their aliases
      • [tags] <Array> optional tags for this query

      Returns:

      Example:

      - -
      new Query().read('primary')
      -new Query().read('p')  // same as primary
      -
      -new Query().read('primaryPreferred')
      -new Query().read('pp') // same as primaryPreferred
      -
      -new Query().read('secondary')
      -new Query().read('s')  // same as secondary
      -
      -new Query().read('secondaryPreferred')
      -new Query().read('sp') // same as secondaryPreferred
      -
      -new Query().read('nearest')
      -new Query().read('n')  // same as nearest
      -
      -// with tags
      -new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
      - -

      Preferences:

      - -
      primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
      -secondary            Read from secondary if available, otherwise error.
      -primaryPreferred     Read from primary if available, otherwise a secondary.
      -secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
      -nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
      - -

      Aliases

      - -
      p   primary
      -pp  primaryPreferred
      -s   secondary
      -sp  secondaryPreferred
      -n   nearest
      - -

      Read more about how to use read preferrences here and here.


      Query#lean(v)

      Sets the lean option.

      show code
      Query.prototype.lean = function (v) {
      -  this.options.lean = arguments.length ? !!v : true;
      -  return this;
      -}

      Parameters:

      Returns:

      Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

      - -

      This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

      - -

      Example:

      - -
      new Query().lean() // true
      -new Query().lean(true)
      -new Query().lean(false)
      -
      -Model.find().lean().exec();
      -
      -var leanStream = Model.find().lean().stream();

      Query#tailable(v)

      Sets tailable option.

      show code
      Query.prototype.tailable = function (v) {
      -  this.options.tailable = arguments.length ? !!v : true;
      -  return this;
      -};

      Parameters:

      Example

      - -
      Kitten.find().tailable() &lt;== true
      -Kitten.find().tailable(true)
      -Kitten.find().tailable(false)

      Query#execFind(callback)

      Executes the query as a find() operation.

      show code
      Query.prototype.execFind = function (callback) {
      -  var model = this.model
      -    , promise = new Promise(callback);
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    promise.error(err);
      -    return this;
      -  }
      -
      -  // apply default schematype path selections
      -  this._applyPaths();
      -
      -  var self = this
      -    , castQuery = this._conditions
      -    , options = this._optionsForExec(model)
      -    , fields = utils.clone(this._fields)
      -
      -  options.fields = this._castFields(fields);
      -  if (options.fields instanceof Error) {
      -    promise.error(options.fields);
      -    return this;
      -  }
      -
      -  model.collection.find(castQuery, options, function (err, cursor) {
      -    if (err) return promise.error(err);
      -    cursor.toArray(tick(cb));
      -  });
      -
      -  function cb (err, docs) {
      -    if (err) return promise.error(err);
      -
      -    if (true === options.lean)
      -      return promise.complete(docs);
      -
      -    var arr = []
      -      , count = docs.length;
      -
      -    if (!count) return promise.complete([]);
      -
      -    for (var i = 0, l = docs.length; i < l; i++) {
      -      arr[i] = new model(undefined, fields, true);
      -      arr[i].init(docs[i], self, function (err) {
      -        if (err) return promise.error(err);
      -        --count || promise.complete(arr);
      -      });
      -    }
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Query#findOne(callback)

      Executes the query as a findOne() operation.

      show code
      Query.prototype.findOne = function (callback) {
      -  this.op = 'findOne';
      -
      -  if (!callback) return this;
      -
      -  var model = this.model;
      -  var promise = new Promise(callback);
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    promise.error(err);
      -    return this;
      -  }
      -
      -  // apply default schematype path selections
      -  this._applyPaths();
      -
      -  var self = this
      -    , castQuery = this._conditions
      -    , options = this._optionsForExec(model)
      -    , fields = utils.clone(this._fields)
      -
      -  options.fields = this._castFields(fields);
      -  if (options.fields instanceof Error) {
      -    promise.error(options.fields);
      -    return this;
      -  }
      -
      -  model.collection.findOne(castQuery, options, tick(function (err, doc) {
      -    if (err) return promise.error(err);
      -    if (!doc) return promise.complete(null);
      -
      -    if (true === options.lean) return promise.complete(doc);
      -
      -    var casted = new model(undefined, fields, true);
      -    casted.init(doc, self, function (err) {
      -      if (err) return promise.error(err);
      -      promise.complete(casted);
      -    });
      -  }));
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      Kitten.where('color', 'white').findOne(function (err, kitten) {
      -  if (err) return handleError(err);
      -
      -  // kitten may be null if no document matched
      -  if (kitten) {
      -    ...
      -  }
      -})

      Query#count(callback)

      Exectues the query as a count() operation.

      show code
      Query.prototype.count = function (callback) {
      -  this.op = 'count';
      -  var model = this.model;
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    return callback(err);
      -  }
      -
      -  var castQuery = this._conditions;
      -  model.collection.count(castQuery, tick(callback));
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      Kitten.where('color', 'black').count(function (err, count) {
      -  if (err) return handleError(err);
      -  console.log('there are %d black kittens', count);
      -})

      Query#distinct(field, callback)

      Executes this query as a distict() operation.

      show code
      Query.prototype.distinct = function (field, callback) {
      -  this.op = 'distinct';
      -  var model = this.model;
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    return callback(err);
      -  }
      -
      -  var castQuery = this._conditions;
      -  model.collection.distinct(field, castQuery, tick(callback));
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Query#update(doc, callback)

      Executes this query as an update() operation.

      show code
      Query.prototype.update = function update (doc, callback) {
      -  this.op = 'update';
      -  this._updateArg = doc;
      -
      -  var model = this.model
      -    , options = this._optionsForExec(model)
      -    , fn = 'function' == typeof callback
      -    , castedQuery
      -    , castedDoc
      -
      -  castedQuery = castQuery(this);
      -  if (castedQuery instanceof Error) {
      -    if (fn) {
      -      process.nextTick(callback.bind(null, castedQuery));
      -      return this;
      -    }
      -    throw castedQuery;
      -  }
      -
      -  castedDoc = castDoc(this);
      -  if (!castedDoc) {
      -    fn && process.nextTick(callback.bind(null, null, 0));
      -    return this;
      -  }
      -
      -  if (castedDoc instanceof Error) {
      -    if (fn) {
      -      process.nextTick(callback.bind(null, castedDoc));
      -      return this;
      -    }
      -    throw castedDoc;
      -  }
      -
      -  if (!fn) {
      -    delete options.safe;
      -  }
      -
      -  model.collection.update(castedQuery, castedDoc, options, tick(callback));
      -  return this;
      -};

      Parameters:

      Returns:

      All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

      - -

      Example

      - -
      Model.update({..}, { title: 'remove words' }, ...)
      - -

      becomes

      - -
      Model.update({..}, { $set: { title: 'remove words' }}, ...)
      - -

      Note

      - -

      Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


      Query#_castUpdate(obj)

      Casts obj for an update command.

      show code
      Query.prototype._castUpdate = function _castUpdate (obj) {
      -  var ops = Object.keys(obj)
      -    , i = ops.length
      -    , ret = {}
      -    , hasKeys
      -    , val
      -
      -  while (i--) {
      -    var op = ops[i];
      -    if ('$' !== op[0]) {
      -      // fix up $set sugar
      -      if (!ret.$set) {
      -        if (obj.$set) {
      -          ret.$set = obj.$set;
      -        } else {
      -          ret.$set = {};
      -        }
      -      }
      -      ret.$set[op] = obj[op];
      -      ops.splice(i, 1);
      -      if (!~ops.indexOf('$set')) ops.push('$set');
      -    } else if ('$set' === op) {
      -      if (!ret.$set) {
      -        ret[op] = obj[op];
      -      }
      -    } else {
      -      ret[op] = obj[op];
      -    }
      -  }
      -
      -  // cast each value
      -  i = ops.length;
      -
      -  while (i--) {
      -    op = ops[i];
      -    val = ret[op];
      -    if ('Object' === val.constructor.name) {
      -      hasKeys |= this._walkUpdatePath(val, op);
      -    } else {
      -      var msg = 'Invalid atomic update value for ' + op + '. '
      -              + 'Expected an object, received ' + typeof val;
      -      throw new Error(msg);
      -    }
      -  }
      -
      -  return hasKeys && ret;
      -}

      Parameters:

      Returns:

      • <Object> obj after casting its values

      Query#_walkUpdatePath(obj, op, pref)

      Walk each path of obj and cast its values
      according to its schema.

      show code
      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
      -  var strict = this.model.schema.options.strict
      -    , prefix = pref ? pref + '.' : ''
      -    , keys = Object.keys(obj)
      -    , i = keys.length
      -    , hasKeys = false
      -    , schema
      -    , key
      -    , val
      -
      -  while (i--) {
      -    key = keys[i];
      -    val = obj[key];
      -
      -    if (val && 'Object' === val.constructor.name) {
      -      // watch for embedded doc schemas
      -      schema = this._getSchema(prefix + key);
      -      if (schema && schema.caster && op in castOps) {
      -        // embedded doc schema
      -
      -        if (strict && !schema) {
      -          // path is not in our strict schema
      -          if ('throw' == strict) {
      -            throw new Error('Field `' + key + '` is not in schema.');
      -          } else {
      -            // ignore paths not specified in schema
      -            delete obj[key];
      -          }
      -        } else {
      -          hasKeys = true;
      -          if ('$each' in val) {
      -            obj[key] = {
      -                $each: this._castUpdateVal(schema, val.$each, op)
      -            }
      -          } else {
      -            obj[key] = this._castUpdateVal(schema, val, op);
      -          }
      -        }
      -      } else {
      -        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
      -      }
      -    } else {
      -      schema = '$each' === key
      -        ? this._getSchema(pref)
      -        : this._getSchema(prefix + key);
      -
      -      var skip = strict &&
      -                 !schema &&
      -                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
      -
      -      if (skip) {
      -        if ('throw' == strict) {
      -          throw new Error('Field `' + prefix + key + '` is not in schema.');
      -        } else {
      -          delete obj[key];
      -        }
      -      } else {
      -        hasKeys = true;
      -        obj[key] = this._castUpdateVal(schema, val, op, key);
      -      }
      -    }
      -  }
      -  return hasKeys;
      -}

      Parameters:

      • obj <Object> - part of a query
      • op <String> - the atomic operator ($pull, $set, etc)
      • pref <String> - path prefix (internal only)

      Returns:

      • <Bool> true if this path has keys to update

      Query#_castUpdateVal(schema, val, op, [$conditional])

      Casts val according to schema and atomic op.

      show code
      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
      -  if (!schema) {
      -    // non-existing schema path
      -    return op in numberOps
      -      ? Number(val)
      -      : val
      -  }
      -
      -  if (schema.caster && op in castOps &&
      -    ('Object' === val.constructor.name || Array.isArray(val))) {
      -    // Cast values for ops that add data to MongoDB.
      -    // Ensures embedded documents get ObjectIds etc.
      -    var tmp = schema.cast(val);
      -
      -    if (Array.isArray(val)) {
      -      val = tmp;
      -    } else {
      -      val = tmp[0];
      -    }
      -  }
      -
      -  if (op in numberOps) return Number(val);
      -  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
      -  return schema.castForQuery(val)
      -}

      Parameters:


      Query#_getSchema(path)

      Finds the schema for path. This is different than
      calling schema.path as it also resolves paths with
      positional selectors (something.$.another.$.path).

      show code
      Query.prototype._getSchema = function _getSchema (path) {
      -  var schema = this.model.schema
      -    , pathschema = schema.path(path);
      -
      -  if (pathschema)
      -    return pathschema;
      -
      -  // look for arrays
      -  return (function search (parts, schema) {
      -    var p = parts.length + 1
      -      , foundschema
      -      , trypath
      -
      -    while (p--) {
      -      trypath = parts.slice(0, p).join('.');
      -      foundschema = schema.path(trypath);
      -      if (foundschema) {
      -        if (foundschema.caster) {
      -
      -          // array of Mixed?
      -          if (foundschema.caster instanceof Types.Mixed) {
      -            return foundschema.caster;
      -          }
      -
      -          // Now that we found the array, we need to check if there
      -          // are remaining document paths to look up for casting.
      -          // Also we need to handle array.$.path since schema.path
      -          // doesn't work for that.
      -          if (p !== parts.length) {
      -            if ('$' === parts[p]) {
      -              // comments.$.comments.$.title
      -              return search(parts.slice(p+1), foundschema.schema);
      -            } else {
      -              // this is the last path of the selector
      -              return search(parts.slice(p), foundschema.schema);
      -            }
      -          }
      -        }
      -        return foundschema;
      -      }
      -    }
      -  })(path.split('.'), schema)
      -}

      Parameters:


      Query#_castFields(fields)

      Casts selected field arguments for field selection with mongo 2.2

      show code
      Query.prototype._castFields = function _castFields (fields) {
      -  var selected
      -    , elemMatchKeys
      -    , keys
      -    , key
      -    , out
      -    , i
      -
      -  if (fields) {
      -    keys = Object.keys(fields);
      -    elemMatchKeys = [];
      -    i = keys.length;
      -
      -    // collect $elemMatch args
      -    while (i--) {
      -      key = keys[i];
      -      if (fields[key].$elemMatch) {
      -        selected || (selected = {});
      -        selected[key] = fields[key];
      -        elemMatchKeys.push(key);
      -      }
      -    }
      -  }
      -
      -  if (selected) {
      -    // they passed $elemMatch, cast em
      -    try {
      -      out = this.cast(this.model, selected);
      -    } catch (err) {
      -      return err;
      -    }
      -
      -    // apply the casted field args
      -    i = elemMatchKeys.length;
      -    while (i--) {
      -      key = elemMatchKeys[i];
      -      fields[key] = out[key];
      -    }
      -  }
      -
      -  return fields;
      -}

      Parameters:

      query.select({ ids: { $elemMatch: { $in: [hexString] }})

      Query#remove(callback)

      Executes this query as a remove() operation.

      show code
      Query.prototype.remove = function (callback) {
      -  this.op = 'remove';
      -
      -  var model = this.model
      -    , options = this._optionsForExec(model)
      -    , cb = 'function' == typeof callback
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    if (cb) return callback(err);
      -    throw err;
      -  }
      -
      -  if (!cb) {
      -    delete options.safe;
      -  }
      -
      -  var castQuery = this._conditions;
      -  model.collection.remove(castQuery, options, tick(callback));
      -  return this;
      -};

      Parameters:

      Example

      - -
      Cassette.where('artist').equals('Anne Murray').remove(callback)

      Query#findOneAndUpdate([query], [doc], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
      -  this.op = 'findOneAndUpdate';
      -
      -  switch (arguments.length) {
      -    case 3:
      -      if ('function' == typeof options)
      -        callback = options, options = {};
      -      break;
      -    case 2:
      -      if ('function' == typeof doc) {
      -        callback = doc;
      -        doc = query;
      -        query = undefined;
      -      }
      -      options = undefined;
      -      break;
      -    case 1:
      -      if ('function' == typeof query) {
      -        callback = query;
      -        query = options = doc = undefined;
      -      } else {
      -        doc = query;
      -        query = options = undefined;
      -      }
      -  }
      -
      -  // apply query
      -  if (query) {
      -    if ('Object' === query.constructor.name) {
      -      merge(this._conditions, query);
      -    } else if (query instanceof Query) {
      -      merge(this._conditions, query._conditions);
      -    } else if (query instanceof Document) {
      -      merge(this._conditions, query.toObject());
      -    }
      -  }
      -
      -  // apply doc
      -  if (doc) {
      -    merge(this._updateArg, doc);
      -  }
      -
      -  // apply options
      -  options && this.setOptions(options);
      -
      -  if (!callback) return this;
      -
      -  return this._findAndModify('update', callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Available options

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      - -

      Examples

      - -
      query.findOneAndUpdate(conditions, update, options, callback) // executes
      -query.findOneAndUpdate(conditions, update, options)  // returns Query
      -query.findOneAndUpdate(conditions, update, callback) // executes
      -query.findOneAndUpdate(conditions, update)           // returns Query
      -query.findOneAndUpdate(callback)                     // executes
      -query.findOneAndUpdate()                             // returns Query

      Query#findOneAndRemove([conditions], [options], [callback])

      Issues a mongodb findAndModify remove command.

      show code
      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
      -  this.op = 'findOneAndRemove';
      -
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = undefined;
      -  } else if ('function' == typeof conditions) {
      -    callback = conditions;
      -    conditions = undefined;
      -  }
      -
      -  // apply conditions
      -  if (conditions) {
      -    if ('Object' === conditions.constructor.name) {
      -      merge(this._conditions, conditions);
      -    } else if (conditions instanceof Query) {
      -      merge(this._conditions, conditions._conditions);
      -    } else if (conditions instanceof Document) {
      -      merge(this._conditions, conditions.toObject());
      -    }
      -  }
      -
      -  // apply options
      -  options && this.setOptions(options);
      -
      -  if (!callback) return this;
      -
      -  return this._findAndModify('remove', callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

      - -

      Available options

      - -
        -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      - -

      Examples

      - -
      A.where().findOneAndRemove(conditions, options, callback) // executes
      -A.where().findOneAndRemove(conditions, options)  // return Query
      -A.where().findOneAndRemove(conditions, callback) // executes
      -A.where().findOneAndRemove(conditions) // returns Query
      -A.where().findOneAndRemove(callback)   // executes
      -A.where().findOneAndRemove()           // returns Query

      Query#_findAndModify(type, callback)

      _findAndModify

      show code
      Query.prototype._findAndModify = function (type, callback) {
      -  var model = this.model
      -    , promise = new Promise(callback)
      -    , self = this
      -    , castedQuery
      -    , castedDoc
      -    , fields
      -    , sort
      -    , opts
      -
      -  castedQuery = castQuery(this);
      -  if (castedQuery instanceof Error) {
      -    process.nextTick(promise.error.bind(promise, castedQuery));
      -    return promise;
      -  }
      -
      -  opts = this._optionsForExec(model);
      -
      -  if ('remove' == type) {
      -    opts.remove = true;
      -  } else {
      -    if (!('new' in opts)) opts.new = true;
      -    if (!('upsert' in opts)) opts.upsert = false;
      -
      -    castedDoc = castDoc(this);
      -    if (!castedDoc) {
      -      if (opts.upsert) {
      -        // still need to do the upsert to empty doc
      -        castedDoc = { $set: {} };
      -      } else {
      -        return this.findOne(callback);
      -      }
      -    } else if (castedDoc instanceof Error) {
      -      process.nextTick(promise.error.bind(promise, castedDoc));
      -      return promise;
      -    }
      -  }
      -
      -  this._applyPaths();
      -
      -  if (this._fields) {
      -    fields = utils.clone(this._fields)
      -    opts.fields = this._castFields(fields);
      -    if (opts.fields instanceof Error) {
      -      process.nextTick(promise.error.bind(promise, opts.fields));
      -      return promise;
      -    }
      -  }
      -
      -  // the driver needs a default
      -  sort = opts.sort || [];
      -
      -  model
      -  .collection
      -  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
      -    if (err) return promise.error(err);
      -    if (!doc) return promise.complete(null);
      -
      -    if (true === opts.lean) {
      -      return promise.complete(doc);
      -    }
      -
      -    var casted = new model(undefined, fields, true);
      -    casted.init(doc, self, function (err) {
      -      if (err) return promise.error(err);
      -      promise.complete(casted);
      -    });
      -  }));
      -
      -  return promise;
      -}

      Parameters:


      Query#populate(path, [fields], [model], [conditions], [options])

      Specifies paths which should be populated with other documents.

      show code
      Query.prototype.populate = function (path, fields, model, conditions, options) {
      -  if ('string' !== typeof model) {
      -    options = conditions;
      -    conditions = model;
      -    model = undefined;
      -  }
      -  // The order of fields/conditions args is opposite Model.find but
      -  // necessary to keep backward compatibility (fields could be
      -  // an array, string, or object literal).
      -  this.options.populate[path] =
      -    new PopulateOptions(fields, conditions, options, model);
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

      - -

      Example:

      - -
      Kitten.findOne().populate('owner').exec(function (err, kitten) {
      -  console.log(kitten.owner.name) // Max
      -})

      Query#stream()

      Returns a stream interface

      show code
      Query.prototype.stream = function stream () {
      -  return new QueryStream(this);
      -}
      -
      -// helpers

      Returns:

      Example

      - -
      // follows the nodejs stream api
      -Thing.find({ name: /^hello/ }).stream().pipe(res)
      -
      -// manual streaming
      -var stream = Thing.find({ name: /^hello/ }).stream();
      -
      -stream.on('data', function (doc) {
      -  // do something with the mongoose document
      -}).on('error', function (err) {
      -  // handle the error
      -}).on('close', function () {
      -  // the stream is closed
      -});

      Query#within

      Syntax sugar for expressive queries.

      - -

      Example

      - -
      query.within.box()
      -query.within.center()

      Returns:


    • querystream.js

      QueryStream(query)

      Provides a ReadStream interface for Queries.

      show code
      function QueryStream (query) {
      -  Stream.call(this);
      -
      -  this.query = query;
      -  this.readable = true;
      -  this.paused = false;
      -  this._cursor = null;
      -  this._destroyed = null;
      -  this._fields = null;
      -  this._buffer = null;
      -  this._inline = T_INIT;
      -  this._running = false;
      -
      -  // give time to hook up events
      -  var self = this;
      -  process.nextTick(function () {
      -    self._init();
      -  });
      -}

      Parameters:

      Inherits:

      Events:

      • data: emits a single Mongoose document

      • error: emits when an error occurs during streaming. This will emit before the close event.

      • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

      var stream = Model.find().stream();
      -
      -stream.on('data', function (doc) {
      -  // do something with the mongoose document
      -}).on('error', function (err) {
      -  // handle the error
      -}).on('close', function () {
      -  // the stream is closed
      -});
      - -

      The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

      - -
      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

      QueryStream#_init()

      Initializes the query.

      show code
      QueryStream.prototype._init = function () {
      -  if (this._destroyed) return;
      -
      -  var query = this.query
      -    , model = query.model
      -    , options = query._optionsForExec(model)
      -    , self = this
      -
      -  try {
      -    query.cast(model);
      -  } catch (err) {
      -    return self.destroy(err);
      -  }
      -
      -  self._fields = utils.clone(query._fields);
      -  options.fields = query._castFields(self._fields);
      -
      -  model.collection.find(query._conditions, options, function (err, cursor) {
      -    if (err) return self.destroy(err);
      -    self._cursor = cursor;
      -    self._next();
      -  });
      -}

      QueryStream#_next()

      Trampoline for pulling the next doc from cursor.

      show code
      QueryStream.prototype._next = function _next () {
      -  if (this.paused || this._destroyed) {
      -    return this._running = false;
      -  }
      -
      -  this._running = true;
      -
      -  if (this._buffer && this._buffer.length) {
      -    var arg;
      -    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
      -      this._onNextObject.apply(this, arg);
      -    }
      -  }
      -
      -  // avoid stack overflows with large result sets.
      -  // trampoline instead of recursion.
      -  while (this.__next()) {}
      -}

      QueryStream#__next()

      Pulls the next doc from the cursor.

      show code
      QueryStream.prototype.__next = function () {
      -  if (this.paused || this._destroyed)
      -    return this._running = false;
      -
      -  var self = this;
      -  self._inline = T_INIT;
      -
      -  self._cursor.nextObject(function cursorcb (err, doc) {
      -    self._onNextObject(err, doc);
      -  });
      -
      -  // if onNextObject() was already called in this tick
      -  // return ourselves to the trampoline.
      -  if (T_CONT === this._inline) {
      -    return true;
      -  } else {
      -    // onNextObject() hasn't fired yet. tell onNextObject
      -    // that its ok to call _next b/c we are not within
      -    // the trampoline anymore.
      -    this._inline = T_IDLE;
      -  }
      -}

      QueryStream#_onNextObject(err, doc)

      Transforms raw docs returned from the cursor into a model instance.

      show code
      QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
      -  if (this._destroyed) return;
      -
      -  if (this.paused) {
      -    this._buffer || (this._buffer = []);
      -    this._buffer.push([err, doc]);
      -    return this._running = false;
      -  }
      -
      -  if (err) return this.destroy(err);
      -
      -  // when doc is null we hit the end of the cursor
      -  if (!doc) {
      -    this.emit('end');
      -    return this.destroy();
      -  }
      -
      -  if (this.query.options && true === this.query.options.lean)  {
      -    this.emit('data', doc);
      -
      -    // trampoline management
      -    if (T_IDLE === this._inline) {
      -      // no longer in trampoline. restart it.
      -      this._next();
      -    } else {
      -      // in a trampoline. tell __next that its
      -      // ok to continue jumping.
      -      this._inline = T_CONT;
      -    }
      -    return;
      -  }
      -
      -  var instance = new this.query.model(undefined, this._fields, true);
      -
      -  var self = this;
      -  instance.init(doc, this.query, function (err) {
      -    if (err) return self.destroy(err);
      -    self.emit('data', instance);
      -
      -    // trampoline management
      -    if (T_IDLE === self._inline) {
      -      // no longer in trampoline. restart it.
      -      self._next();
      -    } else
      -      // in a trampoline. tell __next that its
      -      // ok to continue jumping.
      -      self._inline = T_CONT;
      -  });
      -}

      Parameters:


      QueryStream#pause()

      Pauses this stream.

      show code
      QueryStream.prototype.pause = function () {
      -  this.paused = true;
      -}

      QueryStream#resume()

      Resumes this stream.

      show code
      QueryStream.prototype.resume = function () {
      -  this.paused = false;
      -
      -  if (!this._cursor) {
      -    // cannot start if not initialized
      -    return;
      -  }
      -
      -  // are we within the trampoline?
      -  if (T_INIT === this._inline) {
      -    return;
      -  }
      -
      -  if (!this._running) {
      -    // outside QueryStream control, need manual restart
      -    return this._next();
      -  }
      -}

      QueryStream#destroy([err])

      Destroys the stream, closing the underlying cursor. No more events will be emitted.

      show code
      QueryStream.prototype.destroy = function (err) {
      -  if (this._destroyed) return;
      -  this._destroyed = true;
      -  this._running = false;
      -  this.readable = false;
      -
      -  if (this._cursor) {
      -    this._cursor.close();
      -  }
      -
      -  if (err) {
      -    this.emit('error', err);
      -  }
      -
      -  this.emit('close');
      -}

      Parameters:


      QueryStream#pipe()

      Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

      See:

      Example:

      - -
      query.stream().pipe(writeStream [, options])
      - -

      This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      - -
      var format = new ArrayFormatter;
      -Events.find().stream().pipe(format).pipe(res);
      - -

      As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


      QueryStream#paused

      Flag stating whether or not this stream is paused.


      QueryStream#readable

      Flag stating whether or not this stream is readable.


    • schema/array.js

      SchemaArray(key, cast, options)

      Array SchemaType constructor

      show code
      function SchemaArray (key, cast, options) {
      -  if (cast) {
      -    var castOptions = {};
      -
      -    if ('Object' === cast.constructor.name) {
      -      if (cast.type) {
      -        // support { type: Woot }
      -        castOptions = cast;
      -        cast = cast.type;
      -        delete castOptions.type;
      -      } else {
      -        cast = Mixed;
      -      }
      -    }
      -
      -    var caster = cast.name in Types ? Types[cast.name] : cast;
      -    this.casterConstructor = caster;
      -    this.caster = new caster(null, castOptions);
      -  }
      -
      -  SchemaType.call(this, key, options);
      -
      -  var self = this
      -    , defaultArr
      -    , fn;
      -
      -  if (this.defaultValue) {
      -    defaultArr = this.defaultValue;
      -    fn = 'function' == typeof defaultArr;
      -  }
      -
      -  this.default(function(){
      -    var arr = fn ? defaultArr() : defaultArr || [];
      -    return new MongooseArray(arr, self.path, this);
      -  });
      -};

      Parameters:

      Inherits:


      SchemaArray#checkRequired(value)

      Check required

      show code
      SchemaArray.prototype.checkRequired = function (value) {
      -  return !!(value && value.length);
      -};

      Parameters:


      SchemaArray#applyGetters(value, scope)

      Overrides the getters application for the population special-case

      show code
      SchemaArray.prototype.applyGetters = function (value, scope) {
      -  if (this.caster.options && this.caster.options.ref) {
      -    // means the object id was populated
      -    return value;
      -  }
      -
      -  return SchemaType.prototype.applyGetters.call(this, value, scope);
      -};

      Parameters:


      SchemaArray#cast(value, doc, init)

      Casts contents

      show code
      SchemaArray.prototype.cast = function (value, doc, init) {
      -  if (Array.isArray(value)) {
      -    if (!(value instanceof MongooseArray)) {
      -      value = new MongooseArray(value, this.path, doc);
      -    }
      -
      -    if (this.caster) {
      -      try {
      -        for (var i = 0, l = value.length; i < l; i++) {
      -          value[i] = this.caster.cast(value[i], doc, init);
      -        }
      -      } catch (e) {
      -        // rethrow
      -        throw new CastError(e.type, value);
      -      }
      -    }
      -
      -    return value;
      -  } else {
      -    return this.cast([value], doc, init);
      -  }
      -};

      Parameters:

      • value <Object>
      • doc <Document> document that triggers the casting
      • init <Boolean> whether this is an initialization cast

      SchemaArray#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaArray.prototype.castForQuery = function ($conditional, value) {
      -  var handler
      -    , val;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with Array.");
      -    val = handler.call(this, value);
      -  } else {
      -    val = $conditional;
      -    var proto = this.casterConstructor.prototype;
      -    var method = proto.castForQuery || proto.cast;
      -    if (Array.isArray(val)) {
      -      val = val.map(function (v) {
      -        if (method) v = method.call(proto, v);
      -        return isMongooseObject(v)
      -          ? v.toObject()
      -          : v;
      -      });
      -    } else if (method) {
      -      val = method.call(proto, val);
      -    }
      -  }
      -  return val && isMongooseObject(val)
      -    ? val.toObject()
      -    : val;
      -};

      Parameters:


    • schema/boolean.js

      SchemaBoolean(path, options)

      Boolean SchemaType constructor.

      show code
      function SchemaBoolean (path, options) {
      -  SchemaType.call(this, path, options);
      -};

      Parameters:

      Inherits:


      SchemaBoolean#checkRequired()

      Required validator

      show code
      SchemaBoolean.prototype.checkRequired = function (value) {
      -  return value === true || value === false;
      -};

      SchemaBoolean#cast(value)

      Casts to boolean

      show code
      SchemaBoolean.prototype.cast = function (value) {
      -  if (value === null) return value;
      -  if (value === '0') return false;
      -  return !!value;
      -};

      Parameters:


      SchemaBoolean#castForQuery($conditional, val)

      Casts contents for queries.

      show code
      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (2 === arguments.length) {
      -    handler = SchemaBoolean.$conditionalHandlers[$conditional];
      -
      -    if (handler) {
      -      return handler.call(this, val);
      -    }
      -
      -    return this.cast(val);
      -  }
      -
      -  return this.cast($conditional);
      -};

      Parameters:


    • schema/buffer.js

      SchemaBuffer(key, cast)

      Buffer SchemaType constructor

      show code
      function SchemaBuffer (key, options) {
      -  SchemaType.call(this, key, options, 'Buffer');
      -};

      Parameters:

      Inherits:


      SchemaBuffer#checkRequired()

      Check required

      show code
      SchemaBuffer.prototype.checkRequired = function (value) {
      -  return !!(value && value.length);
      -};

      SchemaBuffer#cast(value, doc, init)

      Casts contents

      show code
      SchemaBuffer.prototype.cast = function (value, doc, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  if (Buffer.isBuffer(value)) {
      -    if (!(value instanceof MongooseBuffer)) {
      -      value = new MongooseBuffer(value, [this.path, doc]);
      -    }
      -
      -    return value;
      -  } else if (value instanceof Binary) {
      -    return new MongooseBuffer(value.value(true), [this.path, doc]);
      -  }
      -
      -  if ('string' === typeof value || Array.isArray(value)) {
      -    return new MongooseBuffer(value, [this.path, doc]);
      -  }
      -
      -  throw new CastError('buffer', value);
      -};

      Parameters:


      SchemaBuffer#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with Buffer.");
      -    return handler.call(this, val);
      -  } else {
      -    val = $conditional;
      -    return this.cast(val).toObject();
      -  }
      -};

      Parameters:


    • schema/date.js

      SchemaDate(key, options)

      Date SchemaType constructor.

      show code
      function SchemaDate (key, options) {
      -  SchemaType.call(this, key, options);
      -};

      Parameters:

      Inherits:


      SchemaDate#checkRequired()

      Required validator for date

      show code
      SchemaDate.prototype.checkRequired = function (value) {
      -  return value instanceof Date;
      -};

      SchemaDate#cast(value)

      Casts to date

      show code
      SchemaDate.prototype.cast = function (value) {
      -  if (value === null || value === '')
      -    return null;
      -
      -  if (value instanceof Date)
      -    return value;
      -
      -  var date;
      -
      -  // support for timestamps
      -  if (value instanceof Number || 'number' == typeof value 
      -      || String(value) == Number(value))
      -    date = new Date(Number(value));
      -
      -  // support for date strings
      -  else if (value.toString)
      -    date = new Date(value.toString());
      -
      -  if (date.toString() != 'Invalid Date')
      -    return date;
      -
      -  throw new CastError('date', value);
      -};

      Parameters:


      SchemaDate#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaDate.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -
      -  if (2 !== arguments.length) {
      -    return this.cast($conditional);
      -  }
      -
      -  handler = this.$conditionalHandlers[$conditional];
      -
      -  if (!handler) {
      -    throw new Error("Can't use " + $conditional + " with Date.");
      -  }
      -
      -  return handler.call(this, val);
      -};

      Parameters:


    • schema/documentarray.js

      DocumentArray(key, schema, options)

      SubdocsArray SchemaType constructor

      show code
      function DocumentArray (key, schema, options) {
      -
      -  // compile an embedded document for this schema
      -  function EmbeddedDocument () {
      -    Subdocument.apply(this, arguments);
      -  }
      -
      -  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
      -  EmbeddedDocument.prototype._setSchema(schema);
      -  EmbeddedDocument.schema = schema;
      -
      -  // apply methods
      -  for (var i in schema.methods) {
      -    EmbeddedDocument.prototype[i] = schema.methods[i];
      -  }
      -
      -  // apply statics
      -  for (var i in schema.statics)
      -    EmbeddedDocument[i] = schema.statics[i];
      -
      -  EmbeddedDocument.options = options;
      -  this.schema = schema;
      -
      -  ArrayType.call(this, key, EmbeddedDocument, options);
      -
      -  this.schema = schema;
      -  var path = this.path;
      -  var fn = this.defaultValue;
      -
      -  this.default(function(){
      -    var arr = fn.call(this);
      -    if (!Array.isArray(arr)) arr = [arr];
      -    return new MongooseDocumentArray(arr, path, this);
      -  });
      -};

      Parameters:

      Inherits:


      DocumentArray#doValidate()

      Performs local validations first, then validations on each embedded doc

      show code
      DocumentArray.prototype.doValidate = function (array, fn, scope) {
      -  var self = this;
      -
      -  SchemaType.prototype.doValidate.call(this, array, function (err) {
      -    if (err) return fn(err);
      -
      -    var count = array && array.length
      -      , error;
      -
      -    if (!count) return fn();
      -
      -    // handle sparse arrays, do not use array.forEach which does not
      -    // iterate over sparse elements yet reports array.length including
      -    // them :(
      -
      -    for (var i = 0, len = count; i < len; ++i) {
      -      // sidestep sparse entries
      -      var doc = array[i];
      -      if (!doc) {
      -        --count || fn();
      -        continue;
      -      }
      -
      -      ;(function (i) {
      -        doc.validate(function (err) {
      -          if (err && !error) {
      -            // rewrite the key
      -            err.key = self.key + '.' + i + '.' + err.key;
      -            return fn(error = err);
      -          }
      -          --count || fn();
      -        });
      -      })(i);
      -    }
      -  }, scope);
      -};

      DocumentArray#cast(value, document)

      Casts contents

      show code
      DocumentArray.prototype.cast = function (value, doc, init, prev) {
      -  var selected
      -    , subdoc
      -    , i
      -
      -  if (!Array.isArray(value)) {
      -    return this.cast([value], doc, init, prev);
      -  }
      -
      -  if (!(value instanceof MongooseDocumentArray)) {
      -    value = new MongooseDocumentArray(value, this.path, doc);
      -  }
      -
      -  i = value.length;
      -
      -  while (i--) {
      -    if (!(value[i] instanceof Subdocument) && value[i]) {
      -      if (init) {
      -        selected || (selected = scopePaths(this, doc._selected, init));
      -        subdoc = new this.casterConstructor(null, value, true, selected);
      -        value[i] = subdoc.init(value[i]);
      -      } else {
      -        if (prev && (subdoc = prev.id(value[i]._id))) {
      -          // handle resetting doc with existing id but differing data
      -          // doc.array = [{ doc: 'val' }]
      -          subdoc.set(value[i]);
      -        } else {
      -          subdoc = new this.casterConstructor(value[i], value);
      -        }
      -
      -        // if set() is hooked it will have no return value
      -        // see gh-746
      -        value[i] = subdoc;
      -      }
      -    }
      -  }
      -
      -  return value;
      -}

      Parameters:


    • schema/mixed.js

      Mixed(path, options)

      Mixed SchemaType constructor.

      show code
      function Mixed (path, options) {
      -  // make sure empty array defaults are handled
      -  if (options &&
      -      options.default &&
      -      Array.isArray(options.default) &&
      -      0 === options.default.length) {
      -    options.default = Array;
      -  }
      -
      -  SchemaType.call(this, path, options);
      -};

      Parameters:

      Inherits:


      Mixed#checkRequired()

      Required validator

      show code
      Mixed.prototype.checkRequired = function (val) {
      -  return true;
      -};

      Mixed#cast(value)

      Casts val for Mixed.

      show code
      Mixed.prototype.cast = function (val) {
      -  return val;
      -};

      Parameters:

      this is a no-op


      Mixed#castForQuery($cond, [val])

      Casts contents for queries.

      show code
      Mixed.prototype.castForQuery = function ($cond, val) {
      -  if (arguments.length === 2) return val;
      -  return $cond;
      -};

      Parameters:


    • schema/number.js

      SchemaNumber(key, options)

      Number SchemaType constructor.

      show code
      function SchemaNumber (key, options) {
      -  SchemaType.call(this, key, options, 'Number');
      -};

      Parameters:

      Inherits:


      SchemaNumber#checkRequired()

      Required validator for number

      show code
      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return typeof value == 'number' || value instanceof Number;
      -  }
      -};

      SchemaNumber#min(value, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.min = function (value, message) {
      -  if (this.minValidator)
      -    this.validators = this.validators.filter(function(v){
      -      return v[1] != 'min';
      -    });
      -  if (value != null)
      -    this.validators.push([function(v){
      -      return v === null || v >= value;
      -    }, 'min']);
      -  return this;
      -};

      Parameters:

      Example:

      - -
      var s = new Schema({ n: { type: Number, min: 10 })
      -var M = db.model('M', s)
      -var m = new M({ n: 9 })
      -m.save(function (err) {
      -  console.error(err) // validator error
      -  m.n = 10;
      -  m.save() // success
      -})

      SchemaNumber#max(maximum, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.max = function (value, message) {
      -  if (this.maxValidator)
      -    this.validators = this.validators.filter(function(v){
      -      return v[1] != 'max';
      -    });
      -  if (value != null)
      -    this.validators.push([this.maxValidator = function(v){
      -      return v === null || v <= value;
      -    }, 'max']);
      -  return this;
      -};

      Parameters:

      Example:

      - -
      var s = new Schema({ n: { type: Number, max: 10 })
      -var M = db.model('M', s)
      -var m = new M({ n: 11 })
      -m.save(function (err) {
      -  console.error(err) // validator error
      -  m.n = 10;
      -  m.save() // success
      -})

      SchemaNumber#cast(value, doc, init)

      Casts to number

      show code
      SchemaNumber.prototype.cast = function (value, doc, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  if (!isNaN(value)){
      -    if (null === value) return value;
      -    if ('' === value) return null;
      -    if ('string' == typeof value) value = Number(value);
      -    if (value instanceof Number) return value
      -    if ('number' == typeof value) return value;
      -    if (value.toString && !Array.isArray(value) &&
      -        value.toString() == Number(value)) {
      -      return new Number(value)
      -    }
      -  }
      -
      -  throw new CastError('number', value);
      -};

      Parameters:


      SchemaNumber#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with Number.");
      -    return handler.call(this, val);
      -  } else {
      -    val = this.cast($conditional);
      -    return val == null ? val : val
      -  }
      -};

      Parameters:


    • schema/objectid.js

      ObjectId(key, options)

      ObjectId SchemaType constructor.

      show code
      function ObjectId (key, options) {
      -  SchemaType.call(this, key, options, 'ObjectID');
      -};

      Parameters:

      Inherits:


      ObjectId#checkRequired()

      Check required

      show code
      ObjectId.prototype.checkRequired = function checkRequired (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return value instanceof oid;
      -  }
      -};

      ObjectId#cast(value, scope, init)

      Casts to ObjectId

      show code
      ObjectId.prototype.cast = function (value, scope, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  if (value === null) return value;
      -
      -  if (value instanceof oid)
      -    return value;
      -
      -  if (value._id && value._id instanceof oid)
      -    return value._id;
      -
      -  if (value.toString)
      -    return oid.fromString(value.toString());
      -
      -  throw new CastError('object id', value);
      -};

      Parameters:


      ObjectId#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      ObjectId.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with ObjectId.");
      -    return handler.call(this, val);
      -  } else {
      -    return this.cast($conditional);
      -  }
      -};

      Parameters:


      ObjectId#auto(turnOn)

      Adds an auto-generated ObjectId default if turnOn is true.

      show code
      ObjectId.prototype.auto = function (turnOn) {
      -  if (turnOn) {
      -    this.default(defaultId);
      -    this.set(resetId)
      -  }
      -};

      Parameters:

      • turnOn <Boolean> auto generated ObjectId defaults

    • schema/string.js

      SchemaString(key, options)

      String SchemaType constructor.

      show code
      function SchemaString (key, options) {
      -  this.enumValues = [];
      -  this.regExp = null;
      -  SchemaType.call(this, key, options, 'String');
      -};

      Parameters:

      Inherits:


      SchemaString#enum([args...])

      Adds enumeration values and a coinciding validator.

      show code
      SchemaString.prototype.enum = function () {
      -  var len = arguments.length;
      -  if (!len || undefined === arguments[0] || false === arguments[0]) {
      -    if (this.enumValidator){
      -      this.enumValidator = false;
      -      this.validators = this.validators.filter(function(v){
      -        return v[1] != 'enum';
      -      });
      -    }
      -    return;
      -  }
      -
      -  for (var i = 0; i < len; i++) {
      -    if (undefined !== arguments[i]) {
      -      this.enumValues.push(this.cast(arguments[i]));
      -    }
      -  }
      -
      -  if (!this.enumValidator) {
      -    var values = this.enumValues;
      -    this.enumValidator = function(v){
      -      return undefined === v || ~values.indexOf(v);
      -    };
      -    this.validators.push([this.enumValidator, 'enum']);
      -  }
      -};

      Parameters:

      • [args...] <String> enumeration values

      Example:

      - -
      var states = 'opening open closing closed'.split(' ')
      -var s = new Schema({ state: { type: String, enum: states })
      -var M = db.model('M', s)
      -var m = new M({ state: 'invalid' })
      -m.save(function (err) {
      -  console.error(err) // validator error
      -  m.state = 'open'
      -  m.save() // success
      -})

      SchemaString#lowercase()

      Adds a lowercase setter.

      show code
      SchemaString.prototype.lowercase = function () {
      -  return this.set(function (v, self) {
      -    if ('string' != typeof v) v = self.cast(v)
      -    if (v) return v.toLowerCase();
      -    return v;
      -  });
      -};

      Example:

      - -
      var s = new Schema({ email: { type: String, lowercase: true }})
      -var M = db.model('M', s);
      -var m = new M({ email: 'SomeEmail@example.COM' });
      -console.log(m.email) // someemail@example.com
      -

      SchemaString#uppercase()

      Adds an uppercase setter.

      show code
      SchemaString.prototype.uppercase = function () {
      -  return this.set(function (v, self) {
      -    if ('string' != typeof v) v = self.cast(v)
      -    if (v) return v.toUpperCase();
      -    return v;
      -  });
      -};

      Example:

      - -
      var s = new Schema({ caps: { type: String, uppercase: true }})
      -var M = db.model('M', s);
      -var m = new M({ caps: 'an example' });
      -console.log(m.caps) // AN EXAMPLE

      SchemaString#trim()

      Adds a trim setter.

      show code
      SchemaString.prototype.trim = function () {
      -  return this.set(function (v, self) {
      -    if ('string' != typeof v) v = self.cast(v)
      -    if (v) return v.trim();
      -    return v;
      -  });
      -};

      The string value will be trimmed when set.

      - -

      Example:

      - -
      var s = new Schema({ name: { type: String, trim: true }})
      -var M = db.model('M', s)
      -var string = ' some name '
      -console.log(string.length) // 11
      -var m = new M({ name: string })
      -console.log(m.name.length) // 9

      SchemaString#match(regExp)

      Sets a regexp validator.

      show code
      SchemaString.prototype.match = function match (regExp) {
      -  this.validators.push([function(v){
      -    return null != v && '' !== v
      -      ? regExp.test(v)
      -      : true
      -  }, 'regexp']);
      -};

      Parameters:

      • regExp <RegExp> regular expression to test against

      Any value that does not pass regExp.test(val) will fail validation.

      - -

      Example:

      - -
      var s = new Schema({ name: { type: String, match: /^a/ }})
      -var M = db.model('M', s)
      -var m = new M({ name: 'invalid' })
      -m.validate(function (err) {
      -  console.error(err) // validation error
      -  m.name = 'apples'
      -  m.validate(function (err) {
      -    assert.ok(err) // success
      -  })
      -})

      SchemaString#checkRequired(value)

      Check required

      show code
      SchemaString.prototype.checkRequired = function checkRequired (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return (value instanceof String || typeof value == 'string') && value.length;
      -  }
      -};

      Parameters:


      SchemaString#cast()

      Casts to String

      show code
      SchemaString.prototype.cast = function (value, scope, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -  if (value === null) return value;
      -  if ('undefined' !== typeof value && value.toString) return value.toString();
      -  throw new CastError('string', value);
      -};

      SchemaString#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      SchemaString.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with String.");
      -    return handler.call(this, val);
      -  } else {
      -    val = $conditional;
      -    if (val instanceof RegExp) return val;
      -    return this.cast(val);
      -  }
      -};

      Parameters:


    • schema.js

      Schema(definition)

      Schema constructor.

      show code
      function Schema (obj, options) {
      -  if (!(this instanceof Schema))
      -    return new Schema(obj, options);
      -
      -  this.paths = {};
      -  this.subpaths = {};
      -  this.virtuals = {};
      -  this.nested = {};
      -  this.inherits = {};
      -  this.callQueue = [];
      -  this._indexes = [];
      -  this.methods = {};
      -  this.statics = {};
      -  this.tree = {};
      -  this._requiredpaths = undefined;
      -
      -  this.options = this.defaultOptions(options);
      -
      -  // build paths
      -  if (obj) {
      -    this.add(obj);
      -  }
      -
      -  // ensure the documents get an auto _id unless disabled
      -  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
      -  if (auto_id) {
      -    this.add({ _id: {type: Schema.ObjectId, auto: true} });
      -  }
      -
      -  // ensure the documents receive an id getter unless disabled
      -  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
      -  if (autoid) {
      -    this.virtual('id').get(idGetter);
      -  }
      -
      -  // versioning not directly added to schema b/c we only want
      -  // it in the top level document, not embedded ones.
      -};

      Parameters:

      Events:

      • init: Emitted after the schema is compiled into a Model.

      Example:

      - -
      var child = new Schema({ name: String });
      -var schema = new Schema({ name: String, age: Number, children: [child] });
      -var Tree = mongoose.model('Tree', schema);
      -
      -// setting schema options
      -new Schema({ name: String }, { _id: false, autoIndex: false })
      - -

      Options:

      - -
        -
      • safe: bool - defaults to true.
      • -
      • read: string
      • -
      • strict: bool - defaults to true
      • -
      • capped: bool - defaults to false
      • -
      • versionKey: bool - defaults to "__v"
      • -
      • shardKey: bool - defaults to null
      • -
      • autoIndex: bool - defaults to true
      • -
      • _id: bool - defaults to true
      • -
      • id: bool - defaults to true
      • -
      • toObject - object - no default
      • -
      • toJSON - object - no default
      • -
      • minimize: bool - controls document#toObject behavior when called manually - defaults to true
      • -
      - -

      Note:

      - -

      When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


      Schema#defaultOptions(options)

      Returns default options for this schema, merged with options.

      show code
      Schema.prototype.defaultOptions = function (options) {
      -  options = utils.options({
      -      safe: true
      -    , strict: true
      -    , capped: false // { size, max, autoIndexId }
      -    , versionKey: '__v'
      -    , minimize: true
      -    , autoIndex: true
      -    , shardKey: null
      -    , read: null
      -    // the following are only applied at construction time
      -    , noId: false // deprecated, use { _id: false }
      -    , _id: true
      -    , noVirtualId: false // deprecated, use { id: false }
      -    , id: true
      -  }, options);
      -
      -  if (options.read)
      -    options.read = utils.readPref(options.read);
      -
      -  return options;
      -}

      Parameters:

      Returns:


      Schema#add(obj, prefix)

      Adds key path / schema type pairs to this schema.

      show code
      Schema.prototype.add = function add (obj, prefix) {
      -  prefix = prefix || '';
      -  for (var i in obj) {
      -    if (null == obj[i]) {
      -      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
      -    }
      -
      -    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
      -      if (Object.keys(obj[i]).length) {
      -        // nested object { last: { name: String }}
      -        this.nested[prefix + i] = true;
      -        this.add(obj[i], prefix + i + '.');
      -      }
      -      else
      -        this.path(prefix + i, obj[i]); // mixed type
      -    } else
      -      this.path(prefix + i, obj[i]);
      -  }
      -};

      Parameters:

      Example:

      - -
      var ToySchema = new Schema;
      -ToySchema.add({ name: 'string', color: 'string', price: 'number' });

      Schema#path(path, constructor)

      Gets/sets schema paths.

      show code
      Schema.prototype.path = function (path, obj) {
      -  if (obj == undefined) {
      -    if (this.paths[path]) return this.paths[path];
      -    if (this.subpaths[path]) return this.subpaths[path];
      -
      -    // subpaths?
      -    return /\.\d+\.?$/.test(path)
      -      ? getPositionalPath(this, path)
      -      : undefined;
      -  }
      -
      -  // some path names conflict with document methods
      -  if (reserved[path]) {
      -    throw new Error("`" + path + "` may not be used as a schema pathname");
      -  }
      -
      -  // update the tree
      -  var subpaths = path.split(/\./)
      -    , last = subpaths.pop()
      -    , branch = this.tree;
      -
      -  subpaths.forEach(function(path) {
      -    if (!branch[path]) branch[path] = {};
      -    branch = branch[path];
      -  });
      -
      -  branch[last] = utils.clone(obj);
      -
      -  this.paths[path] = Schema.interpretAsType(path, obj);
      -  return this;
      -};

      Parameters:

      Sets a path (if arity 2)
      Gets a path (if arity 1)

      - -

      Example

      - -
      schema.path('name') // returns a SchemaType
      -schema.path('name', Number) // changes the schemaType of `name` to Number

      Schema#eachPath(fn)

      Iterates the schemas paths similar to Array#forEach.

      show code
      Schema.prototype.eachPath = function (fn) {
      -  var keys = Object.keys(this.paths)
      -    , len = keys.length;
      -
      -  for (var i = 0; i < len; ++i) {
      -    fn(keys[i], this.paths[keys[i]]);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      The callback is passed the pathname and schemaType as arguments on each iteration.


      Schema#requiredPaths()

      Returns an Array of path strings that are required by this schema.

      show code
      Schema.prototype.requiredPaths = function requiredPaths () {
      -  if (this._requiredpaths) return this._requiredpaths;
      -
      -  var paths = Object.keys(this.paths)
      -    , i = paths.length
      -    , ret = [];
      -
      -  while (i--) {
      -    var path = paths[i];
      -    if (this.paths[path].isRequired) ret.push(path);
      -  }
      -
      -  return this._requiredpaths = ret;
      -}

      Returns:


      Schema#pathType(path)

      Returns the pathType of path for this schema.

      show code
      Schema.prototype.pathType = function (path) {
      -  if (path in this.paths) return 'real';
      -  if (path in this.virtuals) return 'virtual';
      -  if (path in this.nested) return 'nested';
      -  if (path in this.subpaths) return 'real';
      -
      -  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
      -    return 'real';
      -  } else {
      -    return 'adhocOrUndefined'
      -  }
      -};

      Parameters:

      Returns:

      Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


      Schema#queue(name, args)

      Adds a method call to the queue.

      show code
      Schema.prototype.queue = function(name, args){
      -  this.callQueue.push([name, args]);
      -  return this;
      -};

      Parameters:

      • name <String> name of the document method to call later
      • args <Array> arguments to pass to the method

      Schema#pre(method, callback)

      Defines a pre hook for the document.

      show code
      Schema.prototype.pre = function(){
      -  return this.queue('pre', arguments);
      -};

      Parameters:

      Example

      - -
      var toySchema = new Schema(..);
      -
      -toySchema.pre('save', function (next) {
      -  if (!this.created) this.created = new Date;
      -  next();
      -})
      -
      -toySchema.pre('validate', function (next) {
      -  if (this.name != 'Woody') this.name = 'Woody';
      -  next();
      -})

      Schema#post(method, fn)

      Defines a post hook for the document.

      show code
      Schema.prototype.post = function(method, fn){
      -  return this.queue('on', arguments);
      -};

      Parameters:

      Post hooks fire on the event emitted from document instances of Models compiled from this schema.

      - -
      var schema = new Schema(..);
      -schema.post('save', function () {
      -  console.log('this fired after a document was saved');
      -});
      -
      -var Model = mongoose.model('Model', schema);
      -
      -var m = new Model(..);
      -m.save(function (err) {
      -  console.log('this fires after the `post` hook');
      -});

      Schema#plugin(plugin, opts)

      Registers a plugin for this schema.

      show code
      Schema.prototype.plugin = function (fn, opts) {
      -  fn(this, opts);
      -  return this;
      -};

      Parameters:


      Schema#method(method, [fn])

      Adds an instance method to documents constructed from Models compiled from this schema.

      show code
      Schema.prototype.method = function (name, fn) {
      -  if ('string' != typeof name)
      -    for (var i in name)
      -      this.methods[i] = name[i];
      -  else
      -    this.methods[name] = fn;
      -  return this;
      -};

      Parameters:

      Example

      - -
      var schema = kittySchema = new Schema(..);
      -
      -schema.methods.meow = function () {
      -  console.log('meeeeeoooooooooooow');
      -})
      -
      -var Kitty = mongoose.model('Kitty', schema);
      -
      -var fizz = new Kitty;
      -fizz.meow(); // meeeeeooooooooooooow
      - -

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      - -
      schema.method({
      -    purr: function () {}
      -  , scratch: function () {}
      -});
      -
      -// later
      -fizz.purr();
      -fizz.scratch();

      Schema#static(name, fn)

      Adds static "class" methods to Models compiled from this schema.

      show code
      Schema.prototype.static = function(name, fn) {
      -  if ('string' != typeof name)
      -    for (var i in name)
      -      this.statics[i] = name[i];
      -  else
      -    this.statics[name] = fn;
      -  return this;
      -};

      Parameters:

      Example

      - -
      var schema = new Schema(..);
      -schema.static('findByName', function (name, callback) {
      -  return this.find({ name: name }, callback);
      -});
      -
      -var Drink = mongoose.model('Drink', schema);
      -Drink.findByName('sanpellegrino', function (err, drinks) {
      -  //
      -});
      - -

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


      Schema#index(fields, [options])

      Defines an index (most likely compound) for this schema.

      show code
      Schema.prototype.index = function (fields, options) {
      -  options || (options = {});
      -
      -  if (options.expires)
      -    utils.expires(options);
      -
      -  this._indexes.push([fields, options]);
      -  return this;
      -};

      Parameters:

      Example

      - -
      schema.index({ first: 1, last: -1 })

      Schema#set(key, [value])

      Sets/gets a schema option.

      show code
      Schema.prototype.set = function (key, value, tags) {
      -  if (arguments.length == 1)
      -    return this.options[key];
      -
      -  this.options[key] = 'read' == key
      -    ? utils.readPref(value, tags)
      -    : value;
      -
      -  return this;
      -};

      Parameters:

      • key <String> option name
      • [value] <Object> if not passed, the current option value is returned

      Schema#indexes()

      Compiles indexes from fields and schema-level indexes

      show code
      Schema.prototype.indexes = function () {
      -  var indexes = []
      -    , seenSchemas = [];
      -
      -  collectIndexes(this);
      -
      -  return indexes;
      -
      -  function collectIndexes (schema, prefix) {
      -    if (~seenSchemas.indexOf(schema)) return;
      -    seenSchemas.push(schema);
      -
      -    var index;
      -    var paths = schema.paths;
      -    prefix = prefix || '';
      -
      -    for (var i in paths) {
      -      if (paths[i]) {
      -        if (paths[i] instanceof Types.DocumentArray) {
      -          collectIndexes(paths[i].schema, i + '.');
      -        } else {
      -          index = paths[i]._index;
      -
      -          if (index !== false && index !== null){
      -            var field = {};
      -            field[prefix + i] = '2d' === index ? index : 1;
      -            var options = 'Object' === index.constructor.name ? index : {};
      -            if (!('background' in options)) options.background = true;
      -            indexes.push([field, options]);
      -          }
      -        }
      -      }
      -    }
      -
      -    if (prefix) {
      -      fixSubIndexPaths(schema, prefix);
      -    } else {
      -      schema._indexes.forEach(function (index) {
      -        if (!('background' in index[1])) index[1].background = true;
      -      });
      -      indexes = indexes.concat(schema._indexes);
      -    }
      -  }

      Schema#virtual(name, [options])

      Creates a virtual type with the given name.

      show code
      Schema.prototype.virtual = function (name, options) {
      -  var virtuals = this.virtuals;
      -  var parts = name.split('.');
      -  return virtuals[name] = parts.reduce(function (mem, part, i) {
      -    mem[part] || (mem[part] = (i === parts.length-1)
      -                            ? new VirtualType(options, name)
      -                            : {});
      -    return mem[part];
      -  }, this.tree);
      -};

      Parameters:

      Returns:


      Schema#virtualpath(name)

      Returns the virtual type with the given name.

      show code
      Schema.prototype.virtualpath = function (name) {
      -  return this.virtuals[name];
      -};

      Parameters:

      Returns:


      Schema#namedScope()

      These still haven't been fixed. Once they're working we'll make them public again.

      show code
      Schema.prototype.namedScope = function (name, fn) {
      -  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
      -    , newScope = Object.create(namedScopes)
      -    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
      -  allScopes[name] = newScope;
      -  newScope.name = name;
      -  newScope.block = fn;
      -  newScope.query = new Query();
      -  newScope.decorate(namedScopes, {
      -    block0: function (block) {
      -      return function () {
      -        block.call(this.query);
      -        return this;
      -      };
      -    },
      -    blockN: function (block) {
      -      return function () {
      -        block.apply(this.query, arguments);
      -        return this;
      -      };
      -    },
      -    basic: function (query) {
      -      return function () {
      -        this.query.find(query);
      -        return this;
      -      };
      -    }
      -  });
      -  return newScope;
      -};

      Schema.reserved

      Reserved document keys.

      show code
      Schema.reserved = Object.create(null);
      -var reserved = Schema.reserved;
      -reserved.on =
      -reserved.db =
      -reserved.init =
      -reserved.isNew =
      -reserved.errors =
      -reserved.schema =
      -reserved.options =
      -reserved.modelName =
      -reserved.collection = 1;

      Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      - -
      on, db, init, isNew, errors, schema, options, modelName, collection
      - -

      NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

      - -
      var schema = new Schema(..);
      - schema.methods.init = function () {} // potentially breaking

      Schema.interpretAsType(path, obj)

      Converts type arguments into Mongoose Types.

      show code
      Schema.interpretAsType = function (path, obj) {
      -  if (obj.constructor.name != 'Object')
      -    obj = { type: obj };
      -
      -  // Get the type making sure to allow keys named "type"
      -  // and default to mixed if not specified.
      -  // { type: { type: String, default: 'freshcut' } }
      -  var type = obj.type && !obj.type.type
      -    ? obj.type
      -    : {};
      -
      -  if ('Object' == type.constructor.name || 'mixed' == type) {
      -    return new Types.Mixed(path, obj);
      -  }
      -
      -  if (Array.isArray(type) || Array == type || 'array' == type) {
      -    // if it was specified through { type } look for `cast`
      -    var cast = (Array == type || 'array' == type)
      -      ? obj.cast
      -      : type[0];
      -
      -    if (cast instanceof Schema) {
      -      return new Types.DocumentArray(path, cast, obj);
      -    }
      -
      -    if ('string' == typeof cast) {
      -      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
      -    } else if (cast && (!cast.type || cast.type.type)
      -                    && 'Object' == cast.constructor.name
      -                    && Object.keys(cast).length) {
      -      return new Types.DocumentArray(path, new Schema(cast), obj);
      -    }
      -
      -    return new Types.Array(path, cast || Types.Mixed, obj);
      -  }
      -
      -  var name = 'string' == typeof type
      -    ? type
      -    : type.name;
      -
      -  if (name) {
      -    name = name.charAt(0).toUpperCase() + name.substring(1);
      -  }
      -
      -  if (undefined == Types[name]) {
      -    throw new TypeError('Undefined type at `' + path +
      -        '`
      -  Did you try nesting Schemas? ' +
      -        'You can only nest using refs or arrays.');
      -  }
      -
      -  return new Types[name](path, obj);
      -};

      Parameters:


      Schema.Types

      The various Mongoose Schema Types.

      show code
      Schema.Types = require('./schema/index');

      Example:

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -var ObjectId = mongoose.Schema.Types.ObjectId;
      - -

      Types:

      - -
        -
      • String
      • -
      • Number
      • -
      • Boolean | Bool
      • -
      • Array
      • -
      • Buffer
      • -
      • Date
      • -
      • ObjectId | Oid
      • -
      • Mixed
      • -
      - -

      Using this exposed access to the Mixed SchemaType, we can use them in our schema.

      - -
      var Mixed = mongoose.Schema.Types.Mixed;
      -new mongoose.Schema({ _user: Mixed })

      Schema#tree

      Schema as a tree

      - -

      Example:

      - -
      {
      -    '_id'     : ObjectId
      -  , 'nested'  : {
      -        'key' : String
      -    }
      -}

      Schema#paths

      Schema as flat paths

      - -

      Example:

      - -
      {
      -    '_id'        : SchemaType,
      -  , 'nested.key' : SchemaType,
      -}

    • schemadefault.js

      exports#system.profile

      Default model for querying the system.profiles collection.


    • schematype.js

      SchemaType(path, [options], [instance])

      SchemaType constructor

      show code
      function SchemaType (path, options, instance) {
      -  this.path = path;
      -  this.instance = instance;
      -  this.validators = [];
      -  this.setters = [];
      -  this.getters = [];
      -  this.options = options;
      -  this._index = null;
      -  this.selected;
      -
      -  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
      -    // { unique: true, index: true }
      -    if ('index' == i && this._index) continue;
      -
      -    var opts = Array.isArray(options[i])
      -      ? options[i]
      -      : [options[i]];
      -
      -    this[i].apply(this, opts);
      -  }
      -};

      Parameters:


      SchemaType#default(val)

      Sets a default value for this SchemaType.

      show code
      SchemaType.prototype.default = function (val) {
      -  if (1 === arguments.length) {
      -    this.defaultValue = typeof val === 'function'
      -      ? val
      -      : this.cast(val);
      -    return this;
      -  } else if (arguments.length > 1) {
      -    this.defaultValue = utils.args(arguments);
      -  }
      -  return this.defaultValue;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var schema = new Schema({ n: { type: Number, default: 10 })
      -var M = db.model('M', schema)
      -var m = new M;
      -console.log(m.n) // 10
      - -

      Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

      - -

      Example:

      - -
      // values are cast:
      -var schema = new Schema({ aNumber: Number, default: "4.815162342" })
      -var M = db.model('M', schema)
      -var m = new M;
      -console.log(m.aNumber) // 4.815162342
      -
      -// default unique objects for Mixed types:
      -var schema = new Schema({ mixed: Schema.Types.Mixed });
      -schema.path('mixed').default(function () {
      -  return {};
      -});
      -
      -// if we don't use a function to return object literals for Mixed defaults,
      -// each document will receive a reference to the same object literal creating
      -// a "shared" object instance:
      -var schema = new Schema({ mixed: Schema.Types.Mixed });
      -schema.path('mixed').default({});
      -var M = db.model('M', schema);
      -var m1 = new M;
      -m1.mixed.added = 1;
      -console.log(m1.mixed); // { added: 1 }
      -var m2 = new M;
      -console.log(m2.mixed); // { added: 1 }

      SchemaType#index(options)

      Declares the index options for this schematype.

      show code
      SchemaType.prototype.index = function (options) {
      -  this._index = options;
      -  utils.expires(this._index);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var s = new Schema({ name: { type: String, index: true })
      -var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
      -Schema.path('my.path').index(true);
      -Schema.path('my.path').index({ expires: 60 });
      -Schema.path('my.path').index({ unique: true, sparse: true });
      - -

      NOTE:

      - -

      Indexes are created in the background by default. Specify background: false to override.

      - -

      Direction doesn't matter for single key indexes


      SchemaType#unique(bool)

      Declares an unique index.

      show code
      SchemaType.prototype.unique = function (bool) {
      -  if (!this._index || 'Object' !== this._index.constructor.name) {
      -    this._index = {};
      -  }
      -
      -  this._index.unique = bool;
      -  return this;
      -};

      Parameters:

      Returns:

      Examples:

      - -
      var s = new Schema({ name: { type: String, unique: true })
      -Schema.path('name').index({ unique: true });

      SchemaType#sparse(bool)

      Declares a sparse index.

      show code
      SchemaType.prototype.sparse = function (bool) {
      -  if (!this._index || 'Object' !== this._index.constructor.name) {
      -    this._index = {};
      -  }
      -
      -  this._index.sparse = bool;
      -  return this;
      -};

      Parameters:

      Returns:

      Examples:

      - -
      var s = new Schema({ name: { type: String, sparse: true })
      -Schema.path('name').index({ sparse: true });

      SchemaType#expires(when)

      Declares a TTL index (rounded to the nearest second) for Date types only.

      show code
      SchemaType.prototype.expires = function (when) {
      -  if (!this._index || 'Object' !== this._index.constructor.name) {
      -    this._index = {};
      -  }
      -
      -  this._index.expires = when;
      -  utils.expires(this._index);
      -  return this;
      -};

      Parameters:

      Returns:

      This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
      This index type is only compatible with Date types.

      - -

      Example:

      - -
      // expire in 24 hours
      -new Schema({..}, { expires: 60*60*24 });
      - -

      expires utilizes the ms module from guille allowing us to use a friendlier syntax:

      - -

      Example:

      - -
      // expire in 24 hours
      -new Schema({..}, { expires: '24h' });
      -
      -// expire in 1.5 hours
      -new Schema({..}, { expires: '1.5h' });
      -
      -// expire in 7 days
      -var schema = new Schema({..});
      -schema.expires('7d');

      SchemaType#set(fn)

      Adds a setter to this schematype.

      show code
      SchemaType.prototype.set = function (fn) {
      -  if ('function' != typeof fn)
      -    throw new Error('A setter must be a function.');
      -  this.setters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      function capitalize (val) {
      -  if ('string' != typeof val) val = '';
      -  return val.charAt(0).toUpperCase() + val.substring(1);
      -}
      -
      -// defining within the schema
      -var s = new Schema({ name: { type: String, set: capitalize }})
      -
      -// or by retreiving its SchemaType
      -var s = new Schema({ name: String })
      -s.path('name').set(capitalize)
      - -

      Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      - -

      Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

      - -

      You can set up email lower case normalization easily via a Mongoose setter.

      - -
      function toLower (v) {
      -  return v.toLowerCase();
      -}
      -
      -var UserSchema = new Schema({
      -  email: { type: String, set: toLower }
      -})
      -
      -var User = db.model('User', UserSchema)
      -
      -var user = new User({email: 'AVENUE@Q.COM'})
      -console.log(user.email); // 'avenue@q.com'
      -
      -// or
      -var user = new User
      -user.email = 'Avenue@Q.com'
      -console.log(user.email) // 'avenue@q.com'
      -
      - -

      As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      - -

      NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

      - -
      new Schema({ email: { type: String, lowercase: true }})

      SchemaType#get(fn)

      Adds a getter to this schematype.

      show code
      SchemaType.prototype.get = function (fn) {
      -  if ('function' != typeof fn)
      -    throw new Error('A getter must be a function.');
      -  this.getters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      function dob (val) {
      -  if (!val) return val;
      -  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      -}
      -
      -// defining within the schema
      -var s = new Schema({ born: { type: Date, get: dob })
      -
      -// or by retreiving its SchemaType
      -var s = new Schema({ born: Date })
      -s.path('born').get(dob)
      - -

      Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

      - -

      Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

      - -
      function obfuscate (cc) {
      -  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
      -}
      -
      -var AccountSchema = new Schema({
      -  creditCardNumber: { type: String, get: obfuscate }
      -});
      -
      -var Account = db.model('Account', AccountSchema);
      -
      -Account.findById(id, function (err, found) {
      -  console.log(found.creditCardNumber); // '****-****-****-1234'
      -});

      SchemaType#validate(obj, [error])

      Adds validator(s) for this document path.

      show code
      SchemaType.prototype.validate = function (obj, error) {
      -  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
      -    this.validators.push([obj, error]);
      -    return this;
      -  }
      -
      -  var i = arguments.length
      -    , arg
      -
      -  while (i--) {
      -    arg = arguments[i];
      -    if (!(arg && 'Object' == arg.constructor.name)) {
      -      var msg = 'Invalid validator. Received (' + typeof arg + ') '
      -        + arg
      -        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
      -
      -      throw new Error(msg);
      -    }
      -    this.validate(arg.validator, arg.msg);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Validators must return Boolean. Returning false is interpreted as validation failure.

      - -

      Examples:

      - -
      function validator () { ... }
      -
      -var single = [validator, 'failed']
      -new Schema({ name: { type: String, validate: single }});
      -
      -var many = [
      -    { validator: validator, msg: 'uh oh' }
      -  , { validator: fn, msg: 'failed' }
      -]
      -new Schema({ name: { type: String, validate: many }});
      -
      -// or utilizing SchemaType methods directly:
      -
      -var schema = new Schema({ name: 'string' });
      -schema.path('name').validate(validator, 'validation failed');
      - -

      Asynchronous validation:

      - -

      Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

      - -
      schema.path('name').validate(function (value, respond) {
      -  doStuff(value, function () {
      -    ...
      -    respond(false); // validation failed
      -  })
      - }, 'my error type');
      - -

      Validation occurs pre('save') or whenever you manually execute document#validate.

      - -

      If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

      - -
      var conn = mongoose.createConnection(..);
      -conn.on('error', handleError);
      -
      -var Product = conn.model('Product', yourSchema);
      -var dvd = new Product(..);
      -dvd.save(); // emits error on the `conn` above
      - -

      If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

      - -
      // registering an error listener on the Model lets us handle errors more locally
      -Product.on('error', handleError);

      SchemaType#required(required)

      Adds a required validator to this schematype.

      show code
      SchemaType.prototype.required = function (required) {
      -  var self = this;
      -
      -  function __checkRequired (v) {
      -    // in here, `this` refers to the validating document.
      -    // no validation when this path wasn't selected in the query.
      -    if ('isSelected' in this &&
      -        !this.isSelected(self.path) &&
      -        !this.isModified(self.path)) return true;
      -    return self.checkRequired(v);
      -  }
      -
      -  if (false === required) {
      -    this.isRequired = false;
      -    this.validators = this.validators.filter(function (v) {
      -      return v[0].name !== '__checkRequired';
      -    });
      -  } else {
      -    this.isRequired = true;
      -    this.validators.push([__checkRequired, 'required']);
      -  }
      -
      -  return this;
      -};

      Parameters:

      • required <Boolean> enable/disable the validator

      Returns:

      Example:

      - -
      var s = new Schema({ born: { type: Date, required: true })
      -// or
      -Schema.path('name').required(true);

      SchemaType#getDefault(scope, init)

      Gets the default value

      show code
      SchemaType.prototype.getDefault = function (scope, init) {
      -  var ret = 'function' === typeof this.defaultValue
      -    ? this.defaultValue.call(scope)
      -    : this.defaultValue;
      -
      -  if (null !== ret && undefined !== ret) {
      -    return this.cast(ret, scope, init);
      -  } else {
      -    return ret;
      -  }
      -};

      Parameters:

      • scope <Object> the scope which callback are executed
      • init <Boolean>

      SchemaType#applySetters(value, scope, init)

      Applies setters

      show code
      SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  var v = value
      -    , setters = this.setters
      -    , len = setters.length
      -
      -  if (!len) {
      -    if (null === v || undefined === v) return v;
      -    return init
      -      ? v // if we just initialized we dont recast
      -      : this.cast(v, scope, init, priorVal)
      -  }
      -
      -  while (len--) {
      -    v = setters[len].call(scope, v, this);
      -  }
      -
      -  if (null === v || undefined === v) return v;
      -
      -  // do not cast until all setters are applied #665
      -  v = this.cast(v, scope, init, priorVal);
      -
      -  return v;
      -};

      Parameters:


      SchemaType#applyGetters(value, scope)

      Applies getters to a value

      show code
      SchemaType.prototype.applyGetters = function (value, scope) {
      -  if (SchemaType._isRef(this, value, true)) return value;
      -
      -  var v = value
      -    , getters = this.getters
      -    , len = getters.length;
      -
      -  if (!len) {
      -    return v;
      -  }
      -
      -  while (len--) {
      -    v = getters[len].call(scope, v, this);
      -  }
      -
      -  return v;
      -};

      Parameters:


      SchemaType#select(val)

      Sets default select() behavior for this path.

      show code
      SchemaType.prototype.select = function select (val) {
      -  this.selected = !! val;
      -}

      Parameters:

      Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

      - -

      Example:

      - -
      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      -T.find(..); // field x will always be selected ..
      -// .. unless overridden;
      -T.find().select('-x').exec(callback);

      SchemaType#doValidate(value, callback, scope)

      Performs a validation of value using the validators declared for this SchemaType.

      show code
      SchemaType.prototype.doValidate = function (value, fn, scope) {
      -  var err = false
      -    , path = this.path
      -    , count = this.validators.length;
      -
      -  if (!count) return fn(null);
      -
      -  function validate (val, msg) {
      -    if (err) return;
      -    if (val === undefined || val) {
      -      --count || fn(null);
      -    } else {
      -      fn(err = new ValidatorError(path, msg));
      -    }
      -  }
      -
      -  this.validators.forEach(function (v) {
      -    var validator = v[0]
      -      , message   = v[1];
      -
      -    if (validator instanceof RegExp) {
      -      validate(validator.test(value), message);
      -    } else if ('function' === typeof validator) {
      -      if (2 === validator.length) {
      -        validator.call(scope, value, function (val) {
      -          validate(val, message);
      -        });
      -      } else {
      -        validate(validator.call(scope, value), message);
      -      }
      -    }
      -  });
      -};

      Parameters:


      SchemaType._isRef(self, value, init)

      Determines if value is a valid Reference.

      show code
      SchemaType._isRef = function (self, value, init) {
      -  if (init && self.options && self.options.ref) {
      -    if (null == value) return true;
      -    if (value._id && value._id.constructor.name === self.instance) return true;
      -  }
      -
      -  return false;
      -}

      Parameters:

      Returns:


    • types/array.js

      MongooseArray(values, path, doc)

      Mongoose Array constructor.

      show code
      function MongooseArray (values, path, doc) {
      -  var arr = [];
      -  arr.push.apply(arr, values);
      -  arr.__proto__ = MongooseArray.prototype;
      -
      -  arr._atomics = {};
      -  arr.validators = [];
      -  arr._path = path;
      -
      -  if (doc) {
      -    arr._parent = doc;
      -    arr._schema = doc.schema.path(path);
      -  }
      -
      -  return arr;
      -};

      Parameters:

      Inherits:

      NOTE:

      - -

      Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


      MongooseArray#_cast(value)

      Casts a member based on this arrays schema.

      show code
      MongooseArray.prototype._cast = function (value) {
      -  var cast = this._schema.caster.cast
      -    , doc = this._parent;
      -
      -  return cast.call(null, value, doc);
      -};

      Parameters:

      Returns:

      • <value> the casted value

      MongooseArray#_markModified(embeddedDoc, embeddedPath)

      Marks this array as modified.

      show code
      MongooseArray.prototype._markModified = function (elem, embeddedPath) {
      -  var parent = this._parent
      -    , dirtyPath;
      -
      -  if (parent) {
      -    dirtyPath = this._path;
      -
      -    if (arguments.length) {
      -      if (null != embeddedPath) {
      -        // an embedded doc bubbled up the change
      -        dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
      -      } else {
      -        // directly set an index
      -        dirtyPath = dirtyPath + '.' + elem;
      -      }
      -
      -    }
      -    parent.markModified(dirtyPath);
      -  }
      -
      -  return this;
      -};

      Parameters:

      • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
      • embeddedPath <String> the path which changed in the embeddedDoc

      If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


      MongooseArray#_registerAtomic(op, val)

      Register an atomic operation with the parent.

      show code
      MongooseArray.prototype._registerAtomic = function (op, val) {
      -  if ('$set' == op) {
      -    // $set takes precedence over all other ops.
      -    // mark entire array modified.
      -    this._atomics = { $set: val };
      -    return this;
      -  }
      -
      -  var atomics = this._atomics;
      -
      -  // reset pop/shift after save
      -  if ('$pop' == op && !('$pop' in atomics)) {
      -    var self = this;
      -    this._parent.once('save', function () {
      -      self._popped = self._shifted = null;
      -    });
      -  }
      -
      -  // check for impossible $atomic combos (Mongo denies more than one
      -  // $atomic op on a single path
      -  if (this._atomics.$set ||
      -      Object.keys(atomics).length && !(op in atomics)) {
      -    // a different op was previously registered.
      -    // save the entire thing.
      -    this._atomics = { $set: this };
      -    return this;
      -  }
      -
      -  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
      -    atomics[op] || (atomics[op] = []);
      -    atomics[op] = atomics[op].concat(val);
      -  } else if (op === '$pullDocs') {
      -    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
      -      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
      -    selector['$in'] = selector['$in'].concat(val);
      -  } else {
      -    atomics[op] = val;
      -  }
      -
      -  return this;
      -};

      Parameters:


      MongooseArray#hasAtomics()

      Returns the number of pending atomic operations to send to the db for this array.

      show code
      MongooseArray.prototype.hasAtomics = function hasAtomics () {
      -  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
      -    return 0;
      -  }
      -
      -  return Object.keys(this._atomics).length;
      -}

      Returns:


      MongooseArray#push([args...])

      Wraps Array#push with proper change tracking.

      show code
      MongooseArray.prototype.push = function () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , ret = [].push.apply(this, values);
      -
      -  // $pushAll might be fibbed (could be $push). But it makes it easier to
      -  // handle what could have been $push, $pushAll combos
      -  this._registerAtomic('$pushAll', values);
      -  this._markModified();
      -  return ret;
      -};

      Parameters:


      MongooseArray#nonAtomicPush([args...])

      Pushes items to the array non-atomically.

      show code
      MongooseArray.prototype.nonAtomicPush = function () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , ret = [].push.apply(this, values);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -};

      Parameters:

      • [args...] <any>

      NOTE:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$pop()

      Pops the array atomically at most one time per document save().

      NOTE:

      - -

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      - -
      doc.array = [1,2,3];
      -
      - var popped = doc.array.$pop();
      - console.log(popped); // 3
      - console.log(doc.array); // [1,2]
      -
      - // no affect
      - popped = doc.array.$pop();
      - console.log(doc.array); // [1,2]
      -
      - doc.save(function (err) {
      -   if (err) return handleError(err);
      -
      -   // we saved, now $pop works again
      -   popped = doc.array.$pop();
      -   console.log(popped); // 2
      -   console.log(doc.array); // [1]
      - })

      MongooseArray#pop()

      Wraps Array#pop with proper change tracking.

      show code
      MongooseArray.prototype.pop = function () {
      -  var ret = [].pop.call(this);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -};

      Note:

      - -

      marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$shift()

      Atomically shifts the array at most one time per document save().

      NOTE:

      - -

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      - -
      doc.array = [1,2,3];
      -
      - var shifted = doc.array.$shift();
      - console.log(shifted); // 1
      - console.log(doc.array); // [2,3]
      -
      - // no affect
      - shifted = doc.array.$shift();
      - console.log(doc.array); // [2,3]
      -
      - doc.save(function (err) {
      -   if (err) return handleError(err);
      -
      -   // we saved, now $shift works again
      -   shifted = doc.array.$shift();
      -   console.log(shifted ); // 2
      -   console.log(doc.array); // [3]
      - })

      MongooseArray#shift()

      Wraps Array#shift with proper change tracking.

      show code
      MongooseArray.prototype.shift = function () {
      -  var ret = [].shift.call(this);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -};

      Example:

      - -
      doc.array = [2,3];
      -var res = doc.array.shift();
      -console.log(res) // 2
      -console.log(doc.array) // [3]
      - -

      Note:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#remove([args...])

      Removes items from an array atomically

      show code
      MongooseArray.prototype.remove = function () {
      -  var args = [].map.call(arguments, this._cast, this);
      -  if (args.length == 1)
      -    this.pull(args[0]);
      -  else
      -    this.pull.apply(this, args);
      -  return args;
      -};

      Parameters:

      • [args...] <Object> values to remove

      Examples:

      - -
      doc.array.remove(ObjectId)
      -doc.array.remove('tag 1', 'tag 2')

      MongooseArray#pull([args...])

      Pulls items from the array atomically.

      show code
      MongooseArray.prototype.pull = function () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , cur = this._parent.get(this._path)
      -    , i = cur.length
      -    , mem;
      -
      -  while (i--) {
      -    mem = cur[i];
      -    if (mem instanceof EmbeddedDocument) {
      -      if (values.some(function (v) { return v.equals(mem); } )) {
      -        [].splice.call(cur, i, 1);
      -      }
      -    } else if (~cur.indexOf.call(values, mem)) {
      -      [].splice.call(cur, i, 1);
      -    }
      -  }
      -
      -  if (values[0] instanceof EmbeddedDocument) {
      -    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
      -  } else {
      -    this._registerAtomic('$pullAll', values);
      -  }
      -
      -  this._markModified();
      -  return this;
      -};

      Parameters:

      • [args...] <any>

      MongooseArray#splice()

      Wraps Array#splice with proper change tracking and casting.

      show code
      MongooseArray.prototype.splice = function splice () {
      -  var ret, vals, i;
      -
      -  if (arguments.length) {
      -    vals = [];
      -    for (i = 0; i < arguments.length; ++i) {
      -      vals[i] = i < 2
      -        ? arguments[i]
      -        : this._cast(arguments[i]);
      -    }
      -    ret = [].splice.apply(this, vals);
      -    this._registerAtomic('$set', this);
      -    this._markModified();
      -  }
      -
      -  return ret;
      -}

      Note:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#unshift()

      Wraps Array#unshift with proper change tracking.

      show code
      MongooseArray.prototype.unshift = function () {
      -  var values = [].map.call(arguments, this._cast, this);
      -  [].unshift.apply(this, values);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return this.length;
      -};

      Note:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#sort()

      Wraps Array#sort with proper change tracking.

      show code
      MongooseArray.prototype.sort = function () {
      -  var ret = [].sort.apply(this, arguments);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -}

      NOTE:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#addToSet([args...])

      Adds values to the array if not already present.

      show code
      MongooseArray.prototype.addToSet = function addToSet () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , added = []
      -    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
      -             values[0] instanceof Date ? 'date' :
      -             '';
      -
      -  values.forEach(function (v) {
      -    var found;
      -    switch (type) {
      -      case 'doc':
      -        found = this.some(function(doc){ return doc.equals(v) });
      -        break;
      -      case 'date':
      -        var val = +v;
      -        found = this.some(function(d){ return +d === val });
      -        break;
      -      default:
      -        found = ~this.indexOf(v);
      -    }
      -
      -    if (!found) {
      -      [].push.call(this, v);
      -      this._registerAtomic('$addToSet', v);
      -      this._markModified();
      -      [].push.call(added, v);
      -    }
      -  }, this);
      -
      -  return added;
      -};

      Parameters:

      • [args...] <any>

      Returns:

      • <Array> the values that were added

      Example:

      - -
      console.log(doc.array) // [2,3,4]
      -var added = doc.array.addToSet(4,5);
      -console.log(doc.array) // [2,3,4,5]
      -console.log(added)     // [5]

      MongooseArray#set()

      Sets the casted val at index i and marks the array modified.

      show code
      MongooseArray.prototype.set = function set (i, val) {
      -  this[i] = this._cast(val);
      -  this._markModified(i);
      -  return this;
      -}

      Returns:

      Example:

      - -
      // given documents based on the following
      -var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
      -
      -var doc = new Doc({ array: [2,3,4] })
      -
      -console.log(doc.array) // [2,3,4]
      -
      -doc.array.set(1,"5");
      -console.log(doc.array); // [2,5,4] // properly cast to number
      -doc.save() // the change is saved
      -
      -// VS not using array#set
      -doc.array[1] = "5";
      -console.log(doc.array); // [2,"5",4] // no casting
      -doc.save() // change is not saved

      MongooseArray#toObject(options)

      Returns a native js Array.

      show code
      MongooseArray.prototype.toObject = function (options) {
      -  if (options && options.depopulate && this[0] instanceof Document) {
      -    return this.map(function (doc) {
      -      return doc._id;
      -    });
      -  }
      -
      -  // return this.slice()?
      -  return this.map(function (doc) {
      -    return doc;
      -  });
      -};

      Parameters:

      Returns:


      MongooseArray#inspect()

      Helper for console.log

      show code
      MongooseArray.prototype.inspect = function () {
      -  return '[' + this.map(function (doc) {
      -    return ' ' + doc;
      -  }) + ' ]';
      -};

      MongooseArray#indexOf(obj)

      Return the index of obj or -1 if not found.

      show code
      MongooseArray.prototype.indexOf = function indexOf (obj) {
      -  if (obj instanceof ObjectId) obj = obj.toString();
      -  for (var i = 0, len = this.length; i < len; ++i) {
      -    if (obj == this[i])
      -      return i;
      -  }
      -  return -1;
      -};

      Parameters:

      • obj <Object> the item to look for

      Returns:


      MongooseArray#_parent

      Parent owner document


      MongooseArray#_atomics

      Stores a queue of atomic operations to perform


    • types/buffer.js

      MongooseBuffer(value, encode, offset)

      Mongoose Buffer constructor.

      show code
      function MongooseBuffer (value, encode, offset) {
      -  var length = arguments.length;
      -  var val;
      -
      -  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
      -    val = 0;
      -  } else {
      -    val = value;
      -  }
      -
      -  var encoding;
      -  var path;
      -  var doc;
      -
      -  if (Array.isArray(encode)) {
      -    // internal casting
      -    path = encode[0];
      -    doc = encode[1];
      -  } else {
      -    encoding = encode;
      -  }
      -
      -  var buf = new Buffer(val, encoding, offset);
      -  buf.__proto__ = MongooseBuffer.prototype;
      -
      -  // make sure these internal props don't show up in Object.keys()
      -  Object.defineProperties(buf, {
      -      validators: { value: [] }
      -    , _path: { value: path }
      -    , _parent: { value: doc }
      -  });
      -
      -  if (doc && "string" === typeof path) {
      -    Object.defineProperty(buf, '_schema', {
      -        value: doc.schema.path(path)
      -    });
      -  }
      -
      -  return buf;
      -};

      Parameters:

      Inherits:

      Values always have to be passed to the constructor to initialize.


      MongooseBuffer#_markModified()

      Marks this buffer as modified.

      show code
      MongooseBuffer.prototype._markModified = function () {
      -  var parent = this._parent;
      -
      -  if (parent) {
      -    parent.markModified(this._path);
      -  }
      -  return this;
      -};

      MongooseBuffer#write()

      Writes the buffer.

      show code
      MongooseBuffer.prototype.write = function () {
      -  var written = Buffer.prototype.write.apply(this, arguments);
      -
      -  if (written > 0) {
      -    this._markModified();
      -  }
      -
      -  return written;
      -};

      MongooseBuffer#copy(target)

      Copies the buffer.

      show code
      MongooseBuffer.prototype.copy = function (target) {
      -  var ret = Buffer.prototype.copy.apply(this, arguments);
      -
      -  if (target instanceof MongooseBuffer) {
      -    target._markModified();
      -  }
      -
      -  return ret;
      -};

      Parameters:

      Returns:

      Note:

      - -

      Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


      MongooseBuffer#toObject([subtype])

      Converts this buffer to its Binary type representation.

      show code
      MongooseBuffer.prototype.toObject = function (subtype) {
      -  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
      -  return new Binary(this, subtype);
      -};

      Parameters:

      • [subtype] <Hex>

      Returns:

      SubTypes:

      - -
        -
      • 0x00: Binary/Generic
      • -
      • 0x01: Function
      • -
      • 0x02: Binary (Deprecated, 0x00 is new default)
      • -
      • 0x03: UUID
      • -
      • 0x04: MD5
      • -
      • 0x80: User Defined
      • -

      MongooseBuffer#_parent

      Parent owner document


    • types/documentarray.js

      MongooseDocumentArray(values, path, doc)

      DocumentArray constructor

      show code
      function MongooseDocumentArray (values, path, doc) {
      -  var arr = [];
      -
      -  // Values always have to be passed to the constructor to initialize, since
      -  // otherwise MongooseArray#push will mark the array as modified to the parent.
      -  arr.push.apply(arr, values);
      -  arr.__proto__ = MongooseDocumentArray.prototype;
      -
      -  arr._atomics = {};
      -  arr.validators = [];
      -  arr._path = path;
      -
      -  if (doc) {
      -    arr._parent = doc;
      -    arr._schema = doc.schema.path(path);
      -    doc.on('save', arr.notify('save'));
      -    doc.on('isNew', arr.notify('isNew'));
      -  }
      -
      -  return arr;
      -};

      Parameters:

      Inherits:


      MongooseDocumentArray#_cast()

      Overrides MongooseArray#cast

      show code
      MongooseDocumentArray.prototype._cast = function (value) {
      -  if (value instanceof this._schema.casterConstructor)
      -    return value;
      -
      -  return new this._schema.casterConstructor(value, this);
      -};

      MongooseDocumentArray#id(id)

      Searches array items for the first document with a matching id.

      show code
      MongooseDocumentArray.prototype.id = function (id) {
      -  var casted
      -    , _id;
      -
      -  try {
      -    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
      -  } catch (e) {
      -    casted = null;
      -  }
      -
      -  for (var i = 0, l = this.length; i < l; i++) {
      -    _id = this[i].get('_id');
      -    if (!(_id instanceof ObjectId)) {
      -      if (String(id) == _id)
      -        return this[i];
      -    } else {
      -      if (casted == _id)
      -        return this[i];
      -    }
      -  }
      -
      -  return null;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var embeddedDoc = m.array.id(some_id);

      MongooseDocumentArray#toObject()

      Returns a native js Array of plain js objects

      show code
      MongooseDocumentArray.prototype.toObject = function () {
      -  return this.map(function (doc) {
      -    return doc && doc.toObject() || null;
      -  });
      -};

      Returns:

      NOTE:

      - -

      Each sub-document is converted to a plain object by calling its #toObject method.


      MongooseDocumentArray#inspect()

      Helper for console.log

      show code
      MongooseDocumentArray.prototype.inspect = function () {
      -  return '[' + this.map(function (doc) {
      -    if (doc) {
      -      return doc.inspect
      -        ? doc.inspect()
      -        : util.inspect(doc)
      -    }
      -    return 'null'
      -  }).join('
      -') + ']';
      -};

      MongooseDocumentArray#create(obj)

      Creates a subdocument casted to this schema.

      show code
      MongooseDocumentArray.prototype.create = function (obj) {
      -  return new this._schema.casterConstructor(obj);
      -}

      Parameters:

      • obj <Object> the value to cast to this arrays SubDocument schema

      This is the same subdocument constructor used for casting.


      MongooseDocumentArray#notify(event)

      Creates a fn that notifies all child docs of event.

      show code
      MongooseDocumentArray.prototype.notify = function notify (event) {
      -  var self = this;
      -  return function notify (val) {
      -    var i = self.length;
      -    while (i--) {
      -      if (!self[i]) continue;
      -      self[i].emit(event, val);
      -    }
      -  }
      -}

      Parameters:

      Returns:


    • types/embedded.js

      EmbeddedDocument(obj, parentArr, skipId)

      EmbeddedDocument constructor.

      show code
      function EmbeddedDocument (obj, parentArr, skipId, fields) {
      -  if (parentArr) {
      -    this.__parentArray = parentArr;
      -    this.__parent = parentArr._parent;
      -  } else {
      -    this.__parentArray = undefined;
      -    this.__parent = undefined;
      -  }
      -
      -  Document.call(this, obj, fields, skipId);
      -
      -  var self = this;
      -  this.on('isNew', function (val) {
      -    self.isNew = val;
      -  });
      -};

      Parameters:

      Inherits:


      EmbeddedDocument#markModified(path)

      Marks the embedded doc modified.

      show code
      EmbeddedDocument.prototype.markModified = function (path) {
      -  if (!this.__parentArray) return;
      -
      -  this._activePaths.modify(path);
      -
      -  if (this.isNew) {
      -    // Mark the WHOLE parent array as modified
      -    // if this is a new document (i.e., we are initializing
      -    // a document),
      -    this.__parentArray._markModified();
      -  } else
      -    this.__parentArray._markModified(this, path);
      -};

      Parameters:

      • path <String> the path which changed

      Example:

      - -
      var doc = blogpost.comments.id(hexstring);
      -doc.mixed.type = 'changed';
      -doc.markModified('mixed.type');

      EmbeddedDocument#save([fn])

      Used as a stub for hooks.js

      show code
      EmbeddedDocument.prototype.save = function(fn) {
      -  if (fn)
      -    fn(null);
      -  return this;
      -};

      Parameters:

      Returns:

      NOTE:

      - -

      This is a no-op. Does not actually save the doc to the db.


      EmbeddedDocument#remove([fn])

      Removes the subdocument from its parent array.

      show code
      EmbeddedDocument.prototype.remove = function (fn) {
      -  if (!this.__parentArray) return this;
      -
      -  var _id;
      -  if (!this.willRemove) {
      -    _id = this._doc._id;
      -    if (!_id) {
      -      throw new Error('For your own good, Mongoose does not know ' + 
      -                      'how to remove an EmbeddedDocument that has no _id');
      -    }
      -    this.__parentArray.pull({ _id: _id });
      -    this.willRemove = true;
      -  }
      -
      -  if (fn)
      -    fn(null);
      -
      -  return this;
      -};

      Parameters:


      EmbeddedDocument#update()

      Override #update method of parent documents.

      show code
      EmbeddedDocument.prototype.update = function () {
      -  throw new Error('The #update method is not available on EmbeddedDocuments');
      -}

      EmbeddedDocument#inspect()

      Helper for console.log

      show code
      EmbeddedDocument.prototype.inspect = function () {
      -  return inspect(this.toObject());
      -};

      EmbeddedDocument#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
      -  if (!this.__parent) return false;
      -  var index = this.__parentArray.indexOf(this);
      -  var parentPath = this.__parentArray._path;
      -  var fullPath = [parentPath, index, path].join('.');
      -  this.__parent.invalidate(fullPath, err);
      -  if (first)
      -    this._validationError = ownerDocument(this)._validationError;
      -  return true;
      -}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> error which states the reason `path` was invalid

      Returns:


      EmbeddedDocument#ownerDocument()

      Returns the top level document of this sub-document.

      show code
      EmbeddedDocument.prototype.ownerDocument = function () {
      -  return ownerDocument(this);
      -}

      Returns:


      EmbeddedDocument#parent()

      Returns this sub-documents parent document.

      show code
      EmbeddedDocument.prototype.parent = function () {
      -  return this.__parent;
      -}

      EmbeddedDocument#parentArray()

      Returns this sub-documents parent array.

      show code
      EmbeddedDocument.prototype.parentArray = function () {
      -  return this.__parentArray;
      -}

    • types/objectid.js

      ObjectId()

      ObjectId type constructor

      Example

      - -
      var id = new mongoose.Types.ObjectId;

      ObjectId.fromString(str)

      Creates an ObjectId from str

      show code
      ObjectId.fromString;

      Parameters:

      Returns:


      ObjectId.toString(oid)

      Converts oid to a string.

      show code
      ObjectId.toString;

      Parameters:

      Returns:


    • utils.js

      exports.toCollectionName(name)

      Produces a collection name from model name.

      show code
      exports.toCollectionName = function (name) {
      -  if ('system.profile' === name) return name;
      -  if ('system.indexes' === name) return name;
      -  return pluralize(name.toLowerCase());
      -};

      Parameters:

      Returns:


      exports.pluralization

      Pluralization rules.

      show code
      exports.pluralization = [
      -  [/(m)an$/gi, '$1en'],
      -  [/(pe)rson$/gi, '$1ople'],
      -  [/(child)$/gi, '$1ren'],
      -  [/^(ox)$/gi, '$1en'],
      -  [/(ax|test)is$/gi, '$1es'],
      -  [/(octop|vir)us$/gi, '$1i'],
      -  [/(alias|status)$/gi, '$1es'],
      -  [/(bu)s$/gi, '$1ses'],
      -  [/(buffal|tomat|potat)o$/gi, '$1oes'],
      -  [/([ti])um$/gi, '$1a'],
      -  [/sis$/gi, 'ses'],
      -  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
      -  [/(hive)$/gi, '$1s'],
      -  [/([^aeiouy]|qu)y$/gi, '$1ies'],
      -  [/(x|ch|ss|sh)$/gi, '$1es'],
      -  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
      -  [/([m|l])ouse$/gi, '$1ice'],
      -  [/(quiz)$/gi, '$1zes'],
      -  [/s$/gi, 's'],
      -  [/$/gi, 's']
      -];
      -var rules = exports.pluralization;

      These rules are applied while processing the argument to toCollectionName.


      exports.uncountables

      Uncountable words.

      show code
      exports.uncountables = [
      -  'advice',
      -  'energy',
      -  'excretion',
      -  'digestion',
      -  'cooperation',
      -  'health',
      -  'justice',
      -  'labour',
      -  'machinery',
      -  'equipment',
      -  'information',
      -  'pollution',
      -  'sewage',
      -  'paper',
      -  'money',
      -  'species',
      -  'series',
      -  'rain',
      -  'rice',
      -  'fish',
      -  'sheep',
      -  'moose',
      -  'deer',
      -  'news',
      -  'expertise',
      -  'status',
      -  'media'
      -];
      -var uncountables = exports.uncountables;

      These words are applied while processing the argument to toCollectionName.


      exports.deepEqual(a, b)

      Determines if a and b are deep equal.

      show code
      exports.deepEqual = function deepEqual (a, b) {
      -  if (a === b) return true;
      -
      -  if (a instanceof Date && b instanceof Date)
      -    return a.getTime() === b.getTime();
      -
      -  if (a instanceof ObjectId && b instanceof ObjectId) {
      -    return a.toString() === b.toString();
      -  }
      -
      -  if (typeof a !== 'object' && typeof b !== 'object')
      -    return a == b;
      -
      -  if (a === null || b === null || a === undefined || b === undefined)
      -    return false
      -
      -  if (a.prototype !== b.prototype) return false;
      -
      -  // Handle MongooseNumbers
      -  if (a instanceof Number && b instanceof Number) {
      -    return a.valueOf() === b.valueOf();
      -  }
      -
      -  if (Buffer.isBuffer(a)) {
      -    if (!Buffer.isBuffer(b)) return false;
      -    if (a.length !== b.length) return false;
      -    for (var i = 0, len = a.length; i < len; ++i) {
      -      if (a[i] !== b[i]) return false;
      -    }
      -    return true;
      -  }
      -
      -  if (isMongooseObject(a)) a = a.toObject();
      -  if (isMongooseObject(b)) b = b.toObject();
      -
      -  try {
      -    var ka = Object.keys(a),
      -        kb = Object.keys(b),
      -        key, i;
      -  } catch (e) {//happens when one is a string literal and the other isn't
      -    return false;
      -  }
      -
      -  // having the same number of owned properties (keys incorporates
      -  // hasOwnProperty)
      -  if (ka.length != kb.length)
      -    return false;
      -
      -  //the same set of keys (although not necessarily the same order),
      -  ka.sort();
      -  kb.sort();
      -
      -  //~~~cheap key test
      -  for (i = ka.length - 1; i >= 0; i--) {
      -    if (ka[i] != kb[i])
      -      return false;
      -  }
      -
      -  //equivalent values for every corresponding key, and
      -  //~~~possibly expensive deep test
      -  for (i = ka.length - 1; i >= 0; i--) {
      -    key = ka[i];
      -    if (!deepEqual(a[key], b[key])) return false;
      -  }
      -
      -  return true;
      -};

      Parameters:

      • a <any> a value to compare to `b`
      • b <any> a value to compare to `a`

      Returns:

      Modified from node/lib/assert.js


      exports.clone(obj, options)

      Object clone with Mongoose natives support.

      show code
      exports.clone = function clone (obj, options) {
      -  if (obj === undefined || obj === null)
      -    return obj;
      -
      -  if (Array.isArray(obj))
      -    return cloneArray(obj, options);
      -
      -  if (isMongooseObject(obj)) {
      -    if (options && options.json && 'function' === typeof obj.toJSON) {
      -      return obj.toJSON(options);
      -    } else {
      -      return obj.toObject(options);
      -    }
      -  }
      -
      -  if ('Object' === obj.constructor.name)
      -    return cloneObject(obj, options);
      -
      -  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
      -    return new obj.constructor(+obj);
      -
      -  if ('RegExp' === obj.constructor.name)
      -    return new RegExp(obj.source);
      -
      -  if (obj instanceof ObjectId) {
      -    return new ObjectId(obj.id);
      -  }
      -
      -  if (obj.valueOf)
      -    return obj.valueOf();
      -};
      -var clone = exports.clone;

      Parameters:

      Returns:

      Creates a minimal data Object.
      It does not clone empty Arrays, empty Objects, and undefined values.
      This makes the data payload sent to MongoDB as minimal as possible.


      exports.options(defaults, options)

      Copies and merges options with defaults.

      show code
      exports.options = function (defaults, options) {
      -  var keys = Object.keys(defaults)
      -    , i = keys.length
      -    , k ;
      -
      -  options = options || {};
      -
      -  while (i--) {
      -    k = keys[i];
      -    if (!(k in options)) {
      -      options[k] = defaults[k];
      -    }
      -  }
      -
      -  return options;
      -};

      Parameters:

      Returns:


      exports.random()

      Generates a random string

      show code
      exports.random = function () {
      -  return Math.random().toString().substr(3);
      -};

      exports.merge(to, from)

      Merges from into to without overwriting existing properties.

      show code
      exports.merge = function merge (to, from) {
      -  var keys = Object.keys(from)
      -    , i = keys.length
      -    , key
      -
      -  while (i--) {
      -    key = keys[i];
      -    if ('undefined' === typeof to[key]) {
      -      to[key] = from[key];
      -    } else {
      -      merge(to[key], from[key]);
      -    }
      -  }
      -};

      Parameters:


      exports.args

      A faster Array.prototype.slice.call(arguments) alternative

      show code
      exports.args = sliced;

      exports.tick(callback)

      process.nextTick helper.

      show code
      exports.tick = function tick (callback) {
      -  if ('function' !== typeof callback) return;
      -  return function () {
      -    try {
      -      callback.apply(this, arguments);
      -    } catch (err) {
      -      // only nextTick on err to get out of
      -      // the event loop and avoid state corruption.
      -      process.nextTick(function () {
      -        throw err;
      -      });
      -    }
      -  }
      -}

      Parameters:

      Wraps callback in a try/catch + nextTick.

      - -

      node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


      exports.isMongooseObject(v)

      Returns if v is a mongoose object that has a toObject() method we can use.

      show code
      exports.isMongooseObject = function (v) {
      -  Document || (Document = require('./document'));
      -  MongooseArray || (MongooseArray = require('./types').Array);
      -  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
      -
      -  return v instanceof Document ||
      -         v instanceof MongooseArray ||
      -         v instanceof MongooseBuffer
      -}
      -var isMongooseObject = exports.isMongooseObject;

      Parameters:

      This is for compatibility with libs like Date.js which do foolish things to Natives.


      exports.expires(object)

      Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

      show code
      exports.expires = function expires (object) {
      -  if (!(object && 'Object' == object.constructor.name)) return;
      -  if (!('expires' in object)) return;
      -
      -  var when;
      -  if ('string' != typeof object.expires) {
      -    when = object.expires;
      -  } else {
      -    when = Math.round(ms(object.expires) / 1000);
      -  }
      -  object.expireAfterSeconds = when;
      -  delete object.expires;
      -}
      -
      -exports.readPref = function readPref (pref, tags) {
      -  if (Array.isArray(pref)) {
      -    tags = pref[1];
      -    pref = pref[0];
      -  }
      -
      -  switch (pref) {
      -    case 'p':
      -      pref = 'primary';
      -      break;
      -    case 'pp':
      -      pref = 'primaryPrefered';
      -      break;
      -    case 's':
      -      pref = 'secondary';
      -      break;
      -    case 'sp':
      -      pref = 'secondaryPrefered';
      -      break;
      -    case 'n':
      -      pref = 'nearest';
      -      break;
      -  }
      -
      -  return new ReadPref(pref, tags);
      -}

      Parameters:


    • virtualtype.js

      VirtualType()

      VirtualType constructor

      show code
      function VirtualType (options, name) {
      -  this.path = name;
      -  this.getters = [];
      -  this.setters = [];
      -  this.options = options || {};
      -}

      This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

      - -

      Example:

      - -
      var fullname = schema.virtual('fullname');
      -fullname instanceof mongoose.VirtualType // true

      VirtualType#get(fn)

      Defines a getter.

      show code
      VirtualType.prototype.get = function (fn) {
      -  this.getters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var virtual = schema.virtual('fullname');
      -virtual.get(function () {
      -  return this.name.first + ' ' + this.name.last;
      -});

      VirtualType#set(fn)

      Defines a setter.

      show code
      VirtualType.prototype.set = function (fn) {
      -  this.setters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var virtual = schema.virtual('fullname');
      -virtual.set(function (v) {
      -  var parts = v.split(' ');
      -  this.name.first = parts[0];
      -  this.name.last = parts[1];
      -});

      VirtualType#applyGetters(value, scope)

      Applies getters to value using optional scope.

      show code
      VirtualType.prototype.applyGetters = function (value, scope) {
      -  var v = value;
      -  for (var l = this.getters.length - 1; l >= 0; l--) {
      -    v = this.getters[l].call(scope, v, this);
      -  }
      -  return v;
      -};

      Parameters:

      Returns:

      • <any> the value after applying all getters

      VirtualType#applySetters(value, scope)

      Applies setters to value using optional scope.

      show code
      VirtualType.prototype.applySetters = function (value, scope) {
      -  var v = value;
      -  for (var l = this.setters.length - 1; l >= 0; l--) {
      -    v = this.setters[l].call(scope, v, this);
      -  }
      -  return v;
      -};

      Parameters:

      Returns:

      • <any> the value after applying all setters

    diff --git a/docs/3.3.x/docs/api.jade b/docs/3.3.x/docs/api.jade deleted file mode 100644 index 2a4b855e3f2..00000000000 --- a/docs/3.3.x/docs/api.jade +++ /dev/null @@ -1,517 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose API v#{package.version} - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='/docs/css/default.css', rel='stylesheet', type='text/css') - style. - body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; - } - a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; - } - a:hover { - opacity: 0.8; - } - #wrap { - } - h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; - } - pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; - } - code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Monaco; - } - pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; - } - h3 { - padding: 20px 15px; - margin-left: -15px; - } - h3 code { - font-weight: normal; - } - hr { - height: 1px; - border: 0 none; - padding: 0; - margin: 60px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) - } - .doclinks hr { - margin: 10px 0; - } - li { - list-style: square; - } - #header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; - } - #header h1 { - margin-top: 0; - margin-bottom: 0; - } - #header h1 a { - text-decoration: none; - } - #header .mongoose { - font-size: 48px; - font-weight: 100; - color: #fff; - letter-spacing: -5px; - } - #links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - } - #links hr { - margin: 32px 0; - } - #content { - padding: 0; - margin: 0 0 30px 230px; - overflow-x: hidden; - } - #content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; - } - #content .controls:hover { - opacity: .9; - } - #content p { - word-wrap: break-word; - } - #content > ul { - margin: 0; - padding: 0; - } - .private { - display: none; - } - .section { - font-size: 15px; - } - .doclinks li.private a:before, - .doclinks .module.private a:before, - .doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; - } - #content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; - } - .module { - list-style: none; - padding: 30px 0 30px 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; - } - .module > * { - max-width: 700px; - } - .item:last-child { - margin-bottom: 90px; - } - .item:last-child > hr { - display: none; - } - .item h3 a { - color: #333; - text-decoration: none; - } - .property h3 span { - color: #444; - } - .description { - margin-top: 25px; - } - .sourcecode { - display: none; - } - .showcode { - font-size: 12px; - cursor: pointer; - display: none; - } - .load .showcode { - display: block; - } - .types a { - text-decoration: none; - } - @media only screen and (device-width: 768px) { - - } - @media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links hr { - display: none; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - .controls { display: none; } - } - body.api - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - hr - .doclinks - each item in docs - .file(class=item.hasPublic ? '' : 'private') - a.section(href='#' + item.title.replace(/[\.\/#]/g, '-'))= item.title - ul - each method in item.methods - if method.ctx && !method.ignore - li(class= method.isPrivate ? 'private' : '') - case method.ctx.type - when 'method' - id = method.ctx.constructor + '-' + method.ctx.name - when 'function' - id = method.ctx.name - default - id = '' - url = href(klass(item.title) + '_' + id) - a(href='#' + url)= method.ctx.name - each stat in item.statics - if stat.ctx && !stat.ignore - li(class= stat.isPrivate ? 'private' : '') - case stat.ctx.type - when 'method' - id = stat.ctx.receiver + '-' + stat.ctx.name - when 'property' - id = stat.ctx.receiver + '-' + stat.ctx.name - when 'function' - id = stat.ctx.name - url = href(klass(item.title) + '_' + id) - a(href='#' + url)= stat.ctx.name - each property in item.props - if property.ctx && !property.ignore - li(class= property.isPrivate ? 'private' : '') - construct = property.ctx.receiver || property.ctx.constructor - link = href(construct) + '-' + href(property.ctx.name) - url = href(klass(item.title) + '_' + link) - a(href='#' + url)= property.ctx.name - #content - .controls - label - input(type='checkbox') - | private - ul - each item in docs - li.module(class=item.hasPublic ? '' : 'private') - a(href=github + package.version + '/' + item.title, id=item.title.replace(/[\.\/#]/g, '-'))= item.title - each method in item.methods - div.item.method(class= method.isPrivate ? 'private' : 'public') - if method.ctx - case method.ctx.type - when 'method' - id = method.ctx.constructor + '-' + method.ctx.name - text = method.ctx.constructor + '#' + method.ctx.name - when 'function' - id = method.ctx.name - text = method.ctx.name - default - text = '' - url = href(klass(item.title) + '_' + text) - h3(id= url) - a(href= '#' + url) - = text - | ( - each tag, i in method.params - code= tag.name - if i+1 < method.params.length - | , - | ) - else - - // console.log('\nmissing method name', method); - h3 MISSING method name - != method.description.summary - if method.code - span.showcode show code - .sourcecode - != hl(method.code) - if method.params.length - .params - h4 Parameters: - ul - each tag in method.params - li - code= tag.name - if tag.types && tag.types.length - span.types - | < - each type, i in tag.types - != linktype(type) - if i+1 < tag.types.length - | , - | > - span= tag.description - if method.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in method.return.types - != linktype(type) - if i+1 < method.return.types.length - | , - | > - span= method.return.description - if method.inherits - .inherits - h4 Inherits: - ul - li - != method.inherits - if method.events && method.events.length - .events - h4 Events: - ul - each event in method.events - li - != event.string - if method.see.length - .see - h4 See: - ul.see - each see in method.see - li - url = see.url || see.local - a(href=url, title=see.title || see.local)= see.title || see.url || see.local - div.description - != method.description.body - hr(class= method.isPrivate ? 'private' : '') - each stat in item.statics - div.item.static(class= stat.isPrivate ? 'private' : 'public') - if stat.ctx - case stat.ctx.type - when 'method' - id = stat.ctx.receiver + '-' + stat.ctx.name - text = stat.ctx.receiver + '.' + stat.ctx.name - when 'property' - id = stat.ctx.receiver + '-' + stat.ctx.name - text = stat.ctx.receiver + '.' + stat.ctx.name - when 'function' - id = stat.ctx.name - text = stat.ctx.name - default - text = '' - url = href(klass(item.title) + '_' + id) - h3(id= url) - a(href= '#' + url) - = text - if 'property' != stat.ctx.type - | ( - each tag, i in stat.params - code= tag.name - if i+1 < stat.params.length - | , - | ) - else - - // console.log('\nmissing static name', stat); - h3 MISSING stat name - != stat.description.summary - if stat.code - span.showcode show code - .sourcecode - != hl(stat.code) - if stat.params.length - .params - h4 Parameters: - ul - each tag in stat.params - li - - if (!tag.name) - - // console.log(tag) - code= tag.name - if tag.types && tag.types.length - span.types - | < - each type, i in tag.types - != linktype(type) - if i+1 < tag.types.length - | , - | > - span= tag.description - if stat.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in stat.return.types - != linktype(type) - if i+1 < stat.return.types.length - | , - | > - span= stat.return.description - if stat.inherits - .inherits - h4 Inherits: - ul - li - != stat.inherits - if stat.see.length - .see - h4 See: - ul.see - each see in stat.see - li - url = see.url || see.local - a(href=url, title=see.title || see.local)= see.title || see.url || see.local - != stat.description.body - hr(class= stat.isPrivate ? 'private' : '') - each property in item.props - div.item.property(class= property.ignore || property.isPrivate ? 'private' : 'public') - construct = property.ctx.receiver || property.ctx.constructor - link = href(construct) + '-' + href(property.ctx.name) - url = href(klass(item.title) + '_' + link) - h3(id = url) - a(href= '#' + url) - = construct + '#' - span= property.ctx.name - != property.description.full - if property.return - .returns - h4 Returns: - ul - li - span.types - | < - each type, i in property.return.types - != linktype(type) - if i+1 < property.return.types.length - | , - | > - span= property.return.description - hr(class= property.isPrivate ? 'private' : '') - script. - document.body.className = 'load'; - include includes/googleanalytics - script(src="/docs/js/zepto.min.js") - script(src="/docs/js/cookies.min.js") - script. - $(".module").on("click", ".showcode", function (e) { - $(this).closest(".item").find(".sourcecode").first().toggle(); - }); - $("#content .controls input").on("click", function (e) { - $(".private").toggle() - var checked = $(this).prop('checked'); - Cookies.set('prv', checked); - }); - ;(function(){ - var checked = 'true' === Cookies.get('prv'); - if (checked) { - $("#content .controls input").prop('checked', 'checked'); - $(".private").show() - } - })() diff --git a/docs/3.3.x/docs/connections.html b/docs/3.3.x/docs/connections.html deleted file mode 100644 index 056b76affcf..00000000000 --- a/docs/3.3.x/docs/connections.html +++ /dev/null @@ -1,27 +0,0 @@ -Mongoose Connecting to MongoDB v3.3.1Fork me on GitHub

    Connections

    We may connect to MongoDB by utilizing the mongoose.connect() method.

    mongoose.connect('mongodb://localhost/myapp');
    -

    This is the minimum needed to connect the myapp database running locally on the default port (27017). We may also specify several more parameters in the uri depending on your environment:

    mongoose.connect('mongodb://username:password@host:port/database');
    -

    Options

    The connect method also accepts an options object which will be passed on to the underlying driver.

    mongoose.connect(uri, options);
    -

    The following option keys are available:

    - -
     db      - passed to the connection db instance
    - server  - passed to the connection server instance(s)
    - replset - passed to the connection ReplSet instance
    - user    - username for authentication (if not specified in uri)
    - pass    - password for authentication (if not specified in uri)
    - -

    See the driver for more information about available options.

    - -

    Note: The server option auto_reconnect is defaulted to true.

    - -

    Note: The db option forceServerObjectId is set to false and cannot be overridden.

    ReplicaSet Connections

    The same method is used to connect to a replica set but instead of passing a single uri we pass a comma delimited list of uris.

    mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]);
    -

    NOTE: The database need only be specified in one of the uris.

    Multiple connections

    So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize mongoose.createConnection() which accepts all the arguments already discussed and returns a fresh connection for you.

    var conn = mongoose.createConnection('uri,uri,uri...', options);
    -

    Connection pools

    Each connection, whether created with mongoose.connect or mongoose.createConnection are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options:

    mongoose.createConnection(uri, { server: { poolSize: 10 }});
    -

    Next Up

    Now that we've covered connections, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

    diff --git a/docs/3.3.x/docs/connections.jade b/docs/3.3.x/docs/connections.jade deleted file mode 100644 index 5e67abc8a4b..00000000000 --- a/docs/3.3.x/docs/connections.jade +++ /dev/null @@ -1,65 +0,0 @@ -extends layout - -block content - h2 Connections - :markdown - We may connect to MongoDB by utilizing the `mongoose.connect()` method. - - :js - mongoose.connect('mongodb://localhost/myapp'); - - :markdown - This is the minimum needed to connect the `myapp` database running locally on the default port (27017). We may also specify several more parameters in the `uri` depending on your environment: - - :js - mongoose.connect('mongodb://username:password@host:port/database'); - - h3 Options - :markdown - The `connect` method also accepts an `options` object which will be passed on to the underlying driver. - - :js - mongoose.connect(uri, options); - - :markdown - The following option keys are available: - - db - passed to the connection db instance - server - passed to the connection server instance(s) - replset - passed to the connection ReplSet instance - user - username for authentication (if not specified in uri) - pass - password for authentication (if not specified in uri) - - See the [driver](https://github.com/mongodb/node-mongodb-native) for more information about available options. - - _Note: The server option `auto_reconnect` is defaulted to true._ - - _Note: The db option `forceServerObjectId` is set to false and cannot be overridden._ - - h3 ReplicaSet Connections - :markdown - The same method is used to connect to a replica set but instead of passing a single `uri` we pass a comma delimited list of `uri`s. - - :js - mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]); - - :markdown - _NOTE: The `database` need only be specified in one of the `uri`s._ - - h3 Multiple connections - :markdown - So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize `mongoose.createConnection()` which accepts all the arguments already discussed and returns a fresh connection for you. - - :js - var conn = mongoose.createConnection('uri,uri,uri...', options); - - h3 Connection pools - :markdown - Each `connection`, whether created with `mongoose.connect` or `mongoose.createConnection` are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options: - - :js - mongoose.createConnection(uri, { server: { poolSize: 10 }}); - - h3#next Next Up - :markdown - Now that we've covered `connections`, let's take a look at how we can break pieces of our functionality out into reusable and shareable [plugins](/docs/plugins.html). diff --git a/docs/3.3.x/docs/contributing.html b/docs/3.3.x/docs/contributing.html deleted file mode 100644 index b7c60dc4438..00000000000 --- a/docs/3.3.x/docs/contributing.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose Contributing v3.3.1Fork me on GitHub

    Contributing

    Please read all about contributing here.

    diff --git a/docs/3.3.x/docs/contributing.jade b/docs/3.3.x/docs/contributing.jade deleted file mode 100644 index 48d9a658aaf..00000000000 --- a/docs/3.3.x/docs/contributing.jade +++ /dev/null @@ -1,8 +0,0 @@ -extends layout - -block content - h2 Contributing - - :markdown - Please read all about contributing [here](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md). - diff --git a/docs/3.3.x/docs/css/default.css b/docs/3.3.x/docs/css/default.css deleted file mode 100644 index ccb22728ed3..00000000000 --- a/docs/3.3.x/docs/css/default.css +++ /dev/null @@ -1,135 +0,0 @@ -/* - -Original style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ - -pre code { - display: block; padding: 0.5em; - background: #F0F0F0; -} - -pre code, -pre .ruby .subst, -pre .tag .title, -pre .lisp .title, -pre .clojure .built_in, -pre .nginx .title { - color: black; -} - -pre .string, -pre .title, -pre .constant, -pre .parent, -pre .tag .value, -pre .rules .value, -pre .rules .value .number, -pre .preprocessor, -pre .ruby .symbol, -pre .ruby .symbol .string, -pre .ruby .symbol .keyword, -pre .ruby .symbol .keymethods, -pre .instancevar, -pre .aggregate, -pre .template_tag, -pre .django .variable, -pre .smalltalk .class, -pre .addition, -pre .flow, -pre .stream, -pre .bash .variable, -pre .apache .tag, -pre .apache .cbracket, -pre .tex .command, -pre .tex .special, -pre .erlang_repl .function_or_atom, -pre .markdown .header { - color: #800; -} - -pre .comment, -pre .annotation, -pre .template_comment, -pre .diff .header, -pre .chunk, -pre .markdown .blockquote { - color: #888; -} - -pre .number, -pre .date, -pre .regexp, -pre .literal, -pre .smalltalk .symbol, -pre .smalltalk .char, -pre .go .constant, -pre .change, -pre .markdown .bullet, -pre .markdown .link_url { - color: #080; -} - -pre .label, -pre .javadoc, -pre .ruby .string, -pre .decorator, -pre .filter .argument, -pre .localvars, -pre .array, -pre .attr_selector, -pre .important, -pre .pseudo, -pre .pi, -pre .doctype, -pre .deletion, -pre .envvar, -pre .shebang, -pre .apache .sqbracket, -pre .nginx .built_in, -pre .tex .formula, -pre .erlang_repl .reserved, -pre .input_number, -pre .markdown .link_label, -pre .vhdl .attribute, -pre .clojure .attribute { - color: #88F -} - -pre .keyword, -pre .id, -pre .phpdoc, -pre .title, -pre .built_in, -pre .aggregate, -pre .css .tag, -pre .javadoctag, -pre .phpdoc, -pre .yardoctag, -pre .smalltalk .class, -pre .winutils, -pre .bash .variable, -pre .apache .tag, -pre .go .typename, -pre .tex .command, -pre .markdown .strong, -pre .request, -pre .status { - font-weight: bold; -} - -pre .markdown .emphasis { - font-style: italic; -} - -pre .nginx .built_in { - font-weight: normal; -} - -pre .coffeescript .javascript, -pre .xml .css, -pre .xml .javascript, -pre .xml .vbscript, -pre .tex .formula { - opacity: 0.5; -} diff --git a/docs/3.3.x/docs/css/guide.css b/docs/3.3.x/docs/css/guide.css deleted file mode 100644 index b77ffe83b0c..00000000000 --- a/docs/3.3.x/docs/css/guide.css +++ /dev/null @@ -1,326 +0,0 @@ -html, body, #content { - height: 100%; -} -:target::before { - content: ">>> "; - color: #1371C9; - font-weight: bold; - font-size: 20px; -} -.module { - min-height: 100%; - box-sizing: border-box; - overflow-x: hidden; -} -body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; -} -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; -} -code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Monaco; - /*text-shadow: 1px 2px 2px #555;*/ -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -h2 { - margin-top: 0; -} -h2 a { - font-size: 12px; - position: relative; - bottom: 3px; - font-weight: normal; -} -h3 { padding-top: 35px; } -h3 code { - font-weight: normal; -} -hr { - display: none; - height: 1px; - border: 0 none; - padding: 0; - margin: 90px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) -} -.doclinks hr { - margin: 10px 0; -} -li { - list-style: square; -} -#header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -#header .mongoose { - font-size: 48px; - font-weight: 100; - color: #fff; - letter-spacing: -5px; -} -#links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; -} -#links .schematypes span { - display: none; -} -#content { - padding: 0; - margin: 0 0 0 230px; -} -#content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -#content .controls:hover { - opacity: .9; -} -#content p { - word-wrap: break-word; -} -#content > ul { - margin: 0; - padding: 0; -} -.private { - display: none; -} -.doclinks li.private a:before, -.doclinks .module.private a:before, -.doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; -} -#content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; -} -.module { - list-style: none; - padding: 30px 0 0 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; -} -.module > * { - max-width: 700px; -} -.item { - margin-bottom: 175px; -} -.item h3 a { - color: #333; - text-decoration: none; -} -.property h3 span { - color: #444; -} -.description { - margin-top: 25px; -} -.sourcecode { - display: none; -} -.showcode { - font-size: 12px; - cursor: pointer; - display: none; -} -.load .showcode { - display: block; -} -.types a { - text-decoration: none; -} -li.guide ul { - padding-left: 16px; -} - -ul.inthewild { - margin: 30px 0 0 -30px; - padding: 0; - width: 125%; - max-width: 125%; -} -ul.inthewild li { - display: inline-block; - list-style: none; -} -ul.inthewild img { - width: 200px; -} - -@media only screen and (device-width: 768px) { - ul.inthewild { - margin-left: 0px; - } -} - -@media only screen and (max-width: 480px) { - ul.inthewild { - margin-left: 0px; - } - ul.inthewild li { - margin: 5px; - border-width: 2px 2px 0 2px; - border-style: solid; - border-color: #eee; - } - ul.inthewild li img { - width: 140px; - } - h2 a { - white-space: nowrap; - } - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - html, body, #content { - height: auto; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - #links li.guide { - display: block; - width: 390px; - margin-bottom: 15px; - } - #links li.guide > a { - display: none; - } - #links li ul li { - width: 44%; - text-align: left; - } - #links li ul li ul li { - width: 95%; - } - #links .plugins, - #links .changelog { - display: none; - } - #links .schematypes span { - display: inline; - } - #links .double { - width: 332px; - } - #links .double > ul { - display: inline; - float: right; - } - #links .double > ul li { - width: 155px; - } -} diff --git a/docs/3.3.x/docs/css/style.css b/docs/3.3.x/docs/css/style.css deleted file mode 100644 index 34fee99b3f7..00000000000 --- a/docs/3.3.x/docs/css/style.css +++ /dev/null @@ -1,225 +0,0 @@ -body { - font-family: 'Open Sans', Helvetica, Arial, FreeSans; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; -} - -/* location.hash */ -:target::before { - content: ">>> "; - color: #1371C9; - font-weight: bold; - font-size: 20px; -} -/* ignore home page hash */ -#production:target::before { - content: ""; - font-size: inherit; -} - -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { - width: 600px; - margin: 0 auto; - position:relative; -} -li { - list-style: square; -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: #eee; - padding: 5px; - border-radius: 3px; -} -code { - color: #333; - font-size: 11px; - font-family: Monaco; -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -#header { - text-align: center; - padding-top: 40px; -} -#header, h2, h3, .tagline, .blurb { - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -h2 { - margin: 30px 0; -} -h2 a { - font-size: 11px; - position: relative; - bottom: 4px; -} -#header .mongoose { - font-size: 146px; - font-weight: 100; - text-indent: -23px; -} -.load #header .mongoose { - letter-spacing: -14px; -} -.tagline { - color: #333; - font-size: 25px; - text-shadow: 1px 1px #f8f8f8; - text-align: center; -} -.blurb { - text-align: center; - font-style: oblique; - font-size: 12px; - margin-bottom: 20px; -} -.tagline a, .blurb a { - text-decoration: none; - color: #800; -} -#links { - margin: 30px 10px 46px; - text-align: center; - position: relative; -} -#links ul { - margin: 0; - padding: 0; -} -#links li { - display: inline-block; - margin: 0 15px; - background-color: #FEFEFE; -} -#links a { - background: #444; - padding: 9px 0px; - border-radius: 3px; - color: white; - width: 180px; - display: inline-block; - text-decoration: none; - text-transform: lowercase; - text-shadow: 1px 1px 7px #222; -} -#production ul { - padding: 0; -} -#production li { - list-style: none; - overflow: hidden; - display: inline-block; - height: 114px; -} -#production img { - width: 180px; - margin: 10px; -} -#production img#mcds { - width: 134px; - margin: 10px 25px; -} -#production a { - -webkit-transition-property: opacity; - -moz-transition-property: opacity; - -o-transition-property: opacity; - transition-property: opacity; - -webkit-transition-duration: 0.25s; - -moz-transition-duration: 0.25s; - -o-transition-duration: 0.25s; - transition-duration: 0.25s; - opacity: 0.7; -} -#production a:hover { - opacity: 1.0; -} -#footer { - text-align: center; - font-size: 12px; - margin-bottom: 20px; -} -@media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header { - padding-top: 12px; - } - #header .mongoose { - text-align: center; - font-size: 65px; - font-weight: 100; - letter-spacing: -7px; - } - .load #header .mongoose { - letter-spacing: -7px; - } - .tagline { - text-align: center; - font-size: 14px; - } - .tagline a { - text-decoration: none; - } - .blurb { - font-size: 16px; - text-align: justify; - margin-top: 25px; - } - #links { - margin-bottom: 40px; - } - #links li { - padding: 8px 2px; - margin: 0 12px; - } - #links a { - background: #444; - padding: 7px 34px; - font-size: 15px; - } - #docs { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - #wrap { - width: auto; - padding: 0 5px; - } - #production li { - margin-bottom: 8px; - } - #production a { - opacity: 1; - } - #production img { - width: 175px; - } - .addyourown, .addyourown a { - width: 100%; - } -} diff --git a/docs/3.3.x/docs/documents.html b/docs/3.3.x/docs/documents.html deleted file mode 100644 index 415588076cd..00000000000 --- a/docs/3.3.x/docs/documents.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose Documents v3.3.1Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    -  if (err) return handleError(err);
    -  
    -  tank.size = 'large';
    -  tank.save(function (err) {
    -    if (err) return handleError(err);
    -    res.send(tank);
    -  });
    -});

    This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    -  if (err) return handleError(err);
    -  res.send(tank);
    -});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    diff --git a/docs/3.3.x/docs/documents.jade b/docs/3.3.x/docs/documents.jade deleted file mode 100644 index 67134e821b3..00000000000 --- a/docs/3.3.x/docs/documents.jade +++ /dev/null @@ -1,42 +0,0 @@ -extends layout - -block content - h2 Documents - :markdown - Mongoose [documents](./api.html#document-js) represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its [Model](./models.html). - h3 Retrieving - :markdown - There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on [querying](./queries.html) for detail. - h3 Updating - :markdown - There are a number of ways to update documents. We'll first look at a traditional approach using [findById](./api.html#model_Model-findById): - :js - Tank.findById(id, function (err, tank) { - if (err) return handleError(err); - - tank.size = 'large'; - tank.save(function (err) { - if (err) return handleError(err); - res.send(tank); - }); - }); - :markdown - This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model-update) is right for us: - :js - Tank.update({ _id: id }, { $set: { size: 'large' }}, callback); - :markdown - If we do need the document returned in our application there is another, often [better](./api.html#model_Model-findByIdAndUpdate), option: - :js - Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) { - if (err) return handleError(err); - res.send(tank); - }); - :markdown - The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model-findByIdAndRemove) [several](./api.html#model_Model-findOneAndUpdate) [variations](./api.html#model_Model-findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. - h3 Validating - :markdown - Documents are validated before they are saved. Read the [api](./api.html#document_Document-validate) docs or the [validation](./validation.html) chapter for detail. - - h3#next Next Up - :markdown - Now that we've covered `Documents`, let's take a look at [Sub-documents](/docs/subdocs.html). diff --git a/docs/3.3.x/docs/faq.html b/docs/3.3.x/docs/faq.html deleted file mode 100644 index d00c66400f7..00000000000 --- a/docs/3.3.x/docs/faq.html +++ /dev/null @@ -1,31 +0,0 @@ -Mongoose FAQ v3.3.1Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    -doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    -doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    -new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    -doc.user.remove();// ?
    -doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    - -

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    - -

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    -mongoose.connect(..);
    -mongoose.connection.on('error', handleError);
    -
    -// if connecting on a separate connection
    -var conn = mongoose.createConnection(..);
    -conn.on('error', handleError);
    -

    Something to add?

    - -

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    diff --git a/docs/3.3.x/docs/faq.jade b/docs/3.3.x/docs/faq.jade deleted file mode 100644 index 07abc7ea928..00000000000 --- a/docs/3.3.x/docs/faq.jade +++ /dev/null @@ -1,63 +0,0 @@ -extends layout - -block append style - style. - hr { - display: block; - margin: 30px 0; - } - -block content - h2 FAQ - :markdown - **Q**. Why don't my changes to arrays get saved when I update an element directly? - :js - doc.array[3] = 'changed'; - doc.save(); - :markdown - **A**. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving. - :js - doc.markModified('array'); - doc.save(); - hr - :markdown - **Q**. Why doesn't mongoose allow me to directly assign schemas to paths? - :js - var userSchema = new Schema({ name: String }); - new Schema({ user: userSchema }) - :markdown - **A**. Schemas have a one-to-one mapping with documents. Documents have `save` and `remove` methods along with their own `pre` and `post` hooks which would lead to code like the following: - :js - doc.user.save(); // ? - doc.user.remove();// ? - doc.save() - :markdown - We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling `save` on a sub-document is a no-op and exists only to support `pre` save hooks). In the future this is likely to be revisited. - hr - :markdown - **Q**. How can I enable debugging? - - **A**. Set the `debug` option to `true`: - :js - mongoose.set('debug', true) - hr - :markdown - **Q**. My `save()` callback never executes. What am I doing wrong? - - **A**. All `collection` actions (insert, remove, queries, etc) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. - :js - // if connecting on the default mongoose connection - mongoose.connect(..); - mongoose.connection.on('error', handleError); - - // if connecting on a separate connection - var conn = mongoose.createConnection(..); - conn.on('error', handleError); - - hr - :markdown - **Something to add?** - - If you'd like to contribute to this page, please [visit it](https://github.com/learnboost/mongoose/tree/master/docs/faq.jade) on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request. - br - diff --git a/docs/3.3.x/docs/guide.html b/docs/3.3.x/docs/guide.html deleted file mode 100644 index 1c526d64d10..00000000000 --- a/docs/3.3.x/docs/guide.html +++ /dev/null @@ -1,188 +0,0 @@ -Mongoose Schemas v3.3.1Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

    If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    -  title:  String,
    -  author: String,
    -  body:   String,
    -  comments: [{ body: String, date: Date }],
    -  date: { type: Date, default: Date.now },
    -  hidden: Boolean,
    -  meta: {
    -    votes: Number,
    -    favs:  Number
    -  }
    -});

    If you want to add additional keys later, use the Schema#add method.

    -Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. -Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    -
    -animalSchema.methods.findSimilarTypes = function (cb) {
    -  return this.model('Animal').find({ type: this.type }, cb);
    -}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    -var dog = new Animal({ type: 'dog' });
    -
    -dog.findSimilarTypes(function (err, dogs) {
    -  console.log(dogs); // woof
    -});

    Statics

    -Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    -  this.find({ name: new RegExp(name, 'i') }, cb);
    -}
    -
    -var Animal = mongoose.model('Animal', animalSchema);
    -Animal.findByName('fido', function (err, animals) {
    -  console.log(animals);
    -});

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });
    -

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index. It is recommended this behavior be disabled in production by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false);
    -// or
    -new Schema({..}, { autoIndex: false });
    -

    See also the Model#ensureIndexes method for more details.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    -  name: {
    -    first: String,
    -    last: String
    -  }
    -});
    -
    -var Person = mongoose.model('Person', personSchema);
    -
    -var bad = new Person({
    -    name: { first: 'Walter', last: 'White' }
    -});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    -  return this.name.first + ' ' + this.name.last;
    -});

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full); // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    -  var split = name.split(' ');
    -  this.name.first = split[0];
    -  this.name.last = split[1];
    -});
    -
    -...
    -
    -mad.name.full = 'Breaking Bad';
    -console.log(mad.name.first); // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    -
    -// or
    -
    -var schema = new Schema({..});
    -schema.set(option, value);
    -

    Valid options:

    - -

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false });
    -var Clock = db.model('Clock', schema);
    -Clock.ensureIndexes(callback);
    -

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 });

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });
    -

    option: collection

    Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Set this option if you need a different name for your collection.

    var dataSchema = new Schema({..}, { collection: 'data' });
    -

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    -var schema = new Schema({ name: String });
    -var Page = db.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p.id); // '50341373e894ad16347efe01'
    -
    -// disabled id
    -var schema = new Schema({ name: String }, { id: false });
    -var Page = db.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p.id); // undefined
    -

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    - -

    Pass this option during schema construction to prevent documents from getting an auto _id created.

    // default behavior
    -var schema = new Schema({ name: String });
    -var Page = db.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
    -
    -// disabled _id
    -var schema = new Schema({ name: String }, { _id: false });
    -var Page = db.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p); // { name: 'mongodb.org' }
    -

    option: read

    Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

    var schema = new Schema({..}, { read: 'primary' });            // also aliased as 'p'
    -var schema = new Schema({..}, { read: 'primaryPreferred' });   // aliased as 'pp'
    -var schema = new Schema({..}, { read: 'secondary' });          // aliased as 's'
    -var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp'
    -var schema = new Schema({..}, { read: 'nearest' });            // aliased as 'n'
    -

    The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'.

    - -

    The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

    - -

    NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

    // pings the replset members periodically to track network latency
    -// now `nearest` works as intended
    -var options = { replset: { strategy: 'ping' }};
    -mongoose.connect(uri, options);
    -
    -var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
    -mongoose.model('JellyBean', schema);
    -

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    -new Schema({ .. }, { safe: safe });
    -

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. -By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    - -

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
    -new Schema({ .. }, { safe: safe });
    -

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    -

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: strict

    The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.

    var thingSchema = new Schema({..})
    -var Thing = db.model('Thing', schemaSchema);
    -var thing = new Thing({ iAmNotInTheSchema: true });
    -thing.save(); // iAmNotInTheSchema is not saved to the db
    -
    -// set to false..
    -var thingSchema = new Schema({..}, { strict: false });
    -var thing = new Thing({ iAmNotInTheSchema: true });
    -thing.save(); // iAmNotInTheSchema is now saved to the db!!
    -

    This also affects the use of doc.set() to set a property value.

    var thingSchema = new Schema({..})
    -var Thing = db.model('Thing', schemaSchema);
    -var thing = new Thing;
    -thing.set('iAmNotInTheSchema', true);
    -thing.save(); // iAmNotInTheSchema is not saved to the db
    -

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = db.model('Thing');
    -var thing = new Thing(doc, true);  // enables strict mode
    -var thing = new Thing(doc, false); // disables strict mode
    -

    The strict option may also be set to "throw" which will cause errors to be produced instead of dropping the bad data.

    NOTE: do not set to false unless you have good reason.

    - -

    NOTE: in mongoose v2 the default was false.

    - -

    NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.

    var thingSchema = new Schema({..})
    -var Thing = db.model('Thing', schemaSchema);
    -var thing = new Thing;
    -thing.iAmNotInTheSchema = true;
    -thing.save(); // iAmNotInTheSchema is never saved to the db
    -

    option: toJSON

    Exactly the same as the toObject option but only applies when the documents toJSON method is called.

    var schema = new Schema({ name: String });
    -schema.path('name').get(function (v) {
    -  return v + ' is my name';
    -});
    -schema.set('toJSON', { getters: true, virtuals: false });
    -var M = mongoose.model('Person', schema);
    -var m = new M({ name: 'Max Headroom' });
    -console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
    -console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    -// since we know toJSON is called whenever a js object is stringified:
    -console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
    -

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    - -

    To have all virtuals show up in your console.log output, set the toObject option to { getters: true }:

    var schema = new Schema({ name: String });
    -schema.path('name').get(function (v) {
    -  return v + ' is my name';
    -});
    -schema.set('toObject', { getters: true });
    -var M = mongoose.model('Person', schema);
    -var m = new M({ name: 'Max Headroom' });
    -console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    -

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    -var Thing = db.model('Thing', schema);
    -var thing = new Thing({ name: 'mongoose v3' });
    -thing.save(); // { __v: 0, name: 'mongoose v3' }
    -
    -// customized versionKey
    -new Schema({..}, { versionKey: '_somethingElse' })
    -var Thing = db.model('Thing', schema);
    -var thing = new Thing({ name: 'mongoose v3' });
    -thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    -

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false });
    -var Thing = db.model('Thing', schema);
    -var thing = new Thing({ name: 'no versioning please' });
    -thing.save(); // { name: 'no versioning please' }
    -
    -

    Next Up

    Now that we've covered Schemas, let's take a look at SchemaTypes.

    diff --git a/docs/3.3.x/docs/guide.jade b/docs/3.3.x/docs/guide.jade deleted file mode 100644 index 79286e877fe..00000000000 --- a/docs/3.3.x/docs/guide.jade +++ /dev/null @@ -1,457 +0,0 @@ -extends layout - -block content - h2 Schemas - :markdown - If you haven't yet done so, please take a minute to read the [quickstart](./index.html) to get an idea of how Mongoose works. - :markdown - If you are migrating from 2.x to 3.x please take a moment to read the [migration guide](./migration.html). - :markdown - This page covers `Schema` [definition](#definition), [plugins](#plugins), instance [methods](#methods), [statics](#statics), [indexes](#indexes), [virtuals](#virtuals) and [options](#options). Let's start with `Schema` definition. - h3#definition Defining your schema - p - | Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection. - :js - var blogSchema = new Schema({ - title: String, - author: String, - body: String, - comments: [{ body: String, date: Date }], - date: { type: Date, default: Date.now }, - hidden: Boolean, - meta: { - votes: Number, - favs: Number - } - }); - p - em - | If you want to add additional keys later, use the - a(href="./api.html#schema_Schema-add") Schema#add - | method. - p - | Each key in our - code blogSchema - | defines a property in our documents which will be cast to its associated - a(href="./api.html#schematype_SchemaType") SchemaType - |. For example, we've defined a - code title - | which will be cast to the - a(href="./api.html#schema-string-js") String - | SchemaType and - code date - | which will be cast to a - code Date - | SchemaType. - | Keys may also be assigned nested objects containing further key/type definitions - em (e.g. the `meta` property above). - p - | The permitted SchemaTypes are - ul - li String - li Number - li Date - li Buffer - li Boolean - li Mixed - li ObjectId - li Array - | Read more about them - a(href="./schematypes.html") here - | . - p - | Schemas not only define the structure of your document and casting of properties, they also define document - a(href="#methods") instance methods - |, static - a(href="#statics") Model methods - |, - a(href="#indexes") compound indexes - | and document lifecycle hooks called - a(href="./middleware.html") middleware - |. - h3#plugins Pluggable - p - | Schemas are - a(href="./plugins.html") pluggable - | which allows us to package up reusable features into - a(href="http://plugins.mongoosejs.com") plugins - | that can be shared with the community or just between your projects. - h3#methods Instance methods - p - a(href="./models.html") Models - | are just fancy - code constructor - | functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are - a(href="./documents.html") documents - |. - p - | Defining an instance method is easy. - :js - var animalSchema = new Schema({ name: String, type: String }); - - animalSchema.methods.findSimilarTypes = function (cb) { - return this.model('Animal').find({ type: this.type }, cb); - } - p - | Now all of our - code animal - | instances have a - code findSimilarTypes - | method available to it. - :js - var Animal = mongoose.model('Animal', animalSchema); - var dog = new Animal({ type: 'dog' }); - - dog.findSimilarTypes(function (err, dogs) { - console.log(dogs); // woof - }); - h3#statics Statics - p - | Adding static constructor methods to Models is simple as well. Continuing with our - code animalSchema - |: - :js - animalSchema.statics.findByName = function (name, cb) { - this.find({ name: new RegExp(name, 'i') }, cb); - } - - var Animal = mongoose.model('Animal', animalSchema); - Animal.findByName('fido', function (err, animals) { - console.log(animals); - }); - h3#indexes Indexes - p - a(href="http://www.mongodb.org/display/DOCS/Indexes") Indexes - | can be defined - a(href="./api.html#schematype_SchemaType-index") at - | - a(href="./api.html#schematype_SchemaType-unique") the - | - a(href="./api.html#schematype_SchemaType-sparse") path - | - a(href="./api.html#schematype_SchemaType-expires") level - | or the - code schema - | level. Defining indexes at the schema level is necessary when defining - a(href="http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys", target="_blank") compound indexes - |. - :js - animalSchema.index({ name: 1, type: -1 }); - - :markdown - When your application starts up, Mongoose automatically calls `ensureIndex` for each defined index. It is recommended this behavior be disabled in production by setting the `autoIndex` option of your schema to `false`. - - :js - animalSchema.set('autoIndex', false); - // or - new Schema({..}, { autoIndex: false }); - - p - | See also the - a(href="./api.html#model_Model-ensureIndexes") - code Model#ensureIndexes - | method for more details. - - h3#virtuals Virtuals - :markdown - [Virtual](./api.html#schema_Schema-virtual) attributes are attributes that are convenient to have around but that do not get persisted to MongoDB. - :js - var personSchema = new Schema({ - name: { - first: String, - last: String - } - }); - - var Person = mongoose.model('Person', personSchema); - - var bad = new Person({ - name: { first: 'Walter', last: 'White' } - }); - :markdown - Suppose we want to log the full name of `bad`. We could do this manually like so: - :js - console.log(bad.name.first + ' ' + bad.name.last); // Walter White - :markdown - Or we could add a `virtual` attribute [getter](./api.html#virtualtype_VirtualType-get) to our `personSchema` so we don't need to write out this string concatenation mess each time: - :js - personSchema.virtual('name.full').get(function () { - return this.name.first + ' ' + this.name.last; - }); - :markdown - Now, when we access our virtual full name property, our getter function will be invoked and the value returned: - :js - console.log('%s is insane', bad.name.full); // Walter White is insane - :markdown - It would also be nice to be able to set `this.name.first` and `this.name.last` by setting `this.name.full`. For example, if we wanted to change `bad`'s `name.first` and `name.last` to 'Breaking' and 'Bad' respectively, it'd be nice to just: - :js - bad.name.full = 'Breaking Bad'; - :markdown - Mongoose lets you do this as well through its virtual attribute [setters](./api.html#virtualtype_VirtualType-set): - :js - personSchema.virtual('name.full').set(function (name) { - var split = name.split(' '); - this.name.first = split[0]; - this.name.last = split[1]; - }); - - ... - - mad.name.full = 'Breaking Bad'; - console.log(mad.name.first); // Breaking - :markdown - If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you. - - h3#options Options - :markdown - `Schema`s have a few configurable options which can be passed to the constructor or `set` directly: - :js - new Schema({..}, options); - - // or - - var schema = new Schema({..}); - schema.set(option, value); - - :markdown - Valid options: - - - [autoIndex](#autoIndex) - - [capped](#capped) - - [collection](#collection) - - [id](#id) - - [_id](#_id) - - [read](#read) - - [safe](#safe) - - [shardKey](#shardKey) - - [strict](#strict) - - [toJSON](#toJSON) - - [toObject](#toObject) - - [versionKey](#versionKey) - - h4#autoIndex option: autoIndex - :markdown - At application startup, Mongoose sends an `ensureIndex` command for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model-ensureIndexes) method on your model. - :js - var schema = new Schema({..}, { autoIndex: false }); - var Clock = db.model('Clock', schema); - Clock.ensureIndexes(callback); - - h4#capped option: capped - :markdown - Mongoose supports MongoDBs [capped](http://www.mongodb.org/display/DOCS/Capped+Collections) collections. To specify the underlying MongoDB collection be `capped`, set the `capped` option to the maximum size of the collection in [bytes](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-size.). - :js - new Schema({..}, { capped: 1024 }); - :markdown - The `capped` option may also be set to an object if you want to pass additional options like [max](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-max) or [autoIndexId](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-autoIndexId). In this case you must explicitly pass the `size` option which is required. - :js - new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } }); - - h4#collection option: collection - :markdown - Mongoose by default produces a collection name by passing the model name to the [utils.toCollectionName](./api.html#utils.toCollectionName) method. This method pluralizes the name. Set this option if you need a different name for your collection. - :js - var dataSchema = new Schema({..}, { collection: 'data' }); - - h4#id option: id - :markdown - Mongoose assigns each of your schemas an `id` virtual getter by default which returns the documents `_id` field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an `id` getter added to your schema, you may disable it passing this option at schema construction time. - :js - // default behavior - var schema = new Schema({ name: String }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p.id); // '50341373e894ad16347efe01' - - // disabled id - var schema = new Schema({ name: String }, { id: false }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p.id); // undefined - - h4#_id option: _id - :markdown - Mongoose assigns each of your schemas an `_id` field by default if one is not passed into the [Schema](/docs/api.html#schema-js) constructor. The type assiged is an [ObjectId](/docs/api.html#schema_Schema-Types) to coincide with MongoDBs default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option. - - Pass this option during schema construction to prevent documents from getting an auto `_id` created. - :js - // default behavior - var schema = new Schema({ name: String }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' } - - // disabled _id - var schema = new Schema({ name: String }, { _id: false }); - var Page = db.model('Page', schema); - var p = new Page({ name: 'mongodb.org' }); - console.log(p); // { name: 'mongodb.org' } - - h4#read option: read - :markdown - Allows setting [query#read](/docs/api.html#query_Query-read) options at the schema level, providing us a way to apply default [ReadPreferences](http://docs.mongodb.org/manual/applications/replication/#replica-set-read-preference) to all queries derived from a model. - - :js - var schema = new Schema({..}, { read: 'primary' }); // also aliased as 'p' - var schema = new Schema({..}, { read: 'primaryPreferred' }); // aliased as 'pp' - var schema = new Schema({..}, { read: 'secondary' }); // aliased as 's' - var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp' - var schema = new Schema({..}, { read: 'nearest' }); // aliased as 'n' - - :markdown - The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'. - - The read option also allows us to specify _tag sets_. These tell the [driver](https://github.com/mongodb/node-mongodb-native/) from which members of the replica-set it should attempt to read. Read more about tag sets [here](http://docs.mongodb.org/manual/applications/replication/#tag-sets) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences). - - _NOTE: if you specify the read pref 'nearest', you must also pass the [strategy](http://mongodb.github.com/node-mongodb-native/api-generated/replset.html?highlight=strategy) option when connecting or your reads will not behave predictably:_ - - :js - // pings the replset members periodically to track network latency - // now `nearest` works as intended - var options = { replset: { strategy: 'ping' }}; - mongoose.connect(uri, options); - - var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] }); - mongoose.model('JellyBean', schema); - - h4#safe option: safe - :markdown - This option is passed to MongoDB with all operations and specifies if errors should be returned to our callbacks as well as tune write behavior. - - :js - var safe = true; - new Schema({ .. }, { safe: safe }); - - :markdown - By default this is set to `true` for all schemas which guarentees that any occurring error gets passed back to our callback. - By setting `safe` to something else like `{ j: 1, w: 2, wtimeout: 10000 }` we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback. - - There are other write concerns like `{ w: "majority" }` too. See the MongoDB [docs](http://www.mongodb.org/display/DOCS/getLastError+Command) for more details. - - :js - var safe = { w: "majority", wtimeout: 10000 }; - new Schema({ .. }, { safe: safe }); - - h4#shardKey option: shardKey - :markdown - The `shardKey` option is used when we have a [sharded MongoDB architecture](http://www.mongodb.org/display/DOCS/Sharding+Introduction). Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set. - - :js - new Schema({ .. }, { shardkey: { tag: 1, name: 1 }}) - - :markdown - _Note that Mongoose does not send the `shardcollection` command for you. You must configure your shards yourself._ - - h4#strict option: strict - :markdown - The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db. - - :js - var thingSchema = new Schema({..}) - var Thing = db.model('Thing', schemaSchema); - var thing = new Thing({ iAmNotInTheSchema: true }); - thing.save(); // iAmNotInTheSchema is not saved to the db - - // set to false.. - var thingSchema = new Schema({..}, { strict: false }); - var thing = new Thing({ iAmNotInTheSchema: true }); - thing.save(); // iAmNotInTheSchema is now saved to the db!! - - :markdown - This also affects the use of `doc.set()` to set a property value. - - :js - var thingSchema = new Schema({..}) - var Thing = db.model('Thing', schemaSchema); - var thing = new Thing; - thing.set('iAmNotInTheSchema', true); - thing.save(); // iAmNotInTheSchema is not saved to the db - - :markdown - This value can be overridden at the model instance level by passing a second boolean argument: - - :js - var Thing = db.model('Thing'); - var thing = new Thing(doc, true); // enables strict mode - var thing = new Thing(doc, false); // disables strict mode - - :markdown - The `strict` option may also be set to `"throw"` which will cause errors to be produced instead of dropping the bad data. - - :markdown - _NOTE: do not set to false unless you have good reason._ - - _NOTE: in mongoose v2 the default was false._ - - _NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option._ - - :js - var thingSchema = new Schema({..}) - var Thing = db.model('Thing', schemaSchema); - var thing = new Thing; - thing.iAmNotInTheSchema = true; - thing.save(); // iAmNotInTheSchema is never saved to the db - - h4#toJSON option: toJSON - :markdown - Exactly the same as the [toObject](#toObject) option but only applies when the documents `toJSON` method is called. - :js - var schema = new Schema({ name: String }); - schema.path('name').get(function (v) { - return v + ' is my name'; - }); - schema.set('toJSON', { getters: true, virtuals: false }); - var M = mongoose.model('Person', schema); - var m = new M({ name: 'Max Headroom' }); - console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' } - console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } - // since we know toJSON is called whenever a js object is stringified: - console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" } - - h4#toObject option: toObject - :markdown - Documents have a [toObject](/docs/api.html#document_Document-toObject) method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default. - - To have all virtuals show up in your `console.log` output, set the `toObject` option to `{ getters: true }`: - - :js - var schema = new Schema({ name: String }); - schema.path('name').get(function (v) { - return v + ' is my name'; - }); - schema.set('toObject', { getters: true }); - var M = mongoose.model('Person', schema); - var m = new M({ name: 'Max Headroom' }); - console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } - - h4#versionKey option: versionKey - :markdown - The `versionKey` is a property set on each document when first created by Mongoose. This keys value contains the internal [revision](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning) of the document. The name of this document property is configurable. The default is `__v`. If this conflicts with your application you can configure as such: - :js - var schema = new Schema({ name: 'string' }); - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'mongoose v3' }); - thing.save(); // { __v: 0, name: 'mongoose v3' } - - // customized versionKey - new Schema({..}, { versionKey: '_somethingElse' }) - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'mongoose v3' }); - thing.save(); // { _somethingElse: 0, name: 'mongoose v3' } - - :markdown - Document versioning can also be disabled by setting the `versionKey` to false. _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning)._ - :js - new Schema({..}, { versionKey: false }); - var Thing = db.model('Thing', schema); - var thing = new Thing({ name: 'no versioning please' }); - thing.save(); // { name: 'no versioning please' } - - - h3#next Next Up - :markdown - Now that we've covered `Schemas`, let's take a look at [SchemaTypes](/docs/schematypes.html). - -script. -document.body.className = 'load'; -include includes/googleanalytics diff --git a/docs/3.3.x/docs/helpers/filters.js b/docs/3.3.x/docs/helpers/filters.js deleted file mode 100644 index 33546a7e805..00000000000 --- a/docs/3.3.x/docs/helpers/filters.js +++ /dev/null @@ -1,20 +0,0 @@ - -var hl = require('highlight.js') - -module.exports = exports = function (jade) { - // add highlighting filter to jade - - jade.filters.js = function (str) { - str = str.replace(/\\n/g, '\n'); - var ret = hl.highlight('javascript', str).value; - var code = '
    ' + ret.replace(/\n/g, '\\n') + '
    '; - return code; - } - - jade.filters.bash = function (str) { - var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; - var code = '
    ' + ret + '
    '; - return code - } - -} diff --git a/docs/3.3.x/docs/helpers/highlight.js b/docs/3.3.x/docs/helpers/highlight.js deleted file mode 100644 index 8aca9b9e222..00000000000 --- a/docs/3.3.x/docs/helpers/highlight.js +++ /dev/null @@ -1,11 +0,0 @@ - -var h = require('highlight.js') - -function hl (str) { - str = str.replace(/\\n/g, '\n'); - var ret = h.highlight('javascript', str).value; - var code = '
    ' + ret+ '
    '; - return code; -} - -module.exports = hl; diff --git a/docs/3.3.x/docs/helpers/href.js b/docs/3.3.x/docs/helpers/href.js deleted file mode 100644 index e7299b1cf0d..00000000000 --- a/docs/3.3.x/docs/helpers/href.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str, char) { - if ('string' != typeof str) return str; - return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); -} diff --git a/docs/3.3.x/docs/helpers/klass.js b/docs/3.3.x/docs/helpers/klass.js deleted file mode 100644 index 0c4a865b43b..00000000000 --- a/docs/3.3.x/docs/helpers/klass.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str) { - var parts = str.replace(/\.js$/, '').split('/'); - return parts.join('_'); -} diff --git a/docs/3.3.x/docs/helpers/linktype.js b/docs/3.3.x/docs/helpers/linktype.js deleted file mode 100644 index 997e740f671..00000000000 --- a/docs/3.3.x/docs/helpers/linktype.js +++ /dev/null @@ -1,50 +0,0 @@ - -var types = {}; -types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; -types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' -types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' -types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' -types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' -types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' -types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' -types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' -types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' -types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' - -// mongoose -types.ObjectId = '#types_objectid_ObjectId'; -types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; -types.MongooseArray = '#types_array_MongooseArray'; -types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; -types.Query = '#query-js'; -types.QueryStream = '#querystream_QueryStream'; -types.Document = '#document_Document'; -types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; -types.Document = '#document_Document'; -types.Model = '#model_Model'; -types.Connection = '#connection_Connection'; -types.Collection = '#collection_Collection'; -types.Schema = '#schema_Schema'; -types.Promise = '#promise_Promise'; -types.Mongoose = '#index_Mongoose'; -types.MongooseError = '#error_MongooseError'; -types.Type = '#schematype_SchemaType'; // ? -types.SchemaType = '#schematype_SchemaType'; -types.SchemaArray = '#schema_array_SchemaArray'; -types.Mixed = '#schema_mixed_Mixed'; -types.VirtualType = '#virtualtype_VirtualType'; -types.MongooseBuffer = '#types_buffer_MongooseBuffer'; -types.Buffer = 'http://nodejs.org/api/buffer.html'; - -module.exports= function (type) { - if (types[type]) { - return '' + type + ''; - } - return '' + type + ''; -} - -module.exports.types = types; -module.exports.type = function (str) { - if (types[str]) return types[str]; - return str; -} diff --git a/docs/3.3.x/docs/images/apps/attictv.png b/docs/3.3.x/docs/images/apps/attictv.png deleted file mode 100644 index 1327f0bd858cf6f002a077a9aafba1217ce38e9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42666 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 Cl*SPN diff --git a/docs/3.3.x/docs/images/apps/calllist.png b/docs/3.3.x/docs/images/apps/calllist.png deleted file mode 100644 index 824fa428eb2de2a237b37ada591cc7056d68f399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33502 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 $5C9j=SSd5$;KOc+eQQ2^5$rlF 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 diff --git a/docs/3.3.x/docs/images/apps/cldfy.png b/docs/3.3.x/docs/images/apps/cldfy.png deleted file mode 100644 index c44ca3525daa7b847ab2869d44a00ebae852646d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9773 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 AJOBUy diff --git a/docs/3.3.x/docs/images/apps/clickdummy.png b/docs/3.3.x/docs/images/apps/clickdummy.png deleted file mode 100644 index 773ce3ec638a72dd3eb7ab6d103dade3874fa53e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34210 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 O0000=x}o)VD=23xZGidKsJj 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

    &}XJ7y^uLKL|l(=^=~M7SI1ZoeQx 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

  • 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 Q6aWAK07*qoM6N<$g5iQW;Q#;t diff --git a/docs/3.3.x/docs/images/apps/furbabyrescue.png b/docs/3.3.x/docs/images/apps/furbabyrescue.png deleted file mode 100644 index 79dafc640738444c01883ac66e8f0f2584a45a57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49891 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 diff --git a/docs/3.3.x/docs/images/apps/geeklist.png b/docs/3.3.x/docs/images/apps/geeklist.png deleted file mode 100644 index c6579c12f6f37e10ab1a3f667e33f70fbdc87173..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27911 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 /dev/null - then - echo waiting for manual firefox shutdown... - fi - - while true; do - if ps ax | grep -v grep | grep firefox > /dev/null - then - sleep 1 - else - break - fi - done - echo firefox shutdown detected -} - -if test -z "$1" -then - while read line - do - func $line - done < urls -else - func $1 "$2" -fi - diff --git a/docs/3.3.x/docs/images/apps/growthegamegolf.png b/docs/3.3.x/docs/images/apps/growthegamegolf.png deleted file mode 100644 index a8d6e9fb7493ce38c487cb2f31416838fe063bb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43441 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 diff --git a/docs/3.3.x/docs/images/apps/h_learnboost.png b/docs/3.3.x/docs/images/apps/h_learnboost.png deleted file mode 100644 index 2940dc31489e2f0db0857ecf2c32a2dabb907b69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12727 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 diff --git a/docs/3.3.x/docs/images/apps/h_mcds.png b/docs/3.3.x/docs/images/apps/h_mcds.png deleted file mode 100644 index 1ac655377ad9e784895c1d0ac1e74d46d4949752..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3904 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 O0000D_X* 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 diff --git a/docs/3.3.x/docs/images/apps/kyyti.png b/docs/3.3.x/docs/images/apps/kyyti.png deleted file mode 100644 index f74d98da1346a95376b33f6bc6118e8864261b4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41966 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 ^!Ew8_;FrDA-Jwjzfp_2R2 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 diff --git a/docs/3.3.x/docs/images/apps/learnboost.png b/docs/3.3.x/docs/images/apps/learnboost.png deleted file mode 100644 index a6c33c8bd41f9806ab255e4afe5e0187c65810fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31434 zcmV)FK)=6=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81VslAEK~#9!?frMOW!HJw3I6sz`R12X zy-KJmBHVoxS(Bzx-|S z=}&)J(}OS!iJ}O@FtBYKtu;aj@}PB6Jbj)oGyHD2-j&+gsqEGCaizY8-=%F1|9dTc z1)@ZFMS8L4gKS*_A60H@hmo9Sg)JX!rd)pz%?Yudp z5U88j$Mv>3U4t4oAQDT|WPNpJHw4 z(rtwtSMyyrvfj1!aWi|l-u7?yxZX-&?)Fk^jbWO+`{O^(qo4Rm#%K4i5%_#>^%D12 zCYjuGkUJm!0NqxL&;Q=1Xf+$RWMjPzw?8PQ&{|`f<{NKp2hds*$1ze$;yA{#tZQx~ zj^pG&7}~eyZft{6ihJJiDDV4)zlkFaI_HjY6gaoC#6%b{*KT1|#<~B)pXA($V?6bx zzd%a4O#r%9!Dpv3S88Kand_bKn+f_R_i?@L-^g)AQM3&)u0;tk3`!;cCUR~1Oc4YD zwrvvxL53LD(od>vl0)3iF1(M%Efl%;iJwBc1)N|LYxQNe*3YuwdQ{F`#(Vj7DsB#UCGeJefrP6{#5rq&uM<<+%sS~!k_*;^l_6mcBi^aCJ@B7z_w z2m-<|!m=#X$ess5 zkbQp~$JsN>w$Uoi+Us_^_!$EE18t`Wylu{Q`Y5e5-sB8syn_41{|0&fIf^QxrrwF= z%<RfI@BYVY2?T)cRZ ziHQl8mX>fF2O$JUjvUF5rPJv!K0c1``!t(P#>dBrq6noF>+9>>bI&~-J9Z4;_jg?! ztu>b8@`)e+NgNgM%B!!j)o5bcF0Lhc{n+b-aXhlFG)zADk&iP`c6jCJQQ}x343oh3 zDV54hPES)`U**)P6BNegc=yA1^W2LsW0?kqX`*5UI_B7G#|Y!m8(3-0`#$_p_D)uL z{`)Tz#TviU#H&v7-bWwi+uwQ$>6DnCo#NQ5uO^EdMHEX_=BLLwcm6ELUOPrNj7Q1` zN@?En{txrOU58k@bcxevPg8HSD0nXC&YWaz^X9R?aU2sx5uou(D@Yp(<{EaiNzh)PvC*dftq$Skh*%o<_Z(trYmIKFlbsUjq*#`f zQIS%q#Knsjaa|Xs6wPLnnVA_((`0FBiH(g7W@l%KF%*=55^l7@?F3Zcygkd;(Q|C_8PPfb1^XGZw-h27T6MKl1!gR}=dg&Qnc;N+< z9$n9J3?|0Mn46hqVebJfQ=;M!q=RD!lwmMFHpXB4=^r91^W1yi1MJy%7%5^5Ltr{Z zMA+gt|M_old83_ezTc=SCi&dl@GFa0r_vBBi@6iT_&0u;bs>1_U;d9A|N56e2&Si}SzKJ?+_`fsEG)3Gu|c=n z#c>>5*TwgJOw&XN!G#MK*t2I3&1RG7>1mdimow7ZXf(1qtyYU52pAt9=luEe96WfC zG2AUb_dH4fTUa<PX9`QY;XKQL_1z!gFj+o_L*(AC5#ktzmXzWA9x;`Osj*`~PBh>@-{z{J!vrqD>kBn$!+n!pbd3SnDVriJU+ zG@4Bu$D!41(CH?Jw&O}Z@(bhaxx?l7_uG8!(;LK*&c^CE4xLUX>#I^5qg*Ty$BI(9 z!XuBogRlLEFVg777!m?Mpw(^z2~~4l_v#S?t?|YtdF=21Qzqy4aPg@xGFIEfRliAj zYLb=Zze>APr!n`<2Z{J+Egh5v*DPy7_Ft`i*p97g#=>_74!(Qdan{_In{ z`0xK$I`z#=U6AiM{k_{J9)6dvGhF{_+S{p*>*1y44z`&%Rs-)wee*CvT3vUO@?8Nth2iv1Gx0;lepz7`r|*(*z_#2 z@?)st2iaWT;L`I?@zS4siu%%pz7FkecpFF%qf)8d689Q_QmJ&^o(?0QKmPdRS8PoP zL3wVGi9`3{lw4vzV)M*#HqIU=^8M{-d>g>^vIRGiop`hQxShZKtpeiXKk{Q*Yeix@ z8HFRsbFFnE$%%wlgJB24eEr?q%6^N%HzNnQ6GjjG5Zj(hDN)&Xjc#9v?Qar!L2c_v z40n+InSRsgj~UhP_6?XXrAPcd8Z;xSX^>K&l+H@%9V!jK6=F1Eqe>;hc z;0Ol&brQLtxA{_yj_B7(%ceDC(m=1B!M0^j#z>JtpbKjYg+?yeEiiP3Ab5TE6wr z-zwLCzP`%ZNFJ(ueUVzL`}H8{OY7XY2Kps8*50$BZ%l-9woTZM`!w78+mT^ZTiF_Z zdm|n?4w3;6o|A*vFzEZ<*TM|KFgE4~)PI#BLXH|`$bimmHl1y%{>JNVNS$u}!QS%E zG6WL3-*$>%x$=EP7;LAH2)SniZ4dR``$myNko>W}Z7HvC(CKY|r<$yOT|HF3zo~|v zr^rKpqw8$*BCkU9!4rMPu~6{D%I1R(MJTO`}2Hd38H_f zDV2B&BxC5$)lOW0o=$7P95v-hsl19Xsid;Kn>@%=Yr8CEI+z3*a;H~1$h7esi#9OS z6zMXAPsf$ccps6|?baK058)WtsUm-Rh}_uqAi@q%xc*QEPyZoKVsKnT)4A>BO2?4j zu?#*Nu99E>;oUy8e1pZ)&CbX=`RVPmO}X+qH=iO~*<4%s0qcI7dc=X=qz8}7Yy;_R zF>(jO;3|m0(>!f!keVbjHcUMvdZ1qaG}lR+IhLe<;`b>|(pHX&{R}T?vFWpA(BlZdYH6r83(9}$UPdO=nNx=?(d1A9hN?l^w&IYMf!Z;{L>j_$tXkiUMFR9hcg3p$ykMK|Ija!SCWdft%QLdptb{h z9?|=)x2tQjMb+D}%s}I}J4A6}c*+$Xp1%=@Ik+lf+qrSa`}ueTn=aSOlkFEGWc z1B-oC)aNY;nkb&aF8>1zV-}?~GVe~*lc&jP9RbWdpL@k^Eje`%@kA8LMcBe#2{(ObiVW(dOM8u_68v& z!-`}n4f-0B8@GN!Kos?~I;jHYw%H$|XR|VTepLoS3Urq7W>Dj(bx&QJs>`ILPg8YY z7P5+lwY1iMju}rc(3_1F6|F{jF}$ zmtVnRylor+@ejVEoDfhQdw{K$N5}>U3)^roC5Rj62@WJ|)8auF9h5kKYK3CGOS9z> zg%$2R;&JwD7a735yKF9=i_j{G1BoL=96=nKY;-;Dy4&N_b20b4BTQ^qH)<{b#|7K% z?_eoGNWINYnlhMX`dp>KA!$qb3i|5z-|*^)P8;jHFJirT91%psi*p3;eu#K+`i*~a z93z4V?bw6h*Vb^q{B4jn{zudMaQq9fc~-IS zZjbMOcasxG6^ln|NV#$omPUi_%M@tU^T5!9c8ngFeV2{Am1Us0tkN|NRtQ9^LGibK z7w@T8Fz!AG6%YOCFA{v^8S4M|*NLa9eG{pm=XEA>yj|~^$URGaQ>4Ux?KQmL{W8tJ z`zyqA)j>*-uOkJfR+L^oihAxG;luY6Pn79fc<58HZG8=mDeoJTH=CvuQ0C@Q<$N9F zfGIW^s}Oy`ZkxYGs!q)L&*aB&6;w|e7M055EU$eX%L+-{CT={n)Jk*UT`lGhO(TpD zySPQv_4xi*Yxs=<^M~6!_--F$#Nr_nv}WpXlOLOzO{QIJv3zlw$385n&Ro7ZF&vrS zNlyc-bwZWIXeq%QRvhRd2RD&x_nJTm?5{qB_v8!2zy3Gb`skx5%f$QEcPRYv*DyOB z%rCr%Z2E+EAHY0zitv$#&?3Tl@@eFHlj#1t2p+o+(QaXV>v_ym7tpmD{)gX<_9V_1 zzKQj{m+}7iOLTwY{X~1FvrQydSFxXb8sqW?@!|r(haRQziN`5?|9|fxZ43L`&ttxR z7F{S3eBe={eY42*b?mP_jd5{}c;6zy2i}DiG4|J=#yoWiH9LdA9xq>{3K|N`T7a$Z$6Lcgvob3dLLqI6X(fiP-A1L z@gmmKFQfMFBRsNz{q<)M!ovUP+k{M18$7>mH9N|2B6t#CB^$)z0$S@#` zXy1Py@sT6Mu1)3SX^cO9l6ZOyt5BpdJ&F16Ka1N1u{cirKmRt3zx%6*S(oZxeg|eJ z(ckzo=J88(|JIM7V>7yvq&5;RV!}pQ63lB|KP8KNM?i zmFkzig`6Bmedh&&7fw?DNB=4AAAOGEpFfLy>>l)|{+MQ=gla5N`u~0w)-qts#e8xELy)-#s2i?D175(j0X;(pZPw)SDvBq-~OkF^-Glh$!}xT#t>r# z;xBxI*3bVq(T5+P{HJBukb(Wk$Pnw`Wh*r?-Yky`<+|HDsE_}71k_tFLA z1N%|`%kR^e7^nNt9lKHvfgtFvqTA(>;gRpsSyQJLMgf! z-i6!-yBT9s+gYg|t&mdYdQ6^~AbQk)5NrCzkNi-t9y5eiNIyi`HnEf-1wUDWV_!Akm&NoM&Ff`_^+b|K4Ar{c|5h zUtY&PdoDSVOJg)Y@i>K7mT3IVpTpljnQRh6Vmlcw*Z7e%Eh1>fVu^+q>?%9j^%w?p2&g=~4gGbPJ9i}=x7 zvf@|HI5|AVUbTKJxp<6`R}UyfEDVJ1=a3RTmU5uoj6$T^>>R(O=(z*uT(WiM-F5Yt ztW67jXbimWjIXN_IesDkKf{H{=JnExBesha{!J!N& z+YzJBT4f;)Ls@4sPAAO*GqB?Ye%RvW)&DnLeIAio`?bnGLG>~{>fSsE(s&F_#yW}o z0EY#PYou`g$KHqY_2()6KmRrIXP!V!Rq3p6QBVS585n0Tf*-==HAKrt-?0x-^XP80 z@gI8tj9lP)80T)fe!7 z=g$yNybJTS6X-pA(YA%?b}(N%f&KE!2xZcE{9)|>{WF;DHsK8wW_s{<=-gjR{EmooJqgOW&TP@VyJ&36i&hLE&6}B;-dl7TB zN%x)iB9;o+zx@TgfB!|Ixhl?|eie=!KzkO(`O9cOK%QSFo-cz^hzrYzRyUc%%{u0Z z(^$Xrr?lSrPK=-V5Y9jQ-*8?#OL*`89p_#M$=1g6gu!u4Gw!AG(HJtqF>4f@Ni>=u zR&)b3;O;H7&e-YUj4gfky1%LWQF}RMM9yVa00qaulrkeGDvpS|9ds`psn#GJ2Vo4! zO=-%TZ2Jv(_mQ$f84~HlZK)pzBaqk-K^zB2VIqV?N2+J}&bh7UwtX%hBTs_zF5gL< z0Qwqb45jHVE@J*S{|Uw4|8tx_{)=R)O9kRz{z;;J)095-B-YF%#?ja5t~^d~$3cSs z{1++w;g|7#^EjeZq_bxa>Z9++{hiNK`Rz|54(vsQXDPmLl*W(07ySz#ru6L>;T?C; zoEihA@bA70@9+Lqihul<6n^V9M5RpUzyUgk?!b8LPKw`ujo^KcV4hs2@~{604$dR? zbtoP^fxhn!?9Y7*^^`*1eT44E9z|R}NAdT+gnId9#Pkfok3UZFxtFkO74+Hj_~(}C z-nEGT_x}ck-~Al!zx+Lf>k|F#U!?Qs-H6}-PNPHROHZOB1qb)j`qiI7wCfa)ok7l2 zDLnlWjh}uW@{R?(V<+gY)RBv`*ymosJ-LK=?*ZJu_z%fmd;FcmkKNtRbUXsIj)_8r z>pYRfa>s473Qt_R9%5-2sYX=o}mV`-+4Eoow%f7%}!<$=9|+oVGBOlyq}x~#Q*gfuXu zOfd6GASG55VmF$ISP>NpgawyaX`F5s87s691g?vc0wD!XtA*L=5*G^io`=>NuhB?Y zmvRxK(?yvkf#YCkh28EDSvH}S`_QzVc9*DFAn-gCV21%Rj0ijrr`1G8ilAJ=@O`v2 z2t5a<)xziogvA1Zo460StrkYdCn_dmvbtT2D4G1gb%_lLQsQ(wSdAviap{&zN%*D^ z7+T@f>q&o=3W04RqZqr}MQBilL1-cEDykKx@t4`S4zT;vI7dVhG9l zcfLaV9*VWzE8bgr%`WUmh(I+YL!Z*f@zwxJ00RE&e%UcjCiRY(UvwRp8hv{>ns0^!}t9tAOD&E3Ab3w zFh4(?WVf=lp>S{L9LdZC88%Z`d-d2KILtdrdueY3q?}04$!Jp zvT{MOm^{~-SV-EXV%BCh?tymt?FXg>mJM3dE>{wEKx=|R0fELidx2bkCBSsX&#&w;j5Z?%;EsI32XAwf=LZQBu+=4vw!|Ec85~HOg@a zT(>_5)oQ=&Rj6Gv0aO4@)s)@d$ZMs>Oby*nV!o;k}Gzw|{4UV&D-g<%*x`skxvym*mTvqcys<+RdC zwnHO9k{|t%A7ydxB2gG^6X=CB66ZmonV!Fg_kH{y;uXhswCkAJ#AR{@nK^zKLEZ?A z)SvGZFFxYANO@QzS>T?Q0Q;F2FppoR^D`eoTRm^ml#(euP%kme0n)%cc?#z%&(rzo zkD|s331UeoJo_TvzxfQo``^vhKm666K&JYLm$n7Tv()=CXZXuDu9Q8#TlL3srFj|p z_Wb)BZiCPeG`85dbb%LNJIBkfo}#n5f){w0mc@6UZ}aLg8$XP(OoOf;(e^`Lc~vu0 zE8^M)-7v=L%}3muUjan1qTLM%wpwTsAFVuRB7v>7RVw=r6C-KY8-#v9;0H`hOz^=E zd=STRh~fxC8dR%QO2tx^-ChVmr_dlfuCGCVB02rFYx}{7D|)6 z@8kcFiJ8NwIL?OQsA7ZPHdHNzqgXr*n)OZ=WvWC30hMt~4$00_ui}k{bcz^O`;)QvF$L>Z|iiuqG zi4S0Z<5@)4$2@)tv9w0Ke=#xC34v%fF<(242%@C@i3-NavxrWBnx96ltfD3-Q6(4i z_0!1pI%;vAXz%QsJAWfUYt8;imwTp7UVZHZRoUU*S%=D46|;A1uhyD^o!qNY_Dss2 znF+pr5G6F_YmU6XV^ORI_923n3hXm*lgA7 zpcK>7)7y4jZES2?-r0pcd$I)KQ5;imG|*aOS!U+`-p>-EIC$5`C{-tWc8si{f$&;% z??$C<3I%d*BIJ}(Zx(I{f!tiD^gsP8+~o!k<1g$b{IPf8KJzMiqfPCPzChFa5!~PX zQ>@Jny3xSjyPw8?{U75VJx1|2|A2665)pJTXQyF(9o=eE{nIbdoE@X}z#-6@$h3$p z6Z6HRR8O5kuGI-=W~u+9{~YZ=@t^%R-uX2!An+03k41E$ox$iQfGf>aio(OB-|_ybu3_ z@4)=dDLQ}uR|v)mn1Agjh$4mY-Dj}=>}kxiD+G_f3+Ksau)g+v^nd(wbe?zw@!ShI z|DVs&`t@JIKQuqIVKqVtqQCRYM4QW4|MMSUU08*sQ@GE(M)_;g*`7F-TCeh#f6)7B_u5`zlu3val^H zmxw@T|K{x&X}zos@`k-ZyD{7T5}8bs&t`6T1=8&6Ni(BQ-YY%NUvD?+ZtqbB%zOr! z{Ju|Bz*#bc4D)3l`*uprc*{X4;+a|0ul*F(=e|jF^cdX_KThB{n3jbh4LYR~;?gDf z-#(8MDujrVR4%b1vTY*Mz&N;%t)KibLB+#;*~S)|d- zO2siDj*%h+JL8{f>{k>kinr zr)M8{^ARI|UD>dZI_m0yD`l9^Z^ltq78r&k^t+rndxmDK!`#ANW~V2zG3<1!Q97Qq z@7)k&z`!?TFwCbN&E#l?j1pon>!Fzs&dB}Ds@@KGft1MOrwPw)5d0s173Ygz!TEzf z$AAAj!Lbl)Ygi}FVSWF5I4_^2`;UJeUico)i)Rp>E~4ur{19c?s3=YZVar6cn^;Fr z5>J=Wc5<}W?L&eXF(5|gsvX*3urpE&Z`k3@o8CcEuW$0|tFM9S zaPZKP+&I+0rrxRDQINk!WB6IVu2Q)JNu=h%+&3g0lIAeeSzf7}F|)sLI!_62hQs4E zfngdHzV`y*b4L+D7x~~_=gV?M^p>6-*aE0wfO2cu}&|8xrO`mD@1c1(v%cG z`6WbBe4f(xd3hk;R{DFVHb=FU-~6K}SNhHmBVKMQ+L(;FCYD?1tDgpTnC`oh ze0MWSz0xxhGcdTcz5wOFd5F=QjecNHJ_u+aXh>u>1)X|bYMlwaVyK?Z+a1zpLuIv0 z?H0M9C6NUEh+fcC=784o*8y^N41HT@qaZluZkwh?g3gHU{Ia zh2grr1QEUZsjEqjLo!nbs($dE9`K17#;G?Iw1!cFT7F~iU=S1W4hF_i2DYKHVn}0^ zTEnyXP-^tt+$PAd8+2NAzVVHxFieL^twt0?OiWD@w3@_1qEtv21URnC%=|nvlatA} z@4`xD^ES*50q4)0qUFaZ72|gUoI(LxD7v9S>4>1y!EzjG6BF!TTpWoAyRmxd`$6iF zU%kGDweRnkY;>7ZJee6mNLj9-eUh=+uloi0-|v&ogdLeOe7n4Ozp zz1d`=zJXILVPUYovCj0|{5Bb5CsrnXH~6V1;h8!P4bRNY}-+ z9M(6MD3mJ$D&BlwDK*>alG5#nI&{z_FM6W$c7#KNczQF+X|4NJ^DgMAAHE8@tiGA7 z)Z6feA(1gcDy{>7@B7BJ=giaK@0Tu3?6<8}D=C{<|+mSrJ?pxfJS)9GYaC!3~;=Xp2v>+1FTz*W`T^BN3>8ug8sx`zuQ=R`;! zIdra4c3A8nP+c$N4L6ymr;0(yYm#LK?%94bAa$wf3FHHTUbiV^C$Ul(hC#9C;d`?{ zDV0$Q*L5ir3OBXCR;xAe_np0@r(@!yf*Mqc| zPT_ZbD)alPPEN9Zd6~G=K${*D3-cI;K@2OHm|*MtDctdS_T7I!r=R@> z8Vl2L(A_phvBKK9lX#{@{n8nnQW;@8Nep!uP%4$!+}NZ#J<0Ofb5zI2=+w8UEZ)iV zOpVhozKG@8iC>jaXkid*!NmL?I_v8!Jn%4UufN2lvuE(CQ*gAh2qc{dp7ZrvS zCZ_S%m+5pnEZqArD<@v2>kC}hM1=vBeMhL(O1$#*uV6bCaSUE{jLC%smR^0C^4vbw z&%Tc7dQ|rugw{IsdWX{F1nre2f+)r-mhkJFOy2bnQws|>gc_xeb;CmKP2Zlkh>~vq zmOLu-gmIC(mM*;pAm;!n`{4^ZE0~TyldW}1g5Jn*70ahiFflbng(8!%jCX;teihfYjcav+66W*U7$2QkB9@dmM>B)l`wVu zMkasT#*srBpPLQ0vaemo(fe0IriRUIUGz<2Wq=8p1v3~kE(|h*PTwlg1 zln`1`oS0yrurY+ftxeHbIzw%892 z@ws_6&Y#6`9aI!zm?n;6;ubwh#S%fYPHA$6(%2@k5-c2=W8=a(EYm?n5w(eFbSFUT zh{oj=W)9zjjv`8)hgYf~WEaEG`0*xYZ34qI(S-uGSD;$-5OF|da+cEAI4dWQqOAh^ z@4lDT#wKp5azmM))VLSNF~0BL)J+?PVbZ5gLQ&ITqniavDJ;v%X{rX_XNSKSmOsek zMe)p5a-DG^jE%5(=YGdQm(|wwt7}tR{Ii1r;w=9YwwXz|4c|pcXNe}(w)qD6IByJ}52qnT!PK;@t;WEQEi}d|YPLOio;+J%6d9%d!jc%rU zCrxXWcgY>hMmXrlaxKu_+5jO@afCDsf^HYDSSD6+VmA?zu-n0MJltY|#`-Ecj@dkW zoUsFUqvHs-QX^*jU5zN~o|)94qP<&Z4XW6AKGCu0wNU z4YypwkkH)P!Vrp;b4wg}$2%~j5@De0G8E#yV4njt~Yxl5Z)FsZ7q$ZEO%LL3MKK4V#nlmf<)Ixwy1Mp&mR5$m9x{BNZv} zFjJS0zW>M&UzYh$aa|-s2*K9b*J(65M4cvv<5DgaS#EYPZHw~cIGt|9@`aN zbz!h|=^~b6Vb~saX^aE!dW81M1une&619DIuyXPk<%vmFy)wdY5p~)qrRZ!fbNaha zQJkDjHfD8~| zNW2-986$hdnP-);i^zvyi`>qiV{(U(Z3Mfyo0$*t~p!+Wg+c z4WLj)2uU3JtSv3kX|=J-6O<;WQ9%c7xwuo)pkgkcK0z2ow6?Y=6f3kgHt>p7x{U@g zCe@jFw2;VR8P(iEOB><1=qRK#InCJ23}Xw67_m>}`>b8OKpY2jT1|@MlT;S=&|FsMO{xp~>1?hLG@Dq35>XgZT|9^(HCty-AWR3lSRiQB z6T_PALL4G(4^-4k+yz#thKRegH#Vru@1?u3OcW^!wHlqRI&P_mMxp{AZ)%S2>Lt33 zI)>w-mBt&NAZRsFL5HyGQ<~q8WgFDbpTVh&5qDd}D#>kX6e~!b+%wVHSi>8i#W109 zd5O~WJdxi;nikI3B;nRFE2mCSon0jEHtDun6sH!@VH>kJhT|A4AAgO~>|QE!^RzCX zqq(+@ien7RL|QIV$4J{w^L2H3C zF_qavl-Akrw41y&y4Pvn5HsZGpCNOeA5AAQoxr?WieCIg>ieI4Yubm%CWstKCJnC1 zorpUvO#Y+OYo7;VmeWgcQr@=bZ<8#b9Q4^q7q~x-03$DWo<1y**H=j~KS=4fs)Ivz=Q)(=?3%;X7?Oj#Y+Kf?=9+ z4WPjppY9JhC&Ul_PBwqvqgQ6ZKw2x7j=x4}YL;T9LV62nYL!nhIh&`x1I&PSN%XW{ zO6P)85U41`Z+Eam~` zY9@DeZXX26vnULarkSXMcbVcFYQxCf&XZR2o~Umo)J2s|QrZzD~eQgcPaREhVV*^9N%H?Ior)F4Ry3F{VJxm=qgrOB1 zm(DUazZbt%XZ73}yxJt%ZxLZ&TL!Iq1Isk<{Vra09GdI2S611)a0YSjL$p?w@W!Sv zBsA7msLU+T-C9E_&E+$v+5gaER3^r5Va&^RZPD#OF<^Iv_sSr4B5(m7n{~-V1pZs%d$013rF19yzqbDSe**JNWW6!_Hp?80fvoAbD zZDO4DOXrFG4wYIhu^I@?>1V!37{e*Bbj+qyEVFXr7^Y?6cSD5KTzJ`_xwJ%W zVJ}g)MYrp7$0HwPYHFO-*I%L0*upK8nV6m>h`Pxf6beZ;&&De4tw}25HLU6whGlZ< zxn~IKbsCp1|zyftVY;r5eHpbmoIYqx$h8ky4b}srE-Dh))rcY1YIAuI*u?+ z3KP>vL(p7XMM(>{P^RFyY_6|j+Af8H&HCCJj^|M*RSCL2Ua?4hb(v1Re#_!rM#XF2 zF0fO8(r$K)eBDvccgFpcm&%)-6Kz%Qehk$UhzEl>`VHL7>Cl*Nkw<^x7m35f2&k08 zbY1q||4wuq5l0b*SHiGe-u>f0i($KHl{nTJwnNa^#41$KD(qptMp`yutAQ4RW8eKc zcR%_#PO*Seii3~5AB2I9BZQO`N)-&pCGK`Wnix)^4U(40kq6(I*d9s`5_K9Fw#UrD zpzj7^+MwnTrp3hE94ZJNu4#!gd2;*cg^c9EM2Sxn-8t*wFgyDJv@Wzx281Y&8e@qK^5m1DU5osz2Urm;%**Wlm>zacG>MJ}d@ zVVX8`volzRU}!9BX_PR?eJ9ItTYGosiR?zPr9le5`8x|2y- zN~<=R^<%o+Lir-^b`GxV?wSd3Cl+Ox_s^HzDI?%;nc++%wrvkQ%Ui^U`?-?e)L_5E z&S`oZbQlHpDa?mG^xe%x?wwAvohO)@xIK(oxMAz-%>)6|!+;Z=27$i$3Cqfc z$sL6XwoHs%1{%+}HE8K8O`yar$B_I+_DWSAeeB(YK^LWaES6G9B5f%#r9lvMFm0D0 z2zF$NuH-&4EXRyOl$2fDNtPKl;0+_>sJf6Kh#^QKSTmc37&z$D$D&s*%M#LPZzaL^ zBb2@(FPYrzMFXB~Zt(e_g}Mb4%2SHJDI`ZqHDaZhb|w4E&Mo=Y^=`zmMwrs%TLyWT zi7<+A90$jB2O~Fg@}BFtSv|P=Afn;2qo_mvneY49wvAyJ*~Z_=?R+P#)F}TcDd1q$ zCX^PPNYRBs?d!nYBsM)0G}5r}3Pm1#@BzN_+>2QNM;^JfzA+JGR|5^DXaT9C!T^$A z?c#HFWg|45oV$iOB1q|GfJpn|){AlZ4Q!ewV`F2tcm$(iYio-z3^8(v*xsnydFuP- zn1YIHvEB{o#(+qpKL?$q`quymK^*y9ymXP%ufIaa4>O0ltj;Z$TQ#Z|TdDy^2uva9 zYDJLQT6*eG1~EU4)iQ)2(u2Axkt>s_qlfa)YTZj*oU60*C|PZ$Kb@}7M3XqBTcnna%8^5 zcTa3EUb6ZAxjLd%@$_`gi7JZicKj|fD23;k{4o4lSHXtDa}xl|AfU+ zusGqNkBs412CZ(Coi?Tv%#XXcmc)>Pg>knR5TlqMcNr_$+_$$v#WPu{`$TaVjH}lL+H{h@n-kUj|6m~NR4v&AQ=Xqq3LSW=V6Z&yV8B?9>8%z*%J8jlC z>nyLX4Y+=!Lim7ua%-jtrTY;g4dAIL*}f$-=eO##rNNVNoEum_1^m7+vNI0BEMFPS#cGwsPlu2@TARxkGiyf|K4Xijm3~ zsh)phVz3|YL>m<*-C6hhK&ZSi}* z_q)BwseX8y6apxp-Y;~wtkdL#JIeM?bZ#zN3q2=?m}yUse3%OR3Zyf8t5R+RmrVc zLk&#W4xe;pZ+>Szh;x$|XbAM1FNoe;7_?*Lo%ix?6lq$V@$vC2E`0k*KFp_I8x>4l zMcVClcDvI~2EO5RJ1JZ-f^S5>>9~hSn;QJgU;97(mkFtnGKu-tP^?t4RFnBEA-9V1 zCw%_xsbl{^fOKOirHG@D&8-HNN*S#ZrAIzk$S_O{DS7dG&k|s9_|Sfgo*z}W-Q?os zRrc@OmxMqIL7`C0G@Dlfr4-F(lTN3@>gp;By=xAx77vq^;Jj)Qlww7krN z4?j$~;3A~Nb!^sGHu%Fo_yfwt0_|qN;=x7MSC@GDTi-@W$>RPy_`v($bJd6;gy7Pp zOB_3PjD7p|4U8}U`;ABN<-Wc5pOM`Z28iu$CuS7Ixn#j&0EO}ir*5??_}g&vARobJ zm^OR%?4i}zVr+5_$CMNbE{GW0GD#1^`Nh4AP0cVlUL^>+Xk}8U6uJAZJ83ss_))~n z+&rFr^@$zQ`~U8_=bmlhwdpu-Oa$M+Q!-zpVc(q`buiPygN+WyC%jE5-YRgVl}a7w z65&%*s#GbKD=;@pmb4C-nVU!T60${6M5$V%T!rbGncdsJ1{OGuFMb#+1hYh zZ#aT4&u-<8cQNpzf29NnOqrRfM!DNDpz3;?mAd^PT@eXbQs5W@TPFV*xp37OO%Q9s zP$7Emi=(trX`3mFVwxtKo15DN-m4zp4nasM)M~YXa>L=X*Au~)KF@v+)lcYU-@!2d zoZdULr_9alUj3S)Cz0f9zRgPAE|7Q-L&22PY=ep=aSeeXM;v24$x;AOD4-K<6PvvF;`99U zNA728qKIiGS2o9SjM9oQh_FnPSSiZo5@8S!D}|H>S}VdZ%+l~kDe${Nrt*zdOcX{~ zww?WZk8$q8c^3EWr@gt(^4bQ4Vu^OA zjcHq0QW7fIzqp6jUq6<3S!jdWcoo0ZC5U~5Au*+i-|bSVPB1Z1=EC_U{IH8wNpk7g zJ$t$9(7_!k%C$!DZC|^DN@NrRJ%k(?#pvJd-G7nIWa3PSc*BXE->RTV1Y6e-6ii9c zOn7-m%FI(!0in`#V?{esw4&s9Jj$Q(I$**v*jKVJr6AUc2bs~688V|(_TR9JLvQo+ zLOHd7G%bPBFjcep`S%?`N=dD3VVbj`G_!LHL{XF&_za0*7);JgVLL8jZkD}4khIae zAvO7}@jRDWtxBvE2uZ~q zs+PntdYYbHKxqh+rV+-hc4Jokh;FQR9MdSs_b}&~>?vAk(f9F55h4xIO(}&KQNQ1p z=plwc_TAYSRqKV9j5PwH?foJN9PR6 z>4wfM)WgEQOy!>*6PY4`0IkKq4NtpmiV=7N^jN9g7A+$=Z!!5I{RUeK%9f;N8I*dP z+w4tptTn#UG(*K!7*h`vzS5XNFzp#E7A(q^!L{7lEJZ?HT*GA2HEBl{7uz8h+Y!F% z^RFrO@p{OnNz&=GBSkY*1WGgOnJkv9EdE2LaRoi&T#6uKK>i!z#fR2Yi=JFUPGBBV z(+`(G#0*K?}Ytr{< zO{G|1yy%R~0+KyQHQ9Rm90^2U_!b%I%6(XGW;25E7C{aTc!prcGnsKsN|xO9q@Q+^ zlfD%xR{e;AA(?W`YeI-oAb_GNIb3m=bWKh-0t_jbat*v*oTcvZ{%P=#AYseek)mQH z!MzDm^btbRLx>!;fSr{idE;&xN1sBYzC{peYSnUf2eh(>@=4n3$Ic`#b%De2t*{v zPJ`S+E0tV)B#hn#NJ`2~V>Bl@EzC9-b? zypRHBJ(Imfo3eHF7dc7+WlK`F?5nPGEih&qcr}-d@&b#wRMAJ9i$_u&9lXQE-ZY@%b`ur>PpUMPxlx-FY)*C+UZ!~mcMLSMHW(7GOR^&Eq@BdR?-{>KM z%&5emJTcO}VaK`a8NE{WL?i~ishL?U$3r7AO@p!Vaa`BIG7J>ZuGiUYw1^Z;j89++ zNxRd<@d}LBDuiK(S1e=8Dvef$TCIxb772VG({ZR(Y#z`MD5w?WR^9-7rX-HAG^( z%G?=93|E0l{@Y2*ld?{CRvo6@tH04S<*C!))`Zo_ZNM7@omkO{6A?c}h~XZ#X_tiP z3D*qdLlRe{7*~eW;H8yfd}5NZ@reNo^nh((W;#jVDh-5ya=F6%!XA(kW5|7DVk)UK zHa2*XO`DxMYLmu1ooFKrmg}hLZ#`%Nj5`0G*HpgE@(8N)&x-^fI3o8FeLU> z@Mg&zBv~dB7Y$9QQ*YKmSs~xr;K`q7eERR?kaFaWQncMp>Ore=|Jktb(@x>B`SiE`LQJdYv^np7uO%rLP?&oqOwUAQcc*(^;J89Z-6P{bW{$@7&4~I&o zLbn(UR7yAWq-QejniR~0?NK`6qqjoEnjh2YrMuZ_NHxpgaMfnazP77$T|=_JWHaHI z9IN{nLa?V`?YdDkeI7rRmr{ftME2xuNd{a(r?n-+`ugshYR49 zt0ebDYN9a8cif++p08B9vBhNB${j8{Q=)+loj$lm=QUWRJfy zOe;BPWa0%Zq-3#JU~$atZ~Rg7Jp5hcm?Ev&#((TI@mg!Dj=`Ryn{C9MpkPW4RT7@x zmIBw1g8}n5Xn`FgIZst?gT}emB?+sAAd5{%1=?+Po00$NOx>pt_)25M3eS)Pv7+0P zQBo~a%Kzu(iD8>VU&h#3b{VynHyR;!Vu6zWw;S+a(0g^K6gj)Kd!@0|DrFwMrZ6Y@qUKxs`Uj?ubr2-~LC%x_luh?4)NfpO^My%xIf zLnFup^2}hAYe(iH9sAlQF|z%ujb|C2pHa5gH#+yXLlWnKLurJz?nXnbG~Gxc#FZ63 zSB)4_2-;e3e7%lwm80LTcpLrfdfH0anW3#XQpYbww6%*gwaZ`q26k$DxQ}bu%r|nr zb{+rFJ8=zVuQaaR#yhf~)I2Z(QLm+~E6tN2iCzq(iD_T?V842b0hpFWBqhO{dE?0q z262VIN4^tRQRXW8)$C3M^oVj-f?dlFy2Fin1=slQtpsTd`_(`%9^>lc19l3Ie=CEy z%4gf&-#`Sp-uHRfsoX#^y=$p=mHobzV5b9V_*=~@u>_2$U|nffyhY)vsKqWX^OHR4 z_pO3$tctionJcyN0|FXNkYjcRZw1gjAGU(hY$yeCcLDsG zC`R6GKni))>c_X?c7q?jg;QE1mFkh4E7P27LW}{UnYcZ4;cvsWf!3NRXafFDCHTQZ z9F3-cG@YxLrLVn{AGAsP;R2;Joz_WQ`y3x7qAXngxsYM*!y@){!W-iGT1g_LRR!w|?Aq`v8h zaW(GfHx{m~uN%G#8{hmMOaJD}So;=efA?wpI_&xNpC?{hWAm%e;T+me<qzJZ@!FsWRdoZ$FTOyV|tR#sf(yiMD@du5MI1M`{i>KAG?oeX^C*PMfGEk zVbzLne9%8+(2Gc67%`HB92$g7e8qON)8umB_A|@$efS2``RMF@3Tx|aN<|ynzEua| zwITWq9hD9P8s9yNQM74%=M_v#VpNI?{rt-`o!1D_!G%kd-}ex$XI^0QOV1*U4sv3g@sB)o zizfC58^SPRYpYAaG4Vr1vFy-k2S~%fkPt=+A)wOqP{ioG_$vNtn~9(M z5Sw5A9+h|Bg<7qn!Ke$^0IVm5XhpCs-UWadElH zzQr=f+MCQymT5PAX6LHROt=_^fg)z#o^k&8&(1UV#55b1JGjLvmzOpvmp%3_*0^wf zi_>Q}xckUBtyY)kzkiX*$r86tnR9LZh@*A?s_2;3nj(t1f{hd+GxA+8Xy2#t>`^c* zN)H`DI#+*p+uLyc5XXvU{S}JtdGb+mmoGKgXlg1B96#G&@7@}hF4dWxud=?}Kv*V@ z38rO&fGCLYN-le6Eq?d+o@U?S1I$mCXf}Kt&&H4t#Tv&@Y&Byn%cN4XIk2}#9L1bI zv(C&+g;L4B>Ha55K_@suvAmCN9C5xA!xjAf-ZT}Ea2zU+KlEmG|3eOgtdvGGJy&H$ z08z}sVht_f!2SwaYYy()Ik2f!Z)4al_uf0h?6`%}J2`C#Ac=l7Oq0Whr~5ZJ-2ztX zT5<1f-RKW3`fn-5Ac zc*o>bz%50LQ0XlB^0h)7g{-Zw<9bCZ<t;Vpq2SDUXW2RD6Z#5%c%B zPQbo>dwK2XQI5X)D&Kmv zNEQk$qTORfuRNsdtCxW!xd&-`1GlA&5h{&DP_nOI`yiyGT5>sc`V5VFow@x7D7zMy zM3T`u3In8RQmIr>BQc;y6SI1KTp``aX{1(CKt26pI9Y7t40gaYPtv z3a*>nas309(BWD@3b4#k{E|Q^6DbXp>R;I@R2O&Uv&fC3gtI?}xZ|&584jQcXwzsP zBlycY;$Z{*LJY1zSR|V~0vwSbgwW9Lbz2}IHsb;zA^wI!xFGgQ@SvA~I6)c}+;@Znava(`w-rikOCx2==|3b{xkc3<4yAt<6m)CZ{mtkSLCE9Ggz7 zg<;#7oZb-+PeN;2?KXu%0VySc-=W^@FgYGd4e&s&>OSNGTaGU zAliT}lS{JCC5Ah(0BnK2s1Y+FdAF4yh?o=TWf1pEgwsQU^Psyu1TugwFe4BpV55gP z=XCOWTx8d@^(G&7RYPAr+;qe!nSy(37GV_9ZnrUe+M;f^i)orzmes$tQzdb^wlNq@ zu2sybGiRvP#`yk=FR*X_elA};&+MLkY+N`;BZx7j?y*rCEiD#i=Q#QL>llW~T78wf z?s<@))ucQ=f$BCmdHO82?PQz2;1xg!!Z=2$m}0Ta;X4lS()V8^j5WeAC>1NWW!g63+#`hIF)F2X zv~Kk4YY?tLzRyS~MJkU!+WR+Ur-I&ZNDu%Z)aWjVX@T)cvqu>~FDvv$Qcvs?h*EEy z3b0A~5P-vw@#NZUFuTDGMT}4-SMoY2R2&V&hCKE zM3@2&SFE9IhsiCU-A;!%3^;Z2IDQy&xKw7#G>F@6E-kO%dIeM*5MvN@y0rX|v5Ld^ z_yjALF4AsysZLB%ueUG^$?Dn~reUGAqS@?V+ZM5k@QO7gf@Z79<;$1pL@{^Yc^7Ld zE0~srWtv=CUE$REC2G}iN<|wXU8D|a`2kTJ(pX=kR4%h`-(KqVO-`LWLEy&-t+{aS z49lylL{W@di?J=2;-0;@w@8hwfKcT(kmiNcpXIsBzs<_t6TEN!f1zaVMTmY<SH=ZF6)(od^S^d0{=Iq`J(QQ9=!*1g!~zAfXUF_C+a$@B73^ z+R~3&Sw5 zEEB)eK?zBvQYQ4fwAvjU$03Sh&b71Eru? zEMnU?-;pwo70u>J3We4FCJ=&+<~hFb!ars?exAGb{xt8I{SAuNY?9J+ZC zMT!`K*x+3EPYD0Aj@|$P%PgnrjZ8Kcu#q*R)FbDRimDR^+)B8p9dZVM@8mbFkyNf3q^>(cIY zaBLgfFtFkn*Rlv=O*hsQ%zKp;VF?-SrAMu1BZcrB*9L?~a9H;V=gd--*#nS{=tRlarJEG1xYxayhxU#I~_) zI~jxH(C&077K^y9JCF|F?{tV2OifKE%cnK9v5DS-rQ?igwG)b!+!_Qbj%cNupYeZR~+ZugNL6opedKJVhNf{ILNd+E=aljSGyCu2>`lLqObze_Ak?mW1kS6+UFNJFJmq|s`iB0;HK zq}y(SkVw(Y1Fr9wL@BQh!RjLRcLH9 z31h`Xv4mv^wzldNiY4av%yRzRStci@*xXphbjt)`M5$84G$l*t&e8BYxNebnE2Puz zU|TjZT{ME_OBV=Yf#*7`t*p@6Y;gBIceB2_%Gzd&v9WPX6;LdW6LcEHN)tyR4L?K} zHEOkSRxX_6+`02i&&;!Deum4J&(muA>|I>od(S?N?G`Z&$;C_OaoqxU9XZJJ&p)4> z%3%^q?Yb`Y%?;X}E{4%YYmMW1REi#c7+yDGC=KC=Y<#iS+_~qI+_Ufrf*?j|u!IDI z>^9d}4c3iB&r4)OCz_*z=nLHdPLKMxfsRh>8&_i91>j!$cf|@qy}kK2UB(zyr`>J? z3?PT^`)I&*oWwuBcjJu)T4BOU4ZG@e+ikjGi0e44t}KD!FgZ3xH}LU14=JG2>0p=^ zj%^bLK7J5lStd$D(esGn7zBiV^3L-LNC92n$1n`ySWzk!Idl3n(=)R~QHX8Z_(0&SFKQd1^q$$lgVg zZg(Cjoo(z#b`Q958P{!*vQnYg;9UKW2tLWzp$&3BwS}vaoHNmMzNu`j0GYEvwg@Ct(s*}ciIEjv?eL}7qsI}|*ZPP>H=k^=`1 z_EpG1fMHt66}e8ouXeM+=2o4_iE*5s?PPFfEj+Wo1LpSZ$=W=0=#Iq3RT#9qyKd5c z`m{DSHrQt22CWODeFUYY5bAsq#Iys_NvV>{aNLZ)o p9@50zB*Y-Q;%(bWe;qQ${~zbWB7!lcBnAKg002ovPDHLkV1l?yf1>~Z diff --git a/docs/3.3.x/docs/images/apps/linkr.png b/docs/3.3.x/docs/images/apps/linkr.png deleted file mode 100644 index 62dc5f6c51174c77fdc4356a7f442e95cf8fb6ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6428 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 diff --git a/docs/3.3.x/docs/images/apps/lists.png b/docs/3.3.x/docs/images/apps/lists.png deleted file mode 100644 index a0f48c63b1eb40fa7cab3c8384ed97834c621e21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 697 zcmeAS@N?(olHy`uVBq!ia0vp^CxBRtg9%7-@wrR`Qk?m2ZpAEalYaqsP{)A^Sj1dctwU7GX!VMxakkWGLLhaEi%=MM)`1Ny}*B_UE=g6@Hf9OG}D!*=!SaY~Mw{B&8&`z~pu3{nFAH zT0aHx>V=+M9-MM3=o!-~Lnp(3RySKK7R9I-r|t|h*!^VEi>Zlm~ zine~g|E~CbcW-6ydmk6FdMf{XJ*lq>S=ajI?%3GAeOGRE_~6solkasuKkv49W0=MM zU+cCW;*gtNzPB#mqt?D}BC%f|FFr2IE7HY%x7%%}O$W!c(13RvH$BhQ;oVr4x?$Ow zS&kd?VjG`c>Xy=edE-iV@5Y)xXQPw8i|1;0oIN!?ePf=k%&e2gy46n}w%%R0V2fL| zy3CQ2cbl)JWX%ekG2=_s>eQaVx{8VdYs0qAOHxUZeBk=-x6c&J8oFNXGh8Od zwr@Gl=6|klqi3$%5L$3mzWCJUBMcvE`CS57oRWf;3S8AHl+j+gHEi?CEBuEaYMk7s zaLhm?)P^_haCi83KjjoQZz ze__LE4_L^-`IrAke7j$BX#craa=UNeTyu@T`2D+=>-C=Q0VP0BS3j3^P6yKO9<|AaQA}+cL~nHUB0~k;MU!(ovGfb z+TEV*nR%Y>o~WOSQYeVu5g{NTP-LXVRsPi@|E^egxPK+J){-U!1kRbYnAlHiQ+o&q zt-&;HST%K}wgOiNjEqakPGA|3PvUSM#o#;aS9Drf3UNqfVHo8fv|rK1v67O1Vu?dS zN(@7k9uWTc*naJKT+(%1%I4_>g7O7?AGR=G^&nOpFvY~6jlV+#2M@|{hV$|(&M@(} zYeGPCLz4GF;}uJ3{c251!+SEEoS+Hx$Oln)m<4?r7Tw<=-a-*i8~FWK0Jrvd)B`)ZvZDvElXl{Xd$jr#mUCMKn#$H z9!1?kB&R`z&ED6*9(ER)-aZ7zoS2Q&fBCC%kMv|gb(v(arectz@D zkE7sY2pk{S@0YQ_Fa4TggEi*?34d@1tgd~Tu41{y`~GqnJR+{=fiJaodpsn24@#^C zk|3TaF^6|AEREjezN9uYj~}Dy)3ZBql_&Mk@Tr7O#}ht%J-@)V`_!eP+f4ao`7%lM z%ftvGG7zRKkPjYCH}Fd)q<-Ne@KEHqU-}GERG36XhJO*TWwd1s$KuFBo=H0u)4S0L zcnT!G63+)56Mc%d!8YuWll?&oeaAzY4qpV)rJ1E2KTbYDu?;U;0@YuaAn1c- zB{oIfOD;=@N_2jr1b+DwZX~J zLv7rWxL;x5PxsI6Wv~X67kG`;#ghqghcGx~pu2d`6H1?pf<64;Xdi#3Bh6E(f&XU3EJ9zhjZ&8C43 z;jrcVc6#N01-iOK^0v+k@FM?j|jKvKV zAB2?%*(f5&{Y6%U=NHs+pTaDJPM`l3IzJ?|5lk11s?j$;2stBIJ7M(D5O{QfAw*{} zs6<=}BwDfWiGpTutHLvh_y^FiVqa&!(jZI(DvBKy#{A@PgSH926iX-)IflK1(+TVm zJ^O)J9*SqAsD+*$oMvplg4G)GI4F2U%Kc3-T&X|I3C|C^HUd1TwDZ*q@dJXn1R@%0 zICM`!rZ82xlSVETX#!tDbhu<*8TJ>e8sl%gsA0=rw2NdmC~*=CCEl|bk<@Xs4_0V* zq;CAYnEt5xVYO01!a`!bBFseq6L?(ISX@bL(^%($C!^vYw3$%ylz&mnk+eZgnb-{9 zCPT3Y=t$=-WA8_aMl4L^>fKj7&PhDJ17inwwVX}3-E%49BaueSc4qc!_tu=m+O;>( z_+j($nPa&6fIA`AQBP2B*nac@@In#WBqgMnB&w866t@&Hq?2S-B(_v%)H#&vBo&l6 zWSZ1%LeVhMqS0qq2{cqz!%b_sR`c2oAr=DTLr=JaNf=B#E-E8>Njh23MA zle-iCljM_$6W){Z6XiR&RWGy&SI8!)4IC8ixvOlt1tXu3&ENbjr ztVHZ1Zbjx#`C$1G`5<|1d9EzUtfefTtd^|q%!N$btcXla?G^22tuC#3?NcpDttD-5 zt$S@~EmtjkE$Wq7yJEW~J7v40)y|b~t9UDaRs>cSRvjA?T>A)$2{;KNcqVv!c+z<~ zxKVh-ct9>5E=(>g&eqP)u7}PoE{skKuC`9E&PUE|&b>#*2XlWB4rmX&`4W{F+}qI^#uYx653k*?7_VJ#b8d-u>voB8NHBkXyTaxspJlA4 zqoFva@e-{UaWaUM7}KKB_$7Iq_CrKV^(oOQ>#81JLtL9exK!Ls80(ul`aL!y#syBu zFxK$fkn9lLFv}j@UjLr?o+(Bu#u`Qv1_y>CMHa<01tujvg^zi8+LBnSw1-wai6x1rTCMVBOjl-C#+&!^5#k-NkGHdTqo!+oIg^*+Rua+p~jZddDM055E3^g1r7_j3%pyYx+i#g_MDN53dBg7`tO%4QR0c>Z>@B%fR2^Kk=$& zm~OK4Y-i`;^k5Zlq4>voZK0u}!gbp9?AGgM{mEK$B z^y|2%)UUELxrVjG<;>;ku#zt4_m@AifBtB4*P8w5%bJ|j;tZxF4T_|84cL%_%Cs=i4V z2)syoDM=swosi>`>ia#PMz9jBe%yVlwtJE%INb9RQ1&qbnHKc7zdNKxEL-fc;6%We z+m8RuY{UQ<`kW3M5*GCMx&;b=f3I)Iyh(a6y{6t( zY7?^cztnfp$$l4oX?*9n#XoDC+&=8}WYA?)s)ebst1kaEdRJ~K?^^1gZ5Xzp=2)-VuxSf*aBp7 zs9+!3PZ=xS*l!x}qv4jM`&610^@YeJW~v;@%=5Cd-g6mj@@!G8qxH=V%1wMOYEA+B zTazhMuc-;?+mbt_JDA2KWYnjO9+F*BChD?UYdTaSt&$GnkQ%AVYjwG`Ds?Xw%p&^Q zg9>a4XWS5TzH$*HqbZ6lGfH|} z=ejQXo4wBH?May0o0R;`0`^^~KEBWB{`T(=FSjtlkg7rUA~?Y*qJCmEsI)0w16Rfc zgHq%==i#L5Y((VG0flMDT)*ymWr>3QCsu2Z`(u`Ao=*A{%)B-soL za{2CA&TJoCW+qM!Hx9e*q3-ZTM6a8|kNBhGzu}}W<~!2+yBI(1d9A8Fiw-}^E}DvgglgQFs`o~dp4d`;b-H6x!gJ1w!7C|jtul|-F3Zv$KT)L z?`Fu+-hg(*bRJD^bpqKw8{4;6GXFqa1*5{{B(_=wnEx3u4NONER%o2WhPdgF%dn&Lo$QQUiMf~g<3z_;1icxJ1`P+Tkh*u( zi$AkQp1zpmf*$=(KDndL%fKxu=q}QVr0RyAsP4)L?RxKKi7xZxKh9@ZIcn=}K>1g< z2(wXKYC}stoNoW@TDVtzRB^&7PoUzt6Zrc0rfXmQ+<#?sPIE0`-f<2EfR2zPZ~EttqpwTcBVO4hD<$*@jtTb^ThbFs@w`1k z!v~=TzqP-!ylah=O+`>sEBR08%ot2-3%)aY(t=GtO!_O>gl6V*RcR5KY8g)Wg!DU| zj34&S8gULouoIYCG+Om8D_^|A+AKc*?AbD(;@0YJNK1IsweTh1=c7o(iA`q$Zy3LT z2_0+fY^@!;0cGSswo4H;&4Iz{%Vep;1khuy55}DBt6DMICf63gmBe%wF!qx5QU4Kn z|Law2==K1IdSu_gr*}TjC`T*T&d1+m;v{ZJ_if#CA&-r+DPqfdT6qQql)+5k4}R=- zoqIH$t(XNB$rTw&8uUa*%nX>78+-v4-VW zV{@}jvm8s}J*&g&L%JiTJ=&e=^_1a^0b*KVtVNu?uP>w<^eS}UsVpdF=pp48q~m1- zk{!}J$aHBkNWkTV#gXdgniHBHD#q&GMLNZQJ2W*2s{|{R>$1uYt7eErw)bocijf9?ly;(@s|4*)h6l{C0;#O{ynq3spGe` zG8;p9myf!OUQd$U!dm<-`$VmCqMe52lzG>Uv&KhKV)FupZO&d8Kn(=?ERh$3G#4)6 z2DS^o8sFV$(f4FF7Yoe@-EcqxP3#6f4_+GjG@d{62xB^}$D7l1QYm+Z*X~nVNghJS zs2|3CvUrMiylQD+Dww)lwV?b@nWY6f+o95)Vtheoep)_ZqN!K*<=xA_IN{WgMTTwgL>X(D*M zh%F=qWEPDRmFZfsKl6qEL7^G zP6%N|=w!<+*uX3T2zn?84>|}zWhA3P9SB&0Pu~Dx>Aff^7e%T*6!Ad*Wb1559E$CD zIBRK1Z|vq^QVPDU&|{LX(n#ZIgM}&5f-A5JgXmL8XMOos2o#g}!OO~iG_Gn4zY#gY zM@rP^M2=nVkdO&Su*S!D8_+e7asn^TLvHD}p znT)=gS(~*O-g#p|ht4sAZ`Us+_H^mwgDA=r$?Y>iHU2 zN}wH^Ci$Z}hH_D{6|tND*yqS-tFK3HooI4s$Z8>9ndIZ<8{yG+3fN&il5H@22^{Pv zcfcMJd?e0)Gico!_1E!Res_nSfvbh}4MiqoC20wrlvC@kFqJ0FZPplvkGe>HZ6k9e)ijFX(bW7}tHucuIeYN&_<|)IYYQpJ$(G zw`Z^Ay5q^y%*L$4Eam_%62wKDOXEPE^&`q9vrx2MSV9C_fkWy-epAX+ctNpBWL>gC zZduGxPAJH%{47>mzF1x<6RqJ#!(x+8Q;%tkF?GGBla=$7(_g17Csk*qtBpN@meB;I zh=Q=skUoKaJ5onu!mp6ZyewVZl2FVtloHem^dTAADR~+ADPZOHIxoXYspql@O^)B) z^QTMS1G0B@DC`XhsrAJKu>HNE&Beq@LPoBsa1?;k=?p83_cc(7Y>c3XSp6RV{6W}J z&I)EG#8(Wx0-_yW+{-2K%+c;e7TA3h2(ldU94w#}W}0Q9VSUn*_C5B+aLp9)G8;M^ zySB>4yYG-{-4#LLtU z$U4uBCCn&a4}Je!a>Qy<+W>1HxAl6+7o18@WRTpe4EQQbZu&*rX7+QsS^bBhF~znc zdShn<3Wy2-_wO8c;eOf1>3|ulA|vG!*O#`5KYcAdaR<{gHDIA-k9Rcks)BD$kO+m4 z)j?d5(6Bqa$FN{hR%v9`2TcZSw;ff1ht`~%FQ&UYOKErTf#KNMvHUia&YbC zc`cCXg9XC#`mA>*uDtx<12W~qszV8=9;u0oW=q=TDn-2uj3m6I(xj*5HWl|}n?!RI zs6`%A1v7*Ceh&W{e2S(G&x+|tIK-;r%RvRwe1RT?JA%<9f3(ggF=!H)_hWd|`rrs+ z4lW4mL2!&xiMo!lm1&oul1`K6n&3})rvjB5RcHQMtQ4(0{q3Po7_p(Q+wypPaLRJB z{Jj%*Asab6uL-`Pu`Q{Eu+7u?*qzlSpcS-!KN>{A6^VN)xL0|gelGUccdCHDkbjIH zCX_Q#bfANbw}i}u9}N&)CmqSdncbd+OgvgKo0}+yB8NXy57OgK%Vx~FCF9~Stl5z> zzVCn@KA_ByOJmxgUtn+R3BQ_VYrFQ`JLSS($c6=@ZphiG z+8G|x1QsF%QS(~6==N+j8};9QuI%h^eT=!C zKZq28gAXJTQ7IOWmdj43SuLg1ZVqOwHRmB%w*>ht1DDo-54B6aW^2iIbHx<8snStc zA>u445U?f?WY8hww^UsOFYZ0hOCQca-!0@VlCOQpV;}i!M+%$b13xID$=DS}*^$*=?#+L0_L?kMI;U;dc3lpicIvEVxFp~Jxil+pCwiHW zh;oFg6b=ol1(+WcdzM>!m0u2Q9#>A8nXieqmdKp@OKe zlpQ0x5)WKYxD?=1RVZ}d9@YfttuTrY4)rU9_#Jy%l{otziD9f*NfjxilTdHCiEv9Fvz*4&^sWNt3oi)pGh@Xr0NaCK$f#joW|YLBU!NQW$5s-T<275Dn(5yWdROE z6}iLuwj`x6kUmr)sXJUc6w1Mg$rRBntei4fMcUs)DPS1u0CCZnp^3Pw&GHAZmGu%V z+47MP=(rsWbkQ<ozU4NGzWjxz>*U@?e5v zws;yBH3!$+@f_+r-SLQ5|vP|rvLNbXsh*w(wpN@2~=-H(&Q!*RR>e4VI z^{m>(ilMA9VdG@DoU6NJqO!xcud&&iGP$o_&3a1z&EZXnQ zBQmY&s|p!1VWr%g4kj%}slDkp0y1V{+Au2Eq@y`)J@Vh2@cRnCyPy~|%KVJ@pk~>$ zT^9D6L3yLLt=7|w3R zTLUy8X~GuWV@=|XN`hoDgh}!RJuFCYp}Y7aKQev1Gu+*;m)CbzQ(CIXH=!I1u0vIr z+q|KXuinwTYlw{kA#0_OVN3%dTl@aK4A%(h|0okBSKzGs2LK1m-7#R4OEbA&m0Kl7EH$tCrd`T|o+bn(f#Jqh` zF}Atg?cr3yzu+m|nRGF+HsPx#%fx@-rjn^8OXcT~$2yKCueCTVKtTI}5+SlxGG&I$ z=61-18VkD0e~{sjyUeBF3ZOO=qe>DOxqUK=CbSXb?$&K`MiEIJcTE+pLBh4i7eT{g zu}0CXzblN6Oz5IDg*?YIe_q6J{-5)Z#%-u9=RBWd_ zvEp~E@0rNLu0~L?JdYIquZy_^RoIecHIcK#DP*Q5BqPMwyn}zb1e68UT5mLxM`U?* z?Z>}2>!PGWMTt_f=p-Zlfmp^#RT00o-DXyiZ3eTI$N}ifDl=Pb@)7`-@Rmo*JiU$> z3Mu@4cTmH*gBP#V+`XqahP_ub`-cQ^5i<>QPG40DF)N~&$m%U0B2AuI z>G%+NnLJ?N!$3)6i4NCscrHOOL(9?<1zeJCd!4g)rqZMpqHntXu2ui~Gw10eRRx~3 z4HV<3bv_G1I7NB<{lzZ;x1no`Bp$OA9SaHd&<{@H zJHh7z--FRHwCcq@j7YE=g6ScFqY(GNjZeyb`J_sXSS}3)?BFniF)kaciW#_mI>|If zZ4*L2P?Sst?@JkkKH`8@*%WagK0+6ThyzB}>|>^(R;e1(f_2-Rd`k5``Y22Oy2vry zpF{7ZGosf=@E|M49uswHIl|gB6@J_|u{6Y1d(RUOdDeJ;?|rp_1tr0x{O(~=3#tgo zU<|k~j~9C<75Sw<*asGeI7_Lb1|nNpI9OXHN-0VPv5UDy+$zGk6<4$j%h*{ZI}(*( z_aDU8pND$iz28VWPvtJXAPv2*XbN6#N(lIXeXp0m6u?^>00u%oB^41b6n(Ss2IsO~ zob~`athMtJHsdXMIn*#s`_EGF^f{z!be%IqXY8a0hnKXCa598o@R17FC zidd-9+7xF7KQ6ORg|;85b6SS_hqt2%CfcawMfw=4YuCO z`D(3nrcN-aPsCYTPI*O}GIO&BSlwlZ8LDh;r>2>2u0jA|vmEmDF_BOM+@iD+Oa)T# zDBJeQg}Yi*_mUyRKFhvL2;t~IX)O%z1ONvijz|9B_AH^-HPciVypf0)zc>6*s}53f z*qqIMiH|!z%dr*S-m4igFOez0>yk6F!p(x?I%v5dzvLopiixY;{t+H<4@gi?Z}@S_%FWE=TF8I;BHHs{&>^a}1sQUV+ydtMM*He21kZgbBF1$;8T#e8~%8U{QX$LDHU zv>T~TW%9c_#1Z#ea&b8l?*X0%BRVWUxvLa1TEa)A04FuaYkkBnY^f@5A%IV6zssNs zAef3$ttWX+K%GatK*H&kPH)`uxLwcy*RjK`;4La#zQRI>(|VRlMnqpFDY!# z{9ZdG1l_g`zHzPjJ&b9?I60K{$2ahYQ{mC`h)04bK96JPcy7{D%~h$8vqtClU|3YrL8Ib9<3iWS`7Lro{s{+!SC4=N4Us1 z1P+@V$ih69uIray|1Pbc6VN*uw~R+UqYTjOKK452R)A_;U5ZBPy5E^jF9HFNS)+Kg z+_>2Xvu?k;#|I$Y1{!;j+a=@ijl@^y{2#iOER)1Pf}n1uo$X?OJ7>?`&oHa^dx zv~`an9CG)F1J2hsT#X3yWgXT92J~M?v~0cnt{ZN>M1~T!cn78D{`Q;7ZFpJ*565xJ zwV;y2M!Y64B{rdKxxRXAknF`Is-rDdj1L3nIc%mZNXKr{s~1k%RLCc1R(a zm}+i5176?*+<3kuoxwismemhaC|Usngfu8+FmwnDxRu3?$H4E;gSpv;hlZbRjyIe8 zxBTud@qlN;k7OxOEyT_`f$!fDQGrkx!q0S z5vpu{J7u~jDOw3|=$y~nCOL}4`Um|A@ZWk2cE`)y( z2|~5@Dke6-KrF*D^xL8Bc^P65U3i`aUYda-2LW$)o>tBNR23u7IgXnk@cS@1`?}z> zY*s?oBj*4OX*?!t2Z7LQ50IAc`)%(t?6>7?{*B+at6vgQNS?DEH^R27ug4t)q>8Zs z7ZDERwT@Sn5sFD|ZsFndeg}2kQFTIh$lC!PsFi1aPyU_@+J;9dX!*jb2&yUjZ*i{= zw+$fTqCcpa*{dTFfIF&>gQ^7Qn*rXmT~@&3yQlI*W?;>FW2o%9HqA=<|ci)#
  • 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 T655ph=X$5122!n4wvPBe3)j3P diff --git a/docs/3.3.x/docs/images/apps/mcdonalds.png b/docs/3.3.x/docs/images/apps/mcdonalds.png deleted file mode 100644 index 28a1bbf0bc13f1d3728ad42e53a04eb669f14517..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57481 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

    kEHs_LGe?wKJuGaPCdM8l?nCCj!TI01$Q7!ES* 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 diff --git a/docs/3.3.x/docs/images/apps/nextdays.png b/docs/3.3.x/docs/images/apps/nextdays.png deleted file mode 100644 index 9ca96fe961a84f3df23513aa4ceeef52bddbf91c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35067 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

    w5Dis*m_y7@7D1e4 z9KyYI4f%OwlzTAnb!V%w9KSzGo_o-qx+T}|jD5Ifli>QkW^4Dl0qy#E)^i;gdP#au zr9x#A#Io9I&z!xvS$TH47mkmAF#UBdPbm|v{2;slZ$DJmPmS?1yxcuDGRQ(}O$K=1 zFn#VfHDa?`9liRT@+C{IRnxxx?5s8Rh~lDICyci{z1SY120Tc4v~$^^!r%f8jxW19 z-!W`RQzz>^r}e(!0X7(Pb?K+iq5AfybxkX}f4^kWitELX$1DEcEnRK_ph}nDH>*zm zy3V{RsVR+=)o!jcG2+*20u33eu<^y~xtRhKSCPtAvS`<=_T}huGX{g3*M2{`*=99p ziLoS6f4d24rO6V*^XZ~5A;7S1u*90%{i(w@k(ax90!}Ao?BL|`vVe5C|Fs)o<1=Hq z*7Vq=V1_&ljo$rq-0i93i}&NK89GXC(^RniXeiBYq{#U9Smxv!xmqg?NPZZDZFt9y`?L~^|PZTaeRVGu4$>! z*~xLh8OqGkTu?%Ax&5K@^>KM7$B~oKE=0ZapNoslb^sxS4bxDC-UpY9UPH33=VPt2 z5r0ae{#CbkC7>lHTD!U4=#7o5gX{F)zoHsnFm6{J<$b^s0bLQW)vWQ(qAB9ooxZI8 zHE%f*;8ul9KplfaG~DLj@NarC&|=6w${-C|QJeA1WQiC7JB0BHFR$)Ziqf=cNr(U= zX~>2fSWgU4gLxZqWnCT4kPOmpRcD}FM2g}#|Y z2!kk!^pH_ZOiZGfS!G;QDIGV)`bUORxeQbKV1=4JswDh82)g6ZIc0#v?Dlr7b$XIi zv6$P`D->mFWKe!dG3olV0;r;P6^2>XBJL!I045|waUG527M&6RuVRrY#GJU12%1Pn z8Hrk=IN^?^1))EM)m#lzi~=FXdJ;}t%U4cHvRFk(B2lE@=A7h?jE3OPSY?+swf2O$ z>0-s+ikvXb-`O&X;XAN|a^uNniST-~HUwYP&lgwN&27EIQNNMA`P+oxa0#67&ueB}*bx zi*h9ssAUNGpp1{!+D_AniHlRBmr^EsTP^3ev|yA&bhA&!Cz?u-&sUyZ5MN;8^16Ty zG_Ew76Mu(WdHWf^+O!@e$nXLrW|p^wEiG}5r?LuE$}ckF=SUJMoer3@>G#Oy^NhZk zsF>y0UbwLQvhhdB_dE5ioT6ygT~JlXI6Q5FM3_YT>nK&J(n7*nEFuF@Q07^ny>c0% zG?qL3ovkT<^WW2?SfZ+d8KRXNCve0tA_UIBL90wGU2xC%r0;{3)>&mPJ-RG8H`<@f zpsKw4O{M%aWHG=cVj=hjhc_%<&k&*F{*`Cr$({M6!Mc7Vlp+yW**cv+S50r}*u21z zXO=3w?8XvY$mtlAGmv#zC5i)NKl98WL5Z&rTC3I0x?ksSR6rE1WsCOqWkyc6;TuQd z#;5za#T;QGO#Dm%P~yUUH+uo?vXj$^{JpgJSs1bsDG4kl9!|-AhSj?2-2MfU!hwNj zt@(c?_DXcg4)G19kP1?XW5x=>u<=`?Co@=(;$$c5Gr*m;hUXk{szo7RTk7~L!a4Jj zl9F&#$o@EZ#9ZNuH0A+Q$#z<&7E?^j-zCLe*+oWo_YLCiL-ZRm-3nsR5U{uNs4_9p zKS0p~Swv_}1TD$e65+FP`kUv^*BXNT{ROoeRx>UX;M-Jwn#0Qd%o=|BTe;nttb*%s zJAss=ZZeP}8-U#LF3uA%6d0OJI%zUJOc#uT!3$l}3Uxvo$L_mu#%f zgc;J;);FJ2Qd0KHxGEF!zJO-KCT?Jnq0|<&Pd0iSDT6Vtks>Jm#MOT)88Jur2&?k< z$44f+{o?@)D8h?SyjOk{tdJaHmSI05B;1f?oFwxv!QYe&Rg0uDx39`+K z&(@|Oo{$n9IwOhE=VuZdCPv33lyBV$WhldnEmED5kT&(Q`e(>gwuvE=e05VW1+<+` zs8q3#rzZvsP~XfAe4u`$Xf8=g6lL@te!l!q4E7Ii?=D=QBg%Sf-Les&J*tWnsY4Z> z@jTuBKB`-{yr(Hf3?&wadw@mRNQp8>btEBp@?UvRZJZqSauW|&gY6u=DERC`9fT7z z+ft1zBDJP0LLp2Nl%F~3#Z_IX`9$Br<~QW5t!Yu9!=jC&FFjO3p(6uf3H2Qu5*U;k zo0|+J`<@3$6mjj}pBXodQ)n|^M~t;4Nol4K5R6voPMu%}kW{2ZA*bMHJGxVgER`t^ z%&$&{8Nd~Fn3>DbB9o|8=hA7khLWTqN+QvhYR>xN6slkEAFE3lSmnx5W|p=h6e7w` zDdFe)oM~W(h{8nzEEY|@uRO+r%^~G-h_WXQw8)yxl^%GD(4fr?rNZMNwL~#XM87S# zTxIVsVHCPiH!DjKpJNReLO5)6Lx6j>(4Q6WWAgAnj3OaZ`Z?jp3?|a8KStRB>&N zD$^2)zJ7*-n1r4AaOV^Y&hR-m9H}qdb~^X32UAttz&Hf+g_kre&8p+*zC}NDB6zy_ z)uR_-%gIRAvCBx=IY(B5)nX;kw93J(tlLx*P}gGFS4TGbpXop^mTMi@`(TDYb8x(m>HJWH7W`T<-rQ|PyI}s#2S?sC%W}F)Sc5W zDrj@>3RcUQ4^G>yCz_i{PEY}prJNzi<2SNv&x0n?bu?ZguxRfm%g{ikp)^1OL9fLf zZK{$4KhRe(V0DnWL!&CshF`@KY)+S#YH4Y zC<+op2{e?<=k>?ahL#tAxHd--L!}NW-e&xZ1eNiYTQ-*wmlQx1LkUeJOFFZmdV@Sh zzO<9JGqe*NAs*}2lr(}3uU~-TXu*(iD9H0IOAkgEoWc~UWUi{>DU;^-0(#wikh!sc zEW$}v=MC48yD3IkWNKt;F!jeNT{owagbU|NOviI9)~yTzWLU-nwy|e2J~B}oO*0DC z$kZUEt6yRaha9rp;VI28v1Dmj)dul}&tAd5b@U3HNzIM_LlLKw!leHNd?d?gMWSN? z(o-eZTfhCCvY!z_O${*7j6?y7K77mQH+K?yC1OyqewluV>9QEhej; zM=_s^)GZ!v2Ky0=?sxaC=SM*405Z?@&Hyex$E5c5?XQSLqef>JVO)j3ZWULtpyjb9S6-e2KxxW9r?{*h+@Q!Wzl0y$dA#XROv5 zgJ<&_FkKS7-yWIRoI+x~4v0Hn@UHfjaDFlj`; z%@f%Al6;cdh1OsDc#L^+qj;d+6Y%@@u&TvsRu$I9`pC$CU%D4V_1Z3n29u2)s~Xjvw^bIspAW?|LNT{3df4Yp4(^xr{k;w_N#TyTY&96dKwKJmW5^6qC5|KP!y}sKNalZ;zLI z6##ea%#1HoEvByi6tFN=z>#MH;TQGuRL8jzkdus>1k&sWmIXvt0^%jf^lG$P& z>nct$Alb?3+3~^%xGH}h@3I`gmcH5K2ebe0q(6Dz$bkkUJhwrU0(ErB8@ByS>x7F; z51&mhV7n4gXN1w;oLYrIZK2D}$0tUWDEv2UHk@)JNZQo%jY!@?EF>gt3`2qhrK!=- zz|TMnt)x`KM4KUqEP0fPi$?^FI$@L~TqUFQ_uCJ7gslDV0qbgnkX-ZL1`~w`jkh@p zJGnTc0+B~W0{&hFMliyIp;Jc;fnxsp=<1T7Ov}mWbx0^mfDw}>jQ>lj65d2+E`_U{ zP@fslb=X@>cIZ$eNzc`AC)E~Zpvf`bn!$3j2aG@+c2IBWbnna5kk*hxoJT)oRO`p7 zl|az<`sH z!#FuTO_v<2p4C#MQ)i%sTekm0h7C;!lYFF;FNI01Gp_H==3fU1sYoe`1kNm2IV4j( zd6&4pu1>*3_v=>UJL$i~mzV{UrYp}<^C!Rzs%}pwKSBw6neAkhB!zbS6;2Q{L_~4H zj6W>o0^r>#Ge5`>wP<4jMlFRI`*on0<8=hB%ZpPhB2%X$A|=^JogjN;XB8=tiS%~9 z>gtF8O1JHCNmFw+dNZStv)yfu(_($8b-_p+WAy!7I9&F?<>myXz}8vf=Zd-tQEQY+ zYHF?m7$fN_VkizQ0WVB-$wa9V$QFpA6ExdK1oEH%HLoI1MKl;7%IkO1;#`1gTOF_DunM44AwwmE*)M98l@RRi#Q0p zN|Fo}Tu^}NrN7FdkYO)F*OStnFg-}RTt@&lELp6;UYS+`T^}2T{^xfxqr3okDkab; zHf(MKKsjYeX6TnCu?R`UPMRx9urZQZMpoLGY3E3s;D77&jalkc|y}-20VEA4y zO|`G%wy3g|f|V2ogZ5Ec{s>et`_%Nt$@xusk3QeY>gAPHpDKOP^sCu?!iZv6Eg@XU zMpu`;7s8UtaI#<)iQ962$#&_Terd!YGE{6)nB?#v314CrO%UMxs|NffSOKB1^a2 zKR9?G6QUiAmOv3B@m>6gp8OX|%7An}NDrdeDCn1jupu|hH`Oaa1J99fCk1{hk98AG zj!OXA@39y+aF)QjliiZ)5G0N&P^peK6+sK-azM^EEBa5bIQ<4PAxppyeA}zl@^Fn> znFl%w3`P}1vO{_j@l98phB*y;xQQlaiU71MQc&8`VkwXXK2S$G237cY#$JXkS;zvS zB=8q(jg}}B-?xcNwMh^q7HE|hC_>YY962OKn)GvsSp@$C8%u_*wnlmW0SyL})K7;j zF;SpR{qxT{r`jMm{fZ;z1`Ho5twdA%;13JXF+WMjQa4e_Om`jOK1xZ#vJpg3cD*vm zLW23oA|E5A4P}!B-e{DBTI(!>g*?LIP>NIDz4dx^=$_QEW_c)IX-QA5@B0MpWip}Nu69(SKkaUp^u24(&i?I-v58z86Gvt1wqo6W{ZH2anWTc+;gtGWu+!+h>%QXmu}iYT&>6gcatw7fi` z>xMnl_xmQ9O)$;?xIm7nIT5m`{Z_&@cSfQNWMTRx{$eyJ#NP*{{2%7~TD)WA+fuBis{|q!`;wG3VKc1Q{P$rhjpz1S>WHB0 zb_~&LES0h9rl#aoRaH^Z(Yvj5g#&>H(k37%;ox0e)AZA$aD5TTAtsvNbAccuC&$Fd z*tg1Dij#4@+2K0Byey6xl6t@xx+Nk5L^42AC%C*%_$)cx4G z&#~dQAMNB!+q3-@5yA6a%;L6>vpupq5X$Lz1pnRtd+EG-cv7OlLQ^7zg~a+1fq3o=;hn`Lk`i+<}=#TLHUR^uXIO3-7;D9smB zB1m68#20-i*d!v!#uzGf>apX3!p$(E+wEv#m#mLB|dcO&cC6VPB`2S zjDSH|GCR~%atqxS8@#ins>~M5s{aY&5FGCmR$NG~wZgP)uGz5ztua)z}?O%R->(@83+-tKzx|3@M1?TDmVOsO4z`Dpik6I>owm>yXmGG!5c7#xMSplu00&y@hQMICga(>g+^yE`4l?bn zKyAVaDI2l3&sFYUNu8okQajdgl8^e^(`1aQH1&#q*P zMHXDBRB{|=*%VDeNYZ8&Q&|W@K)sp^@)vdH14!1d=+$G~7dgdcvMuu)uLYJ|n|VxD zN3ALZT0^z!VcQPrOd7vji=<~rgKRoYSSnGeR6&JkrKnatT3TDE231OB4=HPA15%ne zi3ElvQQVLkz@CFP7&HS#L2+VG?wH0&WM4x+fS_y<<$iTn=Jv}{F zBt5A+cC961U24?7p>5k3hOsI~rVC+3cMQw2o|lQkT$6#T$^O=|tSkP=b=xZ;#Eh#i zn5I#iOwd>y)-o20=R5cJayWM_6;_lmu2kuDH9%`ke}DgyMIjVIFgh~G@aQC|bc!IT z`GLEpNw%Yd^_^W@I+f$HT?Sy969eZR2^)^QoSs^^8(Q0mP^ z-NJS$eM}tNM(c=@ACOHXh>HcnFsPYJh_%UvgkeY!1oMcXQmHhez_0n;ZZ&uetu^_4 zfn+j4xm>}vEet~vhVjfmYP3={zGB8aeO{CcYW6hs6{t>VQp%d4qGe(lCWe$VHa1|} z7Eu%dH3C&ylW<*xl(^4BvNSjH#=4brbHEuFXE}N!U$W!qHOv}Xg zeIhR)k6o3Bw4jmrevJrKD6W;Q1k`RI+jW@WTKp3{)Ir+ZJII zBBg<|hNM2{84Vr0wYFX7`S3R(Qm)8jQ8pn(66jlF1~AL}FFjb~#v4!YKGt z4EtvgGnBDV(|sPn=-Gc}pPNx{Es*nStr1epGZ~t5v-bYn`+9ywmpzXbzB}i)Mw6k1 zjQzs>Fcv~s|9{Wher>O=vx-J!10uEVmdhWqkb zXye7OvZ4-Ao7^gj8908H*7h8uLlZczjqO-OK?qXT7-(w#29{-FS{7p?6C{%^Q3R=! zjpzA98e%`ha%~*f!YfsXB8}x(NI7GPY8a$aNybLTNv2#fxeQ*pN*rrqt#KTKSQzy5 zbkxq1q+XJLWoA# zo4IXWYy4&%D<5!;+61#LlhChu?D>@{pg}82#R^g>4A()p7L`hsOiPYr(#7{GfI}38 zcoh#NCBzDX5X(03${wa=QA-lWzwL&kaDXG)=!#+dQl&}h;+$A-+dE0#)WtqFo)%`&G; z1*KHeh!AS7sDbBk>i8L|QG_iG5Q?x`GcT`HV}t?8Yyv|=wOk>U%VHUV>5`8nG_ISZ zP|V}H4nZ{_)|!s4b|%IrkV0TPXjmC0p)^A*oG$blk#BuH1u9YH= z;u-HRhd7KtgD?z)R&+^;nDOI=p4z)nj0O@3m+syUqAmT4i0Fdab<)N)Iw(n(6i3Q-WDMa{)B4r5S?FpRNXi*zPM zxl{oGaimEkY|7;dLP}7AWZESP0#u~YQec>pa@8Z5OwiHMx~wU>TsMi1#uynMBAH52 z4Sc3zMeq8ahJ?E@AkV z?}9_5b>kRVt7GYz@2g=FT`m?ocFxsz{M<9&q3?0#*cqx`NQ^+}kT{0+&UW$>)8x9_ zm>QiV3TsE9Tze~9ui0>ZS&OWg=UtomE#}-8LR^$*URcHjS7sqFm+52vJjAYD%S68_ z%(r1#boF%;D~(~9=r|^h6^`qWYs(-EiQ`z9Gj=tWV=t=EUVB)&4?Wk25SGueYBf>c zz1L#mpcN$y*GiC7DTF0RCuYnh>fd^fwFer+oIEnM`LOmUg+`Om$%YyAm7pFbUrI@( zTqcZS+=N>bHP56szS^*u^HLngYwj2Y%gAGBtvPt`AcKR0vr#{^B2rg>;O2|=TY({r zMt+MIT+R%SA%vhfHO<7tB$3caG?`orogE!(eg~N=u7#RwYu#6+j=F;Hg~kJL9EVrF z@|9N;#=SP77so2(7XioYyD$hDQ08qURi{~dCD&hO2w!-X54G>__474 z^TQj}oVXS)81-jf$arb3$>nnF+qduPAq=45qg)?|wdka@oc+F1!k7!WjCzul!eWtA z>iv8ncX_!)u!+l^GY`x#i3k z6VJqPukQ?66U{6t%Q+cV1NCSk$z*a(Et;!F7+Py$rHH~1r8TBu)IPqH5UECRF)0nS zR)k?l9M6ba4TCU@kU|i}GufJ?L~Df~M3|<95Sk!}5JJv`!xzMH*of*;oA@$7H@lPwxg?5pewU z5WZI>kxCPXK3W){B4RDrxqBB=BZEv#m#9`f(&;24!^4D8yc(Zw+2+Dp!>SO5kODW6 zKv0XBR7ZW1oj2J;%`KKWlQQ96TJw9pqnLYl#Go{(%sd{ z-+t^PJbUcai)!asYgnBfLn(@-GFr`eqRk|8QCgEoI0SwGLSS39l^jtEbyHj2Ydc9Y zm8vC{S#r#u`19^8qWHTU!Vp3*F+R*>Ip$@z+=SMWVzJ2SQzvkf8A7G;y(;V0_YwwG zCMTy5I_C7rbBs=vxc-hBnh{+dJ8FM%|E2XFeH{~H3qeDq;iaT%)7h_26wiCy+)0oXMES%ex`q{nC%+I}kxx3tzVqtpf z*=($9A1fZzc`d@U9QN$piwdipJ~KGuN$3;Dnnc3I^J=*}q+#GVHi7S>wZNK*l$cB= z@jVYUlVwQ**=&wXI>GqFBw-LX@|g#|4^raTHc|+JD59&Yo5J)oUEN)jig_lc@?u}6^Pdtd+%!4DH?NPr7K)(5(upoxwa1a*RP|sql1^+ zbPLsL6~mN_jZV|m(aMPvN2o>yyLN1?1y~S@QY9oTO>uU-!2WA@Q<$0p(_-u9&1kKN zg8(n6P%KqRCKCi+K(@7&Cx83{l-`FD*0v0jlhd3y zdKhgb>1=PMzrPPdN`!`3De|QvrXh*L7=fUzy$!7uDhj#t>;KBY;K;JC@N0DkF@Xu7 zeI+Vei*AfsLt%Q7vgebilsS54kX%bEwq=mbq_IttVxa(Tj^gwrL0rrD>R1*}A3025 zBoR`QNTeuNE1WwwSQGVDYjJIbX;CQ^7#td9%hs(#kwVLme7?YuqescMwPO)8Ha^1f z6UUj(m)LgAHbfk7>dYx7r}9)P6{@8PhDN5?ym=#q=>m>xQ?B^5w`Dnge1QJ`KElxF z?BH1{RgZPuo!E{`sZ>N+n$}!~LZL`8KV8c*l}ORv*}>T85QV7%gF{1X*tiMXGG=%c lwP*&ar62#bwNTda{{zOpNBnz{3a0=7002ovPDHLkV1l1B;i~`u diff --git a/docs/3.3.x/docs/images/apps/nuorder.png b/docs/3.3.x/docs/images/apps/nuorder.png deleted file mode 100644 index da4cf597aae0b92aff5c13b2638ec7edc997705d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38163 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 Ef(FYGSO5S3 diff --git a/docs/3.3.x/docs/images/apps/scottyapp.png b/docs/3.3.x/docs/images/apps/scottyapp.png deleted file mode 100644 index d5142f34601224e550deb71b93313497f5720cf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118416 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 Dx(}}{ diff --git a/docs/3.3.x/docs/images/apps/seelio.png b/docs/3.3.x/docs/images/apps/seelio.png deleted file mode 100644 index e3e7a8e65abae0ad30c3db0a00782d8b1d54ce9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24005 zcmV*3Kz6^0P)=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81MQ%w%K~#9!?Y(!DWXE~l{j0k7cFvR2 z<_PQpSO|e&0E3u=DN>?DS+Wu(QIdU*W!bV7EGOBrK3leB(^jxerOzUzj}{40rbv?_ z!Av3%VHd#WG&yxnH&uOq-0q&9+1Z_*T>zWrIcLsv-@dnQs;AyqZ;3}9c|-#UA#hz6 z&+{-01Ix15!WM2}2tcEII9MxIE*Ga~0nyoi3tPBZVM-}4`=gMOR4PTYUPlW_BxF)5SBNE& zpnZl$cktGS4)NJ9e;rdf%q%RENvEll%ecPJwa`Orjn*0|W#_Yy@``P09mqK$#419s zg;EM3E+z1lj@iQP1=DSMSP}D*ACyuYzUKiRyzemQ&z@&!WR&gO#(Dg)Z!xxG4l+{%Hkq5BBNR@M%cfXfTBP2v zJDqneQ4*;%rcjhCHBzY*rD74*5WuuT4D|O?tCT2~%Fu30NV2&;%Edgs+9Jp+39VG; zJwWhLcj@xo8p~!Ox*H7|S^fPoFsp?Iv2=uR>{4S}E7-MjH|cagF;nra#~x?@;Uh$p z&C}03hiO{)o=2nUbLXBtWU?7P`iFnahky3(GT8SwT$sxvH`&3o)?^1pdEG+~P;1uM zvv&`XXq@rU5hf?6@O*_~8Z_&5PM5)(O8Q2zV~}@>?-HaU!YcNU`1nuO_N-%pJHK|7hgEaV#Vbed+PLC6ZzXjJihg%A?7!i>Z?ux~HT zN|C3Ri|9rbvs48EDwRf~Fe=q6UX`hQO}*GeN^yzg5WvY3rx+U>BNVY19_V9!YMQ$a z9VDHZr`FKKVlmRGB))4?s=IvGy+@dtJWsJ)>lo!%1H&+gr*iDtv5kmSEEUQey8CWi z+hgkDdB(;jxN!C)x^3(r4~@2J*I3ChJhOT`-Z z-g_UFQi*srhh48?no)M|+QIznBp0Vkco$B!Lc^^QiKb~*N<@<> z?1oK$Uxw$8JA z;`EubjPKZmR1V99GO1)7&sS*QrQY-y8y#k5>LSa95?8Wct_(r{z#x&Zg|9TBkcsDd zXdOsEX@;2?9ps6}AIJ4o=a_-PLA3G-g+hUZP#PgLiwldWmI$>%VbZAtwOW&0E{*Ri zw(Z_WM7X?o;tY{Ug#7X%wR+=v_nTWDT5D37K1PQJ$)vNCt9c^P6v=pua5zMxUMHIy zq*|EcnHNvf-`~%U?c2HY&I6oy@p(!$2j8}XeH(QO#R|hi11P2NeTQ>r&Tt`-!A~a8 zi6o7^dl8K?)=~j$ewO(06I{;y+93u&BoQK>j&u~Wj?vpPW&xy>C>3?X`(joOxVH}R$)~aGK@>Ny~HpJKmDVt zHV7#QMJ&W-%>xaS=#CxGX%Dd_Ft%{h!TgYaaMcE(;I4;uFtR6y-Wuw+aGS!sI}d)x zvlHla_ml+p^k-YdXd5YOhkYIVT}9Ak3tPC+Va5le6lQB3^+#zaE;ev|00mwdoJDZ+ z;5PsbG7M%0LIYrBK!#cb*&@jnZVi};T$I9Wl@*B~XjW>d(ldzKGf+PRZUK}7ti%iu z7MLlBOdwMCK;jUX>8^dYu!Wl!reUqIvXzZjdz+ zW@Wh%7}#C~2qKKhbQ2*IT1yD^Lu?O3wj-!`k`OJ`OGv0Z zgI*d&483<{`xdrvlfcwoiMB1EwIG>lkQ>jz==%`y1JIfS9;i;;5McEq`ri)medyUg zhsGIJNT8wcRY=?ciG%AL|H_~($2Q8VY29V;r+b_8zJ*&CCb}y_RV&8#MTqTv7sPg7 zYDZjx)^D-hh_N3FP+LT~?a=A1T0<-)*!9|n5b@nX24k<# z3L;~Oq3;RE;n(PRtZK)hF$wYAFRRp$1X7`?6f+Hn7ix8mR;rw=H<@YLlv-r)wMOZc zIw);vA^=MY;?khcGMR{mxicQ)a5B!mc$A!FVFv8i`jy*Iq!xcfTw*AX{@nW^9MYN)^7EFLA6|W6||+yYl?IlUjl*KbNXj zuF@2gN8WWgS#R*AgjXq*eazl7?P6hZpR$y%MyE*AJ=zR1O96IW?uiwMS5Og36;k2I9x zM6J&8TAfE0mN=Y<^X|bMug_-4TILo(Zc&(83lhl&_dQ%9F*tH<8MRtNWE`wMu%`hT z^fYG){CX>8W&U(_k+Y3vXZtIGwiNQT=80m3Z_do|x?F~z+p~l3%BDM>tu5UAFkk=nQw$81 z(P9`O46gar3M0tA?QTc=pgp*Tt|NuuWUbEcP0sRYzSL5guHS(?M6u&n)%SSHEQ1<*yS2cXO zptZ*LFD*YRh2T5I5`X`hV|;mG>4v%9Eo>euNlePQ)XlnCXdhjEsx{NE3$dLb!aXB%msqrr?L;s-ZncY9j%htu=?$;<-oHISlB1R(@5DM_0q zS<4`0nnaDDAhfMC70;*OxfETWn(yPcj=5awW81#C91J12P;c*$3~BSM1^8SR}MLV~@Bo_{1rVQ<&o(Hdg=A-b*Swgm90g=PL|dj6_O z(I&%yWpQUB#*tKlgYg)nkq~LqAS@+ji@d%DM=PqH&%EPuvew|~N|om-HKv<3UdzDl z#zw?|fE?#*b$;#G3I5xW!|YEbw#ac4LD*0KxW=!rVl8Wk?L~}y5F*=I$vIv3@RnUM zgP!|ys6M~C9T`JR{4^vF^+XIQ1m7x_`IVFBSaiKjC#x$BhJbzXC~xh{@^CKAj%b8P zD;ZF?>RzqAo3$CZu2Rg}4&N?S`0QeVXDd~jN_7ZQt<|t?yQgdNwdO5D1N` zf*AT&~xk?SCHI+&Q&+|6b-rw7^gJ0agd&}myNg$m1g4Xko!15Q?{Gf1VaeEoGM=u)0vfBpm~%GFJc{=U|{sxQm`xbH6dL!m8|>IR2w z2jIl;_rbusf?(V#dqA$JQOa4VFC`@FlEO?Q;(J>uARE7a0Tf)1Kbcve?0K6Yg=Rbw z;-Bx{&IgAF2uu008n^A1-#pOAM~)ogflUVR3?XQ=B_DJw1rm&D^WNZMGU?R zG4`QgDylGgn8CLW+Q&36g5EeLB81?J%LTquuJ&wKD6JWbg!$*YxADfl%uA{|Z3JIy z?nJX zw&#QS7tP5lx@p_)*%zwyo~4B)1Rok7;!W2%7s=O}L+K>{^p3p@ghM@-mQz~u$n-oj zO?#_$$_uva+dXpG3 z((3RLuyTm_{+6UjLh^n{-V5nhL-vi3eFLN(fY<>DjRwa%tBr60)P0}FOVyrUr~?2LBM(GY?cD^-5%JI8pUSi)Rq0#|!q z(e-`3&#d_@*R-{^osG7wcg>eO*OjiZ`}^9z&ULOiSGz4K1fQ6h??Eo5FFc(%GY zDg?~h4rl5;x-GTlO}Pvck?;*!KV1V!)8zeQ!<`~+8^P0>$Cryed*eFKjv(%HvRb3$ zdhAQYi5QZLji7$kg?h6?P5~@AE~l!sPK>DFdNh>kr1rPB`&zT?xTsb-{<&J6i(PFk zJ1!@yHHxm+>6q=dYptNH0OoCnGqpNS>l|&AJde7+vaRTPG+W>2ZHH6UI(1(mMetj} z^;R9*@D+L2rQ-S2eV?N1;c3m;TAit;jnYA9ww2;^wa%jBAbyiH^{pi2lO(SR^a-jrXtk(F=Q|F0DfgvTo zeqc9A)8LWW1wOy9#8lJfN5)6_p@|V5nO)$|rss%BiK{g~w{wEeFDw(5l3(7plRurB z<>_LD|8my>zOii2n3Nq4m_jfV4)Ke7caSg)gb@6%$ypX`hktQkH}kg5KRkAl zpWQjZxmttIE-Vp|5<>|7(ViWAZMnb~m-771T?ffnCjasD1s=$zIa;ppe5FRtvN)1X zvh2FNP_EKYiXWL6;oeM&e}C#c4d18gD}HkO7&~K8B8H^sc>K-cGEutC? z4!?7Ll2_-_d|+&dujPw8UMO|$?M(wY9xIeMUvKc$r6Q&b)SZt{&+$+8?%*SL9pGRx z&PUE&4}igbDwsmBBOaqaygHxho67}$<>+yK`l)C6wPPnZS}I@i za7`h2AeSZ7gE}REit901Z}e<8`C9YF{w#lMWRTxHd5$NFWds6C3f?x@$4Dg1XgE+e zCmT&7hUCF)nxtv+rv4lS*JDRCO58B`KXZ%341@3P&+*suOPsGacvF9lQ?)t|<p0Dm9iIhh@j*T)n}!@q z%XB26(wc*bIQOKJd~$YyFD>PH-^d_Kj>||S#NFv6Y0KhG{W+!@&0sdPT(NN+rI0|x zknD-ac^*jc{AsnUn{K7H|w#_4R3k-xUcE+RJmr3!v=O;OsOz@7O zem*`mOGHWzB;p)OCHVZpGAAlEj#q1Zc`45$vkMG{Eq-GA7-4Bpay_OSP2M`t$1m*J z&Yw-s(NK!*(I`jKDSmdx1m8O{$j(@_Goecg!TU#s_~c9w+GfkVXEftw< z+Wh6*0(;^ya+XQcSDdLe_{wsDCyQk&o`JA*NJ>z9qPWK=y@9kxHJT{W22j|FmgGx zJCUmtqUG6nO@EI2b7_v1DpWj=-#vYS$MOaK;QqVWmrU@{bCbMvXn#XWy)~-ujz`&>i1Wt&ED=NU z{i8$7G;MzAg_DG&GS*`P#`6U#ZH}&VZFP-A&cW>hl zE==?3xdjHpVSZuvc2Z{hU25*lBpHf?xi_6+AQU2NS^V_&asK;-DJ0MrviSMk+Zl~S zc*{T^zjgXNd*U(PG1$-1a+QP0I0q8(j#~Rfp~Rn5X7JE_aBP@YWi!k*9e(+RQ-q}C zy(0rW+?QipG{WPB62sw8Q0ustXYDlduc!xH3OHZ4`HAOGvglknhM|D5aEOl{+Q;}N z(k@oc73i^T+d&YFrjJa|@mRh{SV}%HG0Lm^vi!+~DL!^_nm>K;2sO{=r=EI_zq4(e zHxKpm{oi_uUpladca03&1eSHw+&nitHG?+aO2LLdZGJfDi^k+m!$ zQg%AwWTVM!)8@BMU*MnZ-^E?&BuWQG^Ga^uvFZz1goHp5sEq~JC1IK^J4z9j5>IKu zhC~8BuxvY6Qj)dIPM=w_9ZV_6TER4lhOZC;3XtDkE0aFN@c#iTwvL811X_3|LNp8J~y|>n}-JI3y1i%W5+pOsd8s3Ny+t? zY1mA}qU=w^d9G9@W*Fo`7Ec#T_yl%D!&jWDRM{4bt|A4k-?N*T!dmkJw_~r+K-@4G z35T&{K!ixw9CiUD3dyTr z4PRPV;-B5IkI`tDvg@*BJ3P9u%m*e$h#QjQl`3~-QyfaC`0Lqu3@P~G?c@CW6K61` zKlUWXeMd0vJA#NtFG~&$t<;5$)v&fo zi8Psra{)Sh?@ql>d*1v zUE7G8CS}*;%1> z$NR#g=$To}x4jvWNv}^1t%(|vP%p#~f?6vDpnn|~Xwh}?l)@5{Hx2eN6bZLFn&5?U zg~RD2KQJ-Mu6T@0%Rqep*a&|yHA`4Z`a%|;pIanlnf%7#1H5x&5MOI{#A9SEi+_9g zK*xahT1L0kilH{f3us?qz4u*+ zc!RvAD9>=Bqh7zG5*26U7e1< zUWdKXpxyR*E!uX^8N<1dby?}NdS}6MzCf*BXWRG~T5CMtLu-v~+r(orl=3kQ17G>j z>WJ-aS}RVSJx3;;rZ1amZPO^NFr*AVE5CCLLNGZ!16ngOG>BUVnQD!{`}9$U zBN0lj%U$Ud*^oudH2ATd6a3(|(ZHkA>LA^DQdbKp1oKUs#pcE_3<$g`!;vtOjccj+ zzR$(!X|&dC8y{nSafy7fh-I3TD-|;7G}T&-L@b8wxOl!tG7%?VD6xOfZhYToaXF7^ zn9MIOGSJsYzF1@+m!mJ2<=n+d3`3%IP*AQvm!np%BM{8YFHkI%$z?N?%4NdgU^zOa zGza(XVQOZUrfuVT9=`9BO{a;+V$>TAD%BdrQi;KVelAQ+)1S*ysa9J=FsRk*gu@~F zvROuk203-^9F}P!g~V4rdv@-?SBi5NCMi|Q4E6U@saBcxJYvx(i%ZK4^!Fi!pja*w zi$pOklR~jXDw!aYPGQ>)p6>;An%0CuA!g_1X*O;4?A)>LyIM^QA<(5V-Zvi$Bmf}N zX{`6X3%O@^hbY}6w}?eC?zU7 zr8QGCv-Ib()M|m3&-Z+m@_Dw8j|FOt6!^Z6Atl*#nsTK=)3&KptK>2nY$wub&vD(B zv;x<2nHU{mDW6|?CZ-uk3&3wG9M`2#ED?!>aoh;D;}8yqY1%eQDFz4nX*3#mzE3)t zqEf5k)~ZAz5gf;%-e^)RmM{!SJQkzYXrOGH(cvNLSI9cJgc$17Y4pNkM}0CLesw^K z%XOd@QRL3;m~VU-_b)#axOK}F)Ug)>Vyr!>6zqsbdJ3Wl;Ao{r$@58@tMjFVfT$_? z+}t8)c<<;C-#b3i@!!9;KiAPTdvy_C3tX*vEMLTF*&|ni2GXX*ws>^I>rzV5Y}(v= z_aPRSm+^cb*L6`kuo=)AtrYb}1H&+AG@C>t5pvlKsYHTMC`5H}iBvL4rCOy}DwEA- zh)1JHDG7xvT-T#qt%87By+JmU0j;rG@qkDqLZw>8^E?Ln`tUrDR5I|&`Cgz#S*D5S z`#6q^#-T5prBEsn35Q9<<0z$wMI%_2MZM9)bq#9u1|U{dcC<{BLa9VF5+N3iQmfZl zDinx>LPVp{F4Zqk$D)x42thItr(rj#HyT8Ma5&6zzCa=#!!k{T2+os;$4Mp=SeDgM z?Jntet0Lb@;eO%~{G&k)TDff;>+k#kA{Oh-1?xCCAN${^(`NvX6XS$_^amlbI;F!9 zf=Ba3{^9Yn>w28lcA&T+`OgP-^Quhh5>=<2-T{FW(60ai)`Jv+=|+POe(O7&u5LVC z*VmdOnKU1J)e$n*#sNX4R`hux1g`6X2vW}jBRS|OXU<o>N{0@U_J}7kZq0rGY!sNm4zK z0tk#^t#KWfO07o7GD)XWEpN|?w`I@H9eAEcBoe42p^$~=`|R94LB3FAWO#^>Wvv<| zwboeO9hQ~$AV{=~$6~}{QAUS{h=ju((rB#-heFUQnB9Gx5CY4xI@>JE3{;^|kh3JD zY;|@hl`9yA#57Homh+4b4|O_iyPY-+W99nWlA!&4baVx zoC2HiN;%F-@J>oZF1O;M?X`pSVyUBMEiUIV&A>4i^98E4I(v3*$Mrlew(Op2 z%f?A1lPu-)K|-iB=*wkTTFw&=g-9k7EG{h*i^cGLAKSL+%jIxgmqMwGZQEFug<(i0 zMn^kdueDgcb?uy@t4Z}1a^<+74EegdMGVP<>10oxNCMNg!>1RQZ#YswphkUhVUfr4 z#h&g*X&8xwxi_2MRAQv#y7c9;ND&yhGjj`En3_f@#Ztb2WtyERd9&HX_kGS!PEv0K zdbed+Ois_RxV+4T$tirLa6J#t^RP^lg~cTd!=T=1u(-TTBoZcHD3UK00X!YU;)%y% z#A7iU%_hZCnZf=63dLf_$hTYB#Pf@b7>1%NR(D&(rFsaCLznhG!3fNI;Lq*ESHId!-PVijsZM1 zGt0KIF+9&BlS+XI+_Sz4;u)1n70Wb;Mx!JXafA?5t2HWijlqF_ga|xPa8V03ug+x5oxfer9QmG{MdV_2_jpI1f8V!8kqc4}G zTCHMPR&Z>kLMoAYvw6icO!QSCT^WQfP2Bom2_T@en2a9xjd zDn+ecr(UmL@ma4BLu*7dg2-jj^9#WXJbwXf8$zMp-kjs0&Yq{GY(g>_{H^oum4@xn zF!!Yr{GY}Ah8?OsY5sps&GE1IZYObr)Ryu!{NcHaJY6jHTum`%7`%OCkdTx;6I^S} z@X#Qx>k?||+d@hP`}>hXGSC;evxN}!WwSW0%gE3mvZbbkLxFMI-%%k*h6V>nr&B@ut>|*QEdhi=A%qa@+p`M+^kp;nN(I|lvGJr3WYej@CUV`tz1nON z3We~!z;K=zAL|^`_A=^yJt z${@+`{Kde=PzpIQzHaopjj)uwy+6m7@+F#Us!FVT3L*GvzR1UCV|-|Q<9WL;Hw+>8 z%-lSGd|_&XP~{4ItvQ@d@=%YZcDi92MkghujaW2#iMvrsiPdFbTUM;|xt;kN4hNl? zF2hx}jO?}TMZ)3Be(yHe*D59kbPWAOJRStsTD7;@Ua{^9j)t-Ft=*QCvUBWu*Cs8C z9or^a4uIDEU1q8JSZhXMr0bq9hcz~a#@M$9k;?|1*>&;0{590n^h$ozx~)j`>^$z5 zz7iPkT0=C7arodBk5gK6Upm2&RJ`X-;sJj&JW^N^2>LAVis-qT61?g$vcM!Z>VaDTeuXL=1TcK z#_$NLzaO<2M8Ng@BJL;u5`V{bw<7!$~3Vl;W>u=K0Ozr#V;a zedz*dRcap`;GH8|(&A>oN=k?jP_Cj+ox^?Xan$tmN<89n9iaV!+cw3agP0G$re{*D zY6|$hi?jUx)a<5@Glk%dximjHKFq;Zg}IlilxMrD$Yj02N6%g4V;83>yWZxi6l%?A zG{XP5?{2;;o8FQZHvv{8hU22=7EueqOg%X|3WkA@61BLvB0*Zog-D68Oh_h?6XO_% zTQ)@x>eG6Vzz>cL@LaXV*9*P7KHGIyKfhGqXr;#chWdHWK#uW9xHHe;YPw;2g3_Yx z@VU7K{`mYP&zGy6-+D!R-uln&*};)@a=o^2V;-5Z^ckEc8 zDvgX_+;I>wJ`9NjBAEzWvMm?wwLl8N^VJ&v_{2FbY@&2!8}0RGw@1Rfxi7;Ta~bx; zqQp&!KwRR5>2|S-uBna<-{*X-!Iu}8`1H&?$4V7krLL;zn*#p!#3;XhXn)TRhAmuw z1jO(ax>!bZFJ#inwAA?$6iT>HJb_wRz`Fl_`5OoR)*|4vpyc^{yIAJ2VwsSXBu#^~X_7PyBCYyF zwo+7mpOWiS_B|F$Wo*aks8ZKLiX)jc|LV|wMx&A2QiT#iaI{?I8~M@=BPo^E?1)8p z%Rugmb7oehgsh8X9Qw0J+kw08LS)krkG?FVXhQ(+AMV4^ijQ2Fq1Gzudo}HJs+4O@ z-t|~^Jl0wr?fO(&DRht7u~$NS$>aa$t^*uMCT>eoK=522T`KU0le3pR(<_xkxSIVo zYNLI;(whB=IIqd3uUKQar-EyuKZmZ?gKWf1>Z%Rw&D@BA;Df^hm_qPhFV0Zhq$gfwl81+HozDAVZ|ViVEdvy`k5#w@QSTi5MP0dw!rsy#g=0{XoBecz}#) z^4k}tnQYqEJepq#eyhC9)n2av9_;JqUmx1X;q>h*DXs{mcsL$sS2T*P6yGYBIp=xA zMNotHj!1;EQe5;r2BqZPnP9ze}|8sbsJwo!O0)-k)VS9OAbxO!HLB zW%_c^!|$4RyxHrFNQ1WwkMh3pZDc}`tsvey&_KUwvOgB%1p;wBE$`YXX|y|(BIFQa+!y+Sr*G>2Et(m zOp|Yy%M3@O>&Vv#w=;ekws zqT_HRnPf*K!XM4duK|M)8H<@j`*J);w7( zaB6vVwILx_5gGHri_&%ed5a(+(Y~YDP z0S|chzyL#*MRF5`wqY|1$J_u=1a`;kb7>AIV|-z$$R`(;I9{#ewklIxZD;hAx+;1U@n|!+}^VSSi+ZsdyfH<8c-p zhb7l#tl2~f!GiDe)k+1UTIG1X&J*=IQYq4n2EI}>T56FiC4VwIOH4{0tyY z9GjnK#IpE&sYG>?PL-RA7;X4klQB)ce`J6+_GS1=zQ|{n3Orw}QStna`*kzj()azV zGQ0&)bzPn+EORiG?rbl)8aD#BIX7@y25+|tZUfJ*nOgdEt=9Q`rfV6x7dxp)lG&CG zINhD#+CpAy@~zIl&~8g9=GWSdt@1t_;ie=8tW2`$w@f}TJiy!fvpip|^VNKbC(BhX zG@I1@6))39M7dhSyNzcGdEPTRLAt$)kJ3~C*o{gNqw21HFu|y z!CER;z$?Dg*vo}>7Oc{mqU-UkVuL5kH71)4795);$D!h{-}!Z`pqP6NQyCc`aVzQm-((-e`o))r*Sn{x3M}Ema?_D=#BFb zdZ|`<%MfGLjRS^gt$_eUrNKZbNJC%G&8u3eAf4}8(-#ht3x%0&)Ty=$Twj4C5;#^W zvS>FM3I`=gn=N%JcbltI?WE3|3AZFMAXp!~ofe=8O4gW{A%^Gso!6$cW;hz{l7H%lqy2KDc zmaX5ah8UHSkdQRFG+VcAcq^@$h{gHoJ^MJ6&Z4#Ej&z1Q(iz_Ec}z9xJYOnsv{>X^ ztwPy#@w?o_u2MXeU*dHGgP0=7-Yt6?M?vWJHZ^WK+>*oyRH@+4*DEO-At_nw9?@EN zVi>y;Nj|)LANx}2j!UoY)ruMh`;sa4B~!d(WSrSXofpa_o+}nOQ!P_;g2f|WESH$B z*V&l}O5`_vsCtUN(B_t8-oo|8ElCUr=7AeRpb6}Zkd#CWiFP&JN|3J zfm@asQmh2mG!PPkm^4^hGSKrp?o4I)soi^-i1l9ht+O(dkW9qmY>UTv!7>KHEWvP3%d>9bM!;=B3y`uY{K>f9{qw2?c>?strR3;&OE{f_sx`etcrb zx}*pSqzQJ#Bok3d))Isyt2|xnL9LT=pa^oOUaFElH#=OdsrW(aPRaAoK*@118ag{P3`uk zSEaLj@6ZTo!(5jXNkgzBCP|v@q6y$AP0iPoJ*aw`rqUhbUTknJ6;EUPnuu|Gt5fYI zpFcIf#6%=a-f{WB=nzfc<8K!8+?P&La9toE$3#5NK-lEPVj06Q*^`KIv0A0>`8-pq zvOON7-!ciA28Bk0ujR|U6{vYWmJrl^g`+&`TJpBRT+b5wmL&$z8Q~!qLE?si6oS`f z`gq^aFmY+DJBnv5!H%dTYOJU}Qb5!YL=8b-2s{lm=xDDmC>S!8Ql%rLn>m*L|Vr*Y9(NQ$oF;ej-dFBd5I@Uy$O@r}i03cf~a zO~Z51Qn1i;*po;gwc;^yz8?mAZZGcra%!$le$lbC=EYIKkq)K;A#59H&SxME01;7 zDVevM*sZuyE*wT_9V}su#_n>6^nzO^iSUveBM7d&SoJ&goa(-hDFoqlNFfCbhb3bX zi7BowfnjCoqD>kzus?``~9WHE$gm@KoXcjT=qf74A>oe z=}EC3wg|Brou$OqJo=aN8C_F6vFhd zRVlbMmeEGe3Stxyxuxr057Ft^M6i;bQslxGO{Ex&M$oOi=$L5)g)l9XaLB+`KKqW`TR!`yD< zxaE!S+Xn))gI@eASpJ)q4ber4wlt8jpwmkWlmmV(P_eqTZy`Z7VDU3(Z6gN%7KjkH z6FIhsamzrX^IwMLFSfi+UEwTYLToRj?m)HbruzEyDr@#y72XYSbl|7#4?hI zi4Q~KK+AZ)^>IrF_--5cjliyOOROSAcnmTAX5ltX|n>rV#`0M2!A0 zSXov%NWC(8>GR+>uJ@h3V%Q?a%?=@F=+js`Yy!K z_Xh6U_BJ7*b{uLadh>4G0=PZy@>YiS(B-GVx4Sk9=zAl?uSWGzkh%}j53bp42j|h( zwp_x^f-Pd)3}~;zd`T*U0JjYFvt3?S4dD?)`c+qdK4~JduM48$tVE!xpIxJ_-MZK! z#*GRgKuS;w-Dsk#HFT{8PEbJuDT95S1@MY=UZvI$KL}Qit9Gwy1(8vR?&>nsMQ|Qx z;kqnP`buNVU3;TJ2+$h6oX0{4e$^mzo+d*P%5#vUJ5a@ax|B3J5KlLoSP=NNj9j#GXYYk`5 z<3I5&6$5ey5xW^RY40xJQjG3{Mxl$4*(kNS6PXK z0|L34Vwus2CcrCaIv}c0y1Fw}*K``!`qSP%9RQ=3qH?Wa_ z(BSRBi!EYYcX%HDvqzy3bYziAV!rLW5rYFkCttVrj|S7ke9Z&Mz4xH2(Vzp{4%+pC zc*C_ssf9q7p8*q^t5#xG72z0rEx;WJ-IVtZvh@2Q(@kU(^T0z<`}5J&5P}TY6Q7WZjnvf140HWRQ^#`5kN>t-VH|NdOx*S1Y5+oo)7|ECy@_;FMJa{`!R6l2wwG-Rw)-y zKaZaIW2hcmy|1t!_r`0Brr%`P@=9HAbSL=XkC zVT?NuLTjmIJvWc{=vSf9ymETC5cn^iz<>P7P5@904j^}J12cmd{(*oX$-}MkH;R>+ zd_DYWH<)|j7F)*q?FG~IjZR5JahVsP+htDI`%EWOdZj#S*OyhL*V|8^oy}kxMzGk1Zmp$kNE-DzN=w3)i8Ljq6~c3x_zL3jI9mDGjtd9` z8X+a|c#LYL68J{iwMBhJwNWDyiIdA^aO@_wZMW`0QK{8Q#^aPLHIj)qLI@IxB(7uQ zI1UJbW81_MDKhCK0F6e2X0w63nTY{GNvLWan$6WCNiu;5ht?&AE>{9KuV@V|LLyR0 zFpW$17qTT)8bKY~p6vw@NE>N_jB>-PQvxF42$p4Cds8Q#KdPr@7jf-6m1=`f!~!L$ zRZ4^tF-&QKHjqM7tCfl6`pG52OwTMZGB!r7u*CdwP$by0EF9No-+{fHJADc%Eetbw zDa}TMNFs*kz@2vZq#voMJQy_Xf!bliS4+=qA@_@`#wfX?^eE#kOrZU*;2Cv wLdc+^wepd@MvAv^%OjJ?kVqu1d9eKd0XM+pbQF5AivR!s07*qoM6N<$g87z;T>t<8 diff --git a/docs/3.3.x/docs/images/apps/selectvids.png b/docs/3.3.x/docs/images/apps/selectvids.png deleted file mode 100644 index 9ba693a6a156164f547eb4b615afaa43a2475a81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42214 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 KMNUMnLSTZ(DAHH} diff --git a/docs/3.3.x/docs/images/apps/sharelatex.png b/docs/3.3.x/docs/images/apps/sharelatex.png deleted file mode 100644 index e3ef6dd25e1f81de2a170ede0e3a3665fe98b80d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19707 zcmW(*1ymc|8pMk`#fv+|-QC^Y-QC@tV#SI(6nA$h8r*^vDNx+Ky!~Ht!shIT-R!+{ z=bLXPu_{W^D2N1z5D*Y3vN95Cz;+CHCBVZ0e`$19v>_mHPi@7;Rcy^2As}>yGjw4! zG?m*6+?_BpFQmG<%ewg`4;N632w*YL>0l`(AXPnYk<*iDHoPn>|xE zZ2b}LX9Ago=ir?E4<^x2jNq|dF?vg#kXpJM3$e4$=b}sPk}ODJ%FllIx$ouLQBkLB zZ{_Vzk%Zv$HTc2dJ`Aac{_6mVkY27ZUi2P(bhEDE z9P_|)qTt&sU%!(R3cOhIwODMk+vpu`#)StoL9P|;)jhO+;dzVk9SwLTnpCf&uww{Z zKUji`gzis++Tz2tXF7(UWi5UZtF(TZqOLSEfrtr# z=?US7htm)Flm%&6_}G0YdORp|3MnQ+swOM26ufP+Z3@Tg%u10(Hyz)<*%ka0LUJXM zAAJ1fL#!RPahHO887bl&A7v(LMWm)^=9?B$Rg;Zn%VdFfU_45EaO+E14cdbC9=GIC z`$Nh{^}A@l#6thQ>j!vW*pm%{y<08VU1n8=S;qO_$pEJr$IYPs>qu68FUy=exm#kxyXy(yiwlatgoDm@VVMj}j@2VBR40Dv2uWkQt_6 zh@08VOL)|7z1R2XbokOPiqy9h@ABZIr}2fb7*CuzJ{!-G*_gz61sg8X(C^ZWb%`qy z0fiwdo*%udms(Ihmm6$u-b|3Y#9`q>y~V@cP=?%;98m{H`-HP4iD%!9_5{WTzohO7 zG%c_-nOI-Gx3=`JpIua;tA7Y{kT>DdPeF;)-J*SkiJjR9u;Bgi9!(wdlU)l3!fC@t z;v0GJ{2V_D+&5@D$`{>~yl^yl3cpDx$wIi65Fr-G?*phj;m|RjfuiWeuGlW8v4k*q+=nVv3p$kAlo51wIsGEEafRHzVbr3<12!}@(96@vyhx&#` zi9{z(@J+}9Ze3*d8{q*otT@IT1}(y5h?4kGVY~{b2ee(-g?Mt2=rQaaoL)$u*eMHQ zc?7GM>*$QObjnF8BdBbQ2jwIN74l~XW=k@o{GR3 zq9>cbNVp&WGG=8a-{86Cbw=t%(48>+TgTOm$MXkOQVh~~+3xIK-QI?ac!%yLngDD* zA#*(UK=*F=b?g(=8%_X25WH~o4rvJ)7O6T_GvzI1JlPa^4XHi#DNQaFn6!clmt32s zo#K&3SjtGoNPb)LU)&oZEbQnPL>xqWMBzA?II*}>>}1+)m7l5$s&Q(6)w-N2o{GiP4y*UWLcy%cV|cO{V>&)x^*gTt;7}v17A?v~&Cm zz0|k_yVPF!T7_%-%Lc~Q!#0NFnnRL9k;9y0s^zYQt>t@*XiIjBwhhVR?BefZn3KB` zfs@pe$rHYl@)Om&fV-}{FL$zcICqA3&B!`%WN_wi!BNOj_Q-+A@(CUZHwmZ-^9hm( zk9ZYXDhgo=V+x@Px(eLcQrRonyxFbUy;+M{_Sw-{+PZ7HEjm3q3%Y-Gq;ytveRb}2 zp>^DK2z6-I<{XM0Rvc6vj@G-@KCk1iEw2f#Ev`E^CA$w06%%n0Me|Pb`tg3}?c_n> z73T%HdATvUvAWv2KD!^fwz_?FS#-B|d38N&ERWR27?}Nfs$}Qck@9p8W=hfG1_uJfClHc{eNpMNAR6bwf@KDTsZJ?*6 zJf`&#YY=rYijn-KL#tIOb)3N>s-yn&%_aM)0bWZ&mr|ru!a@Z5vnKjI&R5KH-0)HC z(YFz~5x7y-J^H=DJZ^Y z--77GY0SyfXcrl8HMKNW#M@-NbdpG|Nxe1dR4?LtvU)P#e4mdH?-2hW(qQvpw_#^s z%f_|FA<4bTImwO6nNK25YE5QOCTpS?TK;AjqOI#&m2rKupPbQg2=YunVX zZpZa5{`Fsq{foO?!QsQP$-!i!V0&YS$vMTbV|Q)qYo}>9V;gVtYHz&!uau%ze4(?X zxw@vBumW5cy}-UCzk0e@vDm&UTp?`RFg`F|IA$`TGI-Ts+Kn;xYl(K;W;$zeZMb8@ zXF_6va`qsUuB@u|gmfR1pBTmVuf6A@V1_mZFFr3_FXr>ebBZ&5qDo=|;%Z_o;(H=xekER6-cepb zS1b1icPEd*PM!{pF2>8noy>mc70p4;QBRNlxqrv+$!HD4@B%KEr1zqGgZfT*+|um~ zPPr2DX85k_TWh^*ffM4Z`w8Qpl)r)mK(Nf7^@~RC+kdw!dXEB^0^I^X2XF==1>nAW zyw5%dUUT0t-y5SeAa@Wo5Fg{|;6|XiA=x38BcZ|vp%39;60_maf6l?=^OU()`By}h zN>{~(j0h%K!J7>+aPy~#ph%MLiCv0ejC;d4ME7LK;o{@z;+Eo|{%XavLi(^^dS{wE zOf2n_OvHaft;By}CV+kUWydxB(&lD<9cDP9+WcS~DoIc=T}dGCNpOO-iZ`2`m(2I2 z|W7fQ1x$2s$$yb z>-ggO{*Ka4Si-I7?6s-Zr|GZ1>vc{1!hdqF5~%R57VbQ(QR2RDk|wJz-K=+;*PZIk z+Ja0+E0=@&ulM2KbxzDX8rE& z^OTp8@8i|Uxqj*X1o^Z=RhOE_y|)^_Px6FD`(A>|{*6Iqg#H=q4X+i?5q~T=5%lMA z5O}i~F|%-43c7pFI$c|G2OZrqLm3C)Cll@XWM3iP(g%iF6`Q1*H=VWqI_;txt@3xi z+rH~-4SaRmFn<|VSeyRiaKk^;9madn`PX;-`8#ZQWa#7THYf=Gy`eGdCgs8Wn&!81 zyRd!Wg`t~X&b!!4(>v!a;c5HS&SAedqyAUrI+$9ApXDDW@2aikJuAHz9YXCGt+8On zP0V$>f3`2T%U*L2UbHC^o4tsI-w^%%p|9@QQrmf;MTA2(=_-Q`rTUQ&I|BxOEkdS7 z2o0dA$lB;9eAa>=kFqA)r`E1$C`2Z;Q0G)-UXYvfozG-fV2@=RZ)j;$ZRU5=a0%Mq zo=Tg3O;7&5Beh$)i)BhmPV@JxmsF3mnWmi1h90$Oo0O9Tq*l7>M*WXEwfYw;W>G`k zVMTVu)2Igq!=C)&zG%@l(~|j81dB;$E1L`F6iZ+5-_Cn9eQJJQfB9(A@ie8@S!ILm zGkrJ1t$tVZjub52Eh>Q)LB}3cKmTX+K*#roms=PSNcB)hQQWXJu>kQ}RJt^up)1pZ zVQC6Iikf1#l6`Y1^E@;{64hk&IBkLI)WX1Nj(OGz2Hv-)>+~KhoT~PPjYWTUDR$$6 zAN=>Mr}htSvy&%>n}ws87XDDa`4tQ{^=>+?A&Z~(0es|)C=bLZSLG&$pRv-;%lJidnB}Jc$auYku@kTs#h9YinYYtToXiL zY?Ej{-ktKK=EKRI!d}J2`~Gr}zOfX|UFPgquDa;S{=jbE?0Y$~(>k+0Ju^*W{7o;* z*Z7{yN7c#o*?fy88Prm6$*B9a_touy;dV88r>XA~GnRHw3Qvyi`A<#K$6>Sg3JJjX<<4eu_F>CHzmwR+(w;c?&N0WODugXA16D1MKf5?YSD7i32XY+ zyaY09Rb6!@AFY46UAq;x^KRI zx+He4b+ET}?hP)Z=w`nV)zBUq{&|rqeV7b-{NaZ=Z~v-MjJCzS9qdkOJ{SD!CHr5) zznJ^VSDlgD16-Q1eIvjAg*=m7ogWT zaX$XLdhqJK0XS?@ug)u7C%_g?&CJdHE6HTe`eH(h_f`yVbe8mam* z?^)zfanqdHagYL|7Gifucf=!A8o55jWf5&z0{NQCgqpf){ajC>V?|9l$TG(K&a}x? z%NoPf(qhXZ*P3L{=J4ks{Snh1-R=xHZ8UR;giZu|33m_Ug=~{Sjh=woigK0#Ql3#J zNmek`>3b)+K5ZuHWqDz7jOLm4q_&rusitp{Uh$t!Z7t#&p(@q-?6Sj}+6szF`I1j} zeJ3FN1cGf&dX@(^43=!RuN=)Bd*VVNq-mC5pFwv(>eRH+qjyx;J$g<^hicxS)jPX)ejR~3xPiO#fMRb z8;^Js$4x+k|8Bg9AeG(CN;_IVDma-oVUv&-KLdRRKahFs>vuY@HZKv+mo(+-1?9_S)>i23hst|ONd;Z`8TrKD%zbh$?uIu5JL7#D zpEqFntkpn!pfcQ<^oIP*ubQ2OZmLBJ)dn45kC^sU=ax70O?GyasY~@;hWx7jwHNF6 zGr2?U22KTi>}vya$D10P0xMyiGz)fXf3}0}{yitH%&wxfk=%Hl3f=hrSa;u_u({MK zkoo8fWe-mSSwt%*1rRg`Zgb4OvIUF%RbFl zHY!a@7leosbgK0>Y)Cc{1OpU=7d?cKDw4^t9t14WhkuZW%wDXtn-cW^ibRM&s%;J= zF6B-VoUM$MFHTDs872RA#4#y`4AKPJaABH^&>F1bF#0so=|KJ!0_7B8*s5v(t-A(e zH6mx!Sc&Gm=&{=!5;E}^_QWr~MszKt+>rADQy1zEhfQ|@W+C()i6{zp${KQg8g80? znLasFQB}#kcJZpK&Ow)otw1*x?nENk-@84(&R^5{YNWNcEeS8gN926l_H)X{L z`;~eevu1dGi+P<|r$)bkydck}Y+3)SY~qzZi&l=FmEMsdSR-45SnYHjT=q|-M88?t z-oW3;S`zKpJS7m-If9#-y@3~*x z$i~d5Y5h6_%hz`A#4y{a0xQa%xFA_Pmh7AmMpt9Vx8a}aL8<%M1hiQsuon@$@}Q)^-6Mg%65 z4D#+X{qEaqz3zPSwy?A4w1_`|ive-d{h)QC$YzOk%PJJ>5RnwcQRI|9SJ;v^7gNgSIy05Dpn5&@U%uc>(5A8Lu6x`u=%ZM4DLs)z@~ko9uPV726lJ3*h?}t8DzF-85Oc6)ZXZ96G0xLx`=Vr7Fu%+wrb+mNGqd#iBtW+1_IxYhf;FK;QbZat2)p;6aV8s zT_8{>@Jj$Dg6o^uP$xNG3Avd7T5w#wObjnqPDeH}$#})wk8koQ@`SSuAOoI^oUhrp z$w*nts*RUG5v-@tLmBf)jQBqA~3i-~-#(|c+tRH-4cBhVe z$aY+=sQJo%$^TqDt`}*-L9Fsr#!5knPvwt}_pce2@rRiVeGCjWDK$vK2EljrCw0p| zu~x)aqq(rT5V`vt2%Nt=IytO68otK9oZQ|1K^|jQ3VZQ<>vpI zOA67k2;p$(;Ow04=l?Ye%a)|G6$jZ=J)A7CW-Rx^@HRCHe#}W0{?u* z4{-nC%;cpdAU^(k7WP)80ecXfrKH?}?SBt62*ajoNC*gyQdtR64WEtk-ib6K?VzJ) z-@d5v{1hZN$VM6nD9W}yH6pE6Jxg`XYJ5U=Vht`w_XSa!?0+HoxzirG{U&?EjWQJ86KWllqLLyPBz=%R*i(E8HKmGf&dy6IK z@#ymCvi)O3_}{*;90VCm{?YGOq3Y`5Q$D~F)F6cmlBYB?sga=mI+`5(X1=}}8sjBH zhi{%x5;8#FfXs2XQwe8 zK{AHlQ-KYaU60#eMux}BtI<3V!tg(& zRpc~v8l_!drqIixzi@r#w>FlXopg(nt}h1&1|Tc@<~T=iWwl&8mCr)tN&D8@>@8Ja^;Itns~6axxdvIu;Rxzp{G^@Gn7vwO?JyhgNBhg77P zHcYA(HEt|c`?Jl8{Zj5%4NY-US3_LQ#R)t(;%@nNFd2NYy}D+idWABU59%plEc6c&hXe+#I7n6FXjJq5g+ zC~g>%gi5Gtu;F73v(RcMss7TH(JZXy)3;~%S-Z;Ok!S8+&(aPNSDf0a5H?U@~vdE#gTq3CLO zKEqt~3ecRczNLGOT=!y`4&$7Ycf(Jjv_q);BQnbvm@}tna6zzAj98h06^<Z~)Cx#0&CD7DMeQVgwnCf1!x1j=0*MDw>hmz+|sJ5cM^g|h&2A^;L4 zSHYpuI}Gt!rA{X^`}w$rb;>Zc#HBrPbgQ!tm6k#Nc=;7e4n8bK-iG_MBVU`MI3wZ;T9R=2vnf_MV#50D9V&XIP(`-Tq@v&H90rK ztAcHU6GVUe^C;6{nhFUSUwTWb&U4`GJbDxJ`y`6Nb12dv2ZlL5&^gsq(^nVoJ~n&{ zZyHt-ZqT2{O%7GqmMBTb9=_nM-C~g(r4{w=7rQDH;5vJ=9Tz}?9WXjta~2MNZ|vQx zsSZ1O?moZ>9m&l)n*VqR-o-7)ypY8Bwg}^BJhq5Sb(QrVEj<2mvzl_1_t1bXc>-Sf zxXSo<7*v>uJ~>CI*geq_yUZ_JtQ>pf+nuzt#T0hw51tJB*H@MfEdj|tbbn<}6hMp7 zNKXMSGh7WCx9ER;zoWKvw+c_LT)_q^_XO4?#B`rlJgiYX^D`6U z)A;n%)>h6H?iGaa3f!f~)4s+Mzr+^RlUKhsGLg~_8HrDKdG3|Qi3xeIUXNh^p1M<; zoQK3IbK~)6)QuyS%l@1gkKck{ zih6ayo5x2N{W3`D#E`P1w%1STMZzql@J|&_3a=LohhT1I7G}R%XR5o>N3)Xl1dVbl zzH$26y!KF9aP7UmZ%$bzvB<$>*fmn{Hc{a6aJC+pI3Eu;@4!`t9%jIlxv@(l{EQI% zQV~1}tmxam6{VsMo5JWWyua94=ThJz#My7$ z@h9}k6E`sFUM)MJ*FDFRg1qaA z#`S?wD~1oP`uo$fMnRYAM^|W+l&P8&R^UN^@5_4?mg?lvs?tlT;-x<`>`?G)=EoQf zN$`U7uV{Q_NxbUvoA=A$0`Hwb?%1zA0TXTUa^w}17?{345bFZPl@MLRiYXi3e zz=W!3Mi%N@oHHc)lh|gJm$DG2P7Do$G{kU!rjF3di=j;-k!`?U8CKRZWPPsmJMd{^ z{UGFOkv_O1$|+W5bE8!=i?tcT31(uCcK?#U_B(b?5-4Xt$&bn`}q z_Rt*G(1k? z)vZc2!X*!Ff;Tp&bJB6?A&8DSdYnRb%;M2;+}srpkO&ktWPx5B}x=EMLu zRzj0gL$geWmNa63qr}Hy)zcfQsO=*jc8j>C{mlJ-tRBTj`N^huVKBI&u5Ow$~RW6+}xU!)Bfs(74RcHG;z&$Xr+X7QUT*XGLWXC9)ayX|cRr?&>uM!Haun z?tMyCsiXyy)d{9TyW&-)8;QZIEwm%v6)CF|p3Z#Qm`ML4Rv3kvnSAte_i^u+XV*Fz ziG+&|_4iaoKhg`O3HF$STx>o;MiPvnc%j@2sx~|d7JBr5bGl^+x_+XD8uaiABQbu1 zB&pjPdvI{`gHu%1Jze4Xo?Y5=$9Gg`qw{?9p4AVT5b2ycaTW z>KWAjXYQ{@JFHW-#lqFQjC?6AVpLrTnqTz=o5Gzx1*-q^1zxU~9-^1DBVAmo&$t{y z*+~owGExL$wg4?3$7*q!?jf>ejR?O>mDj0H5vb7tHY8R7Lwvr{%YMxXms8u6i+jS( zKdl^0O#(w|oU~idlc8I16&RyE2`#|cdD<5lGT?603ikQp;NV0SA;Y1m%K#0(k;fHR z%%WLUcp4e%bXa$r&=Z%AOg8V`IhAN2CtIaatU*r&#>Sa7qG@D|HXTv3)w5W$=TuN4 z+>z3SzrOZ$d;!*WXgUm=1o`vzC<$rVh^L4qY`tOu4e}t}iG^DaHqaZTvZFR$Mpn%Y? z{4k~=b$_uFiEf{5gWB%Mc-fPy>}>SMvpB7@_$$H@vrmrRefo9J7UYQcsP-ZH)DXwz zs1dKhTBK#M>Aq&XZDB&)a-Aw+Ax5#D_{!{dgWD*^7su zQzt@F4;x2CLTxcSP=vK-lanQvI8dY;rp?VY#f$Y1xqLp3!fz!!7RNlyO#Gy!nNhkN zLR{-CUI5-j52hPOMQFSIF1GY>y+8iiq80_4xgB}y99A4sELjjrqT5p2V{zITr^*Yu zU%#b=7ZaKMmSA=B&b|W)V@m6C%C|mD*y6=962|?`xNJHaYLO7?3JLQpmM>KzTCr#u z7)ZS8dE(WL-R6joUge51EF*+6Y!VnK*hQ+iKb_5vp?ZHuQqDNj6kSG;&KiNn5hizN*B@m-gtqx_B?uyu@Oy2PZ=?``JdXqkF(oo|WHd!j#mq3N7 zQ?|^4!37ky8XDcK)rpLPM~Xlp8JNq^jQxhaDg^V)n4a_Cmd?&tN3aDO{>C|1-6?rQ zp6($f_T7=Pn8*d>Z>naV1jHHb*7bXzgm@|9iG2WI1|46& z((H&K!j@8|V}d4B112KQ`x+HluLNBUej!CzS6gr+=OyS;Z)#zUCWVK~=7bhaY(+h9 zB*-ysf`i}qQN-Z&YCoeN&c~@%ijbAP!{D1p+t6NY()pT;pyjR%PDM0^GJlCVF7d|n z63DRAHpwQV5|pc9vP{PjP@9>gjQ9JY+RM%BMkJi~gFKRF@BI2wR2kgc(A6b}7p0)6 zD0tZ@tQJ#(oeV_?3rfv^x^QfL8Z93jjTFf2p(jkvv}p&&MpZAKnB-6cli>U1_V$+X z>sPX}5e~)AxVW!csqfFyjqx)CZA~(CyuLRU!E~X+HFm*`4YetJ^dr{_I&^eYan&kd zzmao&@2X$7212ZfN50sIkrI_{jPU_N1#1|<{cSnnPBj6S>V|XIIB(l-dySnsj@)-x zg~6WNgki_(42KDlplM_;N>BMNC&yBI?hh+QVy6!|y3Yk~(@ESjKw+)pAxQYOL509F zDKEeYbWa$)`OoY0a)b8^SiKFi2uX<$QrNy4{9KMQ{cQgm@;dNly z3%LE`55hx-u%o53K%@;hl9_dSlcqjur67r(=f7ahCHfGW_OTjjPsf~En#h?~kWoJp z`v7lqC@QeCz2QftYy`Q0E91odF_M8#G|^%s#vXPHK%c`M} zq1GYQpqaRRE>{*=WNKvbj?`;c+MfRH!!@b^32sIp%5x}Oz-o9>`%MeKt4y3cAI-x) z(l+RrJ|}?J_d?mYRmDUp_>THrf-uUdJ-$vF#-ZKhLSck2Qq+T?ue;f-L&>8%3ZdR$ zZQZHPI-7QuLhe@9ce4&GI;BWn7RGnDFE45?S*C$;rrCTjMHtB zw#Xh^jv#YJ(5p-F!1k-G_j(aC>s)ip4$rxU7ExY4MQr!w{uCZ^i&~%qXVkQVt79w1 zav@Qs?U%AhAkI&<5ij0znO?&5YDRFs7*T(wbY zl|_zflpQ`uR7DqS=;=}DH97)@Rve7tKYTRBzk}pUyhiqBR2)LgH53pFl|g=~=XEe6 zo)B({fDty`-k%4*BPNHf2>i&e_ovDRSm^7?Mo^+3>qDw6oGN_=CU*vFJ}dd{V+zZS zpsrcPHlz&SH(IbnqxMh>4d)0-vqMFO6rq5z-VUITX|c&OZyjNbEY?l~gL?bVxt>f} z)P~8+MlK}uYBO=dv*FG0FBcUm$6c6wU4|zQnhxmT0sOua&k;^pX?> z==8gSfnNA~X68IcBG8MHNuHY+B z<|yU6#pBB+7U`dKD=kJaF0z8P1KrGl{^6db=yxnLl28``6Co7EmpM zJ=3;N)S=C}W*WgB)4PfEupfjTMb_p>gA=qjxALh#+>z?V(VL>g7`{W%<;IX}L-qHM zHt?VtN}pXFI(dUe-t!wr5qyb2=l1GzrI7>jq8zank%}P$dQb=*b`Ei_6&4qFyA1~c zgwFTTGWpDxo2Bw~7O5)jSEbhoC-QKH*}FTA47oCp>U_g)>t)mXSord5%2aela#I9{ zon@V7P)rl?@Rwg9mx!>Mm4Lp|=77SV(rh-c7IYFh&H~yPmZSVcfh_sEdzG1T-Z!rJ8%Wyr(aOq7?J$93f4iY{ zT6w>S*ADhNu)wQ(E7LPD!8#&~)}mh!DBc5J$W#+(RIf3lvKu|pBZl=+w&{-M=_-QA z;p5u$I5*D%U3J3G;Yh=@51t7cXQdtd1ZPX3dGO(+18wI;Vh=`8?weN39~JLsgn!a- zobB7eFrp&u;6yR~$dF}Dc(G$Cs$Vwkrgn%qiYlBcI4(pk0$JH%W*9fjvC9{-t`P?b z(Diu2uj`|H(RkbxHR^Sd5TW*Ori{}@O(SXOo3urnu0(BZZCO8lY_2=! zTy6IcpMy<~F;dc}Ob8lSND$Q82zh0H&*{xG`VtiO0t2w%~-z0Ok%+sNZs;dufpB;mA#5!R< zhQU{3_q4}DERgtth+c2=Wf7yzEUH1Na7{lni^n7Ck@-Lb8C^s7<25s(?&;rRZLQt>7F09oCQ>46XW7 zCGsn{UTv}k6`-KNpS-4geQ@JDa}<^#8h&wX2e;_ex_?W>^2aw%8aBXdIxxf`jx(PHzBMiuRvxLqDX=0%n)`n_ zRhIDNPU7;~W6qaQe=6QP2_%Xt9f@U?i;`LNMx#hK)jDed^~Si{+s8BazcqnYnv8AW zx?{|C#&eW|&rC&AS&m}xUh?~v@LtuMAA(2#6EYR&Ax+D={#<15AZwxr#+JX&v=n2+ zlscipi1lG=wsZo=|7+tbf-iBKUV@u#y#_szaL|wJFX8!@uYqObei%`v!BEGLKKask zQ2?fvWOsePh@zKX5PHqF_$S)OjuhAidIEur+JjN^k#E&ea{SBPc7HlsFH_Y|9r;x$DQ#eMukNMdYPH&X_vPr*Ne^0@M2n7 zV>P*;+uR)>)d7IRg6zAW$W8k>o`V48Vyj!adu!}gfN@GJrV_cuQny792#U(KoY=X! zGc|tl`9CmnJ8zfH+W@tJot+&xN=-upq)3X3m}YkEV2ftm*#cn@O+kPdUKC)z0L{vC zKt2*K({2}&@W(Rzct*VWXlx?%w!u%K80iOC9j|}4IC#tl$Ms(+U6!@=G1Q1vX`Oqi@LmYD*qa(`VDVCgmWeJo)HiKK=7}(wX%w;s;Z*Y zl9;TFI|Z!lDAPh)g1Xb4WmBb!IaSQR_y@-c{c9k)5PtFEM)K9kv4>1`(D02X*3{OTRdZ&g;z zPlJDlR{{f=2cYssnPIks()-5M;W^JdrHb&=E^I_tz-I;^1=Iu@(~fJH>>ocU(TAgz6rqn%F5@Y{lZhe z@0PB6BM5y@dq^RD3!g;MDI2e?XMg;6_O-Uey3-c0BjXe~@^EQ~)ijr3ryJ}rONaXr zDgZ9?@g!BI%+A19FEzTyr|W$H4`I);X2izg~o8drfNiyYSiXu~Y%V!(Q>@3}#o zu}aIxz;Wv|Xo|x@gbgDt)SzeOht?WJ}ry7OGUE4khw%L=51^vwsl|n(n^roBI2g9`Ff( z+jIpMC1NC$y}iB8_YCaS9>CyF+TVTszsoNMA2&+=c(Fy1ImOD(KAgwzZNrt@Q8)GW z7SKe#WXH*&Xl`W%2X0#j{OBe|zzuaZ%rtA1saPCzCHf-ZBf^wv?&Os8{OlV>YGQAX zWVlL~AqR}p#ZJF6SFU26qork}U2Dz()(S`B^73*-Yy5iI#DwgBhfC%Q!RJjt@7t(j z0elKrJXPuyz_hluwn~^>YO)bUYVK!iY7j^e*mF)Q3OKSvE54b&!huT-D=c*b3DTRb zLDUZF6^pWLF*Z3-=waE}_@(JU{jM|U90IgorB)4gyrjY+B|MadrsS$;80l^z_qK?p zCgarJmiLb2B8P|J5s*(rn949^?nev1k)e?Ym1@wd(w_0CJohC742FV6Cc*Z5?;2^C zWxd>1Z>TPh&oeHKMwz;76F~4KWkwBKHf_b#(h@d+9$Lh5Tk4++yFQ~z1?vuN%;nU` z!xqbI$l)Y!yPpvBm-*|4|BRRpvDZ{`#G(7OkK+AdVw>C$REUy!CGx6uCBEjtejE({ z1Ppl+iLeq7#HUTL@bb#mYLx(GkOvju(3zQ;gF$B}r(#+}KyLzb1c;vw0CGcCBUr1R zhFx1sz&Zrxrb@%i+&moMyJA{|_>8GT9b;qV8zbPmBd&V--W{vnSa}mgkB&-KFVh3c z+v!eSU47~Fo-#?0dP&>Jm&&x!48LgIp$Q;;06`E~SXi-bsKs4m@$vBhCoMQ|0ov{+ z!x20U*f4Pb1xW#{bTE;Y(lm7IjWPBgtI{N3OAocg@+R;+5Olm(nnX)NC5fTK$X2n& zEM>Jj?^xN|#sVN98vidJ;z=5=)o=eVbb1aDGIcFY2dqYbDS$=g);S%EMdJg2SByg* zT!wD;RrBXE!tl4po!|noqL9m12L}h2-$SsoKX`{L3WDUy)CSuefyCr#FP`~nlsPE0 zx*D*utgNj8FNCuH{oL92>542v?!U4y9F3Mn5JgBx_|ykluF=lU$|5ZQ?RPPe1U-?7 z!2`CFH7MT_0HsvPAW%Utz2-R-0odG~ECM7A6trbK&TCAdzyO^RD?fkyk?&@wJB=w_ z@GE#ntw!_l>nSlDkQk=Lkkg?7-M(-L<&?X=zuZg2dtC2HHmx(}DbXOz#jR(0Z~I1@ zu~y@4+qM3(U<2A5Ak52da4olWyV&FfZa&q0jB$M;ji%G(H&k^s^|H(UYZ6LaqX{w6 z_IQ%yKZ9$|AHugkx>88GJd^}SMfQGnN1XV^Wq zbmyTKetAfhphF?qRVXkm)JW2v($cr*IDC-yUcSD*xv3DR&cw(_nG|^~K`im6wT(ti z?Nvc`mO)}RA_4ynsosmQOG>`bvaehq)LVZVOH8%zQQC`_&_wiy9IGZ`an8T@I?gX$ zr>cVe3MFT|?d_{BbD1-8?pv=QTcQkd_any)IH(z76X*}g9!x2}XlfB(hy2pJ?%y#0HaoX{rUW>TiB>YXL zvQn)Ys-FXslZabR+^&ts9(({q0B)?VUO4fzP1*$I_e-OEVW5f= zl&(cmwt0-(Y3@9_64AsadK1y8qK;gU_OAGVZh^Q+aS_O=0-KZqcA`uvweEpdnm$9W z_)p^U9AK2*D4*>u*tPNmz4@>)CG7+C0CTvY?lh}BTjymThsR1@TJUH%%GzukkBS2g zYv5Bdu_UQ~mC534?n>RV-SzGuG+Q<@ut?#_Iy_H5_rD!7^Sb{*UU&Fz)jR?8v(CNu zp8-V@{P7rUZDmF6x_lK_;M6_^;FbpvQvJ^}&X_2gKkESX0stTE+&@zvbYC-ap<1Qk zVwib)o>dz3GIYB7`XyR5Kz#$ef!f-y z|G@&d?0-rt%`f`e!VpOKZVsp3!2R#~Vw=DsR)x9K+uQLy0)!DNpyNh>81v{TJ3oJn z1sULd(8~*7SDiVSt4s|6+@@<_0JxVz|DMbN2hh}%EF~B2aCBIK@)LPNZ}C-BD+x6b zT5~ZPR^1|pR>@LZlqm~4dm5!dnws0;Bu)}Bf7Frh^vsNE&2nnHFHnkHT`?3Fe;v93 zlL~MM5K;eKqElG3aCJ@b>P8s==nP=9%IZl#Ua=~s0gADquP@){Xw3P|sySPsV{~-1 z6lMcB2#|~dby`cW#|dWLDPXh$I@c^HC?ClC6A8I(TJ?Ye2i)7C8}Gcx=utZ(L!&v2 z=)l{X01%V_HZB#{H-KG9G26iBTsh^90FUnNk(=TH;o^7n9Y7#fS3eLpXEq<1j)c0e z3dx?07=agm!0oqP|LfgUlxlQXTwGL8P`GQ2f!vy?$K8huL1S;myY~KD#t^U%fCp9%S&=;(=%>dd% zM_(ThBG(UK=i8Htf(57cG`zSqIH2)gtv3e19RBh6;B32Rm;6v*fE$=Dc%!7H!4!t(Mmg+hUI=g#r?@nh=sI@8nB zD2hV8UPse33WWmMY!*dP$mMd$suTwZ*|we7HHyU|ufP6!U;IWspU3k&Y}-!u*Xwm= zW@e~VD#<;@ZXvOgqG1@x-|Mfx&gSMOrfFiDW?zI~EO^KFoXh1B179qQ9HkXQG@DHs zy9*4WR;%%cfB1*I_uhMb+pVm{fB8TE3vayf#?Wxf0iny>-}H< z^;>GS3u`mx&%tkD0#BLw}olYkq ziXaFQ>$C6siIZYJpHKRVRlkF3+t{NwzSerZ4$#L9#C>(U-Q)!k`+mjgh#ow6&_@)# zpNA1oMHo`bB+eMv#ZL9HG}{A+q990D%MQAI3}ekksd>{dj4*&cb}C*~8jVIDQ5c4i ztUB?8j3-ANMC3RQwrvxJVUipnwsE+woA^UHjzhcMPTr)kARH4$tJO-j$8IaJcdlU= z$-X!qJU)Ls2EE~`u?%6`cES!BhLQME#rGH6P~!M*+qP*oo5_8|k%D0uCNUmC5G1Qn z{31{kh0b>2oufb$a6lPD2!W!ioIQ1#R-=aP1{AUxsrT%+yy zWV0D+TU$7;mkeOBRKoXMx?P7tF^}Ep;0FP@d=8|*&^7AyI;vq(sZ7wQRk0lxRn;gK z3rW0kM1&GVOq3+w;|JASEHh?fdIOdQ5yu(y8q#!KPyCBwIVEj;;z=L3={;tU$Ya72 zLL`oknM{UUF4vbJE++Cc|0W@#nC;&Dyz%|T#5#z0C5n%awRZ8!8WVvKA~lnJd@s#b zlTgY-oyfTt2X;F*%q;JI=UvuU*O{7`W2%(pSHJo>j<3>a)VXx|Rf14qdg4u59h*YV z(Y+5+aeI%H%|m)s-bazw?mqeeb)h zEI&duG;ZCx$;Hc8A&>|m>2^A(nueyTXu3uaf}twB_pkrL(&|RCI=~Kr!~$#l=8J{q zv}&_`x4(}_!%@zTqxQwWV>x3#eedVIX~*=+U%l;nw~so$Z~GClXFPo-!tMJF1E1yP zM>wuat6Agj-7nbOs^Lq?nX_jxb(IHS-DQ2Nj_Y*!;)^d)R1HN{QPe20K&#oL)3rfB zr`=+GZH+((2t!=grdqEdq@>xXa{KeodGvS<6$m_^>Q)ucvDvCt@jMS96nxJ^BG5FI zPNzk^(PUV@|6am~T|(l>w=tdoL)5f~)fer+b`00)^8fzp|C0>D4qyKzpDGGchJ-=L zC!c)Ww|{x*0k9Ky9WTT2pen!k#V+|F3_~8TEE9$yAN)EJ4u5y|Ue7s+SSfad#~t~F zWP2~N*({c2^|e2&5A%5<&UT*smWMk{=QA} z)u8n?p76cIa@cv`7Y%6|%EOGOB8(sixOeX!nyMYDV3e3uiq(}cUL~FtdTlQ+t&AaM zl!9`MF-GAq%NXO=B#c}x$Gh*oJJiTD#u%e;@!~}; zT{@fpxf>8 z)A!$})9&nJGQ|R=81j46krLA|dG|Z-Qpg|8Qm(~fksCK|u(-H*w6#(b6BGQwAN;}d zzSgf58yg#JZdR!`8c`y-fjKYPww@0vS;Y2#GICx_(_YKoW?>XE`=9>T|HQ(={PVu; zF^1sC7unrE1Xr$J!}I)uceMwiIEt~{_9A0U7~4=3g}J#oWH|cG4?Qwg+)x0rcZo?~ zT6$Ubu|ng;#+Wd+5d=P}B0%~2d15J}^NsQ1Vr<~shPPec;p@as_x%Mj$9VBDUNN@e zdLBLVHbUCsv6l){${io~A-knyOc*aX#)PqrIJP@dFYZL7i2>O__Wai?Nr>Jpv8OM+ zlE%)jC|=qd$9}xP7!wAOvCVZ{!r*`|(=lE2{2bf|F=4oU>1@V$u`nhKBEoPSmmmnY zxu9qk53UqD+NhmvByD!K_OBv?h_*)O3&w=;f?`Yk@>$gb`yGBbD+!CV~A4 z?^1&6diZ`oPky&CULcGK1MvL--w*nDN*vr4p{41;65SQrxqk&KZD-C}R&@llHd?3JZ*XI1k3F)Q_=;-x1H zDJ72{KW2S>10mx4w0j&A|CdG`>8+D<#h+mqQmITZS(zATDtQ6%(i29vYjf}3eQMPj zLfKtwJRNe++{MGP^2L8)7*em*Sv+?pwb1<-&lfK>VK|P%%};+ztyaYke56mpQtd=` z_PTNm_K@yk-mCT<{N9@wuGMaH^X4tCU%xU=I`M+xr6r7Rx6AE2U$C*UNj95JRJP9w zvX9@|U0pUR0%KCG)%oo6J6t%wNG_Ls-orA+HeO1?=yq-HKUl(XTuP-9hG8Uy=byy& zJel$%RI)qh&(5c5dQxuK_XF-fSmNY~<747@LGaQMMwBsq1yxn4R3`9Tm#&pbN_{06 z(xvRl;N8y#rPZ~D^!gVfE@Fd-{wYx%j;Q#Ig=J+h3Hb_ zkk3Wscpb+@Q6OXLC_>@~8ouY@x*o3Q;kh23AAP!>8~yfNJl`kqeS#oF%5XabL!hWi zRJ2CZ&~!a2jAQ8N+nBqxvfTVRZRVJPDe zInW(_`69Vr8Lb>+q8I}}i@ig4l@OB>MaaZ|=%_>4&N(Z?@TGYfj4>QyeSKYep0~?^ zEtKGgV7w$A&|Vmo#!$yA#!CZD(}qS)YAY)%)a&)EG}NWh>?;fRhycc w+RWv0lh6Ai#~9=x}o)VD=23xZGidKsJj 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

    UgJe6f|Y=Yr! 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 M07*qoM6N<$f<=x}o)VD=23xZGidKsJj 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 P00000NkvXXu0mjfkLXIi diff --git a/docs/3.3.x/docs/images/apps/stachify.png b/docs/3.3.x/docs/images/apps/stachify.png deleted file mode 100644 index 14a64c23af6ffe25419224c9e6313b366b925014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27783 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 DnZfGr diff --git a/docs/3.3.x/docs/images/apps/todaylaunch.png b/docs/3.3.x/docs/images/apps/todaylaunch.png deleted file mode 100644 index f75fba3bda92d1387dc24b7cb6d5eaa648fff69e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33233 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 KMNUMnLSTZ9^9~09 diff --git a/docs/3.3.x/docs/images/apps/upcload.png b/docs/3.3.x/docs/images/apps/upcload.png deleted file mode 100644 index 4199712ee7ca626e6f2b45800fce43336a6da398..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37792 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 C>_hDU diff --git a/docs/3.3.x/docs/images/apps/wavo.png b/docs/3.3.x/docs/images/apps/wavo.png deleted file mode 100644 index 3ab6bb877c1b05a6f2f20a8cd697bc21ee84a7aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54906 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

    Getting Started

    First be sure you have MongoDB and Nodejs installed.

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. -The first thing we need to do is include mongoose in our project and open a connection.

    var mongoose = require('mongoose')
    -  , db = mongoose.createConnection('localhost', 'test');

    We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    db.on('error', console.error.bind(console, 'connection error:'));
    -db.once('open', function () {
    -  // yay!
    -});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = new mongoose.Schema({
    -    name: String
    -})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a model.

    var Kitten = db.model('Kitten', kittySchema)

    A model is a class with which we construct documents. -In this case, each document will be a kitten with properties and behaviors as declared in our schema. -Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    -console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    kittySchema.methods.speak = function () {
    -  var greeting = this.name
    -    ? "Meow name is " + this.name
    -    : "I don't have a name"
    -  console.log(greeting);
    -}
    -
    -var Kitten = db.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    -fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. -Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err) {
    -  if (err) // TODO handle the error
    -  console.log('meow')
    -});

    Say time goes by and we want to display all the kittens we've seen. -We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    -  if (err) // TODO handle err
    -  console.log(kittens)
    -})

    We just logged all of the kittens in our db to the console. -If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax.

    Kitten.find({ name: /fluff/i }, callback)

    This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or api docs for more.

    diff --git a/docs/3.3.x/docs/index.jade b/docs/3.3.x/docs/index.jade deleted file mode 100644 index 49a6b0e808e..00000000000 --- a/docs/3.3.x/docs/index.jade +++ /dev/null @@ -1,119 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose Quick Start v#{package.version} - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - link(href='css/guide.css', rel='stylesheet', type='text/css') - style. - body.api - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - #content - .module - h2 Getting Started - p - em - | First be sure you have - a(href="http://www.mongodb.org/downloads") MongoDB - | and - a(href="http://nodejs.org/") Nodejs - | installed. - p - | Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. - | The first thing we need to do is include mongoose in our project and open a connection. - :js - var mongoose = require('mongoose') - , db = mongoose.createConnection('localhost', 'test'); - p We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs: - :js - db.on('error', console.error.bind(console, 'connection error:')); - db.once('open', function () { - // yay! - }); - p Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback. - p - | With Mongoose, everything is derived from a - a(href="./api.html#schema_Schema") Schema - | . Let's get a reference to it and define our kittens. - :js - var kittySchema = new mongoose.Schema({ - name: String - }) - p - | So far so good. We've got a schema with one property, - code name - | , which will be a - code String - | . The next step is compiling our schema into a - a(href="./api.html#model_Model") model - | . - :js - var Kitten = db.model('Kitten', kittySchema) - p - | A model is a class with which we construct documents. - | In this case, each document will be a kitten with properties and behaviors as declared in our schema. - | Let's create a kitten document representing the little guy we just met on the sidewalk outside: - :js - var silence = new Kitten({ name: 'Silence' }) - console.log(silence.name) // 'Silence' - p Kittens can meow, so let's take a look at how to add "speak" functionality to our documents: - :js - kittySchema.methods.speak = function () { - var greeting = this.name - ? "Meow name is " + this.name - : "I don't have a name" - console.log(greeting); - } - - var Kitten = db.model('Kitten', kittySchema) - p - | Functions added to the - code methods - | property of a schema get compiled into the Model prototype and exposed on each document instance: - :js - var fluffy = new Kitten({ name: 'fluffy' }); - fluffy.speak() // "Meow name is fluffy" - p - | We have talking kittens! But we still haven't saved anything to MongoDB. - | Each document can be saved to the database by calling its - code save - | method. The first argument to the callback will be an error if any occured. - :js - fluffy.save(function (err) { - if (err) // TODO handle the error - console.log('meow') - }); - p - | Say time goes by and we want to display all the kittens we've seen. - | We can access all of the kitten documents through our Kitten model. - :js - Kitten.find(function (err, kittens) { - if (err) // TODO handle err - console.log(kittens) - }) - p - | We just logged all of the kittens in our db to the console. - | If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax. - :js - Kitten.find({ name: /fluff/i }, callback) - p - | This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback. - h3 Congratulations - p - | That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the - a(href="guide.html") guide - | , or - a(href="api.html") api docs - | for more. - script. - document.body.className = 'load'; - include includes/googleanalytics diff --git a/docs/3.3.x/docs/js/cookies.min.js b/docs/3.3.x/docs/js/cookies.min.js deleted file mode 100644 index dc94dbc5bbc..00000000000 --- a/docs/3.3.x/docs/js/cookies.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! Cookies.js - 0.2.0; Copyright (c) 2012, Scott Hamper; http://www.opensource.org/licenses/MIT */ -(function(f,e){var b=function(c,d,a){return 1===arguments.length?b.get(c):b.set(c,d,a)};b.get=function(c){f.cookie!==b._cacheString&&b._populateCache();return b._cache[c]};b.defaults={path:"/"};b.set=function(c,d,a){a={path:a&&a.path||b.defaults.path,domain:a&&a.domain||b.defaults.domain,expires:a&&a.expires||b.defaults.expires,secure:a&&a.secure!==e?a.secure:b.defaults.secure};d===e&&(a.expires=-1);switch(typeof a.expires){case "number":a.expires=new Date((new Date).getTime()+1E3*a.expires);break; -case "string":a.expires=new Date(a.expires)}c=encodeURIComponent(c)+"="+(d+"").replace(/[^!#-+\--:<-[\]-~]/g,encodeURIComponent);c+=a.path?";path="+a.path:"";c+=a.domain?";domain="+a.domain:"";c+=a.expires?";expires="+a.expires.toGMTString():"";c+=a.secure?";secure":"";f.cookie=c;return b};b.expire=function(c,d){return b.set(c,e,d)};b._populateCache=function(){b._cache={};b._cacheString=f.cookie;for(var c=b._cacheString.split("; "),d=0;d>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.3.x/docs/layout.jade b/docs/3.3.x/docs/layout.jade deleted file mode 100644 index 6585074f210..00000000000 --- a/docs/3.3.x/docs/layout.jade +++ /dev/null @@ -1,25 +0,0 @@ -doctype html -html(lang='en') - head - meta(charset="utf-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") - title Mongoose #{title} v#{package.version} - block style - link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') - link(href='css/default.css', rel='stylesheet', type='text/css') - link(href='css/guide.css', rel='stylesheet', type='text/css') - body - a#forkbanner(href="http://github.com/learnboost/mongoose") - img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") - #links - #header - h1 - a(href="../index.html") - .mongoose Mongoose - include includes/nav - #content - .module - block content - script. - document.body.className = 'load'; - include includes/googleanalytics diff --git a/docs/3.3.x/docs/middleware.html b/docs/3.3.x/docs/middleware.html deleted file mode 100644 index b9b3e244ca4..00000000000 --- a/docs/3.3.x/docs/middleware.html +++ /dev/null @@ -1,29 +0,0 @@ -Mongoose Middleware v3.3.1Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

    -There are two types of middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next

    var schema = new Schema(..);
    -schema.pre('save', function (next) {
    -  // do stuff
    -  next();
    -});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    -schema.pre('save', true, function (next, done) {
    -  // calling next kicks off the next middleware in parallel
    -  next();
    -  doAsync(done);
    -});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    -  var err = new Error('something went wrong');
    -  next(err);
    -});
    -
    -// later...
    -
    -myModel.save(function (err) {
    -  console.log(err.message) // something went wrong
    -});
    -

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    diff --git a/docs/3.3.x/docs/middleware.jade b/docs/3.3.x/docs/middleware.jade deleted file mode 100644 index b9e9e9eca94..00000000000 --- a/docs/3.3.x/docs/middleware.jade +++ /dev/null @@ -1,74 +0,0 @@ -extends layout - -block content - h2 Middleware - p - | Middleware are functions which are passed control of flow during execution of - a(href="./api.html#document_Document-init") init - |, - a(href="./api.html#document_Document-validate") validate - |, - a(href="./api.html#model_Model-save") save - | and - a(href="./api.html#model_Model-remove") remove - | methods. - p - | There are two types of middleware, serial and parallel. - h4 Serial - p - | Serial middleware are executed one after another, when each middleware calls - code next - :js - var schema = new Schema(..); - schema.pre('save', function (next) { - // do stuff - next(); - }); - h4 Parallel - p - | Parallel middleware offer more fine-grained flow control. - :js - var schema = new Schema(..); - schema.pre('save', true, function (next, done) { - // calling next kicks off the next middleware in parallel - next(); - doAsync(done); - }); - p - | The hooked method, in this case - code save - |, will not be executed until - code done - | is called by each middleware. - h4 Use Cases - p - | Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas: - ul - li complex validation - li - | removing dependent documents - ul - li (removing a user removes all his blogposts) - li asynchronous defaults - li asynchronous tasks that a certain action triggers - ul - li triggering custom events - li notifications - h4 Error handling - :markdown - If any middleware calls `next` or `done` with an `Error` instance, the flow is interrupted, and the error is passed to the callback. - :js - schema.pre('save', function (next) { - var err = new Error('something went wrong'); - next(err); - }); - - // later... - - myModel.save(function (err) { - console.log(err.message) // something went wrong - }); - - h3#next Next Up - :markdown - Now that we've covered `middleware`, let's take a look at Mongoose's approach to faking JOINs with its query [population](/docs/populate.html) helper. diff --git a/docs/3.3.x/docs/migration.html b/docs/3.3.x/docs/migration.html deleted file mode 100644 index dec9b499446..00000000000 --- a/docs/3.3.x/docs/migration.html +++ /dev/null @@ -1,40 +0,0 @@ -Mongoose Migration Guide v3.3.1Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    - -

    Here are the removed methods are their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    - -

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    • are now strict by default.
    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    - -

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    - -
    • $inc
    • $increment
    • $decrement
    - -

    If you really want this behavior back, include the mongoose-number module in your project.

    - -

    A good alternative is to start using the new findAndModify helpers. -Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    -...
    -Inventory.findById(id, function (err, inventory) {
    -  if (err) return handleError(err);
    -  inventory.productCount.$decrement(7);
    -  inventory.save(function (err) {
    -    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    -    if (err) return handleError(err);
    -    res.send(inventory.productCount); // 3
    -  });
    -});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    -  if (err) return handleError(err);
    -  res.send(inventory.productCount); // 3
    -});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This change allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    More Info

    Related blog posts:

    - -
    diff --git a/docs/3.3.x/docs/migration.jade b/docs/3.3.x/docs/migration.jade deleted file mode 100644 index 988c6964f85..00000000000 --- a/docs/3.3.x/docs/migration.jade +++ /dev/null @@ -1,280 +0,0 @@ -extends layout - -block append style - style. - table td { - padding-right: 15px; - } - -block content - h2 Migrating from 2.x to 3.x - :markdown - Migrating from Mongoose 2.x to 3.x brings with it [several changes](https://github.com/LearnBoost/mongoose/blob/master/History.md) to be aware of: - - h3 Query clean-up - :markdown - Many methods of the [Query](./api.html#query-js) API were nothing but aliases and have been [removed](https://github.com/LearnBoost/mongoose/commit/1149804c) in an effort to keep Mongoose clean and focused on there being as close to [one way](http://www.python.org/dev/peps/pep-0020/) of doing things as possible. If you really love all that extra noise, you can bring most of it back with [this module](https://github.com/aheckmann/mongoose-v2-compat). - - Here are the removed methods are their still existing aliases: - table - thead - tr(style='text-align:left') - th Removed - th Alternative - tbody - tr - td - code query.run - td - code query.exec - tr - td - code query.$or - td - code query.or - tr - td - code query.$nor - td - code query.nor - tr - td - code query.$gt - td - code query.gt - tr - td - code query.$gte - td - code query.gte - tr - td - code query.$lt - td - code query.lt - tr - td - code query.$lte - td - code query.lte - tr - td - code query.$ne - td - code query.ne - tr - td - code query.$in - td - code query.in - tr - td - code query.$nin - td - code query.nin - tr - td - code query.$all - td - code query.all - tr - td - code query.$regex - td - code query.regex - tr - td - code query.$size - td - code query.size - tr - td - code query.$maxDistance - td - code query.maxDistance - tr - td - code query.$mod - td - code query.mod - tr - td - code query.$near - td - code query.near - tr - td - code query.$exists - td - code query.exists - tr - td - code query.$elemMatch - td - code query.elemMatch - tr - td - code query.$within - td - code query.within - tr - td - code query.$box - td - code query.box - tr - td - code query.$center - td - code query.center - tr - td - code query.$centerSphere - td - code query.centerSphere - tr - td - code query.$slice - td - code query.slice - tr - td - code query.notEqualTo - td - code query.ne - tr - td - code query.wherein - td - code query.within - tr - td - code query.asc - td - code - | query.sort - a(href="#asc") * - tr - td - code query.desc - td - code - | query.sort - a(href="#desc") * - tr - td - code query.fields - td - code - | query.select - a(href="#fields") * - - h4#asc query#asc - :markdown - The `asc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#desc query#desc - :markdown - The `desc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#sort query#sort - :markdown - The [sort](./api.html#query_Query-sort) method of [Queries](./api.html#query-js) now accepts slightly different arguments. Read the [docs](./api.html#query_Query-sort) to make sure your application is all set. - h4#fields query#fields - :markdown - The `fields` method of [Query](./api.html#query-js) has been removed, it being mostly an alias for the [select](./api.html#query_Query-select) method anyway. The `select` method has slightly different arguments so read the [docs](./api.html#query_Query-select) to make sure your application is all set. - - Because of the change to the `fields` method, the field selection argument for [query.populate](./api.html#query_Query-populate) and model methods like [findById](./api.html#model_Model-findById), [find](./api.html#model_Model-find), etc, is slightly different as well (no longer accepts arrays for example), so read the [docs](./api.html#query_Query-select) to make sure your application is all set. - - h3 Connecting to ReplicaSets - :markdown - To connect to a [ReplicaSet](http://www.mongodb.org/display/DOCS/Replica+Sets) you no longer use the separate `connectSet` or `createSetConnection` methods. Both [mongoose.connect](./api.html#index_Mongoose-connect) and [mongoose.createConnection](./api.html#index_Mongoose-createConnection) are now smart enough to just do the right thing with your connection string. If you really want to bring `connectSet` and `createSetConnection` back use [this module](https://github.com/aheckmann/mongoose-v2-compat). - - h3 Schemas - :markdown - - are now [strict](./guide.html#strict) by default. - - Arrays of [object literal](./subdocs.html#altsyntax) now creates document arrays instead of arrays of [Mixed](./schematypes.html#mixed). - - Indexes are now created in [background](./guide.html#autoIndex) by default. - - Index errors are now emitted on their model instead of the connection. See issue [#984](https://github.com/LearnBoost/mongoose/issues/984). - - h3#arrays Arrays - :markdown - - [pop](./api.html#types_array_MongooseArray-pop) is now fixed causing a $set of the entire array. - - [$pop](./api.html#types_array_MongooseArray-%24pop) is now fixed and behaves just as MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the last element of the array. - - [shift](./api.html#types_array_MongooseArray-shift) is now fixed causing a $set of the entire array. - - [$shift](./api.html#types_array_MongooseArray-%24shift) is now fixed and behaves just as a [MongoDB $pop -1](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the first element of array. - - `$unshift` was removed, use [unshift](./api.html#types_array_MongooseArray-unshift) instead. - - `$addToSet` was removed, use [addToSet](./api.html#types_array_MongooseArray-addToSet) instead. - - `$pushAll` was removed, use [push](./api.html#types_array_MongooseArray-push) instead. - - `$pull` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. - - `$pullAll` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. - - `doAtomics` was changed to the [hasAtomics](./api.html#types_array_MongooseArray-hasAtomics) private method - - h3#mongoosenumber Number type - :markdown - The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused [too many problems](https://groups.google.com/d/msg/mongoose-orm/syKlN2xL1EE/FfRFhEFj4KcJ) when doing comparisons and had other bad side-effects. - - With it out of the picture, the following helper methods of MongooseNumbers are now also gone: - - - $inc - - $increment - - $decrement - - If you really want this behavior back, include the [mongoose-number](https://github.com/aheckmann/mongoose-number) module in your project. - - A good alternative is to start using the new [findAndModify](./api.html#model_Model-findOneAndUpdate) [helpers](./api.html#model_Model-findOneAndRemove). - Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber: - :js - var inventorySchema = new Schema({ productCount: Number }); - ... - Inventory.findById(id, function (err, inventory) { - if (err) return handleError(err); - inventory.productCount.$decrement(7); - inventory.save(function (err) { - // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback); - if (err) return handleError(err); - res.send(inventory.productCount); // 3 - }); - }); - :markdown - With MongooseNumber out of the picture, we'll instead use the [Account.findByIdAndUpdate](./api.html#model_Model-findByIdAndUpdate) helper: - :js - Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) { - if (err) return handleError(err); - res.send(inventory.productCount); // 3 - }); - :markdown - The `findByIdAndUpdate` helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases. - - h3#documents Documents - :markdown - - `doc#commit` is now removed, use [doc.markModified](./api.html#document_Document-markModified) instead - - [doc#modifiedPaths](./api.html#document_Document-modifiedPaths) is now a method not a getter - - `doc.modified` is now removed, use [doc.isModified](./api.html#document_Document-isModified) instead - - h4#gettercasting getter casting - :markdown - Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue [#820](https://github.com/LearnBoost/mongoose/issues/820) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). - - h4#setterorder setter order - :markdown - Values being set no longer cast until _after_ all setters have been applied. Previously the value returned from each setter was cast _before_ passing it on to the next setter. This change allows more flexible processing of values in setters. See issue [#665](https://github.com/learnboost/mongoose/issues/665) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). - - h3#subdocs Subdocuments - :markdown - - `subdoc.parent` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parent). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). - - `subdoc.parentArray` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parentArray). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). - - h3#stringmatch String match validator - :markdown - The String SchemaType [match](./api.html#schema_string_SchemaString-match) validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the [required](./api.html#schematype_SchemaType-required) validator as well. See issue [#934](https://github.com/LearnBoost/mongoose/issues/934) and pull request [#935](https://github.com/LearnBoost/mongoose/pull/935). - - h3#version Versioning - :markdown - Documents are now transparently versioned. Read the in depth details [here](http://aaronheckmann.posterous.com/tag/versioning). - - h3#moreinfo More Info - :markdown - Related blog posts: - - - [Mongoose v3 released](http://aaronheckmann.posterous.com/mongoose-v3-released) - - [API changes](http://aaronheckmann.posterous.com/mongoose-v3-part-3-api-changes) - - [FindAndModify](http://aaronheckmann.posterous.com/mongoose-v3-part-2-findandmodify) diff --git a/docs/3.3.x/docs/models.html b/docs/3.3.x/docs/models.html deleted file mode 100644 index e507b8ab97b..00000000000 --- a/docs/3.3.x/docs/models.html +++ /dev/null @@ -1,32 +0,0 @@ -Mongoose Models v3.3.1Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var schema = new Schema({ name: 'string', size: 'string' });
    -var Tank = mongoose.model('Tank', schema);
    -
    -// or, if you are using separate connections
    -var db = mongoose.createConnection(..);
    -var Tank = db.model('Tank', schema);
    -

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = db.model('Tank', yourSchema);
    -
    -var small = new Tank({ size: 'small' });
    -small.save(function (err) {
    -  if (err) return handleError(err);
    -  // saved!
    -})
    -
    -// or
    -
    -Tank.create({ size: 'small' }, function (err) {
    -  if (err) return handleError(err);
    -  // saved!
    -})
    -

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    -  if (err) return handleError(err);
    -  // removed!
    -});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at Documents.

    diff --git a/docs/3.3.x/docs/models.jade b/docs/3.3.x/docs/models.jade deleted file mode 100644 index 105ef327803..00000000000 --- a/docs/3.3.x/docs/models.jade +++ /dev/null @@ -1,61 +0,0 @@ -extends layout - -block content - h2 Models - :markdown - [Models](./api.html#model-js) are fancy constructors compiled from our `Schema` definitions. Instances of these models represent [documents](./documents.html) which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models. - - h3 Compiling your first model - :js - var schema = new Schema({ name: 'string', size: 'string' }); - var Tank = mongoose.model('Tank', schema); - - // or, if you are using separate connections - var db = mongoose.createConnection(..); - var Tank = db.model('Tank', schema); - - h3 Constructing documents - :markdown - [Documents](./documents.html) are instances of our model. Creating them and saving to the database is easy: - :js - var Tank = db.model('Tank', yourSchema); - - var small = new Tank({ size: 'small' }); - small.save(function (err) { - if (err) return handleError(err); - // saved! - }) - - // or - - Tank.create({ size: 'small' }, function (err) { - if (err) return handleError(err); - // saved! - }) - - h3 Querying - :markdown - Finding documents is easy with Mongoose, which supports the [rich](http://www.mongodb.org/display/DOCS/Advanced+Queries) query syntax of MongoDB. Documents can be retreived using each `models` [find](./api.html#model_Model-find), [findById](./api.html#model_Model-findById), [findOne](./api.html#model_Model-findOne), or [where](./api.html#model_Model-where) static methods. - - :js - Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback); - :markdown - See the chapter on [querying](./queries.html) for more details on how to use the [Query](./api.html#query-js) api. - h3 Removing - :markdown - Models have a static `remove` method available for removing all documents matching `conditions`. - :js - Tank.remove({ size: 'large' }, function (err) { - if (err) return handleError(err); - // removed! - }); - h3 Updating - :markdown - Each `model` has its own `update` method for modifying documents in the database without returning them to your application. See the [API](./api.html#model_Model-update) docs for more detail. - h3 Yet more - :markdown - The [API docs](./api.html#model_Model) cover many additional methods available like [count](./api.html#model_Model-count), [mapReduce](./api.html#model_Model-mapReduce), [aggregate](./api.html#model_Model-aggregate), and more. - - h3#next Next Up - :markdown - Now that we've covered `Models`, let's take a look at [Documents](/docs/documents.html). diff --git a/docs/3.3.x/docs/plugins.html b/docs/3.3.x/docs/plugins.html deleted file mode 100644 index 74429a0022d..00000000000 --- a/docs/3.3.x/docs/plugins.html +++ /dev/null @@ -1,33 +0,0 @@ -Mongoose Plugins v3.3.1Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    - -

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    -module.exports = exports = function lastModifiedPlugin (schema, options) {
    -  schema.add({ lastMod: Date })
    -  
    -  schema.pre('save', function (next) {
    -    this.lastMod = new Date
    -    next()
    -  })
    -  
    -  if (options && options.index) {
    -    schema.path('lastMod').index(options.index)
    -  }
    -}
    -
    -// game-schema.js
    -var lastMod = require('./lastMod');
    -var Game = new Schema({ ... });
    -Game.plugin(lastMod, { index: true });
    -
    -// player-schema.js
    -var lastMod = require('./lastMod');
    -var Player = new Schema({ ... });
    -Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    diff --git a/docs/3.3.x/docs/plugins.jade b/docs/3.3.x/docs/plugins.jade deleted file mode 100644 index 4930fd8a46e..00000000000 --- a/docs/3.3.x/docs/plugins.jade +++ /dev/null @@ -1,42 +0,0 @@ -extends layout - -block content - h2 Plugins - :markdown - Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature. - - Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each `Schema`: - - :js - // lastMod.js - module.exports = exports = function lastModifiedPlugin (schema, options) { - schema.add({ lastMod: Date }) - - schema.pre('save', function (next) { - this.lastMod = new Date - next() - }) - - if (options && options.index) { - schema.path('lastMod').index(options.index) - } - } - - // game-schema.js - var lastMod = require('./lastMod'); - var Game = new Schema({ ... }); - Game.plugin(lastMod, { index: true }); - - // player-schema.js - var lastMod = require('./lastMod'); - var Player = new Schema({ ... }); - Player.plugin(lastMod); - :markdown - We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code. - h3 Community! - :markdown - Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. - - h3#next Next Up - :markdown - Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help [contribute](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md) to the continuing development of Mongoose itself. diff --git a/docs/3.3.x/docs/populate.html b/docs/3.3.x/docs/populate.html deleted file mode 100644 index 3d0a4de8e8a..00000000000 --- a/docs/3.3.x/docs/populate.html +++ /dev/null @@ -1,104 +0,0 @@ -Mongoose Query Population v3.3.1Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    - -

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    -  , Schema = mongoose.Schema
    -  
    -var PersonSchema = new Schema({
    -  name    : String,
    -  age     : Number,
    -  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    -});
    -
    -var StorySchema = new Schema({
    -  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    -  title    : String,
    -  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    -});
    -
    -var Story  = mongoose.model('Story', StorySchema);
    -var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    -
    -aaron.save(function (err) {
    -  if (err) return handleError(err);
    -  
    -  var story1 = new Story({
    -    title: "Once upon a timex.",
    -    _creator: aaron._id    // assign an ObjectId
    -  });
    -  
    -  story1.save(function (err) {
    -    if (err) return handleError(err);
    -    // thats it!
    -  });
    -})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    -.findOne({ title: /timex/ })
    -.populate('_creator')
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    -})
    -

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    - -

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    -.findOne({ title: /timex/i })
    -.populate('_creator', 'name') // only return the Persons name
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  
    -  console.log('The creator is %s', story._creator.name);
    -  // prints "The creator is Aaron"
    -  
    -  console.log('The creators age is %s', story._creator.age);
    -  // prints "The creators age is null'
    -})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    -.find(...)
    -.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    - -

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    -aaron.save();

    This allows us to perform a find and populate combo:

    Person
    -.findOne({ name: 'Aaron' })
    -.populate('stories') // only works if we pushed refs to children
    -.exec(function (err, person) {
    -  if (err) return handleError(err);
    -  console.log(person);
    -})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    -.find({ _creator: aaron._id })
    -.populate('_creator') // not really necessary
    -.exec(function (err, stories) {
    -  if (err) return handleError(err);
    -  console.log('The stories are an array: ', stories);
    -})
    -

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    -guille.save(function (err) {
    -  if (err) return handleError(err);
    -  
    -  story._creator = guille; // or guille._id
    -  
    -  story.save(function (err) {
    -    if (err) return handleError(err);
    -    
    -    Story
    -    .findOne({ title: /timex/i })
    -    .populate('_creator', 'name')
    -    .exec(function (err, story) {
    -      if (err) return handleError(err);
    -      
    -      console.log('The creator is %s', story._creator.name)
    -      // prints "The creator is Guillermo"
    -    })
    -  })
    -})
    -

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    -Story.findOne(..).populate('_creator', 'name age').exec(..);
    -
    -// this doesn't
    -Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
    -

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at connections.

    diff --git a/docs/3.3.x/docs/populate.jade b/docs/3.3.x/docs/populate.jade deleted file mode 100644 index 5443bbbcc28..00000000000 --- a/docs/3.3.x/docs/populate.jade +++ /dev/null @@ -1,164 +0,0 @@ -extends layout - -block content - h2 Query Population - :markdown - There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. - - `ObjectIds` can refer to another document in a collection within our database and be `populate()`d when querying: - :js - var mongoose = require('mongoose') - , Schema = mongoose.Schema - - var PersonSchema = new Schema({ - name : String, - age : Number, - stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] - }); - - var StorySchema = new Schema({ - _creator : { type: Schema.Types.ObjectId, ref: 'Person' }, - title : String, - fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }] - }); - - var Story = mongoose.model('Story', StorySchema); - var Person = mongoose.model('Person', PersonSchema); - :markdown - So far we've created two `models`. Our `Person` model has it's `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose in which model to look, in our case the `Story` model. All `_id`s we store here must be document _ids from the `Story` model. We also added a `_creator` `ObjectId` to our `Story` schema which refers to a single `Person`. - h3 Saving refs - :markdown - Saving refs to other documents works the same way you normally save objectids, just assign an `ObjectId`: - :js - var aaron = new Person({ name: 'Aaron', age: 100 }); - - aaron.save(function (err) { - if (err) return handleError(err); - - var story1 = new Story({ - title: "Once upon a timex.", - _creator: aaron._id // assign an ObjectId - }); - - story1.save(function (err) { - if (err) return handleError(err); - // thats it! - }); - }) - h3 Population - :markdown - So far we haven't done anything special. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator`: - :js - Story - .findOne({ title: /timex/ }) - .populate('_creator') - .exec(function (err, story) { - if (err) return handleError(err); - console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron" - }) - - :markdown - Populated paths are no longer set to their original `ObjectId`s, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. - - Arrays of `ObjectId` refs work the same way. Just call the [populate](./api.html#query_Query-populate) method on the query and an array of documents will be returned _in place_ of the `ObjectIds`. - - h3 Field selection - :markdown - What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: - :js - Story - .findOne({ title: /timex/i }) - .populate('_creator', 'name') // only return the Persons name - .exec(function (err, story) { - if (err) return handleError(err); - - console.log('The creator is %s', story._creator.name); - // prints "The creator is Aaron" - - console.log('The creators age is %s', story._creator.age); - // prints "The creators age is null' - }) - h3 Query conditions for populate - :markdown - What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them? - :js - Story - .find(...) - .populate('fans', null, { age: { $gte: 21 }}, { limit: 5 }) - :markdown - Done. `Conditions` and `options` for populate queries are passed as the third and fourth arguments respectively. - h3 Refs to children - :markdown - We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' on to `aaron.stories`. - - There are two perspectives to this story. First, it's nice to have `aaron` know which are his stories. - :js - aaron.stories.push(story1); - aaron.save(); - :markdown - This allows us to perform a `find` and `populate` combo: - :js - Person - .findOne({ name: 'Aaron' }) - .populate('stories') // only works if we pushed refs to children - .exec(function (err, person) { - if (err) return handleError(err); - console.log(person); - }) - :markdown - However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely `find()` the documents we are interested in. - :js - Story - .find({ _creator: aaron._id }) - .populate('_creator') // not really necessary - .exec(function (err, stories) { - if (err) return handleError(err); - console.log('The stories are an array: ', stories); - }) - - h3 Updating refs - :markdown - Now that we have a `story` we realized that the `_creator` was incorrect. We can update `ObjectId` refs the same as any other property through the magic of Mongoose's internal casting: - :js - var guille = new Person({ name: 'Guillermo' }); - guille.save(function (err) { - if (err) return handleError(err); - - story._creator = guille; // or guille._id - - story.save(function (err) { - if (err) return handleError(err); - - Story - .findOne({ title: /timex/i }) - .populate('_creator', 'name') - .exec(function (err, story) { - if (err) return handleError(err); - - console.log('The creator is %s', story._creator.name) - // prints "The creator is Guillermo" - }) - }) - }) - - h4 NOTE: - :markdown - The documents returned from calling [populate](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. - - h4 NOTE: - :markdown - _Field selection_ in v3 is slightly different than v2. Arrays of fields are no longer accepted. - - :js - // this works - Story.findOne(..).populate('_creator', 'name age').exec(..); - - // this doesn't - Story.findOne(..).populate('_creator', ['name', 'age']).exec(..); - - :markdown - See the [migration guide](./migration.html#fields) for more detail. - - h3#next Next Up - :markdown - Now that we've covered query population, let's take a look at [connections](/docs/connections.html). diff --git a/docs/3.3.x/docs/prior.html b/docs/3.3.x/docs/prior.html deleted file mode 100644 index 7968715028f..00000000000 --- a/docs/3.3.x/docs/prior.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose v3.3.1Fork me on GitHub

    Prior Release Documentation

    diff --git a/docs/3.3.x/docs/prior.jade b/docs/3.3.x/docs/prior.jade deleted file mode 100644 index 1ef7d088a72..00000000000 --- a/docs/3.3.x/docs/prior.jade +++ /dev/null @@ -1,8 +0,0 @@ -extends layout - -block content - h2 Prior Release Documentation - ul - each release in releases - li - a(href=release.url)= release.version diff --git a/docs/3.3.x/docs/production.html b/docs/3.3.x/docs/production.html deleted file mode 100644 index f7da97ec7e1..00000000000 --- a/docs/3.3.x/docs/production.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose Production v3.3.1Fork me on GitHub

    Mongoose In The Wild (add your project)

    • LearnBoost is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students.
    • Storify lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative.
    • Geeklist is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found.
    • ClickDummy is a rapid mockup prototyping application for designers and dummies.
    • Scotty App allows you to create data driven backends for your apps in minutes instead of weeks.
    • Bozuko is an exciting customer rewards program.
    • Call List helps you maintain a todo list for people you need to call.
    • Grow The Game Golf lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more.
    • nextdays lets you share plans with friends and discover what is happening around you.
    • AtticTV is Music Television (MTV) for the web.
    • LocalResponse helps marketers respond to real-time consumer intent.
    • Select Vids is a collection of amazing, funny, and creative videos for you to discover.
    • cldfy delivers mail to your app.
    • ShareLatex is a real-time LaTeX collaboration tool.
    • Cyborg Vision uses real-time facial recognition to identify your friends and show their information.
    • Wavo lets you express yourself through the songs you love.
    • seelio is a stage for college students to distinguish themselves and connect with companies.
    • TodayLaunch is a free dashboard for your social media accounts.
    • Stachify
    • Skim is a playful way to meet new people.
    • NuORDER online fashion wholesale for brands and buyers.
    • UPcload helps you find clothes that fit you when shopping online.
    • TreinoSmart is a system for gym and physical trainers.
    • ShoeJitsu lets you shop, compare, and share fashion.
    • Kyyti is a meeting place for rides.
    • Nimble Quiz allows you to quickly create and manage simple multiple choice quizzes.
    • Fur Baby Rescue provides a temporary, safe home for cats, dogs, puppies and kittens.
    • McDonalds food, your questions answered.
    • SquadSheet is a sports app packed with fun and powerful social features.
    • VeriWalk is live GPS dog walking software.
    • DashKu lets you build real-time dashboards and widgets using HTML, CSS, and JavaScript.
    • First Impression helps singles find fun, safe and exciting dates.
    • Muffle is a suite of Twitter reputation management tools.
    • Zootify is a live, real-time YouTube party app.
    diff --git a/docs/3.3.x/docs/production.jade b/docs/3.3.x/docs/production.jade deleted file mode 100644 index da5c5f9d13e..00000000000 --- a/docs/3.3.x/docs/production.jade +++ /dev/null @@ -1,11 +0,0 @@ -extends layout - -block content - h2 - | Mongoose In The Wild - a(href='mailto:aaronheckmann+github@gmail.com?subject=Please add my project to mongoosejs.com', title='add/remove your project') (add your project) - ul.inthewild - each img in images - li - a(href=img.url, title=img.title + ' ' + img.desc) - img(src="images/apps/" + img.src + ".png", alt=img.title + ' ' + img.desc) diff --git a/docs/3.3.x/docs/queries.html b/docs/3.3.x/docs/queries.html deleted file mode 100644 index d2165946657..00000000000 --- a/docs/3.3.x/docs/queries.html +++ /dev/null @@ -1,41 +0,0 @@ -Mongoose Queries v3.3.1Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    - -

    When a callback function:

    - -
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    - -

    Let's take a look at what happens when passing a callback:

    var Person = db.model('Person', yourSchema);
    -
    -// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    -Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    -  if (err) return handleError(err);
    -  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    Here we see that the query was executed immediately and the results passed to our callback. -Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    -var query = Person.findOne({ 'name.last': 'Ghost' });
    -
    -// selecting the `name` and `occupation` fields
    -query.select('name occupation');
    -
    -// execute the query at a later time
    -query.exec(function (err, person) {
    -  if (err) return handleError(err);
    -  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    -.find({ occupation: /host/ })
    -.where('name.last').equals('Ghost')
    -.where('age').gt(17).lt(66)
    -.where('likes').in(['vaporizing', 'talking'])
    -.limit(10)
    -.sort('-occupation')
    -.select('name occupation')
    -.exec(callback);
    -

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    diff --git a/docs/3.3.x/docs/queries.jade b/docs/3.3.x/docs/queries.jade deleted file mode 100644 index 68c529efe25..00000000000 --- a/docs/3.3.x/docs/queries.jade +++ /dev/null @@ -1,62 +0,0 @@ -extends layout - -block content - h2 Queries - :markdown - Documents can be retrieved through several static helper methods of [models](./models.html). - :markdown - Any [model](./api.html#model_Model) method which [involves](./api.html#model_Model-find) [specifying](./api.html#model_Model-findById) [query](./api.html#model_Model-count) [conditions](./api.html#model_Model-update) can be executed two ways: - - When a `callback` function: - - - is passed, the operation will be executed immediately with the results passed to the callback. - - is not passed, an instance of [Query](./api.html#query-js) is returned, which provides a special `QueryBuilder` interface for you. - - Let's take a look at what happens when passing a `callback`: - :js - var Person = db.model('Person', yourSchema); - - // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields - Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { - if (err) return handleError(err); - console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. - }) - :markdown - Here we see that the query was executed immediately and the results passed to our callback. - Now let's look at what happens when no `callback` is passed: - :js - // find each person with a last name matching 'Ghost' - var query = Person.findOne({ 'name.last': 'Ghost' }); - - // selecting the `name` and `occupation` fields - query.select('name occupation'); - - // execute the query at a later time - query.exec(function (err, person) { - if (err) return handleError(err); - console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. - }) - :markdown - An instance of [Query](./api.html#query-js) was returned which allows us to build up our query. Taking this example further: - :js - Person - .find({ occupation: /host/ }) - .where('name.last').equals('Ghost') - .where('age').gt(17).lt(66) - .where('likes').in(['vaporizing', 'talking']) - .limit(10) - .sort('-occupation') - .select('name occupation') - .exec(callback); - - h3#refs References to other documents - :markdown - There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. Read more [here](./populate.html). - - h3 Streaming - :markdown - Queries can be [streamed](http://nodejs.org/api/stream.html) from MongoDB to your application as well. Simply call the query's [stream](./api.html#query_Query-stream) method instead of [exec](./api.html#query_Query-exec) to return an instance of [QueryStream](./api.html#querystream_QueryStream). - - h3#next Next Up - :markdown - Now that we've covered `Queries`, let's take a look at [validation](/docs/validation.html). diff --git a/docs/3.3.x/docs/releases b/docs/3.3.x/docs/releases deleted file mode 100644 index f48a582a3ee..00000000000 --- a/docs/3.3.x/docs/releases +++ /dev/null @@ -1,5 +0,0 @@ -3.2.x -3.1.x -3.0.x -2.8.x -2.7.x diff --git a/docs/3.3.x/docs/schematypes.html b/docs/3.3.x/docs/schematypes.html deleted file mode 100644 index f314761f410..00000000000 --- a/docs/3.3.x/docs/schematypes.html +++ /dev/null @@ -1,67 +0,0 @@ -Mongoose SchemaTypes v3.3.1Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    -  name:    String,
    -  binary:  Buffer,
    -  living:  Boolean,
    -  updated: { type: Date, default: Date.now },
    -  age:     { type: Number, min: 18, max: 65 },
    -  mixed:   Schema.Types.Mixed,
    -  _someId: Schema.Types.ObjectId,
    -  array:      [],
    -  ofString:   [String],
    -  ofNumber:   [Number],
    -  ofDates:    [Date],
    -  ofBuffer:   [Buffer],
    -  ofBoolean:  [Boolean],
    -  ofMixed:    [Schema.Types.Mixed],
    -  ofObjectId: [Schema.Types.ObjectId],
    -  nested: {
    -    stuff: { type: String, lowercase: true, trim: true }
    -  }
    -})
    -
    -// example use
    -
    -var Thing = mongoose.model('Thing', schema);
    -
    -var m = new Thing;
    -m.name = 'Statue of Liberty';
    -m.age = 125;
    -m.updated = new Date;
    -m.binary = new Buffer(0);
    -m.living = false;
    -m.mixed = {[ any: { thing: 'i want' } ]};
    -m.markModified('mixed');
    -m._someId = new mongoose.Types.ObjectId;
    -m.array.push(1);
    -m.ofString.push("strings!");
    -m.ofNumber.unshift(1,2,3,4);
    -m.ofDates.addToSet(new Date);
    -m.ofBuffer.pop();
    -m.ofMixed = [1, [], 'three', { four: 5 }];
    -m.nested.stuff = 'good';
    -m.save(callback);
    -

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    -var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    -person.markModified('anything');
    -person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    -var ObjectId = mongoose.Schema.Types.ObjectId;
    -var Car = new Schema({ driver: ObjectId });
    -// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    -var ToyBox = new Schema({
    -  toys: [ToySchema],
    -  buffers: [Buffer],
    -  string:  [String],
    -  numbers: [Number]
    -  // ... etc
    -});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    -var Empty2 = new Schema({ any: Array });
    -var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    -var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Models.

    diff --git a/docs/3.3.x/docs/schematypes.jade b/docs/3.3.x/docs/schematypes.jade deleted file mode 100644 index afa3c3276fe..00000000000 --- a/docs/3.3.x/docs/schematypes.jade +++ /dev/null @@ -1,146 +0,0 @@ -extends layout - -block content - h2 SchemaTypes - p - | SchemaTypes handle definition of path - a(href="./api.html#schematype_SchemaType-default") defaults - |, - a(href="./api.html#schematype_SchemaType-validate") validation - |, - a(href="./api.html#schematype_SchemaType-get") getters - |, - a(href="./api.html#schematype_SchemaType-set") setters - |, - a(href="./api.html#schematype_SchemaType-select") field selection defaults - | for - a(href="./api.html#query-js") queries - | and other general characteristics for - a(href="./api.html#schema-string-js") Strings - | and - a(href="./api.html#schema-number-js") Numbers - |. Check out their respective API documentation for more detail. - p - | Following are all valid - a(href="./api.html#schema_Schema-Types") Schema Types - |. - ul - li String - li Number - li Date - li Buffer - li Boolean - li Mixed - li ObjectId - li Array - h4 Example - :js - var schema = new Schema({ - name: String, - binary: Buffer, - living: Boolean, - updated: { type: Date, default: Date.now }, - age: { type: Number, min: 18, max: 65 }, - mixed: Schema.Types.Mixed, - _someId: Schema.Types.ObjectId, - array: [], - ofString: [String], - ofNumber: [Number], - ofDates: [Date], - ofBuffer: [Buffer], - ofBoolean: [Boolean], - ofMixed: [Schema.Types.Mixed], - ofObjectId: [Schema.Types.ObjectId], - nested: { - stuff: { type: String, lowercase: true, trim: true } - } - }) - - // example use - - var Thing = mongoose.model('Thing', schema); - - var m = new Thing; - m.name = 'Statue of Liberty'; - m.age = 125; - m.updated = new Date; - m.binary = new Buffer(0); - m.living = false; - m.mixed = {[ any: { thing: 'i want' } ]}; - m.markModified('mixed'); - m._someId = new mongoose.Types.ObjectId; - m.array.push(1); - m.ofString.push("strings!"); - m.ofNumber.unshift(1,2,3,4); - m.ofDates.addToSet(new Date); - m.ofBuffer.pop(); - m.ofMixed = [1, [], 'three', { four: 5 }]; - m.nested.stuff = 'good'; - m.save(callback); - - h3 Usage notes: - h4#mixed Mixed - p An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent: - :js - var Any = new Schema({ any: {} }); - var Any = new Schema({ any: Schema.Types.Mixed }); - p - | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the - code .markModified(path) - | method of the document passing the path to the Mixed type you just changed. - :js - person.anything = { x: [3, 4, { y: "changed" }] }; - person.markModified('anything'); - person.save(); // anything will now get saved - h4#objectids ObjectIds - p - | To specify a type of ObjectId, use - code Schema.Types.ObjectId - | in your declaration. - :js - var mongoose = require('mongoose'); - var ObjectId = mongoose.Schema.Types.ObjectId; - var Car = new Schema({ driver: ObjectId }); - // or just Schema.ObjectId for backwards compatibility with v2 - h4#arrays Arrays - p - | Provide creation of arrays of - a(href="./api.html#schema_Schema-Types") SchemaTypes - | or - a(href="./subdocs.html") Sub-Documents - |. - :js - var ToySchema = new Schema({ name: String }); - var ToyBox = new Schema({ - toys: [ToySchema], - buffers: [Buffer], - string: [String], - numbers: [Number] - // ... etc - }); - p - | Note: specifying an empty array is equivalent to - code Mixed - |. The following all create arrays of - code Mixed - |: - :js - var Empty1 = new Schema({ any: [] }); - var Empty2 = new Schema({ any: Array }); - var Empty3 = new Schema({ any: [Schema.Types.Mixed] }); - var Empty4 = new Schema({ any: [{}] }); - h3#customtypes Creating Custom Types - p - | Mongoose can also be extended with custom SchemaTypes. Search the - a(href="http://plugins.mongoosejs.com") plugins - | site for compatible types like - a(href="https://github.com/aheckmann/mongoose-long") mongoose-long - | and - a(href="https://github.com/aheckmann/mongoose-number") other - | - a(href="https://github.com/bnoguchi/mongoose-types") types - |. - - h3#next Next Up - :markdown - Now that we've covered `SchemaTypes`, let's take a look at [Models](/docs/models.html). diff --git a/docs/3.3.x/docs/source/_docs b/docs/3.3.x/docs/source/_docs deleted file mode 100644 index 628139bb801..00000000000 --- a/docs/3.3.x/docs/source/_docs +++ /dev/null @@ -1,16292 +0,0 @@ - -### lib/collection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var STATES = require('./connectionstate')", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "require('./connectionstate')", - "string": "STATES" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the collection" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "conn", - "description": "A MongooseConnection instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "optional collection options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", - "summary": "

    Abstract Collection constructor

    ", - "body": "

    This is the base class that drivers inherit from and implement.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", - "ctx": { - "type": "function", - "name": "Collection", - "string": "Collection()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "name" - } - ], - "description": { - "full": "

    The collection name

    ", - "summary": "

    The collection name

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.name;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "conn" - } - ], - "description": { - "full": "

    The Connection instance

    ", - "summary": "

    The Connection instance

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.conn;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the database connects

    ", - "summary": "

    Called when the database connects

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onOpen", - "string": "Collection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the database disconnects

    ", - "summary": "

    Called when the database disconnects

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onClose", - "string": "Collection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the method to queue" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method when executed" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Queues a method for later execution when its
    database connection opens.

    ", - "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "addQueue", - "string": "Collection.prototype.addQueue()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes all queued methods and clears the queue.

    ", - "summary": "

    Executes all queued methods and clears the queue.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "doQueue", - "string": "Collection.prototype.doQueue()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "ensureIndex", - "string": "Collection.prototype.ensureIndex()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findAndModify", - "string": "Collection.prototype.findAndModify()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findOne", - "string": "Collection.prototype.findOne()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "find", - "string": "Collection.prototype.find()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "insert", - "string": "Collection.prototype.insert()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "save", - "string": "Collection.prototype.save()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "update", - "string": "Collection.prototype.update()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "getIndexes", - "string": "Collection.prototype.getIndexes()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "mapReduce", - "string": "Collection.prototype.mapReduce()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Collection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Collection", - "string": "module.exports" - } - } -] -### lib/connection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , assert =require('assert')", - "ctx": { - "type": "declaration", - "name": "url", - "value": "require('url')", - "string": "url" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Protocol prefix regexp.

    ", - "summary": "

    Protocol prefix regexp.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", - "ctx": { - "type": "declaration", - "name": "rgxProtocol", - "value": "/^(?:.)+:\\/\\//", - "string": "rgxProtocol" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "a mongoose instance" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." - }, - { - "type": "event", - "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." - }, - { - "type": "event", - "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." - }, - { - "type": "event", - "string": "`disconnecting`: Emitted when `connection.close()` was executed." - }, - { - "type": "event", - "string": "`disconnected`: Emitted after getting disconnected from the db." - }, - { - "type": "event", - "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." - }, - { - "type": "event", - "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." - }, - { - "type": "event", - "string": "`error`: Emitted when an error occurs on this connection." - }, - { - "type": "event", - "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", - "summary": "

    Connection constructor

    ", - "body": "

    For practical reasons, a Connection equals a Db.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", - "ctx": { - "type": "function", - "name": "Connection", - "string": "Connection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter

    ", - "summary": "

    Inherit from EventEmitter

    ", - "body": "" - }, - "ignore": true, - "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Connection", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Connection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readyState" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", - "summary": "

    Connection ready state

    ", - "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" - }, - { - "tags": [ - { - "type": "property", - "string": "collections" - } - ], - "description": { - "full": "

    A hash of the collections associated with this connection

    ", - "summary": "

    A hash of the collections associated with this connection

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collections;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

    The mongodb.Db instance, set when the connection is opened

    ", - "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.db;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "connection_string", - "description": "mongodb://uri or the host to which you are connecting" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[port]", - "description": "database port" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    ", - "summary": "

    Opens the connection to MongoDB.

    ", - "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n uri = url.parse(host);\n host = uri.hostname;\n port = uri.port || 27017;\n database = uri.pathname && uri.pathname.replace(/\\//g, '');\n }\n\n this.options = this.defaultOptions(options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing database name.'), callback);\n return this;\n }\n\n // handle authentication\n if (uri && uri.auth) {\n var auth = uri.auth.split(':');\n this.user = auth[0];\n this.pass = auth[1];\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n // user/pass options\n } else if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "open", - "string": "Connection.prototype.open()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "uris", - "description": "comma-separated mongodb:// `URI`s" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name if not included in `uris`" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "passed to the internal driver" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connects to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    ", - "summary": "

    Connects to a replica set.

    ", - "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n var uris = uris.split(',')\n , self = this;\n\n switch (arguments.length) {\n case 3:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'object':\n callback = options;\n options = database;\n database = null;\n break;\n }\n\n if ('function' === typeof options) {\n callback = options;\n options = {};\n }\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n this.options = options = this.defaultOptions(options);\n\n if (uris.length < 2) {\n this.error(new Error('Please provide comma-separated URIs'), callback);\n return this;\n }\n\n this.replica = true;\n this.host = [];\n this.port = [];\n\n uris.forEach(function (uri) {\n // handle missing protocols\n if (!rgxProtocol.test(uri))\n uri = 'mongodb://' + uri;\n\n var uri = url.parse(uri);\n\n self.host.push(uri.hostname);\n self.port.push(uri.port || 27017);\n\n if (!self.name && uri.pathname && uri.pathname.replace(/\\//g, ''))\n self.name = uri.pathname.replace(/\\//g, '');\n\n if (!self.user && uri.auth) {\n var auth = uri.auth.split(':');\n self.user = auth[0];\n self.pass = auth[1];\n }\n });\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "openSet", - "string": "Connection.prototype.openSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "optional" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", - "summary": "

    error

    ", - "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "error", - "string": "Connection.prototype.error()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", - "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "_open", - "string": "Connection.prototype._open()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection is opened

    ", - "summary": "

    Called when the connection is opened

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onOpen", - "string": "Connection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "self" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Closes the connection

    ", - "summary": "

    Closes the connection

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "close", - "string": "Connection.prototype.close()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection closes

    ", - "summary": "

    Called when the connection closes

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onClose", - "string": "Connection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "of the collection" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional collection options" - }, - { - "type": "return", - "types": [ - "Collection" - ], - "description": "collection instance" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Retrieves a collection, creating it if not cached.

    ", - "summary": "

    Retrieves a collection, creating it if not cached.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "collection", - "string": "Connection.prototype.collection()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "the model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "a schema. necessary when defining a model" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name of mongodb collection (optional) if not given it will be induced from model name" - }, - { - "type": "see", - "local": "Mongoose#model #index_Mongoose-model", - "visibility": "Mongoose#model" - }, - { - "type": "return", - "types": [ - "Model" - ], - "description": "The compiled model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    ", - "summary": "

    Defines or retrieves a model.

    ", - "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.model = function (name, schema, collection) {\n if (!this.models[name]) {\n var model = this.base.model(name, schema, collection, true)\n , Model\n\n if (this != model.prototype.db) {\n // subclass model using this connection and collection name\n Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model))\n return new Model(doc, fields, skipId);\n model.call(this, doc, fields, skipId);\n };\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = this;\n\n // collection name discovery\n if ('string' === typeof schema) {\n collection = schema;\n }\n\n if (!collection) {\n collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);\n }\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n Model.prototype.collection = this.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n }\n\n this.models[name] = Model || model;\n }\n\n return this.models[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "model", - "string": "Connection.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "level", - "description": "either off (0), slow (1), or all (2)" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[ms]", - "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Set profiling level.

    ", - "summary": "

    Set profiling level.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "setProfiling", - "string": "Connection.prototype.setProfiling()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Prepares default connection options.

    ", - "summary": "

    Prepares default connection options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.defaultOptions = function (options) {\n var o = options || {};\n\n o.server = o.server || {};\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n o.db || (o.db = {});\n o.db.forceServerObjectId = false;\n\n // TODO default to true once the driver is fixed\n if (!('safe' in o.db)) o.db.safe = false;\n\n return o;\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "defaultOptions", - "string": "Connection.prototype.defaultOptions()" - } - }, - { - "tags": [], - "description": { - "full": "

    Noop.

    ", - "summary": "

    Noop.

    ", - "body": "" - }, - "ignore": true, - "code": "function noop () {}", - "ctx": { - "type": "function", - "name": "noop", - "string": "noop()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", - "ctx": { - "type": "property", - "receiver": "Connection", - "name": "STATES", - "value": "STATES", - "string": "Connection.STATES" - } - } -] -### lib/connectionstate.js -[ - { - "tags": [], - "description": { - "full": "

    Connection states

    ", - "summary": "

    Connection states

    ", - "body": "" - }, - "ignore": true, - "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "module.exports = exports = Object.create(null)", - "string": "STATES" - } - } -] -### lib/document.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray\n , MongooseArray", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the values to set" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "the fields which were selected in the query returning this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "bool, should we auto create an ObjectId _id" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." - }, - { - "type": "event", - "string": "`save`: Emitted when the document is successfully saved" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Document constructor.

    ", - "summary": "

    Document constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", - "ctx": { - "type": "function", - "name": "Document", - "string": "Document()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Document.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Document.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "schema" - } - ], - "description": { - "full": "

    The documents schema.

    ", - "summary": "

    The documents schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.schema;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "isNew" - } - ], - "description": { - "full": "

    Boolean flag specifying if the document is new.

    ", - "summary": "

    Boolean flag specifying if the document is new.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isNew;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "local": "Schema options /docs/guide.html#options", - "visibility": "Schema" - }, - { - "type": "property", - "string": "id" - } - ], - "description": { - "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", - "summary": "

    The string version of this documents _id.

    ", - "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.id;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "errors" - } - ], - "description": { - "full": "

    Hash containing current validation errors.

    ", - "summary": "

    Hash containing current validation errors.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.errors;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Builds the default doc structure

    ", - "summary": "

    Builds the default doc structure

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_buildDoc", - "string": "Document.prototype._buildDoc()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", - "summary": "

    Initializes the document without setters or marking anything modified.

    ", - "body": "

    Called internally after a document is returned from mongodb.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init');\n if (fn) fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "init", - "string": "Document.prototype.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "self", - "description": "document instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "raw mongodb doc" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "object we are initializing" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Init helper.

    ", - "summary": "

    Init helper.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", - "ctx": { - "type": "function", - "name": "init", - "string": "init()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", - "summary": "

    Stores the current values of the shard keys.

    ", - "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_storeShard", - "string": "Document.prototype._storeShard()" - } - }, - { - "tags": [], - "description": { - "full": "

    Set up middleware support

    ", - "summary": "

    Set up middleware support

    ", - "body": "" - }, - "ignore": true, - "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    ", - "summary": "

    Sends an update command with this document _id as the query selector.

    ", - "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "update", - "string": "Document.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "path", - "description": "path or object of key/vals to set" - }, - { - "type": "param", - "types": [ - "Any" - ], - "name": "val", - "description": "the value to set" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for \"on-the-fly\" attributes" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optionally specify options that modify the behavior of the set" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    ", - "summary": "

    Sets the value of a path, or many paths.

    ", - "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.set = function (path, val, type, options) {\n if (type && 'Object' == type.constructor.name) {\n options = type;\n type = undefined;\n }\n\n var merge = options && options.merge\n , adhoc = type && true !== type\n , constructing = true === type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n if (null != path[key] && 'Object' === path[key].constructor.name\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n pathtype = this.schema.pathType(prefix + key);\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n if (!merge) this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "set", - "string": "Document.prototype.set()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determine if we should mark this change as modified.

    ", - "summary": "

    Determine if we should mark this change as modified.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._shouldModify = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n if (this.isNew) return true;\n if (this.isDirectModified(pathToMark)) return false;\n\n if (undefined === val && !this.isSelected(path)) {\n // when a path is not selected in a query, its initial\n // value will be undefined.\n return true;\n }\n\n if (undefined === val && path in this._activePaths.states.default) {\n // we're just unsetting the default value which was never saved\n return false;\n }\n\n if (!deepEqual(val, priorVal || this.get(path))) {\n return true;\n }\n\n if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n return true;\n }\n\n return false;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_shouldModify", - "string": "Document.prototype._shouldModify()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", - "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._set = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n var shouldModify = this._shouldModify.apply(this, arguments);\n\n if (shouldModify) {\n this.markModified(pathToMark, val);\n\n // handle directly setting arrays (gh-1126)\n MongooseArray || (MongooseArray = require('./types/array'));\n if (val instanceof MongooseArray) {\n val._registerAtomic('$set', val);\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_set", - "string": "Document.prototype._set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Gets a raw value from a path (no getters)

    ", - "summary": "

    Gets a raw value from a path (no getters)

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "getValue", - "string": "Document.prototype.getValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", - "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "setValue", - "string": "Document.prototype.setValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for on-the-fly attributes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", - "summary": "

    Returns the value of a path.

    ", - "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "get", - "string": "Document.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns the schematype for the given path.

    ", - "summary": "

    Returns the schematype for the given path.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_path", - "string": "Document.prototype._path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to mark modified" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", - "summary": "

    Marks the path as having pending changes to write to the db.

    ", - "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "markModified", - "string": "Document.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "function to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope with which to call fn" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", - "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "try", - "string": "Document.prototype.try()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the list of paths that have been modified.

    ", - "summary": "

    Returns the list of paths that have been modified.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "modifiedPaths", - "string": "Document.prototype.modifiedPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", - "summary": "

    Returns true if this document was modified, else false.

    ", - "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isModified", - "string": "Document.prototype.isModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", - "summary": "

    Returns true if path was directly set and modified, else false.

    ", - "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isDirectModified", - "string": "Document.prototype.isDirectModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Checks if path was initialized.

    ", - "summary": "

    Checks if path was initialized.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isInit", - "string": "Document.prototype.isInit()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", - "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", - "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isSelected", - "string": "Document.prototype.isSelected()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "cb", - "description": "called after validation completes, passing an error if one occurred" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", - "summary": "

    Executes registered validation rules for this document.

    ", - "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n paths = paths.concat(Object.keys(this._activePaths.states.default));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n cb(err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "validate", - "string": "Document.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "the error which states the reason `path` was invalid" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks a path as invalid, causing validation to fail.

    ", - "summary": "

    Marks a path as invalid, causing validation to fail.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "invalidate", - "string": "Document.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Resets the internal modified state of this document.

    ", - "summary": "

    Resets the internal modified state of this document.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n })\n .forEach(function (array) {\n var i = array.length;\n while (i--) {\n var doc = array[i];\n if (!doc) continue;\n doc._reset();\n }\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_reset", - "string": "Document.prototype._reset()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns this documents dirty paths / vals.

    ", - "summary": "

    Returns this documents dirty paths / vals.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_dirty", - "string": "Document.prototype._dirty()" - } - }, - { - "tags": [], - "description": { - "full": "

    Compiles schemas.

    ", - "summary": "

    Compiles schemas.

    ", - "body": "" - }, - "ignore": true, - "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", - "ctx": { - "type": "function", - "name": "compile", - "string": "compile()" - } - }, - { - "tags": [], - "description": { - "full": "

    Defines the accessor named prop on the incoming prototype.

    ", - "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", - "body": "" - }, - "ignore": true, - "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", - "ctx": { - "type": "function", - "name": "define", - "string": "define()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Assigns/compiles schema into this documents prototype.

    ", - "summary": "

    Assigns/compiles schema into this documents prototype.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_setSchema", - "string": "Document.prototype._setSchema()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register default hooks

    ", - "summary": "

    Register default hooks

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n if (error) return;\n\n // handle sparse arrays by using for loop vs array.forEach\n // which skips the sparse elements\n\n var len = array.length\n subdocs += len;\n\n for (var i = 0; i < len; ++i) {\n if (error) break;\n\n var doc = array[i];\n if (!doc) {\n --subdocs || next();\n continue;\n }\n\n doc.save(handleSave);\n }\n });\n\n function handleSave (err) {\n if (error) return;\n\n if (err) {\n self._validationError = undefined;\n return next(error = err);\n }\n\n --subdocs || next();\n }\n\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_registerHooks", - "string": "Document.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Registers an error

    ", - "summary": "

    Registers an error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_error", - "string": "Document.prototype._error()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes methods queued from the Schema definition

    ", - "summary": "

    Executes methods queued from the Schema definition

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_doQueue", - "string": "Document.prototype._doQueue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "js object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Converts this document into a plain javascript object

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    ", - "summary": "

    Converts this document into a plain javascript object

    ", - "body": "

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n if (true === options.transform) {\n var opts = options.json\n ? this.schema.options.toJSON\n : this.schema.options.toObject;\n if (opts) {\n options.transform = opts.transform;\n }\n }\n\n if ('function' == typeof options.transform) {\n var xformed = options.transform(this, ret, options);\n if ('undefined' != typeof xformed) ret = xformed;\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toObject", - "string": "Document.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "json", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "either `virtuals` or `paths`" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "`json`" - } - ], - "description": { - "full": "

    Applies virtuals properties to json.

    ", - "summary": "

    Applies virtuals properties to json.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", - "ctx": { - "type": "function", - "name": "applyGetters", - "string": "applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "same options as [Document#toObject](#document_Document-toObject)" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "see", - "local": "Document#toObject #document_Document-toObject", - "visibility": "Document#toObject" - }, - { - "type": "", - "string": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    \n\n

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", - "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", - "body": "

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toJSON", - "string": "Document.prototype.toJSON()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "inspect", - "string": "Document.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "toString" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toString = Document.prototype.inspect;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "toString", - "value": "Document.prototype.inspect", - "string": "Document.prototypetoString" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "a document to compare" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", - "summary": "

    Returns true if the Document stores the same data as doc.

    ", - "body": "

    Documents are considered equal when they have matching _ids.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "equals", - "string": "Document.prototype.equals()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", - "ctx": { - "type": "property", - "receiver": "Document", - "name": "ValidationError", - "value": "ValidationError", - "string": "Document.ValidationError" - } - } -] -### lib/drivers/node-mongodb-native/binary.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require('mongodb').BSONPure.Binary", - "string": "Binary" - } - } -] -### lib/drivers/node-mongodb-native/collection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", - "ctx": { - "type": "declaration", - "name": "MongooseCollection", - "value": "require('../../collection')", - "string": "MongooseCollection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Collection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", - "summary": "

    A node-mongodb-native collection implementation.

    ", - "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", - "ctx": { - "type": "function", - "name": "NativeCollection", - "string": "NativeCollection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from abstract Collection.

    ", - "summary": "

    Inherit from abstract Collection.

    ", - "body": "" - }, - "ignore": true, - "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "__proto__", - "value": "MongooseCollection.prototype", - "string": "NativeCollection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection opens.

    ", - "summary": "

    Called when the connection opens.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onOpen", - "string": "NativeCollection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection closes

    ", - "summary": "

    Called when the connection closes

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onClose", - "string": "NativeCollection.prototype.onClose()" - } - }, - { - "tags": [], - "description": { - "full": "

    Copy the collection methods and make them subject to queues

    ", - "summary": "

    Copy the collection methods and make them subject to queues

    ", - "body": "" - }, - "ignore": true, - "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" - }, - { - "tags": [], - "description": { - "full": "

    Debug print helper

    ", - "summary": "

    Debug print helper

    ", - "body": "" - }, - "ignore": true, - "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", - "ctx": { - "type": "function", - "name": "print", - "string": "print()" - } - }, - { - "tags": [], - "description": { - "full": "

    Debug print helper

    ", - "summary": "

    Debug print helper

    ", - "body": "" - }, - "ignore": true, - "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if ('Date' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", - "ctx": { - "type": "function", - "name": "format", - "string": "format()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "method", - "string": "getIndexes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Retreives information about this collections indexes.

    ", - "summary": "

    Retreives information about this collections indexes.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "getIndexes", - "value": "NativeCollection.prototype.indexInformation", - "string": "NativeCollection.prototypegetIndexes" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeCollection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeCollection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/connection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", - "ctx": { - "type": "declaration", - "name": "MongooseConnection", - "value": "require('../../connection')", - "string": "MongooseConnection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Connection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A node-mongodb-native connection implementation.

    ", - "summary": "

    A node-mongodb-native connection implementation.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", - "ctx": { - "type": "function", - "name": "NativeConnection", - "string": "NativeConnection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Connection.

    ", - "summary": "

    Inherits from Connection.

    ", - "body": "" - }, - "ignore": true, - "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeConnection", - "name": "__proto__", - "value": "MongooseConnection.prototype", - "string": "NativeConnection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Opens the connection to MongoDB.

    ", - "summary": "

    Opens the connection to MongoDB.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, Number(this.port), this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpen", - "string": "NativeConnection.prototype.doOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - } - ], - "description": { - "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", - "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", - "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , ports = this.port\n , self = this\n\n this.host.forEach(function (host, i) {\n servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));\n });\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpenSet", - "string": "NativeConnection.prototype.doOpenSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Closes the connection

    ", - "summary": "

    Closes the connection

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doClose", - "string": "NativeConnection.prototype.doClose()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeConnection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeConnection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/objectid.js -[ - { - "tags": [ - { - "type": "constructor", - "string": "NodeMongoDbObjectId" - }, - { - "type": "see", - "local": "ObjectId", - "visibility": "ObjectId" - } - ], - "description": { - "full": "

    node-mongodb-native ObjectId

    ", - "summary": "

    node-mongodb-native ObjectId

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require('mongodb').BSONPure.ObjectID", - "string": "ObjectId" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", - "ctx": { - "type": "declaration", - "name": "ObjectIdToString", - "value": "ObjectId.toString.bind(ObjectId)", - "string": "ObjectIdToString" - } - } -] -### lib/error.js -[ - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" - } - ], - "description": { - "full": "

    Mongoose error

    ", - "summary": "

    Mongoose error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", - "ctx": { - "type": "function", - "name": "MongooseError", - "string": "MongooseError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Error.

    ", - "summary": "

    Inherits from Error.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseError.prototype.__proto__ = Error.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseError", - "name": "__proto__", - "value": "Error.prototype", - "string": "MongooseError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseError", - "string": "module.exports" - } - } -] -### lib/errors/cast.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casting Error constructor.

    ", - "summary": "

    Casting Error constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", - "ctx": { - "type": "function", - "name": "CastError", - "string": "CastError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "CastError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "CastError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "CastError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = CastError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "CastError", - "string": "module.exports" - } - } -] -### lib/errors/document.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements

    ", - "summary": "

    Module requirements

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Document Error

    ", - "summary": "

    Document Error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", - "ctx": { - "type": "function", - "name": "DocumentError", - "string": "DocumentError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "DocumentError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = DocumentError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = DocumentError", - "string": "module.exports" - } - } -] -### lib/errors/validation.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements

    ", - "summary": "

    Module requirements

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "instance", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

    Document Validation Error

    ", - "summary": "

    Document Validation Error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", - "ctx": { - "type": "function", - "name": "ValidationError", - "string": "ValidationError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Console.log helper

    ", - "summary": "

    Console.log helper

    ", - "body": "" - }, - "ignore": false, - "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", - "ctx": { - "type": "method", - "constructor": "ValidationError", - "name": "toString", - "string": "ValidationError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidationError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidationError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports

    ", - "summary": "

    Module exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = ValidationError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = ValidationError", - "string": "module.exports" - } - } -] -### lib/errors/validator.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Schema validator error

    ", - "summary": "

    Schema validator error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", - "ctx": { - "type": "function", - "name": "ValidatorError", - "string": "ValidatorError()" - } - }, - { - "tags": [], - "description": { - "full": "

    toString helper

    ", - "summary": "

    toString helper

    ", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", - "ctx": { - "type": "method", - "constructor": "ValidatorError", - "name": "toString", - "string": "ValidatorError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError

    ", - "summary": "

    Inherits from MongooseError

    ", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidatorError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidatorError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ValidatorError", - "string": "module.exports" - } - } -] -### lib/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", - "summary": "

    Mongoose constructor.

    ", - "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", - "ctx": { - "type": "function", - "name": "Mongoose", - "string": "Mongoose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", - "summary": "

    Sets mongoose options

    ", - "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "set", - "string": "Mongoose.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "method", - "string": "get" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", - "summary": "

    Gets mongoose options

    ", - "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.get = Mongoose.prototype.set;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "get", - "value": "Mongoose.prototype.set", - "string": "Mongoose.prototypeget" - } - }, - { - "tags": [], - "description": { - "full": "

    ReplSet connection string check.

    ", - "summary": "

    ReplSet connection string check.

    ", - "body": "" - }, - "ignore": true, - "code": "var rgxReplSet = /^.+,.+$/;", - "ctx": { - "type": "declaration", - "name": "rgxReplSet", - "value": "/^.+,.+$/", - "string": "rgxReplSet" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[uri]", - "description": "a mongodb:// URI" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options to pass to the driver" - }, - { - "type": "see", - "local": "Connection#open #connection_Connection-open", - "visibility": "Connection#open" - }, - { - "type": "see", - "local": "Connection#openSet #connection_Connection-openSet", - "visibility": "Connection#openSet" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "the created Connection object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Connection instance.

    \n\n

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    ", - "summary": "

    Creates a Connection instance.

    ", - "body": "

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "createConnection", - "string": "Mongoose.prototype.createConnection()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Mongoose#createConnection #index_Mongoose-createConnection", - "visibility": "Mongoose#createConnection" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - } - ], - "description": { - "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    ", - "summary": "

    Opens the default mongoose connection.

    ", - "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "connect", - "string": "Mongoose.prototype.connect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "called after all connection close." - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Disconnects all connections.

    ", - "summary": "

    Disconnects all connections.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "disconnect", - "string": "Mongoose.prototype.disconnect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name (optional, induced from model name)" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipInit]", - "description": "whether to skip initialization (defaults to false)" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    ", - "summary": "

    Defines a model or retrieves it.

    ", - "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n // normalize collection\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // look up models for the collection\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n this.modelSchemas[name] = schema;\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n } else {\n throw new Error('Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)');\n }\n }\n\n if (!this.models[name]) {\n schema || (schema = this.modelSchemas[name]);\n collection || (collection = schema.set('collection') || format(name));\n\n var model = Model.compile(name\n , this.modelSchemas[name]\n , collection\n , this.connection\n , this);\n\n if (!skipInit) model.init();\n\n this.models[name] = model;\n }\n\n return this.models[name];\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "model", - "string": "Mongoose.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "plugin callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "optional options" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", - "summary": "

    Declares a global plugin executed on all Schemas.

    ", - "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "plugin", - "string": "Mongoose.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "connection" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", - "summary": "

    The default connection of the mongoose module.

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" - }, - { - "tags": [], - "description": { - "full": "

    Driver depentend APIs

    ", - "summary": "

    Driver depentend APIs

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

    Connection

    ", - "summary": "

    Connection

    ", - "body": "" - }, - "ignore": true, - "code": "var Connection = require(driver + '/connection');", - "ctx": { - "type": "declaration", - "name": "Connection", - "value": "require(driver + '/connection')", - "string": "Connection" - } - }, - { - "tags": [], - "description": { - "full": "

    Collection

    ", - "summary": "

    Collection

    ", - "body": "" - }, - "ignore": true, - "code": "var Collection = require(driver + '/collection');", - "ctx": { - "type": "declaration", - "name": "Collection", - "value": "require(driver + '/collection')", - "string": "Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The exports object is an instance of Mongoose.

    ", - "summary": "

    The exports object is an instance of Mongoose.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = new Mongoose", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Collection constructor

    ", - "summary": "

    The Mongoose Collection constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Collection = Collection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Collection", - "value": "Collection", - "string": "mongoose.Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Connection constructor

    ", - "summary": "

    The Mongoose Connection constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Connection = Connection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Connection", - "value": "Connection", - "string": "mongoose.Connection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Mongoose version

    ", - "summary": "

    Mongoose version

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "version", - "value": "JSON.parse(", - "string": "mongoose.version" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", - "summary": "

    The Mongoose constructor

    ", - "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Mongoose = Mongoose;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Mongoose", - "value": "Mongoose", - "string": "mongoose.Mongoose" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", - "summary": "

    The Mongoose Schema constructor

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Schema = Schema;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Schema", - "value": "Schema", - "string": "mongoose.Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose SchemaType constructor.

    ", - "summary": "

    The Mongoose SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaType = SchemaType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaType", - "value": "SchemaType", - "string": "mongoose.SchemaType" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Schema.SchemaTypes #schema_Schema-Types", - "visibility": "Schema.SchemaTypes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", - "summary": "

    The various Mongoose SchemaTypes.

    ", - "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaTypes = Schema.Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaTypes", - "value": "Schema.Types", - "string": "mongoose.SchemaTypes" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose VirtualType constructor.

    ", - "summary": "

    The Mongoose VirtualType constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.VirtualType = VirtualType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "VirtualType", - "value": "VirtualType", - "string": "mongoose.VirtualType" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", - "summary": "

    The various Mongoose Types.

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Types = Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Types", - "value": "Types", - "string": "mongoose.Types" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Query constructor.

    ", - "summary": "

    The Mongoose Query constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Query = Query;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Query", - "value": "Query", - "string": "mongoose.Query" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Promise constructor.

    ", - "summary": "

    The Mongoose Promise constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Promise = Promise;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Promise", - "value": "Promise", - "string": "mongoose.Promise" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Model constructor.

    ", - "summary": "

    The Mongoose Model constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Model = Model;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Model", - "value": "Model", - "string": "mongoose.Model" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Document constructor.

    ", - "summary": "

    The Mongoose Document constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Document = Document;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Document", - "value": "Document", - "string": "mongoose.Document" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The MongooseError constructor.

    ", - "summary": "

    The MongooseError constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Error = require('./error');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Error", - "value": "require('./error')", - "string": "mongoose.Error" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The node-mongodb-native driver Mongoose uses.

    ", - "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.mongo = require('mongodb');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "mongo", - "value": "require('mongodb')", - "string": "mongoose.mongo" - } - } -] -### lib/model.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('./document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "values to with which to create the document" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "event", - "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." - }, - { - "type": "event", - "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Model constructor

    ", - "summary": "

    Model constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", - "ctx": { - "type": "function", - "name": "Model", - "string": "Model()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Document.

    ", - "summary": "

    Inherits from Document.

    ", - "body": "" - }, - "ignore": true, - "code": "Model.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "Model", - "name": "__proto__", - "value": "Document.prototype", - "string": "Model.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

    Connection the model uses.

    ", - "summary": "

    Connection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.db;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "collection" - } - ], - "description": { - "full": "

    Collection the model uses.

    ", - "summary": "

    Collection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.collection;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "modelName" - } - ], - "description": { - "full": "

    The name of the model

    ", - "summary": "

    The name of the model

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.modelName;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "object" - }, - { - "type": "return", - "types": [ - "Object", - "undefined" - ], - "description": "population paths" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns what paths can be populated

    ", - "summary": "

    Returns what paths can be populated

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_getPopulationKeys", - "string": "Model.prototype._getPopulationKeys()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "schema", - "description": "type for the oid" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "oid", - "description": "object id or array of object ids" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "query", - "description": "object specifying query conditions, fields, and options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Populates an object

    ", - "summary": "

    Populates an object

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_populate", - "string": "Model.prototype._populate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "query that originated the initialization" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs auto-population of relations.

    ", - "summary": "

    Performs auto-population of relations.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "init", - "string": "Model.prototype.init()" - } - }, - { - "tags": [], - "description": { - "full": "

    Handles doc.save() callbacks

    ", - "summary": "

    Handles doc.save() callbacks

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new Error('No matching document found.'));\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", - "ctx": { - "type": "function", - "name": "handleSave", - "string": "handleSave()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "title": "middleware", - "url": "http://mongoosejs.com/docs/middleware.html", - "visibility": "http://mongoosejs.com/docs/middleware.html" - } - ], - "description": { - "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", - "summary": "

    Saves this document.

    ", - "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n process.nextTick(function () {\n complete(null);\n })\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "save", - "string": "Model.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Mixed" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[operation]", - "description": "" - } - ], - "description": { - "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", - "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", - "ctx": { - "type": "function", - "name": "operand", - "string": "operand()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "val", - "description": "" - } - ], - "description": { - "full": "

    Compiles an update and where clause for a val with _atomics.

    ", - "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", - "ctx": { - "type": "function", - "name": "handleAtomics", - "string": "handleAtomics()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Produces a special query document of the modified properties used in updates.

    ", - "summary": "

    Produces a special query document of the modified properties used in updates.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_delta", - "string": "Model.prototype._delta()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Appends versioning to the where and update clauses.

    ", - "summary": "

    Appends versioning to the where and update clauses.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_version", - "string": "Model.prototype._version()" - } - }, - { - "tags": [ - { - "type": "see", - "title": "versionKeys", - "url": "http://mongoosejs.com/docs/guide.html#versionKey", - "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Signal that we desire an increment of this documents version.

    ", - "summary": "

    Signal that we desire an increment of this documents version.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "increment", - "string": "Model.prototype.increment()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns a query object which applies shardkeys if they exist.

    ", - "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_where", - "string": "Model.prototype._where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", - "summary": "

    Removes this document from the db.

    ", - "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) return this;\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "remove", - "string": "Model.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register hooks override

    ", - "summary": "

    Register hooks override

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_registerHooks", - "string": "Model.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", - "summary": "

    Returns another Model instance.

    ", - "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "model", - "string": "Model.prototype.model()" - } - }, - { - "tags": [ - { - "type": "TODO", - "string": "determine if this is still necessary" - } - ], - "description": { - "full": "

    Give the constructor the ability to emit events.

    ", - "summary": "

    Give the constructor the ability to emit events.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the model compiles.

    ", - "summary": "

    Called when the model compiles.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.init = function init () {\n if (this.schema.options.autoIndex)\n this.ensureIndexes();\n\n this.schema.emit('init', this);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "init", - "string": "Model.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[cb]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    ", - "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", - "body": "

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "ensureIndexes", - "string": "Model.ensureIndexes()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "schema" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Schema the model uses.

    ", - "summary": "

    Schema the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.schema;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Database instance the model uses.

    ", - "summary": "

    Database instance the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.db;" - }, - { - "tags": [ - { - "type": "property", - "string": "collection" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Collection the model uses.

    ", - "summary": "

    Collection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.collection;" - }, - { - "tags": [ - { - "type": "property", - "string": "base" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Base Mongoose instance the model uses.

    ", - "summary": "

    Base Mongoose instance the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.base;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes documents from the collection.

    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    ", - "summary": "

    Removes documents from the collection.

    ", - "body": "

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "remove", - "string": "Model.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds documents

    \n\n

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    ", - "summary": "

    Finds documents

    ", - "body": "

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "find", - "string": "Model.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Merges the current named scope query into query.

    ", - "summary": "

    Merges the current named scope query into query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "_applyNamedScope", - "string": "Model._applyNamedScope()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "objectid, or a value that can be casted to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds a single document by id.

    \n\n

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    ", - "summary": "

    Finds a single document by id.

    ", - "body": "

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findById", - "string": "Model.findById()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    ", - "summary": "

    Finds one document.

    ", - "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n // TODO Handle all 3 of the following scenarios\n // Hint: Only some of these scenarios are possible if cQuery is present\n // Scenario: findOne(conditions, fields, callback);\n // Scenario: findOne(fields, options, callback);\n // Scenario: findOne(conditions, options, callback);\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n // TODO Handle all 2 of the following scenarios\n // Scenario: findOne(conditions, callback)\n // Scenario: findOne(fields, callback)\n // Scenario: findOne(options, callback);\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOne", - "string": "Model.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", - "summary": "

    Counts number of matching documents in a database collection.

    ", - "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "count", - "string": "Model.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes a DISTINCT command

    ", - "summary": "

    Executes a DISTINCT command

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "distinct", - "string": "Model.distinct()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "optional value" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", - "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", - "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "where", - "string": "Model.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "argument", - "description": "is a javascript string or anonymous function" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "memberOf", - "parent": "Model" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Query.$where #query_Query-%24where", - "visibility": "Query.$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    ", - "summary": "

    Creates a Query and specifies a $where condition.

    ", - "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Issues a mongodb findAndModify update command.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndUpdate", - "string": "Model.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "an ObjectId or string that can be cast to one." - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", - "visibility": "Model.findOneAndUpdate" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndUpdate", - "string": "Model.findByIdAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", - "summary": "

    Issue a mongodb findAndModify remove command.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndRemove", - "string": "Model.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "id", - "description": "ObjectId or string that can be cast to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", - "visibility": "Model.findOneAndRemove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - } - ], - "description": { - "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", - "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndRemove", - "string": "Model.findByIdAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array", - "Object..." - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", - "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", - "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "create", - "string": "Model.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "update", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Updates documents in the database without returning them.

    ", - "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "update", - "string": "Model.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "o", - "description": "an object specifying map-reduce options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/MapReduce", - "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", - "summary": "

    Executes a mapReduce command.

    ", - "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "mapReduce", - "string": "Model.mapReduce()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "an array of pipeline commands" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "aggregation", - "url": "http://docs.mongodb.org/manual/applications/aggregation/", - "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", - "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes an aggregate command on this models collection.

    \n\n

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    ", - "summary": "

    Executes an aggregate command on this models collection.

    ", - "body": "

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "aggregate", - "string": "Model.aggregate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "collectionName", - "description": "" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "connection", - "description": "" - }, - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "mongoose instance" - } - ], - "description": { - "full": "

    Compiler utility.

    ", - "summary": "

    Compiler utility.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "compile", - "string": "Model.compile()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Model;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Model", - "string": "module.exports" - } - } -] -### lib/namedscope.js -[ - { - "tags": [ - { - "type": "param", - "types": [ - "NamedScope" - ], - "name": "target", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "getters", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Decorate

    ", - "summary": "

    Decorate

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", - "ctx": { - "type": "method", - "constructor": "NamedScope", - "name": "decorate", - "string": "NamedScope.prototype.decorate()" - } - } -] -### lib/promise.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", - "ctx": { - "type": "declaration", - "name": "util", - "value": "require('./utils')", - "string": "util" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "back", - "description": "a callback+errback that accepts `fn(err, ...){}` as signature" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`err`: Emits when the promise resolves to an error." - }, - { - "type": "event", - "string": "`complete`: Emits when the promise resolves sucessfully." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Promise constructor.

    ", - "summary": "

    Promise constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", - "ctx": { - "type": "function", - "name": "Promise", - "string": "Promise()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from EventEmitter.

    ", - "summary": "

    Inherits from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Promise", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Promise.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Event" - ], - "name": "event", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds listener to the event.

    \n\n

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", - "summary": "

    Adds listener to the event.

    ", - "body": "

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "on", - "string": "Promise.prototype.on()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Keeps track of emitted events to run them on on.

    ", - "summary": "

    Keeps track of emitted events to run them on on.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "emit", - "string": "Promise.prototype.emit()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for emitting the complete event.

    ", - "summary": "

    Shortcut for emitting the complete event.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "complete", - "string": "Promise.prototype.complete()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

    Shortcut for emitting the err event.

    ", - "summary": "

    Shortcut for emitting the err event.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "error", - "string": "Promise.prototype.error()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for .on('complete', fn).

    ", - "summary": "

    Shortcut for .on('complete', fn).

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addCallback", - "string": "Promise.prototype.addCallback()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for .on('err', fn).

    ", - "summary": "

    Shortcut for .on('err', fn).

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addErrback", - "string": "Promise.prototype.addErrback()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

    Adds a single function that's both a callback and errback.

    ", - "summary": "

    Adds a single function that's both a callback and errback.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addBack", - "string": "Promise.prototype.addBack()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "optional error or null" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "value to complete the promise with" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", - "summary": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "resolve", - "string": "Promise.prototype.resolve()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Promise;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Promise", - "string": "module.exports" - } - } -] -### lib/query.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "criteria", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", - "summary": "

    Query constructor used for building queries.

    ", - "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n if (criteria) this.find(criteria);\n}", - "ctx": { - "type": "function", - "name": "Query", - "string": "Query()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", - "summary": "

    Sets query options.

    ", - "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "setOptions", - "string": "Query.prototype.setOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "the model to which the query is bound" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "the operation to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "updateArg", - "description": "used in update methods" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Binds this query to a model.

    ", - "summary": "

    Binds this query to a model.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "bind", - "string": "Query.prototype.bind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "[operation]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", - "summary": "

    Executes the query

    ", - "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exec", - "string": "Query.prototype.exec()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[criteria]", - "description": "mongodb selector" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", - "summary": "

    Finds documents.

    ", - "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "find", - "string": "Query.prototype.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[obj]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", - "summary": "

    Casts this query to the schema of model

    ", - "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path || '$and' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "cast", - "string": "Query.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns default options.

    ", - "summary": "

    Returns default options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_optionsForExec", - "string": "Query.prototype._optionsForExec()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies schematype selected options to this query.

    ", - "summary": "

    Applies schematype selected options to this query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_applyPaths", - "string": "Query.prototype._applyPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "js", - "description": "javascript string or function" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", - "summary": "

    Specifies a $where condition

    ", - "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", - "summary": "

    Specifies a path for use with chaining.

    ", - "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "where", - "string": "Query.prototype.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", - "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", - "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "equals", - "string": "Query.prototype.equals()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", - "summary": "

    Specifies arguments for an $or condition.

    ", - "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "or", - "string": "Query.prototype.or()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", - "summary": "

    Specifies arguments for a $nor condition.

    ", - "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nor", - "string": "Query.prototype.nor()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "gt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", - "summary": "

    Specifies a $gt query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "gte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $gte query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $lt query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $lte query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "ne" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $ne query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "in" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $in query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "nin" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $nin query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "all" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $all query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "size" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $size query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "regex" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $regex query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxDistance" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $maxDistance query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", - "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", - "body": "
    Thing.where('type').nin(array)\n
    " - }, - "ignore": true, - "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $near condition

    ", - "summary": "

    Specifies a $near condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "near", - "string": "Query.prototype.near()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $nearSphere condition.

    ", - "summary": "

    Specifies a $nearSphere condition.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nearSphere", - "string": "Query.prototype.nearSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $mod condition

    ", - "summary": "

    Specifies a $mod condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "mod", - "string": "Query.prototype.mod()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $exists condition

    ", - "summary": "

    Specifies an $exists condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exists", - "string": "Query.prototype.exists()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object", - "Function" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "Function" - ], - "name": "criteria", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", - "summary": "

    Specifies an $elemMatch condition

    ", - "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "elemMatch", - "string": "Query.prototype.elemMatch()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "within" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Syntax sugar for expressive queries.

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    ", - "summary": "

    Syntax sugar for expressive queries.

    ", - "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "see", - "local": "Query#within #query_Query-within", - "visibility": "Query#within" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", - "summary": "

    Specifies a $box condition

    ", - "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "box", - "string": "Query.prototype.box()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "options e.g. { $uniqueDocs: true }" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", - "summary": "

    Specifies a $center condition

    ", - "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "center", - "string": "Query.prototype.center()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", - "summary": "

    Specifies a $centerSphere condition

    ", - "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "centerSphere", - "string": "Query.prototype.centerSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Array", - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", - "summary": "

    Specifies a $polygon condition

    ", - "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "polygon", - "string": "Query.prototype.polygon()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "local": "SchemaType", - "visibility": "SchemaType" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    ", - "summary": "

    Specifies which document fields to include or exclude

    ", - "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "select", - "string": "Query.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "number of elements to slice" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", - "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", - "summary": "

    Specifies a $slice condition

    ", - "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slice", - "string": "Query.prototype.slice()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", - "summary": "

    Sets the sort order

    ", - "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "sort", - "string": "Query.prototype.sort()" - } - }, - { - "tags": [], - "description": { - "full": "

    @ignore

    ", - "summary": "

    @ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", - "ctx": { - "type": "function", - "name": "push", - "string": "push()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "limit" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", - "summary": "

    Specifies the limit option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "skip" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", - "summary": "

    Specifies the skip option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxscan" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", - "summary": "

    Specifies the maxscan option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "batchSize" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", - "summary": "

    Specifies the batchSize option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "comment" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", - "summary": "

    Specifies the comment option.

    ", - "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", - "summary": "

    limit, skip, maxscan, batchSize, comment

    ", - "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " - }, - "ignore": true, - "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", - "summary": "

    Specifies this query as a snapshot query.

    ", - "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "snapshot", - "string": "Query.prototype.snapshot()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "a hint object" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", - "summary": "

    Sets query hints.

    ", - "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "hint", - "string": "Query.prototype.hint()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", - "summary": "

    Sets the slaveOk option.

    ", - "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slaveOk", - "string": "Query.prototype.slaveOk()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "one of the listed preference options or their aliases" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "[tags]", - "description": "optional tags for this query" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", - "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the readPreference option for the query.

    \n\n

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    ", - "summary": "

    Sets the readPreference option for the query.

    ", - "body": "

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "read", - "string": "Query.prototype.read()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", - "summary": "

    Sets the lean option.

    ", - "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "lean", - "string": "Query.prototype.lean()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", - "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", - "summary": "

    Sets tailable option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "tailable", - "string": "Query.prototype.tailable()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes the query as a find() operation.

    ", - "summary": "

    Executes the query as a find() operation.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "execFind", - "string": "Query.prototype.execFind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", - "summary": "

    Executes the query as a findOne() operation.

    ", - "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOne", - "string": "Query.prototype.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", - "summary": "

    Exectues the query as a count() operation.

    ", - "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "count", - "string": "Query.prototype.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as a distict() operation.

    ", - "summary": "

    Executes this query as a distict() operation.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "distinct", - "string": "Query.prototype.distinct()" - } - }, - { - "tags": [], - "description": { - "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", - "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", - "body": "" - }, - "ignore": true, - "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", - "ctx": { - "type": "declaration", - "name": "castOps", - "value": "{", - "string": "castOps" - } - }, - { - "tags": [], - "description": { - "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", - "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", - "body": "" - }, - "ignore": true, - "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", - "ctx": { - "type": "declaration", - "name": "numberOps", - "value": "{", - "string": "numberOps" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "the update conditions" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", - "summary": "

    Executes this query as an update() operation.

    ", - "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n delete options.safe;\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "update", - "string": "Query.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "obj after casting its values" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts obj for an update command.

    ", - "summary": "

    Casts obj for an update command.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdate", - "string": "Query.prototype._castUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "- part of a query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "- path prefix (internal only)" - }, - { - "type": "return", - "types": [ - "Bool" - ], - "description": "true if this path has keys to update" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", - "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_walkUpdatePath", - "string": "Query.prototype._walkUpdatePath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[$conditional]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts val according to schema and atomic op.

    ", - "summary": "

    Casts val according to schema and atomic op.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdateVal", - "string": "Query.prototype._castUpdateVal()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_getSchema", - "string": "Query.prototype._getSchema()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "https://github.com/LearnBoost/mongoose/issues/1091", - "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" - }, - { - "type": "see", - "title": "", - "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", - "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts selected field arguments for field selection with mongo 2.2

    \n\n
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    ", - "summary": "

    Casts selected field arguments for field selection with mongo 2.2

    ", - "body": "
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castFields", - "string": "Query.prototype._castFields()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", - "summary": "

    Executes this query as a remove() operation.

    ", - "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n delete options.safe;\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "remove", - "string": "Query.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[query]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[doc]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", - "summary": "

    Issues a mongodb findAndModify update command.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndUpdate", - "string": "Query.prototype.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", - "summary": "

    Issues a mongodb findAndModify remove command.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndRemove", - "string": "Query.prototype.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "- either \"remove\" or \"update\"" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    _findAndModify

    ", - "summary": "

    _findAndModify

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n this._applyPaths();\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_findAndModify", - "string": "Query.prototype._findAndModify()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Model" - ], - "name": "[model]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "see", - "local": "population ./populate.html", - "visibility": "population" - }, - { - "type": "see", - "local": "Query#select #query_Query-select", - "visibility": "Query#select" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    ", - "summary": "

    Specifies paths which should be populated with other documents.

    ", - "body": "

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "populate", - "string": "Query.prototype.populate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Populate options constructor

    ", - "summary": "

    Populate options constructor

    ", - "body": "" - }, - "ignore": true, - "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", - "ctx": { - "type": "function", - "name": "PopulateOptions", - "string": "PopulateOptions()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "QueryStream" - ], - "description": "" - }, - { - "type": "see", - "local": "QueryStream", - "visibility": "QueryStream" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a stream interface

    \n\n

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    ", - "summary": "

    Returns a stream interface

    ", - "body": "

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "stream", - "string": "Query.prototype.stream()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    castDoc

    ", - "summary": "

    castDoc

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castDoc", - "string": "castDoc()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    castQuery

    ", - "summary": "

    castQuery

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castQuery", - "string": "castQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Exports.

    ", - "summary": "

    Exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Query", - "string": "module.exports" - } - } -] -### lib/querystream.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", - "ctx": { - "type": "declaration", - "name": "Stream", - "value": "require('stream').Stream", - "string": "Stream" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS Stream http://nodejs.org/api/stream.html" - }, - { - "type": "event", - "string": "`data`: emits a single Mongoose document" - }, - { - "type": "event", - "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." - }, - { - "type": "event", - "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Provides a ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    ", - "summary": "

    Provides a ReadStream interface for Queries.

    ", - "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n this._running = false;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", - "ctx": { - "type": "function", - "name": "QueryStream", - "string": "QueryStream()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Stream

    ", - "summary": "

    Inherit from Stream

    ", - "body": "" - }, - "ignore": true, - "code": "QueryStream.prototype.__proto__ = Stream.prototype;", - "ctx": { - "type": "property", - "constructor": "QueryStream", - "name": "__proto__", - "value": "Stream.prototype", - "string": "QueryStream.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readable" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Flag stating whether or not this stream is readable.

    ", - "summary": "

    Flag stating whether or not this stream is readable.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.readable;" - }, - { - "tags": [ - { - "type": "property", - "string": "paused" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Flag stating whether or not this stream is paused.

    ", - "summary": "

    Flag stating whether or not this stream is paused.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Initializes the query.

    ", - "summary": "

    Initializes the query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_init", - "string": "QueryStream.prototype._init()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#__next #querystream_QueryStream-__next", - "visibility": "QueryStream#__next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Trampoline for pulling the next doc from cursor.

    ", - "summary": "

    Trampoline for pulling the next doc from cursor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) {\n return this._running = false;\n }\n\n this._running = true;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n while (this.__next()) {}\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_next", - "string": "QueryStream.prototype._next()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#_next #querystream_QueryStream-_next", - "visibility": "QueryStream#_next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Pulls the next doc from the cursor.

    ", - "summary": "

    Pulls the next doc from the cursor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed)\n return this._running = false;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "__next", - "string": "QueryStream.prototype.__next()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error", - "null" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", - "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return this._running = false;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && true === this.query.options.lean) {\n this.emit('data', doc);\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_onNextObject", - "string": "QueryStream.prototype._onNextObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pauses this stream.

    ", - "summary": "

    Pauses this stream.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "pause", - "string": "QueryStream.prototype.pause()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Resumes this stream.

    ", - "summary": "

    Resumes this stream.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n\n if (!this._cursor) {\n // cannot start if not initialized\n return;\n }\n\n // are we within the trampoline?\n if (T_INIT === this._inline) {\n return;\n }\n\n if (!this._running) {\n // outside QueryStream control, need manual restart\n return this._next();\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "resume", - "string": "QueryStream.prototype.resume()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "[err]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", - "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this._running = false;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "destroy", - "string": "QueryStream.prototype.destroy()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "pipe" - }, - { - "type": "memberOf", - "parent": "QueryStream" - }, - { - "type": "see", - "title": "NodeJS", - "url": "http://nodejs.org/api/stream.html", - "visibility": "http://nodejs.org/api/stream.html" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", - "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", - "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    Module exports

    ", - "summary": "

    Module exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = QueryStream", - "string": "module.exports" - } - } -] -### lib/schema/array.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Array SchemaType constructor

    ", - "summary": "

    Array SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "SchemaArray", - "string": "SchemaArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaArray", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "checkRequired", - "string": "SchemaArray.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Overrides the getters application for the population special-case

    ", - "summary": "

    Overrides the getters application for the population special-case

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "applyGetters", - "string": "SchemaArray.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "cast", - "string": "SchemaArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "castForQuery", - "string": "SchemaArray.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    @ignore

    ", - "summary": "

    @ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': SchemaArray.prototype.castForQuery\n , '$gte': SchemaArray.prototype.castForQuery\n , '$lt': SchemaArray.prototype.castForQuery\n , '$lte': SchemaArray.prototype.castForQuery\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", - "ctx": { - "type": "function", - "name": "castToNumber", - "string": "castToNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaArray", - "string": "module.exports" - } - } -] -### lib/schema/boolean.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Boolean SchemaType constructor.

    ", - "summary": "

    Boolean SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaBoolean", - "string": "SchemaBoolean()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBoolean", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBoolean.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator

    ", - "summary": "

    Required validator

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "checkRequired", - "string": "SchemaBoolean.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to boolean

    ", - "summary": "

    Casts to boolean

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "cast", - "string": "SchemaBoolean.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", - "ctx": { - "type": "function", - "name": "handleArray", - "string": "handleArray()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "castForQuery", - "string": "SchemaBoolean.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBoolean;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBoolean", - "string": "module.exports" - } - } -] -### lib/schema/buffer.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Buffer SchemaType constructor

    ", - "summary": "

    Buffer SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", - "ctx": { - "type": "function", - "name": "SchemaBuffer", - "string": "SchemaBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBuffer", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBuffer.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "checkRequired", - "string": "SchemaBuffer.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "cast", - "string": "SchemaBuffer.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "castForQuery", - "string": "SchemaBuffer.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBuffer;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBuffer", - "string": "module.exports" - } - } -] -### lib/schema/date.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements.

    ", - "summary": "

    Module requirements.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Date SchemaType constructor.

    ", - "summary": "

    Date SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaDate", - "string": "SchemaDate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaDate", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaDate.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator for date

    ", - "summary": "

    Required validator for date

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "checkRequired", - "string": "SchemaDate.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to date

    ", - "summary": "

    Casts to date

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "cast", - "string": "SchemaDate.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Date Query casting.

    ", - "summary": "

    Date Query casting.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "castForQuery", - "string": "SchemaDate.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaDate;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaDate", - "string": "module.exports" - } - } -] -### lib/schema/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaArray" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    SubdocsArray SchemaType constructor

    ", - "summary": "

    SubdocsArray SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "DocumentArray", - "string": "DocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from ArrayType.

    ", - "summary": "

    Inherits from ArrayType.

    ", - "body": "" - }, - "ignore": true, - "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentArray", - "name": "__proto__", - "value": "ArrayType.prototype", - "string": "DocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs local validations first, then validations on each embedded doc

    ", - "summary": "

    Performs local validations first, then validations on each embedded doc

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n\n SchemaType.prototype.doValidate.call(this, array, function (err) {\n if (err) return fn(err);\n\n var count = array && array.length\n , error;\n\n if (!count) return fn();\n\n // handle sparse arrays, do not use array.forEach which does not\n // iterate over sparse elements yet reports array.length including\n // them :(\n\n for (var i = 0, len = count; i < len; ++i) {\n // sidestep sparse entries\n var doc = array[i];\n if (!doc) {\n --count || fn();\n continue;\n }\n\n ;(function (i) {\n doc.validate(function (err) {\n if (err && !error) {\n // rewrite the key\n err.key = self.key + '.' + i + '.' + err.key;\n return fn(error = err);\n }\n --count || fn();\n });\n })(i);\n }\n }, scope);\n};", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "doValidate", - "string": "DocumentArray.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "document", - "description": "that triggers the casting" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument) && value[i]) {\n if (init) {\n selected || (selected = scopePaths(this, doc._selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "cast", - "string": "DocumentArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "DocumentArray" - ], - "name": "array", - "description": "- the array to scope `fields` paths" - }, - { - "type": "param", - "types": [ - "Object", - "undefined" - ], - "name": "fields", - "description": "- the root fields selected in the query" - }, - { - "type": "param", - "types": [ - "Boolean", - "undefined" - ], - "name": "init", - "description": "- if we are being created part of a query result" - } - ], - "description": { - "full": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", - "summary": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , hasKeys\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n hasKeys || (hasKeys = true);\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return hasKeys && selected || undefined;\n}", - "ctx": { - "type": "function", - "name": "scopePaths", - "string": "scopePaths()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = DocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "DocumentArray", - "string": "module.exports" - } - } -] -### lib/schema/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "String", - "value": "require('./string')", - "string": "exports.String" - } - } -] -### lib/schema/mixed.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Mixed SchemaType constructor.

    ", - "summary": "

    Mixed SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "Mixed", - "string": "Mixed()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "Mixed", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "Mixed.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator

    ", - "summary": "

    Required validator

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "checkRequired", - "string": "Mixed.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", - "summary": "

    Casts val for Mixed.

    ", - "body": "

    this is a no-op

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "cast", - "string": "Mixed.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$cond", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "castForQuery", - "string": "Mixed.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Mixed;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Mixed", - "string": "module.exports" - } - } -] -### lib/schema/number.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements.

    ", - "summary": "

    Module requirements.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Number SchemaType constructor.

    ", - "summary": "

    Number SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", - "ctx": { - "type": "function", - "name": "SchemaNumber", - "string": "SchemaNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaNumber", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaNumber.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator for number

    ", - "summary": "

    Required validator for number

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "checkRequired", - "string": "SchemaNumber.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "value", - "description": "minimum number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", - "summary": "

    Sets a maximum number validator.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "min", - "string": "SchemaNumber.prototype.min()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "maximum", - "description": "number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", - "summary": "

    Sets a maximum number validator.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "max", - "string": "SchemaNumber.prototype.max()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "value to cast" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to number

    ", - "summary": "

    Casts to number

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "cast", - "string": "SchemaNumber.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "castForQuery", - "string": "SchemaNumber.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaNumber;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaNumber", - "string": "module.exports" - } - } -] -### lib/schema/objectid.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    ObjectId SchemaType constructor.

    ", - "summary": "

    ObjectId SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", - "ctx": { - "type": "function", - "name": "ObjectId", - "string": "ObjectId()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "ObjectId", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "ObjectId.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "checkRequired", - "string": "ObjectId.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to ObjectId

    ", - "summary": "

    Casts to ObjectId

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "cast", - "string": "ObjectId.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "castForQuery", - "string": "ObjectId.prototype.castForQuery()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "turnOn", - "description": "auto generated ObjectId defaults" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", - "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "auto", - "string": "ObjectId.prototype.auto()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", - "ctx": { - "type": "function", - "name": "defaultId", - "string": "defaultId()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = ObjectId;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ObjectId", - "string": "module.exports" - } - } -] -### lib/schema/string.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    String SchemaType constructor.

    ", - "summary": "

    String SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", - "ctx": { - "type": "function", - "name": "SchemaString", - "string": "SchemaString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaString", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaString.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[args...]", - "description": "enumeration values" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", - "summary": "

    Adds enumeration values and a coinciding validator.

    ", - "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "enum", - "string": "SchemaString.prototype.enum()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", - "summary": "

    Adds a lowercase setter.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toLowerCase();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "lowercase", - "string": "SchemaString.prototype.lowercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", - "summary": "

    Adds an uppercase setter.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toUpperCase();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "uppercase", - "string": "SchemaString.prototype.uppercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", - "summary": "

    Adds a trim setter.

    ", - "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.trim();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "trim", - "string": "SchemaString.prototype.trim()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp" - ], - "name": "regExp", - "description": "regular expression to test against" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", - "summary": "

    Sets a regexp validator.

    ", - "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "match", - "string": "SchemaString.prototype.match()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "null", - "undefined" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "checkRequired", - "string": "SchemaString.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to String

    ", - "summary": "

    Casts to String

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "cast", - "string": "SchemaString.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "castForQuery", - "string": "SchemaString.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaString;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaString", - "string": "module.exports" - } - } -] -### lib/schema.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "definition", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted after the schema is compiled into a `Model`." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", - "summary": "

    Schema constructor.

    ", - "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", - "ctx": { - "type": "function", - "name": "Schema", - "string": "Schema()" - } - }, - { - "tags": [], - "description": { - "full": "

    Returns this documents _id cast to a string.

    ", - "summary": "

    Returns this documents _id cast to a string.

    ", - "body": "" - }, - "ignore": true, - "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", - "ctx": { - "type": "function", - "name": "idGetter", - "string": "idGetter()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Schema", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Schema.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "paths" - } - ], - "description": { - "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", - "summary": "

    Schema as flat paths

    ", - "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.paths;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "tree" - } - ], - "description": { - "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", - "summary": "

    Schema as a tree

    ", - "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.tree;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns default options for this schema, merged with options.

    ", - "summary": "

    Returns default options for this schema, merged with options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.defaultOptions = function (options) {\n options = utils.options({\n safe: true\n , strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "defaultOptions", - "string": "Schema.prototype.defaultOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "prefix", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", - "summary": "

    Adds key path / schema type pairs to this schema.

    ", - "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n } else {\n this.path(prefix + i, obj[i]); // mixed type\n }\n } else {\n this.path(prefix + i, obj[i]);\n }\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "add", - "string": "Schema.prototype.add()" - } - }, - { - "tags": [], - "description": { - "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    ", - "summary": "

    Reserved document keys.

    ", - "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    " - }, - "ignore": false, - "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "reserved", - "value": "Object.create(null)", - "string": "Schema.reserved" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "constructor", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", - "summary": "

    Gets/sets schema paths.

    ", - "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(sub, i) {\n if (!branch[sub]) branch[sub] = {};\n if ('function' == typeof branch[sub]) {\n var msg = 'Cannot set nested path `' + path + '`. '\n + 'Parent path `'\n + subpaths.slice(0, i).concat([sub]).join('.')\n + '` already set to type ' + branch[sub].name\n + '.';\n throw new Error(msg);\n }\n branch = branch[sub];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "path", - "string": "Schema.prototype.path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "constructor" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts type arguments into Mongoose Types.

    ", - "summary": "

    Converts type arguments into Mongoose Types.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", - "ctx": { - "type": "method", - "receiver": "Schema", - "name": "interpretAsType", - "string": "Schema.interpretAsType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback function" - }, - { - "type": "return", - "types": [ - "Schema" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", - "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", - "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "eachPath", - "string": "Schema.prototype.eachPath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns an Array of path strings that are required by this schema.

    ", - "summary": "

    Returns an Array of path strings that are required by this schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "requiredPaths", - "string": "Schema.prototype.requiredPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", - "summary": "

    Returns the pathType of path for this schema.

    ", - "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pathType", - "string": "Schema.prototype.pathType()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", - "ctx": { - "type": "function", - "name": "getPositionalPath", - "string": "getPositionalPath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the document method to call later" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Adds a method call to the queue.

    ", - "summary": "

    Adds a method call to the queue.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "queue", - "string": "Schema.prototype.queue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", - "summary": "

    Defines a pre hook for the document.

    ", - "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pre", - "string": "Schema.prototype.pre()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "name of the method to hook" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", - "summary": "

    Defines a post hook for the document.

    ", - "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "post", - "string": "Schema.prototype.post()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "plugin", - "description": "callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "" - }, - { - "type": "see", - "local": "plugins", - "visibility": "plugins" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Registers a plugin for this schema.

    ", - "summary": "

    Registers a plugin for this schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "plugin", - "string": "Schema.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "method", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", - "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", - "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "method", - "string": "Schema.prototype.method()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", - "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", - "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "static", - "string": "Schema.prototype.static()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", - "summary": "

    Defines an index (most likely compound) for this schema.

    ", - "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "index", - "string": "Schema.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "option name" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[value]", - "description": "if not passed, the current option value is returned" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets/gets a schema option.

    ", - "summary": "

    Sets/gets a schema option.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.set = function (key, value, tags) {\n if (arguments.length == 1)\n return this.options[key];\n\n this.options[key] = 'read' == key\n ? utils.readPref(value, tags)\n : value;\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "set", - "string": "Schema.prototype.set()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Compiles indexes from fields and schema-level indexes

    ", - "summary": "

    Compiles indexes from fields and schema-level indexes

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "indexes", - "string": "Schema.prototype.indexes()" - } - }, - { - "tags": [], - "description": { - "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", - "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", - "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " - }, - "ignore": true, - "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", - "ctx": { - "type": "function", - "name": "fixSubIndexPaths", - "string": "fixSubIndexPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

    Creates a virtual type with the given name.

    ", - "summary": "

    Creates a virtual type with the given name.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtual", - "string": "Schema.prototype.virtual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the virtual type with the given name.

    ", - "summary": "

    Returns the virtual type with the given name.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtualpath", - "string": "Schema.prototype.virtualpath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", - "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "namedScope", - "string": "Schema.prototype.namedScope()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Schema", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose Schema Types.

    \n\n

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", - "summary": "

    The various Mongoose Schema Types.

    ", - "body": "

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.Types = require('./schema/index');", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "Types", - "value": "require('./schema/index')", - "string": "Schema.Types" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" - } -] -### lib/schemadefault.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "property", - "string": "system.profile" - }, - { - "type": "receiver", - "string": "exports" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Default model for querying the system.profiles collection.

    ", - "summary": "

    Default model for querying the system.profiles collection.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" - } -] -### lib/schematype.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');\nvar CastError = require('./errors/cast')\nvar ValidatorError = require('./errors/validator')", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[instance]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    SchemaType constructor

    ", - "summary": "

    SchemaType constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", - "ctx": { - "type": "function", - "name": "SchemaType", - "string": "SchemaType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function", - "any" - ], - "name": "val", - "description": "the default value" - }, - { - "type": "return", - "types": [ - "defaultValue" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", - "summary": "

    Sets a default value for this SchemaType.

    ", - "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "default", - "string": "SchemaType.prototype.default()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "Boolean" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", - "summary": "

    Declares the index options for this schematype.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "index", - "string": "SchemaType.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares an unique index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    ", - "summary": "

    Declares an unique index.

    ", - "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "unique", - "string": "SchemaType.prototype.unique()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a sparse index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", - "summary": "

    Declares a sparse index.

    ", - "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "sparse", - "string": "SchemaType.prototype.sparse()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "when", - "description": "" - }, - { - "type": "added", - "string": "3.0.0" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    ", - "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", - "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "expires", - "string": "SchemaType.prototype.expires()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    ", - "summary": "

    Adds a setter to this schematype.

    ", - "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "set", - "string": "SchemaType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    ", - "summary": "

    Adds a getter to this schematype.

    ", - "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "get", - "string": "SchemaType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp", - "Function", - "Object" - ], - "name": "obj", - "description": "validator" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[error]", - "description": "optional error message" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", - "summary": "

    Adds validator(s) for this document path.

    ", - "body": "

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "validate", - "string": "SchemaType.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "required", - "description": "enable/disable the validator" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", - "summary": "

    Adds a required validator to this schematype.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "required", - "string": "SchemaType.prototype.required()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope which callback are executed" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Gets the default value

    ", - "summary": "

    Gets the default value

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "getDefault", - "string": "SchemaType.prototype.getDefault()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies setters

    ", - "summary": "

    Applies setters

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applySetters", - "string": "SchemaType.prototype.applySetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies getters to a value

    ", - "summary": "

    Applies getters to a value

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applyGetters", - "string": "SchemaType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", - "summary": "

    Sets default select() behavior for this path.

    ", - "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "select", - "string": "SchemaType.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", - "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "doValidate", - "string": "SchemaType.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determines if value is a valid Reference.

    ", - "summary": "

    Determines if value is a valid Reference.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", - "ctx": { - "type": "method", - "receiver": "SchemaType", - "name": "_isRef", - "string": "SchemaType._isRef()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = SchemaType", - "string": "module.exports" - } - } -] -### lib/statemachine.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", - "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", - "ctx": { - "type": "declaration", - "name": "StateMachine", - "value": "module.exports = exports = function StateMachine () {", - "string": "StateMachine" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "subclass constructor" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", - "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", - "ctx": { - "type": "method", - "receiver": "StateMachine", - "name": "ctor", - "string": "StateMachine.ctor()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", - "summary": "

    This function is wrapped by the state change functions

    ", - "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_changeState", - "string": "StateMachine.prototype._changeState()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "clear", - "string": "StateMachine.prototype.clear()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "that we want to check for." - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", - "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "some", - "string": "StateMachine.prototype.some()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "iterMethod", - "description": "is either 'forEach' or 'map'" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", - "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_iter", - "string": "StateMachine.prototype._iter()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", - "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", - "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "forEach", - "string": "StateMachine.prototype.forEach()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", - "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", - "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "map", - "string": "StateMachine.prototype.map()" - } - } -] -### lib/types/array.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", - "ctx": { - "type": "declaration", - "name": "EmbeddedDocument", - "value": "require('./embedded')", - "string": "EmbeddedDocument" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Array" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", - "summary": "

    Mongoose Array constructor.

    ", - "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseArray", - "string": "MongooseArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Array

    ", - "summary": "

    Inherit from Array

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseArray.prototype = new Array;", - "ctx": { - "type": "property", - "receiver": "MongooseArray", - "name": "prototype", - "value": "new Array", - "string": "MongooseArray.prototype" - } - }, - { - "tags": [ - { - "type": "property", - "string": "_atomics" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Stores a queue of atomic operations to perform

    ", - "summary": "

    Stores a queue of atomic operations to perform

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._atomics;" - }, - { - "tags": [ - { - "type": "property", - "string": "_parent" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Parent owner document

    ", - "summary": "

    Parent owner document

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._parent;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "return", - "types": [ - "value" - ], - "description": "the casted value" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts a member based on this arrays schema.

    ", - "summary": "

    Casts a member based on this arrays schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_cast", - "string": "MongooseArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "EmbeddedDocument" - ], - "name": "embeddedDoc", - "description": "the embedded doc that invoked this method on the Array" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "embeddedPath", - "description": "the path which changed in the embeddedDoc" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", - "summary": "

    Marks this array as modified.

    ", - "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._markModified = function (elem, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n dirtyPath = this._path;\n\n if (arguments.length) {\n if (null != embeddedPath) {\n // an embedded doc bubbled up the change\n dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;\n } else {\n // directly set an index\n dirtyPath = dirtyPath + '.' + elem;\n }\n\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_markModified", - "string": "MongooseArray.prototype._markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "op", - "description": "operation" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register an atomic operation with the parent.

    ", - "summary": "

    Register an atomic operation with the parent.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (this._atomics.$set ||\n Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_registerAtomic", - "string": "MongooseArray.prototype._registerAtomic()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", - "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "hasAtomics", - "string": "MongooseArray.prototype.hasAtomics()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#push with proper change tracking.

    ", - "summary": "

    Wraps Array#push with proper change tracking.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "push", - "string": "MongooseArray.prototype.push()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Pushes items to the array non-atomically.

    ", - "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "nonAtomicPush", - "string": "MongooseArray.prototype.nonAtomicPush()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "$pop" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", - "summary": "

    Pops the array atomically at most one time per document save().

    ", - "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n this._markModified();\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" - }, - { - "tags": [ - { - "type": "see", - "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", - "visibility": "MongooseArray#$pop" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#pop with proper change tracking.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pop", - "string": "MongooseArray.prototype.pop()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "method", - "string": "$shift" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", - "summary": "

    Atomically shifts the array at most one time per document save().

    ", - "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n this._markModified();\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#shift with proper change tracking.

    ", - "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "shift", - "string": "MongooseArray.prototype.shift()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "values to remove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes items from an array atomically

    \n\n

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    ", - "summary": "

    Removes items from an array atomically

    ", - "body": "

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "remove", - "string": "MongooseArray.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pulls items from the array atomically.

    ", - "summary": "

    Pulls items from the array atomically.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n this._markModified();\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pull", - "string": "MongooseArray.prototype.pull()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#splice with proper change tracking and casting.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#splice with proper change tracking and casting.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.splice = function splice () {\n var ret, vals, i;\n\n if (arguments.length) {\n vals = [];\n for (i = 0; i < arguments.length; ++i) {\n vals[i] = i < 2\n ? arguments[i]\n : this._cast(arguments[i]);\n }\n ret = [].splice.apply(this, vals);\n this._registerAtomic('$set', this);\n this._markModified();\n }\n\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "splice", - "string": "MongooseArray.prototype.splice()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#unshift with proper change tracking.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return this.length;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "unshift", - "string": "MongooseArray.prototype.unshift()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#sort with proper change tracking.

    ", - "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "sort", - "string": "MongooseArray.prototype.sort()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "the values that were added" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", - "summary": "

    Adds values to the array if not already present.

    ", - "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n this._markModified();\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "addToSet", - "string": "MongooseArray.prototype.addToSet()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the casted val at index i and marks the array modified.

    \n\n

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    ", - "summary": "

    Sets the casted val at index i and marks the array modified.

    ", - "body": "

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.set = function set (i, val) {\n this[i] = this._cast(val);\n this._markModified(i);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "set", - "string": "MongooseArray.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a native js Array.

    ", - "summary": "

    Returns a native js Array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "toObject", - "string": "MongooseArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "inspect", - "string": "MongooseArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the item to look for" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Return the index of obj or -1 if not found.

    ", - "summary": "

    Return the index of obj or -1 if not found.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "indexOf", - "string": "MongooseArray.prototype.indexOf()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = MongooseArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = MongooseArray", - "string": "module.exports" - } - } -] -### lib/types/buffer.js -[ - { - "tags": [], - "description": { - "full": "

    Access driver.

    ", - "summary": "

    Access driver.

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Binary = require(driver + '/binary');", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require(driver + '/binary')", - "string": "Binary" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "encode", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "offset", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Buffer" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", - "summary": "

    Mongoose Buffer constructor.

    ", - "body": "

    Values always have to be passed to the constructor to initialize.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", - "ctx": { - "type": "function", - "name": "MongooseBuffer", - "string": "MongooseBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Buffer.

    ", - "summary": "

    Inherit from Buffer.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.prototype = new Buffer(0);", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "prototype", - "value": "new Buffer(0)", - "string": "MongooseBuffer.prototype" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "_parent" - } - ], - "description": { - "full": "

    Parent owner document

    ", - "summary": "

    Parent owner document

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._parent;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Marks this buffer as modified.

    ", - "summary": "

    Marks this buffer as modified.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "_markModified", - "string": "MongooseBuffer.prototype._markModified()" - } - }, - { - "tags": [], - "description": { - "full": "

    Writes the buffer.

    ", - "summary": "

    Writes the buffer.

    ", - "body": "" - }, - "ignore": false, - "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "write", - "string": "MongooseBuffer.prototype.write()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "MongooseBuffer" - ], - "description": "" - }, - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "target", - "description": "" - } - ], - "description": { - "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", - "summary": "

    Copies the buffer.

    ", - "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "copy", - "string": "MongooseBuffer.prototype.copy()" - } - }, - { - "tags": [], - "description": { - "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", - "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", - "body": "" - }, - "ignore": true, - "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://bsonspec.org/#/specification", - "visibility": "http://bsonspec.org/#/specification" - }, - { - "type": "param", - "types": [ - "Hex" - ], - "name": "[subtype]", - "description": "" - }, - { - "type": "return", - "types": [ - "Binary" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", - "summary": "

    Converts this buffer to its Binary type representation.

    ", - "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "toObject", - "string": "MongooseBuffer.prototype.toObject()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "Binary", - "value": "Binary", - "string": "MongooseBuffer.Binary" - } - } -] -### lib/types/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", - "ctx": { - "type": "declaration", - "name": "MongooseArray", - "value": "require('./array')", - "string": "MongooseArray" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to this array" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "MongooseDocumentArray" - ], - "description": "" - }, - { - "type": "inherits", - "string": "MongooseArray" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    DocumentArray constructor

    ", - "summary": "

    DocumentArray constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseDocumentArray", - "string": "MongooseDocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseArray

    ", - "summary": "

    Inherits from MongooseArray

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseDocumentArray", - "name": "__proto__", - "value": "MongooseArray.prototype", - "string": "MongooseDocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Overrides MongooseArray#cast

    ", - "summary": "

    Overrides MongooseArray#cast

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype._cast = function (value) {\n if (value instanceof this._schema.casterConstructor)\n return value;\n\n return new this._schema.casterConstructor(value, this);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "_cast", - "string": "MongooseDocumentArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "EmbeddedDocument", - "null" - ], - "description": "the subdocuent or null if not found." - }, - { - "type": "param", - "types": [ - "ObjectId", - "String", - "Number", - "Buffer" - ], - "name": "id", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Searches array items for the first document with a matching id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", - "summary": "

    Searches array items for the first document with a matching id.

    ", - "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "id", - "string": "MongooseDocumentArray.prototype.id()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", - "summary": "

    Returns a native js Array of plain js objects

    ", - "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "toObject", - "string": "MongooseDocumentArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "inspect", - "string": "MongooseDocumentArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the value to cast to this arrays SubDocument schema" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", - "summary": "

    Creates a subdocument casted to this schema.

    ", - "body": "

    This is the same subdocument constructor used for casting.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "create", - "string": "MongooseDocumentArray.prototype.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Creates a fn that notifies all child docs of event.

    ", - "summary": "

    Creates a fn that notifies all child docs of event.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n if (!self[i]) continue;\n self[i].emit(event, val);\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "notify", - "string": "MongooseDocumentArray.prototype.notify()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseDocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseDocumentArray", - "string": "module.exports" - } - } -] -### lib/types/embedded.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Document = require('../document')\n , inspect = require('util').inspect;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('../document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "js object returned from the db" - }, - { - "type": "param", - "types": [ - "MongooseDocumentArray" - ], - "name": "parentArr", - "description": "the parent array of this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "skipId", - "description": "" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    EmbeddedDocument constructor.

    ", - "summary": "

    EmbeddedDocument constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", - "ctx": { - "type": "function", - "name": "EmbeddedDocument", - "string": "EmbeddedDocument()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Document

    ", - "summary": "

    Inherit from Document

    ", - "body": "" - }, - "ignore": true, - "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "EmbeddedDocument", - "name": "__proto__", - "value": "Document.prototype", - "string": "EmbeddedDocument.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path which changed" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", - "summary": "

    Marks the embedded doc modified.

    ", - "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "markModified", - "string": "EmbeddedDocument.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "return", - "types": [ - "EmbeddedDocument" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", - "summary": "

    Used as a stub for hooks.js

    ", - "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "save", - "string": "EmbeddedDocument.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes the subdocument from its parent array.

    ", - "summary": "

    Removes the subdocument from its parent array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "remove", - "string": "EmbeddedDocument.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Override #update method of parent documents.

    ", - "summary": "

    Override #update method of parent documents.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "update", - "string": "EmbeddedDocument.prototype.update()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "inspect", - "string": "EmbeddedDocument.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "error which states the reason `path` was invalid" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks a path as invalid, causing validation to fail.

    ", - "summary": "

    Marks a path as invalid, causing validation to fail.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "invalidate", - "string": "EmbeddedDocument.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the top level document of this sub-document.

    ", - "summary": "

    Returns the top level document of this sub-document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "ownerDocument", - "string": "EmbeddedDocument.prototype.ownerDocument()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the top level document of this sub-document.

    ", - "summary": "

    Returns the top level document of this sub-document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", - "ctx": { - "type": "function", - "name": "ownerDocument", - "string": "ownerDocument()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns this sub-documents parent document.

    ", - "summary": "

    Returns this sub-documents parent document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parent", - "string": "EmbeddedDocument.prototype.parent()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns this sub-documents parent array.

    ", - "summary": "

    Returns this sub-documents parent array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parentArray", - "string": "EmbeddedDocument.prototype.parentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = EmbeddedDocument;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "EmbeddedDocument", - "string": "module.exports" - } - } -] -### lib/types/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "Array", - "value": "require('./array')", - "string": "exports.Array" - } - } -] -### lib/types/objectid.js -[ - { - "tags": [], - "description": { - "full": "

    Access driver.

    ", - "summary": "

    Access driver.

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [ - { - "type": "constructor", - "string": "ObjectId" - } - ], - "description": { - "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", - "summary": "

    ObjectId type constructor

    ", - "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require(driver + '/objectid')", - "string": "ObjectId" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "str", - "description": "" - }, - { - "type": "static", - "string": "fromString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "ObjectId" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Creates an ObjectId from str

    ", - "summary": "

    Creates an ObjectId from str

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.fromString;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId" - ], - "name": "oid", - "description": "ObjectId instance" - }, - { - "type": "static", - "string": "toString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts oid to a string.

    ", - "summary": "

    Converts oid to a string.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.toString;" - } -] -### lib/utils.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , sliced = require('sliced')\n , MongooseBuffer\n , MongooseArray\n , Document", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "a model name" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "a collection name" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Produces a collection name from model name.

    ", - "summary": "

    Produces a collection name from model name.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "toCollectionName", - "string": "exports.toCollectionName()" - } - }, - { - "tags": [], - "description": { - "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", - "summary": "

    Pluralization rules.

    ", - "body": "

    These rules are applied while processing the argument to toCollectionName.

    " - }, - "ignore": false, - "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "pluralization", - "value": "[", - "string": "exports.pluralization" - } - }, - { - "tags": [], - "description": { - "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", - "summary": "

    Uncountable words.

    ", - "body": "

    These words are applied while processing the argument to toCollectionName.

    " - }, - "ignore": false, - "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news',\n 'expertise',\n 'status',\n 'media'\n];\nvar uncountables = exports.uncountables;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "uncountables", - "value": "[", - "string": "exports.uncountables" - } - }, - { - "tags": [ - { - "type": "author", - "string": "TJ Holowaychuk (extracted from _ext.js_)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "string", - "description": "to pluralize" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Pluralize function.

    ", - "summary": "

    Pluralize function.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", - "ctx": { - "type": "function", - "name": "pluralize", - "string": "pluralize()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "listener", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Add once to EventEmitter if absent

    ", - "summary": "

    Add once to EventEmitter if absent

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", - "ctx": { - "type": "declaration", - "name": "Events", - "value": "EventEmitter", - "string": "Events" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Events", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Events.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Add once.

    ", - "summary": "

    Add once.

    ", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", - "ctx": { - "type": "method", - "constructor": "Events", - "name": "once", - "string": "Events.prototype.once()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "a", - "description": "a value to compare to `b`" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "b", - "description": "a value to compare to `a`" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", - "summary": "

    Determines if a and b are deep equal.

    ", - "body": "

    Modified from node/lib/assert.js

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "deepEqual", - "string": "exports.deepEqual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the object to clone" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the cloned object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Object clone with Mongoose natives support.

    \n\n

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    ", - "summary": "

    Object clone with Mongoose natives support.

    ", - "body": "

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId)\n return new ObjectId(obj.id);\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "clone", - "string": "exports.clone()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", - "ctx": { - "type": "function", - "name": "cloneObject", - "string": "cloneObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "defaults", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the merged object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Copies and merges options with defaults.

    ", - "summary": "

    Copies and merges options with defaults.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "options", - "string": "exports.options()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Generates a random string

    ", - "summary": "

    Generates a random string

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "random", - "string": "exports.random()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "to", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "from", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Merges from into to without overwriting existing properties.

    ", - "summary": "

    Merges from into to without overwriting existing properties.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n if (exports.isObject(from[key])) {\n merge(to[key], from[key]);\n } else {\n to[key] = from[key];\n }\n }\n }\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "merge", - "string": "exports.merge()" - } - }, - { - "tags": [], - "description": { - "full": "

    toString helper

    ", - "summary": "

    toString helper

    ", - "body": "" - }, - "ignore": true, - "code": "var toString = Object.prototype.toString;", - "ctx": { - "type": "declaration", - "name": "toString", - "value": "Object.prototype.toString", - "string": "toString" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "Array", - "String", - "Function", - "RegExp", - "any" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - } - ], - "description": { - "full": "

    Determines if arg is an object.

    ", - "summary": "

    Determines if arg is an object.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "exports.isObject = function (arg) {\n return '[object Object]' == toString(arg);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isObject", - "string": "exports.isObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", - "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.args = sliced;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "args", - "value": "sliced", - "string": "exports.args" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", - "summary": "

    process.nextTick helper.

    ", - "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "tick", - "string": "exports.tick()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "v", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", - "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", - "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isMongooseObject", - "string": "exports.isMongooseObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "object", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", - "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expireAfterSeconds = when;\n delete object.expires;\n}\n\nexports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "expires", - "string": "exports.expires()" - } - } -] -### lib/virtualtype.js -[ - { - "tags": [ - { - "type": "parma", - "string": "{Object} options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", - "summary": "

    VirtualType constructor

    ", - "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", - "ctx": { - "type": "function", - "name": "VirtualType", - "string": "VirtualType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", - "summary": "

    Defines a getter.

    ", - "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "get", - "string": "VirtualType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", - "summary": "

    Defines a setter.

    ", - "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "set", - "string": "VirtualType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all getters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Applies getters to value using optional scope.

    ", - "summary": "

    Applies getters to value using optional scope.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applyGetters", - "string": "VirtualType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all setters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Applies setters to value using optional scope.

    ", - "summary": "

    Applies setters to value using optional scope.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applySetters", - "string": "VirtualType.prototype.applySetters()" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = VirtualType;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "VirtualType", - "string": "module.exports" - } - } -] diff --git a/docs/3.3.x/docs/source/api.js b/docs/3.3.x/docs/source/api.js deleted file mode 100644 index 8fd87f0035b..00000000000 --- a/docs/3.3.x/docs/source/api.js +++ /dev/null @@ -1,220 +0,0 @@ -/*! - * Module dependencies - */ - -var fs = require('fs'); -var link = require('../helpers/linktype'); -var hl = require('highlight.js') -var md = require('markdown') - -module.exports = { - docs: [] - , github: 'https://github.com/LearnBoost/mongoose/tree/' - , title: 'API docs' -} - -var out = module.exports.docs; - -var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); -parse(docs); -order(out); - -function parse (docs) { - docs.split(/^### /gm).forEach(function (chunk) { - if (!(chunk = chunk.trim())) return; - - chunk = chunk.split(/^([^\n]+)\n/); - - var title = chunk[1]; - - if (!title || !(title = title.trim())) - throw new Error('missing title'); - - title = title.replace(/^lib\//, ''); - - var json = JSON.parse(chunk[2]); - - var props = []; - var methods = []; - var statics = []; - var constructor = null; - - json.forEach(function (comment) { - if (comment.description) - highlight(comment.description); - - var prop = false; - comment.params = []; - comment.see = []; - - var i = comment.tags.length; - while (i--) { - var tag = comment.tags[i]; - switch (tag.type) { - case 'property': - prop = true; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - props.unshift(comment); - break; - case 'method': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'method'; - comment.code = ''; - break; - case 'memberOf': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.constructor = tag.parent; - break; - case 'static': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - comment.ctx.type = 'method'; - break; - case 'receiver': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.receiver = tag.string; - break; - case 'constructor': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'function'; - comment.code = ''; - break; - case 'inherits': - if (/http/.test(tag.string)) { - var result = tag.string.split(' '); - var href = result.pop(); - var title = result.join(' '); - comment.inherits = '' + title + ''; - } else { - comment.inherits = link(tag.string); - } - comment.tags.splice(i, 1); - break; - case 'param': - comment.params.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'return': - comment.return = tag; - comment.tags.splice(i, 1); - break; - case 'see': - if (tag.local) { - var parts = tag.local.split(' '); - if (1 === parts.length) { - tag.url = link.type(parts[0]); - tag.title = parts[0]; - } else { - tag.url = parts.pop(); - tag.title = parts.join(' '); - } - } - comment.see.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'event': - var str = tag.string.replace(/\\n/g, '\n'); - tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); - comment.events || (comment.events = []); - comment.events.unshift(tag); - comment.tags.splice(i, 1); - } - } - - if (!prop) { - methods.push(comment); - } - }); - - methods = methods.filter(ignored); - props = props.filter(ignored); - - function ignored (method) { - if (method.ignore) return false; - return true; - } - - if (0 === methods.length + props.length) return; - - // add constructor to properties too - methods.some(function (method) { - if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { - props.forEach(function (prop) { - prop.ctx.constructor = method.ctx.constructor; - }); - return true; - } - return false; - }); - - var len = methods.length; - while (len--) { - method = methods[len]; - if (method.ctx && method.ctx.receiver) { - var stat = methods.splice(len, 1)[0]; - statics.unshift(stat); - } - } - - out.push({ - title: title - , methods: methods - , props: props - , statics: statics - , hasPublic: hasPublic(methods, props, statics) - }); - }); -} - -function hasPublic () { - for (var i = 0; i < arguments.length; ++i) { - var arr = arguments[i]; - for (var j = 0; j < arr.length; ++j) { - var item = arr[j]; - if (!item.ignore && !item.isPrivate) return true; - } - } - return false; -} - -// add "class='language'" to our
     elements
    -function highlight (o) {
    -  o.full = fix(o.full);
    -  o.summary = fix(o.summary);
    -  o.body = fix(o.body);
    -}
    -
    -function fix (str) {
    -  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    -
    -    // parse out the ```language
    -    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    -
    -    if ('js' == code[1] || !code[1]) {
    -      code[1] = 'javascript';
    -    }
    -
    -    return $1
    -          + hl.highlight(code[1], code[2]).value.trim()
    -          + $3;
    -  });
    -}
    -
    -function order (docs) {
    -  // want index first
    -  for (var i = 0; i < docs.length; ++i) {
    -    if ('index.js' == docs[i].title) {
    -      docs.unshift(docs.splice(i, 1)[0]);
    -    }
    -  }
    -}
    diff --git a/docs/3.3.x/docs/source/home.js b/docs/3.3.x/docs/source/home.js
    deleted file mode 100644
    index e349d8ddcad..00000000000
    --- a/docs/3.3.x/docs/source/home.js
    +++ /dev/null
    @@ -1,7 +0,0 @@
    -
    -var package = require('./../../package.json')
    -
    -module.exports = {
    -    package: package
    -  , title: 'ODM'
    -}
    diff --git a/docs/3.3.x/docs/source/index.js b/docs/3.3.x/docs/source/index.js
    deleted file mode 100644
    index 18b3eeb5718..00000000000
    --- a/docs/3.3.x/docs/source/index.js
    +++ /dev/null
    @@ -1,20 +0,0 @@
    -
    -exports['index.jade'] = require('./home')
    -exports['docs/api.jade'] = require('./api')
    -exports['docs/index.jade'] = { title: 'Getting Started' }
    -exports['docs/production.jade'] = require('./production')
    -exports['docs/prior.jade'] = require('./prior')
    -exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    -exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    -exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    -exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    -exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    -exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    -exports['docs/models.jade'] = { guide: true, title: 'Models' }
    -exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    -exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    -exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    -exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    -exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    -exports['docs/connections.jade'] = { guide: true, title: 'Connecting to MongoDB' }
    -exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.3.x/docs/source/prior.js b/docs/3.3.x/docs/source/prior.js
    deleted file mode 100644
    index 2e03811d215..00000000000
    --- a/docs/3.3.x/docs/source/prior.js
    +++ /dev/null
    @@ -1,13 +0,0 @@
    -var fs = require('fs')
    -var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    -releases = releases.split('\n').filter(Boolean);
    -
    -module.exports = exports = {
    -    title: ''
    -  , releases: releases.map(function (version) {
    -      return {
    -          url: version + '/'
    -        , version: version
    -      }
    -    })
    -}
    diff --git a/docs/3.3.x/docs/source/production.js b/docs/3.3.x/docs/source/production.js
    deleted file mode 100644
    index 9fdbcfffbc7..00000000000
    --- a/docs/3.3.x/docs/source/production.js
    +++ /dev/null
    @@ -1,17 +0,0 @@
    -
    -var fs = require('fs')
    -var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    -
    -var imgs = [];
    -
    -images.forEach(function (line) {
    -  line = line.trim();
    -  if (!line) return;
    -  line = line.split('|');
    -  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    -});
    -
    -module.exports = {
    -    images: imgs
    -  , title: 'Production'
    -}
    diff --git a/docs/3.3.x/docs/subdocs.html b/docs/3.3.x/docs/subdocs.html
    deleted file mode 100644
    index 42f1c21c61d..00000000000
    --- a/docs/3.3.x/docs/subdocs.html
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -Mongoose SubDocuments v3.3.1Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    -
    -var parentSchema = new Schema({
    -  children: [childSchema]
    -})
    -

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = db.model('Parent', parentSchema);
    -var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    -parent.children[0].name = 'Matthew';
    -parent.save(callback);
    -

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    -  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    -  next();
    -});
    -
    -var parent = new Parent({ children: [{ name: 'invalid' }] });
    -parent.save(function (err) {
    -  console.log(err.message) // #sadpanda
    -})
    -

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    -

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = db.model('Parent');
    -var parent = new Parent;
    -
    -// create a comment
    -post.children.push({ name: 'Liesl' });
    -var doc = post.children[0];
    -console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    -doc.isNew; // true
    -
    -post.save(function (err) {
    -  if (err) return handleError(err)
    -  console.log('Success!');
    -});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    -

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    -parent.save(function (err) {
    -  if (err) return handleError(err);
    -  console.log('the sub-doc was removed')
    -});
    -

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    -  children: [{ name: 'string' }]
    -})
    -

    Next Up

    Now that we've covered Sub-documents, let's take a look at querying.

    diff --git a/docs/3.3.x/docs/subdocs.jade b/docs/3.3.x/docs/subdocs.jade deleted file mode 100644 index 9e568e3ab74..00000000000 --- a/docs/3.3.x/docs/subdocs.jade +++ /dev/null @@ -1,84 +0,0 @@ -extends layout - -block content - h2 Sub Docs - :markdown - [Sub-documents](./api.html#types-embedded-js) are docs with schemas of their own which are elements of a parents document array: - :js - var childSchema = new Schema({ name: 'string' }); - - var parentSchema = new Schema({ - children: [childSchema] - }) - - :markdown - Sub-documents enjoy all the same features as normal [documents](./api.html#document-js). The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved. - :js - var Parent = db.model('Parent', parentSchema); - var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) - parent.children[0].name = 'Matthew'; - parent.save(callback); - - :markdown - If an error occurs in a sub-documents' middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap! - - :js - childSchema.pre('save', function (next) { - if ('invalid' == this.name) return next(new Error('#sadpanda')); - next(); - }); - - var parent = new Parent({ children: [{ name: 'invalid' }] }); - parent.save(function (err) { - console.log(err.message) // #sadpanda - }) - - h3 Finding a sub-document - :markdown - Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. - :js - var doc = parent.children.id(id); - - h3 Adding sub-docs - :markdown - MongooseArray methods such as [push](./api.html#types_array_MongooseArray-push), [unshift](./api.html#types_array_MongooseArray-unshift), [addToSet](./api.html#types_array_MongooseArray-addToSet), and others cast arguments to their proper types transparently: - :js - var Parent = db.model('Parent'); - var parent = new Parent; - - // create a comment - post.children.push({ name: 'Liesl' }); - var doc = post.children[0]; - console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' } - doc.isNew; // true - - post.save(function (err) { - if (err) return handleError(err) - console.log('Success!'); - }); - :markdown - Sub-docs may also be created without adding them to the array by using the [create](./api.html#types_documentarray_MongooseDocumentArray-create) method of MongooseArrays. - :js - var newdoc = post.children.create({ name: 'Aaron' }); - - h3 Removing docs - :markdown - Each sub-document has it's own [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. - :js - var doc = parent.children.id(id).remove(); - parent.save(function (err) { - if (err) return handleError(err); - console.log('the sub-doc was removed') - }); - - h4#altsyntax Alternate declaration syntax - :markdown - _New in v3_ If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal: - :js - var parentSchema = new Schema({ - children: [{ name: 'string' }] - }) - - h3#next Next Up - :markdown - Now that we've covered `Sub-documents`, let's take a look at [querying](/docs/queries.html). diff --git a/docs/3.3.x/docs/validation.html b/docs/3.3.x/docs/validation.html deleted file mode 100644 index 7a7d182e83e..00000000000 --- a/docs/3.3.x/docs/validation.html +++ /dev/null @@ -1,37 +0,0 @@ -Mongoose Validation v3.3.1Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    - -
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    - -

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    -  color: String,
    -  name: String
    -});
    -
    -var Toy = db.model('Toy', toySchema);
    -
    -Toy.schema.path('color').validate(function (value) {
    -  return /blue|green|white|red|orange|periwinkel/i.test(value);
    -}, 'Invalid color');
    -
    -var toy = new Toy({ color: 'grease'});
    -
    -toy.save(function (err) {
    -  // err.errors.color is a ValidatorError object
    -  
    -  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    -  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    -  console.log(err.errors.color.type) // prints "Invalid color"
    -  console.log(err.errors.color.path) // prints "color"
    -  console.log(err.name) // prints "ValidationError"
    -  console.log(err.message) // prints "Validation failed"
    -});
    -

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    -

    Next Up

    Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

    diff --git a/docs/3.3.x/docs/validation.jade b/docs/3.3.x/docs/validation.jade deleted file mode 100644 index 5b267bf95a5..00000000000 --- a/docs/3.3.x/docs/validation.jade +++ /dev/null @@ -1,58 +0,0 @@ -extends layout - -block content - h2 Validation - :markdown - Before we get into the specifics of validation syntax, please keep the following rules in mind: - - - Validation is defined in the [SchemaType](./schematypes.html) - - Validation is an internal piece of [middleware](./middleware.html) - - Validation occurs when a document attempts to be [saved](./api.html#model_Model-save), after defaults have been applied - - Validation is asynchronously recursive: when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed. If an error happens, your Model#save callback receives it - - Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, `"min"` is the identifier for the error triggered when a number doesn't meet the [minimum value](./api.html#schema_number_SchemaNumber-min). The path and value that triggered the error can be accessed in the `ValidationError` object - h3 Built in validators - :markdown - Mongoose has several built in validators. - - - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. - - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. - - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum) and [match](./api.html#schema_string_SchemaString-match) validators. - h3 Custom validators - :markdown - Custom validation is declared by passing a validation `function` and an error type to your `SchemaType`s validate method. Read the [API](./api.html#schematype_SchemaType-validate) docs for details on custom validators, async validators, and more. - h3 Validation errors - :markdown - Errors returned after failed validation contain an `errors` object holding the actual `ValidatorErrors`. Each [ValidatorError](./api.html#errors-validation-js) has a `type` and `path` property providing us with a little more error handling flexibility. - :js - var toySchema = new Schema({ - color: String, - name: String - }); - - var Toy = db.model('Toy', toySchema); - - Toy.schema.path('color').validate(function (value) { - return /blue|green|white|red|orange|periwinkel/i.test(value); - }, 'Invalid color'); - - var toy = new Toy({ color: 'grease'}); - - toy.save(function (err) { - // err.errors.color is a ValidatorError object - - console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color' - console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color' - console.log(err.errors.color.type) // prints "Invalid color" - console.log(err.errors.color.path) // prints "color" - console.log(err.name) // prints "ValidationError" - console.log(err.message) // prints "Validation failed" - }); - - :markdown - After a validation error, the document will also have the same `errors` property available: - :js - toy.errors.color.message === err.errors.color.message - - h3#next Next Up - :markdown - Now that we've covered `validation`, let's take a look at how you might handle advanced validation with Mongoose's [middleware](/docs/middleware.html). diff --git a/docs/3.3.x/docs/website.js b/docs/3.3.x/docs/website.js deleted file mode 100644 index d1adea38b5c..00000000000 --- a/docs/3.3.x/docs/website.js +++ /dev/null @@ -1,48 +0,0 @@ - -var fs= require('fs') -var jade = require('jade') -var package = require('./package') -var hl = require('./docs/helpers/highlight') -var linktype = require('./docs/helpers/linktype') -var href = require('./docs/helpers/href') -var klass = require('./docs/helpers/klass') - -// add custom jade filters -require('./docs/helpers/filters')(jade); - -// clean up version for ui -package.version = package.version.replace(/-pre$/, ''); - -var filemap = require('./docs/source'); -var files = Object.keys(filemap); - -files.forEach(function (file) { - var filename = __dirname + '/' + file; - jadeify(filename, filemap[file]); - - if ('--watch' == process.argv[2]) { - fs.watchFile(filename, { interval: 1000 }, function (cur, prev) { - if (cur.mtime > prev.mtime) { - jadeify(filename, filemap[file]); - } - }); - } -}); - -function jadeify (filename, options) { - options || (options = {}); - options.package = package; - options.hl = hl; - options.linktype = linktype; - options.href = href; - options.klass = klass; - jade.renderFile(filename, options, function (err, str) { - if (err) return console.error(err.stack); - - var newfile = filename.replace('.jade', '.html') - fs.writeFile(newfile, str, function (err) { - if (err) return console.error('could not write', err.stack); - console.log('%s : rendered ', new Date, newfile); - }); - }); -} diff --git a/docs/3.3.x/index.html b/docs/3.3.x/index.html deleted file mode 100644 index ceb880d8c89..00000000000 --- a/docs/3.3.x/index.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose ODM v3.3.1Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

    var mongoose = require('mongoose');
    -var db = mongoose.createConnection('localhost', 'test');
    -
    -var schema = mongoose.Schema({ name: 'string' });
    -var Cat = db.model('Cat', schema);
    -
    -var kitty = new Cat({ name: 'Zildjian' });
    -kitty.save(function (err) {
    -  if (err) // ...
    -  res.end('meow');
    -});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    Production - View More

    • Storify
    • LearnBoost
    • GeekList
    • McDonalds
    • ShoeJitsu
    • Bozuko
    \ No newline at end of file diff --git a/docs/3.3.x/static.js b/docs/3.3.x/static.js deleted file mode 100644 index fc0e722dd4e..00000000000 --- a/docs/3.3.x/static.js +++ /dev/null @@ -1,17 +0,0 @@ - -var static = require('node-static'); -var server = new static.Server('.', { cache: 0 }); - -require('http').createServer(function (req, res) { - req.on('end', function () { - server.serve(req, res, function (err) { - if (err) { - console.error(err, req.url); - res.writeHead(err.status, err.headers); - res.end(); - } - }); - }); -}).listen(8088); - -console.error('now listening on localhost:8088'); diff --git a/docs/3.4.x/docs/api.html b/docs/3.4.x/docs/api.html deleted file mode 100644 index 53740ed405f..00000000000 --- a/docs/3.4.x/docs/api.html +++ /dev/null @@ -1,6999 +0,0 @@ -Mongoose API v3.4.0Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      -  this.connections = [];
      -  this.plugins = [];
      -  this.models = {};
      -  this.modelSchemas = {};
      -  this.options = {};
      -  this.createConnection(); // default connection
      -};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      -  if (arguments.length == 1)
      -    return this.options[key];
      -  this.options[key] = value;
      -  return this;
      -};

      Parameters:

      Example:

      - -
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      - -
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri], [options])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      -  var conn = new Connection(this);
      -  this.connections.push(conn);
      -
      -  if (arguments.length) {
      -    if (rgxReplSet.test(arguments[0])) {
      -      conn.openSet.apply(conn, arguments);
      -    } else {
      -      conn.open.apply(conn, arguments);
      -    }
      -  }
      -
      -  return conn;
      -};

      Parameters:

      • [uri] <String> a mongodb:// URI
      • [options] <Object> options to pass to the driver

      Returns:

      Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

      - -

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver. Note that the safe option specified in your schema will overwrite the safe db option specified here unless you set your schemas safe option to undefined. See this for more information.

      - -

      Example:

      - -
      // with mongodb:// URI
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
      -
      -// and options
      -var opts = { db: { native_parser: true }}
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
      -
      -// replica sets
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
      -
      -// and options
      -var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
      -
      -// with [host, database_name[, port] signature
      -db = mongoose.createConnection('localhost', 'database', port)
      -
      -// and options
      -var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
      -db = mongoose.createConnection('localhost', 'database', port, opts)
      -
      -// initialize now, connect later
      -db = mongoose.createConnection();
      -db.open('localhost', 'database', port, [opts]);

      Mongoose#connect()

      Opens the default mongoose connection.

      show code
      Mongoose.prototype.connect = function () {
      -  var conn = this.connection;
      -
      -  if (rgxReplSet.test(arguments[0])) {
      -    conn.openSet.apply(conn, arguments);
      -  } else {
      -    conn.open.apply(conn, arguments);
      -  }
      -
      -  return this;
      -};

      Returns:

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


      Mongoose#disconnect([fn])

      Disconnects all connections.

      show code
      Mongoose.prototype.disconnect = function (fn) {
      -  var count = this.connections.length
      -    , error
      -
      -  this.connections.forEach(function(conn){
      -    conn.close(function(err){
      -      if (error) return;
      -
      -      if (err) {
      -        error = err;
      -        if (fn) return fn(err);
      -        throw err;
      -      }
      -
      -      if (fn)
      -        --count || fn();
      -    });
      -  });
      -  return this;
      -};

      Parameters:

      • [fn] <Function> called after all connection close.

      Returns:


      Mongoose#model(name, [schema], [collection], [skipInit])

      Defines a model or retrieves it.

      show code
      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
      -  if (!(schema instanceof Schema)) {
      -    collection = schema;
      -    schema = false;
      -  }
      -
      -  if ('boolean' === typeof collection) {
      -    skipInit = collection;
      -    collection = null;
      -  }
      -
      -  // look up models for the collection
      -  if (!this.modelSchemas[name]) {
      -    if (!schema && name in SchemaDefaults) {
      -      schema = SchemaDefaults[name];
      -    }
      -
      -    if (schema) {
      -      this.modelSchemas[name] = schema;
      -      for (var i = 0, l = this.plugins.length; i < l; i++) {
      -        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
      -      }
      -    } else {
      -      throw new Error('Schema hasn\'t been registered for model "' + name + '".
      -'
      -                    + 'Use mongoose.model(name, schema)');
      -    }
      -  }
      -
      -  if (!this.models[name]) {
      -    schema || (schema = this.modelSchemas[name]);
      -    collection || (collection = schema.set('collection') || format(name));
      -
      -    var model = Model.compile(name
      -                        , this.modelSchemas[name]
      -                        , collection
      -                        , this.connection
      -                        , this);
      -
      -    if (!skipInit) model.init();
      -
      -    this.models[name] = model;
      -  }
      -
      -  return this.models[name];
      -};

      Parameters:

      • name <String> model name
      • [schema] <Schema>
      • [collection] <String> name (optional, induced from model name)
      • [skipInit] <Boolean> whether to skip initialization (defaults to false)

      Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -
      -// define an Actor model with this mongoose instance
      -mongoose.model('Actor', new Schema({ name: String }));
      -
      -// create a new connection
      -var conn = mongoose.createConnection(..);
      -
      -// retrieve the Actor model
      -var Actor = conn.model('Actor');
      - -

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

      - -

      Example:

      - -
      var schema = new Schema({ name: String });
      -schema.set('collection', 'actor');

      Mongoose#plugin(fn, [opts])

      Declares a global plugin executed on all Schemas.

      show code
      Mongoose.prototype.plugin = function (fn, opts) {
      -  this.plugins.push([fn, opts]);
      -  return this;
      -};

      Parameters:

      Returns:

      Equivalent to calling .plugin(fn) on each Schema you create.


      module.exports

      The exports object is an instance of Mongoose.

      show code
      module.exports = exports = new Mongoose;
      -var mongoose = module.exports;

      mongoose.Collection

      The Mongoose Collection constructor

      show code
      mongoose.Collection = Collection;

      mongoose.Connection

      The Mongoose Connection constructor

      show code
      mongoose.Connection = Connection;

      mongoose.version

      Mongoose version

      show code
      mongoose.version = JSON.parse(
      -  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      -).version;

      mongoose.Mongoose

      The Mongoose constructor

      show code
      mongoose.Mongoose = Mongoose;

      The exports of the mongoose module is an instance of this class.

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -var mongoose2 = new mongoose.Mongoose();

      mongoose.Schema

      The Mongoose Schema constructor

      show code
      mongoose.Schema = Schema;

      Example:

      - -
      var mongoose = require('mongoose');
      -var Schema = mongoose.Schema;
      -var CatSchema = new Schema(..);

      mongoose.SchemaType

      The Mongoose SchemaType constructor.

      show code
      mongoose.SchemaType = SchemaType;

      mongoose.SchemaTypes

      The various Mongoose SchemaTypes.

      show code
      mongoose.SchemaTypes = Schema.Types;

      Note:

      - -

      Alias of mongoose.Schema.Types for backwards compatibility.


      mongoose.VirtualType

      The Mongoose VirtualType constructor.

      show code
      mongoose.VirtualType = VirtualType;

      mongoose.Types

      The various Mongoose Types.

      show code
      mongoose.Types = Types;

      Example:

      - -
      var mongoose = require('mongoose');
      -var array = mongoose.Types.Array;
      - -

      Types:

      - -
        -
      • Array
      • -
      • Buffer
      • -
      • Document
      • -
      • Embedded
      • -
      • DocumentArray
      • -
      • ObjectId
      • -
      - -

      Using this exposed access to the ObjectId type, we can construct ids on demand.

      - -
      var ObjectId = mongoose.Types.ObjectId;
      -var id1 = new ObjectId;

      mongoose.Query

      The Mongoose Query constructor.

      show code
      mongoose.Query = Query;

      mongoose.Promise

      The Mongoose Promise constructor.

      show code
      mongoose.Promise = Promise;

      mongoose.Model

      The Mongoose Model constructor.

      show code
      mongoose.Model = Model;

      mongoose.Document

      The Mongoose Document constructor.

      show code
      mongoose.Document = Document;

      mongoose.Error

      The MongooseError constructor.

      show code
      mongoose.Error = require('./error');

      mongoose.mongo

      The node-mongodb-native driver Mongoose uses.

      show code
      mongoose.mongo = require('mongodb');

      Mongoose#connection

      The default connection of the mongoose module.

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -mongoose.connect(...);
      -mongoose.connection.on('error', cb);
      - -

      This is the connection used by default for every model created using mongoose.model.

      Returns:


    • collection.js

      Collection(name, conn, opts)

      Abstract Collection constructor

      show code
      function Collection (name, conn, opts) {
      -  this.name = name;
      -  this.conn = conn;
      -  this.buffer = true;
      -  this.queue = [];
      -
      -  if ('number' == typeof opts) opts = { size: opts };
      -  this.opts = opts || {};
      -
      -  if (STATES.connected == this.conn.readyState) {
      -    this.onOpen();
      -  }
      -};

      Parameters:

      • name <String> name of the collection
      • conn <Connection> A MongooseConnection instance
      • opts <Object> optional collection options

      This is the base class that drivers inherit from and implement.


      Collection#onOpen()

      Called when the database connects

      show code
      Collection.prototype.onOpen = function () {
      -  var self = this;
      -  this.buffer = false;
      -  self.doQueue();
      -};

      Collection#onClose()

      Called when the database disconnects

      show code
      Collection.prototype.onClose = function () {
      -  this.buffer = true;
      -};

      Collection#addQueue(name, args)

      Queues a method for later execution when its
      database connection opens.

      show code
      Collection.prototype.addQueue = function (name, args) {
      -  this.queue.push([name, args]);
      -  return this;
      -};

      Parameters:

      • name <String> name of the method to queue
      • args <Array> arguments to pass to the method when executed

      Collection#doQueue()

      Executes all queued methods and clears the queue.

      show code
      Collection.prototype.doQueue = function () {
      -  for (var i = 0, l = this.queue.length; i < l; i++){
      -    this[this.queue[i][0]].apply(this, this.queue[i][1]);
      -  }
      -  this.queue = [];
      -  return this;
      -};

      Collection#ensureIndex()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.ensureIndex = function(){
      -  throw new Error('Collection#ensureIndex unimplemented by driver');
      -};

      Collection#findAndModify()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findAndModify = function(){
      -  throw new Error('Collection#findAndModify unimplemented by driver');
      -};

      Collection#findOne()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findOne = function(){
      -  throw new Error('Collection#findOne unimplemented by driver');
      -};

      Collection#find()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.find = function(){
      -  throw new Error('Collection#find unimplemented by driver');
      -};

      Collection#insert()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.insert = function(){
      -  throw new Error('Collection#insert unimplemented by driver');
      -};

      Collection#save()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.save = function(){
      -  throw new Error('Collection#save unimplemented by driver');
      -};

      Collection#update()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.update = function(){
      -  throw new Error('Collection#update unimplemented by driver');
      -};

      Collection#getIndexes()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.getIndexes = function(){
      -  throw new Error('Collection#getIndexes unimplemented by driver');
      -};

      Collection#mapReduce()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.mapReduce = function(){
      -  throw new Error('Collection#mapReduce unimplemented by driver');
      -};

      Collection#conn

      The Connection instance


      Collection#name

      The collection name


    • connection.js

      Connection(base)

      Connection constructor

      show code
      function Connection (base) {
      -  this.base = base;
      -  this.collections = {};
      -  this.models = {};
      -  this.replica = false;
      -  this.host = null;
      -  this.port = null;
      -  this.user = null;
      -  this.pass = null;
      -  this.name = null;
      -  this.options = null;
      -  this._readyState = STATES.disconnected;
      -  this._closeCalled = false;
      -  this._hasOpened = false;
      -};

      Parameters:

      Events:

      • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

      • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

      • open: Emitted after we connected and onOpen is executed on all of this connections models.

      • disconnecting: Emitted when connection.close() was executed.

      • disconnected: Emitted after getting disconnected from the db.

      • close: Emitted after we disconnected and onClose executed on all of this connections models.

      • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

      • error: Emitted when an error occurs on this connection.

      • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

      For practical reasons, a Connection equals a Db.


      Connection#open(connection_string, [database], [port], [options], [callback])

      Opens the connection to MongoDB.

      show code
      Connection.prototype.open = function (host, database, port, options, callback) {
      -  var self = this
      -    , uri;
      -
      -  if ('string' === typeof database) {
      -    switch (arguments.length) {
      -      case 2:
      -        port = 27017;
      -      case 3:
      -        switch (typeof port) {
      -          case 'function':
      -            callback = port, port = 27017;
      -            break;
      -          case 'object':
      -            options = port, port = 27017;
      -            break;
      -        }
      -        break;
      -      case 4:
      -        if ('function' === typeof options)
      -          callback = options, options = {};
      -    }
      -  } else {
      -    switch (typeof database) {
      -      case 'function':
      -        callback = database, database = undefined;
      -        break;
      -      case 'object':
      -        options = database;
      -        database = undefined;
      -        callback = port;
      -        break;
      -    }
      -
      -    if (!rgxProtocol.test(host)) {
      -      host = 'mongodb://' + host;
      -    }
      -
      -    uri = url.parse(host);
      -    host = uri.hostname;
      -    port = uri.port || 27017;
      -    database = uri.pathname && uri.pathname.replace(/\//g, '');
      -  }
      -
      -  this.options = this.defaultOptions(options);
      -
      -  // make sure we can open
      -  if (STATES.disconnected !== this.readyState) {
      -    var err = new Error('Trying to open unclosed connection.');
      -    err.state = this.readyState;
      -    this.error(err, callback);
      -    return this;
      -  }
      -
      -  if (!host) {
      -    this.error(new Error('Missing hostname.'), callback);
      -    return this;
      -  }
      -
      -  if (!database) {
      -    this.error(new Error('Missing database name.'), callback);
      -    return this;
      -  }
      -
      -  // handle authentication
      -  if (uri && uri.auth) {
      -    var auth = uri.auth.split(':');
      -    this.user = auth[0];
      -    this.pass = auth[1];
      -
      -  // Check hostname for user/pass
      -  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
      -    host = host.split('@');
      -    var auth = host.shift().split(':');
      -    host = host.pop();
      -    this.user = auth[0];
      -    this.pass = auth[1];
      -
      -  // user/pass options
      -  } else if (options && options.user && options.pass) {
      -    this.user = options.user;
      -    this.pass = options.pass;
      -
      -  } else {
      -    this.user = this.pass = undefined;
      -  }
      -
      -  this.name = database;
      -  this.host = host;
      -  this.port = port;
      -
      -  this._open(callback);
      -  return this;
      -};

      Parameters:

      • connection_string <String> mongodb://uri or the host to which you are connecting
      • [database] <String> database name
      • [port] <Number> database port
      • [options] <Object> options
      • [callback] <Function>

      options is a hash with the following possible properties:

      - -
      db      - passed to the connection db instance
      -server  - passed to the connection server instance(s)
      -replset - passed to the connection ReplSet instance
      -user    - username for authentication
      -pass    - password for authentication
      - -

      Notes:

      - -

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.


      Connection#openSet(uris, [database], [options], [callback])

      Connects to a replica set.

      show code
      Connection.prototype.openSet = function (uris, database, options, callback) {
      -  var uris = uris.split(',')
      -    , self = this;
      -
      -  switch (arguments.length) {
      -    case 3:
      -      switch (typeof database) {
      -        case 'string':
      -          this.name = database;
      -          break;
      -        case 'object':
      -          callback = options;
      -          options = database;
      -          database = null;
      -          break;
      -      }
      -
      -      if ('function' === typeof options) {
      -        callback = options;
      -        options = {};
      -      }
      -      break;
      -    case 2:
      -      switch (typeof database) {
      -        case 'string':
      -          this.name = database;
      -          break;
      -        case 'function':
      -          callback = database, database = null;
      -          break;
      -        case 'object':
      -          options = database, database = null;
      -          break;
      -      }
      -  }
      -
      -  this.options = options = this.defaultOptions(options);
      -
      -  if (uris.length < 2) {
      -    this.error(new Error('Please provide comma-separated URIs'), callback);
      -    return this;
      -  }
      -
      -  this.replica = true;
      -  this.host = [];
      -  this.port = [];
      -
      -  uris.forEach(function (uri) {
      -    // handle missing protocols
      -    if (!rgxProtocol.test(uri))
      -      uri = 'mongodb://' + uri;
      -
      -    var uri = url.parse(uri);
      -
      -    self.host.push(uri.hostname);
      -    self.port.push(uri.port || 27017);
      -
      -    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
      -      self.name = uri.pathname.replace(/\//g, '');
      -
      -    if (!self.user && uri.auth) {
      -      var auth = uri.auth.split(':');
      -      self.user = auth[0];
      -      self.pass = auth[1];
      -    }
      -  });
      -
      -  if (!this.name) {
      -    this.error(new Error('No database name provided for replica set'), callback);
      -    return this;
      -  }
      -
      -  this._open(callback);
      -  return this;
      -};

      Parameters:

      • uris <String> comma-separated mongodb:// `URI`s
      • [database] <String> database name if not included in `uris`
      • [options] <Object> passed to the internal driver
      • [callback] <Function>

      Example:

      - -
      var db = mongoose.createConnection();
      -db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
      - -

      The database name and/or auth need only be included in one URI.
      The options is a hash which is passed to the internal driver connection object.

      - -

      Valid options

      - -
      db      - passed to the connection db instance
      -server  - passed to the connection server instance(s)
      -replset - passed to the connection ReplSetServer instance
      -user    - username for authentication
      -pass    - password for authentication

      Connection#error(err, callback)

      error

      show code
      Connection.prototype.error = function (err, callback) {
      -  if (callback) return callback(err);
      -  this.emit('error', err);
      -}

      Parameters:

      Graceful error handling, passes error to callback
      if available, else emits error on the connection.


      Connection#_open(callback)

      Handles opening the connection with the appropriate method based on connection type.

      show code
      Connection.prototype._open = function (callback) {
      -  this.readyState = STATES.connecting;
      -  this._closeCalled = false;
      -
      -  var self = this;
      -
      -  var method = this.replica
      -    ? 'doOpenSet'
      -    : 'doOpen';
      -
      -  // open connection
      -  this[method](function (err) {
      -    if (err) {
      -      self.readyState = STATES.disconnected;
      -      if (self._hasOpened) {
      -        if (callback) callback(err);
      -      } else {
      -        self.error(err, callback);
      -      }
      -      return;
      -    }
      -
      -    self.onOpen();
      -    callback && callback();
      -  });
      -}

      Parameters:


      Connection#onOpen()

      Called when the connection is opened

      show code
      Connection.prototype.onOpen = function () {
      -  var self = this;
      -
      -  function open () {
      -    self.readyState = STATES.connected;
      -
      -    // avoid having the collection subscribe to our event emitter
      -    // to prevent 0.3 warning
      -    for (var i in self.collections)
      -      self.collections[i].onOpen();
      -
      -    self.emit('open');
      -  };
      -
      -  // re-authenticate
      -  if (self.user && self.pass)
      -    self.db.authenticate(self.user, self.pass, open);
      -  else
      -    open();
      -};

      Connection#close([callback])

      Closes the connection

      show code
      Connection.prototype.close = function (callback) {
      -  var self = this;
      -  this._closeCalled = true;
      -
      -  switch (this.readyState){
      -    case 0: // disconnected
      -      callback && callback();
      -      break;
      -
      -    case 1: // connected
      -      this.readyState = STATES.disconnecting;
      -      this.doClose(function(err){
      -        if (err){
      -          self.error(err, callback);
      -        } else {
      -          self.onClose();
      -          callback && callback();
      -        }
      -      });
      -      break;
      -
      -    case 2: // connecting
      -      this.once('open', function(){
      -        self.close(callback);
      -      });
      -      break;
      -
      -    case 3: // disconnecting
      -      if (!callback) break;
      -      this.once('close', function () {
      -        callback();
      -      });
      -      break;
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Connection#onClose()

      Called when the connection closes

      show code
      Connection.prototype.onClose = function () {
      -  this.readyState = STATES.disconnected;
      -
      -  // avoid having the collection subscribe to our event emitter
      -  // to prevent 0.3 warning
      -  for (var i in this.collections)
      -    this.collections[i].onClose();
      -
      -  this.emit('close');
      -};

      Connection#collection(name, [options])

      Retrieves a collection, creating it if not cached.

      show code
      Connection.prototype.collection = function (name, options) {
      -  if (!(name in this.collections))
      -    this.collections[name] = new Collection(name, this, options);
      -  return this.collections[name];
      -};

      Parameters:

      • name <String> of the collection
      • [options] <Object> optional collection options

      Returns:


      Connection#model(name, [schema], [collection])

      Defines or retrieves a model.

      show code
      Connection.prototype.model = function (name, schema, collection) {
      -  if (!this.models[name]) {
      -    var model = this.base.model(name, schema, collection, true)
      -      , Model
      -
      -    if (this != model.prototype.db) {
      -      // subclass model using this connection and collection name
      -      Model = function Model (doc, fields, skipId) {
      -        if (!(this instanceof Model))
      -          return new Model(doc, fields, skipId);
      -        model.call(this, doc, fields, skipId);
      -      };
      -
      -      Model.__proto__ = model;
      -      Model.prototype.__proto__ = model.prototype;
      -      Model.db = Model.prototype.db = this;
      -
      -      // collection name discovery
      -      if ('string' === typeof schema) {
      -        collection = schema;
      -      }
      -
      -      if (!collection) {
      -        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
      -      }
      -
      -      var s = 'string' != typeof schema
      -        ? schema
      -        : model.prototype.schema;
      -
      -      Model.prototype.collection = this.collection(collection, s && s.options.capped);
      -      Model.collection = Model.prototype.collection;
      -      Model.init();
      -    }
      -
      -    this.models[name] = Model || model;
      -  }
      -
      -  return this.models[name];
      -};

      Parameters:

      • name <String> the model name
      • [schema] <Schema> a schema. necessary when defining a model
      • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

      Returns:

      • <Model> The compiled model
      var mongoose = require('mongoose');
      -var db = mongoose.createConnection(..);
      -db.model('Venue', new Schema(..));
      -var Ticket = db.model('Ticket', new Schema(..));
      -var Venue = db.model('Venue');

      Connection#setProfiling(level, [ms], callback)

      Set profiling level.

      show code
      Connection.prototype.setProfiling = function (level, ms, callback) {
      -  if (STATES.connected !== this.readyState) {
      -    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
      -  }
      -
      -  if (!callback) callback = ms, ms = 100;
      -
      -  var cmd = {};
      -
      -  switch (level) {
      -    case 0:
      -    case 'off':
      -      cmd.profile = 0;
      -      break;
      -    case 1:
      -    case 'slow':
      -      cmd.profile = 1;
      -      if ('number' !== typeof ms) {
      -        ms = parseInt(ms, 10);
      -        if (isNaN(ms)) ms = 100;
      -      }
      -      cmd.slowms = ms;
      -      break;
      -    case 2:
      -    case 'all':
      -      cmd.profile = 2;
      -      break;
      -    default:
      -      return callback(new Error('Invalid profiling level: '+ level));
      -  }
      -
      -  this.db.executeDbCommand(cmd, function (err, resp) {
      -    if (err) return callback(err);
      -
      -    var doc = resp.documents[0];
      -
      -    err = 1 === doc.ok
      -      ? null
      -      : new Error('Could not set profiling level to: '+ level)
      -
      -    callback(err, doc);
      -  });
      -};

      Parameters:

      • level <Number, String> either off (0), slow (1), or all (2)
      • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
      • callback <Function>

      Connection#defaultOptions(options)

      Prepares default connection options.

      show code
      Connection.prototype.defaultOptions = function (options) {
      -  var o = options || {};
      -
      -  o.server = o.server || {};
      -
      -  if (!('auto_reconnect' in o.server)) {
      -    o.server.auto_reconnect = true;
      -  }
      -
      -  o.db || (o.db = {});
      -  o.db.forceServerObjectId = false;
      -
      -  // TODO default to true once the driver is fixed
      -  if (!('safe' in o.db)) o.db.safe = false;
      -
      -  return o;
      -}

      Parameters:


      Connection#db

      The mongodb.Db instance, set when the connection is opened


      Connection#collections

      A hash of the collections associated with this connection


      Connection#readyState

      Connection ready state

      - -
        -
      • 0 = disconnected
      • -
      • 1 = connected
      • -
      • 2 = connecting
      • -
      • 3 = disconnecting
      • -
      - -

      Each state change emits its associated event name.

      - -

      Example

      - -
      conn.on('connected', callback);
      -conn.on('disconnected', callback);

    • document.js

      Document(obj, [fields], [skipId])

      Document constructor.

      show code
      function Document (obj, fields, skipId) {
      -  // node <0.4.3 bug
      -  if (!this._events) this._events = {};
      -  this.setMaxListeners(0);
      -
      -  if ('boolean' === typeof fields) {
      -    this._strictMode = fields;
      -    this._selected = fields = undefined;
      -  } else {
      -    this._strictMode = this.schema.options && this.schema.options.strict;
      -    this._selected = fields;
      -  }
      -
      -  this.isNew = true;
      -  this.errors = undefined;
      -  this._shardval = undefined;
      -  this._saveError = undefined;
      -  this._validationError = undefined;
      -  this._adhocPaths = undefined;
      -  this._removing = undefined;
      -  this._inserting = undefined;
      -  this.__version = undefined;
      -  this.__getters = {};
      -  this.__id = undefined;
      -
      -  this._activePaths = new ActiveRoster;
      -
      -  var required = this.schema.requiredPaths();
      -  for (var i = 0; i < required.length; ++i) {
      -    this._activePaths.require(required[i]);
      -  }
      -
      -  this._doc = this._buildDoc(obj, fields, skipId);
      -  if (obj) this.set(obj, undefined, true);
      -  this._registerHooks();
      -};

      Parameters:

      • obj <Object> the values to set
      • [fields] <Object> the fields which were selected in the query returning this document
      • [skipId] <Boolean> bool, should we auto create an ObjectId _id

      Events:

      • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

      • save: Emitted when the document is successfully saved


      Document#_buildDoc(obj, [fields], [skipId])

      Builds the default doc structure

      show code
      Document.prototype._buildDoc = function (obj, fields, skipId) {
      -  var doc = {}
      -    , self = this
      -    , exclude
      -    , keys
      -    , key
      -    , ki
      -
      -  // determine if this doc is a result of a query with
      -  // excluded fields
      -  if (fields && 'Object' === fields.constructor.name) {
      -    keys = Object.keys(fields);
      -    ki = keys.length;
      -
      -    while (ki--) {
      -      if ('_id' !== keys[ki]) {
      -        exclude = 0 === fields[keys[ki]];
      -        break;
      -      }
      -    }
      -  }
      -
      -  var paths = Object.keys(this.schema.paths)
      -    , plen = paths.length
      -    , ii = 0
      -
      -  for (; ii < plen; ++ii) {
      -    var p = paths[ii];
      -
      -    if ('_id' == p) {
      -      if (skipId) continue;
      -      if (obj && '_id' in obj) continue;
      -    }
      -
      -    var type = this.schema.paths[p]
      -      , path = p.split('.')
      -      , len = path.length
      -      , last = len-1
      -      , doc_ = doc
      -      , i = 0
      -
      -    for (; i < len; ++i) {
      -      var piece = path[i]
      -        , def
      -
      -      if (i === last) {
      -        if (fields) {
      -          if (exclude) {
      -            // apply defaults to all non-excluded fields
      -            if (p in fields) continue;
      -
      -            def = type.getDefault(self, true);
      -            if ('undefined' !== typeof def) {
      -              doc_[piece] = def;
      -              self._activePaths.default(p);
      -            }
      -
      -          } else if (p in fields) {
      -            // selected field
      -            def = type.getDefault(self, true);
      -            if ('undefined' !== typeof def) {
      -              doc_[piece] = def;
      -              self._activePaths.default(p);
      -            }
      -          }
      -        } else {
      -          def = type.getDefault(self, true);
      -          if ('undefined' !== typeof def) {
      -            doc_[piece] = def;
      -            self._activePaths.default(p);
      -          }
      -        }
      -      } else {
      -        doc_ = doc_[piece] || (doc_[piece] = {});
      -      }
      -    }
      -  };
      -
      -  return doc;
      -};

      Parameters:

      Returns:


      Document#init(doc, fn)

      Initializes the document without setters or marking anything modified.

      show code
      Document.prototype.init = function (doc, fn) {
      -  this.isNew = false;
      -
      -  init(this, doc, this._doc);
      -  this._storeShard();
      -
      -  this.emit('init');
      -  if (fn) fn(null);
      -  return this;
      -};

      Parameters:

      Called internally after a document is returned from mongodb.


      Document#_storeShard()

      Stores the current values of the shard keys.

      show code
      Document.prototype._storeShard = function _storeShard () {
      -  // backwards compat
      -  var key = this.schema.options.shardKey || this.schema.options.shardkey;
      -  if (!(key && 'Object' == key.constructor.name)) return;
      -
      -  var orig = this._shardval = {}
      -    , paths = Object.keys(key)
      -    , len = paths.length
      -    , val
      -
      -  for (var i = 0; i < len; ++i) {
      -    val = this.getValue(paths[i]);
      -    if (isMongooseObject(val)) {
      -      orig[paths[i]] = val.toObject({ depopulate: true })
      -    } else if (null != val && val.valueOf) {
      -      orig[paths[i]] = val.valueOf();
      -    } else {
      -      orig[paths[i]] = val;
      -    }
      -  }
      -}

      Note:

      - -

      Shard key values do not / are not allowed to change.


      Document#update(doc, options, callback)

      Sends an update command with this document _id as the query selector.

      show code
      Document.prototype.update = function update () {
      -  var args = utils.args(arguments);
      -  args.unshift({_id: this._id});
      -  this.constructor.update.apply(this.constructor, args);
      -}

      Parameters:

      Returns:

      Example:

      - -
      weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
      - -

      Valid options:

      - -
        -
      • safe safe mode (defaults to value set in schema (true))
      • -
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • -

      Document#set(path, val, [type], [options])

      Sets the value of a path, or many paths.

      show code
      Document.prototype.set = function (path, val, type, options) {
      -  if (type && 'Object' == type.constructor.name) {
      -    options = type;
      -    type = undefined;
      -  }
      -
      -  var merge = options && options.merge
      -    , adhoc = type && true !== type
      -    , constructing = true === type
      -    , adhocs
      -
      -  if (adhoc) {
      -    adhocs = this._adhocPaths || (this._adhocPaths = {});
      -    adhocs[path] = Schema.interpretAsType(path, type);
      -  }
      -
      -  if ('string' !== typeof path) {
      -    // new Document({ key: val })
      -
      -    if (null === path || undefined === path) {
      -      var _ = path;
      -      path = val;
      -      val = _;
      -
      -    } else {
      -      var prefix = val
      -        ? val + '.'
      -        : '';
      -
      -      if (path instanceof Document) path = path._doc;
      -
      -      var keys = Object.keys(path)
      -        , i = keys.length
      -        , pathtype
      -        , key
      -
      -      while (i--) {
      -        key = keys[i];
      -        if (null != path[key] && 'Object' === path[key].constructor.name
      -          && !(this._path(prefix + key) instanceof MixedSchema)) {
      -          this.set(path[key], prefix + key, constructing);
      -        } else if (this._strictMode) {
      -          pathtype = this.schema.pathType(prefix + key);
      -          if ('real' === pathtype || 'virtual' === pathtype) {
      -            this.set(prefix + key, path[key], constructing);
      -          } else if ('throw' == this._strictMode) {
      -            throw new Error("Field `" + key + "` is not in schema.");
      -          }
      -        } else if (undefined !== path[key]) {
      -          this.set(prefix + key, path[key], constructing);
      -        }
      -      }
      -
      -      return this;
      -    }
      -  }
      -
      -  // ensure _strict is honored for obj props
      -  // docschema = new Schema({ path: { nest: 'string' }})
      -  // doc.set('path', obj);
      -  var pathType = this.schema.pathType(path);
      -  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
      -    if (!merge) this.setValue(path, null);
      -    this.set(val, path, constructing);
      -    return this;
      -  }
      -
      -  var schema;
      -  if ('adhocOrUndefined' == pathType && this._strictMode) {
      -    return this;
      -  } else if ('virtual' == pathType) {
      -    schema = this.schema.virtualpath(path);
      -    schema.applySetters(val, this);
      -    return this;
      -  } else {
      -    schema = this._path(path);
      -  }
      -
      -  var parts = path.split('.')
      -    , pathToMark
      -
      -  // When using the $set operator the path to the field must already exist.
      -  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
      -
      -  if (parts.length <= 1) {
      -    pathToMark = path;
      -  } else {
      -    for (var i = 0; i < parts.length; ++i) {
      -      var part = parts[i];
      -      var subpath = parts.slice(0, i).concat(part).join('.');
      -      if (this.isDirectModified(subpath) // earlier prefixes that are already
      -                                         // marked as dirty have precedence
      -          || this.get(subpath) === null) {
      -        pathToMark = subpath;
      -        break;
      -      }
      -    }
      -
      -    if (!pathToMark) pathToMark = path;
      -  }
      -
      -  if (!schema || null === val || undefined === val) {
      -    this._set(pathToMark, path, constructing, parts, schema, val);
      -    return this;
      -  }
      -
      -  var self = this;
      -
      -  // if this doc is being constructed we should not
      -  // trigger getters.
      -  var priorVal = constructing
      -    ? undefined
      -    : this.get(path);
      -
      -  var shouldSet = this.try(function(){
      -    val = schema.applySetters(val, self, false, priorVal);
      -  });
      -
      -  if (shouldSet) {
      -    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
      -  }
      -
      -  return this;
      -}

      Parameters:

      • path <String, Object> path or object of key/vals to set
      • val <Any> the value to set
      • [type] <Schema, String, Number, Buffer, etc..> optionally specify a type for "on-the-fly" attributes
      • [options] <Object> optionally specify options that modify the behavior of the set

      Example:

      - -
      // path, value
      -doc.set(path, value)
      -
      -// object
      -doc.set({
      -    path  : value
      -  , path2 : {
      -       path  : value
      -    }
      -})
      -
      -// only-the-fly cast to number
      -doc.set(path, value, Number)
      -
      -// only-the-fly cast to string
      -doc.set(path, value, String)

      Document#_shouldModify()

      Determine if we should mark this change as modified.

      show code
      Document.prototype._shouldModify = function (
      -    pathToMark, path, constructing, parts, schema, val, priorVal) {
      -
      -  if (this.isNew) return true;
      -  if (this.isDirectModified(pathToMark)) return false;
      -
      -  if (undefined === val && !this.isSelected(path)) {
      -    // when a path is not selected in a query, its initial
      -    // value will be undefined.
      -    return true;
      -  }
      -
      -  if (undefined === val && path in this._activePaths.states.default) {
      -    // we're just unsetting the default value which was never saved
      -    return false;
      -  }
      -
      -  if (!deepEqual(val, priorVal || this.get(path))) {
      -    return true;
      -  }
      -
      -  if (!constructing &&
      -      null != val &&
      -      path in this._activePaths.states.default &&
      -      deepEqual(val, schema.getDefault(this, constructing))) {
      -    // a path with a default was $unset on the server
      -    // and the user is setting it to the same value again
      -    return true;
      -  }
      -
      -  return false;
      -}

      Returns:


      Document#_set()

      Handles the actual setting of the value and marking the path modified if appropriate.

      show code
      Document.prototype._set = function (
      -    pathToMark, path, constructing, parts, schema, val, priorVal) {
      -
      -  var shouldModify = this._shouldModify.apply(this, arguments);
      -
      -  if (shouldModify) {
      -    this.markModified(pathToMark, val);
      -
      -    // handle directly setting arrays (gh-1126)
      -    MongooseArray || (MongooseArray = require('./types/array'));
      -    if (val instanceof MongooseArray) {
      -      val._registerAtomic('$set', val);
      -    }
      -  }
      -
      -  var obj = this._doc
      -    , i = 0
      -    , l = parts.length
      -
      -  for (; i < l; i++) {
      -    var next = i + 1
      -      , last = next === l;
      -
      -    if (last) {
      -      obj[parts[i]] = val;
      -    } else {
      -      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
      -        obj = obj[parts[i]];
      -      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
      -        obj = obj[parts[i]];
      -      } else {
      -        obj = obj[parts[i]] = {};
      -      }
      -    }
      -  }
      -}

      Document#getValue(path)

      Gets a raw value from a path (no getters)

      show code
      Document.prototype.getValue = function (path) {
      -  var parts = path.split('.')
      -    , obj = this._doc
      -    , part;
      -
      -  for (var i = 0, l = parts.length; i < l; i++) {
      -    part = parts[i];
      -    obj = obj.getValue
      -        ? obj.getValue(part) // If we have an embedded array document member
      -        : obj[part];
      -    if (!obj) return obj;
      -  }
      -
      -  return obj;
      -}

      Parameters:


      Document#setValue(path, value)

      Sets a raw value for a path (no casting, setters, transformations)

      show code
      Document.prototype.setValue = function (path, val) {
      -  var parts = path.split('.')
      -    , obj = this._doc;
      -
      -  for (var i = 0, len = parts.length-1; i < len; i++) {
      -    obj = obj[parts[i]];
      -  }
      -
      -  obj[parts[len]] = val;
      -  return this;
      -};

      Parameters:


      Document#get(path, [type])

      Returns the value of a path.

      show code
      Document.prototype.get = function (path, type) {
      -  var adhocs;
      -  if (type) {
      -    adhocs = this._adhocPaths || (this._adhocPaths = {});
      -    adhocs[path] = Schema.interpretAsType(path, type);
      -  }
      -
      -  var schema = this._path(path) || this.schema.virtualpath(path)
      -    , pieces = path.split('.')
      -    , obj = this._doc;
      -
      -  for (var i = 0, l = pieces.length; i < l; i++) {
      -    obj = null == obj ? null : obj[pieces[i]];
      -  }
      -
      -  if (schema) {
      -    obj = schema.applyGetters(obj, this);
      -  }
      -
      -  return obj;
      -};

      Parameters:

      Example

      - -
      // path
      -doc.get('age') // 47
      -
      -// dynamic casting to a string
      -doc.get('age', String) // "47"

      Document#_path(path)

      Returns the schematype for the given path.

      show code
      Document.prototype._path = function (path) {
      -  var adhocs = this._adhocPaths
      -    , adhocType = adhocs && adhocs[path];
      -
      -  if (adhocType) {
      -    return adhocType;
      -  } else {
      -    return this.schema.path(path);
      -  }
      -};

      Parameters:


      Document#markModified(path)

      Marks the path as having pending changes to write to the db.

      show code
      Document.prototype.markModified = function (path) {
      -  this._activePaths.modify(path);
      -}

      Parameters:

      • path <String> the path to mark modified

      Very helpful when using Mixed types.

      - -

      Example:

      - -
      doc.mixed.type = 'changed';
      -doc.markModified('mixed.type');
      -doc.save() // changes to mixed.type are now persisted

      Document#try(fn, scope)

      Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

      show code
      Document.prototype.try = function (fn, scope) {
      -  var res;
      -  try {
      -    fn.call(scope);
      -    res = true;
      -  } catch (e) {
      -    this._error(e);
      -    res = false;
      -  }
      -  return res;
      -};

      Parameters:

      • fn <Function> function to execute
      • scope <Object> the scope with which to call fn

      Document#modifiedPaths()

      Returns the list of paths that have been modified.

      show code
      Document.prototype.modifiedPaths = function () {
      -  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
      -
      -  return directModifiedPaths.reduce(function (list, path) {
      -    var parts = path.split('.');
      -    return list.concat(parts.reduce(function (chains, part, i) {
      -      return chains.concat(parts.slice(0, i).concat(part).join('.'));
      -    }, []));
      -  }, []);
      -};

      Returns:


      Document#isModified([path])

      Returns true if this document was modified, else false.

      show code
      Document.prototype.isModified = function (path) {
      -  return path
      -    ? !!~this.modifiedPaths().indexOf(path)
      -    : this._activePaths.some('modify');
      -};

      Parameters:

      Returns:

      If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

      - -

      Example

      - -
      doc.set('documents.0.title', 'changed');
      -doc.isModified()                    // true
      -doc.isModified('documents')         // true
      -doc.isModified('documents.0.title') // true
      -doc.isDirectModified('documents')   // false

      Document#isDirectModified(path)

      Returns true if path was directly set and modified, else false.

      show code
      Document.prototype.isDirectModified = function (path) {
      -  return (path in this._activePaths.states.modify);
      -};

      Parameters:

      Returns:

      Example

      - -
      doc.set('documents.0.title', 'changed');
      -doc.isDirectModified('documents.0.title') // true
      -doc.isDirectModified('documents') // false

      Document#isInit(path)

      Checks if path was initialized.

      show code
      Document.prototype.isInit = function (path) {
      -  return (path in this._activePaths.states.init);
      -};

      Parameters:

      Returns:


      Document#isSelected(path)

      Checks if path was selected in the source query which initialized this document.

      show code
      Document.prototype.isSelected = function isSelected (path) {
      -  if (this._selected) {
      -
      -    if ('_id' === path) {
      -      return 0 !== this._selected._id;
      -    }
      -
      -    var paths = Object.keys(this._selected)
      -      , i = paths.length
      -      , inclusive = false
      -      , cur
      -
      -    if (1 === i && '_id' === paths[0]) {
      -      // only _id was selected.
      -      return 0 === this._selected._id;
      -    }
      -
      -    while (i--) {
      -      cur = paths[i];
      -      if ('_id' == cur) continue;
      -      inclusive = !! this._selected[cur];
      -      break;
      -    }
      -
      -    if (path in this._selected) {
      -      return inclusive;
      -    }
      -
      -    i = paths.length;
      -    var pathDot = path + '.';
      -
      -    while (i--) {
      -      cur = paths[i];
      -      if ('_id' == cur) continue;
      -
      -      if (0 === cur.indexOf(pathDot)) {
      -        return inclusive;
      -      }
      -
      -      if (0 === pathDot.indexOf(cur)) {
      -        return inclusive;
      -      }
      -    }
      -
      -    return ! inclusive;
      -  }
      -
      -  return true;
      -}

      Parameters:

      Returns:

      Example

      - -
      Thing.findOne().select('name').exec(function (err, doc) {
      -   doc.isSelected('name') // true
      -   doc.isSelected('age')  // false
      -})

      Document#validate(cb)

      Executes registered validation rules for this document.

      show code
      Document.prototype.validate = function (cb) {
      -  var self = this
      -
      -  // only validate required fields when necessary
      -  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
      -    if (!self.isSelected(path) && !self.isModified(path)) return false;
      -    return true;
      -  });
      -
      -  paths = paths.concat(Object.keys(this._activePaths.states.init));
      -  paths = paths.concat(Object.keys(this._activePaths.states.modify));
      -  paths = paths.concat(Object.keys(this._activePaths.states.default));
      -
      -  if (0 === paths.length) {
      -    complete();
      -    return this;
      -  }
      -
      -  var validating = {}
      -    , total = 0;
      -
      -  paths.forEach(validatePath);
      -  return this;
      -
      -  function validatePath (path) {
      -    if (validating[path]) return;
      -
      -    validating[path] = true;
      -    total++;
      -
      -    process.nextTick(function(){
      -      var p = self.schema.path(path);
      -      if (!p) return --total || complete();
      -
      -      p.doValidate(self.getValue(path), function (err) {
      -        if (err) self.invalidate(path, err, true);
      -        --total || complete();
      -      }, self);
      -    });
      -  }
      -
      -  function complete () {
      -    var err = self._validationError;
      -    self._validationError = undefined;
      -    cb(err);
      -  }
      -};

      Parameters:

      • cb <Function> called after validation completes, passing an error if one occurred

      Note:

      - -

      This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

      - -

      Example:

      - -
      doc.validate(function (err) {
      -  if (err) handleError(err);
      -  else // validation passed
      -});

      Document#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      Document.prototype.invalidate = function (path, err) {
      -  if (!this._validationError) {
      -    this._validationError = new ValidationError(this);
      -  }
      -
      -  if (!err || 'string' === typeof err) {
      -    err = new ValidatorError(path, err);
      -  }
      -
      -  this._validationError.errors[path] = err;
      -}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> the error which states the reason `path` was invalid

      Document#_reset()

      Resets the internal modified state of this document.

      show code
      Document.prototype._reset = function reset () {
      -  var self = this;
      -  DocumentArray || (DocumentArray = require('./types/documentarray'));
      -
      -  this._activePaths
      -  .map('init', 'modify', function (i) {
      -    return self.getValue(i);
      -  })
      -  .filter(function (val) {
      -    return val && val instanceof DocumentArray && val.length;
      -  })
      -  .forEach(function (array) {
      -    var i = array.length;
      -    while (i--) {
      -      var doc = array[i];
      -      if (!doc) continue;
      -      doc._reset();
      -    }
      -  });
      -
      -  // clear atomics
      -  this._dirty().forEach(function (dirt) {
      -    var type = dirt.value;
      -    if (type && type._atomics) {
      -      type._atomics = {};
      -    }
      -  });
      -
      -  // Clear 'modify'('dirty') cache
      -  this._activePaths.clear('modify');
      -  this._validationError = undefined;
      -  this.errors = undefined;
      -  var self = this;
      -  this.schema.requiredPaths().forEach(function (path) {
      -    self._activePaths.require(path);
      -  });
      -
      -  return this;
      -}

      Returns:


      Document#_dirty()

      Returns this documents dirty paths / vals.

      show code
      Document.prototype._dirty = function _dirty () {
      -  var self = this;
      -
      -  var all = this._activePaths.map('modify', function (path) {
      -    return { path: path
      -           , value: self.getValue(path)
      -           , schema: self._path(path) };
      -  });
      -
      -  // Sort dirty paths in a flat hierarchy.
      -  all.sort(function (a, b) {
      -    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
      -  });
      -
      -  // Ignore "foo.a" if "foo" is dirty already.
      -  var minimal = []
      -    , lastPath
      -    , top;
      -
      -  all.forEach(function (item, i) {
      -    if (item.path.indexOf(lastPath) !== 0) {
      -      lastPath = item.path + '.';
      -      minimal.push(item);
      -      top = item;
      -    } else {
      -      if (!(item.value && top.value)) return;
      -
      -      // special case for top level MongooseArrays
      -      if (top.value._atomics && top.value.hasAtomics()) {
      -        // the `top` array itself and a sub path of `top` are being modified.
      -        // the only way to honor all of both modifications is through a $set
      -        // of entire array.
      -        top.value._atomics = {};
      -        top.value._atomics.$set = top.value;
      -      }
      -    }
      -  });
      -
      -  top = lastPath = null;
      -  return minimal;
      -}

      Document#_setSchema(schema)

      Assigns/compiles schema into this documents prototype.

      show code
      Document.prototype._setSchema = function (schema) {
      -  compile(schema.tree, this);
      -  this.schema = schema;
      -}

      Parameters:


      Document#_registerHooks()

      Register default hooks

      show code
      Document.prototype._registerHooks = function _registerHooks () {
      -  if (!this.save) return;
      -
      -  DocumentArray || (DocumentArray = require('./types/documentarray'));
      -
      -  this.pre('save', function (next) {
      -    // we keep the error semaphore to make sure we don't
      -    // call `save` unnecessarily (we only need 1 error)
      -    var subdocs = 0
      -      , error = false
      -      , self = this;
      -
      -    // check for DocumentArrays
      -    var arrays = this._activePaths
      -    .map('init', 'modify', function (i) {
      -      return self.getValue(i);
      -    })
      -    .filter(function (val) {
      -      return val && val instanceof DocumentArray && val.length;
      -    });
      -
      -    if (!arrays.length)
      -      return next();
      -
      -    arrays.forEach(function (array) {
      -      if (error) return;
      -
      -      // handle sparse arrays by using for loop vs array.forEach
      -      // which skips the sparse elements
      -
      -      var len = array.length
      -      subdocs += len;
      -
      -      for (var i = 0; i < len; ++i) {
      -        if (error) break;
      -
      -        var doc = array[i];
      -        if (!doc) {
      -          --subdocs || next();
      -          continue;
      -        }
      -
      -        doc.save(handleSave);
      -      }
      -    });
      -
      -    function handleSave (err) {
      -      if (error) return;
      -
      -      if (err) {
      -        self._validationError = undefined;
      -        return next(error = err);
      -      }
      -
      -      --subdocs || next();
      -    }
      -
      -  }, function (err) {
      -    // emit on the Model if listening
      -    if (this.constructor.listeners('error').length) {
      -      this.constructor.emit('error', err);
      -    } else {
      -      // emit on the connection
      -      if (!this.db.listeners('error').length) {
      -        err.stack = 'No listeners detected, throwing. '
      -                  + 'Consider adding an error listener to your connection.
      -'
      -                  + err.stack
      -      }
      -      this.db.emit('error', err);
      -    }
      -  }).pre('save', function checkForExistingErrors (next) {
      -    // if any doc.set() calls failed
      -    if (this._saveError) {
      -      next(this._saveError);
      -      this._saveError = null;
      -    } else {
      -      next();
      -    }
      -  }).pre('save', function validation (next) {
      -    return this.validate(next);
      -  });
      -
      -  // add user defined queues
      -  this._doQueue();
      -};

      Document#_error(err)

      Registers an error

      show code
      Document.prototype._error = function (err) {
      -  this._saveError = err;
      -  return this;
      -};

      Parameters:


      Document#_doQueue()

      Executes methods queued from the Schema definition

      show code
      Document.prototype._doQueue = function () {
      -  var q = this.schema && this.schema.callQueue;
      -  if (q) {
      -    for (var i = 0, l = q.length; i < l; i++) {
      -      this[q[i][0]].apply(this, q[i][1]);
      -    }
      -  }
      -  return this;
      -};

      Document#toObject([options])

      Converts this document into a plain javascript object

      show code
      Document.prototype.toObject = function (options) {
      -  // When internally saving this document we always pass options,
      -  // bypassing the custom schema options.
      -  if (!(options && 'Object' == options.constructor.name)) {
      -    options = this.schema.options.toObject
      -      ? clone(this.schema.options.toObject)
      -      : {};
      -  }
      -
      -  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
      -
      -  var ret = clone(this._doc, options);
      -
      -  if (options.virtuals || options.getters && false !== options.virtuals) {
      -    applyGetters(this, ret, 'virtuals', options);
      -  }
      -
      -  if (options.getters) {
      -    applyGetters(this, ret, 'paths', options);
      -  }
      -
      -  if (true === options.transform) {
      -    var opts = options.json
      -      ? this.schema.options.toJSON
      -      : this.schema.options.toObject;
      -    if (opts) {
      -      options.transform = opts.transform;
      -    }
      -  }
      -
      -  if ('function' == typeof options.transform) {
      -    var xformed = options.transform(this, ret, options);
      -    if ('undefined' != typeof xformed) ret = xformed;
      -  }
      -
      -  return ret;
      -};

      Parameters:

      Returns:

      Options:

      - -
        -
      • getters apply all getters (path and virtual getters)
      • -
      • virtuals apply virtual getters (can override getters option)
      • -
      • minimize remove empty objects (defaults to true)
      • -
      • transform a transform function to apply to the resulting document before returning
      • -
      - -

      Getters/Virtuals

      - -

      Example of only applying path getters

      - -
      doc.toObject({ getters: true, virtuals: false })
      - -

      Example of only applying virtual getters

      - -
      doc.toObject({ virtuals: true })
      - -

      Example of applying both path and virtual getters

      - -
      doc.toObject({ getters: true })
      - -

      To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

      - -
      schema.set('toObject', { virtuals: true })
      - -

      Transform

      - -

      We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

      - -

      Transform functions receive three arguments

      - -
      function (doc, ret, options) {}
      - -
        -
      • doc The mongoose document which is being converted
      • -
      • ret The plain object representation which has been converted
      • -
      • options The options in use (either schema options or the options passed inline)
      • -
      - -

      Example

      - -
      // specify the transform schema option
      -schema.options.toObject.transform = function (doc, ret, options) {
      -  // remove the _id of every document before returning the result
      -  delete ret._id;
      -}
      -
      -// without the transformation in the schema
      -doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
      -
      -// with the transformation
      -doc.toObject(); // { name: 'Wreck-it Ralph' }
      - -

      With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

      - -
      schema.options.toObject.transform = function (doc, ret, options) {
      -  return { movie: ret.name }
      -}
      -
      -// without the transformation in the schema
      -doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
      -
      -// with the transformation
      -doc.toObject(); // { movie: 'Wreck-it Ralph' }
      - -

      Note: if a transform function returns undefined, the return value will be ignored.

      - -

      Transformations may also be applied inline, overridding any transform set in the options:

      - -
      function xform (doc, ret, options) {
      -  return { inline: ret.name, custom: true }
      -}
      -
      -// pass the transform as an inline option
      -doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }
      - -

      Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

      - -
      schema.options.toObject.hide = '_id';
      -schema.options.toObject.transform = function (doc, ret, options) {
      -  if (options.hide) {
      -    options.hide.split(' ').forEach(function (prop) {
      -      delete ret[prop];
      -    });
      -  }
      -}
      -
      -var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });
      -doc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }
      -doc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }
      -doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }
      - -

      Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

      - -
      if ('function' == typeof doc.ownerDocument) {
      -  // working with a sub doc
      -}
      - -

      Transforms, like all of these options, are also available for toJSON.

      - -

      See schema options for some more details.


      Document#toJSON(options)

      The return value of this method is used in calls to JSON.stringify(doc).

      show code
      Document.prototype.toJSON = function (options) {
      -  // check for object type since an array of documents
      -  // being stringified passes array indexes instead
      -  // of options objects. JSON.stringify([doc, doc])
      -  if (!(options && 'Object' == options.constructor.name)) {
      -    options = this.schema.options.toJSON
      -      ? clone(this.schema.options.toJSON)
      -      : {};
      -  }
      -  options.json = true;
      -  return this.toObject(options);
      -};

      Parameters:

      • options <Object> same options as [Document#toObject](#document_Document-toObject)

      Returns:

      This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

      - -
      schema.set('toJSON', { virtuals: true })
      - -

      See schema options for details.


      Document#inspect()

      Helper for console.log

      show code
      Document.prototype.inspect = function (options) {
      -  var opts = options && 'Object' == options.constructor.name
      -    ? options
      -    : undefined
      -  return inspect(this.toObject(opts));
      -};

      Document#toString()

      Helper for console.log


      Document#equals(doc)

      Returns true if the Document stores the same data as doc.

      show code
      Document.prototype.equals = function (doc) {
      -  var tid = this.get('_id');
      -  var docid = doc.get('_id');
      -  return tid.equals
      -    ? tid.equals(docid)
      -    : tid === docid;
      -};

      Parameters:

      Returns:

      Documents are considered equal when they have matching _ids.


      Document#errors

      Hash containing current validation errors.


      Document#id

      The string version of this documents _id.

      - -

      Note:

      - -

      This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

      - -
      new Schema({ name: String }, { id: false });

      Document#isNew

      Boolean flag specifying if the document is new.


      Document#schema

      The documents schema.


    • drivers/node-mongodb-native/collection.js

      NativeCollection()

      A node-mongodb-native collection implementation.

      show code
      function NativeCollection () {
      -  this.collection = null;
      -  MongooseCollection.apply(this, arguments);
      -}

      Inherits:

      All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


      NativeCollection#onOpen()

      Called when the connection opens.

      show code
      NativeCollection.prototype.onOpen = function () {
      -  var self = this;
      -
      -  if (this.collection) {
      -    return MongooseCollection.prototype.onOpen.call(self);
      -  }
      -
      -  if (!self.opts.size) {
      -    // non-capped
      -    return self.conn.db.collection(self.name, callback);
      -  }
      -
      -  // capped
      -  return self.conn.db.collection(self.name, function (err, c) {
      -    if (err) return callback(err);
      -
      -    // discover if this collection exists and if it is capped
      -    c.options(function (err, exists) {
      -      if (err) return callback(err);
      -
      -      if (exists) {
      -        if (exists.capped) {
      -          callback(null, c);
      -        } else {
      -          var msg = 'A non-capped collection exists with this name.
      -
      -'
      -                  + ' To use this collection as a capped collection, please '
      -                  + 'first convert it.
      -'
      -                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
      -          err = new Error(msg);
      -          callback(err);
      -        }
      -      } else {
      -        // create
      -        var opts = utils.clone(self.opts);
      -        opts.capped = true;
      -        self.conn.db.createCollection(self.name, opts, callback);
      -      }
      -    });
      -  });
      -
      -  function callback (err, collection) {
      -    if (err) {
      -      // likely a strict mode error
      -      self.conn.emit('error', err);
      -    } else {
      -      self.collection = collection;
      -      MongooseCollection.prototype.onOpen.call(self);
      -    }
      -  };
      -};

      NativeCollection#onClose()

      Called when the connection closes

      show code
      NativeCollection.prototype.onClose = function () {
      -  MongooseCollection.prototype.onClose.call(this);
      -};

      NativeCollection#getIndexes(callback)

      Retreives information about this collections indexes.

      Parameters:


    • drivers/node-mongodb-native/connection.js

      NativeConnection()

      A node-mongodb-native connection implementation.

      show code
      function NativeConnection() {
      -  MongooseConnection.apply(this, arguments);
      -};

      Inherits:


      NativeConnection#doOpen(fn)

      Opens the connection to MongoDB.

      show code
      NativeConnection.prototype.doOpen = function (fn) {
      -  var server
      -    , self = this;
      -
      -  if (!this.db) {
      -    server = new mongo.Server(this.host, Number(this.port), this.options.server);
      -    this.db = new mongo.Db(this.name, server, this.options.db);
      -  }
      -
      -  this.db.open(function (err) {
      -    if (err) return fn(err);
      -    fn();
      -    listen(self);
      -  });
      -
      -  return this;
      -};
      -
      -function listen (conn) {
      -  if (conn._listening) return;
      -  conn._listening = true;
      -
      -  conn.db.on('close', function(){
      -    if (conn._closeCalled) return;
      -
      -    // the driver never emits an `open` event. auto_reconnect still
      -    // emits a `close` event but since we never get another
      -    // `open` we can't emit close
      -    if (conn.db.serverConfig.autoReconnect) {
      -      conn.readyState = STATES.disconnected;
      -      conn.emit('close');
      -      return;
      -    }
      -    conn.onClose();
      -  });
      -  conn.db.on('error', function(err){
      -    conn.emit('error', err);
      -  });
      -  conn.db.on('timeout', function(err){
      -    var error = new Error(err && err.err || 'connection timeout');
      -    conn.emit('error', error);
      -  });
      -  conn.db.on('open', function (err, db) {
      -    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
      -      conn.readyState = STATES.connected;
      -      conn.emit('reconnected')
      -    }
      -  })
      -}

      Parameters:

      Returns:


      NativeConnection#doOpenSet(fn)

      Opens a connection to a MongoDB ReplicaSet.

      show code
      NativeConnection.prototype.doOpenSet = function (fn) {
      -  if (!this.db) {
      -    var servers = []
      -      , ports = this.port
      -      , self = this
      -
      -    this.host.forEach(function (host, i) {
      -      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
      -    });
      -
      -    var server = new ReplSetServers(servers, this.options.replset);
      -    this.db = new mongo.Db(this.name, server, this.options.db);
      -
      -    this.db.on('fullsetup', function () {
      -      self.emit('fullsetup')
      -    });
      -  }
      -
      -  this.db.open(function (err) {
      -    if (err) return fn(err);
      -    fn();
      -    listen(self);
      -  });
      -
      -  return this;
      -};

      Parameters:

      Returns:

      See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


      NativeConnection#doClose(fn)

      Closes the connection

      show code
      NativeConnection.prototype.doClose = function (fn) {
      -  this.db.close();
      -  if (fn) fn();
      -  return this;
      -}

      Parameters:

      Returns:


    • error.js

      MongooseError()

      Mongoose error

      show code
      function MongooseError (msg) {
      -  Error.call(this);
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.message = msg;
      -  this.name = 'MongooseError';
      -};

      Inherits:


    • errors/cast.js

      CastError(type, value)

      Casting Error constructor.

      show code
      function CastError (type, value) {
      -  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'CastError';
      -  this.type = type;
      -  this.value = value;
      -};

      Parameters:

      Inherits:


    • errors/document.js

      DocumentError(msg)

      Document Error

      show code
      function DocumentError (msg) {
      -  MongooseError.call(this, msg);
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'DocumentError';
      -};

      Parameters:

      Inherits:


    • errors/validation.js

      ValidationError(instance)

      Document Validation Error

      show code
      function ValidationError (instance) {
      -  MongooseError.call(this, "Validation failed");
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'ValidationError';
      -  this.errors = instance.errors = {};
      -};

      Parameters:

      Inherits:


      ValidationError#toString()

      Console.log helper

      show code
      ValidationError.prototype.toString = function () {
      -  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
      -    return String(this.errors[key]);
      -  }, this).join(', ');
      -};

    • errors/validator.js

      ValidatorError(path, msg)

      Schema validator error

      show code
      function ValidatorError (path, type) {
      -  var msg = type
      -    ? '"' + type + '" '
      -    : '';
      -  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'ValidatorError';
      -  this.path = path;
      -  this.type = type;
      -};

      Parameters:

      Inherits:


    • errors/version.js

      VersionError()

      Version Error constructor.

      show code
      function VersionError () {
      -  MongooseError.call(this, 'No matching document found.');
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'VersionError';
      -};

      Inherits:


    • model.js

      Model(doc)

      Model constructor

      show code
      function Model (doc, fields, skipId) {
      -  Document.call(this, doc, fields, skipId);
      -};

      Parameters:

      • doc <Object> values to with which to create the document

      Inherits:

      Events:

      • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

      • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


      Model#_getPopulationKeys(query)

      Returns what paths can be populated

      show code
      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
      -  if (!(query && query.options.populate)) return;
      -
      -  var names = Object.keys(query.options.populate)
      -    , n = names.length
      -    , name
      -    , paths = {}
      -    , hasKeys
      -    , schema
      -
      -  while (n--) {
      -    name = names[n];
      -    schema = this.schema.path(name);
      -    hasKeys = true;
      -
      -    if (!schema) {
      -      // if the path is not recognized, it's potentially embedded docs
      -      // walk path atoms from right to left to find a matching path
      -      var pieces = name.split('.')
      -        , i = pieces.length;
      -
      -      while (i--) {
      -        var path = pieces.slice(0, i).join('.')
      -          , pathSchema = this.schema.path(path);
      -
      -        // loop until we find an array schema
      -        if (pathSchema && pathSchema.caster) {
      -          if (!paths[path]) {
      -            paths[path] = { sub: {} };
      -          }
      -
      -          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
      -          hasKeys || (hasKeys = true);
      -          break;
      -        }
      -      }
      -    } else {
      -      paths[name] = query.options.populate[name];
      -      hasKeys || (hasKeys = true);
      -    }
      -  }
      -
      -  return hasKeys && paths;
      -};

      Parameters:

      Returns:


      Model#_populate(schema, oid, query, fn)

      Populates an object

      show code
      Model.prototype._populate = function populate (schema, oid, query, fn) {
      -  if (!Array.isArray(oid)) {
      -    var conditions = query.conditions || {};
      -    conditions._id = oid;
      -
      -    return this
      -    .db.model(query.model || schema.options.ref)
      -    .findOne(conditions, query.fields, query.options, fn);
      -  }
      -
      -  if (!oid.length) {
      -    return fn(null, oid);
      -  }
      -
      -  var model = this.db.model(query.model || schema.caster.options.ref)
      -    , conditions = query && query.conditions || {};
      -
      -  conditions._id || (conditions._id = { $in: oid });
      -
      -  model.find(conditions, query.fields, query.options, function (err, docs) {
      -    if (err) return fn(err);
      -
      -    // user specified sort order?
      -    if (query.options && query.options.sort) {
      -      return fn(null, docs);
      -    }
      -
      -    // put back in original id order (using a hash reduces complexity from n*n to 2n)
      -    var docHash = {};
      -    docs.forEach(function (doc) {
      -      docHash[doc._id] = doc;
      -    });
      -
      -    var arr = [];
      -    oid.forEach(function (id) {
      -      if (id in docHash) arr.push(docHash[id]);
      -    });
      -
      -    fn(null, arr);
      -  });
      -};

      Parameters:

      • schema <SchemaType> type for the oid
      • oid <Object> object id or array of object ids
      • query <Object> object specifying query conditions, fields, and options
      • fn <Function>

      Model#init(doc, query, fn)

      Performs auto-population of relations.

      show code
      Model.prototype.init = function init (doc, query, fn) {
      -  if ('function' == typeof query) {
      -    fn = query;
      -    query = null;
      -  }
      -
      -  var populate = this._getPopulationKeys(query);
      -
      -  if (!populate) {
      -    return Document.prototype.init.call(this, doc, fn);
      -  }
      -
      -  // population from other models is necessary
      -  var self = this;
      -
      -  init(doc, '', function (err) {
      -    if (err) return fn(err);
      -    Document.prototype.init.call(self, doc, fn);
      -  });
      -
      -  return this;
      -
      -  function init (obj, prefix, fn) {
      -    prefix = prefix || '';
      -
      -    var keys = Object.keys(obj)
      -      , len = keys.length;
      -
      -    return next();
      -
      -    function next () {
      -      if (--len < 0) return fn();
      -
      -      var i = keys[len]
      -        , path = prefix + i
      -        , schema = self.schema.path(path)
      -        , total = 0
      -        , inline = false
      -        , poppath
      -
      -      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
      -        // assume nested object
      -        return init(obj[i], path + '.', next);
      -      }
      -
      -      if (!(obj[i] && schema && populate[path])) return next();
      -
      -      // this query object is re-used and passed around. we clone
      -      // it to prevent query condition contamination between
      -      // one populate call to the next.
      -      poppath = utils.clone(populate[path]);
      -
      -      if (poppath.sub) {
      -        obj[i].forEach(function (subobj) {
      -          inline = true;
      -
      -          var pkeys = Object.keys(poppath.sub)
      -            , pi = pkeys.length
      -            , key
      -
      -          while (pi--) {
      -            key = pkeys[pi];
      -
      -            if (subobj[key]) (function (key) {
      -              total++;
      -              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
      -              function done (err, doc) {
      -                if (err) return error(err);
      -                subobj[key] = doc;
      -                if (--total < 1 && !inline) {
      -                  next();
      -                }
      -              }
      -            })(key);
      -          }
      -        });
      -
      -        inline = false;
      -
      -        if (0 === total) return next();
      -
      -      } else {
      -        self._populate(schema, obj[i], poppath, function (err, doc) {
      -          if (err) return error(err);
      -          obj[i] = doc;
      -          next();
      -        });
      -      }
      -    };
      -  };
      -
      -  function error (err) {
      -    if (error.err) return;
      -    fn(error.err = err);
      -  }
      -};

      Parameters:

      • doc <Object> document returned by mongo
      • query <Query> query that originated the initialization
      • fn <Function>

      Model#save([fn])

      Saves this document.

      show code
      Model.prototype.save = function save (fn) {
      -  var promise = new Promise(fn)
      -    , complete = handleSave(promise, this)
      -    , options = {}
      -
      -  if (this.schema.options.safe) {
      -    options.safe = this.schema.options.safe;
      -  }
      -
      -  if (this.isNew) {
      -    // send entire doc
      -    var obj = this.toObject({ depopulate: 1 });
      -    this._version(true, obj);
      -    this.collection.insert(obj, options, complete);
      -    this._reset();
      -    this.isNew = false;
      -    this.emit('isNew', false);
      -    // Make it possible to retry the insert
      -    this._inserting = true;
      -
      -  } else {
      -    // Make sure we don't treat it as a new object on error,
      -    // since it already exists
      -    this._inserting = false;
      -
      -    var delta = this._delta();
      -    if (delta) {
      -      var where = this._where(delta[0]);
      -      this.collection.update(where, delta[1], options, complete);
      -    } else {
      -      process.nextTick(function () {
      -        complete(null);
      -      })
      -    }
      -
      -    this._reset();
      -    this.emit('isNew', false);
      -  }
      -};

      Parameters:

      Example:

      - -
      product.sold = Date.now();
      -product.save(function (err, product) {
      -  if (err) ..
      -})
      - -

      The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      - -
      var db = mongoose.createConnection(..);
      -var schema = new Schema(..);
      -var Product = db.model('Product', schema);
      -
      -db.on('error', handleError);
      - -

      However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

      - -
      Product.on('error', handleError);

      Model#_delta()

      Produces a special query document of the modified properties used in updates.

      show code
      Model.prototype._delta = function _delta () {
      -  var dirty = this._dirty();
      -  if (!dirty.length) return;
      -
      -  var self = this
      -    , where = {}
      -    , delta = {}
      -    , len = dirty.length
      -    , d = 0
      -    , val
      -    , obj
      -
      -  for (; d < len; ++d) {
      -    var data = dirty[d]
      -    var value = data.value
      -    var schema = data.schema
      -
      -    if (undefined === value) {
      -      operand(self, where, delta, data, 1, '$unset');
      -
      -    } else if (null === value) {
      -      operand(self, where, delta, data, null);
      -
      -    } else if (value._path && value._atomics) {
      -      // arrays and other custom types (support plugins etc)
      -      handleAtomics(self, where, delta, data, value);
      -
      -    } else if (value._path && Buffer.isBuffer(value)) {
      -      // MongooseBuffer
      -      value = value.toObject();
      -      operand(self, where, delta, data, value);
      -
      -    } else {
      -      value = utils.clone(value);
      -      operand(self, where, delta, data, value);
      -    }
      -  }
      -
      -  if (this.__version) {
      -    this._version(where, delta);
      -  }
      -
      -  return [where, delta];
      -}

      Model#_version()

      Appends versioning to the where and update clauses.

      show code
      Model.prototype._version = function _version (where, delta) {
      -  var key = this.schema.options.versionKey;
      -
      -  if (true === where) {
      -    // this is an insert
      -    if (key) this.setValue(key, delta[key] = 0);
      -    return;
      -  }
      -
      -  // updates
      -
      -  // only apply versioning if our versionKey was selected. else
      -  // there is no way to select the correct version. we could fail
      -  // fast here and force them to include the versionKey but
      -  // thats a bit intrusive. can we do this automatically?
      -  // TODO fail fast option?
      -  if (!this.isSelected(key)) {
      -    return;
      -  }
      -
      -  // $push $addToSet don't need the where clause set
      -  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
      -    where[key] = this.getValue(key);
      -  }
      -
      -  if (VERSION_INC === (VERSION_INC & this.__version)) {
      -    delta.$inc || (delta.$inc = {});
      -    delta.$inc[key] = 1;
      -  }
      -}

      Model#increment()

      Signal that we desire an increment of this documents version.

      show code
      Model.prototype.increment = function increment () {
      -  this.__version = VERSION_ALL;
      -  return this;
      -}

      Model#_where()

      Returns a query object which applies shardkeys if they exist.

      show code
      Model.prototype._where = function _where (where) {
      -  where || (where = {});
      -
      -  var paths
      -    , len
      -
      -  if (this._shardval) {
      -    paths = Object.keys(this._shardval)
      -    len = paths.length
      -
      -    for (var i = 0; i < len; ++i) {
      -      where[paths[i]] = this._shardval[paths[i]];
      -    }
      -  }
      -
      -  where._id = this._doc._id;
      -  return where;
      -}

      Model#remove([fn])

      Removes this document from the db.

      show code
      Model.prototype.remove = function remove (fn) {
      -  if (this._removing) {
      -    this._removing.addBack(fn);
      -    return this;
      -  }
      -
      -  var promise = this._removing = new Promise(fn)
      -    , where = this._where()
      -    , self = this
      -    , options = {}
      -
      -  if (this.schema.options.safe) {
      -    options.safe = this.schema.options.safe;
      -  }
      -
      -  this.collection.remove(where, options, tick(function (err) {
      -    if (err) {
      -      promise.error(err);
      -      promise = self = self._removing = where = options = null;
      -      return;
      -    }
      -    self.emit('remove', self);
      -    promise.complete();
      -    promise = self = where = options = null;
      -  }));
      -
      -  return this;
      -};

      Parameters:

      Example:

      - -
      product.remove(function (err, product) {
      -  if (err) return handleError(err);
      -  Product.findById(product._id, function (err, product) {
      -    console.log(product) // null
      -  })
      -})

      Model#_registerHooks()

      Register hooks override

      show code
      Model.prototype._registerHooks = function registerHooks () {
      -  Document.prototype._registerHooks.call(this);
      -};

      Model#model(name)

      Returns another Model instance.

      show code
      Model.prototype.model = function model (name) {
      -  return this.db.model(name);
      -};
      -
      -// Model (class) features

      Parameters:

      Example:

      - -
      var doc = new Tank;
      -doc.model('User').findById(id, callback);

      Model#$where(argument)

      Creates a Query and specifies a $where condition.

      Parameters:

      • argument <String, Function> is a javascript string or anonymous function

      Returns:

      Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      - -
      Blog.$where('this.comments.length &gt; 5');

      Model.init()

      Called when the model compiles.

      show code
      Model.init = function init () {
      -  if (this.schema.options.autoIndex)
      -    this.ensureIndexes();
      -
      -  this.schema.emit('init', this);
      -};

      Model.ensureIndexes([cb])

      Sends ensureIndex commands to mongo for each index declared in the schema.

      show code
      Model.ensureIndexes = function ensureIndexes (cb) {
      -  var indexes = this.schema.indexes();
      -  if (!indexes.length) {
      -    return cb && cb();
      -  }
      -
      -  var self = this
      -    , safe = self.schema.options.safe
      -    , count = indexes.length
      -    , error
      -
      -  indexes.forEach(function (index) {
      -    var options = index[1];
      -    options.safe = safe;
      -    self.collection.ensureIndex(index[0], options, tick(function (err) {
      -      if (err) error = err;
      -      if (--count) return;
      -
      -      self.emit('index', error);
      -      cb && cb(error);
      -    }));
      -  });
      -}

      Parameters:

      After completion, an index event is emitted on this Model passing an error if one occurred.

      - -

      NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

      - -

      Example:

      - -
      Event.ensureIndexes(function (err) {
      -  if (err) return handleError(err);
      -});

      Model.remove(conditions, [callback])

      Removes documents from the collection.

      show code
      Model.remove = function remove (conditions, callback) {
      -  if ('function' === typeof conditions) {
      -    callback = conditions;
      -    conditions = {};
      -  }
      -
      -  var query = new Query(conditions).bind(this, 'remove');
      -
      -  if ('undefined' === typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.remove(callback);
      -};

      Parameters:

      Returns:

      Note:

      - -

      To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      - -
      Comment.remove({ _id: id }).exec();

      Model.find(conditions, [fields], [options], [callback])

      Finds documents

      show code
      Model.find = function find (conditions, fields, options, callback) {
      -  if ('function' == typeof conditions) {
      -    callback = conditions;
      -    conditions = {};
      -    fields = null;
      -    options = null;
      -  } else if ('function' == typeof fields) {
      -    callback = fields;
      -    fields = null;
      -    options = null;
      -  } else if ('function' == typeof options) {
      -    callback = options;
      -    options = null;
      -  }
      -
      -  var query = new Query(conditions, options);
      -  query.bind(this, 'find');
      -  query.select(fields);
      -
      -  if ('undefined' === typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.find(callback);
      -};

      Parameters:

      Returns:

      Examples:

      - -
      // retrieve only certain keys
      -MyModel.find({ name: /john/i }, 'name friends', function () { })
      -
      -// pass options
      -MyModel.find({ name: /john/i }, null, { skip: 10 } )

      Model._applyNamedScope(query)

      Merges the current named scope query into query.

      show code
      Model._applyNamedScope = function _applyNamedScope (query) {
      -  var cQuery = this._cumulativeQuery;
      -
      -  if (cQuery) {
      -    merge(query._conditions, cQuery._conditions);
      -    if (query._fields && cQuery._fields)
      -      merge(query._fields, cQuery._fields);
      -    if (query.options && cQuery.options)
      -      merge(query.options, cQuery.options);
      -    delete this._cumulativeQuery;
      -  }
      -
      -  return query;
      -}

      Parameters:

      Returns:


      Model.findById(id, [fields], [options], [callback])

      Finds a single document by id.

      show code
      Model.findById = function findById (id, fields, options, callback) {
      -  return this.findOne({ _id: id }, fields, options, callback);
      -};

      Parameters:

      Returns:

      The id is cast to an ObjectId before sending the command.

      - -

      Example:

      - -
      Adventure.findById(id, callback);

      Model.findOne(conditions, [fields], [options], [callback])

      Finds one document.

      show code
      Model.findOne = function findOne (conditions, fields, options, callback) {
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = null;
      -  } else if ('function' == typeof fields) {
      -    callback = fields;
      -    fields = null;
      -    options = null;
      -  } else if ('function' == typeof conditions) {
      -    callback = conditions;
      -    conditions = {};
      -    fields = null;
      -    options = null;
      -  }
      -
      -  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.findOne(callback);
      -};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      - -

      Example:

      - -
      Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

      Model.count(conditions, [callback])

      Counts number of matching documents in a database collection.

      show code
      Model.count = function count (conditions, callback) {
      -  if ('function' === typeof conditions)
      -    callback = conditions, conditions = {};
      -
      -  var query = new Query(conditions).bind(this, 'count');
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.count(callback);
      -};

      Parameters:

      Returns:

      Example:

      - -
      Adventure.count({ type: 'jungle' }, function (err, count) {
      -  if (err) ..
      -  console.log('there are %d jungle adventures', count);
      -});

      Model.distinct(field, [conditions], [callback])

      Executes a DISTINCT command

      show code
      Model.distinct = function distinct (field, conditions, callback) {
      -  var query = new Query(conditions).bind(this, 'distinct');
      -  if ('undefined' == typeof callback) {
      -    query._distinctArg = field;
      -    return query;
      -  }
      -
      -  this._applyNamedScope(query);
      -  return query.distinct(field, callback);
      -};

      Parameters:

      Returns:


      Model.where(path, [val])

      Creates a Query, applies the passed conditions, and returns the Query.

      show code
      Model.where = function where (path, val) {
      -  var q = new Query().bind(this, 'find');
      -  return q.where.apply(q, arguments);
      -};

      Parameters:

      Returns:

      For example, instead of writing:

      - -
      User.find({age: {$gte: 21, $lte: 65}}, callback);
      - -

      we can instead write:

      - -
      User.where('age').gte(21).lte(65).exec(callback);
      - -

      Since the Query class also supports where you can continue chaining

      - -
      User
      -.where('age').gte(21).lte(65)
      -.where('name', /^b/i)
      -... etc

      Model.findOneAndUpdate([conditions], [update], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Model.findOneAndUpdate = function (conditions, update, options, callback) {
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = null;
      -  }
      -  else if (1 === arguments.length) {
      -    if ('function' == typeof conditions) {
      -      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
      -
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(update)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate()
      -';
      -      throw new TypeError(msg)
      -    }
      -    update = conditions;
      -    conditions = undefined;
      -  }
      -
      -  var fields;
      -  if (options && options.fields) {
      -    fields = options.fields;
      -    options.fields = undefined;
      -  }
      -
      -  var query = new Query(conditions);
      -  query.setOptions(options);
      -  query.select(fields);
      -  query.bind(this, 'findOneAndUpdate', update);
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.findOneAndUpdate(callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findOneAndUpdate(conditions, update, options, callback) // executes
      -A.findOneAndUpdate(conditions, update, options)  // returns Query
      -A.findOneAndUpdate(conditions, update, callback) // executes
      -A.findOneAndUpdate(conditions, update)           // returns Query
      -A.findOneAndUpdate()                             // returns Query
      - -

      Note:

      - -

      All top level update keys which are not atomic operation names are treated as set operations:

      - -

      Example:

      - -
      var query = { name: 'borne' };
      -Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
      -
      -// is sent as
      -Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
      - -

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      - -

      Note:

      - -

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      - -
        -
      • defaults
      • -
      • setters
      • -
      • validators
      • -
      • middleware
      • -
      - -

      If you need those features, use the traditional approach of first retrieving the document.

      - -
      Model.findOne({ name: 'borne' }, function (err, doc) {
      -  if (err) ..
      -  doc.name = 'jason borne';
      -  doc.save(callback);
      -})

      Model.findByIdAndUpdate(id, [update], [options], [callback])

      Issues a mongodb findAndModify update command by a documents id.

      show code
      Model.findByIdAndUpdate = function (id, update, options, callback) {
      -  var args;
      -
      -  if (1 === arguments.length) {
      -    if ('function' == typeof id) {
      -      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
      -
      -'
      -                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      -'
      -                + '  ' + this.modelName + '.findByIdAndUpdate(id)
      -'
      -                + '  ' + this.modelName + '.findByIdAndUpdate()
      -';
      -      throw new TypeError(msg)
      -    }
      -    return this.findOneAndUpdate({_id: id }, undefined);
      -  }
      -
      -  args = utils.args(arguments, 1);
      -  args.unshift({ _id: id });
      -  return this.findOneAndUpdate.apply(this, args);
      -}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findByIdAndUpdate(id, update, options, callback) // executes
      -A.findByIdAndUpdate(id, update, options)  // returns Query
      -A.findByIdAndUpdate(id, update, callback) // executes
      -A.findByIdAndUpdate(id, update)           // returns Query
      -A.findByIdAndUpdate()                     // returns Query
      - -

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      - -

      Note:

      - -

      All top level update keys which are not atomic operation names are treated as set operations:

      - -

      Example:

      - -
      Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
      -
      -// is sent as
      -Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
      - -

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      - -

      Note:

      - -

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      - -
        -
      • defaults
      • -
      • setters
      • -
      • validators
      • -
      • middleware
      • -
      - -

      If you need those features, use the traditional approach of first retrieving the document.

      - -
      Model.findById(id, function (err, doc) {
      -  if (err) ..
      -  doc.name = 'jason borne';
      -  doc.save(callback);
      -})

      Model.findOneAndRemove(conditions, [options], [callback])

      Issue a mongodb findAndModify remove command.

      show code
      Model.findOneAndRemove = function (conditions, options, callback) {
      -  if (1 === arguments.length && 'function' == typeof conditions) {
      -    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
      -
      -'
      -              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      -'
      -              + '  ' + this.modelName + '.findOneAndRemove(conditions)
      -'
      -              + '  ' + this.modelName + '.findOneAndRemove()
      -';
      -    throw new TypeError(msg)
      -  }
      -
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = undefined;
      -  }
      -
      -  var fields;
      -  if (options) {
      -    fields = options.select;
      -    options.select = undefined;
      -  }
      -
      -  var query = new Query(conditions);
      -  query.setOptions(options);
      -  query.select(fields);
      -  query.bind(this, 'findOneAndRemove');
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.findOneAndRemove(callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      - -

      Executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findOneAndRemove(conditions, options, callback) // executes
      -A.findOneAndRemove(conditions, options)  // return Query
      -A.findOneAndRemove(conditions, callback) // executes
      -A.findOneAndRemove(conditions) // returns Query
      -A.findOneAndRemove()           // returns Query

      Model.findByIdAndRemove(id, [options], [callback])

      Issue a mongodb findAndModify remove command by a documents id.

      show code
      Model.findByIdAndRemove = function (id, options, callback) {
      -  if (1 === arguments.length && 'function' == typeof id) {
      -    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
      -
      -'
      -              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      -'
      -              + '  ' + this.modelName + '.findByIdAndRemove(id)
      -'
      -              + '  ' + this.modelName + '.findByIdAndRemove()
      -';
      -    throw new TypeError(msg)
      -  }
      -
      -  return this.findOneAndRemove({ _id: id }, options, callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      - -

      Executes immediately if callback is passed, else a Query object is returned.

      - -

      Options:

      - -
        -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findByIdAndRemove(id, options, callback) // executes
      -A.findByIdAndRemove(id, options)  // return Query
      -A.findByIdAndRemove(id, callback) // executes
      -A.findByIdAndRemove(id) // returns Query
      -A.findByIdAndRemove()           // returns Query

      Model.create(doc, fn)

      Shortcut for creating a new Document that is automatically saved to the db if valid.

      show code
      Model.create = function create (doc, fn) {
      -  if (1 === arguments.length) {
      -    return 'function' === typeof doc && doc(null);
      -  }
      -
      -  var self = this
      -    , docs = [null]
      -    , promise
      -    , count
      -    , args
      -
      -  if (Array.isArray(doc)) {
      -    args = doc;
      -  } else {
      -    args = utils.args(arguments, 0, arguments.length - 1);
      -    fn = arguments[arguments.length - 1];
      -  }
      -
      -  if (0 === args.length) return fn(null);
      -
      -  promise = new Promise(fn);
      -  count = args.length;
      -
      -  args.forEach(function (arg, i) {
      -    var doc = new self(arg);
      -    docs[i+1] = doc;
      -    doc.save(function (err) {
      -      if (err) return promise.error(err);
      -      --count || fn.apply(null, docs);
      -    });
      -  });
      -
      -  // TODO
      -  // utilize collection.insertAll for batch processing?
      -};

      Parameters:

      Example:

      - -
      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
      -  if (err) // ...
      -});
      -
      -var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      -Candy.create(array, function (err, jellybean, snickers) {
      -  if (err) // ...
      -});

      Model.update(conditions, update, [options], [callback])

      Updates documents in the database without returning them.

      show code
      Model.update = function update (conditions, doc, options, callback) {
      -  if (arguments.length < 4) {
      -    if ('function' === typeof options) {
      -      // Scenario: update(conditions, doc, callback)
      -      callback = options;
      -      options = null;
      -    } else if ('function' === typeof doc) {
      -      // Scenario: update(doc, callback);
      -      callback = doc;
      -      doc = conditions;
      -      conditions = {};
      -      options = null;
      -    }
      -  }
      -
      -  var query = new Query(conditions, options).bind(this, 'update', doc);
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.update(doc, callback);
      -};

      Parameters:

      Returns:

      Examples:

      - -
      MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
      -MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
      -  if (err) return handleError(err);
      -  console.log('The number of updated documents was %d', numberAffected);
      -  console.log('The raw response from Mongo was ', raw);
      -});
      - -

      Valid options:

      - -
        -
      • safe (boolean) safe mode (defaults to value set in schema (true))
      • -
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • -
      • multi (boolean) whether multiple documents should be updated (false)
      • -
      - -

      All update values are cast to their appropriate SchemaTypes before being sent.

      - -

      The callback function receives (err, numberAffected, rawResponse).

      - -
        -
      • err is the error if any occurred
      • -
      • numberAffected is the count of updated documents Mongo reported
      • -
      • rawResponse is the full response from Mongo
      • -
      - -

      Note:

      - -

      All top level keys which are not atomic operation names are treated as set operations:

      - -

      Example:

      - -
      var query = { name: 'borne' };
      -Model.update(query, { name: 'jason borne' }, options, callback)
      -
      -// is sent as
      -Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
      - -

      This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

      - -

      Note:

      - -

      To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      - -
      Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
      - -

      Note:

      - -

      Although values are casted to their appropriate types when using update, the following are not applied:

      - -
        -
      • defaults
      • -
      • setters
      • -
      • validators
      • -
      • middleware
      • -
      - -

      If you need those features, use the traditional approach of first retrieving the document.

      - -
      Model.findOne({ name: 'borne' }, function (err, doc) {
      -  if (err) ..
      -  doc.name = 'jason borne';
      -  doc.save(callback);
      -})

      Model.mapReduce(o, callback)

      Executes a mapReduce command.

      show code
      Model.mapReduce = function mapReduce (o, callback) {
      -  if ('function' != typeof callback) throw new Error('missing callback');
      -
      -  var self = this;
      -
      -  if (!Model.mapReduce.schema) {
      -    var opts = { noId: true, noVirtualId: true, strict: false }
      -    Model.mapReduce.schema = new Schema({}, opts);
      -  }
      -
      -  if (!o.out) o.out = { inline: 1 };
      -
      -  o.map = String(o.map);
      -  o.reduce = String(o.reduce);
      -
      -  if (o.query) {
      -    var q = new Query(o.query);
      -    q.cast(this);
      -    o.query = q._conditions;
      -    q = undefined;
      -  }
      -
      -  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
      -    if (err) return callback(err);
      -
      -    if (ret.findOne && ret.mapReduce) {
      -      // returned a collection, convert to Model
      -      var model = Model.compile(
      -          '_mapreduce_' + ret.collectionName
      -        , Model.mapReduce.schema
      -        , ret.collectionName
      -        , self.db
      -        , self.base);
      -
      -      model._mapreduce = true;
      -
      -      return callback(err, model, stats);
      -    }
      -
      -    callback(err, ret, stats);
      -  });
      -}

      Parameters:

      • o <Object> an object specifying map-reduce options
      • callback <Function>

      o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

      - -

      Example:

      - -
      var o = {};
      -o.map = function () { emit(this.name, 1) }
      -o.reduce = function (k, vals) { return vals.length }
      -User.mapReduce(o, function (err, results) {
      -  console.log(results)
      -})
      - -

      Other options:

      - -
        -
      • query {Object} query filter object.
      • -
      • limit {Number} max number of documents
      • -
      • keeptemp {Boolean, default:false} keep temporary data
      • -
      • finalize {Function} finalize function
      • -
      • scope {Object} scope variables exposed to map/reduce/finalize during execution
      • -
      • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
      • -
      • verbose {Boolean, default:false} provide statistics on job execution time.
      • -
      • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
      • -
      - -

      * out options:

      - -
        -
      • {inline:1} the results are returned in an array
      • -
      • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
      • -
      • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
      • -
      • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
      • -
      - -

      If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

      - -

      Example:

      - -
      var o = {};
      -o.map = function () { emit(this.name, 1) }
      -o.reduce = function (k, vals) { return vals.length }
      -o.out = { replace: 'createdCollectionNameForResults' }
      -o.verbose = true;
      -User.mapReduce(o, function (err, model, stats) {
      -  console.log('map reduce took %d ms', stats.processtime)
      -  model.find().where('value').gt(10).exec(function (err, docs) {
      -    console.log(docs);
      -  });
      -})

      Model.aggregate(array, [options], callback)

      Executes an aggregate command on this models collection.

      show code
      Model.aggregate = function aggregate () {
      -  return this.collection.aggregate.apply(this.collection, arguments);
      -}

      Parameters:

      Example:

      - -
      // find the max age of all users
      -Users.aggregate(
      -    { $group: { _id: null, maxAge: { $max: '$age' }}}
      -  , { $project: { _id: 0, maxAge: 1 }}
      -  , function (err, res) {
      -  if (err) return handleError(err);
      -  console.log(res); // [ { maxAge: 98 } ]
      -});
      - -

      NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

      - -

      NOTE: this requires running MongoDB >= 2.1


      Model#base

      Base Mongoose instance the model uses.


      Model#collection

      Collection the model uses.


      Model#db

      Database instance the model uses.


      Model#schema

      Schema the model uses.


      Model#modelName

      The name of the model


      Model#collection

      Collection the model uses.


      Model#db

      Connection the model uses.


    • namedscope.js

      NamedScope#decorate(target, getters)

      Decorate

      show code
      NamedScope.prototype.decorate = function (target, getters) {
      -  var name = this.name
      -    , block = this.block
      -    , query = this.query;
      -  if (block) {
      -    if (block.length === 0) {
      -      Object.defineProperty(target, name, {
      -        get: getters.block0(block)
      -      });
      -    } else {
      -      target[name] = getters.blockN(block);
      -    }
      -  } else {
      -    Object.defineProperty(target, name, {
      -      get: getters.basic(query)
      -    });
      -  }
      -};
      -
      -NamedScope.prototype.compile = function (model) {
      -  var allScopes = this.scopesByName
      -    , scope;
      -  for (var k in allScopes) {
      -    scope = allScopes[k];
      -    scope.decorate(model, {
      -      block0: function (block) {
      -        return function () {
      -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      -          block.call(cquery);
      -          return this;
      -        };
      -      },
      -      blockN: function (block) {
      -        return function () {
      -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      -          block.apply(cquery, arguments);
      -          return this;
      -        };
      -      },
      -      basic: function (query) {
      -        return function () {
      -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      -          cquery.find(query);
      -          return this;
      -        };
      -      }
      -    });
      -  }
      -};
      -
      -module.exports = NamedScope;

      Parameters:


    • promise.js

      Promise(back)

      Promise constructor.

      show code
      function Promise (back) {
      -  this.emitted = {};
      -  if ('function' == typeof back)
      -    this.addBack(back);
      -};

      Parameters:

      • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

      Events:

      • err: Emits when the promise resolves to an error.

      • complete: Emits when the promise resolves sucessfully.


      Promise#on(event, callback)

      Adds listener to the event.

      show code
      Promise.prototype.on = function (event, callback) {
      -  if (this.emitted[event])
      -    callback.apply(this, this.emitted[event]);
      -  else
      -    EventEmitter.prototype.on.call(this, event, callback);
      -
      -  return this;
      -};

      Parameters:

      Returns:

      If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


      Promise#emit()

      Keeps track of emitted events to run them on on.

      show code
      Promise.prototype.emit = function (event) {
      -  // ensures a promise can't be complete() or error() twice
      -  if (event == 'err' || event == 'complete'){
      -    if (this.emitted.err || this.emitted.complete) {
      -      return this;
      -    }
      -    this.emitted[event] = util.args(arguments, 1);
      -  }
      -
      -  return EventEmitter.prototype.emit.apply(this, arguments);
      -};

      Promise#complete()

      Shortcut for emitting the complete event.

      show code
      Promise.prototype.complete = function () {
      -  var args = util.args(arguments);
      -  return this.emit.apply(this, ['complete'].concat(args));
      -};

      Promise#error()

      Shortcut for emitting the err event.

      show code
      Promise.prototype.error = function (err) {
      -  if (!(err instanceof Error)) err = new Error(err);
      -  return this.emit('err', err);
      -};

      Returns:


      Promise#addCallback()

      Shortcut for .on('complete', fn).

      show code
      Promise.prototype.addCallback = function (fn) {
      -  return this.on('complete', fn);
      -};

      Returns:


      Promise#addErrback()

      Shortcut for .on('err', fn).

      show code
      Promise.prototype.addErrback = function (fn) {
      -  return this.on('err', fn);
      -};

      Returns:


      Promise#addBack(fn)

      Adds a single function that's both a callback and errback.

      show code
      Promise.prototype.addBack = function (fn) {
      -  this.on('err', function(err){
      -    fn.call(this, err);
      -  });
      -
      -  this.on('complete', function(){
      -    var args = util.args(arguments);
      -    fn.apply(this, [null].concat(args));
      -  });
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Promise#resolve(err, val)

      Sugar for handling cases where you may be resolving to either an error condition or a success condition.

      show code
      Promise.prototype.resolve = function (err, val) {
      -  if (err) return this.error(err);
      -  return this.complete(val);
      -};

      Parameters:

      • err <Error> optional error or null
      • val <Object> value to complete the promise with

    • query.js

      Query(criteria, options)

      Query constructor used for building queries.

      show code
      function Query (criteria, options) {
      -  this.setOptions(options, true);
      -  this._conditions = {};
      -  this._updateArg = {};
      -  this._fields = undefined;
      -  if (criteria) this.find(criteria);
      -}

      Parameters:

      Example:

      - -
      var query = Model.find();
      -query.where('age').gte(21).exec(callback);

      Query#setOptions(options)

      Sets query options.

      show code
      Query.prototype.setOptions = function (options, overwrite) {
      -  // overwrite is internal use only
      -  if (overwrite) {
      -    options = this.options = options || {};
      -    this.safe = options.safe
      -
      -    // normalize population options
      -    var pop = this.options.populate;
      -    this.options.populate = {};
      -
      -    if (pop && Array.isArray(pop)) {
      -      for (var i = 0, l = pop.length; i < l; i++) {
      -        this.options.populate[pop[i]] = {};
      -      }
      -    }
      -
      -    return this;
      -  }
      -
      -  if (!(options && 'Object' == options.constructor.name))
      -    return this;
      -
      -  if ('safe' in options)
      -    this.safe = options.safe;
      -
      -  // set arbitrary options
      -  var methods = Object.keys(options)
      -    , i = methods.length
      -    , method
      -
      -  while (i--) {
      -    method = methods[i];
      -
      -    // use methods if exist (safer option manipulation)
      -    if ('function' == typeof this[method]) {
      -      var args = Array.isArray(options[method])
      -        ? options[method]
      -        : [options[method]];
      -      this[method].apply(this, args)
      -    } else {
      -      this.options[method] = options[method];
      -    }
      -  }
      -  return this;
      -}

      Parameters:

      Options:

      - - - -

      * denotes a query helper method is also available


      Query#bind(model, op, updateArg)

      Binds this query to a model.

      show code
      Query.prototype.bind = function bind (model, op, updateArg) {
      -  this.model = model;
      -  this.op = op;
      -
      -  if (model._mapreduce) this.options.lean = true;
      -
      -  if (op == 'update' || op == 'findOneAndUpdate') {
      -    merge(this._updateArg, updateArg || {});
      -  }
      -
      -  return this;
      -};

      Parameters:

      • model <Model> the model to which the query is bound
      • op <String> the operation to execute
      • updateArg <Object> used in update methods

      Returns:


      Query#exec([operation], [callback])

      Executes the query

      show code
      Query.prototype.exec = function exec (op, callback) {
      -  var promise = new Promise();
      -
      -  switch (typeof op) {
      -    case 'function':
      -      callback = op;
      -      op = null;
      -      break;
      -    case 'string':
      -      this.op = op;
      -      break;
      -  }
      -
      -  if (callback) promise.addBack(callback);
      -
      -  if (!this.op) {
      -    promise.complete();
      -    return promise;
      -  }
      -
      -  if ('update' == this.op) {
      -    this[this.op](this._updateArg, promise.resolve.bind(promise));
      -    return promise;
      -  }
      -
      -  if ('distinct' == this.op) {
      -    this.distinct(this._distinctArg, promise.resolve.bind(promise));
      -    return promise;
      -  }
      -
      -  this[this.op](promise.resolve.bind(promise));
      -  return promise;
      -};

      Parameters:

      Returns:

      Examples

      - -
      query.exec();
      -query.exec(callback);
      -query.exec('update');
      -query.exec('find', callback);

      Query#find([criteria], [callback])

      Finds documents.

      show code
      Query.prototype.find = function (criteria, callback) {
      -  this.op = 'find';
      -  if ('function' === typeof criteria) {
      -    callback = criteria;
      -    criteria = {};
      -  } else if (criteria instanceof Query) {
      -    // TODO Merge options, too
      -    merge(this._conditions, criteria._conditions);
      -  } else if (criteria instanceof Document) {
      -    merge(this._conditions, criteria.toObject());
      -  } else if (criteria && 'Object' === criteria.constructor.name) {
      -    merge(this._conditions, criteria);
      -  }
      -  if (!callback) return this;
      -  return this.execFind(callback);
      -};

      Parameters:

      Returns:

      When no callback is passed, the query is not executed.

      - -

      Example

      - -
      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

      Query#cast(model, [obj])

      Casts this query to the schema of model

      show code
      Query.prototype.cast = function (model, obj) {
      -  obj || (obj= this._conditions);
      -
      -  var schema = model.schema
      -    , paths = Object.keys(obj)
      -    , i = paths.length
      -    , any$conditionals
      -    , schematype
      -    , nested
      -    , path
      -    , type
      -    , val;
      -
      -  while (i--) {
      -    path = paths[i];
      -    val = obj[path];
      -
      -    if ('$or' === path || '$nor' === path || '$and' === path) {
      -      var k = val.length
      -        , orComponentQuery;
      -
      -      while (k--) {
      -        orComponentQuery = new Query(val[k]);
      -        orComponentQuery.cast(model);
      -        val[k] = orComponentQuery._conditions;
      -      }
      -
      -    } else if (path === '$where') {
      -      type = typeof val;
      -
      -      if ('string' !== type && 'function' !== type) {
      -        throw new Error("Must have a string or function for $where");
      -      }
      -
      -      if ('function' === type) {
      -        obj[path] = val.toString();
      -      }
      -
      -      continue;
      -
      -    } else {
      -
      -      if (!schema) {
      -        // no casting for Mixed types
      -        continue;
      -      }
      -
      -      schematype = schema.path(path);
      -
      -      if (!schematype) {
      -        // Handle potential embedded array queries
      -        var split = path.split('.')
      -          , j = split.length
      -          , pathFirstHalf
      -          , pathLastHalf
      -          , remainingConds
      -          , castingQuery;
      -
      -        // Find the part of the var path that is a path of the Schema
      -        while (j--) {
      -          pathFirstHalf = split.slice(0, j).join('.');
      -          schematype = schema.path(pathFirstHalf);
      -          if (schematype) break;
      -        }
      -
      -        // If a substring of the input path resolves to an actual real path...
      -        if (schematype) {
      -          // Apply the casting; similar code for $elemMatch in schema/array.js
      -          if (schematype.caster && schematype.caster.schema) {
      -            remainingConds = {};
      -            pathLastHalf = split.slice(j).join('.');
      -            remainingConds[pathLastHalf] = val;
      -            castingQuery = new Query(remainingConds);
      -            castingQuery.cast(schematype.caster);
      -            obj[path] = castingQuery._conditions[pathLastHalf];
      -          } else {
      -            obj[path] = val;
      -          }
      -        }
      -
      -      } else if (val === null || val === undefined) {
      -        continue;
      -      } else if ('Object' === val.constructor.name) {
      -
      -        any$conditionals = Object.keys(val).some(function (k) {
      -          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
      -        });
      -
      -        if (!any$conditionals) {
      -          obj[path] = schematype.castForQuery(val);
      -        } else {
      -
      -          var ks = Object.keys(val)
      -            , k = ks.length
      -            , $cond;
      -
      -          while (k--) {
      -            $cond = ks[k];
      -            nested = val[$cond];
      -
      -            if ('$exists' === $cond) {
      -              if ('boolean' !== typeof nested) {
      -                throw new Error("$exists parameter must be Boolean");
      -              }
      -              continue;
      -            }
      -
      -            if ('$type' === $cond) {
      -              if ('number' !== typeof nested) {
      -                throw new Error("$type parameter must be Number");
      -              }
      -              continue;
      -            }
      -
      -            if ('$not' === $cond) {
      -              this.cast(model, nested);
      -            } else {
      -              val[$cond] = schematype.castForQuery($cond, nested);
      -            }
      -          }
      -        }
      -      } else {
      -        obj[path] = schematype.castForQuery(val);
      -      }
      -    }
      -  }
      -
      -  return obj;
      -};

      Parameters:

      Returns:

      Note

      - -

      If obj is present, it is cast instead of this query.


      Query#_optionsForExec(model)

      Returns default options.

      show code
      Query.prototype._optionsForExec = function (model) {
      -  var options = utils.clone(this.options, { retainKeyOrder: true });
      -  delete options.populate;
      -
      -  if (!('safe' in options))
      -    options.safe = model.schema.options.safe;
      -
      -  if (!('readPreference' in options) && model.schema.options.read)
      -    options.readPreference = model.schema.options.read;
      -
      -  return options;
      -};

      Parameters:


      Query#_applyPaths()

      Applies schematype selected options to this query.

      show code
      Query.prototype._applyPaths = function applyPaths () {
      -  // determine if query is selecting or excluding fields
      -
      -  var fields = this._fields
      -    , exclude
      -    , keys
      -    , ki
      -
      -  if (fields) {
      -    keys = Object.keys(fields);
      -    ki = keys.length;
      -
      -    while (ki--) {
      -      if ('+' == keys[ki][0]) continue;
      -      exclude = 0 === fields[keys[ki]];
      -      break;
      -    }
      -  }
      -
      -  // if selecting, apply default schematype select:true fields
      -  // if excluding, apply schematype select:false fields
      -
      -  var selected = []
      -    , excluded = []
      -    , seen = [];
      -
      -  analyzeSchema(this.model.schema);
      -
      -  switch (exclude) {
      -    case true:
      -      excluded.length && this.select('-' + excluded.join(' -'));
      -      break;
      -    case false:
      -      selected.length && this.select(selected.join(' '));
      -      break;
      -    case undefined:
      -      // user didn't specify fields, implies returning all fields.
      -      // only need to apply excluded fields
      -      excluded.length && this.select('-' + excluded.join(' -'));
      -      break;
      -  }
      -
      -  return seen = excluded = selected = keys = fields = null;
      -
      -  function analyzeSchema (schema, prefix) {
      -    prefix || (prefix = '');
      -
      -    // avoid recursion
      -    if (~seen.indexOf(schema)) return;
      -    seen.push(schema);
      -
      -    schema.eachPath(function (path, type) {
      -      if (prefix) path = prefix + '.' + path;
      -
      -      // array of subdocs?
      -      if (type.schema) {
      -        analyzeSchema(type.schema, path);
      -      }
      -
      -      analyzePath(path, type);
      -    });
      -  }
      -
      -  function analyzePath (path, type) {
      -    if ('boolean' != typeof type.selected) return;
      -
      -    if (fields && ('+' + path) in fields) {
      -      // forced inclusion
      -      delete fields['+' + path];
      -
      -      // if there are other fields being included, add this one
      -      // if no other included fields, leave this out (implied inclusion)
      -      if (false === exclude && keys.length > 1) {
      -        fields[path] = 1;
      -      }
      -
      -      return
      -    };
      -
      -    ;(type.selected ? selected : excluded).push(path);
      -  }
      -}

      Query#$where(js)

      Specifies a $where condition

      Parameters:

      Returns:

      Use $where when you need to select documents using a JavaScript expression.

      - -

      Example

      - -
      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
      -
      -query.$where(function () {
      -  return this.comments.length &gt; 10 || this.name.length &gt; 5;
      -})

      Query#where([path], [val])

      Specifies a path for use with chaining.

      show code
      Query.prototype.where = function (path, val) {
      -  if (!arguments.length) return this;
      -
      -  if ('string' != typeof path) {
      -    throw new TypeError('path must be a string');
      -  }
      -
      -  this._currPath = path;
      -
      -  if (2 === arguments.length) {
      -    this._conditions[path] = val;
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      // instead of writing:
      -User.find({age: {$gte: 21, $lte: 65}}, callback);
      -
      -// we can instead write:
      -User.where('age').gte(21).lte(65);
      -
      -// Moreover, you can also chain a bunch of these together:
      -
      -User
      -.where('age').gte(21).lte(65)
      -.where('name', /^b/i)
      -.where('friends').slice(10)
      -.exec(callback)

      Query#equals(val)

      Specifies the complementary comparison value for paths specified with where()

      show code
      Query.prototype.equals = function equals (val) {
      -  var path = this._currPath;
      -  if (!path) throw new Error('equals() must be used after where()');
      -  this._conditions[path] = val;
      -  return this;
      -}

      Parameters:

      Returns:

      Example

      - -
      User.where('age').equals(49);
      -
      -// is the same as
      -
      -User.where('age', 49);

      Query#or(array)

      Specifies arguments for an $or condition.

      show code
      Query.prototype.or = function or (array) {
      -  var or = this._conditions.$or || (this._conditions.$or = []);
      -  if (!Array.isArray(array)) array = [array];
      -  or.push.apply(or, array);
      -  return this;
      -}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      - -
      query.or([{ color: 'red' }, { status: 'emergency' }])

      Query#nor(array)

      Specifies arguments for a $nor condition.

      show code
      Query.prototype.nor = function nor (array) {
      -  var nor = this._conditions.$nor || (this._conditions.$nor = []);
      -  if (!Array.isArray(array)) array = [array];
      -  nor.push.apply(nor, array);
      -  return this;
      -}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      - -
      query.nor([{ color: 'green' }, { status: 'ok' }])

      Query#and(array)

      Specifies arguments for a $and condition.

      show code
      Query.prototype.and = function and (array) {
      -  var and = this._conditions.$and || (this._conditions.$and = []);
      -  if (!Array.isArray(array)) array = [array];
      -  and.push.apply(and, array);
      -  return this;
      -}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      - -
      query.and([{ color: 'green' }, { status: 'ok' }])

      Query#gt(path, val)

      Specifies a $gt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.

      - -

      Example

      - -
      Thing.find().where('age').gt(21)
      -
      -// or
      -Thing.find().gt('age', 21)

      Query#gte(path, val)

      Specifies a $gte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lt(path, val)

      Specifies a $lt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lte(path, val)

      Specifies a $lte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#ne(path, val)

      Specifies a $ne query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#in(path, val)

      Specifies an $in query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#nin(path, val)

      Specifies an $nin query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#all(path, val)

      Specifies an $all query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#size(path, val)

      Specifies an $size query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#regex(path, val)

      Specifies a $regex query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#maxDistance(path, val)

      Specifies a $maxDistance query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#near(path, val)

      Specifies a $near condition

      show code
      Query.prototype.near = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath
      -  } else if (arguments.length === 2 && !Array.isArray(val)) {
      -    val = utils.args(arguments);
      -    path = this._currPath;
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds.$near = val;
      -  return this;
      -}

      Parameters:

      Returns:


      Query#nearSphere(path, val)

      Specifies a $nearSphere condition.

      show code
      Query.prototype.nearSphere = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath
      -  } else if (arguments.length === 2 && !Array.isArray(val)) {
      -    val = utils.args(arguments);
      -    path = this._currPath;
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds.$nearSphere = val;
      -  return this;
      -}

      Parameters:

      Returns:


      Query#mod(path, val)

      Specifies a $mod condition

      show code
      Query.prototype.mod = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath
      -  } else if (arguments.length === 2 && !Array.isArray(val)) {
      -    val = utils.args(arguments);
      -    path = this._currPath;
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds.$mod = val;
      -  return this;
      -}

      Parameters:

      Returns:


      Query#exists(path, val)

      Specifies an $exists condition

      show code
      Query.prototype.exists = function (path, val) {
      -  if (arguments.length === 0) {
      -    path = this._currPath
      -    val = true;
      -  } else if (arguments.length === 1) {
      -    if ('boolean' === typeof path) {
      -      val = path;
      -      path = this._currPath;
      -    } else {
      -      val = true;
      -    }
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$exists'] = val;
      -  return this;
      -};

      Parameters:

      Returns:


      Query#elemMatch(path, criteria)

      Specifies an $elemMatch condition

      show code
      Query.prototype.elemMatch = function (path, criteria) {
      -  var block;
      -  if ('Object' === path.constructor.name) {
      -    criteria = path;
      -    path = this._currPath;
      -  } else if ('function' === typeof path) {
      -    block = path;
      -    path = this._currPath;
      -  } else if ('Object' === criteria.constructor.name) {
      -  } else if ('function' === typeof criteria) {
      -    block = criteria;
      -  } else {
      -    throw new Error("Argument error");
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  if (block) {
      -    criteria = new Query();
      -    block(criteria);
      -    conds['$elemMatch'] = criteria._conditions;
      -  } else {
      -    conds['$elemMatch'] = criteria;
      -  }
      -  return this;
      -};
      -
      -// Spatial queries

      Parameters:

      Returns:

      Example

      - -
      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
      -
      -query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
      -
      -query.elemMatch('comment', function (elem) {
      -  elem.where('author').equals('autobot');
      -  elem.where('votes').gte(5);
      -})
      -
      -query.where('comment').elemMatch(function (elem) {
      -  elem.where('author').equals('autobot');
      -  elem.where('votes').gte(5);
      -})

      Query#box(path, val)

      Specifies a $box condition

      show code
      Query.prototype.box = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$box': [val.ll, val.ur]  };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var lowerLeft = [40.73083, -73.99756]
      -var upperRight= [40.741404,  -73.988135]
      -query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

      Query#center(path, val, [opts])

      Specifies a $center condition

      show code
      Query.prototype.center = function (path, val, opts) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$center': [val.center, val.radius]  };
      -
      -  // copy any options
      -  if (opts && 'Object' == opts.constructor.name) {
      -    utils.options(opts, conds.$within);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var area = { center: [50, 50], radius: 10 }
      -query.where('loc').within.center(area)

      Query#centerSphere(path, val)

      Specifies a $centerSphere condition

      show code
      Query.prototype.centerSphere = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var area = { center: [50, 50], radius: 10 }
      -query.where('loc').within.centerSphere(area)

      Query#polygon(path, val)

      Specifies a $polygon condition

      show code
      Query.prototype.polygon = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$polygon': val };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      -query.where('loc').within.polygon(polyA)
      -
      -// or
      -var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      -query.where('loc').within.polygon(polyB)

      Query#select(arg)

      Specifies which document fields to include or exclude

      show code
      Query.prototype.select = function select (arg) {
      -  if (!arg) return this;
      -
      -  var fields = this._fields || (this._fields = {});
      -
      -  if ('Object' === arg.constructor.name) {
      -    Object.keys(arg).forEach(function (field) {
      -      fields[field] = arg[field];
      -    });
      -  } else if (1 === arguments.length && 'string' == typeof arg) {
      -    arg.split(/\s+/).forEach(function (field) {
      -      if (!field) return;
      -      var include = '-' == field[0] ? 0 : 1;
      -      if (include === 0) field = field.substring(1);
      -      fields[field] = include;
      -    });
      -  } else {
      -    throw new TypeError('Invalid select() argument. Must be a string or object.');
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

      - -

      Example

      - -
      // include a and b, exclude c
      -query.select('a b -c');
      -
      -// or you may use object notation, useful when
      -// you have keys already prefixed with a "-"
      -query.select({a: 1, b: 1, c: 0});
      -
      -// force inclusion of field excluded at schema level
      -query.select('+path')
      - -

      NOTE:

      - -

      v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


      Query#slice(path, val)

      Specifies a $slice condition

      show code
      Query.prototype.slice = function (path, val) {
      -  if (arguments.length === 1) {
      -      val = path;
      -      path = this._currPath
      -  } else if (arguments.length === 2) {
      -    if ('number' === typeof path) {
      -      val = [path, val];
      -      path = this._currPath;
      -    }
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var myFields = this._fields || (this._fields = {});
      -  myFields[path] = { '$slice': val };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      query.slice('comments', 5)
      -query.slice('comments', -5)
      -query.slice('comments', [10, 5])
      -query.where('comments').slice(5)
      -query.where('comments').slice([-10, 5])

      Query#sort(arg)

      Sets the sort order

      show code
      Query.prototype.sort = function (arg) {
      -  if (!arg) return this;
      -
      -  var sort = this.options.sort || (this.options.sort = []);
      -
      -  if ('Object' === arg.constructor.name) {
      -    Object.keys(arg).forEach(function (field) {
      -      push(sort, field, arg[field]);
      -    });
      -  } else if (1 === arguments.length && 'string' == typeof arg) {
      -    arg.split(/\s+/).forEach(function (field) {
      -      if (!field) return;
      -      var ascend = '-' == field[0] ? -1 : 1;
      -      if (ascend === -1) field = field.substring(1);
      -      push(sort, field, ascend);
      -    });
      -  } else {
      -    throw new TypeError('Invalid sort() argument. Must be a string or object.');
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

      - -

      If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

      - -

      Example

      - -
      // these are equivalent
      -query.sort({ field: 'asc', test: -1 });
      -query.sort('field -test');

      Query#limit(val)

      Specifies the limit option.

      Parameters:

      Example

      - -
      Kitten.find().limit(20)

      Query#skip(val)

      Specifies the skip option.

      Parameters:

      Example

      - -
      Kitten.find().skip(100).limit(20)

      Query#maxscan(val)

      Specifies the maxscan option.

      Parameters:

      Example

      - -
      Kitten.find().maxscan(100)

      Query#batchSize(val)

      Specifies the batchSize option.

      Parameters:

      Example

      - -
      Kitten.find().batchSize(100)

      Query#comment(val)

      Specifies the comment option.

      Parameters:

      Example

      - -
      Kitten.findOne(condition).comment('login query')

      Query#snapshot()

      Specifies this query as a snapshot query.

      show code
      Query.prototype.snapshot = function () {
      -  this.options.snapshot = true;
      -  return this;
      -};

      Returns:

      Example

      - -
      Kitten.find().snapshot()

      Query#hint(val)

      Sets query hints.

      show code
      Query.prototype.hint = function (val) {
      -  if (!val) return this;
      -
      -  var hint = this.options.hint || (this.options.hint = {});
      -
      -  if ('Object' === val.constructor.name) {
      -    // must keep object keys in order so don't use Object.keys()
      -    for (var k in val) {
      -      hint[k] = val[k];
      -    }
      -  } else {
      -    throw new TypeError('Invalid hint. ' + val);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      Model.find().hint({ indexA: 1, indexB: -1})

      Query#slaveOk(v)

      Sets the slaveOk option.

      show code
      Query.prototype.slaveOk = function (v) {
      -  this.options.slaveOk = arguments.length ? !!v : true;
      -  return this;
      -}

      Parameters:

      Returns:

      Example:

      - -
      new Query().slaveOk() // true
      -new Query().slaveOk(true)
      -new Query().slaveOk(false)

      Query#read(pref, [tags])

      Sets the readPreference option for the query.

      show code
      Query.prototype.read = function (pref, tags) {
      -  this.options.readPreference = utils.readPref(pref, tags);
      -  return this;
      -}

      Parameters:

      • pref <String> one of the listed preference options or their aliases
      • [tags] <Array> optional tags for this query

      Returns:

      Example:

      - -
      new Query().read('primary')
      -new Query().read('p')  // same as primary
      -
      -new Query().read('primaryPreferred')
      -new Query().read('pp') // same as primaryPreferred
      -
      -new Query().read('secondary')
      -new Query().read('s')  // same as secondary
      -
      -new Query().read('secondaryPreferred')
      -new Query().read('sp') // same as secondaryPreferred
      -
      -new Query().read('nearest')
      -new Query().read('n')  // same as nearest
      -
      -// with tags
      -new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
      - -

      Preferences:

      - -
      primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
      -secondary            Read from secondary if available, otherwise error.
      -primaryPreferred     Read from primary if available, otherwise a secondary.
      -secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
      -nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
      - -

      Aliases

      - -
      p   primary
      -pp  primaryPreferred
      -s   secondary
      -sp  secondaryPreferred
      -n   nearest
      - -

      Read more about how to use read preferrences here and here.


      Query#lean(v)

      Sets the lean option.

      show code
      Query.prototype.lean = function (v) {
      -  this.options.lean = arguments.length ? !!v : true;
      -  return this;
      -}

      Parameters:

      Returns:

      Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

      - -

      This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

      - -

      Example:

      - -
      new Query().lean() // true
      -new Query().lean(true)
      -new Query().lean(false)
      -
      -Model.find().lean().exec();
      -
      -var leanStream = Model.find().lean().stream();

      Query#tailable(v)

      Sets tailable option.

      show code
      Query.prototype.tailable = function (v) {
      -  this.options.tailable = arguments.length ? !!v : true;
      -  return this;
      -};

      Parameters:

      Example

      - -
      Kitten.find().tailable() &lt;== true
      -Kitten.find().tailable(true)
      -Kitten.find().tailable(false)

      Query#execFind(callback)

      Executes the query as a find() operation.

      show code
      Query.prototype.execFind = function (callback) {
      -  var model = this.model
      -    , promise = new Promise(callback);
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    promise.error(err);
      -    return this;
      -  }
      -
      -  // apply default schematype path selections
      -  this._applyPaths();
      -
      -  var self = this
      -    , castQuery = this._conditions
      -    , options = this._optionsForExec(model)
      -    , fields = utils.clone(this._fields)
      -
      -  options.fields = this._castFields(fields);
      -  if (options.fields instanceof Error) {
      -    promise.error(options.fields);
      -    return this;
      -  }
      -
      -  model.collection.find(castQuery, options, function (err, cursor) {
      -    if (err) return promise.error(err);
      -    cursor.toArray(tick(cb));
      -  });
      -
      -  function cb (err, docs) {
      -    if (err) return promise.error(err);
      -
      -    if (true === options.lean)
      -      return promise.complete(docs);
      -
      -    var arr = []
      -      , count = docs.length;
      -
      -    if (!count) return promise.complete([]);
      -
      -    for (var i = 0, l = docs.length; i < l; i++) {
      -      arr[i] = new model(undefined, fields, true);
      -      arr[i].init(docs[i], self, function (err) {
      -        if (err) return promise.error(err);
      -        --count || promise.complete(arr);
      -      });
      -    }
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Query#findOne(callback)

      Executes the query as a findOne() operation.

      show code
      Query.prototype.findOne = function (callback) {
      -  this.op = 'findOne';
      -
      -  if (!callback) return this;
      -
      -  var model = this.model;
      -  var promise = new Promise(callback);
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    promise.error(err);
      -    return this;
      -  }
      -
      -  // apply default schematype path selections
      -  this._applyPaths();
      -
      -  var self = this
      -    , castQuery = this._conditions
      -    , options = this._optionsForExec(model)
      -    , fields = utils.clone(this._fields)
      -
      -  options.fields = this._castFields(fields);
      -  if (options.fields instanceof Error) {
      -    promise.error(options.fields);
      -    return this;
      -  }
      -
      -  model.collection.findOne(castQuery, options, tick(function (err, doc) {
      -    if (err) return promise.error(err);
      -    if (!doc) return promise.complete(null);
      -
      -    if (true === options.lean) return promise.complete(doc);
      -
      -    var casted = new model(undefined, fields, true);
      -    casted.init(doc, self, function (err) {
      -      if (err) return promise.error(err);
      -      promise.complete(casted);
      -    });
      -  }));
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      Kitten.where('color', 'white').findOne(function (err, kitten) {
      -  if (err) return handleError(err);
      -
      -  // kitten may be null if no document matched
      -  if (kitten) {
      -    ...
      -  }
      -})

      Query#count(callback)

      Exectues the query as a count() operation.

      show code
      Query.prototype.count = function (callback) {
      -  this.op = 'count';
      -  var model = this.model;
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    return callback(err);
      -  }
      -
      -  var castQuery = this._conditions;
      -  model.collection.count(castQuery, tick(callback));
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      Kitten.where('color', 'black').count(function (err, count) {
      -  if (err) return handleError(err);
      -  console.log('there are %d black kittens', count);
      -})

      Query#distinct(field, callback)

      Executes this query as a distict() operation.

      show code
      Query.prototype.distinct = function (field, callback) {
      -  this.op = 'distinct';
      -  var model = this.model;
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    return callback(err);
      -  }
      -
      -  var castQuery = this._conditions;
      -  model.collection.distinct(field, castQuery, tick(callback));
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Query#update(doc, callback)

      Executes this query as an update() operation.

      show code
      Query.prototype.update = function update (doc, callback) {
      -  this.op = 'update';
      -  this._updateArg = doc;
      -
      -  var model = this.model
      -    , options = this._optionsForExec(model)
      -    , fn = 'function' == typeof callback
      -    , castedQuery
      -    , castedDoc
      -
      -  castedQuery = castQuery(this);
      -  if (castedQuery instanceof Error) {
      -    if (fn) {
      -      process.nextTick(callback.bind(null, castedQuery));
      -      return this;
      -    }
      -    throw castedQuery;
      -  }
      -
      -  castedDoc = castDoc(this);
      -  if (!castedDoc) {
      -    fn && process.nextTick(callback.bind(null, null, 0));
      -    return this;
      -  }
      -
      -  if (castedDoc instanceof Error) {
      -    if (fn) {
      -      process.nextTick(callback.bind(null, castedDoc));
      -      return this;
      -    }
      -    throw castedDoc;
      -  }
      -
      -  if (!fn) {
      -    delete options.safe;
      -  }
      -
      -  model.collection.update(castedQuery, castedDoc, options, tick(callback));
      -  return this;
      -};

      Parameters:

      Returns:

      All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

      - -

      Example

      - -
      Model.update({..}, { title: 'remove words' }, ...)
      - -

      becomes

      - -
      Model.update({..}, { $set: { title: 'remove words' }}, ...)
      - -

      Note

      - -

      Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


      Query#_castUpdate(obj)

      Casts obj for an update command.

      show code
      Query.prototype._castUpdate = function _castUpdate (obj) {
      -  var ops = Object.keys(obj)
      -    , i = ops.length
      -    , ret = {}
      -    , hasKeys
      -    , val
      -
      -  while (i--) {
      -    var op = ops[i];
      -    if ('$' !== op[0]) {
      -      // fix up $set sugar
      -      if (!ret.$set) {
      -        if (obj.$set) {
      -          ret.$set = obj.$set;
      -        } else {
      -          ret.$set = {};
      -        }
      -      }
      -      ret.$set[op] = obj[op];
      -      ops.splice(i, 1);
      -      if (!~ops.indexOf('$set')) ops.push('$set');
      -    } else if ('$set' === op) {
      -      if (!ret.$set) {
      -        ret[op] = obj[op];
      -      }
      -    } else {
      -      ret[op] = obj[op];
      -    }
      -  }
      -
      -  // cast each value
      -  i = ops.length;
      -
      -  while (i--) {
      -    op = ops[i];
      -    val = ret[op];
      -    if ('Object' === val.constructor.name) {
      -      hasKeys |= this._walkUpdatePath(val, op);
      -    } else {
      -      var msg = 'Invalid atomic update value for ' + op + '. '
      -              + 'Expected an object, received ' + typeof val;
      -      throw new Error(msg);
      -    }
      -  }
      -
      -  return hasKeys && ret;
      -}

      Parameters:

      Returns:

      • <Object> obj after casting its values

      Query#_walkUpdatePath(obj, op, pref)

      Walk each path of obj and cast its values
      according to its schema.

      show code
      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
      -  var strict = this.model.schema.options.strict
      -    , prefix = pref ? pref + '.' : ''
      -    , keys = Object.keys(obj)
      -    , i = keys.length
      -    , hasKeys = false
      -    , schema
      -    , key
      -    , val
      -
      -  while (i--) {
      -    key = keys[i];
      -    val = obj[key];
      -
      -    if (val && 'Object' === val.constructor.name) {
      -      // watch for embedded doc schemas
      -      schema = this._getSchema(prefix + key);
      -      if (schema && schema.caster && op in castOps) {
      -        // embedded doc schema
      -
      -        if (strict && !schema) {
      -          // path is not in our strict schema
      -          if ('throw' == strict) {
      -            throw new Error('Field `' + key + '` is not in schema.');
      -          } else {
      -            // ignore paths not specified in schema
      -            delete obj[key];
      -          }
      -        } else {
      -          hasKeys = true;
      -          if ('$each' in val) {
      -            obj[key] = {
      -                $each: this._castUpdateVal(schema, val.$each, op)
      -            }
      -          } else {
      -            obj[key] = this._castUpdateVal(schema, val, op);
      -          }
      -        }
      -      } else {
      -        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
      -      }
      -    } else {
      -      schema = '$each' === key
      -        ? this._getSchema(pref)
      -        : this._getSchema(prefix + key);
      -
      -      var skip = strict &&
      -                 !schema &&
      -                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
      -
      -      if (skip) {
      -        if ('throw' == strict) {
      -          throw new Error('Field `' + prefix + key + '` is not in schema.');
      -        } else {
      -          delete obj[key];
      -        }
      -      } else {
      -        hasKeys = true;
      -        obj[key] = this._castUpdateVal(schema, val, op, key);
      -      }
      -    }
      -  }
      -  return hasKeys;
      -}

      Parameters:

      • obj <Object> - part of a query
      • op <String> - the atomic operator ($pull, $set, etc)
      • pref <String> - path prefix (internal only)

      Returns:

      • <Bool> true if this path has keys to update

      Query#_castUpdateVal(schema, val, op, [$conditional])

      Casts val according to schema and atomic op.

      show code
      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
      -  if (!schema) {
      -    // non-existing schema path
      -    return op in numberOps
      -      ? Number(val)
      -      : val
      -  }
      -
      -  if (schema.caster && op in castOps &&
      -    ('Object' === val.constructor.name || Array.isArray(val))) {
      -    // Cast values for ops that add data to MongoDB.
      -    // Ensures embedded documents get ObjectIds etc.
      -    var tmp = schema.cast(val);
      -
      -    if (Array.isArray(val)) {
      -      val = tmp;
      -    } else {
      -      val = tmp[0];
      -    }
      -  }
      -
      -  if (op in numberOps) return Number(val);
      -  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
      -  return schema.castForQuery(val)
      -}

      Parameters:


      Query#_getSchema(path)

      Finds the schema for path. This is different than
      calling schema.path as it also resolves paths with
      positional selectors (something.$.another.$.path).

      show code
      Query.prototype._getSchema = function _getSchema (path) {
      -  var schema = this.model.schema
      -    , pathschema = schema.path(path);
      -
      -  if (pathschema)
      -    return pathschema;
      -
      -  // look for arrays
      -  return (function search (parts, schema) {
      -    var p = parts.length + 1
      -      , foundschema
      -      , trypath
      -
      -    while (p--) {
      -      trypath = parts.slice(0, p).join('.');
      -      foundschema = schema.path(trypath);
      -      if (foundschema) {
      -        if (foundschema.caster) {
      -
      -          // array of Mixed?
      -          if (foundschema.caster instanceof Types.Mixed) {
      -            return foundschema.caster;
      -          }
      -
      -          // Now that we found the array, we need to check if there
      -          // are remaining document paths to look up for casting.
      -          // Also we need to handle array.$.path since schema.path
      -          // doesn't work for that.
      -          if (p !== parts.length) {
      -            if ('$' === parts[p]) {
      -              // comments.$.comments.$.title
      -              return search(parts.slice(p+1), foundschema.schema);
      -            } else {
      -              // this is the last path of the selector
      -              return search(parts.slice(p), foundschema.schema);
      -            }
      -          }
      -        }
      -        return foundschema;
      -      }
      -    }
      -  })(path.split('.'), schema)
      -}

      Parameters:


      Query#_castFields(fields)

      Casts selected field arguments for field selection with mongo 2.2

      show code
      Query.prototype._castFields = function _castFields (fields) {
      -  var selected
      -    , elemMatchKeys
      -    , keys
      -    , key
      -    , out
      -    , i
      -
      -  if (fields) {
      -    keys = Object.keys(fields);
      -    elemMatchKeys = [];
      -    i = keys.length;
      -
      -    // collect $elemMatch args
      -    while (i--) {
      -      key = keys[i];
      -      if (fields[key].$elemMatch) {
      -        selected || (selected = {});
      -        selected[key] = fields[key];
      -        elemMatchKeys.push(key);
      -      }
      -    }
      -  }
      -
      -  if (selected) {
      -    // they passed $elemMatch, cast em
      -    try {
      -      out = this.cast(this.model, selected);
      -    } catch (err) {
      -      return err;
      -    }
      -
      -    // apply the casted field args
      -    i = elemMatchKeys.length;
      -    while (i--) {
      -      key = elemMatchKeys[i];
      -      fields[key] = out[key];
      -    }
      -  }
      -
      -  return fields;
      -}

      Parameters:

      query.select({ ids: { $elemMatch: { $in: [hexString] }})

      Query#remove(callback)

      Executes this query as a remove() operation.

      show code
      Query.prototype.remove = function (callback) {
      -  this.op = 'remove';
      -
      -  var model = this.model
      -    , options = this._optionsForExec(model)
      -    , cb = 'function' == typeof callback
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    if (cb) return callback(err);
      -    throw err;
      -  }
      -
      -  if (!cb) {
      -    delete options.safe;
      -  }
      -
      -  var castQuery = this._conditions;
      -  model.collection.remove(castQuery, options, tick(callback));
      -  return this;
      -};

      Parameters:

      Example

      - -
      Cassette.where('artist').equals('Anne Murray').remove(callback)

      Query#findOneAndUpdate([query], [doc], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
      -  this.op = 'findOneAndUpdate';
      -
      -  switch (arguments.length) {
      -    case 3:
      -      if ('function' == typeof options)
      -        callback = options, options = {};
      -      break;
      -    case 2:
      -      if ('function' == typeof doc) {
      -        callback = doc;
      -        doc = query;
      -        query = undefined;
      -      }
      -      options = undefined;
      -      break;
      -    case 1:
      -      if ('function' == typeof query) {
      -        callback = query;
      -        query = options = doc = undefined;
      -      } else {
      -        doc = query;
      -        query = options = undefined;
      -      }
      -  }
      -
      -  // apply query
      -  if (query) {
      -    if ('Object' === query.constructor.name) {
      -      merge(this._conditions, query);
      -    } else if (query instanceof Query) {
      -      merge(this._conditions, query._conditions);
      -    } else if (query instanceof Document) {
      -      merge(this._conditions, query.toObject());
      -    }
      -  }
      -
      -  // apply doc
      -  if (doc) {
      -    merge(this._updateArg, doc);
      -  }
      -
      -  // apply options
      -  options && this.setOptions(options);
      -
      -  if (!callback) return this;
      -
      -  return this._findAndModify('update', callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Available options

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      - -

      Examples

      - -
      query.findOneAndUpdate(conditions, update, options, callback) // executes
      -query.findOneAndUpdate(conditions, update, options)  // returns Query
      -query.findOneAndUpdate(conditions, update, callback) // executes
      -query.findOneAndUpdate(conditions, update)           // returns Query
      -query.findOneAndUpdate(callback)                     // executes
      -query.findOneAndUpdate()                             // returns Query

      Query#findOneAndRemove([conditions], [options], [callback])

      Issues a mongodb findAndModify remove command.

      show code
      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
      -  this.op = 'findOneAndRemove';
      -
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = undefined;
      -  } else if ('function' == typeof conditions) {
      -    callback = conditions;
      -    conditions = undefined;
      -  }
      -
      -  // apply conditions
      -  if (conditions) {
      -    if ('Object' === conditions.constructor.name) {
      -      merge(this._conditions, conditions);
      -    } else if (conditions instanceof Query) {
      -      merge(this._conditions, conditions._conditions);
      -    } else if (conditions instanceof Document) {
      -      merge(this._conditions, conditions.toObject());
      -    }
      -  }
      -
      -  // apply options
      -  options && this.setOptions(options);
      -
      -  if (!callback) return this;
      -
      -  return this._findAndModify('remove', callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

      - -

      Available options

      - -
        -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      - -

      Examples

      - -
      A.where().findOneAndRemove(conditions, options, callback) // executes
      -A.where().findOneAndRemove(conditions, options)  // return Query
      -A.where().findOneAndRemove(conditions, callback) // executes
      -A.where().findOneAndRemove(conditions) // returns Query
      -A.where().findOneAndRemove(callback)   // executes
      -A.where().findOneAndRemove()           // returns Query

      Query#_findAndModify(type, callback)

      _findAndModify

      show code
      Query.prototype._findAndModify = function (type, callback) {
      -  var model = this.model
      -    , promise = new Promise(callback)
      -    , self = this
      -    , castedQuery
      -    , castedDoc
      -    , fields
      -    , sort
      -    , opts
      -
      -  castedQuery = castQuery(this);
      -  if (castedQuery instanceof Error) {
      -    process.nextTick(promise.error.bind(promise, castedQuery));
      -    return promise;
      -  }
      -
      -  opts = this._optionsForExec(model);
      -
      -  if ('remove' == type) {
      -    opts.remove = true;
      -  } else {
      -    if (!('new' in opts)) opts.new = true;
      -    if (!('upsert' in opts)) opts.upsert = false;
      -
      -    castedDoc = castDoc(this);
      -    if (!castedDoc) {
      -      if (opts.upsert) {
      -        // still need to do the upsert to empty doc
      -        castedDoc = { $set: {} };
      -      } else {
      -        return this.findOne(callback);
      -      }
      -    } else if (castedDoc instanceof Error) {
      -      process.nextTick(promise.error.bind(promise, castedDoc));
      -      return promise;
      -    }
      -  }
      -
      -  this._applyPaths();
      -
      -  if (this._fields) {
      -    fields = utils.clone(this._fields)
      -    opts.fields = this._castFields(fields);
      -    if (opts.fields instanceof Error) {
      -      process.nextTick(promise.error.bind(promise, opts.fields));
      -      return promise;
      -    }
      -  }
      -
      -  // the driver needs a default
      -  sort = opts.sort || [];
      -
      -  model
      -  .collection
      -  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
      -    if (err) return promise.error(err);
      -    if (!doc) return promise.complete(null);
      -
      -    if (true === opts.lean) {
      -      return promise.complete(doc);
      -    }
      -
      -    var casted = new model(undefined, fields, true);
      -    casted.init(doc, self, function (err) {
      -      if (err) return promise.error(err);
      -      promise.complete(casted);
      -    });
      -  }));
      -
      -  return promise;
      -}

      Parameters:


      Query#populate(path, [fields], [model], [conditions], [options])

      Specifies paths which should be populated with other documents.

      show code
      Query.prototype.populate = function (path, fields, model, conditions, options) {
      -  if ('string' !== typeof model) {
      -    options = conditions;
      -    conditions = model;
      -    model = undefined;
      -  }
      -  // The order of fields/conditions args is opposite Model.find but
      -  // necessary to keep backward compatibility (fields could be
      -  // an array, string, or object literal).
      -  this.options.populate[path] =
      -    new PopulateOptions(fields, conditions, options, model);
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

      - -

      Example:

      - -
      Kitten.findOne().populate('owner').exec(function (err, kitten) {
      -  console.log(kitten.owner.name) // Max
      -})

      Query#stream()

      Returns a stream interface

      show code
      Query.prototype.stream = function stream () {
      -  return new QueryStream(this);
      -}
      -
      -// helpers

      Returns:

      Example

      - -
      // follows the nodejs stream api
      -Thing.find({ name: /^hello/ }).stream().pipe(res)
      -
      -// manual streaming
      -var stream = Thing.find({ name: /^hello/ }).stream();
      -
      -stream.on('data', function (doc) {
      -  // do something with the mongoose document
      -}).on('error', function (err) {
      -  // handle the error
      -}).on('close', function () {
      -  // the stream is closed
      -});

      Query#within

      Syntax sugar for expressive queries.

      - -

      Example

      - -
      query.within.box()
      -query.within.center()

      Returns:


    • querystream.js

      QueryStream(query)

      Provides a ReadStream interface for Queries.

      show code
      function QueryStream (query) {
      -  Stream.call(this);
      -
      -  this.query = query;
      -  this.readable = true;
      -  this.paused = false;
      -  this._cursor = null;
      -  this._destroyed = null;
      -  this._fields = null;
      -  this._buffer = null;
      -  this._inline = T_INIT;
      -  this._running = false;
      -
      -  // give time to hook up events
      -  var self = this;
      -  process.nextTick(function () {
      -    self._init();
      -  });
      -}

      Parameters:

      Inherits:

      Events:

      • data: emits a single Mongoose document

      • error: emits when an error occurs during streaming. This will emit before the close event.

      • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

      var stream = Model.find().stream();
      -
      -stream.on('data', function (doc) {
      -  // do something with the mongoose document
      -}).on('error', function (err) {
      -  // handle the error
      -}).on('close', function () {
      -  // the stream is closed
      -});
      - -

      The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

      - -
      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

      QueryStream#_init()

      Initializes the query.

      show code
      QueryStream.prototype._init = function () {
      -  if (this._destroyed) return;
      -
      -  var query = this.query
      -    , model = query.model
      -    , options = query._optionsForExec(model)
      -    , self = this
      -
      -  try {
      -    query.cast(model);
      -  } catch (err) {
      -    return self.destroy(err);
      -  }
      -
      -  self._fields = utils.clone(query._fields);
      -  options.fields = query._castFields(self._fields);
      -
      -  model.collection.find(query._conditions, options, function (err, cursor) {
      -    if (err) return self.destroy(err);
      -    self._cursor = cursor;
      -    self._next();
      -  });
      -}

      QueryStream#_next()

      Trampoline for pulling the next doc from cursor.

      show code
      QueryStream.prototype._next = function _next () {
      -  if (this.paused || this._destroyed) {
      -    return this._running = false;
      -  }
      -
      -  this._running = true;
      -
      -  if (this._buffer && this._buffer.length) {
      -    var arg;
      -    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
      -      this._onNextObject.apply(this, arg);
      -    }
      -  }
      -
      -  // avoid stack overflows with large result sets.
      -  // trampoline instead of recursion.
      -  while (this.__next()) {}
      -}

      QueryStream#__next()

      Pulls the next doc from the cursor.

      show code
      QueryStream.prototype.__next = function () {
      -  if (this.paused || this._destroyed)
      -    return this._running = false;
      -
      -  var self = this;
      -  self._inline = T_INIT;
      -
      -  self._cursor.nextObject(function cursorcb (err, doc) {
      -    self._onNextObject(err, doc);
      -  });
      -
      -  // if onNextObject() was already called in this tick
      -  // return ourselves to the trampoline.
      -  if (T_CONT === this._inline) {
      -    return true;
      -  } else {
      -    // onNextObject() hasn't fired yet. tell onNextObject
      -    // that its ok to call _next b/c we are not within
      -    // the trampoline anymore.
      -    this._inline = T_IDLE;
      -  }
      -}

      QueryStream#_onNextObject(err, doc)

      Transforms raw docs returned from the cursor into a model instance.

      show code
      QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
      -  if (this._destroyed) return;
      -
      -  if (this.paused) {
      -    this._buffer || (this._buffer = []);
      -    this._buffer.push([err, doc]);
      -    return this._running = false;
      -  }
      -
      -  if (err) return this.destroy(err);
      -
      -  // when doc is null we hit the end of the cursor
      -  if (!doc) {
      -    this.emit('end');
      -    return this.destroy();
      -  }
      -
      -  if (this.query.options && true === this.query.options.lean)  {
      -    this.emit('data', doc);
      -
      -    // trampoline management
      -    if (T_IDLE === this._inline) {
      -      // no longer in trampoline. restart it.
      -      this._next();
      -    } else {
      -      // in a trampoline. tell __next that its
      -      // ok to continue jumping.
      -      this._inline = T_CONT;
      -    }
      -    return;
      -  }
      -
      -  var instance = new this.query.model(undefined, this._fields, true);
      -
      -  var self = this;
      -  instance.init(doc, this.query, function (err) {
      -    if (err) return self.destroy(err);
      -    self.emit('data', instance);
      -
      -    // trampoline management
      -    if (T_IDLE === self._inline) {
      -      // no longer in trampoline. restart it.
      -      self._next();
      -    } else
      -      // in a trampoline. tell __next that its
      -      // ok to continue jumping.
      -      self._inline = T_CONT;
      -  });
      -}

      Parameters:


      QueryStream#pause()

      Pauses this stream.

      show code
      QueryStream.prototype.pause = function () {
      -  this.paused = true;
      -}

      QueryStream#resume()

      Resumes this stream.

      show code
      QueryStream.prototype.resume = function () {
      -  this.paused = false;
      -
      -  if (!this._cursor) {
      -    // cannot start if not initialized
      -    return;
      -  }
      -
      -  // are we within the trampoline?
      -  if (T_INIT === this._inline) {
      -    return;
      -  }
      -
      -  if (!this._running) {
      -    // outside QueryStream control, need manual restart
      -    return this._next();
      -  }
      -}

      QueryStream#destroy([err])

      Destroys the stream, closing the underlying cursor. No more events will be emitted.

      show code
      QueryStream.prototype.destroy = function (err) {
      -  if (this._destroyed) return;
      -  this._destroyed = true;
      -  this._running = false;
      -  this.readable = false;
      -
      -  if (this._cursor) {
      -    this._cursor.close();
      -  }
      -
      -  if (err) {
      -    this.emit('error', err);
      -  }
      -
      -  this.emit('close');
      -}

      Parameters:


      QueryStream#pipe()

      Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

      See:

      Example:

      - -
      query.stream().pipe(writeStream [, options])
      - -

      This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      - -
      var format = new ArrayFormatter;
      -Events.find().stream().pipe(format).pipe(res);
      - -

      As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


      QueryStream#paused

      Flag stating whether or not this stream is paused.


      QueryStream#readable

      Flag stating whether or not this stream is readable.


    • schema/array.js

      SchemaArray(key, cast, options)

      Array SchemaType constructor

      show code
      function SchemaArray (key, cast, options) {
      -  if (cast) {
      -    var castOptions = {};
      -
      -    if ('Object' === cast.constructor.name) {
      -      if (cast.type) {
      -        // support { type: Woot }
      -        castOptions = cast;
      -        cast = cast.type;
      -        delete castOptions.type;
      -      } else {
      -        cast = Mixed;
      -      }
      -    }
      -
      -    var caster = cast.name in Types ? Types[cast.name] : cast;
      -    this.casterConstructor = caster;
      -    this.caster = new caster(null, castOptions);
      -  }
      -
      -  SchemaType.call(this, key, options);
      -
      -  var self = this
      -    , defaultArr
      -    , fn;
      -
      -  if (this.defaultValue) {
      -    defaultArr = this.defaultValue;
      -    fn = 'function' == typeof defaultArr;
      -  }
      -
      -  this.default(function(){
      -    var arr = fn ? defaultArr() : defaultArr || [];
      -    return new MongooseArray(arr, self.path, this);
      -  });
      -};

      Parameters:

      Inherits:


      SchemaArray#checkRequired(value)

      Check required

      show code
      SchemaArray.prototype.checkRequired = function (value) {
      -  return !!(value && value.length);
      -};

      Parameters:


      SchemaArray#applyGetters(value, scope)

      Overrides the getters application for the population special-case

      show code
      SchemaArray.prototype.applyGetters = function (value, scope) {
      -  if (this.caster.options && this.caster.options.ref) {
      -    // means the object id was populated
      -    return value;
      -  }
      -
      -  return SchemaType.prototype.applyGetters.call(this, value, scope);
      -};

      Parameters:


      SchemaArray#cast(value, doc, init)

      Casts contents

      show code
      SchemaArray.prototype.cast = function (value, doc, init) {
      -  if (Array.isArray(value)) {
      -    if (!(value instanceof MongooseArray)) {
      -      value = new MongooseArray(value, this.path, doc);
      -    }
      -
      -    if (this.caster) {
      -      try {
      -        for (var i = 0, l = value.length; i < l; i++) {
      -          value[i] = this.caster.cast(value[i], doc, init);
      -        }
      -      } catch (e) {
      -        // rethrow
      -        throw new CastError(e.type, value);
      -      }
      -    }
      -
      -    return value;
      -  } else {
      -    return this.cast([value], doc, init);
      -  }
      -};

      Parameters:

      • value <Object>
      • doc <Document> document that triggers the casting
      • init <Boolean> whether this is an initialization cast

      SchemaArray#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaArray.prototype.castForQuery = function ($conditional, value) {
      -  var handler
      -    , val;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with Array.");
      -    val = handler.call(this, value);
      -  } else {
      -    val = $conditional;
      -    var proto = this.casterConstructor.prototype;
      -    var method = proto.castForQuery || proto.cast;
      -    if (Array.isArray(val)) {
      -      val = val.map(function (v) {
      -        if (method) v = method.call(proto, v);
      -        return isMongooseObject(v)
      -          ? v.toObject()
      -          : v;
      -      });
      -    } else if (method) {
      -      val = method.call(proto, val);
      -    }
      -  }
      -  return val && isMongooseObject(val)
      -    ? val.toObject()
      -    : val;
      -};

      Parameters:


    • schema/boolean.js

      SchemaBoolean(path, options)

      Boolean SchemaType constructor.

      show code
      function SchemaBoolean (path, options) {
      -  SchemaType.call(this, path, options);
      -};

      Parameters:

      Inherits:


      SchemaBoolean#checkRequired()

      Required validator

      show code
      SchemaBoolean.prototype.checkRequired = function (value) {
      -  return value === true || value === false;
      -};

      SchemaBoolean#cast(value)

      Casts to boolean

      show code
      SchemaBoolean.prototype.cast = function (value) {
      -  if (value === null) return value;
      -  if (value === '0') return false;
      -  return !!value;
      -};

      Parameters:


      SchemaBoolean#castForQuery($conditional, val)

      Casts contents for queries.

      show code
      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (2 === arguments.length) {
      -    handler = SchemaBoolean.$conditionalHandlers[$conditional];
      -
      -    if (handler) {
      -      return handler.call(this, val);
      -    }
      -
      -    return this.cast(val);
      -  }
      -
      -  return this.cast($conditional);
      -};

      Parameters:


    • schema/buffer.js

      SchemaBuffer(key, cast)

      Buffer SchemaType constructor

      show code
      function SchemaBuffer (key, options) {
      -  SchemaType.call(this, key, options, 'Buffer');
      -};

      Parameters:

      Inherits:


      SchemaBuffer#checkRequired()

      Check required

      show code
      SchemaBuffer.prototype.checkRequired = function (value) {
      -  return !!(value && value.length);
      -};

      SchemaBuffer#cast(value, doc, init)

      Casts contents

      show code
      SchemaBuffer.prototype.cast = function (value, doc, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  if (Buffer.isBuffer(value)) {
      -    if (!(value instanceof MongooseBuffer)) {
      -      value = new MongooseBuffer(value, [this.path, doc]);
      -    }
      -
      -    return value;
      -  } else if (value instanceof Binary) {
      -    return new MongooseBuffer(value.value(true), [this.path, doc]);
      -  }
      -
      -  if ('string' === typeof value || Array.isArray(value)) {
      -    return new MongooseBuffer(value, [this.path, doc]);
      -  }
      -
      -  throw new CastError('buffer', value);
      -};

      Parameters:


      SchemaBuffer#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with Buffer.");
      -    return handler.call(this, val);
      -  } else {
      -    val = $conditional;
      -    return this.cast(val).toObject();
      -  }
      -};

      Parameters:


    • schema/date.js

      SchemaDate(key, options)

      Date SchemaType constructor.

      show code
      function SchemaDate (key, options) {
      -  SchemaType.call(this, key, options);
      -};

      Parameters:

      Inherits:


      SchemaDate#checkRequired()

      Required validator for date

      show code
      SchemaDate.prototype.checkRequired = function (value) {
      -  return value instanceof Date;
      -};

      SchemaDate#cast(value)

      Casts to date

      show code
      SchemaDate.prototype.cast = function (value) {
      -  if (value === null || value === '')
      -    return null;
      -
      -  if (value instanceof Date)
      -    return value;
      -
      -  var date;
      -
      -  // support for timestamps
      -  if (value instanceof Number || 'number' == typeof value 
      -      || String(value) == Number(value))
      -    date = new Date(Number(value));
      -
      -  // support for date strings
      -  else if (value.toString)
      -    date = new Date(value.toString());
      -
      -  if (date.toString() != 'Invalid Date')
      -    return date;
      -
      -  throw new CastError('date', value);
      -};

      Parameters:


      SchemaDate#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaDate.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -
      -  if (2 !== arguments.length) {
      -    return this.cast($conditional);
      -  }
      -
      -  handler = this.$conditionalHandlers[$conditional];
      -
      -  if (!handler) {
      -    throw new Error("Can't use " + $conditional + " with Date.");
      -  }
      -
      -  return handler.call(this, val);
      -};

      Parameters:


    • schema/documentarray.js

      DocumentArray(key, schema, options)

      SubdocsArray SchemaType constructor

      show code
      function DocumentArray (key, schema, options) {
      -
      -  // compile an embedded document for this schema
      -  function EmbeddedDocument () {
      -    Subdocument.apply(this, arguments);
      -  }
      -
      -  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
      -  EmbeddedDocument.prototype._setSchema(schema);
      -  EmbeddedDocument.schema = schema;
      -
      -  // apply methods
      -  for (var i in schema.methods) {
      -    EmbeddedDocument.prototype[i] = schema.methods[i];
      -  }
      -
      -  // apply statics
      -  for (var i in schema.statics)
      -    EmbeddedDocument[i] = schema.statics[i];
      -
      -  EmbeddedDocument.options = options;
      -  this.schema = schema;
      -
      -  ArrayType.call(this, key, EmbeddedDocument, options);
      -
      -  this.schema = schema;
      -  var path = this.path;
      -  var fn = this.defaultValue;
      -
      -  this.default(function(){
      -    var arr = fn.call(this);
      -    if (!Array.isArray(arr)) arr = [arr];
      -    return new MongooseDocumentArray(arr, path, this);
      -  });
      -};

      Parameters:

      Inherits:


      DocumentArray#doValidate()

      Performs local validations first, then validations on each embedded doc

      show code
      DocumentArray.prototype.doValidate = function (array, fn, scope) {
      -  var self = this;
      -
      -  SchemaType.prototype.doValidate.call(this, array, function (err) {
      -    if (err) return fn(err);
      -
      -    var count = array && array.length
      -      , error;
      -
      -    if (!count) return fn();
      -
      -    // handle sparse arrays, do not use array.forEach which does not
      -    // iterate over sparse elements yet reports array.length including
      -    // them :(
      -
      -    for (var i = 0, len = count; i < len; ++i) {
      -      // sidestep sparse entries
      -      var doc = array[i];
      -      if (!doc) {
      -        --count || fn();
      -        continue;
      -      }
      -
      -      ;(function (i) {
      -        doc.validate(function (err) {
      -          if (err && !error) {
      -            // rewrite the key
      -            err.key = self.key + '.' + i + '.' + err.key;
      -            return fn(error = err);
      -          }
      -          --count || fn();
      -        });
      -      })(i);
      -    }
      -  }, scope);
      -};

      DocumentArray#cast(value, document)

      Casts contents

      show code
      DocumentArray.prototype.cast = function (value, doc, init, prev) {
      -  var selected
      -    , subdoc
      -    , i
      -
      -  if (!Array.isArray(value)) {
      -    return this.cast([value], doc, init, prev);
      -  }
      -
      -  if (!(value instanceof MongooseDocumentArray)) {
      -    value = new MongooseDocumentArray(value, this.path, doc);
      -  }
      -
      -  i = value.length;
      -
      -  while (i--) {
      -    if (!(value[i] instanceof Subdocument) && value[i]) {
      -      if (init) {
      -        selected || (selected = scopePaths(this, doc._selected, init));
      -        subdoc = new this.casterConstructor(null, value, true, selected);
      -        value[i] = subdoc.init(value[i]);
      -      } else {
      -        if (prev && (subdoc = prev.id(value[i]._id))) {
      -          // handle resetting doc with existing id but differing data
      -          // doc.array = [{ doc: 'val' }]
      -          subdoc.set(value[i]);
      -        } else {
      -          subdoc = new this.casterConstructor(value[i], value);
      -        }
      -
      -        // if set() is hooked it will have no return value
      -        // see gh-746
      -        value[i] = subdoc;
      -      }
      -    }
      -  }
      -
      -  return value;
      -}

      Parameters:


    • schema/mixed.js

      Mixed(path, options)

      Mixed SchemaType constructor.

      show code
      function Mixed (path, options) {
      -  // make sure empty array defaults are handled
      -  if (options &&
      -      options.default &&
      -      Array.isArray(options.default) &&
      -      0 === options.default.length) {
      -    options.default = Array;
      -  }
      -
      -  SchemaType.call(this, path, options);
      -};

      Parameters:

      Inherits:


      Mixed#checkRequired()

      Required validator

      show code
      Mixed.prototype.checkRequired = function (val) {
      -  return true;
      -};

      Mixed#cast(value)

      Casts val for Mixed.

      show code
      Mixed.prototype.cast = function (val) {
      -  return val;
      -};

      Parameters:

      this is a no-op


      Mixed#castForQuery($cond, [val])

      Casts contents for queries.

      show code
      Mixed.prototype.castForQuery = function ($cond, val) {
      -  if (arguments.length === 2) return val;
      -  return $cond;
      -};

      Parameters:


    • schema/number.js

      SchemaNumber(key, options)

      Number SchemaType constructor.

      show code
      function SchemaNumber (key, options) {
      -  SchemaType.call(this, key, options, 'Number');
      -};

      Parameters:

      Inherits:


      SchemaNumber#checkRequired()

      Required validator for number

      show code
      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return typeof value == 'number' || value instanceof Number;
      -  }
      -};

      SchemaNumber#min(value, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.min = function (value, message) {
      -  if (this.minValidator)
      -    this.validators = this.validators.filter(function(v){
      -      return v[1] != 'min';
      -    });
      -  if (value != null)
      -    this.validators.push([function(v){
      -      return v === null || v >= value;
      -    }, 'min']);
      -  return this;
      -};

      Parameters:

      Example:

      - -
      var s = new Schema({ n: { type: Number, min: 10 })
      -var M = db.model('M', s)
      -var m = new M({ n: 9 })
      -m.save(function (err) {
      -  console.error(err) // validator error
      -  m.n = 10;
      -  m.save() // success
      -})

      SchemaNumber#max(maximum, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.max = function (value, message) {
      -  if (this.maxValidator)
      -    this.validators = this.validators.filter(function(v){
      -      return v[1] != 'max';
      -    });
      -  if (value != null)
      -    this.validators.push([this.maxValidator = function(v){
      -      return v === null || v <= value;
      -    }, 'max']);
      -  return this;
      -};

      Parameters:

      Example:

      - -
      var s = new Schema({ n: { type: Number, max: 10 })
      -var M = db.model('M', s)
      -var m = new M({ n: 11 })
      -m.save(function (err) {
      -  console.error(err) // validator error
      -  m.n = 10;
      -  m.save() // success
      -})

      SchemaNumber#cast(value, doc, init)

      Casts to number

      show code
      SchemaNumber.prototype.cast = function (value, doc, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  if (!isNaN(value)){
      -    if (null === value) return value;
      -    if ('' === value) return null;
      -    if ('string' == typeof value) value = Number(value);
      -    if (value instanceof Number) return value
      -    if ('number' == typeof value) return value;
      -    if (value.toString && !Array.isArray(value) &&
      -        value.toString() == Number(value)) {
      -      return new Number(value)
      -    }
      -  }
      -
      -  throw new CastError('number', value);
      -};

      Parameters:


      SchemaNumber#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with Number.");
      -    return handler.call(this, val);
      -  } else {
      -    val = this.cast($conditional);
      -    return val == null ? val : val
      -  }
      -};

      Parameters:


    • schema/objectid.js

      ObjectId(key, options)

      ObjectId SchemaType constructor.

      show code
      function ObjectId (key, options) {
      -  SchemaType.call(this, key, options, 'ObjectID');
      -};

      Parameters:

      Inherits:


      ObjectId#checkRequired()

      Check required

      show code
      ObjectId.prototype.checkRequired = function checkRequired (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return value instanceof oid;
      -  }
      -};

      ObjectId#cast(value, scope, init)

      Casts to ObjectId

      show code
      ObjectId.prototype.cast = function (value, scope, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  if (value === null) return value;
      -
      -  if (value instanceof oid)
      -    return value;
      -
      -  if (value._id && value._id instanceof oid)
      -    return value._id;
      -
      -  if (value.toString)
      -    return oid.fromString(value.toString());
      -
      -  throw new CastError('object id', value);
      -};

      Parameters:


      ObjectId#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      ObjectId.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with ObjectId.");
      -    return handler.call(this, val);
      -  } else {
      -    return this.cast($conditional);
      -  }
      -};

      Parameters:


      ObjectId#auto(turnOn)

      Adds an auto-generated ObjectId default if turnOn is true.

      show code
      ObjectId.prototype.auto = function (turnOn) {
      -  if (turnOn) {
      -    this.default(defaultId);
      -    this.set(resetId)
      -  }
      -};

      Parameters:

      • turnOn <Boolean> auto generated ObjectId defaults

    • schema/string.js

      SchemaString(key, options)

      String SchemaType constructor.

      show code
      function SchemaString (key, options) {
      -  this.enumValues = [];
      -  this.regExp = null;
      -  SchemaType.call(this, key, options, 'String');
      -};

      Parameters:

      Inherits:


      SchemaString#enum([args...])

      Adds enumeration values and a coinciding validator.

      show code
      SchemaString.prototype.enum = function () {
      -  var len = arguments.length;
      -  if (!len || undefined === arguments[0] || false === arguments[0]) {
      -    if (this.enumValidator){
      -      this.enumValidator = false;
      -      this.validators = this.validators.filter(function(v){
      -        return v[1] != 'enum';
      -      });
      -    }
      -    return;
      -  }
      -
      -  for (var i = 0; i < len; i++) {
      -    if (undefined !== arguments[i]) {
      -      this.enumValues.push(this.cast(arguments[i]));
      -    }
      -  }
      -
      -  if (!this.enumValidator) {
      -    var values = this.enumValues;
      -    this.enumValidator = function(v){
      -      return undefined === v || ~values.indexOf(v);
      -    };
      -    this.validators.push([this.enumValidator, 'enum']);
      -  }
      -};

      Parameters:

      • [args...] <String> enumeration values

      Example:

      - -
      var states = 'opening open closing closed'.split(' ')
      -var s = new Schema({ state: { type: String, enum: states })
      -var M = db.model('M', s)
      -var m = new M({ state: 'invalid' })
      -m.save(function (err) {
      -  console.error(err) // validator error
      -  m.state = 'open'
      -  m.save() // success
      -})

      SchemaString#lowercase()

      Adds a lowercase setter.

      show code
      SchemaString.prototype.lowercase = function () {
      -  return this.set(function (v, self) {
      -    if ('string' != typeof v) v = self.cast(v)
      -    if (v) return v.toLowerCase();
      -    return v;
      -  });
      -};

      Example:

      - -
      var s = new Schema({ email: { type: String, lowercase: true }})
      -var M = db.model('M', s);
      -var m = new M({ email: 'SomeEmail@example.COM' });
      -console.log(m.email) // someemail@example.com
      -

      SchemaString#uppercase()

      Adds an uppercase setter.

      show code
      SchemaString.prototype.uppercase = function () {
      -  return this.set(function (v, self) {
      -    if ('string' != typeof v) v = self.cast(v)
      -    if (v) return v.toUpperCase();
      -    return v;
      -  });
      -};

      Example:

      - -
      var s = new Schema({ caps: { type: String, uppercase: true }})
      -var M = db.model('M', s);
      -var m = new M({ caps: 'an example' });
      -console.log(m.caps) // AN EXAMPLE

      SchemaString#trim()

      Adds a trim setter.

      show code
      SchemaString.prototype.trim = function () {
      -  return this.set(function (v, self) {
      -    if ('string' != typeof v) v = self.cast(v)
      -    if (v) return v.trim();
      -    return v;
      -  });
      -};

      The string value will be trimmed when set.

      - -

      Example:

      - -
      var s = new Schema({ name: { type: String, trim: true }})
      -var M = db.model('M', s)
      -var string = ' some name '
      -console.log(string.length) // 11
      -var m = new M({ name: string })
      -console.log(m.name.length) // 9

      SchemaString#match(regExp)

      Sets a regexp validator.

      show code
      SchemaString.prototype.match = function match (regExp) {
      -  this.validators.push([function(v){
      -    return null != v && '' !== v
      -      ? regExp.test(v)
      -      : true
      -  }, 'regexp']);
      -};

      Parameters:

      • regExp <RegExp> regular expression to test against

      Any value that does not pass regExp.test(val) will fail validation.

      - -

      Example:

      - -
      var s = new Schema({ name: { type: String, match: /^a/ }})
      -var M = db.model('M', s)
      -var m = new M({ name: 'invalid' })
      -m.validate(function (err) {
      -  console.error(err) // validation error
      -  m.name = 'apples'
      -  m.validate(function (err) {
      -    assert.ok(err) // success
      -  })
      -})

      SchemaString#checkRequired(value)

      Check required

      show code
      SchemaString.prototype.checkRequired = function checkRequired (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return (value instanceof String || typeof value == 'string') && value.length;
      -  }
      -};

      Parameters:


      SchemaString#cast()

      Casts to String

      show code
      SchemaString.prototype.cast = function (value, scope, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -  if (value === null) return value;
      -  if ('undefined' !== typeof value && value.toString) return value.toString();
      -  throw new CastError('string', value);
      -};

      SchemaString#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      SchemaString.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with String.");
      -    return handler.call(this, val);
      -  } else {
      -    val = $conditional;
      -    if (val instanceof RegExp) return val;
      -    return this.cast(val);
      -  }
      -};

      Parameters:


    • schema.js

      Schema(definition)

      Schema constructor.

      show code
      function Schema (obj, options) {
      -  if (!(this instanceof Schema))
      -    return new Schema(obj, options);
      -
      -  this.paths = {};
      -  this.subpaths = {};
      -  this.virtuals = {};
      -  this.nested = {};
      -  this.inherits = {};
      -  this.callQueue = [];
      -  this._indexes = [];
      -  this.methods = {};
      -  this.statics = {};
      -  this.tree = {};
      -  this._requiredpaths = undefined;
      -
      -  this.options = this.defaultOptions(options);
      -
      -  // build paths
      -  if (obj) {
      -    this.add(obj);
      -  }
      -
      -  // ensure the documents get an auto _id unless disabled
      -  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
      -  if (auto_id) {
      -    this.add({ _id: {type: Schema.ObjectId, auto: true} });
      -  }
      -
      -  // ensure the documents receive an id getter unless disabled
      -  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
      -  if (autoid) {
      -    this.virtual('id').get(idGetter);
      -  }
      -
      -  // versioning not directly added to schema b/c we only want
      -  // it in the top level document, not embedded ones.
      -};

      Parameters:

      Events:

      • init: Emitted after the schema is compiled into a Model.

      Example:

      - -
      var child = new Schema({ name: String });
      -var schema = new Schema({ name: String, age: Number, children: [child] });
      -var Tree = mongoose.model('Tree', schema);
      -
      -// setting schema options
      -new Schema({ name: String }, { _id: false, autoIndex: false })
      - -

      Options:

      - -
        -
      • autoIndex: bool - defaults to true
      • -
      • capped: bool - defaults to false
      • -
      • collection: string - no default
      • -
      • id: bool - defaults to true
      • -
      • _id: bool - defaults to true
      • -
      • read: string
      • -
      • safe: bool - defaults to true.
      • -
      • shardKey: bool - defaults to null
      • -
      • strict: bool - defaults to true
      • -
      • toJSON - object - no default
      • -
      • toObject - object - no default
      • -
      • versionKey: bool - defaults to "__v"
      • -
      • minimize: bool - controls document#toObject behavior when called manually - defaults to true
      • -
      - -

      Note:

      - -

      When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


      Schema#defaultOptions(options)

      Returns default options for this schema, merged with options.

      show code
      Schema.prototype.defaultOptions = function (options) {
      -  options = utils.options({
      -      safe: true
      -    , strict: true
      -    , capped: false // { size, max, autoIndexId }
      -    , versionKey: '__v'
      -    , minimize: true
      -    , autoIndex: true
      -    , shardKey: null
      -    , read: null
      -    // the following are only applied at construction time
      -    , noId: false // deprecated, use { _id: false }
      -    , _id: true
      -    , noVirtualId: false // deprecated, use { id: false }
      -    , id: true
      -  }, options);
      -
      -  if (options.read)
      -    options.read = utils.readPref(options.read);
      -
      -  return options;
      -}

      Parameters:

      Returns:


      Schema#add(obj, prefix)

      Adds key path / schema type pairs to this schema.

      show code
      Schema.prototype.add = function add (obj, prefix) {
      -  prefix = prefix || '';
      -  for (var i in obj) {
      -    if (null == obj[i]) {
      -      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
      -    }
      -
      -    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
      -      if (Object.keys(obj[i]).length) {
      -        // nested object { last: { name: String }}
      -        this.nested[prefix + i] = true;
      -        this.add(obj[i], prefix + i + '.');
      -      } else {
      -        this.path(prefix + i, obj[i]); // mixed type
      -      }
      -    } else {
      -      this.path(prefix + i, obj[i]);
      -    }
      -  }
      -};

      Parameters:

      Example:

      - -
      var ToySchema = new Schema;
      -ToySchema.add({ name: 'string', color: 'string', price: 'number' });

      Schema#path(path, constructor)

      Gets/sets schema paths.

      show code
      Schema.prototype.path = function (path, obj) {
      -  if (obj == undefined) {
      -    if (this.paths[path]) return this.paths[path];
      -    if (this.subpaths[path]) return this.subpaths[path];
      -
      -    // subpaths?
      -    return /\.\d+\.?$/.test(path)
      -      ? getPositionalPath(this, path)
      -      : undefined;
      -  }
      -
      -  // some path names conflict with document methods
      -  if (reserved[path]) {
      -    throw new Error("`" + path + "` may not be used as a schema pathname");
      -  }
      -
      -  // update the tree
      -  var subpaths = path.split(/\./)
      -    , last = subpaths.pop()
      -    , branch = this.tree;
      -
      -  subpaths.forEach(function(sub, i) {
      -    if (!branch[sub]) branch[sub] = {};
      -    if ('object' != typeof branch[sub]) {
      -      var msg = 'Cannot set nested path `' + path + '`. '
      -              + 'Parent path `'
      -              + subpaths.slice(0, i).concat([sub]).join('.')
      -              + '` already set to type ' + branch[sub].name
      -              + '.';
      -      throw new Error(msg);
      -    }
      -    branch = branch[sub];
      -  });
      -
      -  branch[last] = utils.clone(obj);
      -
      -  this.paths[path] = Schema.interpretAsType(path, obj);
      -  return this;
      -};

      Parameters:

      Sets a path (if arity 2)
      Gets a path (if arity 1)

      - -

      Example

      - -
      schema.path('name') // returns a SchemaType
      -schema.path('name', Number) // changes the schemaType of `name` to Number

      Schema#eachPath(fn)

      Iterates the schemas paths similar to Array#forEach.

      show code
      Schema.prototype.eachPath = function (fn) {
      -  var keys = Object.keys(this.paths)
      -    , len = keys.length;
      -
      -  for (var i = 0; i < len; ++i) {
      -    fn(keys[i], this.paths[keys[i]]);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      The callback is passed the pathname and schemaType as arguments on each iteration.


      Schema#requiredPaths()

      Returns an Array of path strings that are required by this schema.

      show code
      Schema.prototype.requiredPaths = function requiredPaths () {
      -  if (this._requiredpaths) return this._requiredpaths;
      -
      -  var paths = Object.keys(this.paths)
      -    , i = paths.length
      -    , ret = [];
      -
      -  while (i--) {
      -    var path = paths[i];
      -    if (this.paths[path].isRequired) ret.push(path);
      -  }
      -
      -  return this._requiredpaths = ret;
      -}

      Returns:


      Schema#pathType(path)

      Returns the pathType of path for this schema.

      show code
      Schema.prototype.pathType = function (path) {
      -  if (path in this.paths) return 'real';
      -  if (path in this.virtuals) return 'virtual';
      -  if (path in this.nested) return 'nested';
      -  if (path in this.subpaths) return 'real';
      -
      -  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
      -    return 'real';
      -  } else {
      -    return 'adhocOrUndefined'
      -  }
      -};

      Parameters:

      Returns:

      Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


      Schema#queue(name, args)

      Adds a method call to the queue.

      show code
      Schema.prototype.queue = function(name, args){
      -  this.callQueue.push([name, args]);
      -  return this;
      -};

      Parameters:

      • name <String> name of the document method to call later
      • args <Array> arguments to pass to the method

      Schema#pre(method, callback)

      Defines a pre hook for the document.

      show code
      Schema.prototype.pre = function(){
      -  return this.queue('pre', arguments);
      -};

      Parameters:

      Example

      - -
      var toySchema = new Schema(..);
      -
      -toySchema.pre('save', function (next) {
      -  if (!this.created) this.created = new Date;
      -  next();
      -})
      -
      -toySchema.pre('validate', function (next) {
      -  if (this.name != 'Woody') this.name = 'Woody';
      -  next();
      -})

      Schema#post(method, fn)

      Defines a post hook for the document.

      show code
      Schema.prototype.post = function(method, fn){
      -  return this.queue('on', arguments);
      -};

      Parameters:

      Post hooks fire on the event emitted from document instances of Models compiled from this schema.

      - -
      var schema = new Schema(..);
      -schema.post('save', function () {
      -  console.log('this fired after a document was saved');
      -});
      -
      -var Model = mongoose.model('Model', schema);
      -
      -var m = new Model(..);
      -m.save(function (err) {
      -  console.log('this fires after the `post` hook');
      -});

      Schema#plugin(plugin, opts)

      Registers a plugin for this schema.

      show code
      Schema.prototype.plugin = function (fn, opts) {
      -  fn(this, opts);
      -  return this;
      -};

      Parameters:


      Schema#method(method, [fn])

      Adds an instance method to documents constructed from Models compiled from this schema.

      show code
      Schema.prototype.method = function (name, fn) {
      -  if ('string' != typeof name)
      -    for (var i in name)
      -      this.methods[i] = name[i];
      -  else
      -    this.methods[name] = fn;
      -  return this;
      -};

      Parameters:

      Example

      - -
      var schema = kittySchema = new Schema(..);
      -
      -schema.methods.meow = function () {
      -  console.log('meeeeeoooooooooooow');
      -})
      -
      -var Kitty = mongoose.model('Kitty', schema);
      -
      -var fizz = new Kitty;
      -fizz.meow(); // meeeeeooooooooooooow
      - -

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      - -
      schema.method({
      -    purr: function () {}
      -  , scratch: function () {}
      -});
      -
      -// later
      -fizz.purr();
      -fizz.scratch();

      Schema#static(name, fn)

      Adds static "class" methods to Models compiled from this schema.

      show code
      Schema.prototype.static = function(name, fn) {
      -  if ('string' != typeof name)
      -    for (var i in name)
      -      this.statics[i] = name[i];
      -  else
      -    this.statics[name] = fn;
      -  return this;
      -};

      Parameters:

      Example

      - -
      var schema = new Schema(..);
      -schema.static('findByName', function (name, callback) {
      -  return this.find({ name: name }, callback);
      -});
      -
      -var Drink = mongoose.model('Drink', schema);
      -Drink.findByName('sanpellegrino', function (err, drinks) {
      -  //
      -});
      - -

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


      Schema#index(fields, [options])

      Defines an index (most likely compound) for this schema.

      show code
      Schema.prototype.index = function (fields, options) {
      -  options || (options = {});
      -
      -  if (options.expires)
      -    utils.expires(options);
      -
      -  this._indexes.push([fields, options]);
      -  return this;
      -};

      Parameters:

      Example

      - -
      schema.index({ first: 1, last: -1 })

      Schema#set(key, [value])

      Sets/gets a schema option.

      show code
      Schema.prototype.set = function (key, value, tags) {
      -  if (arguments.length == 1)
      -    return this.options[key];
      -
      -  this.options[key] = 'read' == key
      -    ? utils.readPref(value, tags)
      -    : value;
      -
      -  return this;
      -};

      Parameters:

      • key <String> option name
      • [value] <Object> if not passed, the current option value is returned

      Schema#indexes()

      Compiles indexes from fields and schema-level indexes

      show code
      Schema.prototype.indexes = function () {
      -  var indexes = []
      -    , seenSchemas = [];
      -
      -  collectIndexes(this);
      -
      -  return indexes;
      -
      -  function collectIndexes (schema, prefix) {
      -    if (~seenSchemas.indexOf(schema)) return;
      -    seenSchemas.push(schema);
      -
      -    var index;
      -    var paths = schema.paths;
      -    prefix = prefix || '';
      -
      -    for (var i in paths) {
      -      if (paths[i]) {
      -        if (paths[i] instanceof Types.DocumentArray) {
      -          collectIndexes(paths[i].schema, i + '.');
      -        } else {
      -          index = paths[i]._index;
      -
      -          if (index !== false && index !== null){
      -            var field = {};
      -            field[prefix + i] = '2d' === index ? index : 1;
      -            var options = 'Object' === index.constructor.name ? index : {};
      -            if (!('background' in options)) options.background = true;
      -            indexes.push([field, options]);
      -          }
      -        }
      -      }
      -    }
      -
      -    if (prefix) {
      -      fixSubIndexPaths(schema, prefix);
      -    } else {
      -      schema._indexes.forEach(function (index) {
      -        if (!('background' in index[1])) index[1].background = true;
      -      });
      -      indexes = indexes.concat(schema._indexes);
      -    }
      -  }

      Schema#virtual(name, [options])

      Creates a virtual type with the given name.

      show code
      Schema.prototype.virtual = function (name, options) {
      -  var virtuals = this.virtuals;
      -  var parts = name.split('.');
      -  return virtuals[name] = parts.reduce(function (mem, part, i) {
      -    mem[part] || (mem[part] = (i === parts.length-1)
      -                            ? new VirtualType(options, name)
      -                            : {});
      -    return mem[part];
      -  }, this.tree);
      -};

      Parameters:

      Returns:


      Schema#virtualpath(name)

      Returns the virtual type with the given name.

      show code
      Schema.prototype.virtualpath = function (name) {
      -  return this.virtuals[name];
      -};

      Parameters:

      Returns:


      Schema#namedScope()

      These still haven't been fixed. Once they're working we'll make them public again.

      show code
      Schema.prototype.namedScope = function (name, fn) {
      -  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
      -    , newScope = Object.create(namedScopes)
      -    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
      -  allScopes[name] = newScope;
      -  newScope.name = name;
      -  newScope.block = fn;
      -  newScope.query = new Query();
      -  newScope.decorate(namedScopes, {
      -    block0: function (block) {
      -      return function () {
      -        block.call(this.query);
      -        return this;
      -      };
      -    },
      -    blockN: function (block) {
      -      return function () {
      -        block.apply(this.query, arguments);
      -        return this;
      -      };
      -    },
      -    basic: function (query) {
      -      return function () {
      -        this.query.find(query);
      -        return this;
      -      };
      -    }
      -  });
      -  return newScope;
      -};

      Schema.reserved

      Reserved document keys.

      show code
      Schema.reserved = Object.create(null);
      -var reserved = Schema.reserved;
      -reserved.on =
      -reserved.db =
      -reserved.init =
      -reserved.isNew =
      -reserved.errors =
      -reserved.schema =
      -reserved.options =
      -reserved.modelName =
      -reserved.collection = 1;

      Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      - -
      on, db, init, isNew, errors, schema, options, modelName, collection
      - -

      NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

      - -
      var schema = new Schema(..);
      - schema.methods.init = function () {} // potentially breaking

      Schema.interpretAsType(path, obj)

      Converts type arguments into Mongoose Types.

      show code
      Schema.interpretAsType = function (path, obj) {
      -  if (obj.constructor.name != 'Object')
      -    obj = { type: obj };
      -
      -  // Get the type making sure to allow keys named "type"
      -  // and default to mixed if not specified.
      -  // { type: { type: String, default: 'freshcut' } }
      -  var type = obj.type && !obj.type.type
      -    ? obj.type
      -    : {};
      -
      -  if ('Object' == type.constructor.name || 'mixed' == type) {
      -    return new Types.Mixed(path, obj);
      -  }
      -
      -  if (Array.isArray(type) || Array == type || 'array' == type) {
      -    // if it was specified through { type } look for `cast`
      -    var cast = (Array == type || 'array' == type)
      -      ? obj.cast
      -      : type[0];
      -
      -    if (cast instanceof Schema) {
      -      return new Types.DocumentArray(path, cast, obj);
      -    }
      -
      -    if ('string' == typeof cast) {
      -      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
      -    } else if (cast && (!cast.type || cast.type.type)
      -                    && 'Object' == cast.constructor.name
      -                    && Object.keys(cast).length) {
      -      return new Types.DocumentArray(path, new Schema(cast), obj);
      -    }
      -
      -    return new Types.Array(path, cast || Types.Mixed, obj);
      -  }
      -
      -  var name = 'string' == typeof type
      -    ? type
      -    : type.name;
      -
      -  if (name) {
      -    name = name.charAt(0).toUpperCase() + name.substring(1);
      -  }
      -
      -  if (undefined == Types[name]) {
      -    throw new TypeError('Undefined type at `' + path +
      -        '`
      -  Did you try nesting Schemas? ' +
      -        'You can only nest using refs or arrays.');
      -  }
      -
      -  return new Types[name](path, obj);
      -};

      Parameters:


      Schema.Types

      The various Mongoose Schema Types.

      show code
      Schema.Types = require('./schema/index');

      Example:

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -var ObjectId = mongoose.Schema.Types.ObjectId;
      - -

      Types:

      - -
        -
      • String
      • -
      • Number
      • -
      • Boolean | Bool
      • -
      • Array
      • -
      • Buffer
      • -
      • Date
      • -
      • ObjectId | Oid
      • -
      • Mixed
      • -
      - -

      Using this exposed access to the Mixed SchemaType, we can use them in our schema.

      - -
      var Mixed = mongoose.Schema.Types.Mixed;
      -new mongoose.Schema({ _user: Mixed })

      Schema#tree

      Schema as a tree

      - -

      Example:

      - -
      {
      -    '_id'     : ObjectId
      -  , 'nested'  : {
      -        'key' : String
      -    }
      -}

      Schema#paths

      Schema as flat paths

      - -

      Example:

      - -
      {
      -    '_id'        : SchemaType,
      -  , 'nested.key' : SchemaType,
      -}

    • schemadefault.js

      exports#system.profile

      Default model for querying the system.profiles collection.


    • schematype.js

      SchemaType(path, [options], [instance])

      SchemaType constructor

      show code
      function SchemaType (path, options, instance) {
      -  this.path = path;
      -  this.instance = instance;
      -  this.validators = [];
      -  this.setters = [];
      -  this.getters = [];
      -  this.options = options;
      -  this._index = null;
      -  this.selected;
      -
      -  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
      -    // { unique: true, index: true }
      -    if ('index' == i && this._index) continue;
      -
      -    var opts = Array.isArray(options[i])
      -      ? options[i]
      -      : [options[i]];
      -
      -    this[i].apply(this, opts);
      -  }
      -};

      Parameters:


      SchemaType#default(val)

      Sets a default value for this SchemaType.

      show code
      SchemaType.prototype.default = function (val) {
      -  if (1 === arguments.length) {
      -    this.defaultValue = typeof val === 'function'
      -      ? val
      -      : this.cast(val);
      -    return this;
      -  } else if (arguments.length > 1) {
      -    this.defaultValue = utils.args(arguments);
      -  }
      -  return this.defaultValue;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var schema = new Schema({ n: { type: Number, default: 10 })
      -var M = db.model('M', schema)
      -var m = new M;
      -console.log(m.n) // 10
      - -

      Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

      - -

      Example:

      - -
      // values are cast:
      -var schema = new Schema({ aNumber: Number, default: "4.815162342" })
      -var M = db.model('M', schema)
      -var m = new M;
      -console.log(m.aNumber) // 4.815162342
      -
      -// default unique objects for Mixed types:
      -var schema = new Schema({ mixed: Schema.Types.Mixed });
      -schema.path('mixed').default(function () {
      -  return {};
      -});
      -
      -// if we don't use a function to return object literals for Mixed defaults,
      -// each document will receive a reference to the same object literal creating
      -// a "shared" object instance:
      -var schema = new Schema({ mixed: Schema.Types.Mixed });
      -schema.path('mixed').default({});
      -var M = db.model('M', schema);
      -var m1 = new M;
      -m1.mixed.added = 1;
      -console.log(m1.mixed); // { added: 1 }
      -var m2 = new M;
      -console.log(m2.mixed); // { added: 1 }

      SchemaType#index(options)

      Declares the index options for this schematype.

      show code
      SchemaType.prototype.index = function (options) {
      -  this._index = options;
      -  utils.expires(this._index);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var s = new Schema({ name: { type: String, index: true })
      -var s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
      -Schema.path('my.path').index(true);
      -Schema.path('my.date').index({ expires: 60 });
      -Schema.path('my.path').index({ unique: true, sparse: true });
      - -

      NOTE:

      - -

      Indexes are created in the background by default. Specify background: false to override.

      - -

      Direction doesn't matter for single key indexes


      SchemaType#unique(bool)

      Declares an unique index.

      show code
      SchemaType.prototype.unique = function (bool) {
      -  if (!this._index || 'Object' !== this._index.constructor.name) {
      -    this._index = {};
      -  }
      -
      -  this._index.unique = bool;
      -  return this;
      -};

      Parameters:

      Returns:

      Examples:

      - -
      var s = new Schema({ name: { type: String, unique: true })
      -Schema.path('name').index({ unique: true });

      SchemaType#sparse(bool)

      Declares a sparse index.

      show code
      SchemaType.prototype.sparse = function (bool) {
      -  if (!this._index || 'Object' !== this._index.constructor.name) {
      -    this._index = {};
      -  }
      -
      -  this._index.sparse = bool;
      -  return this;
      -};

      Parameters:

      Returns:

      Examples:

      - -
      var s = new Schema({ name: { type: String, sparse: true })
      -Schema.path('name').index({ sparse: true });

      SchemaType#expires(when)

      Declares a TTL index (rounded to the nearest second) for Date types only.

      show code
      SchemaType.prototype.expires = function (when) {
      -  if (!this._index || 'Object' !== this._index.constructor.name) {
      -    this._index = {};
      -  }
      -
      -  this._index.expires = when;
      -  utils.expires(this._index);
      -  return this;
      -};

      Parameters:

      Returns:

      This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
      This index type is only compatible with Date types.

      - -

      Example:

      - -
      // expire in 24 hours
      -new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
      - -

      expires utilizes the ms module from guille allowing us to use a friendlier syntax:

      - -

      Example:

      - -
      // expire in 24 hours
      -new Schema({ createdAt: { type: Date, expires: '24h' }});
      -
      -// expire in 1.5 hours
      -new Schema({ createdAt: { type: Date, expires: '1.5h' }});
      -
      -// expire in 7 days
      -var schema = new Schema({ createdAt: Date });
      -schema.path('createdAt').expires('7d');

      SchemaType#set(fn)

      Adds a setter to this schematype.

      show code
      SchemaType.prototype.set = function (fn) {
      -  if ('function' != typeof fn)
      -    throw new Error('A setter must be a function.');
      -  this.setters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      function capitalize (val) {
      -  if ('string' != typeof val) val = '';
      -  return val.charAt(0).toUpperCase() + val.substring(1);
      -}
      -
      -// defining within the schema
      -var s = new Schema({ name: { type: String, set: capitalize }})
      -
      -// or by retreiving its SchemaType
      -var s = new Schema({ name: String })
      -s.path('name').set(capitalize)
      - -

      Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      - -

      Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

      - -

      You can set up email lower case normalization easily via a Mongoose setter.

      - -
      function toLower (v) {
      -  return v.toLowerCase();
      -}
      -
      -var UserSchema = new Schema({
      -  email: { type: String, set: toLower }
      -})
      -
      -var User = db.model('User', UserSchema)
      -
      -var user = new User({email: 'AVENUE@Q.COM'})
      -console.log(user.email); // 'avenue@q.com'
      -
      -// or
      -var user = new User
      -user.email = 'Avenue@Q.com'
      -console.log(user.email) // 'avenue@q.com'
      -
      - -

      As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      - -

      NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

      - -
      new Schema({ email: { type: String, lowercase: true }})

      SchemaType#get(fn)

      Adds a getter to this schematype.

      show code
      SchemaType.prototype.get = function (fn) {
      -  if ('function' != typeof fn)
      -    throw new Error('A getter must be a function.');
      -  this.getters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      function dob (val) {
      -  if (!val) return val;
      -  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      -}
      -
      -// defining within the schema
      -var s = new Schema({ born: { type: Date, get: dob })
      -
      -// or by retreiving its SchemaType
      -var s = new Schema({ born: Date })
      -s.path('born').get(dob)
      - -

      Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

      - -

      Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

      - -
      function obfuscate (cc) {
      -  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
      -}
      -
      -var AccountSchema = new Schema({
      -  creditCardNumber: { type: String, get: obfuscate }
      -});
      -
      -var Account = db.model('Account', AccountSchema);
      -
      -Account.findById(id, function (err, found) {
      -  console.log(found.creditCardNumber); // '****-****-****-1234'
      -});

      SchemaType#validate(obj, [error])

      Adds validator(s) for this document path.

      show code
      SchemaType.prototype.validate = function (obj, error) {
      -  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
      -    this.validators.push([obj, error]);
      -    return this;
      -  }
      -
      -  var i = arguments.length
      -    , arg
      -
      -  while (i--) {
      -    arg = arguments[i];
      -    if (!(arg && 'Object' == arg.constructor.name)) {
      -      var msg = 'Invalid validator. Received (' + typeof arg + ') '
      -        + arg
      -        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
      -
      -      throw new Error(msg);
      -    }
      -    this.validate(arg.validator, arg.msg);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Validators must return Boolean. Returning false is interpreted as validation failure.

      - -

      Examples:

      - -
      function validator () { ... }
      -
      -var single = [validator, 'failed']
      -new Schema({ name: { type: String, validate: single }});
      -
      -var many = [
      -    { validator: validator, msg: 'uh oh' }
      -  , { validator: fn, msg: 'failed' }
      -]
      -new Schema({ name: { type: String, validate: many }});
      -
      -// or utilizing SchemaType methods directly:
      -
      -var schema = new Schema({ name: 'string' });
      -schema.path('name').validate(validator, 'validation failed');
      - -

      Asynchronous validation:

      - -

      Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

      - -
      schema.path('name').validate(function (value, respond) {
      -  doStuff(value, function () {
      -    ...
      -    respond(false); // validation failed
      -  })
      - }, 'my error type');
      - -

      Validation occurs pre('save') or whenever you manually execute document#validate.

      - -

      If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

      - -
      var conn = mongoose.createConnection(..);
      -conn.on('error', handleError);
      -
      -var Product = conn.model('Product', yourSchema);
      -var dvd = new Product(..);
      -dvd.save(); // emits error on the `conn` above
      - -

      If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

      - -
      // registering an error listener on the Model lets us handle errors more locally
      -Product.on('error', handleError);

      SchemaType#required(required)

      Adds a required validator to this schematype.

      show code
      SchemaType.prototype.required = function (required) {
      -  var self = this;
      -
      -  function __checkRequired (v) {
      -    // in here, `this` refers to the validating document.
      -    // no validation when this path wasn't selected in the query.
      -    if ('isSelected' in this &&
      -        !this.isSelected(self.path) &&
      -        !this.isModified(self.path)) return true;
      -    return self.checkRequired(v);
      -  }
      -
      -  if (false === required) {
      -    this.isRequired = false;
      -    this.validators = this.validators.filter(function (v) {
      -      return v[0].name !== '__checkRequired';
      -    });
      -  } else {
      -    this.isRequired = true;
      -    this.validators.push([__checkRequired, 'required']);
      -  }
      -
      -  return this;
      -};

      Parameters:

      • required <Boolean> enable/disable the validator

      Returns:

      Example:

      - -
      var s = new Schema({ born: { type: Date, required: true })
      -// or
      -Schema.path('name').required(true);

      SchemaType#getDefault(scope, init)

      Gets the default value

      show code
      SchemaType.prototype.getDefault = function (scope, init) {
      -  var ret = 'function' === typeof this.defaultValue
      -    ? this.defaultValue.call(scope)
      -    : this.defaultValue;
      -
      -  if (null !== ret && undefined !== ret) {
      -    return this.cast(ret, scope, init);
      -  } else {
      -    return ret;
      -  }
      -};

      Parameters:

      • scope <Object> the scope which callback are executed
      • init <Boolean>

      SchemaType#applySetters(value, scope, init)

      Applies setters

      show code
      SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  var v = value
      -    , setters = this.setters
      -    , len = setters.length
      -
      -  if (!len) {
      -    if (null === v || undefined === v) return v;
      -    return init
      -      ? v // if we just initialized we dont recast
      -      : this.cast(v, scope, init, priorVal)
      -  }
      -
      -  while (len--) {
      -    v = setters[len].call(scope, v, this);
      -  }
      -
      -  if (null === v || undefined === v) return v;
      -
      -  // do not cast until all setters are applied #665
      -  v = this.cast(v, scope, init, priorVal);
      -
      -  return v;
      -};

      Parameters:


      SchemaType#applyGetters(value, scope)

      Applies getters to a value

      show code
      SchemaType.prototype.applyGetters = function (value, scope) {
      -  if (SchemaType._isRef(this, value, true)) return value;
      -
      -  var v = value
      -    , getters = this.getters
      -    , len = getters.length;
      -
      -  if (!len) {
      -    return v;
      -  }
      -
      -  while (len--) {
      -    v = getters[len].call(scope, v, this);
      -  }
      -
      -  return v;
      -};

      Parameters:


      SchemaType#select(val)

      Sets default select() behavior for this path.

      show code
      SchemaType.prototype.select = function select (val) {
      -  this.selected = !! val;
      -}

      Parameters:

      Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

      - -

      Example:

      - -
      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      -T.find(..); // field x will always be selected ..
      -// .. unless overridden;
      -T.find().select('-x').exec(callback);

      SchemaType#doValidate(value, callback, scope)

      Performs a validation of value using the validators declared for this SchemaType.

      show code
      SchemaType.prototype.doValidate = function (value, fn, scope) {
      -  var err = false
      -    , path = this.path
      -    , count = this.validators.length;
      -
      -  if (!count) return fn(null);
      -
      -  function validate (val, msg) {
      -    if (err) return;
      -    if (val === undefined || val) {
      -      --count || fn(null);
      -    } else {
      -      fn(err = new ValidatorError(path, msg));
      -    }
      -  }
      -
      -  this.validators.forEach(function (v) {
      -    var validator = v[0]
      -      , message   = v[1];
      -
      -    if (validator instanceof RegExp) {
      -      validate(validator.test(value), message);
      -    } else if ('function' === typeof validator) {
      -      if (2 === validator.length) {
      -        validator.call(scope, value, function (val) {
      -          validate(val, message);
      -        });
      -      } else {
      -        validate(validator.call(scope, value), message);
      -      }
      -    }
      -  });
      -};

      Parameters:


      SchemaType._isRef(self, value, init)

      Determines if value is a valid Reference.

      show code
      SchemaType._isRef = function (self, value, init) {
      -  if (init && self.options && self.options.ref) {
      -    if (null == value) return true;
      -    if (value._id && value._id.constructor.name === self.instance) return true;
      -  }
      -
      -  return false;
      -}

      Parameters:

      Returns:


    • types/array.js

      MongooseArray(values, path, doc)

      Mongoose Array constructor.

      show code
      function MongooseArray (values, path, doc) {
      -  var arr = [];
      -  arr.push.apply(arr, values);
      -  arr.__proto__ = MongooseArray.prototype;
      -
      -  arr._atomics = {};
      -  arr.validators = [];
      -  arr._path = path;
      -
      -  if (doc) {
      -    arr._parent = doc;
      -    arr._schema = doc.schema.path(path);
      -  }
      -
      -  return arr;
      -};

      Parameters:

      Inherits:

      NOTE:

      - -

      Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


      MongooseArray#_cast(value)

      Casts a member based on this arrays schema.

      show code
      MongooseArray.prototype._cast = function (value) {
      -  var cast = this._schema.caster.cast
      -    , doc = this._parent;
      -
      -  return cast.call(null, value, doc);
      -};

      Parameters:

      Returns:

      • <value> the casted value

      MongooseArray#_markModified(embeddedDoc, embeddedPath)

      Marks this array as modified.

      show code
      MongooseArray.prototype._markModified = function (elem, embeddedPath) {
      -  var parent = this._parent
      -    , dirtyPath;
      -
      -  if (parent) {
      -    dirtyPath = this._path;
      -
      -    if (arguments.length) {
      -      if (null != embeddedPath) {
      -        // an embedded doc bubbled up the change
      -        dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
      -      } else {
      -        // directly set an index
      -        dirtyPath = dirtyPath + '.' + elem;
      -      }
      -
      -    }
      -    parent.markModified(dirtyPath);
      -  }
      -
      -  return this;
      -};

      Parameters:

      • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
      • embeddedPath <String> the path which changed in the embeddedDoc

      If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


      MongooseArray#_registerAtomic(op, val)

      Register an atomic operation with the parent.

      show code
      MongooseArray.prototype._registerAtomic = function (op, val) {
      -  if ('$set' == op) {
      -    // $set takes precedence over all other ops.
      -    // mark entire array modified.
      -    this._atomics = { $set: val };
      -    return this;
      -  }
      -
      -  var atomics = this._atomics;
      -
      -  // reset pop/shift after save
      -  if ('$pop' == op && !('$pop' in atomics)) {
      -    var self = this;
      -    this._parent.once('save', function () {
      -      self._popped = self._shifted = null;
      -    });
      -  }
      -
      -  // check for impossible $atomic combos (Mongo denies more than one
      -  // $atomic op on a single path
      -  if (this._atomics.$set ||
      -      Object.keys(atomics).length && !(op in atomics)) {
      -    // a different op was previously registered.
      -    // save the entire thing.
      -    this._atomics = { $set: this };
      -    return this;
      -  }
      -
      -  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
      -    atomics[op] || (atomics[op] = []);
      -    atomics[op] = atomics[op].concat(val);
      -  } else if (op === '$pullDocs') {
      -    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
      -      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
      -    selector['$in'] = selector['$in'].concat(val);
      -  } else {
      -    atomics[op] = val;
      -  }
      -
      -  return this;
      -};

      Parameters:


      MongooseArray#hasAtomics()

      Returns the number of pending atomic operations to send to the db for this array.

      show code
      MongooseArray.prototype.hasAtomics = function hasAtomics () {
      -  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
      -    return 0;
      -  }
      -
      -  return Object.keys(this._atomics).length;
      -}

      Returns:


      MongooseArray#push([args...])

      Wraps Array#push with proper change tracking.

      show code
      MongooseArray.prototype.push = function () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , ret = [].push.apply(this, values);
      -
      -  // $pushAll might be fibbed (could be $push). But it makes it easier to
      -  // handle what could have been $push, $pushAll combos
      -  this._registerAtomic('$pushAll', values);
      -  this._markModified();
      -  return ret;
      -};

      Parameters:


      MongooseArray#nonAtomicPush([args...])

      Pushes items to the array non-atomically.

      show code
      MongooseArray.prototype.nonAtomicPush = function () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , ret = [].push.apply(this, values);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -};

      Parameters:

      • [args...] <any>

      NOTE:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$pop()

      Pops the array atomically at most one time per document save().

      NOTE:

      - -

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      - -
      doc.array = [1,2,3];
      -
      - var popped = doc.array.$pop();
      - console.log(popped); // 3
      - console.log(doc.array); // [1,2]
      -
      - // no affect
      - popped = doc.array.$pop();
      - console.log(doc.array); // [1,2]
      -
      - doc.save(function (err) {
      -   if (err) return handleError(err);
      -
      -   // we saved, now $pop works again
      -   popped = doc.array.$pop();
      -   console.log(popped); // 2
      -   console.log(doc.array); // [1]
      - })

      MongooseArray#pop()

      Wraps Array#pop with proper change tracking.

      show code
      MongooseArray.prototype.pop = function () {
      -  var ret = [].pop.call(this);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -};

      Note:

      - -

      marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$shift()

      Atomically shifts the array at most one time per document save().

      NOTE:

      - -

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      - -
      doc.array = [1,2,3];
      -
      - var shifted = doc.array.$shift();
      - console.log(shifted); // 1
      - console.log(doc.array); // [2,3]
      -
      - // no affect
      - shifted = doc.array.$shift();
      - console.log(doc.array); // [2,3]
      -
      - doc.save(function (err) {
      -   if (err) return handleError(err);
      -
      -   // we saved, now $shift works again
      -   shifted = doc.array.$shift();
      -   console.log(shifted ); // 2
      -   console.log(doc.array); // [3]
      - })

      MongooseArray#shift()

      Wraps Array#shift with proper change tracking.

      show code
      MongooseArray.prototype.shift = function () {
      -  var ret = [].shift.call(this);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -};

      Example:

      - -
      doc.array = [2,3];
      -var res = doc.array.shift();
      -console.log(res) // 2
      -console.log(doc.array) // [3]
      - -

      Note:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#remove([args...])

      Removes items from an array atomically

      show code
      MongooseArray.prototype.remove = function () {
      -  var args = [].map.call(arguments, this._cast, this);
      -  if (args.length == 1)
      -    this.pull(args[0]);
      -  else
      -    this.pull.apply(this, args);
      -  return args;
      -};

      Parameters:

      • [args...] <Object> values to remove

      Examples:

      - -
      doc.array.remove(ObjectId)
      -doc.array.remove('tag 1', 'tag 2')

      MongooseArray#pull([args...])

      Pulls items from the array atomically.

      show code
      MongooseArray.prototype.pull = function () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , cur = this._parent.get(this._path)
      -    , i = cur.length
      -    , mem;
      -
      -  while (i--) {
      -    mem = cur[i];
      -    if (mem instanceof EmbeddedDocument) {
      -      if (values.some(function (v) { return v.equals(mem); } )) {
      -        [].splice.call(cur, i, 1);
      -      }
      -    } else if (~cur.indexOf.call(values, mem)) {
      -      [].splice.call(cur, i, 1);
      -    }
      -  }
      -
      -  if (values[0] instanceof EmbeddedDocument) {
      -    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
      -  } else {
      -    this._registerAtomic('$pullAll', values);
      -  }
      -
      -  this._markModified();
      -  return this;
      -};

      Parameters:

      • [args...] <any>

      MongooseArray#splice()

      Wraps Array#splice with proper change tracking and casting.

      show code
      MongooseArray.prototype.splice = function splice () {
      -  var ret, vals, i;
      -
      -  if (arguments.length) {
      -    vals = [];
      -    for (i = 0; i < arguments.length; ++i) {
      -      vals[i] = i < 2
      -        ? arguments[i]
      -        : this._cast(arguments[i]);
      -    }
      -    ret = [].splice.apply(this, vals);
      -    this._registerAtomic('$set', this);
      -    this._markModified();
      -  }
      -
      -  return ret;
      -}

      Note:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#unshift()

      Wraps Array#unshift with proper change tracking.

      show code
      MongooseArray.prototype.unshift = function () {
      -  var values = [].map.call(arguments, this._cast, this);
      -  [].unshift.apply(this, values);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return this.length;
      -};

      Note:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#sort()

      Wraps Array#sort with proper change tracking.

      show code
      MongooseArray.prototype.sort = function () {
      -  var ret = [].sort.apply(this, arguments);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -}

      NOTE:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#addToSet([args...])

      Adds values to the array if not already present.

      show code
      MongooseArray.prototype.addToSet = function addToSet () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , added = []
      -    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
      -             values[0] instanceof Date ? 'date' :
      -             '';
      -
      -  values.forEach(function (v) {
      -    var found;
      -    switch (type) {
      -      case 'doc':
      -        found = this.some(function(doc){ return doc.equals(v) });
      -        break;
      -      case 'date':
      -        var val = +v;
      -        found = this.some(function(d){ return +d === val });
      -        break;
      -      default:
      -        found = ~this.indexOf(v);
      -    }
      -
      -    if (!found) {
      -      [].push.call(this, v);
      -      this._registerAtomic('$addToSet', v);
      -      this._markModified();
      -      [].push.call(added, v);
      -    }
      -  }, this);
      -
      -  return added;
      -};

      Parameters:

      • [args...] <any>

      Returns:

      • <Array> the values that were added

      Example:

      - -
      console.log(doc.array) // [2,3,4]
      -var added = doc.array.addToSet(4,5);
      -console.log(doc.array) // [2,3,4,5]
      -console.log(added)     // [5]

      MongooseArray#set()

      Sets the casted val at index i and marks the array modified.

      show code
      MongooseArray.prototype.set = function set (i, val) {
      -  this[i] = this._cast(val);
      -  this._markModified(i);
      -  return this;
      -}

      Returns:

      Example:

      - -
      // given documents based on the following
      -var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
      -
      -var doc = new Doc({ array: [2,3,4] })
      -
      -console.log(doc.array) // [2,3,4]
      -
      -doc.array.set(1,"5");
      -console.log(doc.array); // [2,5,4] // properly cast to number
      -doc.save() // the change is saved
      -
      -// VS not using array#set
      -doc.array[1] = "5";
      -console.log(doc.array); // [2,"5",4] // no casting
      -doc.save() // change is not saved

      MongooseArray#toObject(options)

      Returns a native js Array.

      show code
      MongooseArray.prototype.toObject = function (options) {
      -  if (options && options.depopulate && this[0] instanceof Document) {
      -    return this.map(function (doc) {
      -      return doc._id;
      -    });
      -  }
      -
      -  // return this.slice()?
      -  return this.map(function (doc) {
      -    return doc;
      -  });
      -};

      Parameters:

      Returns:


      MongooseArray#inspect()

      Helper for console.log

      show code
      MongooseArray.prototype.inspect = function () {
      -  return '[' + this.map(function (doc) {
      -    return ' ' + doc;
      -  }) + ' ]';
      -};

      MongooseArray#indexOf(obj)

      Return the index of obj or -1 if not found.

      show code
      MongooseArray.prototype.indexOf = function indexOf (obj) {
      -  if (obj instanceof ObjectId) obj = obj.toString();
      -  for (var i = 0, len = this.length; i < len; ++i) {
      -    if (obj == this[i])
      -      return i;
      -  }
      -  return -1;
      -};

      Parameters:

      • obj <Object> the item to look for

      Returns:


      MongooseArray#_parent

      Parent owner document


      MongooseArray#_atomics

      Stores a queue of atomic operations to perform


    • types/buffer.js

      MongooseBuffer(value, encode, offset)

      Mongoose Buffer constructor.

      show code
      function MongooseBuffer (value, encode, offset) {
      -  var length = arguments.length;
      -  var val;
      -
      -  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
      -    val = 0;
      -  } else {
      -    val = value;
      -  }
      -
      -  var encoding;
      -  var path;
      -  var doc;
      -
      -  if (Array.isArray(encode)) {
      -    // internal casting
      -    path = encode[0];
      -    doc = encode[1];
      -  } else {
      -    encoding = encode;
      -  }
      -
      -  var buf = new Buffer(val, encoding, offset);
      -  buf.__proto__ = MongooseBuffer.prototype;
      -
      -  // make sure these internal props don't show up in Object.keys()
      -  Object.defineProperties(buf, {
      -      validators: { value: [] }
      -    , _path: { value: path }
      -    , _parent: { value: doc }
      -  });
      -
      -  if (doc && "string" === typeof path) {
      -    Object.defineProperty(buf, '_schema', {
      -        value: doc.schema.path(path)
      -    });
      -  }
      -
      -  return buf;
      -};

      Parameters:

      Inherits:

      Values always have to be passed to the constructor to initialize.


      MongooseBuffer#_markModified()

      Marks this buffer as modified.

      show code
      MongooseBuffer.prototype._markModified = function () {
      -  var parent = this._parent;
      -
      -  if (parent) {
      -    parent.markModified(this._path);
      -  }
      -  return this;
      -};

      MongooseBuffer#write()

      Writes the buffer.

      show code
      MongooseBuffer.prototype.write = function () {
      -  var written = Buffer.prototype.write.apply(this, arguments);
      -
      -  if (written > 0) {
      -    this._markModified();
      -  }
      -
      -  return written;
      -};

      MongooseBuffer#copy(target)

      Copies the buffer.

      show code
      MongooseBuffer.prototype.copy = function (target) {
      -  var ret = Buffer.prototype.copy.apply(this, arguments);
      -
      -  if (target instanceof MongooseBuffer) {
      -    target._markModified();
      -  }
      -
      -  return ret;
      -};

      Parameters:

      Returns:

      Note:

      - -

      Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


      MongooseBuffer#toObject([subtype])

      Converts this buffer to its Binary type representation.

      show code
      MongooseBuffer.prototype.toObject = function (subtype) {
      -  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
      -  return new Binary(this, subtype);
      -};

      Parameters:

      • [subtype] <Hex>

      Returns:

      SubTypes:

      - -
        -
      • 0x00: Binary/Generic
      • -
      • 0x01: Function
      • -
      • 0x02: Binary (Deprecated, 0x00 is new default)
      • -
      • 0x03: UUID
      • -
      • 0x04: MD5
      • -
      • 0x80: User Defined
      • -

      MongooseBuffer#_parent

      Parent owner document


    • types/documentarray.js

      MongooseDocumentArray(values, path, doc)

      DocumentArray constructor

      show code
      function MongooseDocumentArray (values, path, doc) {
      -  var arr = [];
      -
      -  // Values always have to be passed to the constructor to initialize, since
      -  // otherwise MongooseArray#push will mark the array as modified to the parent.
      -  arr.push.apply(arr, values);
      -  arr.__proto__ = MongooseDocumentArray.prototype;
      -
      -  arr._atomics = {};
      -  arr.validators = [];
      -  arr._path = path;
      -
      -  if (doc) {
      -    arr._parent = doc;
      -    arr._schema = doc.schema.path(path);
      -    doc.on('save', arr.notify('save'));
      -    doc.on('isNew', arr.notify('isNew'));
      -  }
      -
      -  return arr;
      -};

      Parameters:

      Inherits:


      MongooseDocumentArray#_cast()

      Overrides MongooseArray#cast

      show code
      MongooseDocumentArray.prototype._cast = function (value) {
      -  if (value instanceof this._schema.casterConstructor)
      -    return value;
      -
      -  return new this._schema.casterConstructor(value, this);
      -};

      MongooseDocumentArray#id(id)

      Searches array items for the first document with a matching id.

      show code
      MongooseDocumentArray.prototype.id = function (id) {
      -  var casted
      -    , _id;
      -
      -  try {
      -    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
      -  } catch (e) {
      -    casted = null;
      -  }
      -
      -  for (var i = 0, l = this.length; i < l; i++) {
      -    _id = this[i].get('_id');
      -    if (!(_id instanceof ObjectId)) {
      -      if (String(id) == _id)
      -        return this[i];
      -    } else {
      -      if (casted == _id)
      -        return this[i];
      -    }
      -  }
      -
      -  return null;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var embeddedDoc = m.array.id(some_id);

      MongooseDocumentArray#toObject()

      Returns a native js Array of plain js objects

      show code
      MongooseDocumentArray.prototype.toObject = function () {
      -  return this.map(function (doc) {
      -    return doc && doc.toObject() || null;
      -  });
      -};

      Returns:

      NOTE:

      - -

      Each sub-document is converted to a plain object by calling its #toObject method.


      MongooseDocumentArray#inspect()

      Helper for console.log

      show code
      MongooseDocumentArray.prototype.inspect = function () {
      -  return '[' + this.map(function (doc) {
      -    if (doc) {
      -      return doc.inspect
      -        ? doc.inspect()
      -        : util.inspect(doc)
      -    }
      -    return 'null'
      -  }).join('
      -') + ']';
      -};

      MongooseDocumentArray#create(obj)

      Creates a subdocument casted to this schema.

      show code
      MongooseDocumentArray.prototype.create = function (obj) {
      -  return new this._schema.casterConstructor(obj);
      -}

      Parameters:

      • obj <Object> the value to cast to this arrays SubDocument schema

      This is the same subdocument constructor used for casting.


      MongooseDocumentArray#notify(event)

      Creates a fn that notifies all child docs of event.

      show code
      MongooseDocumentArray.prototype.notify = function notify (event) {
      -  var self = this;
      -  return function notify (val) {
      -    var i = self.length;
      -    while (i--) {
      -      if (!self[i]) continue;
      -      self[i].emit(event, val);
      -    }
      -  }
      -}

      Parameters:

      Returns:


    • types/embedded.js

      EmbeddedDocument(obj, parentArr, skipId)

      EmbeddedDocument constructor.

      show code
      function EmbeddedDocument (obj, parentArr, skipId, fields) {
      -  if (parentArr) {
      -    this.__parentArray = parentArr;
      -    this.__parent = parentArr._parent;
      -  } else {
      -    this.__parentArray = undefined;
      -    this.__parent = undefined;
      -  }
      -
      -  Document.call(this, obj, fields, skipId);
      -
      -  var self = this;
      -  this.on('isNew', function (val) {
      -    self.isNew = val;
      -  });
      -};

      Parameters:

      Inherits:


      EmbeddedDocument#markModified(path)

      Marks the embedded doc modified.

      show code
      EmbeddedDocument.prototype.markModified = function (path) {
      -  if (!this.__parentArray) return;
      -
      -  this._activePaths.modify(path);
      -
      -  if (this.isNew) {
      -    // Mark the WHOLE parent array as modified
      -    // if this is a new document (i.e., we are initializing
      -    // a document),
      -    this.__parentArray._markModified();
      -  } else
      -    this.__parentArray._markModified(this, path);
      -};

      Parameters:

      • path <String> the path which changed

      Example:

      - -
      var doc = blogpost.comments.id(hexstring);
      -doc.mixed.type = 'changed';
      -doc.markModified('mixed.type');

      EmbeddedDocument#save([fn])

      Used as a stub for hooks.js

      show code
      EmbeddedDocument.prototype.save = function(fn) {
      -  if (fn)
      -    fn(null);
      -  return this;
      -};

      Parameters:

      Returns:

      NOTE:

      - -

      This is a no-op. Does not actually save the doc to the db.


      EmbeddedDocument#remove([fn])

      Removes the subdocument from its parent array.

      show code
      EmbeddedDocument.prototype.remove = function (fn) {
      -  if (!this.__parentArray) return this;
      -
      -  var _id;
      -  if (!this.willRemove) {
      -    _id = this._doc._id;
      -    if (!_id) {
      -      throw new Error('For your own good, Mongoose does not know ' + 
      -                      'how to remove an EmbeddedDocument that has no _id');
      -    }
      -    this.__parentArray.pull({ _id: _id });
      -    this.willRemove = true;
      -  }
      -
      -  if (fn)
      -    fn(null);
      -
      -  return this;
      -};

      Parameters:


      EmbeddedDocument#update()

      Override #update method of parent documents.

      show code
      EmbeddedDocument.prototype.update = function () {
      -  throw new Error('The #update method is not available on EmbeddedDocuments');
      -}

      EmbeddedDocument#inspect()

      Helper for console.log

      show code
      EmbeddedDocument.prototype.inspect = function () {
      -  return inspect(this.toObject());
      -};

      EmbeddedDocument#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
      -  if (!this.__parent) return false;
      -  var index = this.__parentArray.indexOf(this);
      -  var parentPath = this.__parentArray._path;
      -  var fullPath = [parentPath, index, path].join('.');
      -  this.__parent.invalidate(fullPath, err);
      -  if (first)
      -    this._validationError = ownerDocument(this)._validationError;
      -  return true;
      -}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> error which states the reason `path` was invalid

      Returns:


      EmbeddedDocument#ownerDocument()

      Returns the top level document of this sub-document.

      show code
      EmbeddedDocument.prototype.ownerDocument = function () {
      -  return ownerDocument(this);
      -}

      Returns:


      EmbeddedDocument#parent()

      Returns this sub-documents parent document.

      show code
      EmbeddedDocument.prototype.parent = function () {
      -  return this.__parent;
      -}

      EmbeddedDocument#parentArray()

      Returns this sub-documents parent array.

      show code
      EmbeddedDocument.prototype.parentArray = function () {
      -  return this.__parentArray;
      -}

    • types/objectid.js

      ObjectId()

      ObjectId type constructor

      Example

      - -
      var id = new mongoose.Types.ObjectId;

      ObjectId.fromString(str)

      Creates an ObjectId from str

      show code
      ObjectId.fromString;

      Parameters:

      Returns:


      ObjectId.toString(oid)

      Converts oid to a string.

      show code
      ObjectId.toString;

      Parameters:

      Returns:


    • utils.js

      exports.toCollectionName(name)

      Produces a collection name from model name.

      show code
      exports.toCollectionName = function (name) {
      -  if ('system.profile' === name) return name;
      -  if ('system.indexes' === name) return name;
      -  return pluralize(name.toLowerCase());
      -};

      Parameters:

      Returns:


      exports.pluralization

      Pluralization rules.

      show code
      exports.pluralization = [
      -  [/(m)an$/gi, '$1en'],
      -  [/(pe)rson$/gi, '$1ople'],
      -  [/(child)$/gi, '$1ren'],
      -  [/^(ox)$/gi, '$1en'],
      -  [/(ax|test)is$/gi, '$1es'],
      -  [/(octop|vir)us$/gi, '$1i'],
      -  [/(alias|status)$/gi, '$1es'],
      -  [/(bu)s$/gi, '$1ses'],
      -  [/(buffal|tomat|potat)o$/gi, '$1oes'],
      -  [/([ti])um$/gi, '$1a'],
      -  [/sis$/gi, 'ses'],
      -  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
      -  [/(hive)$/gi, '$1s'],
      -  [/([^aeiouy]|qu)y$/gi, '$1ies'],
      -  [/(x|ch|ss|sh)$/gi, '$1es'],
      -  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
      -  [/([m|l])ouse$/gi, '$1ice'],
      -  [/(quiz)$/gi, '$1zes'],
      -  [/s$/gi, 's'],
      -  [/$/gi, 's']
      -];
      -var rules = exports.pluralization;

      These rules are applied while processing the argument to toCollectionName.


      exports.uncountables

      Uncountable words.

      show code
      exports.uncountables = [
      -  'advice',
      -  'energy',
      -  'excretion',
      -  'digestion',
      -  'cooperation',
      -  'health',
      -  'justice',
      -  'labour',
      -  'machinery',
      -  'equipment',
      -  'information',
      -  'pollution',
      -  'sewage',
      -  'paper',
      -  'money',
      -  'species',
      -  'series',
      -  'rain',
      -  'rice',
      -  'fish',
      -  'sheep',
      -  'moose',
      -  'deer',
      -  'news',
      -  'expertise',
      -  'status',
      -  'media'
      -];
      -var uncountables = exports.uncountables;

      These words are applied while processing the argument to toCollectionName.


      exports.deepEqual(a, b)

      Determines if a and b are deep equal.

      show code
      exports.deepEqual = function deepEqual (a, b) {
      -  if (a === b) return true;
      -
      -  if (a instanceof Date && b instanceof Date)
      -    return a.getTime() === b.getTime();
      -
      -  if (a instanceof ObjectId && b instanceof ObjectId) {
      -    return a.toString() === b.toString();
      -  }
      -
      -  if (typeof a !== 'object' && typeof b !== 'object')
      -    return a == b;
      -
      -  if (a === null || b === null || a === undefined || b === undefined)
      -    return false
      -
      -  if (a.prototype !== b.prototype) return false;
      -
      -  // Handle MongooseNumbers
      -  if (a instanceof Number && b instanceof Number) {
      -    return a.valueOf() === b.valueOf();
      -  }
      -
      -  if (Buffer.isBuffer(a)) {
      -    if (!Buffer.isBuffer(b)) return false;
      -    if (a.length !== b.length) return false;
      -    for (var i = 0, len = a.length; i < len; ++i) {
      -      if (a[i] !== b[i]) return false;
      -    }
      -    return true;
      -  }
      -
      -  if (isMongooseObject(a)) a = a.toObject();
      -  if (isMongooseObject(b)) b = b.toObject();
      -
      -  try {
      -    var ka = Object.keys(a),
      -        kb = Object.keys(b),
      -        key, i;
      -  } catch (e) {//happens when one is a string literal and the other isn't
      -    return false;
      -  }
      -
      -  // having the same number of owned properties (keys incorporates
      -  // hasOwnProperty)
      -  if (ka.length != kb.length)
      -    return false;
      -
      -  //the same set of keys (although not necessarily the same order),
      -  ka.sort();
      -  kb.sort();
      -
      -  //~~~cheap key test
      -  for (i = ka.length - 1; i >= 0; i--) {
      -    if (ka[i] != kb[i])
      -      return false;
      -  }
      -
      -  //equivalent values for every corresponding key, and
      -  //~~~possibly expensive deep test
      -  for (i = ka.length - 1; i >= 0; i--) {
      -    key = ka[i];
      -    if (!deepEqual(a[key], b[key])) return false;
      -  }
      -
      -  return true;
      -};

      Parameters:

      • a <any> a value to compare to `b`
      • b <any> a value to compare to `a`

      Returns:

      Modified from node/lib/assert.js


      exports.clone(obj, options)

      Object clone with Mongoose natives support.

      show code
      exports.clone = function clone (obj, options) {
      -  if (obj === undefined || obj === null)
      -    return obj;
      -
      -  if (Array.isArray(obj))
      -    return cloneArray(obj, options);
      -
      -  if (isMongooseObject(obj)) {
      -    if (options && options.json && 'function' === typeof obj.toJSON) {
      -      return obj.toJSON(options);
      -    } else {
      -      return obj.toObject(options);
      -    }
      -  }
      -
      -  if ('Object' === obj.constructor.name)
      -    return cloneObject(obj, options);
      -
      -  if ('Date' === obj.constructor.name)
      -    return new obj.constructor(+obj);
      -
      -  if ('RegExp' === obj.constructor.name)
      -    return new RegExp(obj.source);
      -
      -  if (obj instanceof ObjectId)
      -    return new ObjectId(obj.id);
      -
      -  if (obj.valueOf)
      -    return obj.valueOf();
      -};
      -var clone = exports.clone;

      Parameters:

      Returns:

      If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

      - -

      Functions are never cloned.


      exports.options(defaults, options)

      Copies and merges options with defaults.

      show code
      exports.options = function (defaults, options) {
      -  var keys = Object.keys(defaults)
      -    , i = keys.length
      -    , k ;
      -
      -  options = options || {};
      -
      -  while (i--) {
      -    k = keys[i];
      -    if (!(k in options)) {
      -      options[k] = defaults[k];
      -    }
      -  }
      -
      -  return options;
      -};

      Parameters:

      Returns:


      exports.random()

      Generates a random string

      show code
      exports.random = function () {
      -  return Math.random().toString().substr(3);
      -};

      exports.merge(to, from)

      Merges from into to without overwriting existing properties.

      show code
      exports.merge = function merge (to, from) {
      -  var keys = Object.keys(from)
      -    , i = keys.length
      -    , key
      -
      -  while (i--) {
      -    key = keys[i];
      -    if ('undefined' === typeof to[key]) {
      -      to[key] = from[key];
      -    } else {
      -      if (exports.isObject(from[key])) {
      -        merge(to[key], from[key]);
      -      } else {
      -        to[key] = from[key];
      -      }
      -    }
      -  }
      -};

      Parameters:


      exports.isObject(arg)

      Determines if arg is an object.

      show code
      exports.isObject = function (arg) {
      -  return '[object Object]' == toString(arg);
      -}

      Parameters:

      Returns:


      exports.args

      A faster Array.prototype.slice.call(arguments) alternative

      show code
      exports.args = sliced;

      exports.tick(callback)

      process.nextTick helper.

      show code
      exports.tick = function tick (callback) {
      -  if ('function' !== typeof callback) return;
      -  return function () {
      -    try {
      -      callback.apply(this, arguments);
      -    } catch (err) {
      -      // only nextTick on err to get out of
      -      // the event loop and avoid state corruption.
      -      process.nextTick(function () {
      -        throw err;
      -      });
      -    }
      -  }
      -}

      Parameters:

      Wraps callback in a try/catch + nextTick.

      - -

      node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


      exports.isMongooseObject(v)

      Returns if v is a mongoose object that has a toObject() method we can use.

      show code
      exports.isMongooseObject = function (v) {
      -  Document || (Document = require('./document'));
      -  MongooseArray || (MongooseArray = require('./types').Array);
      -  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
      -
      -  return v instanceof Document ||
      -         v instanceof MongooseArray ||
      -         v instanceof MongooseBuffer
      -}
      -var isMongooseObject = exports.isMongooseObject;

      Parameters:

      This is for compatibility with libs like Date.js which do foolish things to Natives.


      exports.expires(object)

      Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

      show code
      exports.expires = function expires (object) {
      -  if (!(object && 'Object' == object.constructor.name)) return;
      -  if (!('expires' in object)) return;
      -
      -  var when;
      -  if ('string' != typeof object.expires) {
      -    when = object.expires;
      -  } else {
      -    when = Math.round(ms(object.expires) / 1000);
      -  }
      -  object.expireAfterSeconds = when;
      -  delete object.expires;
      -}
      -
      -exports.readPref = function readPref (pref, tags) {
      -  if (Array.isArray(pref)) {
      -    tags = pref[1];
      -    pref = pref[0];
      -  }
      -
      -  switch (pref) {
      -    case 'p':
      -      pref = 'primary';
      -      break;
      -    case 'pp':
      -      pref = 'primaryPrefered';
      -      break;
      -    case 's':
      -      pref = 'secondary';
      -      break;
      -    case 'sp':
      -      pref = 'secondaryPrefered';
      -      break;
      -    case 'n':
      -      pref = 'nearest';
      -      break;
      -  }
      -
      -  return new ReadPref(pref, tags);
      -}

      Parameters:


    • virtualtype.js

      VirtualType()

      VirtualType constructor

      show code
      function VirtualType (options, name) {
      -  this.path = name;
      -  this.getters = [];
      -  this.setters = [];
      -  this.options = options || {};
      -}

      This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

      - -

      Example:

      - -
      var fullname = schema.virtual('fullname');
      -fullname instanceof mongoose.VirtualType // true

      VirtualType#get(fn)

      Defines a getter.

      show code
      VirtualType.prototype.get = function (fn) {
      -  this.getters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var virtual = schema.virtual('fullname');
      -virtual.get(function () {
      -  return this.name.first + ' ' + this.name.last;
      -});

      VirtualType#set(fn)

      Defines a setter.

      show code
      VirtualType.prototype.set = function (fn) {
      -  this.setters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var virtual = schema.virtual('fullname');
      -virtual.set(function (v) {
      -  var parts = v.split(' ');
      -  this.name.first = parts[0];
      -  this.name.last = parts[1];
      -});

      VirtualType#applyGetters(value, scope)

      Applies getters to value using optional scope.

      show code
      VirtualType.prototype.applyGetters = function (value, scope) {
      -  var v = value;
      -  for (var l = this.getters.length - 1; l >= 0; l--) {
      -    v = this.getters[l].call(scope, v, this);
      -  }
      -  return v;
      -};

      Parameters:

      Returns:

      • <any> the value after applying all getters

      VirtualType#applySetters(value, scope)

      Applies setters to value using optional scope.

      show code
      VirtualType.prototype.applySetters = function (value, scope) {
      -  var v = value;
      -  for (var l = this.setters.length - 1; l >= 0; l--) {
      -    v = this.setters[l].call(scope, v, this);
      -  }
      -  return v;
      -};

      Parameters:

      Returns:

      • <any> the value after applying all setters

    diff --git a/docs/3.4.x/docs/connections.html b/docs/3.4.x/docs/connections.html deleted file mode 100644 index 7761fd4d84c..00000000000 --- a/docs/3.4.x/docs/connections.html +++ /dev/null @@ -1,27 +0,0 @@ -Mongoose Connecting to MongoDB v3.4.0Fork me on GitHub

    Connections

    We may connect to MongoDB by utilizing the mongoose.connect() method.

    mongoose.connect('mongodb://localhost/myapp');
    -

    This is the minimum needed to connect the myapp database running locally on the default port (27017). We may also specify several more parameters in the uri depending on your environment:

    mongoose.connect('mongodb://username:password@host:port/database');
    -

    Options

    The connect method also accepts an options object which will be passed on to the underlying driver.

    mongoose.connect(uri, options);
    -

    The following option keys are available:

    - -
     db      - passed to the connection db instance
    - server  - passed to the connection server instance(s)
    - replset - passed to the connection ReplSet instance
    - user    - username for authentication (if not specified in uri)
    - pass    - password for authentication (if not specified in uri)
    - -

    See the driver for more information about available options.

    - -

    Note: The server option auto_reconnect is defaulted to true.

    - -

    Note: The db option forceServerObjectId is set to false and cannot be overridden.

    ReplicaSet Connections

    The same method is used to connect to a replica set but instead of passing a single uri we pass a comma delimited list of uris.

    mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]);
    -

    NOTE: The database need only be specified in one of the uris.

    Multiple connections

    So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize mongoose.createConnection() which accepts all the arguments already discussed and returns a fresh connection for you.

    var conn = mongoose.createConnection('uri,uri,uri...', options);
    -

    Connection pools

    Each connection, whether created with mongoose.connect or mongoose.createConnection are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options:

    mongoose.createConnection(uri, { server: { poolSize: 10 }});
    -

    Next Up

    Now that we've covered connections, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

    diff --git a/docs/3.4.x/docs/contributing.html b/docs/3.4.x/docs/contributing.html deleted file mode 100644 index b75cc3d3d3c..00000000000 --- a/docs/3.4.x/docs/contributing.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose Contributing v3.4.0Fork me on GitHub

    Contributing

    Please read all about contributing here.

    diff --git a/docs/3.4.x/docs/css/default.css b/docs/3.4.x/docs/css/default.css deleted file mode 100644 index ccb22728ed3..00000000000 --- a/docs/3.4.x/docs/css/default.css +++ /dev/null @@ -1,135 +0,0 @@ -/* - -Original style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ - -pre code { - display: block; padding: 0.5em; - background: #F0F0F0; -} - -pre code, -pre .ruby .subst, -pre .tag .title, -pre .lisp .title, -pre .clojure .built_in, -pre .nginx .title { - color: black; -} - -pre .string, -pre .title, -pre .constant, -pre .parent, -pre .tag .value, -pre .rules .value, -pre .rules .value .number, -pre .preprocessor, -pre .ruby .symbol, -pre .ruby .symbol .string, -pre .ruby .symbol .keyword, -pre .ruby .symbol .keymethods, -pre .instancevar, -pre .aggregate, -pre .template_tag, -pre .django .variable, -pre .smalltalk .class, -pre .addition, -pre .flow, -pre .stream, -pre .bash .variable, -pre .apache .tag, -pre .apache .cbracket, -pre .tex .command, -pre .tex .special, -pre .erlang_repl .function_or_atom, -pre .markdown .header { - color: #800; -} - -pre .comment, -pre .annotation, -pre .template_comment, -pre .diff .header, -pre .chunk, -pre .markdown .blockquote { - color: #888; -} - -pre .number, -pre .date, -pre .regexp, -pre .literal, -pre .smalltalk .symbol, -pre .smalltalk .char, -pre .go .constant, -pre .change, -pre .markdown .bullet, -pre .markdown .link_url { - color: #080; -} - -pre .label, -pre .javadoc, -pre .ruby .string, -pre .decorator, -pre .filter .argument, -pre .localvars, -pre .array, -pre .attr_selector, -pre .important, -pre .pseudo, -pre .pi, -pre .doctype, -pre .deletion, -pre .envvar, -pre .shebang, -pre .apache .sqbracket, -pre .nginx .built_in, -pre .tex .formula, -pre .erlang_repl .reserved, -pre .input_number, -pre .markdown .link_label, -pre .vhdl .attribute, -pre .clojure .attribute { - color: #88F -} - -pre .keyword, -pre .id, -pre .phpdoc, -pre .title, -pre .built_in, -pre .aggregate, -pre .css .tag, -pre .javadoctag, -pre .phpdoc, -pre .yardoctag, -pre .smalltalk .class, -pre .winutils, -pre .bash .variable, -pre .apache .tag, -pre .go .typename, -pre .tex .command, -pre .markdown .strong, -pre .request, -pre .status { - font-weight: bold; -} - -pre .markdown .emphasis { - font-style: italic; -} - -pre .nginx .built_in { - font-weight: normal; -} - -pre .coffeescript .javascript, -pre .xml .css, -pre .xml .javascript, -pre .xml .vbscript, -pre .tex .formula { - opacity: 0.5; -} diff --git a/docs/3.4.x/docs/css/guide.css b/docs/3.4.x/docs/css/guide.css deleted file mode 100644 index b77ffe83b0c..00000000000 --- a/docs/3.4.x/docs/css/guide.css +++ /dev/null @@ -1,326 +0,0 @@ -html, body, #content { - height: 100%; -} -:target::before { - content: ">>> "; - color: #1371C9; - font-weight: bold; - font-size: 20px; -} -.module { - min-height: 100%; - box-sizing: border-box; - overflow-x: hidden; -} -body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; -} -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; -} -code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Monaco; - /*text-shadow: 1px 2px 2px #555;*/ -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -h2 { - margin-top: 0; -} -h2 a { - font-size: 12px; - position: relative; - bottom: 3px; - font-weight: normal; -} -h3 { padding-top: 35px; } -h3 code { - font-weight: normal; -} -hr { - display: none; - height: 1px; - border: 0 none; - padding: 0; - margin: 90px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) -} -.doclinks hr { - margin: 10px 0; -} -li { - list-style: square; -} -#header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -#header .mongoose { - font-size: 48px; - font-weight: 100; - color: #fff; - letter-spacing: -5px; -} -#links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; -} -#links .schematypes span { - display: none; -} -#content { - padding: 0; - margin: 0 0 0 230px; -} -#content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -#content .controls:hover { - opacity: .9; -} -#content p { - word-wrap: break-word; -} -#content > ul { - margin: 0; - padding: 0; -} -.private { - display: none; -} -.doclinks li.private a:before, -.doclinks .module.private a:before, -.doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; -} -#content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; -} -.module { - list-style: none; - padding: 30px 0 0 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; -} -.module > * { - max-width: 700px; -} -.item { - margin-bottom: 175px; -} -.item h3 a { - color: #333; - text-decoration: none; -} -.property h3 span { - color: #444; -} -.description { - margin-top: 25px; -} -.sourcecode { - display: none; -} -.showcode { - font-size: 12px; - cursor: pointer; - display: none; -} -.load .showcode { - display: block; -} -.types a { - text-decoration: none; -} -li.guide ul { - padding-left: 16px; -} - -ul.inthewild { - margin: 30px 0 0 -30px; - padding: 0; - width: 125%; - max-width: 125%; -} -ul.inthewild li { - display: inline-block; - list-style: none; -} -ul.inthewild img { - width: 200px; -} - -@media only screen and (device-width: 768px) { - ul.inthewild { - margin-left: 0px; - } -} - -@media only screen and (max-width: 480px) { - ul.inthewild { - margin-left: 0px; - } - ul.inthewild li { - margin: 5px; - border-width: 2px 2px 0 2px; - border-style: solid; - border-color: #eee; - } - ul.inthewild li img { - width: 140px; - } - h2 a { - white-space: nowrap; - } - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - html, body, #content { - height: auto; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - #links li.guide { - display: block; - width: 390px; - margin-bottom: 15px; - } - #links li.guide > a { - display: none; - } - #links li ul li { - width: 44%; - text-align: left; - } - #links li ul li ul li { - width: 95%; - } - #links .plugins, - #links .changelog { - display: none; - } - #links .schematypes span { - display: inline; - } - #links .double { - width: 332px; - } - #links .double > ul { - display: inline; - float: right; - } - #links .double > ul li { - width: 155px; - } -} diff --git a/docs/3.4.x/docs/css/style.css b/docs/3.4.x/docs/css/style.css deleted file mode 100644 index 34fee99b3f7..00000000000 --- a/docs/3.4.x/docs/css/style.css +++ /dev/null @@ -1,225 +0,0 @@ -body { - font-family: 'Open Sans', Helvetica, Arial, FreeSans; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; -} - -/* location.hash */ -:target::before { - content: ">>> "; - color: #1371C9; - font-weight: bold; - font-size: 20px; -} -/* ignore home page hash */ -#production:target::before { - content: ""; - font-size: inherit; -} - -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { - width: 600px; - margin: 0 auto; - position:relative; -} -li { - list-style: square; -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: #eee; - padding: 5px; - border-radius: 3px; -} -code { - color: #333; - font-size: 11px; - font-family: Monaco; -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -#header { - text-align: center; - padding-top: 40px; -} -#header, h2, h3, .tagline, .blurb { - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -h2 { - margin: 30px 0; -} -h2 a { - font-size: 11px; - position: relative; - bottom: 4px; -} -#header .mongoose { - font-size: 146px; - font-weight: 100; - text-indent: -23px; -} -.load #header .mongoose { - letter-spacing: -14px; -} -.tagline { - color: #333; - font-size: 25px; - text-shadow: 1px 1px #f8f8f8; - text-align: center; -} -.blurb { - text-align: center; - font-style: oblique; - font-size: 12px; - margin-bottom: 20px; -} -.tagline a, .blurb a { - text-decoration: none; - color: #800; -} -#links { - margin: 30px 10px 46px; - text-align: center; - position: relative; -} -#links ul { - margin: 0; - padding: 0; -} -#links li { - display: inline-block; - margin: 0 15px; - background-color: #FEFEFE; -} -#links a { - background: #444; - padding: 9px 0px; - border-radius: 3px; - color: white; - width: 180px; - display: inline-block; - text-decoration: none; - text-transform: lowercase; - text-shadow: 1px 1px 7px #222; -} -#production ul { - padding: 0; -} -#production li { - list-style: none; - overflow: hidden; - display: inline-block; - height: 114px; -} -#production img { - width: 180px; - margin: 10px; -} -#production img#mcds { - width: 134px; - margin: 10px 25px; -} -#production a { - -webkit-transition-property: opacity; - -moz-transition-property: opacity; - -o-transition-property: opacity; - transition-property: opacity; - -webkit-transition-duration: 0.25s; - -moz-transition-duration: 0.25s; - -o-transition-duration: 0.25s; - transition-duration: 0.25s; - opacity: 0.7; -} -#production a:hover { - opacity: 1.0; -} -#footer { - text-align: center; - font-size: 12px; - margin-bottom: 20px; -} -@media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header { - padding-top: 12px; - } - #header .mongoose { - text-align: center; - font-size: 65px; - font-weight: 100; - letter-spacing: -7px; - } - .load #header .mongoose { - letter-spacing: -7px; - } - .tagline { - text-align: center; - font-size: 14px; - } - .tagline a { - text-decoration: none; - } - .blurb { - font-size: 16px; - text-align: justify; - margin-top: 25px; - } - #links { - margin-bottom: 40px; - } - #links li { - padding: 8px 2px; - margin: 0 12px; - } - #links a { - background: #444; - padding: 7px 34px; - font-size: 15px; - } - #docs { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - #wrap { - width: auto; - padding: 0 5px; - } - #production li { - margin-bottom: 8px; - } - #production a { - opacity: 1; - } - #production img { - width: 175px; - } - .addyourown, .addyourown a { - width: 100%; - } -} diff --git a/docs/3.4.x/docs/documents.html b/docs/3.4.x/docs/documents.html deleted file mode 100644 index c10a191f2b0..00000000000 --- a/docs/3.4.x/docs/documents.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose Documents v3.4.0Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    -  if (err) return handleError(err);
    -  
    -  tank.size = 'large';
    -  tank.save(function (err) {
    -    if (err) return handleError(err);
    -    res.send(tank);
    -  });
    -});

    This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    -  if (err) return handleError(err);
    -  res.send(tank);
    -});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    diff --git a/docs/3.4.x/docs/faq.html b/docs/3.4.x/docs/faq.html deleted file mode 100644 index 35cc94d6d1e..00000000000 --- a/docs/3.4.x/docs/faq.html +++ /dev/null @@ -1,31 +0,0 @@ -Mongoose FAQ v3.4.0Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    -doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    -doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    -new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    -doc.user.remove();// ?
    -doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    - -

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    - -

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    -mongoose.connect(..);
    -mongoose.connection.on('error', handleError);
    -
    -// if connecting on a separate connection
    -var conn = mongoose.createConnection(..);
    -conn.on('error', handleError);
    -

    Something to add?

    - -

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    diff --git a/docs/3.4.x/docs/guide.html b/docs/3.4.x/docs/guide.html deleted file mode 100644 index c9e352dd274..00000000000 --- a/docs/3.4.x/docs/guide.html +++ /dev/null @@ -1,190 +0,0 @@ -Mongoose Schemas v3.4.0Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

    If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    -  title:  String,
    -  author: String,
    -  body:   String,
    -  comments: [{ body: String, date: Date }],
    -  date: { type: Date, default: Date.now },
    -  hidden: Boolean,
    -  meta: {
    -    votes: Number,
    -    favs:  Number
    -  }
    -});

    If you want to add additional keys later, use the Schema#add method.

    -Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. -Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    -
    -animalSchema.methods.findSimilarTypes = function (cb) {
    -  return this.model('Animal').find({ type: this.type }, cb);
    -}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    -var dog = new Animal({ type: 'dog' });
    -
    -dog.findSimilarTypes(function (err, dogs) {
    -  console.log(dogs); // woof
    -});

    Statics

    -Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    -  this.find({ name: new RegExp(name, 'i') }, cb);
    -}
    -
    -var Animal = mongoose.model('Animal', animalSchema);
    -Animal.findByName('fido', function (err, animals) {
    -  console.log(animals);
    -});

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });
    -

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index. It is recommended this behavior be disabled in production by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false);
    -// or
    -new Schema({..}, { autoIndex: false });
    -

    See also the Model#ensureIndexes method for more details.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    -  name: {
    -    first: String,
    -    last: String
    -  }
    -});
    -
    -var Person = mongoose.model('Person', personSchema);
    -
    -var bad = new Person({
    -    name: { first: 'Walter', last: 'White' }
    -});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    -  return this.name.first + ' ' + this.name.last;
    -});

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full); // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    -  var split = name.split(' ');
    -  this.name.first = split[0];
    -  this.name.last = split[1];
    -});
    -
    -...
    -
    -mad.name.full = 'Breaking Bad';
    -console.log(mad.name.first); // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    -
    -// or
    -
    -var schema = new Schema({..});
    -schema.set(option, value);
    -

    Valid options:

    - -

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false });
    -var Clock = db.model('Clock', schema);
    -Clock.ensureIndexes(callback);
    -

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 });

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });
    -

    option: collection

    Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Set this option if you need a different name for your collection.

    var dataSchema = new Schema({..}, { collection: 'data' });
    -

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    -var schema = new Schema({ name: String });
    -var Page = db.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p.id); // '50341373e894ad16347efe01'
    -
    -// disabled id
    -var schema = new Schema({ name: String }, { id: false });
    -var Page = db.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p.id); // undefined
    -

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    - -

    Pass this option during schema construction to prevent documents from getting an auto _id created.

    // default behavior
    -var schema = new Schema({ name: String });
    -var Page = db.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
    -
    -// disabled _id
    -var schema = new Schema({ name: String }, { _id: false });
    -var Page = db.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p); // { name: 'mongodb.org' }
    -

    option: read

    Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

    var schema = new Schema({..}, { read: 'primary' });            // also aliased as 'p'
    -var schema = new Schema({..}, { read: 'primaryPreferred' });   // aliased as 'pp'
    -var schema = new Schema({..}, { read: 'secondary' });          // aliased as 's'
    -var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp'
    -var schema = new Schema({..}, { read: 'nearest' });            // aliased as 'n'
    -

    The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'.

    - -

    The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

    - -

    NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

    // pings the replset members periodically to track network latency
    -// now `nearest` works as intended
    -var options = { replset: { strategy: 'ping' }};
    -mongoose.connect(uri, options);
    -
    -var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
    -mongoose.model('JellyBean', schema);
    -

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    -new Schema({ .. }, { safe: safe });
    -

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. -By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    - -

    NOTE: this setting overrides any setting specified by passing db options while creating a connection. To prevent this behavior and allow your db safe option to be honored, you must set this option to undefined on your schemas.

    - -

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
    -new Schema({ .. }, { safe: safe });
    -

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    -

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: strict

    The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.

    var thingSchema = new Schema({..})
    -var Thing = db.model('Thing', schemaSchema);
    -var thing = new Thing({ iAmNotInTheSchema: true });
    -thing.save(); // iAmNotInTheSchema is not saved to the db
    -
    -// set to false..
    -var thingSchema = new Schema({..}, { strict: false });
    -var thing = new Thing({ iAmNotInTheSchema: true });
    -thing.save(); // iAmNotInTheSchema is now saved to the db!!
    -

    This also affects the use of doc.set() to set a property value.

    var thingSchema = new Schema({..})
    -var Thing = db.model('Thing', schemaSchema);
    -var thing = new Thing;
    -thing.set('iAmNotInTheSchema', true);
    -thing.save(); // iAmNotInTheSchema is not saved to the db
    -

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = db.model('Thing');
    -var thing = new Thing(doc, true);  // enables strict mode
    -var thing = new Thing(doc, false); // disables strict mode
    -

    The strict option may also be set to "throw" which will cause errors to be produced instead of dropping the bad data.

    NOTE: do not set to false unless you have good reason.

    - -

    NOTE: in mongoose v2 the default was false.

    - -

    NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.

    var thingSchema = new Schema({..})
    -var Thing = db.model('Thing', schemaSchema);
    -var thing = new Thing;
    -thing.iAmNotInTheSchema = true;
    -thing.save(); // iAmNotInTheSchema is never saved to the db
    -

    option: toJSON

    Exactly the same as the toObject option but only applies when the documents toJSON method is called.

    var schema = new Schema({ name: String });
    -schema.path('name').get(function (v) {
    -  return v + ' is my name';
    -});
    -schema.set('toJSON', { getters: true, virtuals: false });
    -var M = mongoose.model('Person', schema);
    -var m = new M({ name: 'Max Headroom' });
    -console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
    -console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    -// since we know toJSON is called whenever a js object is stringified:
    -console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
    -

    To see all available toJSON/toObject options, read this.

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    - -

    To have all virtuals show up in your console.log output, set the toObject option to { getters: true }:

    var schema = new Schema({ name: String });
    -schema.path('name').get(function (v) {
    -  return v + ' is my name';
    -});
    -schema.set('toObject', { getters: true });
    -var M = mongoose.model('Person', schema);
    -var m = new M({ name: 'Max Headroom' });
    -console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    -

    To see all available toObject options, read this.

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    -var Thing = db.model('Thing', schema);
    -var thing = new Thing({ name: 'mongoose v3' });
    -thing.save(); // { __v: 0, name: 'mongoose v3' }
    -
    -// customized versionKey
    -new Schema({..}, { versionKey: '_somethingElse' })
    -var Thing = db.model('Thing', schema);
    -var thing = new Thing({ name: 'mongoose v3' });
    -thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    -

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false });
    -var Thing = db.model('Thing', schema);
    -var thing = new Thing({ name: 'no versioning please' });
    -thing.save(); // { name: 'no versioning please' }
    -
    -

    Next Up

    Now that we've covered Schemas, let's take a look at SchemaTypes.

    diff --git a/docs/3.4.x/docs/helpers/filters.js b/docs/3.4.x/docs/helpers/filters.js deleted file mode 100644 index 33546a7e805..00000000000 --- a/docs/3.4.x/docs/helpers/filters.js +++ /dev/null @@ -1,20 +0,0 @@ - -var hl = require('highlight.js') - -module.exports = exports = function (jade) { - // add highlighting filter to jade - - jade.filters.js = function (str) { - str = str.replace(/\\n/g, '\n'); - var ret = hl.highlight('javascript', str).value; - var code = '
    ' + ret.replace(/\n/g, '\\n') + '
    '; - return code; - } - - jade.filters.bash = function (str) { - var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; - var code = '
    ' + ret + '
    '; - return code - } - -} diff --git a/docs/3.4.x/docs/helpers/highlight.js b/docs/3.4.x/docs/helpers/highlight.js deleted file mode 100644 index 8aca9b9e222..00000000000 --- a/docs/3.4.x/docs/helpers/highlight.js +++ /dev/null @@ -1,11 +0,0 @@ - -var h = require('highlight.js') - -function hl (str) { - str = str.replace(/\\n/g, '\n'); - var ret = h.highlight('javascript', str).value; - var code = '
    ' + ret+ '
    '; - return code; -} - -module.exports = hl; diff --git a/docs/3.4.x/docs/helpers/href.js b/docs/3.4.x/docs/helpers/href.js deleted file mode 100644 index e7299b1cf0d..00000000000 --- a/docs/3.4.x/docs/helpers/href.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str, char) { - if ('string' != typeof str) return str; - return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); -} diff --git a/docs/3.4.x/docs/helpers/klass.js b/docs/3.4.x/docs/helpers/klass.js deleted file mode 100644 index 0c4a865b43b..00000000000 --- a/docs/3.4.x/docs/helpers/klass.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str) { - var parts = str.replace(/\.js$/, '').split('/'); - return parts.join('_'); -} diff --git a/docs/3.4.x/docs/helpers/linktype.js b/docs/3.4.x/docs/helpers/linktype.js deleted file mode 100644 index 997e740f671..00000000000 --- a/docs/3.4.x/docs/helpers/linktype.js +++ /dev/null @@ -1,50 +0,0 @@ - -var types = {}; -types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; -types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' -types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' -types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' -types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' -types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' -types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' -types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' -types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' -types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' - -// mongoose -types.ObjectId = '#types_objectid_ObjectId'; -types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; -types.MongooseArray = '#types_array_MongooseArray'; -types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; -types.Query = '#query-js'; -types.QueryStream = '#querystream_QueryStream'; -types.Document = '#document_Document'; -types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; -types.Document = '#document_Document'; -types.Model = '#model_Model'; -types.Connection = '#connection_Connection'; -types.Collection = '#collection_Collection'; -types.Schema = '#schema_Schema'; -types.Promise = '#promise_Promise'; -types.Mongoose = '#index_Mongoose'; -types.MongooseError = '#error_MongooseError'; -types.Type = '#schematype_SchemaType'; // ? -types.SchemaType = '#schematype_SchemaType'; -types.SchemaArray = '#schema_array_SchemaArray'; -types.Mixed = '#schema_mixed_Mixed'; -types.VirtualType = '#virtualtype_VirtualType'; -types.MongooseBuffer = '#types_buffer_MongooseBuffer'; -types.Buffer = 'http://nodejs.org/api/buffer.html'; - -module.exports= function (type) { - if (types[type]) { - return '' + type + ''; - } - return '' + type + ''; -} - -module.exports.types = types; -module.exports.type = function (str) { - if (types[str]) return types[str]; - return str; -} diff --git a/docs/3.4.x/docs/images/apps/attictv.png b/docs/3.4.x/docs/images/apps/attictv.png deleted file mode 100644 index 1327f0bd858cf6f002a077a9aafba1217ce38e9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42666 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 Cl*SPN diff --git a/docs/3.4.x/docs/images/apps/calllist.png b/docs/3.4.x/docs/images/apps/calllist.png deleted file mode 100644 index 824fa428eb2de2a237b37ada591cc7056d68f399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33502 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 $5C9j=SSd5$;KOc+eQQ2^5$rlF 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 diff --git a/docs/3.4.x/docs/images/apps/cldfy.png b/docs/3.4.x/docs/images/apps/cldfy.png deleted file mode 100644 index c44ca3525daa7b847ab2869d44a00ebae852646d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9773 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 AJOBUy diff --git a/docs/3.4.x/docs/images/apps/clickdummy.png b/docs/3.4.x/docs/images/apps/clickdummy.png deleted file mode 100644 index 773ce3ec638a72dd3eb7ab6d103dade3874fa53e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34210 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 O0000=x}o)VD=23xZGidKsJj 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

    &}XJ7y^uLKL|l(=^=~M7SI1ZoeQx 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

  • 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 Q6aWAK07*qoM6N<$g5iQW;Q#;t diff --git a/docs/3.4.x/docs/images/apps/furbabyrescue.png b/docs/3.4.x/docs/images/apps/furbabyrescue.png deleted file mode 100644 index 79dafc640738444c01883ac66e8f0f2584a45a57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49891 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 diff --git a/docs/3.4.x/docs/images/apps/geeklist.png b/docs/3.4.x/docs/images/apps/geeklist.png deleted file mode 100644 index c6579c12f6f37e10ab1a3f667e33f70fbdc87173..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27911 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 /dev/null - then - echo waiting for manual firefox shutdown... - fi - - while true; do - if ps ax | grep -v grep | grep firefox > /dev/null - then - sleep 1 - else - break - fi - done - echo firefox shutdown detected -} - -if test -z "$1" -then - while read line - do - func $line - done < urls -else - func $1 "$2" -fi - diff --git a/docs/3.4.x/docs/images/apps/growthegamegolf.png b/docs/3.4.x/docs/images/apps/growthegamegolf.png deleted file mode 100644 index a8d6e9fb7493ce38c487cb2f31416838fe063bb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43441 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 diff --git a/docs/3.4.x/docs/images/apps/h_learnboost.png b/docs/3.4.x/docs/images/apps/h_learnboost.png deleted file mode 100644 index 2940dc31489e2f0db0857ecf2c32a2dabb907b69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12727 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 diff --git a/docs/3.4.x/docs/images/apps/h_mcds.png b/docs/3.4.x/docs/images/apps/h_mcds.png deleted file mode 100644 index 1ac655377ad9e784895c1d0ac1e74d46d4949752..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3904 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 O0000D_X* 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 diff --git a/docs/3.4.x/docs/images/apps/kyyti.png b/docs/3.4.x/docs/images/apps/kyyti.png deleted file mode 100644 index f74d98da1346a95376b33f6bc6118e8864261b4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41966 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 ^!Ew8_;FrDA-Jwjzfp_2R2 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 diff --git a/docs/3.4.x/docs/images/apps/learnboost.png b/docs/3.4.x/docs/images/apps/learnboost.png deleted file mode 100644 index a6c33c8bd41f9806ab255e4afe5e0187c65810fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31434 zcmV)FK)=6=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81VslAEK~#9!?frMOW!HJw3I6sz`R12X zy-KJmBHVoxS(Bzx-|S z=}&)J(}OS!iJ}O@FtBYKtu;aj@}PB6Jbj)oGyHD2-j&+gsqEGCaizY8-=%F1|9dTc z1)@ZFMS8L4gKS*_A60H@hmo9Sg)JX!rd)pz%?Yudp z5U88j$Mv>3U4t4oAQDT|WPNpJHw4 z(rtwtSMyyrvfj1!aWi|l-u7?yxZX-&?)Fk^jbWO+`{O^(qo4Rm#%K4i5%_#>^%D12 zCYjuGkUJm!0NqxL&;Q=1Xf+$RWMjPzw?8PQ&{|`f<{NKp2hds*$1ze$;yA{#tZQx~ zj^pG&7}~eyZft{6ihJJiDDV4)zlkFaI_HjY6gaoC#6%b{*KT1|#<~B)pXA($V?6bx zzd%a4O#r%9!Dpv3S88Kand_bKn+f_R_i?@L-^g)AQM3&)u0;tk3`!;cCUR~1Oc4YD zwrvvxL53LD(od>vl0)3iF1(M%Efl%;iJwBc1)N|LYxQNe*3YuwdQ{F`#(Vj7DsB#UCGeJefrP6{#5rq&uM<<+%sS~!k_*;^l_6mcBi^aCJ@B7z_w z2m-<|!m=#X$ess5 zkbQp~$JsN>w$Uoi+Us_^_!$EE18t`Wylu{Q`Y5e5-sB8syn_41{|0&fIf^QxrrwF= z%<RfI@BYVY2?T)cRZ ziHQl8mX>fF2O$JUjvUF5rPJv!K0c1``!t(P#>dBrq6noF>+9>>bI&~-J9Z4;_jg?! ztu>b8@`)e+NgNgM%B!!j)o5bcF0Lhc{n+b-aXhlFG)zADk&iP`c6jCJQQ}x343oh3 zDV54hPES)`U**)P6BNegc=yA1^W2LsW0?kqX`*5UI_B7G#|Y!m8(3-0`#$_p_D)uL z{`)Tz#TviU#H&v7-bWwi+uwQ$>6DnCo#NQ5uO^EdMHEX_=BLLwcm6ELUOPrNj7Q1` zN@?En{txrOU58k@bcxevPg8HSD0nXC&YWaz^X9R?aU2sx5uou(D@Yp(<{EaiNzh)PvC*dftq$Skh*%o<_Z(trYmIKFlbsUjq*#`f zQIS%q#Knsjaa|Xs6wPLnnVA_((`0FBiH(g7W@l%KF%*=55^l7@?F3Zcygkd;(Q|C_8PPfb1^XGZw-h27T6MKl1!gR}=dg&Qnc;N+< z9$n9J3?|0Mn46hqVebJfQ=;M!q=RD!lwmMFHpXB4=^r91^W1yi1MJy%7%5^5Ltr{Z zMA+gt|M_old83_ezTc=SCi&dl@GFa0r_vBBi@6iT_&0u;bs>1_U;d9A|N56e2&Si}SzKJ?+_`fsEG)3Gu|c=n z#c>>5*TwgJOw&XN!G#MK*t2I3&1RG7>1mdimow7ZXf(1qtyYU52pAt9=luEe96WfC zG2AUb_dH4fTUa<PX9`QY;XKQL_1z!gFj+o_L*(AC5#ktzmXzWA9x;`Osj*`~PBh>@-{z{J!vrqD>kBn$!+n!pbd3SnDVriJU+ zG@4Bu$D!41(CH?Jw&O}Z@(bhaxx?l7_uG8!(;LK*&c^CE4xLUX>#I^5qg*Ty$BI(9 z!XuBogRlLEFVg777!m?Mpw(^z2~~4l_v#S?t?|YtdF=21Qzqy4aPg@xGFIEfRliAj zYLb=Zze>APr!n`<2Z{J+Egh5v*DPy7_Ft`i*p97g#=>_74!(Qdan{_In{ z`0xK$I`z#=U6AiM{k_{J9)6dvGhF{_+S{p*>*1y44z`&%Rs-)wee*CvT3vUO@?8Nth2iv1Gx0;lepz7`r|*(*z_#2 z@?)st2iaWT;L`I?@zS4siu%%pz7FkecpFF%qf)8d689Q_QmJ&^o(?0QKmPdRS8PoP zL3wVGi9`3{lw4vzV)M*#HqIU=^8M{-d>g>^vIRGiop`hQxShZKtpeiXKk{Q*Yeix@ z8HFRsbFFnE$%%wlgJB24eEr?q%6^N%HzNnQ6GjjG5Zj(hDN)&Xjc#9v?Qar!L2c_v z40n+InSRsgj~UhP_6?XXrAPcd8Z;xSX^>K&l+H@%9V!jK6=F1Eqe>;hc z;0Ol&brQLtxA{_yj_B7(%ceDC(m=1B!M0^j#z>JtpbKjYg+?yeEiiP3Ab5TE6wr z-zwLCzP`%ZNFJ(ueUVzL`}H8{OY7XY2Kps8*50$BZ%l-9woTZM`!w78+mT^ZTiF_Z zdm|n?4w3;6o|A*vFzEZ<*TM|KFgE4~)PI#BLXH|`$bimmHl1y%{>JNVNS$u}!QS%E zG6WL3-*$>%x$=EP7;LAH2)SniZ4dR``$myNko>W}Z7HvC(CKY|r<$yOT|HF3zo~|v zr^rKpqw8$*BCkU9!4rMPu~6{D%I1R(MJTO`}2Hd38H_f zDV2B&BxC5$)lOW0o=$7P95v-hsl19Xsid;Kn>@%=Yr8CEI+z3*a;H~1$h7esi#9OS z6zMXAPsf$ccps6|?baK058)WtsUm-Rh}_uqAi@q%xc*QEPyZoKVsKnT)4A>BO2?4j zu?#*Nu99E>;oUy8e1pZ)&CbX=`RVPmO}X+qH=iO~*<4%s0qcI7dc=X=qz8}7Yy;_R zF>(jO;3|m0(>!f!keVbjHcUMvdZ1qaG}lR+IhLe<;`b>|(pHX&{R}T?vFWpA(BlZdYH6r83(9}$UPdO=nNx=?(d1A9hN?l^w&IYMf!Z;{L>j_$tXkiUMFR9hcg3p$ykMK|Ija!SCWdft%QLdptb{h z9?|=)x2tQjMb+D}%s}I}J4A6}c*+$Xp1%=@Ik+lf+qrSa`}ueTn=aSOlkFEGWc z1B-oC)aNY;nkb&aF8>1zV-}?~GVe~*lc&jP9RbWdpL@k^Eje`%@kA8LMcBe#2{(ObiVW(dOM8u_68v& z!-`}n4f-0B8@GN!Kos?~I;jHYw%H$|XR|VTepLoS3Urq7W>Dj(bx&QJs>`ILPg8YY z7P5+lwY1iMju}rc(3_1F6|F{jF}$ zmtVnRylor+@ejVEoDfhQdw{K$N5}>U3)^roC5Rj62@WJ|)8auF9h5kKYK3CGOS9z> zg%$2R;&JwD7a735yKF9=i_j{G1BoL=96=nKY;-;Dy4&N_b20b4BTQ^qH)<{b#|7K% z?_eoGNWINYnlhMX`dp>KA!$qb3i|5z-|*^)P8;jHFJirT91%psi*p3;eu#K+`i*~a z93z4V?bw6h*Vb^q{B4jn{zudMaQq9fc~-IS zZjbMOcasxG6^ln|NV#$omPUi_%M@tU^T5!9c8ngFeV2{Am1Us0tkN|NRtQ9^LGibK z7w@T8Fz!AG6%YOCFA{v^8S4M|*NLa9eG{pm=XEA>yj|~^$URGaQ>4Ux?KQmL{W8tJ z`zyqA)j>*-uOkJfR+L^oihAxG;luY6Pn79fc<58HZG8=mDeoJTH=CvuQ0C@Q<$N9F zfGIW^s}Oy`ZkxYGs!q)L&*aB&6;w|e7M055EU$eX%L+-{CT={n)Jk*UT`lGhO(TpD zySPQv_4xi*Yxs=<^M~6!_--F$#Nr_nv}WpXlOLOzO{QIJv3zlw$385n&Ro7ZF&vrS zNlyc-bwZWIXeq%QRvhRd2RD&x_nJTm?5{qB_v8!2zy3Gb`skx5%f$QEcPRYv*DyOB z%rCr%Z2E+EAHY0zitv$#&?3Tl@@eFHlj#1t2p+o+(QaXV>v_ym7tpmD{)gX<_9V_1 zzKQj{m+}7iOLTwY{X~1FvrQydSFxXb8sqW?@!|r(haRQziN`5?|9|fxZ43L`&ttxR z7F{S3eBe={eY42*b?mP_jd5{}c;6zy2i}DiG4|J=#yoWiH9LdA9xq>{3K|N`T7a$Z$6Lcgvob3dLLqI6X(fiP-A1L z@gmmKFQfMFBRsNz{q<)M!ovUP+k{M18$7>mH9N|2B6t#CB^$)z0$S@#` zXy1Py@sT6Mu1)3SX^cO9l6ZOyt5BpdJ&F16Ka1N1u{cirKmRt3zx%6*S(oZxeg|eJ z(ckzo=J88(|JIM7V>7yvq&5;RV!}pQ63lB|KP8KNM?i zmFkzig`6Bmedh&&7fw?DNB=4AAAOGEpFfLy>>l)|{+MQ=gla5N`u~0w)-qts#e8xELy)-#s2i?D175(j0X;(pZPw)SDvBq-~OkF^-Glh$!}xT#t>r# z;xBxI*3bVq(T5+P{HJBukb(Wk$Pnw`Wh*r?-Yky`<+|HDsE_}71k_tFLA z1N%|`%kR^e7^nNt9lKHvfgtFvqTA(>;gRpsSyQJLMgf! z-i6!-yBT9s+gYg|t&mdYdQ6^~AbQk)5NrCzkNi-t9y5eiNIyi`HnEf-1wUDWV_!Akm&NoM&Ff`_^+b|K4Ar{c|5h zUtY&PdoDSVOJg)Y@i>K7mT3IVpTpljnQRh6Vmlcw*Z7e%Eh1>fVu^+q>?%9j^%w?p2&g=~4gGbPJ9i}=x7 zvf@|HI5|AVUbTKJxp<6`R}UyfEDVJ1=a3RTmU5uoj6$T^>>R(O=(z*uT(WiM-F5Yt ztW67jXbimWjIXN_IesDkKf{H{=JnExBesha{!J!N& z+YzJBT4f;)Ls@4sPAAO*GqB?Ye%RvW)&DnLeIAio`?bnGLG>~{>fSsE(s&F_#yW}o z0EY#PYou`g$KHqY_2()6KmRrIXP!V!Rq3p6QBVS585n0Tf*-==HAKrt-?0x-^XP80 z@gI8tj9lP)80T)fe!7 z=g$yNybJTS6X-pA(YA%?b}(N%f&KE!2xZcE{9)|>{WF;DHsK8wW_s{<=-gjR{EmooJqgOW&TP@VyJ&36i&hLE&6}B;-dl7TB zN%x)iB9;o+zx@TgfB!|Ixhl?|eie=!KzkO(`O9cOK%QSFo-cz^hzrYzRyUc%%{u0Z z(^$Xrr?lSrPK=-V5Y9jQ-*8?#OL*`89p_#M$=1g6gu!u4Gw!AG(HJtqF>4f@Ni>=u zR&)b3;O;H7&e-YUj4gfky1%LWQF}RMM9yVa00qaulrkeGDvpS|9ds`psn#GJ2Vo4! zO=-%TZ2Jv(_mQ$f84~HlZK)pzBaqk-K^zB2VIqV?N2+J}&bh7UwtX%hBTs_zF5gL< z0Qwqb45jHVE@J*S{|Uw4|8tx_{)=R)O9kRz{z;;J)095-B-YF%#?ja5t~^d~$3cSs z{1++w;g|7#^EjeZq_bxa>Z9++{hiNK`Rz|54(vsQXDPmLl*W(07ySz#ru6L>;T?C; zoEihA@bA70@9+Lqihul<6n^V9M5RpUzyUgk?!b8LPKw`ujo^KcV4hs2@~{604$dR? zbtoP^fxhn!?9Y7*^^`*1eT44E9z|R}NAdT+gnId9#Pkfok3UZFxtFkO74+Hj_~(}C z-nEGT_x}ck-~Al!zx+Lf>k|F#U!?Qs-H6}-PNPHROHZOB1qb)j`qiI7wCfa)ok7l2 zDLnlWjh}uW@{R?(V<+gY)RBv`*ymosJ-LK=?*ZJu_z%fmd;FcmkKNtRbUXsIj)_8r z>pYRfa>s473Qt_R9%5-2sYX=o}mV`-+4Eoow%f7%}!<$=9|+oVGBOlyq}x~#Q*gfuXu zOfd6GASG55VmF$ISP>NpgawyaX`F5s87s691g?vc0wD!XtA*L=5*G^io`=>NuhB?Y zmvRxK(?yvkf#YCkh28EDSvH}S`_QzVc9*DFAn-gCV21%Rj0ijrr`1G8ilAJ=@O`v2 z2t5a<)xziogvA1Zo460StrkYdCn_dmvbtT2D4G1gb%_lLQsQ(wSdAviap{&zN%*D^ z7+T@f>q&o=3W04RqZqr}MQBilL1-cEDykKx@t4`S4zT;vI7dVhG9l zcfLaV9*VWzE8bgr%`WUmh(I+YL!Z*f@zwxJ00RE&e%UcjCiRY(UvwRp8hv{>ns0^!}t9tAOD&E3Ab3w zFh4(?WVf=lp>S{L9LdZC88%Z`d-d2KILtdrdueY3q?}04$!Jp zvT{MOm^{~-SV-EXV%BCh?tymt?FXg>mJM3dE>{wEKx=|R0fELidx2bkCBSsX&#&w;j5Z?%;EsI32XAwf=LZQBu+=4vw!|Ec85~HOg@a zT(>_5)oQ=&Rj6Gv0aO4@)s)@d$ZMs>Oby*nV!o;k}Gzw|{4UV&D-g<%*x`skxvym*mTvqcys<+RdC zwnHO9k{|t%A7ydxB2gG^6X=CB66ZmonV!Fg_kH{y;uXhswCkAJ#AR{@nK^zKLEZ?A z)SvGZFFxYANO@QzS>T?Q0Q;F2FppoR^D`eoTRm^ml#(euP%kme0n)%cc?#z%&(rzo zkD|s331UeoJo_TvzxfQo``^vhKm666K&JYLm$n7Tv()=CXZXuDu9Q8#TlL3srFj|p z_Wb)BZiCPeG`85dbb%LNJIBkfo}#n5f){w0mc@6UZ}aLg8$XP(OoOf;(e^`Lc~vu0 zE8^M)-7v=L%}3muUjan1qTLM%wpwTsAFVuRB7v>7RVw=r6C-KY8-#v9;0H`hOz^=E zd=STRh~fxC8dR%QO2tx^-ChVmr_dlfuCGCVB02rFYx}{7D|)6 z@8kcFiJ8NwIL?OQsA7ZPHdHNzqgXr*n)OZ=WvWC30hMt~4$00_ui}k{bcz^O`;)QvF$L>Z|iiuqG zi4S0Z<5@)4$2@)tv9w0Ke=#xC34v%fF<(242%@C@i3-NavxrWBnx96ltfD3-Q6(4i z_0!1pI%;vAXz%QsJAWfUYt8;imwTp7UVZHZRoUU*S%=D46|;A1uhyD^o!qNY_Dss2 znF+pr5G6F_YmU6XV^ORI_923n3hXm*lgA7 zpcK>7)7y4jZES2?-r0pcd$I)KQ5;imG|*aOS!U+`-p>-EIC$5`C{-tWc8si{f$&;% z??$C<3I%d*BIJ}(Zx(I{f!tiD^gsP8+~o!k<1g$b{IPf8KJzMiqfPCPzChFa5!~PX zQ>@Jny3xSjyPw8?{U75VJx1|2|A2665)pJTXQyF(9o=eE{nIbdoE@X}z#-6@$h3$p z6Z6HRR8O5kuGI-=W~u+9{~YZ=@t^%R-uX2!An+03k41E$ox$iQfGf>aio(OB-|_ybu3_ z@4)=dDLQ}uR|v)mn1Agjh$4mY-Dj}=>}kxiD+G_f3+Ksau)g+v^nd(wbe?zw@!ShI z|DVs&`t@JIKQuqIVKqVtqQCRYM4QW4|MMSUU08*sQ@GE(M)_;g*`7F-TCeh#f6)7B_u5`zlu3val^H zmxw@T|K{x&X}zos@`k-ZyD{7T5}8bs&t`6T1=8&6Ni(BQ-YY%NUvD?+ZtqbB%zOr! z{Ju|Bz*#bc4D)3l`*uprc*{X4;+a|0ul*F(=e|jF^cdX_KThB{n3jbh4LYR~;?gDf z-#(8MDujrVR4%b1vTY*Mz&N;%t)KibLB+#;*~S)|d- zO2siDj*%h+JL8{f>{k>kinr zr)M8{^ARI|UD>dZI_m0yD`l9^Z^ltq78r&k^t+rndxmDK!`#ANW~V2zG3<1!Q97Qq z@7)k&z`!?TFwCbN&E#l?j1pon>!Fzs&dB}Ds@@KGft1MOrwPw)5d0s173Ygz!TEzf z$AAAj!Lbl)Ygi}FVSWF5I4_^2`;UJeUico)i)Rp>E~4ur{19c?s3=YZVar6cn^;Fr z5>J=Wc5<}W?L&eXF(5|gsvX*3urpE&Z`k3@o8CcEuW$0|tFM9S zaPZKP+&I+0rrxRDQINk!WB6IVu2Q)JNu=h%+&3g0lIAeeSzf7}F|)sLI!_62hQs4E zfngdHzV`y*b4L+D7x~~_=gV?M^p>6-*aE0wfO2cu}&|8xrO`mD@1c1(v%cG z`6WbBe4f(xd3hk;R{DFVHb=FU-~6K}SNhHmBVKMQ+L(;FCYD?1tDgpTnC`oh ze0MWSz0xxhGcdTcz5wOFd5F=QjecNHJ_u+aXh>u>1)X|bYMlwaVyK?Z+a1zpLuIv0 z?H0M9C6NUEh+fcC=784o*8y^N41HT@qaZluZkwh?g3gHU{Ia zh2grr1QEUZsjEqjLo!nbs($dE9`K17#;G?Iw1!cFT7F~iU=S1W4hF_i2DYKHVn}0^ zTEnyXP-^tt+$PAd8+2NAzVVHxFieL^twt0?OiWD@w3@_1qEtv21URnC%=|nvlatA} z@4`xD^ES*50q4)0qUFaZ72|gUoI(LxD7v9S>4>1y!EzjG6BF!TTpWoAyRmxd`$6iF zU%kGDweRnkY;>7ZJee6mNLj9-eUh=+uloi0-|v&ogdLeOe7n4Ozp zz1d`=zJXILVPUYovCj0|{5Bb5CsrnXH~6V1;h8!P4bRNY}-+ z9M(6MD3mJ$D&BlwDK*>alG5#nI&{z_FM6W$c7#KNczQF+X|4NJ^DgMAAHE8@tiGA7 z)Z6feA(1gcDy{>7@B7BJ=giaK@0Tu3?6<8}D=C{<|+mSrJ?pxfJS)9GYaC!3~;=Xp2v>+1FTz*W`T^BN3>8ug8sx`zuQ=R`;! zIdra4c3A8nP+c$N4L6ymr;0(yYm#LK?%94bAa$wf3FHHTUbiV^C$Ul(hC#9C;d`?{ zDV0$Q*L5ir3OBXCR;xAe_np0@r(@!yf*Mqc| zPT_ZbD)alPPEN9Zd6~G=K${*D3-cI;K@2OHm|*MtDctdS_T7I!r=R@> z8Vl2L(A_phvBKK9lX#{@{n8nnQW;@8Nep!uP%4$!+}NZ#J<0Ofb5zI2=+w8UEZ)iV zOpVhozKG@8iC>jaXkid*!NmL?I_v8!Jn%4UufN2lvuE(CQ*gAh2qc{dp7ZrvS zCZ_S%m+5pnEZqArD<@v2>kC}hM1=vBeMhL(O1$#*uV6bCaSUE{jLC%smR^0C^4vbw z&%Tc7dQ|rugw{IsdWX{F1nre2f+)r-mhkJFOy2bnQws|>gc_xeb;CmKP2Zlkh>~vq zmOLu-gmIC(mM*;pAm;!n`{4^ZE0~TyldW}1g5Jn*70ahiFflbng(8!%jCX;teihfYjcav+66W*U7$2QkB9@dmM>B)l`wVu zMkasT#*srBpPLQ0vaemo(fe0IriRUIUGz<2Wq=8p1v3~kE(|h*PTwlg1 zln`1`oS0yrurY+ftxeHbIzw%892 z@ws_6&Y#6`9aI!zm?n;6;ubwh#S%fYPHA$6(%2@k5-c2=W8=a(EYm?n5w(eFbSFUT zh{oj=W)9zjjv`8)hgYf~WEaEG`0*xYZ34qI(S-uGSD;$-5OF|da+cEAI4dWQqOAh^ z@4lDT#wKp5azmM))VLSNF~0BL)J+?PVbZ5gLQ&ITqniavDJ;v%X{rX_XNSKSmOsek zMe)p5a-DG^jE%5(=YGdQm(|wwt7}tR{Ii1r;w=9YwwXz|4c|pcXNe}(w)qD6IByJ}52qnT!PK;@t;WEQEi}d|YPLOio;+J%6d9%d!jc%rU zCrxXWcgY>hMmXrlaxKu_+5jO@afCDsf^HYDSSD6+VmA?zu-n0MJltY|#`-Ecj@dkW zoUsFUqvHs-QX^*jU5zN~o|)94qP<&Z4XW6AKGCu0wNU z4YypwkkH)P!Vrp;b4wg}$2%~j5@De0G8E#yV4njt~Yxl5Z)FsZ7q$ZEO%LL3MKK4V#nlmf<)Ixwy1Mp&mR5$m9x{BNZv} zFjJS0zW>M&UzYh$aa|-s2*K9b*J(65M4cvv<5DgaS#EYPZHw~cIGt|9@`aN zbz!h|=^~b6Vb~saX^aE!dW81M1une&619DIuyXPk<%vmFy)wdY5p~)qrRZ!fbNaha zQJkDjHfD8~| zNW2-986$hdnP-);i^zvyi`>qiV{(U(Z3Mfyo0$*t~p!+Wg+c z4WLj)2uU3JtSv3kX|=J-6O<;WQ9%c7xwuo)pkgkcK0z2ow6?Y=6f3kgHt>p7x{U@g zCe@jFw2;VR8P(iEOB><1=qRK#InCJ23}Xw67_m>}`>b8OKpY2jT1|@MlT;S=&|FsMO{xp~>1?hLG@Dq35>XgZT|9^(HCty-AWR3lSRiQB z6T_PALL4G(4^-4k+yz#thKRegH#Vru@1?u3OcW^!wHlqRI&P_mMxp{AZ)%S2>Lt33 zI)>w-mBt&NAZRsFL5HyGQ<~q8WgFDbpTVh&5qDd}D#>kX6e~!b+%wVHSi>8i#W109 zd5O~WJdxi;nikI3B;nRFE2mCSon0jEHtDun6sH!@VH>kJhT|A4AAgO~>|QE!^RzCX zqq(+@ien7RL|QIV$4J{w^L2H3C zF_qavl-Akrw41y&y4Pvn5HsZGpCNOeA5AAQoxr?WieCIg>ieI4Yubm%CWstKCJnC1 zorpUvO#Y+OYo7;VmeWgcQr@=bZ<8#b9Q4^q7q~x-03$DWo<1y**H=j~KS=4fs)Ivz=Q)(=?3%;X7?Oj#Y+Kf?=9+ z4WPjppY9JhC&Ul_PBwqvqgQ6ZKw2x7j=x4}YL;T9LV62nYL!nhIh&`x1I&PSN%XW{ zO6P)85U41`Z+Eam~` zY9@DeZXX26vnULarkSXMcbVcFYQxCf&XZR2o~Umo)J2s|QrZzD~eQgcPaREhVV*^9N%H?Ior)F4Ry3F{VJxm=qgrOB1 zm(DUazZbt%XZ73}yxJt%ZxLZ&TL!Iq1Isk<{Vra09GdI2S611)a0YSjL$p?w@W!Sv zBsA7msLU+T-C9E_&E+$v+5gaER3^r5Va&^RZPD#OF<^Iv_sSr4B5(m7n{~-V1pZs%d$013rF19yzqbDSe**JNWW6!_Hp?80fvoAbD zZDO4DOXrFG4wYIhu^I@?>1V!37{e*Bbj+qyEVFXr7^Y?6cSD5KTzJ`_xwJ%W zVJ}g)MYrp7$0HwPYHFO-*I%L0*upK8nV6m>h`Pxf6beZ;&&De4tw}25HLU6whGlZ< zxn~IKbsCp1|zyftVY;r5eHpbmoIYqx$h8ky4b}srE-Dh))rcY1YIAuI*u?+ z3KP>vL(p7XMM(>{P^RFyY_6|j+Af8H&HCCJj^|M*RSCL2Ua?4hb(v1Re#_!rM#XF2 zF0fO8(r$K)eBDvccgFpcm&%)-6Kz%Qehk$UhzEl>`VHL7>Cl*Nkw<^x7m35f2&k08 zbY1q||4wuq5l0b*SHiGe-u>f0i($KHl{nTJwnNa^#41$KD(qptMp`yutAQ4RW8eKc zcR%_#PO*Seii3~5AB2I9BZQO`N)-&pCGK`Wnix)^4U(40kq6(I*d9s`5_K9Fw#UrD zpzj7^+MwnTrp3hE94ZJNu4#!gd2;*cg^c9EM2Sxn-8t*wFgyDJv@Wzx281Y&8e@qK^5m1DU5osz2Urm;%**Wlm>zacG>MJ}d@ zVVX8`volzRU}!9BX_PR?eJ9ItTYGosiR?zPr9le5`8x|2y- zN~<=R^<%o+Lir-^b`GxV?wSd3Cl+Ox_s^HzDI?%;nc++%wrvkQ%Ui^U`?-?e)L_5E z&S`oZbQlHpDa?mG^xe%x?wwAvohO)@xIK(oxMAz-%>)6|!+;Z=27$i$3Cqfc z$sL6XwoHs%1{%+}HE8K8O`yar$B_I+_DWSAeeB(YK^LWaES6G9B5f%#r9lvMFm0D0 z2zF$NuH-&4EXRyOl$2fDNtPKl;0+_>sJf6Kh#^QKSTmc37&z$D$D&s*%M#LPZzaL^ zBb2@(FPYrzMFXB~Zt(e_g}Mb4%2SHJDI`ZqHDaZhb|w4E&Mo=Y^=`zmMwrs%TLyWT zi7<+A90$jB2O~Fg@}BFtSv|P=Afn;2qo_mvneY49wvAyJ*~Z_=?R+P#)F}TcDd1q$ zCX^PPNYRBs?d!nYBsM)0G}5r}3Pm1#@BzN_+>2QNM;^JfzA+JGR|5^DXaT9C!T^$A z?c#HFWg|45oV$iOB1q|GfJpn|){AlZ4Q!ewV`F2tcm$(iYio-z3^8(v*xsnydFuP- zn1YIHvEB{o#(+qpKL?$q`quymK^*y9ymXP%ufIaa4>O0ltj;Z$TQ#Z|TdDy^2uva9 zYDJLQT6*eG1~EU4)iQ)2(u2Axkt>s_qlfa)YTZj*oU60*C|PZ$Kb@}7M3XqBTcnna%8^5 zcTa3EUb6ZAxjLd%@$_`gi7JZicKj|fD23;k{4o4lSHXtDa}xl|AfU+ zusGqNkBs412CZ(Coi?Tv%#XXcmc)>Pg>knR5TlqMcNr_$+_$$v#WPu{`$TaVjH}lL+H{h@n-kUj|6m~NR4v&AQ=Xqq3LSW=V6Z&yV8B?9>8%z*%J8jlC z>nyLX4Y+=!Lim7ua%-jtrTY;g4dAIL*}f$-=eO##rNNVNoEum_1^m7+vNI0BEMFPS#cGwsPlu2@TARxkGiyf|K4Xijm3~ zsh)phVz3|YL>m<*-C6hhK&ZSi}* z_q)BwseX8y6apxp-Y;~wtkdL#JIeM?bZ#zN3q2=?m}yUse3%OR3Zyf8t5R+RmrVc zLk&#W4xe;pZ+>Szh;x$|XbAM1FNoe;7_?*Lo%ix?6lq$V@$vC2E`0k*KFp_I8x>4l zMcVClcDvI~2EO5RJ1JZ-f^S5>>9~hSn;QJgU;97(mkFtnGKu-tP^?t4RFnBEA-9V1 zCw%_xsbl{^fOKOirHG@D&8-HNN*S#ZrAIzk$S_O{DS7dG&k|s9_|Sfgo*z}W-Q?os zRrc@OmxMqIL7`C0G@Dlfr4-F(lTN3@>gp;By=xAx77vq^;Jj)Qlww7krN z4?j$~;3A~Nb!^sGHu%Fo_yfwt0_|qN;=x7MSC@GDTi-@W$>RPy_`v($bJd6;gy7Pp zOB_3PjD7p|4U8}U`;ABN<-Wc5pOM`Z28iu$CuS7Ixn#j&0EO}ir*5??_}g&vARobJ zm^OR%?4i}zVr+5_$CMNbE{GW0GD#1^`Nh4AP0cVlUL^>+Xk}8U6uJAZJ83ss_))~n z+&rFr^@$zQ`~U8_=bmlhwdpu-Oa$M+Q!-zpVc(q`buiPygN+WyC%jE5-YRgVl}a7w z65&%*s#GbKD=;@pmb4C-nVU!T60${6M5$V%T!rbGncdsJ1{OGuFMb#+1hYh zZ#aT4&u-<8cQNpzf29NnOqrRfM!DNDpz3;?mAd^PT@eXbQs5W@TPFV*xp37OO%Q9s zP$7Emi=(trX`3mFVwxtKo15DN-m4zp4nasM)M~YXa>L=X*Au~)KF@v+)lcYU-@!2d zoZdULr_9alUj3S)Cz0f9zRgPAE|7Q-L&22PY=ep=aSeeXM;v24$x;AOD4-K<6PvvF;`99U zNA728qKIiGS2o9SjM9oQh_FnPSSiZo5@8S!D}|H>S}VdZ%+l~kDe${Nrt*zdOcX{~ zww?WZk8$q8c^3EWr@gt(^4bQ4Vu^OA zjcHq0QW7fIzqp6jUq6<3S!jdWcoo0ZC5U~5Au*+i-|bSVPB1Z1=EC_U{IH8wNpk7g zJ$t$9(7_!k%C$!DZC|^DN@NrRJ%k(?#pvJd-G7nIWa3PSc*BXE->RTV1Y6e-6ii9c zOn7-m%FI(!0in`#V?{esw4&s9Jj$Q(I$**v*jKVJr6AUc2bs~688V|(_TR9JLvQo+ zLOHd7G%bPBFjcep`S%?`N=dD3VVbj`G_!LHL{XF&_za0*7);JgVLL8jZkD}4khIae zAvO7}@jRDWtxBvE2uZ~q zs+PntdYYbHKxqh+rV+-hc4Jokh;FQR9MdSs_b}&~>?vAk(f9F55h4xIO(}&KQNQ1p z=plwc_TAYSRqKV9j5PwH?foJN9PR6 z>4wfM)WgEQOy!>*6PY4`0IkKq4NtpmiV=7N^jN9g7A+$=Z!!5I{RUeK%9f;N8I*dP z+w4tptTn#UG(*K!7*h`vzS5XNFzp#E7A(q^!L{7lEJZ?HT*GA2HEBl{7uz8h+Y!F% z^RFrO@p{OnNz&=GBSkY*1WGgOnJkv9EdE2LaRoi&T#6uKK>i!z#fR2Yi=JFUPGBBV z(+`(G#0*K?}Ytr{< zO{G|1yy%R~0+KyQHQ9Rm90^2U_!b%I%6(XGW;25E7C{aTc!prcGnsKsN|xO9q@Q+^ zlfD%xR{e;AA(?W`YeI-oAb_GNIb3m=bWKh-0t_jbat*v*oTcvZ{%P=#AYseek)mQH z!MzDm^btbRLx>!;fSr{idE;&xN1sBYzC{peYSnUf2eh(>@=4n3$Ic`#b%De2t*{v zPJ`S+E0tV)B#hn#NJ`2~V>Bl@EzC9-b? zypRHBJ(Imfo3eHF7dc7+WlK`F?5nPGEih&qcr}-d@&b#wRMAJ9i$_u&9lXQE-ZY@%b`ur>PpUMPxlx-FY)*C+UZ!~mcMLSMHW(7GOR^&Eq@BdR?-{>KM z%&5emJTcO}VaK`a8NE{WL?i~ishL?U$3r7AO@p!Vaa`BIG7J>ZuGiUYw1^Z;j89++ zNxRd<@d}LBDuiK(S1e=8Dvef$TCIxb772VG({ZR(Y#z`MD5w?WR^9-7rX-HAG^( z%G?=93|E0l{@Y2*ld?{CRvo6@tH04S<*C!))`Zo_ZNM7@omkO{6A?c}h~XZ#X_tiP z3D*qdLlRe{7*~eW;H8yfd}5NZ@reNo^nh((W;#jVDh-5ya=F6%!XA(kW5|7DVk)UK zHa2*XO`DxMYLmu1ooFKrmg}hLZ#`%Nj5`0G*HpgE@(8N)&x-^fI3o8FeLU> z@Mg&zBv~dB7Y$9QQ*YKmSs~xr;K`q7eERR?kaFaWQncMp>Ore=|Jktb(@x>B`SiE`LQJdYv^np7uO%rLP?&oqOwUAQcc*(^;J89Z-6P{bW{$@7&4~I&o zLbn(UR7yAWq-QejniR~0?NK`6qqjoEnjh2YrMuZ_NHxpgaMfnazP77$T|=_JWHaHI z9IN{nLa?V`?YdDkeI7rRmr{ftME2xuNd{a(r?n-+`ugshYR49 zt0ebDYN9a8cif++p08B9vBhNB${j8{Q=)+loj$lm=QUWRJfy zOe;BPWa0%Zq-3#JU~$atZ~Rg7Jp5hcm?Ev&#((TI@mg!Dj=`Ryn{C9MpkPW4RT7@x zmIBw1g8}n5Xn`FgIZst?gT}emB?+sAAd5{%1=?+Po00$NOx>pt_)25M3eS)Pv7+0P zQBo~a%Kzu(iD8>VU&h#3b{VynHyR;!Vu6zWw;S+a(0g^K6gj)Kd!@0|DrFwMrZ6Y@qUKxs`Uj?ubr2-~LC%x_luh?4)NfpO^My%xIf zLnFup^2}hAYe(iH9sAlQF|z%ujb|C2pHa5gH#+yXLlWnKLurJz?nXnbG~Gxc#FZ63 zSB)4_2-;e3e7%lwm80LTcpLrfdfH0anW3#XQpYbww6%*gwaZ`q26k$DxQ}bu%r|nr zb{+rFJ8=zVuQaaR#yhf~)I2Z(QLm+~E6tN2iCzq(iD_T?V842b0hpFWBqhO{dE?0q z262VIN4^tRQRXW8)$C3M^oVj-f?dlFy2Fin1=slQtpsTd`_(`%9^>lc19l3Ie=CEy z%4gf&-#`Sp-uHRfsoX#^y=$p=mHobzV5b9V_*=~@u>_2$U|nffyhY)vsKqWX^OHR4 z_pO3$tctionJcyN0|FXNkYjcRZw1gjAGU(hY$yeCcLDsG zC`R6GKni))>c_X?c7q?jg;QE1mFkh4E7P27LW}{UnYcZ4;cvsWf!3NRXafFDCHTQZ z9F3-cG@YxLrLVn{AGAsP;R2;Joz_WQ`y3x7qAXngxsYM*!y@){!W-iGT1g_LRR!w|?Aq`v8h zaW(GfHx{m~uN%G#8{hmMOaJD}So;=efA?wpI_&xNpC?{hWAm%e;T+me<qzJZ@!FsWRdoZ$FTOyV|tR#sf(yiMD@du5MI1M`{i>KAG?oeX^C*PMfGEk zVbzLne9%8+(2Gc67%`HB92$g7e8qON)8umB_A|@$efS2``RMF@3Tx|aN<|ynzEua| zwITWq9hD9P8s9yNQM74%=M_v#VpNI?{rt-`o!1D_!G%kd-}ex$XI^0QOV1*U4sv3g@sB)o zizfC58^SPRYpYAaG4Vr1vFy-k2S~%fkPt=+A)wOqP{ioG_$vNtn~9(M z5Sw5A9+h|Bg<7qn!Ke$^0IVm5XhpCs-UWadElH zzQr=f+MCQymT5PAX6LHROt=_^fg)z#o^k&8&(1UV#55b1JGjLvmzOpvmp%3_*0^wf zi_>Q}xckUBtyY)kzkiX*$r86tnR9LZh@*A?s_2;3nj(t1f{hd+GxA+8Xy2#t>`^c* zN)H`DI#+*p+uLyc5XXvU{S}JtdGb+mmoGKgXlg1B96#G&@7@}hF4dWxud=?}Kv*V@ z38rO&fGCLYN-le6Eq?d+o@U?S1I$mCXf}Kt&&H4t#Tv&@Y&Byn%cN4XIk2}#9L1bI zv(C&+g;L4B>Ha55K_@suvAmCN9C5xA!xjAf-ZT}Ea2zU+KlEmG|3eOgtdvGGJy&H$ z08z}sVht_f!2SwaYYy()Ik2f!Z)4al_uf0h?6`%}J2`C#Ac=l7Oq0Whr~5ZJ-2ztX zT5<1f-RKW3`fn-5Ac zc*o>bz%50LQ0XlB^0h)7g{-Zw<9bCZ<t;Vpq2SDUXW2RD6Z#5%c%B zPQbo>dwK2XQI5X)D&Kmv zNEQk$qTORfuRNsdtCxW!xd&-`1GlA&5h{&DP_nOI`yiyGT5>sc`V5VFow@x7D7zMy zM3T`u3In8RQmIr>BQc;y6SI1KTp``aX{1(CKt26pI9Y7t40gaYPtv z3a*>nas309(BWD@3b4#k{E|Q^6DbXp>R;I@R2O&Uv&fC3gtI?}xZ|&584jQcXwzsP zBlycY;$Z{*LJY1zSR|V~0vwSbgwW9Lbz2}IHsb;zA^wI!xFGgQ@SvA~I6)c}+;@Znava(`w-rikOCx2==|3b{xkc3<4yAt<6m)CZ{mtkSLCE9Ggz7 zg<;#7oZb-+PeN;2?KXu%0VySc-=W^@FgYGd4e&s&>OSNGTaGU zAliT}lS{JCC5Ah(0BnK2s1Y+FdAF4yh?o=TWf1pEgwsQU^Psyu1TugwFe4BpV55gP z=XCOWTx8d@^(G&7RYPAr+;qe!nSy(37GV_9ZnrUe+M;f^i)orzmes$tQzdb^wlNq@ zu2sybGiRvP#`yk=FR*X_elA};&+MLkY+N`;BZx7j?y*rCEiD#i=Q#QL>llW~T78wf z?s<@))ucQ=f$BCmdHO82?PQz2;1xg!!Z=2$m}0Ta;X4lS()V8^j5WeAC>1NWW!g63+#`hIF)F2X zv~Kk4YY?tLzRyS~MJkU!+WR+Ur-I&ZNDu%Z)aWjVX@T)cvqu>~FDvv$Qcvs?h*EEy z3b0A~5P-vw@#NZUFuTDGMT}4-SMoY2R2&V&hCKE zM3@2&SFE9IhsiCU-A;!%3^;Z2IDQy&xKw7#G>F@6E-kO%dIeM*5MvN@y0rX|v5Ld^ z_yjALF4AsysZLB%ueUG^$?Dn~reUGAqS@?V+ZM5k@QO7gf@Z79<;$1pL@{^Yc^7Ld zE0~srWtv=CUE$REC2G}iN<|wXU8D|a`2kTJ(pX=kR4%h`-(KqVO-`LWLEy&-t+{aS z49lylL{W@di?J=2;-0;@w@8hwfKcT(kmiNcpXIsBzs<_t6TEN!f1zaVMTmY<SH=ZF6)(od^S^d0{=Iq`J(QQ9=!*1g!~zAfXUF_C+a$@B73^ z+R~3&Sw5 zEEB)eK?zBvQYQ4fwAvjU$03Sh&b71Eru? zEMnU?-;pwo70u>J3We4FCJ=&+<~hFb!ars?exAGb{xt8I{SAuNY?9J+ZC zMT!`K*x+3EPYD0Aj@|$P%PgnrjZ8Kcu#q*R)FbDRimDR^+)B8p9dZVM@8mbFkyNf3q^>(cIY zaBLgfFtFkn*Rlv=O*hsQ%zKp;VF?-SrAMu1BZcrB*9L?~a9H;V=gd--*#nS{=tRlarJEG1xYxayhxU#I~_) zI~jxH(C&077K^y9JCF|F?{tV2OifKE%cnK9v5DS-rQ?igwG)b!+!_Qbj%cNupYeZR~+ZugNL6opedKJVhNf{ILNd+E=aljSGyCu2>`lLqObze_Ak?mW1kS6+UFNJFJmq|s`iB0;HK zq}y(SkVw(Y1Fr9wL@BQh!RjLRcLH9 z31h`Xv4mv^wzldNiY4av%yRzRStci@*xXphbjt)`M5$84G$l*t&e8BYxNebnE2Puz zU|TjZT{ME_OBV=Yf#*7`t*p@6Y;gBIceB2_%Gzd&v9WPX6;LdW6LcEHN)tyR4L?K} zHEOkSRxX_6+`02i&&;!Deum4J&(muA>|I>od(S?N?G`Z&$;C_OaoqxU9XZJJ&p)4> z%3%^q?Yb`Y%?;X}E{4%YYmMW1REi#c7+yDGC=KC=Y<#iS+_~qI+_Ufrf*?j|u!IDI z>^9d}4c3iB&r4)OCz_*z=nLHdPLKMxfsRh>8&_i91>j!$cf|@qy}kK2UB(zyr`>J? z3?PT^`)I&*oWwuBcjJu)T4BOU4ZG@e+ikjGi0e44t}KD!FgZ3xH}LU14=JG2>0p=^ zj%^bLK7J5lStd$D(esGn7zBiV^3L-LNC92n$1n`ySWzk!Idl3n(=)R~QHX8Z_(0&SFKQd1^q$$lgVg zZg(Cjoo(z#b`Q958P{!*vQnYg;9UKW2tLWzp$&3BwS}vaoHNmMzNu`j0GYEvwg@Ct(s*}ciIEjv?eL}7qsI}|*ZPP>H=k^=`1 z_EpG1fMHt66}e8ouXeM+=2o4_iE*5s?PPFfEj+Wo1LpSZ$=W=0=#Iq3RT#9qyKd5c z`m{DSHrQt22CWODeFUYY5bAsq#Iys_NvV>{aNLZ)o p9@50zB*Y-Q;%(bWe;qQ${~zbWB7!lcBnAKg002ovPDHLkV1l?yf1>~Z diff --git a/docs/3.4.x/docs/images/apps/linkr.png b/docs/3.4.x/docs/images/apps/linkr.png deleted file mode 100644 index 62dc5f6c51174c77fdc4356a7f442e95cf8fb6ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6428 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 diff --git a/docs/3.4.x/docs/images/apps/lists.png b/docs/3.4.x/docs/images/apps/lists.png deleted file mode 100644 index a0f48c63b1eb40fa7cab3c8384ed97834c621e21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 697 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
  • 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 T655ph=X$5122!n4wvPBe3)j3P diff --git a/docs/3.4.x/docs/images/apps/mcdonalds.png b/docs/3.4.x/docs/images/apps/mcdonalds.png deleted file mode 100644 index 28a1bbf0bc13f1d3728ad42e53a04eb669f14517..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57481 zcmV)KK)Sz)P)-8l5@^cREC_vA)_DyB1r)WqJStMf+!eCA|Qw;B1wXx zAPNX5Dh5E3>;=RB_PyP+XM0Zf{ibepb#+yBs2Kp*ZWBX817R8ff`Y?IHikMpPR=eo zxL1ID_rnLsh#p~~+E!L(;D0SEqX61@K9ksy1^$19*3&D@0|3Yh!S0@69zh7c4FIaq zBa{>l0A@!Xe^hwr4$ej}0|`+O!4*5$=NE3=!S26s?=Fv>jV^+x0Kiici6kEY2#W}v zC(^?QkwZlZ0G2M;(=QlddlL@g~vut?iK^w?NmU5h{b{zQ`;B;b ze!vrX{-JyP3*8pPf{%z)FA(-;G&CDp1FeQOLs~7Q%A%FgDu3SfEjBFv)#{h7K1g4Q z-xQtS+DHDY_6PkEN&nWz{cn%|)X4zM>`ML3AzdTAAiepg|35Rv>SOh=Mpy%^2r3nI z3)PLfk9v%1K{Ws#R2!-h)r-2fga2(5;%}>vcIRt~jOYa-cE1Jxj~Ye%<@imd5~WfA zHoN=*$UDEkBRK48?e`y2B9Q8iNb*PCnf{&QA4>}&)>T03pw$sOBQ{1eq1k{0S{|{u zHd+($fdWF+{r6tKTM6L3Ys<*pxdecB2o4JOiVoiibls597?PilZ#a)OvRitI^B4zv zNQ(2wO3TQCoxS(h(*9<%yQe}-{r}L2$X=){3jn#!KeP}eHf!^d<#6^Nnjo^ySXBVH zY2y(=iu^@G?=%=>N2f-jpB33T_<%5?rz}teYCsF<0~25g?0_>kfLPZT1R)wnfg|7; zNC6oj8{~s?pcIsYDsTP-?ao+#>|tyswgg*;ZO0B`r?Ja89F7$yhEvB`;)u9#Tng?i?kcVgH-wwT{lHV; zx$&}i1H2197@vqQz+b_);)n2a_zf}|G66DGGD|W~vKX=~vI??hvVO8zvJG-tav^ec zayxQ=@?+$Mplq9&sjpw^~7 zKpjh6Kz)n4pL&soj7E?~mxf3aPg6wGL^DRSOiNEILu*MJM4L%_h4wM+JROcskWQb@ zlP;OAoUW5@njS^ZN3TooL7zllLEl9`%YbDNVlZa#XUJf<#?Z&G#7M^|&*;Dy%~-^E zk8z3##U#jN%oNC!#dMQtlxdxrlUbYDi#d(CmU)PIm4%%}i^Yp2ou!Utgk_zThgF|7 zfHjA;fpvln%_hob%@)OWo~?^*k)45EjopJio&6^JI0wuj%3;HCn4_Gdmt&cei_?%Z zl=CcSC+8v;6PFg3KUW@CE7t-yJ+}t8A9o&i8~1x2MjmaRK%PRL2Ruu>9K1%n5xf_9 z`*=6@2<@@olenjD&jcSipE92}Umjlv-x5DJzd8RA{u=&q0Wtw)0bhYL0^I_uf393!qG9xPraJ|;map)C<9Q6uq2l1b7`GEuTY@{<(5l#5i3RJYVmX$9#(=?dwW zGITN~GKn(HGGApyWj$nzWQXMlat3lo^LvH%dhM;) zJFUJ)ov40MeM*Bz!%gFY#*`+nCQ-9Y^Q{)2mZw&w)||G8w!ijO?N2(=IwYMtI;*;> zx^cSgdMG_Zy>z`keL8)6{d4-0273&A3~CIP3>6Fy8@3x^j7*JkjK+*PjXjL3jh9T6 zOyW!)m{OYBnw~R#YbI(&GHW)6%}va6&0kpvSOi-%SOQC9%UsI|DhU< z*6(a&Y>wD;+tS+}w7p`xVy9!5W%trv*gnF(!-3kt)uGy9)ltv!wBwYMlvAA36K6JO zKj%gloQs1?rOWa@{eAiSW?dCrQ(Q;)3+<2I|M&pgfxrXz4pJW^9=zp-adULL;BQ5C-;*4Znv*$`6OyNo8y>Go zp-Lg8jGa(BQJRWQ^-JwblS@0B_A}ixy(dFDqab55(<8Izq|C{}liR1fPxWOfW}VN* zW(Q}F=4j?rou)k`M4Xu_G%IX8%YQce?B+S& zb0bAMMRmm-#c9Q>C7vZi=e5q)mU5P6l&)X!yYT#?;l=tg!LovKY$lGb*<(2Vb75vZ;DdtyEooh2u(A4O|mZvvAe*>cBON2i_>k-%A z-*CGzdeih~$1UYswYLRs7vG`3lU@(i$J8%1_%=*6IyVkBnKX4Yt2N)bD|z>F3vWx& zJ;r-kt>mrAt=ny}ZOiSU?Thz)?oW3d?0DJf)H(dX`axfpY1gBN1`j*CwY%FMsXuCY ztopdAN4clriQ<#`UWMK}PZgft=~L{h?^o(?98ei(9^5f0n^K&*_eSqc?_1lq zFQ+}GKg@*9Y|bXXBfKk^yGPl8&R9M&B85_t>&Mm zKVNMJZEuGXNyOc&01BzFw>JP^FC%%2GXV4h$en`fS8nvXppeT4j65A6N$3Oo0F{Kc z#b{xLaBO%MGH!Bp3Jb~rLN-+s^&+hVofmyM!!(m9a|}xx8#TKlM+N6M?!7$8yifUP z`E3MF3O*4AB66bMVrRsABvz$_rLAQWWNYL`6ktUerTxn3D)p*w_7c>UHQY4Qv~Fm> z(#7j3>U$Vu8#WqEnn0%fW`^ee7Fm|Jt)5%|uw}B7v$u2zay;o&>-@y!&Auhq)%_a> zfg3rI)m_3v+tbGDptqL~(bv{*uRl)!6fhOo7IYyvDa1F_>X0&tCk!9I*i$+=S>v%Y38 z=d7Gw&Rx!1FF>DREEGR$c+R8fXmMdl?fJISCl`h00R*7-^W4nTaf^thd=FIVd>gxb|@;@Lc3= z+w+odS%5;2TS!6JSj0^zmk{dYA>9M_a^OCRrV~PO(X~O}ERmPj^UmjB)aH zwsX|UJsAazu!&U0lTR-%FJXv#D`?x-^Nx3z?>whuu05XN1!(J#XDhn-! z?#IMprLYUQOL$*0DY7;49*R=RD1r@@EHxGN3e5}JcDic%T!uJCA0``Sbrum;M%GQX zdG;ZWR?b?ka_%CY0^YnmS$rw{kpe_PeIXv9AHuyNrJ`YCM&i5@u*8DonA9WbW|=Fp zg>nhg8ih!HOC`PCeDn`uU)G4g&^nu z+Wvb75)SIR;oSy_#qI$fdp#*V$Gt9lAM#Q5+4ODmOYqkU00HfR$AWZ&(ZO9I$3wM4 ze;leIIU{Fwb+~2t_lUyCy^)hq3DKO<_hQ^)nPSHe*BnWTbBY&^Upd;DkbBH0Q7=g} zndLY|3P|~WVmkF{T3vc(1~F6qB<|$+sq0zk*#S9*r|C{V%-xr}m=~L`U7&L&^(_8e zdeKY?>v`Eyl?y5t70RT_g)4Y3u~yPvCa)r^rbZ%3{i@rw6Sddso?YL(DSXT2_USu= z4GfLWO~uV)Etq>Et%hyx?MLsQ?`Z9O{b2hcZ@2CvpU0U!H=d04ZuN=u?;AKXIQdL= z_~gi^G27=&c+tDBm$tbUa zRxpHQ$D0rxBm!w6`C%Az63GXlsuTIvH&kr|tmz2v_okR=!>WGXBsLJ(OJ9TB@LeqJJ8 z(p5@Dnn8L==BexzxiooS1rtR{B}S!f<&P?pszYi$d%M&hXmo4#X^m^o>#XPjeJrxi z;f?UdWG0lR3}(FM@)j1B!B%#DyH?NEl7bOEx>caw0EH zJiRN^>l9zt>#6ZzYPJm*x3&CVaZ5L0%cV*Ij1^@Xd_wNp1P-agPk(Nx>AzfG)z zyUXBFSubV3@ZidD&Y19v!B^*BpLsj<&TV1sBi-k#U%_|j6_wTPweKZWMN`dDJ5%@37|^uSYS6aP>C*Mk+tN=U zndv%X7LzE`6XruKOf2=R)~xT?V%Q1n6&zX|Gn_eGCfroq6Fj$gPwnyJ)8S{~{~&Nr zFk8r5SVu%aluisUj*-AiQc2NC)5_pw)@0}9#^iex?knC`>QR2F@>Pv$ue7?ghM#7* z7D?Mz$4S>vPeoteK-tjH=%8`D$wkv{vn305OMR;V+th9!T7kN)5m<0Xp(zU!c(znCo<5Psi)YpI&%_po$__hsGU_SQY%p@6}gBmdsq=! z$$t4>wR;WY)rs1!>-{&E@5nS9X?oH^-Ky74>Zp9M(5>_MX0J?N@xa8;_u((2bI+&8 z=U;t)4ZR_sW|-xlGg>HERQjC$t#UPRt#2cFvvceF&$V6u!^rBV1zbP^XaH;A4dOrn zxDI;3dx#7YgUlfkR0y?0?_nlb4-SVb;c*l#${3Z5YDaCM)zGo%X7naT8M*`yiectr?qfN{>dvOaF3Q2cvB5dP)yRFCCy3WM)l zqEur1;#v}Jk_l2J(v33DWWUL?DHtmzDs`$*s=BIOSH~fD)mH62I=OmG`n85G#yl~ zh|Z{p7|+9>;wutjj*TX6Cd0?^DKsbKQp3`QGwd@LPNil`=Df&F%~vbd4-O`L=0lis6099{hM z$>4L$QpuN-Un9QheOvv0W!Yl+<%;jh%4+25!VlLU{cE~wHS2`+(Dk7Wg^j|EFPp}j zWt$sYc3aneqJBF4yt)l-+izdl@qd`Nob2xL0a5AzfSKIh{w4?j?lb^fIosPCW!u|Z zgo)j0W{KpBuI%ANHK|`qA6Jt$FeAomt~EuB`3|;%N~s+TT7NWmS&A)kLYEI zLotXnL68JM00cmw5jv;p%IW2B;|V+XkA2R$=e{aH)X0+N51n4sFP(eB-oN<$C2`}% z4M%wtTBEf_DMc8D{F@x&-{{l-;rI{7zu!ar<)8T(hXCi`{fCE~&oUgdgk60v#CIll z=RA+4Qt~?s^Yp_A;T-?r_z%aw$>9K;LkL;@^!q-nb4V#Yf&Xh9!Dl}68Gm!wGkaxgUHPq>3i~7153)RO zJe)uTLH$58n!+`2P(Mrgj7PXp2nwyqg?NZDoO3KJuW!a0w+ z_rI-s{p-Ff&e2;~;mTtd*x%b`G|6bUTWDP{8jVp>5rhFa2%?BQ&(KAIvyLG2bl2{* zDY6``3wC$+$npXJr4-f}WDxSilUK;bBSzy%MO0Ylh)Y4dxw*+W&8DBT7U$r?rN>AV z91I3jOcJPwIFQ`DbDLb7`n`fQO>2TR*3?WfrEza(g>x-zR$wy?LZId%%%s5P7D`U7 z7STFKmSv>I%wDVfTUQrMvWyd_P7_2SK@hTe?=ITF^4b~;3yZYc9i%f9R?}^DxOMvu zqhWy%u&}tw+S)2NZrmhHTAW=!4$ct>$^F~!vU6_-b>u76t)nmSRk`0{?#_ zncv6t{%sml|E>;)5DF;;Q54mtuoMy}z-o;vtq5%l&Os1*Yr$HFl%jr1qcvHU1D+1! zIHnTfQb|ugaf~sVPH&D#Ne06q09lsRG!(}%d7k4+jiRLVW|I(Tt&viqb%D_a+pv6s zyfUQ#Yi(^pRm-oEkoBMZkJ$OGZ?f=#6CC^DCz*SCod>`C8mr&4!oqvz+4;SFPy*u| z+Bqi9Q4|HaF^~2!JO`0ZCJ+6o-=CF|0@!2f_~%(RJ-KN}Hjh%v!Dwn@Iv5TI4_$la zk(l}4zZb%)?_I9Zqo1_=-FH0a-xre=fMYTq&pd7O31`;YO@D5Fh3TFPA&^p%=lRT? z#^W&p81x6Td)nATDZL49og*)SrK8XDh;Im_l#HvF2m+9D>X2AR>%toGT1fw!SCQeE zi~oxcFnoK1!$f%7^ck9T0}kh=Y?hZy zarFEqT?$vOO-Um~p$UQ@pePCtX_bz5^>EHPdQYsP54O;wl=Sv4GMg~DwM{zF9NgUJ z{6|*M3FwiVAwDT3N=not7El1Pc8X>fR><-N-RuI0()4-MhE~K|Er*nz;HZH2TDq8#f&8~CWIg;&kvPgt{V}C z$|GY+VvWTZhqV@6SS+BFtkrqF$tBa~x%R@zICN9x;JL{xm^xk+h=SH;qHX6oe?ieilLq5W{xg)gG+^Y=;e+|_~v3)3sgx0 z(NL8o>NdS;B`w|2O`JKU-mvMlAKsMNwVB>%W+R&)oT9!+DKN&vhRyQ@9+p;(wXV*W zN=)HRDNq80k$}KD5OVq~m8QgjGfjd7J<D5RxZsTU&4Me@x zUh0Y?Yd)(@AGJ0$fmZ8m?F@ld?_EjtS%P+0Yy7^H8p@VVqbO;rHj_%H+F6TiXdzDz zUdYU7tE10aKcC;bpxS_@RCR!H4kH{Q88aCS$gM*dgU$PxGzS6J`&qPB6=7GRC$pwV zwP3=5m9h@Vi844d-xZu&57_Tp?rt0AI)Xq64o8mVdB_V$B0(Gqw6W|BKpVfL^Bw54 zJR#=Vv3+1Uv8-6^32tv14u%dT1!s;cIxV)?ei1OSj##1wA8C>#&CubN~mYe4TOQoj3n_|L&F`%lA6SL1Gyi?+d72!2TP3Qtw znLZYTsI)?`@WGt4vflf*RQ zS3QfEy}k+)I`d~y;T$^MCGFqF8I1r`5ODm$WmZm~V>0M-=gn7{3=Tbm0LMbfQ@xl# zz&m5jo!oludDP#i_t4cpBTB|-O8MMck1APVR%;~aG2aM zyq(iomn=OQvi0?Bs-up$|H4hpD{UR8*A)NfpYCvMSs@(!ou40b@r2^Sdcc4F-;Vg( z|I-ei{bs@Uy+2~1C$JX2`L^c2{AXjb-0_!xtj+g4A8~KTa_fQNTUQJI;t#iR0=D)H zfBnB6^WmpL{^LKKU>#h$tNA-WKjHuM7dosgO48Kv3%`@|Pk$@L+G)hw+NmBp8tZS` zrLrMSXPL>>>#L;nQT)oBsF|Xv+VOsYwg@S)#vxT{7Ypx6*Cv+$hb)OymCtKYLSPM; zQtDL%-Q4g>C{arPqmF13$q}Ulx20JmEA8d%bUhkIM#V_Bw%Mz-v5jla9#RUwHr2W| z84iaE+pJ#xVOGyP&oft6xp8}kcV7B!_HTR!gyZ>7{um$o$v;bbegUHku7BgJeEJ{# zUG_Ha@#Lvv{PmAM&11@-celAW%J|v0?(>DcN5`kCwQ&urq4qI^5Tw>Jbgo|D&c!F# zcx9Q%!8Yx)L*lhHM*D}Tg@DD=J)F+D`GpA8?sD+%i?zh8q^ZA5LzOb+n;-pH%u-MC z7yjmeKmLh`zxcx~-nnB~TNDW4II%2Q=t_<+N`B=_9%lP9e=y-6{_2>`9M%>kgR$dR zemA2(wEWDEwfLQv3V!alQvUD%Ntd7gp@a`T8S>9Qlk)kOHUIE`+2sd57_l-Z`6vJ1 z6eZy={b-BNy_9on!$2vaYkRsuU`)=uSzc8)an zfm5kUlf?6rzh-U1RUD#9C%UxbokIxQ@asww@~DFixFdp4R$8Nh=DAAhAEh2AN(QJt zJ@s70(X}bHXm!0Q6_jh%IG=`A6{R21U45Fl_2+r|@m2oEKmHj1*Z*h1(%J7OA8yc! z`+Ve&{Ao^~Sfw2}7L%Ax>$@53?eLj@^0WNZho9qpXO9tGzCymW$&xPki`lPnd$P%m ziJqpJG+4Ijd(JRMN# zYW81z5trvvDOH&nOl|4vfmRkI_jWDU?i*geY53%a1W7C~7L1+U*q{7F%tA--i(kmt zAC%I`!kJ@|AN)|nyLUD79m#7qGOpe=+}<)=SeJAXc;lAgox7UNJq)yH-sydN6@rMr#W1rMtNq*ZT9~HK`0;&Bw^^0C8Hf_VZ6y|9hr7m zr%@7uK$h^YsQoG-tGGqeW%t*%m48+~*Fz9$$=MabSD%%l0nHy(0S%_FI8uru4C5*| z-PQg{wKg^Ed}J-Bh}4wh>PIjCE`=oS9s{9RTTYMy#*+dWL?rX)nV;XLJ-5J0OYq(2 zJ4hkeO-G!1>N!@99pkabE>QHhFgLH0-ns$Say$^6Z%1687-W;m(bGahsJ(o2XSz-AdpiOX~JXvE;HH+@2&G4;nQc&|nj8mr-~-UV+c5wdWt{y$%M1VCC^_D_&fi6%=dpV;xGMZiw{2?aBf}l|M^_T$DRrK@$ZUR z=n8Ib7~X#+;N+_0x4xbugjc0if?_T0EG5A;5G?Qgl_o~zhqxI6sNPu#h@*g3FCt2m zCj#vV1_gt0j>g9!jME4Qffgts36wx7Nf1baP$DYst%$#LW}UMb>tiQc`|m4an}Ka9 z1+)|h3*H=WXo}j0n#K^C1XRJZo`y^K)lLbjTALbHX_$_pgr!{RTQm&3#+OQ4Idpai z&T(&Z%(XiMws%u6pqycJu#Zm1Sl3~DWVm%uust$3t(lBQ-2CRZ_~1|fS++m(X(m_S z0V%xzs$C$_SQGKEAQ1x9>2&^v&k>QlASLIg%!AEyY?`7618kO293D~}9AJh+ihdt6 z9^;CFVlcprM&;r`4tz-|22#!1xOfLtO1M=z$j?6>^5!kg&;Ig+SFU^9|J=Ib=RcS6 zxo_qeC-}n4IbVBA)9VP{xns$-L*lr4&+ztbgSPPM4bAeLkm#-O4 zuPIKfNdED!r+oe;jdczs;l_sLzxtJwRwT#@xV33(+q?EG8jf=1AeKfAQc6S_4E5VB zXC2!Tp^^fkK+>6y30n#k2&4oRD}q2$WQIalge)pY0wsl)=!g=@ku~vDL@9(9GS*tG zG3Y{*7Zzh1$WDbH*BYXPhNY~p*(8=qaEo%U>L6UhJZ>_}^xC2p2TBNp^jgn9=M-nI z?jy@gYA2}Aue6gC5}oyl=S~o{mgx^Q_qN95<6RE#ewo4c4O(*xbk01^wFASwfgwv% zUis{A@b-&ep+8A^IzQz2d)`BO;~Eq>?~V$7Woyj9lzxP3>{T6{E#o29BG%T{-0to! zLJ0noAmDo_ow)y=hX4k^|0RmJ7X(OVxw6tAfe`2tb#!(rVL}I1Kx!?a6t%jRCBb@o z-FcI%gy8_R@lI$<3dW^fUO~H+w66m_whYcmffW!rkV=pP>WFPDC=og!76Jui<;F@k zb$FE!7$B7X9rDtbP!787koJ63GKD}$e?MVixRBtPBkK)KQAMJqhpeOa3cV8_ChD$ZixGp(mq_>C24{)d9p3W?|1cMy{}2ec`SLgT z)^Gd@!-IVU@c#LjKmL*DnA^I~or592v^D0nVKE~FC;@`XjH}))&$C&^_)|f^_lrlU zmVZsg*oq?lo>D%?srk23su<_^UL{!(@SDc*!%A@7I*v)fGg5Hi9KWa?CnTIe@N35M z6QSgqg^N;f956UuvW_nrPqYgHeq2e;3c+0*zib>Il!DYbe$T=mQG!>j;{_$?;L}!q z+d_=vdrKJfYu2$M;9|LO*PJ5)Ubl_`{`y_uCFl4;dCk|IW7ENh1$@!M4=BN^fV&7j zGv~lj+OAIDxuEG6tyK|IG99l_r#% zA-?9Os7lLJ3{Z({A!Zn<_Bdo2kD*dxQ)ZX~DsCDzE@LiJaO=@Ap(ZUHjcFWpfGM?& zR54&NI;*o3DrFTWEfA7?GQwIjjd$SpwxuMgb)?oI8>npasLbc;qIq^C^8Fh@z)OLu z7o>7bX7XklzpFXly4s`wm?*{Gj1;NRC|7O-yz3m_uOt@)gup)VQ7QOm+VXxW_{l(U z-@$nSpEB^25KM&QNdd1LOA7p$lDuLJI}UyzP+U^*ONHeRDajv}FehLr1Yfs~XQg1n zI-V7tLGC!m*a`kvC>dCI%UYy^mn}RMdNb&?-0&wu$q30)5_TPY$yok)AQ?K#b5imo z@ax)fMG7(;?~(8+3mxJ84(l97TTEdQ3Zzs%6+%dKZpczy5`{yS=9j91UnTJwYimEm z0Ya9k{>~S5IXg{Hsfk8RrM0LDZ)#RKJ4@uX;eRC6q&lYwOV2_J_36!I1DvyUETnpt z8T8vZ{|vS7G1chPTrPhxtJ6lzWtQR7@wk5ECJ>^8Ah(d~%Ga${+10ez%wdBPu`6F< z2Cf|m$t|foettyaIP2<&V$IoA)KEQ)Qwz#yq_y<}m9ZS86x?!NTl`cg`CGZ+87a8y z9KUNJ#qm>tr<}iD z-@!M49U;h#Bgia)k|4{C&mEIPU7J3(TpJ;%Q?tE~?l7eUw19CITi9BfPSY-?W|yq( z=jlGyv5Si6DiqQ+pmouR23L8}{(=0p%8hT*0S%4#LY5n-DIIAum5%OGGwQ#FH` zO_;xmrBvo%t>BzPsmj)DIRBzNUovyPD^1>}Kxmry6_6}tFbmfTN=&>d2g*e@&gb2z z1|!+>ca>S-&-Z~TYi;e0&Y)A}B3j_CbL=_CJ?B`oj`s(O_esa|Qn2S>*Eudp!Q%ot zI0nukf$P?BMZyj17?&J=-#MNTg69N0rv%&1F#(PX|M>(+OF;eW)^W`^4341_e9BnP zOTi0D@N3pP_7Z_C-*+P5(7^{Jgidf=!fVEH$-(bf_@sh~^Jy(FTJK-{Q3=liJsj7q zB`*wNCVl3JwKyv%a^tC8c$?bP8*6LnoLfs_t#`Pctv0Aani&SGsNK-j3Ku1b@eM`gZE{oRId@sKw^wJK_- zz7dVDkgbv*8}uZn(f%2@SUh}f?`+m_nMxQnvj9|}W=*MS@X0pR88zBeNgit(Tvpqt zvujv!zZ7z6^ERY`0LH*I>tVDPt>c1p{K>#e;$P5~9p^YH;U@ygtH$vyW4Ry|Up0=` zEWBSy=A5H%9lv25e_RQEDv(t1*55OZPXvM=2_(O39q%Hz4Ln!+GT*R{7VwPppZPWI zICPE&RuD+94evO(=N#`C#~%qKR|3I{#_?5SIVU7OlqQQT z(=x1eNF}{rBD|9ykC~J}(Obhj)hC3@k zqohPRN2DaNl1L>=9|Uq^{l6-)u6%a@6{xA%Qr^cHhcTwK^BewRnc83Z=GBf@iF~zY z5J%F^Ygs(M3U)Wn@{=xPec( ziQ~}kRblG-@ERm&JV%wI<(+xoU%(0Pt4USntCc>^;)!0t|PnmkuuydVr6k__fv>`!LH z579)j{O6lhnp3l^8435-52JuqDN zy4^P5n4}p9N1+W?yBSzmNjeP-NL zO;)&d9TcgVWxB22!IIOMf$$w0oV6HdYxOpbE0RwW`kDzlV=|QC;+YK-Lexb_*k+vI2(sfS@9pX|Z)*+O3XFAFiH|#! zjGbviUjD2~bB;<|H_cO5ak;;V^CGZL!>H2BD~&VbxLSu()WubmGh3S(<@;6A-(Olz z6Cj(!-b5#v`U)ygr9*Cge1_?sRxuIhD5LlRNgM+nY8DM4WSuQFrr%?n!%0~~v{fQw zMJt_7izJTy^9BK7pvVhNk^6da2Si~&7zVXwK?sCY9*{8_BmHw$W?dL7y4|E1`SvQT z`4G*ou8c@ll0r00t%}QMoVXeP<4ETbDS6_lr#ZH=%y8&inKZi}dIk*$%8J4u2C#2UqhWpBiixFCoWJ-Op|ni0f-tCBwseVtfKG3o z%a2`TG8|yaG>|J#JHXgDqtardo zy+5S@DH3+=m zQBn{_0VCLPpiAa*jH)oJ#gk3gG25@DSqy&;UFu7gl?JM)}eTjpQ_$Jgd)x4XRk#w)C!xy;!!Cn?eq`-ekh zpfFiRuQ$()ci&?1_*ssv&GGc(R}fLm+poRCrKjFYOBoIaLtF_YEX>XE)o)mye*7uo zSnzwl_j_Er@)Yx(gu}xzK^(BR`GEPAHE!Lw&Ub(B_hU>!H)%1NOh_U{l=KJ`96xiK zD2NH;gj?^v#@D|23NTIXleMJwHoqygSYd6Q)Mu9bl}3H>^xLL9~qClS_#kQL6| z@C|AQ%*|rcRhqFCqG47|rA;%%qI$E@u#X-YqPUGiGT&`691hvq-ozM7Q5d?t4qcJdf}#(5`gG8tnFgLQ^NL#N#) zPzs|RD=W*S>6oqUZDgy<@nh@s=H@7}36n|6;_@0vEEx|+Oj5)A{31yda?tM+#mQ7a zm4Ze#G_xtqQUud9_(s6a;WLF{nwC)$Yq=Mu+@7j(uDMsP;rLexiZvrO%vmLT&X)?P z(_E?tl9D>Y>?8OUg4aO1WIc^G7 zD>X$`jq!ejHXhwlf%2;>I1*3sfW&xmIEzZP+il;ut#p8^UOzsIvf+0)%KGCnGFdrH zC1zd)kE$fJYJ+MCR7#JgmI?w7|K)knFrmT{H*Y%p{yMrSN~lfv4s|LZ2vwP3s%xzl zMFGw_@**b)qtYCh+VQT8Hk;BUQ_}k>Qc8@`9_;LYR1|s~V-W2!SrMmuvK|hWw{m+E|Nax>rFE z5QN^0^u*}%%BF29r$VvLDlYfXlw9P>+_UO*Zx$)SSP@1+SwrG|H>G545*cfKRicok zi4+nA(bU(}8fy*48l+SuGUS^|7-KQUuZgt=Yjo|mN)-}>VS{-c*6LcTc{8&NEH^Bm z!uV!zGE@XgA%(&^{~V^!I0r!}dC!N>K057u8eeH-M%Fwrb-tRK#0TwWlkaBh7pm*| zi)pQEzr{A%`hyX^?T}z)b(Ou{ zZ9tHwrj~?Rn$qm@p~8sMCy#OO?mhCtcX>Bu(w&DZC5wv-AS4TOJ&ZNvlQDY-LyoT> zXL)Ify`3%YZ)}ofo`~v>Dg6;QqZSggcwP0bvSdF+EE1vqcF z3n$8;W`VXAL)o|3nX(It@oQh2b)u~9bCp)X`vx;><|=LDbH%KkroL7XcU6PpO(Y8? z@?{Fo>>eER*OO}6KRMOK5yq%=k9CbouW8QxH1DPkV8V#`Zi~&WU7RzF#yRbFOrbTccDHnp488ez@;s&0ZgcbPH#qnBdzeck_ctG4 zH6-m8Mi<$6UX5owFA%aN*n;?%lkF4Pu1T zgh9w)I3kK8TCFyd$(ZZ6?(qYE;1fhjvA4g+-tG?9ZrPb!?UnYza zhNBTniwj=D7dZ$YL)g4~lfzNLrSoSIDqu365Vs<}`L(Zde{;KTF9WW24r}y?DIr#p z-7Ax+Ltd+L*VwDlw=kwMk^Ek|5_PjPd)3HyXh_>S6~3Xlq>?^59LV~f&cX892~Hkc z;r{)*#7PURMG}&YM_6r{jK>s3R+>{5q(G{m&Vn{ZW2~9_JEch$CvCzg_8L{^SX+>5 zQ=^Tdih@&Kx29!T1Em5{=b~xj!3t}OnuG;{P^rp(Z7@cCVK<9eR|c(XI6k8J1C529 zhT|(UrH&RgWup*;B?{C@LZYP2WH{jD>9YjVl1?;IS?+CYbNR~S^!Ij|OeQ!XSv$7I z?dvzVar+*vg=0kP$5>okAWL)RmsX*e@Y&CPhL3*FCmGp{PH&#MUQFIjSP~Hk*xh-6 z2xEHP4*Lg(EFV9`%GxTU{yyVT#`5w4!%4>CT#q;3++ch20lRzq1QHM-typpY!6sUR zP>K_0PI3ACI@{a(EU&H*C_xyuDAEy5`ewwpuBI%lo#xWz$JpBRjiXnV7Z{I6C8jP8@`{@FTLBe|mfuL>pjTqZMf3IBuF;+85s*Ok?gRZ-Q^;OkUAPD=r%A+2e=M~W)C zUim(jg~e5#dg^^#JbQ&WaNM|clevX;mgl?NzVv2!b-5MAWu+?O->hh-;cv-Y&JqCv{nSglWpw{Y}Z#YPWIL zk;Gx$IWG(XjIm{8R8wd}lEhf!n~5nEASH~)6SOu&QRqYXQHV1dQ+CKm(~MTTgR_weq(U|%91+>vruy;Kw>2pc6u1v?fh6qByEk2BJ_g7>?+6 zdtL%ckCW@XK$ZT8_Xm7DBMJk?qcK4kkt8uip3_@cV!j>n_SI`mL0=zI;9*PaJm%gs zOG{Kqi89zXb^XY-DK!E0zBuOteYhj0kEmJ;i5X_BVjCW`^1gyBHANJ~bUJNKc37n+!)IP++CO3NPEEFsL<=F$SZp&pSmBhY?W_ z5rt9dcY0K?C^Uu5$?|a-y{E3SG+2V5Z1iVASVR zKuCDzg%b}mMi>V5!d38JQv%gRLscM7Hq*|1kxeCuDph_ozpBFPX?))2s5t@^(&=~; zrgB8Bvo%9Sam@0IQK60MexHXD;+Y(}9C^Sy`$A}1?~vSXtM z6I38eO|N+7g%h)B=TK&eSL(T`mMaLPTB|Bb-ApK~qR|aPo>~UYScc%qr=MkMehz0f zX__;)Fb@vq7Uoe1Hg|Tg#?WfD8ISr%0XJ^m<*DbM;mrCPSKoOTl)`F5t}Q2yukzAM zFLUb5S#Y3rN)jh*Z13>VkA9q;2Y1-q*(Ho3oKT!xU*#8n@t3)HCg3ms;h2}M8Qyat z;9FNU?HIDm@$QD<<##mq_L{w1p;;1I#{`&-6*T=SDMdq2%=T6~YBkkPZDrcp=~{ZS z5OqgFSrV+OU~y5VS|hMdl)*j^m6`_g)=~XBWoOouqJmVLfm?hniBds{;#K){inAxW z{FOiZ0Y3c9DpAPPmzqbl=}N8QWhp)6hiZ3VuI>GWdO!OaILfB&Dp z%$L4?duE-LDwFFQ8{qSK?xFd>Y59Aq*cG8q>vuCDs#x=Io$fiO9l4S3;$A7p=LgQuT))|)W|SPR*t&%)9w z7cX2Q3PZw3kc~&&zqdg)$yhsnj8kXNGsz30C}uJmaB}@PQthyR=vbcjwGz*qQ{3LN zbms(dOR%?VxwET%39S%ySHtE;b7XCr834`fr_tXu|&P2F6%M z!y!qMP!t92R*O8(84ic+?d_0dDcyF5EKeB>M*Q|?K1~#cewtDoQ5Z`S$Baf}4*Q0` zyODxN6p16ju_ej+g5Z^R4YzlED^F&GLFr$W33qk$v>A7p!XY)NQ5USvtWAl#H?~|f z*{KpHVj85Q%*TS}=2kHT-$_N3*SBJtPc`*rnx>#3{^?d>t1jOq0f zkcPFTgy$dcVe&EGcx{iDul70UXZ%O+Tjq(g^Ze@X4p?0d=#LHU0LDi8U>}+|4%r{( zWVzvqiyc1nc#CPsr@wuRAxv&SS)Tw3P-&d3KP zg~K?Du^uvZ*7`1&&f!w~h^EeBDnD$4(CdY2pcAta&DC`f%^ZH3KbOv{l!6C$Zn3j* zpQ0#gLZJ)_HdEE79PPP$IOx~E^XJ0BzK?MvafHzs&T1ZPY!F2O3kyB+tYA2t5JeG1 zk>Q+Ucju5aD+pA;fQTTFSO@*S;qG?f2iZt3nI*O+(4&FM(r~Ha(59JH{S`N5l9?7X z)!H3-R~pi_TJuo&q9k9*SJp(7Uqu<4k$4EUYC-j|dE!bltAb&v&7CGA(9jZ9pm&z} z4AvD02TD3Z*GFd)jxA`?G-Yuv zFO~gS{?0a1KBvxSv%+dtJ4}C`?vyQ^rMxKWHDhU1iSWBOtWq<#GEH6AV zSDHC6ZF*cK+f}nGru~>~?Kf18Y}4d=cx@^l%+=Lul`m1hJCqv2r`{;0TE!UOJi%Fq zwqCWn*_ov-6)jUXgzyQ1Dg^6%diT!$ggf`QSn0G` z>A?5BFQlC)+OeaX^!do+5@SVO=qChdBT>?zjqgfB#vmc6HnAq(rLHK%*mk6maR+^rBs_L!}1M2IT-iUgpYZ~CB{ zcl|d!Y=ASq!hgLhpy%&n9DMrABi^`q=+Qb2h5|>G{v(Kj2Ti|VW?dO+g-$!6mBeMtLecAVh!dX%;;bbs^Qk-< zW^kot?nmbaHF3x)ZCMw-jeMD&Zt@gVP!om_Ae3KBW32D=XD!wgKJ7gWeFFn$>KvUy z8+4g!p5=Kt;6*b|GxEG>NY~kkK+UzOoMGXnFtBG5S9S_?RZfME2wPi9I8hRF1zY0d z9KzKl#J<&z#UapTIq1|pttFn1gH(*h^m(EA?6wwx6|!cHBajhM5Q5EduHZA@?4yf} zAOC2~@x@0YMvwmGcj5-m%uOe`nOWQP(x<5}B_7rgD5Dg9?@hrke<`CVjL-k70)izS zD;fDNn#K@l%aWBxHAd4^5Hr8483m>RC0DhGV7>Tc|uSn)M-klED58^yFnn-G@G=#PnEaj8wAKYFzJV3 zI!~NJOj9Q6AtsJo8?r1b<1?nUkJ*U{|?CU!FgPu1^zDRp>=OOz&H(**UI+>R&;2~|+%Lph&2Qb)QKf-q31GFIlCA5bc# zAPNHtBbew2gCtTRW8;NomB^`-ryE^lxU4`HmX)A8%NW)=l$v7KM>)4HR;i?3dBzl% zpLMjS{~pecjlzf@`|%&+&-|G`!|BtfX9}dIiGvLXw?Sx4i9B;&gV>tGS7s{os`K2G zsb+}w+W-eOoDC0M@2ErmsO}fDMEdCSjy_8zq=v&GU-Q zD$}Tn4^-CNbf`^5aAi72m7vssdMlr!X|gpBfzM}}Oj5!i^npOU^wJ& z{>{HhS`K#?Qt<4RdEWO_k9Hy(3_LY2X8M33*xoDn@;CRnw>haHdY_pvg@Wr(*Niju zDV=qU$0NXNe60-HR8fL#xWg3f;$W{ztfE54+DIo|$lnRLB z1YL-di4-CXJtOym@6hd>SqWYJTw8LbeMUpNP7#*MRdF*8yi$sG64UK=_=A7o`#5>> zan=p8F_cHzjJ4RpA%v++6(4hume~1%BvC@vw)EM8IG`0L{^?a-ZREg2yu3E8q&hqT77v~ZyLd629lkQsj8f| zB#u~|pCgGQ;y7k?Wu;cL01xip;l_>Ite-l=nNuhHOlBeK#KJfVYgL)&xv%dnKd-eW zief*=+}gU9+ZbQ4WUVF7GY0(uonFt^3YXJrlcdGo?iMOcnCo@Pi-Mpr88nLHI!O8Z zA@J{X-nY|qzu)ub=H^(QpX08QeB`-#{@PC^EcOPz6$#MqTV8xi^X#RNue@TIpO>^_ zfz^(cm5_@kEy_8bzbyIR{`p1z?EikmV5BLNn@Wb56&%y723MPz)>>cxUhTW}X3X8& z?=tH5*xK2`Si@*|$Z#}fI6P!&X_4*iEqa|~dN~?A+<4!(6_T_9wDx9~(xT-4{Q+8a z_^W?1gknUQJHhi86;GUP@zUEVDv-4~;|r^(>mr&A@o2US&Cqf#byCV`v%RFigR)(dY=0UY#Ge*N>;_@z(3MwXXD zV}z`$6Gb^Gx9U9OjHEv<;~34%#byheZ@0m9{r0z$ZuKHK!YE>8agHR3ky3fYqA2Rt z|CL=C#|d-u3v}8MZ@hh-UN=D(1^xbjR(B2+gk<9(gHcYql~Cjv4<6j7C~}UUJWr?u zdF~r?ZEkE}O~GW6(rWp72qzRt95I=sblPowCih5l>d{c=qfNE%WLiB05q0=R9w@^`t5R#%OFxm$;wJ~M+sjcg!j~>=KzW2iy z_%HtI$2qy94Z=5PNhm#ku7Z6$#!(>m(-QJeQ&Sz%=%;b(vD zYxVRg&vcgD7F0ceJwbypf!Bd5Ta0 ztyYUTig@a&C%JX+KF3zqh~gOGEJ7(vk)y)MH!KSjX`0b)x4m;F6}UyLb(}qSp1deX zl7v7>&R@7luQ&IQAN1|b&Tp?Z9`(0x#{@_JK1~uVCoCz!YgaYdP!fl(vTXU}heA5> zi2g({&H|!1AW=DiuoO0gBCBck)*ZpdhM^U=NID&ocB>vPZ>+(Z=`b3j4MmY-jc1ao zxqz>4k^H$If0~u~fGqP|+8=5EoaLy3RxH^&%n(YVgd@uxx%R$H5=pdiM1dgFCE8Xx z+NRVt^SzK(EN407D8T`RaaaXHShV&u76uY29e?Z(J`uR5F>)ft1qb<@T7bF7R>%s{x-a_REpb)y7NFkR1Xr9UvgxWrR)^CdQY6c(L2)fKTH zCCnsA>gx$1SXpV!FvWK=a~?(9|0)FPsAJ!}-efXiFc@GO4G;!{KF%6~K=9)01;6y$ ziXZ=Oh$5dhvXtzCgVi?BIZ8NF?XtBE|L9*>c6K#!FGdAEi$IobKRqVnV;Qy_h^V#3 zlz~=jOxeu9u)dmbeqB*y1DtbYso`J#PM^i)4i}HXBv)KMCHdNGDT{NGH*QWiwiKa_ zWbaV3(DR9Zem=V9!LCL|0TGUc`Ix~l=e_6v_{cLI zq=flIaQu8C_;XD(>CAjn?|1P9jy~Esv1Q5^vL4e>f0HqnK!x;F_QD zPPwVmMVi+?`qeaM3O))2`&YrP-$|2vCseH{3hvy##l8Cv$kGXgv8=8gW86RFV0RB^ zU_5gCy??Ix=3DTAD}r_mG?An7i<`nq7z>;G@H^jxSFZW?rY6fVd5%k3<^89LqEZM% zD5s{ib9J{whrmf6G|eab*iHxzCL_nGwSdCqZ0>4|73|MT7Tbm*hqG&vxsImWlH3j) z?N~FII9jp98qKjqNoJtP9C2dkMV62;CM%{2;}P1z@4rtX1V@os^4z~4%Ex-LbmB9i zrLT+eE9Rzgl+p(3AEX3P6cUw;fzfsBs}9B6vbRwk9i=8(O54#oTRT?mR?PCk98nmQ znV1q#KG&vXG_5sX`kl}5vG4jGo_gllX>}C%D0TV$G|l?qLzL?FQI2r)`{p&i9i-X} z1U~8-Grv2MBlGQpd5wIjM>y(7@868ko8hZ(QF^?>6q^e_fG5q$Wv^o&!~2gP>d_3%c;b8kJys;~xLj|Lt$_ zNB+eBh$~M$O%#Sl@?NTA8gO#ofyj=Mv2^huW46|8j)+9 zchq#7p2v(NKU(ND!$1f|<8hh1sOa^2^bZgD+^2q(FMsAYF&IQp<~j*K6HvIS2QT$? zoO1{(>ijA2DIiMvvQM8C>>p02DU*W(jPd&g_}sE02V3B*##!HIw(2h>q;Dc%o#Yoj zyT^&;g3BkXNw5`^^YGsMe!f2X^JNA`^S8~71e8-{0|ZN33Xl$`1^4$1fA62|aP$6{ zC<;l_6l)DdVakSW75FAF#!=)To_^2!-NE4@;3(3u@Bafcb=}R>j3yD)ftqrY10`AL zcIb6l)8d}eKkyQ!3JzMZ2CWTo(qegaweA7|Rp;yGq#nxOmnj2scIJU~4jD$MAONGW zx~QePbq=9I;%*nK3tW~yWC|%c?S)mhxNl?v7-K*M1nn;56NEEVkfn1D5w(3A7&9rC z$@@|jG9jwGDj9%E5H?3(N_4MGi9nEzCrl2<-qtn73knINL7#)Yy%}bcN=&CSS)X3+ z3R^?z(;}*>p-j{7@y{idD)U1C<>vz;D+2VA+RytdXKM)2Sf8o~tbd2&%Ml-bQn9|I zajrRhL(B*OuWSs?=$Xv%T2PdeYO8#$>afl?dZ;GSK1wt`1da;W>pMRCt&G>NXAKi` zx;8U(QeHHQVgePY+F8{?)N{z{P=ydRH#J$r4^w0+5)rhMgjNzwo%k{#&+5XfZz-_| zoK)z%z-o;hkGOLu^|b|g?j=>(fjo#}WEi3+<7oi#h>PPYh7rE&US*cK<_k+n7$@Eo zFs6|_=!sHEQRd}L%`*hZCN1d==(LDc}Qig9^# z2j{@#1*XVqPOr;eec21T3$XIwoOvC56Aih-t@erkkP8c;<6 zsudwaZ~7Wzk=APjsVb?{@F~k1HVdabEx7vBiawHbF|T0 z*EydSUT0=2Ne~4%5#W$ynI_G3<9t^$QthWS{L0Gem^r^ZD!QsPVC82hr3fgcL|ueG z)9Sxr-HYi0&#J4^G!i}|QmUZ5mgiojBr=HWtWTY#b$x{je8G{^ITX2H<0{n~ht5;4 za;uk%VoardLjO6RmQohdl)ZLU+(PDsH=U+V$MkuR2%DzCICU6-!eH&#n<`Qgwb~HG zP)ugjva4V}DazUogNmcFvaVd4s8!Yq`1i3Q^u1brytVFQ6}4mXNjd{8R9d+iB$Q?S zs&x)mQ~|3;AzvlK3qcTv1ib_m1^$xOAhqxPTjfI8DsRe8yGBYe?Pd-Q`ly|7S8Y>|~|?^V>g+>0tc<{AZBqADN@2tz|01*G|GpW25t!7NkE!1eVb z9T{d+k$L&Khmr{E8&q~UzRO%y-dQb5)euBh=2!KR$_y@hs;VF=9k;4KlthJb-O#u2 z4QFdg6{S?iT1=LEC*FY!0%RC@)nDY(CdEw6JLkMvrSr@`xe%y0!R2{v)7H0=vO#E5 z6na_+L@m(}K%QZ<5q^4U6Cy4LL*5h@I!$Z=XflucUqf~ure)m=dQ#75t2*y6&-+v2ul zItxfunm~RstMiFC0X`%258AuX$>Xi8R1wng1NqgsD&u~g`sM4)h3tWMF{5K2?IRQ;a0N}td3 zuSCV2GUGr(kzq|ynokYkim3Pz<1A>6a{^OnvOr?@Pe#xqK_Z_-Km4Aqs%JKM z0aUf0v6VSp8&j2!E5iUO1Dy7$t5SKN!Wvhaf({Xfs3^f@hlrqsQ(n>w6{09RPdJCo zGhEn01tHRvRfMIAst8^P5Y{(dh}vBy`yAS&_hP0h z(Ny#In#@y~QcB?bN)UH?sL1#DoUOpC)R@;CRSWhi6+;Lwncs8e3?F>&bA(9?SER&A z+xrQ^(Z7F<_S_1S!)=N@Crmm_28X1RF~(>{g8_5vrzlVicQ(lm_o*^=MadnN#Gkg} z6ogTTbQYPc63;K85BD&WVV%vT%G45PeXT+F*cxFJGueKCpffX6#g#Crjatl|I!_XX zOzvHyclI&bkwlC(LB$OA_P|=g#Wm)Z7Gbo72-`S9^khgle~flFK?M;Ah0BM?xPwd< zJn<=oC=)9EEWJ_}=LZz&h#Rloo8>4WAKqj)-Tb;7)>UP(ej1TO5VjOcPpuN2 znIr0Uh&%JBu!S>@JR4Dr`=p~obe7_Z9A`BWhjInN7{Wjjwqk;Io1nKy5Vk=@IHxe# z2$LP6(=j%icwi)nP;nO(wMypjJ_#6v&5+U&#PfvhV-R+|HDRI1Clup7ioqtP$VoFt znn8|0i-62XHg?Cn{_Y0DNrALg33f?;OnWU%7pc+sq4bArgE5X~OjN&@Qlho?DIr1V zGb>d9QJmBoL@8CyNRtFgd6URFoYlmUxBG^p9BmEGSw`A&=EM?bE?#E$-B&ny;uJDz zF)niM*e#aMUS#9lAvRO2ojl3tu!S*(Y%*bYYm1dL%cPT(10vkgv8hui>sDnoBB_%{zqGt%S_Vc(;KL0)0nwt?$3c%pfL#}@Ls~leYDoGGS5SFcSW+kAg?bm4_Ox6NVpq#=X=$%QJ zd!mJ03+XI%=`JoZw|tuR+zEtAFoh-^?$Y16!*KHsll?7hHo@r}ml@(f5+?!Ce2>=h zB4N@Zh*}WD=;0pOL0VS8`Rv@F)gg!z4(bAEOh&;~;!Z0KZL%N+d?|<$RQaTDF$O=nVXpAmcTAU{gJA`3`Fb1m!40rC+ z2_%Js?Sm0TuF2C0Z@l#`NfdFgy~%LnCMV8bWGFlA9S#Xb6UIi+zq>)6<|M6{Fbc8G zk@OacR?jose1MHpTHP+gjXMZoYv)P9-g{HInSuR~V&&kCW z@7%u4a4;lp#q1pnIKDK`3s+9ji$m1%I%050l4ZELHJok}rFV#09i+7&J@_E72vs0u zgcTMiJc_gbV277J_f1CoL*#q{67*OjoS5xASc4p8fU-gcotMxSKLX4yD-Mg4cqFlM zK%p&ZW|+^Ry?7QCc8C_bEcA}kK6Zs-v`_!;HTqxwZ8}&EikRQs7i3D4i+u_VN;;f2 zgi13POVWc~mKVFc_nC9Ff&?W(WZ@72$iN{~fsh($Gn`3r91=`4(IfyXFnJ#V1g&LE zvVwI1*6fpx?qT#8S>(t#Wv(^HdoQnYXX65gqk{2xLZ0X4#3eiPugL(9s{E|F>(`8Q zM0;502!cSNf&hg>ZEuhmL%T4jEF;MLkdO0cpQo!0BJ1OdjG-&Id*eRsLCVe(XE?sH zK)$)haFlZJ)mQo2tM3pifz<_Xe&Jn2D;Lp=B&Kafnzl$rbx|x48G# z7tp34PYa~n#^!lhqZ@#Qb`rACO$aP3Mlr+@yIVPL9PTq1jj&<_!2nU_d||vjZ>?p; zTIQVP;GUn+V2!s^D^se~l05m{=Q;I>pJd};z}w$^m#<#kL4^??T{%Oj4URd!_3m4| z_~u&}YuPy%u(~wQo4bNI+Cs%|AWTl61TwnjolKYesJIGBtY6hJimK_CR6eL>vWzrY zMSpO)20U!;J#S+Tfv^Nvq}CXt(bka}OHn$aN~yA~zDIY691K8={q@_!eOkl2sPHX> zim9>;y^ke0dHyude)tLQz5b6e<6Z8KBYx|SWt_A)u!@6J(+&jfIHVN^%rCSVZQMsD z9e(YtkSN|M%~o5FAMl8h_l>0Rt&XI;juS7HfQrYORn)G1RiBQM*4;dO>mu*(48}e) zJBp$@;q+07qE$j^GuhNw%W(-O#MCKwWsni!gR=d+;G6qHf-2M>7lx;A@39sIB%?mb z;h0zmMxo$~-+YCj)dp=ToMa$0hf49j_8fMQbGSWVyn8@8@;zw#a=`pt3n?Un;e@Ey zqPr-`hdJr6&uWyAr;e}{BSg&M);2e9Zj$8&6)Nx0DOr{RJEBM;Ep(%hJRBp_f?g+K z<@ge(7MDoo0`@x#+#L?t7>~$JRWx6A@kUFPhGcXz~IPKN>?qEU~YLv`s0+lkWnQrQ%O?@?Q zVaYP1xO7H?0M+d=g?0qONrWi~@(H2IP|iUd5)jb}W4d9&xX?V<-NWFR>$DqYLs|Qx zePB&(jz}InKvyv-rI#qh(3@jzo<22 zbIfwn2R_OW)xSy$RCVDe19)CFfO{#KJ9Ui7?jgl!%x)lgXH*b)yWJ8mE%W%F`bm~o zmT9**sE;8KO<6w|dNJUim zO0;+|Al90NPMi5wo3PNdIxYG}GtM&7EJGK@2ePd68K%}^wc-4S-oqdGYd_7W|BpY* z-4|a&O2s%E@$xI5;oaBYVmvs&N`X+0?ZX3FdXAl}&+Yv_)>(8>P!zuHic+eaYwZbM zsWPpi^3gw+jp|B41k|G}$Vd`}A+1)MKq~HR zZZjTE=+3q4&L4ipg^vx$GKIuCht-CY&pys4|MUMjpZ~l6FW&v^R}fNRT)QlSF3_n+y4-IJhQEB`~bKGVFd{b1r%EPk8vU2$xKm1?*r+n?7{337u+UKZR z%mscjrUfZ!9Xm$2ILBmZnf-Go(NYm?ZG%2wcsN07OOfrfbZm(WPhH`{`UN&W`x^|# zWA=9kjPn$Q?=Gk(k`M?34+F<@3)sOJqbvL#;P&h9GU$)#NkxHR+@D}evqFp~M8HMa!o)2m3(HJ&!Eihx$qMHB z2iQDk@xp0Nz5f}yi}QT*|NZM6+3?F{5uywn%0FxaTKyL*I{QcBFl0*omPEK=fpIv!#Ud!Zc{pj~ci@F|FE^xHQX1280FH7h63g;pZI>>_eXz(FZ}&~%!@zwON8YJv2mukb+6C&JiWx#d<&iV(ZqS4 zQVd3%U0CGQ;sW;%4mkhVS>{)cbFlxbWlX|j{M}xgBF}LM+MO1{`EGX--^(Zn6>%Jq zj#F}N>9i6i6JPS#>vf2tfbl3}k`)wrP8-2!G$6}TKZaKd!Z7e7r!9W;vvmk8HcOE* zpx16OE()K|RY~EBF-i&k)F;1-kNkx{#n=An&-3NK|8oRU=!w&6@?ykjd4bDMKF-3* z0`eQLGD>1vMZwvnHr=qx_U1OD@c~H^)9$u8*dI|v+`7FE04vM$Y(Cf~EezdG!eBUN zd3h1xEd9Zlxw#GkN0w_w!!d<6gi*v?uf=$h6Gs94{?HHBJi-{2NqV%pvgvOeg=MEb z&V1_3X)P^~7KX#a0r_x@3KiYu z6()y!Fz7V%wF#Ys$=)Hh&}@!U-so#iuAbnlFTKoz?JY**F;?eXSYBkk*XI3C zU*XE*=LzTMnO{1|(`#!Sj{79N9&xM1C%*qf>~C(98TjOnd@rX~+a&V~tSof6^u#5e zea}VCo;}IQ^#yXP_~a*F;P$m!Xc6#<@BIK5E}bA01shuf0&TF9F?l-1Xib>Jgkj*D z3aXG?KxWLeJ_0{MNt6;;C`Aycda#TW5FZ>8^$)Ry#pF3!8-i||$w42T<^-*Pg^P>a z+U)c3kA9e^u3TpKaKO#Y12l%?b200S%XGUPbUI`|@6%aXVQY85(6vxO#Gm-npX9s0 z=XpN<(dP(kL2qrHpZVz@;>OKw{^DQ!2|o7GXINR8<0t;;ALQh*1>W=g74{x%vbl4} zsq^Rf>;LON&HTbVKm0>4@Z~SPLSbAzF{jF%nv4y6{a)Mr) z^l*rtq>QxTTl;+iDV2AM27N~V@E_7u5E;WMG@*l`gfkaT^T8kdB;($7 zf9+-Ve)ZGH;h3o1=GeuPEG^IT*n6L3?er?|{phoF7P@rLKEuJ*9^*m5%3PPY6%uwj z1dBZe;{u_^m}m!?1k9a3fd~U!o|Ec={$PwQ3X)tSoh6!#Ne&L^c007^7l{^@7*0~| z-@Aj|AJXe2%&jf394Ho+7ErAgo#V$*t+o%S3Bm0bU*XnQU*@q-e3&2jYyT5I^*8=L zcVB#kKu9`q$mZ@ggTp@K@rXRvO!A!A88)`}>0G?b5B$K#h`RH9>33gZCpWAdJBACq zFVXFF2m{6P+9GGqtWhikn7ez7_np^p-Gppnk*$ym=a18y?{WIr9520e59J&>%jrZ4 zVGKH(5DBj#9NtHnOeUn0oRQWHi;Pey=6gLloi@fgMw1bFnU<0W;Rk9;k331J<5CY^ zeT#c9zscDbp5q7p4?n|a|MoxT>SulrlMWeN`x?C@V*l`v!a54=m>ll0nP%J$Q!XE0 zCu{`_g(XM=dO<|H(?;~YR9;w^11wGm)=#Z*X=R;r=T7qcdmbZ+LR26)b83}NE2iHc zv36>XRvZGphuDcTC-}bkF8zaDf>0r{Y0djl|DhSfsLitP#297jh*W~@cW&_6zx|Im z{?uiD=)d?YeC5CX?|9>1ex}4c1nT0Ir~XEs7qqSA1N%EfqdpWlA&$WL+@lj0ALq%R z_*0xXb%FI`rxEQrmhW#e{MI+QdT;C8=}d7A9HFXi|{phJJs< z;r1Rbo3Q-YW$th7vAelXp?zbud@#afIYAtd^n9(v`0#*ya8NtGqn$nOzx)n6S8rhQ zf{C*XCFnHc`n?AXQV&&6#u=+gm$j93Tqv1qD=uEX$Q$omtBD9cBg}MhPPk6K|7LMd+92tFP$OJQ-+5F z!Z2X>!482?=qw}83MS(T|kp&4YkuV*oa(Qrhj4M`jl3c)xl*x1^^WI6M3%Li=3 z7$Ftm?k?fsL9JmX`-ePut7>sCj zI$XMRhI}&Oa8z*e)Cxs9;qHSST1mp)+YfxQ%OfJyO-*qWojQ6{DevnNPAX9cMzj8i zjaRR-`R2RmamvIvUL9-1_y5pOxc!3zde-v8;}LU3&Rkw_Jdn(FLxMnYHSF>WYZvHP zjqLY%Cv5YBHs$=`2A>)XNWzf$6RQ+O=Eq3~0r6ZHYYmf~1A;)Ij3suCRwqG5A?e|e zIEe_IqtHMc`+!}R(H~E+2n>FVb9cVYc$hLg7(%KMg{370t4m#uKYoF0ckZ)$XN$-| zrxg+-h$G3u@g){dpC;cQuygA=g~{=~u0kJ`EgfQ<!@C?XJo?tF)Q zJV9#<#u2p=tko2gg18-Fa!uT6BLa!Gg7(@f#c)X0?^9%18IiX*sTh~zm94N8LLsfA z+lp9UT|pukWjVQZL=H@UKzDhW)`^q2B1hf3gWBFGv!O*fJA4}8YR?C}@W~5&_RH6} zyn2>yyUiEhc!|5)1K!>^U}>?j$xK!P@q%F_)Hl z?C&3DQ3)BUpQCj*UzB6DL2BedeG}ClC$&3aV^hb!s92D;o&uWTC#W5b` zyc=gZFW{muRXyW0gSbo_-OCGpdw1w(dI$$5j<|mLB(fOOdG#t!Zy$0hnx_?dTmHhm zUG^s<6gl71ku16anNCTaZ;5#PiF5R~w;2yJTJ6|7I;}ZQKYp59-+Bir0xmv(8Iw-9 z^YRU3(qjJ93Y%|SW96}n^j11VaYDAe%i!J~N-0_=kCCPmtcK{x1@EBW++v&;n5;lc z$IV-}8RiAia*y%$A^9XD2}6RyVD|f%XoE>=342Q@3H^SbRv0qBxJWWLPlO}XhTFGq za4_z3ZmGw)<#{&y1NQTbwa{@Mi5c$l%yUn0xO9Q-V$6vXYgi{a*v`1Ivr804Tz=tM z2HV^855_Dk%psgbwY!|Ve3Fgp_eitCHxHHy5&EI*lW|6x7A&1uWpR0)u$5qR!L6%@ zjD;bb@3PX3nG7>Jb8{dxZ@qrQ$9jPIUYBkwrYJN@2$p+Y!Z74uzt1>OxFYwZ0a1iG zd!Fp{**cBemicDYD2HxmL~m`CD85g7K4NKkp5QIP;}=da5Hb7x5#M^S%h*aj8YtFJ z%#)@md+9Wo_tdjjnDqC#x3N#B>+_*x81vk77rFk`W z=T36&^opNZlI2{xe%CWwx5KfeE_d$lkhEH?EVX(4^&6yF@sL*db{$-N90P76xNX(U z`9hS5s7^A>3o<7Nl0?yJg~Wlw$^&cyqs4@sjUDE+CUqfeXnr)5Y-NtZI-W2Qhq~aZ z)#yMXx^0%uuQPvUnYh&^N+Pm@eeT`d;p{V)Iez&ZX`0fCV|14D_?eSrSx!3%xc2r< z7MJE&dh#s0cej`%F)J@TO{<;IUg&_5n>TJ#OmZH3{1SN_;~WHW!l_HADNZdDCM}{k!c4|| z;~Vb~EzEQIg%z~U3FDYB4$y@oFLH`J=PO@%8#UJ>3lxisU0j~AdUBno-t!nTifAXX z@5gH#cW>WecXOA~FeL~A!Z0Kb0zYvoj(n`3OaLsh47D(ilZsq>&79|!I0|TYBXEAM zM}VIxk|ZeyJNJ0&ool@J$)}h*wnozFaOeIeH}CJ07nV$G-n{vMQ>PbcEktbYjpzHyeQCF#&7=ii<~~S zPH!&ZIY-or5AJ zPD&4lUpc$R;X;Ctj&3g_pBVZ=u&E8*tbjaWqBY5h38~45b4{x?#_VN`jUkF-P>R=o z?`6jQF`b1j6b05;a&6h%+CwOb2D;sZ(f)uU^OHJPPOg%+VqW{!o7}p38zm*#{viv? zd&Ej&3XMuaaE2g?7;f$|Iv6s_3Z!$ytr%$yK^!xOV{K)gD;Lgi;NZ1)uCud$K#&U- zwP5q^13G(qbh=%Z+A&ftbNluK$PKZ!%q{ka<_cO_!dy6EPDu`gAXfqE)H)}gd5XJX z#OJ>FWwvhJ?5^ZfLhLZ`MR>G;JMM4p#V&XqH=Z%pX6; z=f8fH-Gd>mq)nO|3M09@+2`Ja1Ge_Y91aS4b6tcGy!O(Y>}(&fusFwLGC>H*;lYSk zzWEkO60o;-NW0U<=mHf+Cq|=JHe*F&13vJ$d;|4-FtW@mm?4q>~yD8!4m*A`a6P|I7d5)NLnGi6YCs0$Bo-}*%=IB zl(8JdEcIf#aX=h~w3n8-`e2KV`&%R^hF!xO`97CcP7=iloBIbG6b2_HC)ba$G`|22 zCTU6{z_k)Y5Yq4WnVah|9Hs2+9iokCz>0z(P=1VAU8;GsDBnx#s*jvz#Cd>2-S# zP28Qv}hysVs3ZkOm@~L%{lH9&?A8iAq zY_UDbnM=B;?i^D)hoCO`&#GF zMiUg;lu=d3T)T_N1l!x2$gfL0Qbg^E1OeQuWXc~~M;_27^w5MX>SrNDT{ zQy51eCG^LnT2mmf_?(!D6l6Hsy$;#_ki+d=PF_00lka_+&7zoUga7QVVcsXBlbD#2MyCBczU*XoC}iPN#)Xk|HnYkH!>6`y?~K zYC|Md-F_uE7L)nb^Tt|6lbkfmd|*oYkx?R0zTvP`6nOz*09u2U6xNYj2Z6wt0$2FP zT&|pdEy{Aq`?~{N;RubvNx|X4A*;(vyzqUW;H}rb#==~};^G`pcR)HC^UiCpbNA*= z!YF32e*ngK=(KM7H7yRUJDHUEQpQdz0;}SCzt&!Z$g1AB;RjYNf~>rG>4lWm zU`%bUG>?jyrW2Q{hG>qX&hAn3r76LWnp;QBnRYATdq47CT5&|2#NY%)J|=gP(I_Pd zAlH_`Fl9Izp^fFucW!!mVK&HjG`7*yXw&zZ)`wRe8zm6PavOrW-Rjyb97n(4>tGx z6j>!XzP`-)69K%7th%!eU9Hm?%)?6sbPrgAIzwVA>eNIaCmE>9Nz~ zX-2n`kmVX}46AD^Y}~%b_1l{>Q*%$AIYCQkuHV_7YLAL3c=%}gUDg_$9&`Nc5*s(~ z5+*%dHYUJv=Hy9QZG}*6$c7Au8QMC|tgo=sAEI@}tFPar(0aCM#}VdjGR#9xdnxb& zXMK>z0)xW=Sy5mGq}pJFxBr(;uk*skpZ8rl0>$YkcSyQz3ah#M#&u4gJxi+-Gs$zT zgw1zvvAlkQh2<`RQkcT<=I6h`>V*>|NyOax3IUFEl(BGpnfce=W@C54nIHHt*(4*+ zau#|Ct8vI~0ZUI`CSQzs_s)H8zjKSzkDc?QsL}#g6x@3I7VDQTu)N&G8H)@BX=c!Q zju4iYe&cHxf!^$UApP7DA36TcSVS_jBKzLk5bc-uDdO_gzo% zo4@`gKJxMR^YyR1%tt=<9AEgIud#A$g(A%mQlY|tq#cu|DT`}sEO#Vf(n31T#?Fw- zSI(n^V6eN(jeCc@@WID97)*Hl{2E{U-B%cl3s#nT1mt?nXup;?mK+}kAz7nq9^4hBPx;W&7(gA{^RyG;;BFb_<6= zry8jw)>xF1gn`5=$z+hSKTff^X1sHQ*7+sc?>~c-Lv&FP1p!ef;QFg?@ZY}uHb#Vm zNt-LrUO`I7nTuy=M~cPeMWQeuP7+4L0iXY^uaL(bPMz%W{*Qf-?b|o_m!E!#Q>Rvm zqJUfDK4Bbj_VfxHUw?}zj`{e<-@`la-s6Q2J;n8_4_IFGeSA-xJ;6sl{v^NiFFwuH z>l=j9R{KT(=IfQqU_vK7=x&UK%SG0MntVPO8AJhHI7jF?jgSYj&E*Zg&+`` zB0Ip^tkIqZCc`1W_%A+-b#Up~C&|(YON;Zo^6D#eyB9cj_5|}w3%v8nYn;DymcSLP zom{6g7<23cPcq+)xN-F^XU`sI{=gMHRcEHgOV^0hx%O49Nr(Q~U^4z@N3f-Z}z3!Lr`XyLeY=^Q7IFZ0S9Z?m&| zNS5a{BK9Z~uhtf2E7`zU-{#%864%y+FS2po(G@~svXs|OSUTpV-Z z+$lD%UT5p}7M-O9OrCML+b0Y>EGFZaC<&PKC%pOPS1EKsdtnZ&Vdvfs^K)J1+c9%t zME~G5OcbGwJ(ios~aa6e`3 z>}iy+y!rYyR@PVOby_%GFgQHK%7kMpkR%aTuifFyQ}fKvcNmQ)EG*0s1_4nVF&Pah zv}QOO((jMyblV*4_lepao_+cPtt9fD_A*TvMqIdXf*=Z6Sn3ho-9Z*i|=w(mj1shu`* zbG-PKmx!e$X(jCL4-pD*j?0%F?_9mZgchqyUGfJztRGut^k4_uieQqlzqQZfr;oFg z1nk_pLy&aXz59Uf+#CovJlr7!Hm|VHBXBz?;~;rdwYG{U_>0XSz2F2s{l9ZvwY?RNv}(h zXH0evINTqzur^N^MZ~RyFjU;RdXwAt_Idv&KTHxx4sUJJ2^GVwK1*j-eLpHCD8>`4 zwuDhcnq_p9U~qGnQ%_yw>|9J1hU`537?CUp(}H%V&EUnCdEe@B?EBC2?zOvQd5%&M zzGld=@#anJDD$JGoFGsEouwX%0pu1HNvuxmX+ddGAcVmHDvr=v^SfVqnZv<|FaFNg zNhhht`5$ayWyE+q!dTcJ7RVcS8EkLS>a^+a?K4RyeC9X5OrC3!P%u2~^X0F;fwP)h z*YEjSjX=?AMT|!&t#%9N3}61zOT7DLm%-*f2#AxAI0}hW=sQC?>6_R2QYcK>H%bWn zoNMRk25{}#Ev`I%g;pzJl1>=*56hV*6&mAxkk`mTn8CZ?2gFO z5#xhCxt65EL&88Z*}jP`Qo<;qGuPwp8ykq$5_x|IJvqP`10n!tiCYPWwPUeua{7mT+DdTt^l|RK?rk^OiP^sSfQ5w~b89UolZ>F%!i9Z;ZW|j0h*m%*LAGN? zMzgrsr7b`dhSgJR^!E?Yoff9oBFi;rpSZwq|B!T?G1%HeEcS>OyXsW``lwI#AtGk;=@yLaz1!EpS_Szi6zH%Npcj1{^l==FMt zZcaMMnG`uD9pX%0c4Y^nHAqFP+rt9)?`>1$n!_>ya%;=ybcIn)e>mY_e}J)$z3n}A zw;g$2lt_u-?YC|rrDS2Thj5M?H}2DlLkA-|chb z)wjsCA6|4thOzm{>(Q?+8sXp@#nGWn8_sL*MI#>1X1j(>q6fFaXilG z^?c35AO7L*;&Y$+JgwD}eDu9%`1xP>96=Nzf`}javG3*!zx8Fd4pPFv2kdZyB#E&` zBSQ!21StdGHbzQ>bd1Mil1_*J=ns6DSHJWkhkc(#Txf%p9^P%YW1=#ztJCeGivdRG z9pHA%X-U99y^c5zbKz z_Xy(uUv>W(t67%b_o2TPc6#H

    kEHs_LGe?wKJuGaPCdM8l?nCCj!TI01$Q7!ES* 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 diff --git a/docs/3.4.x/docs/images/apps/nextdays.png b/docs/3.4.x/docs/images/apps/nextdays.png deleted file mode 100644 index 9ca96fe961a84f3df23513aa4ceeef52bddbf91c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35067 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

    w5Dis*m_y7@7D1e4 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 diff --git a/docs/3.4.x/docs/images/apps/nuorder.png b/docs/3.4.x/docs/images/apps/nuorder.png deleted file mode 100644 index da4cf597aae0b92aff5c13b2638ec7edc997705d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38163 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 Ef(FYGSO5S3 diff --git a/docs/3.4.x/docs/images/apps/scottyapp.png b/docs/3.4.x/docs/images/apps/scottyapp.png deleted file mode 100644 index d5142f34601224e550deb71b93313497f5720cf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118416 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 Dx(}}{ diff --git a/docs/3.4.x/docs/images/apps/seelio.png b/docs/3.4.x/docs/images/apps/seelio.png deleted file mode 100644 index e3e7a8e65abae0ad30c3db0a00782d8b1d54ce9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24005 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 diff --git a/docs/3.4.x/docs/images/apps/selectvids.png b/docs/3.4.x/docs/images/apps/selectvids.png deleted file mode 100644 index 9ba693a6a156164f547eb4b615afaa43a2475a81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42214 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 KMNUMnLSTZ(DAHH} diff --git a/docs/3.4.x/docs/images/apps/sharelatex.png b/docs/3.4.x/docs/images/apps/sharelatex.png deleted file mode 100644 index e3ef6dd25e1f81de2a170ede0e3a3665fe98b80d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19707 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 w+RWv0lh6Ai#~9=x}o)VD=23xZGidKsJj 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

    UgJe6f|Y=Yr! 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 M07*qoM6N<$f<=x}o)VD=23xZGidKsJj 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 P00000NkvXXu0mjfkLXIi diff --git a/docs/3.4.x/docs/images/apps/stachify.png b/docs/3.4.x/docs/images/apps/stachify.png deleted file mode 100644 index 14a64c23af6ffe25419224c9e6313b366b925014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27783 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 DnZfGr diff --git a/docs/3.4.x/docs/images/apps/todaylaunch.png b/docs/3.4.x/docs/images/apps/todaylaunch.png deleted file mode 100644 index f75fba3bda92d1387dc24b7cb6d5eaa648fff69e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33233 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 KMNUMnLSTZ9^9~09 diff --git a/docs/3.4.x/docs/images/apps/upcload.png b/docs/3.4.x/docs/images/apps/upcload.png deleted file mode 100644 index 4199712ee7ca626e6f2b45800fce43336a6da398..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37792 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 C>_hDU diff --git a/docs/3.4.x/docs/images/apps/wavo.png b/docs/3.4.x/docs/images/apps/wavo.png deleted file mode 100644 index 3ab6bb877c1b05a6f2f20a8cd697bc21ee84a7aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54906 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

    Getting Started

    First be sure you have MongoDB and Node.js installed.

    - -

    Next install Mongoose from the command line using npm:

    - -
    $ npm install mongoose

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. -The first thing we need to do is include mongoose in our project and open a connection to the test database on our locally running instance of MongoDB.

    // getting-started.js
    -var mongoose = require('mongoose');
    -var db = mongoose.createConnection('mongodb://localhost/test');

    We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    db.on('error', console.error.bind(console, 'connection error:'));
    -db.once('open', function callback () {
    -  // yay!
    -});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = new mongoose.Schema({
    -    name: String
    -})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a Model.

    var Kitten = db.model('Kitten', kittySchema)

    A model is a class with which we construct documents. -In this case, each document will be a kitten with properties and behaviors as declared in our schema. -Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    -console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    kittySchema.methods.speak = function () {
    -  var greeting = this.name
    -    ? "Meow name is " + this.name
    -    : "I don't have a name"
    -  console.log(greeting);
    -}
    -
    -var Kitten = db.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    -fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. -Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err, fluffy) {
    -  if (err) // TODO handle the error
    -  fluffy.speak();
    -});

    Say time goes by and we want to display all the kittens we've seen. -We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    -  if (err) // TODO handle err
    -  console.log(kittens)
    -})

    We just logged all of the kittens in our db to the console. -If we want to filter our kittens by name, Mongoose supports MongoDBs rich querying syntax.

    Kitten.find({ name: /^Fluff/ }, callback)

    This performs a search for all documents with a name property that begins with "Fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or API docs for more.

    diff --git a/docs/3.4.x/docs/js/cookies.min.js b/docs/3.4.x/docs/js/cookies.min.js deleted file mode 100644 index dc94dbc5bbc..00000000000 --- a/docs/3.4.x/docs/js/cookies.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! Cookies.js - 0.2.0; Copyright (c) 2012, Scott Hamper; http://www.opensource.org/licenses/MIT */ -(function(f,e){var b=function(c,d,a){return 1===arguments.length?b.get(c):b.set(c,d,a)};b.get=function(c){f.cookie!==b._cacheString&&b._populateCache();return b._cache[c]};b.defaults={path:"/"};b.set=function(c,d,a){a={path:a&&a.path||b.defaults.path,domain:a&&a.domain||b.defaults.domain,expires:a&&a.expires||b.defaults.expires,secure:a&&a.secure!==e?a.secure:b.defaults.secure};d===e&&(a.expires=-1);switch(typeof a.expires){case "number":a.expires=new Date((new Date).getTime()+1E3*a.expires);break; -case "string":a.expires=new Date(a.expires)}c=encodeURIComponent(c)+"="+(d+"").replace(/[^!#-+\--:<-[\]-~]/g,encodeURIComponent);c+=a.path?";path="+a.path:"";c+=a.domain?";domain="+a.domain:"";c+=a.expires?";expires="+a.expires.toGMTString():"";c+=a.secure?";secure":"";f.cookie=c;return b};b.expire=function(c,d){return b.set(c,e,d)};b._populateCache=function(){b._cache={};b._cacheString=f.cookie;for(var c=b._cacheString.split("; "),d=0;d>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.4.x/docs/middleware.html b/docs/3.4.x/docs/middleware.html deleted file mode 100644 index c90a4257eeb..00000000000 --- a/docs/3.4.x/docs/middleware.html +++ /dev/null @@ -1,29 +0,0 @@ -Mongoose Middleware v3.4.0Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

    -There are two types of middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next

    var schema = new Schema(..);
    -schema.pre('save', function (next) {
    -  // do stuff
    -  next();
    -});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    -schema.pre('save', true, function (next, done) {
    -  // calling next kicks off the next middleware in parallel
    -  next();
    -  doAsync(done);
    -});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    -  var err = new Error('something went wrong');
    -  next(err);
    -});
    -
    -// later...
    -
    -myModel.save(function (err) {
    -  console.log(err.message) // something went wrong
    -});
    -

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    diff --git a/docs/3.4.x/docs/migration.html b/docs/3.4.x/docs/migration.html deleted file mode 100644 index af30ffe1c77..00000000000 --- a/docs/3.4.x/docs/migration.html +++ /dev/null @@ -1,40 +0,0 @@ -Mongoose Migration Guide v3.4.0Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    - -

    Here are the removed methods are their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    - -

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    • are now strict by default.
    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    - -

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    - -
    • $inc
    • $increment
    • $decrement
    - -

    If you really want this behavior back, include the mongoose-number module in your project.

    - -

    A good alternative is to start using the new findAndModify helpers. -Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    -...
    -Inventory.findById(id, function (err, inventory) {
    -  if (err) return handleError(err);
    -  inventory.productCount.$decrement(7);
    -  inventory.save(function (err) {
    -    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    -    if (err) return handleError(err);
    -    res.send(inventory.productCount); // 3
    -  });
    -});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    -  if (err) return handleError(err);
    -  res.send(inventory.productCount); // 3
    -});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This change allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    More Info

    Related blog posts:

    - -
    diff --git a/docs/3.4.x/docs/models.html b/docs/3.4.x/docs/models.html deleted file mode 100644 index cfecd30c71a..00000000000 --- a/docs/3.4.x/docs/models.html +++ /dev/null @@ -1,31 +0,0 @@ -Mongoose Models v3.4.0Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var db = mongoose.createConnection(..);
    -var schema = new mongoose.Schema({ name: 'string', size: 'string' });
    -var Tank = db.model('Tank', schema);
    -

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = db.model('Tank', yourSchema);
    -
    -var small = new Tank({ size: 'small' });
    -small.save(function (err) {
    -  if (err) return handleError(err);
    -  // saved!
    -})
    -
    -// or
    -
    -Tank.create({ size: 'small' }, function (err, small) {
    -  if (err) return handleError(err);
    -  // saved!
    -})
    -

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    -  if (err) return handleError(err);
    -  // removed!
    -});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    - -

    If you want to update a single document in the db and return it to your application, use findOneAndUpdate instead.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at Documents.

    diff --git a/docs/3.4.x/docs/plugins.html b/docs/3.4.x/docs/plugins.html deleted file mode 100644 index b21f4c90703..00000000000 --- a/docs/3.4.x/docs/plugins.html +++ /dev/null @@ -1,33 +0,0 @@ -Mongoose Plugins v3.4.0Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    - -

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    -module.exports = exports = function lastModifiedPlugin (schema, options) {
    -  schema.add({ lastMod: Date })
    -  
    -  schema.pre('save', function (next) {
    -    this.lastMod = new Date
    -    next()
    -  })
    -  
    -  if (options && options.index) {
    -    schema.path('lastMod').index(options.index)
    -  }
    -}
    -
    -// game-schema.js
    -var lastMod = require('./lastMod');
    -var Game = new Schema({ ... });
    -Game.plugin(lastMod, { index: true });
    -
    -// player-schema.js
    -var lastMod = require('./lastMod');
    -var Player = new Schema({ ... });
    -Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    diff --git a/docs/3.4.x/docs/populate.html b/docs/3.4.x/docs/populate.html deleted file mode 100644 index 2e51f09da4c..00000000000 --- a/docs/3.4.x/docs/populate.html +++ /dev/null @@ -1,104 +0,0 @@ -Mongoose Query Population v3.4.0Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    - -

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    -  , Schema = mongoose.Schema
    -  
    -var PersonSchema = new Schema({
    -  name    : String,
    -  age     : Number,
    -  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    -});
    -
    -var StorySchema = new Schema({
    -  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    -  title    : String,
    -  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    -});
    -
    -var Story  = mongoose.model('Story', StorySchema);
    -var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    -
    -aaron.save(function (err) {
    -  if (err) return handleError(err);
    -  
    -  var story1 = new Story({
    -    title: "Once upon a timex.",
    -    _creator: aaron._id    // assign an ObjectId
    -  });
    -  
    -  story1.save(function (err) {
    -    if (err) return handleError(err);
    -    // thats it!
    -  });
    -})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    -.findOne({ title: /timex/ })
    -.populate('_creator')
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    -})
    -

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    - -

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    -.findOne({ title: /timex/i })
    -.populate('_creator', 'name') // only return the Persons name
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  
    -  console.log('The creator is %s', story._creator.name);
    -  // prints "The creator is Aaron"
    -  
    -  console.log('The creators age is %s', story._creator.age);
    -  // prints "The creators age is null'
    -})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    -.find(...)
    -.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    - -

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    -aaron.save();

    This allows us to perform a find and populate combo:

    Person
    -.findOne({ name: 'Aaron' })
    -.populate('stories') // only works if we pushed refs to children
    -.exec(function (err, person) {
    -  if (err) return handleError(err);
    -  console.log(person);
    -})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    -.find({ _creator: aaron._id })
    -.populate('_creator') // not really necessary
    -.exec(function (err, stories) {
    -  if (err) return handleError(err);
    -  console.log('The stories are an array: ', stories);
    -})
    -

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    -guille.save(function (err) {
    -  if (err) return handleError(err);
    -  
    -  story._creator = guille; // or guille._id
    -  
    -  story.save(function (err) {
    -    if (err) return handleError(err);
    -    
    -    Story
    -    .findOne({ title: /timex/i })
    -    .populate('_creator', 'name')
    -    .exec(function (err, story) {
    -      if (err) return handleError(err);
    -      
    -      console.log('The creator is %s', story._creator.name)
    -      // prints "The creator is Guillermo"
    -    })
    -  })
    -})
    -

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    -Story.findOne(..).populate('_creator', 'name age').exec(..);
    -
    -// this doesn't
    -Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
    -

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at connections.

    diff --git a/docs/3.4.x/docs/prior.html b/docs/3.4.x/docs/prior.html deleted file mode 100644 index fe8db728380..00000000000 --- a/docs/3.4.x/docs/prior.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose v3.4.0Fork me on GitHub

    Prior Release Documentation

    diff --git a/docs/3.4.x/docs/production.html b/docs/3.4.x/docs/production.html deleted file mode 100644 index caf6e8b1e11..00000000000 --- a/docs/3.4.x/docs/production.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose Production v3.4.0Fork me on GitHub

    Mongoose In The Wild (add your project)

    • LearnBoost is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students.
    • Storify lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative.
    • Geeklist is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found.
    • ClickDummy is a rapid mockup prototyping application for designers and dummies.
    • Scotty App allows you to create data driven backends for your apps in minutes instead of weeks.
    • Bozuko is an exciting customer rewards program.
    • Call List helps you maintain a todo list for people you need to call.
    • Grow The Game Golf lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more.
    • nextdays lets you share plans with friends and discover what is happening around you.
    • AtticTV is Music Television (MTV) for the web.
    • LocalResponse helps marketers respond to real-time consumer intent.
    • Select Vids is a collection of amazing, funny, and creative videos for you to discover.
    • cldfy delivers mail to your app.
    • ShareLatex is a real-time LaTeX collaboration tool.
    • Cyborg Vision uses real-time facial recognition to identify your friends and show their information.
    • Wavo lets you express yourself through the songs you love.
    • seelio is a stage for college students to distinguish themselves and connect with companies.
    • TodayLaunch is a free dashboard for your social media accounts.
    • Stachify
    • Skim is a playful way to meet new people.
    • NuORDER online fashion wholesale for brands and buyers.
    • UPcload helps you find clothes that fit you when shopping online.
    • TreinoSmart is a system for gym and physical trainers.
    • ShoeJitsu let's you shop, compare, and share fashion.
    • Kyyti is a meeting place for rides.
    • Nimble Quiz allows you to quickly create and manage simple multiple choice quizzes.
    • Fur Baby Rescue provides a temporary, safe home for cats, dogs, puppies and kittens.
    • McDonalds food, your questions answered.
    • SquadSheet is a sports app packed with fun and powerful social features.
    • VeriWalk is live GPS dog walking software.
    • DashKu lets you build real-time dashboards and widgets using HTML, CSS, and JavaScript.
    • First Impression helps singles find fun, safe and exciting dates.
    • Muffle is a suite of Twitter reputation management tools.
    • Zootify is a live, real-time YouTube party app.
    diff --git a/docs/3.4.x/docs/queries.html b/docs/3.4.x/docs/queries.html deleted file mode 100644 index c939cc5c648..00000000000 --- a/docs/3.4.x/docs/queries.html +++ /dev/null @@ -1,41 +0,0 @@ -Mongoose Queries v3.4.0Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    - -

    When a callback function:

    - -
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    - -

    Let's take a look at what happens when passing a callback:

    var Person = db.model('Person', yourSchema);
    -
    -// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    -Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    -  if (err) return handleError(err);
    -  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    Here we see that the query was executed immediately and the results passed to our callback. -Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    -var query = Person.findOne({ 'name.last': 'Ghost' });
    -
    -// selecting the `name` and `occupation` fields
    -query.select('name occupation');
    -
    -// execute the query at a later time
    -query.exec(function (err, person) {
    -  if (err) return handleError(err);
    -  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    -.find({ occupation: /host/ })
    -.where('name.last').equals('Ghost')
    -.where('age').gt(17).lt(66)
    -.where('likes').in(['vaporizing', 'talking'])
    -.limit(10)
    -.sort('-occupation')
    -.select('name occupation')
    -.exec(callback);
    -

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    diff --git a/docs/3.4.x/docs/releases b/docs/3.4.x/docs/releases deleted file mode 100644 index 6131da8e54a..00000000000 --- a/docs/3.4.x/docs/releases +++ /dev/null @@ -1,6 +0,0 @@ -3.3.x -3.2.x -3.1.x -3.0.x -2.8.x -2.7.x diff --git a/docs/3.4.x/docs/schematypes.html b/docs/3.4.x/docs/schematypes.html deleted file mode 100644 index b3a96950f30..00000000000 --- a/docs/3.4.x/docs/schematypes.html +++ /dev/null @@ -1,67 +0,0 @@ -Mongoose SchemaTypes v3.4.0Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    -  name:    String,
    -  binary:  Buffer,
    -  living:  Boolean,
    -  updated: { type: Date, default: Date.now },
    -  age:     { type: Number, min: 18, max: 65 },
    -  mixed:   Schema.Types.Mixed,
    -  _someId: Schema.Types.ObjectId,
    -  array:      [],
    -  ofString:   [String],
    -  ofNumber:   [Number],
    -  ofDates:    [Date],
    -  ofBuffer:   [Buffer],
    -  ofBoolean:  [Boolean],
    -  ofMixed:    [Schema.Types.Mixed],
    -  ofObjectId: [Schema.Types.ObjectId],
    -  nested: {
    -    stuff: { type: String, lowercase: true, trim: true }
    -  }
    -})
    -
    -// example use
    -
    -var Thing = mongoose.model('Thing', schema);
    -
    -var m = new Thing;
    -m.name = 'Statue of Liberty';
    -m.age = 125;
    -m.updated = new Date;
    -m.binary = new Buffer(0);
    -m.living = false;
    -m.mixed = {[ any: { thing: 'i want' } ]};
    -m.markModified('mixed');
    -m._someId = new mongoose.Types.ObjectId;
    -m.array.push(1);
    -m.ofString.push("strings!");
    -m.ofNumber.unshift(1,2,3,4);
    -m.ofDates.addToSet(new Date);
    -m.ofBuffer.pop();
    -m.ofMixed = [1, [], 'three', { four: 5 }];
    -m.nested.stuff = 'good';
    -m.save(callback);
    -

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    -var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    -person.markModified('anything');
    -person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    -var ObjectId = mongoose.Schema.Types.ObjectId;
    -var Car = new Schema({ driver: ObjectId });
    -// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    -var ToyBox = new Schema({
    -  toys: [ToySchema],
    -  buffers: [Buffer],
    -  string:  [String],
    -  numbers: [Number]
    -  // ... etc
    -});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    -var Empty2 = new Schema({ any: Array });
    -var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    -var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Models.

    diff --git a/docs/3.4.x/docs/source/_docs b/docs/3.4.x/docs/source/_docs deleted file mode 100644 index f30bb740efb..00000000000 --- a/docs/3.4.x/docs/source/_docs +++ /dev/null @@ -1,16713 +0,0 @@ - -### lib/collection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var STATES = require('./connectionstate')", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "require('./connectionstate')", - "string": "STATES" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the collection" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "conn", - "description": "A MongooseConnection instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "optional collection options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", - "summary": "

    Abstract Collection constructor

    ", - "body": "

    This is the base class that drivers inherit from and implement.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", - "ctx": { - "type": "function", - "name": "Collection", - "string": "Collection()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "name" - } - ], - "description": { - "full": "

    The collection name

    ", - "summary": "

    The collection name

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.name;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "conn" - } - ], - "description": { - "full": "

    The Connection instance

    ", - "summary": "

    The Connection instance

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.conn;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the database connects

    ", - "summary": "

    Called when the database connects

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onOpen", - "string": "Collection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the database disconnects

    ", - "summary": "

    Called when the database disconnects

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onClose", - "string": "Collection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the method to queue" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method when executed" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Queues a method for later execution when its
    database connection opens.

    ", - "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "addQueue", - "string": "Collection.prototype.addQueue()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes all queued methods and clears the queue.

    ", - "summary": "

    Executes all queued methods and clears the queue.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "doQueue", - "string": "Collection.prototype.doQueue()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "ensureIndex", - "string": "Collection.prototype.ensureIndex()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findAndModify", - "string": "Collection.prototype.findAndModify()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findOne", - "string": "Collection.prototype.findOne()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "find", - "string": "Collection.prototype.find()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "insert", - "string": "Collection.prototype.insert()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "save", - "string": "Collection.prototype.save()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "update", - "string": "Collection.prototype.update()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "getIndexes", - "string": "Collection.prototype.getIndexes()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "mapReduce", - "string": "Collection.prototype.mapReduce()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Collection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Collection", - "string": "module.exports" - } - } -] -### lib/connection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , MongooseError = require('./error')\n , assert =require('assert')\n , muri = require('muri')", - "ctx": { - "type": "declaration", - "name": "url", - "value": "require('url')", - "string": "url" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Protocol prefix regexp.

    ", - "summary": "

    Protocol prefix regexp.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", - "ctx": { - "type": "declaration", - "name": "rgxProtocol", - "value": "/^(?:.)+:\\/\\//", - "string": "rgxProtocol" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "a mongoose instance" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." - }, - { - "type": "event", - "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." - }, - { - "type": "event", - "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." - }, - { - "type": "event", - "string": "`disconnecting`: Emitted when `connection.close()` was executed." - }, - { - "type": "event", - "string": "`disconnected`: Emitted after getting disconnected from the db." - }, - { - "type": "event", - "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." - }, - { - "type": "event", - "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." - }, - { - "type": "event", - "string": "`error`: Emitted when an error occurs on this connection." - }, - { - "type": "event", - "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", - "summary": "

    Connection constructor

    ", - "body": "

    For practical reasons, a Connection equals a Db.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.hosts = null;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", - "ctx": { - "type": "function", - "name": "Connection", - "string": "Connection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter

    ", - "summary": "

    Inherit from EventEmitter

    ", - "body": "" - }, - "ignore": true, - "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Connection", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Connection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readyState" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", - "summary": "

    Connection ready state

    ", - "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" - }, - { - "tags": [ - { - "type": "property", - "string": "collections" - } - ], - "description": { - "full": "

    A hash of the collections associated with this connection

    ", - "summary": "

    A hash of the collections associated with this connection

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collections;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

    The mongodb.Db instance, set when the connection is opened

    ", - "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.db;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "connection_string", - "description": "mongodb://uri or the host to which you are connecting" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[port]", - "description": "database port" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    \n\n

    Options passed take precedence over options included in connection strings.

    ", - "summary": "

    Opens the connection to MongoDB.

    ", - "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    \n\n

    Options passed take precedence over options included in connection strings.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , parsed\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n try {\n parsed = muri(host);\n } catch (err) {\n this.error(err, callback);\n return this;\n }\n\n database = parsed.db;\n host = parsed.hosts.length && parsed.hosts[0].host;\n port = parsed.hosts[0].port;\n }\n\n this.options = this.parseOptions(options, parsed && parsed.options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing database name.'), callback);\n return this;\n }\n\n // authentication\n if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else if (parsed && parsed.auth) {\n this.user = parsed.auth.user;\n this.pass = parsed.auth.pass;\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "open", - "string": "Connection.prototype.open()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "uris", - "description": "comma-separated mongodb:// `URI`s" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name if not included in `uris`" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "passed to the internal driver" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connects to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Options passed take precedence over options included in connection strings.

    ", - "summary": "

    Connects to a replica set.

    ", - "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Options passed take precedence over options included in connection strings.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n if (!rgxProtocol.test(uris)) {\n uris = 'mongodb://' + uris;\n }\n\n var self = this;\n\n switch (arguments.length) {\n case 3:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'object':\n callback = options;\n options = database;\n database = null;\n break;\n }\n\n if ('function' === typeof options) {\n callback = options;\n options = {};\n }\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n var parsed;\n try {\n parsed = muri(uris);\n } catch (err) {\n this.error(err, callback);\n return this;\n }\n\n if (!this.name) {\n this.name = parsed.db;\n }\n\n this.hosts = parsed.hosts;\n this.options = this.parseOptions(options, parsed && parsed.options);\n this.replica = true;\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "openSet", - "string": "Connection.prototype.openSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "optional" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", - "summary": "

    error

    ", - "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "error", - "string": "Connection.prototype.error()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", - "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "_open", - "string": "Connection.prototype._open()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection is opened

    ", - "summary": "

    Called when the connection is opened

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onOpen", - "string": "Connection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "self" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Closes the connection

    ", - "summary": "

    Closes the connection

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "close", - "string": "Connection.prototype.close()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection closes

    ", - "summary": "

    Called when the connection closes

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onClose", - "string": "Connection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "of the collection" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional collection options" - }, - { - "type": "return", - "types": [ - "Collection" - ], - "description": "collection instance" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Retrieves a collection, creating it if not cached.

    ", - "summary": "

    Retrieves a collection, creating it if not cached.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "collection", - "string": "Connection.prototype.collection()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "the model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "a schema. necessary when defining a model" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name of mongodb collection (optional) if not given it will be induced from model name" - }, - { - "type": "see", - "local": "Mongoose#model #index_Mongoose-model", - "visibility": "Mongoose#model" - }, - { - "type": "return", - "types": [ - "Model" - ], - "description": "The compiled model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    ", - "summary": "

    Defines or retrieves a model.

    ", - "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.model = function (name, schema, collection) {\n // collection name discovery\n if ('string' == typeof schema) {\n collection = schema;\n schema = false;\n }\n\n if (this.models[name] && !collection) {\n // model exists but we are not subclassing with custom collection\n if (schema instanceof Schema && schema != this.models[name].schema) {\n throw new MongooseError.OverwriteModelError(name);\n }\n return this.models[name];\n }\n\n var opts = { cache: false, connection: this }\n var model;\n\n if (schema instanceof Schema) {\n // compile a model\n model = this.base.model(name, schema, collection, opts)\n\n // only the first model with this name is cached to allow\n // for one-offs with custom collection names etc.\n if (!this.models[name]) {\n this.models[name] = model;\n }\n\n model.init();\n return model;\n }\n\n if (this.models[name] && collection) {\n // subclassing current model with alternate collection\n model = this.models[name];\n schema = model.prototype.schema;\n var sub = model.__subclass(this, schema, collection);\n // do not cache the sub model\n return sub;\n }\n\n // lookup model in mongoose module\n model = this.base.models[name];\n\n if (!model) {\n throw new MongooseError.MissingSchemaError(name);\n }\n\n if (this == model.prototype.db\n && (!collection || collection == model.collection.name)) {\n // model already uses this connection.\n\n // only the first model with this name is cached to allow\n // for one-offs with custom collection names etc.\n if (!this.models[name]) {\n this.models[name] = model;\n }\n\n return model;\n }\n\n return this.models[name] = model.__subclass(this, schema, collection);\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "model", - "string": "Connection.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "level", - "description": "either off (0), slow (1), or all (2)" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[ms]", - "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Set profiling level.

    ", - "summary": "

    Set profiling level.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "setProfiling", - "string": "Connection.prototype.setProfiling()" - } - }, - { - "tags": [], - "description": { - "full": "

    Noop.

    ", - "summary": "

    Noop.

    ", - "body": "" - }, - "ignore": true, - "code": "function noop () {}", - "ctx": { - "type": "function", - "name": "noop", - "string": "noop()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", - "ctx": { - "type": "property", - "receiver": "Connection", - "name": "STATES", - "value": "STATES", - "string": "Connection.STATES" - } - } -] -### lib/connectionstate.js -[ - { - "tags": [], - "description": { - "full": "

    Connection states

    ", - "summary": "

    Connection states

    ", - "body": "" - }, - "ignore": true, - "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "module.exports = exports = Object.create(null)", - "string": "STATES" - } - } -] -### lib/document.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray\n , MongooseArray", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the values to set" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "the fields which were selected in the query returning this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "bool, should we auto create an ObjectId _id" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." - }, - { - "type": "event", - "string": "`save`: Emitted when the document is successfully saved" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Document constructor.

    ", - "summary": "

    Document constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", - "ctx": { - "type": "function", - "name": "Document", - "string": "Document()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Document.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Document.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "schema" - } - ], - "description": { - "full": "

    The documents schema.

    ", - "summary": "

    The documents schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.schema;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "isNew" - } - ], - "description": { - "full": "

    Boolean flag specifying if the document is new.

    ", - "summary": "

    Boolean flag specifying if the document is new.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isNew;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "local": "Schema options /docs/guide.html#options", - "visibility": "Schema" - }, - { - "type": "property", - "string": "id" - } - ], - "description": { - "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", - "summary": "

    The string version of this documents _id.

    ", - "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.id;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "errors" - } - ], - "description": { - "full": "

    Hash containing current validation errors.

    ", - "summary": "

    Hash containing current validation errors.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.errors;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Builds the default doc structure

    ", - "summary": "

    Builds the default doc structure

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_buildDoc", - "string": "Document.prototype._buildDoc()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", - "summary": "

    Initializes the document without setters or marking anything modified.

    ", - "body": "

    Called internally after a document is returned from mongodb.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init', this);\n if (fn) fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "init", - "string": "Document.prototype.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "self", - "description": "document instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "raw mongodb doc" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "object we are initializing" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Init helper.

    ", - "summary": "

    Init helper.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", - "ctx": { - "type": "function", - "name": "init", - "string": "init()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", - "summary": "

    Stores the current values of the shard keys.

    ", - "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_storeShard", - "string": "Document.prototype._storeShard()" - } - }, - { - "tags": [], - "description": { - "full": "

    Set up middleware support

    ", - "summary": "

    Set up middleware support

    ", - "body": "" - }, - "ignore": true, - "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    ", - "summary": "

    Sends an update command with this document _id as the query selector.

    ", - "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "update", - "string": "Document.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "path", - "description": "path or object of key/vals to set" - }, - { - "type": "param", - "types": [ - "Any" - ], - "name": "val", - "description": "the value to set" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for \"on-the-fly\" attributes" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optionally specify options that modify the behavior of the set" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    ", - "summary": "

    Sets the value of a path, or many paths.

    ", - "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.set = function (path, val, type, options) {\n if (type && 'Object' == type.constructor.name) {\n options = type;\n type = undefined;\n }\n\n var merge = options && options.merge\n , adhoc = type && true !== type\n , constructing = true === type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n pathtype = this.schema.pathType(prefix + key);\n if (null != path[key]\n && 'Object' == path[key].constructor.name\n && 'virtual' != pathtype\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n if (!merge) this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "set", - "string": "Document.prototype.set()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determine if we should mark this change as modified.

    ", - "summary": "

    Determine if we should mark this change as modified.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._shouldModify = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n if (this.isNew) return true;\n if (this.isDirectModified(pathToMark)) return false;\n\n if (undefined === val && !this.isSelected(path)) {\n // when a path is not selected in a query, its initial\n // value will be undefined.\n return true;\n }\n\n if (undefined === val && path in this._activePaths.states.default) {\n // we're just unsetting the default value which was never saved\n return false;\n }\n\n if (!deepEqual(val, priorVal || this.get(path))) {\n return true;\n }\n\n if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n return true;\n }\n\n return false;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_shouldModify", - "string": "Document.prototype._shouldModify()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", - "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._set = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n var shouldModify = this._shouldModify.apply(this, arguments);\n\n if (shouldModify) {\n this.markModified(pathToMark, val);\n\n // handle directly setting arrays (gh-1126)\n MongooseArray || (MongooseArray = require('./types/array'));\n if (val instanceof MongooseArray) {\n val._registerAtomic('$set', val);\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_set", - "string": "Document.prototype._set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Gets a raw value from a path (no getters)

    ", - "summary": "

    Gets a raw value from a path (no getters)

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "getValue", - "string": "Document.prototype.getValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", - "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "setValue", - "string": "Document.prototype.setValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for on-the-fly attributes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", - "summary": "

    Returns the value of a path.

    ", - "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "get", - "string": "Document.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns the schematype for the given path.

    ", - "summary": "

    Returns the schematype for the given path.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_path", - "string": "Document.prototype._path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to mark modified" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", - "summary": "

    Marks the path as having pending changes to write to the db.

    ", - "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "markModified", - "string": "Document.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "function to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope with which to call fn" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", - "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "try", - "string": "Document.prototype.try()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the list of paths that have been modified.

    ", - "summary": "

    Returns the list of paths that have been modified.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "modifiedPaths", - "string": "Document.prototype.modifiedPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", - "summary": "

    Returns true if this document was modified, else false.

    ", - "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isModified", - "string": "Document.prototype.isModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", - "summary": "

    Returns true if path was directly set and modified, else false.

    ", - "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isDirectModified", - "string": "Document.prototype.isDirectModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Checks if path was initialized.

    ", - "summary": "

    Checks if path was initialized.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isInit", - "string": "Document.prototype.isInit()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", - "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", - "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isSelected", - "string": "Document.prototype.isSelected()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "cb", - "description": "called after validation completes, passing an error if one occurred" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", - "summary": "

    Executes registered validation rules for this document.

    ", - "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n paths = paths.concat(Object.keys(this._activePaths.states.default));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n self.emit('validate', self);\n cb(err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "validate", - "string": "Document.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "the error which states the reason `path` was invalid" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks a path as invalid, causing validation to fail.

    ", - "summary": "

    Marks a path as invalid, causing validation to fail.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "invalidate", - "string": "Document.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Resets the internal modified state of this document.

    ", - "summary": "

    Resets the internal modified state of this document.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n })\n .forEach(function (array) {\n var i = array.length;\n while (i--) {\n var doc = array[i];\n if (!doc) continue;\n doc._reset();\n }\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_reset", - "string": "Document.prototype._reset()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns this documents dirty paths / vals.

    ", - "summary": "

    Returns this documents dirty paths / vals.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_dirty", - "string": "Document.prototype._dirty()" - } - }, - { - "tags": [], - "description": { - "full": "

    Compiles schemas.

    ", - "summary": "

    Compiles schemas.

    ", - "body": "" - }, - "ignore": true, - "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", - "ctx": { - "type": "function", - "name": "compile", - "string": "compile()" - } - }, - { - "tags": [], - "description": { - "full": "

    Defines the accessor named prop on the incoming prototype.

    ", - "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", - "body": "" - }, - "ignore": true, - "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", - "ctx": { - "type": "function", - "name": "define", - "string": "define()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Assigns/compiles schema into this documents prototype.

    ", - "summary": "

    Assigns/compiles schema into this documents prototype.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_setSchema", - "string": "Document.prototype._setSchema()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register default hooks

    ", - "summary": "

    Register default hooks

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n if (error) return;\n\n // handle sparse arrays by using for loop vs array.forEach\n // which skips the sparse elements\n\n var len = array.length\n subdocs += len;\n\n for (var i = 0; i < len; ++i) {\n if (error) break;\n\n var doc = array[i];\n if (!doc) {\n --subdocs || next();\n continue;\n }\n\n doc.save(handleSave);\n }\n });\n\n function handleSave (err) {\n if (error) return;\n\n if (err) {\n self._validationError = undefined;\n return next(error = err);\n }\n\n --subdocs || next();\n }\n\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_registerHooks", - "string": "Document.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Registers an error

    ", - "summary": "

    Registers an error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_error", - "string": "Document.prototype._error()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes methods queued from the Schema definition

    ", - "summary": "

    Executes methods queued from the Schema definition

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "_doQueue", - "string": "Document.prototype._doQueue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "js object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Converts this document into a plain javascript object

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    ", - "summary": "

    Converts this document into a plain javascript object

    ", - "body": "

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n if (true === options.transform) {\n var opts = options.json\n ? this.schema.options.toJSON\n : this.schema.options.toObject;\n if (opts) {\n options.transform = opts.transform;\n }\n }\n\n if ('function' == typeof options.transform) {\n var xformed = options.transform(this, ret, options);\n if ('undefined' != typeof xformed) ret = xformed;\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toObject", - "string": "Document.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "json", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "either `virtuals` or `paths`" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "`json`" - } - ], - "description": { - "full": "

    Applies virtuals properties to json.

    ", - "summary": "

    Applies virtuals properties to json.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", - "ctx": { - "type": "function", - "name": "applyGetters", - "string": "applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "same options as [Document#toObject](#document_Document-toObject)" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "see", - "local": "Document#toObject #document_Document-toObject", - "visibility": "Document#toObject" - }, - { - "type": "", - "string": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    \n\n

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", - "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", - "body": "

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toJSON", - "string": "Document.prototype.toJSON()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "inspect", - "string": "Document.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "toString" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toString = Document.prototype.inspect;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "toString", - "value": "Document.prototype.inspect", - "string": "Document.prototypetoString" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "a document to compare" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", - "summary": "

    Returns true if the Document stores the same data as doc.

    ", - "body": "

    Documents are considered equal when they have matching _ids.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "equals", - "string": "Document.prototype.equals()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", - "ctx": { - "type": "property", - "receiver": "Document", - "name": "ValidationError", - "value": "ValidationError", - "string": "Document.ValidationError" - } - } -] -### lib/drivers/node-mongodb-native/binary.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require('mongodb').BSONPure.Binary", - "string": "Binary" - } - } -] -### lib/drivers/node-mongodb-native/collection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", - "ctx": { - "type": "declaration", - "name": "MongooseCollection", - "value": "require('../../collection')", - "string": "MongooseCollection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Collection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", - "summary": "

    A node-mongodb-native collection implementation.

    ", - "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", - "ctx": { - "type": "function", - "name": "NativeCollection", - "string": "NativeCollection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from abstract Collection.

    ", - "summary": "

    Inherit from abstract Collection.

    ", - "body": "" - }, - "ignore": true, - "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "__proto__", - "value": "MongooseCollection.prototype", - "string": "NativeCollection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection opens.

    ", - "summary": "

    Called when the connection opens.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onOpen", - "string": "NativeCollection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection closes

    ", - "summary": "

    Called when the connection closes

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onClose", - "string": "NativeCollection.prototype.onClose()" - } - }, - { - "tags": [], - "description": { - "full": "

    Copy the collection methods and make them subject to queues

    ", - "summary": "

    Copy the collection methods and make them subject to queues

    ", - "body": "" - }, - "ignore": true, - "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" - }, - { - "tags": [], - "description": { - "full": "

    Debug print helper

    ", - "summary": "

    Debug print helper

    ", - "body": "" - }, - "ignore": true, - "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", - "ctx": { - "type": "function", - "name": "print", - "string": "print()" - } - }, - { - "tags": [], - "description": { - "full": "

    Debug print helper

    ", - "summary": "

    Debug print helper

    ", - "body": "" - }, - "ignore": true, - "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if ('Date' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", - "ctx": { - "type": "function", - "name": "format", - "string": "format()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "method", - "string": "getIndexes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Retreives information about this collections indexes.

    ", - "summary": "

    Retreives information about this collections indexes.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "getIndexes", - "value": "NativeCollection.prototype.indexInformation", - "string": "NativeCollection.prototypegetIndexes" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeCollection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeCollection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/connection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", - "ctx": { - "type": "declaration", - "name": "MongooseConnection", - "value": "require('../../connection')", - "string": "MongooseConnection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Connection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A node-mongodb-native connection implementation.

    ", - "summary": "

    A node-mongodb-native connection implementation.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", - "ctx": { - "type": "function", - "name": "NativeConnection", - "string": "NativeConnection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Connection.

    ", - "summary": "

    Inherits from Connection.

    ", - "body": "" - }, - "ignore": true, - "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeConnection", - "name": "__proto__", - "value": "MongooseConnection.prototype", - "string": "NativeConnection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Opens the connection to MongoDB.

    ", - "summary": "

    Opens the connection to MongoDB.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, this.port, this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpen", - "string": "NativeConnection.prototype.doOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - } - ], - "description": { - "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", - "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", - "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , self = this\n\n this.hosts.forEach(function (server) {\n servers.push(new mongo.Server(server.host, server.port, self.options.server));\n })\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpenSet", - "string": "NativeConnection.prototype.doOpenSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Closes the connection

    ", - "summary": "

    Closes the connection

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doClose", - "string": "NativeConnection.prototype.doClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "passed", - "description": "options that were passed directly during connection" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[connStrOptions]", - "description": "options that were passed in the connection string" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Prepares default connection options for the node-mongodb-native driver.

    \n\n

    NOTE: passed options take precedence over connection string options.

    ", - "summary": "

    Prepares default connection options for the node-mongodb-native driver.

    ", - "body": "

    NOTE: passed options take precedence over connection string options.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {\n var o = passed || {};\n o.db || (o.db = {});\n o.server || (o.server = {});\n o.replset || (o.replset = {});\n o.server.socketOptions || (o.server.socketOptions = {});\n o.replset.socketOptions || (o.replset.socketOptions = {});\n\n var opts = connStrOpts || {};\n Object.keys(opts).forEach(function (name) {\n switch (name) {\n case 'poolSize':\n if ('undefined' == typeof o.server.poolSize) {\n o.server.poolSize = o.replset.poolSize = opts[name];\n }\n break;\n case 'slaveOk':\n if ('undefined' == typeof o.server.slave_ok) {\n o.server.slave_ok = opts[name];\n }\n break;\n case 'autoReconnect':\n if ('undefined' == typeof o.server.auto_reconnect) {\n o.server.auto_reconnect = opts[name];\n }\n break;\n case 'ssl':\n case 'socketTimeoutMS':\n case 'connectTimeoutMS':\n if ('undefined' == typeof o.server.socketOptions[name]) {\n o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];\n }\n break;\n case 'retries':\n case 'reconnectWait':\n case 'rs_name':\n if ('undefined' == typeof o.replset[name]) {\n o.replset[name] = opts[name];\n }\n break;\n case 'replicaSet':\n if ('undefined' == typeof o.replset.rs_name) {\n o.replset.rs_name = opts[name];\n }\n break;\n case 'readSecondary':\n if ('undefined' == typeof o.replset.read_secondary) {\n o.replset.read_secondary = opts[name];\n }\n break;\n case 'nativeParser':\n if ('undefined' == typeof o.db.native_parser) {\n o.db.native_parser = opts[name];\n }\n break;\n case 'w':\n case 'safe':\n case 'fsync':\n case 'journal':\n case 'wtimeoutMS':\n if ('undefined' == typeof o.db[name]) {\n o.db[name] = opts[name];\n }\n break;\n case 'readPreference':\n if ('undefined' == typeof o.db.read_preference) {\n o.db.read_preference = opts[name];\n }\n break;\n case 'readPreferenceTags':\n if ('undefined' == typeof o.db.read_preference_tags) {\n o.db.read_preference_tags = opts[name];\n }\n break;\n }\n })\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n if (!o.db.read_preference) {\n o.db.read_preference = 'primary';\n }\n\n o.db.forceServerObjectId = false;\n\n // default safe using new nomenclature\n if (!(o.db.journal || o.db.fsync || o.db.safe || 'w' in o.db)) {\n o.db.w = 1;\n }\n\n validate(o);\n return o;\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "parseOptions", - "string": "NativeConnection.prototype.parseOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "o", - "description": "" - } - ], - "description": { - "full": "

    Validates the driver db options.

    ", - "summary": "

    Validates the driver db options.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function validate (o) {\n if (-1 === o.db.w || 0 === o.db.w) {\n if (o.db.journal || o.db.fsync || o.db.safe) {\n throw new Error(\n 'Invalid writeConcern: '\n + 'w set to -1 or 0 cannot be combined with safe|fsync|journal');\n }\n }\n}", - "ctx": { - "type": "function", - "name": "validate", - "string": "validate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeConnection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeConnection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/objectid.js -[ - { - "tags": [ - { - "type": "constructor", - "string": "NodeMongoDbObjectId" - }, - { - "type": "see", - "local": "ObjectId", - "visibility": "ObjectId" - } - ], - "description": { - "full": "

    node-mongodb-native ObjectId

    ", - "summary": "

    node-mongodb-native ObjectId

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require('mongodb').BSONPure.ObjectID", - "string": "ObjectId" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", - "ctx": { - "type": "declaration", - "name": "ObjectIdToString", - "value": "ObjectId.toString.bind(ObjectId)", - "string": "ObjectIdToString" - } - } -] -### lib/error.js -[ - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" - } - ], - "description": { - "full": "

    Mongoose error

    ", - "summary": "

    Mongoose error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", - "ctx": { - "type": "function", - "name": "MongooseError", - "string": "MongooseError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Error.

    ", - "summary": "

    Inherits from Error.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseError.prototype.__proto__ = Error.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseError", - "name": "__proto__", - "value": "Error.prototype", - "string": "MongooseError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = MongooseError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = MongooseError", - "string": "module.exports" - } - }, - { - "tags": [], - "description": { - "full": "

    Expose subclasses

    ", - "summary": "

    Expose subclasses

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseError.CastError = require('./errors/cast');\nMongooseError.DocumentError = require('./errors/document');\nMongooseError.ValidationError = require('./errors/validation')\nMongooseError.ValidatorError = require('./errors/validator')\nMongooseError.VersionError =require('./errors/version')\nMongooseError.OverwriteModelError = require('./errors/overwriteModel')\nMongooseError.MissingSchemaError = require('./errors/missingSchema')", - "ctx": { - "type": "property", - "receiver": "MongooseError", - "name": "CastError", - "value": "require('./errors/cast')", - "string": "MongooseError.CastError" - } - } -] -### lib/errors/cast.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casting Error constructor.

    ", - "summary": "

    Casting Error constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", - "ctx": { - "type": "function", - "name": "CastError", - "string": "CastError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "CastError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "CastError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "CastError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = CastError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "CastError", - "string": "module.exports" - } - } -] -### lib/errors/document.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements

    ", - "summary": "

    Module requirements

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Document Error

    ", - "summary": "

    Document Error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", - "ctx": { - "type": "function", - "name": "DocumentError", - "string": "DocumentError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "DocumentError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = DocumentError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = DocumentError", - "string": "module.exports" - } - } -] -### lib/errors/missingSchema.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

    MissingSchema Error constructor.

    ", - "summary": "

    MissingSchema Error constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function MissingSchemaError (name) {\n var msg = 'Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)';\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'MissingSchemaError';\n};", - "ctx": { - "type": "function", - "name": "MissingSchemaError", - "string": "MissingSchemaError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "MissingSchemaError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "MissingSchemaError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "MissingSchemaError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = MissingSchemaError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MissingSchemaError", - "string": "module.exports" - } - } -] -### lib/errors/overwriteModel.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

    OverwriteModel Error constructor.

    ", - "summary": "

    OverwriteModel Error constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function OverwriteModelError (name) {\n MongooseError.call(this, 'Cannot overwrite `' + name + '` model once compiled.');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'OverwriteModelError';\n};", - "ctx": { - "type": "function", - "name": "OverwriteModelError", - "string": "OverwriteModelError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "OverwriteModelError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "OverwriteModelError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "OverwriteModelError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = OverwriteModelError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "OverwriteModelError", - "string": "module.exports" - } - } -] -### lib/errors/validation.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements

    ", - "summary": "

    Module requirements

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "instance", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

    Document Validation Error

    ", - "summary": "

    Document Validation Error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", - "ctx": { - "type": "function", - "name": "ValidationError", - "string": "ValidationError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Console.log helper

    ", - "summary": "

    Console.log helper

    ", - "body": "" - }, - "ignore": false, - "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", - "ctx": { - "type": "method", - "constructor": "ValidationError", - "name": "toString", - "string": "ValidationError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidationError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidationError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports

    ", - "summary": "

    Module exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = ValidationError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = ValidationError", - "string": "module.exports" - } - } -] -### lib/errors/validator.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Schema validator error

    ", - "summary": "

    Schema validator error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", - "ctx": { - "type": "function", - "name": "ValidatorError", - "string": "ValidatorError()" - } - }, - { - "tags": [], - "description": { - "full": "

    toString helper

    ", - "summary": "

    toString helper

    ", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", - "ctx": { - "type": "method", - "constructor": "ValidatorError", - "name": "toString", - "string": "ValidatorError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError

    ", - "summary": "

    Inherits from MongooseError

    ", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidatorError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidatorError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ValidatorError", - "string": "module.exports" - } - } -] -### lib/errors/version.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Version Error constructor.

    ", - "summary": "

    Version Error constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function VersionError () {\n MongooseError.call(this, 'No matching document found.');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'VersionError';\n};", - "ctx": { - "type": "function", - "name": "VersionError", - "string": "VersionError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "VersionError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "VersionError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "VersionError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = VersionError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "VersionError", - "string": "module.exports" - } - } -] -### lib/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", - "summary": "

    Mongoose constructor.

    ", - "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", - "ctx": { - "type": "function", - "name": "Mongoose", - "string": "Mongoose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", - "summary": "

    Sets mongoose options

    ", - "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "set", - "string": "Mongoose.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "method", - "string": "get" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", - "summary": "

    Gets mongoose options

    ", - "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.get = Mongoose.prototype.set;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "get", - "value": "Mongoose.prototype.set", - "string": "Mongoose.prototypeget" - } - }, - { - "tags": [], - "description": { - "full": "

    ReplSet connection string check.

    ", - "summary": "

    ReplSet connection string check.

    ", - "body": "" - }, - "ignore": true, - "code": "var rgxReplSet = /^.+,.+$/;", - "ctx": { - "type": "declaration", - "name": "rgxReplSet", - "value": "/^.+,.+$/", - "string": "rgxReplSet" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[uri]", - "description": "a mongodb:// URI" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options to pass to the driver" - }, - { - "type": "see", - "local": "Connection#open #connection_Connection-open", - "visibility": "Connection#open" - }, - { - "type": "see", - "local": "Connection#openSet #connection_Connection-openSet", - "visibility": "Connection#openSet" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "the created Connection object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Connection instance.

    \n\n

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    ", - "summary": "

    Creates a Connection instance.

    ", - "body": "

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "createConnection", - "string": "Mongoose.prototype.createConnection()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Mongoose#createConnection #index_Mongoose-createConnection", - "visibility": "Mongoose#createConnection" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - } - ], - "description": { - "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    \n\n

    Options passed take precedence over options included in connection strings.

    ", - "summary": "

    Opens the default mongoose connection.

    ", - "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    \n\n

    Options passed take precedence over options included in connection strings.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "connect", - "string": "Mongoose.prototype.connect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "called after all connection close." - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Disconnects all connections.

    ", - "summary": "

    Disconnects all connections.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "disconnect", - "string": "Mongoose.prototype.disconnect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name (optional, induced from model name)" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipInit]", - "description": "whether to skip initialization (defaults to false)" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    ", - "summary": "

    Defines a model or retrieves it.

    ", - "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // handle internal options from connection.model()\n var options;\n if (skipInit && utils.isObject(skipInit)) {\n options = skipInit;\n skipInit = true;\n } else {\n options = {};\n }\n\n // look up schema for the collection. this might be a\n // default schema like system.indexes stored in SchemaDefaults.\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n // cache it so we only apply plugins once\n this.modelSchemas[name] = schema;\n this._applyPlugins(schema);\n } else {\n throw new mongoose.Error.MissingSchemaError(name);\n }\n }\n\n var model;\n var sub;\n\n // connection.model() may be passing a different schema for\n // an existing model name. in this case don't read from cache.\n if (this.models[name] && false !== options.cache) {\n if (schema instanceof Schema && schema != this.models[name].schema) {\n throw new mongoose.Error.OverwriteModelError(name);\n }\n\n if (collection) {\n // subclass current model with alternate collection\n model = this.models[name];\n schema = model.prototype.schema;\n sub = model.__subclass(this.connection, schema, collection);\n // do not cache the sub model\n return sub;\n }\n\n return this.models[name];\n }\n\n // ensure a schema exists\n if (!schema) {\n schema = this.modelSchemas[name];\n if (!schema) {\n throw new mongoose.Error.MissingSchemaError(name);\n }\n }\n\n if (!collection) {\n collection = schema.get('collection') || format(name);\n }\n\n var connection = options.connection || this.connection;\n model = Model.compile(name, schema, collection, connection, this);\n\n if (!skipInit) {\n model.init();\n }\n\n if (false === options.cache) {\n return model;\n }\n\n return this.models[name] = model;\n}", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "model", - "string": "Mongoose.prototype.model()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies global plugins to schema.

    ", - "summary": "

    Applies global plugins to schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mongoose.prototype._applyPlugins = function (schema) {\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n}", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "_applyPlugins", - "string": "Mongoose.prototype._applyPlugins()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "plugin callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "optional options" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "see", - "local": "plugins ./plugins.html", - "visibility": "plugins" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", - "summary": "

    Declares a global plugin executed on all Schemas.

    ", - "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "plugin", - "string": "Mongoose.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "connection" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", - "summary": "

    The default connection of the mongoose module.

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" - }, - { - "tags": [], - "description": { - "full": "

    Driver depentend APIs

    ", - "summary": "

    Driver depentend APIs

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

    Connection

    ", - "summary": "

    Connection

    ", - "body": "" - }, - "ignore": true, - "code": "var Connection = require(driver + '/connection');", - "ctx": { - "type": "declaration", - "name": "Connection", - "value": "require(driver + '/connection')", - "string": "Connection" - } - }, - { - "tags": [], - "description": { - "full": "

    Collection

    ", - "summary": "

    Collection

    ", - "body": "" - }, - "ignore": true, - "code": "var Collection = require(driver + '/collection');", - "ctx": { - "type": "declaration", - "name": "Collection", - "value": "require(driver + '/collection')", - "string": "Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The exports object is an instance of Mongoose.

    ", - "summary": "

    The exports object is an instance of Mongoose.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = new Mongoose", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Collection constructor

    ", - "summary": "

    The Mongoose Collection constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Collection = Collection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Collection", - "value": "Collection", - "string": "mongoose.Collection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Connection constructor

    ", - "summary": "

    The Mongoose Connection constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Connection = Connection;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Connection", - "value": "Connection", - "string": "mongoose.Connection" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Mongoose version

    ", - "summary": "

    Mongoose version

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "version", - "value": "JSON.parse(", - "string": "mongoose.version" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", - "summary": "

    The Mongoose constructor

    ", - "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Mongoose = Mongoose;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Mongoose", - "value": "Mongoose", - "string": "mongoose.Mongoose" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", - "summary": "

    The Mongoose Schema constructor

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Schema = Schema;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Schema", - "value": "Schema", - "string": "mongoose.Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose SchemaType constructor.

    ", - "summary": "

    The Mongoose SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaType = SchemaType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaType", - "value": "SchemaType", - "string": "mongoose.SchemaType" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Schema.SchemaTypes #schema_Schema-Types", - "visibility": "Schema.SchemaTypes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", - "summary": "

    The various Mongoose SchemaTypes.

    ", - "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.SchemaTypes = Schema.Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "SchemaTypes", - "value": "Schema.Types", - "string": "mongoose.SchemaTypes" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose VirtualType constructor.

    ", - "summary": "

    The Mongoose VirtualType constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.VirtualType = VirtualType;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "VirtualType", - "value": "VirtualType", - "string": "mongoose.VirtualType" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", - "summary": "

    The various Mongoose Types.

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Types = Types;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Types", - "value": "Types", - "string": "mongoose.Types" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Query constructor.

    ", - "summary": "

    The Mongoose Query constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Query = Query;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Query", - "value": "Query", - "string": "mongoose.Query" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Promise constructor.

    ", - "summary": "

    The Mongoose Promise constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Promise = Promise;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Promise", - "value": "Promise", - "string": "mongoose.Promise" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Model constructor.

    ", - "summary": "

    The Mongoose Model constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Model = Model;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Model", - "value": "Model", - "string": "mongoose.Model" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Document constructor.

    ", - "summary": "

    The Mongoose Document constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Document = Document;", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Document", - "value": "Document", - "string": "mongoose.Document" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The MongooseError constructor.

    ", - "summary": "

    The MongooseError constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.Error = require('./error');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "Error", - "value": "require('./error')", - "string": "mongoose.Error" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The node-mongodb-native driver Mongoose uses.

    ", - "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "mongoose.mongo = require('mongodb');", - "ctx": { - "type": "property", - "receiver": "mongoose", - "name": "mongo", - "value": "require('mongodb')", - "string": "mongoose.mongo" - } - } -] -### lib/model.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , VersionError = require('./errors/version')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('./document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "values to with which to create the document" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "event", - "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." - }, - { - "type": "event", - "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Model constructor

    ", - "summary": "

    Model constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", - "ctx": { - "type": "function", - "name": "Model", - "string": "Model()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Document.

    \n\n

    All Model.prototype features are available on
    top level (non-sub) documents.

    ", - "summary": "

    Inherits from Document.

    ", - "body": "

    All Model.prototype features are available on
    top level (non-sub) documents.

    " - }, - "ignore": true, - "code": "Model.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "Model", - "name": "__proto__", - "value": "Document.prototype", - "string": "Model.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

    Connection the model uses.

    ", - "summary": "

    Connection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.db;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "collection" - } - ], - "description": { - "full": "

    Collection the model uses.

    ", - "summary": "

    Collection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.collection;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "modelName" - } - ], - "description": { - "full": "

    The name of the model

    ", - "summary": "

    The name of the model

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.modelName;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "object" - }, - { - "type": "return", - "types": [ - "Object", - "undefined" - ], - "description": "population paths" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns what paths can be populated

    ", - "summary": "

    Returns what paths can be populated

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_getPopulationKeys", - "string": "Model.prototype._getPopulationKeys()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "schema", - "description": "type for the oid" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "oid", - "description": "object id or array of object ids" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "query", - "description": "object specifying query conditions, fields, and options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Populates an object

    ", - "summary": "

    Populates an object

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_populate", - "string": "Model.prototype._populate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "query that originated the initialization" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs auto-population of relations.

    ", - "summary": "

    Performs auto-population of relations.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "init", - "string": "Model.prototype.init()" - } - }, - { - "tags": [], - "description": { - "full": "

    Handles doc.save() callbacks

    ", - "summary": "

    Handles doc.save() callbacks

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new VersionError);\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", - "ctx": { - "type": "function", - "name": "handleSave", - "string": "handleSave()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "title": "middleware", - "url": "http://mongoosejs.com/docs/middleware.html", - "visibility": "http://mongoosejs.com/docs/middleware.html" - } - ], - "description": { - "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", - "summary": "

    Saves this document.

    ", - "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n process.nextTick(function () {\n complete(null);\n })\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "save", - "string": "Model.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Mixed" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[operation]", - "description": "" - } - ], - "description": { - "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", - "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", - "ctx": { - "type": "function", - "name": "operand", - "string": "operand()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "val", - "description": "" - } - ], - "description": { - "full": "

    Compiles an update and where clause for a val with _atomics.

    ", - "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", - "ctx": { - "type": "function", - "name": "handleAtomics", - "string": "handleAtomics()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Produces a special query document of the modified properties used in updates.

    ", - "summary": "

    Produces a special query document of the modified properties used in updates.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n // arrays and other custom types (support plugins etc)\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_delta", - "string": "Model.prototype._delta()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Appends versioning to the where and update clauses.

    ", - "summary": "

    Appends versioning to the where and update clauses.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_version", - "string": "Model.prototype._version()" - } - }, - { - "tags": [ - { - "type": "see", - "title": "versionKeys", - "url": "http://mongoosejs.com/docs/guide.html#versionKey", - "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Signal that we desire an increment of this documents version.

    ", - "summary": "

    Signal that we desire an increment of this documents version.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "increment", - "string": "Model.prototype.increment()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns a query object which applies shardkeys if they exist.

    ", - "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_where", - "string": "Model.prototype._where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", - "summary": "

    Removes this document from the db.

    ", - "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) {\n this._removing.addBack(fn);\n return this;\n }\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "remove", - "string": "Model.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register hooks override

    ", - "summary": "

    Register hooks override

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "_registerHooks", - "string": "Model.prototype._registerHooks()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", - "summary": "

    Returns another Model instance.

    ", - "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};\n\n// Model (class) features", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "model", - "string": "Model.prototype.model()" - } - }, - { - "tags": [], - "description": { - "full": "

    Give the constructor the ability to emit events.

    ", - "summary": "

    Give the constructor the ability to emit events.

    ", - "body": "" - }, - "ignore": true, - "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the model compiles.

    ", - "summary": "

    Called when the model compiles.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.init = function init () {\n if (this.schema.options.autoIndex) {\n this.ensureIndexes();\n }\n\n this.schema.emit('init', this);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "init", - "string": "Model.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[cb]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    ", - "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", - "body": "

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "ensureIndexes", - "string": "Model.ensureIndexes()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "schema" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Schema the model uses.

    ", - "summary": "

    Schema the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.schema;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Database instance the model uses.

    ", - "summary": "

    Database instance the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.db;" - }, - { - "tags": [ - { - "type": "property", - "string": "collection" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Collection the model uses.

    ", - "summary": "

    Collection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.collection;" - }, - { - "tags": [ - { - "type": "property", - "string": "base" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Base Mongoose instance the model uses.

    ", - "summary": "

    Base Mongoose instance the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.base;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes documents from the collection.

    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    ", - "summary": "

    Removes documents from the collection.

    ", - "body": "

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "remove", - "string": "Model.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds documents

    \n\n

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    ", - "summary": "

    Finds documents

    ", - "body": "

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "find", - "string": "Model.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Merges the current named scope query into query.

    ", - "summary": "

    Merges the current named scope query into query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "_applyNamedScope", - "string": "Model._applyNamedScope()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "objectid, or a value that can be casted to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds a single document by id.

    \n\n

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    ", - "summary": "

    Finds a single document by id.

    ", - "body": "

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findById", - "string": "Model.findById()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    ", - "summary": "

    Finds one document.

    ", - "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOne", - "string": "Model.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", - "summary": "

    Counts number of matching documents in a database collection.

    ", - "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "count", - "string": "Model.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes a DISTINCT command

    ", - "summary": "

    Executes a DISTINCT command

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "distinct", - "string": "Model.distinct()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "optional value" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", - "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", - "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "where", - "string": "Model.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "argument", - "description": "is a javascript string or anonymous function" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "memberOf", - "parent": "Model" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Query.$where #query_Query-%24where", - "visibility": "Query.$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    ", - "summary": "

    Creates a Query and specifies a $where condition.

    ", - "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Issues a mongodb findAndModify update command.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndUpdate", - "string": "Model.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "an ObjectId or string that can be cast to one." - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", - "visibility": "Model.findOneAndUpdate" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndUpdate", - "string": "Model.findByIdAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", - "summary": "

    Issue a mongodb findAndModify remove command.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndRemove", - "string": "Model.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "id", - "description": "ObjectId or string that can be cast to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", - "visibility": "Model.findOneAndRemove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - } - ], - "description": { - "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", - "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndRemove", - "string": "Model.findByIdAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array", - "Object..." - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", - "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", - "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "create", - "string": "Model.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "update", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Updates documents in the database without returning them.

    ", - "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "update", - "string": "Model.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "o", - "description": "an object specifying map-reduce options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/MapReduce", - "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", - "summary": "

    Executes a mapReduce command.

    ", - "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "mapReduce", - "string": "Model.mapReduce()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "an array of pipeline commands" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "aggregation", - "url": "http://docs.mongodb.org/manual/applications/aggregation/", - "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", - "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes an aggregate command on this models collection.

    \n\n

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    ", - "summary": "

    Executes an aggregate command on this models collection.

    ", - "body": "

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "aggregate", - "string": "Model.aggregate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "collectionName", - "description": "" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "connection", - "description": "" - }, - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "mongoose instance" - } - ], - "description": { - "full": "

    Compiler utility.

    ", - "summary": "

    Compiler utility.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "compile", - "string": "Model.compile()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Connection" - ], - "name": "conn", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "" - }, - { - "type": "return", - "types": [ - "Model" - ], - "description": "" - } - ], - "description": { - "full": "

    Subclass this model with conn, schema, and collection settings.

    ", - "summary": "

    Subclass this model with conn, schema, and collection settings.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.__subclass = function subclass (conn, schema, collection) {\n // subclass model using this connection and collection name\n var model = this;\n\n var Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model)) {\n return new Model(doc, fields, skipId);\n }\n model.call(this, doc, fields, skipId);\n }\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = conn;\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n if (!collection) {\n collection = model.prototype.schema.get('collection')\n || utils.toCollectionName(model.modelName);\n }\n\n Model.prototype.collection = conn.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n return Model;\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "__subclass", - "string": "Model.__subclass()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Model;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Model", - "string": "module.exports" - } - } -] -### lib/namedscope.js -[ - { - "tags": [ - { - "type": "param", - "types": [ - "NamedScope" - ], - "name": "target", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "getters", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Decorate

    ", - "summary": "

    Decorate

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", - "ctx": { - "type": "method", - "constructor": "NamedScope", - "name": "decorate", - "string": "NamedScope.prototype.decorate()" - } - } -] -### lib/promise.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", - "ctx": { - "type": "declaration", - "name": "util", - "value": "require('./utils')", - "string": "util" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "back", - "description": "a callback+errback that accepts `fn(err, ...){}` as signature" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`err`: Emits when the promise resolves to an error." - }, - { - "type": "event", - "string": "`complete`: Emits when the promise resolves sucessfully." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Promise constructor.

    ", - "summary": "

    Promise constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", - "ctx": { - "type": "function", - "name": "Promise", - "string": "Promise()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from EventEmitter.

    ", - "summary": "

    Inherits from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Promise", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Promise.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Event" - ], - "name": "event", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds listener to the event.

    \n\n

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", - "summary": "

    Adds listener to the event.

    ", - "body": "

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "on", - "string": "Promise.prototype.on()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Keeps track of emitted events to run them on on.

    ", - "summary": "

    Keeps track of emitted events to run them on on.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "emit", - "string": "Promise.prototype.emit()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for emitting the complete event.

    ", - "summary": "

    Shortcut for emitting the complete event.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "complete", - "string": "Promise.prototype.complete()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

    Shortcut for emitting the err event.

    ", - "summary": "

    Shortcut for emitting the err event.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "error", - "string": "Promise.prototype.error()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for .on('complete', fn).

    ", - "summary": "

    Shortcut for .on('complete', fn).

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addCallback", - "string": "Promise.prototype.addCallback()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for .on('err', fn).

    ", - "summary": "

    Shortcut for .on('err', fn).

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addErrback", - "string": "Promise.prototype.addErrback()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - } - ], - "description": { - "full": "

    Adds a single function that's both a callback and errback.

    ", - "summary": "

    Adds a single function that's both a callback and errback.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "addBack", - "string": "Promise.prototype.addBack()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "optional error or null" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "value to complete the promise with" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", - "summary": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "resolve", - "string": "Promise.prototype.resolve()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Promise;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Promise", - "string": "module.exports" - } - } -] -### lib/query.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "criteria", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", - "summary": "

    Query constructor used for building queries.

    ", - "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n if (criteria) this.find(criteria);\n}", - "ctx": { - "type": "function", - "name": "Query", - "string": "Query()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", - "summary": "

    Sets query options.

    ", - "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "setOptions", - "string": "Query.prototype.setOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "the model to which the query is bound" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "the operation to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "updateArg", - "description": "used in update methods" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Binds this query to a model.

    ", - "summary": "

    Binds this query to a model.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "bind", - "string": "Query.prototype.bind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "[operation]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", - "summary": "

    Executes the query

    ", - "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exec", - "string": "Query.prototype.exec()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[criteria]", - "description": "mongodb selector" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", - "summary": "

    Finds documents.

    ", - "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "find", - "string": "Query.prototype.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[obj]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", - "summary": "

    Casts this query to the schema of model

    ", - "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path || '$and' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "cast", - "string": "Query.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns default options.

    ", - "summary": "

    Returns default options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_optionsForExec", - "string": "Query.prototype._optionsForExec()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies schematype selected options to this query.

    ", - "summary": "

    Applies schematype selected options to this query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_applyPaths", - "string": "Query.prototype._applyPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "js", - "description": "javascript string or function" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", - "summary": "

    Specifies a $where condition

    ", - "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", - "summary": "

    Specifies a path for use with chaining.

    ", - "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "where", - "string": "Query.prototype.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", - "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", - "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "equals", - "string": "Query.prototype.equals()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", - "summary": "

    Specifies arguments for an $or condition.

    ", - "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "or", - "string": "Query.prototype.or()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", - "summary": "

    Specifies arguments for a $nor condition.

    ", - "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nor", - "string": "Query.prototype.nor()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for a $and condition.

    \n\n

    Example

    \n\n
    query.and([{ color: 'green' }, { status: 'ok' }])\n
    ", - "summary": "

    Specifies arguments for a $and condition.

    ", - "body": "

    Example

    \n\n
    query.and([{ color: 'green' }, { status: 'ok' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.and = function and (array) {\n var and = this._conditions.$and || (this._conditions.$and = []);\n if (!Array.isArray(array)) array = [array];\n and.push.apply(and, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "and", - "string": "Query.prototype.and()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "gt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", - "summary": "

    Specifies a $gt query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "gte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $gte query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $lt query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $lte query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "ne" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $ne query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "in" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $in query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "nin" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $nin query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "all" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $all query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "size" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $size query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "regex" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $regex query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxDistance" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $maxDistance query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", - "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", - "body": "
    Thing.where('type').nin(array)\n
    " - }, - "ignore": true, - "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $near condition

    ", - "summary": "

    Specifies a $near condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "near", - "string": "Query.prototype.near()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $nearSphere condition.

    ", - "summary": "

    Specifies a $nearSphere condition.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nearSphere", - "string": "Query.prototype.nearSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $mod condition

    ", - "summary": "

    Specifies a $mod condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "mod", - "string": "Query.prototype.mod()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $exists condition

    ", - "summary": "

    Specifies an $exists condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exists", - "string": "Query.prototype.exists()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object", - "Function" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "Function" - ], - "name": "criteria", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", - "summary": "

    Specifies an $elemMatch condition

    ", - "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "elemMatch", - "string": "Query.prototype.elemMatch()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "within" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Syntax sugar for expressive queries.

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    ", - "summary": "

    Syntax sugar for expressive queries.

    ", - "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "see", - "local": "Query#within #query_Query-within", - "visibility": "Query#within" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", - "summary": "

    Specifies a $box condition

    ", - "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "box", - "string": "Query.prototype.box()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "options e.g. { $uniqueDocs: true }" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", - "summary": "

    Specifies a $center condition

    ", - "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "center", - "string": "Query.prototype.center()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", - "summary": "

    Specifies a $centerSphere condition

    ", - "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "centerSphere", - "string": "Query.prototype.centerSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Array", - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", - "summary": "

    Specifies a $polygon condition

    ", - "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "polygon", - "string": "Query.prototype.polygon()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "local": "SchemaType", - "visibility": "SchemaType" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    ", - "summary": "

    Specifies which document fields to include or exclude

    ", - "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "select", - "string": "Query.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "number of elements to slice" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", - "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", - "summary": "

    Specifies a $slice condition

    ", - "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slice", - "string": "Query.prototype.slice()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", - "summary": "

    Sets the sort order

    ", - "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "sort", - "string": "Query.prototype.sort()" - } - }, - { - "tags": [], - "description": { - "full": "

    @ignore

    ", - "summary": "

    @ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", - "ctx": { - "type": "function", - "name": "push", - "string": "push()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "limit" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", - "summary": "

    Specifies the limit option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "skip" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", - "summary": "

    Specifies the skip option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxscan" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", - "summary": "

    Specifies the maxscan option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "batchSize" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", - "summary": "

    Specifies the batchSize option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "comment" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", - "summary": "

    Specifies the comment option.

    ", - "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", - "summary": "

    limit, skip, maxscan, batchSize, comment

    ", - "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " - }, - "ignore": true, - "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", - "summary": "

    Specifies this query as a snapshot query.

    ", - "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "snapshot", - "string": "Query.prototype.snapshot()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "a hint object" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", - "summary": "

    Sets query hints.

    ", - "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "hint", - "string": "Query.prototype.hint()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", - "summary": "

    Sets the slaveOk option.

    ", - "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slaveOk", - "string": "Query.prototype.slaveOk()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "one of the listed preference options or their aliases" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "[tags]", - "description": "optional tags for this query" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", - "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the readPreference option for the query.

    \n\n

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    ", - "summary": "

    Sets the readPreference option for the query.

    ", - "body": "

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "read", - "string": "Query.prototype.read()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", - "summary": "

    Sets the lean option.

    ", - "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "lean", - "string": "Query.prototype.lean()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", - "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", - "summary": "

    Sets tailable option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "tailable", - "string": "Query.prototype.tailable()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes the query as a find() operation.

    ", - "summary": "

    Executes the query as a find() operation.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "execFind", - "string": "Query.prototype.execFind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", - "summary": "

    Executes the query as a findOne() operation.

    ", - "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOne", - "string": "Query.prototype.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", - "summary": "

    Exectues the query as a count() operation.

    ", - "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "count", - "string": "Query.prototype.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as a distict() operation.

    ", - "summary": "

    Executes this query as a distict() operation.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "distinct", - "string": "Query.prototype.distinct()" - } - }, - { - "tags": [], - "description": { - "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", - "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", - "body": "" - }, - "ignore": true, - "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", - "ctx": { - "type": "declaration", - "name": "castOps", - "value": "{", - "string": "castOps" - } - }, - { - "tags": [], - "description": { - "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", - "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", - "body": "" - }, - "ignore": true, - "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", - "ctx": { - "type": "declaration", - "name": "numberOps", - "value": "{", - "string": "numberOps" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "the update conditions" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", - "summary": "

    Executes this query as an update() operation.

    ", - "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n options.safe = { w: 0 };\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "update", - "string": "Query.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "obj after casting its values" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts obj for an update command.

    ", - "summary": "

    Casts obj for an update command.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdate", - "string": "Query.prototype._castUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "- part of a query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "- path prefix (internal only)" - }, - { - "type": "return", - "types": [ - "Bool" - ], - "description": "true if this path has keys to update" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", - "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_walkUpdatePath", - "string": "Query.prototype._walkUpdatePath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[$conditional]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts val according to schema and atomic op.

    ", - "summary": "

    Casts val according to schema and atomic op.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdateVal", - "string": "Query.prototype._castUpdateVal()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_getSchema", - "string": "Query.prototype._getSchema()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "https://github.com/LearnBoost/mongoose/issues/1091", - "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" - }, - { - "type": "see", - "title": "", - "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", - "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts selected field arguments for field selection with mongo 2.2

    \n\n
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    ", - "summary": "

    Casts selected field arguments for field selection with mongo 2.2

    ", - "body": "
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castFields", - "string": "Query.prototype._castFields()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", - "summary": "

    Executes this query as a remove() operation.

    ", - "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n options.safe = { w: 0 };\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "remove", - "string": "Query.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[query]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[doc]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", - "summary": "

    Issues a mongodb findAndModify update command.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndUpdate", - "string": "Query.prototype.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", - "summary": "

    Issues a mongodb findAndModify remove command.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndRemove", - "string": "Query.prototype.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "- either \"remove\" or \"update\"" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    _findAndModify

    ", - "summary": "

    _findAndModify

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n this._applyPaths();\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_findAndModify", - "string": "Query.prototype._findAndModify()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Model" - ], - "name": "[model]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "see", - "local": "population ./populate.html", - "visibility": "population" - }, - { - "type": "see", - "local": "Query#select #query_Query-select", - "visibility": "Query#select" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    ", - "summary": "

    Specifies paths which should be populated with other documents.

    ", - "body": "

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "populate", - "string": "Query.prototype.populate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Populate options constructor

    ", - "summary": "

    Populate options constructor

    ", - "body": "" - }, - "ignore": true, - "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", - "ctx": { - "type": "function", - "name": "PopulateOptions", - "string": "PopulateOptions()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "QueryStream" - ], - "description": "" - }, - { - "type": "see", - "local": "QueryStream", - "visibility": "QueryStream" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a stream interface

    \n\n

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    ", - "summary": "

    Returns a stream interface

    ", - "body": "

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "stream", - "string": "Query.prototype.stream()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    castDoc

    ", - "summary": "

    castDoc

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castDoc", - "string": "castDoc()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    castQuery

    ", - "summary": "

    castQuery

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castQuery", - "string": "castQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Exports.

    ", - "summary": "

    Exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Query", - "string": "module.exports" - } - } -] -### lib/querystream.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", - "ctx": { - "type": "declaration", - "name": "Stream", - "value": "require('stream').Stream", - "string": "Stream" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS Stream http://nodejs.org/api/stream.html" - }, - { - "type": "event", - "string": "`data`: emits a single Mongoose document" - }, - { - "type": "event", - "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." - }, - { - "type": "event", - "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Provides a ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    ", - "summary": "

    Provides a ReadStream interface for Queries.

    ", - "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n this._running = false;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", - "ctx": { - "type": "function", - "name": "QueryStream", - "string": "QueryStream()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Stream

    ", - "summary": "

    Inherit from Stream

    ", - "body": "" - }, - "ignore": true, - "code": "QueryStream.prototype.__proto__ = Stream.prototype;", - "ctx": { - "type": "property", - "constructor": "QueryStream", - "name": "__proto__", - "value": "Stream.prototype", - "string": "QueryStream.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readable" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Flag stating whether or not this stream is readable.

    ", - "summary": "

    Flag stating whether or not this stream is readable.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.readable;" - }, - { - "tags": [ - { - "type": "property", - "string": "paused" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Flag stating whether or not this stream is paused.

    ", - "summary": "

    Flag stating whether or not this stream is paused.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Initializes the query.

    ", - "summary": "

    Initializes the query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_init", - "string": "QueryStream.prototype._init()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#__next #querystream_QueryStream-__next", - "visibility": "QueryStream#__next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Trampoline for pulling the next doc from cursor.

    ", - "summary": "

    Trampoline for pulling the next doc from cursor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) {\n return this._running = false;\n }\n\n this._running = true;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n while (this.__next()) {}\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_next", - "string": "QueryStream.prototype._next()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#_next #querystream_QueryStream-_next", - "visibility": "QueryStream#_next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Pulls the next doc from the cursor.

    ", - "summary": "

    Pulls the next doc from the cursor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed)\n return this._running = false;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "__next", - "string": "QueryStream.prototype.__next()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error", - "null" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", - "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return this._running = false;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && true === this.query.options.lean) {\n this.emit('data', doc);\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_onNextObject", - "string": "QueryStream.prototype._onNextObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pauses this stream.

    ", - "summary": "

    Pauses this stream.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "pause", - "string": "QueryStream.prototype.pause()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Resumes this stream.

    ", - "summary": "

    Resumes this stream.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n\n if (!this._cursor) {\n // cannot start if not initialized\n return;\n }\n\n // are we within the trampoline?\n if (T_INIT === this._inline) {\n return;\n }\n\n if (!this._running) {\n // outside QueryStream control, need manual restart\n return this._next();\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "resume", - "string": "QueryStream.prototype.resume()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "[err]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", - "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this._running = false;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "destroy", - "string": "QueryStream.prototype.destroy()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "pipe" - }, - { - "type": "memberOf", - "parent": "QueryStream" - }, - { - "type": "see", - "title": "NodeJS", - "url": "http://nodejs.org/api/stream.html", - "visibility": "http://nodejs.org/api/stream.html" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", - "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", - "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    Module exports

    ", - "summary": "

    Module exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = QueryStream", - "string": "module.exports" - } - } -] -### lib/schema/array.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Array SchemaType constructor

    ", - "summary": "

    Array SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "SchemaArray", - "string": "SchemaArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaArray", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "checkRequired", - "string": "SchemaArray.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Overrides the getters application for the population special-case

    ", - "summary": "

    Overrides the getters application for the population special-case

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "applyGetters", - "string": "SchemaArray.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "cast", - "string": "SchemaArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "castForQuery", - "string": "SchemaArray.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    @ignore

    ", - "summary": "

    @ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': SchemaArray.prototype.castForQuery\n , '$gte': SchemaArray.prototype.castForQuery\n , '$lt': SchemaArray.prototype.castForQuery\n , '$lte': SchemaArray.prototype.castForQuery\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", - "ctx": { - "type": "function", - "name": "castToNumber", - "string": "castToNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaArray", - "string": "module.exports" - } - } -] -### lib/schema/boolean.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Boolean SchemaType constructor.

    ", - "summary": "

    Boolean SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaBoolean", - "string": "SchemaBoolean()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBoolean", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBoolean.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator

    ", - "summary": "

    Required validator

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "checkRequired", - "string": "SchemaBoolean.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to boolean

    ", - "summary": "

    Casts to boolean

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "cast", - "string": "SchemaBoolean.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", - "ctx": { - "type": "function", - "name": "handleArray", - "string": "handleArray()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "castForQuery", - "string": "SchemaBoolean.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBoolean;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBoolean", - "string": "module.exports" - } - } -] -### lib/schema/buffer.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Buffer SchemaType constructor

    ", - "summary": "

    Buffer SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", - "ctx": { - "type": "function", - "name": "SchemaBuffer", - "string": "SchemaBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBuffer", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBuffer.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "checkRequired", - "string": "SchemaBuffer.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "cast", - "string": "SchemaBuffer.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "castForQuery", - "string": "SchemaBuffer.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBuffer;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBuffer", - "string": "module.exports" - } - } -] -### lib/schema/date.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements.

    ", - "summary": "

    Module requirements.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Date SchemaType constructor.

    ", - "summary": "

    Date SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaDate", - "string": "SchemaDate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaDate", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaDate.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator for date

    ", - "summary": "

    Required validator for date

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "checkRequired", - "string": "SchemaDate.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to date

    ", - "summary": "

    Casts to date

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "cast", - "string": "SchemaDate.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Date Query casting.

    ", - "summary": "

    Date Query casting.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "castForQuery", - "string": "SchemaDate.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaDate;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaDate", - "string": "module.exports" - } - } -] -### lib/schema/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaArray" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    SubdocsArray SchemaType constructor

    ", - "summary": "

    SubdocsArray SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "DocumentArray", - "string": "DocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from ArrayType.

    ", - "summary": "

    Inherits from ArrayType.

    ", - "body": "" - }, - "ignore": true, - "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentArray", - "name": "__proto__", - "value": "ArrayType.prototype", - "string": "DocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs local validations first, then validations on each embedded doc

    ", - "summary": "

    Performs local validations first, then validations on each embedded doc

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n\n SchemaType.prototype.doValidate.call(this, array, function (err) {\n if (err) return fn(err);\n\n var count = array && array.length\n , error;\n\n if (!count) return fn();\n\n // handle sparse arrays, do not use array.forEach which does not\n // iterate over sparse elements yet reports array.length including\n // them :(\n\n for (var i = 0, len = count; i < len; ++i) {\n // sidestep sparse entries\n var doc = array[i];\n if (!doc) {\n --count || fn();\n continue;\n }\n\n ;(function (i) {\n doc.validate(function (err) {\n if (err && !error) {\n // rewrite the key\n err.key = self.key + '.' + i + '.' + err.key;\n return fn(error = err);\n }\n --count || fn();\n });\n })(i);\n }\n }, scope);\n};", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "doValidate", - "string": "DocumentArray.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "document", - "description": "that triggers the casting" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument) && value[i]) {\n if (init) {\n selected || (selected = scopePaths(this, doc._selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "cast", - "string": "DocumentArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "DocumentArray" - ], - "name": "array", - "description": "- the array to scope `fields` paths" - }, - { - "type": "param", - "types": [ - "Object", - "undefined" - ], - "name": "fields", - "description": "- the root fields selected in the query" - }, - { - "type": "param", - "types": [ - "Boolean", - "undefined" - ], - "name": "init", - "description": "- if we are being created part of a query result" - } - ], - "description": { - "full": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", - "summary": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , hasKeys\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n hasKeys || (hasKeys = true);\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return hasKeys && selected || undefined;\n}", - "ctx": { - "type": "function", - "name": "scopePaths", - "string": "scopePaths()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = DocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "DocumentArray", - "string": "module.exports" - } - } -] -### lib/schema/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "String", - "value": "require('./string')", - "string": "exports.String" - } - } -] -### lib/schema/mixed.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Mixed SchemaType constructor.

    ", - "summary": "

    Mixed SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "Mixed", - "string": "Mixed()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "Mixed", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "Mixed.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator

    ", - "summary": "

    Required validator

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "checkRequired", - "string": "Mixed.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", - "summary": "

    Casts val for Mixed.

    ", - "body": "

    this is a no-op

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "cast", - "string": "Mixed.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$cond", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "castForQuery", - "string": "Mixed.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Mixed;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Mixed", - "string": "module.exports" - } - } -] -### lib/schema/number.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements.

    ", - "summary": "

    Module requirements.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Number SchemaType constructor.

    ", - "summary": "

    Number SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", - "ctx": { - "type": "function", - "name": "SchemaNumber", - "string": "SchemaNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaNumber", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaNumber.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator for number

    ", - "summary": "

    Required validator for number

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "checkRequired", - "string": "SchemaNumber.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "value", - "description": "minimum number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", - "summary": "

    Sets a maximum number validator.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "min", - "string": "SchemaNumber.prototype.min()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "maximum", - "description": "number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", - "summary": "

    Sets a maximum number validator.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "max", - "string": "SchemaNumber.prototype.max()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "value to cast" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to number

    ", - "summary": "

    Casts to number

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "cast", - "string": "SchemaNumber.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "castForQuery", - "string": "SchemaNumber.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaNumber;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaNumber", - "string": "module.exports" - } - } -] -### lib/schema/objectid.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    ObjectId SchemaType constructor.

    ", - "summary": "

    ObjectId SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", - "ctx": { - "type": "function", - "name": "ObjectId", - "string": "ObjectId()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "ObjectId", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "ObjectId.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "checkRequired", - "string": "ObjectId.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to ObjectId

    ", - "summary": "

    Casts to ObjectId

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "cast", - "string": "ObjectId.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "castForQuery", - "string": "ObjectId.prototype.castForQuery()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "turnOn", - "description": "auto generated ObjectId defaults" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", - "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "auto", - "string": "ObjectId.prototype.auto()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", - "ctx": { - "type": "function", - "name": "defaultId", - "string": "defaultId()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = ObjectId;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ObjectId", - "string": "module.exports" - } - } -] -### lib/schema/string.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    String SchemaType constructor.

    ", - "summary": "

    String SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", - "ctx": { - "type": "function", - "name": "SchemaString", - "string": "SchemaString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaString", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaString.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[args...]", - "description": "enumeration values" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", - "summary": "

    Adds enumeration values and a coinciding validator.

    ", - "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "enum", - "string": "SchemaString.prototype.enum()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", - "summary": "

    Adds a lowercase setter.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toLowerCase();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "lowercase", - "string": "SchemaString.prototype.lowercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", - "summary": "

    Adds an uppercase setter.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toUpperCase();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "uppercase", - "string": "SchemaString.prototype.uppercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", - "summary": "

    Adds a trim setter.

    ", - "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.trim();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "trim", - "string": "SchemaString.prototype.trim()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp" - ], - "name": "regExp", - "description": "regular expression to test against" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", - "summary": "

    Sets a regexp validator.

    ", - "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "match", - "string": "SchemaString.prototype.match()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "null", - "undefined" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "checkRequired", - "string": "SchemaString.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to String

    ", - "summary": "

    Casts to String

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "cast", - "string": "SchemaString.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "castForQuery", - "string": "SchemaString.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaString;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaString", - "string": "module.exports" - } - } -] -### lib/schema.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "definition", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted after the schema is compiled into a `Model`." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • autoIndex: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • collection: string - no default
    • \n
    • id: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • read: string
    • \n
    • safe: bool - defaults to true.
    • \n
    • shardKey: bool - defaults to null
    • \n
    • strict: bool - defaults to true
    • \n
    • toJSON - object - no default
    • \n
    • toObject - object - no default
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", - "summary": "

    Schema constructor.

    ", - "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • autoIndex: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • collection: string - no default
    • \n
    • id: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • read: string
    • \n
    • safe: bool - defaults to true.
    • \n
    • shardKey: bool - defaults to null
    • \n
    • strict: bool - defaults to true
    • \n
    • toJSON - object - no default
    • \n
    • toObject - object - no default
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", - "ctx": { - "type": "function", - "name": "Schema", - "string": "Schema()" - } - }, - { - "tags": [], - "description": { - "full": "

    Returns this documents _id cast to a string.

    ", - "summary": "

    Returns this documents _id cast to a string.

    ", - "body": "" - }, - "ignore": true, - "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", - "ctx": { - "type": "function", - "name": "idGetter", - "string": "idGetter()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Schema", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Schema.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "paths" - } - ], - "description": { - "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", - "summary": "

    Schema as flat paths

    ", - "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.paths;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "tree" - } - ], - "description": { - "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", - "summary": "

    Schema as a tree

    ", - "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.tree;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns default options for this schema, merged with options.

    ", - "summary": "

    Returns default options for this schema, merged with options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.defaultOptions = function (options) {\n if (options && false === options.safe) {\n options.safe = { w: 0 };\n }\n\n options = utils.options({\n strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "defaultOptions", - "string": "Schema.prototype.defaultOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "prefix", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", - "summary": "

    Adds key path / schema type pairs to this schema.

    ", - "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n } else {\n this.path(prefix + i, obj[i]); // mixed type\n }\n } else {\n this.path(prefix + i, obj[i]);\n }\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "add", - "string": "Schema.prototype.add()" - } - }, - { - "tags": [], - "description": { - "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    ", - "summary": "

    Reserved document keys.

    ", - "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    " - }, - "ignore": false, - "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "reserved", - "value": "Object.create(null)", - "string": "Schema.reserved" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "constructor", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", - "summary": "

    Gets/sets schema paths.

    ", - "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(sub, i) {\n if (!branch[sub]) branch[sub] = {};\n if ('object' != typeof branch[sub]) {\n var msg = 'Cannot set nested path `' + path + '`. '\n + 'Parent path `'\n + subpaths.slice(0, i).concat([sub]).join('.')\n + '` already set to type ' + branch[sub].name\n + '.';\n throw new Error(msg);\n }\n branch = branch[sub];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "path", - "string": "Schema.prototype.path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "constructor" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts type arguments into Mongoose Types.

    ", - "summary": "

    Converts type arguments into Mongoose Types.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", - "ctx": { - "type": "method", - "receiver": "Schema", - "name": "interpretAsType", - "string": "Schema.interpretAsType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback function" - }, - { - "type": "return", - "types": [ - "Schema" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", - "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", - "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "eachPath", - "string": "Schema.prototype.eachPath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns an Array of path strings that are required by this schema.

    ", - "summary": "

    Returns an Array of path strings that are required by this schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "requiredPaths", - "string": "Schema.prototype.requiredPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", - "summary": "

    Returns the pathType of path for this schema.

    ", - "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pathType", - "string": "Schema.prototype.pathType()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", - "ctx": { - "type": "function", - "name": "getPositionalPath", - "string": "getPositionalPath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the document method to call later" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Adds a method call to the queue.

    ", - "summary": "

    Adds a method call to the queue.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "queue", - "string": "Schema.prototype.queue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", - "summary": "

    Defines a pre hook for the document.

    ", - "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pre", - "string": "Schema.prototype.pre()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "name of the method to hook" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function (doc) {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", - "summary": "

    Defines a post hook for the document.

    ", - "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function (doc) {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "post", - "string": "Schema.prototype.post()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "plugin", - "description": "callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "" - }, - { - "type": "see", - "local": "plugins", - "visibility": "plugins" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Registers a plugin for this schema.

    ", - "summary": "

    Registers a plugin for this schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "plugin", - "string": "Schema.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "method", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", - "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", - "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "method", - "string": "Schema.prototype.method()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", - "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", - "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "static", - "string": "Schema.prototype.static()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", - "summary": "

    Defines an index (most likely compound) for this schema.

    ", - "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "index", - "string": "Schema.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "option name" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[value]", - "description": "if not passed, the current option value is returned" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets/gets a schema option.

    ", - "summary": "

    Sets/gets a schema option.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.set = function (key, value, _tags) {\n if (1 === arguments.length) {\n return this.options[key];\n }\n\n switch (key) {\n case 'read':\n this.options[key] = utils.readPref(value, _tags)\n break;\n case 'safe':\n this.options[key] = false === value\n ? { w: 0 }\n : value\n break;\n default:\n this.options[key] = value;\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "set", - "string": "Schema.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "option name" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets a schema option.

    ", - "summary": "

    Gets a schema option.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.get = function (key) {\n return this.options[key];\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "get", - "string": "Schema.prototype.get()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Compiles indexes from fields and schema-level indexes

    ", - "summary": "

    Compiles indexes from fields and schema-level indexes

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "indexes", - "string": "Schema.prototype.indexes()" - } - }, - { - "tags": [], - "description": { - "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", - "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", - "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " - }, - "ignore": true, - "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", - "ctx": { - "type": "function", - "name": "fixSubIndexPaths", - "string": "fixSubIndexPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

    Creates a virtual type with the given name.

    ", - "summary": "

    Creates a virtual type with the given name.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtual", - "string": "Schema.prototype.virtual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the virtual type with the given name.

    ", - "summary": "

    Returns the virtual type with the given name.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtualpath", - "string": "Schema.prototype.virtualpath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", - "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "namedScope", - "string": "Schema.prototype.namedScope()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Schema", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose Schema Types.

    \n\n

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", - "summary": "

    The various Mongoose Schema Types.

    ", - "body": "

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.Types = require('./schema/index');", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "Types", - "value": "require('./schema/index')", - "string": "Schema.Types" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" - } -] -### lib/schemadefault.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "property", - "string": "system.profile" - }, - { - "type": "receiver", - "string": "exports" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Default model for querying the system.profiles collection.

    ", - "summary": "

    Default model for querying the system.profiles collection.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" - } -] -### lib/schematype.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');\nvar CastError = require('./error').CastError;\nvar ValidatorError = require('./error').ValidatorError;", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[instance]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    SchemaType constructor

    ", - "summary": "

    SchemaType constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", - "ctx": { - "type": "function", - "name": "SchemaType", - "string": "SchemaType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function", - "any" - ], - "name": "val", - "description": "the default value" - }, - { - "type": "return", - "types": [ - "defaultValue" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", - "summary": "

    Sets a default value for this SchemaType.

    ", - "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "default", - "string": "SchemaType.prototype.default()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "Boolean" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.date').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", - "summary": "

    Declares the index options for this schematype.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.date').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "index", - "string": "SchemaType.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares an unique index.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    \n\n

    NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.

    ", - "summary": "

    Declares an unique index.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    \n\n

    NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "unique", - "string": "SchemaType.prototype.unique()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a sparse index.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", - "summary": "

    Declares a sparse index.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "sparse", - "string": "SchemaType.prototype.sparse()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "when", - "description": "" - }, - { - "type": "added", - "string": "3.0.0" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: 60*60*24 }});\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: '24h' }});\n\n// expire in 1.5 hours\nnew Schema({ createdAt: { type: Date, expires: '1.5h' }});\n\n// expire in 7 days\nvar schema = new Schema({ createdAt: Date });\nschema.path('createdAt').expires('7d');\n
    ", - "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", - "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: 60*60*24 }});\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: '24h' }});\n\n// expire in 1.5 hours\nnew Schema({ createdAt: { type: Date, expires: '1.5h' }});\n\n// expire in 7 days\nvar schema = new Schema({ createdAt: Date });\nschema.path('createdAt').expires('7d');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "expires", - "string": "SchemaType.prototype.expires()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    ", - "summary": "

    Adds a setter to this schematype.

    ", - "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "set", - "string": "SchemaType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    ", - "summary": "

    Adds a getter to this schematype.

    ", - "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "get", - "string": "SchemaType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp", - "Function", - "Object" - ], - "name": "obj", - "description": "validator" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[error]", - "description": "optional error message" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", - "summary": "

    Adds validator(s) for this document path.

    ", - "body": "

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "validate", - "string": "SchemaType.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "required", - "description": "enable/disable the validator" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", - "summary": "

    Adds a required validator to this schematype.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "required", - "string": "SchemaType.prototype.required()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope which callback are executed" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Gets the default value

    ", - "summary": "

    Gets the default value

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "getDefault", - "string": "SchemaType.prototype.getDefault()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies setters

    ", - "summary": "

    Applies setters

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applySetters", - "string": "SchemaType.prototype.applySetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies getters to a value

    ", - "summary": "

    Applies getters to a value

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applyGetters", - "string": "SchemaType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", - "summary": "

    Sets default select() behavior for this path.

    ", - "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "select", - "string": "SchemaType.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", - "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "doValidate", - "string": "SchemaType.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determines if value is a valid Reference.

    ", - "summary": "

    Determines if value is a valid Reference.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", - "ctx": { - "type": "method", - "receiver": "SchemaType", - "name": "_isRef", - "string": "SchemaType._isRef()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = SchemaType", - "string": "module.exports" - } - } -] -### lib/statemachine.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", - "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", - "ctx": { - "type": "declaration", - "name": "StateMachine", - "value": "module.exports = exports = function StateMachine () {", - "string": "StateMachine" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "subclass constructor" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", - "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", - "ctx": { - "type": "method", - "receiver": "StateMachine", - "name": "ctor", - "string": "StateMachine.ctor()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", - "summary": "

    This function is wrapped by the state change functions

    ", - "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_changeState", - "string": "StateMachine.prototype._changeState()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "clear", - "string": "StateMachine.prototype.clear()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "that we want to check for." - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", - "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "some", - "string": "StateMachine.prototype.some()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "iterMethod", - "description": "is either 'forEach' or 'map'" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", - "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_iter", - "string": "StateMachine.prototype._iter()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", - "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", - "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "forEach", - "string": "StateMachine.prototype.forEach()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", - "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", - "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "map", - "string": "StateMachine.prototype.map()" - } - } -] -### lib/types/array.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", - "ctx": { - "type": "declaration", - "name": "EmbeddedDocument", - "value": "require('./embedded')", - "string": "EmbeddedDocument" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Array" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", - "summary": "

    Mongoose Array constructor.

    ", - "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseArray", - "string": "MongooseArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Array

    ", - "summary": "

    Inherit from Array

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseArray.prototype = new Array;", - "ctx": { - "type": "property", - "receiver": "MongooseArray", - "name": "prototype", - "value": "new Array", - "string": "MongooseArray.prototype" - } - }, - { - "tags": [ - { - "type": "property", - "string": "_atomics" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Stores a queue of atomic operations to perform

    ", - "summary": "

    Stores a queue of atomic operations to perform

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._atomics;" - }, - { - "tags": [ - { - "type": "property", - "string": "_parent" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Parent owner document

    ", - "summary": "

    Parent owner document

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._parent;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "return", - "types": [ - "value" - ], - "description": "the casted value" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts a member based on this arrays schema.

    ", - "summary": "

    Casts a member based on this arrays schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_cast", - "string": "MongooseArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "EmbeddedDocument" - ], - "name": "embeddedDoc", - "description": "the embedded doc that invoked this method on the Array" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "embeddedPath", - "description": "the path which changed in the embeddedDoc" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", - "summary": "

    Marks this array as modified.

    ", - "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._markModified = function (elem, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n dirtyPath = this._path;\n\n if (arguments.length) {\n if (null != embeddedPath) {\n // an embedded doc bubbled up the change\n dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;\n } else {\n // directly set an index\n dirtyPath = dirtyPath + '.' + elem;\n }\n\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_markModified", - "string": "MongooseArray.prototype._markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "op", - "description": "operation" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register an atomic operation with the parent.

    ", - "summary": "

    Register an atomic operation with the parent.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (this._atomics.$set ||\n Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_registerAtomic", - "string": "MongooseArray.prototype._registerAtomic()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", - "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "hasAtomics", - "string": "MongooseArray.prototype.hasAtomics()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#push with proper change tracking.

    ", - "summary": "

    Wraps Array#push with proper change tracking.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "push", - "string": "MongooseArray.prototype.push()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Pushes items to the array non-atomically.

    ", - "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "nonAtomicPush", - "string": "MongooseArray.prototype.nonAtomicPush()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "$pop" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", - "summary": "

    Pops the array atomically at most one time per document save().

    ", - "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n this._markModified();\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" - }, - { - "tags": [ - { - "type": "see", - "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", - "visibility": "MongooseArray#$pop" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#pop with proper change tracking.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pop", - "string": "MongooseArray.prototype.pop()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "method", - "string": "$shift" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", - "summary": "

    Atomically shifts the array at most one time per document save().

    ", - "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n this._markModified();\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#shift with proper change tracking.

    ", - "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "shift", - "string": "MongooseArray.prototype.shift()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "values to remove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes items from an array atomically

    \n\n

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    ", - "summary": "

    Removes items from an array atomically

    ", - "body": "

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "remove", - "string": "MongooseArray.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pulls items from the array atomically.

    ", - "summary": "

    Pulls items from the array atomically.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n this._markModified();\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pull", - "string": "MongooseArray.prototype.pull()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#splice with proper change tracking and casting.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#splice with proper change tracking and casting.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.splice = function splice () {\n var ret, vals, i;\n\n if (arguments.length) {\n vals = [];\n for (i = 0; i < arguments.length; ++i) {\n vals[i] = i < 2\n ? arguments[i]\n : this._cast(arguments[i]);\n }\n ret = [].splice.apply(this, vals);\n this._registerAtomic('$set', this);\n this._markModified();\n }\n\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "splice", - "string": "MongooseArray.prototype.splice()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#unshift with proper change tracking.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return this.length;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "unshift", - "string": "MongooseArray.prototype.unshift()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#sort with proper change tracking.

    ", - "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "sort", - "string": "MongooseArray.prototype.sort()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "the values that were added" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", - "summary": "

    Adds values to the array if not already present.

    ", - "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n this._markModified();\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "addToSet", - "string": "MongooseArray.prototype.addToSet()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the casted val at index i and marks the array modified.

    \n\n

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    ", - "summary": "

    Sets the casted val at index i and marks the array modified.

    ", - "body": "

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.set = function set (i, val) {\n this[i] = this._cast(val);\n this._markModified(i);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "set", - "string": "MongooseArray.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a native js Array.

    ", - "summary": "

    Returns a native js Array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "toObject", - "string": "MongooseArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "inspect", - "string": "MongooseArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the item to look for" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Return the index of obj or -1 if not found.

    ", - "summary": "

    Return the index of obj or -1 if not found.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "indexOf", - "string": "MongooseArray.prototype.indexOf()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = MongooseArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = MongooseArray", - "string": "module.exports" - } - } -] -### lib/types/buffer.js -[ - { - "tags": [], - "description": { - "full": "

    Access driver.

    ", - "summary": "

    Access driver.

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Binary = require(driver + '/binary');", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require(driver + '/binary')", - "string": "Binary" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "encode", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "offset", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Buffer" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", - "summary": "

    Mongoose Buffer constructor.

    ", - "body": "

    Values always have to be passed to the constructor to initialize.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", - "ctx": { - "type": "function", - "name": "MongooseBuffer", - "string": "MongooseBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Buffer.

    ", - "summary": "

    Inherit from Buffer.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.prototype = new Buffer(0);", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "prototype", - "value": "new Buffer(0)", - "string": "MongooseBuffer.prototype" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "_parent" - } - ], - "description": { - "full": "

    Parent owner document

    ", - "summary": "

    Parent owner document

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._parent;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Marks this buffer as modified.

    ", - "summary": "

    Marks this buffer as modified.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "_markModified", - "string": "MongooseBuffer.prototype._markModified()" - } - }, - { - "tags": [], - "description": { - "full": "

    Writes the buffer.

    ", - "summary": "

    Writes the buffer.

    ", - "body": "" - }, - "ignore": false, - "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "write", - "string": "MongooseBuffer.prototype.write()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "MongooseBuffer" - ], - "description": "" - }, - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "target", - "description": "" - } - ], - "description": { - "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", - "summary": "

    Copies the buffer.

    ", - "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "copy", - "string": "MongooseBuffer.prototype.copy()" - } - }, - { - "tags": [], - "description": { - "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", - "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", - "body": "" - }, - "ignore": true, - "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://bsonspec.org/#/specification", - "visibility": "http://bsonspec.org/#/specification" - }, - { - "type": "param", - "types": [ - "Hex" - ], - "name": "[subtype]", - "description": "" - }, - { - "type": "return", - "types": [ - "Binary" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", - "summary": "

    Converts this buffer to its Binary type representation.

    ", - "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "toObject", - "string": "MongooseBuffer.prototype.toObject()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "Binary", - "value": "Binary", - "string": "MongooseBuffer.Binary" - } - } -] -### lib/types/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", - "ctx": { - "type": "declaration", - "name": "MongooseArray", - "value": "require('./array')", - "string": "MongooseArray" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to this array" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "MongooseDocumentArray" - ], - "description": "" - }, - { - "type": "inherits", - "string": "MongooseArray" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    DocumentArray constructor

    ", - "summary": "

    DocumentArray constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseDocumentArray", - "string": "MongooseDocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseArray

    ", - "summary": "

    Inherits from MongooseArray

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseDocumentArray", - "name": "__proto__", - "value": "MongooseArray.prototype", - "string": "MongooseDocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Overrides MongooseArray#cast

    ", - "summary": "

    Overrides MongooseArray#cast

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype._cast = function (value) {\n if (value instanceof this._schema.casterConstructor)\n return value;\n\n return new this._schema.casterConstructor(value, this);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "_cast", - "string": "MongooseDocumentArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "EmbeddedDocument", - "null" - ], - "description": "the subdocuent or null if not found." - }, - { - "type": "param", - "types": [ - "ObjectId", - "String", - "Number", - "Buffer" - ], - "name": "id", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Searches array items for the first document with a matching id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", - "summary": "

    Searches array items for the first document with a matching id.

    ", - "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "id", - "string": "MongooseDocumentArray.prototype.id()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", - "summary": "

    Returns a native js Array of plain js objects

    ", - "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "toObject", - "string": "MongooseDocumentArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "inspect", - "string": "MongooseDocumentArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the value to cast to this arrays SubDocument schema" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", - "summary": "

    Creates a subdocument casted to this schema.

    ", - "body": "

    This is the same subdocument constructor used for casting.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "create", - "string": "MongooseDocumentArray.prototype.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Creates a fn that notifies all child docs of event.

    ", - "summary": "

    Creates a fn that notifies all child docs of event.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n if (!self[i]) continue;\n self[i].emit(event, val);\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "notify", - "string": "MongooseDocumentArray.prototype.notify()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseDocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseDocumentArray", - "string": "module.exports" - } - } -] -### lib/types/embedded.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Document = require('../document')\n , inspect = require('util').inspect;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('../document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "js object returned from the db" - }, - { - "type": "param", - "types": [ - "MongooseDocumentArray" - ], - "name": "parentArr", - "description": "the parent array of this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "skipId", - "description": "" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    EmbeddedDocument constructor.

    ", - "summary": "

    EmbeddedDocument constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", - "ctx": { - "type": "function", - "name": "EmbeddedDocument", - "string": "EmbeddedDocument()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Document

    ", - "summary": "

    Inherit from Document

    ", - "body": "" - }, - "ignore": true, - "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "EmbeddedDocument", - "name": "__proto__", - "value": "Document.prototype", - "string": "EmbeddedDocument.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path which changed" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", - "summary": "

    Marks the embedded doc modified.

    ", - "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "markModified", - "string": "EmbeddedDocument.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "return", - "types": [ - "EmbeddedDocument" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", - "summary": "

    Used as a stub for hooks.js

    ", - "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "save", - "string": "EmbeddedDocument.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes the subdocument from its parent array.

    ", - "summary": "

    Removes the subdocument from its parent array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "remove", - "string": "EmbeddedDocument.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Override #update method of parent documents.

    ", - "summary": "

    Override #update method of parent documents.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "update", - "string": "EmbeddedDocument.prototype.update()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "inspect", - "string": "EmbeddedDocument.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "error which states the reason `path` was invalid" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks a path as invalid, causing validation to fail.

    ", - "summary": "

    Marks a path as invalid, causing validation to fail.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "invalidate", - "string": "EmbeddedDocument.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the top level document of this sub-document.

    ", - "summary": "

    Returns the top level document of this sub-document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "ownerDocument", - "string": "EmbeddedDocument.prototype.ownerDocument()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the top level document of this sub-document.

    ", - "summary": "

    Returns the top level document of this sub-document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", - "ctx": { - "type": "function", - "name": "ownerDocument", - "string": "ownerDocument()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns this sub-documents parent document.

    ", - "summary": "

    Returns this sub-documents parent document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parent", - "string": "EmbeddedDocument.prototype.parent()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns this sub-documents parent array.

    ", - "summary": "

    Returns this sub-documents parent array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parentArray", - "string": "EmbeddedDocument.prototype.parentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = EmbeddedDocument;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "EmbeddedDocument", - "string": "module.exports" - } - } -] -### lib/types/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "Array", - "value": "require('./array')", - "string": "exports.Array" - } - } -] -### lib/types/objectid.js -[ - { - "tags": [], - "description": { - "full": "

    Access driver.

    ", - "summary": "

    Access driver.

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [ - { - "type": "constructor", - "string": "ObjectId" - } - ], - "description": { - "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", - "summary": "

    ObjectId type constructor

    ", - "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require(driver + '/objectid')", - "string": "ObjectId" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "str", - "description": "" - }, - { - "type": "static", - "string": "fromString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "ObjectId" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Creates an ObjectId from str

    ", - "summary": "

    Creates an ObjectId from str

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.fromString;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId" - ], - "name": "oid", - "description": "ObjectId instance" - }, - { - "type": "static", - "string": "toString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts oid to a string.

    ", - "summary": "

    Converts oid to a string.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.toString;" - } -] -### lib/utils.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , sliced = require('sliced')\n , MongooseBuffer\n , MongooseArray\n , Document", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "a model name" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "a collection name" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Produces a collection name from model name.

    ", - "summary": "

    Produces a collection name from model name.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "toCollectionName", - "string": "exports.toCollectionName()" - } - }, - { - "tags": [], - "description": { - "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", - "summary": "

    Pluralization rules.

    ", - "body": "

    These rules are applied while processing the argument to toCollectionName.

    " - }, - "ignore": false, - "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "pluralization", - "value": "[", - "string": "exports.pluralization" - } - }, - { - "tags": [], - "description": { - "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", - "summary": "

    Uncountable words.

    ", - "body": "

    These words are applied while processing the argument to toCollectionName.

    " - }, - "ignore": false, - "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news',\n 'expertise',\n 'status',\n 'media'\n];\nvar uncountables = exports.uncountables;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "uncountables", - "value": "[", - "string": "exports.uncountables" - } - }, - { - "tags": [ - { - "type": "author", - "string": "TJ Holowaychuk (extracted from _ext.js_)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "string", - "description": "to pluralize" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Pluralize function.

    ", - "summary": "

    Pluralize function.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", - "ctx": { - "type": "function", - "name": "pluralize", - "string": "pluralize()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "listener", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Add once to EventEmitter if absent

    ", - "summary": "

    Add once to EventEmitter if absent

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", - "ctx": { - "type": "declaration", - "name": "Events", - "value": "EventEmitter", - "string": "Events" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Events", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Events.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Add once.

    ", - "summary": "

    Add once.

    ", - "body": "" - }, - "ignore": true, - "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", - "ctx": { - "type": "method", - "constructor": "Events", - "name": "once", - "string": "Events.prototype.once()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "a", - "description": "a value to compare to `b`" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "b", - "description": "a value to compare to `a`" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", - "summary": "

    Determines if a and b are deep equal.

    ", - "body": "

    Modified from node/lib/assert.js

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "deepEqual", - "string": "exports.deepEqual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the object to clone" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the cloned object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Object clone with Mongoose natives support.

    \n\n

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    ", - "summary": "

    Object clone with Mongoose natives support.

    ", - "body": "

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId)\n return new ObjectId(obj.id);\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "clone", - "string": "exports.clone()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", - "ctx": { - "type": "function", - "name": "cloneObject", - "string": "cloneObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "defaults", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the merged object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Copies and merges options with defaults.

    ", - "summary": "

    Copies and merges options with defaults.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "options", - "string": "exports.options()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Generates a random string

    ", - "summary": "

    Generates a random string

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "random", - "string": "exports.random()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "to", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "from", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Merges from into to without overwriting existing properties.

    ", - "summary": "

    Merges from into to without overwriting existing properties.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n if (exports.isObject(from[key])) {\n merge(to[key], from[key]);\n } else {\n to[key] = from[key];\n }\n }\n }\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "merge", - "string": "exports.merge()" - } - }, - { - "tags": [], - "description": { - "full": "

    toString helper

    ", - "summary": "

    toString helper

    ", - "body": "" - }, - "ignore": true, - "code": "var toString = Object.prototype.toString;", - "ctx": { - "type": "declaration", - "name": "toString", - "value": "Object.prototype.toString", - "string": "toString" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "Array", - "String", - "Function", - "RegExp", - "any" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - } - ], - "description": { - "full": "

    Determines if arg is an object.

    ", - "summary": "

    Determines if arg is an object.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "exports.isObject = function (arg) {\n return '[object Object]' == toString.call(arg);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isObject", - "string": "exports.isObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", - "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.args = sliced;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "args", - "value": "sliced", - "string": "exports.args" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", - "summary": "

    process.nextTick helper.

    ", - "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "tick", - "string": "exports.tick()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "v", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", - "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", - "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isMongooseObject", - "string": "exports.isMongooseObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "object", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", - "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expireAfterSeconds = when;\n delete object.expires;\n}\n\nexports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "expires", - "string": "exports.expires()" - } - } -] -### lib/virtualtype.js -[ - { - "tags": [ - { - "type": "parma", - "string": "{Object} options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", - "summary": "

    VirtualType constructor

    ", - "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", - "ctx": { - "type": "function", - "name": "VirtualType", - "string": "VirtualType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", - "summary": "

    Defines a getter.

    ", - "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "get", - "string": "VirtualType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", - "summary": "

    Defines a setter.

    ", - "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "set", - "string": "VirtualType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all getters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Applies getters to value using optional scope.

    ", - "summary": "

    Applies getters to value using optional scope.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applyGetters", - "string": "VirtualType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all setters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Applies setters to value using optional scope.

    ", - "summary": "

    Applies setters to value using optional scope.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applySetters", - "string": "VirtualType.prototype.applySetters()" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = VirtualType;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "VirtualType", - "string": "module.exports" - } - } -] diff --git a/docs/3.4.x/docs/source/api.js b/docs/3.4.x/docs/source/api.js deleted file mode 100644 index 8fd87f0035b..00000000000 --- a/docs/3.4.x/docs/source/api.js +++ /dev/null @@ -1,220 +0,0 @@ -/*! - * Module dependencies - */ - -var fs = require('fs'); -var link = require('../helpers/linktype'); -var hl = require('highlight.js') -var md = require('markdown') - -module.exports = { - docs: [] - , github: 'https://github.com/LearnBoost/mongoose/tree/' - , title: 'API docs' -} - -var out = module.exports.docs; - -var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); -parse(docs); -order(out); - -function parse (docs) { - docs.split(/^### /gm).forEach(function (chunk) { - if (!(chunk = chunk.trim())) return; - - chunk = chunk.split(/^([^\n]+)\n/); - - var title = chunk[1]; - - if (!title || !(title = title.trim())) - throw new Error('missing title'); - - title = title.replace(/^lib\//, ''); - - var json = JSON.parse(chunk[2]); - - var props = []; - var methods = []; - var statics = []; - var constructor = null; - - json.forEach(function (comment) { - if (comment.description) - highlight(comment.description); - - var prop = false; - comment.params = []; - comment.see = []; - - var i = comment.tags.length; - while (i--) { - var tag = comment.tags[i]; - switch (tag.type) { - case 'property': - prop = true; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - props.unshift(comment); - break; - case 'method': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'method'; - comment.code = ''; - break; - case 'memberOf': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.constructor = tag.parent; - break; - case 'static': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - comment.ctx.type = 'method'; - break; - case 'receiver': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.receiver = tag.string; - break; - case 'constructor': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'function'; - comment.code = ''; - break; - case 'inherits': - if (/http/.test(tag.string)) { - var result = tag.string.split(' '); - var href = result.pop(); - var title = result.join(' '); - comment.inherits = '' + title + ''; - } else { - comment.inherits = link(tag.string); - } - comment.tags.splice(i, 1); - break; - case 'param': - comment.params.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'return': - comment.return = tag; - comment.tags.splice(i, 1); - break; - case 'see': - if (tag.local) { - var parts = tag.local.split(' '); - if (1 === parts.length) { - tag.url = link.type(parts[0]); - tag.title = parts[0]; - } else { - tag.url = parts.pop(); - tag.title = parts.join(' '); - } - } - comment.see.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'event': - var str = tag.string.replace(/\\n/g, '\n'); - tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); - comment.events || (comment.events = []); - comment.events.unshift(tag); - comment.tags.splice(i, 1); - } - } - - if (!prop) { - methods.push(comment); - } - }); - - methods = methods.filter(ignored); - props = props.filter(ignored); - - function ignored (method) { - if (method.ignore) return false; - return true; - } - - if (0 === methods.length + props.length) return; - - // add constructor to properties too - methods.some(function (method) { - if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { - props.forEach(function (prop) { - prop.ctx.constructor = method.ctx.constructor; - }); - return true; - } - return false; - }); - - var len = methods.length; - while (len--) { - method = methods[len]; - if (method.ctx && method.ctx.receiver) { - var stat = methods.splice(len, 1)[0]; - statics.unshift(stat); - } - } - - out.push({ - title: title - , methods: methods - , props: props - , statics: statics - , hasPublic: hasPublic(methods, props, statics) - }); - }); -} - -function hasPublic () { - for (var i = 0; i < arguments.length; ++i) { - var arr = arguments[i]; - for (var j = 0; j < arr.length; ++j) { - var item = arr[j]; - if (!item.ignore && !item.isPrivate) return true; - } - } - return false; -} - -// add "class='language'" to our
     elements
    -function highlight (o) {
    -  o.full = fix(o.full);
    -  o.summary = fix(o.summary);
    -  o.body = fix(o.body);
    -}
    -
    -function fix (str) {
    -  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    -
    -    // parse out the ```language
    -    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    -
    -    if ('js' == code[1] || !code[1]) {
    -      code[1] = 'javascript';
    -    }
    -
    -    return $1
    -          + hl.highlight(code[1], code[2]).value.trim()
    -          + $3;
    -  });
    -}
    -
    -function order (docs) {
    -  // want index first
    -  for (var i = 0; i < docs.length; ++i) {
    -    if ('index.js' == docs[i].title) {
    -      docs.unshift(docs.splice(i, 1)[0]);
    -    }
    -  }
    -}
    diff --git a/docs/3.4.x/docs/source/home.js b/docs/3.4.x/docs/source/home.js
    deleted file mode 100644
    index e349d8ddcad..00000000000
    --- a/docs/3.4.x/docs/source/home.js
    +++ /dev/null
    @@ -1,7 +0,0 @@
    -
    -var package = require('./../../package.json')
    -
    -module.exports = {
    -    package: package
    -  , title: 'ODM'
    -}
    diff --git a/docs/3.4.x/docs/source/index.js b/docs/3.4.x/docs/source/index.js
    deleted file mode 100644
    index 18b3eeb5718..00000000000
    --- a/docs/3.4.x/docs/source/index.js
    +++ /dev/null
    @@ -1,20 +0,0 @@
    -
    -exports['index.jade'] = require('./home')
    -exports['docs/api.jade'] = require('./api')
    -exports['docs/index.jade'] = { title: 'Getting Started' }
    -exports['docs/production.jade'] = require('./production')
    -exports['docs/prior.jade'] = require('./prior')
    -exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    -exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    -exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    -exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    -exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    -exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    -exports['docs/models.jade'] = { guide: true, title: 'Models' }
    -exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    -exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    -exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    -exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    -exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    -exports['docs/connections.jade'] = { guide: true, title: 'Connecting to MongoDB' }
    -exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.4.x/docs/source/prior.js b/docs/3.4.x/docs/source/prior.js
    deleted file mode 100644
    index 2e03811d215..00000000000
    --- a/docs/3.4.x/docs/source/prior.js
    +++ /dev/null
    @@ -1,13 +0,0 @@
    -var fs = require('fs')
    -var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    -releases = releases.split('\n').filter(Boolean);
    -
    -module.exports = exports = {
    -    title: ''
    -  , releases: releases.map(function (version) {
    -      return {
    -          url: version + '/'
    -        , version: version
    -      }
    -    })
    -}
    diff --git a/docs/3.4.x/docs/source/production.js b/docs/3.4.x/docs/source/production.js
    deleted file mode 100644
    index 9fdbcfffbc7..00000000000
    --- a/docs/3.4.x/docs/source/production.js
    +++ /dev/null
    @@ -1,17 +0,0 @@
    -
    -var fs = require('fs')
    -var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    -
    -var imgs = [];
    -
    -images.forEach(function (line) {
    -  line = line.trim();
    -  if (!line) return;
    -  line = line.split('|');
    -  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    -});
    -
    -module.exports = {
    -    images: imgs
    -  , title: 'Production'
    -}
    diff --git a/docs/3.4.x/docs/subdocs.html b/docs/3.4.x/docs/subdocs.html
    deleted file mode 100644
    index a97d0e026c7..00000000000
    --- a/docs/3.4.x/docs/subdocs.html
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -Mongoose SubDocuments v3.4.0Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    -
    -var parentSchema = new Schema({
    -  children: [childSchema]
    -})
    -

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = db.model('Parent', parentSchema);
    -var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    -parent.children[0].name = 'Matthew';
    -parent.save(callback);
    -

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    -  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    -  next();
    -});
    -
    -var parent = new Parent({ children: [{ name: 'invalid' }] });
    -parent.save(function (err) {
    -  console.log(err.message) // #sadpanda
    -})
    -

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    -

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = db.model('Parent');
    -var parent = new Parent;
    -
    -// create a comment
    -post.children.push({ name: 'Liesl' });
    -var doc = post.children[0];
    -console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    -doc.isNew; // true
    -
    -post.save(function (err) {
    -  if (err) return handleError(err)
    -  console.log('Success!');
    -});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    -

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    -parent.save(function (err) {
    -  if (err) return handleError(err);
    -  console.log('the sub-doc was removed')
    -});
    -

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    -  children: [{ name: 'string' }]
    -})
    -

    Next Up

    Now that we've covered Sub-documents, let's take a look at querying.

    diff --git a/docs/3.4.x/docs/validation.html b/docs/3.4.x/docs/validation.html deleted file mode 100644 index 832b43aa4ae..00000000000 --- a/docs/3.4.x/docs/validation.html +++ /dev/null @@ -1,37 +0,0 @@ -Mongoose Validation v3.4.0Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    - -
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    - -

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    -  color: String,
    -  name: String
    -});
    -
    -var Toy = db.model('Toy', toySchema);
    -
    -Toy.schema.path('color').validate(function (value) {
    -  return /blue|green|white|red|orange|periwinkel/i.test(value);
    -}, 'Invalid color');
    -
    -var toy = new Toy({ color: 'grease'});
    -
    -toy.save(function (err) {
    -  // err.errors.color is a ValidatorError object
    -  
    -  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    -  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    -  console.log(err.errors.color.type) // prints "Invalid color"
    -  console.log(err.errors.color.path) // prints "color"
    -  console.log(err.name) // prints "ValidationError"
    -  console.log(err.message) // prints "Validation failed"
    -});
    -

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    -

    Next Up

    Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

    diff --git a/docs/3.4.x/docs/website.js b/docs/3.4.x/docs/website.js deleted file mode 100644 index d1adea38b5c..00000000000 --- a/docs/3.4.x/docs/website.js +++ /dev/null @@ -1,48 +0,0 @@ - -var fs= require('fs') -var jade = require('jade') -var package = require('./package') -var hl = require('./docs/helpers/highlight') -var linktype = require('./docs/helpers/linktype') -var href = require('./docs/helpers/href') -var klass = require('./docs/helpers/klass') - -// add custom jade filters -require('./docs/helpers/filters')(jade); - -// clean up version for ui -package.version = package.version.replace(/-pre$/, ''); - -var filemap = require('./docs/source'); -var files = Object.keys(filemap); - -files.forEach(function (file) { - var filename = __dirname + '/' + file; - jadeify(filename, filemap[file]); - - if ('--watch' == process.argv[2]) { - fs.watchFile(filename, { interval: 1000 }, function (cur, prev) { - if (cur.mtime > prev.mtime) { - jadeify(filename, filemap[file]); - } - }); - } -}); - -function jadeify (filename, options) { - options || (options = {}); - options.package = package; - options.hl = hl; - options.linktype = linktype; - options.href = href; - options.klass = klass; - jade.renderFile(filename, options, function (err, str) { - if (err) return console.error(err.stack); - - var newfile = filename.replace('.jade', '.html') - fs.writeFile(newfile, str, function (err) { - if (err) return console.error('could not write', err.stack); - console.log('%s : rendered ', new Date, newfile); - }); - }); -} diff --git a/docs/3.4.x/index.html b/docs/3.4.x/index.html deleted file mode 100644 index 5bf9aaee774..00000000000 --- a/docs/3.4.x/index.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose ODM v3.4.0Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

    var mongoose = require('mongoose');
    -var db = mongoose.createConnection('localhost', 'test');
    -
    -var schema = mongoose.Schema({ name: 'string' });
    -var Cat = db.model('Cat', schema);
    -
    -var kitty = new Cat({ name: 'Zildjian' });
    -kitty.save(function (err) {
    -  if (err) // ...
    -  console.log('meow');
    -});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    Production - View More

    • Storify
    • LearnBoost
    • GeekList
    • McDonalds
    • ShoeJitsu
    • Bozuko
    \ No newline at end of file diff --git a/docs/3.4.x/static.js b/docs/3.4.x/static.js deleted file mode 100644 index fc0e722dd4e..00000000000 --- a/docs/3.4.x/static.js +++ /dev/null @@ -1,17 +0,0 @@ - -var static = require('node-static'); -var server = new static.Server('.', { cache: 0 }); - -require('http').createServer(function (req, res) { - req.on('end', function () { - server.serve(req, res, function (err) { - if (err) { - console.error(err, req.url); - res.writeHead(err.status, err.headers); - res.end(); - } - }); - }); -}).listen(8088); - -console.error('now listening on localhost:8088'); diff --git a/docs/3.5.x/docs/api.html b/docs/3.5.x/docs/api.html deleted file mode 100644 index 9bb76bb0a0f..00000000000 --- a/docs/3.5.x/docs/api.html +++ /dev/null @@ -1,7225 +0,0 @@ -Mongoose API v3.5.9Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      -  this.connections = [];
      -  this.plugins = [];
      -  this.models = {};
      -  this.modelSchemas = {};
      -  this.options = {};
      -  this.createConnection(); // default connection
      -};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      -  if (arguments.length == 1)
      -    return this.options[key];
      -  this.options[key] = value;
      -  return this;
      -};

      Parameters:

      Example:

      - -
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      - -
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri], [options])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      -  var conn = new Connection(this);
      -  this.connections.push(conn);
      -
      -  if (arguments.length) {
      -    if (rgxReplSet.test(arguments[0])) {
      -      conn.openSet.apply(conn, arguments);
      -    } else {
      -      conn.open.apply(conn, arguments);
      -    }
      -  }
      -
      -  return conn;
      -};

      Parameters:

      • [uri] <String> a mongodb:// URI
      • [options] <Object> options to pass to the driver

      Returns:

      Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

      - -

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver. Note that the safe option specified in your schema will overwrite the safe db option specified here unless you set your schemas safe option to undefined. See this for more information.

      - -

      Options passed take precedence over options included in connection strings.

      - -

      Example:

      - -
      // with mongodb:// URI
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
      -
      -// and options
      -var opts = { db: { native_parser: true }}
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
      -
      -// replica sets
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
      -
      -// and options
      -var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
      -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
      -
      -// with [host, database_name[, port] signature
      -db = mongoose.createConnection('localhost', 'database', port)
      -
      -// and options
      -var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
      -db = mongoose.createConnection('localhost', 'database', port, opts)
      -
      -// initialize now, connect later
      -db = mongoose.createConnection();
      -db.open('localhost', 'database', port, [opts]);

      Mongoose#connect()

      Opens the default mongoose connection.

      show code
      Mongoose.prototype.connect = function () {
      -  var conn = this.connection;
      -
      -  if (rgxReplSet.test(arguments[0])) {
      -    conn.openSet.apply(conn, arguments);
      -  } else {
      -    conn.open.apply(conn, arguments);
      -  }
      -
      -  return this;
      -};

      Returns:

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

      - -

      Options passed take precedence over options included in connection strings.


      Mongoose#disconnect([fn])

      Disconnects all connections.

      show code
      Mongoose.prototype.disconnect = function (fn) {
      -  var count = this.connections.length
      -    , error
      -
      -  this.connections.forEach(function(conn){
      -    conn.close(function(err){
      -      if (error) return;
      -
      -      if (err) {
      -        error = err;
      -        if (fn) return fn(err);
      -        throw err;
      -      }
      -
      -      if (fn)
      -        --count || fn();
      -    });
      -  });
      -  return this;
      -};

      Parameters:

      • [fn] <Function> called after all connection close.

      Returns:


      Mongoose#model(name, [schema], [collection], [skipInit])

      Defines a model or retrieves it.

      show code
      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
      -  if (!(schema instanceof Schema)) {
      -    collection = schema;
      -    schema = false;
      -  }
      -
      -  if ('boolean' === typeof collection) {
      -    skipInit = collection;
      -    collection = null;
      -  }
      -
      -  // handle internal options from connection.model()
      -  var options;
      -  if (skipInit && utils.isObject(skipInit)) {
      -    options = skipInit;
      -    skipInit = true;
      -  } else {
      -    options = {};
      -  }
      -
      -  // look up schema for the collection. this might be a
      -  // default schema like system.indexes stored in SchemaDefaults.
      -  if (!this.modelSchemas[name]) {
      -    if (!schema && name in SchemaDefaults) {
      -      schema = SchemaDefaults[name];
      -    }
      -
      -    if (schema) {
      -      // cache it so we only apply plugins once
      -      this.modelSchemas[name] = schema;
      -      this._applyPlugins(schema);
      -    } else {
      -      throw new mongoose.Error.MissingSchemaError(name);
      -    }
      -  }
      -
      -  var model;
      -  var sub;
      -
      -  // connection.model() may be passing a different schema for
      -  // an existing model name. in this case don't read from cache.
      -  if (this.models[name] && false !== options.cache) {
      -    if (schema instanceof Schema && schema != this.models[name].schema) {
      -      throw new mongoose.Error.OverwriteModelError(name);
      -    }
      -
      -    if (collection) {
      -      // subclass current model with alternate collection
      -      model = this.models[name];
      -      schema = model.prototype.schema;
      -      sub = model.__subclass(this.connection, schema, collection);
      -      // do not cache the sub model
      -      return sub;
      -    }
      -
      -    return this.models[name];
      -  }
      -
      -  // ensure a schema exists
      -  if (!schema) {
      -    schema = this.modelSchemas[name];
      -    if (!schema) {
      -      throw new mongoose.Error.MissingSchemaError(name);
      -    }
      -  }
      -
      -  if (!collection) {
      -    collection = schema.get('collection') || format(name);
      -  }
      -
      -  var connection = options.connection || this.connection;
      -  model = Model.compile(name, schema, collection, connection, this);
      -
      -  if (!skipInit) {
      -    model.init();
      -  }
      -
      -  if (false === options.cache) {
      -    return model;
      -  }
      -
      -  return this.models[name] = model;
      -}

      Parameters:

      • name <String> model name
      • [schema] <Schema>
      • [collection] <String> name (optional, induced from model name)
      • [skipInit] <Boolean> whether to skip initialization (defaults to false)

      Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -
      -// define an Actor model with this mongoose instance
      -mongoose.model('Actor', new Schema({ name: String }));
      -
      -// create a new connection
      -var conn = mongoose.createConnection(..);
      -
      -// retrieve the Actor model
      -var Actor = conn.model('Actor');
      - -

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

      - -

      Example:

      - -
      var schema = new Schema({ name: String }, { collection: 'actor' });
      -
      -// or
      -
      -schema.set('collection', 'actor');
      -
      -// or
      -
      -var collectionName = 'actor'
      -var M = mongoose.model('Actor', schema, collectionName)

      Mongoose#_applyPlugins(schema)

      Applies global plugins to schema.

      show code
      Mongoose.prototype._applyPlugins = function (schema) {
      -  for (var i = 0, l = this.plugins.length; i < l; i++) {
      -    schema.plugin(this.plugins[i][0], this.plugins[i][1]);
      -  }
      -}

      Parameters:


      Mongoose#plugin(fn, [opts])

      Declares a global plugin executed on all Schemas.

      show code
      Mongoose.prototype.plugin = function (fn, opts) {
      -  this.plugins.push([fn, opts]);
      -  return this;
      -};

      Parameters:

      Returns:

      Equivalent to calling .plugin(fn) on each Schema you create.


      module.exports

      The exports object is an instance of Mongoose.

      show code
      module.exports = exports = new Mongoose;
      -var mongoose = module.exports;

      mongoose.Collection

      The Mongoose Collection constructor

      show code
      mongoose.Collection = Collection;

      mongoose.Connection

      The Mongoose Connection constructor

      show code
      mongoose.Connection = Connection;

      mongoose.version

      Mongoose version

      show code
      mongoose.version = JSON.parse(
      -  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      -).version;

      mongoose.Mongoose

      The Mongoose constructor

      show code
      mongoose.Mongoose = Mongoose;

      The exports of the mongoose module is an instance of this class.

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -var mongoose2 = new mongoose.Mongoose();

      mongoose.Schema

      The Mongoose Schema constructor

      show code
      mongoose.Schema = Schema;

      Example:

      - -
      var mongoose = require('mongoose');
      -var Schema = mongoose.Schema;
      -var CatSchema = new Schema(..);

      mongoose.SchemaType

      The Mongoose SchemaType constructor.

      show code
      mongoose.SchemaType = SchemaType;

      mongoose.SchemaTypes

      The various Mongoose SchemaTypes.

      show code
      mongoose.SchemaTypes = Schema.Types;

      Note:

      - -

      Alias of mongoose.Schema.Types for backwards compatibility.


      mongoose.VirtualType

      The Mongoose VirtualType constructor.

      show code
      mongoose.VirtualType = VirtualType;

      mongoose.Types

      The various Mongoose Types.

      show code
      mongoose.Types = Types;

      Example:

      - -
      var mongoose = require('mongoose');
      -var array = mongoose.Types.Array;
      - -

      Types:

      - -
        -
      • Array
      • -
      • Buffer
      • -
      • Document
      • -
      • Embedded
      • -
      • DocumentArray
      • -
      • ObjectId
      • -
      - -

      Using this exposed access to the ObjectId type, we can construct ids on demand.

      - -
      var ObjectId = mongoose.Types.ObjectId;
      -var id1 = new ObjectId;

      mongoose.Query

      The Mongoose Query constructor.

      show code
      mongoose.Query = Query;

      mongoose.Promise

      The Mongoose Promise constructor.

      show code
      mongoose.Promise = Promise;

      mongoose.Model

      The Mongoose Model constructor.

      show code
      mongoose.Model = Model;

      mongoose.Document

      The Mongoose Document constructor.

      show code
      mongoose.Document = Document;

      mongoose.Error

      The MongooseError constructor.

      show code
      mongoose.Error = require('./error');

      mongoose.mongo

      The node-mongodb-native driver Mongoose uses.

      show code
      mongoose.mongo = require('mongodb');

      Mongoose#connection

      The default connection of the mongoose module.

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -mongoose.connect(...);
      -mongoose.connection.on('error', cb);
      - -

      This is the connection used by default for every model created using mongoose.model.

      Returns:


    • connection.js

      Connection(base)

      Connection constructor

      show code
      function Connection (base) {
      -  this.base = base;
      -  this.collections = {};
      -  this.models = {};
      -  this.replica = false;
      -  this.hosts = null;
      -  this.host = null;
      -  this.port = null;
      -  this.user = null;
      -  this.pass = null;
      -  this.name = null;
      -  this.options = null;
      -  this._readyState = STATES.disconnected;
      -  this._closeCalled = false;
      -  this._hasOpened = false;
      -};

      Parameters:

      Events:

      • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

      • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

      • open: Emitted after we connected and onOpen is executed on all of this connections models.

      • disconnecting: Emitted when connection.close() was executed.

      • disconnected: Emitted after getting disconnected from the db.

      • close: Emitted after we disconnected and onClose executed on all of this connections models.

      • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

      • error: Emitted when an error occurs on this connection.

      • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

      For practical reasons, a Connection equals a Db.


      Connection#open(connection_string, [database], [port], [options], [callback])

      Opens the connection to MongoDB.

      show code
      Connection.prototype.open = function (host, database, port, options, callback) {
      -  var self = this
      -    , parsed
      -    , uri;
      -
      -  if ('string' === typeof database) {
      -    switch (arguments.length) {
      -      case 2:
      -        port = 27017;
      -      case 3:
      -        switch (typeof port) {
      -          case 'function':
      -            callback = port, port = 27017;
      -            break;
      -          case 'object':
      -            options = port, port = 27017;
      -            break;
      -        }
      -        break;
      -      case 4:
      -        if ('function' === typeof options)
      -          callback = options, options = {};
      -    }
      -  } else {
      -    switch (typeof database) {
      -      case 'function':
      -        callback = database, database = undefined;
      -        break;
      -      case 'object':
      -        options = database;
      -        database = undefined;
      -        callback = port;
      -        break;
      -    }
      -
      -    if (!rgxProtocol.test(host)) {
      -      host = 'mongodb://' + host;
      -    }
      -
      -    try {
      -      parsed = muri(host);
      -    } catch (err) {
      -      this.error(err, callback);
      -      return this;
      -    }
      -
      -    database = parsed.db;
      -    host = parsed.hosts[0].host || parsed.hosts[0].ipc;
      -    port = parsed.hosts[0].port || 27017;
      -  }
      -
      -  this.options = this.parseOptions(options, parsed && parsed.options);
      -
      -  // make sure we can open
      -  if (STATES.disconnected !== this.readyState) {
      -    var err = new Error('Trying to open unclosed connection.');
      -    err.state = this.readyState;
      -    this.error(err, callback);
      -    return this;
      -  }
      -
      -  if (!host) {
      -    this.error(new Error('Missing hostname.'), callback);
      -    return this;
      -  }
      -
      -  if (!database) {
      -    this.error(new Error('Missing database name.'), callback);
      -    return this;
      -  }
      -
      -  // authentication
      -  if (options && options.user && options.pass) {
      -    this.user = options.user;
      -    this.pass = options.pass;
      -
      -  } else if (parsed && parsed.auth) {
      -    this.user = parsed.auth.user;
      -    this.pass = parsed.auth.pass;
      -
      -  // Check hostname for user/pass
      -  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
      -    host = host.split('@');
      -    var auth = host.shift().split(':');
      -    host = host.pop();
      -    this.user = auth[0];
      -    this.pass = auth[1];
      -
      -  } else {
      -    this.user = this.pass = undefined;
      -  }
      -
      -  this.name = database;
      -  this.host = host;
      -  this.port = port;
      -
      -  this._open(callback);
      -  return this;
      -};

      Parameters:

      • connection_string <String> mongodb://uri or the host to which you are connecting
      • [database] <String> database name
      • [port] <Number> database port
      • [options] <Object> options
      • [callback] <Function>

      options is a hash with the following possible properties:

      - -
      db      - passed to the connection db instance
      -server  - passed to the connection server instance(s)
      -replset - passed to the connection ReplSet instance
      -user    - username for authentication
      -pass    - password for authentication
      -auth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
      -
      - -

      Notes:

      - -

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.

      - -

      Options passed take precedence over options included in connection strings.


      Connection#openSet(uris, [database], [options], [callback])

      Opens the connection to a replica set.

      show code
      Connection.prototype.openSet = function (uris, database, options, callback) {
      -  if (!rgxProtocol.test(uris)) {
      -    uris = 'mongodb://' + uris;
      -  }
      -
      -  var self = this;
      -
      -  switch (arguments.length) {
      -    case 3:
      -      switch (typeof database) {
      -        case 'string':
      -          this.name = database;
      -          break;
      -        case 'object':
      -          callback = options;
      -          options = database;
      -          database = null;
      -          break;
      -      }
      -
      -      if ('function' === typeof options) {
      -        callback = options;
      -        options = {};
      -      }
      -      break;
      -    case 2:
      -      switch (typeof database) {
      -        case 'string':
      -          this.name = database;
      -          break;
      -        case 'function':
      -          callback = database, database = null;
      -          break;
      -        case 'object':
      -          options = database, database = null;
      -          break;
      -      }
      -  }
      -
      -  var parsed;
      -  try {
      -    parsed = muri(uris);
      -  } catch (err) {
      -    this.error(err, callback);
      -    return this;
      -  }
      -
      -  if (!this.name) {
      -    this.name = parsed.db;
      -  }
      -
      -  this.hosts = parsed.hosts;
      -  this.options = this.parseOptions(options, parsed && parsed.options);
      -  this.replica = true;
      -
      -  if (!this.name) {
      -    this.error(new Error('No database name provided for replica set'), callback);
      -    return this;
      -  }
      -
      -  // authentication
      -  if (options && options.user && options.pass) {
      -    this.user = options.user;
      -    this.pass = options.pass;
      -
      -  } else if (parsed && parsed.auth) {
      -    this.user = parsed.auth.user;
      -    this.pass = parsed.auth.pass;
      -
      -  } else {
      -    this.user = this.pass = undefined;
      -  }
      -
      -  this._open(callback);
      -  return this;
      -};

      Parameters:

      • uris <String> comma-separated mongodb:// `URI`s
      • [database] <String> database name if not included in `uris`
      • [options] <Object> passed to the internal driver
      • [callback] <Function>

      Example:

      - -
      var db = mongoose.createConnection();
      -db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
      - -

      The database name and/or auth need only be included in one URI.
      The options is a hash which is passed to the internal driver connection object.

      - -

      Valid options

      - -
      db      - passed to the connection db instance
      -server  - passed to the connection server instance(s)
      -replset - passed to the connection ReplSetServer instance
      -user    - username for authentication
      -pass    - password for authentication
      -auth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
      -
      - -

      Options passed take precedence over options included in connection strings.

      - -

      Notes:

      - -

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.


      Connection#error(err, callback)

      error

      show code
      Connection.prototype.error = function (err, callback) {
      -  if (callback) return callback(err);
      -  this.emit('error', err);
      -}

      Parameters:

      Graceful error handling, passes error to callback
      if available, else emits error on the connection.


      Connection#_open(callback)

      Handles opening the connection with the appropriate method based on connection type.

      show code
      Connection.prototype._open = function (callback) {
      -  this.readyState = STATES.connecting;
      -  this._closeCalled = false;
      -
      -  var self = this;
      -
      -  var method = this.replica
      -    ? 'doOpenSet'
      -    : 'doOpen';
      -
      -  // open connection
      -  this[method](function (err) {
      -    if (err) {
      -      self.readyState = STATES.disconnected;
      -      if (self._hasOpened) {
      -        if (callback) callback(err);
      -      } else {
      -        self.error(err, callback);
      -      }
      -      return;
      -    }
      -
      -    self.onOpen(callback);
      -  });
      -}

      Parameters:


      Connection#onOpen()

      Called when the connection is opened

      show code
      Connection.prototype.onOpen = function (callback) {
      -  var self = this;
      -
      -  function open (err) {
      -    if (err) {
      -      self.readyState = STATES.disconnected;
      -      if (self._hasOpened) {
      -        if (callback) callback(err);
      -      } else {
      -        self.error(err, callback);
      -      }
      -      return;
      -    }
      -
      -    self.readyState = STATES.connected;
      -
      -    // avoid having the collection subscribe to our event emitter
      -    // to prevent 0.3 warning
      -    for (var i in self.collections)
      -      self.collections[i].onOpen();
      -
      -    callback && callback();
      -    self.emit('open');
      -  };
      -
      -  // re-authenticate
      -  if (self.user && self.pass) {
      -    self.db.authenticate(self.user, self.pass, self.options.auth, open);
      -  }
      -  else
      -    open();
      -};

      Connection#close([callback])

      Closes the connection

      show code
      Connection.prototype.close = function (callback) {
      -  var self = this;
      -  this._closeCalled = true;
      -
      -  switch (this.readyState){
      -    case 0: // disconnected
      -      callback && callback();
      -      break;
      -
      -    case 1: // connected
      -      this.readyState = STATES.disconnecting;
      -      this.doClose(function(err){
      -        if (err){
      -          self.error(err, callback);
      -        } else {
      -          self.onClose();
      -          callback && callback();
      -        }
      -      });
      -      break;
      -
      -    case 2: // connecting
      -      this.once('open', function(){
      -        self.close(callback);
      -      });
      -      break;
      -
      -    case 3: // disconnecting
      -      if (!callback) break;
      -      this.once('close', function () {
      -        callback();
      -      });
      -      break;
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Connection#onClose()

      Called when the connection closes

      show code
      Connection.prototype.onClose = function () {
      -  this.readyState = STATES.disconnected;
      -
      -  // avoid having the collection subscribe to our event emitter
      -  // to prevent 0.3 warning
      -  for (var i in this.collections)
      -    this.collections[i].onClose();
      -
      -  this.emit('close');
      -};

      Connection#collection(name, [options])

      Retrieves a collection, creating it if not cached.

      show code
      Connection.prototype.collection = function (name, options) {
      -  if (!(name in this.collections))
      -    this.collections[name] = new Collection(name, this, options);
      -  return this.collections[name];
      -};

      Parameters:

      • name <String> of the collection
      • [options] <Object> optional collection options

      Returns:


      Connection#model(name, [schema], [collection])

      Defines or retrieves a model.

      show code
      Connection.prototype.model = function (name, schema, collection) {
      -  // collection name discovery
      -  if ('string' == typeof schema) {
      -    collection = schema;
      -    schema = false;
      -  }
      -
      -  if (this.models[name] && !collection) {
      -    // model exists but we are not subclassing with custom collection
      -    if (schema instanceof Schema && schema != this.models[name].schema) {
      -      throw new MongooseError.OverwriteModelError(name);
      -    }
      -    return this.models[name];
      -  }
      -
      -  var opts = { cache: false, connection: this }
      -  var model;
      -
      -  if (schema instanceof Schema) {
      -    // compile a model
      -    model = this.base.model(name, schema, collection, opts)
      -
      -    // only the first model with this name is cached to allow
      -    // for one-offs with custom collection names etc.
      -    if (!this.models[name]) {
      -      this.models[name] = model;
      -    }
      -
      -    model.init();
      -    return model;
      -  }
      -
      -  if (this.models[name] && collection) {
      -    // subclassing current model with alternate collection
      -    model = this.models[name];
      -    schema = model.prototype.schema;
      -    var sub = model.__subclass(this, schema, collection);
      -    // do not cache the sub model
      -    return sub;
      -  }
      -
      -  // lookup model in mongoose module
      -  model = this.base.models[name];
      -
      -  if (!model) {
      -    throw new MongooseError.MissingSchemaError(name);
      -  }
      -
      -  if (this == model.prototype.db
      -      && (!collection || collection == model.collection.name)) {
      -    // model already uses this connection.
      -
      -    // only the first model with this name is cached to allow
      -    // for one-offs with custom collection names etc.
      -    if (!this.models[name]) {
      -      this.models[name] = model;
      -    }
      -
      -    return model;
      -  }
      -
      -  return this.models[name] = model.__subclass(this, schema, collection);
      -}

      Parameters:

      • name <String> the model name
      • [schema] <Schema> a schema. necessary when defining a model
      • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

      Returns:

      • <Model> The compiled model
      var mongoose = require('mongoose');
      -var db = mongoose.createConnection(..);
      -db.model('Venue', new Schema(..));
      -var Ticket = db.model('Ticket', new Schema(..));
      -var Venue = db.model('Venue');
      - -

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

      - -

      Example:

      - -
      var schema = new Schema({ name: String }, { collection: 'actor' });
      -
      -// or
      -
      -schema.set('collection', 'actor');
      -
      -// or
      -
      -var collectionName = 'actor'
      -var M = conn.model('Actor', schema, collectionName)

      Connection#setProfiling(level, [ms], callback)

      Set profiling level.

      show code
      Connection.prototype.setProfiling = function (level, ms, callback) {
      -  if (STATES.connected !== this.readyState) {
      -    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
      -  }
      -
      -  if (!callback) callback = ms, ms = 100;
      -
      -  var cmd = {};
      -
      -  switch (level) {
      -    case 0:
      -    case 'off':
      -      cmd.profile = 0;
      -      break;
      -    case 1:
      -    case 'slow':
      -      cmd.profile = 1;
      -      if ('number' !== typeof ms) {
      -        ms = parseInt(ms, 10);
      -        if (isNaN(ms)) ms = 100;
      -      }
      -      cmd.slowms = ms;
      -      break;
      -    case 2:
      -    case 'all':
      -      cmd.profile = 2;
      -      break;
      -    default:
      -      return callback(new Error('Invalid profiling level: '+ level));
      -  }
      -
      -  this.db.executeDbCommand(cmd, function (err, resp) {
      -    if (err) return callback(err);
      -
      -    var doc = resp.documents[0];
      -
      -    err = 1 === doc.ok
      -      ? null
      -      : new Error('Could not set profiling level to: '+ level)
      -
      -    callback(err, doc);
      -  });
      -};

      Parameters:

      • level <Number, String> either off (0), slow (1), or all (2)
      • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
      • callback <Function>

      Connection#db

      The mongodb.Db instance, set when the connection is opened


      Connection#collections

      A hash of the collections associated with this connection


      Connection#readyState

      Connection ready state

      - -
        -
      • 0 = disconnected
      • -
      • 1 = connected
      • -
      • 2 = connecting
      • -
      • 3 = disconnecting
      • -
      - -

      Each state change emits its associated event name.

      - -

      Example

      - -
      conn.on('connected', callback);
      -conn.on('disconnected', callback);

    • document.js

      Document(obj, [fields], [skipId])

      Document constructor.

      show code
      function Document (obj, fields, skipId) {
      -  this.setMaxListeners(0);
      -
      -  if ('boolean' === typeof fields) {
      -    this._strictMode = fields;
      -    this._selected = fields = undefined;
      -  } else {
      -    this._strictMode = this.schema.options && this.schema.options.strict;
      -    this._selected = fields;
      -  }
      -
      -  this.isNew = true;
      -  this.errors = undefined;
      -  this._shardval = undefined;
      -  this._saveError = undefined;
      -  this._validationError = undefined;
      -  this._adhocPaths = undefined;
      -  this._removing = undefined;
      -  this._inserting = undefined;
      -  this.__version = undefined;
      -  this.__getters = {};
      -  this.__id = undefined;
      -
      -  this._activePaths = new ActiveRoster;
      -
      -  var required = this.schema.requiredPaths();
      -  for (var i = 0; i < required.length; ++i) {
      -    this._activePaths.require(required[i]);
      -  }
      -
      -  this._doc = this._buildDoc(obj, fields, skipId);
      -  if (obj) this.set(obj, undefined, true);
      -  this._registerHooks();
      -};

      Parameters:

      • obj <Object> the values to set
      • [fields] <Object> the fields which were selected in the query returning this document
      • [skipId] <Boolean> bool, should we auto create an ObjectId _id

      Events:

      • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

      • save: Emitted when the document is successfully saved


      Document#_buildDoc(obj, [fields], [skipId])

      Builds the default doc structure

      show code
      Document.prototype._buildDoc = function (obj, fields, skipId) {
      -  var doc = {}
      -    , self = this
      -    , exclude
      -    , keys
      -    , key
      -    , ki
      -
      -  // determine if this doc is a result of a query with
      -  // excluded fields
      -  if (fields && 'Object' === fields.constructor.name) {
      -    keys = Object.keys(fields);
      -    ki = keys.length;
      -
      -    while (ki--) {
      -      if ('_id' !== keys[ki]) {
      -        exclude = 0 === fields[keys[ki]];
      -        break;
      -      }
      -    }
      -  }
      -
      -  var paths = Object.keys(this.schema.paths)
      -    , plen = paths.length
      -    , ii = 0
      -
      -  for (; ii < plen; ++ii) {
      -    var p = paths[ii];
      -
      -    if ('_id' == p) {
      -      if (skipId) continue;
      -      if (obj && '_id' in obj) continue;
      -    }
      -
      -    var type = this.schema.paths[p]
      -      , path = p.split('.')
      -      , len = path.length
      -      , last = len-1
      -      , doc_ = doc
      -      , i = 0
      -
      -    for (; i < len; ++i) {
      -      var piece = path[i]
      -        , def
      -
      -      if (i === last) {
      -        if (fields) {
      -          if (exclude) {
      -            // apply defaults to all non-excluded fields
      -            if (p in fields) continue;
      -
      -            def = type.getDefault(self, true);
      -            if ('undefined' !== typeof def) {
      -              doc_[piece] = def;
      -              self._activePaths.default(p);
      -            }
      -
      -          } else if (p in fields) {
      -            // selected field
      -            def = type.getDefault(self, true);
      -            if ('undefined' !== typeof def) {
      -              doc_[piece] = def;
      -              self._activePaths.default(p);
      -            }
      -          }
      -        } else {
      -          def = type.getDefault(self, true);
      -          if ('undefined' !== typeof def) {
      -            doc_[piece] = def;
      -            self._activePaths.default(p);
      -          }
      -        }
      -      } else {
      -        doc_ = doc_[piece] || (doc_[piece] = {});
      -      }
      -    }
      -  };
      -
      -  return doc;
      -};

      Parameters:

      Returns:


      Document#init(doc, fn)

      Initializes the document without setters or marking anything modified.

      show code
      Document.prototype.init = function (doc, fn) {
      -  this.isNew = false;
      -
      -  init(this, doc, this._doc);
      -  this._storeShard();
      -
      -  this.emit('init', this);
      -  if (fn) fn(null);
      -  return this;
      -};

      Parameters:

      Called internally after a document is returned from mongodb.


      Document#_storeShard()

      Stores the current values of the shard keys.

      show code
      Document.prototype._storeShard = function _storeShard () {
      -  // backwards compat
      -  var key = this.schema.options.shardKey || this.schema.options.shardkey;
      -  if (!(key && 'Object' == key.constructor.name)) return;
      -
      -  var orig = this._shardval = {}
      -    , paths = Object.keys(key)
      -    , len = paths.length
      -    , val
      -
      -  for (var i = 0; i < len; ++i) {
      -    val = this.getValue(paths[i]);
      -    if (isMongooseObject(val)) {
      -      orig[paths[i]] = val.toObject({ depopulate: true })
      -    } else if (null != val && val.valueOf) {
      -      orig[paths[i]] = val.valueOf();
      -    } else {
      -      orig[paths[i]] = val;
      -    }
      -  }
      -}

      Note:

      - -

      Shard key values do not / are not allowed to change.


      Document#update(doc, options, callback)

      Sends an update command with this document _id as the query selector.

      show code
      Document.prototype.update = function update () {
      -  var args = utils.args(arguments);
      -  args.unshift({_id: this._id});
      -  this.constructor.update.apply(this.constructor, args);
      -}

      Parameters:

      Returns:

      Example:

      - -
      weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);
      - -

      Valid options:

      - -

      Document#set(path, val, [type], [options])

      Sets the value of a path, or many paths.

      show code
      Document.prototype.set = function (path, val, type, options) {
      -  if (type && 'Object' == type.constructor.name) {
      -    options = type;
      -    type = undefined;
      -  }
      -
      -  var merge = options && options.merge
      -    , adhoc = type && true !== type
      -    , constructing = true === type
      -    , adhocs
      -
      -  if (adhoc) {
      -    adhocs = this._adhocPaths || (this._adhocPaths = {});
      -    adhocs[path] = Schema.interpretAsType(path, type);
      -  }
      -
      -  if ('string' !== typeof path) {
      -    // new Document({ key: val })
      -
      -    if (null === path || undefined === path) {
      -      var _ = path;
      -      path = val;
      -      val = _;
      -
      -    } else {
      -      var prefix = val
      -        ? val + '.'
      -        : '';
      -
      -      if (path instanceof Document) path = path._doc;
      -
      -      var keys = Object.keys(path)
      -        , i = keys.length
      -        , pathtype
      -        , key
      -
      -      while (i--) {
      -        key = keys[i];
      -        pathtype = this.schema.pathType(prefix + key);
      -        if (null != path[key]
      -            && 'Object' == path[key].constructor.name
      -            && 'virtual' != pathtype
      -            && !(this._path(prefix + key) instanceof MixedSchema)) {
      -          this.set(path[key], prefix + key, constructing);
      -        } else if (this._strictMode) {
      -          if ('real' === pathtype || 'virtual' === pathtype) {
      -            this.set(prefix + key, path[key], constructing);
      -          } else if ('throw' == this._strictMode) {
      -            throw new Error("Field `" + key + "` is not in schema.");
      -          }
      -        } else if (undefined !== path[key]) {
      -          this.set(prefix + key, path[key], constructing);
      -        }
      -      }
      -
      -      return this;
      -    }
      -  }
      -
      -  // ensure _strict is honored for obj props
      -  // docschema = new Schema({ path: { nest: 'string' }})
      -  // doc.set('path', obj);
      -  var pathType = this.schema.pathType(path);
      -  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
      -    if (!merge) this.setValue(path, null);
      -    this.set(val, path, constructing);
      -    return this;
      -  }
      -
      -  var schema;
      -  if ('adhocOrUndefined' == pathType && this._strictMode) {
      -    return this;
      -  } else if ('virtual' == pathType) {
      -    schema = this.schema.virtualpath(path);
      -    schema.applySetters(val, this);
      -    return this;
      -  } else {
      -    schema = this._path(path);
      -  }
      -
      -  var parts = path.split('.')
      -    , pathToMark
      -
      -  // When using the $set operator the path to the field must already exist.
      -  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
      -
      -  if (parts.length <= 1) {
      -    pathToMark = path;
      -  } else {
      -    for (var i = 0; i < parts.length; ++i) {
      -      var part = parts[i];
      -      var subpath = parts.slice(0, i).concat(part).join('.');
      -      if (this.isDirectModified(subpath) // earlier prefixes that are already
      -                                         // marked as dirty have precedence
      -          || this.get(subpath) === null) {
      -        pathToMark = subpath;
      -        break;
      -      }
      -    }
      -
      -    if (!pathToMark) pathToMark = path;
      -  }
      -
      -  if (!schema || null === val || undefined === val) {
      -    this._set(pathToMark, path, constructing, parts, schema, val);
      -    return this;
      -  }
      -
      -  var self = this;
      -
      -  // if this doc is being constructed we should not
      -  // trigger getters.
      -  var priorVal = constructing
      -    ? undefined
      -    : this.get(path);
      -
      -  var shouldSet = this.try(function(){
      -    val = schema.applySetters(val, self, false, priorVal);
      -  });
      -
      -  if (shouldSet) {
      -    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
      -  }
      -
      -  return this;
      -}

      Parameters:

      • path <String, Object> path or object of key/vals to set
      • val <Any> the value to set
      • [type] <Schema, String, Number, Buffer, etc..> optionally specify a type for "on-the-fly" attributes
      • [options] <Object> optionally specify options that modify the behavior of the set

      Example:

      - -
      // path, value
      -doc.set(path, value)
      -
      -// object
      -doc.set({
      -    path  : value
      -  , path2 : {
      -       path  : value
      -    }
      -})
      -
      -// only-the-fly cast to number
      -doc.set(path, value, Number)
      -
      -// only-the-fly cast to string
      -doc.set(path, value, String)

      Document#_shouldModify()

      Determine if we should mark this change as modified.

      show code
      Document.prototype._shouldModify = function (
      -    pathToMark, path, constructing, parts, schema, val, priorVal) {
      -
      -  if (this.isNew) return true;
      -  if (this.isDirectModified(pathToMark)) return false;
      -
      -  if (undefined === val && !this.isSelected(path)) {
      -    // when a path is not selected in a query, its initial
      -    // value will be undefined.
      -    return true;
      -  }
      -
      -  if (undefined === val && path in this._activePaths.states.default) {
      -    // we're just unsetting the default value which was never saved
      -    return false;
      -  }
      -
      -  if (!deepEqual(val, priorVal || this.get(path))) {
      -    return true;
      -  }
      -
      -  if (!constructing &&
      -      null != val &&
      -      path in this._activePaths.states.default &&
      -      deepEqual(val, schema.getDefault(this, constructing))) {
      -    // a path with a default was $unset on the server
      -    // and the user is setting it to the same value again
      -    return true;
      -  }
      -
      -  return false;
      -}

      Returns:


      Document#_set()

      Handles the actual setting of the value and marking the path modified if appropriate.

      show code
      Document.prototype._set = function (
      -    pathToMark, path, constructing, parts, schema, val, priorVal) {
      -
      -  var shouldModify = this._shouldModify.apply(this, arguments);
      -
      -  if (shouldModify) {
      -    this.markModified(pathToMark, val);
      -
      -    // handle directly setting arrays (gh-1126)
      -    MongooseArray || (MongooseArray = require('./types/array'));
      -    if (val instanceof MongooseArray) {
      -      val._registerAtomic('$set', val);
      -    }
      -  }
      -
      -  var obj = this._doc
      -    , i = 0
      -    , l = parts.length
      -
      -  for (; i < l; i++) {
      -    var next = i + 1
      -      , last = next === l;
      -
      -    if (last) {
      -      obj[parts[i]] = val;
      -    } else {
      -      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
      -        obj = obj[parts[i]];
      -      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
      -        obj = obj[parts[i]];
      -      } else {
      -        obj = obj[parts[i]] = {};
      -      }
      -    }
      -  }
      -}

      Document#getValue(path)

      Gets a raw value from a path (no getters)

      show code
      Document.prototype.getValue = function (path) {
      -  var parts = path.split('.')
      -    , obj = this._doc
      -    , part;
      -
      -  for (var i = 0, l = parts.length; i < l; i++) {
      -    part = parts[i];
      -    obj = obj.getValue
      -        ? obj.getValue(part) // If we have an embedded array document member
      -        : obj[part];
      -    if (!obj) return obj;
      -  }
      -
      -  return obj;
      -}

      Parameters:


      Document#setValue(path, value)

      Sets a raw value for a path (no casting, setters, transformations)

      show code
      Document.prototype.setValue = function (path, val) {
      -  var parts = path.split('.')
      -    , obj = this._doc;
      -
      -  for (var i = 0, len = parts.length-1; i < len; i++) {
      -    obj = obj[parts[i]];
      -  }
      -
      -  obj[parts[len]] = val;
      -  return this;
      -};

      Parameters:


      Document#get(path, [type])

      Returns the value of a path.

      show code
      Document.prototype.get = function (path, type) {
      -  var adhocs;
      -  if (type) {
      -    adhocs = this._adhocPaths || (this._adhocPaths = {});
      -    adhocs[path] = Schema.interpretAsType(path, type);
      -  }
      -
      -  var schema = this._path(path) || this.schema.virtualpath(path)
      -    , pieces = path.split('.')
      -    , obj = this._doc;
      -
      -  for (var i = 0, l = pieces.length; i < l; i++) {
      -    obj = null == obj ? null : obj[pieces[i]];
      -  }
      -
      -  if (schema) {
      -    obj = schema.applyGetters(obj, this);
      -  }
      -
      -  return obj;
      -};

      Parameters:

      Example

      - -
      // path
      -doc.get('age') // 47
      -
      -// dynamic casting to a string
      -doc.get('age', String) // "47"

      Document#_path(path)

      Returns the schematype for the given path.

      show code
      Document.prototype._path = function (path) {
      -  var adhocs = this._adhocPaths
      -    , adhocType = adhocs && adhocs[path];
      -
      -  if (adhocType) {
      -    return adhocType;
      -  } else {
      -    return this.schema.path(path);
      -  }
      -};

      Parameters:


      Document#markModified(path)

      Marks the path as having pending changes to write to the db.

      show code
      Document.prototype.markModified = function (path) {
      -  this._activePaths.modify(path);
      -}

      Parameters:

      • path <String> the path to mark modified

      Very helpful when using Mixed types.

      - -

      Example:

      - -
      doc.mixed.type = 'changed';
      -doc.markModified('mixed.type');
      -doc.save() // changes to mixed.type are now persisted

      Document#try(fn, scope)

      Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

      show code
      Document.prototype.try = function (fn, scope) {
      -  var res;
      -  try {
      -    fn.call(scope);
      -    res = true;
      -  } catch (e) {
      -    this._error(e);
      -    res = false;
      -  }
      -  return res;
      -};

      Parameters:

      • fn <Function> function to execute
      • scope <Object> the scope with which to call fn

      Document#modifiedPaths()

      Returns the list of paths that have been modified.

      show code
      Document.prototype.modifiedPaths = function () {
      -  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
      -
      -  return directModifiedPaths.reduce(function (list, path) {
      -    var parts = path.split('.');
      -    return list.concat(parts.reduce(function (chains, part, i) {
      -      return chains.concat(parts.slice(0, i).concat(part).join('.'));
      -    }, []));
      -  }, []);
      -};

      Returns:


      Document#isModified([path])

      Returns true if this document was modified, else false.

      show code
      Document.prototype.isModified = function (path) {
      -  return path
      -    ? !!~this.modifiedPaths().indexOf(path)
      -    : this._activePaths.some('modify');
      -};

      Parameters:

      Returns:

      If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

      - -

      Example

      - -
      doc.set('documents.0.title', 'changed');
      -doc.isModified()                    // true
      -doc.isModified('documents')         // true
      -doc.isModified('documents.0.title') // true
      -doc.isDirectModified('documents')   // false

      Document#isDirectModified(path)

      Returns true if path was directly set and modified, else false.

      show code
      Document.prototype.isDirectModified = function (path) {
      -  return (path in this._activePaths.states.modify);
      -};

      Parameters:

      Returns:

      Example

      - -
      doc.set('documents.0.title', 'changed');
      -doc.isDirectModified('documents.0.title') // true
      -doc.isDirectModified('documents') // false

      Document#isInit(path)

      Checks if path was initialized.

      show code
      Document.prototype.isInit = function (path) {
      -  return (path in this._activePaths.states.init);
      -};

      Parameters:

      Returns:


      Document#isSelected(path)

      Checks if path was selected in the source query which initialized this document.

      show code
      Document.prototype.isSelected = function isSelected (path) {
      -  if (this._selected) {
      -
      -    if ('_id' === path) {
      -      return 0 !== this._selected._id;
      -    }
      -
      -    var paths = Object.keys(this._selected)
      -      , i = paths.length
      -      , inclusive = false
      -      , cur
      -
      -    if (1 === i && '_id' === paths[0]) {
      -      // only _id was selected.
      -      return 0 === this._selected._id;
      -    }
      -
      -    while (i--) {
      -      cur = paths[i];
      -      if ('_id' == cur) continue;
      -      inclusive = !! this._selected[cur];
      -      break;
      -    }
      -
      -    if (path in this._selected) {
      -      return inclusive;
      -    }
      -
      -    i = paths.length;
      -    var pathDot = path + '.';
      -
      -    while (i--) {
      -      cur = paths[i];
      -      if ('_id' == cur) continue;
      -
      -      if (0 === cur.indexOf(pathDot)) {
      -        return inclusive;
      -      }
      -
      -      if (0 === pathDot.indexOf(cur)) {
      -        return inclusive;
      -      }
      -    }
      -
      -    return ! inclusive;
      -  }
      -
      -  return true;
      -}

      Parameters:

      Returns:

      Example

      - -
      Thing.findOne().select('name').exec(function (err, doc) {
      -   doc.isSelected('name') // true
      -   doc.isSelected('age')  // false
      -})

      Document#validate(cb)

      Executes registered validation rules for this document.

      show code
      Document.prototype.validate = function (cb) {
      -  var self = this
      -
      -  // only validate required fields when necessary
      -  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
      -    if (!self.isSelected(path) && !self.isModified(path)) return false;
      -    return true;
      -  });
      -
      -  paths = paths.concat(Object.keys(this._activePaths.states.init));
      -  paths = paths.concat(Object.keys(this._activePaths.states.modify));
      -  paths = paths.concat(Object.keys(this._activePaths.states.default));
      -
      -  if (0 === paths.length) {
      -    complete();
      -    return this;
      -  }
      -
      -  var validating = {}
      -    , total = 0;
      -
      -  paths.forEach(validatePath);
      -  return this;
      -
      -  function validatePath (path) {
      -    if (validating[path]) return;
      -
      -    validating[path] = true;
      -    total++;
      -
      -    process.nextTick(function(){
      -      var p = self.schema.path(path);
      -      if (!p) return --total || complete();
      -
      -      p.doValidate(self.getValue(path), function (err) {
      -        if (err) self.invalidate(path, err, true);
      -        --total || complete();
      -      }, self);
      -    });
      -  }
      -
      -  function complete () {
      -    var err = self._validationError;
      -    self._validationError = undefined;
      -    self.emit('validate', self);
      -    cb(err);
      -  }
      -};

      Parameters:

      • cb <Function> called after validation completes, passing an error if one occurred

      Note:

      - -

      This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

      - -

      Example:

      - -
      doc.validate(function (err) {
      -  if (err) handleError(err);
      -  else // validation passed
      -});

      Document#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      Document.prototype.invalidate = function (path, err) {
      -  if (!this._validationError) {
      -    this._validationError = new ValidationError(this);
      -  }
      -
      -  if (!err || 'string' === typeof err) {
      -    err = new ValidatorError(path, err);
      -  }
      -
      -  this._validationError.errors[path] = err;
      -}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> the error which states the reason `path` was invalid

      Document#_reset()

      Resets the internal modified state of this document.

      show code
      Document.prototype._reset = function reset () {
      -  var self = this;
      -  DocumentArray || (DocumentArray = require('./types/documentarray'));
      -
      -  this._activePaths
      -  .map('init', 'modify', function (i) {
      -    return self.getValue(i);
      -  })
      -  .filter(function (val) {
      -    return val && val instanceof DocumentArray && val.length;
      -  })
      -  .forEach(function (array) {
      -    var i = array.length;
      -    while (i--) {
      -      var doc = array[i];
      -      if (!doc) continue;
      -      doc._reset();
      -    }
      -  });
      -
      -  // clear atomics
      -  this._dirty().forEach(function (dirt) {
      -    var type = dirt.value;
      -    if (type && type._atomics) {
      -      type._atomics = {};
      -    }
      -  });
      -
      -  // Clear 'modify'('dirty') cache
      -  this._activePaths.clear('modify');
      -  this._validationError = undefined;
      -  this.errors = undefined;
      -  var self = this;
      -  this.schema.requiredPaths().forEach(function (path) {
      -    self._activePaths.require(path);
      -  });
      -
      -  return this;
      -}

      Returns:


      Document#_dirty()

      Returns this documents dirty paths / vals.

      show code
      Document.prototype._dirty = function _dirty () {
      -  var self = this;
      -
      -  var all = this._activePaths.map('modify', function (path) {
      -    return { path: path
      -           , value: self.getValue(path)
      -           , schema: self._path(path) };
      -  });
      -
      -  // Sort dirty paths in a flat hierarchy.
      -  all.sort(function (a, b) {
      -    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
      -  });
      -
      -  // Ignore "foo.a" if "foo" is dirty already.
      -  var minimal = []
      -    , lastPath
      -    , top;
      -
      -  all.forEach(function (item, i) {
      -    if (item.path.indexOf(lastPath) !== 0) {
      -      lastPath = item.path + '.';
      -      minimal.push(item);
      -      top = item;
      -    } else {
      -      // special case for top level MongooseArrays
      -      if (top.value && top.value._atomics && top.value.hasAtomics()) {
      -        // the `top` array itself and a sub path of `top` are being modified.
      -        // the only way to honor all of both modifications is through a $set
      -        // of entire array.
      -        top.value._atomics = {};
      -        top.value._atomics.$set = top.value;
      -      }
      -    }
      -  });
      -
      -  top = lastPath = null;
      -  return minimal;
      -}

      Document#_setSchema(schema)

      Assigns/compiles schema into this documents prototype.

      show code
      Document.prototype._setSchema = function (schema) {
      -  compile(schema.tree, this);
      -  this.schema = schema;
      -}

      Parameters:


      Document#_registerHooks()

      Register default hooks

      show code
      Document.prototype._registerHooks = function _registerHooks () {
      -  if (!this.save) return;
      -
      -  DocumentArray || (DocumentArray = require('./types/documentarray'));
      -
      -  this.pre('save', function (next) {
      -    // we keep the error semaphore to make sure we don't
      -    // call `save` unnecessarily (we only need 1 error)
      -    var subdocs = 0
      -      , error = false
      -      , self = this;
      -
      -    // check for DocumentArrays
      -    var arrays = this._activePaths
      -    .map('init', 'modify', function (i) {
      -      return self.getValue(i);
      -    })
      -    .filter(function (val) {
      -      return val && val instanceof DocumentArray && val.length;
      -    });
      -
      -    if (!arrays.length)
      -      return next();
      -
      -    arrays.forEach(function (array) {
      -      if (error) return;
      -
      -      // handle sparse arrays by using for loop vs array.forEach
      -      // which skips the sparse elements
      -
      -      var len = array.length
      -      subdocs += len;
      -
      -      for (var i = 0; i < len; ++i) {
      -        if (error) break;
      -
      -        var doc = array[i];
      -        if (!doc) {
      -          --subdocs || next();
      -          continue;
      -        }
      -
      -        doc.save(handleSave);
      -      }
      -    });
      -
      -    function handleSave (err) {
      -      if (error) return;
      -
      -      if (err) {
      -        self._validationError = undefined;
      -        return next(error = err);
      -      }
      -
      -      --subdocs || next();
      -    }
      -
      -  }, function (err) {
      -    // emit on the Model if listening
      -    if (this.constructor.listeners('error').length) {
      -      this.constructor.emit('error', err);
      -    } else {
      -      // emit on the connection
      -      if (!this.db.listeners('error').length) {
      -        err.stack = 'No listeners detected, throwing. '
      -                  + 'Consider adding an error listener to your connection.
      -'
      -                  + err.stack
      -      }
      -      this.db.emit('error', err);
      -    }
      -  }).pre('save', function checkForExistingErrors (next) {
      -    // if any doc.set() calls failed
      -    var err = this._saveError;
      -    if (err) {
      -      this._saveError = null;
      -      next(err);
      -    } else {
      -      next();
      -    }
      -  }).pre('save', function validation (next) {
      -    return this.validate(next);
      -  });
      -
      -  // add user defined queues
      -  this._doQueue();
      -};

      Document#_error(err)

      Registers an error

      show code
      Document.prototype._error = function (err) {
      -  this._saveError = err;
      -  return this;
      -};

      Parameters:


      Document#_doQueue()

      Executes methods queued from the Schema definition

      show code
      Document.prototype._doQueue = function () {
      -  var q = this.schema && this.schema.callQueue;
      -  if (q) {
      -    for (var i = 0, l = q.length; i < l; i++) {
      -      this[q[i][0]].apply(this, q[i][1]);
      -    }
      -  }
      -  return this;
      -};

      Document#toObject([options])

      Converts this document into a plain javascript object

      show code
      Document.prototype.toObject = function (options) {
      -  // When internally saving this document we always pass options,
      -  // bypassing the custom schema options.
      -  if (!(options && 'Object' == options.constructor.name)) {
      -    options = this.schema.options.toObject
      -      ? clone(this.schema.options.toObject)
      -      : {};
      -  }
      -
      -  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
      -
      -  var ret = clone(this._doc, options);
      -
      -  if (options.virtuals || options.getters && false !== options.virtuals) {
      -    applyGetters(this, ret, 'virtuals', options);
      -  }
      -
      -  if (options.getters) {
      -    applyGetters(this, ret, 'paths', options);
      -  }
      -
      -  if (true === options.transform) {
      -    var opts = options.json
      -      ? this.schema.options.toJSON
      -      : this.schema.options.toObject;
      -    if (opts) {
      -      options.transform = opts.transform;
      -    }
      -  }
      -
      -  if ('function' == typeof options.transform) {
      -    var xformed = options.transform(this, ret, options);
      -    if ('undefined' != typeof xformed) ret = xformed;
      -  }
      -
      -  return ret;
      -};

      Parameters:

      Returns:

      Options:

      - -
        -
      • getters apply all getters (path and virtual getters)
      • -
      • virtuals apply virtual getters (can override getters option)
      • -
      • minimize remove empty objects (defaults to true)
      • -
      • transform a transform function to apply to the resulting document before returning
      • -
      - -

      Getters/Virtuals

      - -

      Example of only applying path getters

      - -
      doc.toObject({ getters: true, virtuals: false })
      - -

      Example of only applying virtual getters

      - -
      doc.toObject({ virtuals: true })
      - -

      Example of applying both path and virtual getters

      - -
      doc.toObject({ getters: true })
      - -

      To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

      - -
      schema.set('toObject', { virtuals: true })
      - -

      Transform

      - -

      We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

      - -

      Transform functions receive three arguments

      - -
      function (doc, ret, options) {}
      - -
        -
      • doc The mongoose document which is being converted
      • -
      • ret The plain object representation which has been converted
      • -
      • options The options in use (either schema options or the options passed inline)
      • -
      - -

      Example

      - -
      // specify the transform schema option
      -schema.options.toObject.transform = function (doc, ret, options) {
      -  // remove the _id of every document before returning the result
      -  delete ret._id;
      -}
      -
      -// without the transformation in the schema
      -doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
      -
      -// with the transformation
      -doc.toObject(); // { name: 'Wreck-it Ralph' }
      - -

      With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

      - -
      schema.options.toObject.transform = function (doc, ret, options) {
      -  return { movie: ret.name }
      -}
      -
      -// without the transformation in the schema
      -doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
      -
      -// with the transformation
      -doc.toObject(); // { movie: 'Wreck-it Ralph' }
      - -

      Note: if a transform function returns undefined, the return value will be ignored.

      - -

      Transformations may also be applied inline, overridding any transform set in the options:

      - -
      function xform (doc, ret, options) {
      -  return { inline: ret.name, custom: true }
      -}
      -
      -// pass the transform as an inline option
      -doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }
      - -

      Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

      - -
      schema.options.toObject.hide = '_id';
      -schema.options.toObject.transform = function (doc, ret, options) {
      -  if (options.hide) {
      -    options.hide.split(' ').forEach(function (prop) {
      -      delete ret[prop];
      -    });
      -  }
      -}
      -
      -var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });
      -doc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }
      -doc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }
      -doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }
      - -

      Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

      - -
      if ('function' == typeof doc.ownerDocument) {
      -  // working with a sub doc
      -}
      - -

      Transforms, like all of these options, are also available for toJSON.

      - -

      See schema options for some more details.


      Document#toJSON(options)

      The return value of this method is used in calls to JSON.stringify(doc).

      show code
      Document.prototype.toJSON = function (options) {
      -  // check for object type since an array of documents
      -  // being stringified passes array indexes instead
      -  // of options objects. JSON.stringify([doc, doc])
      -  if (!(options && 'Object' == options.constructor.name)) {
      -    options = this.schema.options.toJSON
      -      ? clone(this.schema.options.toJSON)
      -      : {};
      -  }
      -  options.json = true;
      -  return this.toObject(options);
      -};

      Parameters:

      • options <Object> same options as [Document#toObject](#document_Document-toObject)

      Returns:

      This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

      - -
      schema.set('toJSON', { virtuals: true })
      - -

      See schema options for details.


      Document#inspect()

      Helper for console.log

      show code
      Document.prototype.inspect = function (options) {
      -  var opts = options && 'Object' == options.constructor.name ? options :
      -      this.schema.options.toObject ? clone(this.schema.options.toObject) :
      -      {};
      -  opts.minimize = false;
      -  return inspect(this.toObject(opts));
      -};

      Document#toString()

      Helper for console.log


      Document#equals(doc)

      Returns true if the Document stores the same data as doc.

      show code
      Document.prototype.equals = function (doc) {
      -  var tid = this.get('_id');
      -  var docid = doc.get('_id');
      -  return tid.equals
      -    ? tid.equals(docid)
      -    : tid === docid;
      -};

      Parameters:

      Returns:

      Documents are considered equal when they have matching _ids.


      Document#errors

      Hash containing current validation errors.


      Document#id

      The string version of this documents _id.

      - -

      Note:

      - -

      This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

      - -
      new Schema({ name: String }, { id: false });

      Document#isNew

      Boolean flag specifying if the document is new.


      Document#schema

      The documents schema.


    • drivers/node-mongodb-native/collection.js

      NativeCollection()

      A node-mongodb-native collection implementation.

      show code
      function NativeCollection () {
      -  this.collection = null;
      -  MongooseCollection.apply(this, arguments);
      -}

      Inherits:

      All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


      NativeCollection#onOpen()

      Called when the connection opens.

      show code
      NativeCollection.prototype.onOpen = function () {
      -  var self = this;
      -
      -  if (this.collection) {
      -    return MongooseCollection.prototype.onOpen.call(self);
      -  }
      -
      -  if (!self.opts.size) {
      -    // non-capped
      -    return self.conn.db.collection(self.name, callback);
      -  }
      -
      -  // capped
      -  return self.conn.db.collection(self.name, function (err, c) {
      -    if (err) return callback(err);
      -
      -    // discover if this collection exists and if it is capped
      -    c.options(function (err, exists) {
      -      if (err) return callback(err);
      -
      -      if (exists) {
      -        if (exists.capped) {
      -          callback(null, c);
      -        } else {
      -          var msg = 'A non-capped collection exists with this name.
      -
      -'
      -                  + ' To use this collection as a capped collection, please '
      -                  + 'first convert it.
      -'
      -                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
      -          err = new Error(msg);
      -          callback(err);
      -        }
      -      } else {
      -        // create
      -        var opts = utils.clone(self.opts);
      -        opts.capped = true;
      -        self.conn.db.createCollection(self.name, opts, callback);
      -      }
      -    });
      -  });
      -
      -  function callback (err, collection) {
      -    if (err) {
      -      // likely a strict mode error
      -      self.conn.emit('error', err);
      -    } else {
      -      self.collection = collection;
      -      MongooseCollection.prototype.onOpen.call(self);
      -    }
      -  };
      -};

      NativeCollection#onClose()

      Called when the connection closes

      show code
      NativeCollection.prototype.onClose = function () {
      -  MongooseCollection.prototype.onClose.call(this);
      -};

      NativeCollection#getIndexes(callback)

      Retreives information about this collections indexes.

      Parameters:


    • drivers/node-mongodb-native/connection.js

      NativeConnection()

      A node-mongodb-native connection implementation.

      show code
      function NativeConnection() {
      -  MongooseConnection.apply(this, arguments);
      -  this._listening = false;
      -};

      Inherits:


      NativeConnection#doOpen(fn)

      Opens the connection to MongoDB.

      show code
      NativeConnection.prototype.doOpen = function (fn) {
      -  if (this.db) {
      -    mute(this);
      -  }
      -
      -  var server = new mongo.Server(this.host, this.port, this.options.server);
      -  this.db = new mongo.Db(this.name, server, this.options.db);
      -
      -  var self = this;
      -  this.db.open(function (err) {
      -    if (err) return fn(err);
      -    fn();
      -    listen(self);
      -  });
      -
      -  return this;
      -};

      Parameters:

      Returns:


      NativeConnection#doOpenSet(fn)

      Opens a connection to a MongoDB ReplicaSet.

      show code
      NativeConnection.prototype.doOpenSet = function (fn) {
      -  if (this.db) {
      -    mute(this);
      -  }
      -
      -  var servers = []
      -    , self = this;
      -
      -  this.hosts.forEach(function (server) {
      -    var host = server.host || server.ipc;
      -    var port = server.port || 27017;
      -    servers.push(new mongo.Server(host, port, self.options.server));
      -  })
      -
      -  var server = new ReplSetServers(servers, this.options.replset);
      -  this.db = new mongo.Db(this.name, server, this.options.db);
      -
      -  this.db.on('fullsetup', function () {
      -    self.emit('fullsetup')
      -  });
      -
      -  this.db.open(function (err) {
      -    if (err) return fn(err);
      -    fn();
      -    listen(self);
      -  });
      -
      -  return this;
      -};

      Parameters:

      Returns:

      See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


      NativeConnection#doClose(fn)

      Closes the connection

      show code
      NativeConnection.prototype.doClose = function (fn) {
      -  this.db.close();
      -  if (fn) fn();
      -  return this;
      -}

      Parameters:

      Returns:


      NativeConnection#parseOptions(passed, [connStrOptions])

      Prepares default connection options for the node-mongodb-native driver.

      show code
      NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {
      -  var o = passed || {};
      -  o.db || (o.db = {});
      -  o.auth || (o.auth = {});
      -  o.server || (o.server = {});
      -  o.replset || (o.replset = {});
      -  o.server.socketOptions || (o.server.socketOptions = {});
      -  o.replset.socketOptions || (o.replset.socketOptions = {});
      -
      -  var opts = connStrOpts || {};
      -  Object.keys(opts).forEach(function (name) {
      -    switch (name) {
      -      case 'poolSize':
      -        if ('undefined' == typeof o.server.poolSize) {
      -          o.server.poolSize = o.replset.poolSize = opts[name];
      -        }
      -        break;
      -      case 'slaveOk':
      -        if ('undefined' == typeof o.server.slave_ok) {
      -          o.server.slave_ok = opts[name];
      -        }
      -        break;
      -      case 'autoReconnect':
      -        if ('undefined' == typeof o.server.auto_reconnect) {
      -          o.server.auto_reconnect = opts[name];
      -        }
      -        break;
      -      case 'ssl':
      -      case 'socketTimeoutMS':
      -      case 'connectTimeoutMS':
      -        if ('undefined' == typeof o.server.socketOptions[name]) {
      -          o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];
      -        }
      -        break;
      -      case 'authdb':
      -        if ('undefined' == typeof o.auth.authdb) {
      -          o.auth.authdb = opts[name];
      -        }
      -        break;
      -      case 'authSource':
      -        if ('undefined' == typeof o.auth.authSource) {
      -          o.auth.authSource = opts[name];
      -        }
      -        break;
      -      case 'retries':
      -      case 'reconnectWait':
      -      case 'rs_name':
      -        if ('undefined' == typeof o.replset[name]) {
      -          o.replset[name] = opts[name];
      -        }
      -        break;
      -      case 'replicaSet':
      -        if ('undefined' == typeof o.replset.rs_name) {
      -          o.replset.rs_name = opts[name];
      -        }
      -        break;
      -      case 'readSecondary':
      -        if ('undefined' == typeof o.replset.read_secondary) {
      -          o.replset.read_secondary = opts[name];
      -        }
      -        break;
      -      case 'nativeParser':
      -        if ('undefined' == typeof o.db.native_parser) {
      -          o.db.native_parser = opts[name];
      -        }
      -        break;
      -      case 'w':
      -      case 'safe':
      -      case 'fsync':
      -      case 'journal':
      -      case 'wtimeoutMS':
      -        if ('undefined' == typeof o.db[name]) {
      -          o.db[name] = opts[name];
      -        }
      -        break;
      -      case 'readPreference':
      -        if ('undefined' == typeof o.db.read_preference) {
      -          o.db.read_preference = opts[name];
      -        }
      -        break;
      -      case 'readPreferenceTags':
      -        if ('undefined' == typeof o.db.read_preference_tags) {
      -          o.db.read_preference_tags = opts[name];
      -        }
      -        break;
      -    }
      -  })
      -
      -  if (!('auto_reconnect' in o.server)) {
      -    o.server.auto_reconnect = true;
      -  }
      -
      -  if (!o.db.read_preference) {
      -    // read from primaries by default
      -    o.db.read_preference = 'primary';
      -  }
      -
      -  // mongoose creates its own ObjectIds
      -  o.db.forceServerObjectId = false;
      -
      -  // default safe using new nomenclature
      -  if (!('journal' in o.db || 'j' in o.db ||
      -        'fsync' in o.db || 'safe' in o.db || 'w' in o.db)) {
      -    o.db.w = 1;
      -  }
      -
      -  validate(o);
      -  return o;
      -}

      Parameters:

      • passed <Object> options that were passed directly during connection
      • [connStrOptions] <Object> options that were passed in the connection string

      NOTE: passed options take precedence over connection string options.


    • error.js

      MongooseError()

      Mongoose error

      show code
      function MongooseError (msg) {
      -  Error.call(this);
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.message = msg;
      -  this.name = 'MongooseError';
      -};

      Inherits:


    • errors/cast.js

      CastError(type, value)

      Casting Error constructor.

      show code
      function CastError (type, value, path) {
      -  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '" at path "' + path + '"');
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'CastError';
      -  this.type = type;
      -  this.value = value;
      -  this.path = path;
      -};

      Parameters:

      Inherits:


    • errors/document.js

      DocumentError(msg)

      Document Error

      show code
      function DocumentError (msg) {
      -  MongooseError.call(this, msg);
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'DocumentError';
      -};

      Parameters:

      Inherits:


    • errors/validation.js

      ValidationError(instance)

      Document Validation Error

      show code
      function ValidationError (instance) {
      -  MongooseError.call(this, "Validation failed");
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'ValidationError';
      -  this.errors = instance.errors = {};
      -};

      Parameters:

      Inherits:


      ValidationError#toString()

      Console.log helper

      show code
      ValidationError.prototype.toString = function () {
      -  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
      -    return String(this.errors[key]);
      -  }, this).join(', ');
      -};

    • errors/validator.js

      ValidatorError(path, msg)

      Schema validator error

      show code
      function ValidatorError (path, type) {
      -  var msg = type
      -    ? '"' + type + '" '
      -    : '';
      -  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'ValidatorError';
      -  this.path = path;
      -  this.type = type;
      -};

      Parameters:

      Inherits:


    • errors/version.js

      VersionError()

      Version Error constructor.

      show code
      function VersionError () {
      -  MongooseError.call(this, 'No matching document found.');
      -  Error.captureStackTrace(this, arguments.callee);
      -  this.name = 'VersionError';
      -};

      Inherits:


    • model.js

      Model(doc)

      Model constructor

      show code
      function Model (doc, fields, skipId) {
      -  Document.call(this, doc, fields, skipId);
      -};

      Parameters:

      • doc <Object> values to with which to create the document

      Inherits:

      Events:

      • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

      • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


      Model#_getPopulationKeys(query)

      Returns what paths can be populated

      show code
      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
      -  if (!(query && query.options.populate)) return;
      -
      -  var names = Object.keys(query.options.populate)
      -    , n = names.length
      -    , name
      -    , paths = {}
      -    , hasKeys
      -    , schema
      -
      -  while (n--) {
      -    name = names[n];
      -    schema = this.schema.path(name);
      -    hasKeys = true;
      -
      -    if (!schema) {
      -      // if the path is not recognized, it's potentially embedded docs
      -      // walk path atoms from right to left to find a matching path
      -      var pieces = name.split('.')
      -        , i = pieces.length;
      -
      -      while (i--) {
      -        var path = pieces.slice(0, i).join('.')
      -          , pathSchema = this.schema.path(path);
      -
      -        // loop until we find an array schema
      -        if (pathSchema && pathSchema.caster) {
      -          if (!paths[path]) {
      -            paths[path] = { sub: {} };
      -          }
      -
      -          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
      -          hasKeys || (hasKeys = true);
      -          break;
      -        }
      -      }
      -    } else {
      -      paths[name] = query.options.populate[name];
      -      hasKeys || (hasKeys = true);
      -    }
      -  }
      -
      -  return hasKeys && paths;
      -};

      Parameters:

      Returns:


      Model#_populate(schema, oid, query, fn)

      Populates an object

      show code
      Model.prototype._populate = function populate (schema, oid, query, fn) {
      -  if (!Array.isArray(oid)) {
      -    var conditions = query.conditions || {};
      -    conditions._id = oid;
      -
      -    return this
      -    .db.model(query.model || schema.options.ref)
      -    .findOne(conditions, query.fields, query.options, fn);
      -  }
      -
      -  if (!oid.length) {
      -    return fn(null, oid);
      -  }
      -
      -  var model = this.db.model(query.model || schema.caster.options.ref)
      -    , conditions = query && query.conditions || {};
      -
      -  conditions._id || (conditions._id = { $in: oid });
      -
      -  model.find(conditions, query.fields, query.options, function (err, docs) {
      -    if (err) return fn(err);
      -
      -    // user specified sort order?
      -    if (query.options && query.options.sort) {
      -      return fn(null, docs);
      -    }
      -
      -    // put back in original id order (using a hash reduces complexity from n*n to 2n)
      -    var docHash = {};
      -    docs.forEach(function (doc) {
      -      docHash[doc._id] = doc;
      -    });
      -
      -    var arr = [];
      -    oid.forEach(function (id) {
      -      if (id in docHash) arr.push(docHash[id]);
      -    });
      -
      -    fn(null, arr);
      -  });
      -};

      Parameters:

      • schema <SchemaType> type for the oid
      • oid <Object> object id or array of object ids
      • query <Object> object specifying query conditions, fields, and options
      • fn <Function>

      Model#init(doc, query, fn)

      Performs auto-population of relations.

      show code
      Model.prototype.init = function init (doc, query, fn) {
      -  if ('function' == typeof query) {
      -    fn = query;
      -    query = null;
      -  }
      -
      -  var populate = this._getPopulationKeys(query);
      -
      -  if (!populate) {
      -    return Document.prototype.init.call(this, doc, fn);
      -  }
      -
      -  // population from other models is necessary
      -  var self = this;
      -
      -  init(doc, '', function (err) {
      -    if (err) return fn(err);
      -    Document.prototype.init.call(self, doc, fn);
      -  });
      -
      -  return this;
      -
      -  function init (obj, prefix, fn) {
      -    prefix = prefix || '';
      -
      -    var keys = Object.keys(obj)
      -      , len = keys.length;
      -
      -    return next();
      -
      -    function next () {
      -      if (--len < 0) return fn();
      -
      -      var i = keys[len]
      -        , path = prefix + i
      -        , schema = self.schema.path(path)
      -        , total = 0
      -        , inline = false
      -        , poppath
      -
      -      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
      -        // assume nested object
      -        return init(obj[i], path + '.', next);
      -      }
      -
      -      if (!(obj[i] && schema && populate[path])) return next();
      -
      -      // this query object is re-used and passed around. we clone
      -      // it to prevent query condition contamination between
      -      // one populate call to the next.
      -      poppath = utils.clone(populate[path]);
      -
      -      if (poppath.sub) {
      -        obj[i].forEach(function (subobj) {
      -          inline = true;
      -
      -          var pkeys = Object.keys(poppath.sub)
      -            , pi = pkeys.length
      -            , key
      -
      -          while (pi--) {
      -            key = pkeys[pi];
      -
      -            if (subobj[key]) (function (key) {
      -              total++;
      -              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
      -              function done (err, doc) {
      -                if (err) return error(err);
      -                subobj[key] = doc;
      -                if (--total < 1 && !inline) {
      -                  next();
      -                }
      -              }
      -            })(key);
      -          }
      -        });
      -
      -        inline = false;
      -
      -        if (0 === total) return next();
      -
      -      } else {
      -        self._populate(schema, obj[i], poppath, function (err, doc) {
      -          if (err) return error(err);
      -          obj[i] = doc;
      -          next();
      -        });
      -      }
      -    };
      -  };
      -
      -  function error (err) {
      -    if (error.err) return;
      -    fn(error.err = err);
      -  }
      -};

      Parameters:

      • doc <Object> document returned by mongo
      • query <Query> query that originated the initialization
      • fn <Function>

      Model#save([fn])

      Saves this document.

      show code
      Model.prototype.save = function save (fn) {
      -  var promise = new Promise(fn)
      -    , complete = handleSave(promise, this)
      -    , options = {}
      -
      -  if (this.schema.options.safe) {
      -    options.safe = this.schema.options.safe;
      -  }
      -
      -  if (this.isNew) {
      -    // send entire doc
      -    var obj = this.toObject({ depopulate: 1 });
      -    this._version(true, obj);
      -    this.collection.insert(obj, options, complete);
      -    this._reset();
      -    this.isNew = false;
      -    this.emit('isNew', false);
      -    // Make it possible to retry the insert
      -    this._inserting = true;
      -
      -  } else {
      -    // Make sure we don't treat it as a new object on error,
      -    // since it already exists
      -    this._inserting = false;
      -
      -    var delta = this._delta();
      -    if (delta) {
      -      var where = this._where(delta[0]);
      -      this.collection.update(where, delta[1], options, complete);
      -    } else {
      -      process.nextTick(function () {
      -        complete(null);
      -      })
      -    }
      -
      -    this._reset();
      -    this.emit('isNew', false);
      -  }
      -};

      Parameters:

      Example:

      - -
      product.sold = Date.now();
      -product.save(function (err, product) {
      -  if (err) ..
      -})
      - -

      The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      - -
      var db = mongoose.createConnection(..);
      -var schema = new Schema(..);
      -var Product = db.model('Product', schema);
      -
      -db.on('error', handleError);
      - -

      However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

      - -
      Product.on('error', handleError);

      Model#_delta()

      Produces a special query document of the modified properties used in updates.

      show code
      Model.prototype._delta = function _delta () {
      -  var dirty = this._dirty();
      -  if (!dirty.length) return;
      -
      -  var self = this
      -    , where = {}
      -    , delta = {}
      -    , len = dirty.length
      -    , d = 0
      -    , val
      -    , obj
      -
      -  for (; d < len; ++d) {
      -    var data = dirty[d]
      -    var value = data.value
      -    var schema = data.schema
      -
      -    if (undefined === value) {
      -      operand(self, where, delta, data, 1, '$unset');
      -
      -    } else if (null === value) {
      -      operand(self, where, delta, data, null);
      -
      -    } else if (value._path && value._atomics) {
      -      // arrays and other custom types (support plugins etc)
      -      handleAtomics(self, where, delta, data, value);
      -
      -    } else if (value._path && Buffer.isBuffer(value)) {
      -      // MongooseBuffer
      -      value = value.toObject();
      -      operand(self, where, delta, data, value);
      -
      -    } else {
      -      value = utils.clone(value);
      -      operand(self, where, delta, data, value);
      -    }
      -  }
      -
      -  if (this.__version) {
      -    this._version(where, delta);
      -  }
      -
      -  return [where, delta];
      -}

      Model#_version()

      Appends versioning to the where and update clauses.

      show code
      Model.prototype._version = function _version (where, delta) {
      -  var key = this.schema.options.versionKey;
      -
      -  if (true === where) {
      -    // this is an insert
      -    if (key) this.setValue(key, delta[key] = 0);
      -    return;
      -  }
      -
      -  // updates
      -
      -  // only apply versioning if our versionKey was selected. else
      -  // there is no way to select the correct version. we could fail
      -  // fast here and force them to include the versionKey but
      -  // thats a bit intrusive. can we do this automatically?
      -  // TODO fail fast option?
      -  if (!this.isSelected(key)) {
      -    return;
      -  }
      -
      -  // $push $addToSet don't need the where clause set
      -  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
      -    where[key] = this.getValue(key);
      -  }
      -
      -  if (VERSION_INC === (VERSION_INC & this.__version)) {
      -    delta.$inc || (delta.$inc = {});
      -    delta.$inc[key] = 1;
      -  }
      -}

      Model#increment()

      Signal that we desire an increment of this documents version.

      show code
      Model.prototype.increment = function increment () {
      -  this.__version = VERSION_ALL;
      -  return this;
      -}

      Model#_where()

      Returns a query object which applies shardkeys if they exist.

      show code
      Model.prototype._where = function _where (where) {
      -  where || (where = {});
      -
      -  var paths
      -    , len
      -
      -  if (this._shardval) {
      -    paths = Object.keys(this._shardval)
      -    len = paths.length
      -
      -    for (var i = 0; i < len; ++i) {
      -      where[paths[i]] = this._shardval[paths[i]];
      -    }
      -  }
      -
      -  where._id = this._doc._id;
      -  return where;
      -}

      Model#remove([fn])

      Removes this document from the db.

      show code
      Model.prototype.remove = function remove (fn) {
      -  if (this._removing) {
      -    this._removing.addBack(fn);
      -    return this;
      -  }
      -
      -  var promise = this._removing = new Promise(fn)
      -    , where = this._where()
      -    , self = this
      -    , options = {}
      -
      -  if (this.schema.options.safe) {
      -    options.safe = this.schema.options.safe;
      -  }
      -
      -  this.collection.remove(where, options, tick(function (err) {
      -    if (err) {
      -      promise.error(err);
      -      promise = self = self._removing = where = options = null;
      -      return;
      -    }
      -    self.emit('remove', self);
      -    promise.complete();
      -    promise = self = where = options = null;
      -  }));
      -
      -  return this;
      -};

      Parameters:

      Example:

      - -
      product.remove(function (err, product) {
      -  if (err) return handleError(err);
      -  Product.findById(product._id, function (err, product) {
      -    console.log(product) // null
      -  })
      -})

      Model#_registerHooks()

      Register hooks override

      show code
      Model.prototype._registerHooks = function registerHooks () {
      -  Document.prototype._registerHooks.call(this);
      -};

      Model#model(name)

      Returns another Model instance.

      show code
      Model.prototype.model = function model (name) {
      -  return this.db.model(name);
      -};
      -
      -// Model (class) features

      Parameters:

      Example:

      - -
      var doc = new Tank;
      -doc.model('User').findById(id, callback);

      Model#$where(argument)

      Creates a Query and specifies a $where condition.

      Parameters:

      • argument <String, Function> is a javascript string or anonymous function

      Returns:

      Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      - -
      Blog.$where('this.comments.length &gt; 5').exec(function (err, docs) {});

      Model.init()

      Called when the model compiles.

      show code
      Model.init = function init () {
      -  if (this.schema.options.autoIndex) {
      -    this.ensureIndexes();
      -  }
      -
      -  this.schema.emit('init', this);
      -};

      Model.ensureIndexes([cb])

      Sends ensureIndex commands to mongo for each index declared in the schema.

      show code
      Model.ensureIndexes = function ensureIndexes (cb) {
      -  var indexes = this.schema.indexes();
      -  if (!indexes.length) {
      -    return cb && process.nextTick(cb);
      -  }
      -
      -  // Indexes are created one-by-one to support how MongoDB < 2.4 deals
      -  // with background indexes.
      -
      -  var self = this
      -    , safe = self.schema.options.safe
      -
      -  function done (err) {
      -    self.emit('index', err);
      -    cb && cb(err);
      -  }
      -
      -  function create () {
      -    var index = indexes.shift();
      -    if (!index) return done();
      -
      -    var options = index[1];
      -    options.safe = safe;
      -    self.collection.ensureIndex(index[0], options, tick(function (err) {
      -      if (err) return done(err);
      -      create();
      -    }));
      -  }
      -
      -  create();
      -}

      Parameters:

      Example:

      - -
      Event.ensureIndexes(function (err) {
      -  if (err) return handleError(err);
      -});
      - -

      After completion, an index event is emitted on this Model passing an error if one occurred.

      - -

      Example:

      - -
      var eventSchema = new Schema({ thing: { type: 'string', unique: true }})
      -var Event = mongoose.model('Event', eventSchema);
      -
      -Event.on('index', function (err) {
      -  if (err) console.error(err); // error occurred during index creation
      -})
      - -

      NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

      - -

      The ensureIndex commands are not sent in parallel. This is to avoid the MongoError: cannot add index with a background operation in progress error. See this ticket for more information.


      Model.remove(conditions, [callback])

      Removes documents from the collection.

      show code
      Model.remove = function remove (conditions, callback) {
      -  if ('function' === typeof conditions) {
      -    callback = conditions;
      -    conditions = {};
      -  }
      -
      -  var query = new Query(conditions).bind(this, 'remove');
      -
      -  if ('undefined' === typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.remove(callback);
      -};

      Parameters:

      Returns:

      Example:

      - -
      Comment.remove({ title: 'baby born from alien father' }, function (err) {
      -
      -});
      - -

      Note:

      - -

      To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      - -
      var query = Comment.remove({ _id: id });
      -query.exec();
      - -

      Note:

      - -

      This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, no middleware (hooks) are executed.


      Model.find(conditions, [fields], [options], [callback])

      Finds documents

      show code
      Model.find = function find (conditions, fields, options, callback) {
      -  if ('function' == typeof conditions) {
      -    callback = conditions;
      -    conditions = {};
      -    fields = null;
      -    options = null;
      -  } else if ('function' == typeof fields) {
      -    callback = fields;
      -    fields = null;
      -    options = null;
      -  } else if ('function' == typeof options) {
      -    callback = options;
      -    options = null;
      -  }
      -
      -  var query = new Query(conditions, options);
      -  query.bind(this, 'find');
      -  query.select(fields);
      -
      -  if ('undefined' === typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.find(callback);
      -};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      - -

      Examples:

      - -
      // named john and at least 18
      -MyModel.find({ name: 'john', age: { $gte: 18 }});
      -
      -// executes immediately, passing results to callback
      -MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});
      -
      -// name LIKE john and only selecting the "name" and "friends" fields, executing immediately
      -MyModel.find({ name: /john/i }, 'name friends', function (err, docs) { })
      -
      -// passing options
      -MyModel.find({ name: /john/i }, null, { skip: 10 })
      -
      -// passing options and executing immediately
      -MyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {});
      -
      -// executing a query explicitly
      -var query = MyModel.find({ name: /john/i }, null, { skip: 10 })
      -query.exec(function (err, docs) {});
      -
      -// using the promise returned from executing a query
      -var query = MyModel.find({ name: /john/i }, null, { skip: 10 });
      -var promise = query.exec();
      -promise.addBack(function (err, docs) {});

      Model._applyNamedScope(query)

      Merges the current named scope query into query.

      show code
      Model._applyNamedScope = function _applyNamedScope (query) {
      -  var cQuery = this._cumulativeQuery;
      -
      -  if (cQuery) {
      -    merge(query._conditions, cQuery._conditions);
      -    if (query._fields && cQuery._fields)
      -      merge(query._fields, cQuery._fields);
      -    if (query.options && cQuery.options)
      -      merge(query.options, cQuery.options);
      -    delete this._cumulativeQuery;
      -  }
      -
      -  return query;
      -}

      Parameters:

      Returns:


      Model.findById(id, [fields], [options], [callback])

      Finds a single document by id.

      show code
      Model.findById = function findById (id, fields, options, callback) {
      -  return this.findOne({ _id: id }, fields, options, callback);
      -};

      Parameters:

      Returns:

      The id is cast based on the Schema before sending the command.

      - -

      Example:

      - -
      // find adventure by id and execute immediately
      -Adventure.findById(id, function (err, adventure) {});
      -
      -// same as above
      -Adventure.findById(id).exec(callback);
      -
      -// select only the adventures name and length
      -Adventure.findById(id, 'name length', function (err, adventure) {});
      -
      -// same as above
      -Adventure.findById(id, 'name length').exec(callback);
      -
      -// include all properties except for `length`
      -Adventure.findById(id, '-length').exec(function (err, adventure) {});
      -
      -// passing options (in this case return the raw js objects, not mongoose documents by passing `lean`
      -Adventure.findById(id, 'name', { lean: true }, function (err, doc) {});
      -
      -// same as above
      -Adventure.findById(id, 'name').lean().exec(function (err, doc) {});

      Model.findOne(conditions, [fields], [options], [callback])

      Finds one document.

      show code
      Model.findOne = function findOne (conditions, fields, options, callback) {
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = null;
      -  } else if ('function' == typeof fields) {
      -    callback = fields;
      -    fields = null;
      -    options = null;
      -  } else if ('function' == typeof conditions) {
      -    callback = conditions;
      -    conditions = {};
      -    fields = null;
      -    options = null;
      -  }
      -
      -  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.findOne(callback);
      -};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      - -

      Example:

      - -
      // find one iphone adventures - iphone adventures??
      -Adventure.findOne({ type: 'iphone' }, function (err, adventure) {});
      -
      -// same as above
      -Adventure.findOne({ type: 'iphone' }).exec(function (err, adventure) {});
      -
      -// select only the adventures name
      -Adventure.findOne({ type: 'iphone' }, 'name', function (err, adventure) {});
      -
      -// same as above
      -Adventure.findOne({ type: 'iphone' }, 'name').exec(function (err, adventure) {});
      -
      -// specify options, in this case lean
      -Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }, callback);
      -
      -// same as above
      -Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }).exec(callback);
      -
      -// chaining findOne queries (same as above)
      -Adventure.findOne({ type: 'iphone' }).select('name').lean().exec(callback);

      Model.count(conditions, [callback])

      Counts number of matching documents in a database collection.

      show code
      Model.count = function count (conditions, callback) {
      -  if ('function' === typeof conditions)
      -    callback = conditions, conditions = {};
      -
      -  var query = new Query(conditions).bind(this, 'count');
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.count(callback);
      -};

      Parameters:

      Returns:

      Example:

      - -
      Adventure.count({ type: 'jungle' }, function (err, count) {
      -  if (err) ..
      -  console.log('there are %d jungle adventures', count);
      -});

      Model.distinct(field, [conditions], [callback])

      Executes a DISTINCT command

      show code
      Model.distinct = function distinct (field, conditions, callback) {
      -  var query = new Query(conditions).bind(this, 'distinct');
      -  if ('undefined' == typeof callback) {
      -    query._distinctArg = field;
      -    return query;
      -  }
      -
      -  this._applyNamedScope(query);
      -  return query.distinct(field, callback);
      -};

      Parameters:

      Returns:


      Model.where(path, [val])

      Creates a Query, applies the passed conditions, and returns the Query.

      show code
      Model.where = function where (path, val) {
      -  var q = new Query().bind(this, 'find');
      -  return q.where.apply(q, arguments);
      -};

      Parameters:

      Returns:

      For example, instead of writing:

      - -
      User.find({age: {$gte: 21, $lte: 65}}, callback);
      - -

      we can instead write:

      - -
      User.where('age').gte(21).lte(65).exec(callback);
      - -

      Since the Query class also supports where you can continue chaining

      - -
      User
      -.where('age').gte(21).lte(65)
      -.where('name', /^b/i)
      -... etc

      Model.findOneAndUpdate([conditions], [update], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Model.findOneAndUpdate = function (conditions, update, options, callback) {
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = null;
      -  }
      -  else if (1 === arguments.length) {
      -    if ('function' == typeof conditions) {
      -      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
      -
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate(update)
      -'
      -              + '  ' + this.modelName + '.findOneAndUpdate()
      -';
      -      throw new TypeError(msg)
      -    }
      -    update = conditions;
      -    conditions = undefined;
      -  }
      -
      -  var fields;
      -  if (options && options.fields) {
      -    fields = options.fields;
      -    options.fields = undefined;
      -  }
      -
      -  var query = new Query(conditions);
      -  query.setOptions(options);
      -  query.select(fields);
      -  query.bind(this, 'findOneAndUpdate', update);
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.findOneAndUpdate(callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findOneAndUpdate(conditions, update, options, callback) // executes
      -A.findOneAndUpdate(conditions, update, options)  // returns Query
      -A.findOneAndUpdate(conditions, update, callback) // executes
      -A.findOneAndUpdate(conditions, update)           // returns Query
      -A.findOneAndUpdate()                             // returns Query
      - -

      Note:

      - -

      All top level update keys which are not atomic operation names are treated as set operations:

      - -

      Example:

      - -
      var query = { name: 'borne' };
      -Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
      -
      -// is sent as
      -Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
      - -

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      - -

      Note:

      - -

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      - -
        -
      • defaults
      • -
      • setters
      • -
      • validators
      • -
      • middleware
      • -
      - -

      If you need those features, use the traditional approach of first retrieving the document.

      - -
      Model.findOne({ name: 'borne' }, function (err, doc) {
      -  if (err) ..
      -  doc.name = 'jason borne';
      -  doc.save(callback);
      -})

      Model.findByIdAndUpdate(id, [update], [options], [callback])

      Issues a mongodb findAndModify update command by a documents id.

      show code
      Model.findByIdAndUpdate = function (id, update, options, callback) {
      -  var args;
      -
      -  if (1 === arguments.length) {
      -    if ('function' == typeof id) {
      -      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
      -
      -'
      -                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      -'
      -                + '  ' + this.modelName + '.findByIdAndUpdate(id)
      -'
      -                + '  ' + this.modelName + '.findByIdAndUpdate()
      -';
      -      throw new TypeError(msg)
      -    }
      -    return this.findOneAndUpdate({_id: id }, undefined);
      -  }
      -
      -  args = utils.args(arguments, 1);
      -  args.unshift({ _id: id });
      -  return this.findOneAndUpdate.apply(this, args);
      -}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findByIdAndUpdate(id, update, options, callback) // executes
      -A.findByIdAndUpdate(id, update, options)  // returns Query
      -A.findByIdAndUpdate(id, update, callback) // executes
      -A.findByIdAndUpdate(id, update)           // returns Query
      -A.findByIdAndUpdate()                     // returns Query
      - -

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      - -

      Note:

      - -

      All top level update keys which are not atomic operation names are treated as set operations:

      - -

      Example:

      - -
      Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
      -
      -// is sent as
      -Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
      - -

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      - -

      Note:

      - -

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      - -
        -
      • defaults
      • -
      • setters
      • -
      • validators
      • -
      • middleware
      • -
      - -

      If you need those features, use the traditional approach of first retrieving the document.

      - -
      Model.findById(id, function (err, doc) {
      -  if (err) ..
      -  doc.name = 'jason borne';
      -  doc.save(callback);
      -})

      Model.findOneAndRemove(conditions, [options], [callback])

      Issue a mongodb findAndModify remove command.

      show code
      Model.findOneAndRemove = function (conditions, options, callback) {
      -  if (1 === arguments.length && 'function' == typeof conditions) {
      -    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
      -
      -'
      -              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      -'
      -              + '  ' + this.modelName + '.findOneAndRemove(conditions)
      -'
      -              + '  ' + this.modelName + '.findOneAndRemove()
      -';
      -    throw new TypeError(msg)
      -  }
      -
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = undefined;
      -  }
      -
      -  var fields;
      -  if (options) {
      -    fields = options.select;
      -    options.select = undefined;
      -  }
      -
      -  var query = new Query(conditions);
      -  query.setOptions(options);
      -  query.select(fields);
      -  query.bind(this, 'findOneAndRemove');
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.findOneAndRemove(callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      - -

      Executes immediately if callback is passed else a Query object is returned.

      - -

      Options:

      - -
        -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findOneAndRemove(conditions, options, callback) // executes
      -A.findOneAndRemove(conditions, options)  // return Query
      -A.findOneAndRemove(conditions, callback) // executes
      -A.findOneAndRemove(conditions) // returns Query
      -A.findOneAndRemove()           // returns Query

      Model.findByIdAndRemove(id, [options], [callback])

      Issue a mongodb findAndModify remove command by a documents id.

      show code
      Model.findByIdAndRemove = function (id, options, callback) {
      -  if (1 === arguments.length && 'function' == typeof id) {
      -    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
      -
      -'
      -              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      -'
      -              + '  ' + this.modelName + '.findByIdAndRemove(id)
      -'
      -              + '  ' + this.modelName + '.findByIdAndRemove()
      -';
      -    throw new TypeError(msg)
      -  }
      -
      -  return this.findOneAndRemove({ _id: id }, options, callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      - -

      Executes immediately if callback is passed, else a Query object is returned.

      - -

      Options:

      - -
        -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      • select: sets the document fields to return
      • -
      - -

      Examples:

      - -
      A.findByIdAndRemove(id, options, callback) // executes
      -A.findByIdAndRemove(id, options)  // return Query
      -A.findByIdAndRemove(id, callback) // executes
      -A.findByIdAndRemove(id) // returns Query
      -A.findByIdAndRemove()           // returns Query

      Model.create(doc, fn)

      Shortcut for creating a new Document that is automatically saved to the db if valid.

      show code
      Model.create = function create (doc, fn) {
      -  if (1 === arguments.length) {
      -    return 'function' === typeof doc && doc(null);
      -  }
      -
      -  var self = this
      -    , docs = [null]
      -    , promise
      -    , count
      -    , args
      -
      -  if (Array.isArray(doc)) {
      -    args = doc;
      -  } else {
      -    args = utils.args(arguments, 0, arguments.length - 1);
      -    fn = arguments[arguments.length - 1];
      -  }
      -
      -  if (0 === args.length) return fn(null);
      -
      -  promise = new Promise(fn);
      -  count = args.length;
      -
      -  args.forEach(function (arg, i) {
      -    var doc = new self(arg);
      -    docs[i+1] = doc;
      -    doc.save(function (err) {
      -      if (err) return promise.error(err);
      -      --count || fn.apply(null, docs);
      -    });
      -  });
      -
      -  // TODO
      -  // utilize collection.insertAll for batch processing?
      -};

      Parameters:

      Example:

      - -
      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
      -  if (err) // ...
      -});
      -
      -var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      -Candy.create(array, function (err, jellybean, snickers) {
      -  if (err) // ...
      -});

      Model.update(conditions, update, [options], [callback])

      Updates documents in the database without returning them.

      show code
      Model.update = function update (conditions, doc, options, callback) {
      -  if (arguments.length < 4) {
      -    if ('function' === typeof options) {
      -      // Scenario: update(conditions, doc, callback)
      -      callback = options;
      -      options = null;
      -    } else if ('function' === typeof doc) {
      -      // Scenario: update(doc, callback);
      -      callback = doc;
      -      doc = conditions;
      -      conditions = {};
      -      options = null;
      -    }
      -  }
      -
      -  var query = new Query(conditions, options).bind(this, 'update', doc);
      -
      -  if ('undefined' == typeof callback)
      -    return query;
      -
      -  this._applyNamedScope(query);
      -  return query.update(doc, callback);
      -};

      Parameters:

      Returns:

      Examples:

      - -
      MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
      -MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
      -  if (err) return handleError(err);
      -  console.log('The number of updated documents was %d', numberAffected);
      -  console.log('The raw response from Mongo was ', raw);
      -});
      - -

      Valid options:

      - -
        -
      • safe (boolean) safe mode (defaults to value set in schema (true))
      • -
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • -
      • multi (boolean) whether multiple documents should be updated (false)
      • -
      - -

      All update values are cast to their appropriate SchemaTypes before being sent.

      - -

      The callback function receives (err, numberAffected, rawResponse).

      - -
        -
      • err is the error if any occurred
      • -
      • numberAffected is the count of updated documents Mongo reported
      • -
      • rawResponse is the full response from Mongo
      • -
      - -

      Note:

      - -

      All top level keys which are not atomic operation names are treated as set operations:

      - -

      Example:

      - -
      var query = { name: 'borne' };
      -Model.update(query, { name: 'jason borne' }, options, callback)
      -
      -// is sent as
      -Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
      - -

      This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

      - -

      Note:

      - -

      To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      - -
      Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
      - -

      Note:

      - -

      Although values are casted to their appropriate types when using update, the following are not applied:

      - -
        -
      • defaults
      • -
      • setters
      • -
      • validators
      • -
      • middleware
      • -
      - -

      If you need those features, use the traditional approach of first retrieving the document.

      - -
      Model.findOne({ name: 'borne' }, function (err, doc) {
      -  if (err) ..
      -  doc.name = 'jason borne';
      -  doc.save(callback);
      -})

      Model.mapReduce(o, callback)

      Executes a mapReduce command.

      show code
      Model.mapReduce = function mapReduce (o, callback) {
      -  if ('function' != typeof callback) throw new Error('missing callback');
      -
      -  var self = this;
      -
      -  if (!Model.mapReduce.schema) {
      -    var opts = { noId: true, noVirtualId: true, strict: false }
      -    Model.mapReduce.schema = new Schema({}, opts);
      -  }
      -
      -  if (!o.out) o.out = { inline: 1 };
      -
      -  o.map = String(o.map);
      -  o.reduce = String(o.reduce);
      -
      -  if (o.query) {
      -    var q = new Query(o.query);
      -    q.cast(this);
      -    o.query = q._conditions;
      -    q = undefined;
      -  }
      -
      -  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
      -    if (err) return callback(err);
      -
      -    if (ret.findOne && ret.mapReduce) {
      -      // returned a collection, convert to Model
      -      var model = Model.compile(
      -          '_mapreduce_' + ret.collectionName
      -        , Model.mapReduce.schema
      -        , ret.collectionName
      -        , self.db
      -        , self.base);
      -
      -      model._mapreduce = true;
      -
      -      return callback(err, model, stats);
      -    }
      -
      -    callback(err, ret, stats);
      -  });
      -}

      Parameters:

      • o <Object> an object specifying map-reduce options
      • callback <Function>

      o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

      - -

      Example:

      - -
      var o = {};
      -o.map = function () { emit(this.name, 1) }
      -o.reduce = function (k, vals) { return vals.length }
      -User.mapReduce(o, function (err, results) {
      -  console.log(results)
      -})
      - -

      Other options:

      - -
        -
      • query {Object} query filter object.
      • -
      • limit {Number} max number of documents
      • -
      • keeptemp {Boolean, default:false} keep temporary data
      • -
      • finalize {Function} finalize function
      • -
      • scope {Object} scope variables exposed to map/reduce/finalize during execution
      • -
      • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
      • -
      • verbose {Boolean, default:false} provide statistics on job execution time.
      • -
      • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
      • -
      - -

      * out options:

      - -
        -
      • {inline:1} the results are returned in an array
      • -
      • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
      • -
      • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
      • -
      • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
      • -
      - -

      If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

      - -

      Example:

      - -
      var o = {};
      -o.map = function () { emit(this.name, 1) }
      -o.reduce = function (k, vals) { return vals.length }
      -o.out = { replace: 'createdCollectionNameForResults' }
      -o.verbose = true;
      -User.mapReduce(o, function (err, model, stats) {
      -  console.log('map reduce took %d ms', stats.processtime)
      -  model.find().where('value').gt(10).exec(function (err, docs) {
      -    console.log(docs);
      -  });
      -})

      Model.aggregate(array, [options], callback)

      Executes an aggregate command on this models collection.

      show code
      Model.aggregate = function aggregate () {
      -  return this.collection.aggregate.apply(this.collection, arguments);
      -}

      Parameters:

      Example:

      - -
      // find the max age of all users
      -Users.aggregate(
      -    { $group: { _id: null, maxAge: { $max: '$age' }}}
      -  , { $project: { _id: 0, maxAge: 1 }}
      -  , function (err, res) {
      -  if (err) return handleError(err);
      -  console.log(res); // [ { maxAge: 98 } ]
      -});
      - -

      NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

      - -

      NOTE: this requires running MongoDB >= 2.1


      Model#base

      Base Mongoose instance the model uses.


      Model#schema

      Schema the model uses.


      Model#modelName

      The name of the model


      Model#collection

      Collection the model uses.


      Model#db

      Connection the model uses.


    • namedscope.js

      NamedScope#decorate(target, getters)

      Decorate

      show code
      NamedScope.prototype.decorate = function (target, getters) {
      -  var name = this.name
      -    , block = this.block
      -    , query = this.query;
      -  if (block) {
      -    if (block.length === 0) {
      -      Object.defineProperty(target, name, {
      -        get: getters.block0(block)
      -      });
      -    } else {
      -      target[name] = getters.blockN(block);
      -    }
      -  } else {
      -    Object.defineProperty(target, name, {
      -      get: getters.basic(query)
      -    });
      -  }
      -};
      -
      -NamedScope.prototype.compile = function (model) {
      -  var allScopes = this.scopesByName
      -    , scope;
      -  for (var k in allScopes) {
      -    scope = allScopes[k];
      -    scope.decorate(model, {
      -      block0: function (block) {
      -        return function () {
      -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      -          block.call(cquery);
      -          return this;
      -        };
      -      },
      -      blockN: function (block) {
      -        return function () {
      -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      -          block.apply(cquery, arguments);
      -          return this;
      -        };
      -      },
      -      basic: function (query) {
      -        return function () {
      -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      -          cquery.find(query);
      -          return this;
      -        };
      -      }
      -    });
      -  }
      -};
      -
      -module.exports = NamedScope;

      Parameters:


    • promise.js

      Promise(back)

      Promise constructor.

      show code
      function Promise (back) {
      -  this.emitted = {};
      -  if ('function' == typeof back)
      -    this.addBack(back);
      -};

      Parameters:

      • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

      Events:

      • err: Emits when the promise resolves to an error.

      • complete: Emits when the promise resolves sucessfully.


      Promise#on(event, callback)

      Adds listener to the event.

      show code
      Promise.prototype.on = function (event, callback) {
      -  if (this.emitted[event])
      -    callback.apply(this, this.emitted[event]);
      -  else
      -    EventEmitter.prototype.on.call(this, event, callback);
      -
      -  return this;
      -};

      Parameters:

      Returns:

      If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


      Promise#emit()

      Keeps track of emitted events to run them on on.

      show code
      Promise.prototype.emit = function (event) {
      -  // ensures a promise can't be complete() or error() twice
      -  if (event == 'err' || event == 'complete'){
      -    if (this.emitted.err || this.emitted.complete) {
      -      return this;
      -    }
      -    this.emitted[event] = util.args(arguments, 1);
      -  }
      -
      -  return EventEmitter.prototype.emit.apply(this, arguments);
      -};

      Promise#complete()

      Shortcut for emitting the complete event.

      show code
      Promise.prototype.complete = function () {
      -  var args = util.args(arguments);
      -  return this.emit.apply(this, ['complete'].concat(args));
      -};

      Promise#error()

      Shortcut for emitting the err event.

      show code
      Promise.prototype.error = function (err) {
      -  if (!(err instanceof Error)) err = new Error(err);
      -  return this.emit('err', err);
      -};

      Returns:

      If err is not instanceof Error, it is cast to Error before rejecting.


      Promise#addCallback()

      Adds a listener to the complete (success) event.

      show code
      Promise.prototype.addCallback = function (fn) {
      -  return this.on('complete', fn);
      -};

      Returns:


      Promise#addErrback()

      Adds a listener to the err (rejected) event.

      show code
      Promise.prototype.addErrback = function (fn) {
      -  return this.on('err', fn);
      -};

      Returns:


      Promise#addBack(fn)

      Adds a single function as both a callback and errback.

      show code
      Promise.prototype.addBack = function (fn) {
      -  this.on('err', function(err){
      -    fn.call(this, err);
      -  });
      -
      -  this.on('complete', function(){
      -    var args = util.args(arguments);
      -    fn.apply(this, [null].concat(args));
      -  });
      -
      -  return this;
      -};

      Parameters:

      Returns:

      It will be executed with traditional node.js argument position:
      function (err, args...) {}


      Promise#resolve([err], [val])

      Resolves this promise to an error state if err is passed or success state when no err is passed.

      show code
      Promise.prototype.resolve = function (err, val) {
      -  if (err) return this.error(err);
      -  return this.complete(val);
      -};

      Parameters:

      • [err] <Error> error or null
      • [val] <Object> value to complete the promise with

      err will be cast to an Error if not already instanceof Error.


    • query.js

      Query(criteria, options)

      Query constructor used for building queries.

      show code
      function Query (criteria, options) {
      -  this.setOptions(options, true);
      -  this._conditions = {};
      -  this._updateArg = {};
      -  this._fields = undefined;
      -  if (criteria) this.find(criteria);
      -}

      Parameters:

      Example:

      - -
      var query = Model.find();
      -query.where('age').gte(21).exec(callback);

      Query#setOptions(options)

      Sets query options.

      show code
      Query.prototype.setOptions = function (options, overwrite) {
      -  // overwrite is internal use only
      -  if (overwrite) {
      -    options = this.options = options || {};
      -    this.safe = options.safe
      -
      -    // normalize population options
      -    var pop = this.options.populate;
      -    this.options.populate = {};
      -
      -    if (pop && Array.isArray(pop)) {
      -      for (var i = 0, l = pop.length; i < l; i++) {
      -        this.options.populate[pop[i]] = {};
      -      }
      -    }
      -
      -    return this;
      -  }
      -
      -  if (!(options && 'Object' == options.constructor.name))
      -    return this;
      -
      -  if ('safe' in options)
      -    this.safe = options.safe;
      -
      -  // set arbitrary options
      -  var methods = Object.keys(options)
      -    , i = methods.length
      -    , method
      -
      -  while (i--) {
      -    method = methods[i];
      -
      -    // use methods if exist (safer option manipulation)
      -    if ('function' == typeof this[method]) {
      -      var args = Array.isArray(options[method])
      -        ? options[method]
      -        : [options[method]];
      -      this[method].apply(this, args)
      -    } else {
      -      this.options[method] = options[method];
      -    }
      -  }
      -  return this;
      -}

      Parameters:

      Options:

      - - - -

      * denotes a query helper method is also available


      Query#bind(model, op, updateArg)

      Binds this query to a model.

      show code
      Query.prototype.bind = function bind (model, op, updateArg) {
      -  this.model = model;
      -  this.op = op;
      -
      -  if (model._mapreduce) this.options.lean = true;
      -
      -  if (op == 'update' || op == 'findOneAndUpdate') {
      -    merge(this._updateArg, updateArg || {});
      -  }
      -
      -  return this;
      -};

      Parameters:

      • model <Model> the model to which the query is bound
      • op <String> the operation to execute
      • updateArg <Object> used in update methods

      Returns:


      Query#exec([operation], [callback])

      Executes the query

      show code
      Query.prototype.exec = function exec (op, callback) {
      -  var promise = new Promise();
      -
      -  switch (typeof op) {
      -    case 'function':
      -      callback = op;
      -      op = null;
      -      break;
      -    case 'string':
      -      this.op = op;
      -      break;
      -  }
      -
      -  if (callback) promise.addBack(callback);
      -
      -  if (!this.op) {
      -    promise.complete();
      -    return promise;
      -  }
      -
      -  if ('update' == this.op) {
      -    this[this.op](this._updateArg, promise.resolve.bind(promise));
      -    return promise;
      -  }
      -
      -  if ('distinct' == this.op) {
      -    this.distinct(this._distinctArg, promise.resolve.bind(promise));
      -    return promise;
      -  }
      -
      -  this[this.op](promise.resolve.bind(promise));
      -  return promise;
      -};

      Parameters:

      Returns:

      Examples

      - -
      query.exec();
      -query.exec(callback);
      -query.exec('update');
      -query.exec('find', callback);

      Query#find([criteria], [callback])

      Finds documents.

      show code
      Query.prototype.find = function (criteria, callback) {
      -  this.op = 'find';
      -  if ('function' === typeof criteria) {
      -    callback = criteria;
      -    criteria = {};
      -  } else if (criteria instanceof Query) {
      -    // TODO Merge options, too
      -    merge(this._conditions, criteria._conditions);
      -  } else if (criteria instanceof Document) {
      -    merge(this._conditions, criteria.toObject());
      -  } else if (criteria && 'Object' === criteria.constructor.name) {
      -    merge(this._conditions, criteria);
      -  }
      -  if (!callback) return this;
      -  return this.execFind(callback);
      -};

      Parameters:

      Returns:

      When no callback is passed, the query is not executed.

      - -

      Example

      - -
      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

      Query#cast(model, [obj])

      Casts this query to the schema of model

      show code
      Query.prototype.cast = function (model, obj) {
      -  obj || (obj= this._conditions);
      -
      -  var schema = model.schema
      -    , paths = Object.keys(obj)
      -    , i = paths.length
      -    , any$conditionals
      -    , schematype
      -    , nested
      -    , path
      -    , type
      -    , val;
      -
      -  while (i--) {
      -    path = paths[i];
      -    val = obj[path];
      -
      -    if ('$or' === path || '$nor' === path || '$and' === path) {
      -      var k = val.length
      -        , orComponentQuery;
      -
      -      while (k--) {
      -        orComponentQuery = new Query(val[k]);
      -        orComponentQuery.cast(model);
      -        val[k] = orComponentQuery._conditions;
      -      }
      -
      -    } else if (path === '$where') {
      -      type = typeof val;
      -
      -      if ('string' !== type && 'function' !== type) {
      -        throw new Error("Must have a string or function for $where");
      -      }
      -
      -      if ('function' === type) {
      -        obj[path] = val.toString();
      -      }
      -
      -      continue;
      -
      -    } else {
      -
      -      if (!schema) {
      -        // no casting for Mixed types
      -        continue;
      -      }
      -
      -      schematype = schema.path(path);
      -
      -      if (!schematype) {
      -        // Handle potential embedded array queries
      -        var split = path.split('.')
      -          , j = split.length
      -          , pathFirstHalf
      -          , pathLastHalf
      -          , remainingConds
      -          , castingQuery;
      -
      -        // Find the part of the var path that is a path of the Schema
      -        while (j--) {
      -          pathFirstHalf = split.slice(0, j).join('.');
      -          schematype = schema.path(pathFirstHalf);
      -          if (schematype) break;
      -        }
      -
      -        // If a substring of the input path resolves to an actual real path...
      -        if (schematype) {
      -          // Apply the casting; similar code for $elemMatch in schema/array.js
      -          if (schematype.caster && schematype.caster.schema) {
      -            remainingConds = {};
      -            pathLastHalf = split.slice(j).join('.');
      -            remainingConds[pathLastHalf] = val;
      -            castingQuery = new Query(remainingConds);
      -            castingQuery.cast(schematype.caster);
      -            obj[path] = castingQuery._conditions[pathLastHalf];
      -          } else {
      -            obj[path] = val;
      -          }
      -          continue;
      -        }
      -
      -        if (utils.isObject(val)) {
      -          // handle geo schemas that use object notation
      -          // { loc: { long: Number, lat: Number }
      -
      -          var geo = val.$near ? '$near' :
      -                    val.$nearSphere ? '$nearSphere' :
      -                    val.$within ? '$within' : '';
      -
      -          if (!geo) {
      -            continue;
      -          }
      -
      -          var numbertype = new Types.Number('__QueryCasting__')
      -          var value = val[geo];
      -
      -          if (val.$maxDistance) {
      -            val.$maxDistance = numbertype.castForQuery(val.$maxDistance);
      -          }
      -
      -          if ('$within' == geo) {
      -            // find $center, $centerSphere, $box, $polygon
      -            var withinType = value.$center || value.$centerSphere || value.$box || value.$polygon;
      -            if (!withinType) {
      -              throw new Error('Bad $within paramater: ' + JSON.stringify(val));
      -            }
      -
      -            value = withinType;
      -          }
      -
      -          ;(function _cast (val) {
      -            if (Array.isArray(val)) {
      -              val.forEach(function (item, i) {
      -                if (Array.isArray(item) || utils.isObject(item)) {
      -                  return _cast(item);
      -                }
      -                val[i] = numbertype.castForQuery(item);
      -              });
      -            } else {
      -              var nearKeys= Object.keys(val);
      -              var nearLen = nearKeys.length;
      -              while (nearLen--) {
      -                var nkey = nearKeys[nearLen];
      -                var item = val[nkey];
      -                if (Array.isArray(item) || utils.isObject(item)) {
      -                  _cast(item);
      -                  val[nkey] = item;
      -                } else {
      -                  val[nkey] = numbertype.castForQuery(item);
      -                }
      -              }
      -            }
      -          })(value);
      -        }
      -
      -      } else if (val === null || val === undefined) {
      -        continue;
      -      } else if ('Object' === val.constructor.name) {
      -
      -        any$conditionals = Object.keys(val).some(function (k) {
      -          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
      -        });
      -
      -        if (!any$conditionals) {
      -          obj[path] = schematype.castForQuery(val);
      -        } else {
      -
      -          var ks = Object.keys(val)
      -            , k = ks.length
      -            , $cond;
      -
      -          while (k--) {
      -            $cond = ks[k];
      -            nested = val[$cond];
      -
      -            if ('$exists' === $cond) {
      -              if ('boolean' !== typeof nested) {
      -                throw new Error("$exists parameter must be Boolean");
      -              }
      -              continue;
      -            }
      -
      -            if ('$type' === $cond) {
      -              if ('number' !== typeof nested) {
      -                throw new Error("$type parameter must be Number");
      -              }
      -              continue;
      -            }
      -
      -            if ('$not' === $cond) {
      -              this.cast(model, nested);
      -            } else {
      -              val[$cond] = schematype.castForQuery($cond, nested);
      -            }
      -          }
      -        }
      -      } else {
      -        obj[path] = schematype.castForQuery(val);
      -      }
      -    }
      -  }
      -
      -  return obj;
      -};

      Parameters:

      Returns:

      Note

      - -

      If obj is present, it is cast instead of this query.


      Query#_optionsForExec(model)

      Returns default options.

      show code
      Query.prototype._optionsForExec = function (model) {
      -  var options = utils.clone(this.options, { retainKeyOrder: true });
      -  delete options.populate;
      -
      -  if (!('safe' in options))
      -    options.safe = model.schema.options.safe;
      -
      -  if (!('readPreference' in options) && model.schema.options.read)
      -    options.readPreference = model.schema.options.read;
      -
      -  return options;
      -};

      Parameters:


      Query#_applyPaths()

      Applies schematype selected options to this query.

      show code
      Query.prototype._applyPaths = function applyPaths () {
      -  // determine if query is selecting or excluding fields
      -
      -  var fields = this._fields
      -    , exclude
      -    , keys
      -    , ki
      -
      -  if (fields) {
      -    keys = Object.keys(fields);
      -    ki = keys.length;
      -
      -    while (ki--) {
      -      if ('+' == keys[ki][0]) continue;
      -      exclude = 0 === fields[keys[ki]];
      -      break;
      -    }
      -  }
      -
      -  // if selecting, apply default schematype select:true fields
      -  // if excluding, apply schematype select:false fields
      -
      -  var selected = []
      -    , excluded = []
      -    , seen = [];
      -
      -  analyzeSchema(this.model.schema);
      -
      -  switch (exclude) {
      -    case true:
      -      excluded.length && this.select('-' + excluded.join(' -'));
      -      break;
      -    case false:
      -      selected.length && this.select(selected.join(' '));
      -      break;
      -    case undefined:
      -      // user didn't specify fields, implies returning all fields.
      -      // only need to apply excluded fields
      -      excluded.length && this.select('-' + excluded.join(' -'));
      -      break;
      -  }
      -
      -  return seen = excluded = selected = keys = fields = null;
      -
      -  function analyzeSchema (schema, prefix) {
      -    prefix || (prefix = '');
      -
      -    // avoid recursion
      -    if (~seen.indexOf(schema)) return;
      -    seen.push(schema);
      -
      -    schema.eachPath(function (path, type) {
      -      if (prefix) path = prefix + '.' + path;
      -
      -      // array of subdocs?
      -      if (type.schema) {
      -        analyzeSchema(type.schema, path);
      -      }
      -
      -      analyzePath(path, type);
      -    });
      -  }
      -
      -  function analyzePath (path, type) {
      -    if ('boolean' != typeof type.selected) return;
      -
      -    if (fields && ('+' + path) in fields) {
      -      // forced inclusion
      -      delete fields['+' + path];
      -
      -      // if there are other fields being included, add this one
      -      // if no other included fields, leave this out (implied inclusion)
      -      if (false === exclude && keys.length > 1) {
      -        fields[path] = 1;
      -      }
      -
      -      return
      -    };
      -
      -    ;(type.selected ? selected : excluded).push(path);
      -  }
      -}

      Query#$where(js)

      Specifies a $where condition

      Parameters:

      Returns:

      Use $where when you need to select documents using a JavaScript expression.

      - -

      Example

      - -
      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
      -
      -query.$where(function () {
      -  return this.comments.length &gt; 10 || this.name.length &gt; 5;
      -})

      Query#where([path], [val])

      Specifies a path for use with chaining.

      show code
      Query.prototype.where = function (path, val) {
      -  if (!arguments.length) return this;
      -
      -  if ('string' != typeof path) {
      -    throw new TypeError('path must be a string');
      -  }
      -
      -  this._currPath = path;
      -
      -  if (2 === arguments.length) {
      -    this._conditions[path] = val;
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      // instead of writing:
      -User.find({age: {$gte: 21, $lte: 65}}, callback);
      -
      -// we can instead write:
      -User.where('age').gte(21).lte(65);
      -
      -// Moreover, you can also chain a bunch of these together:
      -
      -User
      -.where('age').gte(21).lte(65)
      -.where('name', /^b/i)
      -.where('friends').slice(10)
      -.exec(callback)

      Query#equals(val)

      Specifies the complementary comparison value for paths specified with where()

      show code
      Query.prototype.equals = function equals (val) {
      -  var path = this._currPath;
      -  if (!path) throw new Error('equals() must be used after where()');
      -  this._conditions[path] = val;
      -  return this;
      -}

      Parameters:

      Returns:

      Example

      - -
      User.where('age').equals(49);
      -
      -// is the same as
      -
      -User.where('age', 49);

      Query#or(array)

      Specifies arguments for an $or condition.

      show code
      Query.prototype.or = function or (array) {
      -  var or = this._conditions.$or || (this._conditions.$or = []);
      -  if (!Array.isArray(array)) array = [array];
      -  or.push.apply(or, array);
      -  return this;
      -}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      - -
      query.or([{ color: 'red' }, { status: 'emergency' }])

      Query#nor(array)

      Specifies arguments for a $nor condition.

      show code
      Query.prototype.nor = function nor (array) {
      -  var nor = this._conditions.$nor || (this._conditions.$nor = []);
      -  if (!Array.isArray(array)) array = [array];
      -  nor.push.apply(nor, array);
      -  return this;
      -}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      - -
      query.nor([{ color: 'green' }, { status: 'ok' }])

      Query#and(array)

      Specifies arguments for a $and condition.

      show code
      Query.prototype.and = function and (array) {
      -  var and = this._conditions.$and || (this._conditions.$and = []);
      -  if (!Array.isArray(array)) array = [array];
      -  and.push.apply(and, array);
      -  return this;
      -}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      - -
      query.and([{ color: 'green' }, { status: 'ok' }])

      Query#gt(path, val)

      Specifies a $gt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.

      - -

      Example

      - -
      Thing.find().where('age').gt(21)
      -
      -// or
      -Thing.find().gt('age', 21)

      Query#gte(path, val)

      Specifies a $gte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lt(path, val)

      Specifies a $lt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lte(path, val)

      Specifies a $lte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#ne(path, val)

      Specifies a $ne query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#in(path, val)

      Specifies an $in query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#nin(path, val)

      Specifies an $nin query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#all(path, val)

      Specifies an $all query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#size(path, val)

      Specifies an $size query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#regex(path, val)

      Specifies a $regex query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#maxDistance(path, val)

      Specifies a $maxDistance query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#near(path, val)

      Specifies a $near condition

      show code
      Query.prototype.near = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath
      -  } else if (arguments.length === 2 && !Array.isArray(val)) {
      -    val = utils.args(arguments);
      -    path = this._currPath;
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds.$near = val;
      -  return this;
      -}

      Parameters:

      Returns:


      Query#nearSphere(path, val)

      Specifies a $nearSphere condition.

      show code
      Query.prototype.nearSphere = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath
      -  } else if (arguments.length === 2 && !Array.isArray(val)) {
      -    val = utils.args(arguments);
      -    path = this._currPath;
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds.$nearSphere = val;
      -  return this;
      -}

      Parameters:

      Returns:


      Query#mod(path, val)

      Specifies a $mod condition

      show code
      Query.prototype.mod = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath
      -  } else if (arguments.length === 2 && !Array.isArray(val)) {
      -    val = utils.args(arguments);
      -    path = this._currPath;
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds.$mod = val;
      -  return this;
      -}

      Parameters:

      Returns:


      Query#exists(path, val)

      Specifies an $exists condition

      show code
      Query.prototype.exists = function (path, val) {
      -  if (arguments.length === 0) {
      -    path = this._currPath
      -    val = true;
      -  } else if (arguments.length === 1) {
      -    if ('boolean' === typeof path) {
      -      val = path;
      -      path = this._currPath;
      -    } else {
      -      val = true;
      -    }
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$exists'] = val;
      -  return this;
      -};

      Parameters:

      Returns:


      Query#elemMatch(path, criteria)

      Specifies an $elemMatch condition

      show code
      Query.prototype.elemMatch = function (path, criteria) {
      -  var block;
      -  if ('Object' === path.constructor.name) {
      -    criteria = path;
      -    path = this._currPath;
      -  } else if ('function' === typeof path) {
      -    block = path;
      -    path = this._currPath;
      -  } else if ('Object' === criteria.constructor.name) {
      -  } else if ('function' === typeof criteria) {
      -    block = criteria;
      -  } else {
      -    throw new Error("Argument error");
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  if (block) {
      -    criteria = new Query();
      -    block(criteria);
      -    conds['$elemMatch'] = criteria._conditions;
      -  } else {
      -    conds['$elemMatch'] = criteria;
      -  }
      -  return this;
      -};
      -
      -// Spatial queries

      Parameters:

      Returns:

      Example

      - -
      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
      -
      -query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
      -
      -query.elemMatch('comment', function (elem) {
      -  elem.where('author').equals('autobot');
      -  elem.where('votes').gte(5);
      -})
      -
      -query.where('comment').elemMatch(function (elem) {
      -  elem.where('author').equals('autobot');
      -  elem.where('votes').gte(5);
      -})

      Query#box(path, val)

      Specifies a $box condition

      show code
      Query.prototype.box = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$box': [val.ll, val.ur]  };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var lowerLeft = [40.73083, -73.99756]
      -var upperRight= [40.741404,  -73.988135]
      -query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

      Query#center(path, val, [opts])

      Specifies a $center condition

      show code
      Query.prototype.center = function (path, val, opts) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$center': [val.center, val.radius]  };
      -
      -  // copy any options
      -  if (opts && 'Object' == opts.constructor.name) {
      -    utils.options(opts, conds.$within);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var area = { center: [50, 50], radius: 10 }
      -query.where('loc').within.center(area)

      Query#centerSphere(path, val)

      Specifies a $centerSphere condition

      show code
      Query.prototype.centerSphere = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var area = { center: [50, 50], radius: 10 }
      -query.where('loc').within.centerSphere(area)

      Query#polygon(path, val)

      Specifies a $polygon condition

      show code
      Query.prototype.polygon = function (path, val) {
      -  if (arguments.length === 1) {
      -    val = path;
      -    path = this._currPath;
      -  }
      -  var conds = this._conditions[path] || (this._conditions[path] = {});
      -  conds['$within'] = { '$polygon': val };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      -query.where('loc').within.polygon(polyA)
      -
      -// or
      -var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      -query.where('loc').within.polygon(polyB)

      Query#select(arg)

      Specifies which document fields to include or exclude

      show code
      Query.prototype.select = function select (arg) {
      -  if (!arg) return this;
      -
      -  var fields = this._fields || (this._fields = {});
      -
      -  if ('Object' === arg.constructor.name) {
      -    Object.keys(arg).forEach(function (field) {
      -      fields[field] = arg[field];
      -    });
      -  } else if (1 === arguments.length && 'string' == typeof arg) {
      -    arg.split(/\s+/).forEach(function (field) {
      -      if (!field) return;
      -      var include = '-' == field[0] ? 0 : 1;
      -      if (include === 0) field = field.substring(1);
      -      fields[field] = include;
      -    });
      -  } else {
      -    throw new TypeError('Invalid select() argument. Must be a string or object.');
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

      - -

      Example

      - -
      // include a and b, exclude c
      -query.select('a b -c');
      -
      -// or you may use object notation, useful when
      -// you have keys already prefixed with a "-"
      -query.select({a: 1, b: 1, c: 0});
      -
      -// force inclusion of field excluded at schema level
      -query.select('+path')
      - -

      NOTE:

      - -

      v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


      Query#slice(path, val)

      Specifies a $slice condition

      show code
      Query.prototype.slice = function (path, val) {
      -  if (arguments.length === 1) {
      -      val = path;
      -      path = this._currPath
      -  } else if (arguments.length === 2) {
      -    if ('number' === typeof path) {
      -      val = [path, val];
      -      path = this._currPath;
      -    }
      -  } else if (arguments.length === 3) {
      -    val = utils.args(arguments, 1);
      -  }
      -  var myFields = this._fields || (this._fields = {});
      -  myFields[path] = { '$slice': val };
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      query.slice('comments', 5)
      -query.slice('comments', -5)
      -query.slice('comments', [10, 5])
      -query.where('comments').slice(5)
      -query.where('comments').slice([-10, 5])

      Query#sort(arg)

      Sets the sort order

      show code
      Query.prototype.sort = function (arg) {
      -  if (!arg) return this;
      -
      -  var sort = this.options.sort || (this.options.sort = []);
      -
      -  if ('Object' === arg.constructor.name) {
      -    Object.keys(arg).forEach(function (field) {
      -      push(sort, field, arg[field]);
      -    });
      -  } else if (1 === arguments.length && 'string' == typeof arg) {
      -    arg.split(/\s+/).forEach(function (field) {
      -      if (!field) return;
      -      var ascend = '-' == field[0] ? -1 : 1;
      -      if (ascend === -1) field = field.substring(1);
      -      push(sort, field, ascend);
      -    });
      -  } else {
      -    throw new TypeError('Invalid sort() argument. Must be a string or object.');
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

      - -

      If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

      - -

      Example

      - -
      // these are equivalent
      -query.sort({ field: 'asc', test: -1 });
      -query.sort('field -test');

      Query#limit(val)

      Specifies the limit option.

      Parameters:

      Example

      - -
      Kitten.find().limit(20)

      Query#skip(val)

      Specifies the skip option.

      Parameters:

      Example

      - -
      Kitten.find().skip(100).limit(20)

      Query#maxscan(val)

      Specifies the maxscan option.

      Parameters:

      Example

      - -
      Kitten.find().maxscan(100)

      Query#batchSize(val)

      Specifies the batchSize option.

      Parameters:

      Example

      - -
      Kitten.find().batchSize(100)

      Query#comment(val)

      Specifies the comment option.

      Parameters:

      Example

      - -
      Kitten.findOne(condition).comment('login query')

      Query#snapshot()

      Specifies this query as a snapshot query.

      show code
      Query.prototype.snapshot = function () {
      -  this.options.snapshot = true;
      -  return this;
      -};

      Returns:

      Example

      - -
      Kitten.find().snapshot()

      Query#hint(val)

      Sets query hints.

      show code
      Query.prototype.hint = function (val) {
      -  if (!val) return this;
      -
      -  var hint = this.options.hint || (this.options.hint = {});
      -
      -  if ('Object' === val.constructor.name) {
      -    // must keep object keys in order so don't use Object.keys()
      -    for (var k in val) {
      -      hint[k] = val[k];
      -    }
      -  } else {
      -    throw new TypeError('Invalid hint. ' + val);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      Model.find().hint({ indexA: 1, indexB: -1})

      Query#slaveOk(v)

      Sets the slaveOk option.

      show code
      Query.prototype.slaveOk = function (v) {
      -  this.options.slaveOk = arguments.length ? !!v : true;
      -  return this;
      -}

      Parameters:

      Returns:

      Example:

      - -
      new Query().slaveOk() // true
      -new Query().slaveOk(true)
      -new Query().slaveOk(false)

      Query#read(pref, [tags])

      Sets the readPreference option for the query.

      show code
      Query.prototype.read = function (pref, tags) {
      -  this.options.readPreference = utils.readPref(pref, tags);
      -  return this;
      -}

      Parameters:

      • pref <String> one of the listed preference options or their aliases
      • [tags] <Array> optional tags for this query

      Returns:

      Example:

      - -
      new Query().read('primary')
      -new Query().read('p')  // same as primary
      -
      -new Query().read('primaryPreferred')
      -new Query().read('pp') // same as primaryPreferred
      -
      -new Query().read('secondary')
      -new Query().read('s')  // same as secondary
      -
      -new Query().read('secondaryPreferred')
      -new Query().read('sp') // same as secondaryPreferred
      -
      -new Query().read('nearest')
      -new Query().read('n')  // same as nearest
      -
      -// with tags
      -new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
      - -

      Preferences:

      - -
      primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
      -secondary            Read from secondary if available, otherwise error.
      -primaryPreferred     Read from primary if available, otherwise a secondary.
      -secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
      -nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
      - -

      Aliases

      - -
      p   primary
      -pp  primaryPreferred
      -s   secondary
      -sp  secondaryPreferred
      -n   nearest
      - -

      Read more about how to use read preferrences here and here.


      Query#lean(v)

      Sets the lean option.

      show code
      Query.prototype.lean = function (v) {
      -  this.options.lean = arguments.length ? !!v : true;
      -  return this;
      -}

      Parameters:

      Returns:

      Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

      - -

      This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

      - -

      Example:

      - -
      new Query().lean() // true
      -new Query().lean(true)
      -new Query().lean(false)
      -
      -Model.find().lean().exec();
      -
      -var leanStream = Model.find().lean().stream();

      Query#tailable(v)

      Sets tailable option.

      show code
      Query.prototype.tailable = function (v) {
      -  this.options.tailable = arguments.length ? !!v : true;
      -  return this;
      -};

      Parameters:

      Example

      - -
      Kitten.find().tailable() &lt;== true
      -Kitten.find().tailable(true)
      -Kitten.find().tailable(false)

      Query#execFind(callback)

      Executes the query as a find() operation.

      show code
      Query.prototype.execFind = function (callback) {
      -  var model = this.model
      -    , promise = new Promise(callback);
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    promise.error(err);
      -    return this;
      -  }
      -
      -  // apply default schematype path selections
      -  this._applyPaths();
      -
      -  var self = this
      -    , castQuery = this._conditions
      -    , options = this._optionsForExec(model)
      -    , fields = utils.clone(this._fields)
      -
      -  options.fields = this._castFields(fields);
      -  if (options.fields instanceof Error) {
      -    promise.error(options.fields);
      -    return this;
      -  }
      -
      -  model.collection.find(castQuery, options, function (err, cursor) {
      -    if (err) return promise.error(err);
      -    cursor.toArray(tick(cb));
      -  });
      -
      -  function cb (err, docs) {
      -    if (err) return promise.error(err);
      -
      -    if (true === options.lean)
      -      return promise.complete(docs);
      -
      -    var arr = []
      -      , count = docs.length;
      -
      -    if (!count) return promise.complete([]);
      -
      -    for (var i = 0, l = docs.length; i < l; i++) {
      -      arr[i] = new model(undefined, fields, true);
      -      arr[i].init(docs[i], self, function (err) {
      -        if (err) return promise.error(err);
      -        --count || promise.complete(arr);
      -      });
      -    }
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Query#findOne(callback)

      Executes the query as a findOne() operation.

      show code
      Query.prototype.findOne = function (callback) {
      -  this.op = 'findOne';
      -
      -  if (!callback) return this;
      -
      -  var model = this.model;
      -  var promise = new Promise(callback);
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    promise.error(err);
      -    return this;
      -  }
      -
      -  // apply default schematype path selections
      -  this._applyPaths();
      -
      -  var self = this
      -    , castQuery = this._conditions
      -    , options = this._optionsForExec(model)
      -    , fields = utils.clone(this._fields)
      -
      -  options.fields = this._castFields(fields);
      -  if (options.fields instanceof Error) {
      -    promise.error(options.fields);
      -    return this;
      -  }
      -
      -  model.collection.findOne(castQuery, options, tick(function (err, doc) {
      -    if (err) return promise.error(err);
      -    if (!doc) return promise.complete(null);
      -
      -    if (true === options.lean) return promise.complete(doc);
      -
      -    var casted = new model(undefined, fields, true);
      -    casted.init(doc, self, function (err) {
      -      if (err) return promise.error(err);
      -      promise.complete(casted);
      -    });
      -  }));
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      Kitten.where('color', 'white').findOne(function (err, kitten) {
      -  if (err) return handleError(err);
      -
      -  // kitten may be null if no document matched
      -  if (kitten) {
      -    ...
      -  }
      -})

      Query#count(callback)

      Exectues the query as a count() operation.

      show code
      Query.prototype.count = function (callback) {
      -  this.op = 'count';
      -  var model = this.model;
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    return callback(err);
      -  }
      -
      -  var castQuery = this._conditions;
      -  model.collection.count(castQuery, tick(callback));
      -
      -  return this;
      -};

      Parameters:

      Returns:

      Example

      - -
      Kitten.where('color', 'black').count(function (err, count) {
      -  if (err) return handleError(err);
      -  console.log('there are %d black kittens', count);
      -})

      Query#distinct(field, callback)

      Executes this query as a distict() operation.

      show code
      Query.prototype.distinct = function (field, callback) {
      -  this.op = 'distinct';
      -  var model = this.model;
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    return callback(err);
      -  }
      -
      -  var castQuery = this._conditions;
      -  model.collection.distinct(field, castQuery, tick(callback));
      -
      -  return this;
      -};

      Parameters:

      Returns:


      Query#update(doc, callback)

      Executes this query as an update() operation.

      show code
      Query.prototype.update = function update (doc, callback) {
      -  this.op = 'update';
      -  this._updateArg = doc;
      -
      -  var model = this.model
      -    , options = this._optionsForExec(model)
      -    , fn = 'function' == typeof callback
      -    , castedQuery
      -    , castedDoc
      -
      -  castedQuery = castQuery(this);
      -  if (castedQuery instanceof Error) {
      -    if (fn) {
      -      process.nextTick(callback.bind(null, castedQuery));
      -      return this;
      -    }
      -    throw castedQuery;
      -  }
      -
      -  castedDoc = castDoc(this);
      -  if (!castedDoc) {
      -    fn && process.nextTick(callback.bind(null, null, 0));
      -    return this;
      -  }
      -
      -  if (castedDoc instanceof Error) {
      -    if (fn) {
      -      process.nextTick(callback.bind(null, castedDoc));
      -      return this;
      -    }
      -    throw castedDoc;
      -  }
      -
      -  if (!fn) {
      -    options.safe = { w: 0 };
      -  }
      -
      -  model.collection.update(castedQuery, castedDoc, options, tick(callback));
      -  return this;
      -};

      Parameters:

      Returns:

      All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

      - -

      Example

      - -
      Model.update({..}, { title: 'remove words' }, ...)
      - -

      becomes

      - -
      Model.update({..}, { $set: { title: 'remove words' }}, ...)
      - -

      Note

      - -

      Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


      Query#_castUpdate(obj)

      Casts obj for an update command.

      show code
      Query.prototype._castUpdate = function _castUpdate (obj) {
      -  var ops = Object.keys(obj)
      -    , i = ops.length
      -    , ret = {}
      -    , hasKeys
      -    , val
      -
      -  while (i--) {
      -    var op = ops[i];
      -    if ('$' !== op[0]) {
      -      // fix up $set sugar
      -      if (!ret.$set) {
      -        if (obj.$set) {
      -          ret.$set = obj.$set;
      -        } else {
      -          ret.$set = {};
      -        }
      -      }
      -      ret.$set[op] = obj[op];
      -      ops.splice(i, 1);
      -      if (!~ops.indexOf('$set')) ops.push('$set');
      -    } else if ('$set' === op) {
      -      if (!ret.$set) {
      -        ret[op] = obj[op];
      -      }
      -    } else {
      -      ret[op] = obj[op];
      -    }
      -  }
      -
      -  // cast each value
      -  i = ops.length;
      -
      -  while (i--) {
      -    op = ops[i];
      -    val = ret[op];
      -    if ('Object' === val.constructor.name) {
      -      hasKeys |= this._walkUpdatePath(val, op);
      -    } else {
      -      var msg = 'Invalid atomic update value for ' + op + '. '
      -              + 'Expected an object, received ' + typeof val;
      -      throw new Error(msg);
      -    }
      -  }
      -
      -  return hasKeys && ret;
      -}

      Parameters:

      Returns:

      • <Object> obj after casting its values

      Query#_walkUpdatePath(obj, op, pref)

      Walk each path of obj and cast its values
      according to its schema.

      show code
      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
      -  var strict = this.model.schema.options.strict
      -    , prefix = pref ? pref + '.' : ''
      -    , keys = Object.keys(obj)
      -    , i = keys.length
      -    , hasKeys = false
      -    , schema
      -    , key
      -    , val
      -
      -  while (i--) {
      -    key = keys[i];
      -    val = obj[key];
      -
      -    if (val && 'Object' === val.constructor.name) {
      -      // watch for embedded doc schemas
      -      schema = this._getSchema(prefix + key);
      -      if (schema && schema.caster && op in castOps) {
      -        // embedded doc schema
      -
      -        if (strict && !schema) {
      -          // path is not in our strict schema
      -          if ('throw' == strict) {
      -            throw new Error('Field `' + key + '` is not in schema.');
      -          } else {
      -            // ignore paths not specified in schema
      -            delete obj[key];
      -          }
      -        } else {
      -          hasKeys = true;
      -          if ('$each' in val) {
      -            obj[key] = {
      -                $each: this._castUpdateVal(schema, val.$each, op)
      -            }
      -          } else {
      -            obj[key] = this._castUpdateVal(schema, val, op);
      -          }
      -        }
      -      } else {
      -        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
      -      }
      -    } else {
      -      schema = '$each' === key
      -        ? this._getSchema(pref)
      -        : this._getSchema(prefix + key);
      -
      -      var skip = strict &&
      -                 !schema &&
      -                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
      -
      -      if (skip) {
      -        if ('throw' == strict) {
      -          throw new Error('Field `' + prefix + key + '` is not in schema.');
      -        } else {
      -          delete obj[key];
      -        }
      -      } else {
      -        hasKeys = true;
      -        obj[key] = this._castUpdateVal(schema, val, op, key);
      -      }
      -    }
      -  }
      -  return hasKeys;
      -}

      Parameters:

      • obj <Object> - part of a query
      • op <String> - the atomic operator ($pull, $set, etc)
      • pref <String> - path prefix (internal only)

      Returns:

      • <Bool> true if this path has keys to update

      Query#_castUpdateVal(schema, val, op, [$conditional])

      Casts val according to schema and atomic op.

      show code
      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
      -  if (!schema) {
      -    // non-existing schema path
      -    return op in numberOps
      -      ? Number(val)
      -      : val
      -  }
      -
      -  if (schema.caster && op in castOps &&
      -    ('Object' === val.constructor.name || Array.isArray(val))) {
      -    // Cast values for ops that add data to MongoDB.
      -    // Ensures embedded documents get ObjectIds etc.
      -    var tmp = schema.cast(val);
      -
      -    if (Array.isArray(val)) {
      -      val = tmp;
      -    } else {
      -      val = tmp[0];
      -    }
      -  }
      -
      -  if (op in numberOps) return Number(val);
      -  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
      -  return schema.castForQuery(val)
      -}

      Parameters:


      Query#_getSchema(path)

      Finds the schema for path. This is different than
      calling schema.path as it also resolves paths with
      positional selectors (something.$.another.$.path).

      show code
      Query.prototype._getSchema = function _getSchema (path) {
      -  var schema = this.model.schema
      -    , pathschema = schema.path(path);
      -
      -  if (pathschema)
      -    return pathschema;
      -
      -  // look for arrays
      -  return (function search (parts, schema) {
      -    var p = parts.length + 1
      -      , foundschema
      -      , trypath
      -
      -    while (p--) {
      -      trypath = parts.slice(0, p).join('.');
      -      foundschema = schema.path(trypath);
      -      if (foundschema) {
      -        if (foundschema.caster) {
      -
      -          // array of Mixed?
      -          if (foundschema.caster instanceof Types.Mixed) {
      -            return foundschema.caster;
      -          }
      -
      -          // Now that we found the array, we need to check if there
      -          // are remaining document paths to look up for casting.
      -          // Also we need to handle array.$.path since schema.path
      -          // doesn't work for that.
      -          if (p !== parts.length) {
      -            if ('$' === parts[p]) {
      -              // comments.$.comments.$.title
      -              return search(parts.slice(p+1), foundschema.schema);
      -            } else {
      -              // this is the last path of the selector
      -              return search(parts.slice(p), foundschema.schema);
      -            }
      -          }
      -        }
      -        return foundschema;
      -      }
      -    }
      -  })(path.split('.'), schema)
      -}

      Parameters:


      Query#_castFields(fields)

      Casts selected field arguments for field selection with mongo 2.2

      show code
      Query.prototype._castFields = function _castFields (fields) {
      -  var selected
      -    , elemMatchKeys
      -    , keys
      -    , key
      -    , out
      -    , i
      -
      -  if (fields) {
      -    keys = Object.keys(fields);
      -    elemMatchKeys = [];
      -    i = keys.length;
      -
      -    // collect $elemMatch args
      -    while (i--) {
      -      key = keys[i];
      -      if (fields[key].$elemMatch) {
      -        selected || (selected = {});
      -        selected[key] = fields[key];
      -        elemMatchKeys.push(key);
      -      }
      -    }
      -  }
      -
      -  if (selected) {
      -    // they passed $elemMatch, cast em
      -    try {
      -      out = this.cast(this.model, selected);
      -    } catch (err) {
      -      return err;
      -    }
      -
      -    // apply the casted field args
      -    i = elemMatchKeys.length;
      -    while (i--) {
      -      key = elemMatchKeys[i];
      -      fields[key] = out[key];
      -    }
      -  }
      -
      -  return fields;
      -}

      Parameters:

      query.select({ ids: { $elemMatch: { $in: [hexString] }})

      Query#remove(callback)

      Executes this query as a remove() operation.

      show code
      Query.prototype.remove = function (callback) {
      -  this.op = 'remove';
      -
      -  var model = this.model
      -    , options = this._optionsForExec(model)
      -    , cb = 'function' == typeof callback
      -
      -  try {
      -    this.cast(model);
      -  } catch (err) {
      -    if (cb) return callback(err);
      -    throw err;
      -  }
      -
      -  if (!cb) {
      -    options.safe = { w: 0 };
      -  }
      -
      -  var castQuery = this._conditions;
      -  model.collection.remove(castQuery, options, tick(callback));
      -  return this;
      -};

      Parameters:

      Example

      - -
      Cassette.where('artist').equals('Anne Murray').remove(callback)

      Query#findOneAndUpdate([query], [doc], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
      -  this.op = 'findOneAndUpdate';
      -
      -  switch (arguments.length) {
      -    case 3:
      -      if ('function' == typeof options)
      -        callback = options, options = {};
      -      break;
      -    case 2:
      -      if ('function' == typeof doc) {
      -        callback = doc;
      -        doc = query;
      -        query = undefined;
      -      }
      -      options = undefined;
      -      break;
      -    case 1:
      -      if ('function' == typeof query) {
      -        callback = query;
      -        query = options = doc = undefined;
      -      } else {
      -        doc = query;
      -        query = options = undefined;
      -      }
      -  }
      -
      -  // apply query
      -  if (query) {
      -    if ('Object' === query.constructor.name) {
      -      merge(this._conditions, query);
      -    } else if (query instanceof Query) {
      -      merge(this._conditions, query._conditions);
      -    } else if (query instanceof Document) {
      -      merge(this._conditions, query.toObject());
      -    }
      -  }
      -
      -  // apply doc
      -  if (doc) {
      -    merge(this._updateArg, doc);
      -  }
      -
      -  // apply options
      -  options && this.setOptions(options);
      -
      -  if (!callback) return this;
      -
      -  return this._findAndModify('update', callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      - -

      Available options

      - -
        -
      • new: bool - true to return the modified document rather than the original. defaults to true
      • -
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      - -

      Examples

      - -
      query.findOneAndUpdate(conditions, update, options, callback) // executes
      -query.findOneAndUpdate(conditions, update, options)  // returns Query
      -query.findOneAndUpdate(conditions, update, callback) // executes
      -query.findOneAndUpdate(conditions, update)           // returns Query
      -query.findOneAndUpdate(callback)                     // executes
      -query.findOneAndUpdate()                             // returns Query

      Query#findOneAndRemove([conditions], [options], [callback])

      Issues a mongodb findAndModify remove command.

      show code
      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
      -  this.op = 'findOneAndRemove';
      -
      -  if ('function' == typeof options) {
      -    callback = options;
      -    options = undefined;
      -  } else if ('function' == typeof conditions) {
      -    callback = conditions;
      -    conditions = undefined;
      -  }
      -
      -  // apply conditions
      -  if (conditions) {
      -    if ('Object' === conditions.constructor.name) {
      -      merge(this._conditions, conditions);
      -    } else if (conditions instanceof Query) {
      -      merge(this._conditions, conditions._conditions);
      -    } else if (conditions instanceof Document) {
      -      merge(this._conditions, conditions.toObject());
      -    }
      -  }
      -
      -  // apply options
      -  options && this.setOptions(options);
      -
      -  if (!callback) return this;
      -
      -  return this._findAndModify('remove', callback);
      -}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

      - -

      Available options

      - -
        -
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • -
      - -

      Examples

      - -
      A.where().findOneAndRemove(conditions, options, callback) // executes
      -A.where().findOneAndRemove(conditions, options)  // return Query
      -A.where().findOneAndRemove(conditions, callback) // executes
      -A.where().findOneAndRemove(conditions) // returns Query
      -A.where().findOneAndRemove(callback)   // executes
      -A.where().findOneAndRemove()           // returns Query

      Query#_findAndModify(type, callback)

      _findAndModify

      show code
      Query.prototype._findAndModify = function (type, callback) {
      -  var model = this.model
      -    , promise = new Promise(callback)
      -    , self = this
      -    , castedQuery
      -    , castedDoc
      -    , fields
      -    , sort
      -    , opts
      -
      -  castedQuery = castQuery(this);
      -  if (castedQuery instanceof Error) {
      -    process.nextTick(promise.error.bind(promise, castedQuery));
      -    return promise;
      -  }
      -
      -  opts = this._optionsForExec(model);
      -
      -  if ('remove' == type) {
      -    opts.remove = true;
      -  } else {
      -    if (!('new' in opts)) opts.new = true;
      -    if (!('upsert' in opts)) opts.upsert = false;
      -
      -    castedDoc = castDoc(this);
      -    if (!castedDoc) {
      -      if (opts.upsert) {
      -        // still need to do the upsert to empty doc
      -        castedDoc = { $set: {} };
      -      } else {
      -        return this.findOne(callback);
      -      }
      -    } else if (castedDoc instanceof Error) {
      -      process.nextTick(promise.error.bind(promise, castedDoc));
      -      return promise;
      -    }
      -  }
      -
      -  this._applyPaths();
      -
      -  if (this._fields) {
      -    fields = utils.clone(this._fields)
      -    opts.fields = this._castFields(fields);
      -    if (opts.fields instanceof Error) {
      -      process.nextTick(promise.error.bind(promise, opts.fields));
      -      return promise;
      -    }
      -  }
      -
      -  // the driver needs a default
      -  sort = opts.sort || [];
      -
      -  model
      -  .collection
      -  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
      -    if (err) return promise.error(err);
      -    if (!doc) return promise.complete(null);
      -
      -    if (true === opts.lean) {
      -      return promise.complete(doc);
      -    }
      -
      -    var casted = new model(undefined, fields, true);
      -    casted.init(doc, self, function (err) {
      -      if (err) return promise.error(err);
      -      promise.complete(casted);
      -    });
      -  }));
      -
      -  return promise;
      -}

      Parameters:


      Query#populate(path, [fields], [model], [conditions], [options])

      Specifies paths which should be populated with other documents.

      show code
      Query.prototype.populate = function (path, fields, model, conditions, options) {
      -  if ('string' !== typeof model) {
      -    options = conditions;
      -    conditions = model;
      -    model = undefined;
      -  }
      -  // The order of fields/conditions args is opposite Model.find but
      -  // necessary to keep backward compatibility (fields could be
      -  // an array, string, or object literal).
      -  this.options.populate[path] =
      -    new PopulateOptions(fields, conditions, options, model);
      -
      -  return this;
      -};

      Parameters:

      • path <String>
      • [fields] <Object, String> Field selection for the population query
      • [model] <Model> The name of the model you wish to use for population. If not specified, the name is looked up from the Schema ref.
      • [conditions] <Object> Conditions for the population query
      • [options] <Object> Options for the population query (sort, etc)

      Returns:

      Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

      - -

      Example:

      - -
      Kitten.findOne().populate('owner').exec(function (err, kitten) {
      -  console.log(kitten.owner.name) // Max
      -})

      Query#stream([options])

      Returns a Node.js 0.8 style read stream interface.

      show code
      Query.prototype.stream = function stream (opts) {
      -  return new QueryStream(this, opts);
      -}
      -
      -// helpers

      Parameters:

      Returns:

      Example

      - -
      // follows the nodejs 0.8 stream api
      -Thing.find({ name: /^hello/ }).stream().pipe(res)
      -
      -// manual streaming
      -var stream = Thing.find({ name: /^hello/ }).stream();
      -
      -stream.on('data', function (doc) {
      -  // do something with the mongoose document
      -}).on('error', function (err) {
      -  // handle the error
      -}).on('close', function () {
      -  // the stream is closed
      -});
      - -

      Valid options

      - -
        -
      • transform: optional function which accepts a mongoose document. The return value of the function will be emitted.
      • -
      - -

      Example

      - -
      // JSON.stringify all documents before emitting
      -var stream = Thing.find().stream({ transform: JSON.stringify });
      -stream.pipe(writeStream);

      Query#within

      Syntax sugar for expressive queries.

      - -

      Example

      - -
      query.within.box()
      -query.within.center()

      Returns:


    • querystream.js

      QueryStream(query)

      Provides a Node.js 0.8 style ReadStream interface for Queries.

      show code
      function QueryStream (query, options) {
      -  Stream.call(this);
      -
      -  this.query = query;
      -  this.readable = true;
      -  this.paused = false;
      -  this._cursor = null;
      -  this._destroyed = null;
      -  this._fields = null;
      -  this._buffer = null;
      -  this._inline = T_INIT;
      -  this._running = false;
      -  this._transform = options && 'function' == typeof options.transform
      -    ? options.transform
      -    : K;
      -
      -  // give time to hook up events
      -  var self = this;
      -  process.nextTick(function () {
      -    self._init();
      -  });
      -}

      Parameters:

      Inherits:

      Events:

      • data: emits a single Mongoose document

      • error: emits when an error occurs during streaming. This will emit before the close event.

      • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

      var stream = Model.find().stream();
      -
      -stream.on('data', function (doc) {
      -  // do something with the mongoose document
      -}).on('error', function (err) {
      -  // handle the error
      -}).on('close', function () {
      -  // the stream is closed
      -});
      - -

      The stream interface allows us to simply "plug-in" to other Node.js 0.8 style write streams.

      - -
      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);
      - -

      NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary.

      - -

      NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work.


      QueryStream#_init()

      Initializes the query.

      show code
      QueryStream.prototype._init = function () {
      -  if (this._destroyed) return;
      -
      -  var query = this.query
      -    , model = query.model
      -    , options = query._optionsForExec(model)
      -    , self = this
      -
      -  try {
      -    query.cast(model);
      -  } catch (err) {
      -    return self.destroy(err);
      -  }
      -
      -  self._fields = utils.clone(query._fields);
      -  options.fields = query._castFields(self._fields);
      -
      -  model.collection.find(query._conditions, options, function (err, cursor) {
      -    if (err) return self.destroy(err);
      -    self._cursor = cursor;
      -    self._next();
      -  });
      -}

      QueryStream#_next()

      Trampoline for pulling the next doc from cursor.

      show code
      QueryStream.prototype._next = function _next () {
      -  if (this.paused || this._destroyed) {
      -    return this._running = false;
      -  }
      -
      -  this._running = true;
      -
      -  if (this._buffer && this._buffer.length) {
      -    var arg;
      -    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
      -      this._onNextObject.apply(this, arg);
      -    }
      -  }
      -
      -  // avoid stack overflows with large result sets.
      -  // trampoline instead of recursion.
      -  while (this.__next()) {}
      -}

      QueryStream#__next()

      Pulls the next doc from the cursor.

      show code
      QueryStream.prototype.__next = function () {
      -  if (this.paused || this._destroyed)
      -    return this._running = false;
      -
      -  var self = this;
      -  self._inline = T_INIT;
      -
      -  self._cursor.nextObject(function cursorcb (err, doc) {
      -    self._onNextObject(err, doc);
      -  });
      -
      -  // if onNextObject() was already called in this tick
      -  // return ourselves to the trampoline.
      -  if (T_CONT === this._inline) {
      -    return true;
      -  } else {
      -    // onNextObject() hasn't fired yet. tell onNextObject
      -    // that its ok to call _next b/c we are not within
      -    // the trampoline anymore.
      -    this._inline = T_IDLE;
      -  }
      -}

      QueryStream#_onNextObject(err, doc)

      Transforms raw docs returned from the cursor into a model instance.

      show code
      QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
      -  if (this._destroyed) return;
      -
      -  if (this.paused) {
      -    this._buffer || (this._buffer = []);
      -    this._buffer.push([err, doc]);
      -    return this._running = false;
      -  }
      -
      -  if (err) return this.destroy(err);
      -
      -  // when doc is null we hit the end of the cursor
      -  if (!doc) {
      -    this.emit('end');
      -    return this.destroy();
      -  }
      -
      -  if (this.query.options && true === this.query.options.lean)  {
      -    this.emit('data', this._transform(doc));
      -
      -    // trampoline management
      -    if (T_IDLE === this._inline) {
      -      // no longer in trampoline. restart it.
      -      this._next();
      -    } else {
      -      // in a trampoline. tell __next that its
      -      // ok to continue jumping.
      -      this._inline = T_CONT;
      -    }
      -    return;
      -  }
      -
      -  var instance = new this.query.model(undefined, this._fields, true);
      -
      -  var self = this;
      -  instance.init(doc, this.query, function (err) {
      -    if (err) return self.destroy(err);
      -    self.emit('data', self._transform(instance));
      -
      -    // trampoline management
      -    if (T_IDLE === self._inline) {
      -      // no longer in trampoline. restart it.
      -      self._next();
      -    } else
      -      // in a trampoline. tell __next that its
      -      // ok to continue jumping.
      -      self._inline = T_CONT;
      -  });
      -}

      Parameters:


      QueryStream#pause()

      Pauses this stream.

      show code
      QueryStream.prototype.pause = function () {
      -  this.paused = true;
      -}

      QueryStream#resume()

      Resumes this stream.

      show code
      QueryStream.prototype.resume = function () {
      -  this.paused = false;
      -
      -  if (!this._cursor) {
      -    // cannot start if not initialized
      -    return;
      -  }
      -
      -  // are we within the trampoline?
      -  if (T_INIT === this._inline) {
      -    return;
      -  }
      -
      -  if (!this._running) {
      -    // outside QueryStream control, need manual restart
      -    return this._next();
      -  }
      -}

      QueryStream#destroy([err])

      Destroys the stream, closing the underlying cursor. No more events will be emitted.

      show code
      QueryStream.prototype.destroy = function (err) {
      -  if (this._destroyed) return;
      -  this._destroyed = true;
      -  this._running = false;
      -  this.readable = false;
      -
      -  if (this._cursor) {
      -    this._cursor.close();
      -  }
      -
      -  if (err) {
      -    this.emit('error', err);
      -  }
      -
      -  this.emit('close');
      -}

      Parameters:


      QueryStream#pipe()

      Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

      See:

      Example:

      - -
      query.stream().pipe(writeStream [, options])
      - -

      This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      - -
      var format = new ArrayFormatter;
      -Events.find().stream().pipe(format).pipe(res);
      - -

      As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


      QueryStream#paused

      Flag stating whether or not this stream is paused.


      QueryStream#readable

      Flag stating whether or not this stream is readable.


    • schema/array.js

      SchemaArray(key, cast, options)

      Array SchemaType constructor

      show code
      function SchemaArray (key, cast, options) {
      -  if (cast) {
      -    var castOptions = {};
      -
      -    if ('Object' === cast.constructor.name) {
      -      if (cast.type) {
      -        // support { type: Woot }
      -        castOptions = cast;
      -        cast = cast.type;
      -        delete castOptions.type;
      -      } else {
      -        cast = Mixed;
      -      }
      -    }
      -
      -    var caster = cast.name in Types ? Types[cast.name] : cast;
      -    this.casterConstructor = caster;
      -    this.caster = new caster(null, castOptions);
      -    if (!(this.caster instanceof EmbeddedDoc)) {
      -      this.caster.path = key;
      -    }
      -  }
      -
      -  SchemaType.call(this, key, options);
      -
      -  var self = this
      -    , defaultArr
      -    , fn;
      -
      -  if (this.defaultValue) {
      -    defaultArr = this.defaultValue;
      -    fn = 'function' == typeof defaultArr;
      -  }
      -
      -  this.default(function(){
      -    var arr = fn ? defaultArr() : defaultArr || [];
      -    return new MongooseArray(arr, self.path, this);
      -  });
      -};

      Parameters:

      Inherits:


      SchemaArray#checkRequired(value)

      Check required

      show code
      SchemaArray.prototype.checkRequired = function (value) {
      -  return !!(value && value.length);
      -};

      Parameters:


      SchemaArray#applyGetters(value, scope)

      Overrides the getters application for the population special-case

      show code
      SchemaArray.prototype.applyGetters = function (value, scope) {
      -  if (this.caster.options && this.caster.options.ref) {
      -    // means the object id was populated
      -    return value;
      -  }
      -
      -  return SchemaType.prototype.applyGetters.call(this, value, scope);
      -};

      Parameters:


      SchemaArray#cast(value, doc, init)

      Casts contents

      show code
      SchemaArray.prototype.cast = function (value, doc, init) {
      -  if (Array.isArray(value)) {
      -    if (!(value instanceof MongooseArray)) {
      -      value = new MongooseArray(value, this.path, doc);
      -    }
      -
      -    if (this.caster) {
      -      try {
      -        for (var i = 0, l = value.length; i < l; i++) {
      -          value[i] = this.caster.cast(value[i], doc, init);
      -        }
      -      } catch (e) {
      -        // rethrow
      -        throw new CastError(e.type, value, this.path);
      -      }
      -    }
      -
      -    return value;
      -  } else {
      -    return this.cast([value], doc, init);
      -  }
      -};

      Parameters:

      • value <Object>
      • doc <Document> document that triggers the casting
      • init <Boolean> whether this is an initialization cast

      SchemaArray#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaArray.prototype.castForQuery = function ($conditional, value) {
      -  var handler
      -    , val;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with Array.");
      -    val = handler.call(this, value);
      -  } else {
      -    val = $conditional;
      -    var proto = this.casterConstructor.prototype;
      -    var method = proto.castForQuery || proto.cast;
      -
      -    var caster = this.caster;
      -    if (Array.isArray(val)) {
      -      val = val.map(function (v) {
      -        if (method) v = method.call(caster, v);
      -
      -        return isMongooseObject(v)
      -          ? v.toObject()
      -          : v;
      -      });
      -    } else if (method) {
      -      val = method.call(caster, val);
      -    }
      -  }
      -  return val && isMongooseObject(val)
      -    ? val.toObject()
      -    : val;
      -};

      Parameters:


    • schema/boolean.js

      SchemaBoolean(path, options)

      Boolean SchemaType constructor.

      show code
      function SchemaBoolean (path, options) {
      -  SchemaType.call(this, path, options);
      -};

      Parameters:

      Inherits:


      SchemaBoolean#checkRequired()

      Required validator

      show code
      SchemaBoolean.prototype.checkRequired = function (value) {
      -  return value === true || value === false;
      -};

      SchemaBoolean#cast(value)

      Casts to boolean

      show code
      SchemaBoolean.prototype.cast = function (value) {
      -  if (value === null) return value;
      -  if (value === '0') return false;
      -  return !!value;
      -};

      Parameters:


      SchemaBoolean#castForQuery($conditional, val)

      Casts contents for queries.

      show code
      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (2 === arguments.length) {
      -    handler = SchemaBoolean.$conditionalHandlers[$conditional];
      -
      -    if (handler) {
      -      return handler.call(this, val);
      -    }
      -
      -    return this.cast(val);
      -  }
      -
      -  return this.cast($conditional);
      -};

      Parameters:


    • schema/buffer.js

      SchemaBuffer(key, cast)

      Buffer SchemaType constructor

      show code
      function SchemaBuffer (key, options) {
      -  SchemaType.call(this, key, options, 'Buffer');
      -};

      Parameters:

      Inherits:


      SchemaBuffer#checkRequired()

      Check required

      show code
      SchemaBuffer.prototype.checkRequired = function (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return !!(value && value.length);
      -  }
      -};

      SchemaBuffer#cast(value, doc, init)

      Casts contents

      show code
      SchemaBuffer.prototype.cast = function (value, doc, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  if (Buffer.isBuffer(value)) {
      -    if (!(value instanceof MongooseBuffer)) {
      -      value = new MongooseBuffer(value, [this.path, doc]);
      -    }
      -
      -    return value;
      -  } else if (value instanceof Binary) {
      -    return new MongooseBuffer(value.value(true), [this.path, doc]);
      -  }
      -
      -  var type = typeof value;
      -  if ('string' == type || 'number' == type || Array.isArray(value)) {
      -    return new MongooseBuffer(value, [this.path, doc]);
      -  }
      -
      -  throw new CastError('buffer', value, this.path);
      -};

      Parameters:


      SchemaBuffer#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with Buffer.");
      -    return handler.call(this, val);
      -  } else {
      -    val = $conditional;
      -    return this.cast(val).toObject();
      -  }
      -};

      Parameters:


    • schema/date.js

      SchemaDate(key, options)

      Date SchemaType constructor.

      show code
      function SchemaDate (key, options) {
      -  SchemaType.call(this, key, options);
      -};

      Parameters:

      Inherits:


      SchemaDate#checkRequired()

      Required validator for date

      show code
      SchemaDate.prototype.checkRequired = function (value) {
      -  return value instanceof Date;
      -};

      SchemaDate#cast(value)

      Casts to date

      show code
      SchemaDate.prototype.cast = function (value) {
      -  if (value === null || value === '')
      -    return null;
      -
      -  if (value instanceof Date)
      -    return value;
      -
      -  var date;
      -
      -  // support for timestamps
      -  if (value instanceof Number || 'number' == typeof value 
      -      || String(value) == Number(value))
      -    date = new Date(Number(value));
      -
      -  // support for date strings
      -  else if (value.toString)
      -    date = new Date(value.toString());
      -
      -  if (date.toString() != 'Invalid Date')
      -    return date;
      -
      -  throw new CastError('date', value, this.path);
      -};

      Parameters:


      SchemaDate#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaDate.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -
      -  if (2 !== arguments.length) {
      -    return this.cast($conditional);
      -  }
      -
      -  handler = this.$conditionalHandlers[$conditional];
      -
      -  if (!handler) {
      -    throw new Error("Can't use " + $conditional + " with Date.");
      -  }
      -
      -  return handler.call(this, val);
      -};

      Parameters:


    • schema/documentarray.js

      DocumentArray(key, schema, options)

      SubdocsArray SchemaType constructor

      show code
      function DocumentArray (key, schema, options) {
      -
      -  // compile an embedded document for this schema
      -  function EmbeddedDocument () {
      -    Subdocument.apply(this, arguments);
      -  }
      -
      -  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
      -  EmbeddedDocument.prototype._setSchema(schema);
      -  EmbeddedDocument.schema = schema;
      -
      -  // apply methods
      -  for (var i in schema.methods) {
      -    EmbeddedDocument.prototype[i] = schema.methods[i];
      -  }
      -
      -  // apply statics
      -  for (var i in schema.statics)
      -    EmbeddedDocument[i] = schema.statics[i];
      -
      -  EmbeddedDocument.options = options;
      -  this.schema = schema;
      -
      -  ArrayType.call(this, key, EmbeddedDocument, options);
      -
      -  this.schema = schema;
      -  var path = this.path;
      -  var fn = this.defaultValue;
      -
      -  this.default(function(){
      -    var arr = fn.call(this);
      -    if (!Array.isArray(arr)) arr = [arr];
      -    return new MongooseDocumentArray(arr, path, this);
      -  });
      -};

      Parameters:

      Inherits:


      DocumentArray#doValidate()

      Performs local validations first, then validations on each embedded doc

      show code
      DocumentArray.prototype.doValidate = function (array, fn, scope) {
      -  var self = this;
      -
      -  SchemaType.prototype.doValidate.call(this, array, function (err) {
      -    if (err) return fn(err);
      -
      -    var count = array && array.length
      -      , error;
      -
      -    if (!count) return fn();
      -
      -    // handle sparse arrays, do not use array.forEach which does not
      -    // iterate over sparse elements yet reports array.length including
      -    // them :(
      -
      -    for (var i = 0, len = count; i < len; ++i) {
      -      // sidestep sparse entries
      -      var doc = array[i];
      -      if (!doc) {
      -        --count || fn();
      -        continue;
      -      }
      -
      -      ;(function (i) {
      -        doc.validate(function (err) {
      -          if (err && !error) {
      -            // rewrite the key
      -            err.key = self.key + '.' + i + '.' + err.key;
      -            return fn(error = err);
      -          }
      -          --count || fn();
      -        });
      -      })(i);
      -    }
      -  }, scope);
      -};

      DocumentArray#cast(value, document)

      Casts contents

      show code
      DocumentArray.prototype.cast = function (value, doc, init, prev) {
      -  var selected
      -    , subdoc
      -    , i
      -
      -  if (!Array.isArray(value)) {
      -    return this.cast([value], doc, init, prev);
      -  }
      -
      -  if (!(value instanceof MongooseDocumentArray)) {
      -    value = new MongooseDocumentArray(value, this.path, doc);
      -  }
      -
      -  i = value.length;
      -
      -  while (i--) {
      -    if (!(value[i] instanceof Subdocument) && value[i]) {
      -      if (init) {
      -        selected || (selected = scopePaths(this, doc._selected, init));
      -        subdoc = new this.casterConstructor(null, value, true, selected);
      -        value[i] = subdoc.init(value[i]);
      -      } else {
      -        if (prev && (subdoc = prev.id(value[i]._id))) {
      -          // handle resetting doc with existing id but differing data
      -          // doc.array = [{ doc: 'val' }]
      -          subdoc.set(value[i]);
      -        } else {
      -          subdoc = new this.casterConstructor(value[i], value);
      -        }
      -
      -        // if set() is hooked it will have no return value
      -        // see gh-746
      -        value[i] = subdoc;
      -      }
      -    }
      -  }
      -
      -  return value;
      -}

      Parameters:


    • schema/mixed.js

      Mixed(path, options)

      Mixed SchemaType constructor.

      show code
      function Mixed (path, options) {
      -  // make sure empty array defaults are handled
      -  if (options &&
      -      options.default &&
      -      Array.isArray(options.default) &&
      -      0 === options.default.length) {
      -    options.default = Array;
      -  }
      -
      -  SchemaType.call(this, path, options);
      -};

      Parameters:

      Inherits:


      Mixed#checkRequired()

      Required validator

      show code
      Mixed.prototype.checkRequired = function (val) {
      -  return true;
      -};

      Mixed#cast(value)

      Casts val for Mixed.

      show code
      Mixed.prototype.cast = function (val) {
      -  return val;
      -};

      Parameters:

      this is a no-op


      Mixed#castForQuery($cond, [val])

      Casts contents for queries.

      show code
      Mixed.prototype.castForQuery = function ($cond, val) {
      -  if (arguments.length === 2) return val;
      -  return $cond;
      -};

      Parameters:


    • schema/number.js

      SchemaNumber(key, options)

      Number SchemaType constructor.

      show code
      function SchemaNumber (key, options) {
      -  SchemaType.call(this, key, options, 'Number');
      -};

      Parameters:

      Inherits:


      SchemaNumber#checkRequired()

      Required validator for number

      show code
      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return typeof value == 'number' || value instanceof Number;
      -  }
      -};

      SchemaNumber#min(value, message)

      Sets a minimum number validator.

      show code
      SchemaNumber.prototype.min = function (value, message) {
      -  if (this.minValidator)
      -    this.validators = this.validators.filter(function(v){
      -      return v[1] != 'min';
      -    });
      -  if (value != null)
      -    this.validators.push([function(v){
      -      return v === null || v >= value;
      -    }, 'min']);
      -  return this;
      -};

      Parameters:

      Example:

      - -
      var s = new Schema({ n: { type: Number, min: 10 })
      -var M = db.model('M', s)
      -var m = new M({ n: 9 })
      -m.save(function (err) {
      -  console.error(err) // validator error
      -  m.n = 10;
      -  m.save() // success
      -})

      SchemaNumber#max(maximum, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.max = function (value, message) {
      -  if (this.maxValidator)
      -    this.validators = this.validators.filter(function(v){
      -      return v[1] != 'max';
      -    });
      -  if (value != null)
      -    this.validators.push([this.maxValidator = function(v){
      -      return v === null || v <= value;
      -    }, 'max']);
      -  return this;
      -};

      Parameters:

      Example:

      - -
      var s = new Schema({ n: { type: Number, max: 10 })
      -var M = db.model('M', s)
      -var m = new M({ n: 11 })
      -m.save(function (err) {
      -  console.error(err) // validator error
      -  m.n = 10;
      -  m.save() // success
      -})

      SchemaNumber#cast(value, doc, init)

      Casts to number

      show code
      SchemaNumber.prototype.cast = function (value, doc, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  if (!isNaN(value)){
      -    if (null === value) return value;
      -    if ('' === value) return null;
      -    if ('string' == typeof value) value = Number(value);
      -    if (value instanceof Number) return value
      -    if ('number' == typeof value) return value;
      -    if (value.toString && !Array.isArray(value) &&
      -        value.toString() == Number(value)) {
      -      return new Number(value)
      -    }
      -  }
      -
      -  throw new CastError('number', value, this.path);
      -};

      Parameters:


      SchemaNumber#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with Number.");
      -    return handler.call(this, val);
      -  } else {
      -    val = this.cast($conditional);
      -    return val == null ? val : val
      -  }
      -};

      Parameters:


    • schema/objectid.js

      ObjectId(key, options)

      ObjectId SchemaType constructor.

      show code
      function ObjectId (key, options) {
      -  SchemaType.call(this, key, options, 'ObjectID');
      -};

      Parameters:

      Inherits:


      ObjectId#checkRequired()

      Check required

      show code
      ObjectId.prototype.checkRequired = function checkRequired (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return value instanceof oid;
      -  }
      -};

      ObjectId#cast(value, scope, init)

      Casts to ObjectId

      show code
      ObjectId.prototype.cast = function (value, scope, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  if (value === null) return value;
      -
      -  if (value instanceof oid)
      -    return value;
      -
      -  if (value._id && value._id instanceof oid)
      -    return value._id;
      -
      -  if (value.toString) {
      -    try {
      -      return oid.fromString(value.toString());
      -    } catch (err) {
      -      throw new CastError('ObjectId', value, this.path);
      -    }
      -  }
      -
      -  throw new CastError('ObjectId', value, this.path);
      -};

      Parameters:


      ObjectId#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      ObjectId.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with ObjectId.");
      -    return handler.call(this, val);
      -  } else {
      -    return this.cast($conditional);
      -  }
      -};

      Parameters:


      ObjectId#auto(turnOn)

      Adds an auto-generated ObjectId default if turnOn is true.

      show code
      ObjectId.prototype.auto = function (turnOn) {
      -  if (turnOn) {
      -    this.default(defaultId);
      -    this.set(resetId)
      -  }
      -};

      Parameters:

      • turnOn <Boolean> auto generated ObjectId defaults

    • schema/string.js

      SchemaString(key, options)

      String SchemaType constructor.

      show code
      function SchemaString (key, options) {
      -  this.enumValues = [];
      -  this.regExp = null;
      -  SchemaType.call(this, key, options, 'String');
      -};

      Parameters:

      Inherits:


      SchemaString#enum([args...])

      Adds enumeration values and a coinciding validator.

      show code
      SchemaString.prototype.enum = function () {
      -  var len = arguments.length;
      -  if (!len || undefined === arguments[0] || false === arguments[0]) {
      -    if (this.enumValidator){
      -      this.enumValidator = false;
      -      this.validators = this.validators.filter(function(v){
      -        return v[1] != 'enum';
      -      });
      -    }
      -    return;
      -  }
      -
      -  for (var i = 0; i < len; i++) {
      -    if (undefined !== arguments[i]) {
      -      this.enumValues.push(this.cast(arguments[i]));
      -    }
      -  }
      -
      -  if (!this.enumValidator) {
      -    var values = this.enumValues;
      -    this.enumValidator = function(v){
      -      return undefined === v || ~values.indexOf(v);
      -    };
      -    this.validators.push([this.enumValidator, 'enum']);
      -  }
      -};

      Parameters:

      • [args...] <String> enumeration values

      Example:

      - -
      var states = 'opening open closing closed'.split(' ')
      -var s = new Schema({ state: { type: String, enum: states })
      -var M = db.model('M', s)
      -var m = new M({ state: 'invalid' })
      -m.save(function (err) {
      -  console.error(err) // validator error
      -  m.state = 'open'
      -  m.save() // success
      -})

      SchemaString#lowercase()

      Adds a lowercase setter.

      show code
      SchemaString.prototype.lowercase = function () {
      -  return this.set(function (v, self) {
      -    if ('string' != typeof v) v = self.cast(v)
      -    if (v) return v.toLowerCase();
      -    return v;
      -  });
      -};

      Example:

      - -
      var s = new Schema({ email: { type: String, lowercase: true }})
      -var M = db.model('M', s);
      -var m = new M({ email: 'SomeEmail@example.COM' });
      -console.log(m.email) // someemail@example.com
      -

      SchemaString#uppercase()

      Adds an uppercase setter.

      show code
      SchemaString.prototype.uppercase = function () {
      -  return this.set(function (v, self) {
      -    if ('string' != typeof v) v = self.cast(v)
      -    if (v) return v.toUpperCase();
      -    return v;
      -  });
      -};

      Example:

      - -
      var s = new Schema({ caps: { type: String, uppercase: true }})
      -var M = db.model('M', s);
      -var m = new M({ caps: 'an example' });
      -console.log(m.caps) // AN EXAMPLE

      SchemaString#trim()

      Adds a trim setter.

      show code
      SchemaString.prototype.trim = function () {
      -  return this.set(function (v, self) {
      -    if ('string' != typeof v) v = self.cast(v)
      -    if (v) return v.trim();
      -    return v;
      -  });
      -};

      The string value will be trimmed when set.

      - -

      Example:

      - -
      var s = new Schema({ name: { type: String, trim: true }})
      -var M = db.model('M', s)
      -var string = ' some name '
      -console.log(string.length) // 11
      -var m = new M({ name: string })
      -console.log(m.name.length) // 9

      SchemaString#match(regExp)

      Sets a regexp validator.

      show code
      SchemaString.prototype.match = function match (regExp) {
      -  this.validators.push([function(v){
      -    return null != v && '' !== v
      -      ? regExp.test(v)
      -      : true
      -  }, 'regexp']);
      -};

      Parameters:

      • regExp <RegExp> regular expression to test against

      Any value that does not pass regExp.test(val) will fail validation.

      - -

      Example:

      - -
      var s = new Schema({ name: { type: String, match: /^a/ }})
      -var M = db.model('M', s)
      -var m = new M({ name: 'invalid' })
      -m.validate(function (err) {
      -  console.error(err) // validation error
      -  m.name = 'apples'
      -  m.validate(function (err) {
      -    assert.ok(err) // success
      -  })
      -})

      SchemaString#checkRequired(value)

      Check required

      show code
      SchemaString.prototype.checkRequired = function checkRequired (value) {
      -  if (SchemaType._isRef(this, value, true)) {
      -    return null != value;
      -  } else {
      -    return (value instanceof String || typeof value == 'string') && value.length;
      -  }
      -};

      Parameters:


      SchemaString#cast()

      Casts to String

      show code
      SchemaString.prototype.cast = function (value, scope, init) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -  if (value === null) return value;
      -  if ('undefined' !== typeof value && value.toString) return value.toString();
      -  throw new CastError('string', value, this.path);
      -};

      SchemaString#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      SchemaString.prototype.castForQuery = function ($conditional, val) {
      -  var handler;
      -  if (arguments.length === 2) {
      -    handler = this.$conditionalHandlers[$conditional];
      -    if (!handler)
      -      throw new Error("Can't use " + $conditional + " with String.");
      -    return handler.call(this, val);
      -  } else {
      -    val = $conditional;
      -    if (val instanceof RegExp) return val;
      -    return this.cast(val);
      -  }
      -};

      Parameters:


    • schema.js

      Schema(definition)

      Schema constructor.

      show code
      function Schema (obj, options) {
      -  if (!(this instanceof Schema))
      -    return new Schema(obj, options);
      -
      -  this.paths = {};
      -  this.subpaths = {};
      -  this.virtuals = {};
      -  this.nested = {};
      -  this.inherits = {};
      -  this.callQueue = [];
      -  this._indexes = [];
      -  this.methods = {};
      -  this.statics = {};
      -  this.tree = {};
      -  this._requiredpaths = undefined;
      -
      -  this.options = this.defaultOptions(options);
      -
      -  // build paths
      -  if (obj) {
      -    this.add(obj);
      -  }
      -
      -  // ensure the documents get an auto _id unless disabled
      -  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
      -  if (auto_id) {
      -    this.add({ _id: {type: Schema.ObjectId, auto: true} });
      -  }
      -
      -  // ensure the documents receive an id getter unless disabled
      -  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
      -  if (autoid) {
      -    this.virtual('id').get(idGetter);
      -  }
      -
      -  // versioning not directly added to schema b/c we only want
      -  // it in the top level document, not embedded ones.
      -};

      Parameters:

      Events:

      • init: Emitted after the schema is compiled into a Model.

      Example:

      - -
      var child = new Schema({ name: String });
      -var schema = new Schema({ name: String, age: Number, children: [child] });
      -var Tree = mongoose.model('Tree', schema);
      -
      -// setting schema options
      -new Schema({ name: String }, { _id: false, autoIndex: false })
      - -

      Options:

      - -
        -
      • autoIndex: bool - defaults to true
      • -
      • capped: bool - defaults to false
      • -
      • collection: string - no default
      • -
      • id: bool - defaults to true
      • -
      • _id: bool - defaults to true
      • -
      • read: string
      • -
      • safe: bool - defaults to true.
      • -
      • shardKey: bool - defaults to null
      • -
      • strict: bool - defaults to true
      • -
      • toJSON - object - no default
      • -
      • toObject - object - no default
      • -
      • versionKey: bool - defaults to "__v"
      • -
      • minimize: bool - controls document#toObject behavior when called manually - defaults to true
      • -
      - -

      Note:

      - -

      When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


      Schema#defaultOptions(options)

      Returns default options for this schema, merged with options.

      show code
      Schema.prototype.defaultOptions = function (options) {
      -  if (options && false === options.safe) {
      -    options.safe = { w: 0 };
      -  }
      -
      -  options = utils.options({
      -      strict: true
      -    , capped: false // { size, max, autoIndexId }
      -    , versionKey: '__v'
      -    , minimize: true
      -    , autoIndex: true
      -    , shardKey: null
      -    , read: null
      -    // the following are only applied at construction time
      -    , noId: false // deprecated, use { _id: false }
      -    , _id: true
      -    , noVirtualId: false // deprecated, use { id: false }
      -    , id: true
      -  }, options);
      -
      -  if (options.read)
      -    options.read = utils.readPref(options.read);
      -
      -  return options;
      -}

      Parameters:

      Returns:


      Schema#add(obj, prefix)

      Adds key path / schema type pairs to this schema.

      show code
      Schema.prototype.add = function add (obj, prefix) {
      -  prefix = prefix || '';
      -  for (var i in obj) {
      -    if (null == obj[i]) {
      -      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
      -    }
      -
      -    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
      -      if (Object.keys(obj[i]).length) {
      -        // nested object { last: { name: String }}
      -        this.nested[prefix + i] = true;
      -        this.add(obj[i], prefix + i + '.');
      -      } else {
      -        this.path(prefix + i, obj[i]); // mixed type
      -      }
      -    } else {
      -      this.path(prefix + i, obj[i]);
      -    }
      -  }
      -};

      Parameters:

      Example:

      - -
      var ToySchema = new Schema;
      -ToySchema.add({ name: 'string', color: 'string', price: 'number' });

      Schema#path(path, constructor)

      Gets/sets schema paths.

      show code
      Schema.prototype.path = function (path, obj) {
      -  if (obj == undefined) {
      -    if (this.paths[path]) return this.paths[path];
      -    if (this.subpaths[path]) return this.subpaths[path];
      -
      -    // subpaths?
      -    return /\.\d+\.?$/.test(path)
      -      ? getPositionalPath(this, path)
      -      : undefined;
      -  }
      -
      -  // some path names conflict with document methods
      -  if (reserved[path]) {
      -    throw new Error("`" + path + "` may not be used as a schema pathname");
      -  }
      -
      -  // update the tree
      -  var subpaths = path.split(/\./)
      -    , last = subpaths.pop()
      -    , branch = this.tree;
      -
      -  subpaths.forEach(function(sub, i) {
      -    if (!branch[sub]) branch[sub] = {};
      -    if ('object' != typeof branch[sub]) {
      -      var msg = 'Cannot set nested path `' + path + '`. '
      -              + 'Parent path `'
      -              + subpaths.slice(0, i).concat([sub]).join('.')
      -              + '` already set to type ' + branch[sub].name
      -              + '.';
      -      throw new Error(msg);
      -    }
      -    branch = branch[sub];
      -  });
      -
      -  branch[last] = utils.clone(obj);
      -
      -  this.paths[path] = Schema.interpretAsType(path, obj);
      -  return this;
      -};

      Parameters:

      Sets a path (if arity 2)
      Gets a path (if arity 1)

      - -

      Example

      - -
      schema.path('name') // returns a SchemaType
      -schema.path('name', Number) // changes the schemaType of `name` to Number

      Schema#eachPath(fn)

      Iterates the schemas paths similar to Array#forEach.

      show code
      Schema.prototype.eachPath = function (fn) {
      -  var keys = Object.keys(this.paths)
      -    , len = keys.length;
      -
      -  for (var i = 0; i < len; ++i) {
      -    fn(keys[i], this.paths[keys[i]]);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Returns:

      The callback is passed the pathname and schemaType as arguments on each iteration.


      Schema#requiredPaths()

      Returns an Array of path strings that are required by this schema.

      show code
      Schema.prototype.requiredPaths = function requiredPaths () {
      -  if (this._requiredpaths) return this._requiredpaths;
      -
      -  var paths = Object.keys(this.paths)
      -    , i = paths.length
      -    , ret = [];
      -
      -  while (i--) {
      -    var path = paths[i];
      -    if (this.paths[path].isRequired) ret.push(path);
      -  }
      -
      -  return this._requiredpaths = ret;
      -}

      Returns:


      Schema#pathType(path)

      Returns the pathType of path for this schema.

      show code
      Schema.prototype.pathType = function (path) {
      -  if (path in this.paths) return 'real';
      -  if (path in this.virtuals) return 'virtual';
      -  if (path in this.nested) return 'nested';
      -  if (path in this.subpaths) return 'real';
      -
      -  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
      -    return 'real';
      -  } else {
      -    return 'adhocOrUndefined'
      -  }
      -};

      Parameters:

      Returns:

      Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


      Schema#queue(name, args)

      Adds a method call to the queue.

      show code
      Schema.prototype.queue = function(name, args){
      -  this.callQueue.push([name, args]);
      -  return this;
      -};

      Parameters:

      • name <String> name of the document method to call later
      • args <Array> arguments to pass to the method

      Schema#pre(method, callback)

      Defines a pre hook for the document.

      show code
      Schema.prototype.pre = function(){
      -  return this.queue('pre', arguments);
      -};

      Parameters:

      Example

      - -
      var toySchema = new Schema(..);
      -
      -toySchema.pre('save', function (next) {
      -  if (!this.created) this.created = new Date;
      -  next();
      -})
      -
      -toySchema.pre('validate', function (next) {
      -  if (this.name != 'Woody') this.name = 'Woody';
      -  next();
      -})

      Schema#post(method, fn)

      Defines a post hook for the document.

      show code
      Schema.prototype.post = function(method, fn){
      -  return this.queue('on', arguments);
      -};

      Parameters:

      Post hooks fire on the event emitted from document instances of Models compiled from this schema.

      - -
      var schema = new Schema(..);
      -schema.post('save', function (doc) {
      -  console.log('this fired after a document was saved');
      -});
      -
      -var Model = mongoose.model('Model', schema);
      -
      -var m = new Model(..);
      -m.save(function (err) {
      -  console.log('this fires after the `post` hook');
      -});

      Schema#plugin(plugin, opts)

      Registers a plugin for this schema.

      show code
      Schema.prototype.plugin = function (fn, opts) {
      -  fn(this, opts);
      -  return this;
      -};

      Parameters:


      Schema#method(method, [fn])

      Adds an instance method to documents constructed from Models compiled from this schema.

      show code
      Schema.prototype.method = function (name, fn) {
      -  if ('string' != typeof name)
      -    for (var i in name)
      -      this.methods[i] = name[i];
      -  else
      -    this.methods[name] = fn;
      -  return this;
      -};

      Parameters:

      Example

      - -
      var schema = kittySchema = new Schema(..);
      -
      -schema.methods.meow = function () {
      -  console.log('meeeeeoooooooooooow');
      -})
      -
      -var Kitty = mongoose.model('Kitty', schema);
      -
      -var fizz = new Kitty;
      -fizz.meow(); // meeeeeooooooooooooow
      - -

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      - -
      schema.method({
      -    purr: function () {}
      -  , scratch: function () {}
      -});
      -
      -// later
      -fizz.purr();
      -fizz.scratch();

      Schema#static(name, fn)

      Adds static "class" methods to Models compiled from this schema.

      show code
      Schema.prototype.static = function(name, fn) {
      -  if ('string' != typeof name)
      -    for (var i in name)
      -      this.statics[i] = name[i];
      -  else
      -    this.statics[name] = fn;
      -  return this;
      -};

      Parameters:

      Example

      - -
      var schema = new Schema(..);
      -schema.static('findByName', function (name, callback) {
      -  return this.find({ name: name }, callback);
      -});
      -
      -var Drink = mongoose.model('Drink', schema);
      -Drink.findByName('sanpellegrino', function (err, drinks) {
      -  //
      -});
      - -

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


      Schema#index(fields, [options])

      Defines an index (most likely compound) for this schema.

      show code
      Schema.prototype.index = function (fields, options) {
      -  options || (options = {});
      -
      -  if (options.expires)
      -    utils.expires(options);
      -
      -  this._indexes.push([fields, options]);
      -  return this;
      -};

      Parameters:

      Example

      - -
      schema.index({ first: 1, last: -1 })

      Schema#set(key, [value])

      Sets/gets a schema option.

      show code
      Schema.prototype.set = function (key, value, _tags) {
      -  if (1 === arguments.length) {
      -    return this.options[key];
      -  }
      -
      -  switch (key) {
      -    case 'read':
      -      this.options[key] = utils.readPref(value, _tags)
      -      break;
      -    case 'safe':
      -      this.options[key] = false === value
      -        ? { w: 0 }
      -        : value
      -      break;
      -    default:
      -      this.options[key] = value;
      -  }
      -
      -  return this;
      -}

      Parameters:

      • key <String> option name
      • [value] <Object> if not passed, the current option value is returned

      Schema#get(key)

      Gets a schema option.

      show code
      Schema.prototype.get = function (key) {
      -  return this.options[key];
      -}

      Parameters:


      Schema#indexes()

      Compiles indexes from fields and schema-level indexes

      show code
      Schema.prototype.indexes = function () {
      -  var indexes = []
      -    , seenSchemas = [];
      -
      -  collectIndexes(this);
      -
      -  return indexes;
      -
      -  function collectIndexes (schema, prefix) {
      -    if (~seenSchemas.indexOf(schema)) return;
      -    seenSchemas.push(schema);
      -
      -    var index;
      -    var paths = schema.paths;
      -    prefix = prefix || '';
      -
      -    for (var i in paths) {
      -      if (paths[i]) {
      -        if (paths[i] instanceof Types.DocumentArray) {
      -          collectIndexes(paths[i].schema, i + '.');
      -        } else {
      -          index = paths[i]._index;
      -
      -          if (index !== false && index !== null){
      -            var field = {};
      -            field[prefix + i] = '2d' === index ? index : 1;
      -            var options = 'Object' === index.constructor.name ? index : {};
      -            if (!('background' in options)) options.background = true;
      -            indexes.push([field, options]);
      -          }
      -        }
      -      }
      -    }
      -
      -    if (prefix) {
      -      fixSubIndexPaths(schema, prefix);
      -    } else {
      -      schema._indexes.forEach(function (index) {
      -        if (!('background' in index[1])) index[1].background = true;
      -      });
      -      indexes = indexes.concat(schema._indexes);
      -    }
      -  }

      Schema#virtual(name, [options])

      Creates a virtual type with the given name.

      show code
      Schema.prototype.virtual = function (name, options) {
      -  var virtuals = this.virtuals;
      -  var parts = name.split('.');
      -  return virtuals[name] = parts.reduce(function (mem, part, i) {
      -    mem[part] || (mem[part] = (i === parts.length-1)
      -                            ? new VirtualType(options, name)
      -                            : {});
      -    return mem[part];
      -  }, this.tree);
      -};

      Parameters:

      Returns:


      Schema#virtualpath(name)

      Returns the virtual type with the given name.

      show code
      Schema.prototype.virtualpath = function (name) {
      -  return this.virtuals[name];
      -};

      Parameters:

      Returns:


      Schema#namedScope()

      These still haven't been fixed. Once they're working we'll make them public again.

      show code
      Schema.prototype.namedScope = function (name, fn) {
      -  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
      -    , newScope = Object.create(namedScopes)
      -    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
      -  allScopes[name] = newScope;
      -  newScope.name = name;
      -  newScope.block = fn;
      -  newScope.query = new Query();
      -  newScope.decorate(namedScopes, {
      -    block0: function (block) {
      -      return function () {
      -        block.call(this.query);
      -        return this;
      -      };
      -    },
      -    blockN: function (block) {
      -      return function () {
      -        block.apply(this.query, arguments);
      -        return this;
      -      };
      -    },
      -    basic: function (query) {
      -      return function () {
      -        this.query.find(query);
      -        return this;
      -      };
      -    }
      -  });
      -  return newScope;
      -};

      Schema.reserved

      Reserved document keys.

      show code
      Schema.reserved = Object.create(null);
      -var reserved = Schema.reserved;
      -reserved.on =
      -reserved.db =
      -reserved.init =
      -reserved.isNew =
      -reserved.errors =
      -reserved.schema =
      -reserved.options =
      -reserved.modelName =
      -reserved.collection =
      -reserved.emit =    // EventEmitter
      -reserved._events = // EventEmitter
      -reserved._pres = reserved._posts = 1 // hooks.js

      Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      - -
      on, emit, _events, db, init, isNew, errors, schema, options, modelName, collection, _pres, _posts
      - -

      NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

      - -
      var schema = new Schema(..);
      - schema.methods.init = function () {} // potentially breaking

      Schema.interpretAsType(path, obj)

      Converts type arguments into Mongoose Types.

      show code
      Schema.interpretAsType = function (path, obj) {
      -  if (obj.constructor.name != 'Object')
      -    obj = { type: obj };
      -
      -  // Get the type making sure to allow keys named "type"
      -  // and default to mixed if not specified.
      -  // { type: { type: String, default: 'freshcut' } }
      -  var type = obj.type && !obj.type.type
      -    ? obj.type
      -    : {};
      -
      -  if ('Object' == type.constructor.name || 'mixed' == type) {
      -    return new Types.Mixed(path, obj);
      -  }
      -
      -  if (Array.isArray(type) || Array == type || 'array' == type) {
      -    // if it was specified through { type } look for `cast`
      -    var cast = (Array == type || 'array' == type)
      -      ? obj.cast
      -      : type[0];
      -
      -    if (cast instanceof Schema) {
      -      return new Types.DocumentArray(path, cast, obj);
      -    }
      -
      -    if ('string' == typeof cast) {
      -      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
      -    } else if (cast && (!cast.type || cast.type.type)
      -                    && 'Object' == cast.constructor.name
      -                    && Object.keys(cast).length) {
      -      return new Types.DocumentArray(path, new Schema(cast), obj);
      -    }
      -
      -    return new Types.Array(path, cast || Types.Mixed, obj);
      -  }
      -
      -  var name = 'string' == typeof type
      -    ? type
      -    : type.name;
      -
      -  if (name) {
      -    name = name.charAt(0).toUpperCase() + name.substring(1);
      -  }
      -
      -  if (undefined == Types[name]) {
      -    throw new TypeError('Undefined type at `' + path +
      -        '`
      -  Did you try nesting Schemas? ' +
      -        'You can only nest using refs or arrays.');
      -  }
      -
      -  return new Types[name](path, obj);
      -};

      Parameters:


      Schema.Types

      The various Mongoose Schema Types.

      show code
      Schema.Types = require('./schema/index');

      Example:

      - -

      Example:

      - -
      var mongoose = require('mongoose');
      -var ObjectId = mongoose.Schema.Types.ObjectId;
      - -

      Types:

      - -
        -
      • String
      • -
      • Number
      • -
      • Boolean | Bool
      • -
      • Array
      • -
      • Buffer
      • -
      • Date
      • -
      • ObjectId | Oid
      • -
      • Mixed
      • -
      - -

      Using this exposed access to the Mixed SchemaType, we can use them in our schema.

      - -
      var Mixed = mongoose.Schema.Types.Mixed;
      -new mongoose.Schema({ _user: Mixed })

      Schema#tree

      Schema as a tree

      - -

      Example:

      - -
      {
      -    '_id'     : ObjectId
      -  , 'nested'  : {
      -        'key' : String
      -    }
      -}

      Schema#paths

      Schema as flat paths

      - -

      Example:

      - -
      {
      -    '_id'        : SchemaType,
      -  , 'nested.key' : SchemaType,
      -}

    • schemadefault.js

      exports#system.profile

      Default model for querying the system.profiles collection.


    • schematype.js

      SchemaType(path, [options], [instance])

      SchemaType constructor

      show code
      function SchemaType (path, options, instance) {
      -  this.path = path;
      -  this.instance = instance;
      -  this.validators = [];
      -  this.setters = [];
      -  this.getters = [];
      -  this.options = options;
      -  this._index = null;
      -  this.selected;
      -
      -  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
      -    // { unique: true, index: true }
      -    if ('index' == i && this._index) continue;
      -
      -    var opts = Array.isArray(options[i])
      -      ? options[i]
      -      : [options[i]];
      -
      -    this[i].apply(this, opts);
      -  }
      -};

      Parameters:


      SchemaType#default(val)

      Sets a default value for this SchemaType.

      show code
      SchemaType.prototype.default = function (val) {
      -  if (1 === arguments.length) {
      -    this.defaultValue = typeof val === 'function'
      -      ? val
      -      : this.cast(val);
      -    return this;
      -  } else if (arguments.length > 1) {
      -    this.defaultValue = utils.args(arguments);
      -  }
      -  return this.defaultValue;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var schema = new Schema({ n: { type: Number, default: 10 })
      -var M = db.model('M', schema)
      -var m = new M;
      -console.log(m.n) // 10
      - -

      Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

      - -

      Example:

      - -
      // values are cast:
      -var schema = new Schema({ aNumber: Number, default: "4.815162342" })
      -var M = db.model('M', schema)
      -var m = new M;
      -console.log(m.aNumber) // 4.815162342
      -
      -// default unique objects for Mixed types:
      -var schema = new Schema({ mixed: Schema.Types.Mixed });
      -schema.path('mixed').default(function () {
      -  return {};
      -});
      -
      -// if we don't use a function to return object literals for Mixed defaults,
      -// each document will receive a reference to the same object literal creating
      -// a "shared" object instance:
      -var schema = new Schema({ mixed: Schema.Types.Mixed });
      -schema.path('mixed').default({});
      -var M = db.model('M', schema);
      -var m1 = new M;
      -m1.mixed.added = 1;
      -console.log(m1.mixed); // { added: 1 }
      -var m2 = new M;
      -console.log(m2.mixed); // { added: 1 }

      SchemaType#index(options)

      Declares the index options for this schematype.

      show code
      SchemaType.prototype.index = function (options) {
      -  this._index = options;
      -  utils.expires(this._index);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var s = new Schema({ name: { type: String, index: true })
      -var s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
      -Schema.path('my.path').index(true);
      -Schema.path('my.date').index({ expires: 60 });
      -Schema.path('my.path').index({ unique: true, sparse: true });
      - -

      NOTE:

      - -

      Indexes are created in the background by default. Specify background: false to override.

      - -

      Direction doesn't matter for single key indexes


      SchemaType#unique(bool)

      Declares an unique index.

      show code
      SchemaType.prototype.unique = function (bool) {
      -  if (!this._index || 'Object' !== this._index.constructor.name) {
      -    this._index = {};
      -  }
      -
      -  this._index.unique = bool;
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var s = new Schema({ name: { type: String, unique: true })
      -Schema.path('name').index({ unique: true });
      - -

      NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.


      SchemaType#sparse(bool)

      Declares a sparse index.

      show code
      SchemaType.prototype.sparse = function (bool) {
      -  if (!this._index || 'Object' !== this._index.constructor.name) {
      -    this._index = {};
      -  }
      -
      -  this._index.sparse = bool;
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var s = new Schema({ name: { type: String, sparse: true })
      -Schema.path('name').index({ sparse: true });

      SchemaType#expires(when)

      Declares a TTL index (rounded to the nearest second) for Date types only.

      show code
      SchemaType.prototype.expires = function (when) {
      -  if (!this._index || 'Object' !== this._index.constructor.name) {
      -    this._index = {};
      -  }
      -
      -  this._index.expires = when;
      -  utils.expires(this._index);
      -  return this;
      -};

      Parameters:

      Returns:

      This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
      This index type is only compatible with Date types.

      - -

      Example:

      - -
      // expire in 24 hours
      -new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
      - -

      expires utilizes the ms module from guille allowing us to use a friendlier syntax:

      - -

      Example:

      - -
      // expire in 24 hours
      -new Schema({ createdAt: { type: Date, expires: '24h' }});
      -
      -// expire in 1.5 hours
      -new Schema({ createdAt: { type: Date, expires: '1.5h' }});
      -
      -// expire in 7 days
      -var schema = new Schema({ createdAt: Date });
      -schema.path('createdAt').expires('7d');

      SchemaType#set(fn)

      Adds a setter to this schematype.

      show code
      SchemaType.prototype.set = function (fn) {
      -  if ('function' != typeof fn)
      -    throw new Error('A setter must be a function.');
      -  this.setters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      function capitalize (val) {
      -  if ('string' != typeof val) val = '';
      -  return val.charAt(0).toUpperCase() + val.substring(1);
      -}
      -
      -// defining within the schema
      -var s = new Schema({ name: { type: String, set: capitalize }})
      -
      -// or by retreiving its SchemaType
      -var s = new Schema({ name: String })
      -s.path('name').set(capitalize)
      - -

      Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      - -

      Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

      - -

      You can set up email lower case normalization easily via a Mongoose setter.

      - -
      function toLower (v) {
      -  return v.toLowerCase();
      -}
      -
      -var UserSchema = new Schema({
      -  email: { type: String, set: toLower }
      -})
      -
      -var User = db.model('User', UserSchema)
      -
      -var user = new User({email: 'AVENUE@Q.COM'})
      -console.log(user.email); // 'avenue@q.com'
      -
      -// or
      -var user = new User
      -user.email = 'Avenue@Q.com'
      -console.log(user.email) // 'avenue@q.com'
      -
      - -

      As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      - -

      NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

      - -
      new Schema({ email: { type: String, lowercase: true }})
      - -

      Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.

      - -
      function inspector (val, schematype) {
      -  if (schematype.options.required) {
      -    return schematype.path + ' is required';
      -  } else {
      -    return val;
      -  }
      -}
      -
      -var VirusSchema = new Schema({
      -  name: { type: String, required: true, set: inspector },
      -  taxonomy: { type: String, set: inspector }
      -})
      -
      -var Virus = db.model('Virus', VirusSchema);
      -var v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });
      -
      -console.log(v.name);     // name is required
      -console.log(v.taxonomy); // Parvovirinae

      SchemaType#get(fn)

      Adds a getter to this schematype.

      show code
      SchemaType.prototype.get = function (fn) {
      -  if ('function' != typeof fn)
      -    throw new Error('A getter must be a function.');
      -  this.getters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      function dob (val) {
      -  if (!val) return val;
      -  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      -}
      -
      -// defining within the schema
      -var s = new Schema({ born: { type: Date, get: dob })
      -
      -// or by retreiving its SchemaType
      -var s = new Schema({ born: Date })
      -s.path('born').get(dob)
      - -

      Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

      - -

      Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

      - -
      function obfuscate (cc) {
      -  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
      -}
      -
      -var AccountSchema = new Schema({
      -  creditCardNumber: { type: String, get: obfuscate }
      -});
      -
      -var Account = db.model('Account', AccountSchema);
      -
      -Account.findById(id, function (err, found) {
      -  console.log(found.creditCardNumber); // '****-****-****-1234'
      -});
      - -

      Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.

      - -
      function inspector (val, schematype) {
      -  if (schematype.options.required) {
      -    return schematype.path + ' is required';
      -  } else {
      -    return schematype.path + ' is not';
      -  }
      -}
      -
      -var VirusSchema = new Schema({
      -  name: { type: String, required: true, get: inspector },
      -  taxonomy: { type: String, get: inspector }
      -})
      -
      -var Virus = db.model('Virus', VirusSchema);
      -
      -Virus.findById(id, function (err, virus) {
      -  console.log(virus.name);     // name is required
      -  console.log(virus.taxonomy); // taxonomy is not
      -})

      SchemaType#validate(obj, [error])

      Adds validator(s) for this document path.

      show code
      SchemaType.prototype.validate = function (obj, error) {
      -  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
      -    this.validators.push([obj, error]);
      -    return this;
      -  }
      -
      -  var i = arguments.length
      -    , arg
      -
      -  while (i--) {
      -    arg = arguments[i];
      -    if (!(arg && 'Object' == arg.constructor.name)) {
      -      var msg = 'Invalid validator. Received (' + typeof arg + ') '
      -        + arg
      -        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
      -
      -      throw new Error(msg);
      -    }
      -    this.validate(arg.validator, arg.msg);
      -  }
      -
      -  return this;
      -};

      Parameters:

      Validators always receive the value to validate as their first argument and must return Boolean. Returning false is interpreted as validation failure.

      - -

      Examples:

      - -
      function validator (val) {
      -  return val == 'something';
      -}
      -
      -new Schema({ name: { type: String, validate: validator }});
      -
      -// with a custom error message
      -
      -var custom = [validator, 'validation failed']
      -new Schema({ name: { type: String, validate: custom }});
      -
      -var many = [
      -    { validator: validator, msg: 'uh oh' }
      -  , { validator: fn, msg: 'failed' }
      -]
      -new Schema({ name: { type: String, validate: many }});
      -
      -// or utilizing SchemaType methods directly:
      -
      -var schema = new Schema({ name: 'string' });
      -schema.path('name').validate(validator, 'validation failed');
      - -

      Asynchronous validation:

      - -

      Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The second argument is an callback function that must be passed either true or false when validation is complete.

      - -
      schema.path('name').validate(function (value, respond) {
      -  doStuff(value, function () {
      -    ...
      -    respond(false); // validation failed
      -  })
      - }, 'my error type');
      - -

      You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.

      - -

      Validation occurs pre('save') or whenever you manually execute document#validate.

      - -

      If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

      - -
      var conn = mongoose.createConnection(..);
      -conn.on('error', handleError);
      -
      -var Product = conn.model('Product', yourSchema);
      -var dvd = new Product(..);
      -dvd.save(); // emits error on the `conn` above
      - -

      If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

      - -
      // registering an error listener on the Model lets us handle errors more locally
      -Product.on('error', handleError);

      SchemaType#required(required)

      Adds a required validator to this schematype.

      show code
      SchemaType.prototype.required = function (required) {
      -  var self = this;
      -
      -  function __checkRequired (v) {
      -    // in here, `this` refers to the validating document.
      -    // no validation when this path wasn't selected in the query.
      -    if ('isSelected' in this &&
      -        !this.isSelected(self.path) &&
      -        !this.isModified(self.path)) return true;
      -    return self.checkRequired(v);
      -  }
      -
      -  if (false === required) {
      -    this.isRequired = false;
      -    this.validators = this.validators.filter(function (v) {
      -      return v[0].name !== '__checkRequired';
      -    });
      -  } else {
      -    this.isRequired = true;
      -    this.validators.push([__checkRequired, 'required']);
      -  }
      -
      -  return this;
      -};

      Parameters:

      • required <Boolean> enable/disable the validator

      Returns:

      Example:

      - -
      var s = new Schema({ born: { type: Date, required: true })
      -// or
      -Schema.path('name').required(true);

      SchemaType#getDefault(scope, init)

      Gets the default value

      show code
      SchemaType.prototype.getDefault = function (scope, init) {
      -  var ret = 'function' === typeof this.defaultValue
      -    ? this.defaultValue.call(scope)
      -    : this.defaultValue;
      -
      -  if (null !== ret && undefined !== ret) {
      -    return this.cast(ret, scope, init);
      -  } else {
      -    return ret;
      -  }
      -};

      Parameters:

      • scope <Object> the scope which callback are executed
      • init <Boolean>

      SchemaType#applySetters(value, scope, init)

      Applies setters

      show code
      SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
      -  if (SchemaType._isRef(this, value, init)) return value;
      -
      -  var v = value
      -    , setters = this.setters
      -    , len = setters.length
      -
      -  if (!len) {
      -    if (null === v || undefined === v) return v;
      -    return init
      -      ? v // if we just initialized we dont recast
      -      : this.cast(v, scope, init, priorVal)
      -  }
      -
      -  while (len--) {
      -    v = setters[len].call(scope, v, this);
      -  }
      -
      -  if (null === v || undefined === v) return v;
      -
      -  // do not cast until all setters are applied #665
      -  v = this.cast(v, scope, init, priorVal);
      -
      -  return v;
      -};

      Parameters:


      SchemaType#applyGetters(value, scope)

      Applies getters to a value

      show code
      SchemaType.prototype.applyGetters = function (value, scope) {
      -  if (SchemaType._isRef(this, value, true)) return value;
      -
      -  var v = value
      -    , getters = this.getters
      -    , len = getters.length;
      -
      -  if (!len) {
      -    return v;
      -  }
      -
      -  while (len--) {
      -    v = getters[len].call(scope, v, this);
      -  }
      -
      -  return v;
      -};

      Parameters:


      SchemaType#select(val)

      Sets default select() behavior for this path.

      show code
      SchemaType.prototype.select = function select (val) {
      -  this.selected = !! val;
      -}

      Parameters:

      Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

      - -

      Example:

      - -
      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      -T.find(..); // field x will always be selected ..
      -// .. unless overridden;
      -T.find().select('-x').exec(callback);

      SchemaType#doValidate(value, callback, scope)

      Performs a validation of value using the validators declared for this SchemaType.

      show code
      SchemaType.prototype.doValidate = function (value, fn, scope) {
      -  var err = false
      -    , path = this.path
      -    , count = this.validators.length;
      -
      -  if (!count) return fn(null);
      -
      -  function validate (val, msg) {
      -    if (err) return;
      -    if (val === undefined || val) {
      -      --count || fn(null);
      -    } else {
      -      fn(err = new ValidatorError(path, msg));
      -    }
      -  }
      -
      -  this.validators.forEach(function (v) {
      -    var validator = v[0]
      -      , message   = v[1];
      -
      -    if (validator instanceof RegExp) {
      -      validate(validator.test(value), message);
      -    } else if ('function' === typeof validator) {
      -      if (2 === validator.length) {
      -        validator.call(scope, value, function (val) {
      -          validate(val, message);
      -        });
      -      } else {
      -        validate(validator.call(scope, value), message);
      -      }
      -    }
      -  });
      -};

      Parameters:


      SchemaType._isRef(self, value, init)

      Determines if value is a valid Reference.

      show code
      SchemaType._isRef = function (self, value, init) {
      -  if (init && self.options && self.options.ref) {
      -    if (null == value) return true;
      -    if (value._id && value._id.constructor.name === self.instance) return true;
      -  }
      -
      -  return false;
      -}

      Parameters:

      Returns:


    • types/array.js

      MongooseArray(values, path, doc)

      Mongoose Array constructor.

      show code
      function MongooseArray (values, path, doc) {
      -  var arr = [];
      -  arr.push.apply(arr, values);
      -  arr.__proto__ = MongooseArray.prototype;
      -
      -  arr._atomics = {};
      -  arr.validators = [];
      -  arr._path = path;
      -
      -  if (doc) {
      -    arr._parent = doc;
      -    arr._schema = doc.schema.path(path);
      -  }
      -
      -  return arr;
      -};

      Parameters:

      Inherits:

      NOTE:

      - -

      Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


      MongooseArray#_cast(value)

      Casts a member based on this arrays schema.

      show code
      MongooseArray.prototype._cast = function (value) {
      -  var cast = this._schema.caster.cast
      -    , doc = this._parent;
      -
      -  return cast.call(null, value, doc);
      -};

      Parameters:

      Returns:

      • <value> the casted value

      MongooseArray#_markModified(embeddedDoc, embeddedPath)

      Marks this array as modified.

      show code
      MongooseArray.prototype._markModified = function (elem, embeddedPath) {
      -  var parent = this._parent
      -    , dirtyPath;
      -
      -  if (parent) {
      -    dirtyPath = this._path;
      -
      -    if (arguments.length) {
      -      if (null != embeddedPath) {
      -        // an embedded doc bubbled up the change
      -        dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
      -      } else {
      -        // directly set an index
      -        dirtyPath = dirtyPath + '.' + elem;
      -      }
      -
      -    }
      -    parent.markModified(dirtyPath);
      -  }
      -
      -  return this;
      -};

      Parameters:

      • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
      • embeddedPath <String> the path which changed in the embeddedDoc

      If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


      MongooseArray#_registerAtomic(op, val)

      Register an atomic operation with the parent.

      show code
      MongooseArray.prototype._registerAtomic = function (op, val) {
      -  if ('$set' == op) {
      -    // $set takes precedence over all other ops.
      -    // mark entire array modified.
      -    this._atomics = { $set: val };
      -    return this;
      -  }
      -
      -  var atomics = this._atomics;
      -
      -  // reset pop/shift after save
      -  if ('$pop' == op && !('$pop' in atomics)) {
      -    var self = this;
      -    this._parent.once('save', function () {
      -      self._popped = self._shifted = null;
      -    });
      -  }
      -
      -  // check for impossible $atomic combos (Mongo denies more than one
      -  // $atomic op on a single path
      -  if (this._atomics.$set ||
      -      Object.keys(atomics).length && !(op in atomics)) {
      -    // a different op was previously registered.
      -    // save the entire thing.
      -    this._atomics = { $set: this };
      -    return this;
      -  }
      -
      -  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
      -    atomics[op] || (atomics[op] = []);
      -    atomics[op] = atomics[op].concat(val);
      -  } else if (op === '$pullDocs') {
      -    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
      -      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
      -    selector['$in'] = selector['$in'].concat(val);
      -  } else {
      -    atomics[op] = val;
      -  }
      -
      -  return this;
      -};

      Parameters:


      MongooseArray#hasAtomics()

      Returns the number of pending atomic operations to send to the db for this array.

      show code
      MongooseArray.prototype.hasAtomics = function hasAtomics () {
      -  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
      -    return 0;
      -  }
      -
      -  return Object.keys(this._atomics).length;
      -}

      Returns:


      MongooseArray#push([args...])

      Wraps Array#push with proper change tracking.

      show code
      MongooseArray.prototype.push = function () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , ret = [].push.apply(this, values);
      -
      -  // $pushAll might be fibbed (could be $push). But it makes it easier to
      -  // handle what could have been $push, $pushAll combos
      -  this._registerAtomic('$pushAll', values);
      -  this._markModified();
      -  return ret;
      -};

      Parameters:


      MongooseArray#nonAtomicPush([args...])

      Pushes items to the array non-atomically.

      show code
      MongooseArray.prototype.nonAtomicPush = function () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , ret = [].push.apply(this, values);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -};

      Parameters:

      • [args...] <any>

      NOTE:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$pop()

      Pops the array atomically at most one time per document save().

      NOTE:

      - -

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      - -
      doc.array = [1,2,3];
      -
      - var popped = doc.array.$pop();
      - console.log(popped); // 3
      - console.log(doc.array); // [1,2]
      -
      - // no affect
      - popped = doc.array.$pop();
      - console.log(doc.array); // [1,2]
      -
      - doc.save(function (err) {
      -   if (err) return handleError(err);
      -
      -   // we saved, now $pop works again
      -   popped = doc.array.$pop();
      -   console.log(popped); // 2
      -   console.log(doc.array); // [1]
      - })

      MongooseArray#pop()

      Wraps Array#pop with proper change tracking.

      show code
      MongooseArray.prototype.pop = function () {
      -  var ret = [].pop.call(this);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -};

      Note:

      - -

      marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$shift()

      Atomically shifts the array at most one time per document save().

      NOTE:

      - -

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      - -
      doc.array = [1,2,3];
      -
      - var shifted = doc.array.$shift();
      - console.log(shifted); // 1
      - console.log(doc.array); // [2,3]
      -
      - // no affect
      - shifted = doc.array.$shift();
      - console.log(doc.array); // [2,3]
      -
      - doc.save(function (err) {
      -   if (err) return handleError(err);
      -
      -   // we saved, now $shift works again
      -   shifted = doc.array.$shift();
      -   console.log(shifted ); // 2
      -   console.log(doc.array); // [3]
      - })

      MongooseArray#shift()

      Wraps Array#shift with proper change tracking.

      show code
      MongooseArray.prototype.shift = function () {
      -  var ret = [].shift.call(this);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -};

      Example:

      - -
      doc.array = [2,3];
      -var res = doc.array.shift();
      -console.log(res) // 2
      -console.log(doc.array) // [3]
      - -

      Note:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#remove([args...])

      Removes items from an array atomically

      show code
      MongooseArray.prototype.remove = function () {
      -  var args = [].map.call(arguments, this._cast, this);
      -  if (args.length == 1)
      -    this.pull(args[0]);
      -  else
      -    this.pull.apply(this, args);
      -  return args;
      -};

      Parameters:

      • [args...] <Object> values to remove

      Examples:

      - -
      doc.array.remove(ObjectId)
      -doc.array.remove('tag 1', 'tag 2')

      MongooseArray#pull([args...])

      Pulls items from the array atomically.

      show code
      MongooseArray.prototype.pull = function () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , cur = this._parent.get(this._path)
      -    , i = cur.length
      -    , mem;
      -
      -  while (i--) {
      -    mem = cur[i];
      -    if (mem instanceof EmbeddedDocument) {
      -      if (values.some(function (v) { return v.equals(mem); } )) {
      -        [].splice.call(cur, i, 1);
      -      }
      -    } else if (~cur.indexOf.call(values, mem)) {
      -      [].splice.call(cur, i, 1);
      -    }
      -  }
      -
      -  if (values[0] instanceof EmbeddedDocument) {
      -    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
      -  } else {
      -    this._registerAtomic('$pullAll', values);
      -  }
      -
      -  this._markModified();
      -  return this;
      -};

      Parameters:

      • [args...] <any>

      MongooseArray#splice()

      Wraps Array#splice with proper change tracking and casting.

      show code
      MongooseArray.prototype.splice = function splice () {
      -  var ret, vals, i;
      -
      -  if (arguments.length) {
      -    vals = [];
      -    for (i = 0; i < arguments.length; ++i) {
      -      vals[i] = i < 2
      -        ? arguments[i]
      -        : this._cast(arguments[i]);
      -    }
      -    ret = [].splice.apply(this, vals);
      -    this._registerAtomic('$set', this);
      -    this._markModified();
      -  }
      -
      -  return ret;
      -}

      Note:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#unshift()

      Wraps Array#unshift with proper change tracking.

      show code
      MongooseArray.prototype.unshift = function () {
      -  var values = [].map.call(arguments, this._cast, this);
      -  [].unshift.apply(this, values);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return this.length;
      -};

      Note:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#sort()

      Wraps Array#sort with proper change tracking.

      show code
      MongooseArray.prototype.sort = function () {
      -  var ret = [].sort.apply(this, arguments);
      -  this._registerAtomic('$set', this);
      -  this._markModified();
      -  return ret;
      -}

      NOTE:

      - -

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#addToSet([args...])

      Adds values to the array if not already present.

      show code
      MongooseArray.prototype.addToSet = function addToSet () {
      -  var values = [].map.call(arguments, this._cast, this)
      -    , added = []
      -    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
      -             values[0] instanceof Date ? 'date' :
      -             '';
      -
      -  values.forEach(function (v) {
      -    var found;
      -    switch (type) {
      -      case 'doc':
      -        found = this.some(function(doc){ return doc.equals(v) });
      -        break;
      -      case 'date':
      -        var val = +v;
      -        found = this.some(function(d){ return +d === val });
      -        break;
      -      default:
      -        found = ~this.indexOf(v);
      -    }
      -
      -    if (!found) {
      -      [].push.call(this, v);
      -      this._registerAtomic('$addToSet', v);
      -      this._markModified();
      -      [].push.call(added, v);
      -    }
      -  }, this);
      -
      -  return added;
      -};

      Parameters:

      • [args...] <any>

      Returns:

      • <Array> the values that were added

      Example:

      - -
      console.log(doc.array) // [2,3,4]
      -var added = doc.array.addToSet(4,5);
      -console.log(doc.array) // [2,3,4,5]
      -console.log(added)     // [5]

      MongooseArray#set()

      Sets the casted val at index i and marks the array modified.

      show code
      MongooseArray.prototype.set = function set (i, val) {
      -  this[i] = this._cast(val);
      -  this._markModified(i);
      -  return this;
      -}

      Returns:

      Example:

      - -
      // given documents based on the following
      -var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
      -
      -var doc = new Doc({ array: [2,3,4] })
      -
      -console.log(doc.array) // [2,3,4]
      -
      -doc.array.set(1,"5");
      -console.log(doc.array); // [2,5,4] // properly cast to number
      -doc.save() // the change is saved
      -
      -// VS not using array#set
      -doc.array[1] = "5";
      -console.log(doc.array); // [2,"5",4] // no casting
      -doc.save() // change is not saved

      MongooseArray#toObject(options)

      Returns a native js Array.

      show code
      MongooseArray.prototype.toObject = function (options) {
      -  if (options && options.depopulate && this[0] instanceof Document) {
      -    return this.map(function (doc) {
      -      return doc._id;
      -    });
      -  }
      -
      -  // return this.slice()?
      -  return this.map(function (doc) {
      -    return doc;
      -  });
      -};

      Parameters:

      Returns:


      MongooseArray#inspect()

      Helper for console.log

      show code
      MongooseArray.prototype.inspect = function () {
      -  return '[' + this.map(function (doc) {
      -    return ' ' + doc;
      -  }) + ' ]';
      -};

      MongooseArray#indexOf(obj)

      Return the index of obj or -1 if not found.

      show code
      MongooseArray.prototype.indexOf = function indexOf (obj) {
      -  if (obj instanceof ObjectId) obj = obj.toString();
      -  for (var i = 0, len = this.length; i < len; ++i) {
      -    if (obj == this[i])
      -      return i;
      -  }
      -  return -1;
      -};

      Parameters:

      • obj <Object> the item to look for

      Returns:


      MongooseArray#_parent

      Parent owner document


      MongooseArray#_atomics

      Stores a queue of atomic operations to perform


    • types/buffer.js

      MongooseBuffer(value, encode, offset)

      Mongoose Buffer constructor.

      show code
      function MongooseBuffer (value, encode, offset) {
      -  var length = arguments.length;
      -  var val;
      -
      -  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
      -    val = 0;
      -  } else {
      -    val = value;
      -  }
      -
      -  var encoding;
      -  var path;
      -  var doc;
      -
      -  if (Array.isArray(encode)) {
      -    // internal casting
      -    path = encode[0];
      -    doc = encode[1];
      -  } else {
      -    encoding = encode;
      -  }
      -
      -  var buf = new Buffer(val, encoding, offset);
      -  buf.__proto__ = MongooseBuffer.prototype;
      -
      -  // make sure these internal props don't show up in Object.keys()
      -  Object.defineProperties(buf, {
      -      validators: { value: [] }
      -    , _path: { value: path }
      -    , _parent: { value: doc }
      -  });
      -
      -  if (doc && "string" === typeof path) {
      -    Object.defineProperty(buf, '_schema', {
      -        value: doc.schema.path(path)
      -    });
      -  }
      -
      -  return buf;
      -};

      Parameters:

      Inherits:

      Values always have to be passed to the constructor to initialize.


      MongooseBuffer#_markModified()

      Marks this buffer as modified.

      show code
      MongooseBuffer.prototype._markModified = function () {
      -  var parent = this._parent;
      -
      -  if (parent) {
      -    parent.markModified(this._path);
      -  }
      -  return this;
      -};

      MongooseBuffer#write()

      Writes the buffer.

      show code
      MongooseBuffer.prototype.write = function () {
      -  var written = Buffer.prototype.write.apply(this, arguments);
      -
      -  if (written > 0) {
      -    this._markModified();
      -  }
      -
      -  return written;
      -};

      MongooseBuffer#copy(target)

      Copies the buffer.

      show code
      MongooseBuffer.prototype.copy = function (target) {
      -  var ret = Buffer.prototype.copy.apply(this, arguments);
      -
      -  if (target instanceof MongooseBuffer) {
      -    target._markModified();
      -  }
      -
      -  return ret;
      -};

      Parameters:

      Returns:

      Note:

      - -

      Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


      MongooseBuffer#toObject([subtype])

      Converts this buffer to its Binary type representation.

      show code
      MongooseBuffer.prototype.toObject = function (options) {
      -  var subtype = 'number' == typeof options
      -    ? options
      -    : 0x00;
      -  return new Binary(this, subtype);
      -};

      Parameters:

      • [subtype] <Hex>

      Returns:

      SubTypes:

      - -
        -
      • 0x00: Binary/Generic
      • -
      • 0x01: Function
      • -
      • 0x02: Binary (Deprecated, 0x00 is new default)
      • -
      • 0x03: UUID
      • -
      • 0x04: MD5
      • -
      • 0x80: User Defined
      • -

      MongooseBuffer#equals(other)

      Determines if this buffer is equals to other buffer

      show code
      MongooseBuffer.prototype.equals = function (other) {
      -  if (!Buffer.isBuffer(other)) {
      -    return false;
      -  }
      -
      -  if (this.length !== other.length) {
      -    return false;
      -  }
      -
      -  for (var i = 0; i < this.length; ++i) {
      -    if (this[i] !== other[i]) return false;
      -  }
      -
      -  return true;
      -}

      Parameters:

      Returns:


      MongooseBuffer#_parent

      Parent owner document


    • types/documentarray.js

      MongooseDocumentArray(values, path, doc)

      DocumentArray constructor

      show code
      function MongooseDocumentArray (values, path, doc) {
      -  var arr = [];
      -
      -  // Values always have to be passed to the constructor to initialize, since
      -  // otherwise MongooseArray#push will mark the array as modified to the parent.
      -  arr.push.apply(arr, values);
      -  arr.__proto__ = MongooseDocumentArray.prototype;
      -
      -  arr._atomics = {};
      -  arr.validators = [];
      -  arr._path = path;
      -
      -  if (doc) {
      -    arr._parent = doc;
      -    arr._schema = doc.schema.path(path);
      -    doc.on('save', arr.notify('save'));
      -    doc.on('isNew', arr.notify('isNew'));
      -  }
      -
      -  return arr;
      -};

      Parameters:

      Inherits:


      MongooseDocumentArray#_cast()

      Overrides MongooseArray#cast

      show code
      MongooseDocumentArray.prototype._cast = function (value) {
      -  if (value instanceof this._schema.casterConstructor)
      -    return value;
      -
      -  return new this._schema.casterConstructor(value, this);
      -};

      MongooseDocumentArray#id(id)

      Searches array items for the first document with a matching _id.

      show code
      MongooseDocumentArray.prototype.id = function (id) {
      -  var casted
      -    , _id;
      -
      -  try {
      -    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
      -  } catch (e) {
      -    casted = null;
      -  }
      -
      -  for (var i = 0, l = this.length; i < l; i++) {
      -    _id = this[i].get('_id');
      -    if (!(_id instanceof ObjectId)) {
      -      if (String(id) == _id)
      -        return this[i];
      -    } else {
      -      if (casted == _id)
      -        return this[i];
      -    }
      -  }
      -
      -  return null;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var embeddedDoc = m.array.id(some_id);

      MongooseDocumentArray#toObject()

      Returns a native js Array of plain js objects

      show code
      MongooseDocumentArray.prototype.toObject = function () {
      -  return this.map(function (doc) {
      -    return doc && doc.toObject() || null;
      -  });
      -};

      Returns:

      NOTE:

      - -

      Each sub-document is converted to a plain object by calling its #toObject method.


      MongooseDocumentArray#inspect()

      Helper for console.log

      show code
      MongooseDocumentArray.prototype.inspect = function () {
      -  return '[' + this.map(function (doc) {
      -    if (doc) {
      -      return doc.inspect
      -        ? doc.inspect()
      -        : util.inspect(doc)
      -    }
      -    return 'null'
      -  }).join('
      -') + ']';
      -};

      MongooseDocumentArray#create(obj)

      Creates a subdocument casted to this schema.

      show code
      MongooseDocumentArray.prototype.create = function (obj) {
      -  return new this._schema.casterConstructor(obj);
      -}

      Parameters:

      • obj <Object> the value to cast to this arrays SubDocument schema

      This is the same subdocument constructor used for casting.


      MongooseDocumentArray#notify(event)

      Creates a fn that notifies all child docs of event.

      show code
      MongooseDocumentArray.prototype.notify = function notify (event) {
      -  var self = this;
      -  return function notify (val) {
      -    var i = self.length;
      -    while (i--) {
      -      if (!self[i]) continue;
      -      self[i].emit(event, val);
      -    }
      -  }
      -}

      Parameters:

      Returns:


    • types/embedded.js

      EmbeddedDocument(obj, parentArr, skipId)

      EmbeddedDocument constructor.

      show code
      function EmbeddedDocument (obj, parentArr, skipId, fields) {
      -  if (parentArr) {
      -    this.__parentArray = parentArr;
      -    this.__parent = parentArr._parent;
      -  } else {
      -    this.__parentArray = undefined;
      -    this.__parent = undefined;
      -  }
      -
      -  Document.call(this, obj, fields, skipId);
      -
      -  var self = this;
      -  this.on('isNew', function (val) {
      -    self.isNew = val;
      -  });
      -};

      Parameters:

      Inherits:


      EmbeddedDocument#markModified(path)

      Marks the embedded doc modified.

      show code
      EmbeddedDocument.prototype.markModified = function (path) {
      -  if (!this.__parentArray) return;
      -
      -  this._activePaths.modify(path);
      -
      -  if (this.isNew) {
      -    // Mark the WHOLE parent array as modified
      -    // if this is a new document (i.e., we are initializing
      -    // a document),
      -    this.__parentArray._markModified();
      -  } else
      -    this.__parentArray._markModified(this, path);
      -};

      Parameters:

      • path <String> the path which changed

      Example:

      - -
      var doc = blogpost.comments.id(hexstring);
      -doc.mixed.type = 'changed';
      -doc.markModified('mixed.type');

      EmbeddedDocument#save([fn])

      Used as a stub for hooks.js

      show code
      EmbeddedDocument.prototype.save = function(fn) {
      -  if (fn)
      -    fn(null);
      -  return this;
      -};

      Parameters:

      Returns:

      NOTE:

      - -

      This is a no-op. Does not actually save the doc to the db.


      EmbeddedDocument#remove([fn])

      Removes the subdocument from its parent array.

      show code
      EmbeddedDocument.prototype.remove = function (fn) {
      -  if (!this.__parentArray) return this;
      -
      -  var _id;
      -  if (!this.willRemove) {
      -    _id = this._doc._id;
      -    if (!_id) {
      -      throw new Error('For your own good, Mongoose does not know ' + 
      -                      'how to remove an EmbeddedDocument that has no _id');
      -    }
      -    this.__parentArray.pull({ _id: _id });
      -    this.willRemove = true;
      -  }
      -
      -  if (fn)
      -    fn(null);
      -
      -  return this;
      -};

      Parameters:


      EmbeddedDocument#update()

      Override #update method of parent documents.

      show code
      EmbeddedDocument.prototype.update = function () {
      -  throw new Error('The #update method is not available on EmbeddedDocuments');
      -}

      EmbeddedDocument#inspect()

      Helper for console.log

      show code
      EmbeddedDocument.prototype.inspect = function () {
      -  return inspect(this.toObject());
      -};

      EmbeddedDocument#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
      -  if (!this.__parent) return false;
      -  var index = this.__parentArray.indexOf(this);
      -  var parentPath = this.__parentArray._path;
      -  var fullPath = [parentPath, index, path].join('.');
      -  this.__parent.invalidate(fullPath, err);
      -  if (first)
      -    this._validationError = ownerDocument(this)._validationError;
      -  return true;
      -}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> error which states the reason `path` was invalid

      Returns:


      EmbeddedDocument#ownerDocument()

      Returns the top level document of this sub-document.

      show code
      EmbeddedDocument.prototype.ownerDocument = function () {
      -  return ownerDocument(this);
      -}

      Returns:


      EmbeddedDocument#parent()

      Returns this sub-documents parent document.

      show code
      EmbeddedDocument.prototype.parent = function () {
      -  return this.__parent;
      -}

      EmbeddedDocument#parentArray()

      Returns this sub-documents parent array.

      show code
      EmbeddedDocument.prototype.parentArray = function () {
      -  return this.__parentArray;
      -}

    • types/objectid.js

      ObjectId()

      ObjectId type constructor

      Example

      - -
      var id = new mongoose.Types.ObjectId;

      ObjectId.fromString(str)

      Creates an ObjectId from str

      show code
      ObjectId.fromString;

      Parameters:

      Returns:


      ObjectId.toString(oid)

      Converts oid to a string.

      show code
      ObjectId.toString;

      Parameters:

      Returns:


    • utils.js

      exports.toCollectionName(name)

      Produces a collection name from model name.

      show code
      exports.toCollectionName = function (name) {
      -  if ('system.profile' === name) return name;
      -  if ('system.indexes' === name) return name;
      -  return pluralize(name.toLowerCase());
      -};

      Parameters:

      Returns:


      exports.pluralization

      Pluralization rules.

      show code
      exports.pluralization = [
      -  [/(m)an$/gi, '$1en'],
      -  [/(pe)rson$/gi, '$1ople'],
      -  [/(child)$/gi, '$1ren'],
      -  [/^(ox)$/gi, '$1en'],
      -  [/(ax|test)is$/gi, '$1es'],
      -  [/(octop|vir)us$/gi, '$1i'],
      -  [/(alias|status)$/gi, '$1es'],
      -  [/(bu)s$/gi, '$1ses'],
      -  [/(buffal|tomat|potat)o$/gi, '$1oes'],
      -  [/([ti])um$/gi, '$1a'],
      -  [/sis$/gi, 'ses'],
      -  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
      -  [/(hive)$/gi, '$1s'],
      -  [/([^aeiouy]|qu)y$/gi, '$1ies'],
      -  [/(x|ch|ss|sh)$/gi, '$1es'],
      -  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
      -  [/([m|l])ouse$/gi, '$1ice'],
      -  [/(quiz)$/gi, '$1zes'],
      -  [/s$/gi, 's'],
      -  [/$/gi, 's']
      -];
      -var rules = exports.pluralization;

      These rules are applied while processing the argument to toCollectionName.


      exports.uncountables

      Uncountable words.

      show code
      exports.uncountables = [
      -  'advice',
      -  'energy',
      -  'excretion',
      -  'digestion',
      -  'cooperation',
      -  'health',
      -  'justice',
      -  'labour',
      -  'machinery',
      -  'equipment',
      -  'information',
      -  'pollution',
      -  'sewage',
      -  'paper',
      -  'money',
      -  'species',
      -  'series',
      -  'rain',
      -  'rice',
      -  'fish',
      -  'sheep',
      -  'moose',
      -  'deer',
      -  'news',
      -  'expertise',
      -  'status',
      -  'media'
      -];
      -var uncountables = exports.uncountables;

      These words are applied while processing the argument to toCollectionName.


      exports.deepEqual(a, b)

      Determines if a and b are deep equal.

      show code
      exports.deepEqual = function deepEqual (a, b) {
      -  if (a === b) return true;
      -
      -  if (a instanceof Date && b instanceof Date)
      -    return a.getTime() === b.getTime();
      -
      -  if (a instanceof ObjectId && b instanceof ObjectId) {
      -    return a.toString() === b.toString();
      -  }
      -
      -  if (a instanceof RegExp && b instanceof RegExp) {
      -    return a.source == b.source &&
      -           a.ignoreCase == b.ignoreCase &&
      -           a.multiline == b.multiline &&
      -           a.global == b.global;
      -  }
      -
      -  if (typeof a !== 'object' && typeof b !== 'object')
      -    return a == b;
      -
      -  if (a === null || b === null || a === undefined || b === undefined)
      -    return false
      -
      -  if (a.prototype !== b.prototype) return false;
      -
      -  // Handle MongooseNumbers
      -  if (a instanceof Number && b instanceof Number) {
      -    return a.valueOf() === b.valueOf();
      -  }
      -
      -  if (Buffer.isBuffer(a)) {
      -    if (!Buffer.isBuffer(b)) return false;
      -    if (a.length !== b.length) return false;
      -    for (var i = 0, len = a.length; i < len; ++i) {
      -      if (a[i] !== b[i]) return false;
      -    }
      -    return true;
      -  }
      -
      -  if (isMongooseObject(a)) a = a.toObject();
      -  if (isMongooseObject(b)) b = b.toObject();
      -
      -  try {
      -    var ka = Object.keys(a),
      -        kb = Object.keys(b),
      -        key, i;
      -  } catch (e) {//happens when one is a string literal and the other isn't
      -    return false;
      -  }
      -
      -  // having the same number of owned properties (keys incorporates
      -  // hasOwnProperty)
      -  if (ka.length != kb.length)
      -    return false;
      -
      -  //the same set of keys (although not necessarily the same order),
      -  ka.sort();
      -  kb.sort();
      -
      -  //~~~cheap key test
      -  for (i = ka.length - 1; i >= 0; i--) {
      -    if (ka[i] != kb[i])
      -      return false;
      -  }
      -
      -  //equivalent values for every corresponding key, and
      -  //~~~possibly expensive deep test
      -  for (i = ka.length - 1; i >= 0; i--) {
      -    key = ka[i];
      -    if (!deepEqual(a[key], b[key])) return false;
      -  }
      -
      -  return true;
      -};

      Parameters:

      • a <any> a value to compare to `b`
      • b <any> a value to compare to `a`

      Returns:

      Modified from node/lib/assert.js


      exports.clone(obj, options)

      Object clone with Mongoose natives support.

      show code
      exports.clone = function clone (obj, options) {
      -  if (obj === undefined || obj === null)
      -    return obj;
      -
      -  if (Array.isArray(obj))
      -    return cloneArray(obj, options);
      -
      -  if (isMongooseObject(obj)) {
      -    if (options && options.json && 'function' === typeof obj.toJSON) {
      -      return obj.toJSON(options);
      -    } else {
      -      return obj.toObject(options);
      -    }
      -  }
      -
      -  if ('Object' === obj.constructor.name)
      -    return cloneObject(obj, options);
      -
      -  if ('Date' === obj.constructor.name)
      -    return new obj.constructor(+obj);
      -
      -  if ('RegExp' === obj.constructor.name) {
      -    var flags = [];
      -    if (obj.global) flags.push('g');
      -    if (obj.multiline) flags.push('m');
      -    if (obj.ignoreCase) flags.push('i');
      -    return new RegExp(obj.source, flags.join(''));
      -  }
      -
      -  if (obj instanceof ObjectId)
      -    return new ObjectId(obj.id);
      -
      -  if (obj.valueOf)
      -    return obj.valueOf();
      -};
      -var clone = exports.clone;

      Parameters:

      Returns:

      If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

      - -

      Functions are never cloned.


      exports.options(defaults, options)

      Copies and merges options with defaults.

      show code
      exports.options = function (defaults, options) {
      -  var keys = Object.keys(defaults)
      -    , i = keys.length
      -    , k ;
      -
      -  options = options || {};
      -
      -  while (i--) {
      -    k = keys[i];
      -    if (!(k in options)) {
      -      options[k] = defaults[k];
      -    }
      -  }
      -
      -  return options;
      -};

      Parameters:

      Returns:


      exports.random()

      Generates a random string

      show code
      exports.random = function () {
      -  return Math.random().toString().substr(3);
      -};

      exports.merge(to, from)

      Merges from into to without overwriting existing properties.

      show code
      exports.merge = function merge (to, from) {
      -  var keys = Object.keys(from)
      -    , i = keys.length
      -    , key
      -
      -  while (i--) {
      -    key = keys[i];
      -    if ('undefined' === typeof to[key]) {
      -      to[key] = from[key];
      -    } else {
      -      if (exports.isObject(from[key])) {
      -        merge(to[key], from[key]);
      -      } else {
      -        to[key] = from[key];
      -      }
      -    }
      -  }
      -};

      Parameters:


      exports.isObject(arg)

      Determines if arg is an object.

      show code
      exports.isObject = function (arg) {
      -  return '[object Object]' == toString.call(arg);
      -}

      Parameters:

      Returns:


      exports.args

      A faster Array.prototype.slice.call(arguments) alternative

      show code
      exports.args = sliced;

      exports.tick(callback)

      process.nextTick helper.

      show code
      exports.tick = function tick (callback) {
      -  if ('function' !== typeof callback) return;
      -  return function () {
      -    try {
      -      callback.apply(this, arguments);
      -    } catch (err) {
      -      // only nextTick on err to get out of
      -      // the event loop and avoid state corruption.
      -      process.nextTick(function () {
      -        throw err;
      -      });
      -    }
      -  }
      -}

      Parameters:

      Wraps callback in a try/catch + nextTick.

      - -

      node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


      exports.isMongooseObject(v)

      Returns if v is a mongoose object that has a toObject() method we can use.

      show code
      exports.isMongooseObject = function (v) {
      -  Document || (Document = require('./document'));
      -  MongooseArray || (MongooseArray = require('./types').Array);
      -  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
      -
      -  return v instanceof Document ||
      -         v instanceof MongooseArray ||
      -         v instanceof MongooseBuffer
      -}
      -var isMongooseObject = exports.isMongooseObject;

      Parameters:

      This is for compatibility with libs like Date.js which do foolish things to Natives.


      exports.expires(object)

      Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

      show code
      exports.expires = function expires (object) {
      -  if (!(object && 'Object' == object.constructor.name)) return;
      -  if (!('expires' in object)) return;
      -
      -  var when;
      -  if ('string' != typeof object.expires) {
      -    when = object.expires;
      -  } else {
      -    when = Math.round(ms(object.expires) / 1000);
      -  }
      -  object.expireAfterSeconds = when;
      -  delete object.expires;
      -}
      -
      -exports.readPref = function readPref (pref, tags) {
      -  if (Array.isArray(pref)) {
      -    tags = pref[1];
      -    pref = pref[0];
      -  }
      -
      -  switch (pref) {
      -    case 'p':
      -      pref = 'primary';
      -      break;
      -    case 'pp':
      -      pref = 'primaryPrefered';
      -      break;
      -    case 's':
      -      pref = 'secondary';
      -      break;
      -    case 'sp':
      -      pref = 'secondaryPrefered';
      -      break;
      -    case 'n':
      -      pref = 'nearest';
      -      break;
      -  }
      -
      -  return new ReadPref(pref, tags);
      -}

      Parameters:


    • virtualtype.js

      VirtualType()

      VirtualType constructor

      show code
      function VirtualType (options, name) {
      -  this.path = name;
      -  this.getters = [];
      -  this.setters = [];
      -  this.options = options || {};
      -}

      This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

      - -

      Example:

      - -
      var fullname = schema.virtual('fullname');
      -fullname instanceof mongoose.VirtualType // true

      VirtualType#get(fn)

      Defines a getter.

      show code
      VirtualType.prototype.get = function (fn) {
      -  this.getters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var virtual = schema.virtual('fullname');
      -virtual.get(function () {
      -  return this.name.first + ' ' + this.name.last;
      -});

      VirtualType#set(fn)

      Defines a setter.

      show code
      VirtualType.prototype.set = function (fn) {
      -  this.setters.push(fn);
      -  return this;
      -};

      Parameters:

      Returns:

      Example:

      - -
      var virtual = schema.virtual('fullname');
      -virtual.set(function (v) {
      -  var parts = v.split(' ');
      -  this.name.first = parts[0];
      -  this.name.last = parts[1];
      -});

      VirtualType#applyGetters(value, scope)

      Applies getters to value using optional scope.

      show code
      VirtualType.prototype.applyGetters = function (value, scope) {
      -  var v = value;
      -  for (var l = this.getters.length - 1; l >= 0; l--) {
      -    v = this.getters[l].call(scope, v, this);
      -  }
      -  return v;
      -};

      Parameters:

      Returns:

      • <any> the value after applying all getters

      VirtualType#applySetters(value, scope)

      Applies setters to value using optional scope.

      show code
      VirtualType.prototype.applySetters = function (value, scope) {
      -  var v = value;
      -  for (var l = this.setters.length - 1; l >= 0; l--) {
      -    v = this.setters[l].call(scope, v, this);
      -  }
      -  return v;
      -};

      Parameters:

      Returns:

      • <any> the value after applying all setters

    • collection.js

      Collection(name, conn, opts)

      Abstract Collection constructor

      show code
      function Collection (name, conn, opts) {
      -  this.name = name;
      -  this.conn = conn;
      -  this.buffer = true;
      -  this.queue = [];
      -
      -  if ('number' == typeof opts) opts = { size: opts };
      -  this.opts = opts || {};
      -
      -  if (STATES.connected == this.conn.readyState) {
      -    this.onOpen();
      -  }
      -};

      Parameters:

      • name <String> name of the collection
      • conn <Connection> A MongooseConnection instance
      • opts <Object> optional collection options

      This is the base class that drivers inherit from and implement.


      Collection#onOpen()

      Called when the database connects

      show code
      Collection.prototype.onOpen = function () {
      -  var self = this;
      -  this.buffer = false;
      -  self.doQueue();
      -};

      Collection#onClose()

      Called when the database disconnects

      show code
      Collection.prototype.onClose = function () {
      -  this.buffer = true;
      -};

      Collection#addQueue(name, args)

      Queues a method for later execution when its
      database connection opens.

      show code
      Collection.prototype.addQueue = function (name, args) {
      -  this.queue.push([name, args]);
      -  return this;
      -};

      Parameters:

      • name <String> name of the method to queue
      • args <Array> arguments to pass to the method when executed

      Collection#doQueue()

      Executes all queued methods and clears the queue.

      show code
      Collection.prototype.doQueue = function () {
      -  for (var i = 0, l = this.queue.length; i < l; i++){
      -    this[this.queue[i][0]].apply(this, this.queue[i][1]);
      -  }
      -  this.queue = [];
      -  return this;
      -};

      Collection#ensureIndex()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.ensureIndex = function(){
      -  throw new Error('Collection#ensureIndex unimplemented by driver');
      -};

      Collection#findAndModify()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findAndModify = function(){
      -  throw new Error('Collection#findAndModify unimplemented by driver');
      -};

      Collection#findOne()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findOne = function(){
      -  throw new Error('Collection#findOne unimplemented by driver');
      -};

      Collection#find()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.find = function(){
      -  throw new Error('Collection#find unimplemented by driver');
      -};

      Collection#insert()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.insert = function(){
      -  throw new Error('Collection#insert unimplemented by driver');
      -};

      Collection#save()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.save = function(){
      -  throw new Error('Collection#save unimplemented by driver');
      -};

      Collection#update()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.update = function(){
      -  throw new Error('Collection#update unimplemented by driver');
      -};

      Collection#getIndexes()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.getIndexes = function(){
      -  throw new Error('Collection#getIndexes unimplemented by driver');
      -};

      Collection#mapReduce()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.mapReduce = function(){
      -  throw new Error('Collection#mapReduce unimplemented by driver');
      -};

      Collection#conn

      The Connection instance


      Collection#name

      The collection name


    diff --git a/docs/3.5.x/docs/connections.html b/docs/3.5.x/docs/connections.html deleted file mode 100644 index 35a0bd237b9..00000000000 --- a/docs/3.5.x/docs/connections.html +++ /dev/null @@ -1,32 +0,0 @@ -Mongoose Connecting to MongoDB v3.5.9Fork me on GitHub

    Connections

    We may connect to MongoDB by utilizing the mongoose.connect() method.

    mongoose.connect('mongodb://localhost/myapp');
    -

    This is the minimum needed to connect the myapp database running locally on the default port (27017). We may also specify several more parameters in the uri depending on your environment:

    mongoose.connect('mongodb://username:password@host:port/database?options...');
    -

    See the mongodb connection string spec for more detail.

    Options

    The connect method also accepts an options object which will be passed on to the underlying driver. All options included here take precedence over options passed in the connection string.

    mongoose.connect(uri, options);
    -

    The following option keys are available:

    - -
     db      - passed to the connection db instance
    - server  - passed to the connection server instance(s)
    - replset - passed to the connection ReplSet instance
    - user    - username for authentication (if not specified in uri)
    - pass    - password for authentication (if not specified in uri)
    - -

    See the driver for more information about available options.

    - -

    Note: The server option auto_reconnect is defaulted to true.

    - -

    Note: The db option forceServerObjectId is set to false and cannot be overridden.

    ReplicaSet Connections

    The same method is used to connect to a replica set but instead of passing a single uri we pass a comma delimited list of uris.

    mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port?options...' [, options]);
    -

    NOTE: The database need only be specified in one of the uris.

    Multiple connections

    So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize mongoose.createConnection() which accepts all the arguments already discussed and returns a fresh connection for you.

    var conn = mongoose.createConnection('uri,uri,uri...', options);
    -

    Connection pools

    Each connection, whether created with mongoose.connect or mongoose.createConnection are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options:

    var uri = 'mongodb://localhost/test';
    -mongoose.createConnection(uri, { server: { poolSize: 10 }});
    -
    -// or
    -var uri = 'mongodb://localhost/test?poolSize=10';
    -mongoose.createConnection(uri);
    -

    Next Up

    Now that we've covered connections, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/contributing.html b/docs/3.5.x/docs/contributing.html deleted file mode 100644 index 1cb806450bb..00000000000 --- a/docs/3.5.x/docs/contributing.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose Contributing v3.5.9Fork me on GitHub

    Contributing

    Please read all about contributing here.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/css/api.css b/docs/3.5.x/docs/css/api.css deleted file mode 100644 index 6aaae04b23e..00000000000 --- a/docs/3.5.x/docs/css/api.css +++ /dev/null @@ -1,244 +0,0 @@ -body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; -} -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; -} -code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Consolas, "Liberation Mono", Courier, monospace; -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -h3 { - padding: 20px 15px; - margin-left: -15px; -} -h3 code { - font-weight: normal; -} -hr { - height: 1px; - border: 0 none; - padding: 0; - margin: 60px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) -} -.doclinks hr { - margin: 10px 0; -} -li { - list-style: square; -} -#header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -#header .mongoose { - font-size: 48px; - font-weight: 100; - color: #fff; - letter-spacing: -5px; -} -#links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; -} -#links hr { - margin: 32px 0; -} -#content { - padding: 0; - margin: 0 0 30px 230px; - overflow-x: hidden; -} -#content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -#content .controls:hover { - opacity: .9; -} -#content p { - word-wrap: break-word; -} -#content > ul { - margin: 0; - padding: 0; -} -.private { - display: none; -} -.section { - font-size: 15px; -} -.doclinks li.private a:before, -.doclinks .module.private a:before, -.doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; -} -#content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; -} -.module { - list-style: none; - padding: 30px 0 30px 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; -} -.module > * { - max-width: 700px; -} -.item:last-child { - margin-bottom: 90px; -} -.item:last-child > hr { - display: none; -} -.item h3 a { - color: #333; - text-decoration: none; -} -.property h3 span { - color: #444; -} -.description { - margin-top: 25px; -} -.sourcecode { - display: none; -} -.showcode { - font-size: 12px; - cursor: pointer; - display: none; -} -.load .showcode { - display: block; -} -.types a { - text-decoration: none; -} -@media only screen and (device-width: 768px) { - -} -@media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links hr { - display: none; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - .controls { display: none; } -} diff --git a/docs/3.5.x/docs/css/default.css b/docs/3.5.x/docs/css/default.css deleted file mode 100644 index ccb22728ed3..00000000000 --- a/docs/3.5.x/docs/css/default.css +++ /dev/null @@ -1,135 +0,0 @@ -/* - -Original style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ - -pre code { - display: block; padding: 0.5em; - background: #F0F0F0; -} - -pre code, -pre .ruby .subst, -pre .tag .title, -pre .lisp .title, -pre .clojure .built_in, -pre .nginx .title { - color: black; -} - -pre .string, -pre .title, -pre .constant, -pre .parent, -pre .tag .value, -pre .rules .value, -pre .rules .value .number, -pre .preprocessor, -pre .ruby .symbol, -pre .ruby .symbol .string, -pre .ruby .symbol .keyword, -pre .ruby .symbol .keymethods, -pre .instancevar, -pre .aggregate, -pre .template_tag, -pre .django .variable, -pre .smalltalk .class, -pre .addition, -pre .flow, -pre .stream, -pre .bash .variable, -pre .apache .tag, -pre .apache .cbracket, -pre .tex .command, -pre .tex .special, -pre .erlang_repl .function_or_atom, -pre .markdown .header { - color: #800; -} - -pre .comment, -pre .annotation, -pre .template_comment, -pre .diff .header, -pre .chunk, -pre .markdown .blockquote { - color: #888; -} - -pre .number, -pre .date, -pre .regexp, -pre .literal, -pre .smalltalk .symbol, -pre .smalltalk .char, -pre .go .constant, -pre .change, -pre .markdown .bullet, -pre .markdown .link_url { - color: #080; -} - -pre .label, -pre .javadoc, -pre .ruby .string, -pre .decorator, -pre .filter .argument, -pre .localvars, -pre .array, -pre .attr_selector, -pre .important, -pre .pseudo, -pre .pi, -pre .doctype, -pre .deletion, -pre .envvar, -pre .shebang, -pre .apache .sqbracket, -pre .nginx .built_in, -pre .tex .formula, -pre .erlang_repl .reserved, -pre .input_number, -pre .markdown .link_label, -pre .vhdl .attribute, -pre .clojure .attribute { - color: #88F -} - -pre .keyword, -pre .id, -pre .phpdoc, -pre .title, -pre .built_in, -pre .aggregate, -pre .css .tag, -pre .javadoctag, -pre .phpdoc, -pre .yardoctag, -pre .smalltalk .class, -pre .winutils, -pre .bash .variable, -pre .apache .tag, -pre .go .typename, -pre .tex .command, -pre .markdown .strong, -pre .request, -pre .status { - font-weight: bold; -} - -pre .markdown .emphasis { - font-style: italic; -} - -pre .nginx .built_in { - font-weight: normal; -} - -pre .coffeescript .javascript, -pre .xml .css, -pre .xml .javascript, -pre .xml .vbscript, -pre .tex .formula { - opacity: 0.5; -} diff --git a/docs/3.5.x/docs/css/guide.css b/docs/3.5.x/docs/css/guide.css deleted file mode 100644 index d18ea6af618..00000000000 --- a/docs/3.5.x/docs/css/guide.css +++ /dev/null @@ -1,332 +0,0 @@ -html, body, #content { - height: 100%; -} -:target::before { - content: ">>> "; - color: #1371C9; - font-weight: bold; - font-size: 20px; -} -.module { - min-height: 100%; - box-sizing: border-box; - overflow-x: hidden; -} -body { - background: #d8e2d8 url(/docs/images/square_bg.png) fixed; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; - font-size: 14px; - line-height: 22px; -} -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: rgba(255,255,255,.8); - border: 1px solid #bbb; - padding:5px; - border-radius: 3px; - box-shadow: 1px 3px 6px #ddd; -} -code { - background: rgba(255,255,255,.8); - color: #333; - border-radius: 3px; - font-size: 13px; - font-family: Consolas, "Liberation Mono", Courier, monospace; - /*text-shadow: 1px 2px 2px #555;*/ -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -h2 { - margin-top: 0; -} -h2 a { - font-size: 12px; - position: relative; - bottom: 3px; - font-weight: normal; -} -h3 { padding-top: 35px; } -h3 code { - font-weight: normal; -} -hr { - display: none; - height: 1px; - border: 0 none; - padding: 0; - margin: 90px 0; - background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) -} -.doclinks hr { - margin: 10px 0; -} -li { - list-style: square; -} -#header { - padding-top: 22px; - padding-bottom: 25px; - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -#header .mongoose { - font-size: 48px; - font-weight: 100; - color: #fff; - letter-spacing: -5px; -} -#links { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 210px; - overflow-x: hidden; - overflow-y: auto; - padding: 15px 0 30px 20px; - border-right: 1px solid #ddd; - background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; -} -#links .schematypes span { - display: none; -} -#content { - padding: 0; - margin: 0 0 0 230px; -} -#content .controls { - padding: 5px 15px 5px 10px; - position: fixed; - background: #fff; - border: 3px solid #eee; - border-radius: 0 0 12px 0; - border-width: 0 3px 3px 10px; - width: 100%; - bottom: 0; - opacity: 0.75; - -webkit-transition-property: opacity; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -#content .controls:hover { - opacity: .9; -} -#content p { - word-wrap: break-word; -} -#content > ul { - margin: 0; - padding: 0; -} -.private { - display: none; -} -.doclinks li.private a:before, -.doclinks .module.private a:before, -.doclinks item.private a:before { - content: "p"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-right: 5px; -} -#content .private h3:after { - content: "private"; - background: #333; - color: #fff; - font-size: 11px; - line-height: 15px; - font-weight: normal; - padding: 0 2px; - border-radius: 3px; - border: 1px solid #333; - display: inline-block; - margin-left: 5px; -} -.module { - list-style: none; - padding: 30px 0 0 30px; - border-color: #eee; - border-width: 9px 10px; - border-style: solid; - background-color: #fff; -} -.module > * { - max-width: 700px; -} -.item { - margin-bottom: 175px; -} -.item h3 a { - color: #333; - text-decoration: none; -} -.property h3 span { - color: #444; -} -.description { - margin-top: 25px; -} -.sourcecode { - display: none; -} -.showcode { - font-size: 12px; - cursor: pointer; - display: none; -} -.load .showcode { - display: block; -} -.types a { - text-decoration: none; -} -li.guide ul { - padding-left: 16px; -} - -.important { - background-color: #FBFF94; - margin-left: 5px; -} -.important p { - padding: 22px; -} - -ul.inthewild { - margin: 30px 0 0 -30px; - padding: 0; - width: 125%; - max-width: 125%; -} -ul.inthewild li { - display: inline-block; - list-style: none; -} -ul.inthewild img { - width: 200px; -} - -@media only screen and (device-width: 768px) { - ul.inthewild { - margin-left: 0px; - } -} - -@media only screen and (max-width: 480px) { - ul.inthewild { - margin-left: 0px; - } - ul.inthewild li { - margin: 5px; - border-width: 2px 2px 0 2px; - border-style: solid; - border-color: #eee; - } - ul.inthewild li img { - width: 140px; - } - h2 a { - white-space: nowrap; - } - #forkbanner { display: none } - #header .mongoose { - font-size: 65px; - text-align: center; - } - html, body, #content { - height: auto; - } - #links { - position: static; - width: auto; - border: 0 none; - border-right: 0 none; - border-bottom: 1px solid #ddd; - background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; - padding: 15px 0; - } - #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - #links ul { padding: 0 10px 0 0; } - #links li { - list-style: none; - display: inline-block; - width: 25%; - text-align: center; - } - #links .home, #links .support, #links .fork { - display: none; - } - .doclinks { - display: none; - } - #content { margin-left: 0; } - .module { - padding-left: 5px; - border-width: 3px; - } - #links li.guide { - display: block; - width: 390px; - margin-bottom: 15px; - } - #links li.guide > a { - display: none; - } - #links li ul li { - width: 44%; - text-align: left; - } - #links li ul li ul li { - width: 95%; - } - #links .plugins, - #links .changelog { - display: none; - } - #links .schematypes span { - display: inline; - } - #links .double { - width: 332px; - } - #links .double > ul { - display: inline; - float: right; - } - #links .double > ul li { - width: 155px; - } -} diff --git a/docs/3.5.x/docs/css/style.css b/docs/3.5.x/docs/css/style.css deleted file mode 100644 index 5e40d383d58..00000000000 --- a/docs/3.5.x/docs/css/style.css +++ /dev/null @@ -1,255 +0,0 @@ -body { - font-family: 'Open Sans', Helvetica, Arial, FreeSans; - color: #333; - -webkit-font-smoothing: antialiased; - -webkit-text-size-adjust: 100%; - padding: 0; - margin: 0; -} - -/* location.hash */ -:target::before { - content: ">>> "; - color: #1371C9; - font-weight: bold; - font-size: 20px; -} -/* ignore home page hash */ -#production:target::before { - content: ""; - font-size: inherit; -} - -a { - color: #800; - -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; - -webkit-transition-duration: 0.15s; - -webkit-transition-timing-function: ease-out; -} -a:hover { - opacity: 0.8; -} -#wrap { - width: 600px; - margin: 0 auto; - position:relative; -} -li { - list-style: square; -} -h1 { - font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; - text-rendering: geometricPrecision; -} -pre { - background: #eee; - padding: 5px; - border-radius: 3px; -} -code { - color: #333; - font-size: 11px; - font-family: Consolas, "Liberation Mono", Courier, monospace; -} -pre code { - border: 0 none; - padding: 1.2em; - overflow-x: auto; -} -#header { - text-align: center; - padding-top: 40px; -} -#header, h2, h3, .tagline, .blurb { - text-transform: lowercase; -} -#header h1 { - margin-top: 0; - margin-bottom: 0; -} -#header h1 a { - text-decoration: none; -} -h2 { - margin: 30px 0; -} -h2 a { - font-size: 11px; - position: relative; - bottom: 4px; -} -#header .mongoose { - font-size: 146px; - font-weight: 100; - text-indent: -23px; -} -.load #header .mongoose { - letter-spacing: -14px; -} -.tagline { - color: #333; - font-size: 25px; - text-shadow: 1px 1px #f8f8f8; - text-align: center; - margin: 7px 0; -} -.blurb { - text-align: center; - font-style: oblique; - font-size: 12px; - margin-bottom: 20px; -} -.tagline a, .blurb a { - text-decoration: none; - color: #800; -} -#links { - margin: 50px 10px 20px; - text-align: center; - position: relative; -} -#links ul { - margin: 0; - padding: 0; -} -#links li { - display: inline-block; - margin: 0 15px; - background-color: #FEFEFE; -} -#links a { - background: #444; - padding: 9px 0px; - border-radius: 3px; - color: white; - width: 180px; - display: inline-block; - text-decoration: none; - text-transform: lowercase; - text-shadow: 1px 1px 7px #222; -} -#follow { - margin-bottom: 38px; - margin-left: 109px; -} -#follow ul { - height: 26px; -} -#follow li { - display: inline-block; - font-size: 12px; - margin-right: 12px; -} -#follow #version { - margin: 0 29px 0 10px; -} -#follow #version span { - position: relative; - top: -4px; -} -#production ul { - padding: 0; -} -#production li { - list-style: none; - overflow: hidden; - display: inline-block; - height: 114px; -} -#production img { - width: 180px; - margin: 10px; -} -#production img#mcds { - width: 134px; - margin: 10px 25px; -} -#production a { - -webkit-transition-property: opacity; - -moz-transition-property: opacity; - -o-transition-property: opacity; - transition-property: opacity; - -webkit-transition-duration: 0.25s; - -moz-transition-duration: 0.25s; - -o-transition-duration: 0.25s; - transition-duration: 0.25s; - opacity: 0.7; -} -#production a:hover { - opacity: 1.0; -} -#footer { - text-align: center; - font-size: 12px; - margin-bottom: 20px; -} -@media only screen and (max-width: 480px) { - #forkbanner { display: none } - #header { - padding-top: 12px; - } - #header .mongoose { - text-align: center; - font-size: 65px; - font-weight: 100; - letter-spacing: -7px; - } - .load #header .mongoose { - letter-spacing: -7px; - } - .tagline { - text-align: center; - font-size: 14px; - } - .tagline a { - text-decoration: none; - } - .blurb { - font-size: 16px; - text-align: justify; - margin-top: 25px; - } - #links { - margin-bottom: 40px; - } - #links li { - padding: 8px 2px; - margin: 0 12px; - } - #links a { - background: #444; - padding: 7px 34px; - font-size: 15px; - } - #follow, #docs { margin-left: 0; } - #follow ul { padding-left: 15px } - #follow li { margin-right: 0px } - #follow #version { - margin-left: 5px; - margin-right: 15px; - } - .module { - padding-left: 5px; - border-width: 3px; - } - #wrap { - width: auto; - padding: 0 5px; - } - #production li { - margin-bottom: 8px; - } - #production a { - opacity: 1; - } - #production img { - width: 175px; - } - .addyourown, .addyourown a { - width: 100%; - } -} - -#wrap.homepage #install code, #wrap.homepage #example code { - font-size: 13px; -} diff --git a/docs/3.5.x/docs/documents.html b/docs/3.5.x/docs/documents.html deleted file mode 100644 index cfb86afdc35..00000000000 --- a/docs/3.5.x/docs/documents.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose Documents v3.5.9Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    -  if (err) return handleError(err);
    -  
    -  tank.size = 'large';
    -  tank.save(function (err) {
    -    if (err) return handleError(err);
    -    res.send(tank);
    -  });
    -});

    This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    -  if (err) return handleError(err);
    -  res.send(tank);
    -});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/faq.html b/docs/3.5.x/docs/faq.html deleted file mode 100644 index f8e0616ab2b..00000000000 --- a/docs/3.5.x/docs/faq.html +++ /dev/null @@ -1,31 +0,0 @@ -Mongoose FAQ v3.5.9Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    -doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    -doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    -new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    -doc.user.remove();// ?
    -doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    - -

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    - -

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    -mongoose.connect(..);
    -mongoose.connection.on('error', handleError);
    -
    -// if connecting on a separate connection
    -var conn = mongoose.createConnection(..);
    -conn.on('error', handleError);
    -

    Something to add?

    - -

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    \ No newline at end of file diff --git a/docs/3.5.x/docs/guide.html b/docs/3.5.x/docs/guide.html deleted file mode 100644 index 47fdc94d50f..00000000000 --- a/docs/3.5.x/docs/guide.html +++ /dev/null @@ -1,200 +0,0 @@ -Mongoose Schemas v3.5.9Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works. -If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    -  title:  String,
    -  author: String,
    -  body:   String,
    -  comments: [{ body: String, date: Date }],
    -  date: { type: Date, default: Date.now },
    -  hidden: Boolean,
    -  meta: {
    -    votes: Number,
    -    favs:  Number
    -  }
    -});

    If you want to add additional keys later, use the Schema#add method.

    -Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. -Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    -
    -animalSchema.methods.findSimilarTypes = function (cb) {
    -  return this.model('Animal').find({ type: this.type }, cb);
    -}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    -var dog = new Animal({ type: 'dog' });
    -
    -dog.findSimilarTypes(function (err, dogs) {
    -  console.log(dogs); // woof
    -});

    Statics

    -Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    -  this.find({ name: new RegExp(name, 'i') }, cb);
    -}
    -
    -var Animal = mongoose.model('Animal', animalSchema);
    -Animal.findByName('fido', function (err, animals) {
    -  console.log(animals);
    -});

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });
    -

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index in your schema. -While nice for development, it is recommended this behavior be disabled in production since index creation can cause a significant performance impact. Disable the behavior by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false);
    -// or
    -new Schema({..}, { autoIndex: false });
    -

    See also the Model#ensureIndexes method.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    -  name: {
    -    first: String,
    -    last: String
    -  }
    -});
    -
    -var Person = mongoose.model('Person', personSchema);
    -
    -var bad = new Person({
    -    name: { first: 'Walter', last: 'White' }
    -});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    -  return this.name.first + ' ' + this.name.last;
    -});

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full); // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    -  var split = name.split(' ');
    -  this.name.first = split[0];
    -  this.name.last = split[1];
    -});
    -
    -...
    -
    -mad.name.full = 'Breaking Bad';
    -console.log(mad.name.first); // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    -
    -// or
    -
    -var schema = new Schema({..});
    -schema.set(option, value);
    -

    Valid options:

    - -

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false });
    -var Clock = mongoose.model('Clock', schema);
    -Clock.ensureIndexes(callback);
    -

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 });

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });
    -

    option: collection

    Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Set this option if you need a different name for your collection.

    var dataSchema = new Schema({..}, { collection: 'data' });
    -

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    -var schema = new Schema({ name: String });
    -var Page = mongoose.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p.id); // '50341373e894ad16347efe01'
    -
    -// disabled id
    -var schema = new Schema({ name: String }, { id: false });
    -var Page = mongoose.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p.id); // undefined
    -

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    - -

    Pass this option during schema construction to prevent documents from getting an _id auto created by Mongoose (parent documents will still have an _id created by MongoDB when inserted).

    // default behavior
    -var schema = new Schema({ name: String });
    -var Page = mongoose.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
    -
    -// disabled _id
    -var schema = new Schema({ name: String }, { _id: false });
    -var Page = mongoose.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p); // { name: 'mongodb.org' }
    -// MongoDB will create the _id when inserted
    -p.save(function (err) {
    -  if (err) return handleError(err);
    -  Page.findById(p, function (err, doc) {
    -    if (err) return handleError(err);
    -    console.log(doc); // { name: 'mongodb.org', _id: '50341373e894ad16347efe12' }
    -  })
    -})
    -

    option: read

    Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

    var schema = new Schema({..}, { read: 'primary' });            // also aliased as 'p'
    -var schema = new Schema({..}, { read: 'primaryPreferred' });   // aliased as 'pp'
    -var schema = new Schema({..}, { read: 'secondary' });          // aliased as 's'
    -var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp'
    -var schema = new Schema({..}, { read: 'nearest' });            // aliased as 'n'
    -

    The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'.

    - -

    The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

    - -

    NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

    // pings the replset members periodically to track network latency
    -// now `nearest` works as intended
    -var options = { replset: { strategy: 'ping' }};
    -mongoose.connect(uri, options);
    -
    -var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
    -mongoose.model('JellyBean', schema);
    -

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    -new Schema({ .. }, { safe: safe });
    -

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. -By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    - -

    **NOTE: this setting overrides any setting specified by passing db options while creating a connection.

    - -

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
    -new Schema({ .. }, { safe: safe });
    -

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    -

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: strict

    The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.

    var thingSchema = new Schema({..})
    -var Thing = mongoose.model('Thing', schemaSchema);
    -var thing = new Thing({ iAmNotInTheSchema: true });
    -thing.save(); // iAmNotInTheSchema is not saved to the db
    -
    -// set to false..
    -var thingSchema = new Schema({..}, { strict: false });
    -var thing = new Thing({ iAmNotInTheSchema: true });
    -thing.save(); // iAmNotInTheSchema is now saved to the db!!
    -

    This also affects the use of doc.set() to set a property value.

    var thingSchema = new Schema({..})
    -var Thing = mongoose.model('Thing', schemaSchema);
    -var thing = new Thing;
    -thing.set('iAmNotInTheSchema', true);
    -thing.save(); // iAmNotInTheSchema is not saved to the db
    -

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = mongoose.model('Thing');
    -var thing = new Thing(doc, true);  // enables strict mode
    -var thing = new Thing(doc, false); // disables strict mode
    -

    The strict option may also be set to "throw" which will cause errors to be produced instead of dropping the bad data.

    NOTE: do not set to false unless you have good reason.

    - -

    NOTE: in mongoose v2 the default was false.

    - -

    NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.

    var thingSchema = new Schema({..})
    -var Thing = mongoose.model('Thing', schemaSchema);
    -var thing = new Thing;
    -thing.iAmNotInTheSchema = true;
    -thing.save(); // iAmNotInTheSchema is never saved to the db
    -

    option: toJSON

    Exactly the same as the toObject option but only applies when the documents toJSON method is called.

    var schema = new Schema({ name: String });
    -schema.path('name').get(function (v) {
    -  return v + ' is my name';
    -});
    -schema.set('toJSON', { getters: true, virtuals: false });
    -var M = mongoose.model('Person', schema);
    -var m = new M({ name: 'Max Headroom' });
    -console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
    -console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    -// since we know toJSON is called whenever a js object is stringified:
    -console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
    -

    To see all available toJSON/toObject options, read this.

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    - -

    To have all virtuals show up in your console.log output, set the toObject option to { getters: true }:

    var schema = new Schema({ name: String });
    -schema.path('name').get(function (v) {
    -  return v + ' is my name';
    -});
    -schema.set('toObject', { getters: true });
    -var M = mongoose.model('Person', schema);
    -var m = new M({ name: 'Max Headroom' });
    -console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    -

    To see all available toObject options, read this.

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    -var Thing = mongoose.model('Thing', schema);
    -var thing = new Thing({ name: 'mongoose v3' });
    -thing.save(); // { __v: 0, name: 'mongoose v3' }
    -
    -// customized versionKey
    -new Schema({..}, { versionKey: '_somethingElse' })
    -var Thing = mongoose.model('Thing', schema);
    -var thing = new Thing({ name: 'mongoose v3' });
    -thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    -

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false });
    -var Thing = mongoose.model('Thing', schema);
    -var thing = new Thing({ name: 'no versioning please' });
    -thing.save(); // { name: 'no versioning please' }
    -
    -

    Next Up

    Now that we've covered Schemas, let's take a look at SchemaTypes.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/helpers/filters.js b/docs/3.5.x/docs/helpers/filters.js deleted file mode 100644 index 33546a7e805..00000000000 --- a/docs/3.5.x/docs/helpers/filters.js +++ /dev/null @@ -1,20 +0,0 @@ - -var hl = require('highlight.js') - -module.exports = exports = function (jade) { - // add highlighting filter to jade - - jade.filters.js = function (str) { - str = str.replace(/\\n/g, '\n'); - var ret = hl.highlight('javascript', str).value; - var code = '
    ' + ret.replace(/\n/g, '\\n') + '
    '; - return code; - } - - jade.filters.bash = function (str) { - var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; - var code = '
    ' + ret + '
    '; - return code - } - -} diff --git a/docs/3.5.x/docs/helpers/highlight.js b/docs/3.5.x/docs/helpers/highlight.js deleted file mode 100644 index 8aca9b9e222..00000000000 --- a/docs/3.5.x/docs/helpers/highlight.js +++ /dev/null @@ -1,11 +0,0 @@ - -var h = require('highlight.js') - -function hl (str) { - str = str.replace(/\\n/g, '\n'); - var ret = h.highlight('javascript', str).value; - var code = '
    ' + ret+ '
    '; - return code; -} - -module.exports = hl; diff --git a/docs/3.5.x/docs/helpers/href.js b/docs/3.5.x/docs/helpers/href.js deleted file mode 100644 index e6d6568b123..00000000000 --- a/docs/3.5.x/docs/helpers/href.js +++ /dev/null @@ -1,8 +0,0 @@ - -module.exports = exports = function (str, char) { - if ('string' != typeof str) return str; - return encodeURIComponent( - str.replace(/\.js$/, '') - .replace(/#/g, char || '-') - ); -} diff --git a/docs/3.5.x/docs/helpers/klass.js b/docs/3.5.x/docs/helpers/klass.js deleted file mode 100644 index 0c4a865b43b..00000000000 --- a/docs/3.5.x/docs/helpers/klass.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = exports = function (str) { - var parts = str.replace(/\.js$/, '').split('/'); - return parts.join('_'); -} diff --git a/docs/3.5.x/docs/helpers/linktype.js b/docs/3.5.x/docs/helpers/linktype.js deleted file mode 100644 index 997e740f671..00000000000 --- a/docs/3.5.x/docs/helpers/linktype.js +++ /dev/null @@ -1,50 +0,0 @@ - -var types = {}; -types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; -types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' -types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' -types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' -types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' -types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' -types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' -types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' -types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' -types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' - -// mongoose -types.ObjectId = '#types_objectid_ObjectId'; -types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; -types.MongooseArray = '#types_array_MongooseArray'; -types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; -types.Query = '#query-js'; -types.QueryStream = '#querystream_QueryStream'; -types.Document = '#document_Document'; -types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; -types.Document = '#document_Document'; -types.Model = '#model_Model'; -types.Connection = '#connection_Connection'; -types.Collection = '#collection_Collection'; -types.Schema = '#schema_Schema'; -types.Promise = '#promise_Promise'; -types.Mongoose = '#index_Mongoose'; -types.MongooseError = '#error_MongooseError'; -types.Type = '#schematype_SchemaType'; // ? -types.SchemaType = '#schematype_SchemaType'; -types.SchemaArray = '#schema_array_SchemaArray'; -types.Mixed = '#schema_mixed_Mixed'; -types.VirtualType = '#virtualtype_VirtualType'; -types.MongooseBuffer = '#types_buffer_MongooseBuffer'; -types.Buffer = 'http://nodejs.org/api/buffer.html'; - -module.exports= function (type) { - if (types[type]) { - return '' + type + ''; - } - return '' + type + ''; -} - -module.exports.types = types; -module.exports.type = function (str) { - if (types[str]) return types[str]; - return str; -} diff --git a/docs/3.5.x/docs/images/apps/attictv.png b/docs/3.5.x/docs/images/apps/attictv.png deleted file mode 100644 index 1327f0bd858cf6f002a077a9aafba1217ce38e9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42666 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 Cl*SPN diff --git a/docs/3.5.x/docs/images/apps/calllist.png b/docs/3.5.x/docs/images/apps/calllist.png deleted file mode 100644 index 824fa428eb2de2a237b37ada591cc7056d68f399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33502 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 $5C9j=SSd5$;KOc+eQQ2^5$rlF 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 diff --git a/docs/3.5.x/docs/images/apps/cldfy.png b/docs/3.5.x/docs/images/apps/cldfy.png deleted file mode 100644 index c44ca3525daa7b847ab2869d44a00ebae852646d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9773 zcmeIX<8vm=6Ym{wY}>}hwl}tI+qq(Hvazn%w#|)k#n#5QdG6oy`~~OznXc(?&AjQV z=}%Sn%tR|IN+ZGJ!-Ii=A<4=}sQ#xT|IJufnEyPD_Occj7|ywkxVW;7nFAP@_E4%0 zw7P~;Tb`REdis@AXIDuVzvSUOk|91c8Y&$$r3AQ&2$afCIy6)X%)}&RObKvs$zibK z1EQZ_JMX>E%X&`BnY?{npj<(}r)`XPeXvzW3~_Nt6MV3ckRe&F2tEPD8D@cYEigzP zaEg9Nyh3U1^48Q;yceU%3ECjfTo9$FdGNPU!Q%t`Js4P{SbdjOhBRu36J(I>11wcI zWYAjTCr9Bh1<*w?_!{cmQ`V6?!IT`_tK?VuXEJ9DuM>`T$bHp!m|Axf{lcv+vNS`iWF zs~@FpFX03mm#eS?L%nEHPkp!k5G;2D1uzeS}S`feZq6*qdV%biZn@{#~~+R zIKI&MSFv3`2DHS7YAyoemv9KJZ~d5WV!6lrkGKt=;Wu)wueAU5dP?;j6j=`@g1t~- z4F9{dGX9YJkY77spc-sVq)rplNgKjFOZ?iM-C5Yrk zA~*1a_*<+Ex?z`sda>FYLhv#@?kG=q9rw!y@DKb@~m8ZFtibtVUY~V+i>rxh3XN zbX7!Lq^pb+^kXT)R^qYn>T)-bApB*6zIf|3lbpggIBLsi;JZi)Es!@rtwN##GiaJQ z5bSQ|`WhCwOZWXVG6lA{lOpLO(W^A@_+@lHB+3J8me1Pb?@ZL6IeBX?(%>{{#@av2 z68`x?${yc6E7zJ3-q-7Fu3pUGyF?+OgFS^qUJwS{lpGNU$NK~`MSm{R4EF>^28fgP z1RCer8jY>4KUT`+kd;({>~ zz#Bz{cz*m6L;=~tKq)9nY`pbCIP8bftMsTpJYgUJ~~+l!!vg~Fl={)KlDhe*Js zM4%JLPY^PPSreH_AUJ@87Dt;!qlKFYQWQVVk5T4yhqMj35|1wsJ%N6J(GBVqJO2q^ z8ir@AsEwKyl4|0xirE_aJS22O#)GXGp)?TgjOUM48+kpXw2S5q{{_ZU1oj(ZIBZW+ zHa|tBlU6PTVS+$XY`AD%1-hI~ov9Kpdf2L*Zjsy;>5t?>kEUpxmS**+8i*eykx(o<;sw3o51RYRQ1{NdsWEj>U zJ=xqk8G;AD1_0H-I=}Gy>(~tcAZTW0q9%; zmKg5-uHDev=og3&EPsXoSmDSW(jqbpQZ=e3%6rNfvPtqPQakE%nk=df(lRO>axI!R zif0;ODMJ}Uxoyd>-ya0f(8I*=Snzi6!oQ(@i~T;wjHlgJu2z{>`K@}U+Nmm~oLkr} zzoz&aaz_v>f=X$PrVslsOfAe-jK(DCCiHjiucV2LiR3d{4KxkGCDbJvTQ*y8TZc2q z#fC-b#kTVI3LKj;YbYCcn<$Q34oMCL4l|C)=7(ms=Co$fW?-|HHOa!v!oL%!(}z=m z)1=dhQ@+#EQtT!fLl6TH5>X}ldgNW9{_ zAXiUUW>;1h8<$tNLzfm;Cg%k=JLh+oW0y9UzGIVvxg)p(x&xp7roWQ|c7F*5{1V&Z zz0BfgiQfgI{m!1`ZxZk6?tShLZ#{09Zr$#)?n(aD{UgC4#Zbn+!Q!EqWvZvAr97ea z7ONL^HjI)S)27udmpV!PDXOjZlHd%ysfX2+(4iD5mM|B=#MVH4#9~6f#0ee79RB$G z>o3eO>mL2yz@EjP8F~u(I(i~HC%O|QkaC(5gNlGsSoT(~L*`J%L+&$0GXXiJHX(pc zoW_hinRbEkUPDuTS-e%oQ#+2-iquQJR^=+DJEJ@O!{_xF{sI07o(7W-vlTNHQ}%bu zZ-ieTzZ`!J|1z6EoY0&APQ#s9(r~H_&`efFQ0^+^>eI5WTiO2I zvvB6O7=4DbRL0@WvB|+~EpKyYi_SU8v15B{<72B~J8ctV{cdNp^i@nzBR=0z)Kpnj zNl>;?8#&LuD7SLHP`1#vB3veHQ$N~2nm=MZt~_v4Z_XdmUoy}(8bd2 z$<5Jypo6Dfy_4~JVJE%MX<1`{bJ)YZZ}#itGajX$2v)%Pn)Fe0Z$Qrxms`4x!7)oh z&J@pOZELk>6)-NovL8G8Lx~9_0D@-ms9P{}+dkVa>p2E20$c&u{+s{=f1FSE&zV=i zE%zPEqY+X)Vmo0y(Fv|LP8f>L3<65gRT&b|yNXhs>k$R{>QLT?HE= z{07M~?o5!rs~<%eMVxeZ^kNj_?+>&?R1bzsE$|x%sG+b*vx8BHI6;LJMS+|b!Ex3KULZR!na^AMzuQdA zN=(&>Rk#+6l8O`czQtaSj^-vC;RV43Kel3acs4F}K{h|diEKuJ4#32_x>1_x@~geQ zr}L9_oTcKD&H6$^S()3k+xfls-TZy;G09Y*KB7z10{!=y7X-K`uZQnRqR!zD|_dcg9$&01!rWJF` ztUG<_*LLP+=N9%x>n8DfulLUJm;2~ITzZaT&Jap9$%6;bQ_$D?roKt9tLrlHttf4@ zGCs>U#ScH1R;c1y6mc&7Ms-l?D;kG;T$`Cn6W z=f!}B*NpSkMK{p#Jqv`9KVCfHjyLcI{+=EXVp(XMWY&1mGIricH(cT8^sxQV+X8rZ zT{n9hl3$%VvcKaW>NxXRdrgB54G(^P-v$N1e%3c++$BDl-O~J1Y7@2tTp76P zW`2sjHGXp56P&kA?i}`cG3qfX)k4+SSC@Vpf2y>Ub}#o_wF|YOwM1_)ZlbT*e%ZX; zFL};BdD13IZ1%wCC&2spLEb#FCAINDiUSD8nM-GvXOCtZt#58nY2tTPcMjO!o=l#4Pl-?4 zk=iZZ#V{cyr#WNtl2;UYA{~TK8tjB5I&Bq`-UNZaQJ+ByN411R||F!#R*9k^B1o{rc3r7yfMielBUq5s48?V z+BbtR%RwO^QHfXkttC*IlnEU+`m>VmHdm=6_^8w|jD( znK(V%JnVjic)%MGyKRa%7Wf^9jgz*R>%;(XHF??dUQ>S+8-D(^XfZ-RXPd)N%c-Ju zU%ORJRQ>K6`c%5fw6S60)p%Y-kV$aO?ZMTy)3f1vY-nKTq37c_{`nF2Fhhaz(Pd9U z@7d&DCz$EGxpRLb`(G1R#su*A42Luc?Gz6yumb&#=#j>hVl6T=(*RKzS^qH`?Mi%6 z_2%SGWUt`j{d_w}SznCgE^%@wRax+0e`2?5^11%I(=xp_H9bXQl%Sj8WAsSot>WnN zYPLla4{FZ4X4GNod3QZvxL=9fY3%*Mf}z!&$djpay`HqWz5OUm;!gA=JzjV;$Ndvd znqPF+vsy97~$;&2mTz4N;4;Bk_U&Np80a zvit`zEmTK1X4oIeO$oEVuES0;55H#QiY&Y>o+moSA{oqSHEB8Ngf)Ds-T*9`IR@fV z3;GPo{Bp;gS3%p-klkcuiPa6g(LEKBI`uxylHC?bOD^Y_S?U|^UGnelk>;bgG)7kZ zI6Z*OT9|hOWC@}vuP((4=j+>(yY79B3&85=oYs2$ywhADX+Cc~UpXxg10`#U`&eo* z)(BB6nh?4R6C2fppsuhKU)uN2W3*+S5%0{R)glHsr}#(8ZJ7zBIKE!t;e#;4N*#RG zPwkPCsYn_cCBTI4jN!D7&?l1@-L=`5=|CB~@XUO+8XY`yE#oP_utBG@$BhFzc zRy=cyW~=^H#hZ6{o8|Y?o*l~>Zmr&?jHG8>3xCpME|TOQ@#&1NJEkAkL{2sKb~a8u zfh81O>{p`dT7yH?S4q-`@u25yU-UV(#IWa4{ChN+GrcAL95O3KZ@=pc2NH!;?S%Ite6X-_*7PJm zo>3FNE2t~%nJSrFkK($3wj`E(Re4-hO{H$OJKv$KsuW}qW%gjwXrgI_W@2H!Wu9e4 zvS)o*eMo=Iyhpb?y^%beK1f0*g1LyZhxSIc$)HM)Pi;v#!vHSFC=(|unBex@z8q;!i&Y<=A{4m z#D?}0$i~Fc#4!r=(xueF*K5%3X>)8DZ+UD{Yob|I;?s8%*fZaoI{8>Hu{DBq{i?g{ z^CJD1UrVs>W}`IB$2EW zr&b)4a!pgJmRGt|Vr7ZSeyFsk7?;*lblGp>Oxsts;+e)Ah_zrgMl-iDZ!ylX zlCwxR$vdJwbU#Mle;fErpvhZtix(hCyQcbP3T7M-AyYG9MGF~AI*D2}xV=ZeO{!I; zpGTaRV^gxI8!H)qr_Z4MMbAp_z!0boR3}nBU)w185-HMaQnJ(cGqjRKIWbEFAUlO| zQ?nOvSp3}QOmC~NM{J#Fa%=#$P^?b!^YD-G8aM~+vK{|wFnS9b8lZ5*`YZHIlKWxU zx;+Ze^CS^XLl^(PhBdL`~;!odiYH9+}7 zxCs|1<&rP2BCYIEj>kc;4wDmnH7J7XF=aAkFh#A2krf7rEgIn6Xa3i_*K*tO;$?1Y z-eDed022k`rpu;vqyYYmcFo8aYZs9e#ZusuzLejRHWOJ;tP`H?M!P^(BVI#!bRx{N%(QGT`Z9hee&}u)qTc3z565n;GjZ=%tA{}Q zQ2YCFiX`{4g|b(&a7x3aIb$MLrMae{vnkmrkBJq*B2Ud4nHq@_^#k(G3lm9ms`o>` zr7O-@EgIXd+UFhpUWx_h;!{}!k19j{ilVy#v9_80tR6PNFeHZfPGn!~j9?ydUf|;= z=R<^lrb$}hjCFyr%BkC1+r(0TOYfh9>6w~q;T6wM6pE@mY-ez|eDLaE?kGs;UA`0O zYce(&M7Bs7WwJ%&o=BjvAP-?}*r-Y~t(iJoB~eSbrub-K)?5~@gFK%lB14E^L{7iW z?!=9^KWspTe0X&jA@ws2Nx^JUyIh5sPoA-)w{)t^wA_~B{;wvnECm|T=MRqj`%~&D*i0wF4`ZEqcF!%S`^PVxuk|og7f~2AKG7>!7L$p;k|H9(W=q6 zF?O=;veYuEGTaja$)D7qQse53^2G|VinB^j1ER=H4ZW7**ML^g#^Y!(C3h6=nb2OvfyRaSk>6CFK)%4308|)Pg4kdOIbRXE zsQ^mg?>d<%Uarh`AR@_V*=%-#9FiQtOg%`SCpD7^cu&sFX;iZ-XY$wqIeb8sE|ibsBh-wk-wZ@dm3>w&E9tFwRgr%u#gFTjl3ymuV!y_LK|TGin;}O zc3H(}*ar6ALn?|Rf+D0EN91#z;*9_nysY1Rrnct}dx*ANF37n`zVTnq?zamxp&(W{ zDkH^!KQE=v4v+7t7BPqE4805tRf$yy!uo*^b*HsU)fmg-E0J87T=3kz_V`X|4vzL~ z4hHYhZ>JCUXI#w=eE^HmZi%Inx^ZLNmiMiiizDhHUeMudFC&2DuRxZHg=!GPV5 zD_)?Sug$pkE;MJ2nRu>ITvRml8qwl8-p*<{?!NMJ_wUu`=vYta>g^--$lwd0rCT>V z*|9vSD~B6V)$@5sZ*g%acrcagR|~_yPmju~s!9H-4=QQq^!<+G-2K|FE7yRroA4(8PdiZkXY2dR zh|#yC&s#-&{9TLHciQOpL6yB-#V-HOC-L*^>K0SGbICgKB3?t%z zJh>vZYA1)oF~1*h-L%h_ehE*dy3`{h`PAdHvp-MYU~DU^H2w6VQc^?z`4B@wLUzCG z#R%N~#kg2+i3$CI;=0=p4j(?4By}lG@)6?neSfdMvYhB>DD4M;I3Hc>EJZUz3@-RGH2ipaUIRRbZgzG=JAE!7d@SvJ2tI$#P_o&ob+GhbtYQ za}eKqm%dqlPR+Nz!Sk|DGQYkp>u4M1g%a4GPW;MtT1k7%tbefVcWvrxpCMHUN_&}n#wtiRMkTyk*4js!+|JX-Le_*ekt&JklftTqQZ!s&gg98 zoS;uuY;mbujl}!WcRlZS1VNO=hs(1t`C=YXT1xG!NNDEHHdGpiQ_2^T**K z`>dd{HdiL2tn8XGi;sKZ-UUaTV!x_~Nn(OLM!K`J)B6Z$mDWsSX=#~}o68(uc19qh zDdBUON-`Vx0m-JOCQ*on+~*fH=fu6nPlYk+z41v`2WI846HU;foO7hAUQZVX4lqa<>U~+_#Hb!odWK! zPk6UL5i>Ox9X2>#+b#^^`|KB6UFmK;qr8BC487-ze<$zPH^Rd2yzD@oWruAsH8YC% zz}I*nl0bmR0c|fyk=wl{G2p?Z68-l7XTtJsenr#iDrl#g^VIt^-sjuUZ8(ZS&b2$dKjv79q`asR#*L1oyi{k7a zI+~rstI|PCzCRI01epnL+V!v3Ug-kmzxTT@4UQutBib7c;eTqF4&3kpo}NH!fQ=k= zn*CU0qh0eIFr>#8j+SOsH4V5RaK;kTzof7eshuUyj79tV#j1~CqKPsb@G);PQ!M-M zi5>mZk43QJKVf#B>9AvPK|@na$FBjr`H5p^28H7-P6Zd;?-a-+uds}im6dB9W(=d9 zo!TqCiE{-eduT%si-=9^7#}NveX>S7KIo|$4|$hGy$y*#`LwAA9zYL3!YtJo!JNJ6 z08&npaq#3XNA8bvUA^dGhPCG)m{V>!3p0RS%te`v;;KL<0GO0VKG{L!PPVMbwpu^M$Py*j%sMXob>wZ+ZO#U?h|O0-yJn=xii8wOo?%M(Bu zVkKZYhg;Ff2meagQ|4=9w<99NK0Z4}Io_`H-M?$K#^p-Hu#=ium+bmD$@~m_67UC6 zAVM&fs6M{74t)sZ9`F0yf7XkK7#D2KyM5pS3qjM|SN+OouU1Dw6zI{)Q^(%dpU>7i z%{d-SNdHwN@elQ;oPtBQ%MHy%&#@uCT1jNY5nB(G zht@C6JG~wQJzM#AhF;;o=X2Nl_9^bc9@o&VK6_GZ7Mi`nV_b4%tx=Fil)eQfB3dMs z;7e^}Rpl@Wo}^~u!EL=KZsLCh785=Z+SV+JCk2FyLnAg5=ijh_i><9^Wvy`TO`5KS zJkm#k%zKj<`HlC4XE%`1@mm+$P!O`fz&r5uCCLKEV&OS$rp^0nM*?+lJ1(J4*z`uw zfNx@AVqok*jvqP2^XL`aF8%6Y3aQCnU{72CVi=X27&COVPqscXiqN zgs4H=nA!;bmj$9FLPC@%xn+5j2t9aN1k?8B@i6(%tjNK}9aBS_o-~A^`EMVhP5)$& z^_)QkYF9b?{2pMG(_!2lf!pzBRoQM#$68*j6;=hZju_6m_O@IJpPHKKIgv9Wn)u6Rc!VvnQ`$*F#Z^er+NagYzX_NXbZi+Ip}?2*eR|TAP{f@X zY46}BLsTf8iwBMCSMSaTA37lG!<&Y{7ZxH;1=OYF_}wg^*g6t=2T(C)u;8$nq~FC6 zON`~GBf^p+xDklW7SbxiOsENxV)17Fq#ntRkm=C^v{>s)JPcAGS9}NN*&_!~!_s~( zu8GxFcc*ix6WG!-UU8lN!cjvgWd~OS&fmZy)M2T#^R&*={)Bmp7`zMi|2kL9M(OXr zSxnX9dyU?)eCPNBBZr#CJpC{xRa>lYz@O6+D<5g}5@AEH(`gT>u`)5C?#aBDPh&ui zELUk)hf|4=%%I~MbL0yb8A7JjSlp?}A1f2R{vVr%>?86sY+U!JEG6iy;++%uZn6Go zOqI1r-bItfQ(_u+Jn6}=@H+Vq=9^-6d(*Xj05>W0g(_;;KDlCyjguukjM6aV883e!;{24MrISW$^TKBf4*g*!-Nzw zYyXVfDSGc#`a(Q_$F}>`qS(bR@Z_lCCRIx$_ZzlpEhq*9dnfcr7llB3CO$%bS~sMS ziv65DyJhM~9F`3KPhxc?1Y+tE=c2k6`X4Cuk$hC#Qn$1Sd~tzB*UPH0rEF68G@G#oy)B8T;e|J4uNkxfTG2@W`16{rM AJOBUy diff --git a/docs/3.5.x/docs/images/apps/clickdummy.png b/docs/3.5.x/docs/images/apps/clickdummy.png deleted file mode 100644 index 773ce3ec638a72dd3eb7ab6d103dade3874fa53e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34210 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 O0000=x}o)VD=23xZGidKsJj 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

    &}XJ7y^uLKL|l(=^=~M7SI1ZoeQx zU4~gEai7K82`kG>M728gdW}}AMYGYQ-EK2CH&>WCl`3G-QXy3VSNHuQw?jOLdF9nt z(fJF+amd$SflgFyVt28T@8Qsw68{V@wV+(~gN&uV5xIDOPvMbil@@D~PBmBJ*nP zI{hSO;?Xl$RR^OnM<&Qyb&?2luS@Op1IPzXQ*VHBHBNlvF*5H2bT+{`x&rbvz;8^U z-t+*b-Jsu`VsarMURfuYogz9m&!D@`WUEFaiD{lW#O7&WACyguakj?bP?7TPD7Jt zSZ(l{O&ZNf2E9$v)DQ*^n-?sC)-xDvLI3YG&Sa$BE}097+J^`Z9c2*rpze`mJ@VVP zQ8ET4==C+y^J&frl*({IVyH2QQ@WWM()8Ct57qDpA2`FY_r4u<>nd*U2-XQi8gue( z=P=KFir~~K963oxU?2K!Lbr%I{t#kqo%Hf~!fPqv+r9?cllVuElJ`^cqemf5nFs^I zT8+5h<@*2k3k3hwpCJfCx;Jle>vuoO$+P#7^wx-)6WDBk%ZmUmYs+1F`OS{0)3jf_sr-O?ui zL8mjWglTIp*x#juAdM4pV=%7J$*nDun%ImyOYVx<-V&4|+mSI2Ed*K#w6jGlM#U|g zr$t0%p5siBm%^ej&R|WB=jZsMi*y~V>mk@6GIwaz`b6^q{_#1Oo}e#$7JH7hj=?y{ za)Yrkh!kT4X$n~;8Dv}c-k6z2)@sPOOPIy@tx5cP1J5M*on;zthMMkM#nv_z3?KdH*ZlTy>b*5*~)PXf{DpVTCMg0L4@`VPG@`%aNmB@ z8IMlPKT04%0N*dTw0vy{qL3)^Y0b>jn4Q8T1DrP7L~S(lgm92&2?mK@n*`_Z!jwi( zBklEx*Vc&B7z1Qhlk|Ip#>3_sPk5jTMi5Up1RjADOsXknQV3tThzl*wm(*fITPpHe z#HNWE6kMNJQ9~QZvtGgCk_zH{tH0|j8?3%?k(*a8B0LYjHHoqgI=4|u5gdMrFoIAz zRI83#SwWtE4iRr6lMPh7hEyJEu!?=^H;~q&zw||1rWh_3R5P7(r5hnHR8Zf4V?l&FO{P5|+;)39 zr~aTU@`7i(`c6A*Bz# zBFzPv@CjWVFYY4axM*XdiD7{995qj15^y4CkQC2GTgA#oNyWP)6vomhb}qOdIW*YQmUySYKOzJWvFPd1Q&LdRPShn|## zkw+eHA_f+6A8Asg&hcsiwOR{nGm?#rt7#8Kj=~TjsB1$bT|#lZRMq(7D5lBI4MflpM0)CM(NGA3E6vC?A_8 z*i;vSA-0^rw)9sSW7ybO$E$Ssdjaxf$;@#Vh|q4G3&sI_qlfIB$|`VQWi_hWxo0}# zUFv#6K!o?WpWVi06hye+BZi=emqusUTw`^L$#Rs<5H>>(3@WIR$1zzy!Q=*KWg$>r zgdb{rFG1NJMhj|lhlr+T*}QNCQ##ow1w%Ai^pGQ^iMx*xt^5#%9z% zvfs-XOFBpx^fCtB3}*^%sIZk`(iH@PXm%3e2Z*4K-;j7p5{7~x2(kGJdJto!Le*N- zCniZ&Z;`F6(U?DpCm50o1WFLq1z8r-UF&0wM&cmz2$V-giZ5$K%?RZ|C^K|ssfU*N zlOgqKA4Ejf=^{ddbCQ17V60U*nIv=1T%-2{kr#I^PCz9UU(a;?~u*E4Q0-wd_`ERlWUFdQcPxw z=hgP{8x6D;Na+)`8-(pS@+2pmo-49U>5Pggr^wI2wjE<=eA&r^TS?7cAi^qloh|KN zwdy_hV^QAnioNe2>avEphh%H-5qg@Z1tfgfc! zr*KZAtsys%^essjG6T6N@K~y}^hhBQK}36Q0k73Ws3ucyJB}CBXtnFqj~ya^>M88P zQEa14cWsmS`~`Fxqr#WTJFDc~P5i?PM2DtPN8WtmZZCO3%@47 z*3j7i;S6DD32FhhUMpDJrNf$p-t9|tmeW;i5M3{DcsA^?H39{>fT1%vPjz zjxk#+W#vCm%0qc_D;=>EA=xha`ZajDS_uX=1(_JE0)Ej7^fNp%{np&2<>A(6i`Hc$<&Y#CyTO)cUMtDE(f-$;`&T4sHk{B{%|}1_G2ZsXyZD`7{Y8H5cRqm-aPsUU{P+idh~N27ALh|_ zy^qt!=82Pn?j(w8TzvJ*{M0}GS-$hT|7*VG8{SJi7+}lE9|R$nUU{BRKK(L(`FsC7 zN))*vlu~4A%)kEGpW(%;Yy8Ad{5@vc4dNszb_pS<*CPJoFa8_;uV4F}p|AvDlOOrf zA1Bi5{LerAPw6Ka6Vr$I@xS|bxpn@_#A<@KKCr<5^7FsIU-|yO&cfUTgE%gOtt4UK z@qhi|FYv&l?`0;;_^E&P^Zd=f{r}?ZiNhpGTB=9TsMqEOU4MpO`49h= zU;oI*FxK)7ANbRJ_ji0V|DXT&Px8v8>%$#L9OUd>Wt%KLuhmaIVVOEQ$@IxKzVDN+ z+=eW}`JlWBWH^D6O;pgv!~@dx>)3n);T1lBhv^XPMx5 z1M%V~@sbsi>yCW0fjn~(-IHuCcL{Tkuvtfj5-AOhK!XR7=QBMuhY*Kw#?W8iWcBtk z-H`yUN+>GG&FDhzo&WM@`Hhc#4&_Ju@CSd4w?Fa#H*YNRj(5I`7e4oULl{JBVwQJ( z&DU`0;zi!`p7-*~7k{6h|F{1qPWb%LkNi0A{+f3Yg#Q~)yyLx`T$tl0e&Qdpvf0D; zYy6%6<{$9BuYC{eS;*sWdz63kbN`YT&tKx9M;_z<@qK@ZkNw6kaibUTwO{)_KKHx- zk^l79}9aO~vo^Ywq?{e0>pzrw%$KYtbH9H$?AD}VRL{toBPJ;0-nJ;sFS z(4L&(-S2rHtCzmSzx>&Mg#l*gj`83B&w0N66w36V?>1sWxW0M{ZIy24nhY1X-_8i#*RE z67U6h9%yYb5{%Z&&B5^#(CKN`VoSKv=g{#Q#~)~sxuoE!>cqJ93^_eXXceL!VA~V) z+Eb{B8k4ir_?->R%q+pi22+!hh-MS++#&VP;ZID^uraL@E%a1?eDPxhjW+69w@k4N zXpd}FldRr=AYpo@P99m(bWj>HG+B~kU5a%QrHV+FN;9t%^wGSD!*s@1E?(pdpZ@}0 z5b)pqw|}4csbWQX|2KYss8*xdY@n2)*=&?~tP7p&&eAQOdg>{ZUuR`~ljGA9$nreW z?{;|R>1SBp>=J}cR@XO}i|VCHmGSf!KF23M|3&(_;(PP&MoGUgQyR*|JiThYv1!uzWCB5zVRDBKxg?TpZx3>cn zJX8U#HQc^&ou|I=6n+r!>iJ9DxO$%TwKd-Qo(~lM6kVk0UAldXXP$lH~AZX>qm#UF*%x?as;?|0Bs8EMogSaBD^{->!Xtto#gn!VGWo* zh(<(IYk}^fvlT>1UMYo#@C4cx$s?TwfA%P$+rVzzAZYstVZr4n5fU{bnu(>inUj_r zw>bsvjdW$Md&)CPR?=hoaAE-t9RV+ZWL4t_K8be3n|*4NZD!^@UVCW?ooD!d6RAAH zqepS=7RDO7H*aCmS=8hdbu01002KzPL63GbpmXjt#zMTbNYJcP%hnK6Z$Te>3;9Zh zSh|AAa?(tqLWN5*&^?6iVp{>XudXxbcIn@`i8C3_w|FuqtVc*+V$vL0recz+2O);2cy=5PNl-uHp;EL96h-0#rq^|8+K zp7(!%fA-H#;E=ra%?~h9b3AnB)Q}n74}1`U>G?yPJbo0HuNK@uLBx;$xBor=&u))q ztBsO^KmDEmcNXJc$6Cw%4?fJ)M2ny?#i6-rR#%qkC)sx7tJb{s((}A{{t93JC;lYA z{psg;*E=8Msn7j3m#*F{c$6lmIdS+9gE-;qKJabK-}mqk9jvY4qrdwRthLM?I>LQN zj}&3MUXiyB>o{}nK_=VHA#}i6!^=e_7W@*n%5;;R=OC<2s zTl8Lj71nQY_|zt?#V?b&8p~f?#`Y3y>mjl{z>5^7;p4kGT;^eg!U=(2pCC(bV3L%e zCJ}ytKz2@{!Wf$l*PtREzEowa%UX-~_`BZAWb1#UAE(UBFYxVu=39C3OHc7v|H}7r z{J#77$^Y?xWMMkuAO3^C%jduJB3^BpKl@#OiKEAk@@v2Lt6aQ%gJ+)oGC%Y;|0dt^ zjbD!}mFyxnwd3>y4{_qy5f(456f2{YB!f-<-M{^JWVzwNx4et*`wQRB(IcNj8_R=_ zyp@IdIo|#a-_Cb@^EYt(_)-4D&;L{Y`M>@@wjd!vz{biVAN|WV-J0V;}t6%+E|0<~%>-FMQAU^Vpm3XKm>kMr&pcEpYDi@xn(@ zIryaHp-0|AvlbKr=^UOPuypM_uU)y#U;Hb7jptrDk1c&I)sAscCc@E6D#6@?Cpi4b zX?nM>)46SEd6M=*6Vbhc)8&K2Aaoy00#YIT7RnZM`&qJy&NM=Lc=bBX=}DrgqfGagPCn_J84P-~Dc~xLfWL0x8A8nFy=h zLcr|(hdBE1DTEZ5eixm>U@fINm*Xq29*9g5Dh=r!umgn4Q6k0Qqf>`Y2RP~QYHduK zvv&P9p3c~O=Ce%BDTMEXEiggO2^=*{KENhf5xnFXe3_y=izgrmAgqJ$3rb@0;#>qI z(NQ{jhRMT%J1@LIvUr`t=jzOzK2El}iPMI3J>xzD?}L3JboXYXTAt#z{ayr z(>(J4{`3@iEn@leUt;>bPmuOHct>Wb1(NLMbI3-3$@}EY;DU&Fu*Px>o=6b0v$&}? zrqw39e37v3W6~}%Dsq<#;p2qGh%#5npP7ke8L&0cG&-3Gd|0n3j z3GJyF6ow=z*gB#xL~A|74;8uTBx#l*y*5Amw||uH+2|708%#E9h3PU)n4UYwKl~ql zk|fKSo;wWA6u6l@FET9U1^gojgA%x9Nb|JFl+YJeCo{>@BW%U!4r=@!Z&=&cOr!1;YS`o zYfYAB<-KW=WI!Cpy!o+r@-zSRpJ9QMr|-uYLlVaY^^7q{saU#snSb;@{m=Z&PybI$ zh7=6v6odVGb`0wrt+@sZ51qjG!I%uG`-GDU5e4*C)~L@2R2%e$#bvi~Dg>uW!H&^c z2c1Gt^XP8~>T`$i>n)7$6Eq@3YRNWwsEH=RNyu|BIoPZS?@Ll7DL#hKxA+2r5d5Hs zsgPxM(_(dlT-31j!?>P6c|I~9KtI7GfJWz}ftx(e{;W&HlVNM=9!fP+T$n85T7;Aa+TOVb1YLexp+q5QUsMl)*Lo{pw z_Pc!PB2#mRnQS$ znc(R!e1UG9f^%e9#$Wwwf1OW!;uHMNZ~xXkh2l^U@>2o4{~afon4iMR1}2Z$eC@=&fw9+-dUaYn#YMjrz&sWVtO=7o!mqbLb?d-l~(W zECZHkqE6?+RkDpPN5T#dz4H)JBv{R+xp>)O`h8kw9wY)>bB?&%htLtVL!5JTu3p2f zTp?QhUU_x*M^>APkAif zzRL2_4Xm|XxpHM_PaXyLIY3qLc0B_8^F1!U_A=*Rc@fX^v9>7t@)w^O`W0+xIT|IF ztFTR%E?*tuz0~y^cg0pzF(RI)xPJ9g5f9?~i9YXmy;Q)(t0-*%HU#zUshi%A~auIb7v;jSHmgv|csFeGmI8E1Ae^;vW{1; z5kxhFSKK#VK<)Smq$jXFFg=ZOIZ76}t%WoQsgXV?RS1QHA#Tf9Fb2{TlHe%8+4mrV z2rrBX!U$_M$!3bhBTEJS&VW2CcF_7{18e)tJhZ@}M;@ek_7VK{EK`rao2la`$X

  • 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 Q6aWAK07*qoM6N<$g5iQW;Q#;t diff --git a/docs/3.5.x/docs/images/apps/furbabyrescue.png b/docs/3.5.x/docs/images/apps/furbabyrescue.png deleted file mode 100644 index 79dafc640738444c01883ac66e8f0f2584a45a57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49891 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 diff --git a/docs/3.5.x/docs/images/apps/geeklist.png b/docs/3.5.x/docs/images/apps/geeklist.png deleted file mode 100644 index c6579c12f6f37e10ab1a3f667e33f70fbdc87173..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27911 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 /dev/null - then - echo waiting for manual firefox shutdown... - fi - - while true; do - if ps ax | grep -v grep | grep firefox > /dev/null - then - sleep 1 - else - break - fi - done - echo firefox shutdown detected -} - -if test -z "$1" -then - while read line - do - func $line - done < urls -else - func $1 "$2" -fi - diff --git a/docs/3.5.x/docs/images/apps/growthegamegolf.png b/docs/3.5.x/docs/images/apps/growthegamegolf.png deleted file mode 100644 index a8d6e9fb7493ce38c487cb2f31416838fe063bb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43441 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 diff --git a/docs/3.5.x/docs/images/apps/h_learnboost.png b/docs/3.5.x/docs/images/apps/h_learnboost.png deleted file mode 100644 index 2940dc31489e2f0db0857ecf2c32a2dabb907b69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12727 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 diff --git a/docs/3.5.x/docs/images/apps/h_mcds.png b/docs/3.5.x/docs/images/apps/h_mcds.png deleted file mode 100644 index 1ac655377ad9e784895c1d0ac1e74d46d4949752..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3904 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 O0000D_X* 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 diff --git a/docs/3.5.x/docs/images/apps/knack.png b/docs/3.5.x/docs/images/apps/knack.png deleted file mode 100644 index f08fcdbaf24289861c424c5816c2c3959fd9f0dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29572 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 Z_6Wh^+jflZ#s50AmE_c9tHEX={|Dh$?!W*5 diff --git a/docs/3.5.x/docs/images/apps/kyyti.png b/docs/3.5.x/docs/images/apps/kyyti.png deleted file mode 100644 index f74d98da1346a95376b33f6bc6118e8864261b4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41966 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 ^!Ew8_;FrDA-Jwjzfp_2R2 zaiUxZ+bX}XEgqA!F0!cQ=Qaw6h~S8>rEVkxo0tlP?PH9kEXzbY7qMf>mS~esa7dI0 zsQ{yJ&T;3?ZQgzNr+oVG5rcj|am+qG;b-r?$2Z@32N3+LfB7$wQZOA4F-Dieez z9}x33x@vGST|n&8^Q{Nbwc@@1c+TN&AFUF{WkY@TA#RJ_uc!Q}CGb>r+N%ub9UuSv zA&aY$ANx-TK5%$=z(4(G|BU^^9d6&g%?Iy)%n!c*1DdAhzy7cPtBv3aMk$V_d#sj= zZ6fSicS+)%+aeqZ^^mlUXT4fsv%E`ErE=HnmSZUsf3b4h*-0nJtPH}JUBzHD#TWXMR0z#=BFQ>bNgV#{Rfw*jsaPA z%*uOj?tdu~o&A2Fzx^NmhqSFDw*}+LguUGzZr{3vDKzutC2xP@n~CadExlfkWjV(O z&mbFtfTpb}vOZEsjNVk38LGObX_Je!ZOPS9ER>RnF2>p@a)+2`*}Y8Sqb3H|(Y!V1 z%l31^)&gYu{zVn2n$!f-bXvJa3D&C>r>AF(r@ILy3gDxJTCgOQstN(W@x$-4Y9$Bv zen6%I<1DGQw^36zfpwcI0yC33WF?krst>K2$mP1>mTjX% zpL2gP6C!1AY6~MBa6wXK0_Pl=F(@MMeD_b;+1XB+!4R>wWiTAGSj>6twb$6%-lNO~ zgmof-(-}vn3-U}7MaJH!!aGar6J@B6n)%AHJ<8JgP)R1kBrK^V><$As$+$8-wQFS6 zdhVRGNC`K03#wdg$eb^<3NPGbXO#2-2??znvmJb&D!#UpT8uxgtv9bdv)WN!q-+7_ z{f1~Fgg|B#zSkXm-X<;LGjQci)ASSO$#P`8cTD`z9Uce#mkM7oB5qzm+&pAed%RDF zSz_!b&Ep21bk2wvolv4*#A1w8RkgX-)AJ*Kc=S7z*_fNtpF&I1XDI@~*#vhsIo4aO zb>vw^=R!)=h7KtdLMZC>nxo@~IDN{My<1df2Ny!3vbkU>i%>TWQlwaWG#n*3^rfL` zFZf!ez_(}o**(RhnWy^Op$=- z$G~0PV*AY-C?#39o)3;%-g{VY@K3L7WxRd8+Js9n!mLg^>DEA}%#}M&#Y!{YNScKh zdG|rXN2e|8)^AV(F~Z?AN%TKhvE|+Vzws(4X%47TdJ4TF% ztGkG6&rnYd0YcI?a4J&Jw{brHBTszY=r0gte~JktnXDLO+bCfkgZ@Y$zu+z2btq}* zg6}mMM89&Sj7Dn%c~NnA_$qfkYUsK^CPPXU_xb;eJ0F@MwyjZG(b<+fwnb$I8|c|OBB-3KG5R+ z_}-m0#|zu96N#nq?pe#hG~;0MxXpE#tH)y$5(ACUqs`}n6n=f>m698~Irq;y-nqL@ zz2O3m=awJcU-Q;sMp>k@-bJe17@bJydUHPVXl^Ox(>Z@Xw`0T@@iuikJb!ZX1ZMuz zECdK&FsAxA8H*H}-QueZ@{-0S%#6;`=q84LP4Epyi$sSNPAJU?t&#?JXG0$gM~Wh2 zG~6R}hLER0)AGqHre~E%ozYoG+qM+_%b^F*g&r0GiFN$Tunl>F(I}$`zCn-?f+sI> ze7`^~yH-B7xn%3 z30mQI#>7>F{Iy?2-#9=b3Blw4&z};1{r^E{2{GxH&uiby7^f0f@G0W{@VEhD>XG;u zvOok!(34I26_T@C=O9LMqqwn~gf8E?x85AcmrW!y+2aF#PpmCvauWLSI$JsJpLM*o zFP=K{Uf_(85Q|(2hj?Dp_9>~C%VH>-NQ_GXS`Q8QY(67C@wW$=p)k7NE#&3`7X>CI zBG@G{D$d(`1oklU3f2WW-|ObZi1!geWKbqy#LE^ooJMJ(us$(nc%SMhWm#_Y9zuZm z+M{BIQHg-zi<%(S0i;NxkwQwOw?rjUQ&e7{q-InqoK>{VoJ{6;?`Tm-Dd}88Xx1D~ zC#>5*Q@7;8VTv)qww#_VIb5z$i#1`sLjKyXBAth-AfC*L=S%#DkBD!*irg6!fBEZl zxmLJ`(sXPBz390X)@F8;lyyJM0bkyHCEE)AWh4>~pXCPs_WDiRh0zstn0@)=Y z&D}w&<1CxBv}Q&ipGxE=@jmqIEb_60@~6z(&+Qme3hLF0#j?S<2Bcy%o}gvYVoM&M z9$>v*Beh{X7;tiQj1!URc#6`BW;y3YB;cHbrip z8;5`5s1(7w4(~(?>P#>pXeSsdRAx zAq2j6wB@Q}kPDQHU+Ep>lHeqp)ZL3(NE+V)sI)}(g7!Wt0+K8X zc-K*{mnc0+?B?DR(fIX!L^feqZINk#^EtMw(Gmu^reMzTLL!4meI?2wCqvkqB5xid zd>}dxyCWFn#P=Q$&lkk6zlQnR^#nCB8r?qo5n>Pf_~5AJY~}gJ%>mm3m86UHgs$oO zrXxd9rW#U~8P4X((e}nA$|mx>#1606ADd4g5`0f~m-R`LBG1_y8@7fT+csa0V?@B( zj@$3w=6H6*!NDOu3Qq2S#GSkMkW!H4MH0SO8Ff?h&2Ro3CwFi2;QSmRHPh`~s@U*@ zzqmtL6^S;*I*idAUOnXQhaa-6EqR{t^S|(Sx%uknmkfx23xa?_%Yf?|q|Oq9xJ=j_ zV-(Rh$jqT-wQ&R?QY`D7=i!5gxF{G6%8fImm-;vtA0tTvBrg(NJEVf(&bY+e4%dYQ zL=@@TK87#EU;!khSfDh5K^FU}yue1q!&%3*Z9|9>fn|PnoHArOL&%bYg9)NLMaUIG zjgydzDKNPqc5{LVx#V+hle{QcH4Y;zm8u~dGhcRe!BgJ4ff{CM zT84>u!8Zxc)Ml5tQRF}dk@BI_qj9*@(QjC<RLtwsa7!8U| z7@5Rnd{6Z$_~6*GHSCpu`W1?(6WFe^$RbA|Fw&FBuz|RI5gV0;@vtB_7KFfcmSGlf z)=~}zbe$!v&ZvqUl_#jT)CS}(qB|j~su$-}80A2%@p=#Gn^cij0qq`hS@#-qApGoZexgA3Y!FqYd z$=&z*$x5P$Pi1cMOd~|X!pMQ4E??pO6ORz-QUXD2Bdh>&8151yygpV;ipc%DAMx({ zA8ZcfMoG%T@XGZYZ0#MQq)a@t&zVmG&{~n_IkvO3){&VEyd{K`{qO;#%2~J}>ywuK z@d^20m(atol~QCqykaySC7_<|dT?G$_tW_#}XMY0?|5S*=$@At|!- zq7NpL_f8zE<{A1H&wUrYHlGkEogsonS2?3$PZI4NS~zSrASi>k9VV~(T~ULs2zH55 z73=kyO0AIDh$v(lgJ97*5_N`Doah_}+XI}Pq0JWOb-?!LvvH|e zHXbb#RqE-|J@Z*R8+kD6*cw!Hp~6)#+oFkqc9j zC(gH-F|;Aj)C~ba(>`7G_VYW2l)V4WAMhLh<3AI;XR)&U(VstJx%OP&&$xMQic%E< z`1U{lx7>O4U+}-)Y0w+8--|A#zOO8T#`5ofq2OjU=fC`?|HvQy_V1#E#Dzpfv$Hqh z+yCSr@z4JCzhifMAJ=soPNipBUu4TNgYpSsnQ4UxEfIqYl1zApRmSmJv8b1nWeswG z4=H{x%8J!;&R{s~iPIXC@(6r_ldEi_Omt(npmkwWeDa|$;CYYMsi5UtgLE|_Kxqt} z6WGr{e(-eHhjkZvNR7b;kBVs#@~$NYhssJa(#sD%(5x2-m6K-~k^*m!u_y}dP1E5FxJ>lq#g9c5MR4Tp5rgADX5xRAhj&kS_Xpo& zs1+(kq?QP&spo6n|KSffdvKe*-Tlv;*uC5#7LnB5Icpa%Aty#bHJoBGNNu>j>p4C? zPX*1M=ZF{?3<}oEIo_o+P@ZRWU4zjQWs1J1A!)~59Ng&}tXdlqR?NBd+-}8eX_*WR zxm@t}D+Tu#8LbT*FD$Fpf2P(9A;5$+B3QNudw6R(TLh4jp|<#Lfm8+P3LgYTQ6z~0 zsc7pJhK8=`5YnKKRE0*m6=VktFo@`JA`r}wu5(mM;@UZFG-SrGTDP3fX6)@w_}*Pl z8;1P!jRArgt~~=aB{!*%C;OJ*>$^Gg`q^56s#jK$TBG8OkRK3HPcRmW%^37m^YEDZ z^dfokG?3uO9VRn|{VmP9bzfGx_TmQ9e*>-fsjEX~^EFxsf`?_@QB^rg=>#89DRhZl z&GP*}!P}bA)wkFV$25QO+sqedWa{Vm@ZLSzx}(yHu5F1(axIWTv6!zoeQ+1?lRx*F z@6r3jVxfASw?R4Oync|dUShyv)ln1%-_|ItF?mMo64{p^sR~IUklOSiR9`*!4lfHt z&(;SihaMv2Iwj*f=c(J4A}i54Ndw1X$ao?#T2ikfd7Saa;T4n={OEqoM<=O4YuP+W z$(gFfeV_Kl&q7D(j_J;p{P4qbv^MPT@A1%etQSXo?W=EM$_OD4F$kFvDQjH)yL;&M~#uNj5@T^KK^YXIk`C)7UUy|t#Zfor?{`!(B0 zdklU-R!n-`jU;|^eYarMM*jTn`pFsIhnq3NxKh0JN<|@-1X+U6i03R5Aw-Z7eTf`; z^I1$Mji-@IL{edST0R{&_2Q1vA95-kxH5{!I?W{SBe(C(n2swJt3+@tlmgdr@3;Od z_B;O*-?q4`w|M)P{|@ik2476EQF8R?VIn2#VFjg3`R1UYbB?p4M+9d-^F3-U`WDLA zZ>c4_>IOnYeAiOdrGMQ{rH;whVh!BTt}dJI13ys+@XDUJYrQ7KEqBb>E(u zgxoJ)K&~a*c})x&Aq~bDY-cHog88~*Rcj7MIZ|{)QE+3oKuf{A_8VP@3#S<5iZ>2Q z8XLHG*0Sy*c{QdGiq&F9Haft2&uncm<&@#>kU9=9$W2`Uzb3RTI!2Bj-s5~W=j8O9 z;h?~F4a3od5Cw~6&09b5HgYuOeA!Yrj5Q4xn8}o~=U0+SP?f14+5t^S&0b1F(^?vz z(RsM}dP%OKp50@$IOEZAWOC&?H4`RY(rCl!Y0IKcGSor>;<1WqG2TO}1m*A{vRJOU z-w(|^000Y%NklI!>l|8XtPfoKiEpv8 zFk5@ZS%(gukZtp6g}28Hf^j3<6EBJ0T<#l}0`8o&9L+49PvP9#*9MREGD!SVPhC`B z$S;5xJi!M(e7NS(X-#cC*DH@PDNs$&_eRs;UWL#7hmHSzx6h!XXm_k z8ex0LU_7OB9$VMoEkh&0XNi7ZE2c_9V_7d(SX+~2OZldagUMKr2nDx06VF zl$@Q<5Cp#ao$p|>l2N63>+KPFmJy;yD~0m`>wLc+B&8uG1ObIqNeet$&!EcFN*Dsp zi?qAMM4K5yWaSmkCY0{>bPG^e+mI=@34o=D5G?zXjJu~DJ|vmUN}@2q3hdW;g( zU5eLTNGyKaJ@D>q=~y*r&GgU@ttiUGLb7-DjZFq;wOTWuC8yfm-R^}X z6(T-vj=9*9^UM%qq{#EcpK3embzbS5FLV6)02}Tk;1^@B2uYGGYPP2XqEs|4;=0JHaje=@!532T=CvJ! z*nN_p_Y!C?_3x)^T%<<5vnZW*k_$Q`?;W`oT$yC46}UcQXa)m-O$&f`J_+_@2B}iI z_*!|<1QlpHp9D0eN<6yy>7?Z^)~H0lb}gr8EoY0G)ZL z1jo)uvuHzK3z4ZaFLb=~gYSbh461^n8jxwl`ROSkc!V-cr(+)6y@OPmuIrdiCK#o0 zNTi4?7Av}@VY+{S5`oxDA|wVsLtC$Cn~ri&5~JYYm1~?n{D}E-NnTVaC3tlI9;3+? zRaFuLY)?w8b)3vkI8rby3XV^X$g-rV(d4kRGvF`o{6Qk2vyLd>eJOE1@XD(<*xMTM z<9FXp?C(8XziC!TUGVyAxA^G2cR87_7z{G1;S?1+KDzgaBF`wR0mIRl!-G9$XUF{b zz1wW>>>y%NhRyPVsx0{E&Rs^sF(JBySjY_1t!>8RFTpWl47_^lEq>|S|B{olj@N&F zjq@o!-We*krWs0Sga}uzf0eCa;M=zXVK_!w!7u&FuTY<#5{UfMt6$rs)NZ|Yi%}No zf}+YZDx(P@bqlru#-oy*?J--g+(Jn8+%rZh>}BkXrf3Qx+q6whRTw(wSuGc=7H8yn z$*or_yc!Z!pkA+gf-Z&03u50PSDKWbZfwBeHypN!|A+)K%o7I3`6SNRv@L^b(C=*l zf=A*wJvpW-3%oF_YDvWmkt=c&(X`CljPtc52Dz#GKq8SSiwYY&XD5#+x-GWGBbuh} zA=QFvFeERBcxNfAA-Wt9tVL>#QJ~unt#yL&2v6rc!TTgFrX}5aMTnBP@>u672V+c@ z0}B@O^Q5U!R@k;iXot}`!bSEcBi3e0XDvmRu{9l$7g<^`qrwKoa5zX*sCi;hkutT{ z*6S5^Jfz5rH2&VRSj=%DFdB`SEf(w@95P?MN85I|xL{{IWKdQ#ZO!7*BLafm-EFkV zY3e2KzBgksoMO8*oeykHMx355(Nb{l;SndZ1y!#3>2G|4gZ;fv&Y#cS!Pieau~9y` z5d9Dv=D^2!g9K&$1XZWFi198FAY8hQi@){p>t2KkPunRz-oa=wrxM1fr!V#oN>=ykPw4I}Ko-E5A z$L2B6_Ih>FFA<@}x=8Ebhd;iPR?Zm6@{+b*C))mC8H}g2t)q1Tp$qcyet&jJsb|&4 z#3A@T-j`1W{l`o1=7RC>Qokj@h8<8|G+~QKt}Zf;0p~T&#Z3?Ut@5 zp#wY!g^(H1w}hyA=0=CqpUfy)>n@Qlr-4p&EXcF`Qs{YUB3w}ISc{Z$0~_hOj=HWd zEsvMRqW@{<0zQ)XsD=Y}clSOiJoI9YaWNSKrzdB`n6fc~NL~z>PDW4tzOx;-Z{J3n zjPYcPt?83{m=J>Ha?Z)gIl+6fB7dUNS(F2&)A46=3`qJO*4m3NY@9M)a@LFAO%urX zAi_^NbVFZdd{y;e*eX?QkN!X2#)1)g^z)%9Q1UL7X$RnMwYu4xcTlNp2Ux&$qWqo@Af(|(o?YtLtdcxf-~$;S! zh81Vkx6i#}D5dzne{`2We&;^7u5R&5 zKYNXxN!HWQr@~eUY_ygyWS=hV!XZKkiGXtxMh)sg2JR}QBv7Rycc;=)qbl_bw|#^Z5M&8cwK zQVj+)>or9+z}lAex?yW;i@eBr=@c*Rui8HM8AAxc`J!RD?$AoIJt@gDg?PrP;Bv<0 z;@=;a2M!^Aq4PnE@iAS^OM7Ww&|WBAdm&H7roZ;D-kz4OeQ7W4MeT*twJ*=QFYRx$ zefc!wFYTrMEwE?q7|*LY{B^RIA=FFzGED;~z|PY?G{$@?Uj46|y=eX8rM3Y5Z diff --git a/docs/3.5.x/docs/images/apps/learnboost.png b/docs/3.5.x/docs/images/apps/learnboost.png deleted file mode 100644 index a6c33c8bd41f9806ab255e4afe5e0187c65810fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31434 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 diff --git a/docs/3.5.x/docs/images/apps/linkr.png b/docs/3.5.x/docs/images/apps/linkr.png deleted file mode 100644 index 62dc5f6c51174c77fdc4356a7f442e95cf8fb6ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6428 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 diff --git a/docs/3.5.x/docs/images/apps/lists.png b/docs/3.5.x/docs/images/apps/lists.png deleted file mode 100644 index a0f48c63b1eb40fa7cab3c8384ed97834c621e21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 697 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
  • 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 T655ph=X$5122!n4wvPBe3)j3P diff --git a/docs/3.5.x/docs/images/apps/mcdonalds.png b/docs/3.5.x/docs/images/apps/mcdonalds.png deleted file mode 100644 index 28a1bbf0bc13f1d3728ad42e53a04eb669f14517..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57481 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

    w5Dis*m_y7@7D1e4 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 diff --git a/docs/3.5.x/docs/images/apps/nuorder.png b/docs/3.5.x/docs/images/apps/nuorder.png deleted file mode 100644 index da4cf597aae0b92aff5c13b2638ec7edc997705d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38163 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 Ef(FYGSO5S3 diff --git a/docs/3.5.x/docs/images/apps/panemerkille.png b/docs/3.5.x/docs/images/apps/panemerkille.png deleted file mode 100644 index 1c23893588b5750f2f523e5b44568ea271caf2d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26344 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 diff --git a/docs/3.5.x/docs/images/apps/pictorious.png b/docs/3.5.x/docs/images/apps/pictorious.png deleted file mode 100644 index e0d30fd24aedac9843c81570908393ba45261951..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45953 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�Ji(&ADpg6G8MuR@X{q2Ka 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 FV1hD~I!yoo diff --git a/docs/3.5.x/docs/images/apps/scottyapp.png b/docs/3.5.x/docs/images/apps/scottyapp.png deleted file mode 100644 index d5142f34601224e550deb71b93313497f5720cf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118416 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 Dx(}}{ diff --git a/docs/3.5.x/docs/images/apps/seelio.png b/docs/3.5.x/docs/images/apps/seelio.png deleted file mode 100644 index e3e7a8e65abae0ad30c3db0a00782d8b1d54ce9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24005 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 diff --git a/docs/3.5.x/docs/images/apps/selectvids.png b/docs/3.5.x/docs/images/apps/selectvids.png deleted file mode 100644 index 9ba693a6a156164f547eb4b615afaa43a2475a81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42214 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 KMNUMnLSTZ(DAHH} diff --git a/docs/3.5.x/docs/images/apps/sharelatex.png b/docs/3.5.x/docs/images/apps/sharelatex.png deleted file mode 100644 index e3ef6dd25e1f81de2a170ede0e3a3665fe98b80d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19707 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 w+RWv0lh6Ai#~9=x}o)VD=23xZGidKsJj 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

    UgJe6f|Y=Yr! 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 M07*qoM6N<$f<=x}o)VD=23xZGidKsJj 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 P00000NkvXXu0mjfkLXIi diff --git a/docs/3.5.x/docs/images/apps/stachify.png b/docs/3.5.x/docs/images/apps/stachify.png deleted file mode 100644 index 14a64c23af6ffe25419224c9e6313b366b925014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27783 zcmV)HK)t_-P)=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81R4_?IK~#9!?Y(!fWyg8g`RhL6rkCS{ zHxV;~Fu(u=Nq__hFoaPlu4K!lbr3Cy z3bdF5M3E8!5Fm0IU@$qnoZq|or0)IW-284hHw-|p*;T;2drqIP`}?}T?k{$WFMa7t z8bAnv=XvCG=;aPe@$pnp{cGX zc`fbszSs*-Q#VhVk42MDJJPP&w>r|)jze7|y3z-8ES2D9m1fhbXIKq%ZeN-(X+Q9^ zZWx^w@bqACg@z#)?fN-bT(#DS(g(GDXoNRNHKjXv(eSP1N8JM~xff{jilW2BXxYPv z@H)W{5fu^p(Yan3UL;&2w5c@%!xhR4m#FD$Yh0uBE$YOp?VD}`Z;qMMJ4ZZxkv0f_#YU{Q8rd2!5>NSH`{<{D1S5aq5PS)m^!Mo=73uudcQ4+SO|{5&JFW{xu>erL4S*(yvZ9 zl;K4wwYWxK=|oF7QQ-ATyJj@#2G=OGYkc>^G*4=2+RZ$XgYICn4h+I}UAM&#cxCMc z#v2tC&`&$9Cd8W^(GX=f?-%E0FuQ?oMs;|!LazLGqZ4UQeWe-<3Zm}YS|PYBU+=Yi zh0mpIFK244QA#xxRiZ8gt>{pO(YQi3(qK@f*M;lNp8Vb7bTby{UW?Wmv)RLPN1ILz zr7$gvSUf>Ik-#(!gpid<3m5E%pb09!~v${%hc$j1|S%q7&Rcocu zG$?EuG`hyrR<=iLvYzI`)f)iFl7+%B3{1@Km92@VX8W1A+nW#T&p=C560Woa=o zfun>_M5SH%*`NlwpT0F6+a`UB$~^6!^}`^8fEAT?&2TlN0z7o=I7d$2#<>fZ`141f zU}a^6d_GSQ1RcK}~m{|V18*!}Npftkkg=re$)ryaU=v%*~9qqcE6U}ff|L&D`?Z(w?H3@2; z9lhlwlLrp-2Y>XZT)1$7AEx-K(a}-vzWZ+W@892Y^~z*3T)uRfcr3=-A9$Fj9{(#` z$LVOL=p+kwqFpn1t*lkOz-sJIzkO?0dYN?XEOWh1;z8hA{=QW|wboS!U*lF%{&0L^ zl9@wC`NKc{6JCG)^&cvx061~t1QQbzm0Xg>|AHVOl}vHhU3U>E#lq?ar|*7COA~1; z=4xvTZ$i6Hb)$+oQ6_A&{xxH`DCXcOxJETEN5QqFj@e`XqR_6Lg|l2_ZRNdN3miLn zE02BuNv>VJ8mTjHWHC*X)2B}(gdhllmj9I*+Y;J849~xz1YO1Z1up5!28SOd^ zMif}B>ULw7k1`3O`XJs6T%+`>{mnwO-*xDgAiO`^9yT@VdeG zX2LSdFZLj#HHlP;tIO+=EKhHANhXt=Jb4nOR9AYB5CWw@7zUPYfQ&af9-_>A=Qhc~l8q+XvBd+dIiQ11jw-#Qf zNP=$r)~%BJM&ddMc!S2ZsUM>{Q6>Fm_zjPYkUVfFL#9J|cbi-;j}U^RM~`y<{r6*< z<{s`Y|GTlV!K05p%GTCa9ZV@Dr%s(hN?FkzTH(>mJf}*|MQVZ&yYW$Ua;y!a49YXz zZU4K)^^KxkuT0Y`u1!7P;j=KdDd^KYTPPHW`okS2QZh{f1vO_N|+p zszT>x$gXOFoz5)fbbROSkYkO@?lnpwlYa zEv~gRd?WhyX3}nt@?9%44rb37Y?+yvVS0MHPWS0njtqkybvYb(&--3VD>0%Qc-@MH zQQ-}uZ&Bd&0_$ebZV>%zA4E7ng>Mi=2*I&q$1qK^XA^RTF`8JS+O3G4N;ejks1v^1 zmA&06+)6j;cJlQ@qbRiN1iM$-b=zmN_TyTBx(LCL0QbcK| z8N6nL-w9qbMY+>T9tD0YSe+J`sPLjPXeZjW6{WP+d*g|CbBZA)M-CrC=rGr!u0!pZ zxBOm+x|G@QRrDRFl{j*(iiUIjDHIJ&aK=YScd;J9HR(bd2UR zu`&Z|-dF!FWp9`M-)dk43Xo_hW#?%fCLWCp4KZ>1ojCE@lM`zZZ{H_bEFf}O08|;j zHgxM`Q*XBYMv;F9?W}88Ze~0E;L%R>9ArEFl(sqFq1C3;L9Lnn)MuFZ#809tD|VeQ zQe*nml~tOO(Ki+ZjOc(}VN#Sbj9wH~X3>DH0`>(Si&hM0X9ra*aAb0lgoJrB#;P5w z9*$75DhWh|^_m~q88X?(E6+3b#P>?sef4JEZmn9aXconJHHbm($Li9pqpMZv#!=S~ zyk4D{?eLERt7XnNx-`*hUs)D1nL-Et-ntbIs#-#IX|*=c{Ee|BcMc_aC7op{U*t7k zv7)tr(r99N0hKTC1%(o= zmdRwy=IlrJ+va==DXVi#hz7=}KCcsO6j+_MA6WgL0#}2@UwgLYR|LVvO(< z648<=+L<~ViQ9~J?clW=_$UM3Y{wW>-=cW7qrz)9iKBY9qndT2`h1$fYX+-jbZsSc zqNb=~0Y8%l)j0Vp(`?T#Eg&W&C#FW($me-|H^V8{!%&K~T#kb8lW|>QL4XPZo?KXB zIvHmskzhP#qkX~or2tI!5v*90FqlLtGoG|}82vAzr+7p*D!HmE7B}C8U?=({A9^jZvTQTJ4y#?CS;B9q|5(S#T-$~S0&L!t6FAhZobqt?-Vtnk&*~BL791K z{4Jp`QiBe6p31JL!LkLfEo=T_F{m8MCTc$)uoEmQyg{2Go3+!*{Q1L*Yd>*egQRDh zuyd$WWHn5VkMNc|j}!P+{7MuDpmb0v~FOK>X9|N=64A-K%)c|-JtA!*GeN) z#bXh+qgBOOr&XAlCzL4d7}X;{g@Cof8h)@rP(D(Ws@~nNU!Y&pVU%y9c;=hIYJ?jV z*M9Yke&F>&yLRGbFMTsxy=ZDdF-#0QhA^!cU*x`yDPTf*c5~1Hf=z2y`)y?l_g$O+R>D=|H9Ww>#%8E-F1WrnWKDCh^l4G9!fLOV^C#~ z@S;wRMtoXLvj4x~+O9-CyEX(0NC8Te=A}l9P;{wfl<=j5vXWbptF+cAp=xEAQYUp4 zMxYT=R75qQb*V{>MwK2*K!v-N1`MMtONERos$x{=_zq8F5ByNaP=Tr_>9xw(AmX2H zhJ4&TdE^!bcH%lx}?;W zm?dN(S@MqSst&FcnOu?cH&%(8g1BW6kH<(QVib!Gj_Wc$I!ruf*B~fM3|DP5bfZ)U zN|&}EQF2!Vs(kR8qSAN`v6|W5yBWMz^*aqnBkX1Yi;eK2!i>_lR!tIrI?IwJ; zQL^orpj*1N&H1i4@5)6QVA?=X*$u)~IVgWvnxuNqZa|qiO3WlnuoqS~`TAq8@Wk00 zT)4i9L}8#v+9spJ2^?QBJDTJJ_us}t_uawBP_m8)q3EP)Wat`akJ4x(+;Py^$IU)dv6r3-TD-Ipd$NnMJXGhe00SXp+eE5T(4}7)c_@iDJk4#rdV9r;Gg`?SNYZxud$mggnEeb zLhF^3C~cxq2x;I4KECU7eQlS2^Jh=6k#_j>2j0f91CteTsg@~f@hLwuN}N$qzLlZ{ zUo>?9MP-VcWq%)}<7<%S;hSx0ely|iNo}nyRRe74w_$)~g-UNZEJ}wvLTGUUEme)q zp=)-E&>!J@9-sTl5BT;|7swU8a92=@pp=!Tyf7mJAW%L+NP<9N8Yc6bMSklGPx9U8 zF7s+KjqRG3qhM7ny$pmb-SXb`2K7WdkJdoA6>6Se!kS^QKlift=hB`VWL z@qsk!cQ^P(ZKGe>b%NX2580{#N-JkAC?QQSEwpK%4GCr_T49)ASm?^X78o{28(~-o z!ve#=^*qj9nCClBzKY`(k=n;J1VTtm11wV#w+#e7f&i@og22NtG_iOb+l~Q(7hb=? zXaDdo$mSiSVId70!>}+63n@$giSS=TT1aUE0u`w0j?tjxHVedSN*AIja#3vQ&Dv}i zXxM2|w40#K`rj(5H_9T>t0gOn65UN{M!QzHMxkA~G`;7$&N5PYr$ZgXuo0$>kOo3Z zgi(sX_55&WC^L#_fN7#jj3P{%?>_z#|Ho(ljK#Gb3@I_KIF_A2NQo4Zm>oxBkW8k+ z%PdWSWrWP>IC&f=kB}16FuAg@!3!5|AS{VC1V{rzh74ks7)448X_y!?v`Sa4QdJ*D z)Ey#|7rkCA%(6lQTvmIdsqGUZP7XyTe zmKuZs%BN(n1*xivw;>5Pqf(%thV9KAzVw|JxU{%QERjUX7=AvFX<7^o*{C2uNJ%P| zD6M4RIu1@TPY`%0<)cub<5;%M+HQg0`uw*!eey6fQ)8ij1Zu>#vehi~i)bM#%C}({ zrRd-2c@VvdMvVi$Cw-+_n{t$Jh`($*aNYE`R}rU8h2HvBUI?0e+mCUhRe$@TommT{ zULFG>8zxRk`9_642`x+@Ku8TzqFo1p2t}^)@ar)5;n62v=Iq5Kq%`n+mrN#$KvT#& z#4H=rvJnCd0%Fo2>v$9jc`VBYVW52%DGglLB^I-hhRIW}E%2}Z742vB7y&nO$}HIoghaX@%(eKDbV`4()fT zPAh*uxVEZOVT`@9R%z9$Yg2}kRECpX3JFSvTD1ux2ue8|)#L~vOdQAI2QOa1N~AFT z9Gfef2nBZ@n&I{%a~#<}!`4oYvC%R1O;0c}GQ!gOCSQ5%`=oOP;&zOyYujuW9Ku~F zKq((TfZzMdlZ=m~_#c1zLs+I6?gSsAhmE4N#mVSP%kt$v{Ug5n$Tym{AMWNF9ZwJ(IgXy3 z3BCVHK`x72Swya{Kq)<-cA|E2vbDrlYxKw{-j978@8}7%2z^rat1n=E?_1zFVYPSy zVOdo-Q4kQ^dI#P+-$#%d03`}x~H@c|Cc z&5=qb5rIYs6KUBX1$P`j%-c>KWpitbOfJilXV3HKYgf3jokgKB3=5&bbv^#*n@{uJ z`|sq;>03aBYqC&f6R|3p7-Z$V+r~JlrsnDfB9?zQiYU!!rO4g zV|DHba%&yq>BkA~emmZKKLV*?D*K}65==~y92w!}g zQoD1u>R01fw0jnXLE3rT&F;8RfG`juK#1^WA}uspdExe`LD(^ZVi6gOBLpbru`s{J z^@VjZxg7aIkrVsI_-{V>A?| zQU1=sX&x9GMhe*We7?7p=08e7?!!Mp;`(JoCSA|45v)o5?j-HZ&rKbCbt_u^ClykL z@~=jC4yuqx2`Hp@aEk?e$0J`T;%Py8C(VTm3%IUFu25h&Ve_dEyqgbv@$e8q7;sW3!YdbU;5aU^c&rqVSoXrp zP%f6?T_0t}5G@>h&3p&lnk}W2T)cRZlUJ`2kH<;G=DW1<3 zcrrPJj>Qp5p-UndPBGM78pNGidiUy2i4t}L)F08ghd~;Z?@D+_=`aD`MdZ`SSRBK$ zkjf9!R+EC%s1Kgc%us@huV15>Pjh^Dh(iZwc>jCfO(Kkody?9z;$$5c36x%Y`Bg zkKlg%uc0QUQ1L`KDYrJTzwrg+jjMed5ju@)t3|JE&bJVpPzqrf;CVQ?9FITwGN1d}lSpCk-jhc;aQqI z@1NoLEw>O$q)Pc3ih_VZX#zJOC>BW&uzxtlg|!`|G(#(v89MI@o@Rb=mC5M|Y&(XO z0xc<7&_bM4plX<-x?}We4Qa<9j#FfJH_eS3*RgGzp`jsCsU$HwRyn04{7zz;20wW0 zXCtP104z;eWq0k1Zts*U3Xn$82I!ax`Y~ z*3lHhra|6^V{sdQY=kR`(Co_}gdh=GmPb7qbO6eVaG{( zYe&Xt*9eq@0)y~B&qMhhGL-_~qqwt6VS5M5nxN=-T)%RI?>_n*U;C?gab$*FdD#eH$L%9WX;4wEb zhQ7QKiU5F80lx2XV{wIVKKcUtXD8XtgDTJp3rW~%E}5> za)c8nPcS+*hU2)nu1h=~BN2~>cMk%tQy}fS2wRdj@&s|8`Nah;UAl;q%aO3E{*2l_ z1zO{jR{0^*;CMXFW4l?tw6?{qsRYlbv;3XI`xrIDAx@eGfA81N!s@@5X241pR8=~uNT(&iK$`!=7DJ@Z3}=k$K_vKTV}|p9-aD;sWE=`pv|yp zvi|G;h=25%pGKro{QBuz7?qN<)8nkX^FHo2G-IQq#9}diZDJfxhv~^NDf#`yb^hJT zCcm(Mnh#HnvFrQ%%B3Z)rG`WI0L>Yrn}w_AobRTMG_#Lu4Jtq=Mc_N3i4ahphgT?& z8cvbl&2Z_$RlfJci#+wpRhBk0_<^{5G}} z7@kjhbA#38Rpz&{OJvYm+49}7>j8Gg=fsbw3VV;r{WO4;A&98Cs$|9*`tZJUr zP!6xvDrAmo;9=R!-a2co*HSDNdG6U~*xKA+Vq%i|L+&|J{a<>|{Zo|#XrS%Q)HQv{12|#;j?Sl|_ zMF(7$VkV6t!H(PPY^B-S%CM8pv6Xcw1OlbObsciW0?D|IG%YM)AaVufW~VtiH^a%3 z$Jsx%5AsDs(P4UGlDFS-g8Og19pP(|i5L@;;~*p_CdQeK#|V^9GL=GU!O?wVOpheE zvartE-f}ve=t`5#WLa5QVtZ@57P+?OzJVkF=`iIsm&>ufzQ)MN2#G|3rKKfSmX_Gs z+GKNclZAx^Ha9kyoSek>JeC$0DU{B@YN{v-f$`c)u(8H}THoQ3^=&+*7&c8lIXlTe zJ#mO1pBiP!_4xD6-O6`Q?4GvXH_fazq4F&PAE^~yHbZ7@ z4a+u(C1PxC?C{dri)?P~lFoUo@8&5w9y-u?zDKTDKxl;$lKAi_D!-0Il1wH^jExXv z((J6SVS1YVGqZ?z3aJ%Nb_h#q^0_Q-5b(}Z$646i<}WW_A)ieHf^^;|lXEzFKC3Y_qty%;?Avep6YsHwK8ZqiDiIA$;E_kw`E)I?9b}*U07by!7%bC?WAZkIAu7 z?!NmB`Fx()efv0n{yd)NRe~J_MxAvAKsZHYHqF-LH2-3LmFLnqetc$}+lP`&$83J# z&@4BKE_TfUTx+gRUTJ1+i($jSSDNo`W!Ul+$mM&s{CGdJ>pUlFYPkfC4zf%5qVpcR2rBsnsKjG1h$ZIH?5 zadJhj&ad#yE0>wy$g#eY!}E3N)DW28&XP^9?lv>y;?UCGT?ggS~L1c{R9lk*ijUQk&O6H+1tJew_`H0+OA711o~2l(iU&Jk$M zlIt>Rm7)rO4bLNP$jYS81OWjMFSX|bMWsketFjYqdOp5V#CEqkUwzVH+@hqrwzNvM z3jt^x6QOmOh@>^rFu_!i57_a+bonx=p&{JT&K8Ts_WD$mf{`(T!^gR2 zD9-;fH^YwSbE!~dspv6gR&6Qi^7+1{a(gPlr=~}F*Vr&p2y7vE|HKGDWpbNRaL-Vp zvclg!l;Go&qr8|YFk(vXA5Ael@goN~eq=w7y}E>9S{O>>2TthOmIB9dxp4Uk)1zZdrxM`!JpRIKoSk3cw!<^{ zxjeT_PjJ9A5VlFtbJ=zCtY*?&-`L`|ebcP(?y#KR#V}+gPS7&Ib$za^Y%w)4Nh&6> zOi9u6_}X`#W-A-iIm?Ah&)`mT2&EgPW%;)jlM=biWABu23k28+tV6N>R$ z?M$Zk8kQ z7=hLpLhym9v5J!|?fHyYCLf)d-~&@*l@)!;w)i{84wCf)c0Hd_%jADOvY%`a5R=uF zAHtPB(BTRXU<$#{&COQn3w&nZWL>{DJRetSo=stRM8eU;6f3|b4M zkZ1y?#)d-$ba{MxU_Vo zgjLnS7A0J{mymPAFnIo%XSnnIA7<>}VHN_3T3*6QU&i%ap3CNmn+8+yIA$z{GnzzO zNha>OkCiJIIse*g9N#xlIn`a4Rsii5k@*}?X9|4w`UXLLhZi$>ZcW8GnM|jAGdVFzP;^;e+hBcThg`mZ?-g-fk66qm9*^NT1rl)!X&6im$N13Q zNBG8L&r?We*q^kS+BZSmws_{+GGBl09Bb(u@4xppwDL&Gfc5oFHXVm=T)oUru}Cr& z!wmvP;uhOEhrFxMNLDs8T)e)_U8fE)Iy}Vm^b`jYao+uoGkoXSE0KuOZ_c;Yn&F`o z+09*E|BG*8jZI<>4I?d^m=U9}l3{Yw#XHukr^Nakao;ZK}NOe0iWg%Eg3;VOm5rm-))O8)3ceh2u2^<4yzRSMU25kbJY zf=j|M@U_O(nvu0objbz*K`B!9m4eHVVIW1QC>N9>CM79jn@pfE(>p9BlKh`HR*4Bg zHc&W$BEFR&B_%oEH_|W7SmkUMya%&e)YaSRI=2$Ahje^7F zqKmP+g~(oy}~Koa5vAiq)+Q@pz1wWn+{~&arr` zvQtzhy6#?VYL|~)zZEO)xb0T<9Xv!TnZ)x0&YgP=?c_MPZ<2}qGq~Di(_dj{YlVGN zQ=GW_E*#gvaf&Qly@Z$9sZ+kou1Mp>r-?6KN6j5YjZfm6p(RLYMIw_%F5W;c-5{7d zin{Y&isf+cVxHvU4aj9t2M^Yw<#ooQ$@9Pu$ZqVCNW>T!N^$0nQ*3Rl z@kif$ifhXoXc5LExh1(X5szV721+Z01luhzKflEEocjySl>K#x_Do zzWvN4R(JBOtZ#AbP>y^d$AQC#D(2eCBqsERcbnzbC|0%l&N3u^cAMgEf|0~Q5($f2 z4j*K3agn^U0m(c{DSW@c%)}^j2WE+z0>9{ySzksKvdD(}4r+hNwPob$aw%`iDO#8AS<4J2#34xZ=n z`lah!onPbXwfS&<)S=qjv7C*08Lb${cO90mUt#(Bl|4+9&hAv6W%FrXUtg+^CN0g{ zmi^n4MAoG2@d1P(#bq;fUG96sH_ar4#<1{mJYD5IR6=zqoE-kOHw3}f!Q^4_j#->MkZDj|;vU%^l$M77F^H-Pn zi4VPl!$;;=SX|@V>uGii9=2r>j}7zaOY{90M zOlc6aOf1vDk`fcxwE~=RlY}ifbK(fgTUjoxZDW}R8|fTYEJ-4jVk47ddug4u%?%c} z(iHMV-g?h1{PHjV4YUY7$ycr}aQ@;v#||Ihq5Dol;B)lIK0f~5d-?1i{S{l8B4*sg z(Spm%JACF74>38C*1| zGx&t-RNq}bkG%YPU0%Ab5z~ZWbZud}DLLP*E9$y@3?T&CR|GqGjtvj`Kr<#=ftCBzM+2Gh@R%}2;^r=n=lSn22!TL^y z<;^Yf`6Bn+ahQ*N{GE)C4`an`P@4U-6FhMLU7-vbD6|yJ9XZU<@F;)&{j>bVb64?l zn|$UyxA6-<^GT-m?E^#bmb-7`kN^Cos_d%UuZ;aKF*o@ zPJgIlPzMG9} z=bZ0~GAM9zd5W1FT9}w|J3MLJ@bDZ5#QQV;|V1;-(-Oh_g%;z<(1 z;`q_SBoc8BUb@QS<_?*>gX?)1Xof9=4}R!APTzAI_?q$=RpBbHN(@&vQHIZ~gv5+l z{KBUm;?tjeHwO>R0Scj9(6J_7)ZSL_Rui#tM^H-Rcy3ips9wlXN84(qp{UfWBr%nq z>n03P$pjSDNhXCLW?M~7mYwvCPP6t?LQv*;h=dHENfDl>8wBV;^WKN=<9!bW*ztIH#TelwG9qw6 z1=a9=(b^c;PtJGkfGw?WaQVhk>Bt^c35YWc11XzdR$tvMYT-d$4s4|^)aQ{1Ow-`5 z6Gs^z9c~$E+ATiqCYER;{zTEK8h3%VC)V^h7M=9OwyCYnoK}_XzeWKUhKaNj;h}>X zglUB$j%5-6g?zqrmv(sWlaK;oSfoa#n4rjw<*Q7PBsDw=hJ~=>B*!f5WRm>OE?&`L z%re;C-QdX=Ut(l5$;8wY(lkpmL{vS&LWT!;AwYW&1jG^vP+k}suRYKPNE2k3V6~Ts zoyDL|rIo`kn=eps9OmZc_}~XWh%V)4eB&G6V10d^BS(&~zP^s*IGCnMDwSevY>egQ zWkyFw5kerPWOHi^r|5(UTBT>M>oPJr%JkF}OG`_5UZ~$Wu1mpj8E-K;+J#$3E#1P4 zE^3Ot`xhmjJ1Q)*(?{hkTL_S*6|UleMwQNv(n=xGn6`&>UHm|y5CqD{4+4tC0}KuD6hQxePfc!~CUX{%qr$oIZSn{m19ncl;>H@rg>5 zY1v+`l`0)JtU}@78eXmHl$EL#thPDdx*S3v!o!`l5UBDoG$K4fF9=lWmLfn%Ow+{uL-3 ze0hO8-f=h6$B&kfl4zkz*PvOTgYdcz(++nMDJxOIWpTYMu~)pl4O@9TSvTqcl^c4)>vO( z=hatV1wuwzSXihqR=IvF=is37pj$;rM48Nk%+Ve+yk>P;hn#7Co*3PVJcBJjgJ2C>mV^UgcD?Y7$(85v=5ago{CS!~CID>H}?B0PS^^$2_q<@@Ns2OXXoVptN(wlPbG3u~pYZ5zX~Kq*Y6P<}Z1 zonnq+A;a#@7Dcy+781vEN$+godp;V09ZMnu4F#X2-A$Za4k;z^c|FEM0z|Ag{`(*1WD(+JfW$1UI$i{vsHa=A2xT#g_Ja9t0lSRj+m zkj-ZC{qVkwVQsLM$&$`)6z$fX0A z%L04pHY7w%G_I7GmKmPm6a?6@7;yonYmpd9q0*(>IB8kokFDvF)I z))(>UqmL2<0r`BMmtJ~_7himlot+(i|M!0%*LC^a=RU_z|MXAu)vtaPr4+?tkuQGn zi)?Og5>F&pSX^XtV}nE@fl`WiJWiodD24ZX+?by)9R!^tYH4OpZG~&Q2;wN7_ExlO zTTCfE1bL0KO*IP3n5DPPH2=FN2jJkE@7@g=v}u2xLs)2!|jsOd>TI zD&M=S= zE{T|3ITqC^lk&xi6op&oMl)M;*c`#T8CM0kW| zZkLPS|0d_pEwL`rjLA5z<8aqo-^ncxe++3S2vk7o;3>ZIg@4cWg^PHuhcqOKM4X2{ z_zB+r;h(}vB=J3u-NlPM_4PmC{9nDm;SCodz_M-bIP)&FJ&Wfnv`qCd$3=D*{J4VxLt?RPBq7G2ANoSW1KrZWSdJnu(Y*gDx zq3c6L!k2sDl^7_B65MX`M~SH#RQP)4Md3HwttwSjHC$zF+a?~5W7{@T zO7i(UbBB&_`mVb;_hJ^L!CT(;R!-h}8?ji7L?VIKnnIz#kz*&g_105tt=&K=#ar)x zfVsKD#1rxGiY=`v7K_|^+nt;^aUA7j7#khs-S7JV)6+A=<6%9e6oo>8Gxxleb1!`# zC$~jBX7k{?9%guW7|XJ-EUV;6Hn{g~_w&qOeS_7VJi@OrJ(v76jdu8MoJ;K#$;OG) zEZ(QF%}An62%!1IipT)%M51mcT&uP^Fyoi2oOuM~_=Op!<=DHe-tZEc~oW_Wlw44yOM;bC94#rWhj3yX_L zDL8!iFvVh#g@pySwzd(%!jOVgYKWPA2Z_hyT)%$3qI4cTdX$mTaZ*ELC})>=JkI#! z43=e+OeToO<9MDIo>G!XVVE(r&eajV?0*q8gz0utL^Wl$8}M%6bz53Z)Lz?(Y8C1x zy0zbSJK-Aj`^fniP!(lmDcfpmYm3i+{`35^fA-IC9EYFznV;eI+iz!nVHqP(BrKEd zoitB9^%TGT+rQ1~>MB7HaPs6yKKjv*vbM2>NqDElGtWHBcOQG6vuDp@+cw2wk)fd> zW@ct^GRqv@KTI}XZ8FY!F;Jz89UAT9@G#%8KwAC?6 zQU^i^48!33`SU#X*kjyv*If(^4e`h$kFc_`O5i(KfFT5zUVoL<9hXz5PVq~>^h-F7 z!y}J8!dJigRSLUH+;V6P-w$x}1%B~=`uh|L1=iQsky0`-F~Rr0|9$@Qk;_=tIPrwd z>dFGXj`4Fp_jBBL-+f%aex27}f1L{#&SMCLX&H#X=hFGt7#^QtZf*{vlpcBh{CQq} z=|y~}ut)LMv|pv0ZON?$wHGn$W|ud6@^_*^lxJ^NspMlcKCE`M-n5xYCHa+K`4w)t z~5`c^7vugLI$NYSFbPf?9)#Y zXc!tA3hSMFjaOcN2}^pQHATlEoz3y|(@(Lzvr8(KqF5~Q>Z`A^y0(mz8tn!M(;ybJ zdHRV*SzKCXa&nT@)m5JU!4o7bNo;I{-Ibk6fL>_DDdQN;G}+Ar=qK5xpGg#T0<>~; zwF{)|7S~R+>x5f3xb{oCX1KP_`L0x=GNBUj7|S;jctrttDvFkB2f&(n{8mq5et z@CZp$Gji-GSI+HLc%UjuH7|`s8l-N~%mUbJyjC-K&9VZ!?cX3*=ytU0#q8RMYx#Gt zv}-mFNp0co$;hJpS$`!Ok*8*C)TWiRUY_x^zFEQshb}XV-hZqbu8u1KK!P zO=;HxUX;-AD6kqQMZbM3e;>uO-7l_<@H&-FmZpAjZDs^8n*p!$4p-ufB);d6%Q~du zVHB(`XkQ_uM5FKn2UBQbhD3W#ctx=e zZy^eD8R9!jyz@N|a@$>}DQ43Iu8V1!#8X4WQYpx7<87~j3NN5-`Kn$<7SANHkPocyPQB&*8388&GOO` z+uPgq#6dGNGt03{^Ps;{rcTSPe$dKZGuVUreo*i_?U?<*doyU&30@S~?HQv+)DS|D zPG?wNTE-88j(}T&D>_)8{VYKcVAwX>zw}EGvuh*6QD_Q&fi>3ocZq+;&wKwZ$2pFw zTmrbaD5bb~@dCv{0T4*TKm`Gy+1cJp?jGCu4DreeOSS<>&ua7y<%yjFFKU zes}tJSxC(DQ2rszb(CTVQR!;7{mfbuF2M{zx^F3!$1ZBdS{nrPPRkq#{k%1Djp zT)s;58s@0Ah74jGA5>_=pghyPwABr+Zxro%VVY)ri^?=+>+MW6oWUemURva(7hkAz zuIx#iY1a2jq+U&(#%KK&QA#{&c1o>~tgWpgWsQze)7NHxfv6tkD8D-mNULw#!7Ib; zH=LsuR%3fnqKEsTT@>2Z;@K_jI`yqxe_H2!H#`gFaqS0o6!^8jTPxo}G?_frY_dTIcfFCN5+>Dz zaLrbyer4&X<&BEGZHH^G{d=?LK{rm=C`C4Y)EGZK^cF)xSZG|Db6%2zYHTJ8Q>egB-MS%53N-c;t$Iy|63tLUOjD+^B4Z`uubJ9ts8S0K138j6UfJI8l z{sRXvOe69)gN#$^ru5_R>ar1CGIwc2Bs8pLj47zPIp z9H``GPnXhBrIZ{#e3+4u5wzB&lRn&=qv&g02|tWN)W#LI*$Np|N$W z>jb|Qyg}16D!d9~>`_ug{atXqbfQ%;41;7cStsYNuCB7UxXAAAF1Bq~`qFb;R!8EL z!rT#E4N6pzsMU9aSdIHJANRZCcY|v$a9f$mZ$?BxyCPdPSeE&us2Z*Y)j6e9UFf=$ zl2j^HIV!(ae7YICMJ1G>)J`YGy4Ao$Rp`pkYT@)dp`v(oTYc9_EbPX#+sVt{FYTJS z4F<)G?abJ1%(Xg9L$$2F8gEvDAYgNIv$Eaq?CdZxF~Oljhj3k&-BO6SVHlND3I|oR z4iAk(>z?$NeoV5>R>eV>cpG8%QwABn-cA|rSIirPdAya0UTfVh=UY%LK4~1-$WUQX5TmdZn|TXk>1_eW@ct;piEJQpUGr6fBt;s zQpMVBO$b3Mm11~!cwlXoOArLiOixoR=aq$q?QB)rBQr&BQCAQb;W!)t|Wzj0|%XcuMN+up(Fc`jS4OWgnV zx8D@&5J0h5WOH+q-Q8V+AgG*@elwWDbzM%KJjqbPW@}@;?RMI4`-AR(CuOzU_M(Jw z_X@AyiG8za7bPaGC1aF1_xhE~%#4q4|9$u2dfrWAkU_=EG%HFeT-Rl8ZjJ}vaUYk? zy;`SuM+x`t1(#kXU$a4s62H}|y(S(Gi|{`Wd#jx9bN&lv0FB$wxmdaku3@CK3tmzWWS!pT3>T=UySbyVG=q>t#UO z(XOBTgif(rQQ$Qbxdtf)-AvjI0@uFq`tZBn-VuV<;oWhEjvi-hdX}x-3>zDpWV2aZ z*R7lfRb#iH6uMe}(McW7;rqHPwQ9bm{GF&Ck|rA8(>xha%FxuCOeC3{oM3i(ionTp z^}>1b`S4ogzKAv;-Q>+Gjs36v-OOtCpEItVaBo@fBM;rD+Xa%938j=K2z-Pz85$jB zcx;?_Jb_`D;Y1Tv`A}Bm#2OECg-OEyg^yH)A1cT4Q=RBxKT27GW%xDyEB#T^YhB?r z&-d|Mhg>?%&h{owAs-&%*21CF&EU7IKS)@$cy?p=ALK-i(!Xw$=0+3q&8A(i@XU5h zQT{u0wh0o+VGPs4bsbg~!dsP;Qq421Yj=b2K?tvM2Y07$%5THJtIQ(mnMc%bNVU(U zl*DYCcdV2>y2pw>B8E}ob?TJ2wmWLuV{@qx=1W${yh}O_v zL%s6ff$!tF9(kE3o=A{Nrf`admM1AjiJ*F zS|;f5FzQ@3I}q<~r+#)*r=6bC3%oMSX778ADi{>LW|WWOi6q6MLoOfQF>UOT(VNVA z(PZX|@@g1FFib3~{=}lig?aw%zxphH^Kbq496Wpk(=gcG-QlzU z{GYPCIA0MZ-zYi19j-qNx<^C6k8tX?TiICO0U?;2-cKT#tiTQ_`eyYbTZ)4$4&(b9b`C53Fhxg1#fU;XqIHR40Lqjg_Y|0yf$QidXg4obR5 zeau!ZoVpF8;axN4l$9MMv~D@BTe*(8cGu`txoss{1ir^cG2qd($v>Qx%rMR3;#r=1 zVI50ApaN3EBh1Y1BNk6!+cCx_#@N}~uAB{A#Gz3vE& z@ng-}=!SL`9iy=U2=gX zR=8eDJ0-qTD9E0jw3)fKyyBatMW8f}<5YBkW=GCczH9Qn?8m5MK0pdliJT2o$P7xW zO5V5DVJ=9WwWHd>_7RjcvjtT9CZr@Dv++HzFPXKKB}51jD&L6&p}D&JK~3jMOz!(W z`CNPD`)0`0gAj!V-M1emcrDGfA>jIZ-DF9=FN-u`WomSW+Lf)|JgaLb1mSKJ`bSi# zyBHFwB}ys+-!Ew%x(;4-uM)LQ@A0+^N=J;=^jB0wJc-bH@9xtBk=xO(SS(O179znG zLXgX5N`IFztB2QZi5h<0%eObHZ$C`%>TXopD<){5YHqCcsg>t`Wn$K<4-JE>btvms z9O9H^e-*C&QdDkK5+XcGGkhniZIwSPwO`9*wGNG1t5=yRtGZCNlg*CkY$R$_rL>>A zy$oWM)xIBiz4X7E^23B{t2!-nzAM%rU72D)xNFqvzO_tJnXpY7s!U)}RVd3awAQ7G zT5h}4rWEY)m55recWrwimy|7M)!Yv1MVPX&pypt=RtjaWaXbACO4RmxjY4gQYZQ3B z#y0iZzkYCS*Z)q@z%B3j4xfdWIttlPr-q|+?J8ZPfHyU@QmvzF!bHL_5{VWinHoS= zSNwYUtzN7uKd%oXsa4Rc?N)JZ?Ko@Zoo!6Ksa5E@aRRo=Mr-w~+X1c>dk5LKsPMW8 zsEpdbR`42e?S^*cy6yTVJIR_AzW^2AZT+OI>;`RI-?iLXhEp40SemT0aLe&gm5=KB zS(WKT?Z2g0Wh+#rtZx-*%xk zdpzHbX01+2jVLik3yTqr5j5}vu(1KJwM8-()g^Cv#T2qa6O!mk#iGw z;F}VwuuEVV2yKSpDg+pT8}68fi54-G0JKLuzeRrRC>k)`JW}}x?U3A^r&mi=qiEPp z-01~gC)!1g9PVZeJHhL>4s^)*Zby`EIywk@e7_=0w*=}P*YLM8VqkzaER?jtND!DY zFrgr9gjV4WA>$}1unKFKZjnHmNI*#o-%4Q>R!WvT*)!gqXxA&QgQwkK{Wg7vg!I!; zR3dcpJoZwecu~6@pl-t^nis|J#!F}+Km{miA+=vo9dzktCxIp~lL)_v&;bI77uGA> zrG-GK07U1+szKx0&seM6 z5Xwgq@`4#S^%3!3NjLBYU9Z=9*Q|~dLTpAM zYPY7aS{RLgcUyW5QfmdPlSy$<4y@KTrdk7mX!u=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81fB;EEK~#9!?EQDJZP|U_iG5bs>BO5~ zew`BmQ@yMTk-_c zqC^suKmn8p5+GtX8lAge_j~=)&G+OTR`MTf-*fNl_Zk2xiiE^osK&eJoE_F)d;Qk> zh41hC6aV;^e>ngkz!-zI7OgZ%lJIVOxBYQ#`qy3-C!a)$ASD3t|K4rywm*JN2oPU? zV-nu+N5H=;ApiEY_TBzbwh&@Jl=y@1Ng&|;$#Z_kQ~3Bm0V0HO&-2E{F*BYEo!_5I z)js#T?YpoA@2INk5C6vPER|A{zIecvi?PHR4Qd&&d7jEmibOWl-iqVOT0gusQs zZ*5Nj!PgJw{FO&HSWWf2Lh@~zcMc&XLWpm>qJ$9Qao^^<_&vbgzfGnyj4@FZ;@ush>#zV9r* z{*5uevoqyFZ-IbW-|> z%>Lep^B2$3>-EUAV*hZ2 zlmewRN^4RH*WS9##^x$QN}6)PqN-V6Ut>C3&>!@0&NG`F;e;XtMVb_%na*EK&#% zf)D~yN(dmNz&T3@kftft+E%^r@!V4{-&%{c-M}Qk^=jE}ou;r*C`g z?>H?idNP@EY?+_@d-C@m^$@<>-fjQ7nmGQyz{!r)eyM{G1Og$1rNo4H3Vom6*1p~6 z-^;PbpMNjM{!yR%`?=4*Nn`Ve{d|9jV-p03d$`3#8xa&jpoJ6=1VXgJL3>hrrFVCW zciX>hP2BbOi6t*M77QWoGG0#3j3OMucd6+Av0769ZGXN${IL-t5Zy;7?bs&KQp#oI z^v($C@6Eb+yJ2&Tg?T5_>e!q0$Et;I{nJwCJ=MgwKlM9q$L}_LOK->@Gyi=i#@T2jtwRu1h%S}-Mj_fg8(T`1mCxI zlmKQrp^@s;BGLxDT6K~TD2j|To9nIp<=dEnTE+#05J)L-i#g6%k}RXCD!gqF5fp^d z8U$Dajszi3Cg*Z7LLg-PJL}{mSqv{V)>B!B05Yveb#$+~s-oWAgZ5dD`y9f_>M7EM z{LB_o$7>m57>_4NDHsk{P)go8_XPy+@utQ(htvr=$(C@6`Fuw39&0U&`2vDRN=Xos zywgP`3A4&j8pk^?hoGdS-|L;YibKFT3n8GCMo0+=tXtqhwLFHmd#^%(An-=aC>W%{SiQ)1Uq{*RRhRPnx^> zw7HQpTupiI%^ie*htIFk?_?ZKN_s^`q9x9I_QwmZUwsqI94X=a`SbL9edeUC36nVE#x6>g@)4O(?5CYTLoU>;(*;-%6c~8?c%;$4V)1Z@tqSK)$3fyeY!8e~L zct@HQBx#Bif+Wvz)-oF%;k;u%DR7+*$MB@!!8(tWA_~59bh`x?&uw6vIXVP_b%-n> zG;80x0>2wIjgAnK< zVS8M%JuV}_PC%{|=Z6Jb!ved%PyPBEQ6EkcWVeINb3#?)rc;7*pcTb?oR^4@?7&7`!;h31Y)-9D#KivHRPLTRv;FdgGeg==b(EF)bzi%^>2r_f9Y zKEwq;or<{}JBn0-D>b5BtlzHW2r01EbB>0!UI)?yoF`NzBq>-!@E+GRyytyS@iTwn zFCp_H#^p}zjuQh!Dv8z_ghXkDwH|9?6g&iwN|Wa)T5Ha&^*O(>!qKec>du7AXNKH= zc9p})g8fO=4uC)@MV6){QX-s3N=1?ioQo?@mZq$)u2R)C-ut@-S8IjVF;Y31Oc)>T zkxEcHK}cxIIZ_BRrAU*6+6b(36bKTf$ye48A)o`yCS&p}AzK|l2qcMSQ8vsMC25)< zg`_b}dryU#EGUd3SO=m)HX{&%v6rac1}O@w1^YX@)OAfD;Cu{#&dr?Oa7daaG(nK) z6r~ly3zSw!B@yj{M4|{Gus1X8%?uui)^SA)0(NE%Qftv>0_S7YzLTfSYK!m=ArsOpWouZFsQ4_?vZ0$Nl(i*IBnNYYC~~CMn4^8{ z^Z=-Os3O&Kow$#LkKL&1?A+BVUdz# zDFTmi4Z+mdDxg$OQsgvA+$z0y$fA#HCzu)xQ1e;4g}ZoH6Y$Qq>P5gh(@s{2)+u;T zXaYEouzsm>2^2|^AgrOO8|I6e;5`8_1RS7($NPXvB*6#jMct}VV5$ZoCC=1H;phxj zsgZ1tOIA850@$8ZNFlhi+F@E7ZjVcHW#eSYQe4x}FN$`Blq4G)xT-Ooe?|}%@9D-c%(X+$Vao1GpjxFR5R@6^gHpm$vg^Dnx<@RoI&b@s$7t0 z&Djg*SuHDe59WYG$cTarA<*k~Gvy4-4O7kA<$S$<2}|pQX%LJI!l}5c$aRf5>pyxqcPIMJRedT zPd@~Pc|wsWgn(2FLIq{xmxHH>W2F0h;(HI*}|&z%8;dHIQbJIQ;a~+JB*xijhYA^Y4ai;dDWsCR{$Vf&kv!KH}#7B<5)-jrW1sWQ=JHTbmmcS%x%00(B_&G$qXE)OB;pGc8(m^4O>k7@JZqrnss^JI}&NROzWh%D{V^5@OH$VW0VU zhKk+=tkslKQshP4fwU&clI2i)>zM8y0S0RuthYGt@gdMy&$w(@>!#G!F{^BAw}1;C z-@4JgF^sNULFEPAGiT_W*@|Gf6GZ@}H7jS&GdtMB)HQjp&#^Z$_`uXy=F=&|sv^xY z);Bh|apOAP2WsmuHc*6stt(`whfWf7(ZSSZ)FOhTwk0lTCSIV0hzR0Y#k@9jvV^iR z(Fi(PBZEf>NR-47nAQsr5-k-nc+66@3DnNuZTvXs=5+InPM*?O z$M(S(-$Ksav05HH=!7sD#go#E;4CZ_1f`*=m%D`!pue40&RLI6WV`bUoVzn*xVh40 z*v+}VJEp7+A%OAGh!sRn)NDSXEElY;uCg*5FrUpR7Zt&Jf{>WnK!DkN2J^QmQ9`h} zv56qsDMhEpB!v(#rh=v8-=hW=x$U zTU(`>MK9UumSs7tZDNff?{t=Z2?WRzb`SRPuf4{jk3Gh0KF2hM#e9yjp1jiqYoaZn zHH-O->2yj{8+-^zrOApuvw2C8CTJxo>xOw{2*B7xlyBWc#V4&x(t3e24M>5M5+eeo z^QbI~>JJ`KS7gp(158?HhR``mWgrwGnCS4R4O^=N(nMohVX)SnXp3=mh=P!11k*&1 zR9zE{jr!M84x$F3-@Z`@#PWjcYdLitA4Z-!rqfB5Agx}Jk|v7#&#m5pvohB6=ItXE zvm+9%NLIGUiUO??f{c?U)hS1_3Dy{Ns_1sQcjX93A&@F=p-M`UL{l1vlPM{ls_`HK zrGZYjN0z0Srbf-?=&HsGL9vexFWnz;j>yB5%BP3nAj_ zYK`UGgOBl-{zre7fBsK@m7U!KG8E?@eS-hNkA0B8^MCyZ_^Kh3kY*jc_o%GLpZ>Ey z#XtImzsrknT*m`_nX)&YVn$=uSJqhTuOgMiny4ByRf!e`qu}B9e}o_Wksso-pZgqp zuil`n8?1-zqd5*iH;qn^UIOob|3^souk-b1pNFCV4?pu4|1#UxUgD)UZ!)`aV+ku4 z#vr7`FBU9r-b4yPv$@IRAN?NQ`_M&Rdi@&bw>J3y{o`L{|L~CP+BNE`ii|N;$+@)^ zR#sLx+}R=R^hk;>lj)qgtf;L6sp<4Kky!`1Fl1V?xzfd2&uY&h+6B@%Ph&mX2V>m! zHq)kNVJt$Yq^YLYjcR7Lm|<k*1V3FkBl_8-vQmNGZrtjq{#G z-LP{wp)roPw_prG3MflRG-yp&I4JUHUz}1>0-SiIPHR((g=KHQj2@9=e>;%qxN|HP zhN`hR=Q$WJSnC%gS}g@bDM2SsIJ?&4>SD%9uScyrR87Uv*C0^MCm-^EFsY>#HV zc4LQ2moG6s+~;6C=gCLzXFUs?+1lXd_19Tl-(=(57JCPWTz=#+_OHFj{Ps5IFJ44y zP5;7qvi^Ymoo&K!mGc)bvUB@3z4Z+)T)4=^3+K7HeLy)*`0z(RPF2m>zIB8B{R1+s z*;-rW{QVE0bV6k;&0;}iELGiLkQlGXx+|#83WBHxO%^rfjs3eOW}HhgccRW$&;{sn zifa})0gZDg0$320L8MXt55^EeKx<9ZoZ_PEd`y4!J}{kERJDnAhx5yo{@4-@!AI57 zdC1b`^bfrr)J=4gv@xM$bK#zeN=Yi{bz`t4#yReU<_e)v39QyR7dHol5V*R1gtbvp z*9RRoRys%tN(-jGLIi~qmT@^ldV?q6(mCgXry#DH|7?m+QI^e$h?_=j+%xbqFO$4i}YkaLL z`GJQXARDZ6?d505q~-Z%p2a6QKmWh@U$MV?i~ApbfTKyt%{N}Aw|0iLl~tzWBN|iF zUpveG-Yq`*(U0(@FFL;O2Y(2eba>;NzsvvkSAK)RpijTwZ+B1=caeFF-xy=5j76vv zX~3K2kPoR`t7*-mDy)KYa7t?MTyyKOxf04o22l>F0kFu!d9Mtf}_8aWo zzJ+j(-}+~tW^nOIe*1HuJ z(L*JYy1zn}51Cgpo_X;Vf}An48F_!eBM)BWH-Gc9eBdJ=;|rhrH1|FEF|NJ&4W3?I z;n63b;`W=*vvvP_DeHzuAA6LlDwk`n4}nQpQZC}|zBJrJiEU=g4j=^2rVyN!GO8kL zYowd&AS8A+rMZ0@tiwvdjvwKrkG>TYQb=rTS0Lm4HaE_*xp^VJ?GOmlIaC#5WdLnz z>@ubSOeYf#4i5++urgd>xUza8AjBBfy;=aI_sEMEL8{|S5#-%+5q-HzNwk*H7HGG% zJWtSC#ov@_{mF3)iZ}K+W6{JYloXpsduN;`xETm0zYdI!Xbr02t(_1rbre2 zOtaZZSuGN}Sql@8lCtqkOUtaZG&W#ejGM$5N?3AW1tpgMY2Blfo+C*HbcP!|{NRJ^ z?%v=V&wdqzz?E}WMa9>?`4R@n!L>IT4%d0&k^2D&GOmED8)xwKl&jaTV@=H)Z(LzC zn^P|4SRcS!);BkK&!rXq?l1l~Y#&Z3GR1ozzRc~L*V&(x_y7-FJWDTyH{W=JANc-1 z!NK)cK_!g#cPR3V2OfTey`5X^?`?BydzU};<3G;t{>$Ism20>8Ge7(9u)4NF(^TBP zb({Mhew>ZfK3SGAo=vGtLsoQoPLQvM7}M{t#!TjdOaS0{Ba(C{Bh2mJIloj=NS(A zF#s0=!h3YDOL68bW_z3F+EtP~r#O2SNk9aTcNS+It_k?Y6Ko(@k9Qss97@FWRV5`# zNaVak?Cc}<4iS5Ys1ThjO2%Vm(+M|k-k>QLXj4-j?J=7i#h{-QF>*hdaBF9WTRS`K z9vrZHaKLyr@EJmKm0H8&XX7Gy!6~xdHFN1q00%kLcz;#TxVr^ zlcYC?-J@cMz8Sd3(xQ?{&o`pp9#{L+^wgk!R3_~-xh)2wf7@R5&x9N{Wnc;yOdn(*tt^2@yXwN3g( zj!IIxot)8lLf-un&Kkb_wP$$w`ERhkwodSl{$RlF&JK&RLWY59kM{=feEG}Yz%)=4IdxrARTWCLlTPas6hhm&-EMomluMT` z#npN`yHo2O3<(5elHfz2zI~hQ+_~2K(;YlO;~g$l07w z*D?MuTf}I!)=Ox}WHLc`$9k`zlW69(VKy4k>kpUnaZ#2n&TCGZrbsC%t1^ZX=JO~J zr@UDDULe|&KwmuASjWn+gEchJRhEkHMs%V@= z5ztC7olaTQmicIgkOH-`f|8P>@q~b&-^nm_$)ZY8QZSx1SOjHNk>ycE6~NKK0bl*f zm$-3rn<5cNsW45=WISe=C)jevsGOma6yH=-b&Vjfn9nKl9HkUZ(@=Ce%;xim8Zd^r z(rlewN5~mRhhv-*ND+=VKc=%I(k#&HYechx6dAj_yIi|=joEC55P~yj&ak$&#%wmD zXd~+Yv)PO^O=+5j!^1-+lL@ogoq{1mT%~2F143X%BbuYbrGYD@L?;Qx1_s>@{ceF& z3ga58P-E-~fx7ocnnbAgRJNU{P1hIx)oG?VuJ zv~zYbozY9PQ!%>M_ScsFwT8qj~^h8A#L1;2Quo78>FW@7ZwT-qP`GgDI9!g5)LDP2@6(Xt? zDG^CRa1JjdWn(~U3_8L*LLdl%RuUHk#svmN61{1Sr250wRuMU6srxBb>2#Ay`>i#WfYCYVbbXL1OUMTW?{EVK^Lecz8sXWjye}gA_%I z@!PDe^$0=WY<$sDf{+0z16pS&nPH9Nt+(Fd=;&y9UGF_dM@NxmAgm(T&dfg7wQAyb}IOi$bRbEPo z>-PwGO3)H9nE(-ZskNq?=afPq0>}`VMM3~?n&qmm>IQRkMB#iyKGY4=4MVMw#++;j z$GaZ)XtR0E)oc4pHR*U)Da#Yu6RjneF7%NyMr7x+8OEBp^@h-*T{{?A6GV;41M}Sy zVJu~1C|2`UkFybuEufHs%C+ze01w6o3MFU)^oJ`LyFj_X%K9e9`e4x;kYyQ3?s1e$ z#A*l;79fs!hTdj?2`Mo_kY*V=jcC!qV2GDwg zDhiZNa0up&Wpj|@L*Uj?Nwgp=q`#W}xU>(6Z%-$YmZx7Y)qdJ||fhZtIf(R7-E@m>0 z@4IPOG$q}l%V4mIae{+`gQyKG7I!4-9p|z5;5mQ(JTghBd|W&V9fd@z6qTOvnfbcL zmDTb&d=()eb~Yo)izT}JcvnK1zU290L8sG&pwa1hyz3%58EHAEtQ)G*(pXR4-9&a~5d2aofXGwTLiwGKJ?>_T z^^T5Spm2&JMV^5Fyzop-RHZCa>LAf{an#h|L{$htmgkhcb&|7>A!4ia|v<*pjKyiwKR22m>P4P|Z0d3vD z>DnqXO_tAo47R<;juBOvy}b!a>th_>a@7(-Fr8L_r(0yybwjV$qiGtZ(+>Sq+!%DMn~W7cDBcEVF5~tR@WBGml0QR zaR&w{5U4nUFyda*L`p&D%q5H}2z5j7cS8xbdV-Zq^5&tXa*(KKnAKhod>j)k16si1 z9yvP4{krSk-Y~8#wH3%LV`c+&z1{mYGeft*5I*L@|fkkBq(~6EW7+c@fhhsLz&@v2WS%!0tqoX6Lx*;g& z7ZUH{E@O7K84QMTNA30Cu0mfl|yl9F19xw2OBLMhLJrNcgiKTqjt| z%eUqvsiaq=n9A`Rug&=6V;!z+*Mv0T`|itm^DugiMvDk&+~{hqAJn|CYwp0B1q3R1 zYGaw#1|cL$3#{`v+d`&;;mBl-TYh60c z@!lvPID~+ewPJa#Mt8ZYy36qsQxlyWjfb^!?ZbQ2jUCFxjIyjyQcxO;_kpspgz>Z` zv5tk@ex(i#1usr0Pa8$zw?bRUA#b^=Xa1T z9DCvrqSehUjjOSyiK>F}rvxMBhi57y5#W{NPk-<%c^254I==S$gsnl!pZV|^zWBn3 z&t6?{-)4`qD>;K+if=441G$#`y?=2ls-xo0F%EbNEu$B$6$}Y&GFV&`tZArB$@=Og zJf5@OqGX116}4Hgv-die&wrS;?mBte0pU=gVeV7Tu071dmp;zCJS0mx^t+oBNy=}3 z{TH~t^Lh*S0q^1ji=LsoXG6^4@pL)~HU&Y35*mC!m5*NoL8pB78 zBP5-Zm(bL(eFI$d1X%~;S^2gJ&v#VU!WctY-g$1_+82M@L6@G7&C;P^Vgx zC6ueHP%h}22qh0b;BAd-8mh8n_wbO-b7v{bl7syN8dIZ`j)^ZvM|8R!E?vAtuh);z z<7vggw8HqXtk$&BNm(Cu+GLgp_R5m9g$+l;BGDQt1=c#UG)JRb_h`(UUM%L+jfvg} zDdR2`JjOPJAX!nO3=7K)3}(C zW<9~jK9451xPJRZs(MW0Jnwn%lcdV=>}#K6(Nv6Phg`e)9L?GVdfoG+(s1R*3wTv9 zI(myN?XuE8!_nv(D(RBygtu2=ty=;l1K1)U;eJ})`5x0!!&_Ue{FXuD90(S zF{vr=3p?}W-@o#;YH7KhW-mIO5qaD~0HmX;4VjckADGn%-R4xT0vXIwYzkZ$d z_4Q@EB5u|$#zI0DDQd>kN!*RNFhnHjDD}jpg-XD z_HC@Oj3;AgDPf$4(PYkjXIDs+#9B`Xo{MW8!fJ;bJBO5&VP(+eaO7i(s}FSY44r6# z_Y_&mY+f>-m!!Q6?;K@mqyJlIyb7p1?iRFeRUrg*S&=A(bC$ZP$+8shU4$V!htO(C zlYh+gaO_b!*5*#=Z_6}g;?U;VIpq`JJPMcUSLQB##WmMHPc0tkP ztgWx2lp+L=QgXQx4u*Y>4oC6%e6%HuF{EvthP(PNNXBn4oy{onoIG#2g|wy(n-hS8 zX-#b$d7@bBXLrC==JPp?F?eekWI8fbxPS>Uhr|TI;k+RLgCb*AR}|A*taWm##<4SM z_~IA#dH7-nMWEmB<IFwVzPT%pCnwW$vwglPO~5$jU`YnkS9 zH|5%_=FM5n6T^a3wszDXwFJCFyCd@b_7Y11X!4YWR&;uORJVg~-Eq}uLZcPgpwIT` zhzm-wGF(}%o*U~M%R!7_S&3GX)j^jVx1(yK+646AqdvMe?9s_n_6|nT(DpG?FHJOy zvPLP%Y*A6y4S8O$C}#*fP2HesOVz}L{mC>Ys&qOjX}3d`YKFr;T5C*GlV>T`nq}bZ zn7XE_YwYb8FuN~PmnHe2PslQq(vhr8#QxUCakx8U(KtG(qPN*2Ph(K8EK8vhTvC+L;S$K1A!Jw0{(oJ#3<6Ma3Zc=eLo0Dacxk4vt zgv0xQXp154O>0smS?%Vy!#&J+LPw=cM2EVm(5a#<7l;;C9RS+~Nt99uC$Y|=m8J@U zQ~(l;cSvh7brc-cU!~h;sk$BS_#+E?Wdlt>iO|L{;!N1u+By-2Qw;dEbtt)@F+;Ra zREH&R~pL3SpXN z6h({&jVJrKmaithBgxXU)%I+my3AGY9#3|vSpyGWqJ{f@*R;nTd#u$WT7<=XQQkp1 zF2r$==?~9DI(7@5Ue()Q-uC$f<`RE>r{lkUdpk_ym}u*sB6+Xdyv@b^om4=L0sMFF z<8gldcQRggT=W$7<8)WU+y1)qG2S+&-*J0q1lD&v`r*4zp%OwwR>{+ZYp3HF(JLjF ztINCX-S)?+1vp^|`R?=)yxZPwfB5ZNCMuoKZu}nGw^PPXA9vbl`F%fyxcB+r>e_cf zPVe#g?gx7t-uw&e}5%>1K{a(iI?Z@8hIqyZ$|Lw-`Tj^VO zjln&};+^{a_P*S6yx#T>elLA{r*Zl=O)SdlZaM_#@Qp!eNpK#aWJ`e`pI#;jzN!$X z+SbrZJW*OIsIk zXjukLOrjDe5O8QyU!B7`*9P2T-pa9F>#W6x7-tYfFUfJ=j?+8i@ez*}+Hs6SDq~HL zHgG9hf;`=(4Mgf7Lz+d8lWpDaTB{hjZpi_TpA{km$axd&YaL+Gc+*<3U z+gyr>RXcWwIBP-3WxuU+G0{q?_&%EEj^AAy>ryQit_2n#m0G@oYmq`C1$^lXU!c<;G8!GCG%RKndC|iM&)V7=(luCB@ZKjLia@%0 z##g`bBB>G--7aQcGOZi>-3+Bt=2gv^bLZGx>GIXDeU10L?}Kct4oK3BS6_IJg_BGU z_vsFL42J`5Z}0JmkADJZYHVHcrQiKBy4U5Q2Onhr`V9_dW7Y=i92_37b^Z*~qa*VE zka{)-ozc{Dw$5JW(TDHH`@pp;uQQpI1ZVLguvpCLc7}LkS=ktJ>*j5SYpayg5w(*D zZ&}$mgRAC9ov@fs$$CRvRYGta9ZfiQ`7)EyK6&2f>8GE<`@r7r4X)qZ!8SE2%}Io0 zQP&Jtx-8~3BEVv?;Ns|A_a0_@m@nVd@3XKKDHR z;gBNFxpn(GdETd~N>^9gB^Fh3e$yy4cZo7f{-;MR>pw$5y^zqiZL!6Cig3j0R~6h($@ z8k(kJQ8}cP%&%UFq}H2fIJdRIXfma)9lcyK8&7%V#TOW^45?}pp(Tx_t}BFq?VVd} zoVi4jYNn$R;cew@)GjXEs1F+qZ$UY^<*_=*G{9 zl*|_;=gyts#g|^D=;qW-Bz$=7wbyv^eeWgj3U+SHBgANa25UXj*%VLCcyFJ@$g^0? zX^dxHH#~TLlUvvKx%|*W+}^%{_h6cu@pK*q<2&3j?pCFQ!0g^atg%NU^2_&=Zf>09C|4zQ9WnF6)m5Bpzz1ft1=iFw&NCbg zBcIe@NTMa<(HICUs)j_0h|8A(XB|puiXvlgZ=W=a^&wU_wpd#kVoV*cYa1q$Nv!p! zB;8IIsWgLrkGfoNCNTdjaAR#!iqRW{xTL=M1 z2YVcirgSNk*ds_V$nHbPB4fCeIS;+Rz*Hs23%5V;HQgfitYGZ^YoGmUG7A3BCRbsa6P~SY2NQ@3?jICXMwB`h6N} z=yW>Z9eexxbUI!7y1&7utbyb3p=tQw7YX}i!x+oVEoerHm$2(7wCiDk`s0vpl zH*Vf!xUz<`1}R1C?_h`wo+QgrN-#P+L?t;fkBAhh2tMlTd7dxp-o=~=OI;hXJa6gw<9)2PAOzmKHVCEB zN@1N{2Bn znkLdYw)T(r4j~kIo)LmavB}sy_2HW=e7!d#`$7-#pt7bVCriqDF zT1RG;#u&6#I2S02yv^6P)OACmHFeXFWf76=S}2T?vhDkE?K(l0#zK^)iM&opOMa22 zI^MrceLc=w5G`$zY!kn%b1li(4L#78A{3}9aCsy zI^O$Oyb^(T9;M@ZtLi$=C2^AS3Q$)O{(npgSJxF(>~rZLl`zaC?8ux$_qpq=A=Sd!4nFP0)(_A9#R738sffs3d3a<_&Hi z9*|`c>jk}D#?jH7)qaQCc@m{58^h%X9%g!QgLy4@`UCI78pC2S#)*`p+cz0arZ^+` z`1gGec!PC;*Is^}vT@vc>l(w24bnuBq#ecwJIEwsV`G)=?Oopg^hX)?Vnv{@J@XB; z1SeH>*&NI`#NgVkK~%9X1;{h<%>+RM+Q^C8lfn4p*)9Z(EcDaRAu_n{9`qzTT} zeD&+!pqCa{>2S_6na{~oMyeG-DpuCkSQ!o&6e-U<_aa(A-tBO(e;DiWNzdVUPIs_^ zZ5lQ<)==IuGlGvi{Ul}8u)F;hFTQexyvXV11*J7S{r;zUPABxU9%Zwj=yjQl zCWtiSqaXet-g(A{dwk>hmlzI*Bxw?9I`{S%uB|f}$8(K$bUGP(M+ZFo$P-*Ve+KUZ zZ@l&*w|9@|b_+rv>gJs;Drmf~sI1`Pxr^NY&;`EmJD*1@&8?js);BiMDl(cYG-=`? z>+}96AEm4tc5Ynf)i)5AJeo-7OeExma*?IO6E&h@wB_=8c=|93HW#EFXB!Lu{?D zQ8$!?s>A899CQUb|ZVVupFXj{>4KKfTorfNK99&6lEQRi{wz5uT8b(J)q)Ec`XpilkZKMZF zpx5n?8H7 zmar(^lJVgoySv*o zK~gT}Xe3F$i?flGttuDH$^{SJ{}?;BZ?U(t!|mHU47+J$1re~nyTfpEi+-ArW(9k@ zw@_&ZtrAxILxQkey?(1LFHzC$^-*s}LX`JVrK)y28XXnugWYRdf=QS&X$D9vp%c2q8Ip_AF@< zJvO_02jp2w)flpt;OyM_vnVMe9prqD1j?$S+w0+d+!|-IdAwI$v%0a#px4DY%V>0j zb+PK}Vm3o18QwO?B*j_Nsu+Q-tu5xW2~`y-K!dYPW-~h7K6#qb>2}ddVvLDIV^u|6 zl?b62tPBwT*v%}^NyOYZV+jNnvjsv$FWtPX=ykhviVpL|0%sd)6IU&*Bze&xO*M=8 z9G&Jgiy32qLOoMW@H+#ySExJlJQpC`q-ZF^*ohU^1K0Ejm%%v<;*2gtg5r@RqWy zfk15rBG7P>Gntx&2)Uk;b=^eXDrH!;b6#kG-hLK3u3iAWE=bNAy6(B zI2ZG3%BmzuQU?72)-_n`m`!KoMG_(e2Xf#oYoV z&elw43(lT9Pnzg^s#5n9jJmEc#_rEu45s3=g6|0 zB+*M_ziLc7fgO2KM18cXmgd$mC6H_jtt%DnBkLTA)|6F=l!`3NFinl~k*UPGmbP9h zvQ)DuD~ckr7dmUHn3^7qz$I-zelg|2J?d&h-)-tk;c;Pl7$ zJFaYcn)--S_c`v<@|ve&N5}U&HaM4c;FqV0dtc|&^-fN|`?|-+Ea{F;jny4^uD4zL zbfE6|T1$ia_&%q2r+{Tl=j}m0A)>S7ohZCP1cLkCaM?XZ71 z<RnDB2!ievNG(q$yN!**p~P!K?F~bnnAB<2>?oFvpIvo5GA9p-ZYlA zjSV_^P6+=3dXzb-S)@1y_=2nZhN=gqurILbSEx$p!xqpz)_pf^H@8>?hpL73J?sM zIT7Czndy!XYH3d2e&9*FD*@&^?9E+wzQ?uU_o=s^40B6Ha@PPXKfkSycMaAtkYAkg z-JR;=N%!u~Q9sG@7I&O`oL?U9Js9^IhI{t^czjOBHQs61zms;Hw-Da>McunocfH>> z4@Ss44*OQm628OV{#B0sR_C6Mn&`J@a0w}S{&#&?Vw>?SyqaKwQdC59nKs< zNcz15+ZcvC8&JB>bZwNB`7VC zD#D*-@Eq>%aCEqhYijVZE=I4LvcA@1V{^dDphM9~(22$xOF1t&npPZ)8v+HDl?2=H zSbxS7!zr4`gy&qq_`p}LH+=0zWJM1lX82_~@ZN`WQVlO%tC-A0OA!Q8I6nM9&ZDc) z&l9@2LQ28@-1FI2XLzX?^b|$rNp%#oy0Pth5Nu@$7Y9)=5Rw~{is!d$#{dY#?F8hl(Fj2FzS zhT2BqAVA&38W@Pki{-s%rJwUBp8i=X+ps7X2x49HH{X1NG|ec>2=_R4voGcgy4?=% zd+Pl-=Xmjj7nn{aF;JYP%;$5QbDTYQj`zLyDU?=}Wyy2j_y%=dw;Wi3qA19+ocDj= z16XT$;f3cpJUB$_nEj`dgu1NS=M7xEbcrXQd@?Smr!!B5xOdLCP84~bk|c`7xW)w; z%l3+}tm7voI2T$%E>OB<%{x}X0_1swbcEmuA(qpMs#(i&mvk6zULeUjIA@UpQmygc zakzJj>EQvvIy$-LiHA0L>U|IK_~Vzj@A5eY!$HJrIp1E-6TBr@$7H(Tty?3${`^}! z|J;?xYAB=7%Mi(pGa>1A;!5p&z`H z4okt_#IZh5Tt1r+geS>UB#vM`S(-$+xDeqMJy3Aci?bHtT&QFTXls zQW^%GYzeXW+Bdf8cO}!xa(1)FQ|~#;XFvZYwO3?`rYmxkan#1)Lqr%vH@O6*TNe3* zfAUYi4!!sA<3II5ymzc`ZSmsEFL5-PEK`<^i*>gfV|eemr^ve<2ypSf`}oGQ&ma@c z-oZgESDdCi@X*5ut?xVqLiZB?ehK)e1O4l7>gni?oj#QoyZUZC<0OhbjuhVTG~vlPm10v<#E>IyvMt+ zBo{u`FHK`eWjxmeL85ev>2V0D>8xym%BZUaLIkYycw-qK9Wb99qDA1+r2(J(_fP`4*xFj-{`)WT=YDL!4}EBpE8lp9 z`uZe3M;nz6BG4%$>+4CZuU&iQ^MPo`;X2Icpg>muO zf)6yc;J3bbmDNGYg+%b=BOC0EYOY?Nk>v?R8?dddL#fz@5JF42B$<~DU;O&3Je_}@ z#jSt~9tC`&X$U?^64*Pr6QMt^FFXqTfA2wJVFHI!IW(K%OGGLLd5fZ@O|)Se(YNd zhL*8dy#NxeP*Nd8EG(k6LaV6Lhaj=SVr;;+TXLcmT4@3v5j_1YAtP?Fjkg#dFe2bW zpkB;L(k@cyNcry^lkox7V$9Z1@MAytKECghPqVVpWoK{9=l{{ay+AOy?B@ zhj*Zp6d^p;HYfpWy$%mPaE7NI-Q>Xs&r)OxL$qI{jAmt!f-INxyHO>y3X&i>FaqfX zS_-mMlcoaG(l>?>pIavqoyJ81VwGEQO4${7q=3dq_KzHgR6eHT}F-%}U)N5A|H_Qy3+r6{eaf})yBbdvJMbx)BG*;t*Th2qWa z2})?v7JM1fl)8yYP|n5r=>iEN(0uuulwaRn(*BDO5ci!U{ju+(`TW6Omt+IaNaK~5~YbC1VPn6 zV=NasibwkyiF6#+o`c4+UrTP6b1FSSDveSJE;xj@T;9<9yFdMYzUPxaz+1Ox{QZCU zyL|J7D;$kycpo$P(j+6*noQ@MyLf@|!9II?J1nZ2?Y)x2*;^bPO}KeupJaB6&7{p% zlM&YJ2{g51H1c=^34vU;On@TR7)+D4rZ$ji&3sXF43LQ|8@g2^+p@C9G>O7Tl~X!g zh;*%yl2@S^ylQ$#i55A;hBa!y=89P)p0CZ20XjUS%|?c<6z3qzJ67fjmX~Yls?EM@C#nz#C0Sy1okLwbL+3C4 zH0p^5aBtoq|C67f`TW-r-ov7Vc^R2zCJRKCMiEFO0k>M|_G2{ZKvyh2pXDd|%8R;AwVlv5JYRxt8Zkfnld zp&9maw1C5^rf%ZP&pVn0c_e zYH;3jX(Qohe()il{?PmR%x}KLKl{v=86O_8+ATPgP3<10#h{!EGpIdwobP_?Qb22zW(3V&8WC^Tx z1-3bMV@jlwh?qctRGg@hAv$KII3Db_g6gsRBZTOcQi56CaBJVtD>VIXf|3E}9irV$ z9C4d>2$TeE3`HUt_9DxA@U4C=91clnF>QoEXwyT3^8_bIB&>E4loZ^$J!4un3|9)a zcjlyN%6lHa%yZ9N;mqbbR;@CA@p_wH8&gsjmEzjY0)c|y2_lknAFI`Anv-V*)*7m6 zK`=5{|}TEy~5|Z;8;xptA&Wk^CGaBMe<=4LaYTRCB|3;p7U#6E?v6BXFmT1&p&&ek3M{f z2RGl(#`-!d8>{pO1JrPnChrl-1sM&h6Uhwf-EAi05w*(E!SdQ`&-3~-pG7ntA7VjB z#IY_c5I9T|>x-vS5`=6q{;fjP5+5g8MREjjoGQ^$>Z?eYoFR|Y9O7tas5aRf?766hpJ zV_m@Da6-gnq5v)gjA>}<@dpu!MxEP2tPYUpws1FhV5LupnO+1S{k{(&HdbKJL-xCi_*~gj;)e@t-YML!!N;!##>q3IR%kRFI|d4OhmYeVi~+ z)r*0^+B%M=3o@GLH5Sc>elJoLO7tzF|h%>tV+S_{kwn zWwx_zQ>k6_AHr6tl+Ty%LD1p)-WUO-sF@6(H2Ty~2C2JQ85+&M_ z(5(=+jsp`sNQn!9s`kv9z@j#Eb49lsi7Q%5ia?;Yp0ajKD^H$ijElBRmS}|3%;z_hK?eh2sFO_C2hM*SOKKs|H`G3b+i@ClmVd4}}kPf`Ew zb0m-7kKZ3*U%Y~R_&!2e<8JS@lUU*oN04ZQQn=gu=#M-}^Bcbdhm&s^Y}VqK>h1Jy zNA&9|83!*bo!uUzNJ`_Hq{PpM{8GM|!k`^cm~XhDCa#|Kw7NtzPfOlXdF z5wkhk2l~SE*g#WsHLh9VpufQm*YP5>Rb5-gJTK{Y9Ge3eFXGCsQr+tFaT0fn_=E~e z@W=k4xSC5PPb@SE-ENA`71hi$Dx+(++e=wni5@%GvS=JHC~?L2OZ6+VC3>uZSqobi zZ6+QvvN4to81G4B6hs>WH;yU}XAV!`@@5fNZ*eNSK*YVVHi7M{e(wmoy@y&~ z!M}DL^})vxo2!IbiD(1R!TVE16r)C$*c6O0-mD2z)uC_6~%k5b(hVFY@6h?jzNj z+C^_iQdf8}At-_F3`kT8l!TBVR02tgt0Qqh)>I@e5LCfRZwpY-02I+FAQ7Nor7yYv zaza@_)dYN))9-pR6(_Mgo|q`yagIe0h!EpB#|E2HBGOm3JF0AVCgDA6gOov6b8}}F z-Q9UKzK>Vm6HE0(%M~q#<#amfyzyK=tT8TdVXZ(4fgLP{NjctMaT7#)?2j!KM) z&Il=DVbCl~(ONBOjM5+Z1f3uL6#M%z7SZeX7#$u_3qkm^KTN07p>7(&eOt&hXMcZ> z{HMN;;cyVy5#Rr4q`!9cs zDc#%=aO7FaqHdVZtEJwoTJKEcK8;>2@1slhsDbClg8hZ%Jx)VX^Ws6n>$8A?=&7KF zVDLh)wc6*WzVE|4@SevBGG+h9HB2=lpU(-6L-bZbB!sdiR1T1+B*Xd==OlVKq%jUR z8dGFB>-}}|yn~>OEBz_hfRxd2?e`RGI@%pJXc7fMLvLs)8$-D`j{LT;2PsgAB1u|q zTp^fEDw>v_N3?MqDWU@+PX$_m)`BF7lU8d!C1!3M$Hc;>Zh z{q}Je5CMu@adxW{7a~)~XOa+96l|pgc`oP$L9cM6O3>|OlufJ@HD1(6A?Re9EY-}W z1|ei?KhzXOPL^s`S5`TH?i{^dLGaKK6`SFR$!v|^|!M-F>^m+xICm*K%*n9ck z{U`qudc8h>{;&QO{ttie|HK0iKf=-BA^+pQ^p|=58?UmnyF(&1uf6&TN-93}Q$NXP zfAiP*EC0cN$VWc$34Y<$wZ(t@pZ=$ud-#z%#NeLpT0snM2^j?>;IPh+r5fQK{Z!*!MrABI735jk4oXx> z8q<(v(FmO`46je&ww7F(TYmetW$rvjR$yC9l_!u0M=Aq_ufREUXNZ>ytrBYE=+zc{ zgY0;OF_C0C&5?=1&Bjm~#-llEI>R&->w^K-d6ZBTd6(MEBJ`t;3kXDvMM#Blu?(_S z9-Vljtf|QljLs78OuRkmU*1#z3l+0c1cc5jnhUXjNN*N8oLAAxCsV zR00){YDp)JMtm>Vcwk-{v=lV1W<0H!*N#Ca<>@CL;v-Kz!AieFWtWOR7Qjkn(7SAXf3c;V|`XLEgn;5>`T zl+pe^-~Y)U;MacnA93T&H@WfFb*lNC*IsymfAN{m@TJdxo(`C|FbH;t0Ca3INyK&yb%0jb-_wf1y!*dLqa(jsIa2uldD-nD2a zb6bkM4SP5`g=AJmy|&v;xc^eYbY8{Cwv^6CWg3($>aaBQgZGFaD73%-nb;7c;vpbJoV5e{>1wp=F-+CgHF!W zSl-wh;k2MAI%G6lc;Dk3UcSh`eD)h0RVf-6Pp4R8u`M+b#PZACzT>n1^w-%se}2h6 z-_$jxZs>Nq{Mb+aB+q~2IllI#-^E$8tXR94&!LSQrD?`sWtGqT+OKl<`~~E(J6H&8 zWBB6dKTn<)T)ccAzx3bye@K#q(cuwa`^r~PZB6&x?c1bDL|2t`Ym9?L!lP$X&I~)4X2z96jguu(nPm{qSdUWC zmI%h`CB`&s3#upElCo2Y=sc?2Lm2|?~{DeZE+N3v4?f8A&pyi&?|Uy==~i7-oWJif z|G|Is*ZI5u_21?zU-}Y9qcMN(=l%lEeDy1g$741&H~HP){%y3@Bxy=k6qNHh`#ZZ- zW%=!y2#<})G}8zz5y6w?0&5HcNs%aO8_|rZ)_5Dywa&%mtKZQiO0qRf@Bt1c23#P~ z3Tr+6BBh&q4reuOi3N098aV`y7J;cXTzmCJ?tlC-RN6;oDGrYe;2MLH8X+`(Hl=lf zA<`6Y6?Iu*W+ldX4yF^5G|m-`3|)6vH7dKsmGAxG8YyfK6jL zyVXEgAPDFrdZoMsp#@Saq;4rGrC=}wQ6yLsefmiP-fJX|MYSMJ9ZCg6qN1@bB~nMv zo)!uvq8%bti#cntYEf;9@5R*)83JWv*cp4Qbrd>~B#KU|DKbGfOUN@tq6MjrD|6)p zD?Q72Zkd-2rSTv=vnuXBSsHioey;f7gXekg{IMP0eb zia#B(+RF&e(zHCZog#08kFntAU-h^v4wo)p;HeM3pZQ`zH_PdFJIlGbx-z8v=^tlx>l_D%hiu=v!N%GOfA#18Di7U% ziNE&O{~A@@@bmxS&-3J?kMj5<4{+`F9{qlg+c$2|>-E@NTj6LjqO2l4>R`~ntG3Ly zRHd|zTXmAEJL+i@qG73|jP#amk@%w#3pTny17iKELlB8maD6!C9s5h<}KigOGHg1pc;CvhgB=mhW9c7=Q$WP zG$t_YsTQ&?kn-4x5hL|V1eEs_3i`d2Ttg?78)97mMbW^4?OWk;y#*%9I@cn1_51mB`QuS)0QkYreeJRI&X{)**o0fd*1&TAN{^R!&koWyS(_!SJ-;& zL!`y4Jb3>F9(&?Zs;cJto3HQ>|Jz@rY%D#ccyhHMI8U$F<lXJ<(kEGN>x`}`q-aBr3LSO?+19}qubEMr4*3<|W zNQ(@iG}Uy@WHP~8gUmCGHO%IRn5JZ2I_esR9mmD>4zFFCFrMtTWxN!r3TzEC9=mUq zt%2tAFHEUQ*vvb0GDj0U#ygrskobrZQmrMO1dmQ3cLER^vr8De~XDHQ>4|;@7hmr{U@gk~hG=^$XqNSsg zr?_T;tSdUf;OmkLmoD)qKlRgm<=I#M|Ly&Euw_Sn=ZSqXkH7vt@5&ogpGd*DhSlDf$*_%6 z_GvH}jhSrM`R1?u8n66`&AZp`$!1VL<44r6P#=$s5CBUWDyRIpvVZcQMkoB7Mi=AjWAynrlqy z<+d~(@ehCDWArZH!c7zv*H8~aDwPP=mCU1vssaD6i)*CP-i%fn?MkYiAaD)6yqqix zMc{%XB~dNHbM3Sjr3q>^MrnpC1%+_Xra&2k=Qy}wl}audB?E*G7-cbo;SQ1l*A=*E zrY9l>!-R%c<;>Xy0xtsTu-6;0zO&2s-`(TP@fuTgpKg*;ZB&?RTO5@VRsed~%Wz$J zIP(z(8c~2NghiTajdENHtto`IDVVm;RXP@Qc!0G+f*aal-9+G0tqPL3pb}Yfm;{sr zg(g+n5|j*}EdDA^3z9;UCJ@XV% zrHXJpQbKB;z^#P5dGTG2OwDki)uffj%uIxIeV44r+1ktb?t6E5?WLEfwPvU|F3+7@ zB=kLEU7<)*rq4dhFiyF7cbznyVt#ItkALMG{P0iy0CLUj`4=$JG@kEL@f{{7+nhRa zoX>sc)4cY>@8e#%$n(!VP3kzTt!!ZW9fC)wss7lAp-Xm-!Qgu?ai$q7jY2X?a(qRMQwwdb-?YRZA5hX`FEw~tGEsLqf3(fHjUMl8#pGq{Fmep-P*C?EQ5JXa zxdPuaNDN7mQy7CTa-34c&5Hs?qcM&jkQNHzdiY*syCS|us2r6Q42E6$-7Sn!)T=&b zPca^6eDUdH9G{-XA*9F!^-7gWr9!7a;MVFru5NG88xBw?G7TA&kQf(VYDT>TrOTn5 z5O~66X>!WSkftedmXYR~B+p5tBFQy*Q6RNtib==88qNrWV{kn?U#JE?Mmr4p3DOt} zt?{w--nh_g4iuRxsQQw2%^}V;D|<0+RHe~uP^}AmFQyU*i;fl!g@#dFu$5?bhB?(J zWV16ONHmqILp^kvnTp5?MUg^(Ftnh@AfOS{FuK4|kjG>4c#LNhBJiwvq%P39AkGWi z$pxNz;xVRrwYksA?MGS$Z zm$l6;(w%ia`ScN%8Yg*tw#nWg<7PIAS8w8nRnjCT4g&72?GUFa#};RK;cMSykU(Q% z0;LsMZr85sSOVL`M4PYw+%K^H^fO%k;rBQ)8M2@DXdF9@^nwrVj7M(_A<5DlrEDD$ zdV-4YS`3V^;l1KXE-X%h>(U>MIn`>jcXb=7C56iHT%Q=1wO)$vB-HCu?Dk?@B)UB9 zB2Ut&I8>a1wh!y#0LH8dTxlo9^%<0`A+$YJ$rWDclLL8PkmWhqI3)`Wd6JW737JwP zDx_>6I0T_j6iF)DSb+cyD$hyNjB#TBL0Lqq=LQ&Kq2P7T z#q~WFk1lcU!e_X1_cB*6Uqa@hthoe^fN^Tr=@+Q7GuWv3C<5?e-+g zS6|`vKmP-KSw?oOGm;+!eB;wE@a}snnC>3E7&dlBG}C}BHKH1MOtz}j>ovORnCaOG za#axLxdojVjfrDSmZM!4Z9I$-WX6yv!=5)uHa*YAPM^eGLlp&Ut8en`$DZQEk!dsz zSvKI*u?04goJ+g+xVN^&)buRH$|h$XKf$TSB-2lyAwPSB{$uluHm;KQy8P(P_rR|* z{p4}FY2Z@LcKz= zJH`*{q)CPlf=VD+Y6VE8Nd__doiRxQg)&IjK^YikHe$?20oS@?5-l)VpbEp>sbhTn z>wh2mImxYeF4gP$_tzjB)2xR$j*I8| zHnnjCNvaw3Mz}$M>)WU)T%X7d2}4DzC`i(Tc$}b=u>}6YMP?y|792VLan3#ctK>>> z=l%DvHM)aqAV-51RH6!na8S~)H&BcVXf_+nOieL4eT32OJv`4xmRt;QaHNapTMv?r z%^_(%U~XxS>h1tnWvuPQj1o<HhJOWPqDGK&G%os$j;Ut zUmE8;_riIk7jojs7x6y+EU$n2PuRTrI@!V;XqR(Gr+Dk_E8M+(jj4rWOwPmu|&e zx;~~q5>#sejl~uG`j1#&UZ*KT@^naUG+yB1Vwi17=5xtPN3%DAy?%yt9KQ9fA8_UB zDxdq}mzb#9Nwz}{+IpKvVXP&a=U`9>M^LE-w9*t$OPr{V&?!6nBkJ`C&l9Y6hM2x) zm>SYJx9mb=5T;~70uqT*nog>4!YZdmU8a|g@Ycn*xpnP^Z9QYC*6RH7FaIh=Ya$<> zc=2a!w=hn~(wtl=8nr5oM%A|Tr3JP;{=(-u|LhB7c|kHxX|$RwJ^n1cZkHeoi7GYA z{B))LcZuRXlyRc;AD8k0boqVuQQi0X^5;KAr_-U?sDDVa_>mjK8n@U&(;CQ&GKyHl zEkc09GJoVzUoO$YV2;m|_$>jOx7+$-G?r!5alE`xzBnfd+pakTFM&$+ZaLBN`iYLct zQ8E&Yt(mmS8ISr@{3-GxqZ$SH(qTA`8D=T%YLh7P$efg^h2!jW@6g@bwE(%&MoS7x zc!4gJM{H-P*VVj#C&P^@ymh%lmRTN)ZKo&jP zGCwy76&KwZB3(O&I+%0FQo2V&0GE}rLG`5f0JO_M{;$o#?rXU?9*7|Wde=!jvgu}YdN%ElC-Z+R7g zW5H;nq`^j6_f7{l^b#(r;v(gjK36NWBf;IhyZRAk20x8EWv zVw_2j^G6q$m|yO-W2&obNGF`6I<7>~xJS;pf}T)+)|T;nl0 zGsUHM-X)46M%$xO7s_LLZVoN1%FK;hH&|X>rYJ0%R65q-D+nW+laowMO*6l=h!+OD zfB7;=lHmCsj&z7B5$7L&oMx+S2~wr{%SUbuDdnLRm(m5&F$96Yl?8LH$c81y<@o6( z^1`4B+crexNXLfrVVa|p96!{w!U$EQ><$t(dZ`^m3EO%M0%%mKeB$$8;`3kp85S3p zh$k#3 zw~Z1WaR$TKvnir6fGR!OyIfvq^FWgAr+=aO*L}C?Ou~QfoBuoanwHV5y9#R7RE! z2wa;M_s8*}je-!MkreMV6K9gx= zFQzCALKH};3BL0NS;>A}%5vtlE-lqcj=XYVR1kdUO$x`MDkY&(OvRv;4@pTo9%h97 zs|W#OZF%+nQ|IC5zWkFnhL9GbVU$5QRtB?Cl`Kp~9ABKG-EK28KhNy+Ec>_bknD9B zTfIihDD-@CmD3+5h)k2_1rt@Dz0sI)l2h}1jHgj(W*Rkq;g^4%7ry!ncwWV}h>bmw zl(LvC*Yl9VZV%xFgvU=~8V$xb-ovclfiyw*K1fMtcaMAPLxiglLL-%;S)XC%_<8*H zER(Y**uQ<9WZc8aQe4lY)~cYAm>_T%V`r|)kXRmum|8*P({p!2KKUk&|@w7F{kvZHiew^afOUTf} zd;ApHdpAh(0ug$UWSDV^2|eUi2iY4z`S`~A0soRibxm<_Y+76wkPAV6APZ_he(W6H zW5+1|^lxCCV1y{;b4tANB?jp^M3o7SKmB!{{QS@1 z_+iO~7KcXV!{Lxxt!DfEhj*vZ!bMKaQ;lk*(!h;Nh^(xIv?3kn^af+JbZJg6a{93^ zGJpIGI6iJvp|K?B+`del7evA#s8kS^UtVXQ~?Y7IrM4Ra_$IGYi+$vY@+~!`` z!8lc1Kji(D4Kh^<%2&h2gPT-&EP z)8?~JEfS>}LTN$?ld|As%VT$>2y(&L7fj99IpU_3r$hvT)Uef#`{E$p))ENIu+J8L+;$V&V^M4|AXe}ZCZ4pS63pLvGp*~g(! z6r0;PQABZX9rwf{#k~!j$4}Z0TdhK|vyY5Iinp)go&-tUj z#yK*F`{GmRoepL&!W0GW*FK5+_-W$*_Fuv3_J=mZN7fjY&>{)^IsD)RMu+$kz`>Xy zNjf4|l0v0;G61i_)Iyz)ec{V&yz>f14RJlFIf7c`A(bJVm}c_mIs9OU+1Ul6qhBLz zpRxV?!<56GEcbI&8#x|n|D|kUCn`-Q&pprb{w^jR(ONo>JAItH8~ZFg_B`_^AIJAY zl-3k!jxttnw>EPW=?1J`eVhH=Ez)?*_Wqdfzk8dt+dk)yH}Jxm)oXPfyll*|W`HSt zq|%5qM2%deYrvCKLYMAdpXsL0+1VN9TP<3X3%IUBmd9LK>!6VqYHteiIHBP>G+mbf zm-$+qc$7e)INGkzthkH^BUY|1lk8}+?H={n7DZS=`VJ;7s5>rh#ifO0vT$*9gi{M} zdVK~7)LV55m6K+gdplc}7ZNA-kODmXzk*95nAO)a*EudpZl@m z?v9}n`fLwU8nboQw)goT{>>j#3tg7ZoWt=deBzUzU~YbvKmYT;Kzk9D?MJJGsH`C0 z>k=GWK=+44zw~AFP6r%`w>WLN_Q&RNrrOA33#h#=vRT7OiB2sJ&i}&4ab_nGGi{uv zr6!op0F$Kz|I=T(&UB8=^`b$MGqQVU)%U8AZSmL)ilZ8q*3IofWcj;^b&_g(k~>%4V)gcQ(!oBi$O$SD((xJe_Nhb> zDlZuA@8C#i%r4TbxP;wJ)>islxw*$%*LQjA`YzXQ?b6xqv$j28buVUnbI8`(nC^a# zC;~#!!qF~{29xJBYLir=1~N;i1uh$V+gAD8Sf%(PODUA$*wh3Ql?cak85WwM$}qm+ z$b1drA*;9d=?!vBkrUObIDTLu=|-W2!_A!`opC{$=j6gC!O+$KK91*5XvO9IluO$q zn{OM##6*?<`EULPU;mjelV@Evwz_C73H&OK3`pXHB#te#UkH5HCD*VsOv#jHX?_MH zJ+^jt@g2={t4*cRLIKTIiwhSXr`2rWU%tcSR{sIt6oWXnK=6g~dy@Jzf zp!fTz{VuW+VMb$gnqiDadLC+PA6c)Gzxke3B77hcRGv6X>+7HU@f*XD4zK>;2mHYw z{WbUY6mMR-Mjnruo1G$;l75`xhE2jsooc0ml%CZT$`x7*oJxym_9%X1k~m2j?R8Ow zrgicHwPVlHUOJB(cy`!?Ee_(!?)2H-%9swS)PssuH;e~VqBc%WM3Tk|-vzH$LrT}ye$ruM zSn#9GgnO~z-L-vU*W>x8=E(+Q;=-}WUJPBw;8&pP6hxjNbPaKDn~j^-xpZZP<&7Rj zyXCtyq-kpPddo&sp|w>vNAcY0MV`BGn$_Jt3d!W`9Ba!fv}+NydJBWVa|5QPr)b>S zMqXR7-NJ)P!*ft+M)AGZDQ>Tz*0#w0jo>Fa zu|DML>Q$&tRWaCp`fxO&b?h92?KQ^3K9%|evvZ3)@rkeS>f3KIrB+!TN=D-W=SE$e zsEG`!XsxNt9;d(8!Pf>cb&@;nFY!m;{|nM0Cl`XK>T~AtBiy-s2U#fEfuLOt=%K+C zB#gLn_Xh6LDO}ec6xnD%=ouW>L#cv^dXs8YLFFm6rb{H-EXkOA!-VBdhnZ##Ur74> z5i2`GT-Rf}qiOn*mgmt>nsks-#iQbAl0tHEYe?c$8INPe3h2dLxv`5Jq|8PYaDA@q z4)7)g|M(kAL=_K3M4S)k?`QnkpS{E7H4FB19LEYe7>(;WDD9N3XG<#pI6B$j?|tqW zoJxaN-o4Fu6mxrdozC7a+gscG$}j%{Gsn+R3a1l(;p2oC&NCX1aHK;RMU007lmPS1 z&*26>xhmk3PebU_?e+-1@&ZA%!e}%iJUVNs#XtKQGOf{Rf}Cnm`Q{fGjfTkQ&*N7r z6!VJo=q!m*1k$DQ%`c#}W;h<fuJx}Ay4THT@(~qf#W#T zW|lbi^e1UA9OcgYZ}G;PZ;;YrR8$xYbNc-*-R%`j*0FvX!o6RIWBDLf@R$!p5MvB^ zUN9I8a2yMkGhSd(sX>76hxB?q_E#=a(OqH_(XNLaIerG=h9$S%`bQ`Ol}3}OTBF-@ zdE>n`_6O@^S%TvV9=ou}&Q^~!QJ^&Ks^qbARgNtkhn2lPz0nx$R%y?l!5@#9s8(3%4%ixw+3Af~8E1H{Hd}ighRU!$$k-fd zq$4oWMY$fihRd6MHWG(S3wCyP06|e0Hg|_41vDxZcE%YO*E{qwkDE8Q>2`BOA!tRC zI2ZiIYh6alFV*a=D1|Ot-EFRSMkK-j&LJUc{%D1;)h3x7QtNj( zJ>6z`zsGKxaQea%xPi;=&NdE)-1X^=Qnm`oUT2KnPw+jLy;z||j#fQ9H^2`flosUq zh)$w-dv%|*P~duu_6MwQrR;QlZrt3aUX%2VWIu5ZpQpjXB8<_cET@C#`>3KI2tphw zS?i|!;kRGqGtZpGr$DKKUbk;2*h$8>Uw#YU3;4xf`FqqS=P+7Rq#1XvU8mpc(WuvX z^VJ_Bft{TlhTSe(YwO&(eVcx_OM7C1rKKg};fR}8t}yEL5!$f1yvoM<8lC+;)>c-S zpPS>g?|+|aQ~{+Kbh~UUukuU3{%id4AO0bCuHRs5bA!FDZQ{Xz@Bj5*^WATKi(mT> z{wKWtqaSkd_1C$3;|9;Z_#!7yo+9vn8u=UnC@+nsa*Yj~5L8I0ttk&(oXmf+vlTTp$I-Q+e#`_(rjTX~0ZJLv9 z_9u^X<;pE4rmiw`at32O9&FMor4H4z4>k(eX|Lnh7o273A%;h(f;=}2M`PxXoaV;u z8=N{a#ni%avO<+UfKX&H(s7WEb#m$tN60|Xt{c1}qB|}~HFWk<#<3+x83dVfSlQ4R z>EJuiaxy5OP<@0M5a*hmI3+*y2Q(;EkZ8De;|@|v&YgP#S*g+3UFXS#X~wk)s>e=} zWFt--UBm;9pE$xRZ(JrD_o)Uh%X>qPOixgkK7&N#`E@3z=czYabbATgYj-e3k8x30 zU|pV~(gY(U<18ii1W8wMdpALe(9Vbiwhe!90F}}`TIR5X7 zC{FM^>l8IgQvT|tA2L5X$>+cJjYIHWRH;xDIp6x@KW27z&f3Y9?^G#8tybe_fBu`i z^~USG_1YU&{X;*Y$9HkFAYO0zUu&olb{NxATw(<&Up1fXtPQ9AQ(MLla2D-ngLH zDLA*-fIR2cJ8w{FH1R7H6d}U%N)ETe^Fk&jXVF?S9`smS-JFe$O>pw~6g_7LKd6)E8e_7eE4qCUy+}DE5vW&EZHArDmz(R;p*-tV~G|hI6 z=g*&`S&z_8NS4GnzK`R&6j?$ky-1z|p2s*#sXHl)^Hc1NGcMoT;^x(R2%uRDaHWkT zN_%9fW>_fpRA$@U4>S`F?)?ypQ}V-C_lNY}exKAhJo(sJoHQXD45%$EK@ee7&cf6L zLK)5;KS2}){N;Clz%b5u?Bo>9DCG8ff>KazOtG}I#EF?YD;>rDZkMd+S>Ar3Sg83d zO?d1MV^XEq>cyl$tXza^q1oo(*_K7-!F?-LaNx^n+r9}SDcIWU6G+KK%zxa#1^VVDJ?{{c48@&GNtEF!Ucz%E?6r;hAG)X_C-~4EF zZ7FwdRXxmMks<|jW5e5bx}2Y@(o$WPZ{FnSh37EFlz=WpAO-c-GzgC@&)M1D;M%QQ zv`$X3R847B+cXb4##$SndmKRns`y*{q%lqa5p zE(~E55L6;IH`jUWvB$`Bh0Zea%(4MJBP@Za$Z&&73Cc56Y7->JWwhHP3SAysY%kTuO_bppbmvC%*hKNVrFB}Xd%ZKi|WJYlD-S=3&bBBdyoij)0X#_5Y0%0J} zQ-=Fp#+hbeZh^_kNw&8)n4O+tZEH+-7-NtOM?D;q4r-`&bc{MToh+M(&v1TrU84m-n?M(8nJk8mBIu@dBk zAO>6WZ+-m0IOP zQR9&tW1J-Ph9ldNFa}2)7%^G^S)9Z5%>id-Lps;4P@O$aquC-a3bZK*8%_M6Mw%7Y zTQ5(Uo0~%omKmh0q@F`Q-6EW>AO<}=KcPO^V5%X}qJqjYKI$^Ykmeb#ZXXcsiruq;$I-oLY;)pwIJX0+Rj)E9*H*VeQq@F7ID?kLx!iyL(+!p4e2f zOoN7*W-XO8>opo`NZnOdy-{cmv~sJ}kRs2Czt&p zDucB^;%h@zIC#=0&J}4IbLZ9_(&3Pzl``tDu)N%1ud~IcpFYR4pZX?mzWO8XTz!w} zGf#8<)-6sPUF7NKpCL_CHdb%)NB{QsiHm}UGV047N4ct>+#S2 z5B~+zHJ?*QX6UfbvALtH-n+}K>(}|6fBm~S6E3f9j4{HhrYy9ooLQJ-bv#4~c=5Ss zaUbDt^XSPpf+WjPT5}L%%z-q0nH7vOxUxPbj1_M6%LsEFtmNJP5a8oiXv6OA7D7U$+8`Agm1Pz}UT6xfSm}>14DD8%nVAVzR#q@$eF$_EWf(LiY0Qy6qd29rx6fofAdLJHB4G|wM9_G`M#sTu zM3QAlWvBo{*JZNNW@BrY&fX5jD583eUawETKOjkB97i%9j~R{=;&_*}odK7-Df-9+ z3xP{-&tcf_G57QrkbZ^7FFeK7cP=tqxxzxT%4{v7HapGi{50{P$7^q2!|lZ6$&e)1 zM6QR|aJaVF!D-G?6d6CdxXd%pCQQ$K6zp6G3S~gJ)<*)1e+OISm@?-S0%B#zDe`EBB#3Z@VlWONA2Lc37Uu%+XGu$N*L@P9 zc_bvnU`Ub#*L4X4Tbvmn9t{zW%Md{nMu4PNud}?Y*xTM^yyu%=ShYL?$VDj-#kr$d9?_J{LtV^83>TYsqXK-+gfnZ`{mf3|RvNUIR zdxL&=565-TdCpdEM1K^ci-H6Pq=PIwQT<+zUbjP@=ZAuF*1k-ZE~f%h6bzCcz3v`L zX&hsydL9mfOer!2xw7Beb!|GD6$OR1e%gD3ge+C`Z{Fppk6ZbijlF%IIDMM!EI=zo zmSt2b5piD7Ni@4%#h{;~3&V0hW@4s=%nS0y5?yD4acpVHzx3<>h?oEP_qlm*gKKy9 zm|gGkvCn>q=fC#%Ise69V!zwtop&zr-leyh3UW4gH<+59VqgNoFe38(2Y7uyVPgnj zFpAmQ-L*s?MWbC?e1d0y&5-IvBsvmD{r`a@t<$gA}# zt;reIH`l2(=WxQBEuNJkD+=P#7%zydTTzyvDTtF4Pry<$Ac#{2{epPC&-T7mJJb(A zpd;VI5rSqlB-fhFPS1L9lpEu)-Rwv-QvL$5y|iBqKO5gVU+0AW4i z{mWOFYqdF7uhGh5rY1sqz8#9Lc869z=ld_?*Cv=%h9{5BQwe;us8D1X)90RJ5U1R{ zv%!&tDduL{hw?dDu4o>A5*#@Ifyk=Ekm z+M91Ncj64~xhZO)$9S;AnNuxl6HBC-gCRTI68AegADDn2yfCbov@YAY##q%5tt}$- zVDtEaZ+$!*k4`@&iARK9M4n|O%`zd&a>A%ap$b%9pfzM^LMRmZpd{A#n$`W3L3*$$ zv?U;6I59gxAO+1@g{}QAn|oHI+GumX<>@#j^qj*D``~vwxMrF)eAi)ZbC;>R_i%iV zoz4i1$5uy@A7I9?#pnU(vb(>}{{AkW=a(FJ_0aJmN`G=F+ug!GKPd!xQJUCeHLEll zp~~m0t@p))kxgqDCIzw7_@0lWz;P6=BQXw044qD&ZntOK=*gI#u|Dd9&28@9T<3{1 zragzOE#Lf|RD2}r_n}}h$ErGDfX z(*G&tbBwWWNr5Y9ReV~ZM=Nls`!0cFjl>5E?)74}dNxGIaY9zuJaaf4g0%KzT3IUS z^xQOC+db~x+92-j<17YDPfZclW=S&#ME)U{OlxFjlNHQC#IV0FN;!O`w3Ug^H;}U_zg@ zt%6+NueUIoisv%hD4`y{vy=l zy3X|MEPAWMiL*yIUKcbjoFF+mO?RnA(YcEm4te#B%NRFe;=%&MR1pvQ_(eq5DB2S? zrP|*gFrtPNNs=@#>qaZl6u1tpdPEplPmm+WP7rt=>sK!lO`oK>WO+ItDW7A2iVMe^ zK2y~SjmRT#1)dOij>HvK1~T#l6~BTmESt^xI~T;`nDKaw>-+Wvg;r@Ks?YMolZO5M zJzA|A^~MastCC~~>C^pNJK$tl($f7KJBS$iP^3W~o@S#YA?Fh9Hsd(Kl@4({!t+Cnbm(`x#G?VOE0C@r$ra1}l(thaIoqP2yY#Z&p<)Kcpn!=+ zg=*v=0-w&_9*%&=7H7D*wnb8=P@ZS8NEmI^0rT8?89t(^us<9z)0||!RcF1^qbCPt z-E$vdd|(dhI+BX(5CuWmo-O553q_$7>I1m5gC{IY!=C#-efOXK0qaedo8+J~Y3a^3 z%{m|+**^zu)Zx!*Q&>A}M_PR?VX4k4hiHBVcV&ZTpLv|E&0W6p@@wpF?(*d?eu|I1 za1P&(IQH@9aX9SP4dveDK83o{Q=Uk?N>_EM`JXj@yK?q9Es;T>?JvI98--VK#&)?g?wyn zFxpxMG)_=q5G!h)An+>;a-Tt}tQNCtmEQ9#$Cof&^(f*Yt^uhPCuZBM?e`fb83you z-=4)7asv=W}$Sl1;{4*3oqu~zD^mNQ1;`?Yd9ZXH@hdD!Su zLFU2lAcQ~}O|BH{>&x7}d5NP7(-<>>*9=(v_;W}c=9NLZ9$Oo`OrJc4UYI6JGp<~E zgIc{#V}6F_^jAoWg3)M9G*RQ3&pgBN{e7ZJg{WG^b$#-DKyPc!Y69yzp6B970Wu`R z!>?8tjtkzobcgl3%cMz6p4oRZ8V=ao+Tn-o5a)|uU}AFeC#6yb&-bX*sIC)`*X1+w_nts2BbX|PUBg?Y#l+%YBzzT6bYKSKu&;WXHa~w>P z@1Lxq9LXA^8N~@{nh=E%y7YphObL=SMY#$`O2QzZR;v?_#@3HR2+#&)G}3Vi90^%U z(cdM=3Qo2ol+uhxG13T*HUe-xl#mQYV``p*NXPW{GOE=GB_tcW9q#RqtkkII*^Mgh zgCVm#KSZm3aQh1k)gZ7syb?~#PZ8$@-C<1Vxd_+6lY-E9sfRxGz@_SYxV~?-l^pBd z6lp;tbeXP(?2S|IZtYR81WZp(vOh}b4adYuR@OfUC%>^>$Af676vBz9Hs+9Son*9y z%CJO4>DZ#)3#dgNnaS`X&Fo?u0pxki?e}l;{+l=1-P*?weU6@<=kaGx5jC3h z3l9;7q&tfJ?R{=uyu!V!SLyC;)9rNu!Sqa)KO1KkS-Wz~h5B zuLqyH*4ABhwpquQ5T^-RIM#wJ^jT_GafGm&#&N8Wn(JESLDxkHE2vhO`vXKJ?3`n= z7BM~9V4_`Petw2H*KF@~xp8Ot5L#{y=aTl1ht3l)rF>_} z(U-y;rh7))&Y3X=U1(;G%u!^D?tX`b*=fQcBuP?KQQ(JuX~X6q9BHMOjHbw}@dEn( zS`k>AG>u{P&Ni?7<=b?+BeYiN&WMfGJ-Yh|CtrAq6o)+Bp|ib=gn7N zWjr2}r<&g07%2qX>mBm6c<7BhvR#`i%^=QkTua4NLSS&wjwIIwnNp0hf__>sxwJ@o zdX}QF9SllI6Qyi-NSTKhz)yEQ)K4h~jn<&?;841sp4;wBo);uC!E+pPZHZIja6zV4 zx#9uuw{e`<`!xcUCuGSOfmIl{i_Ad_ZS9${lA49Fj+6z^OAVEZM-cfq!eu-flPT=? zbtKY}+oqj2pJLJdk(HEN%8`z1hL8)B{{W9WLw{*UxvWKb2Nf9SD3uC zYcrOwFQg>T6>(Aoy741 zj84(%fGp{t@)4*6qjP&`>C(fzw5Ij~9~{YOG(zWgePmgR?|Vem5Z80SvqEKV~xo|;d(w2Lophl;si$s^7248TA)-}t{6}X z;vy%`69#e0ZnsCTH(;jSqE(G>qY7t_gbYRr-8iKer=^ptIouQ<`o0fse?yk#bVo6v zXBTZhPEgv=AI0nlL%kB%7pD)Ewho`AE3H%|0;?RD=Y*k0ty;kk?3^Gk6j~N216h`p zun%(xYtcp$ROj)k^BDXCCrd!sqT2OA_!zf_8&08%G5L6lY`l%usRa@mf!3C|<_A83 z?~{&`5@T$LM=|wA4W)9lvMtpE7hN2C5Tgx_u+C3uUa)#|lWHSEtAfsUmtJSY+MP{? zqY=iybmVZn?bB`s6ar2@bB5E;Um(j;mai_;-`b&74WUS=I@Y#AJN9{lAyW2 z!;jq<8bMq@ZY+#EQ;HaYrJ`Nwb*D=R#$o#r4%?r3Uf2O-xd4kiXEYuWCze2z=L%sI{rx?nN)5;J zNqhTlCK*|8& z)(}n)bXt0xV|gpakd}3fR*LDlDLT6y;?bBij!Ul)D^Y3;s8ZD(tr1#NZPckWY8075 zpU>G^-R0`rHyQTFIIcsj9uWl|6gji4fWS2j`$OhVEHdu(xbxmk*00_}?ez&Um}bbR z-^a_W9b1aV^#s*=l{`t=THkx<9l4KMl*2S+!+i9Y)Ze zoZ;ywA7|y>EpFaj;pC}PRKpNm6x_ajn>0zS)KB>mR9=uIiH#(}7KCYLxyzz7qffKc zD$xZIo!wp1c+AYq93OlB<47slxP61S-@QbZ9~doa#z{hwa6d>{Jzs5LoGVfd zqfE0uOz_-3g)tOLqgC;tDDkM@J3a4faFK2WH=4oVU{q12p=H1* zH?vX7y6lSkQ+pvjr1UK!yPS8JvS7&zRYqIGcpOuySLp6_(Ro3=X**qLjnbNNoU*mi zBag>SPK3BBg(5|`9#gYTCT3dHTNN(9bA_3uBg~&T!5e?_H*~LDqY=8yPPPc5fJ&>% z-o^%Mr^k%r(w?7Tb7hM>Hr(6nFfzIvFKBd`?i*pqi~ON?@<`5ie;l*E-$6=;LKS@O zXMTZ?KYf<}>wojl`IZ0RH~Ec!^y|ET?JiTT8habd?2Q%Y&p*z1(B;|L8yArEmQqH#dg-FaPmxF;IYTaU8)bue{9S zsdJoIn&a}Nci7(T-p|X+gH%e8(!D=b#*h~3Fp52Dy8WolA#o$2gAZ_WCSN zPf-aYYa5+q2VjL z{?ZBXD{~-2TX&V*5u?g9M_SuyD|1w8*p}TaAtXo_JMUHxrNUZSA9o`JNs^=U92Y^} z?~@d^lP3U?EAs6Qciy-~W2Q;F?y-IAF0L04Hfp$0h#v;jDv~E(d=~9BkX}eH*2t)W z&SM7qea61W=609L;u6C5QI#s23OcO@JDn~Y8r*6Vtu`^*9w+Izuu`hdPh$f>DScSB zM9-c*!}{7X+q=75yLFpi{>rC0cII(zUU{D~tHvCbaTXJ=U7r8sXYox+KX+-?YdrP* zC&<%`V++&#_y6)=^I-jB2S&2&>01Qt!HKE$!vMjD3+;zfsZvghahe{InuL@L$1&Uc z9j4nh)zV7Q8^*wcnw{aZwid07jK&_QsTvsx-~PB5yg^d1gu~uwFnxoSMH;&m|AEKt3 zFwsKiis`v|W@n~ZINo9LnWveUnPvUb+YC0>*}T0%bE-{LtFpH_g!VimIp(E5{XV_D zF0EQXE6W%sDUR>rH5zQJ_NmQQ5xuOOA!(FwP=#S{bpyu{cpexn$r39SD}O3~jQcZD zgpl05yUeGbJWjn<lZ@>OJpZNTj$j1X-dE;HqUHBMvPgCTIG>IAXdMvN3 zaCC8+Yd7xl!qeyZfBx?8arERVs-Z_J1IDT1!V^zX*&Gr1g3HSrG~5yUMUAQHX&SW( zfAR85?CoqHE_}Nw9>yI>BOd|`{-o=JN+~zvf>5oRlX@-;~lte44m5973 z2%~^zHMEP^anRDSetFv1X>@6soEM65k}?>LNYjiYvp`K{z>8W)ziEf2Wjow%URfdx zN*;LG2EI=>QHSh4gnOuPe((WWtFmUW7^=e9P14)gA#}h@G}u|$qFSp_env-p+?VR0yPBM&Xv}%B0r{~erF_|iG$2AI>G8YU8 zD&Aqro+c@-bg5P&3N^y<9X!v)4QvPVgEjykQVEe#^76|s^WE=!_fT(jbA648nFT)f zv8Ny(^WB%e&)obXCMyU%mv`T~$jrhLX)H=k`rDw|C2lyZkV?Q9n9LJSg69 z@beG;-cGEY2avW0Fb#PaS#o9T9i?sA>o^kM_b~`6m8vavODMX=LcX&+Cr&bke-*uD!~|Q+G$GU@Tp@< zoIHL6*qmQuuCw?@96^C&_bb z8SNMzJO4Oe`s&a8zWVT)BJ^3~X%ga_8o?5|Abi2VM`!;p925zVb4j=aFT(?I{~9;#F&Y_{#SQ z{D3^qP+GIOy@l&IWLd_$moA}{VlWzW_x3G>F)SQA#f2p1tv6mH#pf%Z{|rBP`6Y&< zA>aD5e^-JmBsZ_U$DLc(5yG&wu|>bz;Rhx3`hcOim(NQX z4Pl6qhFY_UNODFyT?V+gQZm@sL5=GW`V4ma2;q{BGd$lg)_r7D!ACOJ2$*Uwka+=4 zH>TF8u%C<>4l^3<28&Ba==U~gO-uUwIq^V|X9dIlh2m*>cKU@U1coh#V zqAbe}y%@AH6y-^l8_2Vq2R@R*kvOGch%UJUmb~P!v3if+|ATFM{XThK@bCWY&*=7g z7+rQCw6;?9#_~F{EJKwOal1GVBtdPv@c?mp5FxDU$H8JYhn=v)Tm!>T(~Ua#%m*XL zg8~pAOuM8MRz0K05kj)9N|vOtE!g6)J#1@>2eigZFrxho&kG3Zv*^NLRDpCHz@iln zI)sN%6#?%%4`fn5 z&QYn17RDePk1v1aYs|F*-n#f6&p!7IFa6bDaBpJ^;W~D3Weg@M5w*fp4vbdj0t-<-Tr+DKn>*}M50>^R5^PItOK%QlG z=w%GD+#FH0Mxz?By|a6`h+WrxDB3-|=nspZZM1oY^-)E(u{PkOLMYD)$ve9bLz$OG?wOATi@gDH}BBd?~{yU zluv&Z=1U%pBb$0%iRJqJH@>2`aBRgb9Jpi&)CXicv({OMFe z4j!Zdbdj;&8SoE&@n_lVj0io6Uv2Q&&z@!F&P^t!7np9>xN-dkC(fQ@Vse75%?-M} zAq$H~m~7YC*x2M#pZpZ7H!iZev2CM*<8kWP5--2}3TMuqB^!?!CMlusf^&!yMzQ){+ZTv$LCiqC)HbG-EJZ*le3J@P_v z?un1_sNooa zr4Ao(Q?%ANWmEwUS$PLga>}8h#w7?EMD1Bz3S_QuT zywE2d_mPg|#OV`+M)9%ASD2oh;Q#b{|Ay4_IpjPa6!6l{c?zu&%76qr&(eo!u_8-VBq?8Aihqj%%OsM{bOR$?-v& z@YauB;+;=_nqTU_gH`j3+1=ac=f3_m+#q0gbDhpOAqoSYdj3;< z_A?*n%Eh<2eCaYuf4Hmks73#iu19I}ey~VC_zWo}VHlQPA;x-2IFc;Oc~DyxEPYmK z{eaA=Jmj}1r7%+B1XZLP(z*2(z zcLnOMVQpHXiJUu97&=K-OVnQYJ}^#D6JUm_o+7{&OLpW zW5=dAHrGH8MyPRy7kGHSOFkMA)ayL|+!=0MSz~>>i*!pROlkkVYnQHZ?CcU}E}UWI z)?MQ97=<0^fnhWp)7kCOm~2w7PLP#@-;a(MhlH4e)?3aSZ(n30e2nfeVQF!WzxnpJ zaH0msP8_q!8lI%z>+tfMuX63yGLJv?0#avOzj>SUXHL-X_1WIsMC0hc|igA1HEeS*cKN7>!kVK5y1)C>P7 zZK6lDZa;V_eZW|h%r6}!kU5E#j0QtHrOy&vFCg$7JH)Ivtj1PJaoyV5!Vg29eDX;= zFXa8}YfR2Gsrw1-r%#i_DU~Qd8^w=aeS^sL`0CGo3D5I*_07x7&rEXb=1ul`Bl0Yz z*X^=!;u!g@8bPZ?U)Ctp-XV7SU=0;TL6)S9dOa$Y5UCB3CuyHtqPyK;<@y@kVM1%V zh4dWy-2t^i^Zchz)2dhSRe^Q{G&p1y3P*xcEFGQU*Z;$xuQWj7KAitRTxWd_Q2&A5fHnebbY(^!puD{!{2mJs`?oVwM7?Cu-z{ zA(V#iy!0}&GqY@N?;(Nx-F+q}XFw?$)f#Bc-CNgKJ$01lo;uH4Z@tOfkyF&0E!4d& za;2G@p5%=;-lU&No_^wSbP@B?-@L)6KK&`?rULf1M`)eVXitH(-g~YFNl559boM$l z8ZC-Eq19}VB{|J{g?o2yv$MU05*}yIo@Kl9HjkY-&Fbkc!Y{4^hb{z@}sve zJs?o_(HrD{>~-+}IgW!YmB<~VX}2fv%otL`sS~H|35{Yr7~#5-d-v{f`ux*Ov>RmU znEl;t_V;#~nOop%U;hTuap?}fMS);)vQE3*MAeJZqS@eiF47S^^Yr61n+@K4=Y4AR z3YExbuR9=)$Ncd7FR`_Lnx^zw-YfXa*KSY^6pfZXj1~ZClF;pR=-%zqv>r52!U7OfQAFYkS;$e-$@s^URB9@j@F3{J^(*S3;sNXvaa+8k{+GmQ$a4 zp7v~ufA_n8L7HUbc}lml$9r$R%O}3{B0(6EX9ZFS!YHItt&pV|yF0rGX_%d#X1X;; zy;6U$OhcsE!&}95UH;4e^1t9e`=|f(KF3!GyiyLaC~^#fdbLWDjHyJ`Qgs3x*CVPm z4srRO=Mx6LrMi|yYfL%-ieN{{))1;Q|7Wp$lewL%=n zC~f$)U;YN2-F2ccVqh zB3dnk>mz+1Q)-9xc6yF{6-1hr0$hq@ zJYrPB8x99n!m4>BaeTO_2ED!&`2vQ6`yGNbO>yLX+T{lq%m;7T7(*P74+%mCmnwgq zm%zY0&qBI@7XWdV5-9?|W}OT`P% zbuidsHp?v1_J9L_I3p2)Bu(h`d-va$bkW+dvAKoO2FH;UMNSeQ3=|K#S{kDZgyXWY zv1uC&QrhQIKJIrfUu9-`ifpX;%kREQmMbcOz?hs%mv3{(Bm?p^Vc6?XsGL0YSX>FC3-p@$7F7f=lb}b&-&eU9M^J#40e#}NJA8bm=+XyPP5f0J9Q7g zj~`=aEFO~If7DB~i_usTk+j&HJTFMQUAx$f!4VcJ?nsF!Js8S%P6NDz@z} z?7)zRr{qdmk!D;Q@1?MyJ!8ZJf(G|L>)`XHu$?Pqtk|~QeD`r(;{MG5_h%TQR2VV( z06%5F_NDjUFZuN5!%tX$_&w!WffrT~^%{Ho8J%9tSAJ$1*A$3C^YP~v+1l!I_1chR zW5oJi&eUX$YRhFbP`rL=7u7h)a4@1VQU8#V*`sR=Z628$KWf%sJ0jXj(C8HDxaAAM@&%+s zI^`s_lzr4%p^X8Nmnst$rs}vJvXp>7?B{Dcw0hKapZfGbuO3Rq--oY46-XfuXD^Rf zsSkaQ)mXZp<`_Qwzx|}=^wZWC4{Z=0J{<1hNzV@lYikNRpV9)qVChb_ps&Ywv6f(se;t z<&U5eFn?m2_2qR`p^0h{K^T&ZGlUd42t3z87mB1P$kL3c8q%I>vAeT}bSZu0KVoBu z62J2(i?4?l0Qa#y^1e8M?X^o}8Hx|3Ny^h#;v7z7wJ{|o-*z#iwmoUY!C>nnW&u3- z(tezVq5XRfU>u@6MSuKfnL}@JZOj9I_U~U$JnH&T(|cv9kfj&*qw^1u$;9vlbCZx2^BHhRksJjn;D(uZP%c;J~>a*S156b`}&{8&*b z1pECVS&}j?3YzUnBm#B7)zF6NsRoOS4R$VXU^U;Y`k^Wmsz}-2@>sjEOlzt^Pz{le zLr|>}*6a9zhcR&Kv6CD2B{BZ(gt z68})~Erj6u_3K={a^=IT=Kk~h@M;ndEY5@BSNY!`wYVQ#(1$0Tc;HXW{gm!+XYt*y zO|-VqhY#gj4}FjO|KEqc|A$t{zt4^R6h9*@F6o1hLhA=@Js-Hq^0YcQSi}Q6raXrp zf_yx9Ggh;f4}a!IeSw329UyFtp;?V+G-_4^O{r3k%wuu3Wx44Gw<;xT8y)t$F;Y7B z<%UWOSrmCp&NT6S7wOtAo$Gl>*EviHbzud(^E@ZdQi8~*--+4T*eegk`!{JYs6rj4 zh(b!{7w0*B?#%sfout`^UX3hMp#Oik{&v51vH_ z!@`F?`$NUv!73N`H=H=gWIlX7n6g@g@WYe=H_z@sxBYk5|5vV`uD$Y;uEUV^ zz$yDs*je^=w%Oa+vO^`$p*1y2Bo%j8w`fmJ zlEou#+`L7m6qD@g6~tPKp0HxE$AI za&qeLBF5icKlVD1FH)+&^MVhdXp`|6Ed-ShoUs3I{3cy;8C%K%00000NkvXXu0mjf DnZfGr diff --git a/docs/3.5.x/docs/images/apps/todaylaunch.png b/docs/3.5.x/docs/images/apps/todaylaunch.png deleted file mode 100644 index f75fba3bda92d1387dc24b7cb6d5eaa648fff69e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33233 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 KMNUMnLSTZ9^9~09 diff --git a/docs/3.5.x/docs/images/apps/upcload.png b/docs/3.5.x/docs/images/apps/upcload.png deleted file mode 100644 index 4199712ee7ca626e6f2b45800fce43336a6da398..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37792 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 C>_hDU diff --git a/docs/3.5.x/docs/images/apps/wavo.png b/docs/3.5.x/docs/images/apps/wavo.png deleted file mode 100644 index 3ab6bb877c1b05a6f2f20a8cd697bc21ee84a7aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54906 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

    Getting Started

    First be sure you have MongoDB and Node.js installed.

    - -

    Next install Mongoose from the command line using npm:

    - -
    $ npm install mongoose

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. -The first thing we need to do is include mongoose in our project and open a connection to the test database on our locally running instance of MongoDB.

    // getting-started.js
    -var mongoose = require('mongoose');
    -mongoose.connect('mongodb://localhost/test');

    We have a pending connection to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    var db = mongoose.connection;
    -db.on('error', console.error.bind(console, 'connection error:'));
    -db.once('open', function callback () {
    -  // yay!
    -});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = mongoose.Schema({
    -    name: String
    -})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a Model.

    var Kitten = mongoose.model('Kitten', kittySchema)

    A model is a class with which we construct documents. -In this case, each document will be a kitten with properties and behaviors as declared in our schema. -Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    -console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    // NOTE: methods must be added to the schema before compiling it with mongoose.model()
    -kittySchema.methods.speak = function () {
    -  var greeting = this.name
    -    ? "Meow name is " + this.name
    -    : "I don't have a name"
    -  console.log(greeting);
    -}
    -
    -var Kitten = mongoose.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    -fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. -Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err, fluffy) {
    -  if (err) // TODO handle the error
    -  fluffy.speak();
    -});

    Say time goes by and we want to display all the kittens we've seen. -We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    -  if (err) // TODO handle err
    -  console.log(kittens)
    -})

    We just logged all of the kittens in our db to the console. -If we want to filter our kittens by name, Mongoose supports MongoDBs rich querying syntax.

    Kitten.find({ name: /^Fluff/ }, callback)

    This performs a search for all documents with a name property that begins with "Fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or API docs for more.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/js/cookies.min.js b/docs/3.5.x/docs/js/cookies.min.js deleted file mode 100644 index dc94dbc5bbc..00000000000 --- a/docs/3.5.x/docs/js/cookies.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! Cookies.js - 0.2.0; Copyright (c) 2012, Scott Hamper; http://www.opensource.org/licenses/MIT */ -(function(f,e){var b=function(c,d,a){return 1===arguments.length?b.get(c):b.set(c,d,a)};b.get=function(c){f.cookie!==b._cacheString&&b._populateCache();return b._cache[c]};b.defaults={path:"/"};b.set=function(c,d,a){a={path:a&&a.path||b.defaults.path,domain:a&&a.domain||b.defaults.domain,expires:a&&a.expires||b.defaults.expires,secure:a&&a.secure!==e?a.secure:b.defaults.secure};d===e&&(a.expires=-1);switch(typeof a.expires){case "number":a.expires=new Date((new Date).getTime()+1E3*a.expires);break; -case "string":a.expires=new Date(a.expires)}c=encodeURIComponent(c)+"="+(d+"").replace(/[^!#-+\--:<-[\]-~]/g,encodeURIComponent);c+=a.path?";path="+a.path:"";c+=a.domain?";domain="+a.domain:"";c+=a.expires?";expires="+a.expires.toGMTString():"";c+=a.secure?";secure":"";f.cookie=c;return b};b.expire=function(c,d){return b.set(c,e,d)};b._populateCache=function(){b._cache={};b._cacheString=f.cookie;for(var c=b._cacheString.split("; "),d=0;d>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.5.x/docs/middleware.html b/docs/3.5.x/docs/middleware.html deleted file mode 100644 index 6aa1061e6ba..00000000000 --- a/docs/3.5.x/docs/middleware.html +++ /dev/null @@ -1,40 +0,0 @@ -Mongoose Middleware v3.5.9Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods. There are two types of middleware, pre and post. Let's start with pre.

    Pre

    There are two types of pre middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next.

    var schema = new Schema(..);
    -schema.pre('save', function (next) {
    -  // do stuff
    -  next();
    -});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    -schema.pre('save', true, function (next, done) {
    -  // calling next kicks off the next middleware in parallel
    -  next();
    -  doAsync(done);
    -});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    -  var err = new Error('something went wrong');
    -  next(err);
    -});
    -
    -// later...
    -
    -myModel.save(function (err) {
    -  console.log(err.message) // something went wrong
    -});
    -

    Post middleware

    post middleware are executed after the hooked method and all of its pre middleware have completed. post middleware do not directly receive flow control, e.g. no next or done callbacks are passed to it. post hooks are a way to register traditional event listeners for these methods.

    schema.post('init', function (doc) {
    -  console.log('%s has been initialized from the db', doc._id);
    -})
    -schema.post('validate', function (doc) {
    -  console.log('%s has been validated (but not saved yet)', doc._id);
    -})
    -schema.post('save', function (doc) {
    -  console.log('%s has been saved', doc._id);
    -})
    -schema.post('remove', function (doc) {
    -  console.log('%s has been removed', doc._id);
    -})
    -

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/migration.html b/docs/3.5.x/docs/migration.html deleted file mode 100644 index 190fd95143c..00000000000 --- a/docs/3.5.x/docs/migration.html +++ /dev/null @@ -1,40 +0,0 @@ -Mongoose Migration Guide v3.5.9Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    - -

    Here are the removed methods and their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    - -

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    Schemas are now strict by default. This means that if you depended on saving fields not defined in the schema, you may lose data unless you set this back to false.

    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    - -

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    - -
    • $inc
    • $increment
    • $decrement
    - -

    If you really want this behavior back, include the mongoose-number module in your project.

    - -

    A good alternative is to start using the new findAndModify helpers. -Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    -...
    -Inventory.findById(id, function (err, inventory) {
    -  if (err) return handleError(err);
    -  inventory.productCount.$decrement(7);
    -  inventory.save(function (err) {
    -    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    -    if (err) return handleError(err);
    -    res.send(inventory.productCount); // 3
    -  });
    -});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    -  if (err) return handleError(err);
    -  res.send(inventory.productCount); // 3
    -});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This change allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    More Info

    Related blog posts:

    - -
    \ No newline at end of file diff --git a/docs/3.5.x/docs/models.html b/docs/3.5.x/docs/models.html deleted file mode 100644 index f6a827e10c7..00000000000 --- a/docs/3.5.x/docs/models.html +++ /dev/null @@ -1,30 +0,0 @@ -Mongoose Models v3.5.9Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var schema = new mongoose.Schema({ name: 'string', size: 'string' });
    -var Tank = mongoose.model('Tank', schema);
    -

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = mongoose.model('Tank', yourSchema);
    -
    -var small = new Tank({ size: 'small' });
    -small.save(function (err) {
    -  if (err) return handleError(err);
    -  // saved!
    -})
    -
    -// or
    -
    -Tank.create({ size: 'small' }, function (err, small) {
    -  if (err) return handleError(err);
    -  // saved!
    -})

    Note that no tanks will be created/removed until the connection your model uses is open. In this case we are using mongoose.model() so let's open the default mongoose connection:

    mongoose.connect('localhost', 'gettingstarted');
    -

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    -  if (err) return handleError(err);
    -  // removed!
    -});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    - -

    If you want to update a single document in the db and return it to your application, use findOneAndUpdate instead.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at Documents.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/plugins.html b/docs/3.5.x/docs/plugins.html deleted file mode 100644 index d031056e738..00000000000 --- a/docs/3.5.x/docs/plugins.html +++ /dev/null @@ -1,33 +0,0 @@ -Mongoose Plugins v3.5.9Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    - -

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    -module.exports = exports = function lastModifiedPlugin (schema, options) {
    -  schema.add({ lastMod: Date })
    -  
    -  schema.pre('save', function (next) {
    -    this.lastMod = new Date
    -    next()
    -  })
    -  
    -  if (options && options.index) {
    -    schema.path('lastMod').index(options.index)
    -  }
    -}
    -
    -// game-schema.js
    -var lastMod = require('./lastMod');
    -var Game = new Schema({ ... });
    -Game.plugin(lastMod, { index: true });
    -
    -// player-schema.js
    -var lastMod = require('./lastMod');
    -var Player = new Schema({ ... });
    -Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/populate.html b/docs/3.5.x/docs/populate.html deleted file mode 100644 index 1a7b88a68a8..00000000000 --- a/docs/3.5.x/docs/populate.html +++ /dev/null @@ -1,104 +0,0 @@ -Mongoose Query Population v3.5.9Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    - -

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    -  , Schema = mongoose.Schema
    -  
    -var PersonSchema = new Schema({
    -  name    : String,
    -  age     : Number,
    -  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    -});
    -
    -var StorySchema = new Schema({
    -  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    -  title    : String,
    -  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    -});
    -
    -var Story  = mongoose.model('Story', StorySchema);
    -var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    -
    -aaron.save(function (err) {
    -  if (err) return handleError(err);
    -  
    -  var story1 = new Story({
    -    title: "Once upon a timex.",
    -    _creator: aaron._id    // assign an ObjectId
    -  });
    -  
    -  story1.save(function (err) {
    -    if (err) return handleError(err);
    -    // thats it!
    -  });
    -})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    -.findOne({ title: /timex/ })
    -.populate('_creator')
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    -})
    -

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    - -

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    -.findOne({ title: /timex/i })
    -.populate('_creator', 'name') // only return the Persons name
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  
    -  console.log('The creator is %s', story._creator.name);
    -  // prints "The creator is Aaron"
    -  
    -  console.log('The creators age is %s', story._creator.age);
    -  // prints "The creators age is null'
    -})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    -.find(...)
    -.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    - -

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    -aaron.save();

    This allows us to perform a find and populate combo:

    Person
    -.findOne({ name: 'Aaron' })
    -.populate('stories') // only works if we pushed refs to children
    -.exec(function (err, person) {
    -  if (err) return handleError(err);
    -  console.log(person);
    -})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    -.find({ _creator: aaron._id })
    -.populate('_creator') // not really necessary
    -.exec(function (err, stories) {
    -  if (err) return handleError(err);
    -  console.log('The stories are an array: ', stories);
    -})
    -

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    -guille.save(function (err) {
    -  if (err) return handleError(err);
    -  
    -  story._creator = guille; // or guille._id
    -  
    -  story.save(function (err) {
    -    if (err) return handleError(err);
    -    
    -    Story
    -    .findOne({ title: /timex/i })
    -    .populate('_creator', 'name')
    -    .exec(function (err, story) {
    -      if (err) return handleError(err);
    -      
    -      console.log('The creator is %s', story._creator.name)
    -      // prints "The creator is Guillermo"
    -    })
    -  })
    -})
    -

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    -Story.findOne(..).populate('_creator', 'name age').exec(..);
    -
    -// this doesn't
    -Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
    -

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at connections.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/prior.html b/docs/3.5.x/docs/prior.html deleted file mode 100644 index d26f9269381..00000000000 --- a/docs/3.5.x/docs/prior.html +++ /dev/null @@ -1,9 +0,0 @@ -Mongoose v3.5.9Fork me on GitHub

    Prior Release Documentation

    \ No newline at end of file diff --git a/docs/3.5.x/docs/production.html b/docs/3.5.x/docs/production.html deleted file mode 100644 index 29f93a58b97..00000000000 --- a/docs/3.5.x/docs/production.html +++ /dev/null @@ -1,9 +0,0 @@ -MongooseFork me on GitHub

    You are being redirected to http://mongoosejs.tumblr.com.
    Please click here if you are not redirected in 5 seconds.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/queries.html b/docs/3.5.x/docs/queries.html deleted file mode 100644 index f5ef969088c..00000000000 --- a/docs/3.5.x/docs/queries.html +++ /dev/null @@ -1,41 +0,0 @@ -Mongoose Queries v3.5.9Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    - -

    When a callback function:

    - -
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    - -

    Let's take a look at what happens when passing a callback:

    var Person = mongoose.model('Person', yourSchema);
    -
    -// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    -Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    -  if (err) return handleError(err);
    -  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    Here we see that the query was executed immediately and the results passed to our callback. -Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    -var query = Person.findOne({ 'name.last': 'Ghost' });
    -
    -// selecting the `name` and `occupation` fields
    -query.select('name occupation');
    -
    -// execute the query at a later time
    -query.exec(function (err, person) {
    -  if (err) return handleError(err);
    -  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    -.find({ occupation: /host/ })
    -.where('name.last').equals('Ghost')
    -.where('age').gt(17).lt(66)
    -.where('likes').in(['vaporizing', 'talking'])
    -.limit(10)
    -.sort('-occupation')
    -.select('name occupation')
    -.exec(callback);
    -

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream. Note: QueryStreams are Node.js 0.8 style read streams not Node.js 0.10 style.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/schematypes.html b/docs/3.5.x/docs/schematypes.html deleted file mode 100644 index d42c5e0a073..00000000000 --- a/docs/3.5.x/docs/schematypes.html +++ /dev/null @@ -1,67 +0,0 @@ -Mongoose SchemaTypes v3.5.9Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    -  name:    String,
    -  binary:  Buffer,
    -  living:  Boolean,
    -  updated: { type: Date, default: Date.now },
    -  age:     { type: Number, min: 18, max: 65 },
    -  mixed:   Schema.Types.Mixed,
    -  _someId: Schema.Types.ObjectId,
    -  array:      [],
    -  ofString:   [String],
    -  ofNumber:   [Number],
    -  ofDates:    [Date],
    -  ofBuffer:   [Buffer],
    -  ofBoolean:  [Boolean],
    -  ofMixed:    [Schema.Types.Mixed],
    -  ofObjectId: [Schema.Types.ObjectId],
    -  nested: {
    -    stuff: { type: String, lowercase: true, trim: true }
    -  }
    -})
    -
    -// example use
    -
    -var Thing = mongoose.model('Thing', schema);
    -
    -var m = new Thing;
    -m.name = 'Statue of Liberty';
    -m.age = 125;
    -m.updated = new Date;
    -m.binary = new Buffer(0);
    -m.living = false;
    -m.mixed = {[ any: { thing: 'i want' } ]};
    -m.markModified('mixed');
    -m._someId = new mongoose.Types.ObjectId;
    -m.array.push(1);
    -m.ofString.push("strings!");
    -m.ofNumber.unshift(1,2,3,4);
    -m.ofDates.addToSet(new Date);
    -m.ofBuffer.pop();
    -m.ofMixed = [1, [], 'three', { four: 5 }];
    -m.nested.stuff = 'good';
    -m.save(callback);
    -

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    -var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    -person.markModified('anything');
    -person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    -var ObjectId = mongoose.Schema.Types.ObjectId;
    -var Car = new Schema({ driver: ObjectId });
    -// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    -var ToyBox = new Schema({
    -  toys: [ToySchema],
    -  buffers: [Buffer],
    -  string:  [String],
    -  numbers: [Number]
    -  // ... etc
    -});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    -var Empty2 = new Schema({ any: Array });
    -var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    -var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Models.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/source/_docs b/docs/3.5.x/docs/source/_docs deleted file mode 100644 index 6f04de5db44..00000000000 --- a/docs/3.5.x/docs/source/_docs +++ /dev/null @@ -1,18108 +0,0 @@ - -### lib/collection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var STATES = require('./connectionstate')", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "require('./connectionstate')", - "string": "STATES" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the collection" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "conn", - "description": "A MongooseConnection instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "optional collection options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", - "summary": "

    Abstract Collection constructor

    ", - "body": "

    This is the base class that drivers inherit from and implement.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Collection (name, conn, opts) {\n if (undefined === opts) opts = {};\n if (undefined === opts.capped) opts.capped = {};\n\n opts.bufferCommands = undefined === opts.bufferCommands\n ? true\n : opts.bufferCommands;\n\n if ('number' == typeof opts.capped) {\n opts.capped = { size: opts.capped };\n }\n\n this.opts = opts;\n this.name = name;\n this.conn = conn;\n this.queue = [];\n this.buffer = this.opts.bufferCommands;\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", - "ctx": { - "type": "function", - "name": "Collection", - "string": "Collection()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "name" - } - ], - "description": { - "full": "

    The collection name

    ", - "summary": "

    The collection name

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.name;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "conn" - } - ], - "description": { - "full": "

    The Connection instance

    ", - "summary": "

    The Connection instance

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Collection.prototype.conn;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the database connects

    ", - "summary": "

    Called when the database connects

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onOpen", - "string": "Collection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the database disconnects

    ", - "summary": "

    Called when the database disconnects

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.onClose = function () {\n if (this.opts.bufferCommands) {\n this.buffer = true;\n }\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "onClose", - "string": "Collection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the method to queue" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method when executed" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Queues a method for later execution when its
    database connection opens.

    ", - "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "addQueue", - "string": "Collection.prototype.addQueue()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes all queued methods and clears the queue.

    ", - "summary": "

    Executes all queued methods and clears the queue.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "doQueue", - "string": "Collection.prototype.doQueue()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "ensureIndex", - "string": "Collection.prototype.ensureIndex()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findAndModify", - "string": "Collection.prototype.findAndModify()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "findOne", - "string": "Collection.prototype.findOne()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "find", - "string": "Collection.prototype.find()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "insert", - "string": "Collection.prototype.insert()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "save", - "string": "Collection.prototype.save()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "update", - "string": "Collection.prototype.update()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "getIndexes", - "string": "Collection.prototype.getIndexes()" - } - }, - { - "tags": [], - "description": { - "full": "

    Abstract method that drivers must implement.

    ", - "summary": "

    Abstract method that drivers must implement.

    ", - "body": "" - }, - "ignore": false, - "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", - "ctx": { - "type": "method", - "constructor": "Collection", - "name": "mapReduce", - "string": "Collection.prototype.mapReduce()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Collection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Collection", - "string": "module.exports" - } - } -] -### lib/connection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = require('events').EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , MongooseError = require('./error')\n , assert =require('assert')\n , muri = require('muri')", - "ctx": { - "type": "declaration", - "name": "url", - "value": "require('url')", - "string": "url" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Protocol prefix regexp.

    ", - "summary": "

    Protocol prefix regexp.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", - "ctx": { - "type": "declaration", - "name": "rgxProtocol", - "value": "/^(?:.)+:\\/\\//", - "string": "rgxProtocol" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "a mongoose instance" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." - }, - { - "type": "event", - "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." - }, - { - "type": "event", - "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." - }, - { - "type": "event", - "string": "`disconnecting`: Emitted when `connection.close()` was executed." - }, - { - "type": "event", - "string": "`disconnected`: Emitted after getting disconnected from the db." - }, - { - "type": "event", - "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." - }, - { - "type": "event", - "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." - }, - { - "type": "event", - "string": "`error`: Emitted when an error occurs on this connection." - }, - { - "type": "event", - "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", - "summary": "

    Connection constructor

    ", - "body": "

    For practical reasons, a Connection equals a Db.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.hosts = null;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", - "ctx": { - "type": "function", - "name": "Connection", - "string": "Connection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter

    ", - "summary": "

    Inherit from EventEmitter

    ", - "body": "" - }, - "ignore": true, - "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Connection", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Connection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readyState" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", - "summary": "

    Connection ready state

    ", - "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" - }, - { - "tags": [ - { - "type": "property", - "string": "collections" - } - ], - "description": { - "full": "

    A hash of the collections associated with this connection

    ", - "summary": "

    A hash of the collections associated with this connection

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collections;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

    The mongodb.Db instance, set when the connection is opened

    ", - "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.db;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "connection_string", - "description": "mongodb://uri or the host to which you are connecting" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[port]", - "description": "database port" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "see", - "title": "", - "url": "http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate", - "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\nauth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    \n\n

    Options passed take precedence over options included in connection strings.

    ", - "summary": "

    Opens the connection to MongoDB.

    ", - "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\nauth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    \n\n

    Options passed take precedence over options included in connection strings.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , parsed\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n try {\n parsed = muri(host);\n } catch (err) {\n this.error(err, callback);\n return this;\n }\n\n database = parsed.db;\n host = parsed.hosts[0].host || parsed.hosts[0].ipc;\n port = parsed.hosts[0].port || 27017;\n }\n\n this.options = this.parseOptions(options, parsed && parsed.options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing database name.'), callback);\n return this;\n }\n\n // authentication\n if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else if (parsed && parsed.auth) {\n this.user = parsed.auth.user;\n this.pass = parsed.auth.pass;\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "open", - "string": "Connection.prototype.open()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "uris", - "description": "comma-separated mongodb:// `URI`s" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[database]", - "description": "database name if not included in `uris`" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "passed to the internal driver" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "node-mongodb-native", - "url": "https://github.com/mongodb/node-mongodb-native", - "visibility": "https://github.com/mongodb/node-mongodb-native" - }, - { - "type": "see", - "title": "", - "url": "http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate", - "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Opens the connection to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\nauth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)\n
    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    ", - "summary": "

    Opens the connection to a replica set.

    ", - "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\nauth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)\n
    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n if (!rgxProtocol.test(uris)) {\n uris = 'mongodb://' + uris;\n }\n\n var self = this;\n\n switch (arguments.length) {\n case 3:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'object':\n callback = options;\n options = database;\n database = null;\n break;\n }\n\n if ('function' === typeof options) {\n callback = options;\n options = {};\n }\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n var parsed;\n try {\n parsed = muri(uris);\n } catch (err) {\n this.error(err, callback);\n return this;\n }\n\n if (!this.name) {\n this.name = parsed.db;\n }\n\n this.hosts = parsed.hosts;\n this.options = this.parseOptions(options, parsed && parsed.options);\n this.replica = true;\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n // authentication\n if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else if (parsed && parsed.auth) {\n this.user = parsed.auth.user;\n this.pass = parsed.auth.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this._open(callback);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "openSet", - "string": "Connection.prototype.openSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "optional" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", - "summary": "

    error

    ", - "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "error", - "string": "Connection.prototype.error()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", - "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen(callback);\n });\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "_open", - "string": "Connection.prototype._open()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection is opened

    ", - "summary": "

    Called when the connection is opened

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onOpen = function (callback) {\n var self = this;\n\n function open (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n callback && callback();\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass) {\n self.db.authenticate(self.user, self.pass, self.options.auth, open);\n }\n else\n open();\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onOpen", - "string": "Connection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "self" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Closes the connection

    ", - "summary": "

    Closes the connection

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "close", - "string": "Connection.prototype.close()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection closes

    ", - "summary": "

    Called when the connection closes

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "onClose", - "string": "Connection.prototype.onClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "of the collection" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional collection options" - }, - { - "type": "return", - "types": [ - "Collection" - ], - "description": "collection instance" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Retrieves a collection, creating it if not cached.

    ", - "summary": "

    Retrieves a collection, creating it if not cached.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "collection", - "string": "Connection.prototype.collection()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "the model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "a schema. necessary when defining a model" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name of mongodb collection (optional) if not given it will be induced from model name" - }, - { - "type": "see", - "local": "Mongoose#model #index_Mongoose-model", - "visibility": "Mongoose#model" - }, - { - "type": "return", - "types": [ - "Model" - ], - "description": "The compiled model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String }, { collection: 'actor' });\n\n// or\n\nschema.set('collection', 'actor');\n\n// or\n\nvar collectionName = 'actor'\nvar M = conn.model('Actor', schema, collectionName)\n
    ", - "summary": "

    Defines or retrieves a model.

    ", - "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String }, { collection: 'actor' });\n\n// or\n\nschema.set('collection', 'actor');\n\n// or\n\nvar collectionName = 'actor'\nvar M = conn.model('Actor', schema, collectionName)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.model = function (name, schema, collection) {\n // collection name discovery\n if ('string' == typeof schema) {\n collection = schema;\n schema = false;\n }\n\n if (utils.isObject(schema) && !(schema instanceof Schema)) {\n schema = new Schema(schema);\n }\n\n if (this.models[name] && !collection) {\n // model exists but we are not subclassing with custom collection\n if (schema instanceof Schema && schema != this.models[name].schema) {\n throw new MongooseError.OverwriteModelError(name);\n }\n return this.models[name];\n }\n\n var opts = { cache: false, connection: this }\n var model;\n\n if (schema instanceof Schema) {\n // compile a model\n model = this.base.model(name, schema, collection, opts)\n\n // only the first model with this name is cached to allow\n // for one-offs with custom collection names etc.\n if (!this.models[name]) {\n this.models[name] = model;\n }\n\n model.init();\n return model;\n }\n\n if (this.models[name] && collection) {\n // subclassing current model with alternate collection\n model = this.models[name];\n schema = model.prototype.schema;\n var sub = model.__subclass(this, schema, collection);\n // do not cache the sub model\n return sub;\n }\n\n // lookup model in mongoose module\n model = this.base.models[name];\n\n if (!model) {\n throw new MongooseError.MissingSchemaError(name);\n }\n\n if (this == model.prototype.db\n && (!collection || collection == model.collection.name)) {\n // model already uses this connection.\n\n // only the first model with this name is cached to allow\n // for one-offs with custom collection names etc.\n if (!this.models[name]) {\n this.models[name] = model;\n }\n\n return model;\n }\n\n return this.models[name] = model.__subclass(this, schema, collection);\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "model", - "string": "Connection.prototype.model()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns an array of model names created on this connection.

    ", - "summary": "

    Returns an array of model names created on this connection.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.modelNames = function () {\n return Object.keys(this.models);\n}", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "modelNames", - "string": "Connection.prototype.modelNames()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "level", - "description": "either off (0), slow (1), or all (2)" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "[ms]", - "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Set profiling level.

    ", - "summary": "

    Set profiling level.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", - "ctx": { - "type": "method", - "constructor": "Connection", - "name": "setProfiling", - "string": "Connection.prototype.setProfiling()" - } - }, - { - "tags": [], - "description": { - "full": "

    Noop.

    ", - "summary": "

    Noop.

    ", - "body": "" - }, - "ignore": true, - "code": "function noop () {}", - "ctx": { - "type": "function", - "name": "noop", - "string": "noop()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", - "ctx": { - "type": "property", - "receiver": "Connection", - "name": "STATES", - "value": "STATES", - "string": "Connection.STATES" - } - } -] -### lib/connectionstate.js -[ - { - "tags": [], - "description": { - "full": "

    Connection states

    ", - "summary": "

    Connection states

    ", - "body": "" - }, - "ignore": true, - "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", - "ctx": { - "type": "declaration", - "name": "STATES", - "value": "module.exports = exports = Object.create(null)", - "string": "STATES" - } - } -] -### lib/document.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , ElemMatchError = MongooseError.ElemMatchError\n , ValidationError = MongooseError.ValidationError\n , DocumentError = MongooseError.DocumentError\n , InternalCache = require('./internal')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray\n , MongooseArray", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the values to set" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "optional object containing the fields which were selected in the query returning this document and any populated paths data" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "bool, should we auto create an ObjectId _id" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." - }, - { - "type": "event", - "string": "`save`: Emitted when the document is successfully saved" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Document constructor.

    ", - "summary": "

    Document constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Document (obj, fields, skipId) {\n this.$__ = new InternalCache;\n this.isNew = true;\n this.errors = undefined;\n\n var schema = this.schema;\n\n if ('boolean' === typeof fields) {\n this.$__.strictMode = fields;\n fields = undefined;\n } else {\n this.$__.strictMode = schema.options && schema.options.strict;\n this.$__.selected = fields;\n }\n\n var required = schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this.$__.activePaths.require(required[i]);\n }\n\n this._doc = this.$__buildDoc(obj, fields, skipId);\n this.setMaxListeners(0);\n\n if (obj) {\n this.set(obj, undefined, true);\n }\n\n this.$__registerHooks();\n}", - "ctx": { - "type": "function", - "name": "Document", - "string": "Document()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Document.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Document.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "schema" - } - ], - "description": { - "full": "

    The documents schema.

    ", - "summary": "

    The documents schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.schema;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "isNew" - } - ], - "description": { - "full": "

    Boolean flag specifying if the document is new.

    ", - "summary": "

    Boolean flag specifying if the document is new.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isNew;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "local": "Schema options /docs/guide.html#options", - "visibility": "Schema" - }, - { - "type": "property", - "string": "id" - } - ], - "description": { - "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", - "summary": "

    The string version of this documents _id.

    ", - "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.id;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "errors" - } - ], - "description": { - "full": "

    Hash containing current validation errors.

    ", - "summary": "

    Hash containing current validation errors.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.errors;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipId]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__buildDoc" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Builds the default doc structure

    ", - "summary": "

    Builds the default doc structure

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self.$__.activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self.$__.activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self.$__.activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "document returned by mongo" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", - "summary": "

    Initializes the document without setters or marking anything modified.

    ", - "body": "

    Called internally after a document is returned from mongodb.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.init = function (doc, opts, fn) {\n // do not prefix this method with $__ since its\n // used by public hooks\n\n if ('function' == typeof opts) {\n fn = opts;\n opts = null;\n }\n\n this.isNew = false;\n\n // handle docs with populated paths\n if (doc._id && opts && opts.populated && opts.populated.length) {\n var id = String(doc._id);\n for (var i = 0; i < opts.populated.length; ++i) {\n var item = opts.populated[i];\n this.populated(item.path, item._docs[id], item);\n }\n }\n\n init(this, doc, this._doc);\n this.$__storeShard();\n\n this.emit('init', this);\n if (fn) fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "init", - "string": "Document.prototype.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "self", - "description": "document instance" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "raw mongodb doc" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "object we are initializing" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Init helper.

    ", - "summary": "

    Init helper.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) doc[i] = {};\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.$__try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self.$__.activePaths.init(path);\n }\n }\n};", - "ctx": { - "type": "function", - "name": "init", - "string": "init()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__storeShard" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", - "summary": "

    Stores the current values of the shard keys.

    ", - "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__storeShard = function () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this.$__.shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}" - }, - { - "tags": [], - "description": { - "full": "

    Set up middleware support

    ", - "summary": "

    Set up middleware support

    ", - "body": "" - }, - "ignore": true, - "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" - }, - { - "tags": [ - { - "type": "see", - "local": "Model.update #model_Model.update", - "visibility": "Model.update" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);\n
    \n\n

    Valid options:

    \n\n", - "summary": "

    Sends an update command with this document _id as the query selector.

    ", - "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);\n
    \n\n

    Valid options:

    \n\n" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "update", - "string": "Document.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "path", - "description": "path or object of key/vals to set" - }, - { - "type": "param", - "types": [ - "Any" - ], - "name": "val", - "description": "the value to set" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for \"on-the-fly\" attributes" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optionally specify options that modify the behavior of the set" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n\n// changing strict mode behavior\ndoc.set(path, value, { strict: false });\n
    ", - "summary": "

    Sets the value of a path, or many paths.

    ", - "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n\n// changing strict mode behavior\ndoc.set(path, value, { strict: false });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.set = function (path, val, type, options) {\n if (type && 'Object' == type.constructor.name) {\n options = type;\n type = undefined;\n }\n\n var merge = options && options.merge\n , adhoc = type && true !== type\n , constructing = true === type\n , adhocs\n\n var strict = options && 'strict' in options\n ? options.strict\n : this.$__.strictMode;\n\n if (adhoc) {\n adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n pathtype = this.schema.pathType(prefix + key);\n if (null != path[key]\n && 'Object' == path[key].constructor.name\n && 'virtual' != pathtype\n && !(this.$__path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (strict) {\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == strict) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n if (!merge) this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && strict) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this.$__path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this.$__set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.$__try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "set", - "string": "Document.prototype.set()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__shouldModify" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Determine if we should mark this change as modified.

    ", - "summary": "

    Determine if we should mark this change as modified.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__shouldModify = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n if (this.isNew) return true;\n if (this.isDirectModified(pathToMark)) return false;\n\n if (undefined === val && !this.isSelected(path)) {\n // when a path is not selected in a query, its initial\n // value will be undefined.\n return true;\n }\n\n if (undefined === val && path in this.$__.activePaths.states.default) {\n // we're just unsetting the default value which was never saved\n return false;\n }\n\n if (!deepEqual(val, priorVal || this.get(path))) {\n return true;\n }\n\n if (!constructing &&\n null != val &&\n path in this.$__.activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n return true;\n }\n\n return false;\n}" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__set" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", - "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__set = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n var shouldModify = this.$__shouldModify.apply(this, arguments);\n\n if (shouldModify) {\n this.markModified(pathToMark, val);\n\n // handle directly setting arrays (gh-1126)\n MongooseArray || (MongooseArray = require('./types/array'));\n if (val instanceof MongooseArray) {\n val._registerAtomic('$set', val);\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n}" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Gets a raw value from a path (no getters)

    ", - "summary": "

    Gets a raw value from a path (no getters)

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.getValue = function (path) {\n return utils.getValue(path, this._doc);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "getValue", - "string": "Document.prototype.getValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", - "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.setValue = function (path, val) {\n utils.setValue(path, val, this._doc);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "setValue", - "string": "Document.prototype.setValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema", - "String", - "Number", - "Buffer", - "etc.." - ], - "name": "[type]", - "description": "optionally specify a type for on-the-fly attributes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", - "summary": "

    Returns the value of a path.

    ", - "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this.$__path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "get", - "string": "Document.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__path" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Returns the schematype for the given path.

    ", - "summary": "

    Returns the schematype for the given path.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__path = function (path) {\n var adhocs = this.$__.adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to mark modified" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", - "summary": "

    Marks the path as having pending changes to write to the db.

    ", - "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.markModified = function (path) {\n this.$__.activePaths.modify(path);\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "markModified", - "string": "Document.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "function to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope with which to call fn" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__try" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", - "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this.$__error(e);\n res = false;\n }\n return res;\n};" - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the list of paths that have been modified.

    ", - "summary": "

    Returns the list of paths that have been modified.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "modifiedPaths", - "string": "Document.prototype.modifiedPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "optional" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", - "summary": "

    Returns true if this document was modified, else false.

    ", - "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this.$__.activePaths.some('modify');\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isModified", - "string": "Document.prototype.isModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", - "summary": "

    Returns true if path was directly set and modified, else false.

    ", - "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this.$__.activePaths.states.modify);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isDirectModified", - "string": "Document.prototype.isDirectModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Checks if path was initialized.

    ", - "summary": "

    Checks if path was initialized.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isInit = function (path) {\n return (path in this.$__.activePaths.states.init);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isInit", - "string": "Document.prototype.isInit()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", - "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", - "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this.$__.selected) {\n\n if ('_id' === path) {\n return 0 !== this.$__.selected._id;\n }\n\n var paths = Object.keys(this.$__.selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this.$__.selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this.$__.selected[cur];\n break;\n }\n\n if (path in this.$__.selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "isSelected", - "string": "Document.prototype.isSelected()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "cb", - "description": "called after validation completes, passing an error if one occurred" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", - "summary": "

    Executes registered validation rules for this document.

    ", - "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this.$__.activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this.$__.activePaths.states.init));\n paths = paths.concat(Object.keys(this.$__.activePaths.states.modify));\n paths = paths.concat(Object.keys(this.$__.activePaths.states.default));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n var val = self.getValue(path);\n p.doValidate(val, function (err) {\n if (err) {\n self.invalidate(\n path\n , err\n , undefined\n , true // embedded docs\n );\n }\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self.$__.validationError;\n self.$__.validationError = undefined;\n self.emit('validate', self);\n cb(err);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "validate", - "string": "Document.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "the error which states the reason `path` was invalid" - }, - { - "type": "param", - "types": [ - "Object", - "String", - "Number", - "any" - ], - "name": "value", - "description": "optional invalid value" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks a path as invalid, causing validation to fail.

    ", - "summary": "

    Marks a path as invalid, causing validation to fail.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.invalidate = function (path, err, val) {\n if (!this.$__.validationError) {\n this.$__.validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n // sniffing arguments:\n // need to handle case where user does not pass value\n // so our error message is cleaner\n err = 2 < arguments.length\n ? new ValidatorError(path, err, val)\n : new ValidatorError(path, err)\n }\n\n this.$__.validationError.errors[path] = err;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "invalidate", - "string": "Document.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - }, - { - "type": "method", - "string": "$__reset" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Resets the internal modified state of this document.

    ", - "summary": "

    Resets the internal modified state of this document.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.$__.activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n })\n .forEach(function (array) {\n var i = array.length;\n while (i--) {\n var doc = array[i];\n if (!doc) continue;\n doc.$__reset();\n }\n });\n\n // clear atomics\n this.$__dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this.$__.activePaths.clear('modify');\n this.$__.validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self.$__.activePaths.require(path);\n });\n\n return this;\n}" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__dirty" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Returns this documents dirty paths / vals.

    ", - "summary": "

    Returns this documents dirty paths / vals.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__dirty = function () {\n var self = this;\n\n var all = this.$__.activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self.$__path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n // special case for top level MongooseArrays\n if (top.value && top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}" - }, - { - "tags": [], - "description": { - "full": "

    Compiles schemas.

    ", - "summary": "

    Compiles schemas.

    ", - "body": "" - }, - "ignore": true, - "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", - "ctx": { - "type": "function", - "name": "compile", - "string": "compile()" - } - }, - { - "tags": [], - "description": { - "full": "

    Defines the accessor named prop on the incoming prototype.

    ", - "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", - "body": "" - }, - "ignore": true, - "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.$__.getters)\n this.$__.getters = {};\n\n if (!this.$__.getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested.$__.scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.$__.getters[path] = nested;\n }\n\n return this.$__.getters[path];\n }\n , set: function (v) {\n if (v instanceof Document) v = v.toObject();\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this.$__.scope || this, path); }\n , set: function (v) { return this.set.call(this.$__.scope || this, path, v); }\n });\n }\n};", - "ctx": { - "type": "function", - "name": "define", - "string": "define()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__setSchema" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Assigns/compiles schema into this documents prototype.

    ", - "summary": "

    Assigns/compiles schema into this documents prototype.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__registerHooks" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Register default hooks

    ", - "summary": "

    Register default hooks

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__registerHooks = function () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // validate all document arrays.\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this.$__.activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n if (error) return;\n\n // handle sparse arrays by using for loop vs array.forEach\n // which skips the sparse elements\n\n var len = array.length\n subdocs += len;\n\n for (var i = 0; i < len; ++i) {\n if (error) break;\n\n var doc = array[i];\n if (!doc) {\n --subdocs || next();\n continue;\n }\n\n doc.save(handleSave);\n }\n });\n\n function handleSave (err) {\n if (error) return;\n\n if (err) {\n self.$__.validationError = undefined;\n return next(error = err);\n }\n\n --subdocs || next();\n }\n\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n var err = this.$__.saveError;\n if (err) {\n this.$__.saveError = null;\n next(err);\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this.$__doQueue();\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "err", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__error" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Registers an error

    ", - "summary": "

    Registers an error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__error = function (err) {\n this.$__.saveError = err;\n return this;\n};" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__doQueue" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Executes methods queued from the Schema definition

    ", - "summary": "

    Executes methods queued from the Schema definition

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "js object" - }, - { - "type": "see", - "title": "mongodb.Binary", - "url": "http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html", - "visibility": "http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Converts this document into a plain javascript object, ready for storage in MongoDB.

    \n\n

    Buffers are converted to instances of mongodb.Binary for proper storage.

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    ", - "summary": "

    Converts this document into a plain javascript object, ready for storage in MongoDB.

    ", - "body": "

    Buffers are converted to instances of mongodb.Binary for proper storage.

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toObject = function (options) {\n // check for populated paths that we set to a document\n if (options && options.convertToId) {\n return clone(this._id, options);\n }\n\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n if (true === options.transform) {\n var opts = options.json\n ? this.schema.options.toJSON\n : this.schema.options.toObject;\n if (opts) {\n options.transform = opts.transform;\n }\n }\n\n if ('function' == typeof options.transform) {\n var xformed = options.transform(this, ret, options);\n if ('undefined' != typeof xformed) ret = xformed;\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toObject", - "string": "Document.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "json", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "either `virtuals` or `paths`" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "`json`" - } - ], - "description": { - "full": "

    Applies virtuals properties to json.

    ", - "summary": "

    Applies virtuals properties to json.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", - "ctx": { - "type": "function", - "name": "applyGetters", - "string": "applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "same options as [Document#toObject](#document_Document-toObject)" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "see", - "local": "Document#toObject #document_Document-toObject", - "visibility": "Document#toObject" - }, - { - "type": "", - "string": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    \n\n

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", - "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", - "body": "

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "toJSON", - "string": "Document.prototype.toJSON()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name ? options :\n this.schema.options.toObject ? clone(this.schema.options.toObject) :\n {};\n opts.minimize = false;\n return inspect(this.toObject(opts));\n};", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "inspect", - "string": "Document.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "toString" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.toString = Document.prototype.inspect;", - "ctx": { - "type": "property", - "constructor": "Document", - "name": "toString", - "value": "Document.prototype.inspect", - "string": "Document.prototypetoString" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "a document to compare" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", - "summary": "

    Returns true if the Document stores the same data as doc.

    ", - "body": "

    Documents are considered equal when they have matching _ids.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "equals", - "string": "Document.prototype.equals()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Model.populate #model_Model.populate", - "visibility": "Model.populate" - }, - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "[path]", - "description": "The path to populate or an options object" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "When passed, population is invoked" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Document" - ], - "description": "this" - } - ], - "description": { - "full": "

    Populates document references, executing the callback when complete.

    \n\n

    Example:

    \n\n
    doc\n.populate('company')\n.populate({\n  path: 'notes',\n  match: /airline/,\n  select: 'text',\n  match: 'modelName'\n  options: opts\n}, function (err, user) {\n  assert(doc._id == user._id) // the document itself is passed\n})\n\n// summary\ndoc.populate(path)               // not executed\ndoc.populate(options);           // not executed\ndoc.populate(path, callback)     // executed\ndoc.populate(options, callback); // executed\ndoc.populate(callback);          // executed\n
    \n\n

    NOTE:

    \n\n

    Population does not occur unless a callback is passed.
    Passing the same path a second time will overwrite the previous path options.
    See Model.populate() for explaination of options.

    ", - "summary": "

    Populates document references, executing the callback when complete.

    ", - "body": "

    Example:

    \n\n
    doc\n.populate('company')\n.populate({\n  path: 'notes',\n  match: /airline/,\n  select: 'text',\n  match: 'modelName'\n  options: opts\n}, function (err, user) {\n  assert(doc._id == user._id) // the document itself is passed\n})\n\n// summary\ndoc.populate(path)               // not executed\ndoc.populate(options);           // not executed\ndoc.populate(path, callback)     // executed\ndoc.populate(options, callback); // executed\ndoc.populate(callback);          // executed\n
    \n\n

    NOTE:

    \n\n

    Population does not occur unless a callback is passed.
    Passing the same path a second time will overwrite the previous path options.
    See Model.populate() for explaination of options.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.populate = function populate () {\n if (0 === arguments.length) return this;\n\n var pop = this.$__.populate || (this.$__.populate = {});\n var args = utils.args(arguments);\n var fn;\n\n if ('function' == typeof args[args.length-1]) {\n fn = args.pop();\n }\n\n // allow `doc.populate(callback)`\n if (args.length) {\n // use hash to remove duplicate paths\n var res = utils.populate.apply(null, args);\n for (var i = 0; i < res.length; ++i) {\n pop[res[i].path] = res[i];\n }\n }\n\n if (fn) {\n var paths = utils.object.vals(pop);\n this.$__.populate = undefined;\n this.constructor.populate(this, paths, fn);\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "populate", - "string": "Document.prototype.populate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Array", - "ObjectId", - "Number", - "Buffer", - "String", - "undefined" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets _id(s) used during population of the given path.

    \n\n

    Example:

    \n\n
    Model.findOne().populate('author').exec(function (err, doc) {\n  console.log(doc.author.name)         // Dr.Seuss\n  console.log(doc.populated('author')) // '5144cf8050f071d979c118a7'\n})\n
    \n\n

    If the path was not populated, undefined is returned.

    ", - "summary": "

    Gets _id(s) used during population of the given path.

    ", - "body": "

    Example:

    \n\n
    Model.findOne().populate('author').exec(function (err, doc) {\n  console.log(doc.author.name)         // Dr.Seuss\n  console.log(doc.populated('author')) // '5144cf8050f071d979c118a7'\n})\n
    \n\n

    If the path was not populated, undefined is returned.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Document.prototype.populated = function (path, val, options) {\n // val and options are internal\n\n if (null == val) {\n if (!this.$__.populated) return undefined;\n var v = this.$__.populated[path];\n if (v) return v.value;\n return undefined;\n }\n\n // internal\n\n if (true === val) {\n if (!this.$__.populated) return undefined;\n return this.$__.populated[path];\n }\n\n this.$__.populated || (this.$__.populated = {});\n this.$__.populated[path] = { value: val, options: options };\n return val;\n}", - "ctx": { - "type": "method", - "constructor": "Document", - "name": "populated", - "string": "Document.prototype.populated()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__fullPath" - }, - { - "type": "memberOf", - "parent": "Document" - } - ], - "description": { - "full": "

    Returns the full path to this document.

    ", - "summary": "

    Returns the full path to this document.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Document.prototype.$__fullPath = function (path) {\n // overridden in SubDocuments\n return path || '';\n}" - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", - "ctx": { - "type": "property", - "receiver": "Document", - "name": "ValidationError", - "value": "ValidationError", - "string": "Document.ValidationError" - } - } -] -### lib/drivers/node-mongodb-native/binary.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require('mongodb').BSONPure.Binary", - "string": "Binary" - } - } -] -### lib/drivers/node-mongodb-native/collection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", - "ctx": { - "type": "declaration", - "name": "MongooseCollection", - "value": "require('../../collection')", - "string": "MongooseCollection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Collection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", - "summary": "

    A node-mongodb-native collection implementation.

    ", - "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", - "ctx": { - "type": "function", - "name": "NativeCollection", - "string": "NativeCollection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from abstract Collection.

    ", - "summary": "

    Inherit from abstract Collection.

    ", - "body": "" - }, - "ignore": true, - "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "__proto__", - "value": "MongooseCollection.prototype", - "string": "NativeCollection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection opens.

    ", - "summary": "

    Called when the connection opens.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n // always get a new collection in case the user changed host:port\n // of parent db instance when re-opening the connection.\n\n if (!self.opts.capped.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts.capped);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onOpen", - "string": "NativeCollection.prototype.onOpen()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the connection closes

    ", - "summary": "

    Called when the connection closes

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", - "ctx": { - "type": "method", - "constructor": "NativeCollection", - "name": "onClose", - "string": "NativeCollection.prototype.onClose()" - } - }, - { - "tags": [], - "description": { - "full": "

    Copy the collection methods and make them subject to queues

    ", - "summary": "

    Copy the collection methods and make them subject to queues

    ", - "body": "" - }, - "ignore": true, - "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" - }, - { - "tags": [], - "description": { - "full": "

    Debug print helper

    ", - "summary": "

    Debug print helper

    ", - "body": "" - }, - "ignore": true, - "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", - "ctx": { - "type": "function", - "name": "print", - "string": "print()" - } - }, - { - "tags": [], - "description": { - "full": "

    Debug print helper

    ", - "summary": "

    Debug print helper

    ", - "body": "" - }, - "ignore": true, - "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if ('Date' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", - "ctx": { - "type": "function", - "name": "format", - "string": "format()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "method", - "string": "getIndexes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Retreives information about this collections indexes.

    ", - "summary": "

    Retreives information about this collections indexes.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", - "ctx": { - "type": "property", - "constructor": "NativeCollection", - "name": "getIndexes", - "value": "NativeCollection.prototype.indexInformation", - "string": "NativeCollection.prototypegetIndexes" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeCollection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeCollection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/connection.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", - "ctx": { - "type": "declaration", - "name": "MongooseConnection", - "value": "require('../../connection')", - "string": "MongooseConnection" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "Connection" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A node-mongodb-native connection implementation.

    ", - "summary": "

    A node-mongodb-native connection implementation.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n this._listening = false;\n};", - "ctx": { - "type": "function", - "name": "NativeConnection", - "string": "NativeConnection()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Connection.

    ", - "summary": "

    Inherits from Connection.

    ", - "body": "" - }, - "ignore": true, - "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", - "ctx": { - "type": "property", - "constructor": "NativeConnection", - "name": "__proto__", - "value": "MongooseConnection.prototype", - "string": "NativeConnection.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Opens the connection to MongoDB.

    ", - "summary": "

    Opens the connection to MongoDB.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpen = function (fn) {\n if (this.db) {\n mute(this);\n }\n\n var server = new mongo.Server(this.host, this.port, this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n var self = this;\n this.db.open(function (err) {\n if (err) return fn(err);\n listen(self);\n fn();\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpen", - "string": "NativeConnection.prototype.doOpen()" - } - }, - { - "tags": [], - "description": { - "full": "

    Register listeners for important events and bubble appropriately.

    ", - "summary": "

    Register listeners for important events and bubble appropriately.

    ", - "body": "" - }, - "ignore": true, - "code": "function listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", - "ctx": { - "type": "function", - "name": "listen", - "string": "listen()" - } - }, - { - "tags": [], - "description": { - "full": "

    Remove listeners registered in listen

    ", - "summary": "

    Remove listeners registered in listen

    ", - "body": "" - }, - "ignore": true, - "code": "function mute (conn) {\n if (!conn.db) throw new Error('missing db');\n conn.db.removeAllListeners(\"close\");\n conn.db.removeAllListeners(\"error\");\n conn.db.removeAllListeners(\"timeout\");\n conn.db.removeAllListeners(\"open\");\n conn.db.removeAllListeners(\"fullsetup\");\n conn._listening = false;\n}", - "ctx": { - "type": "function", - "name": "mute", - "string": "mute()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - } - ], - "description": { - "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", - "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", - "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (this.db) {\n mute(this);\n }\n\n var servers = []\n , self = this;\n\n this.hosts.forEach(function (server) {\n var host = server.host || server.ipc;\n var port = server.port || 27017;\n servers.push(new mongo.Server(host, port, self.options.server));\n })\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doOpenSet", - "string": "NativeConnection.prototype.doOpenSet()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Closes the connection

    ", - "summary": "

    Closes the connection

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "doClose", - "string": "NativeConnection.prototype.doClose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "passed", - "description": "options that were passed directly during connection" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[connStrOptions]", - "description": "options that were passed in the connection string" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Prepares default connection options for the node-mongodb-native driver.

    \n\n

    NOTE: passed options take precedence over connection string options.

    ", - "summary": "

    Prepares default connection options for the node-mongodb-native driver.

    ", - "body": "

    NOTE: passed options take precedence over connection string options.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {\n var o = passed || {};\n o.db || (o.db = {});\n o.auth || (o.auth = {});\n o.server || (o.server = {});\n o.replset || (o.replset = {});\n o.server.socketOptions || (o.server.socketOptions = {});\n o.replset.socketOptions || (o.replset.socketOptions = {});\n\n var opts = connStrOpts || {};\n Object.keys(opts).forEach(function (name) {\n switch (name) {\n case 'poolSize':\n if ('undefined' == typeof o.server.poolSize) {\n o.server.poolSize = o.replset.poolSize = opts[name];\n }\n break;\n case 'slaveOk':\n if ('undefined' == typeof o.server.slave_ok) {\n o.server.slave_ok = opts[name];\n }\n break;\n case 'autoReconnect':\n if ('undefined' == typeof o.server.auto_reconnect) {\n o.server.auto_reconnect = opts[name];\n }\n break;\n case 'ssl':\n case 'socketTimeoutMS':\n case 'connectTimeoutMS':\n if ('undefined' == typeof o.server.socketOptions[name]) {\n o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];\n }\n break;\n case 'authdb':\n if ('undefined' == typeof o.auth.authdb) {\n o.auth.authdb = opts[name];\n }\n break;\n case 'authSource':\n if ('undefined' == typeof o.auth.authSource) {\n o.auth.authSource = opts[name];\n }\n break;\n case 'retries':\n case 'reconnectWait':\n case 'rs_name':\n if ('undefined' == typeof o.replset[name]) {\n o.replset[name] = opts[name];\n }\n break;\n case 'replicaSet':\n if ('undefined' == typeof o.replset.rs_name) {\n o.replset.rs_name = opts[name];\n }\n break;\n case 'readSecondary':\n if ('undefined' == typeof o.replset.read_secondary) {\n o.replset.read_secondary = opts[name];\n }\n break;\n case 'nativeParser':\n if ('undefined' == typeof o.db.native_parser) {\n o.db.native_parser = opts[name];\n }\n break;\n case 'w':\n case 'safe':\n case 'fsync':\n case 'journal':\n case 'wtimeoutMS':\n if ('undefined' == typeof o.db[name]) {\n o.db[name] = opts[name];\n }\n break;\n case 'readPreference':\n if ('undefined' == typeof o.db.read_preference) {\n o.db.read_preference = opts[name];\n }\n break;\n case 'readPreferenceTags':\n if ('undefined' == typeof o.db.read_preference_tags) {\n o.db.read_preference_tags = opts[name];\n }\n break;\n }\n })\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n if (!o.db.read_preference) {\n // read from primaries by default\n o.db.read_preference = 'primary';\n }\n\n // mongoose creates its own ObjectIds\n o.db.forceServerObjectId = false;\n\n // default safe using new nomenclature\n if (!('journal' in o.db || 'j' in o.db ||\n 'fsync' in o.db || 'safe' in o.db || 'w' in o.db)) {\n o.db.w = 1;\n }\n\n validate(o);\n return o;\n}", - "ctx": { - "type": "method", - "constructor": "NativeConnection", - "name": "parseOptions", - "string": "NativeConnection.prototype.parseOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "o", - "description": "" - } - ], - "description": { - "full": "

    Validates the driver db options.

    ", - "summary": "

    Validates the driver db options.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function validate (o) {\n if (-1 === o.db.w || 0 === o.db.w) {\n if (o.db.journal || o.db.fsync || o.db.safe) {\n throw new Error(\n 'Invalid writeConcern: '\n + 'w set to -1 or 0 cannot be combined with safe|fsync|journal');\n }\n }\n}", - "ctx": { - "type": "function", - "name": "validate", - "string": "validate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = NativeConnection;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "NativeConnection", - "string": "module.exports" - } - } -] -### lib/drivers/node-mongodb-native/objectid.js -[ - { - "tags": [ - { - "type": "constructor", - "string": "NodeMongoDbObjectId" - }, - { - "type": "see", - "local": "ObjectId", - "visibility": "ObjectId" - } - ], - "description": { - "full": "

    node-mongodb-native ObjectId

    ", - "summary": "

    node-mongodb-native ObjectId

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require('mongodb').BSONPure.ObjectID", - "string": "ObjectId" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", - "ctx": { - "type": "declaration", - "name": "ObjectIdToString", - "value": "ObjectId.toString.bind(ObjectId)", - "string": "ObjectIdToString" - } - } -] -### lib/error.js -[ - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" - } - ], - "description": { - "full": "

    Mongoose error

    ", - "summary": "

    Mongoose error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", - "ctx": { - "type": "function", - "name": "MongooseError", - "string": "MongooseError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Error.

    ", - "summary": "

    Inherits from Error.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseError.prototype.__proto__ = Error.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseError", - "name": "__proto__", - "value": "Error.prototype", - "string": "MongooseError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = MongooseError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = MongooseError", - "string": "module.exports" - } - }, - { - "tags": [], - "description": { - "full": "

    Expose subclasses

    ", - "summary": "

    Expose subclasses

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseError.CastError = require('./errors/cast');\nMongooseError.DocumentError = require('./errors/document');\nMongooseError.ValidationError = require('./errors/validation')\nMongooseError.ValidatorError = require('./errors/validator')\nMongooseError.VersionError =require('./errors/version')\nMongooseError.OverwriteModelError = require('./errors/overwriteModel')\nMongooseError.MissingSchemaError = require('./errors/missingSchema')\nMongooseError.DivergentArrayError = require('./errors/divergentArray')", - "ctx": { - "type": "property", - "receiver": "MongooseError", - "name": "CastError", - "value": "require('./errors/cast')", - "string": "MongooseError.CastError" - } - } -] -### lib/errors/cast.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casting Error constructor.

    ", - "summary": "

    Casting Error constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function CastError (type, value, path) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\" at path \"' + path + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n this.path = path;\n};", - "ctx": { - "type": "function", - "name": "CastError", - "string": "CastError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "CastError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "CastError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "CastError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = CastError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "CastError", - "string": "module.exports" - } - } -] -### lib/errors/divergentArray.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

    DivergentArrayError constructor.

    ", - "summary": "

    DivergentArrayError constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function DivergentArrayError (paths) {\n var msg = 'For your own good, using `document.save()` to update an array '\n + 'which was selected using an $elemMatch projection OR '\n + 'populated using skip, limit, query conditions, or exclusion of '\n + 'the _id field when the operation results in a $pop or $set of '\n + 'the entire array is not supported. The following '\n + 'path(s) would have been modified unsafely:\\n'\n + ' ' + paths.join('\\n ') + '\\n'\n + 'Use Model.update() to update these arrays instead.'\n // TODO write up a docs page (FAQ) and link to it\n\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DivergentArrayError';\n};", - "ctx": { - "type": "function", - "name": "DivergentArrayError", - "string": "DivergentArrayError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "DivergentArrayError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "DivergentArrayError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "DivergentArrayError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = DivergentArrayError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "DivergentArrayError", - "string": "module.exports" - } - } -] -### lib/errors/document.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements

    ", - "summary": "

    Module requirements

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Document Error

    ", - "summary": "

    Document Error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", - "ctx": { - "type": "function", - "name": "DocumentError", - "string": "DocumentError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "DocumentError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = DocumentError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = DocumentError", - "string": "module.exports" - } - } -] -### lib/errors/missingSchema.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

    MissingSchema Error constructor.

    ", - "summary": "

    MissingSchema Error constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function MissingSchemaError (name) {\n var msg = 'Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)';\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'MissingSchemaError';\n};", - "ctx": { - "type": "function", - "name": "MissingSchemaError", - "string": "MissingSchemaError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "MissingSchemaError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "MissingSchemaError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "MissingSchemaError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = MissingSchemaError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MissingSchemaError", - "string": "module.exports" - } - } -] -### lib/errors/overwriteModel.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

    OverwriteModel Error constructor.

    ", - "summary": "

    OverwriteModel Error constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function OverwriteModelError (name) {\n MongooseError.call(this, 'Cannot overwrite `' + name + '` model once compiled.');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'OverwriteModelError';\n};", - "ctx": { - "type": "function", - "name": "OverwriteModelError", - "string": "OverwriteModelError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "OverwriteModelError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "OverwriteModelError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "OverwriteModelError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = OverwriteModelError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "OverwriteModelError", - "string": "module.exports" - } - } -] -### lib/errors/validation.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements

    ", - "summary": "

    Module requirements

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error')", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "instance", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - } - ], - "description": { - "full": "

    Document Validation Error

    ", - "summary": "

    Document Validation Error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", - "ctx": { - "type": "function", - "name": "ValidationError", - "string": "ValidationError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Console.log helper

    ", - "summary": "

    Console.log helper

    ", - "body": "" - }, - "ignore": false, - "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", - "ctx": { - "type": "method", - "constructor": "ValidationError", - "name": "toString", - "string": "ValidationError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidationError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidationError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports

    ", - "summary": "

    Module exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = ValidationError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = ValidationError", - "string": "module.exports" - } - } -] -### lib/errors/validator.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "msg", - "description": "" - }, - { - "type": "param", - "types": [ - "String", - "Number", - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Schema validator error

    ", - "summary": "

    Schema validator error

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ValidatorError (path, type, val) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n\n var message = 'Validator ' + msg + 'failed for path ' + path\n if (2 < arguments.length) message += ' with value `' + String(val) + '`';\n\n MongooseError.call(this, message);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n this.value = val;\n};", - "ctx": { - "type": "function", - "name": "ValidatorError", - "string": "ValidatorError()" - } - }, - { - "tags": [], - "description": { - "full": "

    toString helper

    ", - "summary": "

    toString helper

    ", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", - "ctx": { - "type": "method", - "constructor": "ValidatorError", - "name": "toString", - "string": "ValidatorError.prototype.toString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError

    ", - "summary": "

    Inherits from MongooseError

    ", - "body": "" - }, - "ignore": true, - "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "ValidatorError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "ValidatorError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ValidatorError", - "string": "module.exports" - } - } -] -### lib/errors/version.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseError = require('../error');", - "ctx": { - "type": "declaration", - "name": "MongooseError", - "value": "require('../error')", - "string": "MongooseError" - } - }, - { - "tags": [ - { - "type": "inherits", - "string": "MongooseError" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Version Error constructor.

    ", - "summary": "

    Version Error constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function VersionError () {\n MongooseError.call(this, 'No matching document found.');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'VersionError';\n};", - "ctx": { - "type": "function", - "name": "VersionError", - "string": "VersionError()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseError.

    ", - "summary": "

    Inherits from MongooseError.

    ", - "body": "" - }, - "ignore": true, - "code": "VersionError.prototype.__proto__ = MongooseError.prototype;", - "ctx": { - "type": "property", - "constructor": "VersionError", - "name": "__proto__", - "value": "MongooseError.prototype", - "string": "VersionError.prototype__proto__" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = VersionError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "VersionError", - "string": "module.exports" - } - } -] -### lib/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", - "summary": "

    Mongoose constructor.

    ", - "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", - "ctx": { - "type": "function", - "name": "Mongoose", - "string": "Mongoose()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", - "summary": "

    Sets mongoose options

    ", - "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "set", - "string": "Mongoose.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "method", - "string": "get" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", - "summary": "

    Gets mongoose options

    ", - "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.get = Mongoose.prototype.set;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "get", - "value": "Mongoose.prototype.set", - "string": "Mongoose.prototypeget" - } - }, - { - "tags": [], - "description": { - "full": "

    ReplSet connection string check.

    ", - "summary": "

    ReplSet connection string check.

    ", - "body": "" - }, - "ignore": true, - "code": "var rgxReplSet = /^.+,.+$/;", - "ctx": { - "type": "declaration", - "name": "rgxReplSet", - "value": "/^.+,.+$/", - "string": "rgxReplSet" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[uri]", - "description": "a mongodb:// URI" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "options to pass to the driver" - }, - { - "type": "see", - "local": "Connection#open #connection_Connection-open", - "visibility": "Connection#open" - }, - { - "type": "see", - "local": "Connection#openSet #connection_Connection-openSet", - "visibility": "Connection#openSet" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "the created Connection object" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Connection instance.

    \n\n

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    ", - "summary": "

    Creates a Connection instance.

    ", - "body": "

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "createConnection", - "string": "Mongoose.prototype.createConnection()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "Mongoose#createConnection #index_Mongoose-createConnection", - "visibility": "Mongoose#createConnection" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - } - ], - "description": { - "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    \n\n

    Options passed take precedence over options included in connection strings.

    ", - "summary": "

    Opens the default mongoose connection.

    ", - "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    \n\n

    Options passed take precedence over options included in connection strings.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "connect", - "string": "Mongoose.prototype.connect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "called after all connection close." - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Disconnects all connections.

    ", - "summary": "

    Disconnects all connections.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "disconnect", - "string": "Mongoose.prototype.disconnect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "name (optional, induced from model name)" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "[skipInit]", - "description": "whether to skip initialization (defaults to false)" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String }, { collection: 'actor' });\n\n// or\n\nschema.set('collection', 'actor');\n\n// or\n\nvar collectionName = 'actor'\nvar M = mongoose.model('Actor', schema, collectionName)\n
    ", - "summary": "

    Defines a model or retrieves it.

    ", - "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String }, { collection: 'actor' });\n\n// or\n\nschema.set('collection', 'actor');\n\n// or\n\nvar collectionName = 'actor'\nvar M = mongoose.model('Actor', schema, collectionName)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n if ('string' == typeof schema) {\n collection = schema;\n schema = false;\n }\n\n if (utils.isObject(schema) && !(schema instanceof Schema)) {\n schema = new Schema(schema);\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // handle internal options from connection.model()\n var options;\n if (skipInit && utils.isObject(skipInit)) {\n options = skipInit;\n skipInit = true;\n } else {\n options = {};\n }\n\n // look up schema for the collection. this might be a\n // default schema like system.indexes stored in SchemaDefaults.\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n // cache it so we only apply plugins once\n this.modelSchemas[name] = schema;\n this._applyPlugins(schema);\n } else {\n throw new mongoose.Error.MissingSchemaError(name);\n }\n }\n\n var model;\n var sub;\n\n // connection.model() may be passing a different schema for\n // an existing model name. in this case don't read from cache.\n if (this.models[name] && false !== options.cache) {\n if (schema instanceof Schema && schema != this.models[name].schema) {\n throw new mongoose.Error.OverwriteModelError(name);\n }\n\n if (collection) {\n // subclass current model with alternate collection\n model = this.models[name];\n schema = model.prototype.schema;\n sub = model.__subclass(this.connection, schema, collection);\n // do not cache the sub model\n return sub;\n }\n\n return this.models[name];\n }\n\n // ensure a schema exists\n if (!schema) {\n schema = this.modelSchemas[name];\n if (!schema) {\n throw new mongoose.Error.MissingSchemaError(name);\n }\n }\n\n if (!collection) {\n collection = schema.get('collection') || format(name);\n }\n\n var connection = options.connection || this.connection;\n model = Model.compile(name, schema, collection, connection, this);\n\n if (!skipInit) {\n model.init();\n }\n\n if (false === options.cache) {\n return model;\n }\n\n return this.models[name] = model;\n}", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "model", - "string": "Mongoose.prototype.model()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns an array of model names created on this instance of Mongoose.

    \n\n

    Note:

    \n\n

    Does not include names of models created using connection.model().

    ", - "summary": "

    Returns an array of model names created on this instance of Mongoose.

    ", - "body": "

    Note:

    \n\n

    Does not include names of models created using connection.model().

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.modelNames = function () {\n var names = Object.keys(this.models);\n return names;\n}", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "modelNames", - "string": "Mongoose.prototype.modelNames()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies global plugins to schema.

    ", - "summary": "

    Applies global plugins to schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mongoose.prototype._applyPlugins = function (schema) {\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n}", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "_applyPlugins", - "string": "Mongoose.prototype._applyPlugins()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "plugin callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "optional options" - }, - { - "type": "return", - "types": [ - "Mongoose" - ], - "description": "this" - }, - { - "type": "see", - "local": "plugins ./plugins.html", - "visibility": "plugins" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", - "summary": "

    Declares a global plugin executed on all Schemas.

    ", - "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Mongoose", - "name": "plugin", - "string": "Mongoose.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "connection" - }, - { - "type": "return", - "types": [ - "Connection" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", - "summary": "

    The default connection of the mongoose module.

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" - }, - { - "tags": [], - "description": { - "full": "

    Driver depentend APIs

    ", - "summary": "

    Driver depentend APIs

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

    Connection

    ", - "summary": "

    Connection

    ", - "body": "" - }, - "ignore": true, - "code": "var Connection = require(driver + '/connection');", - "ctx": { - "type": "declaration", - "name": "Connection", - "value": "require(driver + '/connection')", - "string": "Connection" - } - }, - { - "tags": [], - "description": { - "full": "

    Collection

    ", - "summary": "

    Collection

    ", - "body": "" - }, - "ignore": true, - "code": "var Collection = require(driver + '/collection');", - "ctx": { - "type": "declaration", - "name": "Collection", - "value": "require(driver + '/collection')", - "string": "Collection" - } - }, - { - "tags": [ - { - "type": "method", - "string": "Collection" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Collection constructor

    ", - "summary": "

    The Mongoose Collection constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Collection = Collection;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Collection", - "value": "Collection", - "string": "Mongoose.prototypeCollection" - } - }, - { - "tags": [ - { - "type": "method", - "string": "Connection" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Connection constructor

    ", - "summary": "

    The Mongoose Connection constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Connection = Connection;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Connection", - "value": "Connection", - "string": "Mongoose.prototypeConnection" - } - }, - { - "tags": [ - { - "type": "property", - "string": "version" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose version

    ", - "summary": "

    The Mongoose version

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.version = require(__dirname + '/../package.json').version;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "version", - "value": "require(__dirname + '/../package.json').version", - "string": "Mongoose.prototypeversion" - } - }, - { - "tags": [ - { - "type": "method", - "string": "Mongoose" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", - "summary": "

    The Mongoose constructor

    ", - "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Mongoose = Mongoose;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Mongoose", - "value": "Mongoose", - "string": "Mongoose.prototypeMongoose" - } - }, - { - "tags": [ - { - "type": "method", - "string": "Schema" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", - "summary": "

    The Mongoose Schema constructor

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Schema = Schema;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Schema", - "value": "Schema", - "string": "Mongoose.prototypeSchema" - } - }, - { - "tags": [ - { - "type": "method", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose SchemaType constructor.

    ", - "summary": "

    The Mongoose SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.SchemaType = SchemaType;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "SchemaType", - "value": "SchemaType", - "string": "Mongoose.prototypeSchemaType" - } - }, - { - "tags": [ - { - "type": "property", - "string": "SchemaTypes" - }, - { - "type": "see", - "local": "Schema.SchemaTypes #schema_Schema.Types", - "visibility": "Schema.SchemaTypes" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", - "summary": "

    The various Mongoose SchemaTypes.

    ", - "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.SchemaTypes = Schema.Types;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "SchemaTypes", - "value": "Schema.Types", - "string": "Mongoose.prototypeSchemaTypes" - } - }, - { - "tags": [ - { - "type": "method", - "string": "VirtualType" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose VirtualType constructor.

    ", - "summary": "

    The Mongoose VirtualType constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.VirtualType = VirtualType;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "VirtualType", - "value": "VirtualType", - "string": "Mongoose.prototypeVirtualType" - } - }, - { - "tags": [ - { - "type": "property", - "string": "Types" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", - "summary": "

    The various Mongoose Types.

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Types = Types;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Types", - "value": "Types", - "string": "Mongoose.prototypeTypes" - } - }, - { - "tags": [ - { - "type": "method", - "string": "Query" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Query constructor.

    ", - "summary": "

    The Mongoose Query constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Query = Query;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Query", - "value": "Query", - "string": "Mongoose.prototypeQuery" - } - }, - { - "tags": [ - { - "type": "method", - "string": "Promise" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Promise constructor.

    ", - "summary": "

    The Mongoose Promise constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Promise = Promise;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Promise", - "value": "Promise", - "string": "Mongoose.prototypePromise" - } - }, - { - "tags": [ - { - "type": "method", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Model constructor.

    ", - "summary": "

    The Mongoose Model constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Model = Model;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Model", - "value": "Model", - "string": "Mongoose.prototypeModel" - } - }, - { - "tags": [ - { - "type": "method", - "string": "Document" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The Mongoose Document constructor.

    ", - "summary": "

    The Mongoose Document constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Document = Document;", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Document", - "value": "Document", - "string": "Mongoose.prototypeDocument" - } - }, - { - "tags": [ - { - "type": "method", - "string": "Error" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The MongooseError constructor.

    ", - "summary": "

    The MongooseError constructor.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.Error = require('./error');", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "Error", - "value": "require('./error')", - "string": "Mongoose.prototypeError" - } - }, - { - "tags": [ - { - "type": "property", - "string": "mongo" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The node-mongodb-native driver Mongoose uses.

    ", - "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Mongoose.prototype.mongo = require('mongodb');", - "ctx": { - "type": "property", - "constructor": "Mongoose", - "name": "mongo", - "value": "require('mongodb')", - "string": "Mongoose.prototypemongo" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The exports object is an instance of Mongoose.

    ", - "summary": "

    The exports object is an instance of Mongoose.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "var mongoose = module.exports = exports = new Mongoose;", - "ctx": { - "type": "declaration", - "name": "mongoose", - "value": "module.exports = exports = new Mongoose", - "string": "mongoose" - } - } -] -### lib/internal.js -[ - { - "tags": [], - "description": { - "full": "

    Dependencies

    ", - "summary": "

    Dependencies

    ", - "body": "" - }, - "ignore": false, - "code": "var StateMachine = require('./statemachine')\nvar ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n\nmodule.exports = exports = InternalCache;\n\nfunction InternalCache () {\n this.strictMode = undefined;\n this.selected = undefined;\n this.shardval = undefined;\n this.saveError = undefined;\n this.validationError = undefined;\n this.adhocPaths = undefined;\n this.removing = undefined;\n this.inserting = undefined;\n this.version = undefined;\n this.getters = {};\n this._id = undefined;\n this.populate = undefined;\n this.populated = undefined;\n this.scope = undefined;\n this.activePaths = new ActiveRoster;\n\n // embedded docs\n this.ownerDocument = undefined;\n this.fullPath = undefined;\n}", - "ctx": { - "type": "declaration", - "name": "StateMachine", - "value": "require('./statemachine')", - "string": "StateMachine" - } - } -] -### lib/model.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , VersionError = MongooseError.VersionError\n , DivergentArrayError = MongooseError.DivergentArrayError\n , Query = require('./query')\n , Schema = require('./schema')\n , Types = require('./schema/index')\n , utils = require('./utils')\n , hasOwnProperty = utils.object.hasOwnProperty\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = require('events').EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , assert = require('assert')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('./document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "values to with which to create the document" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "event", - "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." - }, - { - "type": "event", - "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Model constructor

    ", - "summary": "

    Model constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", - "ctx": { - "type": "function", - "name": "Model", - "string": "Model()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from Document.

    \n\n

    All Model.prototype features are available on
    top level (non-sub) documents.

    ", - "summary": "

    Inherits from Document.

    ", - "body": "

    All Model.prototype features are available on
    top level (non-sub) documents.

    " - }, - "ignore": true, - "code": "Model.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "Model", - "name": "__proto__", - "value": "Document.prototype", - "string": "Model.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "db" - } - ], - "description": { - "full": "

    Connection the model uses.

    ", - "summary": "

    Connection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.db;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "collection" - } - ], - "description": { - "full": "

    Collection the model uses.

    ", - "summary": "

    Collection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.collection;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "property", - "string": "modelName" - } - ], - "description": { - "full": "

    The name of the model

    ", - "summary": "

    The name of the model

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.modelName;" - }, - { - "tags": [], - "description": { - "full": "

    Handles doc.save() callbacks

    ", - "summary": "

    Handles doc.save() callbacks

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self.$__.inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self.$__storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.$__.version && !self.$__.inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.$__.version);\n self.$__.version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new VersionError);\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", - "ctx": { - "type": "function", - "name": "handleSave", - "string": "handleSave()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "title": "middleware", - "url": "http://mongoosejs.com/docs/middleware.html", - "visibility": "http://mongoosejs.com/docs/middleware.html" - } - ], - "description": { - "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", - "summary": "

    Saves this document.

    ", - "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this.$__version(true, obj);\n this.collection.insert(obj, options, complete);\n this.$__reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this.$__.inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this.$__.inserting = false;\n\n var delta = this.$__delta();\n if (delta) {\n if (delta instanceof Error) return complete(delta);\n var where = this.$__where(delta[0]);\n this.$__reset();\n this.collection.update(where, delta[1], options, complete);\n } else {\n this.$__reset();\n complete(null);\n }\n\n this.emit('isNew', false);\n }\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "save", - "string": "Model.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Mixed" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[operation]", - "description": "" - } - ], - "description": { - "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", - "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.$__.version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.$__.version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.$__.version = VERSION_WHERE;\n }\n}", - "ctx": { - "type": "function", - "name": "operand", - "string": "operand()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "where", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "delta", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "data", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "value", - "description": "" - } - ], - "description": { - "full": "

    Compiles an update and where clause for a val with _atomics.

    ", - "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function handleAtomics (self, where, delta, data, value) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n if ('function' == typeof value.$__getAtomics) {\n value.$__getAtomics().forEach(function (atomic) {\n var op = atomic[0];\n var val = atomic[1];\n operand(self, where, delta, data, val, op);\n })\n return;\n }\n\n // legacy support for plugins\n\n var atomics = value._atomics\n , ops = Object.keys(atomics)\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(value)) {\n value = value.toObject({ depopulate: 1 });\n } else if (value.valueOf) {\n value = value.valueOf();\n }\n\n return operand(self, where, delta, data, value);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", - "ctx": { - "type": "function", - "name": "handleAtomics", - "string": "handleAtomics()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__delta" - }, - { - "type": "memberOf", - "parent": "Model" - } - ], - "description": { - "full": "

    Produces a special query document of the modified properties used in updates.

    ", - "summary": "

    Produces a special query document of the modified properties used in updates.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype.$__delta = function () {\n var dirty = this.$__dirty();\n if (!dirty.length) return;\n\n var where = {}\n , delta = {}\n , len = dirty.length\n , divergent = []\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n var match = checkDivergentArray(this, data.path, value);\n if (match) {\n divergent.push(match);\n continue;\n }\n\n if (divergent.length) continue;\n\n if (undefined === value) {\n operand(this, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(this, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n // arrays and other custom types (support plugins etc)\n handleAtomics(this, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(this, where, delta, data, value);\n\n } else {\n value = utils.clone(value, { convertToId: 1 });\n operand(this, where, delta, data, value);\n }\n }\n\n if (divergent.length) {\n return new DivergentArrayError(divergent);\n }\n\n if (this.$__.version) {\n this.$__version(where, delta);\n }\n\n return [where, delta];\n}" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "https://github.com/LearnBoost/mongoose/issues/1334", - "visibility": "https://github.com/LearnBoost/mongoose/issues/1334" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "String", - "undefined" - ], - "description": "" - } - ], - "description": { - "full": "

    Determine if array was populated with some form of filter and is now
    being updated in a manner which could overwrite data unintentionally.

    ", - "summary": "

    Determine if array was populated with some form of filter and is now
    being updated in a manner which could overwrite data unintentionally.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function checkDivergentArray (doc, path, array) {\n // see if we populated this path\n var pop = doc.populated(path, true);\n\n if (!pop && doc.$__.selected) {\n // If any array was selected using an $elemMatch projection, we deny the update.\n // NOTE: MongoDB only supports projected $elemMatch on top level array.\n var top = path.split('.')[0];\n if (doc.$__.selected[top] && doc.$__.selected[top].$elemMatch) {\n return top;\n }\n }\n\n if (!(pop && array instanceof MongooseArray)) return;\n\n // If the array was populated using options that prevented all\n // documents from being returned (match, skip, limit) or they\n // deselected the _id field, $pop and $set of the array are\n // not safe operations. If _id was deselected, we do not know\n // how to remove elements. $pop will pop off the _id from the end\n // of the array in the db which is not guaranteed to be the\n // same as the last element we have here. $set of the entire array\n // would be similarily destructive as we never received all\n // elements of the array and potentially would overwrite data.\n var check = pop.options.match ||\n pop.options.options && hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted\n pop.options.options && pop.options.options.skip || // 0 is permitted\n pop.options.select && // deselected _id?\n (0 === pop.options.select._id ||\n /\\s?-_id\\s?/.test(pop.options.select))\n\n if (check) {\n var atomics = array._atomics;\n if (0 === Object.keys(atomics).length || atomics.$set || atomics.$pop) {\n return path;\n }\n }\n}", - "ctx": { - "type": "function", - "name": "checkDivergentArray", - "string": "checkDivergentArray()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__version" - }, - { - "type": "memberOf", - "parent": "Model" - } - ], - "description": { - "full": "

    Appends versioning to the where and update clauses.

    ", - "summary": "

    Appends versioning to the where and update clauses.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype.$__version = function (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.$__.version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.$__.version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}" - }, - { - "tags": [ - { - "type": "see", - "title": "versionKeys", - "url": "http://mongoosejs.com/docs/guide.html#versionKey", - "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Signal that we desire an increment of this documents version.

    ", - "summary": "

    Signal that we desire an increment of this documents version.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.increment = function increment () {\n this.$__.version = VERSION_ALL;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "increment", - "string": "Model.prototype.increment()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__where" - }, - { - "type": "memberOf", - "parent": "Model" - } - ], - "description": { - "full": "

    Returns a query object which applies shardkeys if they exist.

    ", - "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.prototype.$__where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this.$__.shardval) {\n paths = Object.keys(this.$__.shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this.$__.shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", - "summary": "

    Removes this document from the db.

    ", - "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.remove = function remove (fn) {\n if (this.$__.removing) {\n this.$__.removing.addBack(fn);\n return this;\n }\n\n var promise = this.$__.removing = new Promise(fn)\n , where = this.$__where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self.$__.removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "remove", - "string": "Model.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", - "summary": "

    Returns another Model instance.

    ", - "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};\n\n// Model (class) features", - "ctx": { - "type": "method", - "constructor": "Model", - "name": "model", - "string": "Model.prototype.model()" - } - }, - { - "tags": [], - "description": { - "full": "

    Give the constructor the ability to emit events.

    ", - "summary": "

    Give the constructor the ability to emit events.

    ", - "body": "" - }, - "ignore": true, - "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Called when the model compiles.

    ", - "summary": "

    Called when the model compiles.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model.init = function init () {\n if (this.schema.options.autoIndex) {\n this.ensureIndexes();\n }\n\n this.schema.emit('init', this);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "init", - "string": "Model.init()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[cb]", - "description": "optional callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    Example:

    \n\n
    var eventSchema = new Schema({ thing: { type: 'string', unique: true }})\nvar Event = mongoose.model('Event', eventSchema);\n\nEvent.on('index', function (err) {\n  if (err) console.error(err); // error occurred during index creation\n})\n
    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    The ensureIndex commands are not sent in parallel. This is to avoid the MongoError: cannot add index with a background operation in progress error. See this ticket for more information.

    ", - "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", - "body": "

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    Example:

    \n\n
    var eventSchema = new Schema({ thing: { type: 'string', unique: true }})\nvar Event = mongoose.model('Event', eventSchema);\n\nEvent.on('index', function (err) {\n  if (err) console.error(err); // error occurred during index creation\n})\n
    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    The ensureIndex commands are not sent in parallel. This is to avoid the MongoError: cannot add index with a background operation in progress error. See this ticket for more information.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && process.nextTick(cb);\n }\n\n // Indexes are created one-by-one to support how MongoDB < 2.4 deals\n // with background indexes.\n\n var self = this\n , safe = self.schema.options.safe\n\n function done (err) {\n self.emit('index', err);\n cb && cb(err);\n }\n\n function create () {\n var index = indexes.shift();\n if (!index) return done();\n\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) return done(err);\n create();\n }));\n }\n\n create();\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "ensureIndexes", - "string": "Model.ensureIndexes()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "schema" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Schema the model uses.

    ", - "summary": "

    Schema the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.schema;" - }, - { - "tags": [ - { - "type": "property", - "string": "db" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Connection instance the model uses.

    ", - "summary": "

    Connection instance the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.db;" - }, - { - "tags": [ - { - "type": "property", - "string": "collection" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Collection the model uses.

    ", - "summary": "

    Collection the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.collection;" - }, - { - "tags": [ - { - "type": "property", - "string": "base" - }, - { - "type": "receiver", - "string": "Model" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Base Mongoose instance the model uses.

    ", - "summary": "

    Base Mongoose instance the model uses.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.base;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes documents from the collection.

    \n\n

    Example:

    \n\n
    Comment.remove({ title: 'baby born from alien father' }, function (err) {\n\n});\n
    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    var query = Comment.remove({ _id: id });\nquery.exec();\n
    \n\n

    Note:

    \n\n

    This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, no middleware (hooks) are executed.

    ", - "summary": "

    Removes documents from the collection.

    ", - "body": "

    Example:

    \n\n
    Comment.remove({ title: 'baby born from alien father' }, function (err) {\n\n});\n
    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    var query = Comment.remove({ _id: id });\nquery.exec();\n
    \n\n

    Note:

    \n\n

    This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, no middleware (hooks) are executed.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "remove", - "string": "Model.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "see", - "local": "promise #promise-js", - "visibility": "promise" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds documents

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Examples:

    \n\n
    // named john and at least 18\nMyModel.find({ name: 'john', age: { $gte: 18 }});\n\n// executes immediately, passing results to callback\nMyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});\n\n// name LIKE john and only selecting the \"name\" and \"friends\" fields, executing immediately\nMyModel.find({ name: /john/i }, 'name friends', function (err, docs) { })\n\n// passing options\nMyModel.find({ name: /john/i }, null, { skip: 10 })\n\n// passing options and executing immediately\nMyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {});\n\n// executing a query explicitly\nvar query = MyModel.find({ name: /john/i }, null, { skip: 10 })\nquery.exec(function (err, docs) {});\n\n// using the promise returned from executing a query\nvar query = MyModel.find({ name: /john/i }, null, { skip: 10 });\nvar promise = query.exec();\npromise.addBack(function (err, docs) {});\n
    ", - "summary": "

    Finds documents

    ", - "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Examples:

    \n\n
    // named john and at least 18\nMyModel.find({ name: 'john', age: { $gte: 18 }});\n\n// executes immediately, passing results to callback\nMyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});\n\n// name LIKE john and only selecting the \"name\" and \"friends\" fields, executing immediately\nMyModel.find({ name: /john/i }, 'name friends', function (err, docs) { })\n\n// passing options\nMyModel.find({ name: /john/i }, null, { skip: 10 })\n\n// passing options and executing immediately\nMyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {});\n\n// executing a query explicitly\nvar query = MyModel.find({ name: /john/i }, null, { skip: 10 })\nquery.exec(function (err, docs) {});\n\n// using the promise returned from executing a query\nvar query = MyModel.find({ name: /john/i }, null, { skip: 10 });\nvar promise = query.exec();\npromise.addBack(function (err, docs) {});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "find", - "string": "Model.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Merges the current named scope query into query.

    ", - "summary": "

    Merges the current named scope query into query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "_applyNamedScope", - "string": "Model._applyNamedScope()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "objectid, or a value that can be casted to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "see", - "local": "lean queries #query_Query-lean", - "visibility": "lean" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds a single document by id.

    \n\n

    The id is cast based on the Schema before sending the command.

    \n\n

    Example:

    \n\n
    // find adventure by id and execute immediately\nAdventure.findById(id, function (err, adventure) {});\n\n// same as above\nAdventure.findById(id).exec(callback);\n\n// select only the adventures name and length\nAdventure.findById(id, 'name length', function (err, adventure) {});\n\n// same as above\nAdventure.findById(id, 'name length').exec(callback);\n\n// include all properties except for `length`\nAdventure.findById(id, '-length').exec(function (err, adventure) {});\n\n// passing options (in this case return the raw js objects, not mongoose documents by passing `lean`\nAdventure.findById(id, 'name', { lean: true }, function (err, doc) {});\n\n// same as above\nAdventure.findById(id, 'name').lean().exec(function (err, doc) {});\n
    ", - "summary": "

    Finds a single document by id.

    ", - "body": "

    The id is cast based on the Schema before sending the command.

    \n\n

    Example:

    \n\n
    // find adventure by id and execute immediately\nAdventure.findById(id, function (err, adventure) {});\n\n// same as above\nAdventure.findById(id).exec(callback);\n\n// select only the adventures name and length\nAdventure.findById(id, 'name length', function (err, adventure) {});\n\n// same as above\nAdventure.findById(id, 'name length').exec(callback);\n\n// include all properties except for `length`\nAdventure.findById(id, '-length').exec(function (err, adventure) {});\n\n// passing options (in this case return the raw js objects, not mongoose documents by passing `lean`\nAdventure.findById(id, 'name', { lean: true }, function (err, doc) {});\n\n// same as above\nAdventure.findById(id, 'name').lean().exec(function (err, doc) {});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findById", - "string": "Model.findById()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[fields]", - "description": "optional fields to select" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "field selection #query_Query-select", - "visibility": "field" - }, - { - "type": "see", - "local": "lean queries #query_Query-lean", - "visibility": "lean" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    // find one iphone adventures - iphone adventures??\nAdventure.findOne({ type: 'iphone' }, function (err, adventure) {});\n\n// same as above\nAdventure.findOne({ type: 'iphone' }).exec(function (err, adventure) {});\n\n// select only the adventures name\nAdventure.findOne({ type: 'iphone' }, 'name', function (err, adventure) {});\n\n// same as above\nAdventure.findOne({ type: 'iphone' }, 'name').exec(function (err, adventure) {});\n\n// specify options, in this case lean\nAdventure.findOne({ type: 'iphone' }, 'name', { lean: true }, callback);\n\n// same as above\nAdventure.findOne({ type: 'iphone' }, 'name', { lean: true }).exec(callback);\n\n// chaining findOne queries (same as above)\nAdventure.findOne({ type: 'iphone' }).select('name').lean().exec(callback);\n
    ", - "summary": "

    Finds one document.

    ", - "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    // find one iphone adventures - iphone adventures??\nAdventure.findOne({ type: 'iphone' }, function (err, adventure) {});\n\n// same as above\nAdventure.findOne({ type: 'iphone' }).exec(function (err, adventure) {});\n\n// select only the adventures name\nAdventure.findOne({ type: 'iphone' }, 'name', function (err, adventure) {});\n\n// same as above\nAdventure.findOne({ type: 'iphone' }, 'name').exec(function (err, adventure) {});\n\n// specify options, in this case lean\nAdventure.findOne({ type: 'iphone' }, 'name', { lean: true }, callback);\n\n// same as above\nAdventure.findOne({ type: 'iphone' }, 'name', { lean: true }).exec(callback);\n\n// chaining findOne queries (same as above)\nAdventure.findOne({ type: 'iphone' }).select('name').lean().exec(callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOne", - "string": "Model.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", - "summary": "

    Counts number of matching documents in a database collection.

    ", - "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "count", - "string": "Model.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "optional" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes a DISTINCT command

    ", - "summary": "

    Executes a DISTINCT command

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "distinct", - "string": "Model.distinct()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "optional value" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", - "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", - "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "where", - "string": "Model.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "argument", - "description": "is a javascript string or anonymous function" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "memberOf", - "parent": "Model" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Query.$where #query_Query-%24where", - "visibility": "Query.$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5').exec(function (err, docs) {});\n
    ", - "summary": "

    Creates a Query and specifies a $where condition.

    ", - "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5').exec(function (err, docs) {});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Issues a mongodb findAndModify update command.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndUpdate", - "string": "Model.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexId" - ], - "name": "id", - "description": "an ObjectId or string that can be cast to one." - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[update]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndUpdate #model_Model.findOneAndUpdate", - "visibility": "Model.findOneAndUpdate" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndUpdate", - "string": "Model.findByIdAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", - "summary": "

    Issue a mongodb findAndModify remove command.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findOneAndRemove", - "string": "Model.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "id", - "description": "ObjectId or string that can be cast to one" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "see", - "local": "Model.findOneAndRemove #model_Model.findOneAndRemove", - "visibility": "Model.findOneAndRemove" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - } - ], - "description": { - "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", - "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "findByIdAndRemove", - "string": "Model.findByIdAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array", - "Object..." - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", - "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", - "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "create", - "string": "Model.create()" - } - }, - { - "tags": [ - { - "type": "see", - "title": "strict", - "url": "schemas http://mongoosejs.com/docs/guide.html#strict", - "visibility": "schemas" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "conditions", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "update", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    • strict (boolean) overrides the strict option for this update
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", - "summary": "

    Updates documents in the database without returning them.

    ", - "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    • strict (boolean) overrides the strict option for this update
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "update", - "string": "Model.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "o", - "description": "an object specifying map-reduce options" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/MapReduce", - "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", - "summary": "

    Executes a mapReduce command.

    ", - "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "mapReduce", - "string": "Model.mapReduce()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "an array of pipeline commands" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "aggregation", - "url": "http://docs.mongodb.org/manual/applications/aggregation/", - "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", - "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes an aggregate command on this models collection.

    \n\n

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    ", - "summary": "

    Executes an aggregate command on this models collection.

    ", - "body": "

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "aggregate", - "string": "Model.aggregate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Document", - "Array" - ], - "name": "docs", - "description": "Either a single document or array of documents to populate." - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "A hash of key/val (path, options) used for population." - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "cb(err,doc)", - "description": "A callback, executed upon completion. Receives `err` and the `doc(s)`." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Populates document references.

    \n\n

    Available options:

    \n\n
      \n
    • path: space delimited path(s) to populate
    • \n
    • select: optional fields to select
    • \n
    • match: optional query conditions to match
    • \n
    • model: optional name of the model to use for population
    • \n
    • options: optional query options like sort, limit, etc
    • \n
    \n\n

    Examples:

    \n\n
    // populates a single object\nUser.findById(id, function (err, user) {\n  var opts = [\n      { path: 'company', match: { x: 1 }, select: 'name' }\n    , { path: 'notes', options: {}, model: 'override' }\n  ]\n\n  User.populate(user, opts, function (err, user) {\n    console.log(user);\n  })\n})\n\n// populates an array of objects\nUser.find(match, function (err, users) {\n  var opts = [{ path: 'company', match: { x: 1 }, select: 'name' }]\n\n  User.populate(users, opts, function (err, user) {\n    console.log(user);\n  })\n})\n\n// imagine a Weapon model exists with two saved documents:\n//   { _id: 389, name: 'whip' }\n//   { _id: 8921, name: 'boomerang' }\n\nvar user = { name: 'Indiana Jones', weapon: 389 }\nWeapon.populate(user, { path: 'weapon', model: 'Weapon' }, function (err, user) {\n  console.log(user.weapon.name) // whip\n})\n\n// populate many plain objects\nvar users = [{ name: 'Indiana Jones', weapon: 389 }]\nusers.push({ name: 'Batman', weapon: 8921 })\nWeapon.populate(users, { path: 'weapon' }, function (err, users) {\n  users.forEach(function (user) {\n    console.log('%s uses a %s', users.name, user.weapon.name)\n    // Indiana Jones uses a whip\n    // Batman uses a boomerang\n  })\n})\n// Note that we didn't need to specify the Weapon model because\n// we were already using it's populate() method.\n
    ", - "summary": "

    Populates document references.

    ", - "body": "

    Available options:

    \n\n
      \n
    • path: space delimited path(s) to populate
    • \n
    • select: optional fields to select
    • \n
    • match: optional query conditions to match
    • \n
    • model: optional name of the model to use for population
    • \n
    • options: optional query options like sort, limit, etc
    • \n
    \n\n

    Examples:

    \n\n
    // populates a single object\nUser.findById(id, function (err, user) {\n  var opts = [\n      { path: 'company', match: { x: 1 }, select: 'name' }\n    , { path: 'notes', options: {}, model: 'override' }\n  ]\n\n  User.populate(user, opts, function (err, user) {\n    console.log(user);\n  })\n})\n\n// populates an array of objects\nUser.find(match, function (err, users) {\n  var opts = [{ path: 'company', match: { x: 1 }, select: 'name' }]\n\n  User.populate(users, opts, function (err, user) {\n    console.log(user);\n  })\n})\n\n// imagine a Weapon model exists with two saved documents:\n//   { _id: 389, name: 'whip' }\n//   { _id: 8921, name: 'boomerang' }\n\nvar user = { name: 'Indiana Jones', weapon: 389 }\nWeapon.populate(user, { path: 'weapon', model: 'Weapon' }, function (err, user) {\n  console.log(user.weapon.name) // whip\n})\n\n// populate many plain objects\nvar users = [{ name: 'Indiana Jones', weapon: 389 }]\nusers.push({ name: 'Batman', weapon: 8921 })\nWeapon.populate(users, { path: 'weapon' }, function (err, users) {\n  users.forEach(function (user) {\n    console.log('%s uses a %s', users.name, user.weapon.name)\n    // Indiana Jones uses a whip\n    // Batman uses a boomerang\n  })\n})\n// Note that we didn't need to specify the Weapon model because\n// we were already using it's populate() method.\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Model.populate = function (docs, paths, cb) {\n assert.equal('function', typeof cb);\n\n // always callback on nextTick for consistent async behavior\n function callback () {\n var args = utils.args(arguments);\n process.nextTick(function () {\n cb.apply(null, args);\n });\n }\n\n // normalized paths\n var paths = utils.populate(paths);\n var pending = paths.length;\n\n if (0 === pending) {\n return callback(null, docs);\n }\n\n // each path has its own query options and must be executed separately\n var i = pending;\n var path;\n while (i--) {\n path = paths[i];\n populate(this, docs, path, next);\n }\n\n function next (err) {\n if (next.err) return;\n if (err) return callback(next.err = err);\n if (--pending) return;\n callback(null, docs);\n }\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "populate", - "string": "Model.populate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Populates docs

    ", - "summary": "

    Populates docs

    ", - "body": "" - }, - "ignore": true, - "code": "function populate (model, docs, options, cb) {\n var select = options.select\n , match = options.match\n , path = options.path\n\n var schema = model._getSchema(path);\n var subpath;\n\n // handle document arrays\n if (schema && schema.caster) {\n schema = schema.caster;\n }\n\n // model name for the populate query\n var modelName = options.model // overridden in query options\n || schema && schema.options.ref // declared in schema\n || model.modelName // an ad-hoc structure\n\n var Model = model.db.model(modelName);\n\n // expose the model used\n options.model = Model;\n\n // normalize single / multiple docs passed\n if (!Array.isArray(docs)) {\n docs = [docs];\n }\n\n if (0 === docs.length || docs.every(utils.isNullOrUndefined)) {\n return cb();\n }\n\n // get all ids for all docs for a given path\n var rawIds = docs.map(function (doc) {\n if (!doc) return doc;\n\n var isDocument = !! doc.$__;\n var ret;\n\n if (isDocument && !doc.isModified(path)) {\n // it is possible a previously populated path is being\n // populated again. because users can specify matcher\n // clauses in their populate arguments we use the cached\n // _ids from the original populate call to ensure all _ids\n // are looked up, but only if the path wasn't modified which\n // signifies the users intent of the state of the path.\n ret = doc.populated(path);\n }\n\n if (!ret || Array.isArray(ret) && 0 === ret.length) {\n ret = utils.getValue(path, doc);\n }\n\n options._docs[doc._id] = Array.isArray(ret)\n ? ret.slice()\n : ret;\n\n if (isDocument) {\n // cache original populated _ids and model used\n doc.populated(path, options._docs[doc._id], options);\n }\n\n return ret;\n });\n\n var ids = utils.array.flatten(rawIds, function (item) {\n // no need to include undefined values in our query\n return undefined !== item;\n });\n\n if (0 === ids.length || ids.every(utils.isNullOrUndefined)) {\n return cb();\n }\n\n // preserve original match conditions by copying\n if (match) {\n match = utils.object.shallowCopy(match);\n } else {\n match = {};\n }\n\n match._id || (match._id = { $in: ids });\n\n var assignmentOpts = {};\n assignmentOpts.sort = options.options && options.options.sort || undefined;\n assignmentOpts.excludeId = /\\s?-_id\\s?/.test(select) || (select && 0 === select._id);\n\n if (assignmentOpts.excludeId) {\n // override the exclusion from the query so we can use the _id\n // for document matching during assignment. we'll delete the\n // _id back off before returning the result.\n if ('string' == typeof select) {\n select = null;\n } else {\n // preserve original select conditions by copying\n select = utils.object.shallowCopy(select);\n delete select._id;\n }\n }\n\n Model.find(match, select, options.options, function (err, vals) {\n if (err) return cb(err);\n\n assignVals({\n rawIds: rawIds\n , rawDocs: vals\n , docs: docs\n , path: path\n , options: assignmentOpts\n })\n\n cb();\n });\n}", - "ctx": { - "type": "function", - "name": "populate", - "string": "populate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Assigns documents returned from a population query back
    to the original document path.

    ", - "summary": "

    Assigns documents returned from a population query back
    to the original document path.

    ", - "body": "" - }, - "ignore": true, - "code": "function assignVals (opts) {\n var rawIds = opts.rawIds;\n var rawDocs = opts.rawDocs;\n var docs = opts.docs;\n var path = opts.path;\n var options = opts.options;\n\n assignRawDocsToIdStructure(rawIds, rawDocs, options);\n\n for (var i = 0; i < docs.length; ++i) {\n utils.setValue(path, rawIds[i], docs[i], function (val) {\n return valueFilter(val, options);\n });\n }\n}", - "ctx": { - "type": "function", - "name": "assignVals", - "string": "assignVals()" - } - }, - { - "tags": [], - "description": { - "full": "

    1) Apply backwards compatible find/findOne behavior to sub documents

    \n\n

    find logic:
    a) filter out non-documents
    b) remove _id from sub docs when user specified

    \n\n

    findOne
    a) if no doc found, set to null
    b) remove _id from sub docs when user specified

    \n\n

    2) Remove _ids when specified by users query.

    \n\n

    background:
    _ids are left in the query even when user excludes them so
    that population mapping can occur.

    ", - "summary": "

    1) Apply backwards compatible find/findOne behavior to sub documents

    ", - "body": "

    find logic:
    a) filter out non-documents
    b) remove _id from sub docs when user specified

    \n\n

    findOne
    a) if no doc found, set to null
    b) remove _id from sub docs when user specified

    \n\n

    2) Remove _ids when specified by users query.

    \n\n

    background:
    _ids are left in the query even when user excludes them so
    that population mapping can occur.

    " - }, - "ignore": true, - "code": "function valueFilter (val, assignmentOpts) {\n if (Array.isArray(val)) {\n // find logic\n var ret = [];\n for (var i = 0; i < val.length; ++i) {\n var subdoc = val[i];\n if (!isDoc(subdoc)) continue;\n maybeRemoveId(subdoc, assignmentOpts);\n ret.push(subdoc);\n }\n return ret;\n }\n\n // findOne\n if (isDoc(val)) {\n maybeRemoveId(val, assignmentOpts);\n return val;\n }\n return null;\n}", - "ctx": { - "type": "function", - "name": "valueFilter", - "string": "valueFilter()" - } - }, - { - "tags": [], - "description": { - "full": "

    Remove _id from subdoc if user specified \"lean\" query option

    ", - "summary": "

    Remove _id from subdoc if user specified \"lean\" query option

    ", - "body": "" - }, - "ignore": true, - "code": "function maybeRemoveId (subdoc, assignmentOpts) {\n if (assignmentOpts.excludeId) {\n if ('function' == typeof subdoc.setValue) {\n subdoc.setValue('_id', undefined);\n } else {\n delete subdoc._id;\n }\n }\n}", - "ctx": { - "type": "function", - "name": "maybeRemoveId", - "string": "maybeRemoveId()" - } - }, - { - "tags": [], - "description": { - "full": "

    Determine if doc is a document returned
    by a populate query.

    ", - "summary": "

    Determine if doc is a document returned
    by a populate query.

    ", - "body": "" - }, - "ignore": true, - "code": "function isDoc (doc) {\n if (null == doc)\n return false;\n\n var type = typeof doc;\n if ('string' == type)\n return false;\n\n if ('number' == type)\n return false;\n\n if (Buffer.isBuffer(doc))\n return false;\n\n if ('ObjectID' == doc.constructor.name)\n return false;\n\n // only docs\n return true;\n}", - "ctx": { - "type": "function", - "name": "isDoc", - "string": "isDoc()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "rawIds", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "vals", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "sort", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Assign vals returned by mongo query to the rawIds
    structure returned from utils.getVals() honoring
    query sort order if specified by user.

    \n\n

    This can be optimized.

    \n\n

    Rules

    \n\n

    if the value of the path is not an array, use findOne rules, else find.
    for findOne the results are assigned directly to doc path (including null results).
    for find, if user specified sort order, results are assigned directly
    else documents are put back in original order of array if found in results

    ", - "summary": "

    Assign vals returned by mongo query to the rawIds
    structure returned from utils.getVals() honoring
    query sort order if specified by user.

    ", - "body": "

    This can be optimized.

    \n\n

    Rules

    \n\n

    if the value of the path is not an array, use findOne rules, else find.
    for findOne the results are assigned directly to doc path (including null results).
    for find, if user specified sort order, results are assigned directly
    else documents are put back in original order of array if found in results

    " - }, - "isPrivate": true, - "ignore": true, - "code": "function assignRawDocsToIdStructure (rawIds, vals, options, recursed) {\n // honor user specified sort order\n var newOrder = [];\n var sorting = options.sort && rawIds.length > 1;\n var found;\n var doc;\n var sid;\n var id;\n\n for (var i = 0; i < rawIds.length; ++i) {\n id = rawIds[i];\n\n if (Array.isArray(id)) {\n // handle [ [id0, id2], [id3] ]\n assignRawDocsToIdStructure(id, vals, options, true);\n newOrder.push(id);\n continue;\n }\n\n if (null === id && !sorting) {\n // keep nulls for findOne unless sorting, which always\n // removes them (backward compat)\n newOrder.push(id);\n continue;\n }\n\n sid = String(id);\n found = false;\n\n if (recursed) {\n // apply find behavior\n\n // assign matching documents in original order unless sorting\n for (var f = 0; f < vals.length; ++f) {\n if (sid == String(vals[f]._id)) {\n found = true;\n if (sorting) {\n newOrder[f] = vals[f];\n } else {\n newOrder.push(vals[f]);\n }\n break;\n }\n }\n\n if (!found) {\n newOrder.push(id);\n }\n\n } else {\n // apply findOne behavior - if document in results, assign, else assign null\n\n doc = null;\n for (var f = 0; f < vals.length; ++f) {\n if (sid == String(vals[f]._id)) {\n doc = vals[f];\n break;\n }\n }\n\n newOrder[i] = doc;\n }\n }\n\n rawIds.length = 0;\n if (newOrder.length) {\n // reassign the documents based on corrected order\n\n // forEach skips over sparse entries in arrays so we\n // can safely use this to our advantage dealing with sorted\n // result sets too.\n newOrder.forEach(function (doc, i) {\n rawIds[i] = doc;\n });\n }\n}", - "ctx": { - "type": "function", - "name": "assignRawDocsToIdStructure", - "string": "assignRawDocsToIdStructure()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "Schema" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Model._getSchema = function _getSchema (path) {\n var schema = this.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "_getSchema", - "string": "Model._getSchema()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "model name" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "collectionName", - "description": "" - }, - { - "type": "param", - "types": [ - "Connection" - ], - "name": "connection", - "description": "" - }, - { - "type": "param", - "types": [ - "Mongoose" - ], - "name": "base", - "description": "mongoose instance" - } - ], - "description": { - "full": "

    Compiler utility.

    ", - "summary": "

    Compiler utility.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n var versioningEnabled = false !== schema.options.versionKey;\n\n if (versioningEnabled && !schema.paths[schema.options.versionKey]) {\n // add versioning to top level documents only\n var o = {};\n o[schema.options.versionKey] = Number;\n schema.add(o);\n }\n\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.base = base;\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.model = Model.prototype.model;\n model.db = model.prototype.db = connection;\n\n model.prototype.$__setSchema(schema);\n\n var collectionOptions = {\n bufferCommands: schema.options.bufferCommands\n , capped: schema.options.capped\n };\n\n model.prototype.collection = connection.collection(\n collectionName\n , collectionOptions\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.schema = model.prototype.schema;\n model.options = model.prototype.options;\n model.collection = model.prototype.collection;\n\n return model;\n};", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "compile", - "string": "Model.compile()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Connection" - ], - "name": "conn", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "[schema]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[collection]", - "description": "" - }, - { - "type": "return", - "types": [ - "Model" - ], - "description": "" - } - ], - "description": { - "full": "

    Subclass this model with conn, schema, and collection settings.

    ", - "summary": "

    Subclass this model with conn, schema, and collection settings.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "Model.__subclass = function subclass (conn, schema, collection) {\n // subclass model using this connection and collection name\n var model = this;\n\n var Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model)) {\n return new Model(doc, fields, skipId);\n }\n model.call(this, doc, fields, skipId);\n }\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = conn;\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n if (!collection) {\n collection = model.prototype.schema.get('collection')\n || utils.toCollectionName(model.modelName);\n }\n\n var collectionOptions = {\n bufferCommands: s ? s.options.bufferCommands : true\n , capped: s && s.options.capped\n };\n\n Model.prototype.collection = conn.collection(collection, collectionOptions);\n Model.collection = Model.prototype.collection;\n Model.init();\n return Model;\n}", - "ctx": { - "type": "method", - "receiver": "Model", - "name": "__subclass", - "string": "Model.__subclass()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Model;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Model", - "string": "module.exports" - } - } -] -### lib/namedscope.js -[ - { - "tags": [ - { - "type": "param", - "types": [ - "NamedScope" - ], - "name": "target", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "getters", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Decorate

    ", - "summary": "

    Decorate

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", - "ctx": { - "type": "method", - "constructor": "NamedScope", - "name": "decorate", - "string": "NamedScope.prototype.decorate()" - } - } -] -### lib/promise.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies

    ", - "summary": "

    Module dependencies

    ", - "body": "" - }, - "ignore": true, - "code": "var MPromise = require('mpromise');", - "ctx": { - "type": "declaration", - "name": "MPromise", - "value": "require('mpromise')", - "string": "MPromise" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "a function which will be called when the promise is resolved that accepts `fn(err, ...){}` as signature" - }, - { - "type": "inherits", - "string": "mpromise https://github.com/aheckmann/mpromise" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`err`: Emits when the promise is rejected" - }, - { - "type": "event", - "string": "`complete`: Emits when the promise is fulfilled" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Promise constructor.

    \n\n

    Promises are returned from executed queries. Example:

    \n\n
    var query = Candy.find({ bar: true });\nvar promise = query.exec();\n
    ", - "summary": "

    Promise constructor.

    ", - "body": "

    Promises are returned from executed queries. Example:

    \n\n
    var query = Candy.find({ bar: true });\nvar promise = query.exec();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Promise (fn) {\n MPromise.call(this, fn);\n}", - "ctx": { - "type": "function", - "name": "Promise", - "string": "Promise()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from mpromise

    ", - "summary": "

    Inherit from mpromise

    ", - "body": "" - }, - "ignore": true, - "code": "Promise.prototype = Object.create(MPromise.prototype, {\n constructor: {\n value: Promise\n , enumerable: false\n , writable: true\n , configurable: true\n }\n});", - "ctx": { - "type": "property", - "receiver": "Promise", - "name": "prototype", - "value": "Object.create(MPromise.prototype, {", - "string": "Promise.prototype" - } - }, - { - "tags": [], - "description": { - "full": "

    Override event names for backward compatibility.

    ", - "summary": "

    Override event names for backward compatibility.

    ", - "body": "" - }, - "ignore": true, - "code": "Promise.SUCCESS = 'complete';\nPromise.FAILURE = 'err';", - "ctx": { - "type": "property", - "receiver": "Promise", - "name": "SUCCESS", - "value": "'complete'", - "string": "Promise.SUCCESS" - } - }, - { - "tags": [ - { - "type": "see", - "title": "mpromise#on", - "url": "https://github.com/aheckmann/mpromise#on", - "visibility": "https://github.com/aheckmann/mpromise#on" - }, - { - "type": "method", - "string": "on" - }, - { - "type": "memberOf", - "parent": "Promise" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "listener", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds listener to the event.

    \n\n

    If event is either the success or failure event and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", - "summary": "

    Adds listener to the event.

    ", - "body": "

    If event is either the success or failure event and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "see", - "title": "mpromise#reject", - "url": "https://github.com/aheckmann/mpromise#reject", - "visibility": "https://github.com/aheckmann/mpromise#reject" - }, - { - "type": "method", - "string": "reject" - }, - { - "type": "memberOf", - "parent": "Promise" - }, - { - "type": "param", - "types": [ - "Object", - "String", - "Error" - ], - "name": "reason", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Rejects this promise with reason.

    \n\n

    If the promise has already been fulfilled or rejected, not action is taken.

    ", - "summary": "

    Rejects this promise with reason.

    ", - "body": "

    If the promise has already been fulfilled or rejected, not action is taken.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "param", - "types": [ - "Error", - "String" - ], - "name": "err", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - } - ], - "description": { - "full": "

    Rejects this promise with err.

    \n\n

    If the promise has already been fulfilled or rejected, not action is taken.

    \n\n

    Differs from #reject by first casting err to an Error if it is not instanceof Error.

    ", - "summary": "

    Rejects this promise with err.

    ", - "body": "

    If the promise has already been fulfilled or rejected, not action is taken.

    \n\n

    Differs from #reject by first casting err to an Error if it is not instanceof Error.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.reject(err);\n}", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "error", - "string": "Promise.prototype.error()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "[err]", - "description": "error or null" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "value to fulfill the promise with" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Resolves this promise to a rejected state if err is passed or a fulfilled state if no err is passed.

    \n\n

    If the promise has already been fulfilled or rejected, not action is taken.

    \n\n

    err will be cast to an Error if not already instanceof Error.

    \n\n

    NOTE: overrides mpromise#resolve to provide error casting.

    ", - "summary": "

    Resolves this promise to a rejected state if err is passed or a fulfilled state if no err is passed.

    ", - "body": "

    If the promise has already been fulfilled or rejected, not action is taken.

    \n\n

    err will be cast to an Error if not already instanceof Error.

    \n\n

    NOTE: overrides mpromise#resolve to provide error casting.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.fulfill(val);\n}", - "ctx": { - "type": "method", - "constructor": "Promise", - "name": "resolve", - "string": "Promise.prototype.resolve()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "addBack" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "listener", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - } - ], - "description": { - "full": "

    Adds a single function as a listener to both err and complete.

    \n\n

    It will be executed with traditional node.js argument position when the promise is resolved.

    \n\n
    promise.addBack(function (err, args...) {\n  if (err) return handleError(err);\n  console.log('success');\n})\n
    \n\n

    Alias of mpromise#onResolve.

    ", - "summary": "

    Adds a single function as a listener to both err and complete.

    ", - "body": "

    It will be executed with traditional node.js argument position when the promise is resolved.

    \n\n
    promise.addBack(function (err, args...) {\n  if (err) return handleError(err);\n  console.log('success');\n})\n
    \n\n

    Alias of mpromise#onResolve.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addBack = Promise.prototype.onResolve;", - "ctx": { - "type": "property", - "constructor": "Promise", - "name": "addBack", - "value": "Promise.prototype.onResolve", - "string": "Promise.prototypeaddBack" - } - }, - { - "tags": [ - { - "type": "method", - "string": "complete" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "args", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Fulfills this promise with passed arguments.

    \n\n

    Alias of mpromise#fulfill.

    ", - "summary": "

    Fulfills this promise with passed arguments.

    ", - "body": "

    Alias of mpromise#fulfill.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.complete = MPromise.prototype.fulfill;", - "ctx": { - "type": "property", - "constructor": "Promise", - "name": "complete", - "value": "MPromise.prototype.fulfill", - "string": "Promise.prototypecomplete" - } - }, - { - "tags": [ - { - "type": "method", - "string": "addCallback" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "listener", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a listener to the complete (success) event.

    \n\n

    Alias of mpromise#onFulfill.

    ", - "summary": "

    Adds a listener to the complete (success) event.

    ", - "body": "

    Alias of mpromise#onFulfill.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addCallback = Promise.prototype.onFulfill;", - "ctx": { - "type": "property", - "constructor": "Promise", - "name": "addCallback", - "value": "Promise.prototype.onFulfill", - "string": "Promise.prototypeaddCallback" - } - }, - { - "tags": [ - { - "type": "method", - "string": "addErrback" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "listener", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a listener to the err (rejected) event.

    \n\n

    Alias of mpromise#onReject.

    ", - "summary": "

    Adds a listener to the err (rejected) event.

    ", - "body": "

    Alias of mpromise#onReject.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Promise.prototype.addErrback = Promise.prototype.onReject;", - "ctx": { - "type": "property", - "constructor": "Promise", - "name": "addErrback", - "value": "Promise.prototype.onReject", - "string": "Promise.prototypeaddErrback" - } - }, - { - "tags": [ - { - "type": "see", - "title": "promises-A+", - "url": "https://github.com/promises-aplus/promises-spec", - "visibility": "https://github.com/promises-aplus/promises-spec" - }, - { - "type": "see", - "title": "mpromise#then", - "url": "https://github.com/aheckmann/mpromise#then", - "visibility": "https://github.com/aheckmann/mpromise#then" - }, - { - "type": "method", - "string": "then" - }, - { - "type": "memberOf", - "parent": "Promise" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "onFulFill", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "onReject", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "newPromise" - } - ], - "description": { - "full": "

    Creates a new promise and returns it. If onFulfill or onReject are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.

    \n\n

    Conforms to promises/A+ specification.

    \n\n

    Example:

    \n\n
    var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec();\npromise.then(function (meetups) {\n  var ids = meetups.map(function (m) {\n    return m._id;\n  });\n  return People.find({ meetups: { $in: ids }).exec();\n}).then(function (people) {\n  if (people.length < 10000) {\n    throw new Error('Too few people!!!');\n  } else {\n    throw new Error('Still need more people!!!');\n  }\n}).then(null, function (err) {\n  assert.ok(err instanceof Error);\n});\n
    ", - "summary": "

    Creates a new promise and returns it. If onFulfill or onReject are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.

    ", - "body": "

    Conforms to promises/A+ specification.

    \n\n

    Example:

    \n\n
    var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec();\npromise.then(function (meetups) {\n  var ids = meetups.map(function (m) {\n    return m._id;\n  });\n  return People.find({ meetups: { $in: ids }).exec();\n}).then(function (people) {\n  if (people.length < 10000) {\n    throw new Error('Too few people!!!');\n  } else {\n    throw new Error('Still need more people!!!');\n  }\n}).then(null, function (err) {\n  assert.ok(err instanceof Error);\n});\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "see", - "title": "mpromise#end", - "url": "https://github.com/aheckmann/mpromise#end", - "visibility": "https://github.com/aheckmann/mpromise#end" - }, - { - "type": "method", - "string": "end" - }, - { - "type": "memberOf", - "parent": "Promise" - } - ], - "description": { - "full": "

    Signifies that this promise was the last in a chain of then()s: if a handler passed to the call to then which produced this promise throws, the exception will go uncaught.

    \n\n

    Example:

    \n\n
    var p = new Promise;\np.then(function(){ throw new Error('shucks') });\nsetTimeout(function () {\n  p.fulfill();\n  // error was caught and swallowed by the promise returned from\n  // p.then(). we either have to always register handlers on\n  // the returned promises or we can do the following...\n}, 10);\n\n// this time we use .end() which prevents catching thrown errors\nvar p = new Promise;\nvar p2 = p.then(function(){ throw new Error('shucks') }).end(); // <--\nsetTimeout(function () {\n  p.fulfill(); // throws \"shucks\"\n}, 10);\n
    ", - "summary": "

    Signifies that this promise was the last in a chain of then()s: if a handler passed to the call to then which produced this promise throws, the exception will go uncaught.

    ", - "body": "

    Example:

    \n\n
    var p = new Promise;\np.then(function(){ throw new Error('shucks') });\nsetTimeout(function () {\n  p.fulfill();\n  // error was caught and swallowed by the promise returned from\n  // p.then(). we either have to always register handlers on\n  // the returned promises or we can do the following...\n}, 10);\n\n// this time we use .end() which prevents catching thrown errors\nvar p = new Promise;\nvar p2 = p.then(function(){ throw new Error('shucks') }).end(); // <--\nsetTimeout(function () {\n  p.fulfill(); // throws \"shucks\"\n}, 10);\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    expose

    ", - "summary": "

    expose

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Promise;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Promise", - "string": "module.exports" - } - } -] -### lib/query.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "criteria", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", - "summary": "

    Query constructor used for building queries.

    ", - "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n this._geoComparison = undefined;\n if (criteria) this.find(criteria);\n}", - "ctx": { - "type": "function", - "name": "Query", - "string": "Query()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", - "summary": "

    Sets query options.

    ", - "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe;\n if ('populate' in options) {\n this.populate(this.options.populate);\n }\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "setOptions", - "string": "Query.prototype.setOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "the model to which the query is bound" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "the operation to execute" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "updateArg", - "description": "used in update methods" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Binds this query to a model.

    ", - "summary": "

    Binds this query to a model.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "bind", - "string": "Query.prototype.bind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "[operation]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Promise" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", - "summary": "

    Executes the query

    ", - "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exec", - "string": "Query.prototype.exec()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[criteria]", - "description": "mongodb selector" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", - "summary": "

    Finds documents.

    ", - "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "find", - "string": "Query.prototype.find()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[obj]", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", - "summary": "

    Casts this query to the schema of model

    ", - "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path || '$and' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n continue;\n }\n\n if (utils.isObject(val)) {\n // handle geo schemas that use object notation\n // { loc: { long: Number, lat: Number }\n\n var geo = val.$near ? '$near' :\n val.$nearSphere ? '$nearSphere' :\n val.$within ? '$within' :\n val.$geoIntersects ? '$geoIntersects' : '';\n\n if (!geo) {\n continue;\n }\n\n var numbertype = new Types.Number('__QueryCasting__')\n var value = val[geo];\n\n if (val.$maxDistance) {\n val.$maxDistance = numbertype.castForQuery(val.$maxDistance);\n }\n\n if ('$within' == geo) {\n var withinType = value.$center\n || value.$centerSphere\n || value.$box\n || value.$polygon;\n\n if (!withinType) {\n throw new Error('Bad $within paramater: ' + JSON.stringify(val));\n }\n\n value = withinType;\n\n } else if ('$near' == geo &&\n 'string' == typeof value.type && Array.isArray(value.coordinates)) {\n // geojson; cast the coordinates\n value = value.coordinates;\n\n } else if (('$near' == geo || '$geoIntersects' == geo) &&\n value.$geometry && 'string' == typeof value.$geometry.type &&\n Array.isArray(value.$geometry.coordinates)) {\n // geojson; cast the coordinates\n value = value.$geometry.coordinates;\n }\n\n ;(function _cast (val) {\n if (Array.isArray(val)) {\n val.forEach(function (item, i) {\n if (Array.isArray(item) || utils.isObject(item)) {\n return _cast(item);\n }\n val[i] = numbertype.castForQuery(item);\n });\n } else {\n var nearKeys= Object.keys(val);\n var nearLen = nearKeys.length;\n while (nearLen--) {\n var nkey = nearKeys[nearLen];\n var item = val[nkey];\n if (Array.isArray(item) || utils.isObject(item)) {\n _cast(item);\n val[nkey] = item;\n } else {\n val[nkey] = numbertype.castForQuery(item);\n }\n }\n }\n })(value);\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "cast", - "string": "Query.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns default options.

    ", - "summary": "

    Returns default options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_optionsForExec", - "string": "Query.prototype._optionsForExec()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies schematype selected options to this query.

    ", - "summary": "

    Applies schematype selected options to this query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_applyPaths", - "string": "Query.prototype._applyPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Function" - ], - "name": "js", - "description": "javascript string or function" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "method", - "string": "$where" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", - "summary": "

    Specifies a $where condition

    ", - "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[val]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", - "summary": "

    Specifies a path for use with chaining.

    ", - "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "where", - "string": "Query.prototype.where()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", - "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", - "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "equals", - "string": "Query.prototype.equals()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", - "summary": "

    Specifies arguments for an $or condition.

    ", - "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "or", - "string": "Query.prototype.or()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", - "summary": "

    Specifies arguments for a $nor condition.

    ", - "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nor", - "string": "Query.prototype.nor()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "array", - "description": "array of conditions" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies arguments for a $and condition.

    \n\n

    Example

    \n\n
    query.and([{ color: 'green' }, { status: 'ok' }])\n
    ", - "summary": "

    Specifies arguments for a $and condition.

    ", - "body": "

    Example

    \n\n
    query.and([{ color: 'green' }, { status: 'ok' }])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.and = function and (array) {\n var and = this._conditions.$and || (this._conditions.$and = []);\n if (!Array.isArray(array)) array = [array];\n and.push.apply(and, array);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "and", - "string": "Query.prototype.and()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "gt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", - "summary": "

    Specifies a $gt query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "gte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $gte query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lt" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $lt query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "lte" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $lte query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "ne" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $ne query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "in" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $in query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "nin" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $nin query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "all" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $all query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "size" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies an $size query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "regex" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $regex query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxDistance" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", - "summary": "

    Specifies a $maxDistance query condition.

    ", - "body": "

    When called with one argument, the most recent path passed to where() is used.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", - "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", - "body": "
    Thing.where('type').nin(array)\n
    " - }, - "ignore": true, - "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $near condition

    ", - "summary": "

    Specifies a $near condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "near", - "string": "Query.prototype.near()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $nearSphere condition.

    ", - "summary": "

    Specifies a $nearSphere condition.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "nearSphere", - "string": "Query.prototype.nearSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $mod condition

    ", - "summary": "

    Specifies a $mod condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "mod", - "string": "Query.prototype.mod()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $exists condition

    ", - "summary": "

    Specifies an $exists condition

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "exists", - "string": "Query.prototype.exists()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object", - "Function" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object", - "Function" - ], - "name": "criteria", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", - "summary": "

    Specifies an $elemMatch condition

    ", - "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "elemMatch", - "string": "Query.prototype.elemMatch()" - } - }, - { - "tags": [ - { - "type": "property", - "string": "within" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "see", - "local": "Query#box #query_Query-box", - "visibility": "Query#box" - }, - { - "type": "see", - "local": "Query#center #query_Query-center", - "visibility": "Query#center" - }, - { - "type": "see", - "local": "Query#centeSphere #query_Query-centerSphere", - "visibility": "Query#centeSphere" - }, - { - "type": "see", - "local": "Query#polygon #query_Query-polygon", - "visibility": "Query#polygon" - }, - { - "type": "see", - "local": "Query#geometry #query_Query-geometry", - "visibility": "Query#geometry" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a $within query for box(), center(), etc

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\nquery.within.geometry()\n
    ", - "summary": "

    Defines a $within query for box(), center(), etc

    ", - "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\nquery.within.geometry()\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () {\n this._geoComparison = '$within';\n return this\n }\n});" - }, - { - "tags": [ - { - "type": "property", - "string": "intersects" - }, - { - "type": "see", - "local": "Query#geometry #query_Query-geometry", - "visibility": "Query#geometry" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares an intersects query for geometry().

    \n\n

    Example

    \n\n
    query.intersects.geometry({\n    type: 'LineString'\n  , coordinates: [[180.0, 11.0], [180, 9.0]]\n})\n
    ", - "summary": "

    Declares an intersects query for geometry().

    ", - "body": "

    Example

    \n\n
    query.intersects.geometry({\n    type: 'LineString'\n  , coordinates: [[180.0, 11.0], [180, 9.0]]\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Object.defineProperty(Query.prototype, 'intersects', {\n get: function () {\n this._geoComparison = '$geoIntersects';\n return this\n }\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "see", - "local": "Query#within #query_Query-within", - "visibility": "Query#within" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", - "summary": "

    Specifies a $box condition

    ", - "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "box", - "string": "Query.prototype.box()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[opts]", - "description": "options e.g. { $uniqueDocs: true }" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", - "summary": "

    Specifies a $center condition

    ", - "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "center", - "string": "Query.prototype.center()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", - "summary": "

    Specifies a $centerSphere condition

    ", - "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "centerSphere", - "string": "Query.prototype.centerSphere()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Array", - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", - "summary": "

    Specifies a $polygon condition

    ", - "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "polygon", - "string": "Query.prototype.polygon()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "", - "url": "http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry", - "visibility": "http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry" - }, - { - "type": "see", - "title": "", - "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", - "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $geometry condition

    \n\n

    Accepts an object that must contain the following two properties

    \n\n
      \n
    • type: String
    • \n
    • coordinates: Array
    • \n
    \n\n

    Example

    \n\n
    var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]]\nquery.where('loc').within.geometry({ type: 'Polygon', coordinates: polyA })\n\n// or\nvar polyB = [[ 0, 0 ], [ 1, 1 ]]\nquery.where('loc').within.geometry({ type: 'LineString', coordinates: polyB })\n\n// or\nvar polyC = [ 0, 0 ]\nquery.where('loc').within.geometry({ type: 'Point', coordinates: polyC })\n\n// or\nvar polyC = [ 0, 0 ]\nquery.where('loc').intersects.geometry({ type: 'Point', coordinates: polyC })\n
    \n\n

    NOTE: Must come after intersects or within.

    ", - "summary": "

    Specifies a $geometry condition

    ", - "body": "

    Accepts an object that must contain the following two properties

    \n\n
      \n
    • type: String
    • \n
    • coordinates: Array
    • \n
    \n\n

    Example

    \n\n
    var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]]\nquery.where('loc').within.geometry({ type: 'Polygon', coordinates: polyA })\n\n// or\nvar polyB = [[ 0, 0 ], [ 1, 1 ]]\nquery.where('loc').within.geometry({ type: 'LineString', coordinates: polyB })\n\n// or\nvar polyC = [ 0, 0 ]\nquery.where('loc').within.geometry({ type: 'Point', coordinates: polyC })\n\n// or\nvar polyC = [ 0, 0 ]\nquery.where('loc').intersects.geometry({ type: 'Point', coordinates: polyC })\n
    \n\n

    NOTE: Must come after intersects or within.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.geometry = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n\n var conds = this._conditions[path] || (this._conditions[path] = {});\n\n if (!this._geoComparison) {\n throw new Error('query.geometry() must come after either `within` or `intersects`');\n }\n\n conds[this._geoComparison] = { $geometry: val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "geometry", - "string": "Query.prototype.geometry()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "local": "SchemaType", - "visibility": "SchemaType" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    ", - "summary": "

    Specifies which document fields to include or exclude

    ", - "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "select", - "string": "Query.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "number of elements to slice" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", - "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", - "summary": "

    Specifies a $slice condition

    ", - "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slice", - "string": "Query.prototype.slice()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "arg", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", - "summary": "

    Sets the sort order

    ", - "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "sort", - "string": "Query.prototype.sort()" - } - }, - { - "tags": [], - "description": { - "full": "

    @ignore

    ", - "summary": "

    @ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", - "ctx": { - "type": "function", - "name": "push", - "string": "push()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "limit" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", - "summary": "

    Specifies the limit option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "skip" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", - "summary": "

    Specifies the skip option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "maxscan" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", - "summary": "

    Specifies the maxscan option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "batchSize" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", - "summary": "

    Specifies the batchSize option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [ - { - "type": "method", - "string": "comment" - }, - { - "type": "memberOf", - "parent": "Query" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "val", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", - "summary": "

    Specifies the comment option.

    ", - "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", - "summary": "

    limit, skip, maxscan, batchSize, comment

    ", - "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " - }, - "ignore": true, - "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", - "summary": "

    Specifies this query as a snapshot query.

    ", - "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "snapshot", - "string": "Query.prototype.snapshot()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "a hint object" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", - "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", - "summary": "

    Sets query hints.

    ", - "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "hint", - "string": "Query.prototype.hint()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", - "summary": "

    Sets the slaveOk option.

    ", - "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "slaveOk", - "string": "Query.prototype.slaveOk()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "one of the listed preference options or their aliases" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "[tags]", - "description": "optional tags for this query" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", - "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" - }, - { - "type": "see", - "title": "driver", - "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", - "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the readPreference option for the query.

    \n\n

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    ", - "summary": "

    Sets the readPreference option for the query.

    ", - "body": "

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "read", - "string": "Query.prototype.read()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", - "summary": "

    Sets the lean option.

    ", - "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "lean", - "string": "Query.prototype.lean()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "v", - "description": "defaults to true" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", - "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", - "summary": "

    Sets tailable option.

    ", - "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "tailable", - "string": "Query.prototype.tailable()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Executes the query as a find() operation.

    ", - "summary": "

    Executes the query as a find() operation.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (0 === docs.length) {\n return promise.complete(docs);\n }\n\n if (!self.options.populate) {\n return true === options.lean\n ? promise.complete(docs)\n : completeMany(model, docs, fields, self, null, promise);\n }\n\n var pop = preparePopulationOptions(self, options);\n model.populate(docs, pop, function (err, docs) {\n if (err) return promise.error(err);\n return true === options.lean\n ? promise.complete(docs)\n : completeMany(model, docs, fields, self, pop, promise);\n });\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "execFind", - "string": "Query.prototype.execFind()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "docs", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "param", - "types": [ - "Query" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "[pop]", - "description": "array of paths used in population" - }, - { - "type": "param", - "types": [ - "Promise" - ], - "name": "promise", - "description": "" - } - ], - "description": { - "full": "

    hydrates many documents

    ", - "summary": "

    hydrates many documents

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function completeMany (model, docs, fields, self, pop, promise) {\n var arr = [];\n var count = docs.length;\n var len = count;\n var i = 0;\n var opts = pop ?\n { populated: pop }\n : undefined;\n\n for (; i < len; ++i) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], opts, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n}", - "ctx": { - "type": "function", - "name": "completeMany", - "string": "completeMany()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", - "summary": "

    Executes the query as a findOne() operation.

    ", - "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (!self.options.populate) {\n return true === options.lean\n ? promise.complete(doc)\n : completeOne(model, doc, fields, self, null, promise);\n }\n\n var pop = preparePopulationOptions(self, options);\n model.populate(doc, pop, function (err, doc) {\n if (err) return promise.error(err);\n return true === options.lean\n ? promise.complete(doc)\n : completeOne(model, doc, fields, self, pop, promise);\n })\n }));\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOne", - "string": "Query.prototype.findOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - } - ], - "description": { - "full": "

    Prepare a set of path options for query population.

    ", - "summary": "

    Prepare a set of path options for query population.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function preparePopulationOptions (query, options) {\n var pop = utils.object.vals(query.options.populate);\n\n // lean options should trickle through all queries\n if (options.lean) pop.forEach(makeLean);\n\n return pop;\n}", - "ctx": { - "type": "function", - "name": "preparePopulationOptions", - "string": "preparePopulationOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "option", - "description": "" - } - ], - "description": { - "full": "

    Set each path query option to lean

    ", - "summary": "

    Set each path query option to lean

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function makeLean (option) {\n option.options || (option.options = {});\n option.options.lean = true;\n}", - "ctx": { - "type": "function", - "name": "makeLean", - "string": "makeLean()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Model" - ], - "name": "model", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "param", - "types": [ - "Query" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "[pop]", - "description": "array of paths used in population" - }, - { - "type": "param", - "types": [ - "Promise" - ], - "name": "promise", - "description": "" - } - ], - "description": { - "full": "

    hydrates a document

    ", - "summary": "

    hydrates a document

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function completeOne (model, doc, fields, self, pop, promise) {\n var opts = pop ?\n { populated: pop }\n : undefined;\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, opts, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n}", - "ctx": { - "type": "function", - "name": "completeOne", - "string": "completeOne()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", - "summary": "

    Exectues the query as a count() operation.

    ", - "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "count", - "string": "Query.prototype.count()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "field", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", - "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as a distict() operation.

    ", - "summary": "

    Executes this query as a distict() operation.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "distinct", - "string": "Query.prototype.distinct()" - } - }, - { - "tags": [], - "description": { - "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", - "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", - "body": "" - }, - "ignore": true, - "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", - "ctx": { - "type": "declaration", - "name": "castOps", - "value": "{", - "string": "castOps" - } - }, - { - "tags": [], - "description": { - "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", - "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", - "body": "" - }, - "ignore": true, - "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", - "ctx": { - "type": "declaration", - "name": "numberOps", - "value": "{", - "string": "numberOps" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "the update conditions" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", - "summary": "

    Executes this query as an update() operation.

    ", - "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n options.safe = { w: 0 };\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "update", - "string": "Query.prototype.update()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "obj after casting its values" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts obj for an update command.

    ", - "summary": "

    Casts obj for an update command.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdate", - "string": "Query.prototype._castUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "- part of a query" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "pref", - "description": "- path prefix (internal only)" - }, - { - "type": "return", - "types": [ - "Bool" - ], - "description": "true if this path has keys to update" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", - "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n var strict = 'strict' in this.options\n ? this.options.strict\n : this.model.schema.options.strict;\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n\n if (val.$slice) {\n obj[key].$slice = val.$slice | 0;\n }\n\n if (val.$sort) {\n obj[key].$sort = val.$sort;\n }\n\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_walkUpdatePath", - "string": "Query.prototype._walkUpdatePath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "op", - "description": "- the atomic operator ($pull, $set, etc)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[$conditional]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts val according to schema and atomic op.

    ", - "summary": "

    Casts val according to schema and atomic op.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castUpdateVal", - "string": "Query.prototype._castUpdateVal()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._getSchema = function _getSchema (path) {\n return this.model._getSchema(path);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_getSchema", - "string": "Query.prototype._getSchema()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "see", - "title": "", - "url": "https://github.com/LearnBoost/mongoose/issues/1091", - "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" - }, - { - "type": "see", - "title": "", - "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", - "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts selected field arguments for field selection with mongo 2.2

    \n\n
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    ", - "summary": "

    Casts selected field arguments for field selection with mongo 2.2

    ", - "body": "
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_castFields", - "string": "Query.prototype._castFields()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", - "summary": "

    Executes this query as a remove() operation.

    ", - "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n options.safe = { w: 0 };\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "remove", - "string": "Query.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[query]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[doc]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", - "summary": "

    Issues a mongodb findAndModify update command.

    ", - "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndUpdate", - "string": "Query.prototype.findOneAndUpdate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[conditions]", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[callback]", - "description": "" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", - "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", - "summary": "

    Issues a mongodb findAndModify remove command.

    ", - "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "findOneAndRemove", - "string": "Query.prototype.findOneAndRemove()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "type", - "description": "- either \"remove\" or \"update\"" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    _findAndModify

    ", - "summary": "

    _findAndModify

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n this._applyPaths();\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "_findAndModify", - "string": "Query.prototype._findAndModify()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "path", - "description": "either the path to populate or an object specifying all parameters" - }, - { - "type": "param", - "types": [ - "Object", - "String" - ], - "name": "[select]", - "description": "Field selection for the population query" - }, - { - "type": "param", - "types": [ - "Model" - ], - "name": "[model]", - "description": "The name of the model you wish to use for population. If not specified, the name is looked up from the Schema [ref](./populate.html)." - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[match]", - "description": "Conditions for the population query" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "Options for the population query (sort, etc)" - }, - { - "type": "see", - "local": "population ./populate.html", - "visibility": "population" - }, - { - "type": "see", - "local": "Query#select #query_Query-select", - "visibility": "Query#select" - }, - { - "type": "return", - "types": [ - "Query" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n\nKitten.find().populate({\n    path: 'owner'\n  , select: 'name'\n  , match: { color: 'black' }\n  , options: { sort: { name: -1 }}\n}).exec(function (err, kittens) {\n  console.log(kittens[0].owner.name) // Zoopa\n})\n\n// alternatively\nKitten.find().populate('owner', 'name', null, {sort: { name: -1 }}).exec(function (err, kittens) {\n  console.log(kittens[0].owner.name) // Zoopa\n})\n
    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    ", - "summary": "

    Specifies paths which should be populated with other documents.

    ", - "body": "

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n\nKitten.find().populate({\n    path: 'owner'\n  , select: 'name'\n  , match: { color: 'black' }\n  , options: { sort: { name: -1 }}\n}).exec(function (err, kittens) {\n  console.log(kittens[0].owner.name) // Zoopa\n})\n\n// alternatively\nKitten.find().populate('owner', 'name', null, {sort: { name: -1 }}).exec(function (err, kittens) {\n  console.log(kittens[0].owner.name) // Zoopa\n})\n
    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.populate = function populate () {\n var res = utils.populate.apply(null, arguments);\n var opts = this.options;\n\n if (!utils.isObject(opts.populate)) {\n opts.populate = {};\n }\n\n for (var i = 0; i < res.length; ++i) {\n opts.populate[res[i].path] = res[i];\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "populate", - "string": "Query.prototype.populate()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "QueryStream" - ], - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "see", - "local": "QueryStream", - "visibility": "QueryStream" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a Node.js 0.8 style read stream interface.

    \n\n

    Example

    \n\n
    // follows the nodejs 0.8 stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    Valid options

    \n\n
      \n
    • transform: optional function which accepts a mongoose document. The return value of the function will be emitted.
    • \n
    \n\n

    Example

    \n\n
    // JSON.stringify all documents before emitting\nvar stream = Thing.find().stream({ transform: JSON.stringify });\nstream.pipe(writeStream);\n
    ", - "summary": "

    Returns a Node.js 0.8 style read stream interface.

    ", - "body": "

    Example

    \n\n
    // follows the nodejs 0.8 stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    Valid options

    \n\n
      \n
    • transform: optional function which accepts a mongoose document. The return value of the function will be emitted.
    • \n
    \n\n

    Example

    \n\n
    // JSON.stringify all documents before emitting\nvar stream = Thing.find().stream({ transform: JSON.stringify });\nstream.pipe(writeStream);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Query.prototype.stream = function stream (opts) {\n return new QueryStream(this, opts);\n}\n\n// helpers", - "ctx": { - "type": "method", - "constructor": "Query", - "name": "stream", - "string": "Query.prototype.stream()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    castDoc

    ", - "summary": "

    castDoc

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castDoc", - "string": "castDoc()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    castQuery

    ", - "summary": "

    castQuery

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", - "ctx": { - "type": "function", - "name": "castQuery", - "string": "castQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Exports.

    ", - "summary": "

    Exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Query", - "string": "module.exports" - } - } -] -### lib/querystream.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')\nvar K = function(k){ return k }", - "ctx": { - "type": "declaration", - "name": "Stream", - "value": "require('stream').Stream", - "string": "Stream" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Query" - ], - "name": "query", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS Stream http://nodejs.org/docs/v0.8.21/api/stream.html#stream_readable_stream" - }, - { - "type": "event", - "string": "`data`: emits a single Mongoose document" - }, - { - "type": "event", - "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." - }, - { - "type": "event", - "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Provides a Node.js 0.8 style ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node.js 0.8 style write streams.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    \n\n

    NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary.

    \n\n

    NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work.

    ", - "summary": "

    Provides a Node.js 0.8 style ReadStream interface for Queries.

    ", - "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node.js 0.8 style write streams.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    \n\n

    NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary.

    \n\n

    NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function QueryStream (query, options) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n this._running = false;\n this._transform = options && 'function' == typeof options.transform\n ? options.transform\n : K;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", - "ctx": { - "type": "function", - "name": "QueryStream", - "string": "QueryStream()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Stream

    ", - "summary": "

    Inherit from Stream

    ", - "body": "" - }, - "ignore": true, - "code": "QueryStream.prototype.__proto__ = Stream.prototype;", - "ctx": { - "type": "property", - "constructor": "QueryStream", - "name": "__proto__", - "value": "Stream.prototype", - "string": "QueryStream.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "property", - "string": "readable" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Flag stating whether or not this stream is readable.

    ", - "summary": "

    Flag stating whether or not this stream is readable.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.readable;" - }, - { - "tags": [ - { - "type": "property", - "string": "paused" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Flag stating whether or not this stream is paused.

    ", - "summary": "

    Flag stating whether or not this stream is paused.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Initializes the query.

    ", - "summary": "

    Initializes the query.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_init", - "string": "QueryStream.prototype._init()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#__next #querystream_QueryStream-__next", - "visibility": "QueryStream#__next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Trampoline for pulling the next doc from cursor.

    ", - "summary": "

    Trampoline for pulling the next doc from cursor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) {\n return this._running = false;\n }\n\n this._running = true;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n while (this.__next()) {}\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_next", - "string": "QueryStream.prototype._next()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "QueryStream#_next #querystream_QueryStream-_next", - "visibility": "QueryStream#_next" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Pulls the next doc from the cursor.

    ", - "summary": "

    Pulls the next doc from the cursor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed)\n return this._running = false;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "__next", - "string": "QueryStream.prototype.__next()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error", - "null" - ], - "name": "err", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", - "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return this._running = false;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && true === this.query.options.lean) {\n this.emit('data', this._transform(doc));\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', self._transform(instance));\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "_onNextObject", - "string": "QueryStream.prototype._onNextObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pauses this stream.

    ", - "summary": "

    Pauses this stream.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "pause", - "string": "QueryStream.prototype.pause()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Resumes this stream.

    ", - "summary": "

    Resumes this stream.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n\n if (!this._cursor) {\n // cannot start if not initialized\n return;\n }\n\n // are we within the trampoline?\n if (T_INIT === this._inline) {\n return;\n }\n\n if (!this._running) {\n // outside QueryStream control, need manual restart\n return this._next();\n }\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "resume", - "string": "QueryStream.prototype.resume()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Error" - ], - "name": "[err]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", - "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this._running = false;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", - "ctx": { - "type": "method", - "constructor": "QueryStream", - "name": "destroy", - "string": "QueryStream.prototype.destroy()" - } - }, - { - "tags": [ - { - "type": "method", - "string": "pipe" - }, - { - "type": "memberOf", - "parent": "QueryStream" - }, - { - "type": "see", - "title": "NodeJS", - "url": "http://nodejs.org/api/stream.html", - "visibility": "http://nodejs.org/api/stream.html" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", - "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", - "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " - }, - "isPrivate": false, - "ignore": false - }, - { - "tags": [], - "description": { - "full": "

    Module exports

    ", - "summary": "

    Module exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = QueryStream;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = QueryStream", - "string": "module.exports" - } - } -] -### lib/schema/array.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , EmbeddedDoc = require('../types').Embedded\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Array SchemaType constructor

    ", - "summary": "

    Array SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n // support { type: 'String' }\n var name = 'string' == typeof cast\n ? cast\n : cast.name;\n\n var caster = name in Types\n ? Types[name]\n : cast;\n\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n if (!(this.caster instanceof EmbeddedDoc)) {\n this.caster.path = key;\n }\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "SchemaArray", - "string": "SchemaArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaArray", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "checkRequired", - "string": "SchemaArray.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Overrides the getters application for the population special-case

    ", - "summary": "

    Overrides the getters application for the population special-case

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "applyGetters", - "string": "SchemaArray.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value, this.path);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "cast", - "string": "SchemaArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n\n var caster = this.caster;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(caster, v);\n\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(caster, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaArray", - "name": "castForQuery", - "string": "SchemaArray.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    @ignore

    ", - "summary": "

    @ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nfunction castArray (arr, self) {\n self || (self = this);\n\n arr.forEach(function (v, i) {\n if (Array.isArray(v)) {\n castArray(v, self);\n } else {\n arr[i] = castToNumber.call(self, v);\n }\n });\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': SchemaArray.prototype.castForQuery\n , '$gte': SchemaArray.prototype.castForQuery\n , '$lt': SchemaArray.prototype.castForQuery\n , '$lte': SchemaArray.prototype.castForQuery\n , '$within': function (val) {\n var self = this;\n\n if (val.$maxDistance) {\n val.$maxDistance = castToNumber.call(this, val.$maxDistance);\n }\n\n if (val.$box || val.$polygon) {\n var type = val.$box ? '$box' : '$polygon';\n val[type].forEach(function (arr) {\n if (!Array.isArray(arr)) {\n var msg = 'Invalid $within $box argument. '\n + 'Expected an array, received ' + arr;\n throw new TypeError(msg);\n }\n arr.forEach(function (v, i) {\n arr[i] = castToNumber.call(this, v);\n });\n })\n } else if (val.$center || val.$centerSphere) {\n var type = val.$center ? '$center' : '$centerSphere';\n val[type].forEach(function (item, i) {\n if (Array.isArray(item)) {\n item.forEach(function (v, j) {\n item[j] = castToNumber.call(this, v);\n });\n } else {\n val[type][i] = castToNumber.call(this, item);\n }\n })\n } else if (val.$geometry) {\n switch (val.$geometry.type) {\n case 'Polygon':\n case 'LineString':\n case 'Point':\n val.$geometry.coordinates.forEach(castArray);\n break;\n default:\n // ignore unknowns\n break;\n }\n }\n\n return val;\n }\n , '$geoIntersects': function (val) {\n var geo = val.$geometry;\n if (!geo) return;\n\n switch (val.$geometry.type) {\n case 'Polygon':\n case 'LineString':\n case 'Point':\n val.$geometry.coordinates.forEach(castArray);\n break;\n default:\n // ignore unknowns\n break;\n }\n }\n , '$maxDistance': castToNumber\n};", - "ctx": { - "type": "function", - "name": "castToNumber", - "string": "castToNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaArray", - "string": "module.exports" - } - } -] -### lib/schema/boolean.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Boolean SchemaType constructor.

    ", - "summary": "

    Boolean SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaBoolean", - "string": "SchemaBoolean()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBoolean", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBoolean.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator

    ", - "summary": "

    Required validator

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "checkRequired", - "string": "SchemaBoolean.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to boolean

    ", - "summary": "

    Casts to boolean

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.cast = function (value) {\n if (null === value) return value;\n if ('0' === value) return false;\n if ('true' === value) return true;\n if ('false' === value) return false;\n return !! value;\n}", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "cast", - "string": "SchemaBoolean.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", - "ctx": { - "type": "function", - "name": "handleArray", - "string": "handleArray()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBoolean", - "name": "castForQuery", - "string": "SchemaBoolean.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBoolean;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBoolean", - "string": "module.exports" - } - } -] -### lib/schema/buffer.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query')\n , utils = require('../utils')\n , Document", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "cast", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Buffer SchemaType constructor

    ", - "summary": "

    Buffer SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", - "ctx": { - "type": "function", - "name": "SchemaBuffer", - "string": "SchemaBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaBuffer", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaBuffer.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.checkRequired = function (value, doc) {\n if (SchemaType._isRef(this, value, doc, true)) {\n return null != value;\n } else {\n return !!(value && value.length);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "checkRequired", - "string": "SchemaBuffer.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, doc, init)) {\n // wait! we may need to cast this to a document\n\n // lazy load\n Document || (Document = require('./../document'));\n\n if (value instanceof Document || null == value) {\n return value;\n }\n\n // setting a populated path\n if (Buffer.isBuffer(value)) {\n return value;\n } else if (!utils.isObject(value)) {\n throw new CastError('buffer', value, this.path);\n }\n\n // Handle the case where user directly sets a populated\n // path to a plain object; cast to the Model used in\n // the population query.\n var path = doc.$__fullPath(this.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n var pop = owner.populated(path, true);\n var ret = new pop.options.model(value);\n return ret;\n }\n\n // documents\n if (value && value._id) {\n value = value._id;\n }\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if (null === value) return value;\n\n var type = typeof value;\n if ('string' == type || 'number' == type || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value, this.path);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "cast", - "string": "SchemaBuffer.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaBuffer", - "name": "castForQuery", - "string": "SchemaBuffer.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaBuffer;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaBuffer", - "string": "module.exports" - } - } -] -### lib/schema/date.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements.

    ", - "summary": "

    Module requirements.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');\nvar CastError = SchemaType.CastError;\nvar utils = require('../utils');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Date SchemaType constructor.

    ", - "summary": "

    Date SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", - "ctx": { - "type": "function", - "name": "SchemaDate", - "string": "SchemaDate()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaDate", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaDate.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number", - "String" - ], - "name": "when", - "description": "" - }, - { - "type": "added", - "string": "3.0.0" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: 60*60*24 }});\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: '24h' }});\n\n// expire in 1.5 hours\nnew Schema({ createdAt: { type: Date, expires: '1.5h' }});\n\n// expire in 7 days\nvar schema = new Schema({ createdAt: Date });\nschema.path('createdAt').expires('7d');\n
    ", - "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", - "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: 60*60*24 }});\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: '24h' }});\n\n// expire in 1.5 hours\nnew Schema({ createdAt: { type: Date, expires: '1.5h' }});\n\n// expire in 7 days\nvar schema = new Schema({ createdAt: Date });\nschema.path('createdAt').expires('7d');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaDate.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "expires", - "string": "SchemaDate.prototype.expires()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator for date

    ", - "summary": "

    Required validator for date

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "checkRequired", - "string": "SchemaDate.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to date

    ", - "summary": "

    Casts to date

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value, this.path);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "cast", - "string": "SchemaDate.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Date Query casting.

    ", - "summary": "

    Date Query casting.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaDate", - "name": "castForQuery", - "string": "SchemaDate.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaDate;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaDate", - "string": "module.exports" - } - } -] -### lib/schema/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , Document = require('../document');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Schema" - ], - "name": "schema", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaArray" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    SubdocsArray SchemaType constructor

    ", - "summary": "

    SubdocsArray SchemaType constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype.$__setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", - "ctx": { - "type": "function", - "name": "DocumentArray", - "string": "DocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from ArrayType.

    ", - "summary": "

    Inherits from ArrayType.

    ", - "body": "" - }, - "ignore": true, - "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", - "ctx": { - "type": "property", - "constructor": "DocumentArray", - "name": "__proto__", - "value": "ArrayType.prototype", - "string": "DocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs local validations first, then validations on each embedded doc

    ", - "summary": "

    Performs local validations first, then validations on each embedded doc

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n\n SchemaType.prototype.doValidate.call(this, array, function (err) {\n if (err) return fn(err);\n\n var count = array && array.length\n , error;\n\n if (!count) return fn();\n\n // handle sparse arrays, do not use array.forEach which does not\n // iterate over sparse elements yet reports array.length including\n // them :(\n\n for (var i = 0, len = count; i < len; ++i) {\n // sidestep sparse entries\n var doc = array[i];\n if (!doc) {\n --count || fn();\n continue;\n }\n\n ;(function (i) {\n doc.validate(function (err) {\n if (err && !error) {\n // rewrite the key\n err.key = self.key + '.' + i + '.' + err.key;\n return fn(error = err);\n }\n --count || fn();\n });\n })(i);\n }\n }, scope);\n};", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "doValidate", - "string": "DocumentArray.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "document", - "description": "that triggers the casting" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents

    ", - "summary": "

    Casts contents

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument) && value[i]) {\n if (init) {\n selected || (selected = scopePaths(this, doc.$__.selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", - "ctx": { - "type": "method", - "constructor": "DocumentArray", - "name": "cast", - "string": "DocumentArray.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "DocumentArray" - ], - "name": "array", - "description": "- the array to scope `fields` paths" - }, - { - "type": "param", - "types": [ - "Object", - "undefined" - ], - "name": "fields", - "description": "- the root fields selected in the query" - }, - { - "type": "param", - "types": [ - "Boolean", - "undefined" - ], - "name": "init", - "description": "- if we are being created part of a query result" - } - ], - "description": { - "full": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", - "summary": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , hasKeys\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n hasKeys || (hasKeys = true);\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return hasKeys && selected || undefined;\n}", - "ctx": { - "type": "function", - "name": "scopePaths", - "string": "scopePaths()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = DocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "DocumentArray", - "string": "module.exports" - } - } -] -### lib/schema/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "String", - "value": "require('./string')", - "string": "exports.String" - } - } -] -### lib/schema/mixed.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype');\nvar utils = require('../utils');", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Mixed SchemaType constructor.

    ", - "summary": "

    Mixed SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function Mixed (path, options) {\n if (options && options.default) {\n var def = options.default;\n if (Array.isArray(def) && 0 === def.length) {\n // make sure empty array defaults are handled\n options.default = Array;\n } else if (!options.shared &&\n utils.isObject(def) &&\n 0 === Object.keys(def).length) {\n // prevent odd \"shared\" objects between documents\n options.default = function () {\n return {}\n }\n }\n }\n\n SchemaType.call(this, path, options);\n};", - "ctx": { - "type": "function", - "name": "Mixed", - "string": "Mixed()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "Mixed", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "Mixed.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator

    ", - "summary": "

    Required validator

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "checkRequired", - "string": "Mixed.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "to cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", - "summary": "

    Casts val for Mixed.

    ", - "body": "

    this is a no-op

    " - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "cast", - "string": "Mixed.prototype.cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$cond", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", - "ctx": { - "type": "method", - "constructor": "Mixed", - "name": "castForQuery", - "string": "Mixed.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = Mixed;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "Mixed", - "string": "module.exports" - } - } -] -### lib/schema/number.js -[ - { - "tags": [], - "description": { - "full": "

    Module requirements.

    ", - "summary": "

    Module requirements.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , utils = require('../utils')\n , Document", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Number SchemaType constructor.

    ", - "summary": "

    Number SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", - "ctx": { - "type": "function", - "name": "SchemaNumber", - "string": "SchemaNumber()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaNumber", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaNumber.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Required validator for number

    ", - "summary": "

    Required validator for number

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value, doc) {\n if (SchemaType._isRef(this, value, doc, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "checkRequired", - "string": "SchemaNumber.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "value", - "description": "minimum number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a minimum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", - "summary": "

    Sets a minimum number validator.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "min", - "string": "SchemaNumber.prototype.min()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Number" - ], - "name": "maximum", - "description": "number" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "message", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", - "summary": "

    Sets a maximum number validator.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "max", - "string": "SchemaNumber.prototype.max()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "value to cast" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "document that triggers the casting" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to number

    ", - "summary": "

    Casts to number

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, doc, init)) {\n // wait! we may need to cast this to a document\n\n // lazy load\n Document || (Document = require('./../document'));\n\n if (value instanceof Document || null == value) {\n return value;\n }\n\n // setting a populated path\n if ('number' == typeof value) {\n return value;\n } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {\n throw new CastError('number', value, this.path);\n }\n\n // Handle the case where user directly sets a populated\n // path to a plain object; cast to the Model used in\n // the population query.\n var path = doc.$__fullPath(this.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n var pop = owner.populated(path, true);\n return new pop.options.model(value);\n }\n\n var val = value && value._id\n ? value._id // documents\n : value;\n\n if (!isNaN(val)){\n if (null === val) return val;\n if ('' === val) return null;\n if ('string' == typeof val) val = Number(val);\n if (val instanceof Number) return val\n if ('number' == typeof val) return val;\n if (val.toString && !Array.isArray(val) &&\n val.toString() == Number(val)) {\n return new Number(val)\n }\n }\n\n throw new CastError('number', value, this.path);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "cast", - "string": "SchemaNumber.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[value]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaNumber", - "name": "castForQuery", - "string": "SchemaNumber.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaNumber;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaNumber", - "string": "module.exports" - } - } -] -### lib/schema/objectid.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid')\n , utils = require('../utils')\n , Document", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    ObjectId SchemaType constructor.

    ", - "summary": "

    ObjectId SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", - "ctx": { - "type": "function", - "name": "ObjectId", - "string": "ObjectId()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "ObjectId", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "ObjectId.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.checkRequired = function checkRequired (value, doc) {\n if (SchemaType._isRef(this, value, doc, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "checkRequired", - "string": "ObjectId.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "whether this is an initialization cast" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to ObjectId

    ", - "summary": "

    Casts to ObjectId

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, doc, init)) {\n // wait! we may need to cast this to a document\n\n // lazy load\n Document || (Document = require('./../document'));\n\n if (value instanceof Document || null == value) {\n return value;\n }\n\n // setting a populated path\n if (value instanceof oid) {\n return value;\n } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {\n throw new CastError('ObjectId', value, this.path);\n }\n\n // Handle the case where user directly sets a populated\n // path to a plain object; cast to the Model used in\n // the population query.\n var path = doc.$__fullPath(this.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n var pop = owner.populated(path, true);\n return new pop.options.model(value);\n }\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString) {\n try {\n return oid.fromString(value.toString());\n } catch (err) {\n throw new CastError('ObjectId', value, this.path);\n }\n }\n\n throw new CastError('ObjectId', value, this.path);\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "cast", - "string": "ObjectId.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "castForQuery", - "string": "ObjectId.prototype.castForQuery()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "turnOn", - "description": "auto generated ObjectId defaults" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", - "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", - "ctx": { - "type": "method", - "constructor": "ObjectId", - "name": "auto", - "string": "ObjectId.prototype.auto()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.$__._id = null;\n return v;\n}", - "ctx": { - "type": "function", - "name": "defaultId", - "string": "defaultId()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = ObjectId;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "ObjectId", - "string": "module.exports" - } - } -] -### lib/schema/string.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , utils = require('../utils')\n , Document", - "ctx": { - "type": "declaration", - "name": "SchemaType", - "value": "require('../schematype')", - "string": "SchemaType" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "inherits", - "string": "SchemaType" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    String SchemaType constructor.

    ", - "summary": "

    String SchemaType constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", - "ctx": { - "type": "function", - "name": "SchemaString", - "string": "SchemaString()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from SchemaType.

    ", - "summary": "

    Inherits from SchemaType.

    ", - "body": "" - }, - "ignore": true, - "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", - "ctx": { - "type": "property", - "constructor": "SchemaString", - "name": "__proto__", - "value": "SchemaType.prototype", - "string": "SchemaString.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[args...]", - "description": "enumeration values" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", - "summary": "

    Adds enumeration values and a coinciding validator.

    ", - "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "enum", - "string": "SchemaString.prototype.enum()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", - "summary": "

    Adds a lowercase setter.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toLowerCase();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "lowercase", - "string": "SchemaString.prototype.lowercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", - "summary": "

    Adds an uppercase setter.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toUpperCase();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "uppercase", - "string": "SchemaString.prototype.uppercase()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", - "summary": "

    Adds a trim setter.

    ", - "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.trim();\n return v;\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "trim", - "string": "SchemaString.prototype.trim()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp" - ], - "name": "regExp", - "description": "regular expression to test against" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", - "summary": "

    Sets a regexp validator.

    ", - "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "match", - "string": "SchemaString.prototype.match()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "null", - "undefined" - ], - "name": "value", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Check required

    ", - "summary": "

    Check required

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.checkRequired = function checkRequired (value, doc) {\n if (SchemaType._isRef(this, value, doc, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "checkRequired", - "string": "SchemaString.prototype.checkRequired()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts to String

    ", - "summary": "

    Casts to String

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, doc, init)) {\n // wait! we may need to cast this to a document\n\n // lazy load\n Document || (Document = require('./../document'));\n\n if (value instanceof Document || null == value) {\n return value;\n }\n\n // setting a populated path\n if ('string' == typeof value) {\n return value;\n } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {\n throw new CastError('string', value, this.path);\n }\n\n // Handle the case where user directly sets a populated\n // path to a plain object; cast to the Model used in\n // the population query.\n var path = doc.$__fullPath(this.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n var pop = owner.populated(path, true);\n return new pop.options.model(value);\n }\n\n if (value === null) {\n return value;\n }\n\n if ('undefined' !== typeof value) {\n // handle documents being passed\n if (value._id && 'string' == typeof value._id) {\n return value._id;\n }\n if (value.toString) {\n return value.toString();\n }\n }\n\n\n throw new CastError('string', value, this.path);\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "cast", - "string": "SchemaString.prototype.cast()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", - "ctx": { - "type": "function", - "name": "handleSingle", - "string": "handleSingle()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "$conditional", - "description": "" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "[val]", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts contents for queries.

    ", - "summary": "

    Casts contents for queries.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaString", - "name": "castForQuery", - "string": "SchemaString.prototype.castForQuery()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = SchemaString;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "SchemaString", - "string": "module.exports" - } - } -] -### lib/schema.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", - "ctx": { - "type": "declaration", - "name": "EventEmitter", - "value": "require('events').EventEmitter", - "string": "EventEmitter" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "definition", - "description": "" - }, - { - "type": "inherits", - "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" - }, - { - "type": "event", - "string": "`init`: Emitted after the schema is compiled into a `Model`." - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n\n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", - "summary": "

    Schema constructor.

    ", - "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n\n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n}", - "ctx": { - "type": "function", - "name": "Schema", - "string": "Schema()" - } - }, - { - "tags": [], - "description": { - "full": "

    Returns this documents _id cast to a string.

    ", - "summary": "

    Returns this documents _id cast to a string.

    ", - "body": "" - }, - "ignore": true, - "code": "function idGetter () {\n if (this.$__._id) {\n return this.$__._id;\n }\n\n return this.$__._id = null == this._id\n ? null\n : String(this._id);\n}", - "ctx": { - "type": "function", - "name": "idGetter", - "string": "idGetter()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from EventEmitter.

    ", - "summary": "

    Inherit from EventEmitter.

    ", - "body": "" - }, - "ignore": true, - "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", - "ctx": { - "type": "property", - "constructor": "Schema", - "name": "__proto__", - "value": "EventEmitter.prototype", - "string": "Schema.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "paths" - } - ], - "description": { - "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", - "summary": "

    Schema as flat paths

    ", - "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.paths;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "tree" - } - ], - "description": { - "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", - "summary": "

    Schema as a tree

    ", - "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.tree;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns default options for this schema, merged with options.

    ", - "summary": "

    Returns default options for this schema, merged with options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.defaultOptions = function (options) {\n if (options && false === options.safe) {\n options.safe = { w: 0 };\n }\n\n options = utils.options({\n strict: true\n , bufferCommands: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "defaultOptions", - "string": "Schema.prototype.defaultOptions()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "prefix", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", - "summary": "

    Adds key path / schema type pairs to this schema.

    ", - "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n } else {\n this.path(prefix + i, obj[i]); // mixed type\n }\n } else {\n this.path(prefix + i, obj[i]);\n }\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "add", - "string": "Schema.prototype.add()" - } - }, - { - "tags": [], - "description": { - "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, emit, _events, db, init, isNew, errors, schema, options, modelName, collection, _pres, _posts, toObject\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    ", - "summary": "

    Reserved document keys.

    ", - "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, emit, _events, db, init, isNew, errors, schema, options, modelName, collection, _pres, _posts, toObject\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    " - }, - "ignore": false, - "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection =\nreserved.toObject =\nreserved.emit = // EventEmitter\nreserved._events = // EventEmitter\nreserved._pres = reserved._posts = 1 // hooks.js", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "reserved", - "value": "Object.create(null)", - "string": "Schema.reserved" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "constructor", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", - "summary": "

    Gets/sets schema paths.

    ", - "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(sub, i) {\n if (!branch[sub]) branch[sub] = {};\n if ('object' != typeof branch[sub]) {\n var msg = 'Cannot set nested path `' + path + '`. '\n + 'Parent path `'\n + subpaths.slice(0, i).concat([sub]).join('.')\n + '` already set to type ' + branch[sub].name\n + '.';\n throw new Error(msg);\n }\n branch = branch[sub];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "path", - "string": "Schema.prototype.path()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "constructor" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts type arguments into Mongoose Types.

    ", - "summary": "

    Converts type arguments into Mongoose Types.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", - "ctx": { - "type": "method", - "receiver": "Schema", - "name": "interpretAsType", - "string": "Schema.interpretAsType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback function" - }, - { - "type": "return", - "types": [ - "Schema" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", - "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", - "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "eachPath", - "string": "Schema.prototype.eachPath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns an Array of path strings that are required by this schema.

    ", - "summary": "

    Returns an Array of path strings that are required by this schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "requiredPaths", - "string": "Schema.prototype.requiredPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", - "summary": "

    Returns the pathType of path for this schema.

    ", - "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pathType", - "string": "Schema.prototype.pathType()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", - "ctx": { - "type": "function", - "name": "getPositionalPath", - "string": "getPositionalPath()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "name of the document method to call later" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "args", - "description": "arguments to pass to the method" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Adds a method call to the queue.

    ", - "summary": "

    Adds a method call to the queue.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "queue", - "string": "Schema.prototype.queue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", - "summary": "

    Defines a pre hook for the document.

    ", - "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "pre", - "string": "Schema.prototype.pre()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "method", - "description": "name of the method to hook" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "callback" - }, - { - "type": "see", - "title": "hooks.js", - "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", - "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function (doc) {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", - "summary": "

    Defines a post hook for the document.

    ", - "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function (doc) {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "post", - "string": "Schema.prototype.post()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "plugin", - "description": "callback" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "opts", - "description": "" - }, - { - "type": "see", - "local": "plugins", - "visibility": "plugins" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Registers a plugin for this schema.

    ", - "summary": "

    Registers a plugin for this schema.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "plugin", - "string": "Schema.prototype.plugin()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String", - "Object" - ], - "name": "method", - "description": "name" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", - "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", - "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "method", - "string": "Schema.prototype.method()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", - "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", - "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "static", - "string": "Schema.prototype.static()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "fields", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", - "summary": "

    Defines an index (most likely compound) for this schema.

    ", - "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "index", - "string": "Schema.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "option name" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[value]", - "description": "if not passed, the current option value is returned" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets/gets a schema option.

    ", - "summary": "

    Sets/gets a schema option.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.set = function (key, value, _tags) {\n if (1 === arguments.length) {\n return this.options[key];\n }\n\n switch (key) {\n case 'read':\n this.options[key] = utils.readPref(value, _tags)\n break;\n case 'safe':\n this.options[key] = false === value\n ? { w: 0 }\n : value\n break;\n default:\n this.options[key] = value;\n }\n\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "set", - "string": "Schema.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "key", - "description": "option name" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Gets a schema option.

    ", - "summary": "

    Gets a schema option.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.get = function (key) {\n return this.options[key];\n}", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "get", - "string": "Schema.prototype.get()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Compiles indexes from fields and schema-level indexes

    ", - "summary": "

    Compiles indexes from fields and schema-level indexes

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.indexes = function () {\n 'use strict';\n\n var indexes = []\n , seenSchemas = []\n , indexTypes = '2d 2dsphere hashed'.split(' ');\n\n collectIndexes(this);\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n prefix = prefix || '';\n\n var key, path, index, field, isObject, options, type;\n var keys = Object.keys(schema.paths);\n\n for (var i = 0; i < keys.length; ++i) {\n key = keys[i];\n path = schema.paths[key];\n\n if (path instanceof Types.DocumentArray) {\n collectIndexes(path.schema, key + '.');\n } else {\n index = path._index;\n\n if (false !== index && null != index) {\n field = {};\n isObject = utils.isObject(index);\n options = isObject ? index : {};\n type = 'string' == typeof index ? index :\n isObject ? index.type :\n false;\n\n if (type && ~indexTypes.indexOf(type)) {\n field[prefix + key] = type;\n } else {\n field[prefix + key] = 1;\n }\n\n delete options.type;\n if (!('background' in options)) {\n options.background = true;\n }\n\n indexes.push([field, options]);\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "indexes", - "string": "Schema.prototype.indexes()" - } - }, - { - "tags": [], - "description": { - "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", - "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", - "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " - }, - "ignore": true, - "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", - "ctx": { - "type": "function", - "name": "fixSubIndexPaths", - "string": "fixSubIndexPaths()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

    Creates a virtual type with the given name.

    ", - "summary": "

    Creates a virtual type with the given name.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtual", - "string": "Schema.prototype.virtual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the virtual type with the given name.

    ", - "summary": "

    Returns the virtual type with the given name.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "virtualpath", - "string": "Schema.prototype.virtualpath()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", - "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", - "ctx": { - "type": "method", - "constructor": "Schema", - "name": "namedScope", - "string": "Schema.prototype.namedScope()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = Schema", - "string": "module.exports" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    The various built-in Mongoose Schema Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n\n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", - "summary": "

    The various built-in Mongoose Schema Types.

    ", - "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n\n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "Schema.Types = require('./schema/index');", - "ctx": { - "type": "property", - "receiver": "Schema", - "name": "Types", - "value": "require('./schema/index')", - "string": "Schema.Types" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" - } -] -### lib/schemadefault.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Schema = require('./schema')", - "ctx": { - "type": "declaration", - "name": "Schema", - "value": "require('./schema')", - "string": "Schema" - } - }, - { - "tags": [ - { - "type": "property", - "string": "system.profile" - }, - { - "type": "receiver", - "string": "exports" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Default model for querying the system.profiles collection.

    ", - "summary": "

    Default model for querying the system.profiles collection.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" - } -] -### lib/schematype.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');\nvar CastError = require('./error').CastError;\nvar ValidatorError = require('./error').ValidatorError;", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "[options]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[instance]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    SchemaType constructor

    ", - "summary": "

    SchemaType constructor

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", - "ctx": { - "type": "function", - "name": "SchemaType", - "string": "SchemaType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function", - "any" - ], - "name": "val", - "description": "the default value" - }, - { - "type": "return", - "types": [ - "defaultValue" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", - "summary": "

    Sets a default value for this SchemaType.

    ", - "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "default", - "string": "SchemaType.prototype.default()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "Boolean", - "String" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ loc: { type: [Number], index: '2d' })\nvar s = new Schema({ loc: { type: [Number], index: '2d', sparse: true })\nvar s = new Schema({ loc: { type: [Number], index: { type: '2d', sparse: true }})\nvar s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.date').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", - "summary": "

    Declares the index options for this schematype.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ loc: { type: [Number], index: '2d' })\nvar s = new Schema({ loc: { type: [Number], index: '2d', sparse: true })\nvar s = new Schema({ loc: { type: [Number], index: { type: '2d', sparse: true }})\nvar s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.date').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "index", - "string": "SchemaType.prototype.index()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares an unique index.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    \n\n

    NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.

    ", - "summary": "

    Declares an unique index.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    \n\n

    NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.unique = function (bool) {\n if (null == this._index || 'boolean' == typeof this._index) {\n this._index = {};\n } else if ('string' == typeof this._index) {\n this._index = { type: this._index };\n }\n\n this._index.unique = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "unique", - "string": "SchemaType.prototype.unique()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "bool", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Declares a sparse index.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", - "summary": "

    Declares a sparse index.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.sparse = function (bool) {\n if (null == this._index || 'boolean' == typeof this._index) {\n this._index = {};\n } else if ('string' == typeof this._index) {\n this._index = { type: this._index };\n }\n\n this._index.sparse = bool;\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "sparse", - "string": "SchemaType.prototype.sparse()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    \n\n

    Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.

    \n\n
    function inspector (val, schematype) {\n  if (schematype.options.required) {\n    return schematype.path + ' is required';\n  } else {\n    return val;\n  }\n}\n\nvar VirusSchema = new Schema({\n  name: { type: String, required: true, set: inspector },\n  taxonomy: { type: String, set: inspector }\n})\n\nvar Virus = db.model('Virus', VirusSchema);\nvar v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });\n\nconsole.log(v.name);     // name is required\nconsole.log(v.taxonomy); // Parvovirinae\n
    ", - "summary": "

    Adds a setter to this schematype.

    ", - "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    \n\n

    Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.

    \n\n
    function inspector (val, schematype) {\n  if (schematype.options.required) {\n    return schematype.path + ' is required';\n  } else {\n    return val;\n  }\n}\n\nvar VirusSchema = new Schema({\n  name: { type: String, required: true, set: inspector },\n  taxonomy: { type: String, set: inspector }\n})\n\nvar Virus = db.model('Virus', VirusSchema);\nvar v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });\n\nconsole.log(v.name);     // name is required\nconsole.log(v.taxonomy); // Parvovirinae\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new TypeError('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "set", - "string": "SchemaType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    \n\n

    Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.

    \n\n
    function inspector (val, schematype) {\n  if (schematype.options.required) {\n    return schematype.path + ' is required';\n  } else {\n    return schematype.path + ' is not';\n  }\n}\n\nvar VirusSchema = new Schema({\n  name: { type: String, required: true, get: inspector },\n  taxonomy: { type: String, get: inspector }\n})\n\nvar Virus = db.model('Virus', VirusSchema);\n\nVirus.findById(id, function (err, virus) {\n  console.log(virus.name);     // name is required\n  console.log(virus.taxonomy); // taxonomy is not\n})\n
    ", - "summary": "

    Adds a getter to this schematype.

    ", - "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    \n\n

    Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.

    \n\n
    function inspector (val, schematype) {\n  if (schematype.options.required) {\n    return schematype.path + ' is required';\n  } else {\n    return schematype.path + ' is not';\n  }\n}\n\nvar VirusSchema = new Schema({\n  name: { type: String, required: true, get: inspector },\n  taxonomy: { type: String, get: inspector }\n})\n\nvar Virus = db.model('Virus', VirusSchema);\n\nVirus.findById(id, function (err, virus) {\n  console.log(virus.name);     // name is required\n  console.log(virus.taxonomy); // taxonomy is not\n})\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new TypeError('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "get", - "string": "SchemaType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "RegExp", - "Function", - "Object" - ], - "name": "obj", - "description": "validator" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[error]", - "description": "optional error message" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators always receive the value to validate as their first argument and must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator (val) {\n  return val == 'something';\n}\n\nnew Schema({ name: { type: String, validate: validator }});\n\n// with a custom error message\n\nvar custom = [validator, 'validation failed']\nnew Schema({ name: { type: String, validate: custom }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The second argument is an callback function that must be passed either true or false when validation is complete.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.

    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", - "summary": "

    Adds validator(s) for this document path.

    ", - "body": "

    Validators always receive the value to validate as their first argument and must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator (val) {\n  return val == 'something';\n}\n\nnew Schema({ name: { type: String, validate: validator }});\n\n// with a custom error message\n\nvar custom = [validator, 'validation failed']\nnew Schema({ name: { type: String, validate: custom }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The second argument is an callback function that must be passed either true or false when validation is complete.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.

    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "validate", - "string": "SchemaType.prototype.validate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "required", - "description": "enable/disable the validator" - }, - { - "type": "return", - "types": [ - "SchemaType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", - "summary": "

    Adds a required validator to this schematype.

    ", - "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v, this);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "required", - "string": "SchemaType.prototype.required()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "the scope which callback are executed" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Gets the default value

    ", - "summary": "

    Gets the default value

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "getDefault", - "string": "SchemaType.prototype.getDefault()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies setters

    ", - "summary": "

    Applies setters

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, scope, init)) {\n return init\n ? value\n : this.cast(value, scope, init, priorVal);\n }\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applySetters", - "string": "SchemaType.prototype.applySetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Applies getters to a value

    ", - "summary": "

    Applies getters to a value

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, scope, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "applyGetters", - "string": "SchemaType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", - "summary": "

    Sets default select() behavior for this path.

    ", - "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "select", - "string": "SchemaType.prototype.select()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", - "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (ok, msg, val) {\n if (err) return;\n if (ok === undefined || ok) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg, val));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message, value);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (ok) {\n validate(ok, message, value);\n });\n } else {\n validate(validator.call(scope, value), message, value);\n }\n }\n });\n};", - "ctx": { - "type": "method", - "constructor": "SchemaType", - "name": "doValidate", - "string": "SchemaType.prototype.doValidate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "SchemaType" - ], - "name": "self", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "init", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determines if value is a valid Reference.

    ", - "summary": "

    Determines if value is a valid Reference.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "SchemaType._isRef = function (self, value, doc, init) {\n // fast path\n var ref = init && self.options && self.options.ref;\n\n if (!ref && doc && doc.$__fullPath) {\n // checks for\n // - this populated with adhoc model and no ref was set in schema OR\n // - setting / pushing values after population\n var path = doc.$__fullPath(self.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n ref = owner.populated(path);\n }\n\n if (ref) {\n if (null == value) return true;\n if (!Buffer.isBuffer(value) && // buffers are objects too\n 'Binary' != value._bsontype // raw binary value from the db\n && utils.isObject(value) // might have deselected _id in population query\n ) {\n return true;\n }\n }\n\n return false;\n}", - "ctx": { - "type": "method", - "receiver": "SchemaType", - "name": "_isRef", - "string": "SchemaType._isRef()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = SchemaType", - "string": "module.exports" - } - } -] -### lib/statemachine.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var utils = require('./utils');", - "ctx": { - "type": "declaration", - "name": "utils", - "value": "require('./utils')", - "string": "utils" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", - "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", - "ctx": { - "type": "declaration", - "name": "StateMachine", - "value": "module.exports = exports = function StateMachine () {", - "string": "StateMachine" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "subclass constructor" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", - "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", - "ctx": { - "type": "method", - "receiver": "StateMachine", - "name": "ctor", - "string": "StateMachine.ctor()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", - "summary": "

    This function is wrapped by the state change functions

    ", - "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_changeState", - "string": "StateMachine.prototype._changeState()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "clear", - "string": "StateMachine.prototype.clear()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "state", - "description": "that we want to check for." - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", - "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "some", - "string": "StateMachine.prototype.some()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "iterMethod", - "description": "is either 'forEach' or 'map'" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", - "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "_iter", - "string": "StateMachine.prototype._iter()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", - "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", - "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "forEach", - "string": "StateMachine.prototype.forEach()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "[state]", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", - "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", - "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " - }, - "isPrivate": false, - "ignore": true, - "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", - "ctx": { - "type": "method", - "constructor": "StateMachine", - "name": "map", - "string": "StateMachine.prototype.map()" - } - } -] -### lib/types/array.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');\nvar utils = require('../utils');\nvar isMongooseObject = utils.isMongooseObject;", - "ctx": { - "type": "declaration", - "name": "EmbeddedDocument", - "value": "require('./embedded')", - "string": "EmbeddedDocument" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Array" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", - "summary": "

    Mongoose Array constructor.

    ", - "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseArray", - "string": "MongooseArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Array

    ", - "summary": "

    Inherit from Array

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseArray.prototype = new Array;", - "ctx": { - "type": "property", - "receiver": "MongooseArray", - "name": "prototype", - "value": "new Array", - "string": "MongooseArray.prototype" - } - }, - { - "tags": [ - { - "type": "property", - "string": "_atomics" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Stores a queue of atomic operations to perform

    ", - "summary": "

    Stores a queue of atomic operations to perform

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._atomics;" - }, - { - "tags": [ - { - "type": "property", - "string": "_parent" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Parent owner document

    ", - "summary": "

    Parent owner document

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._parent;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "value", - "description": "" - }, - { - "type": "return", - "types": [ - "value" - ], - "description": "the casted value" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Casts a member based on this arrays schema.

    ", - "summary": "

    Casts a member based on this arrays schema.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._cast = function (value) {\n var owner = this._owner;\n var populated = false;\n var Model;\n\n if (this._parent) {\n // if a populated array, we must cast to the same model\n // instance as specified in the original query.\n if (!owner) {\n owner = this._owner = this._parent.ownerDocument\n ? this._parent.ownerDocument()\n : this._parent;\n }\n\n populated = owner.populated(this._path, true);\n }\n\n if (populated && null != value) {\n // cast to the populated Models schema\n var Model = populated.options.model;\n\n // only objects are permitted so we can safely assume that\n // non-objects are to be interpreted as _id\n if (Buffer.isBuffer(value) ||\n value instanceof ObjectId || !utils.isObject(value)) {\n value = { _id: value };\n }\n\n value = new Model(value);\n return this._schema.caster.cast(value, this._parent, true)\n }\n\n return this._schema.caster.cast(value, this._parent, false)\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_cast", - "string": "MongooseArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "EmbeddedDocument" - ], - "name": "embeddedDoc", - "description": "the embedded doc that invoked this method on the Array" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "embeddedPath", - "description": "the path which changed in the embeddedDoc" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", - "summary": "

    Marks this array as modified.

    ", - "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._markModified = function (elem, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n dirtyPath = this._path;\n\n if (arguments.length) {\n if (null != embeddedPath) {\n // an embedded doc bubbled up the change\n dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;\n } else {\n // directly set an index\n dirtyPath = dirtyPath + '.' + elem;\n }\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_markModified", - "string": "MongooseArray.prototype._markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "op", - "description": "operation" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "val", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Register an atomic operation with the parent.

    ", - "summary": "

    Register an atomic operation with the parent.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (this._atomics.$set ||\n Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "_registerAtomic", - "string": "MongooseArray.prototype._registerAtomic()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "method", - "string": "$__getAtomics" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.

    \n\n

    If no atomics exist, we return all array values after conversion.

    ", - "summary": "

    Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.

    ", - "body": "

    If no atomics exist, we return all array values after conversion.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype.$__getAtomics = function () {\n var ret = [];\n var keys = Object.keys(this._atomics);\n var i = keys.length;\n\n if (0 === i) {\n ret[0] = ['$set', this.toObject({ depopulate: 1 })];\n return ret;\n }\n\n while (i--) {\n var op = keys[i];\n var val = this._atomics[op];\n\n // the atomic values which are arrays are not MongooseArrays. we\n // need to convert their elements as if they were MongooseArrays\n // to handle populated arrays versus DocumentArrays properly.\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (Array.isArray(val)) {\n val = this.toObject.call(val, { depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n if ('$addToSet' == op) {\n val = { $each: val }\n }\n\n ret.push([op, val]);\n }\n\n return ret;\n}" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", - "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "hasAtomics", - "string": "MongooseArray.prototype.hasAtomics()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#push with proper change tracking.

    ", - "summary": "

    Wraps Array#push with proper change tracking.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "push", - "string": "MongooseArray.prototype.push()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Pushes items to the array non-atomically.

    ", - "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "nonAtomicPush", - "string": "MongooseArray.prototype.nonAtomicPush()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "method", - "string": "$pop" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", - "summary": "

    Pops the array atomically at most one time per document save().

    ", - "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n this._markModified();\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" - }, - { - "tags": [ - { - "type": "see", - "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", - "visibility": "MongooseArray#$pop" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#pop with proper change tracking.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pop", - "string": "MongooseArray.prototype.pop()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "method", - "string": "$shift" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" - } - ], - "description": { - "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", - "summary": "

    Atomically shifts the array at most one time per document save().

    ", - "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n this._markModified();\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#shift with proper change tracking.

    ", - "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "shift", - "string": "MongooseArray.prototype.shift()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Pulls items from the array atomically.

    \n\n

    Examples:

    \n\n
    doc.array.pull(ObjectId)\ndoc.array.pull({ _id: 'someId' })\ndoc.array.pull(36)\ndoc.array.pull('tag 1', 'tag 2')\n
    \n\n

    To remove a document from a subdocument array we may pass an object with a matching _id.

    \n\n
    doc.subdocs.push({ _id: 4815162342 })\ndoc.subdocs.pull({ _id: 4815162342 }) // removed\n
    \n\n

    Or we may passing the _id directly and let mongoose take care of it.

    \n\n
    doc.subdocs.push({ _id: 4815162342 })\ndoc.subdocs.pull(4815162342); // works\n
    ", - "summary": "

    Pulls items from the array atomically.

    ", - "body": "

    Examples:

    \n\n
    doc.array.pull(ObjectId)\ndoc.array.pull({ _id: 'someId' })\ndoc.array.pull(36)\ndoc.array.pull('tag 1', 'tag 2')\n
    \n\n

    To remove a document from a subdocument array we may pass an object with a matching _id.

    \n\n
    doc.subdocs.push({ _id: 4815162342 })\ndoc.subdocs.pull({ _id: 4815162342 }) // removed\n
    \n\n

    Or we may passing the _id directly and let mongoose take care of it.

    \n\n
    doc.subdocs.push({ _id: 4815162342 })\ndoc.subdocs.pull(4815162342); // works\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n this._markModified();\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "pull", - "string": "MongooseArray.prototype.pull()" - } - }, - { - "tags": [ - { - "type": "see", - "local": "MongooseArray#pull #types_array_MongooseArray-pull", - "visibility": "MongooseArray#pull" - }, - { - "type": "see", - "title": "mongodb", - "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", - "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" - }, - { - "type": "api", - "visibility": "public" - }, - { - "type": "memberOf", - "parent": "MongooseArray" - }, - { - "type": "method", - "string": "remove" - } - ], - "description": { - "full": "

    Alias of pull

    ", - "summary": "

    Alias of pull

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.remove = MongooseArray.prototype.pull;", - "ctx": { - "type": "property", - "constructor": "MongooseArray", - "name": "remove", - "value": "MongooseArray.prototype.pull", - "string": "MongooseArray.prototyperemove" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#splice with proper change tracking and casting.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#splice with proper change tracking and casting.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.splice = function splice () {\n var ret, vals, i;\n\n if (arguments.length) {\n vals = [];\n for (i = 0; i < arguments.length; ++i) {\n vals[i] = i < 2\n ? arguments[i]\n : this._cast(arguments[i]);\n }\n ret = [].splice.apply(this, vals);\n this._registerAtomic('$set', this);\n this._markModified();\n }\n\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "splice", - "string": "MongooseArray.prototype.splice()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#unshift with proper change tracking.

    ", - "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return this.length;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "unshift", - "string": "MongooseArray.prototype.unshift()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", - "summary": "

    Wraps Array#sort with proper change tracking.

    ", - "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "sort", - "string": "MongooseArray.prototype.sort()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "[args...]", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "the values that were added" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", - "summary": "

    Adds values to the array if not already present.

    ", - "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n this._markModified();\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "addToSet", - "string": "MongooseArray.prototype.addToSet()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Sets the casted val at index i and marks the array modified.

    \n\n

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    ", - "summary": "

    Sets the casted val at index i and marks the array modified.

    ", - "body": "

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.set = function set (i, val) {\n this[i] = this._cast(val);\n this._markModified(i);\n return this;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "set", - "string": "MongooseArray.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a native js Array.

    ", - "summary": "

    Returns a native js Array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate) {\n return this.map(function (doc) {\n // this is called on populated arrays too\n return doc instanceof Document\n ? doc._id\n : doc\n });\n }\n\n return this.slice()\n}", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "toObject", - "string": "MongooseArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "inspect", - "string": "MongooseArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the item to look for" - }, - { - "type": "return", - "types": [ - "Number" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Return the index of obj or -1 if not found.

    ", - "summary": "

    Return the index of obj or -1 if not found.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseArray", - "name": "indexOf", - "string": "MongooseArray.prototype.indexOf()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = exports = MongooseArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "exports = MongooseArray", - "string": "module.exports" - } - } -] -### lib/types/buffer.js -[ - { - "tags": [], - "description": { - "full": "

    Access driver.

    ", - "summary": "

    Access driver.

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Binary = require(driver + '/binary');", - "ctx": { - "type": "declaration", - "name": "Binary", - "value": "require(driver + '/binary')", - "string": "Binary" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "encode", - "description": "" - }, - { - "type": "param", - "types": [ - "Number" - ], - "name": "offset", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "inherits", - "string": "Buffer" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", - "summary": "

    Mongoose Buffer constructor.

    ", - "body": "

    Values always have to be passed to the constructor to initialize.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", - "ctx": { - "type": "function", - "name": "MongooseBuffer", - "string": "MongooseBuffer()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Buffer.

    ", - "summary": "

    Inherit from Buffer.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.prototype = new Buffer(0);", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "prototype", - "value": "new Buffer(0)", - "string": "MongooseBuffer.prototype" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - }, - { - "type": "property", - "string": "_parent" - } - ], - "description": { - "full": "

    Parent owner document

    ", - "summary": "

    Parent owner document

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._parent;" - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Marks this buffer as modified.

    ", - "summary": "

    Marks this buffer as modified.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "_markModified", - "string": "MongooseBuffer.prototype._markModified()" - } - }, - { - "tags": [], - "description": { - "full": "

    Writes the buffer.

    ", - "summary": "

    Writes the buffer.

    ", - "body": "" - }, - "ignore": false, - "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "write", - "string": "MongooseBuffer.prototype.write()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "MongooseBuffer" - ], - "description": "" - }, - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "target", - "description": "" - } - ], - "description": { - "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", - "summary": "

    Copies the buffer.

    ", - "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "copy", - "string": "MongooseBuffer.prototype.copy()" - } - }, - { - "tags": [], - "description": { - "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", - "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", - "body": "" - }, - "ignore": true, - "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" - }, - { - "tags": [ - { - "type": "see", - "title": "", - "url": "http://bsonspec.org/#/specification", - "visibility": "http://bsonspec.org/#/specification" - }, - { - "type": "param", - "types": [ - "Hex" - ], - "name": "[subtype]", - "description": "" - }, - { - "type": "return", - "types": [ - "Binary" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", - "summary": "

    Converts this buffer to its Binary type representation.

    ", - "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.toObject = function (options) {\n var subtype = 'number' == typeof options\n ? options\n : 0x00;\n return new Binary(this, subtype);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "toObject", - "string": "MongooseBuffer.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Buffer" - ], - "name": "other", - "description": "" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - } - ], - "description": { - "full": "

    Determines if this buffer is equals to other buffer

    ", - "summary": "

    Determines if this buffer is equals to other buffer

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseBuffer.prototype.equals = function (other) {\n if (!Buffer.isBuffer(other)) {\n return false;\n }\n\n if (this.length !== other.length) {\n return false;\n }\n\n for (var i = 0; i < this.length; ++i) {\n if (this[i] !== other[i]) return false;\n }\n\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "MongooseBuffer", - "name": "equals", - "string": "MongooseBuffer.prototype.equals()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", - "ctx": { - "type": "property", - "receiver": "MongooseBuffer", - "name": "Binary", - "value": "Binary", - "string": "MongooseBuffer.Binary" - } - } -] -### lib/types/documentarray.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , utils = require('../utils')\n , util = require('util')", - "ctx": { - "type": "declaration", - "name": "MongooseArray", - "value": "require('./array')", - "string": "MongooseArray" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "values", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path to this array" - }, - { - "type": "param", - "types": [ - "Document" - ], - "name": "doc", - "description": "parent document" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "MongooseDocumentArray" - ], - "description": "" - }, - { - "type": "inherits", - "string": "MongooseArray" - }, - { - "type": "see", - "title": "", - "url": "http://bit.ly/f6CnZU", - "visibility": "http://bit.ly/f6CnZU" - } - ], - "description": { - "full": "

    DocumentArray constructor

    ", - "summary": "

    DocumentArray constructor

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", - "ctx": { - "type": "function", - "name": "MongooseDocumentArray", - "string": "MongooseDocumentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherits from MongooseArray

    ", - "summary": "

    Inherits from MongooseArray

    ", - "body": "" - }, - "ignore": true, - "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", - "ctx": { - "type": "property", - "constructor": "MongooseDocumentArray", - "name": "__proto__", - "value": "MongooseArray.prototype", - "string": "MongooseDocumentArray.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Overrides MongooseArray#cast

    ", - "summary": "

    Overrides MongooseArray#cast

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype._cast = function (value) {\n if (value instanceof this._schema.casterConstructor) {\n return value;\n }\n\n // handle cast('string') or cast(ObjectId) etc.\n // only objects are permitted so we can safely assume that\n // non-objects are to be interpreted as _id\n if (Buffer.isBuffer(value) ||\n value instanceof ObjectId || !utils.isObject(value)) {\n value = { _id: value };\n }\n\n return new this._schema.casterConstructor(value, this);\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "_cast", - "string": "MongooseDocumentArray.prototype._cast()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "EmbeddedDocument", - "null" - ], - "description": "the subdocuent or null if not found." - }, - { - "type": "param", - "types": [ - "ObjectId", - "String", - "Number", - "Buffer" - ], - "name": "id", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Searches array items for the first document with a matching _id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", - "summary": "

    Searches array items for the first document with a matching _id.

    ", - "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "id", - "string": "MongooseDocumentArray.prototype.id()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", - "summary": "

    Returns a native js Array of plain js objects

    ", - "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "toObject", - "string": "MongooseDocumentArray.prototype.toObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "inspect", - "string": "MongooseDocumentArray.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the value to cast to this arrays SubDocument schema" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", - "summary": "

    Creates a subdocument casted to this schema.

    ", - "body": "

    This is the same subdocument constructor used for casting.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "create", - "string": "MongooseDocumentArray.prototype.create()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "event", - "description": "" - }, - { - "type": "return", - "types": [ - "Function" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Creates a fn that notifies all child docs of event.

    ", - "summary": "

    Creates a fn that notifies all child docs of event.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n if (!self[i]) continue;\n self[i].emit(event, val);\n }\n }\n}", - "ctx": { - "type": "method", - "constructor": "MongooseDocumentArray", - "name": "notify", - "string": "MongooseDocumentArray.prototype.notify()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = MongooseDocumentArray;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "MongooseDocumentArray", - "string": "module.exports" - } - } -] -### lib/types/embedded.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var Document = require('../document')\n , inspect = require('util').inspect;", - "ctx": { - "type": "declaration", - "name": "Document", - "value": "require('../document')", - "string": "Document" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "js object returned from the db" - }, - { - "type": "param", - "types": [ - "MongooseDocumentArray" - ], - "name": "parentArr", - "description": "the parent array of this document" - }, - { - "type": "param", - "types": [ - "Boolean" - ], - "name": "skipId", - "description": "" - }, - { - "type": "inherits", - "string": "Document" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    EmbeddedDocument constructor.

    ", - "summary": "

    EmbeddedDocument constructor.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", - "ctx": { - "type": "function", - "name": "EmbeddedDocument", - "string": "EmbeddedDocument()" - } - }, - { - "tags": [], - "description": { - "full": "

    Inherit from Document

    ", - "summary": "

    Inherit from Document

    ", - "body": "" - }, - "ignore": true, - "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", - "ctx": { - "type": "property", - "constructor": "EmbeddedDocument", - "name": "__proto__", - "value": "Document.prototype", - "string": "EmbeddedDocument.prototype__proto__" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the path which changed" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", - "summary": "

    Marks the embedded doc modified.

    ", - "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this.$__.activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "markModified", - "string": "EmbeddedDocument.prototype.markModified()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "return", - "types": [ - "EmbeddedDocument" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", - "summary": "

    Used as a stub for hooks.js

    ", - "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "save", - "string": "EmbeddedDocument.prototype.save()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "[fn]", - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Removes the subdocument from its parent array.

    ", - "summary": "

    Removes the subdocument from its parent array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' +\n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "remove", - "string": "EmbeddedDocument.prototype.remove()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Override #update method of parent documents.

    ", - "summary": "

    Override #update method of parent documents.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "update", - "string": "EmbeddedDocument.prototype.update()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Helper for console.log

    ", - "summary": "

    Helper for console.log

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "inspect", - "string": "EmbeddedDocument.prototype.inspect()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "the field to invalidate" - }, - { - "type": "param", - "types": [ - "String", - "Error" - ], - "name": "err", - "description": "error which states the reason `path` was invalid" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Marks a path as invalid, causing validation to fail.

    ", - "summary": "

    Marks a path as invalid, causing validation to fail.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.invalidate = function (path, err, val, first) {\n if (!this.__parent) {\n var msg = 'Unable to invalidate a subdocument that has not been added to an array.'\n throw new Error(msg);\n }\n\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n\n // sniffing arguments:\n // need to check if user passed a value to keep\n // our error message clean.\n if (2 < arguments.length) {\n this.__parent.invalidate(fullPath, err, val);\n } else {\n this.__parent.invalidate(fullPath, err);\n }\n\n if (first)\n this.$__.validationError = this.ownerDocument().$__.validationError;\n return true;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "invalidate", - "string": "EmbeddedDocument.prototype.invalidate()" - } - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Document" - ], - "description": "" - } - ], - "description": { - "full": "

    Returns the top level document of this sub-document.

    ", - "summary": "

    Returns the top level document of this sub-document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n if (this.$__.ownerDocument) {\n return this.$__.ownerDocument;\n }\n\n var parent = this.__parent;\n if (!parent) return this;\n\n while (parent.__parent) {\n parent = parent.__parent;\n }\n\n return this.$__.ownerDocument = parent;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "ownerDocument", - "string": "EmbeddedDocument.prototype.ownerDocument()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "[path]", - "description": "" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "method", - "string": "$__fullPath" - }, - { - "type": "memberOf", - "parent": "EmbeddedDocument" - } - ], - "description": { - "full": "

    Returns the full path to this document. If optional path is passed, it is appended to the full path.

    ", - "summary": "

    Returns the full path to this document. If optional path is passed, it is appended to the full path.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "EmbeddedDocument.prototype.$__fullPath = function (path) {\n if (!this.$__.fullPath) {\n var parent = this;\n if (!parent.__parent) return path;\n\n var paths = [];\n while (parent.__parent) {\n paths.unshift(parent.__parentArray._path);\n parent = parent.__parent;\n }\n\n this.$__.fullPath = paths.join('.');\n\n if (!this.$__.ownerDocument) {\n // optimization\n this.$__.ownerDocument = parent;\n }\n }\n\n return path\n ? this.$__.fullPath + '.' + path\n : this.$__.fullPath;\n}" - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns this sub-documents parent document.

    ", - "summary": "

    Returns this sub-documents parent document.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parent", - "string": "EmbeddedDocument.prototype.parent()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Returns this sub-documents parent array.

    ", - "summary": "

    Returns this sub-documents parent array.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", - "ctx": { - "type": "method", - "constructor": "EmbeddedDocument", - "name": "parentArray", - "string": "EmbeddedDocument.prototype.parentArray()" - } - }, - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = EmbeddedDocument;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "EmbeddedDocument", - "string": "module.exports" - } - } -] -### lib/types/index.js -[ - { - "tags": [], - "description": { - "full": "

    Module exports.

    ", - "summary": "

    Module exports.

    ", - "body": "" - }, - "ignore": true, - "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "Array", - "value": "require('./array')", - "string": "exports.Array" - } - } -] -### lib/types/objectid.js -[ - { - "tags": [], - "description": { - "full": "

    Access driver.

    ", - "summary": "

    Access driver.

    ", - "body": "" - }, - "ignore": true, - "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", - "ctx": { - "type": "declaration", - "name": "driver", - "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", - "string": "driver" - } - }, - { - "tags": [ - { - "type": "constructor", - "string": "ObjectId" - } - ], - "description": { - "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", - "summary": "

    ObjectId type constructor

    ", - "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", - "ctx": { - "type": "declaration", - "name": "ObjectId", - "value": "require(driver + '/objectid')", - "string": "ObjectId" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId", - "HexString" - ], - "name": "str", - "description": "" - }, - { - "type": "static", - "string": "fromString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "ObjectId" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Creates an ObjectId from str

    ", - "summary": "

    Creates an ObjectId from str

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.fromString;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "ObjectId" - ], - "name": "oid", - "description": "ObjectId instance" - }, - { - "type": "static", - "string": "toString" - }, - { - "type": "receiver", - "string": "ObjectId" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts oid to a string.

    ", - "summary": "

    Converts oid to a string.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": false, - "code": "ObjectId.toString;" - } -] -### lib/utils.js -[ - { - "tags": [], - "description": { - "full": "

    Module dependencies.

    ", - "summary": "

    Module dependencies.

    ", - "body": "" - }, - "ignore": true, - "code": "var ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , sliced = require('sliced')\n , mpath = require('mpath')\n , MongooseBuffer\n , MongooseArray\n , Document", - "ctx": { - "type": "declaration", - "name": "ReadPref", - "value": "require('mongodb').ReadPreference", - "string": "ReadPref" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "name", - "description": "a model name" - }, - { - "type": "return", - "types": [ - "String" - ], - "description": "a collection name" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Produces a collection name from model name.

    ", - "summary": "

    Produces a collection name from model name.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "toCollectionName", - "string": "exports.toCollectionName()" - } - }, - { - "tags": [ - { - "type": "deprecated", - "string": "remove in 4.x gh-1350" - } - ], - "description": { - "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", - "summary": "

    Pluralization rules.

    ", - "body": "

    These rules are applied while processing the argument to toCollectionName.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "pluralization", - "value": "[", - "string": "exports.pluralization" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", - "summary": "

    Uncountable words.

    ", - "body": "

    These words are applied while processing the argument to toCollectionName.

    " - }, - "isPrivate": false, - "ignore": false, - "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news',\n 'expertise',\n 'status',\n 'media'\n];\nvar uncountables = exports.uncountables;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "uncountables", - "value": "[", - "string": "exports.uncountables" - } - }, - { - "tags": [ - { - "type": "author", - "string": "TJ Holowaychuk (extracted from _ext.js_)" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "string", - "description": "to pluralize" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Pluralize function.

    ", - "summary": "

    Pluralize function.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", - "ctx": { - "type": "function", - "name": "pluralize", - "string": "pluralize()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "a", - "description": "a value to compare to `b`" - }, - { - "type": "param", - "types": [ - "any" - ], - "name": "b", - "description": "a value to compare to `a`" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", - "summary": "

    Determines if a and b are deep equal.

    ", - "body": "

    Modified from node/lib/assert.js

    " - }, - "isPrivate": true, - "ignore": true, - "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (a instanceof RegExp && b instanceof RegExp) {\n return a.source == b.source &&\n a.ignoreCase == b.ignoreCase &&\n a.multiline == b.multiline &&\n a.global == b.global;\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "deepEqual", - "string": "exports.deepEqual()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "the object to clone" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the cloned object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Object clone with Mongoose natives support.

    \n\n

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    ", - "summary": "

    Object clone with Mongoose natives support.

    ", - "body": "

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    " - }, - "isPrivate": true, - "ignore": true, - "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name) {\n var flags = [];\n if (obj.global) flags.push('g');\n if (obj.multiline) flags.push('m');\n if (obj.ignoreCase) flags.push('i');\n return new RegExp(obj.source, flags.join(''));\n }\n\n if (obj instanceof ObjectId)\n return new ObjectId(obj.id);\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "clone", - "string": "exports.clone()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", - "ctx": { - "type": "function", - "name": "cloneObject", - "string": "cloneObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "defaults", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "options", - "description": "" - }, - { - "type": "return", - "types": [ - "Object" - ], - "description": "the merged object" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Shallow copies defaults into options.

    ", - "summary": "

    Shallow copies defaults into options.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "options", - "string": "exports.options()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Generates a random string

    ", - "summary": "

    Generates a random string

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "random", - "string": "exports.random()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "to", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "from", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Merges from into to without overwriting existing properties.

    ", - "summary": "

    Merges from into to without overwriting existing properties.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n if (exports.isObject(from[key])) {\n merge(to[key], from[key]);\n } else {\n to[key] = from[key];\n }\n }\n }\n};", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "merge", - "string": "exports.merge()" - } - }, - { - "tags": [], - "description": { - "full": "

    toString helper

    ", - "summary": "

    toString helper

    ", - "body": "" - }, - "ignore": true, - "code": "var toString = Object.prototype.toString;", - "ctx": { - "type": "declaration", - "name": "toString", - "value": "Object.prototype.toString", - "string": "toString" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object", - "Array", - "String", - "Function", - "RegExp", - "any" - ], - "name": "arg", - "description": "" - }, - { - "type": "api", - "visibility": "private" - }, - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - } - ], - "description": { - "full": "

    Determines if arg is an object.

    ", - "summary": "

    Determines if arg is an object.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "exports.isObject = function (arg) {\n return '[object Object]' == toString.call(arg);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isObject", - "string": "exports.isObject()" - } - }, - { - "tags": [ - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", - "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "exports.args = sliced;", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "args", - "value": "sliced", - "string": "exports.args" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "callback", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", - "summary": "

    process.nextTick helper.

    ", - "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " - }, - "isPrivate": true, - "ignore": true, - "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "tick", - "string": "exports.tick()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "any" - ], - "name": "v", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", - "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", - "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " - }, - "isPrivate": true, - "ignore": true, - "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isMongooseObject", - "string": "exports.isMongooseObject()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "object", - "description": "" - }, - { - "type": "api", - "visibility": "private" - } - ], - "description": { - "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", - "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", - "body": "" - }, - "isPrivate": true, - "ignore": true, - "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expireAfterSeconds = when;\n delete object.expires;\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "expires", - "string": "exports.expires()" - } - }, - { - "tags": [ - { - "type": "TODO", - "string": "move this into the driver layer" - }, - { - "type": "param", - "types": [ - "String", - "Array" - ], - "name": "pref", - "description": "" - }, - { - "type": "param", - "types": [ - "Array" - ], - "name": "[tags]", - "description": "" - } - ], - "description": { - "full": "

    Converts arguments to ReadPrefs the driver
    can understand.

    ", - "summary": "

    Converts arguments to ReadPrefs the driver
    can understand.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "exports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "readPref", - "string": "exports.readPref()" - } - }, - { - "tags": [], - "description": { - "full": "

    Populate options constructor

    ", - "summary": "

    Populate options constructor

    ", - "body": "" - }, - "ignore": true, - "code": "function PopulateOptions (path, select, match, options, model) {\n this.path = path;\n this.match = match;\n this.select = select;\n this.options = options;\n this.model = model;\n this._docs = {};\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;\n\n// expose\nexports.PopulateOptions = PopulateOptions;", - "ctx": { - "type": "function", - "name": "PopulateOptions", - "string": "PopulateOptions()" - } - }, - { - "tags": [], - "description": { - "full": "

    populate helper

    ", - "summary": "

    populate helper

    ", - "body": "" - }, - "ignore": true, - "code": "exports.populate = function populate (path, select, model, match, options) {\n // The order of select/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (select could be\n // an array, string, or object literal).\n\n // might have passed an object specifying all arguments\n if (1 === arguments.length) {\n if (path instanceof PopulateOptions) {\n return [path];\n }\n\n if (Array.isArray(path)) {\n return path.map(function(o){\n return exports.populate(o)[0];\n });\n }\n\n if (exports.isObject(path)) {\n match = path.match;\n options = path.options;\n select = path.select;\n model = path.model;\n path = path.path;\n }\n } else if ('string' !== typeof model) {\n options = match;\n match = model;\n model = undefined;\n }\n\n if ('string' != typeof path) {\n throw new TypeError('utils.populate: invalid path. Expected string. Got typeof `' + typeof path + '`');\n }\n\n var ret = [];\n var paths = path.split(' ');\n for (var i = 0; i < paths.length; ++i) {\n ret.push(new PopulateOptions(paths[i], select, match, options, model));\n }\n\n return ret;\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "populate", - "string": "exports.populate()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - } - ], - "description": { - "full": "

    Return the value of obj at the given path.

    ", - "summary": "

    Return the value of obj at the given path.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "exports.getValue = function (path, obj, map) {\n return mpath.get(path, obj, '_doc', map);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "getValue", - "string": "exports.getValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "String" - ], - "name": "path", - "description": "" - }, - { - "type": "param", - "types": [ - "Anything" - ], - "name": "val", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - } - ], - "description": { - "full": "

    Sets the value of obj at the given path.

    ", - "summary": "

    Sets the value of obj at the given path.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "exports.setValue = function (path, val, obj, map) {\n mpath.set(path, val, obj, '_doc', map);\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "setValue", - "string": "exports.setValue()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "o", - "description": "" - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Returns an array of values from object o.

    ", - "summary": "

    Returns an array of values from object o.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "exports.object = {};\nexports.object.vals = function vals (o) {\n var keys = Object.keys(o)\n , i = keys.length\n , ret = [];\n\n while (i--) {\n ret.push(o[keys[i]]);\n }\n\n return ret;\n}", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "object", - "value": "{}", - "string": "exports.object" - } - }, - { - "tags": [], - "description": { - "full": "

    @see exports.options

    ", - "summary": "

    @see exports.options

    ", - "body": "" - }, - "ignore": true, - "code": "exports.object.shallowCopy = exports.options;" - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "obj", - "description": "" - }, - { - "type": "param", - "types": [ - "String" - ], - "name": "prop", - "description": "" - } - ], - "description": { - "full": "

    Safer helper for hasOwnProperty checks

    ", - "summary": "

    Safer helper for hasOwnProperty checks

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "exports.object.hasOwnProperty = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}" - }, - { - "tags": [ - { - "type": "return", - "types": [ - "Boolean" - ], - "description": "" - } - ], - "description": { - "full": "

    Determine if val is null or undefined

    ", - "summary": "

    Determine if val is null or undefined

    ", - "body": "" - }, - "isPrivate": false, - "ignore": true, - "code": "exports.isNullOrUndefined = function (val) {\n return null == val\n}", - "ctx": { - "type": "method", - "receiver": "exports", - "name": "isNullOrUndefined", - "string": "exports.isNullOrUndefined()" - } - }, - { - "tags": [], - "description": { - "full": "

    ignore

    ", - "summary": "

    ignore

    ", - "body": "" - }, - "ignore": true, - "code": "exports.array = {};", - "ctx": { - "type": "property", - "receiver": "exports", - "name": "array", - "value": "{}", - "string": "exports.array" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Array" - ], - "name": "arr", - "description": "" - }, - { - "type": "param", - "types": [ - "Function" - ], - "name": "[filter]", - "description": "If passed, will be invoked with each item in the array. If `filter` returns a falsey value, the item will not be included in the results." - }, - { - "type": "return", - "types": [ - "Array" - ], - "description": "" - }, - { - "type": "private", - "string": "" - } - ], - "description": { - "full": "

    Flattens an array.

    \n\n

    [ 1, [ 2, 3, [4] ]] -> [1,2,3,4]

    ", - "summary": "

    Flattens an array.

    ", - "body": "

    [ 1, [ 2, 3, [4] ]] -> [1,2,3,4]

    " - }, - "isPrivate": false, - "ignore": true, - "code": "exports.array.flatten = function flatten (arr, filter, ret) {\n ret || (ret = []);\n\n arr.forEach(function (item) {\n if (Array.isArray(item)) {\n flatten(item, filter, ret);\n } else {\n if (!filter || filter(item)) {\n ret.push(item);\n }\n }\n });\n\n return ret;\n}" - } -] -### lib/virtualtype.js -[ - { - "tags": [ - { - "type": "parma", - "string": "{Object} options" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", - "summary": "

    VirtualType constructor

    ", - "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", - "ctx": { - "type": "function", - "name": "VirtualType", - "string": "VirtualType()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", - "summary": "

    Defines a getter.

    ", - "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "get", - "string": "VirtualType.prototype.get()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Function" - ], - "name": "fn", - "description": "" - }, - { - "type": "return", - "types": [ - "VirtualType" - ], - "description": "this" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", - "summary": "

    Defines a setter.

    ", - "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "set", - "string": "VirtualType.prototype.set()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all getters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Applies getters to value using optional scope.

    ", - "summary": "

    Applies getters to value using optional scope.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applyGetters", - "string": "VirtualType.prototype.applyGetters()" - } - }, - { - "tags": [ - { - "type": "param", - "types": [ - "Object" - ], - "name": "value", - "description": "" - }, - { - "type": "param", - "types": [ - "Object" - ], - "name": "scope", - "description": "" - }, - { - "type": "return", - "types": [ - "any" - ], - "description": "the value after applying all setters" - }, - { - "type": "api", - "visibility": "public" - } - ], - "description": { - "full": "

    Applies setters to value using optional scope.

    ", - "summary": "

    Applies setters to value using optional scope.

    ", - "body": "" - }, - "isPrivate": false, - "ignore": false, - "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", - "ctx": { - "type": "method", - "constructor": "VirtualType", - "name": "applySetters", - "string": "VirtualType.prototype.applySetters()" - } - }, - { - "tags": [], - "description": { - "full": "

    exports

    ", - "summary": "

    exports

    ", - "body": "" - }, - "ignore": true, - "code": "module.exports = VirtualType;", - "ctx": { - "type": "property", - "receiver": "module", - "name": "exports", - "value": "VirtualType", - "string": "module.exports" - } - } -] diff --git a/docs/3.5.x/docs/source/api.js b/docs/3.5.x/docs/source/api.js deleted file mode 100644 index 2acf17aeeb5..00000000000 --- a/docs/3.5.x/docs/source/api.js +++ /dev/null @@ -1,223 +0,0 @@ -/*! - * Module dependencies - */ - -var fs = require('fs'); -var link = require('../helpers/linktype'); -var hl = require('highlight.js') -var md = require('markdown') - -module.exports = { - docs: [] - , github: 'https://github.com/LearnBoost/mongoose/blob/' - , title: 'API docs' -} - -var out = module.exports.docs; - -var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); -parse(docs); -order(out); - -function parse (docs) { - docs.split(/^### /gm).forEach(function (chunk) { - if (!(chunk = chunk.trim())) return; - - chunk = chunk.split(/^([^\n]+)\n/); - - var fulltitle = chunk[1]; - - if (!fulltitle || !(fulltitle = fulltitle.trim())) - throw new Error('missing title'); - - var title = fulltitle.replace(/^lib\//, ''); - var json = JSON.parse(chunk[2]); - - var props = []; - var methods = []; - var statics = []; - var constructor = null; - - json.forEach(function (comment) { - if (comment.description) - highlight(comment.description); - - var prop = false; - comment.params = []; - comment.see = []; - - var i = comment.tags.length; - while (i--) { - var tag = comment.tags[i]; - switch (tag.type) { - case 'property': - prop = true; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - props.unshift(comment); - break; - case 'method': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'method'; - comment.code = ''; - break; - case 'memberOf': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.constructor = tag.parent; - break; - case 'static': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name = tag.string; - comment.ctx.type = 'static'; - break; - case 'receiver': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.receiver = tag.string; - break; - case 'constructor': - prop = false; - comment.ctx || (comment.ctx = {}); - comment.ctx.name || (comment.ctx.name = tag.string); - comment.ctx.type = 'function'; - comment.code = ''; - break; - case 'inherits': - if (/http/.test(tag.string)) { - var result = tag.string.split(' '); - var href = result.pop(); - var title = result.join(' '); - comment.inherits = '' + title + ''; - } else { - comment.inherits = link(tag.string); - } - comment.tags.splice(i, 1); - break; - case 'param': - comment.params.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'return': - comment.return = tag; - comment.tags.splice(i, 1); - break; - case 'see': - if (tag.local) { - var parts = tag.local.split(' '); - if (1 === parts.length) { - tag.url = link.type(parts[0]); - tag.title = parts[0]; - } else { - tag.url = parts.pop(); - tag.title = parts.join(' '); - } - } - comment.see.unshift(tag); - comment.tags.splice(i, 1); - break; - case 'event': - var str = tag.string.replace(/\\n/g, '\n'); - tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); - comment.events || (comment.events = []); - comment.events.unshift(tag); - comment.tags.splice(i, 1); - } - } - - if (!prop) { - methods.push(comment); - } - }); - - methods = methods.filter(ignored); - props = props.filter(ignored); - - function ignored (method) { - if (method.ignore) return false; - return true; - } - - if (0 === methods.length + props.length) return; - - // add constructor to properties too - methods.some(function (method) { - if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { - props.forEach(function (prop) { - prop.ctx.constructor = method.ctx.constructor; - }); - return true; - } - return false; - }); - - var len = methods.length; - while (len--) { - method = methods[len]; - if (method.ctx && method.ctx.receiver) { - var stat = methods.splice(len, 1)[0]; - statics.unshift(stat); - } - } - - out.push({ - title: title - , fulltitle: fulltitle - , cleantitle: title.replace(/[\.\/#]/g, '-') - , methods: methods - , props: props - , statics: statics - , hasPublic: hasPublic(methods, props, statics) - }); - }); -} - -function hasPublic () { - for (var i = 0; i < arguments.length; ++i) { - var arr = arguments[i]; - for (var j = 0; j < arr.length; ++j) { - var item = arr[j]; - if (!item.ignore && !item.isPrivate) return true; - } - } - return false; -} - -// add "class='language'" to our
     elements
    -function highlight (o) {
    -  o.full = fix(o.full);
    -  o.summary = fix(o.summary);
    -  o.body = fix(o.body);
    -}
    -
    -function fix (str) {
    -  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    -
    -    // parse out the ```language
    -    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    -
    -    if ('js' == code[1] || !code[1]) {
    -      code[1] = 'javascript';
    -    }
    -
    -    return $1
    -          + hl.highlight(code[1], code[2]).value.trim()
    -          + $3;
    -  });
    -}
    -
    -function order (docs) {
    -  // want index first
    -  for (var i = 0; i < docs.length; ++i) {
    -    if ('index.js' == docs[i].title) {
    -      docs.unshift(docs.splice(i, 1)[0]);
    -    } else if ('collection.js' == docs[i].title) {
    -      docs.push(docs.splice(i, 1)[0]);
    -    }
    -  }
    -}
    diff --git a/docs/3.5.x/docs/source/home.js b/docs/3.5.x/docs/source/home.js
    deleted file mode 100644
    index e349d8ddcad..00000000000
    --- a/docs/3.5.x/docs/source/home.js
    +++ /dev/null
    @@ -1,7 +0,0 @@
    -
    -var package = require('./../../package.json')
    -
    -module.exports = {
    -    package: package
    -  , title: 'ODM'
    -}
    diff --git a/docs/3.5.x/docs/source/index.js b/docs/3.5.x/docs/source/index.js
    deleted file mode 100644
    index 18b3eeb5718..00000000000
    --- a/docs/3.5.x/docs/source/index.js
    +++ /dev/null
    @@ -1,20 +0,0 @@
    -
    -exports['index.jade'] = require('./home')
    -exports['docs/api.jade'] = require('./api')
    -exports['docs/index.jade'] = { title: 'Getting Started' }
    -exports['docs/production.jade'] = require('./production')
    -exports['docs/prior.jade'] = require('./prior')
    -exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    -exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    -exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    -exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    -exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    -exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    -exports['docs/models.jade'] = { guide: true, title: 'Models' }
    -exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    -exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    -exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    -exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    -exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    -exports['docs/connections.jade'] = { guide: true, title: 'Connecting to MongoDB' }
    -exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.5.x/docs/source/prior.js b/docs/3.5.x/docs/source/prior.js
    deleted file mode 100644
    index 350ec4994bd..00000000000
    --- a/docs/3.5.x/docs/source/prior.js
    +++ /dev/null
    @@ -1,13 +0,0 @@
    -var fs = require('fs')
    -var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    -releases = releases.split('\n').filter(Boolean);
    -
    -module.exports = exports = {
    -    title: ''
    -  , releases: releases.map(function (version) {
    -      return {
    -          url: '/docs/' + version + '/'
    -        , version: version
    -      }
    -    })
    -}
    diff --git a/docs/3.5.x/docs/source/production.js b/docs/3.5.x/docs/source/production.js
    deleted file mode 100644
    index 9fdbcfffbc7..00000000000
    --- a/docs/3.5.x/docs/source/production.js
    +++ /dev/null
    @@ -1,17 +0,0 @@
    -
    -var fs = require('fs')
    -var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    -
    -var imgs = [];
    -
    -images.forEach(function (line) {
    -  line = line.trim();
    -  if (!line) return;
    -  line = line.split('|');
    -  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    -});
    -
    -module.exports = {
    -    images: imgs
    -  , title: 'Production'
    -}
    diff --git a/docs/3.5.x/docs/subdocs.html b/docs/3.5.x/docs/subdocs.html
    deleted file mode 100644
    index 424477f06c4..00000000000
    --- a/docs/3.5.x/docs/subdocs.html
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -Mongoose SubDocuments v3.5.9Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    -
    -var parentSchema = new Schema({
    -  children: [childSchema]
    -})
    -

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = mongoose.model('Parent', parentSchema);
    -var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    -parent.children[0].name = 'Matthew';
    -parent.save(callback);
    -

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    -  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    -  next();
    -});
    -
    -var parent = new Parent({ children: [{ name: 'invalid' }] });
    -parent.save(function (err) {
    -  console.log(err.message) // #sadpanda
    -})
    -

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    -

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = mongoose.model('Parent');
    -var parent = new Parent;
    -
    -// create a comment
    -post.children.push({ name: 'Liesl' });
    -var doc = post.children[0];
    -console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    -doc.isNew; // true
    -
    -post.save(function (err) {
    -  if (err) return handleError(err)
    -  console.log('Success!');
    -});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    -

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    -parent.save(function (err) {
    -  if (err) return handleError(err);
    -  console.log('the sub-doc was removed')
    -});
    -

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    -  children: [{ name: 'string' }]
    -})
    -

    Next Up

    Now that we've covered Sub-documents, let's take a look at querying.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/validation.html b/docs/3.5.x/docs/validation.html deleted file mode 100644 index adf73caa2df..00000000000 --- a/docs/3.5.x/docs/validation.html +++ /dev/null @@ -1,37 +0,0 @@ -Mongoose Validation v3.5.9Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    - -
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    - -

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    -  color: String,
    -  name: String
    -});
    -
    -var Toy = mongoose.model('Toy', toySchema);
    -
    -Toy.schema.path('color').validate(function (value) {
    -  return /blue|green|white|red|orange|periwinkel/i.test(value);
    -}, 'Invalid color');
    -
    -var toy = new Toy({ color: 'grease'});
    -
    -toy.save(function (err) {
    -  // err.errors.color is a ValidatorError object
    -  
    -  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    -  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    -  console.log(err.errors.color.type) // prints "Invalid color"
    -  console.log(err.errors.color.path) // prints "color"
    -  console.log(err.name) // prints "ValidationError"
    -  console.log(err.message) // prints "Validation failed"
    -});
    -

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    -

    Next Up

    Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

    \ No newline at end of file diff --git a/docs/3.5.x/index.html b/docs/3.5.x/index.html deleted file mode 100644 index 68d28f54ca5..00000000000 --- a/docs/3.5.x/index.html +++ /dev/null @@ -1,20 +0,0 @@ -Mongoose ODM v3.5.9Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    • Version 3.5.9
    var mongoose = require('mongoose');
    -mongoose.connect('localhost', 'test');
    -
    -var schema = mongoose.Schema({ name: 'string' });
    -var Cat = mongoose.model('Cat', schema);
    -
    -var kitty = new Cat({ name: 'Zildjian' });
    -kitty.save(function (err) {
    -  if (err) // ...
    -  console.log('meow');
    -});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    Changelog

    Production - View More

    • Storify
    • LearnBoost
    • GeekList
    • McDonalds
    • ShoeJitsu
    • Bozuko
    \ No newline at end of file diff --git a/docs/3.5.x/static.js b/docs/3.5.x/static.js deleted file mode 100644 index fc0e722dd4e..00000000000 --- a/docs/3.5.x/static.js +++ /dev/null @@ -1,17 +0,0 @@ - -var static = require('node-static'); -var server = new static.Server('.', { cache: 0 }); - -require('http').createServer(function (req, res) { - req.on('end', function () { - server.serve(req, res, function (err) { - if (err) { - console.error(err, req.url); - res.writeHead(err.status, err.headers); - res.end(); - } - }); - }); -}).listen(8088); - -console.error('now listening on localhost:8088'); diff --git a/docs/api.html b/docs/api.html index deb2b859ad6..49cdbfb2aa8 100644 --- a/docs/api.html +++ b/docs/api.html @@ -1,279 +1,83 @@ -Mongoose API v3.3.1Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      -  this.connections = [];
      -  this.plugins = [];
      -  this.models = {};
      -  this.modelSchemas = {};
      -  this.options = {};
      -  this.createConnection(); // default connection
      -};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      -  if (arguments.length == 1)
      -    return this.options[key];
      -  this.options[key] = value;
      -  return this;
      -};

      Parameters:

      Example:

      +
      checkReplicaSetInUri('localhost:27000?replicaSet=rs0'); // true
      show code
      var checkReplicaSetInUri = function(uri) {
      +  if (!uri) {
      +    return false;
      +  }
       
      -
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      + var queryStringStart = uri.indexOf('?'); + var isReplicaSet = false; + if (queryStringStart !== -1) { + try { + var obj = querystring.parse(uri.substr(queryStringStart + 1)); + if (obj && obj.replicaSet) { + isReplicaSet = true; + } + } catch (e) { + return false; + } + } -
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri], [options])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      -  var conn = new Connection(this);
      -  this.connections.push(conn);
      +  return isReplicaSet;
      +};

      Mongoose#Collection()

      The Mongoose Collection constructor


      Mongoose#connect(uri(s), [options], [options.useMongoClient], [callback])

      Opens the default mongoose connection.

      Parameters:

      • uri(s) <String>
      • [options] <Object>
      • [options.useMongoClient] <Boolean> false by default, set to true to use new mongoose connection logic
      • [callback] <Function>

      Returns:

      If arguments are passed, they are proxied to either
      Connection#open or
      Connection#openSet appropriately.

      - if (arguments.length) { - if (rgxReplSet.test(arguments[0])) { - conn.openSet.apply(conn, arguments); - } else { - conn.open.apply(conn, arguments); - } +

      Options passed take precedence over options included in connection strings.

      + +

      Example:

      + +
      mongoose.connect('mongodb://user:pass@localhost:port/database');
      +
      +// replica sets
      +var uri = 'mongodb://user:pass@localhost:port,anotherhost:port,yetanother:port/mydatabase';
      +mongoose.connect(uri);
      +
      +// with options
      +mongoose.connect(uri, options);
      +
      +// connecting to multiple mongos
      +var uri = 'mongodb://hostA:27501,hostB:27501';
      +var opts = { mongos: true };
      +mongoose.connect(uri, opts);
      +
      +// optional callback that gets fired when initial connection completed
      +var uri = 'mongodb://nonexistent.domain:27000';
      +mongoose.connect(uri, function(error) {
      +  // if error is truthy, the initial connection failed.
      +})
      show code
      Mongoose.prototype.connect = function() {
      +  var conn = this.connection;
      +  if ((arguments.length === 2 || arguments.length === 3) &&
      +      typeof arguments[0] === 'string' &&
      +      typeof arguments[1] === 'object' &&
      +      arguments[1].useMongoClient === true) {
      +    return conn.openUri(arguments[0], arguments[1], arguments[2]);
      +  }
      +  if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) {
      +    return new MongooseThenable(this, conn.openSet.apply(conn, arguments));
         }
       
      -  return conn;
      -};

      Parameters:

      • [uri] <String> a mongodb:// URI
      • [options] <Object> options to pass to the driver

      Returns:

      Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

      + return new MongooseThenable(this, conn.open.apply(conn, arguments)); +}; +Mongoose.prototype.connect.$hasSideEffects = true;

    pXXe2ORF;vcoEbz2iDTOstx40ATaVts+dhf0Q!zZ(<;blE zx&NUL)7+wQy%(W~>dZ$Ck8Xozkr@9kD7matSpz1d^`?oo=B3LpQm zPx86{`X9Kwu%6S>TN0^EUI-{(1^gwc%G(uVa4p5qa22IeHtJ2V1VIqc>vqYqoNU1Y zq(dNdZN>#@DKJ;685I z&wq+zM-KCcfATs0=|B5TUU>Ww+KD9SHYpAcll6KCk+&eY{hoI*Ty**4KlxLR+w3 z`vs)5FiK(iJ7L~j=0`p4zYE34*`@_kQ&WtOYWD8iLuYdnEfnq0P#D<5KluB9pR*S( z^MUt&kjB~~tMx`soJAfFFAr339IM}92#^LLK`PTX$NF9Iv?fh+ULr?=XQw!}VfXYH z7{kzTm4fduJ9C9jtB0~=-X`k0JnB0@rPqoOxWcfqFwaBx{WMwF93`#Su{) z(rPCdFD0=OF3+4Jwabi@Y<9ozC`H#0Cgbcj571mW&r^>-K{M^X+FKA1#-iXCnH(FY z=B2E+LN0G6v=c>|B`B3*`sKh67Cy>)omNqPp~(3w7Z@7-2vda` zu4%Enx`g9+c%IJ(KlBm4@K;}9VP%z%eEgGSwu>)4luik{9mb~iGB#A<%(>IJ#Tx(c z|N4Icl?UXfcJF5P@+_P6C8iD>VrA|Ej%}lrCQ%t6sa4CA%4G(sl^n3B4Ox_+waP=b z1s5q~-VLZ9)>m4gwR*>}C~hl;(u$R(CI0k}{}XHL4eq}ER>}i47G|%oYkUe}d+eE> z;{W@f{xh$<_#Dl~I-Nu^I#6W2(PnCNfO@0NefQkX=0+WK0xCtIFj}Fr5Uo;l8uce- zN|tGCM_{s)xU<2oscDYfc7WFA8d0xJrC<|>7R@+^qabrQh*mj3P*{0RLz~xQ%g%|= z=4LMQ`9J*=HddF(Oh#>Z43qTO+-wjh0uwd~7VA9y)eWj+)9l;77e^R2HtQGxmD(=DHWh~34 z(d;ldIQSak04XgF+;V{Do_U()>cY0^wY<2z4PD=Acq7Ru)CNhy4(Cpv+}@B3u(GlS zMsW1bd$y;uTNq?|-+o4`hF-nN<<*#h{Rb%N1fw&Q&bIsTy+&OP{U+qE_7h~MVgQ*^ zOifK)SK-HZ?ZP%GCtf;^<9S@3TVQ$7;hsB>F+Y2WXI^*(uTW%p_5$Mr7DlJ^I-AVQ z&R_`v*(M7{V@Zqk^*Tmt*4EZYvV_wY&LV_FXgK-uix>Rw?B(LIb-C9ZV177_O%d+zu+2_*Do29-At=>sGEkqu{5eSsl_Ty@+I8ct&j zzV9Q1*lx07j3Iwky5FrRZv?5d#weY0+zLpu4EkAmyU%m0ltR6Rh2XWI_SfOm29ZN- zEbBUrcyY*w1&ar7Hag-=Shz*4zF8e7CZ*cim0-!O6`#d{b`9b>yaE+?1Pg z9l5C(H|3^WM{X*{O}Q!8k(-KfQ*O$2WLq(=Wz@b_-U$r_Z^}*ie#y3C1VJw^m{A!) z5N<1i5CSPBL9fHg>Uy5-ycsUMDSyo+FKtyRpZ%jhWc=WrIB|oEi!DC=QxE4Ab<(2O z>(Sg?XKB5IEprz0$%*mp_EtCLru=o2t=_+EZq#}1#GfKf#?a^%{_1~16@&l24$1sLsrN)B~9!8R~ys}BNvB5@t zgX#STu!LcDc8;(cVtX$8_wIR3O~FmMDSw?LhlE%*_dWO?4jev;R3Yas&XPr4>dg+5 z6BE>`RYt~kA*D^!X|S@g%)x{EZ&0#-Q*O#TTST+j%-gQZyb{awq1bOE?{sk9O}QyI zlB+8CfE*J34oBJEl$-Ka<)))>Q*O$2WZU`HO67$=*Ri6$*ZsrnDC#%gbxF`xanDW` zz8&|{bP7_E@~oXeJES@xE5F8NnppYKU*|ChhmnE>6Y-7)=RUcF@TI(On#e&B7Y zyMDpePUyVqKd0-B>)N8Ho$qh`Zu%E?b&*t`th;~V*P6-K7Mu02HvjzVQ2peEXRn3) zZxvhZEOXfUzBgMU@Y=$&*L!wXKew%W_D1wX&{qtl6h>N{SgaGJIV%S{=HAvV*?DvG z>N*>YyLFrTRQv*jg+s_lVH1;B6hx1~!aAw;AOl-Kk}4chTq^~sbK*6TKOoV+S#g|E zEVu|IkisI(BC-^UMTbmf^g0>R7+lZ8-}ew5UEUtN?pGVmEv?b%_4*BQ@>+2z`^ih) zf5bxM-)b~Ql}Z`gaS<}7mo#X?I3F+MqYRaGCr`Sa&F zdGh3I&Jk%4NJMx#NJBza>QA#h!nAPBI8V03td`o;$ID+86z*;)#|N2OF|*RD}+ zJ$eks%|r2F&|`UFjw`eC`S)u>5Jgn0C3fu^Vq|!fa&?eGsnl2J{F+u*SNZzazkbyu zHpVbHImrVLJh1(Iw%%V~U+1yM9(zOIwOlUq$xnWgYPI^B$-PwxiiB=2Bnm@IiQXGAXP)Mw_f)OF@UPL*ys7Ouf_Q*1Yr3>4G z?ezlUC}Dhjh$QLZx`M_=56_w)E3dJ>stDQ+rLx07t%g(ipJDjks~&=o7J;Y`xjx=t z5zEzBw!yY-q_nns&lxl-%SgICOr}t=IW~edQ6Jf8`bKzUyu#r>8k`_Z`SW zk%6%h0-<^Av9B|K?gT^CHgj_q>9j+l$l|`kM|iMs3xgNdNM{%5k+HtM#))u)GdctV zE`pL}vr($B=oY!BGRmh9-Htak0-i_jBO0-L>Z%7OrR0lW{35^o+rNF)sw*vvd+s>K z_^wedUA)M8y^gRQ#wI41o|@wHsnhtb%g_GIr}@^mzC{ovOixd0!+@`R;V<~+qmN-(HkU8WZ~o?z`^gw%gvt z)WJh}&+xut%*@R2PyWe2q1UJD*;?s8`q7Va@4fe4wL3^DdFiE>`1N1^^*5|e+`W4@ z4?OSyLqkKaUG)uInV;vY-+YwkUU-S0`N^N);g5ZYG|l+`{LvrrZ~y&&z|sz5yC%5( z_M?2{gYV&?_uR|yV2x{wd3Q9YloUjjSopc)VRG%4Qeqo{kULC=oE;2f#Rx0GG8VSU zTZIXcl3Iq?_6gEaru{W!^BhSx!7oTGu}MmYil>pOMV3m8iqYKwU#4hd0Tx-aN3~i& zrZFl@39<-R`gpd(!c0i2YzBrbq@B@?>lD*~*H$VU3Y8)S-@`9BxDH5@?=nUy{{QX0 zcZ{XidFJ^$=gT+W%AqTCj%+sBOwBA&RkvNW7WNqdWue|UqCMJs~PH_47 z366dLS=!x@R3Xdg_B5wXoo0D{9XlncHJgx_G+QwT+Wj2fHjY@{puKz*)3Zsdn4FZ1 zC<7aXs|AtkQB4_ajT8RC?tScXQ^aWx?WK|J_!jqcV}`hiyQX1!dYU8($>eg>8V&p) zq_na^e>TVccin?&89esbV`vQCE-Ic>v3{s5P4G z+q;KGz0U3(J9*@x`&loSsI|((QA`|!w5m07{e#Fib@(^aif(z$Kkc60`ZnJ(b6&e~ zAtaS*jW2!m>wMu$Ut#|8Wq$X!{|S#gd_PheJoW6;{NZQ+lxnk!)FzeAWoE9Fc;>~U z{M&!^FZj@V-;HD2n@+dlErB7xu)%V#Uj@?W`P{MTqNJ{^cg3|JFhQ8T8AXE-3Mmq7 z8;YWh9ZMu8PQJzBMu{z+hnI4(3~N*7GN#px@tc~A?a>0l#J~>?0-dAXfO0FKFQ38` zE=DAoKYJO&vKSn3N#ckoh;Xx6Y|FvdHy8KEal+!oc_w!4pyf9SHfpq2O38Gf8NIMh#aQBpY3#%nIX0&BoP)Fp>-n z^SL5`NEgJOru%j;fEeTBe86w z=ZzkP*v5ZB5AV%=+{KGC{Dtt*`im$nZ`c3`0gfqgt)6aePhL@6_nVMX zY;FYQ^{X)*2liId~Y?wg{t;mft3f zLXtQpihL^N7&~V(GM>dwrCC^5BS`|ZfEmN*gy(Z`co4nX!6%_95}HYLUAjl59MWEz z_wT)%(ZP}4{wtfoO1fNn;V9OYJX@~GwY-CtN~Or=a;&Yb;aE0>bcQ5~SXo)2R;zKx z9e0pUrzsYTT)lb~%d)U6i~0F^N~IEGV`Gerj9gcT0WeIHp`js;{pctsPM+k+XI{i_ z)!Dau8*6K8^!4=-$1#SKx0Ff!#k9>CND5Azxxl~rcmI($PG3aJ6x+6r@PYTfmrL`D z_~#@3w@ya^Vu<=}*{-S|2Ei&m8_uqR529mQEXZWA~?f=PLci+js{1^X>!T#dS z=9HEtv7*fx0Rt&-pgcnA%>e1ir}Q@E8bgCJBtj~LFwjJ_!X|-G^xGk6xq%KlC`aQK zOu~AM?rM}Uh(e3?m5`OIG0nEiMy<{2T0*Q{mS0*TQ5N-T4bO}i$V(=NY_?8~VA%p; zML3=W8IdR-P`7-1mR~1XS|VG_WA~@9JsTk%G!R7{+T9kNPLo!-Ok=%FErwzkv-bVjc{Q9-3+F)h@4BZ)}ng;0?HGdUYTVF(a(V8^=9+!+qPnv z263WTUR}XpL%z z&wBh1zx&&7UP=jUQ(~Dt{h%IlBR8SJo|pDbYeoTD_TV~Y2#^9pCfHgaRhrf05Sh+P z46=@+T6CmOXm_yE1=_yL(p-x$%rZOEWOX%U{q!8ZPI_{VB4NGKq#Hm!<1t>e(6&P; zO)8xRUhI(f6v7f%mW`K6{aB`NA_A(NDl=sm+KRR}d z$5-e1tBs5N_QRtLZ`+HXP8e@?Iri1#h)Y%W?!TRhiAnsmDyrS3Q>)QfEAdKwi7S0J zTQjM5JX`eC=?!-8+C?Fsr&4PYL?NB7&yYLHrP*2f`uiCh8)s%_mbuwE`ud6}rD(L8 z01S_ekj|vvCWV^G<*{vttIKOhDX7%yJoU`;Twc7&k-P3hB?+laj@;1rJG|DvUlRh9 z)_nCFPx9&;Co#uld_l?9U!02;iVid zTw3JhnVC(YaLKdJzs3W1AG#43Qh;k2M7DWdolgkS6J?eXDXt+=n}D3WVR51ijg}fq zOHz?y&{k}5=W%Q2Sg$NnbcXSa5ge-cqKkA=oH*5>*$h!;hLv`eQb*B>C1DbRmC%e8 zp_2F^c)nm~ahSqLfo@Qu=?C=LX-qrb)K$H;epHeqJooi)^70Rka(1-*%h^RHUnHH&;udnGvKfv({|YBwc%C@&0nOfgfycJ*;zXswGxL{-RDyxV5P;HT z9G8)Sej2SNDh^TWb#ji&1GgV$bYcsgJ&N?NY@^UuBwed8`{G%`TAQ6CQ%vqVKv-)b zElFc$j$<>YnKLyjmSVA7=gxZLhVtD{?JR9%D9iRAx&K%d^;Ei&X=Z?Nkq6O%H(f$Gc(I-B}-ksAt_u^~( z@t=K-mfuBM2CtsDfPrMFkm29_um7Ao4;?@V#if}A{^h^>0~VH-5on|#$z(H}Jay^K zODTbA3T(^Rw4*h8NuAC0w}HMHVUPk-85kP05n#!HoE4Ck5d*5mRCpH4^Qn3n7D{#U zBB9UelAtJ6V&;~*Tqy-)hl;GX1*LXGU^@6QgmDa7U^^yF6f2F0mrpKo>f{1j1`Qs0 zbOdQ;iNi8l#el|8HxPyE!7e3--~DcO9=?NPCr&dpwS$M>{U{UL#xZRR({ivZ8_P5? zEsN!uIhN)Y`ISc>VdmsTW;fRPwYwfYzX zdF=$WePkG;^BxDL4^b0K)Xy~;x~G8F4vo4=yBRZ>w+PP75Vkw`)f#K(cCYHxqsDG{LI*?C1WRFbsQewCF8%*VZ?Pb&TygL`g!ayur5JJE_!b{N>}HM@R$T z_fcB0UMlhGE3a_pefQy}QkxQ-5~QRP#(C+wL-MC1(TEi3uNfL4J;2!eX443AvaQw`9a>We!VgcLn==dEB z;I_S!q*E@X)e?^D@barCuw09LzCgWJ$F)7$9iQ($fAmd(AvDs^m{w1Cw{dY zN%-Qozs!j^hyvlXkmH7}N=afG`M%M+wNdk7LMn>W7dHXf^N6FDS_FW z*+ZSMQLCa@eFgrtOV}o|R zf}s>jnv9K(@W#nA%r0Cdj1+g=wwEx7>Fdj}vA%(A8}#+(dGVFk=_?jUlw@V2&b~dn z=r3<@_S`IB)9OZ4s;xKYF?!a(+7j0(2iLzgGs9AdUgmd`fh$o+6=6vmN2f?(lQBCu zY7N45Ow|PKgAp+@k|T*TTs_|;XoYxg8q3o}p`sr8v=nqrNn)EQA+T+OFz~U^bT#N8 zA+H>|iOJkdoh_pocJ1xM%L$|hw{knwTC-lRaQgfOByefrGXM9V{t4Rbbs`0#j-Cbw-F=id8|F!kUaSaT)JR><_w2x{Eqwtw_N?36>CBnaC<7$%W4kw%UeUOz>% zQRAs|XQ|a&d}3%Thh!fE{R8NuE7(hUrlviNuF3Yh9-_Ot%4}=I7^_o}T2MyAD(6>+5OY-efx7(;7AmlZ{G)QHjer+iLlKvP64Zx4NBGW_5Fwmn8@DN zTR>ZYdFUX!j@*YoGf#K6PFg0!qQmj?>ue1){e=`lD-sc+RHJ82ki_hH;7;bdb>2Vy zFh>`b_~TcPbAQn0m+ElhwWCbshnR95`bPUO#>Y9iI>&2kOPnFX^&@tzmKe{akV3Lv z_tCD0Bg~(Pr)HWaN~yPX#B0LPNA5eqfxY_(x?TSEsc*BmxJVdAxUR?e_&CL4ann05 zWM*c8-Mext5QHz)XPtCx>3O=A<8l0CkS?!mG`^lY%CG|-~Qmol|P z3WrQ_fK<|fpiQ~DO1;*mkg{;K0g*&S7M*59+Ye|5F>$O3V@+3Sq-kLrCha65QVB}Z zL%AFq&$8(Tb$qQ!W1vk7zpGha?XaaNsHIGl>J{h7mm}uGRMZ*Q%t%JDbMD~ADzPZ`ZN5~-}wZVX%lvv)M{5qFc=s< zKsuYn$~$DG=Dz(~IWRfQ`V%km%K4XhqB_GsV})NEm|~}=$;@A&va-xoLe%E$;QImZ z{@BA@TwmkpOJ`VZHVNYJ9d{TZ1chROO1bj3QCbLtYPH7y^A~@KYum(0LKH_x!yr)! zeT4#rLV;{9OVACd)tU$l<`$QD`uoojMiE*owoOe@tv9GtE5vb37zRW_5J<^C|BZjl zV~;(?6OVt1ZmU7F)j%c5&)rq5)A4Dv+GxK^616d;%bf>zGdkGMcb|QsXJ#ZNTJ)^W z3dJm+{P-{9dJX_jfA2-U_2hFzNrcuW(y$pEO!3G=_p!ECys9`MjBjvp1TffFy>=aiP=7`tVIooX!>4=qjm%sSa zCzu!?;+H=3AeR?sxp3(e+qT`w`sxP9pZz{TZ5EMsDRr7em)Ch%d$_}We5zpDkfFIy6GN(ISY#w~2I1X`r>H z8$|#Zrq#0#&~V4W+cBhMd3l9)t4%IjAW@1&wL)Ju%`d(8y^L*{|1m|aGC|Amx zeFm-(NKc$N$wsBZ;?fekw@wj;AxZLfvxvV>6GG7OecFDPcGpMg7=ws|`*sjV5ih)W zlrV~LEDNm@w2t|}dmd)j_9^CO=Wx?mzWmqU#t#)>1A;<6$GhHjKSM)9guW(G5!2H{ zH_sTZZ6K3PmGI4=xJD*4w74mcA%wutCI%kbjM2J{VVM+-J=ld5#pEn>ni=_{?X%K>v6@rP>;E3qJSUcLz^=_HX$5m%hsIkjr}5V0z~W?plLx zCrAIp2y&r!ZY>1UnIYQU7Il@NkR)2+3r#iba^VN3iHj+O1^f3*(_hTI<2;5&vuo=% zJk#RX>66!aKW}B=-uPLg;+SHg!2J(AK%-u#*=R5}HbxkQ7=}To8*%pRMM~>+c5mN~ z-)d8>RaN zfHI)~02V<>L_t(Dx3EN#D9)XoyLt2N3Ijv-I?{Cps+0(kU`TQO{;ogZ&5gL0l7t9! z29hdKHzx6Gn6xompY)K09V=`t7|eU<)(ZHVBoIV80pa6%HjeJCU!`GS8&JqN$VlOu z0<^%h4Lncc+JceMJXQ*{6(cN-khjQu3qj6KasO?1(l1@sN)57Ui?KoxFO_G+lRR?d z2-fsCfAPgHbI$|!^3X#Mp_JnC>;j#3$gX{dxHP-S?p;&de%C%MTQh&P!`ReTjy!OX zxFa(oupI5>xl~TN||& z+O-+ly@Oh-MJEW~aUKH&lM~~-`>{uu`2O?E&dqV^>{;YBl!}|n1`?GJhXL<-*N1uN z(MMRCU%>M`gp@3ombo}POJB8*OfE+dMl4-jq0w$pYt-Mihp{Y+Vm?pCOJN#4`1kVi zDzS=x&Kqw?r#uW4jambtG=*G>sV!q1KX;DxN&^!cbb@6{{_&@Nm9%S;q|?kSEb@h~ ze}hOzNYNt<-hOZ=xpay%=PodM$6ij)%z#Mf1~;Kn0!vE7wNbT43c(O2hAENahHX|a zSR`5oAS0B{AXOF%1J4!2W`jmGMyd@Qw?-Z^@$1tX?^e4K@gS4e9EVc8V>iX1p_0M~UnckUc2Q3wQE#0S%V&k1>zV+s4dhb2=FgZ5Ck6wSB%S%gC zYqgsknXY{{3PTR;-_LLU=5HW?iHV7x&GAN=OeTX;3deCsrBZ}Zgdc^hRm#LkeDm^1 zKomu6Y;4eW90vOOF$@FCvgsz#&n+mfHP7=H86Dxm+*Py|jExOZC=@tz`V#4MzURQD zW42C?V%i4JzxXPdbe6~e`Wp}l`U-iZ;eu9-j*jr+4_;@mufR(`Izgu!VOfHYe&9WC z&U_1OdeE$6S}3In{VsMYjUx>VQ}oj2YO?}tlSd_mMkE>`O$_Z~$vmmtHfr7^NuV%o z2O*jyk%6>L(!~_R!yaYdq!DV|dO(s$Fd${BUJk=cp%a5vrHM=gku7j-i>$2}Ex1gL zr7$g@N~z10g)+lq15EE#kh=LHnx^Cvj~*e_>e3y_)9%#iBryarcB-G&q)V|J`TUvwJ@yBV!m+a^S#zx?P{6FTcb~M-?Cbl@IgU58vSG(p5G} zYt+gm9(&(o+<)XDVyTc;!otxD$V4Cv@T9;NFx#r~qPoN(M31T+2XwVUXfP2ZD#r1$ zv}KwD_ubFH$nZ@CJwGupguwD#vY9mY)FjP%jmeQwHrCcQJ@ejF1sErIuE!@n{%hQI z_%6DgHgTd*hN6F ziB*Da#?(3yU1g#SgLW7a#9gG}poD?#nxyT7!JNr}oiLP9SVoJ1;Vi?c0!vp*bo~zT z_4VwH7AFbcc=fxiT)4=V;c-R=$0+1;@qM3kI!(7x7J}iS zA zXv(t-c>DKZIS%CBS#9%XT+pmHSXfw~QmzmuF(3HA`xqJ@;XnVuAEM(Ju?f#+(kVXn zkq@(V>okTTY1Zr1sx`XZE(o}I`Ye;9qr^iBgkWHBfW@mz)a&&hd+t3ucQQOY#Paf0 z3b_IbLA}+uZe#rOYD#IwMuxfb_WjH+E-*AWNTpKc(#%B+!(?n^f|QpfjugJ?(CxOU zHa3tl!8EMv$f{)-_?-yT63oqArdDeJ63=tV6$&>3Lu*Z>Vy-M*rrxa6_B))vbdmG3 zGu(H_J}d#6WOJt2%zR5Qj0BZvY?;RII=pe>3X97TNSCbV^IMN>VSK!bZnOxi7KMQk zvRR337O-a&Q5=wHMU;5dx|(K~kQjfk1P4ex8Me1>z{eZ}(<~ zYPrJdN{LK9hwrz!{m?;*{YB26Im@lGc0ve#`GX%|$MiH$J@pisY>wC7I1WGOpt#mg zbD1>%0NYWlS1U|SPx9dpK8$6Wy!7&`y!ys5Y|}x?5TyjE zOd2grk~rYeM;_oCPkq04soEf)&9Y)56*>9q&RUOYvSPH9n63VL~R#TF1nOKfQ8a1Y- zLPY=D9wU|70=4EM&@;grxsF*}+kQPZC(`fqG zQc|upNoUfGjF0fj>px;;d4*zMkyL+?rL|T5=9}Lp>?RZnMRI)^PE}X9xORc}c4}D7 z24g}nt2J${X$ys>x49Q#f=LfmFQLh|+c?z*saQdL>paFa=T@;P9?>f-5-coU?g;@j zo8)pi3~5jt>}PUv65DZzqKIO?KsKG>>F<0OKMa|hnc>pR42Cr5wA*xpfa7P*aJjUM z+$e!k{KXf(z)jUlZ)u5E{K@A&*E@#qV;Lqv5MVg=P52|w>-44x4gLmD34_gNNNR(n}@iHq*D|l`S({>1g2*>kq9EXvC zB5}~BR9YtJgdhxB^)h+Kyy4nfuhsa>AN)Q^qR1EWG#U-UW|j43jlcTR7uh;B)uVT7 za2$s)411gLO%ykZLe@9dF{CE;TjU4QR4M^qeKMg@lUN267ptf!qS5H!I1aWQp&~^b z#00UX)d{d{n=n?)ou4C&B(|l=dXUSxm>r0dh&WC_NG!LDw7|3sK7Aly+rZmvzB}Cw zG+i7=(($_hIF?O1?ec2ibGhr2eC4a0I(~}FmoF0~$tJ>MAS7s^(T1SXZqpHv7qGsz zL9-LnR1K=fPm{`eblM#n^%kITT${9)!Y^bvbL9g4O4AYs4V}>zO*_i_nTvpSi^OnHgqhXYo5eLJEQ~L}^XO_t6@XDBe6@a?>-tRjX8M*E{sJ%)9lL z&-SwA;g9D}y~#Z|N#a`qa*alV#~**3LZLtsMLhfT(>(XmQ99LXZxtgX=T9H!kN&t! ztybrm7hcBi_>2_O3=U)|ZEVnNm8q?^NXacc@%R^6S-je-N3twB6`Q~L>#y9HG2$eq zUT^Y&4}FC3!6K=2j%S|!I-}e6ao2(U7)HXg&pgYvJ-2ai?@ngUoo4p(BE|k83K^I0 zKKng7zR$MlDWnb=8;C$k+O0IH6qt6cM@8_HUMAf#NkoFMd;j(#h2;ti(*&&%hCvwh z%;jy{0#g%9)uX|q34??Nh{lJ$LTmyH9?L6K5~5|MojMa(F*~ z{^y@(?}3BtKX{Oh)m6N7ifX-1A)n{U6Kq{Rf zn@iJd1|U6pS^$C|Rusm^s7uL(g$4Ac`o*<FKllz&&Rc%>9$lUsT0ks}0wpmcSX(ngtDt$}4(7^aQTF_~PE zLOx59Bt1@FBJf-Xbb>}=+7{`wN0KC5St;R%0sZ|&^0^E_(4~;iVp%3}6p&7NT)H|B z8XU*u&~1B|92-Gt^`_0YRuuXN*uQ;(&wcLC_?_STANie6{}vmKfI=oiH>lC<)EOHc z;N>5^%m?55KDO@Kft&58y?&W)X9FQkf*@gNIE!tzX|-%3zfIqOflvujLAM*?x)#Fd zjmC=J2CoMb8%S|YsI5mi#}**fbxkM$(>6%7Ld6jKif$AWN6Fh}dLaaTd5;~_<5cTq z{@efl_gGq9BAqWX)HlHNw(X3KPoopfj_o@c94v7D;v8G2Ci%i=|A=ot{Tv#JG$cZ5 z!fr^t(Hohv8IP#jp|o6Qtt1H|g=Kl5tR5m0waMj&D5SQsarG*G5@XSm%#jEp0g335 z+}<1_Q5c~*KEg5yegX!NWS-M24zCkQ}f*?T$8m$z~NFc+I zRH{ox0+B{XF|h_L7lrOI8+C$Ia#N{qGgrc95L}ltxq&umEfGRvT9PP?Ng_ee4v52B zWWJ?f+qNRE7qWeNn%UXYj7?0_Zq=xi69T_ZWuwH(@)`(1qgf$LH0Xq8tBsTbr9fB; z*RqI&gYQQOt!Q<8v~ozH@jRQcp>$6$0)-R}Y)25aS4dednUqDd>-SWL&=?4?Y#hg; z)@-2x0|)_?C@f+0xJ^HyAC=eF_^U5J!RX{Ja*o4}9XqJ3U!~n{@y4q^pxkINJvqtv z*a+QF5rthW$6?#{9Vn&9<#UubHgH{+AnZZ0O81s|NuvJV!Eh_Jzn`W6*!9~y^{sE> zhX%JF*oA9K)+=?UrY2cgTq2XRX}8+6YqjgMnGk|h%H{B(LktZJpa9#nsMecQs#St8 zW_JEEW23_ep&1<>W@%-GEu*6>E-tcVY?$3Uw=&RIyh)w$dSDoaK`!g?^iy9Yo%RSq zpF}4}38rCUm?m-9W$oDW%wBknj^8HbrbyxlVMy}D0g^-!CyF>us8@Y(4BWy1+7zTb zjT?tJ84F=aY+GYlAeBO@&4+ePyGr*Gj&T$LVzY{HlZvvbV4?*iMM0<41#Myfm~zTu z-vFnMy~w$fKO~A{Y{#b6Zef}(o?9ReEzX~xA?0}}G&}b0=hCTTY}DFpnVcYwLi+k$ z`o_{EO4F$Oh|P{{8j^g*#xxBK+anAkOv3^lp#|8Mi;fb;rYDH3GNADgIEG1VTjcwT ztd`b@qXqf@_j?tj`z0D)vD!QQPNvATSc$XCW#eM6k`|$ zN-2~|FpOR`;I$FXG<%u<-tR<@zO=anl5f$j?ICn;x=gJJ!d+$`gI^Lx`;lS-u+9v*(%-#VQRtE;PT`}|G8xw+&{r_&gQ@e_mg zS|YPY7IcwP;JI#3wn%HtO%BXg2gxcNn!PTnjb{Bu5b4~TyI4gLgmyPFEq z{vP*qJr3SFUWl8%{cOj*#%t0)+daM0WB-5Yzesp~=i zPG&-LU|^t}PN)0d(V6~h`>*Z)M@?&uWm!lmiK3s4(D?rXQ(dZQ_j;({00000NkvXX Hu0mjfzLskk diff --git a/docs/3.5.x/docs/images/square_bg.png b/docs/3.5.x/docs/images/square_bg.png deleted file mode 100644 index f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.5.9Fork me on GitHub

    kEHs_LGe?wKJuGaPCdM8l?nCCj!TI01$Q7!ES* z4~7jGu>HyKy|}==0xoVaaIY;x60S*Gq$SFvIHbtoJ4sEPm2+GF-x^YZi zl+;y?@}V@^-dN+aFWq1|nvzIOzmqWBKP9g%oqmVObcTvF@4xysqnYKUpSsP;Mwfb& zvvX&Mi_1&&x4L9b(yl5_4u@>ryh_$f0^Ar$qCgo>D^BUPV^kEgdi4U;@iDV$#pLjW zq|>Ig)@M8#p^QYv3RxPa2Lo1Leumjnk621tv10xCt2mKz`-?9TJ-Ev>FZtlLcge>E z`K+duKvb5*d6@8W}_*~8|%bc@Y*YHa`oA#nI0cf6csmLc!tZ@u8>N@ zU;3-RL`zxz=im4SDo*(4{)L}qFe=E40x2c4!gBM*2D|%1);CumpW%g~&LUa!T)>zBE;x{R_G>lJCg!^ybd*=Lry`{979hHihAB+00%oVqTlYp9JS zmzwFcrYbe?q`;>q5L6V#vA)!0rPrmM#6d#3s2Os~$;lY)9ckqQO;Q|%oye95VJV9m zAqDy5fZ{t%@umn}>+t}gBQ`Frkx$16pCe?7nH_=cqO(4qeg0|c+Hiko|6^VAIeBzLh7kCB z%CcrWnT6I)6d~|*y+k?B>V*x`_Lw9|@TFnpsTLwjaYeyK=Mu(vq8Q$K^*&c_U85?d zq}>ko@gXm~^en~{XdRQ575d>Z(Mq4rg&xzpk1&;B?aC%A-4;=rG1}e552tt>-K}+2 zdoAAj>MQgvZxeSkda1+GYM0}qQ_?5}U*Y1I%|G`d-c%$?F*!cL-o3}gU-?-kiKD11 z?!EgVZd_1$OO?a8v?O^!Z(7jpc&4KnvuVMstcV2kn)!d_45Jxdv8zGS%9iK9t=3KeBK^z5^5hrqXA3R3(*4S9>u)kZewY|dYuk5k1k#Og& z4@f&p^gAhsheIykxWL0Z54rHvbyn7Uy#L-qk|?FsPEf)kWQ5il7o|uQlcWJm=e*}+ z(8XDWpPjKjo;RG~$tmCZ#%ui2&wd(NYYrbB;>w~ST(A`R6o;THrlBYhM@%PUs%aRG zGB#pxe1NM%8C}K?DT@kgg0`QrE}(=XLq3^Op6&#q>xMu=D+x;D9mMTbqDWEAhD{GB zu&l&sf|3dyXBb;!y(eicLp{Xghd483yWi!@KYfdT@RbR};rL1TNT^Vwt#yHE0?49> z?S2oBM`a0xsW}~vm>nJQkN(GhMC3fZhRIxLg%yI{<{GBTd3rj3+&M~VD4XrT7I^KQbeRe*02!PU(C~I@$sf&z;6E-ex z^WG2N;Ok#2`P^r3^6K|qr@y*_wT7y$n9eG^ttrZy4?mc&wY3q-h{kbxuuEQ)JbZk@ z`clGg{m!@f)Tf^%i3F3;jA5Sh%!SJ+si~`quYKbU^1%s{X^ruc$>|CE2V*+zh_~)O zV0nFo?|tL@Oi5Ykr)*!m!p@^3^0G!Jt)>zcMD2aUCXbM)Btm5|UVprk4Y0Mf!C(HB zFLU)`pQFe7jHff&ofOj$HJIFlGI9(mO4+=&&B6V<417C4R&+rts)<)t5hiCm8WSnO zjc1=_@BTf!5XiX4_Jw6GT)WEPVZzRx59w}PLdR{Wha^c%*6A`C4vFFz+ln#9(OSMl zIX+tl#}bHm_Y~^XfYLcOH`IlvXQYd^+ah?WgFjc6spj9WFn2gRM)ew9*KiWOQ)C zwdOSZbw2A}Dv-vPKKRN*wd{ zw|+?F1xhQtb+jUlcOH|a%&G!r6}BkJ#DG>iMFUwJ^K`#Mr4;Q=&)d6u45u?Dc)Ct8 z^N>XXW1%bqm5`Ky5VJC&LM5eScyhu&{zrev_U1Zi7B|RG7L4D6(S)L`0MDKG?>DQh zT*$c1iyo?BBs`A_op-&z{f!?qqM(9@5BHn6SCOSD%j=s|lQD0+{x-k&`>(Rv%jn0t zX;3M?`rBVe60l;{dk&_SQEBM)TKwg|bP32wlB|KpxCJ>jo`o8fH4Ww2$M8`QDaB8} ze2b^A^~q-iE9)JyOtZ4NNl}&v4Egwo{`O@qKYg8IGG#D0;o9w63PB90;rdlBT)%)bo=&QH^$%WS_0l?NCn5S!(_LAk z-D~sdKleGZB;vhqy~$^O`STp_91zEv$~y9CLAu*VBkcr(?#mu<~1_i4eH5rlk~#l=#w8;VGPBILTR?%}9EEBIkMj z+BJG>>-^x2H<``~4vb~92B!ovR%b}d^U6dE0x%zB*kovu+1gN9%gRb0Yb?X@bRo+Y z9757=XKZb+^V!cm$7C?3x7_32dw2QXYaccwZTblV)H+B&he}Z(!c$7Jy0XOEuYbUJ zGUCzWBjO~*qNp9jQin3FpG$TrPVtK zjPD&{R3C_*fJxkX>M~b1I+R6;x0YFv6Svx-q;E=Qd0@3493HZ?zRKkEnCWCjl*F`E zMkb2@07xfEL_t(nR`F6&S4Efw!6Dp3EP~p3tOF+mhdcXx?H~Lum4K|@VY!oX=bd{jU)m;Z z33l)7(0_DFF2ig^Z7t}8-A8*Iy?dA8{*cM6Ag>I0U1PjqGM-`(s4Ncb-E+vV5DdMe zEDcKpo?@jG#k4?2nhQ&P?i)i56xL#e#9Kja9GQ}22)Zj>PG<#mUZNsNyLMztOK6vK z^~y!s-4=NF#b5a%t4l53di_H#UcZDbbFMyp zgTsgS`TcKNe*Wh_!_oc$S*L?3D=u8Qh;{`|r)>0E>>iymo=iW6$eo8XPY6&pRg(4f zH7;Gc#AtBJ>0p4VE21c-*I!|Lvd3yGB~eiWeHR?eDh|gv-b0ecJayw5N(FvmAw`3v zmH}+&gMzIy7B4+}Co}%(Hy?5Ff+t>HU(7`>bu(VLv4$uoJbZgZU6+`;2-+tYOqFA5 zi#1`4_Lbd-%_;}*Y>uV|9cFJg+ zFBU=OSgEqAD9Z|`9b#58IT@4Vurf4^EFL?{nN15!BvJdv>;j39y!D6QM@m6#9jKbq zyrirhv%JFKIov;BbGeVLYit!r#7>Tfl)~e+!YhfGW8oW;W$zrZOsTzRRMli!;iUu< z1PNPN#74i%L7ror1SPQu3KLk-<4A`c!vy7>N#zjAVvml9d`Z+>W;IO_<5SizUgTY4 zC?^vtSy5Jw+MOj~3vx*zKzMFk-yqKoU;c&9aC&?~=h{>B+L||akMTlt;leu8S;cZ! zk##p&YQ=o>Tkr7nb5HRb|M(jm48qD3MbSCOI8RS`)^t)za`EB?o_*$NaGu#@OqvE6 zfiz9&FRf5chXAy*7P+zP91odQ24iZ#bLGl)E?(GXIvybeq-o%_HO5etX96s9)^s5o z39xhL9>)5!H6b&^<6PYs|ONx4wXa;8SAILulJ@G@vIQXb(%m__k2K}sK_ z&zeO?Dh|sSwKF<#LOGj}4<_i!5eY$QEX+!Z$&4gP zhz|BCM-$ZWgwDEQC5o6M!F&T6B#Idol#&9?RDT#D+&e>Qv!kp4)zH2C@xODL%Pe1*1 zz(SdtZm-8Q&jG>7@geP23!yc+cUUXfJ05U4917x9)rups8wT49{z{^J2fX%-{0=V!sS^8)83 zI4HftG!jrk2&%FI0ap0XOyW#~&$+P5E1{5)Vp1_BLR5%90{4vBptN1Fehk z7Nb=Y-3}c>({O#o7G(@MYr4KbTB|lNl}&DyBA~z>Z%b>Y09hC7=-Y=@WS&f zF9n2ZlB861Bjx5ik&e+(d{%XuYdSf=2YCW1CB`|{`x$8(;hhPqtxOTVLd8kg?R@x- z-qz?S!Oz*rrN-1Hz78^N!t3C4!jcakqogN}6I7DW-&*DBvp4wlfAHIU`0o3(+9}tc zy2`Kor9Y1sio=~9ymuI5v2Mm>u#Yn#ACV%st8)$^Biv*!fFcPKqqa89n8Mi{Oq8}6 z7lKFo!zaSp1&t@5%etnlE3}Xp?=XTeLmg@Is#>gY5)s(2t)(_K7U)JXy(|m(mNMuy zSnH_0!w`UYI*w_j5wS|CaU{w!#bLZ#P`q33S&lQ-vldz@YAtE?B~cQg6NC1GUMoW= z$gN{mR!ob6GHu|0jiDP=5)3 zHJxjT6f~b_xpMg;Pv5wKn$JE9L7Jw-N!;*Aor8M#v#iDwc)a|gN+VfaZlj_YTUHHa ze;tfW#|UJg3!RQ|bwQM5IBStY5O=m1pY9-)4cZ_!2ya?zuyqkwRIG=3#;uosmS6jy z{vq%D@J*JM`;@Z@Z@&5}v+2S>8;FP)yyOzZ?Qzw40m|I&D zDUXyk^h*@zSP;btS++)7U8cXh#V`K3&+~)te4ocB1ExjQ@Z>f-Mp;$lMTr&?;X|UE zS0$AVv)A)Uv-xbY6_7haSI4yDgd~o_2&=UiYcS4IV@a}vtDCEQ@#lVypZ>xZLa#)y zP-C5kDDwnQH@ms(3JE+FPt#`Q6pnTA*Hd11prK~Da z6Gk+R6c}5h+RF?rh)G4;Nm{jG>C!sM=|0h^K%?li+kod}Fu*s(gr#1GM2DV=agHdC zP`W9_N>37p$vM?ZQA#&tW)5R5zwpva{IxItT!1Q^W7RvGhCb7UP*M@c@xof?VU`E# zPd!ih3qOw#@S9)zCjZa>`Pa_@{X!EgO;cWY;d!z&K?;Qz0rRDl4%b(mBNuN7*Ssf8 zCVCfw_r`IvG+}#d18lX}1(Z&3COC#~&JiInUZ6x22p1%nY8+(VlBD6rbST0wQ}9QD z^M?M)3bV@d;d>v@YG?e-|M1^o|M6pf<5&L|-g@l~9)9VIc-5oG3$k>D!~IhZ?|eum zLC1=TR1~oy%LH0^w1ha8B#EHaNfE+<)1;-(b&$DMnq@iW3)?4{TM@tWJ$QT+ z7N~%gsw`z`sD&W4o`UtDtHq)X2z&cN93`r8?$E#*u+Ii1fzfY_}Um(j`)W!yVyCw`N zZP;1xVCssAEd$%QjOZ$jMKCord-v{hJS|viDi+0LiYp81vSL=1R4QULo=}w~MOlQn zRSDX$B9TzrU})aQXNj_q#Cpy`0ZNDKCD1sp*<4*>du=7my<5Z4Xwv9Z1e;mwb(t2$ zB3Yc|Ik67cpl+IQ&U;pSJytp$lu~T2tTf~aL8Zym1`s^`)O9XhxNydyWG&7GIfme2 zL9jk7Ks0FFv!s8nzwQZ1=zxfrEJV1yX)#{VzE?IAdR__>PJ*jYL z=Se$V4qQ!PAd3`9OHg~qaj6)3fiZwE#8FO>PcciHOKF>G*1^wCsUpwLqk^*3NLe+- zT7xzwbY`WHL_Qe4RuU(|2N>^=UJ&UZ9lR_An^B54meN`h-D)Uff>G84iq3YY&GJg0 zC{l|pdpI8R-S_Tb1*B1oQW2lJw8eMczeB7vMO6n1|41?^D`Fj?m87T)pTB*J3;htf z2qi#?z%b&%?0F>xMo1zl(UB&p1VvRc@s`9|`dV^STJ9YU!c9swNxw~1=6GAPwXsA$ zTj$*Y+}oSrtUU{PghVTe780e!Vy8MQ>k3+}>`8vrrkv=U4Kc3^yW?aw<@@iyPffT6 z9?55~U*_BIz7I-cokuuF8Y@P5NfJkBAt~yb&pi7q*H)K;@Jq9@ZEUQvwYAP0ufI#D z+u_Aey+GXL56=4r3>hkRL8F3@gwn_xGvArc&v=JOp{OcG;|cAR3`e6)?!j7va|KdH z2pJ=hVRBMQglq*EhqnkDoK+}+6eg&vy0D`NZ_%*~YQ3G5)%7(_k5BmT|GU4(-lMmu z^8?nlR$1HF;Qkw5W8=az2w&s#Lz38ItAI4_v^p%AF~e$xDI&&o*o`XTkTQfvQW_$e z<1Orr2jnA3oE8XYQPEY#lPN7VW*}5>|EN zPC{j7R?_OEL7-d&_BJoT;4#k8Ze=LJ8B2!ubXsk0U%lMOPX&BS5+{86`n6^tKadz? zaYWseZ;f-LQA96|7gd8ej_7yWxZ0qdM>~PQVYFgW8QQH3?JPknRfAwGai~Rk+ z^K1O@`>&G4Q+n+-U;6T2V03Vop8kLoi!_=`S8JqQ=D`OeeC-(T>~I>zlnrr)aiE1D z&0@x7O=T=uni02CGy-QGrz1(%St6gKii$)>WYN6y-9SQ0W2lTpDMcyfV)o%lQ52zM z5Y*60u_QIrw&_qh<`M!)E5*35a(Wjo{%|7g zB%v^pBr(e?OH4;&s0^~UbiAacBPMCez&eyMTwPsddt-}t?montiYU^^Btgd-VKvjL zrdO2|C&#Erkn|$_p=q3X4%Z0IKCWu45TFf0E8-}Wvu#7LrsNqAO*Z=0p##n$7XgTL z#PzMsk6nX)`;WN>%qvJulI%iARMs_RRkOLd!E?_&6O7+E#^VWjS&%l^volg;j|&-p z<77cdeO^scIwAXM`X&;$|9DtAzSMSN!-EYd(@=^6wVn;UE%#)yk25# z2$#GUlvRx*V>$`*Ce{jOc}=^O@YSz;m0O?r9RJqe{MUJK{{gWqxOC+brab2O?zdRo zSYkRIb98Jt8o=SPBTq6~ODWD} zS5-B&_1t~*kjMLbBvFJG3K}4!v6khPKHHZsvUB$#hx-FIRz07+ahV4PM<@XmlB2;G zX+rg?n3WWxDP~oYSAkZvs_R9SW4`+4wZVD)-jt+DTXjJCZG2Wl)2F}UjoEJnwAZ*Qe zY!Ft_?c{9rQsSkHpjtSusj3;X;e9}2y$Zuhgwnb9pk?5xC8;UvAerqv%!&$ThVOm# zx7pfWW&6rS`aRF_-FFbKLim`s-x{!cpqUgh%%~%gkw!%kT56Wt9g;L*HW^{83%#6j zN;ggDb~~JoCYUm(x3Y$c%z*F@g4xpKmoh(gaO8u{RPz3eRN4rS%qI($`Q zZ1_G}tB}0nn`AX1Y2?dVt(0~vWAEgcgVQjcDy3vRo^pR@pW1{`&u*u~t((u0Wq~Rm zAdch3)-FWYZLM?s;SXQu(WA%2aT4f15o~U*bM4v{@PgTFx(Kbbj-IH~&vQMGTM&$) z0>g-FDs5?+Ho1sfOtT%%46A8ERZej}#qPCfbz(N!;IVjH;%trg3Qxo3C3Mi{6QL6h zmZ*_sOH)U;9h_52H)le^+CBE}?2=wlWNFOtX~GA0;AoHqNeB;-5_Ecfgwm9=36WNG zx?LudF-~Z-wkSMOc#<@wb_QoHS(*~Z5oIw2V`z1|NEL;NO>YpcT43aYW4N#?7!y{K zB#J}zplL1zxI$QMYUeO@)30!WWp6Z|ki`)yib6;eY0^lMD#>9{V7w)ZHKx)yDd`Hq zj8M~d){>Vc?Kr~JmfD8?$E2v3RyFN7q1%c>NmxLfCX~~HsQHXI4Rgt(*^EpoR2t#6 zB(H1I@rVoS>+D&}U^u0>TJ!YQ2IF!@zth^rTTH5)aamB+@?01-A6}Wm zZbGTKs%unJg>!|+TC?CqP2z-ByM+>x;b=-6hZQ)etEMDz#CSRjO|hn28b=Y4)=l0e zm}^c80w)y>aa$ZmtgfuEx3|}5XG0WeZryy2G>#dMPB9HjpKes1&Nr?WYL z2YK(wvXrgOO_Yb?oHH2*S-Xvvp-MTLdER?a66>5qTdb3mb!4u``T?RFN7yeiO25@`@xlEr<>e9B~a z2r5PB7*iMIlPR4z^fo}Cg`?GK-sycmjq)qBz0S7UwnIo5eY6V;z;TMCTw0 z-n-B=5n|Eo@jxvFS_FMJ6?}v65?1>+W=!Ja}X-5s+IG|G@`ByBWodz z(8D1YFJ0hxcaM|3LrU)$PYdE!#@5CL<#^1c#p)C_JMO}e<_f4yI2ICe zL*ygY*Vm9zHMiWey}iZ7OWTacBZ{IRNis}T6Gd?YX=#%DIiwmEaF2O;*tvk>6?h^I z%1eqlvuN|3s>WuYn&++x5*?)AgtJX~Um``r8{k}1z76EnT4}u37;msv zQq`Jb>KW!S$D^3ac;0zGLWww_8iYW&8YvQ@2C-}%RAm7|5+?~&F+->v=L5D&Wid98 zA5)bzy-d)~B>AieRaR%Ia!-;3m`Uj+N7H)2LnJKoUI`r0qH5NPWZ=G1 zin21HQP^mRCvg<$SDT(o+GBx#1T250NQ0o>%oQ5**?4jXoU9chG=80#6A zmhr3v0kc`oWHLeAeCnD%Jw2h-YVpjo&!M7-`+G-JwWlWykt-HAS4tV0eDkttk}@5S zLbxG4a{@+F2Oio;2|BHaEKxMX-WcO4auaYY&fzS?S;F$gH9AY{)Ww*c`}a9LDR9;| z-FVql3?PXjV!2qzP=0=*&`)A|t%Rj+OcG0!4usLF(ebV-ODQ5u+@+``C*vbfA<@Qq zQW9F(IueBv4rdGENaAeOV3`Qy1W`n{*GC``<(O)8K-x|kLN|rfbM|t9RH9)LQ3xe) zb=~mss;~=UIX;>3-utIiby$Q97Oew8vyOCAK5clflnT%aXK;9|3(0zI9YvW_*EMzJ z2q7|f3AJ$;)9gSpIJ;`z$GM;>UN#}J(wa9TC>u^F19ibs76XLR>C@iz~3MM|^di-Lo8#25d@zsj|1 zw>dbx!`}Wo#5$!eMnSiageY#~E5lRIeufL1H+b*Pdwlz?uM=fS__9iZ3bFtQffHe- z#fUjaYXg05fR5h5wYrt~3{U4DaEEOoaPKI`3)z9Nf`G3C-biddK}Cw`*phS;lGTl1 z$aUE;=7Tpmm=Y^G#223m*U{!soIo)SU@w{CjK$7|*veoW#4B3}Z^=)Fm}%Y2l7P-q zRFZ|9NT)nJ81S7B9tV~XV+_`NTHPM6-#ub)=8(3=mqYTrWL#LBhBOk?&Z4{w^0>2t zU+8vNZX|bq)ZstrL2>ra!nEr=f(&F%VhqdLa%uY(o?0{@_6{jW)4v%oLAWjlYzfbzJUnXv4 zA3M?c|15v>(F6KIeB{LZC;av#54re}?sYO@m1n7!@XKG^q}u{- zfSE?r1>Oaap*4=m3bN%4KO%_aXpe|8h*MnYph~GuBudm2b%IlhrJGmrLc{bBS2u%m z)flQNYV#&~^AeZ>%mju4W-WYe5K)57bE-j3ITO%XrMI<)v=a{BjX8QJUo2AI3#5y} zoQbh)NzEHd1~LTe94Ds({>kruov(awgso`DJ@hxG)Aiv@2TtIuBJXa4PfiSPaozs~Wy_psh$tYQv5r=pkQWu!!R?>=BLBv}|L>73t$@ktM3RFC z@1r{zmsV2Z&MNuI5I3!`KETRB1vvpP7U9bDV1meEqPUC8Pr+F*CP+$X1y&$CJ<5|K z;>==XhOrWqM|cs!He>KULPTA3uZJy1h-wDYeSBfVLRggusd05dRah(ut@UL{70!3? zdWbbmg6KT0^<}>FAO35+^IKoz;WvMP5Bd#g?4(Cn2rnHd*=;KPxg2;iMaLRt^cD>>yJGaP9y@7d8w6h z`|<|8PAA9(3xRc>ysSyrQ_suHSqSHJPx!p7YE9!Zlv| z{dYJnEnX80&gQt>AhbocG(-t1Etw5!`kNWDoPwW$w|HwnN01~?l*qJ2H6D}nCD!LES6Gk^Ur^4hQdWB%cP`hUXK zb))17wRKFVB|4JC(o>FeZm)fg&p&^eb~HmzJU_TM;Ak>nI?h>LmP{v;C&HGG>M-~} zW*3>4RG%2_n_rcm{Kkp*o-f_H&R_hQ7x?zO_xZp7<~OLV3DRB8aWE=)*GsyYU`2V} zdgBdlz5Y7e7cVgzO<7-C;pIQ~3(Velmv8>g|H8@sF4LLg>hl@iwGkph7)yCN11#x! zj_mg7Tw0=-gr*^J3sKG*I@A%k6qGV?mwQsM-V-sC-C08)MZfQX8~xgR=-z zK{W>Jf@4%uh@&u$=p7rchAh-O$1}h51-|^Z{w?l)?R)&g|Lp%vJu99_ z{UwN6HEEO9LHrY385h*gK>?h$#O^zLwXd61J73BNdk;!B?gwLTN55_@J_ED9IPHh_{NGcZ}y& zthgPkpNx%oa7B%omZ8;}MEJT6P6!}jt=}b%1l?4@Sh1e=h~ulovEo9ixW4k3-QCBy z!gBI>pV~J(ug>!Dl{bQOtBB>TW$wTB9@l^B1$KV;HnWo<&P)2+>nvZpN~|1iqNWEdFSl78J>sS7R~U^P!*YN%CEm5!dhtuNIxUXh{4RTU zcDVN0FEBcOj87!`nGICjLm^2bK{>e3?pyzq^{2l?XZt3zqa$`-{~juxP|Zr>(JnHJ zam5rA3g?|fJ`v?ESN%NsHY`f z2t*R$^MZyC2>{jYcK@rq2!D(Ww7nqeZBn4v>ZNRS+bAg*&t}X_g+tLwS|pt=U--h$ zvGnjR);fN-Fnp%prIw0UCMEZ+rSO6Wwc(B0u_`5RTF=nK)O!??O%1=38~RyDw(qzw zxc-zDykv*pi4(_uzx{t9XTip&AL*44I_3~$kBE_5k>u+=CyYF!G7rwy3 zn{V*`AHG6+b&1j53Eh4hq7-QgoNAG1!<}!w%I;h5Gd?^eYWHY&HLv{IKcO6r7(6`U z+UGz0lXDCqn4S#Chhuh6$9(Voha_>tzxL&qIT(&P9L>l_WA6Xp4Wv{=QAU(@SXtga#daDp69oC-v91ri^WAm9$p_3IZe*VuhJvnCi z@{3r}#p^bmr7iBi^(q_JKh5dhhb&+D9FKPP*|>3w)5CiRVW_7ChzOk~nArqVH&r&3 zpd(GxNy4sRYA8zVY>W^dk@gYNQ}ywY%Q~#dg`J?E5*?`r>F_~ zXx%n6xSlz>^x*R+A*ec8}beFqKj)wF%wm7->kkxCK0xaYwa5O!AjJ2GMC%pa8 zv%S)1TG}&0IIZwfGa}{iXu!emevMB*{WQOF^Cc>0IeL6Rw7iKcYtm`XpmYM4ol;rfmF2Db`{|*p3vXyllO>-XX z7vRRI+H?ET1#B{+C_ZF;d6o6GnvKm>{8mOv!uatiF3zx_*}yYD|0SX84qv8}LJzgcG{e+kP>OUXgC0Zl3e6s9%)(U^} z_aFZvG|YwJZBIs1e(h^NSd0vZnF)dQmf_Jp#cak&UGsna`@c$2R9swNgXm@Y&54=JW(3G(tq+3=dy_1(Gh+!3WsVad>BkwQH*+(eG0f6N>Gt9488q^_jf? zeYC7O{NOv($tL5&MI8!$;yI?1~z~j zGT@sG&=P{vrQ8y^0ZhiXZqQSY61u7uC zM<+2!dx_5WCbkUIimKspn!{+j7d8Sy0q!0V;h-!-=rHfjdQUl>ku>w@nRn|fAIS`!ppg&=OVxp#QVcfRvY{?_06PpG3d|Gz)@4zJuj z=4aqz#Br2Zyi@RE(_$ zI7etO3V{%sWK+{krX<~UWP1zp-7ssLZXoKKx4wUu$$JJ3EGE_J+EH7N@DiD298chf zWgq1$q^~H`O(xx^sg`cwHm=~JF-)QMp4X-&i4??AP&!W{B`aEBJUp%pxeucCv4E=S zd(_^u5oy+xSf#90~!iL7Jmg{Mh--5>iJw3hm`m-?Uhm{f|^QXt1O!r_tVD8fZ4U;3HP@^AjN zzrYXgKI9+#fBr7tdE-r_mW;jNo?IOl|s0(I~ z->1y?5N?dH6MWQ1s0>7qTN6Tn8G$VV3`T(v8YwkN%acTo_F5OcvH_E67}Uy^P+5oG z!6{}QO2Hi4B2h|UL;&j59!`6g=x*F1HHOMBQ>T4w+Qla=OcgSGhi5%j#0W;t(NlrW zMI#!~M98FU93t!-Jt-ME$ILmrk|?07C5aRyQgBi`43Nsup%e%b8N#nW&EfyJ$Gpc0 zjgLAgB^i~EIULL|wP&f@LSmV!h~D-^?!NgBCzDf@(ojgAB7|z~wKd`_BOi{)`aM7r zXBoY%4O9|`>Q|V~$JI4OSrMlR-dM(u_vvh`62%#?4Y6!snUx2fohV^qC(;0UWG<^%gt`Q5ttt>t#Cl6O*y?EaIHS_oU$rUiq9YSEr z8FjHo_u@9!U%bK9+n1P5D~?Wcwl;c<#+GYOU8X&qF)IX}PM_)ge00Rdb2pIDId1vp z3uh}!3&WhBp?4OOS45o*Go4b+D$=DMa&3wJwM*wtRW%9IQ&oW@IElL zEVUvwR=QXla9M8ph`;~qe~+j*;i;Z(C^!M<@H*ncS_`cuz8o{S_d3QZW=NzjF_S~4 z2Nk|Npw*YCtVdq1fjNT72znQxcO93{sHcZGZ&5NvQ<9GzzSF{*V+0Og9wG8Q%*>&C z>jJO1lqm`R0?9{Scm6Rx@?L)? z4l(~cDcRdS5|^8)i4`G;k|a=8M$P3s-=%!w zf}QVF2!+5bZh0Vo}Kj^cJ}L7(&EU4%d7 zRamV4e+sPGpTXgqnQ(k3;#)arvwSiat&wQ&(0&9$~=7=u*`JDVV;#}LJchONZg60c(7Ucad>DX<3Wx}i$6 zP>-9?NH)cZW<1p=2$kS{APf{TM(Yky+C_MS!J<@zh&xanf{L3kOaeOm9x9b*%y@7X z?tJv;M?L=kPsbnS?jER`G0z2u$|wB<3;Ouqew@$$qe7pba9H%GJ-jD`6(XXV4ycO> zb#1W566r8tB&25T(n=tc$SbT11PE5P$j9Y^SJ4{-vV~R-Q4es%2w&BB*Ni4eNnLx& zqsIta)6mf3yu_;(L_NH30Eu-K5Ua*DjO!)dG*u~Ah1Xi38Lx##>|W|XR-si${4q!w zhn>dG5b0WQ4s7UrH@8!s4U?RWRGvRd?Q?Ps#rXBeu>_*5-_Pac(Fs5Ci)LE>Mmp4c+LU%#dwW zF+CZ6B6iBvHRX8vCwjj>t0Q34T!74YO`TUb;}N<|*2`GhS|M&_A?zwETwNn{pQO7= z(&^x3iYaPrU1IA3?d6>e)p!(1cO55MI4^KQF&pMsC#FK)q8h4;9sz~z%>hzW!Y#C}Q#UY9_z*n)D1w+^q{p~~kfu+_pb z7NOK9t!5s$?*wfr*!7;udDg8Z6+uhSc}N6AQZjaqRVm0lbOlTrLJ{XZwt1ct0gEFD zzbDO&c<4M!LeLe0p>wQhMeRM-dnyRpY|U6^M+&AMO6OTtl9qsBD+()kN1IC$p+_TPWRji38zvUbd!uYH$`pL>~hFGWa&iZrIG7gK7^ zn6m^tuqUIn$s&+*~6zRInaf0j3Y_jeF7MtDowU8c3X zNw&N}K6pre`aSX~blQO+FK#a*-3;ZYNTCoaVfES1kiR;kE(XNC7UgtGJ)M#+b%@um zvU1}^_Fw-4I%`ic9#2W)80TxMYJ`f~2+=`!flwJD?qExc@D1%~>Cs7qDGkU7nRL-< z4-ut^!iH-pG?a&+vVg*!vnDn>*%OZOqgIcnb@;%E^B4&SRx(4-kzplIgk%%PBP15s zcd#uyQv_BBie{wHdFU$1iGYsx=!PP4Sp_FM_MV+alAwd&o(rqLYQ|SRK{3cXLE#;l zkW9Rw58QLGBn49h&&ojB@ThT!Q3ESa@pR9V0eo~3@IH_%%#E=5TYF`h?dK9Ch7Z5~ zI>m6xaOW|5uO5TeT>t#b-2eJ_5K+wRWI)_$2hJlYNqa47tGN2oGYszUvUKelcmCj8 zh=zY^HW<_0UZ*@h!5D!n3*P&^ZxVOfl+!$nwZ;)r2-0pwZ6(vkJG3uc;>u@lA^!}* zuSMNVC&);lBFSKHm-oK=EhhVq*c=aOZC&NY7eC9+55G#Xw9Wcc&oS6LV)^NpiPL39 z$2r@#pQAo~M0@Khqk|nf{dLUbA-iwCii$I~KJ_K4qYGqfmnn}=aY(us)^SzP&?_c^ zL?h9C*0wL;ZN<)OUuWgYO_Z$BaT1tqv_@M;F`Xi{q8JTmuWoYxJNpPJ(8&@aZXtBi zNmNC4-oh!f%l%XKE{taWMe2-8#X;3omG(*)gmwGD@hB_Wi8MRTGInQ zl22T84?*n7145xaY-xccFysk9d(Wztq0u5jFC_3JH>3n2@Mf!KQg1U7q;ski?^sS1 zvI(c$yyM;&x;SU}=NEv6BH&45^U&Gcpt~&@?>wTM)wEapj2`XLT3w+S9AS)OX?u+i zUwM~SyG6RR#O!DvgG4AnSp>be_UZ}($LMIl=8a42y?>Y0tCtx+-lMyGUB9Uu=kMB?mgPQ4rx21 z*HNfem#ovH7!4U8?%|E)@b266SGT!z`6kuu5K|8s9o@qtA&NP8d`vN!GC4U25caE| zLI}%Hj@Y{T42L^+kglXWet?|~aCL>L6qDm);%)~Ij1C@i<;9=k_~9M2a!^TRwv6)y zQYDmCMS1sis_}qi^*SnTLzIQ2-xLesG-aaSpXB~ zIdz6q2-*TB&C08UKzdJw;J_NLYq>D~%EQciT2f#eEJ)cj_heH6)6FDV;XSbkVbHYU zQ?)>iAjWfIAr|4Mtt2z&iSfk1Ze!=04Hs4>1(CPs@AHpd70)|{_tZA(l~?_;Z)q}!pr zzQLAtv^O@m(eF?dhP7)KIJvh&(rROkBU|p#8X2yA=2`aMy2ILyr;)y9@Mxc;+s4Zt zt~O_L96zb!+gck+Nt>nW5U>Z-m5(pxTpk&76w2hJf*R0MT)5n zubUEPFg%i7>u3oPn6hBBd&I>T zZ;>wdx$-kFHN79`UA_neQnL%6`4j+4mp8-CCBwjskdpqT?eM&+V0Jp=!i&!mFZH?n zGcPw-D9`fsD^ECfHOoI@)jujoJol;wUnf4{`BKS1kt#yrr?Q@+GSp>>%3@YFmJr@> z{MJ`cT2qwD86uIHOul^QMuZL2W zJI6Z+ZZnlkypAA}x+aU4Fp z8KSF}aHU6jM`ANXN+BBEiok}^ zu)-sOmK2miAe;GY=V9g{6`*B!T@2*SYcdHrVnMN=Nx_^NSxT``4m}?og>cL-lH>W# zw^J0ndNSnF?PuA1>RQ9`N=SGc9;3N2+pbU#TSp=4;fdVw`H5*MK7fOP^%pcE2~ zwwa7GMAT|9X%=s5Tsg&?AU&qDCA?}Rn*nb^kLB^ z@E8xnh6cwsRUq?`|S`A}~3 z9@pr2s3gKwH7bdN)|+qCi{comC9bwX|IG)Of=c3G=w&DiO4(dH8CGklLMW=5Yh%hP zloE{rrAV?2*@UZe*vb4FyH5y-&m8QW1AJ_8ICG4AFeK8NS!LNf$wN=a(ZuE+9mgat z#?%#p2q6WgD6m!#5k_O9D8-k6Qg|ntvTndC32(7A*vcXE8lhYmpJ={=t-u#mXrqWZ z2Nod5&CL?c2yTc#0s%!3xsgKR8yLEf4xt^W0x7_`Fe2;gVEj^P;;{?_p}HOQ+cQf82X}F z=>u*`G};XzmzY`i1b1v~=ebBoz-@qw1+2dJsAk7;5S)-FQiUhxdFQM2oRXQElPzs57{uko3bK~vgYQWeaAV6)k4DT98PQg{l)nr#QZtupWpo5HI5{N zL`v7t`1?k<(l^ivi;NSjv8Xs9(gC$BtVKl;)oc=GTxK((Bt}IsLNqfKVND4V5?U|L zBM8(ROx@@`>ae5CWu93Wa1gK&i*uHX9>$!ETggV_oAA9CXD7n!jgW!Y$~X2Co*Fu2 zwqdz^!ZFUTIN4`^fzGw3$&pm|-hJb z?&9V+6Fj@E)M7_Tg;?;zx;fx0jH?q1K~0GN<7Ox)ZMbu5&l3Q0F9gCpS&H@NcZiRy zrt`(}jCY_3IRp!$vrnql%?;dpf5yn@ee>BKPbl?SYZfbwP^uA~7eQ&LX^cg!7T$$j z0uvfnDvmHkiEnm}B#r}PqX|2YH3seGntSKa3XL&K`4N8F^Uxm8VyB#og3cF!GXm>C z&FWnvG3UcLsckBJe!dGqV?Z>7%#ONI_?0RQ2nnT$+ude&GogVtN5Bbx<`jZJY=E2F zGG6Mipm+gd&Y*4^fS|<-6?lUiwOTi?G&TiPypj~`K+8X*KnyE_~n z9MO6Dmsz^~EBuu&_WA1n_79o8KBF=fH$U|P4?p;jDxY%ygF6`OsGE>VviMG+dey|7 ziGa9a<*OTGNQDS}4W4A;2$1o4IJa06gPS!m_Y=?O?Du&bFPhg2asKbk>%B)s5m`?K z;)r(EJQkjJ>CzQeIvr+ZK@`P-7=UmyvNXd~1&61nY;JAQiW5!`4|wPO_eqzQXti4m z#$#T7;U%)jGZ;-nUgs^-yx^H@*Eu*kpscE}#Yc)e_wJ)~M3Te|#}l5t@eG|-gAcNn zJNNE0D@sn80WV9kaf&LYa>_Iyptipv!mf?j7PdB1tnwqcJbM z_yt;#LrTePJfbLTqDb-K2k#=Ij9a&#$JRO1(FmzhirTWezDik?M3Kf?!(=kWn-VD% zX_Aq&`V5aAap%MLchDdF~d)@QC4PjL<16 zj;X6EsNzNu$NP_Y^x*!&aJPjm6gMP{>#E6+TO zSAx~0KL7Yv{~nJHPjFL%A6E!x*dNq9edB532%dfEvs}CRY4X8ib{;)qS_Bcm>f93U zrF;Ue9mL8(OO14nSO~({cUbl0nKv&&DIvsy21cAWd~x=C520+=ECNC{dJfHAo4TrKcOwoS-^a@!p$49A zx64u|10S42&MI1|q}9sMNr&a-b;^8%DIMK@m&4;R7q+iqjKNeBoR?gkN9*wB08sE8wOV_xx7IUz_PgjkIbzuD#QiC&`9-llB>z+5jv;N6hST&Ci zKicK}LO!Qb)vb5UVj&fm9lYL~4anNyCL~QBqKqdBb%OB+P=g zUm2v~d{ea&f~C!i^xAFq4|a*7n7YiV%N(r~DvFUhYs7LaN`~;OE(`M6j7eeHKb;~@ zj}QI(ckZ#Vxk(hMW}TwfosYcoHZeD zav>3p(`4~sp-kKeiB=U->BVe{RM8paqPd37)}cBykN2DJELDWS;*3MZ2|@*ILm;pS z3!bwTuC78(DRpyx;qz_Xx?F`i7x+AD0Vwz&835w@z3I&l5m ze(qWJ_x9P}+haD%QITS4ZIezUIUbJjcxIzh-hKZry-p8-WtvY>Dke!|j5Q=WVmKON zObAgry*{h`7Q@km*>oCIMU#|UH*b+8QIO>NSQY655gIg7I%YtKsCx~lE*=H}L__n!5&RiZf5+MNq}-_|+e_)P5m z^!SLpa;$G|(CsgWy08e1r*@~qbGL4Wd2wrrqo`>nSz6s*C~4w(>7^d6RtslqilPJ& zbR~pTC@Cn40u@ClDY4d~q-1Gj4Lrn2+*pC5EX#%t=Gi4+16sYNIy8ueB$&kP*|DvA&`=v?@wW~j76N{wqoSAs6~e8~4K zNAf(m8+>%9m>cn2CHJGxpEnYpoaYyda}6&)%ewrzuyEn9&LedYf)q-HAtFM4=9~{k z?B}aSFm9#iNaJ~Ed{zYUPpmkh8Y%t!GRmg1dG`5Ep6iB*dEfFZxE76+nfGV++t17J u1U08dTY5nkG@s~O*as|RoS)c51^n;lv!>;>pjvSN0000-8l5@^cREC_vA)_DyB1r)WqJStMf+!eCA|Qw;B1wXx zAPNX5Dh5E3>;=RB_PyP+XM0Zf{ibepb#+yBs2Kp*ZWBX817R8ff`Y?IHikMpPR=eo zxL1ID_rnLsh#p~~+E!L(;D0SEqX61@K9ksy1^$19*3&D@0|3Yh!S0@69zh7c4FIaq zBa{>l0A@!Xe^hwr4$ej}0|`+O!4*5$=NE3=!S26s?=Fv>jV^+x0Kiici6kEY2#W}v zC(^?QkwZlZ0G2M;(=QlddlL@g~vut?iK^w?NmU5h{b{zQ`;B;b ze!vrX{-JyP3*8pPf{%z)FA(-;G&CDp1FeQOLs~7Q%A%FgDu3SfEjBFv)#{h7K1g4Q z-xQtS+DHDY_6PkEN&nWz{cn%|)X4zM>`ML3AzdTAAiepg|35Rv>SOh=Mpy%^2r3nI z3)PLfk9v%1K{Ws#R2!-h)r-2fga2(5;%}>vcIRt~jOYa-cE1Jxj~Ye%<@imd5~WfA zHoN=*$UDEkBRK48?e`y2B9Q8iNb*PCnf{&QA4>}&)>T03pw$sOBQ{1eq1k{0S{|{u zHd+($fdWF+{r6tKTM6L3Ys<*pxdecB2o4JOiVoiibls597?PilZ#a)OvRitI^B4zv zNQ(2wO3TQCoxS(h(*9<%yQe}-{r}L2$X=){3jn#!KeP}eHf!^d<#6^Nnjo^ySXBVH zY2y(=iu^@G?=%=>N2f-jpB33T_<%5?rz}teYCsF<0~25g?0_>kfLPZT1R)wnfg|7; zNC6oj8{~s?pcIsYDsTP-?ao+#>|tyswgg*;ZO0B`r?Ja89F7$yhEvB`;)u9#Tng?i?kcVgH-wwT{lHV; zx$&}i1H2197@vqQz+b_);)n2a_zf}|G66DGGD|W~vKX=~vI??hvVO8zvJG-tav^ec zayxQ=@?+$Mplq9&sjpw^~7 zKpjh6Kz)n4pL&soj7E?~mxf3aPg6wGL^DRSOiNEILu*MJM4L%_h4wM+JROcskWQb@ zlP;OAoUW5@njS^ZN3TooL7zllLEl9`%YbDNVlZa#XUJf<#?Z&G#7M^|&*;Dy%~-^E zk8z3##U#jN%oNC!#dMQtlxdxrlUbYDi#d(CmU)PIm4%%}i^Yp2ou!Utgk_zThgF|7 zfHjA;fpvln%_hob%@)OWo~?^*k)45EjopJio&6^JI0wuj%3;HCn4_Gdmt&cei_?%Z zl=CcSC+8v;6PFg3KUW@CE7t-yJ+}t8A9o&i8~1x2MjmaRK%PRL2Ruu>9K1%n5xf_9 z`*=6@2<@@olenjD&jcSipE92}Umjlv-x5DJzd8RA{u=&q0Wtw)0bhYL0^I_uf393!qG9xPraJ|;map)C<9Q6uq2l1b7`GEuTY@{<(5l#5i3RJYVmX$9#(=?dwW zGITN~GKn(HGGApyWj$nzWQXMlat3lo^LvH%dhM;) zJFUJ)ov40MeM*Bz!%gFY#*`+nCQ-9Y^Q{)2mZw&w)||G8w!ijO?N2(=IwYMtI;*;> zx^cSgdMG_Zy>z`keL8)6{d4-0273&A3~CIP3>6Fy8@3x^j7*JkjK+*PjXjL3jh9T6 zOyW!)m{OYBnw~R#YbI(&GHW)6%}va6&0kpvSOi-%SOQC9%UsI|DhU< z*6(a&Y>wD;+tS+}w7p`xVy9!5W%trv*gnF(!-3kt)uGy9)ltv!wBwYMlvAA36K6JO zKj%gloQs1?rOWa@{eAiSW?dCrQ(Q;)3+<2I|M&pgfxrXz4pJW^9=zp-adULL;BQ5C-;*4Znv*$`6OyNo8y>Go zp-Lg8jGa(BQJRWQ^-JwblS@0B_A}ixy(dFDqab55(<8Izq|C{}liR1fPxWOfW}VN* zW(Q}F=4j?rou)k`M4Xu_G%IX8%YQce?B+S& zb0bAMMRmm-#c9Q>C7vZi=e5q)mU5P6l&)X!yYT#?;l=tg!LovKY$lGb*<(2Vb75vZ;DdtyEooh2u(A4O|mZvvAe*>cBON2i_>k-%A z-*CGzdeih~$1UYswYLRs7vG`3lU@(i$J8%1_%=*6IyVkBnKX4Yt2N)bD|z>F3vWx& zJ;r-kt>mrAt=ny}ZOiSU?Thz)?oW3d?0DJf)H(dX`axfpY1gBN1`j*CwY%FMsXuCY ztopdAN4clriQ<#`UWMK}PZgft=~L{h?^o(?98ei(9^5f0n^K&*_eSqc?_1lq zFQ+}GKg@*9Y|bXXBfKk^yGPl8&R9M&B85_t>&Mm zKVNMJZEuGXNyOc&01BzFw>JP^FC%%2GXV4h$en`fS8nvXppeT4j65A6N$3Oo0F{Kc z#b{xLaBO%MGH!Bp3Jb~rLN-+s^&+hVofmyM!!(m9a|}xx8#TKlM+N6M?!7$8yifUP z`E3MF3O*4AB66bMVrRsABvz$_rLAQWWNYL`6ktUerTxn3D)p*w_7c>UHQY4Qv~Fm> z(#7j3>U$Vu8#WqEnn0%fW`^ee7Fm|Jt)5%|uw}B7v$u2zay;o&>-@y!&Auhq)%_a> zfg3rI)m_3v+tbGDptqL~(bv{*uRl)!6fhOo7IYyvDa1F_>X0&tCk!9I*i$+=S>v%Y38 z=d7Gw&Rx!1FF>DREEGR$c+R8fXmMdl?fJISCl`h00R*7-^W4nTaf^thd=FIVd>gxb|@;@Lc3= z+w+odS%5;2TS!6JSj0^zmk{dYA>9M_a^OCRrV~PO(X~O}ERmPj^UmjB)aH zwsX|UJsAazu!&U0lTR-%FJXv#D`?x-^Nx3z?>whuu05XN1!(J#XDhn-! z?#IMprLYUQOL$*0DY7;49*R=RD1r@@EHxGN3e5}JcDic%T!uJCA0``Sbrum;M%GQX zdG;ZWR?b?ka_%CY0^YnmS$rw{kpe_PeIXv9AHuyNrJ`YCM&i5@u*8DonA9WbW|=Fp zg>nhg8ih!HOC`PCeDn`uU)G4g&^nu z+Wvb75)SIR;oSy_#qI$fdp#*V$Gt9lAM#Q5+4ODmOYqkU00HfR$AWZ&(ZO9I$3wM4 ze;leIIU{Fwb+~2t_lUyCy^)hq3DKO<_hQ^)nPSHe*BnWTbBY&^Upd;DkbBH0Q7=g} zndLY|3P|~WVmkF{T3vc(1~F6qB<|$+sq0zk*#S9*r|C{V%-xr}m=~L`U7&L&^(_8e zdeKY?>v`Eyl?y5t70RT_g)4Y3u~yPvCa)r^rbZ%3{i@rw6Sddso?YL(DSXT2_USu= z4GfLWO~uV)Etq>Et%hyx?MLsQ?`Z9O{b2hcZ@2CvpU0U!H=d04ZuN=u?;AKXIQdL= z_~gi^G27=&c+tDBm$tbUa zRxpHQ$D0rxBm!w6`C%Az63GXlsuTIvH&kr|tmz2v_okR=!>WGXBsLJ(OJ9TB@LeqJJ8 z(p5@Dnn8L==BexzxiooS1rtR{B}S!f<&P?pszYi$d%M&hXmo4#X^m^o>#XPjeJrxi z;f?UdWG0lR3}(FM@)j1B!B%#DyH?NEl7bOEx>caw0EH zJiRN^>l9zt>#6ZzYPJm*x3&CVaZ5L0%cV*Ij1^@Xd_wNp1P-agPk(Nx>AzfG)z zyUXBFSubV3@ZidD&Y19v!B^*BpLsj<&TV1sBi-k#U%_|j6_wTPweKZWMN`dDJ5%@37|^uSYS6aP>C*Mk+tN=U zndv%X7LzE`6XruKOf2=R)~xT?V%Q1n6&zX|Gn_eGCfroq6Fj$gPwnyJ)8S{~{~&Nr zFk8r5SVu%aluisUj*-AiQc2NC)5_pw)@0}9#^iex?knC`>QR2F@>Pv$ue7?ghM#7* z7D?Mz$4S>vPeoteK-tjH=%8`D$wkv{vn305OMR;V+th9!T7kN)5m<0Xp(zU!c(znCo<5Psi)YpI&%_po$__hsGU_SQY%p@6}gBmdsq=! z$$t4>wR;WY)rs1!>-{&E@5nS9X?oH^-Ky74>Zp9M(5>_MX0J?N@xa8;_u((2bI+&8 z=U;t)4ZR_sW|-xlGg>HERQjC$t#UPRt#2cFvvceF&$V6u!^rBV1zbP^XaH;A4dOrn zxDI;3dx#7YgUlfkR0y?0?_nlb4-SVb;c*l#${3Z5YDaCM)zGo%X7naT8M*`yiectr?qfN{>dvOaF3Q2cvB5dP)yRFCCy3WM)l zqEur1;#v}Jk_l2J(v33DWWUL?DHtmzDs`$*s=BIOSH~fD)mH62I=OmG`n85G#yl~ zh|Z{p7|+9>;wutjj*TX6Cd0?^DKsbKQp3`QGwd@LPNil`=Df&F%~vbd4-O`L=0lis6099{hM z$>4L$QpuN-Un9QheOvv0W!Yl+<%;jh%4+25!VlLU{cE~wHS2`+(Dk7Wg^j|EFPp}j zWt$sYc3aneqJBF4yt)l-+izdl@qd`Nob2xL0a5AzfSKIh{w4?j?lb^fIosPCW!u|Z zsCUeyMbPOp+v6mW6HGydE%scwMga=A!i$UK=dkIFr2+pve9RLFepZ^64Oi z0Aq$TLy*1Qe6x9cc5MEY5cxR+r41OgB=M;O)0b@2v*fuOz99O{Tj6QLNIdJ81&Azkdsu@88!UtE;Mk9qJ z)fxdvDe^&LcmqS)%;r_KHYg=B1~4WY3bA$K447k+Q3elXFalyL!TI0}25(PVQ;iVU zkX8X0F*5nDC#~j9O6%4+AcWa{(!OqUAY)|9jB@(O>X{t~Qpl0P5SyGi7;mwaX@!&{ ztBBYVZ3MvgUxG)<9GBBb253$Xd1_n=isIkFmE16s}Av>I*D`prkHxX!fd zA+73lq*d&o)!HNwME;NlE5atn4lXjX2O;t+na%B0Z1UxnZFj)7#vr8_^19iiCA%>J zQYvJAE`vcB!4?co`v%jB1j)6aRgNqfH#n{NL=~@qRx|oMa^mEOcs=}nWPy-UAQ1>D zN5rg==PAG#F%+u?BBVj&g8zF2F&%KH7D`f(aIKD zM_0Jf2X{lzia?`Z5v^KlOdKOSZP0q;OrY7Mca)yNJ?T+eb1v9H>&}NcWMXX$Mr%Z_ za}1=Fk%KeF&h;nlx|mWKDMZE?BZqC7I0G&+kli4FWXlR5Mt?h^km^(q&oR0x4j;+r zzPdTOFi^Y(Gg)k|lIAtgDqb!dXqEy;sjO_|?wlWzkDbNFJ$52CJhqYj^ znPofoh%z-YaM`$Mgpg<$v65sfgUJsboQHv2X-sZy*qv5jWEEta7?pph8E)5``{Srp zDi<$A{;eL|r`%jca}Ds#No&q9yU;om$9JO@V0{%j?OZIlL17H6t{}nyN@XmueR~yx zBuP1W;w&rYFHo4@$6N2YjdH;y)hVggsMLTIBuRphVmJtCs?l0wDTPuBV>F32SSnM- zk~Gc5CW&P!gd99*!EoFe*%`#>inVDL-SMzSp3^`f+wx$Bn%{Q0dQ?o112VGn%8_%L zEf;vjv~D$XzQMGPFu^OMl|5+{SE5zqy3eSd@fu-tHjji9Aht1EK9|L-VZxlb1!OzM z@WupaWBA%Pp1^zfD;!IEeDk?FrD}}_-g1bOFI?o*xkYR#i8X9A+mwqQ)01NuZCG4w zP%0HEc@D=8&C>05IemVaYS|-B4a=(y?l^Xc>3Ws`I^ED(Bc()1 zxw*RL)`jg%J+NO7CPJDTEK6-#!q~Kmr8+b32_aBwV1W}`c0n=N`NZby-Dn+{6bE$3 z!9y`y2YopCazn#V^vEaY=Bhh7$;~bkZJ=L>U1{AsGh695I~SL0LF?x4ccYb|j(1HU z6_vL>gjFnpwCFzlb<%#2P3km3RqD92^Z4hU$E4|=;@j?wF%VH16{WKOEG}3W6LjW(^0Po-SIwQWj8mmrAf_9LdoD`*U3)gmB}B4g<1&o5Cf6{wGuDL4+6 zk|f$tuayIj_lm{0fn>3{W8~Z9 zzS%mn6IJ?A%(<5q5thxJ#|~00Sa`0>-Nz48D0;+k!s7A@cOE~=&q_))*{hF+WpBhY{|(Q{mqB%gbRYl(qNz)X|b(kD4BhjP=NDbN;R6cVY+otF_lspfFA&C<@ z-9E184LzY|M9ww?yT&fG3e3=qzsXEun;w)Yz#^05hGQ+I++4+nqTc9gJ`%!_&ziw; znKOH2@?Hh4yc$~b?_WKwBg}Y}D5Nnxsc>~lg2Xl{0!_&z=vcG%nSaY_8X=2yWa%G~ zuAFD_3{3W2~>+HfUPhbYA~BeNN-4&wMWm1z3{e!*?)cd@ zZw%UKmRB0sj>{c~=TItNl}9Gim1rHr=Zvz;KuH)loQCH!TbFk;n2^JtiIMxuEj)vJ z8+En~_Nx(Z?X{yd*YozI)iCs(yd13v%$L51`OY_AwN+|VIs-QSAyT2L!F;J-@f8kdU<8>@jy~RxqaA3C1{PZ{)fvqG)Cm5r#rO0H-{8~=ILYow+ zGP|8}6kfiLNMUV>;Sv&DTjeIgbSR%2ZH5Cm+~tiyDM@{-JhC#0p-X@8JO}@5QHt|7 za#S(S@7oxSF$TxBn3|}JJa@s&L~ZyKjL{?GWnPxn!35l#ZYDFi3NTwN>H`r>WY^dt zkB_ddgP=bU!k`B?F!B)1a6X$ih*qwS)`1m4YhEq(oZ31iX|9ei=;(I1Db`&ThFfWN zyj7b!w(ZJ$Z+$zr#jO^kEyr$IWriOPXYW?)i`kR2N6pAPmyT`pY|%U4Y_yJQ6IVfN z&M?=VRs_M^A>z3UpcFSOj6qat6laeh$0rdhm(Oe+(Y>&Je9g-oyJZ>Q_Bk)}*~`&z zi`JWpR^98M{r)xcV_Y8?L@t`46xP*mHLvIzyZ^>q;n-_Q!!25GC|YHyf-F^D!H?fS zz+Rt*1UGQ-$}QZ&8;4traSOMw3vMySE!@H`xWyQ^a0|QO7GvDP zE$o6@jByL!br|M*zXrd_EylQo?+OSZkWvyw5zS^3Aq354YqRRiD`b*eevDhVsWD)P z=bk%(W!bdbZNBo=uk*t{^dY|Rg+Jx5{k5MYNm7c%A_oud&vNXq!mo0RF>c|e#+fr` z@jQ=*AN~%HJn}fDa)}EUE^_+xSz4_Yy?&pSl@)&SCqII1XVZOVX8L8BL#$jnee<~` zZ{bZ3tu>aV_}CwQg0Fn#YiMoQ*w{b_nbp|Jb4hewK4<^_eI!ZB&;8ub@O|I=KH@mO z;`wjw7`JfKK}yMq6VLOlZ#~TA%S)`UZ%`-{*th=xE6YnHNwVcwfQ5xiNGUma@)T>U ztGwqu4>CPHwdc-pOZmQqn+{rQJkRBu-}(+uKl3cc81B9At^CIS@=rN<=r9j`&-Zcn z-S<+f)zEn!h%pAOHGlf2f5tbz^&JYu(iMY!Z|xYja8tn;!Qy&j+c+-G>^=_e6LKJ?)a?OKfyt|w#Uwqujm zS-ob^8Xbq2Fhmwg2*-gmeO39yMyHrC%xbHaDuBiWS)REnRbDoa-lQoe3NUekEL9Nd zmSlQ8A%x(}*%$cMHy>s+IV4R}KL5GTaA{$Ix88q0Cr&(zANaJ}Ex!1<&+-eu^vnFK z|NURkXl&$#9TbjZbN0*`s^uc(a%l&1Tqnjb^uO~}g7Ys@de0By?caY@w&RzDPH6n` z|4sMtZ)4(wslW3-V;3cBANy_WBllDP@xO*pSK-JJ0u%ID|JZNgpL`Zko?_yo{|{PU z_&uV9i#T^a$jq<&y}i#R1Say?_``oo@9D=8g$ZW=yWhZ`9Dn&mKx9?Cw=Wn%X8G`# zSDzdGW`LzEE?m4szwZxM`>CmECMT!pbUOTR|Kc|ZgMi7&DZcQz&vN0ydBQN@{&zgU z&}aX$3nALfB~JqSYZ z_~Vb#@Avr+|NeKV*Xta+?f8(Hyh4HZzV|_@)$;2jN(m_mPCrSsuz;{F`cHj}^d~=x zDwnpbkS30@JYZ!bB&59_*7yX%veDfpX|IQ>j3JA~;qTIR6X)P@tnoT&KL%mp-T461 zfA{}`8lOWr78z$~(&h#_2$AIqs$9u`-$45Ts#Zr93zXjZ5RE_n_ZUEpPg8pPgS5W% znT)yp9wcFQPqvfQOHEURTR?gRupEkSdk?boe}PgNldfDwm8u!d0BJ(fT*qjz#wN1y zc;YWv`j`I`h5J8D@t(ILizT8LpJwS_{$s4!w@|$A9jHnLStvmolQh;bhHPw^)g1mN@O?i0>CZAhH_MSD2d}>&pnM3{k-P$Nmld6VIUP2k?&HjnF=g&-@F{S zB!A{>$2KV?|Q6-PwH@`^d8(*dQ#owp- zg-=j^-;d!PIYjG=zelvZLFw%eX2;+54krKWU!(la_fmTMyAeuY&)>nsU;j1AZ+{2P z&-^aUKlwD}@A(Pb1M{>#|9b=%FJaXuh%cO>{ih!%T)2dL`1Wi^++$+uG+||ViS>;J zgp#n=$_xpV5&;FFg#>TLTOtabK^r@3%MYVR~ zn(i1v3jAjtCR$q|c=lTmG_ud0{x(VH=dmi8I3?Wzg*)#>D1~s#O#k=)UkXQ$V!|HY z?ROJhIFIi2veGMIm*DhM#2f3BzyAlRKJ){0zVwI08$EcYpto6r$&v_bbHWH);@$B!$`8DcjnDrv z@zO<-W`p9pK1kuV+cE`txC(3J*bL+U)h{7+i{Q*D;>C-^FFlGe(0}}E=)bF4QRgND!!s^Nr%~qGOu`10*lS09x z-}iA`hcq=*DkT~l4N9dF-F_d}v2k3FIPmd`Wpom9>hufT|G>K#bL{K7a~NY79~@+JV;}oCr%#_IiX!S06WsNdyQxo1@Yzp)3eWRcT)f2RKl^FIDCD{4o@HfuX}Bm@ zmchrjVjzJm`T|7s8@p*z5&QiJmZJPs^rl2+U z{@d}6-iCB7Ha`8^Y<&E8D1YBi;U2q#;QU$8dbr!9?Iv+!9h1kom^9ALlZ_fiX9ayt z6cR07!kL~#`+b^!{M$6X@M)?)@{72sPjq=9t8F@39dER#tI-IdD82gwwEp5x=zQgm z5mGVrkzdWqdTw82jKM@9X|Ds)!k(Kac_}Lu=^TCwrTgBBNi@Yf@23CoxooWb4oPzZ z>DWUN&O}|3<_09)%!Z&f?$LWFzU3ZFYAD`*C;f+C1Z{AR-Gh7J5JK!d5sgl1b^6Ti z+t13S1x_q4VY?oVk{mobP8|B2J$sHyxyU1@PBAq*$I{|ud_SO2F4JjjP$-rumrJZJ zUB)ZdXoNldFrwS(;<`4K+9aOmT{mXfj$*MuwOXXrY7!?2U;T?er(CHpIWb9nVv;Bd z`M~#o5Gf@qE6b#5%Eb#8==Hj^TdlnROG33$OlNe-~%EPUq`?hVHhA*H$RL?cG?#5<2M8_|$(Sc;R_;&_`Gm3b)^h|HRkv zPdtq=8r@tYZLX7c`;_i~i1_?T!gHqxPCP-fx`^(#(NRKl;S|Bir_ezU`|zFEV^#c< zPZ2!#DBXwuobd7r#%~k6cm{Mz+E^iNHAuTXqJ?vWXHH;zAB0Q)sc#T3yoB!iIEU}0 zaK~K)&pkqL<~iIu-_68FKDxQH2ua#lqW$I1kajvm7tY{6^C-^k?_lC*e+6M8f|E}Y zuPhQ@K8Jtm1ckdEK*Sxo4}X<-`2xL1zm7I8?#vXOzxoo%>H@vT{)(iR;2k-Nf9k3H z_b(Ehc^+r~QQBYm6w$@==zbSjn!-DFY|rN*q@>?%vb4O4-|M23&Dg{wW0f+g5ll?f zSy@^nP7-Xlz~LiDSiEqK1c{QF{O%Sj96of2IP~fDyRriblNm7m;yA98EIeq#JVHnbAG`M{E675!t)2B|dyu3sZ_|)r@96WT0QzuW* z>-CtNoaCcF`?DN8aFEG~`kr|j*EG7;f96|+3l|a6qWHFlK=C%hzo_z{yavo_5 zqQy(t^G6UmByBY?7~Es`;vPIi|M71SE?h)a#wgtLPLyZS{m$3H@~|f-i7vc=tWF|r zh3>ThQ1y9qzkvySK;Yf|ZoDIhS^xci&iWsHjOqX3HyL~X_h-#W0E8fIuF(3EPa>)l zn4pI&R4KmWA)MJ+Oc>xl`v}3gGYDnl9KM6Xo%ex`=zi|lJ^Fs1`gk4J zb@=sP|9^4tz`iR+*k0SPb18=n6OGO$&``m}Y)-1d=Oc1DS`VFH`Qe-0cn05%6lmUB zuzTb@d7G)hF(wz02In0#HrZS!Hh(*)wK||bJo_}u|LT8+;ynBQ$v;Dti`$gkO<%$= zGGx?oC)G%^$b3vjd?~|wGY0Z;8q%zDnzz&|*7<#G8@HE1*7j|)^VG1)rx{c&->g>N zY-|ul2@{i3*p|w#Gg6cH3b>Mfajh(4qt{wpYv8yp|MuVfJI zVWK{^r~hI|@2z}{U67lUm;d*FOz)ZJnE4-mlghi_^O`Dlzfnk& zh^3`vY`4Jl^we-c**a0hkRheqY)rG+1Ae5eK6{&I2gi^47zRo`0Try+P^zci)r_G$G*RGfxp}$;3pRG!6-(gi5K%`uaLTNXpe3CJqTx z!^C)v_4N&EwHl3PgG!}Br`_e?kt4)GAIo;=v|F@VEvjR6ibW4gDO!yNou1Fp+is)V zTxWS@jrv5LjkR@3l?uyCixkTh%H=YV-=k0&!^8pIe!y6*O1I~8=*ST~+j>>K`b6I8 z>8YomqdqZ7r`_bl$x4nb7zs^ewi}d>ehmRg*V`Z5_r9`z-;idEE*>~s|w;evfV~;(~_*ji|FTTX| z>>RyLg9yb;eT>VO7T9;_FrDTaL1?Iz3$)rTQepG1cRfg@?7gOV)4^_)rYYKhr7~ZO z-rh#)DsXd!osY%_jo$2*&+{fHgGp@$GW^JjKWe-lh(|(T!akj^eSvtROZ}(+2ExvN zKhPsa&$k<0c|Q#y>GoruQQqi)iU0X{(Jjy$@@wM!a+plOzbKkfk!Z)6R~c-G_8Nj85?%`x=Y?;vb`? z?_lOv{}J}&G}h!ay5AXVFi?9sgrNvi?MMmjd}+A7YzLkN=)Enmi( zoWmL$&kj#w;>C+3ttP5Afiu6Kw7EvwZe<%*u>xs~4t!L#jx{k&+FT`CTtGM_+yjRZ zj{S-{1$Da}q-CQ7B&osk+|4nKLr$G~p2J7)pjdDSf&k01aU2I@H2uC$u~_7#7tYX& z;hwkLNw3?%Efmm6LYySHu8U<^xsM3%zlm2&pq!Q?Og9U341KMBvDL)K@heBXy?|H&UAN>j}JqkoQfa6ifFB^LkL zuj4=e48kd*#_Ci)__Nd=dM~U0_dg?AS^+e|Dl+lQ|A6xS?*I%Y=(6(f{wcjDA3;{? zNLvywUc$ZOZ4mbeUp$R_=L5|Az2Cqp*lhgazoGNZuOo^jbf-o2hkg-}HfVnS;}`_x z_kVhsEKU+^ z+kru|%aQhE0|mL;>EL<=Y}?w}&~g_=eBeYg25j5fqKNNx{FTo4M&QO^&#Qu<^zI+X zJjGTKcmF{epZpyfpZxb|98|4_d;8mQ=B7xyeQH1a*D2g~oZ!?W1Pd3beBTd~_Sy({ zjKW*q0Y+1N$NO>SW-(f$#wMwK_$Luc;v9Y}v;Xj)Q~UlOpz+7QL-#x1r1GI(VB)9$ zI??%OXngt)&_Nb?i&LO@?*r&g7P(t~=!cM=P4N6P6yEv}_RJLi(+?9~xJdu8udwmy zKfv1m7G{3!pCCj;^Rxc}YyVwX6LoaAk9Yh1ShX6mHb?26`&s{ke?_#sO8uk%Emo~e z`^*2CXm#bP60?MWwbf;soepcOE1Z1xX`Xxj3{t7hcqpZCY$+u@lQO7j#6sx{s5{}L^>Az$G%Rov6^QQrj*|G0i4hLKFR6@ zf)h`IQ=#%bKZvvxMr(xaVol9v^1N5YJ9Za@EyD9>5l#X3;4v(>hj47tjb(HgAw4H^ z-W@oCPzrnI7}fXxD7~+J8e>`1KKK#hi_Z{VTm%f^x#ux)j6Ht{XZ|3nQYGG4M3%-W z-TxrL3m+pqdxB`;CCU%|2&$ln7A|07L+cCw3GGKXbNdmNg&4@sQeH8t_Q~&jlhm%z zURwm|QW>wYviK6pa!Ep;%ES!!-**ouo_UOg%S%|6MWt3}a=gL|FP^7fpP*1GlSV#q z9MfpF*ni*v7cZQr;1%inKKH!s9mvFIz1by+0+KXgqtWEhp~EC`g3$^4j~s)j&!dk$ z#@P5I-FAaQWgJ^+mX=nz^PaadUQ~SI6MxLTZ+|D9Rs-Ain46m;4Esc3K)dVHSz97h z1wQfdk) zedKRpPfujJLBEHpO;dXNdue>`6Er{npYZPa9=wAGx5i85uXS&o@TIdz%OHzoOdOGH ztUw{aL^1Zolu7_G2t6`FtY2l!{sQ~%k&jWaX7 zCvzlm#OW8FBMy9~Cuit~ZCb4!vy*k6KYfOSN00NCJCF19Q%}-t_ZV0-EhQ;e%A7oL zf;3IAY=q`6!o{+f39aIQiVuG`lgCN)cOG#Kz)#AG{CW4{2_!@WQzT_D|Qjv~ZDruZ0wX zW-nx{=u(+1(rq^pmFlpF+O@_tjg`9I5K>`+F5QR!0^Ax?fAjB?Ts}>3_IXP0`!Qk>3jTMy#A0jyOG~wB2@lQU58r#prFZ>$L+-&BJP69SQ@jHa)U&JIKY0x8l{wYix zVuT@h_EEIo!{AW;z>gANI!k!=If9cU(eBmU)nP>5zeUx}@gW|pKp!M0`rTfS?C_V52+_|}38AAxc`sx~Y+^pRnLkH%0`te7&?Vbmish4PW`rLWfTWD>pkV=cY@3{}x z%2G-Zf*=SeRjQ2DC%NtDQ3}NpM~)m~@zMgycA4LQnBzweaO(6aO4S-ulT#!~%HhL@ z@cVsMmM>EspQ2hRU7xvj(Ip?~Z#hy>%A;$*&;Bj z_8q}JbPORgcXV+28KUK7yxZT3Gdlx-i9*72&l9h$A`2rlT|7&?zCqzF_aj|r&ml|G zWN1Dfy;aMy2!jBG#C4q=QKnJ~!Z5<~3g|S+Ls1Mt5MtXlQfB9jj2!ZeSk%RCTHl1?_fl`Vn3UeQXg;Ihr43Sa|z3;Yd z=by5-BgSLoAFeG*rV;$NJiqV1_~bt($*RqAO9_yU-}cKe)XSb0fD+SJi!_T&zXU8>0Vy?E+G#Y>Q`V9Y8tI^BeUYxEXhhR|%6QL>B?TH9yK;M2$^i)hDjrL3Rso zO5A)q#;b%-7Vfb-cZO%&!Y%BAHw|L|H)YuPExa+fi9Fx8a0{;=ZZXC!+`=xn#Td76 z3%lUWrDME8ym_j^-ogL_v&=2V*aM+4`1+Rh>dgcxpe!YlTa2+Q1hAN-JQXIlc8xa) z3{Vj8P{E}n#ZJc9ULxg2NE+Er-|In>24Z7wF~*w&2Cxx(h*HMTYPE=?2x(dLdR^)h zQxrTm&!5c#xrCI6ZJA)BNhn%tv@uv}GhRN;!yuGWq-ly$7HJaUhYtG2)GZEsPia}Wf3#{2)rBabfZ5+q8n4Xe3>8Kfo&#nV*|yVqzTI zwu#~h%W;^Tn#6W&#_Cgeu5-gN#dZv;`z>`EG`ejflM*BmBGybwm(&kvcG@)jF8wIX z8nx%YyWwx{O@J*shS8eo+5JpR?*sI(+~)p+2hiH!x*q%X&t;W11dLBj<9P+7fG~;+RD1 zAtM-L*eo)6W5WPK8w!rYvC0IOyA9fYpTpI0?wy?_P80f3%tjE<^!s%DK9SKVX<=J7 zj%{Um&Wr|Xn_-F3?bm``#IQZT_-=$j3`&=>wF=Rz!4BnHDuvuuuzC<fa`fX6zJREaxZDBah%Ph8_Tvw>Z;ycFv4JzKp4$j zrO14(!k5oJPn5wr3pm@%7WX*r#5d7hFw~1At<;73XaRT zC0SfqB}fe-2{HXX%77!llaiukQ*vxdwoS=$C@2d{N|4#)&3Pna&LK59T~}k(%a>a% zMnyZZ`TjlJ=fg3r$Kp3Xrxzn+RzYP}pE328cvTU<{2Ug4jnIP)1-QaV&`=C9brx zoyE#tds5*liOSolDXB8?HLo`%Mjy7w-{+RHR2Z85E)};x!KiGJz5(Y(k{XtSfS%*w z37f?*;8+w>_Oe=8uLe69!z+#9xWza6USBuFQ6InCc+Kb8QA7-glay|p&`mWJ8_MF! z8+4o`_$I}*9V{U-BZd@6qjQl)Wckr5^Ua#P`e#VysULKfCCd7R3zJQBOB>!bJ&j`v zv>&5|AkiraoBb4oQ6xf>q?%?FA&eoChD*%`_s#C7TqtM98z3*`DGOmTg!=M|b>5_2((_}uyD`RMVx zsarOCT}>d^hy%0$ODU?h!%CEbRG2+Xw}X#|l?KH&Su`(btaQRX6EjSDnGquaQlm*R z+5e1z6qJEW{VpHBaGF$R#S2oe$mzy98@(>6fvV#$Td7f$3QY<^zTsKiY3?`6d`6i_ zf3ekI%=H-eJcI@oj?F$^2KFlhE7_Bfx}^Skc`jQTO8ku3N62-~9> zYtC*onJc(dT#tgXhAXU;0wp90!Ft?BDTNe*gOd}iU0TkZp09Su^2uT&v7{sxV3{l? zNJ@z_TB%ckkx)uJY~>)OjS!#^^htRs3Nb=rf*uQ4E;E!8wN}i zE2w;-)NEekwJwR8Eb>C;*~yj>Bxn{oEmD!~cv(eyfwCQ1exLPjpULqO2K|b}y*(Mj z@3tvcYNS!0#zuoU3J}twQm)WxH;LkqLb1l!m_p}eQ+k~ij^hzWKK))BFr-OJ9LHIm zqQJ-TO6)su^t#mpdP8A0Lp)aeF22!NGJ6=pve7_GYg%zM?4xE#IMeGQHpVgR2BeW~-?gv8`-zunU3If{JZ3RV=gK>kR8%WfObAPzDrOQOfaB zg(G7VC?#kH0cST>DJX}jVqS3(L!2h)G^H?L?$>ZT0)a3BX(Sp5b;?3}orQJ-Q7jF0 zsz@g2Fkqio;y|@Nv=CksQOYfp=yh9IN>QoSNRt@HE8#dUN-2tVh1&Q8k>4gwHHAV6 z+jgnc>IgJp&_^kYSVUO1g8^Kxh~pN&JDDPf0b-MK+3$jt`DBcM!9tz&p~x*iB3n_F z$R4Bme?E8hTq5_6`xfwnEIEo$K?He)pm z0&P+}DY$K73Y%*EwfR2HS)<0#z>QxIPzb|sr1GoO`_NI`%y+08a8@;TBNw* z6Ci0fYoRb#UVxs;xtCb3AV_4M@Tj7At4aCm^w%S0AUQW z;L`E3b_h~~NwZF>CIu63MxPBTzh7>(Nio=lEjo!#4g2jP$Lo`r)R0PptpxMq75145 zv4#_?%RIZfh?atVV|6^~(29KSnVG{+V=i}^?6)WIl)B^(^NnPO$Rd{wj6PrJeX38>?dr{VMl~P3&L{zt_O;y>^G!n+coZp}@$MyCR; z$$b+7BeI_BS|_+wkCKw4YICY=?N%iigE? zrOM(K2^+)2Wcuzi$$zPXUlE@xdJReYLhucP@AFhT98OVBkVA4+f0?KH2r|7+5|Jj zG8&CE;7CQ7CL|c-7KLl%O2&}p#@QfAu=2z>5F|#@KX`zp@j9*Zr+NMZAEcucHDRM= zfxZDpyq3Kp!>yd}*ND-DBoT(1K<0tu;m0 zdf7Y-Z47=K<-5u5$7CW@9y})mD1oi4O`ZKJ*1auFXh&ch!CDydg$rl+z`ldj-C`c% zEzm-tjNxFhMsso=Y=`xJkMUv=PYF_y>0ir!mjVi3N9?QBvCOD?4?z;M+HDVuR$Izq zcD$DDei&40P+pz$KljV%JMZDh5B?CIS0GN|l4|mNV+kvj9GRX*h*uwczJoEe-dtOf zB+24WhTGDWo&S4zwnxLx&7hUAF_=LLtYz(LwKB#KN13_zX3*Jnl44tmsfvp&JoeSf zyi@O^7ly3#dz@%)aHh2ZLXsfRN`VkK5$mJbR-J1WAMx;$=d>vq;#?yee^| z$W5Mx(RgLCi|W2LQEEhgBD-GdI6U9=>7GBwhYuWKwou3zJwHdmanV9yNrll#mXniT zRT)7^+3YLVS?M=O;uKri7`eHN`9T0uFjt!dV^C6|Ofpo&g-A(6jJ6evPMP(M2CM!u zeiE?1Sf=j>lx;5;C|^Bx3^YiE*`3MxtSOUg8hw(xIB_w6X!ci8j zFs2oTv_c<&pw|nD9ffV%SSm{d8!UJ_-vM-LNYVtM#LMPIh+H<3Lf}Y=%p-Kg=)yL_ zeWPi$+881oV^WDU>2Qh}lX0UlhBKW$(@U55;Ul+gT8{-JX-bl$6kLI$T>4Q;p+7q`A2`ZH#pCG{ zC#X+OlSV#4WO&qIxv`l75TVcUr@qZyX`A-%e}Z&+4(t6th|vR?U$Yi; zDcKGMOHy?l4php-+7Rf3Fir^i5q=t?F{GBJg%;EMbok?T@5 z&tuu|GVZzv$uMIxBBc}bC>E<|sWVF%f|X8_^{CH8X^hM5CXtRvMb>r6wrp(2VXfCD zOk!%rCURU7ZAknc^VM)Fh{61#p=24_{x&eiPi|x4VpPMBJLZpBcNwHYw*sk`78KJlnxfH3i$ku`~Dlz@L@7+cLMG5VVt!7h4VHN@Y@= zlB6lI*7#|JV;rQVkZC$p;sqd$z>fk7%4W>ONy#0=SBvB zB>PLzgv}0m{Ur``P7+k!f>qtm(fTBc+}Cmqu$3{4pK8C49*AqfX!xq$yz#km>|M=2_mVm&oC7V>F+8 z@fi+PCaIT-nJ%FuEge%yA=L?%R3t!>WM<_=YgXEAD#ZdZhDOlmOk;_56majpBTN*% z&8r!m|H+|mXRNcv-HoTXJw3~*nxthb=H_Oo+78-WyEYHISf$LK#*r=JjA6%?RVr60 zi_PQqN`u|){p9p4lZ+NT7(B9@16pe~4jg3Sqko$fzfY}L!st!*-U#~G%DOVEn?d4D zLe0y>Zb9mPiMGhdlP8G|%g82!0+gHDj8^{RfCAWevq0NYZeMk9Ujltr8* zXiI>l=!XII!q!OQR4R;7RQjvzUweili{FHv&&BC`cxwJ_%uOAoqO5B!YVTpLeYF=c zFK2Pw`_9A0#6}2F(Ne>p)n$JylsR%T-)ALX&%~v3?w?C=6KnJGzLkQ zW_r9j1xC<{eAYsr%e^jI%1qP{CjZNuR^~FjtyK2ekT1-h^bhFpq@-S`u;@3i9l57{ z$7q8{HDi_XP_{Q13bw^kzl|?kgl!`MEo|a6z;?hPx3HN6&$ID$8DYGDa37_k~JyQxHoi~kS5`4KM_!} zT-Jj&Q$psAKK|Ol2Z<7yI|)@b*4LObc5pzURKqJ)ukBTCU<7`LZgcsX zoJ(4;suN0ni^OlE$|W=wPHHnUeJpFAlVTgYs8Ve9kOc^ayPAV^YD zWnqtWOWh(G<)Us^8_x847*b>s^We-pZn1R59a;-P*>+Gy5u|xIZhnPzZ!@UjJt`TaDryOjlcK3wmOKvBMNrYf%u{WE6A(_)V z`>j#}P-rA3FJh3S>881C5K_*lI3@6uP1z}O(eI;1Y6uUMeXTV$M=@S0v3>gyLLimG zB=Im`eNdHTV7bvkV2r|zeWrtT4tHMS-uM!S-GsjMIAI^+;p%=CCns4K5JVBKrLm;P zdJ;2%z*Q21LFr6%yq36v%w&kdFe|yDEYu#h^UOP)9hVhm&P=X5!sT@498_0pgTL8e zz`|hc0_p5QNH0@*@$-x=e3@kIAYtVgZ?pFCL|>xD_mN76Y!AqtXStjl#|dM$joed9 z&%D~LFy0y{x67){wo^z0B2Gz&vcSXqdu?=sGJRG|jYpk(Xw2MAzqpSu z>~Q;dnJ^Z7=logxRD#gxG$oCK%#_UaDFU}AWAr;s`ayuD6uoYTV!4J_C}3GOey@#G z7HN`Ds?=z0EaQhEmSv&Sl={>>ItkGx3uU%!hhC=vLg9J^sd5>ncOc-#vs+p7x+eVHPb!KW>k}ul8zs8 zX`{t~@hY1;h9DIVQW#QXCT1CnLJ~05U*bUjJolSLj>!<$)?CKsS+Sqy^qr*jJD41w z#0vT>w;I%{B`m4XmS%o@jD=>Cvh?Uj5!F&@n6q&`3SjTa7*QDD6-uOGpEON~f)0V- zr&_Jj>vaf2pRxKZNgR-9L$O$**KJcQRly|mdfhDJD@h1~0LO9g{RV}&Mx|Q6DPo^q z2{KVg;z@;a9h}NIPI;Vk|J^i#9?j-O%=!t+{zb;Z%gnZ(Cy5etZ6E929P8dJJ#U^4 z9@U9@_Rt4|B=i=k%4kg|4zD@^XRvp;LSYHXAdOrN{U^JH!)J+Vchx63+1#LGKuCiy zGM|nHBA_E>7K^5VHinCo9+CT%d)In8|g z31UCw-s&7q{~&Q;A8~PtxHLoRRT0X=C=a8+*Md%(W+vHOAs%Q6n`Jr8u-Jjl8A~aN zR0=J`2-O(|g#-o(t*OY~&zCD4uGV;}(?Loza5v^5^a^9!ys)xNT?gz_A(dc_@zyf$ zT|bMb`&0^ou7QiX!U=PjOO+`aGy8D7IyJ9IDGj)5Vvd4kVjP(~2b()!M}CI4y4s zXaoge(a=6?L7&+|iBy<87a}WipxhEuQxzIkg;VVgmz0Ly3T}6m5*I1?mzj-EG9jO% zoFquC@v5`L-V~ubN$OOHWQoac8);Pul}#!fQelzGL0YWI8A9cg+@Q3^5m|kyEf|*4 z$y94;@^E;evpX`NltJp4VkofaQAmC2VTZA_&AjL^rCS_Yh^U%~RP^b`iWhx2CCV%? z&5}1ud2Bz^wQ&kwnS-{2qp~oXeoykP%NMwNb{|QS@chOK(#?DynMR#4VwQNNsg?>D zosgOoIWRk42V9lILP$AeiZ?U1G=|y!9h(IPijK>RjWwp-BB`aboStDQMT!wIM{5-} z{4Pe?cvDAV@+b@8y*$2f8kO`Yg2>(kQVHKJ<7T;@}ILP$)tnNl?_?0#;`kB?cZbJ-i>4gh(ADbplClhc6E3(-!0zra}B@A~?O!CO` z60Y>P5_Y;o8pg_1Z0WM0 z6=#gcikW0xRB4o5npTm%T_RLAu5EL?Hcr$JxO;Ar=|U-6>B(}0lO z>@Zgy$4^5-V`#N{^rDy`P6$m(oVhD8LV^(ZVN4jOT<*514Qokp{T+O96cF>~DTZ(@ zM|9w%%W|0|i4hcy+7gCgMCMg60%~57Bh?z`+HEekTdYMrTql#Avrs~TW!Yfam|}s@ zOwh%!6dJtRG%GqGNFvg>he<-LijRl`AjVDt937xcgk=RdX-pwdcu8h17eas-!>E)r z5lD(8!XdJ3v~WpXkErAjNsAYvgw@m{wOzDQXiMQ>A(e$t5=%fal|->mx8G-fX@W7U zNEju=Bw6yCHl(Da7!+B->LiZ2qf)0CCp@>hineSda z&~=cf_7J7M`;_C?6Eb&j{nhyw*f%l8Tk6x;Sp}&r#~EWdR2yTp-^Gt(TsJdw?p7Er z%Y(=sSkZQvu1(+yoe3prmeiA&2(1mVPKk9wtOcFeaG|k=aTNlMmHV5N%yK-OK@*x` zn1(>e%p9w*v4Eh{B#8~Sl#mBB3X=yWCTSM#Av3kzGm?TO>GfNTm5NkkmYC%zJ8MZG z6}DyJNC{H$?8Yh!jRwm0P|D7995Gt@dNi_EktP9UWpQ+37G*Lcf#lk=#;%Mp>SNej ze0Xh~x_j}pE1gs18L>A<#BIqdu-@-;dVK|xq}*1Yrfk_;Dwhku5|Z2N(>$_zIa7FF zE>BrQK}sy4bG=4_%ECmz%cHAuUjrIHNjTqa5+Jd)MJ%#>3KORssTDamIfgMBY2+^E z&&;9MOCqX5Q&e_VlPb@VP)MW@Xl;0EW0^yx3O|1EIJOelmW4aw%pG|8Qc}&OPP;>)Sje`@yc|ov*Tb?M9A{@@QWOUGVMMi3x%Q)Q z9iWup=+qS2Xg0b%9$UP~d*=^fE4ihRSt_97cuW_HT#VW%ab@p>F;E!PwAE(l+}ey5 z+RRBXKx{OEY?W3cdE(j#bUyLZoSAk;-e&PkMcZPoP+}}^AGiI9hH=6nzrQTb6FUqC2^CGvSne}7GaXm4#O;@1TfM@<~6896ms9x zEc?f+47@4VOSajuV_aUiz~a&pj#ng(dy0*^V^JQfLmaWu zYGrkUr9mi%O1a4T+8U1Q5rh%<+yL- zsME~*tTnt`U0ajlQsOkzg?c7NBq`6Xuh1i9QaGe0=8m~(DtXb3L~GhXm|Zi~oZo2Bjzf$Q z?Dss5*T&IC=YfOQZys#R`BvDLM5E~UdQ47Fl7um*ofbRNU9TYx z1Zl#m-{I-?MJxe{Nm%LjSx+^whQt_RG$b+an3`eV#3V;hXblU!24NIZa$OV#rJ!Ca zK<;R)I5RxIw1_emhiWy9$abOEP#Nc{u;oc;t(l(N&)CE)+N4;v4caijZyt@LR4k&D zM5i&XSEf+#h~kuT(W6)y=itGES@?&YHM1|4${aj+gnjb|==FLyu1lQ6ndJt_c&&m` z4r!WDC|4;sHV>4FL~%?KCpfNy<9I}&kFp)Syan>jfYIccQn7$U;-ogsuur|<4x6(0 zNy0NLmq;AR)rMCVtc)?ll~oZWk}%CILa;4_-5A1D6CrVo$-=;gL5#fpb0W+JeIMYq$Zp$)dQax0r6)`mERqOvg>EGaouo#b+-!Fszxy;{Oz zG;iAwr!jNID*GzqC^6E;;5rKpJC-QN^>DqdS1pyd=W7=zRccu&Ng;^BfaAw+r&QYN z1T@AB^@VD!w&UW)7^Y_mTi&~aHpqGHsSLHj0XI>y>&W<7Zk8EmY|gbBEcH5AQsPQQ zs5SjK!L{J!IKu!I5?9$=X}`!Oa`rkgY2N2zD=f?AV!KDHAF{7nq2$;2TJD zV@GB>-f9{#WF<7aI>Jw4W~!CE0VWKC*u~cVUP3C?f*$jgN)}QgG|IqSrN(Nn&03?y z^w>CqR;$`TyXQ0E7ExReqwL<;b??5acElrj-IncOJG+^YhXfl(jCDowA@SYI4Y!oNyt_KP!Fw&-(rZmrBVT9tNbprN0*{^Tvkd+BMM0p zo#ly$Eb2oU!ECw4N~gu;R)e|mF^n;6G@BHpN5yqX(VICPuLG`G4(rV#;=CacSwj}B z$jqvPCXxyc)u*Wz%e>H9qZxL=64=AaAtUB1GEvu6PR1Bl2({KCt1oLr=F`|q=8}jk zjag-)RXa&(gh6Hj>iCG<$C0E7{Z52Ct0=o(zH=KQk=2$h73`cuxrGK{a?@~rc_|FO zPU*xE<9Tlj$Q`2^rYkj~&IXNkR@g3ugy#CHJT>EQk&w?C<@kQ|Gv?R>btSYz+8JZG5%5rq-A9dYPOxj zu{<_HpVe*;9Vc0BszDTPoMwvo7SVU46zeF2Kug8NPJ^++%$C`nX6_hf%i}z^x`=Dp z92=X%3=4d|zSzMSu2*`~<$S+Uj3Es}+msS8S1B=8DzMOQaR&j*OdEW1X*OR6x=mF#erINI8iMWi++zYoh6JJ zSxj?Dd#92t5z1yg4$xX7a|fUt-VeR&YQ<$yU^CCu;>@va zV_6nbzKW)VZ!(Owb*b7mm8p4Bof4%fej3q_!n{g+!v3*3wvZTYh%CwJZktf$%`mkF zogl&pl!Nt}#yykpwGmwCbU0kCqqHWKnW}xUvq7=oZT*EH^Wf`@V|1Q8H3+cm#|dd_ zvM7M;c9B4gq1EpJxoD>i`VH!1x+i1w+6`>CL>l#3U%5obEo@p#gdvF&q{uw0Gjj)6 zU%gDJI*Ca_+O3UTzRUvFk|bt)av!x_Ot!bMI|jBNOGz9dDccUFP#%ggSw$N|V#D!T zoiu@$`fVs=g(!ryM$EsjA*L-46_HYLqP5OFGjr4}g}~5@6PDvH6{kpIG-yzk#4-Zc zwh?iHCczfjPG(yI7lkQEmi-Q8%O%ZgVF?5MAOK_VWL7IHm9M|jJ;0ufp)8xg@1mrj zTB{TIJrEMDQ>4lQ474%0g%U=m#BtWkE=?1ZWfLb6Qd+oP5dt5_ee)>v*8-yvqgfrQ ztxh^Ehk_VF!m-J5^lHpYk&m)n5Qdkr=w2mq=|D<0;)tbghw<@xuJ|XEgdz1U^|LrD>WML6fgK z@Xi3Pl+;`&3y%~EZ8E1MLa@^9^TOIXFLj#CR?FNuF~?m}qK!tVtU8G>f=&|f=*0_^ zJddI*;MpEetS`~ihC|gFN~eq!U8Y(dt;nZRD7+!j4!bm`)M%Z)nseQhF#6h+j(=m3 z?Hp63B8&ZIRyS7Jm?UJz@i5xZhm6`*YkS$NKfDjMM)`+ zj7{*=>Ix;>&EmGMBFz3;VVCBVX>Mk_g_{Y3)l?XmbPANG=h*Q3jCn57WKpSOUWq&F zf+seXK&d@F=7OwjC$VPC2=1AiW5V{b`c!~%@)Xoul?4>9rMfI@26Unp~MyiVD* zNJ;ZUM82b#yk4%s^(+b|^T?+H>P~6%7_NplvNYMty*5uTFYtjQw_z}Nmd&Bs80R`o zCW@8e{k4E*f>kQ zE`d()?CWFM%$$r{=irVjHU9WN(E9UFUr`3VCX`6Y^soKDsXp{!%qytv^m;-F!KKq@ zdGgP{x|Mvb^YSyh&{izGZ617^5qO17kV~_KN zFMRGQ^R2JreQCpL(8uKT8?sgnW46bJZD*CxuXFn74&9tx$EuAJoI63hzOu<2H(~6Q0RF~L z{WRmX8lU*$7kTWNXYj*d%V1v)d@dGkp8WH_VrHz4=Q>l9D)0 zNsYmE9MUvJDMb`TSqOca688Iu>XjH{3xy6dAN}tr9y~zz#1p7;6=&`U?Z5gYaa>~G z&;Js^;v(_#InpRW_nTPN3B3J>={);w?D{NmV~xsN--`|cRzLIah*p=bubB2az;j*R zegE5;o|xo+{kOlxlP6CgM|RCd6!P@S5}*ItSCLUn!S(0`ex{U5dBZf%DLOVfiZUk6 z|D=>V^1H7VnVRw18D3&gQW9v5Cdr(Ou8Sol8?k2jt`DJ=v*UM;-(=?GpHX!^O17P) z=bEf@ZIC9c^twzN`G&HC82Vt|L8m$;TbLdbe zSlKpDZM4`hf(H-IfmAQU7-_`vAN?P+AHI!veHm35M+ZGfBa)ua#oziLiPo2~@(xMH zq(n;>kfjNfVkfOh4_D(YHfy#Nwb*VB-(I9|ltr~M*uWTB zi-MhynDHYd#xQVEkDgs^(@#d}hs!KZ)|ect?!p*GgVuw%W|EC1I%}764jrjB zBp_b7074QjoE;fx0qZM!JOsIQpl)y<27p^Cpllm6veI8#Ud|@aE+Ub#ESy3CWm$N| zB7Ubs$MEXjy1u zXoleyCaTyD-8dq>!rZvxtQmx{??va9w^?zCL~EqToBxcV#z# zWnoRt-q6gUwdUYmcj5kGi8PM58b5~RI7}Zpi0wGM?`Qridd=ol{O$(8NNm&~qws1W zF!YV!xztd03*1qwp@ri8`--giJ~h{6qu1k1r^{XSaXhJ*@LY_5?<`)XnWW4WN*u0M z=tcp5v9LflNw4du8DPTmc>ByO7us!3H8!?DX!EQY*V*Ul-{76HcJX@sWM%7WqHZOadd-5E8W7)00G3>un|SP zPEycyyN_|l##It)d1aMW>&=sYaSPWEuV)F(>xIh$tJLJ=c2Y;0#^+qSu}H?}smZTp+||JQ?lrl-4aPt~ncr%v@m zC@V@Kz~aJ!fPf&#NQ)m6i_90z3O7n+zDm@zI$P|$!3XDBbf;xr?Fn^u6&^8nOnIH7UD znx>}tjz0rk5y+aSVA4tg#Fu}_(gNKi7|1AW|5dIrp$K#j0!ZZ?Su#2zh`AJ@zq-c> z;o*XKL+2*G1jk*{;OVxYsR>o7{;J7kUllk2y!A2=qTtMs`&w^1ThI1kW|K% z1tx6cLy`K>Fs3;)5KgXODSm3|pHLR0+AE)cgO?Akj4OXL)CfWU+q(7(%&uI3wk0vk z(YICXcPBW6 z9-Wqy#Tk)D8d0f+PZ9ZT*GsPpJ*;R045EZSzQmIV{MAUfbEMaD;0nR?PcSUo*sch{ z0SE}Kjqd`Q0Ehgc>-IjjEpo7|ZI4YlTlbz$(~$QyoX^C#LKvwZJ8AOhVXb+Aw@d`e z^F8E6LM}D4eVgf$Z-p1qD4cw5J5u$nTJ@jy8RafYg}J9pS^1HHpu|5=Z+=`6W7~of z8bP`QZe6EB6+n^IKtY2BN>kh_e|!G+48s}h8j3b5WoG(vI{(@Q^Xo(N{3`JNfZN0z z42la^XF`6mU}wkE1*-|=6w_rW9xqIpqxIir-{~H6Dypa8zA~7KAChmSM`xaswJ~Mr+m(&KUhNi`EgedVK9fvFNarmN8f?A>q!rA!&I?C7EOU8X+ zefdnJN*aF_D}5)mmGPCcPb3FNx}+g|p1+8~N5(11RT8~8(X@$=cR zR}W^V+h$^PvmHFZ9U2k#ITCRj#$_{p7CSL7&YnAtvr*40;vO5yTRQT7RCZ!CD5v{* zdH&11sk2N}{_}e_eAKX<9uA~^TIdflIj7Bi!lA6EHL*n2P{5?f~s&EN~KBsX($FY-vy&V!VUj&iUxc zziAy1Hoy_`AvU0p`q7v{B>Uu;AcKVpAi+hr!$Ic6s*$)>(|=#dJ+5pCk!mxLAqgu&8JqDr#4Imm&GZGY7}qJ z?@}RG=cgsm2%r^PEX+*M_6f}tWhh*l)n*sSgklKvn1{BDdlDuR9Vud)JD$}z@p=Gz zV0*xOKz*YM4cP4qH&$mE#-@r!qJ&KfqUlpNxiadAf8>wS={ISR*Cwe(MZKKX_P;Q; zrECG$3$q(RG%0JC;Kq-|pbAwR(b)@cbI^yqqQ9c8Mc@j~8v5*0+iAaT^Z@IE6U5F7 zXX*p=x9)}AIKLpU;NFxa={k`(xjOMV`QMoygd8*< z7#!4%_Npi=Ulb@8)R*2AN#|1+w<+F+?;#A~QV^6-moS#lnSmeDj87zACNoj@qCkU- z1Y!1vAS-f9lvBE(Qo;z8pHz@nL|5=v#HwPbEUF=>_!d$YVdgKD3JMd*83_AEb>w*^ zghoroOQwZNqbaG0FNm{AHp$B=(TUl};E89+c!xZ(T=EmdD#k13O(!vC)MnQv{mLYi zn31ZJyB5h42Z(G-2u%c-A)7Fp-&l+qwGGdX)DKFJP|uw7VNYofdc-+K!VHm*{+vV~ zO&)SdvP!nf$w<=4T8-j~X;1YG_e=@Nk%$_KqR1(UH48S&NeR=);|SmgYYub`LYSf) zH=n{Ba?7oWvP;MbG>F;!Es*m``OXbBNiuFc;Fw;NU6f{;krcHM&z5{oZ$WiTiiMVj znI@z~s71H@gG-ipDn^2O_E>}2LG#83rt_#0QvJ0gP%k$lX>k0a@VLPd< z?AHu95ll7=% zOu|gyXVlNILue;RC#gf+!=BNoG4HXwH2+%RI-^<#(E>4JITe|NV(qH7{K2||QuS)~ z(#d?=lI)5PX^5i2A}93{2{Q!^6%PH!(lZMVm}Zb>I_rC&XT2_KR`_aqq;ksrRD5NB zOARRO2Ms4v)={c7$=}yt=B1WtmMmqrgtzoQX5^t7(hlU;e;UW^!jDq4 za*1;9c?@Pr$BY(^5~(1nv=&+w{Vwu06*rwXIWj>oVIq(udg9)241OMMAhX~5v(Gpz zc6)V8AoUtcNtC0&EMLwm=|{h_vLJpsxDc_OgrAg|#FK=USQdvzSSM2;OHvY@qs*t0 z8L9XvcPW=7$CvfQw#n8_CB|DsY|6Gk)^uDvIrcYcy{t>=(Tv7CXJ*(O$|CN_@<=_W zRDi(Si+7p7RWOc1s5 zY06%*F1qyn+^XEP9D5yRZETO;>(7g@StPtD8X_wpOn=lbm-nWn<1LD^l2xW+rgZ>Y zZ-ZawhryTkNaNz&f$Z$~u=N|#5|M_@xXtEy?71_ZN>beHg0D z;ARyFY(;%57YKlf%rlA&gj!rTuh-0p+ZvL?@rB};WJ8(r<* zr@}20i$QO4&641f8Z*?NHV2aEMiMwBpW~;rkCpaMsQ*$pHrN;b{IcwwA3CQw^Tz&( z$BCe%k!yY??v}le$lxxPf^!YRyvno-Udz$MxFOT7L%< zm!ZNR7@dumQ}dDkE@X+@tqU)LDMZT|jVH-E zX`xO@u|mPuL+x$J9GAm@%T%a|GwWIL!(csoYGd-_7NQ~~<5`0!2n<=Q;Y_W zhEP8#%c7}QR96UC?pev5>Yid@TcsywM9^1Mx2{t1P;(!)Jvma{=pWdv-zVDZ1c=7# zNsFv#4=S)r(rbN$iq{=;c>26V?c$@Xz|Kx&Vh5QVw&O1dqkJFCph?C$~@^dudzbbjA z+k|O}7#b^GrYg?1{X6&UN5qfiD+K8a`-$Iy{uc7U zai=%=TyEBjF`#j_s3-K`&#&XG^WG*{FVoJ^bMDV_1Hu}TJ77pnPYcHodNnd=Qc@4s zCg%ZQrD^22BaBoXrw&3$q36JOgq?z0bL+5v(+}mAB%;JKcf~}}lw4A1@q8kQ)tuI? zb-E(W{jt?0pyNaHk?=!Y#FvDyfaq^GX-T26iR4}vYW-l)LHa+kQ}YbE#tpQ({%=wPa(v|-)mpqP^gG! z9lM*55kps?gx&%)0wdjw-b8mQPpc1h_i{JOuppq9fg?dKzvuc5NJhk(#r*LrNqERC z++5qtUY^7Mj&>&`sld!-&pn%Lm}HoYAT8s|L^?-e#R7QNGUB}_sZ^L`*fS2fC19mr z{Y-ctt#l2%%pqCSzR0f*UMkLYPFF#BLd#ASg(f%CI@7VT>J0LoDIe*-^u6ZfVa`2Q zRa4+-u`tGq$3y5mm>M+a4JqqLt4bwFWj-s{o6(w=&vFg6yJ&nS4xdi>ej~ugOe+jc znKGn%lh%aVU0q6D=UrP~`g|I_li0Ujk>!nK2yo>_KmB@)c(}&nX5)U9cY8S)En`_f zR@m=ix~D2ORO^n&97~UTwY+sToAMg@?)4*Er_q)GaZ2D{*dVNL=w zk^t#bgy^HP2DR0O%MaN1pFx6_;lGuh9s_R+gpQYDRbbl*I#{10Mi`^63({l`{yCC` zOhEp_isaQ8+XZzDsx#jTJIK?RU>-)OTJ3Z0S6Vu z-9<|w(11%kJ(vZ_6k})mGyUh&1=8jDB<1uRM;(V3#}2zJgEYNi5`sR6KBgM8`rfwU zg7snnza;xg-$Y-ijp**+-s>vic;K%4pqC<^0-O3LEj^_uvJNT%N++G4A*tcKhO9)U zh?mS!#RWz?yC(nwO+to3vc&E%jy9=M%v!*^^B<9=i_Mc&jLpn>^$DmiedEk-%+2sm z%H&db^RA;iOw81NP0u9;&L%f-Z%-(T5$-a$X(at4eVQjZA_s1d!J43zg$cY3e~?mCw5eH zn9O=_cE%m1({G~swT=OKo_r6}cE*=vo5xjve)m(1l*P;DhsWWV-KkE!Lm{!&6t`z2 z%V#bq-abU|K>AtmqdpAqK#zDZT4A&ks3s#glb~W^v{5|Spz-|oSv_n7xPEhH7(poa zzj-S7)N21w)CsI1r$SpqEb=>Fq7GH`Vm zS4rDJ_wE&7sUp{{{%86FVp|>y7GZ zONk37E5b9yCiKav%FM|ujPIB&{X9M#KJZ4rqTA9sQ}L^~(}=OI`_s`JnrGgIDYLFM zBD1WlBmvkGUY(si$#?7;lUVrGL;>d}=UWAGAV1M0V47y1ckIyLFm)Og^|uFnxeTfe zF|_ls^WM|L`^bCq_Ub<4cJsypHXiN|TqL|8);!@`?jXK7G9iv5j}w0;rr-mE3bLc&B|rPvvQyM*_!(o^E!FJZQtPR^Da}7^Gw;uF~HX! zp_?SnJpC|_O_y3*{Vn^e#)-qB#-7Zx$@%e#o2}v^9M>vyrfv1fk>k`V=4#S zHdcN@q97tlH4-|Ku(8iEDe4F6E7eNnEh=r4EfosYd)3y3w)yH=^97k%ff6KhVrF%g zGv*$XNaG`uD^s4Kv+2?S#_|5XhJK#@#Zli(s_+3-tE(ocnpCwv?I=g))V7B{*~~a3W*wt6$!Kep*Y^5Hhj7~ z9D8OUZ;uYuBsPZf7v;dnEe$)>f$G3~DBA@amSTyy+)>x4!ju->i>kKol`xCv*r93( z-19j5#5&Wd#*?~^2Ga710YN!OxlIR&&;6v`M^4+@)bJnk{!XxG)OGZAEZ#^WZ9#GO zZD0H+@oM+d>yLm1ev%g5oM4vVtHXP@{kF$>j2q7_lW0x1cI#AORU0TVIsWAXn@ldOYjvcxLPCdWX`D zx3B?EeSq)Ii(C$N5cJ+H5rIN7nD4Le5r5Fc(cYq;ls|fa;y4>Jv&Du=X?8@rgf^@`8sEd$}Cadiv&~@ zrQ~-$bvOk5d1ZO$Rqa(>n~=K(x|Y^*V_|;2Q5lUyaau4k>W@=_B-ZZb_4RxH>O0Sx?vtmdxASB=w>aYXM${HA1Q=!SIB;X*bvZcR~ z_sZYZ46?4iZgX?4K3h#XzfyZYf3Bx|z6YP9{%}-f;N>}Jm8+_)oi>>CTTv(CdMzq@ z6Ig^gPID(cRC>N}$q_W@yxY$DMO^y+t$oS6)tWc?j9)cXcf9^hJ0cDpx-2N;aP1bX z%v}w4@ zM++?xP)Mo(Mi0ko6Epkxz(GSYVU!wTkTjXggXV6flgVN@p;-{{V+&pyoLcscC}`f9 zX+Xy?Hbm5^I8EH1i<+|4~UjR8E> ztVD~7W^U^ujv+r_8N9&gK83g>q`M39y3njVl34KH@2gvu`X|S1*QWXu^*w_&_(dJ@ z#&2TNnw(^Mo!F+zpcOI$X`8cC17B8|Up<)5Tj_nIv3~;;jLHs0v*m!t!_^hxVdc6d&o<>%GL-x&Mb_Y))$m8u!{m(5e85HnJ^pkX{^ZRNaD*$IgmcbXyf{Ot{CoSyKTX4x*uPdVPJ|ewAD`z% z!$`O|=}E`5_trh3`E+)M_fZIzq0#Yl4m1fhE$v>%d2La3wXLo>nyACejqy^g!Nkc4 z_2c8?zvbm7yLHaJTaQ>7^O@W!3@!b@+H-q1uI?H~(P-mL%2KPIRXbm?0&3Vy&Ia#B zwx_DPo^iGr{(&CfcL#3#hldA;-4HBQ03eUe)Y9Jmc(y>S-A>WQhK|i*S{z!09rv&= z5bWXcktDcp|JDc_GP01kWb$)jse&3dLOh7WX6fKeT>}^v&uEBYj_vy7s4$XJQZnSI zUHb&reb>)QD<+_5<5OW~I@qDN=I*aquq1=QV+X<5Vj7Eo@8Adb9SMDIM3$;`ekY?E zEH}_cxt=dIct8L8)wT)WrN`m2q@rX|k9p?dtlVK2k=9$eMaGcfZzyrRqsRHF+CQax>>$`c(6D z7}wV6Nq|xy0cYxdK($$}HG91~%=Z6!y;yC6%A1k$^yEPjctA$tzX5t$5FK*wHt6Ek`hFvajZms`OXklw=YN~abLOuAW_lBa{KkggvjRd-KZj{4#}!Z`R(0eh=Od&wU9NQ#hLvv#npMb0-&tTxb(BsO}=C8kdfob3}`6 z1sI8oihFf5z=IW(@9$?7f!Ta?NCVO`{QjuQL`#E{;SS5+TH{ann_WKR*|&*uh_WU^JJb`#ZA%F{-LCXhm4aoL+uMneOS%sjDfAd0*y& zLeRulfV=X{K|?cl1D+IIlD)5gdn2&BFgKEIMl_Q$wvpB3(>J|=c{i72T&q@e4!B1U zN>qU*Zse6PG#Z()Dt{-8gurd!*z`$vcei%x&{ns%PKOH(VO*F8zanc!aZ?kT!otbL zMRq-4*)=CL6cQ1iTiC*a3K;M%?(X|;ofSYckHiv;)OfRQy-vHUYG_Ev$-%jG=GfG> zhXRf7cD)sooS2%5Ntyr+?2YUDJ}$oa2;$=6zId|G6AI>rrk$qm z;01t>YOpajq^YSX5Sac0*|WteD@#jYARbL+S=rf5MaWa7>1k<&O_>)}RYmpm2ueyy zmeG1qL8c){;KQVY`7lr+^XQEnERE|icN+}&H0o~dh zA3bRGwxWIfL7Vtj z=V(Y%R|04@)2q_6zjV?FkEjM)ZAB79)!Lv5*^`4gz232D=QV4<|Lz~0odL;7$s3@WN0YG-Pj6A;_qP% ztZ%>3LXs038(Ba6gmQ9nc)G=a6SJ~%&xIET{0Gnhz|9@CXi-Dh`1r+*jsNYauJK@J?1Ik8WzjWlI=bU`HZL z-lARgp^(l(vaq6w9FTCB(d56!Ov1kua|UNIK}jZ!FjRlYJX`iH;pTVKCF(+&spct1 z=}W87>|uZiqTa6+I2#RWX`XsVjv(5=50kVwtFm-ue`w?_HPtfla6VDz)Bm)x53GUIQNj?n){CifKxE47x`-54%yq^2QHHL2CM8vT&Q(1N!G1x$ z82z*<&#ItPfT~$nng+NSKb|eRxVp0N^H2VlT7W1Vui9uf@gHtP7AouMMHNy5Y0dEP zFfik^ZT>VQD)5G*rn5my)wJOr1Q~+TEli(NYm>5z8RQ85}iI^fi)g-rHwE7#EVb zULI^y&Bv)qq630DmK1mU+gLS$nzIgx3|EqxS9F4xuw({BwRA=(veJYyvD^)BKGBj9 zOM%M=l}5ywr$W0Ocj|JQn>~lv6r@}cOFF{DUG=_JZa$V&RrMb?6`2*WT^5CiE4Rq_ z!*|le81nOZkg{^lDKGkF=#)iXOAow85r$`Mhui!jY(J2Mi2%_$i_>oJ>;2jS$Zm>N zY1Y=(>gl7@X@}_Qy8Z%j#razJEt|z+8h@z{Ff%)gTvAfP&dJHj%bQ6kHSzcQdH>Pt z^y=ye$Pma=WF2pIL^?V;>Q`<5{rguBWFPx2Dk|uy^g4fI3HU7S><<4MXZLT&#Y)3( zEPzi!Vj}9-<@OhYySBeVe13b>!XOz1XPpomWbDItWoki~&wv0-CSvR|7vkzOdKOrx zfC5y<2wwv~$vk`F@)kQnl1-W+|5xnPwSSEH@hg)8X1m$rf)2FGY`0TUQv>qD-^$eD z8X6d8W@hk6NTxcNrBgDRo_ha;i)1xv2S9t<#kkMA8H7q!&X)b8Jgnn&=#cur5aHy@V; zsMX@G)wkW~-?GPJFU6~E;4-fre`*CfaLY4ei!ZPPuimYbV1PMXvWOcW5s^r663C2Y zU4fk(pJTp=k$wL6i>6>vlFZCZ?QSm)Utiy9gHB9?<@T4oD96rCd~Sz;%k@?^W@cd^ z4Z1&?G98M<0P=Srvlb&pHUdVKN4H_F?~@LYh$hN08UrIH4d9niSV+p)et^oZUVLnmbICylzFOVrr&y(?x? zoteegh5Z7%3M+5G#eLGmq`!M(5Yszf71&s+nL<<9w;tYh1+&PT*3AfYen639B-jJ6 zm;^wNS?>GXo#-F;oNla8Foai@Pt4n`<_H?trE14Wjcd_cZ&l9{PuP7{!w z-;j6pRuTG#{_WjMhCHri4?}c^)@lFVbB+UJ!s}i}5*k8cOp)s6ez&OW3e&riv|M*1@g&ihMy|0q=Z zIhdK!NK%izIib6%Z9!qP0o$JU&1)5aj;Qy!NbDb16L(MTj-N1!-nxta#b!j8o89Q1 zAM^%|&<1>ueix$9dkx6j-&YJ5tJ|4#ipMs?7#oC0aF|TTp?LN`H3w+w^}KQ}2~JLp zzWWEtJAMzzr7B;zfUsIwqBg_9LUgnuC=wDUwwCdvbr{ zZDLz>u|6R0<6)!?pHukmA&+S1>iui-0-~zzab&x!SetJ=+mzR$sHiGe&^uln6*`)Q zojthL1`R(#wF3R~(-&XRB|Nu>Aq1UBdX7?)-K5*)MoOZ{U05 z4b3N)bW-Lr3EiYwEE&6dzFY`>p-na6u|%U+nvc}Nz%NYN zl|`$=(wQD7ahyzWS^l%*WbEF<#jNATn!3uLJXd5hJi?h^b@uBSjds@xWm(V*b@ZlK zV8$lEqrgIXp`TIB&b+5Oq9ti-QepJS7n=EN#wIAC>rAmG+KQ(DD0h+v{}h zYK+_9zLqh4kafD*9yOFL?bMYYvgLh|D+xLYDG78UN-RQ0KimPnUlD5C&Scm0-0nBz zvQ#)?`nNQD9%JepKM{xyyVz#(Kc(TGH@%VcTCPcPV|HEIb^f^U5Pi&srL#4G77wY# z2@C>qbtfi|B(fXoBfPJ>p)4FR0KKnO9-Gq@T8K0>PpS1TuTHi&!?WxN6gbAm(*lEP zFpzIhY;+|*&r2USzDI-J3v(m}5iQr?#%&t{6B+Y80 zmB91%HwZ(RUWDX6cMhXD=hW^Rl25qvw0k;q;O8?upv!%fk zKqnQ8Pl^r?B0H>8nd1Ad`_lUT!kgB0Z%f**V(4i`#v*n&{_ICA@D7JfaIt?FgEt!~ z`*IVb(!r~1b$&tF%^>S!v`vV~2naEwe4WZ^y$=)m#3`_T`J_mfOstJXY_VUL{fn;e z_@(-EwJAo7FQJ0|gY5UkT62^o>Da6=6H~2TSW#Q@x%~@wWo7+i%A?PHR_p8{U%HoYGf!zkVR2XP_2-VJpu-f$$GTR}v^OIU5?M-d zhcTnj+wG;k%N1>|&x3Kx#Y)(S-Z<9xjQ`E~_DAUVd);^N_PO~??9|8Mm_whxZftk`30TVbwYM3K#^b zvR#K!3kz5X+nxGy*l3aBjBe^^xDjRCd^!h$#ecaV{zP|Z?;5BQQ z!9Te=&2&Gb#8S?8!f8l=2Adym_jtkeejGBr&Ngcm+2D$OZeG~%yu69t;6vF*tTc-* zYB##@)CviXpEw8^Yn4WkIBPdL5Jre6hRCI|br!^G zxnG)&wAhL7FPF{4s+us}-7$T?e>)yZ92@IERwO${do;mr5=gxqGU<+b*1-f;R=kW? zy>=@3MxMb6)x5jaU+MrbrWX4GV`1nK)jpIXbC zmL>T4+?K?`& zZo(ovP8$IZ2K@D?vBRLui7@I4MLj*aq-6v&6pXED!=aGsW+tJe1=J5Ne;S;x{eqR- zP9mRgwyKz(i|T#(h8wHo-xwyU(l4; zFclJIDHLt2_gleDfs)uo`;>ZW+UyeBDgS(ARa-EyLQNlFV8G|~K>mT7U>O8) zf6QFe13AH~iFG2jH)!fu zIQIg>7Mg(~e(;=UmEIP~e-b&=q$Dt%+x?D1KtPrtZ=$mV9!58Sk7Y6%O_g7$lsy&_ zFxPs%566+5$ei0tsdeD?e)S@cBd+Re3f2KqEZ-g6N`Mxem&^ z)pW{jsu8@EPO`fC0>1@j7~lI!yB(Vtft|YgqT_HR+YMHy)oO2;LtQ8YyXh*%AHJ*8s^-!a{OVopEY;v;Z(#|LZMA8ZepDyLg-K~)hC0iEe&0*aKA14Px z5JC*X?e+IFz;pMo=3=8GVxnN9XFc@E8>Y9wLsY?tG^&B|_ z%5=8HJuR684Bn^B6)Oh6Qkek5;?1iMz`mXY4{usXWjQy2L~`m&y?j#Q9c|Ce5YwJ3 zpUjZye?^!wdF06X$ghPvpHrn@rLssqu&haq69)38Vgy}X7z6T&(v-JvpXlxQ(GoxC zwSnc<*T8lWNZ=gF)784tICDjX&14Eq{Ka~b;6o}p778MKlj(b{OSOI;Qr_~^PW~wP zPiAaF0tpRvd9wapvM`qF(}hR#8Qb^gi{hd(qPV)?@B5Ux`&#E|VnRaGDKsPkHjTi_ zN-2dSRasiPN}%^(9uXQ$*EP4ihdLcr*i|E_*ITa#nH78ti564Lq%%CkEU&aZCYVFP zG3gB>m(>PWR;Z=>H`<*YI|U|l1(MQQuSp2e{!OM!-EXXFr+Q{z1`*@pnr*__@Vr;2 zu>aF6t%DVDa0$R#sxf=iv2d6^Yts21cXP8_9sT||(VP}?$9Q-DwcGRlElrHS-x24R z`FelUb@W-CEWcw!Ly~1F*LYI>cXNY%Ws;@)V|v?wF?J^*1C z5ueO3WQWJWZCTlBD75M=GoGPtn3xdPbGQ|@OG~q3-}TQ;XQg^OB{?s;6v46MVMUan ztLcHRwl50JYHdzqTl$H@#+HP|s_FduIVzprBN)Fkcjw`Gh>NW!*qNI3aB+v>jN^G_ zy)kY7_bmAs`yW8)39-U%XJ&p~KF76~S5_OF&Hc?C*~LDU8&X(4X=N=cEi+!9zR(pO zsmhdUR!~WbwM$9`i5YZvhHKj~yy8H#{W+8My3y;Gp|t%XLR)1ss~!@#<<|2!Rd?s# z`^He~aqW7s)|pq9>!0xc<-mpXefxY`LJ)Fjkvjvm^=*iruob0Le#|{8iN!w-FG|gQ ziAcXdii)_fx;V1O!}fZz?VC8g<>z+EHyYRb4LIqLBu(fucfZT6sypmzn(m8)3Se(~ z_4Qj4_{7S6xzBTYl5xgl+!tH!CBl#~+mxRcI;JOlxmWvhu{q}cbSc`pnlYz6qs<&_ z75(gQWrm>`mSaTTr{wnlfQR_CC#KbtG@MC`==yN8|NW(ut;i?3c>5{~9n6c3M?iud zseI_HqG1qXMD_08J-*!Qm;T*;dECB8%Qs#5>v(|Z9h{-&@?xbsPw3+fYopEzTM|~; z(y%L0$>#&|A~R@k{1MQ@priR9km05X^^eK_bpjyNT^%olRy-v{YjdvSI4leFV{F-I z!aDET1tLEo*JDf*xA!AYcIO-Y1!oRWPT@Bcnn_tfI{BzG|&d}Y<*pxaN6xo z6wb$!(^Gw-(AkPm6o)DFhF#%jXSiq9RX|-}cVn@N=FxM`j&ppRR{PIS94?;=G@pYv z8^=}G#0Y97p<8SNUow4<*Z0>GsBJiC>oZ)BW8hunuQUF+r8utXr4f~<^tz3~jftrI zLx!10ocCWyTYX`*ouP?|s;P{6(~*Z04xRYPsakW&0685`2l$1j&w--g^2$uMYhW^yl5t~Kn4nM}+fpK;c14#k z!X6IBmR>z>N&smxHg_?YApo|%q6?`{blzsDF$|WGP4=G4D?=-3ixXw!C&p6}WJ}_O`Pu*W`t3S*HJ&41zu#EAylH*Guw@J; z=AW;r+!mlqC}cIK>+rEsG|g9{y#b&DOH0DFC!!!ejm--%=Bqyr9W{&g~}R)i_i&Xr%|O34+}vau1t$S0h5qmF96 zbZF6fM{B+=!ab)!4`y{15&E(+q%2#@t8Yyz829S}n{By>*@DCIiD2IDb9~InEKs0Au6nW2oir!>l3w{EBHv1pt$7inu422i5g$`@c6)s&Fm>RxW@nGWBWlxr zye(UDnA!7X3vhq4z*L%Mh~9J4`<;W-dmT9$4XPycM&Mm|SMU$!5s_rtZ;fBP`K%u=q18kVoc_5dirfg&owY`^c;RNr_}ruX%# zaN9+b%v0@eI9cP$JY8?c85_n5$IA|KJLE$QFso=VPZe3zf7GlT*p{~QvP#pn4u4{o z&dVOp$C>#laoH$7SmG(E`23@%0v{(|UOQcE{Tw;!7`R$`Rv=A*F)^U9j``O2fn?rGXKxPHT5(r^B7i z*tNA6jnmb4=u%qJ5*fs5HQ_`5&cZU)#DmgcRa)YSGcY1Q;RI}Jhb^42dV38uw-;YX zq*riDArg>dN9;ax;}GB!Hg_kHw&E4baHGz6D;Q-^3UqHiJR>Et!UM6x+Q#}8y_1bo zl{IOXI&eWFc%gP-$tzfxI%pXn3jEh}EI*hK3Aky|z=O*(a>P)>I)S>zva+EjD@i~n z2;^JG>D8%NIW9s>47W>)FmZU{X>w|Ee&wlv2R&{~0QvL*X_bUlnk+SyIQj3X1HsH`fdCy->^hwbFby3F4)I70yr8r}^B zcEpJQJ1VsO*u8hJfhyP7{#TUaa*+x1dqc;$2U@+a1eZAiXTJ?vn<|nwsup^yNCP(VeWj?ujD1 zG=P>UvD*6a^$O@2{p)!;$QYOa>i1sN>0v&_D>?Fm82y97Oy6S+!)MQwYv!kUc(l;wyB^`og4n|oQlflm{py9f z=Cae}BiBvOvteLusaAM@&o4j6k<04s7g*Ckx1ca`~9JqI%L=o5$ZO9A$ou(W?uU#rTL;(p3@QcrTMW{)r3iAra3Ah-jRb1R3tL~ zFDsHv=Ja)bBJW&9VU!@O+%Guy&$CvS$0s$7<-S4*IF*p0mZ_|lRlC*&Hs;7eXi3S? zlhaf4OXs-Ti?zr9RdQ8fZ8g!h#i0~;cY?bVC?4FcI25P26qn)z5AGCcC{Ub2k>c)< z;_gr!irYQ^^Zo9_&D-S5Npfc9%-(zLwbq|Mv)V^qJR-cKTfxuxiSO%CbZ7R(+6rFo z3aINnCW0tVEQq)aR16>)*Rx@d_ZbqlJrzq+{PB4?LavAE&RZG|s6?U3coH0~P3Hrs z)UeXhjAwvv6F${t`ux!P(g&aDkep5$b#jLN+1nT_d|JNVqP{q4$U zeX_m!a5_LhCaB6tLb7!(Pqm)z^2GdG#_~3>ueTVt@pm26?CFGRlLeoTaPLIaWy|~K z2~r59;jdbUlPR8nk#ZCkJ$gj#uQLhztu(B|W| zC=a`$X?od~7rS~?29+z(5$*0tJW*3UkEFz*bn}nrj)m^}D)0^M#vk6Dcz4MAdj~Vg zZwAzO z?79vx1VW!suZ#E9cE{|qYy7h1VgSwzkW$(f1k*}1AKN}YCWzi`%Zq=hV#U0=;SuH! z9Xt|>z_Dvd;R?KSSO)Udi%OSA)SYJwcKG^a7h)#fq7imVa;Skv_T3`K+Qy#u@{mx+ zHK9`M3PX{mp^+$eJcIiCa}t?ishB70$7-(N_|}t_9G8{H)70CTi*dxz52k)0PNFxP z>=zdi!B4@D7a87{aHHVSi-=1!RC(X+jVN^R7AWg7EYLsBy_{yOjC@jJUc4)E` zG)(zosbBu>EkDDJ3>sar&=e0h=);Q@7qL#Zvi4?aHJf+u6W#Z?PB+KRmWTW~JJ3c6 zfDDv)vE?4_@5PvxSsTqJ2(e+? zR5okR%6UHNN3ZCE&^hVx4a#7@R}sdu^t#k~eu!#vf0zgwzv;Mf%C`A~iynV*CWDO^ z*SpXf$md|T9Ie5>`qYknSzoZ$HF5GQEciKULSwtmqr{q6UA!LU9Yhf>m(k<6)I!Pf z@hq8Yiw_*l37wN+_^9mXRCa%z-YtDBO2jf z>wl+pK_#=zq4Rmpnl%Va|52+ zZb-wd>73KNqhI#h@J{EZ;)+F|n$VPwm;mVegeETnkagmftJ|{s0Q^gdN&lB8V@CU7 z0M^eHnFlD5NQ?i%PY=;T1p*g?w{s@m9N&VtVD@fzgdfg(EfZ^fKfGCLa-k=CS=W@u zRMo9r@C^T=dRVZdY(SQeMpQbuOnM#5>2 z3E=!vwY_+Yy>u&MV#U8gC>`PHI*_ntfH2^F`C3bX%ff$I-N!6lryS$R&6AXz!)(J}h@`u4%KpfrXQd|7 znUS7$oFM*N^Cf-?lWD7Sdtcq&_PVu4%A^O=`F4KIZRZ}iKl9Krk{iFSU zvra1$9uBiOalKi5-c+1X98H;TkZSF|hz4J4=bOE-{*14`I~$PbtLuAXzfzxd`f_`H zz$(nzXGnx`cH0xYjeYZso-@*;d)kqIsaK#1wQ(O2a)uQLV=CZRr$b&7l8`Iruvzu$ zcGXH&nbXQLX=H<)R@lY8w&H~yS??^g#%xL(i^8uJ!+mt>FJCe}jpq21@Z>dlsGn}v zw2d^g`OI)*B$c{~`Yvlm*Hb^|IuCWIHWjjlhJVDvKph&Rz?1Hh^h?tsJi-#i%6S_? zlNF5p?+Y zOHQMCb1IiVTDC+I@-SCP3S3yGjad8L6DSf0Zea#10?h_IWy4@M_RH70K+hq(mh&9{1Q0D5lpNsCrZ_ZjZ zIVvt}B*QtHzu?UgJf+D}sq@~`GhIGY>Q7K8`XuuCN&tj_cTO@EOXP9<`E=`V1!vE( z1_{|;dc3#A)+)-TtSl|+O|)lNINKDFL!bpnBA&kr;<-A2R`Kv~#rNt;8#QfwFQfa_ z$apSG#YuvQr&jMt_g{#Gpi$@S6ffvlg}f%gBKGmtZgp^)+3J%KSxyGf)Oir^XghQk zznjATYR?)ng$pEz%=?;Z$g9Hj9);ZAC&owFO6+)jTh->*qonwcjf@9bAj+>Qb%B>m zRDliY`He&;FIxozdEshB*aYCd9d|mUe_l_G=om>+dD!dPo#iaZ`1Qk@GVdarfefT8NkV>GKydV1In{@nkd2*ma80 zUU?OtG8FTiWC#Qtvn%EB&J2F%9}bR4l4*(jWTbE0++D~N3^8@|rZexVU#9`mgZ zY&ng`a^J~_P5s^xGK!~Hi$nqEX06kyRM2JY(!QActLl;d7UFzcSN<>64KX8Jtw;iE zuh;oq@0uh`Gib=?*iiKnlY9u{iv7`6_xp=hD3dK_B&f=e6Gs1S6{3RM-6_(aRqF6EW7Ph3;*&)eeiZcoVK~#Ydh2u z4~CbzE;clv-}5XnUvMSJ(=@QRS*HbTm_27vKY=)Gp07;25f1j_J$AV^V$B}$1PB>D zo8Bg52&ulv_@!4nXG%G#5?1B~irvkJDVS^l_!cgO{~KOwf5Ld6nToU$7$(+n!Z=&$ z8~NEGpEfYa!)<8i!#VVDEwKSpiPhmYiYp-G<@uD_wdQ9Y>d8}J3mUkv_;X}^A}&IM!kqR+3X=G zjy%8r_wVh-IY2i!u;5NPns3k3;E(KRNbZXzGH0OsZ>%5&?ulC%&0mlNn&I%stE1(5 z>XlvdzViA^30o9V?<1Og6-`Z(iO1&p`6gT7MD76qwOYFk1SI?B=c>FV(l_B{-^;AK z+I&HDPLscadgO}E3F>$GJ)WB@4uq$>JI_E~r8(9k=@xLE66@)yRXJ~UE)dxpV)pIA zH6YCi4y3+Py=*>iT>8#>RfHz>;Q`llu_okX^|hmysOsfz{r%C5&wEZ4cu7ZT*b_(8 zl&5^Z`idg(XCJPQWi8SFlG#r2SKzY8(xYNeuCB;H2PW#iDc2leWS8@ah;{bA<(hK8 zMZ=3|iIf{R4dnbhLzoFu6eIfha822ZuV^!tClA0_uQobCqF%?{+yGw5RnkJo@%xj6 zds5&7Hl8wrU9LdJjxw>jg9l?c4G~sN;D8z)OGGV??&`;yOP0gaP)KkuFsdwP}3jwBni-tH1hrl*vX?{S#~6> zoD^Hs!w`NOuse8fks0Zh>hl4OanC6EXLkPCZ{NX}en;|373#PsWz~oBL6xJWAKUDr zvkO6kRUqa~^2=7@#U*#%R{Nnm*Lk312(*1SE{PVBrF8bkGI+O^ zxd2wtnjy;zS=lIQcVo)vc=*KGu`S)eLYF{rHU|i>wrN{AAaXqbQ3|R;I)CK#_>4#4 zB^v4Gmwt?}>IdTPCm39$w(dEl9_je{r9-XFdQ<6lnz@1A>`Bp=4$ZcMsqr_U^~z`= z>%PpSDG##JTl|$4m2oU3)8+v`+fNy@kYf?kcgzoCcY-Dc5zFV8cfII<34*NN6zjLa ztdZQuhi%!Wlofq-Sgw%A!+j)Q=Ci@_^7rl=Vio zvHr5y;pXZJ7t%NBNuEYXC@U>R0d`&ngPTLfs7qwUhV5u%0nv_*bgDtL z3J#$|`ewb;?6sYdGBJ5KcY!KM9)!X|O0i!$xYf7QfEen^-Kh_f1|&Y?ssa^PYB5$!zkuaYhr{`OLN@qEg!VoFf)rgK@lTu?bTog_EzJ z#(mCq4p}ZA$i%C23cG?3x?Dvll3)Or)k8;ma%c_8Axai+QNQFNk|895 z{EwUrf-_C!ww9)|_o_3Ky#{)BQ# z8j{`iE&U_Ac)S^@XMOHV{ErLSAoM{QWffDRW>`Yish{1dLSZHTEN3 z<*aPceHMVZS)5d!`RVmoTZ<)E3{J0wrq}5*Sl5KIs}>ibkXx-Z#oRo+a06G11+jG{ z1m_@i?EUZGgK-`G`}=70#g+i3iB}8y{eH!9`B%v1G^U*J2^ z+JrzB4Y9(ohegX;FyOlZ7vh#j)~L|c3QzL`Z}nR8^dm?CV1AFqn8(B>h_fdyq0W9u zjg0*7!QnA2@NKU1q+}H4>?GaJO}J=rxES)1h5&+LVK_PCl~kw^+EVWB*CM)5>m=%L zgk?d-)MqMT!y582TbAx)N$S6wE2u)2FohQi>ODFNJ*eAaEPHP%ukZWx*QVfCs!clt z=`KjCsg41C$U?z_o0RFCiipSzv6nAq_&94XCXmy(jUOCJF`cr+v4XbxXg{xhwO zkPiGk$@=CSu0ggDC3(IHIRm$TH2Qznq#eYaT)k=bui`>aX`b^RhRAu+Lx ztbF$Hv}Kne`s8zZV# zg9ug>oxUZ`CYb85li5ztbI+^tf8-V;8g#q_XuZ+xU7Ev6G4_Z144Yc>zpPQQTGha+ zh+fGJ-d9EYUggR$JX%bLbJfN6t}LHOTWVxcL4$%s0INI$Sbx+vzDkG&As95ykr`x$}EvgGsTdIy&t1@OPI)bSaA0 z4L8&JAG*>xaunqd2r~5W(2?Dmk1(+kXhQn$MSvGC3n>{16&0+hG{q@rk>}gjMmNE| z+@G5bOtC`)IbOGd9I^WBG4_U-*jQhRw2s{HW96WD7U#l(t(1IeCEw>`Eqdph{i)Mt zW|~2?Ruo~wY!%-@Y>WgXeW~`rF$5yS#;)RJc1h{!J%7gSHYxY=V&}G)xOqoACqX+q zJ0vM87(jp*FCfk_L1lo*QmD@1>I3lem)-TFdc8sn2m@t5Qx>oxg`>g6K%fQ~%~Jq@ zqbDpZ4!JnjWA!fe;dgVThM70BOtGcHNXgY8ZZ{N^HuIL8FL?ccd559j7Y|lT;)>%zS z^S?$D@NSF_mtlB|pW`f3FIrYvMnj;y`DeZFik#aWqKlLV0P+cOnp%dDfEuge2StuT zt=I9Jd1G+^tDTzhOCmN~l;qDBT+I=!Psm$py6Aqx1#EPs2agIe-I>qqh7Hjd$#|YQ z@pk;uVp%{R9CV%Wb(nx$uw8{6Ivjq-gNB5F25meCI#sRjoho)XuQ%De&MzY0BGJ3? z3pka`&#a6s??&W)-p#V(9kSz&TR9nA;6V=UawBH|gX!=Qc_orf((HlbgD3&-6_K(L()rrG*D!~)9MvHL?{`y+_WNjy4;O* z;ZIse9EI~+MX)N|Qkl}m_K^E~krJr1w{VuI3ze5@PjcwR1+OQ71r_6mcYcI>;O~-0 z2!XqZW96oOiz7nk_GGk?WMslJwF(=0<@t$ZKIn!P(zJ{v^f=o-?8b+`CAVeI8rYcS z)T=TM31uL`Oj3Yp=)MI6JnUp$yROMfvZR!6Hn=$YtebfFgN>D)d0CS*RY2v2#1c@ShC|tHZ9b|5iB)2G2*Hxb0dE+`E1R!`-h}f z7O!ll!s zfwI+t_i#-Y+7rFa0tLKgEL>ela^T>yHFF zuJjm$cPvtD;=g@nrhn6nOV$ck<_6Chd)vlC=y ze6|3>wqkZNuoM+MMSKNxpEl0=A@@}Hwq^km{rB}RJ(hvJf= zY`Uno%AsR0br73b9Z%Xng`r=ShI;w`dg_2+(pi1qV9VU4kUIR=a9Ane z;CPupt88dZ)F38}a78UzZ*WShAwWwJ@XV6iCk* zb^KirjfaPNMhBN>U_j0);CSGH(`-{PuY~h-%Yz6>JK|o4Nuez@&T~veY4b`>`P-@> z6YU+PkCNy*!_H1KcTW0eL%Ma)KA=sc7O;ZY+D??gk{4?6I@ z7Q017@p9==VPvVwk^1q3gA}=jW1aK64X<+kgL%Rnq$z&)p%SaG9P@{7sEkBA;6|Vl zbx)ktY0D|JsWVVkfB>+woF6H!GR(Bk41)7OKS)Y(^jIV47(cbk#5Ztvccq9}sx-0< zxAxT187i|V_7@Fsh&pLK&nlC0gm>E1f1}509|96*`)~~%3POQQ2+|O=5Q0=7z>sTo z8(n06>BG}4#ZI5bcbkIe*~EODlt%l!EQ+7GKaWY0H~^8Q8(5xI9mtfwE7&7NqpGJ? z>!wnLPwP!r3xK=Iq=8!{4*$AaceDAU%+hm@C=~S?FmN!xymQl=nSNNdoL3s2T%p3F zmk}PWP(Vgxh`eVp@x|Jh4MWpqBqTuu(`d8AiW*1&=7|aKKJWx`D~KGuf+8nXWh!2e0xr5d%f&Ab9&c6U zqC>Jma~xYJsyEbQ@xH!L7%oodLWL3MCPKq#2t_@8?E6>g8(I`;kjgHBFAo-wV~9&r znSOZ0zs<;%x@xU5cbxDt{>-O zy4DhNp+!8*FT80UP|s?Yg?sYra`VnlY=oh@3R9M7F(E);2Q(Zd<@M&y_?1!E7WxNo z^UJ^6r?{~wGQQO@k|RaL$ak&ISpJ7Ro$KiS?m@!P!iDtl+QK*ySrBX)5bKs_18z zBGRIZA0E-beQ|OS?63PW;4B-DfGqsSsTEp)9Nxw+b z;UX3Sv&yZ7l8)4)PzYiLbab-p2<39D(B5M&DxrocBdI-Y^EfyXz=;!c#~v>i8MQ;A zC+a%kV&oAEH$Cc8VcLJZ{0%5efhleH;TaR=lX^1nj3iB?iio2?A2Ip4iHRHg&IE$MwC9{4-aJT=Y8+`&mJHkAy)c!W8Dva;`jatg0JVPrt`r&_J)CDBZR_^>U#_Bwr77@sRfL zVz%V_rsfN%7ZEmR`Hn@gm^5P0GNNK1$$0y5ThRWai?2U6ajRyQmSYAk7LRK-zi;=**Tlf=l4ec)o)ZlY#Y4>Jg4to*qk#ABP!@kq^!E!zIr9nUq?iX{6od;a~>jA4yq1(*U{P{;{Ja zKS^obsJcBExzH{Y2|bFYPje!093&Jl(=R9Khn2mHnLn-xnFwM^xZ zz<))bM&^A>9BRc2Df(_#o}BOrx^VwJMw)@FPgf@#R!$-p<0>2qKae*64-Go@N`}bZ zf2n2#3RE#7aM8M}h{h@c^Z?^_srx*zJ)$$N52rlzlZQ(5SE2J-mG&t6lbr(Gi(vJ^ zx3BT5_Fg!@ei6bOAf8i#{B=!MGqs@H;_>aixd={-`jN_PZ2B5G*E#pAU#nyZ@}pCs zIh(HJ>yosgy8~3%&on=_a0@Qra*ULNKtrRl|BQl~;zH4#UL&i700WIq0uZ;{{~8GK zFZ#}!%(BWJiyz-QG*D;|5Yn!a-22Lq$o!{QK3ekr^1(DPt-ZZ{c|i5_`#+JSg3gGo z{o~90_p^MYW_|cR=`3&%Wj!VD>9@8QCe!ixgq^hHr|zSljt@xd*FKXvSKn<^Zxig> zO_bghI))57Om2%O`Eq34#^XC~GOgrI!<@^#Y&sOthDSyW>a2M9Z29xOK6l%zQ_zRg zkj1*4{=V_JS@Cw;9>fKv7S?l#5*#C*;d|G@gxwczY^t4bTB6h8+smg*Rs;FR?(P!J zGE6|{@`{nvLaarH2l8e5G}_n*zQ!!MjZclADbj(+WK4L6lz&sBGPm@HKWBJ&SaD69 zr{LEho4CJ(WpnyKH0keIzy-#_Vl8^;x6t#G#l(Vzk_ea zenWlx_Xjz1KjFW(4b%JR6UBzH+g}3x9{g~!43u_X3I+(YtCHO<*<4MU5{(a?EiJes*u@v@#w**aQzfAHAPCN;z0K8;g6f~E z(T_U8&vAXcChwxIo)CTUQt%iQ)QpejlI?{~3qW9i6nyRDME?7%R~Yi%vz|6b1H6!e za;L0V?Y-&o958c(=w;jBSoDJXC87dIM_0ho038J-L8aCZHeh>kB(d7|IP;2Mx45~P zG#C;bV36OyLCzICEy&rUU@`rP-?uMI#{m|&)y8)ak3QE=+|Qzy&;DEW@53X{kIKre z;HSe35X*T1(e7mOImpE1x6hL}zpASI$so?pBG%p_O?H-=Ly>aW*F{GXh%k&1VEgOa z#F&HPsty_O(FqDSFMhere+F97c!~!0ELT52hlkOMty)-2p$UG#b8D$5 z(lgcG(#&qB_VSKk8YGW6Ub?@L-K9uUU&qsuivhd<+Du(+enO*1XH_k%GldUjQkJ%9 z>q{}Rnvhd`_sD5+d~K`B^xU&Pf}r-c&YzQ1K+M&m%vZ;^-rR+W(X*_m$ZZK=D3-#iUegm< zxbjQ#LSGRqtD!momQ+n2Wg1x*qy|)H5OTGGHK)b@V^}WjHx?xTU2fPZ6vpTP1BC`ahB_I1B&) diff --git a/docs/3.5.x/docs/images/apps/mybrickbuilds.png b/docs/3.5.x/docs/images/apps/mybrickbuilds.png deleted file mode 100644 index 4d9f560b3ba67f9d13afb5f77b71a2fe0d14e4c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42263 zcmV)8K*qm`P)-8l5@^cREC_vA)_DyB1r)WqJStMf+!eCA|Qw;B1wXx zAPNX5Dh5E3>;=RB_PyP+XM0Zf{ibepb#+yBs2Kp*ZWBX817R8ff`Y?IHikMpPR=eo zxL1ID_rnLsh#p~~+E!L(;D0SEqX61@K9ksy1^$19*3&D@0|3Yh!S0@69zh7c4FIaq zBa{>l0A@!Xe^hwr4$ej}0|`+O!4*5$=NE3=!S26s?=Fv>jV^+x0Kiici6kEY2#W}v zC(^?QkwZlZ0G2M;(=QlddlL@g~vut?iK^w?NmU5h{b{zQ`;B;b ze!vrX{-JyP3*8pPf{%z)FA(-;G&CDp1FeQOLs~7Q%A%FgDu3SfEjBFv)#{h7K1g4Q z-xQtS+DHDY_6PkEN&nWz{cn%|)X4zM>`ML3AzdTAAiepg|35Rv>SOh=Mpy%^2r3nI z3)PLfk9v%1K{Ws#R2!-h)r-2fga2(5;%}>vcIRt~jOYa-cE1Jxj~Ye%<@imd5~WfA zHoN=*$UDEkBRK48?e`y2B9Q8iNb*PCnf{&QA4>}&)>T03pw$sOBQ{1eq1k{0S{|{u zHd+($fdWF+{r6tKTM6L3Ys<*pxdecB2o4JOiVoiibls597?PilZ#a)OvRitI^B4zv zNQ(2wO3TQCoxS(h(*9<%yQe}-{r}L2$X=){3jn#!KeP}eHf!^d<#6^Nnjo^ySXBVH zY2y(=iu^@G?=%=>N2f-jpB33T_<%5?rz}teYCsF<0~25g?0_>kfLPZT1R)wnfg|7; zNC6oj8{~s?pcIsYDsTP-?ao+#>|tyswgg*;ZO0B`r?Ja89F7$yhEvB`;)u9#Tng?i?kcVgH-wwT{lHV; zx$&}i1H2197@vqQz+b_);)n2a_zf}|G66DGGD|W~vKX=~vI??hvVO8zvJG-tav^ec zayxQ=@?+$Mplq9&sjpw^~7 zKpjh6Kz)n4pL&soj7E?~mxf3aPg6wGL^DRSOiNEILu*MJM4L%_h4wM+JROcskWQb@ zlP;OAoUW5@njS^ZN3TooL7zllLEl9`%YbDNVlZa#XUJf<#?Z&G#7M^|&*;Dy%~-^E zk8z3##U#jN%oNC!#dMQtlxdxrlUbYDi#d(CmU)PIm4%%}i^Yp2ou!Utgk_zThgF|7 zfHjA;fpvln%_hob%@)OWo~?^*k)45EjopJio&6^JI0wuj%3;HCn4_Gdmt&cei_?%Z zl=CcSC+8v;6PFg3KUW@CE7t-yJ+}t8A9o&i8~1x2MjmaRK%PRL2Ruu>9K1%n5xf_9 z`*=6@2<@@olenjD&jcSipE92}Umjlv-x5DJzd8RA{u=&q0Wtw)0bhYL0^I_uf393!qG9xPraJ|;map)C<9Q6uq2l1b7`GEuTY@{<(5l#5i3RJYVmX$9#(=?dwW zGITN~GKn(HGGApyWj$nzWQXMlat3lo^LvH%dhM;) zJFUJ)ov40MeM*Bz!%gFY#*`+nCQ-9Y^Q{)2mZw&w)||G8w!ijO?N2(=IwYMtI;*;> zx^cSgdMG_Zy>z`keL8)6{d4-0273&A3~CIP3>6Fy8@3x^j7*JkjK+*PjXjL3jh9T6 zOyW!)m{OYBnw~R#YbI(&GHW)6%}va6&0kpvSOi-%SOQC9%UsI|DhU< z*6(a&Y>wD;+tS+}w7p`xVy9!5W%trv*gnF(!-3kt)uGy9)ltv!wBwYMlvAA36K6JO zKj%gloQs1?rOWa@{eAiSW?dCrQ(Q;)3+<2I|M&pgfxrXz4pJW^9=zp-adULL;BQ5C-;*4Znv*$`6OyNo8y>Go zp-Lg8jGa(BQJRWQ^-JwblS@0B_A}ixy(dFDqab55(<8Izq|C{}liR1fPxWOfW}VN* zW(Q}F=4j?rou)k`M4Xu_G%IX8%YQce?B+S& zb0bAMMRmm-#c9Q>C7vZi=e5q)mU5P6l&)X!yYT#?;l=tg!LovKY$lGb*<(2Vb75vZ;DdtyEooh2u(A4O|mZvvAe*>cBON2i_>k-%A z-*CGzdeih~$1UYswYLRs7vG`3lU@(i$J8%1_%=*6IyVkBnKX4Yt2N)bD|z>F3vWx& zJ;r-kt>mrAt=ny}ZOiSU?Thz)?oW3d?0DJf)H(dX`axfpY1gBN1`j*CwY%FMsXuCY ztopdAN4clriQ<#`UWMK}PZgft=~L{h?^o(?98ei(9^5f0n^K&*_eSqc?_1lq zFQ+}GKg@*9Y|bXXBfKk^yGPl8&R9M&B85_t>&Mm zKVNMJZEuGXNyOc&01BzFw>JP^FC%%2GXV4h$en`fS8nvXppeT4j65A6N$3Oo0F{Kc z#b{xLaBO%MGH!Bp3Jb~rLN-+s^&+hVofmyM!!(m9a|}xx8#TKlM+N6M?!7$8yifUP z`E3MF3O*4AB66bMVrRsABvz$_rLAQWWNYL`6ktUerTxn3D)p*w_7c>UHQY4Qv~Fm> z(#7j3>U$Vu8#WqEnn0%fW`^ee7Fm|Jt)5%|uw}B7v$u2zay;o&>-@y!&Auhq)%_a> zfg3rI)m_3v+tbGDptqL~(bv{*uRl)!6fhOo7IYyvDa1F_>X0&tCk!9I*i$+=S>v%Y38 z=d7Gw&Rx!1FF>DREEGR$c+R8fXmMdl?fJISCl`h00R*7-^W4nTaf^thd=FIVd>gxb|@;@Lc3= z+w+odS%5;2TS!6JSj0^zmk{dYA>9M_a^OCRrV~PO(X~O}ERmPj^UmjB)aH zwsX|UJsAazu!&U0lTR-%FJXv#D`?x-^Nx3z?>whuu05XN1!(J#XDhn-! z?#IMprLYUQOL$*0DY7;49*R=RD1r@@EHxGN3e5}JcDic%T!uJCA0``Sbrum;M%GQX zdG;ZWR?b?ka_%CY0^YnmS$rw{kpe_PeIXv9AHuyNrJ`YCM&i5@u*8DonA9WbW|=Fp zg>nhg8ih!HOC`PCeDn`uU)G4g&^nu z+Wvb75)SIR;oSy_#qI$fdp#*V$Gt9lAM#Q5+4ODmOYqkU00HfR$AWZ&(ZO9I$3wM4 ze;leIIU{Fwb+~2t_lUyCy^)hq3DKO<_hQ^)nPSHe*BnWTbBY&^Upd;DkbBH0Q7=g} zndLY|3P|~WVmkF{T3vc(1~F6qB<|$+sq0zk*#S9*r|C{V%-xr}m=~L`U7&L&^(_8e zdeKY?>v`Eyl?y5t70RT_g)4Y3u~yPvCa)r^rbZ%3{i@rw6Sddso?YL(DSXT2_USu= z4GfLWO~uV)Etq>Et%hyx?MLsQ?`Z9O{b2hcZ@2CvpU0U!H=d04ZuN=u?;AKXIQdL= z_~gi^G27=&c+tDBm$tbUa zRxpHQ$D0rxBm!w6`C%Az63GXlsuTIvH&kr|tmz2v_okR=!>WGXBsLJ(OJ9TB@LeqJJ8 z(p5@Dnn8L==BexzxiooS1rtR{B}S!f<&P?pszYi$d%M&hXmo4#X^m^o>#XPjeJrxi z;f?UdWG0lR3}(FM@)j1B!B%#DyH?NEl7bOEx>caw0EH zJiRN^>l9zt>#6ZzYPJm*x3&CVaZ5L0%cV*Ij1^@Xd_wNp1P-agPk(Nx>AzfG)z zyUXBFSubV3@ZidD&Y19v!B^*BpLsj<&TV1sBi-k#U%_|j6_wTPweKZWMN`dDJ5%@37|^uSYS6aP>C*Mk+tN=U zndv%X7LzE`6XruKOf2=R)~xT?V%Q1n6&zX|Gn_eGCfroq6Fj$gPwnyJ)8S{~{~&Nr zFk8r5SVu%aluisUj*-AiQc2NC)5_pw)@0}9#^iex?knC`>QR2F@>Pv$ue7?ghM#7* z7D?Mz$4S>vPeoteK-tjH=%8`D$wkv{vn305OMR;V+th9!T7kN)5m<0Xp(zU!c(znCo<5Psi)YpI&%_po$__hsGU_SQY%p@6}gBmdsq=! z$$t4>wR;WY)rs1!>-{&E@5nS9X?oH^-Ky74>Zp9M(5>_MX0J?N@xa8;_u((2bI+&8 z=U;t)4ZR_sW|-xlGg>HERQjC$t#UPRt#2cFvvceF&$V6u!^rBV1zbP^XaH;A4dOrn zxDI;3dx#7YgUlfkR0y?0?_nlb4-SVb;c*l#${3Z5YDaCM)zGo%X7naT8M*`yiectr?qfN{>dvOaF3Q2cvB5dP)yRFCCy3WM)l zqEur1;#v}Jk_l2J(v33DWWUL?DHtmzDs`$*s=BIOSH~fD)mH62I=OmG`n85G#yl~ zh|Z{p7|+9>;wutjj*TX6Cd0?^DKsbKQp3`QGwd@LPNil`=Df&F%~vbd4-O`L=0lis6099{hM z$>4L$QpuN-Un9QheOvv0W!Yl+<%;jh%4+25!VlLU{cE~wHS2`+(Dk7Wg^j|EFPp}j zWt$sYc3aneqJBF4yt)l-+izdl@qd`Nob2xL0a5AzfSKIh{w4?j?lb^fIosPCW!u|Z z&Fue($s4ZAPTe ztTdHb-dDA$c4)K#&?FoQ0)!zU5`+x(Sm@BR^4)m7D*Sp|p$Cs&(kE+OW3}(~-tAvjpWJq?`27bTl>Cf-Mn9uFNPHE3CKx}X zpD6t(3@CntbAA}oR-NYlvLF1mDNO)Bj%)sm{_2wis=AJE7(YCtdmeGyMtzs=O?!8r zT%v}270CxIAy6FWhd)kL`|m9A}03iJbE^Z zS1JR%`2L z!gQac2=Ifq2cebkJNiioq?D@;Zocp1`TojDw+(`8(aQN!QQpTYKX^A9mQoVm zwvDa-?4MCS`WA|5QaO2?>|>9y^n;gZOiUmYjlsYF4;lI!pTVlwZ2edNicohuT0BE^ zxF0Rw%bx%GhxGs2uaOw-r*Py1oge!}ymE=euHAT*GTEozM{KB<=%%fh`5Z<%g}qo{ z=>PT)+4@iaF}lZ2&t;*`7X@1G`{EJxh??^2tfoe-lfNTS7!{NC_7h}q9dDWPE8XZ>|_4LR~Y=8f19AT#Fc;Yzf(SSmckovG4Q$1 zg5M;*_hCZ)12h+H`hWd1)GwSyjitHtzx)p*_CG|=hu=?6y-8}DZFYGEfk@2=`@wuGX3v+oXWW~T>PUy!FRoP{rTQ~8zU4V|AFVQ7Z%Ap z_5@licFV3vKlT{b*jcXpKfi?3RC+)CDe7a>)K4B_=Fh*0mg>OFq-ab}5!tefL^6k8 zDDoAjB6HvP#_FmR-~u42OpX(ZM^W@JnN1rho;u3%)iIo=#oUo2G$v>8guvt7 z_ezPc3i0l^Yo)|&Z)eB9{kP;l@BsqbMlnp5Ui?0%{?^~3IXz8$_W|^n%JQp+(PBxG z2lf!^>8E<+RjL=Rp(Qf({q4Vv9#&a=@ducly@a|tQB8yD+0)nyMcUr;C~mb*1Hf<-U*YG`XXKzrwGD-e@ zPqFY9U#5QP`n&wve@bX&fVc=0?|t#PxF zI|6n>QRtVF*t=wWzk7nQ^5V2)lCF<_6eE|zEf$&i@|RnN_sWCbG|t{(c!`$jCRe$; zyMvmmcElPlY)ymxw*P--c>j3F2d*dzjUc#l$1PqEYfcTCqA)Ba(f=+5`T2Xy0yx|uchb#-Gt;htbXo#_p;VKy#0Rfea`*fajQ+aZks>+)8Ffw zcSe@iWvaUV*sIP1ip`JS$JLzp-VJHNB9kzl{r#F z+pq%_*J{#cxXfL-hD>x}q|>MxsD>aMR>&m`HgC+bp*upOR%U#vj_U;|nvMX31Xb0L z0$k6<_g&18PG?&bC9s)Ww5c_HPz9Q*VrUAQreGKXMNtTR03C^fCk27$qN+ZoDbS@v zGfWgkLy-ba*U+>O^`^upXt^MTY)OJpQH4u@B=8kvpdgS)d6{ z?clxd{Y4Z-K~>dv^ylpibvuu|-M8|-`DC^BRuj1OgmJC^*AtApk6Z2jRuk@Z1AMDV z((R3}cA-0OOyc_i-+KO4zWcowfjE%B2=62}l)*?(;Yo=M0zBKos+0+6(m9-`Z&QZT z&mW@Z93$Q}N_lz#>?VFJiJo&&jXBhihGxKMe~c#|=po&i!t!e@7H7CVQKaE0=w_Hm zJW48)AQClj>Ltb|CRr@Hrk-xvGco3ibtab@6q_xc7cxK!g?L!dn>JBRovSlt zYL;wuj`WcTgpf!X;J7Zn6Ci*f@DR$|42hKJszo?hBCJ8YJw_-JN6`d_f5uMn@`{7@tgl^>os=!32R;K?h79|a)dYEd=nuAkw^qpRjD^-*svi@p%BGa zcaa}@7%iSa3J`%rN`YoXQ51z_zKsL#*+N@;m~807yzmEqOyTS)!kt5?{X?js2m%SJ zM?9v`-LCQMqy2QIqqy}3QZ!K%jeJ|2vSkxUpLEKkyE9EFqEebK(31;cDuPHXpw=iN zHItE%0i3rl|CEtZR{NxL{$`g8DP5}O~<2QJE%g? zo=Tu8l2kZJZ!W=NrO8aGNwMJ))&;|z2|5#D6cpOxCKslPELB{BVC6j`kpY;Rfrtp2 zmW}Tj1c8sDwBB71ppK#{1Tp|2$PT19@aQnuZPfy51bqK1K{sDMNh z0?p8g8V1Co?=T)Bx}-lFqazii+^{h2rI&ZUWYu1^(K8Wu>|nmK|%VEbX3Ql(NZ5Y`1wECK|~&CTIEO+q0Pn*dLGD4vS0 znFurx9`a^jZH>M@d*KRS`r3C}*A+MUL%jWfLLgWfiC2D0Ay%5ZZG;vAfztZ_Ca(bU zu6AyV?%v6NE7x5aGB9>$@ip}O-1LSiN@LV)iWAe&5=C55xbZ*6z zK6WF(Gz1SF$TQsAMo7A7ibX0O$M$S0%T>HUf&!6fl&on|D%LTT5D`nG!}d^8y-bZ=D_!{>jlb%1vWprg|41B zN&t#b(G>-!;V^UdHNsVoz)oV&;E7*&fb9cW6zS2^2I*LcLQS$%Qc!e3cdm`jjtuE! z4EzQY6VsH+E~Q!(Ba|ZEW|CA*!l4j`ZV*xhJ@F{Xka-)M-!_u`Sfca-Q_&b|PmoKR z#0(unRaWjnkP2z+8t&xHbJJ8B4oFGh2dJ8gqO?ZQVpAcL(hV+f(#nk|G-K|p6N#`bN4#1dJ| zPz+5o5sHfE`&f?8$upOk92>hOP&b+X)(q6b3%xx-p|nuF+KRBTI&Q z?pbAex!1ncF6g>0moHx?7K;IJ_3BkT&nMNriPDt?7Os4iboWDejzM+t25rNGB(o8k z4GS}5A_y>aorfNIh$}}6_Zv3FAkOLJrR-XigyH2JO$ z5~(yI@Tip*u{@7dzJpX=MK^R*O(Co*#B`Ogs-r6^x~dRX)w>4zJ5|dc3klE=WWwg1 ze+p1g$S1>WAI@|1(k!k63OYj%s7@wf5{m{%uZgBhf&dId0xF;qcoIKwiA3T= zOHGWaDPmm;B6w$?-eM+2Mb%9FAXqW@Tl-s{F=d61#jX1kE3?JT5x>5Cl^e&7lk4oG zyLXg)&k)&sC(&32O*irF8k6HK!MKH)LvY(<(TeZgiDYZ3Wp}^6+tm5BJYaY8@mj~c zLonX)V(xO`uGaYNy4~%^UAc0FMx#L>C9^X#ASE02?j$yl;rw_1n1#z@51G{KRV)#g$p=t3;cbHhi?jr04W1NVZLB7FVASUtIZIrO})2otExsW z*NzBW#wI5LC@)lq_6p*iZ75nlnf|>*(g~yp2waER$pt1)U8Y)U5QsFh%N3sZxq}RE z&!dQdR4Rd?L|I-e<5&(8(@lICkcfxLr=!#x9=eex6poXK#)+9GNnH@pR5V3h(OG{K zXvj~N1T7~3LT!1u^2wEc0EvpkL(+QZy3ulIfFO`A8VaT~pk8758-GsyPri;)YGBh! zEnSalO_yskCF((#MBGQ$Rpw?Ev23Tsw2DAkxfV!5;V=gud4PR;x06XH2pJltrlRW_ znyR!M8>(_kbsE{w$NQf+z;dO=ONUNz^sN*4o_D9?3xVfL&Rkt&ddX(c&ETjRwvPDk z;J>x_bUm-@T70anCT(lcYVNJI1WO2k=ld9%vf{>*l;-MGj@+O;HbE#kL^R)pZM&#K z5U2sUe1?s?9_D*r_#Cvdi&ZL zzj2Lntx0#^Ac>Gk(hLz(HB9w3X!5N&|Gz)FdDqH{2`X3ge6gZA$v`3$Koy|3)EN<& zsDVnbJjLQ4{65y7J&$ZySPIxdD<9&PyI~cTxhLwi>oy3zdHjQ@Cp3l+K(?c$sCL9S-`T^iJv&LH(ljj(83+s^NU93Cut`W$(Qk6i zPZ`}2!4&{1inu8(Ehg1vfFi>LvQGJh=P7;p8+eXGfJ7is;T`VIyO|@OP4W1FIEJRQ zih=kNceIzs9@s^>*5K9GkMZpnzK>;FC_Y=%@KMI;&_ z6bex)m1$HL*t&TKnx?PJ-~vU$jxB?nJ981~2WYComeD?T@7Yd1mn9kv6E+P(hDJzJ z5LWrVahvx8V!e9?(biL;Ry$#>#%}*DWy{zr77BNCVs+*Wh50zy;k|@&S$ql7xAA4b zmaPNi^HG$*XZqr4W=@@=I5C9UXz=U5^+8NMAfE{nH*@s$4KloWGm%)B#rZj;RB6w3 zpbC|QVG!5!6`%M|AK?9#S_K5Wo$00sg+NLase#(EA6(z1c=#2TzWFr_X`^TY8G!B! zG$i6CAae~v)Ny^vwI*R*VQFcOY&MT+n&`S9lZ^77#}6<)JY+F035#jWyBP`C(vvG6>Lb(~V3}{q~Xo|q|1@-DYV^<0U zUWu-*9x`oh#A6BKu^6$4Nj@U(Irsmt0&%<9pxw&@b^A&86U(^WLv_dO19**DLdiZ- zokIvMgkcB*FGMn~FxcOLA_61<8#Zp{&^KRU=EfU*_P0Jq-(Z?*ae+B0s6`Zpw`?OG zkD)j=zUNS=NGu!Lk{XeC^frO`?^A8M7u|d+A#ctYZ^vJx5EvM^p2f`bUt{)P|8tD7 z34BeV?n(+k0l^%S#){X6Ra9eu*_kO`J$jB@XE)bxTp~c>q5Th_2=M#>+i^%HTCgAA z^C&DXFh4toqUp>`&12O{D*<1fY(CHK2Op=SyPrzU=Ho` zfRN10OmN}kRr2S1=<4Yukw~H`3bAOIfq@~Od-9Qc#+cUP>H9$*Yip@OtEo^of8T8U z_WgI0s;YM!>-#?0fxSc`4o+v=CuU;o_xv{^jqz#=vMFpLyR-hT5}))s=g><h!tSs z3L<(Xw%|KW#{c4rod37~oXU*}mR*$@TQcjyqAw`OfF)ob;+6rvS|47%aGrnl&;Bt7 zpZPwfey?Uz+>f9LA>J9_`;ofoZo@^>IB?(qsZh6L9Xp25Jly&` zsu@NPMX1g%Ae&2!jP5}wE^YuP&yAByhCph3^fMpC2!ZRUba!^p)s)}_P+t1G47@Bw+vhY(Q6tXo7Na-VeiMR=0N4bRyX?ZSN-XRZ(>$wyalWYB3 zIC628g5y%K11bTOCDZ{2*c7b1t2HQ*ZAVXMIdS|=X0Kl%*FQp|c8F*s!M6PmGIsq6 zstC87D^gRL+%{?jn}^?bfLykPQ@Va_jJFP*!&)lv3%_`f zo}qRM#bsh)g^1>I@x%!peB@yob&GGke3qu|@*5xA#g3jBs<;^l`{|+;R$=bkG3H+X z9`V3IBJq4sOdSz25oQFTsx5ei9sF-B8_7o8(VDF|)OioWSIlI8ZQjx-PiRD5O zBc$EozP_7*9NVR{XCp`-rCcUiEuiMR$aeQKIe85)2+&lCRBoOhAQXWajp6$~&7~Q( z_6$;-pCz|pCcMg;9J#q@arA#?j9z<-7xgqd0ks=iuqyGrq!k;-}jlBnc-&I zuE?jqkni1qzug@!n2UAsHGR#`itEnI!}*$H7fO*NhM- z3boQA6$E55#G_GkUB|yIO?@p@>25FT&F5S%zeq~?_Ka~q@r?D-5^vY-eBbBz@#9>& zbcuSsPOyTtiKmimKKLM=8?yYtKl;z42L>6NUnZW=NT=gG`>|i3y|bJ4-gXYZc!Ue* zZt&qxKY@@Iz7Px#4-*k8-MJ_qe$Pe@jC7!DDnC8KaOry zR|QoPkpWs@BV3}C2t`YB@jo+PD*F^v$_rFP

  • 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 Hu0mjfzLskk diff --git a/docs/3.4.x/docs/images/square_bg.png b/docs/3.4.x/docs/images/square_bg.png deleted file mode 100644 index f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.4.0Fork me on GitHub

  • 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 Hu0mjfzLskk diff --git a/docs/3.3.x/docs/images/square_bg.png b/docs/3.3.x/docs/images/square_bg.png deleted file mode 100644 index f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.3.1Fork me on GitHub


  • Mongoose#Connection()

    The Mongoose Connection constructor


    Mongoose#createConnection([uri], [options], [options.config], [options.config.autoIndex], [options.useMongoClient])

    Creates a Connection instance.

    Parameters:

    • [uri] <String> a mongodb:// URI
    • [options] <Object> options to pass to the driver
    • [options.config] <Object> mongoose-specific options
    • [options.config.autoIndex] <Boolean> set to false to disable automatic index creation for all models associated with this connection.
    • [options.useMongoClient] <Boolean> false by default, set to true to use new mongoose connection logic

    Returns:

    • <Connection, Promise> the created Connection object, or promise that resolves to the connection if `useMongoClient` option specified.

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    -

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    +

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver. Note that the safe option specified in your schema will overwrite the safe db option specified here unless you set your schemas safe option to undefined. See this for more information.

    + +

    Options passed take precedence over options included in connection strings.

    Example:

    @@ -285,11 +89,11 @@

    Example:

    db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts); // replica sets -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port'); +db = mongoose.createConnection('mongodb://user:pass@localhost:port,anotherhost:port,yetanother:port/database'); // and options var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }} -db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts); +db = mongoose.createConnection('mongodb://user:pass@localhost:port,anotherhost:port,yetanother:port/database', opts); // with [host, database_name[, port] signature db = mongoose.createConnection('localhost', 'database', port) @@ -300,82 +104,58 @@

    Example:

    // initialize now, connect later db = mongoose.createConnection(); -db.open('localhost', 'database', port, [opts]);

    Mongoose#connect()

    Opens the default mongoose connection.

    show code
    Mongoose.prototype.connect = function () {
    -  var conn = this.connection;
    -
    -  if (rgxReplSet.test(arguments[0])) {
    -    conn.openSet.apply(conn, arguments);
    -  } else {
    -    conn.open.apply(conn, arguments);
    -  }
    -
    -  return this;
    -};

    Returns:

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


    Mongoose#disconnect([fn])

    Disconnects all connections.

    show code
    Mongoose.prototype.disconnect = function (fn) {
    -  var count = this.connections.length
    -    , error
    -
    -  this.connections.forEach(function(conn){
    -    conn.close(function(err){
    -      if (error) return;
    -
    -      if (err) {
    -        error = err;
    -        if (fn) return fn(err);
    -        throw err;
    -      }
    +db.open('localhost', 'database', port, [opts]);
    show code
    Mongoose.prototype.createConnection = function(uri, options) {
    +  var conn = new Connection(this);
    +  this.connections.push(conn);
     
    -      if (fn)
    -        --count || fn();
    -    });
    -  });
    -  return this;
    -};

    Parameters:

    • [fn] <Function> called after all connection close.

    Returns:


    Mongoose#model(name, [schema], [collection], [skipInit])

    Defines a model or retrieves it.

    show code
    Mongoose.prototype.model = function (name, schema, collection, skipInit) {
    -  // normalize collection
    -  if (!(schema instanceof Schema)) {
    -    collection = schema;
    -    schema = false;
    -  }
    +  var rsOption = options && (options.replset || options.replSet);
     
    -  if ('boolean' === typeof collection) {
    -    skipInit = collection;
    -    collection = null;
    +  if (options && options.useMongoClient) {
    +    return conn.openUri(uri, options);
       }
     
    -  // look up models for the collection
    -  if (!this.modelSchemas[name]) {
    -    if (!schema && name in SchemaDefaults) {
    -      schema = SchemaDefaults[name];
    -    }
    -
    -    if (schema) {
    -      this.modelSchemas[name] = schema;
    -      for (var i = 0, l = this.plugins.length; i < l; i++) {
    -        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
    -      }
    -    } else {
    -      throw new Error('Schema hasn\'t been registered for model "' + name + '".
    -'
    -                    + 'Use mongoose.model(name, schema)');
    +  if (arguments.length) {
    +    if (rgxReplSet.test(arguments[0]) || checkReplicaSetInUri(arguments[0])) {
    +      conn._openSetWithoutPromise.apply(conn, arguments);
    +    } else if (rsOption &&
    +        (rsOption.replicaSet || rsOption.rs_name)) {
    +      conn._openSetWithoutPromise.apply(conn, arguments);
    +    } else {
    +      conn._openWithoutPromise.apply(conn, arguments);
         }
       }
     
    -  if (!this.models[name]) {
    -    schema || (schema = this.modelSchemas[name]);
    -    collection || (collection = schema.set('collection') || format(name));
    -
    -    var model = Model.compile(name
    -                        , this.modelSchemas[name]
    -                        , collection
    -                        , this.connection
    -                        , this);
    -
    -    if (!skipInit) model.init();
    -
    -    this.models[name] = model;
    -  }
    +  return conn;
    +};
    +Mongoose.prototype.createConnection.$hasSideEffects = true;

    Mongoose#disconnect([fn])

    Disconnects all connections.

    Parameters:

    • [fn] <Function> called after all connection close.

    Returns:

    show code
    Mongoose.prototype.disconnect = function(fn) {
    +  var _this = this;
    +
    +  var Promise = PromiseProvider.get();
    +  return new MongooseThenable(this, new Promise.ES6(function(resolve, reject) {
    +    var remaining = _this.connections.length;
    +    if (remaining <= 0) {
    +      fn && fn();
    +      resolve();
    +      return;
    +    }
    +    _this.connections.forEach(function(conn) {
    +      conn.close(function(error) {
    +        if (error) {
    +          fn && fn(error);
    +          reject(error);
    +          return;
    +        }
    +        if (!--remaining) {
    +          fn && fn();
    +          resolve();
    +        }
    +      });
    +    });
    +  }));
    +};
    +Mongoose.prototype.disconnect.$hasSideEffects = true;

    Mongoose#Document()

    The Mongoose Document constructor.


    Mongoose#DocumentProvider()

    The Mongoose DocumentProvider constructor.


    Mongoose#get(key)

    Gets mongoose options

    Parameters:

    Example:

    - return this.models[name]; -};

    Parameters:

    • name <String> model name
    • [schema] <Schema>
    • [collection] <String> name (optional, induced from model name)
    • [skipInit] <Boolean> whether to skip initialization (defaults to false)

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    +
    mongoose.get('test') // returns the 'test' value

    Mongoose#getPromiseConstructor()

    Returns the current ES6-style promise constructor. In Mongoose 4.x,
    equivalent to mongoose.Promise.ES6, but will change once we get rid
    of the .ES6 bit.


    Mongoose#model(name, [schema], [collection], [skipInit])

    Defines a model or retrieves it.

    Parameters:

    • name <String, Function> model name or class extending Model
    • [schema] <Schema>
    • [collection] <String> name (optional, inferred from model name)
    • [skipInit] <Boolean> whether to skip initialization (defaults to false)

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    Example:

    @@ -390,6484 +170,10800 @@

    Example:

    // retrieve the Actor model var Actor = conn.model('Actor');
    -

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    +

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    Example:

    -
    var schema = new Schema({ name: String });
    -schema.set('collection', 'actor');

    Mongoose#plugin(fn, [opts])

    Declares a global plugin executed on all Schemas.

    show code
    Mongoose.prototype.plugin = function (fn, opts) {
    -  this.plugins.push([fn, opts]);
    -  return this;
    -};

    Parameters:

    Returns:

    Equivalent to calling .plugin(fn) on each Schema you create.


    module.exports

    The exports object is an instance of Mongoose.

    show code
    module.exports = exports = new Mongoose;
    -var mongoose = module.exports;

    mongoose.Collection

    The Mongoose Collection constructor

    show code
    mongoose.Collection = Collection;

    mongoose.Connection

    The Mongoose Connection constructor

    show code
    mongoose.Connection = Connection;

    mongoose.version

    Mongoose version

    show code
    mongoose.version = JSON.parse(
    -  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
    -).version;

    mongoose.Mongoose

    The Mongoose constructor

    show code
    mongoose.Mongoose = Mongoose;

    The exports of the mongoose module is an instance of this class.

    +
    var schema = new Schema({ name: String }, { collection: 'actor' });
     
    -

    Example:

    +// or -
    var mongoose = require('mongoose');
    -var mongoose2 = new mongoose.Mongoose();

    mongoose.Schema

    The Mongoose Schema constructor

    show code
    mongoose.Schema = Schema;

    Example:

    +schema.set('collection', 'actor'); -
    var mongoose = require('mongoose');
    -var Schema = mongoose.Schema;
    -var CatSchema = new Schema(..);

    mongoose.SchemaType

    The Mongoose SchemaType constructor.

    show code
    mongoose.SchemaType = SchemaType;

    mongoose.SchemaTypes

    The various Mongoose SchemaTypes.

    show code
    mongoose.SchemaTypes = Schema.Types;

    Note:

    +// or -

    Alias of mongoose.Schema.Types for backwards compatibility.


    mongoose.VirtualType

    The Mongoose VirtualType constructor.

    show code
    mongoose.VirtualType = VirtualType;

    mongoose.Types

    The various Mongoose Types.

    show code
    mongoose.Types = Types;

    Example:

    +var collectionName = 'actor' +var M = mongoose.model('Actor', schema, collectionName)
    show code
    Mongoose.prototype.model = function(name, schema, collection, skipInit) {
    +  var model;
    +  if (typeof name === 'function') {
    +    model = name;
    +    name = model.name;
    +    if (!(model.prototype instanceof Model)) {
    +      throw new mongoose.Error('The provided class ' + name + ' must extend Model');
    +    }
    +  }
     
    -
    var mongoose = require('mongoose');
    -var array = mongoose.Types.Array;
    + if (typeof schema === 'string') { + collection = schema; + schema = false; + } -

    Types:

    + if (utils.isObject(schema) && !(schema.instanceOfSchema)) { + schema = new Schema(schema); + } + if (schema && !schema.instanceOfSchema) { + throw new Error('The 2nd parameter to `mongoose.model()` should be a ' + + 'schema or a POJO'); + } -
      -
    • Array
    • -
    • Buffer
    • -
    • Document
    • -
    • Embedded
    • -
    • DocumentArray
    • -
    • ObjectId
    • -
    + if (typeof collection === 'boolean') { + skipInit = collection; + collection = null; + } -

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    + // handle internal options from connection.model() + var options; + if (skipInit && utils.isObject(skipInit)) { + options = skipInit; + skipInit = true; + } else { + options = {}; + } -
    var ObjectId = mongoose.Types.ObjectId;
    -var id1 = new ObjectId;

    mongoose.Query

    The Mongoose Query constructor.

    show code
    mongoose.Query = Query;

    mongoose.Promise

    The Mongoose Promise constructor.

    show code
    mongoose.Promise = Promise;

    mongoose.Model

    The Mongoose Model constructor.

    show code
    mongoose.Model = Model;

    mongoose.Document

    The Mongoose Document constructor.

    show code
    mongoose.Document = Document;

    mongoose.Error

    The MongooseError constructor.

    show code
    mongoose.Error = require('./error');

    mongoose.mongo

    The node-mongodb-native driver Mongoose uses.

    show code
    mongoose.mongo = require('mongodb');

    Mongoose#connection

    The default connection of the mongoose module.

    + // look up schema for the collection. + if (!this.modelSchemas[name]) { + if (schema) { + // cache it so we only apply plugins once + this.modelSchemas[name] = schema; + } else { + throw new mongoose.Error.MissingSchemaError(name); + } + } -

    Example:

    + if (schema) { + this._applyPlugins(schema); + } -
    var mongoose = require('mongoose');
    -mongoose.connect(...);
    -mongoose.connection.on('error', cb);
    + var sub; -

    This is the connection used by default for every model created using mongoose.model.

    Returns:


  • collection.js

    Collection(name, conn, opts)

    Abstract Collection constructor

    show code
    function Collection (name, conn, opts) {
    -  this.name = name;
    -  this.conn = conn;
    -  this.buffer = true;
    -  this.queue = [];
    +  // connection.model() may be passing a different schema for
    +  // an existing model name. in this case don't read from cache.
    +  if (this.models[name] && options.cache !== false) {
    +    if (schema && schema.instanceOfSchema && schema !== this.models[name].schema) {
    +      throw new mongoose.Error.OverwriteModelError(name);
    +    }
     
    -  if ('number' == typeof opts) opts = { size: opts };
    -  this.opts = opts || {};
    +    if (collection) {
    +      // subclass current model with alternate collection
    +      model = this.models[name];
    +      schema = model.prototype.schema;
    +      sub = model.__subclass(this.connection, schema, collection);
    +      // do not cache the sub model
    +      return sub;
    +    }
     
    -  if (STATES.connected == this.conn.readyState) {
    -    this.onOpen();
    -  }
    -};

    Parameters:

    • name <String> name of the collection
    • conn <Connection> A MongooseConnection instance
    • opts <Object> optional collection options

    This is the base class that drivers inherit from and implement.


    Collection#onOpen()

    Called when the database connects

    show code
    Collection.prototype.onOpen = function () {
    -  var self = this;
    -  this.buffer = false;
    -  self.doQueue();
    -};

    Collection#onClose()

    Called when the database disconnects

    show code
    Collection.prototype.onClose = function () {
    -  this.buffer = true;
    -};

    Collection#addQueue(name, args)

    Queues a method for later execution when its
    database connection opens.

    show code
    Collection.prototype.addQueue = function (name, args) {
    -  this.queue.push([name, args]);
    -  return this;
    -};

    Parameters:

    • name <String> name of the method to queue
    • args <Array> arguments to pass to the method when executed

    Collection#doQueue()

    Executes all queued methods and clears the queue.

    show code
    Collection.prototype.doQueue = function () {
    -  for (var i = 0, l = this.queue.length; i < l; i++){
    -    this[this.queue[i][0]].apply(this, this.queue[i][1]);
    +    return this.models[name];
       }
    -  this.queue = [];
    -  return this;
    -};

    Collection#ensureIndex()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.ensureIndex = function(){
    -  throw new Error('Collection#ensureIndex unimplemented by driver');
    -};

    Collection#findAndModify()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findAndModify = function(){
    -  throw new Error('Collection#findAndModify unimplemented by driver');
    -};

    Collection#findOne()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findOne = function(){
    -  throw new Error('Collection#findOne unimplemented by driver');
    -};

    Collection#find()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.find = function(){
    -  throw new Error('Collection#find unimplemented by driver');
    -};

    Collection#insert()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.insert = function(){
    -  throw new Error('Collection#insert unimplemented by driver');
    -};

    Collection#save()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.save = function(){
    -  throw new Error('Collection#save unimplemented by driver');
    -};

    Collection#update()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.update = function(){
    -  throw new Error('Collection#update unimplemented by driver');
    -};

    Collection#getIndexes()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.getIndexes = function(){
    -  throw new Error('Collection#getIndexes unimplemented by driver');
    -};

    Collection#mapReduce()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.mapReduce = function(){
    -  throw new Error('Collection#mapReduce unimplemented by driver');
    -};

    Collection#conn

    The Connection instance


    Collection#name

    The collection name


  • connection.js

    Connection(base)

    Connection constructor

    show code
    function Connection (base) {
    -  this.base = base;
    -  this.collections = {};
    -  this.models = {};
    -  this.replica = false;
    -  this.host = null;
    -  this.port = null;
    -  this.user = null;
    -  this.pass = null;
    -  this.name = null;
    -  this.options = null;
    -  this._readyState = STATES.disconnected;
    -  this._closeCalled = false;
    -  this._hasOpened = false;
    -};

    Parameters:

    Events:

    • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

    • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

    • open: Emitted after we connected and onOpen is executed on all of this connections models.

    • disconnecting: Emitted when connection.close() was executed.

    • disconnected: Emitted after getting disconnected from the db.

    • close: Emitted after we disconnected and onClose executed on all of this connections models.

    • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

    • error: Emitted when an error occurs on this connection.

    • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

    For practical reasons, a Connection equals a Db.


    Connection#open(connection_string, [database], [port], [options], [callback])

    Opens the connection to MongoDB.

    show code
    Connection.prototype.open = function (host, database, port, options, callback) {
    -  var self = this
    -    , uri;
    -
    -  if ('string' === typeof database) {
    -    switch (arguments.length) {
    -      case 2:
    -        port = 27017;
    -      case 3:
    -        switch (typeof port) {
    -          case 'function':
    -            callback = port, port = 27017;
    -            break;
    -          case 'object':
    -            options = port, port = 27017;
    -            break;
    -        }
    -        break;
    -      case 4:
    -        if ('function' === typeof options)
    -          callback = options, options = {};
    -    }
    -  } else {
    -    switch (typeof database) {
    -      case 'function':
    -        callback = database, database = undefined;
    -        break;
    -      case 'object':
    -        options = database;
    -        database = undefined;
    -        callback = port;
    -        break;
    -    }
     
    -    if (!rgxProtocol.test(host)) {
    -      host = 'mongodb://' + host;
    +  // ensure a schema exists
    +  if (!schema) {
    +    schema = this.modelSchemas[name];
    +    if (!schema) {
    +      throw new mongoose.Error.MissingSchemaError(name);
         }
    -
    -    uri = url.parse(host);
    -    host = uri.hostname;
    -    port = uri.port || 27017;
    -    database = uri.pathname && uri.pathname.replace(/\//g, '');
       }
     
    -  this.options = this.defaultOptions(options);
    +  // Apply relevant "global" options to the schema
    +  if (!('pluralization' in schema.options)) schema.options.pluralization = this.options.pluralization;
     
    -  // make sure we can open
    -  if (STATES.disconnected !== this.readyState) {
    -    var err = new Error('Trying to open unclosed connection.');
    -    err.state = this.readyState;
    -    this.error(err, callback);
    -    return this;
    +
    +  if (!collection) {
    +    collection = schema.get('collection') || format(name, schema.options);
       }
     
    -  if (!host) {
    -    this.error(new Error('Missing hostname.'), callback);
    -    return this;
    +  var connection = options.connection || this.connection;
    +  model = this.Model.compile(model || name, schema, collection, connection, this);
    +
    +  if (!skipInit) {
    +    model.init();
       }
     
    -  if (!database) {
    -    this.error(new Error('Missing database name.'), callback);
    -    return this;
    +  if (options.cache === false) {
    +    return model;
       }
     
    -  // handle authentication
    -  if (uri && uri.auth) {
    -    var auth = uri.auth.split(':');
    -    this.user = auth[0];
    -    this.pass = auth[1];
    +  this.models[name] = model;
    +  return this.models[name];
    +};
    +Mongoose.prototype.model.$hasSideEffects = true;

    Mongoose#Model()

    The Mongoose Model constructor.


    Mongoose#modelNames()

    Returns an array of model names created on this instance of Mongoose.

    Returns:

    Note:

    - // Check hostname for user/pass - } else if (/@/.test(host) && /:/.test(host.split('@')[0])) { - host = host.split('@'); - var auth = host.shift().split(':'); - host = host.pop(); - this.user = auth[0]; - this.pass = auth[1]; +

    Does not include names of models created using connection.model().

    show code
    Mongoose.prototype.modelNames = function() {
    +  var names = Object.keys(this.models);
    +  return names;
    +};
    +Mongoose.prototype.modelNames.$hasSideEffects = true;

    Mongoose()

    Mongoose constructor.

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    show code
    function Mongoose() {
    +  this.connections = [];
    +  this.models = {};
    +  this.modelSchemas = {};
    +  // default global options
    +  this.options = {
    +    pluralization: true
    +  };
    +  var conn = this.createConnection(); // default connection
    +  conn.models = this.models;
    +
    +  Object.defineProperty(this, 'plugins', {
    +    configurable: false,
    +    enumerable: true,
    +    writable: false,
    +    value: [
    +      [saveSubdocs, { deduplicate: true }],
    +      [validateBeforeSave, { deduplicate: true }],
    +      [shardingPlugin, { deduplicate: true }]
    +    ]
    +  });
    +}

    Mongoose#Mongoose()

    The Mongoose constructor

    The exports of the mongoose module is an instance of this class.

    - // user/pass options - } else if (options && options.user && options.pass) { - this.user = options.user; - this.pass = options.pass; +

    Example:

    - } else { - this.user = this.pass = undefined; +
    var mongoose = require('mongoose');
    +var mongoose2 = new mongoose.Mongoose();

    MongooseThenable()

    Wraps the given Mongoose instance into a thenable (pseudo-promise). This
    is so connect() and disconnect() can return a thenable while maintaining
    backwards compatibility.

    show code
    function MongooseThenable(mongoose, promise) {
    +  var _this = this;
    +  for (var key in mongoose) {
    +    if (typeof mongoose[key] === 'function' && mongoose[key].$hasSideEffects) {
    +      (function(key) {
    +        _this[key] = function() {
    +          return mongoose[key].apply(mongoose, arguments);
    +        };
    +      })(key);
    +    } else if (['connection', 'connections'].indexOf(key) !== -1) {
    +      _this[key] = mongoose[key];
    +    }
       }
    +  this.$opPromise = promise;
    +}
     
    -  this.name = database;
    -  this.host = host;
    -  this.port = port;
    -
    -  this._open(callback);
    +MongooseThenable.prototype = new Mongoose;

    Mongoose#plugin(fn, [opts])

    Declares a global plugin executed on all Schemas.

    Parameters:

    Returns:

    Equivalent to calling .plugin(fn) on each Schema you create.

    show code
    Mongoose.prototype.plugin = function(fn, opts) {
    +  this.plugins.push([fn, opts]);
       return this;
    -};

    Parameters:

    • connection_string <String> mongodb://uri or the host to which you are connecting
    • [database] <String> database name
    • [port] <Number> database port
    • [options] <Object> options
    • [callback] <Function>

    options is a hash with the following possible properties:

    - -
    db      - passed to the connection db instance
    -server  - passed to the connection server instance(s)
    -replset - passed to the connection ReplSet instance
    -user    - username for authentication
    -pass    - password for authentication
    +}; +Mongoose.prototype.plugin.$hasSideEffects = true;

  • Mongoose#PromiseProvider()

    Storage layer for mongoose promises


    Mongoose#Query()

    The Mongoose Query constructor.


    Mongoose#Schema()

    The Mongoose Schema constructor

    Example:

    -

    Notes:

    +
    var mongoose = require('mongoose');
    +var Schema = mongoose.Schema;
    +var CatSchema = new Schema(..);

    Mongoose#SchemaType()

    The Mongoose SchemaType constructor


    Mongoose#set(key, value)

    Sets mongoose options

    Parameters:

    Example:

    -

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.


    Connection#openSet(uris, [database], [options], [callback])

    Connects to a replica set.

    show code
    Connection.prototype.openSet = function (uris, database, options, callback) {
    -  var uris = uris.split(',')
    -    , self = this;
    +
    mongoose.set('test', value) // sets the 'test' option to `value`
     
    -  switch (arguments.length) {
    -    case 3:
    -      switch (typeof database) {
    -        case 'string':
    -          this.name = database;
    -          break;
    -        case 'object':
    -          callback = options;
    -          options = database;
    -          database = null;
    -          break;
    -      }
    +mongoose.set('debug', true) // enable logging collection methods + arguments to the console
     
    -      if ('function' === typeof options) {
    -        callback = options;
    -        options = {};
    -      }
    -      break;
    -    case 2:
    -      switch (typeof database) {
    -        case 'string':
    -          this.name = database;
    -          break;
    -        case 'function':
    -          callback = database, database = null;
    -          break;
    -        case 'object':
    -          options = database, database = null;
    -          break;
    -      }
    +mongoose.set('debug', function(collectionName, methodName, arg1, arg2...) {}); // use custom function to log collection methods + arguments
    show code
    Mongoose.prototype.set = function(key, value) {
    +  if (arguments.length === 1) {
    +    return this.options[key];
       }
     
    -  this.options = options = this.defaultOptions(options);
    +  this.options[key] = value;
    +  return this;
    +};
    +Mongoose.prototype.set.$hasSideEffects = true;

    ()

    Expose connection states for user-land

    show code
    Mongoose.prototype.STATES = STATES;

    MongooseThenable#then(onFulfilled, onRejected)

    Ability to use mongoose object as a pseudo-promise so .connect().then()
    and .disconnect().then() are viable.

    Parameters:

    Returns:

    show code
    MongooseThenable.prototype.then = function(onFulfilled, onRejected) {
    +  var Promise = PromiseProvider.get();
    +  if (!this.$opPromise) {
    +    return new Promise.ES6(function(resolve, reject) {
    +      reject(new Error('Can only call `.then()` if connect() or disconnect() ' +
    +        'has been called'));
    +    }).then(onFulfilled, onRejected);
    +  }
    +  this.$opPromise.$hasHandler = true;
    +  return this.$opPromise.then(onFulfilled, onRejected);
    +};

    Mongoose#VirtualType()

    The Mongoose VirtualType constructor


    Mongoose#connection

    The default connection of the mongoose module.

    - if (uris.length < 2) { - this.error(new Error('Please provide comma-separated URIs'), callback); - return this; - } +

    Example:

    - this.replica = true; - this.host = []; - this.port = []; +
    var mongoose = require('mongoose');
    +mongoose.connect(...);
    +mongoose.connection.on('error', cb);
    - uris.forEach(function (uri) { - // handle missing protocols - if (!rgxProtocol.test(uri)) - uri = 'mongodb://' + uri; +

    This is the connection used by default for every model created using mongoose.model.

    show code
    Mongoose.prototype.__defineGetter__('connection', function() {
    +  return this.connections[0];
    +});
     
    -    var uri = url.parse(uri);
    +Mongoose.prototype.__defineSetter__('connection', function(v) {
    +  this.connections[0] = v;
    +});

    Returns:


    Mongoose#mongo

    The node-mongodb-native driver Mongoose uses.

    show code
    Mongoose.prototype.mongo = require('mongodb');

    Mongoose#mquery

    The mquery query builder Mongoose uses.

    show code
    Mongoose.prototype.mquery = require('mquery');

    Mongoose#SchemaTypes

    The various Mongoose SchemaTypes.

    - self.host.push(uri.hostname); - self.port.push(uri.port || 27017); +

    Note:

    - if (!self.name && uri.pathname && uri.pathname.replace(/\//g, '')) - self.name = uri.pathname.replace(/\//g, ''); +

    Alias of mongoose.Schema.Types for backwards compatibility.

    show code
    Mongoose.prototype.SchemaTypes = Schema.Types;

    Mongoose#Types

    The various Mongoose Types.

    - if (!self.user && uri.auth) { - var auth = uri.auth.split(':'); - self.user = auth[0]; - self.pass = auth[1]; - } - }); +

    Example:

    - if (!this.name) { - this.error(new Error('No database name provided for replica set'), callback); - return this; - } +
    var mongoose = require('mongoose');
    +var array = mongoose.Types.Array;
    - this._open(callback); - return this; -};

    Parameters:

    • uris <String> comma-separated mongodb:// `URI`s
    • [database] <String> database name if not included in `uris`
    • [options] <Object> passed to the internal driver
    • [callback] <Function>

    Example:

    +

    Types:

    -
    var db = mongoose.createConnection();
    -db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
    + -

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    +

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    -

    Valid options

    - -
    db      - passed to the connection db instance
    -server  - passed to the connection server instance(s)
    -replset - passed to the connection ReplSetServer instance
    -user    - username for authentication
    -pass    - password for authentication

    Connection#error(err, callback)

    error

    show code
    Connection.prototype.error = function (err, callback) {
    -  if (callback) return callback(err);
    -  this.emit('error', err);
    -}

    Parameters:

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.


    Connection#_open(callback)

    Handles opening the connection with the appropriate method based on connection type.

    show code
    Connection.prototype._open = function (callback) {
    -  this.readyState = STATES.connecting;
    -  this._closeCalled = false;
    -
    -  var self = this;
    -
    -  var method = this.replica
    -    ? 'doOpenSet'
    -    : 'doOpen';
    +
    var ObjectId = mongoose.Types.ObjectId;
    +var id1 = new ObjectId;
    show code
    Mongoose.prototype.Types = Types;

    Mongoose#version

    The Mongoose version

    show code
    Mongoose.prototype.version = pkg.version;

  • querystream.js

    QueryStream#__next()

    Pulls the next doc from the cursor.

    show code
    QueryStream.prototype.__next = function() {
    +  if (this.paused || this._destroyed) {
    +    this._running = false;
    +    return this._running;
    +  }
     
    -  // open connection
    -  this[method](function (err) {
    -    if (err) {
    -      self.readyState = STATES.disconnected;
    -      if (self._hasOpened) {
    -        if (callback) callback(err);
    -      } else {
    -        self.error(err, callback);
    -      }
    -      return;
    -    }
    +  var _this = this;
    +  _this._inline = T_INIT;
     
    -    self.onOpen();
    -    callback && callback();
    +  _this._cursor.nextObject(function cursorcb(err, doc) {
    +    _this._onNextObject(err, doc);
       });
    -}

    Parameters:


    Connection#onOpen()

    Called when the connection is opened

    show code
    Connection.prototype.onOpen = function () {
    -  var self = this;
     
    -  function open () {
    -    self.readyState = STATES.connected;
    +  // if onNextObject() was already called in this tick
    +  // return ourselves to the trampoline.
    +  if (T_CONT === this._inline) {
    +    return true;
    +  }
    +  // onNextObject() hasn't fired yet. tell onNextObject
    +  // that its ok to call _next b/c we are not within
    +  // the trampoline anymore.
    +  this._inline = T_IDLE;
    +};

    QueryStream#_init()

    Initializes the query.

    show code
    QueryStream.prototype._init = function() {
    +  if (this._destroyed) {
    +    return;
    +  }
     
    -    // avoid having the collection subscribe to our event emitter
    -    // to prevent 0.3 warning
    -    for (var i in self.collections)
    -      self.collections[i].onOpen();
    +  var query = this.query,
    +      model = query.model,
    +      options = query._optionsForExec(model),
    +      _this = this;
     
    -    self.emit('open');
    -  };
    +  try {
    +    query.cast(model);
    +  } catch (err) {
    +    return _this.destroy(err);
    +  }
     
    -  // re-authenticate
    -  if (self.user && self.pass)
    -    self.db.authenticate(self.user, self.pass, open);
    -  else
    -    open();
    -};

    Connection#close([callback])

    Closes the connection

    show code
    Connection.prototype.close = function (callback) {
    -  var self = this;
    -  this._closeCalled = true;
    +  _this._fields = utils.clone(query._fields);
    +  options.fields = query._castFields(_this._fields);
     
    -  switch (this.readyState){
    -    case 0: // disconnected
    -      callback && callback();
    -      break;
    +  model.collection.find(query._conditions, options, function(err, cursor) {
    +    if (err) {
    +      return _this.destroy(err);
    +    }
    +    _this._cursor = cursor;
    +    _this._next();
    +  });
    +};

    QueryStream#_next()

    Trampoline for pulling the next doc from cursor.

    show code
    QueryStream.prototype._next = function _next() {
    +  if (this.paused || this._destroyed) {
    +    this._running = false;
    +    return this._running;
    +  }
     
    -    case 1: // connected
    -      this.readyState = STATES.disconnecting;
    -      this.doClose(function(err){
    -        if (err){
    -          self.error(err, callback);
    -        } else {
    -          self.onClose();
    -          callback && callback();
    -        }
    -      });
    -      break;
    +  this._running = true;
     
    -    case 2: // connecting
    -      this.once('open', function(){
    -        self.close(callback);
    -      });
    -      break;
    +  if (this._buffer && this._buffer.length) {
    +    var arg;
    +    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) { // eslint-disable-line no-cond-assign
    +      this._onNextObject.apply(this, arg);
    +    }
    +  }
     
    -    case 3: // disconnecting
    -      if (!callback) break;
    -      this.once('close', function () {
    -        callback();
    -      });
    -      break;
    +  // avoid stack overflows with large result sets.
    +  // trampoline instead of recursion.
    +  while (this.__next()) {
    +  }
    +};

    QueryStream#_onNextObject(err, doc)

    Transforms raw docs returned from the cursor into a model instance.

    Parameters:

    show code
    QueryStream.prototype._onNextObject = function _onNextObject(err, doc) {
    +  if (this._destroyed) {
    +    return;
       }
     
    -  return this;
    -};

    Parameters:

    Returns:


    Connection#onClose()

    Called when the connection closes

    show code
    Connection.prototype.onClose = function () {
    -  this.readyState = STATES.disconnected;
    +  if (this.paused) {
    +    this._buffer || (this._buffer = []);
    +    this._buffer.push([err, doc]);
    +    this._running = false;
    +    return this._running;
    +  }
     
    -  // avoid having the collection subscribe to our event emitter
    -  // to prevent 0.3 warning
    -  for (var i in this.collections)
    -    this.collections[i].onClose();
    +  if (err) {
    +    return this.destroy(err);
    +  }
     
    -  this.emit('close');
    -};

    Connection#collection(name, [options])

    Retrieves a collection, creating it if not cached.

    show code
    Connection.prototype.collection = function (name, options) {
    -  if (!(name in this.collections))
    -    this.collections[name] = new Collection(name, this, options);
    -  return this.collections[name];
    -};

    Parameters:

    • name <String> of the collection
    • [options] <Object> optional collection options

    Returns:


    Connection#model(name, [schema], [collection])

    Defines or retrieves a model.

    show code
    Connection.prototype.model = function (name, schema, collection) {
    -  if (!this.models[name]) {
    -    var model = this.base.model(name, schema, collection, true)
    -      , Model
    -
    -    if (this != model.prototype.db) {
    -      // subclass model using this connection and collection name
    -      Model = function Model (doc, fields, skipId) {
    -        if (!(this instanceof Model))
    -          return new Model(doc, fields, skipId);
    -        model.call(this, doc, fields, skipId);
    -      };
    +  // when doc is null we hit the end of the cursor
    +  if (!doc) {
    +    this.emit('end');
    +    return this.destroy();
    +  }
     
    -      Model.__proto__ = model;
    -      Model.prototype.__proto__ = model.prototype;
    -      Model.db = Model.prototype.db = this;
    +  var opts = this.query._mongooseOptions;
     
    -      // collection name discovery
    -      if ('string' === typeof schema) {
    -        collection = schema;
    -      }
    +  if (!opts.populate) {
    +    return opts.lean === true ?
    +        emit(this, doc) :
    +        createAndEmit(this, null, doc);
    +  }
     
    -      if (!collection) {
    -        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
    -      }
    +  var _this = this;
    +  var pop = helpers.preparePopulationOptionsMQ(_this.query, _this.query._mongooseOptions);
     
    -      var s = 'string' != typeof schema
    -        ? schema
    -        : model.prototype.schema;
    +  // Hack to work around gh-3108
    +  pop.forEach(function(option) {
    +    delete option.model;
    +  });
     
    -      Model.prototype.collection = this.collection(collection, s && s.options.capped);
    -      Model.collection = Model.prototype.collection;
    -      Model.init();
    +  pop.__noPromise = true;
    +  _this.query.model.populate(doc, pop, function(err, doc) {
    +    if (err) {
    +      return _this.destroy(err);
         }
    +    return opts.lean === true ?
    +        emit(_this, doc) :
    +        createAndEmit(_this, pop, doc);
    +  });
    +};
     
    -    this.models[name] = Model || model;
    -  }
    +function createAndEmit(self, populatedIds, doc) {
    +  var instance = helpers.createModel(self.query.model, doc, self._fields);
    +  var opts = populatedIds ?
    +    {populated: populatedIds} :
    +    undefined;
     
    -  return this.models[name];
    -};

    Parameters:

    • name <String> the model name
    • [schema] <Schema> a schema. necessary when defining a model
    • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

    Returns:

    • <Model> The compiled model
    var mongoose = require('mongoose');
    -var db = mongoose.createConnection(..);
    -db.model('Venue', new Schema(..));
    -var Ticket = db.model('Ticket', new Schema(..));
    -var Venue = db.model('Venue');

    Connection#setProfiling(level, [ms], callback)

    Set profiling level.

    show code
    Connection.prototype.setProfiling = function (level, ms, callback) {
    -  if (STATES.connected !== this.readyState) {
    -    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
    +  instance.init(doc, opts, function(err) {
    +    if (err) {
    +      return self.destroy(err);
    +    }
    +    emit(self, instance);
    +  });
    +}

    QueryStream#destroy([err])

    Destroys the stream, closing the underlying cursor, which emits the close event. No more events will be emitted after the close event.

    Parameters:

    show code
    QueryStream.prototype.destroy = function(err) {
    +  if (this._destroyed) {
    +    return;
       }
    +  this._destroyed = true;
    +  this._running = false;
    +  this.readable = false;
     
    -  if (!callback) callback = ms, ms = 100;
    -
    -  var cmd = {};
    +  if (this._cursor) {
    +    this._cursor.close();
    +  }
     
    -  switch (level) {
    -    case 0:
    -    case 'off':
    -      cmd.profile = 0;
    -      break;
    -    case 1:
    -    case 'slow':
    -      cmd.profile = 1;
    -      if ('number' !== typeof ms) {
    -        ms = parseInt(ms, 10);
    -        if (isNaN(ms)) ms = 100;
    -      }
    -      cmd.slowms = ms;
    -      break;
    -    case 2:
    -    case 'all':
    -      cmd.profile = 2;
    -      break;
    -    default:
    -      return callback(new Error('Invalid profiling level: '+ level));
    +  if (err) {
    +    this.emit('error', err);
       }
     
    -  this.db.executeDbCommand(cmd, function (err, resp) {
    -    if (err) return callback(err);
    +  this.emit('close');
    +};

    QueryStream#pause()

    Pauses this stream.

    show code
    QueryStream.prototype.pause = function() {
    +  this.paused = true;
    +};

    QueryStream#pipe()

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    See:

    Example:

    - var doc = resp.documents[0]; +
    query.stream().pipe(writeStream [, options])

    QueryStream(query, [options])

    Provides a Node.js 0.8 style ReadStream interface for Queries.

    Parameters:

    Inherits:

    Events:

    • data: emits a single Mongoose document

    • error: emits when an error occurs during streaming. This will emit before the close event.

    • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

    var stream = Model.find().stream();
     
    -    err = 1 === doc.ok
    -      ? null
    -      : new Error('Could not set profiling level to: '+ level)
    +stream.on('data', function (doc) {
    +  // do something with the mongoose document
    +}).on('error', function (err) {
    +  // handle the error
    +}).on('close', function () {
    +  // the stream is closed
    +});
    - callback(err, doc); - }); -};
  • Parameters:

    • level <Number, String> either off (0), slow (1), or all (2)
    • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
    • callback <Function>

    Connection#defaultOptions(options)

    Prepares default connection options.

    show code
    Connection.prototype.defaultOptions = function (options) {
    -  var o = options || {};
    +

    The stream interface allows us to simply "plug-in" to other Node.js 0.8 style write streams.

    - o.server = o.server || {}; +
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);
    - if (!('auto_reconnect' in o.server)) { - o.server.auto_reconnect = true; - } +

    Valid options

    - o.db || (o.db = {}); - o.db.forceServerObjectId = false; +
      +
    • transform: optional function which accepts a mongoose document. The return value of the function will be emitted on data.
    • +
    - // TODO default to true once the driver is fixed - if (!('safe' in o.db)) o.db.safe = false; +

    Example

    - return o; -}

    Parameters:


    Connection#db

    The mongodb.Db instance, set when the connection is opened


    Connection#collections

    A hash of the collections associated with this connection


    Connection#readyState

    Connection ready state

    +
    // JSON.stringify all documents before emitting
    +var stream = Thing.find().stream({ transform: JSON.stringify });
    +stream.pipe(writeStream);
    -
      -
    • 0 = disconnected
    • -
    • 1 = connected
    • -
    • 2 = connecting
    • -
    • 3 = disconnecting
    • -
    +

    NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary.

    -

    Each state change emits its associated event name.

    +

    NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work.

    show code
    function QueryStream(query, options) {
    +  Stream.call(this);
     
    -

    Example

    + this.query = query; + this.readable = true; + this.paused = false; + this._cursor = null; + this._destroyed = null; + this._fields = null; + this._buffer = null; + this._inline = T_INIT; + this._running = false; + this._transform = options && typeof options.transform === 'function' + ? options.transform + : K; -
    conn.on('connected', callback);
    -conn.on('disconnected', callback);

  • document.js

    Document(obj, [fields], [skipId])

    Document constructor.

    show code
    function Document (obj, fields, skipId) {
    -  // node <0.4.3 bug
    -  if (!this._events) this._events = {};
    -  this.setMaxListeners(0);
    -
    -  if ('boolean' === typeof fields) {
    -    this._strictMode = fields;
    -    this._selected = fields = undefined;
    -  } else {
    -    this._strictMode = this.schema.options && this.schema.options.strict;
    -    this._selected = fields;
    -  }
    +  // give time to hook up events
    +  var _this = this;
    +  process.nextTick(function() {
    +    _this._init();
    +  });
    +}

    QueryStream#resume()

    Resumes this stream.

    show code
    QueryStream.prototype.resume = function() {
    +  this.paused = false;
     
    -  this.isNew = true;
    -  this.errors = undefined;
    -  this._shardval = undefined;
    -  this._saveError = undefined;
    -  this._validationError = undefined;
    -  this._adhocPaths = undefined;
    -  this._removing = undefined;
    -  this._inserting = undefined;
    -  this.__version = undefined;
    -  this.__getters = {};
    -  this.__id = undefined;
    -
    -  this._activePaths = new ActiveRoster;
    +  if (!this._cursor) {
    +    // cannot start if not initialized
    +    return;
    +  }
     
    -  var required = this.schema.requiredPaths();
    -  for (var i = 0; i < required.length; ++i) {
    -    this._activePaths.require(required[i]);
    -  }
    -
    -  this._doc = this._buildDoc(obj, fields, skipId);
    -  if (obj) this.set(obj, undefined, true);
    -  this._registerHooks();
    -};

    Parameters:

    • obj <Object> the values to set
    • [fields] <Object> the fields which were selected in the query returning this document
    • [skipId] <Boolean> bool, should we auto create an ObjectId _id

    Events:

    • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

    • save: Emitted when the document is successfully saved


    Document#_buildDoc(obj, [fields], [skipId])

    Builds the default doc structure

    show code
    Document.prototype._buildDoc = function (obj, fields, skipId) {
    -  var doc = {}
    -    , self = this
    -    , exclude
    -    , keys
    -    , key
    -    , ki
    -
    -  // determine if this doc is a result of a query with
    -  // excluded fields
    -  if (fields && 'Object' === fields.constructor.name) {
    -    keys = Object.keys(fields);
    -    ki = keys.length;
    +  // are we within the trampoline?
    +  if (T_INIT === this._inline) {
    +    return;
    +  }
     
    -    while (ki--) {
    -      if ('_id' !== keys[ki]) {
    -        exclude = 0 === fields[keys[ki]];
    -        break;
    -      }
    -    }
    +  if (!this._running) {
    +    // outside QueryStream control, need manual restart
    +    return this._next();
       }
    +};

    QueryStream#paused

    Flag stating whether or not this stream is paused.

    show code
    QueryStream.prototype.paused;
    +
    +// trampoline flags
    +var T_INIT = 0;
    +var T_IDLE = 1;
    +var T_CONT = 2;

    QueryStream#readable

    Flag stating whether or not this stream is readable.

    show code
    QueryStream.prototype.readable;

  • connection.js

    Connection(base)

    Connection constructor

    Parameters:

    Events:

    • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

    • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

    • open: Emitted after we connected and onOpen is executed on all of this connections models.

    • disconnecting: Emitted when connection.close() was executed.

    • disconnected: Emitted after getting disconnected from the db.

    • close: Emitted after we disconnected and onClose executed on all of this connections models.

    • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

    • error: Emitted when an error occurs on this connection.

    • fullsetup: Emitted in a replica-set scenario, when primary and at least one seconaries specified in the connection string are connected.

    • all: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

    For practical reasons, a Connection equals a Db.

    show code
    function Connection(base) {
    +  this.base = base;
    +  this.collections = {};
    +  this.models = {};
    +  this.config = {autoIndex: true};
    +  this.replica = false;
    +  this.hosts = null;
    +  this.host = null;
    +  this.port = null;
    +  this.user = null;
    +  this.pass = null;
    +  this.name = null;
    +  this.options = null;
    +  this.otherDbs = [];
    +  this._readyState = STATES.disconnected;
    +  this._closeCalled = false;
    +  this._hasOpened = false;
    +}

    (connection_string, [database], [port], [options], [callback])

    Opens the connection to MongoDB.

    Parameters:

    • connection_string <String> mongodb://uri or the host to which you are connecting
    • [database] <String> database name
    • [port] <Number> database port
    • [options] <Object> options
    • [callback] <Function>

    options is a hash with the following possible properties:

    - var paths = Object.keys(this.schema.paths) - , plen = paths.length - , ii = 0 +
    config  - passed to the connection config instance
    +db      - passed to the connection db instance
    +server  - passed to the connection server instance(s)
    +replset - passed to the connection ReplSet instance
    +user    - username for authentication
    +pass    - password for authentication
    +auth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
    +
    - for (; ii < plen; ++ii) { - var p = paths[ii]; +

    Notes:

    - if ('_id' == p) { - if (skipId) continue; - if (obj && '_id' in obj) continue; - } +

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    - var type = this.schema.paths[p] - , path = p.split('.') - , len = path.length - , last = len-1 - , doc_ = doc - , i = 0 +

    Options passed take precedence over options included in connection strings.

    show code
    Connection.prototype.open = util.deprecate(function() {
    +  var Promise = PromiseProvider.get();
    +  var callback;
     
    -    for (; i < len; ++i) {
    -      var piece = path[i]
    -        , def
    +  try {
    +    callback = this._handleOpenArgs.apply(this, arguments);
    +  } catch (error) {
    +    return new Promise.ES6(function(resolve, reject) {
    +      reject(error);
    +    });
    +  }
     
    -      if (i === last) {
    -        if (fields) {
    -          if (exclude) {
    -            // apply defaults to all non-excluded fields
    -            if (p in fields) continue;
    +  var _this = this;
    +  var promise = new Promise.ES6(function(resolve, reject) {
    +    _this._open(true, function(error) {
    +      callback && callback(error);
    +      if (error) {
    +        // Error can be on same tick re: christkv/mongodb-core#157
    +        setImmediate(function() {
    +          reject(error);
    +          if (!callback && !promise.$hasHandler) {
    +            _this.emit('error', error);
    +          }
    +        });
    +        return;
    +      }
    +      resolve();
    +    });
    +  });
     
    -            def = type.getDefault(self, true);
    -            if ('undefined' !== typeof def) {
    -              doc_[piece] = def;
    -              self._activePaths.default(p);
    -            }
    +  // Monkey-patch `.then()` so if the promise is handled, we don't emit an
    +  // `error` event.
    +  var _then = promise.then;
    +  promise.then = function(resolve, reject) {
    +    promise.$hasHandler = true;
    +    return _then.call(promise, resolve, reject);
    +  };
     
    -          } else if (p in fields) {
    -            // selected field
    -            def = type.getDefault(self, true);
    -            if ('undefined' !== typeof def) {
    -              doc_[piece] = def;
    -              self._activePaths.default(p);
    -            }
    +  return promise;
    +}, '`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/connections.html#use-mongo-client');

    Connection#dropDatabase(callback)

    Helper for dropDatabase().

    Parameters:

    Returns:

    show code
    Connection.prototype.dropDatabase = function(callback) {
    +  var Promise = PromiseProvider.get();
    +  var _this = this;
    +  var promise = new Promise.ES6(function(resolve, reject) {
    +    if (_this.readyState !== STATES.connected) {
    +      _this.on('open', function() {
    +        _this.db.dropDatabase(function(error) {
    +          if (error) {
    +            reject(error);
    +          } else {
    +            resolve();
               }
    +        });
    +      });
    +    } else {
    +      _this.db.dropDatabase(function(error) {
    +        if (error) {
    +          reject(error);
             } else {
    -          def = type.getDefault(self, true);
    -          if ('undefined' !== typeof def) {
    -            doc_[piece] = def;
    -            self._activePaths.default(p);
    -          }
    +          resolve();
             }
    -      } else {
    -        doc_ = doc_[piece] || (doc_[piece] = {});
    -      }
    +      });
         }
    -  };
    +  });
    +  if (callback) {
    +    promise.then(function() { callback(); }, callback);
    +  }
    +  return promise;
    +};

    (uris, [database], [options], [callback])

    Opens the connection to a replica set.

    Parameters:

    • uris <String> MongoDB connection string
    • [database] <String> database name if not included in uris
    • [options] <Object> passed to the internal driver
    • [callback] <Function>

    Example:

    - return doc; -};
  • Parameters:

    Returns:


    Document#init(doc, fn)

    Initializes the document without setters or marking anything modified.

    show code
    Document.prototype.init = function (doc, fn) {
    -  this.isNew = false;
    +
    var db = mongoose.createConnection();
    +db.openSet("mongodb://user:pwd@localhost:27020,localhost:27021,localhost:27012/mydb");
    - init(this, doc, this._doc); - this._storeShard(); +

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    - this.emit('init'); - if (fn) fn(null); - return this; -};

    Parameters:

    Called internally after a document is returned from mongodb.


    Document#_storeShard()

    Stores the current values of the shard keys.

    show code
    Document.prototype._storeShard = function _storeShard () {
    -  // backwards compat
    -  var key = this.schema.options.shardKey || this.schema.options.shardkey;
    -  if (!(key && 'Object' == key.constructor.name)) return;
    +

    Valid options

    - var orig = this._shardval = {} - , paths = Object.keys(key) - , len = paths.length - , val +
    db      - passed to the connection db instance
    +server  - passed to the connection server instance(s)
    +replset - passed to the connection ReplSetServer instance
    +user    - username for authentication
    +pass    - password for authentication
    +auth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
    +mongos  - Boolean - if true, enables High Availability support for mongos
    +
    - for (var i = 0; i < len; ++i) { - val = this.getValue(paths[i]); - if (isMongooseObject(val)) { - orig[paths[i]] = val.toObject({ depopulate: true }) - } else if (null != val && val.valueOf) { - orig[paths[i]] = val.valueOf(); - } else { - orig[paths[i]] = val; - } - } -}

    Note:

    +

    Options passed take precedence over options included in connection strings.

    -

    Shard key values do not / are not allowed to change.


    Document#update(doc, options, callback)

    Sends an update command with this document _id as the query selector.

    show code
    Document.prototype.update = function update () {
    -  var args = utils.args(arguments);
    -  args.unshift({_id: this._id});
    -  this.constructor.update.apply(this.constructor, args);
    -}

    Parameters:

    Returns:

    Example:

    +

    Notes:

    -
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
    +

    If connecting to multiple mongos servers, set the mongos option to true.

    -

    Valid options:

    +
    conn.open('mongodb://mongosA:27501,mongosB:27501', { mongos: true }, cb);
    -
      -
    • safe safe mode (defaults to value set in schema (true))
    • -
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • -

    Document#set(path, val, [type], [options])

    Sets the value of a path, or many paths.

    show code
    Document.prototype.set = function (path, val, type, options) {
    -  if (type && 'Object' == type.constructor.name) {
    -    options = type;
    -    type = undefined;
    -  }
    +

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    - var merge = options && options.merge - , adhoc = type && true !== type - , constructing = true === type - , adhocs +

    Options passed take precedence over options included in connection strings.

    show code
    Connection.prototype.openSet = util.deprecate(function(uris, database, options, callback) {
    +  var Promise = PromiseProvider.get();
     
    -  if (adhoc) {
    -    adhocs = this._adhocPaths || (this._adhocPaths = {});
    -    adhocs[path] = Schema.interpretAsType(path, type);
    +  try {
    +    callback = this._handleOpenSetArgs.apply(this, arguments);
    +  } catch (err) {
    +    return new Promise.ES6(function(resolve, reject) {
    +      reject(err);
    +    });
       }
     
    -  if ('string' !== typeof path) {
    -    // new Document({ key: val })
    +  var _this = this;
    +  var emitted = false;
    +  var promise = new Promise.ES6(function(resolve, reject) {
    +    _this._open(true, function(error) {
    +      callback && callback(error);
    +      if (error) {
    +        reject(error);
    +        if (!callback && !promise.$hasHandler && !emitted) {
    +          emitted = true;
    +          _this.emit('error', error);
    +        }
    +        return;
    +      }
    +      resolve();
    +    });
    +  });
     
    -    if (null === path || undefined === path) {
    -      var _ = path;
    -      path = val;
    -      val = _;
    -
    -    } else {
    -      var prefix = val
    -        ? val + '.'
    -        : '';
    -
    -      if (path instanceof Document) path = path._doc;
    -
    -      var keys = Object.keys(path)
    -        , i = keys.length
    -        , pathtype
    -        , key
    -
    -      while (i--) {
    -        key = keys[i];
    -        if (null != path[key] && 'Object' === path[key].constructor.name
    -          && !(this._path(prefix + key) instanceof MixedSchema)) {
    -          this.set(path[key], prefix + key, constructing);
    -        } else if (this._strictMode) {
    -          pathtype = this.schema.pathType(prefix + key);
    -          if ('real' === pathtype || 'virtual' === pathtype) {
    -            this.set(prefix + key, path[key], constructing);
    -          } else if ('throw' == this._strictMode) {
    -            throw new Error("Field `" + key + "` is not in schema.");
    -          }
    -        } else if (undefined !== path[key]) {
    -          this.set(prefix + key, path[key], constructing);
    -        }
    -      }
    -
    -      return this;
    -    }
    -  }
    -
    -  // ensure _strict is honored for obj props
    -  // docschema = new Schema({ path: { nest: 'string' }})
    -  // doc.set('path', obj);
    -  var pathType = this.schema.pathType(path);
    -  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
    -    if (!merge) this.setValue(path, null);
    -    this.set(val, path, constructing);
    -    return this;
    -  }
    +  // Monkey-patch `.then()` so if the promise is handled, we don't emit an
    +  // `error` event.
    +  var _then = promise.then;
    +  promise.then = function(resolve, reject) {
    +    promise.$hasHandler = true;
    +    return _then.call(promise, resolve, reject);
    +  };
     
    -  var schema;
    -  if ('adhocOrUndefined' == pathType && this._strictMode) {
    -    return this;
    -  } else if ('virtual' == pathType) {
    -    schema = this.schema.virtualpath(path);
    -    schema.applySetters(val, this);
    -    return this;
    -  } else {
    -    schema = this._path(path);
    +  return promise;
    +}, '`openSet()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/connections.html#use-mongo-client');

    Connection#error(err, callback)

    error

    Parameters:

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    show code
    Connection.prototype.error = function(err, callback) {
    +  if (callback) {
    +    return callback(err);
       }
    +  this.emit('error', err);
    +};

    Connection#_open(callback)

    Handles opening the connection with the appropriate method based on connection type.

    Parameters:

    show code
    Connection.prototype._open = function(emit, callback) {
    +  this.readyState = STATES.connecting;
    +  this._closeCalled = false;
     
    -  var parts = path.split('.')
    -    , pathToMark
    +  var _this = this;
     
    -  // When using the $set operator the path to the field must already exist.
    -  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
    +  var method = this.replica
    +      ? 'doOpenSet'
    +      : 'doOpen';
     
    -  if (parts.length <= 1) {
    -    pathToMark = path;
    -  } else {
    -    for (var i = 0; i < parts.length; ++i) {
    -      var part = parts[i];
    -      var subpath = parts.slice(0, i).concat(part).join('.');
    -      if (this.isDirectModified(subpath) // earlier prefixes that are already
    -                                         // marked as dirty have precedence
    -          || this.get(subpath) === null) {
    -        pathToMark = subpath;
    -        break;
    +  // open connection
    +  this[method](function(err) {
    +    if (err) {
    +      _this.readyState = STATES.disconnected;
    +      if (_this._hasOpened) {
    +        if (callback) {
    +          callback(err);
    +        }
    +      } else {
    +        _this.error(err, emit && callback);
           }
    +      return;
         }
     
    -    if (!pathToMark) pathToMark = path;
    -  }
    -
    -  if (!schema || null === val || undefined === val) {
    -    this._set(pathToMark, path, constructing, parts, schema, val);
    -    return this;
    -  }
    -
    -  var self = this;
    -
    -  // if this doc is being constructed we should not
    -  // trigger getters.
    -  var priorVal = constructing
    -    ? undefined
    -    : this.get(path);
    -
    -  var shouldSet = this.try(function(){
    -    val = schema.applySetters(val, self, false, priorVal);
    +    _this.onOpen(callback);
       });
    +};

    Connection#onOpen()

    Called when the connection is opened

    show code
    Connection.prototype.onOpen = function(callback) {
    +  var _this = this;
     
    -  if (shouldSet) {
    -    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
    -  }
    -
    -  return this;
    -}

    Parameters:

    • path <String, Object> path or object of key/vals to set
    • val <Any> the value to set
    • [type] <Schema, String, Number, Buffer, etc..> optionally specify a type for "on-the-fly" attributes
    • [options] <Object> optionally specify options that modify the behavior of the set

    Example:

    - -
    // path, value
    -doc.set(path, value)
    -
    -// object
    -doc.set({
    -    path  : value
    -  , path2 : {
    -       path  : value
    +  function open(err, isAuth) {
    +    if (err) {
    +      _this.readyState = isAuth ? STATES.unauthorized : STATES.disconnected;
    +      _this.error(err, callback);
    +      return;
         }
    -})
    -
    -// only-the-fly cast to number
    -doc.set(path, value, Number)
     
    -// only-the-fly cast to string
    -doc.set(path, value, String)

    Document#_shouldModify()

    Determine if we should mark this change as modified.

    show code
    Document.prototype._shouldModify = function (
    -    pathToMark, path, constructing, parts, schema, val, priorVal) {
    +    _this.readyState = STATES.connected;
     
    -  if (this.isNew) return true;
    -  if (this.isDirectModified(pathToMark)) return false;
    +    // avoid having the collection subscribe to our event emitter
    +    // to prevent 0.3 warning
    +    for (var i in _this.collections) {
    +      if (utils.object.hasOwnProperty(_this.collections, i)) {
    +        _this.collections[i].onOpen();
    +      }
    +    }
     
    -  if (undefined === val && !this.isSelected(path)) {
    -    // when a path is not selected in a query, its initial
    -    // value will be undefined.
    -    return true;
    +    callback && callback();
    +    _this.emit('open');
       }
     
    -  if (undefined === val && path in this._activePaths.states.default) {
    -    // we're just unsetting the default value which was never saved
    -    return false;
    +  // re-authenticate if we're not already connected #3871
    +  if (this._readyState !== STATES.connected && this.shouldAuthenticate()) {
    +    _this.db.authenticate(_this.user, _this.pass, _this.options.auth, function(err) {
    +      open(err, true);
    +    });
    +  } else {
    +    open();
       }
    +};

    Connection#openUri(uri, [options], [callback])

    Opens the connection with a URI using MongoClient.connect().

    Parameters:

    • uri <String> The URI to connect with.
    • [options] <Object> Passed on to http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect
    • [callback] <Function>
    show code
    Connection.prototype.openUri = function(uri, options, callback) {
    +  this.readyState = STATES.connecting;
    +  this._closeCalled = false;
     
    -  if (!deepEqual(val, priorVal || this.get(path))) {
    -    return true;
    +  try {
    +    var parsed = muri(uri);
    +    this.name = parsed.db;
    +    this.host = parsed.hosts[0].host || parsed.hosts[0].ipc;
    +    this.port = parsed.hosts[0].port || 27017;
    +    if (parsed.auth) {
    +      this.user = parsed.auth.user;
    +      this.pass = parsed.auth.pass;
    +    }
    +  } catch (error) {
    +    this.error(error, callback);
    +    throw error;
       }
     
    -  if (!constructing &&
    -      null != val &&
    -      path in this._activePaths.states.default &&
    -      deepEqual(val, schema.getDefault(this, constructing))) {
    -    // a path with a default was $unset on the server
    -    // and the user is setting it to the same value again
    -    return true;
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
       }
     
    -  return false;
    -}

    Returns:


    Document#_set()

    Handles the actual setting of the value and marking the path modified if appropriate.

    show code
    Document.prototype._set = function (
    -    pathToMark, path, constructing, parts, schema, val, priorVal) {
    -
    -  var shouldModify = this._shouldModify.apply(this, arguments);
    +  var Promise = PromiseProvider.get();
    +  var _this = this;
     
    -  if (shouldModify) {
    -    this.markModified(pathToMark, val);
    +  if (options) {
    +    options = utils.clone(options, { retainKeyOrder: true });
    +    delete options.useMongoClient;
    +    if (options.config && options.config.autoIndex != null) {
    +      this.config.autoIndex = options.config.autoIndex !== false;
    +      delete options.config;
    +    }
     
    -    // handle directly setting arrays (gh-1126)
    -    MongooseArray || (MongooseArray = require('./types/array'));
    -    if (val instanceof MongooseArray) {
    -      val._registerAtomic('$set', val);
    +    // Backwards compat
    +    if (options.user || options.pass) {
    +      options.auth = options.auth || {};
    +      options.auth.user = options.user;
    +      options.auth.password = options.pass;
    +      delete options.user;
    +      delete options.pass;
    +      this.user = options.auth.user;
    +      this.pass = options.auth.password;
         }
       }
     
    -  var obj = this._doc
    -    , i = 0
    -    , l = parts.length
    -
    -  for (; i < l; i++) {
    -    var next = i + 1
    -      , last = next === l;
    +  this._connectionOptions = options;
     
    -    if (last) {
    -      obj[parts[i]] = val;
    -    } else {
    -      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
    -        obj = obj[parts[i]];
    -      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
    -        obj = obj[parts[i]];
    -      } else {
    -        obj = obj[parts[i]] = {};
    +  var promise = new Promise.ES6(function(resolve, reject) {
    +    mongodb.MongoClient.connect(uri, options, function(error, db) {
    +      if (error) {
    +        _this.readyState = STATES.disconnected;
    +        if (_this.listeners('error').length) {
    +          _this.emit('error', error);
    +        }
    +        return reject(error);
           }
    -    }
    -  }
    -}

    Document#getValue(path)

    Gets a raw value from a path (no getters)

    show code
    Document.prototype.getValue = function (path) {
    -  var parts = path.split('.')
    -    , obj = this._doc
    -    , part;
    +      // Backwards compat for mongoose 4.x
    +      db.on('reconnect', function() {
    +        _this.emit('reconnected');
    +      });
    +      db.s.topology.on('close', function() {
    +        _this.emit('disconnected');
    +      });
     
    -  for (var i = 0, l = parts.length; i < l; i++) {
    -    part = parts[i];
    -    obj = obj.getValue
    -        ? obj.getValue(part) // If we have an embedded array document member
    -        : obj[part];
    -    if (!obj) return obj;
    -  }
    +      _this.db = db;
    +      _this.readyState = STATES.connected;
     
    -  return obj;
    -}

    Parameters:


    Document#setValue(path, value)

    Sets a raw value for a path (no casting, setters, transformations)

    show code
    Document.prototype.setValue = function (path, val) {
    -  var parts = path.split('.')
    -    , obj = this._doc;
    +      for (var i in _this.collections) {
    +        if (utils.object.hasOwnProperty(_this.collections, i)) {
    +          _this.collections[i].onOpen();
    +        }
    +      }
     
    -  for (var i = 0, len = parts.length-1; i < len; i++) {
    -    obj = obj[parts[i]];
    -  }
    +      callback && callback(null, _this);
    +      delete _this.then;
    +      delete _this.catch;
    +      resolve(_this);
    +      _this.emit('open');
    +    });
    +  });
     
    -  obj[parts[len]] = val;
    -  return this;
    -};

    Parameters:


    Document#get(path, [type])

    Returns the value of a path.

    show code
    Document.prototype.get = function (path, type) {
    -  var adhocs;
    -  if (type) {
    -    adhocs = this._adhocPaths || (this._adhocPaths = {});
    -    adhocs[path] = Schema.interpretAsType(path, type);
    -  }
    +  this.then = function(resolve, reject) {
    +    return promise.then(resolve, reject);
    +  };
    +  this.catch = function(reject) {
    +    return promise.catch(reject);
    +  };
     
    -  var schema = this._path(path) || this.schema.virtualpath(path)
    -    , pieces = path.split('.')
    -    , obj = this._doc;
    +  return this;
    +};

    Connection#close([callback])

    Closes the connection

    Parameters:

    Returns:

    show code
    Connection.prototype.close = function(callback) {
    +  var _this = this;
    +  var Promise = PromiseProvider.get();
    +  return new Promise.ES6(function(resolve, reject) {
    +    _this._close(function(error) {
    +      callback && callback(error);
    +      if (error) {
    +        reject(error);
    +        return;
    +      }
    +      resolve();
    +    });
    +  });
    +};

    Connection#_close(callback)

    Handles closing the connection

    Parameters:

    show code
    Connection.prototype._close = function(callback) {
    +  var _this = this;
    +  this._closeCalled = true;
     
    -  for (var i = 0, l = pieces.length; i < l; i++) {
    -    obj = null == obj ? null : obj[pieces[i]];
    -  }
    +  switch (this.readyState) {
    +    case 0: // disconnected
    +      callback && callback();
    +      break;
     
    -  if (schema) {
    -    obj = schema.applyGetters(obj, this);
    -  }
    +    case 1: // connected
    +    case 4: // unauthorized
    +      this.readyState = STATES.disconnecting;
    +      this.doClose(function(err) {
    +        if (err) {
    +          _this.error(err, callback);
    +        } else {
    +          _this.onClose();
    +          callback && callback();
    +        }
    +      });
    +      break;
     
    -  return obj;
    -};

    Parameters:

    Example

    + case 2: // connecting + this.once('open', function() { + _this.close(callback); + }); + break; -
    // path
    -doc.get('age') // 47
    +    case 3: // disconnecting
    +      if (!callback) {
    +        break;
    +      }
    +      this.once('close', function() {
    +        callback();
    +      });
    +      break;
    +  }
     
    -// dynamic casting to a string
    -doc.get('age', String) // "47"

    Document#_path(path)

    Returns the schematype for the given path.

    show code
    Document.prototype._path = function (path) {
    -  var adhocs = this._adhocPaths
    -    , adhocType = adhocs && adhocs[path];
    +  return this;
    +};

    Connection#onClose()

    Called when the connection closes

    show code
    Connection.prototype.onClose = function() {
    +  this.readyState = STATES.disconnected;
     
    -  if (adhocType) {
    -    return adhocType;
    -  } else {
    -    return this.schema.path(path);
    +  // avoid having the collection subscribe to our event emitter
    +  // to prevent 0.3 warning
    +  for (var i in this.collections) {
    +    if (utils.object.hasOwnProperty(this.collections, i)) {
    +      this.collections[i].onClose();
    +    }
       }
    -};

    Parameters:


    Document#markModified(path)

    Marks the path as having pending changes to write to the db.

    show code
    Document.prototype.markModified = function (path) {
    -  this._activePaths.modify(path);
    -}

    Parameters:

    • path <String> the path to mark modified

    Very helpful when using Mixed types.

    - -

    Example:

    -
    doc.mixed.type = 'changed';
    -doc.markModified('mixed.type');
    -doc.save() // changes to mixed.type are now persisted

    Document#try(fn, scope)

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    show code
    Document.prototype.try = function (fn, scope) {
    -  var res;
    -  try {
    -    fn.call(scope);
    -    res = true;
    -  } catch (e) {
    -    this._error(e);
    -    res = false;
    +  this.emit('close');
    +};

    Connection#collection(name, [options])

    Retrieves a collection, creating it if not cached.

    Parameters:

    • name <String> of the collection
    • [options] <Object> optional collection options

    Returns:

    Not typically needed by applications. Just talk to your collection through your model.

    show code
    Connection.prototype.collection = function(name, options) {
    +  if (!(name in this.collections)) {
    +    this.collections[name] = new Collection(name, this, options);
       }
    -  return res;
    -};

    Parameters:

    • fn <Function> function to execute
    • scope <Object> the scope with which to call fn

    Document#modifiedPaths()

    Returns the list of paths that have been modified.

    show code
    Document.prototype.modifiedPaths = function () {
    -  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
    +  return this.collections[name];
    +};

    Connection#model(name, [schema], [collection])

    Defines or retrieves a model.

    Parameters:

    • name <String> the model name
    • [schema] <Schema> a schema. necessary when defining a model
    • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

    Returns:

    • <Model> The compiled model
    var mongoose = require('mongoose');
    +var db = mongoose.createConnection(..);
    +db.model('Venue', new Schema(..));
    +var Ticket = db.model('Ticket', new Schema(..));
    +var Venue = db.model('Venue');
    - return directModifiedPaths.reduce(function (list, path) { - var parts = path.split('.'); - return list.concat(parts.reduce(function (chains, part, i) { - return chains.concat(parts.slice(0, i).concat(part).join('.')); - }, [])); - }, []); -};

    Returns:


    Document#isModified([path])

    Returns true if this document was modified, else false.

    show code
    Document.prototype.isModified = function (path) {
    -  return path
    -    ? !!~this.modifiedPaths().indexOf(path)
    -    : this._activePaths.some('modify');
    -};

    Parameters:

    Returns:

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    +

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    -

    Example

    +

    Example:

    -
    doc.set('documents.0.title', 'changed');
    -doc.isModified()                    // true
    -doc.isModified('documents')         // true
    -doc.isModified('documents.0.title') // true
    -doc.isDirectModified('documents')   // false

    Document#isDirectModified(path)

    Returns true if path was directly set and modified, else false.

    show code
    Document.prototype.isDirectModified = function (path) {
    -  return (path in this._activePaths.states.modify);
    -};

    Parameters:

    Returns:

    Example

    +
    var schema = new Schema({ name: String }, { collection: 'actor' });
     
    -
    doc.set('documents.0.title', 'changed');
    -doc.isDirectModified('documents.0.title') // true
    -doc.isDirectModified('documents') // false

    Document#isInit(path)

    Checks if path was initialized.

    show code
    Document.prototype.isInit = function (path) {
    -  return (path in this._activePaths.states.init);
    -};

    Parameters:

    Returns:


    Document#isSelected(path)

    Checks if path was selected in the source query which initialized this document.

    show code
    Document.prototype.isSelected = function isSelected (path) {
    -  if (this._selected) {
    +// or
     
    -    if ('_id' === path) {
    -      return 0 !== this._selected._id;
    -    }
    +schema.set('collection', 'actor');
     
    -    var paths = Object.keys(this._selected)
    -      , i = paths.length
    -      , inclusive = false
    -      , cur
    +// or
     
    -    if (1 === i && '_id' === paths[0]) {
    -      // only _id was selected.
    -      return 0 === this._selected._id;
    -    }
    +var collectionName = 'actor'
    +var M = conn.model('Actor', schema, collectionName)
    show code
    Connection.prototype.model = function(name, schema, collection) {
    +  // collection name discovery
    +  if (typeof schema === 'string') {
    +    collection = schema;
    +    schema = false;
    +  }
     
    -    while (i--) {
    -      cur = paths[i];
    -      if ('_id' == cur) continue;
    -      inclusive = !! this._selected[cur];
    -      break;
    -    }
    +  if (utils.isObject(schema) && !schema.instanceOfSchema) {
    +    schema = new Schema(schema);
    +  }
    +  if (schema && !schema.instanceOfSchema) {
    +    throw new Error('The 2nd parameter to `mongoose.model()` should be a ' +
    +      'schema or a POJO');
    +  }
     
    -    if (path in this._selected) {
    -      return inclusive;
    +  if (this.models[name] && !collection) {
    +    // model exists but we are not subclassing with custom collection
    +    if (schema && schema.instanceOfSchema && schema !== this.models[name].schema) {
    +      throw new MongooseError.OverwriteModelError(name);
         }
    +    return this.models[name];
    +  }
     
    -    i = paths.length;
    -    var pathDot = path + '.';
    -
    -    while (i--) {
    -      cur = paths[i];
    -      if ('_id' == cur) continue;
    +  var opts = {cache: false, connection: this};
    +  var model;
     
    -      if (0 === cur.indexOf(pathDot)) {
    -        return inclusive;
    -      }
    +  if (schema && schema.instanceOfSchema) {
    +    // compile a model
    +    model = this.base.model(name, schema, collection, opts);
     
    -      if (0 === pathDot.indexOf(cur)) {
    -        return inclusive;
    -      }
    +    // only the first model with this name is cached to allow
    +    // for one-offs with custom collection names etc.
    +    if (!this.models[name]) {
    +      this.models[name] = model;
         }
     
    -    return ! inclusive;
    +    model.init();
    +    return model;
       }
     
    -  return true;
    -}

    Parameters:

    Returns:

    Example

    - -
    Thing.findOne().select('name').exec(function (err, doc) {
    -   doc.isSelected('name') // true
    -   doc.isSelected('age')  // false
    -})

    Document#validate(cb)

    Executes registered validation rules for this document.

    show code
    Document.prototype.validate = function (cb) {
    -  var self = this
    -
    -  // only validate required fields when necessary
    -  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
    -    if (!self.isSelected(path) && !self.isModified(path)) return false;
    -    return true;
    -  });
    -
    -  paths = paths.concat(Object.keys(this._activePaths.states.init));
    -  paths = paths.concat(Object.keys(this._activePaths.states.modify));
    -  paths = paths.concat(Object.keys(this._activePaths.states.default));
    -
    -  if (0 === paths.length) {
    -    complete();
    -    return this;
    +  if (this.models[name] && collection) {
    +    // subclassing current model with alternate collection
    +    model = this.models[name];
    +    schema = model.prototype.schema;
    +    var sub = model.__subclass(this, schema, collection);
    +    // do not cache the sub model
    +    return sub;
       }
     
    -  var validating = {}
    -    , total = 0;
    -
    -  paths.forEach(validatePath);
    -  return this;
    -
    -  function validatePath (path) {
    -    if (validating[path]) return;
    +  // lookup model in mongoose module
    +  model = this.base.models[name];
     
    -    validating[path] = true;
    -    total++;
    -
    -    process.nextTick(function(){
    -      var p = self.schema.path(path);
    -      if (!p) return --total || complete();
    -
    -      p.doValidate(self.getValue(path), function (err) {
    -        if (err) self.invalidate(path, err, true);
    -        --total || complete();
    -      }, self);
    -    });
    +  if (!model) {
    +    throw new MongooseError.MissingSchemaError(name);
       }
     
    -  function complete () {
    -    var err = self._validationError;
    -    self._validationError = undefined;
    -    cb(err);
    -  }
    -};

    Parameters:

    • cb <Function> called after validation completes, passing an error if one occurred

    Note:

    - -

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    + if (this === model.prototype.db + && (!collection || collection === model.collection.name)) { + // model already uses this connection. -

    Example:

    + // only the first model with this name is cached to allow + // for one-offs with custom collection names etc. + if (!this.models[name]) { + this.models[name] = model; + } -
    doc.validate(function (err) {
    -  if (err) handleError(err);
    -  else // validation passed
    -});

    Document#invalidate(path, err)

    Marks a path as invalid, causing validation to fail.

    show code
    Document.prototype.invalidate = function (path, err) {
    -  if (!this._validationError) {
    -    this._validationError = new ValidationError(this);
    +    return model;
       }
    -
    -  if (!err || 'string' === typeof err) {
    -    err = new ValidatorError(path, err);
    +  this.models[name] = model.__subclass(this, schema, collection);
    +  return this.models[name];
    +};

    Connection#modelNames()

    Returns an array of model names created on this connection.

    Returns:

    show code
    Connection.prototype.modelNames = function() {
    +  return Object.keys(this.models);
    +};

    Connection#shouldAuthenticate()

    @brief Returns if the connection requires authentication after it is opened. Generally if a
    username and password are both provided than authentication is needed, but in some cases a
    password is not required.

    Returns:

    • <Boolean> true if the connection should be authenticated after it is opened, otherwise false.
    show code
    Connection.prototype.shouldAuthenticate = function() {
    +  return (this.user !== null && this.user !== void 0) &&
    +      ((this.pass !== null || this.pass !== void 0) || this.authMechanismDoesNotRequirePassword());
    +};

    Connection#authMechanismDoesNotRequirePassword()

    @brief Returns a boolean value that specifies if the current authentication mechanism needs a
    password to authenticate according to the auth objects passed into the open/openSet methods.

    Returns:

    • <Boolean> true if the authentication mechanism specified in the options object requires
    show code
    Connection.prototype.authMechanismDoesNotRequirePassword = function() {
    +  if (this.options && this.options.auth) {
    +    return authMechanismsWhichDontRequirePassword.indexOf(this.options.auth.authMechanism) >= 0;
       }
    +  return true;
    +};

    Connection#optionsProvideAuthenticationData([options])

    @brief Returns a boolean value that specifies if the provided objects object provides enough
    data to authenticate with. Generally this is true if the username and password are both specified
    but in some authentication methods, a password is not required for authentication so only a username
    is required.

    Parameters:

    • [options] <Object> the options object passed into the open/openSet methods.

    Returns:

    • <Boolean> true if the provided options object provides enough data to authenticate with,
    show code
    Connection.prototype.optionsProvideAuthenticationData = function(options) {
    +  return (options) &&
    +      (options.user) &&
    +      ((options.pass) || this.authMechanismDoesNotRequirePassword());
    +};

    Connection#config

    A hash of the global options that are associated with this connection

    show code
    Connection.prototype.config;

    Connection#db

    The mongodb.Db instance, set when the connection is opened

    show code
    Connection.prototype.db;

    Connection#collections

    A hash of the collections associated with this connection

    show code
    Connection.prototype.collections;

    Connection#readyState

    Connection ready state

    - this._validationError.errors[path] = err; -}

    Parameters:

    • path <String> the field to invalidate
    • err <String, Error> the error which states the reason `path` was invalid

    Document#_reset()

    Resets the internal modified state of this document.

    show code
    Document.prototype._reset = function reset () {
    -  var self = this;
    -  DocumentArray || (DocumentArray = require('./types/documentarray'));
    -
    -  this._activePaths
    -  .map('init', 'modify', function (i) {
    -    return self.getValue(i);
    -  })
    -  .filter(function (val) {
    -    return val && val instanceof DocumentArray && val.length;
    -  })
    -  .forEach(function (array) {
    -    var i = array.length;
    -    while (i--) {
    -      var doc = array[i];
    -      if (!doc) continue;
    -      doc._reset();
    -    }
    -  });
    -
    -  // clear atomics
    -  this._dirty().forEach(function (dirt) {
    -    var type = dirt.value;
    -    if (type && type._atomics) {
    -      type._atomics = {};
    -    }
    -  });
    -
    -  // Clear 'modify'('dirty') cache
    -  this._activePaths.clear('modify');
    -  this._validationError = undefined;
    -  this.errors = undefined;
    -  var self = this;
    -  this.schema.requiredPaths().forEach(function (path) {
    -    self._activePaths.require(path);
    -  });
    -
    -  return this;
    -}

    Returns:


    Document#_dirty()

    Returns this documents dirty paths / vals.

    show code
    Document.prototype._dirty = function _dirty () {
    -  var self = this;
    +
      +
    • 0 = disconnected
    • +
    • 1 = connected
    • +
    • 2 = connecting
    • +
    • 3 = disconnecting
    • +
    - var all = this._activePaths.map('modify', function (path) { - return { path: path - , value: self.getValue(path) - , schema: self._path(path) }; - }); +

    Each state change emits its associated event name.

    - // Sort dirty paths in a flat hierarchy. - all.sort(function (a, b) { - return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0)); - }); +

    Example

    - // Ignore "foo.a" if "foo" is dirty already. - var minimal = [] - , lastPath - , top; +
    conn.on('connected', callback);
    +conn.on('disconnected', callback);
    show code
    Object.defineProperty(Connection.prototype, 'readyState', {
    +  get: function() {
    +    return this._readyState;
    +  },
    +  set: function(val) {
    +    if (!(val in STATES)) {
    +      throw new Error('Invalid connection state: ' + val);
    +    }
     
    -  all.forEach(function (item, i) {
    -    if (item.path.indexOf(lastPath) !== 0) {
    -      lastPath = item.path + '.';
    -      minimal.push(item);
    -      top = item;
    -    } else {
    -      if (!(item.value && top.value)) return;
    +    if (this._readyState !== val) {
    +      this._readyState = val;
    +      // loop over the otherDbs on this connection and change their state
    +      for (var i = 0; i < this.otherDbs.length; i++) {
    +        this.otherDbs[i].readyState = val;
    +      }
     
    -      // special case for top level MongooseArrays
    -      if (top.value._atomics && top.value.hasAtomics()) {
    -        // the `top` array itself and a sub path of `top` are being modified.
    -        // the only way to honor all of both modifications is through a $set
    -        // of entire array.
    -        top.value._atomics = {};
    -        top.value._atomics.$set = top.value;
    +      if (STATES.connected === val) {
    +        this._hasOpened = true;
           }
    -    }
    -  });
     
    -  top = lastPath = null;
    -  return minimal;
    -}

    Document#_setSchema(schema)

    Assigns/compiles schema into this documents prototype.

    show code
    Document.prototype._setSchema = function (schema) {
    -  compile(schema.tree, this);
    -  this.schema = schema;
    -}

    Parameters:


    Document#_registerHooks()

    Register default hooks

    show code
    Document.prototype._registerHooks = function _registerHooks () {
    -  if (!this.save) return;
    -
    -  DocumentArray || (DocumentArray = require('./types/documentarray'));
    -
    -  this.pre('save', function (next) {
    -    // we keep the error semaphore to make sure we don't
    -    // call `save` unnecessarily (we only need 1 error)
    -    var subdocs = 0
    -      , error = false
    -      , self = this;
    -
    -    // check for DocumentArrays
    -    var arrays = this._activePaths
    -    .map('init', 'modify', function (i) {
    -      return self.getValue(i);
    -    })
    -    .filter(function (val) {
    -      return val && val instanceof DocumentArray && val.length;
    -    });
    -
    -    if (!arrays.length)
    -      return next();
    -
    -    arrays.forEach(function (array) {
    -      if (error) return;
    -
    -      // handle sparse arrays by using for loop vs array.forEach
    -      // which skips the sparse elements
    -
    -      var len = array.length
    -      subdocs += len;
    -
    -      for (var i = 0; i < len; ++i) {
    -        if (error) break;
    -
    -        var doc = array[i];
    -        if (!doc) {
    -          --subdocs || next();
    -          continue;
    -        }
    -
    -        doc.save(handleSave);
    -      }
    -    });
    -
    -    function handleSave (err) {
    -      if (error) return;
    -
    -      if (err) {
    -        self._validationError = undefined;
    -        return next(error = err);
    -      }
    -
    -      --subdocs || next();
    +      this.emit(STATES[val]);
         }
    -
    -  }, function (err) {
    -    // emit on the Model if listening
    -    if (this.constructor.listeners('error').length) {
    -      this.constructor.emit('error', err);
    -    } else {
    -      // emit on the connection
    -      if (!this.db.listeners('error').length) {
    -        err.stack = 'No listeners detected, throwing. '
    -                  + 'Consider adding an error listener to your connection.
    -'
    -                  + err.stack
    +  }
    +});

  • utils.js

    exports.each(arr, fn)

    Executes a function on each element of an array (like _.each)

    show code
    exports.each = function(arr, fn) {
    +  for (var i = 0; i < arr.length; ++i) {
    +    fn(arr[i]);
    +  }
    +};

    Parameters:


    exports.mergeClone(to, fromObj)

    merges to with a copy of from

    show code
    exports.mergeClone = function(to, fromObj) {
    +  var keys = Object.keys(fromObj);
    +  var len = keys.length;
    +  var i = 0;
    +  var key;
    +
    +  while (i < len) {
    +    key = keys[i++];
    +    if (typeof to[key] === 'undefined') {
    +      // make sure to retain key order here because of a bug handling the $each
    +      // operator in mongodb 2.4.4
    +      to[key] = exports.clone(fromObj[key], {
    +        retainKeyOrder: 1,
    +        flattenDecimals: false
    +      });
    +    } else {
    +      if (exports.isObject(fromObj[key])) {
    +        var obj = fromObj[key];
    +        if (isMongooseObject(fromObj[key]) && !fromObj[key].isMongooseBuffer) {
    +          obj = obj.toObject({ transform: false, virtuals: false });
    +        }
    +        if (fromObj[key].isMongooseBuffer) {
    +          obj = new Buffer(obj);
    +        }
    +        exports.mergeClone(to[key], obj);
    +      } else {
    +        // make sure to retain key order here because of a bug handling the
    +        // $each operator in mongodb 2.4.4
    +        to[key] = exports.clone(fromObj[key], {
    +          retainKeyOrder: 1,
    +          flattenDecimals: false
    +        });
           }
    -      this.db.emit('error', err);
    -    }
    -  }).pre('save', function checkForExistingErrors (next) {
    -    // if any doc.set() calls failed
    -    if (this._saveError) {
    -      next(this._saveError);
    -      this._saveError = null;
    -    } else {
    -      next();
    -    }
    -  }).pre('save', function validation (next) {
    -    return this.validate(next);
    -  });
    -
    -  // add user defined queues
    -  this._doQueue();
    -};

    Document#_error(err)

    Registers an error

    show code
    Document.prototype._error = function (err) {
    -  this._saveError = err;
    -  return this;
    -};

    Parameters:


    Document#_doQueue()

    Executes methods queued from the Schema definition

    show code
    Document.prototype._doQueue = function () {
    -  var q = this.schema && this.schema.callQueue;
    -  if (q) {
    -    for (var i = 0, l = q.length; i < l; i++) {
    -      this[q[i][0]].apply(this, q[i][1]);
         }
       }
    -  return this;
    -};

    Document#toObject([options])

    Converts this document into a plain javascript object

    show code
    Document.prototype.toObject = function (options) {
    -  // When internally saving this document we always pass options,
    -  // bypassing the custom schema options.
    -  if (!(options && 'Object' == options.constructor.name)) {
    -    options = this.schema.options.toObject
    -      ? clone(this.schema.options.toObject)
    -      : {};
    -  }
    +};

    Parameters:


    exports.pluralization

    Pluralization rules.

    show code
    exports.pluralization = [
    +  [/(m)an$/gi, '$1en'],
    +  [/(pe)rson$/gi, '$1ople'],
    +  [/(child)$/gi, '$1ren'],
    +  [/^(ox)$/gi, '$1en'],
    +  [/(ax|test)is$/gi, '$1es'],
    +  [/(octop|vir)us$/gi, '$1i'],
    +  [/(alias|status)$/gi, '$1es'],
    +  [/(bu)s$/gi, '$1ses'],
    +  [/(buffal|tomat|potat)o$/gi, '$1oes'],
    +  [/([ti])um$/gi, '$1a'],
    +  [/sis$/gi, 'ses'],
    +  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
    +  [/(hive)$/gi, '$1s'],
    +  [/([^aeiouy]|qu)y$/gi, '$1ies'],
    +  [/(x|ch|ss|sh)$/gi, '$1es'],
    +  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
    +  [/([m|l])ouse$/gi, '$1ice'],
    +  [/(kn|w|l)ife$/gi, '$1ives'],
    +  [/(quiz)$/gi, '$1zes'],
    +  [/s$/gi, 's'],
    +  [/([^a-z])$/, '$1'],
    +  [/$/gi, 's']
    +];
    +var rules = exports.pluralization;

    These rules are applied while processing the argument to toCollectionName.


    exports.uncountables

    Uncountable words.

    show code
    exports.uncountables = [
    +  'advice',
    +  'energy',
    +  'excretion',
    +  'digestion',
    +  'cooperation',
    +  'health',
    +  'justice',
    +  'labour',
    +  'machinery',
    +  'equipment',
    +  'information',
    +  'pollution',
    +  'sewage',
    +  'paper',
    +  'money',
    +  'species',
    +  'series',
    +  'rain',
    +  'rice',
    +  'fish',
    +  'sheep',
    +  'moose',
    +  'deer',
    +  'news',
    +  'expertise',
    +  'status',
    +  'media'
    +];
    +var uncountables = exports.uncountables;

    These words are applied while processing the argument to toCollectionName.


  • browser.js

    exports.Document()

    The Mongoose browser Document constructor.


    exports.PromiseProvider()

    Storage layer for mongoose promises


    exports.Schema()

    The Mongoose Schema constructor

    Example:

    - ;('minimize' in options) || (options.minimize = this.schema.options.minimize); +
    var mongoose = require('mongoose');
    +var Schema = mongoose.Schema;
    +var CatSchema = new Schema(..);

    exports.VirtualType()

    The Mongoose VirtualType constructor


    exports#SchemaTypes

    The various Mongoose SchemaTypes.

    - var ret = clone(this._doc, options); +

    Note:

    - if (options.virtuals || options.getters && false !== options.virtuals) { - applyGetters(this, ret, 'virtuals', options); - } +

    Alias of mongoose.Schema.Types for backwards compatibility.

    show code
    exports.SchemaType = require('./schematype.js');

    exports#Types

    The various Mongoose Types.

    - if (options.getters) { - applyGetters(this, ret, 'paths', options); - } +

    Example:

    - return ret; -};
  • Parameters:

    Returns:

    Options:

    +
    var mongoose = require('mongoose');
    +var array = mongoose.Types.Array;
    + +

    Types:

      -
    • getters apply all getters (path and virtual getters)
    • -
    • virtuals apply virtual getters (can override getters option)
    • -
    • minimize remove empty objects (defaults to true)
    • +
    • ObjectId
    • +
    • Buffer
    • +
    • SubDocument
    • +
    • Array
    • +
    • DocumentArray
    -

    Example of only applying path getters

    - -
    doc.toObject({ getters: true, virtuals: false })
    - -

    Example of only applying virtual getters

    - -
    doc.toObject({ virtuals: true })
    - -

    Example of applying both path and virtual getters

    - -
    doc.toObject({ getters: true })
    - -

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    - -
    schema.set('toObject', { virtuals: true })
    - -

    See schema options for details.


    Document#toJSON(options)

    The return value of this method is used in calls to JSON.stringify(doc).

    show code
    Document.prototype.toJSON = function (options) {
    -  // check for object type since an array of documents
    -  // being stringified passes array indexes instead
    -  // of options objects. JSON.stringify([doc, doc])
    -  if (!(options && 'Object' == options.constructor.name)) {
    -    options = this.schema.options.toJSON
    -      ? clone(this.schema.options.toJSON)
    -      : {};
    -  }
    -  options.json = true;
    -  return this.toObject(options);
    -};

    Parameters:

    • options <Object> same options as `Document#toObject`

    Returns:

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    - -
    schema.set('toJSON', { virtuals: true })
    - -

    See schema options for details.


    Document#inspect()

    Helper for console.log

    show code
    Document.prototype.inspect = function (options) {
    -  var opts = options && 'Object' == options.constructor.name
    -    ? options
    -    : undefined
    -  return inspect(this.toObject(opts));
    -};

    Document#toString()

    Helper for console.log


    Document#equals(doc)

    Returns true if the Document stores the same data as doc.

    show code
    Document.prototype.equals = function (doc) {
    -  var tid = this.get('_id');
    -  var docid = doc.get('_id');
    -  return tid.equals
    -    ? tid.equals(docid)
    -    : tid === docid;
    -};

    Parameters:

    Returns:

    Documents are considered equal when they have matching _ids.


    Document#errors

    Hash containing current validation errors.


    Document#id

    The string version of this documents _id.

    - -

    Note:

    - -

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    +

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    -
    new Schema({ name: String }, { id: false });

    Document#isNew

    Boolean flag specifying if the document is new.


    Document#schema

    The documents schema.


  • drivers/node-mongodb-native/collection.js

    NativeCollection()

    A node-mongodb-native collection implementation.

    show code
    function NativeCollection () {
    +
    var ObjectId = mongoose.Types.ObjectId;
    +var id1 = new ObjectId;
    show code
    exports.Types = require('./types');

    exports#utils

    Internal utils

    show code
    exports.utils = require('./utils.js');

  • drivers/node-mongodb-native/collection.js

    function Object() { [native code] }#$format()

    Formatter for debug print args


    NativeCollection#getIndexes(callback)

    Retreives information about this collections indexes.

    Parameters:


    NativeCollection()

    A node-mongodb-native collection implementation.

    Inherits:

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    show code
    function NativeCollection() {
       this.collection = null;
       MongooseCollection.apply(this, arguments);
    -}

    Inherits:

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


    NativeCollection#onOpen()

    Called when the connection opens.

    show code
    NativeCollection.prototype.onOpen = function () {
    -  var self = this;
    +}

    NativeCollection#onClose()

    Called when the connection closes

    show code
    NativeCollection.prototype.onClose = function() {
    +  MongooseCollection.prototype.onClose.call(this);
    +};

    NativeCollection#onOpen()

    Called when the connection opens.

    show code
    NativeCollection.prototype.onOpen = function() {
    +  var _this = this;
     
    -  if (this.collection) {
    -    return MongooseCollection.prototype.onOpen.call(self);
    -  }
    +  // always get a new collection in case the user changed host:port
    +  // of parent db instance when re-opening the connection.
     
    -  if (!self.opts.size) {
    +  if (!_this.opts.capped.size) {
         // non-capped
    -    return self.conn.db.collection(self.name, callback);
    +    callback(null, _this.conn.db.collection(_this.name));
    +    return _this.collection;
       }
     
       // capped
    -  return self.conn.db.collection(self.name, function (err, c) {
    +  return _this.conn.db.collection(_this.name, function(err, c) {
         if (err) return callback(err);
     
         // discover if this collection exists and if it is capped
    -    c.options(function (err, exists) {
    -      if (err) return callback(err);
    +    _this.conn.db.listCollections({name: _this.name}).toArray(function(err, docs) {
    +      if (err) {
    +        return callback(err);
    +      }
    +      var doc = docs[0];
    +      var exists = !!doc;
     
           if (exists) {
    -        if (exists.capped) {
    +        if (doc.options && doc.options.capped) {
               callback(null, c);
             } else {
    -          var msg = 'A non-capped collection exists with this name.
    +          var msg = 'A non-capped collection exists with the name: ' + _this.name + '
     
     '
    -                  + ' To use this collection as a capped collection, please '
    -                  + 'first convert it.
    +              + ' To use this collection as a capped collection, please '
    +              + 'first convert it.
     '
    -                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
    +              + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped';
               err = new Error(msg);
               callback(err);
             }
           } else {
             // create
    -        var opts = utils.clone(self.opts);
    +        var opts = utils.clone(_this.opts.capped);
             opts.capped = true;
    -        self.conn.db.createCollection(self.name, opts, callback);
    +        _this.conn.db.createCollection(_this.name, opts, callback);
           }
         });
       });
     
    -  function callback (err, collection) {
    +  function callback(err, collection) {
         if (err) {
           // likely a strict mode error
    -      self.conn.emit('error', err);
    +      _this.conn.emit('error', err);
         } else {
    -      self.collection = collection;
    -      MongooseCollection.prototype.onOpen.call(self);
    +      _this.collection = collection;
    +      MongooseCollection.prototype.onOpen.call(_this);
         }
    -  };
    -};

    NativeCollection#onClose()

    Called when the connection closes

    show code
    NativeCollection.prototype.onClose = function () {
    -  MongooseCollection.prototype.onClose.call(this);
    -};

    NativeCollection#getIndexes(callback)

    Retreives information about this collections indexes.

    Parameters:


  • drivers/node-mongodb-native/connection.js

    NativeConnection()

    A node-mongodb-native connection implementation.

    show code
    function NativeConnection() {
    -  MongooseConnection.apply(this, arguments);
    -};

    Inherits:


    NativeConnection#doOpen(fn)

    Opens the connection to MongoDB.

    show code
    NativeConnection.prototype.doOpen = function (fn) {
    -  var server
    -    , self = this;
    +  }
    +};

  • drivers/node-mongodb-native/connection.js

    NativeConnection#doClose(fn)

    Closes the connection

    Parameters:

    Returns:

    show code
    NativeConnection.prototype.doClose = function(fn) {
    +  this.db.close(fn);
    +  return this;
    +};

    NativeConnection#doOpen(fn)

    Opens the connection to MongoDB.

    Parameters:

    Returns:

    show code
    NativeConnection.prototype.doOpen = function(fn) {
    +  var _this = this;
    +  var server = new Server(this.host, this.port, this.options.server);
     
    -  if (!this.db) {
    -    server = new mongo.Server(this.host, Number(this.port), this.options.server);
    -    this.db = new mongo.Db(this.name, server, this.options.db);
    +  if (this.options && this.options.mongos) {
    +    var mongos = new Mongos([server], this.options.mongos);
    +    this.db = new Db(this.name, mongos, this.options.db);
    +  } else {
    +    this.db = new Db(this.name, server, this.options.db);
       }
     
    -  this.db.open(function (err) {
    +  this.db.open(function(err) {
    +    listen(_this);
    +
    +    if (!mongos) {
    +      server.s.server.on('error', function(error) {
    +        if (/after \d+ attempts/.test(error.message)) {
    +          _this.emit('error', new DisconnectedError(server.s.server.name));
    +        }
    +      });
    +    }
    +
         if (err) return fn(err);
    +
         fn();
    -    listen(self);
       });
     
       return this;
    -};
    -
    -function listen (conn) {
    -  if (conn._listening) return;
    -  conn._listening = true;
    +};

    NativeConnection#doOpenSet(fn)

    Opens a connection to a MongoDB ReplicaSet.

    Parameters:

    Returns:

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    show code
    NativeConnection.prototype.doOpenSet = function(fn) {
    +  var servers = [],
    +      _this = this;
    +
    +  this.hosts.forEach(function(server) {
    +    var host = server.host || server.ipc;
    +    var port = server.port || 27017;
    +    servers.push(new Server(host, port, _this.options.server));
    +  });
     
    -  conn.db.on('close', function(){
    -    if (conn._closeCalled) return;
    +  var server = this.options.mongos
    +    ? new Mongos(servers, this.options.mongos)
    +    : new ReplSetServers(servers, this.options.replset || this.options.replSet);
    +  this.db = new Db(this.name, server, this.options.db);
     
    -    // the driver never emits an `open` event. auto_reconnect still
    -    // emits a `close` event but since we never get another
    -    // `open` we can't emit close
    -    if (conn.db.serverConfig.autoReconnect) {
    -      conn.readyState = STATES.disconnected;
    -      conn.emit('close');
    -      return;
    -    }
    -    conn.onClose();
    -  });
    -  conn.db.on('error', function(err){
    -    conn.emit('error', err);
    +  this.db.on('fullsetup', function() {
    +    _this.emit('fullsetup');
       });
    -  conn.db.on('timeout', function(err){
    -    var error = new Error(err && err.err || 'connection timeout');
    -    conn.emit('error', error);
    -  });
    -  conn.db.on('open', function (err, db) {
    -    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
    -      conn.readyState = STATES.connected;
    -      conn.emit('reconnected')
    -    }
    -  })
    -}

    Parameters:

    Returns:


    NativeConnection#doOpenSet(fn)

    Opens a connection to a MongoDB ReplicaSet.

    show code
    NativeConnection.prototype.doOpenSet = function (fn) {
    -  if (!this.db) {
    -    var servers = []
    -      , ports = this.port
    -      , self = this
    -
    -    this.host.forEach(function (host, i) {
    -      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
    -    });
     
    -    var server = new ReplSetServers(servers, this.options.replset);
    -    this.db = new mongo.Db(this.name, server, this.options.db);
    -
    -    this.db.on('fullsetup', function () {
    -      self.emit('fullsetup')
    -    });
    -  }
    +  this.db.on('all', function() {
    +    _this.emit('all');
    +  });
     
    -  this.db.open(function (err) {
    +  this.db.open(function(err) {
         if (err) return fn(err);
         fn();
    -    listen(self);
    +    listen(_this);
       });
     
       return this;
    -};

    Parameters:

    Returns:

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


    NativeConnection#doClose(fn)

    Closes the connection

    show code
    NativeConnection.prototype.doClose = function (fn) {
    -  this.db.close();
    -  if (fn) fn();
    -  return this;
    -}

    Parameters:

    Returns:


  • error.js

    MongooseError()

    Mongoose error

    show code
    function MongooseError (msg) {
    -  Error.call(this);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.message = msg;
    -  this.name = 'MongooseError';
    -};

    Inherits:


  • errors/cast.js

    CastError(type, value)

    Casting Error constructor.

    show code
    function CastError (type, value) {
    -  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'CastError';
    -  this.type = type;
    -  this.value = value;
    -};

    Parameters:

    Inherits:


  • errors/document.js

    DocumentError(msg)

    Document Error

    show code
    function DocumentError (msg) {
    -  MongooseError.call(this, msg);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'DocumentError';
    -};

    Parameters:

    Inherits:


  • errors/validation.js

    ValidationError(instance)

    Document Validation Error

    show code
    function ValidationError (instance) {
    -  MongooseError.call(this, "Validation failed");
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'ValidationError';
    -  this.errors = instance.errors = {};
    -};

    Parameters:

    Inherits:


    ValidationError#toString()

    Console.log helper

    show code
    ValidationError.prototype.toString = function () {
    -  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
    -    return String(this.errors[key]);
    -  }, this).join(', ');
    -};

  • errors/validator.js

    ValidatorError(path, msg)

    Schema validator error

    show code
    function ValidatorError (path, type) {
    -  var msg = type
    -    ? '"' + type + '" '
    -    : '';
    -  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
    -  Error.captureStackTrace(this, arguments.callee);
    -  this.name = 'ValidatorError';
    -  this.path = path;
    -  this.type = type;
    -};

    Parameters:

    Inherits:


  • model.js

    Model(doc)

    Model constructor

    show code
    function Model (doc, fields, skipId) {
    -  Document.call(this, doc, fields, skipId);
    -};

    Parameters:

    • doc <Object> values to with which to create the document

    Inherits:

    Events:

    • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

    • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


    Model#_getPopulationKeys(query)

    Returns what paths can be populated

    show code
    Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
    -  if (!(query && query.options.populate)) return;
    -
    -  var names = Object.keys(query.options.populate)
    -    , n = names.length
    -    , name
    -    , paths = {}
    -    , hasKeys
    -    , schema
    -
    -  while (n--) {
    -    name = names[n];
    -    schema = this.schema.path(name);
    -    hasKeys = true;
    -
    -    if (!schema) {
    -      // if the path is not recognized, it's potentially embedded docs
    -      // walk path atoms from right to left to find a matching path
    -      var pieces = name.split('.')
    -        , i = pieces.length;
    -
    -      while (i--) {
    -        var path = pieces.slice(0, i).join('.')
    -          , pathSchema = this.schema.path(path);
    -
    -        // loop until we find an array schema
    -        if (pathSchema && pathSchema.caster) {
    -          if (!paths[path]) {
    -            paths[path] = { sub: {} };
    -          }
    +};

    NativeConnection()

    A node-mongodb-native connection implementation.

    Inherits:

    show code
    function NativeConnection() {
    +  MongooseConnection.apply(this, arguments);
    +  this._listening = false;
    +}

    NativeConnection#parseOptions(passed, [connStrOptions])

    Prepares default connection options for the node-mongodb-native driver.

    Parameters:

    • passed <Object> options that were passed directly during connection
    • [connStrOptions] <Object> options that were passed in the connection string

    NOTE: passed options take precedence over connection string options.

    show code
    NativeConnection.prototype.parseOptions = function(passed, connStrOpts) {
    +  var o = passed ? require('../../utils').clone(passed) : {};
     
    -          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
    -          hasKeys || (hasKeys = true);
    -          break;
    +  o.db || (o.db = {});
    +  o.auth || (o.auth = {});
    +  o.server || (o.server = {});
    +  o.replset || (o.replset = o.replSet) || (o.replset = {});
    +  o.server.socketOptions || (o.server.socketOptions = {});
    +  o.replset.socketOptions || (o.replset.socketOptions = {});
    +  o.mongos || (o.mongos = (connStrOpts && connStrOpts.mongos));
    +  (o.mongos === true) && (o.mongos = {});
    +
    +  var opts = connStrOpts || {};
    +  Object.keys(opts).forEach(function(name) {
    +    switch (name) {
    +      case 'ssl':
    +        o.server.ssl = opts.ssl;
    +        o.replset.ssl = opts.ssl;
    +        o.mongos && (o.mongos.ssl = opts.ssl);
    +        break;
    +      case 'poolSize':
    +        if (typeof o.server[name] === 'undefined') {
    +          o.server[name] = o.replset[name] = opts[name];
             }
    -      }
    -    } else {
    -      paths[name] = query.options.populate[name];
    -      hasKeys || (hasKeys = true);
    +        break;
    +      case 'slaveOk':
    +        if (typeof o.server.slave_ok === 'undefined') {
    +          o.server.slave_ok = opts[name];
    +        }
    +        break;
    +      case 'autoReconnect':
    +        if (typeof o.server.auto_reconnect === 'undefined') {
    +          o.server.auto_reconnect = opts[name];
    +        }
    +        break;
    +      case 'socketTimeoutMS':
    +      case 'connectTimeoutMS':
    +        if (typeof o.server.socketOptions[name] === 'undefined') {
    +          o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];
    +        }
    +        break;
    +      case 'authdb':
    +        if (typeof o.auth.authdb === 'undefined') {
    +          o.auth.authdb = opts[name];
    +        }
    +        break;
    +      case 'authSource':
    +        if (typeof o.auth.authSource === 'undefined') {
    +          o.auth.authSource = opts[name];
    +        }
    +        break;
    +      case 'authMechanism':
    +        if (typeof o.auth.authMechanism === 'undefined') {
    +          o.auth.authMechanism = opts[name];
    +        }
    +        break;
    +      case 'retries':
    +      case 'reconnectWait':
    +      case 'rs_name':
    +        if (typeof o.replset[name] === 'undefined') {
    +          o.replset[name] = opts[name];
    +        }
    +        break;
    +      case 'replicaSet':
    +        if (typeof o.replset.rs_name === 'undefined') {
    +          o.replset.rs_name = opts[name];
    +        }
    +        break;
    +      case 'readSecondary':
    +        if (typeof o.replset.read_secondary === 'undefined') {
    +          o.replset.read_secondary = opts[name];
    +        }
    +        break;
    +      case 'nativeParser':
    +        if (typeof o.db.native_parser === 'undefined') {
    +          o.db.native_parser = opts[name];
    +        }
    +        break;
    +      case 'w':
    +      case 'safe':
    +      case 'fsync':
    +      case 'journal':
    +      case 'wtimeoutMS':
    +        if (typeof o.db[name] === 'undefined') {
    +          o.db[name] = opts[name];
    +        }
    +        break;
    +      case 'readPreference':
    +        if (typeof o.db.readPreference === 'undefined') {
    +          o.db.readPreference = opts[name];
    +        }
    +        break;
    +      case 'readPreferenceTags':
    +        if (typeof o.db.read_preference_tags === 'undefined') {
    +          o.db.read_preference_tags = opts[name];
    +        }
    +        break;
    +      case 'sslValidate':
    +        o.server.sslValidate = opts.sslValidate;
    +        o.replset.sslValidate = opts.sslValidate;
    +        o.mongos && (o.mongos.sslValidate = opts.sslValidate);
         }
    +  });
    +
    +  if (!('auto_reconnect' in o.server)) {
    +    o.server.auto_reconnect = true;
       }
     
    -  return hasKeys && paths;
    -};

    Parameters:

    Returns:


    Model#_populate(schema, oid, query, fn)

    Populates an object

    show code
    Model.prototype._populate = function populate (schema, oid, query, fn) {
    -  if (!Array.isArray(oid)) {
    -    var conditions = query.conditions || {};
    -    conditions._id = oid;
    +  // mongoose creates its own ObjectIds
    +  o.db.forceServerObjectId = false;
     
    -    return this
    -    .db.model(query.model || schema.options.ref)
    -    .findOne(conditions, query.fields, query.options, fn);
    +  // default safe using new nomenclature
    +  if (!('journal' in o.db || 'j' in o.db ||
    +        'fsync' in o.db || 'safe' in o.db || 'w' in o.db)) {
    +    o.db.w = 1;
       }
     
    -  if (!oid.length) {
    -    return fn(null, oid);
    +  if (o.promiseLibrary) {
    +    o.db.promiseLibrary = o.promiseLibrary;
       }
     
    -  var model = this.db.model(query.model || schema.caster.options.ref)
    -    , conditions = query && query.conditions || {};
    -
    -  conditions._id || (conditions._id = { $in: oid });
    -
    -  model.find(conditions, query.fields, query.options, function (err, docs) {
    -    if (err) return fn(err);
    -
    -    // user specified sort order?
    -    if (query.options && query.options.sort) {
    -      return fn(null, docs);
    -    }
    -
    -    // put back in original id order (using a hash reduces complexity from n*n to 2n)
    -    var docHash = {};
    -    docs.forEach(function (doc) {
    -      docHash[doc._id] = doc;
    -    });
    -
    -    var arr = [];
    -    oid.forEach(function (id) {
    -      if (id in docHash) arr.push(docHash[id]);
    -    });
    -
    -    fn(null, arr);
    -  });
    -};

    Parameters:

    • schema <SchemaType> type for the oid
    • oid <Object> object id or array of object ids
    • query <Object> object specifying query conditions, fields, and options
    • fn <Function>

    Model#init(doc, query, fn)

    Performs auto-population of relations.

    show code
    Model.prototype.init = function init (doc, query, fn) {
    -  if ('function' == typeof query) {
    -    fn = query;
    -    query = null;
    +  validate(o);
    +  return o;
    +};

    NativeConnection#useDb(name)

    Switches to a different database using the same connection pool.

    Parameters:

    • name <String> The database name

    Returns:

    Returns a new connection object, with the new db.

    show code
    NativeConnection.prototype.useDb = function(name) {
    +  // we have to manually copy all of the attributes...
    +  var newConn = new this.constructor();
    +  newConn.name = name;
    +  newConn.base = this.base;
    +  newConn.collections = {};
    +  newConn.models = {};
    +  newConn.replica = this.replica;
    +  newConn.hosts = this.hosts;
    +  newConn.host = this.host;
    +  newConn.port = this.port;
    +  newConn.user = this.user;
    +  newConn.pass = this.pass;
    +  newConn.options = this.options;
    +  newConn._readyState = this._readyState;
    +  newConn._closeCalled = this._closeCalled;
    +  newConn._hasOpened = this._hasOpened;
    +  newConn._listening = false;
    +
    +  // First, when we create another db object, we are not guaranteed to have a
    +  // db object to work with. So, in the case where we have a db object and it
    +  // is connected, we can just proceed with setting everything up. However, if
    +  // we do not have a db or the state is not connected, then we need to wait on
    +  // the 'open' event of the connection before doing the rest of the setup
    +  // the 'connected' event is the first time we'll have access to the db object
    +
    +  var _this = this;
    +
    +  if (this.db && this._readyState === STATES.connected) {
    +    wireup();
    +  } else {
    +    this.once('connected', wireup);
       }
     
    -  var populate = this._getPopulationKeys(query);
    -
    -  if (!populate) {
    -    return Document.prototype.init.call(this, doc, fn);
    +  function wireup() {
    +    newConn.db = _this.db.db(name);
    +    newConn.onOpen();
    +    // setup the events appropriately
    +    listen(newConn);
       }
     
    -  // population from other models is necessary
    -  var self = this;
    -
    -  init(doc, '', function (err) {
    -    if (err) return fn(err);
    -    Document.prototype.init.call(self, doc, fn);
    -  });
    -
    -  return this;
    -
    -  function init (obj, prefix, fn) {
    -    prefix = prefix || '';
    -
    -    var keys = Object.keys(obj)
    -      , len = keys.length;
    -
    -    return next();
    -
    -    function next () {
    -      if (--len < 0) return fn();
    -
    -      var i = keys[len]
    -        , path = prefix + i
    -        , schema = self.schema.path(path)
    -        , total = 0
    -        , inline = false
    -        , poppath
    -
    -      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
    -        // assume nested object
    -        return init(obj[i], path + '.', next);
    -      }
    +  newConn.name = name;
     
    -      if (!(obj[i] && schema && populate[path])) return next();
    +  // push onto the otherDbs stack, this is used when state changes
    +  this.otherDbs.push(newConn);
    +  newConn.otherDbs.push(this);
     
    -      // this query object is re-used and passed around. we clone
    -      // it to prevent query condition contamination between
    -      // one populate call to the next.
    -      poppath = utils.clone(populate[path]);
    +  return newConn;
    +};

    NativeConnection.STATES

    Expose the possible connection states.

    show code
    NativeConnection.STATES = STATES;

  • error/version.js

    VersionError()

    Version Error constructor.

    Inherits:

    show code
    function VersionError(doc) {
    +  MongooseError.call(this, 'No matching document found for id "' + doc._id +
    +    '"');
    +  this.name = 'VersionError';
    +}

  • error/messages.js

    MongooseError.messages()

    The default built-in validator error messages. These may be customized.

    show code
    var msg = module.exports = exports = {};
     
    -      if (poppath.sub) {
    -        obj[i].forEach(function (subobj) {
    -          inline = true;
    +msg.DocumentNotFoundError = null;
     
    -          var pkeys = Object.keys(poppath.sub)
    -            , pi = pkeys.length
    -            , key
    +msg.general = {};
    +msg.general.default = 'Validator failed for path `{PATH}` with value `{VALUE}`';
    +msg.general.required = 'Path `{PATH}` is required.';
     
    -          while (pi--) {
    -            key = pkeys[pi];
    +msg.Number = {};
    +msg.Number.min = 'Path `{PATH}` ({VALUE}) is less than minimum allowed value ({MIN}).';
    +msg.Number.max = 'Path `{PATH}` ({VALUE}) is more than maximum allowed value ({MAX}).';
     
    -            if (subobj[key]) (function (key) {
    -              total++;
    -              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
    -              function done (err, doc) {
    -                if (err) return error(err);
    -                subobj[key] = doc;
    -                if (--total < 1 && !inline) {
    -                  next();
    -                }
    -              }
    -            })(key);
    -          }
    -        });
    +msg.Date = {};
    +msg.Date.min = 'Path `{PATH}` ({VALUE}) is before minimum allowed value ({MIN}).';
    +msg.Date.max = 'Path `{PATH}` ({VALUE}) is after maximum allowed value ({MAX}).';
     
    -        inline = false;
    +msg.String = {};
    +msg.String.enum = '`{VALUE}` is not a valid enum value for path `{PATH}`.';
    +msg.String.match = 'Path `{PATH}` is invalid ({VALUE}).';
    +msg.String.minlength = 'Path `{PATH}` (`{VALUE}`) is shorter than the minimum allowed length ({MINLENGTH}).';
    +msg.String.maxlength = 'Path `{PATH}` (`{VALUE}`) is longer than the maximum allowed length ({MAXLENGTH}).';
    // customize within each schema or globally like so
    +var mongoose = require('mongoose');
    +mongoose.Error.messages.String.enum  = "Your custom message for {PATH}.";
    - if (0 === total) return next(); +

    As you might have noticed, error messages support basic templating

    - } else { - self._populate(schema, obj[i], poppath, function (err, doc) { - if (err) return error(err); - obj[i] = doc; - next(); - }); - } - }; - }; +
      +
    • {PATH} is replaced with the invalid document path
    • +
    • {VALUE} is replaced with the invalid value
    • +
    • {TYPE} is replaced with the validator type such as "regexp", "min", or "user defined"
    • +
    • {MIN} is replaced with the declared min value for the Number.min validator
    • +
    • {MAX} is replaced with the declared max value for the Number.max validator
    • +
    - function error (err) { - if (error.err) return; - fn(error.err = err); +

    Click the "show code" link below to see all defaults.


  • error/disconnected.js

    DisconnectedError(type, value)

    Casting Error constructor.

    Parameters:

    Inherits:

    show code
    function DisconnectedError(connectionString) {
    +  MongooseError.call(this, 'Ran out of retries trying to reconnect to "' +
    +    connectionString + '". Try setting `server.reconnectTries` and ' +
    +    '`server.reconnectInterval` to something higher.');
    +  this.name = 'DisconnectedError';
    +  if (Error.captureStackTrace) {
    +    Error.captureStackTrace(this);
    +  } else {
    +    this.stack = new Error().stack;
       }
    -};

    Parameters:

    • doc <Object> document returned by mongo
    • query <Query> query that originated the initialization
    • fn <Function>

    Model#save([fn])

    Saves this document.

    show code
    Model.prototype.save = function save (fn) {
    -  var promise = new Promise(fn)
    -    , complete = handleSave(promise, this)
    -    , options = {}
    -
    -  if (this.schema.options.safe) {
    -    options.safe = this.schema.options.safe;
    +}

  • error/strict.js

    StrictModeError(type, value)

    Strict mode error constructor

    Parameters:

    Inherits:

    show code
    function StrictModeError(path, msg) {
    +  msg = msg || 'Field `' + path + '` is not in schema and strict ' +
    +    'mode is set to throw.';
    +  MongooseError.call(this, msg);
    +  this.name = 'StrictModeError';
    +  if (Error.captureStackTrace) {
    +    Error.captureStackTrace(this);
    +  } else {
    +    this.stack = new Error().stack;
       }
    -
    -  if (this.isNew) {
    -    // send entire doc
    -    var obj = this.toObject({ depopulate: 1 });
    -    this._version(true, obj);
    -    this.collection.insert(obj, options, complete);
    -    this._reset();
    -    this.isNew = false;
    -    this.emit('isNew', false);
    -    // Make it possible to retry the insert
    -    this._inserting = true;
    -
    +  this.path = path;
    +}

  • error/validation.js

    ValidationError#toString()

    Console.log helper

    show code
    ValidationError.prototype.toString = function() {
    +  return this.name + ': ' + _generateMessage(this);
    +};

    ValidationError(instance)

    Document Validation Error

    Parameters:

    Inherits:

    show code
    function ValidationError(instance) {
    +  this.errors = {};
    +  this._message = '';
    +  if (instance && instance.constructor.name === 'model') {
    +    this._message = instance.constructor.modelName + ' validation failed';
    +    MongooseError.call(this, this._message);
       } else {
    -    // Make sure we don't treat it as a new object on error,
    -    // since it already exists
    -    this._inserting = false;
    -
    -    var delta = this._delta();
    -    if (delta) {
    -      var where = this._where(delta[0]);
    -      this.collection.update(where, delta[1], options, complete);
    -    } else {
    -      process.nextTick(function () {
    -        complete(null);
    -      })
    -    }
    -
    -    this._reset();
    -    this.emit('isNew', false);
    +    this._message = 'Validation failed';
    +    MongooseError.call(this, this._message);
    +  }
    +  this.name = 'ValidationError';
    +  if (Error.captureStackTrace) {
    +    Error.captureStackTrace(this);
    +  } else {
    +    this.stack = new Error().stack;
    +  }
    +  if (instance) {
    +    instance.errors = this.errors;
    +  }
    +}

  • error/cast.js

    CastError(type, value)

    Casting Error constructor.

    Parameters:

    Inherits:

    show code
    function CastError(type, value, path, reason) {
    +  var stringValue = util.inspect(value);
    +  stringValue = stringValue.replace(/^'/, '"').replace(/'$/, '"');
    +  if (stringValue.charAt(0) !== '"') {
    +    stringValue = '"' + stringValue + '"';
    +  }
    +  MongooseError.call(this, 'Cast to ' + type + ' failed for value ' +
    +    stringValue + ' at path "' + path + '"');
    +  this.name = 'CastError';
    +  if (Error.captureStackTrace) {
    +    Error.captureStackTrace(this);
    +  } else {
    +    this.stack = new Error().stack;
    +  }
    +  this.stringValue = stringValue;
    +  this.kind = type;
    +  this.value = value;
    +  this.path = path;
    +  this.reason = reason;
    +}

  • error/validator.js

    ValidatorError(properties)

    Schema validator error

    Parameters:

    Inherits:

    show code
    function ValidatorError(properties) {
    +  var msg = properties.message;
    +  if (!msg) {
    +    msg = MongooseError.messages.general.default;
       }
    -};

    Parameters:

    Example:

    - -
    product.sold = Date.now();
    -product.save(function (err, product) {
    -  if (err) ..
    -})
    - -

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    -
    var db = mongoose.createConnection(..);
    -var schema = new Schema(..);
    -var Product = db.model('Product', schema);
    +  var message = this.formatMessage(msg, properties);
    +  MongooseError.call(this, message);
    +  this.name = 'ValidatorError';
    +  if (Error.captureStackTrace) {
    +    Error.captureStackTrace(this);
    +  } else {
    +    this.stack = new Error().stack;
    +  }
    +  this.properties = properties;
    +  this.kind = properties.type;
    +  this.path = properties.path;
    +  this.value = properties.value;
    +  this.reason = properties.reason;
    +}

  • error/objectExpected.js

    ObjectExpectedError(type, value)

    Strict mode error constructor

    Parameters:

    Inherits:

    show code
    function ObjectExpectedError(path, val) {
    +  MongooseError.call(this, 'Tried to set nested object field `' + path +
    +    '` to primitive value `' + val + '` and strict mode is set to throw.');
    +  this.name = 'ObjectExpectedError';
    +  if (Error.captureStackTrace) {
    +    Error.captureStackTrace(this);
    +  } else {
    +    this.stack = new Error().stack;
    +  }
    +  this.path = path;
    +}

  • error.js

    MongooseError(msg)

    MongooseError constructor

    Parameters:

    Inherits:

    show code
    function MongooseError(msg) {
    +  Error.call(this);
    +  if (Error.captureStackTrace) {
    +    Error.captureStackTrace(this);
    +  } else {
    +    this.stack = new Error().stack;
    +  }
    +  this.message = msg;
    +  this.name = 'MongooseError';
    +}

    MongooseError.DocumentNotFoundError

    This error will be called when save() fails because the underlying
    document was not found. The constructor takes one parameter, the
    conditions that mongoose passed to update() when trying to update
    the document.

    show code
    MongooseError.DocumentNotFoundError = require('./error/notFound');

    MongooseError.messages

    The default built-in validator error messages.

    show code
    MongooseError.messages = require('./error/messages');
     
    -db.on('error', handleError);
    +// backward compat +MongooseError.Messages = MongooseError.messages;

  • virtualtype.js

    VirtualType#applyGetters(value, scope)

    Applies getters to value using optional scope.

    Parameters:

    Returns:

    • <T> the value after applying all getters
    show code
    VirtualType.prototype.applyGetters = function(value, scope) {
    +  var v = value;
    +  for (var l = this.getters.length - 1; l >= 0; l--) {
    +    v = this.getters[l].call(scope, v, this);
    +  }
    +  return v;
    +};

    VirtualType#applySetters(value, scope)

    Applies setters to value using optional scope.

    Parameters:

    Returns:

    • <T> the value after applying all setters
    show code
    VirtualType.prototype.applySetters = function(value, scope) {
    +  var v = value;
    +  for (var l = this.setters.length - 1; l >= 0; l--) {
    +    v = this.setters[l].call(scope, v, this);
    +  }
    +  return v;
    +};

    VirtualType#get(fn)

    Defines a getter.

    Parameters:

    Returns:

    Example:

    -

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    +
    var virtual = schema.virtual('fullname');
    +virtual.get(function () {
    +  return this.name.first + ' ' + this.name.last;
    +});
    show code
    VirtualType.prototype.get = function(fn) {
    +  this.getters.push(fn);
    +  return this;
    +};

    VirtualType#set(fn)

    Defines a setter.

    Parameters:

    Returns:

    Example:

    -
    Product.on('error', handleError);

    Model#_delta()

    Produces a special query document of the modified properties used in updates.

    show code
    Model.prototype._delta = function _delta () {
    -  var dirty = this._dirty();
    -  if (!dirty.length) return;
    +
    var virtual = schema.virtual('fullname');
    +virtual.set(function (v) {
    +  var parts = v.split(' ');
    +  this.name.first = parts[0];
    +  this.name.last = parts[1];
    +});
    show code
    VirtualType.prototype.set = function(fn) {
    +  this.setters.push(fn);
    +  return this;
    +};

    VirtualType()

    VirtualType constructor

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    - var self = this - , where = {} - , delta = {} - , len = dirty.length - , d = 0 - , val - , obj +

    Example:

    - for (; d < len; ++d) { - var data = dirty[d] - var value = data.value - var schema = data.schema +
    var fullname = schema.virtual('fullname');
    +fullname instanceof mongoose.VirtualType // true
    show code
    function VirtualType(options, name) {
    +  this.path = name;
    +  this.getters = [];
    +  this.setters = [];
    +  this.options = options || {};
    +}

  • document_provider.js

    module.exports()

    Returns the Document constructor for the current context

    show code
    module.exports = function() {
    +  if (isBrowser) {
    +    return BrowserDocument;
    +  }
    +  return Document;
    +};

  • schema.js

    Schema#add(obj, prefix)

    Adds key path / schema type pairs to this schema.

    Parameters:

    Example:

    - if (undefined === value) { - operand(self, where, delta, data, 1, '$unset'); +
    var ToySchema = new Schema;
    +ToySchema.add({ name: 'string', color: 'string', price: 'number' });
    show code
    Schema.prototype.add = function add(obj, prefix) {
    +  prefix = prefix || '';
    +  var keys = Object.keys(obj);
     
    -    } else if (null === value) {
    -      operand(self, where, delta, data, null);
    +  for (var i = 0; i < keys.length; ++i) {
    +    var key = keys[i];
     
    -    } else if (value._path && value._atomics) {
    -      handleAtomics(self, where, delta, data, value);
    +    if (obj[key] == null) {
    +      throw new TypeError('Invalid value for schema path `' + prefix + key + '`');
    +    }
     
    -    } else if (value._path && Buffer.isBuffer(value)) {
    -      // MongooseBuffer
    -      value = value.toObject();
    -      operand(self, where, delta, data, value);
    +    if (Array.isArray(obj[key]) && obj[key].length === 1 && obj[key][0] == null) {
    +      throw new TypeError('Invalid value for schema Array path `' + prefix + key + '`');
    +    }
     
    +    if (utils.isObject(obj[key]) &&
    +        (!obj[key].constructor || utils.getFunctionName(obj[key].constructor) === 'Object') &&
    +        (!obj[key][this.options.typeKey] || (this.options.typeKey === 'type' && obj[key].type.type))) {
    +      if (Object.keys(obj[key]).length) {
    +        // nested object { last: { name: String }}
    +        this.nested[prefix + key] = true;
    +        this.add(obj[key], prefix + key + '.');
    +      } else {
    +        if (prefix) {
    +          this.nested[prefix.substr(0, prefix.length - 1)] = true;
    +        }
    +        this.path(prefix + key, obj[key]); // mixed type
    +      }
         } else {
    -      value = utils.clone(value);
    -      operand(self, where, delta, data, value);
    +      if (prefix) {
    +        this.nested[prefix.substr(0, prefix.length - 1)] = true;
    +      }
    +      this.path(prefix + key, obj[key]);
         }
       }
    -
    -  if (this.__version) {
    -    this._version(where, delta);
    +};

    Schema#clone()

    Returns a deep copy of the schema

    Returns:

    show code
    Schema.prototype.clone = function() {
    +  var s = new Schema(this.obj, this.options);
    +  // Clone the call queue
    +  s.callQueue = this.callQueue.map(function(f) { return f; });
    +  s.methods = utils.clone(this.methods);
    +  s.statics = utils.clone(this.statics);
    +  s.plugins = Array.prototype.slice.call(this.plugins);
    +  s._indexes = utils.clone(this._indexes);
    +  s.s.hooks = this.s.hooks.clone();
    +  return s;
    +};

    Schema#defaultOptions(options)

    Returns default options for this schema, merged with options.

    Parameters:

    Returns:

    show code
    Schema.prototype.defaultOptions = function(options) {
    +  if (options && options.safe === false) {
    +    options.safe = {w: 0};
       }
     
    -  return [where, delta];
    -}

    Model#_version()

    Appends versioning to the where and update clauses.

    show code
    Model.prototype._version = function _version (where, delta) {
    -  var key = this.schema.options.versionKey;
    -
    -  if (true === where) {
    -    // this is an insert
    -    if (key) this.setValue(key, delta[key] = 0);
    -    return;
    +  if (options && options.safe && options.safe.w === 0) {
    +    // if you turn off safe writes, then versioning goes off as well
    +    options.versionKey = false;
       }
     
    -  // updates
    +  options = utils.options({
    +    strict: true,
    +    bufferCommands: true,
    +    capped: false, // { size, max, autoIndexId }
    +    versionKey: '__v',
    +    discriminatorKey: '__t',
    +    minimize: true,
    +    autoIndex: null,
    +    shardKey: null,
    +    read: null,
    +    validateBeforeSave: true,
    +    // the following are only applied at construction time
    +    noId: false, // deprecated, use { _id: false }
    +    _id: true,
    +    noVirtualId: false, // deprecated, use { id: false }
    +    id: true,
    +    typeKey: 'type',
    +    retainKeyOrder: false
    +  }, options);
     
    -  // only apply versioning if our versionKey was selected. else
    -  // there is no way to select the correct version. we could fail
    -  // fast here and force them to include the versionKey but
    -  // thats a bit intrusive. can we do this automatically?
    -  // TODO fail fast option?
    -  if (!this.isSelected(key)) {
    -    return;
    +  if (options.read) {
    +    options.read = readPref(options.read);
       }
     
    -  // $push $addToSet don't need the where clause set
    -  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
    -    where[key] = this.getValue(key);
    -  }
    +  return options;
    +};

    Schema#eachPath(fn)

    Iterates the schemas paths similar to Array#forEach.

    Parameters:

    Returns:

    The callback is passed the pathname and schemaType as arguments on each iteration.

    show code
    Schema.prototype.eachPath = function(fn) {
    +  var keys = Object.keys(this.paths),
    +      len = keys.length;
     
    -  if (VERSION_INC === (VERSION_INC & this.__version)) {
    -    delta.$inc || (delta.$inc = {});
    -    delta.$inc[key] = 1;
    +  for (var i = 0; i < len; ++i) {
    +    fn(keys[i], this.paths[keys[i]]);
       }
    -}

    Model#increment()

    Signal that we desire an increment of this documents version.

    show code
    Model.prototype.increment = function increment () {
    -  this.__version = VERSION_ALL;
    -  return this;
    -}

    Model#_where()

    Returns a query object which applies shardkeys if they exist.

    show code
    Model.prototype._where = function _where (where) {
    -  where || (where = {});
    -
    -  var paths
    -    , len
    -
    -  if (this._shardval) {
    -    paths = Object.keys(this._shardval)
    -    len = paths.length
     
    -    for (var i = 0; i < len; ++i) {
    -      where[paths[i]] = this._shardval[paths[i]];
    +  return this;
    +};

    Schema#get(key)

    Gets a schema option.

    Parameters:

    show code
    Schema.prototype.get = function(key) {
    +  return this.options[key];
    +};

    Schema#hasMixedParent(path)

    Returns true iff this path is a child of a mixed schema.

    Parameters:

    Returns:

    show code
    Schema.prototype.hasMixedParent = function(path) {
    +  var subpaths = path.split(/\./g);
    +  path = '';
    +  for (var i = 0; i < subpaths.length; ++i) {
    +    path = i > 0 ? path + '.' + subpaths[i] : subpaths[i];
    +    if (path in this.paths &&
    +        this.paths[path] instanceof MongooseTypes.Mixed) {
    +      return true;
         }
       }
     
    -  where._id = this._doc._id;
    -  return where;
    -}

    Model#remove([fn])

    Removes this document from the db.

    show code
    Model.prototype.remove = function remove (fn) {
    -  if (this._removing) return this;
    +  return false;
    +};

    Schema#index(fields, [options], [options.expires=null])

    Defines an index (most likely compound) for this schema.

    Parameters:

    Example

    - var promise = this._removing = new Promise(fn) - , where = this._where() - , self = this - , options = {} +
    schema.index({ first: 1, last: -1 })
    show code
    Schema.prototype.index = function(fields, options) {
    +  options || (options = {});
     
    -  if (this.schema.options.safe) {
    -    options.safe = this.schema.options.safe;
    +  if (options.expires) {
    +    utils.expires(options);
       }
     
    -  this.collection.remove(where, options, tick(function (err) {
    -    if (err) {
    -      promise.error(err);
    -      promise = self = self._removing = where = options = null;
    +  this._indexes.push([fields, options]);
    +  return this;
    +};

    Schema#indexedPaths()

    Returns indexes from fields and schema-level indexes (cached).

    Returns:

    show code
    Schema.prototype.indexedPaths = function indexedPaths() {
    +  if (this._indexedpaths) {
    +    return this._indexedpaths;
    +  }
    +  this._indexedpaths = this.indexes();
    +  return this._indexedpaths;
    +};

    Schema#indexes()

    Compiles indexes from fields and schema-level indexes

    show code
    Schema.prototype.indexes = function() {
    +  'use strict';
    +
    +  var indexes = [];
    +  var schemaStack = [];
    +
    +  var collectIndexes = function(schema, prefix) {
    +    // Ignore infinitely nested schemas, if we've already seen this schema
    +    // along this path there must be a cycle
    +    if (schemaStack.indexOf(schema) !== -1) {
           return;
         }
    -    self.emit('remove', self);
    -    promise.complete();
    -    promise = self = where = options = null;
    -  }));
    -
    -  return this;
    -};

    Parameters:

    Example:

    - -
    product.remove(function (err, product) {
    -  if (err) return handleError(err);
    -  Product.findById(product._id, function (err, product) {
    -    console.log(product) // null
    -  })
    -})

    Model#_registerHooks()

    Register hooks override

    show code
    Model.prototype._registerHooks = function registerHooks () {
    -  Document.prototype._registerHooks.call(this);
    -};

    Model#model(name)

    Returns another Model instance.

    show code
    Model.prototype.model = function model (name) {
    -  return this.db.model(name);
    -};

    Parameters:

    Example:

    - -
    var doc = new Tank;
    -doc.model('User').findById(id, callback);

    Model#$where(argument)

    Creates a Query and specifies a $where condition.

    Parameters:

    • argument <String, Function> is a javascript string or anonymous function

    Returns:

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    + schemaStack.push(schema); -
    Blog.$where('this.comments.length &gt; 5');

    Model.init()

    Called when the model compiles.

    show code
    Model.init = function init () {
    -  if (this.schema.options.autoIndex)
    -    this.ensureIndexes();
    +    prefix = prefix || '';
    +    var key, path, index, field, isObject, options, type;
    +    var keys = Object.keys(schema.paths);
     
    -  this.schema.emit('init', this);
    -};

    Model.ensureIndexes([cb])

    Sends ensureIndex commands to mongo for each index declared in the schema.

    show code
    Model.ensureIndexes = function ensureIndexes (cb) {
    -  var indexes = this.schema.indexes();
    -  if (!indexes.length) {
    -    return cb && cb();
    -  }
    +    for (var i = 0; i < keys.length; ++i) {
    +      key = keys[i];
    +      path = schema.paths[key];
     
    -  var self = this
    -    , safe = self.schema.options.safe
    -    , count = indexes.length
    -    , error
    +      if ((path instanceof MongooseTypes.DocumentArray) || path.$isSingleNested) {
    +        collectIndexes(path.schema, prefix + key + '.');
    +      } else {
    +        index = path._index || (path.caster && path.caster._index);
    +
    +        if (index !== false && index !== null && index !== undefined) {
    +          field = {};
    +          isObject = utils.isObject(index);
    +          options = isObject ? index : {};
    +          type = typeof index === 'string' ? index :
    +              isObject ? index.type :
    +                  false;
    +
    +          if (type && ~Schema.indexTypes.indexOf(type)) {
    +            field[prefix + key] = type;
    +          } else if (options.text) {
    +            field[prefix + key] = 'text';
    +            delete options.text;
    +          } else {
    +            field[prefix + key] = 1;
    +          }
     
    -  indexes.forEach(function (index) {
    -    var options = index[1];
    -    options.safe = safe;
    -    self.collection.ensureIndex(index[0], options, tick(function (err) {
    -      if (err) error = err;
    -      if (--count) return;
    +          delete options.type;
    +          if (!('background' in options)) {
    +            options.background = true;
    +          }
     
    -      self.emit('index', error);
    -      cb && cb(error);
    -    }));
    -  });
    -}

    Parameters:

    After completion, an index event is emitted on this Model passing an error if one occurred.

    + indexes.push([field, options]); + } + } + } -

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    + schemaStack.pop(); -

    Example:

    + if (prefix) { + fixSubIndexPaths(schema, prefix); + } else { + schema._indexes.forEach(function(index) { + if (!('background' in index[1])) { + index[1].background = true; + } + }); + indexes = indexes.concat(schema._indexes); + } + }; -
    Event.ensureIndexes(function (err) {
    -  if (err) return handleError(err);
    -});

    Model.remove(conditions, [callback])

    Removes documents from the collection.

    show code
    Model.remove = function remove (conditions, callback) {
    -  if ('function' === typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    +  collectIndexes(this);
    +  return indexes;

    Schema#loadClass(model)

    Loads an ES6 class into a schema. Maps setters + getters, static methods, and instance methods to schema virtuals, statics, and methods.

    Parameters:

    show code
    Schema.prototype.loadClass = function(model, virtualsOnly) {
    +  if (model === Object.prototype ||
    +      model === Function.prototype ||
    +      model.prototype.hasOwnProperty('$isMongooseModelPrototype')) {
    +    return this;
       }
     
    -  var query = new Query(conditions).bind(this, 'remove');
    -
    -  if ('undefined' === typeof callback)
    -    return query;
    -
    -  this._applyNamedScope(query);
    -  return query.remove(callback);
    -};

    Parameters:

    Returns:

    Note:

    + this.loadClass(Object.getPrototypeOf(model)); -

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    - -
    Comment.remove({ _id: id }).exec();

    Model.find(conditions, [fields], [options], [callback])

    Finds documents

    show code
    Model.find = function find (conditions, fields, options, callback) {
    -  if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof fields) {
    -    callback = fields;
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof options) {
    -    callback = options;
    -    options = null;
    +  // Add static methods
    +  if (!virtualsOnly) {
    +    Object.getOwnPropertyNames(model).forEach(function(name) {
    +      if (name.match(/^(length|name|prototype)$/)) {
    +        return;
    +      }
    +      var method = Object.getOwnPropertyDescriptor(model, name);
    +      if (typeof method.value === 'function') {
    +        this.static(name, method.value);
    +      }
    +    }, this);
       }
     
    -  var query = new Query(conditions, options);
    -  query.bind(this, 'find');
    -  query.select(fields);
    +  // Add methods and virtuals
    +  Object.getOwnPropertyNames(model.prototype).forEach(function(name) {
    +    if (name.match(/^(constructor)$/)) {
    +      return;
    +    }
    +    var method = Object.getOwnPropertyDescriptor(model.prototype, name);
    +    if (!virtualsOnly) {
    +      if (typeof method.value === 'function') {
    +        this.method(name, method.value);
    +      }
    +    }
    +    if (typeof method.get === 'function') {
    +      this.virtual(name).get(method.get);
    +    }
    +    if (typeof method.set === 'function') {
    +      this.virtual(name).set(method.set);
    +    }
    +  }, this);
     
    -  if ('undefined' === typeof callback)
    -    return query;
    +  return this;
    +};

    Schema#method(method, [fn])

    Adds an instance method to documents constructed from Models compiled from this schema.

    Parameters:

    Example

    - this._applyNamedScope(query); - return query.find(callback); -};

    Parameters:

    Returns:

    Examples:

    +
    var schema = kittySchema = new Schema(..);
     
    -
    // retrieve only certain keys
    -MyModel.find({ name: /john/i }, 'name friends', function () { })
    +schema.method('meow', function () {
    +  console.log('meeeeeoooooooooooow');
    +})
     
    -// pass options
    -MyModel.find({ name: /john/i }, null, { skip: 10 } )

    Model._applyNamedScope(query)

    Merges the current named scope query into query.

    show code
    Model._applyNamedScope = function _applyNamedScope (query) {
    -  var cQuery = this._cumulativeQuery;
    +var Kitty = mongoose.model('Kitty', schema);
     
    -  if (cQuery) {
    -    merge(query._conditions, cQuery._conditions);
    -    if (query._fields && cQuery._fields)
    -      merge(query._fields, cQuery._fields);
    -    if (query.options && cQuery.options)
    -      merge(query.options, cQuery.options);
    -    delete this._cumulativeQuery;
    -  }
    +var fizz = new Kitty;
    +fizz.meow(); // meeeeeooooooooooooow
    - return query; -}

    Parameters:

    Returns:


    Model.findById(id, [fields], [options], [callback])

    Finds a single document by id.

    show code
    Model.findById = function findById (id, fields, options, callback) {
    -  return this.findOne({ _id: id }, fields, options, callback);
    -};

    Parameters:

    Returns:

    The id is cast to an ObjectId before sending the command.

    +

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    -

    Example:

    +
    schema.method({
    +    purr: function () {}
    +  , scratch: function () {}
    +});
     
    -
    Adventure.findById(id, callback);

    Model.findOne(conditions, [fields], [options], [callback])

    Finds one document.

    show code
    Model.findOne = function findOne (conditions, fields, options, callback) {
    -  if ('function' == typeof options) {
    -    // TODO Handle all 3 of the following scenarios
    -    // Hint: Only some of these scenarios are possible if cQuery is present
    -    // Scenario: findOne(conditions, fields, callback);
    -    // Scenario: findOne(fields, options, callback);
    -    // Scenario: findOne(conditions, options, callback);
    -    callback = options;
    -    options = null;
    -  } else if ('function' == typeof fields) {
    -    // TODO Handle all 2 of the following scenarios
    -    // Scenario: findOne(conditions, callback)
    -    // Scenario: findOne(fields, callback)
    -    // Scenario: findOne(options, callback);
    -    callback = fields;
    -    fields = null;
    -    options = null;
    -  } else if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = {};
    -    fields = null;
    -    options = null;
    +// later
    +fizz.purr();
    +fizz.scratch();
    show code
    Schema.prototype.method = function(name, fn) {
    +  if (typeof name !== 'string') {
    +    for (var i in name) {
    +      this.methods[i] = name[i];
    +    }
    +  } else {
    +    this.methods[name] = fn;
       }
    +  return this;
    +};

    Schema#path(path, constructor)

    Gets/sets schema paths.

    Parameters:

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    - var query = new Query(conditions, options).select(fields).bind(this, 'findOne'); - - if ('undefined' == typeof callback) - return query; +

    Example

    - this._applyNamedScope(query); - return query.findOne(callback); -};

    Parameters:

    Returns:

    The conditions are cast to their respective SchemaTypes before the command is sent.

    +
    schema.path('name') // returns a SchemaType
    +schema.path('name', Number) // changes the schemaType of `name` to Number
    show code
    Schema.prototype.path = function(path, obj) {
    +  if (obj === undefined) {
    +    if (this.paths[path]) {
    +      return this.paths[path];
    +    }
    +    if (this.subpaths[path]) {
    +      return this.subpaths[path];
    +    }
    +    if (this.singleNestedPaths[path]) {
    +      return this.singleNestedPaths[path];
    +    }
     
    -

    Example:

    + // subpaths? + return /\.\d+\.?.*$/.test(path) + ? getPositionalPath(this, path) + : undefined; + } -
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

    Model.count(conditions, [callback])

    Counts number of matching documents in a database collection.

    show code
    Model.count = function count (conditions, callback) {
    -  if ('function' === typeof conditions)
    -    callback = conditions, conditions = {};
    +  // some path names conflict with document methods
    +  if (reserved[path]) {
    +    throw new Error('`' + path + '` may not be used as a schema pathname');
    +  }
     
    -  var query = new Query(conditions).bind(this, 'count');
    -  if ('undefined' == typeof callback)
    -    return query;
    +  if (warnings[path]) {
    +    console.log('WARN: ' + warnings[path]);
    +  }
     
    -  this._applyNamedScope(query);
    -  return query.count(callback);
    -};

    Parameters:

    Returns:

    Example:

    + // update the tree + var subpaths = path.split(/\./), + last = subpaths.pop(), + branch = this.tree; -
    Adventure.count({ type: 'jungle' }, function (err, count) {
    -  if (err) ..
    -  console.log('there are %d jungle adventures', count);
    -});

    Model.distinct(field, [conditions], [callback])

    Executes a DISTINCT command

    show code
    Model.distinct = function distinct (field, conditions, callback) {
    -  var query = new Query(conditions).bind(this, 'distinct');
    -  if ('undefined' == typeof callback) {
    -    query._distinctArg = field;
    -    return query;
    -  }
    -
    -  this._applyNamedScope(query);
    -  return query.distinct(field, callback);
    -};

    Parameters:

    Returns:


    Model.where(path, [val])

    Creates a Query, applies the passed conditions, and returns the Query.

    show code
    Model.where = function where (path, val) {
    -  var q = new Query().bind(this, 'find');
    -  return q.where.apply(q, arguments);
    -};

    Parameters:

    Returns:

    For example, instead of writing:

    + subpaths.forEach(function(sub, i) { + if (!branch[sub]) { + branch[sub] = {}; + } + if (typeof branch[sub] !== 'object') { + var msg = 'Cannot set nested path `' + path + '`. ' + + 'Parent path `' + + subpaths.slice(0, i).concat([sub]).join('.') + + '` already set to type ' + branch[sub].name + + '.'; + throw new Error(msg); + } + branch = branch[sub]; + }); -
    User.find({age: {$gte: 21, $lte: 65}}, callback);
    + branch[last] = utils.clone(obj); -

    we can instead write:

    + this.paths[path] = Schema.interpretAsType(path, obj, this.options); -
    User.where('age').gte(21).lte(65).exec(callback);
    + if (this.paths[path].$isSingleNested) { + for (var key in this.paths[path].schema.paths) { + this.singleNestedPaths[path + '.' + key] = + this.paths[path].schema.paths[key]; + } + for (key in this.paths[path].schema.singleNestedPaths) { + this.singleNestedPaths[path + '.' + key] = + this.paths[path].schema.singleNestedPaths[key]; + } -

    Since the Query class also supports where you can continue chaining

    + this.childSchemas.push({ + schema: this.paths[path].schema, + model: this.paths[path].caster + }); + } else if (this.paths[path].$isMongooseDocumentArray) { + this.childSchemas.push({ + schema: this.paths[path].schema, + model: this.paths[path].casterConstructor + }); + } + return this; +};

    Schema#pathType(path)

    Returns the pathType of path for this schema.

    Parameters:

    Returns:

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    show code
    Schema.prototype.pathType = function(path) {
    +  if (path in this.paths) {
    +    return 'real';
    +  }
    +  if (path in this.virtuals) {
    +    return 'virtual';
    +  }
    +  if (path in this.nested) {
    +    return 'nested';
    +  }
    +  if (path in this.subpaths) {
    +    return 'real';
    +  }
    +  if (path in this.singleNestedPaths) {
    +    return 'real';
    +  }
     
    -
    User
    -.where('age').gte(21).lte(65)
    -.where('name', /^b/i)
    -... etc

    Model.findOneAndUpdate([conditions], [update], [options], [callback])

    Issues a mongodb findAndModify update command.

    show code
    Model.findOneAndUpdate = function (conditions, update, options, callback) {
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = null;
    +  if (/\.\d+\.|\.\d+$/.test(path)) {
    +    return getPositionalPathType(this, path);
    +  }
    +  return 'adhocOrUndefined';
    +};

    Schema#plugin(plugin, [opts])

    Registers a plugin for this schema.

    Parameters:

    show code
    Schema.prototype.plugin = function(fn, opts) {
    +  if (typeof fn !== 'function') {
    +    throw new Error('First param to `schema.plugin()` must be a function, ' +
    +      'got "' + (typeof fn) + '"');
       }
    -  else if (1 === arguments.length) {
    -    if ('function' == typeof conditions) {
    -      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
     
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate(update)
    -'
    -              + '  ' + this.modelName + '.findOneAndUpdate()
    -';
    -      throw new TypeError(msg)
    +  if (opts &&
    +      opts.deduplicate) {
    +    for (var i = 0; i < this.plugins.length; ++i) {
    +      if (this.plugins[i].fn === fn) {
    +        return this;
    +      }
         }
    -    update = conditions;
    -    conditions = undefined;
       }
    +  this.plugins.push({ fn: fn, opts: opts });
     
    -  var fields;
    -  if (options && options.fields) {
    -    fields = options.fields;
    -    options.fields = undefined;
    -  }
    +  fn(this, opts);
    +  return this;
    +};

    Schema#post(method, fn)

    Defines a post hook for the document

    Parameters:

    var schema = new Schema(..);
    +schema.post('save', function (doc) {
    +  console.log('this fired after a document was saved');
    +});
     
    -  var query = new Query(conditions);
    -  query.setOptions(options);
    -  query.select(fields);
    -  query.bind(this, 'findOneAndUpdate', update);
    +schema.post('find', function(docs) {
    +  console.log('this fired after you run a find query');
    +});
     
    -  if ('undefined' == typeof callback)
    -    return query;
    +var Model = mongoose.model('Model', schema);
     
    -  this._applyNamedScope(query);
    -  return query.findOneAndUpdate(callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    +var m = new Model(..); +m.save(function(err) { + console.log('this fires after the `post` hook'); +}); -

    Options:

    +m.find(function(err, docs) { + console.log('this fires after the post find hook'); +});
    show code
    Schema.prototype.post = function(method, fn) {
    +  if (IS_KAREEM_HOOK[method]) {
    +    this.s.hooks.post.apply(this.s.hooks, arguments);
    +    return this;
    +  }
    +  // assuming that all callbacks with arity < 2 are synchronous post hooks
    +  if (fn.length < 2) {
    +    return this.queue('on', [arguments[0], function(doc) {
    +      return fn.call(doc, doc);
    +    }]);
    +  }
    +
    +  if (fn.length === 3) {
    +    this.s.hooks.post(method + ':error', fn);
    +    return this;
    +  }
    +
    +  return this.queue('post', [arguments[0], function(next) {
    +    // wrap original function so that the callback goes last,
    +    // for compatibility with old code that is using synchronous post hooks
    +    var _this = this;
    +    var args = Array.prototype.slice.call(arguments, 1);
    +    fn.call(this, this, function(err) {
    +      return next.apply(_this, [err].concat(args));
    +    });
    +  }]);
    +};

    Schema#pre(method, callback)

    Defines a pre hook for the document.

    Parameters:

    Example

    + +
    var toySchema = new Schema(..);
    +
    +toySchema.pre('save', function (next) {
    +  if (!this.created) this.created = new Date;
    +  next();
    +})
    +
    +toySchema.pre('validate', function (next) {
    +  if (this.name !== 'Woody') this.name = 'Woody';
    +  next();
    +})
    show code
    Schema.prototype.pre = function() {
    +  var name = arguments[0];
    +  if (IS_KAREEM_HOOK[name]) {
    +    this.s.hooks.pre.apply(this.s.hooks, arguments);
    +    return this;
    +  }
    +  return this.queue('pre', arguments);
    +};

    Schema#queue(name, args)

    Adds a method call to the queue.

    Parameters:

    • name <String> name of the document method to call later
    • args <Array> arguments to pass to the method
    show code
    Schema.prototype.queue = function(name, args) {
    +  this.callQueue.push([name, args]);
    +  return this;
    +};

    Schema#remove(path)

    Removes the given path (or [paths]).

    Parameters:

    show code
    Schema.prototype.remove = function(path) {
    +  if (typeof path === 'string') {
    +    path = [path];
    +  }
    +  if (Array.isArray(path)) {
    +    path.forEach(function(name) {
    +      if (this.path(name)) {
    +        delete this.paths[name];
    +
    +        var pieces = name.split('.');
    +        var last = pieces.pop();
    +        var branch = this.tree;
    +        for (var i = 0; i < pieces.length; ++i) {
    +          branch = branch[pieces[i]];
    +        }
    +        delete branch[last];
    +      }
    +    }, this);
    +  }
    +};

    Schema#requiredPaths(invalidate)

    Returns an Array of path strings that are required by this schema.

    Parameters:

    • invalidate <Boolean> refresh the cache

    Returns:

    show code
    Schema.prototype.requiredPaths = function requiredPaths(invalidate) {
    +  if (this._requiredpaths && !invalidate) {
    +    return this._requiredpaths;
    +  }
    +
    +  var paths = Object.keys(this.paths),
    +      i = paths.length,
    +      ret = [];
    +
    +  while (i--) {
    +    var path = paths[i];
    +    if (this.paths[path].isRequired) {
    +      ret.push(path);
    +    }
    +  }
    +  this._requiredpaths = ret;
    +  return this._requiredpaths;
    +};

    Schema(definition, [options])

    Schema constructor.

    Parameters:

    Events:

    • init: Emitted after the schema is compiled into a Model.

    Example:

    + +
    var child = new Schema({ name: String });
    +var schema = new Schema({ name: String, age: Number, children: [child] });
    +var Tree = mongoose.model('Tree', schema);
    +
    +// setting schema options
    +new Schema({ name: String }, { _id: false, autoIndex: false })
    + +

    Options:

    + + + +

    Note:

    + +

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into its parent.

    show code
    function Schema(obj, options) {
    +  if (!(this instanceof Schema)) {
    +    return new Schema(obj, options);
    +  }
    +
    +  this.obj = obj;
    +  this.paths = {};
    +  this.aliases = {};
    +  this.subpaths = {};
    +  this.virtuals = {};
    +  this.singleNestedPaths = {};
    +  this.nested = {};
    +  this.inherits = {};
    +  this.callQueue = [];
    +  this._indexes = [];
    +  this.methods = {};
    +  this.statics = {};
    +  this.tree = {};
    +  this.query = {};
    +  this.childSchemas = [];
    +  this.plugins = [];
    +
    +  this.s = {
    +    hooks: new Kareem(),
    +    kareemHooks: IS_KAREEM_HOOK
    +  };
    +
    +  this.options = this.defaultOptions(options);
    +
    +  // build paths
    +  if (obj) {
    +    this.add(obj);
    +  }
    +
    +  // check if _id's value is a subdocument (gh-2276)
    +  var _idSubDoc = obj && obj._id && utils.isObject(obj._id);
    +
    +  // ensure the documents get an auto _id unless disabled
    +  var auto_id = !this.paths['_id'] &&
    +      (!this.options.noId && this.options._id) && !_idSubDoc;
    +
    +  if (auto_id) {
    +    var _obj = {_id: {auto: true}};
    +    _obj._id[this.options.typeKey] = Schema.ObjectId;
    +    this.add(_obj);
    +  }
    +
    +  for (var i = 0; i < this._defaultMiddleware.length; ++i) {
    +    var m = this._defaultMiddleware[i];
    +    this[m.kind](m.hook, !!m.isAsync, m.fn);
    +  }
    +
    +  if (this.options.timestamps) {
    +    this.setupTimestamp(this.options.timestamps);
    +  }
    +
    +  // Assign virtual properties based on alias option
    +  aliasFields(this);
    +}

    Schema#set(key, [value])

    Sets/gets a schema option.

    Parameters:

    • key <String> option name
    • [value] <Object> if not passed, the current option value is returned

    See:

    Example

    + +
    schema.set('strict'); // 'true' by default
    +schema.set('strict', false); // Sets 'strict' to false
    +schema.set('strict'); // 'false'
    show code
    Schema.prototype.set = function(key, value, _tags) {
    +  if (arguments.length === 1) {
    +    return this.options[key];
    +  }
    +
    +  switch (key) {
    +    case 'read':
    +      this.options[key] = readPref(value, _tags);
    +      break;
    +    case 'safe':
    +      this.options[key] = value === false
    +          ? {w: 0}
    +          : value;
    +      break;
    +    case 'timestamps':
    +      this.setupTimestamp(value);
    +      this.options[key] = value;
    +      break;
    +    default:
    +      this.options[key] = value;
    +  }
    +
    +  return this;
    +};

    Schema#setupTimestamp(timestamps)

    Setup updatedAt and createdAt timestamps to documents if enabled

    Parameters:

    show code
    Schema.prototype.setupTimestamp = function(timestamps) {
    +  if (timestamps) {
    +    var createdAt = timestamps.createdAt || 'createdAt';
    +    var updatedAt = timestamps.updatedAt || 'updatedAt';
    +    var schemaAdditions = {};
    +
    +    var parts = createdAt.split('.');
    +    var i;
    +    var cur = schemaAdditions;
    +    if (this.pathType(createdAt) === 'adhocOrUndefined') {
    +      for (i = 0; i < parts.length; ++i) {
    +        cur[parts[i]] = (i < parts.length - 1 ?
    +          cur[parts[i]] || {} :
    +          Date);
    +      }
    +    }
    +
    +    parts = updatedAt.split('.');
    +    cur = schemaAdditions;
    +    if (this.pathType(createdAt) === 'adhocOrUndefined') {
    +      for (i = 0; i < parts.length; ++i) {
    +        cur[parts[i]] = (i < parts.length - 1 ?
    +          cur[parts[i]] || {} :
    +          Date);
    +      }
    +    }
    +
    +    this.add(schemaAdditions);
    +
    +    this.pre('save', function(next) {
    +      var defaultTimestamp = new Date();
    +      var auto_id = this._id && this._id.auto;
    +
    +      if (!this.get(createdAt) && this.isSelected(createdAt)) {
    +        this.set(createdAt, auto_id ? this._id.getTimestamp() : defaultTimestamp);
    +      }
    +
    +      if (this.isNew || this.isModified()) {
    +        this.set(updatedAt, this.isNew ? this.get(createdAt) : defaultTimestamp);
    +      }
    +
    +      next();
    +    });
    +
    +    var genUpdates = function(currentUpdate, overwrite) {
    +      var now = new Date();
    +      var updates = {};
    +      var _updates = updates;
    +      if (overwrite) {
    +        if (currentUpdate && currentUpdate.$set) {
    +          currentUpdate = currentUpdate.$set;
    +          updates.$set = {};
    +          _updates = updates.$set;
    +        }
    +        if (!currentUpdate[updatedAt]) {
    +          _updates[updatedAt] = now;
    +        }
    +        if (!currentUpdate[createdAt]) {
    +          _updates[createdAt] = now;
    +        }
    +        return updates;
    +      }
    +      updates = { $set: {} };
    +      currentUpdate = currentUpdate || {};
    +
    +      if (!currentUpdate.$currentDate || !currentUpdate.$currentDate[updatedAt]) {
    +        updates.$set[updatedAt] = now;
    +      }
    +
    +      if (currentUpdate[createdAt]) {
    +        delete currentUpdate[createdAt];
    +      }
    +      if (currentUpdate.$set && currentUpdate.$set[createdAt]) {
    +        delete currentUpdate.$set[createdAt];
    +      }
    +
    +      updates.$setOnInsert = {};
    +      updates.$setOnInsert[createdAt] = now;
    +
    +      return updates;
    +    };
    +
    +    this.methods.initializeTimestamps = function() {
    +      if (!this.get(createdAt)) {
    +        this.set(createdAt, new Date());
    +      }
    +      if (!this.get(updatedAt)) {
    +        this.set(updatedAt, new Date());
    +      }
    +      return this;
    +    };
    +
    +    this.pre('findOneAndUpdate', function(next) {
    +      var overwrite = this.options.overwrite;
    +      this.findOneAndUpdate({}, genUpdates(this.getUpdate(), overwrite), {
    +        overwrite: overwrite
    +      });
    +      applyTimestampsToChildren(this);
    +      next();
    +    });
    +
    +    this.pre('update', function(next) {
    +      var overwrite = this.options.overwrite;
    +      this.update({}, genUpdates(this.getUpdate(), overwrite), {
    +        overwrite: overwrite
    +      });
    +      applyTimestampsToChildren(this);
    +      next();
    +    });
    +  }
    +};

    Schema#static(name, [fn])

    Adds static "class" methods to Models compiled from this schema.

    Parameters:

    Example

    + +
    var schema = new Schema(..);
    +schema.static('findByName', function (name, callback) {
    +  return this.find({ name: name }, callback);
    +});
    +
    +var Drink = mongoose.model('Drink', schema);
    +Drink.findByName('sanpellegrino', function (err, drinks) {
    +  //
    +});
    + +

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    show code
    Schema.prototype.static = function(name, fn) {
    +  if (typeof name !== 'string') {
    +    for (var i in name) {
    +      this.statics[i] = name[i];
    +    }
    +  } else {
    +    this.statics[name] = fn;
    +  }
    +  return this;
    +};

    Schema#virtual(name, [options])

    Creates a virtual type with the given name.

    Parameters:

    Returns:

    show code
    Schema.prototype.virtual = function(name, options) {
    +  if (options && options.ref) {
    +    if (!options.localField) {
    +      throw new Error('Reference virtuals require `localField` option');
    +    }
    +
    +    if (!options.foreignField) {
    +      throw new Error('Reference virtuals require `foreignField` option');
    +    }
    +
    +    this.pre('init', function(next, obj) {
    +      if (mpath.has(name, obj)) {
    +        var _v = mpath.get(name, obj);
    +        if (!this.$$populatedVirtuals) {
    +          this.$$populatedVirtuals = {};
    +        }
    +
    +        if (options.justOne) {
    +          this.$$populatedVirtuals[name] = Array.isArray(_v) ?
    +            _v[0] :
    +            _v;
    +        } else {
    +          this.$$populatedVirtuals[name] = Array.isArray(_v) ?
    +            _v :
    +            _v == null ? [] : [_v];
    +        }
    +
    +        mpath.unset(name, obj);
    +      }
    +      if (this.ownerDocument) {
    +        next();
    +        return this;
    +      } else {
    +        next();
    +      }
    +    });
    +
    +    var virtual = this.virtual(name);
    +    virtual.options = options;
    +    return virtual.
    +      get(function() {
    +        if (!this.$$populatedVirtuals) {
    +          this.$$populatedVirtuals = {};
    +        }
    +        if (name in this.$$populatedVirtuals) {
    +          return this.$$populatedVirtuals[name];
    +        }
    +        return null;
    +      }).
    +      set(function(_v) {
    +        if (!this.$$populatedVirtuals) {
    +          this.$$populatedVirtuals = {};
    +        }
    +
    +        if (options.justOne) {
    +          this.$$populatedVirtuals[name] = Array.isArray(_v) ?
    +            _v[0] :
    +            _v;
    +
    +          if (typeof this.$$populatedVirtuals[name] !== 'object') {
    +            this.$$populatedVirtuals[name] = null;
    +          }
    +        } else {
    +          this.$$populatedVirtuals[name] = Array.isArray(_v) ?
    +            _v :
    +            _v == null ? [] : [_v];
    +
    +          this.$$populatedVirtuals[name] = this.$$populatedVirtuals[name].filter(function(doc) {
    +            return doc && typeof doc === 'object';
    +          });
    +        }
    +      });
    +  }
    +
    +  var virtuals = this.virtuals;
    +  var parts = name.split('.');
    +
    +  if (this.pathType(name) === 'real') {
    +    throw new Error('Virtual path "' + name + '"' +
    +      ' conflicts with a real path in the schema');
    +  }
    +
    +  virtuals[name] = parts.reduce(function(mem, part, i) {
    +    mem[part] || (mem[part] = (i === parts.length - 1)
    +        ? new VirtualType(options, name)
    +        : {});
    +    return mem[part];
    +  }, this.tree);
    +
    +  return virtuals[name];
    +};

    Schema#virtualpath(name)

    Returns the virtual type with the given name.

    Parameters:

    Returns:

    show code
    Schema.prototype.virtualpath = function(name) {
    +  return this.virtuals[name];
    +};

    Schema.indexTypes()

    The allowed index types

    show code
    var indexTypes = '2d 2dsphere hashed text'.split(' ');
    +
    +Object.defineProperty(Schema, 'indexTypes', {
    +  get: function() {
    +    return indexTypes;
    +  },
    +  set: function() {
    +    throw new Error('Cannot overwrite Schema.indexTypes');
    +  }
    +});

    Schema.interpretAsType(path, obj)

    Converts type arguments into Mongoose Types.

    show code
    Schema.interpretAsType = function(path, obj, options) {
    +  if (obj.constructor) {
    +    var constructorName = utils.getFunctionName(obj.constructor);
    +    if (constructorName !== 'Object') {
    +      var oldObj = obj;
    +      obj = {};
    +      obj[options.typeKey] = oldObj;
    +    }
    +  }
    +
    +  // Get the type making sure to allow keys named "type"
    +  // and default to mixed if not specified.
    +  // { type: { type: String, default: 'freshcut' } }
    +  var type = obj[options.typeKey] && (options.typeKey !== 'type' || !obj.type.type)
    +      ? obj[options.typeKey]
    +      : {};
    +
    +  if (utils.getFunctionName(type.constructor) === 'Object' || type === 'mixed') {
    +    return new MongooseTypes.Mixed(path, obj);
    +  }
    +
    +  if (Array.isArray(type) || Array === type || type === 'array') {
    +    // if it was specified through { type } look for `cast`
    +    var cast = (Array === type || type === 'array')
    +        ? obj.cast
    +        : type[0];
    +
    +    if (cast && cast.instanceOfSchema) {
    +      return new MongooseTypes.DocumentArray(path, cast, obj);
    +    }
    +    if (cast &&
    +        cast[options.typeKey] &&
    +        cast[options.typeKey].instanceOfSchema) {
    +      return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj);
    +    }
    +
    +    if (Array.isArray(cast)) {
    +      return new MongooseTypes.Array(path, Schema.interpretAsType(path, cast, options), obj);
    +    }
    +
    +    if (typeof cast === 'string') {
    +      cast = MongooseTypes[cast.charAt(0).toUpperCase() + cast.substring(1)];
    +    } else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type))
    +        && utils.getFunctionName(cast.constructor) === 'Object') {
    +      if (Object.keys(cast).length) {
    +        // The `minimize` and `typeKey` options propagate to child schemas
    +        // declared inline, like `{ arr: [{ val: { $type: String } }] }`.
    +        // See gh-3560
    +        var childSchemaOptions = {minimize: options.minimize};
    +        if (options.typeKey) {
    +          childSchemaOptions.typeKey = options.typeKey;
    +        }
    +        //propagate 'strict' option to child schema
    +        if (options.hasOwnProperty('strict')) {
    +          childSchemaOptions.strict = options.strict;
    +        }
    +        //propagate 'runSettersOnQuery' option to child schema
    +        if (options.hasOwnProperty('runSettersOnQuery')) {
    +          childSchemaOptions.runSettersOnQuery = options.runSettersOnQuery;
    +        }
    +        var childSchema = new Schema(cast, childSchemaOptions);
    +        childSchema.$implicitlyCreated = true;
    +        return new MongooseTypes.DocumentArray(path, childSchema, obj);
    +      } else {
    +        // Special case: empty object becomes mixed
    +        return new MongooseTypes.Array(path, MongooseTypes.Mixed, obj);
    +      }
    +    }
    +
    +    if (cast) {
    +      type = cast[options.typeKey] && (options.typeKey !== 'type' || !cast.type.type)
    +          ? cast[options.typeKey]
    +          : cast;
    +
    +      name = typeof type === 'string'
    +          ? type
    +          : type.schemaName || utils.getFunctionName(type);
    +
    +      if (!(name in MongooseTypes)) {
    +        throw new TypeError('Undefined type `' + name + '` at array `' + path +
    +          '`');
    +      }
    +    }
    +
    +    return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj, options);
    +  }
    +
    +  if (type && type.instanceOfSchema) {
    +    return new MongooseTypes.Embedded(type, path, obj);
    +  }
    +
    +  var name;
    +  if (Buffer.isBuffer(type)) {
    +    name = 'Buffer';
    +  } else {
    +    name = typeof type === 'string'
    +        ? type
    +      // If not string, `type` is a function. Outside of IE, function.name
    +      // gives you the function name. In IE, you need to compute it
    +        : type.schemaName || utils.getFunctionName(type);
    +  }
    +
    +  if (name) {
    +    name = name.charAt(0).toUpperCase() + name.substring(1);
    +  }
    +
    +  if (undefined == MongooseTypes[name]) {
    +    throw new TypeError('Undefined type `' + name + '` at `' + path +
    +        '`
    +  Did you try nesting Schemas? ' +
    +        'You can only nest using refs or arrays.');
    +  }
    +
    +  obj = utils.clone(obj, { retainKeyOrder: true });
    +  if (!('runSettersOnQuery' in obj)) {
    +    obj.runSettersOnQuery = options.runSettersOnQuery;
    +  }
    +  return new MongooseTypes[name](path, obj);
    +};

    Parameters:


    Schema.reserved

    Reserved document keys.

    show code
    Schema.reserved = Object.create(null);
    +var reserved = Schema.reserved;
    +// Core object
    +reserved['prototype'] =
    +// EventEmitter
    +reserved.emit =
    +reserved.on =
    +reserved.once =
    +reserved.listeners =
    +reserved.removeListener =
    +// document properties and functions
    +reserved.collection =
    +reserved.db =
    +reserved.errors =
    +reserved.init =
    +reserved.isModified =
    +reserved.isNew =
    +reserved.get =
    +reserved.modelName =
    +reserved.save =
    +reserved.schema =
    +reserved.set =
    +reserved.toObject =
    +reserved.validate =
    +reserved.remove =
    +// hooks.js
    +reserved._pres = reserved._posts = 1;

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    + +
    on, emit, _events, db, get, set, init, isNew, errors, schema, options, modelName, collection, _pres, _posts, toObject
    + +

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    + +
    var schema = new Schema(..);
    + schema.methods.init = function () {} // potentially breaking

    Schema.Types

    The various built-in Mongoose Schema Types.

    show code
    Schema.Types = MongooseTypes = require('./schema/index');

    Example:

    + +
    var mongoose = require('mongoose');
    +var ObjectId = mongoose.Schema.Types.ObjectId;
    + +

    Types:

    + + + +

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    + +
    var Mixed = mongoose.Schema.Types.Mixed;
    +new mongoose.Schema({ _user: Mixed })

    Schema#_defaultMiddleware

    Default middleware attached to a schema. Cannot be changed.

    + +

    This field is used to make sure discriminators don't get multiple copies of
    built-in middleware. Declared as a constant because changing this at runtime
    may lead to instability with Model.prototype.discriminator().

    show code
    Object.defineProperty(Schema.prototype, '_defaultMiddleware', {
    +  configurable: false,
    +  enumerable: false,
    +  writable: false,
    +  value: [
    +    {
    +      kind: 'pre',
    +      hook: 'remove',
    +      isAsync: true,
    +      fn: function(next, done) {
    +        if (this.ownerDocument) {
    +          done();
    +          next();
    +          return;
    +        }
    +
    +        var subdocs = this.$__getAllSubdocs();
    +
    +        if (!subdocs.length) {
    +          done();
    +          next();
    +          return;
    +        }
    +
    +        each(subdocs, function(subdoc, cb) {
    +          subdoc.remove({ noop: true }, function(err) {
    +            cb(err);
    +          });
    +        }, function(error) {
    +          if (error) {
    +            done(error);
    +            return;
    +          }
    +          next();
    +          done();
    +        });
    +      }
    +    }
    +  ]
    +});

    Schema#obj

    The original object passed to the schema constructor

    + +

    Example:

    + +
    var schema = new Schema({ a: String }).add({ b: String });
    +schema.obj; // { a: String }
    show code
    Schema.prototype.obj;

    Schema#paths

    Schema as flat paths

    + +

    Example:

    + +
    {
    +    '_id'        : SchemaType,
    +  , 'nested.key' : SchemaType,
    +}
    show code
    Schema.prototype.paths;

    Schema#tree

    Schema as a tree

    + +

    Example:

    + +
    {
    +    '_id'     : ObjectId
    +  , 'nested'  : {
    +        'key' : String
    +    }
    +}
    show code
    Schema.prototype.tree;

  • document.js

    Document#$__buildDoc(obj, [fields], [skipId])

    Builds the default doc structure

    Parameters:

    Returns:


    Document#$__dirty()

    Returns this documents dirty paths / vals.


    Document#$__fullPath([path])

    Returns the full path to this document.

    Parameters:

    Returns:


    Document#$__getAllSubdocs()

    Get all subdocs (by bfs)


    Document#$__getArrayPathsToValidate()

    Get active path that were changed and are arrays


    Document#$__path(path)

    Returns the schematype for the given path.

    Parameters:


    Document#$__reset()

    Resets the internal modified state of this document.

    Returns:


    Document#$__set()

    Handles the actual setting of the value and marking the path modified if appropriate.


    Document#$__setSchema(schema)

    Assigns/compiles schema into this documents prototype.

    Parameters:


    Document#$__shouldModify()

    Determine if we should mark this change as modified.

    Returns:


    Document#$ignore(path)

    Don't run validation on this path or persist changes to this path.

    Parameters:

    • path <String> the path to ignore

    Example:

    + +
    doc.foo = null;
    +doc.$ignore('foo');
    +doc.save() // changes to foo will not be persisted and validators won't be run

    Document#$isDefault([path])

    Checks if a path is set to its default.

    Parameters:

    Returns:

    Example

    + +
    MyModel = mongoose.model('test', { name: { type: String, default: 'Val '} });
    +var m = new MyModel();
    +m.$isDefault('name'); // true

    Document#$toObject()

    Internal helper for toObject() and toJSON() that doesn't manipulate options


    Document#depopulate(path)

    Takes a populated field and returns it to its unpopulated state.

    Parameters:

    Returns:

    Example:

    + +
    Model.findOne().populate('author').exec(function (err, doc) {
    +  console.log(doc.author.name); // Dr.Seuss
    +  console.log(doc.depopulate('author'));
    +  console.log(doc.author); // '5144cf8050f071d979c118a7'
    +})
    + +

    If the path was not populated, this is a no-op.

    show code
    Document.prototype.depopulate = function(path) {
    +  var populatedIds = this.populated(path);
    +  if (!populatedIds) {
    +    return;
    +  }
    +  delete this.$__.populated[path];
    +  this.set(path, populatedIds);
    +  return this;
    +};

    Document(obj, [fields], [skipId])

    Document constructor.

    Parameters:

    • obj <Object> the values to set
    • [fields] <Object> optional object containing the fields which were selected in the query returning this document and any populated paths data
    • [skipId] <Boolean> bool, should we auto create an ObjectId _id

    Events:

    • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

    • save: Emitted when the document is successfully saved

    show code
    function Document(obj, fields, skipId) {
    +  this.$__ = new InternalCache;
    +  this.$__.emitter = new EventEmitter();
    +  this.isNew = true;
    +  this.errors = undefined;
    +
    +  var schema = this.schema;
    +
    +  if (typeof fields === 'boolean') {
    +    this.$__.strictMode = fields;
    +    fields = undefined;
    +  } else {
    +    this.$__.strictMode = schema.options && schema.options.strict;
    +    this.$__.selected = fields;
    +  }
    +
    +  var required = schema.requiredPaths(true);
    +  for (var i = 0; i < required.length; ++i) {
    +    this.$__.activePaths.require(required[i]);
    +  }
    +
    +  this.$__.emitter.setMaxListeners(0);
    +  this._doc = this.$__buildDoc(obj, fields, skipId);
    +
    +  if (obj) {
    +    if (obj instanceof Document) {
    +      this.isNew = obj.isNew;
    +    }
    +    // Skip set hooks
    +    if (this.$__original_set) {
    +      this.$__original_set(obj, undefined, true);
    +    } else {
    +      this.set(obj, undefined, true);
    +    }
    +  }
    +
    +  this.$__._id = this._id;
    +
    +  if (!schema.options.strict && obj) {
    +    var _this = this,
    +        keys = Object.keys(this._doc);
    +
    +    keys.forEach(function(key) {
    +      if (!(key in schema.tree)) {
    +        defineKey(key, null, _this);
    +      }
    +    });
    +  }
    +
    +  applyQueue(this);
    +}

    Document#equals(doc)

    Returns true if the Document stores the same data as doc.

    Parameters:

    Returns:

    Documents are considered equal when they have matching _ids, unless neither
    document has an _id, in which case this function falls back to using
    deepEqual().

    show code
    Document.prototype.equals = function(doc) {
    +  if (!doc) {
    +    return false;
    +  }
    +
    +  var tid = this.get('_id');
    +  var docid = doc.get ? doc.get('_id') : doc;
    +  if (!tid && !docid) {
    +    return deepEqual(this, doc);
    +  }
    +  return tid && tid.equals
    +      ? tid.equals(docid)
    +      : tid === docid;
    +};

    Document#execPopulate()

    Explicitly executes population and returns a promise. Useful for ES2015
    integration.

    Returns:

    • <Promise> promise that resolves to the document when population is done

    Example:

    + +
    var promise = doc.
    +  populate('company').
    +  populate({
    +    path: 'notes',
    +    match: /airline/,
    +    select: 'text',
    +    model: 'modelName'
    +    options: opts
    +  }).
    +  execPopulate();
    +
    +// summary
    +doc.execPopulate().then(resolve, reject);
    show code
    Document.prototype.execPopulate = function() {
    +  var Promise = PromiseProvider.get();
    +  var _this = this;
    +  return new Promise.ES6(function(resolve, reject) {
    +    _this.populate(function(error, res) {
    +      if (error) {
    +        reject(error);
    +      } else {
    +        resolve(res);
    +      }
    +    });
    +  });
    +};

    Document#get(path, [type])

    Returns the value of a path.

    Parameters:

    Example

    + +
    // path
    +doc.get('age') // 47
    +
    +// dynamic casting to a string
    +doc.get('age', String) // "47"
    show code
    Document.prototype.get = function(path, type) {
    +  var adhoc;
    +  if (type) {
    +    adhoc = Schema.interpretAsType(path, type, this.schema.options);
    +  }
    +
    +  var schema = this.$__path(path) || this.schema.virtualpath(path);
    +  var pieces = path.split('.');
    +  var obj = this._doc;
    +
    +  if (schema instanceof VirtualType) {
    +    return schema.applyGetters(null, this);
    +  }
    +
    +  for (var i = 0, l = pieces.length; i < l; i++) {
    +    obj = obj === null || obj === void 0
    +        ? undefined
    +        : obj[pieces[i]];
    +  }
    +
    +  if (adhoc) {
    +    obj = adhoc.cast(obj);
    +  }
    +
    +  if (schema) {
    +    obj = schema.applyGetters(obj, this);
    +  }
    +
    +  return obj;
    +};

    Document#getValue(path)

    Gets a raw value from a path (no getters)

    Parameters:

    show code
    Document.prototype.getValue = function(path) {
    +  return utils.getValue(path, this._doc);
    +};

    Document#init(doc, fn)

    Initializes the document without setters or marking anything modified.

    Parameters:

    Called internally after a document is returned from mongodb.

    show code
    Document.prototype.init = function(doc, opts, fn) {
    +  // do not prefix this method with $__ since its
    +  // used by public hooks
    +
    +  if (typeof opts === 'function') {
    +    fn = opts;
    +    opts = null;
    +  }
    +
    +  this.isNew = false;
    +  this.$init = true;
    +
    +  // handle docs with populated paths
    +  // If doc._id is not null or undefined
    +  if (doc._id !== null && doc._id !== undefined &&
    +    opts && opts.populated && opts.populated.length) {
    +    var id = String(doc._id);
    +    for (var i = 0; i < opts.populated.length; ++i) {
    +      var item = opts.populated[i];
    +      if (item.isVirtual) {
    +        this.populated(item.path, utils.getValue(item.path, doc), item);
    +      } else {
    +        this.populated(item.path, item._docs[id], item);
    +      }
    +    }
    +  }
    +
    +  init(this, doc, this._doc);
    +
    +  this.emit('init', this);
    +  this.constructor.emit('init', this);
    +
    +  this.$__._id = this._id;
    +
    +  if (fn) {
    +    fn(null);
    +  }
    +  return this;
    +};

    Document#inspect()

    Helper for console.log

    show code
    Document.prototype.inspect = function(options) {
    +  var isPOJO = options &&
    +    utils.getFunctionName(options.constructor) === 'Object';
    +  var opts;
    +  if (isPOJO) {
    +    opts = options;
    +    opts.minimize = false;
    +    opts.retainKeyOrder = true;
    +  }
    +  return this.toObject(opts);
    +};

    Document#invalidate(path, errorMsg, value, [kind])

    Marks a path as invalid, causing validation to fail.

    Parameters:

    • path <String> the field to invalidate
    • errorMsg <String, Error> the error which states the reason path was invalid
    • value <Object, String, Number, T> optional invalid value
    • [kind] <String> optional kind property for the error

    Returns:

    • <ValidationError> the current ValidationError, with all currently invalidated paths

    The errorMsg argument will become the message of the ValidationError.

    + +

    The value argument (if passed) will be available through the ValidationError.value property.

    + +
    doc.invalidate('size', 'must be less than 20', 14);
    +
    +doc.validate(function (err) {
    +  console.log(err)
    +  // prints
    +  { message: 'Validation failed',
    +    name: 'ValidationError',
    +    errors:
    +     { size:
    +        { message: 'must be less than 20',
    +          name: 'ValidatorError',
    +          path: 'size',
    +          type: 'user defined',
    +          value: 14 } } }
    +})
    show code
    Document.prototype.invalidate = function(path, err, val, kind) {
    +  if (!this.$__.validationError) {
    +    this.$__.validationError = new ValidationError(this);
    +  }
    +
    +  if (this.$__.validationError.errors[path]) {
    +    return;
    +  }
    +
    +  if (!err || typeof err === 'string') {
    +    err = new ValidatorError({
    +      path: path,
    +      message: err,
    +      type: kind || 'user defined',
    +      value: val
    +    });
    +  }
    +
    +  if (this.$__.validationError === err) {
    +    return this.$__.validationError;
    +  }
    +
    +  this.$__.validationError.addError(path, err);
    +  return this.$__.validationError;
    +};

    Document#isDirectModified(path)

    Returns true if path was directly set and modified, else false.

    Parameters:

    Returns:

    Example

    + +
    doc.set('documents.0.title', 'changed');
    +doc.isDirectModified('documents.0.title') // true
    +doc.isDirectModified('documents') // false
    show code
    Document.prototype.isDirectModified = function(path) {
    +  return (path in this.$__.activePaths.states.modify);
    +};

    Document#isDirectSelected(path)

    Checks if path was explicitly selected. If no projection, always returns
    true.

    Parameters:

    Returns:

    Example

    + +
    Thing.findOne().select('nested.name').exec(function (err, doc) {
    +   doc.isDirectSelected('nested.name') // true
    +   doc.isDirectSelected('nested.otherName') // false
    +   doc.isDirectSelected('nested')  // false
    +})
    show code
    Document.prototype.isDirectSelected = function isDirectSelected(path) {
    +  if (this.$__.selected) {
    +    if (path === '_id') {
    +      return this.$__.selected._id !== 0;
    +    }
    +
    +    var paths = Object.keys(this.$__.selected);
    +    var i = paths.length;
    +    var inclusive = null;
    +    var cur;
    +
    +    if (i === 1 && paths[0] === '_id') {
    +      // only _id was selected.
    +      return this.$__.selected._id === 0;
    +    }
    +
    +    while (i--) {
    +      cur = paths[i];
    +      if (cur === '_id') {
    +        continue;
    +      }
    +      if (this.$__.selected[cur] && this.$__.selected[cur].$meta) {
    +        continue;
    +      }
    +      inclusive = !!this.$__.selected[cur];
    +      break;
    +    }
    +
    +    if (inclusive === null) {
    +      return true;
    +    }
    +
    +    if (path in this.$__.selected) {
    +      return inclusive;
    +    }
    +
    +    return !inclusive;
    +  }
    +
    +  return true;
    +};

    Document#isInit(path)

    Checks if path was initialized.

    Parameters:

    Returns:

    show code
    Document.prototype.isInit = function(path) {
    +  return (path in this.$__.activePaths.states.init);
    +};

    Document#isModified([path])

    Returns true if this document was modified, else false.

    Parameters:

    Returns:

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    + +

    Example

    + +
    doc.set('documents.0.title', 'changed');
    +doc.isModified()                      // true
    +doc.isModified('documents')           // true
    +doc.isModified('documents.0.title')   // true
    +doc.isModified('documents otherProp') // true
    +doc.isDirectModified('documents')     // false
    show code
    Document.prototype.isModified = function(paths) {
    +  if (paths) {
    +    if (!Array.isArray(paths)) {
    +      paths = paths.split(' ');
    +    }
    +    var modified = this.modifiedPaths();
    +    var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
    +    var isModifiedChild = paths.some(function(path) {
    +      return !!~modified.indexOf(path);
    +    });
    +    return isModifiedChild || paths.some(function(path) {
    +      return directModifiedPaths.some(function(mod) {
    +        return mod === path || path.indexOf(mod + '.') === 0;
    +      });
    +    });
    +  }
    +  return this.$__.activePaths.some('modify');
    +};

    Document#isSelected(path)

    Checks if path was selected in the source query which initialized this document.

    Parameters:

    Returns:

    Example

    + +
    Thing.findOne().select('name').exec(function (err, doc) {
    +   doc.isSelected('name') // true
    +   doc.isSelected('age')  // false
    +})
    show code
    Document.prototype.isSelected = function isSelected(path) {
    +  if (this.$__.selected) {
    +    if (path === '_id') {
    +      return this.$__.selected._id !== 0;
    +    }
    +
    +    var paths = Object.keys(this.$__.selected);
    +    var i = paths.length;
    +    var inclusive = null;
    +    var cur;
    +
    +    if (i === 1 && paths[0] === '_id') {
    +      // only _id was selected.
    +      return this.$__.selected._id === 0;
    +    }
    +
    +    while (i--) {
    +      cur = paths[i];
    +      if (cur === '_id') {
    +        continue;
    +      }
    +      if (this.$__.selected[cur] && this.$__.selected[cur].$meta) {
    +        continue;
    +      }
    +      inclusive = !!this.$__.selected[cur];
    +      break;
    +    }
    +
    +    if (inclusive === null) {
    +      return true;
    +    }
    +
    +    if (path in this.$__.selected) {
    +      return inclusive;
    +    }
    +
    +    i = paths.length;
    +    var pathDot = path + '.';
    +
    +    while (i--) {
    +      cur = paths[i];
    +      if (cur === '_id') {
    +        continue;
    +      }
    +
    +      if (cur.indexOf(pathDot) === 0) {
    +        return inclusive || cur !== pathDot;
    +      }
    +
    +      if (pathDot.indexOf(cur + '.') === 0) {
    +        return inclusive;
    +      }
    +    }
    +
    +    return !inclusive;
    +  }
    +
    +  return true;
    +};

    Document#markModified(path, [scope])

    Marks the path as having pending changes to write to the db.

    Parameters:

    • path <String> the path to mark modified
    • [scope] <Document> the scope to run validators with

    Very helpful when using Mixed types.

    + +

    Example:

    + +
    doc.mixed.type = 'changed';
    +doc.markModified('mixed.type');
    +doc.save() // changes to mixed.type are now persisted
    show code
    Document.prototype.markModified = function(path, scope) {
    +  this.$__.activePaths.modify(path);
    +  if (scope != null && !this.ownerDocument) {
    +    this.$__.pathsToScopes[path] = scope;
    +  }
    +};

    Document#modifiedPaths()

    Returns the list of paths that have been modified.

    Returns:

    show code
    Document.prototype.modifiedPaths = function() {
    +  var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
    +  return directModifiedPaths.reduce(function(list, path) {
    +    var parts = path.split('.');
    +    return list.concat(parts.reduce(function(chains, part, i) {
    +      return chains.concat(parts.slice(0, i).concat(part).join('.'));
    +    }, []).filter(function(chain) {
    +      return (list.indexOf(chain) === -1);
    +    }));
    +  }, []);
    +};

    Document#populate([path], [callback])

    Populates document references, executing the callback when complete.
    If you want to use promises instead, use this function with
    execPopulate()

    Parameters:

    • [path] <String, Object> The path to populate or an options object
    • [callback] <Function> When passed, population is invoked

    Returns:

    Example:

    + +
    doc
    +.populate('company')
    +.populate({
    +  path: 'notes',
    +  match: /airline/,
    +  select: 'text',
    +  model: 'modelName'
    +  options: opts
    +}, function (err, user) {
    +  assert(doc._id === user._id) // the document itself is passed
    +})
    +
    +// summary
    +doc.populate(path)                   // not executed
    +doc.populate(options);               // not executed
    +doc.populate(path, callback)         // executed
    +doc.populate(options, callback);     // executed
    +doc.populate(callback);              // executed
    +doc.populate(options).execPopulate() // executed, returns promise
    + +

    NOTE:

    + +

    Population does not occur unless a callback is passed or you explicitly
    call execPopulate().
    Passing the same path a second time will overwrite the previous path options.
    See Model.populate() for explaination of options.

    show code
    Document.prototype.populate = function populate() {
    +  if (arguments.length === 0) {
    +    return this;
    +  }
    +
    +  var pop = this.$__.populate || (this.$__.populate = {});
    +  var args = utils.args(arguments);
    +  var fn;
    +
    +  if (typeof args[args.length - 1] === 'function') {
    +    fn = args.pop();
    +  }
    +
    +  // allow `doc.populate(callback)`
    +  if (args.length) {
    +    // use hash to remove duplicate paths
    +    var res = utils.populate.apply(null, args);
    +    for (var i = 0; i < res.length; ++i) {
    +      pop[res[i].path] = res[i];
    +    }
    +  }
    +
    +  if (fn) {
    +    var paths = utils.object.vals(pop);
    +    this.$__.populate = undefined;
    +    paths.__noPromise = true;
    +    this.constructor.populate(this, paths, fn);
    +  }
    +
    +  return this;
    +};

    Document#populated(path)

    Gets _id(s) used during population of the given path.

    Parameters:

    Example:

    + +
    Model.findOne().populate('author').exec(function (err, doc) {
    +  console.log(doc.author.name)         // Dr.Seuss
    +  console.log(doc.populated('author')) // '5144cf8050f071d979c118a7'
    +})
    + +

    If the path was not populated, undefined is returned.

    show code
    Document.prototype.populated = function(path, val, options) {
    +  // val and options are internal
    +
    +  if (val === null || val === void 0) {
    +    if (!this.$__.populated) {
    +      return undefined;
    +    }
    +    var v = this.$__.populated[path];
    +    if (v) {
    +      return v.value;
    +    }
    +    return undefined;
    +  }
    +
    +  // internal
    +
    +  if (val === true) {
    +    if (!this.$__.populated) {
    +      return undefined;
    +    }
    +    return this.$__.populated[path];
    +  }
    +
    +  this.$__.populated || (this.$__.populated = {});
    +  this.$__.populated[path] = {value: val, options: options};
    +  return val;
    +};

    function Object() { [native code] }#save([options], [options.safe], [options.validateBeforeSave], [fn])

    Saves this document.

    Parameters:

    Returns:

    Example:

    + +
    product.sold = Date.now();
    +product.save(function (err, product, numAffected) {
    +  if (err) ..
    +})
    + +

    The callback will receive three parameters

    + +
      +
    1. err if an error occurred
    2. +
    3. product which is the saved product
    4. +
    5. numAffected will be 1 when the document was successfully persisted to MongoDB, otherwise 0. Unless you tweak mongoose's internals, you don't need to worry about checking this parameter for errors - checking err is sufficient to make sure your document was properly saved.
    6. +
    + +

    As an extra measure of flow control, save will return a Promise.

    + +

    Example:

    + +
    product.save().then(function(product) {
    +   ...
    +});
    + +

    For legacy reasons, mongoose stores object keys in reverse order on initial
    save. That is, { a: 1, b: 2 } will be saved as { b: 2, a: 1 } in
    MongoDB. To override this behavior, set
    the toObject.retainKeyOrder option
    to true on your schema.


    Document#set(path, val, [type], [options])

    Sets the value of a path, or many paths.

    Parameters:

    • path <String, Object> path or object of key/vals to set
    • val <Any> the value to set
    • [type] <Schema, String, Number, Buffer, *> optionally specify a type for "on-the-fly" attributes
    • [options] <Object> optionally specify options that modify the behavior of the set

    Example:

    + +
    // path, value
    +doc.set(path, value)
    +
    +// object
    +doc.set({
    +    path  : value
    +  , path2 : {
    +       path  : value
    +    }
    +})
    +
    +// on-the-fly cast to number
    +doc.set(path, value, Number)
    +
    +// on-the-fly cast to string
    +doc.set(path, value, String)
    +
    +// changing strict mode behavior
    +doc.set(path, value, { strict: false });
    show code
    Document.prototype.set = function(path, val, type, options) {
    +  //console.log('set', path, val, this, new Error().stack)
    +  if (type && utils.getFunctionName(type.constructor) === 'Object') {
    +    options = type;
    +    type = undefined;
    +  }
    +
    +  var merge = options && options.merge,
    +      adhoc = type && type !== true,
    +      constructing = type === true,
    +      adhocs;
    +
    +  var strict = options && 'strict' in options
    +      ? options.strict
    +      : this.$__.strictMode;
    +
    +  if (adhoc) {
    +    adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {});
    +    adhocs[path] = Schema.interpretAsType(path, type, this.schema.options);
    +  }
    +
    +  if (typeof path !== 'string') {
    +    // new Document({ key: val })
    +
    +    if (path === null || path === void 0) {
    +      var _ = path;
    +      path = val;
    +      val = _;
    +    } else {
    +      var prefix = val
    +          ? val + '.'
    +          : '';
    +
    +      if (path instanceof Document) {
    +        if (path.$__isNested) {
    +          path = path.toObject();
    +        } else {
    +          path = path._doc;
    +        }
    +      }
    +
    +      var keys = Object.keys(path);
    +      var len = keys.length;
    +      var i = 0;
    +      var pathtype;
    +      var key;
    +
    +      if (len === 0 && !this.schema.options.minimize) {
    +        if (val) {
    +          this.set(val, {});
    +        }
    +        return this;
    +      }
    +
    +      if (this.schema.options.retainKeyOrder) {
    +        while (i < len) {
    +          _handleIndex.call(this, i++);
    +        }
    +      } else {
    +        while (len--) {
    +          _handleIndex.call(this, len);
    +        }
    +      }
    +
    +      return this;
    +    }
    +  }
    +
    +  function _handleIndex(i) {
    +    key = keys[i];
    +    var pathName = prefix + key;
    +    pathtype = this.schema.pathType(pathName);
    +
    +    if (path[key] !== null
    +        && path[key] !== void 0
    +          // need to know if plain object - no Buffer, ObjectId, ref, etc
    +        && utils.isObject(path[key])
    +        && (!path[key].constructor || utils.getFunctionName(path[key].constructor) === 'Object')
    +        && pathtype !== 'virtual'
    +        && pathtype !== 'real'
    +        && !(this.$__path(pathName) instanceof MixedSchema)
    +        && !(this.schema.paths[pathName] &&
    +        this.schema.paths[pathName].options &&
    +        this.schema.paths[pathName].options.ref)) {
    +      this.set(path[key], prefix + key, constructing);
    +    } else if (strict) {
    +      // Don't overwrite defaults with undefined keys (gh-3981)
    +      if (constructing && path[key] === void 0 &&
    +          this.get(key) !== void 0) {
    +        return;
    +      }
    +
    +      if (pathtype === 'real' || pathtype === 'virtual') {
    +        // Check for setting single embedded schema to document (gh-3535)
    +        var p = path[key];
    +        if (this.schema.paths[pathName] &&
    +            this.schema.paths[pathName].$isSingleNested &&
    +            path[key] instanceof Document) {
    +          p = p.toObject({ virtuals: false, transform: false });
    +        }
    +        this.set(prefix + key, p, constructing);
    +      } else if (pathtype === 'nested' && path[key] instanceof Document) {
    +        this.set(prefix + key,
    +            path[key].toObject({transform: false}), constructing);
    +      } else if (strict === 'throw') {
    +        if (pathtype === 'nested') {
    +          throw new ObjectExpectedError(key, path[key]);
    +        } else {
    +          throw new StrictModeError(key);
    +        }
    +      }
    +    } else if (path[key] !== void 0) {
    +      this.set(prefix + key, path[key], constructing);
    +    }
    +  }
    +
    +  var pathType = this.schema.pathType(path);
    +  if (pathType === 'nested' && val) {
    +    if (utils.isObject(val) &&
    +        (!val.constructor || utils.getFunctionName(val.constructor) === 'Object')) {
    +      if (!merge) {
    +        this.setValue(path, null);
    +        cleanModifiedSubpaths(this, path);
    +      }
    +
    +      if (Object.keys(val).length === 0) {
    +        this.setValue(path, {});
    +        this.markModified(path);
    +        cleanModifiedSubpaths(this, path);
    +      } else {
    +        this.set(val, path, constructing);
    +      }
    +      return this;
    +    }
    +    this.invalidate(path, new MongooseError.CastError('Object', val, path));
    +    return this;
    +  }
    +
    +  var schema;
    +  var parts = path.split('.');
    +
    +  if (pathType === 'adhocOrUndefined' && strict) {
    +    // check for roots that are Mixed types
    +    var mixed;
    +
    +    for (i = 0; i < parts.length; ++i) {
    +      var subpath = parts.slice(0, i + 1).join('.');
    +      schema = this.schema.path(subpath);
    +      if (schema instanceof MixedSchema) {
    +        // allow changes to sub paths of mixed types
    +        mixed = true;
    +        break;
    +      }
    +
    +      // If path is underneath a virtual, bypass everything and just set it.
    +      if (i + 1 < parts.length && this.schema.pathType(subpath) === 'virtual') {
    +        mpath.set(path, val, this);
    +        return this;
    +      }
    +    }
    +
    +    if (!mixed) {
    +      if (strict === 'throw') {
    +        throw new StrictModeError(path);
    +      }
    +      return this;
    +    }
    +  } else if (pathType === 'virtual') {
    +    schema = this.schema.virtualpath(path);
    +    schema.applySetters(val, this);
    +    return this;
    +  } else {
    +    schema = this.$__path(path);
    +  }
    +
    +  // gh-4578, if setting a deeply nested path that doesn't exist yet, create it
    +  var cur = this._doc;
    +  var curPath = '';
    +  for (i = 0; i < parts.length - 1; ++i) {
    +    cur = cur[parts[i]];
    +    curPath += (curPath.length > 0 ? '.' : '') + parts[i];
    +    if (!cur) {
    +      this.set(curPath, {});
    +      cur = this.getValue(curPath);
    +    }
    +  }
    +
    +  var pathToMark;
    +
    +  // When using the $set operator the path to the field must already exist.
    +  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
    +
    +  if (parts.length <= 1) {
    +    pathToMark = path;
    +  } else {
    +    for (i = 0; i < parts.length; ++i) {
    +      subpath = parts.slice(0, i + 1).join('.');
    +      if (this.isDirectModified(subpath) // earlier prefixes that are already
    +            // marked as dirty have precedence
    +          || this.get(subpath) === null) {
    +        pathToMark = subpath;
    +        break;
    +      }
    +    }
    +
    +    if (!pathToMark) {
    +      pathToMark = path;
    +    }
    +  }
    +
    +  // if this doc is being constructed we should not trigger getters
    +  var priorVal = constructing ?
    +    undefined :
    +    this.getValue(path);
    +
    +  if (!schema) {
    +    this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal);
    +    return this;
    +  }
    +
    +  var shouldSet = true;
    +  try {
    +    // If the user is trying to set a ref path to a document with
    +    // the correct model name, treat it as populated
    +    var didPopulate = false;
    +    if (schema.options &&
    +        schema.options.ref &&
    +        val instanceof Document &&
    +        (schema.options.ref === val.constructor.modelName || schema.options.ref === val.constructor.baseModelName)) {
    +      if (this.ownerDocument) {
    +        this.ownerDocument().populated(this.$__fullPath(path),
    +          val._id, {model: val.constructor});
    +      } else {
    +        this.populated(path, val._id, {model: val.constructor});
    +      }
    +      didPopulate = true;
    +    }
    +
    +    var popOpts;
    +    if (schema.options &&
    +        Array.isArray(schema.options[this.schema.options.typeKey]) &&
    +        schema.options[this.schema.options.typeKey].length &&
    +        schema.options[this.schema.options.typeKey][0].ref &&
    +        Array.isArray(val) &&
    +        val.length > 0 &&
    +        val[0] instanceof Document &&
    +        val[0].constructor.modelName &&
    +        (schema.options[this.schema.options.typeKey][0].ref === val[0].constructor.baseModelName || schema.options[this.schema.options.typeKey][0].ref === val[0].constructor.modelName)) {
    +      if (this.ownerDocument) {
    +        popOpts = { model: val[0].constructor };
    +        this.ownerDocument().populated(this.$__fullPath(path),
    +          val.map(function(v) { return v._id; }), popOpts);
    +      } else {
    +        popOpts = { model: val[0].constructor };
    +        this.populated(path, val.map(function(v) { return v._id; }), popOpts);
    +      }
    +      didPopulate = true;
    +    }
    +
    +    val = schema.applySetters(val, this, false, priorVal);
    +
    +    if (!didPopulate && this.$__.populated) {
    +      delete this.$__.populated[path];
    +    }
    +
    +    this.$markValid(path);
    +  } catch (e) {
    +    this.invalidate(path,
    +      new MongooseError.CastError(schema.instance, val, path, e));
    +    shouldSet = false;
    +  }
    +
    +  if (shouldSet) {
    +    this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal);
    +  }
    +
    +  if (schema.$isSingleNested && (this.isDirectModified(path) || val == null)) {
    +    cleanModifiedSubpaths(this, path);
    +  }
    +
    +  return this;
    +};

    Document#setValue(path, value)

    Sets a raw value for a path (no casting, setters, transformations)

    Parameters:

    show code
    Document.prototype.setValue = function(path, val) {
    +  utils.setValue(path, val, this._doc);
    +  return this;
    +};

    Document#toJSON(options)

    The return value of this method is used in calls to JSON.stringify(doc).

    Parameters:

    Returns:

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    + +
    schema.set('toJSON', { virtuals: true })
    + +

    See schema options for details.

    show code
    Document.prototype.toJSON = function(options) {
    +  return this.$toObject(options, true);
    +};

    Document#toObject([options])

    Converts this document into a plain javascript object, ready for storage in MongoDB.

    Parameters:

    Returns:

    Buffers are converted to instances of mongodb.Binary for proper storage.

    + +

    Options:

    + +
      +
    • getters apply all getters (path and virtual getters)
    • +
    • virtuals apply virtual getters (can override getters option)
    • +
    • minimize remove empty objects (defaults to true)
    • +
    • transform a transform function to apply to the resulting document before returning
    • +
    • depopulate depopulate any populated paths, replacing them with their original refs (defaults to false)
    • +
    • versionKey whether to include the version key (defaults to true)
    • +
    • retainKeyOrder keep the order of object keys. If this is set to true, Object.keys(new Doc({ a: 1, b: 2}).toObject()) will always produce ['a', 'b'] (defaults to false)
    • +
    + +

    Getters/Virtuals

    + +

    Example of only applying path getters

    + +
    doc.toObject({ getters: true, virtuals: false })
    + +

    Example of only applying virtual getters

    + +
    doc.toObject({ virtuals: true })
    + +

    Example of applying both path and virtual getters

    + +
    doc.toObject({ getters: true })
    + +

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    + +
    schema.set('toObject', { virtuals: true })
    + +

    Transform

    + +

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    + +

    Transform functions receive three arguments

    + +
    function (doc, ret, options) {}
    + +
      +
    • doc The mongoose document which is being converted
    • +
    • ret The plain object representation which has been converted
    • +
    • options The options in use (either schema options or the options passed inline)
    • +
    + +

    Example

    + +
    // specify the transform schema option
    +if (!schema.options.toObject) schema.options.toObject = {};
    +schema.options.toObject.transform = function (doc, ret, options) {
    +  // remove the _id of every document before returning the result
    +  delete ret._id;
    +  return ret;
    +}
    +
    +// without the transformation in the schema
    +doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
    +
    +// with the transformation
    +doc.toObject(); // { name: 'Wreck-it Ralph' }
    + +

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    + +
    if (!schema.options.toObject) schema.options.toObject = {};
    +schema.options.toObject.transform = function (doc, ret, options) {
    +  return { movie: ret.name }
    +}
    +
    +// without the transformation in the schema
    +doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
    +
    +// with the transformation
    +doc.toObject(); // { movie: 'Wreck-it Ralph' }
    + +

    Note: if a transform function returns undefined, the return value will be ignored.

    + +

    Transformations may also be applied inline, overridding any transform set in the options:

    + +
    function xform (doc, ret, options) {
    +  return { inline: ret.name, custom: true }
    +}
    +
    +// pass the transform as an inline option
    +doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }
    + +

    If you want to skip transformations, use transform: false:

    + +
    if (!schema.options.toObject) schema.options.toObject = {};
    +schema.options.toObject.hide = '_id';
    +schema.options.toObject.transform = function (doc, ret, options) {
    +  if (options.hide) {
    +    options.hide.split(' ').forEach(function (prop) {
    +      delete ret[prop];
    +    });
    +  }
    +  return ret;
    +}
    +
    +var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });
    +doc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }
    +doc.toObject({ hide: 'secret _id', transform: false });// { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }
    +doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }
    + +

    Transforms are applied only to the document and are not applied to sub-documents.

    + +

    Transforms, like all of these options, are also available for toJSON.

    + +

    See schema options for some more details.

    + +

    During save, no custom options are applied to the document before being sent to the database.

    show code
    Document.prototype.toObject = function(options) {
    +  return this.$toObject(options);
    +};

    Document#toString()

    Helper for console.log


    Document#unmarkModified(path)

    Clears the modified state on the specified path.

    Parameters:

    • path <String> the path to unmark modified

    Example:

    + +
    doc.foo = 'bar';
    +doc.unmarkModified('foo');
    +doc.save() // changes to foo will not be persisted
    show code
    Document.prototype.unmarkModified = function(path) {
    +  this.$__.activePaths.init(path);
    +  delete this.$__.pathsToScopes[path];
    +};

    Document#update(doc, options, callback)

    Sends an update command with this document _id as the query selector.

    Parameters:

    Returns:

    Example:

    + +
    weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);
    + +

    Valid options:

    + +
    show code
    Document.prototype.update = function update() {
    +  var args = utils.args(arguments);
    +  args.unshift({_id: this._id});
    +  return this.constructor.update.apply(this.constructor, args);
    +};

    Document#validate(optional, callback)

    Executes registered validation rules for this document.

    Parameters:

    • optional <Object> options internal options
    • callback <Function> optional callback called after validation completes, passing an error if one occurred

    Returns:

    Note:

    + +

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    + +

    Example:

    + +
    doc.validate(function (err) {
    +  if (err) handleError(err);
    +  else // validation passed
    +});
    show code
    Document.prototype.validate = function(options, callback) {
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
    +  }
    +
    +  this.$__validate(callback || function() {});
    +};

    Document#validateSync(pathsToValidate)

    Executes registered validation rules (skipping asynchronous validators) for this document.

    Parameters:

    • pathsToValidate <Array, string> only validate the given paths

    Returns:

    • <MongooseError, undefined> MongooseError if there are errors during validation, or undefined if there is no error.

    Note:

    + +

    This method is useful if you need synchronous validation.

    + +

    Example:

    + +
    var err = doc.validateSync();
    +if ( err ){
    +  handleError( err );
    +} else {
    +  // validation passed
    +}
    show code
    Document.prototype.validateSync = function(pathsToValidate) {
    +  var _this = this;
    +
    +  if (typeof pathsToValidate === 'string') {
    +    pathsToValidate = pathsToValidate.split(' ');
    +  }
    +
    +  // only validate required fields when necessary
    +  var paths = _getPathsToValidate(this);
    +
    +  if (pathsToValidate && pathsToValidate.length) {
    +    var tmp = [];
    +    for (var i = 0; i < paths.length; ++i) {
    +      if (pathsToValidate.indexOf(paths[i]) !== -1) {
    +        tmp.push(paths[i]);
    +      }
    +    }
    +    paths = tmp;
    +  }
    +
    +  var validating = {};
    +
    +  paths.forEach(function(path) {
    +    if (validating[path]) {
    +      return;
    +    }
    +
    +    validating[path] = true;
    +
    +    var p = _this.schema.path(path);
    +    if (!p) {
    +      return;
    +    }
    +    if (!_this.$isValid(path)) {
    +      return;
    +    }
    +
    +    var val = _this.getValue(path);
    +    var err = p.doValidateSync(val, _this);
    +    if (err) {
    +      _this.invalidate(path, err, undefined, true);
    +    }
    +  });
    +
    +  var err = _this.$__.validationError;
    +  _this.$__.validationError = undefined;
    +  _this.emit('validate', _this);
    +  _this.constructor.emit('validate', _this);
    +
    +  if (err) {
    +    for (var key in err.errors) {
    +      // Make sure cast errors persist
    +      if (err.errors[key] instanceof MongooseError.CastError) {
    +        _this.invalidate(key, err.errors[key]);
    +      }
    +    }
    +  }
    +
    +  return err;
    +};

    Document.$isValid(path)

    Checks if a path is invalid

    Parameters:

    • path <String> the field to check

    Document.$markValid(path)

    Marks a path as valid, removing existing validation errors.

    Parameters:

    • path <String> the field to mark as valid

    Document#errors

    Hash containing current validation errors.

    show code
    Document.prototype.errors;

    Document#id

    The string version of this documents _id.

    + +

    Note:

    + +

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    + +
    new Schema({ name: String }, { id: false });
    show code
    Document.prototype.id;

    Document#isNew

    Boolean flag specifying if the document is new.

    show code
    Document.prototype.isNew;

    Document#schema

    The documents schema.

    show code
    Document.prototype.schema;

  • types/decimal128.js

    exports()

    ObjectId type constructor

    Example

    + +
    var id = new mongoose.Types.ObjectId;

  • types/subdocument.js

    Subdocument#ownerDocument()

    Returns the top level document of this sub-document.

    Returns:

    show code
    Subdocument.prototype.ownerDocument = function() {
    +  if (this.$__.ownerDocument) {
    +    return this.$__.ownerDocument;
    +  }
    +
    +  var parent = this.$parent;
    +  if (!parent) {
    +    return this;
    +  }
    +
    +  while (parent.$parent || parent.__parent) {
    +    parent = parent.$parent || parent.__parent;
    +  }
    +  this.$__.ownerDocument = parent;
    +  return this.$__.ownerDocument;
    +};

    Subdocument#parent()

    Returns this sub-documents parent document.

    show code
    Subdocument.prototype.parent = function() {
    +  return this.$parent;
    +};

    Subdocument#remove([options], [callback])

    Null-out this subdoc

    Parameters:

    • [options] <Object>
    • [callback] <Function> optional callback for compatibility with Document.prototype.remove
    show code
    Subdocument.prototype.remove = function(options, callback) {
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
    +  }
    +
    +  registerRemoveListener(this);
    +
    +  // If removing entire doc, no need to remove subdoc
    +  if (!options || !options.noop) {
    +    this.$parent.set(this.$basePath, null);
    +  }
    +
    +  if (typeof callback === 'function') {
    +    callback(null);
    +  }
    +};

    Subdocument#save([fn])

    Used as a stub for hooks.js

    Parameters:

    Returns:

    NOTE:

    + +

    This is a no-op. Does not actually save the doc to the db.

    show code
    Subdocument.prototype.save = function(fn) {
    +  var Promise = PromiseProvider.get();
    +  return new Promise.ES6(function(resolve) {
    +    fn && fn();
    +    resolve();
    +  });
    +};
    +
    +Subdocument.prototype.$isValid = function(path) {
    +  if (this.$parent) {
    +    return this.$parent.$isValid([this.$basePath, path].join('.'));
    +  }
    +  return Document.prototype.$isValid.call(this, path);
    +};
    +
    +Subdocument.prototype.markModified = function(path) {
    +  Document.prototype.markModified.call(this, path);
    +  if (this.$parent) {
    +    if (this.$parent.isDirectModified(this.$basePath)) {
    +      return;
    +    }
    +    this.$parent.markModified([this.$basePath, path].join('.'));
    +  }
    +};
    +
    +Subdocument.prototype.$markValid = function(path) {
    +  Document.prototype.$markValid.call(this, path);
    +  if (this.$parent) {
    +    this.$parent.$markValid([this.$basePath, path].join('.'));
    +  }
    +};
    +
    +Subdocument.prototype.invalidate = function(path, err, val) {
    +  // Hack: array subdocuments' validationError is equal to the owner doc's,
    +  // so validating an array subdoc gives the top-level doc back. Temporary
    +  // workaround for #5208 so we don't have circular errors.
    +  if (err !== this.ownerDocument().$__.validationError) {
    +    Document.prototype.invalidate.call(this, path, err, val);
    +  }
    +
    +  if (this.$parent) {
    +    this.$parent.invalidate([this.$basePath, path].join('.'), err, val);
    +  } else if (err.kind === 'cast' || err.name === 'CastError') {
    +    throw err;
    +  }
    +};

    Subdocument()

    Subdocument constructor.

    Inherits:

    show code
    function Subdocument(value, fields) {
    +  this.$isSingleNested = true;
    +  Document.call(this, value, fields);
    +}
    +
    +Subdocument.prototype = Object.create(Document.prototype);
    +
    +Subdocument.prototype.toBSON = function() {
    +  return this.toObject({
    +    transform: false,
    +    virtuals: false,
    +    _skipDepopulateTopLevel: true,
    +    depopulate: true,
    +    flattenDecimals: false
    +  });
    +};

  • types/array.js

    MongooseArray#$__getAtomics()

    Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.

    Returns:

    If no atomics exist, we return all array values after conversion.


    MongooseArray#$shift()

    Atomically shifts the array at most one time per document save().

    NOTE:

    + +

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    + +
    doc.array = [1,2,3];
    +
    + var shifted = doc.array.$shift();
    + console.log(shifted); // 1
    + console.log(doc.array); // [2,3]
    +
    + // no affect
    + shifted = doc.array.$shift();
    + console.log(doc.array); // [2,3]
    +
    + doc.save(function (err) {
    +   if (err) return handleError(err);
    +
    +   // we saved, now $shift works again
    +   shifted = doc.array.$shift();
    +   console.log(shifted ); // 2
    +   console.log(doc.array); // [3]
    + })

    MongooseArray(values, path, doc)

    Mongoose Array constructor.

    Parameters:

    Inherits:

    NOTE:

    + +

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    show code
    function MongooseArray(values, path, doc) {
    +  var arr = [].concat(values);
    +
    +  var keysMA = Object.keys(MongooseArray.mixin);
    +  var numKeys = keysMA.length;
    +  for (var i = 0; i < numKeys; ++i) {
    +    arr[keysMA[i]] = MongooseArray.mixin[keysMA[i]];
    +  }
    +
    +  arr._path = path;
    +  arr.isMongooseArray = true;
    +  arr.validators = [];
    +  arr._atomics = {};
    +  arr._schema = void 0;
    +
    +  // Because doc comes from the context of another function, doc === global
    +  // can happen if there was a null somewhere up the chain (see #3020)
    +  // RB Jun 17, 2015 updated to check for presence of expected paths instead
    +  // to make more proof against unusual node environments
    +  if (doc && doc instanceof Document) {
    +    arr._parent = doc;
    +    arr._schema = doc.schema.path(path);
    +  }
    +
    +  return arr;
    +}
    +
    +MongooseArray.mixin = {

    MongooseArray._cast(value)

    Casts a member based on this arrays schema.

    Parameters:

    • value <T>

    Returns:

    • <value> the casted value

    MongooseArray._mapCast()

    Internal helper for .map()

    Returns:


    MongooseArray._markModified(embeddedDoc, embeddedPath)

    Marks this array as modified.

    Parameters:

    • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
    • embeddedPath <String> the path which changed in the embeddedDoc

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


    MongooseArray._registerAtomic(op, val)

    Register an atomic operation with the parent.

    Parameters:

    • op <Array> operation
    • val <T>

    MongooseArray.$pop()

    Pops the array atomically at most one time per document save().

    NOTE:

    + +

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    + +
    doc.array = [1,2,3];
    +
    + var popped = doc.array.$pop();
    + console.log(popped); // 3
    + console.log(doc.array); // [1,2]
    +
    + // no affect
    + popped = doc.array.$pop();
    + console.log(doc.array); // [1,2]
    +
    + doc.save(function (err) {
    +   if (err) return handleError(err);
    +
    +   // we saved, now $pop works again
    +   popped = doc.array.$pop();
    +   console.log(popped); // 2
    +   console.log(doc.array); // [1]
    + })

    MongooseArray.addToSet([args...])

    Adds values to the array if not already present.

    Parameters:

    • [args...] <T>

    Returns:

    • <Array> the values that were added

    Example:

    + +
    console.log(doc.array) // [2,3,4]
    +var added = doc.array.addToSet(4,5);
    +console.log(doc.array) // [2,3,4,5]
    +console.log(added)     // [5]

    MongooseArray.hasAtomics()

    Returns the number of pending atomic operations to send to the db for this array.

    Returns:


    MongooseArray.indexOf(obj)

    Return the index of obj or -1 if not found.

    Parameters:

    • obj <Object> the item to look for

    Returns:


    MongooseArray.inspect()

    Helper for console.log


    MongooseArray.nonAtomicPush([args...])

    Pushes items to the array non-atomically.

    Parameters:

    • [args...] <T>

    NOTE:

    + +

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray.pop()

    Wraps Array#pop with proper change tracking.

    Note:

    + +

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray.pull([args...])

    Pulls items from the array atomically. Equality is determined by casting
    the provided value to an embedded document and comparing using
    the Document.equals() function.

    Parameters:

    • [args...] <T>

    Examples:

    + +
    doc.array.pull(ObjectId)
    +doc.array.pull({ _id: 'someId' })
    +doc.array.pull(36)
    +doc.array.pull('tag 1', 'tag 2')
    + +

    To remove a document from a subdocument array we may pass an object with a matching _id.

    + +
    doc.subdocs.push({ _id: 4815162342 })
    +doc.subdocs.pull({ _id: 4815162342 }) // removed
    + +

    Or we may passing the _id directly and let mongoose take care of it.

    + +
    doc.subdocs.push({ _id: 4815162342 })
    +doc.subdocs.pull(4815162342); // works
    + +

    The first pull call will result in a atomic operation on the database, if pull is called repeatedly without saving the document, a $set operation is used on the complete array instead, overwriting possible changes that happened on the database in the meantime.


    MongooseArray.push([args...])

    Wraps Array#push with proper change tracking.

    Parameters:


    MongooseArray.set()

    Sets the casted val at index i and marks the array modified.

    Returns:

    Example:

    + +
    // given documents based on the following
    +var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
    +
    +var doc = new Doc({ array: [2,3,4] })
    +
    +console.log(doc.array) // [2,3,4]
    +
    +doc.array.set(1,"5");
    +console.log(doc.array); // [2,5,4] // properly cast to number
    +doc.save() // the change is saved
    +
    +// VS not using array#set
    +doc.array[1] = "5";
    +console.log(doc.array); // [2,"5",4] // no casting
    +doc.save() // change is not saved

    MongooseArray.shift()

    Wraps Array#shift with proper change tracking.

    Example:

    + +
    doc.array = [2,3];
    +var res = doc.array.shift();
    +console.log(res) // 2
    +console.log(doc.array) // [3]
    + +

    Note:

    + +

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray.sort()

    Wraps Array#sort with proper change tracking.

    NOTE:

    + +

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray.splice()

    Wraps Array#splice with proper change tracking and casting.

    Note:

    + +

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray.toObject(options)

    Returns a native js Array.

    Parameters:

    Returns:


    MongooseArray.unshift()

    Wraps Array#unshift with proper change tracking.

    Note:

    + +

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#_atomics

    Stores a queue of atomic operations to perform

    show code
    _atomics: undefined,

    MongooseArray#_parent

    Parent owner document

    show code
    _parent: undefined,

  • types/documentarray.js

    MongooseDocumentArray(values, path, doc)

    DocumentArray constructor

    Parameters:

    Inherits:

    show code
    function MongooseDocumentArray(values, path, doc) {
    +  var arr = [].concat(values);
    +  arr._path = path;
    +
    +  var props = {
    +    isMongooseArray: true,
    +    isMongooseDocumentArray: true,
    +    validators: [],
    +    _atomics: {},
    +    _schema: void 0,
    +    _handlers: void 0
    +  };
    +
    +  // Values always have to be passed to the constructor to initialize, since
    +  // otherwise MongooseArray#push will mark the array as modified to the parent.
    +  var keysMA = Object.keys(MongooseArray.mixin);
    +  var numKeys = keysMA.length;
    +  for (var j = 0; j < numKeys; ++j) {
    +    arr[keysMA[j]] = MongooseArray.mixin[keysMA[j]];
    +  }
    +
    +  var keysMDA = Object.keys(MongooseDocumentArray.mixin);
    +  numKeys = keysMDA.length;
    +  for (var i = 0; i < numKeys; ++i) {
    +    arr[keysMDA[i]] = MongooseDocumentArray.mixin[keysMDA[i]];
    +  }
    +
    +  var keysP = Object.keys(props);
    +  numKeys = keysP.length;
    +  for (var k = 0; k < numKeys; ++k) {
    +    arr[keysP[k]] = props[keysP[k]];
    +  }
    +
    +  // Because doc comes from the context of another function, doc === global
    +  // can happen if there was a null somewhere up the chain (see #3020 && #3034)
    +  // RB Jun 17, 2015 updated to check for presence of expected paths instead
    +  // to make more proof against unusual node environments
    +  if (doc && doc instanceof Document) {
    +    arr._parent = doc;
    +    arr._schema = doc.schema.path(path);
    +    arr._handlers = {
    +      isNew: arr.notify('isNew'),
    +      save: arr.notify('save')
    +    };
    +
    +    doc.on('save', arr._handlers.save);
    +    doc.on('isNew', arr._handlers.isNew);
    +  }
    +
    +  return arr;
    +}

    MongooseDocumentArray._cast()

    Overrides MongooseArray#cast


    MongooseDocumentArray.create(obj)

    Creates a subdocument casted to this schema.

    Parameters:

    • obj <Object> the value to cast to this arrays SubDocument schema

    This is the same subdocument constructor used for casting.


    MongooseDocumentArray.id(id)

    Searches array items for the first document with a matching _id.

    Parameters:

    Returns:

    Example:

    + +
    var embeddedDoc = m.array.id(some_id);

    MongooseDocumentArray.inspect()

    Helper for console.log


    MongooseDocumentArray.notify(event)

    Creates a fn that notifies all child docs of event.

    Parameters:

    Returns:


    MongooseDocumentArray.toObject([options])

    Returns a native js Array of plain js objects

    Parameters:

    • [options] <Object> optional options to pass to each documents <code>toObject</code> method call during conversion

    Returns:

    NOTE:

    + +

    Each sub-document is converted to a plain object by calling its #toObject method.


  • types/buffer.js

    MongooseBuffer(value, encode, offset)

    Mongoose Buffer constructor.

    Parameters:

    Inherits:

    Values always have to be passed to the constructor to initialize.

    show code
    function MongooseBuffer(value, encode, offset) {
    +  var length = arguments.length;
    +  var val;
    +
    +  if (length === 0 || arguments[0] === null || arguments[0] === undefined) {
    +    val = 0;
    +  } else {
    +    val = value;
    +  }
    +
    +  var encoding;
    +  var path;
    +  var doc;
    +
    +  if (Array.isArray(encode)) {
    +    // internal casting
    +    path = encode[0];
    +    doc = encode[1];
    +  } else {
    +    encoding = encode;
    +  }
    +
    +  var buf = new Buffer(val, encoding, offset);
    +  utils.decorate(buf, MongooseBuffer.mixin);
    +  buf.isMongooseBuffer = true;
    +
    +  // make sure these internal props don't show up in Object.keys()
    +  Object.defineProperties(buf, {
    +    validators: {value: []},
    +    _path: {value: path},
    +    _parent: {value: doc}
    +  });
    +
    +  if (doc && typeof path === 'string') {
    +    Object.defineProperty(buf, '_schema', {
    +      value: doc.schema.path(path)
    +    });
    +  }
    +
    +  buf._subtype = 0;
    +  return buf;
    +}

    MongooseBuffer._markModified()

    Marks this buffer as modified.


    MongooseBuffer.copy(target)

    Copies the buffer.

    Parameters:

    Returns:

    • <Number> The number of bytes copied.

    Note:

    + +

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


    MongooseBuffer.equals(other)

    Determines if this buffer is equals to other buffer

    Parameters:

    Returns:


    MongooseBuffer.subtype(subtype)

    Sets the subtype option and marks the buffer modified.

    Parameters:

    SubTypes:

    + +

    var bson = require('bson')
    bson.BSON_BINARY_SUBTYPE_DEFAULT
    bson.BSON_BINARY_SUBTYPE_FUNCTION
    bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
    bson.BSON_BINARY_SUBTYPE_UUID
    bson.BSON_BINARY_SUBTYPE_MD5
    bson.BSON_BINARY_SUBTYPE_USER_DEFINED

    + +

    doc.buffer.subtype(bson.BSON_BINARY_SUBTYPE_UUID);


    MongooseBuffer.toBSON()

    Converts this buffer for storage in MongoDB, including subtype

    Returns:


    MongooseBuffer.toObject([subtype])

    Converts this buffer to its Binary type representation.

    Parameters:

    • [subtype] <Hex>

    Returns:

    SubTypes:

    + +

    var bson = require('bson')
    bson.BSON_BINARY_SUBTYPE_DEFAULT
    bson.BSON_BINARY_SUBTYPE_FUNCTION
    bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
    bson.BSON_BINARY_SUBTYPE_UUID
    bson.BSON_BINARY_SUBTYPE_MD5
    bson.BSON_BINARY_SUBTYPE_USER_DEFINED

    + +

    doc.buffer.toObject(bson.BSON_BINARY_SUBTYPE_USER_DEFINED);


    MongooseBuffer.write()

    Writes the buffer.


    MongooseBuffer#_parent

    Parent owner document

    show code
    _parent: undefined,

    MongooseBuffer#_subtype

    Default subtype for the Binary representing this Buffer

    show code
    _subtype: undefined,

  • types/objectid.js

    ObjectId()

    ObjectId type constructor

    Example

    + +
    var id = new mongoose.Types.ObjectId;

  • types/embedded.js

    EmbeddedDocument#$__fullPath([path])

    Returns the full path to this document. If optional path is passed, it is appended to the full path.

    Parameters:

    Returns:


    EmbeddedDocument(obj, parentArr, skipId)

    EmbeddedDocument constructor.

    Parameters:

    Inherits:

    show code
    function EmbeddedDocument(obj, parentArr, skipId, fields, index) {
    +  if (parentArr) {
    +    this.__parentArray = parentArr;
    +    this.__parent = parentArr._parent;
    +  } else {
    +    this.__parentArray = undefined;
    +    this.__parent = undefined;
    +  }
    +  this.__index = index;
    +
    +  Document.call(this, obj, fields, skipId);
    +
    +  var _this = this;
    +  this.on('isNew', function(val) {
    +    _this.isNew = val;
    +  });
    +
    +  _this.on('save', function() {
    +    _this.constructor.emit('save', _this);
    +  });
    +}

    EmbeddedDocument#inspect()

    Helper for console.log

    show code
    EmbeddedDocument.prototype.inspect = function() {
    +  return this.toObject({
    +    transform: false,
    +    retainKeyOrder: true,
    +    virtuals: false,
    +    flattenDecimals: false
    +  });
    +};

    EmbeddedDocument#invalidate(path, err)

    Marks a path as invalid, causing validation to fail.

    Parameters:

    • path <String> the field to invalidate
    • err <String, Error> error which states the reason path was invalid

    Returns:

    show code
    EmbeddedDocument.prototype.invalidate = function(path, err, val, first) {
    +  if (!this.__parent) {
    +    Document.prototype.invalidate.call(this, path, err, val);
    +    if (err.$isValidatorError) {
    +      return true;
    +    }
    +    throw err;
    +  }
    +
    +  var index = this.__index;
    +  if (typeof index !== 'undefined') {
    +    var parentPath = this.__parentArray._path;
    +    var fullPath = [parentPath, index, path].join('.');
    +    this.__parent.invalidate(fullPath, err, val);
    +  }
    +
    +  if (first) {
    +    this.$__.validationError = this.ownerDocument().$__.validationError;
    +  }
    +
    +  return true;
    +};

    EmbeddedDocument#ownerDocument()

    Returns the top level document of this sub-document.

    Returns:

    show code
    EmbeddedDocument.prototype.ownerDocument = function() {
    +  if (this.$__.ownerDocument) {
    +    return this.$__.ownerDocument;
    +  }
    +
    +  var parent = this.__parent;
    +  if (!parent) {
    +    return this;
    +  }
    +
    +  while (parent.__parent || parent.$parent) {
    +    parent = parent.__parent || parent.$parent;
    +  }
    +
    +  this.$__.ownerDocument = parent;
    +  return this.$__.ownerDocument;
    +};

    EmbeddedDocument#parent()

    Returns this sub-documents parent document.

    show code
    EmbeddedDocument.prototype.parent = function() {
    +  return this.__parent;
    +};

    EmbeddedDocument#parentArray()

    Returns this sub-documents parent array.

    show code
    EmbeddedDocument.prototype.parentArray = function() {
    +  return this.__parentArray;
    +};

    EmbeddedDocument#remove([options], [fn])

    Removes the subdocument from its parent array.

    Parameters:

    show code
    EmbeddedDocument.prototype.remove = function(options, fn) {
    +  if ( typeof options === 'function' && !fn ) {
    +    fn = options;
    +    options = undefined;
    +  }
    +  if (!this.__parentArray || (options && options.noop)) {
    +    fn && fn(null);
    +    return this;
    +  }
    +
    +  var _id;
    +  if (!this.willRemove) {
    +    _id = this._doc._id;
    +    if (!_id) {
    +      throw new Error('For your own good, Mongoose does not know ' +
    +          'how to remove an EmbeddedDocument that has no _id');
    +    }
    +    this.__parentArray.pull({_id: _id});
    +    this.willRemove = true;
    +    registerRemoveListener(this);
    +  }
    +
    +  if (fn) {
    +    fn(null);
    +  }
    +
    +  return this;
    +};

    EmbeddedDocument#save([fn])

    Used as a stub for hooks.js

    Parameters:

    Returns:

    NOTE:

    + +

    This is a no-op. Does not actually save the doc to the db.

    show code
    EmbeddedDocument.prototype.save = function(fn) {
    +  var Promise = PromiseProvider.get();
    +  return new Promise.ES6(function(resolve) {
    +    fn && fn();
    +    resolve();
    +  });
    +};

    EmbeddedDocument#update()

    Override #update method of parent documents.

    show code
    EmbeddedDocument.prototype.update = function() {
    +  throw new Error('The #update method is not available on EmbeddedDocuments');
    +};

    EmbeddedDocument.$isValid(path)

    Checks if a path is invalid

    Parameters:

    • path <String> the field to check

    EmbeddedDocument.$markValid(path)

    Marks a path as valid, removing existing validation errors.

    Parameters:

    • path <String> the field to mark as valid

    EmbeddedDocument.markModified(path)

    Marks the embedded doc modified.

    show code
    EmbeddedDocument.prototype.markModified = function(path) {
    +  this.$__.activePaths.modify(path);
    +  if (!this.__parentArray) {
    +    return;
    +  }
    +
    +  if (this.isNew) {
    +    // Mark the WHOLE parent array as modified
    +    // if this is a new document (i.e., we are initializing
    +    // a document),
    +    this.__parentArray._markModified();
    +  } else {
    +    this.__parentArray._markModified(this, path);
    +  }
    +};

    Parameters:

    • path <String> the path which changed

    Example:

    + +
    var doc = blogpost.comments.id(hexstring);
    +doc.mixed.type = 'changed';
    +doc.markModified('mixed.type');

  • cursor/AggregationCursor.js

    AggregationCursor#addCursorFlag(flag, value)

    Adds a cursor flag.
    Useful for setting the noCursorTimeout and tailable flags.

    Parameters:

    Returns:


    AggregationCursor(agg, options)

    An AggregationCursor is a concurrency primitive for processing aggregation
    results one document at a time. It is analogous to QueryCursor.

    Parameters:

    Inherits:

    Events:

    • cursor: Emitted when the cursor is created

    • error: Emitted when an error occurred

    • data: Emitted when the stream is flowing and the next doc is ready

    • end: Emitted when the stream is exhausted

    An AggregationCursor fulfills the Node.js streams3 API,
    in addition to several other mechanisms for loading documents from MongoDB
    one at a time.

    + +

    Unless you're an advanced user, do not instantiate this class directly.
    Use Aggregate#cursor() instead.

    show code
    function AggregationCursor(agg) {
    +  Readable.call(this, { objectMode: true });
    +
    +  this.cursor = null;
    +  this.agg = agg;
    +  this._transforms = [];
    +  var model = agg._model;
    +  delete agg.options.cursor.useMongooseAggCursor;
    +
    +  _init(model, this, agg);
    +}
    +
    +util.inherits(AggregationCursor, Readable);

    AggregationCursor#close(callback)

    Marks this cursor as closed. Will stop streaming and subsequent calls to
    next() will error.

    Parameters:

    Returns:


    AggregationCursor#eachAsync(fn, [callback])

    Execute fn for every document in the cursor. If fn returns a promise,
    will wait for the promise to resolve before iterating on to the next one.
    Returns a promise that resolves when done.

    Parameters:

    Returns:


    AggregationCursor#map(fn)

    Registers a transform function which subsequently maps documents retrieved
    via the streams interface or .next()

    Parameters:

    Returns:

    Example

    + +
    // Map documents returned by `data` events
    +Thing.
    +  find({ name: /^hello/ }).
    +  cursor().
    +  map(function (doc) {
    +   doc.foo = "bar";
    +   return doc;
    +  })
    +  on('data', function(doc) { console.log(doc.foo); });
    +
    +// Or map documents returned by `.next()`
    +var cursor = Thing.find({ name: /^hello/ }).
    +  cursor().
    +  map(function (doc) {
    +    doc.foo = "bar";
    +    return doc;
    +  });
    +cursor.next(function(error, doc) {
    +  console.log(doc.foo);
    +});

    AggregationCursor#next(callback)

    Get the next document from this cursor. Will return null when there are
    no documents left.

    Parameters:

    Returns:


  • cursor/QueryCursor.js

    QueryCursor#addCursorFlag(flag, value)

    Adds a cursor flag.
    Useful for setting the noCursorTimeout and tailable flags.

    Parameters:

    Returns:


    QueryCursor#close(callback)

    Marks this cursor as closed. Will stop streaming and subsequent calls to
    next() will error.

    Parameters:

    Returns:


    QueryCursor#eachAsync(fn, [options], [options.parallel], [callback])

    Execute fn for every document in the cursor. If fn returns a promise,
    will wait for the promise to resolve before iterating on to the next one.
    Returns a promise that resolves when done.

    Parameters:

    • fn <Function>
    • [options] <Object>
    • [options.parallel] <Number> the number of promises to execute in parallel. Defaults to 1.
    • [callback] <Function> executed when all docs have been processed

    Returns:


    QueryCursor#map(fn)

    Registers a transform function which subsequently maps documents retrieved
    via the streams interface or .next()

    Parameters:

    Returns:

    Example

    + +
    // Map documents returned by `data` events
    +Thing.
    +  find({ name: /^hello/ }).
    +  cursor().
    +  map(function (doc) {
    +   doc.foo = "bar";
    +   return doc;
    +  })
    +  on('data', function(doc) { console.log(doc.foo); });
    +
    +// Or map documents returned by `.next()`
    +var cursor = Thing.find({ name: /^hello/ }).
    +  cursor().
    +  map(function (doc) {
    +    doc.foo = "bar";
    +    return doc;
    +  });
    +cursor.next(function(error, doc) {
    +  console.log(doc.foo);
    +});

    QueryCursor#next(callback)

    Get the next document from this cursor. Will return null when there are
    no documents left.

    Parameters:

    Returns:


    QueryCursor(query, options)

    A QueryCursor is a concurrency primitive for processing query results
    one document at a time. A QueryCursor fulfills the Node.js streams3 API,
    in addition to several other mechanisms for loading documents from MongoDB
    one at a time.

    Parameters:

    • query <Query>
    • options <Object> query options passed to .find()

    Inherits:

    Events:

    • cursor: Emitted when the cursor is created

    • error: Emitted when an error occurred

    • data: Emitted when the stream is flowing and the next doc is ready

    • end: Emitted when the stream is exhausted

    QueryCursors execute the model's pre find hooks, but not the model's
    post find hooks.

    + +

    Unless you're an advanced user, do not instantiate this class directly.
    Use Query#cursor() instead.

    show code
    function QueryCursor(query, options) {
    +  Readable.call(this, { objectMode: true });
    +
    +  this.cursor = null;
    +  this.query = query;
    +  this._transforms = options.transform ? [options.transform] : [];
    +  var _this = this;
    +  var model = query.model;
    +  model.hooks.execPre('find', query, function() {
    +    model.collection.find(query._conditions, options, function(err, cursor) {
    +      if (_this._error) {
    +        cursor.close(function() {});
    +        _this.listeners('error').length > 0 && _this.emit('error', _this._error);
    +      }
    +      if (err) {
    +        return _this.emit('error', err);
    +      }
    +      _this.cursor = cursor;
    +      _this.emit('cursor', cursor);
    +    });
    +  });
    +}
    +
    +util.inherits(QueryCursor, Readable);

  • cast.js

    module.exports(schema, obj, options, context)

    Handles internal casting for queries

    show code
    module.exports = function cast(schema, obj, options, context) {
    +  if (Array.isArray(obj)) {
    +    throw new Error('Query filter must be an object, got an array ', util.inspect(obj));
    +  }
    +
    +  var paths = Object.keys(obj);
    +  var i = paths.length;
    +  var _keys;
    +  var any$conditionals;
    +  var schematype;
    +  var nested;
    +  var path;
    +  var type;
    +  var val;
    +
    +  while (i--) {
    +    path = paths[i];
    +    val = obj[path];
    +
    +    if (path === '$or' || path === '$nor' || path === '$and') {
    +      var k = val.length;
    +
    +      while (k--) {
    +        val[k] = cast(schema, val[k], options, context);
    +      }
    +    } else if (path === '$where') {
    +      type = typeof val;
    +
    +      if (type !== 'string' && type !== 'function') {
    +        throw new Error('Must have a string or function for $where');
    +      }
    +
    +      if (type === 'function') {
    +        obj[path] = val.toString();
    +      }
    +
    +      continue;
    +    } else if (path === '$elemMatch') {
    +      val = cast(schema, val, options, context);
    +    } else {
    +      if (!schema) {
    +        // no casting for Mixed types
    +        continue;
    +      }
    +
    +      schematype = schema.path(path);
    +
    +      if (!schematype) {
    +        // Handle potential embedded array queries
    +        var split = path.split('.'),
    +            j = split.length,
    +            pathFirstHalf,
    +            pathLastHalf,
    +            remainingConds;
    +
    +        // Find the part of the var path that is a path of the Schema
    +        while (j--) {
    +          pathFirstHalf = split.slice(0, j).join('.');
    +          schematype = schema.path(pathFirstHalf);
    +          if (schematype) {
    +            break;
    +          }
    +        }
    +
    +        // If a substring of the input path resolves to an actual real path...
    +        if (schematype) {
    +          // Apply the casting; similar code for $elemMatch in schema/array.js
    +          if (schematype.caster && schematype.caster.schema) {
    +            remainingConds = {};
    +            pathLastHalf = split.slice(j).join('.');
    +            remainingConds[pathLastHalf] = val;
    +            obj[path] = cast(schematype.caster.schema, remainingConds, options, context)[pathLastHalf];
    +          } else {
    +            obj[path] = val;
    +          }
    +          continue;
    +        }
    +
    +        if (utils.isObject(val)) {
    +          // handle geo schemas that use object notation
    +          // { loc: { long: Number, lat: Number }
    +
    +          var geo = '';
    +          if (val.$near) {
    +            geo = '$near';
    +          } else if (val.$nearSphere) {
    +            geo = '$nearSphere';
    +          } else if (val.$within) {
    +            geo = '$within';
    +          } else if (val.$geoIntersects) {
    +            geo = '$geoIntersects';
    +          } else if (val.$geoWithin) {
    +            geo = '$geoWithin';
    +          }
    +
    +          if (geo) {
    +            var numbertype = new Types.Number('__QueryCasting__');
    +            var value = val[geo];
    +
    +            if (val.$maxDistance != null) {
    +              val.$maxDistance = numbertype.castForQueryWrapper({
    +                val: val.$maxDistance,
    +                context: context
    +              });
    +            }
    +            if (val.$minDistance != null) {
    +              val.$minDistance = numbertype.castForQueryWrapper({
    +                val: val.$minDistance,
    +                context: context
    +              });
    +            }
    +
    +            if (geo === '$within') {
    +              var withinType = value.$center
    +                  || value.$centerSphere
    +                  || value.$box
    +                  || value.$polygon;
    +
    +              if (!withinType) {
    +                throw new Error('Bad $within paramater: ' + JSON.stringify(val));
    +              }
    +
    +              value = withinType;
    +            } else if (geo === '$near' &&
    +                typeof value.type === 'string' && Array.isArray(value.coordinates)) {
    +              // geojson; cast the coordinates
    +              value = value.coordinates;
    +            } else if ((geo === '$near' || geo === '$nearSphere' || geo === '$geoIntersects') &&
    +                value.$geometry && typeof value.$geometry.type === 'string' &&
    +                Array.isArray(value.$geometry.coordinates)) {
    +              if (value.$maxDistance != null) {
    +                value.$maxDistance = numbertype.castForQueryWrapper({
    +                  val: value.$maxDistance,
    +                  context: context
    +                });
    +              }
    +              if (value.$minDistance != null) {
    +                value.$minDistance = numbertype.castForQueryWrapper({
    +                  val: value.$minDistance,
    +                  context: context
    +                });
    +              }
    +              if (utils.isMongooseObject(value.$geometry)) {
    +                value.$geometry = value.$geometry.toObject({
    +                  transform: false,
    +                  virtuals: false
    +                });
    +              }
    +              value = value.$geometry.coordinates;
    +            } else if (geo === '$geoWithin') {
    +              if (value.$geometry) {
    +                if (utils.isMongooseObject(value.$geometry)) {
    +                  value.$geometry = value.$geometry.toObject({ virtuals: false });
    +                }
    +                var geoWithinType = value.$geometry.type;
    +                if (ALLOWED_GEOWITHIN_GEOJSON_TYPES.indexOf(geoWithinType) === -1) {
    +                  throw new Error('Invalid geoJSON type for $geoWithin "' +
    +                    geoWithinType + '", must be "Polygon" or "MultiPolygon"');
    +                }
    +                value = value.$geometry.coordinates;
    +              } else {
    +                value = value.$box || value.$polygon || value.$center ||
    +                  value.$centerSphere;
    +                if (utils.isMongooseObject(value)) {
    +                  value = value.toObject({ virtuals: false });
    +                }
    +              }
    +            }
    +
    +            _cast(value, numbertype, context);
    +            continue;
    +          }
    +        }
    +
    +        if (options && options.upsert && options.strict) {
    +          if (options.strict === 'throw') {
    +            throw new StrictModeError(path);
    +          }
    +          throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
    +            'schema, strict mode is `true`, and upsert is `true`.');
    +        } else if (options && options.strictQuery === 'throw') {
    +          throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
    +            'schema and strictQuery is true.');
    +        }
    +      } else if (val === null || val === undefined) {
    +        obj[path] = null;
    +        continue;
    +      } else if (val.constructor.name === 'Object') {
    +        any$conditionals = Object.keys(val).some(function(k) {
    +          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
    +        });
    +
    +        if (!any$conditionals) {
    +          obj[path] = schematype.castForQueryWrapper({
    +            val: val,
    +            context: context
    +          });
    +        } else {
    +          var ks = Object.keys(val),
    +              $cond;
    +
    +          k = ks.length;
    +
    +          while (k--) {
    +            $cond = ks[k];
    +            nested = val[$cond];
    +
    +            if ($cond === '$not') {
    +              if (nested && schematype && !schematype.caster) {
    +                _keys = Object.keys(nested);
    +                if (_keys.length && _keys[0].charAt(0) === '$') {
    +                  for (var key in nested) {
    +                    nested[key] = schematype.castForQueryWrapper({
    +                      $conditional: key,
    +                      val: nested[key],
    +                      context: context
    +                    });
    +                  }
    +                } else {
    +                  val[$cond] = schematype.castForQueryWrapper({
    +                    $conditional: $cond,
    +                    val: nested,
    +                    context: context
    +                  });
    +                }
    +                continue;
    +              }
    +              cast(schematype.caster ? schematype.caster.schema : schema, nested, options, context);
    +            } else {
    +              val[$cond] = schematype.castForQueryWrapper({
    +                $conditional: $cond,
    +                val: nested,
    +                context: context
    +              });
    +            }
    +          }
    +        }
    +      } else if (val.constructor.name === 'Array' && ['Buffer', 'Array'].indexOf(schematype.instance) === -1) {
    +        var casted = [];
    +        for (var valIndex = 0; valIndex < val.length; valIndex++) {
    +          casted.push(schematype.castForQueryWrapper({
    +            val: val[valIndex],
    +            context: context
    +          }));
    +        }
    +
    +        obj[path] = { $in: casted };
    +      } else {
    +        obj[path] = schematype.castForQueryWrapper({
    +          val: val,
    +          context: context
    +        });
    +      }
    +    }
    +  }
    +
    +  return obj;
    +};
    +
    +function _cast(val, numbertype, context) {
    +  if (Array.isArray(val)) {
    +    val.forEach(function(item, i) {
    +      if (Array.isArray(item) || utils.isObject(item)) {
    +        return _cast(item, numbertype, context);
    +      }
    +      val[i] = numbertype.castForQueryWrapper({ val: item, context: context });
    +    });
    +  } else {
    +    var nearKeys = Object.keys(val);
    +    var nearLen = nearKeys.length;
    +    while (nearLen--) {
    +      var nkey = nearKeys[nearLen];
    +      var item = val[nkey];
    +      if (Array.isArray(item) || utils.isObject(item)) {
    +        _cast(item, numbertype, context);
    +        val[nkey] = item;
    +      } else {
    +        val[nkey] = numbertype.castForQuery({ val: item, context: context });
    +      }
    +    }
    +  }
    +}

    Parameters:


  • query.js

    Query#_applyPaths()

    Applies schematype selected options to this query.

    show code
    Query.prototype._applyPaths = function applyPaths() {
    +  this._fields = this._fields || {};
    +  helpers.applyPaths(this._fields, this.model.schema);
    +};

    Query#_castFields(fields)

    Casts selected field arguments for field selection with mongo 2.2

    Parameters:

    query.select({ ids: { $elemMatch: { $in: [hexString] }})
    show code
    Query.prototype._castFields = function _castFields(fields) {
    +  var selected,
    +      elemMatchKeys,
    +      keys,
    +      key,
    +      out,
    +      i;
    +
    +  if (fields) {
    +    keys = Object.keys(fields);
    +    elemMatchKeys = [];
    +    i = keys.length;
    +
    +    // collect $elemMatch args
    +    while (i--) {
    +      key = keys[i];
    +      if (fields[key].$elemMatch) {
    +        selected || (selected = {});
    +        selected[key] = fields[key];
    +        elemMatchKeys.push(key);
    +      }
    +    }
    +  }
    +
    +  if (selected) {
    +    // they passed $elemMatch, cast em
    +    try {
    +      out = this.cast(this.model, selected);
    +    } catch (err) {
    +      return err;
    +    }
    +
    +    // apply the casted field args
    +    i = elemMatchKeys.length;
    +    while (i--) {
    +      key = elemMatchKeys[i];
    +      fields[key] = out[key];
    +    }
    +  }
    +
    +  return fields;
    +};

    Query#_count([callback])

    Thunk around count()

    Parameters:

    See:

    show code
    Query.prototype._count = function(callback) {
    +  try {
    +    this.cast(this.model);
    +  } catch (err) {
    +    process.nextTick(function() {
    +      callback(err);
    +    });
    +    return this;
    +  }
    +
    +  var conds = this._conditions;
    +  var options = this._optionsForExec();
    +
    +  this._collection.count(conds, options, utils.tick(callback));
    +};

    Query#_find([callback])

    Thunk around find()

    Parameters:

    Returns:

    show code
    Query.prototype._find = function(callback) {
    +  this._castConditions();
    +
    +  if (this._castError) {
    +    callback(this._castError);
    +    return this;
    +  }
    +
    +  this._applyPaths();
    +  this._fields = this._castFields(this._fields);
    +
    +  var fields = this._fieldsForExec();
    +  var options = this._mongooseOptions;
    +  var _this = this;
    +  var userProvidedFields = _this._userProvidedFields || {};
    +
    +  var cb = function(err, docs) {
    +    if (err) {
    +      return callback(err);
    +    }
    +
    +    if (docs.length === 0) {
    +      return callback(null, docs);
    +    }
    +
    +    if (!options.populate) {
    +      return !!options.lean === true
    +          ? callback(null, docs)
    +          : completeMany(_this.model, docs, fields, userProvidedFields, null, callback);
    +    }
    +
    +    var pop = helpers.preparePopulationOptionsMQ(_this, options);
    +    pop.__noPromise = true;
    +    _this.model.populate(docs, pop, function(err, docs) {
    +      if (err) return callback(err);
    +      return !!options.lean === true
    +          ? callback(null, docs)
    +          : completeMany(_this.model, docs, fields, userProvidedFields, pop, callback);
    +    });
    +  };
    +
    +  return Query.base.find.call(this, {}, cb);
    +};

    Query#_findOne([callback])

    Thunk around findOne()

    Parameters:

    show code
    Query.prototype._findOne = function(callback) {
    +  this._castConditions();
    +
    +  if (this._castError) {
    +    return callback(this._castError);
    +  }
    +
    +  this._applyPaths();
    +  this._fields = this._castFields(this._fields);
    +
    +  var options = this._mongooseOptions;
    +  var projection = this._fieldsForExec();
    +  var userProvidedFields = this._userProvidedFields || {};
    +  var _this = this;
    +
    +  // don't pass in the conditions because we already merged them in
    +  Query.base.findOne.call(_this, {}, function(err, doc) {
    +    if (err) {
    +      return callback(err);
    +    }
    +    if (!doc) {
    +      return callback(null, null);
    +    }
    +
    +    if (!options.populate) {
    +      return !!options.lean === true
    +          ? callback(null, doc)
    +          : completeOne(_this.model, doc, null, {}, projection, userProvidedFields, null, callback);
    +    }
    +
    +    var pop = helpers.preparePopulationOptionsMQ(_this, options);
    +    pop.__noPromise = true;
    +    _this.model.populate(doc, pop, function(err, doc) {
    +      if (err) {
    +        return callback(err);
    +      }
    +      return !!options.lean === true
    +          ? callback(null, doc)
    +          : completeOne(_this.model, doc, null, {}, projection, userProvidedFields, pop, callback);
    +    });
    +  });
    +};

    Query#_optionsForExec(model)

    Returns default options for this query.

    Parameters:

    show code
    Query.prototype._optionsForExec = function(model) {
    +  var options = Query.base._optionsForExec.call(this);
    +
    +  delete options.populate;
    +  delete options.retainKeyOrder;
    +  model = model || this.model;
    +
    +  if (!model) {
    +    return options;
    +  }
    +
    +  if (!('safe' in options) && model.schema.options.safe) {
    +    options.safe = model.schema.options.safe;
    +  }
    +
    +  if (!('readPreference' in options) && model.schema.options.read) {
    +    options.readPreference = model.schema.options.read;
    +  }
    +
    +  return options;
    +};

    Query#$where(js)

    Specifies a javascript function or expression to pass to MongoDBs query system.

    Parameters:

    Returns:

    See:

    Example

    + +
    query.$where('this.comments.length === 10 || this.name.length === 5')
    +
    +// or
    +
    +query.$where(function () {
    +  return this.comments.length === 10 || this.name.length === 5;
    +})
    + +

    NOTE:

    + +

    Only use $where when you have a condition that cannot be met using other MongoDB operators like $lt.
    Be sure to read about all of its caveats before using.


    Query#all([path], val)

    Specifies an $all query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.


    Query#and(array)

    Specifies arguments for a $and condition.

    Parameters:

    • array <Array> array of conditions

    Returns:

    See:

    Example

    + +
    query.and([{ color: 'green' }, { status: 'ok' }])

    Query#batchSize(val)

    Specifies the batchSize option.

    Parameters:

    Example

    + +
    query.batchSize(100)
    + +

    Note

    + +

    Cannot be used with distinct()


    Query#box(val, Upper)

    Specifies a $box condition

    Parameters:

    Returns:

    Example

    + +
    var lowerLeft = [40.73083, -73.99756]
    +var upperRight= [40.741404,  -73.988135]
    +
    +query.where('loc').within().box(lowerLeft, upperRight)
    +query.box({ ll : lowerLeft, ur : upperRight })

    Query#canMerge(conds)

    Determines if conds can be merged using mquery().merge()

    Parameters:

    Returns:


    Query#cast(model, [obj])

    Casts this query to the schema of model

    Parameters:

    Returns:

    Note

    + +

    If obj is present, it is cast instead of this query.

    show code
    Query.prototype.cast = function(model, obj) {
    +  obj || (obj = this._conditions);
    +
    +  try {
    +    return cast(model.schema, obj, {
    +      upsert: this.options && this.options.upsert,
    +      strict: (this.options && 'strict' in this.options) ?
    +        this.options.strict :
    +        (model.schema.options && model.schema.options.strict),
    +      strictQuery: (this.options && this.options.strictQuery) ||
    +        (model.schema.options && model.schema.options.strictQuery)
    +    }, this);
    +  } catch (err) {
    +    // CastError, assign model
    +    if (typeof err.setModel === 'function') {
    +      err.setModel(model);
    +    }
    +    throw err;
    +  }
    +};

    Query#catch([reject])

    Executes the query returning a Promise which will be
    resolved with either the doc(s) or rejected with the error.
    Like .then(), but only takes a rejection handler.

    Parameters:

    Returns:

    show code
    Query.prototype.catch = function(reject) {
    +  return this.exec().then(null, reject);
    +};

    Query#center()

    DEPRECATED Alias for circle

    Deprecated. Use circle instead.


    Query#centerSphere([path], val)

    DEPRECATED Specifies a $centerSphere condition

    Parameters:

    Returns:

    Deprecated. Use circle instead.

    + +

    Example

    + +
    var area = { center: [50, 50], radius: 10 };
    +query.where('loc').within().centerSphere(area);
    show code
    Query.prototype.centerSphere = function() {
    +  if (arguments[0] && arguments[0].constructor.name === 'Object') {
    +    arguments[0].spherical = true;
    +  }
    +
    +  if (arguments[1] && arguments[1].constructor.name === 'Object') {
    +    arguments[1].spherical = true;
    +  }
    +
    +  Query.base.circle.apply(this, arguments);
    +};

    Query#circle([path], area)

    Specifies a $center or $centerSphere condition.

    Parameters:

    Returns:

    Example

    + +
    var area = { center: [50, 50], radius: 10, unique: true }
    +query.where('loc').within().circle(area)
    +// alternatively
    +query.circle('loc', area);
    +
    +// spherical calculations
    +var area = { center: [50, 50], radius: 10, unique: true, spherical: true }
    +query.where('loc').within().circle(area)
    +// alternatively
    +query.circle('loc', area);
    + +

    New in 3.7.0


    Query#collation(value)

    Adds a collation to this op (MongoDB 3.4 and up)

    Parameters:

    Returns:

    show code
    Query.prototype.collation = function(value) {
    +  if (this.options == null) {
    +    this.options = {};
    +  }
    +  this.options.collation = value;
    +  return this;
    +};

    Query#comment(val)

    Specifies the comment option.

    Parameters:

    Example

    + +
    query.comment('login query')
    + +

    Note

    + +

    Cannot be used with distinct()


    Query#count([criteria], [callback])

    Specifying this query as a count query.

    Parameters:

    • [criteria] <Object> mongodb selector
    • [callback] <Function> optional params are (error, count)

    Returns:

    See:

    Passing a callback executes the query.

    + +

    Example:

    + +
    var countQuery = model.where({ 'color': 'black' }).count();
    +
    +query.count({ color: 'black' }).count(callback)
    +
    +query.count({ color: 'black' }, callback)
    +
    +query.where('color', 'black').count(function (err, count) {
    +  if (err) return handleError(err);
    +  console.log('there are %d kittens', count);
    +})
    show code
    Query.prototype.count = function(conditions, callback) {
    +  if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = undefined;
    +  }
    +
    +  if (mquery.canMerge(conditions)) {
    +    this.merge(conditions);
    +  }
    +
    +  this.op = 'count';
    +  if (!callback) {
    +    return this;
    +  }
    +
    +  this._count(callback);
    +
    +  return this;
    +};

    Query#cursor([options])

    Returns a wrapper around a mongodb driver cursor.
    A QueryCursor exposes a Streams3-compatible
    interface, as well as a .next() function.

    Parameters:

    Returns:

    The .cursor() function triggers pre find hooks, but not post find hooks.

    + +

    Example

    + +
    // There are 2 ways to use a cursor. First, as a stream:
    +Thing.
    +  find({ name: /^hello/ }).
    +  cursor().
    +  on('data', function(doc) { console.log(doc); }).
    +  on('end', function() { console.log('Done!'); });
    +
    +// Or you can use `.next()` to manually get the next doc in the stream.
    +// `.next()` returns a promise, so you can use promises or callbacks.
    +var cursor = Thing.find({ name: /^hello/ }).cursor();
    +cursor.next(function(error, doc) {
    +  console.log(doc);
    +});
    +
    +// Because `.next()` returns a promise, you can use co
    +// to easily iterate through all documents without loading them
    +// all into memory.
    +co(function*() {
    +  const cursor = Thing.find({ name: /^hello/ }).cursor();
    +  for (let doc = yield cursor.next(); doc != null; doc = yield cursor.next()) {
    +    console.log(doc);
    +  }
    +});
    + +

    Valid options

    + +
      +
    • transform: optional function which accepts a mongoose document. The return value of the function will be emitted on data and returned by .next().
    • +
    show code
    Query.prototype.cursor = function cursor(opts) {
    +  this._applyPaths();
    +  this._fields = this._castFields(this._fields);
    +  this.setOptions({ fields: this._fieldsForExec() });
    +  if (opts) {
    +    this.setOptions(opts);
    +  }
    +
    +  try {
    +    this.cast(this.model);
    +  } catch (err) {
    +    return (new QueryCursor(this, this.options))._markError(err);
    +  }
    +
    +  return new QueryCursor(this, this.options);
    +};
    +
    +// the rest of these are basically to support older Mongoose syntax with mquery

    Query#deleteMany([filter], [callback])

    Declare and/or execute this query as a deleteMany() operation. Works like
    remove, except it deletes every document that matches criteria in the
    collection, regardless of the value of single.

    Parameters:

    • [filter] <Object, Query> mongodb selector
    • [callback] <Function> optional params are (error, writeOpResult)

    Returns:

    Example

    + +
    Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, callback)
    +Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }).then(next)
    show code
    Query.prototype.deleteMany = function(filter, callback) {
    +  if (typeof filter === 'function') {
    +    callback = filter;
    +    filter = null;
    +  }
    +
    +  filter = utils.toObject(filter, { retainKeyOrder: true });
    +
    +  try {
    +    this.cast(this.model, filter);
    +    this.merge(filter);
    +  } catch (err) {
    +    this._castError = err;
    +  }
    +
    +  prepareDiscriminatorCriteria(this);
    +
    +  if (!callback) {
    +    return Query.base.deleteMany.call(this);
    +  }
    +
    +  return this._deleteMany.call(this, callback);
    +};

    Query#deleteOne([filter], [callback])

    Declare and/or execute this query as a deleteOne() operation. Works like
    remove, except it deletes at most one document regardless of the single
    option.

    Parameters:

    • [filter] <Object, Query> mongodb selector
    • [callback] <Function> optional params are (error, writeOpResult)

    Returns:

    Example

    + +
    Character.deleteOne({ name: 'Eddard Stark' }, callback)
    +Character.deleteOne({ name: 'Eddard Stark' }).then(next)
    show code
    Query.prototype.deleteOne = function(filter, callback) {
    +  if (typeof filter === 'function') {
    +    callback = filter;
    +    filter = null;
    +  }
    +
    +  filter = utils.toObject(filter, { retainKeyOrder: true });
    +
    +  try {
    +    this.cast(this.model, filter);
    +    this.merge(filter);
    +  } catch (err) {
    +    this._castError = err;
    +  }
    +
    +  prepareDiscriminatorCriteria(this);
    +
    +  if (!callback) {
    +    return Query.base.deleteOne.call(this);
    +  }
    +
    +  return this._deleteOne.call(this, callback);
    +};

    Query#distinct([field], [criteria], [callback])

    Declares or executes a distict() operation.

    Parameters:

    Returns:

    Passing a callback executes the query.

    + +

    Example

    + +
    distinct(field, conditions, callback)
    +distinct(field, conditions)
    +distinct(field, callback)
    +distinct(field)
    +distinct(callback)
    +distinct()
    show code
    Query.prototype.distinct = function(field, conditions, callback) {
    +  if (!callback) {
    +    if (typeof conditions === 'function') {
    +      callback = conditions;
    +      conditions = undefined;
    +    } else if (typeof field === 'function') {
    +      callback = field;
    +      field = undefined;
    +      conditions = undefined;
    +    }
    +  }
    +
    +  conditions = utils.toObject(conditions);
    +
    +  if (mquery.canMerge(conditions)) {
    +    this.merge(conditions);
    +  }
    +
    +  try {
    +    this.cast(this.model);
    +  } catch (err) {
    +    if (!callback) {
    +      throw err;
    +    }
    +    callback(err);
    +    return this;
    +  }
    +
    +  return Query.base.distinct.call(this, {}, field, callback);
    +};

    Query#elemMatch(path, criteria)

    Specifies an $elemMatch condition

    Parameters:

    Returns:

    Example

    + +
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
    +
    +query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
    +
    +query.elemMatch('comment', function (elem) {
    +  elem.where('author').equals('autobot');
    +  elem.where('votes').gte(5);
    +})
    +
    +query.where('comment').elemMatch(function (elem) {
    +  elem.where({ author: 'autobot' });
    +  elem.where('votes').gte(5);
    +})

    Query#equals(val)

    Specifies the complementary comparison value for paths specified with where()

    Parameters:

    Returns:

    Example

    + +
    User.where('age').equals(49);
    +
    +// is the same as
    +
    +User.where('age', 49);

    Query#exec([operation], [callback])

    Executes the query

    Parameters:

    Returns:

    Examples:

    + +
    var promise = query.exec();
    +var promise = query.exec('update');
    +
    +query.exec(callback);
    +query.exec('find', callback);
    show code
    Query.prototype.exec = function exec(op, callback) {
    +  var Promise = PromiseProvider.get();
    +  var _this = this;
    +
    +  if (typeof op === 'function') {
    +    callback = op;
    +    op = null;
    +  } else if (typeof op === 'string') {
    +    this.op = op;
    +  }
    +
    +  var _results;
    +  var promise = new Promise.ES6(function(resolve, reject) {
    +    if (!_this.op) {
    +      resolve();
    +      return;
    +    }
    +
    +    _this[_this.op].call(_this, function(error, res) {
    +      if (error) {
    +        reject(error);
    +        return;
    +      }
    +      _results = arguments;
    +      resolve(res);
    +    });
    +  });
    +
    +  if (callback) {
    +    promise.then(
    +      function() {
    +        callback.apply(null, _results);
    +        return null;
    +      },
    +      function(error) {
    +        callback(error, null);
    +      }).
    +      catch(function(error) {
    +        // If we made it here, we must have an error in the callback re:
    +        // gh-4500, so we need to emit.
    +        setImmediate(function() {
    +          _this.model.emit('error', error);
    +        });
    +      });
    +  }
    +
    +  return promise;
    +};

    Query#exists([path], val)

    Specifies an $exists condition

    Parameters:

    Returns:

    Example

    + +
    // { name: { $exists: true }}
    +Thing.where('name').exists()
    +Thing.where('name').exists(true)
    +Thing.find().exists('name')
    +
    +// { name: { $exists: false }}
    +Thing.where('name').exists(false);
    +Thing.find().exists('name', false);

    Query#find([criteria], [callback])

    Finds documents.

    Parameters:

    Returns:

    When no callback is passed, the query is not executed. When the query is executed, the result will be an array of documents.

    + +

    Example

    + +
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)
    show code
    Query.prototype.find = function(conditions, callback) {
    +  if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = {};
    +  }
    +
    +  conditions = utils.toObject(conditions);
    +
    +  if (mquery.canMerge(conditions)) {
    +    this.merge(conditions);
    +  }
    +
    +  prepareDiscriminatorCriteria(this);
    +
    +  // if we don't have a callback, then just return the query object
    +  if (!callback) {
    +    return Query.base.find.call(this);
    +  }
    +
    +  this._find(callback);
    +
    +  return this;
    +};

    Query#findOne([criteria], [projection], [callback])

    Declares the query a findOne operation. When executed, the first found document is passed to the callback.

    Parameters:

    • [criteria] <Object, Query> mongodb selector
    • [projection] <Object> optional fields to return
    • [callback] <Function> optional params are (error, document)

    Returns:

    Passing a callback executes the query. The result of the query is a single document.

    + +
      +
    • Note: conditions is optional, and if conditions is null or undefined, +mongoose will send an empty findOne command to MongoDB, which will return +an arbitrary document. If you're querying by _id, use Model.findById() +instead.
    • +
    + +

    Example

    + +
    var query  = Kitten.where({ color: 'white' });
    +query.findOne(function (err, kitten) {
    +  if (err) return handleError(err);
    +  if (kitten) {
    +    // doc may be null if no document matched
    +  }
    +});
    show code
    Query.prototype.findOne = function(conditions, projection, options, callback) {
    +  if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = null;
    +    projection = null;
    +    options = null;
    +  } else if (typeof projection === 'function') {
    +    callback = projection;
    +    options = null;
    +    projection = null;
    +  } else if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
    +  }
    +
    +  // make sure we don't send in the whole Document to merge()
    +  conditions = utils.toObject(conditions);
    +
    +  this.op = 'findOne';
    +
    +  if (options) {
    +    this.setOptions(options);
    +  }
    +
    +  if (projection) {
    +    this.select(projection);
    +  }
    +
    +  if (mquery.canMerge(conditions)) {
    +    this.merge(conditions);
    +  } else if (conditions != null) {
    +    throw new Error('Invalid argument to findOne(): ' +
    +      util.inspect(conditions));
    +  }
    +
    +  prepareDiscriminatorCriteria(this);
    +
    +  try {
    +    this.cast(this.model);
    +    this._castError = null;
    +  } catch (err) {
    +    this._castError = err;
    +  }
    +
    +  if (!callback) {
    +    // already merged in the conditions, don't need to send them in.
    +    return Query.base.findOne.call(this);
    +  }
    +
    +  this._findOne(callback);
    +
    +  return this;
    +};

    Query#findOneAndRemove([conditions], [options], [options.passRawResult], [options.strict], [callback])

    Issues a mongodb findAndModify remove command.

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed.

    + +

    Available options

    + + + +

    Callback Signature

    + +
    function(error, doc, result) {
    +  // error: any errors that occurred
    +  // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
    +  // result: [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
    +}
    +
    + +

    Examples

    + +
    A.where().findOneAndRemove(conditions, options, callback) // executes
    +A.where().findOneAndRemove(conditions, options)  // return Query
    +A.where().findOneAndRemove(conditions, callback) // executes
    +A.where().findOneAndRemove(conditions) // returns Query
    +A.where().findOneAndRemove(callback)   // executes
    +A.where().findOneAndRemove()           // returns Query

    Query#findOneAndUpdate([query], [doc], [options], [options.passRawResult], [options.strict], [callback])

    Issues a mongodb findAndModify update command.

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed.

    + +

    Available options

    + +
      +
    • new: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0)
    • +
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • +
    • fields: {Object|String} - Field selection. Equivalent to .select(fields).findOneAndUpdate()
    • +
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • +
    • maxTimeMS: puts a time limit on the query - requires mongodb >= 2.6.0
    • +
    • runValidators: if true, runs update validators on this command. Update validators validate the update operation against the model's schema.
    • +
    • setDefaultsOnInsert: if this and upsert are true, mongoose will apply the defaults specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on MongoDB's $setOnInsert operator.
    • +
    • passRawResult: if true, passes the raw result from the MongoDB driver as the third callback parameter
    • +
    • context (string) if set to 'query' and runValidators is on, this will refer to the query in custom validator functions that update validation runs. Does nothing if runValidators is false.
    • +
    • runSettersOnQuery: bool - if true, run all setters defined on the associated model's schema for all fields defined in the query and the update.
    • +
    + +

    Callback Signature

    + +
    function(error, doc) {
    +  // error: any errors that occurred
    +  // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
    +}
    + +

    Examples

    + +
    query.findOneAndUpdate(conditions, update, options, callback) // executes
    +query.findOneAndUpdate(conditions, update, options)  // returns Query
    +query.findOneAndUpdate(conditions, update, callback) // executes
    +query.findOneAndUpdate(conditions, update)           // returns Query
    +query.findOneAndUpdate(update, callback)             // returns Query
    +query.findOneAndUpdate(update)                       // returns Query
    +query.findOneAndUpdate(callback)                     // executes
    +query.findOneAndUpdate()                             // returns Query

    Query#geometry(object)

    Specifies a $geometry condition

    Parameters:

    • object <Object> Must contain a type property which is a String and a coordinates property which is an Array. See the examples.

    Returns:

    Example

    + +
    var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]]
    +query.where('loc').within().geometry({ type: 'Polygon', coordinates: polyA })
    +
    +// or
    +var polyB = [[ 0, 0 ], [ 1, 1 ]]
    +query.where('loc').within().geometry({ type: 'LineString', coordinates: polyB })
    +
    +// or
    +var polyC = [ 0, 0 ]
    +query.where('loc').within().geometry({ type: 'Point', coordinates: polyC })
    +
    +// or
    +query.where('loc').intersects().geometry({ type: 'Point', coordinates: polyC })
    + +

    The argument is assigned to the most recent path passed to where().

    + +

    NOTE:

    + +

    geometry() must come after either intersects() or within().

    + +

    The object argument must contain type and coordinates properties.
    - type {String}
    - coordinates {Array}


    Query#getQuery()

    Returns the current query conditions as a JSON object.

    Returns:

    • <Object> current query conditions

    Example:

    + +
    var query = new Query();
    +query.find({ a: 1 }).where('b').gt(2);
    +query.getQuery(); // { a: 1, b: { $gt: 2 } }
    show code
    Query.prototype.getQuery = function() {
    +  return this._conditions;
    +};

    Query#getUpdate()

    Returns the current update operations as a JSON object.

    Returns:

    • <Object> current update operations

    Example:

    + +
    var query = new Query();
    +query.update({}, { $set: { a: 5 } });
    +query.getUpdate(); // { $set: { a: 5 } }
    show code
    Query.prototype.getUpdate = function() {
    +  return this._update;
    +};

    Query#gt([path], val)

    Specifies a $gt query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.

    + +

    Example

    + +
    Thing.find().where('age').gt(21)
    +
    +// or
    +Thing.find().gt('age', 21)

    Query#gte([path], val)

    Specifies a $gte query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.


    Query#hint(val)

    Sets query hints.

    Parameters:

    Returns:

    See:

    Example

    + +
    query.hint({ indexA: 1, indexB: -1})
    + +

    Note

    + +

    Cannot be used with distinct()


    Query#in([path], val)

    Specifies an $in query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.


    Query#intersects([arg])

    Declares an intersects query for geometry().

    Parameters:

    Returns:

    Example

    + +
    query.where('path').intersects().geometry({
    +    type: 'LineString'
    +  , coordinates: [[180.0, 11.0], [180, 9.0]]
    +})
    +
    +query.where('path').intersects({
    +    type: 'LineString'
    +  , coordinates: [[180.0, 11.0], [180, 9.0]]
    +})
    + +

    NOTE:

    + +

    MUST be used after where().

    + +

    NOTE:

    + +

    In Mongoose 3.7, intersects changed from a getter to a function. If you need the old syntax, use this.


    Query#lean(bool)

    Sets the lean option.

    Parameters:

    Returns:

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or other Mongoose magic applied.

    + +

    Example:

    + +
    new Query().lean() // true
    +new Query().lean(true)
    +new Query().lean(false)
    +
    +Model.find().lean().exec(function (err, docs) {
    +  docs[0] instanceof mongoose.Document // false
    +});
    + +

    This is a great option in high-performance read-only scenarios, especially when combined with stream.

    show code
    Query.prototype.lean = function(v) {
    +  this._mongooseOptions.lean = arguments.length ? v : true;
    +  return this;
    +};

    Query#limit(val)

    Specifies the maximum number of documents the query will return.

    Parameters:

    Example

    + +
    query.limit(20)
    + +

    Note

    + +

    Cannot be used with distinct()


    Query#lt([path], val)

    Specifies a $lt query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.


    Query#lte([path], val)

    Specifies a $lte query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.


    Query#maxDistance([path], val)

    Specifies a $maxDistance query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#maxscan()

    DEPRECATED Alias of maxScan


    Query#maxScan(val)

    Specifies the maxScan option.

    Parameters:

    Example

    + +
    query.maxScan(100)
    + +

    Note

    + +

    Cannot be used with distinct()


    Query#merge(source)

    Merges another Query or conditions object into this one.

    Parameters:

    Returns:

    When a Query is passed, conditions, field selection and options are merged.

    show code
    Query.prototype.merge = function(source) {
    +  if (!source) {
    +    return this;
    +  }
    +
    +  var opts = { retainKeyOrder: this.options.retainKeyOrder, overwrite: true };
    +
    +  if (source instanceof Query) {
    +    // if source has a feature, apply it to ourselves
    +
    +    if (source._conditions) {
    +      utils.merge(this._conditions, source._conditions, opts);
    +    }
    +
    +    if (source._fields) {
    +      this._fields || (this._fields = {});
    +      utils.merge(this._fields, source._fields, opts);
    +    }
    +
    +    if (source.options) {
    +      this.options || (this.options = {});
    +      utils.merge(this.options, source.options, opts);
    +    }
    +
    +    if (source._update) {
    +      this._update || (this._update = {});
    +      utils.mergeClone(this._update, source._update);
    +    }
    +
    +    if (source._distinct) {
    +      this._distinct = source._distinct;
    +    }
    +
    +    return this;
    +  }
    +
    +  // plain object
    +  utils.merge(this._conditions, source, opts);
    +
    +  return this;
    +};

    Query#merge(source)

    Merges another Query or conditions object into this one.

    Parameters:

    Returns:

    When a Query is passed, conditions, field selection and options are merged.

    + +

    New in 3.7.0


    Query#mod([path], val)

    Specifies a $mod condition

    Parameters:

    Returns:

    See:


    Query#mongooseOptions(options)

    Getter/setter around the current mongoose-specific options for this query
    (populate, lean, etc.)

    Parameters:

    • options <Object> if specified, overwrites the current options
    show code
    Query.prototype.mongooseOptions = function(v) {
    +  if (arguments.length > 0) {
    +    this._mongooseOptions = v;
    +  }
    +  return this._mongooseOptions;
    +};

    Query#ne([path], val)

    Specifies a $ne query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.


    Query#near([path], val)

    Specifies a $near or $nearSphere condition

    Parameters:

    Returns:

    These operators return documents sorted by distance.

    + +

    Example

    + +
    query.where('loc').near({ center: [10, 10] });
    +query.where('loc').near({ center: [10, 10], maxDistance: 5 });
    +query.where('loc').near({ center: [10, 10], maxDistance: 5, spherical: true });
    +query.near('loc', { center: [10, 10], maxDistance: 5 });

    Query#nearSphere()

    DEPRECATED Specifies a $nearSphere condition

    Example

    + +
    query.where('loc').nearSphere({ center: [10, 10], maxDistance: 5 });
    + +

    Deprecated. Use query.near() instead with the spherical option set to true.

    + +

    Example

    + +
    query.where('loc').near({ center: [10, 10], spherical: true });
    show code
    Query.prototype.nearSphere = function() {
    +  this._mongooseOptions.nearSphere = true;
    +  this.near.apply(this, arguments);
    +  return this;
    +};

    Query#nin([path], val)

    Specifies an $nin query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.


    Query#nor(array)

    Specifies arguments for a $nor condition.

    Parameters:

    • array <Array> array of conditions

    Returns:

    See:

    Example

    + +
    query.nor([{ color: 'green' }, { status: 'ok' }])

    Query#or(array)

    Specifies arguments for an $or condition.

    Parameters:

    • array <Array> array of conditions

    Returns:

    See:

    Example

    + +
    query.or([{ color: 'red' }, { status: 'emergency' }])

    Query#polygon([path], [coordinatePairs...])

    Specifies a $polygon condition

    Parameters:

    Returns:

    Example

    + +
    query.where('loc').within().polygon([10,20], [13, 25], [7,15])
    +query.polygon('loc', [10,20], [13, 25], [7,15])

    Query#populate(path, [select], [model], [match], [options])

    Specifies paths which should be populated with other documents.

    Parameters:

    • path <Object, String> either the path to populate or an object specifying all parameters
    • [select] <Object, String> Field selection for the population query
    • [model] <Model> The model you wish to use for population. If not specified, populate will look up the model by the name in the Schema's ref field.
    • [match] <Object> Conditions for the population query
    • [options] <Object> Options for the population query (sort, etc)

    Returns:

    Example:

    + +
    Kitten.findOne().populate('owner').exec(function (err, kitten) {
    +  console.log(kitten.owner.name) // Max
    +})
    +
    +Kitten.find().populate({
    +    path: 'owner'
    +  , select: 'name'
    +  , match: { color: 'black' }
    +  , options: { sort: { name: -1 }}
    +}).exec(function (err, kittens) {
    +  console.log(kittens[0].owner.name) // Zoopa
    +})
    +
    +// alternatively
    +Kitten.find().populate('owner', 'name', null, {sort: { name: -1 }}).exec(function (err, kittens) {
    +  console.log(kittens[0].owner.name) // Zoopa
    +})
    + +

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    show code
    Query.prototype.populate = function() {
    +  if (arguments.length === 0) {
    +    return this;
    +  }
    +
    +  var i;
    +
    +  var res = utils.populate.apply(null, arguments);
    +
    +  // Propagate readPreference from parent query, unless one already specified
    +  if (this.options && this.options.readPreference != null) {
    +    for (i = 0; i < res.length; ++i) {
    +      if (!res[i].options || res[i].options.readPreference == null) {
    +        res[i].options = res[i].options || {};
    +        res[i].options.readPreference = this.options.readPreference;
    +      }
    +    }
    +  }
    +
    +  var opts = this._mongooseOptions;
    +
    +  if (!utils.isObject(opts.populate)) {
    +    opts.populate = {};
    +  }
    +
    +  var pop = opts.populate;
    +
    +  for (i = 0; i < res.length; ++i) {
    +    var path = res[i].path;
    +    if (pop[path] && pop[path].populate && res[i].populate) {
    +      res[i].populate = pop[path].populate.concat(res[i].populate);
    +    }
    +    pop[res[i].path] = res[i];
    +  }
    +
    +  return this;
    +};

    Query([options], [model], [conditions], [collection])

    Query constructor used for building queries.

    Parameters:

    Example:

    + +
    var query = new Query();
    +query.setOptions({ lean : true });
    +query.collection(model.collection);
    +query.where('age').gte(21).exec(callback);
    show code
    function Query(conditions, options, model, collection) {
    +  // this stuff is for dealing with custom queries created by #toConstructor
    +  if (!this._mongooseOptions) {
    +    this._mongooseOptions = {};
    +  }
    +
    +  // this is the case where we have a CustomQuery, we need to check if we got
    +  // options passed in, and if we did, merge them in
    +  if (options) {
    +    var keys = Object.keys(options);
    +    for (var i = 0; i < keys.length; ++i) {
    +      var k = keys[i];
    +      this._mongooseOptions[k] = options[k];
    +    }
    +  }
    +
    +  if (collection) {
    +    this.mongooseCollection = collection;
    +  }
    +
    +  if (model) {
    +    this.model = model;
    +    this.schema = model.schema;
    +  }
    +
    +  // this is needed because map reduce returns a model that can be queried, but
    +  // all of the queries on said model should be lean
    +  if (this.model && this.model._mapreduce) {
    +    this.lean();
    +  }
    +
    +  // inherit mquery
    +  mquery.call(this, this.mongooseCollection, options);
    +
    +  if (conditions) {
    +    this.find(conditions);
    +  }
    +
    +  if (this.schema) {
    +    var kareemOptions = {
    +      useErrorHandlers: true,
    +      numCallbackParams: 1,
    +      nullResultByDefault: true
    +    };
    +    this._count = this.model.hooks.createWrapper('count',
    +        Query.prototype._count, this, kareemOptions);
    +    this._execUpdate = this.model.hooks.createWrapper('update',
    +        Query.prototype._execUpdate, this, kareemOptions);
    +    this._find = this.model.hooks.createWrapper('find',
    +        Query.prototype._find, this, kareemOptions);
    +    this._findOne = this.model.hooks.createWrapper('findOne',
    +        Query.prototype._findOne, this, kareemOptions);
    +    this._findOneAndRemove = this.model.hooks.createWrapper('findOneAndRemove',
    +        Query.prototype._findOneAndRemove, this, kareemOptions);
    +    this._findOneAndUpdate = this.model.hooks.createWrapper('findOneAndUpdate',
    +        Query.prototype._findOneAndUpdate, this, kareemOptions);
    +    this._replaceOne = this.model.hooks.createWrapper('replaceOne',
    +        Query.prototype._replaceOne, this, kareemOptions);
    +    this._updateMany = this.model.hooks.createWrapper('updateMany',
    +        Query.prototype._updateMany, this, kareemOptions);
    +    this._updateOne = this.model.hooks.createWrapper('updateOne',
    +        Query.prototype._updateOne, this, kareemOptions);
    +  }
    +}

    Query#read(pref, [tags])

    Determines the MongoDB nodes from which to read.

    Parameters:

    • pref <String> one of the listed preference options or aliases
    • [tags] <Array> optional tags for this query

    Returns:

    Preferences:

    + +
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
    +secondary            Read from secondary if available, otherwise error.
    +primaryPreferred     Read from primary if available, otherwise a secondary.
    +secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
    +nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
    + +

    Aliases

    + +
    p   primary
    +pp  primaryPreferred
    +s   secondary
    +sp  secondaryPreferred
    +n   nearest
    + +

    Example:

    + +
    new Query().read('primary')
    +new Query().read('p')  // same as primary
    +
    +new Query().read('primaryPreferred')
    +new Query().read('pp') // same as primaryPreferred
    +
    +new Query().read('secondary')
    +new Query().read('s')  // same as secondary
    +
    +new Query().read('secondaryPreferred')
    +new Query().read('sp') // same as secondaryPreferred
    +
    +new Query().read('nearest')
    +new Query().read('n')  // same as nearest
    +
    +// read from secondaries with matching tags
    +new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
    + +

    Read more about how to use read preferrences here and here.


    Query#regex([path], val)

    Specifies a $regex query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.


    Query#remove([filter], [callback])

    Declare and/or execute this query as a remove() operation.

    Parameters:

    • [filter] <Object, Query> mongodb selector
    • [callback] <Function> optional params are (error, writeOpResult)

    Returns:

    Example

    + +
    Model.remove({ artist: 'Anne Murray' }, callback)
    + +

    Note

    + +

    The operation is only executed when a callback is passed. To force execution without a callback, you must first call remove() and then execute it by using the exec() method.

    + +
    // not executed
    +var query = Model.find().remove({ name: 'Anne Murray' })
    +
    +// executed
    +query.remove({ name: 'Anne Murray' }, callback)
    +query.remove({ name: 'Anne Murray' }).remove(callback)
    +
    +// executed without a callback
    +query.exec()
    +
    +// summary
    +query.remove(conds, fn); // executes
    +query.remove(conds)
    +query.remove(fn) // executes
    +query.remove()
    show code
    Query.prototype.remove = function(filter, callback) {
    +  if (typeof filter === 'function') {
    +    callback = filter;
    +    filter = null;
    +  }
    +
    +  filter = utils.toObject(filter, { retainKeyOrder: true });
    +
    +  try {
    +    this.cast(this.model, filter);
    +    this.merge(filter);
    +  } catch (err) {
    +    this._castError = err;
    +  }
    +
    +  prepareDiscriminatorCriteria(this);
    +
    +  if (!callback) {
    +    return Query.base.remove.call(this);
    +  }
    +
    +  return this._remove(callback);
    +};

    Query#replaceOne([criteria], [doc], [options], [callback])

    Declare and/or execute this query as a replaceOne() operation. Same as
    update(), except MongoDB will replace the existing document and will
    not accept any atomic operators ($set, etc.)

    Parameters:

    • [criteria] <Object>
    • [doc] <Object> the update command
    • [options] <Object>
    • [callback] <Function> optional params are (error, writeOpResult)

    Returns:

    Note replaceOne will not fire update middleware. Use pre('replaceOne')
    and post('replaceOne') instead.

    show code
    Query.prototype.replaceOne = function(conditions, doc, options, callback) {
    +  if (typeof options === 'function') {
    +    // .update(conditions, doc, callback)
    +    callback = options;
    +    options = null;
    +  } else if (typeof doc === 'function') {
    +    // .update(doc, callback);
    +    callback = doc;
    +    doc = conditions;
    +    conditions = {};
    +    options = null;
    +  } else if (typeof conditions === 'function') {
    +    // .update(callback)
    +    callback = conditions;
    +    conditions = undefined;
    +    doc = undefined;
    +    options = undefined;
    +  } else if (typeof conditions === 'object' && !doc && !options && !callback) {
    +    // .update(doc)
    +    doc = conditions;
    +    conditions = undefined;
    +    options = undefined;
    +    callback = undefined;
    +  }
    +
    +  this.setOptions({ overwrite: true });
    +  return _update(this, 'replaceOne', conditions, doc, options, callback);
    +};

    Query#select(arg)

    Specifies which document fields to include or exclude (also known as the query "projection")

    Parameters:

    Returns:

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    + +

    A projection must be either inclusive or exclusive. In other words, you must
    either list the fields to include (which excludes all others), or list the fields
    to exclude (which implies all other fields are included). The _id field is the only exception because MongoDB includes it by default.

    + +

    Example

    + +
    // include a and b, exclude other fields
    +query.select('a b');
    +
    +// exclude c and d, include other fields
    +query.select('-c -d');
    +
    +// or you may use object notation, useful when
    +// you have keys already prefixed with a "-"
    +query.select({ a: 1, b: 1 });
    +query.select({ c: 0, d: 0 });
    +
    +// force inclusion of field excluded at schema level
    +query.select('+path')

    Query#selected()

    Determines if field selection has been made.

    Returns:


    Query#selectedExclusively()

    Determines if exclusive field selection has been made.

    Returns:

    query.selectedExclusively() // false
    +query.select('-name')
    +query.selectedExclusively() // true
    +query.selectedInclusively() // false

    Query#selectedInclusively()

    Determines if inclusive field selection has been made.

    Returns:

    query.selectedInclusively() // false
    +query.select('name')
    +query.selectedInclusively() // true

    Query#setOptions(options)

    Sets query options.

    Parameters:

    Options:

      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • +
    • tailable *
    • +
    • sort *
    • +
    • limit *
    • +
    • skip *
    • +
    • maxscan *
    • +
    • batchSize *
    • +
    • comment *
    • +
    • snapshot *
    • +
    • hint *
    • +
    • readPreference **
    • +
    • lean *
    • +
    • safe
    -

    Examples:

    +

    * denotes a query helper method is also available
    ** query helper method to set readPreference is read()

    show code
    Query.prototype.setOptions = function(options, overwrite) {
    +  // overwrite is only for internal use
    +  if (overwrite) {
    +    // ensure that _mongooseOptions & options are two different objects
    +    this._mongooseOptions = (options && utils.clone(options)) || {};
    +    this.options = options || {};
     
    -
    A.findOneAndUpdate(conditions, update, options, callback) // executes
    -A.findOneAndUpdate(conditions, update, options)  // returns Query
    -A.findOneAndUpdate(conditions, update, callback) // executes
    -A.findOneAndUpdate(conditions, update)           // returns Query
    -A.findOneAndUpdate()                             // returns Query
    + if ('populate' in options) { + this.populate(this._mongooseOptions); + } + return this; + } -

    Note:

    + if (!(options && options.constructor.name === 'Object')) { + return this; + } -

    All top level update keys which are not atomic operation names are treated as set operations:

    + if (options && Array.isArray(options.populate)) { + var populate = options.populate; + delete options.populate; + var _numPopulate = populate.length; + for (var i = 0; i < _numPopulate; ++i) { + this.populate(populate[i]); + } + } + + return Query.base.setOptions.call(this, options); +};

    Query#size([path], val)

    Specifies a $size query condition.

    Parameters:

    See:

    When called with one argument, the most recent path passed to where() is used.

    + +

    Example

    + +
    MyModel.where('tags').size(0).exec(function (err, docs) {
    +  if (err) return handleError(err);
    +
    +  assert(Array.isArray(docs));
    +  console.log('documents with 0 tags', docs);
    +})

    Query#skip(val)

    Specifies the number of documents to skip.

    Parameters:

    Example

    + +
    query.skip(100).limit(20)
    + +

    Note

    + +

    Cannot be used with distinct()


    Query#slaveOk(v)

    DEPRECATED Sets the slaveOk option.

    Parameters:

    Returns:

    Deprecated in MongoDB 2.2 in favor of read preferences.

    Example:

    -
    var query = { name: 'borne' };
    -Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
    +
    query.slaveOk() // true
    +query.slaveOk(true)
    +query.slaveOk(false)

    Query#slice([path], val)

    Specifies a $slice projection for an array.

    Parameters:

    • [path] <String>
    • val <Number> number/range of elements to slice

    Returns:

    Example

    -// is sent as -Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback) +
    query.slice('comments', 5)
    +query.slice('comments', -5)
    +query.slice('comments', [10, 5])
    +query.where('comments').slice(5)
    +query.where('comments').slice([-10, 5])

    Query#snapshot()

    Specifies this query as a snapshot query.

    Returns:

    Example

    -

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    +
    query.snapshot() // true
    +query.snapshot(true)
    +query.snapshot(false)
    -

    Note:

    +

    Note

    + +

    Cannot be used with distinct()


    Query#sort(arg)

    Sets the sort order

    Parameters:

    Returns:

    If an object is passed, values allowed are asc, desc, ascending, descending, 1, and -1.

    + +

    If a string is passed, it must be a space delimited list of path names. The
    sort order of each path is ascending unless the path name is prefixed with -
    which will be treated as descending.

    + +

    Example

    -

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    +
    // sort by "field" ascending and "test" descending
    +query.sort({ field: 'asc', test: -1 });
    +
    +// equivalent
    +query.sort('field -test');
    + +

    Note

    + +

    Cannot be used with distinct()

    show code
    Query.prototype.sort = function(arg) {
    +  if (arguments.length > 1) {
    +    throw new Error('sort() only takes 1 Argument');
    +  }
    +
    +  return Query.base.sort.call(this, arg);
    +};

    Query#stream([options])

    Returns a Node.js 0.8 style read stream interface.

    Parameters:

    Returns:

    Example

    + +
    // follows the nodejs 0.8 stream api
    +Thing.find({ name: /^hello/ }).stream().pipe(res)
    +
    +// manual streaming
    +var stream = Thing.find({ name: /^hello/ }).stream();
    +
    +stream.on('data', function (doc) {
    +  // do something with the mongoose document
    +}).on('error', function (err) {
    +  // handle the error
    +}).on('close', function () {
    +  // the stream is closed
    +});
    + +

    Valid options

      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • +
    • transform: optional function which accepts a mongoose document. The return value of the function will be emitted on data.
    -

    If you need those features, use the traditional approach of first retrieving the document.

    +

    Example

    -
    Model.findOne({ name: 'borne' }, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.findByIdAndUpdate(id, [update], [options], [callback])

    Issues a mongodb findAndModify update command by a documents id.

    show code
    Model.findByIdAndUpdate = function (id, update, options, callback) {
    -  var args;
    +
    // JSON.stringify all documents before emitting
    +var stream = Thing.find().stream({ transform: JSON.stringify });
    +stream.pipe(writeStream);
    show code
    Query.prototype.stream = function stream(opts) {
    +  this._applyPaths();
    +  this._fields = this._castFields(this._fields);
    +  this._castConditions();
    +  return new QueryStream(this, opts);
    +};
    +Query.prototype.stream = util.deprecate(Query.prototype.stream, 'Mongoose: ' +
    +  'Query.prototype.stream() is deprecated in mongoose >= 4.5.0, ' +
    +  'use Query.prototype.cursor() instead');

    Query#tailable(bool, [opts], [opts.numberOfRetries], [opts.tailableRetryInterval])

    Sets the tailable option (for use with capped collections).

    Parameters:

    • bool <Boolean> defaults to true
    • [opts] <Object> options to set
    • [opts.numberOfRetries] <Number> if cursor is exhausted, retry this many times before giving up
    • [opts.tailableRetryInterval] <Number> if cursor is exhausted, wait this many milliseconds before retrying

    Example

    - if (1 === arguments.length) { - if ('function' == typeof id) { - var msg = 'Model.findByIdAndUpdate(): First argument must not be a function. +
    query.tailable() // true
    +query.tailable(true)
    +query.tailable(false)
    -' - + ' ' + this.modelName + '.findByIdAndUpdate(id, callback) -' - + ' ' + this.modelName + '.findByIdAndUpdate(id) -' - + ' ' + this.modelName + '.findByIdAndUpdate() -'; - throw new TypeError(msg) +

    Note

    + +

    Cannot be used with distinct()

    show code
    Query.prototype.tailable = function(val, opts) {
    +  // we need to support the tailable({ awaitdata : true }) as well as the
    +  // tailable(true, {awaitdata :true}) syntax that mquery does not support
    +  if (val && val.constructor.name === 'Object') {
    +    opts = val;
    +    val = true;
    +  }
    +
    +  if (val === undefined) {
    +    val = true;
    +  }
    +
    +  if (opts && typeof opts === 'object') {
    +    for (var key in opts) {
    +      if (key === 'awaitdata') {
    +        // For backwards compatibility
    +        this.options[key] = !!opts[key];
    +      } else {
    +        this.options[key] = opts[key];
    +      }
         }
    -    return this.findOneAndUpdate({_id: id }, undefined);
       }
     
    -  args = utils.args(arguments, 1);
    -  args.unshift({ _id: id });
    -  return this.findOneAndUpdate.apply(this, args);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    + return Query.base.tailable.call(this, val); +};

    Query#then([resolve], [reject])

    Executes the query returning a Promise which will be
    resolved with either the doc(s) or rejected with the error.

    Parameters:

    Returns:

    show code
    Query.prototype.then = function(resolve, reject) {
    +  return this.exec().then(resolve, reject);
    +};

    Query#toConstructor()

    Converts this query to a customized, reusable query constructor with all arguments and options retained.

    Returns:

    • <Query> subclass-of-Query

    Example

    -

    Options:

    +
    // Create a query for adventure movies and read from the primary
    +// node in the replica-set unless it is down, in which case we'll
    +// read from a secondary node.
    +var query = Movie.find({ tags: 'adventure' }).read('primaryPreferred');
     
    -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    +// create a custom Query constructor based off these settings +var Adventure = query.toConstructor(); -

    Examples:

    +// Adventure is now a subclass of mongoose.Query and works the same way but with the +// default query parameters and options set. +Adventure().exec(callback) -
    A.findByIdAndUpdate(id, update, options, callback) // executes
    -A.findByIdAndUpdate(id, update, options)  // returns Query
    -A.findByIdAndUpdate(id, update, callback) // executes
    -A.findByIdAndUpdate(id, update)           // returns Query
    -A.findByIdAndUpdate()                     // returns Query
    +// further narrow down our query results while still using the previous settings +Adventure().where({ name: /^Life/ }).exec(callback); + +// since Adventure is a stand-alone constructor we can also add our own +// helper methods and getters without impacting global queries +Adventure.prototype.startsWith = function (prefix) { + this.where({ name: new RegExp('^' + prefix) }) + return this; +} +Object.defineProperty(Adventure.prototype, 'highlyRated', { + get: function () { + this.where({ rating: { $gt: 4.5 }}); + return this; + } +}) +Adventure().highlyRated.startsWith('Life').exec(callback)
    -

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    +

    New in 3.7.3

    show code
    Query.prototype.toConstructor = function toConstructor() {
    +  var model = this.model;
    +  var coll = this.mongooseCollection;
     
    -

    Options:

    + var CustomQuery = function(criteria, options) { + if (!(this instanceof CustomQuery)) { + return new CustomQuery(criteria, options); + } + this._mongooseOptions = utils.clone(p._mongooseOptions); + Query.call(this, criteria, options || null, model, coll); + }; -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    + util.inherits(CustomQuery, Query); -

    Note:

    + // set inherited defaults + var p = CustomQuery.prototype; -

    All top level update keys which are not atomic operation names are treated as set operations:

    + p.options = {}; -

    Example:

    + p.setOptions(this.options); -
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
    +  p.op = this.op;
    +  p._conditions = utils.clone(this._conditions, { retainKeyOrder: true });
    +  p._fields = utils.clone(this._fields);
    +  p._update = utils.clone(this._update, {
    +    flattenDecimals: false,
    +    retainKeyOrder: true
    +  });
    +  p._path = this._path;
    +  p._distinct = this._distinct;
    +  p._collection = this._collection;
    +  p._mongooseOptions = this._mongooseOptions;
     
    -// is sent as
    -Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
    + return CustomQuery; +};

    Query#update([criteria], [doc], [options], [callback])

    Declare and/or execute this query as an update() operation.

    Parameters:

    • [criteria] <Object>
    • [doc] <Object> the update command
    • [options] <Object>
    • [callback] <Function> optional, params are (error, writeOpResult)

    Returns:

    All paths passed that are not $atomic operations will become $set ops.

    -

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    +

    Example

    -

    Note:

    +
    Model.where({ _id: id }).update({ title: 'words' })
     
    -

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    +// becomes + +Model.where({ _id: id }).update({ $set: { title: 'words' }})
    + +

    Valid options:

      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • +
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • +
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • +
    • multi (boolean) whether multiple documents should be updated (false)
    • +
    • runValidators: if true, runs update validators on this command. Update validators validate the update operation against the model's schema.
    • +
    • setDefaultsOnInsert: if this and upsert are true, mongoose will apply the defaults specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on MongoDB's $setOnInsert operator.
    • +
    • strict (boolean) overrides the strict option for this update
    • +
    • overwrite (boolean) disables update-only mode, allowing you to overwrite the doc (false)
    • +
    • context (string) if set to 'query' and runValidators is on, this will refer to the query in custom validator functions that update validation runs. Does nothing if runValidators is false.
    -

    If you need those features, use the traditional approach of first retrieving the document.

    +

    Note

    -
    Model.findById(id, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.findOneAndRemove(conditions, [options], [callback])

    Issue a mongodb findAndModify remove command.

    show code
    Model.findOneAndRemove = function (conditions, options, callback) {
    -  if (1 === arguments.length && 'function' == typeof conditions) {
    -    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
    +

    Passing an empty object {} as the doc will result in a no-op unless the overwrite option is passed. Without the overwrite option set, the update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting documents in the collection.

    -' - + ' ' + this.modelName + '.findOneAndRemove(conditions, callback) -' - + ' ' + this.modelName + '.findOneAndRemove(conditions) -' - + ' ' + this.modelName + '.findOneAndRemove() -'; - throw new TypeError(msg) +

    Note

    + +

    The operation is only executed when a callback is passed. To force execution without a callback, we must first call update() and then execute it by using the exec() method.

    + +
    var q = Model.where({ _id: id });
    +q.update({ $set: { name: 'bob' }}).update(); // not executed
    +
    +q.update({ $set: { name: 'bob' }}).exec(); // executed
    +
    +// keys that are not $atomic ops become $set.
    +// this executes the same command as the previous example.
    +q.update({ name: 'bob' }).exec();
    +
    +// overwriting with empty docs
    +var q = Model.where({ _id: id }).setOptions({ overwrite: true })
    +q.update({ }, callback); // executes
    +
    +// multi update with overwrite to empty doc
    +var q = Model.where({ _id: id });
    +q.setOptions({ multi: true, overwrite: true })
    +q.update({ });
    +q.update(callback); // executed
    +
    +// multi updates
    +Model.where()
    +     .update({ name: /^match/ }, { $set: { arr: [] }}, { multi: true }, callback)
    +
    +// more multi updates
    +Model.where()
    +     .setOptions({ multi: true })
    +     .update({ $set: { arr: [] }}, callback)
    +
    +// single update by default
    +Model.where({ email: 'address@example.com' })
    +     .update({ $inc: { counter: 1 }}, callback)
    +
    + +

    API summary

    + +
    update(criteria, doc, options, cb) // executes
    +update(criteria, doc, options)
    +update(criteria, doc, cb) // executes
    +update(criteria, doc)
    +update(doc, cb) // executes
    +update(doc)
    +update(cb) // executes
    +update(true) // executes
    +update()
    show code
    Query.prototype.update = function(conditions, doc, options, callback) {
    +  if (typeof options === 'function') {
    +    // .update(conditions, doc, callback)
    +    callback = options;
    +    options = null;
    +  } else if (typeof doc === 'function') {
    +    // .update(doc, callback);
    +    callback = doc;
    +    doc = conditions;
    +    conditions = {};
    +    options = null;
    +  } else if (typeof conditions === 'function') {
    +    // .update(callback)
    +    callback = conditions;
    +    conditions = undefined;
    +    doc = undefined;
    +    options = undefined;
    +  } else if (typeof conditions === 'object' && !doc && !options && !callback) {
    +    // .update(doc)
    +    doc = conditions;
    +    conditions = undefined;
    +    options = undefined;
    +    callback = undefined;
    +  }
    +
    +  return _update(this, 'update', conditions, doc, options, callback);
    +};

    Query#updateMany([criteria], [doc], [options], [callback])

    Declare and/or execute this query as an updateMany() operation. Same as
    update(), except MongoDB will update all documents that match
    criteria (as opposed to just the first one) regardless of the value of
    the multi option.

    Parameters:

    • [criteria] <Object>
    • [doc] <Object> the update command
    • [options] <Object>
    • [callback] <Function> optional params are (error, writeOpResult)

    Returns:

    Note updateMany will not fire update middleware. Use pre('updateMany')
    and post('updateMany') instead.

    show code
    Query.prototype.updateMany = function(conditions, doc, options, callback) {
    +  if (typeof options === 'function') {
    +    // .update(conditions, doc, callback)
    +    callback = options;
    +    options = null;
    +  } else if (typeof doc === 'function') {
    +    // .update(doc, callback);
    +    callback = doc;
    +    doc = conditions;
    +    conditions = {};
    +    options = null;
    +  } else if (typeof conditions === 'function') {
    +    // .update(callback)
    +    callback = conditions;
    +    conditions = undefined;
    +    doc = undefined;
    +    options = undefined;
    +  } else if (typeof conditions === 'object' && !doc && !options && !callback) {
    +    // .update(doc)
    +    doc = conditions;
    +    conditions = undefined;
    +    options = undefined;
    +    callback = undefined;
    +  }
    +
    +  return _update(this, 'updateMany', conditions, doc, options, callback);
    +};

    Query#updateOne([criteria], [doc], [options], [callback])

    Declare and/or execute this query as an updateOne() operation. Same as
    update(), except MongoDB will update only the first document that
    matches criteria regardless of the value of the multi option.

    Parameters:

    Returns:

    Note updateOne will not fire update middleware. Use pre('updateOne')
    and post('updateOne') instead.

    show code
    Query.prototype.updateOne = function(conditions, doc, options, callback) {
    +  if (typeof options === 'function') {
    +    // .update(conditions, doc, callback)
    +    callback = options;
    +    options = null;
    +  } else if (typeof doc === 'function') {
    +    // .update(doc, callback);
    +    callback = doc;
    +    doc = conditions;
    +    conditions = {};
    +    options = null;
    +  } else if (typeof conditions === 'function') {
    +    // .update(callback)
    +    callback = conditions;
    +    conditions = undefined;
    +    doc = undefined;
    +    options = undefined;
    +  } else if (typeof conditions === 'object' && !doc && !options && !callback) {
    +    // .update(doc)
    +    doc = conditions;
    +    conditions = undefined;
    +    options = undefined;
    +    callback = undefined;
       }
     
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = undefined;
    -  }
    +  return _update(this, 'updateOne', conditions, doc, options, callback);
    +};

    Query#where([path], [val])

    Specifies a path for use with chaining.

    Parameters:

    Returns:

    Example

    + +
    // instead of writing:
    +User.find({age: {$gte: 21, $lte: 65}}, callback);
    +
    +// we can instead write:
    +User.where('age').gte(21).lte(65);
    +
    +// passing query conditions is permitted
    +User.find().where({ name: 'vonderful' })
    +
    +// chaining
    +User
    +.where('age').gte(21).lte(65)
    +.where('name', /^vonderful/i)
    +.where('friends').slice(10)
    +.exec(callback)

    Query#within()

    Defines a $within or $geoWithin argument for geo-spatial queries.

    Returns:

    Example

    + +
    query.where(path).within().box()
    +query.where(path).within().circle()
    +query.where(path).within().geometry()
     
    -  var fields;
    -  if (options) {
    -    fields = options.select;
    -    options.select = undefined;
    -  }
    +query.where('loc').within({ center: [50,50], radius: 10, unique: true, spherical: true });
    +query.where('loc').within({ box: [[40.73, -73.9], [40.7, -73.988]] });
    +query.where('loc').within({ polygon: [[],[],[],[]] });
     
    -  var query = new Query(conditions);
    -  query.setOptions(options);
    -  query.select(fields);
    -  query.bind(this, 'findOneAndRemove');
    +query.where('loc').within([], [], []) // polygon
    +query.where('loc').within([], []) // box
    +query.where('loc').within({ type: 'LineString', coordinates: [...] }); // geometry
    - if ('undefined' == typeof callback) - return query; +

    MUST be used after where().

    - this._applyNamedScope(query); - return query.findOneAndRemove(callback); -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    +

    NOTE:

    -

    Executes immediately if callback is passed else a Query object is returned.

    +

    As of Mongoose 3.7, $geoWithin is always used for queries. To change this behavior, see Query.use$geoWithin.

    -

    Options:

    +

    NOTE:

    -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    +

    In Mongoose 3.7, within changed from a getter to a function. If you need the old syntax, use this.


    Query._ensurePath(method)

    Makes sure _path is set.

    Parameters:


    Query._fieldsForExec()

    Returns fields selection for this query.

    Returns:


    Query._updateForExec()

    Return an update document with corrected $set operations.


    Query#use$geoWithin

    Flag to opt out of using $geoWithin.

    -

    Examples:

    +
    mongoose.Query.use$geoWithin = false;
    -
    A.findOneAndRemove(conditions, options, callback) // executes
    -A.findOneAndRemove(conditions, options)  // return Query
    -A.findOneAndRemove(conditions, callback) // executes
    -A.findOneAndRemove(conditions) // returns Query
    -A.findOneAndRemove()           // returns Query

    Model.findByIdAndRemove(id, [options], [callback])

    Issue a mongodb findAndModify remove command by a documents id.

    show code
    Model.findByIdAndRemove = function (id, options, callback) {
    -  if (1 === arguments.length && 'function' == typeof id) {
    -    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
    +

    MongoDB 2.4 deprecated the use of $within, replacing it with $geoWithin. Mongoose uses $geoWithin by default (which is 100% backward compatible with $within). If you are running an older version of MongoDB, set this flag to false so your within() queries continue to work.

    show code
    Query.use$geoWithin = mquery.use$geoWithin;

  • schema/decimal128.js

    Decimal128#cast(value, doc, init)

    Casts to Decimal128

    Parameters:

    show code
    Decimal128.prototype.cast = function(value, doc, init) {
    +  if (SchemaType._isRef(this, value, doc, init)) {
    +    // wait! we may need to cast this to a document
     
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove(id)
    -'
    -              + '  ' + this.modelName + '.findByIdAndRemove()
    -';
    -    throw new TypeError(msg)
    -  }
    +    if (value === null || value === undefined) {
    +      return value;
    +    }
     
    -  return this.findOneAndRemove({ _id: id }, options, callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    + // lazy load + Document || (Document = require('./../document')); -

    Executes immediately if callback is passed, else a Query object is returned.

    + if (value instanceof Document) { + value.$__.wasPopulated = true; + return value; + } -

    Options:

    + // setting a populated path + if (value instanceof Decimal128Type) { + return value; + } else if (Buffer.isBuffer(value) || !utils.isObject(value)) { + throw new CastError('Decimal128', value, this.path); + } -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    • select: sets the document fields to return
    • -
    + // Handle the case where user directly sets a populated + // path to a plain object; cast to the Model used in + // the population query. + var path = doc.$__fullPath(this.path); + var owner = doc.ownerDocument ? doc.ownerDocument() : doc; + var pop = owner.populated(path, true); + var ret = value; + if (!doc.$__.populated || + !doc.$__.populated[path] || + !doc.$__.populated[path].options || + !doc.$__.populated[path].options.options || + !doc.$__.populated[path].options.options.lean) { + ret = new pop.options.model(value); + ret.$__.wasPopulated = true; + } -

    Examples:

    + return ret; + } -
    A.findByIdAndRemove(id, options, callback) // executes
    -A.findByIdAndRemove(id, options)  // return Query
    -A.findByIdAndRemove(id, callback) // executes
    -A.findByIdAndRemove(id) // returns Query
    -A.findByIdAndRemove()           // returns Query

    Model.create(doc, fn)

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    show code
    Model.create = function create (doc, fn) {
    -  if (1 === arguments.length) {
    -    return 'function' === typeof doc && doc(null);
    +  if (value == null) {
    +    return value;
       }
     
    -  var self = this
    -    , docs = [null]
    -    , promise
    -    , count
    -    , args
    +  if (typeof value === 'object' && typeof value.$numberDecimal === 'string') {
    +    return Decimal128Type.fromString(value.$numberDecimal);
    +  }
     
    -  if (Array.isArray(doc)) {
    -    args = doc;
    -  } else {
    -    args = utils.args(arguments, 0, arguments.length - 1);
    -    fn = arguments[arguments.length - 1];
    +  if (value instanceof Decimal128Type) {
    +    return value;
       }
     
    -  if (0 === args.length) return fn(null);
    +  if (typeof value === 'string') {
    +    return Decimal128Type.fromString(value);
    +  }
     
    -  promise = new Promise(fn);
    -  count = args.length;
    +  if (Buffer.isBuffer(value)) {
    +    return new Decimal128Type(value);
    +  }
     
    -  args.forEach(function (arg, i) {
    -    var doc = new self(arg);
    -    docs[i+1] = doc;
    -    doc.save(function (err) {
    -      if (err) return promise.error(err);
    -      --count || fn.apply(null, docs);
    -    });
    -  });
    +  throw new CastError('Decimal128', value, this.path);
    +};

    Decimal128#checkRequired(value, doc)

    Check if the given value satisfies a required validator.

    Parameters:

    Returns:

    show code
    Decimal128.prototype.checkRequired = function checkRequired(value, doc) {
    +  if (SchemaType._isRef(this, value, doc, true)) {
    +    return !!value;
    +  }
    +  return value instanceof Decimal128Type;
    +};

    Decimal128(key, options)

    Decimal128 SchemaType constructor.

    Parameters:

    Inherits:

    show code
    function Decimal128(key, options) {
    +  SchemaType.call(this, key, options, 'Decimal128');
    +}

    Decimal128.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    Decimal128.schemaName = 'Decimal128';

  • schema/array.js

    SchemaArray#applyGetters(value, scope)

    Overrides the getters application for the population special-case

    Parameters:

    show code
    SchemaArray.prototype.applyGetters = function(value, scope) {
    +  if (this.caster.options && this.caster.options.ref) {
    +    // means the object id was populated
    +    return value;
    +  }
     
    -  // TODO
    -  // utilize collection.insertAll for batch processing?
    -};

    Parameters:

    Example:

    + return SchemaType.prototype.applyGetters.call(this, value, scope); +};

    SchemaArray#cast(value, doc, init)

    Casts values for set().

    Parameters:

    • value <Object>
    • doc <Document> document that triggers the casting
    • init <Boolean> whether this is an initialization cast
    show code
    SchemaArray.prototype.cast = function(value, doc, init) {
    +  if (Array.isArray(value)) {
    +    if (!value.length && doc) {
    +      var indexes = doc.schema.indexedPaths();
     
    -
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
    -  if (err) // ...
    -});
    +      for (var i = 0, l = indexes.length; i < l; ++i) {
    +        var pathIndex = indexes[i][0][this.path];
    +        if (pathIndex === '2dsphere' || pathIndex === '2d') {
    +          return;
    +        }
    +      }
    +    }
     
    -var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
    -Candy.create(array, function (err, jellybean, snickers) {
    -  if (err) // ...
    -});

    Model.update(conditions, update, [options], [callback])

    Updates documents in the database without returning them.

    show code
    Model.update = function update (conditions, doc, options, callback) {
    -  if (arguments.length < 4) {
    -    if ('function' === typeof options) {
    -      // Scenario: update(conditions, doc, callback)
    -      callback = options;
    -      options = null;
    -    } else if ('function' === typeof doc) {
    -      // Scenario: update(doc, callback);
    -      callback = doc;
    -      doc = conditions;
    -      conditions = {};
    -      options = null;
    +    if (!(value && value.isMongooseArray)) {
    +      value = new MongooseArray(value, this.path, doc);
    +    } else if (value && value.isMongooseArray) {
    +      // We need to create a new array, otherwise change tracking will
    +      // update the old doc (gh-4449)
    +      value = new MongooseArray(value, this.path, doc);
         }
    -  }
     
    -  var query = new Query(conditions, options).bind(this, 'update', doc);
    +    if (this.caster) {
    +      try {
    +        for (i = 0, l = value.length; i < l; i++) {
    +          value[i] = this.caster.cast(value[i], doc, init);
    +        }
    +      } catch (e) {
    +        // rethrow
    +        throw new CastError('[' + e.kind + ']', util.inspect(value), this.path, e);
    +      }
    +    }
     
    -  if ('undefined' == typeof callback)
    -    return query;
    +    return value;
    +  }
    +  // gh-2442: if we're loading this from the db and its not an array, mark
    +  // the whole array as modified.
    +  if (!!doc && !!init) {
    +    doc.markModified(this.path);
    +  }
    +  return this.cast([value], doc, init);
    +};

    SchemaArray#castForQuery($conditional, [value])

    Casts values for queries.

    Parameters:

    • $conditional <String>
    • [value] <T>
    show code
    SchemaArray.prototype.castForQuery = function($conditional, value) {
    +  var handler,
    +      val;
     
    -  this._applyNamedScope(query);
    -  return query.update(doc, callback);
    -};

    Parameters:

    Returns:

    Examples:

    + if (arguments.length === 2) { + handler = this.$conditionalHandlers[$conditional]; -
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
    -MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
    -  if (err) return handleError(err);
    -  console.log('The number of updated documents was %d', numberAffected);
    -  console.log('The raw response from Mongo was ', raw);
    -});
    + if (!handler) { + throw new Error('Can\'t use ' + $conditional + ' with Array.'); + } -

    Valid options:

    + val = handler.call(this, value); + } else { + val = $conditional; + var Constructor = this.casterConstructor; + + if (val && + Constructor.discriminators && + Constructor.schema.options.discriminatorKey && + typeof val[Constructor.schema.options.discriminatorKey] === 'string' && + Constructor.discriminators[val[Constructor.schema.options.discriminatorKey]]) { + Constructor = Constructor.discriminators[val[Constructor.schema.options.discriminatorKey]]; + } -
      -
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • -
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • -
    • multi (boolean) whether multiple documents should be updated (false)
    • -
    + var proto = this.casterConstructor.prototype; + var method = proto && (proto.castForQuery || proto.cast); + if (!method && Constructor.castForQuery) { + method = Constructor.castForQuery; + } + var caster = this.caster; -

    All update values are cast to their appropriate SchemaTypes before being sent.

    + if (Array.isArray(val)) { + val = val.map(function(v) { + if (utils.isObject(v) && v.$elemMatch) { + return v; + } + if (method) { + v = method.call(caster, v); + return v; + } + if (v != null) { + v = new Constructor(v); + return v; + } + return v; + }); + } else if (method) { + val = method.call(caster, val); + } else if (val != null) { + val = new Constructor(val); + } + } -

    The callback function receives (err, numberAffected, rawResponse).

    + return val; +}; -
      -
    • err is the error if any occurred
    • -
    • numberAffected is the count of updated documents Mongo reported
    • -
    • rawResponse is the full response from Mongo
    • -
    +function cast$all(val) { + if (!Array.isArray(val)) { + val = [val]; + } -

    Note:

    + val = val.map(function(v) { + if (utils.isObject(v)) { + var o = {}; + o[this.path] = v; + return cast(this.casterConstructor.schema, o)[this.path]; + } + return v; + }, this); -

    All top level keys which are not atomic operation names are treated as set operations:

    + return this.castForQuery(val); +} -

    Example:

    +function cast$elemMatch(val) { + var keys = Object.keys(val); + var numKeys = keys.length; + var key; + var value; + for (var i = 0; i < numKeys; ++i) { + key = keys[i]; + value = val[key]; + if (key.indexOf('$') === 0 && value) { + val[key] = this.castForQuery(key, value); + } + } -
    var query = { name: 'borne' };
    -Model.update(query, { name: 'jason borne' }, options, callback)
    +  return cast(this.casterConstructor.schema, val);
    +}
     
    -// is sent as
    -Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
    +var handle = SchemaArray.prototype.$conditionalHandlers = {}; -

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    +handle.$all = cast$all; +handle.$options = String; +handle.$elemMatch = cast$elemMatch; +handle.$geoIntersects = geospatial.cast$geoIntersects; +handle.$or = handle.$and = function(val) { + if (!Array.isArray(val)) { + throw new TypeError('conditional $or/$and require array'); + } -

    Note:

    + var ret = []; + for (var i = 0; i < val.length; ++i) { + ret.push(cast(this.casterConstructor.schema, val[i])); + } -

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    + return ret; +}; -
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
    +handle.$near = +handle.$nearSphere = geospatial.cast$near; -

    Note:

    +handle.$within = +handle.$geoWithin = geospatial.cast$within; -

    Although values are casted to their appropriate types when using update, the following are not applied:

    +handle.$size = +handle.$minDistance = +handle.$maxDistance = castToNumber; -
      -
    • defaults
    • -
    • setters
    • -
    • validators
    • -
    • middleware
    • -
    +handle.$exists = $exists; +handle.$type = $type; -

    If you need those features, use the traditional approach of first retrieving the document.

    +handle.$eq = +handle.$gt = +handle.$gte = +handle.$in = +handle.$lt = +handle.$lte = +handle.$ne = +handle.$nin = +handle.$regex = SchemaArray.prototype.castForQuery;

    SchemaArray#checkRequired(value)

    Check if the given value satisfies a required validator. The given value
    must be not null nor undefined, and have a positive length.

    Parameters:

    Returns:

    show code
    SchemaArray.prototype.checkRequired = function(value) {
    +  return !!(value && value.length);
    +};

    SchemaArray(key, cast, options)

    Array SchemaType constructor

    Parameters:

    Inherits:

    show code
    function SchemaArray(key, cast, options, schemaOptions) {
    +  var typeKey = 'type';
    +  if (schemaOptions && schemaOptions.typeKey) {
    +    typeKey = schemaOptions.typeKey;
    +  }
     
    -
    Model.findOne({ name: 'borne' }, function (err, doc) {
    -  if (err) ..
    -  doc.name = 'jason borne';
    -  doc.save(callback);
    -})

    Model.mapReduce(o, callback)

    Executes a mapReduce command.

    show code
    Model.mapReduce = function mapReduce (o, callback) {
    -  if ('function' != typeof callback) throw new Error('missing callback');
    +  if (cast) {
    +    var castOptions = {};
     
    -  var self = this;
    +    if (utils.getFunctionName(cast.constructor) === 'Object') {
    +      if (cast[typeKey]) {
    +        // support { type: Woot }
    +        castOptions = utils.clone(cast); // do not alter user arguments
    +        delete castOptions[typeKey];
    +        cast = cast[typeKey];
    +      } else {
    +        cast = Mixed;
    +      }
    +    }
     
    -  if (!Model.mapReduce.schema) {
    -    var opts = { noId: true, noVirtualId: true, strict: false }
    -    Model.mapReduce.schema = new Schema({}, opts);
    -  }
    +    // support { type: 'String' }
    +    var name = typeof cast === 'string'
    +        ? cast
    +        : utils.getFunctionName(cast);
     
    -  if (!o.out) o.out = { inline: 1 };
    +    var caster = name in Types
    +        ? Types[name]
    +        : cast;
     
    -  o.map = String(o.map);
    -  o.reduce = String(o.reduce);
    +    this.casterConstructor = caster;
    +    if (typeof caster === 'function' && !caster.$isArraySubdocument) {
    +      this.caster = new caster(null, castOptions);
    +    } else {
    +      this.caster = caster;
    +    }
     
    -  if (o.query) {
    -    var q = new Query(o.query);
    -    q.cast(this);
    -    o.query = q._conditions;
    -    q = undefined;
    +    if (!(this.caster instanceof EmbeddedDoc)) {
    +      this.caster.path = key;
    +    }
       }
     
    -  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
    -    if (err) return callback(err);
    +  this.$isMongooseArray = true;
     
    -    if (ret.findOne && ret.mapReduce) {
    -      // returned a collection, convert to Model
    -      var model = Model.compile(
    -          '_mapreduce_' + ret.collectionName
    -        , Model.mapReduce.schema
    -        , ret.collectionName
    -        , self.db
    -        , self.base);
    +  SchemaType.call(this, key, options, 'Array');
     
    -      model._mapreduce = true;
    +  var defaultArr;
    +  var fn;
     
    -      return callback(err, model, stats);
    -    }
    +  if (this.defaultValue != null) {
    +    defaultArr = this.defaultValue;
    +    fn = typeof defaultArr === 'function';
    +  }
     
    -    callback(err, ret, stats);
    -  });
    -}

    Parameters:

    • o <Object> an object specifying map-reduce options
    • callback <Function>

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    + if (!('defaultValue' in this) || this.defaultValue !== void 0) { + this.default(function() { + var arr = []; + if (fn) { + arr = defaultArr(); + } else if (defaultArr != null) { + arr = defaultArr; + } + // Leave it up to `cast()` to convert the array + return arr; + }); + } +}

    SchemaArray.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    SchemaArray.schemaName = 'Array';

  • schema/string.js

    SchemaString#cast()

    Casts to String

    show code
    SchemaString.prototype.cast = function(value, doc, init) {
    +  if (SchemaType._isRef(this, value, doc, init)) {
    +    // wait! we may need to cast this to a document
     
    -

    Example:

    + if (value === null || value === undefined) { + return value; + } -
    var o = {};
    -o.map = function () { emit(this.name, 1) }
    -o.reduce = function (k, vals) { return vals.length }
    -User.mapReduce(o, function (err, results) {
    -  console.log(results)
    -})
    + // lazy load + Document || (Document = require('./../document')); -

    Other options:

    + if (value instanceof Document) { + value.$__.wasPopulated = true; + return value; + } -
      -
    • query {Object} query filter object.
    • -
    • limit {Number} max number of documents
    • -
    • keeptemp {Boolean, default:false} keep temporary data
    • -
    • finalize {Function} finalize function
    • -
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • -
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • -
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • -
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • -
    + // setting a populated path + if (typeof value === 'string') { + return value; + } else if (Buffer.isBuffer(value) || !utils.isObject(value)) { + throw new CastError('string', value, this.path); + } -

    * out options:

    + // Handle the case where user directly sets a populated + // path to a plain object; cast to the Model used in + // the population query. + var path = doc.$__fullPath(this.path); + var owner = doc.ownerDocument ? doc.ownerDocument() : doc; + var pop = owner.populated(path, true); + var ret = new pop.options.model(value); + ret.$__.wasPopulated = true; + return ret; + } -
      -
    • {inline:1} the results are returned in an array
    • -
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • -
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • -
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • -
    + // If null or undefined + if (value === null || value === undefined) { + return value; + } -

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    + if (typeof value !== 'undefined') { + // handle documents being passed + if (value._id && typeof value._id === 'string') { + return value._id; + } -

    Example:

    + // Re: gh-647 and gh-3030, we're ok with casting using `toString()` + // **unless** its the default Object.toString, because "[object Object]" + // doesn't really qualify as useful data + if (value.toString && value.toString !== Object.prototype.toString) { + return value.toString(); + } + } -
    var o = {};
    -o.map = function () { emit(this.name, 1) }
    -o.reduce = function (k, vals) { return vals.length }
    -o.out = { replace: 'createdCollectionNameForResults' }
    -o.verbose = true;
    -User.mapReduce(o, function (err, model, stats) {
    -  console.log('map reduce took %d ms', stats.processtime)
    -  model.find().where('value').gt(10).exec(function (err, docs) {
    -    console.log(docs);
    -  });
    -})

    Model.aggregate(array, [options], callback)

    Executes an aggregate command on this models collection.

    show code
    Model.aggregate = function aggregate () {
    -  return this.collection.aggregate.apply(this.collection, arguments);
    -}

    Parameters:

    Example:

    + throw new CastError('string', value, this.path); +};

    SchemaString#castForQuery($conditional, [val])

    Casts contents for queries.

    Parameters:

    • $conditional <String>
    • [val] <T>
    show code
    SchemaString.prototype.castForQuery = function($conditional, val) {
    +  var handler;
    +  if (arguments.length === 2) {
    +    handler = this.$conditionalHandlers[$conditional];
    +    if (!handler) {
    +      throw new Error('Can\'t use ' + $conditional + ' with String.');
    +    }
    +    return handler.call(this, val);
    +  }
    +  val = $conditional;
    +  if (Object.prototype.toString.call(val) === '[object RegExp]') {
    +    return val;
    +  }
     
    -
    // find the max age of all users
    -Users.aggregate(
    -    { $group: { _id: null, maxAge: { $max: '$age' }}}
    -  , { $project: { _id: 0, maxAge: 1 }}
    -  , function (err, res) {
    -  if (err) return handleError(err);
    -  console.log(res); // [ { maxAge: 98 } ]
    -});
    + return this._castForQuery(val); +};

    SchemaString#checkRequired(value, doc)

    Check if the given value satisfies the required validator. The value is
    considered valid if it is a string (that is, not null or undefined) and
    has positive length. The required validator will fail for empty
    strings.

    Parameters:

    Returns:

    show code
    SchemaString.prototype.checkRequired = function checkRequired(value, doc) {
    +  if (SchemaType._isRef(this, value, doc, true)) {
    +    return !!value;
    +  }
    +  return (value instanceof String || typeof value === 'string') && value.length;
    +};

    SchemaString#enum([args...])

    Adds an enum validator

    Parameters:

    Returns:

    Example:

    -

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    +
    var states = ['opening', 'open', 'closing', 'closed']
    +var s = new Schema({ state: { type: String, enum: states }})
    +var M = db.model('M', s)
    +var m = new M({ state: 'invalid' })
    +m.save(function (err) {
    +  console.error(String(err)) // ValidationError: `invalid` is not a valid enum value for path `state`.
    +  m.state = 'open'
    +  m.save(callback) // success
    +})
     
    -

    NOTE: this requires running MongoDB >= 2.1


    Model#base

    Base Mongoose instance the model uses.


    Model#collection

    Collection the model uses.


    Model#db

    Database instance the model uses.


    Model#schema

    Schema the model uses.


    Model#modelName

    The name of the model


    Model#collection

    Collection the model uses.


    Model#db

    Connection the model uses.


  • namedscope.js

    NamedScope#decorate(target, getters)

    Decorate

    show code
    NamedScope.prototype.decorate = function (target, getters) {
    -  var name = this.name
    -    , block = this.block
    -    , query = this.query;
    -  if (block) {
    -    if (block.length === 0) {
    -      Object.defineProperty(target, name, {
    -        get: getters.block0(block)
    -      });
    -    } else {
    -      target[name] = getters.blockN(block);
    -    }
    -  } else {
    -    Object.defineProperty(target, name, {
    -      get: getters.basic(query)
    -    });
    +// or with custom error messages
    +var enum = {
    +  values: ['opening', 'open', 'closing', 'closed'],
    +  message: 'enum validator failed for path `{PATH}` with value `{VALUE}`'
    +}
    +var s = new Schema({ state: { type: String, enum: enum })
    +var M = db.model('M', s)
    +var m = new M({ state: 'invalid' })
    +m.save(function (err) {
    +  console.error(String(err)) // ValidationError: enum validator failed for path `state` with value `invalid`
    +  m.state = 'open'
    +  m.save(callback) // success
    +})
    show code
    SchemaString.prototype.enum = function() {
    +  if (this.enumValidator) {
    +    this.validators = this.validators.filter(function(v) {
    +      return v.validator !== this.enumValidator;
    +    }, this);
    +    this.enumValidator = false;
       }
    -};
     
    -NamedScope.prototype.compile = function (model) {
    -  var allScopes = this.scopesByName
    -    , scope;
    -  for (var k in allScopes) {
    -    scope = allScopes[k];
    -    scope.decorate(model, {
    -      block0: function (block) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          block.call(cquery);
    -          return this;
    -        };
    -      },
    -      blockN: function (block) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          block.apply(cquery, arguments);
    -          return this;
    -        };
    -      },
    -      basic: function (query) {
    -        return function () {
    -          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
    -          cquery.find(query);
    -          return this;
    -        };
    -      }
    -    });
    +  if (arguments[0] === void 0 || arguments[0] === false) {
    +    return this;
       }
    -};
     
    -module.exports = NamedScope;

    Parameters:


  • promise.js

    Promise(back)

    Promise constructor.

    show code
    function Promise (back) {
    -  this.emitted = {};
    -  if ('function' == typeof back)
    -    this.addBack(back);
    -};

    Parameters:

    • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

    Events:

    • err: Emits when the promise resolves to an error.

    • complete: Emits when the promise resolves sucessfully.


    Promise#on(event, callback)

    Adds listener to the event.

    show code
    Promise.prototype.on = function (event, callback) {
    -  if (this.emitted[event])
    -    callback.apply(this, this.emitted[event]);
    -  else
    -    EventEmitter.prototype.on.call(this, event, callback);
    +  var values;
    +  var errorMessage;
     
    -  return this;
    -};

    Parameters:

    Returns:

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


    Promise#emit()

    Keeps track of emitted events to run them on on.

    show code
    Promise.prototype.emit = function (event) {
    -  // ensures a promise can't be complete() or error() twice
    -  if (event == 'err' || event == 'complete'){
    -    if (this.emitted.err || this.emitted.complete) {
    -      return this;
    +  if (utils.isObject(arguments[0])) {
    +    values = arguments[0].values;
    +    errorMessage = arguments[0].message;
    +  } else {
    +    values = arguments;
    +    errorMessage = MongooseError.messages.String.enum;
    +  }
    +
    +  for (var i = 0; i < values.length; i++) {
    +    if (undefined !== values[i]) {
    +      this.enumValues.push(this.cast(values[i]));
         }
    -    this.emitted[event] = util.args(arguments, 1);
    -  }
    -
    -  return EventEmitter.prototype.emit.apply(this, arguments);
    -};

    Promise#complete()

    Shortcut for emitting the complete event.

    show code
    Promise.prototype.complete = function () {
    -  var args = util.args(arguments);
    -  return this.emit.apply(this, ['complete'].concat(args));
    -};

    Promise#error()

    Shortcut for emitting the err event.

    show code
    Promise.prototype.error = function (err) {
    -  if (!(err instanceof Error)) err = new Error(err);
    -  return this.emit('err', err);
    -};

    Returns:


    Promise#addCallback()

    Shortcut for .on('complete', fn).

    show code
    Promise.prototype.addCallback = function (fn) {
    -  return this.on('complete', fn);
    -};

    Returns:


    Promise#addErrback()

    Shortcut for .on('err', fn).

    show code
    Promise.prototype.addErrback = function (fn) {
    -  return this.on('err', fn);
    -};

    Returns:


    Promise#addBack(fn)

    Adds a single function that's both a callback and errback.

    show code
    Promise.prototype.addBack = function (fn) {
    -  this.on('err', function(err){
    -    fn.call(this, err);
    -  });
    +  }
     
    -  this.on('complete', function(){
    -    var args = util.args(arguments);
    -    fn.apply(this, [null].concat(args));
    +  var vals = this.enumValues;
    +  this.enumValidator = function(v) {
    +    return undefined === v || ~vals.indexOf(v);
    +  };
    +  this.validators.push({
    +    validator: this.enumValidator,
    +    message: errorMessage,
    +    type: 'enum',
    +    enumValues: vals
       });
     
       return this;
    -};

    Parameters:

    Returns:


    Promise#resolve(err, val)

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    show code
    Promise.prototype.resolve = function (err, val) {
    -  if (err) return this.error(err);
    -  return this.complete(val);
    -};

    Parameters:

    • err <Error> optional error or null
    • val <Object> value to complete the promise with

  • query.js

    Query(criteria, options)

    Query constructor used for building queries.

    show code
    function Query (criteria, options) {
    -  this.setOptions(options, true);
    -  this._conditions = {};
    -  this._updateArg = {};
    -  this._fields = undefined;
    -  if (criteria) this.find(criteria);
    -}

    Parameters:

    Example:

    - -
    var query = Model.find();
    -query.where('age').gte(21).exec(callback);

    Query#setOptions(options)

    Sets query options.

    show code
    Query.prototype.setOptions = function (options, overwrite) {
    -  // overwrite is internal use only
    -  if (overwrite) {
    -    options = this.options = options || {};
    -    this.safe = options.safe
    -
    -    // normalize population options
    -    var pop = this.options.populate;
    -    this.options.populate = {};
    -
    -    if (pop && Array.isArray(pop)) {
    -      for (var i = 0, l = pop.length; i < l; i++) {
    -        this.options.populate[pop[i]] = {};
    -      }
    -    }
    +};

    SchemaString#lowercase()

    Adds a lowercase setter.

    Returns:

    Example:

    +
    var s = new Schema({ email: { type: String, lowercase: true }})
    +var M = db.model('M', s);
    +var m = new M({ email: 'SomeEmail@example.COM' });
    +console.log(m.email) // someemail@example.com
    +
    show code
    SchemaString.prototype.lowercase = function(shouldApply) {
    +  if (arguments.length > 0 && !shouldApply) {
         return this;
       }
    +  return this.set(function(v, self) {
    +    if (typeof v !== 'string') {
    +      v = self.cast(v);
    +    }
    +    if (v) {
    +      return v.toLowerCase();
    +    }
    +    return v;
    +  });
    +};

    SchemaString#match(regExp, [message])

    Sets a regexp validator.

    Parameters:

    • regExp <RegExp> regular expression to test against
    • [message] <String> optional custom error message

    Returns:

    Any value that does not pass regExp.test(val) will fail validation.

    - if (!(options && 'Object' == options.constructor.name)) - return this; +

    Example:

    + +
    var s = new Schema({ name: { type: String, match: /^a/ }})
    +var M = db.model('M', s)
    +var m = new M({ name: 'I am invalid' })
    +m.validate(function (err) {
    +  console.error(String(err)) // "ValidationError: Path `name` is invalid (I am invalid)."
    +  m.name = 'apples'
    +  m.validate(function (err) {
    +    assert.ok(err) // success
    +  })
    +})
    +
    +// using a custom error message
    +var match = [ /\.html$/, "That file doesn't end in .html ({VALUE})" ];
    +var s = new Schema({ file: { type: String, match: match }})
    +var M = db.model('M', s);
    +var m = new M({ file: 'invalid' });
    +m.validate(function (err) {
    +  console.log(String(err)) // "ValidationError: That file doesn't end in .html (invalid)"
    +})
    - if ('safe' in options) - this.safe = options.safe; +

    Empty strings, undefined, and null values always pass the match validator. If you require these values, enable the required validator also.

    - // set arbitrary options - var methods = Object.keys(options) - , i = methods.length - , method +
    var s = new Schema({ name: { type: String, match: /^a/, required: true }})
    show code
    SchemaString.prototype.match = function match(regExp, message) {
    +  // yes, we allow multiple match validators
     
    -  while (i--) {
    -    method = methods[i];
    -
    -    // use methods if exist (safer option manipulation)
    -    if ('function' == typeof this[method]) {
    -      var args = Array.isArray(options[method])
    -        ? options[method]
    -        : [options[method]];
    -      this[method].apply(this, args)
    -    } else {
    -      this.options[method] = options[method];
    +  var msg = message || MongooseError.messages.String.match;
    +
    +  var matchValidator = function(v) {
    +    if (!regExp) {
    +      return false;
         }
    -  }
    -  return this;
    -}

    Parameters:

    Options:

    - + var ret = ((v != null && v !== '') + ? regExp.test(v) + : true); + return ret; + }; -

    * denotes a query helper method is also available


    Query#bind(model, op, updateArg)

    Binds this query to a model.

    show code
    Query.prototype.bind = function bind (model, op, updateArg) {
    -  this.model = model;
    -  this.op = op;
    +  this.validators.push({
    +    validator: matchValidator,
    +    message: msg,
    +    type: 'regexp',
    +    regexp: regExp
    +  });
    +  return this;
    +};

    SchemaString#maxlength(value, [message])

    Sets a maximum length validator.

    Parameters:

    • value <Number> maximum string length
    • [message] <String> optional custom error message

    Returns:

    Example:

    - if (model._mapreduce) this.options.lean = true; +
    var schema = new Schema({ postalCode: { type: String, maxlength: 9 })
    +var Address = db.model('Address', schema)
    +var address = new Address({ postalCode: '9512512345' })
    +address.save(function (err) {
    +  console.error(err) // validator error
    +  address.postalCode = '95125';
    +  address.save() // success
    +})
     
    -  if (op == 'update' || op == 'findOneAndUpdate') {
    -    merge(this._updateArg, updateArg || {});
    +// custom error messages
    +// We can also use the special {MAXLENGTH} token which will be replaced with the maximum allowed length
    +var maxlength = [9, 'The value of path `{PATH}` (`{VALUE}`) exceeds the maximum allowed length ({MAXLENGTH}).'];
    +var schema = new Schema({ postalCode: { type: String, maxlength: maxlength })
    +var Address = mongoose.model('Address', schema);
    +var address = new Address({ postalCode: '9512512345' });
    +address.validate(function (err) {
    +  console.log(String(err)) // ValidationError: The value of path `postalCode` (`9512512345`) exceeds the maximum allowed length (9).
    +})
    show code
    SchemaString.prototype.maxlength = function(value, message) {
    +  if (this.maxlengthValidator) {
    +    this.validators = this.validators.filter(function(v) {
    +      return v.validator !== this.maxlengthValidator;
    +    }, this);
    +  }
    +
    +  if (value !== null && value !== undefined) {
    +    var msg = message || MongooseError.messages.String.maxlength;
    +    msg = msg.replace(/{MAXLENGTH}/, value);
    +    this.validators.push({
    +      validator: this.maxlengthValidator = function(v) {
    +        return v === null || v.length <= value;
    +      },
    +      message: msg,
    +      type: 'maxlength',
    +      maxlength: value
    +    });
       }
     
       return this;
    -};

    Parameters:

    • model <Model> the model to which the query is bound
    • op <String> the operation to execute
    • updateArg <Object> used in update methods

    Returns:


    Query#exec([operation], [callback])

    Executes the query

    show code
    Query.prototype.exec = function exec (op, callback) {
    -  var promise = new Promise();
    +};

    SchemaString#minlength(value, [message])

    Sets a minimum length validator.

    Parameters:

    • value <Number> minimum string length
    • [message] <String> optional custom error message

    Returns:

    Example:

    - switch (typeof op) { - case 'function': - callback = op; - op = null; - break; - case 'string': - this.op = op; - break; +
    var schema = new Schema({ postalCode: { type: String, minlength: 5 })
    +var Address = db.model('Address', schema)
    +var address = new Address({ postalCode: '9512' })
    +address.save(function (err) {
    +  console.error(err) // validator error
    +  address.postalCode = '95125';
    +  address.save() // success
    +})
    +
    +// custom error messages
    +// We can also use the special {MINLENGTH} token which will be replaced with the minimum allowed length
    +var minlength = [5, 'The value of path `{PATH}` (`{VALUE}`) is shorter than the minimum allowed length ({MINLENGTH}).'];
    +var schema = new Schema({ postalCode: { type: String, minlength: minlength })
    +var Address = mongoose.model('Address', schema);
    +var address = new Address({ postalCode: '9512' });
    +address.validate(function (err) {
    +  console.log(String(err)) // ValidationError: The value of path `postalCode` (`9512`) is shorter than the minimum length (5).
    +})
    show code
    SchemaString.prototype.minlength = function(value, message) {
    +  if (this.minlengthValidator) {
    +    this.validators = this.validators.filter(function(v) {
    +      return v.validator !== this.minlengthValidator;
    +    }, this);
    +  }
    +
    +  if (value !== null && value !== undefined) {
    +    var msg = message || MongooseError.messages.String.minlength;
    +    msg = msg.replace(/{MINLENGTH}/, value);
    +    this.validators.push({
    +      validator: this.minlengthValidator = function(v) {
    +        return v === null || v.length >= value;
    +      },
    +      message: msg,
    +      type: 'minlength',
    +      minlength: value
    +    });
       }
     
    -  if (callback) promise.addBack(callback);
    +  return this;
    +};

    SchemaString(key, options)

    String SchemaType constructor.

    Parameters:

    Inherits:

    show code
    function SchemaString(key, options) {
    +  this.enumValues = [];
    +  this.regExp = null;
    +  SchemaType.call(this, key, options, 'String');
    +}

    SchemaString#trim()

    Adds a trim setter.

    Returns:

    The string value will be trimmed when set.

    - if (!this.op) { - promise.complete(); - return promise; - } +

    Example:

    - if ('update' == this.op) { - this[this.op](this._updateArg, promise.resolve.bind(promise)); - return promise; +
    var s = new Schema({ name: { type: String, trim: true }})
    +var M = db.model('M', s)
    +var string = ' some name '
    +console.log(string.length) // 11
    +var m = new M({ name: string })
    +console.log(m.name.length) // 9
    show code
    SchemaString.prototype.trim = function(shouldTrim) {
    +  if (arguments.length > 0 && !shouldTrim) {
    +    return this;
       }
    +  return this.set(function(v, self) {
    +    if (typeof v !== 'string') {
    +      v = self.cast(v);
    +    }
    +    if (v) {
    +      return v.trim();
    +    }
    +    return v;
    +  });
    +};

    SchemaString#uppercase()

    Adds an uppercase setter.

    Returns:

    Example:

    - if ('distinct' == this.op) { - this.distinct(this._distinctArg, promise.resolve.bind(promise)); - return promise; +
    var s = new Schema({ caps: { type: String, uppercase: true }})
    +var M = db.model('M', s);
    +var m = new M({ caps: 'an example' });
    +console.log(m.caps) // AN EXAMPLE
    show code
    SchemaString.prototype.uppercase = function(shouldApply) {
    +  if (arguments.length > 0 && !shouldApply) {
    +    return this;
       }
    +  return this.set(function(v, self) {
    +    if (typeof v !== 'string') {
    +      v = self.cast(v);
    +    }
    +    if (v) {
    +      return v.toUpperCase();
    +    }
    +    return v;
    +  });
    +};

    SchemaString.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    SchemaString.schemaName = 'String';

  • schema/documentarray.js

    DocumentArray#cast(value, document)

    Casts contents

    Parameters:

    show code
    DocumentArray.prototype.cast = function(value, doc, init, prev, options) {
    +  var selected;
    +  var subdoc;
    +  var i;
    +  var _opts = { transform: false, virtuals: false };
     
    -  this[this.op](promise.resolve.bind(promise));
    -  return promise;
    -};

    Parameters:

    Returns:

    Examples

    - -
    query.exec();
    -query.exec(callback);
    -query.exec('update');
    -query.exec('find', callback);

    Query#find([criteria], [callback])

    Finds documents.

    show code
    Query.prototype.find = function (criteria, callback) {
    -  this.op = 'find';
    -  if ('function' === typeof criteria) {
    -    callback = criteria;
    -    criteria = {};
    -  } else if (criteria instanceof Query) {
    -    // TODO Merge options, too
    -    merge(this._conditions, criteria._conditions);
    -  } else if (criteria instanceof Document) {
    -    merge(this._conditions, criteria.toObject());
    -  } else if (criteria && 'Object' === criteria.constructor.name) {
    -    merge(this._conditions, criteria);
    -  }
    -  if (!callback) return this;
    -  return this.execFind(callback);
    -};

    Parameters:

    Returns:

    When no callback is passed, the query is not executed.

    - -

    Example

    + if (!Array.isArray(value)) { + // gh-2442 mark whole array as modified if we're initializing a doc from + // the db and the path isn't an array in the document + if (!!doc && init) { + doc.markModified(this.path); + } + return this.cast([value], doc, init, prev); + } -
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)

    Query#cast(model, [obj])

    Casts this query to the schema of model

    show code
    Query.prototype.cast = function (model, obj) {
    -  obj || (obj= this._conditions);
    +  if (!(value && value.isMongooseDocumentArray) &&
    +      (!options || !options.skipDocumentArrayCast)) {
    +    value = new MongooseDocumentArray(value, this.path, doc);
    +    if (prev && prev._handlers) {
    +      for (var key in prev._handlers) {
    +        doc.removeListener(key, prev._handlers[key]);
    +      }
    +    }
    +  } else if (value && value.isMongooseDocumentArray) {
    +    // We need to create a new array, otherwise change tracking will
    +    // update the old doc (gh-4449)
    +    value = new MongooseDocumentArray(value, this.path, doc);
    +  }
     
    -  var schema = model.schema
    -    , paths = Object.keys(obj)
    -    , i = paths.length
    -    , any$conditionals
    -    , schematype
    -    , nested
    -    , path
    -    , type
    -    , val;
    +  i = value.length;
     
       while (i--) {
    -    path = paths[i];
    -    val = obj[path];
    +    if (!value[i]) {
    +      continue;
    +    }
     
    -    if ('$or' === path || '$nor' === path) {
    -      var k = val.length
    -        , orComponentQuery;
    +    var Constructor = this.casterConstructor;
    +    if (Constructor.discriminators &&
    +        typeof value[i][Constructor.schema.options.discriminatorKey] === 'string' &&
    +        Constructor.discriminators[value[i][Constructor.schema.options.discriminatorKey]]) {
    +      Constructor = Constructor.discriminators[value[i][Constructor.schema.options.discriminatorKey]];
    +    }
     
    -      while (k--) {
    -        orComponentQuery = new Query(val[k]);
    -        orComponentQuery.cast(model);
    -        val[k] = orComponentQuery._conditions;
    -      }
    +    // Check if the document has a different schema (re gh-3701)
    +    if ((value[i] instanceof Subdocument) &&
    +        value[i].schema !== Constructor.schema) {
    +      value[i] = value[i].toObject({ transform: false, virtuals: false });
    +    }
    +    if (!(value[i] instanceof Subdocument) && value[i]) {
    +      if (init) {
    +        if (doc) {
    +          selected || (selected = scopePaths(this, doc.$__.selected, init));
    +        } else {
    +          selected = true;
    +        }
     
    -    } else if (path === '$where') {
    -      type = typeof val;
    +        subdoc = new Constructor(null, value, true, selected, i);
    +        value[i] = subdoc.init(value[i]);
    +      } else {
    +        if (prev && (subdoc = prev.id(value[i]._id))) {
    +          subdoc = prev.id(value[i]._id);
    +        }
     
    -      if ('string' !== type && 'function' !== type) {
    -        throw new Error("Must have a string or function for $where");
    +        if (prev && subdoc && utils.deepEqual(subdoc.toObject(_opts), value[i])) {
    +          // handle resetting doc with existing id and same data
    +          subdoc.set(value[i]);
    +          // if set() is hooked it will have no return value
    +          // see gh-746
    +          value[i] = subdoc;
    +        } else {
    +          try {
    +            subdoc = new Constructor(value[i], value, undefined,
    +                undefined, i);
    +            // if set() is hooked it will have no return value
    +            // see gh-746
    +            value[i] = subdoc;
    +          } catch (error) {
    +            var valueInErrorMessage = util.inspect(value[i]);
    +            throw new CastError('embedded', valueInErrorMessage,
    +              value._path, error);
    +          }
    +        }
           }
    +    }
    +  }
     
    -      if ('function' === type) {
    -        obj[path] = val.toString();
    -      }
    +  return value;
    +};

    DocumentArray(key, schema, options)

    SubdocsArray SchemaType constructor

    Parameters:

    Inherits:

    show code
    function DocumentArray(key, schema, options) {
    +  var EmbeddedDocument = _createConstructor(schema, options);
     
    -      continue;
    +  ArrayType.call(this, key, EmbeddedDocument, options);
     
    -    } else {
    +  this.schema = schema;
    +  this.$isMongooseDocumentArray = true;
    +  var fn = this.defaultValue;
     
    -      if (!schema) {
    -        // no casting for Mixed types
    -        continue;
    +  if (!('defaultValue' in this) || fn !== void 0) {
    +    this.default(function() {
    +      var arr = fn.call(this);
    +      if (!Array.isArray(arr)) {
    +        arr = [arr];
           }
    +      // Leave it up to `cast()` to convert this to a documentarray
    +      return arr;
    +    });
    +  }
    +}

    DocumentArray#doValidate()

    Performs local validations first, then validations on each embedded doc

    show code
    DocumentArray.prototype.doValidate = function(array, fn, scope, options) {
    +  var _this = this;
    +  SchemaType.prototype.doValidate.call(this, array, function(err) {
    +    if (err) {
    +      return fn(err);
    +    }
     
    -      schematype = schema.path(path);
    +    var count = array && array.length;
    +    var error;
     
    -      if (!schematype) {
    -        // Handle potential embedded array queries
    -        var split = path.split('.')
    -          , j = split.length
    -          , pathFirstHalf
    -          , pathLastHalf
    -          , remainingConds
    -          , castingQuery;
    +    if (!count) {
    +      return fn();
    +    }
    +    if (options && options.updateValidator) {
    +      return fn();
    +    }
    +    if (!array.isMongooseDocumentArray) {
    +      array = new MongooseDocumentArray(array, _this.path, scope);
    +    }
     
    -        // Find the part of the var path that is a path of the Schema
    -        while (j--) {
    -          pathFirstHalf = split.slice(0, j).join('.');
    -          schematype = schema.path(pathFirstHalf);
    -          if (schematype) break;
    -        }
    +    // handle sparse arrays, do not use array.forEach which does not
    +    // iterate over sparse elements yet reports array.length including
    +    // them :(
     
    -        // If a substring of the input path resolves to an actual real path...
    -        if (schematype) {
    -          // Apply the casting; similar code for $elemMatch in schema/array.js
    -          if (schematype.caster && schematype.caster.schema) {
    -            remainingConds = {};
    -            pathLastHalf = split.slice(j).join('.');
    -            remainingConds[pathLastHalf] = val;
    -            castingQuery = new Query(remainingConds);
    -            castingQuery.cast(schematype.caster);
    -            obj[path] = castingQuery._conditions[pathLastHalf];
    -          } else {
    -            obj[path] = val;
    -          }
    -        }
    +    function callback(err) {
    +      if (err) {
    +        error = err;
    +      }
    +      --count || fn(error);
    +    }
     
    -      } else if (val === null || val === undefined) {
    +    for (var i = 0, len = count; i < len; ++i) {
    +      // sidestep sparse entries
    +      var doc = array[i];
    +      if (!doc) {
    +        --count || fn(error);
             continue;
    -      } else if ('Object' === val.constructor.name) {
    +      }
     
    -        any$conditionals = Object.keys(val).some(function (k) {
    -          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
    -        });
    +      // If you set the array index directly, the doc might not yet be
    +      // a full fledged mongoose subdoc, so make it into one.
    +      if (!(doc instanceof Subdocument)) {
    +        doc = array[i] = new _this.casterConstructor(doc, array, undefined,
    +            undefined, i);
    +      }
     
    -        if (!any$conditionals) {
    -          obj[path] = schematype.castForQuery(val);
    -        } else {
    +      // HACK: use $__original_validate to avoid promises so bluebird doesn't
    +      // complain
    +      if (doc.$__original_validate) {
    +        doc.$__original_validate({__noPromise: true}, callback);
    +      } else {
    +        doc.validate({__noPromise: true}, callback);
    +      }
    +    }
    +  }, scope);
    +};

    DocumentArray#doValidateSync()

    Performs local validations first, then validations on each embedded doc.

    Note:

    - var ks = Object.keys(val) - , k = ks.length - , $cond; +

    This method ignores the asynchronous validators.

    show code
    DocumentArray.prototype.doValidateSync = function(array, scope) {
    +  var schemaTypeError = SchemaType.prototype.doValidateSync.call(this, array, scope);
    +  if (schemaTypeError) {
    +    return schemaTypeError;
    +  }
     
    -          while (k--) {
    -            $cond = ks[k];
    -            nested = val[$cond];
    +  var count = array && array.length,
    +      resultError = null;
     
    -            if ('$exists' === $cond) {
    -              if ('boolean' !== typeof nested) {
    -                throw new Error("$exists parameter must be Boolean");
    -              }
    -              continue;
    -            }
    +  if (!count) {
    +    return;
    +  }
     
    -            if ('$type' === $cond) {
    -              if ('number' !== typeof nested) {
    -                throw new Error("$type parameter must be Number");
    -              }
    -              continue;
    -            }
    +  // handle sparse arrays, do not use array.forEach which does not
    +  // iterate over sparse elements yet reports array.length including
    +  // them :(
     
    -            if ('$not' === $cond) {
    -              this.cast(model, nested);
    -            } else {
    -              val[$cond] = schematype.castForQuery($cond, nested);
    -            }
    -          }
    -        }
    -      } else {
    -        obj[path] = schematype.castForQuery(val);
    -      }
    +  for (var i = 0, len = count; i < len; ++i) {
    +    // only first error
    +    if (resultError) {
    +      break;
    +    }
    +    // sidestep sparse entries
    +    var doc = array[i];
    +    if (!doc) {
    +      continue;
         }
    -  }
    -
    -  return obj;
    -};

    Parameters:

    Returns:

    Note

    -

    If obj is present, it is cast instead of this query.


    Query#_optionsForExec(model)

    Returns default options.

    show code
    Query.prototype._optionsForExec = function (model) {
    -  var options = utils.clone(this.options, { retainKeyOrder: true });
    -  delete options.populate;
    +    // If you set the array index directly, the doc might not yet be
    +    // a full fledged mongoose subdoc, so make it into one.
    +    if (!(doc instanceof Subdocument)) {
    +      doc = array[i] = new this.casterConstructor(doc, array, undefined,
    +        undefined, i);
    +    }
     
    -  if (!('safe' in options))
    -    options.safe = model.schema.options.safe;
    +    var subdocValidateError = doc.validateSync();
     
    -  if (!('readPreference' in options) && model.schema.options.read)
    -    options.readPreference = model.schema.options.read;
    +    if (subdocValidateError) {
    +      resultError = subdocValidateError;
    +    }
    +  }
     
    -  return options;
    -};

    Parameters:


    Query#_applyPaths()

    Applies schematype selected options to this query.

    show code
    Query.prototype._applyPaths = function applyPaths () {
    -  // determine if query is selecting or excluding fields
    +  return resultError;
    +};

    DocumentArray.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    DocumentArray.schemaName = 'DocumentArray';

  • schema/number.js

    SchemaNumber#cast(value, doc, init)

    Casts to number

    Parameters:

    show code
    SchemaNumber.prototype.cast = function(value, doc, init) {
    +  if (SchemaType._isRef(this, value, doc, init)) {
    +    // wait! we may need to cast this to a document
     
    -  var fields = this._fields
    -    , exclude
    -    , keys
    -    , ki
    +    if (value === null || value === undefined) {
    +      return value;
    +    }
     
    -  if (fields) {
    -    keys = Object.keys(fields);
    -    ki = keys.length;
    +    // lazy load
    +    Document || (Document = require('./../document'));
     
    -    while (ki--) {
    -      if ('+' == keys[ki][0]) continue;
    -      exclude = 0 === fields[keys[ki]];
    -      break;
    +    if (value instanceof Document) {
    +      value.$__.wasPopulated = true;
    +      return value;
         }
    -  }
     
    -  // if selecting, apply default schematype select:true fields
    -  // if excluding, apply schematype select:false fields
    +    // setting a populated path
    +    if (typeof value === 'number') {
    +      return value;
    +    } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
    +      throw new CastError('number', value, this.path);
    +    }
     
    -  var selected = []
    -    , excluded = []
    -    , seen = [];
    +    // Handle the case where user directly sets a populated
    +    // path to a plain object; cast to the Model used in
    +    // the population query.
    +    var path = doc.$__fullPath(this.path);
    +    var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
    +    var pop = owner.populated(path, true);
    +    var ret = new pop.options.model(value);
    +    ret.$__.wasPopulated = true;
    +    return ret;
    +  }
     
    -  analyzeSchema(this.model.schema);
    +  var val = value && typeof value._id !== 'undefined' ?
    +    value._id : // documents
    +    value;
     
    -  switch (exclude) {
    -    case true:
    -      excluded.length && this.select('-' + excluded.join(' -'));
    -      break;
    -    case false:
    -      selected.length && this.select(selected.join(' '));
    -      break;
    -    case undefined:
    -      // user didn't specify fields, implies returning all fields.
    -      // only need to apply excluded fields
    -      excluded.length && this.select('-' + excluded.join(' -'));
    -      break;
    +  if (!isNaN(val)) {
    +    if (val === null) {
    +      return val;
    +    }
    +    if (val === '') {
    +      return null;
    +    }
    +    if (typeof val === 'string' || typeof val === 'boolean') {
    +      val = Number(val);
    +    }
    +    if (val instanceof Number) {
    +      return val;
    +    }
    +    if (typeof val === 'number') {
    +      return val;
    +    }
    +    if (val.toString && !Array.isArray(val) && val.toString() == Number(val)) {
    +      return new Number(val);
    +    }
       }
     
    -  return seen = excluded = selected = keys = fields = null;
    +  throw new CastError('number', value, this.path);
    +};

    SchemaNumber#castForQuery($conditional, [value])

    Casts contents for queries.

    Parameters:

    • $conditional <String>
    • [value] <T>
    show code
    SchemaNumber.prototype.castForQuery = function($conditional, val) {
    +  var handler;
    +  if (arguments.length === 2) {
    +    handler = this.$conditionalHandlers[$conditional];
    +    if (!handler) {
    +      throw new Error('Can\'t use ' + $conditional + ' with Number.');
    +    }
    +    return handler.call(this, val);
    +  }
    +  val = this._castForQuery($conditional);
    +  return val;
    +};

    SchemaNumber#checkRequired(value, doc)

    Check if the given value satisfies a required validator.

    Parameters:

    Returns:

    show code
    SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
    +  if (SchemaType._isRef(this, value, doc, true)) {
    +    return !!value;
    +  }
    +  return typeof value === 'number' || value instanceof Number;
    +};

    SchemaNumber#max(maximum, [message])

    Sets a maximum number validator.

    Parameters:

    • maximum <Number> number
    • [message] <String> optional custom error message

    Returns:

    Example:

    - function analyzeSchema (schema, prefix) { - prefix || (prefix = ''); +
    var s = new Schema({ n: { type: Number, max: 10 })
    +var M = db.model('M', s)
    +var m = new M({ n: 11 })
    +m.save(function (err) {
    +  console.error(err) // validator error
    +  m.n = 10;
    +  m.save() // success
    +})
     
    -    // avoid recursion
    -    if (~seen.indexOf(schema)) return;
    -    seen.push(schema);
    +// custom error messages
    +// We can also use the special {MAX} token which will be replaced with the invalid value
    +var max = [10, 'The value of path `{PATH}` ({VALUE}) exceeds the limit ({MAX}).'];
    +var schema = new Schema({ n: { type: Number, max: max })
    +var M = mongoose.model('Measurement', schema);
    +var s= new M({ n: 4 });
    +s.validate(function (err) {
    +  console.log(String(err)) // ValidationError: The value of path `n` (4) exceeds the limit (10).
    +})
    show code
    SchemaNumber.prototype.max = function(value, message) {
    +  if (this.maxValidator) {
    +    this.validators = this.validators.filter(function(v) {
    +      return v.validator !== this.maxValidator;
    +    }, this);
    +  }
    +
    +  if (value !== null && value !== undefined) {
    +    var msg = message || MongooseError.messages.Number.max;
    +    msg = msg.replace(/{MAX}/, value);
    +    this.validators.push({
    +      validator: this.maxValidator = function(v) {
    +        return v == null || v <= value;
    +      },
    +      message: msg,
    +      type: 'max',
    +      max: value
    +    });
    +  }
     
    -    schema.eachPath(function (path, type) {
    -      if (prefix) path = prefix + '.' + path;
    +  return this;
    +};

    SchemaNumber#min(value, [message])

    Sets a minimum number validator.

    Parameters:

    • value <Number> minimum number
    • [message] <String> optional custom error message

    Returns:

    Example:

    - // array of subdocs? - if (type.schema) { - analyzeSchema(type.schema, path); - } +
    var s = new Schema({ n: { type: Number, min: 10 })
    +var M = db.model('M', s)
    +var m = new M({ n: 9 })
    +m.save(function (err) {
    +  console.error(err) // validator error
    +  m.n = 10;
    +  m.save() // success
    +})
     
    -      analyzePath(path, type);
    +// custom error messages
    +// We can also use the special {MIN} token which will be replaced with the invalid value
    +var min = [10, 'The value of path `{PATH}` ({VALUE}) is beneath the limit ({MIN}).'];
    +var schema = new Schema({ n: { type: Number, min: min })
    +var M = mongoose.model('Measurement', schema);
    +var s= new M({ n: 4 });
    +s.validate(function (err) {
    +  console.log(String(err)) // ValidationError: The value of path `n` (4) is beneath the limit (10).
    +})
    show code
    SchemaNumber.prototype.min = function(value, message) {
    +  if (this.minValidator) {
    +    this.validators = this.validators.filter(function(v) {
    +      return v.validator !== this.minValidator;
    +    }, this);
    +  }
    +
    +  if (value !== null && value !== undefined) {
    +    var msg = message || MongooseError.messages.Number.min;
    +    msg = msg.replace(/{MIN}/, value);
    +    this.validators.push({
    +      validator: this.minValidator = function(v) {
    +        return v == null || v >= value;
    +      },
    +      message: msg,
    +      type: 'min',
    +      min: value
         });
       }
     
    -  function analyzePath (path, type) {
    -    if ('boolean' != typeof type.selected) return;
    +  return this;
    +};

    SchemaNumber(key, options)

    Number SchemaType constructor.

    Parameters:

    Inherits:

    show code
    function SchemaNumber(key, options) {
    +  SchemaType.call(this, key, options, 'Number');
    +}

    SchemaNumber.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    SchemaNumber.schemaName = 'Number';

  • schema/date.js

    SchemaDate#cast(value)

    Casts to date

    Parameters:

    show code
    SchemaDate.prototype.cast = function(value) {
    +  // If null or undefined
    +  if (value === null || value === void 0 || value === '') {
    +    return null;
    +  }
     
    -    if (fields && ('+' + path) in fields) {
    -      // forced inclusion
    -      delete fields['+' + path];
    +  if (value instanceof Date) {
    +    if (isNaN(value.valueOf())) {
    +      throw new CastError('date', value, this.path);
    +    }
     
    -      // if there are other fields being included, add this one
    -      // if no other included fields, leave this out (implied inclusion)
    -      if (false === exclude && keys.length > 1) {
    -        fields[path] = 1;
    -      }
    +    return value;
    +  }
     
    -      return
    -    };
    +  var date;
     
    -    ;(type.selected ? selected : excluded).push(path);
    +  if (typeof value === 'boolean') {
    +    throw new CastError('date', value, this.path);
       }
    -}

    Query#$where(js)

    Specifies a $where condition

    Parameters:

    Returns:

    Use $where when you need to select documents using a JavaScript expression.

    -

    Example

    + if (value instanceof Number || typeof value === 'number' + || String(value) == Number(value)) { + // support for timestamps + date = new Date(Number(value)); + } else if (value.valueOf) { + // support for moment.js + date = new Date(value.valueOf()); + } -
    query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
    +  if (!isNaN(date.valueOf())) {
    +    return date;
    +  }
     
    -query.$where(function () {
    -  return this.comments.length &gt; 10 || this.name.length &gt; 5;
    -})

    Query#where([path], [val])

    Specifies a path for use with chaining.

    show code
    Query.prototype.where = function (path, val) {
    -  if (!arguments.length) return this;
    +  throw new CastError('date', value, this.path);
    +};

    SchemaDate#castForQuery($conditional, [value])

    Casts contents for queries.

    Parameters:

    • $conditional <String>
    • [value] <T>
    show code
    SchemaDate.prototype.castForQuery = function($conditional, val) {
    +  var handler;
     
    -  if ('string' != typeof path) {
    -    throw new TypeError('path must be a string');
    +  if (arguments.length !== 2) {
    +    return this._castForQuery($conditional);
       }
     
    -  this._currPath = path;
    +  handler = this.$conditionalHandlers[$conditional];
     
    -  if (2 === arguments.length) {
    -    this._conditions[path] = val;
    +  if (!handler) {
    +    throw new Error('Can\'t use ' + $conditional + ' with Date.');
       }
     
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    + return handler.call(this, val); +};

    SchemaDate#checkRequired(value, doc)

    Check if the given value satisfies a required validator. To satisfy
    a required validator, the given value must be an instance of Date.

    Parameters:

    Returns:

    show code
    SchemaDate.prototype.checkRequired = function(value) {
    +  return value instanceof Date;
    +};

    SchemaDate#expires(when)

    Declares a TTL index (rounded to the nearest second) for Date types only.

    Parameters:

    Returns:

    This sets the expireAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    -
    // instead of writing:
    -User.find({age: {$gte: 21, $lte: 65}}, callback);
    +

    Example:

    -// we can instead write: -User.where('age').gte(21).lte(65); +
    // expire in 24 hours
    +new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
    -// Moreover, you can also chain a bunch of these together: +

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    -User -.where('age').gte(21).lte(65) -.where('name', /^b/i) -.where('friends').slice(10) -.exec(callback)

    Query#equals(val)

    Specifies the complementary comparison value for paths specified with where()

    show code
    Query.prototype.equals = function equals (val) {
    -  var path = this._currPath;
    -  if (!path) throw new Error('equals() must be used after where()');
    -  this._conditions[path] = val;
    -  return this;
    -}

    Parameters:

    Returns:

    Example

    +

    Example:

    -
    User.where('age').equals(49);
    +
    // expire in 24 hours
    +new Schema({ createdAt: { type: Date, expires: '24h' }});
     
    -// is the same as
    +// expire in 1.5 hours
    +new Schema({ createdAt: { type: Date, expires: '1.5h' }});
     
    -User.where('age', 49);

    Query#or(array)

    Specifies arguments for an $or condition.

    show code
    Query.prototype.or = function or (array) {
    -  var or = this._conditions.$or || (this._conditions.$or = []);
    -  if (!Array.isArray(array)) array = [array];
    -  or.push.apply(or, array);
    -  return this;
    -}

    Parameters:

    • array <Array> array of conditions

    Returns:

    Example

    +// expire in 7 days +var schema = new Schema({ createdAt: Date }); +schema.path('createdAt').expires('7d');
    show code
    SchemaDate.prototype.expires = function(when) {
    +  if (!this._index || this._index.constructor.name !== 'Object') {
    +    this._index = {};
    +  }
     
    -
    query.or([{ color: 'red' }, { status: 'emergency' }])

    Query#nor(array)

    Specifies arguments for a $nor condition.

    show code
    Query.prototype.nor = function nor (array) {
    -  var nor = this._conditions.$nor || (this._conditions.$nor = []);
    -  if (!Array.isArray(array)) array = [array];
    -  nor.push.apply(nor, array);
    +  this._index.expires = when;
    +  utils.expires(this._index);
       return this;
    -}

    Parameters:

    • array <Array> array of conditions

    Returns:

    Example

    - -
    query.nor([{ color: 'green' }, { status: 'ok' }])

    Query#gt(path, val)

    Specifies a $gt query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.

    +};

    SchemaDate#max(maximum, [message])

    Sets a maximum date validator.

    Parameters:

    • maximum <Date> date
    • [message] <String> optional custom error message

    Returns:

    Example:

    -

    Example

    - -
    Thing.find().where('age').gt(21)
    +
    var s = new Schema({ d: { type: Date, max: Date('2014-01-01') })
    +var M = db.model('M', s)
    +var m = new M({ d: Date('2014-12-08') })
    +m.save(function (err) {
    +  console.error(err) // validator error
    +  m.d = Date('2013-12-31');
    +  m.save() // success
    +})
     
    -// or
    -Thing.find().gt('age', 21)

    Query#gte(path, val)

    Specifies a $gte query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#lt(path, val)

    Specifies a $lt query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#lte(path, val)

    Specifies a $lte query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#ne(path, val)

    Specifies a $ne query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#in(path, val)

    Specifies an $in query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#nin(path, val)

    Specifies an $nin query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#all(path, val)

    Specifies an $all query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#size(path, val)

    Specifies an $size query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#regex(path, val)

    Specifies a $regex query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#maxDistance(path, val)

    Specifies a $maxDistance query condition.

    Parameters:

    When called with one argument, the most recent path passed to where() is used.


    Query#near(path, val)

    Specifies a $near condition

    show code
    Query.prototype.near = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$near = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#nearSphere(path, val)

    Specifies a $nearSphere condition.

    show code
    Query.prototype.nearSphere = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$nearSphere = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#mod(path, val)

    Specifies a $mod condition

    show code
    Query.prototype.mod = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath
    -  } else if (arguments.length === 2 && !Array.isArray(val)) {
    -    val = utils.args(arguments);
    -    path = this._currPath;
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds.$mod = val;
    -  return this;
    -}

    Parameters:

    Returns:


    Query#exists(path, val)

    Specifies an $exists condition

    show code
    Query.prototype.exists = function (path, val) {
    -  if (arguments.length === 0) {
    -    path = this._currPath
    -    val = true;
    -  } else if (arguments.length === 1) {
    -    if ('boolean' === typeof path) {
    -      val = path;
    -      path = this._currPath;
    -    } else {
    -      val = true;
    -    }
    +// custom error messages
    +// We can also use the special {MAX} token which will be replaced with the invalid value
    +var max = [Date('2014-01-01'), 'The value of path `{PATH}` ({VALUE}) exceeds the limit ({MAX}).'];
    +var schema = new Schema({ d: { type: Date, max: max })
    +var M = mongoose.model('M', schema);
    +var s= new M({ d: Date('2014-12-08') });
    +s.validate(function (err) {
    +  console.log(String(err)) // ValidationError: The value of path `d` (2014-12-08) exceeds the limit (2014-01-01).
    +})
    show code
    SchemaDate.prototype.max = function(value, message) {
    +  if (this.maxValidator) {
    +    this.validators = this.validators.filter(function(v) {
    +      return v.validator !== this.maxValidator;
    +    }, this);
    +  }
    +
    +  if (value) {
    +    var msg = message || MongooseError.messages.Date.max;
    +    msg = msg.replace(/{MAX}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
    +    var _this = this;
    +    this.validators.push({
    +      validator: this.maxValidator = function(val) {
    +        var max = (value === Date.now ? value() : _this.cast(value));
    +        return val === null || val.valueOf() <= max.valueOf();
    +      },
    +      message: msg,
    +      type: 'max',
    +      max: value
    +    });
       }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$exists'] = val;
    +
       return this;
    -};

    Parameters:

    Returns:


    Query#elemMatch(path, criteria)

    Specifies an $elemMatch condition

    show code
    Query.prototype.elemMatch = function (path, criteria) {
    -  var block;
    -  if ('Object' === path.constructor.name) {
    -    criteria = path;
    -    path = this._currPath;
    -  } else if ('function' === typeof path) {
    -    block = path;
    -    path = this._currPath;
    -  } else if ('Object' === criteria.constructor.name) {
    -  } else if ('function' === typeof criteria) {
    -    block = criteria;
    -  } else {
    -    throw new Error("Argument error");
    -  }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  if (block) {
    -    criteria = new Query();
    -    block(criteria);
    -    conds['$elemMatch'] = criteria._conditions;
    -  } else {
    -    conds['$elemMatch'] = criteria;
    +};

    SchemaDate#min(value, [message])

    Sets a minimum date validator.

    Parameters:

    • value <Date> minimum date
    • [message] <String> optional custom error message

    Returns:

    Example:

    + +
    var s = new Schema({ d: { type: Date, min: Date('1970-01-01') })
    +var M = db.model('M', s)
    +var m = new M({ d: Date('1969-12-31') })
    +m.save(function (err) {
    +  console.error(err) // validator error
    +  m.d = Date('2014-12-08');
    +  m.save() // success
    +})
    +
    +// custom error messages
    +// We can also use the special {MIN} token which will be replaced with the invalid value
    +var min = [Date('1970-01-01'), 'The value of path `{PATH}` ({VALUE}) is beneath the limit ({MIN}).'];
    +var schema = new Schema({ d: { type: Date, min: min })
    +var M = mongoose.model('M', schema);
    +var s= new M({ d: Date('1969-12-31') });
    +s.validate(function (err) {
    +  console.log(String(err)) // ValidationError: The value of path `d` (1969-12-31) is before the limit (1970-01-01).
    +})
    show code
    SchemaDate.prototype.min = function(value, message) {
    +  if (this.minValidator) {
    +    this.validators = this.validators.filter(function(v) {
    +      return v.validator !== this.minValidator;
    +    }, this);
    +  }
    +
    +  if (value) {
    +    var msg = message || MongooseError.messages.Date.min;
    +    msg = msg.replace(/{MIN}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
    +    var _this = this;
    +    this.validators.push({
    +      validator: this.minValidator = function(val) {
    +        var min = (value === Date.now ? value() : _this.cast(value));
    +        return val === null || val.valueOf() >= min.valueOf();
    +      },
    +      message: msg,
    +      type: 'min',
    +      min: value
    +    });
       }
    +
       return this;
    -};
    +};

    SchemaDate(key, options)

    Date SchemaType constructor.

    Parameters:

    Inherits:

    show code
    function SchemaDate(key, options) {
    +  SchemaType.call(this, key, options, 'Date');
    +}

    SchemaDate.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    SchemaDate.schemaName = 'Date';

  • schema/buffer.js

    SchemaBuffer#cast(value, doc, init)

    Casts contents

    Parameters:

    show code
    SchemaBuffer.prototype.cast = function(value, doc, init) {
    +  var ret;
    +  if (SchemaType._isRef(this, value, doc, init)) {
    +    // wait! we may need to cast this to a document
    +
    +    if (value === null || value === undefined) {
    +      return value;
    +    }
     
    -// Spatial queries

    Parameters:

    Returns:

    Example

    + // lazy load + Document || (Document = require('./../document')); -
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
    +    if (value instanceof Document) {
    +      value.$__.wasPopulated = true;
    +      return value;
    +    }
     
    -query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
    +    // setting a populated path
    +    if (Buffer.isBuffer(value)) {
    +      return value;
    +    } else if (!utils.isObject(value)) {
    +      throw new CastError('buffer', value, this.path);
    +    }
     
    -query.elemMatch('comment', function (elem) {
    -  elem.where('author').equals('autobot');
    -  elem.where('votes').gte(5);
    -})
    +    // Handle the case where user directly sets a populated
    +    // path to a plain object; cast to the Model used in
    +    // the population query.
    +    var path = doc.$__fullPath(this.path);
    +    var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
    +    var pop = owner.populated(path, true);
    +    ret = new pop.options.model(value);
    +    ret.$__.wasPopulated = true;
    +    return ret;
    +  }
     
    -query.where('comment').elemMatch(function (elem) {
    -  elem.where('author').equals('autobot');
    -  elem.where('votes').gte(5);
    -})

    Query#box(path, val)

    Specifies a $box condition

    show code
    Query.prototype.box = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    +  // documents
    +  if (value && value._id) {
    +    value = value._id;
       }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$box': [val.ll, val.ur]  };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    -
    var lowerLeft = [40.73083, -73.99756]
    -var upperRight= [40.741404,  -73.988135]
    -query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

    Query#center(path, val, [opts])

    Specifies a $center condition

    show code
    Query.prototype.center = function (path, val, opts) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    +  if (value && value.isMongooseBuffer) {
    +    return value;
       }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$center': [val.center, val.radius]  };
     
    -  // copy any options
    -  if (opts && 'Object' == opts.constructor.name) {
    -    utils.options(opts, conds.$within);
    +  if (Buffer.isBuffer(value)) {
    +    if (!value || !value.isMongooseBuffer) {
    +      value = new MongooseBuffer(value, [this.path, doc]);
    +    }
    +
    +    return value;
    +  } else if (value instanceof Binary) {
    +    ret = new MongooseBuffer(value.value(true), [this.path, doc]);
    +    if (typeof value.sub_type !== 'number') {
    +      throw new CastError('buffer', value, this.path);
    +    }
    +    ret._subtype = value.sub_type;
    +    return ret;
       }
     
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    + if (value === null) { + return value; + } -
    var area = { center: [50, 50], radius: 10 }
    -query.where('loc').within.center(area)

    Query#centerSphere(path, val)

    Specifies a $centerSphere condition

    show code
    Query.prototype.centerSphere = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    +  var type = typeof value;
    +  if (type === 'string' || type === 'number' || Array.isArray(value)) {
    +    if (type === 'number') {
    +      value = [value];
    +    }
    +    ret = new MongooseBuffer(value, [this.path, doc]);
    +    return ret;
       }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    -
    var area = { center: [50, 50], radius: 10 }
    -query.where('loc').within.centerSphere(area)

    Query#polygon(path, val)

    Specifies a $polygon condition

    show code
    Query.prototype.polygon = function (path, val) {
    -  if (arguments.length === 1) {
    -    val = path;
    -    path = this._currPath;
    +  throw new CastError('buffer', value, this.path);
    +};

    SchemaBuffer#castForQuery($conditional, [value])

    Casts contents for queries.

    Parameters:

    • $conditional <String>
    • [value] <T>
    show code
    SchemaBuffer.prototype.castForQuery = function($conditional, val) {
    +  var handler;
    +  if (arguments.length === 2) {
    +    handler = this.$conditionalHandlers[$conditional];
    +    if (!handler) {
    +      throw new Error('Can\'t use ' + $conditional + ' with Buffer.');
    +    }
    +    return handler.call(this, val);
       }
    -  var conds = this._conditions[path] || (this._conditions[path] = {});
    -  conds['$within'] = { '$polygon': val };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    + val = $conditional; + var casted = this._castForQuery(val); + return casted ? casted.toObject({ transform: false, virtuals: false }) : casted; +};

    SchemaBuffer#checkRequired(value, doc)

    Check if the given value satisfies a required validator. To satisfy a
    required validator, a buffer must not be null or undefined and have
    non-zero length.

    Parameters:

    Returns:

    show code
    SchemaBuffer.prototype.checkRequired = function(value, doc) {
    +  if (SchemaType._isRef(this, value, doc, true)) {
    +    return !!value;
    +  }
    +  return !!(value && value.length);
    +};

    SchemaBuffer(key, options)

    Buffer SchemaType constructor

    Parameters:

    Inherits:

    show code
    function SchemaBuffer(key, options) {
    +  SchemaType.call(this, key, options, 'Buffer');
    +}

    SchemaBuffer.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    SchemaBuffer.schemaName = 'Buffer';

  • schema/boolean.js

    SchemaBoolean#cast(value)

    Casts to boolean

    Parameters:

    show code
    SchemaBoolean.prototype.cast = function(value) {
    +  if (value === null) {
    +    return value;
    +  }
    +  if (value === '0') {
    +    return false;
    +  }
    +  if (value === 'true') {
    +    return true;
    +  }
    +  if (value === 'false') {
    +    return false;
    +  }
    +  return !!value;
    +};
     
    -
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
    -query.where('loc').within.polygon(polyA)
    +SchemaBoolean.$conditionalHandlers =
    +    utils.options(SchemaType.prototype.$conditionalHandlers, {});

    SchemaBoolean#castForQuery($conditional, val)

    Casts contents for queries.

    Parameters:

    • $conditional <String>
    • val <T>
    show code
    SchemaBoolean.prototype.castForQuery = function($conditional, val) {
    +  var handler;
    +  if (arguments.length === 2) {
    +    handler = SchemaBoolean.$conditionalHandlers[$conditional];
     
    -// or
    -var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
    -query.where('loc').within.polygon(polyB)

    Query#select(arg)

    Specifies which document fields to include or exclude

    show code
    Query.prototype.select = function select (arg) {
    -  if (!arg) return this;
    +    if (handler) {
    +      return handler.call(this, val);
    +    }
     
    -  var fields = this._fields || (this._fields = {});
    +    return this._castForQuery(val);
    +  }
     
    -  if ('Object' === arg.constructor.name) {
    -    Object.keys(arg).forEach(function (field) {
    -      fields[field] = arg[field];
    -    });
    -  } else if (1 === arguments.length && 'string' == typeof arg) {
    -    arg.split(/\s+/).forEach(function (field) {
    -      if (!field) return;
    -      var include = '-' == field[0] ? 0 : 1;
    -      if (include === 0) field = field.substring(1);
    -      fields[field] = include;
    -    });
    -  } else {
    -    throw new TypeError('Invalid select() argument. Must be a string or object.');
    +  return this._castForQuery($conditional);
    +};

    SchemaBoolean#checkRequired(value)

    Check if the given value satisfies a required validator. For a boolean
    to satisfy a required validator, it must be strictly equal to true or to
    false.

    Parameters:

    Returns:

    show code
    SchemaBoolean.prototype.checkRequired = function(value) {
    +  return value === true || value === false;
    +};

    SchemaBoolean(path, options)

    Boolean SchemaType constructor.

    Parameters:

    Inherits:

    show code
    function SchemaBoolean(path, options) {
    +  SchemaType.call(this, path, options, 'Boolean');
    +}

    SchemaBoolean.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    SchemaBoolean.schemaName = 'Boolean';

  • schema/objectid.js

    ObjectId#auto(turnOn)

    Adds an auto-generated ObjectId default if turnOn is true.

    Parameters:

    • turnOn <Boolean> auto generated ObjectId defaults

    Returns:

    show code
    ObjectId.prototype.auto = function(turnOn) {
    +  if (turnOn) {
    +    this.default(defaultId);
    +    this.set(resetId);
       }
     
       return this;
    -};

    Parameters:

    Returns:

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    - -

    Example

    - -
    // include a and b, exclude c
    -query.select('a b -c');
    +};

    ObjectId#cast(value, doc, init)

    Casts to ObjectId

    Parameters:

    show code
    ObjectId.prototype.cast = function(value, doc, init) {
    +  if (SchemaType._isRef(this, value, doc, init)) {
    +    // wait! we may need to cast this to a document
     
    -// or you may use object notation, useful when
    -// you have keys already prefixed with a "-"
    -query.select({a: 1, b: 1, c: 0});
    +    if (value === null || value === undefined) {
    +      return value;
    +    }
     
    -// force inclusion of field excluded at schema level
    -query.select('+path')
    + // lazy load + Document || (Document = require('./../document')); -

    NOTE:

    + if (value instanceof Document) { + value.$__.wasPopulated = true; + return value; + } -

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


    Query#slice(path, val)

    Specifies a $slice condition

    show code
    Query.prototype.slice = function (path, val) {
    -  if (arguments.length === 1) {
    -      val = path;
    -      path = this._currPath
    -  } else if (arguments.length === 2) {
    -    if ('number' === typeof path) {
    -      val = [path, val];
    -      path = this._currPath;
    -    }
    -  } else if (arguments.length === 3) {
    -    val = utils.args(arguments, 1);
    -  }
    -  var myFields = this._fields || (this._fields = {});
    -  myFields[path] = { '$slice': val };
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    + // setting a populated path + if (value instanceof oid) { + return value; + } else if ((value.constructor.name || '').toLowerCase() === 'objectid') { + return new oid(value.toHexString()); + } else if (Buffer.isBuffer(value) || !utils.isObject(value)) { + throw new CastError('ObjectId', value, this.path); + } -
    query.slice('comments', 5)
    -query.slice('comments', -5)
    -query.slice('comments', [10, 5])
    -query.where('comments').slice(5)
    -query.where('comments').slice([-10, 5])

    Query#sort(arg)

    Sets the sort order

    show code
    Query.prototype.sort = function (arg) {
    -  if (!arg) return this;
    +    // Handle the case where user directly sets a populated
    +    // path to a plain object; cast to the Model used in
    +    // the population query.
    +    var path = doc.$__fullPath(this.path);
    +    var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
    +    var pop = owner.populated(path, true);
    +    var ret = value;
    +    if (!doc.$__.populated ||
    +        !doc.$__.populated[path] ||
    +        !doc.$__.populated[path].options ||
    +        !doc.$__.populated[path].options.options ||
    +        !doc.$__.populated[path].options.options.lean) {
    +      ret = new pop.options.model(value);
    +      ret.$__.wasPopulated = true;
    +    }
     
    -  var sort = this.options.sort || (this.options.sort = []);
    +    return ret;
    +  }
     
    -  if ('Object' === arg.constructor.name) {
    -    Object.keys(arg).forEach(function (field) {
    -      push(sort, field, arg[field]);
    -    });
    -  } else if (1 === arguments.length && 'string' == typeof arg) {
    -    arg.split(/\s+/).forEach(function (field) {
    -      if (!field) return;
    -      var ascend = '-' == field[0] ? -1 : 1;
    -      if (ascend === -1) field = field.substring(1);
    -      push(sort, field, ascend);
    -    });
    -  } else {
    -    throw new TypeError('Invalid sort() argument. Must be a string or object.');
    +  if (value === null || value === undefined) {
    +    return value;
       }
     
    -  return this;
    -};

    Parameters:

    Returns:

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    + if (value instanceof oid) { + return value; + } -

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    + if (value._id) { + if (value._id instanceof oid) { + return value._id; + } + if (value._id.toString instanceof Function) { + try { + return new oid(value._id.toString()); + } catch (e) { + } + } + } -

    Example

    + if (value.toString instanceof Function) { + try { + return new oid(value.toString()); + } catch (err) { + throw new CastError('ObjectId', value, this.path); + } + } -
    // these are equivalent
    -query.sort({ field: 'asc', test: -1 });
    -query.sort('field -test');

    Query#limit(val)

    Specifies the limit option.

    Parameters:

    Example

    + throw new CastError('ObjectId', value, this.path); +};

    ObjectId#castForQuery($conditional, [val])

    Casts contents for queries.

    Parameters:

    • $conditional <String>
    • [val] <T>
    show code
    ObjectId.prototype.castForQuery = function($conditional, val) {
    +  var handler;
    +  if (arguments.length === 2) {
    +    handler = this.$conditionalHandlers[$conditional];
    +    if (!handler) {
    +      throw new Error('Can\'t use ' + $conditional + ' with ObjectId.');
    +    }
    +    return handler.call(this, val);
    +  }
    +  return this._castForQuery($conditional);
    +};

    ObjectId#checkRequired(value, doc)

    Check if the given value satisfies a required validator.

    Parameters:

    Returns:

    show code
    ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
    +  if (SchemaType._isRef(this, value, doc, true)) {
    +    return !!value;
    +  }
    +  return value instanceof oid;
    +};

    ObjectId(key, options)

    ObjectId SchemaType constructor.

    Parameters:

    Inherits:

    show code
    function ObjectId(key, options) {
    +  if ((typeof key === 'string' && key.length === 24) || typeof key === 'undefined') {
    +    console.warn('To create a new ObjectId please try ' +
    +      '`Mongoose.Types.ObjectId` instead of using ' +
    +      '`Mongoose.Schema.ObjectId`.');
    +  }
    +  SchemaType.call(this, key, options, 'ObjectID');
    +}

    ObjectId.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    ObjectId.schemaName = 'ObjectId';

  • schema/mixed.js

    Mixed#cast(value)

    Casts val for Mixed.

    Parameters:

    this is a no-op

    show code
    Mixed.prototype.cast = function(val) {
    +  return val;
    +};

    Mixed#castForQuery($cond, [val])

    Casts contents for queries.

    Parameters:

    show code
    Mixed.prototype.castForQuery = function($cond, val) {
    +  if (arguments.length === 2) {
    +    return val;
    +  }
    +  return $cond;
    +};

    Mixed(path, options)

    Mixed SchemaType constructor.

    Parameters:

    Inherits:

    show code
    function Mixed(path, options) {
    +  if (options && options.default) {
    +    var def = options.default;
    +    if (Array.isArray(def) && def.length === 0) {
    +      // make sure empty array defaults are handled
    +      options.default = Array;
    +    } else if (!options.shared && utils.isObject(def) && Object.keys(def).length === 0) {
    +      // prevent odd "shared" objects between documents
    +      options.default = function() {
    +        return {};
    +      };
    +    }
    +  }
     
    -
    Kitten.find().limit(20)

    Query#skip(val)

    Specifies the skip option.

    Parameters:

    Example

    + SchemaType.call(this, path, options, 'Mixed'); +}

    Mixed.schemaName

    This schema type's name, to defend against minifiers that mangle
    function names.

    show code
    Mixed.schemaName = 'Mixed';

  • schema/embedded.js

    Embedded#cast(value)

    Casts contents

    Parameters:

    show code
    Embedded.prototype.cast = function(val, doc, init, priorVal) {
    +  if (val && val.$isSingleNested) {
    +    return val;
    +  }
     
    -
    Kitten.find().skip(100).limit(20)

    Query#maxscan(val)

    Specifies the maxscan option.

    Parameters:

    Example

    + var subdoc; + if (init) { + subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); + subdoc.init(val); + } else { + if (Object.keys(val).length === 0) { + return new this.caster({}, doc ? doc.$__.selected : void 0, doc); + } -
    Kitten.find().maxscan(100)

    Query#batchSize(val)

    Specifies the batchSize option.

    Parameters:

    Example

    + if (priorVal && priorVal.$isSingleNested) { + subdoc = new this.caster(priorVal.toObject(), doc ? doc.$__.selected : void 0, doc); + } else { + subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); + } -
    Kitten.find().batchSize(100)

    Query#comment(val)

    Specifies the comment option.

    Parameters:

    Example

    + subdoc.set(val, undefined, false); + } -
    Kitten.findOne(condition).comment('login query')

    Query#snapshot()

    Specifies this query as a snapshot query.

    show code
    Query.prototype.snapshot = function () {
    -  this.options.snapshot = true;
    -  return this;
    -};

    Returns:

    Example

    + return subdoc; +};

    Embedded#castForQuery([$conditional], value)

    Casts contents for query

    Parameters:

    • [$conditional] <string> optional query operator (like $eq or $in)
    • value <T>
    show code
    Embedded.prototype.castForQuery = function($conditional, val) {
    +  var handler;
    +  if (arguments.length === 2) {
    +    handler = this.$conditionalHandlers[$conditional];
    +    if (!handler) {
    +      throw new Error('Can\'t use ' + $conditional);
    +    }
    +    return handler.call(this, val);
    +  }
    +  val = $conditional;
    +  if (val == null) {
    +    return val;
    +  }
     
    -
    Kitten.find().snapshot()

    Query#hint(val)

    Sets query hints.

    show code
    Query.prototype.hint = function (val) {
    -  if (!val) return this;
    +  if (this.options.runSetters) {
    +    val = this._applySetters(val);
    +  }
     
    -  var hint = this.options.hint || (this.options.hint = {});
    +  return new this.caster(val);
    +};

    Embedded#doValidate()

    Async validation on this single nested doc.

    show code
    Embedded.prototype.doValidate = function(value, fn, scope) {
    +  var Constructor = this.caster;
    +  SchemaType.prototype.doValidate.call(this, value, function(error) {
    +    if (error) {
    +      return fn(error);
    +    }
    +    if (!value) {
    +      return fn(null);
    +    }
    +    if (!(value instanceof Constructor)) {
    +      value = new Constructor(value);
    +    }
    +    value.validate({__noPromise: true}, fn);
    +  }, scope);
    +};

    Embedded#doValidateSync()

    Synchronously validate this single nested doc

    show code
    Embedded.prototype.doValidateSync = function(value, scope) {
    +  var schemaTypeError = SchemaType.prototype.doValidateSync.call(this, value, scope);
    +  if (schemaTypeError) {
    +    return schemaTypeError;
    +  }
    +  if (!value) {
    +    return;
    +  }
    +  return value.validateSync();
    +};

    Embedded(schema, key, options)

    Sub-schema schematype constructor

    Parameters:

    Inherits:

    show code
    function Embedded(schema, path, options) {
    +  var _embedded = function SingleNested(value, path, parent) {
    +    var _this = this;
    +    Subdocument.apply(this, arguments);
    +    this.$parent = parent;
    +    if (parent) {
    +      parent.on('save', function() {
    +        _this.emit('save', _this);
    +        _this.constructor.emit('save', _this);
    +      });
     
    -  if ('Object' === val.constructor.name) {
    -    // must keep object keys in order so don't use Object.keys()
    -    for (var k in val) {
    -      hint[k] = val[k];
    +      parent.on('isNew', function(val) {
    +        _this.isNew = val;
    +        _this.emit('isNew', val);
    +        _this.constructor.emit('isNew', val);
    +      });
         }
    -  } else {
    -    throw new TypeError('Invalid hint. ' + val);
    +  };
    +  _embedded.prototype = Object.create(Subdocument.prototype);
    +  _embedded.prototype.$__setSchema(schema);
    +  _embedded.prototype.constructor = _embedded;
    +  _embedded.schema = schema;
    +  _embedded.$isSingleNested = true;
    +  _embedded.prototype.$basePath = path;
    +  _embedded.prototype.toBSON = function() {
    +    return this.toObject({
    +      transform: false,
    +      retainKeyOrder: true,
    +      virtuals: false,
    +      _skipDepopulateTopLevel: true,
    +      depopulate: true,
    +      flattenDecimals: false
    +    });
    +  };
    +
    +  // apply methods
    +  for (var i in schema.methods) {
    +    _embedded.prototype[i] = schema.methods[i];
       }
     
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    - -
    Model.find().hint({ indexA: 1, indexB: -1})

    Query#slaveOk(v)

    Sets the slaveOk option.

    show code
    Query.prototype.slaveOk = function (v) {
    -  this.options.slaveOk = arguments.length ? !!v : true;
    -  return this;
    -}

    Parameters:

    Returns:

    Example:

    + // apply statics + for (i in schema.statics) { + _embedded[i] = schema.statics[i]; + } -
    new Query().slaveOk() // true
    -new Query().slaveOk(true)
    -new Query().slaveOk(false)

    Query#read(pref, [tags])

    Sets the readPreference option for the query.

    show code
    Query.prototype.read = function (pref, tags) {
    -  this.options.readPreference = utils.readPref(pref, tags);
    -  return this;
    -}

    Parameters:

    • pref <String> one of the listed preference options or their aliases
    • [tags] <Array> optional tags for this query

    Returns:

    Example:

    + for (i in EventEmitter.prototype) { + _embedded[i] = EventEmitter.prototype[i]; + } -
    new Query().read('primary')
    -new Query().read('p')  // same as primary
    +  this.caster = _embedded;
    +  this.schema = schema;
    +  this.$isSingleNested = true;
    +  SchemaType.call(this, path, options, 'Embedded');
    +}
     
    -new Query().read('primaryPreferred')
    -new Query().read('pp') // same as primaryPreferred
    +Embedded.prototype = Object.create(SchemaType.prototype);

  • aggregate.js

    Aggregate#addCursorFlag(flag, value)

    Adds a cursor flag

    Parameters:

    Example:

    -new Query().read('secondary') -new Query().read('s') // same as secondary +
    Model.aggregate(..).addCursorFlag('noCursorTimeout', true).exec();
    show code
    Aggregate.prototype.addCursorFlag = function(flag, value) {
    +  if (!this.options) {
    +    this.options = {};
    +  }
    +  this.options[flag] = value;
    +  return this;
    +};

    Aggregate([ops])

    Aggregate constructor used for building aggregation pipelines.

    Parameters:

    • [ops] <Object, Array> aggregation operator(s) or operator array

    Example:

    -new Query().read('secondaryPreferred') -new Query().read('sp') // same as secondaryPreferred +
    new Aggregate();
    +new Aggregate({ $project: { a: 1, b: 1 } });
    +new Aggregate({ $project: { a: 1, b: 1 } }, { $skip: 5 });
    +new Aggregate([{ $project: { a: 1, b: 1 } }, { $skip: 5 }]);
    -new Query().read('nearest') -new Query().read('n') // same as nearest +

    Returned when calling Model.aggregate().

    -// with tags -new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
    +

    Example:

    -

    Preferences:

    +
    Model
    +.aggregate({ $match: { age: { $gte: 21 }}})
    +.unwind('tags')
    +.exec(callback)
    -
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
    -secondary            Read from secondary if available, otherwise error.
    -primaryPreferred     Read from primary if available, otherwise a secondary.
    -secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
    -nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
    +

    Note:

    -

    Aliases

    +
      +
    • The documents returned are plain javascript objects, not mongoose documents (since any shape of document can be returned).
    • +
    • Requires MongoDB >= 2.1
    • +
    • Mongoose does not cast pipeline stages. new Aggregate({ $match: { _id: '00000000000000000000000a' } }); will not work unless _id is a string in the database. Use new Aggregate({ $match: { _id: mongoose.Types.ObjectId('00000000000000000000000a') } }); instead.
    • +
    show code
    function Aggregate() {
    +  this._pipeline = [];
    +  this._model = undefined;
    +  this.options = {};
     
    -
    p   primary
    -pp  primaryPreferred
    -s   secondary
    -sp  secondaryPreferred
    -n   nearest
    + if (arguments.length === 1 && util.isArray(arguments[0])) { + this.append.apply(this, arguments[0]); + } else { + this.append.apply(this, arguments); + } +}

    Aggregate#allowDiskUse(value, [tags])

    Sets the allowDiskUse option for the aggregation query (ignored for < 2.6.0)

    Parameters:

    • value <Boolean> Should tell server it can use hard drive to store data during aggregation.
    • [tags] <Array> optional tags for this query

    Example:

    -

    Read more about how to use read preferrences here and here.


    Query#lean(v)

    Sets the lean option.

    show code
    Query.prototype.lean = function (v) {
    -  this.options.lean = arguments.length ? !!v : true;
    +
    Model.aggregate(..).allowDiskUse(true).exec(callback)
    show code
    Aggregate.prototype.allowDiskUse = function(value) {
    +  if (!this.options) {
    +    this.options = {};
    +  }
    +  this.options.allowDiskUse = value;
       return this;
    -}

    Parameters:

    Returns:

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    +};

    Aggregate#append(ops)

    Appends new operators to this aggregate pipeline

    Parameters:

    • ops <Object> operator(s) to append

    Returns:

    Examples:

    -

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    +
    aggregate.append({ $project: { field: 1 }}, { $limit: 2 });
     
    -

    Example:

    +// or pass an array +var pipeline = [{ $match: { daw: 'Logic Audio X' }} ]; +aggregate.append(pipeline);
    show code
    Aggregate.prototype.append = function() {
    +  var args = (arguments.length === 1 && util.isArray(arguments[0]))
    +      ? arguments[0]
    +      : utils.args(arguments);
     
    -
    new Query().lean() // true
    -new Query().lean(true)
    -new Query().lean(false)
    +  if (!args.every(isOperator)) {
    +    throw new Error('Arguments must be aggregate pipeline operators');
    +  }
     
    -Model.find().lean().exec();
    +  this._pipeline = this._pipeline.concat(args);
     
    -var leanStream = Model.find().lean().stream();

    Query#tailable(v)

    Sets tailable option.

    show code
    Query.prototype.tailable = function (v) {
    -  this.options.tailable = arguments.length ? !!v : true;
       return this;
    -};

    Parameters:

    Example

    +};

    Aggregate#collation(collation, value)

    Adds a collation

    Parameters:

    Example:

    -
    Kitten.find().tailable() &lt;== true
    -Kitten.find().tailable(true)
    -Kitten.find().tailable(false)

    Query#execFind(callback)

    Executes the query as a find() operation.

    show code
    Query.prototype.execFind = function (callback) {
    -  var model = this.model
    -    , promise = new Promise(callback);
    +
    Model.aggregate(..).collation({ locale: 'en_US', strength: 1 }).exec();
    show code
    Aggregate.prototype.collation = function(collation) {
    +  if (!this.options) {
    +    this.options = {};
    +  }
    +  this.options.collation = collation;
    +  return this;
    +};

    Aggregate#cursor(options, options.batchSize, [options.useMongooseAggCursor])

    Sets the cursor option option for the aggregation query (ignored for < 2.6.0).
    Note the different syntax below: .exec() returns a cursor object, and no callback
    is necessary.

    Parameters:

    • options <Object>
    • options.batchSize <Number> set the cursor batch size
    • [options.useMongooseAggCursor] <Boolean> use experimental mongoose-specific aggregation cursor (for eachAsync() and other query cursor semantics)

    Example:

    - try { - this.cast(model); - } catch (err) { - promise.error(err); - return this; +
    var cursor = Model.aggregate(..).cursor({ batchSize: 1000 }).exec();
    +cursor.each(function(error, doc) {
    +  // use doc
    +});
    show code
    Aggregate.prototype.cursor = function(options) {
    +  if (!this.options) {
    +    this.options = {};
    +  }
    +  this.options.cursor = options || {};
    +  return this;
    +};

    Aggregate#exec([callback])

    Executes the aggregate pipeline on the currently bound Model.

    Parameters:

    Returns:

    Example:

    + +
    aggregate.exec(callback);
    +
    +// Because a promise is returned, the `callback` is optional.
    +var promise = aggregate.exec();
    +promise.then(..);
    show code
    Aggregate.prototype.exec = function(callback) {
    +  if (!this._model) {
    +    throw new Error('Aggregate not bound to any Model');
    +  }
    +  var _this = this;
    +  var Promise = PromiseProvider.get();
    +  var options = utils.clone(this.options);
    +
    +  if (options && options.cursor) {
    +    if (options.cursor.async) {
    +      delete options.cursor.async;
    +      return new Promise.ES6(function(resolve) {
    +        if (!_this._model.collection.buffer) {
    +          process.nextTick(function() {
    +            var cursor = _this._model.collection.
    +              aggregate(_this._pipeline, options || {});
    +            decorateCursor(cursor);
    +            resolve(cursor);
    +            callback && callback(null, cursor);
    +          });
    +          return;
    +        }
    +        _this._model.collection.emitter.once('queue', function() {
    +          var cursor = _this._model.collection.
    +            aggregate(_this._pipeline, options || {});
    +          decorateCursor(cursor);
    +          resolve(cursor);
    +          callback && callback(null, cursor);
    +        });
    +      });
    +    } else if (options.cursor.useMongooseAggCursor) {
    +      delete options.cursor.useMongooseAggCursor;
    +      return new AggregationCursor(this);
    +    }
    +    var cursor = this._model.collection.
    +      aggregate(this._pipeline, this.options || {});
    +    decorateCursor(cursor);
    +    return cursor;
       }
     
    -  // apply default schematype path selections
    -  this._applyPaths();
    +  return new Promise.ES6(function(resolve, reject) {
    +    if (!_this._pipeline.length) {
    +      var err = new Error('Aggregate has empty pipeline');
    +      if (callback) {
    +        callback(err);
    +      }
    +      reject(err);
    +      return;
    +    }
     
    -  var self = this
    -    , castQuery = this._conditions
    -    , options = this._optionsForExec(model)
    -    , fields = utils.clone(this._fields)
    +    prepareDiscriminatorPipeline(_this);
     
    -  options.fields = this._castFields(fields);
    -  if (options.fields instanceof Error) {
    -    promise.error(options.fields);
    -    return this;
    -  }
    +    _this._model
    +        .collection
    +        .aggregate(_this._pipeline, _this.options || {}, function(error, result) {
    +          if (error) {
    +            if (callback) {
    +              callback(error);
    +            }
    +            reject(error);
    +            return;
    +          }
     
    -  model.collection.find(castQuery, options, function (err, cursor) {
    -    if (err) return promise.error(err);
    -    cursor.toArray(tick(cb));
    +          if (callback) {
    +            callback(null, result);
    +          }
    +          resolve(result);
    +        });
       });
    +};

    Aggregate#explain(callback)

    Execute the aggregation with explain

    Parameters:

    Returns:

    Example:

    + +
    Model.aggregate(..).explain(callback)
    show code
    Aggregate.prototype.explain = function(callback) {
    +  var _this = this;
    +  var Promise = PromiseProvider.get();
    +  return new Promise.ES6(function(resolve, reject) {
    +    if (!_this._pipeline.length) {
    +      var err = new Error('Aggregate has empty pipeline');
    +      if (callback) {
    +        callback(err);
    +      }
    +      reject(err);
    +      return;
    +    }
     
    -  function cb (err, docs) {
    -    if (err) return promise.error(err);
    -
    -    if (true === options.lean)
    -      return promise.complete(docs);
    -
    -    var arr = []
    -      , count = docs.length;
    +    prepareDiscriminatorPipeline(_this);
     
    -    if (!count) return promise.complete([]);
    +    _this._model
    +        .collection
    +        .aggregate(_this._pipeline, _this.options || {})
    +        .explain(function(error, result) {
    +          if (error) {
    +            if (callback) {
    +              callback(error);
    +            }
    +            reject(error);
    +            return;
    +          }
     
    -    for (var i = 0, l = docs.length; i < l; i++) {
    -      arr[i] = new model(undefined, fields, true);
    -      arr[i].init(docs[i], self, function (err) {
    -        if (err) return promise.error(err);
    -        --count || promise.complete(arr);
    -      });
    -    }
    -  }
    +          if (callback) {
    +            callback(null, result);
    +          }
    +          resolve(result);
    +        });
    +  });
    +};

    Aggregate#facet(facet)

    Combines multiple aggregation pipelines.

    Parameters:

    Returns:

    See:

    Example:

    - return this; -};

    Parameters:

    Returns:


    Query#findOne(callback)

    Executes the query as a findOne() operation.

    show code
    Query.prototype.findOne = function (callback) {
    -  this.op = 'findOne';
    +
    Model.aggregate(...)
    + .facet({
    +   books: [{ groupBy: '$author' }],
    +   price: [{ $bucketAuto: { groupBy: '$price', buckets: 2 } }]
    + })
    + .exec();
     
    -  if (!callback) return this;
    +// Output: { books: [...], price: [{...}, {...}] }
    show code
    Aggregate.prototype.facet = function(options) {
    +  return this.append({$facet: options});
    +};

    Aggregate#graphLookup(options)

    Appends new custom $graphLookup operator(s) to this aggregate pipeline, performing a recursive search on a collection.

    Parameters:

    • options <Object> to $graphLookup as described in the above link

    Returns:

    Note that graphLookup can only consume at most 100MB of memory, and does not allow disk use even if { allowDiskUse: true } is specified.

    - var model = this.model; - var promise = new Promise(callback); +

    Examples:

    - try { - this.cast(model); - } catch (err) { - promise.error(err); - return this; - } +
    // Suppose we have a collection of courses, where a document might look like `{ _id: 0, name: 'Calculus', prerequisite: 'Trigonometry'}` and `{ _id: 0, name: 'Trigonometry', prerequisite: 'Algebra' }`
    + aggregate.graphLookup({ from: 'courses', startWith: '$prerequisite', connectFromField: 'prerequisite', connectToField: 'name', as: 'prerequisites', maxDepth: 3 }) // this will recursively search the 'courses' collection up to 3 prerequisites
    show code
    Aggregate.prototype.graphLookup = function(options) {
    +  var cloneOptions = {};
    +  if (options) {
    +    if (!utils.isObject(options)) {
    +      throw new TypeError('Invalid graphLookup() argument. Must be an object.');
    +    }
     
    -  // apply default schematype path selections
    -  this._applyPaths();
    +    utils.mergeClone(cloneOptions, options);
    +    var startWith = cloneOptions.startWith;
     
    -  var self = this
    -    , castQuery = this._conditions
    -    , options = this._optionsForExec(model)
    -    , fields = utils.clone(this._fields)
    +    if (startWith && typeof startWith === 'string') {
    +      cloneOptions.startWith = cloneOptions.startWith.charAt(0) === '$' ?
    +        cloneOptions.startWith :
    +        '$' + cloneOptions.startWith;
    +    }
     
    -  options.fields = this._castFields(fields);
    -  if (options.fields instanceof Error) {
    -    promise.error(options.fields);
    -    return this;
       }
    +  return this.append({ $graphLookup: cloneOptions });
    +};

    Aggregate#group(arg)

    Appends a new custom $group operator to this aggregate pipeline.

    Parameters:

    • arg <Object> $group operator contents

    Returns:

    See:

    Examples:

    - model.collection.findOne(castQuery, options, tick(function (err, doc) { - if (err) return promise.error(err); - if (!doc) return promise.complete(null); +
    aggregate.group({ _id: "$department" });

    isOperator(obj)

    Checks whether an object is likely a pipeline operator

    Parameters:

    Returns:

    show code
    function isOperator(obj) {
    +  var k;
     
    -    if (true === options.lean) return promise.complete(doc);
    +  if (typeof obj !== 'object') {
    +    return false;
    +  }
     
    -    var casted = new model(undefined, fields, true);
    -    casted.init(doc, self, function (err) {
    -      if (err) return promise.error(err);
    -      promise.complete(casted);
    -    });
    -  }));
    +  k = Object.keys(obj);
     
    -  return this;
    -};

    Parameters:

    Returns:

    Example

    + return k.length === 1 && k + .some(function(key) { + return key[0] === '$'; + }); +}

    Aggregate#limit(num)

    Appends a new $limit operator to this aggregate pipeline.

    Parameters:

    • num <Number> maximum number of records to pass to the next stage

    Returns:

    See:

    Examples:

    -
    Kitten.where('color', 'white').findOne(function (err, kitten) {
    -  if (err) return handleError(err);
    +
    aggregate.limit(10);

    Aggregate#lookup(options)

    Appends new custom $lookup operator(s) to this aggregate pipeline.

    Parameters:

    • options <Object> to $lookup as described in the above link

    Returns:

    Examples:

    - // kitten may be null if no document matched - if (kitten) { - ... - } -})

    Query#count(callback)

    Exectues the query as a count() operation.

    show code
    Query.prototype.count = function (callback) {
    -  this.op = 'count';
    -  var model = this.model;
    +
    aggregate.lookup({ from: 'users', localField: 'userId', foreignField: '_id', as: 'users' });
    show code
    Aggregate.prototype.lookup = function(options) {
    +  return this.append({$lookup: options});
    +};

    Aggregate#match(arg)

    Appends a new custom $match operator to this aggregate pipeline.

    Parameters:

    • arg <Object> $match operator contents

    Returns:

    See:

    Examples:

    - try { - this.cast(model); - } catch (err) { - return callback(err); +
    aggregate.match({ department: { $in: [ "sales", "engineering" ] } });

    Aggregate#model(model)

    Binds this aggregate to a model.

    Parameters:

    • model <Model> the model to which the aggregate is to be bound

    Returns:

    show code
    Aggregate.prototype.model = function(model) {
    +  this._model = model;
    +  if (this.options.readPreference == null &&
    +      model.schema &&
    +      model.schema.options.read != null) {
    +    this.options.readPreference = model.schema.options.read;
       }
    +  return this;
    +};

    Aggregate#near(parameters)

    Appends a new $geoNear operator to this aggregate pipeline.

    Parameters:

    Returns:

    NOTE:

    - var castQuery = this._conditions; - model.collection.count(castQuery, tick(callback)); +

    MUST be used as the first operator in the pipeline.

    - return this; -};

    Parameters:

    Returns:

    Example

    +

    Examples:

    -
    Kitten.where('color', 'black').count(function (err, count) {
    -  if (err) return handleError(err);
    -  console.log('there are %d black kittens', count);
    -})

    Query#distinct(field, callback)

    Executes this query as a distinct() operation.

    show code
    Query.prototype.distinct = function (field, callback) {
    -  this.op = 'distinct';
    -  var model = this.model;
    +
    aggregate.near({
    +  near: [40.724, -73.997],
    +  distanceField: "dist.calculated", // required
    +  maxDistance: 0.008,
    +  query: { type: "public" },
    +  includeLocs: "dist.location",
    +  uniqueDocs: true,
    +  num: 5
    +});

    Aggregate#project(arg)

    Appends a new $project operator to this aggregate pipeline.

    Parameters:

    Returns:

    Mongoose query selection syntax is also supported.

    - try { - this.cast(model); - } catch (err) { - return callback(err); - } +

    Examples:

    - var castQuery = this._conditions; - model.collection.distinct(field, castQuery, tick(callback)); +
    // include a, include b, exclude _id
    +aggregate.project("a b -_id");
     
    -  return this;
    -};

    Parameters:

    Returns:


    Query#update(doc, callback)

    Executes this query as an update() operation.

    show code
    Query.prototype.update = function update (doc, callback) {
    -  this.op = 'update';
    -  this._updateArg = doc;
    -
    -  var model = this.model
    -    , options = this._optionsForExec(model)
    -    , fn = 'function' == typeof callback
    -    , castedQuery
    -    , castedDoc
    -
    -  castedQuery = castQuery(this);
    -  if (castedQuery instanceof Error) {
    -    if (fn) {
    -      process.nextTick(callback.bind(null, castedQuery));
    -      return this;
    +// or you may use object notation, useful when
    +// you have keys already prefixed with a "-"
    +aggregate.project({a: 1, b: 1, _id: 0});
    +
    +// reshaping documents
    +aggregate.project({
    +    newField: '$b.nested'
    +  , plusTen: { $add: ['$val', 10]}
    +  , sub: {
    +       name: '$a'
         }
    -    throw castedQuery;
    -  }
    +})
     
    -  castedDoc = castDoc(this);
    -  if (!castedDoc) {
    -    fn && process.nextTick(callback.bind(null, null, 0));
    -    return this;
    -  }
    +// etc
    +aggregate.project({ salary_k: { $divide: [ "$salary", 1000 ] } });
    show code
    Aggregate.prototype.project = function(arg) {
    +  var fields = {};
     
    -  if (castedDoc instanceof Error) {
    -    if (fn) {
    -      process.nextTick(callback.bind(null, castedDoc));
    -      return this;
    -    }
    -    throw castedDoc;
    +  if (typeof arg === 'object' && !util.isArray(arg)) {
    +    Object.keys(arg).forEach(function(field) {
    +      fields[field] = arg[field];
    +    });
    +  } else if (arguments.length === 1 && typeof arg === 'string') {
    +    arg.split(/\s+/).forEach(function(field) {
    +      if (!field) {
    +        return;
    +      }
    +      var include = field[0] === '-' ? 0 : 1;
    +      if (include === 0) {
    +        field = field.substring(1);
    +      }
    +      fields[field] = include;
    +    });
    +  } else {
    +    throw new Error('Invalid project() argument. Must be string or object');
       }
     
    -  if (!fn) {
    -    delete options.safe;
    -  }
    +  return this.append({$project: fields});
    +};

    Aggregate#read(pref, [tags])

    Sets the readPreference option for the aggregation query.

    Parameters:

    • pref <String> one of the listed preference options or their aliases
    • [tags] <Array> optional tags for this query

    Example:

    - model.collection.update(castedQuery, castedDoc, options, tick(callback)); +
    Model.aggregate(..).read('primaryPreferred').exec(callback)
    show code
    Aggregate.prototype.read = function(pref, tags) {
    +  if (!this.options) {
    +    this.options = {};
    +  }
    +  read.call(this, pref, tags);
       return this;
    -};

    Parameters:

    Returns:

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    - -

    Example

    - -
    Model.update({..}, { title: 'remove words' }, ...)
    +};

    Aggregate#sample(size)

    Appepnds new custom $sample operator(s) to this aggregate pipeline.

    Parameters:

    • size <Number> number of random documents to pick

    Returns:

    Examples:

    -

    becomes

    +
    aggregate.sample(3); // Add a pipeline that picks 3 random documents
    show code
    Aggregate.prototype.sample = function(size) {
    +  return this.append({$sample: {size: size}});
    +};

    Aggregate#skip(num)

    Appends a new $skip operator to this aggregate pipeline.

    Parameters:

    • num <Number> number of records to skip before next stage

    Returns:

    See:

    Examples:

    -
    Model.update({..}, { $set: { title: 'remove words' }}, ...)
    +
    aggregate.skip(10);

    Aggregate#sort(arg)

    Appends a new $sort operator to this aggregate pipeline.

    Parameters:

    Returns:

    See:

    If an object is passed, values allowed are asc, desc, ascending, descending, 1, and -1.

    -

    Note

    +

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    -

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


    Query#_castUpdate(obj)

    Casts obj for an update command.

    show code
    Query.prototype._castUpdate = function _castUpdate (obj) {
    -  var ops = Object.keys(obj)
    -    , i = ops.length
    -    , ret = {}
    -    , hasKeys
    -    , val
    +

    Examples:

    - while (i--) { - var op = ops[i]; - if ('$' !== op[0]) { - // fix up $set sugar - if (!ret.$set) { - if (obj.$set) { - ret.$set = obj.$set; - } else { - ret.$set = {}; - } +
    // these are equivalent
    +aggregate.sort({ field: 'asc', test: -1 });
    +aggregate.sort('field -test');
    show code
    Aggregate.prototype.sort = function(arg) {
    +  // TODO refactor to reuse the query builder logic
    +
    +  var sort = {};
    +
    +  if (arg.constructor.name === 'Object') {
    +    var desc = ['desc', 'descending', -1];
    +    Object.keys(arg).forEach(function(field) {
    +      // If sorting by text score, skip coercing into 1/-1
    +      if (arg[field] instanceof Object && arg[field].$meta) {
    +        sort[field] = arg[field];
    +        return;
           }
    -      ret.$set[op] = obj[op];
    -      ops.splice(i, 1);
    -      if (!~ops.indexOf('$set')) ops.push('$set');
    -    } else if ('$set' === op) {
    -      if (!ret.$set) {
    -        ret[op] = obj[op];
    +      sort[field] = desc.indexOf(arg[field]) === -1 ? 1 : -1;
    +    });
    +  } else if (arguments.length === 1 && typeof arg === 'string') {
    +    arg.split(/\s+/).forEach(function(field) {
    +      if (!field) {
    +        return;
           }
    -    } else {
    -      ret[op] = obj[op];
    -    }
    +      var ascend = field[0] === '-' ? -1 : 1;
    +      if (ascend === -1) {
    +        field = field.substring(1);
    +      }
    +      sort[field] = ascend;
    +    });
    +  } else {
    +    throw new TypeError('Invalid sort() argument. Must be a string or object.');
       }
     
    -  // cast each value
    -  i = ops.length;
    +  return this.append({$sort: sort});
    +};

    Aggregate#then([resolve], [reject])

    Provides promise for aggregate.

    Parameters:

    Returns:

    Example:

    - while (i--) { - op = ops[i]; - val = ret[op]; - if ('Object' === val.constructor.name) { - hasKeys |= this._walkUpdatePath(val, op); - } else { - var msg = 'Invalid atomic update value for ' + op + '. ' - + 'Expected an object, received ' + typeof val; - throw new Error(msg); - } - } - - return hasKeys && ret; -}

    Parameters:

    Returns:

    • <Object> obj after casting its values

    Query#_walkUpdatePath(obj, op, pref)

    Walk each path of obj and cast its values
    according to its schema.

    show code
    Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
    -  var strict = this.model.schema.options.strict
    -    , prefix = pref ? pref + '.' : ''
    -    , keys = Object.keys(obj)
    -    , i = keys.length
    -    , hasKeys = false
    -    , schema
    -    , key
    -    , val
    +
    Model.aggregate(..).then(successCallback, errorCallback);
    show code
    Aggregate.prototype.then = function(resolve, reject) {
    +  return this.exec().then(resolve, reject);
    +};

    Aggregate#unwind(fields)

    Appends new custom $unwind operator(s) to this aggregate pipeline.

    Parameters:

    • fields <String> the field(s) to unwind

    Returns:

    Note that the $unwind operator requires the path name to start with '$'.
    Mongoose will prepend '$' if the specified field doesn't start '$'.

    - while (i--) { - key = keys[i]; - val = obj[key]; - - if (val && 'Object' === val.constructor.name) { - // watch for embedded doc schemas - schema = this._getSchema(prefix + key); - if (schema && schema.caster && op in castOps) { - // embedded doc schema - - if (strict && !schema) { - // path is not in our strict schema - if ('throw' == strict) { - throw new Error('Field `' + key + '` is not in schema.'); - } else { - // ignore paths not specified in schema - delete obj[key]; - } - } else { - hasKeys = true; - if ('$each' in val) { - obj[key] = { - $each: this._castUpdateVal(schema, val.$each, op) - } - } else { - obj[key] = this._castUpdateVal(schema, val, op); - } - } - } else { - hasKeys |= this._walkUpdatePath(val, op, prefix + key); - } - } else { - schema = '$each' === key - ? this._getSchema(pref) - : this._getSchema(prefix + key); +

    Examples:

    - var skip = strict && - !schema && - !/real|nested/.test(this.model.schema.pathType(prefix + key)); +
    aggregate.unwind("tags");
    +aggregate.unwind("a", "b", "c");
    show code
    Aggregate.prototype.unwind = function() {
    +  var args = utils.args(arguments);
     
    -      if (skip) {
    -        if ('throw' == strict) {
    -          throw new Error('Field `' + prefix + key + '` is not in schema.');
    -        } else {
    -          delete obj[key];
    -        }
    -      } else {
    -        hasKeys = true;
    -        obj[key] = this._castUpdateVal(schema, val, op, key);
    -      }
    +  var res = [];
    +  for (var i = 0; i < args.length; ++i) {
    +    var arg = args[i];
    +    if (arg && typeof arg === 'object') {
    +      res.push({ $unwind: arg });
    +    } else if (typeof arg === 'string') {
    +      res.push({
    +        $unwind: (arg && arg.charAt(0) === '$') ? arg : '$' + arg
    +      });
    +    } else {
    +      throw new Error('Invalid arg "' + arg + '" to unwind(), ' +
    +        'must be string or object');
         }
       }
    -  return hasKeys;
    -}

    Parameters:

    • obj <Object> - part of a query
    • op <String> - the atomic operator ($pull, $set, etc)
    • pref <String> - path prefix (internal only)

    Returns:

    • <Bool> true if this path has keys to update

    Query#_castUpdateVal(schema, val, op, [$conditional])

    Casts val according to schema and atomic op.

    show code
    Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
    -  if (!schema) {
    -    // non-existing schema path
    -    return op in numberOps
    -      ? Number(val)
    -      : val
    -  }
     
    -  if (schema.caster && op in castOps &&
    -    ('Object' === val.constructor.name || Array.isArray(val))) {
    -    // Cast values for ops that add data to MongoDB.
    -    // Ensures embedded documents get ObjectIds etc.
    -    var tmp = schema.cast(val);
    +  return this.append.apply(this, res);
    +};

  • document_provider.web.js

    module.exports()

    Returns the Document constructor for the current context

    show code
    module.exports = function() {
    +  return BrowserDocument;
    +};

  • schematype.js

    SchemaType#applyGetters(value, scope)

    Applies getters to a value

    Parameters:

    show code
    SchemaType.prototype.applyGetters = function(value, scope) {
    +  var v = value,
    +      getters = this.getters,
    +      len = getters.length;
     
    -    if (Array.isArray(val)) {
    -      val = tmp;
    -    } else {
    -      val = tmp[0];
    -    }
    +  if (!len) {
    +    return v;
       }
     
    -  if (op in numberOps) return Number(val);
    -  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
    -  return schema.castForQuery(val)
    -}

    Parameters:


    Query#_getSchema(path)

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    show code
    Query.prototype._getSchema = function _getSchema (path) {
    -  var schema = this.model.schema
    -    , pathschema = schema.path(path);
    -
    -  if (pathschema)
    -    return pathschema;
    +  while (len--) {
    +    v = getters[len].call(scope, v, this);
    +  }
     
    -  // look for arrays
    -  return (function search (parts, schema) {
    -    var p = parts.length + 1
    -      , foundschema
    -      , trypath
    +  return v;
    +};

    SchemaType#applySetters(value, scope, init)

    Applies setters

    Parameters:

    show code
    SchemaType.prototype.applySetters = function(value, scope, init, priorVal, options) {
    +  var v = this._applySetters(value, scope, init, priorVal, options);
     
    -    while (p--) {
    -      trypath = parts.slice(0, p).join('.');
    -      foundschema = schema.path(trypath);
    -      if (foundschema) {
    -        if (foundschema.caster) {
    +  if (v == null) {
    +    return v;
    +  }
     
    -          // array of Mixed?
    -          if (foundschema.caster instanceof Types.Mixed) {
    -            return foundschema.caster;
    -          }
    +  // do not cast until all setters are applied #665
    +  v = this.cast(v, scope, init, priorVal, options);
     
    -          // Now that we found the array, we need to check if there
    -          // are remaining document paths to look up for casting.
    -          // Also we need to handle array.$.path since schema.path
    -          // doesn't work for that.
    -          if (p !== parts.length) {
    -            if ('$' === parts[p]) {
    -              // comments.$.comments.$.title
    -              return search(parts.slice(p+1), foundschema.schema);
    -            } else {
    -              // this is the last path of the selector
    -              return search(parts.slice(p), foundschema.schema);
    -            }
    -          }
    -        }
    -        return foundschema;
    -      }
    +  return v;
    +};

    SchemaType#castForQuery([$conditional], val)

    Cast the given value with the given optional query operator.

    Parameters:

    • [$conditional] <String> query operator, like $eq or $in
    • val <T>
    show code
    SchemaType.prototype.castForQuery = function($conditional, val) {
    +  var handler;
    +  if (arguments.length === 2) {
    +    handler = this.$conditionalHandlers[$conditional];
    +    if (!handler) {
    +      throw new Error('Can\'t use ' + $conditional);
         }
    -  })(path.split('.'), schema)
    -}

    Parameters:


    Query#_castFields(fields)

    Casts selected field arguments for field selection with mongo 2.2

    show code
    Query.prototype._castFields = function _castFields (fields) {
    -  var selected
    -    , elemMatchKeys
    -    , keys
    -    , key
    -    , out
    -    , i
    +    return handler.call(this, val);
    +  }
    +  val = $conditional;
    +  return this._castForQuery(val);
    +};

    SchemaType#checkRequired(val)

    Default check for if this path satisfies the required validator.

    Parameters:

    • val <T>
    show code
    SchemaType.prototype.checkRequired = function(val) {
    +  return val != null;
    +};

    SchemaType#default(val)

    Sets a default value for this SchemaType.

    Parameters:

    Returns:

    Example:

    - if (fields) { - keys = Object.keys(fields); - elemMatchKeys = []; - i = keys.length; +
    var schema = new Schema({ n: { type: Number, default: 10 })
    +var M = db.model('M', schema)
    +var m = new M;
    +console.log(m.n) // 10
    - // collect $elemMatch args - while (i--) { - key = keys[i]; - if (fields[key].$elemMatch) { - selected || (selected = {}); - selected[key] = fields[key]; - elemMatchKeys.push(key); - } - } - } +

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    - if (selected) { - // they passed $elemMatch, cast em - try { - out = this.cast(this.model, selected); - } catch (err) { - return err; - } +

    Example:

    - // apply the casted field args - i = elemMatchKeys.length; - while (i--) { - key = elemMatchKeys[i]; - fields[key] = out[key]; +
    // values are cast:
    +var schema = new Schema({ aNumber: { type: Number, default: 4.815162342 }})
    +var M = db.model('M', schema)
    +var m = new M;
    +console.log(m.aNumber) // 4.815162342
    +
    +// default unique objects for Mixed types:
    +var schema = new Schema({ mixed: Schema.Types.Mixed });
    +schema.path('mixed').default(function () {
    +  return {};
    +});
    +
    +// if we don't use a function to return object literals for Mixed defaults,
    +// each document will receive a reference to the same object literal creating
    +// a "shared" object instance:
    +var schema = new Schema({ mixed: Schema.Types.Mixed });
    +schema.path('mixed').default({});
    +var M = db.model('M', schema);
    +var m1 = new M;
    +m1.mixed.added = 1;
    +console.log(m1.mixed); // { added: 1 }
    +var m2 = new M;
    +console.log(m2.mixed); // { added: 1 }
    show code
    SchemaType.prototype.default = function(val) {
    +  if (arguments.length === 1) {
    +    if (val === void 0) {
    +      this.defaultValue = void 0;
    +      return void 0;
         }
    +    this.defaultValue = val;
    +    return this.defaultValue;
    +  } else if (arguments.length > 1) {
    +    this.defaultValue = utils.args(arguments);
       }
    +  return this.defaultValue;
    +};

    SchemaType#doValidate(value, callback, scope)

    Performs a validation of value using the validators declared for this SchemaType.

    Parameters:

    show code
    SchemaType.prototype.doValidate = function(value, fn, scope) {
    +  var err = false;
    +  var path = this.path;
    +  var count = this.validators.length;
     
    -  return fields;
    -}

    Parameters:

    query.select({ ids: { $elemMatch: { $in: [hexString] }})

    Query#remove(callback)

    Executes this query as a remove() operation.

    show code
    Query.prototype.remove = function (callback) {
    -  this.op = 'remove';
    -
    -  var model = this.model
    -    , options = this._optionsForExec(model)
    -    , cb = 'function' == typeof callback
    -
    -  try {
    -    this.cast(model);
    -  } catch (err) {
    -    if (cb) return callback(err);
    -    throw err;
    +  if (!count) {
    +    return fn(null);
       }
     
    -  if (!cb) {
    -    delete options.safe;
    -  }
    +  var validate = function(ok, validatorProperties) {
    +    if (err) {
    +      return;
    +    }
    +    if (ok === undefined || ok) {
    +      --count || fn(null);
    +    } else {
    +      var ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
    +      err = new ErrorConstructor(validatorProperties);
    +      err.$isValidatorError = true;
    +      fn(err);
    +    }
    +  };
     
    -  var castQuery = this._conditions;
    -  model.collection.remove(castQuery, options, tick(callback));
    -  return this;
    -};

    Parameters:

    Example

    + var _this = this; + this.validators.forEach(function(v) { + if (err) { + return; + } -
    Cassette.where('artist').equals('Anne Murray').remove(callback)

    Query#findOneAndUpdate([query], [doc], [options], [callback])

    Issues a mongodb findAndModify update command.

    show code
    Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
    -  this.op = 'findOneAndUpdate';
    +    var validator = v.validator;
    +    var ok;
     
    -  switch (arguments.length) {
    -    case 3:
    -      if ('function' == typeof options)
    -        callback = options, options = {};
    -      break;
    -    case 2:
    -      if ('function' == typeof doc) {
    -        callback = doc;
    -        doc = query;
    -        query = undefined;
    +    var validatorProperties = utils.clone(v);
    +    validatorProperties.path = path;
    +    validatorProperties.value = value;
    +
    +    if (validator instanceof RegExp) {
    +      validate(validator.test(value), validatorProperties);
    +    } else if (typeof validator === 'function') {
    +      if (value === undefined && validator !== _this.requiredValidator) {
    +        validate(true, validatorProperties);
    +        return;
           }
    -      options = undefined;
    -      break;
    -    case 1:
    -      if ('function' == typeof query) {
    -        callback = query;
    -        query = options = doc = undefined;
    +      if (validatorProperties.isAsync) {
    +        asyncValidate(validator, scope, value, validatorProperties, validate);
    +      } else if (validator.length === 2 && !('isAsync' in validatorProperties)) {
    +        legacyAsyncValidate(validator, scope, value, validatorProperties,
    +          validate);
           } else {
    -        doc = query;
    -        query = options = undefined;
    +        try {
    +          ok = validator.call(scope, value);
    +        } catch (error) {
    +          ok = false;
    +          validatorProperties.reason = error;
    +        }
    +        if (ok && typeof ok.then === 'function') {
    +          ok.then(
    +            function(ok) { validate(ok, validatorProperties); },
    +            function(error) {
    +              validatorProperties.reason = error;
    +              ok = false;
    +              validate(ok, validatorProperties);
    +            });
    +        } else {
    +          validate(ok, validatorProperties);
    +        }
           }
    +    }
    +  });
    +};

    SchemaType#doValidateSync(value, scope)

    Performs a validation of value using the validators declared for this SchemaType.

    Parameters:

    Note:

    + +

    This method ignores the asynchronous validators.

    show code
    SchemaType.prototype.doValidateSync = function(value, scope) {
    +  var err = null,
    +      path = this.path,
    +      count = this.validators.length;
    +
    +  if (!count) {
    +    return null;
       }
     
    -  // apply query
    -  if (query) {
    -    if ('Object' === query.constructor.name) {
    -      merge(this._conditions, query);
    -    } else if (query instanceof Query) {
    -      merge(this._conditions, query._conditions);
    -    } else if (query instanceof Document) {
    -      merge(this._conditions, query.toObject());
    +  var validate = function(ok, validatorProperties) {
    +    if (err) {
    +      return;
         }
    -  }
    +    if (ok !== undefined && !ok) {
    +      var ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
    +      err = new ErrorConstructor(validatorProperties);
    +      err.$isValidatorError = true;
    +    }
    +  };
     
    -  // apply doc
    -  if (doc) {
    -    merge(this._updateArg, doc);
    +  var validators = this.validators;
    +  if (value === void 0) {
    +    if (this.validators.length > 0 && this.validators[0].type === 'required') {
    +      validators = [this.validators[0]];
    +    } else {
    +      return null;
    +    }
       }
     
    -  // apply options
    -  options && this.setOptions(options);
    -
    -  if (!callback) return this;
    +  validators.forEach(function(v) {
    +    if (err) {
    +      return;
    +    }
     
    -  return this._findAndModify('update', callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    + var validator = v.validator; + var validatorProperties = utils.clone(v); + validatorProperties.path = path; + validatorProperties.value = value; + var ok; -

    Available options

    + if (validator instanceof RegExp) { + validate(validator.test(value), validatorProperties); + } else if (typeof validator === 'function') { + // if not async validators + if (validator.length !== 2 && !validatorProperties.isAsync) { + try { + ok = validator.call(scope, value); + } catch (error) { + ok = false; + validatorProperties.reason = error; + } + validate(ok, validatorProperties); + } + } + }); -
      -
    • new: bool - true to return the modified document rather than the original. defaults to true
    • -
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    + return err; +};

    SchemaType#get(fn)

    Adds a getter to this schematype.

    Parameters:

    Returns:

    Example:

    -

    Examples

    +
    function dob (val) {
    +  if (!val) return val;
    +  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
    +}
     
    -
    query.findOneAndUpdate(conditions, update, options, callback) // executes
    -query.findOneAndUpdate(conditions, update, options)  // returns Query
    -query.findOneAndUpdate(conditions, update, callback) // executes
    -query.findOneAndUpdate(conditions, update)           // returns Query
    -query.findOneAndUpdate(callback)                     // executes
    -query.findOneAndUpdate()                             // returns Query

    Query#findOneAndRemove([conditions], [options], [callback])

    Issues a mongodb findAndModify remove command.

    show code
    Query.prototype.findOneAndRemove = function (conditions, options, callback) {
    -  this.op = 'findOneAndRemove';
    +// defining within the schema
    +var s = new Schema({ born: { type: Date, get: dob })
     
    -  if ('function' == typeof options) {
    -    callback = options;
    -    options = undefined;
    -  } else if ('function' == typeof conditions) {
    -    callback = conditions;
    -    conditions = undefined;
    -  }
    +// or by retreiving its SchemaType
    +var s = new Schema({ born: Date })
    +s.path('born').get(dob)
    - // apply conditions - if (conditions) { - if ('Object' === conditions.constructor.name) { - merge(this._conditions, conditions); - } else if (conditions instanceof Query) { - merge(this._conditions, conditions._conditions); - } else if (conditions instanceof Document) { - merge(this._conditions, conditions.toObject()); - } - } +

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    - // apply options - options && this.setOptions(options); +

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    - if (!callback) return this; +
    function obfuscate (cc) {
    +  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
    +}
     
    -  return this._findAndModify('remove', callback);
    -}

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    +var AccountSchema = new Schema({ + creditCardNumber: { type: String, get: obfuscate } +}); -

    Available options

    +var Account = db.model('Account', AccountSchema); -
      -
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • -
    +Account.findById(id, function (err, found) { + console.log(found.creditCardNumber); // '****-****-****-1234' +});
    -

    Examples

    +

    Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.

    -
    A.where().findOneAndRemove(conditions, options, callback) // executes
    -A.where().findOneAndRemove(conditions, options)  // return Query
    -A.where().findOneAndRemove(conditions, callback) // executes
    -A.where().findOneAndRemove(conditions) // returns Query
    -A.where().findOneAndRemove(callback)   // executes
    -A.where().findOneAndRemove()           // returns Query

    Query#_findAndModify(type, callback)

    _findAndModify

    show code
    Query.prototype._findAndModify = function (type, callback) {
    -  var model = this.model
    -    , promise = new Promise(callback)
    -    , self = this
    -    , castedQuery
    -    , castedDoc
    -    , fields
    -    , sort
    -    , opts
    -
    -  castedQuery = castQuery(this);
    -  if (castedQuery instanceof Error) {
    -    process.nextTick(promise.error.bind(promise, castedQuery));
    -    return promise;
    -  }
    -
    -  opts = this._optionsForExec(model);
    -
    -  if ('remove' == type) {
    -    opts.remove = true;
    +
    function inspector (val, schematype) {
    +  if (schematype.options.required) {
    +    return schematype.path + ' is required';
       } else {
    -    if (!('new' in opts)) opts.new = true;
    -    if (!('upsert' in opts)) opts.upsert = false;
    -
    -    castedDoc = castDoc(this);
    -    if (!castedDoc) {
    -      if (opts.upsert) {
    -        // still need to do the upsert to empty doc
    -        castedDoc = { $set: {} };
    -      } else {
    -        return this.findOne(callback);
    -      }
    -    } else if (castedDoc instanceof Error) {
    -      process.nextTick(promise.error.bind(promise, castedDoc));
    -      return promise;
    -    }
    -  }
    -
    -  this._applyPaths();
    -
    -  if (this._fields) {
    -    fields = utils.clone(this._fields)
    -    opts.fields = this._castFields(fields);
    -    if (opts.fields instanceof Error) {
    -      process.nextTick(promise.error.bind(promise, opts.fields));
    -      return promise;
    -    }
    +    return schematype.path + ' is not';
       }
    +}
     
    -  // the driver needs a default
    -  sort = opts.sort || [];
    +var VirusSchema = new Schema({
    +  name: { type: String, required: true, get: inspector },
    +  taxonomy: { type: String, get: inspector }
    +})
     
    -  model
    -  .collection
    -  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
    -    if (err) return promise.error(err);
    -    if (!doc) return promise.complete(null);
    +var Virus = db.model('Virus', VirusSchema);
     
    -    if (true === opts.lean) {
    -      return promise.complete(doc);
    +Virus.findById(id, function (err, virus) {
    +  console.log(virus.name);     // name is required
    +  console.log(virus.taxonomy); // taxonomy is not
    +})
    show code
    SchemaType.prototype.get = function(fn) {
    +  if (typeof fn !== 'function') {
    +    throw new TypeError('A getter must be a function.');
    +  }
    +  this.getters.push(fn);
    +  return this;
    +};

    SchemaType#getDefault(scope, init)

    Gets the default value

    Parameters:

    • scope <Object> the scope which callback are executed
    • init <Boolean>
    show code
    SchemaType.prototype.getDefault = function(scope, init) {
    +  var ret = typeof this.defaultValue === 'function'
    +      ? this.defaultValue.call(scope)
    +      : this.defaultValue;
    +
    +  if (ret !== null && ret !== undefined) {
    +    if (typeof ret === 'object' && (!this.options || !this.options.shared)) {
    +      ret = utils.clone(ret, { retainKeyOrder: true });
         }
     
    -    var casted = new model(undefined, fields, true);
    -    casted.init(doc, self, function (err) {
    -      if (err) return promise.error(err);
    -      promise.complete(casted);
    -    });
    -  }));
    -
    -  return promise;
    -}

    Parameters:


    Query#populate(path, [fields], [model], [conditions], [options])

    Specifies paths which should be populated with other documents.

    show code
    Query.prototype.populate = function (path, fields, model, conditions, options) {
    -  if ('string' !== typeof model) {
    -    options = conditions;
    -    conditions = model;
    -    model = undefined;
    -  }
    -  // The order of fields/conditions args is opposite Model.find but
    -  // necessary to keep backward compatibility (fields could be
    -  // an array, string, or object literal).
    -  this.options.populate[path] =
    -    new PopulateOptions(fields, conditions, options, model);
    +    var casted = this.cast(ret, scope, init);
    +    if (casted && casted.$isSingleNested) {
    +      casted.$parent = scope;
    +    }
    +    return casted;
    +  }
    +  return ret;
    +};

    SchemaType#index(options)

    Declares the index options for this schematype.

    Parameters:

    Returns:

    Example:

    - return this; -};

    Parameters:

    Returns:

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    +
    var s = new Schema({ name: { type: String, index: true })
    +var s = new Schema({ loc: { type: [Number], index: 'hashed' })
    +var s = new Schema({ loc: { type: [Number], index: '2d', sparse: true })
    +var s = new Schema({ loc: { type: [Number], index: { type: '2dsphere', sparse: true }})
    +var s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
    +Schema.path('my.path').index(true);
    +Schema.path('my.date').index({ expires: 60 });
    +Schema.path('my.path').index({ unique: true, sparse: true });
    -

    Example:

    +

    NOTE:

    -
    Kitten.findOne().populate('owner').exec(function (err, kitten) {
    -  console.log(kitten.owner.name) // Max
    -})

    Query#stream()

    Returns a stream interface

    show code
    Query.prototype.stream = function stream () {
    -  return new QueryStream(this);
    -}
    +

    Indexes are created in the background by default. Specify background: false to override.

    -// helpers

    Returns:

    show code
    SchemaType.prototype.index = function(options) {
    +  this._index = options;
    +  utils.expires(this._index);
    +  return this;
    +};

    SchemaType#required(required, [options.isRequired], [options.ErrorConstructor], [message])

    Adds a required validator to this SchemaType. The validator gets added
    to the front of this SchemaType's validators array using unshift().

    Parameters:

    • required <Boolean, Function, Object> enable/disable the validator, or function that returns required boolean, or options object
    • [options.isRequired] <Boolean, Function> enable/disable the validator, or function that returns required boolean
    • [options.ErrorConstructor] <Function> custom error constructor. The constructor receives 1 parameter, an object containing the validator properties.
    • [message] <String> optional custom error message

    Returns:

    Example:

    -
    // follows the nodejs stream api
    -Thing.find({ name: /^hello/ }).stream().pipe(res)
    +
    var s = new Schema({ born: { type: Date, required: true })
     
    -// manual streaming
    -var stream = Thing.find({ name: /^hello/ }).stream();
    +// or with custom error message
     
    -stream.on('data', function (doc) {
    -  // do something with the mongoose document
    -}).on('error', function (err) {
    -  // handle the error
    -}).on('close', function () {
    -  // the stream is closed
    -});

    Query#within

    Syntax sugar for expressive queries.

    +var s = new Schema({ born: { type: Date, required: '{PATH} is required!' }) -

    Example

    +// or with a function -
    query.within.box()
    -query.within.center()

    Returns:


  • querystream.js

    QueryStream(query)

    Provides a ReadStream interface for Queries.

    show code
    function QueryStream (query) {
    -  Stream.call(this);
    +var s = new Schema({
    +  userId: ObjectId,
    +  username: {
    +    type: String,
    +    required: function() { return this.userId != null; }
    +  }
    +})
     
    -  this.query = query;
    -  this.readable = true;
    -  this.paused = false;
    -  this._cursor = null;
    -  this._destroyed = null;
    -  this._fields = null;
    -  this._buffer = null;
    -  this._inline = T_INIT;
    -  this._running = false;
    +// or with a function and a custom message
    +var s = new Schema({
    +  userId: ObjectId,
    +  username: {
    +    type: String,
    +    required: [
    +      function() { return this.userId != null; },
    +      'username is required if id is specified'
    +    ]
    +  }
    +})
     
    -  // give time to hook up events
    -  var self = this;
    -  process.nextTick(function () {
    -    self._init();
    -  });
    -}

    Parameters:

    Inherits:

    Events:

    • data: emits a single Mongoose document

    • error: emits when an error occurs during streaming. This will emit before the close event.

    • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

    var stream = Model.find().stream();
    +// or through the path API
     
    -stream.on('data', function (doc) {
    -  // do something with the mongoose document
    -}).on('error', function (err) {
    -  // handle the error
    -}).on('close', function () {
    -  // the stream is closed
    -});
    +Schema.path('name').required(true); -

    The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

    +// with custom error messaging -
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

    QueryStream#_init()

    Initializes the query.

    show code
    QueryStream.prototype._init = function () {
    -  if (this._destroyed) return;
    +Schema.path('name').required(true, 'grrr :( ');
     
    -  var query = this.query
    -    , model = query.model
    -    , options = query._optionsForExec(model)
    -    , self = this
    +// or make a path conditionally required based on a function
    +var isOver18 = function() { return this.age &gt;= 18; };
    +Schema.path('voterRegistrationId').required(isOver18);
    - try { - query.cast(model); - } catch (err) { - return self.destroy(err); +

    The required validator uses the SchemaType's checkRequired function to
    determine whether a given value satisfies the required validator. By default,
    a value satisfies the required validator if val != null (that is, if
    the value is not null nor undefined). However, most built-in mongoose schema
    types override the default checkRequired function:

    show code
    SchemaType.prototype.required = function(required, message) {
    +  var customOptions = {};
    +  if (typeof required === 'object') {
    +    customOptions = required;
    +    message = customOptions.message || message;
    +    required = required.isRequired;
       }
     
    -  self._fields = utils.clone(query._fields);
    -  options.fields = query._castFields(self._fields);
    +  if (required === false) {
    +    this.validators = this.validators.filter(function(v) {
    +      return v.validator !== this.requiredValidator;
    +    }, this);
     
    -  model.collection.find(query._conditions, options, function (err, cursor) {
    -    if (err) return self.destroy(err);
    -    self._cursor = cursor;
    -    self._next();
    -  });
    -}

    QueryStream#_next()

    Trampoline for pulling the next doc from cursor.

    show code
    QueryStream.prototype._next = function _next () {
    -  if (this.paused || this._destroyed) {
    -    return this._running = false;
    +    this.isRequired = false;
    +    return this;
       }
     
    -  this._running = true;
    +  var _this = this;
    +  this.isRequired = true;
     
    -  if (this._buffer && this._buffer.length) {
    -    var arg;
    -    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
    -      this._onNextObject.apply(this, arg);
    +  this.requiredValidator = function(v) {
    +    // in here, `this` refers to the validating document.
    +    // no validation when this path wasn't selected in the query.
    +    if ('isSelected' in this && !this.isSelected(_this.path) && !this.isModified(_this.path)) {
    +      return true;
         }
    -  }
     
    -  // avoid stack overflows with large result sets.
    -  // trampoline instead of recursion.
    -  while (this.__next()) {}
    -}

    QueryStream#__next()

    Pulls the next doc from the cursor.

    show code
    QueryStream.prototype.__next = function () {
    -  if (this.paused || this._destroyed)
    -    return this._running = false;
    -
    -  var self = this;
    -  self._inline = T_INIT;
    -
    -  self._cursor.nextObject(function cursorcb (err, doc) {
    -    self._onNextObject(err, doc);
    -  });
    +    return ((typeof required === 'function') && !required.apply(this)) ||
    +        _this.checkRequired(v, this);
    +  };
    +  this.originalRequiredValue = required;
     
    -  // if onNextObject() was already called in this tick
    -  // return ourselves to the trampoline.
    -  if (T_CONT === this._inline) {
    -    return true;
    -  } else {
    -    // onNextObject() hasn't fired yet. tell onNextObject
    -    // that its ok to call _next b/c we are not within
    -    // the trampoline anymore.
    -    this._inline = T_IDLE;
    +  if (typeof required === 'string') {
    +    message = required;
    +    required = undefined;
       }
    -}

    QueryStream#_onNextObject(err, doc)

    Transforms raw docs returned from the cursor into a model instance.

    show code
    QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
    -  if (this._destroyed) return;
     
    -  if (this.paused) {
    -    this._buffer || (this._buffer = []);
    -    this._buffer.push([err, doc]);
    -    return this._running = false;
    -  }
    +  var msg = message || MongooseError.messages.general.required;
    +  this.validators.unshift(utils.assign({}, customOptions, {
    +    validator: this.requiredValidator,
    +    message: msg,
    +    type: 'required'
    +  }));
     
    -  if (err) return this.destroy(err);
    +  return this;
    +};

    SchemaType(path, [options], [instance])

    SchemaType constructor

    Parameters:

    show code
    function SchemaType(path, options, instance) {
    +  this.path = path;
    +  this.instance = instance;
    +  this.validators = [];
    +  this.setters = [];
    +  this.getters = [];
    +  this.options = options;
    +  this._index = null;
    +  this.selected;
     
    -  // when doc is null we hit the end of the cursor
    -  if (!doc) {
    -    this.emit('end');
    -    return this.destroy();
    -  }
    +  for (var i in options) {
    +    if (this[i] && typeof this[i] === 'function') {
    +      // { unique: true, index: true }
    +      if (i === 'index' && this._index) {
    +        continue;
    +      }
     
    -  if (this.query.options && true === this.query.options.lean)  {
    -    this.emit('data', doc);
    +      var opts = Array.isArray(options[i])
    +          ? options[i]
    +          : [options[i]];
     
    -    // trampoline management
    -    if (T_IDLE === this._inline) {
    -      // no longer in trampoline. restart it.
    -      this._next();
    -    } else {
    -      // in a trampoline. tell __next that its
    -      // ok to continue jumping.
    -      this._inline = T_CONT;
    +      this[i].apply(this, opts);
         }
    -    return;
       }
    +}

    SchemaType#select(val)

    Sets default select() behavior for this path.

    Parameters:

    Returns:

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    - var instance = new this.query.model(undefined, this._fields, true); +

    Example:

    - var self = this; - instance.init(doc, this.query, function (err) { - if (err) return self.destroy(err); - self.emit('data', instance); +
    T = db.model('T', new Schema({ x: { type: String, select: true }}));
    +T.find(..); // field x will always be selected ..
    +// .. unless overridden;
    +T.find().select('-x').exec(callback);
    show code
    SchemaType.prototype.select = function select(val) {
    +  this.selected = !!val;
    +  return this;
    +};

    SchemaType#set(fn)

    Adds a setter to this schematype.

    Parameters:

    Returns:

    Example:

    - // trampoline management - if (T_IDLE === self._inline) { - // no longer in trampoline. restart it. - self._next(); - } else - // in a trampoline. tell __next that its - // ok to continue jumping. - self._inline = T_CONT; - }); -}

    Parameters:


    QueryStream#pause()

    Pauses this stream.

    show code
    QueryStream.prototype.pause = function () {
    -  this.paused = true;
    -}

    QueryStream#resume()

    Resumes this stream.

    show code
    QueryStream.prototype.resume = function () {
    -  this.paused = false;
    +
    function capitalize (val) {
    +  if (typeof val !== 'string') val = '';
    +  return val.charAt(0).toUpperCase() + val.substring(1);
    +}
     
    -  if (!this._cursor) {
    -    // cannot start if not initialized
    -    return;
    -  }
    +// defining within the schema
    +var s = new Schema({ name: { type: String, set: capitalize }})
     
    -  // are we within the trampoline?
    -  if (T_INIT === this._inline) {
    -    return;
    -  }
    +// or by retreiving its SchemaType
    +var s = new Schema({ name: String })
    +s.path('name').set(capitalize)
    - if (!this._running) { - // outside QueryStream control, need manual restart - return this._next(); - } -}

    QueryStream#destroy([err])

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    show code
    QueryStream.prototype.destroy = function (err) {
    -  if (this._destroyed) return;
    -  this._destroyed = true;
    -  this._running = false;
    -  this.readable = false;
    +

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    + +

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    + +

    You can set up email lower case normalization easily via a Mongoose setter.

    + +
    function toLower (v) {
    +  return v.toLowerCase();
    +}
     
    -  if (this._cursor) {
    -    this._cursor.close();
    -  }
    +var UserSchema = new Schema({
    +  email: { type: String, set: toLower }
    +})
     
    -  if (err) {
    -    this.emit('error', err);
    -  }
    +var User = db.model('User', UserSchema)
     
    -  this.emit('close');
    -}

    Parameters:


    QueryStream#pipe()

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    See:

    Example:

    +var user = new User({email: 'AVENUE@Q.COM'}) +console.log(user.email); // 'avenue@q.com' -
    query.stream().pipe(writeStream [, options])
    +// or +var user = new User +user.email = 'Avenue@Q.com' +console.log(user.email) // 'avenue@q.com' +
    -

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    +

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    -
    var format = new ArrayFormatter;
    -Events.find().stream().pipe(format).pipe(res);
    +

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    -

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


    QueryStream#paused

    Flag stating whether or not this stream is paused.


    QueryStream#readable

    Flag stating whether or not this stream is readable.


  • schema/array.js

    SchemaArray(key, cast, options)

    Array SchemaType constructor

    show code
    function SchemaArray (key, cast, options) {
    -  if (cast) {
    -    var castOptions = {};
    +
    new Schema({ email: { type: String, lowercase: true }})
    - if ('Object' === cast.constructor.name) { - if (cast.type) { - // support { type: Woot } - castOptions = cast; - cast = cast.type; - delete castOptions.type; - } else { - cast = Mixed; - } - } +

    Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.

    - var caster = cast.name in Types ? Types[cast.name] : cast; - this.casterConstructor = caster; - this.caster = new caster(null, castOptions); +
    function inspector (val, schematype) {
    +  if (schematype.options.required) {
    +    return schematype.path + ' is required';
    +  } else {
    +    return val;
       }
    +}
     
    -  SchemaType.call(this, key, options);
    +var VirusSchema = new Schema({
    +  name: { type: String, required: true, set: inspector },
    +  taxonomy: { type: String, set: inspector }
    +})
     
    -  var self = this
    -    , defaultArr
    -    , fn;
    +var Virus = db.model('Virus', VirusSchema);
    +var v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });
     
    -  if (this.defaultValue) {
    -    defaultArr = this.defaultValue;
    -    fn = 'function' == typeof defaultArr;
    +console.log(v.name);     // name is required
    +console.log(v.taxonomy); // Parvovirinae
    show code
    SchemaType.prototype.set = function(fn) {
    +  if (typeof fn !== 'function') {
    +    throw new TypeError('A setter must be a function.');
       }
    +  this.setters.push(fn);
    +  return this;
    +};

    SchemaType#sparse(bool)

    Declares a sparse index.

    Parameters:

    Returns:

    Example:

    - this.default(function(){ - var arr = fn ? defaultArr() : defaultArr || []; - return new MongooseArray(arr, self.path, this); - }); -};

    Parameters:

    Inherits:


    SchemaArray#checkRequired(value)

    Check required

    show code
    SchemaArray.prototype.checkRequired = function (value) {
    -  return !!(value && value.length);
    -};

    Parameters:


    SchemaArray#applyGetters(value, scope)

    Overrides the getters application for the population special-case

    show code
    SchemaArray.prototype.applyGetters = function (value, scope) {
    -  if (this.caster.options && this.caster.options.ref) {
    -    // means the object id was populated
    -    return value;
    +
    var s = new Schema({ name: { type: String, sparse: true })
    +Schema.path('name').index({ sparse: true });
    show code
    SchemaType.prototype.sparse = function(bool) {
    +  if (this._index === null || this._index === undefined ||
    +    typeof this._index === 'boolean') {
    +    this._index = {};
    +  } else if (typeof this._index === 'string') {
    +    this._index = {type: this._index};
       }
     
    -  return SchemaType.prototype.applyGetters.call(this, value, scope);
    -};

    Parameters:


    SchemaArray#cast(value, doc, init)

    Casts contents

    show code
    SchemaArray.prototype.cast = function (value, doc, init) {
    -  if (Array.isArray(value)) {
    -    if (!(value instanceof MongooseArray)) {
    -      value = new MongooseArray(value, this.path, doc);
    -    }
    -
    -    if (this.caster) {
    -      try {
    -        for (var i = 0, l = value.length; i < l; i++) {
    -          value[i] = this.caster.cast(value[i], doc, init);
    -        }
    -      } catch (e) {
    -        // rethrow
    -        throw new CastError(e.type, value);
    -      }
    -    }
    +  this._index.sparse = bool;
    +  return this;
    +};

    SchemaType#text(bool)

    Declares a full text index.

    Parameters:

    Returns:

    Example:

    - return value; - } else { - return this.cast([value], doc, init); +
    var s = new Schema({name : {type: String, text : true })
    + Schema.path('name').index({text : true});
    show code
    SchemaType.prototype.text = function(bool) {
    +  if (this._index === null || this._index === undefined ||
    +    typeof this._index === 'boolean') {
    +    this._index = {};
    +  } else if (typeof this._index === 'string') {
    +    this._index = {type: this._index};
       }
    -};

    Parameters:

    • value <Object>
    • doc <Document> document that triggers the casting
    • init <Boolean> whether this is an initialization cast

    SchemaArray#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaArray.prototype.castForQuery = function ($conditional, value) {
    -  var handler
    -    , val;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Array.");
    -    val = handler.call(this, value);
    -  } else {
    -    val = $conditional;
    -    var proto = this.casterConstructor.prototype;
    -    var method = proto.castForQuery || proto.cast;
    -    if (Array.isArray(val)) {
    -      val = val.map(function (v) {
    -        if (method) v = method.call(proto, v);
    -        return isMongooseObject(v)
    -          ? v.toObject()
    -          : v;
    -      });
    -    } else if (method) {
    -      val = method.call(proto, val);
    +
    +  this._index.text = bool;
    +  return this;
    +};

    SchemaType#unique(bool)

    Declares an unique index.

    Parameters:

    Returns:

    Example:

    + +
    var s = new Schema({ name: { type: String, unique: true }});
    +Schema.path('name').index({ unique: true });
    + +

    NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.

    show code
    SchemaType.prototype.unique = function(bool) {
    +  if (this._index === false) {
    +    if (!bool) {
    +      return;
         }
    +    throw new Error('Path "' + this.path + '" may not have `index` set to ' +
    +      'false and `unique` set to true');
    +  }
    +  if (this._index == null || this._index === true) {
    +    this._index = {};
    +  } else if (typeof this._index === 'string') {
    +    this._index = {type: this._index};
       }
    -  return val && isMongooseObject(val)
    -    ? val.toObject()
    -    : val;
    -};

    Parameters:


  • schema/boolean.js

    SchemaBoolean(path, options)

    Boolean SchemaType constructor.

    show code
    function SchemaBoolean (path, options) {
    -  SchemaType.call(this, path, options);
    -};

    Parameters:

    Inherits:


    SchemaBoolean#checkRequired()

    Required validator

    show code
    SchemaBoolean.prototype.checkRequired = function (value) {
    -  return value === true || value === false;
    -};

    SchemaBoolean#cast(value)

    Casts to boolean

    show code
    SchemaBoolean.prototype.cast = function (value) {
    -  if (value === null) return value;
    -  if (value === '0') return false;
    -  return !!value;
    -};

    Parameters:


    SchemaBoolean#castForQuery($conditional, val)

    Casts contents for queries.

    show code
    SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (2 === arguments.length) {
    -    handler = SchemaBoolean.$conditionalHandlers[$conditional];
     
    -    if (handler) {
    -      return handler.call(this, val);
    -    }
    +  this._index.unique = bool;
    +  return this;
    +};

    SchemaType#validate(obj, [errorMsg], [type])

    Adds validator(s) for this document path.

    Parameters:

    Returns:

    Validators always receive the value to validate as their first argument and must return Boolean. Returning false means validation failed.

    - return this.cast(val); - } +

    The error message argument is optional. If not passed, the default generic error message template will be used.

    - return this.cast($conditional); -};

    Parameters:


  • schema/buffer.js

    SchemaBuffer(key, cast)

    Buffer SchemaType constructor

    show code
    function SchemaBuffer (key, options) {
    -  SchemaType.call(this, key, options, 'Buffer');
    -};

    Parameters:

    Inherits:


    SchemaBuffer#checkRequired()

    Check required

    show code
    SchemaBuffer.prototype.checkRequired = function (value) {
    -  return !!(value && value.length);
    -};

    SchemaBuffer#cast(value, doc, init)

    Casts contents

    show code
    SchemaBuffer.prototype.cast = function (value, doc, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    +

    Examples:

    - if (Buffer.isBuffer(value)) { - if (!(value instanceof MongooseBuffer)) { - value = new MongooseBuffer(value, [this.path, doc]); - } +
    // make sure every value is equal to "something"
    +function validator (val) {
    +  return val == 'something';
    +}
    +new Schema({ name: { type: String, validate: validator }});
     
    -    return value;
    -  } else if (value instanceof Binary) {
    -    return new MongooseBuffer(value.value(true), [this.path, doc]);
    -  }
    +// with a custom error message
     
    -  if ('string' === typeof value || Array.isArray(value)) {
    -    return new MongooseBuffer(value, [this.path, doc]);
    -  }
    +var custom = [validator, 'Uh oh, {PATH} does not equal "something".']
    +new Schema({ name: { type: String, validate: custom }});
     
    -  throw new CastError('buffer', value);
    -};

    Parameters:


    SchemaBuffer#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Buffer.");
    -    return handler.call(this, val);
    -  } else {
    -    val = $conditional;
    -    return this.cast(val).toObject();
    -  }
    -};

    Parameters:


  • schema/date.js

    SchemaDate(key, options)

    Date SchemaType constructor.

    show code
    function SchemaDate (key, options) {
    -  SchemaType.call(this, key, options);
    -};

    Parameters:

    Inherits:


    SchemaDate#checkRequired()

    Required validator for date

    show code
    SchemaDate.prototype.checkRequired = function (value) {
    -  return value instanceof Date;
    -};

    SchemaDate#cast(value)

    Casts to date

    show code
    SchemaDate.prototype.cast = function (value) {
    -  if (value === null || value === '')
    -    return null;
    +// adding many validators at a time
     
    -  if (value instanceof Date)
    -    return value;
    +var many = [
    +    { validator: validator, msg: 'uh oh' }
    +  , { validator: anotherValidator, msg: 'failed' }
    +]
    +new Schema({ name: { type: String, validate: many }});
     
    -  var date;
    +// or utilizing SchemaType methods directly:
     
    -  // support for timestamps
    -  if (value instanceof Number || 'number' == typeof value 
    -      || String(value) == Number(value))
    -    date = new Date(Number(value));
    +var schema = new Schema({ name: 'string' });
    +schema.path('name').validate(validator, 'validation of `{PATH}` failed with value `{VALUE}`');
    - // support for date strings - else if (value.toString) - date = new Date(value.toString()); +

    Error message templates:

    - if (date.toString() != 'Invalid Date') - return date; +

    From the examples above, you may have noticed that error messages support basic templating. There are a few other template keywords besides {PATH} and {VALUE} too. To find out more, details are available here

    - throw new CastError('date', value); -};

    Parameters:


    SchemaDate#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaDate.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    +

    Asynchronous validation:

    - if (2 !== arguments.length) { - return this.cast($conditional); - } +

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first argument passed to the validator function is the value being validated. The second argument is a callback function that must called when you finish validating the value and passed either true or false to communicate either success or failure respectively.

    - handler = this.$conditionalHandlers[$conditional]; +
    schema.path('name').validate({
    +  isAsync: true,
    +  validator: function (value, respond) {
    +    doStuff(value, function () {
    +      ...
    +      respond(false); // validation failed
    +    });
    +  },
    +  message: 'Custom error message!' // Optional
    +});
     
    -  if (!handler) {
    -    throw new Error("Can't use " + $conditional + " with Date.");
    +// Can also return a promise
    +schema.path('name').validate({
    +  validator: function (value) {
    +    return new Promise(function (resolve, reject) {
    +      resolve(false); // validation failed
    +    });
       }
    +});
    - return handler.call(this, val); -};

    Parameters:


  • schema/documentarray.js

    DocumentArray(key, schema, options)

    SubdocsArray SchemaType constructor

    show code
    function DocumentArray (key, schema, options) {
    +

    You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.

    - // compile an embedded document for this schema - function EmbeddedDocument () { - Subdocument.apply(this, arguments); - } +

    Validation occurs pre('save') or whenever you manually execute document#validate.

    - EmbeddedDocument.prototype.__proto__ = Subdocument.prototype; - EmbeddedDocument.prototype._setSchema(schema); - EmbeddedDocument.schema = schema; +

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    - // apply methods - for (var i in schema.methods) { - EmbeddedDocument.prototype[i] = schema.methods[i]; - } +
    var conn = mongoose.createConnection(..);
    +conn.on('error', handleError);
     
    -  // apply statics
    -  for (var i in schema.statics)
    -    EmbeddedDocument[i] = schema.statics[i];
    +var Product = conn.model('Product', yourSchema);
    +var dvd = new Product(..);
    +dvd.save(); // emits error on the `conn` above
    - EmbeddedDocument.options = options; - this.schema = schema; +

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    - ArrayType.call(this, key, EmbeddedDocument, options); +
    // registering an error listener on the Model lets us handle errors more locally
    +Product.on('error', handleError);
    show code
    SchemaType.prototype.validate = function(obj, message, type) {
    +  if (typeof obj === 'function' || obj && utils.getFunctionName(obj.constructor) === 'RegExp') {
    +    var properties;
    +    if (message instanceof Object && !type) {
    +      properties = utils.clone(message);
    +      if (!properties.message) {
    +        properties.message = properties.msg;
    +      }
    +      properties.validator = obj;
    +      properties.type = properties.type || 'user defined';
    +    } else {
    +      if (!message) {
    +        message = MongooseError.messages.general.default;
    +      }
    +      if (!type) {
    +        type = 'user defined';
    +      }
    +      properties = {message: message, type: type, validator: obj};
    +    }
    +    this.validators.push(properties);
    +    return this;
    +  }
     
    -  this.schema = schema;
    -  var path = this.path;
    -  var fn = this.defaultValue;
    +  var i,
    +      length,
    +      arg;
     
    -  this.default(function(){
    -    var arr = fn.call(this);
    -    if (!Array.isArray(arr)) arr = [arr];
    -    return new MongooseDocumentArray(arr, path, this);
    -  });
    -};

    Parameters:

    Inherits:


    DocumentArray#doValidate()

    Performs local validations first, then validations on each embedded doc

    show code
    DocumentArray.prototype.doValidate = function (array, fn, scope) {
    -  var self = this;
    +  for (i = 0, length = arguments.length; i < length; i++) {
    +    arg = arguments[i];
    +    if (!(arg && utils.getFunctionName(arg.constructor) === 'Object')) {
    +      var msg = 'Invalid validator. Received (' + typeof arg + ') '
    +          + arg
    +          + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
     
    -  SchemaType.prototype.doValidate.call(this, array, function (err) {
    -    if (err) return fn(err);
    +      throw new Error(msg);
    +    }
    +    this.validate(arg.validator, arg);
    +  }
     
    -    var count = array && array.length
    -      , error;
    +  return this;
    +};

    SchemaType._isRef(self, value, doc, init)

    Determines if value is a valid Reference.

    show code
    SchemaType._isRef = function(self, value, doc, init) {
    +  // fast path
    +  var ref = init && self.options && self.options.ref;
    +
    +  if (!ref && doc && doc.$__fullPath) {
    +    // checks for
    +    // - this populated with adhoc model and no ref was set in schema OR
    +    // - setting / pushing values after population
    +    var path = doc.$__fullPath(self.path);
    +    var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
    +    ref = owner.populated(path);
    +  }
    +
    +  if (ref) {
    +    if (value == null) {
    +      return true;
    +    }
    +    if (!Buffer.isBuffer(value) &&  // buffers are objects too
    +        value._bsontype !== 'Binary' // raw binary value from the db
    +        && utils.isObject(value)    // might have deselected _id in population query
    +    ) {
    +      return true;
    +    }
    +  }
     
    -    if (!count) return fn();
    +  return false;
    +};

    Parameters:

    Returns:


  • promise.js

    Promise#addBack(listener)

    Adds a single function as a listener to both err and complete.

    Parameters:

    Returns:

    It will be executed with traditional node.js argument position when the promise is resolved.

    - // handle sparse arrays, do not use array.forEach which does not - // iterate over sparse elements yet reports array.length including - // them :( +
    promise.addBack(function (err, args...) {
    +  if (err) return handleError(err);
    +  console.log('success');
    +})
    - for (var i = 0, len = count; i < len; ++i) { - // sidestep sparse entries - var doc = array[i]; - if (!doc) { - --count || fn(); - continue; - } +

    Alias of mpromise#onResolve.

    - ;(function (i) { - doc.validate(function (err) { - if (err && !error) { - // rewrite the key - err.key = self.key + '.' + i + '.' + err.key; - return fn(error = err); - } - --count || fn(); - }); - })(i); - } - }, scope); -};

    DocumentArray#cast(value, document)

    Casts contents

    show code
    DocumentArray.prototype.cast = function (value, doc, init, prev) {
    -  var selected
    -    , subdoc
    -    , i
    +

    Deprecated. Use onResolve instead.


    Promise#addCallback(listener)

    Adds a listener to the complete (success) event.

    Parameters:

    Returns:

    Alias of mpromise#onFulfill.

    - if (!Array.isArray(value)) { - return this.cast([value], doc, init, prev); - } +

    Deprecated. Use onFulfill instead.


    Promise#addErrback(listener)

    Adds a listener to the err (rejected) event.

    Parameters:

    Returns:

    Alias of mpromise#onReject.

    - if (!(value instanceof MongooseDocumentArray)) { - value = new MongooseDocumentArray(value, this.path, doc); - } +

    Deprecated. Use onReject instead.


    Promise#catch(onReject)

    ES6-style .catch() shorthand

    Parameters:

    Returns:


    Promise#end()

    Signifies that this promise was the last in a chain of then()s: if a handler passed to the call to then which produced this promise throws, the exception will go uncaught.

    Example:

    - i = value.length; +
    var p = new Promise;
    +p.then(function(){ throw new Error('shucks') });
    +setTimeout(function () {
    +  p.fulfill();
    +  // error was caught and swallowed by the promise returned from
    +  // p.then(). we either have to always register handlers on
    +  // the returned promises or we can do the following...
    +}, 10);
     
    -  while (i--) {
    -    if (!(value[i] instanceof Subdocument) && value[i]) {
    -      if (init) {
    -        selected || (selected = scopePaths(this, doc._selected, init));
    -        subdoc = new this.casterConstructor(null, value, true, selected);
    -        value[i] = subdoc.init(value[i]);
    -      } else {
    -        if (prev && (subdoc = prev.id(value[i]._id))) {
    -          // handle resetting doc with existing id but differing data
    -          // doc.array = [{ doc: 'val' }]
    -          subdoc.set(value[i]);
    -        } else {
    -          subdoc = new this.casterConstructor(value[i], value);
    -        }
    +// this time we use .end() which prevents catching thrown errors
    +var p = new Promise;
    +var p2 = p.then(function(){ throw new Error('shucks') }).end(); // &lt;--
    +setTimeout(function () {
    +  p.fulfill(); // throws "shucks"
    +}, 10);

    Promise#error(err)

    Rejects this promise with err.

    Parameters:

    Returns:

    If the promise has already been fulfilled or rejected, not action is taken.

    - // if set() is hooked it will have no return value - // see gh-746 - value[i] = subdoc; - } +

    Differs from #reject by first casting err to an Error if it is not instanceof Error.

    show code
    Promise.prototype.error = function(err) {
    +  if (!(err instanceof Error)) {
    +    if (err instanceof Object) {
    +      err = util.inspect(err);
         }
    +    err = new Error(err);
       }
    +  return this.reject(err);
    +};

    Promise#on(event, listener)

    Adds listener to the event.

    Parameters:

    Returns:

    If event is either the success or failure event and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


    Promise(fn)

    Promise constructor.

    Parameters:

    • fn <Function> a function which will be called when the promise is resolved that accepts fn(err, ...){} as signature

    Inherits:

    Events:

    • err: Emits when the promise is rejected

    • complete: Emits when the promise is fulfilled

    Promises are returned from executed queries. Example:

    - return value; -}

    Parameters:


  • schema/mixed.js

    Mixed(path, options)

    Mixed SchemaType constructor.

    show code
    function Mixed (path, options) {
    -  // make sure empty array defaults are handled
    -  if (options &&
    -      options.default &&
    -      Array.isArray(options.default) &&
    -      0 === options.default.length) {
    -    options.default = Array;
    -  }
    +
    var query = Candy.find({ bar: true });
    +var promise = query.exec();
    - SchemaType.call(this, path, options); -};

    Parameters:

    Inherits:


    Mixed#checkRequired()

    Required validator

    show code
    Mixed.prototype.checkRequired = function (val) {
    -  return true;
    -};

    Mixed#cast(value)

    Casts val for Mixed.

    show code
    Mixed.prototype.cast = function (val) {
    -  return val;
    -};

    Parameters:

    this is a no-op


    Mixed#castForQuery($cond, [val])

    Casts contents for queries.

    show code
    Mixed.prototype.castForQuery = function ($cond, val) {
    -  if (arguments.length === 2) return val;
    -  return $cond;
    -};

    Parameters:


  • schema/number.js

    SchemaNumber(key, options)

    Number SchemaType constructor.

    show code
    function SchemaNumber (key, options) {
    -  SchemaType.call(this, key, options, 'Number');
    -};

    Parameters:

    Inherits:


    SchemaNumber#checkRequired()

    Required validator for number

    show code
    SchemaNumber.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return typeof value == 'number' || value instanceof Number;
    -  }
    -};

    SchemaNumber#min(value, message)

    Sets a maximum number validator.

    show code
    SchemaNumber.prototype.min = function (value, message) {
    -  if (this.minValidator)
    -    this.validators = this.validators.filter(function(v){
    -      return v[1] != 'min';
    -    });
    -  if (value != null)
    -    this.validators.push([function(v){
    -      return v === null || v >= value;
    -    }, 'min']);
    -  return this;
    -};

    Parameters:

    Example:

    +

    DEPRECATED. Mongoose 5.0 will use native promises by default (or bluebird,
    if native promises are not present) but still
    support plugging in your own ES6-compatible promises library. Mongoose 5.0
    will not support mpromise.

    show code
    function Promise(fn) {
    +  MPromise.call(this, fn);
    +}

    Promise#reject(reason)

    Rejects this promise with reason.

    Parameters:

    Returns:

    If the promise has already been fulfilled or rejected, not action is taken.


    Promise#resolve([err], [val])

    Resolves this promise to a rejected state if err is passed or a fulfilled state if no err is passed.

    Parameters:

    • [err] <Error> error or null
    • [val] <Object> value to fulfill the promise with

    If the promise has already been fulfilled or rejected, not action is taken.

    -
    var s = new Schema({ n: { type: Number, min: 10 })
    -var M = db.model('M', s)
    -var m = new M({ n: 9 })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.n = 10;
    -  m.save() // success
    -})

    SchemaNumber#max(maximum, message)

    Sets a maximum number validator.

    show code
    SchemaNumber.prototype.max = function (value, message) {
    -  if (this.maxValidator)
    -    this.validators = this.validators.filter(function(v){
    -      return v[1] != 'max';
    -    });
    -  if (value != null)
    -    this.validators.push([this.maxValidator = function(v){
    -      return v === null || v <= value;
    -    }, 'max']);
    -  return this;
    -};

    Parameters:

    Example:

    +

    err will be cast to an Error if not already instanceof Error.

    -
    var s = new Schema({ n: { type: Number, max: 10 })
    -var M = db.model('M', s)
    -var m = new M({ n: 11 })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.n = 10;
    -  m.save() // success
    -})

    SchemaNumber#cast(value, doc, init)

    Casts to number

    show code
    SchemaNumber.prototype.cast = function (value, doc, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    +

    NOTE: overrides mpromise#resolve to provide error casting.

    show code
    Promise.prototype.resolve = function(err) {
    +  if (err) return this.error(err);
    +  return this.fulfill.apply(this, Array.prototype.slice.call(arguments, 1));
    +};

    Promise#then(onFulFill, onReject)

    Creates a new promise and returns it. If onFulfill or onReject are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.

    Parameters:

    Returns:

    Conforms to promises/A+ specification.

    - if (!isNaN(value)){ - if (null === value) return value; - if ('' === value) return null; - if ('string' == typeof value) value = Number(value); - if (value instanceof Number) return value - if ('number' == typeof value) return value; - if (value.toString && !Array.isArray(value) && - value.toString() == Number(value)) { - return new Number(value) - } - } +

    Example:

    - throw new CastError('number', value); -};

    Parameters:


    SchemaNumber#castForQuery($conditional, [value])

    Casts contents for queries.

    show code
    SchemaNumber.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with Number.");
    -    return handler.call(this, val);
    -  } else {
    -    val = this.cast($conditional);
    -    return val == null ? val : val
    -  }
    -};

    Parameters:


  • schema/objectid.js

    ObjectId(key, options)

    ObjectId SchemaType constructor.

    show code
    function ObjectId (key, options) {
    -  SchemaType.call(this, key, options, 'ObjectID');
    -};

    Parameters:

    Inherits:


    ObjectId#checkRequired()

    Check required

    show code
    ObjectId.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    +
    var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec();
    +promise.then(function (meetups) {
    +  var ids = meetups.map(function (m) {
    +    return m._id;
    +  });
    +  return People.find({ meetups: { $in: ids } }).exec();
    +}).then(function (people) {
    +  if (people.length &lt; 10000) {
    +    throw new Error('Too few people!!!');
       } else {
    -    return value instanceof oid;
    +    throw new Error('Still need more people!!!');
       }
    -};

    ObjectId#cast(value, scope, init)

    Casts to ObjectId

    show code
    ObjectId.prototype.cast = function (value, scope, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    +}).then(null, function (err) {
    +  assert.ok(err instanceof Error);
    +});

    Promise.complete(args)

    Fulfills this promise with passed arguments.

    Parameters:

    • args <T>

    Alias of mpromise#fulfill.

    - if (value === null) return value; +

    Deprecated. Use fulfill instead.


    Promise.ES6(resolver)

    ES6-style promise constructor wrapper around mpromise.

    show code
    Promise.ES6 = function(resolver) {
    +  var promise = new Promise();
     
    -  if (value instanceof oid)
    -    return value;
    +  // No try/catch for backwards compatibility
    +  resolver(
    +    function() {
    +      promise.complete.apply(promise, arguments);
    +    },
    +    function(e) {
    +      promise.error(e);
    +    });
     
    -  if (value._id && value._id instanceof oid)
    -    return value._id;
    +  return promise;
    +};

    Parameters:

    Returns:


    Promise.fulfill(args)

    Fulfills this promise with passed arguments.

    Parameters:

    • args <T>

  • ES6Promise.js

    ES6Promise(fn)

    ES6 Promise wrapper constructor.

    Parameters:

    • fn <Function> a function which will be called when the promise is resolved that accepts fn(err, ...){} as signature

    Promises are returned from executed queries. Example:

    - if (value.toString) - return oid.fromString(value.toString()); +
    var query = Candy.find({ bar: true });
    +var promise = query.exec();
    - throw new CastError('object id', value); -};

    Parameters:


    ObjectId#castForQuery($conditional, [val])

    Casts contents for queries.

    show code
    ObjectId.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with ObjectId.");
    -    return handler.call(this, val);
    -  } else {
    -    return this.cast($conditional);
    -  }
    -};

    Parameters:


    ObjectId#auto(turnOn)

    Adds an auto-generated ObjectId default if turnOn is true.

    show code
    ObjectId.prototype.auto = function (turnOn) {
    -  if (turnOn) {
    -    this.default(defaultId);
    -    this.set(resetId)
    -  }
    -};

    Parameters:

    • turnOn <Boolean> auto generated ObjectId defaults

  • schema/string.js

    SchemaString(key, options)

    String SchemaType constructor.

    show code
    function SchemaString (key, options) {
    -  this.enumValues = [];
    -  this.regExp = null;
    -  SchemaType.call(this, key, options, 'String');
    -};

    Parameters:

    Inherits:


    SchemaString#enum([args...])

    Adds enumeration values and a coinciding validator.

    show code
    SchemaString.prototype.enum = function () {
    -  var len = arguments.length;
    -  if (!len || undefined === arguments[0] || false === arguments[0]) {
    -    if (this.enumValidator){
    -      this.enumValidator = false;
    -      this.validators = this.validators.filter(function(v){
    -        return v[1] != 'enum';
    -      });
    -    }
    -    return;
    -  }
    +

    DEPRECATED. Mongoose 5.0 will use native promises by default (or bluebird,
    if native promises are not present) but still
    support plugging in your own ES6-compatible promises library. Mongoose 5.0
    will not support mpromise.

    show code
    function ES6Promise() {
    +  throw new Error('Can\'t use ES6 promise with mpromise style constructor');
    +}
     
    -  for (var i = 0; i < len; i++) {
    -    if (undefined !== arguments[i]) {
    -      this.enumValues.push(this.cast(arguments[i]));
    -    }
    +ES6Promise.use = function(Promise) {
    +  ES6Promise.ES6 = Promise;
    +};
    +
    +module.exports = ES6Promise;

  • browserDocument.js

    Document(obj, [fields], [skipId])

    Document constructor.

    Parameters:

    • obj <Object> the values to set
    • [fields] <Object> optional object containing the fields which were selected in the query returning this document and any populated paths data
    • [skipId] <Boolean> bool, should we auto create an ObjectId _id

    Events:

    • init: Emitted on a document after it has was retrieved from the db and fully hydrated by Mongoose.

    • save: Emitted when the document is successfully saved

    show code
    function Document(obj, schema, fields, skipId, skipInit) {
    +  if (!(this instanceof Document)) {
    +    return new Document(obj, schema, fields, skipId, skipInit);
       }
     
    -  if (!this.enumValidator) {
    -    var values = this.enumValues;
    -    this.enumValidator = function(v){
    -      return undefined === v || ~values.indexOf(v);
    -    };
    -    this.validators.push([this.enumValidator, 'enum']);
    +
    +  if (utils.isObject(schema) && !schema.instanceOfSchema) {
    +    schema = new Schema(schema);
       }
    -};

    Parameters:

    • [args...] <String> enumeration values

    Example:

    -
    var states = 'opening open closing closed'.split(' ')
    -var s = new Schema({ state: { type: String, enum: states })
    -var M = db.model('M', s)
    -var m = new M({ state: 'invalid' })
    -m.save(function (err) {
    -  console.error(err) // validator error
    -  m.state = 'open'
    -  m.save() // success
    -})

    SchemaString#lowercase()

    Adds a lowercase setter.

    show code
    SchemaString.prototype.lowercase = function () {
    -  return this.set(function (v, self) {
    -    if ('string' != typeof v) v = self.cast(v)
    -    if (v) return v.toLowerCase();
    -    return v;
    -  });
    -};

    Example:

    + // When creating EmbeddedDocument, it already has the schema and he doesn't need the _id + schema = this.schema || schema; -
    var s = new Schema({ email: { type: String, lowercase: true }})
    -var M = db.model('M', s);
    -var m = new M({ email: 'SomeEmail@example.COM' });
    -console.log(m.email) // someemail@example.com
    -

    SchemaString#uppercase()

    Adds an uppercase setter.

    show code
    SchemaString.prototype.uppercase = function () {
    -  return this.set(function (v, self) {
    -    if ('string' != typeof v) v = self.cast(v)
    -    if (v) return v.toUpperCase();
    -    return v;
    -  });
    -};

    Example:

    + // Generate ObjectId if it is missing, but it requires a scheme + if (!this.schema && schema.options._id) { + obj = obj || {}; -
    var s = new Schema({ caps: { type: String, uppercase: true }})
    -var M = db.model('M', s);
    -var m = new M({ caps: 'an example' });
    -console.log(m.caps) // AN EXAMPLE

    SchemaString#trim()

    Adds a trim setter.

    show code
    SchemaString.prototype.trim = function () {
    -  return this.set(function (v, self) {
    -    if ('string' != typeof v) v = self.cast(v)
    -    if (v) return v.trim();
    -    return v;
    -  });
    -};

    The string value will be trimmed when set.

    + if (obj._id === undefined) { + obj._id = new ObjectId(); + } + } -

    Example:

    + if (!schema) { + throw new MongooseError.MissingSchemaError(); + } -
    var s = new Schema({ name: { type: String, trim: true }})
    -var M = db.model('M', s)
    -var string = ' some name '
    -console.log(string.length) // 11
    -var m = new M({ name: string })
    -console.log(m.name.length) // 9

    SchemaString#match(regExp)

    Sets a regexp validator.

    show code
    SchemaString.prototype.match = function match (regExp) {
    -  this.validators.push([function(v){
    -    return null != v && '' !== v
    -      ? regExp.test(v)
    -      : true
    -  }, 'regexp']);
    -};

    Parameters:

    • regExp <RegExp> regular expression to test against

    Any value that does not pass regExp.test(val) will fail validation.

    + this.$__setSchema(schema); -

    Example:

    + this.$__ = new InternalCache; + this.$__.emitter = new EventEmitter(); + this.isNew = true; + this.errors = undefined; -
    var s = new Schema({ name: { type: String, match: /^a/ }})
    -var M = db.model('M', s)
    -var m = new M({ name: 'invalid' })
    -m.validate(function (err) {
    -  console.error(err) // validation error
    -  m.name = 'apples'
    -  m.validate(function (err) {
    -    assert.ok(err) // success
    -  })
    -})

    SchemaString#checkRequired(value)

    Check required

    show code
    SchemaString.prototype.checkRequired = function checkRequired (value) {
    -  if (SchemaType._isRef(this, value, true)) {
    -    return null != value;
    -  } else {
    -    return (value instanceof String || typeof value == 'string') && value.length;
    -  }
    -};

    Parameters:


    SchemaString#cast()

    Casts to String

    show code
    SchemaString.prototype.cast = function (value, scope, init) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    -  if (value === null) return value;
    -  if ('undefined' !== typeof value && value.toString) return value.toString();
    -  throw new CastError('string', value);
    -};

    SchemaString#castForQuery($conditional, [val])

    Casts contents for queries.

    show code
    SchemaString.prototype.castForQuery = function ($conditional, val) {
    -  var handler;
    -  if (arguments.length === 2) {
    -    handler = this.$conditionalHandlers[$conditional];
    -    if (!handler)
    -      throw new Error("Can't use " + $conditional + " with String.");
    -    return handler.call(this, val);
    +  if (typeof fields === 'boolean') {
    +    this.$__.strictMode = fields;
    +    fields = undefined;
       } else {
    -    val = $conditional;
    -    if (val instanceof RegExp) return val;
    -    return this.cast(val);
    +    this.$__.strictMode = this.schema.options && this.schema.options.strict;
    +    this.$__.selected = fields;
       }
    -};

    Parameters:


  • schema.js

    Schema(definition)

    Schema constructor.

    show code
    function Schema (obj, options) {
    -  if (!(this instanceof Schema))
    -    return new Schema(obj, options);
     
    -  this.paths = {};
    -  this.subpaths = {};
    -  this.virtuals = {};
    -  this.nested = {};
    -  this.inherits = {};
    -  this.callQueue = [];
    -  this._indexes = [];
    -  this.methods = {};
    -  this.statics = {};
    -  this.tree = {};
    -  this._requiredpaths = undefined;
    +  var required = this.schema.requiredPaths();
    +  for (var i = 0; i < required.length; ++i) {
    +    this.$__.activePaths.require(required[i]);
    +  }
     
    -  this.options = this.defaultOptions(options);
    +  this.$__.emitter.setMaxListeners(0);
    +  this._doc = this.$__buildDoc(obj, fields, skipId);
     
    -  // build paths
    -  if (obj) {
    -    this.add(obj);
    +  if (!skipInit && obj) {
    +    this.init(obj);
       }
     
    -  // ensure the documents get an auto _id unless disabled
    -  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
    -  if (auto_id) {
    -    this.add({ _id: {type: Schema.ObjectId, auto: true} });
    -  }
    +  this.$__registerHooksFromSchema();
     
    -  // ensure the documents receive an id getter unless disabled
    -  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
    -  if (autoid) {
    -    this.virtual('id').get(idGetter);
    +  // apply methods
    +  for (var m in schema.methods) {
    +    this[m] = schema.methods[m];
    +  }
    +  // apply statics
    +  for (var s in schema.statics) {
    +    this[s] = schema.statics[s];
       }
    +}

  • services/setDefaultsOnInsert.js

    module.exports(query, schema, castedDoc, options)

    Applies defaults to update and findOneAndUpdate operations.

    Parameters:


  • services/cursor/eachAsync.js

    module.exports(next, fn, options, [callback])

    Execute fn for every document in the cursor. If fn returns a promise,
    will wait for the promise to resolve before iterating on to the next one.
    Returns a promise that resolves when done.

    Parameters:

    • next <Function> the thunk to call to get the next document
    • fn <Function>
    • options <Object>
    • [callback] <Function> executed when all docs have been processed

    Returns:


  • services/updateValidators.js

    module.exports(query, schema, castedDoc, options)

    Applies validators and defaults to update and findOneAndUpdate operations,
    specifically passing a null doc as this to validators and defaults

    Parameters:


  • model.js

    Model#$__delta()

    Produces a special query document of the modified properties used in updates.


    Model#$__version()

    Appends versioning to the where and update clauses.


    Model#$__where()

    Returns a query object


    Model#$where(argument)

    Creates a Query and specifies a $where condition.

    Parameters:

    • argument <String, Function> is a javascript string or anonymous function

    Returns:

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    - // versioning not directly added to schema b/c we only want - // it in the top level document, not embedded ones. -};

    Parameters:

    Events:

    • init: Emitted after the schema is compiled into a Model.

    Example:

    +
    Blog.$where('this.username.indexOf("val") !== -1').exec(function (err, docs) {});

    Model#increment()

    Signal that we desire an increment of this documents version.

    Example:

    -
    var child = new Schema({ name: String });
    -var schema = new Schema({ name: String, age: Number, children: [child] });
    -var Tree = mongoose.model('Tree', schema);
    +
    Model.findById(id, function (err, doc) {
    +  doc.increment();
    +  doc.save(function (err) { .. })
    +})
    show code
    Model.prototype.increment = function increment() {
    +  this.$__.version = VERSION_ALL;
    +  return this;
    +};

    Model#model(name)

    Returns another Model instance.

    Parameters:

    Example:

    -// setting schema options -new Schema({ name: String }, { _id: false, autoIndex: false }) +
    var doc = new Tank;
    +doc.model('User').findById(id, callback);
    show code
    Model.prototype.model = function model(name) {
    +  return this.db.model(name);
    +};

    Model(doc)

    Model constructor

    Parameters:

    • doc <Object> values with which to create the document

    Inherits:

    Events:

    • error: If listening to this event, 'error' is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

    • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.

    • index-single-start: Emitted when an individual index starts within Model#ensureIndexes. The fields and options being used to build the index are also passed with the event.

    • index-single-done: Emitted when an individual index finishes within Model#ensureIndexes. If an error occurred it is passed with the event. The fields, options, and index name are also passed.

    Provides the interface to MongoDB collections as well as creates document instances.

    show code
    function Model(doc, fields, skipId) {
    +  Document.call(this, doc, fields, skipId, true);
    +}

    Model#remove([fn])

    Removes this document from the db.

    Parameters:

    Returns:

    Example:

    -

    Options:

    +
    product.remove(function (err, product) {
    +  if (err) return handleError(err);
    +  Product.findById(product._id, function (err, product) {
    +    console.log(product) // null
    +  })
    +})
    -
      -
    • safe: bool - defaults to true.
    • -
    • read: string
    • -
    • strict: bool - defaults to true
    • -
    • capped: bool - defaults to false
    • -
    • versionKey: bool - defaults to "__v"
    • -
    • shardKey: bool - defaults to null
    • -
    • autoIndex: bool - defaults to true
    • -
    • _id: bool - defaults to true
    • -
    • id: bool - defaults to true
    • -
    • toObject - object - no default
    • -
    • toJSON - object - no default
    • -
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • -
    +

    As an extra measure of flow control, remove will return a Promise (bound to fn if passed) so it could be chained, or hooked to recive errors

    -

    Note:

    +

    Example:

    -

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


    Schema#defaultOptions(options)

    Returns default options for this schema, merged with options.

    show code
    Schema.prototype.defaultOptions = function (options) {
    -  options = utils.options({
    -      safe: true
    -    , strict: true
    -    , capped: false // { size, max, autoIndexId }
    -    , versionKey: '__v'
    -    , minimize: true
    -    , autoIndex: true
    -    , shardKey: null
    -    , read: null
    -    // the following are only applied at construction time
    -    , noId: false // deprecated, use { _id: false }
    -    , _id: true
    -    , noVirtualId: false // deprecated, use { id: false }
    -    , id: true
    -  }, options);
    +
    product.remove().then(function (product) {
    +   ...
    +}).onRejected(function (err) {
    +   assert.ok(err)
    +})
    show code
    Model.prototype.remove = function remove(options, fn) {
    +  if (typeof options === 'function') {
    +    fn = options;
    +    options = undefined;
    +  }
     
    -  if (options.read)
    -    options.read = utils.readPref(options.read);
    +  if (!options) {
    +    options = {};
    +  }
     
    -  return options;
    -}

    Parameters:

    Returns:


    Schema#add(obj, prefix)

    Adds key path / schema type pairs to this schema.

    show code
    Schema.prototype.add = function add (obj, prefix) {
    -  prefix = prefix || '';
    -  for (var i in obj) {
    -    if (null == obj[i]) {
    -      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
    +  if (this.$__.removing) {
    +    if (fn) {
    +      this.$__.removing.then(
    +          function(res) { fn(null, res); },
    +          function(err) { fn(err); });
         }
    -
    -    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
    -      if (Object.keys(obj[i]).length) {
    -        // nested object { last: { name: String }}
    -        this.nested[prefix + i] = true;
    -        this.add(obj[i], prefix + i + '.');
    -      }
    -      else
    -        this.path(prefix + i, obj[i]); // mixed type
    -    } else
    -      this.path(prefix + i, obj[i]);
    +    return this;
       }
    -};

    Parameters:

    Example:

    -
    var ToySchema = new Schema;
    -ToySchema.add({ name: 'string', color: 'string', price: 'number' });

    Schema#path(path, constructor)

    Gets/sets schema paths.

    show code
    Schema.prototype.path = function (path, obj) {
    -  if (obj == undefined) {
    -    if (this.paths[path]) return this.paths[path];
    -    if (this.subpaths[path]) return this.subpaths[path];
    +  var _this = this;
    +  var Promise = PromiseProvider.get();
     
    -    // subpaths?
    -    return /\.\d+\.?$/.test(path)
    -      ? getPositionalPath(this, path)
    -      : undefined;
    +  if (fn) {
    +    fn = this.constructor.$wrapCallback(fn);
       }
     
    -  // some path names conflict with document methods
    -  if (reserved[path]) {
    -    throw new Error("`" + path + "` may not be used as a schema pathname");
    -  }
    +  this.$__.removing = new Promise.ES6(function(resolve, reject) {
    +    var where = _this.$__where();
    +    if (where instanceof Error) {
    +      reject(where);
    +      fn && fn(where);
    +      return;
    +    }
     
    -  // update the tree
    -  var subpaths = path.split(/\./)
    -    , last = subpaths.pop()
    -    , branch = this.tree;
    +    if (!options.safe && _this.schema.options.safe) {
    +      options.safe = _this.schema.options.safe;
    +    }
     
    -  subpaths.forEach(function(path) {
    -    if (!branch[path]) branch[path] = {};
    -    branch = branch[path];
    +    _this.collection.remove(where, options, function(err) {
    +      if (!err) {
    +        _this.emit('remove', _this);
    +        _this.constructor.emit('remove', _this);
    +        resolve(_this);
    +        fn && fn(null, _this);
    +        return;
    +      }
    +      reject(err);
    +      fn && fn(err);
    +    });
       });
    +  return this.$__.removing;
    +};

    Model#save([options], [options.safe], [options.validateBeforeSave], [fn])

    Saves this document.

    Parameters:

    Returns:

    Example:

    - branch[last] = utils.clone(obj); +
    product.sold = Date.now();
    +product.save(function (err, product, numAffected) {
    +  if (err) ..
    +})
    - this.paths[path] = Schema.interpretAsType(path, obj); - return this; -};

    Parameters:

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    +

    The callback will receive three parameters

    -

    Example

    +
      +
    1. err if an error occurred
    2. +
    3. product which is the saved product
    4. +
    5. numAffected will be 1 when the document was successfully persisted to MongoDB, otherwise 0. Unless you tweak mongoose's internals, you don't need to worry about checking this parameter for errors - checking err is sufficient to make sure your document was properly saved.
    6. +
    -
    schema.path('name') // returns a SchemaType
    -schema.path('name', Number) // changes the schemaType of `name` to Number

    Schema#eachPath(fn)

    Iterates the schemas paths similar to Array#forEach.

    show code
    Schema.prototype.eachPath = function (fn) {
    -  var keys = Object.keys(this.paths)
    -    , len = keys.length;
    +

    As an extra measure of flow control, save will return a Promise.

    - for (var i = 0; i < len; ++i) { - fn(keys[i], this.paths[keys[i]]); - } +

    Example:

    - return this; -};

    Parameters:

    Returns:

    The callback is passed the pathname and schemaType as arguments on each iteration.


    Schema#requiredPaths()

    Returns an Array of path strings that are required by this schema.

    show code
    Schema.prototype.requiredPaths = function requiredPaths () {
    -  if (this._requiredpaths) return this._requiredpaths;
    +
    product.save().then(function(product) {
    +   ...
    +});
    + +

    For legacy reasons, mongoose stores object keys in reverse order on initial
    save. That is, { a: 1, b: 2 } will be saved as { b: 2, a: 1 } in
    MongoDB. To override this behavior, set
    the toObject.retainKeyOrder option
    to true on your schema.

    show code
    Model.prototype.save = function(options, fn) {
    +  if (typeof options === 'function') {
    +    fn = options;
    +    options = undefined;
    +  }
     
    -  var paths = Object.keys(this.paths)
    -    , i = paths.length
    -    , ret = [];
    +  if (!options) {
    +    options = {};
    +  }
     
    -  while (i--) {
    -    var path = paths[i];
    -    if (this.paths[path].isRequired) ret.push(path);
    +  if (fn) {
    +    fn = this.constructor.$wrapCallback(fn);
       }
     
    -  return this._requiredpaths = ret;
    -}

    Returns:


    Schema#pathType(path)

    Returns the pathType of path for this schema.

    show code
    Schema.prototype.pathType = function (path) {
    -  if (path in this.paths) return 'real';
    -  if (path in this.virtuals) return 'virtual';
    -  if (path in this.nested) return 'nested';
    -  if (path in this.subpaths) return 'real';
    +  return this.$__save(options, fn);
    +};

    Model._getSchema(path)

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    show code
    Model._getSchema = function _getSchema(path) {
    +  return this.schema._getSchema(path);
    +};

    Parameters:

    Returns:


    Model.aggregate([...], [callback])

    Performs aggregations on the models collection.

    show code
    Model.aggregate = function aggregate() {
    +  var args = [].slice.call(arguments),
    +      aggregate,
    +      callback;
     
    -  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
    -    return 'real';
    +  if (typeof args[args.length - 1] === 'function') {
    +    callback = args.pop();
    +  }
    +
    +  if (args.length === 1 && util.isArray(args[0])) {
    +    aggregate = new Aggregate(args[0]);
       } else {
    -    return 'adhocOrUndefined'
    +    aggregate = new Aggregate(args);
       }
    -};

    Parameters:

    Returns:

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


    Schema#queue(name, args)

    Adds a method call to the queue.

    show code
    Schema.prototype.queue = function(name, args){
    -  this.callQueue.push([name, args]);
    -  return this;
    -};

    Parameters:

    • name <String> name of the document method to call later
    • args <Array> arguments to pass to the method

    Schema#pre(method, callback)

    Defines a pre hook for the document.

    show code
    Schema.prototype.pre = function(){
    -  return this.queue('pre', arguments);
    -};

    Parameters:

    Example

    -
    var toySchema = new Schema(..);
    +  aggregate.model(this);
     
    -toySchema.pre('save', function (next) {
    -  if (!this.created) this.created = new Date;
    -  next();
    -})
    +  if (typeof callback === 'undefined') {
    +    return aggregate;
    +  }
     
    -toySchema.pre('validate', function (next) {
    -  if (this.name != 'Woody') this.name = 'Woody';
    -  next();
    -})

    Schema#post(method, fn)

    Defines a post hook for the document.

    show code
    Schema.prototype.post = function(method, fn){
    -  return this.queue('on', arguments);
    -};

    Parameters:

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    + if (callback) { + callback = this.$wrapCallback(callback); + } -
    var schema = new Schema(..);
    -schema.post('save', function () {
    -  console.log('this fired after a document was saved');
    -});
    +  aggregate.exec(callback);
    +};

    Parameters:

    Returns:

    If a callback is passed, the aggregate is executed and a Promise is returned. If a callback is not passed, the aggregate itself is returned.

    -var Model = mongoose.model('Model', schema); +

    Example:

    -var m = new Model(..); -m.save(function (err) { - console.log('this fires after the `post` hook'); -});

    Schema#plugin(plugin, opts)

    Registers a plugin for this schema.

    show code
    Schema.prototype.plugin = function (fn, opts) {
    -  fn(this, opts);
    -  return this;
    -};

    Parameters:


    Schema#method(method, [fn])

    Adds an instance method to documents constructed from Models compiled from this schema.

    show code
    Schema.prototype.method = function (name, fn) {
    -  if ('string' != typeof name)
    -    for (var i in name)
    -      this.methods[i] = name[i];
    -  else
    -    this.methods[name] = fn;
    -  return this;
    -};

    Parameters:

    Example

    +
    // Find the max balance of all accounts
    +Users.aggregate(
    +  { $group: { _id: null, maxBalance: { $max: '$balance' }}},
    +  { $project: { _id: 0, maxBalance: 1 }},
    +  function (err, res) {
    +    if (err) return handleError(err);
    +    console.log(res); // [ { maxBalance: 98000 } ]
    +  });
     
    -
    var schema = kittySchema = new Schema(..);
    +// Or use the aggregation pipeline builder.
    +Users.aggregate()
    +  .group({ _id: null, maxBalance: { $max: '$balance' } })
    +  .select('-id maxBalance')
    +  .exec(function (err, res) {
    +    if (err) return handleError(err);
    +    console.log(res); // [ { maxBalance: 98 } ]
    +});
    -schema.methods.meow = function () { - console.log('meeeeeoooooooooooow'); -}) +

    NOTE:

    -var Kitty = mongoose.model('Kitty', schema); +
      +
    • Arguments are not cast to the model's schema because $project operators allow redefining the "shape" of the documents at any stage of the pipeline, which may leave documents in an incompatible format.
    • +
    • The documents returned are plain javascript objects, not mongoose documents (since any shape of document can be returned).
    • +
    • Requires MongoDB >= 2.1
    • +

    Model.bulkWrite(ops, [options], [callback])

    Sends multiple insertOne, updateOne, updateMany, replaceOne,
    deleteOne, and/or deleteMany operations to the MongoDB server in one
    command. This is faster than sending multiple independent operations (like)
    if you use create()) because with bulkWrite() there is only one round
    trip to MongoDB.

    show code
    Model.bulkWrite = function(ops, options, callback) {
    +  var Promise = PromiseProvider.get();
    +  var _this = this;
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
    +  }
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
    +  }
    +  options = options || {};
     
    -var fizz = new Kitty;
    -fizz.meow(); // meeeeeooooooooooooow
    + var validations = ops.map(function(op) { + if (op['insertOne']) { + return function(callback) { + op['insertOne']['document'] = new _this(op['insertOne']['document']); + op['insertOne']['document'].validate({ __noPromise: true }, function(error) { + if (error) { + return callback(error); + } + callback(null); + }); + }; + } else if (op['updateOne']) { + return function(callback) { + try { + op['updateOne']['filter'] = cast(_this.schema, + op['updateOne']['filter']); + op['updateOne']['update'] = castUpdate(_this.schema, + op['updateOne']['update'], _this.schema.options.strict); + } catch (error) { + return callback(error); + } -

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    + callback(null); + }; + } else if (op['updateMany']) { + return function(callback) { + try { + op['updateMany']['filter'] = cast(_this.schema, + op['updateMany']['filter']); + op['updateMany']['update'] = castUpdate(_this.schema, op['updateMany']['update'], { + strict: _this.schema.options.strict, + overwrite: false + }); + } catch (error) { + return callback(error); + } -
    schema.method({
    -    purr: function () {}
    -  , scratch: function () {}
    -});
    +        callback(null);
    +      };
    +    } else if (op['replaceOne']) {
    +      return function(callback) {
    +        try {
    +          op['replaceOne']['filter'] = cast(_this.schema,
    +            op['replaceOne']['filter']);
    +        } catch (error) {
    +          return callback(error);
    +        }
     
    -// later
    -fizz.purr();
    -fizz.scratch();

    Schema#static(name, fn)

    Adds static "class" methods to Models compiled from this schema.

    show code
    Schema.prototype.static = function(name, fn) {
    -  if ('string' != typeof name)
    -    for (var i in name)
    -      this.statics[i] = name[i];
    -  else
    -    this.statics[name] = fn;
    -  return this;
    -};

    Parameters:

    Example

    + // set `skipId`, otherwise we get "_id field cannot be changed" + op['replaceOne']['replacement'] = + new _this(op['replaceOne']['replacement'], null, true); + op['replaceOne']['replacement'].validate({ __noPromise: true }, function(error) { + if (error) { + return callback(error); + } + callback(null); + }); + }; + } else if (op['deleteOne']) { + return function(callback) { + try { + op['deleteOne']['filter'] = cast(_this.schema, + op['deleteOne']['filter']); + } catch (error) { + return callback(error); + } -
    var schema = new Schema(..);
    -schema.static('findByName', function (name, callback) {
    -  return this.find({ name: name }, callback);
    -});
    +        callback(null);
    +      };
    +    } else if (op['deleteMany']) {
    +      return function(callback) {
    +        try {
    +          op['deleteMany']['filter'] = cast(_this.schema,
    +            op['deleteMany']['filter']);
    +        } catch (error) {
    +          return callback(error);
    +        }
     
    -var Drink = mongoose.model('Drink', schema);
    -Drink.findByName('sanpellegrino', function (err, drinks) {
    -  //
    -});
    + callback(null); + }; + } else { + return function(callback) { + callback(new Error('Invalid op passed to `bulkWrite()`')); + }; + } + }); -

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


    Schema#index(fields, [options])

    Defines an index (most likely compound) for this schema.

    show code
    Schema.prototype.index = function (fields, options) {
    -  options || (options = {});
    +  var promise = new Promise.ES6(function(resolve, reject) {
    +    parallel(validations, function(error) {
    +      if (error) {
    +        callback && callback(error);
    +        return reject(error);
    +      }
     
    -  if (options.expires)
    -    utils.expires(options);
    +      _this.collection.bulkWrite(ops, options, function(error, res) {
    +        if (error) {
    +          callback && callback(error);
    +          return reject(error);
    +        }
     
    -  this._indexes.push([fields, options]);
    -  return this;
    -};

    Parameters:

    Example

    + callback && callback(null, res); + resolve(res); + }); + }); + }); + + return promise; +};

    Parameters:

    • ops <Array>
    • [options] <Object>
    • [callback] <Function> callback <code>function(error, bulkWriteOpResult) {}</code>

    Returns:

    • <Promise> resolves to a `BulkWriteOpResult` if the operation succeeds

    Mongoose will perform casting on all operations you provide.

    + +

    This function does not trigger any middleware. If you need to trigger
    save() middleware for every document use create() instead.

    + +

    Example:

    + +
    Character.bulkWrite([
    +  {
    +    insertOne: {
    +      document: {
    +        name: 'Eddard Stark',
    +        title: 'Warden of the North'
    +      }
    +    }
    +  },
    +  {
    +    updateOne: {
    +      filter: { name: 'Eddard Stark' },
    +      // If you were using the MongoDB driver directly, you'd need to do
    +      // `update: { $set: { title: ... } }` but mongoose adds $set for
    +      // you.
    +      update: { title: 'Hand of the King' }
    +    }
    +  },
    +  {
    +    deleteOne: {
    +      {
    +        filter: { name: 'Eddard Stark' }
    +      }
    +    }
    +  }
    +]).then(handleResult);

    Model.count(conditions, [callback])

    Counts number of matching documents in a database collection.

    show code
    Model.count = function count(conditions, callback) {
    +  if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = {};
    +  }
    +
    +  // get the mongodb collection object
    +  var mq = new this.Query({}, {}, this, this.collection);
    +
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
    +  }
     
    -
    schema.index({ first: 1, last: -1 })

    Schema#set(key, [value])

    Sets/gets a schema option.

    show code
    Schema.prototype.set = function (key, value, tags) {
    -  if (arguments.length == 1)
    -    return this.options[key];
    +  return mq.count(conditions, callback);
    +};

    Parameters:

    Returns:

    Example:

    - this.options[key] = 'read' == key - ? utils.readPref(value, tags) - : value; +
    Adventure.count({ type: 'jungle' }, function (err, count) {
    +  if (err) ..
    +  console.log('there are %d jungle adventures', count);
    +});

    Model.create(doc(s), [callback])

    Shortcut for saving one or more documents to the database.
    MyModel.create(docs) does new MyModel(doc).save() for every doc in
    docs.

    show code
    Model.create = function create(doc, callback) {
    +  var args;
    +  var cb;
    +  var discriminatorKey = this.schema.options.discriminatorKey;
     
    -  return this;
    -};

    Parameters:

    • key <String> option name
    • [value] <Object> if not passed, the current option value is returned

    Schema#indexes()

    Compiles indexes from fields and schema-level indexes

    show code
    Schema.prototype.indexes = function () {
    -  var indexes = []
    -    , seenSchemas = [];
    +  if (Array.isArray(doc)) {
    +    args = doc;
    +    cb = callback;
    +  } else {
    +    var last = arguments[arguments.length - 1];
    +    // Handle falsy callbacks re: #5061
    +    if (typeof last === 'function' || !last) {
    +      cb = last;
    +      args = utils.args(arguments, 0, arguments.length - 1);
    +    } else {
    +      args = utils.args(arguments);
    +    }
    +  }
     
    -  collectIndexes(this);
    +  var Promise = PromiseProvider.get();
    +  var _this = this;
    +  if (cb) {
    +    cb = this.$wrapCallback(cb);
    +  }
    +
    +  var promise = new Promise.ES6(function(resolve, reject) {
    +    if (args.length === 0) {
    +      setImmediate(function() {
    +        cb && cb(null);
    +        resolve(null);
    +      });
    +      return;
    +    }
     
    -  return indexes;
    +    var toExecute = [];
    +    var firstError;
    +    args.forEach(function(doc) {
    +      toExecute.push(function(callback) {
    +        var Model = _this.discriminators && doc[discriminatorKey] ?
    +          _this.discriminators[doc[discriminatorKey]] :
    +          _this;
    +        var toSave = doc instanceof Model ? doc : new Model(doc);
    +        var callbackWrapper = function(error, doc) {
    +          if (error) {
    +            if (!firstError) {
    +              firstError = error;
    +            }
    +            return callback(null, { error: error });
    +          }
    +          callback(null, { doc: doc });
    +        };
     
    -  function collectIndexes (schema, prefix) {
    -    if (~seenSchemas.indexOf(schema)) return;
    -    seenSchemas.push(schema);
    +        // Hack to avoid getting a promise because of
    +        // $__registerHooksFromSchema
    +        if (toSave.$__original_save) {
    +          toSave.$__original_save({ __noPromise: true }, callbackWrapper);
    +        } else {
    +          toSave.save({ __noPromise: true }, callbackWrapper);
    +        }
    +      });
    +    });
     
    -    var index;
    -    var paths = schema.paths;
    -    prefix = prefix || '';
    +    parallel(toExecute, function(error, res) {
    +      var savedDocs = [];
    +      var len = res.length;
    +      for (var i = 0; i < len; ++i) {
    +        if (res[i].doc) {
    +          savedDocs.push(res[i].doc);
    +        }
    +      }
     
    -    for (var i in paths) {
    -      if (paths[i]) {
    -        if (paths[i] instanceof Types.DocumentArray) {
    -          collectIndexes(paths[i].schema, i + '.');
    +      if (firstError) {
    +        if (cb) {
    +          cb(firstError, savedDocs);
             } else {
    -          index = paths[i]._index;
    -
    -          if (index !== false && index !== null){
    -            var field = {};
    -            field[prefix + i] = '2d' === index ? index : 1;
    -            var options = 'Object' === index.constructor.name ? index : {};
    -            if (!('background' in options)) options.background = true;
    -            indexes.push([field, options]);
    -          }
    +          reject(firstError);
             }
    +        return;
           }
    -    }
     
    -    if (prefix) {
    -      fixSubIndexPaths(schema, prefix);
    -    } else {
    -      schema._indexes.forEach(function (index) {
    -        if (!('background' in index[1])) index[1].background = true;
    -      });
    -      indexes = indexes.concat(schema._indexes);
    -    }
    -  }

    Schema#virtual(name, [options])

    Creates a virtual type with the given name.

    show code
    Schema.prototype.virtual = function (name, options) {
    -  var virtuals = this.virtuals;
    -  var parts = name.split('.');
    -  return virtuals[name] = parts.reduce(function (mem, part, i) {
    -    mem[part] || (mem[part] = (i === parts.length-1)
    -                            ? new VirtualType(options, name)
    -                            : {});
    -    return mem[part];
    -  }, this.tree);
    -};

    Parameters:

    Returns:


    Schema#virtualpath(name)

    Returns the virtual type with the given name.

    show code
    Schema.prototype.virtualpath = function (name) {
    -  return this.virtuals[name];
    -};

    Parameters:

    Returns:


    Schema#namedScope()

    These still haven't been fixed. Once they're working we'll make them public again.

    show code
    Schema.prototype.namedScope = function (name, fn) {
    -  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
    -    , newScope = Object.create(namedScopes)
    -    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
    -  allScopes[name] = newScope;
    -  newScope.name = name;
    -  newScope.block = fn;
    -  newScope.query = new Query();
    -  newScope.decorate(namedScopes, {
    -    block0: function (block) {
    -      return function () {
    -        block.call(this.query);
    -        return this;
    -      };
    -    },
    -    blockN: function (block) {
    -      return function () {
    -        block.apply(this.query, arguments);
    -        return this;
    -      };
    -    },
    -    basic: function (query) {
    -      return function () {
    -        this.query.find(query);
    -        return this;
    -      };
    -    }
    +      if (doc instanceof Array) {
    +        resolve(savedDocs);
    +        cb && cb.call(_this, null, savedDocs);
    +      } else {
    +        resolve.apply(promise, savedDocs);
    +        if (cb) {
    +          cb.apply(_this, [null].concat(savedDocs));
    +        }
    +      }
    +    });
       });
    -  return newScope;
    -};

    Schema.reserved

    Reserved document keys.

    show code
    Schema.reserved = Object.create(null);
    -var reserved = Schema.reserved;
    -reserved.on =
    -reserved.db =
    -reserved.init =
    -reserved.isNew =
    -reserved.errors =
    -reserved.schema =
    -reserved.options =
    -reserved.modelName =
    -reserved.collection = 1;

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    -
    on, db, init, isNew, errors, schema, options, modelName, collection
    + return promise; +};

    Parameters:

    Returns:

    Hooks Triggered

    -

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    +
      +
    • save()
    • +
    -
    var schema = new Schema(..);
    - schema.methods.init = function () {} // potentially breaking

    Schema.interpretAsType(path, obj)

    Converts type arguments into Mongoose Types.

    show code
    Schema.interpretAsType = function (path, obj) {
    -  if (obj.constructor.name != 'Object')
    -    obj = { type: obj };
    +

    Example:

    - // Get the type making sure to allow keys named "type" - // and default to mixed if not specified. - // { type: { type: String, default: 'freshcut' } } - var type = obj.type && !obj.type.type - ? obj.type - : {}; +
    // pass individual docs
    +Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
    +  if (err) // ...
    +});
     
    -  if ('Object' == type.constructor.name || 'mixed' == type) {
    -    return new Types.Mixed(path, obj);
    -  }
    +// pass an array
    +var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
    +Candy.create(array, function (err, candies) {
    +  if (err) // ...
     
    -  if (Array.isArray(type) || Array == type || 'array' == type) {
    -    // if it was specified through { type } look for `cast`
    -    var cast = (Array == type || 'array' == type)
    -      ? obj.cast
    -      : type[0];
    +  var jellybean = candies[0];
    +  var snickers = candies[1];
    +  // ...
    +});
     
    -    if (cast instanceof Schema) {
    -      return new Types.DocumentArray(path, cast, obj);
    -    }
    +// callback is optional; use the returned promise if you like:
    +var promise = Candy.create({ type: 'jawbreaker' });
    +promise.then(function (jawbreaker) {
    +  // ...
    +})

    Model.deleteMany(conditions, [callback])

    Deletes all of the documents that match conditions from the collection.
    Behaves like remove(), but deletes all documents that match conditions
    regardless of the single option.

    show code
    Model.deleteMany = function deleteMany(conditions, callback) {
    +  if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = {};
    +  }
     
    -    if ('string' == typeof cast) {
    -      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
    -    } else if (cast && (!cast.type || cast.type.type)
    -                    && 'Object' == cast.constructor.name
    -                    && Object.keys(cast).length) {
    -      return new Types.DocumentArray(path, new Schema(cast), obj);
    -    }
    +  // get the mongodb collection object
    +  var mq = new this.Query(conditions, {}, this, this.collection);
     
    -    return new Types.Array(path, cast || Types.Mixed, obj);
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
       }
     
    -  var name = 'string' == typeof type
    -    ? type
    -    : type.name;
    +  return mq.deleteMany(callback);
    +};

    Parameters:

    Returns:

    Example:

    + +
    Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, function (err) {});
    - if (name) { - name = name.charAt(0).toUpperCase() + name.substring(1); +

    Note:

    + +

    Like Model.remove(), this function does not trigger pre('remove') or post('remove') hooks.


    Model.deleteOne(conditions, [callback])

    Deletes the first document that matches conditions from the collection.
    Behaves like remove(), but deletes at most one document regardless of the
    single option.

    show code
    Model.deleteOne = function deleteOne(conditions, callback) {
    +  if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = {};
       }
     
    -  if (undefined == Types[name]) {
    -    throw new TypeError('Undefined type at `' + path +
    -        '`
    -  Did you try nesting Schemas? ' +
    -        'You can only nest using refs or arrays.');
    +  // get the mongodb collection object
    +  var mq = new this.Query(conditions, {}, this, this.collection);
    +
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
       }
     
    -  return new Types[name](path, obj);
    -};

    Parameters:


    Schema.Types

    The various Mongoose Schema Types.

    show code
    Schema.Types = require('./schema/index');

    Example:

    + return mq.deleteOne(callback); +};

    Parameters:

    Returns:

    Example:

    -

    Example:

    +
    Character.deleteOne({ name: 'Eddard Stark' }, function (err) {});
    -
    var mongoose = require('mongoose');
    -var ObjectId = mongoose.Schema.Types.ObjectId;
    +

    Note:

    -

    Types:

    +

    Like Model.remove(), this function does not trigger pre('remove') or post('remove') hooks.


    Model.discriminator(name, schema)

    Adds a discriminator type.

    show code
    Model.discriminator = function(name, schema) {
    +  var model;
    +  if (typeof name === 'function') {
    +    model = name;
    +    name = utils.getFunctionName(model);
    +  }
     
    -
      -
    • String
    • -
    • Number
    • -
    • Boolean | Bool
    • -
    • Array
    • -
    • Buffer
    • -
    • Date
    • -
    • ObjectId | Oid
    • -
    • Mixed
    • -
    + schema = discriminator(this, name, schema); + if (this.db.models[name]) { + throw new OverwriteModelError(name); + } -

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    + schema.$isRootDiscriminator = true; -
    var Mixed = mongoose.Schema.Types.Mixed;
    -new mongoose.Schema({ _user: Mixed })

    Schema#tree

    Schema as a tree

    + if (!model) { + model = this.db.model(name, schema, this.collection.name); + } + this.discriminators[name] = model; + var d = this.discriminators[name]; + d.prototype.__proto__ = this.prototype; + Object.defineProperty(d, 'baseModelName', { + value: this.modelName, + configurable: true, + writable: false + }); -

    Example:

    + // apply methods and statics + applyMethods(d, schema); + applyStatics(d, schema); -
    {
    -    '_id'     : ObjectId
    -  , 'nested'  : {
    -        'key' : String
    -    }
    -}

    Schema#paths

    Schema as flat paths

    + return d; +}; -

    Example:

    +// Model (class) features

    Parameters:

    • name <String> discriminator model name
    • schema <Schema> discriminator model schema

    Example:

    -
    {
    -    '_id'        : SchemaType,
    -  , 'nested.key' : SchemaType,
    -}

  • schemadefault.js

    exports#system.profile

    Default model for querying the system.profiles collection.


  • schematype.js

    SchemaType(path, [options], [instance])

    SchemaType constructor

    show code
    function SchemaType (path, options, instance) {
    -  this.path = path;
    -  this.instance = instance;
    -  this.validators = [];
    -  this.setters = [];
    -  this.getters = [];
    -  this.options = options;
    -  this._index = null;
    -  this.selected;
    +
    function BaseSchema() {
    +  Schema.apply(this, arguments);
     
    -  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
    -    // { unique: true, index: true }
    -    if ('index' == i && this._index) continue;
    +  this.add({
    +    name: String,
    +    createdAt: Date
    +  });
    +}
    +util.inherits(BaseSchema, Schema);
     
    -    var opts = Array.isArray(options[i])
    -      ? options[i]
    -      : [options[i]];
    +var PersonSchema = new BaseSchema();
    +var BossSchema = new BaseSchema({ department: String });
     
    -    this[i].apply(this, opts);
    +var Person = mongoose.model('Person', PersonSchema);
    +var Boss = Person.discriminator('Boss', BossSchema);

    Model.distinct(field, [conditions], [callback])

    Creates a Query for a distinct operation.

    show code
    Model.distinct = function distinct(field, conditions, callback) {
    +  // get the mongodb collection object
    +  var mq = new this.Query({}, {}, this, this.collection);
    +
    +  if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = {};
       }
    -};

    Parameters:


    SchemaType#default(val)

    Sets a default value for this SchemaType.

    show code
    SchemaType.prototype.default = function (val) {
    -  if (1 === arguments.length) {
    -    this.defaultValue = typeof val === 'function'
    -      ? val
    -      : this.cast(val);
    -    return this;
    -  } else if (arguments.length > 1) {
    -    this.defaultValue = utils.args(arguments);
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
       }
    -  return this.defaultValue;
    -};

    Parameters:

    Returns:

    Example:

    -
    var schema = new Schema({ n: { type: Number, default: 10 })
    -var M = db.model('M', schema)
    -var m = new M;
    -console.log(m.n) // 10
    + return mq.distinct(field, conditions, callback); +};

    Parameters:

    Returns:

    Passing a callback immediately executes the query.

    -

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    +

    Example

    -

    Example:

    +
    Link.distinct('url', { clicks: {$gt: 100}}, function (err, result) {
    +  if (err) return handleError(err);
     
    -
    // values are cast:
    -var schema = new Schema({ aNumber: Number, default: "4.815162342" })
    -var M = db.model('M', schema)
    -var m = new M;
    -console.log(m.aNumber) // 4.815162342
    +  assert(Array.isArray(result));
    +  console.log('unique urls with more than 100 clicks', result);
    +})
     
    -// default unique objects for Mixed types:
    -var schema = new Schema({ mixed: Schema.Types.Mixed });
    -schema.path('mixed').default(function () {
    -  return {};
    -});
    +var query = Link.distinct('url');
    +query.exec(callback);

    Model.ensureIndexes([options], [cb])

    Sends ensureIndex commands to mongo for each index declared in the schema.

    show code
    Model.ensureIndexes = function ensureIndexes(options, callback) {
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
    +  }
     
    -// if we don't use a function to return object literals for Mixed defaults,
    -// each document will receive a reference to the same object literal creating
    -// a "shared" object instance:
    -var schema = new Schema({ mixed: Schema.Types.Mixed });
    -schema.path('mixed').default({});
    -var M = db.model('M', schema);
    -var m1 = new M;
    -m1.mixed.added = 1;
    -console.log(m1.mixed); // { added: 1 }
    -var m2 = new M;
    -console.log(m2.mixed); // { added: 1 }

    SchemaType#index(options)

    Declares the index options for this schematype.

    show code
    SchemaType.prototype.index = function (options) {
    -  this._index = options;
    -  utils.expires(this._index);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    + if (options && options.__noPromise) { + _ensureIndexes(this, options, callback); + return; + } -
    var s = new Schema({ name: { type: String, index: true })
    -var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
    -Schema.path('my.path').index(true);
    -Schema.path('my.path').index({ expires: 60 });
    -Schema.path('my.path').index({ unique: true, sparse: true });
    + if (callback) { + callback = this.$wrapCallback(callback); + } -

    NOTE:

    + var _this = this; + var Promise = PromiseProvider.get(); + return new Promise.ES6(function(resolve, reject) { + _ensureIndexes(_this, options || {}, function(error) { + if (error) { + callback && callback(error); + reject(error); + } + callback && callback(); + resolve(); + }); + }); +}; -

    Indexes are created in the background by default. Specify background: false to override.

    +function _ensureIndexes(model, options, callback) { + var indexes = model.schema.indexes(); -

    Direction doesn't matter for single key indexes


    SchemaType#unique(bool)

    Declares an unique index.

    show code
    SchemaType.prototype.unique = function (bool) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    +  var done = function(err) {
    +    if (err && model.schema.options.emitIndexErrors) {
    +      model.emit('error', err);
    +    }
    +    model.emit('index', err);
    +    callback && callback(err);
    +  };
    +
    +  if (!indexes.length) {
    +    setImmediate(function() {
    +      done();
    +    });
    +    return;
       }
    +  // Indexes are created one-by-one to support how MongoDB < 2.4 deals
    +  // with background indexes.
     
    -  this._index.unique = bool;
    -  return this;
    -};

    Parameters:

    Returns:

    Examples:

    + var indexSingleDone = function(err, fields, options, name) { + model.emit('index-single-done', err, fields, options, name); + }; + var indexSingleStart = function(fields, options) { + model.emit('index-single-start', fields, options); + }; -
    var s = new Schema({ name: { type: String, unique: true })
    -Schema.path('name').index({ unique: true });

    SchemaType#sparse(bool)

    Declares a sparse index.

    show code
    SchemaType.prototype.sparse = function (bool) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    -  }
    +  var create = function() {
    +    if (options && options._automatic) {
    +      if (model.schema.options.autoIndex === false ||
    +          (model.schema.options.autoIndex == null && model.db.config.autoIndex === false)) {
    +        return done();
    +      }
    +    }
     
    -  this._index.sparse = bool;
    -  return this;
    -};

    Parameters:

    Returns:

    Examples:

    + var index = indexes.shift(); + if (!index) return done(); -
    var s = new Schema({ name: { type: String, sparse: true })
    -Schema.path('name').index({ sparse: true });

    SchemaType#expires(when)

    Declares a TTL index (rounded to the nearest second) for Date types only.

    show code
    SchemaType.prototype.expires = function (when) {
    -  if (!this._index || 'Object' !== this._index.constructor.name) {
    -    this._index = {};
    +    var indexFields = index[0];
    +    var indexOptions = index[1];
    +    _handleSafe(options);
    +
    +    indexSingleStart(indexFields, options);
    +
    +    model.collection.ensureIndex(indexFields, indexOptions, utils.tick(function(err, name) {
    +      indexSingleDone(err, indexFields, indexOptions, name);
    +      if (err) {
    +        return done(err);
    +      }
    +      create();
    +    }));
    +  };
    +
    +  setImmediate(function() {
    +    // If buffering is off, do this manually.
    +    if (options._automatic && !model.collection.collection) {
    +      model.collection.addQueue(create, []);
    +    } else {
    +      create();
    +    }
    +  });
    +}
    +
    +function _handleSafe(options) {
    +  if (options.safe) {
    +    if (typeof options.safe === 'boolean') {
    +      options.w = options.safe;
    +      delete options.safe;
    +    }
    +    if (typeof options.safe === 'object') {
    +      options.w = options.safe.w;
    +      options.j = options.safe.j;
    +      options.wtimeout = options.safe.wtimeout;
    +      delete options.safe;
    +    }
       }
    +}

    Parameters:

    Returns:

    Example:

    - this._index.expires = when; - utils.expires(this._index); - return this; -};

    Parameters:

    Returns:

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    +
    Event.ensureIndexes(function (err) {
    +  if (err) return handleError(err);
    +});
    + +

    After completion, an index event is emitted on this Model passing an error if one occurred.

    Example:

    -
    // expire in 24 hours
    -new Schema({..}, { expires: 60*60*24 });
    +
    var eventSchema = new Schema({ thing: { type: 'string', unique: true }})
    +var Event = mongoose.model('Event', eventSchema);
     
    -

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    +Event.on('index', function (err) { + if (err) console.error(err); // error occurred during index creation +})
    -

    Example:

    +

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    -
    // expire in 24 hours
    -new Schema({..}, { expires: '24h' });
    +

    The ensureIndex commands are not sent in parallel. This is to avoid the MongoError: cannot add index with a background operation in progress error. See this ticket for more information.


    Model.find(conditions, [projection], [options], [callback])

    Finds documents

    show code
    Model.find = function find(conditions, projection, options, callback) {
    +  if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = {};
    +    projection = null;
    +    options = null;
    +  } else if (typeof projection === 'function') {
    +    callback = projection;
    +    projection = null;
    +    options = null;
    +  } else if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
    +  }
     
    -// expire in 1.5 hours
    -new Schema({..}, { expires: '1.5h' });
    +  var mq = new this.Query({}, {}, this, this.collection);
    +  mq.select(projection);
    +  mq.setOptions(options);
    +  if (this.schema.discriminatorMapping &&
    +      this.schema.discriminatorMapping.isRoot &&
    +      mq.selectedInclusively()) {
    +    // Need to select discriminator key because original schema doesn't have it
    +    mq.select(this.schema.options.discriminatorKey);
    +  }
     
    -// expire in 7 days
    -var schema = new Schema({..});
    -schema.expires('7d');

    SchemaType#set(fn)

    Adds a setter to this schematype.

    show code
    SchemaType.prototype.set = function (fn) {
    -  if ('function' != typeof fn)
    -    throw new Error('A setter must be a function.');
    -  this.setters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    + if (callback) { + callback = this.$wrapCallback(callback); + } -
    function capitalize (val) {
    -  if ('string' != typeof val) val = '';
    -  return val.charAt(0).toUpperCase() + val.substring(1);
    -}
    +  return mq.find(conditions, callback);
    +};

    Parameters:

    • conditions <Object>
    • [projection] <Object> optional fields to return (http://bit.ly/1HotzBo)
    • [options] <Object> optional
    • [callback] <Function>

    Returns:

    The conditions are cast to their respective SchemaTypes before the command is sent.

    -// defining within the schema -var s = new Schema({ name: { type: String, set: capitalize }}) +

    Examples:

    -// or by retreiving its SchemaType -var s = new Schema({ name: String }) -s.path('name').set(capitalize)
    +
    // named john and at least 18
    +MyModel.find({ name: 'john', age: { $gte: 18 }});
     
    -

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    +// executes immediately, passing results to callback +MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {}); + +// name LIKE john and only selecting the "name" and "friends" fields, executing immediately +MyModel.find({ name: /john/i }, 'name friends', function (err, docs) { }) + +// passing options +MyModel.find({ name: /john/i }, null, { skip: 10 }) + +// passing options and executing immediately +MyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {}); -

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    +// executing a query explicitly +var query = MyModel.find({ name: /john/i }, null, { skip: 10 }) +query.exec(function (err, docs) {}); -

    You can set up email lower case normalization easily via a Mongoose setter.

    +// using the promise returned from executing a query +var query = MyModel.find({ name: /john/i }, null, { skip: 10 }); +var promise = query.exec(); +promise.addBack(function (err, docs) {});

    Model.findById(id, [projection], [options], [callback])

    Finds a single document by its _id field. findById(id) is almost*
    equivalent to findOne({ _id: id }). If you want to query by a document's
    _id, use findById() instead of findOne().

    show code
    Model.findById = function findById(id, projection, options, callback) {
    +  if (typeof id === 'undefined') {
    +    id = null;
    +  }
     
    -
    function toLower (v) {
    -  return v.toLowerCase();
    -}
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
    +  }
     
    -var UserSchema = new Schema({
    -  email: { type: String, set: toLower }
    -})
    +  return this.findOne({_id: id}, projection, options, callback);
    +};

    Parameters:

    Returns:

    The id is cast based on the Schema before sending the command.

    -var User = db.model('User', UserSchema) +

    Note: findById() triggers findOne hooks.

    -var user = new User({email: 'AVENUE@Q.COM'}) -console.log(user.email); // 'avenue@q.com' +
      +
    • Except for how it treats undefined. If you use findOne(), you'll see +that findOne(undefined) and findOne({ _id: undefined }) are equivalent +to findOne({}) and return arbitrary documents. However, mongoose +translates findById(undefined) into findOne({ _id: null }).
    • +
    -// or -var user = new User -user.email = 'Avenue@Q.com' -console.log(user.email) // 'avenue@q.com' -
    +

    Example:

    -

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    +
    // find adventure by id and execute immediately
    +Adventure.findById(id, function (err, adventure) {});
     
    -

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    +// same as above +Adventure.findById(id).exec(callback); -
    new Schema({ email: { type: String, lowercase: true }})

    SchemaType#get(fn)

    Adds a getter to this schematype.

    show code
    SchemaType.prototype.get = function (fn) {
    -  if ('function' != typeof fn)
    -    throw new Error('A getter must be a function.');
    -  this.getters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    +// select only the adventures name and length +Adventure.findById(id, 'name length', function (err, adventure) {}); -
    function dob (val) {
    -  if (!val) return val;
    -  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
    -}
    +// same as above
    +Adventure.findById(id, 'name length').exec(callback);
     
    -// defining within the schema
    -var s = new Schema({ born: { type: Date, get: dob })
    +// include all properties except for `length`
    +Adventure.findById(id, '-length').exec(function (err, adventure) {});
     
    -// or by retreiving its SchemaType
    -var s = new Schema({ born: Date })
    -s.path('born').get(dob)
    +// passing options (in this case return the raw js objects, not mongoose documents by passing `lean` +Adventure.findById(id, 'name', { lean: true }, function (err, doc) {}); -

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    +// same as above +Adventure.findById(id, 'name').lean().exec(function (err, doc) {});

    Model.findByIdAndRemove(id, [options], [callback])

    Issue a mongodb findAndModify remove command by a document's _id field. findByIdAndRemove(id, ...) is equivalent to findOneAndRemove({ _id: id }, ...).

    show code
    Model.findByIdAndRemove = function(id, options, callback) {
    +  if (arguments.length === 1 && typeof id === 'function') {
    +    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
     
    -

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    +' + + ' ' + this.modelName + '.findByIdAndRemove(id, callback) +' + + ' ' + this.modelName + '.findByIdAndRemove(id) +' + + ' ' + this.modelName + '.findByIdAndRemove() +'; + throw new TypeError(msg); + } + if (callback) { + callback = this.$wrapCallback(callback); + } -
    function obfuscate (cc) {
    -  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
    -}
    +  return this.findOneAndRemove({_id: id}, options, callback);
    +};

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    -var AccountSchema = new Schema({ - creditCardNumber: { type: String, get: obfuscate } -}); +

    Executes immediately if callback is passed, else a Query object is returned.

    -var Account = db.model('Account', AccountSchema); +

    Options:

    -Account.findById(id, function (err, found) { - console.log(found.creditCardNumber); // '****-****-****-1234' -});

    SchemaType#validate(obj, [error])

    Adds validator(s) for this document path.

    show code
    SchemaType.prototype.validate = function (obj, error) {
    -  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
    -    this.validators.push([obj, error]);
    -    return this;
    -  }
    +
     
    -  var i = arguments.length
    -    , arg
    +

    Examples:

    - while (i--) { - arg = arguments[i]; - if (!(arg && 'Object' == arg.constructor.name)) { - var msg = 'Invalid validator. Received (' + typeof arg + ') ' - + arg - + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate'; +
    A.findByIdAndRemove(id, options, callback) // executes
    +A.findByIdAndRemove(id, options)  // return Query
    +A.findByIdAndRemove(id, callback) // executes
    +A.findByIdAndRemove(id) // returns Query
    +A.findByIdAndRemove()           // returns Query

    Model.findByIdAndUpdate(id, [update], [options], [callback])

    Issues a mongodb findAndModify update command by a document's _id field.
    findByIdAndUpdate(id, ...) is equivalent to findOneAndUpdate({ _id: id }, ...).

    show code
    Model.findByIdAndUpdate = function(id, update, options, callback) {
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
    +  }
    +  if (arguments.length === 1) {
    +    if (typeof id === 'function') {
    +      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
     
    -      throw new Error(msg);
    +'
    +          + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
    +'
    +          + '  ' + this.modelName + '.findByIdAndUpdate(id)
    +'
    +          + '  ' + this.modelName + '.findByIdAndUpdate()
    +';
    +      throw new TypeError(msg);
         }
    -    this.validate(arg.validator, arg.msg);
    +    return this.findOneAndUpdate({_id: id}, undefined);
       }
     
    -  return this;
    -};

    Parameters:

    Validators must return Boolean. Returning false is interpreted as validation failure.

    + // if a model is passed in instead of an id + if (id instanceof Document) { + id = id._id; + } -

    Examples:

    + return this.findOneAndUpdate.call(this, {_id: id}, update, options, callback); +};

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg,
    passing any options, and returns the found document (if any) to the
    callback. The query executes immediately if callback is passed else a
    Query object is returned.

    -
    function validator () { ... }
    +

    This function triggers findOneAndUpdate middleware.

    -var single = [validator, 'failed'] -new Schema({ name: { type: String, validate: single }}); +

    Options:

    -var many = [ - { validator: validator, msg: 'uh oh' } - , { validator: fn, msg: 'failed' } -] -new Schema({ name: { type: String, validate: many }}); +
      +
    • new: bool - true to return the modified document rather than the original. defaults to false
    • +
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • +
    • runValidators: if true, runs update validators on this command. Update validators validate the update operation against the model's schema.
    • +
    • setDefaultsOnInsert: if this and upsert are true, mongoose will apply the defaults specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on MongoDB's $setOnInsert operator.
    • +
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • +
    • select: sets the document fields to return
    • +
    • passRawResult: if true, passes the raw result from the MongoDB driver as the third callback parameter
    • +
    • strict: overwrites the schema's strict mode option for this update
    • +
    • runSettersOnQuery: bool - if true, run all setters defined on the associated model's schema for all fields defined in the query and the update.
    • +
    -// or utilizing SchemaType methods directly: +

    Examples:

    -var schema = new Schema({ name: 'string' }); -schema.path('name').validate(validator, 'validation failed');
    +
    A.findByIdAndUpdate(id, update, options, callback) // executes
    +A.findByIdAndUpdate(id, update, options)  // returns Query
    +A.findByIdAndUpdate(id, update, callback) // executes
    +A.findByIdAndUpdate(id, update)           // returns Query
    +A.findByIdAndUpdate()                     // returns Query
    -

    Asynchronous validation:

    +

    Note:

    -

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    +

    All top level update keys which are not atomic operation names are treated as set operations:

    -
    schema.path('name').validate(function (value, respond) {
    -  doStuff(value, function () {
    -    ...
    -    respond(false); // validation failed
    -  })
    - }, 'my error type');
    +

    Example:

    -

    Validation occurs pre('save') or whenever you manually execute document#validate.

    +
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
     
    -

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    +// is sent as +Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
    -
    var conn = mongoose.createConnection(..);
    -conn.on('error', handleError);
    +

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    -var Product = conn.model('Product', yourSchema); -var dvd = new Product(..); -dvd.save(); // emits error on the `conn` above
    +

    Note:

    -

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    +

    Values are cast to their appropriate types when using the findAndModify helpers.
    However, the below are not executed by default.

    -
    // registering an error listener on the Model lets us handle errors more locally
    -Product.on('error', handleError);

    SchemaType#required(required)

    Adds a required validator to this schematype.

    show code
    SchemaType.prototype.required = function (required) {
    -  var self = this;
    +
      +
    • defaults. Use the setDefaultsOnInsert option to override.
    • +
    • setters. Use the runSettersOnQuery option to override.
    • +
    - function __checkRequired (v) { - // in here, `this` refers to the validating document. - // no validation when this path wasn't selected in the query. - if ('isSelected' in this && - !this.isSelected(self.path) && - !this.isModified(self.path)) return true; - return self.checkRequired(v); +

    findAndModify helpers support limited validation. You can
    enable these by setting the runValidators options,
    respectively.

    + +

    If you need full-fledged validation, use the traditional approach of first
    retrieving the document.

    + +
    Model.findById(id, function (err, doc) {
    +  if (err) ..
    +  doc.name = 'jason borne';
    +  doc.save(callback);
    +});

    Model.findOne([conditions], [projection], [options], [callback])

    Finds one document.

    show code
    Model.findOne = function findOne(conditions, projection, options, callback) {
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
    +  } else if (typeof projection === 'function') {
    +    callback = projection;
    +    projection = null;
    +    options = null;
    +  } else if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = {};
    +    projection = null;
    +    options = null;
       }
     
    -  if (false === required) {
    -    this.isRequired = false;
    -    this.validators = this.validators.filter(function (v) {
    -      return v[0].name !== '__checkRequired';
    -    });
    -  } else {
    -    this.isRequired = true;
    -    this.validators.push([__checkRequired, 'required']);
    +  // get the mongodb collection object
    +  var mq = new this.Query({}, {}, this, this.collection);
    +  mq.select(projection);
    +  mq.setOptions(options);
    +  if (this.schema.discriminatorMapping &&
    +      this.schema.discriminatorMapping.isRoot &&
    +      mq.selectedInclusively()) {
    +    mq.select(this.schema.options.discriminatorKey);
       }
     
    -  return this;
    -};

    Parameters:

    • required <Boolean> enable/disable the validator

    Returns:

    Example:

    + if (callback) { + callback = this.$wrapCallback(callback); + } -
    var s = new Schema({ born: { type: Date, required: true })
    -// or
    -Schema.path('name').required(true);

    SchemaType#getDefault(scope, init)

    Gets the default value

    show code
    SchemaType.prototype.getDefault = function (scope, init) {
    -  var ret = 'function' === typeof this.defaultValue
    -    ? this.defaultValue.call(scope)
    -    : this.defaultValue;
    +  return mq.findOne(conditions, callback);
    +};

    Parameters:

    • [conditions] <Object>
    • [projection] <Object> optional fields to return (http://bit.ly/1HotzBo)
    • [options] <Object> optional
    • [callback] <Function>

    Returns:

    The conditions are cast to their respective SchemaTypes before the command is sent.

    - if (null !== ret && undefined !== ret) { - return this.cast(ret, scope, init); - } else { - return ret; - } -};

    Parameters:

    • scope <Object> the scope which callback are executed
    • init <Boolean>

    SchemaType#applySetters(value, scope, init)

    Applies setters

    show code
    SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
    -  if (SchemaType._isRef(this, value, init)) return value;
    +

    Note: conditions is optional, and if conditions is null or undefined,
    mongoose will send an empty findOne command to MongoDB, which will return
    an arbitrary document. If you're querying by _id, use findById() instead.

    - var v = value - , setters = this.setters - , len = setters.length +

    Example:

    - if (!len) { - if (null === v || undefined === v) return v; - return init - ? v // if we just initialized we dont recast - : this.cast(v, scope, init, priorVal) - } +
    // find one iphone adventures - iphone adventures??
    +Adventure.findOne({ type: 'iphone' }, function (err, adventure) {});
     
    -  while (len--) {
    -    v = setters[len].call(scope, v, this);
    -  }
    +// same as above
    +Adventure.findOne({ type: 'iphone' }).exec(function (err, adventure) {});
     
    -  if (null === v || undefined === v) return v;
    +// select only the adventures name
    +Adventure.findOne({ type: 'iphone' }, 'name', function (err, adventure) {});
     
    -  // do not cast until all setters are applied #665
    -  v = this.cast(v, scope, init, priorVal);
    +// same as above
    +Adventure.findOne({ type: 'iphone' }, 'name').exec(function (err, adventure) {});
     
    -  return v;
    -};

    Parameters:


    SchemaType#applyGetters(value, scope)

    Applies getters to a value

    show code
    SchemaType.prototype.applyGetters = function (value, scope) {
    -  if (SchemaType._isRef(this, value, true)) return value;
    +// specify options, in this case lean
    +Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }, callback);
     
    -  var v = value
    -    , getters = this.getters
    -    , len = getters.length;
    +// same as above
    +Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }).exec(callback);
     
    -  if (!len) {
    -    return v;
    +// chaining findOne queries (same as above)
    +Adventure.findOne({ type: 'iphone' }).select('name').lean().exec(callback);

    Model.findOneAndRemove(conditions, [options], [callback])

    Issue a mongodb findAndModify remove command.

    show code
    Model.findOneAndRemove = function(conditions, options, callback) {
    +  if (arguments.length === 1 && typeof conditions === 'function') {
    +    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
    +
    +'
    +        + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
    +'
    +        + '  ' + this.modelName + '.findOneAndRemove(conditions)
    +'
    +        + '  ' + this.modelName + '.findOneAndRemove()
    +';
    +    throw new TypeError(msg);
       }
     
    -  while (len--) {
    -    v = getters[len].call(scope, v, this);
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = undefined;
    +  }
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
       }
     
    -  return v;
    -};

    Parameters:


    SchemaType#select(val)

    Sets default select() behavior for this path.

    show code
    SchemaType.prototype.select = function select (val) {
    -  this.selected = !! val;
    -}

    Parameters:

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    + var fields; + if (options) { + fields = options.select; + options.select = undefined; + } -

    Example:

    + var mq = new this.Query({}, {}, this, this.collection); + mq.select(fields); -
    T = db.model('T', new Schema({ x: { type: String, select: true }}));
    -T.find(..); // field x will always be selected ..
    -// .. unless overridden;
    -T.find().select('-x').exec(callback);

    SchemaType#doValidate(value, callback, scope)

    Performs a validation of value using the validators declared for this SchemaType.

    show code
    SchemaType.prototype.doValidate = function (value, fn, scope) {
    -  var err = false
    -    , path = this.path
    -    , count = this.validators.length;
    +  return mq.findOneAndRemove(conditions, options, callback);
    +};

    Parameters:

    Returns:

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    + +

    Executes immediately if callback is passed else a Query object is returned.

    - if (!count) return fn(null); +

    Options:

    - function validate (val, msg) { - if (err) return; - if (val === undefined || val) { - --count || fn(null); - } else { - fn(err = new ValidatorError(path, msg)); + + +

    Examples:

    + +
    A.findOneAndRemove(conditions, options, callback) // executes
    +A.findOneAndRemove(conditions, options)  // return Query
    +A.findOneAndRemove(conditions, callback) // executes
    +A.findOneAndRemove(conditions) // returns Query
    +A.findOneAndRemove()           // returns Query
    + +

    Values are cast to their appropriate types when using the findAndModify helpers.
    However, the below are not executed by default.

    + +
      +
    • defaults. Use the setDefaultsOnInsert option to override.
    • +
    • setters. Use the runSettersOnQuery option to override.
    • +
    + +

    findAndModify helpers support limited validation. You can
    enable these by setting the runValidators options,
    respectively.

    + +

    If you need full-fledged validation, use the traditional approach of first
    retrieving the document.

    + +
    Model.findById(id, function (err, doc) {
    +  if (err) ..
    +  doc.name = 'jason borne';
    +  doc.save(callback);
    +});

    Model.findOneAndUpdate([conditions], [update], [options], [callback])

    Issues a mongodb findAndModify update command.

    show code
    Model.findOneAndUpdate = function(conditions, update, options, callback) {
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
    +  } else if (arguments.length === 1) {
    +    if (typeof conditions === 'function') {
    +      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
    +
    +'
    +          + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
    +'
    +          + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
    +'
    +          + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
    +'
    +          + '  ' + this.modelName + '.findOneAndUpdate(update)
    +'
    +          + '  ' + this.modelName + '.findOneAndUpdate()
    +';
    +      throw new TypeError(msg);
         }
    +    update = conditions;
    +    conditions = undefined;
    +  }
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
       }
     
    -  this.validators.forEach(function (v) {
    -    var validator = v[0]
    -      , message   = v[1];
    +  var fields;
    +  if (options && options.fields) {
    +    fields = options.fields;
    +  }
     
    -    if (validator instanceof RegExp) {
    -      validate(validator.test(value), message);
    -    } else if ('function' === typeof validator) {
    -      if (2 === validator.length) {
    -        validator.call(scope, value, function (val) {
    -          validate(val, message);
    -        });
    -      } else {
    -        validate(validator.call(scope, value), message);
    -      }
    +  update = utils.clone(update, {depopulate: 1, _isNested: true});
    +  if (this.schema.options.versionKey && options && options.upsert) {
    +    if (!update.$setOnInsert) {
    +      update.$setOnInsert = {};
         }
    -  });
    -};

    Parameters:


    SchemaType._isRef(self, value, init)

    Determines if value is a valid Reference.

    show code
    SchemaType._isRef = function (self, value, init) {
    -  if (init && self.options && self.options.ref) {
    -    if (null == value) return true;
    -    if (value._id && value._id.constructor.name === self.instance) return true;
    +    update.$setOnInsert[this.schema.options.versionKey] = 0;
       }
     
    -  return false;
    -}

    Parameters:

    Returns:


  • types/array.js

    MongooseArray(values, path, doc)

    Mongoose Array constructor.

    show code
    function MongooseArray (values, path, doc) {
    -  var arr = [];
    -  arr.push.apply(arr, values);
    -  arr.__proto__ = MongooseArray.prototype;
    +  var mq = new this.Query({}, {}, this, this.collection);
    +  mq.select(fields);
     
    -  arr._atomics = {};
    -  arr.validators = [];
    -  arr._path = path;
    +  return mq.findOneAndUpdate(conditions, update, options, callback);
    +};

    Parameters:

    Returns:

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    - if (doc) { - arr._parent = doc; - arr._schema = doc.schema.path(path); - } +

    Options:

    - return arr; -};

    Parameters:

    Inherits:

    NOTE:

    +
      +
    • new: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0)
    • +
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • +
    • fields: {Object|String} - Field selection. Equivalent to .select(fields).findOneAndUpdate()
    • +
    • maxTimeMS: puts a time limit on the query - requires mongodb >= 2.6.0
    • +
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • +
    • runValidators: if true, runs update validators on this command. Update validators validate the update operation against the model's schema.
    • +
    • setDefaultsOnInsert: if this and upsert are true, mongoose will apply the defaults specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on MongoDB's $setOnInsert operator.
    • +
    • passRawResult: if true, passes the raw result from the MongoDB driver as the third callback parameter
    • +
    • strict: overwrites the schema's strict mode option for this update
    • +
    • runSettersOnQuery: bool - if true, run all setters defined on the associated model's schema for all fields defined in the query and the update.
    • +
    + +

    Examples:

    + +
    A.findOneAndUpdate(conditions, update, options, callback) // executes
    +A.findOneAndUpdate(conditions, update, options)  // returns Query
    +A.findOneAndUpdate(conditions, update, callback) // executes
    +A.findOneAndUpdate(conditions, update)           // returns Query
    +A.findOneAndUpdate()                             // returns Query
    + +

    Note:

    + +

    All top level update keys which are not atomic operation names are treated as set operations:

    + +

    Example:

    + +
    var query = { name: 'borne' };
    +Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
    +
    +// is sent as
    +Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
    + +

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    + +

    Note:

    -

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


    MongooseArray#_cast(value)

    Casts a member based on this arrays schema.

    show code
    MongooseArray.prototype._cast = function (value) {
    -  var cast = this._schema.caster.cast
    -    , doc = this._parent;
    +

    Values are cast to their appropriate types when using the findAndModify helpers.
    However, the below are not executed by default.

    - return cast.call(null, value, doc); -};

    Parameters:

    Returns:

    • <value> the casted value

    MongooseArray#_markModified(embeddedDoc, embeddedPath)

    Marks this array as modified.

    show code
    MongooseArray.prototype._markModified = function (elem, embeddedPath) {
    -  var parent = this._parent
    -    , dirtyPath;
    +
      +
    • defaults. Use the setDefaultsOnInsert option to override.
    • +
    • setters. Use the runSettersOnQuery option to override.
    • +
    - if (parent) { - dirtyPath = this._path; +

    findAndModify helpers support limited validation. You can
    enable these by setting the runValidators options,
    respectively.

    - if (arguments.length) { - if (null != embeddedPath) { - // an embedded doc bubbled up the change - dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath; - } else { - // directly set an index - dirtyPath = dirtyPath + '.' + elem; - } +

    If you need full-fledged validation, use the traditional approach of first
    retrieving the document.

    - } - parent.markModified(dirtyPath); +
    Model.findById(id, function (err, doc) {
    +  if (err) ..
    +  doc.name = 'jason borne';
    +  doc.save(callback);
    +});

    Model.geoNear(GeoJSON, options, [callback])

    geoNear support for Mongoose

    show code
    Model.geoNear = function(near, options, callback) {
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = {};
       }
     
    -  return this;
    -};

    Parameters:

    • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
    • embeddedPath <String> the path which changed in the embeddedDoc

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


    MongooseArray#_registerAtomic(op, val)

    Register an atomic operation with the parent.

    show code
    MongooseArray.prototype._registerAtomic = function (op, val) {
    -  if ('$set' == op) {
    -    // $set takes precedence over all other ops.
    -    // mark entire array modified.
    -    this._atomics = { $set: val };
    -    return this;
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
       }
     
    -  var atomics = this._atomics;
    -
    -  // reset pop/shift after save
    -  if ('$pop' == op && !('$pop' in atomics)) {
    -    var self = this;
    -    this._parent.once('save', function () {
    -      self._popped = self._shifted = null;
    +  var _this = this;
    +  var Promise = PromiseProvider.get();
    +  if (!near) {
    +    return new Promise.ES6(function(resolve, reject) {
    +      var error = new Error('Must pass a near option to geoNear');
    +      reject(error);
    +      callback && callback(error);
         });
       }
     
    -  // check for impossible $atomic combos (Mongo denies more than one
    -  // $atomic op on a single path
    -  if (this._atomics.$set ||
    -      Object.keys(atomics).length && !(op in atomics)) {
    -    // a different op was previously registered.
    -    // save the entire thing.
    -    this._atomics = { $set: this };
    -    return this;
    -  }
    +  var x, y;
     
    -  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
    -    atomics[op] || (atomics[op] = []);
    -    atomics[op] = atomics[op].concat(val);
    -  } else if (op === '$pullDocs') {
    -    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
    -      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
    -    selector['$in'] = selector['$in'].concat(val);
    -  } else {
    -    atomics[op] = val;
    -  }
    +  return new Promise.ES6(function(resolve, reject) {
    +    var handler = function(err, res) {
    +      if (err) {
    +        reject(err);
    +        callback && callback(err);
    +        return;
    +      }
    +      if (options.lean) {
    +        resolve(res.results, res.stats);
    +        callback && callback(null, res.results, res.stats);
    +        return;
    +      }
     
    -  return this;
    -};

    Parameters:


    MongooseArray#hasAtomics()

    Returns the number of pending atomic operations to send to the db for this array.

    show code
    MongooseArray.prototype.hasAtomics = function hasAtomics () {
    -  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
    -    return 0;
    -  }
    +      var count = res.results.length;
    +      // if there are no results, fulfill the promise now
    +      if (count === 0) {
    +        resolve(res.results, res.stats);
    +        callback && callback(null, res.results, res.stats);
    +        return;
    +      }
     
    -  return Object.keys(this._atomics).length;
    -}

    Returns:


    MongooseArray#push([args...])

    Wraps Array#push with proper change tracking.

    show code
    MongooseArray.prototype.push = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , ret = [].push.apply(this, values);
    +      var errSeen = false;
     
    -  // $pushAll might be fibbed (could be $push). But it makes it easier to
    -  // handle what could have been $push, $pushAll combos
    -  this._registerAtomic('$pushAll', values);
    -  this._markModified();
    -  return ret;
    -};

    Parameters:


    MongooseArray#nonAtomicPush([args...])

    Pushes items to the array non-atomically.

    show code
    MongooseArray.prototype.nonAtomicPush = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , ret = [].push.apply(this, values);
    -  this._registerAtomic('$set', this);
    -  this._markModified();
    -  return ret;
    -};

    Parameters:

    • [args...] <any>

    NOTE:

    + function init(err) { + if (err && !errSeen) { + errSeen = true; + reject(err); + callback && callback(err); + return; + } + if (--count <= 0) { + resolve(res.results, res.stats); + callback && callback(null, res.results, res.stats); + } + } -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#$pop()

    Pops the array atomically at most one time per document save().

    NOTE:

    + for (var i = 0; i < res.results.length; i++) { + var temp = res.results[i].obj; + res.results[i].obj = new _this(); + res.results[i].obj.init(temp, init); + } + }; -

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    + if (Array.isArray(near)) { + if (near.length !== 2) { + var error = new Error('If using legacy coordinates, must be an array ' + + 'of size 2 for geoNear'); + reject(error); + callback && callback(error); + return; + } + x = near[0]; + y = near[1]; + _this.collection.geoNear(x, y, options, handler); + } else { + if (near.type !== 'Point' || !Array.isArray(near.coordinates)) { + error = new Error('Must pass either a legacy coordinate array or ' + + 'GeoJSON Point to geoNear'); + reject(error); + callback && callback(error); + return; + } -
    doc.array = [1,2,3];
    +      _this.collection.geoNear(near, options, handler);
    +    }
    +  });
    +};

    Parameters:

    • GeoJSON <Object, Array> point or legacy coordinate pair [x,y] to search near
    • options <Object> for the query
    • [callback] <Function> optional callback for the query

    Returns:

    Options:

    - var popped = doc.array.$pop(); - console.log(popped); // 3 - console.log(doc.array); // [1,2] +
      +
    • lean {Boolean} return the raw object
    • +
    • All options supported by the driver are also supported
    • +
    - // no affect - popped = doc.array.$pop(); - console.log(doc.array); // [1,2] +

    Example:

    - doc.save(function (err) { - if (err) return handleError(err); +
    // Legacy point
    +Model.geoNear([1,3], { maxDistance : 5, spherical : true }, function(err, results, stats) {
    +   console.log(results);
    +});
     
    -   // we saved, now $pop works again
    -   popped = doc.array.$pop();
    -   console.log(popped); // 2
    -   console.log(doc.array); // [1]
    - })

    MongooseArray#pop()

    Wraps Array#pop with proper change tracking.

    show code
    MongooseArray.prototype.pop = function () {
    -  var ret = [].pop.call(this);
    -  this._registerAtomic('$set', this);
    -  this._markModified();
    -  return ret;
    -};

    Note:

    +// geoJson +var point = { type : "Point", coordinates : [9,9] }; +Model.geoNear(point, { maxDistance : 5, spherical : true }, function(err, results, stats) { + console.log(results); +});

    Model.geoSearch(conditions, options, [callback])

    Implements $geoSearch functionality for Mongoose

    show code
    Model.geoSearch = function(conditions, options, callback) {
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = {};
    +  }
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
    +  }
    +
    +  var _this = this;
    +  var Promise = PromiseProvider.get();
    +  return new Promise.ES6(function(resolve, reject) {
    +    var error;
    +    if (conditions === undefined || !utils.isObject(conditions)) {
    +      error = new Error('Must pass conditions to geoSearch');
    +    } else if (!options.near) {
    +      error = new Error('Must specify the near option in geoSearch');
    +    } else if (!Array.isArray(options.near)) {
    +      error = new Error('near option must be an array [x, y]');
    +    }
     
    -

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#$shift()

    Atomically shifts the array at most one time per document save().

    NOTE:

    + if (error) { + callback && callback(error); + reject(error); + return; + } -

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    + // send the conditions in the options object + options.search = conditions; -
    doc.array = [1,2,3];
    +    _this.collection.geoHaystackSearch(options.near[0], options.near[1], options, function(err, res) {
    +      // have to deal with driver problem. Should be fixed in a soon-ish release
    +      // (7/8/2013)
    +      if (err) {
    +        callback && callback(err);
    +        reject(err);
    +        return;
    +      }
     
    - var shifted = doc.array.$shift();
    - console.log(shifted); // 1
    - console.log(doc.array); // [2,3]
    +      var count = res.results.length;
    +      if (options.lean || count === 0) {
    +        callback && callback(null, res.results, res.stats);
    +        resolve(res.results, res.stats);
    +        return;
    +      }
     
    - // no affect
    - shifted = doc.array.$shift();
    - console.log(doc.array); // [2,3]
    +      var errSeen = false;
     
    - doc.save(function (err) {
    -   if (err) return handleError(err);
    +      function init(err) {
    +        if (err && !errSeen) {
    +          callback && callback(err);
    +          reject(err);
    +          return;
    +        }
     
    -   // we saved, now $shift works again
    -   shifted = doc.array.$shift();
    -   console.log(shifted ); // 2
    -   console.log(doc.array); // [3]
    - })

    MongooseArray#shift()

    Wraps Array#shift with proper change tracking.

    show code
    MongooseArray.prototype.shift = function () {
    -  var ret = [].shift.call(this);
    -  this._registerAtomic('$set', this);
    -  this._markModified();
    -  return ret;
    -};

    Example:

    + if (!--count && !errSeen) { + callback && callback(null, res.results, res.stats); + resolve(res.results, res.stats); + } + } -
    doc.array = [2,3];
    -var res = doc.array.shift();
    -console.log(res) // 2
    -console.log(doc.array) // [3]
    + for (var i = 0; i < res.results.length; i++) { + var temp = res.results[i]; + res.results[i] = new _this(); + res.results[i].init(temp, {}, init); + } + }); + }); +};

    Parameters:

    • conditions <Object> an object that specifies the match condition (required)
    • options <Object> for the geoSearch, some (near, maxDistance) are required
    • [callback] <Function> optional callback

    Returns:

    Example:

    -

    Note:

    +
    var options = { near: [10, 10], maxDistance: 5 };
    +Locations.geoSearch({ type : "house" }, options, function(err, res) {
    +  console.log(res);
    +});
    -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#remove([args...])

    Removes items from an array atomically

    show code
    MongooseArray.prototype.remove = function () {
    -  var args = [].map.call(arguments, this._cast, this);
    -  if (args.length == 1)
    -    this.pull(args[0]);
    -  else
    -    this.pull.apply(this, args);
    -  return args;
    -};

    Parameters:

    • [args...] <Object> values to remove

    Examples:

    - -
    doc.array.remove(ObjectId)
    -doc.array.remove('tag 1', 'tag 2')

    MongooseArray#pull([args...])

    Pulls items from the array atomically.

    show code
    MongooseArray.prototype.pull = function () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , cur = this._parent.get(this._path)
    -    , i = cur.length
    -    , mem;
    +

    Options:

    - while (i--) { - mem = cur[i]; - if (mem instanceof EmbeddedDocument) { - if (values.some(function (v) { return v.equals(mem); } )) { - [].splice.call(cur, i, 1); - } - } else if (~cur.indexOf.call(values, mem)) { - [].splice.call(cur, i, 1); - } +
      +
    • near {Array} x,y point to search for
    • +
    • maxDistance {Number} the maximum distance from the point near that a result can be
    • +
    • limit {Number} The maximum number of results to return
    • +
    • lean {Boolean} return the raw object instead of the Mongoose Model
    • +

    Model.hydrate(obj)

    Shortcut for creating a new Document from existing raw data, pre-saved in the DB.
    The document returned has no paths marked as modified initially.

    show code
    Model.hydrate = function(obj) {
    +  var model = require('./queryhelpers').createModel(this, obj);
    +  model.init(obj);
    +  return model;
    +};

    Parameters:

    Returns:

    Example:

    + +
    // hydrate previous data into a Mongoose document
    +var mongooseCandy = Candy.hydrate({ _id: '54108337212ffb6d459f854c', type: 'jelly bean' });

    Model.init()

    Called when the model compiles.

    show code
    Model.init = function init() {
    +  if ((this.schema.options.autoIndex) ||
    +      (this.schema.options.autoIndex == null && this.db.config.autoIndex)) {
    +    this.ensureIndexes({ __noPromise: true, _automatic: true });
       }
     
    -  if (values[0] instanceof EmbeddedDocument) {
    -    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
    -  } else {
    -    this._registerAtomic('$pullAll', values);
    +  this.schema.emit('init', this);
    +};

    Model.insertMany(doc(s), [options], [callback])

    Shortcut for validating an array of documents and inserting them into
    MongoDB if they're all valid. This function is faster than .create()
    because it only sends one operation to the server, rather than one for each
    document.

    show code
    Model.insertMany = function(arr, options, callback) {
    +  var _this = this;
    +  if (typeof options === 'function') {
    +    callback = options;
    +    options = null;
    +  }
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
    +  }
    +  var limit = options && options.limit;
    +  if (typeof limit !== 'number') {
    +    limit = 1000;
       }
     
    -  this._markModified();
    -  return this;
    -};

    Parameters:

    • [args...] <any>

    MongooseArray#splice()

    Wraps Array#splice with proper change tracking and casting.

    show code
    MongooseArray.prototype.splice = function splice () {
    -  var ret, vals, i;
    +  if (!Array.isArray(arr)) {
    +    arr = [arr];
    +  }
     
    -  if (arguments.length) {
    -    vals = [];
    -    for (i = 0; i < arguments.length; ++i) {
    -      vals[i] = i < 2
    -        ? arguments[i]
    -        : this._cast(arguments[i]);
    +  var toExecute = [];
    +  arr.forEach(function(doc) {
    +    toExecute.push(function(callback) {
    +      doc = new _this(doc);
    +      doc.validate({ __noPromise: true }, function(error) {
    +        if (error) {
    +          // Option `ordered` signals that insert should be continued after reaching
    +          // a failing insert. Therefore we delegate "null", meaning the validation
    +          // failed. It's up to the next function to filter out all failed models
    +          if (options != null && typeof options === 'object' && options['ordered'] === false) {
    +            return callback(null, null);
    +          }
    +          return callback(error);
    +        }
    +        callback(null, doc);
    +      });
    +    });
    +  });
    +
    +  parallelLimit(toExecute, limit, function(error, docs) {
    +    if (error) {
    +      callback && callback(error);
    +      return;
         }
    -    ret = [].splice.apply(this, vals);
    -    this._registerAtomic('$set', this);
    -    this._markModified();
    -  }
    +    // We filter all failed pre-validations by removing nulls
    +    var docAttributes = docs.filter(function(doc) {
    +      return doc != null;
    +    });
    +    // Quickly escape while there aren't any valid docAttributes
    +    if (docAttributes.length < 1) {
    +      callback && callback(null, []);
    +      return;
    +    }
    +    var docObjects = docAttributes.map(function(doc) {
    +      if (doc.schema.options.versionKey) {
    +        doc[doc.schema.options.versionKey] = 0;
    +      }
    +      if (doc.initializeTimestamps) {
    +        return doc.initializeTimestamps().toObject(INSERT_MANY_CONVERT_OPTIONS);
    +      }
    +      return doc.toObject(INSERT_MANY_CONVERT_OPTIONS);
    +    });
     
    -  return ret;
    -}

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#unshift()

    Wraps Array#unshift with proper change tracking.

    show code
    MongooseArray.prototype.unshift = function () {
    -  var values = [].map.call(arguments, this._cast, this);
    -  [].unshift.apply(this, values);
    -  this._registerAtomic('$set', this);
    -  this._markModified();
    -  return this.length;
    -};

    Note:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#sort()

    Wraps Array#sort with proper change tracking.

    show code
    MongooseArray.prototype.sort = function () {
    -  var ret = [].sort.apply(this, arguments);
    -  this._registerAtomic('$set', this);
    -  this._markModified();
    -  return ret;
    -}

    NOTE:

    - -

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


    MongooseArray#addToSet([args...])

    Adds values to the array if not already present.

    show code
    MongooseArray.prototype.addToSet = function addToSet () {
    -  var values = [].map.call(arguments, this._cast, this)
    -    , added = []
    -    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
    -             values[0] instanceof Date ? 'date' :
    -             '';
    -
    -  values.forEach(function (v) {
    -    var found;
    -    switch (type) {
    -      case 'doc':
    -        found = this.some(function(doc){ return doc.equals(v) });
    -        break;
    -      case 'date':
    -        var val = +v;
    -        found = this.some(function(d){ return +d === val });
    -        break;
    -      default:
    -        found = ~this.indexOf(v);
    +    _this.collection.insertMany(docObjects, options, function(error) {
    +      if (error) {
    +        callback && callback(error);
    +        return;
    +      }
    +      for (var i = 0; i < docAttributes.length; ++i) {
    +        docAttributes[i].isNew = false;
    +        docAttributes[i].emit('isNew', false);
    +        docAttributes[i].constructor.emit('isNew', false);
    +      }
    +      callback && callback(null, docAttributes);
    +    });
    +  });
    +};

    Parameters:

    • doc(s) <Array, Object, *>
    • [options] <Object> see the <a href="http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#insertMany">mongodb driver options</a>
    • [callback] <Function> callback

    Returns:

    This function does not trigger save middleware.

    + +

    Example:

    + +
    var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }];
    +Movies.insertMany(arr, function(error, docs) {});

    Model.mapReduce(o, [callback])

    Executes a mapReduce command.

    show code
    Model.mapReduce = function mapReduce(o, callback) {
    +  var _this = this;
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
    +  }
    +  var resolveToObject = o.resolveToObject;
    +  var Promise = PromiseProvider.get();
    +  return new Promise.ES6(function(resolve, reject) {
    +    if (!Model.mapReduce.schema) {
    +      var opts = {noId: true, noVirtualId: true, strict: false};
    +      Model.mapReduce.schema = new Schema({}, opts);
         }
     
    -    if (!found) {
    -      [].push.call(this, v);
    -      this._registerAtomic('$addToSet', v);
    -      this._markModified();
    -      [].push.call(added, v);
    +    if (!o.out) o.out = {inline: 1};
    +    if (o.verbose !== false) o.verbose = true;
    +
    +    o.map = String(o.map);
    +    o.reduce = String(o.reduce);
    +
    +    if (o.query) {
    +      var q = new _this.Query(o.query);
    +      q.cast(_this);
    +      o.query = q._conditions;
    +      q = undefined;
         }
    -  }, this);
     
    -  return added;
    -};

    Parameters:

    • [args...] <any>

    Returns:

    • <Array> the values that were added

    Example:

    + _this.collection.mapReduce(null, null, o, function(err, ret, stats) { + if (err) { + callback && callback(err); + reject(err); + return; + } -
    console.log(doc.array) // [2,3,4]
    -var added = doc.array.addToSet(4,5);
    -console.log(doc.array) // [2,3,4,5]
    -console.log(added)     // [5]

    MongooseArray#set()

    Sets the casted val at index i and marks the array modified.

    show code
    MongooseArray.prototype.set = function set (i, val) {
    -  this[i] = this._cast(val);
    -  this._markModified(i);
    -  return this;
    -}

    Returns:

    Example:

    + if (ret.findOne && ret.mapReduce) { + // returned a collection, convert to Model + var model = Model.compile( + '_mapreduce_' + ret.collectionName + , Model.mapReduce.schema + , ret.collectionName + , _this.db + , _this.base); + + model._mapreduce = true; + + callback && callback(null, model, stats); + return resolveToObject ? resolve({ + model: model, + stats: stats + }) : resolve(model, stats); + } -
    // given documents based on the following
    -var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
    +      callback && callback(null, ret, stats);
    +      if (resolveToObject) {
    +        return resolve({ model: ret, stats: stats });
    +      }
    +      resolve(ret, stats);
    +    });
    +  });
    +};

    Parameters:

    • o <Object> an object specifying map-reduce options
    • [callback] <Function> optional callback

    Returns:

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation. See node-mongodb-native mapReduce() documentation for more detail about options.

    -var doc = new Doc({ array: [2,3,4] }) +

    Example:

    -console.log(doc.array) // [2,3,4] +
    var o = {};
    +o.map = function () { emit(this.name, 1) }
    +o.reduce = function (k, vals) { return vals.length }
    +User.mapReduce(o, function (err, results) {
    +  console.log(results)
    +})
    -doc.array.set(1,"5"); -console.log(doc.array); // [2,5,4] // properly cast to number -doc.save() // the change is saved +

    Other options:

    -// VS not using array#set -doc.array[1] = "5"; -console.log(doc.array); // [2,"5",4] // no casting -doc.save() // change is not saved

    MongooseArray#toObject(options)

    Returns a native js Array.

    show code
    MongooseArray.prototype.toObject = function (options) {
    -  if (options && options.depopulate && this[0] instanceof Document) {
    -    return this.map(function (doc) {
    -      return doc._id;
    -    });
    -  }
    +
      +
    • query {Object} query filter object.
    • +
    • sort {Object} sort input objects using this key
    • +
    • limit {Number} max number of documents
    • +
    • keeptemp {Boolean, default:false} keep temporary data
    • +
    • finalize {Function} finalize function
    • +
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • +
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • +
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • +
    • readPreference {String}
    • +
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • +
    - // return this.slice()? - return this.map(function (doc) { - return doc; - }); -};

    Parameters:

    Returns:


    MongooseArray#inspect()

    Helper for console.log

    show code
    MongooseArray.prototype.inspect = function () {
    -  return '[' + this.map(function (doc) {
    -    return ' ' + doc;
    -  }) + ' ]';
    -};

    MongooseArray#indexOf(obj)

    Return the index of obj or -1 if not found.

    show code
    MongooseArray.prototype.indexOf = function indexOf (obj) {
    -  if (obj instanceof ObjectId) obj = obj.toString();
    -  for (var i = 0, len = this.length; i < len; ++i) {
    -    if (obj == this[i])
    -      return i;
    -  }
    -  return -1;
    -};

    Parameters:

    • obj <Object> the item to look for

    Returns:


    MongooseArray#_parent

    Parent owner document


    MongooseArray#_atomics

    Stores a queue of atomic operations to perform


  • types/buffer.js

    MongooseBuffer(value, encode, offset)

    Mongoose Buffer constructor.

    show code
    function MongooseBuffer (value, encode, offset) {
    -  var length = arguments.length;
    -  var val;
    +

    * out options:

    - if (0 === length || null === arguments[0] || undefined === arguments[0]) { - val = 0; - } else { - val = value; - } +
      +
    • {inline:1} the results are returned in an array
    • +
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • +
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • +
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • +
    - var encoding; - var path; - var doc; +

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    - if (Array.isArray(encode)) { - // internal casting - path = encode[0]; - doc = encode[1]; - } else { - encoding = encode; - } +

    Example:

    - var buf = new Buffer(val, encoding, offset); - buf.__proto__ = MongooseBuffer.prototype; +
    var o = {};
    +o.map = function () { emit(this.name, 1) }
    +o.reduce = function (k, vals) { return vals.length }
    +o.out = { replace: 'createdCollectionNameForResults' }
    +o.verbose = true;
     
    -  // make sure these internal props don't show up in Object.keys()
    -  Object.defineProperties(buf, {
    -      validators: { value: [] }
    -    , _path: { value: path }
    -    , _parent: { value: doc }
    +User.mapReduce(o, function (err, model, stats) {
    +  console.log('map reduce took %d ms', stats.processtime)
    +  model.find().where('value').gt(10).exec(function (err, docs) {
    +    console.log(docs);
       });
    +})
     
    -  if (doc && "string" === typeof path) {
    -    Object.defineProperty(buf, '_schema', {
    -        value: doc.schema.path(path)
    -    });
    +// `mapReduce()` returns a promise. However, ES6 promises can only
    +// resolve to exactly one value,
    +o.resolveToObject = true;
    +var promise = User.mapReduce(o);
    +promise.then(function (res) {
    +  var model = res.model;
    +  var stats = res.stats;
    +  console.log('map reduce took %d ms', stats.processtime)
    +  return model.find().where('value').gt(10).exec();
    +}).then(function (docs) {
    +   console.log(docs);
    +}).then(null, handleError).end()

    Model.populate(docs, options, [callback(err,doc)])

    Populates document references.

    show code
    Model.populate = function(docs, paths, callback) {
    +  var _this = this;
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
       }
     
    -  return buf;
    -};

    Parameters:

    Inherits:

    Values always have to be passed to the constructor to initialize.


    MongooseBuffer#_markModified()

    Marks this buffer as modified.

    show code
    MongooseBuffer.prototype._markModified = function () {
    -  var parent = this._parent;
    +  // normalized paths
    +  var noPromise = paths && !!paths.__noPromise;
    +  paths = utils.populate(paths);
     
    -  if (parent) {
    -    parent.markModified(this._path);
    -  }
    -  return this;
    -};

    MongooseBuffer#write()

    Writes the buffer.

    show code
    MongooseBuffer.prototype.write = function () {
    -  var written = Buffer.prototype.write.apply(this, arguments);
    +  // data that should persist across subPopulate calls
    +  var cache = {};
     
    -  if (written > 0) {
    -    this._markModified();
    +  if (noPromise) {
    +    _populate(this, docs, paths, cache, callback);
    +  } else {
    +    var Promise = PromiseProvider.get();
    +    return new Promise.ES6(function(resolve, reject) {
    +      _populate(_this, docs, paths, cache, function(error, docs) {
    +        if (error) {
    +          callback && callback(error);
    +          reject(error);
    +        } else {
    +          callback && callback(null, docs);
    +          resolve(docs);
    +        }
    +      });
    +    });
       }
    +};

    Parameters:

    • docs <Document, Array> Either a single document or array of documents to populate.
    • options <Object> A hash of key/val (path, options) used for population.
    • [callback(err,doc)] <Function> Optional callback, executed upon completion. Receives <code>err</code> and the <code>doc(s)</code>.

    Returns:

    Available options:

    - return written; -};

    MongooseBuffer#copy(target)

    Copies the buffer.

    show code
    MongooseBuffer.prototype.copy = function (target) {
    -  var ret = Buffer.prototype.copy.apply(this, arguments);
    +
      +
    • path: space delimited path(s) to populate
    • +
    • select: optional fields to select
    • +
    • match: optional query conditions to match
    • +
    • model: optional name of the model to use for population
    • +
    • options: optional query options like sort, limit, etc
    • +
    - if (target instanceof MongooseBuffer) { - target._markModified(); - } +

    Examples:

    - return ret; -};

    Parameters:

    Returns:

    Note:

    +
    // populates a single object
    +User.findById(id, function (err, user) {
    +  var opts = [
    +      { path: 'company', match: { x: 1 }, select: 'name' }
    +    , { path: 'notes', options: { limit: 10 }, model: 'override' }
    +  ]
     
    -

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


    MongooseBuffer#toObject([subtype])

    Converts this buffer to its Binary type representation.

    show code
    MongooseBuffer.prototype.toObject = function (subtype) {
    -  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
    -  return new Binary(this, subtype);
    -};

    Parameters:

    • [subtype] <Hex>

    Returns:

    SubTypes:

    + User.populate(user, opts, function (err, user) { + console.log(user); + }); +}); -
      -
    • 0x00: Binary/Generic
    • -
    • 0x01: Function
    • -
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • -
    • 0x03: UUID
    • -
    • 0x04: MD5
    • -
    • 0x80: User Defined
    • -

    MongooseBuffer#_parent

    Parent owner document


  • types/documentarray.js

    MongooseDocumentArray(values, path, doc)

    DocumentArray constructor

    show code
    function MongooseDocumentArray (values, path, doc) {
    -  var arr = [];
    +// populates an array of objects
    +User.find(match, function (err, users) {
    +  var opts = [{ path: 'company', match: { x: 1 }, select: 'name' }]
     
    -  // Values always have to be passed to the constructor to initialize, since
    -  // otherwise MongooseArray#push will mark the array as modified to the parent.
    -  arr.push.apply(arr, values);
    -  arr.__proto__ = MongooseDocumentArray.prototype;
    +  var promise = User.populate(users, opts);
    +  promise.then(console.log).end();
    +})
     
    -  arr._atomics = {};
    -  arr.validators = [];
    -  arr._path = path;
    +// imagine a Weapon model exists with two saved documents:
    +//   { _id: 389, name: 'whip' }
    +//   { _id: 8921, name: 'boomerang' }
    +// and this schema:
    +// new Schema({
    +//   name: String,
    +//   weapon: { type: ObjectId, ref: 'Weapon' }
    +// });
    +
    +var user = { name: 'Indiana Jones', weapon: 389 }
    +Weapon.populate(user, { path: 'weapon', model: 'Weapon' }, function (err, user) {
    +  console.log(user.weapon.name) // whip
    +})
     
    -  if (doc) {
    -    arr._parent = doc;
    -    arr._schema = doc.schema.path(path);
    -    doc.on('save', arr.notify('save'));
    -    doc.on('isNew', arr.notify('isNew'));
    +// populate many plain objects
    +var users = [{ name: 'Indiana Jones', weapon: 389 }]
    +users.push({ name: 'Batman', weapon: 8921 })
    +Weapon.populate(users, { path: 'weapon' }, function (err, users) {
    +  users.forEach(function (user) {
    +    console.log('%s uses a %s', users.name, user.weapon.name)
    +    // Indiana Jones uses a whip
    +    // Batman uses a boomerang
    +  });
    +});
    +// Note that we didn't need to specify the Weapon model because
    +// it is in the schema's ref

    Model.remove(conditions, [callback])

    Removes all documents that match conditions from the collection.
    To remove just the first document that matches conditions, set the single
    option to true.

    show code
    Model.remove = function remove(conditions, callback) {
    +  if (typeof conditions === 'function') {
    +    callback = conditions;
    +    conditions = {};
       }
     
    -  return arr;
    -};

    Parameters:

    Inherits:


    MongooseDocumentArray#_cast()

    Overrides MongooseArray#cast

    show code
    MongooseDocumentArray.prototype._cast = function (value) {
    -  if (value instanceof this._schema.casterConstructor)
    -    return value;
    -
    -  return new this._schema.casterConstructor(value, this);
    -};

    MongooseDocumentArray#id(id)

    Searches array items for the first document with a matching id.

    show code
    MongooseDocumentArray.prototype.id = function (id) {
    -  var casted
    -    , _id;
    +  // get the mongodb collection object
    +  var mq = new this.Query({}, {}, this, this.collection);
     
    -  try {
    -    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
    -  } catch (e) {
    -    casted = null;
    +  if (callback) {
    +    callback = this.$wrapCallback(callback);
       }
     
    -  for (var i = 0, l = this.length; i < l; i++) {
    -    _id = this[i].get('_id');
    -    if (!(_id instanceof ObjectId)) {
    -      if (String(id) == _id)
    -        return this[i];
    -    } else {
    -      if (casted == _id)
    -        return this[i];
    -    }
    -  }
    +  return mq.remove(conditions, callback);
    +};

    Parameters:

    Returns:

    Example:

    - return null; -};

    Parameters:

    Returns:

    Example:

    +
    Character.remove({ name: 'Eddard Stark' }, function (err) {});
    -
    var embeddedDoc = m.array.id(some_id);

    MongooseDocumentArray#toObject()

    Returns a native js Array of plain js objects

    show code
    MongooseDocumentArray.prototype.toObject = function () {
    -  return this.map(function (doc) {
    -    return doc && doc.toObject() || null;
    -  });
    -};

    Returns:

    NOTE:

    - -

    Each sub-document is converted to a plain object by calling its #toObject method.


    MongooseDocumentArray#inspect()

    Helper for console.log

    show code
    MongooseDocumentArray.prototype.inspect = function () {
    -  return '[' + this.map(function (doc) {
    -    if (doc) {
    -      return doc.inspect
    -        ? doc.inspect()
    -        : util.inspect(doc)
    -    }
    -    return 'null'
    -  }).join('
    -') + ']';
    -};

    MongooseDocumentArray#create(obj)

    Creates a subdocument casted to this schema.

    show code
    MongooseDocumentArray.prototype.create = function (obj) {
    -  return new this._schema.casterConstructor(obj);
    -}

    Parameters:

    • obj <Object> the value to cast to this arrays SubDocument schema

    This is the same subdocument constructor used for casting.


    MongooseDocumentArray#notify(event)

    Creates a fn that notifies all child docs of event.

    show code
    MongooseDocumentArray.prototype.notify = function notify (event) {
    -  var self = this;
    -  return function notify (val) {
    -    var i = self.length;
    -    while (i--) {
    -      if (!self[i]) continue;
    -      self[i].emit(event, val);
    +

    Note:

    + +

    This method sends a remove command directly to MongoDB, no Mongoose documents
    are involved. Because no Mongoose documents are involved, no middleware
    (hooks) are executed
    .


    Model.replaceOne(conditions, doc, [options], [callback])

    Same as update(), except MongoDB replace the existing document with the
    given document (no atomic operators like $set).

    show code
    Model.replaceOne = function replaceOne(conditions, doc, options, callback) {
    +  return _update(this, 'replaceOne', conditions, doc, options, callback);
    +};

    Parameters:

    Returns:


    Model.translateAliases(raw)

    Translate any aliases fields/conditions so the final query or document object is pure

    show code
    Model.translateAliases = function translateAliases(fields) {
    +  var aliases = this.schema.aliases;
    +
    +  if (typeof fields === 'object') {
    +    // Fields is an object (query conditions or document fields)
    +    for (var key in fields) {
    +      if (aliases[key]) {
    +        fields[aliases[key]] = fields[key];
    +        delete fields[key];
    +      }
         }
    -  }
    -}

    Parameters:

    Returns:


  • types/embedded.js

    EmbeddedDocument(obj, parentArr, skipId)

    EmbeddedDocument constructor.

    show code
    function EmbeddedDocument (obj, parentArr, skipId, fields) {
    -  if (parentArr) {
    -    this.__parentArray = parentArr;
    -    this.__parent = parentArr._parent;
    +
    +    return fields;
       } else {
    -    this.__parentArray = undefined;
    -    this.__parent = undefined;
    +    // Don't know typeof fields
    +    return fields;
       }
    +};

    Parameters:

    • raw <Object> fields/conditions that may contain aliased keys

    Returns:

    • <Object> the translated 'pure' fields/conditions

    Example:

    - Document.call(this, obj, fields, skipId); +
    Character
    +  .find(Character.translateAliases({
    +    '名': 'Eddard Stark' // Alias for 'name'
    +  })
    +  .exec(function(err, characters) {})
    - var self = this; - this.on('isNew', function (val) { - self.isNew = val; - }); -};

    Parameters:

    Inherits:


    EmbeddedDocument#markModified(path)

    Marks the embedded doc modified.

    show code
    EmbeddedDocument.prototype.markModified = function (path) {
    -  if (!this.__parentArray) return;
    +

    Note:

    - this._activePaths.modify(path); +

    Only translate arguments of object type anything else is returned raw


    Model.update(conditions, doc, [options], [callback])

    Updates one document in the database without returning it.

    show code
    Model.update = function update(conditions, doc, options, callback) {
    +  return _update(this, 'update', conditions, doc, options, callback);
    +};

    Parameters:

    Returns:

    Examples:

    - if (this.isNew) { - // Mark the WHOLE parent array as modified - // if this is a new document (i.e., we are initializing - // a document), - this.__parentArray._markModified(); - } else - this.__parentArray._markModified(this, path); -};

    Parameters:

    • path <String> the path which changed

    Example:

    +
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
    +MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, raw) {
    +  if (err) return handleError(err);
    +  console.log('The raw response from Mongo was ', raw);
    +});
    -
    var doc = blogpost.comments.id(hexstring);
    -doc.mixed.type = 'changed';
    -doc.markModified('mixed.type');

    EmbeddedDocument#save([fn])

    Used as a stub for hooks.js

    show code
    EmbeddedDocument.prototype.save = function(fn) {
    -  if (fn)
    -    fn(null);
    -  return this;
    -};

    Parameters:

    Returns:

    NOTE:

    +

    Valid options:

    -

    This is a no-op. Does not actually save the doc to the db.


    EmbeddedDocument#remove([fn])

    Removes the subdocument from its parent array.

    show code
    EmbeddedDocument.prototype.remove = function (fn) {
    -  if (!this.__parentArray) return this;
    +
      +
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • +
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • +
    • multi (boolean) whether multiple documents should be updated (false)
    • +
    • runValidators: if true, runs update validators on this command. Update validators validate the update operation against the model's schema.
    • +
    • setDefaultsOnInsert: if this and upsert are true, mongoose will apply the defaults specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on MongoDB's $setOnInsert operator.
    • +
    • strict (boolean) overrides the strict option for this update
    • +
    • overwrite (boolean) disables update-only mode, allowing you to overwrite the doc (false)
    • +
    - var _id; - if (!this.willRemove) { - _id = this._doc._id; - if (!_id) { - throw new Error('For your own good, Mongoose does not know ' + - 'how to remove an EmbeddedDocument that has no _id'); - } - this.__parentArray.pull({ _id: _id }); - this.willRemove = true; - } +

    All update values are cast to their appropriate SchemaTypes before being sent.

    - if (fn) - fn(null); +

    The callback function receives (err, rawResponse).

    - return this; -};

    Parameters:


    EmbeddedDocument#update()

    Override #update method of parent documents.

    show code
    EmbeddedDocument.prototype.update = function () {
    -  throw new Error('The #update method is not available on EmbeddedDocuments');
    -}

    EmbeddedDocument#inspect()

    Helper for console.log

    show code
    EmbeddedDocument.prototype.inspect = function () {
    -  return inspect(this.toObject());
    -};

    EmbeddedDocument#invalidate(path, err)

    Marks a path as invalid, causing validation to fail.

    show code
    EmbeddedDocument.prototype.invalidate = function (path, err, first) {
    -  if (!this.__parent) return false;
    -  var index = this.__parentArray.indexOf(this);
    -  var parentPath = this.__parentArray._path;
    -  var fullPath = [parentPath, index, path].join('.');
    -  this.__parent.invalidate(fullPath, err);
    -  if (first)
    -    this._validationError = ownerDocument(this)._validationError;
    -  return true;
    -}

    Parameters:

    • path <String> the field to invalidate
    • err <String, Error> error which states the reason `path` was invalid

    Returns:


    EmbeddedDocument#ownerDocument()

    Returns the top level document of this sub-document.

    show code
    EmbeddedDocument.prototype.ownerDocument = function () {
    -  return ownerDocument(this);
    -}

    Returns:


    EmbeddedDocument#parent()

    Returns this sub-documents parent document.

    show code
    EmbeddedDocument.prototype.parent = function () {
    -  return this.__parent;
    -}

    EmbeddedDocument#parentArray()

    Returns this sub-documents parent array.

    show code
    EmbeddedDocument.prototype.parentArray = function () {
    -  return this.__parentArray;
    -}

  • types/objectid.js

    ObjectId()

    ObjectId type constructor

    Example

    +
      +
    • err is the error if any occurred
    • +
    • rawResponse is the full response from Mongo
    • +
    -
    var id = new mongoose.Types.ObjectId;

    ObjectId.fromString(str)

    Creates an ObjectId from str

    show code
    ObjectId.fromString;

    Parameters:

    Returns:


    ObjectId.toString(oid)

    Converts oid to a string.

    show code
    ObjectId.toString;

    Parameters:

    Returns:


  • utils.js

    exports.toCollectionName(name)

    Produces a collection name from model name.

    show code
    exports.toCollectionName = function (name) {
    -  if ('system.profile' === name) return name;
    -  if ('system.indexes' === name) return name;
    -  return pluralize(name.toLowerCase());
    -};

    Parameters:

    Returns:


    exports.pluralization

    Pluralization rules.

    show code
    exports.pluralization = [
    -  [/(m)an$/gi, '$1en'],
    -  [/(pe)rson$/gi, '$1ople'],
    -  [/(child)$/gi, '$1ren'],
    -  [/^(ox)$/gi, '$1en'],
    -  [/(ax|test)is$/gi, '$1es'],
    -  [/(octop|vir)us$/gi, '$1i'],
    -  [/(alias|status)$/gi, '$1es'],
    -  [/(bu)s$/gi, '$1ses'],
    -  [/(buffal|tomat|potat)o$/gi, '$1oes'],
    -  [/([ti])um$/gi, '$1a'],
    -  [/sis$/gi, 'ses'],
    -  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
    -  [/(hive)$/gi, '$1s'],
    -  [/([^aeiouy]|qu)y$/gi, '$1ies'],
    -  [/(x|ch|ss|sh)$/gi, '$1es'],
    -  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
    -  [/([m|l])ouse$/gi, '$1ice'],
    -  [/(quiz)$/gi, '$1zes'],
    -  [/s$/gi, 's'],
    -  [/$/gi, 's']
    -];
    -var rules = exports.pluralization;

    These rules are applied while processing the argument to toCollectionName.


    exports.uncountables

    Uncountable words.

    show code
    exports.uncountables = [
    -  'advice',
    -  'energy',
    -  'excretion',
    -  'digestion',
    -  'cooperation',
    -  'health',
    -  'justice',
    -  'labour',
    -  'machinery',
    -  'equipment',
    -  'information',
    -  'pollution',
    -  'sewage',
    -  'paper',
    -  'money',
    -  'species',
    -  'series',
    -  'rain',
    -  'rice',
    -  'fish',
    -  'sheep',
    -  'moose',
    -  'deer',
    -  'news',
    -  'expertise',
    -  'status',
    -  'media'
    -];
    -var uncountables = exports.uncountables;

    These words are applied while processing the argument to toCollectionName.


    exports.deepEqual(a, b)

    Determines if a and b are deep equal.

    show code
    exports.deepEqual = function deepEqual (a, b) {
    -  if (a === b) return true;
    +

    Note:

    - if (a instanceof Date && b instanceof Date) - return a.getTime() === b.getTime(); +

    All top level keys which are not atomic operation names are treated as set operations:

    - if (a instanceof ObjectId && b instanceof ObjectId) { - return a.toString() === b.toString(); - } +

    Example:

    - if (typeof a !== 'object' && typeof b !== 'object') - return a == b; +
    var query = { name: 'borne' };
    +Model.update(query, { name: 'jason borne' }, options, callback)
     
    -  if (a === null || b === null || a === undefined || b === undefined)
    -    return false
    +// is sent as
    +Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
    +// if overwrite option is false. If overwrite is true, sent without the $set wrapper.
    - if (a.prototype !== b.prototype) return false; +

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    - // Handle MongooseNumbers - if (a instanceof Number && b instanceof Number) { - return a.valueOf() === b.valueOf(); - } +

    Note:

    - if (Buffer.isBuffer(a)) { - if (!Buffer.isBuffer(b)) return false; - if (a.length !== b.length) return false; - for (var i = 0, len = a.length; i < len; ++i) { - if (a[i] !== b[i]) return false; - } - return true; - } +

    Be careful to not use an existing model instance for the update clause (this won't work and can cause weird behavior like infinite loops). Also, ensure that the update clause does not have an _id property, which causes Mongo to return a "Mod on _id not allowed" error.

    - if (isMongooseObject(a)) a = a.toObject(); - if (isMongooseObject(b)) b = b.toObject(); +

    Note:

    - try { - var ka = Object.keys(a), - kb = Object.keys(b), - key, i; - } catch (e) {//happens when one is a string literal and the other isn't - return false; - } +

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    - // having the same number of owned properties (keys incorporates - // hasOwnProperty) - if (ka.length != kb.length) - return false; +
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
    - //the same set of keys (although not necessarily the same order), - ka.sort(); - kb.sort(); +

    Note:

    - //~~~cheap key test - for (i = ka.length - 1; i >= 0; i--) { - if (ka[i] != kb[i]) - return false; - } +

    Although values are casted to their appropriate types when using update, the following are not applied:

    - //equivalent values for every corresponding key, and - //~~~possibly expensive deep test - for (i = ka.length - 1; i >= 0; i--) { - key = ka[i]; - if (!deepEqual(a[key], b[key])) return false; - } +
      +
    • defaults
    • +
    • setters
    • +
    • validators
    • +
    • middleware
    • +
    - return true; -};

    Parameters:

    • a <any> a value to compare to `b`
    • b <any> a value to compare to `a`

    Returns:

    Modified from node/lib/assert.js


    exports.clone(obj, options)

    Object clone with Mongoose natives support.

    show code
    exports.clone = function clone (obj, options) {
    -  if (obj === undefined || obj === null)
    -    return obj;
    +

    If you need those features, use the traditional approach of first retrieving the document.

    - if (Array.isArray(obj)) - return cloneArray(obj, options); +
    Model.findOne({ name: 'borne' }, function (err, doc) {
    +  if (err) ..
    +  doc.name = 'jason borne';
    +  doc.save(callback);
    +})

    Model.updateMany(conditions, doc, [options], [callback])

    Same as update(), except MongoDB will update all documents that match
    criteria (as opposed to just the first one) regardless of the value of
    the multi option.

    show code
    Model.updateMany = function updateMany(conditions, doc, options, callback) {
    +  return _update(this, 'updateMany', conditions, doc, options, callback);
    +};

    Parameters:

    Returns:

    Note updateMany will not fire update middleware. Use pre('updateMany')
    and post('updateMany') instead.


    Model.updateOne(conditions, doc, [options], [callback])

    Same as update(), except MongoDB will update only the first document that
    matches criteria regardless of the value of the multi option.

    show code
    Model.updateOne = function updateOne(conditions, doc, options, callback) {
    +  return _update(this, 'updateOne', conditions, doc, options, callback);
    +};

    Parameters:

    Returns:


    Model.where(path, [val])

    Creates a Query, applies the passed conditions, and returns the Query.

    show code
    Model.where = function where(path, val) {
    +  void val; // eslint
    +  // get the mongodb collection object
    +  var mq = new this.Query({}, {}, this, this.collection).find({});
    +  return mq.where.apply(mq, arguments);
    +};

    Parameters:

    Returns:

    For example, instead of writing:

    - if (isMongooseObject(obj)) { - if (options && options.json && 'function' === typeof obj.toJSON) { - return obj.toJSON(options); - } else { - return obj.toObject(options); - } - } +
    User.find({age: {$gte: 21, $lte: 65}}, callback);
    - if ('Object' === obj.constructor.name) - return cloneObject(obj, options); +

    we can instead write:

    - if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name) - return new obj.constructor(+obj); +
    User.where('age').gte(21).lte(65).exec(callback);
    - if ('RegExp' === obj.constructor.name) - return new RegExp(obj.source); +

    Since the Query class also supports where you can continue chaining

    - if (obj instanceof ObjectId) { - return new ObjectId(obj.id); +
    User
    +.where('age').gte(21).lte(65)
    +.where('name', /^b/i)
    +... etc

    Model#$where

    Additional properties to attach to the query when calling save() and
    isNew is false.

    show code
    Model.prototype.$where;

    Model#base

    Base Mongoose instance the model uses.

    show code
    Model.base;

    Model#baseModelName

    If this is a discriminator model, baseModelName is the name of
    the base model.

    show code
    Model.prototype.baseModelName;
    +
    +Model.prototype.$__handleSave = function(options, callback) {
    +  var _this = this;
    +  var i;
    +  var keys;
    +  var len;
    +  if (!options.safe && this.schema.options.safe) {
    +    options.safe = this.schema.options.safe;
       }
    +  if (typeof options.safe === 'boolean') {
    +    options.safe = null;
    +  }
    +  var safe = options.safe ? utils.clone(options.safe, { retainKeyOrder: true }) : options.safe;
     
    -  if (obj.valueOf)
    -    return obj.valueOf();
    -};
    -var clone = exports.clone;

    Parameters:

    Returns:

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.


    exports.options(defaults, options)

    Copies and merges options with defaults.

    show code
    exports.options = function (defaults, options) {
    -  var keys = Object.keys(defaults)
    -    , i = keys.length
    -    , k ;
    +  if (this.isNew) {
    +    // send entire doc
    +    var toObjectOptions = {};
    +
    +    toObjectOptions.retainKeyOrder = this.schema.options.retainKeyOrder;
    +    toObjectOptions.depopulate = 1;
    +    toObjectOptions._skipDepopulateTopLevel = true;
    +    toObjectOptions.transform = false;
    +    toObjectOptions.flattenDecimals = false;
    +
    +    var obj = this.toObject(toObjectOptions);
    +
    +    if ((obj || {})._id === void 0) {
    +      // documents must have an _id else mongoose won't know
    +      // what to update later if more changes are made. the user
    +      // wouldn't know what _id was generated by mongodb either
    +      // nor would the ObjectId generated my mongodb necessarily
    +      // match the schema definition.
    +      setTimeout(function() {
    +        callback(new Error('document must have an _id before saving'));
    +      }, 0);
    +      return;
    +    }
     
    -  options = options || {};
    +    this.$__version(true, obj);
    +    this.collection.insert(obj, safe, function(err, ret) {
    +      if (err) {
    +        _this.isNew = true;
    +        _this.emit('isNew', true);
    +        _this.constructor.emit('isNew', true);
     
    -  while (i--) {
    -    k = keys[i];
    -    if (!(k in options)) {
    -      options[k] = defaults[k];
    -    }
    -  }
    +        callback(err);
    +        return;
    +      }
     
    -  return options;
    -};

    Parameters:

    Returns:


    exports.random()

    Generates a random string

    show code
    exports.random = function () {
    -  return Math.random().toString().substr(3);
    -};

    exports.merge(to, from)

    Merges from into to without overwriting existing properties.

    show code
    exports.merge = function merge (to, from) {
    -  var keys = Object.keys(from)
    -    , i = keys.length
    -    , key
    +      callback(null, ret);
    +    });
    +    this.$__reset();
    +    this.isNew = false;
    +    this.emit('isNew', false);
    +    this.constructor.emit('isNew', false);
    +    // Make it possible to retry the insert
    +    this.$__.inserting = true;
    +  } else {
    +    // Make sure we don't treat it as a new object on error,
    +    // since it already exists
    +    this.$__.inserting = false;
     
    -  while (i--) {
    -    key = keys[i];
    -    if ('undefined' === typeof to[key]) {
    -      to[key] = from[key];
    -    } else {
    -      merge(to[key], from[key]);
    -    }
    -  }
    -};

    Parameters:


    exports.args

    A faster Array.prototype.slice.call(arguments) alternative

    show code
    exports.args = sliced;

    exports.tick(callback)

    process.nextTick helper.

    show code
    exports.tick = function tick (callback) {
    -  if ('function' !== typeof callback) return;
    -  return function () {
    -    try {
    -      callback.apply(this, arguments);
    -    } catch (err) {
    -      // only nextTick on err to get out of
    -      // the event loop and avoid state corruption.
    -      process.nextTick(function () {
    -        throw err;
    +    var delta = this.$__delta();
    +
    +    if (delta) {
    +      if (delta instanceof Error) {
    +        callback(delta);
    +        return;
    +      }
    +
    +      var where = this.$__where(delta[0]);
    +      if (where instanceof Error) {
    +        callback(where);
    +        return;
    +      }
    +
    +      if (this.$where) {
    +        keys = Object.keys(this.$where);
    +        len = keys.length;
    +        for (i = 0; i < len; ++i) {
    +          where[keys[i]] = this.$where[keys[i]];
    +        }
    +      }
    +
    +      this.collection.update(where, delta[1], safe, function(err, ret) {
    +        if (err) {
    +          callback(err);
    +          return;
    +        }
    +        ret.$where = where;
    +        callback(null, ret);
           });
    +    } else {
    +      this.$__reset();
    +      callback();
    +      return;
         }
    -  }
    -}

    Parameters:

    Wraps callback in a try/catch + nextTick.

    - -

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


    exports.isMongooseObject(v)

    Returns if v is a mongoose object that has a toObject() method we can use.

    show code
    exports.isMongooseObject = function (v) {
    -  Document || (Document = require('./document'));
    -  MongooseArray || (MongooseArray = require('./types').Array);
    -  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
     
    -  return v instanceof Document ||
    -         v instanceof MongooseArray ||
    -         v instanceof MongooseBuffer
    -}
    -var isMongooseObject = exports.isMongooseObject;

    Parameters:

    This is for compatibility with libs like Date.js which do foolish things to Natives.


    exports.expires(object)

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    show code
    exports.expires = function expires (object) {
    -  if (!(object && 'Object' == object.constructor.name)) return;
    -  if (!('expires' in object)) return;
    +    this.emit('isNew', false);
    +    this.constructor.emit('isNew', false);
    +  }
    +};

    Model#collection

    Collection the model uses.

    show code
    Model.prototype.collection;

    Model#db

    Connection the model uses.

    show code
    Model.prototype.db;

    Model#discriminators

    Registered discriminators for this model.

    show code
    Model.discriminators;

    Model#modelName

    The name of the model

    show code
    Model.prototype.modelName;

    Model#schema

    Schema the model uses.

    show code
    Model.schema;

  • promise_provider.js

    ()

    Helper for multiplexing promise implementations

    show code
    var Promise = {
    +  _promise: MPromise
    +};

    Promise.get()

    Get the current promise constructor

    show code
    Promise.get = function() {
    +  return Promise._promise;
    +};

    Promise.reset()

    Resets to using mpromise

    show code
    Promise.reset = function() {
    +  Promise._promise = MPromise;
    +};
     
    -  var when;
    -  if ('string' != typeof object.expires) {
    -    when = object.expires;
    -  } else {
    -    when = Math.round(ms(object.expires) / 1000);
    +module.exports = Promise;

    Promise.set()

    Set the current promise constructor

    show code
    Promise.set = function(lib) {
    +  if (lib === MPromise) {
    +    return Promise.reset();
       }
    -  object.expireAfterSeconds = when;
    -  delete object.expires;
    -}
    -
    -exports.readPref = function readPref (pref, tags) {
    -  if (Array.isArray(pref)) {
    -    tags = pref[1];
    -    pref = pref[0];
    +  Promise._promise = require('./ES6Promise');
    +  Promise._promise.use(lib);
    +  require('mquery').Promise = Promise._promise.ES6;
    +};

  • collection.js

    Collection#addQueue(name, args)

    Queues a method for later execution when its
    database connection opens.

    Parameters:

    • name <String> name of the method to queue
    • args <Array> arguments to pass to the method when executed
    show code
    Collection.prototype.addQueue = function(name, args) {
    +  this.queue.push([name, args]);
    +  return this;
    +};

    Collection(name, conn, opts)

    Abstract Collection constructor

    Parameters:

    • name <String> name of the collection
    • conn <Connection> A MongooseConnection instance
    • opts <Object> optional collection options

    This is the base class that drivers inherit from and implement.

    show code
    function Collection(name, conn, opts) {
    +  if (opts === void 0) {
    +    opts = {};
       }
    -
    -  switch (pref) {
    -    case 'p':
    -      pref = 'primary';
    -      break;
    -    case 'pp':
    -      pref = 'primaryPrefered';
    -      break;
    -    case 's':
    -      pref = 'secondary';
    -      break;
    -    case 'sp':
    -      pref = 'secondaryPrefered';
    -      break;
    -    case 'n':
    -      pref = 'nearest';
    -      break;
    +  if (opts.capped === void 0) {
    +    opts.capped = {};
       }
     
    -  return new ReadPref(pref, tags);
    -}

    Parameters:


  • virtualtype.js

    VirtualType()

    VirtualType constructor

    show code
    function VirtualType (options, name) {
    -  this.path = name;
    -  this.getters = [];
    -  this.setters = [];
    -  this.options = options || {};
    -}

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    + opts.bufferCommands = undefined === opts.bufferCommands + ? true + : opts.bufferCommands; -

    Example:

    + if (typeof opts.capped === 'number') { + opts.capped = {size: opts.capped}; + } -
    var fullname = schema.virtual('fullname');
    -fullname instanceof mongoose.VirtualType // true

    VirtualType#get(fn)

    Defines a getter.

    show code
    VirtualType.prototype.get = function (fn) {
    -  this.getters.push(fn);
    -  return this;
    -};

    Parameters:

    Returns:

    Example:

    + this.opts = opts; + this.name = name; + this.collectionName = name; + this.conn = conn; + this.queue = []; + this.buffer = this.opts.bufferCommands; + this.emitter = new EventEmitter(); -
    var virtual = schema.virtual('fullname');
    -virtual.get(function () {
    -  return this.name.first + ' ' + this.name.last;
    -});

    VirtualType#set(fn)

    Defines a setter.

    show code
    VirtualType.prototype.set = function (fn) {
    -  this.setters.push(fn);
    +  if (STATES.connected === this.conn.readyState) {
    +    this.onOpen();
    +  }
    +}

    Collection#doQueue()

    Executes all queued methods and clears the queue.

    show code
    Collection.prototype.doQueue = function() {
    +  for (var i = 0, l = this.queue.length; i < l; i++) {
    +    if (typeof this.queue[i][0] === 'function') {
    +      this.queue[i][0].apply(this, this.queue[i][1]);
    +    } else {
    +      this[this.queue[i][0]].apply(this, this.queue[i][1]);
    +    }
    +  }
    +  this.queue = [];
    +  var _this = this;
    +  process.nextTick(function() {
    +    _this.emitter.emit('queue');
    +  });
       return this;
    -};

    Parameters:

    Returns:

    Example:

    - -
    var virtual = schema.virtual('fullname');
    -virtual.set(function (v) {
    -  var parts = v.split(' ');
    -  this.name.first = parts[0];
    -  this.name.last = parts[1];
    -});

    VirtualType#applyGetters(value, scope)

    Applies getters to value using optional scope.

    show code
    VirtualType.prototype.applyGetters = function (value, scope) {
    -  var v = value;
    -  for (var l = this.getters.length - 1; l >= 0; l--) {
    -    v = this.getters[l].call(scope, v, this);
    +};

    Collection#ensureIndex()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.ensureIndex = function() {
    +  throw new Error('Collection#ensureIndex unimplemented by driver');
    +};

    Collection#find()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.find = function() {
    +  throw new Error('Collection#find unimplemented by driver');
    +};

    Collection#findAndModify()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findAndModify = function() {
    +  throw new Error('Collection#findAndModify unimplemented by driver');
    +};

    Collection#findOne()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.findOne = function() {
    +  throw new Error('Collection#findOne unimplemented by driver');
    +};

    Collection#getIndexes()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.getIndexes = function() {
    +  throw new Error('Collection#getIndexes unimplemented by driver');
    +};

    Collection#insert()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.insert = function() {
    +  throw new Error('Collection#insert unimplemented by driver');
    +};

    Collection#mapReduce()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.mapReduce = function() {
    +  throw new Error('Collection#mapReduce unimplemented by driver');
    +};

    Collection#onClose()

    Called when the database disconnects

    show code
    Collection.prototype.onClose = function() {
    +  if (this.opts.bufferCommands) {
    +    this.buffer = true;
       }
    -  return v;
    -};

    Parameters:

    Returns:

    • <any> the value after applying all getters

    VirtualType#applySetters(value, scope)

    Applies setters to value using optional scope.

    show code
    VirtualType.prototype.applySetters = function (value, scope) {
    -  var v = value;
    -  for (var l = this.setters.length - 1; l >= 0; l--) {
    -    v = this.setters[l].call(scope, v, this);
    +};

    Collection#onOpen()

    Called when the database connects

    show code
    Collection.prototype.onOpen = function() {
    +  this.buffer = false;
    +  this.doQueue();
    +};

    Collection#save()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.save = function() {
    +  throw new Error('Collection#save unimplemented by driver');
    +};

    Collection#update()

    Abstract method that drivers must implement.

    show code
    Collection.prototype.update = function() {
    +  throw new Error('Collection#update unimplemented by driver');
    +};

    Collection#collectionName

    The collection name

    show code
    Collection.prototype.collectionName;

    Collection#conn

    The Connection instance

    show code
    Collection.prototype.conn;

    Collection#name

    The collection name

    show code
    Collection.prototype.name;

  • + $("#links, #content").on("click", "a", function (e) { + if (_gaq && this.hash) { + _gaq.push(['_trackEvent', 'anchor', 'click', this.hash]) + } + }) +})() \ No newline at end of file diff --git a/docs/api.jade b/docs/api.jade index 0a7a95f6f60..34db9a8b6f1 100644 --- a/docs/api.jade +++ b/docs/api.jade @@ -274,7 +274,7 @@ html(lang='en') hr(class= property.isPrivate ? 'private' : '') script. document.body.className = 'load'; - include includes/googleanalytics + include includes/keen script(src="/docs/js/zepto.min.js") script(src="/docs/js/cookies.min.js") script. diff --git a/docs/contributing.html b/docs/contributing.html index 3e20d34c244..26e45d6954f 100644 --- a/docs/contributing.html +++ b/docs/contributing.html @@ -1,9 +1,26 @@ -Mongoose Contributing v3.3.1Fork me on GitHub

    Contributing

    Please read all about contributing here.

    \ No newline at end of file +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/documents.html b/docs/documents.html index 135e56b4eef..520898e9d05 100644 --- a/docs/documents.html +++ b/docs/documents.html @@ -1,20 +1,59 @@ -Mongoose Documents v3.3.1Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    +Mongoose Documents v4.11.9Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a +traditional approach using findById:

    Tank.findById(id, function (err, tank) {
       if (err) return handleError(err);
       
       tank.size = 'large';
    -  tank.save(function (err) {
    +  tank.save(function (err, updatedTank) {
         if (err) return handleError(err);
    -    res.send(tank);
    +    res.send(updatedTank);
       });
    -});

    This approach involves first retrieving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    +});

    You can also use .set() +to modify documents. Under the hood, tank.size = 'large'; becomes tank.set({ size: 'large' }).

    Tank.findById(id, function (err, tank) {
    +  if (err) return handleError(err);
    +  
    +  tank.set({ size: 'large' });
    +  tank.save(function (err, updatedTank) {
    +    if (err) return handleError(err);
    +    res.send(updatedTank);
    +  });
    +});

    This approach involves first retrieving the document from Mongo, then +issuing an update command (triggered by calling save). However, if we +don't need the document returned in our application and merely want to +update a property in the database directly, +Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, { new: true }, function (err, tank) {
       if (err) return handleError(err);
       res.send(tank);
    -});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    +

    _Note that findAndUpdate/Remove do not execute any hooks or validation before making the change in the database. You can use the runValidators option to access a limited subset of document validation. However, if you need hooks and full document validation, first query for the document and then save() it._

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Overwriting

    You can overwrite an entire document using .set(). This is handy if you +want to change what document is being saved in middleware.

    Tank.findById(id, function (err, tank) {
    +  if (err) return handleError(err);
    +  // Now `otherTank` is a copy of `tank`
    +  otherTank.set(tank);
    +});
    +

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    \ No newline at end of file diff --git a/docs/faq.html b/docs/faq.html index e8432a0665e..35c16c6c762 100644 --- a/docs/faq.html +++ b/docs/faq.html @@ -1,31 +1,145 @@ -Mongoose FAQ v3.3.1Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    -doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    -doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    -new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    -doc.user.remove();// ?
    -doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    +Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element +directly?

    doc.array[3] = 'changed';
    +doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without +them mongoose never gets notified of the change and so doesn't know to +persist the new value. The work-around is to use +MongooseArray#set available +in Mongoose >= 3.2.0.

    // 3.2.0
    +doc.array.set(3, 'changed');
    +doc.save();
     
    -

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    +// if running a version less than 3.2.0, you must mark the array modified before saving. +doc.array[3] = 'changed'; +doc.markModified('array'); +doc.save(); +

    Q. I declared a schema property as unique but I can still save duplicates. What gives?

    -

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    +

    A. Mongoose doesn't handle unique on it's own, { name: { type: String, unique: true } } +just a shorthand for creating a MongoDB unique index on name. +For example, if MongoDB doesn't already have a unique index on name, the below code will not error despite the fact that unique is true.

    var schema = new mongoose.Schema({
    +  name: { type: String, unique: true }
    +});
    +var Model = db.model('Test', schema);
    +
    +Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) {
    +  console.log(err); // No error, unless index was already built
    +});

    However, if you wait for the index to build using the Model.on('index') event, attempts to save duplicates will correctly error.

    var schema = new mongoose.Schema({
    +  name: { type: String, unique: true }
    +});
    +var Model = db.model('Test', schema);
    +
    +Model.on('index', function(err) { // <-- Wait for model's indexes to finish
    +  assert.ifError(err);
    +  Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) {
    +    console.log(err);
    +  });
    +});

    MongoDB persists indexes, so you only need to rebuild indexes if you're starting +with a fresh database or you ran db.dropDatabase(). In a production environment, +you should [create your indexes using the MongoDB shell])(https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/) +rather than relying on mongoose to do it for you. The unique option for schemas is +convenient for development and documentation, but mongoose is not an index management solution.


    Q. When I have a nested property in a schema, mongoose adds empty objects by default. Why?

    var schema = new mongoose.Schema({
    +  nested: {
    +    prop: String
    +  }
    +});
    +var Model = db.model('Test', schema);
    +
    +// The below prints `{ _id: /* ... */, nested: {} }`, mongoose assigns
    +// `nested` to an empty object `{}` by default.
    +console.log(new Model());

    A. This is a performance optimization. These empty objects are not saved +to the database, nor are they in the result toObject(), nor do they show +up in JSON.stringify() output unless you turn off the minimize option.

    + +

    The reason for this behavior is that Mongoose's change detection +and getters/setters are based on Object.defineProperty(). +In order to support change detection on nested properties without incurring +the overhead of running Object.defineProperty() every time a document is created, +mongoose defines properties on the Model prototype when the model is compiled. +Because mongoose needs to define getters and setters for nested.prop, nested +must always be defined as an object on a mongoose document, even if nested +is undefined on the underlying POJO.


    Q. Why don't in-place modifications to date objects +(e.g. date.setMonth(1);) get saved?

    doc.createdAt.setDate(2011, 5, 1);
    +doc.save(); // createdAt changes won't get saved!

    A. Mongoose currently doesn't watch for in-place updates to date +objects. If you have need for this feature, feel free to discuss on +this GitHub issue. +There are several workarounds:

    doc.createdAt.setDate(2011, 5, 1);
    +doc.markModified('createdAt');
    +doc.save(); // Works
    doc.createdAt = new Date(2011, 5, 1).setHours(4);
    +doc.save(); // Works
    +

    Q. I'm populating a nested property under an array like the below code:

    + +

    + new Schema({ + arr: [{ + child: { ref: 'OtherModel', type: Schema.Types.ObjectId } + }] + }); +

    + +

    .populate({ path: 'arr.child', options: { sort: 'name' } }) won't sort +by arr.child.name?

    A. See this GitHub issue. It's a known issue but one that's exceptionally difficult to fix.


    Q. All function calls on my models hang, what am I doing wrong?

    + +

    A. By default, mongoose will buffer your function calls until it can +connect to MongoDB. Read the buffering section of the connection docs +for more information.


    Q. How can I enable debugging?

    + +

    A. Set the debug option to true:

    mongoose.set('debug', true)

    All executed collection methods will log output of their arguments to your console.


    Q. My save() callback never executes. What am I doing wrong?

    + +

    A. All collection actions (insert, remove, queries, etc.) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
     mongoose.connect(..);
     mongoose.connection.on('error', handleError);
     
     // if connecting on a separate connection
     var conn = mongoose.createConnection(..);
    -conn.on('error', handleError);
    +conn.on('error', handleError);

    Q. Should I create/destroy a new connection for each database operation?

    + +

    A. No. Open your connection when your application starts up and leave it open until the application shuts down.


    Q. Why do I get "OverwriteModelError: Cannot overwrite .. model once +compiled" when I use nodemon / a testing framework?

    + +

    A. mongoose.model('ModelName', schema) requires 'ModelName' to be +unique, so you can access the model by using mongoose.model('ModelName'). +If you put mongoose.model('ModelName', schema); in a +mocha beforeEach() hook, this code will +attempt to create a new model named 'ModelName' before every test, +and so you will get an error. Make sure you only create a new model with +a given name once. If you need to create multiple models with the +same name, create a new connection and bind the model to the connection.

    var mongoose = require('mongoose');
    +var connection = mongoose.createConnection(..);
    +
    +// use mongoose.Schema
    +var kittySchema = mongoose.Schema({ name: String });
    +
    +// use connection.model
    +var Kitten = connection.model('Kitten', kittySchema);
     

    Something to add?

    -

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    \ No newline at end of file +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/guide.html b/docs/guide.html index 64c442adae9..02d5975ea96 100644 --- a/docs/guide.html +++ b/docs/guide.html @@ -1,4 +1,8 @@ -Mongoose Schemas v3.3.1Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

    If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    +Mongoose Schemas v4.11.9Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works. +If you are migrating from 3.x to 4.x please take a moment to read the migration guide.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var mongoose = require('mongoose');
    +var Schema = mongoose.Schema;
    +
    +var blogSchema = new Schema({
       title:  String,
       author: String,
       body:   String,
    @@ -11,50 +15,119 @@
       }
     });

    If you want to add additional keys later, use the Schema#add method.

    Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. -Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    +Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Creating a model

    To use our schema definition, we need to convert our blogSchema into a Model we can work with. +To do so, we pass it into mongoose.model(modelName, schema):

    var Blog = mongoose.model('Blog', blogSchema);
    +// ready to go!
    +

    Instance methods

    Instances of Models are documents. Documents have many of their own built-in instance methods. We may also define our own custom document instance methods too.

    // define a schema
    +var animalSchema = new Schema({ name: String, type: String });
     
    -animalSchema.methods.findSimilarTypes = function (cb) {
    +// assign a function to the "methods" object of our animalSchema
    +animalSchema.methods.findSimilarTypes = function(cb) {
       return this.model('Animal').find({ type: this.type }, cb);
    -}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    +};

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
     var dog = new Animal({ type: 'dog' });
     
    -dog.findSimilarTypes(function (err, dogs) {
    +dog.findSimilarTypes(function(err, dogs) {
       console.log(dogs); // woof
    -});

    Statics

    -Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    -  this.find({ name: new RegExp(name, 'i') }, cb);
    -}
    +});
    +

    Overwriting a default mongoose document method may lead to unpredictable results. See this for more details.

    Do not declare methods using ES6 arrow functions (=>). Arrow functions explicitly prevent binding this, so your method will not have access to the document and the above examples will not work.

    Statics

    Adding static methods to a Model is simple as well. Continuing with our animalSchema:

    // assign a function to the "statics" object of our animalSchema
    +animalSchema.statics.findByName = function(name, cb) {
    +  return this.find({ name: new RegExp(name, 'i') }, cb);
    +};
    +
    +var Animal = mongoose.model('Animal', animalSchema);
    +Animal.findByName('fido', function(err, animals) {
    +  console.log(animals);
    +});
    +

    Do not declare statics using ES6 arrow functions (=>). Arrow functions explicitly prevent binding this, so the above examples will not work because of the value of this.

    Query Helpers

    You can also add query helper functions, which are like instance methods +but for mongoose queries. Query helper methods let you extend mongoose's +chainable query builder API.

    animalSchema.query.byName = function(name) {
    +  return this.find({ name: new RegExp(name, 'i') });
    +};
     
     var Animal = mongoose.model('Animal', animalSchema);
    -Animal.findByName('fido', function (err, animals) {
    +Animal.find().byName('fido').exec(function(err, animals) {
       console.log(animals);
    -});

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });
    -

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index. It is recommended this behavior be disabled in production by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false);
    +});
    +

    Indexes

    MongoDB supports secondary indexes. +With mongoose, we define these indexes within our Schema at the path level or the schema level. +Defining indexes at the schema level is necessary when creating +compound indexes.

    var animalSchema = new Schema({
    +  name: String,
    +  type: String,
    +  tags: { type: [String], index: true } // field level
    +});
    +
    +animalSchema.index({ name: 1, type: -1 }); // schema level
    +

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index in your schema. +Mongoose will call ensureIndex for each index sequentially, and emit an 'index' event on the model when all the ensureIndex calls succeeded or when there was an error. +While nice for development, it is recommended this behavior be disabled in production since index creation can cause a significant performance impact. Disable the behavior by setting the autoIndex option of your schema to false, or globally on the connection by setting the option config.autoIndex to false.

    mongoose.connect('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } });
    +// or  
    +mongoose.createConnection('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } });
    +// or
    +animalSchema.set('autoIndex', false);
     // or
     new Schema({..}, { autoIndex: false });
    -

    See also the Model#ensureIndexes method for more details.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    +

    Mongoose will emit an index event on the model when indexes are done +building or an error occurred.

    // Will cause an error because mongodb has an _id index by default that
    +// is not sparse
    +animalSchema.index({ _id: 1 }, { sparse: true });
    +var Animal = mongoose.model('Animal', animalSchema);
    +
    +Animal.on('index', function(error) {
    +  // "_id index cannot be sparse"
    +  console.log(error.message);
    +});
    +

    See also the Model#ensureIndexes method.

    Virtuals

    Virtuals are document properties that you can get and set but that do not get persisted to MongoDB. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage.

    // define a schema
    +var personSchema = new Schema({
       name: {
         first: String,
         last: String
       }
     });
     
    +// compile our model
     var Person = mongoose.model('Person', personSchema);
     
    -var bad = new Person({
    -    name: { first: 'Walter', last: 'White' }
    -});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    +// create a document
    +var axl = new Person({
    +  name: { first: 'Axl', last: 'Rose' }
    +});
    +

    Suppose you want to print out the person's full name. You could do it yourself:

    console.log(axl.name.first + ' ' + axl.name.last); // Axl Rose
    +

    But concatenating the first and last name every time can get cumbersome. And what if you want to do some extra processing on the name, like removing diacritics?. A virtual property getter lets you define a fullName property that won't get persisted to MongoDB.

    personSchema.virtual('fullName').get(function () {
       return this.name.first + ' ' + this.name.last;
    -});

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full); // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    -  var split = name.split(' ');
    -  this.name.first = split[0];
    -  this.name.last = split[1];
     });
    +

    Now, mongoose will call your getter function every time you access the fullName property:

    console.log(axl.fullName); // Axl Rose
    +

    If you use toJSON() or toObject() (or use JSON.stringify() on a mongoose document) mongoose will not include virtuals by default. +Pass { virtuals: true } to either toObject() or toJSON().

    -... +

    You can also add a custom setter to your virtual that will let you set both first name and last name via the fullName virtual.

    personSchema.virtual('fullName').
    +  get(function() { return this.name.first + ' ' + this.name.last; }).
    +  set(function(v) {
    +    this.name.first = v.substr(0, v.indexOf(' '));
    +    this.name.last = v.substr(v.indexOf(' ') + 1);
    +  });
    +  
    +axl.fullName = 'William Rose'; // Now `axl.name.first` is "William"
    +

    Virtual property setters are applied before other validation. So the example above would still work even if the first and last name fields were required.

    -mad.name.full = 'Breaking Bad'; -console.log(mad.name.first); // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    +

    Only non-virtual properties work as part of queries and for field selection. Since virtuals are not stored in MongoDB, you can't query with them.

    Aliases

    Aliases are a particular type of virtual where the getter and setter seamlessly get and set another property. This is handy for saving network bandwidth, so you can convert a short property name stored in the database into a longer name for code readability.

    var personSchema = new Schema({
    +  n: {
    +    type: String,
    +    // Now accessing `name` will get you the value of `n`, and setting `n` will set the value of `name`
    +    alias: 'name'
    +  }
    +});
    +
    +// Setting `name` will propagate to `n`
    +var person = new Person({ name: 'Val' });
    +console.log(person); // { n: 'Val' }
    +console.log(person.toObject({ virtuals: true })); // { n: 'Val', name: 'Val' }
    +console.log(person.name); // "Val"
    +
    +person.name = 'Not Val';
    +console.log(person); // { n: 'Not Val' }
    +

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
     
     // or
     
    @@ -62,35 +135,82 @@
     schema.set(option, value);
     

    Valid options:

    -

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false });
    -var Clock = db.model('Clock', schema);
    +

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false });
    +var Clock = mongoose.model('Clock', schema);
     Clock.ensureIndexes(callback);
    +

    option: bufferCommands

    By default, mongoose buffers commands when the connection goes down until +the driver manages to reconnect. To disable buffering, set bufferCommands +to false.

    var schema = new Schema({..}, { bufferCommands: false });
     

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 });

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });
    -

    option: collection

    Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Set this option if you need a different name for your collection.

    var dataSchema = new Schema({..}, { collection: 'data' });
    -

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    +

    option: collection

    Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Set this option if you need a different name for your collection.

    var dataSchema = new Schema({..}, { collection: 'data' });
    +

    option: emitIndexErrors

    By default, mongoose will build any indexes you specify in your schema for +you, and emit an 'index' event on the model when the index build either +succeeds or errors out.

    MyModel.on('index', function(error) {
    +  /* If error is truthy, index build failed */
    +});

    However, this makes it tricky to catch when your index build fails. The +emitIndexErrors option makes seeing when your index build fails simpler. +If this option is on, mongoose will additionally emit an 'error' event +on the model when an index build fails.

    MyModel.schema.options.emitIndexErrors; // true
    +MyModel.on('error', function(error) {
    +  // gets an error whenever index build fails
    +});

    Node.js' built-in +event emitter throws an exception if an error event is emitted and there are no listeners, +so its easy to configure your application to fail fast when an index build fails.

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
     var schema = new Schema({ name: String });
    -var Page = db.model('Page', schema);
    +var Page = mongoose.model('Page', schema);
     var p = new Page({ name: 'mongodb.org' });
     console.log(p.id); // '50341373e894ad16347efe01'
     
     // disabled id
     var schema = new Schema({ name: String }, { id: false });
    -var Page = db.model('Page', schema);
    +var Page = mongoose.model('Page', schema);
     var p = new Page({ name: 'mongodb.org' });
     console.log(p.id); // undefined
    -

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    +

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one +is not passed into the Schema constructor. +The type assigned is an ObjectId +to coincide with MongoDB's default behavior. If you don't want an _id +added to your schema at all, you may disable it using this option.

    -

    Pass this option during schema construction to prevent documents from getting an auto _id created.

    // default behavior
    +

    You can only use this option on sub-documents. Mongoose can't +save a document without knowing its id, so you will get an error if +you try to save a document without an _id.

    // default behavior
     var schema = new Schema({ name: String });
    -var Page = db.model('Page', schema);
    +var Page = mongoose.model('Page', schema);
     var p = new Page({ name: 'mongodb.org' });
     console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
     
     // disabled _id
    -var schema = new Schema({ name: String }, { _id: false });
    -var Page = db.model('Page', schema);
    -var p = new Page({ name: 'mongodb.org' });
    -console.log(p); // { name: 'mongodb.org' }
    +var childSchema = new Schema({ name: String }, { _id: false });
    +var parentSchema = new Schema({ children: [childSchema] });
    +
    +var Model = mongoose.model('Model', parentSchema);
    +
    +Model.create({ children: [{ name: 'Luke' }] }, function(error, doc) {
    +  // doc.children[0]._id will be undefined
    +});
    +

    option: minimize

    Mongoose will, by default, "minimize" schemas by removing empty objects.

    var schema = new Schema({ name: String, inventory: {} });
    +var Character = mongoose.model('Character', schema);
    +
    +// will store `inventory` field if it is not empty
    +var frodo = new Character({ name: 'Frodo', inventory: { ringOfPower: 1 }});
    +Character.findOne({ name: 'Frodo' }, function(err, character) {
    +  console.log(character); // { name: 'Frodo', inventory: { ringOfPower: 1 }}
    +});
    +
    +// will not store `inventory` field if it is empty
    +var sam = new Character({ name: 'Sam', inventory: {}});
    +Character.findOne({ name: 'Sam' }, function(err, character) {
    +  console.log(character); // { name: 'Sam' }
    +});
    +

    This behavior can be overridden by setting minimize option to false. It will then store empty objects.

    var schema = new Schema({ name: String, inventory: {} }, { minimize: false });
    +var Character = mongoose.model('Character', schema);
    +
    +// will store `inventory` if empty
    +var sam = new Character({ name: 'Sam', inventory: {}});
    +Character.findOne({ name: 'Sam' }, function(err, character) {
    +  console.log(character); // { name: 'Sam', inventory: {}}
    +});
     

    option: read

    Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

    var schema = new Schema({..}, { read: 'primary' });            // also aliased as 'p'
     var schema = new Schema({..}, { read: 'primaryPreferred' });   // aliased as 'pp'
     var schema = new Schema({..}, { read: 'secondary' });          // aliased as 's'
    @@ -100,23 +220,26 @@
     
     

    The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

    -

    NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

    // pings the replset members periodically to track network latency
    -// now `nearest` works as intended
    +

    NOTE: you may also specify the driver read pref strategy option when connecting:

    // pings the replset members periodically to track network latency
     var options = { replset: { strategy: 'ping' }};
     mongoose.connect(uri, options);
     
    -var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
    +var schema = new Schema({..}, { read: ['nearest', { disk: 'ssd' }] });
     mongoose.model('JellyBean', schema);
    -

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    +

    option: safe

    This option is passed to MongoDB with all operations and specifies if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
     new Schema({ .. }, { safe: safe });
     

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    +

    NOTE: In 3.6.x, you also need to turn versioning off. In 3.7.x and above, versioning will automatically be disabled when safe is set to false

    + +

    **NOTE: this setting overrides any setting specified by passing db options while creating a connection.

    +

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
     new Schema({ .. }, { safe: safe });
    -

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    +

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardKey: { tag: 1, name: 1 }})
     

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: strict

    The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.

    var thingSchema = new Schema({..})
    -var Thing = db.model('Thing', schemaSchema);
    +var Thing = mongoose.model('Thing', thingSchema);
     var thing = new Thing({ iAmNotInTheSchema: true });
     thing.save(); // iAmNotInTheSchema is not saved to the db
     
    @@ -125,11 +248,11 @@
     var thing = new Thing({ iAmNotInTheSchema: true });
     thing.save(); // iAmNotInTheSchema is now saved to the db!!
     

    This also affects the use of doc.set() to set a property value.

    var thingSchema = new Schema({..})
    -var Thing = db.model('Thing', schemaSchema);
    +var Thing = mongoose.model('Thing', thingSchema);
     var thing = new Thing;
     thing.set('iAmNotInTheSchema', true);
     thing.save(); // iAmNotInTheSchema is not saved to the db
    -

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = db.model('Thing');
    +

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = mongoose.model('Thing');
     var thing = new Thing(doc, true);  // enables strict mode
     var thing = new Thing(doc, false); // disables strict mode
     

    The strict option may also be set to "throw" which will cause errors to be produced instead of dropping the bad data.

    NOTE: do not set to false unless you have good reason.

    @@ -137,7 +260,7 @@

    NOTE: in mongoose v2 the default was false.

    NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.

    var thingSchema = new Schema({..})
    -var Thing = db.model('Thing', schemaSchema);
    +var Thing = mongoose.model('Thing', thingSchema);
     var thing = new Thing;
     thing.iAmNotInTheSchema = true;
     thing.save(); // iAmNotInTheSchema is never saved to the db
    @@ -152,7 +275,7 @@
     console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
     // since we know toJSON is called whenever a js object is stringified:
     console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
    -

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    +

    To see all available toJSON/toObject options, read this.

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    To have all virtuals show up in your console.log output, set the toObject option to { getters: true }:

    var schema = new Schema({ name: String });
     schema.path('name').get(function (v) {
    @@ -162,27 +285,108 @@
     var M = mongoose.model('Person', schema);
     var m = new M({ name: 'Max Headroom' });
     console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    -

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    -var Thing = db.model('Thing', schema);
    +

    To see all available toObject options, read this.

    option: typeKey

    By default, if you have an object with key 'type' in your schema, mongoose +will interpret it as a type declaration.

    // Mongoose interprets this as 'loc is a String'
    +var schema = new Schema({ loc: { type: String, coordinates: [Number] } });
    +

    However, for applications like geoJSON, +the 'type' property is important. If you want to control which key mongoose +uses to find type declarations, set the 'typeKey' schema option.

    var schema = new Schema({
    +  // Mongoose interpets this as 'loc is an object with 2 keys, type and coordinates'
    +  loc: { type: String, coordinates: [Number] },
    +  // Mongoose interprets this as 'name is a String'
    +  name: { $type: String }
    +}, { typeKey: '$type' }); // A '$type' key means this object is a type declaration
    +

    option: validateBeforeSave

    By default, documents are automatically validated before they are saved to the database. This is to prevent saving an invalid document. If you want to handle validation manually, and be able to save objects which don't pass validation, you can set validateBeforeSave to false.

    var schema = new Schema({ name: String });
    +schema.set('validateBeforeSave', false);
    +schema.path('name').validate(function (value) {
    +    return v != null;
    +});
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: null });
    +m.validate(function(err) {
    +    console.log(err); // Will tell you that null is not allowed.
    +});
    +m.save(); // Succeeds despite being invalid
    +

    option: versionKey

    The versionKey is a property set on each document when first created by +Mongoose. This keys value contains the internal +revision +of the document. The versionKey option is a string that represents the +path to use for versioning. The default is __v. If this conflicts with +your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    +var Thing = mongoose.model('Thing', schema);
     var thing = new Thing({ name: 'mongoose v3' });
     thing.save(); // { __v: 0, name: 'mongoose v3' }
     
     // customized versionKey
     new Schema({..}, { versionKey: '_somethingElse' })
    -var Thing = db.model('Thing', schema);
    +var Thing = mongoose.model('Thing', schema);
     var thing = new Thing({ name: 'mongoose v3' });
     thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    -

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false });
    -var Thing = db.model('Thing', schema);
    +

    Document versioning can also be disabled by setting the versionKey to +false. +DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false });
    +var Thing = mongoose.model('Thing', schema);
     var thing = new Thing({ name: 'no versioning please' });
     thing.save(); // { name: 'no versioning please' }
    +

    option: skipVersioning

    skipVersioning allows excluding paths from versioning (i.e., the internal revision will not be incremented even if these paths are updated). DO NOT do this unless you know what you're doing. For sub-documents, include this on the parent document using the fully qualified path.

    new Schema({..}, { skipVersioning: { dontVersionMe: true } });
    +thing.dontVersionMe.push('hey');
    +thing.save(); // version is not incremented
    +

    option: timestamps

    If set timestamps, mongoose assigns createdAt and updatedAt fields to your schema, the type assigned is Date.

    + +

    By default, the name of two fields are createdAt and updatedAt, customize the field name by setting timestamps.createdAt and timestamps.updatedAt.

    var thingSchema = new Schema({..}, { timestamps: { createdAt: 'created_at' } });
    +var Thing = mongoose.model('Thing', thingSchema);
    +var thing = new Thing();
    +thing.save(); // `created_at` & `updatedAt` will be included
    +

    option: useNestedStrict

    In mongoose 4, update() and findOneAndUpdate() only check the top-level +schema's strict mode setting.

    var childSchema = new Schema({}, { strict: false });
    +var parentSchema = new Schema({ child: childSchema }, { strict: 'throw' });
    +var Parent = mongoose.model('Parent', parentSchema);
    +Parent.update({}, { 'child.name': 'Luke Skywalker' }, function(error) {
    +  // Error because parentSchema has `strict: throw`, even though
    +  // `childSchema` has `strict: false`
    +});
    +
    +var update = { 'child.name': 'Luke Skywalker' };
    +var opts = { strict: false };
    +Parent.update({}, update, opts, function(error) {
    +  // This works because passing `strict: false` to `update()` overwrites
    +  // the parent schema.
    +});

    If you set useNestedStrict to true, mongoose will use the child schema's +strict option for casting updates.

    var childSchema = new Schema({}, { strict: false });
    +var parentSchema = new Schema({ child: childSchema },
    +  { strict: 'throw', useNestedStrict: true });
    +var Parent = mongoose.model('Parent', parentSchema);
    +Parent.update({}, { 'child.name': 'Luke Skywalker' }, function(error) {
    +  // Works!
    +});
    +

    option: retainKeyOrder

    By default, mongoose reverses key order in documents as a performance optimization. For example, new Model({ first: 1, second: 2 }); would actually be stored in MongoDB as { second: 2, first: 1 }. This behavior is considered deprecated because it has numerous unintended side effects, including making it difficult to manipulate documents whose _id field is an object.

    -

    Next Up

    Now that we've covered Schemas, let's take a look at SchemaTypes.

    \ No newline at end of file +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/guide.jade b/docs/guide.jade index 553ee21371f..875c7f33ab0 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -738,4 +738,4 @@ block content script. document.body.className = 'load'; -include includes/googleanalytics +include includes/keen diff --git a/docs/includes/googleanalytics.jade b/docs/includes/googleanalytics.jade deleted file mode 100644 index f589283902c..00000000000 --- a/docs/includes/googleanalytics.jade +++ /dev/null @@ -1,10 +0,0 @@ -script. - var _gaq = _gaq || []; - _gaq.push(['_setAccount', 'UA-1122274-9']); - _gaq.push(['_trackPageview', location.pathname + location.search + location.hash]); - - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' === document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); diff --git a/docs/includes/keen.jade b/docs/includes/keen.jade new file mode 100644 index 00000000000..d6b3bd6c6e4 --- /dev/null +++ b/docs/includes/keen.jade @@ -0,0 +1,18 @@ +script(type="text/javascript") + !function(name,path,ctx){ + var latest,prev=name!=='Keen'&&window.Keen?window.Keen:false;ctx[name]=ctx[name]||{ready:function(fn){var h=document.getElementsByTagName('head')[0],s=document.createElement('script'),w=window,loaded;s.onload=s.onerror=s.onreadystatechange=function(){if((s.readyState&&!(/^c|loade/.test(s.readyState)))||loaded){return}s.onload=s.onreadystatechange=null;loaded=1;latest=w.Keen;if(prev){w.Keen=prev}else{try{delete w.Keen}catch(e){w.Keen=void 0}}ctx[name]=latest;ctx[name].ready(fn)};s.async=1;s.src=path;h.parentNode.insertBefore(s,h)}} + }('KeenAsync','https://d26b395fwzu5fz.cloudfront.net/keen-tracking-1.1.3.min.js',this); + + KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); + }); diff --git a/docs/index.html b/docs/index.html index d8d1095828e..caf3771929d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,36 +1,51 @@ -Mongoose Quick Start v3.3.1Fork me on GitHub

    Getting Started

    First be sure you have MongoDB and Nodejs installed.

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. -The first thing we need to do is include mongoose in our project and open a connection.

    var mongoose = require('mongoose')
    -  , db = mongoose.createConnection('localhost', 'test');

    We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    db.on('error', console.error.bind(console, 'connection error:'));
    -db.once('open', function () {
    -  // yay!
    -});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = new mongoose.Schema({
    +Mongoose Quick Start v4.11.9Fork me on GitHub

    Getting Started

    First be sure you have MongoDB and Node.js installed.

    + +

    Next install Mongoose from the command line using npm:

    + +
    $ npm install mongoose

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. +The first thing we need to do is include mongoose in our project and open a connection to the test database on our locally running instance of MongoDB.

    // getting-started.js
    +var mongoose = require('mongoose');
    +mongoose.connect('mongodb://localhost/test');

    We have a pending connection to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    var db = mongoose.connection;
    +db.on('error', console.error.bind(console, 'connection error:'));
    +db.once('open', function() {
    +  // we're connected!
    +});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = mongoose.Schema({
         name: String
    -})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a model.

    var Kitten = db.model('Kitten', kittySchema)

    A model is a class with which we construct documents. +});

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a Model.

    var Kitten = mongoose.model('Kitten', kittySchema);

    A model is a class with which we construct documents. In this case, each document will be a kitten with properties and behaviors as declared in our schema. -Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    -console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    kittySchema.methods.speak = function () {
    +Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' });
    +console.log(silence.name); // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    // NOTE: methods must be added to the schema before compiling it with mongoose.model()
    +kittySchema.methods.speak = function () {
       var greeting = this.name
         ? "Meow name is " + this.name
    -    : "I don't have a name"
    +    : "I don't have a name";
       console.log(greeting);
     }
     
    -var Kitten = db.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    -fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. -Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err) {
    -  if (err) // TODO handle the error
    -  console.log('meow')
    -});

    Say time goes by and we want to display all the kittens we've seen. -We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    -  if (err) // TODO handle err
    -  console.log(kittens)
    +var Kitten = mongoose.model('Kitten', kittySchema);

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    +fluffy.speak(); // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. +Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err, fluffy) {
    +  if (err) return console.error(err);
    +  fluffy.speak();
    +});

    Say time goes by and we want to display all the kittens we've seen. +We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    +  if (err) return console.error(err);
    +  console.log(kittens);
     })

    We just logged all of the kittens in our db to the console. -If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax.

    Kitten.find({ name: /fluff/i }, callback)

    This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the result as an array of kittens to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or api docs for more.

    \ No newline at end of file +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/index.jade b/docs/index.jade index 0055313b232..52911e2c61a 100644 --- a/docs/index.jade +++ b/docs/index.jade @@ -106,4 +106,4 @@ html(lang='en') That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the [guide](guide.html), or [API docs](api.html) for more. script. document.body.className = 'load'; - include includes/googleanalytics + include includes/keen diff --git a/docs/layout.jade b/docs/layout.jade index 957802987b2..9bd93a8cfb4 100644 --- a/docs/layout.jade +++ b/docs/layout.jade @@ -42,4 +42,4 @@ html(lang='en') script. document.body.className = 'load'; include includes/googlesearch - include includes/googleanalytics + include includes/keen diff --git a/docs/middleware.html b/docs/middleware.html index a40ade38c52..50cfa87fcbb 100644 --- a/docs/middleware.html +++ b/docs/middleware.html @@ -1,29 +1,202 @@ -Mongoose Middleware v3.3.1Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

    -There are two types of middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next

    var schema = new Schema(..);
    -schema.pre('save', function (next) {
    +Mongoose Middleware v4.11.9Fork me on GitHub

    Middleware

    Middleware (also called pre and post hooks) are functions which are passed +control during execution of asynchronous functions. Middleware is specified +on the schema level and is useful for writing plugins. +Mongoose 4.x has 3 types +of middleware: document middleware, model middleware, and query middleware. +Document middleware is supported for the following document functions. +In document middleware functions, this refers to the document.

    + + + +

    Query middleware is supported for the following Model and Query functions. +In query middleware functions, this refers to the query.

    + + + +

    Model middleware is supported for the following model functions. +In model middleware functions, this refers to the model.

    + + + +

    All middleware types support pre and post hooks. +How pre and post hooks work is described in more detail below.

    + +

    Note: There is no query hook for remove(), only for documents. +If you set a 'remove' hook, it will be fired when you call myDoc.remove(), +not when you call MyModel.remove(). +Note: The create() function fires save() hooks.

    Pre

    There are two types of pre hooks, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next.

    var schema = new Schema(..);
    +schema.pre('save', function(next) {
       // do stuff
       next();
    -});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    -schema.pre('save', true, function (next, done) {
    +});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    +
    +// `true` means this is a parallel middleware. You **must** specify `true`
    +// as the second parameter if you want to use parallel middleware.
    +schema.pre('save', true, function(next, done) {
       // calling next kicks off the next middleware in parallel
       next();
    -  doAsync(done);
    -});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    +  setTimeout(done, 100);
    +});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with a parameter of type Error, +the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function(next) {
    +  // You **must** do `new Error()`. `next('something went wrong')` will
    +  // **not** work
       var err = new Error('something went wrong');
       next(err);
     });
     
     // later...
     
    -myModel.save(function (err) {
    +myDoc.save(function(err) {
       console.log(err.message) // something went wrong
     });
    -

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    \ No newline at end of file +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/migration.html b/docs/migration.html index 4d22bf79ead..b63279ad884 100644 --- a/docs/migration.html +++ b/docs/migration.html @@ -1,40 +1,43 @@ -Mongoose Migration Guide v3.3.1Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    - -

    Here are the removed methods are their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    - -

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    • are now strict by default.
    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    - -

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    - -
    • $inc
    • $increment
    • $decrement
    - -

    If you really want this behavior back, include the mongoose-number module in your project.

    - -

    A good alternative is to start using the new findAndModify helpers. -Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    -...
    -Inventory.findById(id, function (err, inventory) {
    -  if (err) return handleError(err);
    -  inventory.productCount.$decrement(7);
    -  inventory.save(function (err) {
    -    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    -    if (err) return handleError(err);
    -    res.send(inventory.productCount); // 3
    +Fork me on GitHub

    Migrating from 3.x to 4.x

    There are several backwards-breaking changes to be aware of when migrating from Mongoose 3 to Mongoose 4.

    `findOneAndUpdate()` new field is now `false` by default

    Mongoose's findOneAndUpdate(), findOneAndRemove(), +findByIdAndUpdate(), and findByIdAndRemove() functions are just +wrappers around MongoDB's +findAndModify command. +Both the MongoDB server and the MongoDB NodeJS driver set the new option +to false by default, but mongoose 3 overwrote this default. In order to be +more consistent with the MongoDB server's documentation, mongoose will +use false by default. That is, +findOneAndUpdate({}, { $set: { test: 1 } }, callback); will return the +document as it was before the $set operation was applied.

    + +

    To return the document with modifications made on the update, use the new: true option.

    MyModel.findOneAndUpdate({}, { $set: { test: 1 } }, { new: true }, callback);
    +

    CastError and ValidationError now use `kind` instead of `type` to report error types

    In Mongoose 3, CastError and ValidationError had a type field. For instance, user defined validation errors would have a type property that contained the string 'user defined'. In Mongoose 4, this property has been renamed to kind due to the V8 JavaScript engine using the Error.type property internally.

    Query now has a `.then()` function

    In mongoose 3, you needed to call .exec() on a query chain to get a promise back, like MyModel.find().exec().then();. Mongoose 4 queries are promises, so you can do MyModel.find().then() instead. Be careful if you're using functions like q's Q.ninvoke() or otherwise returning a mongoose query from a promise.

    More Info

    Related blog posts:

    + +
    \ No newline at end of file + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/models.html b/docs/models.html index 97c269bea17..d0ed2530354 100644 --- a/docs/models.html +++ b/docs/models.html @@ -1,10 +1,8 @@ -Mongoose Models v3.3.1Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var schema = new Schema({ name: 'string', size: 'string' });
    +Mongoose Models v4.11.9Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retrieved from our database. All document creation and retrieval from the database is handled by these models.

    Compiling your first model

    var schema = new mongoose.Schema({ name: 'string', size: 'string' });
     var Tank = mongoose.model('Tank', schema);
    -
    -// or, if you are using separate connections
    -var db = mongoose.createConnection(..);
    -var Tank = db.model('Tank', schema);
    -

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = db.model('Tank', yourSchema);
    +

    The first argument is the singular name of the collection your model is for. Mongoose automatically looks for the plural version of your model name. +Thus, for the example above, the model Tank is for the tanks collection in the database. +The .model() function makes a copy of schema. Make sure that you've added everything you want to schema before calling .model()!

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = mongoose.model('Tank', yourSchema);
     
     var small = new Tank({ size: 'small' });
     small.save(function (err) {
    @@ -14,19 +12,42 @@
     
     // or
     
    -Tank.create({ size: 'small' }, function (err) {
    +Tank.create({ size: 'small' }, function (err, small) {
       if (err) return handleError(err);
       // saved!
    -})
    -

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    +})

    Note that no tanks will be created/removed until the connection your model +uses is open. Every model has an associated connection. When you use +mongoose.model(), your model will use the default mongoose connection.

    mongoose.connect('localhost', 'gettingstarted');

    If you create a custom connection, use that connection's model() function +instead.

    var connection = mongoose.createConnection('mongodb://localhost:27017/test');
    +var Tank = connection.model('Tank', yourSchema);
    +

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ size: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
       if (err) return handleError(err);
       // removed!
    -});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at Documents.

    \ No newline at end of file +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/plugins.html b/docs/plugins.html index 1930e6c0f3b..a83f0e81aa3 100644 --- a/docs/plugins.html +++ b/docs/plugins.html @@ -1,4 +1,4 @@ -Mongoose Plugins v3.3.1Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    +Mongoose Plugins v4.11.9Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
     module.exports = exports = function lastModifiedPlugin (schema, options) {
    @@ -22,12 +22,38 @@
     // player-schema.js
     var lastMod = require('./lastMod');
     var Player = new Schema({ ... });
    -Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    \ No newline at end of file +var gameSchema = new Schema({ ... }); +var playerSchema = new Schema({ ... }); +// `lastModifiedPlugin` gets attached to both schemas +var Game = mongoose.model('Game', gameSchema); +var Player = mongoose.model('Player', playerSchema);

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    \ No newline at end of file diff --git a/docs/populate.html b/docs/populate.html index e265c3d167f..35ca6f8a8da 100644 --- a/docs/populate.html +++ b/docs/populate.html @@ -1,104 +1,291 @@ -Mongoose Query Population v3.3.1Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    +Mongoose Query Population v4.11.9Fork me on GitHub

    Population

    MongoDB has the join-like $lookup aggregation operator in versions >= 3.2. Mongoose has a more powerful alternative called populate(), which lets you reference documents in other collections.

    -

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    -  , Schema = mongoose.Schema
    -  
    -var PersonSchema = new Schema({
    -  name    : String,
    -  age     : Number,
    -  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    +

    Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s). We may populate a single document, multiple documents, plain object, multiple plain objects, or all objects returned from a query. Let's look at some examples.

    var mongoose = require('mongoose');
    +var Schema = mongoose.Schema;
    +
    +var personSchema = Schema({
    +  _id: Schema.Types.ObjectId,
    +  name: String,
    +  age: Number,
    +  stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
     });
     
    -var StorySchema = new Schema({
    -  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    -  title    : String,
    -  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    +var storySchema = Schema({
    +  author: { type: Schema.Types.ObjectId, ref: 'Person' },
    +  title: String,
    +  fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
     });
     
    -var Story  = mongoose.model('Story', StorySchema);
    -var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    +var Story = mongoose.model('Story', storySchema);
    +var Person = mongoose.model('Person', personSchema);

    So far we've created two Models. Our Person model has +its stories field set to an array of ObjectIds. The ref option is +what tells Mongoose which model to use during population, in our case +the Story model. All _ids we store here must be document _ids from +the Story model.

    Note: ObjectId, Number, String, and Buffer are valid for use +as refs. However, you should use ObjectId unless you are an advanced +user and have a good reason for doing so.

    Saving refs

    Saving refs to other documents works the same way you normally save +properties, just assign the _id value:

    var author = new Person({
    +  _id: new mongoose.Types.ObjectId(),
    +  name: 'Ian Fleming',
    +  age: 50
    +});
     
    -aaron.save(function (err) {
    +author.save(function (err) {
       if (err) return handleError(err);
       
       var story1 = new Story({
    -    title: "Once upon a timex.",
    -    _creator: aaron._id    // assign an ObjectId
    +    title: 'Casino Royale',
    +    author: author._id    // assign the _id from the person
       });
       
       story1.save(function (err) {
         if (err) return handleError(err);
         // thats it!
       });
    -})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    -.findOne({ title: /timex/ })
    -.populate('_creator')
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    -})
    -

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    - -

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    -.findOne({ title: /timex/i })
    -.populate('_creator', 'name') // only return the Persons name
    -.exec(function (err, story) {
    -  if (err) return handleError(err);
    -  
    -  console.log('The creator is %s', story._creator.name);
    -  // prints "The creator is Aaron"
    -  
    -  console.log('The creators age is %s', story._creator.age);
    -  // prints "The creators age is null'
    -})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    -.find(...)
    -.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    +});

    Population

    So far we haven't done anything much different. We've merely created a Person and a Story. Now let's take a look at populating our story's author using the query builder:

    Story.
    +  findOne({ title: 'Casino Royale' }).
    +  populate('author').
    +  exec(function (err, story) {
    +    if (err) return handleError(err);
    +    console.log('The author is %s', story.author.name);
    +    // prints "The author is Ian Fleming"
    +  });

    Populated paths are no longer set to their original _id , their value +is replaced with the mongoose document returned from the database by +performing a separate query before returning the results.

    -

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    -aaron.save();

    This allows us to perform a find and populate combo:

    Person
    -.findOne({ name: 'Aaron' })
    -.populate('stories') // only works if we pushed refs to children
    -.exec(function (err, person) {
    -  if (err) return handleError(err);
    -  console.log(person);
    -})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    -.find({ _creator: aaron._id })
    -.populate('_creator') // not really necessary
    -.exec(function (err, stories) {
    -  if (err) return handleError(err);
    -  console.log('The stories are an array: ', stories);
    -})
    -

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    -guille.save(function (err) {
    -  if (err) return handleError(err);
    -  
    -  story._creator = guille; // or guille._id
    -  
    -  story.save(function (err) {
    +

    Arrays of refs work the same way. Just call the +populate method on the query and an +array of documents will be returned in place of the original _ids.

    Note: mongoose >= 3.6 exposes the original _ids used during +population through the +document#populated() method.

    Setting Populated Fields

    In Mongoose >= 4.0, you can manually populate a field as well.

    Story.findOne({ title: 'Casino Royale' }, function(error, story) {
    +  if (error) {
    +    return handleError(error);
    +  }
    +  story.author = author;
    +  console.log(story.author.name); // prints "Ian Fleming"
    +});

    Note that this only works for single refs. You currently can't +manually populate an array of refs.

    Field selection

    What if we only want a few specific fields returned for the populated +documents? This can be accomplished by passing the usual +field name syntax as the second argument +to the populate method:

    Story.
    +  findOne({ title: /casino royale/i }).
    +  populate('author', 'name'). // only return the Persons name
    +  exec(function (err, story) {
         if (err) return handleError(err);
         
    -    Story
    -    .findOne({ title: /timex/i })
    -    .populate('_creator', 'name')
    -    .exec(function (err, story) {
    -      if (err) return handleError(err);
    -      
    -      console.log('The creator is %s', story._creator.name)
    -      // prints "The creator is Guillermo"
    -    })
    -  })
    -})
    -

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    -Story.findOne(..).populate('_creator', 'name age').exec(..);
    +    console.log('The author is %s', story.author.name);
    +    // prints "The author is Ian Fleming"
    +    
    +    console.log('The authors age is %s', story.author.age);
    +    // prints "The authors age is null'
    +  })

    Populating multiple paths

    What if we wanted to populate multiple paths at the same time?

    Story.
    +  find(...).
    +  populate('fans').
    +  populate('author').
    +  exec()

    If you call populate() multiple times with the same path, only the last +one will take effect.

    // The 2nd `populate()` call below overwrites the first because they
    +// both populate 'fans'.
    +Story.
    +  find().
    +  populate({ path: 'fans', select: 'name' }).
    +  populate({ path: 'fans', select: 'email' });
    +// The above is equivalent to:
    +Story.find().populate({ path: 'fans', select: 'email' });

    Query conditions and other options

    What if we wanted to populate our fans array based on their age, select +just their names, and return at most, any 5 of them?

    Story.
    +  find(...).
    +  populate({
    +    path: 'fans',
    +    match: { age: { $gte: 21 }},
    +    // Explicitly exclude `_id`, see http://bit.ly/2aEfTdB
    +    select: 'name -_id',
    +    options: { limit: 5 }
    +  }).
    +  exec()

    Refs to children

    We may find however, if we use the author object, we are unable to get a +list of the stories. This is because no story objects were ever 'pushed' +onto author.stories.

    -// this doesn't -Story.findOne(..).populate('_creator', ['name', 'age']).exec(..); -

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at connections.

    \ No newline at end of file +var Event = db1.model('Event', eventSchema); +var Conversation = db2.model('Conversation', conversationSchema);

    In this situation, you will not be able to populate() normally. +The conversation field will always be null, because populate() doesn't +know which model to use. However, +you can specify the model explicitly.

    Event.
    +  find().
    +  populate({ path: 'conversation', model: Conversation }).
    +  exec(function(error, docs) { /* ... */ });

    This is known as a "cross-database populate," because it enables you to +populate across MongoDB databases and even across MongoDB instances.

    Dynamic References

    Mongoose can also populate from multiple collections at the same time. +Let's say you have a user schema that has an array of "connections" - a +user can be connected to either other users or an organization.

    var userSchema = new Schema({
    +  name: String,
    +  connections: [{
    +    kind: String,
    +    item: { type: ObjectId, refPath: 'connections.kind' }
    +  }]
    +});
    +
    +var organizationSchema = new Schema({ name: String, kind: String });
    +
    +var User = mongoose.model('User', userSchema);
    +var Organization = mongoose.model('Organization', organizationSchema);

    The refPath property above means that mongoose will look at the +connections.kind path to determine which model to use for populate(). +In other words, the refPath property enables you to make the ref +property dynamic.

    // Say we have one organization:
    +// `{ _id: ObjectId('000000000000000000000001'), name: "Guns N' Roses", kind: 'Band' }`
    +// And two users:
    +// {
    +//   _id: ObjectId('000000000000000000000002')
    +//   name: 'Axl Rose',
    +//   connections: [
    +//     { kind: 'User', item: ObjectId('000000000000000000000003') },
    +//     { kind: 'Organization', item: ObjectId('000000000000000000000001') }
    +//   ]
    +// },
    +// {
    +//   _id: ObjectId('000000000000000000000003')
    +//   name: 'Slash',
    +//   connections: []
    +// }
    +User.
    +  findOne({ name: 'Axl Rose' }).
    +  populate('connections.item').
    +  exec(function(error, doc) {
    +    // doc.connections[0].item is a User doc
    +    // doc.connections[1].item is an Organization doc
    +  });
    +  

    Populate Virtuals

    New in 4.5.0

    + +

    So far you've only populated based on the _id field. However, that's +sometimes not the right choice. +In particular, arrays that grow without bound are a MongoDB anti-pattern. +Using mongoose virtuals, you can define more sophisticated relationships +between documents.

    var PersonSchema = new Schema({
    +  name: String,
    +  band: String
    +});
    +
    +var BandSchema = new Schema({
    +  name: String
    +});
    +BandSchema.virtual('members', {
    +  ref: 'Person', // The model to use
    +  localField: 'name', // Find people where `localField`
    +  foreignField: 'band', // is equal to `foreignField`
    +  // If `justOne` is true, 'members' will be a single doc as opposed to
    +  // an array. `justOne` is false by default.
    +  justOne: false
    +});
    +
    +var Person = mongoose.model('Person', personSchema);
    +var Band = mongoose.model('Band', bandSchema);
    +
    +/**
    + * Suppose you have 2 bands: "Guns N' Roses" and "Motley Crue"
    + * And 4 people: "Axl Rose" and "Slash" with "Guns N' Roses", and
    + * "Vince Neil" and "Nikki Sixx" with "Motley Crue"
    + */
    +Band.find({}).populate('members').exec(function(error, bands) {
    +  /* `bands.members` is now an array of instances of `Person` */
    +});
    +

    Keep in mind that virtuals are not included in toJSON() output by +default. If you want populate virtuals to show up when using functions +that rely on JSON.stringify(), like Express' +res.json() function, +set the virtuals: true option on your schema's toJSON options.

    // Set `virtuals: true` so `res.json()` works
    +var BandSchema = new Schema({
    +  name: String
    +}, { toJSON: { virtuals: true } });
    +

    If you're using populate projections, make sure foreignField is included +in the projection.

    Band.
    +  find({}).
    +  populate({ path: 'members', select: 'name' }).
    +  exec(function(error, bands) {
    +    // Won't work, foreign field `band` is not selected in the projection
    +  });
    +  
    +Band.
    +  find({}).
    +  populate({ path: 'members', select: 'name band' }).
    +  exec(function(error, bands) {
    +    // Works, foreign field `band` is selected
    +  });
    +  

    Next Up

    Now that we've covered query population, let's take a look at connections.

    \ No newline at end of file diff --git a/docs/prior.html b/docs/prior.html index f8a92d3494e..9b0a4964396 100644 --- a/docs/prior.html +++ b/docs/prior.html @@ -1,9 +1,26 @@ -Mongoose v3.3.1Fork me on GitHub

    Prior Release Documentation

    \ No newline at end of file +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/queries.html b/docs/queries.html index 3955265f398..43330ea9930 100644 --- a/docs/queries.html +++ b/docs/queries.html @@ -1,17 +1,16 @@ -Mongoose Queries v3.3.1Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    +Mongoose Queries v4.11.9Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    When a callback function:

    -
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    - -

    Let's take a look at what happens when passing a callback:

    var Person = db.model('Person', yourSchema);
    +
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special query builder interface.

    In mongoose 4, a Query has a .then() function, and thus can be used as a promise.

    When executing a query with a callback function, you specify your query as a JSON document. The JSON document's syntax is the same as the MongoDB shell.

    var Person = mongoose.model('Person', yourSchema);
     
     // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
     Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
       if (err) return handleError(err);
       console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    Here we see that the query was executed immediately and the results passed to our callback. -Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    +})

    Here we see that the query was executed immediately and the results passed to our callback. All callbacks in Mongoose use the pattern: +callback(error, result). If an error occurs executing the query, the error parameter will contain an error document, and result +will be null. If the query is successful, the error parameter will be null, and the result will be populated with the results of the query.

    Anywhere a callback is passed to a query in Mongoose, the callback follows the pattern callback(error, results). What results is depends on the operation: For findOne() it is a potentially-null single document, find() a list of documents, count() the number of documents, update() the number of documents affected, etc. The API docs for Models provide more detail on what is passed to the callbacks.

    Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
     var query = Person.findOne({ 'name.last': 'Ghost' });
     
     // selecting the `name` and `occupation` fields
    @@ -21,21 +20,78 @@
     query.exec(function (err, person) {
       if (err) return handleError(err);
       console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    -})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    -.find({ occupation: /host/ })
    -.where('name.last').equals('Ghost')
    -.where('age').gt(17).lt(66)
    -.where('likes').in(['vaporizing', 'talking'])
    -.limit(10)
    -.sort('-occupation')
    -.select('name occupation')
    -.exec(callback);
    -

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    \ No newline at end of file +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/redirect.jade b/docs/redirect.jade index 38d81ee14ac..9210193ce93 100644 --- a/docs/redirect.jade +++ b/docs/redirect.jade @@ -24,4 +24,4 @@ html(lang='en') block content script. document.body.className = 'load'; - include includes/googleanalytics + include includes/keen diff --git a/docs/schematypes.html b/docs/schematypes.html index 1676ab74f34..faa1765980f 100644 --- a/docs/schematypes.html +++ b/docs/schematypes.html @@ -1,9 +1,9 @@ -Mongoose SchemaTypes v3.3.1Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    +Mongoose SchemaTypes v4.11.9Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaultsvalidationgetterssettersfield selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    Example

    var schema = new Schema({
       name:    String,
       binary:  Buffer,
       living:  Boolean,
    -  updated: { type: Date, default: Date.now }
    -  age:     { type: Number, min: 18, max: 65 }
    +  updated: { type: Date, default: Date.now },
    +  age:     { type: Number, min: 18, max: 65 },
       mixed:   Schema.Types.Mixed,
       _someId: Schema.Types.ObjectId,
       array:      [],
    @@ -14,6 +14,8 @@
       ofBoolean:  [Boolean],
       ofMixed:    [Schema.Types.Mixed],
       ofObjectId: [Schema.Types.ObjectId],
    +  ofArrays:   [[]]
    +  ofArrayOfNumbers: [[Number]]
       nested: {
         stuff: { type: String, lowercase: true, trim: true }
       }
    @@ -24,29 +26,79 @@
     var Thing = mongoose.model('Thing', schema);
     
     var m = new Thing;
    -m.name = 'Statue of Liberty'
    +m.name = 'Statue of Liberty';
     m.age = 125;
     m.updated = new Date;
     m.binary = new Buffer(0);
     m.living = false;
    -m.mixed = {[ any: { thing: 'i want' } ]};
    +m.mixed = { any: { thing: 'i want' } };
     m.markModified('mixed');
     m._someId = new mongoose.Types.ObjectId;
     m.array.push(1);
     m.ofString.push("strings!");
     m.ofNumber.unshift(1,2,3,4);
    -m.ofDate.addToSet(new Date);
    +m.ofDates.addToSet(new Date);
     m.ofBuffer.pop();
     m.ofMixed = [1, [], 'three', { four: 5 }];
     m.nested.stuff = 'good';
     m.save(callback);
    -

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    +

    SchemaType Options

    You can declare a schema type using the type directly, or an object with +a type property.

    var schema1 = new Schema({
    +  test: String // `test` is a path of type String
    +});
    +
    +var schema2 = new Schema({
    +  test: { type: String } // `test` is a path of type string
    +});

    In addition to the type property, you can specify additional properties +for a path. For example, if you want to lowercase a string before saving:

    var schema2 = new Schema({
    +  test: {
    +    type: String,
    +    lowercase: true // Always convert `test` to lowercase
    +  }
    +});

    The lowercase property only works for strings. There are certain options +which apply for all schema types, and some that apply for specific schema +types.

    All Schema Types
    • required: boolean or function, if true adds a required validator for this property
    • default: Any or function, sets a default value for the path. If the value is a function, the return value of the function is used as the default.
    • select: boolean, specifies default projections for queries
    • validate: function, adds a validator function for this property
    • get: function, defines a custom getter for this property using Object.defineProperty().
    • set: function, defines a custom setter for this property using Object.defineProperty().
    • alias: string, mongoose >= 4.10.0 only. Defines a virtual with the given name that gets/sets this path.
    var numberSchema = new Schema({
    +  integerOnly: {
    +    type: Number,
    +    get: v => Math.round(v),
    +    set: v => Math.round(v),
    +    alias: 'i'
    +  }
    +});
    +
    +var Number = mongoose.model('Number', numberSchema);
    +
    +var doc = new Number();
    +doc.integerOnly = 2.001;
    +doc.integerOnly; // 2
    +doc.i; // 2
    +doc.i = 3.001;
    +doc.integerOnly; // 3
    +doc.i; // 3
    +
    Indexes

    You can also define MongoDB indexes +using schema type options.

    • index: boolean, whether to define an on this property.
    • unique: boolean, whether to define a unique index on this property.
    • sparse: boolean, whether to define a sparse index on this property.
    var schema2 = new Schema({
    +  test: {
    +    type: String,
    +    index: true,
    +    unique: true // Unique index. If you specify `unique: true`
    +    // specifying `index: true` is optional if you do `unique: true`
    +  }
    +});
    String
    • lowercase: boolean, whether to always call .toLowerCase() on the value
    • uppercase: boolean, whether to always call .toUpperCase() on the value
    • trim: boolean, whether to always call .trim() on the value
    • match: RegExp, creates a validator that checks if the value matches the given regular expression
    • enum: Array, creates a validator that checks if the value is in the given array.
    Number
    • min: Number, creates a validator that checks if the value is greater than or equal to the given minimum.
    • max: Number, creates a validator that checks if the value is less than or equal to the given maximum.
    Date
    • min: Date
    • max: Date

    Usage notes:

    Dates

    Built-in Date methods are not hooked into the mongoose change tracking logic which in English means that if you use a Date in your document and modify it with a method like setMonth(), mongoose will be unaware of this change and doc.save() will not persist this modification. If you must modify Date types using built-in methods, tell mongoose about the change with doc.markModified('pathToYourDate') before saving.

    var Assignment = mongoose.model('Assignment', { dueDate: Date });
    +Assignment.findOne(function (err, doc) {
    +  doc.dueDate.setMonth(3);
    +  doc.save(callback); // THIS DOES NOT SAVE YOUR CHANGE
    +  
    +  doc.markModified('dueDate');
    +  doc.save(callback); // works
    +})
    +

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    +var Any = new Schema({ any: Object });
     var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
     person.markModified('anything');
     person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
     var ObjectId = mongoose.Schema.Types.ObjectId;
    -var Car = new Schema({ driver: ObjectId })
    -// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    +var Car = new Schema({ driver: ObjectId });
    +// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
     var ToyBox = new Schema({
       toys: [ToySchema],
       buffers: [Buffer],
    @@ -56,12 +108,56 @@
     });

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
     var Empty2 = new Schema({ any: Array });
     var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    -var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Models.

    \ No newline at end of file +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/docs/subdocs.html b/docs/subdocs.html index efec661a579..7a0c8ae5590 100644 --- a/docs/subdocs.html +++ b/docs/subdocs.html @@ -1,49 +1,138 @@ -Mongoose SubDocuments v3.3.1Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    +Mongoose SubDocuments v4.11.9Fork me on GitHub

    Sub Docs

    Subdocuments are documents embedded in other documents. In Mongoose, this +means you can nest schemas in other schemas. Mongoose has two +distinct notions of subdocuments: arrays of subdocuments and single nested +subdocuments.

    var childSchema = new Schema({ name: 'string' });
     
     var parentSchema = new Schema({
    -  children: [childSchema]
    -})
    -

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = db.model('Parent', parentSchema);
    +  // Array of subdocuments
    +  children: [childSchema],
    +  // Single nested subdocuments. Caveat: single nested subdocs only work
    +  // in mongoose >= 4.2.0
    +  child: childSchema
    +});
    +

    Subdocuments are similar to normal documents. Nested schemas can have +middleware, custom validation logic, +virtuals, and any other feature top-level schemas can use. The major +difference is that subdocuments are +not saved individually, they are saved whenever their top-level parent +document is saved.

    var Parent = mongoose.model('Parent', parentSchema);
     var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
     parent.children[0].name = 'Matthew';
    +
    +// `parent.children[0].save()` is a no-op, it triggers middleware but
    +// does **not** actually save the subdocument. You need to save the parent
    +// doc.
     parent.save(callback);
    -

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    -  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    +

    Subdocuments have save and validate middleware +just like top-level documents. Calling save() on the parent document triggers +the save() middleware for all its subdocuments, and the same for validate() +middleware.

    childSchema.pre('save', function (next) {
    +  if ('invalid' == this.name) {
    +    return next(new Error('#sadpanda'));
    +  }
       next();
     });
     
     var parent = new Parent({ children: [{ name: 'invalid' }] });
     parent.save(function (err) {
       console.log(err.message) // #sadpanda
    -})
    -

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    -

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = db.model('Parent');
    +});
    +

    Subdocuments' pre('save') and pre('validate') middleware execute +before the top-level document's pre('save') but after the +top-level document's pre('validate') middleware. This is because validating +before save() is actually a piece of built-in middleware.

    // Below code will print out 1-4 in order
    +var childSchema = new mongoose.Schema({ name: 'string' });
    +
    +childSchema.pre('validate', function(next) {
    +  console.log('2');
    +  next();
    +});
    +
    +childSchema.pre('save', function(next) {
    +  console.log('3');
    +  next();
    +});
    +
    +var parentSchema = new mongoose.Schema({
    +  child: childSchema,
    +    });
    +    
    +parentSchema.pre('validate', function(next) {
    +  console.log('1');
    +  next();
    +});
    +
    +parentSchema.pre('save', function(next) {
    +  console.log('4');
    +  next();
    +});
    +
    +

    Finding a sub-document

    Each subdocument has an _id by default. Mongoose document arrays have a +special id method +for searching a document array to find a document with a given _id.

    var doc = parent.children.id(_id);
    +

    Adding sub-docs to arrays

    MongooseArray methods such as +push, +unshift, +addToSet, +and others cast arguments to their proper types transparently:

    var Parent = mongoose.model('Parent');
     var parent = new Parent;
     
     // create a comment
    -post.children.push({ name: 'Liesl' });
    -var doc = post.children[0];
    -console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    -doc.isNew; // true
    +parent.children.push({ name: 'Liesl' });
    +var subdoc = parent.children[0];
    +console.log(subdoc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    +subdoc.isNew; // true
     
    -post.save(function (err) {
    +parent.save(function (err) {
       if (err) return handleError(err)
       console.log('Success!');
    -});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    -

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    +});

    Sub-docs may also be created without adding them to the array by using the +create +method of MongooseArrays.

    var newdoc = parent.children.create({ name: 'Aaron' });
    +

    Removing subdocs

    Each subdocument has it's own +remove method. For +an array subdocument, this is equivalent to calling .pull() on the +subdocument. For a single nested subdocument, remove() is equivalent +to setting the subdocument to null.

    // Equivalent to `parent.children.pull(_id)`
    +parent.children.id(_id).remove();
    +// Equivalent to `parent.child = null`
    +parent.child.remove();
     parent.save(function (err) {
       if (err) return handleError(err);
    -  console.log('the sub-doc was removed')
    +  console.log('the subdocs were removed');
     });
    -

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    +

    Alternate declaration syntax for arrays

    If you create a schema with an array of objects, mongoose will automatically +convert the object to a schema for you:

    var parentSchema = new Schema({
       children: [{ name: 'string' }]
    -})
    -

    Next Up

    Now that we've covered Sub-documents, let's take a look at querying.

    \ No newline at end of file +}); +// Equivalent +var parentSchema = new Schema({ + children: [new Schema({ name: 'string' })] +}); +

    Next Up

    Now that we've covered Sub-documents, let's take a look at +querying.

    \ No newline at end of file diff --git a/docs/validation.html b/docs/validation.html index 079ab5315a6..fe7c9c6355a 100644 --- a/docs/validation.html +++ b/docs/validation.html @@ -1,37 +1,451 @@ -Mongoose Validation v3.3.1Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    +Mongoose Validation v4.11.9Fork me on GitHub

    Validation

    +

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    +
      +
    • Validation is defined in the SchemaType
    • +
    • Validation is middleware. Mongoose registers validation as a pre('save') hook on every schema by default.
    • +
    • You can manually run validation using doc.validate(callback) or doc.validateSync()
    • +
    • Validators are not run on undefined values. The only exception is the required validator.
    • +
    • Validation is asynchronously recursive; when you call Model#save, sub-document validation is executed as well. If an error occurs, your Model#save callback receives it
    • +
    • Validation is customizable
    • +
    +
    
    +    var schema = new Schema({
    +      name: {
    +        type: String,
    +        required: true
    +      }
    +    });
    +    var Cat = db.model('Cat', schema);
     
    -
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    + // This cat has no name :( + var cat = new Cat(); + cat.save(function(error) { + assert.equal(error.errors['name'].message, + 'Path `name` is required.'); -

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    -  color: String,
    -  name: String
    -});
    +      error = cat.validateSync();
    +      assert.equal(error.errors['name'].message,
    +        'Path `name` is required.');
    +    });
    +  

    Built-in Validators

    +

    Mongoose has several built-in validators.

    + +

    Each of the validator links above provide more information about how to enable them and customize their error messages.

    +
    
    +    var breakfastSchema = new Schema({
    +      eggs: {
    +        type: Number,
    +        min: [6, 'Too few eggs'],
    +        max: 12
    +      },
    +      bacon: {
    +        type: Number,
    +        required: [true, 'Why no bacon?']
    +      },
    +      drink: {
    +        type: String,
    +        enum: ['Coffee', 'Tea'],
    +        required: function() {
    +          return this.bacon > 3;
    +        }
    +      }
    +    });
    +    var Breakfast = db.model('Breakfast', breakfastSchema);
     
    -var Toy = db.model('Toy', toySchema);
    +    var badBreakfast = new Breakfast({
    +      eggs: 2,
    +      bacon: 0,
    +      drink: 'Milk'
    +    });
    +    var error = badBreakfast.validateSync();
    +    assert.equal(error.errors['eggs'].message,
    +      'Too few eggs');
    +    assert.ok(!error.errors['bacon']);
    +    assert.equal(error.errors['drink'].message,
    +      '`Milk` is not a valid enum value for path `drink`.');
     
    -Toy.schema.path('color').validate(function (value) {
    -  return /blue|green|white|red|orange|periwinkel/i.test(value);
    -}, 'Invalid color');
    +    badBreakfast.bacon = 5;
    +    badBreakfast.drink = null;
     
    -var toy = new Toy({ color: 'grease'});
    +    error = badBreakfast.validateSync();
    +    assert.equal(error.errors['drink'].message, 'Path `drink` is required.');
     
    -toy.save(function (err) {
    -  // err.errors.color is a ValidatorError object
    +    badBreakfast.bacon = null;
    +    error = badBreakfast.validateSync();
    +    assert.equal(error.errors['bacon'].message, 'Why no bacon?');
    +  

    The unique Option is Not a Validator

    +

    A common gotcha for beginners is that the unique option for schemas +is not a validator. It's a convenient helper for building MongoDB unique indexes. +See the FAQ for more information.

    +
    
    +    var uniqueUsernameSchema = new Schema({
    +      username: {
    +        type: String,
    +        unique: true
    +      }
    +    });
    +    var U1 = db.model('U1', uniqueUsernameSchema);
    +    var U2 = db.model('U2', uniqueUsernameSchema);
    +
    +    var dup = [{ username: 'Val' }, { username: 'Val' }];
    +    U1.create(dup, function(error) {
    +      // Will save successfully!
    +    });
    +
    +    // Need to wait for the index to finish building before saving,
    +    // otherwise unique constraints may be violated.
    +    U2.on('index', function(error) {
    +      assert.ifError(error);
    +      U2.create(dup, function(error) {
    +        // Will error, but will *not* be a mongoose validation error, but
    +        // a duplicate key error.
    +        assert.ok(error);
    +        assert.ok(!error.errors);
    +        assert.ok(error.message.indexOf('duplicate key error') !== -1);
    +      });
    +    });
    +  

    Custom Validators

    +

    If the built-in validators aren't enough, you can define custom validators +to suit your needs.

    +

    Custom validation is declared by passing a validation function. +You can find detailed instructions on how to do this in the +SchemaType#validate() API docs.

    +
    
    +    var userSchema = new Schema({
    +      phone: {
    +        type: String,
    +        validate: {
    +          validator: function(v) {
    +            return /\d{3}-\d{3}-\d{4}/.test(v);
    +          },
    +          message: '{VALUE} is not a valid phone number!'
    +        },
    +        required: [true, 'User phone number required']
    +      }
    +    });
    +
    +    var User = db.model('user', userSchema);
    +    var user = new User();
    +    var error;
    +
    +    user.phone = '555.0123';
    +    error = user.validateSync();
    +    assert.equal(error.errors['phone'].message,
    +      '555.0123 is not a valid phone number!');
    +
    +    user.phone = '';
    +    error = user.validateSync();
    +    assert.equal(error.errors['phone'].message,
    +      'User phone number required');
    +
    +    user.phone = '201-555-0123';
    +    // Validation succeeds! Phone number is defined
    +    // and fits `DDD-DDD-DDDD`
    +    error = user.validateSync();
    +    assert.equal(error, null);
    +  

    Async Custom Validators

    +

    Custom validators can also be asynchronous. If your validator function +takes 2 arguments, mongoose will assume the 2nd argument is a callback.

    +

    Even if you don't want to use asynchronous validators, be careful, +because mongoose 4 will assume that all functions that take 2 +arguments are asynchronous, like the +validator.isEmail function. +This behavior is considered deprecated as of 4.9.0, and you can shut +it off by specifying isAsync: false on your custom validator.

    +
    
    +    var userSchema = new Schema({
    +      phone: {
    +        type: String,
    +        validate: {
    +          // `isAsync` is not strictly necessary in mongoose 4.x, but relying
    +          // on 2 argument validators being async is deprecated. Set the
    +          // `isAsync` option to `true` to make deprecation warnings go away.
    +          isAsync: true,
    +          validator: function(v, cb) {
    +            setTimeout(function() {
    +              var phoneRegex = /\d{3}-\d{3}-\d{4}/;
    +              var msg = v + ' is not a valid phone number!';
    +              // First argument is a boolean, whether validator succeeded
    +              // 2nd argument is an optional error message override
    +              cb(phoneRegex.test(v), msg);
    +            }, 5);
    +          },
    +          // Default error message, overridden by 2nd argument to `cb()` above
    +          message: 'Default error message'
    +        },
    +        required: [true, 'User phone number required']
    +      },
    +      name: {
    +        type: String,
    +        // You can also make a validator async by returning a promise. If you
    +        // return a promise, do **not** specify the `isAsync` option.
    +        validate: function(v) {
    +          return new Promise(function(resolve, reject) {
    +            setTimeout(function() {
    +              resolve(false);
    +            }, 5);
    +          });
    +        }
    +      }
    +    });
    +
    +    var User = db.model('User', userSchema);
    +    var user = new User();
    +    var error;
    +
    +    user.phone = '555.0123';
    +    user.name = 'test';
    +    user.validate(function(error) {
    +      assert.ok(error);
    +      assert.equal(error.errors['phone'].message,
    +        '555.0123 is not a valid phone number!');
    +      assert.equal(error.errors['name'].message,
    +        'Validator failed for path `name` with value `test`');
    +    });
    +  

    Validation Errors

    +

    Errors returned after failed validation contain an errors object +holding the actual ValidatorError objects. Each +ValidatorError has kind, path, +value, and message properties.

    +
    
    +    var toySchema = new Schema({
    +      color: String,
    +      name: String
    +    });
    +
    +    var Toy = db.model('Toy', toySchema);
    +
    +    var validator = function (value) {
    +      return /blue|green|white|red|orange|periwinkle/i.test(value);
    +    };
    +    Toy.schema.path('color').validate(validator,
    +      'Color `{VALUE}` not valid', 'Invalid color');
    +
    +    var toy = new Toy({ color: 'grease'});
    +
    +    toy.save(function (err) {
    +      // err is our ValidationError object
    +      // err.errors.color is a ValidatorError object
    +      assert.equal(err.errors.color.message, 'Color `grease` not valid');
    +      assert.equal(err.errors.color.kind, 'Invalid color');
    +      assert.equal(err.errors.color.path, 'color');
    +      assert.equal(err.errors.color.value, 'grease');
    +      assert.equal(err.name, 'ValidationError');
    +    });
    +  

    Required Validators On Nested Objects

    +

    Defining validators on nested objects in mongoose is tricky, because +nested objects are not fully fledged paths.

    +
    
    +    var personSchema = new Schema({
    +      name: {
    +        first: String,
    +        last: String
    +      }
    +    });
    +
    +    assert.throws(function() {
    +      // This throws an error, because 'name' isn't a full fledged path
    +      personSchema.path('name').required(true);
    +    }, /Cannot.*'required'/);
    +
    +    // To make a nested object required, use a single nested schema
    +    var nameSchema = new Schema({
    +      first: String,
    +      last: String
    +    });
    +
    +    personSchema = new Schema({
    +      name: {
    +        type: nameSchema,
    +        required: true
    +      }
    +    });
    +
    +    var Person = db.model('Person', personSchema);
    +
    +    var person = new Person();
    +    var error = person.validateSync();
    +    assert.ok(error.errors['name']);
    +  

    Update Validators

    +

    In the above examples, you learned about document validation. Mongoose also +supports validation for update() and findOneAndUpdate() operations. +In Mongoose 4.x, update validators are off by default - you need to specify +the runValidators option.

    +

    To turn on update validators, set the runValidators option for +update() or findOneAndUpdate(). Be careful: update validators +are off by default because they have several caveats.

    +
    
    +    var toySchema = new Schema({
    +      color: String,
    +      name: String
    +    });
    +
    +    var Toy = db.model('Toys', toySchema);
    +
    +    Toy.schema.path('color').validate(function (value) {
    +      return /blue|green|white|red|orange|periwinkle/i.test(value);
    +    }, 'Invalid color');
    +
    +    var opts = { runValidators: true };
    +    Toy.update({}, { color: 'bacon' }, opts, function (err) {
    +      assert.equal(err.errors.color.message,
    +        'Invalid color');
    +    });
    +  

    Update Validators and this

    +

    There are a couple of key differences between update validators and +document validators. In the color validation function above, this refers +to the document being validated when using document validation. +However, when running update validators, the document being updated +may not be in the server's memory, so by default the value of this is +not defined.

    +
    
    +    var toySchema = new Schema({
    +      color: String,
    +      name: String
    +    });
    +
    +    toySchema.path('color').validate(function(value) {
    +      // When running in `validate()` or `validateSync()`, the
    +      // validator can access the document using `this`.
    +      // Does **not** work with update validators.
    +      if (this.name.toLowerCase().indexOf('red') !== -1) {
    +        return value !== 'red';
    +      }
    +      return true;
    +    });
    +
    +    var Toy = db.model('ActionFigure', toySchema);
    +
    +    var toy = new Toy({ color: 'red', name: 'Red Power Ranger' });
    +    var error = toy.validateSync();
    +    assert.ok(error.errors['color']);
    +
    +    var update = { color: 'red', name: 'Red Power Ranger' };
    +    var opts = { runValidators: true };
    +
    +    Toy.update({}, update, opts, function(error) {
    +      // The update validator throws an error:
    +      // "TypeError: Cannot read property 'toLowerCase' of undefined",
    +      // because `this` is **not** the document being updated when using
    +      // update validators
    +      assert.ok(error);
    +    });
    +  

    The context option

    +

    The context option lets you set the value of this in update validators +to the underlying query.

    +
    
    +    toySchema.path('color').validate(function(value) {
    +      // When running update validators with the `context` option set to
    +      // 'query', `this` refers to the query object.
    +      if (this.getUpdate().$set.name.toLowerCase().indexOf('red') !== -1) {
    +        return value === 'red';
    +      }
    +      return true;
    +    });
    +
    +    var Toy = db.model('Figure', toySchema);
    +
    +    var update = { color: 'blue', name: 'Red Power Ranger' };
    +    // Note the context option
    +    var opts = { runValidators: true, context: 'query' };
    +
    +    Toy.update({}, update, opts, function(error) {
    +      assert.ok(error.errors['color']);
    +    });
    +  

    Update Validator Paths

    +

    The other key difference that update validators only run on the paths +specified in the update. For instance, in the below example, because +'name' is not specified in the update operation, update validation will +succeed.

    +

    When using update validators, required validators only fail when +you try to explicitly $unset the key.

    +
    
    +    var kittenSchema = new Schema({
    +      name: { type: String, required: true },
    +      age: Number
    +    });
    +
    +    var Kitten = db.model('Kitten', kittenSchema);
    +
    +    var update = { color: 'blue' };
    +    var opts = { runValidators: true };
    +    Kitten.update({}, update, opts, function(err) {
    +      // Operation succeeds despite the fact that 'name' is not specified
    +    });
    +
    +    var unset = { $unset: { name: 1 } };
    +    Kitten.update({}, unset, opts, function(err) {
    +      // Operation fails because 'name' is required
    +      assert.ok(err);
    +      assert.ok(err.errors['name']);
    +    });
    +  

    Update Validators Only Run On Specified Paths

    +

    One final detail worth noting: update validators only run on $set +and $unset operations (and $push and $addToSet in >= 4.8.0). +For instance, the below update will succeed, regardless of the value of +number, because update validators ignore $inc.

    +
    
    +    var testSchema = new Schema({
    +      number: { type: Number, max: 0 },
    +    });
    +
    +    var Test = db.model('Test', testSchema);
    +
    +    var update = { $inc: { number: 1 } };
    +    var opts = { runValidators: true };
    +    Test.update({}, update, opts, function(error) {
    +      // There will never be a validation error here
    +    });
    +  

    On $push and $addToSet

    +

    New in 4.8.0: update validators also run on $push and $addToSet

    +
    
    +    var testSchema = new Schema({
    +      numbers: [{ type: Number, max: 0 }],
    +      docs: [{
    +        name: { type: String, required: true }
    +      }]
    +    });
    +
    +    var Test = db.model('TestPush', testSchema);
    +
    +    var update = {
    +      $push: {
    +        numbers: 1,
    +        docs: { name: null }
    +      }
    +    };
    +    var opts = { runValidators: true };
    +    Test.update({}, update, opts, function(error) {
    +      assert.ok(error.errors['numbers']);
    +      assert.ok(error.errors['docs']);
    +    });
    +  
    \ No newline at end of file + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/index.html b/index.html index a7b481e8bcb..37be0705e32 100644 --- a/index.html +++ b/index.html @@ -1,19 +1,30 @@ -Mongoose ODM v3.6.17Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    • Version 3.6.17

    Let's face it, writing MongoDB validation, casting and business logic boilerplate is a drag. That's why we wrote Mongoose.

    var mongoose = require('mongoose');
    +Mongoose ODM v4.11.9Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    • Version 4.11.9

    Let's face it, writing MongoDB validation, casting and business logic boilerplate is a drag. That's why we wrote Mongoose.

    var mongoose = require('mongoose');
     mongoose.connect('mongodb://localhost/test');
     
     var Cat = mongoose.model('Cat', { name: String });
     
     var kitty = new Cat({ name: 'Zildjian' });
     kitty.save(function (err) {
    -  if (err) // ...
    -  console.log('meow');
    -});

    Mongoose provides a straight-forward, schema-based solution to modeling your application data and includes built-in type casting, validation, query building, business logic hooks and more, out of the box.

    Getting Started

    Support

    Changelog

    Unstable

    Production - View More

    • Storify
    • LearnBoost
    • GeekList
    • McDonalds
    • ShoeJitsu
    • Bozuko
    +KeenAsync.ready(function(){ + // Configure a client instance + var client = new KeenAsync({ + projectId: '59aad9cbc9e77c0001ce1b32', + writeKey: '4B38B0046086885E425D368BFAEAD8FD0D4F2DC2FA2F936FDE058D79508AEFAD9886BC020B96520823BB9C8241D9D9BCFDC0EF52E6033BD89D06E4B24FC13AE955896BF443406269A84DD009CEB5862DCEC944874DB2107FD648DA91ADC1E6DE' + }); + + client.recordEvent('pageView', { + host: window.location.host, + pathname: window.location.pathname, + hash: window.location.hash + }); +}); \ No newline at end of file diff --git a/index.jade b/index.jade index eb69d02a82a..245287d4bb6 100644 --- a/index.jade +++ b/index.jade @@ -127,4 +127,4 @@ html(lang='en') p#footer Licensed under MIT. Copyright 2011 LearnBoost. script. document.body.className = 'load'; - include docs/includes/googleanalytics + include docs/includes/keen From c120ab58654f48c1311c110d8cc8de196f234a1f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Sep 2017 19:12:03 -0700 Subject: [PATCH 1836/2240] test(connection): repro #4513 --- test/connection.test.js | 164 +++++++++++++++++++++++++--------------- 1 file changed, 102 insertions(+), 62 deletions(-) diff --git a/test/connection.test.js b/test/connection.test.js index 08fff3fd09a..55ab769d9f8 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -75,71 +75,111 @@ describe('connections:', function() { }).catch(done); }); - it('events (gh-5498) (gh-5524)', function(done) { - this.timeout(25000); - - var conn; - var stopped = false; - var numConnected = 0; - var numDisconnected = 0; - var numReconnected = 0; - server.start(). - then(function() { - conn = mongoose.connect('mongodb://localhost:27000/mongoosetest', { - useMongoClient: true - }); + describe('connection events', function() { + beforeEach(function() { + return server.start(). + then(function() { return server.purge(); }); + }); - conn.on('connected', function() { - ++numConnected; - }); - conn.on('disconnected', function() { - ++numDisconnected; - }); - conn.on('reconnected', function() { - ++numReconnected; - }); + afterEach(function() { + return server.stop(); + }); - return conn; - }). - then(function() { - assert.equal(numConnected, 1); - return server.stop(); - }). - then(function() { - stopped = true; - return new Promise(function(resolve) { - setTimeout(function() { resolve(); }, 50); - }); - }). - then(function() { - assert.equal(numDisconnected, 1); - assert.equal(numReconnected, 0); - }). - then(function() { - return server.start(); - }). - then(function() { - stopped = false; - return new Promise(function(resolve) { - setTimeout(function() { resolve(); }, 2000); + it('disconnected (gh-5498) (gh-5524)', function(done) { + this.timeout(25000); + + var conn; + var stopped = false; + var numConnected = 0; + var numDisconnected = 0; + var numReconnected = 0; + conn = mongoose.connect('mongodb://localhost:27000/mongoosetest', { + useMongoClient: true + }); + + conn.on('connected', function() { + ++numConnected; + }); + conn.on('disconnected', function() { + ++numDisconnected; + }); + conn.on('reconnected', function() { + ++numReconnected; + }); + + conn. + then(function() { + assert.equal(numConnected, 1); + return server.stop(); + }). + then(function() { + stopped = true; + return new Promise(function(resolve) { + setTimeout(function() { resolve(); }, 50); + }); + }). + then(function() { + assert.equal(numDisconnected, 1); + assert.equal(numReconnected, 0); + }). + then(function() { + return server.start(); + }). + then(function() { + stopped = false; + return new Promise(function(resolve) { + setTimeout(function() { resolve(); }, 2000); + }); + }). + then(function() { + assert.equal(numDisconnected, 1); + assert.equal(numReconnected, 1); + done(); + }). + catch(done); + }); + + it('timeout (gh-4513)', function(done) { + this.timeout(25000); + + var conn; + var stopped = false; + var numTimeout = 0; + var numDisconnected = 0; + conn = mongoose.connect('mongodb://localhost:27000/mongoosetest', { + useMongoClient: true, + socketTimeoutMS: 100, + poolSize: 1 + }); + + conn.on('timeout', function() { + ++numTimeout; + }); + + conn.on('disconnected', function() { + ++numDisconnected; + }); + + var Model = conn.model('gh4513', new Schema()); + + conn. + then(function() { + return Model.create({}); + }). + then(function() { + return Model.find({ $where: 'sleep(250) || true' }); + }). + then(function() { + done(new Error('expected timeout')); + }). + catch(function(error) { + assert.ok(error); + assert.ok(error.message.indexOf('timed out'), error.message); + assert.equal(numTimeout, 1); + assert.equal(numDisconnected, 0); + done(); }); - }). - then(function() { - assert.equal(numDisconnected, 1); - assert.equal(numReconnected, 1); - done(); - }). - catch(finish); - - function finish(err) { - if (stopped) { - server.start(). - then(function() { done(err); }). - catch(done); - } else { - done(err); - } - } + }); }); }); From 714357bd6accf4fb98aa993757e334bb4d400b56 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Sep 2017 19:12:07 -0700 Subject: [PATCH 1837/2240] fix(connection): emit timeout event on socket timeout Fix #4513 --- lib/connection.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 9c03dc9123b..ea1d74b5bb2 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -769,6 +769,9 @@ Connection.prototype.openUri = function(uri, options, callback) { db.s.topology.on('close', function() { _this.emit('disconnected'); }); + db.on('timeout', function() { + _this.emit('timeout'); + }); _this.db = db; _this.readyState = STATES.connected; From d000ea96808c9fac6eb5fbc33cded7cacdbbbb9e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Sep 2017 19:17:20 -0700 Subject: [PATCH 1838/2240] style: fix lint --- test/connection.test.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/connection.test.js b/test/connection.test.js index 55ab769d9f8..ae68e32c1ec 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -89,7 +89,6 @@ describe('connections:', function() { this.timeout(25000); var conn; - var stopped = false; var numConnected = 0; var numDisconnected = 0; var numReconnected = 0; @@ -113,7 +112,6 @@ describe('connections:', function() { return server.stop(); }). then(function() { - stopped = true; return new Promise(function(resolve) { setTimeout(function() { resolve(); }, 50); }); @@ -126,7 +124,6 @@ describe('connections:', function() { return server.start(); }). then(function() { - stopped = false; return new Promise(function(resolve) { setTimeout(function() { resolve(); }, 2000); }); @@ -143,7 +140,6 @@ describe('connections:', function() { this.timeout(25000); var conn; - var stopped = false; var numTimeout = 0; var numDisconnected = 0; conn = mongoose.connect('mongodb://localhost:27000/mongoosetest', { From 4d7e976878e4e379eaa836ec129a5e81ce06e26e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Sep 2017 19:21:19 -0700 Subject: [PATCH 1839/2240] test: extend timeout for connection stop/start tests --- test/connection.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/connection.test.js b/test/connection.test.js index ae68e32c1ec..32c02cb193d 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -77,11 +77,13 @@ describe('connections:', function() { describe('connection events', function() { beforeEach(function() { + this.timeout(10000); return server.start(). then(function() { return server.purge(); }); }); afterEach(function() { + this.timeout(10000); return server.stop(); }); From 529df28a0976224b588be37d87525fb861b39304 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Sep 2017 12:01:56 -0700 Subject: [PATCH 1840/2240] test(populate): repro #5564 --- test/model.populate.test.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index ad8b882f17e..0d373c1b9e6 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5527,6 +5527,35 @@ describe('model: populate:', function() { catch(done); }); + it('does not set `populated()` until populate is done (gh-5564)', function() { + var userSchema = new mongoose.Schema({}); + var User = db.model('gh5564', userSchema); + + var testSchema = new mongoose.Schema({ + users: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'gh5564' + }] + }); + var Test = db.model('gh5564_0', testSchema); + + return User.create({}). + then(function(user) { + return Test.create({ users: [user._id] }); + }). + then(function(test) { + var promise = test.populate('users').execPopulate(); + assert.ok(!test.populated('users')); + return promise; + }). + then(function(test) { + assert.ok(test.populated('users')); + assert.ok(test.users[0]._id); + assert.equal(test.users.length, 1); + assert.equal(test.populated('users').length, 1); + }); + }); + it('virtual populate toJSON output (gh-5542)', function(done) { var AuthorSchema = new mongoose.Schema({ name: String From 129ba3a6d5adf1c40ecfa4ff4442a0912db729f1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Sep 2017 12:02:01 -0700 Subject: [PATCH 1841/2240] fix(populate): don't mark path as populated until populate() is done Fix #5564 --- lib/model.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index b48f35249cc..b7fce587ab8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3136,6 +3136,14 @@ function populate(model, docs, options, callback) { var key; var val; + // Clone because `assignRawDocsToIdStructure` will mutate the array + var allIds = [].concat(mod.allIds.map(function(v) { + if (Array.isArray(v)) { + return [].concat(v); + } + return v; + })); + // optimization: // record the document positions as returned by // the query result. @@ -3197,6 +3205,7 @@ function populate(model, docs, options, callback) { assignVals({ originalModel: model, rawIds: mod.allIds, + allIds: allIds, localField: mod.localField, foreignField: mod.foreignField, rawDocs: rawDocs, @@ -3259,6 +3268,9 @@ function assignVals(o) { } cur = cur[parts[j]]; } + if (docs[i].$__) { + docs[i].populated(o.path, o.allIds[i]); + } utils.setValue(o.path, rawIds[i], docs[i], setValue); } } @@ -3454,9 +3466,6 @@ function getModelsMapForPopulate(model, docs, options) { var ret = convertTo_id(utils.getValue(localField, doc)); var id = String(utils.getValue(foreignField, doc)); options._docs[id] = Array.isArray(ret) ? ret.slice() : ret; - if (doc.$__) { - doc.populated(options.path, options._docs[id], options); - } var k = modelNames.length; while (k--) { From 6c2e00dfbdca5fc428be9089b021dd84f278ceee Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Sep 2017 12:14:16 -0700 Subject: [PATCH 1842/2240] docs: add back 3.x docs --- docs/3.0.x/docs/api.html | 6444 ++++++ docs/3.0.x/docs/api.jade | 508 + docs/3.0.x/docs/contributing.html | 11 + docs/3.0.x/docs/contributing.jade | 22 + docs/3.0.x/docs/css/default.css | 135 + docs/3.0.x/docs/css/guide.css | 283 + docs/3.0.x/docs/documents.html | 20 + docs/3.0.x/docs/documents.jade | 38 + docs/3.0.x/docs/faq.html | 31 + docs/3.0.x/docs/faq.jade | 63 + docs/3.0.x/docs/guide.html | 133 + docs/3.0.x/docs/guide.jade | 364 + docs/3.0.x/docs/helpers/filters.js | 20 + docs/3.0.x/docs/helpers/highlight.js | 11 + docs/3.0.x/docs/helpers/href.js | 5 + docs/3.0.x/docs/helpers/klass.js | 5 + docs/3.0.x/docs/helpers/linktype.js | 50 + docs/3.0.x/docs/images/apps/grab | 39 + docs/3.0.x/docs/images/apps/urls | 21 + docs/3.0.x/docs/images/square_bg.png | Bin 0 -> 2217 bytes docs/3.0.x/docs/includes/googleanalytics.jade | 10 + docs/3.0.x/docs/includes/nav.jade | 53 + docs/3.0.x/docs/index.html | 36 + docs/3.0.x/docs/index.jade | 119 + docs/3.0.x/docs/js/zepto.min.js | 2 + docs/3.0.x/docs/layout.jade | 25 + docs/3.0.x/docs/middleware.html | 29 + docs/3.0.x/docs/middleware.jade | 71 + docs/3.0.x/docs/migration.html | 38 + docs/3.0.x/docs/migration.jade | 272 + docs/3.0.x/docs/models.html | 32 + docs/3.0.x/docs/models.jade | 57 + docs/3.0.x/docs/plugins.html | 33 + docs/3.0.x/docs/plugins.jade | 38 + docs/3.0.x/docs/populate.html | 98 + docs/3.0.x/docs/populate.jade | 145 + docs/3.0.x/docs/prior.html | 9 + docs/3.0.x/docs/prior.jade | 8 + docs/3.0.x/docs/queries.html | 41 + docs/3.0.x/docs/queries.jade | 59 + docs/3.0.x/docs/releases | 1 + docs/3.0.x/docs/schematypes.html | 67 + docs/3.0.x/docs/schematypes.jade | 142 + docs/3.0.x/docs/source/_docs | 15928 ++++++++++++++ docs/3.0.x/docs/source/api.js | 220 + docs/3.0.x/docs/source/home.js | 19 + docs/3.0.x/docs/source/index.js | 18 + docs/3.0.x/docs/source/prior.js | 13 + docs/3.0.x/docs/subdocs.html | 48 + docs/3.0.x/docs/subdocs.jade | 80 + docs/3.0.x/docs/validation.html | 36 + docs/3.0.x/docs/validation.jade | 54 + docs/3.0.x/index.html | 238 + docs/3.0.x/static.js | 17 + docs/3.1.x/docs/api.html | 6720 ++++++ docs/3.1.x/docs/api.jade | 508 + docs/3.1.x/docs/contributing.html | 11 + docs/3.1.x/docs/contributing.jade | 22 + docs/3.1.x/docs/css/default.css | 135 + docs/3.1.x/docs/css/guide.css | 283 + docs/3.1.x/docs/documents.html | 20 + docs/3.1.x/docs/documents.jade | 42 + docs/3.1.x/docs/faq.html | 31 + docs/3.1.x/docs/faq.jade | 63 + docs/3.1.x/docs/guide.html | 170 + docs/3.1.x/docs/guide.jade | 428 + docs/3.1.x/docs/helpers/filters.js | 20 + docs/3.1.x/docs/helpers/highlight.js | 11 + docs/3.1.x/docs/helpers/href.js | 5 + docs/3.1.x/docs/helpers/klass.js | 5 + docs/3.1.x/docs/helpers/linktype.js | 50 + docs/3.1.x/docs/images/apps/grab | 39 + docs/3.1.x/docs/images/apps/urls | 21 + docs/3.1.x/docs/images/square_bg.png | Bin 0 -> 2217 bytes docs/3.1.x/docs/includes/googleanalytics.jade | 10 + docs/3.1.x/docs/includes/nav.jade | 53 + docs/3.1.x/docs/index.html | 36 + docs/3.1.x/docs/index.jade | 119 + docs/3.1.x/docs/js/zepto.min.js | 2 + docs/3.1.x/docs/layout.jade | 25 + docs/3.1.x/docs/middleware.html | 29 + docs/3.1.x/docs/middleware.jade | 74 + docs/3.1.x/docs/migration.html | 38 + docs/3.1.x/docs/migration.jade | 272 + docs/3.1.x/docs/models.html | 32 + docs/3.1.x/docs/models.jade | 61 + docs/3.1.x/docs/plugins.html | 33 + docs/3.1.x/docs/plugins.jade | 42 + docs/3.1.x/docs/populate.html | 104 + docs/3.1.x/docs/populate.jade | 164 + docs/3.1.x/docs/prior.html | 9 + docs/3.1.x/docs/prior.jade | 8 + docs/3.1.x/docs/queries.html | 41 + docs/3.1.x/docs/queries.jade | 62 + docs/3.1.x/docs/releases | 2 + docs/3.1.x/docs/schematypes.html | 67 + docs/3.1.x/docs/schematypes.jade | 146 + docs/3.1.x/docs/source/_docs | 16169 ++++++++++++++ docs/3.1.x/docs/source/api.js | 220 + docs/3.1.x/docs/source/home.js | 19 + docs/3.1.x/docs/source/index.js | 18 + docs/3.1.x/docs/source/prior.js | 13 + docs/3.1.x/docs/subdocs.html | 49 + docs/3.1.x/docs/subdocs.jade | 84 + docs/3.1.x/docs/validation.html | 37 + docs/3.1.x/docs/validation.jade | 58 + docs/3.1.x/index.html | 238 + docs/3.1.x/static.js | 17 + docs/3.2.x/docs/api.html | 6828 ++++++ docs/3.2.x/docs/api.jade | 507 + docs/3.2.x/docs/connections.html | 27 + docs/3.2.x/docs/connections.jade | 65 + docs/3.2.x/docs/contributing.html | 9 + docs/3.2.x/docs/contributing.jade | 8 + docs/3.2.x/docs/css/default.css | 135 + docs/3.2.x/docs/css/guide.css | 281 + docs/3.2.x/docs/css/style.css | 207 + docs/3.2.x/docs/documents.html | 20 + docs/3.2.x/docs/documents.jade | 42 + docs/3.2.x/docs/faq.html | 31 + docs/3.2.x/docs/faq.jade | 63 + docs/3.2.x/docs/guide.html | 187 + docs/3.2.x/docs/guide.jade | 450 + docs/3.2.x/docs/helpers/filters.js | 20 + docs/3.2.x/docs/helpers/highlight.js | 11 + docs/3.2.x/docs/helpers/href.js | 5 + docs/3.2.x/docs/helpers/klass.js | 5 + docs/3.2.x/docs/helpers/linktype.js | 50 + docs/3.2.x/docs/images/apps/attictv.png | Bin 0 -> 42666 bytes docs/3.2.x/docs/images/apps/bozuko.png | Bin 0 -> 37827 bytes docs/3.2.x/docs/images/apps/calllist.png | Bin 0 -> 33502 bytes docs/3.2.x/docs/images/apps/cldfy.png | Bin 0 -> 9773 bytes docs/3.2.x/docs/images/apps/clickdummy.png | Bin 0 -> 34210 bytes docs/3.2.x/docs/images/apps/cyborgvision.png | Bin 0 -> 42616 bytes docs/3.2.x/docs/images/apps/furbabyrescue.png | Bin 0 -> 49891 bytes docs/3.2.x/docs/images/apps/geeklist.png | Bin 0 -> 27911 bytes docs/3.2.x/docs/images/apps/grab | 71 + .../docs/images/apps/growthegamegolf.png | Bin 0 -> 43441 bytes docs/3.2.x/docs/images/apps/kyyti.png | Bin 0 -> 41966 bytes docs/3.2.x/docs/images/apps/learnboost.png | Bin 0 -> 31434 bytes docs/3.2.x/docs/images/apps/linkr.png | Bin 0 -> 6428 bytes docs/3.2.x/docs/images/apps/lists.png | Bin 0 -> 697 bytes docs/3.2.x/docs/images/apps/localresponse.png | Bin 0 -> 26423 bytes docs/3.2.x/docs/images/apps/nextdays.png | Bin 0 -> 35067 bytes docs/3.2.x/docs/images/apps/nimblequiz.png | Bin 0 -> 20990 bytes docs/3.2.x/docs/images/apps/nuorder.png | Bin 0 -> 38163 bytes docs/3.2.x/docs/images/apps/scottyapp.png | Bin 0 -> 118416 bytes docs/3.2.x/docs/images/apps/seelio.png | Bin 0 -> 24005 bytes docs/3.2.x/docs/images/apps/selectvids.png | Bin 0 -> 42214 bytes docs/3.2.x/docs/images/apps/sharelatex.png | Bin 0 -> 19707 bytes docs/3.2.x/docs/images/apps/shoejitsu.png | Bin 0 -> 35092 bytes docs/3.2.x/docs/images/apps/skim.png | Bin 0 -> 43580 bytes docs/3.2.x/docs/images/apps/stachify.png | Bin 0 -> 27783 bytes docs/3.2.x/docs/images/apps/storify.png | Bin 0 -> 55982 bytes docs/3.2.x/docs/images/apps/todaylaunch.png | Bin 0 -> 33233 bytes docs/3.2.x/docs/images/apps/treinosmart.png | Bin 0 -> 26723 bytes docs/3.2.x/docs/images/apps/upcload.png | Bin 0 -> 37792 bytes docs/3.2.x/docs/images/apps/urls | 27 + docs/3.2.x/docs/images/apps/wavo.png | Bin 0 -> 54906 bytes docs/3.2.x/docs/images/square_bg.png | Bin 0 -> 2217 bytes docs/3.2.x/docs/includes/googleanalytics.jade | 10 + docs/3.2.x/docs/includes/nav.jade | 55 + docs/3.2.x/docs/index.html | 36 + docs/3.2.x/docs/index.jade | 119 + docs/3.2.x/docs/js/zepto.min.js | 2 + docs/3.2.x/docs/layout.jade | 25 + docs/3.2.x/docs/middleware.html | 29 + docs/3.2.x/docs/middleware.jade | 74 + docs/3.2.x/docs/migration.html | 40 + docs/3.2.x/docs/migration.jade | 280 + docs/3.2.x/docs/models.html | 32 + docs/3.2.x/docs/models.jade | 61 + docs/3.2.x/docs/plugins.html | 33 + docs/3.2.x/docs/plugins.jade | 42 + docs/3.2.x/docs/populate.html | 104 + docs/3.2.x/docs/populate.jade | 164 + docs/3.2.x/docs/prior.html | 9 + docs/3.2.x/docs/prior.jade | 8 + docs/3.2.x/docs/queries.html | 41 + docs/3.2.x/docs/queries.jade | 62 + docs/3.2.x/docs/releases | 2 + docs/3.2.x/docs/schematypes.html | 67 + docs/3.2.x/docs/schematypes.jade | 146 + docs/3.2.x/docs/source/_docs | 16201 ++++++++++++++ docs/3.2.x/docs/source/api.js | 220 + docs/3.2.x/docs/source/home.js | 19 + docs/3.2.x/docs/source/index.js | 19 + docs/3.2.x/docs/source/prior.js | 13 + docs/3.2.x/docs/subdocs.html | 49 + docs/3.2.x/docs/subdocs.jade | 84 + docs/3.2.x/docs/validation.html | 37 + docs/3.2.x/docs/validation.jade | 58 + docs/3.2.x/index.html | 20 + docs/3.2.x/static.js | 17 + docs/3.3.x/docs/api.html | 6883 ++++++ docs/3.3.x/docs/api.jade | 517 + docs/3.3.x/docs/connections.html | 27 + docs/3.3.x/docs/connections.jade | 65 + docs/3.3.x/docs/contributing.html | 9 + docs/3.3.x/docs/contributing.jade | 8 + docs/3.3.x/docs/css/default.css | 135 + docs/3.3.x/docs/css/guide.css | 326 + docs/3.3.x/docs/css/style.css | 225 + docs/3.3.x/docs/documents.html | 20 + docs/3.3.x/docs/documents.jade | 42 + docs/3.3.x/docs/faq.html | 31 + docs/3.3.x/docs/faq.jade | 63 + docs/3.3.x/docs/guide.html | 188 + docs/3.3.x/docs/guide.jade | 457 + docs/3.3.x/docs/helpers/filters.js | 20 + docs/3.3.x/docs/helpers/highlight.js | 11 + docs/3.3.x/docs/helpers/href.js | 5 + docs/3.3.x/docs/helpers/klass.js | 5 + docs/3.3.x/docs/helpers/linktype.js | 50 + docs/3.3.x/docs/images/apps/attictv.png | Bin 0 -> 42666 bytes docs/3.3.x/docs/images/apps/bozuko.png | Bin 0 -> 37827 bytes docs/3.3.x/docs/images/apps/calllist.png | Bin 0 -> 33502 bytes docs/3.3.x/docs/images/apps/cldfy.png | Bin 0 -> 9773 bytes docs/3.3.x/docs/images/apps/clickdummy.png | Bin 0 -> 34210 bytes docs/3.3.x/docs/images/apps/cyborgvision.png | Bin 0 -> 42616 bytes docs/3.3.x/docs/images/apps/dashku.png | Bin 0 -> 25043 bytes .../docs/images/apps/firstimpression.png | Bin 0 -> 32241 bytes docs/3.3.x/docs/images/apps/furbabyrescue.png | Bin 0 -> 49891 bytes docs/3.3.x/docs/images/apps/geeklist.png | Bin 0 -> 27911 bytes docs/3.3.x/docs/images/apps/grab | 71 + .../docs/images/apps/growthegamegolf.png | Bin 0 -> 43441 bytes docs/3.3.x/docs/images/apps/h_bozuko.jpg | Bin 0 -> 11928 bytes docs/3.3.x/docs/images/apps/h_geeklist.png | Bin 0 -> 3482 bytes docs/3.3.x/docs/images/apps/h_learnboost.png | Bin 0 -> 12727 bytes docs/3.3.x/docs/images/apps/h_mcds.png | Bin 0 -> 3904 bytes docs/3.3.x/docs/images/apps/h_shoejitsu.png | Bin 0 -> 12695 bytes docs/3.3.x/docs/images/apps/h_storify.jpg | Bin 0 -> 14291 bytes docs/3.3.x/docs/images/apps/kyyti.png | Bin 0 -> 41966 bytes docs/3.3.x/docs/images/apps/learnboost.png | Bin 0 -> 31434 bytes docs/3.3.x/docs/images/apps/linkr.png | Bin 0 -> 6428 bytes docs/3.3.x/docs/images/apps/lists.png | Bin 0 -> 697 bytes docs/3.3.x/docs/images/apps/localresponse.png | Bin 0 -> 26423 bytes docs/3.3.x/docs/images/apps/mcdonalds.png | Bin 0 -> 57481 bytes docs/3.3.x/docs/images/apps/muffle.png | Bin 0 -> 26658 bytes docs/3.3.x/docs/images/apps/nextdays.png | Bin 0 -> 35067 bytes docs/3.3.x/docs/images/apps/nimblequiz.png | Bin 0 -> 20990 bytes docs/3.3.x/docs/images/apps/nuorder.png | Bin 0 -> 38163 bytes docs/3.3.x/docs/images/apps/scottyapp.png | Bin 0 -> 118416 bytes docs/3.3.x/docs/images/apps/seelio.png | Bin 0 -> 24005 bytes docs/3.3.x/docs/images/apps/selectvids.png | Bin 0 -> 42214 bytes docs/3.3.x/docs/images/apps/sharelatex.png | Bin 0 -> 19707 bytes docs/3.3.x/docs/images/apps/shoejitsu.png | Bin 0 -> 35092 bytes docs/3.3.x/docs/images/apps/skim.png | Bin 0 -> 43580 bytes docs/3.3.x/docs/images/apps/squadsheet.png | Bin 0 -> 37071 bytes docs/3.3.x/docs/images/apps/stachify.png | Bin 0 -> 27783 bytes docs/3.3.x/docs/images/apps/storify.png | Bin 0 -> 55982 bytes docs/3.3.x/docs/images/apps/todaylaunch.png | Bin 0 -> 33233 bytes docs/3.3.x/docs/images/apps/treinosmart.png | Bin 0 -> 26723 bytes docs/3.3.x/docs/images/apps/upcload.png | Bin 0 -> 37792 bytes docs/3.3.x/docs/images/apps/urls | 34 + docs/3.3.x/docs/images/apps/veriwalk.png | Bin 0 -> 28311 bytes docs/3.3.x/docs/images/apps/wavo.png | Bin 0 -> 54906 bytes docs/3.3.x/docs/images/apps/zootify.png | Bin 0 -> 44707 bytes docs/3.3.x/docs/images/square_bg.png | Bin 0 -> 2217 bytes docs/3.3.x/docs/includes/googleanalytics.jade | 10 + docs/3.3.x/docs/includes/nav.jade | 55 + docs/3.3.x/docs/index.html | 36 + docs/3.3.x/docs/index.jade | 119 + docs/3.3.x/docs/js/cookies.min.js | 4 + docs/3.3.x/docs/js/zepto.min.js | 2 + docs/3.3.x/docs/layout.jade | 25 + docs/3.3.x/docs/middleware.html | 29 + docs/3.3.x/docs/middleware.jade | 74 + docs/3.3.x/docs/migration.html | 40 + docs/3.3.x/docs/migration.jade | 280 + docs/3.3.x/docs/models.html | 32 + docs/3.3.x/docs/models.jade | 61 + docs/3.3.x/docs/plugins.html | 33 + docs/3.3.x/docs/plugins.jade | 42 + docs/3.3.x/docs/populate.html | 104 + docs/3.3.x/docs/populate.jade | 164 + docs/3.3.x/docs/prior.html | 9 + docs/3.3.x/docs/prior.jade | 8 + docs/3.3.x/docs/production.html | 9 + docs/3.3.x/docs/production.jade | 11 + docs/3.3.x/docs/queries.html | 41 + docs/3.3.x/docs/queries.jade | 62 + docs/3.3.x/docs/releases | 5 + docs/3.3.x/docs/schematypes.html | 67 + docs/3.3.x/docs/schematypes.jade | 146 + docs/3.3.x/docs/source/_docs | 16292 ++++++++++++++ docs/3.3.x/docs/source/api.js | 220 + docs/3.3.x/docs/source/home.js | 7 + docs/3.3.x/docs/source/index.js | 20 + docs/3.3.x/docs/source/prior.js | 13 + docs/3.3.x/docs/source/production.js | 17 + docs/3.3.x/docs/subdocs.html | 49 + docs/3.3.x/docs/subdocs.jade | 84 + docs/3.3.x/docs/validation.html | 37 + docs/3.3.x/docs/validation.jade | 58 + docs/3.3.x/docs/website.js | 48 + docs/3.3.x/index.html | 20 + docs/3.3.x/static.js | 17 + docs/3.4.x/docs/api.html | 6999 ++++++ docs/3.4.x/docs/connections.html | 27 + docs/3.4.x/docs/contributing.html | 9 + docs/3.4.x/docs/css/default.css | 135 + docs/3.4.x/docs/css/guide.css | 326 + docs/3.4.x/docs/css/style.css | 225 + docs/3.4.x/docs/documents.html | 20 + docs/3.4.x/docs/faq.html | 31 + docs/3.4.x/docs/guide.html | 190 + docs/3.4.x/docs/helpers/filters.js | 20 + docs/3.4.x/docs/helpers/highlight.js | 11 + docs/3.4.x/docs/helpers/href.js | 5 + docs/3.4.x/docs/helpers/klass.js | 5 + docs/3.4.x/docs/helpers/linktype.js | 50 + docs/3.4.x/docs/images/apps/attictv.png | Bin 0 -> 42666 bytes docs/3.4.x/docs/images/apps/bozuko.png | Bin 0 -> 37827 bytes docs/3.4.x/docs/images/apps/calllist.png | Bin 0 -> 33502 bytes docs/3.4.x/docs/images/apps/cldfy.png | Bin 0 -> 9773 bytes docs/3.4.x/docs/images/apps/clickdummy.png | Bin 0 -> 34210 bytes docs/3.4.x/docs/images/apps/cyborgvision.png | Bin 0 -> 42616 bytes docs/3.4.x/docs/images/apps/dashku.png | Bin 0 -> 25043 bytes .../docs/images/apps/firstimpression.png | Bin 0 -> 32241 bytes docs/3.4.x/docs/images/apps/furbabyrescue.png | Bin 0 -> 49891 bytes docs/3.4.x/docs/images/apps/geeklist.png | Bin 0 -> 27911 bytes docs/3.4.x/docs/images/apps/grab | 71 + .../docs/images/apps/growthegamegolf.png | Bin 0 -> 43441 bytes docs/3.4.x/docs/images/apps/h_bozuko.jpg | Bin 0 -> 11928 bytes docs/3.4.x/docs/images/apps/h_geeklist.png | Bin 0 -> 3482 bytes docs/3.4.x/docs/images/apps/h_learnboost.png | Bin 0 -> 12727 bytes docs/3.4.x/docs/images/apps/h_mcds.png | Bin 0 -> 3904 bytes docs/3.4.x/docs/images/apps/h_shoejitsu.png | Bin 0 -> 12695 bytes docs/3.4.x/docs/images/apps/h_storify.jpg | Bin 0 -> 14291 bytes docs/3.4.x/docs/images/apps/kyyti.png | Bin 0 -> 41966 bytes docs/3.4.x/docs/images/apps/learnboost.png | Bin 0 -> 31434 bytes docs/3.4.x/docs/images/apps/linkr.png | Bin 0 -> 6428 bytes docs/3.4.x/docs/images/apps/lists.png | Bin 0 -> 697 bytes docs/3.4.x/docs/images/apps/localresponse.png | Bin 0 -> 26423 bytes docs/3.4.x/docs/images/apps/mcdonalds.png | Bin 0 -> 57481 bytes docs/3.4.x/docs/images/apps/muffle.png | Bin 0 -> 26658 bytes docs/3.4.x/docs/images/apps/nextdays.png | Bin 0 -> 35067 bytes docs/3.4.x/docs/images/apps/nimblequiz.png | Bin 0 -> 20990 bytes docs/3.4.x/docs/images/apps/nuorder.png | Bin 0 -> 38163 bytes docs/3.4.x/docs/images/apps/scottyapp.png | Bin 0 -> 118416 bytes docs/3.4.x/docs/images/apps/seelio.png | Bin 0 -> 24005 bytes docs/3.4.x/docs/images/apps/selectvids.png | Bin 0 -> 42214 bytes docs/3.4.x/docs/images/apps/sharelatex.png | Bin 0 -> 19707 bytes docs/3.4.x/docs/images/apps/shoejitsu.png | Bin 0 -> 35092 bytes docs/3.4.x/docs/images/apps/skim.png | Bin 0 -> 43580 bytes docs/3.4.x/docs/images/apps/squadsheet.png | Bin 0 -> 37071 bytes docs/3.4.x/docs/images/apps/stachify.png | Bin 0 -> 27783 bytes docs/3.4.x/docs/images/apps/storify.png | Bin 0 -> 55982 bytes docs/3.4.x/docs/images/apps/todaylaunch.png | Bin 0 -> 33233 bytes docs/3.4.x/docs/images/apps/treinosmart.png | Bin 0 -> 26723 bytes docs/3.4.x/docs/images/apps/upcload.png | Bin 0 -> 37792 bytes docs/3.4.x/docs/images/apps/urls | 34 + docs/3.4.x/docs/images/apps/veriwalk.png | Bin 0 -> 28311 bytes docs/3.4.x/docs/images/apps/wavo.png | Bin 0 -> 54906 bytes docs/3.4.x/docs/images/apps/zootify.png | Bin 0 -> 44707 bytes docs/3.4.x/docs/images/square_bg.png | Bin 0 -> 2217 bytes docs/3.4.x/docs/includes/googleanalytics.jade | 10 + docs/3.4.x/docs/includes/nav.jade | 55 + docs/3.4.x/docs/index.html | 41 + docs/3.4.x/docs/js/cookies.min.js | 4 + docs/3.4.x/docs/js/zepto.min.js | 2 + docs/3.4.x/docs/middleware.html | 29 + docs/3.4.x/docs/migration.html | 40 + docs/3.4.x/docs/models.html | 31 + docs/3.4.x/docs/plugins.html | 33 + docs/3.4.x/docs/populate.html | 104 + docs/3.4.x/docs/prior.html | 9 + docs/3.4.x/docs/production.html | 9 + docs/3.4.x/docs/queries.html | 41 + docs/3.4.x/docs/releases | 6 + docs/3.4.x/docs/schematypes.html | 67 + docs/3.4.x/docs/source/_docs | 16713 ++++++++++++++ docs/3.4.x/docs/source/api.js | 220 + docs/3.4.x/docs/source/home.js | 7 + docs/3.4.x/docs/source/index.js | 20 + docs/3.4.x/docs/source/prior.js | 13 + docs/3.4.x/docs/source/production.js | 17 + docs/3.4.x/docs/subdocs.html | 49 + docs/3.4.x/docs/validation.html | 37 + docs/3.4.x/docs/website.js | 48 + docs/3.4.x/index.html | 20 + docs/3.4.x/static.js | 17 + docs/3.5.x/docs/api.html | 7225 ++++++ docs/3.5.x/docs/connections.html | 32 + docs/3.5.x/docs/contributing.html | 9 + docs/3.5.x/docs/css/api.css | 244 + docs/3.5.x/docs/css/default.css | 135 + docs/3.5.x/docs/css/guide.css | 332 + docs/3.5.x/docs/css/style.css | 255 + docs/3.5.x/docs/documents.html | 20 + docs/3.5.x/docs/faq.html | 31 + docs/3.5.x/docs/guide.html | 200 + docs/3.5.x/docs/helpers/filters.js | 20 + docs/3.5.x/docs/helpers/highlight.js | 11 + docs/3.5.x/docs/helpers/href.js | 8 + docs/3.5.x/docs/helpers/klass.js | 5 + docs/3.5.x/docs/helpers/linktype.js | 50 + docs/3.5.x/docs/images/apps/attictv.png | Bin 0 -> 42666 bytes docs/3.5.x/docs/images/apps/bozuko.png | Bin 0 -> 37827 bytes docs/3.5.x/docs/images/apps/calllist.png | Bin 0 -> 33502 bytes docs/3.5.x/docs/images/apps/cldfy.png | Bin 0 -> 9773 bytes docs/3.5.x/docs/images/apps/clickdummy.png | Bin 0 -> 34210 bytes docs/3.5.x/docs/images/apps/cyborgvision.png | Bin 0 -> 42616 bytes docs/3.5.x/docs/images/apps/dashku.png | Bin 0 -> 25043 bytes .../docs/images/apps/firstimpression.png | Bin 0 -> 32241 bytes docs/3.5.x/docs/images/apps/furbabyrescue.png | Bin 0 -> 49891 bytes docs/3.5.x/docs/images/apps/geeklist.png | Bin 0 -> 27911 bytes docs/3.5.x/docs/images/apps/grab | 71 + .../docs/images/apps/growthegamegolf.png | Bin 0 -> 43441 bytes docs/3.5.x/docs/images/apps/h_bozuko.jpg | Bin 0 -> 11928 bytes docs/3.5.x/docs/images/apps/h_geeklist.png | Bin 0 -> 3482 bytes docs/3.5.x/docs/images/apps/h_learnboost.png | Bin 0 -> 12727 bytes docs/3.5.x/docs/images/apps/h_mcds.png | Bin 0 -> 3904 bytes docs/3.5.x/docs/images/apps/h_shoejitsu.png | Bin 0 -> 12695 bytes docs/3.5.x/docs/images/apps/h_storify.jpg | Bin 0 -> 14291 bytes docs/3.5.x/docs/images/apps/knack.png | Bin 0 -> 29572 bytes docs/3.5.x/docs/images/apps/kyyti.png | Bin 0 -> 41966 bytes docs/3.5.x/docs/images/apps/learnboost.png | Bin 0 -> 31434 bytes docs/3.5.x/docs/images/apps/linkr.png | Bin 0 -> 6428 bytes docs/3.5.x/docs/images/apps/lists.png | Bin 0 -> 697 bytes docs/3.5.x/docs/images/apps/localresponse.png | Bin 0 -> 26423 bytes docs/3.5.x/docs/images/apps/mcdonalds.png | Bin 0 -> 57481 bytes docs/3.5.x/docs/images/apps/moveline.png | Bin 0 -> 30271 bytes docs/3.5.x/docs/images/apps/muffle.png | Bin 0 -> 26658 bytes docs/3.5.x/docs/images/apps/mybrickbuilds.png | Bin 0 -> 42263 bytes docs/3.5.x/docs/images/apps/nextdays.png | Bin 0 -> 35067 bytes docs/3.5.x/docs/images/apps/nimblequiz.png | Bin 0 -> 20990 bytes docs/3.5.x/docs/images/apps/nuorder.png | Bin 0 -> 38163 bytes docs/3.5.x/docs/images/apps/panemerkille.png | Bin 0 -> 26344 bytes docs/3.5.x/docs/images/apps/pictorious.png | Bin 0 -> 45953 bytes docs/3.5.x/docs/images/apps/scottyapp.png | Bin 0 -> 118416 bytes docs/3.5.x/docs/images/apps/seelio.png | Bin 0 -> 24005 bytes docs/3.5.x/docs/images/apps/selectvids.png | Bin 0 -> 42214 bytes docs/3.5.x/docs/images/apps/sharelatex.png | Bin 0 -> 19707 bytes docs/3.5.x/docs/images/apps/shoejitsu.png | Bin 0 -> 35092 bytes docs/3.5.x/docs/images/apps/skim.png | Bin 0 -> 43580 bytes docs/3.5.x/docs/images/apps/squadsheet.png | Bin 0 -> 37071 bytes docs/3.5.x/docs/images/apps/stachify.png | Bin 0 -> 27783 bytes docs/3.5.x/docs/images/apps/storify.png | Bin 0 -> 55982 bytes docs/3.5.x/docs/images/apps/todaylaunch.png | Bin 0 -> 33233 bytes docs/3.5.x/docs/images/apps/treinosmart.png | Bin 0 -> 26723 bytes docs/3.5.x/docs/images/apps/upcload.png | Bin 0 -> 37792 bytes docs/3.5.x/docs/images/apps/urls | 39 + docs/3.5.x/docs/images/apps/veriwalk.png | Bin 0 -> 28311 bytes docs/3.5.x/docs/images/apps/wavo.png | Bin 0 -> 54906 bytes docs/3.5.x/docs/images/apps/zootify.png | Bin 0 -> 44707 bytes docs/3.5.x/docs/images/square_bg.png | Bin 0 -> 2217 bytes docs/3.5.x/docs/includes/googleanalytics.jade | 10 + docs/3.5.x/docs/includes/nav.jade | 55 + docs/3.5.x/docs/index.html | 43 + docs/3.5.x/docs/js/cookies.min.js | 4 + docs/3.5.x/docs/js/zepto.min.js | 2 + docs/3.5.x/docs/middleware.html | 40 + docs/3.5.x/docs/migration.html | 40 + docs/3.5.x/docs/models.html | 30 + docs/3.5.x/docs/plugins.html | 33 + docs/3.5.x/docs/populate.html | 104 + docs/3.5.x/docs/prior.html | 9 + docs/3.5.x/docs/production.html | 9 + docs/3.5.x/docs/queries.html | 41 + docs/3.5.x/docs/schematypes.html | 67 + docs/3.5.x/docs/source/_docs | 18108 ++++++++++++++++ docs/3.5.x/docs/source/api.js | 223 + docs/3.5.x/docs/source/home.js | 7 + docs/3.5.x/docs/source/index.js | 20 + docs/3.5.x/docs/source/prior.js | 13 + docs/3.5.x/docs/source/production.js | 17 + docs/3.5.x/docs/subdocs.html | 49 + docs/3.5.x/docs/validation.html | 37 + docs/3.5.x/index.html | 20 + docs/3.5.x/static.js | 17 + docs/api.html | 2 +- 473 files changed, 161449 insertions(+), 1 deletion(-) create mode 100644 docs/3.0.x/docs/api.html create mode 100644 docs/3.0.x/docs/api.jade create mode 100644 docs/3.0.x/docs/contributing.html create mode 100644 docs/3.0.x/docs/contributing.jade create mode 100644 docs/3.0.x/docs/css/default.css create mode 100644 docs/3.0.x/docs/css/guide.css create mode 100644 docs/3.0.x/docs/documents.html create mode 100644 docs/3.0.x/docs/documents.jade create mode 100644 docs/3.0.x/docs/faq.html create mode 100644 docs/3.0.x/docs/faq.jade create mode 100644 docs/3.0.x/docs/guide.html create mode 100644 docs/3.0.x/docs/guide.jade create mode 100644 docs/3.0.x/docs/helpers/filters.js create mode 100644 docs/3.0.x/docs/helpers/highlight.js create mode 100644 docs/3.0.x/docs/helpers/href.js create mode 100644 docs/3.0.x/docs/helpers/klass.js create mode 100644 docs/3.0.x/docs/helpers/linktype.js create mode 100755 docs/3.0.x/docs/images/apps/grab create mode 100644 docs/3.0.x/docs/images/apps/urls create mode 100644 docs/3.0.x/docs/images/square_bg.png create mode 100644 docs/3.0.x/docs/includes/googleanalytics.jade create mode 100644 docs/3.0.x/docs/includes/nav.jade create mode 100644 docs/3.0.x/docs/index.html create mode 100644 docs/3.0.x/docs/index.jade create mode 100644 docs/3.0.x/docs/js/zepto.min.js create mode 100644 docs/3.0.x/docs/layout.jade create mode 100644 docs/3.0.x/docs/middleware.html create mode 100644 docs/3.0.x/docs/middleware.jade create mode 100644 docs/3.0.x/docs/migration.html create mode 100644 docs/3.0.x/docs/migration.jade create mode 100644 docs/3.0.x/docs/models.html create mode 100644 docs/3.0.x/docs/models.jade create mode 100644 docs/3.0.x/docs/plugins.html create mode 100644 docs/3.0.x/docs/plugins.jade create mode 100644 docs/3.0.x/docs/populate.html create mode 100644 docs/3.0.x/docs/populate.jade create mode 100644 docs/3.0.x/docs/prior.html create mode 100644 docs/3.0.x/docs/prior.jade create mode 100644 docs/3.0.x/docs/queries.html create mode 100644 docs/3.0.x/docs/queries.jade create mode 100644 docs/3.0.x/docs/releases create mode 100644 docs/3.0.x/docs/schematypes.html create mode 100644 docs/3.0.x/docs/schematypes.jade create mode 100644 docs/3.0.x/docs/source/_docs create mode 100644 docs/3.0.x/docs/source/api.js create mode 100644 docs/3.0.x/docs/source/home.js create mode 100644 docs/3.0.x/docs/source/index.js create mode 100644 docs/3.0.x/docs/source/prior.js create mode 100644 docs/3.0.x/docs/subdocs.html create mode 100644 docs/3.0.x/docs/subdocs.jade create mode 100644 docs/3.0.x/docs/validation.html create mode 100644 docs/3.0.x/docs/validation.jade create mode 100644 docs/3.0.x/index.html create mode 100644 docs/3.0.x/static.js create mode 100644 docs/3.1.x/docs/api.html create mode 100644 docs/3.1.x/docs/api.jade create mode 100644 docs/3.1.x/docs/contributing.html create mode 100644 docs/3.1.x/docs/contributing.jade create mode 100644 docs/3.1.x/docs/css/default.css create mode 100644 docs/3.1.x/docs/css/guide.css create mode 100644 docs/3.1.x/docs/documents.html create mode 100644 docs/3.1.x/docs/documents.jade create mode 100644 docs/3.1.x/docs/faq.html create mode 100644 docs/3.1.x/docs/faq.jade create mode 100644 docs/3.1.x/docs/guide.html create mode 100644 docs/3.1.x/docs/guide.jade create mode 100644 docs/3.1.x/docs/helpers/filters.js create mode 100644 docs/3.1.x/docs/helpers/highlight.js create mode 100644 docs/3.1.x/docs/helpers/href.js create mode 100644 docs/3.1.x/docs/helpers/klass.js create mode 100644 docs/3.1.x/docs/helpers/linktype.js create mode 100755 docs/3.1.x/docs/images/apps/grab create mode 100644 docs/3.1.x/docs/images/apps/urls create mode 100644 docs/3.1.x/docs/images/square_bg.png create mode 100644 docs/3.1.x/docs/includes/googleanalytics.jade create mode 100644 docs/3.1.x/docs/includes/nav.jade create mode 100644 docs/3.1.x/docs/index.html create mode 100644 docs/3.1.x/docs/index.jade create mode 100644 docs/3.1.x/docs/js/zepto.min.js create mode 100644 docs/3.1.x/docs/layout.jade create mode 100644 docs/3.1.x/docs/middleware.html create mode 100644 docs/3.1.x/docs/middleware.jade create mode 100644 docs/3.1.x/docs/migration.html create mode 100644 docs/3.1.x/docs/migration.jade create mode 100644 docs/3.1.x/docs/models.html create mode 100644 docs/3.1.x/docs/models.jade create mode 100644 docs/3.1.x/docs/plugins.html create mode 100644 docs/3.1.x/docs/plugins.jade create mode 100644 docs/3.1.x/docs/populate.html create mode 100644 docs/3.1.x/docs/populate.jade create mode 100644 docs/3.1.x/docs/prior.html create mode 100644 docs/3.1.x/docs/prior.jade create mode 100644 docs/3.1.x/docs/queries.html create mode 100644 docs/3.1.x/docs/queries.jade create mode 100644 docs/3.1.x/docs/releases create mode 100644 docs/3.1.x/docs/schematypes.html create mode 100644 docs/3.1.x/docs/schematypes.jade create mode 100644 docs/3.1.x/docs/source/_docs create mode 100644 docs/3.1.x/docs/source/api.js create mode 100644 docs/3.1.x/docs/source/home.js create mode 100644 docs/3.1.x/docs/source/index.js create mode 100644 docs/3.1.x/docs/source/prior.js create mode 100644 docs/3.1.x/docs/subdocs.html create mode 100644 docs/3.1.x/docs/subdocs.jade create mode 100644 docs/3.1.x/docs/validation.html create mode 100644 docs/3.1.x/docs/validation.jade create mode 100644 docs/3.1.x/index.html create mode 100644 docs/3.1.x/static.js create mode 100644 docs/3.2.x/docs/api.html create mode 100644 docs/3.2.x/docs/api.jade create mode 100644 docs/3.2.x/docs/connections.html create mode 100644 docs/3.2.x/docs/connections.jade create mode 100644 docs/3.2.x/docs/contributing.html create mode 100644 docs/3.2.x/docs/contributing.jade create mode 100644 docs/3.2.x/docs/css/default.css create mode 100644 docs/3.2.x/docs/css/guide.css create mode 100644 docs/3.2.x/docs/css/style.css create mode 100644 docs/3.2.x/docs/documents.html create mode 100644 docs/3.2.x/docs/documents.jade create mode 100644 docs/3.2.x/docs/faq.html create mode 100644 docs/3.2.x/docs/faq.jade create mode 100644 docs/3.2.x/docs/guide.html create mode 100644 docs/3.2.x/docs/guide.jade create mode 100644 docs/3.2.x/docs/helpers/filters.js create mode 100644 docs/3.2.x/docs/helpers/highlight.js create mode 100644 docs/3.2.x/docs/helpers/href.js create mode 100644 docs/3.2.x/docs/helpers/klass.js create mode 100644 docs/3.2.x/docs/helpers/linktype.js create mode 100644 docs/3.2.x/docs/images/apps/attictv.png create mode 100644 docs/3.2.x/docs/images/apps/bozuko.png create mode 100644 docs/3.2.x/docs/images/apps/calllist.png create mode 100644 docs/3.2.x/docs/images/apps/cldfy.png create mode 100644 docs/3.2.x/docs/images/apps/clickdummy.png create mode 100644 docs/3.2.x/docs/images/apps/cyborgvision.png create mode 100644 docs/3.2.x/docs/images/apps/furbabyrescue.png create mode 100644 docs/3.2.x/docs/images/apps/geeklist.png create mode 100755 docs/3.2.x/docs/images/apps/grab create mode 100644 docs/3.2.x/docs/images/apps/growthegamegolf.png create mode 100644 docs/3.2.x/docs/images/apps/kyyti.png create mode 100644 docs/3.2.x/docs/images/apps/learnboost.png create mode 100644 docs/3.2.x/docs/images/apps/linkr.png create mode 100644 docs/3.2.x/docs/images/apps/lists.png create mode 100644 docs/3.2.x/docs/images/apps/localresponse.png create mode 100644 docs/3.2.x/docs/images/apps/nextdays.png create mode 100644 docs/3.2.x/docs/images/apps/nimblequiz.png create mode 100644 docs/3.2.x/docs/images/apps/nuorder.png create mode 100644 docs/3.2.x/docs/images/apps/scottyapp.png create mode 100644 docs/3.2.x/docs/images/apps/seelio.png create mode 100644 docs/3.2.x/docs/images/apps/selectvids.png create mode 100644 docs/3.2.x/docs/images/apps/sharelatex.png create mode 100644 docs/3.2.x/docs/images/apps/shoejitsu.png create mode 100644 docs/3.2.x/docs/images/apps/skim.png create mode 100644 docs/3.2.x/docs/images/apps/stachify.png create mode 100644 docs/3.2.x/docs/images/apps/storify.png create mode 100644 docs/3.2.x/docs/images/apps/todaylaunch.png create mode 100644 docs/3.2.x/docs/images/apps/treinosmart.png create mode 100644 docs/3.2.x/docs/images/apps/upcload.png create mode 100644 docs/3.2.x/docs/images/apps/urls create mode 100644 docs/3.2.x/docs/images/apps/wavo.png create mode 100644 docs/3.2.x/docs/images/square_bg.png create mode 100644 docs/3.2.x/docs/includes/googleanalytics.jade create mode 100644 docs/3.2.x/docs/includes/nav.jade create mode 100644 docs/3.2.x/docs/index.html create mode 100644 docs/3.2.x/docs/index.jade create mode 100644 docs/3.2.x/docs/js/zepto.min.js create mode 100644 docs/3.2.x/docs/layout.jade create mode 100644 docs/3.2.x/docs/middleware.html create mode 100644 docs/3.2.x/docs/middleware.jade create mode 100644 docs/3.2.x/docs/migration.html create mode 100644 docs/3.2.x/docs/migration.jade create mode 100644 docs/3.2.x/docs/models.html create mode 100644 docs/3.2.x/docs/models.jade create mode 100644 docs/3.2.x/docs/plugins.html create mode 100644 docs/3.2.x/docs/plugins.jade create mode 100644 docs/3.2.x/docs/populate.html create mode 100644 docs/3.2.x/docs/populate.jade create mode 100644 docs/3.2.x/docs/prior.html create mode 100644 docs/3.2.x/docs/prior.jade create mode 100644 docs/3.2.x/docs/queries.html create mode 100644 docs/3.2.x/docs/queries.jade create mode 100644 docs/3.2.x/docs/releases create mode 100644 docs/3.2.x/docs/schematypes.html create mode 100644 docs/3.2.x/docs/schematypes.jade create mode 100644 docs/3.2.x/docs/source/_docs create mode 100644 docs/3.2.x/docs/source/api.js create mode 100644 docs/3.2.x/docs/source/home.js create mode 100644 docs/3.2.x/docs/source/index.js create mode 100644 docs/3.2.x/docs/source/prior.js create mode 100644 docs/3.2.x/docs/subdocs.html create mode 100644 docs/3.2.x/docs/subdocs.jade create mode 100644 docs/3.2.x/docs/validation.html create mode 100644 docs/3.2.x/docs/validation.jade create mode 100644 docs/3.2.x/index.html create mode 100644 docs/3.2.x/static.js create mode 100644 docs/3.3.x/docs/api.html create mode 100644 docs/3.3.x/docs/api.jade create mode 100644 docs/3.3.x/docs/connections.html create mode 100644 docs/3.3.x/docs/connections.jade create mode 100644 docs/3.3.x/docs/contributing.html create mode 100644 docs/3.3.x/docs/contributing.jade create mode 100644 docs/3.3.x/docs/css/default.css create mode 100644 docs/3.3.x/docs/css/guide.css create mode 100644 docs/3.3.x/docs/css/style.css create mode 100644 docs/3.3.x/docs/documents.html create mode 100644 docs/3.3.x/docs/documents.jade create mode 100644 docs/3.3.x/docs/faq.html create mode 100644 docs/3.3.x/docs/faq.jade create mode 100644 docs/3.3.x/docs/guide.html create mode 100644 docs/3.3.x/docs/guide.jade create mode 100644 docs/3.3.x/docs/helpers/filters.js create mode 100644 docs/3.3.x/docs/helpers/highlight.js create mode 100644 docs/3.3.x/docs/helpers/href.js create mode 100644 docs/3.3.x/docs/helpers/klass.js create mode 100644 docs/3.3.x/docs/helpers/linktype.js create mode 100644 docs/3.3.x/docs/images/apps/attictv.png create mode 100644 docs/3.3.x/docs/images/apps/bozuko.png create mode 100644 docs/3.3.x/docs/images/apps/calllist.png create mode 100644 docs/3.3.x/docs/images/apps/cldfy.png create mode 100644 docs/3.3.x/docs/images/apps/clickdummy.png create mode 100644 docs/3.3.x/docs/images/apps/cyborgvision.png create mode 100644 docs/3.3.x/docs/images/apps/dashku.png create mode 100644 docs/3.3.x/docs/images/apps/firstimpression.png create mode 100644 docs/3.3.x/docs/images/apps/furbabyrescue.png create mode 100644 docs/3.3.x/docs/images/apps/geeklist.png create mode 100755 docs/3.3.x/docs/images/apps/grab create mode 100644 docs/3.3.x/docs/images/apps/growthegamegolf.png create mode 100644 docs/3.3.x/docs/images/apps/h_bozuko.jpg create mode 100644 docs/3.3.x/docs/images/apps/h_geeklist.png create mode 100644 docs/3.3.x/docs/images/apps/h_learnboost.png create mode 100644 docs/3.3.x/docs/images/apps/h_mcds.png create mode 100644 docs/3.3.x/docs/images/apps/h_shoejitsu.png create mode 100644 docs/3.3.x/docs/images/apps/h_storify.jpg create mode 100644 docs/3.3.x/docs/images/apps/kyyti.png create mode 100644 docs/3.3.x/docs/images/apps/learnboost.png create mode 100644 docs/3.3.x/docs/images/apps/linkr.png create mode 100644 docs/3.3.x/docs/images/apps/lists.png create mode 100644 docs/3.3.x/docs/images/apps/localresponse.png create mode 100644 docs/3.3.x/docs/images/apps/mcdonalds.png create mode 100644 docs/3.3.x/docs/images/apps/muffle.png create mode 100644 docs/3.3.x/docs/images/apps/nextdays.png create mode 100644 docs/3.3.x/docs/images/apps/nimblequiz.png create mode 100644 docs/3.3.x/docs/images/apps/nuorder.png create mode 100644 docs/3.3.x/docs/images/apps/scottyapp.png create mode 100644 docs/3.3.x/docs/images/apps/seelio.png create mode 100644 docs/3.3.x/docs/images/apps/selectvids.png create mode 100644 docs/3.3.x/docs/images/apps/sharelatex.png create mode 100644 docs/3.3.x/docs/images/apps/shoejitsu.png create mode 100644 docs/3.3.x/docs/images/apps/skim.png create mode 100644 docs/3.3.x/docs/images/apps/squadsheet.png create mode 100644 docs/3.3.x/docs/images/apps/stachify.png create mode 100644 docs/3.3.x/docs/images/apps/storify.png create mode 100644 docs/3.3.x/docs/images/apps/todaylaunch.png create mode 100644 docs/3.3.x/docs/images/apps/treinosmart.png create mode 100644 docs/3.3.x/docs/images/apps/upcload.png create mode 100644 docs/3.3.x/docs/images/apps/urls create mode 100644 docs/3.3.x/docs/images/apps/veriwalk.png create mode 100644 docs/3.3.x/docs/images/apps/wavo.png create mode 100644 docs/3.3.x/docs/images/apps/zootify.png create mode 100644 docs/3.3.x/docs/images/square_bg.png create mode 100644 docs/3.3.x/docs/includes/googleanalytics.jade create mode 100644 docs/3.3.x/docs/includes/nav.jade create mode 100644 docs/3.3.x/docs/index.html create mode 100644 docs/3.3.x/docs/index.jade create mode 100644 docs/3.3.x/docs/js/cookies.min.js create mode 100644 docs/3.3.x/docs/js/zepto.min.js create mode 100644 docs/3.3.x/docs/layout.jade create mode 100644 docs/3.3.x/docs/middleware.html create mode 100644 docs/3.3.x/docs/middleware.jade create mode 100644 docs/3.3.x/docs/migration.html create mode 100644 docs/3.3.x/docs/migration.jade create mode 100644 docs/3.3.x/docs/models.html create mode 100644 docs/3.3.x/docs/models.jade create mode 100644 docs/3.3.x/docs/plugins.html create mode 100644 docs/3.3.x/docs/plugins.jade create mode 100644 docs/3.3.x/docs/populate.html create mode 100644 docs/3.3.x/docs/populate.jade create mode 100644 docs/3.3.x/docs/prior.html create mode 100644 docs/3.3.x/docs/prior.jade create mode 100644 docs/3.3.x/docs/production.html create mode 100644 docs/3.3.x/docs/production.jade create mode 100644 docs/3.3.x/docs/queries.html create mode 100644 docs/3.3.x/docs/queries.jade create mode 100644 docs/3.3.x/docs/releases create mode 100644 docs/3.3.x/docs/schematypes.html create mode 100644 docs/3.3.x/docs/schematypes.jade create mode 100644 docs/3.3.x/docs/source/_docs create mode 100644 docs/3.3.x/docs/source/api.js create mode 100644 docs/3.3.x/docs/source/home.js create mode 100644 docs/3.3.x/docs/source/index.js create mode 100644 docs/3.3.x/docs/source/prior.js create mode 100644 docs/3.3.x/docs/source/production.js create mode 100644 docs/3.3.x/docs/subdocs.html create mode 100644 docs/3.3.x/docs/subdocs.jade create mode 100644 docs/3.3.x/docs/validation.html create mode 100644 docs/3.3.x/docs/validation.jade create mode 100644 docs/3.3.x/docs/website.js create mode 100644 docs/3.3.x/index.html create mode 100644 docs/3.3.x/static.js create mode 100644 docs/3.4.x/docs/api.html create mode 100644 docs/3.4.x/docs/connections.html create mode 100644 docs/3.4.x/docs/contributing.html create mode 100644 docs/3.4.x/docs/css/default.css create mode 100644 docs/3.4.x/docs/css/guide.css create mode 100644 docs/3.4.x/docs/css/style.css create mode 100644 docs/3.4.x/docs/documents.html create mode 100644 docs/3.4.x/docs/faq.html create mode 100644 docs/3.4.x/docs/guide.html create mode 100644 docs/3.4.x/docs/helpers/filters.js create mode 100644 docs/3.4.x/docs/helpers/highlight.js create mode 100644 docs/3.4.x/docs/helpers/href.js create mode 100644 docs/3.4.x/docs/helpers/klass.js create mode 100644 docs/3.4.x/docs/helpers/linktype.js create mode 100644 docs/3.4.x/docs/images/apps/attictv.png create mode 100644 docs/3.4.x/docs/images/apps/bozuko.png create mode 100644 docs/3.4.x/docs/images/apps/calllist.png create mode 100644 docs/3.4.x/docs/images/apps/cldfy.png create mode 100644 docs/3.4.x/docs/images/apps/clickdummy.png create mode 100644 docs/3.4.x/docs/images/apps/cyborgvision.png create mode 100644 docs/3.4.x/docs/images/apps/dashku.png create mode 100644 docs/3.4.x/docs/images/apps/firstimpression.png create mode 100644 docs/3.4.x/docs/images/apps/furbabyrescue.png create mode 100644 docs/3.4.x/docs/images/apps/geeklist.png create mode 100755 docs/3.4.x/docs/images/apps/grab create mode 100644 docs/3.4.x/docs/images/apps/growthegamegolf.png create mode 100644 docs/3.4.x/docs/images/apps/h_bozuko.jpg create mode 100644 docs/3.4.x/docs/images/apps/h_geeklist.png create mode 100644 docs/3.4.x/docs/images/apps/h_learnboost.png create mode 100644 docs/3.4.x/docs/images/apps/h_mcds.png create mode 100644 docs/3.4.x/docs/images/apps/h_shoejitsu.png create mode 100644 docs/3.4.x/docs/images/apps/h_storify.jpg create mode 100644 docs/3.4.x/docs/images/apps/kyyti.png create mode 100644 docs/3.4.x/docs/images/apps/learnboost.png create mode 100644 docs/3.4.x/docs/images/apps/linkr.png create mode 100644 docs/3.4.x/docs/images/apps/lists.png create mode 100644 docs/3.4.x/docs/images/apps/localresponse.png create mode 100644 docs/3.4.x/docs/images/apps/mcdonalds.png create mode 100644 docs/3.4.x/docs/images/apps/muffle.png create mode 100644 docs/3.4.x/docs/images/apps/nextdays.png create mode 100644 docs/3.4.x/docs/images/apps/nimblequiz.png create mode 100644 docs/3.4.x/docs/images/apps/nuorder.png create mode 100644 docs/3.4.x/docs/images/apps/scottyapp.png create mode 100644 docs/3.4.x/docs/images/apps/seelio.png create mode 100644 docs/3.4.x/docs/images/apps/selectvids.png create mode 100644 docs/3.4.x/docs/images/apps/sharelatex.png create mode 100644 docs/3.4.x/docs/images/apps/shoejitsu.png create mode 100644 docs/3.4.x/docs/images/apps/skim.png create mode 100644 docs/3.4.x/docs/images/apps/squadsheet.png create mode 100644 docs/3.4.x/docs/images/apps/stachify.png create mode 100644 docs/3.4.x/docs/images/apps/storify.png create mode 100644 docs/3.4.x/docs/images/apps/todaylaunch.png create mode 100644 docs/3.4.x/docs/images/apps/treinosmart.png create mode 100644 docs/3.4.x/docs/images/apps/upcload.png create mode 100644 docs/3.4.x/docs/images/apps/urls create mode 100644 docs/3.4.x/docs/images/apps/veriwalk.png create mode 100644 docs/3.4.x/docs/images/apps/wavo.png create mode 100644 docs/3.4.x/docs/images/apps/zootify.png create mode 100644 docs/3.4.x/docs/images/square_bg.png create mode 100644 docs/3.4.x/docs/includes/googleanalytics.jade create mode 100644 docs/3.4.x/docs/includes/nav.jade create mode 100644 docs/3.4.x/docs/index.html create mode 100644 docs/3.4.x/docs/js/cookies.min.js create mode 100644 docs/3.4.x/docs/js/zepto.min.js create mode 100644 docs/3.4.x/docs/middleware.html create mode 100644 docs/3.4.x/docs/migration.html create mode 100644 docs/3.4.x/docs/models.html create mode 100644 docs/3.4.x/docs/plugins.html create mode 100644 docs/3.4.x/docs/populate.html create mode 100644 docs/3.4.x/docs/prior.html create mode 100644 docs/3.4.x/docs/production.html create mode 100644 docs/3.4.x/docs/queries.html create mode 100644 docs/3.4.x/docs/releases create mode 100644 docs/3.4.x/docs/schematypes.html create mode 100644 docs/3.4.x/docs/source/_docs create mode 100644 docs/3.4.x/docs/source/api.js create mode 100644 docs/3.4.x/docs/source/home.js create mode 100644 docs/3.4.x/docs/source/index.js create mode 100644 docs/3.4.x/docs/source/prior.js create mode 100644 docs/3.4.x/docs/source/production.js create mode 100644 docs/3.4.x/docs/subdocs.html create mode 100644 docs/3.4.x/docs/validation.html create mode 100644 docs/3.4.x/docs/website.js create mode 100644 docs/3.4.x/index.html create mode 100644 docs/3.4.x/static.js create mode 100644 docs/3.5.x/docs/api.html create mode 100644 docs/3.5.x/docs/connections.html create mode 100644 docs/3.5.x/docs/contributing.html create mode 100644 docs/3.5.x/docs/css/api.css create mode 100644 docs/3.5.x/docs/css/default.css create mode 100644 docs/3.5.x/docs/css/guide.css create mode 100644 docs/3.5.x/docs/css/style.css create mode 100644 docs/3.5.x/docs/documents.html create mode 100644 docs/3.5.x/docs/faq.html create mode 100644 docs/3.5.x/docs/guide.html create mode 100644 docs/3.5.x/docs/helpers/filters.js create mode 100644 docs/3.5.x/docs/helpers/highlight.js create mode 100644 docs/3.5.x/docs/helpers/href.js create mode 100644 docs/3.5.x/docs/helpers/klass.js create mode 100644 docs/3.5.x/docs/helpers/linktype.js create mode 100644 docs/3.5.x/docs/images/apps/attictv.png create mode 100644 docs/3.5.x/docs/images/apps/bozuko.png create mode 100644 docs/3.5.x/docs/images/apps/calllist.png create mode 100644 docs/3.5.x/docs/images/apps/cldfy.png create mode 100644 docs/3.5.x/docs/images/apps/clickdummy.png create mode 100644 docs/3.5.x/docs/images/apps/cyborgvision.png create mode 100644 docs/3.5.x/docs/images/apps/dashku.png create mode 100644 docs/3.5.x/docs/images/apps/firstimpression.png create mode 100644 docs/3.5.x/docs/images/apps/furbabyrescue.png create mode 100644 docs/3.5.x/docs/images/apps/geeklist.png create mode 100755 docs/3.5.x/docs/images/apps/grab create mode 100644 docs/3.5.x/docs/images/apps/growthegamegolf.png create mode 100644 docs/3.5.x/docs/images/apps/h_bozuko.jpg create mode 100644 docs/3.5.x/docs/images/apps/h_geeklist.png create mode 100644 docs/3.5.x/docs/images/apps/h_learnboost.png create mode 100644 docs/3.5.x/docs/images/apps/h_mcds.png create mode 100644 docs/3.5.x/docs/images/apps/h_shoejitsu.png create mode 100644 docs/3.5.x/docs/images/apps/h_storify.jpg create mode 100644 docs/3.5.x/docs/images/apps/knack.png create mode 100644 docs/3.5.x/docs/images/apps/kyyti.png create mode 100644 docs/3.5.x/docs/images/apps/learnboost.png create mode 100644 docs/3.5.x/docs/images/apps/linkr.png create mode 100644 docs/3.5.x/docs/images/apps/lists.png create mode 100644 docs/3.5.x/docs/images/apps/localresponse.png create mode 100644 docs/3.5.x/docs/images/apps/mcdonalds.png create mode 100644 docs/3.5.x/docs/images/apps/moveline.png create mode 100644 docs/3.5.x/docs/images/apps/muffle.png create mode 100644 docs/3.5.x/docs/images/apps/mybrickbuilds.png create mode 100644 docs/3.5.x/docs/images/apps/nextdays.png create mode 100644 docs/3.5.x/docs/images/apps/nimblequiz.png create mode 100644 docs/3.5.x/docs/images/apps/nuorder.png create mode 100644 docs/3.5.x/docs/images/apps/panemerkille.png create mode 100644 docs/3.5.x/docs/images/apps/pictorious.png create mode 100644 docs/3.5.x/docs/images/apps/scottyapp.png create mode 100644 docs/3.5.x/docs/images/apps/seelio.png create mode 100644 docs/3.5.x/docs/images/apps/selectvids.png create mode 100644 docs/3.5.x/docs/images/apps/sharelatex.png create mode 100644 docs/3.5.x/docs/images/apps/shoejitsu.png create mode 100644 docs/3.5.x/docs/images/apps/skim.png create mode 100644 docs/3.5.x/docs/images/apps/squadsheet.png create mode 100644 docs/3.5.x/docs/images/apps/stachify.png create mode 100644 docs/3.5.x/docs/images/apps/storify.png create mode 100644 docs/3.5.x/docs/images/apps/todaylaunch.png create mode 100644 docs/3.5.x/docs/images/apps/treinosmart.png create mode 100644 docs/3.5.x/docs/images/apps/upcload.png create mode 100644 docs/3.5.x/docs/images/apps/urls create mode 100644 docs/3.5.x/docs/images/apps/veriwalk.png create mode 100644 docs/3.5.x/docs/images/apps/wavo.png create mode 100644 docs/3.5.x/docs/images/apps/zootify.png create mode 100644 docs/3.5.x/docs/images/square_bg.png create mode 100644 docs/3.5.x/docs/includes/googleanalytics.jade create mode 100644 docs/3.5.x/docs/includes/nav.jade create mode 100644 docs/3.5.x/docs/index.html create mode 100644 docs/3.5.x/docs/js/cookies.min.js create mode 100644 docs/3.5.x/docs/js/zepto.min.js create mode 100644 docs/3.5.x/docs/middleware.html create mode 100644 docs/3.5.x/docs/migration.html create mode 100644 docs/3.5.x/docs/models.html create mode 100644 docs/3.5.x/docs/plugins.html create mode 100644 docs/3.5.x/docs/populate.html create mode 100644 docs/3.5.x/docs/prior.html create mode 100644 docs/3.5.x/docs/production.html create mode 100644 docs/3.5.x/docs/queries.html create mode 100644 docs/3.5.x/docs/schematypes.html create mode 100644 docs/3.5.x/docs/source/_docs create mode 100644 docs/3.5.x/docs/source/api.js create mode 100644 docs/3.5.x/docs/source/home.js create mode 100644 docs/3.5.x/docs/source/index.js create mode 100644 docs/3.5.x/docs/source/prior.js create mode 100644 docs/3.5.x/docs/source/production.js create mode 100644 docs/3.5.x/docs/subdocs.html create mode 100644 docs/3.5.x/docs/validation.html create mode 100644 docs/3.5.x/index.html create mode 100644 docs/3.5.x/static.js diff --git a/docs/3.0.x/docs/api.html b/docs/3.0.x/docs/api.html new file mode 100644 index 00000000000..1db5b1f7e65 --- /dev/null +++ b/docs/3.0.x/docs/api.html @@ -0,0 +1,6444 @@ +Mongoose API v3.0.3Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      +  this.connections = [];
      +  this.plugins = [];
      +  this.models = {};
      +  this.modelSchemas = {};
      +  this.options = {};
      +  this.createConnection(); // default connection
      +};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +  this.options[key] = value;
      +  return this;
      +};

      Parameters:

      Example:

      + +
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      + +
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      +  var conn = new Connection(this);
      +  this.connections.push(conn);
      +
      +  if (arguments.length) {
      +    if (rgxReplSet.test(arguments[0])) {
      +      conn.openSet.apply(conn, arguments);
      +    } else {
      +      conn.open.apply(conn, arguments);
      +    }
      +  }
      +
      +  return conn;
      +};

      Parameters:

      • [uri] <String> a mongodb:// URI

      Returns:

      Example:

      + +
      // with mongodb:// URI
      +db = mongoose.createConnection('mongodb://localhost:port/database');
      +
      +// replica sets
      +db = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
      +
      +// with [host, database_name[, port] signature
      +db = mongoose.createConnection('localhost', 'database', port)
      +
      +// initialize now, connect later
      +db = mongoose.createConnection();
      +db.open('localhost', 'database', port);

      Mongoose#connect()

      Opens the default mongoose connection.

      show code
      Mongoose.prototype.connect = function () {
      +  var conn = this.connection;
      +
      +  if (rgxReplSet.test(arguments[0])) {
      +    conn.openSet.apply(conn, arguments);
      +  } else {
      +    conn.open.apply(conn, arguments);
      +  }
      +
      +  return this;
      +};

      Returns:

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


      Mongoose#disconnect([fn])

      Disconnects all connections.

      show code
      Mongoose.prototype.disconnect = function (fn) {
      +  var count = this.connections.length
      +    , error
      +
      +  this.connections.forEach(function(conn){
      +    conn.close(function(err){
      +      if (error) return;
      +
      +      if (err) {
      +        error = err;
      +        if (fn) return fn(err);
      +        throw err;
      +      }
      +
      +      if (fn)
      +        --count || fn();
      +    });
      +  });
      +  return this;
      +};

      Parameters:

      • [fn] <Function> called after all connection close.

      Returns:


      Mongoose#model(name, [schema], [collection], [skipInit])

      Defines a model or retrieves it.

      show code
      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
      +  // normalize collection
      +  if (!(schema instanceof Schema)) {
      +    collection = schema;
      +    schema = false;
      +  }
      +
      +  if ('boolean' === typeof collection) {
      +    skipInit = collection;
      +    collection = null;
      +  }
      +
      +  // look up models for the collection
      +  if (!this.modelSchemas[name]) {
      +    if (!schema && name in SchemaDefaults) {
      +      schema = SchemaDefaults[name];
      +    }
      +
      +    if (schema) {
      +      this.modelSchemas[name] = schema;
      +      for (var i = 0, l = this.plugins.length; i < l; i++) {
      +        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
      +      }
      +    } else {
      +      throw new Error('Schema hasn\'t been registered for model "' + name + '".
      +'
      +                    + 'Use mongoose.model(name, schema)');
      +    }
      +  }
      +
      +  if (!this.models[name]) {
      +    schema || (schema = this.modelSchemas[name]);
      +    collection || (collection = schema.set('collection') || format(name));
      +
      +    var model = Model.compile(name
      +                        , this.modelSchemas[name]
      +                        , collection
      +                        , this.connection
      +                        , this);
      +
      +    if (!skipInit) model.init();
      +
      +    this.models[name] = model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> model name
      • [schema] <Schema>
      • [collection] <String> name (optional, induced from model name)
      • [skipInit] <Boolean> whether to skip initialization (defaults to false)

      Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +
      +// define an Actor model with this mongoose instance
      +mongoose.model('Actor', new Schema({ name: String }));
      +
      +// create a new connection
      +var conn = mongoose.createConnection(..);
      +
      +// retrieve the Actor model
      +var Actor = conn.model('Actor');
      + +

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

      + +

      Example:

      + +
      var schema = new Schema({ name: String });
      +schema.set('collection', 'actor');

      Mongoose#plugin(fn, [opts])

      Declares a global plugin executed on all Schemas.

      show code
      Mongoose.prototype.plugin = function (fn, opts) {
      +  this.plugins.push([fn, opts]);
      +  return this;
      +};

      Parameters:

      Returns:

      Equivalent to calling .plugin(fn) on each Schema you create.


      module.exports

      The exports object is an instance of Mongoose.

      show code
      module.exports = exports = new Mongoose;
      +var mongoose = module.exports;

      mongoose.Collection

      The Mongoose Collection constructor

      show code
      mongoose.Collection = Collection;

      mongoose.Connection

      The Mongoose Connection constructor

      show code
      mongoose.Connection = Connection;

      mongoose.version

      Mongoose version

      show code
      mongoose.version = JSON.parse(
      +  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      +).version;

      mongoose.Mongoose

      The Mongoose constructor

      show code
      mongoose.Mongoose = Mongoose;

      The exports of the mongoose module is an instance of this class.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var mongoose2 = new mongoose.Mongoose();

      mongoose.Schema

      The Mongoose Schema constructor

      show code
      mongoose.Schema = Schema;

      Example:

      + +
      var mongoose = require('mongoose');
      +var Schema = mongoose.Schema;
      +var CatSchema = new Schema(..);

      mongoose.SchemaType

      The Mongoose SchemaType constructor.

      show code
      mongoose.SchemaType = SchemaType;

      mongoose.SchemaTypes

      The various Mongoose SchemaTypes.

      show code
      mongoose.SchemaTypes = Schema.Types;

      Note:

      + +

      Alias of mongoose.Schema.Types for backwards compatibility.


      mongoose.VirtualType

      The Mongoose VirtualType constructor.

      show code
      mongoose.VirtualType = VirtualType;

      mongoose.Types

      The various Mongoose Types.

      show code
      mongoose.Types = Types;

      Example:

      + +
      var mongoose = require('mongoose');
      +var array = mongoose.Types.Array;
      + +

      Types:

      + +
        +
      • Array
      • +
      • Buffer
      • +
      • Document
      • +
      • Embedded
      • +
      • DocumentArray
      • +
      • ObjectId
      • +
      + +

      Using this exposed access to the ObjectId type, we can construct ids on demand.

      + +
      var ObjectId = mongoose.Types.ObjectId;
      +var id1 = new ObjectId;

      mongoose.Query

      The Mongoose Query constructor.

      show code
      mongoose.Query = Query;

      mongoose.Promise

      The Mongoose Promise constructor.

      show code
      mongoose.Promise = Promise;

      mongoose.Model

      The Mongoose Model constructor.

      show code
      mongoose.Model = Model;

      mongoose.Document

      The Mongoose Document constructor.

      show code
      mongoose.Document = Document;

      mongoose.Error

      The MongooseError constructor.

      show code
      mongoose.Error = require('./error');

      mongoose.mongo

      The node-mongodb-native driver Mongoose uses.

      show code
      mongoose.mongo = require('mongodb');

      Mongoose#connection

      The default connection of the mongoose module.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +mongoose.connect(...);
      +mongoose.connection.on('error', cb);
      + +

      This is the connection used by default for every model created using mongoose.model.

      Returns:


    • collection.js

      Collection(name, conn, opts)

      Abstract Collection constructor

      show code
      function Collection (name, conn, opts) {
      +  this.name = name;
      +  this.conn = conn;
      +  this.buffer = true;
      +  this.queue = [];
      +
      +  if ('number' == typeof opts) opts = { size: opts };
      +  this.opts = opts || {};
      +
      +  if (STATES.connected == this.conn.readyState) {
      +    this.onOpen();
      +  }
      +};

      Parameters:

      • name <String> name of the collection
      • conn <Connection> A MongooseConnection instance
      • opts <Object> optional collection options

      This is the base class that drivers inherit from and implement.


      Collection#onOpen()

      Called when the database connects

      show code
      Collection.prototype.onOpen = function () {
      +  var self = this;
      +  this.buffer = false;
      +  self.doQueue();
      +};

      Collection#onClose()

      Called when the database disconnects

      show code
      Collection.prototype.onClose = function () {
      +  this.buffer = true;
      +};

      Collection#addQueue(name, args)

      Queues a method for later execution when its
      database connection opens.

      show code
      Collection.prototype.addQueue = function (name, args) {
      +  this.queue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the method to queue
      • args <Array> arguments to pass to the method when executed

      Collection#doQueue()

      Executes all queued methods and clears the queue.

      show code
      Collection.prototype.doQueue = function () {
      +  for (var i = 0, l = this.queue.length; i < l; i++){
      +    this[this.queue[i][0]].apply(this, this.queue[i][1]);
      +  }
      +  this.queue = [];
      +  return this;
      +};

      Collection#ensureIndex()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.ensureIndex = function(){
      +  throw new Error('Collection#ensureIndex unimplemented by driver');
      +};

      Collection#findAndModify()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findAndModify = function(){
      +  throw new Error('Collection#findAndModify unimplemented by driver');
      +};

      Collection#findOne()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findOne = function(){
      +  throw new Error('Collection#findOne unimplemented by driver');
      +};

      Collection#find()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.find = function(){
      +  throw new Error('Collection#find unimplemented by driver');
      +};

      Collection#insert()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.insert = function(){
      +  throw new Error('Collection#insert unimplemented by driver');
      +};

      Collection#save()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.save = function(){
      +  throw new Error('Collection#save unimplemented by driver');
      +};

      Collection#update()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.update = function(){
      +  throw new Error('Collection#update unimplemented by driver');
      +};

      Collection#getIndexes()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.getIndexes = function(){
      +  throw new Error('Collection#getIndexes unimplemented by driver');
      +};

      Collection#mapReduce()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.mapReduce = function(){
      +  throw new Error('Collection#mapReduce unimplemented by driver');
      +};

      Collection#conn

      The Connection instance


      Collection#name

      The collection name


    • connection.js

      Connection(base)

      Connection constructor

      show code
      function Connection (base) {
      +  this.base = base;
      +  this.collections = {};
      +  this.models = {};
      +  this.replica = false;
      +  this.host = null;
      +  this.port = null;
      +  this.user = null;
      +  this.pass = null;
      +  this.name = null;
      +  this.options = null;
      +  this._readyState = STATES.disconnected;
      +  this._closeCalled = false;
      +  this._hasOpened = false;
      +};

      Parameters:

      Events:

      • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

      • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

      • open: Emitted after we connected and onOpen is executed on all of this connections models.

      • disconnecting: Emitted when connection.close() was executed.

      • disconnected: Emitted after getting disconnected from the db.

      • close: Emitted after we disconnected and onClose executed on all of this connections models.

      • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

      • error: Emitted when an error occurs on this connection.

      • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

      For practical reasons, a Connection equals a Db.


      Connection#open(connection_string, [database], [port], [options], [callback])

      Opens the connection to MongoDB.

      show code
      Connection.prototype.open = function (host, database, port, options, callback) {
      +  var self = this
      +    , uri;
      +
      +  if ('string' === typeof database) {
      +    switch (arguments.length) {
      +      case 2:
      +        port = 27017;
      +      case 3:
      +        switch (typeof port) {
      +          case 'function':
      +            callback = port, port = 27017;
      +            break;
      +          case 'object':
      +            options = port, port = 27017;
      +            break;
      +        }
      +        break;
      +      case 4:
      +        if ('function' === typeof options)
      +          callback = options, options = {};
      +    }
      +  } else {
      +    switch (typeof database) {
      +      case 'function':
      +        callback = database, database = undefined;
      +        break;
      +      case 'object':
      +        options = database;
      +        database = undefined;
      +        callback = port;
      +        break;
      +    }
      +
      +    if (!rgxProtocol.test(host)) {
      +      host = 'mongodb://' + host;
      +    }
      +
      +    uri = url.parse(host);
      +    host = uri.hostname;
      +    port = uri.port || 27017;
      +    database = uri.pathname && uri.pathname.replace(/\//g, '');
      +  }
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // make sure we can open
      +  if (STATES.disconnected !== this.readyState) {
      +    var err = new Error('Trying to open unclosed connection.');
      +    err.state = this.readyState;
      +    this.error(err, callback);
      +    return this;
      +  }
      +
      +  if (!host) {
      +    this.error(new Error('Missing connection hostname.'), callback);
      +    return this;
      +  }
      +
      +  if (!database) {
      +    this.error(new Error('Missing connection database.'), callback);
      +    return this;
      +  }
      +
      +  // handle authentication
      +  if (uri && uri.auth) {
      +    var auth = uri.auth.split(':');
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // Check hostname for user/pass
      +  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
      +    host = host.split('@');
      +    var auth = host.shift().split(':');
      +    host = host.pop();
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // user/pass options
      +  } else if (options && options.user && options.pass) {
      +    this.user = options.user;
      +    this.pass = options.pass;
      +
      +  } else {
      +    this.user = this.pass = undefined;
      +  }
      +
      +  this.name = database;
      +  this.host = host;
      +  this.port = port;
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • connection_string <String> mongodb://uri or the host to which you are connecting
      • [database] <String> database name
      • [port] <Number> database port
      • [options] <Object> options
      • [callback] <Function>

      options is a hash with the following possible properties:

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSetServer instance
      +user    - username for authentication
      +pass    - password for authentication
      + +

      Notes:

      + +

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.


      Connection#openSet(uris, [database], [options], [callback])

      Connects to a replica set.

      show code
      Connection.prototype.openSet = function (uris, database, options, callback) {
      +  var uris = uris.split(',')
      +    , self = this;
      +
      +  switch (arguments.length) {
      +    case 3:
      +      this.name = database;
      +      if ('function' === typeof options) callback = options, options = {};
      +      break;
      +    case 2:
      +      switch (typeof database) {
      +        case 'string':
      +          this.name = database;
      +        case 'function':
      +          callback = database, database = null;
      +          break;
      +        case 'object':
      +          options = database, database = null;
      +          break;
      +      }
      +  }
      +
      +  this.options = options = this.defaultOptions(options);
      +
      +  if (uris.length < 2) {
      +    this.error(new Error('Please provide comma-separated URIs'), callback);
      +    return this;
      +  }
      +
      +  this.replica = true;
      +  this.host = [];
      +  this.port = [];
      +
      +  uris.forEach(function (uri) {
      +    // handle missing protocols
      +    if (!rgxProtocol.test(uri))
      +      uri = 'mongodb://' + uri;
      +
      +    var uri = url.parse(uri);
      +
      +    self.host.push(uri.hostname);
      +    self.port.push(uri.port || 27017);
      +
      +    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
      +      self.name = uri.pathname.replace(/\//g, '');
      +
      +    if (!self.user && uri.auth) {
      +      var auth = uri.auth.split(':');
      +      self.user = auth[0];
      +      self.pass = auth[1];
      +    }
      +  });
      +
      +  if (!this.name) {
      +    this.error(new Error('No database name provided for replica set'), callback);
      +    return this;
      +  }
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • uris <String> comma-separated mongodb:// `URI`s
      • [database] <String> database name if not included in `uris`
      • [options] <Object> passed to the internal driver
      • [callback] <Function>

      Example:

      + +
      var db = mongoose.createConnection();
      +db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
      + +

      The database name and/or auth need only be included in one URI.
      The options are passed to the internal driver connection object.


      Connection#error(err, callback)

      error

      show code
      Connection.prototype.error = function (err, callback) {
      +  if (callback) return callback(err);
      +  this.emit('error', err);
      +}

      Parameters:

      Graceful error handling, passes error to callback
      if available, else emits error on the connection.


      Connection#_open(callback)

      Handles opening the connection with the appropriate method based on connection type.

      show code
      Connection.prototype._open = function (callback) {
      +  this.readyState = STATES.connecting;
      +  this._closeCalled = false;
      +
      +  var self = this;
      +
      +  var method = this.replica
      +    ? 'doOpenSet'
      +    : 'doOpen';
      +
      +  // open connection
      +  this[method](function (err) {
      +    if (err) {
      +      self.readyState = STATES.disconnected;
      +      if (self._hasOpened) {
      +        if (callback) callback(err);
      +      } else {
      +        self.error(err, callback);
      +      }
      +      return;
      +    }
      +
      +    self.onOpen();
      +    callback && callback();
      +  });
      +}

      Parameters:


      Connection#onOpen()

      Called when the connection is opened

      show code
      Connection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  function open () {
      +    self.readyState = STATES.connected;
      +
      +    // avoid having the collection subscribe to our event emitter
      +    // to prevent 0.3 warning
      +    for (var i in self.collections)
      +      self.collections[i].onOpen();
      +
      +    self.emit('open');
      +  };
      +
      +  // re-authenticate
      +  if (self.user && self.pass)
      +    self.db.authenticate(self.user, self.pass, open);
      +  else
      +    open();
      +};

      Connection#close([callback])

      Closes the connection

      show code
      Connection.prototype.close = function (callback) {
      +  var self = this;
      +  this._closeCalled = true;
      +
      +  switch (this.readyState){
      +    case 0: // disconnected
      +      callback && callback();
      +      break;
      +
      +    case 1: // connected
      +      this.readyState = STATES.disconnecting;
      +      this.doClose(function(err){
      +        if (err){
      +          self.error(err, callback);
      +        } else {
      +          self.onClose();
      +          callback && callback();
      +        }
      +      });
      +      break;
      +
      +    case 2: // connecting
      +      this.once('open', function(){
      +        self.close(callback);
      +      });
      +      break;
      +
      +    case 3: // disconnecting
      +      if (!callback) break;
      +      this.once('close', function () {
      +        callback();
      +      });
      +      break;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Connection#onClose()

      Called when the connection closes

      show code
      Connection.prototype.onClose = function () {
      +  this.readyState = STATES.disconnected;
      +
      +  // avoid having the collection subscribe to our event emitter
      +  // to prevent 0.3 warning
      +  for (var i in this.collections)
      +    this.collections[i].onClose();
      +
      +  this.emit('close');
      +};

      Connection#collection(name, [options])

      Retrieves a collection, creating it if not cached.

      show code
      Connection.prototype.collection = function (name, options) {
      +  if (!(name in this.collections))
      +    this.collections[name] = new Collection(name, this, options);
      +  return this.collections[name];
      +};

      Parameters:

      • name <String> of the collection
      • [options] <Object> optional collection options

      Returns:


      Connection#model(name, [schema], [collection])

      Defines or retrieves a model.

      show code
      Connection.prototype.model = function (name, schema, collection) {
      +  if (!this.models[name]) {
      +    var model = this.base.model(name, schema, collection, true)
      +      , Model
      +
      +    if (this != model.prototype.db) {
      +      // subclass model using this connection and collection name
      +      Model = function Model (doc, fields, skipId) {
      +        if (!(this instanceof Model))
      +          return new Model(doc, fields, skipId);
      +        model.call(this, doc, fields, skipId);
      +      };
      +
      +      Model.__proto__ = model;
      +      Model.prototype.__proto__ = model.prototype;
      +      Model.db = Model.prototype.db = this;
      +
      +      // collection name discovery
      +      if ('string' === typeof schema) {
      +        collection = schema;
      +      }
      +
      +      if (!collection) {
      +        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
      +      }
      +
      +      var s = 'string' != typeof schema
      +        ? schema
      +        : model.prototype.schema;
      +
      +      Model.prototype.collection = this.collection(collection, s && s.options.capped);
      +      Model.collection = Model.prototype.collection;
      +      Model.init();
      +    }
      +
      +    this.models[name] = Model || model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> the model name
      • [schema] <Schema> a schema. necessary when defining a model
      • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

      Returns:

      • <Model> The compiled model
      var mongoose = require('mongoose');
      +var db = mongoose.createConnection(..);
      +db.model('Venue', new Schema(..));
      +var Ticket = db.model('Ticket', new Schema(..));
      +var Venue = db.model('Venue');

      Connection#setProfiling(level, [ms], callback)

      Set profiling level.

      show code
      Connection.prototype.setProfiling = function (level, ms, callback) {
      +  if (STATES.connected !== this.readyState) {
      +    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
      +  }
      +
      +  if (!callback) callback = ms, ms = 100;
      +
      +  var cmd = {};
      +
      +  switch (level) {
      +    case 0:
      +    case 'off':
      +      cmd.profile = 0;
      +      break;
      +    case 1:
      +    case 'slow':
      +      cmd.profile = 1;
      +      if ('number' !== typeof ms) {
      +        ms = parseInt(ms, 10);
      +        if (isNaN(ms)) ms = 100;
      +      }
      +      cmd.slowms = ms;
      +      break;
      +    case 2:
      +    case 'all':
      +      cmd.profile = 2;
      +      break;
      +    default:
      +      return callback(new Error('Invalid profiling level: '+ level));
      +  }
      +
      +  this.db.executeDbCommand(cmd, function (err, resp) {
      +    if (err) return callback(err);
      +
      +    var doc = resp.documents[0];
      +
      +    err = 1 === doc.ok
      +      ? null
      +      : new Error('Could not set profiling level to: '+ level)
      +
      +    callback(err, doc);
      +  });
      +};

      Parameters:

      • level <Number, String> either off (0), slow (1), or all (2)
      • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
      • callback <Function>

      Connection#defaultOptions(options)

      Prepares default connection options.

      show code
      Connection.prototype.defaultOptions = function (options) {
      +  var o = options || {};
      +
      +  o.server = o.server || {};
      +
      +  if (!('auto_reconnect' in o.server)) {
      +    o.server.auto_reconnect = true;
      +  }
      +
      +  o.db = o.db || {};
      +  o.db.forceServerObjectId = false;
      +
      +  return o;
      +}

      Parameters:


      Connection#db

      The mongodb.Db instance, set when the connection is opened


      Connection#collections

      A hash of the collections associated with this connection


      Connection#readyState

      Connection ready state

      + +
        +
      • 0 = disconnected
      • +
      • 1 = connected
      • +
      • 2 = connecting
      • +
      • 3 = disconnecting
      • +
      + +

      Each state change emits its associated event name.

      + +

      Example

      + +
      conn.on('connected', callback);
      +conn.on('disconnected', callback);

    • document.js

      Document(obj, [fields], [skipId])

      Document constructor.

      show code
      function Document (obj, fields, skipId) {
      +  // node <0.4.3 bug
      +  if (!this._events) this._events = {};
      +  this.setMaxListeners(0);
      +
      +  if ('boolean' === typeof fields) {
      +    this._strictMode = fields;
      +    this._selected = fields = undefined;
      +  } else {
      +    this._strictMode = this.schema.options && this.schema.options.strict;
      +    this._selected = fields;
      +  }
      +
      +  this.isNew = true;
      +  this.errors = undefined;
      +  this._shardval = undefined;
      +  this._saveError = undefined;
      +  this._validationError = undefined;
      +  this._adhocPaths = undefined;
      +  this._removing = undefined;
      +  this._inserting = undefined;
      +  this.__version = undefined;
      +  this.__getters = {};
      +  this.__id = undefined;
      +
      +  this._activePaths = new ActiveRoster;
      +
      +  var required = this.schema.requiredPaths();
      +  for (var i = 0; i < required.length; ++i) {
      +    this._activePaths.require(required[i]);
      +  }
      +
      +  this._doc = this._buildDoc(obj, fields, skipId);
      +  if (obj) this.set(obj, undefined, true);
      +  this._registerHooks();
      +};

      Parameters:

      • obj <Object> the values to set
      • [fields] <Object> the fields which were selected in the query returning this document
      • [skipId] <Boolean> bool, should we auto create an ObjectId _id

      Events:

      • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

      • save: Emitted when the document is successfully saved


      Document#_buildDoc(obj, [fields], [skipId])

      Builds the default doc structure

      show code
      Document.prototype._buildDoc = function (obj, fields, skipId) {
      +  var doc = {}
      +    , self = this
      +    , exclude
      +    , keys
      +    , key
      +    , ki
      +
      +  // determine if this doc is a result of a query with
      +  // excluded fields
      +  if (fields && 'Object' === fields.constructor.name) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('_id' !== keys[ki]) {
      +        exclude = 0 === fields[keys[ki]];
      +        break;
      +      }
      +    }
      +  }
      +
      +  var paths = Object.keys(this.schema.paths)
      +    , plen = paths.length
      +    , ii = 0
      +
      +  for (; ii < plen; ++ii) {
      +    var p = paths[ii];
      +
      +    if ('_id' == p) {
      +      if (skipId) continue;
      +      if (obj && '_id' in obj) continue;
      +    }
      +
      +    var type = this.schema.paths[p]
      +      , path = p.split('.')
      +      , len = path.length
      +      , last = len-1
      +      , doc_ = doc
      +      , i = 0
      +
      +    for (; i < len; ++i) {
      +      var piece = path[i]
      +        , def
      +
      +      if (i === last) {
      +        if (fields) {
      +          if (exclude) {
      +            // apply defaults to all non-excluded fields
      +            if (p in fields) continue;
      +
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +
      +          } else if (p in fields) {
      +            // selected field
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +          }
      +        } else {
      +          def = type.getDefault(self, true);
      +          if ('undefined' !== typeof def) {
      +            doc_[piece] = def;
      +            self._activePaths.default(p);
      +          }
      +        }
      +      } else {
      +        doc_ = doc_[piece] || (doc_[piece] = {});
      +      }
      +    }
      +  };
      +
      +  return doc;
      +};

      Parameters:

      Returns:


      Document#init(doc, fn)

      Initializes the document without setters or marking anything modified.

      show code
      Document.prototype.init = function (doc, fn) {
      +  this.isNew = false;
      +
      +  init(this, doc, this._doc);
      +  this._storeShard();
      +
      +  this.emit('init');
      +  if (fn) fn(null);
      +  return this;
      +};

      Parameters:

      Called internally after a document is returned from mongodb.


      Document#_storeShard()

      Stores the current values of the shard keys.

      show code
      Document.prototype._storeShard = function _storeShard () {
      +  // backwards compat
      +  var key = this.schema.options.shardKey || this.schema.options.shardkey;
      +  if (!(key && 'Object' == key.constructor.name)) return;
      +
      +  var orig = this._shardval = {}
      +    , paths = Object.keys(key)
      +    , len = paths.length
      +    , val
      +
      +  for (var i = 0; i < len; ++i) {
      +    val = this.getValue(paths[i]);
      +    if (isMongooseObject(val)) {
      +      orig[paths[i]] = val.toObject({ depopulate: true })
      +    } else if (null != val && val.valueOf) {
      +      orig[paths[i]] = val.valueOf();
      +    } else {
      +      orig[paths[i]] = val;
      +    }
      +  }
      +}

      Note:

      + +

      Shard key values do not / are not allowed to change.


      Document#update(doc, options, callback)

      Sends an update command with this document _id as the query selector.

      show code
      Document.prototype.update = function update () {
      +  var args = utils.args(arguments);
      +  args.unshift({_id: this._id});
      +  this.constructor.update.apply(this.constructor, args);
      +}

      Parameters:

      Returns:

      Example:

      + +
      weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
      + +

      Valid options:

      + +
        +
      • safe safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +

      Document#set(path, val, [type])

      Sets the value of a path, or many paths.

      show code
      Document.prototype.set = function (path, val, type) {
      +  var constructing = true === type
      +    , adhoc = type && true !== type
      +    , adhocs
      +
      +  if (adhoc) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  if ('string' !== typeof path) {
      +    // new Document({ key: val })
      +
      +    if (null === path || undefined === path) {
      +      var _ = path;
      +      path = val;
      +      val = _;
      +
      +    } else {
      +      var prefix = val
      +        ? val + '.'
      +        : '';
      +
      +      if (path instanceof Document) path = path._doc;
      +
      +      var keys = Object.keys(path)
      +        , i = keys.length
      +        , pathtype
      +        , key
      +
      +      while (i--) {
      +        key = keys[i];
      +        if (null != path[key] && 'Object' === path[key].constructor.name
      +          && !(this._path(prefix + key) instanceof MixedSchema)) {
      +          this.set(path[key], prefix + key, constructing);
      +        } else if (this._strictMode) {
      +          pathtype = this.schema.pathType(prefix + key);
      +          if ('real' === pathtype || 'virtual' === pathtype) {
      +            this.set(prefix + key, path[key], constructing);
      +          } else if ('throw' == this._strictMode) {
      +            throw new Error("Field `" + key + "` is not in schema.");
      +          }
      +        } else if (undefined !== path[key]) {
      +          this.set(prefix + key, path[key], constructing);
      +        }
      +      }
      +
      +      return this;
      +    }
      +  }
      +
      +  // ensure _strict is honored for obj props
      +  // docschema = new Schema({ path: { nest: 'string' }})
      +  // doc.set('path', obj);
      +  var pathType = this.schema.pathType(path);
      +  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
      +    this.set(val, path, constructing);
      +    return this;
      +  }
      +
      +  var schema;
      +  if ('adhocOrUndefined' == pathType && this._strictMode) {
      +    return this;
      +  } else if ('virtual' == pathType) {
      +    schema = this.schema.virtualpath(path);
      +    schema.applySetters(val, this);
      +    return this;
      +  } else {
      +    schema = this._path(path);
      +  }
      +
      +  var parts = path.split('.')
      +    , pathToMark
      +
      +  // When using the $set operator the path to the field must already exist.
      +  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
      +
      +  if (parts.length <= 1) {
      +    pathToMark = path;
      +  } else {
      +    for (var i = 0; i < parts.length; ++i) {
      +      var part = parts[i];
      +      var subpath = parts.slice(0, i).concat(part).join('.');
      +      if (this.isDirectModified(subpath) // earlier prefixes that are already
      +                                         // marked as dirty have precedence
      +          || this.get(subpath) === null) {
      +        pathToMark = subpath;
      +        break;
      +      }
      +    }
      +
      +    if (!pathToMark) pathToMark = path;
      +  }
      +
      +  if (!schema || null === val || undefined === val) {
      +    this._set(pathToMark, path, constructing, parts, schema, val);
      +    return this;
      +  }
      +
      +  var self = this;
      +
      +  // if this doc is being constructed we should not
      +  // trigger getters.
      +  var priorVal = constructing
      +    ? undefined
      +    : this.get(path);
      +
      +  var shouldSet = this.try(function(){
      +    val = schema.applySetters(val, self, false, priorVal);
      +  });
      +
      +  if (shouldSet) {
      +    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
      +  }
      +
      +  return this;
      +}

      Parameters:

      Example:

      + +
      // path, value
      +doc.set(path, value)
      +
      +// object
      +doc.set({
      +    path  : value
      +  , path2 : {
      +       path  : value
      +    }
      +})
      +
      +// only-the-fly cast to number
      +doc.set(path, value, Number)
      +
      +// only-the-fly cast to string
      +doc.set(path, value, String)

      Document#_set()

      Handles the actual setting of the value and marking the path modified if appropriate.

      show code
      Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {
      +  if (this.isNew) {
      +    this.markModified(pathToMark);
      +  } else {
      +
      +    priorVal || (priorVal = this.get(path));
      +
      +    if (!this.isDirectModified(pathToMark)) {
      +      if (undefined === val && !this.isSelected(path)) {
      +        // special case:
      +        // when a path is not selected in a query its initial
      +        // value will be undefined.
      +        this.markModified(pathToMark, priorVal);
      +      } else if (undefined === val && path in this._activePaths.states.default) {
      +        // do nothing
      +        // unsetting the default value which was never saved
      +      } else if (!deepEqual(val, priorVal)) {
      +        this.markModified(pathToMark, priorVal);
      +      } else if (!constructing &&
      +                 null != val &&
      +                 path in this._activePaths.states.default &&
      +                 deepEqual(val, schema.getDefault(this, constructing))) {
      +        // special case:
      +        // a path with a default was $unset on the server
      +        // and the user is setting it to the same value again
      +        this.markModified(pathToMark, priorVal);
      +      }
      +    }
      +  }
      +
      +  var obj = this._doc
      +    , i = 0
      +    , l = parts.length
      +
      +  for (; i < l; i++) {
      +    var next = i + 1
      +      , last = next === l;
      +
      +    if (last) {
      +      obj[parts[i]] = val;
      +    } else {
      +      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
      +        obj = obj[parts[i]];
      +      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
      +        obj = obj[parts[i]];
      +      } else {
      +        obj = obj[parts[i]] = {};
      +      }
      +    }
      +  }
      +};

      Document#getValue(path)

      Gets a raw value from a path (no getters)

      show code
      Document.prototype.getValue = function (path) {
      +  var parts = path.split('.')
      +    , obj = this._doc
      +    , part;
      +
      +  for (var i = 0, l = parts.length; i < l; i++) {
      +    part = parts[i];
      +    obj = obj.getValue
      +        ? obj.getValue(part) // If we have an embedded array document member
      +        : obj[part];
      +    if (!obj) return obj;
      +  }
      +
      +  return obj;
      +}

      Parameters:


      Document#setValue(path, value)

      Sets a raw value for a path (no casting, setters, transformations)

      show code
      Document.prototype.setValue = function (path, val) {
      +  var parts = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, len = parts.length-1; i < len; i++) {
      +    obj = obj[parts[i]];
      +  }
      +
      +  obj[parts[len]] = val;
      +  return this;
      +};

      Parameters:


      Document#get(path, [type])

      Returns the value of a path.

      show code
      Document.prototype.get = function (path, type) {
      +  var adhocs;
      +  if (type) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  var schema = this._path(path) || this.schema.virtualpath(path)
      +    , pieces = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, l = pieces.length; i < l; i++) {
      +    obj = null == obj ? null : obj[pieces[i]];
      +  }
      +
      +  if (schema) {
      +    obj = schema.applyGetters(obj, this);
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Example

      + +
      // path
      +doc.get('age') // 47
      +
      +// dynamic casting to a string
      +doc.get('age', String) // "47"

      Document#_path(path)

      Returns the schematype for the given path.

      show code
      Document.prototype._path = function (path) {
      +  var adhocs = this._adhocPaths
      +    , adhocType = adhocs && adhocs[path];
      +
      +  if (adhocType) {
      +    return adhocType;
      +  } else {
      +    return this.schema.path(path);
      +  }
      +};

      Parameters:


      Document#markModified(path)

      Marks the path as having pending changes to write to the db.

      show code
      Document.prototype.markModified = function (path) {
      +  this._activePaths.modify(path);
      +};

      Parameters:

      • path <String> the path to mark modified

      Very helpful when using Mixed types.

      + +

      Example:

      + +
      doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');
      +doc.save() // changes to mixed.type are now persisted

      Document#try(fn, scope)

      Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

      show code
      Document.prototype.try = function (fn, scope) {
      +  var res;
      +  try {
      +    fn.call(scope);
      +    res = true;
      +  } catch (e) {
      +    this._error(e);
      +    res = false;
      +  }
      +  return res;
      +};

      Parameters:

      • fn <Function> function to execute
      • scope <Object> the scope with which to call fn

      Document#modifiedPaths()

      Returns the list of paths that have been modified.

      show code
      Document.prototype.modifiedPaths = function () {
      +  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
      +
      +  return directModifiedPaths.reduce(function (list, path) {
      +    var parts = path.split('.');
      +    return list.concat(parts.reduce(function (chains, part, i) {
      +      return chains.concat(parts.slice(0, i).concat(part).join('.'));
      +    }, []));
      +  }, []);
      +};

      Returns:


      Document#isModified([path])

      Returns true if this document was modified, else false.

      show code
      Document.prototype.isModified = function (path) {
      +  return path
      +    ? !!~this.modifiedPaths().indexOf(path)
      +    : this._activePaths.some('modify');
      +};

      Parameters:

      Returns:

      If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

      + +

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isModified()                    // true
      +doc.isModified('documents')         // true
      +doc.isModified('documents.0.title') // true
      +doc.isDirectModified('documents')   // false

      Document#isDirectModified(path)

      Returns true if path was directly set and modified, else false.

      show code
      Document.prototype.isDirectModified = function (path) {
      +  return (path in this._activePaths.states.modify);
      +};

      Parameters:

      Returns:

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isDirectModified('documents.0.title') // true
      +doc.isDirectModified('documents') // false

      Document#isInit(path)

      Checks if path was initialized.

      show code
      Document.prototype.isInit = function (path) {
      +  return (path in this._activePaths.states.init);
      +};

      Parameters:

      Returns:


      Document#isSelected(path)

      Checks if path was selected in the source query which initialized this document.

      show code
      Document.prototype.isSelected = function isSelected (path) {
      +  if (this._selected) {
      +
      +    if ('_id' === path) {
      +      return 0 !== this._selected._id;
      +    }
      +
      +    var paths = Object.keys(this._selected)
      +      , i = paths.length
      +      , inclusive = false
      +      , cur
      +
      +    if (1 === i && '_id' === paths[0]) {
      +      // only _id was selected.
      +      return 0 === this._selected._id;
      +    }
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +      inclusive = !! this._selected[cur];
      +      break;
      +    }
      +
      +    if (path in this._selected) {
      +      return inclusive;
      +    }
      +
      +    i = paths.length;
      +    var pathDot = path + '.';
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +
      +      if (0 === cur.indexOf(pathDot)) {
      +        return inclusive;
      +      }
      +
      +      if (0 === pathDot.indexOf(cur)) {
      +        return inclusive;
      +      }
      +    }
      +
      +    return ! inclusive;
      +  }
      +
      +  return true;
      +}

      Parameters:

      Returns:

      Example

      + +
      Thing.findOne().select('name').exec(function (err, doc) {
      +   doc.isSelected('name') // true
      +   doc.isSelected('age')  // false
      +})

      Document#validate(cb)

      Executes registered validation rules for this document.

      show code
      Document.prototype.validate = function (cb) {
      +  var self = this
      +
      +  // only validate required fields when necessary
      +  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
      +    if (!self.isSelected(path) && !self.isModified(path)) return false;
      +    return true;
      +  });
      +
      +  paths = paths.concat(Object.keys(this._activePaths.states.init));
      +  paths = paths.concat(Object.keys(this._activePaths.states.modify));
      +
      +  if (0 === paths.length) {
      +    complete();
      +    return this;
      +  }
      +
      +  var validating = {}
      +    , total = 0;
      +
      +  paths.forEach(validatePath);
      +  return this;
      +
      +  function validatePath (path) {
      +    if (validating[path]) return;
      +
      +    validating[path] = true;
      +    total++;
      +
      +    process.nextTick(function(){
      +      var p = self.schema.path(path);
      +      if (!p) return --total || complete();
      +
      +      p.doValidate(self.getValue(path), function (err) {
      +        if (err) self.invalidate(path, err, true);
      +        --total || complete();
      +      }, self);
      +    });
      +  }
      +
      +  function complete () {
      +    var err = self._validationError;
      +    self._validationError = undefined;
      +    cb(err);
      +  }
      +};

      Parameters:

      • cb <Function> called after validation completes, passing an error if one occurred

      Note:

      + +

      This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

      + +

      Example:

      + +
      doc.validate(function (err) {
      +  if (err) handleError(err);
      +  else // validation passed
      +});

      Document#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      Document.prototype.invalidate = function (path, err) {
      +  if (!this._validationError) {
      +    this._validationError = new ValidationError(this);
      +  }
      +
      +  if (!err || 'string' === typeof err) {
      +    err = new ValidatorError(path, err);
      +  }
      +
      +  this._validationError.errors[path] = err;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> the error which states the reason `path` was invalid

      Document#_reset()

      Resets the internal modified state of this document.

      show code
      Document.prototype._reset = function reset () {
      +  var self = this;
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this._activePaths
      +  .map('init', 'modify', function (i) {
      +    return self.getValue(i);
      +  })
      +  .filter(function (val) {
      +    return (val && val instanceof DocumentArray && val.length);
      +  })
      +  .forEach(function (array) {
      +    array.forEach(function (doc) {
      +      doc._reset();
      +    });
      +  });
      +
      +  // clear atomics
      +  this._dirty().forEach(function (dirt) {
      +    var type = dirt.value;
      +    if (type && type._atomics) {
      +      type._atomics = {};
      +    }
      +  });
      +
      +  // Clear 'modify'('dirty') cache
      +  this._activePaths.clear('modify');
      +  this._validationError = undefined;
      +  this.errors = undefined;
      +  var self = this;
      +  this.schema.requiredPaths().forEach(function (path) {
      +    self._activePaths.require(path);
      +  });
      +
      +  return this;
      +}

      Returns:


      Document#_dirty()

      Returns this documents dirty paths / vals.

      show code
      Document.prototype._dirty = function _dirty () {
      +  var self = this;
      +
      +  var all = this._activePaths.map('modify', function (path) {
      +    return { path: path
      +           , value: self.getValue(path)
      +           , schema: self._path(path) };
      +  });
      +
      +  // Sort dirty paths in a flat hierarchy.
      +  all.sort(function (a, b) {
      +    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
      +  });
      +
      +  // Ignore "foo.a" if "foo" is dirty already.
      +  var minimal = []
      +    , lastPath
      +    , top;
      +
      +  all.forEach(function (item, i) {
      +    if (item.path.indexOf(lastPath) !== 0) {
      +      lastPath = item.path + '.';
      +      minimal.push(item);
      +      top = item;
      +    } else {
      +      if (!(item.value && top.value)) return;
      +
      +      // special case for top level MongooseArrays
      +      if (top.value._atomics && top.value.hasAtomics()) {
      +        // the `top` array itself and a sub path of `top` are being modified.
      +        // the only way to honor all of both modifications is through a $set
      +        // of entire array.
      +        top.value._atomics = {};
      +        top.value._atomics.$set = top.value;
      +      }
      +    }
      +  });
      +
      +  top = lastPath = null;
      +  return minimal;
      +}

      Document#_setSchema(schema)

      Assigns/compiles schema into this documents prototype.

      show code
      Document.prototype._setSchema = function (schema) {
      +  compile(schema.tree, this);
      +  this.schema = schema;
      +}

      Parameters:


      Document#_registerHooks()

      Register default hooks

      show code
      Document.prototype._registerHooks = function _registerHooks () {
      +  if (!this.save) return;
      +
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this.pre('save', function (next) {
      +    // we keep the error semaphore to make sure we don't
      +    // call `save` unnecessarily (we only need 1 error)
      +    var subdocs = 0
      +      , error = false
      +      , self = this;
      +
      +    // check for DocumentArrays
      +    var arrays = this._activePaths
      +    .map('init', 'modify', function (i) {
      +      return self.getValue(i);
      +    })
      +    .filter(function (val) {
      +      return (val && val instanceof DocumentArray && val.length);
      +    });
      +
      +    if (!arrays.length)
      +      return next();
      +
      +    arrays.forEach(function (array) {
      +      subdocs += array.length;
      +      array.forEach(function (value) {
      +        if (error) return;
      +
      +        value.save(function (err) {
      +          if (error) return;
      +
      +          if (err) {
      +            error = true;
      +            self._validationError = undefined;
      +            return next(err);
      +          }
      +
      +          --subdocs || next();
      +        });
      +      });
      +    });
      +  }, function (err) {
      +    // emit on the Model if listening
      +    if (this.constructor.listeners('error').length) {
      +      this.constructor.emit('error', err);
      +    } else {
      +      // emit on the connection
      +      if (!this.db.listeners('error').length) {
      +        err.stack = 'No listeners detected, throwing. '
      +                  + 'Consider adding an error listener to your connection.
      +'
      +                  + err.stack
      +      }
      +      this.db.emit('error', err);
      +    }
      +  }).pre('save', function checkForExistingErrors (next) {
      +    // if any doc.set() calls failed
      +    if (this._saveError) {
      +      next(this._saveError);
      +      this._saveError = null;
      +    } else {
      +      next();
      +    }
      +  }).pre('save', function validation (next) {
      +    return this.validate(next);
      +  });
      +
      +  // add user defined queues
      +  this._doQueue();
      +};

      Document#_error(err)

      Registers an error

      show code
      Document.prototype._error = function (err) {
      +  this._saveError = err;
      +  return this;
      +};

      Parameters:


      Document#_doQueue()

      Executes methods queued from the Schema definition

      show code
      Document.prototype._doQueue = function () {
      +  var q = this.schema && this.schema.callQueue;
      +  if (q) {
      +    for (var i = 0, l = q.length; i < l; i++) {
      +      this[q[i][0]].apply(this, q[i][1]);
      +    }
      +  }
      +  return this;
      +};

      Document#toObject([options])

      Converts this document into a plain javascript object

      show code
      Document.prototype.toObject = function (options) {
      +  // When internally saving this document we always pass options,
      +  // bypassing the custom schema options.
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toObject
      +      ? clone(this.schema.options.toObject)
      +      : {};
      +  }
      +
      +  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
      +
      +  var ret = clone(this._doc, options);
      +
      +  if (options.virtuals || options.getters && false !== options.virtuals) {
      +    applyGetters(this, ret, 'virtuals', options);
      +  }
      +
      +  if (options.getters) {
      +    applyGetters(this, ret, 'paths', options);
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Options:

      + +
        +
      • getters apply all getters (path and virtual getters)
      • +
      • virtuals apply virtual getters (can override getters option)
      • +
      • minimize remove empty objects (defaults to true)
      • +
      + +

      Example of only applying path getters

      + +
      doc.toObject({ getters: true, virtuals: false })
      + +

      Example of only applying virtual getters

      + +
      doc.toObject({ virtuals: true })
      + +

      Example of applying both path and virtual getters

      + +
      doc.toObject({ getters: true })

      Document#toJSON(options)

      The return value of this method is used in calls to JSON.stringify(doc).

      show code
      Document.prototype.toJSON = function (options) {
      +  // check for object type since an array of documents
      +  // being stringified passes array indexes instead
      +  // of options objects. JSON.stringify([doc, doc])
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toJSON
      +      ? clone(this.schema.options.toJSON)
      +      : {};
      +  }
      +  options.json = true;
      +  return this.toObject(options);
      +};

      Parameters:

      • options <Object> same options as Document#toObject

      Returns:


      Document#inspect()

      Helper for console.log

      show code
      Document.prototype.inspect = function (options) {
      +  var opts = options && 'Object' == options.constructor.name
      +    ? options
      +    : undefined
      +  return inspect(this.toObject(opts));
      +};

      Document#toString()

      Helper for console.log


      Document#equals(doc)

      Returns true if the Document stores the same data as doc.

      show code
      Document.prototype.equals = function (doc) {
      +  var tid = this.get('_id');
      +  var docid = doc.get('_id');
      +  return tid.equals
      +    ? tid.equals(docid)
      +    : tid === docid;
      +};

      Parameters:

      Returns:

      Documents are considered equal when they have matching _ids.


      Document#errors

      Hash containing current validation errors.


      Document#id

      The string version of this documents _id.

      + +

      Note:

      + +

      This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

      + +
      new Schema({ name: String }, { id: false });

      Document#isNew

      Boolean flag specifying if the document is new.


      Document#schema

      The documents schema.


    • drivers/node-mongodb-native/collection.js

      NativeCollection()

      A node-mongodb-native collection implementation.

      show code
      function NativeCollection () {
      +  this.collection = null;
      +  MongooseCollection.apply(this, arguments);
      +}

      Inherits:

      All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


      NativeCollection#onOpen()

      Called when the connection opens.

      show code
      NativeCollection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  if (this.collection) {
      +    return MongooseCollection.prototype.onOpen.call(self);
      +  }
      +
      +  if (!self.opts.size) {
      +    // non-capped
      +    return self.conn.db.collection(self.name, callback);
      +  }
      +
      +  // capped
      +  return self.conn.db.collection(self.name, function (err, c) {
      +    if (err) return callback(err);
      +
      +    // discover if this collection exists and if it is capped
      +    c.options(function (err, exists) {
      +      if (err) return callback(err);
      +
      +      if (exists) {
      +        if (exists.capped) {
      +          callback(null, c);
      +        } else {
      +          var msg = 'A non-capped collection exists with this name.
      +
      +'
      +                  + ' To use this collection as a capped collection, please '
      +                  + 'first convert it.
      +'
      +                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
      +          err = new Error(msg);
      +          callback(err);
      +        }
      +      } else {
      +        // create
      +        var opts = utils.clone(self.opts);
      +        opts.capped = true;
      +        self.conn.db.createCollection(self.name, opts, callback);
      +      }
      +    });
      +  });
      +
      +  function callback (err, collection) {
      +    if (err) {
      +      // likely a strict mode error
      +      self.conn.emit('error', err);
      +    } else {
      +      self.collection = collection;
      +      MongooseCollection.prototype.onOpen.call(self);
      +    }
      +  };
      +};

      NativeCollection#onClose()

      Called when the connection closes

      show code
      NativeCollection.prototype.onClose = function () {
      +  MongooseCollection.prototype.onClose.call(this);
      +};

      NativeCollection#getIndexes(callback)

      Retreives information about this collections indexes.

      Parameters:


    • drivers/node-mongodb-native/connection.js

      NativeConnection()

      A node-mongodb-native connection implementation.

      show code
      function NativeConnection() {
      +  MongooseConnection.apply(this, arguments);
      +};

      Inherits:


      NativeConnection#doOpen(fn)

      Opens the connection to MongoDB.

      show code
      NativeConnection.prototype.doOpen = function (fn) {
      +  var server
      +    , self = this;
      +
      +  if (!this.db) {
      +    server = new mongo.Server(this.host, Number(this.port), this.options.server);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};
      +
      +function listen (conn) {
      +  if (conn._listening) return;
      +  conn._listening = true;
      +
      +  conn.db.on('close', function(){
      +    if (conn._closeCalled) return;
      +
      +    // the driver never emits an `open` event. auto_reconnect still
      +    // emits a `close` event but since we never get another
      +    // `open` we can't emit close
      +    if (conn.db.serverConfig.autoReconnect) {
      +      conn.readyState = STATES.disconnected;
      +      conn.emit('close');
      +      return;
      +    }
      +    conn.onClose();
      +  });
      +  conn.db.on('error', function(err){
      +    conn.emit('error', err);
      +  });
      +  conn.db.on('timeout', function(err){
      +    var error = new Error(err && err.err || 'connection timeout');
      +    conn.emit('error', error);
      +  });
      +  conn.db.on('open', function (err, db) {
      +    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
      +      conn.readyState = STATES.connected;
      +      conn.emit('reconnected')
      +    }
      +  })
      +}

      Parameters:

      Returns:


      NativeConnection#doOpenSet(fn)

      Opens a connection to a MongoDB ReplicaSet.

      show code
      NativeConnection.prototype.doOpenSet = function (fn) {
      +  if (!this.db) {
      +    var servers = []
      +      , ports = this.port
      +      , self = this
      +
      +    this.host.forEach(function (host, i) {
      +      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
      +    });
      +
      +    var server = new ReplSetServers(servers, this.options.replset);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +
      +    this.db.on('fullsetup', function () {
      +      self.emit('fullsetup')
      +    });
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:

      See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


      NativeConnection#doClose(fn)

      Closes the connection

      show code
      NativeConnection.prototype.doClose = function (fn) {
      +  this.db.close();
      +  if (fn) fn();
      +  return this;
      +}

      Parameters:

      Returns:


    • error.js

      MongooseError()

      Mongoose error

      show code
      function MongooseError (msg) {
      +  Error.call(this);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.message = msg;
      +  this.name = 'MongooseError';
      +};

      Inherits:


    • errors/cast.js

      CastError(type, value)

      Casting Error constructor.

      show code
      function CastError (type, value) {
      +  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'CastError';
      +  this.type = type;
      +  this.value = value;
      +};

      Parameters:

      Inherits:


    • errors/document.js

      DocumentError(msg)

      Document Error

      show code
      function DocumentError (msg) {
      +  MongooseError.call(this, msg);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'DocumentError';
      +};

      Parameters:

      Inherits:


    • errors/validation.js

      ValidationError(instance)

      Document Validation Error

      show code
      function ValidationError (instance) {
      +  MongooseError.call(this, "Validation failed");
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidationError';
      +  this.errors = instance.errors = {};
      +};

      Parameters:

      Inherits:


      ValidationError#toString()

      Console.log helper

      show code
      ValidationError.prototype.toString = function () {
      +  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
      +    return String(this.errors[key]);
      +  }, this).join(', ');
      +};

    • errors/validator.js

      ValidatorError(path, msg)

      Schema validator error

      show code
      function ValidatorError (path, type) {
      +  var msg = type
      +    ? '"' + type + '" '
      +    : '';
      +  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidatorError';
      +  this.path = path;
      +  this.type = type;
      +};

      Parameters:

      Inherits:


    • model.js

      Model(doc)

      Model constructor

      show code
      function Model (doc, fields, skipId) {
      +  Document.call(this, doc, fields, skipId);
      +};

      Parameters:

      • doc <Object> values to with which to create the document

      Inherits:

      Events:

      • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

      • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


      Model#_getPopulationKeys(query)

      Returns what paths can be populated

      show code
      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
      +  if (!(query && query.options.populate)) return;
      +
      +  var names = Object.keys(query.options.populate)
      +    , n = names.length
      +    , name
      +    , paths = {}
      +    , hasKeys
      +    , schema
      +
      +  while (n--) {
      +    name = names[n];
      +    schema = this.schema.path(name);
      +    hasKeys = true;
      +
      +    if (!schema) {
      +      // if the path is not recognized, it's potentially embedded docs
      +      // walk path atoms from right to left to find a matching path
      +      var pieces = name.split('.')
      +        , i = pieces.length;
      +
      +      while (i--) {
      +        var path = pieces.slice(0, i).join('.')
      +          , pathSchema = this.schema.path(path);
      +
      +        // loop until we find an array schema
      +        if (pathSchema && pathSchema.caster) {
      +          if (!paths[path]) {
      +            paths[path] = { sub: {} };
      +          }
      +
      +          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
      +          hasKeys || (hasKeys = true);
      +          break;
      +        }
      +      }
      +    } else {
      +      paths[name] = query.options.populate[name];
      +      hasKeys || (hasKeys = true);
      +    }
      +  }
      +
      +  return hasKeys && paths;
      +};

      Parameters:

      Returns:


      Model#_populate(schema, oid, query, fn)

      Populates an object

      show code
      Model.prototype._populate = function populate (schema, oid, query, fn) {
      +  if (!Array.isArray(oid)) {
      +    var conditions = query.conditions || {};
      +    conditions._id = oid;
      +
      +    return this
      +    .db.model(query.model || schema.options.ref)
      +    .findOne(conditions, query.fields, query.options, fn);
      +  }
      +
      +  if (!oid.length) {
      +    return fn(null, oid);
      +  }
      +
      +  var model = this.db.model(query.model || schema.caster.options.ref)
      +    , conditions = query && query.conditions || {};
      +
      +  conditions._id || (conditions._id = { $in: oid });
      +
      +  model.find(conditions, query.fields, query.options, function (err, docs) {
      +    if (err) return fn(err);
      +
      +    // user specified sort order?
      +    if (query.options && query.options.sort) {
      +      return fn(null, docs);
      +    }
      +
      +    // put back in original id order (using a hash reduces complexity from n*n to 2n)
      +    var docHash = {};
      +    docs.forEach(function (doc) {
      +      docHash[doc._id] = doc;
      +    });
      +
      +    var arr = [];
      +    oid.forEach(function (id) {
      +      if (id in docHash) arr.push(docHash[id]);
      +    });
      +
      +    fn(null, arr);
      +  });
      +};

      Parameters:

      • schema <SchemaType> type for the oid
      • oid <Object> object id or array of object ids
      • query <Object> object specifying query conditions, fields, and options
      • fn <Function>

      Model#init(doc, query, fn)

      Performs auto-population of relations.

      show code
      Model.prototype.init = function init (doc, query, fn) {
      +  if ('function' == typeof query) {
      +    fn = query;
      +    query = null;
      +  }
      +
      +  var populate = this._getPopulationKeys(query);
      +
      +  if (!populate) {
      +    return Document.prototype.init.call(this, doc, fn);
      +  }
      +
      +  // population from other models is necessary
      +  var self = this;
      +
      +  init(doc, '', function (err) {
      +    if (err) return fn(err);
      +    Document.prototype.init.call(self, doc, fn);
      +  });
      +
      +  return this;
      +
      +  function init (obj, prefix, fn) {
      +    prefix = prefix || '';
      +
      +    var keys = Object.keys(obj)
      +      , len = keys.length;
      +
      +    return next();
      +
      +    function next () {
      +      if (--len < 0) return fn();
      +
      +      var i = keys[len]
      +        , path = prefix + i
      +        , schema = self.schema.path(path)
      +        , total = 0
      +        , inline = false
      +        , poppath
      +
      +      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
      +        // assume nested object
      +        return init(obj[i], path + '.', next);
      +      }
      +
      +      if (!(obj[i] && schema && populate[path])) return next();
      +
      +      // this query object is re-used and passed around. we clone
      +      // it to prevent query condition contamination between
      +      // one populate call to the next.
      +      poppath = utils.clone(populate[path]);
      +
      +      if (poppath.sub) {
      +        obj[i].forEach(function (subobj) {
      +          inline = true;
      +
      +          var pkeys = Object.keys(poppath.sub)
      +            , pi = pkeys.length
      +            , key
      +
      +          while (pi--) {
      +            key = pkeys[pi];
      +
      +            if (subobj[key]) (function (key) {
      +              total++;
      +              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
      +              function done (err, doc) {
      +                if (err) return error(err);
      +                subobj[key] = doc;
      +                if (--total < 1 && !inline) {
      +                  next();
      +                }
      +              }
      +            })(key);
      +          }
      +        });
      +
      +        inline = false;
      +
      +        if (0 === total) return next();
      +
      +      } else {
      +        self._populate(schema, obj[i], poppath, function (err, doc) {
      +          if (err) return error(err);
      +          obj[i] = doc;
      +          next();
      +        });
      +      }
      +    };
      +  };
      +
      +  function error (err) {
      +    if (error.err) return;
      +    fn(error.err = err);
      +  }
      +};

      Parameters:

      • doc <Object> document returned by mongo
      • query <Query> query that originated the initialization
      • fn <Function>

      Model#save([fn])

      Saves this document.

      show code
      Model.prototype.save = function save (fn) {
      +  var promise = new Promise(fn)
      +    , complete = handleSave(promise, this)
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  if (this.isNew) {
      +    // send entire doc
      +    var obj = this.toObject({ depopulate: 1 });
      +    this._version(true, obj);
      +    this.collection.insert(obj, options, complete);
      +    this._reset();
      +    this.isNew = false;
      +    this.emit('isNew', false);
      +    // Make it possible to retry the insert
      +    this._inserting = true;
      +
      +  } else {
      +    // Make sure we don't treat it as a new object on error,
      +    // since it already exists
      +    this._inserting = false;
      +
      +    var delta = this._delta();
      +    if (delta) {
      +      var where = this._where(delta[0]);
      +      this.collection.update(where, delta[1], options, complete);
      +    } else {
      +      complete(null);
      +    }
      +
      +    this._reset();
      +    this.emit('isNew', false);
      +  }
      +};

      Parameters:

      Example:

      + +
      product.sold = Date.now();
      +product.save(function (err, product) {
      +  if (err) ..
      +})
      + +

      The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      + +
      var db = mongoose.createConnection(..);
      +var schema = new Schema(..);
      +var Product = db.model('Product', schema);
      +
      +db.on('error', handleError);
      + +

      However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

      + +
      Product.on('error', handleError);

      Model#_delta()

      Produces a special query document of the modified properties used in updates.

      show code
      Model.prototype._delta = function _delta () {
      +  var dirty = this._dirty();
      +  if (!dirty.length) return;
      +
      +  var self = this
      +    , where = {}
      +    , delta = {}
      +    , len = dirty.length
      +    , d = 0
      +    , val
      +    , obj
      +
      +  for (; d < len; ++d) {
      +    var data = dirty[d]
      +    var value = data.value
      +    var schema = data.schema
      +
      +    if (undefined === value) {
      +      operand(self, where, delta, data, 1, '$unset');
      +
      +    } else if (null === value) {
      +      operand(self, where, delta, data, null);
      +
      +    } else if (value._path && value._atomics) {
      +      handleAtomics(self, where, delta, data, value);
      +
      +    } else if (value._path && Buffer.isBuffer(value)) {
      +      // MongooseBuffer
      +      value = value.toObject();
      +      operand(self, where, delta, data, value);
      +
      +    } else {
      +      value = utils.clone(value);
      +      operand(self, where, delta, data, value);
      +    }
      +  }
      +
      +  if (this.__version) {
      +    this._version(where, delta);
      +  }
      +
      +  return [where, delta];
      +}

      Model#_version()

      Appends versioning to the where and update clauses.

      show code
      Model.prototype._version = function _version (where, delta) {
      +  var key = this.schema.options.versionKey;
      +
      +  if (true === where) {
      +    // this is an insert
      +    if (key) this.setValue(key, delta[key] = 0);
      +    return;
      +  }
      +
      +  // updates
      +
      +  // only apply versioning if our versionKey was selected. else
      +  // there is no way to select the correct version. we could fail
      +  // fast here and force them to include the versionKey but
      +  // thats a bit intrusive. can we do this automatically?
      +  // TODO fail fast option?
      +  if (!this.isSelected(key)) {
      +    return;
      +  }
      +
      +  // $push $addToSet don't need the where clause set
      +  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
      +    where[key] = this.getValue(key);
      +  }
      +
      +  if (VERSION_INC === (VERSION_INC & this.__version)) {
      +    delta.$inc || (delta.$inc = {});
      +    delta.$inc[key] = 1;
      +  }
      +}

      Model#increment()

      Signal that we desire an increment of this documents version.

      show code
      Model.prototype.increment = function increment () {
      +  this.__version = VERSION_ALL;
      +  return this;
      +}

      Model#_where()

      Returns a query object which applies shardkeys if they exist.

      show code
      Model.prototype._where = function _where (where) {
      +  where || (where = {});
      +
      +  var paths
      +    , len
      +
      +  if (this._shardval) {
      +    paths = Object.keys(this._shardval)
      +    len = paths.length
      +
      +    for (var i = 0; i < len; ++i) {
      +      where[paths[i]] = this._shardval[paths[i]];
      +    }
      +  }
      +
      +  where._id = this._doc._id;
      +  return where;
      +}

      Model#remove([fn])

      Removes this document from the db.

      show code
      Model.prototype.remove = function remove (fn) {
      +  if (this._removing) return this;
      +
      +  var promise = this._removing = new Promise(fn)
      +    , where = this._where()
      +    , self = this
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  this.collection.remove(where, options, tick(function (err) {
      +    if (err) {
      +      promise.error(err);
      +      promise = self = self._removing = where = options = null;
      +      return;
      +    }
      +    self.emit('remove', self);
      +    promise.complete();
      +    promise = self = where = options = null;
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Example:

      + +
      product.remove(function (err, product) {
      +  if (err) return handleError(err);
      +  Product.findById(product._id, function (err, product) {
      +    console.log(product) // null
      +  })
      +})

      Model#_registerHooks()

      Register hooks override

      show code
      Model.prototype._registerHooks = function registerHooks () {
      +  Document.prototype._registerHooks.call(this);
      +};

      Model#model(name)

      Returns another Model instance.

      show code
      Model.prototype.model = function model (name) {
      +  return this.db.model(name);
      +};

      Parameters:

      Example:

      + +
      var doc = new Tank;
      +doc.model('User').findById(id, callback);

      Model#$where(argument)

      Creates a Query and specifies a $where condition.

      Parameters:

      • argument <String, Function> is a javascript string or anonymous function

      Returns:

      Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      + +
      Blog.$where('this.comments.length &gt; 5');

      Model.init()

      Called when the model compiles.

      show code
      Model.init = function init () {
      +  if (this.schema.options.autoIndex)
      +    this.ensureIndexes();
      +
      +  this.schema.emit('init', this);
      +};

      Model.ensureIndexes([cb])

      Sends ensureIndex commands to mongo for each index declared in the schema.

      show code
      Model.ensureIndexes = function ensureIndexes (cb) {
      +  var indexes = this.schema.indexes();
      +  if (!indexes.length) {
      +    return cb && cb();
      +  }
      +
      +  var self = this
      +    , safe = self.schema.options.safe
      +    , count = indexes.length
      +    , error
      +
      +  indexes.forEach(function (index) {
      +    var options = index[1];
      +    options.safe = safe;
      +    self.collection.ensureIndex(index[0], options, tick(function (err) {
      +      if (err) error = err;
      +      if (--count) return;
      +
      +      self.emit('index', error);
      +      cb && cb(error);
      +    }));
      +  });
      +}

      Parameters:

      After completion, an index event is emitted on this Model passing an error if one occurred.


      Model.remove(conditions, [callback])

      Removes documents from the collection.

      show code
      Model.remove = function remove (conditions, callback) {
      +  if ('function' === typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +  }
      +
      +  var query = new Query(conditions).bind(this, 'remove');
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.remove(callback);
      +};

      Parameters:

      Returns:

      Note:

      + +

      To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.remove({ _id: id }).exec();

      Model.find(conditions, [fields], [options], [callback])

      Finds documents

      show code
      Model.find = function find (conditions, fields, options, callback) {
      +  if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options);
      +  query.bind(this, 'find');
      +  query.select(fields);
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.find(callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      // retrieve only certain keys
      +MyModel.find({ name: /john/i }, 'name friends', function () { })
      +
      +// pass options
      +MyModel.find({ name: /john/i }, null, { skip: 10 } )

      Model._applyNamedScope(query)

      Merges the current named scope query into query.

      show code
      Model._applyNamedScope = function _applyNamedScope (query) {
      +  var cQuery = this._cumulativeQuery;
      +
      +  if (cQuery) {
      +    merge(query._conditions, cQuery._conditions);
      +    if (query._fields && cQuery._fields)
      +      merge(query._fields, cQuery._fields);
      +    if (query.options && cQuery.options)
      +      merge(query.options, cQuery.options);
      +    delete this._cumulativeQuery;
      +  }
      +
      +  return query;
      +}

      Parameters:

      Returns:


      Model.findById(id, [fields], [options], [callback])

      Finds a single document by id.

      show code
      Model.findById = function findById (id, fields, options, callback) {
      +  return this.findOne({ _id: id }, fields, options, callback);
      +};

      Parameters:

      Returns:

      The id is cast to an ObjectId before sending the command.

      + +

      Example:

      + +
      Adventure.findById(id, callback);

      Model.findOne(conditions, [fields], [options], [callback])

      Finds one document.

      show code
      Model.findOne = function findOne (conditions, fields, options, callback) {
      +  if ('function' == typeof options) {
      +    // TODO Handle all 3 of the following scenarios
      +    // Hint: Only some of these scenarios are possible if cQuery is present
      +    // Scenario: findOne(conditions, fields, callback);
      +    // Scenario: findOne(fields, options, callback);
      +    // Scenario: findOne(conditions, options, callback);
      +    callback = options;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    // TODO Handle all 2 of the following scenarios
      +    // Scenario: findOne(conditions, callback)
      +    // Scenario: findOne(fields, callback)
      +    // Scenario: findOne(options, callback);
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOne(callback);
      +};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      + +

      Example:

      + +
      Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

      Model.count(conditions, [callback])

      Counts number of matching documents in a database collection.

      show code
      Model.count = function count (conditions, callback) {
      +  if ('function' === typeof conditions)
      +    callback = conditions, conditions = {};
      +
      +  var query = new Query(conditions).bind(this, 'count');
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.count(callback);
      +};

      Parameters:

      Returns:

      Example:

      + +
      Adventure.count({ type: 'jungle' }, function (err, count) {
      +  if (err) ..
      +  console.log('there are %d jungle adventures', count);
      +});

      Model.distinct(field, [conditions], [callback])

      Executes a DISTINCT command

      show code
      Model.distinct = function distinct (field, conditions, callback) {
      +  var query = new Query(conditions).bind(this, 'distinct');
      +  if ('undefined' == typeof callback) {
      +    query._distinctArg = field;
      +    return query;
      +  }
      +
      +  this._applyNamedScope(query);
      +  return query.distinct(field, callback);
      +};

      Parameters:

      Returns:


      Model.where(path, [val])

      Creates a Query, applies the passed conditions, and returns the Query.

      show code
      Model.where = function where (path, val) {
      +  var q = new Query().bind(this, 'find');
      +  return q.where.apply(q, arguments);
      +};

      Parameters:

      Returns:

      For example, instead of writing:

      + +
      User.find({age: {$gte: 21, $lte: 65}}, callback);
      + +

      we can instead write:

      + +
      User.where('age').gte(21).lte(65).exec(callback);
      + +

      Since the Query class also supports where you can continue chaining

      + +
      User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +... etc

      Model.findOneAndUpdate([conditions], [update], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Model.findOneAndUpdate = function (conditions, update, options, callback) {
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +  else if (1 === arguments.length) {
      +    if ('function' == typeof conditions) {
      +      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    update = conditions;
      +    conditions = undefined;
      +  }
      +
      +  var fields;
      +  if (options && options.fields) {
      +    fields = options.fields;
      +    options.fields = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndUpdate', update);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndUpdate(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndUpdate(conditions, update, options, callback) // executes
      +A.findOneAndUpdate(conditions, update, options)  // returns Query
      +A.findOneAndUpdate(conditions, update, callback) // executes
      +A.findOneAndUpdate(conditions, update)           // returns Query
      +A.findOneAndUpdate()                             // returns Query
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findByIdAndUpdate(id, [update], [options], [callback])

      Issues a mongodb findAndModify update command by a documents id.

      show code
      Model.findByIdAndUpdate = function (id, update, options, callback) {
      +  var args;
      +
      +  if (1 === arguments.length) {
      +    if ('function' == typeof id) {
      +      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
      +
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    return this.findOneAndUpdate({_id: id }, undefined);
      +  }
      +
      +  args = utils.args(arguments, 1);
      +  args.unshift({ _id: id });
      +  return this.findOneAndUpdate.apply(this, args);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndUpdate(id, update, options, callback) // executes
      +A.findByIdAndUpdate(id, update, options)  // returns Query
      +A.findByIdAndUpdate(id, update, callback) // executes
      +A.findByIdAndUpdate(id, update)           // returns Query
      +A.findByIdAndUpdate()                     // returns Query
      + +

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findById(id, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findOneAndRemove(conditions, [options], [callback])

      Issue a mongodb findAndModify remove command.

      show code
      Model.findOneAndRemove = function (conditions, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof conditions) {
      +    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  }
      +
      +  var fields;
      +  if (options) {
      +    fields = options.select;
      +    options.select = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndRemove');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndRemove(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndRemove(conditions, options, callback) // executes
      +A.findOneAndRemove(conditions, options)  // return Query
      +A.findOneAndRemove(conditions, callback) // executes
      +A.findOneAndRemove(conditions) // returns Query
      +A.findOneAndRemove()           // returns Query

      Model.findByIdAndRemove(id, [options], [callback])

      Issue a mongodb findAndModify remove command by a documents id.

      show code
      Model.findByIdAndRemove = function (id, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof id) {
      +    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  return this.findOneAndRemove({ _id: id }, options, callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed, else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndRemove(id, options, callback) // executes
      +A.findByIdAndRemove(id, options)  // return Query
      +A.findByIdAndRemove(id, callback) // executes
      +A.findByIdAndRemove(id) // returns Query
      +A.findByIdAndRemove()           // returns Query

      Model.create(doc, fn)

      Shortcut for creating a new Document that is automatically saved to the db if valid.

      show code
      Model.create = function create (doc, fn) {
      +  if (1 === arguments.length) {
      +    return 'function' === typeof doc && doc(null);
      +  }
      +
      +  var self = this
      +    , docs = [null]
      +    , promise
      +    , count
      +    , args
      +
      +  if (Array.isArray(doc)) {
      +    args = doc;
      +  } else {
      +    args = utils.args(arguments, 0, arguments.length - 1);
      +    fn = arguments[arguments.length - 1];
      +  }
      +
      +  if (0 === args.length) return fn(null);
      +
      +  promise = new Promise(fn);
      +  count = args.length;
      +
      +  args.forEach(function (arg, i) {
      +    var doc = new self(arg);
      +    docs[i+1] = doc;
      +    doc.save(function (err) {
      +      if (err) return promise.error(err);
      +      --count || fn.apply(null, docs);
      +    });
      +  });
      +
      +  // TODO
      +  // utilize collection.insertAll for batch processing?
      +};

      Parameters:

      Example:

      + +
      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});
      +
      +var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      +Candy.create(array, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});

      Model.update(conditions, update, [options], [callback])

      Updates documents in the database without returning them.

      show code
      Model.update = function update (conditions, doc, options, callback) {
      +  if (arguments.length < 4) {
      +    if ('function' === typeof options) {
      +      // Scenario: update(conditions, doc, callback)
      +      callback = options;
      +      options = null;
      +    } else if ('function' === typeof doc) {
      +      // Scenario: update(doc, callback);
      +      callback = doc;
      +      doc = conditions;
      +      conditions = {};
      +      options = null;
      +    }
      +  }
      +
      +  var query = new Query(conditions, options).bind(this, 'update', doc);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.update(doc, callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
      +MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
      +  if (err) return handleError(err);
      +  console.log('The number of updated documents was %d', numberAffected);
      +  console.log('The raw response from Mongo was ', raw);
      +});
      + +

      Valid options:

      + +
        +
      • safe (boolean) safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +
      • multi (boolean) whether multiple documents should be updated (false)
      • +
      + +

      All update values are cast to their appropriate SchemaTypes before being sent.

      + +

      The callback function receives (err, numberAffected, rawResponse).

      + +
        +
      • err is the error if any occurred
      • +
      • numberAffected is the count of updated documents Mongo reported
      • +
      • rawResponse is the full response from Mongo
      • +
      + +

      Note:

      + +

      All top level keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.update(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

      + +

      Note:

      + +

      To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
      + +

      Note:

      + +

      Although values are casted to their appropriate types when using update, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.mapReduce(o, callback)

      Executes a mapReduce command.

      show code
      Model.mapReduce = function mapReduce (o, callback) {
      +  if ('function' != typeof callback) throw new Error('missing callback');
      +
      +  var self = this;
      +
      +  if (!Model.mapReduce.schema) {
      +    var opts = { noId: true, noVirtualId: true, strict: false }
      +    Model.mapReduce.schema = new Schema({}, opts);
      +  }
      +
      +  if (!o.out) o.out = { inline: 1 };
      +
      +  o.map = String(o.map);
      +  o.reduce = String(o.reduce);
      +
      +  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
      +    if (err) return callback(err);
      +
      +    if (ret.findOne && ret.mapReduce) {
      +      // returned a collection, convert to Model
      +      var model = Model.compile(
      +          '_mapreduce_' + ret.collectionName
      +        , Model.mapReduce.schema
      +        , ret.collectionName
      +        , self.db
      +        , self.base);
      +
      +      model._mapreduce = true;
      +
      +      return callback(err, model, stats);
      +    }
      +
      +    callback(err, ret, stats);
      +  });
      +}

      Parameters:

      • o <Object> an object specifying map-reduce options
      • callback <Function>

      o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +User.mapReduce(o, function (err, results) {
      +  console.log(results)
      +})
      + +

      Other options:

      + +
        +
      • query {Object} query filter object.
      • +
      • limit {Number} max number of documents
      • +
      • keeptemp {Boolean, default:false} keep temporary data
      • +
      • finalize {Function} finalize function
      • +
      • scope {Object} scope variables exposed to map/reduce/finalize during execution
      • +
      • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
      • +
      • verbose {Boolean, default:false} provide statistics on job execution time.
      • +
      • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
      • +
      + +

      * out options:

      + +
        +
      • {inline:1} the results are returned in an array
      • +
      • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
      • +
      • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
      • +
      • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
      • +
      + +

      If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +o.out = { replace: 'createdCollectionNameForResults' }
      +o.verbose = true;
      +User.mapReduce(o, function (err, model, stats) {
      +  console.log('map reduce took %d ms', stats.processtime)
      +  model.find().where('value').gt(10).exec(function (err, docs) {
      +    console.log(docs);
      +  });
      +})

      Model#base

      Base Mongoose instance the model uses.


      Model#collection

      Collection the model uses.


      Model#db

      Database instance the model uses.


      Model#schema

      Schema the model uses.


      Model#modelName

      The name of the model


      Model#collection

      Collection the model uses.


      Model#db

      Connection the model uses.


    • namedscope.js

      NamedScope#decorate(target, getters)

      Decorate

      show code
      NamedScope.prototype.decorate = function (target, getters) {
      +  var name = this.name
      +    , block = this.block
      +    , query = this.query;
      +  if (block) {
      +    if (block.length === 0) {
      +      Object.defineProperty(target, name, {
      +        get: getters.block0(block)
      +      });
      +    } else {
      +      target[name] = getters.blockN(block);
      +    }
      +  } else {
      +    Object.defineProperty(target, name, {
      +      get: getters.basic(query)
      +    });
      +  }
      +};
      +
      +NamedScope.prototype.compile = function (model) {
      +  var allScopes = this.scopesByName
      +    , scope;
      +  for (var k in allScopes) {
      +    scope = allScopes[k];
      +    scope.decorate(model, {
      +      block0: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.call(cquery);
      +          return this;
      +        };
      +      },
      +      blockN: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.apply(cquery, arguments);
      +          return this;
      +        };
      +      },
      +      basic: function (query) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          cquery.find(query);
      +          return this;
      +        };
      +      }
      +    });
      +  }
      +};
      +
      +module.exports = NamedScope;

      Parameters:


    • promise.js

      Promise(back)

      Promise constructor.

      show code
      function Promise (back) {
      +  this.emitted = {};
      +  if ('function' == typeof back)
      +    this.addBack(back);
      +};

      Parameters:

      • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

      Events:

      • err: Emits when the promise resolves to an error.

      • complete: Emits when the promise resolves sucessfully.


      Promise#on(event, callback)

      Adds listener to the event.

      show code
      Promise.prototype.on = function (event, callback) {
      +  if (this.emitted[event])
      +    callback.apply(this, this.emitted[event]);
      +  else
      +    EventEmitter.prototype.on.call(this, event, callback);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


      Promise#emit()

      Keeps track of emitted events to run them on on.

      show code
      Promise.prototype.emit = function (event) {
      +  // ensures a promise can't be complete() or error() twice
      +  if (event == 'err' || event == 'complete'){
      +    if (this.emitted.err || this.emitted.complete) {
      +      return this;
      +    }
      +    this.emitted[event] = util.args(arguments, 1);
      +  }
      +
      +  return EventEmitter.prototype.emit.apply(this, arguments);
      +};

      Promise#complete()

      Shortcut for emitting the complete event.

      show code
      Promise.prototype.complete = function () {
      +  var args = util.args(arguments);
      +  return this.emit.apply(this, ['complete'].concat(args));
      +};

      Promise#error()

      Shortcut for emitting the err event.

      show code
      Promise.prototype.error = function (err) {
      +  if (!(err instanceof Error)) err = new Error(err);
      +  return this.emit('err', err);
      +};

      Returns:


      Promise#addCallback()

      Shortcut for .on('complete', fn).

      show code
      Promise.prototype.addCallback = function (fn) {
      +  return this.on('complete', fn);
      +};

      Returns:


      Promise#addErrback()

      Shortcut for .on('err', fn).

      show code
      Promise.prototype.addErrback = function (fn) {
      +  return this.on('err', fn);
      +};

      Returns:


      Promise#addBack(fn)

      Adds a single function that's both a callback and errback.

      show code
      Promise.prototype.addBack = function (fn) {
      +  this.on('err', function(err){
      +    fn.call(this, err);
      +  });
      +
      +  this.on('complete', function(){
      +    var args = util.args(arguments);
      +    fn.apply(this, [null].concat(args));
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Promise#resolve(err, val)

      Sugar for handling cases where you may be resolving to either an error condition or a success condition.

      show code
      Promise.prototype.resolve = function (err, val) {
      +  if (err) return this.error(err);
      +  return this.complete(val);
      +};

      Parameters:

      • err <Error> optional error or null
      • val <Object> value to complete the promise with

    • query.js

      Query(criteria, options)

      Query constructor used for building queries.

      show code
      function Query (criteria, options) {
      +  this.setOptions(options, true);
      +  this._conditions = {};
      +  this._updateArg = {};
      +  if (criteria) this.find(criteria);
      +}

      Parameters:

      Example:

      + +
      var query = Model.find();
      +query.where('age').gte(21).exec(callback);

      Query#setOptions(options)

      Sets query options.

      show code
      Query.prototype.setOptions = function (options, overwrite) {
      +  // overwrite is internal use only
      +  if (overwrite) {
      +    options = this.options = options || {};
      +    this.safe = options.safe
      +
      +    // normalize population options
      +    var pop = this.options.populate;
      +    this.options.populate = {};
      +
      +    if (pop && Array.isArray(pop)) {
      +      for (var i = 0, l = pop.length; i < l; i++) {
      +        this.options.populate[pop[i]] = {};
      +      }
      +    }
      +
      +    return this;
      +  }
      +
      +  if (!(options && 'Object' == options.constructor.name))
      +    return this;
      +
      +  if ('safe' in options)
      +    this.safe = options.safe;
      +
      +  // set arbitrary options
      +  var methods = Object.keys(options)
      +    , i = methods.length
      +    , method
      +
      +  while (i--) {
      +    method = methods[i];
      +
      +    // use methods if exist (safer option manipulation)
      +    if ('function' == typeof this[method]) {
      +      var args = Array.isArray(options[method])
      +        ? options[method]
      +        : [options[method]];
      +      this[method].apply(this, args)
      +    } else {
      +      this.options[method] = options[method];
      +    }
      +  }
      +  return this;
      +}

      Parameters:

      Options:

      + + + +

      * denotes a query helper method is also available


      Query#bind(model, op, updateArg)

      Binds this query to a model.

      show code
      Query.prototype.bind = function bind (model, op, updateArg) {
      +  this.model = model;
      +  this.op = op;
      +
      +  if (model._mapreduce) this.options.lean = true;
      +
      +  if (op == 'update' || op == 'findOneAndUpdate') {
      +    merge(this._updateArg, updateArg || {});
      +  }
      +
      +  return this;
      +};

      Parameters:

      • model <Model> the model to which the query is bound
      • op <String> the operation to execute
      • updateArg <Object> used in update methods

      Returns:


      Query#exec([operation], [callback])

      Executes the query

      show code
      Query.prototype.exec = function exec (op, callback) {
      +  var promise = new Promise();
      +
      +  switch (typeof op) {
      +    case 'function':
      +      callback = op;
      +      op = null;
      +      break;
      +    case 'string':
      +      this.op = op;
      +      break;
      +  }
      +
      +  if (callback) promise.addBack(callback);
      +
      +  if (!this.op) {
      +    promise.complete();
      +    return promise;
      +  }
      +
      +  if ('update' == this.op) {
      +    this[this.op](this._updateArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  if ('distinct' == this.op) {
      +    this.distinct(this._distinctArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  this[this.op](promise.resolve.bind(promise));
      +  return promise;
      +};

      Parameters:

      Returns:

      Examples

      + +
      query.exec();
      +query.exec(callback);
      +query.exec('update');
      +query.exec('find', callback);

      Query#find([criteria], [callback])

      Finds documents.

      show code
      Query.prototype.find = function (criteria, callback) {
      +  this.op = 'find';
      +  if ('function' === typeof criteria) {
      +    callback = criteria;
      +    criteria = {};
      +  } else if (criteria instanceof Query) {
      +    // TODO Merge options, too
      +    merge(this._conditions, criteria._conditions);
      +  } else if (criteria instanceof Document) {
      +    merge(this._conditions, criteria.toObject());
      +  } else if (criteria && 'Object' === criteria.constructor.name) {
      +    merge(this._conditions, criteria);
      +  }
      +  if (!callback) return this;
      +  return this.execFind(callback);
      +};

      Parameters:

      Returns:

      When no callback is passed, the query is not executed.

      + +

      Example

      + +
      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

      Query#cast(model, [obj])

      Casts this query to the schema of model

      show code
      Query.prototype.cast = function (model, obj) {
      +  obj || (obj= this._conditions);
      +
      +  var schema = model.schema
      +    , paths = Object.keys(obj)
      +    , i = paths.length
      +    , any$conditionals
      +    , schematype
      +    , nested
      +    , path
      +    , type
      +    , val;
      +
      +  while (i--) {
      +    path = paths[i];
      +    val = obj[path];
      +
      +    if ('$or' === path || '$nor' === path) {
      +      var k = val.length
      +        , orComponentQuery;
      +
      +      while (k--) {
      +        orComponentQuery = new Query(val[k]);
      +        orComponentQuery.cast(model);
      +        val[k] = orComponentQuery._conditions;
      +      }
      +
      +    } else if (path === '$where') {
      +      type = typeof val;
      +
      +      if ('string' !== type && 'function' !== type) {
      +        throw new Error("Must have a string or function for $where");
      +      }
      +
      +      if ('function' === type) {
      +        obj[path] = val.toString();
      +      }
      +
      +      continue;
      +
      +    } else {
      +
      +      if (!schema) {
      +        // no casting for Mixed types
      +        continue;
      +      }
      +
      +      schematype = schema.path(path);
      +
      +      if (!schematype) {
      +        // Handle potential embedded array queries
      +        var split = path.split('.')
      +          , j = split.length
      +          , pathFirstHalf
      +          , pathLastHalf
      +          , remainingConds
      +          , castingQuery;
      +
      +        // Find the part of the var path that is a path of the Schema
      +        while (j--) {
      +          pathFirstHalf = split.slice(0, j).join('.');
      +          schematype = schema.path(pathFirstHalf);
      +          if (schematype) break;
      +        }
      +
      +        // If a substring of the input path resolves to an actual real path...
      +        if (schematype) {
      +          // Apply the casting; similar code for $elemMatch in schema/array.js
      +          if (schematype.caster && schematype.caster.schema) {
      +            remainingConds = {};
      +            pathLastHalf = split.slice(j).join('.');
      +            remainingConds[pathLastHalf] = val;
      +            castingQuery = new Query(remainingConds);
      +            castingQuery.cast(schematype.caster);
      +            obj[path] = castingQuery._conditions[pathLastHalf];
      +          } else {
      +            obj[path] = val;
      +          }
      +        }
      +
      +      } else if (val === null || val === undefined) {
      +        continue;
      +      } else if ('Object' === val.constructor.name) {
      +
      +        any$conditionals = Object.keys(val).some(function (k) {
      +          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
      +        });
      +
      +        if (!any$conditionals) {
      +          obj[path] = schematype.castForQuery(val);
      +        } else {
      +
      +          var ks = Object.keys(val)
      +            , k = ks.length
      +            , $cond;
      +
      +          while (k--) {
      +            $cond = ks[k];
      +            nested = val[$cond];
      +
      +            if ('$exists' === $cond) {
      +              if ('boolean' !== typeof nested) {
      +                throw new Error("$exists parameter must be Boolean");
      +              }
      +              continue;
      +            }
      +
      +            if ('$type' === $cond) {
      +              if ('number' !== typeof nested) {
      +                throw new Error("$type parameter must be Number");
      +              }
      +              continue;
      +            }
      +
      +            if ('$not' === $cond) {
      +              this.cast(model, nested);
      +            } else {
      +              val[$cond] = schematype.castForQuery($cond, nested);
      +            }
      +          }
      +        }
      +      } else {
      +        obj[path] = schematype.castForQuery(val);
      +      }
      +    }
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Returns:

      Note

      + +

      If obj is present, it is cast instead of this query.


      Query#_optionsForExec(model)

      Returns default options.

      show code
      Query.prototype._optionsForExec = function (model) {
      +  var options = utils.clone(this.options, { retainKeyOrder: true });
      +  delete options.populate;
      +  if (! ('safe' in options)) options.safe = model.schema.options.safe;
      +  return options;
      +};

      Parameters:


      Query#_applyPaths()

      Applies schematype selected options to this query.

      show code
      Query.prototype._applyPaths = function applyPaths () {
      +  // determine if query is selecting or excluding fields
      +
      +  var fields = this._fields
      +    , exclude
      +    , keys
      +    , ki
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('+' == keys[ki][0]) continue;
      +      exclude = 0 === fields[keys[ki]];
      +      break;
      +    }
      +  }
      +
      +  // if selecting, apply default schematype select:true fields
      +  // if excluding, apply schematype select:false fields
      +
      +  var selected = []
      +    , excluded = []
      +    , seen = [];
      +
      +  analyzeSchema(this.model.schema);
      +
      +  switch (exclude) {
      +    case true:
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +    case false:
      +      selected.length && this.select(selected.join(' '));
      +      break;
      +    case undefined:
      +      // user didn't specify fields, implies returning all fields.
      +      // only need to apply excluded fields
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +  }
      +
      +  return seen = excluded = selected = keys = fields = null;
      +
      +  function analyzeSchema (schema, prefix) {
      +    prefix || (prefix = '');
      +
      +    // avoid recursion
      +    if (~seen.indexOf(schema)) return;
      +    seen.push(schema);
      +
      +    schema.eachPath(function (path, type) {
      +      if (prefix) path = prefix + '.' + path;
      +
      +      // array of subdocs?
      +      if (type.schema) {
      +        analyzeSchema(type.schema, path);
      +      }
      +
      +      analyzePath(path, type);
      +    });
      +  }
      +
      +  function analyzePath (path, type) {
      +    if ('boolean' != typeof type.selected) return;
      +
      +    if (fields && ('+' + path) in fields) {
      +      // forced inclusion
      +      delete fields['+' + path];
      +
      +      // if there are other fields being included, add this one
      +      // if no other included fields, leave this out (implied inclusion)
      +      if (false === exclude && keys.length > 1) {
      +        fields[path] = 1;
      +      }
      +
      +      return
      +    };
      +
      +    ;(type.selected ? selected : excluded).push(path);
      +  }
      +}

      Query#$where(js)

      Specifies a $where condition

      Parameters:

      Returns:

      Use $where when you need to select documents using a JavaScript expression.

      + +

      Example

      + +
      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
      +
      +query.$where(function () {
      +  return this.comments.length &gt; 10 || this.name.length &gt; 5;
      +})

      Query#where([path], [val])

      Specifies a path for use with chaining.

      show code
      Query.prototype.where = function (path, val) {
      +  if (!arguments.length) return this;
      +
      +  if ('string' != typeof path) {
      +    throw new TypeError('path must be a string');
      +  }
      +
      +  this._currPath = path;
      +
      +  if (2 === arguments.length) {
      +    this._conditions[path] = val;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      // instead of writing:
      +User.find({age: {$gte: 21, $lte: 65}}, callback);
      +
      +// we can instead write:
      +User.where('age').gte(21).lte(65);
      +
      +// Moreover, you can also chain a bunch of these together:
      +
      +User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +.where('friends').slice(10)
      +.exec(callback)

      Query#equals(val)

      Specifies the complementary comparison value for paths specified with where()

      show code
      Query.prototype.equals = function equals (val) {
      +  var path = this._currPath;
      +  if (!path) throw new Error('equals() must be used after where()');
      +  this._conditions[path] = val;
      +  return this;
      +}

      Parameters:

      Returns:

      Example

      + +
      User.where('age').equals(49);
      +
      +// is the same as
      +
      +User.where('age', 49);

      Query#or(array)

      Specifies arguments for an $or condition.

      show code
      Query.prototype.or = function or (array) {
      +  var or = this._conditions.$or || (this._conditions.$or = []);
      +  if (!Array.isArray(array)) array = [array];
      +  or.push.apply(or, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.or([{ color: 'red' }, { status: 'emergency' }])

      Query#nor(array)

      Specifies arguments for a $nor condition.

      show code
      Query.prototype.nor = function nor (array) {
      +  var nor = this._conditions.$nor || (this._conditions.$nor = []);
      +  if (!Array.isArray(array)) array = [array];
      +  nor.push.apply(nor, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.nor([{ color: 'green' }, { status: 'ok' }])

      Query#gt(path, val)

      Specifies a $gt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.

      + +

      Example

      + +
      Thing.find().where('age').gt(21)
      +
      +// or
      +Thing.find().gt('age', 21)

      Query#gte(path, val)

      Specifies a $gte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lt(path, val)

      Specifies a $lt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lte(path, val)

      Specifies a $lte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#ne(path, val)

      Specifies a $ne query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#in(path, val)

      Specifies an $in query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#nin(path, val)

      Specifies an $nin query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#all(path, val)

      Specifies an $all query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#size(path, val)

      Specifies an $size query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#regex(path, val)

      Specifies a $regex query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#maxDistance(path, val)

      Specifies a $maxDistance query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#near(path, val)

      Specifies a $near condition

      show code
      Query.prototype.near = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$near = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#nearSphere(path, val)

      Specifies a $nearSphere condition.

      show code
      Query.prototype.nearSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$nearSphere = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#mod(path, val)

      Specifies a $mod condition

      show code
      Query.prototype.mod = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$mod = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#exists(path, val)

      Specifies an $exists condition

      show code
      Query.prototype.exists = function (path, val) {
      +  if (arguments.length === 0) {
      +    path = this._currPath
      +    val = true;
      +  } else if (arguments.length === 1) {
      +    if ('boolean' === typeof path) {
      +      val = path;
      +      path = this._currPath;
      +    } else {
      +      val = true;
      +    }
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$exists'] = val;
      +  return this;
      +};

      Parameters:

      Returns:


      Query#elemMatch(path, criteria)

      Specifies an $elemMatch condition

      show code
      Query.prototype.elemMatch = function (path, criteria) {
      +  var block;
      +  if ('Object' === path.constructor.name) {
      +    criteria = path;
      +    path = this._currPath;
      +  } else if ('function' === typeof path) {
      +    block = path;
      +    path = this._currPath;
      +  } else if ('Object' === criteria.constructor.name) {
      +  } else if ('function' === typeof criteria) {
      +    block = criteria;
      +  } else {
      +    throw new Error("Argument error");
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  if (block) {
      +    criteria = new Query();
      +    block(criteria);
      +    conds['$elemMatch'] = criteria._conditions;
      +  } else {
      +    conds['$elemMatch'] = criteria;
      +  }
      +  return this;
      +};
      +
      +// Spatial queries

      Parameters:

      Returns:

      Example

      + +
      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
      +
      +query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
      +
      +query.elemMatch('comment', function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})
      +
      +query.where('comment').elemMatch(function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})

      Query#box(path, val)

      Specifies a $box condition

      show code
      Query.prototype.box = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$box': [val.ll, val.ur]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var lowerLeft = [40.73083, -73.99756]
      +var upperRight= [40.741404,  -73.988135]
      +query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

      Query#center(path, val, [opts])

      Specifies a $center condition

      show code
      Query.prototype.center = function (path, val, opts) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$center': [val.center, val.radius]  };
      +
      +  // copy any options
      +  if (opts && 'Object' == opts.constructor.name) {
      +    utils.options(opts, conds.$within);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.center(area)

      Query#centerSphere(path, val)

      Specifies a $centerSphere condition

      show code
      Query.prototype.centerSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.centerSphere(area)

      Query#polygon(path, val)

      Specifies a $polygon condition

      show code
      Query.prototype.polygon = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$polygon': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      +query.where('loc').within.polygon(polyA)
      +
      +// or
      +var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      +query.where('loc').within.polygon(polyB)

      Query#select(arg)

      Specifies which document fields to include or exclude

      show code
      Query.prototype.select = function select (arg) {
      +  if (!arg) return this;
      +
      +  var fields = this._fields || (this._fields = {});
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      fields[field] = arg[field];
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var include = '-' == field[0] ? 0 : 1;
      +      if (include === 0) field = field.substring(1);
      +      fields[field] = include;
      +    });
      +  } else {
      +    throw new TypeError('Invalid select() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

      + +

      Example

      + +
      // include a and b, exclude c
      +query.select('a b -c');
      +
      +// or you may use object notation, useful when
      +// you have keys already prefixed with a "-"
      +query.select({a: 1, b: 1, c: 0});
      +
      +// force inclusion of field excluded at schema level
      +query.select('+path')

      Query#slice(path, val)

      Specifies a $slice condition

      show code
      Query.prototype.slice = function (path, val) {
      +  if (arguments.length === 1) {
      +      val = path;
      +      path = this._currPath
      +  } else if (arguments.length === 2) {
      +    if ('number' === typeof path) {
      +      val = [path, val];
      +      path = this._currPath;
      +    }
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var myFields = this._fields || (this._fields = {});
      +  myFields[path] = { '$slice': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      query.slice('comments', 5)
      +query.slice('comments', -5)
      +query.slice('comments', [10, 5])
      +query.where('comments').slice(5)
      +query.where('comments').slice([-10, 5])

      Query#sort(arg)

      Sets the sort order

      show code
      Query.prototype.sort = function (arg) {
      +  if (!arg) return this;
      +
      +  var sort = this.options.sort || (this.options.sort = []);
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      push(sort, field, arg[field]);
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var ascend = '-' == field[0] ? -1 : 1;
      +      if (ascend === -1) field = field.substring(1);
      +      push(sort, field, ascend);
      +    });
      +  } else {
      +    throw new TypeError('Invalid sort() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

      + +

      If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

      + +

      Example

      + +
      // these are equivalent
      +query.sort({ field: 'asc', test: -1 });
      +query.sort('field -test');

      Query#limit(val)

      Specifies the limit option.

      Parameters:

      Example

      + +
      Kitten.find().limit(20)

      Query#skip(val)

      Specifies the skip option.

      Parameters:

      Example

      + +
      Kitten.find().skip(100).limit(20)

      Query#maxscan(val)

      Specifies the maxscan option.

      Parameters:

      Example

      + +
      Kitten.find().maxscan(100)

      Query#batchSize(val)

      Specifies the batchSize option.

      Parameters:

      Example

      + +
      Kitten.find().batchSize(100)

      Query#comment(val)

      Specifies the comment option.

      Parameters:

      Example

      + +
      Kitten.findOne(condition).comment('login query')

      Query#snapshot()

      Specifies this query as a snapshot query.

      show code
      Query.prototype.snapshot = function () {
      +  this.options.snapshot = true;
      +  return this;
      +};

      Returns:

      Example

      + +
      Kitten.find().snapshot()

      Query#hint(val)

      Sets query hints.

      show code
      Query.prototype.hint = function (val) {
      +  if (!val) return this;
      +
      +  var hint = this.options.hint || (this.options.hint = {});
      +
      +  if ('Object' === val.constructor.name) {
      +    // must keep object keys in order so don't use Object.keys()
      +    for (var k in val) {
      +      hint[k] = val[k];
      +    }
      +  } else {
      +    throw new TypeError('Invalid hint. ' + val);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Model.find().hint({ indexA: 1, indexB: -1})

      Query#slaveOk(v)

      Sets the slaveOk option.

      show code
      Query.prototype.slaveOk = function (v) {
      +  this.options.slaveOk = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Example:

      + +
      new Query().slaveOk() // true
      +new Query().slaveOk(true)
      +new Query().slaveOk(false)

      Query#lean(v)

      Sets the lean option.

      show code
      Query.prototype.lean = function (v) {
      +  this.options.lean = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

      + +

      This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

      + +

      Example:

      + +
      new Query().lean() // true
      +new Query().lean(true)
      +new Query().lean(false)
      +
      +Model.find().lean().exec();
      +
      +var leanStream = Model.find().lean().stream();

      Query#tailable(v)

      Sets tailable option.

      show code
      Query.prototype.tailable = function (v) {
      +  this.options.tailable = arguments.length ? !!v : true;
      +  return this;
      +};

      Parameters:

      Example

      + +
      Kitten.find().tailable() &lt;== true
      +Kitten.find().tailable(true)
      +Kitten.find().tailable(false)

      Query#execFind(callback)

      Executes the query as a find() operation.

      show code
      Query.prototype.execFind = function (callback) {
      +  var model = this.model
      +    , promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +
      +  var fields = utils.clone(options.fields = this._fields);
      +
      +  model.collection.find(castQuery, options, function (err, cursor) {
      +    if (err) return promise.error(err);
      +    cursor.toArray(tick(cb));
      +  });
      +
      +  function cb (err, docs) {
      +    if (err) return promise.error(err);
      +
      +    if (true === options.lean)
      +      return promise.complete(docs);
      +
      +    var arr = []
      +      , count = docs.length;
      +
      +    if (!count) return promise.complete([]);
      +
      +    for (var i = 0, l = docs.length; i < l; i++) {
      +      arr[i] = new model(undefined, fields, true);
      +      arr[i].init(docs[i], self, function (err) {
      +        if (err) return promise.error(err);
      +        --count || promise.complete(arr);
      +      });
      +    }
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#findOne(callback)

      Executes the query as a findOne() operation.

      show code
      Query.prototype.findOne = function (callback) {
      +  this.op = 'findOne';
      +
      +  if (!callback) return this;
      +
      +  var model = this.model;
      +  var promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +
      +  var fields = utils.clone(options.fields = this._fields);
      +
      +  model.collection.findOne(castQuery, options, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === options.lean) return promise.complete(doc);
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'white').findOne(function (err, kitten) {
      +  if (err) return handleError(err);
      +
      +  // kitten may be null if no document matched
      +  if (kitten) {
      +    ...
      +  }
      +})

      Query#count(callback)

      Exectues the query as a count() operation.

      show code
      Query.prototype.count = function (callback) {
      +  this.op = 'count';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.count(castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'black').count(function (err, count) {
      +  if (err) return handleError(err);
      +  console.log('there are %d black kittens', count);
      +})

      Query#distinct(field, callback)

      Executes this query as a distict() operation.

      show code
      Query.prototype.distinct = function (field, callback) {
      +  this.op = 'distinct';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.distinct(field, castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#update(doc, callback)

      Executes this query as an update() operation.

      show code
      Query.prototype.update = function update (doc, callback) {
      +  this.op = 'update';
      +  this._updateArg = doc;
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , fn = 'function' == typeof callback
      +    , castedQuery
      +    , castedDoc
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedQuery));
      +      return this;
      +    }
      +    throw castedQuery;
      +  }
      +
      +  castedDoc = castDoc(this);
      +  if (!castedDoc) {
      +    fn && process.nextTick(callback.bind(null, null, 0));
      +    return this;
      +  }
      +
      +  if (castedDoc instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedDoc));
      +      return this;
      +    }
      +    throw castedDoc;
      +  }
      +
      +  if (!fn) {
      +    delete options.safe;
      +  }
      +
      +  model.collection.update(castedQuery, castedDoc, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Returns:

      All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

      + +

      Example

      + +
      Model.update({..}, { title: 'remove words' }, ...)
      + +

      becomes

      + +
      Model.update({..}, { $set: { title: 'remove words' }}, ...)
      + +

      Note

      + +

      Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


      Query#_castUpdate(obj)

      Casts obj for an update command.

      show code
      Query.prototype._castUpdate = function _castUpdate (obj) {
      +  var ops = Object.keys(obj)
      +    , i = ops.length
      +    , ret = {}
      +    , hasKeys
      +    , val
      +
      +  while (i--) {
      +    var op = ops[i];
      +    if ('$' !== op[0]) {
      +      // fix up $set sugar
      +      if (!ret.$set) {
      +        if (obj.$set) {
      +          ret.$set = obj.$set;
      +        } else {
      +          ret.$set = {};
      +        }
      +      }
      +      ret.$set[op] = obj[op];
      +      ops.splice(i, 1);
      +      if (!~ops.indexOf('$set')) ops.push('$set');
      +    } else if ('$set' === op) {
      +      if (!ret.$set) {
      +        ret[op] = obj[op];
      +      }
      +    } else {
      +      ret[op] = obj[op];
      +    }
      +  }
      +
      +  // cast each value
      +  i = ops.length;
      +
      +  while (i--) {
      +    op = ops[i];
      +    val = ret[op];
      +    if ('Object' === val.constructor.name) {
      +      hasKeys |= this._walkUpdatePath(val, op);
      +    } else {
      +      var msg = 'Invalid atomic update value for ' + op + '. '
      +              + 'Expected an object, received ' + typeof val;
      +      throw new Error(msg);
      +    }
      +  }
      +
      +  return hasKeys && ret;
      +}

      Parameters:

      Returns:

      • <Object> obj after casting its values

      Query#_walkUpdatePath(obj, op, pref)

      Walk each path of obj and cast its values
      according to its schema.

      show code
      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
      +  var strict = this.model.schema.options.strict
      +    , prefix = pref ? pref + '.' : ''
      +    , keys = Object.keys(obj)
      +    , i = keys.length
      +    , hasKeys = false
      +    , schema
      +    , key
      +    , val
      +
      +  while (i--) {
      +    key = keys[i];
      +    val = obj[key];
      +
      +    if (val && 'Object' === val.constructor.name) {
      +      // watch for embedded doc schemas
      +      schema = this._getSchema(prefix + key);
      +      if (schema && schema.caster && op in castOps) {
      +        // embedded doc schema
      +
      +        if (strict && !schema) {
      +          // path is not in our strict schema
      +          if ('throw' == strict) {
      +            throw new Error('Field `' + key + '` is not in schema.');
      +          } else {
      +            // ignore paths not specified in schema
      +            delete obj[key];
      +          }
      +        } else {
      +          hasKeys = true;
      +          if ('$each' in val) {
      +            obj[key] = {
      +                $each: this._castUpdateVal(schema, val.$each, op)
      +            }
      +          } else {
      +            obj[key] = this._castUpdateVal(schema, val, op);
      +          }
      +        }
      +      } else {
      +        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
      +      }
      +    } else {
      +      schema = '$each' === key
      +        ? this._getSchema(pref)
      +        : this._getSchema(prefix + key);
      +
      +      var skip = strict &&
      +                 !schema &&
      +                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
      +
      +      if (skip) {
      +        if ('throw' == strict) {
      +          throw new Error('Field `' + prefix + key + '` is not in schema.');
      +        } else {
      +          delete obj[key];
      +        }
      +      } else {
      +        hasKeys = true;
      +        obj[key] = this._castUpdateVal(schema, val, op, key);
      +      }
      +    }
      +  }
      +  return hasKeys;
      +}

      Parameters:

      • obj <Object> - part of a query
      • op <String> - the atomic operator ($pull, $set, etc)
      • pref <String> - path prefix (internal only)

      Returns:

      • <Bool> true if this path has keys to update

      Query#_castUpdateVal(schema, val, op, [$conditional])

      Casts val according to schema and atomic op.

      show code
      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
      +  if (!schema) {
      +    // non-existing schema path
      +    return op in numberOps
      +      ? Number(val)
      +      : val
      +  }
      +
      +  if (schema.caster && op in castOps &&
      +    ('Object' === val.constructor.name || Array.isArray(val))) {
      +    // Cast values for ops that add data to MongoDB.
      +    // Ensures embedded documents get ObjectIds etc.
      +    var tmp = schema.cast(val);
      +
      +    if (Array.isArray(val)) {
      +      val = tmp;
      +    } else {
      +      val = tmp[0];
      +    }
      +  }
      +
      +  if (op in numberOps) return Number(val);
      +  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
      +  return schema.castForQuery(val)
      +}

      Parameters:


      Query#_getSchema(path)

      Finds the schema for path. This is different than
      calling schema.path as it also resolves paths with
      positional selectors (something.$.another.$.path).

      show code
      Query.prototype._getSchema = function _getSchema (path) {
      +  var schema = this.model.schema
      +    , pathschema = schema.path(path);
      +
      +  if (pathschema)
      +    return pathschema;
      +
      +  // look for arrays
      +  return (function search (parts, schema) {
      +    var p = parts.length + 1
      +      , foundschema
      +      , trypath
      +
      +    while (p--) {
      +      trypath = parts.slice(0, p).join('.');
      +      foundschema = schema.path(trypath);
      +      if (foundschema) {
      +        if (foundschema.caster) {
      +
      +          // array of Mixed?
      +          if (foundschema.caster instanceof Types.Mixed) {
      +            return foundschema.caster;
      +          }
      +
      +          // Now that we found the array, we need to check if there
      +          // are remaining document paths to look up for casting.
      +          // Also we need to handle array.$.path since schema.path
      +          // doesn't work for that.
      +          if (p !== parts.length) {
      +            if ('$' === parts[p]) {
      +              // comments.$.comments.$.title
      +              return search(parts.slice(p+1), foundschema.schema);
      +            } else {
      +              // this is the last path of the selector
      +              return search(parts.slice(p), foundschema.schema);
      +            }
      +          }
      +        }
      +        return foundschema;
      +      }
      +    }
      +  })(path.split('.'), schema)
      +}

      Parameters:


      Query#remove(callback)

      Executes this query as a remove() operation.

      show code
      Query.prototype.remove = function (callback) {
      +  this.op = 'remove';
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , cb = 'function' == typeof callback
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    if (cb) return callback(err);
      +    throw err;
      +  }
      +
      +  if (!cb) {
      +    delete options.safe;
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.remove(castQuery, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Example

      + +
      Cassette.where('artist').equals('Anne Murray').remove(callback)

      Query#findOneAndUpdate([query], [doc], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
      +  this.op = 'findOneAndUpdate';
      +
      +  switch (arguments.length) {
      +    case 3:
      +      if ('function' == typeof options)
      +        callback = options, options = {};
      +      break;
      +    case 2:
      +      if ('function' == typeof doc) {
      +        callback = doc;
      +        doc = query;
      +        query = undefined;
      +      }
      +      options = undefined;
      +      break;
      +    case 1:
      +      if ('function' == typeof query) {
      +        callback = query;
      +        query = options = doc = undefined;
      +      } else {
      +        doc = query;
      +        query = options = undefined;
      +      }
      +  }
      +
      +  // apply query
      +  if (query) {
      +    if ('Object' === query.constructor.name) {
      +      merge(this._conditions, query);
      +    } else if (query instanceof Query) {
      +      merge(this._conditions, query._conditions);
      +    } else if (query instanceof Document) {
      +      merge(this._conditions, query.toObject());
      +    }
      +  }
      +
      +  // apply doc
      +  if (doc) {
      +    merge(this._updateArg, doc);
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('update', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      query.findOneAndUpdate(conditions, update, options, callback) // executes
      +query.findOneAndUpdate(conditions, update, options)  // returns Query
      +query.findOneAndUpdate(conditions, update, callback) // executes
      +query.findOneAndUpdate(conditions, update)           // returns Query
      +query.findOneAndUpdate(callback)                     // executes
      +query.findOneAndUpdate()                             // returns Query

      Query#findOneAndRemove([conditions], [options], [callback])

      Issues a mongodb findAndModify remove command.

      show code
      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
      +  this.op = 'findOneAndRemove';
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = undefined;
      +  }
      +
      +  // apply conditions
      +  if (conditions) {
      +    if ('Object' === conditions.constructor.name) {
      +      merge(this._conditions, conditions);
      +    } else if (conditions instanceof Query) {
      +      merge(this._conditions, conditions._conditions);
      +    } else if (conditions instanceof Document) {
      +      merge(this._conditions, conditions.toObject());
      +    }
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('remove', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      A.where().findOneAndRemove(conditions, options, callback) // executes
      +A.where().findOneAndRemove(conditions, options)  // return Query
      +A.where().findOneAndRemove(conditions, callback) // executes
      +A.where().findOneAndRemove(conditions) // returns Query
      +A.where().findOneAndRemove(callback)   // executes
      +A.where().findOneAndRemove()           // returns Query

      Query#_findAndModify(type, callback)

      _findAndModify

      show code
      Query.prototype._findAndModify = function (type, callback) {
      +  var model = this.model
      +    , promise = new Promise(callback)
      +    , self = this
      +    , castedQuery
      +    , castedDoc
      +    , fields
      +    , sort
      +    , opts
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    process.nextTick(promise.error.bind(promise, castedQuery));
      +    return promise;
      +  }
      +
      +  opts = this._optionsForExec(model);
      +
      +  if ('remove' == type) {
      +    opts.remove = true;
      +  } else {
      +    if (!('new' in opts)) opts.new = true;
      +    if (!('upsert' in opts)) opts.upsert = false;
      +
      +    castedDoc = castDoc(this);
      +    if (!castedDoc) {
      +      if (opts.upsert) {
      +        // still need to do the upsert to empty doc
      +        castedDoc = { $set: {} };
      +      } else {
      +        return this.findOne(callback);
      +      }
      +    } else if (castedDoc instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, castedDoc));
      +      return promise;
      +    }
      +  }
      +
      +  if (this._fields) {
      +    fields = utils.clone(opts.fields = this._fields);
      +  }
      +
      +  // the driver needs a default
      +  sort = opts.sort || [];
      +
      +  model
      +  .collection
      +  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === opts.lean) {
      +      return promise.complete(doc);
      +    }
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return promise;
      +}

      Parameters:


      Query#populate(path, [fields], [model], [conditions], [options])

      Specifies paths which should be populated with other documents.

      show code
      Query.prototype.populate = function (path, fields, model, conditions, options) {
      +  if ('string' !== typeof model) {
      +    options = conditions;
      +    conditions = model;
      +    model = undefined;
      +  }
      +  // The order of fields/conditions args is opposite Model.find but
      +  // necessary to keep backward compatibility (fields could be
      +  // an array, string, or object literal).
      +  this.options.populate[path] =
      +    new PopulateOptions(fields, conditions, options, model);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

      + +

      Example:

      + +
      Kitten.findOne().populate('owner').exec(function (err, kitten) {
      +  console.log(kitten.owner.name) // Max
      +})

      Query#stream()

      Returns a stream interface

      show code
      Query.prototype.stream = function stream () {
      +  return new QueryStream(this);
      +}
      +
      +// helpers

      Returns:

      Example

      + +
      // follows the nodejs stream api
      +Thing.find({ name: /^hello/ }).stream().pipe(res)
      +
      +// manual streaming
      +var stream = Thing.find({ name: /^hello/ }).stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});

      Query#within

      Syntax sugar for expressive queries.

      + +

      Example

      + +
      query.within.box()
      +query.within.center()

      Returns:


    • querystream.js

      QueryStream(query)

      Provides a ReadStream interface for Queries.

      show code
      function QueryStream (query) {
      +  Stream.call(this);
      +
      +  this.query = query;
      +  this.readable = true;
      +  this.paused = false;
      +  this._cursor = null;
      +  this._destroyed = null;
      +  this._fields = null;
      +  this._ticks = 0;
      +  this._inline = T_INIT;
      +
      +  // give time to hook up events
      +  var self = this;
      +  process.nextTick(function () {
      +    self._init();
      +  });
      +}

      Parameters:

      Inherits:

      Events:

      • data: emits a single Mongoose document

      • error: emits when an error occurs during streaming. This will emit before the close event.

      • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

      var stream = Model.find().stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});
      + +

      The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

      + +
      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

      QueryStream#_init()

      Initializes the query.

      show code
      QueryStream.prototype._init = function () {
      +  if (this._destroyed) return;
      +
      +  var query = this.query
      +    , model = query.model
      +    , options = query._optionsForExec(model)
      +    , self = this
      +
      +  try {
      +    query.cast(model);
      +  } catch (err) {
      +    return self.destroy(err);
      +  }
      +
      +  self._fields = utils.clone(options.fields = query._fields);
      +
      +  model.collection.find(query._conditions, options, function (err, cursor) {
      +    if (err) return self.destroy(err);
      +    self._cursor = cursor;
      +    self._next();
      +  });
      +}

      QueryStream#_next()

      Trampoline for pulling the next doc from cursor.

      show code
      QueryStream.prototype._next = function () {
      +  // avoid stack overflows with large result sets.
      +  // trampoline instead of recursion.
      +  var fn;
      +  while (fn = this.__next()) fn.call(this);
      +}

      QueryStream#__next()

      Pulls the next doc from the cursor.

      show code
      QueryStream.prototype.__next = function () {
      +  if (this.paused || this._destroyed) return;
      +
      +  var self = this;
      +  self._inline = T_INIT;
      +
      +  self._cursor.nextObject(function (err, doc) {
      +    self._onNextObject(err, doc);
      +  });
      +
      +  // if onNextObject() was already called in this tick
      +  // return ourselves to the trampoline.
      +  if (T_CONT === this._inline) {
      +    return this.__next;
      +  } else {
      +    // onNextObject() hasn't fired yet. tell onNextObject
      +    // that its ok to call _next b/c we are not within
      +    // the trampoline anymore.
      +    this._inline = T_IDLE;
      +  }
      +}

      QueryStream#_onNextObject(err, doc)

      Transforms raw docs returned from the cursor into a model instance.

      show code
      QueryStream.prototype._onNextObject = function (err, doc) {
      +  if (err) return this.destroy(err);
      +
      +  // when doc is null we hit the end of the cursor
      +  if (!doc) {
      +    return this.destroy();
      +  }
      +
      +  if (this.query.options && this.query.options.lean === true)  {
      +    this.emit('data', doc);
      +    this._next();
      +    return;
      +  }
      +
      +  var instance = new this.query.model(undefined, this._fields);
      +
      +  // skip _id for pre-init hooks
      +  delete instance._doc._id;
      +
      +  var self = this;
      +  instance.init(doc, this.query, function (err) {
      +    if (err) return self.destroy(err);
      +    self.emit('data', instance);
      +
      +    // trampoline management
      +    if (T_IDLE === self._inline) {
      +      // no longer in trampoline. restart it.
      +      self._next();
      +    } else
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      self._inline = T_CONT;
      +  });
      +}

      Parameters:


      QueryStream#pause()

      Pauses this stream.

      show code
      QueryStream.prototype.pause = function () {
      +  this.paused = true;
      +}

      QueryStream#resume()

      Resumes this stream.

      show code
      QueryStream.prototype.resume = function () {
      +  this.paused = false;
      +  this._next();
      +}

      QueryStream#destroy([err])

      Destroys the stream, closing the underlying cursor. No more events will be emitted.

      show code
      QueryStream.prototype.destroy = function (err) {
      +  if (this._destroyed) return;
      +  this._destroyed = true;
      +  this.readable = false;
      +
      +  if (this._cursor) {
      +    this._cursor.close();
      +  }
      +
      +  if (err) {
      +    this.emit('error', err);
      +  }
      +
      +  this.emit('close');
      +}

      Parameters:


      QueryStream#pipe()

      Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

      See:

      Example:

      + +
      query.stream().pipe(writeStream [, options])
      + +

      This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      + +
      var format = new ArrayFormatter;
      +Events.find().stream().pipe(format).pipe(res);
      + +

      As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


      QueryStream#paused

      Flag stating whether or not this stream is paused.


      QueryStream#readable

      Flag stating whether or not this stream is readable.


    • schema/array.js

      SchemaArray(key, cast, options)

      Array SchemaType constructor

      show code
      function SchemaArray (key, cast, options) {
      +  if (cast) {
      +    var castOptions = {};
      +
      +    if ('Object' === cast.constructor.name) {
      +      if (cast.type) {
      +        // support { type: Woot }
      +        castOptions = cast;
      +        cast = cast.type;
      +        delete castOptions.type;
      +      } else {
      +        cast = Mixed;
      +      }
      +    }
      +
      +    var caster = cast.name in Types ? Types[cast.name] : cast;
      +    this.casterConstructor = caster;
      +    this.caster = new caster(null, castOptions);
      +  }
      +
      +  SchemaType.call(this, key, options);
      +
      +  var self = this
      +    , defaultArr
      +    , fn;
      +
      +  if (this.defaultValue) {
      +    defaultArr = this.defaultValue;
      +    fn = 'function' == typeof defaultArr;
      +  }
      +
      +  this.default(function(){
      +    var arr = fn ? defaultArr() : defaultArr || [];
      +    return new MongooseArray(arr, self.path, this);
      +  });
      +};

      Parameters:

      Inherits:


      SchemaArray#checkRequired(value)

      Check required

      show code
      SchemaArray.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      Parameters:


      SchemaArray#applyGetters(value, scope)

      Overrides the getters application for the population special-case

      show code
      SchemaArray.prototype.applyGetters = function (value, scope) {
      +  if (this.caster.options && this.caster.options.ref) {
      +    // means the object id was populated
      +    return value;
      +  }
      +
      +  return SchemaType.prototype.applyGetters.call(this, value, scope);
      +};

      Parameters:


      SchemaArray#cast(value, doc, init)

      Casts contents

      show code
      SchemaArray.prototype.cast = function (value, doc, init) {
      +  if (Array.isArray(value)) {
      +    if (!(value instanceof MongooseArray)) {
      +      value = new MongooseArray(value, this.path, doc);
      +    }
      +
      +    if (this.caster) {
      +      try {
      +        for (var i = 0, l = value.length; i < l; i++) {
      +          value[i] = this.caster.cast(value[i], doc, init);
      +        }
      +      } catch (e) {
      +        // rethrow
      +        throw new CastError(e.type, value);
      +      }
      +    }
      +
      +    return value;
      +  } else {
      +    return this.cast([value], doc, init);
      +  }
      +};

      Parameters:

      • value <Object>
      • doc <Document> document that triggers the casting
      • init <Boolean> whether this is an initialization cast

      SchemaArray#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaArray.prototype.castForQuery = function ($conditional, value) {
      +  var handler
      +    , val;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Array.");
      +    val = handler.call(this, value);
      +  } else {
      +    val = $conditional;
      +    var proto = this.casterConstructor.prototype;
      +    var method = proto.castForQuery || proto.cast;
      +    if (Array.isArray(val)) {
      +      val = val.map(function (v) {
      +        if (method) v = method.call(proto, v);
      +        return isMongooseObject(v)
      +          ? v.toObject()
      +          : v;
      +      });
      +    } else if (method) {
      +      val = method.call(proto, val);
      +    }
      +  }
      +  return val && isMongooseObject(val)
      +    ? val.toObject()
      +    : val;
      +};

      Parameters:


    • schema/boolean.js

      SchemaBoolean(path, options)

      Boolean SchemaType constructor.

      show code
      function SchemaBoolean (path, options) {
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      SchemaBoolean#checkRequired()

      Required validator

      show code
      SchemaBoolean.prototype.checkRequired = function (value) {
      +  return value === true || value === false;
      +};

      SchemaBoolean#cast(value)

      Casts to boolean

      show code
      SchemaBoolean.prototype.cast = function (value) {
      +  if (value === null) return value;
      +  if (value === '0') return false;
      +  return !!value;
      +};

      Parameters:


      SchemaBoolean#castForQuery($conditional, val)

      Casts contents for queries.

      show code
      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (2 === arguments.length) {
      +    handler = SchemaBoolean.$conditionalHandlers[$conditional];
      +
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Boolean.");
      +
      +    return handler.call(this, val);
      +  }
      +
      +  return this.cast($conditional);
      +};

      Parameters:


    • schema/buffer.js

      SchemaBuffer(key, cast)

      Buffer SchemaType constructor

      show code
      function SchemaBuffer (key, options) {
      +  SchemaType.call(this, key, options, 'Buffer');
      +};

      Parameters:

      Inherits:


      SchemaBuffer#checkRequired()

      Check required

      show code
      SchemaBuffer.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      SchemaBuffer#cast(value, doc, init)

      Casts contents

      show code
      SchemaBuffer.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (Buffer.isBuffer(value)) {
      +    if (!(value instanceof MongooseBuffer)) {
      +      value = new MongooseBuffer(value, [this.path, doc]);
      +    }
      +
      +    return value;
      +  } else if (value instanceof Binary) {
      +    return new MongooseBuffer(value.value(true), [this.path, doc]);
      +  }
      +
      +  if ('string' === typeof value || Array.isArray(value)) {
      +    return new MongooseBuffer(value, [this.path, doc]);
      +  }
      +
      +  throw new CastError('buffer', value);
      +};

      Parameters:


      SchemaBuffer#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Buffer.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    return this.cast(val).toObject();
      +  }
      +};

      Parameters:


    • schema/date.js

      SchemaDate(key, options)

      Date SchemaType constructor.

      show code
      function SchemaDate (key, options) {
      +  SchemaType.call(this, key, options);
      +};

      Parameters:

      Inherits:


      SchemaDate#checkRequired()

      Required validator for date

      show code
      SchemaDate.prototype.checkRequired = function (value) {
      +  return value instanceof Date;
      +};

      SchemaDate#cast(value)

      Casts to date

      show code
      SchemaDate.prototype.cast = function (value) {
      +  if (value === null || value === '')
      +    return null;
      +
      +  if (value instanceof Date)
      +    return value;
      +
      +  var date;
      +
      +  // support for timestamps
      +  if (value instanceof Number || 'number' == typeof value 
      +      || String(value) == Number(value))
      +    date = new Date(Number(value));
      +
      +  // support for date strings
      +  else if (value.toString)
      +    date = new Date(value.toString());
      +
      +  if (date.toString() != 'Invalid Date')
      +    return date;
      +
      +  throw new CastError('date', value);
      +};

      Parameters:


      SchemaDate#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaDate.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +
      +  if (2 !== arguments.length) {
      +    return this.cast($conditional);
      +  }
      +
      +  handler = this.$conditionalHandlers[$conditional];
      +
      +  if (!handler) {
      +    throw new Error("Can't use " + $conditional + " with Date.");
      +  }
      +
      +  return handler.call(this, val);
      +};

      Parameters:


    • schema/documentarray.js

      DocumentArray(key, schema, options)

      SubdocsArray SchemaType constructor

      show code
      function DocumentArray (key, schema, options) {
      +  // compile an embedded document for this schema
      +  // TODO Move this into parent model compilation for performance improvement?
      +  function EmbeddedDocument () {
      +    Subdocument.apply(this, arguments);
      +  };
      +
      +  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
      +  EmbeddedDocument.prototype._setSchema(schema);
      +  EmbeddedDocument.schema = schema;
      +
      +  // apply methods
      +  for (var i in schema.methods) {
      +    EmbeddedDocument.prototype[i] = schema.methods[i];
      +  }
      +
      +  // apply statics
      +  for (var i in schema.statics)
      +    EmbeddedDocument[i] = schema.statics[i];
      +
      +  EmbeddedDocument.options = options;
      +  this.schema = schema;
      +
      +  ArrayType.call(this, key, EmbeddedDocument, options);
      +
      +  this.schema = schema;
      +  var path = this.path;
      +  var fn = this.defaultValue;
      +
      +  this.default(function(){
      +    var arr = fn.call(this);
      +    if (!Array.isArray(arr)) arr = [arr];
      +    return new MongooseDocumentArray(arr, path, this);
      +  });
      +};

      Parameters:

      Inherits:


      DocumentArray#doValidate()

      Performs local validations first, then validations on each embedded doc

      show code
      DocumentArray.prototype.doValidate = function (array, fn, scope) {
      +  var self = this;
      +  SchemaType.prototype.doValidate.call(this, array, function(err){
      +    if (err) return fn(err);
      +
      +    var count = array && array.length
      +      , error = false;
      +
      +    if (!count) return fn();
      +
      +    array.forEach(function(doc, index){
      +      doc.validate(function(err){
      +        if (err && !error){
      +          // rewrite they key
      +          err.key = self.key + '.' + index + '.' + err.key;
      +          fn(err);
      +          error = true;
      +        } else {
      +          --count || fn();
      +        }
      +      });
      +    });
      +  }, scope);
      +};

      DocumentArray#cast(value, document)

      Casts contents

      show code
      DocumentArray.prototype.cast = function (value, doc, init, prev) {
      +  var subdoc
      +    , i
      +
      +  if (Array.isArray(value)) {
      +    if (!(value instanceof MongooseDocumentArray)) {
      +      value = new MongooseDocumentArray(value, this.path, doc);
      +    }
      +
      +    i = value.length;
      +
      +    while (i--) {
      +      if (!(value[i] instanceof Subdocument)) {
      +        if (init) {
      +          subdoc = new this.casterConstructor(null, value, true);
      +          value[i] = subdoc.init(value[i]);
      +        } else {
      +          if (prev && (subdoc = prev.id(value[i]._id))) {
      +            // handle resetting doc with existing id but differing data
      +            // doc.array = [{ doc: 'val' }]
      +            subdoc.set(value[i]);
      +          } else {
      +            subdoc = new this.casterConstructor(value[i], value);
      +          }
      +
      +          // if set() is hooked it will have no return value
      +          // see gh-746
      +          value[i] = subdoc;
      +        }
      +      }
      +    }
      +
      +    return value;
      +  } else {
      +    return this.cast([value], doc, init, prev);
      +  }
      +
      +  throw new CastError('documentarray', value);
      +};

      Parameters:


    • schema/mixed.js

      Mixed(path, options)

      Mixed SchemaType constructor.

      show code
      function Mixed (path, options) {
      +  // make sure empty array defaults are handled
      +  if (options &&
      +      options.default &&
      +      Array.isArray(options.default) &&
      +      0 === options.default.length) {
      +    options.default = Array;
      +  }
      +
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      Mixed#checkRequired()

      Required validator

      show code
      Mixed.prototype.checkRequired = function (val) {
      +  return true;
      +};

      Mixed#cast(value)

      Casts val for Mixed.

      show code
      Mixed.prototype.cast = function (val) {
      +  return val;
      +};

      Parameters:

      this is a no-op


      Mixed#castForQuery($cond, [val])

      Casts contents for queries.

      show code
      Mixed.prototype.castForQuery = function ($cond, val) {
      +  if (arguments.length === 2) return val;
      +  return $cond;
      +};

      Parameters:


    • schema/number.js

      SchemaNumber(key, options)

      Number SchemaType constructor.

      show code
      function SchemaNumber (key, options) {
      +  SchemaType.call(this, key, options, 'Number');
      +};

      Parameters:

      Inherits:


      SchemaNumber#checkRequired()

      Required validator for number

      show code
      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return typeof value == 'number' || value instanceof Number;
      +  }
      +};

      SchemaNumber#min(value, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.min = function (value, message) {
      +  if (this.minValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'min';
      +    });
      +  if (value != null)
      +    this.validators.push([function(v){
      +      return v === null || v >= value;
      +    }, 'min']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, min: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 9 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#max(maximum, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.max = function (value, message) {
      +  if (this.maxValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'max';
      +    });
      +  if (value != null)
      +    this.validators.push([this.maxValidator = function(v){
      +      return v === null || v <= value;
      +    }, 'max']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, max: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 11 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#cast(value, doc, init)

      Casts to number

      show code
      SchemaNumber.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (!isNaN(value)){
      +    if (null === value) return value;
      +    if ('' === value) return null;
      +    if ('string' == typeof value) value = Number(value);
      +    if (value instanceof Number) return value
      +    if ('number' == typeof value) return value;
      +    if (value.toString && !Array.isArray(value) &&
      +        value.toString() == Number(value)) {
      +      return new Number(value)
      +    }
      +  }
      +
      +  throw new CastError('number', value);
      +};

      Parameters:


      SchemaNumber#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Number.");
      +    return handler.call(this, val);
      +  } else {
      +    val = this.cast($conditional);
      +    return val == null ? val : val
      +  }
      +};

      Parameters:


    • schema/objectid.js

      ObjectId(key, options)

      ObjectId SchemaType constructor.

      show code
      function ObjectId (key, options) {
      +  SchemaType.call(this, key, options, 'ObjectID');
      +};

      Parameters:

      Inherits:


      ObjectId#checkRequired()

      Check required

      show code
      ObjectId.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return value instanceof oid;
      +  }
      +};

      ObjectId#cast(value, scope, init)

      Casts to ObjectId

      show code
      ObjectId.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (value === null) return value;
      +
      +  if (value instanceof oid)
      +    return value;
      +
      +  if (value._id && value._id instanceof oid)
      +    return value._id;
      +
      +  if (value.toString)
      +    return oid.fromString(value.toString());
      +
      +  throw new CastError('object id', value);
      +};

      Parameters:


      ObjectId#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      ObjectId.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with ObjectId.");
      +    return handler.call(this, val);
      +  } else {
      +    return this.cast($conditional);
      +  }
      +};

      Parameters:


      ObjectId#auto(turnOn)

      Adds an auto-generated ObjectId default if turnOn is true.

      show code
      ObjectId.prototype.auto = function (turnOn) {
      +  if (turnOn) {
      +    this.default(defaultId);
      +    this.set(resetId)
      +  }
      +};

      Parameters:

      • turnOn <Boolean> auto generated ObjectId defaults

    • schema/string.js

      SchemaString(key, options)

      String SchemaType constructor.

      show code
      function SchemaString (key, options) {
      +  this.enumValues = [];
      +  this.regExp = null;
      +  SchemaType.call(this, key, options, 'String');
      +};

      Parameters:

      Inherits:


      SchemaString#enum([args...])

      Adds enumeration values and a coinciding validator.

      show code
      SchemaString.prototype.enum = function () {
      +  var len = arguments.length;
      +  if (!len || undefined === arguments[0] || false === arguments[0]) {
      +    if (this.enumValidator){
      +      this.enumValidator = false;
      +      this.validators = this.validators.filter(function(v){
      +        return v[1] != 'enum';
      +      });
      +    }
      +    return;
      +  }
      +
      +  for (var i = 0; i < len; i++) {
      +    if (undefined !== arguments[i]) {
      +      this.enumValues.push(this.cast(arguments[i]));
      +    }
      +  }
      +
      +  if (!this.enumValidator) {
      +    var values = this.enumValues;
      +    this.enumValidator = function(v){
      +      return undefined === v || ~values.indexOf(v);
      +    };
      +    this.validators.push([this.enumValidator, 'enum']);
      +  }
      +};

      Parameters:

      • [args...] <String> enumeration values

      Example:

      + +
      var states = 'opening open closing closed'.split(' ')
      +var s = new Schema({ state: { type: String, enum: states })
      +var M = db.model('M', s)
      +var m = new M({ state: 'invalid' })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.state = 'open'
      +  m.save() // success
      +})

      SchemaString#lowercase()

      Adds a lowercase setter.

      show code
      SchemaString.prototype.lowercase = function () {
      +  return this.set(function (v) {
      +    return v.toLowerCase();
      +  });
      +};

      Example:

      + +
      var s = new Schema({ email: { type: String, lowercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ email: 'SomeEmail@example.COM' });
      +console.log(m.email) // someemail@example.com
      +

      SchemaString#uppercase()

      Adds an uppercase setter.

      show code
      SchemaString.prototype.uppercase = function () {
      +  return this.set(function (v) {
      +    return v.toUpperCase();
      +  });
      +};

      Example:

      + +
      var s = new Schema({ caps: { type: String, uppercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ caps: 'an example' });
      +console.log(m.caps) // AN EXAMPLE

      SchemaString#trim()

      Adds a trim setter.

      show code
      SchemaString.prototype.trim = function () {
      +  return this.set(function (v) {
      +    return v.trim();
      +  });
      +};

      The string value will be trimmed when set.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, trim: true }})
      +var M = db.model('M', s)
      +var string = ' some name '
      +console.log(string.length) // 11
      +var m = new M({ name: string })
      +console.log(m.name.length) // 9

      SchemaString#match(regExp)

      Sets a regexp validator.

      show code
      SchemaString.prototype.match = function match (regExp) {
      +  this.validators.push([function(v){
      +    return null != v && '' !== v
      +      ? regExp.test(v)
      +      : true
      +  }, 'regexp']);
      +};

      Parameters:

      • regExp <RegExp> regular expression to test against

      Any value that does not pass regExp.test(val) will fail validation.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, match: /^a/ }})
      +var M = db.model('M', s)
      +var m = new M({ name: 'invalid' })
      +m.validate(function (err) {
      +  console.error(err) // validation error
      +  m.name = 'apples'
      +  m.validate(function (err) {
      +    assert.ok(err) // success
      +  })
      +})

      SchemaString#checkRequired(value)

      Check required

      show code
      SchemaString.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return (value instanceof String || typeof value == 'string') && value.length;
      +  }
      +};

      Parameters:


      SchemaString#cast()

      Casts to String

      show code
      SchemaString.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +  if (value === null) return value;
      +  if ('undefined' !== typeof value && value.toString) return value.toString();
      +  throw new CastError('string', value);
      +};

      SchemaString#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      SchemaString.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with String.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    if (val instanceof RegExp) return val;
      +    return this.cast(val);
      +  }
      +};

      Parameters:


    • schema.js

      Schema(definition)

      Schema constructor.

      show code
      function Schema (obj, options) {
      +  if (!(this instanceof Schema))
      +    return new Schema(obj, options);
      +
      +  this.paths = {};
      +  this.subpaths = {};
      +  this.virtuals = {};
      +  this.nested = {};
      +  this.inherits = {};
      +  this.callQueue = [];
      +  this._indexes = [];
      +  this.methods = {};
      +  this.statics = {};
      +  this.tree = {};
      +  this._requiredpaths = undefined;
      +
      +  // set options
      +  this.options = utils.options({
      +      safe: true
      +    , strict: true
      +    , capped: false // { size, max, autoIndexId }
      +    , versionKey: '__v'
      +    , minimize: true
      +    , autoIndex: true
      +    , shardKey: null
      +    // the following are only applied at construction time
      +    , noId: false // deprecated, use { _id: false }
      +    , _id: true
      +    , noVirtualId: false // deprecated, use { id: false }
      +    , id: true
      +  }, options);
      +
      +  // build paths
      +  if (obj) {
      +    this.add(obj);
      +  }
      +
      +  // ensure the documents get an auto _id unless disabled
      +  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
      +  if (auto_id) {
      +    this.add({ _id: {type: Schema.ObjectId, auto: true} });
      +  }
      +
      +  // ensure the documents receive an id getter unless disabled
      +  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
      +  if (autoid) {
      +    this.virtual('id').get(idGetter);
      +  }
      +
      +  // versioning not directly added to schema b/c we only want
      +  // it in the top level document, not embedded ones.
      +};

      Parameters:

      Events:

      • init: Emitted after the schema is compiled into a Model.

      Example:

      + +
      var child = new Schema({ name: String });
      +var schema = new Schema({ name: String, age: Number, children: [child] });
      +var Tree = mongoose.model('Tree', schema);
      +
      +// setting schema options
      +new Schema({ name: String }, { _id: false, autoIndex: false })
      + +

      Options:

      + +
        +
      • safe: bool - defaults to true.
      • +
      • strict: bool - defaults to true
      • +
      • capped: bool - defaults to false
      • +
      • versionKey: bool - defaults to "__v"
      • +
      • shardKey: bool - defaults to null
      • +
      • autoIndex: bool - defaults to true
      • +
      • _id: bool - defaults to true
      • +
      • id: bool - defaults to true
      • +
      • minimize: bool - controls document#toObject behavior when called manually - defaults to true
      • +
      + +

      Note:

      + +

      When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


      Schema#add(obj, prefix)

      Adds key path / schema type pairs to this schema.

      show code
      Schema.prototype.add = function add (obj, prefix) {
      +  prefix = prefix || '';
      +  for (var i in obj) {
      +    if (null == obj[i]) {
      +      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
      +    }
      +
      +    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
      +      if (Object.keys(obj[i]).length) {
      +        // nested object { last: { name: String }}
      +        this.nested[prefix + i] = true;
      +        this.add(obj[i], prefix + i + '.');
      +      }
      +      else
      +        this.path(prefix + i, obj[i]); // mixed type
      +    } else
      +      this.path(prefix + i, obj[i]);
      +  }
      +};

      Parameters:

      Example:

      + +
      var ToySchema = new Schema;
      +ToySchema.add({ name: 'string', color: 'string', price: 'number' });

      Schema#path(path, constructor)

      Gets/sets schema paths.

      show code
      Schema.prototype.path = function (path, obj) {
      +  if (obj == undefined) {
      +    if (this.paths[path]) return this.paths[path];
      +    if (this.subpaths[path]) return this.subpaths[path];
      +
      +    // subpaths?
      +    return /\.\d+\.?$/.test(path)
      +      ? getPositionalPath(this, path)
      +      : undefined;
      +  }
      +
      +  // some path names conflict with document methods
      +  if (reserved[path]) {
      +    throw new Error("`" + path + "` may not be used as a schema pathname");
      +  }
      +
      +  // update the tree
      +  var subpaths = path.split(/\./)
      +    , last = subpaths.pop()
      +    , branch = this.tree;
      +
      +  subpaths.forEach(function(path) {
      +    if (!branch[path]) branch[path] = {};
      +    branch = branch[path];
      +  });
      +
      +  branch[last] = utils.clone(obj);
      +
      +  this.paths[path] = Schema.interpretAsType(path, obj);
      +  return this;
      +};

      Parameters:

      Sets a path (if arity 2)
      Gets a path (if arity 1)

      + +

      Example

      + +
      schema.path('name') // returns a SchemaType
      +schema.path('name', Number) // changes the schemaType of `name` to Number

      Schema#eachPath(fn)

      Iterates the schemas paths similar to Array#forEach.

      show code
      Schema.prototype.eachPath = function (fn) {
      +  var keys = Object.keys(this.paths)
      +    , len = keys.length;
      +
      +  for (var i = 0; i < len; ++i) {
      +    fn(keys[i], this.paths[keys[i]]);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      The callback is passed the pathname and schemaType as arguments on each iteration.


      Schema#requiredPaths()

      Returns an Array of path strings that are required by this schema.

      show code
      Schema.prototype.requiredPaths = function requiredPaths () {
      +  if (this._requiredpaths) return this._requiredpaths;
      +
      +  var paths = Object.keys(this.paths)
      +    , i = paths.length
      +    , ret = [];
      +
      +  while (i--) {
      +    var path = paths[i];
      +    if (this.paths[path].isRequired) ret.push(path);
      +  }
      +
      +  return this._requiredpaths = ret;
      +}

      Returns:


      Schema#pathType(path)

      Returns the pathType of path for this schema.

      show code
      Schema.prototype.pathType = function (path) {
      +  if (path in this.paths) return 'real';
      +  if (path in this.virtuals) return 'virtual';
      +  if (path in this.nested) return 'nested';
      +  if (path in this.subpaths) return 'real';
      +
      +  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
      +    return 'real';
      +  } else {
      +    return 'adhocOrUndefined'
      +  }
      +};

      Parameters:

      Returns:

      Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


      Schema#queue(name, args)

      Adds a method call to the queue.

      show code
      Schema.prototype.queue = function(name, args){
      +  this.callQueue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the document method to call later
      • args <Array> arguments to pass to the method

      Schema#pre(method, callback)

      Defines a pre hook for the document.

      show code
      Schema.prototype.pre = function(){
      +  return this.queue('pre', arguments);
      +};

      Parameters:

      Example

      + +
      var toySchema = new Schema(..);
      +
      +toySchema.pre('save', function (next) {
      +  if (!this.created) this.created = new Date;
      +  next();
      +})
      +
      +toySchema.pre('validate', function (next) {
      +  if (this.name != 'Woody') this.name = 'Woody';
      +  next();
      +})

      Schema#post(method, fn)

      Defines a post hook for the document.

      show code
      Schema.prototype.post = function(method, fn){
      +  return this.queue('on', arguments);
      +};

      Parameters:

      Post hooks fire on the event emitted from document instances of Models compiled from this schema.

      + +
      var schema = new Schema(..);
      +schema.post('save', function () {
      +  console.log('this fired after a document was saved');
      +});
      +
      +var Model = mongoose.model('Model', schema);
      +
      +var m = new Model(..);
      +m.save(function (err) {
      +  console.log('this fires after the `post` hook');
      +});

      Schema#plugin(plugin, opts)

      Registers a plugin for this schema.

      show code
      Schema.prototype.plugin = function (fn, opts) {
      +  fn(this, opts);
      +  return this;
      +};

      Parameters:


      Schema#method(method, [fn])

      Adds an instance method to documents constructed from Models compiled from this schema.

      show code
      Schema.prototype.method = function (name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.methods[i] = name[i];
      +  else
      +    this.methods[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = kittySchema = new Schema(..);
      +
      +schema.methods.meow = function () {
      +  console.log('meeeeeoooooooooooow');
      +})
      +
      +var Kitty = mongoose.model('Kitty', schema);
      +
      +var fizz = new Kitty;
      +fizz.meow(); // meeeeeooooooooooooow
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      + +
      schema.method({
      +    purr: function () {}
      +  , scratch: function () {}
      +});
      +
      +// later
      +fizz.purr();
      +fizz.scratch();

      Schema#static(name, fn)

      Adds static "class" methods to Models compiled from this schema.

      show code
      Schema.prototype.static = function(name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.statics[i] = name[i];
      +  else
      +    this.statics[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = new Schema(..);
      +schema.static('findByName', function (name, callback) {
      +  return this.find({ name: name }, callback);
      +});
      +
      +var Drink = mongoose.model('Drink', schema);
      +Drink.findByName('sanpellegrino', function (err, drinks) {
      +  //
      +});
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


      Schema#index(fields, [options])

      Defines an index (most likely compound) for this schema.

      show code
      Schema.prototype.index = function (fields, options) {
      +  options || (options = {});
      +
      +  if (options.expires)
      +    utils.expires(options);
      +
      +  this._indexes.push([fields, options]);
      +  return this;
      +};

      Parameters:

      Example

      + +
      schema.index({ first: 1, last: -1 })

      Schema#set(key, [value])

      Sets/gets a schema option.

      show code
      Schema.prototype.set = function (key, value) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +  this.options[key] = value;
      +  return this;
      +};

      Parameters:

      • key <String> option name
      • [value] <Object> if not passed, the current option value is returned

      Schema#indexes()

      Compiles indexes from fields and schema-level indexes

      show code
      Schema.prototype.indexes = function () {
      +  var indexes = []
      +    , seenSchemas = [];
      +
      +  collectIndexes(this);
      +
      +  return indexes;
      +
      +  function collectIndexes (schema, prefix) {
      +    if (~seenSchemas.indexOf(schema)) return;
      +    seenSchemas.push(schema);
      +
      +    var index;
      +    var paths = schema.paths;
      +    prefix = prefix || '';
      +
      +    for (var i in paths) {
      +      if (paths[i]) {
      +        if (paths[i] instanceof Types.DocumentArray) {
      +          collectIndexes(paths[i].schema, i + '.');
      +        } else {
      +          index = paths[i]._index;
      +
      +          if (index !== false && index !== null){
      +            var field = {};
      +            field[prefix + i] = '2d' === index ? index : 1;
      +            var options = 'Object' === index.constructor.name ? index : {};
      +            if (!('background' in options)) options.background = true;
      +            indexes.push([field, options]);
      +          }
      +        }
      +      }
      +    }
      +
      +    if (prefix) {
      +      fixSubIndexPaths(schema, prefix);
      +    } else {
      +      schema._indexes.forEach(function (index) {
      +        if (!('background' in index[1])) index[1].background = true;
      +      });
      +      indexes = indexes.concat(schema._indexes);
      +    }
      +  }

      Schema#virtual(name, [options])

      Creates a virtual type with the given name.

      show code
      Schema.prototype.virtual = function (name, options) {
      +  var virtuals = this.virtuals;
      +  var parts = name.split('.');
      +  return virtuals[name] = parts.reduce(function (mem, part, i) {
      +    mem[part] || (mem[part] = (i === parts.length-1)
      +                            ? new VirtualType(options)
      +                            : {});
      +    return mem[part];
      +  }, this.tree);
      +};

      Parameters:

      Returns:


      Schema#virtualpath(name)

      Returns the virtual type with the given name.

      show code
      Schema.prototype.virtualpath = function (name) {
      +  return this.virtuals[name];
      +};

      Parameters:

      Returns:


      Schema#namedScope()

      These still haven't been fixed. Once they're working we'll make them public again.

      show code
      Schema.prototype.namedScope = function (name, fn) {
      +  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
      +    , newScope = Object.create(namedScopes)
      +    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
      +  allScopes[name] = newScope;
      +  newScope.name = name;
      +  newScope.block = fn;
      +  newScope.query = new Query();
      +  newScope.decorate(namedScopes, {
      +    block0: function (block) {
      +      return function () {
      +        block.call(this.query);
      +        return this;
      +      };
      +    },
      +    blockN: function (block) {
      +      return function () {
      +        block.apply(this.query, arguments);
      +        return this;
      +      };
      +    },
      +    basic: function (query) {
      +      return function () {
      +        this.query.find(query);
      +        return this;
      +      };
      +    }
      +  });
      +  return newScope;
      +};

      Schema.reserved

      Reserved document keys.

      show code
      Schema.reserved = Object.create(null);
      +var reserved = Schema.reserved;
      +reserved.on =
      +reserved.db =
      +reserved.init =
      +reserved.isNew =
      +reserved.errors =
      +reserved.schema =
      +reserved.options =
      +reserved.modelName =
      +reserved.collection = 1;

      Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      + +
      on, db, init, isNew, errors, schema, options, modelName, collection

      Schema.interpretAsType(path, obj)

      Converts type arguments into Mongoose Types.

      show code
      Schema.interpretAsType = function (path, obj) {
      +  if (obj.constructor.name != 'Object')
      +    obj = { type: obj };
      +
      +  // Get the type making sure to allow keys named "type"
      +  // and default to mixed if not specified.
      +  // { type: { type: String, default: 'freshcut' } }
      +  var type = obj.type && !obj.type.type
      +    ? obj.type
      +    : {};
      +
      +  if ('Object' == type.constructor.name || 'mixed' == type) {
      +    return new Types.Mixed(path, obj);
      +  }
      +
      +  if (Array.isArray(type) || Array == type || 'array' == type) {
      +    // if it was specified through { type } look for `cast`
      +    var cast = (Array == type || 'array' == type)
      +      ? obj.cast
      +      : type[0];
      +
      +    if (cast instanceof Schema) {
      +      return new Types.DocumentArray(path, cast, obj);
      +    }
      +
      +    if ('string' == typeof cast) {
      +      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
      +    } else if (cast && (!cast.type || cast.type.type)
      +                    && 'Object' == cast.constructor.name
      +                    && Object.keys(cast).length) {
      +      return new Types.DocumentArray(path, new Schema(cast), obj);
      +    }
      +
      +    return new Types.Array(path, cast || Types.Mixed, obj);
      +  }
      +
      +  var name = 'string' == typeof type
      +    ? type
      +    : type.name;
      +
      +  if (name) {
      +    name = name.charAt(0).toUpperCase() + name.substring(1);
      +  }
      +
      +  if (undefined == Types[name]) {
      +    throw new TypeError('Undefined type at `' + path +
      +        '`
      +  Did you try nesting Schemas? ' +
      +        'You can only nest using refs or arrays.');
      +  }
      +
      +  return new Types[name](path, obj);
      +};

      Parameters:


      Schema.Types

      The various Mongoose Schema Types.

      show code
      Schema.Types = require('./schema/index');

      Example:

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var ObjectId = mongoose.Schema.Types.ObjectId;
      + +

      Types:

      + +
        +
      • String
      • +
      • Number
      • +
      • Boolean | Bool
      • +
      • Array
      • +
      • Buffer
      • +
      • Date
      • +
      • ObjectId | Oid
      • +
      • Mixed
      • +
      + +

      Using this exposed access to the Mixed SchemaType, we can use them in our schema.

      + +
      var Mixed = mongoose.Schema.Types.Mixed;
      +new mongoose.Schema({ _user: Mixed })

      Schema#tree

      Schema as a tree

      + +

      Example:

      + +
      {
      +    '_id'     : ObjectId
      +  , 'nested'  : {
      +        'key' : String
      +    }
      +}

      Schema#paths

      Schema as flat paths

      + +

      Example:

      + +
      {
      +    '_id'        : SchemaType,
      +  , 'nested.key' : SchemaType,
      +}

    • schemadefault.js

      exports#system.profile

      Default model for querying the system.profiles collection.


    • schematype.js

      SchemaType(path, [options], [instance])

      SchemaType constructor

      show code
      function SchemaType (path, options, instance) {
      +  this.path = path;
      +  this.instance = instance;
      +  this.validators = [];
      +  this.setters = [];
      +  this.getters = [];
      +  this.options = options;
      +  this._index = null;
      +  this.selected;
      +
      +  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
      +    // { unique: true, index: true }
      +    if ('index' == i && this._index) continue;
      +
      +    var opts = Array.isArray(options[i])
      +      ? options[i]
      +      : [options[i]];
      +
      +    this[i].apply(this, opts);
      +  }
      +};

      Parameters:


      SchemaType#default(val)

      Sets a default value for this SchemaType.

      show code
      SchemaType.prototype.default = function (val) {
      +  if (1 === arguments.length) {
      +    this.defaultValue = typeof val === 'function'
      +      ? val
      +      : this.cast(val);
      +    return this;
      +  } else if (arguments.length > 1) {
      +    this.defaultValue = utils.args(arguments);
      +  }
      +  return this.defaultValue;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var schema = new Schema({ n: { type: Number, default: 10 })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.n) // 10
      + +

      Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

      + +

      Example:

      + +
      // values are cast:
      +var schema = new Schema({ aNumber: Number, default: "4.815162342" })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.aNumber) // 4.815162342
      +
      +// default unique objects for Mixed types:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default(function () {
      +  return {};
      +});
      +
      +// if we don't use a function to return object literals for Mixed defaults,
      +// each document will receive a reference to the same object literal creating
      +// a "shared" object instance:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default({});
      +var M = db.model('M', schema);
      +var m1 = new M;
      +m1.mixed.added = 1;
      +console.log(m1.mixed); // { added: 1 }
      +var m2 = new M;
      +console.log(m2.mixed); // { added: 1 }

      SchemaType#index(options)

      Declares the index options for this schematype.

      show code
      SchemaType.prototype.index = function (options) {
      +  this._index = options;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var s = new Schema({ name: { type: String, index: true })
      +var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
      +Schema.path('my.path').index(true);
      +Schema.path('my.path').index({ expires: 60 });
      +Schema.path('my.path').index({ unique: true, sparse: true });
      + +

      NOTE:

      + +

      Indexes are created in the background by default. Specify background: false to override.

      + +

      Direction doesn't matter for single key indexes


      SchemaType#unique(bool)

      Declares an unique index.

      show code
      SchemaType.prototype.unique = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.unique = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, unique: true })
      +Schema.path('name').index({ unique: true });

      SchemaType#sparse(bool)

      Declares a sparse index.

      show code
      SchemaType.prototype.sparse = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.sparse = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, sparse: true })
      +Schema.path('name').index({ sparse: true });

      SchemaType#expires(when)

      Declares a TTL index (rounded to the nearest second) for Date types only.

      show code
      SchemaType.prototype.expires = function (when) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.expires = when;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
      This index type is only compatible with Date types.

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({..}, { expires: 60*60*24 });
      + +

      expires utilizes the ms module from guille allowing us to use a friendlier syntax:

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({..}, { expires: '24h' });
      +
      +// expire in 1.5 hours
      +new Schema({..}, { expires: '1.5h' });
      +
      +// expire in 7 days
      +var schema = new Schema({..});
      +schema.expires('7d');

      SchemaType#set(fn)

      Adds a setter to this schematype.

      show code
      SchemaType.prototype.set = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A setter must be a function.');
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function capitalize (val) {
      +  if ('string' != typeof val) val = '';
      +  return val.charAt(0).toUpperCase() + val.substring(1);
      +}
      +
      +var s = new Schema({ name: { type: String, set: capitalize })
      +// or
      +Schema.path('name').set(capitalize);

      SchemaType#get(fn)

      Adds a getter to this schematype.

      show code
      SchemaType.prototype.get = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A getter must be a function.');
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function dob (val) {
      +  if (!val) return val;
      +  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      +}
      +
      +var s = new Schema({ born: { type: Date, get: dob })
      +// or
      +Schema.path('name').get(dob);

      SchemaType#validate(obj, [error])

      Adds validator(s) for this document path.

      show code
      SchemaType.prototype.validate = function (obj, error) {
      +  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
      +    this.validators.push([obj, error]);
      +    return this;
      +  }
      +
      +  var i = arguments.length
      +    , arg
      +
      +  while (i--) {
      +    arg = arguments[i];
      +    if (!(arg && 'Object' == arg.constructor.name)) {
      +      var msg = 'Invalid validator. Received (' + typeof arg + ') '
      +        + arg
      +        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
      +
      +      throw new Error(msg);
      +    }
      +    this.validate(arg.validator, arg.msg);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Validators must return Boolean. Returning false is interpreted as validation failure.

      + +

      Examples:

      + +
      function validator () { ... }
      +
      +var single = [validator, 'failed']
      +new Schema({ name: { type: String, validate: single }});
      +
      +var many = [
      +    { validator: validator, msg: 'uh oh' }
      +  , { validator: fn, msg: 'failed' }
      +]
      +new Schema({ name: { type: String, validate: many }});
      +
      +// or utilizing SchemaType methods directly:
      +
      +var schema = new Schema({ name: 'string' });
      +schema.path('name').validate(validator, 'validation failed');
      + +

      Asynchronous validation:

      + +

      Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

      + +
      schema.path('name').validate(function (value, respond) {
      +  doStuff(value, function () {
      +    ...
      +    respond(false); // validation failed
      +  })
      + }, 'my error type');
      + +

      Validation occurs pre('save') or whenever you manually execute document#validate.

      + +

      If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

      + +
      var conn = mongoose.createConnection(..);
      +conn.on('error', handleError);
      +
      +var Product = conn.model('Product', yourSchema);
      +var dvd = new Product(..);
      +dvd.save(); // emits error on the `conn` above
      + +

      If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

      + +
      // registering an error listener on the Model lets us handle errors more locally
      +Product.on('error', handleError);

      SchemaType#required(required)

      Adds a required validator to this schematype.

      show code
      SchemaType.prototype.required = function (required) {
      +  var self = this;
      +
      +  function __checkRequired (v) {
      +    // in here, `this` refers to the validating document.
      +    // no validation when this path wasn't selected in the query.
      +    if ('isSelected' in this &&
      +        !this.isSelected(self.path) &&
      +        !this.isModified(self.path)) return true;
      +    return self.checkRequired(v);
      +  }
      +
      +  if (false === required) {
      +    this.isRequired = false;
      +    this.validators = this.validators.filter(function (v) {
      +      return v[0].name !== '__checkRequired';
      +    });
      +  } else {
      +    this.isRequired = true;
      +    this.validators.push([__checkRequired, 'required']);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • required <Boolean> enable/disable the validator

      Returns:

      Example:

      + +
      var s = new Schema({ born: { type: Date, required: true })
      +// or
      +Schema.path('name').required(true);

      SchemaType#getDefault(scope, init)

      Gets the default value

      show code
      SchemaType.prototype.getDefault = function (scope, init) {
      +  var ret = 'function' === typeof this.defaultValue
      +    ? this.defaultValue.call(scope)
      +    : this.defaultValue;
      +
      +  if (null !== ret && undefined !== ret) {
      +    return this.cast(ret, scope, init);
      +  } else {
      +    return ret;
      +  }
      +};

      Parameters:

      • scope <Object> the scope which callback are executed
      • init <Boolean>

      SchemaType#applySetters(value, scope, init)

      Applies setters

      show code
      SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  var v = value
      +    , setters = this.setters
      +    , len = setters.length
      +
      +  if (!len) {
      +    if (null === v || undefined === v) return v;
      +    return init
      +      ? v // if we just initialized we dont recast
      +      : this.cast(v, scope, init, priorVal)
      +  }
      +
      +  while (len--) {
      +    v = setters[len].call(scope, v, this);
      +  }
      +
      +  if (null === v || undefined === v) return v;
      +
      +  // do not cast until all setters are applied #665
      +  v = this.cast(v, scope, init, priorVal);
      +
      +  return v;
      +};

      Parameters:


      SchemaType#applyGetters(value, scope)

      Applies getters to a value

      show code
      SchemaType.prototype.applyGetters = function (value, scope) {
      +  if (SchemaType._isRef(this, value, true)) return value;
      +
      +  var v = value
      +    , getters = this.getters
      +    , len = getters.length;
      +
      +  if (!len) {
      +    return v;
      +  }
      +
      +  while (len--) {
      +    v = getters[len].call(scope, v, this);
      +  }
      +
      +  return v;
      +};

      Parameters:


      SchemaType#select(val)

      Sets default select() behavior for this path.

      show code
      SchemaType.prototype.select = function select (val) {
      +  this.selected = !! val;
      +}

      Parameters:

      Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

      + +

      Example:

      + +
      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      +T.find(..); // field x will always be selected ..
      +// .. unless overridden;
      +T.find().select('-x').exec(callback);

      SchemaType#doValidate(value, callback, scope)

      Performs a validation of value using the validators declared for this SchemaType.

      show code
      SchemaType.prototype.doValidate = function (value, fn, scope) {
      +  var err = false
      +    , path = this.path
      +    , count = this.validators.length;
      +
      +  if (!count) return fn(null);
      +
      +  function validate (val, msg) {
      +    if (err) return;
      +    if (val === undefined || val) {
      +      --count || fn(null);
      +    } else {
      +      fn(err = new ValidatorError(path, msg));
      +    }
      +  }
      +
      +  this.validators.forEach(function (v) {
      +    var validator = v[0]
      +      , message   = v[1];
      +
      +    if (validator instanceof RegExp) {
      +      validate(validator.test(value), message);
      +    } else if ('function' === typeof validator) {
      +      if (2 === validator.length) {
      +        validator.call(scope, value, function (val) {
      +          validate(val, message);
      +        });
      +      } else {
      +        validate(validator.call(scope, value), message);
      +      }
      +    }
      +  });
      +};

      Parameters:


      SchemaType._isRef(self, value, init)

      Determines if value is a valid Reference.

      show code
      SchemaType._isRef = function (self, value, init) {
      +  if (init && self.options && self.options.ref) {
      +    if (null == value) return true;
      +    if (value._id && value._id.constructor.name === self.instance) return true;
      +  }
      +
      +  return false;
      +}

      Parameters:

      Returns:


    • types/array.js

      MongooseArray(values, path, doc)

      Mongoose Array constructor.

      show code
      function MongooseArray (values, path, doc) {
      +  var arr = [];
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:

      NOTE:

      + +

      Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


      MongooseArray#_cast(value)

      Casts a member based on this arrays schema.

      show code
      MongooseArray.prototype._cast = function (value) {
      +  var cast = this._schema.caster.cast
      +    , doc = this._parent;
      +
      +  return cast.call(null, value, doc);
      +};

      Parameters:

      Returns:

      • <value> the casted value

      MongooseArray#_markModified(embeddedDoc, embeddedPath)

      Marks this array as modified.

      show code
      MongooseArray.prototype._markModified = function (embeddedDoc, embeddedPath) {
      +  var parent = this._parent
      +    , dirtyPath;
      +
      +  if (parent) {
      +    if (arguments.length) {
      +      // If an embedded doc bubbled up the change
      +      dirtyPath = [this._path, this.indexOf(embeddedDoc), embeddedPath].join('.');
      +    } else {
      +      dirtyPath = this._path;
      +    }
      +    parent.markModified(dirtyPath);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
      • embeddedPath <String> the path which changed in the embeddedDoc

      If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


      MongooseArray#_registerAtomic(op, val)

      Register an atomic operation with the parent.

      show code
      MongooseArray.prototype._registerAtomic = function (op, val) {
      +  if ('$set' == op) {
      +    // $set takes precedence over all other ops.
      +    // mark entire array modified.
      +    this._atomics = { $set: val };
      +    this._markModified();
      +    return this;
      +  }
      +
      +  var atomics = this._atomics;
      +
      +  // reset pop/shift after save
      +  if ('$pop' == op && !('$pop' in atomics)) {
      +    var self = this;
      +    this._parent.once('save', function () {
      +      self._popped = self._shifted = null;
      +    });
      +  }
      +
      +  if (this._atomics.$set) {
      +    return this;
      +  }
      +
      +  // check for impossible $atomic combos (Mongo denies more than one
      +  // $atomic op on a single path
      +  if (Object.keys(atomics).length && !(op in atomics)) {
      +    // a different op was previously registered.
      +    // save the entire thing.
      +    this._atomics = { $set: this };
      +    this._markModified();
      +    return this;
      +  }
      +
      +  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
      +    atomics[op] || (atomics[op] = []);
      +    atomics[op] = atomics[op].concat(val);
      +  } else if (op === '$pullDocs') {
      +    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
      +      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
      +    selector['$in'] = selector['$in'].concat(val);
      +  } else {
      +    atomics[op] = val;
      +  }
      +
      +  this._markModified();
      +  return this;
      +};

      Parameters:


      MongooseArray#hasAtomics()

      Returns the number of pending atomic operations to send to the db for this array.

      show code
      MongooseArray.prototype.hasAtomics = function hasAtomics () {
      +  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
      +    return 0;
      +  }
      +
      +  return Object.keys(this._atomics).length;
      +}

      Returns:


      MongooseArray#push([args...])

      Wraps Array#push with proper change tracking.

      show code
      MongooseArray.prototype.push = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +
      +  // $pushAll might be fibbed (could be $push). But it makes it easier to
      +  // handle what could have been $push, $pushAll combos
      +  this._registerAtomic('$pushAll', values);
      +  return ret;
      +};

      Parameters:


      MongooseArray#nonAtomicPush([args...])

      Pushes items to the array non-atomically.

      show code
      MongooseArray.prototype.nonAtomicPush = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +};

      Parameters:

      • [args...] <any>

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$pop()

      Pops the array atomically at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var popped = doc.array.$pop();
      + console.log(popped); // 3
      + console.log(doc.array); // [1,2]
      +
      + // no affect
      + popped = doc.array.$pop();
      + console.log(doc.array); // [1,2]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $pop works again
      +   popped = doc.array.$pop();
      +   console.log(popped); // 2
      +   console.log(doc.array); // [1]
      + })

      MongooseArray#pop()

      Wraps Array#pop with proper change tracking.

      show code
      MongooseArray.prototype.pop = function () {
      +  var ret = [].pop.call(this);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +};

      Note:

      + +

      marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$shift()

      Atomically shifts the array at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var shifted = doc.array.$shift();
      + console.log(shifted); // 1
      + console.log(doc.array); // [2,3]
      +
      + // no affect
      + shifted = doc.array.$shift();
      + console.log(doc.array); // [2,3]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $shift works again
      +   shifted = doc.array.$shift();
      +   console.log(shifted ); // 2
      +   console.log(doc.array); // [3]
      + })

      MongooseArray#shift()

      Wraps Array#shift with proper change tracking.

      show code
      MongooseArray.prototype.shift = function () {
      +  var ret = [].shift.call(this);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +};

      Example:

      + +
      doc.array = [2,3];
      +var res = doc.array.shift();
      +console.log(res) // 2
      +console.log(doc.array) // [3]
      + +

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#remove([args...])

      Removes items from an array atomically

      show code
      MongooseArray.prototype.remove = function () {
      +  var args = [].map.call(arguments, this._cast, this);
      +  if (args.length == 1)
      +    this.pull(args[0]);
      +  else
      +    this.pull.apply(this, args);
      +  return args;
      +};

      Parameters:

      • [args...] <Object> values to remove

      Examples:

      + +
      doc.array.remove(ObjectId)
      +doc.array.remove('tag 1', 'tag 2')

      MongooseArray#pull([args...])

      Pulls items from the array atomically.

      show code
      MongooseArray.prototype.pull = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , cur = this._parent.get(this._path)
      +    , i = cur.length
      +    , mem;
      +
      +  while (i--) {
      +    mem = cur[i];
      +    if (mem instanceof EmbeddedDocument) {
      +      if (values.some(function (v) { return v.equals(mem); } )) {
      +        [].splice.call(cur, i, 1);
      +      }
      +    } else if (~cur.indexOf.call(values, mem)) {
      +      [].splice.call(cur, i, 1);
      +    }
      +  }
      +
      +  if (values[0] instanceof EmbeddedDocument) {
      +    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
      +  } else {
      +    this._registerAtomic('$pullAll', values);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • [args...] <any>

      MongooseArray#splice()

      Wraps Array#splice with proper change tracking.

      show code
      MongooseArray.prototype.splice = function () {
      +  if (arguments.length) {
      +    var ret = [].splice.apply(this, arguments);
      +    this._registerAtomic('$set', this);
      +  }
      +  return ret;
      +};

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#unshift()

      Wraps Array#unshift with proper change tracking.

      show code
      MongooseArray.prototype.unshift = function () {
      +  var values = [].map.call(arguments, this._cast, this);
      +  [].unshift.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  return this.length;
      +};

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#sort()

      Wraps Array#sort with proper change tracking.

      show code
      MongooseArray.prototype.sort = function () {
      +  var ret = [].sort.apply(this, arguments);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +}

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#addToSet([args...])

      Adds values to the array if not already present.

      show code
      MongooseArray.prototype.addToSet = function addToSet () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , added = []
      +    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
      +             values[0] instanceof Date ? 'date' :
      +             '';
      +
      +  values.forEach(function (v) {
      +    var found;
      +    switch (type) {
      +      case 'doc':
      +        found = this.some(function(doc){ return doc.equals(v) });
      +        break;
      +      case 'date':
      +        var val = +v;
      +        found = this.some(function(d){ return +d === val });
      +        break;
      +      default:
      +        found = ~this.indexOf(v);
      +    }
      +
      +    if (!found) {
      +      [].push.call(this, v);
      +      this._registerAtomic('$addToSet', v);
      +      [].push.call(added, v);
      +    }
      +  }, this);
      +
      +  return added;
      +};

      Parameters:

      • [args...] <any>

      Returns:

      • <Array> the values that were added

      Example:

      + +
      console.log(doc.array) // [2,3,4]
      +var added = doc.array.addToSet(4,5);
      +console.log(doc.array) // [2,3,4,5]
      +console.log(added)     // [5]

      MongooseArray#toObject(options)

      Returns a native js Array.

      show code
      MongooseArray.prototype.toObject = function (options) {
      +  if (options && options.depopulate && this[0] instanceof Document) {
      +    return this.map(function (doc) {
      +      return doc._id;
      +    });
      +  }
      +
      +  // return this.slice()?
      +  return this.map(function (doc) {
      +    return doc;
      +  });
      +};

      Parameters:

      Returns:


      MongooseArray#inspect()

      Helper for console.log

      show code
      MongooseArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    return ' ' + doc;
      +  }) + ' ]';
      +};

      MongooseArray#indexOf(obj)

      Return the index of obj or -1 if not found.

      show code
      MongooseArray.prototype.indexOf = function indexOf (obj) {
      +  if (obj instanceof ObjectId) obj = obj.toString();
      +  for (var i = 0, len = this.length; i < len; ++i) {
      +    if (obj == this[i])
      +      return i;
      +  }
      +  return -1;
      +};

      Parameters:

      • obj <Object> the item to look for

      Returns:


      MongooseArray#_parent

      Parent owner document


      MongooseArray#_atomics

      Stores a queue of atomic operations to perform


    • types/buffer.js

      MongooseBuffer(value, encode, offset)

      Mongoose Buffer constructor.

      show code
      function MongooseBuffer (value, encode, offset) {
      +  var length = arguments.length;
      +  var val;
      +
      +  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
      +    val = 0;
      +  } else {
      +    val = value;
      +  }
      +
      +  var encoding;
      +  var path;
      +  var doc;
      +
      +  if (Array.isArray(encode)) {
      +    // internal casting
      +    path = encode[0];
      +    doc = encode[1];
      +  } else {
      +    encoding = encode;
      +  }
      +
      +  var buf = new Buffer(val, encoding, offset);
      +  buf.__proto__ = MongooseBuffer.prototype;
      +
      +  // make sure these internal props don't show up in Object.keys()
      +  Object.defineProperties(buf, {
      +      validators: { value: [] }
      +    , _path: { value: path }
      +    , _parent: { value: doc }
      +  });
      +
      +  if (doc && "string" === typeof path) {
      +    Object.defineProperty(buf, '_schema', {
      +        value: doc.schema.path(path)
      +    });
      +  }
      +
      +  return buf;
      +};

      Parameters:

      Inherits:

      Values always have to be passed to the constructor to initialize.


      MongooseBuffer#_markModified()

      Marks this buffer as modified.

      show code
      MongooseBuffer.prototype._markModified = function () {
      +  var parent = this._parent;
      +
      +  if (parent) {
      +    parent.markModified(this._path);
      +  }
      +  return this;
      +};

      MongooseBuffer#write()

      Writes the buffer.

      show code
      MongooseBuffer.prototype.write = function () {
      +  var written = Buffer.prototype.write.apply(this, arguments);
      +
      +  if (written > 0) {
      +    this._markModified();
      +  }
      +
      +  return written;
      +};

      MongooseBuffer#copy(target)

      Copies the buffer.

      show code
      MongooseBuffer.prototype.copy = function (target) {
      +  var ret = Buffer.prototype.copy.apply(this, arguments);
      +
      +  if (target instanceof MongooseBuffer) {
      +    target._markModified();
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Note:

      + +

      Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


      MongooseBuffer#toObject([subtype])

      Converts this buffer to its Binary type representation.

      show code
      MongooseBuffer.prototype.toObject = function (subtype) {
      +  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
      +  return new Binary(this, subtype);
      +};

      Parameters:

      • [subtype] <Hex>

      Returns:

      SubTypes:

      + +
        +
      • 0x00: Binary/Generic
      • +
      • 0x01: Function
      • +
      • 0x02: Binary (Deprecated, 0x00 is new default)
      • +
      • 0x03: UUID
      • +
      • 0x04: MD5
      • +
      • 0x80: User Defined
      • +

      MongooseBuffer#_parent

      Parent owner document


    • types/documentarray.js

      MongooseDocumentArray(values, path, doc)

      DocumentArray constructor

      show code
      function MongooseDocumentArray (values, path, doc) {
      +  var arr = [];
      +
      +  // Values always have to be passed to the constructor to initialize, since
      +  // otherwise MongooseArray#push will mark the array as modified to the parent.
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseDocumentArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +    doc.on('save', arr.notify('save'));
      +    doc.on('isNew', arr.notify('isNew'));
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:


      MongooseDocumentArray#_cast()

      Overrides MongooseArray#cast

      show code
      MongooseDocumentArray.prototype._cast = function (value) {
      +  var doc = new this._schema.casterConstructor(value, this);
      +  return doc;
      +};

      MongooseDocumentArray#id(id)

      Searches array items for the first document with a matching id.

      show code
      MongooseDocumentArray.prototype.id = function (id) {
      +  var casted
      +    , _id;
      +
      +  try {
      +    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
      +  } catch (e) {
      +    casted = null;
      +  }
      +
      +  for (var i = 0, l = this.length; i < l; i++) {
      +    _id = this[i].get('_id');
      +    if (!(_id instanceof ObjectId)) {
      +      if (String(id) == _id)
      +        return this[i];
      +    } else {
      +      if (casted == _id)
      +        return this[i];
      +    }
      +  }
      +
      +  return null;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var embeddedDoc = m.array.id(some_id);

      MongooseDocumentArray#toObject()

      Returns a native js Array of plain js objects

      show code
      MongooseDocumentArray.prototype.toObject = function () {
      +  return this.map(function (doc) {
      +    return doc && doc.toObject() || null;
      +  });
      +};

      Returns:

      NOTE:

      + +

      Each sub-document is converted to a plain object by calling its #toObject method.


      MongooseDocumentArray#inspect()

      Helper for console.log

      show code
      MongooseDocumentArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    if (doc) {
      +      return doc.inspect
      +        ? doc.inspect()
      +        : util.inspect(doc)
      +    }
      +    return 'null'
      +  }).join('
      +') + ']';
      +};

      MongooseDocumentArray#create(obj)

      Creates a subdocument casted to this schema.

      show code
      MongooseDocumentArray.prototype.create = function (obj) {
      +  return new this._schema.casterConstructor(obj);
      +}

      Parameters:

      • obj <Object> the value to cast to this arrays SubDocument schema

      This is the same subdocument constructor used for casting.


      MongooseDocumentArray#notify(event)

      Creates a fn that notifies all child docs of event.

      show code
      MongooseDocumentArray.prototype.notify = function notify (event) {
      +  var self = this;
      +  return function notify (val) {
      +    var i = self.length;
      +    while (i--) {
      +      self[i].emit(event, val);
      +    }
      +  }
      +}

      Parameters:

      Returns:


    • types/embedded.js

      EmbeddedDocument(obj, parentArr, skipId)

      EmbeddedDocument constructor.

      show code
      function EmbeddedDocument (obj, parentArr, skipId) {
      +  if (parentArr) {
      +    this.__parentArray = parentArr;
      +    this.__parent = parentArr._parent;
      +  } else {
      +    this.__parentArray = undefined;
      +    this.__parent = undefined;
      +  }
      +
      +  Document.call(this, obj, undefined, skipId);
      +
      +  var self = this;
      +  this.on('isNew', function (val) {
      +    self.isNew = val;
      +  });
      +};

      Parameters:

      Inherits:


      EmbeddedDocument#markModified(path)

      Marks the embedded doc modified.

      show code
      EmbeddedDocument.prototype.markModified = function (path) {
      +  if (!this.__parentArray) return;
      +
      +  this._activePaths.modify(path);
      +
      +  if (this.isNew) {
      +    // Mark the WHOLE parent array as modified
      +    // if this is a new document (i.e., we are initializing
      +    // a document),
      +    this.__parentArray._markModified();
      +  } else
      +    this.__parentArray._markModified(this, path);
      +};

      Parameters:

      • path <String> the path which changed

      Example:

      + +
      var doc = blogpost.comments.id(hexstring);
      +doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');

      EmbeddedDocument#save([fn])

      Used as a stub for hooks.js

      show code
      EmbeddedDocument.prototype.save = function(fn) {
      +  if (fn)
      +    fn(null);
      +  return this;
      +};

      Parameters:

      Returns:

      NOTE:

      + +

      This is a no-op. Does not actually save the doc to the db.


      EmbeddedDocument#remove([fn])

      Removes the subdocument from its parent array.

      show code
      EmbeddedDocument.prototype.remove = function (fn) {
      +  if (!this.__parentArray) return this;
      +
      +  var _id;
      +  if (!this.willRemove) {
      +    _id = this._doc._id;
      +    if (!_id) {
      +      throw new Error('For your own good, Mongoose does not know ' + 
      +                      'how to remove an EmbeddedDocument that has no _id');
      +    }
      +    this.__parentArray.pull({ _id: _id });
      +    this.willRemove = true;
      +  }
      +
      +  if (fn)
      +    fn(null);
      +
      +  return this;
      +};

      Parameters:


      EmbeddedDocument#update()

      Override #update method of parent documents.

      show code
      EmbeddedDocument.prototype.update = function () {
      +  throw new Error('The #update method is not available on EmbeddedDocuments');
      +}

      EmbeddedDocument#inspect()

      Helper for console.log

      show code
      EmbeddedDocument.prototype.inspect = function () {
      +  return inspect(this.toObject());
      +};

      EmbeddedDocument#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
      +  if (!this.__parent) return false;
      +  var index = this.__parentArray.indexOf(this);
      +  var parentPath = this.__parentArray._path;
      +  var fullPath = [parentPath, index, path].join('.');
      +  this.__parent.invalidate(fullPath, err);
      +  if (first)
      +    this._validationError = ownerDocument(this)._validationError;
      +  return true;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> error which states the reason `path` was invalid

      Returns:


      EmbeddedDocument#ownerDocument()

      Returns the top level document of this sub-document.

      show code
      EmbeddedDocument.prototype.ownerDocument = function () {
      +  return ownerDocument(this);
      +}

      Returns:


      EmbeddedDocument#parent()

      Returns this sub-documents parent document.

      show code
      EmbeddedDocument.prototype.parent = function () {
      +  return this.__parent;
      +}

      EmbeddedDocument#parentArray()

      Returns this sub-documents parent array.

      show code
      EmbeddedDocument.prototype.parentArray = function () {
      +  return this.__parentArray;
      +}

    • types/objectid.js

      ObjectId()

      ObjectId type constructor

      Example

      + +
      var id = new mongoose.Types.ObjectId;

      ObjectId.fromString(str)

      Creates an ObjectId from str

      show code
      ObjectId.fromString;

      Parameters:

      Returns:


      ObjectId.toString(oid)

      Converts oid to a string.

      show code
      ObjectId.toString;

      Parameters:

      Returns:


    • utils.js

      exports.toCollectionName(name)

      Produces a collection name from model name.

      show code
      exports.toCollectionName = function (name) {
      +  if ('system.profile' === name) return name;
      +  if ('system.indexes' === name) return name;
      +  return pluralize(name.toLowerCase());
      +};

      Parameters:

      Returns:


      exports.pluralization

      Pluralization rules.

      show code
      exports.pluralization = [
      +  [/(m)an$/gi, '$1en'],
      +  [/(pe)rson$/gi, '$1ople'],
      +  [/(child)$/gi, '$1ren'],
      +  [/^(ox)$/gi, '$1en'],
      +  [/(ax|test)is$/gi, '$1es'],
      +  [/(octop|vir)us$/gi, '$1i'],
      +  [/(alias|status)$/gi, '$1es'],
      +  [/(bu)s$/gi, '$1ses'],
      +  [/(buffal|tomat|potat)o$/gi, '$1oes'],
      +  [/([ti])um$/gi, '$1a'],
      +  [/sis$/gi, 'ses'],
      +  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
      +  [/(hive)$/gi, '$1s'],
      +  [/([^aeiouy]|qu)y$/gi, '$1ies'],
      +  [/(x|ch|ss|sh)$/gi, '$1es'],
      +  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
      +  [/([m|l])ouse$/gi, '$1ice'],
      +  [/(quiz)$/gi, '$1zes'],
      +  [/s$/gi, 's'],
      +  [/$/gi, 's']
      +];
      +var rules = exports.pluralization;

      These rules are applied while processing the argument to toCollectionName.


      exports.uncountables

      Uncountable words.

      show code
      exports.uncountables = [
      +  'advice',
      +  'energy',
      +  'excretion',
      +  'digestion',
      +  'cooperation',
      +  'health',
      +  'justice',
      +  'labour',
      +  'machinery',
      +  'equipment',
      +  'information',
      +  'pollution',
      +  'sewage',
      +  'paper',
      +  'money',
      +  'species',
      +  'series',
      +  'rain',
      +  'rice',
      +  'fish',
      +  'sheep',
      +  'moose',
      +  'deer',
      +  'news'
      +];
      +var uncountables = exports.uncountables;

      These words are applied while processing the argument to toCollectionName.


      exports.deepEqual(a, b)

      Determines if a and b are deep equal.

      show code
      exports.deepEqual = function deepEqual (a, b) {
      +  if (a === b) return true;
      +
      +  if (a instanceof Date && b instanceof Date)
      +    return a.getTime() === b.getTime();
      +
      +  if (a instanceof ObjectId && b instanceof ObjectId) {
      +    return a.toString() === b.toString();
      +  }
      +
      +  if (typeof a !== 'object' && typeof b !== 'object')
      +    return a == b;
      +
      +  if (a === null || b === null || a === undefined || b === undefined)
      +    return false
      +
      +  if (a.prototype !== b.prototype) return false;
      +
      +  // Handle MongooseNumbers
      +  if (a instanceof Number && b instanceof Number) {
      +    return a.valueOf() === b.valueOf();
      +  }
      +
      +  if (Buffer.isBuffer(a)) {
      +    if (!Buffer.isBuffer(b)) return false;
      +    if (a.length !== b.length) return false;
      +    for (var i = 0, len = a.length; i < len; ++i) {
      +      if (a[i] !== b[i]) return false;
      +    }
      +    return true;
      +  }
      +
      +  if (isMongooseObject(a)) a = a.toObject();
      +  if (isMongooseObject(b)) b = b.toObject();
      +
      +  try {
      +    var ka = Object.keys(a),
      +        kb = Object.keys(b),
      +        key, i;
      +  } catch (e) {//happens when one is a string literal and the other isn't
      +    return false;
      +  }
      +
      +  // having the same number of owned properties (keys incorporates
      +  // hasOwnProperty)
      +  if (ka.length != kb.length)
      +    return false;
      +
      +  //the same set of keys (although not necessarily the same order),
      +  ka.sort();
      +  kb.sort();
      +
      +  //~~~cheap key test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    if (ka[i] != kb[i])
      +      return false;
      +  }
      +
      +  //equivalent values for every corresponding key, and
      +  //~~~possibly expensive deep test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    key = ka[i];
      +    if (!deepEqual(a[key], b[key])) return false;
      +  }
      +
      +  return true;
      +};

      Parameters:

      • a <any> a value to compare to `b`
      • b <any> a value to compare to `a`

      Returns:

      Modified from node/lib/assert.js


      exports.clone(obj, options)

      Object clone with Mongoose natives support.

      show code
      exports.clone = function clone (obj, options) {
      +  if (obj === undefined || obj === null)
      +    return obj;
      +
      +  if (Array.isArray(obj))
      +    return cloneArray(obj, options);
      +
      +  if (isMongooseObject(obj)) {
      +    if (options && options.json && 'function' === typeof obj.toJSON) {
      +      return obj.toJSON(options);
      +    } else {
      +      return obj.toObject(options);
      +    }
      +  }
      +
      +  if ('Object' === obj.constructor.name)
      +    return cloneObject(obj, options);
      +
      +  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
      +    return new obj.constructor(+obj);
      +
      +  if ('RegExp' === obj.constructor.name)
      +    return new RegExp(obj.source);
      +
      +  if (obj instanceof ObjectId) {
      +    return new ObjectId(obj.id);
      +  }
      +
      +  if (obj.valueOf)
      +    return obj.valueOf();
      +};
      +var clone = exports.clone;

      Parameters:

      Returns:

      Creates a minimal data Object.
      It does not clone empty Arrays, empty Objects, and undefined values.
      This makes the data payload sent to MongoDB as minimal as possible.


      exports.options(defaults, options)

      Copies and merges options with defaults.

      show code
      exports.options = function (defaults, options) {
      +  var keys = Object.keys(defaults)
      +    , i = keys.length
      +    , k ;
      +
      +  options = options || {};
      +
      +  while (i--) {
      +    k = keys[i];
      +    if (!(k in options)) {
      +      options[k] = defaults[k];
      +    }
      +  }
      +
      +  return options;
      +};

      Parameters:

      Returns:


      exports.random()

      Generates a random string

      show code
      exports.random = function () {
      +  return Math.random().toString().substr(3);
      +};

      exports.merge(to, from)

      Merges from into to without overwriting existing properties.

      show code
      exports.merge = function merge (to, from) {
      +  var keys = Object.keys(from)
      +    , i = keys.length
      +    , key
      +
      +  while (i--) {
      +    key = keys[i];
      +    if ('undefined' === typeof to[key]) {
      +      to[key] = from[key];
      +    } else {
      +      merge(to[key], from[key]);
      +    }
      +  }
      +};

      Parameters:


      exports.args()

      A faster Array.prototype.slice.call(arguments) alternative

      show code
      exports.args = function (args, slice, sliceEnd) {
      +  var ret = [];
      +  var start = slice || 0;
      +  var end = 3 === arguments.length
      +    ? sliceEnd
      +    : args.length;
      +
      +  for (var i = start; i < end; ++i) {
      +    ret[i - start] = args[i];
      +  }
      +
      +  return ret;
      +}

      exports.tick(callback)

      process.nextTick helper.

      show code
      exports.tick = function tick (callback) {
      +  if ('function' !== typeof callback) return;
      +  return function () {
      +    try {
      +      callback.apply(this, arguments);
      +    } catch (err) {
      +      // only nextTick on err to get out of
      +      // the event loop and avoid state corruption.
      +      process.nextTick(function () {
      +        throw err;
      +      });
      +    }
      +  }
      +}

      Parameters:

      Wraps callback in a try/catch + nextTick.

      + +

      node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


      exports.isMongooseObject(v)

      Returns if v is a mongoose object that has a toObject() method we can use.

      show code
      exports.isMongooseObject = function (v) {
      +  Document || (Document = require('./document'));
      +  MongooseArray || (MongooseArray = require('./types').Array);
      +  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
      +
      +  return v instanceof Document ||
      +         v instanceof MongooseArray ||
      +         v instanceof MongooseBuffer
      +}
      +var isMongooseObject = exports.isMongooseObject;

      Parameters:

      This is for compatibility with libs like Date.js which do foolish things to Natives.


      exports.expires(object)

      Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

      show code
      exports.expires = function expires (object) {
      +  if (!(object && 'Object' == object.constructor.name)) return;
      +  if (!('expires' in object)) return;
      +
      +  var when;
      +  if ('string' != typeof object.expires) {
      +    when = object.expires;
      +  } else {
      +    when = Math.round(ms(object.expires) / 1000);
      +  }
      +  object.expiresAfterSeconds = when;
      +  delete object.expires;
      +}

      Parameters:


    • virtualtype.js

      VirtualType()

      VirtualType constructor

      show code
      function VirtualType (options) {
      +  this.getters = [];
      +  this.setters = [];
      +  this.options = options || {};
      +}

      This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

      + +

      Example:

      + +
      var fullname = schema.virtual('fullname');
      +fullname instanceof mongoose.VirtualType // true

      VirtualType#get(fn)

      Defines a getter.

      show code
      VirtualType.prototype.get = function (fn) {
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.get(function () {
      +  return this.name.first + ' ' + this.name.last;
      +});

      VirtualType#set(fn)

      Defines a setter.

      show code
      VirtualType.prototype.set = function (fn) {
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.set(function (v) {
      +  var parts = v.split(' ');
      +  this.name.first = parts[0];
      +  this.name.last = parts[1];
      +});

      VirtualType#applyGetters(value, scope)

      Applies getters to value using optional scope.

      show code
      VirtualType.prototype.applyGetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.getters.length - 1; l >= 0; l--){
      +    v = this.getters[l].call(scope, v);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all getters

      VirtualType#applySetters(value, scope)

      Applies setters to value using optional scope.

      show code
      VirtualType.prototype.applySetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.setters.length - 1; l >= 0; l--){
      +    this.setters[l].call(scope, v);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all setters

    diff --git a/docs/3.0.x/docs/api.jade b/docs/3.0.x/docs/api.jade new file mode 100644 index 00000000000..6f9a2c07307 --- /dev/null +++ b/docs/3.0.x/docs/api.jade @@ -0,0 +1,508 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose API v#{package.version} + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + style. + body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; + } + a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; + } + a:hover { + opacity: 0.8; + } + #wrap { + } + h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; + } + pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; + } + code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Monaco; + } + pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; + } + h3 { + padding: 20px 15px; + margin-left: -15px; + } + h3 code { + font-weight: normal; + } + hr { + height: 1px; + border: 0 none; + padding: 0; + margin: 60px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) + } + .doclinks hr { + margin: 10px 0; + } + li { + list-style: square; + } + #header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; + } + #header h1 { + margin-top: 0; + margin-bottom: 0; + } + #header h1 a { + text-decoration: none; + } + #header .mongoose { + font-size: 50px; + font-weight: 100; + color: #fff; + text-shadow: 6px 4px 5px #777, -2px 0px 2px white; + letter-spacing: -7px; + } + #links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + } + #links hr { + margin: 32px 0; + } + #content { + padding: 0; + margin: 0 0 30px 230px; + overflow-x: hidden; + } + #content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; + } + #content .controls:hover { + opacity: .9; + } + #content p { + word-wrap: break-word; + } + #content > ul { + margin: 0; + padding: 0; + } + .private { + display: none; + } + .section { + font-size: 15px; + } + .doclinks li.private a:before, + .doclinks .module.private a:before, + .doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; + } + #content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; + } + .module { + list-style: none; + padding: 30px 0 30px 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; + } + .module > * { + max-width: 700px; + } + .item:last-child { + margin-bottom: 90px; + } + .item:last-child > hr { + display: none; + } + .item h3 a { + color: #333; + text-decoration: none; + } + .property h3 span { + color: #444; + } + .description { + margin-top: 25px; + } + .sourcecode { + display: none; + } + .showcode { + font-size: 12px; + cursor: pointer; + display: none; + } + .load .showcode { + display: block; + } + .types a { + text-decoration: none; + } + @media only screen and (device-width: 768px) { + + } + @media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links hr { + display: none; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + .controls { display: none; } + } + body.api + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + hr + .doclinks + each item in docs + .file(class=item.hasPublic ? '' : 'private') + a.section(href='#' + item.title.replace(/[\.\/#]/g, '-'))= item.title + ul + each method in item.methods + if method.ctx && !method.ignore + li(class= method.isPrivate ? 'private' : '') + case method.ctx.type + when 'method' + id = method.ctx.constructor + '-' + method.ctx.name + when 'function' + id = method.ctx.name + default + id = '' + url = href(klass(item.title) + '_' + id) + a(href='#' + url)= method.ctx.name + each stat in item.statics + if stat.ctx && !stat.ignore + li(class= stat.isPrivate ? 'private' : '') + case stat.ctx.type + when 'method' + id = stat.ctx.receiver + '-' + stat.ctx.name + when 'property' + id = stat.ctx.receiver + '-' + stat.ctx.name + when 'function' + id = stat.ctx.name + url = href(klass(item.title) + '_' + id) + a(href='#' + url)= stat.ctx.name + each property in item.props + if property.ctx && !property.ignore + li(class= property.isPrivate ? 'private' : '') + construct = property.ctx.receiver || property.ctx.constructor + link = href(construct) + '-' + href(property.ctx.name) + url = href(klass(item.title) + '_' + link) + a(href='#' + url)= property.ctx.name + #content + .controls + label + input(type='checkbox') + | private + ul + each item in docs + li.module(class=item.hasPublic ? '' : 'private') + a(href=github + package.version + '/' + item.title, id=item.title.replace(/[\.\/#]/g, '-'))= item.title + each method in item.methods + div.item.method(class= method.isPrivate ? 'private' : 'public') + if method.ctx + case method.ctx.type + when 'method' + id = method.ctx.constructor + '-' + method.ctx.name + text = method.ctx.constructor + '#' + method.ctx.name + when 'function' + id = method.ctx.name + text = method.ctx.name + default + text = '' + url = href(klass(item.title) + '_' + text) + h3(id= url) + a(href= '#' + url) + = text + | ( + each tag, i in method.params + code= tag.name + if i+1 < method.params.length + | , + | ) + else + - // console.log('\nmissing method name', method); + h3 MISSING method name + != method.description.summary + if method.code + span.showcode show code + .sourcecode + != hl(method.code) + if method.params.length + .params + h4 Parameters: + ul + each tag in method.params + li + code= tag.name + if tag.types && tag.types.length + span.types + | < + each type, i in tag.types + != linktype(type) + if i+1 < tag.types.length + | , + | > + span= tag.description + if method.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in method.return.types + != linktype(type) + if i+1 < method.return.types.length + | , + | > + span= method.return.description + if method.inherits + .inherits + h4 Inherits: + ul + li + != method.inherits + if method.events && method.events.length + .events + h4 Events: + ul + each event in method.events + li + != event.string + if method.see.length + .see + h4 See: + ul.see + each see in method.see + li + url = see.url || see.local + a(href=url, title=see.title || see.local)= see.title || see.url || see.local + div.description + != method.description.body + hr(class= method.isPrivate ? 'private' : '') + each stat in item.statics + div.item.static(class= stat.isPrivate ? 'private' : 'public') + if stat.ctx + case stat.ctx.type + when 'method' + id = stat.ctx.receiver + '-' + stat.ctx.name + text = stat.ctx.receiver + '.' + stat.ctx.name + when 'property' + id = stat.ctx.receiver + '-' + stat.ctx.name + text = stat.ctx.receiver + '.' + stat.ctx.name + when 'function' + id = stat.ctx.name + text = stat.ctx.name + default + text = '' + url = href(klass(item.title) + '_' + id) + h3(id= url) + a(href= '#' + url) + = text + if 'property' != stat.ctx.type + | ( + each tag, i in stat.params + code= tag.name + if i+1 < stat.params.length + | , + | ) + else + - // console.log('\nmissing static name', stat); + h3 MISSING stat name + != stat.description.summary + if stat.code + span.showcode show code + .sourcecode + != hl(stat.code) + if stat.params.length + .params + h4 Parameters: + ul + each tag in stat.params + li + - if (!tag.name) + - // console.log(tag) + code= tag.name + if tag.types && tag.types.length + span.types + | < + each type, i in tag.types + != linktype(type) + if i+1 < tag.types.length + | , + | > + span= tag.description + if stat.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in stat.return.types + != linktype(type) + if i+1 < stat.return.types.length + | , + | > + span= stat.return.description + if stat.inherits + .inherits + h4 Inherits: + ul + li + != stat.inherits + if stat.see.length + .see + h4 See: + ul.see + each see in stat.see + li + url = see.url || see.local + a(href=url, title=see.title || see.local)= see.title || see.url || see.local + != stat.description.body + hr(class= stat.isPrivate ? 'private' : '') + each property in item.props + div.item.property(class= property.ignore || property.isPrivate ? 'private' : 'public') + construct = property.ctx.receiver || property.ctx.constructor + link = href(construct) + '-' + href(property.ctx.name) + url = href(klass(item.title) + '_' + link) + h3(id = url) + a(href= '#' + url) + = construct + '#' + span= property.ctx.name + != property.description.full + if property.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in property.return.types + != linktype(type) + if i+1 < property.return.types.length + | , + | > + span= property.return.description + hr(class= property.isPrivate ? 'private' : '') + script. + document.body.className = 'load'; + include includes/keen + script(src="/docs/js/zepto.min.js") + script. + $(".module").on("click", ".showcode", function (e) { + $(this).closest(".item").find(".sourcecode").first().toggle(); + }); + $("#content .controls input").on("click", function (e) { + $(".private").toggle() + }) diff --git a/docs/3.0.x/docs/contributing.html b/docs/3.0.x/docs/contributing.html new file mode 100644 index 00000000000..21db8a903d0 --- /dev/null +++ b/docs/3.0.x/docs/contributing.html @@ -0,0 +1,11 @@ +Mongoose Contributing v3.0.3Fork me on GitHub

    Contributing

    Bugfixes

    • Before starting to write code, look for existing tickets or create one for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch.
    • Fork the repo or for small documentation changes, navigate to the source on github and click the Edit button.
    • Write inline documentation for new methods or class members.
    • Write tests and make sure they pass (execute make test from the cmd line to run the test suite).
    • Follow the general coding style of the rest of the project (comma first, etc).

    Documentation

    To contribute to the API documentation just make your changes to the inline documentation of the appropriate source code in the master branch and submit a pull request. You might also use the github Edit button.

    + +

    To contribute to the guide or quick start docs, make your changes to the appropriate .jade files in the docs directory of the master branch and submit a pull request. Again, the Edit button might work for you here.

    Plugins

    The plugins site is also an open source project that you can get involved with. Feel free to fork and improve it as well!

    diff --git a/docs/3.0.x/docs/contributing.jade b/docs/3.0.x/docs/contributing.jade new file mode 100644 index 00000000000..eb6cc091510 --- /dev/null +++ b/docs/3.0.x/docs/contributing.jade @@ -0,0 +1,22 @@ +extends layout + +block content + h2 Contributing + + h3 Bugfixes + :markdown + - Before starting to write code, look for existing [tickets](https://github.com/learnboost/mongoose/issues) or [create one](https://github.com/learnboost/mongoose/issues/new) for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. + - Fork the [repo](https://github.com/learnboost/mongoose) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. + - Write inline documentation for new methods or class members. + - Write tests and make sure they pass (execute `make test` from the cmd line to run the test suite). + - Follow the general coding style of the rest of the project (comma first, etc). + + h3 Documentation + :markdown + To contribute to the [API documentation](./api.html) just make your changes to the inline documentation of the appropriate [source code](https://github.com/LearnBoost/mongoose/tree/master/lib) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. + + To contribute to the [guide](./guide.html) or [quick start](./index.html) docs, make your changes to the appropriate `.jade` files in the [docs](https://github.com/LearnBoost/mongoose/tree/master/docs) directory of the master branch and submit a pull request. Again, the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button might work for you here. + + h3 Plugins + :markdown + The [plugins](http://plugins.mongoosejs.com/) site is also an [open source project](https://github.com/aheckmann/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! diff --git a/docs/3.0.x/docs/css/default.css b/docs/3.0.x/docs/css/default.css new file mode 100644 index 00000000000..ccb22728ed3 --- /dev/null +++ b/docs/3.0.x/docs/css/default.css @@ -0,0 +1,135 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +pre code { + display: block; padding: 0.5em; + background: #F0F0F0; +} + +pre code, +pre .ruby .subst, +pre .tag .title, +pre .lisp .title, +pre .clojure .built_in, +pre .nginx .title { + color: black; +} + +pre .string, +pre .title, +pre .constant, +pre .parent, +pre .tag .value, +pre .rules .value, +pre .rules .value .number, +pre .preprocessor, +pre .ruby .symbol, +pre .ruby .symbol .string, +pre .ruby .symbol .keyword, +pre .ruby .symbol .keymethods, +pre .instancevar, +pre .aggregate, +pre .template_tag, +pre .django .variable, +pre .smalltalk .class, +pre .addition, +pre .flow, +pre .stream, +pre .bash .variable, +pre .apache .tag, +pre .apache .cbracket, +pre .tex .command, +pre .tex .special, +pre .erlang_repl .function_or_atom, +pre .markdown .header { + color: #800; +} + +pre .comment, +pre .annotation, +pre .template_comment, +pre .diff .header, +pre .chunk, +pre .markdown .blockquote { + color: #888; +} + +pre .number, +pre .date, +pre .regexp, +pre .literal, +pre .smalltalk .symbol, +pre .smalltalk .char, +pre .go .constant, +pre .change, +pre .markdown .bullet, +pre .markdown .link_url { + color: #080; +} + +pre .label, +pre .javadoc, +pre .ruby .string, +pre .decorator, +pre .filter .argument, +pre .localvars, +pre .array, +pre .attr_selector, +pre .important, +pre .pseudo, +pre .pi, +pre .doctype, +pre .deletion, +pre .envvar, +pre .shebang, +pre .apache .sqbracket, +pre .nginx .built_in, +pre .tex .formula, +pre .erlang_repl .reserved, +pre .input_number, +pre .markdown .link_label, +pre .vhdl .attribute, +pre .clojure .attribute { + color: #88F +} + +pre .keyword, +pre .id, +pre .phpdoc, +pre .title, +pre .built_in, +pre .aggregate, +pre .css .tag, +pre .javadoctag, +pre .phpdoc, +pre .yardoctag, +pre .smalltalk .class, +pre .winutils, +pre .bash .variable, +pre .apache .tag, +pre .go .typename, +pre .tex .command, +pre .markdown .strong, +pre .request, +pre .status { + font-weight: bold; +} + +pre .markdown .emphasis { + font-style: italic; +} + +pre .nginx .built_in { + font-weight: normal; +} + +pre .coffeescript .javascript, +pre .xml .css, +pre .xml .javascript, +pre .xml .vbscript, +pre .tex .formula { + opacity: 0.5; +} diff --git a/docs/3.0.x/docs/css/guide.css b/docs/3.0.x/docs/css/guide.css new file mode 100644 index 00000000000..51a5046fc24 --- /dev/null +++ b/docs/3.0.x/docs/css/guide.css @@ -0,0 +1,283 @@ +html, body, #content { + height: 100%; +} +.module { + min-height: 100%; + box-sizing: border-box; +} +body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; +} +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; +} +code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Monaco; + /*text-shadow: 1px 2px 2px #555;*/ +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +h2 { + margin-top: 0; +} +h3 { padding-top: 35px; } +h3 code { + font-weight: normal; +} +hr { + display: none; + height: 1px; + border: 0 none; + padding: 0; + margin: 90px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) +} +.doclinks hr { + margin: 10px 0; +} +li { + list-style: square; +} +#header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +#header .mongoose { + font-size: 50px; + font-weight: 100; + color: #fff; + text-shadow: 6px 4px 5px #777, -2px 0px 2px white; + letter-spacing: -7px; +} +#links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; +} +#links .schematypes span { + display: none; +} +#content { + padding: 0; + margin: 0 0 0 230px; + overflow-x: hidden; +} +#content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +#content .controls:hover { + opacity: .9; +} +#content p { + word-wrap: break-word; +} +#content > ul { + margin: 0; + padding: 0; +} +.private { + display: none; +} +.doclinks li.private a:before, +.doclinks .module.private a:before, +.doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; +} +#content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; +} +.module { + list-style: none; + padding: 30px 0 0 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; +} +.module > * { + max-width: 700px; +} +.item { + margin-bottom: 175px; +} +.item h3 a { + color: #333; + text-decoration: none; +} +.property h3 span { + color: #444; +} +.description { + margin-top: 25px; +} +.sourcecode { + display: none; +} +.showcode { + font-size: 12px; + cursor: pointer; + display: none; +} +.load .showcode { + display: block; +} +.types a { + text-decoration: none; +} +li.guide ul { + padding-left: 16px; +} + +@media only screen and (device-width: 768px) { + +} +@media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + html, body, #content { + height: auto; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + #links li.guide { + display: block; + width: 390px; + margin-bottom: 15px; + } + #links li.guide > a { + display: none; + } + #links li ul li { + width: 44%; + text-align: left; + } + #links li ul li ul li { + width: 95%; + } + #links .plugins, + #links .changelog { + display: none; + } + #links .schematypes span { + display: inline; + } + #links .double { + width: 332px; + } + #links .double > ul { + display: inline; + float: right; + } + #links .double > ul li { + width: 155px; + } +} diff --git a/docs/3.0.x/docs/documents.html b/docs/3.0.x/docs/documents.html new file mode 100644 index 00000000000..34268b2a98f --- /dev/null +++ b/docs/3.0.x/docs/documents.html @@ -0,0 +1,20 @@ +Mongoose Documents v3.0.3Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retreiving

    There are many ways to retreive documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    +  if (err) return handleError(err);
    +  
    +  tank.size = 'large';
    +  tank.save(function (err) {
    +    if (err) return handleError(err);
    +    res.send(tank);
    +  });
    +});

    This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    +  if (err) return handleError(err);
    +  res.send(tank);
    +});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    diff --git a/docs/3.0.x/docs/documents.jade b/docs/3.0.x/docs/documents.jade new file mode 100644 index 00000000000..825224a4dc1 --- /dev/null +++ b/docs/3.0.x/docs/documents.jade @@ -0,0 +1,38 @@ +extends layout + +block content + h2 Documents + :markdown + Mongoose [documents](./api.html#document-js) represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its [Model](./models.html). + h3 Retreiving + :markdown + There are many ways to retreive documents from MongoDB. We won't cover that in this section. See the chapter on [querying](./queries.html) for detail. + h3 Updating + :markdown + There are a number of ways to update documents. We'll first look at a traditional approach using [findById](./api.html#model_Model-findById): + :js + Tank.findById(id, function (err, tank) { + if (err) return handleError(err); + + tank.size = 'large'; + tank.save(function (err) { + if (err) return handleError(err); + res.send(tank); + }); + }); + :markdown + This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model-update) is right for us: + :js + Tank.update({ _id: id }, { $set: { size: 'large' }}, callback); + :markdown + If we do need the document returned in our application there is another, often [better](./api.html#model_Model-findByIdAndUpdate), option: + :js + Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) { + if (err) return handleError(err); + res.send(tank); + }); + :markdown + The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model-findByIdAndRemove) [several](./api.html#model_Model-findOneAndUpdate) [variations](./api.html#model_Model-findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. + h3 Validating + :markdown + Documents are validated before they are saved. Read the [api](./api.html#document_Document-validate) docs or the [validation](./validation.html) chapter for detail. diff --git a/docs/3.0.x/docs/faq.html b/docs/3.0.x/docs/faq.html new file mode 100644 index 00000000000..d5047a5de84 --- /dev/null +++ b/docs/3.0.x/docs/faq.html @@ -0,0 +1,31 @@ +Mongoose FAQ v3.0.3Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    +doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    +doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    +new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    +doc.user.remove();// ?
    +doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    + +

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    + +

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    +mongoose.connect(..);
    +mongoose.connection.on('error', handleError);
    +
    +// if connecting on a separate connection
    +var conn = mongoose.createConnection(..);
    +conn.on('error', handleError);
    +

    Something to add?

    + +

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    diff --git a/docs/3.0.x/docs/faq.jade b/docs/3.0.x/docs/faq.jade new file mode 100644 index 00000000000..07abc7ea928 --- /dev/null +++ b/docs/3.0.x/docs/faq.jade @@ -0,0 +1,63 @@ +extends layout + +block append style + style. + hr { + display: block; + margin: 30px 0; + } + +block content + h2 FAQ + :markdown + **Q**. Why don't my changes to arrays get saved when I update an element directly? + :js + doc.array[3] = 'changed'; + doc.save(); + :markdown + **A**. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving. + :js + doc.markModified('array'); + doc.save(); + hr + :markdown + **Q**. Why doesn't mongoose allow me to directly assign schemas to paths? + :js + var userSchema = new Schema({ name: String }); + new Schema({ user: userSchema }) + :markdown + **A**. Schemas have a one-to-one mapping with documents. Documents have `save` and `remove` methods along with their own `pre` and `post` hooks which would lead to code like the following: + :js + doc.user.save(); // ? + doc.user.remove();// ? + doc.save() + :markdown + We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling `save` on a sub-document is a no-op and exists only to support `pre` save hooks). In the future this is likely to be revisited. + hr + :markdown + **Q**. How can I enable debugging? + + **A**. Set the `debug` option to `true`: + :js + mongoose.set('debug', true) + hr + :markdown + **Q**. My `save()` callback never executes. What am I doing wrong? + + **A**. All `collection` actions (insert, remove, queries, etc) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. + :js + // if connecting on the default mongoose connection + mongoose.connect(..); + mongoose.connection.on('error', handleError); + + // if connecting on a separate connection + var conn = mongoose.createConnection(..); + conn.on('error', handleError); + + hr + :markdown + **Something to add?** + + If you'd like to contribute to this page, please [visit it](https://github.com/learnboost/mongoose/tree/master/docs/faq.jade) on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request. + br + diff --git a/docs/3.0.x/docs/guide.html b/docs/3.0.x/docs/guide.html new file mode 100644 index 00000000000..6823194546b --- /dev/null +++ b/docs/3.0.x/docs/guide.html @@ -0,0 +1,133 @@ +Mongoose Schemas v3.0.3Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

    If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    +  title:  String,
    +  author: String,
    +  body:   String,
    +  comments: [{ body: String, date: Date }],
    +  date: { type: Date, default: Date.now },
    +  hidden: Boolean,
    +  meta: {
    +    votes: Number,
    +    favs:  Number
    +  }
    +})

    If you want to add additional keys later, use the Schema#add method.

    +Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above). For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType.

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    +
    +animalSchema.methods.findSimilarTypes = function (cb) {
    +  return this.model('Animal').find({ type: this.type }, cb);
    +}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    +var dog = new Animal({ type: 'dog' })
    +
    +dog.findSimilarTypes(function (err, dogs) {
    +  console.log(dogs) // woof
    +})

    Statics

    +Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    +  this.find({ name: new RegExp(name, 'i'), cb);
    +}
    +
    +var Animal = mongoose.model('Animal', animalSchema);
    +Animal.findByName('fido', function (err, animals) {
    +  console.log(animals);
    +})

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index. This behavior can be disabled by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false)
    +// or
    +new Schema({..}, { autoIndex: false })

    See also the Model#ensureIndexes method.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    +  name: {
    +    first: String,
    +    last: String
    +  }
    +});
    +
    +var Person = mongoose.model('Person', personSchema);
    +
    +var bad = new Person({
    +    name: { first: 'Walter', last: 'White' }
    +});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    +  return this.name.first + ' ' + this.name.last;
    +})

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full) // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    +  var split = name.split(' ');
    +  this.name.first = split[0];
    +  this.name.last = split[1];
    +})
    +
    +...
    +
    +mad.name.full = 'Breaking Bad';
    +console.log(mad.name.first) // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    +
    +// or
    +
    +var schema = new Schema({..});
    +schema.set(option, value);
    +

    Valid options:

    + +

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    +new Schema({ .. }, { safe: safe })
    +

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. +By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    + +

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
    +new Schema({ .. }, { safe: safe })
    +

    option: strict

    The strict option, (enabled by default), ensures that values added to our model instance that were not specified in our schema do not get saved to the db. +NOTE: do not set to false unless you have good reason.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save() // iAmNotInTheSchema is not saved to the db
    +
    +// set to false..
    +var thingSchema = new Schema({..}, { strict: false });
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save() // iAmNotInTheSchema is now saved to the db!!
    +

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = db.model('Thing');
    +var thing = new Thing(doc, true);  // enables strict mode
    +var thing = new Thing(doc, false); // disables strict mode
    +

    The strict option may also be set to "throw" which will cause errors to be produced instead of ignoring the bad data.

    NOTE: in mongoose v2 the default was false.

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    +

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 })

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true })
    +

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { __v: 0, name: 'mongoose v3' }
    +
    +// customized versionKey
    +new Schema({..}, { versionKey: '_somethingElse' })
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    +

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false })
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'no versioning please' });
    +thing.save(); // { name: 'no versioning please' }
    +

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false })
    +var Clock = db.model('Clock', schema);
    +Clock.ensureIndexes(callback);
    +

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    + +

    Pass this option during schema construction to prevent documents from getting an auto _id created.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
    +
    +// disabled _id
    +var schema = new Schema({ name: String }, { _id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { name: 'mongodb.org' }
    +

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // '50341373e894ad16347efe01'
    +
    +// disabled id
    +var schema = new Schema({ name: String }, { id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // undefined
    +
    diff --git a/docs/3.0.x/docs/guide.jade b/docs/3.0.x/docs/guide.jade new file mode 100644 index 00000000000..1372997fee0 --- /dev/null +++ b/docs/3.0.x/docs/guide.jade @@ -0,0 +1,364 @@ +extends layout + +block content + h2 Schemas + :markdown + If you haven't yet done so, please take a minute to read the [quickstart](./index.html) to get an idea of how Mongoose works. + :markdown + If you are migrating from 2.x to 3.x please take a moment to read the [migration guide](./migration.html). + :markdown + This page covers `Schema` [definition](#definition), [plugins](#plugins), instance [methods](#methods), [statics](#statics), [indexes](#indexes), [virtuals](#virtuals) and [options](#options). Let's start with `Schema` definition. + h3#definition Defining your schema + p + | Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection. + :js + var blogSchema = new Schema({ + title: String, + author: String, + body: String, + comments: [{ body: String, date: Date }], + date: { type: Date, default: Date.now }, + hidden: Boolean, + meta: { + votes: Number, + favs: Number + } + }) + p + em + | If you want to add additional keys later, use the + a(href="./api.html#schema_Schema-add") Schema#add + | method. + p + | Each key in our + code blogSchema + | defines a property in our documents which will be cast to its associated + a(href="./api.html#schematype_SchemaType") SchemaType + |. Keys may also be assigned nested objects containing further key/type definitions + em (e.g. the `meta` property above). + | For example, we've defined a + code title + | which will be cast to the + a(href="./api.html#schema-string-js") String + | SchemaType and + code date + | which will be cast to a + code Date + | SchemaType. + p + | The permitted SchemaTypes are + ul + li String + li Number + li Date + li Buffer + li Boolean + li Mixed + li ObjectId + li Array + | Read more about them + a(href="./schematypes.html") here + | . + p + | Schemas not only define the structure of your document and casting of properties, they also define document + a(href="#methods") instance methods + |, static + a(href="#statics") Model methods + |, + a(href="#indexes") compound indexes + | and document lifecycle hooks called + a(href="./middleware.html") middleware + |. + h3#plugins Pluggable + p + | Schemas are + a(href="./plugins.html") pluggable + | which allows us to package up reusable features into + a(href="http://plugins.mongoosejs.com") plugins + | that can be shared with the community or just between your projects. + h3#methods Instance methods + p + a(href="./models.html") Models + | are just fancy + code constructor + | functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are + a(href="./documents.html") documents + |. + p + | Defining an instance method is easy. + :js + var animalSchema = new Schema({ name: String, type: String }); + + animalSchema.methods.findSimilarTypes = function (cb) { + return this.model('Animal').find({ type: this.type }, cb); + } + p + | Now all of our + code animal + | instances have a + code findSimilarTypes + | method available to it. + :js + var Animal = mongoose.model('Animal', animalSchema); + var dog = new Animal({ type: 'dog' }) + + dog.findSimilarTypes(function (err, dogs) { + console.log(dogs) // woof + }) + h3#statics Statics + p + | Adding static constructor methods to Models is simple as well. Continuing with our + code animalSchema + |: + :js + animalSchema.statics.findByName = function (name, cb) { + this.find({ name: new RegExp(name, 'i'), cb); + } + + var Animal = mongoose.model('Animal', animalSchema); + Animal.findByName('fido', function (err, animals) { + console.log(animals); + }) + h3#indexes Indexes + p + a(href="http://www.mongodb.org/display/DOCS/Indexes") Indexes + | can be defined + a(href="./api.html#schematype_SchemaType-index") at + | + a(href="./api.html#schematype_SchemaType-unique") the + | + a(href="./api.html#schematype_SchemaType-sparse") path + | + a(href="./api.html#schematype_SchemaType-expires") level + | or the + code schema + | level. Defining indexes at the schema level is necessary when defining + a(href="http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys", target="_blank") compound indexes + |. + :js + animalSchema.index({ name: 1, type: -1 }); + p + | When your application starts up, Mongoose automatically calls + code ensureIndex + | for each defined index. This behavior can be disabled by setting the + code autoIndex + | option of your schema to false. + :js + animalSchema.set('autoIndex', false) + // or + new Schema({..}, { autoIndex: false }) + p + | See also the + a(href="./api.html#model_Model-ensureIndexes") + code Model#ensureIndexes + | method. + + h3#virtuals Virtuals + :markdown + [Virtual](./api.html#schema_Schema-virtual) attributes are attributes that are convenient to have around but that do not get persisted to MongoDB. + :js + var personSchema = new Schema({ + name: { + first: String, + last: String + } + }); + + var Person = mongoose.model('Person', personSchema); + + var bad = new Person({ + name: { first: 'Walter', last: 'White' } + }); + :markdown + Suppose we want to log the full name of `bad`. We could do this manually like so: + :js + console.log(bad.name.first + ' ' + bad.name.last); // Walter White + :markdown + Or we could add a `virtual` attribute [getter](./api.html#virtualtype_VirtualType-get) to our `personSchema` so we don't need to write out this string concatenation mess each time: + :js + personSchema.virtual('name.full').get(function () { + return this.name.first + ' ' + this.name.last; + }) + :markdown + Now, when we access our virtual full name property, our getter function will be invoked and the value returned: + :js + console.log('%s is insane', bad.name.full) // Walter White is insane + :markdown + It would also be nice to be able to set `this.name.first` and `this.name.last` by setting `this.name.full`. For example, if we wanted to change `bad`'s `name.first` and `name.last` to 'Breaking' and 'Bad' respectively, it'd be nice to just: + :js + bad.name.full = 'Breaking Bad'; + :markdown + Mongoose lets you do this as well through its virtual attribute [setters](./api.html#virtualtype_VirtualType-set): + :js + personSchema.virtual('name.full').set(function (name) { + var split = name.split(' '); + this.name.first = split[0]; + this.name.last = split[1]; + }) + + ... + + mad.name.full = 'Breaking Bad'; + console.log(mad.name.first) // Breaking + :markdown + If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you. + + h3#options Options + :markdown + `Schema`s have a few configurable options which can be passed to the constructor or `set` directly: + :js + new Schema({..}, options); + + // or + + var schema = new Schema({..}); + schema.set(option, value); + + :markdown + Valid options: + + - [safe](#safe) + - [strict](#strict) + - [capped](#capped) + - [versionKey](#versionKey) + - [shardKey](#shardKey) + - [autoIndex](#autoIndex) + - [_id](#_id) + - [id](#id) + + h4#safe option: safe + :markdown + This option is passed to MongoDB with all operations and specifies if errors should be returned to our callbacks as well as tune write behavior. + + :js + var safe = true; + new Schema({ .. }, { safe: safe }) + + :markdown + By default this is set to `true` for all schemas which guarentees that any occurring error gets passed back to our callback. + By setting `safe` to something else like `{ j: 1, w: 2, wtimeout: 10000 }` we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback. + + There are other write concerns like `{ w: "majority" }` too. See the MongoDB [docs](http://www.mongodb.org/display/DOCS/getLastError+Command) for more details. + + :js + var safe = { w: "majority", wtimeout: 10000 }; + new Schema({ .. }, { safe: safe }) + + h4#strict option: strict + :markdown + The strict option, (enabled by default), ensures that values added to our model instance that were not specified in our schema do not get saved to the db. + _NOTE: do not set to false unless you have good reason._ + + :js + var thingSchema = new Schema({..}) + var Thing = db.model('Thing', schemaSchema); + var thing = new Thing({ iAmNotInTheSchema: true }); + thing.save() // iAmNotInTheSchema is not saved to the db + + // set to false.. + var thingSchema = new Schema({..}, { strict: false }); + var thing = new Thing({ iAmNotInTheSchema: true }); + thing.save() // iAmNotInTheSchema is now saved to the db!! + + :markdown + This value can be overridden at the model instance level by passing a second boolean argument: + + :js + var Thing = db.model('Thing'); + var thing = new Thing(doc, true); // enables strict mode + var thing = new Thing(doc, false); // disables strict mode + + :markdown + The `strict` option may also be set to `"throw"` which will cause errors to be produced instead of ignoring the bad data. + + :markdown + _NOTE: in mongoose v2 the default was false._ + + h4#shardKey option: shardKey + :markdown + The `shardKey` option is used when we have a [sharded MongoDB architecture](http://www.mongodb.org/display/DOCS/Sharding+Introduction). Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set. + + :js + new Schema({ .. }, { shardkey: { tag: 1, name: 1 }}) + + :markdown + _Note that Mongoose does not send the `shardcollection` command for you. You must configure your shards yourself._ + + h4#capped option: capped + :markdown + Mongoose supports MongoDBs [capped](http://www.mongodb.org/display/DOCS/Capped+Collections) collections. To specify the underlying MongoDB collection be `capped`, set the `capped` option to the maximum size of the collection in [bytes](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-size.). + :js + new Schema({..}, { capped: 1024 }) + :markdown + The `capped` option may also be set to an object if you want to pass additional options like [max](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-max) or [autoIndexId](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-autoIndexId). In this case you must explicitly pass the `size` option which is required. + :js + new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true }) + + h4#versionKey option: versionKey + :markdown + The `versionKey` is a property set on each document when first created by Mongoose. This keys value contains the internal [revision](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning) of the document. The name of this document property is configurable. The default is `__v`. If this conflicts with your application you can configure as such: + :js + var schema = new Schema({ name: 'string' }); + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'mongoose v3' }); + thing.save(); // { __v: 0, name: 'mongoose v3' } + + // customized versionKey + new Schema({..}, { versionKey: '_somethingElse' }) + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'mongoose v3' }); + thing.save(); // { _somethingElse: 0, name: 'mongoose v3' } + + :markdown + Document versioning can also be disabled by setting the `versionKey` to false. _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning)._ + :js + new Schema({..}, { versionKey: false }) + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'no versioning please' }); + thing.save(); // { name: 'no versioning please' } + + h4#autoIndex option: autoIndex + :markdown + At application startup, Mongoose sends an `ensureIndex` command for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model-ensureIndexes) method on your model. + :js + var schema = new Schema({..}, { autoIndex: false }) + var Clock = db.model('Clock', schema); + Clock.ensureIndexes(callback); + + h4#_id option: _id + :markdown + Mongoose assigns each of your schemas an `_id` field by default if one is not passed into the [Schema](/docs/api.html#schema-js) constructor. The type assiged is an [ObjectId](/docs/api.html#schema_Schema-Types) to coincide with MongoDBs default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option. + + Pass this option during schema construction to prevent documents from getting an auto `_id` created. + :js + // default behavior + var schema = new Schema({ name: String }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' } + + // disabled _id + var schema = new Schema({ name: String }, { _id: false }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p); // { name: 'mongodb.org' } + + h4#id option: id + :markdown + Mongoose assigns each of your schemas an `id` virtual getter by default which returns the documents `_id` field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an `id` getter added to your schema, you may disable it passing this option at schema construction time. + :js + // default behavior + var schema = new Schema({ name: String }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p.id); // '50341373e894ad16347efe01' + + // disabled id + var schema = new Schema({ name: String }, { id: false }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p.id); // undefined + +script. +document.body.className = 'load'; +include includes/keen diff --git a/docs/3.0.x/docs/helpers/filters.js b/docs/3.0.x/docs/helpers/filters.js new file mode 100644 index 00000000000..33546a7e805 --- /dev/null +++ b/docs/3.0.x/docs/helpers/filters.js @@ -0,0 +1,20 @@ + +var hl = require('highlight.js') + +module.exports = exports = function (jade) { + // add highlighting filter to jade + + jade.filters.js = function (str) { + str = str.replace(/\\n/g, '\n'); + var ret = hl.highlight('javascript', str).value; + var code = '
    ' + ret.replace(/\n/g, '\\n') + '
    '; + return code; + } + + jade.filters.bash = function (str) { + var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; + var code = '
    ' + ret + '
    '; + return code + } + +} diff --git a/docs/3.0.x/docs/helpers/highlight.js b/docs/3.0.x/docs/helpers/highlight.js new file mode 100644 index 00000000000..8aca9b9e222 --- /dev/null +++ b/docs/3.0.x/docs/helpers/highlight.js @@ -0,0 +1,11 @@ + +var h = require('highlight.js') + +function hl (str) { + str = str.replace(/\\n/g, '\n'); + var ret = h.highlight('javascript', str).value; + var code = '
    ' + ret+ '
    '; + return code; +} + +module.exports = hl; diff --git a/docs/3.0.x/docs/helpers/href.js b/docs/3.0.x/docs/helpers/href.js new file mode 100644 index 00000000000..e7299b1cf0d --- /dev/null +++ b/docs/3.0.x/docs/helpers/href.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str, char) { + if ('string' != typeof str) return str; + return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); +} diff --git a/docs/3.0.x/docs/helpers/klass.js b/docs/3.0.x/docs/helpers/klass.js new file mode 100644 index 00000000000..0c4a865b43b --- /dev/null +++ b/docs/3.0.x/docs/helpers/klass.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str) { + var parts = str.replace(/\.js$/, '').split('/'); + return parts.join('_'); +} diff --git a/docs/3.0.x/docs/helpers/linktype.js b/docs/3.0.x/docs/helpers/linktype.js new file mode 100644 index 00000000000..997e740f671 --- /dev/null +++ b/docs/3.0.x/docs/helpers/linktype.js @@ -0,0 +1,50 @@ + +var types = {}; +types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; +types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' +types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' +types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' +types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' +types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' +types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' +types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' +types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' +types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' + +// mongoose +types.ObjectId = '#types_objectid_ObjectId'; +types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; +types.MongooseArray = '#types_array_MongooseArray'; +types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; +types.Query = '#query-js'; +types.QueryStream = '#querystream_QueryStream'; +types.Document = '#document_Document'; +types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; +types.Document = '#document_Document'; +types.Model = '#model_Model'; +types.Connection = '#connection_Connection'; +types.Collection = '#collection_Collection'; +types.Schema = '#schema_Schema'; +types.Promise = '#promise_Promise'; +types.Mongoose = '#index_Mongoose'; +types.MongooseError = '#error_MongooseError'; +types.Type = '#schematype_SchemaType'; // ? +types.SchemaType = '#schematype_SchemaType'; +types.SchemaArray = '#schema_array_SchemaArray'; +types.Mixed = '#schema_mixed_Mixed'; +types.VirtualType = '#virtualtype_VirtualType'; +types.MongooseBuffer = '#types_buffer_MongooseBuffer'; +types.Buffer = 'http://nodejs.org/api/buffer.html'; + +module.exports= function (type) { + if (types[type]) { + return '' + type + ''; + } + return '' + type + ''; +} + +module.exports.types = types; +module.exports.type = function (str) { + if (types[str]) return types[str]; + return str; +} diff --git a/docs/3.0.x/docs/images/apps/grab b/docs/3.0.x/docs/images/apps/grab new file mode 100755 index 00000000000..ca314e9e858 --- /dev/null +++ b/docs/3.0.x/docs/images/apps/grab @@ -0,0 +1,39 @@ +#!/bin/bash + +#make sure firefox launches in the bottom right corner of the window + +# read URLs from a data file in a loop +#regex='([^[:space:]]+)[[:space:]]*(.*)' +regex='([^[:space:]]+)[|]([^|]+)[|](.*)' + +func() { + [[ $1 =~ $regex ]] + url=${BASH_REMATCH[1]} + # remove middle space, lowercase + name=`echo ${BASH_REMATCH[2]} | tr -d '[[:space:]]' | tr '[A-Z]' '[a-z]'` + desc=${BASH_REMATCH[3]} + + # send URL to the firefox session + # firefox --width 1030 --height 768 $url & + /Applications/Firefox.app/Contents/MacOS/firefox --width 1030 --height 768 $url & + echo started firefox with $url + echo preparing screencapture ... + + # take a picture after waiting a bit for the load to finish + sleep 6 + # gm import -window root -crop 1004x768+414+228 -resize 500x350 $name.png + screencapture -wo $name.png + gm convert $name.png -crop 1004x768+0+80 -resize 200x140 $name.png + echo grabbed screenshot $name.png +} + +if [ $1 ] +then + func "$1 $2" +else + while read line + do + func $line + done < urls +fi + diff --git a/docs/3.0.x/docs/images/apps/urls b/docs/3.0.x/docs/images/apps/urls new file mode 100644 index 00000000000..ca924705938 --- /dev/null +++ b/docs/3.0.x/docs/images/apps/urls @@ -0,0 +1,21 @@ +https://www.learnboost.com|LearnBoost|is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students. +http://storify.com/|Storify|lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative. +https://clickdummy.com|ClickDummy|is a rapid mockup prototyping application for designers and dummies. +http://scottyapp.com|Scotty App|allows you to create data driven backends for your apps in minutes instead of weeks. +http://geekli.st|Geeklist|is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found. +https://bozuko.com|Bozuko|is an exciting customer rewards program. +http://calllistapp.com|Call List|helps you maintain a todo list for people you need to call. +http://www.gtggolf.com|Grow The Game Golf|lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more. +http://nextdays.com/|nextdays|lets you share plans with friends and discover what is happening around you. +http://linkr.cc|Linkr|is a service for saving links for reading later. +http://www.attictv.com/|AtticTV|is Music Television (MTV) for the web. +https://localresponse.com|LocalResponse|helps marketers respond to real-time consumer intent. +http://selectvids.com|Select Vids|is a collection of amazing, funny, and creative videos for you to discover. +https://cldfy.com/|cldfy|delivers mail to your app. +http://www.sharelatex.com|ShareLatex|is a real-time LaTeX collaboration tool. +http://apps.newleafdigital.com/lists|Lists|is a service for saving links for reading later. +http://cyborgvisionapp.com/|Cyborg Vision|uses real-time facial recognition to identify your friends and show their information. +https://wavo.me/|Wavo|lets you express yourself through the songs you love. +http://seelio.com/|seelio|is a stage for college students to distinguish themselves and connect with companies. +http://todaylaunch.com/|TodayLaunch|is a free dashboard for your social media accounts. +http://st.achify.com/|Stachify| diff --git a/docs/3.0.x/docs/images/square_bg.png b/docs/3.0.x/docs/images/square_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca GIT binary patch literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.0.3Fork me on GitHub

    Getting Started

    First be sure you have MongoDB and Nodejs installed.

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. +The first thing we need to do is include mongoose in our project and open a connection.

    var mongoose = require('mongoose')
    +  , db = mongoose.createConnection('localhost', 'test');

    We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    db.on('error', console.error.bind(console, 'connection error:'));
    +db.once('open', function () {
    +  // yay!
    +});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = new mongoose.Schema({
    +    name: String
    +})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a model.

    var Kitten = db.model('Kitten', kittySchema)

    A model is a class with which we construct documents. +In this case, each document will be a kitten with properties and behaviors as declared in our schema. +Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    +console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    kittySchema.methods.speak = function () {
    +  var greeting = this.name
    +    ? 'Meow name is ' + this.name
    +    : 'I don't have a name'
    +  console.log(greeting);
    +}
    +
    +var Kitten = db.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    +fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. +Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err) {
    +  if (err) // TODO handle the error
    +  console.log('meow')
    +});

    Say time goes by and we want to display all the kittens we've seen. +We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    +  if (err) // TODO handle err
    +  console.log(kittens)
    +})

    We just logged all of the kittens in our db to the console. +If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax.

    Kitten.find({ name: /fluff/i }, callback)

    This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or api docs for more.

    diff --git a/docs/3.0.x/docs/index.jade b/docs/3.0.x/docs/index.jade new file mode 100644 index 00000000000..50388b02042 --- /dev/null +++ b/docs/3.0.x/docs/index.jade @@ -0,0 +1,119 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose Quick Start v#{package.version} + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + link(href='css/guide.css', rel='stylesheet', type='text/css') + style. + body.api + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + #content + .module + h2 Getting Started + p + em + | First be sure you have + a(href="http://www.mongodb.org/downloads") MongoDB + | and + a(href="http://nodejs.org/") Nodejs + | installed. + p + | Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. + | The first thing we need to do is include mongoose in our project and open a connection. + :js + var mongoose = require('mongoose') + , db = mongoose.createConnection('localhost', 'test'); + p We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs: + :js + db.on('error', console.error.bind(console, 'connection error:')); + db.once('open', function () { + // yay! + }); + p Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback. + p + | With Mongoose, everything is derived from a + a(href="./api.html#schema_Schema") Schema + | . Let's get a reference to it and define our kittens. + :js + var kittySchema = new mongoose.Schema({ + name: String + }) + p + | So far so good. We've got a schema with one property, + code name + | , which will be a + code String + | . The next step is compiling our schema into a + a(href="./api.html#model_Model") model + | . + :js + var Kitten = db.model('Kitten', kittySchema) + p + | A model is a class with which we construct documents. + | In this case, each document will be a kitten with properties and behaviors as declared in our schema. + | Let's create a kitten document representing the little guy we just met on the sidewalk outside: + :js + var silence = new Kitten({ name: 'Silence' }) + console.log(silence.name) // 'Silence' + p Kittens can meow, so let's take a look at how to add "speak" functionality to our documents: + :js + kittySchema.methods.speak = function () { + var greeting = this.name + ? 'Meow name is ' + this.name + : 'I don't have a name' + console.log(greeting); + } + + var Kitten = db.model('Kitten', kittySchema) + p + | Functions added to the + code methods + | property of a schema get compiled into the Model prototype and exposed on each document instance: + :js + var fluffy = new Kitten({ name: 'fluffy' }); + fluffy.speak() // "Meow name is fluffy" + p + | We have talking kittens! But we still haven't saved anything to MongoDB. + | Each document can be saved to the database by calling its + code save + | method. The first argument to the callback will be an error if any occured. + :js + fluffy.save(function (err) { + if (err) // TODO handle the error + console.log('meow') + }); + p + | Say time goes by and we want to display all the kittens we've seen. + | We can access all of the kitten documents through our Kitten model. + :js + Kitten.find(function (err, kittens) { + if (err) // TODO handle err + console.log(kittens) + }) + p + | We just logged all of the kittens in our db to the console. + | If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax. + :js + Kitten.find({ name: /fluff/i }, callback) + p + | This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback. + h3 Congratulations + p + | That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the + a(href="guide.html") guide + | , or + a(href="api.html") api docs + | for more. + script. + document.body.className = 'load'; + include includes/keen diff --git a/docs/3.0.x/docs/js/zepto.min.js b/docs/3.0.x/docs/js/zepto.min.js new file mode 100644 index 00000000000..428f84a28c5 --- /dev/null +++ b/docs/3.0.x/docs/js/zepto.min.js @@ -0,0 +1,2 @@ +/* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */ +(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.0.x/docs/layout.jade b/docs/3.0.x/docs/layout.jade new file mode 100644 index 00000000000..ab1e9553cbe --- /dev/null +++ b/docs/3.0.x/docs/layout.jade @@ -0,0 +1,25 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose #{title} v#{package.version} + block style + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + link(href='css/guide.css', rel='stylesheet', type='text/css') + body + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + #content + .module + block content + script. + document.body.className = 'load'; + include includes/keen diff --git a/docs/3.0.x/docs/middleware.html b/docs/3.0.x/docs/middleware.html new file mode 100644 index 00000000000..269aba2b32c --- /dev/null +++ b/docs/3.0.x/docs/middleware.html @@ -0,0 +1,29 @@ +Mongoose Middleware v3.0.3Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

    +There are two types of middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next

    var schema = new Schema(..);
    +schema.pre('save', function (next) {
    +  // do stuff
    +  next();
    +});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    +schema.pre('save', true, function (next, done) {
    +  // calling next kicks off the next middleware in parallel
    +  next();
    +  doAsync(done);
    +});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    +  var err = new Error('something went wrong');
    +  next(err);
    +});
    +
    +// later...
    +
    +myModel.save(function (err) {
    +  console.log(err.message) // something went wrong
    +});
    +
    diff --git a/docs/3.0.x/docs/middleware.jade b/docs/3.0.x/docs/middleware.jade new file mode 100644 index 00000000000..716d03831b4 --- /dev/null +++ b/docs/3.0.x/docs/middleware.jade @@ -0,0 +1,71 @@ +extends layout + +block content + h2 Middleware + p + | Middleware are functions which are passed control of flow during execution of + a(href="./api.html#document_Document-init") init + |, + a(href="./api.html#document_Document-validate") validate + |, + a(href="./api.html#model_Model-save") save + | and + a(href="./api.html#model_Model-remove") remove + | methods. + p + | There are two types of middleware, serial and parallel. + h4 Serial + p + | Serial middleware are executed one after another, when each middleware calls + code next + :js + var schema = new Schema(..); + schema.pre('save', function (next) { + // do stuff + next(); + }); + h4 Parallel + p + | Parallel middleware offer more fine-grained flow control. + :js + var schema = new Schema(..); + schema.pre('save', true, function (next, done) { + // calling next kicks off the next middleware in parallel + next(); + doAsync(done); + }); + p + | The hooked method, in this case + code save + |, will not be executed until + code done + | is called by each middleware. + h4 Use Cases + p + | Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas: + ul + li complex validation + li + | removing dependent documents + ul + li (removing a user removes all his blogposts) + li asynchronous defaults + li asynchronous tasks that a certain action triggers + ul + li triggering custom events + li notifications + h4 Error handling + :markdown + If any middleware calls `next` or `done` with an `Error` instance, the flow is interrupted, and the error is passed to the callback. + :js + schema.pre('save', function (next) { + var err = new Error('something went wrong'); + next(err); + }); + + // later... + + myModel.save(function (err) { + console.log(err.message) // something went wrong + }); + diff --git a/docs/3.0.x/docs/migration.html b/docs/3.0.x/docs/migration.html new file mode 100644 index 00000000000..0a053078374 --- /dev/null +++ b/docs/3.0.x/docs/migration.html @@ -0,0 +1,38 @@ +Mongoose Migration Guide v3.0.3Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    + +

    Here are the removed methods are their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    + +

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    • are now strict by default.
    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    + +

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    + +
    • $inc
    • $increment
    • $decrement
    + +

    If you really want this behavior back, include the mongoose-number module in your project.

    + +

    A good alternative is to start using the new findAndModify helpers. +Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    +...
    +Inventory.findById(id, function (err, inventory) {
    +  if (err) return handleError(err);
    +  inventory.productCount.$decrement(7);
    +  inventory.save(function (err) {
    +    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    +    if (err) return handleError(err);
    +    res.send(inventory.productCount); // 3
    +  });
    +});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    +  if (err) return handleError(err);
    +  res.send(inventory.productCount); // 3
    +});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This changes allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    diff --git a/docs/3.0.x/docs/migration.jade b/docs/3.0.x/docs/migration.jade new file mode 100644 index 00000000000..3fca606562a --- /dev/null +++ b/docs/3.0.x/docs/migration.jade @@ -0,0 +1,272 @@ +extends layout + +block append style + style. + table td { + padding-right: 15px; + } + +block content + h2 Migrating from 2.x to 3.x + :markdown + Migrating from Mongoose 2.x to 3.x brings with it [several changes](https://github.com/LearnBoost/mongoose/blob/master/History.md) to be aware of: + + h3 Query clean-up + :markdown + Many methods of the [Query](./api.html#query-js) API were nothing but aliases and have been [removed](https://github.com/LearnBoost/mongoose/commit/1149804c) in an effort to keep Mongoose clean and focused on there being as close to [one way](http://www.python.org/dev/peps/pep-0020/) of doing things as possible. If you really love all that extra noise, you can bring most of it back with [this module](https://github.com/aheckmann/mongoose-v2-compat). + + Here are the removed methods are their still existing aliases: + table + thead + tr(style='text-align:left') + th Removed + th Alternative + tbody + tr + td + code query.run + td + code query.exec + tr + td + code query.$or + td + code query.or + tr + td + code query.$nor + td + code query.nor + tr + td + code query.$gt + td + code query.gt + tr + td + code query.$gte + td + code query.gte + tr + td + code query.$lt + td + code query.lt + tr + td + code query.$lte + td + code query.lte + tr + td + code query.$ne + td + code query.ne + tr + td + code query.$in + td + code query.in + tr + td + code query.$nin + td + code query.nin + tr + td + code query.$all + td + code query.all + tr + td + code query.$regex + td + code query.regex + tr + td + code query.$size + td + code query.size + tr + td + code query.$maxDistance + td + code query.maxDistance + tr + td + code query.$mod + td + code query.mod + tr + td + code query.$near + td + code query.near + tr + td + code query.$exists + td + code query.exists + tr + td + code query.$elemMatch + td + code query.elemMatch + tr + td + code query.$within + td + code query.within + tr + td + code query.$box + td + code query.box + tr + td + code query.$center + td + code query.center + tr + td + code query.$centerSphere + td + code query.centerSphere + tr + td + code query.$slice + td + code query.slice + tr + td + code query.notEqualTo + td + code query.ne + tr + td + code query.wherein + td + code query.within + tr + td + code query.asc + td + code + | query.sort + a(href="#asc") * + tr + td + code query.desc + td + code + | query.sort + a(href="#desc") * + tr + td + code query.fields + td + code + | query.select + a(href="#fields") * + + h4#asc query#asc + :markdown + The `asc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#desc query#desc + :markdown + The `desc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#sort query#sort + :markdown + The [sort](./api.html#query_Query-sort) method of [Queries](./api.html#query-js) now accepts slightly different arguments. Read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#fields query#fields + :markdown + The `fields` method of [Query](./api.html#query-js) has been removed, it being mostly an alias for the [select](./api.html#query_Query-select) method anyway. The `select` method has slightly different arguments so read the [docs](./api.html#query_Query-select) to make sure your application is all set. + + Because of the change to the `fields` method, the field selection argument for [query.populate](./api.html#query_Query-populate) and model methods like [findById](./api.html#model_Model-findById), [find](./api.html#model_Model-find), etc, is slightly different as well (no longer accepts arrays for example), so read the [docs](./api.html#query_Query-select) to make sure your application is all set. + + h3 Connecting to ReplicaSets + :markdown + To connect to a [ReplicaSet](http://www.mongodb.org/display/DOCS/Replica+Sets) you no longer use the separate `connectSet` or `createSetConnection` methods. Both [mongoose.connect](./api.html#index_Mongoose-connect) and [mongoose.createConnection](./api.html#index_Mongoose-createConnection) are now smart enough to just do the right thing with your connection string. If you really want to bring `connectSet` and `createSetConnection` back use [this module](https://github.com/aheckmann/mongoose-v2-compat). + + h3 Schemas + :markdown + - are now [strict](./guide.html#strict) by default. + - Arrays of [object literal](./subdocs.html#altsyntax) now creates document arrays instead of arrays of [Mixed](./schematypes.html#mixed). + - Indexes are now created in [background](./guide.html#autoIndex) by default. + - Index errors are now emitted on their model instead of the connection. See issue [#984](https://github.com/LearnBoost/mongoose/issues/984). + + h3#arrays Arrays + :markdown + - [pop](./api.html#types_array_MongooseArray-pop) is now fixed causing a $set of the entire array. + - [$pop](./api.html#types_array_MongooseArray-%24pop) is now fixed and behaves just as MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the last element of the array. + - [shift](./api.html#types_array_MongooseArray-shift) is now fixed causing a $set of the entire array. + - [$shift](./api.html#types_array_MongooseArray-%24shift) is now fixed and behaves just as a [MongoDB $pop -1](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the first element of array. + - `$unshift` was removed, use [unshift](./api.html#types_array_MongooseArray-unshift) instead. + - `$addToSet` was removed, use [addToSet](./api.html#types_array_MongooseArray-addToSet) instead. + - `$pushAll` was removed, use [push](./api.html#types_array_MongooseArray-push) instead. + - `$pull` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. + - `$pullAll` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. + - `doAtomics` was changed to the [hasAtomics](./api.html#types_array_MongooseArray-hasAtomics) private method + + h3#mongoosenumber Number type + :markdown + The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused [too many problems](https://groups.google.com/d/msg/mongoose-orm/syKlN2xL1EE/FfRFhEFj4KcJ) when doing comparisons and had other bad side-effects. + + With it out of the picture, the following helper methods of MongooseNumbers are now also gone: + + - $inc + - $increment + - $decrement + + If you really want this behavior back, include the [mongoose-number](https://github.com/aheckmann/mongoose-number) module in your project. + + A good alternative is to start using the new [findAndModify](./api.html#model_Model-findOneAndUpdate) [helpers](./api.html#model_Model-findOneAndRemove). + Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber: + :js + var inventorySchema = new Schema({ productCount: Number }); + ... + Inventory.findById(id, function (err, inventory) { + if (err) return handleError(err); + inventory.productCount.$decrement(7); + inventory.save(function (err) { + // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback); + if (err) return handleError(err); + res.send(inventory.productCount); // 3 + }); + }); + :markdown + With MongooseNumber out of the picture, we'll instead use the [Account.findByIdAndUpdate](./api.html#model_Model-findByIdAndUpdate) helper: + :js + Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) { + if (err) return handleError(err); + res.send(inventory.productCount); // 3 + }); + :markdown + The `findByIdAndUpdate` helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases. + + h3#documents Documents + :markdown + - `doc#commit` is now removed, use [doc.markModified](./api.html#document_Document-markModified) instead + - [doc#modifiedPaths](./api.html#document_Document-modifiedPaths) is now a method not a getter + - `doc.modified` is now removed, use [doc.isModified](./api.html#document_Document-isModified) instead + + h4#gettercasting getter casting + :markdown + Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue [#820](https://github.com/LearnBoost/mongoose/issues/820) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). + + h4#setterorder setter order + :markdown + Values being set no longer cast until _after_ all setters have been applied. Previously the value returned from each setter was cast _before_ passing it on to the next setter. This changes allows more flexible processing of values in setters. See issue [#665](https://github.com/learnboost/mongoose/issues/665) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). + + h3#subdocs Subdocuments + :markdown + - `subdoc.parent` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parent). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). + - `subdoc.parentArray` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parentArray). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). + + h3#stringmatch String match validator + :markdown + The String SchemaType [match](./api.html#schema_string_SchemaString-match) validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the [required](./api.html#schematype_SchemaType-required) validator as well. See issue [#934](https://github.com/LearnBoost/mongoose/issues/934) and pull request [#935](https://github.com/LearnBoost/mongoose/pull/935). + + h3#version Versioning + :markdown + Documents are now transparently versioned. Read the in depth details [here](http://aaronheckmann.posterous.com/tag/versioning). diff --git a/docs/3.0.x/docs/models.html b/docs/3.0.x/docs/models.html new file mode 100644 index 00000000000..c6314be54af --- /dev/null +++ b/docs/3.0.x/docs/models.html @@ -0,0 +1,32 @@ +Mongoose Models v3.0.3Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var schema = new Schema({ name: 'string', size: 'string' });
    +var Tank = mongoose.model('Tank', schema);
    +
    +// or, if you are using separate connections
    +var db = mongoose.createConnection(..);
    +var Tank = db.model('Tank', schema);
    +

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = db.model('Tank', yourSchema);
    +
    +var small = new Tank({ size: 'small' });
    +small.save(function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +
    +// or
    +
    +Tank.create({ size: 'small' }, function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    +  if (err) return handleError(err);
    +  // removed!
    +});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, and more.

    diff --git a/docs/3.0.x/docs/models.jade b/docs/3.0.x/docs/models.jade new file mode 100644 index 00000000000..ace22950e08 --- /dev/null +++ b/docs/3.0.x/docs/models.jade @@ -0,0 +1,57 @@ +extends layout + +block content + h2 Models + :markdown + [Models](./api.html#model-js) are fancy constructors compiled from our `Schema` definitions. Instances of these models represent [documents](./documents.html) which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models. + + h3 Compiling your first model + :js + var schema = new Schema({ name: 'string', size: 'string' }); + var Tank = mongoose.model('Tank', schema); + + // or, if you are using separate connections + var db = mongoose.createConnection(..); + var Tank = db.model('Tank', schema); + + h3 Constructing documents + :markdown + [Documents](./documents.html) are instances of our model. Creating them and saving to the database is easy: + :js + var Tank = db.model('Tank', yourSchema); + + var small = new Tank({ size: 'small' }); + small.save(function (err) { + if (err) return handleError(err); + // saved! + }) + + // or + + Tank.create({ size: 'small' }, function (err) { + if (err) return handleError(err); + // saved! + }) + + h3 Querying + :markdown + Finding documents is easy with Mongoose, which supports the [rich](http://www.mongodb.org/display/DOCS/Advanced+Queries) query syntax of MongoDB. Documents can be retreived using each `models` [find](./api.html#model_Model-find), [findById](./api.html#model_Model-findById), [findOne](./api.html#model_Model-findOne), or [where](./api.html#model_Model-where) static methods. + + :js + Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback); + :markdown + See the chapter on [querying](./queries.html) for more details on how to use the [Query](./api.html#query-js) api. + h3 Removing + :markdown + Models have a static `remove` method available for removing all documents matching `conditions`. + :js + Tank.remove({ size: 'large' }, function (err) { + if (err) return handleError(err); + // removed! + }); + h3 Updating + :markdown + Each `model` has its own `update` method for modifying documents in the database without returning them to your application. See the [API](./api.html#model_Model-update) docs for more detail. + h3 Yet more + :markdown + The [API docs](./api.html#model_Model) cover many additional methods available like [count](./api.html#model_Model-count), [mapReduce](./api.html#model_Model-mapReduce), and more. diff --git a/docs/3.0.x/docs/plugins.html b/docs/3.0.x/docs/plugins.html new file mode 100644 index 00000000000..4f13420e6d3 --- /dev/null +++ b/docs/3.0.x/docs/plugins.html @@ -0,0 +1,33 @@ +Mongoose Plugins v3.0.3Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    + +

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    +module.exports = exports = function lastModifiedPlugin (schema, options) {
    +  schema.add({ lastMod: Date })
    +  
    +  schema.pre('save', function (next) {
    +    this.lastMod = new Date
    +    next()
    +  })
    +  
    +  if (options && options.index) {
    +    schema.path('lastMod').index(options.index)
    +  }
    +}
    +
    +// game-schema.js
    +var lastMod = require('./lastMod');
    +var Game = new Schema({ ... });
    +Game.plugin(lastMod, { index: true });
    +
    +// player-schema.js
    +var lastMod = require('./lastMod');
    +var Player = new Schema({ ... });
    +Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    diff --git a/docs/3.0.x/docs/plugins.jade b/docs/3.0.x/docs/plugins.jade new file mode 100644 index 00000000000..ab2ab5359a9 --- /dev/null +++ b/docs/3.0.x/docs/plugins.jade @@ -0,0 +1,38 @@ +extends layout + +block content + h2 Plugins + :markdown + Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature. + + Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each `Schema`: + + :js + // lastMod.js + module.exports = exports = function lastModifiedPlugin (schema, options) { + schema.add({ lastMod: Date }) + + schema.pre('save', function (next) { + this.lastMod = new Date + next() + }) + + if (options && options.index) { + schema.path('lastMod').index(options.index) + } + } + + // game-schema.js + var lastMod = require('./lastMod'); + var Game = new Schema({ ... }); + Game.plugin(lastMod, { index: true }); + + // player-schema.js + var lastMod = require('./lastMod'); + var Player = new Schema({ ... }); + Player.plugin(lastMod); + :markdown + We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code. + h3 Community! + :markdown + Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. diff --git a/docs/3.0.x/docs/populate.html b/docs/3.0.x/docs/populate.html new file mode 100644 index 00000000000..35a3a8807e5 --- /dev/null +++ b/docs/3.0.x/docs/populate.html @@ -0,0 +1,98 @@ +Mongoose Query Population v3.0.3Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    + +

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    +  , Schema = mongoose.Schema
    +  
    +var PersonSchema = new Schema({
    +  name    : String,
    +  age     : Number,
    +  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    +});
    +
    +var StorySchema = new Schema({
    +  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    +  title    : String,
    +  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    +});
    +
    +var Story  = mongoose.model('Story', StorySchema);
    +var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    +
    +aaron.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  var story1 = new Story({
    +    title: "Once upon a timex.",
    +    _creator: aaron._id    // assign an ObjectId
    +  });
    +  
    +  story1.save(function (err) {
    +    if (err) return handleError(err);
    +    // thats it!
    +  });
    +})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    +.findOne({ title: /timex/ })
    +.populate('_creator')
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    +})
    +

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    + +

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    +.findOne({ title: /timex/i })
    +.populate('_creator', 'name') // only return the Persons name
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  
    +  console.log('The creator is %s', story._creator.name);
    +  // prints "The creator is Aaron"
    +  
    +  console.log('The creators age is %s', story._creator.age);
    +  // prints "The creators age is null'
    +})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    +.find(...)
    +.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    + +

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    +aaron.save();

    This allows us to perform a find and populate combo:

    Person
    +.findOne({ name: 'Aaron' })
    +.populate('stories') // only works if we pushed refs to children
    +.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log(person);
    +})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    +.find({ _creator: aaron._id })
    +.populate('_creator') // not really necessary
    +.exec(function (err, stories) {
    +  if (err) return handleError(err);
    +  console.log('The stories are an array: ', stories);
    +})
    +

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    +guille.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  story._creator = guille; // or guille._id
    +  
    +  story.save(function (err) {
    +    if (err) return handleError(err);
    +    
    +    Story
    +    .findOne({ title: /timex/i })
    +    .populate('_creator', ['name'])
    +    .exec(function (err, story) {
    +      if (err) return handleError(err);
    +      
    +      console.log('The creator is %s', story._creator.name)
    +      // prints "The creator is Guillermo"
    +    })
    +  })
    +})

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    diff --git a/docs/3.0.x/docs/populate.jade b/docs/3.0.x/docs/populate.jade new file mode 100644 index 00000000000..593fb4cdce4 --- /dev/null +++ b/docs/3.0.x/docs/populate.jade @@ -0,0 +1,145 @@ +extends layout + +block content + h2 Query Population + :markdown + There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. + + `ObjectIds` can refer to another document in a collection within our database and be `populate()`d when querying: + :js + var mongoose = require('mongoose') + , Schema = mongoose.Schema + + var PersonSchema = new Schema({ + name : String, + age : Number, + stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] + }); + + var StorySchema = new Schema({ + _creator : { type: Schema.Types.ObjectId, ref: 'Person' }, + title : String, + fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }] + }); + + var Story = mongoose.model('Story', StorySchema); + var Person = mongoose.model('Person', PersonSchema); + :markdown + So far we've created two `models`. Our `Person` model has it's `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose in which model to look, in our case the `Story` model. All `_id`s we store here must be document _ids from the `Story` model. We also added a `_creator` `ObjectId` to our `Story` schema which refers to a single `Person`. + h3 Saving refs + :markdown + Saving refs to other documents works the same way you normally save objectids, just assign an `ObjectId`: + :js + var aaron = new Person({ name: 'Aaron', age: 100 }); + + aaron.save(function (err) { + if (err) return handleError(err); + + var story1 = new Story({ + title: "Once upon a timex.", + _creator: aaron._id // assign an ObjectId + }); + + story1.save(function (err) { + if (err) return handleError(err); + // thats it! + }); + }) + h3 Population + :markdown + So far we haven't done anything special. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator`: + :js + Story + .findOne({ title: /timex/ }) + .populate('_creator') + .exec(function (err, story) { + if (err) return handleError(err); + console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron" + }) + + :markdown + Populated paths are no longer set to their original `ObjectId`s, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. + + Arrays of `ObjectId` refs work the same way. Just call the [populate](./api.html#query_Query-populate) method on the query and an array of documents will be returned _in place_ of the `ObjectIds`. + + h3 Field selection + :markdown + What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: + :js + Story + .findOne({ title: /timex/i }) + .populate('_creator', 'name') // only return the Persons name + .exec(function (err, story) { + if (err) return handleError(err); + + console.log('The creator is %s', story._creator.name); + // prints "The creator is Aaron" + + console.log('The creators age is %s', story._creator.age); + // prints "The creators age is null' + }) + h3 Query conditions for populate + :markdown + What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them? + :js + Story + .find(...) + .populate('fans', null, { age: { $gte: 21 }}, { limit: 5 }) + :markdown + Done. `Conditions` and `options` for populate queries are passed as the third and fourth arguments respectively. + h3 Refs to children + :markdown + We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' on to `aaron.stories`. + + There are two perspectives to this story. First, it's nice to have `aaron` know which are his stories. + :js + aaron.stories.push(story1); + aaron.save(); + :markdown + This allows us to perform a `find` and `populate` combo: + :js + Person + .findOne({ name: 'Aaron' }) + .populate('stories') // only works if we pushed refs to children + .exec(function (err, person) { + if (err) return handleError(err); + console.log(person); + }) + :markdown + However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely `find()` the documents we are interested in. + :js + Story + .find({ _creator: aaron._id }) + .populate('_creator') // not really necessary + .exec(function (err, stories) { + if (err) return handleError(err); + console.log('The stories are an array: ', stories); + }) + + h3 Updating refs + :markdown + Now that we have a `story` we realized that the `_creator` was incorrect. We can update `ObjectId` refs the same as any other property through the magic of Mongoose's internal casting: + :js + var guille = new Person({ name: 'Guillermo' }); + guille.save(function (err) { + if (err) return handleError(err); + + story._creator = guille; // or guille._id + + story.save(function (err) { + if (err) return handleError(err); + + Story + .findOne({ title: /timex/i }) + .populate('_creator', ['name']) + .exec(function (err, story) { + if (err) return handleError(err); + + console.log('The creator is %s', story._creator.name) + // prints "The creator is Guillermo" + }) + }) + }) + h4 NOTE: + :markdown + The documents returned from calling [populate](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. diff --git a/docs/3.0.x/docs/prior.html b/docs/3.0.x/docs/prior.html new file mode 100644 index 00000000000..919a0008e27 --- /dev/null +++ b/docs/3.0.x/docs/prior.html @@ -0,0 +1,9 @@ +Mongoose v3.0.3Fork me on GitHub

    Prior Release Documentation

    diff --git a/docs/3.0.x/docs/prior.jade b/docs/3.0.x/docs/prior.jade new file mode 100644 index 00000000000..1ef7d088a72 --- /dev/null +++ b/docs/3.0.x/docs/prior.jade @@ -0,0 +1,8 @@ +extends layout + +block content + h2 Prior Release Documentation + ul + each release in releases + li + a(href=release.url)= release.version diff --git a/docs/3.0.x/docs/queries.html b/docs/3.0.x/docs/queries.html new file mode 100644 index 00000000000..b2efeab7ac4 --- /dev/null +++ b/docs/3.0.x/docs/queries.html @@ -0,0 +1,41 @@ +Mongoose Queries v3.0.3Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    + +

    When a callback function:

    + +
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    + +

    Let's take a look at what happens when passing a callback:

    var Person = db.model('Person', yourSchema);
    +
    +// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    +Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    Here we see that the query was executed immediately and the results passed to our callback. +Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    +var query = Person.findOne({ 'name.last': 'Ghost' });
    +
    +// selecting the `name` and `occupation` fields
    +query.select('name occupation');
    +
    +// execute the query at a later time
    +query.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    +.find({ occupation: /host/ })
    +.where('name.last').equals('Ghost')
    +.where('age').gt(17).lt(66)
    +.where('likes').in(['vaporizing', 'talking'])
    +.limit(10)
    +.sort('-occupation')
    +.select('name occupation')
    +.exec(callback);
    +

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

    diff --git a/docs/3.0.x/docs/queries.jade b/docs/3.0.x/docs/queries.jade new file mode 100644 index 00000000000..488452d2cf5 --- /dev/null +++ b/docs/3.0.x/docs/queries.jade @@ -0,0 +1,59 @@ +extends layout + +block content + h2 Queries + :markdown + Documents can be retrieved through several static helper methods of [models](./models.html). + :markdown + Any [model](./api.html#model_Model) method which [involves](./api.html#model_Model-find) [specifying](./api.html#model_Model-findById) [query](./api.html#model_Model-count) [conditions](./api.html#model_Model-update) can be executed two ways: + + When a `callback` function: + + - is passed, the operation will be executed immediately with the results passed to the callback. + - is not passed, an instance of [Query](./api.html#query-js) is returned, which provides a special `QueryBuilder` interface for you. + + Let's take a look at what happens when passing a `callback`: + :js + var Person = db.model('Person', yourSchema); + + // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields + Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { + if (err) return handleError(err); + console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. + }) + :markdown + Here we see that the query was executed immediately and the results passed to our callback. + Now let's look at what happens when no `callback` is passed: + :js + // find each person with a last name matching 'Ghost' + var query = Person.findOne({ 'name.last': 'Ghost' }); + + // selecting the `name` and `occupation` fields + query.select('name occupation'); + + // execute the query at a later time + query.exec(function (err, person) { + if (err) return handleError(err); + console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. + }) + :markdown + An instance of [Query](./api.html#query-js) was returned which allows us to build up our query. Taking this example further: + :js + Person + .find({ occupation: /host/ }) + .where('name.last').equals('Ghost') + .where('age').gt(17).lt(66) + .where('likes').in(['vaporizing', 'talking']) + .limit(10) + .sort('-occupation') + .select('name occupation') + .exec(callback); + + h3#refs References to other documents + :markdown + There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. Read more [here](./populate.html). + + h3 Streaming + :markdown + Queries can be [streamed](http://nodejs.org/api/stream.html) from MongoDB to your application as well. Simply call the query's [stream](./api.html#query_Query-stream) method instead of [exec](./api.html#query_Query-exec) to return an instance of [QueryStream](./api.html#query_Query-stream). + diff --git a/docs/3.0.x/docs/releases b/docs/3.0.x/docs/releases new file mode 100644 index 00000000000..e17ae757977 --- /dev/null +++ b/docs/3.0.x/docs/releases @@ -0,0 +1 @@ +2.7.x diff --git a/docs/3.0.x/docs/schematypes.html b/docs/3.0.x/docs/schematypes.html new file mode 100644 index 00000000000..6e57f877b45 --- /dev/null +++ b/docs/3.0.x/docs/schematypes.html @@ -0,0 +1,67 @@ +Mongoose SchemaTypes v3.0.3Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    +  name:    String,
    +  binary:  Buffer,
    +  living:  Boolean,
    +  updated: { type: Date, default: Date.now },
    +  age:     { type: Number, min: 18, max: 65 },
    +  mixed:   Schema.Types.Mixed,
    +  _someId: Schema.Types.ObjectId,
    +  array:      [],
    +  ofString:   [String],
    +  ofNumber:   [Number],
    +  ofDates:    [Date],
    +  ofBuffer:   [Buffer],
    +  ofBoolean:  [Boolean],
    +  ofMixed:    [Schema.Types.Mixed],
    +  ofObjectId: [Schema.Types.ObjectId],
    +  nested: {
    +    stuff: { type: String, lowercase: true, trim: true }
    +  }
    +})
    +
    +// example use
    +
    +var Thing = mongoose.model('Thing', schema);
    +
    +var m = new Thing;
    +m.name = 'Statue of Liberty';
    +m.age = 125;
    +m.updated = new Date;
    +m.binary = new Buffer(0);
    +m.living = false;
    +m.mixed = {[ any: { thing: 'i want' } ]};
    +m.markModified('mixed');
    +m._someId = new mongoose.Types.ObjectId;
    +m.array.push(1);
    +m.ofString.push("strings!");
    +m.ofNumber.unshift(1,2,3,4);
    +m.ofDates.addToSet(new Date);
    +m.ofBuffer.pop();
    +m.ofMixed = [1, [], 'three', { four: 5 }];
    +m.nested.stuff = 'good';
    +m.save(callback);
    +

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    +var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    +person.markModified('anything');
    +person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    +var ObjectId = mongoose.Schema.Types.ObjectId;
    +var Car = new Schema({ driver: ObjectId });
    +// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    +var ToyBox = new Schema({
    +  toys: [ToySchema],
    +  buffers: [Buffer],
    +  string:  [String],
    +  numbers: [Number]
    +  // ... etc
    +});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    +var Empty2 = new Schema({ any: Array });
    +var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    +var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    diff --git a/docs/3.0.x/docs/schematypes.jade b/docs/3.0.x/docs/schematypes.jade new file mode 100644 index 00000000000..c787a25fdc9 --- /dev/null +++ b/docs/3.0.x/docs/schematypes.jade @@ -0,0 +1,142 @@ +extends layout + +block content + h2 SchemaTypes + p + | SchemaTypes handle definition of path + a(href="./api.html#schematype_SchemaType-default") defaults + |, + a(href="./api.html#schematype_SchemaType-validate") validation + |, + a(href="./api.html#schematype_SchemaType-get") getters + |, + a(href="./api.html#schematype_SchemaType-set") setters + |, + a(href="./api.html#schematype_SchemaType-select") field selection defaults + | for + a(href="./api.html#query-js") queries + | and other general characteristics for + a(href="./api.html#schema-string-js") Strings + | and + a(href="./api.html#schema-number-js") Numbers + |. Check out their respective API documentation for more detail. + p + | Following are all valid + a(href="./api.html#schema_Schema-Types") Schema Types + |. + ul + li String + li Number + li Date + li Buffer + li Boolean + li Mixed + li ObjectId + li Array + h4 Example + :js + var schema = new Schema({ + name: String, + binary: Buffer, + living: Boolean, + updated: { type: Date, default: Date.now }, + age: { type: Number, min: 18, max: 65 }, + mixed: Schema.Types.Mixed, + _someId: Schema.Types.ObjectId, + array: [], + ofString: [String], + ofNumber: [Number], + ofDates: [Date], + ofBuffer: [Buffer], + ofBoolean: [Boolean], + ofMixed: [Schema.Types.Mixed], + ofObjectId: [Schema.Types.ObjectId], + nested: { + stuff: { type: String, lowercase: true, trim: true } + } + }) + + // example use + + var Thing = mongoose.model('Thing', schema); + + var m = new Thing; + m.name = 'Statue of Liberty'; + m.age = 125; + m.updated = new Date; + m.binary = new Buffer(0); + m.living = false; + m.mixed = {[ any: { thing: 'i want' } ]}; + m.markModified('mixed'); + m._someId = new mongoose.Types.ObjectId; + m.array.push(1); + m.ofString.push("strings!"); + m.ofNumber.unshift(1,2,3,4); + m.ofDates.addToSet(new Date); + m.ofBuffer.pop(); + m.ofMixed = [1, [], 'three', { four: 5 }]; + m.nested.stuff = 'good'; + m.save(callback); + + h3 Usage notes: + h4#mixed Mixed + p An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent: + :js + var Any = new Schema({ any: {} }); + var Any = new Schema({ any: Schema.Types.Mixed }); + p + | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the + code .markModified(path) + | method of the document passing the path to the Mixed type you just changed. + :js + person.anything = { x: [3, 4, { y: "changed" }] }; + person.markModified('anything'); + person.save(); // anything will now get saved + h4#objectids ObjectIds + p + | To specify a type of ObjectId, use + code Schema.Types.ObjectId + | in your declaration. + :js + var mongoose = require('mongoose'); + var ObjectId = mongoose.Schema.Types.ObjectId; + var Car = new Schema({ driver: ObjectId }); + // or just Schema.ObjectId for backwards compatibility with v2 + h4#arrays Arrays + p + | Provide creation of arrays of + a(href="./api.html#schema_Schema-Types") SchemaTypes + | or + a(href="./subdocs.html") Sub-Documents + |. + :js + var ToySchema = new Schema({ name: String }); + var ToyBox = new Schema({ + toys: [ToySchema], + buffers: [Buffer], + string: [String], + numbers: [Number] + // ... etc + }); + p + | Note: specifying an empty array is equivalent to + code Mixed + |. The following all create arrays of + code Mixed + |: + :js + var Empty1 = new Schema({ any: [] }); + var Empty2 = new Schema({ any: Array }); + var Empty3 = new Schema({ any: [Schema.Types.Mixed] }); + var Empty4 = new Schema({ any: [{}] }); + h3#customtypes Creating Custom Types + p + | Mongoose can also be extended with custom SchemaTypes. Search the + a(href="http://plugins.mongoosejs.com") plugins + | site for compatible types like + a(href="https://github.com/aheckmann/mongoose-long") mongoose-long + | and + a(href="https://github.com/aheckmann/mongoose-number") other + | + a(href="https://github.com/bnoguchi/mongoose-types") types + |. diff --git a/docs/3.0.x/docs/source/_docs b/docs/3.0.x/docs/source/_docs new file mode 100644 index 00000000000..483b17b58c8 --- /dev/null +++ b/docs/3.0.x/docs/source/_docs @@ -0,0 +1,15928 @@ + +### lib/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = require('./connectionstate')", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "require('./connectionstate')", + "string": "STATES" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the collection" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "conn", + "description": "A MongooseConnection instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "optional collection options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", + "summary": "

    Abstract Collection constructor

    ", + "body": "

    This is the base class that drivers inherit from and implement.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", + "ctx": { + "type": "function", + "name": "Collection", + "string": "Collection()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "name" + } + ], + "description": { + "full": "

    The collection name

    ", + "summary": "

    The collection name

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.name;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "conn" + } + ], + "description": { + "full": "

    The Connection instance

    ", + "summary": "

    The Connection instance

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.conn;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database connects

    ", + "summary": "

    Called when the database connects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onOpen", + "string": "Collection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database disconnects

    ", + "summary": "

    Called when the database disconnects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onClose", + "string": "Collection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the method to queue" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method when executed" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Queues a method for later execution when its
    database connection opens.

    ", + "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "addQueue", + "string": "Collection.prototype.addQueue()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes all queued methods and clears the queue.

    ", + "summary": "

    Executes all queued methods and clears the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "doQueue", + "string": "Collection.prototype.doQueue()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "ensureIndex", + "string": "Collection.prototype.ensureIndex()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findAndModify", + "string": "Collection.prototype.findAndModify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findOne", + "string": "Collection.prototype.findOne()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "find", + "string": "Collection.prototype.find()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "insert", + "string": "Collection.prototype.insert()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "save", + "string": "Collection.prototype.save()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "update", + "string": "Collection.prototype.update()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "getIndexes", + "string": "Collection.prototype.getIndexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "mapReduce", + "string": "Collection.prototype.mapReduce()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Collection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Collection", + "string": "module.exports" + } + } +] +### lib/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , assert =require('assert')", + "ctx": { + "type": "declaration", + "name": "url", + "value": "require('url')", + "string": "url" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Protocol prefix regexp.

    ", + "summary": "

    Protocol prefix regexp.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", + "ctx": { + "type": "declaration", + "name": "rgxProtocol", + "value": "/^(?:.)+:\\/\\//", + "string": "rgxProtocol" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "a mongoose instance" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." + }, + { + "type": "event", + "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." + }, + { + "type": "event", + "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." + }, + { + "type": "event", + "string": "`disconnecting`: Emitted when `connection.close()` was executed." + }, + { + "type": "event", + "string": "`disconnected`: Emitted after getting disconnected from the db." + }, + { + "type": "event", + "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." + }, + { + "type": "event", + "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." + }, + { + "type": "event", + "string": "`error`: Emitted when an error occurs on this connection." + }, + { + "type": "event", + "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", + "summary": "

    Connection constructor

    ", + "body": "

    For practical reasons, a Connection equals a Db.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", + "ctx": { + "type": "function", + "name": "Connection", + "string": "Connection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter

    ", + "summary": "

    Inherit from EventEmitter

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Connection", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Connection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readyState" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", + "summary": "

    Connection ready state

    ", + "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" + }, + { + "tags": [ + { + "type": "property", + "string": "collections" + } + ], + "description": { + "full": "

    A hash of the collections associated with this connection

    ", + "summary": "

    A hash of the collections associated with this connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collections;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    The mongodb.Db instance, set when the connection is opened

    ", + "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.db;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "connection_string", + "description": "mongodb://uri or the host to which you are connecting" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[port]", + "description": "database port" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n uri = url.parse(host);\n host = uri.hostname;\n port = uri.port || 27017;\n database = uri.pathname && uri.pathname.replace(/\\//g, '');\n }\n\n this.options = this.defaultOptions(options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing connection hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing connection database.'), callback);\n return this;\n }\n\n // handle authentication\n if (uri && uri.auth) {\n var auth = uri.auth.split(':');\n this.user = auth[0];\n this.pass = auth[1];\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n // user/pass options\n } else if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "open", + "string": "Connection.prototype.open()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "uris", + "description": "comma-separated mongodb:// `URI`s" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name if not included in `uris`" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "passed to the internal driver" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connects to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options are passed to the internal driver connection object.

    ", + "summary": "

    Connects to a replica set.

    ", + "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options are passed to the internal driver connection object.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n var uris = uris.split(',')\n , self = this;\n\n switch (arguments.length) {\n case 3:\n this.name = database;\n if ('function' === typeof options) callback = options, options = {};\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n this.options = options = this.defaultOptions(options);\n\n if (uris.length < 2) {\n this.error(new Error('Please provide comma-separated URIs'), callback);\n return this;\n }\n\n this.replica = true;\n this.host = [];\n this.port = [];\n\n uris.forEach(function (uri) {\n // handle missing protocols\n if (!rgxProtocol.test(uri))\n uri = 'mongodb://' + uri;\n\n var uri = url.parse(uri);\n\n self.host.push(uri.hostname);\n self.port.push(uri.port || 27017);\n\n if (!self.name && uri.pathname && uri.pathname.replace(/\\//g, ''))\n self.name = uri.pathname.replace(/\\//g, '');\n\n if (!self.user && uri.auth) {\n var auth = uri.auth.split(':');\n self.user = auth[0];\n self.pass = auth[1];\n }\n });\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "openSet", + "string": "Connection.prototype.openSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "optional" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", + "summary": "

    error

    ", + "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "error", + "string": "Connection.prototype.error()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "_open", + "string": "Connection.prototype._open()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection is opened

    ", + "summary": "

    Called when the connection is opened

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onOpen", + "string": "Connection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "self" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "close", + "string": "Connection.prototype.close()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onClose", + "string": "Connection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "of the collection" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional collection options" + }, + { + "type": "return", + "types": [ + "Collection" + ], + "description": "collection instance" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retrieves a collection, creating it if not cached.

    ", + "summary": "

    Retrieves a collection, creating it if not cached.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "collection", + "string": "Connection.prototype.collection()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "the model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "a schema. necessary when defining a model" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name of mongodb collection (optional) if not given it will be induced from model name" + }, + { + "type": "see", + "local": "Mongoose#model #index_Mongoose-model", + "visibility": "Mongoose#model" + }, + { + "type": "return", + "types": [ + "Model" + ], + "description": "The compiled model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    ", + "summary": "

    Defines or retrieves a model.

    ", + "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.model = function (name, schema, collection) {\n if (!this.models[name]) {\n var model = this.base.model(name, schema, collection, true)\n , Model\n\n if (this != model.prototype.db) {\n // subclass model using this connection and collection name\n Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model))\n return new Model(doc, fields, skipId);\n model.call(this, doc, fields, skipId);\n };\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = this;\n\n // collection name discovery\n if ('string' === typeof schema) {\n collection = schema;\n }\n\n if (!collection) {\n collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);\n }\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n Model.prototype.collection = this.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n }\n\n this.models[name] = Model || model;\n }\n\n return this.models[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "model", + "string": "Connection.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "level", + "description": "either off (0), slow (1), or all (2)" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[ms]", + "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Set profiling level.

    ", + "summary": "

    Set profiling level.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "setProfiling", + "string": "Connection.prototype.setProfiling()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Prepares default connection options.

    ", + "summary": "

    Prepares default connection options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.defaultOptions = function (options) {\n var o = options || {};\n\n o.server = o.server || {};\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n o.db = o.db || {};\n o.db.forceServerObjectId = false;\n\n return o;\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "defaultOptions", + "string": "Connection.prototype.defaultOptions()" + } + }, + { + "tags": [], + "description": { + "full": "

    Noop.

    ", + "summary": "

    Noop.

    ", + "body": "" + }, + "ignore": true, + "code": "function noop () {}", + "ctx": { + "type": "function", + "name": "noop", + "string": "noop()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", + "ctx": { + "type": "property", + "receiver": "Connection", + "name": "STATES", + "value": "STATES", + "string": "Connection.STATES" + } + } +] +### lib/connectionstate.js +[ + { + "tags": [], + "description": { + "full": "

    Connection states

    ", + "summary": "

    Connection states

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "module.exports = exports = Object.create(null)", + "string": "STATES" + } + } +] +### lib/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the values to set" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "the fields which were selected in the query returning this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "bool, should we auto create an ObjectId _id" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." + }, + { + "type": "event", + "string": "`save`: Emitted when the document is successfully saved" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document constructor.

    ", + "summary": "

    Document constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", + "ctx": { + "type": "function", + "name": "Document", + "string": "Document()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Document.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "schema" + } + ], + "description": { + "full": "

    The documents schema.

    ", + "summary": "

    The documents schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.schema;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "isNew" + } + ], + "description": { + "full": "

    Boolean flag specifying if the document is new.

    ", + "summary": "

    Boolean flag specifying if the document is new.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isNew;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "local": "Schema options /docs/guide.html#options", + "visibility": "Schema" + }, + { + "type": "property", + "string": "id" + } + ], + "description": { + "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", + "summary": "

    The string version of this documents _id.

    ", + "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.id;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "errors" + } + ], + "description": { + "full": "

    Hash containing current validation errors.

    ", + "summary": "

    Hash containing current validation errors.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.errors;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Builds the default doc structure

    ", + "summary": "

    Builds the default doc structure

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_buildDoc", + "string": "Document.prototype._buildDoc()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", + "summary": "

    Initializes the document without setters or marking anything modified.

    ", + "body": "

    Called internally after a document is returned from mongodb.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init');\n if (fn) fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "init", + "string": "Document.prototype.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "self", + "description": "document instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "raw mongodb doc" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "object we are initializing" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Init helper.

    ", + "summary": "

    Init helper.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", + "ctx": { + "type": "function", + "name": "init", + "string": "init()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", + "summary": "

    Stores the current values of the shard keys.

    ", + "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_storeShard", + "string": "Document.prototype._storeShard()" + } + }, + { + "tags": [], + "description": { + "full": "

    Set up middleware support

    ", + "summary": "

    Set up middleware support

    ", + "body": "" + }, + "ignore": true, + "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    ", + "summary": "

    Sends an update command with this document _id as the query selector.

    ", + "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "update", + "string": "Document.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "path", + "description": "path or object of key/vals to set" + }, + { + "type": "param", + "types": [ + "Any" + ], + "name": "val", + "description": "the value to set" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for \"on-the-fly\" attributes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    ", + "summary": "

    Sets the value of a path, or many paths.

    ", + "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.set = function (path, val, type) {\n var constructing = true === type\n , adhoc = type && true !== type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n if (null != path[key] && 'Object' === path[key].constructor.name\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n pathtype = this.schema.pathType(prefix + key);\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "set", + "string": "Document.prototype.set()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {\n if (this.isNew) {\n this.markModified(pathToMark);\n } else {\n\n priorVal || (priorVal = this.get(path));\n\n if (!this.isDirectModified(pathToMark)) {\n if (undefined === val && !this.isSelected(path)) {\n // special case:\n // when a path is not selected in a query its initial\n // value will be undefined.\n this.markModified(pathToMark, priorVal);\n } else if (undefined === val && path in this._activePaths.states.default) {\n // do nothing\n // unsetting the default value which was never saved\n } else if (!deepEqual(val, priorVal)) {\n this.markModified(pathToMark, priorVal);\n } else if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // special case:\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n this.markModified(pathToMark, priorVal);\n }\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_set", + "string": "Document.prototype._set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets a raw value from a path (no getters)

    ", + "summary": "

    Gets a raw value from a path (no getters)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "getValue", + "string": "Document.prototype.getValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "setValue", + "string": "Document.prototype.setValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for on-the-fly attributes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", + "summary": "

    Returns the value of a path.

    ", + "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "get", + "string": "Document.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns the schematype for the given path.

    ", + "summary": "

    Returns the schematype for the given path.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_path", + "string": "Document.prototype._path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to mark modified" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", + "summary": "

    Marks the path as having pending changes to write to the db.

    ", + "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "markModified", + "string": "Document.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "function to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope with which to call fn" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "try", + "string": "Document.prototype.try()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the list of paths that have been modified.

    ", + "summary": "

    Returns the list of paths that have been modified.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "modifiedPaths", + "string": "Document.prototype.modifiedPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", + "summary": "

    Returns true if this document was modified, else false.

    ", + "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isModified", + "string": "Document.prototype.isModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", + "summary": "

    Returns true if path was directly set and modified, else false.

    ", + "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isDirectModified", + "string": "Document.prototype.isDirectModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was initialized.

    ", + "summary": "

    Checks if path was initialized.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isInit", + "string": "Document.prototype.isInit()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", + "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", + "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isSelected", + "string": "Document.prototype.isSelected()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "cb", + "description": "called after validation completes, passing an error if one occurred" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", + "summary": "

    Executes registered validation rules for this document.

    ", + "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n cb(err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "validate", + "string": "Document.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "the error which states the reason `path` was invalid" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "invalidate", + "string": "Document.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Resets the internal modified state of this document.

    ", + "summary": "

    Resets the internal modified state of this document.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return (val && val instanceof DocumentArray && val.length);\n })\n .forEach(function (array) {\n array.forEach(function (doc) {\n doc._reset();\n });\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_reset", + "string": "Document.prototype._reset()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns this documents dirty paths / vals.

    ", + "summary": "

    Returns this documents dirty paths / vals.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_dirty", + "string": "Document.prototype._dirty()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compiles schemas.

    ", + "summary": "

    Compiles schemas.

    ", + "body": "" + }, + "ignore": true, + "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", + "ctx": { + "type": "function", + "name": "compile", + "string": "compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Defines the accessor named prop on the incoming prototype.

    ", + "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", + "body": "" + }, + "ignore": true, + "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(v, path);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", + "ctx": { + "type": "function", + "name": "define", + "string": "define()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Assigns/compiles schema into this documents prototype.

    ", + "summary": "

    Assigns/compiles schema into this documents prototype.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_setSchema", + "string": "Document.prototype._setSchema()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register default hooks

    ", + "summary": "

    Register default hooks

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return (val && val instanceof DocumentArray && val.length);\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n subdocs += array.length;\n array.forEach(function (value) {\n if (error) return;\n\n value.save(function (err) {\n if (error) return;\n\n if (err) {\n error = true;\n self._validationError = undefined;\n return next(err);\n }\n\n --subdocs || next();\n });\n });\n });\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_registerHooks", + "string": "Document.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Registers an error

    ", + "summary": "

    Registers an error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_error", + "string": "Document.prototype._error()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes methods queued from the Schema definition

    ", + "summary": "

    Executes methods queued from the Schema definition

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_doQueue", + "string": "Document.prototype._doQueue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "js object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this document into a plain javascript object

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    ", + "summary": "

    Converts this document into a plain javascript object

    ", + "body": "

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toObject", + "string": "Document.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "json", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "either `virtuals` or `paths`" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "`json`" + } + ], + "description": { + "full": "

    Applies virtuals properties to json.

    ", + "summary": "

    Applies virtuals properties to json.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", + "ctx": { + "type": "function", + "name": "applyGetters", + "string": "applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "same options as Document#toObject" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "see", + "local": "Document#toObject", + "visibility": "Document#toObject" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", + "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toJSON", + "string": "Document.prototype.toJSON()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "inspect", + "string": "Document.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "toString" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toString = Document.prototype.inspect;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "toString", + "value": "Document.prototype.inspect", + "string": "Document.prototypetoString" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "a document to compare" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", + "summary": "

    Returns true if the Document stores the same data as doc.

    ", + "body": "

    Documents are considered equal when they have matching _ids.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "equals", + "string": "Document.prototype.equals()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", + "ctx": { + "type": "property", + "receiver": "Document", + "name": "ValidationError", + "value": "ValidationError", + "string": "Document.ValidationError" + } + } +] +### lib/drivers/node-mongodb-native/binary.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require('mongodb').BSONPure.Binary", + "string": "Binary" + } + } +] +### lib/drivers/node-mongodb-native/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", + "ctx": { + "type": "declaration", + "name": "MongooseCollection", + "value": "require('../../collection')", + "string": "MongooseCollection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Collection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", + "summary": "

    A node-mongodb-native collection implementation.

    ", + "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", + "ctx": { + "type": "function", + "name": "NativeCollection", + "string": "NativeCollection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from abstract Collection.

    ", + "summary": "

    Inherit from abstract Collection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "__proto__", + "value": "MongooseCollection.prototype", + "string": "NativeCollection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection opens.

    ", + "summary": "

    Called when the connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onOpen", + "string": "NativeCollection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onClose", + "string": "NativeCollection.prototype.onClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Copy the collection methods and make them subject to queues

    ", + "summary": "

    Copy the collection methods and make them subject to queues

    ", + "body": "" + }, + "ignore": true, + "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", + "ctx": { + "type": "function", + "name": "print", + "string": "print()" + } + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n } else if ('Date' === x[key].constructor.name) {\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", + "ctx": { + "type": "function", + "name": "format", + "string": "format()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "method", + "string": "getIndexes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retreives information about this collections indexes.

    ", + "summary": "

    Retreives information about this collections indexes.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "getIndexes", + "value": "NativeCollection.prototype.indexInformation", + "string": "NativeCollection.prototypegetIndexes" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeCollection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeCollection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", + "ctx": { + "type": "declaration", + "name": "MongooseConnection", + "value": "require('../../connection')", + "string": "MongooseConnection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Connection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native connection implementation.

    ", + "summary": "

    A node-mongodb-native connection implementation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", + "ctx": { + "type": "function", + "name": "NativeConnection", + "string": "NativeConnection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Connection.

    ", + "summary": "

    Inherits from Connection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeConnection", + "name": "__proto__", + "value": "MongooseConnection.prototype", + "string": "NativeConnection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, Number(this.port), this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpen", + "string": "NativeConnection.prototype.doOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", + "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", + "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , ports = this.port\n , self = this\n\n this.host.forEach(function (host, i) {\n servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));\n });\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpenSet", + "string": "NativeConnection.prototype.doOpenSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doClose", + "string": "NativeConnection.prototype.doClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeConnection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeConnection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/objectid.js +[ + { + "tags": [ + { + "type": "constructor", + "string": "NodeMongoDbObjectId" + }, + { + "type": "see", + "local": "ObjectId", + "visibility": "ObjectId" + } + ], + "description": { + "full": "

    node-mongodb-native ObjectId

    ", + "summary": "

    node-mongodb-native ObjectId

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require('mongodb').BSONPure.ObjectID", + "string": "ObjectId" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", + "ctx": { + "type": "declaration", + "name": "ObjectIdToString", + "value": "ObjectId.toString.bind(ObjectId)", + "string": "ObjectIdToString" + } + } +] +### lib/error.js +[ + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" + } + ], + "description": { + "full": "

    Mongoose error

    ", + "summary": "

    Mongoose error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", + "ctx": { + "type": "function", + "name": "MongooseError", + "string": "MongooseError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Error.

    ", + "summary": "

    Inherits from Error.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseError.prototype.__proto__ = Error.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseError", + "name": "__proto__", + "value": "Error.prototype", + "string": "MongooseError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseError", + "string": "module.exports" + } + } +] +### lib/errors/cast.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casting Error constructor.

    ", + "summary": "

    Casting Error constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", + "ctx": { + "type": "function", + "name": "CastError", + "string": "CastError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "CastError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "CastError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "CastError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = CastError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "CastError", + "string": "module.exports" + } + } +] +### lib/errors/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document Error

    ", + "summary": "

    Document Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", + "ctx": { + "type": "function", + "name": "DocumentError", + "string": "DocumentError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "DocumentError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = DocumentError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = DocumentError", + "string": "module.exports" + } + } +] +### lib/errors/validation.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "instance", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    Document Validation Error

    ", + "summary": "

    Document Validation Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", + "ctx": { + "type": "function", + "name": "ValidationError", + "string": "ValidationError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Console.log helper

    ", + "summary": "

    Console.log helper

    ", + "body": "" + }, + "ignore": false, + "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", + "ctx": { + "type": "method", + "constructor": "ValidationError", + "name": "toString", + "string": "ValidationError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidationError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidationError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = ValidationError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = ValidationError", + "string": "module.exports" + } + } +] +### lib/errors/validator.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Schema validator error

    ", + "summary": "

    Schema validator error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", + "ctx": { + "type": "function", + "name": "ValidatorError", + "string": "ValidatorError()" + } + }, + { + "tags": [], + "description": { + "full": "

    toString helper

    ", + "summary": "

    toString helper

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", + "ctx": { + "type": "method", + "constructor": "ValidatorError", + "name": "toString", + "string": "ValidatorError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError

    ", + "summary": "

    Inherits from MongooseError

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidatorError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidatorError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ValidatorError", + "string": "module.exports" + } + } +] +### lib/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", + "summary": "

    Mongoose constructor.

    ", + "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", + "ctx": { + "type": "function", + "name": "Mongoose", + "string": "Mongoose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", + "summary": "

    Sets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "set", + "string": "Mongoose.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "method", + "string": "get" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", + "summary": "

    Gets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.get = Mongoose.prototype.set;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "get", + "value": "Mongoose.prototype.set", + "string": "Mongoose.prototypeget" + } + }, + { + "tags": [], + "description": { + "full": "

    ReplSet connection string check.

    ", + "summary": "

    ReplSet connection string check.

    ", + "body": "" + }, + "ignore": true, + "code": "var rgxReplSet = /^.+,.+$/;", + "ctx": { + "type": "declaration", + "name": "rgxReplSet", + "value": "/^.+,.+$/", + "string": "rgxReplSet" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[uri]", + "description": "a mongodb:// URI" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "the created Connection object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Connection instance.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://localhost:port/database');\n\n// replica sets\ndb = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port);\n
    ", + "summary": "

    Creates a Connection instance.

    ", + "body": "

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://localhost:port/database');\n\n// replica sets\ndb = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "createConnection", + "string": "Mongoose.prototype.createConnection()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Mongoose#createConnection", + "visibility": "Mongoose#createConnection" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    ", + "summary": "

    Opens the default mongoose connection.

    ", + "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "connect", + "string": "Mongoose.prototype.connect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "called after all connection close." + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Disconnects all connections.

    ", + "summary": "

    Disconnects all connections.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "disconnect", + "string": "Mongoose.prototype.disconnect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name (optional, induced from model name)" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipInit]", + "description": "whether to skip initialization (defaults to false)" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    ", + "summary": "

    Defines a model or retrieves it.

    ", + "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n // normalize collection\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // look up models for the collection\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n this.modelSchemas[name] = schema;\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n } else {\n throw new Error('Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)');\n }\n }\n\n if (!this.models[name]) {\n schema || (schema = this.modelSchemas[name]);\n collection || (collection = schema.set('collection') || format(name));\n\n var model = Model.compile(name\n , this.modelSchemas[name]\n , collection\n , this.connection\n , this);\n\n if (!skipInit) model.init();\n\n this.models[name] = model;\n }\n\n return this.models[name];\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "model", + "string": "Mongoose.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "plugin callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "optional options" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", + "summary": "

    Declares a global plugin executed on all Schemas.

    ", + "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "plugin", + "string": "Mongoose.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "connection" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", + "summary": "

    The default connection of the mongoose module.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" + }, + { + "tags": [], + "description": { + "full": "

    Driver depentend APIs

    ", + "summary": "

    Driver depentend APIs

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Connection

    ", + "summary": "

    Connection

    ", + "body": "" + }, + "ignore": true, + "code": "var Connection = require(driver + '/connection');", + "ctx": { + "type": "declaration", + "name": "Connection", + "value": "require(driver + '/connection')", + "string": "Connection" + } + }, + { + "tags": [], + "description": { + "full": "

    Collection

    ", + "summary": "

    Collection

    ", + "body": "" + }, + "ignore": true, + "code": "var Collection = require(driver + '/collection');", + "ctx": { + "type": "declaration", + "name": "Collection", + "value": "require(driver + '/collection')", + "string": "Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The exports object is an instance of Mongoose.

    ", + "summary": "

    The exports object is an instance of Mongoose.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = new Mongoose", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Collection constructor

    ", + "summary": "

    The Mongoose Collection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Collection = Collection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Collection", + "value": "Collection", + "string": "mongoose.Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Connection constructor

    ", + "summary": "

    The Mongoose Connection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Connection = Connection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Connection", + "value": "Connection", + "string": "mongoose.Connection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose version

    ", + "summary": "

    Mongoose version

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "version", + "value": "JSON.parse(", + "string": "mongoose.version" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", + "summary": "

    The Mongoose constructor

    ", + "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Mongoose = Mongoose;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Mongoose", + "value": "Mongoose", + "string": "mongoose.Mongoose" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", + "summary": "

    The Mongoose Schema constructor

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Schema = Schema;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Schema", + "value": "Schema", + "string": "mongoose.Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose SchemaType constructor.

    ", + "summary": "

    The Mongoose SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaType = SchemaType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaType", + "value": "SchemaType", + "string": "mongoose.SchemaType" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Schema.SchemaTypes #schema_Schema-Types", + "visibility": "Schema.SchemaTypes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", + "summary": "

    The various Mongoose SchemaTypes.

    ", + "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaTypes = Schema.Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaTypes", + "value": "Schema.Types", + "string": "mongoose.SchemaTypes" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose VirtualType constructor.

    ", + "summary": "

    The Mongoose VirtualType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.VirtualType = VirtualType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "VirtualType", + "value": "VirtualType", + "string": "mongoose.VirtualType" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", + "summary": "

    The various Mongoose Types.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Types = Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Types", + "value": "Types", + "string": "mongoose.Types" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Query constructor.

    ", + "summary": "

    The Mongoose Query constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Query = Query;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Query", + "value": "Query", + "string": "mongoose.Query" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Promise constructor.

    ", + "summary": "

    The Mongoose Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Promise = Promise;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Promise", + "value": "Promise", + "string": "mongoose.Promise" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Model constructor.

    ", + "summary": "

    The Mongoose Model constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Model = Model;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Model", + "value": "Model", + "string": "mongoose.Model" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Document constructor.

    ", + "summary": "

    The Mongoose Document constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Document = Document;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Document", + "value": "Document", + "string": "mongoose.Document" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The MongooseError constructor.

    ", + "summary": "

    The MongooseError constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Error = require('./error');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Error", + "value": "require('./error')", + "string": "mongoose.Error" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The node-mongodb-native driver Mongoose uses.

    ", + "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.mongo = require('mongodb');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "mongo", + "value": "require('mongodb')", + "string": "mongoose.mongo" + } + } +] +### lib/model.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('./document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "values to with which to create the document" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "event", + "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." + }, + { + "type": "event", + "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Model constructor

    ", + "summary": "

    Model constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", + "ctx": { + "type": "function", + "name": "Model", + "string": "Model()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Document.

    ", + "summary": "

    Inherits from Document.

    ", + "body": "" + }, + "ignore": true, + "code": "Model.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "Model", + "name": "__proto__", + "value": "Document.prototype", + "string": "Model.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    Connection the model uses.

    ", + "summary": "

    Connection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.db;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "collection" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.collection;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "modelName" + } + ], + "description": { + "full": "

    The name of the model

    ", + "summary": "

    The name of the model

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.modelName;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "object" + }, + { + "type": "return", + "types": [ + "Object", + "undefined" + ], + "description": "population paths" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns what paths can be populated

    ", + "summary": "

    Returns what paths can be populated

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_getPopulationKeys", + "string": "Model.prototype._getPopulationKeys()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "schema", + "description": "type for the oid" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "oid", + "description": "object id or array of object ids" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "query", + "description": "object specifying query conditions, fields, and options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Populates an object

    ", + "summary": "

    Populates an object

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_populate", + "string": "Model.prototype._populate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "query that originated the initialization" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs auto-population of relations.

    ", + "summary": "

    Performs auto-population of relations.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "init", + "string": "Model.prototype.init()" + } + }, + { + "tags": [], + "description": { + "full": "

    Handles doc.save() callbacks

    ", + "summary": "

    Handles doc.save() callbacks

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new Error('No matching document found.'));\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", + "ctx": { + "type": "function", + "name": "handleSave", + "string": "handleSave()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "title": "middleware", + "url": "http://mongoosejs.com/docs/middleware.html", + "visibility": "http://mongoosejs.com/docs/middleware.html" + } + ], + "description": { + "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", + "summary": "

    Saves this document.

    ", + "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n complete(null);\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "save", + "string": "Model.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Mixed" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[operation]", + "description": "" + } + ], + "description": { + "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", + "ctx": { + "type": "function", + "name": "operand", + "string": "operand()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "val", + "description": "" + } + ], + "description": { + "full": "

    Compiles an update and where clause for a val with _atomics.

    ", + "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", + "ctx": { + "type": "function", + "name": "handleAtomics", + "string": "handleAtomics()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a special query document of the modified properties used in updates.

    ", + "summary": "

    Produces a special query document of the modified properties used in updates.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_delta", + "string": "Model.prototype._delta()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Appends versioning to the where and update clauses.

    ", + "summary": "

    Appends versioning to the where and update clauses.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_version", + "string": "Model.prototype._version()" + } + }, + { + "tags": [ + { + "type": "see", + "title": "versionKeys", + "url": "http://mongoosejs.com/docs/guide.html#versionKey", + "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Signal that we desire an increment of this documents version.

    ", + "summary": "

    Signal that we desire an increment of this documents version.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "increment", + "string": "Model.prototype.increment()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns a query object which applies shardkeys if they exist.

    ", + "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_where", + "string": "Model.prototype._where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", + "summary": "

    Removes this document from the db.

    ", + "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) return this;\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "remove", + "string": "Model.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register hooks override

    ", + "summary": "

    Register hooks override

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_registerHooks", + "string": "Model.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", + "summary": "

    Returns another Model instance.

    ", + "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "model", + "string": "Model.prototype.model()" + } + }, + { + "tags": [ + { + "type": "TODO", + "string": "determine if this is still necessary" + } + ], + "description": { + "full": "

    Give the constructor the ability to emit events.

    ", + "summary": "

    Give the constructor the ability to emit events.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the model compiles.

    ", + "summary": "

    Called when the model compiles.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.init = function init () {\n if (this.schema.options.autoIndex)\n this.ensureIndexes();\n\n this.schema.emit('init', this);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "init", + "string": "Model.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[cb]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    ", + "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", + "body": "

    After completion, an index event is emitted on this Model passing an error if one occurred.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "ensureIndexes", + "string": "Model.ensureIndexes()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "schema" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema the model uses.

    ", + "summary": "

    Schema the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.schema;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Database instance the model uses.

    ", + "summary": "

    Database instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.db;" + }, + { + "tags": [ + { + "type": "property", + "string": "collection" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.collection;" + }, + { + "tags": [ + { + "type": "property", + "string": "base" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Base Mongoose instance the model uses.

    ", + "summary": "

    Base Mongoose instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.base;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes documents from the collection.

    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    ", + "summary": "

    Removes documents from the collection.

    ", + "body": "

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "remove", + "string": "Model.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents

    \n\n

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    ", + "summary": "

    Finds documents

    ", + "body": "

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "find", + "string": "Model.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges the current named scope query into query.

    ", + "summary": "

    Merges the current named scope query into query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "_applyNamedScope", + "string": "Model._applyNamedScope()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "objectid, or a value that can be casted to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds a single document by id.

    \n\n

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    ", + "summary": "

    Finds a single document by id.

    ", + "body": "

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findById", + "string": "Model.findById()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    ", + "summary": "

    Finds one document.

    ", + "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n // TODO Handle all 3 of the following scenarios\n // Hint: Only some of these scenarios are possible if cQuery is present\n // Scenario: findOne(conditions, fields, callback);\n // Scenario: findOne(fields, options, callback);\n // Scenario: findOne(conditions, options, callback);\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n // TODO Handle all 2 of the following scenarios\n // Scenario: findOne(conditions, callback)\n // Scenario: findOne(fields, callback)\n // Scenario: findOne(options, callback);\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOne", + "string": "Model.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", + "summary": "

    Counts number of matching documents in a database collection.

    ", + "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "count", + "string": "Model.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a DISTINCT command

    ", + "summary": "

    Executes a DISTINCT command

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "distinct", + "string": "Model.distinct()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "optional value" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", + "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", + "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "where", + "string": "Model.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "argument", + "description": "is a javascript string or anonymous function" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "memberOf", + "parent": "Model" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Query.$where #query_Query-%24where", + "visibility": "Query.$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    ", + "summary": "

    Creates a Query and specifies a $where condition.

    ", + "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndUpdate", + "string": "Model.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "an ObjectId or string that can be cast to one." + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", + "visibility": "Model.findOneAndUpdate" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndUpdate", + "string": "Model.findByIdAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndRemove", + "string": "Model.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "id", + "description": "ObjectId or string that can be cast to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", + "visibility": "Model.findOneAndRemove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndRemove", + "string": "Model.findByIdAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array", + "Object..." + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", + "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", + "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "create", + "string": "Model.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "update", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Updates documents in the database without returning them.

    ", + "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "update", + "string": "Model.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "o", + "description": "an object specifying map-reduce options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/MapReduce", + "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", + "summary": "

    Executes a mapReduce command.

    ", + "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "mapReduce", + "string": "Model.mapReduce()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "collectionName", + "description": "" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "connection", + "description": "" + }, + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "mongoose instance" + } + ], + "description": { + "full": "

    Compiler utility.

    ", + "summary": "

    Compiler utility.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "compile", + "string": "Model.compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Model;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Model", + "string": "module.exports" + } + } +] +### lib/namedscope.js +[ + { + "tags": [ + { + "type": "param", + "types": [ + "NamedScope" + ], + "name": "target", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "getters", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Decorate

    ", + "summary": "

    Decorate

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", + "ctx": { + "type": "method", + "constructor": "NamedScope", + "name": "decorate", + "string": "NamedScope.prototype.decorate()" + } + } +] +### lib/promise.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", + "ctx": { + "type": "declaration", + "name": "util", + "value": "require('./utils')", + "string": "util" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "back", + "description": "a callback+errback that accepts `fn(err, ...){}` as signature" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`err`: Emits when the promise resolves to an error." + }, + { + "type": "event", + "string": "`complete`: Emits when the promise resolves sucessfully." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Promise constructor.

    ", + "summary": "

    Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", + "ctx": { + "type": "function", + "name": "Promise", + "string": "Promise()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from EventEmitter.

    ", + "summary": "

    Inherits from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Promise", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Promise.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Event" + ], + "name": "event", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds listener to the event.

    \n\n

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", + "summary": "

    Adds listener to the event.

    ", + "body": "

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "on", + "string": "Promise.prototype.on()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Keeps track of emitted events to run them on on.

    ", + "summary": "

    Keeps track of emitted events to run them on on.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "emit", + "string": "Promise.prototype.emit()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for emitting the complete event.

    ", + "summary": "

    Shortcut for emitting the complete event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "complete", + "string": "Promise.prototype.complete()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Shortcut for emitting the err event.

    ", + "summary": "

    Shortcut for emitting the err event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "error", + "string": "Promise.prototype.error()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('complete', fn).

    ", + "summary": "

    Shortcut for .on('complete', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addCallback", + "string": "Promise.prototype.addCallback()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('err', fn).

    ", + "summary": "

    Shortcut for .on('err', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addErrback", + "string": "Promise.prototype.addErrback()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Adds a single function that's both a callback and errback.

    ", + "summary": "

    Adds a single function that's both a callback and errback.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addBack", + "string": "Promise.prototype.addBack()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "optional error or null" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "value to complete the promise with" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "summary": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "resolve", + "string": "Promise.prototype.resolve()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Promise;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Promise", + "string": "module.exports" + } + } +] +### lib/query.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "criteria", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", + "summary": "

    Query constructor used for building queries.

    ", + "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n if (criteria) this.find(criteria);\n}", + "ctx": { + "type": "function", + "name": "Query", + "string": "Query()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", + "summary": "

    Sets query options.

    ", + "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "setOptions", + "string": "Query.prototype.setOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "the model to which the query is bound" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "the operation to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "updateArg", + "description": "used in update methods" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Binds this query to a model.

    ", + "summary": "

    Binds this query to a model.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "bind", + "string": "Query.prototype.bind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "[operation]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", + "summary": "

    Executes the query

    ", + "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exec", + "string": "Query.prototype.exec()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[criteria]", + "description": "mongodb selector" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", + "summary": "

    Finds documents.

    ", + "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "find", + "string": "Query.prototype.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[obj]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", + "summary": "

    Casts this query to the schema of model

    ", + "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "cast", + "string": "Query.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options.

    ", + "summary": "

    Returns default options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n if (! ('safe' in options)) options.safe = model.schema.options.safe;\n return options;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_optionsForExec", + "string": "Query.prototype._optionsForExec()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies schematype selected options to this query.

    ", + "summary": "

    Applies schematype selected options to this query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_applyPaths", + "string": "Query.prototype._applyPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "js", + "description": "javascript string or function" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", + "summary": "

    Specifies a $where condition

    ", + "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", + "summary": "

    Specifies a path for use with chaining.

    ", + "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "where", + "string": "Query.prototype.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", + "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", + "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "equals", + "string": "Query.prototype.equals()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", + "summary": "

    Specifies arguments for an $or condition.

    ", + "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "or", + "string": "Query.prototype.or()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", + "summary": "

    Specifies arguments for a $nor condition.

    ", + "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nor", + "string": "Query.prototype.nor()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "gt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", + "summary": "

    Specifies a $gt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "gte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $gte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "ne" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $ne query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "in" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $in query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "nin" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $nin query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "all" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $all query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "size" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $size query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "regex" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $regex query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxDistance" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $maxDistance query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", + "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", + "body": "
    Thing.where('type').nin(array)\n
    " + }, + "ignore": true, + "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $near condition

    ", + "summary": "

    Specifies a $near condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "near", + "string": "Query.prototype.near()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $nearSphere condition.

    ", + "summary": "

    Specifies a $nearSphere condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nearSphere", + "string": "Query.prototype.nearSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $mod condition

    ", + "summary": "

    Specifies a $mod condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "mod", + "string": "Query.prototype.mod()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $exists condition

    ", + "summary": "

    Specifies an $exists condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exists", + "string": "Query.prototype.exists()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object", + "Function" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "Function" + ], + "name": "criteria", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", + "summary": "

    Specifies an $elemMatch condition

    ", + "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "elemMatch", + "string": "Query.prototype.elemMatch()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "within" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Syntax sugar for expressive queries.

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    ", + "summary": "

    Syntax sugar for expressive queries.

    ", + "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "see", + "local": "Query#within #query_Query-within", + "visibility": "Query#within" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", + "summary": "

    Specifies a $box condition

    ", + "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "box", + "string": "Query.prototype.box()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "options e.g. { $uniqueDocs: true }" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", + "summary": "

    Specifies a $center condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "center", + "string": "Query.prototype.center()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", + "summary": "

    Specifies a $centerSphere condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "centerSphere", + "string": "Query.prototype.centerSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Array", + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", + "summary": "

    Specifies a $polygon condition

    ", + "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "polygon", + "string": "Query.prototype.polygon()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "local": "SchemaType", + "visibility": "SchemaType" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    ", + "summary": "

    Specifies which document fields to include or exclude

    ", + "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "select", + "string": "Query.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "number of elements to slice" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", + "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", + "summary": "

    Specifies a $slice condition

    ", + "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slice", + "string": "Query.prototype.slice()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", + "summary": "

    Sets the sort order

    ", + "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "sort", + "string": "Query.prototype.sort()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", + "ctx": { + "type": "function", + "name": "push", + "string": "push()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "limit" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", + "summary": "

    Specifies the limit option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "skip" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", + "summary": "

    Specifies the skip option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxscan" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", + "summary": "

    Specifies the maxscan option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "batchSize" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", + "summary": "

    Specifies the batchSize option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "comment" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", + "summary": "

    Specifies the comment option.

    ", + "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", + "summary": "

    limit, skip, maxscan, batchSize, comment

    ", + "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " + }, + "ignore": true, + "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", + "summary": "

    Specifies this query as a snapshot query.

    ", + "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "snapshot", + "string": "Query.prototype.snapshot()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "a hint object" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", + "summary": "

    Sets query hints.

    ", + "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "hint", + "string": "Query.prototype.hint()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", + "summary": "

    Sets the slaveOk option.

    ", + "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slaveOk", + "string": "Query.prototype.slaveOk()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", + "summary": "

    Sets the lean option.

    ", + "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "lean", + "string": "Query.prototype.lean()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", + "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", + "summary": "

    Sets tailable option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "tailable", + "string": "Query.prototype.tailable()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes the query as a find() operation.

    ", + "summary": "

    Executes the query as a find() operation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n\n var fields = utils.clone(options.fields = this._fields);\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "execFind", + "string": "Query.prototype.execFind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", + "summary": "

    Executes the query as a findOne() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n\n var fields = utils.clone(options.fields = this._fields);\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOne", + "string": "Query.prototype.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", + "summary": "

    Exectues the query as a count() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "count", + "string": "Query.prototype.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a distict() operation.

    ", + "summary": "

    Executes this query as a distict() operation.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "distinct", + "string": "Query.prototype.distinct()" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "body": "" + }, + "ignore": true, + "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", + "ctx": { + "type": "declaration", + "name": "castOps", + "value": "{", + "string": "castOps" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "body": "" + }, + "ignore": true, + "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", + "ctx": { + "type": "declaration", + "name": "numberOps", + "value": "{", + "string": "numberOps" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "the update conditions" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", + "summary": "

    Executes this query as an update() operation.

    ", + "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n delete options.safe;\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "update", + "string": "Query.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "obj after casting its values" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts obj for an update command.

    ", + "summary": "

    Casts obj for an update command.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdate", + "string": "Query.prototype._castUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "- part of a query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "- path prefix (internal only)" + }, + { + "type": "return", + "types": [ + "Bool" + ], + "description": "true if this path has keys to update" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_walkUpdatePath", + "string": "Query.prototype._walkUpdatePath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[$conditional]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val according to schema and atomic op.

    ", + "summary": "

    Casts val according to schema and atomic op.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdateVal", + "string": "Query.prototype._castUpdateVal()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_getSchema", + "string": "Query.prototype._getSchema()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", + "summary": "

    Executes this query as a remove() operation.

    ", + "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n delete options.safe;\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "remove", + "string": "Query.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[query]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[doc]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndUpdate", + "string": "Query.prototype.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndRemove", + "string": "Query.prototype.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "- either \"remove\" or \"update\"" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    _findAndModify

    ", + "summary": "

    _findAndModify

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n if (this._fields) {\n fields = utils.clone(opts.fields = this._fields);\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_findAndModify", + "string": "Query.prototype._findAndModify()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Model" + ], + "name": "[model]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "see", + "local": "population ./populate.html", + "visibility": "population" + }, + { + "type": "see", + "local": "Query#select #query_Query-select", + "visibility": "Query#select" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    ", + "summary": "

    Specifies paths which should be populated with other documents.

    ", + "body": "

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "populate", + "string": "Query.prototype.populate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Populate options constructor

    ", + "summary": "

    Populate options constructor

    ", + "body": "" + }, + "ignore": true, + "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", + "ctx": { + "type": "function", + "name": "PopulateOptions", + "string": "PopulateOptions()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "QueryStream" + ], + "description": "" + }, + { + "type": "see", + "local": "QueryStream", + "visibility": "QueryStream" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a stream interface

    \n\n

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    ", + "summary": "

    Returns a stream interface

    ", + "body": "

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "stream", + "string": "Query.prototype.stream()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castDoc

    ", + "summary": "

    castDoc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castDoc", + "string": "castDoc()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castQuery

    ", + "summary": "

    castQuery

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castQuery", + "string": "castQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Exports.

    ", + "summary": "

    Exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Query", + "string": "module.exports" + } + } +] +### lib/querystream.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", + "ctx": { + "type": "declaration", + "name": "Stream", + "value": "require('stream').Stream", + "string": "Stream" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS Stream http://nodejs.org/api/stream.html" + }, + { + "type": "event", + "string": "`data`: emits a single Mongoose document" + }, + { + "type": "event", + "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." + }, + { + "type": "event", + "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Provides a ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    ", + "summary": "

    Provides a ReadStream interface for Queries.

    ", + "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._ticks = 0;\n this._inline = T_INIT;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", + "ctx": { + "type": "function", + "name": "QueryStream", + "string": "QueryStream()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Stream

    ", + "summary": "

    Inherit from Stream

    ", + "body": "" + }, + "ignore": true, + "code": "QueryStream.prototype.__proto__ = Stream.prototype;", + "ctx": { + "type": "property", + "constructor": "QueryStream", + "name": "__proto__", + "value": "Stream.prototype", + "string": "QueryStream.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readable" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is readable.

    ", + "summary": "

    Flag stating whether or not this stream is readable.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.readable;" + }, + { + "tags": [ + { + "type": "property", + "string": "paused" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is paused.

    ", + "summary": "

    Flag stating whether or not this stream is paused.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the query.

    ", + "summary": "

    Initializes the query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(options.fields = query._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_init", + "string": "QueryStream.prototype._init()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#__next #querystream_QueryStream-__next", + "visibility": "QueryStream#__next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Trampoline for pulling the next doc from cursor.

    ", + "summary": "

    Trampoline for pulling the next doc from cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._next = function () {\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n var fn;\n while (fn = this.__next()) fn.call(this);\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_next", + "string": "QueryStream.prototype._next()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#_next #querystream_QueryStream-_next", + "visibility": "QueryStream#_next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pulls the next doc from the cursor.

    ", + "summary": "

    Pulls the next doc from the cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed) return;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return this.__next;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "__next", + "string": "QueryStream.prototype.__next()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error", + "null" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._onNextObject = function (err, doc) {\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n return this.destroy();\n }\n\n if (this.query.options && this.query.options.lean === true) {\n this.emit('data', doc);\n this._next();\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields);\n\n // skip _id for pre-init hooks\n delete instance._doc._id;\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_onNextObject", + "string": "QueryStream.prototype._onNextObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pauses this stream.

    ", + "summary": "

    Pauses this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "pause", + "string": "QueryStream.prototype.pause()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Resumes this stream.

    ", + "summary": "

    Resumes this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n this._next();\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "resume", + "string": "QueryStream.prototype.resume()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "[err]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "destroy", + "string": "QueryStream.prototype.destroy()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "pipe" + }, + { + "type": "memberOf", + "parent": "QueryStream" + }, + { + "type": "see", + "title": "NodeJS", + "url": "http://nodejs.org/api/stream.html", + "visibility": "http://nodejs.org/api/stream.html" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", + "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", + "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = QueryStream", + "string": "module.exports" + } + } +] +### lib/schema/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Array SchemaType constructor

    ", + "summary": "

    Array SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "SchemaArray", + "string": "SchemaArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaArray", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "checkRequired", + "string": "SchemaArray.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides the getters application for the population special-case

    ", + "summary": "

    Overrides the getters application for the population special-case

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "applyGetters", + "string": "SchemaArray.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "cast", + "string": "SchemaArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "castForQuery", + "string": "SchemaArray.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': castToNumber\n , '$gte': castToNumber\n , '$lt': castToNumber\n , '$lte': castToNumber\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", + "ctx": { + "type": "function", + "name": "castToNumber", + "string": "castToNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaArray", + "string": "module.exports" + } + } +] +### lib/schema/boolean.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Boolean SchemaType constructor.

    ", + "summary": "

    Boolean SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaBoolean", + "string": "SchemaBoolean()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBoolean", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBoolean.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "checkRequired", + "string": "SchemaBoolean.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to boolean

    ", + "summary": "

    Casts to boolean

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "cast", + "string": "SchemaBoolean.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", + "ctx": { + "type": "function", + "name": "handleArray", + "string": "handleArray()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Boolean.\");\n\n return handler.call(this, val);\n }\n\n return this.cast($conditional);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "castForQuery", + "string": "SchemaBoolean.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBoolean;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBoolean", + "string": "module.exports" + } + } +] +### lib/schema/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Buffer SchemaType constructor

    ", + "summary": "

    Buffer SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", + "ctx": { + "type": "function", + "name": "SchemaBuffer", + "string": "SchemaBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBuffer", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBuffer.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "checkRequired", + "string": "SchemaBuffer.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "cast", + "string": "SchemaBuffer.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "castForQuery", + "string": "SchemaBuffer.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBuffer;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBuffer", + "string": "module.exports" + } + } +] +### lib/schema/date.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date SchemaType constructor.

    ", + "summary": "

    Date SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaDate", + "string": "SchemaDate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaDate", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaDate.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for date

    ", + "summary": "

    Required validator for date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "checkRequired", + "string": "SchemaDate.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to date

    ", + "summary": "

    Casts to date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "cast", + "string": "SchemaDate.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date Query casting.

    ", + "summary": "

    Date Query casting.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "castForQuery", + "string": "SchemaDate.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaDate;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaDate", + "string": "module.exports" + } + } +] +### lib/schema/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaArray" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    SubdocsArray SchemaType constructor

    ", + "summary": "

    SubdocsArray SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentArray (key, schema, options) {\n // compile an embedded document for this schema\n // TODO Move this into parent model compilation for performance improvement?\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n };\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "DocumentArray", + "string": "DocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from ArrayType.

    ", + "summary": "

    Inherits from ArrayType.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentArray", + "name": "__proto__", + "value": "ArrayType.prototype", + "string": "DocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs local validations first, then validations on each embedded doc

    ", + "summary": "

    Performs local validations first, then validations on each embedded doc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n SchemaType.prototype.doValidate.call(this, array, function(err){\n if (err) return fn(err);\n\n var count = array && array.length\n , error = false;\n\n if (!count) return fn();\n\n array.forEach(function(doc, index){\n doc.validate(function(err){\n if (err && !error){\n // rewrite they key\n err.key = self.key + '.' + index + '.' + err.key;\n fn(err);\n error = true;\n } else {\n --count || fn();\n }\n });\n });\n }, scope);\n};", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "doValidate", + "string": "DocumentArray.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "document", + "description": "that triggers the casting" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var subdoc\n , i\n\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument)) {\n if (init) {\n subdoc = new this.casterConstructor(null, value, true);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init, prev);\n }\n\n throw new CastError('documentarray', value);\n};", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "cast", + "string": "DocumentArray.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = DocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "DocumentArray", + "string": "module.exports" + } + } +] +### lib/schema/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "String", + "value": "require('./string')", + "string": "exports.String" + } + } +] +### lib/schema/mixed.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Mixed SchemaType constructor.

    ", + "summary": "

    Mixed SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "Mixed", + "string": "Mixed()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "Mixed", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "Mixed.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "checkRequired", + "string": "Mixed.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", + "summary": "

    Casts val for Mixed.

    ", + "body": "

    this is a no-op

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "cast", + "string": "Mixed.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$cond", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "castForQuery", + "string": "Mixed.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Mixed;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Mixed", + "string": "module.exports" + } + } +] +### lib/schema/number.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Number SchemaType constructor.

    ", + "summary": "

    Number SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", + "ctx": { + "type": "function", + "name": "SchemaNumber", + "string": "SchemaNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaNumber", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaNumber.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for number

    ", + "summary": "

    Required validator for number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "checkRequired", + "string": "SchemaNumber.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "value", + "description": "minimum number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "min", + "string": "SchemaNumber.prototype.min()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "maximum", + "description": "number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "max", + "string": "SchemaNumber.prototype.max()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "value to cast" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to number

    ", + "summary": "

    Casts to number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "cast", + "string": "SchemaNumber.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "castForQuery", + "string": "SchemaNumber.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaNumber;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaNumber", + "string": "module.exports" + } + } +] +### lib/schema/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    ObjectId SchemaType constructor.

    ", + "summary": "

    ObjectId SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", + "ctx": { + "type": "function", + "name": "ObjectId", + "string": "ObjectId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "ObjectId", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "ObjectId.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "checkRequired", + "string": "ObjectId.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to ObjectId

    ", + "summary": "

    Casts to ObjectId

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "cast", + "string": "ObjectId.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "castForQuery", + "string": "ObjectId.prototype.castForQuery()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "turnOn", + "description": "auto generated ObjectId defaults" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "auto", + "string": "ObjectId.prototype.auto()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", + "ctx": { + "type": "function", + "name": "defaultId", + "string": "defaultId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ObjectId;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ObjectId", + "string": "module.exports" + } + } +] +### lib/schema/string.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    String SchemaType constructor.

    ", + "summary": "

    String SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", + "ctx": { + "type": "function", + "name": "SchemaString", + "string": "SchemaString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaString", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaString.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[args...]", + "description": "enumeration values" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", + "summary": "

    Adds enumeration values and a coinciding validator.

    ", + "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "enum", + "string": "SchemaString.prototype.enum()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", + "summary": "

    Adds a lowercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v) {\n return v.toLowerCase();\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "lowercase", + "string": "SchemaString.prototype.lowercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", + "summary": "

    Adds an uppercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v) {\n return v.toUpperCase();\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "uppercase", + "string": "SchemaString.prototype.uppercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", + "summary": "

    Adds a trim setter.

    ", + "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v) {\n return v.trim();\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "trim", + "string": "SchemaString.prototype.trim()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp" + ], + "name": "regExp", + "description": "regular expression to test against" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", + "summary": "

    Sets a regexp validator.

    ", + "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "match", + "string": "SchemaString.prototype.match()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "null", + "undefined" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "checkRequired", + "string": "SchemaString.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to String

    ", + "summary": "

    Casts to String

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "cast", + "string": "SchemaString.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "castForQuery", + "string": "SchemaString.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaString;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaString", + "string": "module.exports" + } + } +] +### lib/schema.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "definition", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted after the schema is compiled into a `Model`." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", + "summary": "

    Schema constructor.

    ", + "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n // set options\n this.options = utils.options({\n safe: true\n , strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", + "ctx": { + "type": "function", + "name": "Schema", + "string": "Schema()" + } + }, + { + "tags": [], + "description": { + "full": "

    Returns this documents _id cast to a string.

    ", + "summary": "

    Returns this documents _id cast to a string.

    ", + "body": "" + }, + "ignore": true, + "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", + "ctx": { + "type": "function", + "name": "idGetter", + "string": "idGetter()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Schema", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Schema.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "paths" + } + ], + "description": { + "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", + "summary": "

    Schema as flat paths

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.paths;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "tree" + } + ], + "description": { + "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", + "summary": "

    Schema as a tree

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.tree;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "prefix", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", + "summary": "

    Adds key path / schema type pairs to this schema.

    ", + "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n }\n else\n this.path(prefix + i, obj[i]); // mixed type\n } else\n this.path(prefix + i, obj[i]);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "add", + "string": "Schema.prototype.add()" + } + }, + { + "tags": [], + "description": { + "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    ", + "summary": "

    Reserved document keys.

    ", + "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    " + }, + "ignore": false, + "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "reserved", + "value": "Object.create(null)", + "string": "Schema.reserved" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "constructor", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", + "summary": "

    Gets/sets schema paths.

    ", + "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(path) {\n if (!branch[path]) branch[path] = {};\n branch = branch[path];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "path", + "string": "Schema.prototype.path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "constructor" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts type arguments into Mongoose Types.

    ", + "summary": "

    Converts type arguments into Mongoose Types.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", + "ctx": { + "type": "method", + "receiver": "Schema", + "name": "interpretAsType", + "string": "Schema.interpretAsType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback function" + }, + { + "type": "return", + "types": [ + "Schema" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", + "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", + "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "eachPath", + "string": "Schema.prototype.eachPath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns an Array of path strings that are required by this schema.

    ", + "summary": "

    Returns an Array of path strings that are required by this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "requiredPaths", + "string": "Schema.prototype.requiredPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", + "summary": "

    Returns the pathType of path for this schema.

    ", + "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pathType", + "string": "Schema.prototype.pathType()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", + "ctx": { + "type": "function", + "name": "getPositionalPath", + "string": "getPositionalPath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the document method to call later" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds a method call to the queue.

    ", + "summary": "

    Adds a method call to the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "queue", + "string": "Schema.prototype.queue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", + "summary": "

    Defines a pre hook for the document.

    ", + "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pre", + "string": "Schema.prototype.pre()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "name of the method to hook" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", + "summary": "

    Defines a post hook for the document.

    ", + "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "post", + "string": "Schema.prototype.post()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "plugin", + "description": "callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "" + }, + { + "type": "see", + "local": "plugins", + "visibility": "plugins" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Registers a plugin for this schema.

    ", + "summary": "

    Registers a plugin for this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "plugin", + "string": "Schema.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "method", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", + "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "method", + "string": "Schema.prototype.method()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", + "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "static", + "string": "Schema.prototype.static()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", + "summary": "

    Defines an index (most likely compound) for this schema.

    ", + "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "index", + "string": "Schema.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "option name" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[value]", + "description": "if not passed, the current option value is returned" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets/gets a schema option.

    ", + "summary": "

    Sets/gets a schema option.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "set", + "string": "Schema.prototype.set()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Compiles indexes from fields and schema-level indexes

    ", + "summary": "

    Compiles indexes from fields and schema-level indexes

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "indexes", + "string": "Schema.prototype.indexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", + "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", + "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " + }, + "ignore": true, + "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", + "ctx": { + "type": "function", + "name": "fixSubIndexPaths", + "string": "fixSubIndexPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Creates a virtual type with the given name.

    ", + "summary": "

    Creates a virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options)\n : {});\n return mem[part];\n }, this.tree);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtual", + "string": "Schema.prototype.virtual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the virtual type with the given name.

    ", + "summary": "

    Returns the virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtualpath", + "string": "Schema.prototype.virtualpath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "namedScope", + "string": "Schema.prototype.namedScope()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Schema", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Schema Types.

    \n\n

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", + "summary": "

    The various Mongoose Schema Types.

    ", + "body": "

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.Types = require('./schema/index');", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "Types", + "value": "require('./schema/index')", + "string": "Schema.Types" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" + } +] +### lib/schemadefault.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "property", + "string": "system.profile" + }, + { + "type": "receiver", + "string": "exports" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Default model for querying the system.profiles collection.

    ", + "summary": "

    Default model for querying the system.profiles collection.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" + } +] +### lib/schematype.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');\nvar CastError = require('./errors/cast')\nvar ValidatorError = require('./errors/validator')", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[instance]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    SchemaType constructor

    ", + "summary": "

    SchemaType constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", + "ctx": { + "type": "function", + "name": "SchemaType", + "string": "SchemaType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function", + "any" + ], + "name": "val", + "description": "the default value" + }, + { + "type": "return", + "types": [ + "defaultValue" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", + "summary": "

    Sets a default value for this SchemaType.

    ", + "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "default", + "string": "SchemaType.prototype.default()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "Boolean" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", + "summary": "

    Declares the index options for this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "index", + "string": "SchemaType.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares an unique index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    ", + "summary": "

    Declares an unique index.

    ", + "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "unique", + "string": "SchemaType.prototype.unique()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a sparse index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", + "summary": "

    Declares a sparse index.

    ", + "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "sparse", + "string": "SchemaType.prototype.sparse()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "when", + "description": "" + }, + { + "type": "added", + "string": "3.0.0" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    ", + "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", + "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "expires", + "string": "SchemaType.prototype.expires()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\nvar s = new Schema({ name: { type: String, set: capitalize })\n// or\nSchema.path('name').set(capitalize);\n
    ", + "summary": "

    Adds a setter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\nvar s = new Schema({ name: { type: String, set: capitalize })\n// or\nSchema.path('name').set(capitalize);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "set", + "string": "SchemaType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\nvar s = new Schema({ born: { type: Date, get: dob })\n// or\nSchema.path('name').get(dob);\n
    ", + "summary": "

    Adds a getter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\nvar s = new Schema({ born: { type: Date, get: dob })\n// or\nSchema.path('name').get(dob);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "get", + "string": "SchemaType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp", + "Function", + "Object" + ], + "name": "obj", + "description": "validator" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[error]", + "description": "optional error message" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", + "summary": "

    Adds validator(s) for this document path.

    ", + "body": "

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "validate", + "string": "SchemaType.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "required", + "description": "enable/disable the validator" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", + "summary": "

    Adds a required validator to this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "required", + "string": "SchemaType.prototype.required()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope which callback are executed" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets the default value

    ", + "summary": "

    Gets the default value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "getDefault", + "string": "SchemaType.prototype.getDefault()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies setters

    ", + "summary": "

    Applies setters

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applySetters", + "string": "SchemaType.prototype.applySetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies getters to a value

    ", + "summary": "

    Applies getters to a value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applyGetters", + "string": "SchemaType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", + "summary": "

    Sets default select() behavior for this path.

    ", + "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "select", + "string": "SchemaType.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "doValidate", + "string": "SchemaType.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if value is a valid Reference.

    ", + "summary": "

    Determines if value is a valid Reference.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", + "ctx": { + "type": "method", + "receiver": "SchemaType", + "name": "_isRef", + "string": "SchemaType._isRef()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = SchemaType", + "string": "module.exports" + } + } +] +### lib/statemachine.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", + "ctx": { + "type": "declaration", + "name": "StateMachine", + "value": "module.exports = exports = function StateMachine () {", + "string": "StateMachine" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "subclass constructor" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", + "ctx": { + "type": "method", + "receiver": "StateMachine", + "name": "ctor", + "string": "StateMachine.ctor()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", + "summary": "

    This function is wrapped by the state change functions

    ", + "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_changeState", + "string": "StateMachine.prototype._changeState()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "clear", + "string": "StateMachine.prototype.clear()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "that we want to check for." + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "some", + "string": "StateMachine.prototype.some()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "iterMethod", + "description": "is either 'forEach' or 'map'" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_iter", + "string": "StateMachine.prototype._iter()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "forEach", + "string": "StateMachine.prototype.forEach()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "map", + "string": "StateMachine.prototype.map()" + } + } +] +### lib/types/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", + "ctx": { + "type": "declaration", + "name": "EmbeddedDocument", + "value": "require('./embedded')", + "string": "EmbeddedDocument" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Array" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", + "summary": "

    Mongoose Array constructor.

    ", + "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseArray", + "string": "MongooseArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Array

    ", + "summary": "

    Inherit from Array

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseArray.prototype = new Array;", + "ctx": { + "type": "property", + "receiver": "MongooseArray", + "name": "prototype", + "value": "new Array", + "string": "MongooseArray.prototype" + } + }, + { + "tags": [ + { + "type": "property", + "string": "_atomics" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores a queue of atomic operations to perform

    ", + "summary": "

    Stores a queue of atomic operations to perform

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._atomics;" + }, + { + "tags": [ + { + "type": "property", + "string": "_parent" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._parent;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "return", + "types": [ + "value" + ], + "description": "the casted value" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts a member based on this arrays schema.

    ", + "summary": "

    Casts a member based on this arrays schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_cast", + "string": "MongooseArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "EmbeddedDocument" + ], + "name": "embeddedDoc", + "description": "the embedded doc that invoked this method on the Array" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "embeddedPath", + "description": "the path which changed in the embeddedDoc" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", + "summary": "

    Marks this array as modified.

    ", + "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._markModified = function (embeddedDoc, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n if (arguments.length) {\n // If an embedded doc bubbled up the change\n dirtyPath = [this._path, this.indexOf(embeddedDoc), embeddedPath].join('.');\n } else {\n dirtyPath = this._path;\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_markModified", + "string": "MongooseArray.prototype._markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "op", + "description": "operation" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register an atomic operation with the parent.

    ", + "summary": "

    Register an atomic operation with the parent.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n this._markModified();\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n if (this._atomics.$set) {\n return this;\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n this._markModified();\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n this._markModified();\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_registerAtomic", + "string": "MongooseArray.prototype._registerAtomic()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "hasAtomics", + "string": "MongooseArray.prototype.hasAtomics()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#push with proper change tracking.

    ", + "summary": "

    Wraps Array#push with proper change tracking.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "push", + "string": "MongooseArray.prototype.push()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Pushes items to the array non-atomically.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "nonAtomicPush", + "string": "MongooseArray.prototype.nonAtomicPush()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "$pop" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", + "summary": "

    Pops the array atomically at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" + }, + { + "tags": [ + { + "type": "see", + "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", + "visibility": "MongooseArray#$pop" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#pop with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pop", + "string": "MongooseArray.prototype.pop()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "method", + "string": "$shift" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", + "summary": "

    Atomically shifts the array at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#shift with proper change tracking.

    ", + "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "shift", + "string": "MongooseArray.prototype.shift()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "values to remove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes items from an array atomically

    \n\n

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    ", + "summary": "

    Removes items from an array atomically

    ", + "body": "

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "remove", + "string": "MongooseArray.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pulls items from the array atomically.

    ", + "summary": "

    Pulls items from the array atomically.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pull", + "string": "MongooseArray.prototype.pull()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#splice with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#splice with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.splice = function () {\n if (arguments.length) {\n var ret = [].splice.apply(this, arguments);\n this._registerAtomic('$set', this);\n }\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "splice", + "string": "MongooseArray.prototype.splice()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#unshift with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n return this.length;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "unshift", + "string": "MongooseArray.prototype.unshift()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#sort with proper change tracking.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "sort", + "string": "MongooseArray.prototype.sort()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "the values that were added" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", + "summary": "

    Adds values to the array if not already present.

    ", + "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "addToSet", + "string": "MongooseArray.prototype.addToSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array.

    ", + "summary": "

    Returns a native js Array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "toObject", + "string": "MongooseArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "inspect", + "string": "MongooseArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the item to look for" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Return the index of obj or -1 if not found.

    ", + "summary": "

    Return the index of obj or -1 if not found.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "indexOf", + "string": "MongooseArray.prototype.indexOf()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = MongooseArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = MongooseArray", + "string": "module.exports" + } + } +] +### lib/types/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require(driver + '/binary');", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require(driver + '/binary')", + "string": "Binary" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "encode", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "offset", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Buffer" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", + "summary": "

    Mongoose Buffer constructor.

    ", + "body": "

    Values always have to be passed to the constructor to initialize.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", + "ctx": { + "type": "function", + "name": "MongooseBuffer", + "string": "MongooseBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Buffer.

    ", + "summary": "

    Inherit from Buffer.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.prototype = new Buffer(0);", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "prototype", + "value": "new Buffer(0)", + "string": "MongooseBuffer.prototype" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "_parent" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._parent;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this buffer as modified.

    ", + "summary": "

    Marks this buffer as modified.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "_markModified", + "string": "MongooseBuffer.prototype._markModified()" + } + }, + { + "tags": [], + "description": { + "full": "

    Writes the buffer.

    ", + "summary": "

    Writes the buffer.

    ", + "body": "" + }, + "ignore": false, + "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "write", + "string": "MongooseBuffer.prototype.write()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "MongooseBuffer" + ], + "description": "" + }, + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "target", + "description": "" + } + ], + "description": { + "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", + "summary": "

    Copies the buffer.

    ", + "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "copy", + "string": "MongooseBuffer.prototype.copy()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "body": "" + }, + "ignore": true, + "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://bsonspec.org/#/specification", + "visibility": "http://bsonspec.org/#/specification" + }, + { + "type": "param", + "types": [ + "Hex" + ], + "name": "[subtype]", + "description": "" + }, + { + "type": "return", + "types": [ + "Binary" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", + "summary": "

    Converts this buffer to its Binary type representation.

    ", + "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "toObject", + "string": "MongooseBuffer.prototype.toObject()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "Binary", + "value": "Binary", + "string": "MongooseBuffer.Binary" + } + } +] +### lib/types/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", + "ctx": { + "type": "declaration", + "name": "MongooseArray", + "value": "require('./array')", + "string": "MongooseArray" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to this array" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "MongooseDocumentArray" + ], + "description": "" + }, + { + "type": "inherits", + "string": "MongooseArray" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    DocumentArray constructor

    ", + "summary": "

    DocumentArray constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseDocumentArray", + "string": "MongooseDocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseArray

    ", + "summary": "

    Inherits from MongooseArray

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseDocumentArray", + "name": "__proto__", + "value": "MongooseArray.prototype", + "string": "MongooseDocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides MongooseArray#cast

    ", + "summary": "

    Overrides MongooseArray#cast

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype._cast = function (value) {\n var doc = new this._schema.casterConstructor(value, this);\n return doc;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "_cast", + "string": "MongooseDocumentArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "EmbeddedDocument", + "null" + ], + "description": "the subdocuent or null if not found." + }, + { + "type": "param", + "types": [ + "ObjectId", + "String", + "Number", + "Buffer" + ], + "name": "id", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Searches array items for the first document with a matching id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", + "summary": "

    Searches array items for the first document with a matching id.

    ", + "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "id", + "string": "MongooseDocumentArray.prototype.id()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", + "summary": "

    Returns a native js Array of plain js objects

    ", + "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "toObject", + "string": "MongooseDocumentArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "inspect", + "string": "MongooseDocumentArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the value to cast to this arrays SubDocument schema" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", + "summary": "

    Creates a subdocument casted to this schema.

    ", + "body": "

    This is the same subdocument constructor used for casting.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "create", + "string": "MongooseDocumentArray.prototype.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates a fn that notifies all child docs of event.

    ", + "summary": "

    Creates a fn that notifies all child docs of event.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n self[i].emit(event, val);\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "notify", + "string": "MongooseDocumentArray.prototype.notify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseDocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseDocumentArray", + "string": "module.exports" + } + } +] +### lib/types/embedded.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('../document')\n , inspect = require('util').inspect;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('../document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "js object returned from the db" + }, + { + "type": "param", + "types": [ + "MongooseDocumentArray" + ], + "name": "parentArr", + "description": "the parent array of this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "skipId", + "description": "" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    EmbeddedDocument constructor.

    ", + "summary": "

    EmbeddedDocument constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function EmbeddedDocument (obj, parentArr, skipId) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, undefined, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", + "ctx": { + "type": "function", + "name": "EmbeddedDocument", + "string": "EmbeddedDocument()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Document

    ", + "summary": "

    Inherit from Document

    ", + "body": "" + }, + "ignore": true, + "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "EmbeddedDocument", + "name": "__proto__", + "value": "Document.prototype", + "string": "EmbeddedDocument.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path which changed" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", + "summary": "

    Marks the embedded doc modified.

    ", + "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "markModified", + "string": "EmbeddedDocument.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "return", + "types": [ + "EmbeddedDocument" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", + "summary": "

    Used as a stub for hooks.js

    ", + "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "save", + "string": "EmbeddedDocument.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes the subdocument from its parent array.

    ", + "summary": "

    Removes the subdocument from its parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "remove", + "string": "EmbeddedDocument.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Override #update method of parent documents.

    ", + "summary": "

    Override #update method of parent documents.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "update", + "string": "EmbeddedDocument.prototype.update()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "inspect", + "string": "EmbeddedDocument.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "error which states the reason `path` was invalid" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "invalidate", + "string": "EmbeddedDocument.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "ownerDocument", + "string": "EmbeddedDocument.prototype.ownerDocument()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", + "ctx": { + "type": "function", + "name": "ownerDocument", + "string": "ownerDocument()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent document.

    ", + "summary": "

    Returns this sub-documents parent document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parent", + "string": "EmbeddedDocument.prototype.parent()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent array.

    ", + "summary": "

    Returns this sub-documents parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parentArray", + "string": "EmbeddedDocument.prototype.parentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = EmbeddedDocument;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "EmbeddedDocument", + "string": "module.exports" + } + } +] +### lib/types/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "Array", + "value": "require('./array')", + "string": "exports.Array" + } + } +] +### lib/types/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [ + { + "type": "constructor", + "string": "ObjectId" + } + ], + "description": { + "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", + "summary": "

    ObjectId type constructor

    ", + "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require(driver + '/objectid')", + "string": "ObjectId" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "str", + "description": "" + }, + { + "type": "static", + "string": "fromString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "ObjectId" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates an ObjectId from str

    ", + "summary": "

    Creates an ObjectId from str

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.fromString;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId" + ], + "name": "oid", + "description": "ObjectId instance" + }, + { + "type": "static", + "string": "toString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts oid to a string.

    ", + "summary": "

    Converts oid to a string.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.toString;" + } +] +### lib/utils.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , MongooseBuffer\n , MongooseArray\n , Document", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "a model name" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "a collection name" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a collection name from model name.

    ", + "summary": "

    Produces a collection name from model name.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "toCollectionName", + "string": "exports.toCollectionName()" + } + }, + { + "tags": [], + "description": { + "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Pluralization rules.

    ", + "body": "

    These rules are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "pluralization", + "value": "[", + "string": "exports.pluralization" + } + }, + { + "tags": [], + "description": { + "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Uncountable words.

    ", + "body": "

    These words are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news'\n];\nvar uncountables = exports.uncountables;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "uncountables", + "value": "[", + "string": "exports.uncountables" + } + }, + { + "tags": [ + { + "type": "author", + "string": "TJ Holowaychuk (extracted from _ext.js_)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "string", + "description": "to pluralize" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pluralize function.

    ", + "summary": "

    Pluralize function.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", + "ctx": { + "type": "function", + "name": "pluralize", + "string": "pluralize()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "listener", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Add once to EventEmitter if absent

    ", + "summary": "

    Add once to EventEmitter if absent

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", + "ctx": { + "type": "declaration", + "name": "Events", + "value": "EventEmitter", + "string": "Events" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Events", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Events.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Add once.

    ", + "summary": "

    Add once.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", + "ctx": { + "type": "method", + "constructor": "Events", + "name": "once", + "string": "Events.prototype.once()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "a", + "description": "a value to compare to `b`" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "b", + "description": "a value to compare to `a`" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", + "summary": "

    Determines if a and b are deep equal.

    ", + "body": "

    Modified from node/lib/assert.js

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "deepEqual", + "string": "exports.deepEqual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the object to clone" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the cloned object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Object clone with Mongoose natives support.

    \n\n

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.

    ", + "summary": "

    Object clone with Mongoose natives support.

    ", + "body": "

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId) {\n return new ObjectId(obj.id);\n }\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "clone", + "string": "exports.clone()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", + "ctx": { + "type": "function", + "name": "cloneObject", + "string": "cloneObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "defaults", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the merged object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Copies and merges options with defaults.

    ", + "summary": "

    Copies and merges options with defaults.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "options", + "string": "exports.options()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Generates a random string

    ", + "summary": "

    Generates a random string

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "random", + "string": "exports.random()" + } + }, + { + "tags": [], + "description": { + "full": "

    TODO remove

    ", + "summary": "

    TODO remove

    ", + "body": "" + }, + "ignore": true, + "code": "exports.inGroupsOf = function inGroupsOf (card, arr, fn) {\n var group = [];\n for (var i = 0, l = arr.length; i < l; i++) {\n if (i && i % card === 0) {\n fn.apply(this, group);\n group.length = 0;\n }\n group.push(arr[i]);\n }\n fn.apply(this, group);\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "inGroupsOf", + "string": "exports.inGroupsOf()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "to", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "from", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges from into to without overwriting existing properties.

    ", + "summary": "

    Merges from into to without overwriting existing properties.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n merge(to[key], from[key]);\n }\n }\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "merge", + "string": "exports.merge()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.args = function (args, slice, sliceEnd) {\n var ret = [];\n var start = slice || 0;\n var end = 3 === arguments.length\n ? sliceEnd\n : args.length;\n\n for (var i = start; i < end; ++i) {\n ret[i - start] = args[i];\n }\n\n return ret;\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "args", + "string": "exports.args()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", + "summary": "

    process.nextTick helper.

    ", + "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "tick", + "string": "exports.tick()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "v", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", + "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", + "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isMongooseObject", + "string": "exports.isMongooseObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "object", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expiresAfterSeconds = when;\n delete object.expires;\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "expires", + "string": "exports.expires()" + } + } +] +### lib/virtualtype.js +[ + { + "tags": [ + { + "type": "parma", + "string": "{Object} options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", + "summary": "

    VirtualType constructor

    ", + "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function VirtualType (options) {\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", + "ctx": { + "type": "function", + "name": "VirtualType", + "string": "VirtualType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", + "summary": "

    Defines a getter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "get", + "string": "VirtualType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", + "summary": "

    Defines a setter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "set", + "string": "VirtualType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all getters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies getters to value using optional scope.

    ", + "summary": "

    Applies getters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--){\n v = this.getters[l].call(scope, v);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applyGetters", + "string": "VirtualType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all setters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies setters to value using optional scope.

    ", + "summary": "

    Applies setters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--){\n this.setters[l].call(scope, v);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applySetters", + "string": "VirtualType.prototype.applySetters()" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = VirtualType;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "VirtualType", + "string": "module.exports" + } + } +] diff --git a/docs/3.0.x/docs/source/api.js b/docs/3.0.x/docs/source/api.js new file mode 100644 index 00000000000..8fd87f0035b --- /dev/null +++ b/docs/3.0.x/docs/source/api.js @@ -0,0 +1,220 @@ +/*! + * Module dependencies + */ + +var fs = require('fs'); +var link = require('../helpers/linktype'); +var hl = require('highlight.js') +var md = require('markdown') + +module.exports = { + docs: [] + , github: 'https://github.com/LearnBoost/mongoose/tree/' + , title: 'API docs' +} + +var out = module.exports.docs; + +var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); +parse(docs); +order(out); + +function parse (docs) { + docs.split(/^### /gm).forEach(function (chunk) { + if (!(chunk = chunk.trim())) return; + + chunk = chunk.split(/^([^\n]+)\n/); + + var title = chunk[1]; + + if (!title || !(title = title.trim())) + throw new Error('missing title'); + + title = title.replace(/^lib\//, ''); + + var json = JSON.parse(chunk[2]); + + var props = []; + var methods = []; + var statics = []; + var constructor = null; + + json.forEach(function (comment) { + if (comment.description) + highlight(comment.description); + + var prop = false; + comment.params = []; + comment.see = []; + + var i = comment.tags.length; + while (i--) { + var tag = comment.tags[i]; + switch (tag.type) { + case 'property': + prop = true; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + props.unshift(comment); + break; + case 'method': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'method'; + comment.code = ''; + break; + case 'memberOf': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.constructor = tag.parent; + break; + case 'static': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + comment.ctx.type = 'method'; + break; + case 'receiver': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.receiver = tag.string; + break; + case 'constructor': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'function'; + comment.code = ''; + break; + case 'inherits': + if (/http/.test(tag.string)) { + var result = tag.string.split(' '); + var href = result.pop(); + var title = result.join(' '); + comment.inherits = '' + title + ''; + } else { + comment.inherits = link(tag.string); + } + comment.tags.splice(i, 1); + break; + case 'param': + comment.params.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'return': + comment.return = tag; + comment.tags.splice(i, 1); + break; + case 'see': + if (tag.local) { + var parts = tag.local.split(' '); + if (1 === parts.length) { + tag.url = link.type(parts[0]); + tag.title = parts[0]; + } else { + tag.url = parts.pop(); + tag.title = parts.join(' '); + } + } + comment.see.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'event': + var str = tag.string.replace(/\\n/g, '\n'); + tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); + comment.events || (comment.events = []); + comment.events.unshift(tag); + comment.tags.splice(i, 1); + } + } + + if (!prop) { + methods.push(comment); + } + }); + + methods = methods.filter(ignored); + props = props.filter(ignored); + + function ignored (method) { + if (method.ignore) return false; + return true; + } + + if (0 === methods.length + props.length) return; + + // add constructor to properties too + methods.some(function (method) { + if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { + props.forEach(function (prop) { + prop.ctx.constructor = method.ctx.constructor; + }); + return true; + } + return false; + }); + + var len = methods.length; + while (len--) { + method = methods[len]; + if (method.ctx && method.ctx.receiver) { + var stat = methods.splice(len, 1)[0]; + statics.unshift(stat); + } + } + + out.push({ + title: title + , methods: methods + , props: props + , statics: statics + , hasPublic: hasPublic(methods, props, statics) + }); + }); +} + +function hasPublic () { + for (var i = 0; i < arguments.length; ++i) { + var arr = arguments[i]; + for (var j = 0; j < arr.length; ++j) { + var item = arr[j]; + if (!item.ignore && !item.isPrivate) return true; + } + } + return false; +} + +// add "class='language'" to our
     elements
    +function highlight (o) {
    +  o.full = fix(o.full);
    +  o.summary = fix(o.summary);
    +  o.body = fix(o.body);
    +}
    +
    +function fix (str) {
    +  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    +
    +    // parse out the ```language
    +    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    +
    +    if ('js' == code[1] || !code[1]) {
    +      code[1] = 'javascript';
    +    }
    +
    +    return $1
    +          + hl.highlight(code[1], code[2]).value.trim()
    +          + $3;
    +  });
    +}
    +
    +function order (docs) {
    +  // want index first
    +  for (var i = 0; i < docs.length; ++i) {
    +    if ('index.js' == docs[i].title) {
    +      docs.unshift(docs.splice(i, 1)[0]);
    +    }
    +  }
    +}
    diff --git a/docs/3.0.x/docs/source/home.js b/docs/3.0.x/docs/source/home.js
    new file mode 100644
    index 00000000000..557f27b966b
    --- /dev/null
    +++ b/docs/3.0.x/docs/source/home.js
    @@ -0,0 +1,19 @@
    +
    +var fs = require('fs')
    +var package = require('./../../package.json')
    +var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    +
    +var imgs = [];
    +
    +images.forEach(function (line) {
    +  line = line.trim();
    +  if (!line) return;
    +  line = line.split('|');
    +  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    +});
    +
    +module.exports = {
    +    package: package
    +  , images: imgs
    +  , title: 'ODM'
    +}
    diff --git a/docs/3.0.x/docs/source/index.js b/docs/3.0.x/docs/source/index.js
    new file mode 100644
    index 00000000000..d54229720a1
    --- /dev/null
    +++ b/docs/3.0.x/docs/source/index.js
    @@ -0,0 +1,18 @@
    +
    +exports['index.jade'] = require('./home')
    +exports['docs/api.jade'] = require('./api')
    +exports['docs/index.jade'] = { title: 'Getting Started' }
    +exports['docs/prior.jade'] = require('./prior')
    +exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    +exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    +exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    +exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    +exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    +exports['docs/models.jade'] = { guide: true, title: 'Models' }
    +exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    +exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    +exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    +exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    +exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    +exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    +exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.0.x/docs/source/prior.js b/docs/3.0.x/docs/source/prior.js
    new file mode 100644
    index 00000000000..2e03811d215
    --- /dev/null
    +++ b/docs/3.0.x/docs/source/prior.js
    @@ -0,0 +1,13 @@
    +var fs = require('fs')
    +var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    +releases = releases.split('\n').filter(Boolean);
    +
    +module.exports = exports = {
    +    title: ''
    +  , releases: releases.map(function (version) {
    +      return {
    +          url: version + '/'
    +        , version: version
    +      }
    +    })
    +}
    diff --git a/docs/3.0.x/docs/subdocs.html b/docs/3.0.x/docs/subdocs.html
    new file mode 100644
    index 00000000000..183675028fe
    --- /dev/null
    +++ b/docs/3.0.x/docs/subdocs.html
    @@ -0,0 +1,48 @@
    +Mongoose SubDocuments v3.0.3Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    +
    +var parentSchema = new Schema({
    +  children: [childSchema]
    +})
    +

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = db.model('Parent', parentSchema);
    +var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    +parent.children[0].name = 'Matthew';
    +parent.save(callback);
    +

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    +  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    +  next();
    +});
    +
    +var parent = new Parent({ children: [{ name: 'invalid' }] });
    +parent.save(function (err) {
    +  console.log(err.message) // #sadpanda
    +})
    +

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    +

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = db.model('Parent');
    +var parent = new Parent;
    +
    +// create a comment
    +post.children.push({ name: 'Liesl' });
    +var doc = post.children[0];
    +console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    +doc.isNew; // true
    +
    +post.save(function (err) {
    +  if (err) return handleError(err)
    +  console.log('Success!');
    +});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    +

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    +parent.save(function (err) {
    +  if (err) return handleError(err);
    +  console.log('the sub-doc was removed')
    +});
    +

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    +  children: [{ name: 'string' }]
    +})
    diff --git a/docs/3.0.x/docs/subdocs.jade b/docs/3.0.x/docs/subdocs.jade new file mode 100644 index 00000000000..a3988b34993 --- /dev/null +++ b/docs/3.0.x/docs/subdocs.jade @@ -0,0 +1,80 @@ +extends layout + +block content + h2 Sub Docs + :markdown + [Sub-documents](./api.html#types-embedded-js) are docs with schemas of their own which are elements of a parents document array: + :js + var childSchema = new Schema({ name: 'string' }); + + var parentSchema = new Schema({ + children: [childSchema] + }) + + :markdown + Sub-documents enjoy all the same features as normal [documents](./api.html#document-js). The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved. + :js + var Parent = db.model('Parent', parentSchema); + var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) + parent.children[0].name = 'Matthew'; + parent.save(callback); + + :markdown + If an error occurs in a sub-documents' middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap! + + :js + childSchema.pre('save', function (next) { + if ('invalid' == this.name) return next(new Error('#sadpanda')); + next(); + }); + + var parent = new Parent({ children: [{ name: 'invalid' }] }); + parent.save(function (err) { + console.log(err.message) // #sadpanda + }) + + h3 Finding a sub-document + :markdown + Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. + :js + var doc = parent.children.id(id); + + h3 Adding sub-docs + :markdown + MongooseArray methods such as [push](./api.html#types_array_MongooseArray-push), [unshift](./api.html#types_array_MongooseArray-unshift), [addToSet](./api.html#types_array_MongooseArray-addToSet), and others cast arguments to their proper types transparently: + :js + var Parent = db.model('Parent'); + var parent = new Parent; + + // create a comment + post.children.push({ name: 'Liesl' }); + var doc = post.children[0]; + console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' } + doc.isNew; // true + + post.save(function (err) { + if (err) return handleError(err) + console.log('Success!'); + }); + :markdown + Sub-docs may also be created without adding them to the array by using the [create](./api.html#types_documentarray_MongooseDocumentArray-create) method of MongooseArrays. + :js + var newdoc = post.children.create({ name: 'Aaron' }); + + h3 Removing docs + :markdown + Each sub-document has it's own [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. + :js + var doc = parent.children.id(id).remove(); + parent.save(function (err) { + if (err) return handleError(err); + console.log('the sub-doc was removed') + }); + + h4#altsyntax Alternate declaration syntax + :markdown + _New in v3_ If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal: + :js + var parentSchema = new Schema({ + children: [{ name: 'string' }] + }) diff --git a/docs/3.0.x/docs/validation.html b/docs/3.0.x/docs/validation.html new file mode 100644 index 00000000000..4f500d9dd37 --- /dev/null +++ b/docs/3.0.x/docs/validation.html @@ -0,0 +1,36 @@ +Mongoose Validation v3.0.3Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    + +
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    + +

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    +  color: String,
    +  name: String
    +});
    +
    +var Toy = db.model('Toy', toySchema);
    +
    +Toy.schema.path('color').validate(function (value) {
    +  return /blue|green|white|red|orange|periwinkel/i.test(value);
    +}, 'Invalid color');
    +
    +var toy = new Toy({ color: 'grease'});
    +
    +toy.save(function (err) {
    +  // err.errors.color is a ValidatorError object
    +  
    +  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(err.errors.color.type) // prints "Invalid color"
    +  console.log(err.errors.color.path) // prints "color"
    +  console.log(err.name) // prints "ValidationError"
    +  console.log(err.message) // prints "Validation failed"
    +});
    +

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    diff --git a/docs/3.0.x/docs/validation.jade b/docs/3.0.x/docs/validation.jade new file mode 100644 index 00000000000..a085ea49df7 --- /dev/null +++ b/docs/3.0.x/docs/validation.jade @@ -0,0 +1,54 @@ +extends layout + +block content + h2 Validation + :markdown + Before we get into the specifics of validation syntax, please keep the following rules in mind: + + - Validation is defined in the [SchemaType](./schematypes.html) + - Validation is an internal piece of [middleware](./middleware.html) + - Validation occurs when a document attempts to be [saved](./api.html#model_Model-save), after defaults have been applied + - Validation is asynchronously recursive: when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed. If an error happens, your Model#save callback receives it + - Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, `"min"` is the identifier for the error triggered when a number doesn't meet the [minimum value](./api.html#schema_number_SchemaNumber-min). The path and value that triggered the error can be accessed in the `ValidationError` object + h3 Built in validators + :markdown + Mongoose has several built in validators. + + - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. + - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. + - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum) and [match](./api.html#schema_string_SchemaString-match) validators. + h3 Custom validators + :markdown + Custom validation is declared by passing a validation `function` and an error type to your `SchemaType`s validate method. Read the [API](./api.html#schematype_SchemaType-validate) docs for details on custom validators, async validators, and more. + h3 Validation errors + :markdown + Errors returned after failed validation contain an `errors` object holding the actual `ValidatorErrors`. Each [ValidatorError](./api.html#errors-validation-js) has a `type` and `path` property providing us with a little more error handling flexibility. + :js + var toySchema = new Schema({ + color: String, + name: String + }); + + var Toy = db.model('Toy', toySchema); + + Toy.schema.path('color').validate(function (value) { + return /blue|green|white|red|orange|periwinkel/i.test(value); + }, 'Invalid color'); + + var toy = new Toy({ color: 'grease'}); + + toy.save(function (err) { + // err.errors.color is a ValidatorError object + + console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color' + console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color' + console.log(err.errors.color.type) // prints "Invalid color" + console.log(err.errors.color.path) // prints "color" + console.log(err.name) // prints "ValidationError" + console.log(err.message) // prints "Validation failed" + }); + + :markdown + After a validation error, the document will also have the same `errors` property available: + :js + toy.errors.color.message === err.errors.color.message diff --git a/docs/3.0.x/index.html b/docs/3.0.x/index.html new file mode 100644 index 00000000000..28c55db30f1 --- /dev/null +++ b/docs/3.0.x/index.html @@ -0,0 +1,238 @@ +Mongoose ODM v3.0.3Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

    var mongoose = require('mongoose');
    +var db = mongoose.createConnection('localhost', 'test');
    +
    +var schema = mongoose.Schema({ name: 'string' });
    +var Cat = db.model('Cat', schema);
    +
    +var kitty = new Cat({ name: 'Zildjian' });
    +kitty.save(function (err) {
    +  if (err) // ...
    +  res.end('meow');
    +});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    diff --git a/docs/3.0.x/static.js b/docs/3.0.x/static.js new file mode 100644 index 00000000000..fc0e722dd4e --- /dev/null +++ b/docs/3.0.x/static.js @@ -0,0 +1,17 @@ + +var static = require('node-static'); +var server = new static.Server('.', { cache: 0 }); + +require('http').createServer(function (req, res) { + req.on('end', function () { + server.serve(req, res, function (err) { + if (err) { + console.error(err, req.url); + res.writeHead(err.status, err.headers); + res.end(); + } + }); + }); +}).listen(8088); + +console.error('now listening on localhost:8088'); diff --git a/docs/3.1.x/docs/api.html b/docs/3.1.x/docs/api.html new file mode 100644 index 00000000000..61cc402fddb --- /dev/null +++ b/docs/3.1.x/docs/api.html @@ -0,0 +1,6720 @@ +Mongoose API v3.1.2Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      +  this.connections = [];
      +  this.plugins = [];
      +  this.models = {};
      +  this.modelSchemas = {};
      +  this.options = {};
      +  this.createConnection(); // default connection
      +};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +  this.options[key] = value;
      +  return this;
      +};

      Parameters:

      Example:

      + +
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      + +
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      +  var conn = new Connection(this);
      +  this.connections.push(conn);
      +
      +  if (arguments.length) {
      +    if (rgxReplSet.test(arguments[0])) {
      +      conn.openSet.apply(conn, arguments);
      +    } else {
      +      conn.open.apply(conn, arguments);
      +    }
      +  }
      +
      +  return conn;
      +};

      Parameters:

      • [uri] <String> a mongodb:// URI

      Returns:

      Example:

      + +
      // with mongodb:// URI
      +db = mongoose.createConnection('mongodb://localhost:port/database');
      +
      +// replica sets
      +db = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
      +
      +// with [host, database_name[, port] signature
      +db = mongoose.createConnection('localhost', 'database', port)
      +
      +// initialize now, connect later
      +db = mongoose.createConnection();
      +db.open('localhost', 'database', port);

      Mongoose#connect()

      Opens the default mongoose connection.

      show code
      Mongoose.prototype.connect = function () {
      +  var conn = this.connection;
      +
      +  if (rgxReplSet.test(arguments[0])) {
      +    conn.openSet.apply(conn, arguments);
      +  } else {
      +    conn.open.apply(conn, arguments);
      +  }
      +
      +  return this;
      +};

      Returns:

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


      Mongoose#disconnect([fn])

      Disconnects all connections.

      show code
      Mongoose.prototype.disconnect = function (fn) {
      +  var count = this.connections.length
      +    , error
      +
      +  this.connections.forEach(function(conn){
      +    conn.close(function(err){
      +      if (error) return;
      +
      +      if (err) {
      +        error = err;
      +        if (fn) return fn(err);
      +        throw err;
      +      }
      +
      +      if (fn)
      +        --count || fn();
      +    });
      +  });
      +  return this;
      +};

      Parameters:

      • [fn] <Function> called after all connection close.

      Returns:


      Mongoose#model(name, [schema], [collection], [skipInit])

      Defines a model or retrieves it.

      show code
      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
      +  // normalize collection
      +  if (!(schema instanceof Schema)) {
      +    collection = schema;
      +    schema = false;
      +  }
      +
      +  if ('boolean' === typeof collection) {
      +    skipInit = collection;
      +    collection = null;
      +  }
      +
      +  // look up models for the collection
      +  if (!this.modelSchemas[name]) {
      +    if (!schema && name in SchemaDefaults) {
      +      schema = SchemaDefaults[name];
      +    }
      +
      +    if (schema) {
      +      this.modelSchemas[name] = schema;
      +      for (var i = 0, l = this.plugins.length; i < l; i++) {
      +        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
      +      }
      +    } else {
      +      throw new Error('Schema hasn\'t been registered for model "' + name + '".
      +'
      +                    + 'Use mongoose.model(name, schema)');
      +    }
      +  }
      +
      +  if (!this.models[name]) {
      +    schema || (schema = this.modelSchemas[name]);
      +    collection || (collection = schema.set('collection') || format(name));
      +
      +    var model = Model.compile(name
      +                        , this.modelSchemas[name]
      +                        , collection
      +                        , this.connection
      +                        , this);
      +
      +    if (!skipInit) model.init();
      +
      +    this.models[name] = model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> model name
      • [schema] <Schema>
      • [collection] <String> name (optional, induced from model name)
      • [skipInit] <Boolean> whether to skip initialization (defaults to false)

      Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +
      +// define an Actor model with this mongoose instance
      +mongoose.model('Actor', new Schema({ name: String }));
      +
      +// create a new connection
      +var conn = mongoose.createConnection(..);
      +
      +// retrieve the Actor model
      +var Actor = conn.model('Actor');
      + +

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

      + +

      Example:

      + +
      var schema = new Schema({ name: String });
      +schema.set('collection', 'actor');

      Mongoose#plugin(fn, [opts])

      Declares a global plugin executed on all Schemas.

      show code
      Mongoose.prototype.plugin = function (fn, opts) {
      +  this.plugins.push([fn, opts]);
      +  return this;
      +};

      Parameters:

      Returns:

      Equivalent to calling .plugin(fn) on each Schema you create.


      module.exports

      The exports object is an instance of Mongoose.

      show code
      module.exports = exports = new Mongoose;
      +var mongoose = module.exports;

      mongoose.Collection

      The Mongoose Collection constructor

      show code
      mongoose.Collection = Collection;

      mongoose.Connection

      The Mongoose Connection constructor

      show code
      mongoose.Connection = Connection;

      mongoose.version

      Mongoose version

      show code
      mongoose.version = JSON.parse(
      +  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      +).version;

      mongoose.Mongoose

      The Mongoose constructor

      show code
      mongoose.Mongoose = Mongoose;

      The exports of the mongoose module is an instance of this class.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var mongoose2 = new mongoose.Mongoose();

      mongoose.Schema

      The Mongoose Schema constructor

      show code
      mongoose.Schema = Schema;

      Example:

      + +
      var mongoose = require('mongoose');
      +var Schema = mongoose.Schema;
      +var CatSchema = new Schema(..);

      mongoose.SchemaType

      The Mongoose SchemaType constructor.

      show code
      mongoose.SchemaType = SchemaType;

      mongoose.SchemaTypes

      The various Mongoose SchemaTypes.

      show code
      mongoose.SchemaTypes = Schema.Types;

      Note:

      + +

      Alias of mongoose.Schema.Types for backwards compatibility.


      mongoose.VirtualType

      The Mongoose VirtualType constructor.

      show code
      mongoose.VirtualType = VirtualType;

      mongoose.Types

      The various Mongoose Types.

      show code
      mongoose.Types = Types;

      Example:

      + +
      var mongoose = require('mongoose');
      +var array = mongoose.Types.Array;
      + +

      Types:

      + +
        +
      • Array
      • +
      • Buffer
      • +
      • Document
      • +
      • Embedded
      • +
      • DocumentArray
      • +
      • ObjectId
      • +
      + +

      Using this exposed access to the ObjectId type, we can construct ids on demand.

      + +
      var ObjectId = mongoose.Types.ObjectId;
      +var id1 = new ObjectId;

      mongoose.Query

      The Mongoose Query constructor.

      show code
      mongoose.Query = Query;

      mongoose.Promise

      The Mongoose Promise constructor.

      show code
      mongoose.Promise = Promise;

      mongoose.Model

      The Mongoose Model constructor.

      show code
      mongoose.Model = Model;

      mongoose.Document

      The Mongoose Document constructor.

      show code
      mongoose.Document = Document;

      mongoose.Error

      The MongooseError constructor.

      show code
      mongoose.Error = require('./error');

      mongoose.mongo

      The node-mongodb-native driver Mongoose uses.

      show code
      mongoose.mongo = require('mongodb');

      Mongoose#connection

      The default connection of the mongoose module.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +mongoose.connect(...);
      +mongoose.connection.on('error', cb);
      + +

      This is the connection used by default for every model created using mongoose.model.

      Returns:


    • collection.js

      Collection(name, conn, opts)

      Abstract Collection constructor

      show code
      function Collection (name, conn, opts) {
      +  this.name = name;
      +  this.conn = conn;
      +  this.buffer = true;
      +  this.queue = [];
      +
      +  if ('number' == typeof opts) opts = { size: opts };
      +  this.opts = opts || {};
      +
      +  if (STATES.connected == this.conn.readyState) {
      +    this.onOpen();
      +  }
      +};

      Parameters:

      • name <String> name of the collection
      • conn <Connection> A MongooseConnection instance
      • opts <Object> optional collection options

      This is the base class that drivers inherit from and implement.


      Collection#onOpen()

      Called when the database connects

      show code
      Collection.prototype.onOpen = function () {
      +  var self = this;
      +  this.buffer = false;
      +  self.doQueue();
      +};

      Collection#onClose()

      Called when the database disconnects

      show code
      Collection.prototype.onClose = function () {
      +  this.buffer = true;
      +};

      Collection#addQueue(name, args)

      Queues a method for later execution when its
      database connection opens.

      show code
      Collection.prototype.addQueue = function (name, args) {
      +  this.queue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the method to queue
      • args <Array> arguments to pass to the method when executed

      Collection#doQueue()

      Executes all queued methods and clears the queue.

      show code
      Collection.prototype.doQueue = function () {
      +  for (var i = 0, l = this.queue.length; i < l; i++){
      +    this[this.queue[i][0]].apply(this, this.queue[i][1]);
      +  }
      +  this.queue = [];
      +  return this;
      +};

      Collection#ensureIndex()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.ensureIndex = function(){
      +  throw new Error('Collection#ensureIndex unimplemented by driver');
      +};

      Collection#findAndModify()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findAndModify = function(){
      +  throw new Error('Collection#findAndModify unimplemented by driver');
      +};

      Collection#findOne()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findOne = function(){
      +  throw new Error('Collection#findOne unimplemented by driver');
      +};

      Collection#find()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.find = function(){
      +  throw new Error('Collection#find unimplemented by driver');
      +};

      Collection#insert()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.insert = function(){
      +  throw new Error('Collection#insert unimplemented by driver');
      +};

      Collection#save()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.save = function(){
      +  throw new Error('Collection#save unimplemented by driver');
      +};

      Collection#update()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.update = function(){
      +  throw new Error('Collection#update unimplemented by driver');
      +};

      Collection#getIndexes()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.getIndexes = function(){
      +  throw new Error('Collection#getIndexes unimplemented by driver');
      +};

      Collection#mapReduce()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.mapReduce = function(){
      +  throw new Error('Collection#mapReduce unimplemented by driver');
      +};

      Collection#conn

      The Connection instance


      Collection#name

      The collection name


    • connection.js

      Connection(base)

      Connection constructor

      show code
      function Connection (base) {
      +  this.base = base;
      +  this.collections = {};
      +  this.models = {};
      +  this.replica = false;
      +  this.host = null;
      +  this.port = null;
      +  this.user = null;
      +  this.pass = null;
      +  this.name = null;
      +  this.options = null;
      +  this._readyState = STATES.disconnected;
      +  this._closeCalled = false;
      +  this._hasOpened = false;
      +};

      Parameters:

      Events:

      • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

      • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

      • open: Emitted after we connected and onOpen is executed on all of this connections models.

      • disconnecting: Emitted when connection.close() was executed.

      • disconnected: Emitted after getting disconnected from the db.

      • close: Emitted after we disconnected and onClose executed on all of this connections models.

      • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

      • error: Emitted when an error occurs on this connection.

      • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

      For practical reasons, a Connection equals a Db.


      Connection#open(connection_string, [database], [port], [options], [callback])

      Opens the connection to MongoDB.

      show code
      Connection.prototype.open = function (host, database, port, options, callback) {
      +  var self = this
      +    , uri;
      +
      +  if ('string' === typeof database) {
      +    switch (arguments.length) {
      +      case 2:
      +        port = 27017;
      +      case 3:
      +        switch (typeof port) {
      +          case 'function':
      +            callback = port, port = 27017;
      +            break;
      +          case 'object':
      +            options = port, port = 27017;
      +            break;
      +        }
      +        break;
      +      case 4:
      +        if ('function' === typeof options)
      +          callback = options, options = {};
      +    }
      +  } else {
      +    switch (typeof database) {
      +      case 'function':
      +        callback = database, database = undefined;
      +        break;
      +      case 'object':
      +        options = database;
      +        database = undefined;
      +        callback = port;
      +        break;
      +    }
      +
      +    if (!rgxProtocol.test(host)) {
      +      host = 'mongodb://' + host;
      +    }
      +
      +    uri = url.parse(host);
      +    host = uri.hostname;
      +    port = uri.port || 27017;
      +    database = uri.pathname && uri.pathname.replace(/\//g, '');
      +  }
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // make sure we can open
      +  if (STATES.disconnected !== this.readyState) {
      +    var err = new Error('Trying to open unclosed connection.');
      +    err.state = this.readyState;
      +    this.error(err, callback);
      +    return this;
      +  }
      +
      +  if (!host) {
      +    this.error(new Error('Missing connection hostname.'), callback);
      +    return this;
      +  }
      +
      +  if (!database) {
      +    this.error(new Error('Missing connection database.'), callback);
      +    return this;
      +  }
      +
      +  // handle authentication
      +  if (uri && uri.auth) {
      +    var auth = uri.auth.split(':');
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // Check hostname for user/pass
      +  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
      +    host = host.split('@');
      +    var auth = host.shift().split(':');
      +    host = host.pop();
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // user/pass options
      +  } else if (options && options.user && options.pass) {
      +    this.user = options.user;
      +    this.pass = options.pass;
      +
      +  } else {
      +    this.user = this.pass = undefined;
      +  }
      +
      +  this.name = database;
      +  this.host = host;
      +  this.port = port;
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • connection_string <String> mongodb://uri or the host to which you are connecting
      • [database] <String> database name
      • [port] <Number> database port
      • [options] <Object> options
      • [callback] <Function>

      options is a hash with the following possible properties:

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSetServer instance
      +user    - username for authentication
      +pass    - password for authentication
      + +

      Notes:

      + +

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.


      Connection#openSet(uris, [database], [options], [callback])

      Connects to a replica set.

      show code
      Connection.prototype.openSet = function (uris, database, options, callback) {
      +  var uris = uris.split(',')
      +    , self = this;
      +
      +  switch (arguments.length) {
      +    case 3:
      +      this.name = database;
      +      if ('function' === typeof options) callback = options, options = {};
      +      break;
      +    case 2:
      +      switch (typeof database) {
      +        case 'string':
      +          this.name = database;
      +        case 'function':
      +          callback = database, database = null;
      +          break;
      +        case 'object':
      +          options = database, database = null;
      +          break;
      +      }
      +  }
      +
      +  this.options = options = this.defaultOptions(options);
      +
      +  if (uris.length < 2) {
      +    this.error(new Error('Please provide comma-separated URIs'), callback);
      +    return this;
      +  }
      +
      +  this.replica = true;
      +  this.host = [];
      +  this.port = [];
      +
      +  uris.forEach(function (uri) {
      +    // handle missing protocols
      +    if (!rgxProtocol.test(uri))
      +      uri = 'mongodb://' + uri;
      +
      +    var uri = url.parse(uri);
      +
      +    self.host.push(uri.hostname);
      +    self.port.push(uri.port || 27017);
      +
      +    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
      +      self.name = uri.pathname.replace(/\//g, '');
      +
      +    if (!self.user && uri.auth) {
      +      var auth = uri.auth.split(':');
      +      self.user = auth[0];
      +      self.pass = auth[1];
      +    }
      +  });
      +
      +  if (!this.name) {
      +    this.error(new Error('No database name provided for replica set'), callback);
      +    return this;
      +  }
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • uris <String> comma-separated mongodb:// `URI`s
      • [database] <String> database name if not included in `uris`
      • [options] <Object> passed to the internal driver
      • [callback] <Function>

      Example:

      + +
      var db = mongoose.createConnection();
      +db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
      + +

      The database name and/or auth need only be included in one URI.
      The options is a hash which is passed to the internal driver connection object.

      + +

      Valid options

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSetServer instance
      +user    - username for authentication
      +pass    - password for authentication

      Connection#error(err, callback)

      error

      show code
      Connection.prototype.error = function (err, callback) {
      +  if (callback) return callback(err);
      +  this.emit('error', err);
      +}

      Parameters:

      Graceful error handling, passes error to callback
      if available, else emits error on the connection.


      Connection#_open(callback)

      Handles opening the connection with the appropriate method based on connection type.

      show code
      Connection.prototype._open = function (callback) {
      +  this.readyState = STATES.connecting;
      +  this._closeCalled = false;
      +
      +  var self = this;
      +
      +  var method = this.replica
      +    ? 'doOpenSet'
      +    : 'doOpen';
      +
      +  // open connection
      +  this[method](function (err) {
      +    if (err) {
      +      self.readyState = STATES.disconnected;
      +      if (self._hasOpened) {
      +        if (callback) callback(err);
      +      } else {
      +        self.error(err, callback);
      +      }
      +      return;
      +    }
      +
      +    self.onOpen();
      +    callback && callback();
      +  });
      +}

      Parameters:


      Connection#onOpen()

      Called when the connection is opened

      show code
      Connection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  function open () {
      +    self.readyState = STATES.connected;
      +
      +    // avoid having the collection subscribe to our event emitter
      +    // to prevent 0.3 warning
      +    for (var i in self.collections)
      +      self.collections[i].onOpen();
      +
      +    self.emit('open');
      +  };
      +
      +  // re-authenticate
      +  if (self.user && self.pass)
      +    self.db.authenticate(self.user, self.pass, open);
      +  else
      +    open();
      +};

      Connection#close([callback])

      Closes the connection

      show code
      Connection.prototype.close = function (callback) {
      +  var self = this;
      +  this._closeCalled = true;
      +
      +  switch (this.readyState){
      +    case 0: // disconnected
      +      callback && callback();
      +      break;
      +
      +    case 1: // connected
      +      this.readyState = STATES.disconnecting;
      +      this.doClose(function(err){
      +        if (err){
      +          self.error(err, callback);
      +        } else {
      +          self.onClose();
      +          callback && callback();
      +        }
      +      });
      +      break;
      +
      +    case 2: // connecting
      +      this.once('open', function(){
      +        self.close(callback);
      +      });
      +      break;
      +
      +    case 3: // disconnecting
      +      if (!callback) break;
      +      this.once('close', function () {
      +        callback();
      +      });
      +      break;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Connection#onClose()

      Called when the connection closes

      show code
      Connection.prototype.onClose = function () {
      +  this.readyState = STATES.disconnected;
      +
      +  // avoid having the collection subscribe to our event emitter
      +  // to prevent 0.3 warning
      +  for (var i in this.collections)
      +    this.collections[i].onClose();
      +
      +  this.emit('close');
      +};

      Connection#collection(name, [options])

      Retrieves a collection, creating it if not cached.

      show code
      Connection.prototype.collection = function (name, options) {
      +  if (!(name in this.collections))
      +    this.collections[name] = new Collection(name, this, options);
      +  return this.collections[name];
      +};

      Parameters:

      • name <String> of the collection
      • [options] <Object> optional collection options

      Returns:


      Connection#model(name, [schema], [collection])

      Defines or retrieves a model.

      show code
      Connection.prototype.model = function (name, schema, collection) {
      +  if (!this.models[name]) {
      +    var model = this.base.model(name, schema, collection, true)
      +      , Model
      +
      +    if (this != model.prototype.db) {
      +      // subclass model using this connection and collection name
      +      Model = function Model (doc, fields, skipId) {
      +        if (!(this instanceof Model))
      +          return new Model(doc, fields, skipId);
      +        model.call(this, doc, fields, skipId);
      +      };
      +
      +      Model.__proto__ = model;
      +      Model.prototype.__proto__ = model.prototype;
      +      Model.db = Model.prototype.db = this;
      +
      +      // collection name discovery
      +      if ('string' === typeof schema) {
      +        collection = schema;
      +      }
      +
      +      if (!collection) {
      +        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
      +      }
      +
      +      var s = 'string' != typeof schema
      +        ? schema
      +        : model.prototype.schema;
      +
      +      Model.prototype.collection = this.collection(collection, s && s.options.capped);
      +      Model.collection = Model.prototype.collection;
      +      Model.init();
      +    }
      +
      +    this.models[name] = Model || model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> the model name
      • [schema] <Schema> a schema. necessary when defining a model
      • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

      Returns:

      • <Model> The compiled model
      var mongoose = require('mongoose');
      +var db = mongoose.createConnection(..);
      +db.model('Venue', new Schema(..));
      +var Ticket = db.model('Ticket', new Schema(..));
      +var Venue = db.model('Venue');

      Connection#setProfiling(level, [ms], callback)

      Set profiling level.

      show code
      Connection.prototype.setProfiling = function (level, ms, callback) {
      +  if (STATES.connected !== this.readyState) {
      +    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
      +  }
      +
      +  if (!callback) callback = ms, ms = 100;
      +
      +  var cmd = {};
      +
      +  switch (level) {
      +    case 0:
      +    case 'off':
      +      cmd.profile = 0;
      +      break;
      +    case 1:
      +    case 'slow':
      +      cmd.profile = 1;
      +      if ('number' !== typeof ms) {
      +        ms = parseInt(ms, 10);
      +        if (isNaN(ms)) ms = 100;
      +      }
      +      cmd.slowms = ms;
      +      break;
      +    case 2:
      +    case 'all':
      +      cmd.profile = 2;
      +      break;
      +    default:
      +      return callback(new Error('Invalid profiling level: '+ level));
      +  }
      +
      +  this.db.executeDbCommand(cmd, function (err, resp) {
      +    if (err) return callback(err);
      +
      +    var doc = resp.documents[0];
      +
      +    err = 1 === doc.ok
      +      ? null
      +      : new Error('Could not set profiling level to: '+ level)
      +
      +    callback(err, doc);
      +  });
      +};

      Parameters:

      • level <Number, String> either off (0), slow (1), or all (2)
      • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
      • callback <Function>

      Connection#defaultOptions(options)

      Prepares default connection options.

      show code
      Connection.prototype.defaultOptions = function (options) {
      +  var o = options || {};
      +
      +  o.server = o.server || {};
      +
      +  if (!('auto_reconnect' in o.server)) {
      +    o.server.auto_reconnect = true;
      +  }
      +
      +  o.db = o.db || {};
      +  o.db.forceServerObjectId = false;
      +
      +  return o;
      +}

      Parameters:


      Connection#db

      The mongodb.Db instance, set when the connection is opened


      Connection#collections

      A hash of the collections associated with this connection


      Connection#readyState

      Connection ready state

      + +
        +
      • 0 = disconnected
      • +
      • 1 = connected
      • +
      • 2 = connecting
      • +
      • 3 = disconnecting
      • +
      + +

      Each state change emits its associated event name.

      + +

      Example

      + +
      conn.on('connected', callback);
      +conn.on('disconnected', callback);

    • document.js

      Document(obj, [fields], [skipId])

      Document constructor.

      show code
      function Document (obj, fields, skipId) {
      +  // node <0.4.3 bug
      +  if (!this._events) this._events = {};
      +  this.setMaxListeners(0);
      +
      +  if ('boolean' === typeof fields) {
      +    this._strictMode = fields;
      +    this._selected = fields = undefined;
      +  } else {
      +    this._strictMode = this.schema.options && this.schema.options.strict;
      +    this._selected = fields;
      +  }
      +
      +  this.isNew = true;
      +  this.errors = undefined;
      +  this._shardval = undefined;
      +  this._saveError = undefined;
      +  this._validationError = undefined;
      +  this._adhocPaths = undefined;
      +  this._removing = undefined;
      +  this._inserting = undefined;
      +  this.__version = undefined;
      +  this.__getters = {};
      +  this.__id = undefined;
      +
      +  this._activePaths = new ActiveRoster;
      +
      +  var required = this.schema.requiredPaths();
      +  for (var i = 0; i < required.length; ++i) {
      +    this._activePaths.require(required[i]);
      +  }
      +
      +  this._doc = this._buildDoc(obj, fields, skipId);
      +  if (obj) this.set(obj, undefined, true);
      +  this._registerHooks();
      +};

      Parameters:

      • obj <Object> the values to set
      • [fields] <Object> the fields which were selected in the query returning this document
      • [skipId] <Boolean> bool, should we auto create an ObjectId _id

      Events:

      • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

      • save: Emitted when the document is successfully saved


      Document#_buildDoc(obj, [fields], [skipId])

      Builds the default doc structure

      show code
      Document.prototype._buildDoc = function (obj, fields, skipId) {
      +  var doc = {}
      +    , self = this
      +    , exclude
      +    , keys
      +    , key
      +    , ki
      +
      +  // determine if this doc is a result of a query with
      +  // excluded fields
      +  if (fields && 'Object' === fields.constructor.name) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('_id' !== keys[ki]) {
      +        exclude = 0 === fields[keys[ki]];
      +        break;
      +      }
      +    }
      +  }
      +
      +  var paths = Object.keys(this.schema.paths)
      +    , plen = paths.length
      +    , ii = 0
      +
      +  for (; ii < plen; ++ii) {
      +    var p = paths[ii];
      +
      +    if ('_id' == p) {
      +      if (skipId) continue;
      +      if (obj && '_id' in obj) continue;
      +    }
      +
      +    var type = this.schema.paths[p]
      +      , path = p.split('.')
      +      , len = path.length
      +      , last = len-1
      +      , doc_ = doc
      +      , i = 0
      +
      +    for (; i < len; ++i) {
      +      var piece = path[i]
      +        , def
      +
      +      if (i === last) {
      +        if (fields) {
      +          if (exclude) {
      +            // apply defaults to all non-excluded fields
      +            if (p in fields) continue;
      +
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +
      +          } else if (p in fields) {
      +            // selected field
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +          }
      +        } else {
      +          def = type.getDefault(self, true);
      +          if ('undefined' !== typeof def) {
      +            doc_[piece] = def;
      +            self._activePaths.default(p);
      +          }
      +        }
      +      } else {
      +        doc_ = doc_[piece] || (doc_[piece] = {});
      +      }
      +    }
      +  };
      +
      +  return doc;
      +};

      Parameters:

      Returns:


      Document#init(doc, fn)

      Initializes the document without setters or marking anything modified.

      show code
      Document.prototype.init = function (doc, fn) {
      +  this.isNew = false;
      +
      +  init(this, doc, this._doc);
      +  this._storeShard();
      +
      +  this.emit('init');
      +  if (fn) fn(null);
      +  return this;
      +};

      Parameters:

      Called internally after a document is returned from mongodb.


      Document#_storeShard()

      Stores the current values of the shard keys.

      show code
      Document.prototype._storeShard = function _storeShard () {
      +  // backwards compat
      +  var key = this.schema.options.shardKey || this.schema.options.shardkey;
      +  if (!(key && 'Object' == key.constructor.name)) return;
      +
      +  var orig = this._shardval = {}
      +    , paths = Object.keys(key)
      +    , len = paths.length
      +    , val
      +
      +  for (var i = 0; i < len; ++i) {
      +    val = this.getValue(paths[i]);
      +    if (isMongooseObject(val)) {
      +      orig[paths[i]] = val.toObject({ depopulate: true })
      +    } else if (null != val && val.valueOf) {
      +      orig[paths[i]] = val.valueOf();
      +    } else {
      +      orig[paths[i]] = val;
      +    }
      +  }
      +}

      Note:

      + +

      Shard key values do not / are not allowed to change.


      Document#update(doc, options, callback)

      Sends an update command with this document _id as the query selector.

      show code
      Document.prototype.update = function update () {
      +  var args = utils.args(arguments);
      +  args.unshift({_id: this._id});
      +  this.constructor.update.apply(this.constructor, args);
      +}

      Parameters:

      Returns:

      Example:

      + +
      weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
      + +

      Valid options:

      + +
        +
      • safe safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +

      Document#set(path, val, [type])

      Sets the value of a path, or many paths.

      show code
      Document.prototype.set = function (path, val, type) {
      +  var constructing = true === type
      +    , adhoc = type && true !== type
      +    , adhocs
      +
      +  if (adhoc) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  if ('string' !== typeof path) {
      +    // new Document({ key: val })
      +
      +    if (null === path || undefined === path) {
      +      var _ = path;
      +      path = val;
      +      val = _;
      +
      +    } else {
      +      var prefix = val
      +        ? val + '.'
      +        : '';
      +
      +      if (path instanceof Document) path = path._doc;
      +
      +      var keys = Object.keys(path)
      +        , i = keys.length
      +        , pathtype
      +        , key
      +
      +      while (i--) {
      +        key = keys[i];
      +        if (null != path[key] && 'Object' === path[key].constructor.name
      +          && !(this._path(prefix + key) instanceof MixedSchema)) {
      +          this.set(path[key], prefix + key, constructing);
      +        } else if (this._strictMode) {
      +          pathtype = this.schema.pathType(prefix + key);
      +          if ('real' === pathtype || 'virtual' === pathtype) {
      +            this.set(prefix + key, path[key], constructing);
      +          } else if ('throw' == this._strictMode) {
      +            throw new Error("Field `" + key + "` is not in schema.");
      +          }
      +        } else if (undefined !== path[key]) {
      +          this.set(prefix + key, path[key], constructing);
      +        }
      +      }
      +
      +      return this;
      +    }
      +  }
      +
      +  // ensure _strict is honored for obj props
      +  // docschema = new Schema({ path: { nest: 'string' }})
      +  // doc.set('path', obj);
      +  var pathType = this.schema.pathType(path);
      +  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
      +    this.setValue(path, null);
      +    this.set(val, path, constructing);
      +    return this;
      +  }
      +
      +  var schema;
      +  if ('adhocOrUndefined' == pathType && this._strictMode) {
      +    return this;
      +  } else if ('virtual' == pathType) {
      +    schema = this.schema.virtualpath(path);
      +    schema.applySetters(val, this);
      +    return this;
      +  } else {
      +    schema = this._path(path);
      +  }
      +
      +  var parts = path.split('.')
      +    , pathToMark
      +
      +  // When using the $set operator the path to the field must already exist.
      +  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
      +
      +  if (parts.length <= 1) {
      +    pathToMark = path;
      +  } else {
      +    for (var i = 0; i < parts.length; ++i) {
      +      var part = parts[i];
      +      var subpath = parts.slice(0, i).concat(part).join('.');
      +      if (this.isDirectModified(subpath) // earlier prefixes that are already
      +                                         // marked as dirty have precedence
      +          || this.get(subpath) === null) {
      +        pathToMark = subpath;
      +        break;
      +      }
      +    }
      +
      +    if (!pathToMark) pathToMark = path;
      +  }
      +
      +  if (!schema || null === val || undefined === val) {
      +    this._set(pathToMark, path, constructing, parts, schema, val);
      +    return this;
      +  }
      +
      +  var self = this;
      +
      +  // if this doc is being constructed we should not
      +  // trigger getters.
      +  var priorVal = constructing
      +    ? undefined
      +    : this.get(path);
      +
      +  var shouldSet = this.try(function(){
      +    val = schema.applySetters(val, self, false, priorVal);
      +  });
      +
      +  if (shouldSet) {
      +    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
      +  }
      +
      +  return this;
      +}

      Parameters:

      Example:

      + +
      // path, value
      +doc.set(path, value)
      +
      +// object
      +doc.set({
      +    path  : value
      +  , path2 : {
      +       path  : value
      +    }
      +})
      +
      +// only-the-fly cast to number
      +doc.set(path, value, Number)
      +
      +// only-the-fly cast to string
      +doc.set(path, value, String)

      Document#_set()

      Handles the actual setting of the value and marking the path modified if appropriate.

      show code
      Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {
      +  if (this.isNew) {
      +    this.markModified(pathToMark);
      +  } else {
      +
      +    priorVal || (priorVal = this.get(path));
      +
      +    if (!this.isDirectModified(pathToMark)) {
      +      if (undefined === val && !this.isSelected(path)) {
      +        // special case:
      +        // when a path is not selected in a query its initial
      +        // value will be undefined.
      +        this.markModified(pathToMark, priorVal);
      +      } else if (undefined === val && path in this._activePaths.states.default) {
      +        // do nothing
      +        // unsetting the default value which was never saved
      +      } else if (!deepEqual(val, priorVal)) {
      +        this.markModified(pathToMark, priorVal);
      +      } else if (!constructing &&
      +                 null != val &&
      +                 path in this._activePaths.states.default &&
      +                 deepEqual(val, schema.getDefault(this, constructing))) {
      +        // special case:
      +        // a path with a default was $unset on the server
      +        // and the user is setting it to the same value again
      +        this.markModified(pathToMark, priorVal);
      +      }
      +    }
      +  }
      +
      +  var obj = this._doc
      +    , i = 0
      +    , l = parts.length
      +
      +  for (; i < l; i++) {
      +    var next = i + 1
      +      , last = next === l;
      +
      +    if (last) {
      +      obj[parts[i]] = val;
      +    } else {
      +      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
      +        obj = obj[parts[i]];
      +      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
      +        obj = obj[parts[i]];
      +      } else {
      +        obj = obj[parts[i]] = {};
      +      }
      +    }
      +  }
      +};

      Document#getValue(path)

      Gets a raw value from a path (no getters)

      show code
      Document.prototype.getValue = function (path) {
      +  var parts = path.split('.')
      +    , obj = this._doc
      +    , part;
      +
      +  for (var i = 0, l = parts.length; i < l; i++) {
      +    part = parts[i];
      +    obj = obj.getValue
      +        ? obj.getValue(part) // If we have an embedded array document member
      +        : obj[part];
      +    if (!obj) return obj;
      +  }
      +
      +  return obj;
      +}

      Parameters:


      Document#setValue(path, value)

      Sets a raw value for a path (no casting, setters, transformations)

      show code
      Document.prototype.setValue = function (path, val) {
      +  var parts = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, len = parts.length-1; i < len; i++) {
      +    obj = obj[parts[i]];
      +  }
      +
      +  obj[parts[len]] = val;
      +  return this;
      +};

      Parameters:


      Document#get(path, [type])

      Returns the value of a path.

      show code
      Document.prototype.get = function (path, type) {
      +  var adhocs;
      +  if (type) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  var schema = this._path(path) || this.schema.virtualpath(path)
      +    , pieces = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, l = pieces.length; i < l; i++) {
      +    obj = null == obj ? null : obj[pieces[i]];
      +  }
      +
      +  if (schema) {
      +    obj = schema.applyGetters(obj, this);
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Example

      + +
      // path
      +doc.get('age') // 47
      +
      +// dynamic casting to a string
      +doc.get('age', String) // "47"

      Document#_path(path)

      Returns the schematype for the given path.

      show code
      Document.prototype._path = function (path) {
      +  var adhocs = this._adhocPaths
      +    , adhocType = adhocs && adhocs[path];
      +
      +  if (adhocType) {
      +    return adhocType;
      +  } else {
      +    return this.schema.path(path);
      +  }
      +};

      Parameters:


      Document#markModified(path)

      Marks the path as having pending changes to write to the db.

      show code
      Document.prototype.markModified = function (path) {
      +  this._activePaths.modify(path);
      +};

      Parameters:

      • path <String> the path to mark modified

      Very helpful when using Mixed types.

      + +

      Example:

      + +
      doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');
      +doc.save() // changes to mixed.type are now persisted

      Document#try(fn, scope)

      Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

      show code
      Document.prototype.try = function (fn, scope) {
      +  var res;
      +  try {
      +    fn.call(scope);
      +    res = true;
      +  } catch (e) {
      +    this._error(e);
      +    res = false;
      +  }
      +  return res;
      +};

      Parameters:

      • fn <Function> function to execute
      • scope <Object> the scope with which to call fn

      Document#modifiedPaths()

      Returns the list of paths that have been modified.

      show code
      Document.prototype.modifiedPaths = function () {
      +  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
      +
      +  return directModifiedPaths.reduce(function (list, path) {
      +    var parts = path.split('.');
      +    return list.concat(parts.reduce(function (chains, part, i) {
      +      return chains.concat(parts.slice(0, i).concat(part).join('.'));
      +    }, []));
      +  }, []);
      +};

      Returns:


      Document#isModified([path])

      Returns true if this document was modified, else false.

      show code
      Document.prototype.isModified = function (path) {
      +  return path
      +    ? !!~this.modifiedPaths().indexOf(path)
      +    : this._activePaths.some('modify');
      +};

      Parameters:

      Returns:

      If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

      + +

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isModified()                    // true
      +doc.isModified('documents')         // true
      +doc.isModified('documents.0.title') // true
      +doc.isDirectModified('documents')   // false

      Document#isDirectModified(path)

      Returns true if path was directly set and modified, else false.

      show code
      Document.prototype.isDirectModified = function (path) {
      +  return (path in this._activePaths.states.modify);
      +};

      Parameters:

      Returns:

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isDirectModified('documents.0.title') // true
      +doc.isDirectModified('documents') // false

      Document#isInit(path)

      Checks if path was initialized.

      show code
      Document.prototype.isInit = function (path) {
      +  return (path in this._activePaths.states.init);
      +};

      Parameters:

      Returns:


      Document#isSelected(path)

      Checks if path was selected in the source query which initialized this document.

      show code
      Document.prototype.isSelected = function isSelected (path) {
      +  if (this._selected) {
      +
      +    if ('_id' === path) {
      +      return 0 !== this._selected._id;
      +    }
      +
      +    var paths = Object.keys(this._selected)
      +      , i = paths.length
      +      , inclusive = false
      +      , cur
      +
      +    if (1 === i && '_id' === paths[0]) {
      +      // only _id was selected.
      +      return 0 === this._selected._id;
      +    }
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +      inclusive = !! this._selected[cur];
      +      break;
      +    }
      +
      +    if (path in this._selected) {
      +      return inclusive;
      +    }
      +
      +    i = paths.length;
      +    var pathDot = path + '.';
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +
      +      if (0 === cur.indexOf(pathDot)) {
      +        return inclusive;
      +      }
      +
      +      if (0 === pathDot.indexOf(cur)) {
      +        return inclusive;
      +      }
      +    }
      +
      +    return ! inclusive;
      +  }
      +
      +  return true;
      +}

      Parameters:

      Returns:

      Example

      + +
      Thing.findOne().select('name').exec(function (err, doc) {
      +   doc.isSelected('name') // true
      +   doc.isSelected('age')  // false
      +})

      Document#validate(cb)

      Executes registered validation rules for this document.

      show code
      Document.prototype.validate = function (cb) {
      +  var self = this
      +
      +  // only validate required fields when necessary
      +  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
      +    if (!self.isSelected(path) && !self.isModified(path)) return false;
      +    return true;
      +  });
      +
      +  paths = paths.concat(Object.keys(this._activePaths.states.init));
      +  paths = paths.concat(Object.keys(this._activePaths.states.modify));
      +
      +  if (0 === paths.length) {
      +    complete();
      +    return this;
      +  }
      +
      +  var validating = {}
      +    , total = 0;
      +
      +  paths.forEach(validatePath);
      +  return this;
      +
      +  function validatePath (path) {
      +    if (validating[path]) return;
      +
      +    validating[path] = true;
      +    total++;
      +
      +    process.nextTick(function(){
      +      var p = self.schema.path(path);
      +      if (!p) return --total || complete();
      +
      +      p.doValidate(self.getValue(path), function (err) {
      +        if (err) self.invalidate(path, err, true);
      +        --total || complete();
      +      }, self);
      +    });
      +  }
      +
      +  function complete () {
      +    var err = self._validationError;
      +    self._validationError = undefined;
      +    cb(err);
      +  }
      +};

      Parameters:

      • cb <Function> called after validation completes, passing an error if one occurred

      Note:

      + +

      This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

      + +

      Example:

      + +
      doc.validate(function (err) {
      +  if (err) handleError(err);
      +  else // validation passed
      +});

      Document#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      Document.prototype.invalidate = function (path, err) {
      +  if (!this._validationError) {
      +    this._validationError = new ValidationError(this);
      +  }
      +
      +  if (!err || 'string' === typeof err) {
      +    err = new ValidatorError(path, err);
      +  }
      +
      +  this._validationError.errors[path] = err;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> the error which states the reason `path` was invalid

      Document#_reset()

      Resets the internal modified state of this document.

      show code
      Document.prototype._reset = function reset () {
      +  var self = this;
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this._activePaths
      +  .map('init', 'modify', function (i) {
      +    return self.getValue(i);
      +  })
      +  .filter(function (val) {
      +    return (val && val instanceof DocumentArray && val.length);
      +  })
      +  .forEach(function (array) {
      +    array.forEach(function (doc) {
      +      doc._reset();
      +    });
      +  });
      +
      +  // clear atomics
      +  this._dirty().forEach(function (dirt) {
      +    var type = dirt.value;
      +    if (type && type._atomics) {
      +      type._atomics = {};
      +    }
      +  });
      +
      +  // Clear 'modify'('dirty') cache
      +  this._activePaths.clear('modify');
      +  this._validationError = undefined;
      +  this.errors = undefined;
      +  var self = this;
      +  this.schema.requiredPaths().forEach(function (path) {
      +    self._activePaths.require(path);
      +  });
      +
      +  return this;
      +}

      Returns:


      Document#_dirty()

      Returns this documents dirty paths / vals.

      show code
      Document.prototype._dirty = function _dirty () {
      +  var self = this;
      +
      +  var all = this._activePaths.map('modify', function (path) {
      +    return { path: path
      +           , value: self.getValue(path)
      +           , schema: self._path(path) };
      +  });
      +
      +  // Sort dirty paths in a flat hierarchy.
      +  all.sort(function (a, b) {
      +    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
      +  });
      +
      +  // Ignore "foo.a" if "foo" is dirty already.
      +  var minimal = []
      +    , lastPath
      +    , top;
      +
      +  all.forEach(function (item, i) {
      +    if (item.path.indexOf(lastPath) !== 0) {
      +      lastPath = item.path + '.';
      +      minimal.push(item);
      +      top = item;
      +    } else {
      +      if (!(item.value && top.value)) return;
      +
      +      // special case for top level MongooseArrays
      +      if (top.value._atomics && top.value.hasAtomics()) {
      +        // the `top` array itself and a sub path of `top` are being modified.
      +        // the only way to honor all of both modifications is through a $set
      +        // of entire array.
      +        top.value._atomics = {};
      +        top.value._atomics.$set = top.value;
      +      }
      +    }
      +  });
      +
      +  top = lastPath = null;
      +  return minimal;
      +}

      Document#_setSchema(schema)

      Assigns/compiles schema into this documents prototype.

      show code
      Document.prototype._setSchema = function (schema) {
      +  compile(schema.tree, this);
      +  this.schema = schema;
      +}

      Parameters:


      Document#_registerHooks()

      Register default hooks

      show code
      Document.prototype._registerHooks = function _registerHooks () {
      +  if (!this.save) return;
      +
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this.pre('save', function (next) {
      +    // we keep the error semaphore to make sure we don't
      +    // call `save` unnecessarily (we only need 1 error)
      +    var subdocs = 0
      +      , error = false
      +      , self = this;
      +
      +    // check for DocumentArrays
      +    var arrays = this._activePaths
      +    .map('init', 'modify', function (i) {
      +      return self.getValue(i);
      +    })
      +    .filter(function (val) {
      +      return (val && val instanceof DocumentArray && val.length);
      +    });
      +
      +    if (!arrays.length)
      +      return next();
      +
      +    arrays.forEach(function (array) {
      +      subdocs += array.length;
      +      array.forEach(function (value) {
      +        if (error) return;
      +
      +        value.save(function (err) {
      +          if (error) return;
      +
      +          if (err) {
      +            error = true;
      +            self._validationError = undefined;
      +            return next(err);
      +          }
      +
      +          --subdocs || next();
      +        });
      +      });
      +    });
      +  }, function (err) {
      +    // emit on the Model if listening
      +    if (this.constructor.listeners('error').length) {
      +      this.constructor.emit('error', err);
      +    } else {
      +      // emit on the connection
      +      if (!this.db.listeners('error').length) {
      +        err.stack = 'No listeners detected, throwing. '
      +                  + 'Consider adding an error listener to your connection.
      +'
      +                  + err.stack
      +      }
      +      this.db.emit('error', err);
      +    }
      +  }).pre('save', function checkForExistingErrors (next) {
      +    // if any doc.set() calls failed
      +    if (this._saveError) {
      +      next(this._saveError);
      +      this._saveError = null;
      +    } else {
      +      next();
      +    }
      +  }).pre('save', function validation (next) {
      +    return this.validate(next);
      +  });
      +
      +  // add user defined queues
      +  this._doQueue();
      +};

      Document#_error(err)

      Registers an error

      show code
      Document.prototype._error = function (err) {
      +  this._saveError = err;
      +  return this;
      +};

      Parameters:


      Document#_doQueue()

      Executes methods queued from the Schema definition

      show code
      Document.prototype._doQueue = function () {
      +  var q = this.schema && this.schema.callQueue;
      +  if (q) {
      +    for (var i = 0, l = q.length; i < l; i++) {
      +      this[q[i][0]].apply(this, q[i][1]);
      +    }
      +  }
      +  return this;
      +};

      Document#toObject([options])

      Converts this document into a plain javascript object

      show code
      Document.prototype.toObject = function (options) {
      +  // When internally saving this document we always pass options,
      +  // bypassing the custom schema options.
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toObject
      +      ? clone(this.schema.options.toObject)
      +      : {};
      +  }
      +
      +  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
      +
      +  var ret = clone(this._doc, options);
      +
      +  if (options.virtuals || options.getters && false !== options.virtuals) {
      +    applyGetters(this, ret, 'virtuals', options);
      +  }
      +
      +  if (options.getters) {
      +    applyGetters(this, ret, 'paths', options);
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Options:

      + +
        +
      • getters apply all getters (path and virtual getters)
      • +
      • virtuals apply virtual getters (can override getters option)
      • +
      • minimize remove empty objects (defaults to true)
      • +
      + +

      Example of only applying path getters

      + +
      doc.toObject({ getters: true, virtuals: false })
      + +

      Example of only applying virtual getters

      + +
      doc.toObject({ virtuals: true })
      + +

      Example of applying both path and virtual getters

      + +
      doc.toObject({ getters: true })
      + +

      To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

      + +
      schema.set('toObject', { virtuals: true })
      + +

      See schema options for details.


      Document#toJSON(options)

      The return value of this method is used in calls to JSON.stringify(doc).

      show code
      Document.prototype.toJSON = function (options) {
      +  // check for object type since an array of documents
      +  // being stringified passes array indexes instead
      +  // of options objects. JSON.stringify([doc, doc])
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toJSON
      +      ? clone(this.schema.options.toJSON)
      +      : {};
      +  }
      +  options.json = true;
      +  return this.toObject(options);
      +};

      Parameters:

      • options <Object> same options as `Document#toObject`

      Returns:

      This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

      + +
      schema.set('toJSON', { virtuals: true })
      + +

      See schema options for details.


      Document#inspect()

      Helper for console.log

      show code
      Document.prototype.inspect = function (options) {
      +  var opts = options && 'Object' == options.constructor.name
      +    ? options
      +    : undefined
      +  return inspect(this.toObject(opts));
      +};

      Document#toString()

      Helper for console.log


      Document#equals(doc)

      Returns true if the Document stores the same data as doc.

      show code
      Document.prototype.equals = function (doc) {
      +  var tid = this.get('_id');
      +  var docid = doc.get('_id');
      +  return tid.equals
      +    ? tid.equals(docid)
      +    : tid === docid;
      +};

      Parameters:

      Returns:

      Documents are considered equal when they have matching _ids.


      Document#errors

      Hash containing current validation errors.


      Document#id

      The string version of this documents _id.

      + +

      Note:

      + +

      This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

      + +
      new Schema({ name: String }, { id: false });

      Document#isNew

      Boolean flag specifying if the document is new.


      Document#schema

      The documents schema.


    • drivers/node-mongodb-native/collection.js

      NativeCollection()

      A node-mongodb-native collection implementation.

      show code
      function NativeCollection () {
      +  this.collection = null;
      +  MongooseCollection.apply(this, arguments);
      +}

      Inherits:

      All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


      NativeCollection#onOpen()

      Called when the connection opens.

      show code
      NativeCollection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  if (this.collection) {
      +    return MongooseCollection.prototype.onOpen.call(self);
      +  }
      +
      +  if (!self.opts.size) {
      +    // non-capped
      +    return self.conn.db.collection(self.name, callback);
      +  }
      +
      +  // capped
      +  return self.conn.db.collection(self.name, function (err, c) {
      +    if (err) return callback(err);
      +
      +    // discover if this collection exists and if it is capped
      +    c.options(function (err, exists) {
      +      if (err) return callback(err);
      +
      +      if (exists) {
      +        if (exists.capped) {
      +          callback(null, c);
      +        } else {
      +          var msg = 'A non-capped collection exists with this name.
      +
      +'
      +                  + ' To use this collection as a capped collection, please '
      +                  + 'first convert it.
      +'
      +                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
      +          err = new Error(msg);
      +          callback(err);
      +        }
      +      } else {
      +        // create
      +        var opts = utils.clone(self.opts);
      +        opts.capped = true;
      +        self.conn.db.createCollection(self.name, opts, callback);
      +      }
      +    });
      +  });
      +
      +  function callback (err, collection) {
      +    if (err) {
      +      // likely a strict mode error
      +      self.conn.emit('error', err);
      +    } else {
      +      self.collection = collection;
      +      MongooseCollection.prototype.onOpen.call(self);
      +    }
      +  };
      +};

      NativeCollection#onClose()

      Called when the connection closes

      show code
      NativeCollection.prototype.onClose = function () {
      +  MongooseCollection.prototype.onClose.call(this);
      +};

      NativeCollection#getIndexes(callback)

      Retreives information about this collections indexes.

      Parameters:


    • drivers/node-mongodb-native/connection.js

      NativeConnection()

      A node-mongodb-native connection implementation.

      show code
      function NativeConnection() {
      +  MongooseConnection.apply(this, arguments);
      +};

      Inherits:


      NativeConnection#doOpen(fn)

      Opens the connection to MongoDB.

      show code
      NativeConnection.prototype.doOpen = function (fn) {
      +  var server
      +    , self = this;
      +
      +  if (!this.db) {
      +    server = new mongo.Server(this.host, Number(this.port), this.options.server);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};
      +
      +function listen (conn) {
      +  if (conn._listening) return;
      +  conn._listening = true;
      +
      +  conn.db.on('close', function(){
      +    if (conn._closeCalled) return;
      +
      +    // the driver never emits an `open` event. auto_reconnect still
      +    // emits a `close` event but since we never get another
      +    // `open` we can't emit close
      +    if (conn.db.serverConfig.autoReconnect) {
      +      conn.readyState = STATES.disconnected;
      +      conn.emit('close');
      +      return;
      +    }
      +    conn.onClose();
      +  });
      +  conn.db.on('error', function(err){
      +    conn.emit('error', err);
      +  });
      +  conn.db.on('timeout', function(err){
      +    var error = new Error(err && err.err || 'connection timeout');
      +    conn.emit('error', error);
      +  });
      +  conn.db.on('open', function (err, db) {
      +    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
      +      conn.readyState = STATES.connected;
      +      conn.emit('reconnected')
      +    }
      +  })
      +}

      Parameters:

      Returns:


      NativeConnection#doOpenSet(fn)

      Opens a connection to a MongoDB ReplicaSet.

      show code
      NativeConnection.prototype.doOpenSet = function (fn) {
      +  if (!this.db) {
      +    var servers = []
      +      , ports = this.port
      +      , self = this
      +
      +    this.host.forEach(function (host, i) {
      +      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
      +    });
      +
      +    var server = new ReplSetServers(servers, this.options.replset);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +
      +    this.db.on('fullsetup', function () {
      +      self.emit('fullsetup')
      +    });
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:

      See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


      NativeConnection#doClose(fn)

      Closes the connection

      show code
      NativeConnection.prototype.doClose = function (fn) {
      +  this.db.close();
      +  if (fn) fn();
      +  return this;
      +}

      Parameters:

      Returns:


    • error.js

      MongooseError()

      Mongoose error

      show code
      function MongooseError (msg) {
      +  Error.call(this);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.message = msg;
      +  this.name = 'MongooseError';
      +};

      Inherits:


    • errors/cast.js

      CastError(type, value)

      Casting Error constructor.

      show code
      function CastError (type, value) {
      +  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'CastError';
      +  this.type = type;
      +  this.value = value;
      +};

      Parameters:

      Inherits:


    • errors/document.js

      DocumentError(msg)

      Document Error

      show code
      function DocumentError (msg) {
      +  MongooseError.call(this, msg);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'DocumentError';
      +};

      Parameters:

      Inherits:


    • errors/validation.js

      ValidationError(instance)

      Document Validation Error

      show code
      function ValidationError (instance) {
      +  MongooseError.call(this, "Validation failed");
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidationError';
      +  this.errors = instance.errors = {};
      +};

      Parameters:

      Inherits:


      ValidationError#toString()

      Console.log helper

      show code
      ValidationError.prototype.toString = function () {
      +  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
      +    return String(this.errors[key]);
      +  }, this).join(', ');
      +};

    • errors/validator.js

      ValidatorError(path, msg)

      Schema validator error

      show code
      function ValidatorError (path, type) {
      +  var msg = type
      +    ? '"' + type + '" '
      +    : '';
      +  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidatorError';
      +  this.path = path;
      +  this.type = type;
      +};

      Parameters:

      Inherits:


    • model.js

      Model(doc)

      Model constructor

      show code
      function Model (doc, fields, skipId) {
      +  Document.call(this, doc, fields, skipId);
      +};

      Parameters:

      • doc <Object> values to with which to create the document

      Inherits:

      Events:

      • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

      • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


      Model#_getPopulationKeys(query)

      Returns what paths can be populated

      show code
      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
      +  if (!(query && query.options.populate)) return;
      +
      +  var names = Object.keys(query.options.populate)
      +    , n = names.length
      +    , name
      +    , paths = {}
      +    , hasKeys
      +    , schema
      +
      +  while (n--) {
      +    name = names[n];
      +    schema = this.schema.path(name);
      +    hasKeys = true;
      +
      +    if (!schema) {
      +      // if the path is not recognized, it's potentially embedded docs
      +      // walk path atoms from right to left to find a matching path
      +      var pieces = name.split('.')
      +        , i = pieces.length;
      +
      +      while (i--) {
      +        var path = pieces.slice(0, i).join('.')
      +          , pathSchema = this.schema.path(path);
      +
      +        // loop until we find an array schema
      +        if (pathSchema && pathSchema.caster) {
      +          if (!paths[path]) {
      +            paths[path] = { sub: {} };
      +          }
      +
      +          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
      +          hasKeys || (hasKeys = true);
      +          break;
      +        }
      +      }
      +    } else {
      +      paths[name] = query.options.populate[name];
      +      hasKeys || (hasKeys = true);
      +    }
      +  }
      +
      +  return hasKeys && paths;
      +};

      Parameters:

      Returns:


      Model#_populate(schema, oid, query, fn)

      Populates an object

      show code
      Model.prototype._populate = function populate (schema, oid, query, fn) {
      +  if (!Array.isArray(oid)) {
      +    var conditions = query.conditions || {};
      +    conditions._id = oid;
      +
      +    return this
      +    .db.model(query.model || schema.options.ref)
      +    .findOne(conditions, query.fields, query.options, fn);
      +  }
      +
      +  if (!oid.length) {
      +    return fn(null, oid);
      +  }
      +
      +  var model = this.db.model(query.model || schema.caster.options.ref)
      +    , conditions = query && query.conditions || {};
      +
      +  conditions._id || (conditions._id = { $in: oid });
      +
      +  model.find(conditions, query.fields, query.options, function (err, docs) {
      +    if (err) return fn(err);
      +
      +    // user specified sort order?
      +    if (query.options && query.options.sort) {
      +      return fn(null, docs);
      +    }
      +
      +    // put back in original id order (using a hash reduces complexity from n*n to 2n)
      +    var docHash = {};
      +    docs.forEach(function (doc) {
      +      docHash[doc._id] = doc;
      +    });
      +
      +    var arr = [];
      +    oid.forEach(function (id) {
      +      if (id in docHash) arr.push(docHash[id]);
      +    });
      +
      +    fn(null, arr);
      +  });
      +};

      Parameters:

      • schema <SchemaType> type for the oid
      • oid <Object> object id or array of object ids
      • query <Object> object specifying query conditions, fields, and options
      • fn <Function>

      Model#init(doc, query, fn)

      Performs auto-population of relations.

      show code
      Model.prototype.init = function init (doc, query, fn) {
      +  if ('function' == typeof query) {
      +    fn = query;
      +    query = null;
      +  }
      +
      +  var populate = this._getPopulationKeys(query);
      +
      +  if (!populate) {
      +    return Document.prototype.init.call(this, doc, fn);
      +  }
      +
      +  // population from other models is necessary
      +  var self = this;
      +
      +  init(doc, '', function (err) {
      +    if (err) return fn(err);
      +    Document.prototype.init.call(self, doc, fn);
      +  });
      +
      +  return this;
      +
      +  function init (obj, prefix, fn) {
      +    prefix = prefix || '';
      +
      +    var keys = Object.keys(obj)
      +      , len = keys.length;
      +
      +    return next();
      +
      +    function next () {
      +      if (--len < 0) return fn();
      +
      +      var i = keys[len]
      +        , path = prefix + i
      +        , schema = self.schema.path(path)
      +        , total = 0
      +        , inline = false
      +        , poppath
      +
      +      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
      +        // assume nested object
      +        return init(obj[i], path + '.', next);
      +      }
      +
      +      if (!(obj[i] && schema && populate[path])) return next();
      +
      +      // this query object is re-used and passed around. we clone
      +      // it to prevent query condition contamination between
      +      // one populate call to the next.
      +      poppath = utils.clone(populate[path]);
      +
      +      if (poppath.sub) {
      +        obj[i].forEach(function (subobj) {
      +          inline = true;
      +
      +          var pkeys = Object.keys(poppath.sub)
      +            , pi = pkeys.length
      +            , key
      +
      +          while (pi--) {
      +            key = pkeys[pi];
      +
      +            if (subobj[key]) (function (key) {
      +              total++;
      +              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
      +              function done (err, doc) {
      +                if (err) return error(err);
      +                subobj[key] = doc;
      +                if (--total < 1 && !inline) {
      +                  next();
      +                }
      +              }
      +            })(key);
      +          }
      +        });
      +
      +        inline = false;
      +
      +        if (0 === total) return next();
      +
      +      } else {
      +        self._populate(schema, obj[i], poppath, function (err, doc) {
      +          if (err) return error(err);
      +          obj[i] = doc;
      +          next();
      +        });
      +      }
      +    };
      +  };
      +
      +  function error (err) {
      +    if (error.err) return;
      +    fn(error.err = err);
      +  }
      +};

      Parameters:

      • doc <Object> document returned by mongo
      • query <Query> query that originated the initialization
      • fn <Function>

      Model#save([fn])

      Saves this document.

      show code
      Model.prototype.save = function save (fn) {
      +  var promise = new Promise(fn)
      +    , complete = handleSave(promise, this)
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  if (this.isNew) {
      +    // send entire doc
      +    var obj = this.toObject({ depopulate: 1 });
      +    this._version(true, obj);
      +    this.collection.insert(obj, options, complete);
      +    this._reset();
      +    this.isNew = false;
      +    this.emit('isNew', false);
      +    // Make it possible to retry the insert
      +    this._inserting = true;
      +
      +  } else {
      +    // Make sure we don't treat it as a new object on error,
      +    // since it already exists
      +    this._inserting = false;
      +
      +    var delta = this._delta();
      +    if (delta) {
      +      var where = this._where(delta[0]);
      +      this.collection.update(where, delta[1], options, complete);
      +    } else {
      +      complete(null);
      +    }
      +
      +    this._reset();
      +    this.emit('isNew', false);
      +  }
      +};

      Parameters:

      Example:

      + +
      product.sold = Date.now();
      +product.save(function (err, product) {
      +  if (err) ..
      +})
      + +

      The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      + +
      var db = mongoose.createConnection(..);
      +var schema = new Schema(..);
      +var Product = db.model('Product', schema);
      +
      +db.on('error', handleError);
      + +

      However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

      + +
      Product.on('error', handleError);

      Model#_delta()

      Produces a special query document of the modified properties used in updates.

      show code
      Model.prototype._delta = function _delta () {
      +  var dirty = this._dirty();
      +  if (!dirty.length) return;
      +
      +  var self = this
      +    , where = {}
      +    , delta = {}
      +    , len = dirty.length
      +    , d = 0
      +    , val
      +    , obj
      +
      +  for (; d < len; ++d) {
      +    var data = dirty[d]
      +    var value = data.value
      +    var schema = data.schema
      +
      +    if (undefined === value) {
      +      operand(self, where, delta, data, 1, '$unset');
      +
      +    } else if (null === value) {
      +      operand(self, where, delta, data, null);
      +
      +    } else if (value._path && value._atomics) {
      +      handleAtomics(self, where, delta, data, value);
      +
      +    } else if (value._path && Buffer.isBuffer(value)) {
      +      // MongooseBuffer
      +      value = value.toObject();
      +      operand(self, where, delta, data, value);
      +
      +    } else {
      +      value = utils.clone(value);
      +      operand(self, where, delta, data, value);
      +    }
      +  }
      +
      +  if (this.__version) {
      +    this._version(where, delta);
      +  }
      +
      +  return [where, delta];
      +}

      Model#_version()

      Appends versioning to the where and update clauses.

      show code
      Model.prototype._version = function _version (where, delta) {
      +  var key = this.schema.options.versionKey;
      +
      +  if (true === where) {
      +    // this is an insert
      +    if (key) this.setValue(key, delta[key] = 0);
      +    return;
      +  }
      +
      +  // updates
      +
      +  // only apply versioning if our versionKey was selected. else
      +  // there is no way to select the correct version. we could fail
      +  // fast here and force them to include the versionKey but
      +  // thats a bit intrusive. can we do this automatically?
      +  // TODO fail fast option?
      +  if (!this.isSelected(key)) {
      +    return;
      +  }
      +
      +  // $push $addToSet don't need the where clause set
      +  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
      +    where[key] = this.getValue(key);
      +  }
      +
      +  if (VERSION_INC === (VERSION_INC & this.__version)) {
      +    delta.$inc || (delta.$inc = {});
      +    delta.$inc[key] = 1;
      +  }
      +}

      Model#increment()

      Signal that we desire an increment of this documents version.

      show code
      Model.prototype.increment = function increment () {
      +  this.__version = VERSION_ALL;
      +  return this;
      +}

      Model#_where()

      Returns a query object which applies shardkeys if they exist.

      show code
      Model.prototype._where = function _where (where) {
      +  where || (where = {});
      +
      +  var paths
      +    , len
      +
      +  if (this._shardval) {
      +    paths = Object.keys(this._shardval)
      +    len = paths.length
      +
      +    for (var i = 0; i < len; ++i) {
      +      where[paths[i]] = this._shardval[paths[i]];
      +    }
      +  }
      +
      +  where._id = this._doc._id;
      +  return where;
      +}

      Model#remove([fn])

      Removes this document from the db.

      show code
      Model.prototype.remove = function remove (fn) {
      +  if (this._removing) return this;
      +
      +  var promise = this._removing = new Promise(fn)
      +    , where = this._where()
      +    , self = this
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  this.collection.remove(where, options, tick(function (err) {
      +    if (err) {
      +      promise.error(err);
      +      promise = self = self._removing = where = options = null;
      +      return;
      +    }
      +    self.emit('remove', self);
      +    promise.complete();
      +    promise = self = where = options = null;
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Example:

      + +
      product.remove(function (err, product) {
      +  if (err) return handleError(err);
      +  Product.findById(product._id, function (err, product) {
      +    console.log(product) // null
      +  })
      +})

      Model#_registerHooks()

      Register hooks override

      show code
      Model.prototype._registerHooks = function registerHooks () {
      +  Document.prototype._registerHooks.call(this);
      +};

      Model#model(name)

      Returns another Model instance.

      show code
      Model.prototype.model = function model (name) {
      +  return this.db.model(name);
      +};

      Parameters:

      Example:

      + +
      var doc = new Tank;
      +doc.model('User').findById(id, callback);

      Model#$where(argument)

      Creates a Query and specifies a $where condition.

      Parameters:

      • argument <String, Function> is a javascript string or anonymous function

      Returns:

      Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      + +
      Blog.$where('this.comments.length &gt; 5');

      Model.init()

      Called when the model compiles.

      show code
      Model.init = function init () {
      +  if (this.schema.options.autoIndex)
      +    this.ensureIndexes();
      +
      +  this.schema.emit('init', this);
      +};

      Model.ensureIndexes([cb])

      Sends ensureIndex commands to mongo for each index declared in the schema.

      show code
      Model.ensureIndexes = function ensureIndexes (cb) {
      +  var indexes = this.schema.indexes();
      +  if (!indexes.length) {
      +    return cb && cb();
      +  }
      +
      +  var self = this
      +    , safe = self.schema.options.safe
      +    , count = indexes.length
      +    , error
      +
      +  indexes.forEach(function (index) {
      +    var options = index[1];
      +    options.safe = safe;
      +    self.collection.ensureIndex(index[0], options, tick(function (err) {
      +      if (err) error = err;
      +      if (--count) return;
      +
      +      self.emit('index', error);
      +      cb && cb(error);
      +    }));
      +  });
      +}

      Parameters:

      After completion, an index event is emitted on this Model passing an error if one occurred.


      Model.remove(conditions, [callback])

      Removes documents from the collection.

      show code
      Model.remove = function remove (conditions, callback) {
      +  if ('function' === typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +  }
      +
      +  var query = new Query(conditions).bind(this, 'remove');
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.remove(callback);
      +};

      Parameters:

      Returns:

      Note:

      + +

      To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.remove({ _id: id }).exec();

      Model.find(conditions, [fields], [options], [callback])

      Finds documents

      show code
      Model.find = function find (conditions, fields, options, callback) {
      +  if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options);
      +  query.bind(this, 'find');
      +  query.select(fields);
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.find(callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      // retrieve only certain keys
      +MyModel.find({ name: /john/i }, 'name friends', function () { })
      +
      +// pass options
      +MyModel.find({ name: /john/i }, null, { skip: 10 } )

      Model._applyNamedScope(query)

      Merges the current named scope query into query.

      show code
      Model._applyNamedScope = function _applyNamedScope (query) {
      +  var cQuery = this._cumulativeQuery;
      +
      +  if (cQuery) {
      +    merge(query._conditions, cQuery._conditions);
      +    if (query._fields && cQuery._fields)
      +      merge(query._fields, cQuery._fields);
      +    if (query.options && cQuery.options)
      +      merge(query.options, cQuery.options);
      +    delete this._cumulativeQuery;
      +  }
      +
      +  return query;
      +}

      Parameters:

      Returns:


      Model.findById(id, [fields], [options], [callback])

      Finds a single document by id.

      show code
      Model.findById = function findById (id, fields, options, callback) {
      +  return this.findOne({ _id: id }, fields, options, callback);
      +};

      Parameters:

      Returns:

      The id is cast to an ObjectId before sending the command.

      + +

      Example:

      + +
      Adventure.findById(id, callback);

      Model.findOne(conditions, [fields], [options], [callback])

      Finds one document.

      show code
      Model.findOne = function findOne (conditions, fields, options, callback) {
      +  if ('function' == typeof options) {
      +    // TODO Handle all 3 of the following scenarios
      +    // Hint: Only some of these scenarios are possible if cQuery is present
      +    // Scenario: findOne(conditions, fields, callback);
      +    // Scenario: findOne(fields, options, callback);
      +    // Scenario: findOne(conditions, options, callback);
      +    callback = options;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    // TODO Handle all 2 of the following scenarios
      +    // Scenario: findOne(conditions, callback)
      +    // Scenario: findOne(fields, callback)
      +    // Scenario: findOne(options, callback);
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOne(callback);
      +};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      + +

      Example:

      + +
      Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

      Model.count(conditions, [callback])

      Counts number of matching documents in a database collection.

      show code
      Model.count = function count (conditions, callback) {
      +  if ('function' === typeof conditions)
      +    callback = conditions, conditions = {};
      +
      +  var query = new Query(conditions).bind(this, 'count');
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.count(callback);
      +};

      Parameters:

      Returns:

      Example:

      + +
      Adventure.count({ type: 'jungle' }, function (err, count) {
      +  if (err) ..
      +  console.log('there are %d jungle adventures', count);
      +});

      Model.distinct(field, [conditions], [callback])

      Executes a DISTINCT command

      show code
      Model.distinct = function distinct (field, conditions, callback) {
      +  var query = new Query(conditions).bind(this, 'distinct');
      +  if ('undefined' == typeof callback) {
      +    query._distinctArg = field;
      +    return query;
      +  }
      +
      +  this._applyNamedScope(query);
      +  return query.distinct(field, callback);
      +};

      Parameters:

      Returns:


      Model.where(path, [val])

      Creates a Query, applies the passed conditions, and returns the Query.

      show code
      Model.where = function where (path, val) {
      +  var q = new Query().bind(this, 'find');
      +  return q.where.apply(q, arguments);
      +};

      Parameters:

      Returns:

      For example, instead of writing:

      + +
      User.find({age: {$gte: 21, $lte: 65}}, callback);
      + +

      we can instead write:

      + +
      User.where('age').gte(21).lte(65).exec(callback);
      + +

      Since the Query class also supports where you can continue chaining

      + +
      User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +... etc

      Model.findOneAndUpdate([conditions], [update], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Model.findOneAndUpdate = function (conditions, update, options, callback) {
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +  else if (1 === arguments.length) {
      +    if ('function' == typeof conditions) {
      +      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    update = conditions;
      +    conditions = undefined;
      +  }
      +
      +  var fields;
      +  if (options && options.fields) {
      +    fields = options.fields;
      +    options.fields = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndUpdate', update);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndUpdate(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndUpdate(conditions, update, options, callback) // executes
      +A.findOneAndUpdate(conditions, update, options)  // returns Query
      +A.findOneAndUpdate(conditions, update, callback) // executes
      +A.findOneAndUpdate(conditions, update)           // returns Query
      +A.findOneAndUpdate()                             // returns Query
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findByIdAndUpdate(id, [update], [options], [callback])

      Issues a mongodb findAndModify update command by a documents id.

      show code
      Model.findByIdAndUpdate = function (id, update, options, callback) {
      +  var args;
      +
      +  if (1 === arguments.length) {
      +    if ('function' == typeof id) {
      +      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
      +
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    return this.findOneAndUpdate({_id: id }, undefined);
      +  }
      +
      +  args = utils.args(arguments, 1);
      +  args.unshift({ _id: id });
      +  return this.findOneAndUpdate.apply(this, args);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndUpdate(id, update, options, callback) // executes
      +A.findByIdAndUpdate(id, update, options)  // returns Query
      +A.findByIdAndUpdate(id, update, callback) // executes
      +A.findByIdAndUpdate(id, update)           // returns Query
      +A.findByIdAndUpdate()                     // returns Query
      + +

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findById(id, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findOneAndRemove(conditions, [options], [callback])

      Issue a mongodb findAndModify remove command.

      show code
      Model.findOneAndRemove = function (conditions, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof conditions) {
      +    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  }
      +
      +  var fields;
      +  if (options) {
      +    fields = options.select;
      +    options.select = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndRemove');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndRemove(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndRemove(conditions, options, callback) // executes
      +A.findOneAndRemove(conditions, options)  // return Query
      +A.findOneAndRemove(conditions, callback) // executes
      +A.findOneAndRemove(conditions) // returns Query
      +A.findOneAndRemove()           // returns Query

      Model.findByIdAndRemove(id, [options], [callback])

      Issue a mongodb findAndModify remove command by a documents id.

      show code
      Model.findByIdAndRemove = function (id, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof id) {
      +    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  return this.findOneAndRemove({ _id: id }, options, callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed, else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndRemove(id, options, callback) // executes
      +A.findByIdAndRemove(id, options)  // return Query
      +A.findByIdAndRemove(id, callback) // executes
      +A.findByIdAndRemove(id) // returns Query
      +A.findByIdAndRemove()           // returns Query

      Model.create(doc, fn)

      Shortcut for creating a new Document that is automatically saved to the db if valid.

      show code
      Model.create = function create (doc, fn) {
      +  if (1 === arguments.length) {
      +    return 'function' === typeof doc && doc(null);
      +  }
      +
      +  var self = this
      +    , docs = [null]
      +    , promise
      +    , count
      +    , args
      +
      +  if (Array.isArray(doc)) {
      +    args = doc;
      +  } else {
      +    args = utils.args(arguments, 0, arguments.length - 1);
      +    fn = arguments[arguments.length - 1];
      +  }
      +
      +  if (0 === args.length) return fn(null);
      +
      +  promise = new Promise(fn);
      +  count = args.length;
      +
      +  args.forEach(function (arg, i) {
      +    var doc = new self(arg);
      +    docs[i+1] = doc;
      +    doc.save(function (err) {
      +      if (err) return promise.error(err);
      +      --count || fn.apply(null, docs);
      +    });
      +  });
      +
      +  // TODO
      +  // utilize collection.insertAll for batch processing?
      +};

      Parameters:

      Example:

      + +
      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});
      +
      +var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      +Candy.create(array, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});

      Model.update(conditions, update, [options], [callback])

      Updates documents in the database without returning them.

      show code
      Model.update = function update (conditions, doc, options, callback) {
      +  if (arguments.length < 4) {
      +    if ('function' === typeof options) {
      +      // Scenario: update(conditions, doc, callback)
      +      callback = options;
      +      options = null;
      +    } else if ('function' === typeof doc) {
      +      // Scenario: update(doc, callback);
      +      callback = doc;
      +      doc = conditions;
      +      conditions = {};
      +      options = null;
      +    }
      +  }
      +
      +  var query = new Query(conditions, options).bind(this, 'update', doc);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.update(doc, callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
      +MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
      +  if (err) return handleError(err);
      +  console.log('The number of updated documents was %d', numberAffected);
      +  console.log('The raw response from Mongo was ', raw);
      +});
      + +

      Valid options:

      + +
        +
      • safe (boolean) safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +
      • multi (boolean) whether multiple documents should be updated (false)
      • +
      + +

      All update values are cast to their appropriate SchemaTypes before being sent.

      + +

      The callback function receives (err, numberAffected, rawResponse).

      + +
        +
      • err is the error if any occurred
      • +
      • numberAffected is the count of updated documents Mongo reported
      • +
      • rawResponse is the full response from Mongo
      • +
      + +

      Note:

      + +

      All top level keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.update(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

      + +

      Note:

      + +

      To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
      + +

      Note:

      + +

      Although values are casted to their appropriate types when using update, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.mapReduce(o, callback)

      Executes a mapReduce command.

      show code
      Model.mapReduce = function mapReduce (o, callback) {
      +  if ('function' != typeof callback) throw new Error('missing callback');
      +
      +  var self = this;
      +
      +  if (!Model.mapReduce.schema) {
      +    var opts = { noId: true, noVirtualId: true, strict: false }
      +    Model.mapReduce.schema = new Schema({}, opts);
      +  }
      +
      +  if (!o.out) o.out = { inline: 1 };
      +
      +  o.map = String(o.map);
      +  o.reduce = String(o.reduce);
      +
      +  if (o.query) {
      +    var q = new Query(o.query);
      +    q.cast(this);
      +    o.query = q._conditions;
      +    q = undefined;
      +  }
      +
      +  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
      +    if (err) return callback(err);
      +
      +    if (ret.findOne && ret.mapReduce) {
      +      // returned a collection, convert to Model
      +      var model = Model.compile(
      +          '_mapreduce_' + ret.collectionName
      +        , Model.mapReduce.schema
      +        , ret.collectionName
      +        , self.db
      +        , self.base);
      +
      +      model._mapreduce = true;
      +
      +      return callback(err, model, stats);
      +    }
      +
      +    callback(err, ret, stats);
      +  });
      +}

      Parameters:

      • o <Object> an object specifying map-reduce options
      • callback <Function>

      o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +User.mapReduce(o, function (err, results) {
      +  console.log(results)
      +})
      + +

      Other options:

      + +
        +
      • query {Object} query filter object.
      • +
      • limit {Number} max number of documents
      • +
      • keeptemp {Boolean, default:false} keep temporary data
      • +
      • finalize {Function} finalize function
      • +
      • scope {Object} scope variables exposed to map/reduce/finalize during execution
      • +
      • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
      • +
      • verbose {Boolean, default:false} provide statistics on job execution time.
      • +
      • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
      • +
      + +

      * out options:

      + +
        +
      • {inline:1} the results are returned in an array
      • +
      • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
      • +
      • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
      • +
      • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
      • +
      + +

      If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +o.out = { replace: 'createdCollectionNameForResults' }
      +o.verbose = true;
      +User.mapReduce(o, function (err, model, stats) {
      +  console.log('map reduce took %d ms', stats.processtime)
      +  model.find().where('value').gt(10).exec(function (err, docs) {
      +    console.log(docs);
      +  });
      +})

      Model.aggregate(array, [options], callback)

      Executes an aggregate command on this models collection.

      show code
      Model.aggregate = function aggregate () {
      +  return this.collection.aggregate.apply(this.collection, arguments);
      +}

      Parameters:

      Example:

      + +
      // find the max age of all users
      +Users.aggregate(
      +    { $group: { _id: null, maxAge: { $max: '$age' }}}
      +  , { $project: { _id: 0, maxAge: 1 }}
      +  , function (err, res) {
      +  if (err) return handleError(err);
      +  console.log(res); // [ { maxAge: 98 } ]
      +});
      + +

      NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

      + +

      NOTE: this requires running MongoDB >= 2.1


      Model#base

      Base Mongoose instance the model uses.


      Model#collection

      Collection the model uses.


      Model#db

      Database instance the model uses.


      Model#schema

      Schema the model uses.


      Model#modelName

      The name of the model


      Model#collection

      Collection the model uses.


      Model#db

      Connection the model uses.


    • namedscope.js

      NamedScope#decorate(target, getters)

      Decorate

      show code
      NamedScope.prototype.decorate = function (target, getters) {
      +  var name = this.name
      +    , block = this.block
      +    , query = this.query;
      +  if (block) {
      +    if (block.length === 0) {
      +      Object.defineProperty(target, name, {
      +        get: getters.block0(block)
      +      });
      +    } else {
      +      target[name] = getters.blockN(block);
      +    }
      +  } else {
      +    Object.defineProperty(target, name, {
      +      get: getters.basic(query)
      +    });
      +  }
      +};
      +
      +NamedScope.prototype.compile = function (model) {
      +  var allScopes = this.scopesByName
      +    , scope;
      +  for (var k in allScopes) {
      +    scope = allScopes[k];
      +    scope.decorate(model, {
      +      block0: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.call(cquery);
      +          return this;
      +        };
      +      },
      +      blockN: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.apply(cquery, arguments);
      +          return this;
      +        };
      +      },
      +      basic: function (query) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          cquery.find(query);
      +          return this;
      +        };
      +      }
      +    });
      +  }
      +};
      +
      +module.exports = NamedScope;

      Parameters:


    • promise.js

      Promise(back)

      Promise constructor.

      show code
      function Promise (back) {
      +  this.emitted = {};
      +  if ('function' == typeof back)
      +    this.addBack(back);
      +};

      Parameters:

      • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

      Events:

      • err: Emits when the promise resolves to an error.

      • complete: Emits when the promise resolves sucessfully.


      Promise#on(event, callback)

      Adds listener to the event.

      show code
      Promise.prototype.on = function (event, callback) {
      +  if (this.emitted[event])
      +    callback.apply(this, this.emitted[event]);
      +  else
      +    EventEmitter.prototype.on.call(this, event, callback);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


      Promise#emit()

      Keeps track of emitted events to run them on on.

      show code
      Promise.prototype.emit = function (event) {
      +  // ensures a promise can't be complete() or error() twice
      +  if (event == 'err' || event == 'complete'){
      +    if (this.emitted.err || this.emitted.complete) {
      +      return this;
      +    }
      +    this.emitted[event] = util.args(arguments, 1);
      +  }
      +
      +  return EventEmitter.prototype.emit.apply(this, arguments);
      +};

      Promise#complete()

      Shortcut for emitting the complete event.

      show code
      Promise.prototype.complete = function () {
      +  var args = util.args(arguments);
      +  return this.emit.apply(this, ['complete'].concat(args));
      +};

      Promise#error()

      Shortcut for emitting the err event.

      show code
      Promise.prototype.error = function (err) {
      +  if (!(err instanceof Error)) err = new Error(err);
      +  return this.emit('err', err);
      +};

      Returns:


      Promise#addCallback()

      Shortcut for .on('complete', fn).

      show code
      Promise.prototype.addCallback = function (fn) {
      +  return this.on('complete', fn);
      +};

      Returns:


      Promise#addErrback()

      Shortcut for .on('err', fn).

      show code
      Promise.prototype.addErrback = function (fn) {
      +  return this.on('err', fn);
      +};

      Returns:


      Promise#addBack(fn)

      Adds a single function that's both a callback and errback.

      show code
      Promise.prototype.addBack = function (fn) {
      +  this.on('err', function(err){
      +    fn.call(this, err);
      +  });
      +
      +  this.on('complete', function(){
      +    var args = util.args(arguments);
      +    fn.apply(this, [null].concat(args));
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Promise#resolve(err, val)

      Sugar for handling cases where you may be resolving to either an error condition or a success condition.

      show code
      Promise.prototype.resolve = function (err, val) {
      +  if (err) return this.error(err);
      +  return this.complete(val);
      +};

      Parameters:

      • err <Error> optional error or null
      • val <Object> value to complete the promise with

    • query.js

      Query(criteria, options)

      Query constructor used for building queries.

      show code
      function Query (criteria, options) {
      +  this.setOptions(options, true);
      +  this._conditions = {};
      +  this._updateArg = {};
      +  this._fields = undefined;
      +  if (criteria) this.find(criteria);
      +}

      Parameters:

      Example:

      + +
      var query = Model.find();
      +query.where('age').gte(21).exec(callback);

      Query#setOptions(options)

      Sets query options.

      show code
      Query.prototype.setOptions = function (options, overwrite) {
      +  // overwrite is internal use only
      +  if (overwrite) {
      +    options = this.options = options || {};
      +    this.safe = options.safe
      +
      +    // normalize population options
      +    var pop = this.options.populate;
      +    this.options.populate = {};
      +
      +    if (pop && Array.isArray(pop)) {
      +      for (var i = 0, l = pop.length; i < l; i++) {
      +        this.options.populate[pop[i]] = {};
      +      }
      +    }
      +
      +    return this;
      +  }
      +
      +  if (!(options && 'Object' == options.constructor.name))
      +    return this;
      +
      +  if ('safe' in options)
      +    this.safe = options.safe;
      +
      +  // set arbitrary options
      +  var methods = Object.keys(options)
      +    , i = methods.length
      +    , method
      +
      +  while (i--) {
      +    method = methods[i];
      +
      +    // use methods if exist (safer option manipulation)
      +    if ('function' == typeof this[method]) {
      +      var args = Array.isArray(options[method])
      +        ? options[method]
      +        : [options[method]];
      +      this[method].apply(this, args)
      +    } else {
      +      this.options[method] = options[method];
      +    }
      +  }
      +  return this;
      +}

      Parameters:

      Options:

      + + + +

      * denotes a query helper method is also available


      Query#bind(model, op, updateArg)

      Binds this query to a model.

      show code
      Query.prototype.bind = function bind (model, op, updateArg) {
      +  this.model = model;
      +  this.op = op;
      +
      +  if (model._mapreduce) this.options.lean = true;
      +
      +  if (op == 'update' || op == 'findOneAndUpdate') {
      +    merge(this._updateArg, updateArg || {});
      +  }
      +
      +  return this;
      +};

      Parameters:

      • model <Model> the model to which the query is bound
      • op <String> the operation to execute
      • updateArg <Object> used in update methods

      Returns:


      Query#exec([operation], [callback])

      Executes the query

      show code
      Query.prototype.exec = function exec (op, callback) {
      +  var promise = new Promise();
      +
      +  switch (typeof op) {
      +    case 'function':
      +      callback = op;
      +      op = null;
      +      break;
      +    case 'string':
      +      this.op = op;
      +      break;
      +  }
      +
      +  if (callback) promise.addBack(callback);
      +
      +  if (!this.op) {
      +    promise.complete();
      +    return promise;
      +  }
      +
      +  if ('update' == this.op) {
      +    this[this.op](this._updateArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  if ('distinct' == this.op) {
      +    this.distinct(this._distinctArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  this[this.op](promise.resolve.bind(promise));
      +  return promise;
      +};

      Parameters:

      Returns:

      Examples

      + +
      query.exec();
      +query.exec(callback);
      +query.exec('update');
      +query.exec('find', callback);

      Query#find([criteria], [callback])

      Finds documents.

      show code
      Query.prototype.find = function (criteria, callback) {
      +  this.op = 'find';
      +  if ('function' === typeof criteria) {
      +    callback = criteria;
      +    criteria = {};
      +  } else if (criteria instanceof Query) {
      +    // TODO Merge options, too
      +    merge(this._conditions, criteria._conditions);
      +  } else if (criteria instanceof Document) {
      +    merge(this._conditions, criteria.toObject());
      +  } else if (criteria && 'Object' === criteria.constructor.name) {
      +    merge(this._conditions, criteria);
      +  }
      +  if (!callback) return this;
      +  return this.execFind(callback);
      +};

      Parameters:

      Returns:

      When no callback is passed, the query is not executed.

      + +

      Example

      + +
      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

      Query#cast(model, [obj])

      Casts this query to the schema of model

      show code
      Query.prototype.cast = function (model, obj) {
      +  obj || (obj= this._conditions);
      +
      +  var schema = model.schema
      +    , paths = Object.keys(obj)
      +    , i = paths.length
      +    , any$conditionals
      +    , schematype
      +    , nested
      +    , path
      +    , type
      +    , val;
      +
      +  while (i--) {
      +    path = paths[i];
      +    val = obj[path];
      +
      +    if ('$or' === path || '$nor' === path) {
      +      var k = val.length
      +        , orComponentQuery;
      +
      +      while (k--) {
      +        orComponentQuery = new Query(val[k]);
      +        orComponentQuery.cast(model);
      +        val[k] = orComponentQuery._conditions;
      +      }
      +
      +    } else if (path === '$where') {
      +      type = typeof val;
      +
      +      if ('string' !== type && 'function' !== type) {
      +        throw new Error("Must have a string or function for $where");
      +      }
      +
      +      if ('function' === type) {
      +        obj[path] = val.toString();
      +      }
      +
      +      continue;
      +
      +    } else {
      +
      +      if (!schema) {
      +        // no casting for Mixed types
      +        continue;
      +      }
      +
      +      schematype = schema.path(path);
      +
      +      if (!schematype) {
      +        // Handle potential embedded array queries
      +        var split = path.split('.')
      +          , j = split.length
      +          , pathFirstHalf
      +          , pathLastHalf
      +          , remainingConds
      +          , castingQuery;
      +
      +        // Find the part of the var path that is a path of the Schema
      +        while (j--) {
      +          pathFirstHalf = split.slice(0, j).join('.');
      +          schematype = schema.path(pathFirstHalf);
      +          if (schematype) break;
      +        }
      +
      +        // If a substring of the input path resolves to an actual real path...
      +        if (schematype) {
      +          // Apply the casting; similar code for $elemMatch in schema/array.js
      +          if (schematype.caster && schematype.caster.schema) {
      +            remainingConds = {};
      +            pathLastHalf = split.slice(j).join('.');
      +            remainingConds[pathLastHalf] = val;
      +            castingQuery = new Query(remainingConds);
      +            castingQuery.cast(schematype.caster);
      +            obj[path] = castingQuery._conditions[pathLastHalf];
      +          } else {
      +            obj[path] = val;
      +          }
      +        }
      +
      +      } else if (val === null || val === undefined) {
      +        continue;
      +      } else if ('Object' === val.constructor.name) {
      +
      +        any$conditionals = Object.keys(val).some(function (k) {
      +          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
      +        });
      +
      +        if (!any$conditionals) {
      +          obj[path] = schematype.castForQuery(val);
      +        } else {
      +
      +          var ks = Object.keys(val)
      +            , k = ks.length
      +            , $cond;
      +
      +          while (k--) {
      +            $cond = ks[k];
      +            nested = val[$cond];
      +
      +            if ('$exists' === $cond) {
      +              if ('boolean' !== typeof nested) {
      +                throw new Error("$exists parameter must be Boolean");
      +              }
      +              continue;
      +            }
      +
      +            if ('$type' === $cond) {
      +              if ('number' !== typeof nested) {
      +                throw new Error("$type parameter must be Number");
      +              }
      +              continue;
      +            }
      +
      +            if ('$not' === $cond) {
      +              this.cast(model, nested);
      +            } else {
      +              val[$cond] = schematype.castForQuery($cond, nested);
      +            }
      +          }
      +        }
      +      } else {
      +        obj[path] = schematype.castForQuery(val);
      +      }
      +    }
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Returns:

      Note

      + +

      If obj is present, it is cast instead of this query.


      Query#_optionsForExec(model)

      Returns default options.

      show code
      Query.prototype._optionsForExec = function (model) {
      +  var options = utils.clone(this.options, { retainKeyOrder: true });
      +  delete options.populate;
      +
      +  if (!('batchSize' in options))
      +    options.batchSize = 1000;
      +
      +  if (!('safe' in options))
      +    options.safe = model.schema.options.safe;
      +
      +  if (!('readPreference' in options) && model.schema.options.read)
      +    options.readPreference = model.schema.options.read;
      +
      +  return options;
      +};

      Parameters:


      Query#_applyPaths()

      Applies schematype selected options to this query.

      show code
      Query.prototype._applyPaths = function applyPaths () {
      +  // determine if query is selecting or excluding fields
      +
      +  var fields = this._fields
      +    , exclude
      +    , keys
      +    , ki
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('+' == keys[ki][0]) continue;
      +      exclude = 0 === fields[keys[ki]];
      +      break;
      +    }
      +  }
      +
      +  // if selecting, apply default schematype select:true fields
      +  // if excluding, apply schematype select:false fields
      +
      +  var selected = []
      +    , excluded = []
      +    , seen = [];
      +
      +  analyzeSchema(this.model.schema);
      +
      +  switch (exclude) {
      +    case true:
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +    case false:
      +      selected.length && this.select(selected.join(' '));
      +      break;
      +    case undefined:
      +      // user didn't specify fields, implies returning all fields.
      +      // only need to apply excluded fields
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +  }
      +
      +  return seen = excluded = selected = keys = fields = null;
      +
      +  function analyzeSchema (schema, prefix) {
      +    prefix || (prefix = '');
      +
      +    // avoid recursion
      +    if (~seen.indexOf(schema)) return;
      +    seen.push(schema);
      +
      +    schema.eachPath(function (path, type) {
      +      if (prefix) path = prefix + '.' + path;
      +
      +      // array of subdocs?
      +      if (type.schema) {
      +        analyzeSchema(type.schema, path);
      +      }
      +
      +      analyzePath(path, type);
      +    });
      +  }
      +
      +  function analyzePath (path, type) {
      +    if ('boolean' != typeof type.selected) return;
      +
      +    if (fields && ('+' + path) in fields) {
      +      // forced inclusion
      +      delete fields['+' + path];
      +
      +      // if there are other fields being included, add this one
      +      // if no other included fields, leave this out (implied inclusion)
      +      if (false === exclude && keys.length > 1) {
      +        fields[path] = 1;
      +      }
      +
      +      return
      +    };
      +
      +    ;(type.selected ? selected : excluded).push(path);
      +  }
      +}

      Query#$where(js)

      Specifies a $where condition

      Parameters:

      Returns:

      Use $where when you need to select documents using a JavaScript expression.

      + +

      Example

      + +
      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
      +
      +query.$where(function () {
      +  return this.comments.length &gt; 10 || this.name.length &gt; 5;
      +})

      Query#where([path], [val])

      Specifies a path for use with chaining.

      show code
      Query.prototype.where = function (path, val) {
      +  if (!arguments.length) return this;
      +
      +  if ('string' != typeof path) {
      +    throw new TypeError('path must be a string');
      +  }
      +
      +  this._currPath = path;
      +
      +  if (2 === arguments.length) {
      +    this._conditions[path] = val;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      // instead of writing:
      +User.find({age: {$gte: 21, $lte: 65}}, callback);
      +
      +// we can instead write:
      +User.where('age').gte(21).lte(65);
      +
      +// Moreover, you can also chain a bunch of these together:
      +
      +User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +.where('friends').slice(10)
      +.exec(callback)

      Query#equals(val)

      Specifies the complementary comparison value for paths specified with where()

      show code
      Query.prototype.equals = function equals (val) {
      +  var path = this._currPath;
      +  if (!path) throw new Error('equals() must be used after where()');
      +  this._conditions[path] = val;
      +  return this;
      +}

      Parameters:

      Returns:

      Example

      + +
      User.where('age').equals(49);
      +
      +// is the same as
      +
      +User.where('age', 49);

      Query#or(array)

      Specifies arguments for an $or condition.

      show code
      Query.prototype.or = function or (array) {
      +  var or = this._conditions.$or || (this._conditions.$or = []);
      +  if (!Array.isArray(array)) array = [array];
      +  or.push.apply(or, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.or([{ color: 'red' }, { status: 'emergency' }])

      Query#nor(array)

      Specifies arguments for a $nor condition.

      show code
      Query.prototype.nor = function nor (array) {
      +  var nor = this._conditions.$nor || (this._conditions.$nor = []);
      +  if (!Array.isArray(array)) array = [array];
      +  nor.push.apply(nor, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.nor([{ color: 'green' }, { status: 'ok' }])

      Query#gt(path, val)

      Specifies a $gt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.

      + +

      Example

      + +
      Thing.find().where('age').gt(21)
      +
      +// or
      +Thing.find().gt('age', 21)

      Query#gte(path, val)

      Specifies a $gte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lt(path, val)

      Specifies a $lt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lte(path, val)

      Specifies a $lte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#ne(path, val)

      Specifies a $ne query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#in(path, val)

      Specifies an $in query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#nin(path, val)

      Specifies an $nin query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#all(path, val)

      Specifies an $all query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#size(path, val)

      Specifies an $size query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#regex(path, val)

      Specifies a $regex query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#maxDistance(path, val)

      Specifies a $maxDistance query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#near(path, val)

      Specifies a $near condition

      show code
      Query.prototype.near = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$near = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#nearSphere(path, val)

      Specifies a $nearSphere condition.

      show code
      Query.prototype.nearSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$nearSphere = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#mod(path, val)

      Specifies a $mod condition

      show code
      Query.prototype.mod = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$mod = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#exists(path, val)

      Specifies an $exists condition

      show code
      Query.prototype.exists = function (path, val) {
      +  if (arguments.length === 0) {
      +    path = this._currPath
      +    val = true;
      +  } else if (arguments.length === 1) {
      +    if ('boolean' === typeof path) {
      +      val = path;
      +      path = this._currPath;
      +    } else {
      +      val = true;
      +    }
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$exists'] = val;
      +  return this;
      +};

      Parameters:

      Returns:


      Query#elemMatch(path, criteria)

      Specifies an $elemMatch condition

      show code
      Query.prototype.elemMatch = function (path, criteria) {
      +  var block;
      +  if ('Object' === path.constructor.name) {
      +    criteria = path;
      +    path = this._currPath;
      +  } else if ('function' === typeof path) {
      +    block = path;
      +    path = this._currPath;
      +  } else if ('Object' === criteria.constructor.name) {
      +  } else if ('function' === typeof criteria) {
      +    block = criteria;
      +  } else {
      +    throw new Error("Argument error");
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  if (block) {
      +    criteria = new Query();
      +    block(criteria);
      +    conds['$elemMatch'] = criteria._conditions;
      +  } else {
      +    conds['$elemMatch'] = criteria;
      +  }
      +  return this;
      +};
      +
      +// Spatial queries

      Parameters:

      Returns:

      Example

      + +
      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
      +
      +query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
      +
      +query.elemMatch('comment', function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})
      +
      +query.where('comment').elemMatch(function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})

      Query#box(path, val)

      Specifies a $box condition

      show code
      Query.prototype.box = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$box': [val.ll, val.ur]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var lowerLeft = [40.73083, -73.99756]
      +var upperRight= [40.741404,  -73.988135]
      +query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

      Query#center(path, val, [opts])

      Specifies a $center condition

      show code
      Query.prototype.center = function (path, val, opts) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$center': [val.center, val.radius]  };
      +
      +  // copy any options
      +  if (opts && 'Object' == opts.constructor.name) {
      +    utils.options(opts, conds.$within);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.center(area)

      Query#centerSphere(path, val)

      Specifies a $centerSphere condition

      show code
      Query.prototype.centerSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.centerSphere(area)

      Query#polygon(path, val)

      Specifies a $polygon condition

      show code
      Query.prototype.polygon = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$polygon': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      +query.where('loc').within.polygon(polyA)
      +
      +// or
      +var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      +query.where('loc').within.polygon(polyB)

      Query#select(arg)

      Specifies which document fields to include or exclude

      show code
      Query.prototype.select = function select (arg) {
      +  if (!arg) return this;
      +
      +  var fields = this._fields || (this._fields = {});
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      fields[field] = arg[field];
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var include = '-' == field[0] ? 0 : 1;
      +      if (include === 0) field = field.substring(1);
      +      fields[field] = include;
      +    });
      +  } else {
      +    throw new TypeError('Invalid select() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

      + +

      Example

      + +
      // include a and b, exclude c
      +query.select('a b -c');
      +
      +// or you may use object notation, useful when
      +// you have keys already prefixed with a "-"
      +query.select({a: 1, b: 1, c: 0});
      +
      +// force inclusion of field excluded at schema level
      +query.select('+path')
      + +

      NOTE:

      + +

      v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


      Query#slice(path, val)

      Specifies a $slice condition

      show code
      Query.prototype.slice = function (path, val) {
      +  if (arguments.length === 1) {
      +      val = path;
      +      path = this._currPath
      +  } else if (arguments.length === 2) {
      +    if ('number' === typeof path) {
      +      val = [path, val];
      +      path = this._currPath;
      +    }
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var myFields = this._fields || (this._fields = {});
      +  myFields[path] = { '$slice': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      query.slice('comments', 5)
      +query.slice('comments', -5)
      +query.slice('comments', [10, 5])
      +query.where('comments').slice(5)
      +query.where('comments').slice([-10, 5])

      Query#sort(arg)

      Sets the sort order

      show code
      Query.prototype.sort = function (arg) {
      +  if (!arg) return this;
      +
      +  var sort = this.options.sort || (this.options.sort = []);
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      push(sort, field, arg[field]);
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var ascend = '-' == field[0] ? -1 : 1;
      +      if (ascend === -1) field = field.substring(1);
      +      push(sort, field, ascend);
      +    });
      +  } else {
      +    throw new TypeError('Invalid sort() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

      + +

      If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

      + +

      Example

      + +
      // these are equivalent
      +query.sort({ field: 'asc', test: -1 });
      +query.sort('field -test');

      Query#limit(val)

      Specifies the limit option.

      Parameters:

      Example

      + +
      Kitten.find().limit(20)

      Query#skip(val)

      Specifies the skip option.

      Parameters:

      Example

      + +
      Kitten.find().skip(100).limit(20)

      Query#maxscan(val)

      Specifies the maxscan option.

      Parameters:

      Example

      + +
      Kitten.find().maxscan(100)

      Query#batchSize(val)

      Specifies the batchSize option.

      Parameters:

      Example

      + +
      Kitten.find().batchSize(100)

      Query#comment(val)

      Specifies the comment option.

      Parameters:

      Example

      + +
      Kitten.findOne(condition).comment('login query')

      Query#snapshot()

      Specifies this query as a snapshot query.

      show code
      Query.prototype.snapshot = function () {
      +  this.options.snapshot = true;
      +  return this;
      +};

      Returns:

      Example

      + +
      Kitten.find().snapshot()

      Query#hint(val)

      Sets query hints.

      show code
      Query.prototype.hint = function (val) {
      +  if (!val) return this;
      +
      +  var hint = this.options.hint || (this.options.hint = {});
      +
      +  if ('Object' === val.constructor.name) {
      +    // must keep object keys in order so don't use Object.keys()
      +    for (var k in val) {
      +      hint[k] = val[k];
      +    }
      +  } else {
      +    throw new TypeError('Invalid hint. ' + val);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Model.find().hint({ indexA: 1, indexB: -1})

      Query#slaveOk(v)

      Sets the slaveOk option.

      show code
      Query.prototype.slaveOk = function (v) {
      +  this.options.slaveOk = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Example:

      + +
      new Query().slaveOk() // true
      +new Query().slaveOk(true)
      +new Query().slaveOk(false)

      Query#read(pref, [tags])

      Sets the readPreference option for the query.

      show code
      Query.prototype.read = function (pref, tags) {
      +  this.options.readPreference = utils.readPref(pref, tags);
      +  return this;
      +}

      Parameters:

      • pref <String> one of the listed preference options or their aliases
      • [tags] <Array> optional tags for this query

      Returns:

      Example:

      + +
      new Query().read('primary')
      +new Query().read('p')  // same as primary
      +
      +new Query().read('primaryPreferred')
      +new Query().read('pp') // same as primaryPreferred
      +
      +new Query().read('secondary')
      +new Query().read('s')  // same as secondary
      +
      +new Query().read('secondaryPreferred')
      +new Query().read('sp') // same as secondaryPreferred
      +
      +new Query().read('nearest')
      +new Query().read('n')  // same as nearest
      +
      +// with tags
      +new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
      + +

      Preferences:

      + +
      primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
      +secondary            Read from secondary if available, otherwise error.
      +primaryPreferred     Read from primary if available, otherwise a secondary.
      +secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
      +nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
      + +

      Aliases

      + +
      p   primary
      +pp  primaryPreferred
      +s   secondary
      +sp  secondaryPreferred
      +n   nearest
      + +

      Read more about how to use read preferrences here and here.


      Query#lean(v)

      Sets the lean option.

      show code
      Query.prototype.lean = function (v) {
      +  this.options.lean = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

      + +

      This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

      + +

      Example:

      + +
      new Query().lean() // true
      +new Query().lean(true)
      +new Query().lean(false)
      +
      +Model.find().lean().exec();
      +
      +var leanStream = Model.find().lean().stream();

      Query#tailable(v)

      Sets tailable option.

      show code
      Query.prototype.tailable = function (v) {
      +  this.options.tailable = arguments.length ? !!v : true;
      +  return this;
      +};

      Parameters:

      Example

      + +
      Kitten.find().tailable() &lt;== true
      +Kitten.find().tailable(true)
      +Kitten.find().tailable(false)

      Query#execFind(callback)

      Executes the query as a find() operation.

      show code
      Query.prototype.execFind = function (callback) {
      +  var model = this.model
      +    , promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.find(castQuery, options, function (err, cursor) {
      +    if (err) return promise.error(err);
      +    cursor.toArray(tick(cb));
      +  });
      +
      +  function cb (err, docs) {
      +    if (err) return promise.error(err);
      +
      +    if (true === options.lean)
      +      return promise.complete(docs);
      +
      +    var arr = []
      +      , count = docs.length;
      +
      +    if (!count) return promise.complete([]);
      +
      +    for (var i = 0, l = docs.length; i < l; i++) {
      +      arr[i] = new model(undefined, fields, true);
      +      arr[i].init(docs[i], self, function (err) {
      +        if (err) return promise.error(err);
      +        --count || promise.complete(arr);
      +      });
      +    }
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#findOne(callback)

      Executes the query as a findOne() operation.

      show code
      Query.prototype.findOne = function (callback) {
      +  this.op = 'findOne';
      +
      +  if (!callback) return this;
      +
      +  var model = this.model;
      +  var promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.findOne(castQuery, options, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === options.lean) return promise.complete(doc);
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'white').findOne(function (err, kitten) {
      +  if (err) return handleError(err);
      +
      +  // kitten may be null if no document matched
      +  if (kitten) {
      +    ...
      +  }
      +})

      Query#count(callback)

      Exectues the query as a count() operation.

      show code
      Query.prototype.count = function (callback) {
      +  this.op = 'count';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.count(castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'black').count(function (err, count) {
      +  if (err) return handleError(err);
      +  console.log('there are %d black kittens', count);
      +})

      Query#distinct(field, callback)

      Executes this query as a distict() operation.

      show code
      Query.prototype.distinct = function (field, callback) {
      +  this.op = 'distinct';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.distinct(field, castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#update(doc, callback)

      Executes this query as an update() operation.

      show code
      Query.prototype.update = function update (doc, callback) {
      +  this.op = 'update';
      +  this._updateArg = doc;
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , fn = 'function' == typeof callback
      +    , castedQuery
      +    , castedDoc
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedQuery));
      +      return this;
      +    }
      +    throw castedQuery;
      +  }
      +
      +  castedDoc = castDoc(this);
      +  if (!castedDoc) {
      +    fn && process.nextTick(callback.bind(null, null, 0));
      +    return this;
      +  }
      +
      +  if (castedDoc instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedDoc));
      +      return this;
      +    }
      +    throw castedDoc;
      +  }
      +
      +  if (!fn) {
      +    delete options.safe;
      +  }
      +
      +  model.collection.update(castedQuery, castedDoc, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Returns:

      All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

      + +

      Example

      + +
      Model.update({..}, { title: 'remove words' }, ...)
      + +

      becomes

      + +
      Model.update({..}, { $set: { title: 'remove words' }}, ...)
      + +

      Note

      + +

      Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


      Query#_castUpdate(obj)

      Casts obj for an update command.

      show code
      Query.prototype._castUpdate = function _castUpdate (obj) {
      +  var ops = Object.keys(obj)
      +    , i = ops.length
      +    , ret = {}
      +    , hasKeys
      +    , val
      +
      +  while (i--) {
      +    var op = ops[i];
      +    if ('$' !== op[0]) {
      +      // fix up $set sugar
      +      if (!ret.$set) {
      +        if (obj.$set) {
      +          ret.$set = obj.$set;
      +        } else {
      +          ret.$set = {};
      +        }
      +      }
      +      ret.$set[op] = obj[op];
      +      ops.splice(i, 1);
      +      if (!~ops.indexOf('$set')) ops.push('$set');
      +    } else if ('$set' === op) {
      +      if (!ret.$set) {
      +        ret[op] = obj[op];
      +      }
      +    } else {
      +      ret[op] = obj[op];
      +    }
      +  }
      +
      +  // cast each value
      +  i = ops.length;
      +
      +  while (i--) {
      +    op = ops[i];
      +    val = ret[op];
      +    if ('Object' === val.constructor.name) {
      +      hasKeys |= this._walkUpdatePath(val, op);
      +    } else {
      +      var msg = 'Invalid atomic update value for ' + op + '. '
      +              + 'Expected an object, received ' + typeof val;
      +      throw new Error(msg);
      +    }
      +  }
      +
      +  return hasKeys && ret;
      +}

      Parameters:

      Returns:

      • <Object> obj after casting its values

      Query#_walkUpdatePath(obj, op, pref)

      Walk each path of obj and cast its values
      according to its schema.

      show code
      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
      +  var strict = this.model.schema.options.strict
      +    , prefix = pref ? pref + '.' : ''
      +    , keys = Object.keys(obj)
      +    , i = keys.length
      +    , hasKeys = false
      +    , schema
      +    , key
      +    , val
      +
      +  while (i--) {
      +    key = keys[i];
      +    val = obj[key];
      +
      +    if (val && 'Object' === val.constructor.name) {
      +      // watch for embedded doc schemas
      +      schema = this._getSchema(prefix + key);
      +      if (schema && schema.caster && op in castOps) {
      +        // embedded doc schema
      +
      +        if (strict && !schema) {
      +          // path is not in our strict schema
      +          if ('throw' == strict) {
      +            throw new Error('Field `' + key + '` is not in schema.');
      +          } else {
      +            // ignore paths not specified in schema
      +            delete obj[key];
      +          }
      +        } else {
      +          hasKeys = true;
      +          if ('$each' in val) {
      +            obj[key] = {
      +                $each: this._castUpdateVal(schema, val.$each, op)
      +            }
      +          } else {
      +            obj[key] = this._castUpdateVal(schema, val, op);
      +          }
      +        }
      +      } else {
      +        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
      +      }
      +    } else {
      +      schema = '$each' === key
      +        ? this._getSchema(pref)
      +        : this._getSchema(prefix + key);
      +
      +      var skip = strict &&
      +                 !schema &&
      +                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
      +
      +      if (skip) {
      +        if ('throw' == strict) {
      +          throw new Error('Field `' + prefix + key + '` is not in schema.');
      +        } else {
      +          delete obj[key];
      +        }
      +      } else {
      +        hasKeys = true;
      +        obj[key] = this._castUpdateVal(schema, val, op, key);
      +      }
      +    }
      +  }
      +  return hasKeys;
      +}

      Parameters:

      • obj <Object> - part of a query
      • op <String> - the atomic operator ($pull, $set, etc)
      • pref <String> - path prefix (internal only)

      Returns:

      • <Bool> true if this path has keys to update

      Query#_castUpdateVal(schema, val, op, [$conditional])

      Casts val according to schema and atomic op.

      show code
      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
      +  if (!schema) {
      +    // non-existing schema path
      +    return op in numberOps
      +      ? Number(val)
      +      : val
      +  }
      +
      +  if (schema.caster && op in castOps &&
      +    ('Object' === val.constructor.name || Array.isArray(val))) {
      +    // Cast values for ops that add data to MongoDB.
      +    // Ensures embedded documents get ObjectIds etc.
      +    var tmp = schema.cast(val);
      +
      +    if (Array.isArray(val)) {
      +      val = tmp;
      +    } else {
      +      val = tmp[0];
      +    }
      +  }
      +
      +  if (op in numberOps) return Number(val);
      +  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
      +  return schema.castForQuery(val)
      +}

      Parameters:


      Query#_getSchema(path)

      Finds the schema for path. This is different than
      calling schema.path as it also resolves paths with
      positional selectors (something.$.another.$.path).

      show code
      Query.prototype._getSchema = function _getSchema (path) {
      +  var schema = this.model.schema
      +    , pathschema = schema.path(path);
      +
      +  if (pathschema)
      +    return pathschema;
      +
      +  // look for arrays
      +  return (function search (parts, schema) {
      +    var p = parts.length + 1
      +      , foundschema
      +      , trypath
      +
      +    while (p--) {
      +      trypath = parts.slice(0, p).join('.');
      +      foundschema = schema.path(trypath);
      +      if (foundschema) {
      +        if (foundschema.caster) {
      +
      +          // array of Mixed?
      +          if (foundschema.caster instanceof Types.Mixed) {
      +            return foundschema.caster;
      +          }
      +
      +          // Now that we found the array, we need to check if there
      +          // are remaining document paths to look up for casting.
      +          // Also we need to handle array.$.path since schema.path
      +          // doesn't work for that.
      +          if (p !== parts.length) {
      +            if ('$' === parts[p]) {
      +              // comments.$.comments.$.title
      +              return search(parts.slice(p+1), foundschema.schema);
      +            } else {
      +              // this is the last path of the selector
      +              return search(parts.slice(p), foundschema.schema);
      +            }
      +          }
      +        }
      +        return foundschema;
      +      }
      +    }
      +  })(path.split('.'), schema)
      +}

      Parameters:


      Query#_castFields(fields)

      Casts selected field arguments for field selection with mongo 2.2

      show code
      Query.prototype._castFields = function _castFields (fields) {
      +  var selected
      +    , elemMatchKeys
      +    , keys
      +    , key
      +    , out
      +    , i
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    elemMatchKeys = [];
      +    i = keys.length;
      +
      +    // collect $elemMatch args
      +    while (i--) {
      +      key = keys[i];
      +      if (fields[key].$elemMatch) {
      +        selected || (selected = {});
      +        selected[key] = fields[key];
      +        elemMatchKeys.push(key);
      +      }
      +    }
      +  }
      +
      +  if (selected) {
      +    // they passed $elemMatch, cast em
      +    try {
      +      out = this.cast(this.model, selected);
      +    } catch (err) {
      +      return err;
      +    }
      +
      +    // apply the casted field args
      +    i = elemMatchKeys.length;
      +    while (i--) {
      +      key = elemMatchKeys[i];
      +      fields[key] = out[key];
      +    }
      +  }
      +
      +  return fields;
      +}

      Parameters:

      query.select({ ids: { $elemMatch: { $in: [hexString] }})

      Query#remove(callback)

      Executes this query as a remove() operation.

      show code
      Query.prototype.remove = function (callback) {
      +  this.op = 'remove';
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , cb = 'function' == typeof callback
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    if (cb) return callback(err);
      +    throw err;
      +  }
      +
      +  if (!cb) {
      +    delete options.safe;
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.remove(castQuery, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Example

      + +
      Cassette.where('artist').equals('Anne Murray').remove(callback)

      Query#findOneAndUpdate([query], [doc], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
      +  this.op = 'findOneAndUpdate';
      +
      +  switch (arguments.length) {
      +    case 3:
      +      if ('function' == typeof options)
      +        callback = options, options = {};
      +      break;
      +    case 2:
      +      if ('function' == typeof doc) {
      +        callback = doc;
      +        doc = query;
      +        query = undefined;
      +      }
      +      options = undefined;
      +      break;
      +    case 1:
      +      if ('function' == typeof query) {
      +        callback = query;
      +        query = options = doc = undefined;
      +      } else {
      +        doc = query;
      +        query = options = undefined;
      +      }
      +  }
      +
      +  // apply query
      +  if (query) {
      +    if ('Object' === query.constructor.name) {
      +      merge(this._conditions, query);
      +    } else if (query instanceof Query) {
      +      merge(this._conditions, query._conditions);
      +    } else if (query instanceof Document) {
      +      merge(this._conditions, query.toObject());
      +    }
      +  }
      +
      +  // apply doc
      +  if (doc) {
      +    merge(this._updateArg, doc);
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('update', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      query.findOneAndUpdate(conditions, update, options, callback) // executes
      +query.findOneAndUpdate(conditions, update, options)  // returns Query
      +query.findOneAndUpdate(conditions, update, callback) // executes
      +query.findOneAndUpdate(conditions, update)           // returns Query
      +query.findOneAndUpdate(callback)                     // executes
      +query.findOneAndUpdate()                             // returns Query

      Query#findOneAndRemove([conditions], [options], [callback])

      Issues a mongodb findAndModify remove command.

      show code
      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
      +  this.op = 'findOneAndRemove';
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = undefined;
      +  }
      +
      +  // apply conditions
      +  if (conditions) {
      +    if ('Object' === conditions.constructor.name) {
      +      merge(this._conditions, conditions);
      +    } else if (conditions instanceof Query) {
      +      merge(this._conditions, conditions._conditions);
      +    } else if (conditions instanceof Document) {
      +      merge(this._conditions, conditions.toObject());
      +    }
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('remove', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      A.where().findOneAndRemove(conditions, options, callback) // executes
      +A.where().findOneAndRemove(conditions, options)  // return Query
      +A.where().findOneAndRemove(conditions, callback) // executes
      +A.where().findOneAndRemove(conditions) // returns Query
      +A.where().findOneAndRemove(callback)   // executes
      +A.where().findOneAndRemove()           // returns Query

      Query#_findAndModify(type, callback)

      _findAndModify

      show code
      Query.prototype._findAndModify = function (type, callback) {
      +  var model = this.model
      +    , promise = new Promise(callback)
      +    , self = this
      +    , castedQuery
      +    , castedDoc
      +    , fields
      +    , sort
      +    , opts
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    process.nextTick(promise.error.bind(promise, castedQuery));
      +    return promise;
      +  }
      +
      +  opts = this._optionsForExec(model);
      +
      +  if ('remove' == type) {
      +    opts.remove = true;
      +  } else {
      +    if (!('new' in opts)) opts.new = true;
      +    if (!('upsert' in opts)) opts.upsert = false;
      +
      +    castedDoc = castDoc(this);
      +    if (!castedDoc) {
      +      if (opts.upsert) {
      +        // still need to do the upsert to empty doc
      +        castedDoc = { $set: {} };
      +      } else {
      +        return this.findOne(callback);
      +      }
      +    } else if (castedDoc instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, castedDoc));
      +      return promise;
      +    }
      +  }
      +
      +  if (this._fields) {
      +    fields = utils.clone(this._fields)
      +    opts.fields = this._castFields(fields);
      +    if (opts.fields instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, opts.fields));
      +      return promise;
      +    }
      +  }
      +
      +  // the driver needs a default
      +  sort = opts.sort || [];
      +
      +  model
      +  .collection
      +  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === opts.lean) {
      +      return promise.complete(doc);
      +    }
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return promise;
      +}

      Parameters:


      Query#populate(path, [fields], [model], [conditions], [options])

      Specifies paths which should be populated with other documents.

      show code
      Query.prototype.populate = function (path, fields, model, conditions, options) {
      +  if ('string' !== typeof model) {
      +    options = conditions;
      +    conditions = model;
      +    model = undefined;
      +  }
      +  // The order of fields/conditions args is opposite Model.find but
      +  // necessary to keep backward compatibility (fields could be
      +  // an array, string, or object literal).
      +  this.options.populate[path] =
      +    new PopulateOptions(fields, conditions, options, model);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

      + +

      Example:

      + +
      Kitten.findOne().populate('owner').exec(function (err, kitten) {
      +  console.log(kitten.owner.name) // Max
      +})

      Query#stream()

      Returns a stream interface

      show code
      Query.prototype.stream = function stream () {
      +  return new QueryStream(this);
      +}
      +
      +// helpers

      Returns:

      Example

      + +
      // follows the nodejs stream api
      +Thing.find({ name: /^hello/ }).stream().pipe(res)
      +
      +// manual streaming
      +var stream = Thing.find({ name: /^hello/ }).stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});

      Query#within

      Syntax sugar for expressive queries.

      + +

      Example

      + +
      query.within.box()
      +query.within.center()

      Returns:


    • querystream.js

      QueryStream(query)

      Provides a ReadStream interface for Queries.

      show code
      function QueryStream (query) {
      +  Stream.call(this);
      +
      +  this.query = query;
      +  this.readable = true;
      +  this.paused = false;
      +  this._cursor = null;
      +  this._destroyed = null;
      +  this._fields = null;
      +  this._buffer = null;
      +  this._inline = T_INIT;
      +
      +  // give time to hook up events
      +  var self = this;
      +  process.nextTick(function () {
      +    self._init();
      +  });
      +}

      Parameters:

      Inherits:

      Events:

      • data: emits a single Mongoose document

      • error: emits when an error occurs during streaming. This will emit before the close event.

      • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

      var stream = Model.find().stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});
      + +

      The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

      + +
      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

      QueryStream#_init()

      Initializes the query.

      show code
      QueryStream.prototype._init = function () {
      +  if (this._destroyed) return;
      +
      +  var query = this.query
      +    , model = query.model
      +    , options = query._optionsForExec(model)
      +    , self = this
      +
      +  try {
      +    query.cast(model);
      +  } catch (err) {
      +    return self.destroy(err);
      +  }
      +
      +  self._fields = utils.clone(query._fields);
      +  options.fields = query._castFields(self._fields);
      +
      +  model.collection.find(query._conditions, options, function (err, cursor) {
      +    if (err) return self.destroy(err);
      +    self._cursor = cursor;
      +    self._next();
      +  });
      +}

      QueryStream#_next()

      Trampoline for pulling the next doc from cursor.

      show code
      QueryStream.prototype._next = function _next () {
      +  if (this.paused || this._destroyed) return;
      +
      +  if (this._buffer && this._buffer.length) {
      +    var arg;
      +    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
      +      this._onNextObject.apply(this, arg);
      +    }
      +  }
      +
      +  // account for possible nextObjects calling user code
      +  if (this.paused || this._destroyed) return;
      +
      +  // avoid stack overflows with large result sets.
      +  // trampoline instead of recursion.
      +  var fn;
      +  while (this.__next()) {}
      +}

      QueryStream#__next()

      Pulls the next doc from the cursor.

      show code
      QueryStream.prototype.__next = function () {
      +  if (this.paused || this._destroyed) return;
      +
      +  var self = this;
      +  self._inline = T_INIT;
      +
      +  self._cursor.nextObject(function cursorcb (err, doc) {
      +    self._onNextObject(err, doc);
      +  });
      +
      +  // if onNextObject() was already called in this tick
      +  // return ourselves to the trampoline.
      +  if (T_CONT === this._inline) {
      +    return true;
      +  } else {
      +    // onNextObject() hasn't fired yet. tell onNextObject
      +    // that its ok to call _next b/c we are not within
      +    // the trampoline anymore.
      +    this._inline = T_IDLE;
      +  }
      +}

      QueryStream#_onNextObject(err, doc)

      Transforms raw docs returned from the cursor into a model instance.

      show code
      QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
      +  if (this._destroyed) return;
      +
      +  if (this.paused) {
      +    this._buffer || (this._buffer = []);
      +    this._buffer.push([err, doc]);
      +    return;
      +  }
      +
      +  if (err) return this.destroy(err);
      +
      +  // when doc is null we hit the end of the cursor
      +  if (!doc) {
      +    this.emit('end');
      +    return this.destroy();
      +  }
      +
      +  if (this.query.options && this.query.options.lean === true)  {
      +    this.emit('data', doc);
      +
      +    // trampoline management
      +    if (T_IDLE === this._inline) {
      +      // no longer in trampoline. restart it.
      +      this._next();
      +    } else {
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      this._inline = T_CONT;
      +    }
      +    return;
      +  }
      +
      +  var instance = new this.query.model(undefined, this._fields, true);
      +
      +  var self = this;
      +  instance.init(doc, this.query, function (err) {
      +    if (err) return self.destroy(err);
      +    self.emit('data', instance);
      +
      +    // trampoline management
      +    if (T_IDLE === self._inline) {
      +      // no longer in trampoline. restart it.
      +      self._next();
      +    } else
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      self._inline = T_CONT;
      +  });
      +}

      Parameters:


      QueryStream#pause()

      Pauses this stream.

      show code
      QueryStream.prototype.pause = function () {
      +  this.paused = true;
      +}

      QueryStream#resume()

      Resumes this stream.

      show code
      QueryStream.prototype.resume = function () {
      +  this.paused = false;
      +  this._next();
      +}

      QueryStream#destroy([err])

      Destroys the stream, closing the underlying cursor. No more events will be emitted.

      show code
      QueryStream.prototype.destroy = function (err) {
      +  if (this._destroyed) return;
      +  this._destroyed = true;
      +  this.readable = false;
      +
      +  if (this._cursor) {
      +    this._cursor.close();
      +  }
      +
      +  if (err) {
      +    this.emit('error', err);
      +  }
      +
      +  this.emit('close');
      +}

      Parameters:


      QueryStream#pipe()

      Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

      See:

      Example:

      + +
      query.stream().pipe(writeStream [, options])
      + +

      This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      + +
      var format = new ArrayFormatter;
      +Events.find().stream().pipe(format).pipe(res);
      + +

      As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


      QueryStream#paused

      Flag stating whether or not this stream is paused.


      QueryStream#readable

      Flag stating whether or not this stream is readable.


    • schema/array.js

      SchemaArray(key, cast, options)

      Array SchemaType constructor

      show code
      function SchemaArray (key, cast, options) {
      +  if (cast) {
      +    var castOptions = {};
      +
      +    if ('Object' === cast.constructor.name) {
      +      if (cast.type) {
      +        // support { type: Woot }
      +        castOptions = cast;
      +        cast = cast.type;
      +        delete castOptions.type;
      +      } else {
      +        cast = Mixed;
      +      }
      +    }
      +
      +    var caster = cast.name in Types ? Types[cast.name] : cast;
      +    this.casterConstructor = caster;
      +    this.caster = new caster(null, castOptions);
      +  }
      +
      +  SchemaType.call(this, key, options);
      +
      +  var self = this
      +    , defaultArr
      +    , fn;
      +
      +  if (this.defaultValue) {
      +    defaultArr = this.defaultValue;
      +    fn = 'function' == typeof defaultArr;
      +  }
      +
      +  this.default(function(){
      +    var arr = fn ? defaultArr() : defaultArr || [];
      +    return new MongooseArray(arr, self.path, this);
      +  });
      +};

      Parameters:

      Inherits:


      SchemaArray#checkRequired(value)

      Check required

      show code
      SchemaArray.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      Parameters:


      SchemaArray#applyGetters(value, scope)

      Overrides the getters application for the population special-case

      show code
      SchemaArray.prototype.applyGetters = function (value, scope) {
      +  if (this.caster.options && this.caster.options.ref) {
      +    // means the object id was populated
      +    return value;
      +  }
      +
      +  return SchemaType.prototype.applyGetters.call(this, value, scope);
      +};

      Parameters:


      SchemaArray#cast(value, doc, init)

      Casts contents

      show code
      SchemaArray.prototype.cast = function (value, doc, init) {
      +  if (Array.isArray(value)) {
      +    if (!(value instanceof MongooseArray)) {
      +      value = new MongooseArray(value, this.path, doc);
      +    }
      +
      +    if (this.caster) {
      +      try {
      +        for (var i = 0, l = value.length; i < l; i++) {
      +          value[i] = this.caster.cast(value[i], doc, init);
      +        }
      +      } catch (e) {
      +        // rethrow
      +        throw new CastError(e.type, value);
      +      }
      +    }
      +
      +    return value;
      +  } else {
      +    return this.cast([value], doc, init);
      +  }
      +};

      Parameters:

      • value <Object>
      • doc <Document> document that triggers the casting
      • init <Boolean> whether this is an initialization cast

      SchemaArray#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaArray.prototype.castForQuery = function ($conditional, value) {
      +  var handler
      +    , val;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Array.");
      +    val = handler.call(this, value);
      +  } else {
      +    val = $conditional;
      +    var proto = this.casterConstructor.prototype;
      +    var method = proto.castForQuery || proto.cast;
      +    if (Array.isArray(val)) {
      +      val = val.map(function (v) {
      +        if (method) v = method.call(proto, v);
      +        return isMongooseObject(v)
      +          ? v.toObject()
      +          : v;
      +      });
      +    } else if (method) {
      +      val = method.call(proto, val);
      +    }
      +  }
      +  return val && isMongooseObject(val)
      +    ? val.toObject()
      +    : val;
      +};

      Parameters:


    • schema/boolean.js

      SchemaBoolean(path, options)

      Boolean SchemaType constructor.

      show code
      function SchemaBoolean (path, options) {
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      SchemaBoolean#checkRequired()

      Required validator

      show code
      SchemaBoolean.prototype.checkRequired = function (value) {
      +  return value === true || value === false;
      +};

      SchemaBoolean#cast(value)

      Casts to boolean

      show code
      SchemaBoolean.prototype.cast = function (value) {
      +  if (value === null) return value;
      +  if (value === '0') return false;
      +  return !!value;
      +};

      Parameters:


      SchemaBoolean#castForQuery($conditional, val)

      Casts contents for queries.

      show code
      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (2 === arguments.length) {
      +    handler = SchemaBoolean.$conditionalHandlers[$conditional];
      +
      +    if (handler) {
      +      return handler.call(this, val);
      +    }
      +
      +    return this.cast(val);
      +  }
      +
      +  return this.cast($conditional);
      +};

      Parameters:


    • schema/buffer.js

      SchemaBuffer(key, cast)

      Buffer SchemaType constructor

      show code
      function SchemaBuffer (key, options) {
      +  SchemaType.call(this, key, options, 'Buffer');
      +};

      Parameters:

      Inherits:


      SchemaBuffer#checkRequired()

      Check required

      show code
      SchemaBuffer.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      SchemaBuffer#cast(value, doc, init)

      Casts contents

      show code
      SchemaBuffer.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (Buffer.isBuffer(value)) {
      +    if (!(value instanceof MongooseBuffer)) {
      +      value = new MongooseBuffer(value, [this.path, doc]);
      +    }
      +
      +    return value;
      +  } else if (value instanceof Binary) {
      +    return new MongooseBuffer(value.value(true), [this.path, doc]);
      +  }
      +
      +  if ('string' === typeof value || Array.isArray(value)) {
      +    return new MongooseBuffer(value, [this.path, doc]);
      +  }
      +
      +  throw new CastError('buffer', value);
      +};

      Parameters:


      SchemaBuffer#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Buffer.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    return this.cast(val).toObject();
      +  }
      +};

      Parameters:


    • schema/date.js

      SchemaDate(key, options)

      Date SchemaType constructor.

      show code
      function SchemaDate (key, options) {
      +  SchemaType.call(this, key, options);
      +};

      Parameters:

      Inherits:


      SchemaDate#checkRequired()

      Required validator for date

      show code
      SchemaDate.prototype.checkRequired = function (value) {
      +  return value instanceof Date;
      +};

      SchemaDate#cast(value)

      Casts to date

      show code
      SchemaDate.prototype.cast = function (value) {
      +  if (value === null || value === '')
      +    return null;
      +
      +  if (value instanceof Date)
      +    return value;
      +
      +  var date;
      +
      +  // support for timestamps
      +  if (value instanceof Number || 'number' == typeof value 
      +      || String(value) == Number(value))
      +    date = new Date(Number(value));
      +
      +  // support for date strings
      +  else if (value.toString)
      +    date = new Date(value.toString());
      +
      +  if (date.toString() != 'Invalid Date')
      +    return date;
      +
      +  throw new CastError('date', value);
      +};

      Parameters:


      SchemaDate#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaDate.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +
      +  if (2 !== arguments.length) {
      +    return this.cast($conditional);
      +  }
      +
      +  handler = this.$conditionalHandlers[$conditional];
      +
      +  if (!handler) {
      +    throw new Error("Can't use " + $conditional + " with Date.");
      +  }
      +
      +  return handler.call(this, val);
      +};

      Parameters:


    • schema/documentarray.js

      DocumentArray(key, schema, options)

      SubdocsArray SchemaType constructor

      show code
      function DocumentArray (key, schema, options) {
      +
      +  // compile an embedded document for this schema
      +  function EmbeddedDocument () {
      +    Subdocument.apply(this, arguments);
      +  }
      +
      +  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
      +  EmbeddedDocument.prototype._setSchema(schema);
      +  EmbeddedDocument.schema = schema;
      +
      +  // apply methods
      +  for (var i in schema.methods) {
      +    EmbeddedDocument.prototype[i] = schema.methods[i];
      +  }
      +
      +  // apply statics
      +  for (var i in schema.statics)
      +    EmbeddedDocument[i] = schema.statics[i];
      +
      +  EmbeddedDocument.options = options;
      +  this.schema = schema;
      +
      +  ArrayType.call(this, key, EmbeddedDocument, options);
      +
      +  this.schema = schema;
      +  var path = this.path;
      +  var fn = this.defaultValue;
      +
      +  this.default(function(){
      +    var arr = fn.call(this);
      +    if (!Array.isArray(arr)) arr = [arr];
      +    return new MongooseDocumentArray(arr, path, this);
      +  });
      +};

      Parameters:

      Inherits:


      DocumentArray#doValidate()

      Performs local validations first, then validations on each embedded doc

      show code
      DocumentArray.prototype.doValidate = function (array, fn, scope) {
      +  var self = this;
      +  SchemaType.prototype.doValidate.call(this, array, function(err){
      +    if (err) return fn(err);
      +
      +    var count = array && array.length
      +      , error = false;
      +
      +    if (!count) return fn();
      +
      +    array.forEach(function(doc, index){
      +      doc.validate(function(err){
      +        if (err && !error){
      +          // rewrite they key
      +          err.key = self.key + '.' + index + '.' + err.key;
      +          fn(err);
      +          error = true;
      +        } else {
      +          --count || fn();
      +        }
      +      });
      +    });
      +  }, scope);
      +};

      DocumentArray#cast(value, document)

      Casts contents

      show code
      DocumentArray.prototype.cast = function (value, doc, init, prev) {
      +  var selected
      +    , subdoc
      +    , i
      +
      +  if (!Array.isArray(value)) {
      +    return this.cast([value], doc, init, prev);
      +  }
      +
      +  if (!(value instanceof MongooseDocumentArray)) {
      +    value = new MongooseDocumentArray(value, this.path, doc);
      +  }
      +
      +  i = value.length;
      +
      +  while (i--) {
      +    if (!(value[i] instanceof Subdocument)) {
      +      if (init) {
      +        selected || (selected = scopePaths(this, doc._selected, init));
      +        subdoc = new this.casterConstructor(null, value, true, selected);
      +        value[i] = subdoc.init(value[i]);
      +      } else {
      +        if (prev && (subdoc = prev.id(value[i]._id))) {
      +          // handle resetting doc with existing id but differing data
      +          // doc.array = [{ doc: 'val' }]
      +          subdoc.set(value[i]);
      +        } else {
      +          subdoc = new this.casterConstructor(value[i], value);
      +        }
      +
      +        // if set() is hooked it will have no return value
      +        // see gh-746
      +        value[i] = subdoc;
      +      }
      +    }
      +  }
      +
      +  return value;
      +}

      Parameters:


    • schema/mixed.js

      Mixed(path, options)

      Mixed SchemaType constructor.

      show code
      function Mixed (path, options) {
      +  // make sure empty array defaults are handled
      +  if (options &&
      +      options.default &&
      +      Array.isArray(options.default) &&
      +      0 === options.default.length) {
      +    options.default = Array;
      +  }
      +
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      Mixed#checkRequired()

      Required validator

      show code
      Mixed.prototype.checkRequired = function (val) {
      +  return true;
      +};

      Mixed#cast(value)

      Casts val for Mixed.

      show code
      Mixed.prototype.cast = function (val) {
      +  return val;
      +};

      Parameters:

      this is a no-op


      Mixed#castForQuery($cond, [val])

      Casts contents for queries.

      show code
      Mixed.prototype.castForQuery = function ($cond, val) {
      +  if (arguments.length === 2) return val;
      +  return $cond;
      +};

      Parameters:


    • schema/number.js

      SchemaNumber(key, options)

      Number SchemaType constructor.

      show code
      function SchemaNumber (key, options) {
      +  SchemaType.call(this, key, options, 'Number');
      +};

      Parameters:

      Inherits:


      SchemaNumber#checkRequired()

      Required validator for number

      show code
      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return typeof value == 'number' || value instanceof Number;
      +  }
      +};

      SchemaNumber#min(value, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.min = function (value, message) {
      +  if (this.minValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'min';
      +    });
      +  if (value != null)
      +    this.validators.push([function(v){
      +      return v === null || v >= value;
      +    }, 'min']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, min: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 9 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#max(maximum, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.max = function (value, message) {
      +  if (this.maxValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'max';
      +    });
      +  if (value != null)
      +    this.validators.push([this.maxValidator = function(v){
      +      return v === null || v <= value;
      +    }, 'max']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, max: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 11 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#cast(value, doc, init)

      Casts to number

      show code
      SchemaNumber.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (!isNaN(value)){
      +    if (null === value) return value;
      +    if ('' === value) return null;
      +    if ('string' == typeof value) value = Number(value);
      +    if (value instanceof Number) return value
      +    if ('number' == typeof value) return value;
      +    if (value.toString && !Array.isArray(value) &&
      +        value.toString() == Number(value)) {
      +      return new Number(value)
      +    }
      +  }
      +
      +  throw new CastError('number', value);
      +};

      Parameters:


      SchemaNumber#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Number.");
      +    return handler.call(this, val);
      +  } else {
      +    val = this.cast($conditional);
      +    return val == null ? val : val
      +  }
      +};

      Parameters:


    • schema/objectid.js

      ObjectId(key, options)

      ObjectId SchemaType constructor.

      show code
      function ObjectId (key, options) {
      +  SchemaType.call(this, key, options, 'ObjectID');
      +};

      Parameters:

      Inherits:


      ObjectId#checkRequired()

      Check required

      show code
      ObjectId.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return value instanceof oid;
      +  }
      +};

      ObjectId#cast(value, scope, init)

      Casts to ObjectId

      show code
      ObjectId.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (value === null) return value;
      +
      +  if (value instanceof oid)
      +    return value;
      +
      +  if (value._id && value._id instanceof oid)
      +    return value._id;
      +
      +  if (value.toString)
      +    return oid.fromString(value.toString());
      +
      +  throw new CastError('object id', value);
      +};

      Parameters:


      ObjectId#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      ObjectId.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with ObjectId.");
      +    return handler.call(this, val);
      +  } else {
      +    return this.cast($conditional);
      +  }
      +};

      Parameters:


      ObjectId#auto(turnOn)

      Adds an auto-generated ObjectId default if turnOn is true.

      show code
      ObjectId.prototype.auto = function (turnOn) {
      +  if (turnOn) {
      +    this.default(defaultId);
      +    this.set(resetId)
      +  }
      +};

      Parameters:

      • turnOn <Boolean> auto generated ObjectId defaults

    • schema/string.js

      SchemaString(key, options)

      String SchemaType constructor.

      show code
      function SchemaString (key, options) {
      +  this.enumValues = [];
      +  this.regExp = null;
      +  SchemaType.call(this, key, options, 'String');
      +};

      Parameters:

      Inherits:


      SchemaString#enum([args...])

      Adds enumeration values and a coinciding validator.

      show code
      SchemaString.prototype.enum = function () {
      +  var len = arguments.length;
      +  if (!len || undefined === arguments[0] || false === arguments[0]) {
      +    if (this.enumValidator){
      +      this.enumValidator = false;
      +      this.validators = this.validators.filter(function(v){
      +        return v[1] != 'enum';
      +      });
      +    }
      +    return;
      +  }
      +
      +  for (var i = 0; i < len; i++) {
      +    if (undefined !== arguments[i]) {
      +      this.enumValues.push(this.cast(arguments[i]));
      +    }
      +  }
      +
      +  if (!this.enumValidator) {
      +    var values = this.enumValues;
      +    this.enumValidator = function(v){
      +      return undefined === v || ~values.indexOf(v);
      +    };
      +    this.validators.push([this.enumValidator, 'enum']);
      +  }
      +};

      Parameters:

      • [args...] <String> enumeration values

      Example:

      + +
      var states = 'opening open closing closed'.split(' ')
      +var s = new Schema({ state: { type: String, enum: states })
      +var M = db.model('M', s)
      +var m = new M({ state: 'invalid' })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.state = 'open'
      +  m.save() // success
      +})

      SchemaString#lowercase()

      Adds a lowercase setter.

      show code
      SchemaString.prototype.lowercase = function () {
      +  return this.set(function (v) {
      +    return v.toLowerCase();
      +  });
      +};

      Example:

      + +
      var s = new Schema({ email: { type: String, lowercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ email: 'SomeEmail@example.COM' });
      +console.log(m.email) // someemail@example.com
      +

      SchemaString#uppercase()

      Adds an uppercase setter.

      show code
      SchemaString.prototype.uppercase = function () {
      +  return this.set(function (v) {
      +    return v.toUpperCase();
      +  });
      +};

      Example:

      + +
      var s = new Schema({ caps: { type: String, uppercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ caps: 'an example' });
      +console.log(m.caps) // AN EXAMPLE

      SchemaString#trim()

      Adds a trim setter.

      show code
      SchemaString.prototype.trim = function () {
      +  return this.set(function (v) {
      +    return v.trim();
      +  });
      +};

      The string value will be trimmed when set.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, trim: true }})
      +var M = db.model('M', s)
      +var string = ' some name '
      +console.log(string.length) // 11
      +var m = new M({ name: string })
      +console.log(m.name.length) // 9

      SchemaString#match(regExp)

      Sets a regexp validator.

      show code
      SchemaString.prototype.match = function match (regExp) {
      +  this.validators.push([function(v){
      +    return null != v && '' !== v
      +      ? regExp.test(v)
      +      : true
      +  }, 'regexp']);
      +};

      Parameters:

      • regExp <RegExp> regular expression to test against

      Any value that does not pass regExp.test(val) will fail validation.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, match: /^a/ }})
      +var M = db.model('M', s)
      +var m = new M({ name: 'invalid' })
      +m.validate(function (err) {
      +  console.error(err) // validation error
      +  m.name = 'apples'
      +  m.validate(function (err) {
      +    assert.ok(err) // success
      +  })
      +})

      SchemaString#checkRequired(value)

      Check required

      show code
      SchemaString.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return (value instanceof String || typeof value == 'string') && value.length;
      +  }
      +};

      Parameters:


      SchemaString#cast()

      Casts to String

      show code
      SchemaString.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +  if (value === null) return value;
      +  if ('undefined' !== typeof value && value.toString) return value.toString();
      +  throw new CastError('string', value);
      +};

      SchemaString#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      SchemaString.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with String.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    if (val instanceof RegExp) return val;
      +    return this.cast(val);
      +  }
      +};

      Parameters:


    • schema.js

      Schema(definition)

      Schema constructor.

      show code
      function Schema (obj, options) {
      +  if (!(this instanceof Schema))
      +    return new Schema(obj, options);
      +
      +  this.paths = {};
      +  this.subpaths = {};
      +  this.virtuals = {};
      +  this.nested = {};
      +  this.inherits = {};
      +  this.callQueue = [];
      +  this._indexes = [];
      +  this.methods = {};
      +  this.statics = {};
      +  this.tree = {};
      +  this._requiredpaths = undefined;
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // build paths
      +  if (obj) {
      +    this.add(obj);
      +  }
      +
      +  // ensure the documents get an auto _id unless disabled
      +  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
      +  if (auto_id) {
      +    this.add({ _id: {type: Schema.ObjectId, auto: true} });
      +  }
      +
      +  // ensure the documents receive an id getter unless disabled
      +  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
      +  if (autoid) {
      +    this.virtual('id').get(idGetter);
      +  }
      +
      +  // versioning not directly added to schema b/c we only want
      +  // it in the top level document, not embedded ones.
      +};

      Parameters:

      Events:

      • init: Emitted after the schema is compiled into a Model.

      Example:

      + +
      var child = new Schema({ name: String });
      +var schema = new Schema({ name: String, age: Number, children: [child] });
      +var Tree = mongoose.model('Tree', schema);
      +
      +// setting schema options
      +new Schema({ name: String }, { _id: false, autoIndex: false })
      + +

      Options:

      + +
        +
      • safe: bool - defaults to true.
      • +
      • read: string
      • +
      • strict: bool - defaults to true
      • +
      • capped: bool - defaults to false
      • +
      • versionKey: bool - defaults to "__v"
      • +
      • shardKey: bool - defaults to null
      • +
      • autoIndex: bool - defaults to true
      • +
      • _id: bool - defaults to true
      • +
      • id: bool - defaults to true
      • +
      • toObject - object - no default
      • +
      • toJSON - object - no default
      • +
      • minimize: bool - controls document#toObject behavior when called manually - defaults to true
      • +
      + +

      Note:

      + +

      When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


      Schema#defaultOptions(options)

      Returns default options for this schema, merged with options.

      show code
      Schema.prototype.defaultOptions = function (options) {
      +  options = utils.options({
      +      safe: true
      +    , strict: true
      +    , capped: false // { size, max, autoIndexId }
      +    , versionKey: '__v'
      +    , minimize: true
      +    , autoIndex: true
      +    , shardKey: null
      +    , read: null
      +    // the following are only applied at construction time
      +    , noId: false // deprecated, use { _id: false }
      +    , _id: true
      +    , noVirtualId: false // deprecated, use { id: false }
      +    , id: true
      +  }, options);
      +
      +  if (options.read)
      +    options.read = utils.readPref(options.read);
      +
      +  return options;
      +}

      Parameters:

      Returns:


      Schema#add(obj, prefix)

      Adds key path / schema type pairs to this schema.

      show code
      Schema.prototype.add = function add (obj, prefix) {
      +  prefix = prefix || '';
      +  for (var i in obj) {
      +    if (null == obj[i]) {
      +      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
      +    }
      +
      +    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
      +      if (Object.keys(obj[i]).length) {
      +        // nested object { last: { name: String }}
      +        this.nested[prefix + i] = true;
      +        this.add(obj[i], prefix + i + '.');
      +      }
      +      else
      +        this.path(prefix + i, obj[i]); // mixed type
      +    } else
      +      this.path(prefix + i, obj[i]);
      +  }
      +};

      Parameters:

      Example:

      + +
      var ToySchema = new Schema;
      +ToySchema.add({ name: 'string', color: 'string', price: 'number' });

      Schema#path(path, constructor)

      Gets/sets schema paths.

      show code
      Schema.prototype.path = function (path, obj) {
      +  if (obj == undefined) {
      +    if (this.paths[path]) return this.paths[path];
      +    if (this.subpaths[path]) return this.subpaths[path];
      +
      +    // subpaths?
      +    return /\.\d+\.?$/.test(path)
      +      ? getPositionalPath(this, path)
      +      : undefined;
      +  }
      +
      +  // some path names conflict with document methods
      +  if (reserved[path]) {
      +    throw new Error("`" + path + "` may not be used as a schema pathname");
      +  }
      +
      +  // update the tree
      +  var subpaths = path.split(/\./)
      +    , last = subpaths.pop()
      +    , branch = this.tree;
      +
      +  subpaths.forEach(function(path) {
      +    if (!branch[path]) branch[path] = {};
      +    branch = branch[path];
      +  });
      +
      +  branch[last] = utils.clone(obj);
      +
      +  this.paths[path] = Schema.interpretAsType(path, obj);
      +  return this;
      +};

      Parameters:

      Sets a path (if arity 2)
      Gets a path (if arity 1)

      + +

      Example

      + +
      schema.path('name') // returns a SchemaType
      +schema.path('name', Number) // changes the schemaType of `name` to Number

      Schema#eachPath(fn)

      Iterates the schemas paths similar to Array#forEach.

      show code
      Schema.prototype.eachPath = function (fn) {
      +  var keys = Object.keys(this.paths)
      +    , len = keys.length;
      +
      +  for (var i = 0; i < len; ++i) {
      +    fn(keys[i], this.paths[keys[i]]);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      The callback is passed the pathname and schemaType as arguments on each iteration.


      Schema#requiredPaths()

      Returns an Array of path strings that are required by this schema.

      show code
      Schema.prototype.requiredPaths = function requiredPaths () {
      +  if (this._requiredpaths) return this._requiredpaths;
      +
      +  var paths = Object.keys(this.paths)
      +    , i = paths.length
      +    , ret = [];
      +
      +  while (i--) {
      +    var path = paths[i];
      +    if (this.paths[path].isRequired) ret.push(path);
      +  }
      +
      +  return this._requiredpaths = ret;
      +}

      Returns:


      Schema#pathType(path)

      Returns the pathType of path for this schema.

      show code
      Schema.prototype.pathType = function (path) {
      +  if (path in this.paths) return 'real';
      +  if (path in this.virtuals) return 'virtual';
      +  if (path in this.nested) return 'nested';
      +  if (path in this.subpaths) return 'real';
      +
      +  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
      +    return 'real';
      +  } else {
      +    return 'adhocOrUndefined'
      +  }
      +};

      Parameters:

      Returns:

      Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


      Schema#queue(name, args)

      Adds a method call to the queue.

      show code
      Schema.prototype.queue = function(name, args){
      +  this.callQueue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the document method to call later
      • args <Array> arguments to pass to the method

      Schema#pre(method, callback)

      Defines a pre hook for the document.

      show code
      Schema.prototype.pre = function(){
      +  return this.queue('pre', arguments);
      +};

      Parameters:

      Example

      + +
      var toySchema = new Schema(..);
      +
      +toySchema.pre('save', function (next) {
      +  if (!this.created) this.created = new Date;
      +  next();
      +})
      +
      +toySchema.pre('validate', function (next) {
      +  if (this.name != 'Woody') this.name = 'Woody';
      +  next();
      +})

      Schema#post(method, fn)

      Defines a post hook for the document.

      show code
      Schema.prototype.post = function(method, fn){
      +  return this.queue('on', arguments);
      +};

      Parameters:

      Post hooks fire on the event emitted from document instances of Models compiled from this schema.

      + +
      var schema = new Schema(..);
      +schema.post('save', function () {
      +  console.log('this fired after a document was saved');
      +});
      +
      +var Model = mongoose.model('Model', schema);
      +
      +var m = new Model(..);
      +m.save(function (err) {
      +  console.log('this fires after the `post` hook');
      +});

      Schema#plugin(plugin, opts)

      Registers a plugin for this schema.

      show code
      Schema.prototype.plugin = function (fn, opts) {
      +  fn(this, opts);
      +  return this;
      +};

      Parameters:


      Schema#method(method, [fn])

      Adds an instance method to documents constructed from Models compiled from this schema.

      show code
      Schema.prototype.method = function (name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.methods[i] = name[i];
      +  else
      +    this.methods[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = kittySchema = new Schema(..);
      +
      +schema.methods.meow = function () {
      +  console.log('meeeeeoooooooooooow');
      +})
      +
      +var Kitty = mongoose.model('Kitty', schema);
      +
      +var fizz = new Kitty;
      +fizz.meow(); // meeeeeooooooooooooow
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      + +
      schema.method({
      +    purr: function () {}
      +  , scratch: function () {}
      +});
      +
      +// later
      +fizz.purr();
      +fizz.scratch();

      Schema#static(name, fn)

      Adds static "class" methods to Models compiled from this schema.

      show code
      Schema.prototype.static = function(name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.statics[i] = name[i];
      +  else
      +    this.statics[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = new Schema(..);
      +schema.static('findByName', function (name, callback) {
      +  return this.find({ name: name }, callback);
      +});
      +
      +var Drink = mongoose.model('Drink', schema);
      +Drink.findByName('sanpellegrino', function (err, drinks) {
      +  //
      +});
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


      Schema#index(fields, [options])

      Defines an index (most likely compound) for this schema.

      show code
      Schema.prototype.index = function (fields, options) {
      +  options || (options = {});
      +
      +  if (options.expires)
      +    utils.expires(options);
      +
      +  this._indexes.push([fields, options]);
      +  return this;
      +};

      Parameters:

      Example

      + +
      schema.index({ first: 1, last: -1 })

      Schema#set(key, [value])

      Sets/gets a schema option.

      show code
      Schema.prototype.set = function (key, value, tags) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +
      +  this.options[key] = 'read' == key
      +    ? utils.readPref(value, tags)
      +    : value;
      +
      +  return this;
      +};

      Parameters:

      • key <String> option name
      • [value] <Object> if not passed, the current option value is returned

      Schema#indexes()

      Compiles indexes from fields and schema-level indexes

      show code
      Schema.prototype.indexes = function () {
      +  var indexes = []
      +    , seenSchemas = [];
      +
      +  collectIndexes(this);
      +
      +  return indexes;
      +
      +  function collectIndexes (schema, prefix) {
      +    if (~seenSchemas.indexOf(schema)) return;
      +    seenSchemas.push(schema);
      +
      +    var index;
      +    var paths = schema.paths;
      +    prefix = prefix || '';
      +
      +    for (var i in paths) {
      +      if (paths[i]) {
      +        if (paths[i] instanceof Types.DocumentArray) {
      +          collectIndexes(paths[i].schema, i + '.');
      +        } else {
      +          index = paths[i]._index;
      +
      +          if (index !== false && index !== null){
      +            var field = {};
      +            field[prefix + i] = '2d' === index ? index : 1;
      +            var options = 'Object' === index.constructor.name ? index : {};
      +            if (!('background' in options)) options.background = true;
      +            indexes.push([field, options]);
      +          }
      +        }
      +      }
      +    }
      +
      +    if (prefix) {
      +      fixSubIndexPaths(schema, prefix);
      +    } else {
      +      schema._indexes.forEach(function (index) {
      +        if (!('background' in index[1])) index[1].background = true;
      +      });
      +      indexes = indexes.concat(schema._indexes);
      +    }
      +  }

      Schema#virtual(name, [options])

      Creates a virtual type with the given name.

      show code
      Schema.prototype.virtual = function (name, options) {
      +  var virtuals = this.virtuals;
      +  var parts = name.split('.');
      +  return virtuals[name] = parts.reduce(function (mem, part, i) {
      +    mem[part] || (mem[part] = (i === parts.length-1)
      +                            ? new VirtualType(options, name)
      +                            : {});
      +    return mem[part];
      +  }, this.tree);
      +};

      Parameters:

      Returns:


      Schema#virtualpath(name)

      Returns the virtual type with the given name.

      show code
      Schema.prototype.virtualpath = function (name) {
      +  return this.virtuals[name];
      +};

      Parameters:

      Returns:


      Schema#namedScope()

      These still haven't been fixed. Once they're working we'll make them public again.

      show code
      Schema.prototype.namedScope = function (name, fn) {
      +  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
      +    , newScope = Object.create(namedScopes)
      +    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
      +  allScopes[name] = newScope;
      +  newScope.name = name;
      +  newScope.block = fn;
      +  newScope.query = new Query();
      +  newScope.decorate(namedScopes, {
      +    block0: function (block) {
      +      return function () {
      +        block.call(this.query);
      +        return this;
      +      };
      +    },
      +    blockN: function (block) {
      +      return function () {
      +        block.apply(this.query, arguments);
      +        return this;
      +      };
      +    },
      +    basic: function (query) {
      +      return function () {
      +        this.query.find(query);
      +        return this;
      +      };
      +    }
      +  });
      +  return newScope;
      +};

      Schema.reserved

      Reserved document keys.

      show code
      Schema.reserved = Object.create(null);
      +var reserved = Schema.reserved;
      +reserved.on =
      +reserved.db =
      +reserved.init =
      +reserved.isNew =
      +reserved.errors =
      +reserved.schema =
      +reserved.options =
      +reserved.modelName =
      +reserved.collection = 1;

      Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      + +
      on, db, init, isNew, errors, schema, options, modelName, collection

      Schema.interpretAsType(path, obj)

      Converts type arguments into Mongoose Types.

      show code
      Schema.interpretAsType = function (path, obj) {
      +  if (obj.constructor.name != 'Object')
      +    obj = { type: obj };
      +
      +  // Get the type making sure to allow keys named "type"
      +  // and default to mixed if not specified.
      +  // { type: { type: String, default: 'freshcut' } }
      +  var type = obj.type && !obj.type.type
      +    ? obj.type
      +    : {};
      +
      +  if ('Object' == type.constructor.name || 'mixed' == type) {
      +    return new Types.Mixed(path, obj);
      +  }
      +
      +  if (Array.isArray(type) || Array == type || 'array' == type) {
      +    // if it was specified through { type } look for `cast`
      +    var cast = (Array == type || 'array' == type)
      +      ? obj.cast
      +      : type[0];
      +
      +    if (cast instanceof Schema) {
      +      return new Types.DocumentArray(path, cast, obj);
      +    }
      +
      +    if ('string' == typeof cast) {
      +      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
      +    } else if (cast && (!cast.type || cast.type.type)
      +                    && 'Object' == cast.constructor.name
      +                    && Object.keys(cast).length) {
      +      return new Types.DocumentArray(path, new Schema(cast), obj);
      +    }
      +
      +    return new Types.Array(path, cast || Types.Mixed, obj);
      +  }
      +
      +  var name = 'string' == typeof type
      +    ? type
      +    : type.name;
      +
      +  if (name) {
      +    name = name.charAt(0).toUpperCase() + name.substring(1);
      +  }
      +
      +  if (undefined == Types[name]) {
      +    throw new TypeError('Undefined type at `' + path +
      +        '`
      +  Did you try nesting Schemas? ' +
      +        'You can only nest using refs or arrays.');
      +  }
      +
      +  return new Types[name](path, obj);
      +};

      Parameters:


      Schema.Types

      The various Mongoose Schema Types.

      show code
      Schema.Types = require('./schema/index');

      Example:

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var ObjectId = mongoose.Schema.Types.ObjectId;
      + +

      Types:

      + +
        +
      • String
      • +
      • Number
      • +
      • Boolean | Bool
      • +
      • Array
      • +
      • Buffer
      • +
      • Date
      • +
      • ObjectId | Oid
      • +
      • Mixed
      • +
      + +

      Using this exposed access to the Mixed SchemaType, we can use them in our schema.

      + +
      var Mixed = mongoose.Schema.Types.Mixed;
      +new mongoose.Schema({ _user: Mixed })

      Schema#tree

      Schema as a tree

      + +

      Example:

      + +
      {
      +    '_id'     : ObjectId
      +  , 'nested'  : {
      +        'key' : String
      +    }
      +}

      Schema#paths

      Schema as flat paths

      + +

      Example:

      + +
      {
      +    '_id'        : SchemaType,
      +  , 'nested.key' : SchemaType,
      +}

    • schemadefault.js

      exports#system.profile

      Default model for querying the system.profiles collection.


    • schematype.js

      SchemaType(path, [options], [instance])

      SchemaType constructor

      show code
      function SchemaType (path, options, instance) {
      +  this.path = path;
      +  this.instance = instance;
      +  this.validators = [];
      +  this.setters = [];
      +  this.getters = [];
      +  this.options = options;
      +  this._index = null;
      +  this.selected;
      +
      +  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
      +    // { unique: true, index: true }
      +    if ('index' == i && this._index) continue;
      +
      +    var opts = Array.isArray(options[i])
      +      ? options[i]
      +      : [options[i]];
      +
      +    this[i].apply(this, opts);
      +  }
      +};

      Parameters:


      SchemaType#default(val)

      Sets a default value for this SchemaType.

      show code
      SchemaType.prototype.default = function (val) {
      +  if (1 === arguments.length) {
      +    this.defaultValue = typeof val === 'function'
      +      ? val
      +      : this.cast(val);
      +    return this;
      +  } else if (arguments.length > 1) {
      +    this.defaultValue = utils.args(arguments);
      +  }
      +  return this.defaultValue;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var schema = new Schema({ n: { type: Number, default: 10 })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.n) // 10
      + +

      Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

      + +

      Example:

      + +
      // values are cast:
      +var schema = new Schema({ aNumber: Number, default: "4.815162342" })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.aNumber) // 4.815162342
      +
      +// default unique objects for Mixed types:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default(function () {
      +  return {};
      +});
      +
      +// if we don't use a function to return object literals for Mixed defaults,
      +// each document will receive a reference to the same object literal creating
      +// a "shared" object instance:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default({});
      +var M = db.model('M', schema);
      +var m1 = new M;
      +m1.mixed.added = 1;
      +console.log(m1.mixed); // { added: 1 }
      +var m2 = new M;
      +console.log(m2.mixed); // { added: 1 }

      SchemaType#index(options)

      Declares the index options for this schematype.

      show code
      SchemaType.prototype.index = function (options) {
      +  this._index = options;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var s = new Schema({ name: { type: String, index: true })
      +var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
      +Schema.path('my.path').index(true);
      +Schema.path('my.path').index({ expires: 60 });
      +Schema.path('my.path').index({ unique: true, sparse: true });
      + +

      NOTE:

      + +

      Indexes are created in the background by default. Specify background: false to override.

      + +

      Direction doesn't matter for single key indexes


      SchemaType#unique(bool)

      Declares an unique index.

      show code
      SchemaType.prototype.unique = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.unique = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, unique: true })
      +Schema.path('name').index({ unique: true });

      SchemaType#sparse(bool)

      Declares a sparse index.

      show code
      SchemaType.prototype.sparse = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.sparse = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, sparse: true })
      +Schema.path('name').index({ sparse: true });

      SchemaType#expires(when)

      Declares a TTL index (rounded to the nearest second) for Date types only.

      show code
      SchemaType.prototype.expires = function (when) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.expires = when;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
      This index type is only compatible with Date types.

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({..}, { expires: 60*60*24 });
      + +

      expires utilizes the ms module from guille allowing us to use a friendlier syntax:

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({..}, { expires: '24h' });
      +
      +// expire in 1.5 hours
      +new Schema({..}, { expires: '1.5h' });
      +
      +// expire in 7 days
      +var schema = new Schema({..});
      +schema.expires('7d');

      SchemaType#set(fn)

      Adds a setter to this schematype.

      show code
      SchemaType.prototype.set = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A setter must be a function.');
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function capitalize (val) {
      +  if ('string' != typeof val) val = '';
      +  return val.charAt(0).toUpperCase() + val.substring(1);
      +}
      +
      +// defining within the schema
      +var s = new Schema({ name: { type: String, set: capitalize }})
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ name: String })
      +s.path('name').set(capitalize)
      + +

      Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

      + +

      You can set up email lower case normalization easily via a Mongoose setter.

      + +
      function toLower (v) {
      +  return v.toLowerCase();
      +}
      +
      +var UserSchema = new Schema({
      +  email: { type: String, set: toLower }
      +})
      +
      +var User = db.model('User', UserSchema)
      +
      +var user = new User({email: 'AVENUE@Q.COM'})
      +console.log(user.email); // 'avenue@q.com'
      +
      +// or
      +var user = new User
      +user.email = 'Avenue@Q.com'
      +console.log(user.email) // 'avenue@q.com'
      +
      + +

      As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

      + +
      new Schema({ email: { type: String, lowercase: true }})

      SchemaType#get(fn)

      Adds a getter to this schematype.

      show code
      SchemaType.prototype.get = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A getter must be a function.');
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function dob (val) {
      +  if (!val) return val;
      +  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      +}
      +
      +// defining within the schema
      +var s = new Schema({ born: { type: Date, get: dob })
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ born: Date })
      +s.path('born').get(dob)
      + +

      Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

      + +

      Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

      + +
      function obfuscate (cc) {
      +  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
      +}
      +
      +var AccountSchema = new Schema({
      +  creditCardNumber: { type: String, get: obfuscate }
      +});
      +
      +var Account = db.model('Account', AccountSchema);
      +
      +Account.findById(id, function (err, found) {
      +  console.log(found.creditCardNumber); // '****-****-****-1234'
      +});

      SchemaType#validate(obj, [error])

      Adds validator(s) for this document path.

      show code
      SchemaType.prototype.validate = function (obj, error) {
      +  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
      +    this.validators.push([obj, error]);
      +    return this;
      +  }
      +
      +  var i = arguments.length
      +    , arg
      +
      +  while (i--) {
      +    arg = arguments[i];
      +    if (!(arg && 'Object' == arg.constructor.name)) {
      +      var msg = 'Invalid validator. Received (' + typeof arg + ') '
      +        + arg
      +        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
      +
      +      throw new Error(msg);
      +    }
      +    this.validate(arg.validator, arg.msg);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Validators must return Boolean. Returning false is interpreted as validation failure.

      + +

      Examples:

      + +
      function validator () { ... }
      +
      +var single = [validator, 'failed']
      +new Schema({ name: { type: String, validate: single }});
      +
      +var many = [
      +    { validator: validator, msg: 'uh oh' }
      +  , { validator: fn, msg: 'failed' }
      +]
      +new Schema({ name: { type: String, validate: many }});
      +
      +// or utilizing SchemaType methods directly:
      +
      +var schema = new Schema({ name: 'string' });
      +schema.path('name').validate(validator, 'validation failed');
      + +

      Asynchronous validation:

      + +

      Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

      + +
      schema.path('name').validate(function (value, respond) {
      +  doStuff(value, function () {
      +    ...
      +    respond(false); // validation failed
      +  })
      + }, 'my error type');
      + +

      Validation occurs pre('save') or whenever you manually execute document#validate.

      + +

      If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

      + +
      var conn = mongoose.createConnection(..);
      +conn.on('error', handleError);
      +
      +var Product = conn.model('Product', yourSchema);
      +var dvd = new Product(..);
      +dvd.save(); // emits error on the `conn` above
      + +

      If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

      + +
      // registering an error listener on the Model lets us handle errors more locally
      +Product.on('error', handleError);

      SchemaType#required(required)

      Adds a required validator to this schematype.

      show code
      SchemaType.prototype.required = function (required) {
      +  var self = this;
      +
      +  function __checkRequired (v) {
      +    // in here, `this` refers to the validating document.
      +    // no validation when this path wasn't selected in the query.
      +    if ('isSelected' in this &&
      +        !this.isSelected(self.path) &&
      +        !this.isModified(self.path)) return true;
      +    return self.checkRequired(v);
      +  }
      +
      +  if (false === required) {
      +    this.isRequired = false;
      +    this.validators = this.validators.filter(function (v) {
      +      return v[0].name !== '__checkRequired';
      +    });
      +  } else {
      +    this.isRequired = true;
      +    this.validators.push([__checkRequired, 'required']);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • required <Boolean> enable/disable the validator

      Returns:

      Example:

      + +
      var s = new Schema({ born: { type: Date, required: true })
      +// or
      +Schema.path('name').required(true);

      SchemaType#getDefault(scope, init)

      Gets the default value

      show code
      SchemaType.prototype.getDefault = function (scope, init) {
      +  var ret = 'function' === typeof this.defaultValue
      +    ? this.defaultValue.call(scope)
      +    : this.defaultValue;
      +
      +  if (null !== ret && undefined !== ret) {
      +    return this.cast(ret, scope, init);
      +  } else {
      +    return ret;
      +  }
      +};

      Parameters:

      • scope <Object> the scope which callback are executed
      • init <Boolean>

      SchemaType#applySetters(value, scope, init)

      Applies setters

      show code
      SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  var v = value
      +    , setters = this.setters
      +    , len = setters.length
      +
      +  if (!len) {
      +    if (null === v || undefined === v) return v;
      +    return init
      +      ? v // if we just initialized we dont recast
      +      : this.cast(v, scope, init, priorVal)
      +  }
      +
      +  while (len--) {
      +    v = setters[len].call(scope, v, this);
      +  }
      +
      +  if (null === v || undefined === v) return v;
      +
      +  // do not cast until all setters are applied #665
      +  v = this.cast(v, scope, init, priorVal);
      +
      +  return v;
      +};

      Parameters:


      SchemaType#applyGetters(value, scope)

      Applies getters to a value

      show code
      SchemaType.prototype.applyGetters = function (value, scope) {
      +  if (SchemaType._isRef(this, value, true)) return value;
      +
      +  var v = value
      +    , getters = this.getters
      +    , len = getters.length;
      +
      +  if (!len) {
      +    return v;
      +  }
      +
      +  while (len--) {
      +    v = getters[len].call(scope, v, this);
      +  }
      +
      +  return v;
      +};

      Parameters:


      SchemaType#select(val)

      Sets default select() behavior for this path.

      show code
      SchemaType.prototype.select = function select (val) {
      +  this.selected = !! val;
      +}

      Parameters:

      Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

      + +

      Example:

      + +
      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      +T.find(..); // field x will always be selected ..
      +// .. unless overridden;
      +T.find().select('-x').exec(callback);

      SchemaType#doValidate(value, callback, scope)

      Performs a validation of value using the validators declared for this SchemaType.

      show code
      SchemaType.prototype.doValidate = function (value, fn, scope) {
      +  var err = false
      +    , path = this.path
      +    , count = this.validators.length;
      +
      +  if (!count) return fn(null);
      +
      +  function validate (val, msg) {
      +    if (err) return;
      +    if (val === undefined || val) {
      +      --count || fn(null);
      +    } else {
      +      fn(err = new ValidatorError(path, msg));
      +    }
      +  }
      +
      +  this.validators.forEach(function (v) {
      +    var validator = v[0]
      +      , message   = v[1];
      +
      +    if (validator instanceof RegExp) {
      +      validate(validator.test(value), message);
      +    } else if ('function' === typeof validator) {
      +      if (2 === validator.length) {
      +        validator.call(scope, value, function (val) {
      +          validate(val, message);
      +        });
      +      } else {
      +        validate(validator.call(scope, value), message);
      +      }
      +    }
      +  });
      +};

      Parameters:


      SchemaType._isRef(self, value, init)

      Determines if value is a valid Reference.

      show code
      SchemaType._isRef = function (self, value, init) {
      +  if (init && self.options && self.options.ref) {
      +    if (null == value) return true;
      +    if (value._id && value._id.constructor.name === self.instance) return true;
      +  }
      +
      +  return false;
      +}

      Parameters:

      Returns:


    • types/array.js

      MongooseArray(values, path, doc)

      Mongoose Array constructor.

      show code
      function MongooseArray (values, path, doc) {
      +  var arr = [];
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:

      NOTE:

      + +

      Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


      MongooseArray#_cast(value)

      Casts a member based on this arrays schema.

      show code
      MongooseArray.prototype._cast = function (value) {
      +  var cast = this._schema.caster.cast
      +    , doc = this._parent;
      +
      +  return cast.call(null, value, doc);
      +};

      Parameters:

      Returns:

      • <value> the casted value

      MongooseArray#_markModified(embeddedDoc, embeddedPath)

      Marks this array as modified.

      show code
      MongooseArray.prototype._markModified = function (embeddedDoc, embeddedPath) {
      +  var parent = this._parent
      +    , dirtyPath;
      +
      +  if (parent) {
      +    if (arguments.length) {
      +      // If an embedded doc bubbled up the change
      +      dirtyPath = [this._path, this.indexOf(embeddedDoc), embeddedPath].join('.');
      +    } else {
      +      dirtyPath = this._path;
      +    }
      +    parent.markModified(dirtyPath);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
      • embeddedPath <String> the path which changed in the embeddedDoc

      If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


      MongooseArray#_registerAtomic(op, val)

      Register an atomic operation with the parent.

      show code
      MongooseArray.prototype._registerAtomic = function (op, val) {
      +  if ('$set' == op) {
      +    // $set takes precedence over all other ops.
      +    // mark entire array modified.
      +    this._atomics = { $set: val };
      +    this._markModified();
      +    return this;
      +  }
      +
      +  var atomics = this._atomics;
      +
      +  // reset pop/shift after save
      +  if ('$pop' == op && !('$pop' in atomics)) {
      +    var self = this;
      +    this._parent.once('save', function () {
      +      self._popped = self._shifted = null;
      +    });
      +  }
      +
      +  if (this._atomics.$set) {
      +    return this;
      +  }
      +
      +  // check for impossible $atomic combos (Mongo denies more than one
      +  // $atomic op on a single path
      +  if (Object.keys(atomics).length && !(op in atomics)) {
      +    // a different op was previously registered.
      +    // save the entire thing.
      +    this._atomics = { $set: this };
      +    this._markModified();
      +    return this;
      +  }
      +
      +  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
      +    atomics[op] || (atomics[op] = []);
      +    atomics[op] = atomics[op].concat(val);
      +  } else if (op === '$pullDocs') {
      +    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
      +      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
      +    selector['$in'] = selector['$in'].concat(val);
      +  } else {
      +    atomics[op] = val;
      +  }
      +
      +  this._markModified();
      +  return this;
      +};

      Parameters:


      MongooseArray#hasAtomics()

      Returns the number of pending atomic operations to send to the db for this array.

      show code
      MongooseArray.prototype.hasAtomics = function hasAtomics () {
      +  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
      +    return 0;
      +  }
      +
      +  return Object.keys(this._atomics).length;
      +}

      Returns:


      MongooseArray#push([args...])

      Wraps Array#push with proper change tracking.

      show code
      MongooseArray.prototype.push = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +
      +  // $pushAll might be fibbed (could be $push). But it makes it easier to
      +  // handle what could have been $push, $pushAll combos
      +  this._registerAtomic('$pushAll', values);
      +  return ret;
      +};

      Parameters:


      MongooseArray#nonAtomicPush([args...])

      Pushes items to the array non-atomically.

      show code
      MongooseArray.prototype.nonAtomicPush = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +};

      Parameters:

      • [args...] <any>

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$pop()

      Pops the array atomically at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var popped = doc.array.$pop();
      + console.log(popped); // 3
      + console.log(doc.array); // [1,2]
      +
      + // no affect
      + popped = doc.array.$pop();
      + console.log(doc.array); // [1,2]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $pop works again
      +   popped = doc.array.$pop();
      +   console.log(popped); // 2
      +   console.log(doc.array); // [1]
      + })

      MongooseArray#pop()

      Wraps Array#pop with proper change tracking.

      show code
      MongooseArray.prototype.pop = function () {
      +  var ret = [].pop.call(this);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +};

      Note:

      + +

      marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$shift()

      Atomically shifts the array at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var shifted = doc.array.$shift();
      + console.log(shifted); // 1
      + console.log(doc.array); // [2,3]
      +
      + // no affect
      + shifted = doc.array.$shift();
      + console.log(doc.array); // [2,3]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $shift works again
      +   shifted = doc.array.$shift();
      +   console.log(shifted ); // 2
      +   console.log(doc.array); // [3]
      + })

      MongooseArray#shift()

      Wraps Array#shift with proper change tracking.

      show code
      MongooseArray.prototype.shift = function () {
      +  var ret = [].shift.call(this);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +};

      Example:

      + +
      doc.array = [2,3];
      +var res = doc.array.shift();
      +console.log(res) // 2
      +console.log(doc.array) // [3]
      + +

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#remove([args...])

      Removes items from an array atomically

      show code
      MongooseArray.prototype.remove = function () {
      +  var args = [].map.call(arguments, this._cast, this);
      +  if (args.length == 1)
      +    this.pull(args[0]);
      +  else
      +    this.pull.apply(this, args);
      +  return args;
      +};

      Parameters:

      • [args...] <Object> values to remove

      Examples:

      + +
      doc.array.remove(ObjectId)
      +doc.array.remove('tag 1', 'tag 2')

      MongooseArray#pull([args...])

      Pulls items from the array atomically.

      show code
      MongooseArray.prototype.pull = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , cur = this._parent.get(this._path)
      +    , i = cur.length
      +    , mem;
      +
      +  while (i--) {
      +    mem = cur[i];
      +    if (mem instanceof EmbeddedDocument) {
      +      if (values.some(function (v) { return v.equals(mem); } )) {
      +        [].splice.call(cur, i, 1);
      +      }
      +    } else if (~cur.indexOf.call(values, mem)) {
      +      [].splice.call(cur, i, 1);
      +    }
      +  }
      +
      +  if (values[0] instanceof EmbeddedDocument) {
      +    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
      +  } else {
      +    this._registerAtomic('$pullAll', values);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • [args...] <any>

      MongooseArray#splice()

      Wraps Array#splice with proper change tracking.

      show code
      MongooseArray.prototype.splice = function () {
      +  if (arguments.length) {
      +    var ret = [].splice.apply(this, arguments);
      +    this._registerAtomic('$set', this);
      +  }
      +  return ret;
      +};

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#unshift()

      Wraps Array#unshift with proper change tracking.

      show code
      MongooseArray.prototype.unshift = function () {
      +  var values = [].map.call(arguments, this._cast, this);
      +  [].unshift.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  return this.length;
      +};

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#sort()

      Wraps Array#sort with proper change tracking.

      show code
      MongooseArray.prototype.sort = function () {
      +  var ret = [].sort.apply(this, arguments);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +}

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#addToSet([args...])

      Adds values to the array if not already present.

      show code
      MongooseArray.prototype.addToSet = function addToSet () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , added = []
      +    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
      +             values[0] instanceof Date ? 'date' :
      +             '';
      +
      +  values.forEach(function (v) {
      +    var found;
      +    switch (type) {
      +      case 'doc':
      +        found = this.some(function(doc){ return doc.equals(v) });
      +        break;
      +      case 'date':
      +        var val = +v;
      +        found = this.some(function(d){ return +d === val });
      +        break;
      +      default:
      +        found = ~this.indexOf(v);
      +    }
      +
      +    if (!found) {
      +      [].push.call(this, v);
      +      this._registerAtomic('$addToSet', v);
      +      [].push.call(added, v);
      +    }
      +  }, this);
      +
      +  return added;
      +};

      Parameters:

      • [args...] <any>

      Returns:

      • <Array> the values that were added

      Example:

      + +
      console.log(doc.array) // [2,3,4]
      +var added = doc.array.addToSet(4,5);
      +console.log(doc.array) // [2,3,4,5]
      +console.log(added)     // [5]

      MongooseArray#toObject(options)

      Returns a native js Array.

      show code
      MongooseArray.prototype.toObject = function (options) {
      +  if (options && options.depopulate && this[0] instanceof Document) {
      +    return this.map(function (doc) {
      +      return doc._id;
      +    });
      +  }
      +
      +  // return this.slice()?
      +  return this.map(function (doc) {
      +    return doc;
      +  });
      +};

      Parameters:

      Returns:


      MongooseArray#inspect()

      Helper for console.log

      show code
      MongooseArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    return ' ' + doc;
      +  }) + ' ]';
      +};

      MongooseArray#indexOf(obj)

      Return the index of obj or -1 if not found.

      show code
      MongooseArray.prototype.indexOf = function indexOf (obj) {
      +  if (obj instanceof ObjectId) obj = obj.toString();
      +  for (var i = 0, len = this.length; i < len; ++i) {
      +    if (obj == this[i])
      +      return i;
      +  }
      +  return -1;
      +};

      Parameters:

      • obj <Object> the item to look for

      Returns:


      MongooseArray#_parent

      Parent owner document


      MongooseArray#_atomics

      Stores a queue of atomic operations to perform


    • types/buffer.js

      MongooseBuffer(value, encode, offset)

      Mongoose Buffer constructor.

      show code
      function MongooseBuffer (value, encode, offset) {
      +  var length = arguments.length;
      +  var val;
      +
      +  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
      +    val = 0;
      +  } else {
      +    val = value;
      +  }
      +
      +  var encoding;
      +  var path;
      +  var doc;
      +
      +  if (Array.isArray(encode)) {
      +    // internal casting
      +    path = encode[0];
      +    doc = encode[1];
      +  } else {
      +    encoding = encode;
      +  }
      +
      +  var buf = new Buffer(val, encoding, offset);
      +  buf.__proto__ = MongooseBuffer.prototype;
      +
      +  // make sure these internal props don't show up in Object.keys()
      +  Object.defineProperties(buf, {
      +      validators: { value: [] }
      +    , _path: { value: path }
      +    , _parent: { value: doc }
      +  });
      +
      +  if (doc && "string" === typeof path) {
      +    Object.defineProperty(buf, '_schema', {
      +        value: doc.schema.path(path)
      +    });
      +  }
      +
      +  return buf;
      +};

      Parameters:

      Inherits:

      Values always have to be passed to the constructor to initialize.


      MongooseBuffer#_markModified()

      Marks this buffer as modified.

      show code
      MongooseBuffer.prototype._markModified = function () {
      +  var parent = this._parent;
      +
      +  if (parent) {
      +    parent.markModified(this._path);
      +  }
      +  return this;
      +};

      MongooseBuffer#write()

      Writes the buffer.

      show code
      MongooseBuffer.prototype.write = function () {
      +  var written = Buffer.prototype.write.apply(this, arguments);
      +
      +  if (written > 0) {
      +    this._markModified();
      +  }
      +
      +  return written;
      +};

      MongooseBuffer#copy(target)

      Copies the buffer.

      show code
      MongooseBuffer.prototype.copy = function (target) {
      +  var ret = Buffer.prototype.copy.apply(this, arguments);
      +
      +  if (target instanceof MongooseBuffer) {
      +    target._markModified();
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Note:

      + +

      Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


      MongooseBuffer#toObject([subtype])

      Converts this buffer to its Binary type representation.

      show code
      MongooseBuffer.prototype.toObject = function (subtype) {
      +  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
      +  return new Binary(this, subtype);
      +};

      Parameters:

      • [subtype] <Hex>

      Returns:

      SubTypes:

      + +
        +
      • 0x00: Binary/Generic
      • +
      • 0x01: Function
      • +
      • 0x02: Binary (Deprecated, 0x00 is new default)
      • +
      • 0x03: UUID
      • +
      • 0x04: MD5
      • +
      • 0x80: User Defined
      • +

      MongooseBuffer#_parent

      Parent owner document


    • types/documentarray.js

      MongooseDocumentArray(values, path, doc)

      DocumentArray constructor

      show code
      function MongooseDocumentArray (values, path, doc) {
      +  var arr = [];
      +
      +  // Values always have to be passed to the constructor to initialize, since
      +  // otherwise MongooseArray#push will mark the array as modified to the parent.
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseDocumentArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +    doc.on('save', arr.notify('save'));
      +    doc.on('isNew', arr.notify('isNew'));
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:


      MongooseDocumentArray#_cast()

      Overrides MongooseArray#cast

      show code
      MongooseDocumentArray.prototype._cast = function (value) {
      +  var doc = new this._schema.casterConstructor(value, this);
      +  return doc;
      +};

      MongooseDocumentArray#id(id)

      Searches array items for the first document with a matching id.

      show code
      MongooseDocumentArray.prototype.id = function (id) {
      +  var casted
      +    , _id;
      +
      +  try {
      +    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
      +  } catch (e) {
      +    casted = null;
      +  }
      +
      +  for (var i = 0, l = this.length; i < l; i++) {
      +    _id = this[i].get('_id');
      +    if (!(_id instanceof ObjectId)) {
      +      if (String(id) == _id)
      +        return this[i];
      +    } else {
      +      if (casted == _id)
      +        return this[i];
      +    }
      +  }
      +
      +  return null;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var embeddedDoc = m.array.id(some_id);

      MongooseDocumentArray#toObject()

      Returns a native js Array of plain js objects

      show code
      MongooseDocumentArray.prototype.toObject = function () {
      +  return this.map(function (doc) {
      +    return doc && doc.toObject() || null;
      +  });
      +};

      Returns:

      NOTE:

      + +

      Each sub-document is converted to a plain object by calling its #toObject method.


      MongooseDocumentArray#inspect()

      Helper for console.log

      show code
      MongooseDocumentArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    if (doc) {
      +      return doc.inspect
      +        ? doc.inspect()
      +        : util.inspect(doc)
      +    }
      +    return 'null'
      +  }).join('
      +') + ']';
      +};

      MongooseDocumentArray#create(obj)

      Creates a subdocument casted to this schema.

      show code
      MongooseDocumentArray.prototype.create = function (obj) {
      +  return new this._schema.casterConstructor(obj);
      +}

      Parameters:

      • obj <Object> the value to cast to this arrays SubDocument schema

      This is the same subdocument constructor used for casting.


      MongooseDocumentArray#notify(event)

      Creates a fn that notifies all child docs of event.

      show code
      MongooseDocumentArray.prototype.notify = function notify (event) {
      +  var self = this;
      +  return function notify (val) {
      +    var i = self.length;
      +    while (i--) {
      +      self[i].emit(event, val);
      +    }
      +  }
      +}

      Parameters:

      Returns:


    • types/embedded.js

      EmbeddedDocument(obj, parentArr, skipId)

      EmbeddedDocument constructor.

      show code
      function EmbeddedDocument (obj, parentArr, skipId, fields) {
      +  if (parentArr) {
      +    this.__parentArray = parentArr;
      +    this.__parent = parentArr._parent;
      +  } else {
      +    this.__parentArray = undefined;
      +    this.__parent = undefined;
      +  }
      +
      +  Document.call(this, obj, fields, skipId);
      +
      +  var self = this;
      +  this.on('isNew', function (val) {
      +    self.isNew = val;
      +  });
      +};

      Parameters:

      Inherits:


      EmbeddedDocument#markModified(path)

      Marks the embedded doc modified.

      show code
      EmbeddedDocument.prototype.markModified = function (path) {
      +  if (!this.__parentArray) return;
      +
      +  this._activePaths.modify(path);
      +
      +  if (this.isNew) {
      +    // Mark the WHOLE parent array as modified
      +    // if this is a new document (i.e., we are initializing
      +    // a document),
      +    this.__parentArray._markModified();
      +  } else
      +    this.__parentArray._markModified(this, path);
      +};

      Parameters:

      • path <String> the path which changed

      Example:

      + +
      var doc = blogpost.comments.id(hexstring);
      +doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');

      EmbeddedDocument#save([fn])

      Used as a stub for hooks.js

      show code
      EmbeddedDocument.prototype.save = function(fn) {
      +  if (fn)
      +    fn(null);
      +  return this;
      +};

      Parameters:

      Returns:

      NOTE:

      + +

      This is a no-op. Does not actually save the doc to the db.


      EmbeddedDocument#remove([fn])

      Removes the subdocument from its parent array.

      show code
      EmbeddedDocument.prototype.remove = function (fn) {
      +  if (!this.__parentArray) return this;
      +
      +  var _id;
      +  if (!this.willRemove) {
      +    _id = this._doc._id;
      +    if (!_id) {
      +      throw new Error('For your own good, Mongoose does not know ' + 
      +                      'how to remove an EmbeddedDocument that has no _id');
      +    }
      +    this.__parentArray.pull({ _id: _id });
      +    this.willRemove = true;
      +  }
      +
      +  if (fn)
      +    fn(null);
      +
      +  return this;
      +};

      Parameters:


      EmbeddedDocument#update()

      Override #update method of parent documents.

      show code
      EmbeddedDocument.prototype.update = function () {
      +  throw new Error('The #update method is not available on EmbeddedDocuments');
      +}

      EmbeddedDocument#inspect()

      Helper for console.log

      show code
      EmbeddedDocument.prototype.inspect = function () {
      +  return inspect(this.toObject());
      +};

      EmbeddedDocument#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
      +  if (!this.__parent) return false;
      +  var index = this.__parentArray.indexOf(this);
      +  var parentPath = this.__parentArray._path;
      +  var fullPath = [parentPath, index, path].join('.');
      +  this.__parent.invalidate(fullPath, err);
      +  if (first)
      +    this._validationError = ownerDocument(this)._validationError;
      +  return true;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> error which states the reason `path` was invalid

      Returns:


      EmbeddedDocument#ownerDocument()

      Returns the top level document of this sub-document.

      show code
      EmbeddedDocument.prototype.ownerDocument = function () {
      +  return ownerDocument(this);
      +}

      Returns:


      EmbeddedDocument#parent()

      Returns this sub-documents parent document.

      show code
      EmbeddedDocument.prototype.parent = function () {
      +  return this.__parent;
      +}

      EmbeddedDocument#parentArray()

      Returns this sub-documents parent array.

      show code
      EmbeddedDocument.prototype.parentArray = function () {
      +  return this.__parentArray;
      +}

    • types/objectid.js

      ObjectId()

      ObjectId type constructor

      Example

      + +
      var id = new mongoose.Types.ObjectId;

      ObjectId.fromString(str)

      Creates an ObjectId from str

      show code
      ObjectId.fromString;

      Parameters:

      Returns:


      ObjectId.toString(oid)

      Converts oid to a string.

      show code
      ObjectId.toString;

      Parameters:

      Returns:


    • utils.js

      exports.toCollectionName(name)

      Produces a collection name from model name.

      show code
      exports.toCollectionName = function (name) {
      +  if ('system.profile' === name) return name;
      +  if ('system.indexes' === name) return name;
      +  return pluralize(name.toLowerCase());
      +};

      Parameters:

      Returns:


      exports.pluralization

      Pluralization rules.

      show code
      exports.pluralization = [
      +  [/(m)an$/gi, '$1en'],
      +  [/(pe)rson$/gi, '$1ople'],
      +  [/(child)$/gi, '$1ren'],
      +  [/^(ox)$/gi, '$1en'],
      +  [/(ax|test)is$/gi, '$1es'],
      +  [/(octop|vir)us$/gi, '$1i'],
      +  [/(alias|status)$/gi, '$1es'],
      +  [/(bu)s$/gi, '$1ses'],
      +  [/(buffal|tomat|potat)o$/gi, '$1oes'],
      +  [/([ti])um$/gi, '$1a'],
      +  [/sis$/gi, 'ses'],
      +  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
      +  [/(hive)$/gi, '$1s'],
      +  [/([^aeiouy]|qu)y$/gi, '$1ies'],
      +  [/(x|ch|ss|sh)$/gi, '$1es'],
      +  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
      +  [/([m|l])ouse$/gi, '$1ice'],
      +  [/(quiz)$/gi, '$1zes'],
      +  [/s$/gi, 's'],
      +  [/$/gi, 's']
      +];
      +var rules = exports.pluralization;

      These rules are applied while processing the argument to toCollectionName.


      exports.uncountables

      Uncountable words.

      show code
      exports.uncountables = [
      +  'advice',
      +  'energy',
      +  'excretion',
      +  'digestion',
      +  'cooperation',
      +  'health',
      +  'justice',
      +  'labour',
      +  'machinery',
      +  'equipment',
      +  'information',
      +  'pollution',
      +  'sewage',
      +  'paper',
      +  'money',
      +  'species',
      +  'series',
      +  'rain',
      +  'rice',
      +  'fish',
      +  'sheep',
      +  'moose',
      +  'deer',
      +  'news'
      +];
      +var uncountables = exports.uncountables;

      These words are applied while processing the argument to toCollectionName.


      exports.deepEqual(a, b)

      Determines if a and b are deep equal.

      show code
      exports.deepEqual = function deepEqual (a, b) {
      +  if (a === b) return true;
      +
      +  if (a instanceof Date && b instanceof Date)
      +    return a.getTime() === b.getTime();
      +
      +  if (a instanceof ObjectId && b instanceof ObjectId) {
      +    return a.toString() === b.toString();
      +  }
      +
      +  if (typeof a !== 'object' && typeof b !== 'object')
      +    return a == b;
      +
      +  if (a === null || b === null || a === undefined || b === undefined)
      +    return false
      +
      +  if (a.prototype !== b.prototype) return false;
      +
      +  // Handle MongooseNumbers
      +  if (a instanceof Number && b instanceof Number) {
      +    return a.valueOf() === b.valueOf();
      +  }
      +
      +  if (Buffer.isBuffer(a)) {
      +    if (!Buffer.isBuffer(b)) return false;
      +    if (a.length !== b.length) return false;
      +    for (var i = 0, len = a.length; i < len; ++i) {
      +      if (a[i] !== b[i]) return false;
      +    }
      +    return true;
      +  }
      +
      +  if (isMongooseObject(a)) a = a.toObject();
      +  if (isMongooseObject(b)) b = b.toObject();
      +
      +  try {
      +    var ka = Object.keys(a),
      +        kb = Object.keys(b),
      +        key, i;
      +  } catch (e) {//happens when one is a string literal and the other isn't
      +    return false;
      +  }
      +
      +  // having the same number of owned properties (keys incorporates
      +  // hasOwnProperty)
      +  if (ka.length != kb.length)
      +    return false;
      +
      +  //the same set of keys (although not necessarily the same order),
      +  ka.sort();
      +  kb.sort();
      +
      +  //~~~cheap key test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    if (ka[i] != kb[i])
      +      return false;
      +  }
      +
      +  //equivalent values for every corresponding key, and
      +  //~~~possibly expensive deep test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    key = ka[i];
      +    if (!deepEqual(a[key], b[key])) return false;
      +  }
      +
      +  return true;
      +};

      Parameters:

      • a <any> a value to compare to `b`
      • b <any> a value to compare to `a`

      Returns:

      Modified from node/lib/assert.js


      exports.clone(obj, options)

      Object clone with Mongoose natives support.

      show code
      exports.clone = function clone (obj, options) {
      +  if (obj === undefined || obj === null)
      +    return obj;
      +
      +  if (Array.isArray(obj))
      +    return cloneArray(obj, options);
      +
      +  if (isMongooseObject(obj)) {
      +    if (options && options.json && 'function' === typeof obj.toJSON) {
      +      return obj.toJSON(options);
      +    } else {
      +      return obj.toObject(options);
      +    }
      +  }
      +
      +  if ('Object' === obj.constructor.name)
      +    return cloneObject(obj, options);
      +
      +  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
      +    return new obj.constructor(+obj);
      +
      +  if ('RegExp' === obj.constructor.name)
      +    return new RegExp(obj.source);
      +
      +  if (obj instanceof ObjectId) {
      +    return new ObjectId(obj.id);
      +  }
      +
      +  if (obj.valueOf)
      +    return obj.valueOf();
      +};
      +var clone = exports.clone;

      Parameters:

      Returns:

      Creates a minimal data Object.
      It does not clone empty Arrays, empty Objects, and undefined values.
      This makes the data payload sent to MongoDB as minimal as possible.


      exports.options(defaults, options)

      Copies and merges options with defaults.

      show code
      exports.options = function (defaults, options) {
      +  var keys = Object.keys(defaults)
      +    , i = keys.length
      +    , k ;
      +
      +  options = options || {};
      +
      +  while (i--) {
      +    k = keys[i];
      +    if (!(k in options)) {
      +      options[k] = defaults[k];
      +    }
      +  }
      +
      +  return options;
      +};

      Parameters:

      Returns:


      exports.random()

      Generates a random string

      show code
      exports.random = function () {
      +  return Math.random().toString().substr(3);
      +};

      exports.merge(to, from)

      Merges from into to without overwriting existing properties.

      show code
      exports.merge = function merge (to, from) {
      +  var keys = Object.keys(from)
      +    , i = keys.length
      +    , key
      +
      +  while (i--) {
      +    key = keys[i];
      +    if ('undefined' === typeof to[key]) {
      +      to[key] = from[key];
      +    } else {
      +      merge(to[key], from[key]);
      +    }
      +  }
      +};

      Parameters:


      exports.args()

      A faster Array.prototype.slice.call(arguments) alternative

      show code
      exports.args = function (args, slice, sliceEnd) {
      +  var ret = [];
      +  var start = slice || 0;
      +  var end = 3 === arguments.length
      +    ? sliceEnd
      +    : args.length;
      +
      +  for (var i = start; i < end; ++i) {
      +    ret[i - start] = args[i];
      +  }
      +
      +  return ret;
      +}

      exports.tick(callback)

      process.nextTick helper.

      show code
      exports.tick = function tick (callback) {
      +  if ('function' !== typeof callback) return;
      +  return function () {
      +    try {
      +      callback.apply(this, arguments);
      +    } catch (err) {
      +      // only nextTick on err to get out of
      +      // the event loop and avoid state corruption.
      +      process.nextTick(function () {
      +        throw err;
      +      });
      +    }
      +  }
      +}

      Parameters:

      Wraps callback in a try/catch + nextTick.

      + +

      node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


      exports.isMongooseObject(v)

      Returns if v is a mongoose object that has a toObject() method we can use.

      show code
      exports.isMongooseObject = function (v) {
      +  Document || (Document = require('./document'));
      +  MongooseArray || (MongooseArray = require('./types').Array);
      +  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
      +
      +  return v instanceof Document ||
      +         v instanceof MongooseArray ||
      +         v instanceof MongooseBuffer
      +}
      +var isMongooseObject = exports.isMongooseObject;

      Parameters:

      This is for compatibility with libs like Date.js which do foolish things to Natives.


      exports.expires(object)

      Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

      show code
      exports.expires = function expires (object) {
      +  if (!(object && 'Object' == object.constructor.name)) return;
      +  if (!('expires' in object)) return;
      +
      +  var when;
      +  if ('string' != typeof object.expires) {
      +    when = object.expires;
      +  } else {
      +    when = Math.round(ms(object.expires) / 1000);
      +  }
      +  object.expiresAfterSeconds = when;
      +  delete object.expires;
      +}
      +
      +exports.readPref = function readPref (pref, tags) {
      +  if (Array.isArray(pref)) {
      +    tags = pref[1];
      +    pref = pref[0];
      +  }
      +
      +  switch (pref) {
      +    case 'p':
      +      pref = 'primary';
      +      break;
      +    case 'pp':
      +      pref = 'primaryPrefered';
      +      break;
      +    case 's':
      +      pref = 'secondary';
      +      break;
      +    case 'sp':
      +      pref = 'secondaryPrefered';
      +      break;
      +    case 'n':
      +      pref = 'nearest';
      +      break;
      +  }
      +
      +  return new ReadPref(pref, tags);
      +}

      Parameters:


    • virtualtype.js

      VirtualType()

      VirtualType constructor

      show code
      function VirtualType (options, name) {
      +  this.path = name;
      +  this.getters = [];
      +  this.setters = [];
      +  this.options = options || {};
      +}

      This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

      + +

      Example:

      + +
      var fullname = schema.virtual('fullname');
      +fullname instanceof mongoose.VirtualType // true

      VirtualType#get(fn)

      Defines a getter.

      show code
      VirtualType.prototype.get = function (fn) {
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.get(function () {
      +  return this.name.first + ' ' + this.name.last;
      +});

      VirtualType#set(fn)

      Defines a setter.

      show code
      VirtualType.prototype.set = function (fn) {
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.set(function (v) {
      +  var parts = v.split(' ');
      +  this.name.first = parts[0];
      +  this.name.last = parts[1];
      +});

      VirtualType#applyGetters(value, scope)

      Applies getters to value using optional scope.

      show code
      VirtualType.prototype.applyGetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.getters.length - 1; l >= 0; l--) {
      +    v = this.getters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all getters

      VirtualType#applySetters(value, scope)

      Applies setters to value using optional scope.

      show code
      VirtualType.prototype.applySetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.setters.length - 1; l >= 0; l--) {
      +    v = this.setters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all setters

    diff --git a/docs/3.1.x/docs/api.jade b/docs/3.1.x/docs/api.jade new file mode 100644 index 00000000000..6f9a2c07307 --- /dev/null +++ b/docs/3.1.x/docs/api.jade @@ -0,0 +1,508 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose API v#{package.version} + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + style. + body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; + } + a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; + } + a:hover { + opacity: 0.8; + } + #wrap { + } + h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; + } + pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; + } + code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Monaco; + } + pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; + } + h3 { + padding: 20px 15px; + margin-left: -15px; + } + h3 code { + font-weight: normal; + } + hr { + height: 1px; + border: 0 none; + padding: 0; + margin: 60px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) + } + .doclinks hr { + margin: 10px 0; + } + li { + list-style: square; + } + #header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; + } + #header h1 { + margin-top: 0; + margin-bottom: 0; + } + #header h1 a { + text-decoration: none; + } + #header .mongoose { + font-size: 50px; + font-weight: 100; + color: #fff; + text-shadow: 6px 4px 5px #777, -2px 0px 2px white; + letter-spacing: -7px; + } + #links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + } + #links hr { + margin: 32px 0; + } + #content { + padding: 0; + margin: 0 0 30px 230px; + overflow-x: hidden; + } + #content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; + } + #content .controls:hover { + opacity: .9; + } + #content p { + word-wrap: break-word; + } + #content > ul { + margin: 0; + padding: 0; + } + .private { + display: none; + } + .section { + font-size: 15px; + } + .doclinks li.private a:before, + .doclinks .module.private a:before, + .doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; + } + #content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; + } + .module { + list-style: none; + padding: 30px 0 30px 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; + } + .module > * { + max-width: 700px; + } + .item:last-child { + margin-bottom: 90px; + } + .item:last-child > hr { + display: none; + } + .item h3 a { + color: #333; + text-decoration: none; + } + .property h3 span { + color: #444; + } + .description { + margin-top: 25px; + } + .sourcecode { + display: none; + } + .showcode { + font-size: 12px; + cursor: pointer; + display: none; + } + .load .showcode { + display: block; + } + .types a { + text-decoration: none; + } + @media only screen and (device-width: 768px) { + + } + @media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links hr { + display: none; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + .controls { display: none; } + } + body.api + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + hr + .doclinks + each item in docs + .file(class=item.hasPublic ? '' : 'private') + a.section(href='#' + item.title.replace(/[\.\/#]/g, '-'))= item.title + ul + each method in item.methods + if method.ctx && !method.ignore + li(class= method.isPrivate ? 'private' : '') + case method.ctx.type + when 'method' + id = method.ctx.constructor + '-' + method.ctx.name + when 'function' + id = method.ctx.name + default + id = '' + url = href(klass(item.title) + '_' + id) + a(href='#' + url)= method.ctx.name + each stat in item.statics + if stat.ctx && !stat.ignore + li(class= stat.isPrivate ? 'private' : '') + case stat.ctx.type + when 'method' + id = stat.ctx.receiver + '-' + stat.ctx.name + when 'property' + id = stat.ctx.receiver + '-' + stat.ctx.name + when 'function' + id = stat.ctx.name + url = href(klass(item.title) + '_' + id) + a(href='#' + url)= stat.ctx.name + each property in item.props + if property.ctx && !property.ignore + li(class= property.isPrivate ? 'private' : '') + construct = property.ctx.receiver || property.ctx.constructor + link = href(construct) + '-' + href(property.ctx.name) + url = href(klass(item.title) + '_' + link) + a(href='#' + url)= property.ctx.name + #content + .controls + label + input(type='checkbox') + | private + ul + each item in docs + li.module(class=item.hasPublic ? '' : 'private') + a(href=github + package.version + '/' + item.title, id=item.title.replace(/[\.\/#]/g, '-'))= item.title + each method in item.methods + div.item.method(class= method.isPrivate ? 'private' : 'public') + if method.ctx + case method.ctx.type + when 'method' + id = method.ctx.constructor + '-' + method.ctx.name + text = method.ctx.constructor + '#' + method.ctx.name + when 'function' + id = method.ctx.name + text = method.ctx.name + default + text = '' + url = href(klass(item.title) + '_' + text) + h3(id= url) + a(href= '#' + url) + = text + | ( + each tag, i in method.params + code= tag.name + if i+1 < method.params.length + | , + | ) + else + - // console.log('\nmissing method name', method); + h3 MISSING method name + != method.description.summary + if method.code + span.showcode show code + .sourcecode + != hl(method.code) + if method.params.length + .params + h4 Parameters: + ul + each tag in method.params + li + code= tag.name + if tag.types && tag.types.length + span.types + | < + each type, i in tag.types + != linktype(type) + if i+1 < tag.types.length + | , + | > + span= tag.description + if method.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in method.return.types + != linktype(type) + if i+1 < method.return.types.length + | , + | > + span= method.return.description + if method.inherits + .inherits + h4 Inherits: + ul + li + != method.inherits + if method.events && method.events.length + .events + h4 Events: + ul + each event in method.events + li + != event.string + if method.see.length + .see + h4 See: + ul.see + each see in method.see + li + url = see.url || see.local + a(href=url, title=see.title || see.local)= see.title || see.url || see.local + div.description + != method.description.body + hr(class= method.isPrivate ? 'private' : '') + each stat in item.statics + div.item.static(class= stat.isPrivate ? 'private' : 'public') + if stat.ctx + case stat.ctx.type + when 'method' + id = stat.ctx.receiver + '-' + stat.ctx.name + text = stat.ctx.receiver + '.' + stat.ctx.name + when 'property' + id = stat.ctx.receiver + '-' + stat.ctx.name + text = stat.ctx.receiver + '.' + stat.ctx.name + when 'function' + id = stat.ctx.name + text = stat.ctx.name + default + text = '' + url = href(klass(item.title) + '_' + id) + h3(id= url) + a(href= '#' + url) + = text + if 'property' != stat.ctx.type + | ( + each tag, i in stat.params + code= tag.name + if i+1 < stat.params.length + | , + | ) + else + - // console.log('\nmissing static name', stat); + h3 MISSING stat name + != stat.description.summary + if stat.code + span.showcode show code + .sourcecode + != hl(stat.code) + if stat.params.length + .params + h4 Parameters: + ul + each tag in stat.params + li + - if (!tag.name) + - // console.log(tag) + code= tag.name + if tag.types && tag.types.length + span.types + | < + each type, i in tag.types + != linktype(type) + if i+1 < tag.types.length + | , + | > + span= tag.description + if stat.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in stat.return.types + != linktype(type) + if i+1 < stat.return.types.length + | , + | > + span= stat.return.description + if stat.inherits + .inherits + h4 Inherits: + ul + li + != stat.inherits + if stat.see.length + .see + h4 See: + ul.see + each see in stat.see + li + url = see.url || see.local + a(href=url, title=see.title || see.local)= see.title || see.url || see.local + != stat.description.body + hr(class= stat.isPrivate ? 'private' : '') + each property in item.props + div.item.property(class= property.ignore || property.isPrivate ? 'private' : 'public') + construct = property.ctx.receiver || property.ctx.constructor + link = href(construct) + '-' + href(property.ctx.name) + url = href(klass(item.title) + '_' + link) + h3(id = url) + a(href= '#' + url) + = construct + '#' + span= property.ctx.name + != property.description.full + if property.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in property.return.types + != linktype(type) + if i+1 < property.return.types.length + | , + | > + span= property.return.description + hr(class= property.isPrivate ? 'private' : '') + script. + document.body.className = 'load'; + include includes/keen + script(src="/docs/js/zepto.min.js") + script. + $(".module").on("click", ".showcode", function (e) { + $(this).closest(".item").find(".sourcecode").first().toggle(); + }); + $("#content .controls input").on("click", function (e) { + $(".private").toggle() + }) diff --git a/docs/3.1.x/docs/contributing.html b/docs/3.1.x/docs/contributing.html new file mode 100644 index 00000000000..0cf42a44ec6 --- /dev/null +++ b/docs/3.1.x/docs/contributing.html @@ -0,0 +1,11 @@ +Mongoose Contributing v3.1.2Fork me on GitHub

    Contributing

    Bugfixes

    • Before starting to write code, look for existing tickets or create one for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch.
    • Fork the repo or for small documentation changes, navigate to the source on github and click the Edit button.
    • Write inline documentation for new methods or class members.
    • Write tests and make sure they pass (execute make test from the cmd line to run the test suite).
    • Follow the general coding style of the rest of the project (comma first, etc).

    Documentation

    To contribute to the API documentation just make your changes to the inline documentation of the appropriate source code in the master branch and submit a pull request. You might also use the github Edit button.

    + +

    To contribute to the guide or quick start docs, make your changes to the appropriate .jade files in the docs directory of the master branch and submit a pull request. Again, the Edit button might work for you here.

    Plugins

    The plugins site is also an open source project that you can get involved with. Feel free to fork and improve it as well!

    diff --git a/docs/3.1.x/docs/contributing.jade b/docs/3.1.x/docs/contributing.jade new file mode 100644 index 00000000000..eb6cc091510 --- /dev/null +++ b/docs/3.1.x/docs/contributing.jade @@ -0,0 +1,22 @@ +extends layout + +block content + h2 Contributing + + h3 Bugfixes + :markdown + - Before starting to write code, look for existing [tickets](https://github.com/learnboost/mongoose/issues) or [create one](https://github.com/learnboost/mongoose/issues/new) for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. + - Fork the [repo](https://github.com/learnboost/mongoose) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. + - Write inline documentation for new methods or class members. + - Write tests and make sure they pass (execute `make test` from the cmd line to run the test suite). + - Follow the general coding style of the rest of the project (comma first, etc). + + h3 Documentation + :markdown + To contribute to the [API documentation](./api.html) just make your changes to the inline documentation of the appropriate [source code](https://github.com/LearnBoost/mongoose/tree/master/lib) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. + + To contribute to the [guide](./guide.html) or [quick start](./index.html) docs, make your changes to the appropriate `.jade` files in the [docs](https://github.com/LearnBoost/mongoose/tree/master/docs) directory of the master branch and submit a pull request. Again, the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button might work for you here. + + h3 Plugins + :markdown + The [plugins](http://plugins.mongoosejs.com/) site is also an [open source project](https://github.com/aheckmann/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! diff --git a/docs/3.1.x/docs/css/default.css b/docs/3.1.x/docs/css/default.css new file mode 100644 index 00000000000..ccb22728ed3 --- /dev/null +++ b/docs/3.1.x/docs/css/default.css @@ -0,0 +1,135 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +pre code { + display: block; padding: 0.5em; + background: #F0F0F0; +} + +pre code, +pre .ruby .subst, +pre .tag .title, +pre .lisp .title, +pre .clojure .built_in, +pre .nginx .title { + color: black; +} + +pre .string, +pre .title, +pre .constant, +pre .parent, +pre .tag .value, +pre .rules .value, +pre .rules .value .number, +pre .preprocessor, +pre .ruby .symbol, +pre .ruby .symbol .string, +pre .ruby .symbol .keyword, +pre .ruby .symbol .keymethods, +pre .instancevar, +pre .aggregate, +pre .template_tag, +pre .django .variable, +pre .smalltalk .class, +pre .addition, +pre .flow, +pre .stream, +pre .bash .variable, +pre .apache .tag, +pre .apache .cbracket, +pre .tex .command, +pre .tex .special, +pre .erlang_repl .function_or_atom, +pre .markdown .header { + color: #800; +} + +pre .comment, +pre .annotation, +pre .template_comment, +pre .diff .header, +pre .chunk, +pre .markdown .blockquote { + color: #888; +} + +pre .number, +pre .date, +pre .regexp, +pre .literal, +pre .smalltalk .symbol, +pre .smalltalk .char, +pre .go .constant, +pre .change, +pre .markdown .bullet, +pre .markdown .link_url { + color: #080; +} + +pre .label, +pre .javadoc, +pre .ruby .string, +pre .decorator, +pre .filter .argument, +pre .localvars, +pre .array, +pre .attr_selector, +pre .important, +pre .pseudo, +pre .pi, +pre .doctype, +pre .deletion, +pre .envvar, +pre .shebang, +pre .apache .sqbracket, +pre .nginx .built_in, +pre .tex .formula, +pre .erlang_repl .reserved, +pre .input_number, +pre .markdown .link_label, +pre .vhdl .attribute, +pre .clojure .attribute { + color: #88F +} + +pre .keyword, +pre .id, +pre .phpdoc, +pre .title, +pre .built_in, +pre .aggregate, +pre .css .tag, +pre .javadoctag, +pre .phpdoc, +pre .yardoctag, +pre .smalltalk .class, +pre .winutils, +pre .bash .variable, +pre .apache .tag, +pre .go .typename, +pre .tex .command, +pre .markdown .strong, +pre .request, +pre .status { + font-weight: bold; +} + +pre .markdown .emphasis { + font-style: italic; +} + +pre .nginx .built_in { + font-weight: normal; +} + +pre .coffeescript .javascript, +pre .xml .css, +pre .xml .javascript, +pre .xml .vbscript, +pre .tex .formula { + opacity: 0.5; +} diff --git a/docs/3.1.x/docs/css/guide.css b/docs/3.1.x/docs/css/guide.css new file mode 100644 index 00000000000..51a5046fc24 --- /dev/null +++ b/docs/3.1.x/docs/css/guide.css @@ -0,0 +1,283 @@ +html, body, #content { + height: 100%; +} +.module { + min-height: 100%; + box-sizing: border-box; +} +body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; +} +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; +} +code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Monaco; + /*text-shadow: 1px 2px 2px #555;*/ +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +h2 { + margin-top: 0; +} +h3 { padding-top: 35px; } +h3 code { + font-weight: normal; +} +hr { + display: none; + height: 1px; + border: 0 none; + padding: 0; + margin: 90px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) +} +.doclinks hr { + margin: 10px 0; +} +li { + list-style: square; +} +#header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +#header .mongoose { + font-size: 50px; + font-weight: 100; + color: #fff; + text-shadow: 6px 4px 5px #777, -2px 0px 2px white; + letter-spacing: -7px; +} +#links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; +} +#links .schematypes span { + display: none; +} +#content { + padding: 0; + margin: 0 0 0 230px; + overflow-x: hidden; +} +#content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +#content .controls:hover { + opacity: .9; +} +#content p { + word-wrap: break-word; +} +#content > ul { + margin: 0; + padding: 0; +} +.private { + display: none; +} +.doclinks li.private a:before, +.doclinks .module.private a:before, +.doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; +} +#content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; +} +.module { + list-style: none; + padding: 30px 0 0 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; +} +.module > * { + max-width: 700px; +} +.item { + margin-bottom: 175px; +} +.item h3 a { + color: #333; + text-decoration: none; +} +.property h3 span { + color: #444; +} +.description { + margin-top: 25px; +} +.sourcecode { + display: none; +} +.showcode { + font-size: 12px; + cursor: pointer; + display: none; +} +.load .showcode { + display: block; +} +.types a { + text-decoration: none; +} +li.guide ul { + padding-left: 16px; +} + +@media only screen and (device-width: 768px) { + +} +@media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + html, body, #content { + height: auto; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + #links li.guide { + display: block; + width: 390px; + margin-bottom: 15px; + } + #links li.guide > a { + display: none; + } + #links li ul li { + width: 44%; + text-align: left; + } + #links li ul li ul li { + width: 95%; + } + #links .plugins, + #links .changelog { + display: none; + } + #links .schematypes span { + display: inline; + } + #links .double { + width: 332px; + } + #links .double > ul { + display: inline; + float: right; + } + #links .double > ul li { + width: 155px; + } +} diff --git a/docs/3.1.x/docs/documents.html b/docs/3.1.x/docs/documents.html new file mode 100644 index 00000000000..e2f6ef40cbd --- /dev/null +++ b/docs/3.1.x/docs/documents.html @@ -0,0 +1,20 @@ +Mongoose Documents v3.1.2Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    +  if (err) return handleError(err);
    +  
    +  tank.size = 'large';
    +  tank.save(function (err) {
    +    if (err) return handleError(err);
    +    res.send(tank);
    +  });
    +});

    This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    +  if (err) return handleError(err);
    +  res.send(tank);
    +});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    diff --git a/docs/3.1.x/docs/documents.jade b/docs/3.1.x/docs/documents.jade new file mode 100644 index 00000000000..67134e821b3 --- /dev/null +++ b/docs/3.1.x/docs/documents.jade @@ -0,0 +1,42 @@ +extends layout + +block content + h2 Documents + :markdown + Mongoose [documents](./api.html#document-js) represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its [Model](./models.html). + h3 Retrieving + :markdown + There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on [querying](./queries.html) for detail. + h3 Updating + :markdown + There are a number of ways to update documents. We'll first look at a traditional approach using [findById](./api.html#model_Model-findById): + :js + Tank.findById(id, function (err, tank) { + if (err) return handleError(err); + + tank.size = 'large'; + tank.save(function (err) { + if (err) return handleError(err); + res.send(tank); + }); + }); + :markdown + This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model-update) is right for us: + :js + Tank.update({ _id: id }, { $set: { size: 'large' }}, callback); + :markdown + If we do need the document returned in our application there is another, often [better](./api.html#model_Model-findByIdAndUpdate), option: + :js + Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) { + if (err) return handleError(err); + res.send(tank); + }); + :markdown + The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model-findByIdAndRemove) [several](./api.html#model_Model-findOneAndUpdate) [variations](./api.html#model_Model-findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. + h3 Validating + :markdown + Documents are validated before they are saved. Read the [api](./api.html#document_Document-validate) docs or the [validation](./validation.html) chapter for detail. + + h3#next Next Up + :markdown + Now that we've covered `Documents`, let's take a look at [Sub-documents](/docs/subdocs.html). diff --git a/docs/3.1.x/docs/faq.html b/docs/3.1.x/docs/faq.html new file mode 100644 index 00000000000..5d97705475c --- /dev/null +++ b/docs/3.1.x/docs/faq.html @@ -0,0 +1,31 @@ +Mongoose FAQ v3.1.2Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    +doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    +doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    +new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    +doc.user.remove();// ?
    +doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    + +

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    + +

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    +mongoose.connect(..);
    +mongoose.connection.on('error', handleError);
    +
    +// if connecting on a separate connection
    +var conn = mongoose.createConnection(..);
    +conn.on('error', handleError);
    +

    Something to add?

    + +

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    diff --git a/docs/3.1.x/docs/faq.jade b/docs/3.1.x/docs/faq.jade new file mode 100644 index 00000000000..07abc7ea928 --- /dev/null +++ b/docs/3.1.x/docs/faq.jade @@ -0,0 +1,63 @@ +extends layout + +block append style + style. + hr { + display: block; + margin: 30px 0; + } + +block content + h2 FAQ + :markdown + **Q**. Why don't my changes to arrays get saved when I update an element directly? + :js + doc.array[3] = 'changed'; + doc.save(); + :markdown + **A**. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving. + :js + doc.markModified('array'); + doc.save(); + hr + :markdown + **Q**. Why doesn't mongoose allow me to directly assign schemas to paths? + :js + var userSchema = new Schema({ name: String }); + new Schema({ user: userSchema }) + :markdown + **A**. Schemas have a one-to-one mapping with documents. Documents have `save` and `remove` methods along with their own `pre` and `post` hooks which would lead to code like the following: + :js + doc.user.save(); // ? + doc.user.remove();// ? + doc.save() + :markdown + We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling `save` on a sub-document is a no-op and exists only to support `pre` save hooks). In the future this is likely to be revisited. + hr + :markdown + **Q**. How can I enable debugging? + + **A**. Set the `debug` option to `true`: + :js + mongoose.set('debug', true) + hr + :markdown + **Q**. My `save()` callback never executes. What am I doing wrong? + + **A**. All `collection` actions (insert, remove, queries, etc) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. + :js + // if connecting on the default mongoose connection + mongoose.connect(..); + mongoose.connection.on('error', handleError); + + // if connecting on a separate connection + var conn = mongoose.createConnection(..); + conn.on('error', handleError); + + hr + :markdown + **Something to add?** + + If you'd like to contribute to this page, please [visit it](https://github.com/learnboost/mongoose/tree/master/docs/faq.jade) on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request. + br + diff --git a/docs/3.1.x/docs/guide.html b/docs/3.1.x/docs/guide.html new file mode 100644 index 00000000000..a0e25e89e90 --- /dev/null +++ b/docs/3.1.x/docs/guide.html @@ -0,0 +1,170 @@ +Mongoose Schemas v3.1.2Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

    If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    +  title:  String,
    +  author: String,
    +  body:   String,
    +  comments: [{ body: String, date: Date }],
    +  date: { type: Date, default: Date.now },
    +  hidden: Boolean,
    +  meta: {
    +    votes: Number,
    +    favs:  Number
    +  }
    +})

    If you want to add additional keys later, use the Schema#add method.

    +Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. +Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    +
    +animalSchema.methods.findSimilarTypes = function (cb) {
    +  return this.model('Animal').find({ type: this.type }, cb);
    +}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    +var dog = new Animal({ type: 'dog' })
    +
    +dog.findSimilarTypes(function (err, dogs) {
    +  console.log(dogs) // woof
    +})

    Statics

    +Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    +  this.find({ name: new RegExp(name, 'i'), cb);
    +}
    +
    +var Animal = mongoose.model('Animal', animalSchema);
    +Animal.findByName('fido', function (err, animals) {
    +  console.log(animals);
    +})

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index. This behavior can be disabled by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false)
    +// or
    +new Schema({..}, { autoIndex: false })

    See also the Model#ensureIndexes method.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    +  name: {
    +    first: String,
    +    last: String
    +  }
    +});
    +
    +var Person = mongoose.model('Person', personSchema);
    +
    +var bad = new Person({
    +    name: { first: 'Walter', last: 'White' }
    +});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    +  return this.name.first + ' ' + this.name.last;
    +})

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full) // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    +  var split = name.split(' ');
    +  this.name.first = split[0];
    +  this.name.last = split[1];
    +})
    +
    +...
    +
    +mad.name.full = 'Breaking Bad';
    +console.log(mad.name.first) // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    +
    +// or
    +
    +var schema = new Schema({..});
    +schema.set(option, value);
    +

    Valid options:

    + +

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false })
    +var Clock = db.model('Clock', schema);
    +Clock.ensureIndexes(callback);
    +

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 })

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true })
    +

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // '50341373e894ad16347efe01'
    +
    +// disabled id
    +var schema = new Schema({ name: String }, { id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // undefined
    +

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    + +

    Pass this option during schema construction to prevent documents from getting an auto _id created.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
    +
    +// disabled _id
    +var schema = new Schema({ name: String }, { _id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { name: 'mongodb.org' }
    +

    option: read

    Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

    var schema = new Schema({..}, { read: 'primary' })            // also aliased as 'p'
    +var schema = new Schema({..}, { read: 'primaryPreferred' })   // aliased as 'pp'
    +var schema = new Schema({..}, { read: 'secondary' })          // aliased as 's'
    +var schema = new Schema({..}, { read: 'secondaryPreferred' }) // aliased as 'sp'
    +var schema = new Schema({..}, { read: 'nearest' })            // aliased as 'n'
    +

    The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'pp'.

    + +

    The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

    + +

    NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

    // pings the replset members periodically to track network latency
    +// now `nearest` works as intended
    +var options = { replset: { strategy: 'ping' }};
    +mongoose.connect(uri, options);
    +
    +var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
    +mongoose.model('JellyBean', schema);
    +

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    +new Schema({ .. }, { safe: safe })
    +

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. +By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    + +

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
    +new Schema({ .. }, { safe: safe })
    +

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    +

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: strict

    The strict option, (enabled by default), ensures that values added to our model instance that were not specified in our schema do not get saved to the db. +NOTE: do not set to false unless you have good reason.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save() // iAmNotInTheSchema is not saved to the db
    +
    +// set to false..
    +var thingSchema = new Schema({..}, { strict: false });
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save() // iAmNotInTheSchema is now saved to the db!!
    +

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = db.model('Thing');
    +var thing = new Thing(doc, true);  // enables strict mode
    +var thing = new Thing(doc, false); // disables strict mode
    +

    The strict option may also be set to "throw" which will cause errors to be produced instead of ignoring the bad data.

    NOTE: in mongoose v2 the default was false.

    option: toJSON

    Exactly the same as the toObject option but only applies when the documents toJSON method is called.

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toJSON', { getters: true });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
    +console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +// since we know toJSON is called whenever a js object is stringified:
    +console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
    +

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toObject', { getters: true });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { __v: 0, name: 'mongoose v3' }
    +
    +// customized versionKey
    +new Schema({..}, { versionKey: '_somethingElse' })
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    +

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false })
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'no versioning please' });
    +thing.save(); // { name: 'no versioning please' }
    +
    +

    Next Up

    Now that we've covered Schemas, let's take a look at SchemaTypes.

    diff --git a/docs/3.1.x/docs/guide.jade b/docs/3.1.x/docs/guide.jade new file mode 100644 index 00000000000..e610365aa98 --- /dev/null +++ b/docs/3.1.x/docs/guide.jade @@ -0,0 +1,428 @@ +extends layout + +block content + h2 Schemas + :markdown + If you haven't yet done so, please take a minute to read the [quickstart](./index.html) to get an idea of how Mongoose works. + :markdown + If you are migrating from 2.x to 3.x please take a moment to read the [migration guide](./migration.html). + :markdown + This page covers `Schema` [definition](#definition), [plugins](#plugins), instance [methods](#methods), [statics](#statics), [indexes](#indexes), [virtuals](#virtuals) and [options](#options). Let's start with `Schema` definition. + h3#definition Defining your schema + p + | Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection. + :js + var blogSchema = new Schema({ + title: String, + author: String, + body: String, + comments: [{ body: String, date: Date }], + date: { type: Date, default: Date.now }, + hidden: Boolean, + meta: { + votes: Number, + favs: Number + } + }) + p + em + | If you want to add additional keys later, use the + a(href="./api.html#schema_Schema-add") Schema#add + | method. + p + | Each key in our + code blogSchema + | defines a property in our documents which will be cast to its associated + a(href="./api.html#schematype_SchemaType") SchemaType + |. For example, we've defined a + code title + | which will be cast to the + a(href="./api.html#schema-string-js") String + | SchemaType and + code date + | which will be cast to a + code Date + | SchemaType. + | Keys may also be assigned nested objects containing further key/type definitions + em (e.g. the `meta` property above). + p + | The permitted SchemaTypes are + ul + li String + li Number + li Date + li Buffer + li Boolean + li Mixed + li ObjectId + li Array + | Read more about them + a(href="./schematypes.html") here + | . + p + | Schemas not only define the structure of your document and casting of properties, they also define document + a(href="#methods") instance methods + |, static + a(href="#statics") Model methods + |, + a(href="#indexes") compound indexes + | and document lifecycle hooks called + a(href="./middleware.html") middleware + |. + h3#plugins Pluggable + p + | Schemas are + a(href="./plugins.html") pluggable + | which allows us to package up reusable features into + a(href="http://plugins.mongoosejs.com") plugins + | that can be shared with the community or just between your projects. + h3#methods Instance methods + p + a(href="./models.html") Models + | are just fancy + code constructor + | functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are + a(href="./documents.html") documents + |. + p + | Defining an instance method is easy. + :js + var animalSchema = new Schema({ name: String, type: String }); + + animalSchema.methods.findSimilarTypes = function (cb) { + return this.model('Animal').find({ type: this.type }, cb); + } + p + | Now all of our + code animal + | instances have a + code findSimilarTypes + | method available to it. + :js + var Animal = mongoose.model('Animal', animalSchema); + var dog = new Animal({ type: 'dog' }) + + dog.findSimilarTypes(function (err, dogs) { + console.log(dogs) // woof + }) + h3#statics Statics + p + | Adding static constructor methods to Models is simple as well. Continuing with our + code animalSchema + |: + :js + animalSchema.statics.findByName = function (name, cb) { + this.find({ name: new RegExp(name, 'i'), cb); + } + + var Animal = mongoose.model('Animal', animalSchema); + Animal.findByName('fido', function (err, animals) { + console.log(animals); + }) + h3#indexes Indexes + p + a(href="http://www.mongodb.org/display/DOCS/Indexes") Indexes + | can be defined + a(href="./api.html#schematype_SchemaType-index") at + | + a(href="./api.html#schematype_SchemaType-unique") the + | + a(href="./api.html#schematype_SchemaType-sparse") path + | + a(href="./api.html#schematype_SchemaType-expires") level + | or the + code schema + | level. Defining indexes at the schema level is necessary when defining + a(href="http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys", target="_blank") compound indexes + |. + :js + animalSchema.index({ name: 1, type: -1 }); + p + | When your application starts up, Mongoose automatically calls + code ensureIndex + | for each defined index. This behavior can be disabled by setting the + code autoIndex + | option of your schema to false. + :js + animalSchema.set('autoIndex', false) + // or + new Schema({..}, { autoIndex: false }) + p + | See also the + a(href="./api.html#model_Model-ensureIndexes") + code Model#ensureIndexes + | method. + + h3#virtuals Virtuals + :markdown + [Virtual](./api.html#schema_Schema-virtual) attributes are attributes that are convenient to have around but that do not get persisted to MongoDB. + :js + var personSchema = new Schema({ + name: { + first: String, + last: String + } + }); + + var Person = mongoose.model('Person', personSchema); + + var bad = new Person({ + name: { first: 'Walter', last: 'White' } + }); + :markdown + Suppose we want to log the full name of `bad`. We could do this manually like so: + :js + console.log(bad.name.first + ' ' + bad.name.last); // Walter White + :markdown + Or we could add a `virtual` attribute [getter](./api.html#virtualtype_VirtualType-get) to our `personSchema` so we don't need to write out this string concatenation mess each time: + :js + personSchema.virtual('name.full').get(function () { + return this.name.first + ' ' + this.name.last; + }) + :markdown + Now, when we access our virtual full name property, our getter function will be invoked and the value returned: + :js + console.log('%s is insane', bad.name.full) // Walter White is insane + :markdown + It would also be nice to be able to set `this.name.first` and `this.name.last` by setting `this.name.full`. For example, if we wanted to change `bad`'s `name.first` and `name.last` to 'Breaking' and 'Bad' respectively, it'd be nice to just: + :js + bad.name.full = 'Breaking Bad'; + :markdown + Mongoose lets you do this as well through its virtual attribute [setters](./api.html#virtualtype_VirtualType-set): + :js + personSchema.virtual('name.full').set(function (name) { + var split = name.split(' '); + this.name.first = split[0]; + this.name.last = split[1]; + }) + + ... + + mad.name.full = 'Breaking Bad'; + console.log(mad.name.first) // Breaking + :markdown + If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you. + + h3#options Options + :markdown + `Schema`s have a few configurable options which can be passed to the constructor or `set` directly: + :js + new Schema({..}, options); + + // or + + var schema = new Schema({..}); + schema.set(option, value); + + :markdown + Valid options: + + - [autoIndex](#autoIndex) + - [capped](#capped) + - [id](#id) + - [_id](#_id) + - [read](#read) + - [safe](#safe) + - [shardKey](#shardKey) + - [strict](#strict) + - [toJSON](#toJSON) + - [toObject](#toObject) + - [versionKey](#versionKey) + + h4#autoIndex option: autoIndex + :markdown + At application startup, Mongoose sends an `ensureIndex` command for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model-ensureIndexes) method on your model. + :js + var schema = new Schema({..}, { autoIndex: false }) + var Clock = db.model('Clock', schema); + Clock.ensureIndexes(callback); + + h4#capped option: capped + :markdown + Mongoose supports MongoDBs [capped](http://www.mongodb.org/display/DOCS/Capped+Collections) collections. To specify the underlying MongoDB collection be `capped`, set the `capped` option to the maximum size of the collection in [bytes](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-size.). + :js + new Schema({..}, { capped: 1024 }) + :markdown + The `capped` option may also be set to an object if you want to pass additional options like [max](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-max) or [autoIndexId](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-autoIndexId). In this case you must explicitly pass the `size` option which is required. + :js + new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true }) + + h4#id option: id + :markdown + Mongoose assigns each of your schemas an `id` virtual getter by default which returns the documents `_id` field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an `id` getter added to your schema, you may disable it passing this option at schema construction time. + :js + // default behavior + var schema = new Schema({ name: String }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p.id); // '50341373e894ad16347efe01' + + // disabled id + var schema = new Schema({ name: String }, { id: false }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p.id); // undefined + + h4#_id option: _id + :markdown + Mongoose assigns each of your schemas an `_id` field by default if one is not passed into the [Schema](/docs/api.html#schema-js) constructor. The type assiged is an [ObjectId](/docs/api.html#schema_Schema-Types) to coincide with MongoDBs default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option. + + Pass this option during schema construction to prevent documents from getting an auto `_id` created. + :js + // default behavior + var schema = new Schema({ name: String }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' } + + // disabled _id + var schema = new Schema({ name: String }, { _id: false }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p); // { name: 'mongodb.org' } + + h4#read option: read + :markdown + Allows setting [query#read](/docs/api.html#query_Query-read) options at the schema level, providing us a way to apply default [ReadPreferences](http://docs.mongodb.org/manual/applications/replication/#replica-set-read-preference) to all queries derived from a model. + + :js + var schema = new Schema({..}, { read: 'primary' }) // also aliased as 'p' + var schema = new Schema({..}, { read: 'primaryPreferred' }) // aliased as 'pp' + var schema = new Schema({..}, { read: 'secondary' }) // aliased as 's' + var schema = new Schema({..}, { read: 'secondaryPreferred' }) // aliased as 'sp' + var schema = new Schema({..}, { read: 'nearest' }) // aliased as 'n' + + :markdown + The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'pp'. + + The read option also allows us to specify _tag sets_. These tell the [driver](https://github.com/mongodb/node-mongodb-native/) from which members of the replica-set it should attempt to read. Read more about tag sets [here](http://docs.mongodb.org/manual/applications/replication/#tag-sets) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences). + + _NOTE: if you specify the read pref 'nearest', you must also pass the [strategy](http://mongodb.github.com/node-mongodb-native/api-generated/replset.html?highlight=strategy) option when connecting or your reads will not behave predictably:_ + + :js + // pings the replset members periodically to track network latency + // now `nearest` works as intended + var options = { replset: { strategy: 'ping' }}; + mongoose.connect(uri, options); + + var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] }); + mongoose.model('JellyBean', schema); + + h4#safe option: safe + :markdown + This option is passed to MongoDB with all operations, and specifies if errors should be returned to our callbacks as well as tune write behavior. + + :js + var safe = true; + new Schema({ .. }, { safe: safe }) + + :markdown + By default this is set to `true` for all schemas which guarentees that any occurring error gets passed back to our callback. + By setting `safe` to something else like `{ j: 1, w: 2, wtimeout: 10000 }` we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback. + + There are other write concerns like `{ w: "majority" }` too. See the MongoDB [docs](http://www.mongodb.org/display/DOCS/getLastError+Command) for more details. + + :js + var safe = { w: "majority", wtimeout: 10000 }; + new Schema({ .. }, { safe: safe }) + + h4#shardKey option: shardKey + :markdown + The `shardKey` option is used when we have a [sharded MongoDB architecture](http://www.mongodb.org/display/DOCS/Sharding+Introduction). Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set. + + :js + new Schema({ .. }, { shardkey: { tag: 1, name: 1 }}) + + :markdown + _Note that Mongoose does not send the `shardcollection` command for you. You must configure your shards yourself._ + + h4#strict option: strict + :markdown + The strict option, (enabled by default), ensures that values added to our model instance that were not specified in our schema do not get saved to the db. + _NOTE: do not set to false unless you have good reason._ + + :js + var thingSchema = new Schema({..}) + var Thing = db.model('Thing', schemaSchema); + var thing = new Thing({ iAmNotInTheSchema: true }); + thing.save() // iAmNotInTheSchema is not saved to the db + + // set to false.. + var thingSchema = new Schema({..}, { strict: false }); + var thing = new Thing({ iAmNotInTheSchema: true }); + thing.save() // iAmNotInTheSchema is now saved to the db!! + + :markdown + This value can be overridden at the model instance level by passing a second boolean argument: + + :js + var Thing = db.model('Thing'); + var thing = new Thing(doc, true); // enables strict mode + var thing = new Thing(doc, false); // disables strict mode + + :markdown + The `strict` option may also be set to `"throw"` which will cause errors to be produced instead of ignoring the bad data. + + :markdown + _NOTE: in mongoose v2 the default was false._ + + h4#toJSON option: toJSON + :markdown + Exactly the same as the [toObject](#toObject) option but only applies when the documents `toJSON` method is called. + :js + var schema = new Schema({ name: String }); + schema.path('name').get(function (v) { + return v + ' is my name'; + }); + schema.set('toJSON', { getters: true }); + var M = mongoose.model('Person', schema); + var m = new M({ name: 'Max Headroom' }); + console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' } + console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } + // since we know toJSON is called whenever a js object is stringified: + console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" } + + h4#toObject option: toObject + :markdown + Documents have a [toObject](/docs/api.html#document_Document-toObject) method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default. + :js + var schema = new Schema({ name: String }); + schema.path('name').get(function (v) { + return v + ' is my name'; + }); + schema.set('toObject', { getters: true }); + var M = mongoose.model('Person', schema); + var m = new M({ name: 'Max Headroom' }); + console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } + + h4#versionKey option: versionKey + :markdown + The `versionKey` is a property set on each document when first created by Mongoose. This keys value contains the internal [revision](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning) of the document. The name of this document property is configurable. The default is `__v`. If this conflicts with your application you can configure as such: + :js + var schema = new Schema({ name: 'string' }); + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'mongoose v3' }); + thing.save(); // { __v: 0, name: 'mongoose v3' } + + // customized versionKey + new Schema({..}, { versionKey: '_somethingElse' }) + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'mongoose v3' }); + thing.save(); // { _somethingElse: 0, name: 'mongoose v3' } + + :markdown + Document versioning can also be disabled by setting the `versionKey` to false. _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning)._ + :js + new Schema({..}, { versionKey: false }) + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'no versioning please' }); + thing.save(); // { name: 'no versioning please' } + + + h3#next Next Up + :markdown + Now that we've covered `Schemas`, let's take a look at [SchemaTypes](/docs/schematypes.html). + +script. +document.body.className = 'load'; +include includes/keen diff --git a/docs/3.1.x/docs/helpers/filters.js b/docs/3.1.x/docs/helpers/filters.js new file mode 100644 index 00000000000..33546a7e805 --- /dev/null +++ b/docs/3.1.x/docs/helpers/filters.js @@ -0,0 +1,20 @@ + +var hl = require('highlight.js') + +module.exports = exports = function (jade) { + // add highlighting filter to jade + + jade.filters.js = function (str) { + str = str.replace(/\\n/g, '\n'); + var ret = hl.highlight('javascript', str).value; + var code = '
    ' + ret.replace(/\n/g, '\\n') + '
    '; + return code; + } + + jade.filters.bash = function (str) { + var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; + var code = '
    ' + ret + '
    '; + return code + } + +} diff --git a/docs/3.1.x/docs/helpers/highlight.js b/docs/3.1.x/docs/helpers/highlight.js new file mode 100644 index 00000000000..8aca9b9e222 --- /dev/null +++ b/docs/3.1.x/docs/helpers/highlight.js @@ -0,0 +1,11 @@ + +var h = require('highlight.js') + +function hl (str) { + str = str.replace(/\\n/g, '\n'); + var ret = h.highlight('javascript', str).value; + var code = '
    ' + ret+ '
    '; + return code; +} + +module.exports = hl; diff --git a/docs/3.1.x/docs/helpers/href.js b/docs/3.1.x/docs/helpers/href.js new file mode 100644 index 00000000000..e7299b1cf0d --- /dev/null +++ b/docs/3.1.x/docs/helpers/href.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str, char) { + if ('string' != typeof str) return str; + return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); +} diff --git a/docs/3.1.x/docs/helpers/klass.js b/docs/3.1.x/docs/helpers/klass.js new file mode 100644 index 00000000000..0c4a865b43b --- /dev/null +++ b/docs/3.1.x/docs/helpers/klass.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str) { + var parts = str.replace(/\.js$/, '').split('/'); + return parts.join('_'); +} diff --git a/docs/3.1.x/docs/helpers/linktype.js b/docs/3.1.x/docs/helpers/linktype.js new file mode 100644 index 00000000000..997e740f671 --- /dev/null +++ b/docs/3.1.x/docs/helpers/linktype.js @@ -0,0 +1,50 @@ + +var types = {}; +types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; +types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' +types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' +types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' +types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' +types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' +types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' +types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' +types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' +types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' + +// mongoose +types.ObjectId = '#types_objectid_ObjectId'; +types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; +types.MongooseArray = '#types_array_MongooseArray'; +types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; +types.Query = '#query-js'; +types.QueryStream = '#querystream_QueryStream'; +types.Document = '#document_Document'; +types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; +types.Document = '#document_Document'; +types.Model = '#model_Model'; +types.Connection = '#connection_Connection'; +types.Collection = '#collection_Collection'; +types.Schema = '#schema_Schema'; +types.Promise = '#promise_Promise'; +types.Mongoose = '#index_Mongoose'; +types.MongooseError = '#error_MongooseError'; +types.Type = '#schematype_SchemaType'; // ? +types.SchemaType = '#schematype_SchemaType'; +types.SchemaArray = '#schema_array_SchemaArray'; +types.Mixed = '#schema_mixed_Mixed'; +types.VirtualType = '#virtualtype_VirtualType'; +types.MongooseBuffer = '#types_buffer_MongooseBuffer'; +types.Buffer = 'http://nodejs.org/api/buffer.html'; + +module.exports= function (type) { + if (types[type]) { + return '' + type + ''; + } + return '' + type + ''; +} + +module.exports.types = types; +module.exports.type = function (str) { + if (types[str]) return types[str]; + return str; +} diff --git a/docs/3.1.x/docs/images/apps/grab b/docs/3.1.x/docs/images/apps/grab new file mode 100755 index 00000000000..ca314e9e858 --- /dev/null +++ b/docs/3.1.x/docs/images/apps/grab @@ -0,0 +1,39 @@ +#!/bin/bash + +#make sure firefox launches in the bottom right corner of the window + +# read URLs from a data file in a loop +#regex='([^[:space:]]+)[[:space:]]*(.*)' +regex='([^[:space:]]+)[|]([^|]+)[|](.*)' + +func() { + [[ $1 =~ $regex ]] + url=${BASH_REMATCH[1]} + # remove middle space, lowercase + name=`echo ${BASH_REMATCH[2]} | tr -d '[[:space:]]' | tr '[A-Z]' '[a-z]'` + desc=${BASH_REMATCH[3]} + + # send URL to the firefox session + # firefox --width 1030 --height 768 $url & + /Applications/Firefox.app/Contents/MacOS/firefox --width 1030 --height 768 $url & + echo started firefox with $url + echo preparing screencapture ... + + # take a picture after waiting a bit for the load to finish + sleep 6 + # gm import -window root -crop 1004x768+414+228 -resize 500x350 $name.png + screencapture -wo $name.png + gm convert $name.png -crop 1004x768+0+80 -resize 200x140 $name.png + echo grabbed screenshot $name.png +} + +if [ $1 ] +then + func "$1 $2" +else + while read line + do + func $line + done < urls +fi + diff --git a/docs/3.1.x/docs/images/apps/urls b/docs/3.1.x/docs/images/apps/urls new file mode 100644 index 00000000000..ca924705938 --- /dev/null +++ b/docs/3.1.x/docs/images/apps/urls @@ -0,0 +1,21 @@ +https://www.learnboost.com|LearnBoost|is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students. +http://storify.com/|Storify|lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative. +https://clickdummy.com|ClickDummy|is a rapid mockup prototyping application for designers and dummies. +http://scottyapp.com|Scotty App|allows you to create data driven backends for your apps in minutes instead of weeks. +http://geekli.st|Geeklist|is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found. +https://bozuko.com|Bozuko|is an exciting customer rewards program. +http://calllistapp.com|Call List|helps you maintain a todo list for people you need to call. +http://www.gtggolf.com|Grow The Game Golf|lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more. +http://nextdays.com/|nextdays|lets you share plans with friends and discover what is happening around you. +http://linkr.cc|Linkr|is a service for saving links for reading later. +http://www.attictv.com/|AtticTV|is Music Television (MTV) for the web. +https://localresponse.com|LocalResponse|helps marketers respond to real-time consumer intent. +http://selectvids.com|Select Vids|is a collection of amazing, funny, and creative videos for you to discover. +https://cldfy.com/|cldfy|delivers mail to your app. +http://www.sharelatex.com|ShareLatex|is a real-time LaTeX collaboration tool. +http://apps.newleafdigital.com/lists|Lists|is a service for saving links for reading later. +http://cyborgvisionapp.com/|Cyborg Vision|uses real-time facial recognition to identify your friends and show their information. +https://wavo.me/|Wavo|lets you express yourself through the songs you love. +http://seelio.com/|seelio|is a stage for college students to distinguish themselves and connect with companies. +http://todaylaunch.com/|TodayLaunch|is a free dashboard for your social media accounts. +http://st.achify.com/|Stachify| diff --git a/docs/3.1.x/docs/images/square_bg.png b/docs/3.1.x/docs/images/square_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca GIT binary patch literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.1.2Fork me on GitHub

    Getting Started

    First be sure you have MongoDB and Nodejs installed.

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. +The first thing we need to do is include mongoose in our project and open a connection.

    var mongoose = require('mongoose')
    +  , db = mongoose.createConnection('localhost', 'test');

    We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    db.on('error', console.error.bind(console, 'connection error:'));
    +db.once('open', function () {
    +  // yay!
    +});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = new mongoose.Schema({
    +    name: String
    +})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a model.

    var Kitten = db.model('Kitten', kittySchema)

    A model is a class with which we construct documents. +In this case, each document will be a kitten with properties and behaviors as declared in our schema. +Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    +console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    kittySchema.methods.speak = function () {
    +  var greeting = this.name
    +    ? 'Meow name is ' + this.name
    +    : 'I don't have a name'
    +  console.log(greeting);
    +}
    +
    +var Kitten = db.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    +fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. +Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err) {
    +  if (err) // TODO handle the error
    +  console.log('meow')
    +});

    Say time goes by and we want to display all the kittens we've seen. +We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    +  if (err) // TODO handle err
    +  console.log(kittens)
    +})

    We just logged all of the kittens in our db to the console. +If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax.

    Kitten.find({ name: /fluff/i }, callback)

    This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or api docs for more.

    diff --git a/docs/3.1.x/docs/index.jade b/docs/3.1.x/docs/index.jade new file mode 100644 index 00000000000..50388b02042 --- /dev/null +++ b/docs/3.1.x/docs/index.jade @@ -0,0 +1,119 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose Quick Start v#{package.version} + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + link(href='css/guide.css', rel='stylesheet', type='text/css') + style. + body.api + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + #content + .module + h2 Getting Started + p + em + | First be sure you have + a(href="http://www.mongodb.org/downloads") MongoDB + | and + a(href="http://nodejs.org/") Nodejs + | installed. + p + | Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. + | The first thing we need to do is include mongoose in our project and open a connection. + :js + var mongoose = require('mongoose') + , db = mongoose.createConnection('localhost', 'test'); + p We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs: + :js + db.on('error', console.error.bind(console, 'connection error:')); + db.once('open', function () { + // yay! + }); + p Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback. + p + | With Mongoose, everything is derived from a + a(href="./api.html#schema_Schema") Schema + | . Let's get a reference to it and define our kittens. + :js + var kittySchema = new mongoose.Schema({ + name: String + }) + p + | So far so good. We've got a schema with one property, + code name + | , which will be a + code String + | . The next step is compiling our schema into a + a(href="./api.html#model_Model") model + | . + :js + var Kitten = db.model('Kitten', kittySchema) + p + | A model is a class with which we construct documents. + | In this case, each document will be a kitten with properties and behaviors as declared in our schema. + | Let's create a kitten document representing the little guy we just met on the sidewalk outside: + :js + var silence = new Kitten({ name: 'Silence' }) + console.log(silence.name) // 'Silence' + p Kittens can meow, so let's take a look at how to add "speak" functionality to our documents: + :js + kittySchema.methods.speak = function () { + var greeting = this.name + ? 'Meow name is ' + this.name + : 'I don't have a name' + console.log(greeting); + } + + var Kitten = db.model('Kitten', kittySchema) + p + | Functions added to the + code methods + | property of a schema get compiled into the Model prototype and exposed on each document instance: + :js + var fluffy = new Kitten({ name: 'fluffy' }); + fluffy.speak() // "Meow name is fluffy" + p + | We have talking kittens! But we still haven't saved anything to MongoDB. + | Each document can be saved to the database by calling its + code save + | method. The first argument to the callback will be an error if any occured. + :js + fluffy.save(function (err) { + if (err) // TODO handle the error + console.log('meow') + }); + p + | Say time goes by and we want to display all the kittens we've seen. + | We can access all of the kitten documents through our Kitten model. + :js + Kitten.find(function (err, kittens) { + if (err) // TODO handle err + console.log(kittens) + }) + p + | We just logged all of the kittens in our db to the console. + | If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax. + :js + Kitten.find({ name: /fluff/i }, callback) + p + | This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback. + h3 Congratulations + p + | That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the + a(href="guide.html") guide + | , or + a(href="api.html") api docs + | for more. + script. + document.body.className = 'load'; + include includes/keen diff --git a/docs/3.1.x/docs/js/zepto.min.js b/docs/3.1.x/docs/js/zepto.min.js new file mode 100644 index 00000000000..428f84a28c5 --- /dev/null +++ b/docs/3.1.x/docs/js/zepto.min.js @@ -0,0 +1,2 @@ +/* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */ +(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.1.x/docs/layout.jade b/docs/3.1.x/docs/layout.jade new file mode 100644 index 00000000000..ab1e9553cbe --- /dev/null +++ b/docs/3.1.x/docs/layout.jade @@ -0,0 +1,25 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose #{title} v#{package.version} + block style + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + link(href='css/guide.css', rel='stylesheet', type='text/css') + body + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + #content + .module + block content + script. + document.body.className = 'load'; + include includes/keen diff --git a/docs/3.1.x/docs/middleware.html b/docs/3.1.x/docs/middleware.html new file mode 100644 index 00000000000..9fc90aaab6f --- /dev/null +++ b/docs/3.1.x/docs/middleware.html @@ -0,0 +1,29 @@ +Mongoose Middleware v3.1.2Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

    +There are two types of middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next

    var schema = new Schema(..);
    +schema.pre('save', function (next) {
    +  // do stuff
    +  next();
    +});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    +schema.pre('save', true, function (next, done) {
    +  // calling next kicks off the next middleware in parallel
    +  next();
    +  doAsync(done);
    +});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    +  var err = new Error('something went wrong');
    +  next(err);
    +});
    +
    +// later...
    +
    +myModel.save(function (err) {
    +  console.log(err.message) // something went wrong
    +});
    +

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    diff --git a/docs/3.1.x/docs/middleware.jade b/docs/3.1.x/docs/middleware.jade new file mode 100644 index 00000000000..b9e9e9eca94 --- /dev/null +++ b/docs/3.1.x/docs/middleware.jade @@ -0,0 +1,74 @@ +extends layout + +block content + h2 Middleware + p + | Middleware are functions which are passed control of flow during execution of + a(href="./api.html#document_Document-init") init + |, + a(href="./api.html#document_Document-validate") validate + |, + a(href="./api.html#model_Model-save") save + | and + a(href="./api.html#model_Model-remove") remove + | methods. + p + | There are two types of middleware, serial and parallel. + h4 Serial + p + | Serial middleware are executed one after another, when each middleware calls + code next + :js + var schema = new Schema(..); + schema.pre('save', function (next) { + // do stuff + next(); + }); + h4 Parallel + p + | Parallel middleware offer more fine-grained flow control. + :js + var schema = new Schema(..); + schema.pre('save', true, function (next, done) { + // calling next kicks off the next middleware in parallel + next(); + doAsync(done); + }); + p + | The hooked method, in this case + code save + |, will not be executed until + code done + | is called by each middleware. + h4 Use Cases + p + | Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas: + ul + li complex validation + li + | removing dependent documents + ul + li (removing a user removes all his blogposts) + li asynchronous defaults + li asynchronous tasks that a certain action triggers + ul + li triggering custom events + li notifications + h4 Error handling + :markdown + If any middleware calls `next` or `done` with an `Error` instance, the flow is interrupted, and the error is passed to the callback. + :js + schema.pre('save', function (next) { + var err = new Error('something went wrong'); + next(err); + }); + + // later... + + myModel.save(function (err) { + console.log(err.message) // something went wrong + }); + + h3#next Next Up + :markdown + Now that we've covered `middleware`, let's take a look at Mongoose's approach to faking JOINs with its query [population](/docs/populate.html) helper. diff --git a/docs/3.1.x/docs/migration.html b/docs/3.1.x/docs/migration.html new file mode 100644 index 00000000000..7b08121b51f --- /dev/null +++ b/docs/3.1.x/docs/migration.html @@ -0,0 +1,38 @@ +Mongoose Migration Guide v3.1.2Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    + +

    Here are the removed methods are their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    + +

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    • are now strict by default.
    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    + +

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    + +
    • $inc
    • $increment
    • $decrement
    + +

    If you really want this behavior back, include the mongoose-number module in your project.

    + +

    A good alternative is to start using the new findAndModify helpers. +Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    +...
    +Inventory.findById(id, function (err, inventory) {
    +  if (err) return handleError(err);
    +  inventory.productCount.$decrement(7);
    +  inventory.save(function (err) {
    +    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    +    if (err) return handleError(err);
    +    res.send(inventory.productCount); // 3
    +  });
    +});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    +  if (err) return handleError(err);
    +  res.send(inventory.productCount); // 3
    +});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This changes allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    diff --git a/docs/3.1.x/docs/migration.jade b/docs/3.1.x/docs/migration.jade new file mode 100644 index 00000000000..3fca606562a --- /dev/null +++ b/docs/3.1.x/docs/migration.jade @@ -0,0 +1,272 @@ +extends layout + +block append style + style. + table td { + padding-right: 15px; + } + +block content + h2 Migrating from 2.x to 3.x + :markdown + Migrating from Mongoose 2.x to 3.x brings with it [several changes](https://github.com/LearnBoost/mongoose/blob/master/History.md) to be aware of: + + h3 Query clean-up + :markdown + Many methods of the [Query](./api.html#query-js) API were nothing but aliases and have been [removed](https://github.com/LearnBoost/mongoose/commit/1149804c) in an effort to keep Mongoose clean and focused on there being as close to [one way](http://www.python.org/dev/peps/pep-0020/) of doing things as possible. If you really love all that extra noise, you can bring most of it back with [this module](https://github.com/aheckmann/mongoose-v2-compat). + + Here are the removed methods are their still existing aliases: + table + thead + tr(style='text-align:left') + th Removed + th Alternative + tbody + tr + td + code query.run + td + code query.exec + tr + td + code query.$or + td + code query.or + tr + td + code query.$nor + td + code query.nor + tr + td + code query.$gt + td + code query.gt + tr + td + code query.$gte + td + code query.gte + tr + td + code query.$lt + td + code query.lt + tr + td + code query.$lte + td + code query.lte + tr + td + code query.$ne + td + code query.ne + tr + td + code query.$in + td + code query.in + tr + td + code query.$nin + td + code query.nin + tr + td + code query.$all + td + code query.all + tr + td + code query.$regex + td + code query.regex + tr + td + code query.$size + td + code query.size + tr + td + code query.$maxDistance + td + code query.maxDistance + tr + td + code query.$mod + td + code query.mod + tr + td + code query.$near + td + code query.near + tr + td + code query.$exists + td + code query.exists + tr + td + code query.$elemMatch + td + code query.elemMatch + tr + td + code query.$within + td + code query.within + tr + td + code query.$box + td + code query.box + tr + td + code query.$center + td + code query.center + tr + td + code query.$centerSphere + td + code query.centerSphere + tr + td + code query.$slice + td + code query.slice + tr + td + code query.notEqualTo + td + code query.ne + tr + td + code query.wherein + td + code query.within + tr + td + code query.asc + td + code + | query.sort + a(href="#asc") * + tr + td + code query.desc + td + code + | query.sort + a(href="#desc") * + tr + td + code query.fields + td + code + | query.select + a(href="#fields") * + + h4#asc query#asc + :markdown + The `asc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#desc query#desc + :markdown + The `desc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#sort query#sort + :markdown + The [sort](./api.html#query_Query-sort) method of [Queries](./api.html#query-js) now accepts slightly different arguments. Read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#fields query#fields + :markdown + The `fields` method of [Query](./api.html#query-js) has been removed, it being mostly an alias for the [select](./api.html#query_Query-select) method anyway. The `select` method has slightly different arguments so read the [docs](./api.html#query_Query-select) to make sure your application is all set. + + Because of the change to the `fields` method, the field selection argument for [query.populate](./api.html#query_Query-populate) and model methods like [findById](./api.html#model_Model-findById), [find](./api.html#model_Model-find), etc, is slightly different as well (no longer accepts arrays for example), so read the [docs](./api.html#query_Query-select) to make sure your application is all set. + + h3 Connecting to ReplicaSets + :markdown + To connect to a [ReplicaSet](http://www.mongodb.org/display/DOCS/Replica+Sets) you no longer use the separate `connectSet` or `createSetConnection` methods. Both [mongoose.connect](./api.html#index_Mongoose-connect) and [mongoose.createConnection](./api.html#index_Mongoose-createConnection) are now smart enough to just do the right thing with your connection string. If you really want to bring `connectSet` and `createSetConnection` back use [this module](https://github.com/aheckmann/mongoose-v2-compat). + + h3 Schemas + :markdown + - are now [strict](./guide.html#strict) by default. + - Arrays of [object literal](./subdocs.html#altsyntax) now creates document arrays instead of arrays of [Mixed](./schematypes.html#mixed). + - Indexes are now created in [background](./guide.html#autoIndex) by default. + - Index errors are now emitted on their model instead of the connection. See issue [#984](https://github.com/LearnBoost/mongoose/issues/984). + + h3#arrays Arrays + :markdown + - [pop](./api.html#types_array_MongooseArray-pop) is now fixed causing a $set of the entire array. + - [$pop](./api.html#types_array_MongooseArray-%24pop) is now fixed and behaves just as MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the last element of the array. + - [shift](./api.html#types_array_MongooseArray-shift) is now fixed causing a $set of the entire array. + - [$shift](./api.html#types_array_MongooseArray-%24shift) is now fixed and behaves just as a [MongoDB $pop -1](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the first element of array. + - `$unshift` was removed, use [unshift](./api.html#types_array_MongooseArray-unshift) instead. + - `$addToSet` was removed, use [addToSet](./api.html#types_array_MongooseArray-addToSet) instead. + - `$pushAll` was removed, use [push](./api.html#types_array_MongooseArray-push) instead. + - `$pull` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. + - `$pullAll` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. + - `doAtomics` was changed to the [hasAtomics](./api.html#types_array_MongooseArray-hasAtomics) private method + + h3#mongoosenumber Number type + :markdown + The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused [too many problems](https://groups.google.com/d/msg/mongoose-orm/syKlN2xL1EE/FfRFhEFj4KcJ) when doing comparisons and had other bad side-effects. + + With it out of the picture, the following helper methods of MongooseNumbers are now also gone: + + - $inc + - $increment + - $decrement + + If you really want this behavior back, include the [mongoose-number](https://github.com/aheckmann/mongoose-number) module in your project. + + A good alternative is to start using the new [findAndModify](./api.html#model_Model-findOneAndUpdate) [helpers](./api.html#model_Model-findOneAndRemove). + Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber: + :js + var inventorySchema = new Schema({ productCount: Number }); + ... + Inventory.findById(id, function (err, inventory) { + if (err) return handleError(err); + inventory.productCount.$decrement(7); + inventory.save(function (err) { + // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback); + if (err) return handleError(err); + res.send(inventory.productCount); // 3 + }); + }); + :markdown + With MongooseNumber out of the picture, we'll instead use the [Account.findByIdAndUpdate](./api.html#model_Model-findByIdAndUpdate) helper: + :js + Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) { + if (err) return handleError(err); + res.send(inventory.productCount); // 3 + }); + :markdown + The `findByIdAndUpdate` helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases. + + h3#documents Documents + :markdown + - `doc#commit` is now removed, use [doc.markModified](./api.html#document_Document-markModified) instead + - [doc#modifiedPaths](./api.html#document_Document-modifiedPaths) is now a method not a getter + - `doc.modified` is now removed, use [doc.isModified](./api.html#document_Document-isModified) instead + + h4#gettercasting getter casting + :markdown + Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue [#820](https://github.com/LearnBoost/mongoose/issues/820) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). + + h4#setterorder setter order + :markdown + Values being set no longer cast until _after_ all setters have been applied. Previously the value returned from each setter was cast _before_ passing it on to the next setter. This changes allows more flexible processing of values in setters. See issue [#665](https://github.com/learnboost/mongoose/issues/665) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). + + h3#subdocs Subdocuments + :markdown + - `subdoc.parent` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parent). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). + - `subdoc.parentArray` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parentArray). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). + + h3#stringmatch String match validator + :markdown + The String SchemaType [match](./api.html#schema_string_SchemaString-match) validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the [required](./api.html#schematype_SchemaType-required) validator as well. See issue [#934](https://github.com/LearnBoost/mongoose/issues/934) and pull request [#935](https://github.com/LearnBoost/mongoose/pull/935). + + h3#version Versioning + :markdown + Documents are now transparently versioned. Read the in depth details [here](http://aaronheckmann.posterous.com/tag/versioning). diff --git a/docs/3.1.x/docs/models.html b/docs/3.1.x/docs/models.html new file mode 100644 index 00000000000..9f4819a6ba5 --- /dev/null +++ b/docs/3.1.x/docs/models.html @@ -0,0 +1,32 @@ +Mongoose Models v3.1.2Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var schema = new Schema({ name: 'string', size: 'string' });
    +var Tank = mongoose.model('Tank', schema);
    +
    +// or, if you are using separate connections
    +var db = mongoose.createConnection(..);
    +var Tank = db.model('Tank', schema);
    +

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = db.model('Tank', yourSchema);
    +
    +var small = new Tank({ size: 'small' });
    +small.save(function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +
    +// or
    +
    +Tank.create({ size: 'small' }, function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    +  if (err) return handleError(err);
    +  // removed!
    +});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at querying.

    diff --git a/docs/3.1.x/docs/models.jade b/docs/3.1.x/docs/models.jade new file mode 100644 index 00000000000..09aa8736c2e --- /dev/null +++ b/docs/3.1.x/docs/models.jade @@ -0,0 +1,61 @@ +extends layout + +block content + h2 Models + :markdown + [Models](./api.html#model-js) are fancy constructors compiled from our `Schema` definitions. Instances of these models represent [documents](./documents.html) which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models. + + h3 Compiling your first model + :js + var schema = new Schema({ name: 'string', size: 'string' }); + var Tank = mongoose.model('Tank', schema); + + // or, if you are using separate connections + var db = mongoose.createConnection(..); + var Tank = db.model('Tank', schema); + + h3 Constructing documents + :markdown + [Documents](./documents.html) are instances of our model. Creating them and saving to the database is easy: + :js + var Tank = db.model('Tank', yourSchema); + + var small = new Tank({ size: 'small' }); + small.save(function (err) { + if (err) return handleError(err); + // saved! + }) + + // or + + Tank.create({ size: 'small' }, function (err) { + if (err) return handleError(err); + // saved! + }) + + h3 Querying + :markdown + Finding documents is easy with Mongoose, which supports the [rich](http://www.mongodb.org/display/DOCS/Advanced+Queries) query syntax of MongoDB. Documents can be retreived using each `models` [find](./api.html#model_Model-find), [findById](./api.html#model_Model-findById), [findOne](./api.html#model_Model-findOne), or [where](./api.html#model_Model-where) static methods. + + :js + Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback); + :markdown + See the chapter on [querying](./queries.html) for more details on how to use the [Query](./api.html#query-js) api. + h3 Removing + :markdown + Models have a static `remove` method available for removing all documents matching `conditions`. + :js + Tank.remove({ size: 'large' }, function (err) { + if (err) return handleError(err); + // removed! + }); + h3 Updating + :markdown + Each `model` has its own `update` method for modifying documents in the database without returning them to your application. See the [API](./api.html#model_Model-update) docs for more detail. + h3 Yet more + :markdown + The [API docs](./api.html#model_Model) cover many additional methods available like [count](./api.html#model_Model-count), [mapReduce](./api.html#model_Model-mapReduce), [aggregate](./api.html#model_Model-aggregate), and more. + + h3#next Next Up + :markdown + Now that we've covered `Models`, let's take a look at [querying](/docs/queries.html). diff --git a/docs/3.1.x/docs/plugins.html b/docs/3.1.x/docs/plugins.html new file mode 100644 index 00000000000..72482e14fc8 --- /dev/null +++ b/docs/3.1.x/docs/plugins.html @@ -0,0 +1,33 @@ +Mongoose Plugins v3.1.2Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    + +

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    +module.exports = exports = function lastModifiedPlugin (schema, options) {
    +  schema.add({ lastMod: Date })
    +  
    +  schema.pre('save', function (next) {
    +    this.lastMod = new Date
    +    next()
    +  })
    +  
    +  if (options && options.index) {
    +    schema.path('lastMod').index(options.index)
    +  }
    +}
    +
    +// game-schema.js
    +var lastMod = require('./lastMod');
    +var Game = new Schema({ ... });
    +Game.plugin(lastMod, { index: true });
    +
    +// player-schema.js
    +var lastMod = require('./lastMod');
    +var Player = new Schema({ ... });
    +Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    diff --git a/docs/3.1.x/docs/plugins.jade b/docs/3.1.x/docs/plugins.jade new file mode 100644 index 00000000000..24e7c9ab86d --- /dev/null +++ b/docs/3.1.x/docs/plugins.jade @@ -0,0 +1,42 @@ +extends layout + +block content + h2 Plugins + :markdown + Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature. + + Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each `Schema`: + + :js + // lastMod.js + module.exports = exports = function lastModifiedPlugin (schema, options) { + schema.add({ lastMod: Date }) + + schema.pre('save', function (next) { + this.lastMod = new Date + next() + }) + + if (options && options.index) { + schema.path('lastMod').index(options.index) + } + } + + // game-schema.js + var lastMod = require('./lastMod'); + var Game = new Schema({ ... }); + Game.plugin(lastMod, { index: true }); + + // player-schema.js + var lastMod = require('./lastMod'); + var Player = new Schema({ ... }); + Player.plugin(lastMod); + :markdown + We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code. + h3 Community! + :markdown + Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. + + h3#next Next Up + :markdown + Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help [contribute](/docs/contributing.html) to the continuing development of Mongoose itself. diff --git a/docs/3.1.x/docs/populate.html b/docs/3.1.x/docs/populate.html new file mode 100644 index 00000000000..45ecc5fca6a --- /dev/null +++ b/docs/3.1.x/docs/populate.html @@ -0,0 +1,104 @@ +Mongoose Query Population v3.1.2Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    + +

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    +  , Schema = mongoose.Schema
    +  
    +var PersonSchema = new Schema({
    +  name    : String,
    +  age     : Number,
    +  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    +});
    +
    +var StorySchema = new Schema({
    +  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    +  title    : String,
    +  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    +});
    +
    +var Story  = mongoose.model('Story', StorySchema);
    +var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    +
    +aaron.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  var story1 = new Story({
    +    title: "Once upon a timex.",
    +    _creator: aaron._id    // assign an ObjectId
    +  });
    +  
    +  story1.save(function (err) {
    +    if (err) return handleError(err);
    +    // thats it!
    +  });
    +})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    +.findOne({ title: /timex/ })
    +.populate('_creator')
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    +})
    +

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    + +

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    +.findOne({ title: /timex/i })
    +.populate('_creator', 'name') // only return the Persons name
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  
    +  console.log('The creator is %s', story._creator.name);
    +  // prints "The creator is Aaron"
    +  
    +  console.log('The creators age is %s', story._creator.age);
    +  // prints "The creators age is null'
    +})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    +.find(...)
    +.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    + +

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    +aaron.save();

    This allows us to perform a find and populate combo:

    Person
    +.findOne({ name: 'Aaron' })
    +.populate('stories') // only works if we pushed refs to children
    +.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log(person);
    +})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    +.find({ _creator: aaron._id })
    +.populate('_creator') // not really necessary
    +.exec(function (err, stories) {
    +  if (err) return handleError(err);
    +  console.log('The stories are an array: ', stories);
    +})
    +

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    +guille.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  story._creator = guille; // or guille._id
    +  
    +  story.save(function (err) {
    +    if (err) return handleError(err);
    +    
    +    Story
    +    .findOne({ title: /timex/i })
    +    .populate('_creator', 'name')
    +    .exec(function (err, story) {
    +      if (err) return handleError(err);
    +      
    +      console.log('The creator is %s', story._creator.name)
    +      // prints "The creator is Guillermo"
    +    })
    +  })
    +})
    +

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    +Story.findOne(..).populate('_creator', 'name age').exec(..);
    +
    +// this doesn't
    +Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
    +

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

    diff --git a/docs/3.1.x/docs/populate.jade b/docs/3.1.x/docs/populate.jade new file mode 100644 index 00000000000..fcfaf1a437a --- /dev/null +++ b/docs/3.1.x/docs/populate.jade @@ -0,0 +1,164 @@ +extends layout + +block content + h2 Query Population + :markdown + There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. + + `ObjectIds` can refer to another document in a collection within our database and be `populate()`d when querying: + :js + var mongoose = require('mongoose') + , Schema = mongoose.Schema + + var PersonSchema = new Schema({ + name : String, + age : Number, + stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] + }); + + var StorySchema = new Schema({ + _creator : { type: Schema.Types.ObjectId, ref: 'Person' }, + title : String, + fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }] + }); + + var Story = mongoose.model('Story', StorySchema); + var Person = mongoose.model('Person', PersonSchema); + :markdown + So far we've created two `models`. Our `Person` model has it's `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose in which model to look, in our case the `Story` model. All `_id`s we store here must be document _ids from the `Story` model. We also added a `_creator` `ObjectId` to our `Story` schema which refers to a single `Person`. + h3 Saving refs + :markdown + Saving refs to other documents works the same way you normally save objectids, just assign an `ObjectId`: + :js + var aaron = new Person({ name: 'Aaron', age: 100 }); + + aaron.save(function (err) { + if (err) return handleError(err); + + var story1 = new Story({ + title: "Once upon a timex.", + _creator: aaron._id // assign an ObjectId + }); + + story1.save(function (err) { + if (err) return handleError(err); + // thats it! + }); + }) + h3 Population + :markdown + So far we haven't done anything special. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator`: + :js + Story + .findOne({ title: /timex/ }) + .populate('_creator') + .exec(function (err, story) { + if (err) return handleError(err); + console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron" + }) + + :markdown + Populated paths are no longer set to their original `ObjectId`s, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. + + Arrays of `ObjectId` refs work the same way. Just call the [populate](./api.html#query_Query-populate) method on the query and an array of documents will be returned _in place_ of the `ObjectIds`. + + h3 Field selection + :markdown + What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: + :js + Story + .findOne({ title: /timex/i }) + .populate('_creator', 'name') // only return the Persons name + .exec(function (err, story) { + if (err) return handleError(err); + + console.log('The creator is %s', story._creator.name); + // prints "The creator is Aaron" + + console.log('The creators age is %s', story._creator.age); + // prints "The creators age is null' + }) + h3 Query conditions for populate + :markdown + What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them? + :js + Story + .find(...) + .populate('fans', null, { age: { $gte: 21 }}, { limit: 5 }) + :markdown + Done. `Conditions` and `options` for populate queries are passed as the third and fourth arguments respectively. + h3 Refs to children + :markdown + We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' on to `aaron.stories`. + + There are two perspectives to this story. First, it's nice to have `aaron` know which are his stories. + :js + aaron.stories.push(story1); + aaron.save(); + :markdown + This allows us to perform a `find` and `populate` combo: + :js + Person + .findOne({ name: 'Aaron' }) + .populate('stories') // only works if we pushed refs to children + .exec(function (err, person) { + if (err) return handleError(err); + console.log(person); + }) + :markdown + However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely `find()` the documents we are interested in. + :js + Story + .find({ _creator: aaron._id }) + .populate('_creator') // not really necessary + .exec(function (err, stories) { + if (err) return handleError(err); + console.log('The stories are an array: ', stories); + }) + + h3 Updating refs + :markdown + Now that we have a `story` we realized that the `_creator` was incorrect. We can update `ObjectId` refs the same as any other property through the magic of Mongoose's internal casting: + :js + var guille = new Person({ name: 'Guillermo' }); + guille.save(function (err) { + if (err) return handleError(err); + + story._creator = guille; // or guille._id + + story.save(function (err) { + if (err) return handleError(err); + + Story + .findOne({ title: /timex/i }) + .populate('_creator', 'name') + .exec(function (err, story) { + if (err) return handleError(err); + + console.log('The creator is %s', story._creator.name) + // prints "The creator is Guillermo" + }) + }) + }) + + h4 NOTE: + :markdown + The documents returned from calling [populate](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. + + h4 NOTE: + :markdown + _Field selection_ in v3 is slightly different than v2. Arrays of fields are no longer accepted. + + :js + // this works + Story.findOne(..).populate('_creator', 'name age').exec(..); + + // this doesn't + Story.findOne(..).populate('_creator', ['name', 'age']).exec(..); + + :markdown + See the [migration guide](./migration.html#fields) for more detail. + + h3#next Next Up + :markdown + Now that we've covered query population, let's take a look at how we can break pieces of our functionality out into reusable and shareable [plugins](/docs/plugins.html). diff --git a/docs/3.1.x/docs/prior.html b/docs/3.1.x/docs/prior.html new file mode 100644 index 00000000000..c7fa6215c3c --- /dev/null +++ b/docs/3.1.x/docs/prior.html @@ -0,0 +1,9 @@ +Mongoose v3.1.2Fork me on GitHub

    Prior Release Documentation

    diff --git a/docs/3.1.x/docs/prior.jade b/docs/3.1.x/docs/prior.jade new file mode 100644 index 00000000000..1ef7d088a72 --- /dev/null +++ b/docs/3.1.x/docs/prior.jade @@ -0,0 +1,8 @@ +extends layout + +block content + h2 Prior Release Documentation + ul + each release in releases + li + a(href=release.url)= release.version diff --git a/docs/3.1.x/docs/queries.html b/docs/3.1.x/docs/queries.html new file mode 100644 index 00000000000..11dd7c0816c --- /dev/null +++ b/docs/3.1.x/docs/queries.html @@ -0,0 +1,41 @@ +Mongoose Queries v3.1.2Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    + +

    When a callback function:

    + +
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    + +

    Let's take a look at what happens when passing a callback:

    var Person = db.model('Person', yourSchema);
    +
    +// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    +Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    Here we see that the query was executed immediately and the results passed to our callback. +Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    +var query = Person.findOne({ 'name.last': 'Ghost' });
    +
    +// selecting the `name` and `occupation` fields
    +query.select('name occupation');
    +
    +// execute the query at a later time
    +query.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    +.find({ occupation: /host/ })
    +.where('name.last').equals('Ghost')
    +.where('age').gt(17).lt(66)
    +.where('likes').in(['vaporizing', 'talking'])
    +.limit(10)
    +.sort('-occupation')
    +.select('name occupation')
    +.exec(callback);
    +

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    diff --git a/docs/3.1.x/docs/queries.jade b/docs/3.1.x/docs/queries.jade new file mode 100644 index 00000000000..68c529efe25 --- /dev/null +++ b/docs/3.1.x/docs/queries.jade @@ -0,0 +1,62 @@ +extends layout + +block content + h2 Queries + :markdown + Documents can be retrieved through several static helper methods of [models](./models.html). + :markdown + Any [model](./api.html#model_Model) method which [involves](./api.html#model_Model-find) [specifying](./api.html#model_Model-findById) [query](./api.html#model_Model-count) [conditions](./api.html#model_Model-update) can be executed two ways: + + When a `callback` function: + + - is passed, the operation will be executed immediately with the results passed to the callback. + - is not passed, an instance of [Query](./api.html#query-js) is returned, which provides a special `QueryBuilder` interface for you. + + Let's take a look at what happens when passing a `callback`: + :js + var Person = db.model('Person', yourSchema); + + // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields + Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { + if (err) return handleError(err); + console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. + }) + :markdown + Here we see that the query was executed immediately and the results passed to our callback. + Now let's look at what happens when no `callback` is passed: + :js + // find each person with a last name matching 'Ghost' + var query = Person.findOne({ 'name.last': 'Ghost' }); + + // selecting the `name` and `occupation` fields + query.select('name occupation'); + + // execute the query at a later time + query.exec(function (err, person) { + if (err) return handleError(err); + console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. + }) + :markdown + An instance of [Query](./api.html#query-js) was returned which allows us to build up our query. Taking this example further: + :js + Person + .find({ occupation: /host/ }) + .where('name.last').equals('Ghost') + .where('age').gt(17).lt(66) + .where('likes').in(['vaporizing', 'talking']) + .limit(10) + .sort('-occupation') + .select('name occupation') + .exec(callback); + + h3#refs References to other documents + :markdown + There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. Read more [here](./populate.html). + + h3 Streaming + :markdown + Queries can be [streamed](http://nodejs.org/api/stream.html) from MongoDB to your application as well. Simply call the query's [stream](./api.html#query_Query-stream) method instead of [exec](./api.html#query_Query-exec) to return an instance of [QueryStream](./api.html#querystream_QueryStream). + + h3#next Next Up + :markdown + Now that we've covered `Queries`, let's take a look at [validation](/docs/validation.html). diff --git a/docs/3.1.x/docs/releases b/docs/3.1.x/docs/releases new file mode 100644 index 00000000000..cd9fcd27bd1 --- /dev/null +++ b/docs/3.1.x/docs/releases @@ -0,0 +1,2 @@ +2.8.x +2.7.x diff --git a/docs/3.1.x/docs/schematypes.html b/docs/3.1.x/docs/schematypes.html new file mode 100644 index 00000000000..76b695770c7 --- /dev/null +++ b/docs/3.1.x/docs/schematypes.html @@ -0,0 +1,67 @@ +Mongoose SchemaTypes v3.1.2Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    +  name:    String,
    +  binary:  Buffer,
    +  living:  Boolean,
    +  updated: { type: Date, default: Date.now },
    +  age:     { type: Number, min: 18, max: 65 },
    +  mixed:   Schema.Types.Mixed,
    +  _someId: Schema.Types.ObjectId,
    +  array:      [],
    +  ofString:   [String],
    +  ofNumber:   [Number],
    +  ofDates:    [Date],
    +  ofBuffer:   [Buffer],
    +  ofBoolean:  [Boolean],
    +  ofMixed:    [Schema.Types.Mixed],
    +  ofObjectId: [Schema.Types.ObjectId],
    +  nested: {
    +    stuff: { type: String, lowercase: true, trim: true }
    +  }
    +})
    +
    +// example use
    +
    +var Thing = mongoose.model('Thing', schema);
    +
    +var m = new Thing;
    +m.name = 'Statue of Liberty';
    +m.age = 125;
    +m.updated = new Date;
    +m.binary = new Buffer(0);
    +m.living = false;
    +m.mixed = {[ any: { thing: 'i want' } ]};
    +m.markModified('mixed');
    +m._someId = new mongoose.Types.ObjectId;
    +m.array.push(1);
    +m.ofString.push("strings!");
    +m.ofNumber.unshift(1,2,3,4);
    +m.ofDates.addToSet(new Date);
    +m.ofBuffer.pop();
    +m.ofMixed = [1, [], 'three', { four: 5 }];
    +m.nested.stuff = 'good';
    +m.save(callback);
    +

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    +var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    +person.markModified('anything');
    +person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    +var ObjectId = mongoose.Schema.Types.ObjectId;
    +var Car = new Schema({ driver: ObjectId });
    +// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    +var ToyBox = new Schema({
    +  toys: [ToySchema],
    +  buffers: [Buffer],
    +  string:  [String],
    +  numbers: [Number]
    +  // ... etc
    +});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    +var Empty2 = new Schema({ any: Array });
    +var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    +var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Documents.

    diff --git a/docs/3.1.x/docs/schematypes.jade b/docs/3.1.x/docs/schematypes.jade new file mode 100644 index 00000000000..b36574175f4 --- /dev/null +++ b/docs/3.1.x/docs/schematypes.jade @@ -0,0 +1,146 @@ +extends layout + +block content + h2 SchemaTypes + p + | SchemaTypes handle definition of path + a(href="./api.html#schematype_SchemaType-default") defaults + |, + a(href="./api.html#schematype_SchemaType-validate") validation + |, + a(href="./api.html#schematype_SchemaType-get") getters + |, + a(href="./api.html#schematype_SchemaType-set") setters + |, + a(href="./api.html#schematype_SchemaType-select") field selection defaults + | for + a(href="./api.html#query-js") queries + | and other general characteristics for + a(href="./api.html#schema-string-js") Strings + | and + a(href="./api.html#schema-number-js") Numbers + |. Check out their respective API documentation for more detail. + p + | Following are all valid + a(href="./api.html#schema_Schema-Types") Schema Types + |. + ul + li String + li Number + li Date + li Buffer + li Boolean + li Mixed + li ObjectId + li Array + h4 Example + :js + var schema = new Schema({ + name: String, + binary: Buffer, + living: Boolean, + updated: { type: Date, default: Date.now }, + age: { type: Number, min: 18, max: 65 }, + mixed: Schema.Types.Mixed, + _someId: Schema.Types.ObjectId, + array: [], + ofString: [String], + ofNumber: [Number], + ofDates: [Date], + ofBuffer: [Buffer], + ofBoolean: [Boolean], + ofMixed: [Schema.Types.Mixed], + ofObjectId: [Schema.Types.ObjectId], + nested: { + stuff: { type: String, lowercase: true, trim: true } + } + }) + + // example use + + var Thing = mongoose.model('Thing', schema); + + var m = new Thing; + m.name = 'Statue of Liberty'; + m.age = 125; + m.updated = new Date; + m.binary = new Buffer(0); + m.living = false; + m.mixed = {[ any: { thing: 'i want' } ]}; + m.markModified('mixed'); + m._someId = new mongoose.Types.ObjectId; + m.array.push(1); + m.ofString.push("strings!"); + m.ofNumber.unshift(1,2,3,4); + m.ofDates.addToSet(new Date); + m.ofBuffer.pop(); + m.ofMixed = [1, [], 'three', { four: 5 }]; + m.nested.stuff = 'good'; + m.save(callback); + + h3 Usage notes: + h4#mixed Mixed + p An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent: + :js + var Any = new Schema({ any: {} }); + var Any = new Schema({ any: Schema.Types.Mixed }); + p + | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the + code .markModified(path) + | method of the document passing the path to the Mixed type you just changed. + :js + person.anything = { x: [3, 4, { y: "changed" }] }; + person.markModified('anything'); + person.save(); // anything will now get saved + h4#objectids ObjectIds + p + | To specify a type of ObjectId, use + code Schema.Types.ObjectId + | in your declaration. + :js + var mongoose = require('mongoose'); + var ObjectId = mongoose.Schema.Types.ObjectId; + var Car = new Schema({ driver: ObjectId }); + // or just Schema.ObjectId for backwards compatibility with v2 + h4#arrays Arrays + p + | Provide creation of arrays of + a(href="./api.html#schema_Schema-Types") SchemaTypes + | or + a(href="./subdocs.html") Sub-Documents + |. + :js + var ToySchema = new Schema({ name: String }); + var ToyBox = new Schema({ + toys: [ToySchema], + buffers: [Buffer], + string: [String], + numbers: [Number] + // ... etc + }); + p + | Note: specifying an empty array is equivalent to + code Mixed + |. The following all create arrays of + code Mixed + |: + :js + var Empty1 = new Schema({ any: [] }); + var Empty2 = new Schema({ any: Array }); + var Empty3 = new Schema({ any: [Schema.Types.Mixed] }); + var Empty4 = new Schema({ any: [{}] }); + h3#customtypes Creating Custom Types + p + | Mongoose can also be extended with custom SchemaTypes. Search the + a(href="http://plugins.mongoosejs.com") plugins + | site for compatible types like + a(href="https://github.com/aheckmann/mongoose-long") mongoose-long + | and + a(href="https://github.com/aheckmann/mongoose-number") other + | + a(href="https://github.com/bnoguchi/mongoose-types") types + |. + + h3#next Next Up + :markdown + Now that we've covered `SchemaTypes`, let's take a look at [Documents](/docs/documents.html). diff --git a/docs/3.1.x/docs/source/_docs b/docs/3.1.x/docs/source/_docs new file mode 100644 index 00000000000..b127ff2902f --- /dev/null +++ b/docs/3.1.x/docs/source/_docs @@ -0,0 +1,16169 @@ + +### lib/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = require('./connectionstate')", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "require('./connectionstate')", + "string": "STATES" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the collection" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "conn", + "description": "A MongooseConnection instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "optional collection options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", + "summary": "

    Abstract Collection constructor

    ", + "body": "

    This is the base class that drivers inherit from and implement.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", + "ctx": { + "type": "function", + "name": "Collection", + "string": "Collection()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "name" + } + ], + "description": { + "full": "

    The collection name

    ", + "summary": "

    The collection name

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.name;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "conn" + } + ], + "description": { + "full": "

    The Connection instance

    ", + "summary": "

    The Connection instance

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.conn;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database connects

    ", + "summary": "

    Called when the database connects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onOpen", + "string": "Collection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database disconnects

    ", + "summary": "

    Called when the database disconnects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onClose", + "string": "Collection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the method to queue" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method when executed" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Queues a method for later execution when its
    database connection opens.

    ", + "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "addQueue", + "string": "Collection.prototype.addQueue()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes all queued methods and clears the queue.

    ", + "summary": "

    Executes all queued methods and clears the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "doQueue", + "string": "Collection.prototype.doQueue()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "ensureIndex", + "string": "Collection.prototype.ensureIndex()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findAndModify", + "string": "Collection.prototype.findAndModify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findOne", + "string": "Collection.prototype.findOne()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "find", + "string": "Collection.prototype.find()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "insert", + "string": "Collection.prototype.insert()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "save", + "string": "Collection.prototype.save()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "update", + "string": "Collection.prototype.update()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "getIndexes", + "string": "Collection.prototype.getIndexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "mapReduce", + "string": "Collection.prototype.mapReduce()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Collection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Collection", + "string": "module.exports" + } + } +] +### lib/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , assert =require('assert')", + "ctx": { + "type": "declaration", + "name": "url", + "value": "require('url')", + "string": "url" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Protocol prefix regexp.

    ", + "summary": "

    Protocol prefix regexp.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", + "ctx": { + "type": "declaration", + "name": "rgxProtocol", + "value": "/^(?:.)+:\\/\\//", + "string": "rgxProtocol" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "a mongoose instance" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." + }, + { + "type": "event", + "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." + }, + { + "type": "event", + "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." + }, + { + "type": "event", + "string": "`disconnecting`: Emitted when `connection.close()` was executed." + }, + { + "type": "event", + "string": "`disconnected`: Emitted after getting disconnected from the db." + }, + { + "type": "event", + "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." + }, + { + "type": "event", + "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." + }, + { + "type": "event", + "string": "`error`: Emitted when an error occurs on this connection." + }, + { + "type": "event", + "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", + "summary": "

    Connection constructor

    ", + "body": "

    For practical reasons, a Connection equals a Db.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", + "ctx": { + "type": "function", + "name": "Connection", + "string": "Connection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter

    ", + "summary": "

    Inherit from EventEmitter

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Connection", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Connection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readyState" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", + "summary": "

    Connection ready state

    ", + "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" + }, + { + "tags": [ + { + "type": "property", + "string": "collections" + } + ], + "description": { + "full": "

    A hash of the collections associated with this connection

    ", + "summary": "

    A hash of the collections associated with this connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collections;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    The mongodb.Db instance, set when the connection is opened

    ", + "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.db;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "connection_string", + "description": "mongodb://uri or the host to which you are connecting" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[port]", + "description": "database port" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n uri = url.parse(host);\n host = uri.hostname;\n port = uri.port || 27017;\n database = uri.pathname && uri.pathname.replace(/\\//g, '');\n }\n\n this.options = this.defaultOptions(options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing connection hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing connection database.'), callback);\n return this;\n }\n\n // handle authentication\n if (uri && uri.auth) {\n var auth = uri.auth.split(':');\n this.user = auth[0];\n this.pass = auth[1];\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n // user/pass options\n } else if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "open", + "string": "Connection.prototype.open()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "uris", + "description": "comma-separated mongodb:// `URI`s" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name if not included in `uris`" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "passed to the internal driver" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connects to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    ", + "summary": "

    Connects to a replica set.

    ", + "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n var uris = uris.split(',')\n , self = this;\n\n switch (arguments.length) {\n case 3:\n this.name = database;\n if ('function' === typeof options) callback = options, options = {};\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n this.options = options = this.defaultOptions(options);\n\n if (uris.length < 2) {\n this.error(new Error('Please provide comma-separated URIs'), callback);\n return this;\n }\n\n this.replica = true;\n this.host = [];\n this.port = [];\n\n uris.forEach(function (uri) {\n // handle missing protocols\n if (!rgxProtocol.test(uri))\n uri = 'mongodb://' + uri;\n\n var uri = url.parse(uri);\n\n self.host.push(uri.hostname);\n self.port.push(uri.port || 27017);\n\n if (!self.name && uri.pathname && uri.pathname.replace(/\\//g, ''))\n self.name = uri.pathname.replace(/\\//g, '');\n\n if (!self.user && uri.auth) {\n var auth = uri.auth.split(':');\n self.user = auth[0];\n self.pass = auth[1];\n }\n });\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "openSet", + "string": "Connection.prototype.openSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "optional" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", + "summary": "

    error

    ", + "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "error", + "string": "Connection.prototype.error()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "_open", + "string": "Connection.prototype._open()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection is opened

    ", + "summary": "

    Called when the connection is opened

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onOpen", + "string": "Connection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "self" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "close", + "string": "Connection.prototype.close()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onClose", + "string": "Connection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "of the collection" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional collection options" + }, + { + "type": "return", + "types": [ + "Collection" + ], + "description": "collection instance" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retrieves a collection, creating it if not cached.

    ", + "summary": "

    Retrieves a collection, creating it if not cached.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "collection", + "string": "Connection.prototype.collection()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "the model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "a schema. necessary when defining a model" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name of mongodb collection (optional) if not given it will be induced from model name" + }, + { + "type": "see", + "local": "Mongoose#model #index_Mongoose-model", + "visibility": "Mongoose#model" + }, + { + "type": "return", + "types": [ + "Model" + ], + "description": "The compiled model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    ", + "summary": "

    Defines or retrieves a model.

    ", + "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.model = function (name, schema, collection) {\n if (!this.models[name]) {\n var model = this.base.model(name, schema, collection, true)\n , Model\n\n if (this != model.prototype.db) {\n // subclass model using this connection and collection name\n Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model))\n return new Model(doc, fields, skipId);\n model.call(this, doc, fields, skipId);\n };\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = this;\n\n // collection name discovery\n if ('string' === typeof schema) {\n collection = schema;\n }\n\n if (!collection) {\n collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);\n }\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n Model.prototype.collection = this.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n }\n\n this.models[name] = Model || model;\n }\n\n return this.models[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "model", + "string": "Connection.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "level", + "description": "either off (0), slow (1), or all (2)" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[ms]", + "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Set profiling level.

    ", + "summary": "

    Set profiling level.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "setProfiling", + "string": "Connection.prototype.setProfiling()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Prepares default connection options.

    ", + "summary": "

    Prepares default connection options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.defaultOptions = function (options) {\n var o = options || {};\n\n o.server = o.server || {};\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n o.db = o.db || {};\n o.db.forceServerObjectId = false;\n\n return o;\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "defaultOptions", + "string": "Connection.prototype.defaultOptions()" + } + }, + { + "tags": [], + "description": { + "full": "

    Noop.

    ", + "summary": "

    Noop.

    ", + "body": "" + }, + "ignore": true, + "code": "function noop () {}", + "ctx": { + "type": "function", + "name": "noop", + "string": "noop()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", + "ctx": { + "type": "property", + "receiver": "Connection", + "name": "STATES", + "value": "STATES", + "string": "Connection.STATES" + } + } +] +### lib/connectionstate.js +[ + { + "tags": [], + "description": { + "full": "

    Connection states

    ", + "summary": "

    Connection states

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "module.exports = exports = Object.create(null)", + "string": "STATES" + } + } +] +### lib/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the values to set" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "the fields which were selected in the query returning this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "bool, should we auto create an ObjectId _id" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." + }, + { + "type": "event", + "string": "`save`: Emitted when the document is successfully saved" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document constructor.

    ", + "summary": "

    Document constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", + "ctx": { + "type": "function", + "name": "Document", + "string": "Document()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Document.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "schema" + } + ], + "description": { + "full": "

    The documents schema.

    ", + "summary": "

    The documents schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.schema;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "isNew" + } + ], + "description": { + "full": "

    Boolean flag specifying if the document is new.

    ", + "summary": "

    Boolean flag specifying if the document is new.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isNew;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "local": "Schema options /docs/guide.html#options", + "visibility": "Schema" + }, + { + "type": "property", + "string": "id" + } + ], + "description": { + "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", + "summary": "

    The string version of this documents _id.

    ", + "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.id;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "errors" + } + ], + "description": { + "full": "

    Hash containing current validation errors.

    ", + "summary": "

    Hash containing current validation errors.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.errors;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Builds the default doc structure

    ", + "summary": "

    Builds the default doc structure

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_buildDoc", + "string": "Document.prototype._buildDoc()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", + "summary": "

    Initializes the document without setters or marking anything modified.

    ", + "body": "

    Called internally after a document is returned from mongodb.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init');\n if (fn) fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "init", + "string": "Document.prototype.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "self", + "description": "document instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "raw mongodb doc" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "object we are initializing" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Init helper.

    ", + "summary": "

    Init helper.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", + "ctx": { + "type": "function", + "name": "init", + "string": "init()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", + "summary": "

    Stores the current values of the shard keys.

    ", + "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_storeShard", + "string": "Document.prototype._storeShard()" + } + }, + { + "tags": [], + "description": { + "full": "

    Set up middleware support

    ", + "summary": "

    Set up middleware support

    ", + "body": "" + }, + "ignore": true, + "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    ", + "summary": "

    Sends an update command with this document _id as the query selector.

    ", + "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "update", + "string": "Document.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "path", + "description": "path or object of key/vals to set" + }, + { + "type": "param", + "types": [ + "Any" + ], + "name": "val", + "description": "the value to set" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for \"on-the-fly\" attributes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    ", + "summary": "

    Sets the value of a path, or many paths.

    ", + "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.set = function (path, val, type) {\n var constructing = true === type\n , adhoc = type && true !== type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n if (null != path[key] && 'Object' === path[key].constructor.name\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n pathtype = this.schema.pathType(prefix + key);\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "set", + "string": "Document.prototype.set()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {\n if (this.isNew) {\n this.markModified(pathToMark);\n } else {\n\n priorVal || (priorVal = this.get(path));\n\n if (!this.isDirectModified(pathToMark)) {\n if (undefined === val && !this.isSelected(path)) {\n // special case:\n // when a path is not selected in a query its initial\n // value will be undefined.\n this.markModified(pathToMark, priorVal);\n } else if (undefined === val && path in this._activePaths.states.default) {\n // do nothing\n // unsetting the default value which was never saved\n } else if (!deepEqual(val, priorVal)) {\n this.markModified(pathToMark, priorVal);\n } else if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // special case:\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n this.markModified(pathToMark, priorVal);\n }\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_set", + "string": "Document.prototype._set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets a raw value from a path (no getters)

    ", + "summary": "

    Gets a raw value from a path (no getters)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "getValue", + "string": "Document.prototype.getValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "setValue", + "string": "Document.prototype.setValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for on-the-fly attributes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", + "summary": "

    Returns the value of a path.

    ", + "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "get", + "string": "Document.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns the schematype for the given path.

    ", + "summary": "

    Returns the schematype for the given path.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_path", + "string": "Document.prototype._path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to mark modified" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", + "summary": "

    Marks the path as having pending changes to write to the db.

    ", + "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "markModified", + "string": "Document.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "function to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope with which to call fn" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "try", + "string": "Document.prototype.try()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the list of paths that have been modified.

    ", + "summary": "

    Returns the list of paths that have been modified.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "modifiedPaths", + "string": "Document.prototype.modifiedPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", + "summary": "

    Returns true if this document was modified, else false.

    ", + "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isModified", + "string": "Document.prototype.isModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", + "summary": "

    Returns true if path was directly set and modified, else false.

    ", + "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isDirectModified", + "string": "Document.prototype.isDirectModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was initialized.

    ", + "summary": "

    Checks if path was initialized.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isInit", + "string": "Document.prototype.isInit()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", + "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", + "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isSelected", + "string": "Document.prototype.isSelected()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "cb", + "description": "called after validation completes, passing an error if one occurred" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", + "summary": "

    Executes registered validation rules for this document.

    ", + "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n cb(err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "validate", + "string": "Document.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "the error which states the reason `path` was invalid" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "invalidate", + "string": "Document.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Resets the internal modified state of this document.

    ", + "summary": "

    Resets the internal modified state of this document.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return (val && val instanceof DocumentArray && val.length);\n })\n .forEach(function (array) {\n array.forEach(function (doc) {\n doc._reset();\n });\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_reset", + "string": "Document.prototype._reset()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns this documents dirty paths / vals.

    ", + "summary": "

    Returns this documents dirty paths / vals.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_dirty", + "string": "Document.prototype._dirty()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compiles schemas.

    ", + "summary": "

    Compiles schemas.

    ", + "body": "" + }, + "ignore": true, + "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", + "ctx": { + "type": "function", + "name": "compile", + "string": "compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Defines the accessor named prop on the incoming prototype.

    ", + "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", + "body": "" + }, + "ignore": true, + "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", + "ctx": { + "type": "function", + "name": "define", + "string": "define()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Assigns/compiles schema into this documents prototype.

    ", + "summary": "

    Assigns/compiles schema into this documents prototype.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_setSchema", + "string": "Document.prototype._setSchema()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register default hooks

    ", + "summary": "

    Register default hooks

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return (val && val instanceof DocumentArray && val.length);\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n subdocs += array.length;\n array.forEach(function (value) {\n if (error) return;\n\n value.save(function (err) {\n if (error) return;\n\n if (err) {\n error = true;\n self._validationError = undefined;\n return next(err);\n }\n\n --subdocs || next();\n });\n });\n });\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_registerHooks", + "string": "Document.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Registers an error

    ", + "summary": "

    Registers an error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_error", + "string": "Document.prototype._error()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes methods queued from the Schema definition

    ", + "summary": "

    Executes methods queued from the Schema definition

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_doQueue", + "string": "Document.prototype._doQueue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "js object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this document into a plain javascript object

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", + "summary": "

    Converts this document into a plain javascript object

    ", + "body": "

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    See schema options for details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toObject", + "string": "Document.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "json", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "either `virtuals` or `paths`" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "`json`" + } + ], + "description": { + "full": "

    Applies virtuals properties to json.

    ", + "summary": "

    Applies virtuals properties to json.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", + "ctx": { + "type": "function", + "name": "applyGetters", + "string": "applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "same options as `Document#toObject`" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "see", + "local": "Document#toObject #document_Document-toObject", + "visibility": "Document#toObject" + }, + { + "type": "", + "string": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    \n\n

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", + "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", + "body": "

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toJSON", + "string": "Document.prototype.toJSON()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "inspect", + "string": "Document.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "toString" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toString = Document.prototype.inspect;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "toString", + "value": "Document.prototype.inspect", + "string": "Document.prototypetoString" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "a document to compare" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", + "summary": "

    Returns true if the Document stores the same data as doc.

    ", + "body": "

    Documents are considered equal when they have matching _ids.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "equals", + "string": "Document.prototype.equals()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", + "ctx": { + "type": "property", + "receiver": "Document", + "name": "ValidationError", + "value": "ValidationError", + "string": "Document.ValidationError" + } + } +] +### lib/drivers/node-mongodb-native/binary.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require('mongodb').BSONPure.Binary", + "string": "Binary" + } + } +] +### lib/drivers/node-mongodb-native/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", + "ctx": { + "type": "declaration", + "name": "MongooseCollection", + "value": "require('../../collection')", + "string": "MongooseCollection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Collection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", + "summary": "

    A node-mongodb-native collection implementation.

    ", + "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", + "ctx": { + "type": "function", + "name": "NativeCollection", + "string": "NativeCollection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from abstract Collection.

    ", + "summary": "

    Inherit from abstract Collection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "__proto__", + "value": "MongooseCollection.prototype", + "string": "NativeCollection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection opens.

    ", + "summary": "

    Called when the connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onOpen", + "string": "NativeCollection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onClose", + "string": "NativeCollection.prototype.onClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Copy the collection methods and make them subject to queues

    ", + "summary": "

    Copy the collection methods and make them subject to queues

    ", + "body": "" + }, + "ignore": true, + "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", + "ctx": { + "type": "function", + "name": "print", + "string": "print()" + } + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n } else if ('Date' === x[key].constructor.name) {\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", + "ctx": { + "type": "function", + "name": "format", + "string": "format()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "method", + "string": "getIndexes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retreives information about this collections indexes.

    ", + "summary": "

    Retreives information about this collections indexes.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "getIndexes", + "value": "NativeCollection.prototype.indexInformation", + "string": "NativeCollection.prototypegetIndexes" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeCollection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeCollection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", + "ctx": { + "type": "declaration", + "name": "MongooseConnection", + "value": "require('../../connection')", + "string": "MongooseConnection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Connection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native connection implementation.

    ", + "summary": "

    A node-mongodb-native connection implementation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", + "ctx": { + "type": "function", + "name": "NativeConnection", + "string": "NativeConnection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Connection.

    ", + "summary": "

    Inherits from Connection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeConnection", + "name": "__proto__", + "value": "MongooseConnection.prototype", + "string": "NativeConnection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, Number(this.port), this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpen", + "string": "NativeConnection.prototype.doOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", + "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", + "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , ports = this.port\n , self = this\n\n this.host.forEach(function (host, i) {\n servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));\n });\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpenSet", + "string": "NativeConnection.prototype.doOpenSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doClose", + "string": "NativeConnection.prototype.doClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeConnection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeConnection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/objectid.js +[ + { + "tags": [ + { + "type": "constructor", + "string": "NodeMongoDbObjectId" + }, + { + "type": "see", + "local": "ObjectId", + "visibility": "ObjectId" + } + ], + "description": { + "full": "

    node-mongodb-native ObjectId

    ", + "summary": "

    node-mongodb-native ObjectId

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require('mongodb').BSONPure.ObjectID", + "string": "ObjectId" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", + "ctx": { + "type": "declaration", + "name": "ObjectIdToString", + "value": "ObjectId.toString.bind(ObjectId)", + "string": "ObjectIdToString" + } + } +] +### lib/error.js +[ + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" + } + ], + "description": { + "full": "

    Mongoose error

    ", + "summary": "

    Mongoose error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", + "ctx": { + "type": "function", + "name": "MongooseError", + "string": "MongooseError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Error.

    ", + "summary": "

    Inherits from Error.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseError.prototype.__proto__ = Error.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseError", + "name": "__proto__", + "value": "Error.prototype", + "string": "MongooseError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseError", + "string": "module.exports" + } + } +] +### lib/errors/cast.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casting Error constructor.

    ", + "summary": "

    Casting Error constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", + "ctx": { + "type": "function", + "name": "CastError", + "string": "CastError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "CastError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "CastError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "CastError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = CastError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "CastError", + "string": "module.exports" + } + } +] +### lib/errors/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document Error

    ", + "summary": "

    Document Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", + "ctx": { + "type": "function", + "name": "DocumentError", + "string": "DocumentError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "DocumentError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = DocumentError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = DocumentError", + "string": "module.exports" + } + } +] +### lib/errors/validation.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "instance", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    Document Validation Error

    ", + "summary": "

    Document Validation Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", + "ctx": { + "type": "function", + "name": "ValidationError", + "string": "ValidationError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Console.log helper

    ", + "summary": "

    Console.log helper

    ", + "body": "" + }, + "ignore": false, + "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", + "ctx": { + "type": "method", + "constructor": "ValidationError", + "name": "toString", + "string": "ValidationError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidationError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidationError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = ValidationError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = ValidationError", + "string": "module.exports" + } + } +] +### lib/errors/validator.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Schema validator error

    ", + "summary": "

    Schema validator error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", + "ctx": { + "type": "function", + "name": "ValidatorError", + "string": "ValidatorError()" + } + }, + { + "tags": [], + "description": { + "full": "

    toString helper

    ", + "summary": "

    toString helper

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", + "ctx": { + "type": "method", + "constructor": "ValidatorError", + "name": "toString", + "string": "ValidatorError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError

    ", + "summary": "

    Inherits from MongooseError

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidatorError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidatorError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ValidatorError", + "string": "module.exports" + } + } +] +### lib/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", + "summary": "

    Mongoose constructor.

    ", + "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", + "ctx": { + "type": "function", + "name": "Mongoose", + "string": "Mongoose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", + "summary": "

    Sets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "set", + "string": "Mongoose.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "method", + "string": "get" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", + "summary": "

    Gets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.get = Mongoose.prototype.set;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "get", + "value": "Mongoose.prototype.set", + "string": "Mongoose.prototypeget" + } + }, + { + "tags": [], + "description": { + "full": "

    ReplSet connection string check.

    ", + "summary": "

    ReplSet connection string check.

    ", + "body": "" + }, + "ignore": true, + "code": "var rgxReplSet = /^.+,.+$/;", + "ctx": { + "type": "declaration", + "name": "rgxReplSet", + "value": "/^.+,.+$/", + "string": "rgxReplSet" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[uri]", + "description": "a mongodb:// URI" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "the created Connection object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Connection instance.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://localhost:port/database');\n\n// replica sets\ndb = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port);\n
    ", + "summary": "

    Creates a Connection instance.

    ", + "body": "

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://localhost:port/database');\n\n// replica sets\ndb = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "createConnection", + "string": "Mongoose.prototype.createConnection()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Mongoose#createConnection", + "visibility": "Mongoose#createConnection" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    ", + "summary": "

    Opens the default mongoose connection.

    ", + "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "connect", + "string": "Mongoose.prototype.connect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "called after all connection close." + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Disconnects all connections.

    ", + "summary": "

    Disconnects all connections.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "disconnect", + "string": "Mongoose.prototype.disconnect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name (optional, induced from model name)" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipInit]", + "description": "whether to skip initialization (defaults to false)" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    ", + "summary": "

    Defines a model or retrieves it.

    ", + "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n // normalize collection\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // look up models for the collection\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n this.modelSchemas[name] = schema;\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n } else {\n throw new Error('Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)');\n }\n }\n\n if (!this.models[name]) {\n schema || (schema = this.modelSchemas[name]);\n collection || (collection = schema.set('collection') || format(name));\n\n var model = Model.compile(name\n , this.modelSchemas[name]\n , collection\n , this.connection\n , this);\n\n if (!skipInit) model.init();\n\n this.models[name] = model;\n }\n\n return this.models[name];\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "model", + "string": "Mongoose.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "plugin callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "optional options" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", + "summary": "

    Declares a global plugin executed on all Schemas.

    ", + "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "plugin", + "string": "Mongoose.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "connection" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", + "summary": "

    The default connection of the mongoose module.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" + }, + { + "tags": [], + "description": { + "full": "

    Driver depentend APIs

    ", + "summary": "

    Driver depentend APIs

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Connection

    ", + "summary": "

    Connection

    ", + "body": "" + }, + "ignore": true, + "code": "var Connection = require(driver + '/connection');", + "ctx": { + "type": "declaration", + "name": "Connection", + "value": "require(driver + '/connection')", + "string": "Connection" + } + }, + { + "tags": [], + "description": { + "full": "

    Collection

    ", + "summary": "

    Collection

    ", + "body": "" + }, + "ignore": true, + "code": "var Collection = require(driver + '/collection');", + "ctx": { + "type": "declaration", + "name": "Collection", + "value": "require(driver + '/collection')", + "string": "Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The exports object is an instance of Mongoose.

    ", + "summary": "

    The exports object is an instance of Mongoose.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = new Mongoose", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Collection constructor

    ", + "summary": "

    The Mongoose Collection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Collection = Collection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Collection", + "value": "Collection", + "string": "mongoose.Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Connection constructor

    ", + "summary": "

    The Mongoose Connection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Connection = Connection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Connection", + "value": "Connection", + "string": "mongoose.Connection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose version

    ", + "summary": "

    Mongoose version

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "version", + "value": "JSON.parse(", + "string": "mongoose.version" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", + "summary": "

    The Mongoose constructor

    ", + "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Mongoose = Mongoose;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Mongoose", + "value": "Mongoose", + "string": "mongoose.Mongoose" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", + "summary": "

    The Mongoose Schema constructor

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Schema = Schema;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Schema", + "value": "Schema", + "string": "mongoose.Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose SchemaType constructor.

    ", + "summary": "

    The Mongoose SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaType = SchemaType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaType", + "value": "SchemaType", + "string": "mongoose.SchemaType" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Schema.SchemaTypes #schema_Schema-Types", + "visibility": "Schema.SchemaTypes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", + "summary": "

    The various Mongoose SchemaTypes.

    ", + "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaTypes = Schema.Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaTypes", + "value": "Schema.Types", + "string": "mongoose.SchemaTypes" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose VirtualType constructor.

    ", + "summary": "

    The Mongoose VirtualType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.VirtualType = VirtualType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "VirtualType", + "value": "VirtualType", + "string": "mongoose.VirtualType" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", + "summary": "

    The various Mongoose Types.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Types = Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Types", + "value": "Types", + "string": "mongoose.Types" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Query constructor.

    ", + "summary": "

    The Mongoose Query constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Query = Query;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Query", + "value": "Query", + "string": "mongoose.Query" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Promise constructor.

    ", + "summary": "

    The Mongoose Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Promise = Promise;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Promise", + "value": "Promise", + "string": "mongoose.Promise" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Model constructor.

    ", + "summary": "

    The Mongoose Model constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Model = Model;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Model", + "value": "Model", + "string": "mongoose.Model" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Document constructor.

    ", + "summary": "

    The Mongoose Document constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Document = Document;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Document", + "value": "Document", + "string": "mongoose.Document" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The MongooseError constructor.

    ", + "summary": "

    The MongooseError constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Error = require('./error');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Error", + "value": "require('./error')", + "string": "mongoose.Error" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The node-mongodb-native driver Mongoose uses.

    ", + "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.mongo = require('mongodb');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "mongo", + "value": "require('mongodb')", + "string": "mongoose.mongo" + } + } +] +### lib/model.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('./document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "values to with which to create the document" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "event", + "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." + }, + { + "type": "event", + "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Model constructor

    ", + "summary": "

    Model constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", + "ctx": { + "type": "function", + "name": "Model", + "string": "Model()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Document.

    ", + "summary": "

    Inherits from Document.

    ", + "body": "" + }, + "ignore": true, + "code": "Model.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "Model", + "name": "__proto__", + "value": "Document.prototype", + "string": "Model.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    Connection the model uses.

    ", + "summary": "

    Connection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.db;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "collection" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.collection;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "modelName" + } + ], + "description": { + "full": "

    The name of the model

    ", + "summary": "

    The name of the model

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.modelName;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "object" + }, + { + "type": "return", + "types": [ + "Object", + "undefined" + ], + "description": "population paths" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns what paths can be populated

    ", + "summary": "

    Returns what paths can be populated

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_getPopulationKeys", + "string": "Model.prototype._getPopulationKeys()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "schema", + "description": "type for the oid" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "oid", + "description": "object id or array of object ids" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "query", + "description": "object specifying query conditions, fields, and options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Populates an object

    ", + "summary": "

    Populates an object

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_populate", + "string": "Model.prototype._populate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "query that originated the initialization" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs auto-population of relations.

    ", + "summary": "

    Performs auto-population of relations.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "init", + "string": "Model.prototype.init()" + } + }, + { + "tags": [], + "description": { + "full": "

    Handles doc.save() callbacks

    ", + "summary": "

    Handles doc.save() callbacks

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new Error('No matching document found.'));\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", + "ctx": { + "type": "function", + "name": "handleSave", + "string": "handleSave()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "title": "middleware", + "url": "http://mongoosejs.com/docs/middleware.html", + "visibility": "http://mongoosejs.com/docs/middleware.html" + } + ], + "description": { + "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", + "summary": "

    Saves this document.

    ", + "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n complete(null);\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "save", + "string": "Model.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Mixed" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[operation]", + "description": "" + } + ], + "description": { + "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", + "ctx": { + "type": "function", + "name": "operand", + "string": "operand()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "val", + "description": "" + } + ], + "description": { + "full": "

    Compiles an update and where clause for a val with _atomics.

    ", + "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", + "ctx": { + "type": "function", + "name": "handleAtomics", + "string": "handleAtomics()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a special query document of the modified properties used in updates.

    ", + "summary": "

    Produces a special query document of the modified properties used in updates.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_delta", + "string": "Model.prototype._delta()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Appends versioning to the where and update clauses.

    ", + "summary": "

    Appends versioning to the where and update clauses.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_version", + "string": "Model.prototype._version()" + } + }, + { + "tags": [ + { + "type": "see", + "title": "versionKeys", + "url": "http://mongoosejs.com/docs/guide.html#versionKey", + "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Signal that we desire an increment of this documents version.

    ", + "summary": "

    Signal that we desire an increment of this documents version.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "increment", + "string": "Model.prototype.increment()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns a query object which applies shardkeys if they exist.

    ", + "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_where", + "string": "Model.prototype._where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", + "summary": "

    Removes this document from the db.

    ", + "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) return this;\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "remove", + "string": "Model.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register hooks override

    ", + "summary": "

    Register hooks override

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_registerHooks", + "string": "Model.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", + "summary": "

    Returns another Model instance.

    ", + "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "model", + "string": "Model.prototype.model()" + } + }, + { + "tags": [ + { + "type": "TODO", + "string": "determine if this is still necessary" + } + ], + "description": { + "full": "

    Give the constructor the ability to emit events.

    ", + "summary": "

    Give the constructor the ability to emit events.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the model compiles.

    ", + "summary": "

    Called when the model compiles.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.init = function init () {\n if (this.schema.options.autoIndex)\n this.ensureIndexes();\n\n this.schema.emit('init', this);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "init", + "string": "Model.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[cb]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    ", + "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", + "body": "

    After completion, an index event is emitted on this Model passing an error if one occurred.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "ensureIndexes", + "string": "Model.ensureIndexes()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "schema" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema the model uses.

    ", + "summary": "

    Schema the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.schema;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Database instance the model uses.

    ", + "summary": "

    Database instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.db;" + }, + { + "tags": [ + { + "type": "property", + "string": "collection" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.collection;" + }, + { + "tags": [ + { + "type": "property", + "string": "base" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Base Mongoose instance the model uses.

    ", + "summary": "

    Base Mongoose instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.base;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes documents from the collection.

    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    ", + "summary": "

    Removes documents from the collection.

    ", + "body": "

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "remove", + "string": "Model.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents

    \n\n

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    ", + "summary": "

    Finds documents

    ", + "body": "

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "find", + "string": "Model.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges the current named scope query into query.

    ", + "summary": "

    Merges the current named scope query into query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "_applyNamedScope", + "string": "Model._applyNamedScope()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "objectid, or a value that can be casted to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds a single document by id.

    \n\n

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    ", + "summary": "

    Finds a single document by id.

    ", + "body": "

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findById", + "string": "Model.findById()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    ", + "summary": "

    Finds one document.

    ", + "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n // TODO Handle all 3 of the following scenarios\n // Hint: Only some of these scenarios are possible if cQuery is present\n // Scenario: findOne(conditions, fields, callback);\n // Scenario: findOne(fields, options, callback);\n // Scenario: findOne(conditions, options, callback);\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n // TODO Handle all 2 of the following scenarios\n // Scenario: findOne(conditions, callback)\n // Scenario: findOne(fields, callback)\n // Scenario: findOne(options, callback);\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOne", + "string": "Model.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", + "summary": "

    Counts number of matching documents in a database collection.

    ", + "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "count", + "string": "Model.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a DISTINCT command

    ", + "summary": "

    Executes a DISTINCT command

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "distinct", + "string": "Model.distinct()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "optional value" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", + "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", + "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "where", + "string": "Model.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "argument", + "description": "is a javascript string or anonymous function" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "memberOf", + "parent": "Model" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Query.$where #query_Query-%24where", + "visibility": "Query.$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    ", + "summary": "

    Creates a Query and specifies a $where condition.

    ", + "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndUpdate", + "string": "Model.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "an ObjectId or string that can be cast to one." + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", + "visibility": "Model.findOneAndUpdate" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndUpdate", + "string": "Model.findByIdAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndRemove", + "string": "Model.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "id", + "description": "ObjectId or string that can be cast to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", + "visibility": "Model.findOneAndRemove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndRemove", + "string": "Model.findByIdAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array", + "Object..." + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", + "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", + "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "create", + "string": "Model.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "update", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Updates documents in the database without returning them.

    ", + "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "update", + "string": "Model.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "o", + "description": "an object specifying map-reduce options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/MapReduce", + "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", + "summary": "

    Executes a mapReduce command.

    ", + "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "mapReduce", + "string": "Model.mapReduce()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "an array of pipeline commands" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "aggregation", + "url": "http://docs.mongodb.org/manual/applications/aggregation/", + "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", + "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes an aggregate command on this models collection.

    \n\n

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    ", + "summary": "

    Executes an aggregate command on this models collection.

    ", + "body": "

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "aggregate", + "string": "Model.aggregate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "collectionName", + "description": "" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "connection", + "description": "" + }, + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "mongoose instance" + } + ], + "description": { + "full": "

    Compiler utility.

    ", + "summary": "

    Compiler utility.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "compile", + "string": "Model.compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Model;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Model", + "string": "module.exports" + } + } +] +### lib/namedscope.js +[ + { + "tags": [ + { + "type": "param", + "types": [ + "NamedScope" + ], + "name": "target", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "getters", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Decorate

    ", + "summary": "

    Decorate

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", + "ctx": { + "type": "method", + "constructor": "NamedScope", + "name": "decorate", + "string": "NamedScope.prototype.decorate()" + } + } +] +### lib/promise.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", + "ctx": { + "type": "declaration", + "name": "util", + "value": "require('./utils')", + "string": "util" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "back", + "description": "a callback+errback that accepts `fn(err, ...){}` as signature" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`err`: Emits when the promise resolves to an error." + }, + { + "type": "event", + "string": "`complete`: Emits when the promise resolves sucessfully." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Promise constructor.

    ", + "summary": "

    Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", + "ctx": { + "type": "function", + "name": "Promise", + "string": "Promise()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from EventEmitter.

    ", + "summary": "

    Inherits from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Promise", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Promise.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Event" + ], + "name": "event", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds listener to the event.

    \n\n

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", + "summary": "

    Adds listener to the event.

    ", + "body": "

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "on", + "string": "Promise.prototype.on()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Keeps track of emitted events to run them on on.

    ", + "summary": "

    Keeps track of emitted events to run them on on.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "emit", + "string": "Promise.prototype.emit()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for emitting the complete event.

    ", + "summary": "

    Shortcut for emitting the complete event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "complete", + "string": "Promise.prototype.complete()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Shortcut for emitting the err event.

    ", + "summary": "

    Shortcut for emitting the err event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "error", + "string": "Promise.prototype.error()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('complete', fn).

    ", + "summary": "

    Shortcut for .on('complete', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addCallback", + "string": "Promise.prototype.addCallback()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('err', fn).

    ", + "summary": "

    Shortcut for .on('err', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addErrback", + "string": "Promise.prototype.addErrback()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Adds a single function that's both a callback and errback.

    ", + "summary": "

    Adds a single function that's both a callback and errback.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addBack", + "string": "Promise.prototype.addBack()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "optional error or null" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "value to complete the promise with" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "summary": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "resolve", + "string": "Promise.prototype.resolve()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Promise;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Promise", + "string": "module.exports" + } + } +] +### lib/query.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "criteria", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", + "summary": "

    Query constructor used for building queries.

    ", + "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n if (criteria) this.find(criteria);\n}", + "ctx": { + "type": "function", + "name": "Query", + "string": "Query()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", + "summary": "

    Sets query options.

    ", + "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "setOptions", + "string": "Query.prototype.setOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "the model to which the query is bound" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "the operation to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "updateArg", + "description": "used in update methods" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Binds this query to a model.

    ", + "summary": "

    Binds this query to a model.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "bind", + "string": "Query.prototype.bind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "[operation]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", + "summary": "

    Executes the query

    ", + "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exec", + "string": "Query.prototype.exec()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[criteria]", + "description": "mongodb selector" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", + "summary": "

    Finds documents.

    ", + "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "find", + "string": "Query.prototype.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[obj]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", + "summary": "

    Casts this query to the schema of model

    ", + "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "cast", + "string": "Query.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options.

    ", + "summary": "

    Returns default options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('batchSize' in options))\n options.batchSize = 1000;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_optionsForExec", + "string": "Query.prototype._optionsForExec()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies schematype selected options to this query.

    ", + "summary": "

    Applies schematype selected options to this query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_applyPaths", + "string": "Query.prototype._applyPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "js", + "description": "javascript string or function" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", + "summary": "

    Specifies a $where condition

    ", + "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", + "summary": "

    Specifies a path for use with chaining.

    ", + "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "where", + "string": "Query.prototype.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", + "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", + "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "equals", + "string": "Query.prototype.equals()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", + "summary": "

    Specifies arguments for an $or condition.

    ", + "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "or", + "string": "Query.prototype.or()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", + "summary": "

    Specifies arguments for a $nor condition.

    ", + "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nor", + "string": "Query.prototype.nor()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "gt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", + "summary": "

    Specifies a $gt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "gte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $gte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "ne" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $ne query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "in" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $in query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "nin" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $nin query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "all" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $all query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "size" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $size query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "regex" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $regex query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxDistance" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $maxDistance query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", + "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", + "body": "
    Thing.where('type').nin(array)\n
    " + }, + "ignore": true, + "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $near condition

    ", + "summary": "

    Specifies a $near condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "near", + "string": "Query.prototype.near()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $nearSphere condition.

    ", + "summary": "

    Specifies a $nearSphere condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nearSphere", + "string": "Query.prototype.nearSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $mod condition

    ", + "summary": "

    Specifies a $mod condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "mod", + "string": "Query.prototype.mod()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $exists condition

    ", + "summary": "

    Specifies an $exists condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exists", + "string": "Query.prototype.exists()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object", + "Function" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "Function" + ], + "name": "criteria", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", + "summary": "

    Specifies an $elemMatch condition

    ", + "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "elemMatch", + "string": "Query.prototype.elemMatch()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "within" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Syntax sugar for expressive queries.

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    ", + "summary": "

    Syntax sugar for expressive queries.

    ", + "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "see", + "local": "Query#within #query_Query-within", + "visibility": "Query#within" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", + "summary": "

    Specifies a $box condition

    ", + "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "box", + "string": "Query.prototype.box()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "options e.g. { $uniqueDocs: true }" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", + "summary": "

    Specifies a $center condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "center", + "string": "Query.prototype.center()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", + "summary": "

    Specifies a $centerSphere condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "centerSphere", + "string": "Query.prototype.centerSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Array", + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", + "summary": "

    Specifies a $polygon condition

    ", + "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "polygon", + "string": "Query.prototype.polygon()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "local": "SchemaType", + "visibility": "SchemaType" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    ", + "summary": "

    Specifies which document fields to include or exclude

    ", + "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "select", + "string": "Query.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "number of elements to slice" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", + "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", + "summary": "

    Specifies a $slice condition

    ", + "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slice", + "string": "Query.prototype.slice()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", + "summary": "

    Sets the sort order

    ", + "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "sort", + "string": "Query.prototype.sort()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", + "ctx": { + "type": "function", + "name": "push", + "string": "push()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "limit" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", + "summary": "

    Specifies the limit option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "skip" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", + "summary": "

    Specifies the skip option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxscan" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", + "summary": "

    Specifies the maxscan option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "batchSize" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", + "summary": "

    Specifies the batchSize option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "comment" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", + "summary": "

    Specifies the comment option.

    ", + "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", + "summary": "

    limit, skip, maxscan, batchSize, comment

    ", + "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " + }, + "ignore": true, + "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", + "summary": "

    Specifies this query as a snapshot query.

    ", + "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "snapshot", + "string": "Query.prototype.snapshot()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "a hint object" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", + "summary": "

    Sets query hints.

    ", + "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "hint", + "string": "Query.prototype.hint()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", + "summary": "

    Sets the slaveOk option.

    ", + "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slaveOk", + "string": "Query.prototype.slaveOk()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "one of the listed preference options or their aliases" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "[tags]", + "description": "optional tags for this query" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", + "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the readPreference option for the query.

    \n\n

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    ", + "summary": "

    Sets the readPreference option for the query.

    ", + "body": "

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "read", + "string": "Query.prototype.read()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", + "summary": "

    Sets the lean option.

    ", + "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "lean", + "string": "Query.prototype.lean()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", + "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", + "summary": "

    Sets tailable option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "tailable", + "string": "Query.prototype.tailable()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes the query as a find() operation.

    ", + "summary": "

    Executes the query as a find() operation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "execFind", + "string": "Query.prototype.execFind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", + "summary": "

    Executes the query as a findOne() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOne", + "string": "Query.prototype.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", + "summary": "

    Exectues the query as a count() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "count", + "string": "Query.prototype.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a distict() operation.

    ", + "summary": "

    Executes this query as a distict() operation.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "distinct", + "string": "Query.prototype.distinct()" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "body": "" + }, + "ignore": true, + "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", + "ctx": { + "type": "declaration", + "name": "castOps", + "value": "{", + "string": "castOps" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "body": "" + }, + "ignore": true, + "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", + "ctx": { + "type": "declaration", + "name": "numberOps", + "value": "{", + "string": "numberOps" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "the update conditions" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", + "summary": "

    Executes this query as an update() operation.

    ", + "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n delete options.safe;\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "update", + "string": "Query.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "obj after casting its values" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts obj for an update command.

    ", + "summary": "

    Casts obj for an update command.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdate", + "string": "Query.prototype._castUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "- part of a query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "- path prefix (internal only)" + }, + { + "type": "return", + "types": [ + "Bool" + ], + "description": "true if this path has keys to update" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_walkUpdatePath", + "string": "Query.prototype._walkUpdatePath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[$conditional]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val according to schema and atomic op.

    ", + "summary": "

    Casts val according to schema and atomic op.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdateVal", + "string": "Query.prototype._castUpdateVal()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_getSchema", + "string": "Query.prototype._getSchema()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "https://github.com/LearnBoost/mongoose/issues/1091", + "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" + }, + { + "type": "see", + "title": "", + "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", + "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts selected field arguments for field selection with mongo 2.2

    \n\n
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    ", + "summary": "

    Casts selected field arguments for field selection with mongo 2.2

    ", + "body": "
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castFields", + "string": "Query.prototype._castFields()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", + "summary": "

    Executes this query as a remove() operation.

    ", + "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n delete options.safe;\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "remove", + "string": "Query.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[query]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[doc]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndUpdate", + "string": "Query.prototype.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndRemove", + "string": "Query.prototype.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "- either \"remove\" or \"update\"" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    _findAndModify

    ", + "summary": "

    _findAndModify

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_findAndModify", + "string": "Query.prototype._findAndModify()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Model" + ], + "name": "[model]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "see", + "local": "population ./populate.html", + "visibility": "population" + }, + { + "type": "see", + "local": "Query#select #query_Query-select", + "visibility": "Query#select" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    ", + "summary": "

    Specifies paths which should be populated with other documents.

    ", + "body": "

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "populate", + "string": "Query.prototype.populate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Populate options constructor

    ", + "summary": "

    Populate options constructor

    ", + "body": "" + }, + "ignore": true, + "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", + "ctx": { + "type": "function", + "name": "PopulateOptions", + "string": "PopulateOptions()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "QueryStream" + ], + "description": "" + }, + { + "type": "see", + "local": "QueryStream", + "visibility": "QueryStream" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a stream interface

    \n\n

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    ", + "summary": "

    Returns a stream interface

    ", + "body": "

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "stream", + "string": "Query.prototype.stream()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castDoc

    ", + "summary": "

    castDoc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castDoc", + "string": "castDoc()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castQuery

    ", + "summary": "

    castQuery

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castQuery", + "string": "castQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Exports.

    ", + "summary": "

    Exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Query", + "string": "module.exports" + } + } +] +### lib/querystream.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", + "ctx": { + "type": "declaration", + "name": "Stream", + "value": "require('stream').Stream", + "string": "Stream" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS Stream http://nodejs.org/api/stream.html" + }, + { + "type": "event", + "string": "`data`: emits a single Mongoose document" + }, + { + "type": "event", + "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." + }, + { + "type": "event", + "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Provides a ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    ", + "summary": "

    Provides a ReadStream interface for Queries.

    ", + "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", + "ctx": { + "type": "function", + "name": "QueryStream", + "string": "QueryStream()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Stream

    ", + "summary": "

    Inherit from Stream

    ", + "body": "" + }, + "ignore": true, + "code": "QueryStream.prototype.__proto__ = Stream.prototype;", + "ctx": { + "type": "property", + "constructor": "QueryStream", + "name": "__proto__", + "value": "Stream.prototype", + "string": "QueryStream.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readable" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is readable.

    ", + "summary": "

    Flag stating whether or not this stream is readable.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.readable;" + }, + { + "tags": [ + { + "type": "property", + "string": "paused" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is paused.

    ", + "summary": "

    Flag stating whether or not this stream is paused.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the query.

    ", + "summary": "

    Initializes the query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_init", + "string": "QueryStream.prototype._init()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#__next #querystream_QueryStream-__next", + "visibility": "QueryStream#__next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Trampoline for pulling the next doc from cursor.

    ", + "summary": "

    Trampoline for pulling the next doc from cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) return;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // account for possible nextObjects calling user code\n if (this.paused || this._destroyed) return;\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n var fn;\n while (this.__next()) {}\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_next", + "string": "QueryStream.prototype._next()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#_next #querystream_QueryStream-_next", + "visibility": "QueryStream#_next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pulls the next doc from the cursor.

    ", + "summary": "

    Pulls the next doc from the cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed) return;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "__next", + "string": "QueryStream.prototype.__next()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error", + "null" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && this.query.options.lean === true) {\n this.emit('data', doc);\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_onNextObject", + "string": "QueryStream.prototype._onNextObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pauses this stream.

    ", + "summary": "

    Pauses this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "pause", + "string": "QueryStream.prototype.pause()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Resumes this stream.

    ", + "summary": "

    Resumes this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n this._next();\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "resume", + "string": "QueryStream.prototype.resume()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "[err]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "destroy", + "string": "QueryStream.prototype.destroy()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "pipe" + }, + { + "type": "memberOf", + "parent": "QueryStream" + }, + { + "type": "see", + "title": "NodeJS", + "url": "http://nodejs.org/api/stream.html", + "visibility": "http://nodejs.org/api/stream.html" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", + "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", + "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = QueryStream", + "string": "module.exports" + } + } +] +### lib/schema/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Array SchemaType constructor

    ", + "summary": "

    Array SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "SchemaArray", + "string": "SchemaArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaArray", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "checkRequired", + "string": "SchemaArray.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides the getters application for the population special-case

    ", + "summary": "

    Overrides the getters application for the population special-case

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "applyGetters", + "string": "SchemaArray.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "cast", + "string": "SchemaArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "castForQuery", + "string": "SchemaArray.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': castToNumber\n , '$gte': castToNumber\n , '$lt': castToNumber\n , '$lte': castToNumber\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", + "ctx": { + "type": "function", + "name": "castToNumber", + "string": "castToNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaArray", + "string": "module.exports" + } + } +] +### lib/schema/boolean.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Boolean SchemaType constructor.

    ", + "summary": "

    Boolean SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaBoolean", + "string": "SchemaBoolean()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBoolean", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBoolean.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "checkRequired", + "string": "SchemaBoolean.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to boolean

    ", + "summary": "

    Casts to boolean

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "cast", + "string": "SchemaBoolean.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", + "ctx": { + "type": "function", + "name": "handleArray", + "string": "handleArray()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "castForQuery", + "string": "SchemaBoolean.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBoolean;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBoolean", + "string": "module.exports" + } + } +] +### lib/schema/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Buffer SchemaType constructor

    ", + "summary": "

    Buffer SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", + "ctx": { + "type": "function", + "name": "SchemaBuffer", + "string": "SchemaBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBuffer", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBuffer.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "checkRequired", + "string": "SchemaBuffer.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "cast", + "string": "SchemaBuffer.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "castForQuery", + "string": "SchemaBuffer.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBuffer;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBuffer", + "string": "module.exports" + } + } +] +### lib/schema/date.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date SchemaType constructor.

    ", + "summary": "

    Date SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaDate", + "string": "SchemaDate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaDate", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaDate.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for date

    ", + "summary": "

    Required validator for date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "checkRequired", + "string": "SchemaDate.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to date

    ", + "summary": "

    Casts to date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "cast", + "string": "SchemaDate.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date Query casting.

    ", + "summary": "

    Date Query casting.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "castForQuery", + "string": "SchemaDate.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaDate;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaDate", + "string": "module.exports" + } + } +] +### lib/schema/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaArray" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    SubdocsArray SchemaType constructor

    ", + "summary": "

    SubdocsArray SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "DocumentArray", + "string": "DocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from ArrayType.

    ", + "summary": "

    Inherits from ArrayType.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentArray", + "name": "__proto__", + "value": "ArrayType.prototype", + "string": "DocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs local validations first, then validations on each embedded doc

    ", + "summary": "

    Performs local validations first, then validations on each embedded doc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n SchemaType.prototype.doValidate.call(this, array, function(err){\n if (err) return fn(err);\n\n var count = array && array.length\n , error = false;\n\n if (!count) return fn();\n\n array.forEach(function(doc, index){\n doc.validate(function(err){\n if (err && !error){\n // rewrite they key\n err.key = self.key + '.' + index + '.' + err.key;\n fn(err);\n error = true;\n } else {\n --count || fn();\n }\n });\n });\n }, scope);\n};", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "doValidate", + "string": "DocumentArray.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "document", + "description": "that triggers the casting" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument)) {\n if (init) {\n selected || (selected = scopePaths(this, doc._selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "cast", + "string": "DocumentArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "DocumentArray" + ], + "name": "array", + "description": "- the array to scope `fields` paths" + }, + { + "type": "param", + "types": [ + "Object", + "undefined" + ], + "name": "fields", + "description": "- the root fields selected in the query" + }, + { + "type": "param", + "types": [ + "Boolean", + "undefined" + ], + "name": "init", + "description": "- if we are being created part of a query result" + } + ], + "description": { + "full": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "summary": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return selected;\n}", + "ctx": { + "type": "function", + "name": "scopePaths", + "string": "scopePaths()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = DocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "DocumentArray", + "string": "module.exports" + } + } +] +### lib/schema/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "String", + "value": "require('./string')", + "string": "exports.String" + } + } +] +### lib/schema/mixed.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Mixed SchemaType constructor.

    ", + "summary": "

    Mixed SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "Mixed", + "string": "Mixed()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "Mixed", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "Mixed.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "checkRequired", + "string": "Mixed.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", + "summary": "

    Casts val for Mixed.

    ", + "body": "

    this is a no-op

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "cast", + "string": "Mixed.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$cond", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "castForQuery", + "string": "Mixed.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Mixed;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Mixed", + "string": "module.exports" + } + } +] +### lib/schema/number.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Number SchemaType constructor.

    ", + "summary": "

    Number SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", + "ctx": { + "type": "function", + "name": "SchemaNumber", + "string": "SchemaNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaNumber", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaNumber.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for number

    ", + "summary": "

    Required validator for number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "checkRequired", + "string": "SchemaNumber.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "value", + "description": "minimum number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "min", + "string": "SchemaNumber.prototype.min()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "maximum", + "description": "number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "max", + "string": "SchemaNumber.prototype.max()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "value to cast" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to number

    ", + "summary": "

    Casts to number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "cast", + "string": "SchemaNumber.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "castForQuery", + "string": "SchemaNumber.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaNumber;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaNumber", + "string": "module.exports" + } + } +] +### lib/schema/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    ObjectId SchemaType constructor.

    ", + "summary": "

    ObjectId SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", + "ctx": { + "type": "function", + "name": "ObjectId", + "string": "ObjectId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "ObjectId", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "ObjectId.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "checkRequired", + "string": "ObjectId.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to ObjectId

    ", + "summary": "

    Casts to ObjectId

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "cast", + "string": "ObjectId.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "castForQuery", + "string": "ObjectId.prototype.castForQuery()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "turnOn", + "description": "auto generated ObjectId defaults" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "auto", + "string": "ObjectId.prototype.auto()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", + "ctx": { + "type": "function", + "name": "defaultId", + "string": "defaultId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ObjectId;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ObjectId", + "string": "module.exports" + } + } +] +### lib/schema/string.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    String SchemaType constructor.

    ", + "summary": "

    String SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", + "ctx": { + "type": "function", + "name": "SchemaString", + "string": "SchemaString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaString", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaString.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[args...]", + "description": "enumeration values" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", + "summary": "

    Adds enumeration values and a coinciding validator.

    ", + "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "enum", + "string": "SchemaString.prototype.enum()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", + "summary": "

    Adds a lowercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v) {\n return v.toLowerCase();\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "lowercase", + "string": "SchemaString.prototype.lowercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", + "summary": "

    Adds an uppercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v) {\n return v.toUpperCase();\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "uppercase", + "string": "SchemaString.prototype.uppercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", + "summary": "

    Adds a trim setter.

    ", + "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v) {\n return v.trim();\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "trim", + "string": "SchemaString.prototype.trim()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp" + ], + "name": "regExp", + "description": "regular expression to test against" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", + "summary": "

    Sets a regexp validator.

    ", + "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "match", + "string": "SchemaString.prototype.match()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "null", + "undefined" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "checkRequired", + "string": "SchemaString.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to String

    ", + "summary": "

    Casts to String

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "cast", + "string": "SchemaString.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "castForQuery", + "string": "SchemaString.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaString;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaString", + "string": "module.exports" + } + } +] +### lib/schema.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "definition", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted after the schema is compiled into a `Model`." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", + "summary": "

    Schema constructor.

    ", + "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", + "ctx": { + "type": "function", + "name": "Schema", + "string": "Schema()" + } + }, + { + "tags": [], + "description": { + "full": "

    Returns this documents _id cast to a string.

    ", + "summary": "

    Returns this documents _id cast to a string.

    ", + "body": "" + }, + "ignore": true, + "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", + "ctx": { + "type": "function", + "name": "idGetter", + "string": "idGetter()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Schema", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Schema.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "paths" + } + ], + "description": { + "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", + "summary": "

    Schema as flat paths

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.paths;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "tree" + } + ], + "description": { + "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", + "summary": "

    Schema as a tree

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.tree;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options for this schema, merged with options.

    ", + "summary": "

    Returns default options for this schema, merged with options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.defaultOptions = function (options) {\n options = utils.options({\n safe: true\n , strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "defaultOptions", + "string": "Schema.prototype.defaultOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "prefix", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", + "summary": "

    Adds key path / schema type pairs to this schema.

    ", + "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n }\n else\n this.path(prefix + i, obj[i]); // mixed type\n } else\n this.path(prefix + i, obj[i]);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "add", + "string": "Schema.prototype.add()" + } + }, + { + "tags": [], + "description": { + "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    ", + "summary": "

    Reserved document keys.

    ", + "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    " + }, + "ignore": false, + "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "reserved", + "value": "Object.create(null)", + "string": "Schema.reserved" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "constructor", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", + "summary": "

    Gets/sets schema paths.

    ", + "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(path) {\n if (!branch[path]) branch[path] = {};\n branch = branch[path];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "path", + "string": "Schema.prototype.path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "constructor" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts type arguments into Mongoose Types.

    ", + "summary": "

    Converts type arguments into Mongoose Types.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", + "ctx": { + "type": "method", + "receiver": "Schema", + "name": "interpretAsType", + "string": "Schema.interpretAsType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback function" + }, + { + "type": "return", + "types": [ + "Schema" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", + "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", + "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "eachPath", + "string": "Schema.prototype.eachPath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns an Array of path strings that are required by this schema.

    ", + "summary": "

    Returns an Array of path strings that are required by this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "requiredPaths", + "string": "Schema.prototype.requiredPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", + "summary": "

    Returns the pathType of path for this schema.

    ", + "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pathType", + "string": "Schema.prototype.pathType()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", + "ctx": { + "type": "function", + "name": "getPositionalPath", + "string": "getPositionalPath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the document method to call later" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds a method call to the queue.

    ", + "summary": "

    Adds a method call to the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "queue", + "string": "Schema.prototype.queue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", + "summary": "

    Defines a pre hook for the document.

    ", + "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pre", + "string": "Schema.prototype.pre()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "name of the method to hook" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", + "summary": "

    Defines a post hook for the document.

    ", + "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "post", + "string": "Schema.prototype.post()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "plugin", + "description": "callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "" + }, + { + "type": "see", + "local": "plugins", + "visibility": "plugins" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Registers a plugin for this schema.

    ", + "summary": "

    Registers a plugin for this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "plugin", + "string": "Schema.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "method", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", + "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "method", + "string": "Schema.prototype.method()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", + "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "static", + "string": "Schema.prototype.static()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", + "summary": "

    Defines an index (most likely compound) for this schema.

    ", + "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "index", + "string": "Schema.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "option name" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[value]", + "description": "if not passed, the current option value is returned" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets/gets a schema option.

    ", + "summary": "

    Sets/gets a schema option.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.set = function (key, value, tags) {\n if (arguments.length == 1)\n return this.options[key];\n\n this.options[key] = 'read' == key\n ? utils.readPref(value, tags)\n : value;\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "set", + "string": "Schema.prototype.set()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Compiles indexes from fields and schema-level indexes

    ", + "summary": "

    Compiles indexes from fields and schema-level indexes

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "indexes", + "string": "Schema.prototype.indexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", + "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", + "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " + }, + "ignore": true, + "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", + "ctx": { + "type": "function", + "name": "fixSubIndexPaths", + "string": "fixSubIndexPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Creates a virtual type with the given name.

    ", + "summary": "

    Creates a virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtual", + "string": "Schema.prototype.virtual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the virtual type with the given name.

    ", + "summary": "

    Returns the virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtualpath", + "string": "Schema.prototype.virtualpath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "namedScope", + "string": "Schema.prototype.namedScope()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Schema", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Schema Types.

    \n\n

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", + "summary": "

    The various Mongoose Schema Types.

    ", + "body": "

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.Types = require('./schema/index');", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "Types", + "value": "require('./schema/index')", + "string": "Schema.Types" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" + } +] +### lib/schemadefault.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "property", + "string": "system.profile" + }, + { + "type": "receiver", + "string": "exports" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Default model for querying the system.profiles collection.

    ", + "summary": "

    Default model for querying the system.profiles collection.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" + } +] +### lib/schematype.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');\nvar CastError = require('./errors/cast')\nvar ValidatorError = require('./errors/validator')", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[instance]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    SchemaType constructor

    ", + "summary": "

    SchemaType constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", + "ctx": { + "type": "function", + "name": "SchemaType", + "string": "SchemaType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function", + "any" + ], + "name": "val", + "description": "the default value" + }, + { + "type": "return", + "types": [ + "defaultValue" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", + "summary": "

    Sets a default value for this SchemaType.

    ", + "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "default", + "string": "SchemaType.prototype.default()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "Boolean" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", + "summary": "

    Declares the index options for this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "index", + "string": "SchemaType.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares an unique index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    ", + "summary": "

    Declares an unique index.

    ", + "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "unique", + "string": "SchemaType.prototype.unique()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a sparse index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", + "summary": "

    Declares a sparse index.

    ", + "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "sparse", + "string": "SchemaType.prototype.sparse()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "when", + "description": "" + }, + { + "type": "added", + "string": "3.0.0" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    ", + "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", + "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "expires", + "string": "SchemaType.prototype.expires()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    ", + "summary": "

    Adds a setter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "set", + "string": "SchemaType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    ", + "summary": "

    Adds a getter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "get", + "string": "SchemaType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp", + "Function", + "Object" + ], + "name": "obj", + "description": "validator" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[error]", + "description": "optional error message" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", + "summary": "

    Adds validator(s) for this document path.

    ", + "body": "

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "validate", + "string": "SchemaType.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "required", + "description": "enable/disable the validator" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", + "summary": "

    Adds a required validator to this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "required", + "string": "SchemaType.prototype.required()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope which callback are executed" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets the default value

    ", + "summary": "

    Gets the default value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "getDefault", + "string": "SchemaType.prototype.getDefault()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies setters

    ", + "summary": "

    Applies setters

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applySetters", + "string": "SchemaType.prototype.applySetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies getters to a value

    ", + "summary": "

    Applies getters to a value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applyGetters", + "string": "SchemaType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", + "summary": "

    Sets default select() behavior for this path.

    ", + "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "select", + "string": "SchemaType.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "doValidate", + "string": "SchemaType.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if value is a valid Reference.

    ", + "summary": "

    Determines if value is a valid Reference.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", + "ctx": { + "type": "method", + "receiver": "SchemaType", + "name": "_isRef", + "string": "SchemaType._isRef()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = SchemaType", + "string": "module.exports" + } + } +] +### lib/statemachine.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", + "ctx": { + "type": "declaration", + "name": "StateMachine", + "value": "module.exports = exports = function StateMachine () {", + "string": "StateMachine" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "subclass constructor" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", + "ctx": { + "type": "method", + "receiver": "StateMachine", + "name": "ctor", + "string": "StateMachine.ctor()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", + "summary": "

    This function is wrapped by the state change functions

    ", + "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_changeState", + "string": "StateMachine.prototype._changeState()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "clear", + "string": "StateMachine.prototype.clear()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "that we want to check for." + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "some", + "string": "StateMachine.prototype.some()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "iterMethod", + "description": "is either 'forEach' or 'map'" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_iter", + "string": "StateMachine.prototype._iter()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "forEach", + "string": "StateMachine.prototype.forEach()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "map", + "string": "StateMachine.prototype.map()" + } + } +] +### lib/types/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", + "ctx": { + "type": "declaration", + "name": "EmbeddedDocument", + "value": "require('./embedded')", + "string": "EmbeddedDocument" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Array" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", + "summary": "

    Mongoose Array constructor.

    ", + "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseArray", + "string": "MongooseArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Array

    ", + "summary": "

    Inherit from Array

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseArray.prototype = new Array;", + "ctx": { + "type": "property", + "receiver": "MongooseArray", + "name": "prototype", + "value": "new Array", + "string": "MongooseArray.prototype" + } + }, + { + "tags": [ + { + "type": "property", + "string": "_atomics" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores a queue of atomic operations to perform

    ", + "summary": "

    Stores a queue of atomic operations to perform

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._atomics;" + }, + { + "tags": [ + { + "type": "property", + "string": "_parent" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._parent;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "return", + "types": [ + "value" + ], + "description": "the casted value" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts a member based on this arrays schema.

    ", + "summary": "

    Casts a member based on this arrays schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_cast", + "string": "MongooseArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "EmbeddedDocument" + ], + "name": "embeddedDoc", + "description": "the embedded doc that invoked this method on the Array" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "embeddedPath", + "description": "the path which changed in the embeddedDoc" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", + "summary": "

    Marks this array as modified.

    ", + "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._markModified = function (embeddedDoc, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n if (arguments.length) {\n // If an embedded doc bubbled up the change\n dirtyPath = [this._path, this.indexOf(embeddedDoc), embeddedPath].join('.');\n } else {\n dirtyPath = this._path;\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_markModified", + "string": "MongooseArray.prototype._markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "op", + "description": "operation" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register an atomic operation with the parent.

    ", + "summary": "

    Register an atomic operation with the parent.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n this._markModified();\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n if (this._atomics.$set) {\n return this;\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n this._markModified();\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n this._markModified();\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_registerAtomic", + "string": "MongooseArray.prototype._registerAtomic()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "hasAtomics", + "string": "MongooseArray.prototype.hasAtomics()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#push with proper change tracking.

    ", + "summary": "

    Wraps Array#push with proper change tracking.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "push", + "string": "MongooseArray.prototype.push()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Pushes items to the array non-atomically.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "nonAtomicPush", + "string": "MongooseArray.prototype.nonAtomicPush()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "$pop" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", + "summary": "

    Pops the array atomically at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" + }, + { + "tags": [ + { + "type": "see", + "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", + "visibility": "MongooseArray#$pop" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#pop with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pop", + "string": "MongooseArray.prototype.pop()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "method", + "string": "$shift" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", + "summary": "

    Atomically shifts the array at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#shift with proper change tracking.

    ", + "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "shift", + "string": "MongooseArray.prototype.shift()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "values to remove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes items from an array atomically

    \n\n

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    ", + "summary": "

    Removes items from an array atomically

    ", + "body": "

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "remove", + "string": "MongooseArray.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pulls items from the array atomically.

    ", + "summary": "

    Pulls items from the array atomically.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pull", + "string": "MongooseArray.prototype.pull()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#splice with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#splice with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.splice = function () {\n if (arguments.length) {\n var ret = [].splice.apply(this, arguments);\n this._registerAtomic('$set', this);\n }\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "splice", + "string": "MongooseArray.prototype.splice()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#unshift with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n return this.length;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "unshift", + "string": "MongooseArray.prototype.unshift()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#sort with proper change tracking.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "sort", + "string": "MongooseArray.prototype.sort()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "the values that were added" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", + "summary": "

    Adds values to the array if not already present.

    ", + "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "addToSet", + "string": "MongooseArray.prototype.addToSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array.

    ", + "summary": "

    Returns a native js Array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "toObject", + "string": "MongooseArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "inspect", + "string": "MongooseArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the item to look for" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Return the index of obj or -1 if not found.

    ", + "summary": "

    Return the index of obj or -1 if not found.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "indexOf", + "string": "MongooseArray.prototype.indexOf()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = MongooseArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = MongooseArray", + "string": "module.exports" + } + } +] +### lib/types/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require(driver + '/binary');", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require(driver + '/binary')", + "string": "Binary" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "encode", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "offset", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Buffer" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", + "summary": "

    Mongoose Buffer constructor.

    ", + "body": "

    Values always have to be passed to the constructor to initialize.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", + "ctx": { + "type": "function", + "name": "MongooseBuffer", + "string": "MongooseBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Buffer.

    ", + "summary": "

    Inherit from Buffer.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.prototype = new Buffer(0);", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "prototype", + "value": "new Buffer(0)", + "string": "MongooseBuffer.prototype" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "_parent" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._parent;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this buffer as modified.

    ", + "summary": "

    Marks this buffer as modified.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "_markModified", + "string": "MongooseBuffer.prototype._markModified()" + } + }, + { + "tags": [], + "description": { + "full": "

    Writes the buffer.

    ", + "summary": "

    Writes the buffer.

    ", + "body": "" + }, + "ignore": false, + "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "write", + "string": "MongooseBuffer.prototype.write()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "MongooseBuffer" + ], + "description": "" + }, + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "target", + "description": "" + } + ], + "description": { + "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", + "summary": "

    Copies the buffer.

    ", + "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "copy", + "string": "MongooseBuffer.prototype.copy()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "body": "" + }, + "ignore": true, + "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://bsonspec.org/#/specification", + "visibility": "http://bsonspec.org/#/specification" + }, + { + "type": "param", + "types": [ + "Hex" + ], + "name": "[subtype]", + "description": "" + }, + { + "type": "return", + "types": [ + "Binary" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", + "summary": "

    Converts this buffer to its Binary type representation.

    ", + "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "toObject", + "string": "MongooseBuffer.prototype.toObject()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "Binary", + "value": "Binary", + "string": "MongooseBuffer.Binary" + } + } +] +### lib/types/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", + "ctx": { + "type": "declaration", + "name": "MongooseArray", + "value": "require('./array')", + "string": "MongooseArray" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to this array" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "MongooseDocumentArray" + ], + "description": "" + }, + { + "type": "inherits", + "string": "MongooseArray" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    DocumentArray constructor

    ", + "summary": "

    DocumentArray constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseDocumentArray", + "string": "MongooseDocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseArray

    ", + "summary": "

    Inherits from MongooseArray

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseDocumentArray", + "name": "__proto__", + "value": "MongooseArray.prototype", + "string": "MongooseDocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides MongooseArray#cast

    ", + "summary": "

    Overrides MongooseArray#cast

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype._cast = function (value) {\n var doc = new this._schema.casterConstructor(value, this);\n return doc;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "_cast", + "string": "MongooseDocumentArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "EmbeddedDocument", + "null" + ], + "description": "the subdocuent or null if not found." + }, + { + "type": "param", + "types": [ + "ObjectId", + "String", + "Number", + "Buffer" + ], + "name": "id", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Searches array items for the first document with a matching id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", + "summary": "

    Searches array items for the first document with a matching id.

    ", + "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "id", + "string": "MongooseDocumentArray.prototype.id()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", + "summary": "

    Returns a native js Array of plain js objects

    ", + "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "toObject", + "string": "MongooseDocumentArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "inspect", + "string": "MongooseDocumentArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the value to cast to this arrays SubDocument schema" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", + "summary": "

    Creates a subdocument casted to this schema.

    ", + "body": "

    This is the same subdocument constructor used for casting.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "create", + "string": "MongooseDocumentArray.prototype.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates a fn that notifies all child docs of event.

    ", + "summary": "

    Creates a fn that notifies all child docs of event.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n self[i].emit(event, val);\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "notify", + "string": "MongooseDocumentArray.prototype.notify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseDocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseDocumentArray", + "string": "module.exports" + } + } +] +### lib/types/embedded.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('../document')\n , inspect = require('util').inspect;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('../document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "js object returned from the db" + }, + { + "type": "param", + "types": [ + "MongooseDocumentArray" + ], + "name": "parentArr", + "description": "the parent array of this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "skipId", + "description": "" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    EmbeddedDocument constructor.

    ", + "summary": "

    EmbeddedDocument constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", + "ctx": { + "type": "function", + "name": "EmbeddedDocument", + "string": "EmbeddedDocument()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Document

    ", + "summary": "

    Inherit from Document

    ", + "body": "" + }, + "ignore": true, + "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "EmbeddedDocument", + "name": "__proto__", + "value": "Document.prototype", + "string": "EmbeddedDocument.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path which changed" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", + "summary": "

    Marks the embedded doc modified.

    ", + "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "markModified", + "string": "EmbeddedDocument.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "return", + "types": [ + "EmbeddedDocument" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", + "summary": "

    Used as a stub for hooks.js

    ", + "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "save", + "string": "EmbeddedDocument.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes the subdocument from its parent array.

    ", + "summary": "

    Removes the subdocument from its parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "remove", + "string": "EmbeddedDocument.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Override #update method of parent documents.

    ", + "summary": "

    Override #update method of parent documents.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "update", + "string": "EmbeddedDocument.prototype.update()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "inspect", + "string": "EmbeddedDocument.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "error which states the reason `path` was invalid" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "invalidate", + "string": "EmbeddedDocument.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "ownerDocument", + "string": "EmbeddedDocument.prototype.ownerDocument()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", + "ctx": { + "type": "function", + "name": "ownerDocument", + "string": "ownerDocument()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent document.

    ", + "summary": "

    Returns this sub-documents parent document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parent", + "string": "EmbeddedDocument.prototype.parent()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent array.

    ", + "summary": "

    Returns this sub-documents parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parentArray", + "string": "EmbeddedDocument.prototype.parentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = EmbeddedDocument;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "EmbeddedDocument", + "string": "module.exports" + } + } +] +### lib/types/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "Array", + "value": "require('./array')", + "string": "exports.Array" + } + } +] +### lib/types/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [ + { + "type": "constructor", + "string": "ObjectId" + } + ], + "description": { + "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", + "summary": "

    ObjectId type constructor

    ", + "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require(driver + '/objectid')", + "string": "ObjectId" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "str", + "description": "" + }, + { + "type": "static", + "string": "fromString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "ObjectId" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates an ObjectId from str

    ", + "summary": "

    Creates an ObjectId from str

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.fromString;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId" + ], + "name": "oid", + "description": "ObjectId instance" + }, + { + "type": "static", + "string": "toString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts oid to a string.

    ", + "summary": "

    Converts oid to a string.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.toString;" + } +] +### lib/utils.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , MongooseBuffer\n , MongooseArray\n , Document", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "a model name" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "a collection name" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a collection name from model name.

    ", + "summary": "

    Produces a collection name from model name.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "toCollectionName", + "string": "exports.toCollectionName()" + } + }, + { + "tags": [], + "description": { + "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Pluralization rules.

    ", + "body": "

    These rules are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "pluralization", + "value": "[", + "string": "exports.pluralization" + } + }, + { + "tags": [], + "description": { + "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Uncountable words.

    ", + "body": "

    These words are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news'\n];\nvar uncountables = exports.uncountables;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "uncountables", + "value": "[", + "string": "exports.uncountables" + } + }, + { + "tags": [ + { + "type": "author", + "string": "TJ Holowaychuk (extracted from _ext.js_)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "string", + "description": "to pluralize" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pluralize function.

    ", + "summary": "

    Pluralize function.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", + "ctx": { + "type": "function", + "name": "pluralize", + "string": "pluralize()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "listener", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Add once to EventEmitter if absent

    ", + "summary": "

    Add once to EventEmitter if absent

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", + "ctx": { + "type": "declaration", + "name": "Events", + "value": "EventEmitter", + "string": "Events" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Events", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Events.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Add once.

    ", + "summary": "

    Add once.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", + "ctx": { + "type": "method", + "constructor": "Events", + "name": "once", + "string": "Events.prototype.once()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "a", + "description": "a value to compare to `b`" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "b", + "description": "a value to compare to `a`" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", + "summary": "

    Determines if a and b are deep equal.

    ", + "body": "

    Modified from node/lib/assert.js

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "deepEqual", + "string": "exports.deepEqual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the object to clone" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the cloned object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Object clone with Mongoose natives support.

    \n\n

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.

    ", + "summary": "

    Object clone with Mongoose natives support.

    ", + "body": "

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId) {\n return new ObjectId(obj.id);\n }\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "clone", + "string": "exports.clone()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", + "ctx": { + "type": "function", + "name": "cloneObject", + "string": "cloneObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "defaults", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the merged object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Copies and merges options with defaults.

    ", + "summary": "

    Copies and merges options with defaults.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "options", + "string": "exports.options()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Generates a random string

    ", + "summary": "

    Generates a random string

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "random", + "string": "exports.random()" + } + }, + { + "tags": [], + "description": { + "full": "

    TODO remove

    ", + "summary": "

    TODO remove

    ", + "body": "" + }, + "ignore": true, + "code": "exports.inGroupsOf = function inGroupsOf (card, arr, fn) {\n var group = [];\n for (var i = 0, l = arr.length; i < l; i++) {\n if (i && i % card === 0) {\n fn.apply(this, group);\n group.length = 0;\n }\n group.push(arr[i]);\n }\n fn.apply(this, group);\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "inGroupsOf", + "string": "exports.inGroupsOf()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "to", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "from", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges from into to without overwriting existing properties.

    ", + "summary": "

    Merges from into to without overwriting existing properties.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n merge(to[key], from[key]);\n }\n }\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "merge", + "string": "exports.merge()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.args = function (args, slice, sliceEnd) {\n var ret = [];\n var start = slice || 0;\n var end = 3 === arguments.length\n ? sliceEnd\n : args.length;\n\n for (var i = start; i < end; ++i) {\n ret[i - start] = args[i];\n }\n\n return ret;\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "args", + "string": "exports.args()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", + "summary": "

    process.nextTick helper.

    ", + "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "tick", + "string": "exports.tick()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "v", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", + "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", + "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isMongooseObject", + "string": "exports.isMongooseObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "object", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expiresAfterSeconds = when;\n delete object.expires;\n}\n\nexports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "expires", + "string": "exports.expires()" + } + } +] +### lib/virtualtype.js +[ + { + "tags": [ + { + "type": "parma", + "string": "{Object} options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", + "summary": "

    VirtualType constructor

    ", + "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", + "ctx": { + "type": "function", + "name": "VirtualType", + "string": "VirtualType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", + "summary": "

    Defines a getter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "get", + "string": "VirtualType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", + "summary": "

    Defines a setter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "set", + "string": "VirtualType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all getters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies getters to value using optional scope.

    ", + "summary": "

    Applies getters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applyGetters", + "string": "VirtualType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all setters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies setters to value using optional scope.

    ", + "summary": "

    Applies setters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applySetters", + "string": "VirtualType.prototype.applySetters()" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = VirtualType;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "VirtualType", + "string": "module.exports" + } + } +] diff --git a/docs/3.1.x/docs/source/api.js b/docs/3.1.x/docs/source/api.js new file mode 100644 index 00000000000..8fd87f0035b --- /dev/null +++ b/docs/3.1.x/docs/source/api.js @@ -0,0 +1,220 @@ +/*! + * Module dependencies + */ + +var fs = require('fs'); +var link = require('../helpers/linktype'); +var hl = require('highlight.js') +var md = require('markdown') + +module.exports = { + docs: [] + , github: 'https://github.com/LearnBoost/mongoose/tree/' + , title: 'API docs' +} + +var out = module.exports.docs; + +var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); +parse(docs); +order(out); + +function parse (docs) { + docs.split(/^### /gm).forEach(function (chunk) { + if (!(chunk = chunk.trim())) return; + + chunk = chunk.split(/^([^\n]+)\n/); + + var title = chunk[1]; + + if (!title || !(title = title.trim())) + throw new Error('missing title'); + + title = title.replace(/^lib\//, ''); + + var json = JSON.parse(chunk[2]); + + var props = []; + var methods = []; + var statics = []; + var constructor = null; + + json.forEach(function (comment) { + if (comment.description) + highlight(comment.description); + + var prop = false; + comment.params = []; + comment.see = []; + + var i = comment.tags.length; + while (i--) { + var tag = comment.tags[i]; + switch (tag.type) { + case 'property': + prop = true; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + props.unshift(comment); + break; + case 'method': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'method'; + comment.code = ''; + break; + case 'memberOf': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.constructor = tag.parent; + break; + case 'static': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + comment.ctx.type = 'method'; + break; + case 'receiver': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.receiver = tag.string; + break; + case 'constructor': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'function'; + comment.code = ''; + break; + case 'inherits': + if (/http/.test(tag.string)) { + var result = tag.string.split(' '); + var href = result.pop(); + var title = result.join(' '); + comment.inherits = '' + title + ''; + } else { + comment.inherits = link(tag.string); + } + comment.tags.splice(i, 1); + break; + case 'param': + comment.params.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'return': + comment.return = tag; + comment.tags.splice(i, 1); + break; + case 'see': + if (tag.local) { + var parts = tag.local.split(' '); + if (1 === parts.length) { + tag.url = link.type(parts[0]); + tag.title = parts[0]; + } else { + tag.url = parts.pop(); + tag.title = parts.join(' '); + } + } + comment.see.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'event': + var str = tag.string.replace(/\\n/g, '\n'); + tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); + comment.events || (comment.events = []); + comment.events.unshift(tag); + comment.tags.splice(i, 1); + } + } + + if (!prop) { + methods.push(comment); + } + }); + + methods = methods.filter(ignored); + props = props.filter(ignored); + + function ignored (method) { + if (method.ignore) return false; + return true; + } + + if (0 === methods.length + props.length) return; + + // add constructor to properties too + methods.some(function (method) { + if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { + props.forEach(function (prop) { + prop.ctx.constructor = method.ctx.constructor; + }); + return true; + } + return false; + }); + + var len = methods.length; + while (len--) { + method = methods[len]; + if (method.ctx && method.ctx.receiver) { + var stat = methods.splice(len, 1)[0]; + statics.unshift(stat); + } + } + + out.push({ + title: title + , methods: methods + , props: props + , statics: statics + , hasPublic: hasPublic(methods, props, statics) + }); + }); +} + +function hasPublic () { + for (var i = 0; i < arguments.length; ++i) { + var arr = arguments[i]; + for (var j = 0; j < arr.length; ++j) { + var item = arr[j]; + if (!item.ignore && !item.isPrivate) return true; + } + } + return false; +} + +// add "class='language'" to our
     elements
    +function highlight (o) {
    +  o.full = fix(o.full);
    +  o.summary = fix(o.summary);
    +  o.body = fix(o.body);
    +}
    +
    +function fix (str) {
    +  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    +
    +    // parse out the ```language
    +    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    +
    +    if ('js' == code[1] || !code[1]) {
    +      code[1] = 'javascript';
    +    }
    +
    +    return $1
    +          + hl.highlight(code[1], code[2]).value.trim()
    +          + $3;
    +  });
    +}
    +
    +function order (docs) {
    +  // want index first
    +  for (var i = 0; i < docs.length; ++i) {
    +    if ('index.js' == docs[i].title) {
    +      docs.unshift(docs.splice(i, 1)[0]);
    +    }
    +  }
    +}
    diff --git a/docs/3.1.x/docs/source/home.js b/docs/3.1.x/docs/source/home.js
    new file mode 100644
    index 00000000000..557f27b966b
    --- /dev/null
    +++ b/docs/3.1.x/docs/source/home.js
    @@ -0,0 +1,19 @@
    +
    +var fs = require('fs')
    +var package = require('./../../package.json')
    +var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    +
    +var imgs = [];
    +
    +images.forEach(function (line) {
    +  line = line.trim();
    +  if (!line) return;
    +  line = line.split('|');
    +  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    +});
    +
    +module.exports = {
    +    package: package
    +  , images: imgs
    +  , title: 'ODM'
    +}
    diff --git a/docs/3.1.x/docs/source/index.js b/docs/3.1.x/docs/source/index.js
    new file mode 100644
    index 00000000000..d54229720a1
    --- /dev/null
    +++ b/docs/3.1.x/docs/source/index.js
    @@ -0,0 +1,18 @@
    +
    +exports['index.jade'] = require('./home')
    +exports['docs/api.jade'] = require('./api')
    +exports['docs/index.jade'] = { title: 'Getting Started' }
    +exports['docs/prior.jade'] = require('./prior')
    +exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    +exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    +exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    +exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    +exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    +exports['docs/models.jade'] = { guide: true, title: 'Models' }
    +exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    +exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    +exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    +exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    +exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    +exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    +exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.1.x/docs/source/prior.js b/docs/3.1.x/docs/source/prior.js
    new file mode 100644
    index 00000000000..2e03811d215
    --- /dev/null
    +++ b/docs/3.1.x/docs/source/prior.js
    @@ -0,0 +1,13 @@
    +var fs = require('fs')
    +var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    +releases = releases.split('\n').filter(Boolean);
    +
    +module.exports = exports = {
    +    title: ''
    +  , releases: releases.map(function (version) {
    +      return {
    +          url: version + '/'
    +        , version: version
    +      }
    +    })
    +}
    diff --git a/docs/3.1.x/docs/subdocs.html b/docs/3.1.x/docs/subdocs.html
    new file mode 100644
    index 00000000000..626749164c2
    --- /dev/null
    +++ b/docs/3.1.x/docs/subdocs.html
    @@ -0,0 +1,49 @@
    +Mongoose SubDocuments v3.1.2Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    +
    +var parentSchema = new Schema({
    +  children: [childSchema]
    +})
    +

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = db.model('Parent', parentSchema);
    +var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    +parent.children[0].name = 'Matthew';
    +parent.save(callback);
    +

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    +  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    +  next();
    +});
    +
    +var parent = new Parent({ children: [{ name: 'invalid' }] });
    +parent.save(function (err) {
    +  console.log(err.message) // #sadpanda
    +})
    +

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    +

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = db.model('Parent');
    +var parent = new Parent;
    +
    +// create a comment
    +post.children.push({ name: 'Liesl' });
    +var doc = post.children[0];
    +console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    +doc.isNew; // true
    +
    +post.save(function (err) {
    +  if (err) return handleError(err)
    +  console.log('Success!');
    +});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    +

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    +parent.save(function (err) {
    +  if (err) return handleError(err);
    +  console.log('the sub-doc was removed')
    +});
    +

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    +  children: [{ name: 'string' }]
    +})
    +

    Next Up

    Now that we've covered Sub-documents, let's take a look at Models.

    diff --git a/docs/3.1.x/docs/subdocs.jade b/docs/3.1.x/docs/subdocs.jade new file mode 100644 index 00000000000..81b63ec2647 --- /dev/null +++ b/docs/3.1.x/docs/subdocs.jade @@ -0,0 +1,84 @@ +extends layout + +block content + h2 Sub Docs + :markdown + [Sub-documents](./api.html#types-embedded-js) are docs with schemas of their own which are elements of a parents document array: + :js + var childSchema = new Schema({ name: 'string' }); + + var parentSchema = new Schema({ + children: [childSchema] + }) + + :markdown + Sub-documents enjoy all the same features as normal [documents](./api.html#document-js). The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved. + :js + var Parent = db.model('Parent', parentSchema); + var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) + parent.children[0].name = 'Matthew'; + parent.save(callback); + + :markdown + If an error occurs in a sub-documents' middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap! + + :js + childSchema.pre('save', function (next) { + if ('invalid' == this.name) return next(new Error('#sadpanda')); + next(); + }); + + var parent = new Parent({ children: [{ name: 'invalid' }] }); + parent.save(function (err) { + console.log(err.message) // #sadpanda + }) + + h3 Finding a sub-document + :markdown + Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. + :js + var doc = parent.children.id(id); + + h3 Adding sub-docs + :markdown + MongooseArray methods such as [push](./api.html#types_array_MongooseArray-push), [unshift](./api.html#types_array_MongooseArray-unshift), [addToSet](./api.html#types_array_MongooseArray-addToSet), and others cast arguments to their proper types transparently: + :js + var Parent = db.model('Parent'); + var parent = new Parent; + + // create a comment + post.children.push({ name: 'Liesl' }); + var doc = post.children[0]; + console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' } + doc.isNew; // true + + post.save(function (err) { + if (err) return handleError(err) + console.log('Success!'); + }); + :markdown + Sub-docs may also be created without adding them to the array by using the [create](./api.html#types_documentarray_MongooseDocumentArray-create) method of MongooseArrays. + :js + var newdoc = post.children.create({ name: 'Aaron' }); + + h3 Removing docs + :markdown + Each sub-document has it's own [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. + :js + var doc = parent.children.id(id).remove(); + parent.save(function (err) { + if (err) return handleError(err); + console.log('the sub-doc was removed') + }); + + h4#altsyntax Alternate declaration syntax + :markdown + _New in v3_ If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal: + :js + var parentSchema = new Schema({ + children: [{ name: 'string' }] + }) + + h3#next Next Up + :markdown + Now that we've covered `Sub-documents`, let's take a look at [Models](/docs/models.html). diff --git a/docs/3.1.x/docs/validation.html b/docs/3.1.x/docs/validation.html new file mode 100644 index 00000000000..e63f1112399 --- /dev/null +++ b/docs/3.1.x/docs/validation.html @@ -0,0 +1,37 @@ +Mongoose Validation v3.1.2Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    + +
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    + +

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    +  color: String,
    +  name: String
    +});
    +
    +var Toy = db.model('Toy', toySchema);
    +
    +Toy.schema.path('color').validate(function (value) {
    +  return /blue|green|white|red|orange|periwinkel/i.test(value);
    +}, 'Invalid color');
    +
    +var toy = new Toy({ color: 'grease'});
    +
    +toy.save(function (err) {
    +  // err.errors.color is a ValidatorError object
    +  
    +  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(err.errors.color.type) // prints "Invalid color"
    +  console.log(err.errors.color.path) // prints "color"
    +  console.log(err.name) // prints "ValidationError"
    +  console.log(err.message) // prints "Validation failed"
    +});
    +

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    +

    Next Up

    Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

    diff --git a/docs/3.1.x/docs/validation.jade b/docs/3.1.x/docs/validation.jade new file mode 100644 index 00000000000..5b267bf95a5 --- /dev/null +++ b/docs/3.1.x/docs/validation.jade @@ -0,0 +1,58 @@ +extends layout + +block content + h2 Validation + :markdown + Before we get into the specifics of validation syntax, please keep the following rules in mind: + + - Validation is defined in the [SchemaType](./schematypes.html) + - Validation is an internal piece of [middleware](./middleware.html) + - Validation occurs when a document attempts to be [saved](./api.html#model_Model-save), after defaults have been applied + - Validation is asynchronously recursive: when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed. If an error happens, your Model#save callback receives it + - Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, `"min"` is the identifier for the error triggered when a number doesn't meet the [minimum value](./api.html#schema_number_SchemaNumber-min). The path and value that triggered the error can be accessed in the `ValidationError` object + h3 Built in validators + :markdown + Mongoose has several built in validators. + + - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. + - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. + - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum) and [match](./api.html#schema_string_SchemaString-match) validators. + h3 Custom validators + :markdown + Custom validation is declared by passing a validation `function` and an error type to your `SchemaType`s validate method. Read the [API](./api.html#schematype_SchemaType-validate) docs for details on custom validators, async validators, and more. + h3 Validation errors + :markdown + Errors returned after failed validation contain an `errors` object holding the actual `ValidatorErrors`. Each [ValidatorError](./api.html#errors-validation-js) has a `type` and `path` property providing us with a little more error handling flexibility. + :js + var toySchema = new Schema({ + color: String, + name: String + }); + + var Toy = db.model('Toy', toySchema); + + Toy.schema.path('color').validate(function (value) { + return /blue|green|white|red|orange|periwinkel/i.test(value); + }, 'Invalid color'); + + var toy = new Toy({ color: 'grease'}); + + toy.save(function (err) { + // err.errors.color is a ValidatorError object + + console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color' + console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color' + console.log(err.errors.color.type) // prints "Invalid color" + console.log(err.errors.color.path) // prints "color" + console.log(err.name) // prints "ValidationError" + console.log(err.message) // prints "Validation failed" + }); + + :markdown + After a validation error, the document will also have the same `errors` property available: + :js + toy.errors.color.message === err.errors.color.message + + h3#next Next Up + :markdown + Now that we've covered `validation`, let's take a look at how you might handle advanced validation with Mongoose's [middleware](/docs/middleware.html). diff --git a/docs/3.1.x/index.html b/docs/3.1.x/index.html new file mode 100644 index 00000000000..a582e9ec15a --- /dev/null +++ b/docs/3.1.x/index.html @@ -0,0 +1,238 @@ +Mongoose ODM v3.1.2Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

    var mongoose = require('mongoose');
    +var db = mongoose.createConnection('localhost', 'test');
    +
    +var schema = mongoose.Schema({ name: 'string' });
    +var Cat = db.model('Cat', schema);
    +
    +var kitty = new Cat({ name: 'Zildjian' });
    +kitty.save(function (err) {
    +  if (err) // ...
    +  res.end('meow');
    +});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    diff --git a/docs/3.1.x/static.js b/docs/3.1.x/static.js new file mode 100644 index 00000000000..fc0e722dd4e --- /dev/null +++ b/docs/3.1.x/static.js @@ -0,0 +1,17 @@ + +var static = require('node-static'); +var server = new static.Server('.', { cache: 0 }); + +require('http').createServer(function (req, res) { + req.on('end', function () { + server.serve(req, res, function (err) { + if (err) { + console.error(err, req.url); + res.writeHead(err.status, err.headers); + res.end(); + } + }); + }); +}).listen(8088); + +console.error('now listening on localhost:8088'); diff --git a/docs/3.2.x/docs/api.html b/docs/3.2.x/docs/api.html new file mode 100644 index 00000000000..43af3458afe --- /dev/null +++ b/docs/3.2.x/docs/api.html @@ -0,0 +1,6828 @@ +Mongoose API v3.2.2Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      +  this.connections = [];
      +  this.plugins = [];
      +  this.models = {};
      +  this.modelSchemas = {};
      +  this.options = {};
      +  this.createConnection(); // default connection
      +};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +  this.options[key] = value;
      +  return this;
      +};

      Parameters:

      Example:

      + +
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      + +
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri], [options])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      +  var conn = new Connection(this);
      +  this.connections.push(conn);
      +
      +  if (arguments.length) {
      +    if (rgxReplSet.test(arguments[0])) {
      +      conn.openSet.apply(conn, arguments);
      +    } else {
      +      conn.open.apply(conn, arguments);
      +    }
      +  }
      +
      +  return conn;
      +};

      Parameters:

      • [uri] <String> a mongodb:// URI
      • [options] <Object> options to pass to the driver

      Returns:

      Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

      + +

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

      + +

      Example:

      + +
      // with mongodb:// URI
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
      +
      +// and options
      +var opts = { db: { native_parser: true }}
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
      +
      +// replica sets
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
      +
      +// and options
      +var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
      +
      +// with [host, database_name[, port] signature
      +db = mongoose.createConnection('localhost', 'database', port)
      +
      +// and options
      +var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
      +db = mongoose.createConnection('localhost', 'database', port, opts)
      +
      +// initialize now, connect later
      +db = mongoose.createConnection();
      +db.open('localhost', 'database', port, [opts]);

      Mongoose#connect()

      Opens the default mongoose connection.

      show code
      Mongoose.prototype.connect = function () {
      +  var conn = this.connection;
      +
      +  if (rgxReplSet.test(arguments[0])) {
      +    conn.openSet.apply(conn, arguments);
      +  } else {
      +    conn.open.apply(conn, arguments);
      +  }
      +
      +  return this;
      +};

      Returns:

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


      Mongoose#disconnect([fn])

      Disconnects all connections.

      show code
      Mongoose.prototype.disconnect = function (fn) {
      +  var count = this.connections.length
      +    , error
      +
      +  this.connections.forEach(function(conn){
      +    conn.close(function(err){
      +      if (error) return;
      +
      +      if (err) {
      +        error = err;
      +        if (fn) return fn(err);
      +        throw err;
      +      }
      +
      +      if (fn)
      +        --count || fn();
      +    });
      +  });
      +  return this;
      +};

      Parameters:

      • [fn] <Function> called after all connection close.

      Returns:


      Mongoose#model(name, [schema], [collection], [skipInit])

      Defines a model or retrieves it.

      show code
      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
      +  // normalize collection
      +  if (!(schema instanceof Schema)) {
      +    collection = schema;
      +    schema = false;
      +  }
      +
      +  if ('boolean' === typeof collection) {
      +    skipInit = collection;
      +    collection = null;
      +  }
      +
      +  // look up models for the collection
      +  if (!this.modelSchemas[name]) {
      +    if (!schema && name in SchemaDefaults) {
      +      schema = SchemaDefaults[name];
      +    }
      +
      +    if (schema) {
      +      this.modelSchemas[name] = schema;
      +      for (var i = 0, l = this.plugins.length; i < l; i++) {
      +        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
      +      }
      +    } else {
      +      throw new Error('Schema hasn\'t been registered for model "' + name + '".
      +'
      +                    + 'Use mongoose.model(name, schema)');
      +    }
      +  }
      +
      +  if (!this.models[name]) {
      +    schema || (schema = this.modelSchemas[name]);
      +    collection || (collection = schema.set('collection') || format(name));
      +
      +    var model = Model.compile(name
      +                        , this.modelSchemas[name]
      +                        , collection
      +                        , this.connection
      +                        , this);
      +
      +    if (!skipInit) model.init();
      +
      +    this.models[name] = model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> model name
      • [schema] <Schema>
      • [collection] <String> name (optional, induced from model name)
      • [skipInit] <Boolean> whether to skip initialization (defaults to false)

      Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +
      +// define an Actor model with this mongoose instance
      +mongoose.model('Actor', new Schema({ name: String }));
      +
      +// create a new connection
      +var conn = mongoose.createConnection(..);
      +
      +// retrieve the Actor model
      +var Actor = conn.model('Actor');
      + +

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

      + +

      Example:

      + +
      var schema = new Schema({ name: String });
      +schema.set('collection', 'actor');

      Mongoose#plugin(fn, [opts])

      Declares a global plugin executed on all Schemas.

      show code
      Mongoose.prototype.plugin = function (fn, opts) {
      +  this.plugins.push([fn, opts]);
      +  return this;
      +};

      Parameters:

      Returns:

      Equivalent to calling .plugin(fn) on each Schema you create.


      module.exports

      The exports object is an instance of Mongoose.

      show code
      module.exports = exports = new Mongoose;
      +var mongoose = module.exports;

      mongoose.Collection

      The Mongoose Collection constructor

      show code
      mongoose.Collection = Collection;

      mongoose.Connection

      The Mongoose Connection constructor

      show code
      mongoose.Connection = Connection;

      mongoose.version

      Mongoose version

      show code
      mongoose.version = JSON.parse(
      +  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      +).version;

      mongoose.Mongoose

      The Mongoose constructor

      show code
      mongoose.Mongoose = Mongoose;

      The exports of the mongoose module is an instance of this class.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var mongoose2 = new mongoose.Mongoose();

      mongoose.Schema

      The Mongoose Schema constructor

      show code
      mongoose.Schema = Schema;

      Example:

      + +
      var mongoose = require('mongoose');
      +var Schema = mongoose.Schema;
      +var CatSchema = new Schema(..);

      mongoose.SchemaType

      The Mongoose SchemaType constructor.

      show code
      mongoose.SchemaType = SchemaType;

      mongoose.SchemaTypes

      The various Mongoose SchemaTypes.

      show code
      mongoose.SchemaTypes = Schema.Types;

      Note:

      + +

      Alias of mongoose.Schema.Types for backwards compatibility.


      mongoose.VirtualType

      The Mongoose VirtualType constructor.

      show code
      mongoose.VirtualType = VirtualType;

      mongoose.Types

      The various Mongoose Types.

      show code
      mongoose.Types = Types;

      Example:

      + +
      var mongoose = require('mongoose');
      +var array = mongoose.Types.Array;
      + +

      Types:

      + +
        +
      • Array
      • +
      • Buffer
      • +
      • Document
      • +
      • Embedded
      • +
      • DocumentArray
      • +
      • ObjectId
      • +
      + +

      Using this exposed access to the ObjectId type, we can construct ids on demand.

      + +
      var ObjectId = mongoose.Types.ObjectId;
      +var id1 = new ObjectId;

      mongoose.Query

      The Mongoose Query constructor.

      show code
      mongoose.Query = Query;

      mongoose.Promise

      The Mongoose Promise constructor.

      show code
      mongoose.Promise = Promise;

      mongoose.Model

      The Mongoose Model constructor.

      show code
      mongoose.Model = Model;

      mongoose.Document

      The Mongoose Document constructor.

      show code
      mongoose.Document = Document;

      mongoose.Error

      The MongooseError constructor.

      show code
      mongoose.Error = require('./error');

      mongoose.mongo

      The node-mongodb-native driver Mongoose uses.

      show code
      mongoose.mongo = require('mongodb');

      Mongoose#connection

      The default connection of the mongoose module.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +mongoose.connect(...);
      +mongoose.connection.on('error', cb);
      + +

      This is the connection used by default for every model created using mongoose.model.

      Returns:


    • collection.js

      Collection(name, conn, opts)

      Abstract Collection constructor

      show code
      function Collection (name, conn, opts) {
      +  this.name = name;
      +  this.conn = conn;
      +  this.buffer = true;
      +  this.queue = [];
      +
      +  if ('number' == typeof opts) opts = { size: opts };
      +  this.opts = opts || {};
      +
      +  if (STATES.connected == this.conn.readyState) {
      +    this.onOpen();
      +  }
      +};

      Parameters:

      • name <String> name of the collection
      • conn <Connection> A MongooseConnection instance
      • opts <Object> optional collection options

      This is the base class that drivers inherit from and implement.


      Collection#onOpen()

      Called when the database connects

      show code
      Collection.prototype.onOpen = function () {
      +  var self = this;
      +  this.buffer = false;
      +  self.doQueue();
      +};

      Collection#onClose()

      Called when the database disconnects

      show code
      Collection.prototype.onClose = function () {
      +  this.buffer = true;
      +};

      Collection#addQueue(name, args)

      Queues a method for later execution when its
      database connection opens.

      show code
      Collection.prototype.addQueue = function (name, args) {
      +  this.queue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the method to queue
      • args <Array> arguments to pass to the method when executed

      Collection#doQueue()

      Executes all queued methods and clears the queue.

      show code
      Collection.prototype.doQueue = function () {
      +  for (var i = 0, l = this.queue.length; i < l; i++){
      +    this[this.queue[i][0]].apply(this, this.queue[i][1]);
      +  }
      +  this.queue = [];
      +  return this;
      +};

      Collection#ensureIndex()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.ensureIndex = function(){
      +  throw new Error('Collection#ensureIndex unimplemented by driver');
      +};

      Collection#findAndModify()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findAndModify = function(){
      +  throw new Error('Collection#findAndModify unimplemented by driver');
      +};

      Collection#findOne()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findOne = function(){
      +  throw new Error('Collection#findOne unimplemented by driver');
      +};

      Collection#find()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.find = function(){
      +  throw new Error('Collection#find unimplemented by driver');
      +};

      Collection#insert()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.insert = function(){
      +  throw new Error('Collection#insert unimplemented by driver');
      +};

      Collection#save()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.save = function(){
      +  throw new Error('Collection#save unimplemented by driver');
      +};

      Collection#update()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.update = function(){
      +  throw new Error('Collection#update unimplemented by driver');
      +};

      Collection#getIndexes()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.getIndexes = function(){
      +  throw new Error('Collection#getIndexes unimplemented by driver');
      +};

      Collection#mapReduce()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.mapReduce = function(){
      +  throw new Error('Collection#mapReduce unimplemented by driver');
      +};

      Collection#conn

      The Connection instance


      Collection#name

      The collection name


    • connection.js

      Connection(base)

      Connection constructor

      show code
      function Connection (base) {
      +  this.base = base;
      +  this.collections = {};
      +  this.models = {};
      +  this.replica = false;
      +  this.host = null;
      +  this.port = null;
      +  this.user = null;
      +  this.pass = null;
      +  this.name = null;
      +  this.options = null;
      +  this._readyState = STATES.disconnected;
      +  this._closeCalled = false;
      +  this._hasOpened = false;
      +};

      Parameters:

      Events:

      • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

      • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

      • open: Emitted after we connected and onOpen is executed on all of this connections models.

      • disconnecting: Emitted when connection.close() was executed.

      • disconnected: Emitted after getting disconnected from the db.

      • close: Emitted after we disconnected and onClose executed on all of this connections models.

      • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

      • error: Emitted when an error occurs on this connection.

      • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

      For practical reasons, a Connection equals a Db.


      Connection#open(connection_string, [database], [port], [options], [callback])

      Opens the connection to MongoDB.

      show code
      Connection.prototype.open = function (host, database, port, options, callback) {
      +  var self = this
      +    , uri;
      +
      +  if ('string' === typeof database) {
      +    switch (arguments.length) {
      +      case 2:
      +        port = 27017;
      +      case 3:
      +        switch (typeof port) {
      +          case 'function':
      +            callback = port, port = 27017;
      +            break;
      +          case 'object':
      +            options = port, port = 27017;
      +            break;
      +        }
      +        break;
      +      case 4:
      +        if ('function' === typeof options)
      +          callback = options, options = {};
      +    }
      +  } else {
      +    switch (typeof database) {
      +      case 'function':
      +        callback = database, database = undefined;
      +        break;
      +      case 'object':
      +        options = database;
      +        database = undefined;
      +        callback = port;
      +        break;
      +    }
      +
      +    if (!rgxProtocol.test(host)) {
      +      host = 'mongodb://' + host;
      +    }
      +
      +    uri = url.parse(host);
      +    host = uri.hostname;
      +    port = uri.port || 27017;
      +    database = uri.pathname && uri.pathname.replace(/\//g, '');
      +  }
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // make sure we can open
      +  if (STATES.disconnected !== this.readyState) {
      +    var err = new Error('Trying to open unclosed connection.');
      +    err.state = this.readyState;
      +    this.error(err, callback);
      +    return this;
      +  }
      +
      +  if (!host) {
      +    this.error(new Error('Missing connection hostname.'), callback);
      +    return this;
      +  }
      +
      +  if (!database) {
      +    this.error(new Error('Missing connection database.'), callback);
      +    return this;
      +  }
      +
      +  // handle authentication
      +  if (uri && uri.auth) {
      +    var auth = uri.auth.split(':');
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // Check hostname for user/pass
      +  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
      +    host = host.split('@');
      +    var auth = host.shift().split(':');
      +    host = host.pop();
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // user/pass options
      +  } else if (options && options.user && options.pass) {
      +    this.user = options.user;
      +    this.pass = options.pass;
      +
      +  } else {
      +    this.user = this.pass = undefined;
      +  }
      +
      +  this.name = database;
      +  this.host = host;
      +  this.port = port;
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • connection_string <String> mongodb://uri or the host to which you are connecting
      • [database] <String> database name
      • [port] <Number> database port
      • [options] <Object> options
      • [callback] <Function>

      options is a hash with the following possible properties:

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSet instance
      +user    - username for authentication
      +pass    - password for authentication
      + +

      Notes:

      + +

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.


      Connection#openSet(uris, [database], [options], [callback])

      Connects to a replica set.

      show code
      Connection.prototype.openSet = function (uris, database, options, callback) {
      +  var uris = uris.split(',')
      +    , self = this;
      +
      +  switch (arguments.length) {
      +    case 3:
      +      this.name = database;
      +      if ('function' === typeof options) callback = options, options = {};
      +      break;
      +    case 2:
      +      switch (typeof database) {
      +        case 'string':
      +          this.name = database;
      +        case 'function':
      +          callback = database, database = null;
      +          break;
      +        case 'object':
      +          options = database, database = null;
      +          break;
      +      }
      +  }
      +
      +  this.options = options = this.defaultOptions(options);
      +
      +  if (uris.length < 2) {
      +    this.error(new Error('Please provide comma-separated URIs'), callback);
      +    return this;
      +  }
      +
      +  this.replica = true;
      +  this.host = [];
      +  this.port = [];
      +
      +  uris.forEach(function (uri) {
      +    // handle missing protocols
      +    if (!rgxProtocol.test(uri))
      +      uri = 'mongodb://' + uri;
      +
      +    var uri = url.parse(uri);
      +
      +    self.host.push(uri.hostname);
      +    self.port.push(uri.port || 27017);
      +
      +    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
      +      self.name = uri.pathname.replace(/\//g, '');
      +
      +    if (!self.user && uri.auth) {
      +      var auth = uri.auth.split(':');
      +      self.user = auth[0];
      +      self.pass = auth[1];
      +    }
      +  });
      +
      +  if (!this.name) {
      +    this.error(new Error('No database name provided for replica set'), callback);
      +    return this;
      +  }
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • uris <String> comma-separated mongodb:// `URI`s
      • [database] <String> database name if not included in `uris`
      • [options] <Object> passed to the internal driver
      • [callback] <Function>

      Example:

      + +
      var db = mongoose.createConnection();
      +db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
      + +

      The database name and/or auth need only be included in one URI.
      The options is a hash which is passed to the internal driver connection object.

      + +

      Valid options

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSetServer instance
      +user    - username for authentication
      +pass    - password for authentication

      Connection#error(err, callback)

      error

      show code
      Connection.prototype.error = function (err, callback) {
      +  if (callback) return callback(err);
      +  this.emit('error', err);
      +}

      Parameters:

      Graceful error handling, passes error to callback
      if available, else emits error on the connection.


      Connection#_open(callback)

      Handles opening the connection with the appropriate method based on connection type.

      show code
      Connection.prototype._open = function (callback) {
      +  this.readyState = STATES.connecting;
      +  this._closeCalled = false;
      +
      +  var self = this;
      +
      +  var method = this.replica
      +    ? 'doOpenSet'
      +    : 'doOpen';
      +
      +  // open connection
      +  this[method](function (err) {
      +    if (err) {
      +      self.readyState = STATES.disconnected;
      +      if (self._hasOpened) {
      +        if (callback) callback(err);
      +      } else {
      +        self.error(err, callback);
      +      }
      +      return;
      +    }
      +
      +    self.onOpen();
      +    callback && callback();
      +  });
      +}

      Parameters:


      Connection#onOpen()

      Called when the connection is opened

      show code
      Connection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  function open () {
      +    self.readyState = STATES.connected;
      +
      +    // avoid having the collection subscribe to our event emitter
      +    // to prevent 0.3 warning
      +    for (var i in self.collections)
      +      self.collections[i].onOpen();
      +
      +    self.emit('open');
      +  };
      +
      +  // re-authenticate
      +  if (self.user && self.pass)
      +    self.db.authenticate(self.user, self.pass, open);
      +  else
      +    open();
      +};

      Connection#close([callback])

      Closes the connection

      show code
      Connection.prototype.close = function (callback) {
      +  var self = this;
      +  this._closeCalled = true;
      +
      +  switch (this.readyState){
      +    case 0: // disconnected
      +      callback && callback();
      +      break;
      +
      +    case 1: // connected
      +      this.readyState = STATES.disconnecting;
      +      this.doClose(function(err){
      +        if (err){
      +          self.error(err, callback);
      +        } else {
      +          self.onClose();
      +          callback && callback();
      +        }
      +      });
      +      break;
      +
      +    case 2: // connecting
      +      this.once('open', function(){
      +        self.close(callback);
      +      });
      +      break;
      +
      +    case 3: // disconnecting
      +      if (!callback) break;
      +      this.once('close', function () {
      +        callback();
      +      });
      +      break;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Connection#onClose()

      Called when the connection closes

      show code
      Connection.prototype.onClose = function () {
      +  this.readyState = STATES.disconnected;
      +
      +  // avoid having the collection subscribe to our event emitter
      +  // to prevent 0.3 warning
      +  for (var i in this.collections)
      +    this.collections[i].onClose();
      +
      +  this.emit('close');
      +};

      Connection#collection(name, [options])

      Retrieves a collection, creating it if not cached.

      show code
      Connection.prototype.collection = function (name, options) {
      +  if (!(name in this.collections))
      +    this.collections[name] = new Collection(name, this, options);
      +  return this.collections[name];
      +};

      Parameters:

      • name <String> of the collection
      • [options] <Object> optional collection options

      Returns:


      Connection#model(name, [schema], [collection])

      Defines or retrieves a model.

      show code
      Connection.prototype.model = function (name, schema, collection) {
      +  if (!this.models[name]) {
      +    var model = this.base.model(name, schema, collection, true)
      +      , Model
      +
      +    if (this != model.prototype.db) {
      +      // subclass model using this connection and collection name
      +      Model = function Model (doc, fields, skipId) {
      +        if (!(this instanceof Model))
      +          return new Model(doc, fields, skipId);
      +        model.call(this, doc, fields, skipId);
      +      };
      +
      +      Model.__proto__ = model;
      +      Model.prototype.__proto__ = model.prototype;
      +      Model.db = Model.prototype.db = this;
      +
      +      // collection name discovery
      +      if ('string' === typeof schema) {
      +        collection = schema;
      +      }
      +
      +      if (!collection) {
      +        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
      +      }
      +
      +      var s = 'string' != typeof schema
      +        ? schema
      +        : model.prototype.schema;
      +
      +      Model.prototype.collection = this.collection(collection, s && s.options.capped);
      +      Model.collection = Model.prototype.collection;
      +      Model.init();
      +    }
      +
      +    this.models[name] = Model || model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> the model name
      • [schema] <Schema> a schema. necessary when defining a model
      • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

      Returns:

      • <Model> The compiled model
      var mongoose = require('mongoose');
      +var db = mongoose.createConnection(..);
      +db.model('Venue', new Schema(..));
      +var Ticket = db.model('Ticket', new Schema(..));
      +var Venue = db.model('Venue');

      Connection#setProfiling(level, [ms], callback)

      Set profiling level.

      show code
      Connection.prototype.setProfiling = function (level, ms, callback) {
      +  if (STATES.connected !== this.readyState) {
      +    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
      +  }
      +
      +  if (!callback) callback = ms, ms = 100;
      +
      +  var cmd = {};
      +
      +  switch (level) {
      +    case 0:
      +    case 'off':
      +      cmd.profile = 0;
      +      break;
      +    case 1:
      +    case 'slow':
      +      cmd.profile = 1;
      +      if ('number' !== typeof ms) {
      +        ms = parseInt(ms, 10);
      +        if (isNaN(ms)) ms = 100;
      +      }
      +      cmd.slowms = ms;
      +      break;
      +    case 2:
      +    case 'all':
      +      cmd.profile = 2;
      +      break;
      +    default:
      +      return callback(new Error('Invalid profiling level: '+ level));
      +  }
      +
      +  this.db.executeDbCommand(cmd, function (err, resp) {
      +    if (err) return callback(err);
      +
      +    var doc = resp.documents[0];
      +
      +    err = 1 === doc.ok
      +      ? null
      +      : new Error('Could not set profiling level to: '+ level)
      +
      +    callback(err, doc);
      +  });
      +};

      Parameters:

      • level <Number, String> either off (0), slow (1), or all (2)
      • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
      • callback <Function>

      Connection#defaultOptions(options)

      Prepares default connection options.

      show code
      Connection.prototype.defaultOptions = function (options) {
      +  var o = options || {};
      +
      +  o.server = o.server || {};
      +
      +  if (!('auto_reconnect' in o.server)) {
      +    o.server.auto_reconnect = true;
      +  }
      +
      +  o.db || (o.db = {});
      +  o.db.forceServerObjectId = false;
      +
      +  // TODO default to true once the driver is fixed
      +  if (!('safe' in o.db)) o.db.safe = false;
      +
      +  return o;
      +}

      Parameters:


      Connection#db

      The mongodb.Db instance, set when the connection is opened


      Connection#collections

      A hash of the collections associated with this connection


      Connection#readyState

      Connection ready state

      + +
        +
      • 0 = disconnected
      • +
      • 1 = connected
      • +
      • 2 = connecting
      • +
      • 3 = disconnecting
      • +
      + +

      Each state change emits its associated event name.

      + +

      Example

      + +
      conn.on('connected', callback);
      +conn.on('disconnected', callback);

    • document.js

      Document(obj, [fields], [skipId])

      Document constructor.

      show code
      function Document (obj, fields, skipId) {
      +  // node <0.4.3 bug
      +  if (!this._events) this._events = {};
      +  this.setMaxListeners(0);
      +
      +  if ('boolean' === typeof fields) {
      +    this._strictMode = fields;
      +    this._selected = fields = undefined;
      +  } else {
      +    this._strictMode = this.schema.options && this.schema.options.strict;
      +    this._selected = fields;
      +  }
      +
      +  this.isNew = true;
      +  this.errors = undefined;
      +  this._shardval = undefined;
      +  this._saveError = undefined;
      +  this._validationError = undefined;
      +  this._adhocPaths = undefined;
      +  this._removing = undefined;
      +  this._inserting = undefined;
      +  this.__version = undefined;
      +  this.__getters = {};
      +  this.__id = undefined;
      +
      +  this._activePaths = new ActiveRoster;
      +
      +  var required = this.schema.requiredPaths();
      +  for (var i = 0; i < required.length; ++i) {
      +    this._activePaths.require(required[i]);
      +  }
      +
      +  this._doc = this._buildDoc(obj, fields, skipId);
      +  if (obj) this.set(obj, undefined, true);
      +  this._registerHooks();
      +};

      Parameters:

      • obj <Object> the values to set
      • [fields] <Object> the fields which were selected in the query returning this document
      • [skipId] <Boolean> bool, should we auto create an ObjectId _id

      Events:

      • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

      • save: Emitted when the document is successfully saved


      Document#_buildDoc(obj, [fields], [skipId])

      Builds the default doc structure

      show code
      Document.prototype._buildDoc = function (obj, fields, skipId) {
      +  var doc = {}
      +    , self = this
      +    , exclude
      +    , keys
      +    , key
      +    , ki
      +
      +  // determine if this doc is a result of a query with
      +  // excluded fields
      +  if (fields && 'Object' === fields.constructor.name) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('_id' !== keys[ki]) {
      +        exclude = 0 === fields[keys[ki]];
      +        break;
      +      }
      +    }
      +  }
      +
      +  var paths = Object.keys(this.schema.paths)
      +    , plen = paths.length
      +    , ii = 0
      +
      +  for (; ii < plen; ++ii) {
      +    var p = paths[ii];
      +
      +    if ('_id' == p) {
      +      if (skipId) continue;
      +      if (obj && '_id' in obj) continue;
      +    }
      +
      +    var type = this.schema.paths[p]
      +      , path = p.split('.')
      +      , len = path.length
      +      , last = len-1
      +      , doc_ = doc
      +      , i = 0
      +
      +    for (; i < len; ++i) {
      +      var piece = path[i]
      +        , def
      +
      +      if (i === last) {
      +        if (fields) {
      +          if (exclude) {
      +            // apply defaults to all non-excluded fields
      +            if (p in fields) continue;
      +
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +
      +          } else if (p in fields) {
      +            // selected field
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +          }
      +        } else {
      +          def = type.getDefault(self, true);
      +          if ('undefined' !== typeof def) {
      +            doc_[piece] = def;
      +            self._activePaths.default(p);
      +          }
      +        }
      +      } else {
      +        doc_ = doc_[piece] || (doc_[piece] = {});
      +      }
      +    }
      +  };
      +
      +  return doc;
      +};

      Parameters:

      Returns:


      Document#init(doc, fn)

      Initializes the document without setters or marking anything modified.

      show code
      Document.prototype.init = function (doc, fn) {
      +  this.isNew = false;
      +
      +  init(this, doc, this._doc);
      +  this._storeShard();
      +
      +  this.emit('init');
      +  if (fn) fn(null);
      +  return this;
      +};

      Parameters:

      Called internally after a document is returned from mongodb.


      Document#_storeShard()

      Stores the current values of the shard keys.

      show code
      Document.prototype._storeShard = function _storeShard () {
      +  // backwards compat
      +  var key = this.schema.options.shardKey || this.schema.options.shardkey;
      +  if (!(key && 'Object' == key.constructor.name)) return;
      +
      +  var orig = this._shardval = {}
      +    , paths = Object.keys(key)
      +    , len = paths.length
      +    , val
      +
      +  for (var i = 0; i < len; ++i) {
      +    val = this.getValue(paths[i]);
      +    if (isMongooseObject(val)) {
      +      orig[paths[i]] = val.toObject({ depopulate: true })
      +    } else if (null != val && val.valueOf) {
      +      orig[paths[i]] = val.valueOf();
      +    } else {
      +      orig[paths[i]] = val;
      +    }
      +  }
      +}

      Note:

      + +

      Shard key values do not / are not allowed to change.


      Document#update(doc, options, callback)

      Sends an update command with this document _id as the query selector.

      show code
      Document.prototype.update = function update () {
      +  var args = utils.args(arguments);
      +  args.unshift({_id: this._id});
      +  this.constructor.update.apply(this.constructor, args);
      +}

      Parameters:

      Returns:

      Example:

      + +
      weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
      + +

      Valid options:

      + +
        +
      • safe safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +

      Document#set(path, val, [type])

      Sets the value of a path, or many paths.

      show code
      Document.prototype.set = function (path, val, type) {
      +  var constructing = true === type
      +    , adhoc = type && true !== type
      +    , adhocs
      +
      +  if (adhoc) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  if ('string' !== typeof path) {
      +    // new Document({ key: val })
      +
      +    if (null === path || undefined === path) {
      +      var _ = path;
      +      path = val;
      +      val = _;
      +
      +    } else {
      +      var prefix = val
      +        ? val + '.'
      +        : '';
      +
      +      if (path instanceof Document) path = path._doc;
      +
      +      var keys = Object.keys(path)
      +        , i = keys.length
      +        , pathtype
      +        , key
      +
      +      while (i--) {
      +        key = keys[i];
      +        if (null != path[key] && 'Object' === path[key].constructor.name
      +          && !(this._path(prefix + key) instanceof MixedSchema)) {
      +          this.set(path[key], prefix + key, constructing);
      +        } else if (this._strictMode) {
      +          pathtype = this.schema.pathType(prefix + key);
      +          if ('real' === pathtype || 'virtual' === pathtype) {
      +            this.set(prefix + key, path[key], constructing);
      +          } else if ('throw' == this._strictMode) {
      +            throw new Error("Field `" + key + "` is not in schema.");
      +          }
      +        } else if (undefined !== path[key]) {
      +          this.set(prefix + key, path[key], constructing);
      +        }
      +      }
      +
      +      return this;
      +    }
      +  }
      +
      +  // ensure _strict is honored for obj props
      +  // docschema = new Schema({ path: { nest: 'string' }})
      +  // doc.set('path', obj);
      +  var pathType = this.schema.pathType(path);
      +  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
      +    this.setValue(path, null);
      +    this.set(val, path, constructing);
      +    return this;
      +  }
      +
      +  var schema;
      +  if ('adhocOrUndefined' == pathType && this._strictMode) {
      +    return this;
      +  } else if ('virtual' == pathType) {
      +    schema = this.schema.virtualpath(path);
      +    schema.applySetters(val, this);
      +    return this;
      +  } else {
      +    schema = this._path(path);
      +  }
      +
      +  var parts = path.split('.')
      +    , pathToMark
      +
      +  // When using the $set operator the path to the field must already exist.
      +  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
      +
      +  if (parts.length <= 1) {
      +    pathToMark = path;
      +  } else {
      +    for (var i = 0; i < parts.length; ++i) {
      +      var part = parts[i];
      +      var subpath = parts.slice(0, i).concat(part).join('.');
      +      if (this.isDirectModified(subpath) // earlier prefixes that are already
      +                                         // marked as dirty have precedence
      +          || this.get(subpath) === null) {
      +        pathToMark = subpath;
      +        break;
      +      }
      +    }
      +
      +    if (!pathToMark) pathToMark = path;
      +  }
      +
      +  if (!schema || null === val || undefined === val) {
      +    this._set(pathToMark, path, constructing, parts, schema, val);
      +    return this;
      +  }
      +
      +  var self = this;
      +
      +  // if this doc is being constructed we should not
      +  // trigger getters.
      +  var priorVal = constructing
      +    ? undefined
      +    : this.get(path);
      +
      +  var shouldSet = this.try(function(){
      +    val = schema.applySetters(val, self, false, priorVal);
      +  });
      +
      +  if (shouldSet) {
      +    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
      +  }
      +
      +  return this;
      +}

      Parameters:

      Example:

      + +
      // path, value
      +doc.set(path, value)
      +
      +// object
      +doc.set({
      +    path  : value
      +  , path2 : {
      +       path  : value
      +    }
      +})
      +
      +// only-the-fly cast to number
      +doc.set(path, value, Number)
      +
      +// only-the-fly cast to string
      +doc.set(path, value, String)

      Document#_set()

      Handles the actual setting of the value and marking the path modified if appropriate.

      show code
      Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {
      +  if (this.isNew) {
      +    this.markModified(pathToMark);
      +  } else {
      +
      +    priorVal || (priorVal = this.get(path));
      +
      +    if (!this.isDirectModified(pathToMark)) {
      +      if (undefined === val && !this.isSelected(path)) {
      +        // special case:
      +        // when a path is not selected in a query its initial
      +        // value will be undefined.
      +        this.markModified(pathToMark, priorVal);
      +      } else if (undefined === val && path in this._activePaths.states.default) {
      +        // do nothing
      +        // unsetting the default value which was never saved
      +      } else if (!deepEqual(val, priorVal)) {
      +        this.markModified(pathToMark, priorVal);
      +      } else if (!constructing &&
      +                 null != val &&
      +                 path in this._activePaths.states.default &&
      +                 deepEqual(val, schema.getDefault(this, constructing))) {
      +        // special case:
      +        // a path with a default was $unset on the server
      +        // and the user is setting it to the same value again
      +        this.markModified(pathToMark, priorVal);
      +      }
      +    }
      +  }
      +
      +  var obj = this._doc
      +    , i = 0
      +    , l = parts.length
      +
      +  for (; i < l; i++) {
      +    var next = i + 1
      +      , last = next === l;
      +
      +    if (last) {
      +      obj[parts[i]] = val;
      +    } else {
      +      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
      +        obj = obj[parts[i]];
      +      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
      +        obj = obj[parts[i]];
      +      } else {
      +        obj = obj[parts[i]] = {};
      +      }
      +    }
      +  }
      +};

      Document#getValue(path)

      Gets a raw value from a path (no getters)

      show code
      Document.prototype.getValue = function (path) {
      +  var parts = path.split('.')
      +    , obj = this._doc
      +    , part;
      +
      +  for (var i = 0, l = parts.length; i < l; i++) {
      +    part = parts[i];
      +    obj = obj.getValue
      +        ? obj.getValue(part) // If we have an embedded array document member
      +        : obj[part];
      +    if (!obj) return obj;
      +  }
      +
      +  return obj;
      +}

      Parameters:


      Document#setValue(path, value)

      Sets a raw value for a path (no casting, setters, transformations)

      show code
      Document.prototype.setValue = function (path, val) {
      +  var parts = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, len = parts.length-1; i < len; i++) {
      +    obj = obj[parts[i]];
      +  }
      +
      +  obj[parts[len]] = val;
      +  return this;
      +};

      Parameters:


      Document#get(path, [type])

      Returns the value of a path.

      show code
      Document.prototype.get = function (path, type) {
      +  var adhocs;
      +  if (type) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  var schema = this._path(path) || this.schema.virtualpath(path)
      +    , pieces = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, l = pieces.length; i < l; i++) {
      +    obj = null == obj ? null : obj[pieces[i]];
      +  }
      +
      +  if (schema) {
      +    obj = schema.applyGetters(obj, this);
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Example

      + +
      // path
      +doc.get('age') // 47
      +
      +// dynamic casting to a string
      +doc.get('age', String) // "47"

      Document#_path(path)

      Returns the schematype for the given path.

      show code
      Document.prototype._path = function (path) {
      +  var adhocs = this._adhocPaths
      +    , adhocType = adhocs && adhocs[path];
      +
      +  if (adhocType) {
      +    return adhocType;
      +  } else {
      +    return this.schema.path(path);
      +  }
      +};

      Parameters:


      Document#markModified(path)

      Marks the path as having pending changes to write to the db.

      show code
      Document.prototype.markModified = function (path) {
      +  this._activePaths.modify(path);
      +};

      Parameters:

      • path <String> the path to mark modified

      Very helpful when using Mixed types.

      + +

      Example:

      + +
      doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');
      +doc.save() // changes to mixed.type are now persisted

      Document#try(fn, scope)

      Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

      show code
      Document.prototype.try = function (fn, scope) {
      +  var res;
      +  try {
      +    fn.call(scope);
      +    res = true;
      +  } catch (e) {
      +    this._error(e);
      +    res = false;
      +  }
      +  return res;
      +};

      Parameters:

      • fn <Function> function to execute
      • scope <Object> the scope with which to call fn

      Document#modifiedPaths()

      Returns the list of paths that have been modified.

      show code
      Document.prototype.modifiedPaths = function () {
      +  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
      +
      +  return directModifiedPaths.reduce(function (list, path) {
      +    var parts = path.split('.');
      +    return list.concat(parts.reduce(function (chains, part, i) {
      +      return chains.concat(parts.slice(0, i).concat(part).join('.'));
      +    }, []));
      +  }, []);
      +};

      Returns:


      Document#isModified([path])

      Returns true if this document was modified, else false.

      show code
      Document.prototype.isModified = function (path) {
      +  return path
      +    ? !!~this.modifiedPaths().indexOf(path)
      +    : this._activePaths.some('modify');
      +};

      Parameters:

      Returns:

      If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

      + +

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isModified()                    // true
      +doc.isModified('documents')         // true
      +doc.isModified('documents.0.title') // true
      +doc.isDirectModified('documents')   // false

      Document#isDirectModified(path)

      Returns true if path was directly set and modified, else false.

      show code
      Document.prototype.isDirectModified = function (path) {
      +  return (path in this._activePaths.states.modify);
      +};

      Parameters:

      Returns:

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isDirectModified('documents.0.title') // true
      +doc.isDirectModified('documents') // false

      Document#isInit(path)

      Checks if path was initialized.

      show code
      Document.prototype.isInit = function (path) {
      +  return (path in this._activePaths.states.init);
      +};

      Parameters:

      Returns:


      Document#isSelected(path)

      Checks if path was selected in the source query which initialized this document.

      show code
      Document.prototype.isSelected = function isSelected (path) {
      +  if (this._selected) {
      +
      +    if ('_id' === path) {
      +      return 0 !== this._selected._id;
      +    }
      +
      +    var paths = Object.keys(this._selected)
      +      , i = paths.length
      +      , inclusive = false
      +      , cur
      +
      +    if (1 === i && '_id' === paths[0]) {
      +      // only _id was selected.
      +      return 0 === this._selected._id;
      +    }
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +      inclusive = !! this._selected[cur];
      +      break;
      +    }
      +
      +    if (path in this._selected) {
      +      return inclusive;
      +    }
      +
      +    i = paths.length;
      +    var pathDot = path + '.';
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +
      +      if (0 === cur.indexOf(pathDot)) {
      +        return inclusive;
      +      }
      +
      +      if (0 === pathDot.indexOf(cur)) {
      +        return inclusive;
      +      }
      +    }
      +
      +    return ! inclusive;
      +  }
      +
      +  return true;
      +}

      Parameters:

      Returns:

      Example

      + +
      Thing.findOne().select('name').exec(function (err, doc) {
      +   doc.isSelected('name') // true
      +   doc.isSelected('age')  // false
      +})

      Document#validate(cb)

      Executes registered validation rules for this document.

      show code
      Document.prototype.validate = function (cb) {
      +  var self = this
      +
      +  // only validate required fields when necessary
      +  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
      +    if (!self.isSelected(path) && !self.isModified(path)) return false;
      +    return true;
      +  });
      +
      +  paths = paths.concat(Object.keys(this._activePaths.states.init));
      +  paths = paths.concat(Object.keys(this._activePaths.states.modify));
      +  paths = paths.concat(Object.keys(this._activePaths.states.default));
      +
      +  if (0 === paths.length) {
      +    complete();
      +    return this;
      +  }
      +
      +  var validating = {}
      +    , total = 0;
      +
      +  paths.forEach(validatePath);
      +  return this;
      +
      +  function validatePath (path) {
      +    if (validating[path]) return;
      +
      +    validating[path] = true;
      +    total++;
      +
      +    process.nextTick(function(){
      +      var p = self.schema.path(path);
      +      if (!p) return --total || complete();
      +
      +      p.doValidate(self.getValue(path), function (err) {
      +        if (err) self.invalidate(path, err, true);
      +        --total || complete();
      +      }, self);
      +    });
      +  }
      +
      +  function complete () {
      +    var err = self._validationError;
      +    self._validationError = undefined;
      +    cb(err);
      +  }
      +};

      Parameters:

      • cb <Function> called after validation completes, passing an error if one occurred

      Note:

      + +

      This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

      + +

      Example:

      + +
      doc.validate(function (err) {
      +  if (err) handleError(err);
      +  else // validation passed
      +});

      Document#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      Document.prototype.invalidate = function (path, err) {
      +  if (!this._validationError) {
      +    this._validationError = new ValidationError(this);
      +  }
      +
      +  if (!err || 'string' === typeof err) {
      +    err = new ValidatorError(path, err);
      +  }
      +
      +  this._validationError.errors[path] = err;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> the error which states the reason `path` was invalid

      Document#_reset()

      Resets the internal modified state of this document.

      show code
      Document.prototype._reset = function reset () {
      +  var self = this;
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this._activePaths
      +  .map('init', 'modify', function (i) {
      +    return self.getValue(i);
      +  })
      +  .filter(function (val) {
      +    return val && val instanceof DocumentArray && val.length;
      +  })
      +  .forEach(function (array) {
      +    var i = array.length;
      +    while (i--) {
      +      var doc = array[i];
      +      if (!doc) continue;
      +      doc._reset();
      +    }
      +  });
      +
      +  // clear atomics
      +  this._dirty().forEach(function (dirt) {
      +    var type = dirt.value;
      +    if (type && type._atomics) {
      +      type._atomics = {};
      +    }
      +  });
      +
      +  // Clear 'modify'('dirty') cache
      +  this._activePaths.clear('modify');
      +  this._validationError = undefined;
      +  this.errors = undefined;
      +  var self = this;
      +  this.schema.requiredPaths().forEach(function (path) {
      +    self._activePaths.require(path);
      +  });
      +
      +  return this;
      +}

      Returns:


      Document#_dirty()

      Returns this documents dirty paths / vals.

      show code
      Document.prototype._dirty = function _dirty () {
      +  var self = this;
      +
      +  var all = this._activePaths.map('modify', function (path) {
      +    return { path: path
      +           , value: self.getValue(path)
      +           , schema: self._path(path) };
      +  });
      +
      +  // Sort dirty paths in a flat hierarchy.
      +  all.sort(function (a, b) {
      +    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
      +  });
      +
      +  // Ignore "foo.a" if "foo" is dirty already.
      +  var minimal = []
      +    , lastPath
      +    , top;
      +
      +  all.forEach(function (item, i) {
      +    if (item.path.indexOf(lastPath) !== 0) {
      +      lastPath = item.path + '.';
      +      minimal.push(item);
      +      top = item;
      +    } else {
      +      if (!(item.value && top.value)) return;
      +
      +      // special case for top level MongooseArrays
      +      if (top.value._atomics && top.value.hasAtomics()) {
      +        // the `top` array itself and a sub path of `top` are being modified.
      +        // the only way to honor all of both modifications is through a $set
      +        // of entire array.
      +        top.value._atomics = {};
      +        top.value._atomics.$set = top.value;
      +      }
      +    }
      +  });
      +
      +  top = lastPath = null;
      +  return minimal;
      +}

      Document#_setSchema(schema)

      Assigns/compiles schema into this documents prototype.

      show code
      Document.prototype._setSchema = function (schema) {
      +  compile(schema.tree, this);
      +  this.schema = schema;
      +}

      Parameters:


      Document#_registerHooks()

      Register default hooks

      show code
      Document.prototype._registerHooks = function _registerHooks () {
      +  if (!this.save) return;
      +
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this.pre('save', function (next) {
      +    // we keep the error semaphore to make sure we don't
      +    // call `save` unnecessarily (we only need 1 error)
      +    var subdocs = 0
      +      , error = false
      +      , self = this;
      +
      +    // check for DocumentArrays
      +    var arrays = this._activePaths
      +    .map('init', 'modify', function (i) {
      +      return self.getValue(i);
      +    })
      +    .filter(function (val) {
      +      return val && val instanceof DocumentArray && val.length;
      +    });
      +
      +    if (!arrays.length)
      +      return next();
      +
      +    arrays.forEach(function (array) {
      +      if (error) return;
      +
      +      // handle sparse arrays by using for loop vs array.forEach
      +      // which skips the sparse elements
      +
      +      var len = array.length
      +      subdocs += len;
      +
      +      for (var i = 0; i < len; ++i) {
      +        if (error) break;
      +
      +        var doc = array[i];
      +        if (!doc) {
      +          --subdocs || next();
      +          continue;
      +        }
      +
      +        doc.save(handleSave);
      +      }
      +    });
      +
      +    function handleSave (err) {
      +      if (error) return;
      +
      +      if (err) {
      +        self._validationError = undefined;
      +        return next(error = err);
      +      }
      +
      +      --subdocs || next();
      +    }
      +
      +  }, function (err) {
      +    // emit on the Model if listening
      +    if (this.constructor.listeners('error').length) {
      +      this.constructor.emit('error', err);
      +    } else {
      +      // emit on the connection
      +      if (!this.db.listeners('error').length) {
      +        err.stack = 'No listeners detected, throwing. '
      +                  + 'Consider adding an error listener to your connection.
      +'
      +                  + err.stack
      +      }
      +      this.db.emit('error', err);
      +    }
      +  }).pre('save', function checkForExistingErrors (next) {
      +    // if any doc.set() calls failed
      +    if (this._saveError) {
      +      next(this._saveError);
      +      this._saveError = null;
      +    } else {
      +      next();
      +    }
      +  }).pre('save', function validation (next) {
      +    return this.validate(next);
      +  });
      +
      +  // add user defined queues
      +  this._doQueue();
      +};

      Document#_error(err)

      Registers an error

      show code
      Document.prototype._error = function (err) {
      +  this._saveError = err;
      +  return this;
      +};

      Parameters:


      Document#_doQueue()

      Executes methods queued from the Schema definition

      show code
      Document.prototype._doQueue = function () {
      +  var q = this.schema && this.schema.callQueue;
      +  if (q) {
      +    for (var i = 0, l = q.length; i < l; i++) {
      +      this[q[i][0]].apply(this, q[i][1]);
      +    }
      +  }
      +  return this;
      +};

      Document#toObject([options])

      Converts this document into a plain javascript object

      show code
      Document.prototype.toObject = function (options) {
      +  // When internally saving this document we always pass options,
      +  // bypassing the custom schema options.
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toObject
      +      ? clone(this.schema.options.toObject)
      +      : {};
      +  }
      +
      +  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
      +
      +  var ret = clone(this._doc, options);
      +
      +  if (options.virtuals || options.getters && false !== options.virtuals) {
      +    applyGetters(this, ret, 'virtuals', options);
      +  }
      +
      +  if (options.getters) {
      +    applyGetters(this, ret, 'paths', options);
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Options:

      + +
        +
      • getters apply all getters (path and virtual getters)
      • +
      • virtuals apply virtual getters (can override getters option)
      • +
      • minimize remove empty objects (defaults to true)
      • +
      + +

      Example of only applying path getters

      + +
      doc.toObject({ getters: true, virtuals: false })
      + +

      Example of only applying virtual getters

      + +
      doc.toObject({ virtuals: true })
      + +

      Example of applying both path and virtual getters

      + +
      doc.toObject({ getters: true })
      + +

      To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

      + +
      schema.set('toObject', { virtuals: true })
      + +

      See schema options for details.


      Document#toJSON(options)

      The return value of this method is used in calls to JSON.stringify(doc).

      show code
      Document.prototype.toJSON = function (options) {
      +  // check for object type since an array of documents
      +  // being stringified passes array indexes instead
      +  // of options objects. JSON.stringify([doc, doc])
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toJSON
      +      ? clone(this.schema.options.toJSON)
      +      : {};
      +  }
      +  options.json = true;
      +  return this.toObject(options);
      +};

      Parameters:

      • options <Object> same options as `Document#toObject`

      Returns:

      This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

      + +
      schema.set('toJSON', { virtuals: true })
      + +

      See schema options for details.


      Document#inspect()

      Helper for console.log

      show code
      Document.prototype.inspect = function (options) {
      +  var opts = options && 'Object' == options.constructor.name
      +    ? options
      +    : undefined
      +  return inspect(this.toObject(opts));
      +};

      Document#toString()

      Helper for console.log


      Document#equals(doc)

      Returns true if the Document stores the same data as doc.

      show code
      Document.prototype.equals = function (doc) {
      +  var tid = this.get('_id');
      +  var docid = doc.get('_id');
      +  return tid.equals
      +    ? tid.equals(docid)
      +    : tid === docid;
      +};

      Parameters:

      Returns:

      Documents are considered equal when they have matching _ids.


      Document#errors

      Hash containing current validation errors.


      Document#id

      The string version of this documents _id.

      + +

      Note:

      + +

      This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

      + +
      new Schema({ name: String }, { id: false });

      Document#isNew

      Boolean flag specifying if the document is new.


      Document#schema

      The documents schema.


    • drivers/node-mongodb-native/collection.js

      NativeCollection()

      A node-mongodb-native collection implementation.

      show code
      function NativeCollection () {
      +  this.collection = null;
      +  MongooseCollection.apply(this, arguments);
      +}

      Inherits:

      All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


      NativeCollection#onOpen()

      Called when the connection opens.

      show code
      NativeCollection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  if (this.collection) {
      +    return MongooseCollection.prototype.onOpen.call(self);
      +  }
      +
      +  if (!self.opts.size) {
      +    // non-capped
      +    return self.conn.db.collection(self.name, callback);
      +  }
      +
      +  // capped
      +  return self.conn.db.collection(self.name, function (err, c) {
      +    if (err) return callback(err);
      +
      +    // discover if this collection exists and if it is capped
      +    c.options(function (err, exists) {
      +      if (err) return callback(err);
      +
      +      if (exists) {
      +        if (exists.capped) {
      +          callback(null, c);
      +        } else {
      +          var msg = 'A non-capped collection exists with this name.
      +
      +'
      +                  + ' To use this collection as a capped collection, please '
      +                  + 'first convert it.
      +'
      +                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
      +          err = new Error(msg);
      +          callback(err);
      +        }
      +      } else {
      +        // create
      +        var opts = utils.clone(self.opts);
      +        opts.capped = true;
      +        self.conn.db.createCollection(self.name, opts, callback);
      +      }
      +    });
      +  });
      +
      +  function callback (err, collection) {
      +    if (err) {
      +      // likely a strict mode error
      +      self.conn.emit('error', err);
      +    } else {
      +      self.collection = collection;
      +      MongooseCollection.prototype.onOpen.call(self);
      +    }
      +  };
      +};

      NativeCollection#onClose()

      Called when the connection closes

      show code
      NativeCollection.prototype.onClose = function () {
      +  MongooseCollection.prototype.onClose.call(this);
      +};

      NativeCollection#getIndexes(callback)

      Retreives information about this collections indexes.

      Parameters:


    • drivers/node-mongodb-native/connection.js

      NativeConnection()

      A node-mongodb-native connection implementation.

      show code
      function NativeConnection() {
      +  MongooseConnection.apply(this, arguments);
      +};

      Inherits:


      NativeConnection#doOpen(fn)

      Opens the connection to MongoDB.

      show code
      NativeConnection.prototype.doOpen = function (fn) {
      +  var server
      +    , self = this;
      +
      +  if (!this.db) {
      +    server = new mongo.Server(this.host, Number(this.port), this.options.server);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};
      +
      +function listen (conn) {
      +  if (conn._listening) return;
      +  conn._listening = true;
      +
      +  conn.db.on('close', function(){
      +    if (conn._closeCalled) return;
      +
      +    // the driver never emits an `open` event. auto_reconnect still
      +    // emits a `close` event but since we never get another
      +    // `open` we can't emit close
      +    if (conn.db.serverConfig.autoReconnect) {
      +      conn.readyState = STATES.disconnected;
      +      conn.emit('close');
      +      return;
      +    }
      +    conn.onClose();
      +  });
      +  conn.db.on('error', function(err){
      +    conn.emit('error', err);
      +  });
      +  conn.db.on('timeout', function(err){
      +    var error = new Error(err && err.err || 'connection timeout');
      +    conn.emit('error', error);
      +  });
      +  conn.db.on('open', function (err, db) {
      +    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
      +      conn.readyState = STATES.connected;
      +      conn.emit('reconnected')
      +    }
      +  })
      +}

      Parameters:

      Returns:


      NativeConnection#doOpenSet(fn)

      Opens a connection to a MongoDB ReplicaSet.

      show code
      NativeConnection.prototype.doOpenSet = function (fn) {
      +  if (!this.db) {
      +    var servers = []
      +      , ports = this.port
      +      , self = this
      +
      +    this.host.forEach(function (host, i) {
      +      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
      +    });
      +
      +    var server = new ReplSetServers(servers, this.options.replset);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +
      +    this.db.on('fullsetup', function () {
      +      self.emit('fullsetup')
      +    });
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:

      See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


      NativeConnection#doClose(fn)

      Closes the connection

      show code
      NativeConnection.prototype.doClose = function (fn) {
      +  this.db.close();
      +  if (fn) fn();
      +  return this;
      +}

      Parameters:

      Returns:


    • error.js

      MongooseError()

      Mongoose error

      show code
      function MongooseError (msg) {
      +  Error.call(this);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.message = msg;
      +  this.name = 'MongooseError';
      +};

      Inherits:


    • errors/cast.js

      CastError(type, value)

      Casting Error constructor.

      show code
      function CastError (type, value) {
      +  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'CastError';
      +  this.type = type;
      +  this.value = value;
      +};

      Parameters:

      Inherits:


    • errors/document.js

      DocumentError(msg)

      Document Error

      show code
      function DocumentError (msg) {
      +  MongooseError.call(this, msg);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'DocumentError';
      +};

      Parameters:

      Inherits:


    • errors/validation.js

      ValidationError(instance)

      Document Validation Error

      show code
      function ValidationError (instance) {
      +  MongooseError.call(this, "Validation failed");
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidationError';
      +  this.errors = instance.errors = {};
      +};

      Parameters:

      Inherits:


      ValidationError#toString()

      Console.log helper

      show code
      ValidationError.prototype.toString = function () {
      +  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
      +    return String(this.errors[key]);
      +  }, this).join(', ');
      +};

    • errors/validator.js

      ValidatorError(path, msg)

      Schema validator error

      show code
      function ValidatorError (path, type) {
      +  var msg = type
      +    ? '"' + type + '" '
      +    : '';
      +  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidatorError';
      +  this.path = path;
      +  this.type = type;
      +};

      Parameters:

      Inherits:


    • model.js

      Model(doc)

      Model constructor

      show code
      function Model (doc, fields, skipId) {
      +  Document.call(this, doc, fields, skipId);
      +};

      Parameters:

      • doc <Object> values to with which to create the document

      Inherits:

      Events:

      • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

      • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


      Model#_getPopulationKeys(query)

      Returns what paths can be populated

      show code
      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
      +  if (!(query && query.options.populate)) return;
      +
      +  var names = Object.keys(query.options.populate)
      +    , n = names.length
      +    , name
      +    , paths = {}
      +    , hasKeys
      +    , schema
      +
      +  while (n--) {
      +    name = names[n];
      +    schema = this.schema.path(name);
      +    hasKeys = true;
      +
      +    if (!schema) {
      +      // if the path is not recognized, it's potentially embedded docs
      +      // walk path atoms from right to left to find a matching path
      +      var pieces = name.split('.')
      +        , i = pieces.length;
      +
      +      while (i--) {
      +        var path = pieces.slice(0, i).join('.')
      +          , pathSchema = this.schema.path(path);
      +
      +        // loop until we find an array schema
      +        if (pathSchema && pathSchema.caster) {
      +          if (!paths[path]) {
      +            paths[path] = { sub: {} };
      +          }
      +
      +          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
      +          hasKeys || (hasKeys = true);
      +          break;
      +        }
      +      }
      +    } else {
      +      paths[name] = query.options.populate[name];
      +      hasKeys || (hasKeys = true);
      +    }
      +  }
      +
      +  return hasKeys && paths;
      +};

      Parameters:

      Returns:


      Model#_populate(schema, oid, query, fn)

      Populates an object

      show code
      Model.prototype._populate = function populate (schema, oid, query, fn) {
      +  if (!Array.isArray(oid)) {
      +    var conditions = query.conditions || {};
      +    conditions._id = oid;
      +
      +    return this
      +    .db.model(query.model || schema.options.ref)
      +    .findOne(conditions, query.fields, query.options, fn);
      +  }
      +
      +  if (!oid.length) {
      +    return fn(null, oid);
      +  }
      +
      +  var model = this.db.model(query.model || schema.caster.options.ref)
      +    , conditions = query && query.conditions || {};
      +
      +  conditions._id || (conditions._id = { $in: oid });
      +
      +  model.find(conditions, query.fields, query.options, function (err, docs) {
      +    if (err) return fn(err);
      +
      +    // user specified sort order?
      +    if (query.options && query.options.sort) {
      +      return fn(null, docs);
      +    }
      +
      +    // put back in original id order (using a hash reduces complexity from n*n to 2n)
      +    var docHash = {};
      +    docs.forEach(function (doc) {
      +      docHash[doc._id] = doc;
      +    });
      +
      +    var arr = [];
      +    oid.forEach(function (id) {
      +      if (id in docHash) arr.push(docHash[id]);
      +    });
      +
      +    fn(null, arr);
      +  });
      +};

      Parameters:

      • schema <SchemaType> type for the oid
      • oid <Object> object id or array of object ids
      • query <Object> object specifying query conditions, fields, and options
      • fn <Function>

      Model#init(doc, query, fn)

      Performs auto-population of relations.

      show code
      Model.prototype.init = function init (doc, query, fn) {
      +  if ('function' == typeof query) {
      +    fn = query;
      +    query = null;
      +  }
      +
      +  var populate = this._getPopulationKeys(query);
      +
      +  if (!populate) {
      +    return Document.prototype.init.call(this, doc, fn);
      +  }
      +
      +  // population from other models is necessary
      +  var self = this;
      +
      +  init(doc, '', function (err) {
      +    if (err) return fn(err);
      +    Document.prototype.init.call(self, doc, fn);
      +  });
      +
      +  return this;
      +
      +  function init (obj, prefix, fn) {
      +    prefix = prefix || '';
      +
      +    var keys = Object.keys(obj)
      +      , len = keys.length;
      +
      +    return next();
      +
      +    function next () {
      +      if (--len < 0) return fn();
      +
      +      var i = keys[len]
      +        , path = prefix + i
      +        , schema = self.schema.path(path)
      +        , total = 0
      +        , inline = false
      +        , poppath
      +
      +      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
      +        // assume nested object
      +        return init(obj[i], path + '.', next);
      +      }
      +
      +      if (!(obj[i] && schema && populate[path])) return next();
      +
      +      // this query object is re-used and passed around. we clone
      +      // it to prevent query condition contamination between
      +      // one populate call to the next.
      +      poppath = utils.clone(populate[path]);
      +
      +      if (poppath.sub) {
      +        obj[i].forEach(function (subobj) {
      +          inline = true;
      +
      +          var pkeys = Object.keys(poppath.sub)
      +            , pi = pkeys.length
      +            , key
      +
      +          while (pi--) {
      +            key = pkeys[pi];
      +
      +            if (subobj[key]) (function (key) {
      +              total++;
      +              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
      +              function done (err, doc) {
      +                if (err) return error(err);
      +                subobj[key] = doc;
      +                if (--total < 1 && !inline) {
      +                  next();
      +                }
      +              }
      +            })(key);
      +          }
      +        });
      +
      +        inline = false;
      +
      +        if (0 === total) return next();
      +
      +      } else {
      +        self._populate(schema, obj[i], poppath, function (err, doc) {
      +          if (err) return error(err);
      +          obj[i] = doc;
      +          next();
      +        });
      +      }
      +    };
      +  };
      +
      +  function error (err) {
      +    if (error.err) return;
      +    fn(error.err = err);
      +  }
      +};

      Parameters:

      • doc <Object> document returned by mongo
      • query <Query> query that originated the initialization
      • fn <Function>

      Model#save([fn])

      Saves this document.

      show code
      Model.prototype.save = function save (fn) {
      +  var promise = new Promise(fn)
      +    , complete = handleSave(promise, this)
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  if (this.isNew) {
      +    // send entire doc
      +    var obj = this.toObject({ depopulate: 1 });
      +    this._version(true, obj);
      +    this.collection.insert(obj, options, complete);
      +    this._reset();
      +    this.isNew = false;
      +    this.emit('isNew', false);
      +    // Make it possible to retry the insert
      +    this._inserting = true;
      +
      +  } else {
      +    // Make sure we don't treat it as a new object on error,
      +    // since it already exists
      +    this._inserting = false;
      +
      +    var delta = this._delta();
      +    if (delta) {
      +      var where = this._where(delta[0]);
      +      this.collection.update(where, delta[1], options, complete);
      +    } else {
      +      complete(null);
      +    }
      +
      +    this._reset();
      +    this.emit('isNew', false);
      +  }
      +};

      Parameters:

      Example:

      + +
      product.sold = Date.now();
      +product.save(function (err, product) {
      +  if (err) ..
      +})
      + +

      The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      + +
      var db = mongoose.createConnection(..);
      +var schema = new Schema(..);
      +var Product = db.model('Product', schema);
      +
      +db.on('error', handleError);
      + +

      However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

      + +
      Product.on('error', handleError);

      Model#_delta()

      Produces a special query document of the modified properties used in updates.

      show code
      Model.prototype._delta = function _delta () {
      +  var dirty = this._dirty();
      +  if (!dirty.length) return;
      +
      +  var self = this
      +    , where = {}
      +    , delta = {}
      +    , len = dirty.length
      +    , d = 0
      +    , val
      +    , obj
      +
      +  for (; d < len; ++d) {
      +    var data = dirty[d]
      +    var value = data.value
      +    var schema = data.schema
      +
      +    if (undefined === value) {
      +      operand(self, where, delta, data, 1, '$unset');
      +
      +    } else if (null === value) {
      +      operand(self, where, delta, data, null);
      +
      +    } else if (value._path && value._atomics) {
      +      handleAtomics(self, where, delta, data, value);
      +
      +    } else if (value._path && Buffer.isBuffer(value)) {
      +      // MongooseBuffer
      +      value = value.toObject();
      +      operand(self, where, delta, data, value);
      +
      +    } else {
      +      value = utils.clone(value);
      +      operand(self, where, delta, data, value);
      +    }
      +  }
      +
      +  if (this.__version) {
      +    this._version(where, delta);
      +  }
      +
      +  return [where, delta];
      +}

      Model#_version()

      Appends versioning to the where and update clauses.

      show code
      Model.prototype._version = function _version (where, delta) {
      +  var key = this.schema.options.versionKey;
      +
      +  if (true === where) {
      +    // this is an insert
      +    if (key) this.setValue(key, delta[key] = 0);
      +    return;
      +  }
      +
      +  // updates
      +
      +  // only apply versioning if our versionKey was selected. else
      +  // there is no way to select the correct version. we could fail
      +  // fast here and force them to include the versionKey but
      +  // thats a bit intrusive. can we do this automatically?
      +  // TODO fail fast option?
      +  if (!this.isSelected(key)) {
      +    return;
      +  }
      +
      +  // $push $addToSet don't need the where clause set
      +  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
      +    where[key] = this.getValue(key);
      +  }
      +
      +  if (VERSION_INC === (VERSION_INC & this.__version)) {
      +    delta.$inc || (delta.$inc = {});
      +    delta.$inc[key] = 1;
      +  }
      +}

      Model#increment()

      Signal that we desire an increment of this documents version.

      show code
      Model.prototype.increment = function increment () {
      +  this.__version = VERSION_ALL;
      +  return this;
      +}

      Model#_where()

      Returns a query object which applies shardkeys if they exist.

      show code
      Model.prototype._where = function _where (where) {
      +  where || (where = {});
      +
      +  var paths
      +    , len
      +
      +  if (this._shardval) {
      +    paths = Object.keys(this._shardval)
      +    len = paths.length
      +
      +    for (var i = 0; i < len; ++i) {
      +      where[paths[i]] = this._shardval[paths[i]];
      +    }
      +  }
      +
      +  where._id = this._doc._id;
      +  return where;
      +}

      Model#remove([fn])

      Removes this document from the db.

      show code
      Model.prototype.remove = function remove (fn) {
      +  if (this._removing) return this;
      +
      +  var promise = this._removing = new Promise(fn)
      +    , where = this._where()
      +    , self = this
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  this.collection.remove(where, options, tick(function (err) {
      +    if (err) {
      +      promise.error(err);
      +      promise = self = self._removing = where = options = null;
      +      return;
      +    }
      +    self.emit('remove', self);
      +    promise.complete();
      +    promise = self = where = options = null;
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Example:

      + +
      product.remove(function (err, product) {
      +  if (err) return handleError(err);
      +  Product.findById(product._id, function (err, product) {
      +    console.log(product) // null
      +  })
      +})

      Model#_registerHooks()

      Register hooks override

      show code
      Model.prototype._registerHooks = function registerHooks () {
      +  Document.prototype._registerHooks.call(this);
      +};

      Model#model(name)

      Returns another Model instance.

      show code
      Model.prototype.model = function model (name) {
      +  return this.db.model(name);
      +};

      Parameters:

      Example:

      + +
      var doc = new Tank;
      +doc.model('User').findById(id, callback);

      Model#$where(argument)

      Creates a Query and specifies a $where condition.

      Parameters:

      • argument <String, Function> is a javascript string or anonymous function

      Returns:

      Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      + +
      Blog.$where('this.comments.length &gt; 5');

      Model.init()

      Called when the model compiles.

      show code
      Model.init = function init () {
      +  if (this.schema.options.autoIndex)
      +    this.ensureIndexes();
      +
      +  this.schema.emit('init', this);
      +};

      Model.ensureIndexes([cb])

      Sends ensureIndex commands to mongo for each index declared in the schema.

      show code
      Model.ensureIndexes = function ensureIndexes (cb) {
      +  var indexes = this.schema.indexes();
      +  if (!indexes.length) {
      +    return cb && cb();
      +  }
      +
      +  var self = this
      +    , safe = self.schema.options.safe
      +    , count = indexes.length
      +    , error
      +
      +  indexes.forEach(function (index) {
      +    var options = index[1];
      +    options.safe = safe;
      +    self.collection.ensureIndex(index[0], options, tick(function (err) {
      +      if (err) error = err;
      +      if (--count) return;
      +
      +      self.emit('index', error);
      +      cb && cb(error);
      +    }));
      +  });
      +}

      Parameters:

      After completion, an index event is emitted on this Model passing an error if one occurred.

      + +

      NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

      + +

      Example:

      + +
      Event.ensureIndexes(function (err) {
      +  if (err) return handleError(err);
      +});

      Model.remove(conditions, [callback])

      Removes documents from the collection.

      show code
      Model.remove = function remove (conditions, callback) {
      +  if ('function' === typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +  }
      +
      +  var query = new Query(conditions).bind(this, 'remove');
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.remove(callback);
      +};

      Parameters:

      Returns:

      Note:

      + +

      To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.remove({ _id: id }).exec();

      Model.find(conditions, [fields], [options], [callback])

      Finds documents

      show code
      Model.find = function find (conditions, fields, options, callback) {
      +  if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options);
      +  query.bind(this, 'find');
      +  query.select(fields);
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.find(callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      // retrieve only certain keys
      +MyModel.find({ name: /john/i }, 'name friends', function () { })
      +
      +// pass options
      +MyModel.find({ name: /john/i }, null, { skip: 10 } )

      Model._applyNamedScope(query)

      Merges the current named scope query into query.

      show code
      Model._applyNamedScope = function _applyNamedScope (query) {
      +  var cQuery = this._cumulativeQuery;
      +
      +  if (cQuery) {
      +    merge(query._conditions, cQuery._conditions);
      +    if (query._fields && cQuery._fields)
      +      merge(query._fields, cQuery._fields);
      +    if (query.options && cQuery.options)
      +      merge(query.options, cQuery.options);
      +    delete this._cumulativeQuery;
      +  }
      +
      +  return query;
      +}

      Parameters:

      Returns:


      Model.findById(id, [fields], [options], [callback])

      Finds a single document by id.

      show code
      Model.findById = function findById (id, fields, options, callback) {
      +  return this.findOne({ _id: id }, fields, options, callback);
      +};

      Parameters:

      Returns:

      The id is cast to an ObjectId before sending the command.

      + +

      Example:

      + +
      Adventure.findById(id, callback);

      Model.findOne(conditions, [fields], [options], [callback])

      Finds one document.

      show code
      Model.findOne = function findOne (conditions, fields, options, callback) {
      +  if ('function' == typeof options) {
      +    // TODO Handle all 3 of the following scenarios
      +    // Hint: Only some of these scenarios are possible if cQuery is present
      +    // Scenario: findOne(conditions, fields, callback);
      +    // Scenario: findOne(fields, options, callback);
      +    // Scenario: findOne(conditions, options, callback);
      +    callback = options;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    // TODO Handle all 2 of the following scenarios
      +    // Scenario: findOne(conditions, callback)
      +    // Scenario: findOne(fields, callback)
      +    // Scenario: findOne(options, callback);
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOne(callback);
      +};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      + +

      Example:

      + +
      Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

      Model.count(conditions, [callback])

      Counts number of matching documents in a database collection.

      show code
      Model.count = function count (conditions, callback) {
      +  if ('function' === typeof conditions)
      +    callback = conditions, conditions = {};
      +
      +  var query = new Query(conditions).bind(this, 'count');
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.count(callback);
      +};

      Parameters:

      Returns:

      Example:

      + +
      Adventure.count({ type: 'jungle' }, function (err, count) {
      +  if (err) ..
      +  console.log('there are %d jungle adventures', count);
      +});

      Model.distinct(field, [conditions], [callback])

      Executes a DISTINCT command

      show code
      Model.distinct = function distinct (field, conditions, callback) {
      +  var query = new Query(conditions).bind(this, 'distinct');
      +  if ('undefined' == typeof callback) {
      +    query._distinctArg = field;
      +    return query;
      +  }
      +
      +  this._applyNamedScope(query);
      +  return query.distinct(field, callback);
      +};

      Parameters:

      Returns:


      Model.where(path, [val])

      Creates a Query, applies the passed conditions, and returns the Query.

      show code
      Model.where = function where (path, val) {
      +  var q = new Query().bind(this, 'find');
      +  return q.where.apply(q, arguments);
      +};

      Parameters:

      Returns:

      For example, instead of writing:

      + +
      User.find({age: {$gte: 21, $lte: 65}}, callback);
      + +

      we can instead write:

      + +
      User.where('age').gte(21).lte(65).exec(callback);
      + +

      Since the Query class also supports where you can continue chaining

      + +
      User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +... etc

      Model.findOneAndUpdate([conditions], [update], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Model.findOneAndUpdate = function (conditions, update, options, callback) {
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +  else if (1 === arguments.length) {
      +    if ('function' == typeof conditions) {
      +      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    update = conditions;
      +    conditions = undefined;
      +  }
      +
      +  var fields;
      +  if (options && options.fields) {
      +    fields = options.fields;
      +    options.fields = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndUpdate', update);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndUpdate(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndUpdate(conditions, update, options, callback) // executes
      +A.findOneAndUpdate(conditions, update, options)  // returns Query
      +A.findOneAndUpdate(conditions, update, callback) // executes
      +A.findOneAndUpdate(conditions, update)           // returns Query
      +A.findOneAndUpdate()                             // returns Query
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findByIdAndUpdate(id, [update], [options], [callback])

      Issues a mongodb findAndModify update command by a documents id.

      show code
      Model.findByIdAndUpdate = function (id, update, options, callback) {
      +  var args;
      +
      +  if (1 === arguments.length) {
      +    if ('function' == typeof id) {
      +      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
      +
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    return this.findOneAndUpdate({_id: id }, undefined);
      +  }
      +
      +  args = utils.args(arguments, 1);
      +  args.unshift({ _id: id });
      +  return this.findOneAndUpdate.apply(this, args);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndUpdate(id, update, options, callback) // executes
      +A.findByIdAndUpdate(id, update, options)  // returns Query
      +A.findByIdAndUpdate(id, update, callback) // executes
      +A.findByIdAndUpdate(id, update)           // returns Query
      +A.findByIdAndUpdate()                     // returns Query
      + +

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findById(id, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findOneAndRemove(conditions, [options], [callback])

      Issue a mongodb findAndModify remove command.

      show code
      Model.findOneAndRemove = function (conditions, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof conditions) {
      +    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  }
      +
      +  var fields;
      +  if (options) {
      +    fields = options.select;
      +    options.select = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndRemove');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndRemove(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndRemove(conditions, options, callback) // executes
      +A.findOneAndRemove(conditions, options)  // return Query
      +A.findOneAndRemove(conditions, callback) // executes
      +A.findOneAndRemove(conditions) // returns Query
      +A.findOneAndRemove()           // returns Query

      Model.findByIdAndRemove(id, [options], [callback])

      Issue a mongodb findAndModify remove command by a documents id.

      show code
      Model.findByIdAndRemove = function (id, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof id) {
      +    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  return this.findOneAndRemove({ _id: id }, options, callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed, else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndRemove(id, options, callback) // executes
      +A.findByIdAndRemove(id, options)  // return Query
      +A.findByIdAndRemove(id, callback) // executes
      +A.findByIdAndRemove(id) // returns Query
      +A.findByIdAndRemove()           // returns Query

      Model.create(doc, fn)

      Shortcut for creating a new Document that is automatically saved to the db if valid.

      show code
      Model.create = function create (doc, fn) {
      +  if (1 === arguments.length) {
      +    return 'function' === typeof doc && doc(null);
      +  }
      +
      +  var self = this
      +    , docs = [null]
      +    , promise
      +    , count
      +    , args
      +
      +  if (Array.isArray(doc)) {
      +    args = doc;
      +  } else {
      +    args = utils.args(arguments, 0, arguments.length - 1);
      +    fn = arguments[arguments.length - 1];
      +  }
      +
      +  if (0 === args.length) return fn(null);
      +
      +  promise = new Promise(fn);
      +  count = args.length;
      +
      +  args.forEach(function (arg, i) {
      +    var doc = new self(arg);
      +    docs[i+1] = doc;
      +    doc.save(function (err) {
      +      if (err) return promise.error(err);
      +      --count || fn.apply(null, docs);
      +    });
      +  });
      +
      +  // TODO
      +  // utilize collection.insertAll for batch processing?
      +};

      Parameters:

      Example:

      + +
      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});
      +
      +var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      +Candy.create(array, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});

      Model.update(conditions, update, [options], [callback])

      Updates documents in the database without returning them.

      show code
      Model.update = function update (conditions, doc, options, callback) {
      +  if (arguments.length < 4) {
      +    if ('function' === typeof options) {
      +      // Scenario: update(conditions, doc, callback)
      +      callback = options;
      +      options = null;
      +    } else if ('function' === typeof doc) {
      +      // Scenario: update(doc, callback);
      +      callback = doc;
      +      doc = conditions;
      +      conditions = {};
      +      options = null;
      +    }
      +  }
      +
      +  var query = new Query(conditions, options).bind(this, 'update', doc);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.update(doc, callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
      +MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
      +  if (err) return handleError(err);
      +  console.log('The number of updated documents was %d', numberAffected);
      +  console.log('The raw response from Mongo was ', raw);
      +});
      + +

      Valid options:

      + +
        +
      • safe (boolean) safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +
      • multi (boolean) whether multiple documents should be updated (false)
      • +
      + +

      All update values are cast to their appropriate SchemaTypes before being sent.

      + +

      The callback function receives (err, numberAffected, rawResponse).

      + +
        +
      • err is the error if any occurred
      • +
      • numberAffected is the count of updated documents Mongo reported
      • +
      • rawResponse is the full response from Mongo
      • +
      + +

      Note:

      + +

      All top level keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.update(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

      + +

      Note:

      + +

      To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
      + +

      Note:

      + +

      Although values are casted to their appropriate types when using update, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.mapReduce(o, callback)

      Executes a mapReduce command.

      show code
      Model.mapReduce = function mapReduce (o, callback) {
      +  if ('function' != typeof callback) throw new Error('missing callback');
      +
      +  var self = this;
      +
      +  if (!Model.mapReduce.schema) {
      +    var opts = { noId: true, noVirtualId: true, strict: false }
      +    Model.mapReduce.schema = new Schema({}, opts);
      +  }
      +
      +  if (!o.out) o.out = { inline: 1 };
      +
      +  o.map = String(o.map);
      +  o.reduce = String(o.reduce);
      +
      +  if (o.query) {
      +    var q = new Query(o.query);
      +    q.cast(this);
      +    o.query = q._conditions;
      +    q = undefined;
      +  }
      +
      +  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
      +    if (err) return callback(err);
      +
      +    if (ret.findOne && ret.mapReduce) {
      +      // returned a collection, convert to Model
      +      var model = Model.compile(
      +          '_mapreduce_' + ret.collectionName
      +        , Model.mapReduce.schema
      +        , ret.collectionName
      +        , self.db
      +        , self.base);
      +
      +      model._mapreduce = true;
      +
      +      return callback(err, model, stats);
      +    }
      +
      +    callback(err, ret, stats);
      +  });
      +}

      Parameters:

      • o <Object> an object specifying map-reduce options
      • callback <Function>

      o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +User.mapReduce(o, function (err, results) {
      +  console.log(results)
      +})
      + +

      Other options:

      + +
        +
      • query {Object} query filter object.
      • +
      • limit {Number} max number of documents
      • +
      • keeptemp {Boolean, default:false} keep temporary data
      • +
      • finalize {Function} finalize function
      • +
      • scope {Object} scope variables exposed to map/reduce/finalize during execution
      • +
      • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
      • +
      • verbose {Boolean, default:false} provide statistics on job execution time.
      • +
      • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
      • +
      + +

      * out options:

      + +
        +
      • {inline:1} the results are returned in an array
      • +
      • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
      • +
      • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
      • +
      • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
      • +
      + +

      If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +o.out = { replace: 'createdCollectionNameForResults' }
      +o.verbose = true;
      +User.mapReduce(o, function (err, model, stats) {
      +  console.log('map reduce took %d ms', stats.processtime)
      +  model.find().where('value').gt(10).exec(function (err, docs) {
      +    console.log(docs);
      +  });
      +})

      Model.aggregate(array, [options], callback)

      Executes an aggregate command on this models collection.

      show code
      Model.aggregate = function aggregate () {
      +  return this.collection.aggregate.apply(this.collection, arguments);
      +}

      Parameters:

      Example:

      + +
      // find the max age of all users
      +Users.aggregate(
      +    { $group: { _id: null, maxAge: { $max: '$age' }}}
      +  , { $project: { _id: 0, maxAge: 1 }}
      +  , function (err, res) {
      +  if (err) return handleError(err);
      +  console.log(res); // [ { maxAge: 98 } ]
      +});
      + +

      NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

      + +

      NOTE: this requires running MongoDB >= 2.1


      Model#base

      Base Mongoose instance the model uses.


      Model#collection

      Collection the model uses.


      Model#db

      Database instance the model uses.


      Model#schema

      Schema the model uses.


      Model#modelName

      The name of the model


      Model#collection

      Collection the model uses.


      Model#db

      Connection the model uses.


    • namedscope.js

      NamedScope#decorate(target, getters)

      Decorate

      show code
      NamedScope.prototype.decorate = function (target, getters) {
      +  var name = this.name
      +    , block = this.block
      +    , query = this.query;
      +  if (block) {
      +    if (block.length === 0) {
      +      Object.defineProperty(target, name, {
      +        get: getters.block0(block)
      +      });
      +    } else {
      +      target[name] = getters.blockN(block);
      +    }
      +  } else {
      +    Object.defineProperty(target, name, {
      +      get: getters.basic(query)
      +    });
      +  }
      +};
      +
      +NamedScope.prototype.compile = function (model) {
      +  var allScopes = this.scopesByName
      +    , scope;
      +  for (var k in allScopes) {
      +    scope = allScopes[k];
      +    scope.decorate(model, {
      +      block0: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.call(cquery);
      +          return this;
      +        };
      +      },
      +      blockN: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.apply(cquery, arguments);
      +          return this;
      +        };
      +      },
      +      basic: function (query) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          cquery.find(query);
      +          return this;
      +        };
      +      }
      +    });
      +  }
      +};
      +
      +module.exports = NamedScope;

      Parameters:


    • promise.js

      Promise(back)

      Promise constructor.

      show code
      function Promise (back) {
      +  this.emitted = {};
      +  if ('function' == typeof back)
      +    this.addBack(back);
      +};

      Parameters:

      • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

      Events:

      • err: Emits when the promise resolves to an error.

      • complete: Emits when the promise resolves sucessfully.


      Promise#on(event, callback)

      Adds listener to the event.

      show code
      Promise.prototype.on = function (event, callback) {
      +  if (this.emitted[event])
      +    callback.apply(this, this.emitted[event]);
      +  else
      +    EventEmitter.prototype.on.call(this, event, callback);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


      Promise#emit()

      Keeps track of emitted events to run them on on.

      show code
      Promise.prototype.emit = function (event) {
      +  // ensures a promise can't be complete() or error() twice
      +  if (event == 'err' || event == 'complete'){
      +    if (this.emitted.err || this.emitted.complete) {
      +      return this;
      +    }
      +    this.emitted[event] = util.args(arguments, 1);
      +  }
      +
      +  return EventEmitter.prototype.emit.apply(this, arguments);
      +};

      Promise#complete()

      Shortcut for emitting the complete event.

      show code
      Promise.prototype.complete = function () {
      +  var args = util.args(arguments);
      +  return this.emit.apply(this, ['complete'].concat(args));
      +};

      Promise#error()

      Shortcut for emitting the err event.

      show code
      Promise.prototype.error = function (err) {
      +  if (!(err instanceof Error)) err = new Error(err);
      +  return this.emit('err', err);
      +};

      Returns:


      Promise#addCallback()

      Shortcut for .on('complete', fn).

      show code
      Promise.prototype.addCallback = function (fn) {
      +  return this.on('complete', fn);
      +};

      Returns:


      Promise#addErrback()

      Shortcut for .on('err', fn).

      show code
      Promise.prototype.addErrback = function (fn) {
      +  return this.on('err', fn);
      +};

      Returns:


      Promise#addBack(fn)

      Adds a single function that's both a callback and errback.

      show code
      Promise.prototype.addBack = function (fn) {
      +  this.on('err', function(err){
      +    fn.call(this, err);
      +  });
      +
      +  this.on('complete', function(){
      +    var args = util.args(arguments);
      +    fn.apply(this, [null].concat(args));
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Promise#resolve(err, val)

      Sugar for handling cases where you may be resolving to either an error condition or a success condition.

      show code
      Promise.prototype.resolve = function (err, val) {
      +  if (err) return this.error(err);
      +  return this.complete(val);
      +};

      Parameters:

      • err <Error> optional error or null
      • val <Object> value to complete the promise with

    • query.js

      Query(criteria, options)

      Query constructor used for building queries.

      show code
      function Query (criteria, options) {
      +  this.setOptions(options, true);
      +  this._conditions = {};
      +  this._updateArg = {};
      +  this._fields = undefined;
      +  if (criteria) this.find(criteria);
      +}

      Parameters:

      Example:

      + +
      var query = Model.find();
      +query.where('age').gte(21).exec(callback);

      Query#setOptions(options)

      Sets query options.

      show code
      Query.prototype.setOptions = function (options, overwrite) {
      +  // overwrite is internal use only
      +  if (overwrite) {
      +    options = this.options = options || {};
      +    this.safe = options.safe
      +
      +    // normalize population options
      +    var pop = this.options.populate;
      +    this.options.populate = {};
      +
      +    if (pop && Array.isArray(pop)) {
      +      for (var i = 0, l = pop.length; i < l; i++) {
      +        this.options.populate[pop[i]] = {};
      +      }
      +    }
      +
      +    return this;
      +  }
      +
      +  if (!(options && 'Object' == options.constructor.name))
      +    return this;
      +
      +  if ('safe' in options)
      +    this.safe = options.safe;
      +
      +  // set arbitrary options
      +  var methods = Object.keys(options)
      +    , i = methods.length
      +    , method
      +
      +  while (i--) {
      +    method = methods[i];
      +
      +    // use methods if exist (safer option manipulation)
      +    if ('function' == typeof this[method]) {
      +      var args = Array.isArray(options[method])
      +        ? options[method]
      +        : [options[method]];
      +      this[method].apply(this, args)
      +    } else {
      +      this.options[method] = options[method];
      +    }
      +  }
      +  return this;
      +}

      Parameters:

      Options:

      + + + +

      * denotes a query helper method is also available


      Query#bind(model, op, updateArg)

      Binds this query to a model.

      show code
      Query.prototype.bind = function bind (model, op, updateArg) {
      +  this.model = model;
      +  this.op = op;
      +
      +  if (model._mapreduce) this.options.lean = true;
      +
      +  if (op == 'update' || op == 'findOneAndUpdate') {
      +    merge(this._updateArg, updateArg || {});
      +  }
      +
      +  return this;
      +};

      Parameters:

      • model <Model> the model to which the query is bound
      • op <String> the operation to execute
      • updateArg <Object> used in update methods

      Returns:


      Query#exec([operation], [callback])

      Executes the query

      show code
      Query.prototype.exec = function exec (op, callback) {
      +  var promise = new Promise();
      +
      +  switch (typeof op) {
      +    case 'function':
      +      callback = op;
      +      op = null;
      +      break;
      +    case 'string':
      +      this.op = op;
      +      break;
      +  }
      +
      +  if (callback) promise.addBack(callback);
      +
      +  if (!this.op) {
      +    promise.complete();
      +    return promise;
      +  }
      +
      +  if ('update' == this.op) {
      +    this[this.op](this._updateArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  if ('distinct' == this.op) {
      +    this.distinct(this._distinctArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  this[this.op](promise.resolve.bind(promise));
      +  return promise;
      +};

      Parameters:

      Returns:

      Examples

      + +
      query.exec();
      +query.exec(callback);
      +query.exec('update');
      +query.exec('find', callback);

      Query#find([criteria], [callback])

      Finds documents.

      show code
      Query.prototype.find = function (criteria, callback) {
      +  this.op = 'find';
      +  if ('function' === typeof criteria) {
      +    callback = criteria;
      +    criteria = {};
      +  } else if (criteria instanceof Query) {
      +    // TODO Merge options, too
      +    merge(this._conditions, criteria._conditions);
      +  } else if (criteria instanceof Document) {
      +    merge(this._conditions, criteria.toObject());
      +  } else if (criteria && 'Object' === criteria.constructor.name) {
      +    merge(this._conditions, criteria);
      +  }
      +  if (!callback) return this;
      +  return this.execFind(callback);
      +};

      Parameters:

      Returns:

      When no callback is passed, the query is not executed.

      + +

      Example

      + +
      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

      Query#cast(model, [obj])

      Casts this query to the schema of model

      show code
      Query.prototype.cast = function (model, obj) {
      +  obj || (obj= this._conditions);
      +
      +  var schema = model.schema
      +    , paths = Object.keys(obj)
      +    , i = paths.length
      +    , any$conditionals
      +    , schematype
      +    , nested
      +    , path
      +    , type
      +    , val;
      +
      +  while (i--) {
      +    path = paths[i];
      +    val = obj[path];
      +
      +    if ('$or' === path || '$nor' === path) {
      +      var k = val.length
      +        , orComponentQuery;
      +
      +      while (k--) {
      +        orComponentQuery = new Query(val[k]);
      +        orComponentQuery.cast(model);
      +        val[k] = orComponentQuery._conditions;
      +      }
      +
      +    } else if (path === '$where') {
      +      type = typeof val;
      +
      +      if ('string' !== type && 'function' !== type) {
      +        throw new Error("Must have a string or function for $where");
      +      }
      +
      +      if ('function' === type) {
      +        obj[path] = val.toString();
      +      }
      +
      +      continue;
      +
      +    } else {
      +
      +      if (!schema) {
      +        // no casting for Mixed types
      +        continue;
      +      }
      +
      +      schematype = schema.path(path);
      +
      +      if (!schematype) {
      +        // Handle potential embedded array queries
      +        var split = path.split('.')
      +          , j = split.length
      +          , pathFirstHalf
      +          , pathLastHalf
      +          , remainingConds
      +          , castingQuery;
      +
      +        // Find the part of the var path that is a path of the Schema
      +        while (j--) {
      +          pathFirstHalf = split.slice(0, j).join('.');
      +          schematype = schema.path(pathFirstHalf);
      +          if (schematype) break;
      +        }
      +
      +        // If a substring of the input path resolves to an actual real path...
      +        if (schematype) {
      +          // Apply the casting; similar code for $elemMatch in schema/array.js
      +          if (schematype.caster && schematype.caster.schema) {
      +            remainingConds = {};
      +            pathLastHalf = split.slice(j).join('.');
      +            remainingConds[pathLastHalf] = val;
      +            castingQuery = new Query(remainingConds);
      +            castingQuery.cast(schematype.caster);
      +            obj[path] = castingQuery._conditions[pathLastHalf];
      +          } else {
      +            obj[path] = val;
      +          }
      +        }
      +
      +      } else if (val === null || val === undefined) {
      +        continue;
      +      } else if ('Object' === val.constructor.name) {
      +
      +        any$conditionals = Object.keys(val).some(function (k) {
      +          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
      +        });
      +
      +        if (!any$conditionals) {
      +          obj[path] = schematype.castForQuery(val);
      +        } else {
      +
      +          var ks = Object.keys(val)
      +            , k = ks.length
      +            , $cond;
      +
      +          while (k--) {
      +            $cond = ks[k];
      +            nested = val[$cond];
      +
      +            if ('$exists' === $cond) {
      +              if ('boolean' !== typeof nested) {
      +                throw new Error("$exists parameter must be Boolean");
      +              }
      +              continue;
      +            }
      +
      +            if ('$type' === $cond) {
      +              if ('number' !== typeof nested) {
      +                throw new Error("$type parameter must be Number");
      +              }
      +              continue;
      +            }
      +
      +            if ('$not' === $cond) {
      +              this.cast(model, nested);
      +            } else {
      +              val[$cond] = schematype.castForQuery($cond, nested);
      +            }
      +          }
      +        }
      +      } else {
      +        obj[path] = schematype.castForQuery(val);
      +      }
      +    }
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Returns:

      Note

      + +

      If obj is present, it is cast instead of this query.


      Query#_optionsForExec(model)

      Returns default options.

      show code
      Query.prototype._optionsForExec = function (model) {
      +  var options = utils.clone(this.options, { retainKeyOrder: true });
      +  delete options.populate;
      +
      +  if (!('safe' in options))
      +    options.safe = model.schema.options.safe;
      +
      +  if (!('readPreference' in options) && model.schema.options.read)
      +    options.readPreference = model.schema.options.read;
      +
      +  return options;
      +};

      Parameters:


      Query#_applyPaths()

      Applies schematype selected options to this query.

      show code
      Query.prototype._applyPaths = function applyPaths () {
      +  // determine if query is selecting or excluding fields
      +
      +  var fields = this._fields
      +    , exclude
      +    , keys
      +    , ki
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('+' == keys[ki][0]) continue;
      +      exclude = 0 === fields[keys[ki]];
      +      break;
      +    }
      +  }
      +
      +  // if selecting, apply default schematype select:true fields
      +  // if excluding, apply schematype select:false fields
      +
      +  var selected = []
      +    , excluded = []
      +    , seen = [];
      +
      +  analyzeSchema(this.model.schema);
      +
      +  switch (exclude) {
      +    case true:
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +    case false:
      +      selected.length && this.select(selected.join(' '));
      +      break;
      +    case undefined:
      +      // user didn't specify fields, implies returning all fields.
      +      // only need to apply excluded fields
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +  }
      +
      +  return seen = excluded = selected = keys = fields = null;
      +
      +  function analyzeSchema (schema, prefix) {
      +    prefix || (prefix = '');
      +
      +    // avoid recursion
      +    if (~seen.indexOf(schema)) return;
      +    seen.push(schema);
      +
      +    schema.eachPath(function (path, type) {
      +      if (prefix) path = prefix + '.' + path;
      +
      +      // array of subdocs?
      +      if (type.schema) {
      +        analyzeSchema(type.schema, path);
      +      }
      +
      +      analyzePath(path, type);
      +    });
      +  }
      +
      +  function analyzePath (path, type) {
      +    if ('boolean' != typeof type.selected) return;
      +
      +    if (fields && ('+' + path) in fields) {
      +      // forced inclusion
      +      delete fields['+' + path];
      +
      +      // if there are other fields being included, add this one
      +      // if no other included fields, leave this out (implied inclusion)
      +      if (false === exclude && keys.length > 1) {
      +        fields[path] = 1;
      +      }
      +
      +      return
      +    };
      +
      +    ;(type.selected ? selected : excluded).push(path);
      +  }
      +}

      Query#$where(js)

      Specifies a $where condition

      Parameters:

      Returns:

      Use $where when you need to select documents using a JavaScript expression.

      + +

      Example

      + +
      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
      +
      +query.$where(function () {
      +  return this.comments.length &gt; 10 || this.name.length &gt; 5;
      +})

      Query#where([path], [val])

      Specifies a path for use with chaining.

      show code
      Query.prototype.where = function (path, val) {
      +  if (!arguments.length) return this;
      +
      +  if ('string' != typeof path) {
      +    throw new TypeError('path must be a string');
      +  }
      +
      +  this._currPath = path;
      +
      +  if (2 === arguments.length) {
      +    this._conditions[path] = val;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      // instead of writing:
      +User.find({age: {$gte: 21, $lte: 65}}, callback);
      +
      +// we can instead write:
      +User.where('age').gte(21).lte(65);
      +
      +// Moreover, you can also chain a bunch of these together:
      +
      +User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +.where('friends').slice(10)
      +.exec(callback)

      Query#equals(val)

      Specifies the complementary comparison value for paths specified with where()

      show code
      Query.prototype.equals = function equals (val) {
      +  var path = this._currPath;
      +  if (!path) throw new Error('equals() must be used after where()');
      +  this._conditions[path] = val;
      +  return this;
      +}

      Parameters:

      Returns:

      Example

      + +
      User.where('age').equals(49);
      +
      +// is the same as
      +
      +User.where('age', 49);

      Query#or(array)

      Specifies arguments for an $or condition.

      show code
      Query.prototype.or = function or (array) {
      +  var or = this._conditions.$or || (this._conditions.$or = []);
      +  if (!Array.isArray(array)) array = [array];
      +  or.push.apply(or, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.or([{ color: 'red' }, { status: 'emergency' }])

      Query#nor(array)

      Specifies arguments for a $nor condition.

      show code
      Query.prototype.nor = function nor (array) {
      +  var nor = this._conditions.$nor || (this._conditions.$nor = []);
      +  if (!Array.isArray(array)) array = [array];
      +  nor.push.apply(nor, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.nor([{ color: 'green' }, { status: 'ok' }])

      Query#gt(path, val)

      Specifies a $gt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.

      + +

      Example

      + +
      Thing.find().where('age').gt(21)
      +
      +// or
      +Thing.find().gt('age', 21)

      Query#gte(path, val)

      Specifies a $gte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lt(path, val)

      Specifies a $lt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lte(path, val)

      Specifies a $lte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#ne(path, val)

      Specifies a $ne query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#in(path, val)

      Specifies an $in query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#nin(path, val)

      Specifies an $nin query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#all(path, val)

      Specifies an $all query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#size(path, val)

      Specifies an $size query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#regex(path, val)

      Specifies a $regex query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#maxDistance(path, val)

      Specifies a $maxDistance query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#near(path, val)

      Specifies a $near condition

      show code
      Query.prototype.near = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$near = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#nearSphere(path, val)

      Specifies a $nearSphere condition.

      show code
      Query.prototype.nearSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$nearSphere = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#mod(path, val)

      Specifies a $mod condition

      show code
      Query.prototype.mod = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$mod = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#exists(path, val)

      Specifies an $exists condition

      show code
      Query.prototype.exists = function (path, val) {
      +  if (arguments.length === 0) {
      +    path = this._currPath
      +    val = true;
      +  } else if (arguments.length === 1) {
      +    if ('boolean' === typeof path) {
      +      val = path;
      +      path = this._currPath;
      +    } else {
      +      val = true;
      +    }
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$exists'] = val;
      +  return this;
      +};

      Parameters:

      Returns:


      Query#elemMatch(path, criteria)

      Specifies an $elemMatch condition

      show code
      Query.prototype.elemMatch = function (path, criteria) {
      +  var block;
      +  if ('Object' === path.constructor.name) {
      +    criteria = path;
      +    path = this._currPath;
      +  } else if ('function' === typeof path) {
      +    block = path;
      +    path = this._currPath;
      +  } else if ('Object' === criteria.constructor.name) {
      +  } else if ('function' === typeof criteria) {
      +    block = criteria;
      +  } else {
      +    throw new Error("Argument error");
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  if (block) {
      +    criteria = new Query();
      +    block(criteria);
      +    conds['$elemMatch'] = criteria._conditions;
      +  } else {
      +    conds['$elemMatch'] = criteria;
      +  }
      +  return this;
      +};
      +
      +// Spatial queries

      Parameters:

      Returns:

      Example

      + +
      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
      +
      +query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
      +
      +query.elemMatch('comment', function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})
      +
      +query.where('comment').elemMatch(function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})

      Query#box(path, val)

      Specifies a $box condition

      show code
      Query.prototype.box = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$box': [val.ll, val.ur]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var lowerLeft = [40.73083, -73.99756]
      +var upperRight= [40.741404,  -73.988135]
      +query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

      Query#center(path, val, [opts])

      Specifies a $center condition

      show code
      Query.prototype.center = function (path, val, opts) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$center': [val.center, val.radius]  };
      +
      +  // copy any options
      +  if (opts && 'Object' == opts.constructor.name) {
      +    utils.options(opts, conds.$within);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.center(area)

      Query#centerSphere(path, val)

      Specifies a $centerSphere condition

      show code
      Query.prototype.centerSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.centerSphere(area)

      Query#polygon(path, val)

      Specifies a $polygon condition

      show code
      Query.prototype.polygon = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$polygon': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      +query.where('loc').within.polygon(polyA)
      +
      +// or
      +var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      +query.where('loc').within.polygon(polyB)

      Query#select(arg)

      Specifies which document fields to include or exclude

      show code
      Query.prototype.select = function select (arg) {
      +  if (!arg) return this;
      +
      +  var fields = this._fields || (this._fields = {});
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      fields[field] = arg[field];
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var include = '-' == field[0] ? 0 : 1;
      +      if (include === 0) field = field.substring(1);
      +      fields[field] = include;
      +    });
      +  } else {
      +    throw new TypeError('Invalid select() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

      + +

      Example

      + +
      // include a and b, exclude c
      +query.select('a b -c');
      +
      +// or you may use object notation, useful when
      +// you have keys already prefixed with a "-"
      +query.select({a: 1, b: 1, c: 0});
      +
      +// force inclusion of field excluded at schema level
      +query.select('+path')
      + +

      NOTE:

      + +

      v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


      Query#slice(path, val)

      Specifies a $slice condition

      show code
      Query.prototype.slice = function (path, val) {
      +  if (arguments.length === 1) {
      +      val = path;
      +      path = this._currPath
      +  } else if (arguments.length === 2) {
      +    if ('number' === typeof path) {
      +      val = [path, val];
      +      path = this._currPath;
      +    }
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var myFields = this._fields || (this._fields = {});
      +  myFields[path] = { '$slice': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      query.slice('comments', 5)
      +query.slice('comments', -5)
      +query.slice('comments', [10, 5])
      +query.where('comments').slice(5)
      +query.where('comments').slice([-10, 5])

      Query#sort(arg)

      Sets the sort order

      show code
      Query.prototype.sort = function (arg) {
      +  if (!arg) return this;
      +
      +  var sort = this.options.sort || (this.options.sort = []);
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      push(sort, field, arg[field]);
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var ascend = '-' == field[0] ? -1 : 1;
      +      if (ascend === -1) field = field.substring(1);
      +      push(sort, field, ascend);
      +    });
      +  } else {
      +    throw new TypeError('Invalid sort() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

      + +

      If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

      + +

      Example

      + +
      // these are equivalent
      +query.sort({ field: 'asc', test: -1 });
      +query.sort('field -test');

      Query#limit(val)

      Specifies the limit option.

      Parameters:

      Example

      + +
      Kitten.find().limit(20)

      Query#skip(val)

      Specifies the skip option.

      Parameters:

      Example

      + +
      Kitten.find().skip(100).limit(20)

      Query#maxscan(val)

      Specifies the maxscan option.

      Parameters:

      Example

      + +
      Kitten.find().maxscan(100)

      Query#batchSize(val)

      Specifies the batchSize option.

      Parameters:

      Example

      + +
      Kitten.find().batchSize(100)

      Query#comment(val)

      Specifies the comment option.

      Parameters:

      Example

      + +
      Kitten.findOne(condition).comment('login query')

      Query#snapshot()

      Specifies this query as a snapshot query.

      show code
      Query.prototype.snapshot = function () {
      +  this.options.snapshot = true;
      +  return this;
      +};

      Returns:

      Example

      + +
      Kitten.find().snapshot()

      Query#hint(val)

      Sets query hints.

      show code
      Query.prototype.hint = function (val) {
      +  if (!val) return this;
      +
      +  var hint = this.options.hint || (this.options.hint = {});
      +
      +  if ('Object' === val.constructor.name) {
      +    // must keep object keys in order so don't use Object.keys()
      +    for (var k in val) {
      +      hint[k] = val[k];
      +    }
      +  } else {
      +    throw new TypeError('Invalid hint. ' + val);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Model.find().hint({ indexA: 1, indexB: -1})

      Query#slaveOk(v)

      Sets the slaveOk option.

      show code
      Query.prototype.slaveOk = function (v) {
      +  this.options.slaveOk = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Example:

      + +
      new Query().slaveOk() // true
      +new Query().slaveOk(true)
      +new Query().slaveOk(false)

      Query#read(pref, [tags])

      Sets the readPreference option for the query.

      show code
      Query.prototype.read = function (pref, tags) {
      +  this.options.readPreference = utils.readPref(pref, tags);
      +  return this;
      +}

      Parameters:

      • pref <String> one of the listed preference options or their aliases
      • [tags] <Array> optional tags for this query

      Returns:

      Example:

      + +
      new Query().read('primary')
      +new Query().read('p')  // same as primary
      +
      +new Query().read('primaryPreferred')
      +new Query().read('pp') // same as primaryPreferred
      +
      +new Query().read('secondary')
      +new Query().read('s')  // same as secondary
      +
      +new Query().read('secondaryPreferred')
      +new Query().read('sp') // same as secondaryPreferred
      +
      +new Query().read('nearest')
      +new Query().read('n')  // same as nearest
      +
      +// with tags
      +new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
      + +

      Preferences:

      + +
      primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
      +secondary            Read from secondary if available, otherwise error.
      +primaryPreferred     Read from primary if available, otherwise a secondary.
      +secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
      +nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
      + +

      Aliases

      + +
      p   primary
      +pp  primaryPreferred
      +s   secondary
      +sp  secondaryPreferred
      +n   nearest
      + +

      Read more about how to use read preferrences here and here.


      Query#lean(v)

      Sets the lean option.

      show code
      Query.prototype.lean = function (v) {
      +  this.options.lean = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

      + +

      This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

      + +

      Example:

      + +
      new Query().lean() // true
      +new Query().lean(true)
      +new Query().lean(false)
      +
      +Model.find().lean().exec();
      +
      +var leanStream = Model.find().lean().stream();

      Query#tailable(v)

      Sets tailable option.

      show code
      Query.prototype.tailable = function (v) {
      +  this.options.tailable = arguments.length ? !!v : true;
      +  return this;
      +};

      Parameters:

      Example

      + +
      Kitten.find().tailable() &lt;== true
      +Kitten.find().tailable(true)
      +Kitten.find().tailable(false)

      Query#execFind(callback)

      Executes the query as a find() operation.

      show code
      Query.prototype.execFind = function (callback) {
      +  var model = this.model
      +    , promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.find(castQuery, options, function (err, cursor) {
      +    if (err) return promise.error(err);
      +    cursor.toArray(tick(cb));
      +  });
      +
      +  function cb (err, docs) {
      +    if (err) return promise.error(err);
      +
      +    if (true === options.lean)
      +      return promise.complete(docs);
      +
      +    var arr = []
      +      , count = docs.length;
      +
      +    if (!count) return promise.complete([]);
      +
      +    for (var i = 0, l = docs.length; i < l; i++) {
      +      arr[i] = new model(undefined, fields, true);
      +      arr[i].init(docs[i], self, function (err) {
      +        if (err) return promise.error(err);
      +        --count || promise.complete(arr);
      +      });
      +    }
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#findOne(callback)

      Executes the query as a findOne() operation.

      show code
      Query.prototype.findOne = function (callback) {
      +  this.op = 'findOne';
      +
      +  if (!callback) return this;
      +
      +  var model = this.model;
      +  var promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.findOne(castQuery, options, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === options.lean) return promise.complete(doc);
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'white').findOne(function (err, kitten) {
      +  if (err) return handleError(err);
      +
      +  // kitten may be null if no document matched
      +  if (kitten) {
      +    ...
      +  }
      +})

      Query#count(callback)

      Exectues the query as a count() operation.

      show code
      Query.prototype.count = function (callback) {
      +  this.op = 'count';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.count(castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'black').count(function (err, count) {
      +  if (err) return handleError(err);
      +  console.log('there are %d black kittens', count);
      +})

      Query#distinct(field, callback)

      Executes this query as a distict() operation.

      show code
      Query.prototype.distinct = function (field, callback) {
      +  this.op = 'distinct';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.distinct(field, castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#update(doc, callback)

      Executes this query as an update() operation.

      show code
      Query.prototype.update = function update (doc, callback) {
      +  this.op = 'update';
      +  this._updateArg = doc;
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , fn = 'function' == typeof callback
      +    , castedQuery
      +    , castedDoc
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedQuery));
      +      return this;
      +    }
      +    throw castedQuery;
      +  }
      +
      +  castedDoc = castDoc(this);
      +  if (!castedDoc) {
      +    fn && process.nextTick(callback.bind(null, null, 0));
      +    return this;
      +  }
      +
      +  if (castedDoc instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedDoc));
      +      return this;
      +    }
      +    throw castedDoc;
      +  }
      +
      +  if (!fn) {
      +    delete options.safe;
      +  }
      +
      +  model.collection.update(castedQuery, castedDoc, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Returns:

      All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

      + +

      Example

      + +
      Model.update({..}, { title: 'remove words' }, ...)
      + +

      becomes

      + +
      Model.update({..}, { $set: { title: 'remove words' }}, ...)
      + +

      Note

      + +

      Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


      Query#_castUpdate(obj)

      Casts obj for an update command.

      show code
      Query.prototype._castUpdate = function _castUpdate (obj) {
      +  var ops = Object.keys(obj)
      +    , i = ops.length
      +    , ret = {}
      +    , hasKeys
      +    , val
      +
      +  while (i--) {
      +    var op = ops[i];
      +    if ('$' !== op[0]) {
      +      // fix up $set sugar
      +      if (!ret.$set) {
      +        if (obj.$set) {
      +          ret.$set = obj.$set;
      +        } else {
      +          ret.$set = {};
      +        }
      +      }
      +      ret.$set[op] = obj[op];
      +      ops.splice(i, 1);
      +      if (!~ops.indexOf('$set')) ops.push('$set');
      +    } else if ('$set' === op) {
      +      if (!ret.$set) {
      +        ret[op] = obj[op];
      +      }
      +    } else {
      +      ret[op] = obj[op];
      +    }
      +  }
      +
      +  // cast each value
      +  i = ops.length;
      +
      +  while (i--) {
      +    op = ops[i];
      +    val = ret[op];
      +    if ('Object' === val.constructor.name) {
      +      hasKeys |= this._walkUpdatePath(val, op);
      +    } else {
      +      var msg = 'Invalid atomic update value for ' + op + '. '
      +              + 'Expected an object, received ' + typeof val;
      +      throw new Error(msg);
      +    }
      +  }
      +
      +  return hasKeys && ret;
      +}

      Parameters:

      Returns:

      • <Object> obj after casting its values

      Query#_walkUpdatePath(obj, op, pref)

      Walk each path of obj and cast its values
      according to its schema.

      show code
      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
      +  var strict = this.model.schema.options.strict
      +    , prefix = pref ? pref + '.' : ''
      +    , keys = Object.keys(obj)
      +    , i = keys.length
      +    , hasKeys = false
      +    , schema
      +    , key
      +    , val
      +
      +  while (i--) {
      +    key = keys[i];
      +    val = obj[key];
      +
      +    if (val && 'Object' === val.constructor.name) {
      +      // watch for embedded doc schemas
      +      schema = this._getSchema(prefix + key);
      +      if (schema && schema.caster && op in castOps) {
      +        // embedded doc schema
      +
      +        if (strict && !schema) {
      +          // path is not in our strict schema
      +          if ('throw' == strict) {
      +            throw new Error('Field `' + key + '` is not in schema.');
      +          } else {
      +            // ignore paths not specified in schema
      +            delete obj[key];
      +          }
      +        } else {
      +          hasKeys = true;
      +          if ('$each' in val) {
      +            obj[key] = {
      +                $each: this._castUpdateVal(schema, val.$each, op)
      +            }
      +          } else {
      +            obj[key] = this._castUpdateVal(schema, val, op);
      +          }
      +        }
      +      } else {
      +        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
      +      }
      +    } else {
      +      schema = '$each' === key
      +        ? this._getSchema(pref)
      +        : this._getSchema(prefix + key);
      +
      +      var skip = strict &&
      +                 !schema &&
      +                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
      +
      +      if (skip) {
      +        if ('throw' == strict) {
      +          throw new Error('Field `' + prefix + key + '` is not in schema.');
      +        } else {
      +          delete obj[key];
      +        }
      +      } else {
      +        hasKeys = true;
      +        obj[key] = this._castUpdateVal(schema, val, op, key);
      +      }
      +    }
      +  }
      +  return hasKeys;
      +}

      Parameters:

      • obj <Object> - part of a query
      • op <String> - the atomic operator ($pull, $set, etc)
      • pref <String> - path prefix (internal only)

      Returns:

      • <Bool> true if this path has keys to update

      Query#_castUpdateVal(schema, val, op, [$conditional])

      Casts val according to schema and atomic op.

      show code
      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
      +  if (!schema) {
      +    // non-existing schema path
      +    return op in numberOps
      +      ? Number(val)
      +      : val
      +  }
      +
      +  if (schema.caster && op in castOps &&
      +    ('Object' === val.constructor.name || Array.isArray(val))) {
      +    // Cast values for ops that add data to MongoDB.
      +    // Ensures embedded documents get ObjectIds etc.
      +    var tmp = schema.cast(val);
      +
      +    if (Array.isArray(val)) {
      +      val = tmp;
      +    } else {
      +      val = tmp[0];
      +    }
      +  }
      +
      +  if (op in numberOps) return Number(val);
      +  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
      +  return schema.castForQuery(val)
      +}

      Parameters:


      Query#_getSchema(path)

      Finds the schema for path. This is different than
      calling schema.path as it also resolves paths with
      positional selectors (something.$.another.$.path).

      show code
      Query.prototype._getSchema = function _getSchema (path) {
      +  var schema = this.model.schema
      +    , pathschema = schema.path(path);
      +
      +  if (pathschema)
      +    return pathschema;
      +
      +  // look for arrays
      +  return (function search (parts, schema) {
      +    var p = parts.length + 1
      +      , foundschema
      +      , trypath
      +
      +    while (p--) {
      +      trypath = parts.slice(0, p).join('.');
      +      foundschema = schema.path(trypath);
      +      if (foundschema) {
      +        if (foundschema.caster) {
      +
      +          // array of Mixed?
      +          if (foundschema.caster instanceof Types.Mixed) {
      +            return foundschema.caster;
      +          }
      +
      +          // Now that we found the array, we need to check if there
      +          // are remaining document paths to look up for casting.
      +          // Also we need to handle array.$.path since schema.path
      +          // doesn't work for that.
      +          if (p !== parts.length) {
      +            if ('$' === parts[p]) {
      +              // comments.$.comments.$.title
      +              return search(parts.slice(p+1), foundschema.schema);
      +            } else {
      +              // this is the last path of the selector
      +              return search(parts.slice(p), foundschema.schema);
      +            }
      +          }
      +        }
      +        return foundschema;
      +      }
      +    }
      +  })(path.split('.'), schema)
      +}

      Parameters:


      Query#_castFields(fields)

      Casts selected field arguments for field selection with mongo 2.2

      show code
      Query.prototype._castFields = function _castFields (fields) {
      +  var selected
      +    , elemMatchKeys
      +    , keys
      +    , key
      +    , out
      +    , i
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    elemMatchKeys = [];
      +    i = keys.length;
      +
      +    // collect $elemMatch args
      +    while (i--) {
      +      key = keys[i];
      +      if (fields[key].$elemMatch) {
      +        selected || (selected = {});
      +        selected[key] = fields[key];
      +        elemMatchKeys.push(key);
      +      }
      +    }
      +  }
      +
      +  if (selected) {
      +    // they passed $elemMatch, cast em
      +    try {
      +      out = this.cast(this.model, selected);
      +    } catch (err) {
      +      return err;
      +    }
      +
      +    // apply the casted field args
      +    i = elemMatchKeys.length;
      +    while (i--) {
      +      key = elemMatchKeys[i];
      +      fields[key] = out[key];
      +    }
      +  }
      +
      +  return fields;
      +}

      Parameters:

      query.select({ ids: { $elemMatch: { $in: [hexString] }})

      Query#remove(callback)

      Executes this query as a remove() operation.

      show code
      Query.prototype.remove = function (callback) {
      +  this.op = 'remove';
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , cb = 'function' == typeof callback
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    if (cb) return callback(err);
      +    throw err;
      +  }
      +
      +  if (!cb) {
      +    delete options.safe;
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.remove(castQuery, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Example

      + +
      Cassette.where('artist').equals('Anne Murray').remove(callback)

      Query#findOneAndUpdate([query], [doc], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
      +  this.op = 'findOneAndUpdate';
      +
      +  switch (arguments.length) {
      +    case 3:
      +      if ('function' == typeof options)
      +        callback = options, options = {};
      +      break;
      +    case 2:
      +      if ('function' == typeof doc) {
      +        callback = doc;
      +        doc = query;
      +        query = undefined;
      +      }
      +      options = undefined;
      +      break;
      +    case 1:
      +      if ('function' == typeof query) {
      +        callback = query;
      +        query = options = doc = undefined;
      +      } else {
      +        doc = query;
      +        query = options = undefined;
      +      }
      +  }
      +
      +  // apply query
      +  if (query) {
      +    if ('Object' === query.constructor.name) {
      +      merge(this._conditions, query);
      +    } else if (query instanceof Query) {
      +      merge(this._conditions, query._conditions);
      +    } else if (query instanceof Document) {
      +      merge(this._conditions, query.toObject());
      +    }
      +  }
      +
      +  // apply doc
      +  if (doc) {
      +    merge(this._updateArg, doc);
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('update', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      query.findOneAndUpdate(conditions, update, options, callback) // executes
      +query.findOneAndUpdate(conditions, update, options)  // returns Query
      +query.findOneAndUpdate(conditions, update, callback) // executes
      +query.findOneAndUpdate(conditions, update)           // returns Query
      +query.findOneAndUpdate(callback)                     // executes
      +query.findOneAndUpdate()                             // returns Query

      Query#findOneAndRemove([conditions], [options], [callback])

      Issues a mongodb findAndModify remove command.

      show code
      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
      +  this.op = 'findOneAndRemove';
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = undefined;
      +  }
      +
      +  // apply conditions
      +  if (conditions) {
      +    if ('Object' === conditions.constructor.name) {
      +      merge(this._conditions, conditions);
      +    } else if (conditions instanceof Query) {
      +      merge(this._conditions, conditions._conditions);
      +    } else if (conditions instanceof Document) {
      +      merge(this._conditions, conditions.toObject());
      +    }
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('remove', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      A.where().findOneAndRemove(conditions, options, callback) // executes
      +A.where().findOneAndRemove(conditions, options)  // return Query
      +A.where().findOneAndRemove(conditions, callback) // executes
      +A.where().findOneAndRemove(conditions) // returns Query
      +A.where().findOneAndRemove(callback)   // executes
      +A.where().findOneAndRemove()           // returns Query

      Query#_findAndModify(type, callback)

      _findAndModify

      show code
      Query.prototype._findAndModify = function (type, callback) {
      +  var model = this.model
      +    , promise = new Promise(callback)
      +    , self = this
      +    , castedQuery
      +    , castedDoc
      +    , fields
      +    , sort
      +    , opts
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    process.nextTick(promise.error.bind(promise, castedQuery));
      +    return promise;
      +  }
      +
      +  opts = this._optionsForExec(model);
      +
      +  if ('remove' == type) {
      +    opts.remove = true;
      +  } else {
      +    if (!('new' in opts)) opts.new = true;
      +    if (!('upsert' in opts)) opts.upsert = false;
      +
      +    castedDoc = castDoc(this);
      +    if (!castedDoc) {
      +      if (opts.upsert) {
      +        // still need to do the upsert to empty doc
      +        castedDoc = { $set: {} };
      +      } else {
      +        return this.findOne(callback);
      +      }
      +    } else if (castedDoc instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, castedDoc));
      +      return promise;
      +    }
      +  }
      +
      +  if (this._fields) {
      +    fields = utils.clone(this._fields)
      +    opts.fields = this._castFields(fields);
      +    if (opts.fields instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, opts.fields));
      +      return promise;
      +    }
      +  }
      +
      +  // the driver needs a default
      +  sort = opts.sort || [];
      +
      +  model
      +  .collection
      +  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === opts.lean) {
      +      return promise.complete(doc);
      +    }
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return promise;
      +}

      Parameters:


      Query#populate(path, [fields], [model], [conditions], [options])

      Specifies paths which should be populated with other documents.

      show code
      Query.prototype.populate = function (path, fields, model, conditions, options) {
      +  if ('string' !== typeof model) {
      +    options = conditions;
      +    conditions = model;
      +    model = undefined;
      +  }
      +  // The order of fields/conditions args is opposite Model.find but
      +  // necessary to keep backward compatibility (fields could be
      +  // an array, string, or object literal).
      +  this.options.populate[path] =
      +    new PopulateOptions(fields, conditions, options, model);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

      + +

      Example:

      + +
      Kitten.findOne().populate('owner').exec(function (err, kitten) {
      +  console.log(kitten.owner.name) // Max
      +})

      Query#stream()

      Returns a stream interface

      show code
      Query.prototype.stream = function stream () {
      +  return new QueryStream(this);
      +}
      +
      +// helpers

      Returns:

      Example

      + +
      // follows the nodejs stream api
      +Thing.find({ name: /^hello/ }).stream().pipe(res)
      +
      +// manual streaming
      +var stream = Thing.find({ name: /^hello/ }).stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});

      Query#within

      Syntax sugar for expressive queries.

      + +

      Example

      + +
      query.within.box()
      +query.within.center()

      Returns:


    • querystream.js

      QueryStream(query)

      Provides a ReadStream interface for Queries.

      show code
      function QueryStream (query) {
      +  Stream.call(this);
      +
      +  this.query = query;
      +  this.readable = true;
      +  this.paused = false;
      +  this._cursor = null;
      +  this._destroyed = null;
      +  this._fields = null;
      +  this._buffer = null;
      +  this._inline = T_INIT;
      +  this._running = false;
      +
      +  // give time to hook up events
      +  var self = this;
      +  process.nextTick(function () {
      +    self._init();
      +  });
      +}

      Parameters:

      Inherits:

      Events:

      • data: emits a single Mongoose document

      • error: emits when an error occurs during streaming. This will emit before the close event.

      • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

      var stream = Model.find().stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});
      + +

      The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

      + +
      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

      QueryStream#_init()

      Initializes the query.

      show code
      QueryStream.prototype._init = function () {
      +  if (this._destroyed) return;
      +
      +  var query = this.query
      +    , model = query.model
      +    , options = query._optionsForExec(model)
      +    , self = this
      +
      +  try {
      +    query.cast(model);
      +  } catch (err) {
      +    return self.destroy(err);
      +  }
      +
      +  self._fields = utils.clone(query._fields);
      +  options.fields = query._castFields(self._fields);
      +
      +  model.collection.find(query._conditions, options, function (err, cursor) {
      +    if (err) return self.destroy(err);
      +    self._cursor = cursor;
      +    self._next();
      +  });
      +}

      QueryStream#_next()

      Trampoline for pulling the next doc from cursor.

      show code
      QueryStream.prototype._next = function _next () {
      +  if (this.paused || this._destroyed) {
      +    return this._running = false;
      +  }
      +
      +  this._running = true;
      +
      +  if (this._buffer && this._buffer.length) {
      +    var arg;
      +    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
      +      this._onNextObject.apply(this, arg);
      +    }
      +  }
      +
      +  // avoid stack overflows with large result sets.
      +  // trampoline instead of recursion.
      +  while (this.__next()) {}
      +}

      QueryStream#__next()

      Pulls the next doc from the cursor.

      show code
      QueryStream.prototype.__next = function () {
      +  if (this.paused || this._destroyed)
      +    return this._running = false;
      +
      +  var self = this;
      +  self._inline = T_INIT;
      +
      +  self._cursor.nextObject(function cursorcb (err, doc) {
      +    self._onNextObject(err, doc);
      +  });
      +
      +  // if onNextObject() was already called in this tick
      +  // return ourselves to the trampoline.
      +  if (T_CONT === this._inline) {
      +    return true;
      +  } else {
      +    // onNextObject() hasn't fired yet. tell onNextObject
      +    // that its ok to call _next b/c we are not within
      +    // the trampoline anymore.
      +    this._inline = T_IDLE;
      +  }
      +}

      QueryStream#_onNextObject(err, doc)

      Transforms raw docs returned from the cursor into a model instance.

      show code
      QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
      +  if (this._destroyed) return;
      +
      +  if (this.paused) {
      +    this._buffer || (this._buffer = []);
      +    this._buffer.push([err, doc]);
      +    return this._running = false;
      +  }
      +
      +  if (err) return this.destroy(err);
      +
      +  // when doc is null we hit the end of the cursor
      +  if (!doc) {
      +    this.emit('end');
      +    return this.destroy();
      +  }
      +
      +  if (this.query.options && true === this.query.options.lean)  {
      +    this.emit('data', doc);
      +
      +    // trampoline management
      +    if (T_IDLE === this._inline) {
      +      // no longer in trampoline. restart it.
      +      this._next();
      +    } else {
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      this._inline = T_CONT;
      +    }
      +    return;
      +  }
      +
      +  var instance = new this.query.model(undefined, this._fields, true);
      +
      +  var self = this;
      +  instance.init(doc, this.query, function (err) {
      +    if (err) return self.destroy(err);
      +    self.emit('data', instance);
      +
      +    // trampoline management
      +    if (T_IDLE === self._inline) {
      +      // no longer in trampoline. restart it.
      +      self._next();
      +    } else
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      self._inline = T_CONT;
      +  });
      +}

      Parameters:


      QueryStream#pause()

      Pauses this stream.

      show code
      QueryStream.prototype.pause = function () {
      +  this.paused = true;
      +}

      QueryStream#resume()

      Resumes this stream.

      show code
      QueryStream.prototype.resume = function () {
      +  this.paused = false;
      +
      +  if (!this._cursor) {
      +    // cannot start if not initialized
      +    return;
      +  }
      +
      +  // are we within the trampoline?
      +  if (T_INIT === this._inline) {
      +    return;
      +  }
      +
      +  if (!this._running) {
      +    // outside QueryStream control, need manual restart
      +    return this._next();
      +  }
      +}

      QueryStream#destroy([err])

      Destroys the stream, closing the underlying cursor. No more events will be emitted.

      show code
      QueryStream.prototype.destroy = function (err) {
      +  if (this._destroyed) return;
      +  this._destroyed = true;
      +  this._running = false;
      +  this.readable = false;
      +
      +  if (this._cursor) {
      +    this._cursor.close();
      +  }
      +
      +  if (err) {
      +    this.emit('error', err);
      +  }
      +
      +  this.emit('close');
      +}

      Parameters:


      QueryStream#pipe()

      Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

      See:

      Example:

      + +
      query.stream().pipe(writeStream [, options])
      + +

      This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      + +
      var format = new ArrayFormatter;
      +Events.find().stream().pipe(format).pipe(res);
      + +

      As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


      QueryStream#paused

      Flag stating whether or not this stream is paused.


      QueryStream#readable

      Flag stating whether or not this stream is readable.


    • schema/array.js

      SchemaArray(key, cast, options)

      Array SchemaType constructor

      show code
      function SchemaArray (key, cast, options) {
      +  if (cast) {
      +    var castOptions = {};
      +
      +    if ('Object' === cast.constructor.name) {
      +      if (cast.type) {
      +        // support { type: Woot }
      +        castOptions = cast;
      +        cast = cast.type;
      +        delete castOptions.type;
      +      } else {
      +        cast = Mixed;
      +      }
      +    }
      +
      +    var caster = cast.name in Types ? Types[cast.name] : cast;
      +    this.casterConstructor = caster;
      +    this.caster = new caster(null, castOptions);
      +  }
      +
      +  SchemaType.call(this, key, options);
      +
      +  var self = this
      +    , defaultArr
      +    , fn;
      +
      +  if (this.defaultValue) {
      +    defaultArr = this.defaultValue;
      +    fn = 'function' == typeof defaultArr;
      +  }
      +
      +  this.default(function(){
      +    var arr = fn ? defaultArr() : defaultArr || [];
      +    return new MongooseArray(arr, self.path, this);
      +  });
      +};

      Parameters:

      Inherits:


      SchemaArray#checkRequired(value)

      Check required

      show code
      SchemaArray.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      Parameters:


      SchemaArray#applyGetters(value, scope)

      Overrides the getters application for the population special-case

      show code
      SchemaArray.prototype.applyGetters = function (value, scope) {
      +  if (this.caster.options && this.caster.options.ref) {
      +    // means the object id was populated
      +    return value;
      +  }
      +
      +  return SchemaType.prototype.applyGetters.call(this, value, scope);
      +};

      Parameters:


      SchemaArray#cast(value, doc, init)

      Casts contents

      show code
      SchemaArray.prototype.cast = function (value, doc, init) {
      +  if (Array.isArray(value)) {
      +    if (!(value instanceof MongooseArray)) {
      +      value = new MongooseArray(value, this.path, doc);
      +    }
      +
      +    if (this.caster) {
      +      try {
      +        for (var i = 0, l = value.length; i < l; i++) {
      +          value[i] = this.caster.cast(value[i], doc, init);
      +        }
      +      } catch (e) {
      +        // rethrow
      +        throw new CastError(e.type, value);
      +      }
      +    }
      +
      +    return value;
      +  } else {
      +    return this.cast([value], doc, init);
      +  }
      +};

      Parameters:

      • value <Object>
      • doc <Document> document that triggers the casting
      • init <Boolean> whether this is an initialization cast

      SchemaArray#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaArray.prototype.castForQuery = function ($conditional, value) {
      +  var handler
      +    , val;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Array.");
      +    val = handler.call(this, value);
      +  } else {
      +    val = $conditional;
      +    var proto = this.casterConstructor.prototype;
      +    var method = proto.castForQuery || proto.cast;
      +    if (Array.isArray(val)) {
      +      val = val.map(function (v) {
      +        if (method) v = method.call(proto, v);
      +        return isMongooseObject(v)
      +          ? v.toObject()
      +          : v;
      +      });
      +    } else if (method) {
      +      val = method.call(proto, val);
      +    }
      +  }
      +  return val && isMongooseObject(val)
      +    ? val.toObject()
      +    : val;
      +};

      Parameters:


    • schema/boolean.js

      SchemaBoolean(path, options)

      Boolean SchemaType constructor.

      show code
      function SchemaBoolean (path, options) {
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      SchemaBoolean#checkRequired()

      Required validator

      show code
      SchemaBoolean.prototype.checkRequired = function (value) {
      +  return value === true || value === false;
      +};

      SchemaBoolean#cast(value)

      Casts to boolean

      show code
      SchemaBoolean.prototype.cast = function (value) {
      +  if (value === null) return value;
      +  if (value === '0') return false;
      +  return !!value;
      +};

      Parameters:


      SchemaBoolean#castForQuery($conditional, val)

      Casts contents for queries.

      show code
      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (2 === arguments.length) {
      +    handler = SchemaBoolean.$conditionalHandlers[$conditional];
      +
      +    if (handler) {
      +      return handler.call(this, val);
      +    }
      +
      +    return this.cast(val);
      +  }
      +
      +  return this.cast($conditional);
      +};

      Parameters:


    • schema/buffer.js

      SchemaBuffer(key, cast)

      Buffer SchemaType constructor

      show code
      function SchemaBuffer (key, options) {
      +  SchemaType.call(this, key, options, 'Buffer');
      +};

      Parameters:

      Inherits:


      SchemaBuffer#checkRequired()

      Check required

      show code
      SchemaBuffer.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      SchemaBuffer#cast(value, doc, init)

      Casts contents

      show code
      SchemaBuffer.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (Buffer.isBuffer(value)) {
      +    if (!(value instanceof MongooseBuffer)) {
      +      value = new MongooseBuffer(value, [this.path, doc]);
      +    }
      +
      +    return value;
      +  } else if (value instanceof Binary) {
      +    return new MongooseBuffer(value.value(true), [this.path, doc]);
      +  }
      +
      +  if ('string' === typeof value || Array.isArray(value)) {
      +    return new MongooseBuffer(value, [this.path, doc]);
      +  }
      +
      +  throw new CastError('buffer', value);
      +};

      Parameters:


      SchemaBuffer#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Buffer.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    return this.cast(val).toObject();
      +  }
      +};

      Parameters:


    • schema/date.js

      SchemaDate(key, options)

      Date SchemaType constructor.

      show code
      function SchemaDate (key, options) {
      +  SchemaType.call(this, key, options);
      +};

      Parameters:

      Inherits:


      SchemaDate#checkRequired()

      Required validator for date

      show code
      SchemaDate.prototype.checkRequired = function (value) {
      +  return value instanceof Date;
      +};

      SchemaDate#cast(value)

      Casts to date

      show code
      SchemaDate.prototype.cast = function (value) {
      +  if (value === null || value === '')
      +    return null;
      +
      +  if (value instanceof Date)
      +    return value;
      +
      +  var date;
      +
      +  // support for timestamps
      +  if (value instanceof Number || 'number' == typeof value 
      +      || String(value) == Number(value))
      +    date = new Date(Number(value));
      +
      +  // support for date strings
      +  else if (value.toString)
      +    date = new Date(value.toString());
      +
      +  if (date.toString() != 'Invalid Date')
      +    return date;
      +
      +  throw new CastError('date', value);
      +};

      Parameters:


      SchemaDate#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaDate.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +
      +  if (2 !== arguments.length) {
      +    return this.cast($conditional);
      +  }
      +
      +  handler = this.$conditionalHandlers[$conditional];
      +
      +  if (!handler) {
      +    throw new Error("Can't use " + $conditional + " with Date.");
      +  }
      +
      +  return handler.call(this, val);
      +};

      Parameters:


    • schema/documentarray.js

      DocumentArray(key, schema, options)

      SubdocsArray SchemaType constructor

      show code
      function DocumentArray (key, schema, options) {
      +
      +  // compile an embedded document for this schema
      +  function EmbeddedDocument () {
      +    Subdocument.apply(this, arguments);
      +  }
      +
      +  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
      +  EmbeddedDocument.prototype._setSchema(schema);
      +  EmbeddedDocument.schema = schema;
      +
      +  // apply methods
      +  for (var i in schema.methods) {
      +    EmbeddedDocument.prototype[i] = schema.methods[i];
      +  }
      +
      +  // apply statics
      +  for (var i in schema.statics)
      +    EmbeddedDocument[i] = schema.statics[i];
      +
      +  EmbeddedDocument.options = options;
      +  this.schema = schema;
      +
      +  ArrayType.call(this, key, EmbeddedDocument, options);
      +
      +  this.schema = schema;
      +  var path = this.path;
      +  var fn = this.defaultValue;
      +
      +  this.default(function(){
      +    var arr = fn.call(this);
      +    if (!Array.isArray(arr)) arr = [arr];
      +    return new MongooseDocumentArray(arr, path, this);
      +  });
      +};

      Parameters:

      Inherits:


      DocumentArray#doValidate()

      Performs local validations first, then validations on each embedded doc

      show code
      DocumentArray.prototype.doValidate = function (array, fn, scope) {
      +  var self = this;
      +
      +  SchemaType.prototype.doValidate.call(this, array, function (err) {
      +    if (err) return fn(err);
      +
      +    var count = array && array.length
      +      , error;
      +
      +    if (!count) return fn();
      +
      +    // handle sparse arrays, do not use array.forEach which does not
      +    // iterate over sparse elements yet reports array.length including
      +    // them :(
      +
      +    for (var i = 0, len = count; i < len; ++i) {
      +      // sidestep sparse entries
      +      var doc = array[i];
      +      if (!doc) {
      +        --count || fn();
      +        continue;
      +      }
      +
      +      ;(function (i) {
      +        doc.validate(function (err) {
      +          if (err && !error) {
      +            // rewrite the key
      +            err.key = self.key + '.' + i + '.' + err.key;
      +            return fn(error = err);
      +          }
      +          --count || fn();
      +        });
      +      })(i);
      +    }
      +  }, scope);
      +};

      DocumentArray#cast(value, document)

      Casts contents

      show code
      DocumentArray.prototype.cast = function (value, doc, init, prev) {
      +  var selected
      +    , subdoc
      +    , i
      +
      +  if (!Array.isArray(value)) {
      +    return this.cast([value], doc, init, prev);
      +  }
      +
      +  if (!(value instanceof MongooseDocumentArray)) {
      +    value = new MongooseDocumentArray(value, this.path, doc);
      +  }
      +
      +  i = value.length;
      +
      +  while (i--) {
      +    if (!(value[i] instanceof Subdocument) && value[i]) {
      +      if (init) {
      +        selected || (selected = scopePaths(this, doc._selected, init));
      +        subdoc = new this.casterConstructor(null, value, true, selected);
      +        value[i] = subdoc.init(value[i]);
      +      } else {
      +        if (prev && (subdoc = prev.id(value[i]._id))) {
      +          // handle resetting doc with existing id but differing data
      +          // doc.array = [{ doc: 'val' }]
      +          subdoc.set(value[i]);
      +        } else {
      +          subdoc = new this.casterConstructor(value[i], value);
      +        }
      +
      +        // if set() is hooked it will have no return value
      +        // see gh-746
      +        value[i] = subdoc;
      +      }
      +    }
      +  }
      +
      +  return value;
      +}

      Parameters:


    • schema/mixed.js

      Mixed(path, options)

      Mixed SchemaType constructor.

      show code
      function Mixed (path, options) {
      +  // make sure empty array defaults are handled
      +  if (options &&
      +      options.default &&
      +      Array.isArray(options.default) &&
      +      0 === options.default.length) {
      +    options.default = Array;
      +  }
      +
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      Mixed#checkRequired()

      Required validator

      show code
      Mixed.prototype.checkRequired = function (val) {
      +  return true;
      +};

      Mixed#cast(value)

      Casts val for Mixed.

      show code
      Mixed.prototype.cast = function (val) {
      +  return val;
      +};

      Parameters:

      this is a no-op


      Mixed#castForQuery($cond, [val])

      Casts contents for queries.

      show code
      Mixed.prototype.castForQuery = function ($cond, val) {
      +  if (arguments.length === 2) return val;
      +  return $cond;
      +};

      Parameters:


    • schema/number.js

      SchemaNumber(key, options)

      Number SchemaType constructor.

      show code
      function SchemaNumber (key, options) {
      +  SchemaType.call(this, key, options, 'Number');
      +};

      Parameters:

      Inherits:


      SchemaNumber#checkRequired()

      Required validator for number

      show code
      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return typeof value == 'number' || value instanceof Number;
      +  }
      +};

      SchemaNumber#min(value, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.min = function (value, message) {
      +  if (this.minValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'min';
      +    });
      +  if (value != null)
      +    this.validators.push([function(v){
      +      return v === null || v >= value;
      +    }, 'min']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, min: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 9 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#max(maximum, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.max = function (value, message) {
      +  if (this.maxValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'max';
      +    });
      +  if (value != null)
      +    this.validators.push([this.maxValidator = function(v){
      +      return v === null || v <= value;
      +    }, 'max']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, max: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 11 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#cast(value, doc, init)

      Casts to number

      show code
      SchemaNumber.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (!isNaN(value)){
      +    if (null === value) return value;
      +    if ('' === value) return null;
      +    if ('string' == typeof value) value = Number(value);
      +    if (value instanceof Number) return value
      +    if ('number' == typeof value) return value;
      +    if (value.toString && !Array.isArray(value) &&
      +        value.toString() == Number(value)) {
      +      return new Number(value)
      +    }
      +  }
      +
      +  throw new CastError('number', value);
      +};

      Parameters:


      SchemaNumber#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Number.");
      +    return handler.call(this, val);
      +  } else {
      +    val = this.cast($conditional);
      +    return val == null ? val : val
      +  }
      +};

      Parameters:


    • schema/objectid.js

      ObjectId(key, options)

      ObjectId SchemaType constructor.

      show code
      function ObjectId (key, options) {
      +  SchemaType.call(this, key, options, 'ObjectID');
      +};

      Parameters:

      Inherits:


      ObjectId#checkRequired()

      Check required

      show code
      ObjectId.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return value instanceof oid;
      +  }
      +};

      ObjectId#cast(value, scope, init)

      Casts to ObjectId

      show code
      ObjectId.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (value === null) return value;
      +
      +  if (value instanceof oid)
      +    return value;
      +
      +  if (value._id && value._id instanceof oid)
      +    return value._id;
      +
      +  if (value.toString)
      +    return oid.fromString(value.toString());
      +
      +  throw new CastError('object id', value);
      +};

      Parameters:


      ObjectId#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      ObjectId.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with ObjectId.");
      +    return handler.call(this, val);
      +  } else {
      +    return this.cast($conditional);
      +  }
      +};

      Parameters:


      ObjectId#auto(turnOn)

      Adds an auto-generated ObjectId default if turnOn is true.

      show code
      ObjectId.prototype.auto = function (turnOn) {
      +  if (turnOn) {
      +    this.default(defaultId);
      +    this.set(resetId)
      +  }
      +};

      Parameters:

      • turnOn <Boolean> auto generated ObjectId defaults

    • schema/string.js

      SchemaString(key, options)

      String SchemaType constructor.

      show code
      function SchemaString (key, options) {
      +  this.enumValues = [];
      +  this.regExp = null;
      +  SchemaType.call(this, key, options, 'String');
      +};

      Parameters:

      Inherits:


      SchemaString#enum([args...])

      Adds enumeration values and a coinciding validator.

      show code
      SchemaString.prototype.enum = function () {
      +  var len = arguments.length;
      +  if (!len || undefined === arguments[0] || false === arguments[0]) {
      +    if (this.enumValidator){
      +      this.enumValidator = false;
      +      this.validators = this.validators.filter(function(v){
      +        return v[1] != 'enum';
      +      });
      +    }
      +    return;
      +  }
      +
      +  for (var i = 0; i < len; i++) {
      +    if (undefined !== arguments[i]) {
      +      this.enumValues.push(this.cast(arguments[i]));
      +    }
      +  }
      +
      +  if (!this.enumValidator) {
      +    var values = this.enumValues;
      +    this.enumValidator = function(v){
      +      return undefined === v || ~values.indexOf(v);
      +    };
      +    this.validators.push([this.enumValidator, 'enum']);
      +  }
      +};

      Parameters:

      • [args...] <String> enumeration values

      Example:

      + +
      var states = 'opening open closing closed'.split(' ')
      +var s = new Schema({ state: { type: String, enum: states })
      +var M = db.model('M', s)
      +var m = new M({ state: 'invalid' })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.state = 'open'
      +  m.save() // success
      +})

      SchemaString#lowercase()

      Adds a lowercase setter.

      show code
      SchemaString.prototype.lowercase = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.toLowerCase();
      +    return v;
      +  });
      +};

      Example:

      + +
      var s = new Schema({ email: { type: String, lowercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ email: 'SomeEmail@example.COM' });
      +console.log(m.email) // someemail@example.com
      +

      SchemaString#uppercase()

      Adds an uppercase setter.

      show code
      SchemaString.prototype.uppercase = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.toUpperCase();
      +    return v;
      +  });
      +};

      Example:

      + +
      var s = new Schema({ caps: { type: String, uppercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ caps: 'an example' });
      +console.log(m.caps) // AN EXAMPLE

      SchemaString#trim()

      Adds a trim setter.

      show code
      SchemaString.prototype.trim = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.trim();
      +    return v;
      +  });
      +};

      The string value will be trimmed when set.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, trim: true }})
      +var M = db.model('M', s)
      +var string = ' some name '
      +console.log(string.length) // 11
      +var m = new M({ name: string })
      +console.log(m.name.length) // 9

      SchemaString#match(regExp)

      Sets a regexp validator.

      show code
      SchemaString.prototype.match = function match (regExp) {
      +  this.validators.push([function(v){
      +    return null != v && '' !== v
      +      ? regExp.test(v)
      +      : true
      +  }, 'regexp']);
      +};

      Parameters:

      • regExp <RegExp> regular expression to test against

      Any value that does not pass regExp.test(val) will fail validation.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, match: /^a/ }})
      +var M = db.model('M', s)
      +var m = new M({ name: 'invalid' })
      +m.validate(function (err) {
      +  console.error(err) // validation error
      +  m.name = 'apples'
      +  m.validate(function (err) {
      +    assert.ok(err) // success
      +  })
      +})

      SchemaString#checkRequired(value)

      Check required

      show code
      SchemaString.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return (value instanceof String || typeof value == 'string') && value.length;
      +  }
      +};

      Parameters:


      SchemaString#cast()

      Casts to String

      show code
      SchemaString.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +  if (value === null) return value;
      +  if ('undefined' !== typeof value && value.toString) return value.toString();
      +  throw new CastError('string', value);
      +};

      SchemaString#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      SchemaString.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with String.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    if (val instanceof RegExp) return val;
      +    return this.cast(val);
      +  }
      +};

      Parameters:


    • schema.js

      Schema(definition)

      Schema constructor.

      show code
      function Schema (obj, options) {
      +  if (!(this instanceof Schema))
      +    return new Schema(obj, options);
      +
      +  this.paths = {};
      +  this.subpaths = {};
      +  this.virtuals = {};
      +  this.nested = {};
      +  this.inherits = {};
      +  this.callQueue = [];
      +  this._indexes = [];
      +  this.methods = {};
      +  this.statics = {};
      +  this.tree = {};
      +  this._requiredpaths = undefined;
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // build paths
      +  if (obj) {
      +    this.add(obj);
      +  }
      +
      +  // ensure the documents get an auto _id unless disabled
      +  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
      +  if (auto_id) {
      +    this.add({ _id: {type: Schema.ObjectId, auto: true} });
      +  }
      +
      +  // ensure the documents receive an id getter unless disabled
      +  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
      +  if (autoid) {
      +    this.virtual('id').get(idGetter);
      +  }
      +
      +  // versioning not directly added to schema b/c we only want
      +  // it in the top level document, not embedded ones.
      +};

      Parameters:

      Events:

      • init: Emitted after the schema is compiled into a Model.

      Example:

      + +
      var child = new Schema({ name: String });
      +var schema = new Schema({ name: String, age: Number, children: [child] });
      +var Tree = mongoose.model('Tree', schema);
      +
      +// setting schema options
      +new Schema({ name: String }, { _id: false, autoIndex: false })
      + +

      Options:

      + +
        +
      • safe: bool - defaults to true.
      • +
      • read: string
      • +
      • strict: bool - defaults to true
      • +
      • capped: bool - defaults to false
      • +
      • versionKey: bool - defaults to "__v"
      • +
      • shardKey: bool - defaults to null
      • +
      • autoIndex: bool - defaults to true
      • +
      • _id: bool - defaults to true
      • +
      • id: bool - defaults to true
      • +
      • toObject - object - no default
      • +
      • toJSON - object - no default
      • +
      • minimize: bool - controls document#toObject behavior when called manually - defaults to true
      • +
      + +

      Note:

      + +

      When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


      Schema#defaultOptions(options)

      Returns default options for this schema, merged with options.

      show code
      Schema.prototype.defaultOptions = function (options) {
      +  options = utils.options({
      +      safe: true
      +    , strict: true
      +    , capped: false // { size, max, autoIndexId }
      +    , versionKey: '__v'
      +    , minimize: true
      +    , autoIndex: true
      +    , shardKey: null
      +    , read: null
      +    // the following are only applied at construction time
      +    , noId: false // deprecated, use { _id: false }
      +    , _id: true
      +    , noVirtualId: false // deprecated, use { id: false }
      +    , id: true
      +  }, options);
      +
      +  if (options.read)
      +    options.read = utils.readPref(options.read);
      +
      +  return options;
      +}

      Parameters:

      Returns:


      Schema#add(obj, prefix)

      Adds key path / schema type pairs to this schema.

      show code
      Schema.prototype.add = function add (obj, prefix) {
      +  prefix = prefix || '';
      +  for (var i in obj) {
      +    if (null == obj[i]) {
      +      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
      +    }
      +
      +    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
      +      if (Object.keys(obj[i]).length) {
      +        // nested object { last: { name: String }}
      +        this.nested[prefix + i] = true;
      +        this.add(obj[i], prefix + i + '.');
      +      }
      +      else
      +        this.path(prefix + i, obj[i]); // mixed type
      +    } else
      +      this.path(prefix + i, obj[i]);
      +  }
      +};

      Parameters:

      Example:

      + +
      var ToySchema = new Schema;
      +ToySchema.add({ name: 'string', color: 'string', price: 'number' });

      Schema#path(path, constructor)

      Gets/sets schema paths.

      show code
      Schema.prototype.path = function (path, obj) {
      +  if (obj == undefined) {
      +    if (this.paths[path]) return this.paths[path];
      +    if (this.subpaths[path]) return this.subpaths[path];
      +
      +    // subpaths?
      +    return /\.\d+\.?$/.test(path)
      +      ? getPositionalPath(this, path)
      +      : undefined;
      +  }
      +
      +  // some path names conflict with document methods
      +  if (reserved[path]) {
      +    throw new Error("`" + path + "` may not be used as a schema pathname");
      +  }
      +
      +  // update the tree
      +  var subpaths = path.split(/\./)
      +    , last = subpaths.pop()
      +    , branch = this.tree;
      +
      +  subpaths.forEach(function(path) {
      +    if (!branch[path]) branch[path] = {};
      +    branch = branch[path];
      +  });
      +
      +  branch[last] = utils.clone(obj);
      +
      +  this.paths[path] = Schema.interpretAsType(path, obj);
      +  return this;
      +};

      Parameters:

      Sets a path (if arity 2)
      Gets a path (if arity 1)

      + +

      Example

      + +
      schema.path('name') // returns a SchemaType
      +schema.path('name', Number) // changes the schemaType of `name` to Number

      Schema#eachPath(fn)

      Iterates the schemas paths similar to Array#forEach.

      show code
      Schema.prototype.eachPath = function (fn) {
      +  var keys = Object.keys(this.paths)
      +    , len = keys.length;
      +
      +  for (var i = 0; i < len; ++i) {
      +    fn(keys[i], this.paths[keys[i]]);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      The callback is passed the pathname and schemaType as arguments on each iteration.


      Schema#requiredPaths()

      Returns an Array of path strings that are required by this schema.

      show code
      Schema.prototype.requiredPaths = function requiredPaths () {
      +  if (this._requiredpaths) return this._requiredpaths;
      +
      +  var paths = Object.keys(this.paths)
      +    , i = paths.length
      +    , ret = [];
      +
      +  while (i--) {
      +    var path = paths[i];
      +    if (this.paths[path].isRequired) ret.push(path);
      +  }
      +
      +  return this._requiredpaths = ret;
      +}

      Returns:


      Schema#pathType(path)

      Returns the pathType of path for this schema.

      show code
      Schema.prototype.pathType = function (path) {
      +  if (path in this.paths) return 'real';
      +  if (path in this.virtuals) return 'virtual';
      +  if (path in this.nested) return 'nested';
      +  if (path in this.subpaths) return 'real';
      +
      +  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
      +    return 'real';
      +  } else {
      +    return 'adhocOrUndefined'
      +  }
      +};

      Parameters:

      Returns:

      Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


      Schema#queue(name, args)

      Adds a method call to the queue.

      show code
      Schema.prototype.queue = function(name, args){
      +  this.callQueue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the document method to call later
      • args <Array> arguments to pass to the method

      Schema#pre(method, callback)

      Defines a pre hook for the document.

      show code
      Schema.prototype.pre = function(){
      +  return this.queue('pre', arguments);
      +};

      Parameters:

      Example

      + +
      var toySchema = new Schema(..);
      +
      +toySchema.pre('save', function (next) {
      +  if (!this.created) this.created = new Date;
      +  next();
      +})
      +
      +toySchema.pre('validate', function (next) {
      +  if (this.name != 'Woody') this.name = 'Woody';
      +  next();
      +})

      Schema#post(method, fn)

      Defines a post hook for the document.

      show code
      Schema.prototype.post = function(method, fn){
      +  return this.queue('on', arguments);
      +};

      Parameters:

      Post hooks fire on the event emitted from document instances of Models compiled from this schema.

      + +
      var schema = new Schema(..);
      +schema.post('save', function () {
      +  console.log('this fired after a document was saved');
      +});
      +
      +var Model = mongoose.model('Model', schema);
      +
      +var m = new Model(..);
      +m.save(function (err) {
      +  console.log('this fires after the `post` hook');
      +});

      Schema#plugin(plugin, opts)

      Registers a plugin for this schema.

      show code
      Schema.prototype.plugin = function (fn, opts) {
      +  fn(this, opts);
      +  return this;
      +};

      Parameters:


      Schema#method(method, [fn])

      Adds an instance method to documents constructed from Models compiled from this schema.

      show code
      Schema.prototype.method = function (name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.methods[i] = name[i];
      +  else
      +    this.methods[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = kittySchema = new Schema(..);
      +
      +schema.methods.meow = function () {
      +  console.log('meeeeeoooooooooooow');
      +})
      +
      +var Kitty = mongoose.model('Kitty', schema);
      +
      +var fizz = new Kitty;
      +fizz.meow(); // meeeeeooooooooooooow
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      + +
      schema.method({
      +    purr: function () {}
      +  , scratch: function () {}
      +});
      +
      +// later
      +fizz.purr();
      +fizz.scratch();

      Schema#static(name, fn)

      Adds static "class" methods to Models compiled from this schema.

      show code
      Schema.prototype.static = function(name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.statics[i] = name[i];
      +  else
      +    this.statics[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = new Schema(..);
      +schema.static('findByName', function (name, callback) {
      +  return this.find({ name: name }, callback);
      +});
      +
      +var Drink = mongoose.model('Drink', schema);
      +Drink.findByName('sanpellegrino', function (err, drinks) {
      +  //
      +});
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


      Schema#index(fields, [options])

      Defines an index (most likely compound) for this schema.

      show code
      Schema.prototype.index = function (fields, options) {
      +  options || (options = {});
      +
      +  if (options.expires)
      +    utils.expires(options);
      +
      +  this._indexes.push([fields, options]);
      +  return this;
      +};

      Parameters:

      Example

      + +
      schema.index({ first: 1, last: -1 })

      Schema#set(key, [value])

      Sets/gets a schema option.

      show code
      Schema.prototype.set = function (key, value, tags) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +
      +  this.options[key] = 'read' == key
      +    ? utils.readPref(value, tags)
      +    : value;
      +
      +  return this;
      +};

      Parameters:

      • key <String> option name
      • [value] <Object> if not passed, the current option value is returned

      Schema#indexes()

      Compiles indexes from fields and schema-level indexes

      show code
      Schema.prototype.indexes = function () {
      +  var indexes = []
      +    , seenSchemas = [];
      +
      +  collectIndexes(this);
      +
      +  return indexes;
      +
      +  function collectIndexes (schema, prefix) {
      +    if (~seenSchemas.indexOf(schema)) return;
      +    seenSchemas.push(schema);
      +
      +    var index;
      +    var paths = schema.paths;
      +    prefix = prefix || '';
      +
      +    for (var i in paths) {
      +      if (paths[i]) {
      +        if (paths[i] instanceof Types.DocumentArray) {
      +          collectIndexes(paths[i].schema, i + '.');
      +        } else {
      +          index = paths[i]._index;
      +
      +          if (index !== false && index !== null){
      +            var field = {};
      +            field[prefix + i] = '2d' === index ? index : 1;
      +            var options = 'Object' === index.constructor.name ? index : {};
      +            if (!('background' in options)) options.background = true;
      +            indexes.push([field, options]);
      +          }
      +        }
      +      }
      +    }
      +
      +    if (prefix) {
      +      fixSubIndexPaths(schema, prefix);
      +    } else {
      +      schema._indexes.forEach(function (index) {
      +        if (!('background' in index[1])) index[1].background = true;
      +      });
      +      indexes = indexes.concat(schema._indexes);
      +    }
      +  }

      Schema#virtual(name, [options])

      Creates a virtual type with the given name.

      show code
      Schema.prototype.virtual = function (name, options) {
      +  var virtuals = this.virtuals;
      +  var parts = name.split('.');
      +  return virtuals[name] = parts.reduce(function (mem, part, i) {
      +    mem[part] || (mem[part] = (i === parts.length-1)
      +                            ? new VirtualType(options, name)
      +                            : {});
      +    return mem[part];
      +  }, this.tree);
      +};

      Parameters:

      Returns:


      Schema#virtualpath(name)

      Returns the virtual type with the given name.

      show code
      Schema.prototype.virtualpath = function (name) {
      +  return this.virtuals[name];
      +};

      Parameters:

      Returns:


      Schema#namedScope()

      These still haven't been fixed. Once they're working we'll make them public again.

      show code
      Schema.prototype.namedScope = function (name, fn) {
      +  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
      +    , newScope = Object.create(namedScopes)
      +    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
      +  allScopes[name] = newScope;
      +  newScope.name = name;
      +  newScope.block = fn;
      +  newScope.query = new Query();
      +  newScope.decorate(namedScopes, {
      +    block0: function (block) {
      +      return function () {
      +        block.call(this.query);
      +        return this;
      +      };
      +    },
      +    blockN: function (block) {
      +      return function () {
      +        block.apply(this.query, arguments);
      +        return this;
      +      };
      +    },
      +    basic: function (query) {
      +      return function () {
      +        this.query.find(query);
      +        return this;
      +      };
      +    }
      +  });
      +  return newScope;
      +};

      Schema.reserved

      Reserved document keys.

      show code
      Schema.reserved = Object.create(null);
      +var reserved = Schema.reserved;
      +reserved.on =
      +reserved.db =
      +reserved.init =
      +reserved.isNew =
      +reserved.errors =
      +reserved.schema =
      +reserved.options =
      +reserved.modelName =
      +reserved.collection = 1;

      Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      + +
      on, db, init, isNew, errors, schema, options, modelName, collection
      + +

      NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

      + +
      var schema = new Schema(..);
      + schema.methods.init = function () {} // potentially breaking

      Schema.interpretAsType(path, obj)

      Converts type arguments into Mongoose Types.

      show code
      Schema.interpretAsType = function (path, obj) {
      +  if (obj.constructor.name != 'Object')
      +    obj = { type: obj };
      +
      +  // Get the type making sure to allow keys named "type"
      +  // and default to mixed if not specified.
      +  // { type: { type: String, default: 'freshcut' } }
      +  var type = obj.type && !obj.type.type
      +    ? obj.type
      +    : {};
      +
      +  if ('Object' == type.constructor.name || 'mixed' == type) {
      +    return new Types.Mixed(path, obj);
      +  }
      +
      +  if (Array.isArray(type) || Array == type || 'array' == type) {
      +    // if it was specified through { type } look for `cast`
      +    var cast = (Array == type || 'array' == type)
      +      ? obj.cast
      +      : type[0];
      +
      +    if (cast instanceof Schema) {
      +      return new Types.DocumentArray(path, cast, obj);
      +    }
      +
      +    if ('string' == typeof cast) {
      +      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
      +    } else if (cast && (!cast.type || cast.type.type)
      +                    && 'Object' == cast.constructor.name
      +                    && Object.keys(cast).length) {
      +      return new Types.DocumentArray(path, new Schema(cast), obj);
      +    }
      +
      +    return new Types.Array(path, cast || Types.Mixed, obj);
      +  }
      +
      +  var name = 'string' == typeof type
      +    ? type
      +    : type.name;
      +
      +  if (name) {
      +    name = name.charAt(0).toUpperCase() + name.substring(1);
      +  }
      +
      +  if (undefined == Types[name]) {
      +    throw new TypeError('Undefined type at `' + path +
      +        '`
      +  Did you try nesting Schemas? ' +
      +        'You can only nest using refs or arrays.');
      +  }
      +
      +  return new Types[name](path, obj);
      +};

      Parameters:


      Schema.Types

      The various Mongoose Schema Types.

      show code
      Schema.Types = require('./schema/index');

      Example:

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var ObjectId = mongoose.Schema.Types.ObjectId;
      + +

      Types:

      + +
        +
      • String
      • +
      • Number
      • +
      • Boolean | Bool
      • +
      • Array
      • +
      • Buffer
      • +
      • Date
      • +
      • ObjectId | Oid
      • +
      • Mixed
      • +
      + +

      Using this exposed access to the Mixed SchemaType, we can use them in our schema.

      + +
      var Mixed = mongoose.Schema.Types.Mixed;
      +new mongoose.Schema({ _user: Mixed })

      Schema#tree

      Schema as a tree

      + +

      Example:

      + +
      {
      +    '_id'     : ObjectId
      +  , 'nested'  : {
      +        'key' : String
      +    }
      +}

      Schema#paths

      Schema as flat paths

      + +

      Example:

      + +
      {
      +    '_id'        : SchemaType,
      +  , 'nested.key' : SchemaType,
      +}

    • schemadefault.js

      exports#system.profile

      Default model for querying the system.profiles collection.


    • schematype.js

      SchemaType(path, [options], [instance])

      SchemaType constructor

      show code
      function SchemaType (path, options, instance) {
      +  this.path = path;
      +  this.instance = instance;
      +  this.validators = [];
      +  this.setters = [];
      +  this.getters = [];
      +  this.options = options;
      +  this._index = null;
      +  this.selected;
      +
      +  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
      +    // { unique: true, index: true }
      +    if ('index' == i && this._index) continue;
      +
      +    var opts = Array.isArray(options[i])
      +      ? options[i]
      +      : [options[i]];
      +
      +    this[i].apply(this, opts);
      +  }
      +};

      Parameters:


      SchemaType#default(val)

      Sets a default value for this SchemaType.

      show code
      SchemaType.prototype.default = function (val) {
      +  if (1 === arguments.length) {
      +    this.defaultValue = typeof val === 'function'
      +      ? val
      +      : this.cast(val);
      +    return this;
      +  } else if (arguments.length > 1) {
      +    this.defaultValue = utils.args(arguments);
      +  }
      +  return this.defaultValue;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var schema = new Schema({ n: { type: Number, default: 10 })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.n) // 10
      + +

      Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

      + +

      Example:

      + +
      // values are cast:
      +var schema = new Schema({ aNumber: Number, default: "4.815162342" })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.aNumber) // 4.815162342
      +
      +// default unique objects for Mixed types:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default(function () {
      +  return {};
      +});
      +
      +// if we don't use a function to return object literals for Mixed defaults,
      +// each document will receive a reference to the same object literal creating
      +// a "shared" object instance:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default({});
      +var M = db.model('M', schema);
      +var m1 = new M;
      +m1.mixed.added = 1;
      +console.log(m1.mixed); // { added: 1 }
      +var m2 = new M;
      +console.log(m2.mixed); // { added: 1 }

      SchemaType#index(options)

      Declares the index options for this schematype.

      show code
      SchemaType.prototype.index = function (options) {
      +  this._index = options;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var s = new Schema({ name: { type: String, index: true })
      +var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
      +Schema.path('my.path').index(true);
      +Schema.path('my.path').index({ expires: 60 });
      +Schema.path('my.path').index({ unique: true, sparse: true });
      + +

      NOTE:

      + +

      Indexes are created in the background by default. Specify background: false to override.

      + +

      Direction doesn't matter for single key indexes


      SchemaType#unique(bool)

      Declares an unique index.

      show code
      SchemaType.prototype.unique = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.unique = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, unique: true })
      +Schema.path('name').index({ unique: true });

      SchemaType#sparse(bool)

      Declares a sparse index.

      show code
      SchemaType.prototype.sparse = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.sparse = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, sparse: true })
      +Schema.path('name').index({ sparse: true });

      SchemaType#expires(when)

      Declares a TTL index (rounded to the nearest second) for Date types only.

      show code
      SchemaType.prototype.expires = function (when) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.expires = when;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
      This index type is only compatible with Date types.

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({..}, { expires: 60*60*24 });
      + +

      expires utilizes the ms module from guille allowing us to use a friendlier syntax:

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({..}, { expires: '24h' });
      +
      +// expire in 1.5 hours
      +new Schema({..}, { expires: '1.5h' });
      +
      +// expire in 7 days
      +var schema = new Schema({..});
      +schema.expires('7d');

      SchemaType#set(fn)

      Adds a setter to this schematype.

      show code
      SchemaType.prototype.set = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A setter must be a function.');
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function capitalize (val) {
      +  if ('string' != typeof val) val = '';
      +  return val.charAt(0).toUpperCase() + val.substring(1);
      +}
      +
      +// defining within the schema
      +var s = new Schema({ name: { type: String, set: capitalize }})
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ name: String })
      +s.path('name').set(capitalize)
      + +

      Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

      + +

      You can set up email lower case normalization easily via a Mongoose setter.

      + +
      function toLower (v) {
      +  return v.toLowerCase();
      +}
      +
      +var UserSchema = new Schema({
      +  email: { type: String, set: toLower }
      +})
      +
      +var User = db.model('User', UserSchema)
      +
      +var user = new User({email: 'AVENUE@Q.COM'})
      +console.log(user.email); // 'avenue@q.com'
      +
      +// or
      +var user = new User
      +user.email = 'Avenue@Q.com'
      +console.log(user.email) // 'avenue@q.com'
      +
      + +

      As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

      + +
      new Schema({ email: { type: String, lowercase: true }})

      SchemaType#get(fn)

      Adds a getter to this schematype.

      show code
      SchemaType.prototype.get = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A getter must be a function.');
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function dob (val) {
      +  if (!val) return val;
      +  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      +}
      +
      +// defining within the schema
      +var s = new Schema({ born: { type: Date, get: dob })
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ born: Date })
      +s.path('born').get(dob)
      + +

      Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

      + +

      Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

      + +
      function obfuscate (cc) {
      +  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
      +}
      +
      +var AccountSchema = new Schema({
      +  creditCardNumber: { type: String, get: obfuscate }
      +});
      +
      +var Account = db.model('Account', AccountSchema);
      +
      +Account.findById(id, function (err, found) {
      +  console.log(found.creditCardNumber); // '****-****-****-1234'
      +});

      SchemaType#validate(obj, [error])

      Adds validator(s) for this document path.

      show code
      SchemaType.prototype.validate = function (obj, error) {
      +  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
      +    this.validators.push([obj, error]);
      +    return this;
      +  }
      +
      +  var i = arguments.length
      +    , arg
      +
      +  while (i--) {
      +    arg = arguments[i];
      +    if (!(arg && 'Object' == arg.constructor.name)) {
      +      var msg = 'Invalid validator. Received (' + typeof arg + ') '
      +        + arg
      +        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
      +
      +      throw new Error(msg);
      +    }
      +    this.validate(arg.validator, arg.msg);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Validators must return Boolean. Returning false is interpreted as validation failure.

      + +

      Examples:

      + +
      function validator () { ... }
      +
      +var single = [validator, 'failed']
      +new Schema({ name: { type: String, validate: single }});
      +
      +var many = [
      +    { validator: validator, msg: 'uh oh' }
      +  , { validator: fn, msg: 'failed' }
      +]
      +new Schema({ name: { type: String, validate: many }});
      +
      +// or utilizing SchemaType methods directly:
      +
      +var schema = new Schema({ name: 'string' });
      +schema.path('name').validate(validator, 'validation failed');
      + +

      Asynchronous validation:

      + +

      Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

      + +
      schema.path('name').validate(function (value, respond) {
      +  doStuff(value, function () {
      +    ...
      +    respond(false); // validation failed
      +  })
      + }, 'my error type');
      + +

      Validation occurs pre('save') or whenever you manually execute document#validate.

      + +

      If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

      + +
      var conn = mongoose.createConnection(..);
      +conn.on('error', handleError);
      +
      +var Product = conn.model('Product', yourSchema);
      +var dvd = new Product(..);
      +dvd.save(); // emits error on the `conn` above
      + +

      If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

      + +
      // registering an error listener on the Model lets us handle errors more locally
      +Product.on('error', handleError);

      SchemaType#required(required)

      Adds a required validator to this schematype.

      show code
      SchemaType.prototype.required = function (required) {
      +  var self = this;
      +
      +  function __checkRequired (v) {
      +    // in here, `this` refers to the validating document.
      +    // no validation when this path wasn't selected in the query.
      +    if ('isSelected' in this &&
      +        !this.isSelected(self.path) &&
      +        !this.isModified(self.path)) return true;
      +    return self.checkRequired(v);
      +  }
      +
      +  if (false === required) {
      +    this.isRequired = false;
      +    this.validators = this.validators.filter(function (v) {
      +      return v[0].name !== '__checkRequired';
      +    });
      +  } else {
      +    this.isRequired = true;
      +    this.validators.push([__checkRequired, 'required']);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • required <Boolean> enable/disable the validator

      Returns:

      Example:

      + +
      var s = new Schema({ born: { type: Date, required: true })
      +// or
      +Schema.path('name').required(true);

      SchemaType#getDefault(scope, init)

      Gets the default value

      show code
      SchemaType.prototype.getDefault = function (scope, init) {
      +  var ret = 'function' === typeof this.defaultValue
      +    ? this.defaultValue.call(scope)
      +    : this.defaultValue;
      +
      +  if (null !== ret && undefined !== ret) {
      +    return this.cast(ret, scope, init);
      +  } else {
      +    return ret;
      +  }
      +};

      Parameters:

      • scope <Object> the scope which callback are executed
      • init <Boolean>

      SchemaType#applySetters(value, scope, init)

      Applies setters

      show code
      SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  var v = value
      +    , setters = this.setters
      +    , len = setters.length
      +
      +  if (!len) {
      +    if (null === v || undefined === v) return v;
      +    return init
      +      ? v // if we just initialized we dont recast
      +      : this.cast(v, scope, init, priorVal)
      +  }
      +
      +  while (len--) {
      +    v = setters[len].call(scope, v, this);
      +  }
      +
      +  if (null === v || undefined === v) return v;
      +
      +  // do not cast until all setters are applied #665
      +  v = this.cast(v, scope, init, priorVal);
      +
      +  return v;
      +};

      Parameters:


      SchemaType#applyGetters(value, scope)

      Applies getters to a value

      show code
      SchemaType.prototype.applyGetters = function (value, scope) {
      +  if (SchemaType._isRef(this, value, true)) return value;
      +
      +  var v = value
      +    , getters = this.getters
      +    , len = getters.length;
      +
      +  if (!len) {
      +    return v;
      +  }
      +
      +  while (len--) {
      +    v = getters[len].call(scope, v, this);
      +  }
      +
      +  return v;
      +};

      Parameters:


      SchemaType#select(val)

      Sets default select() behavior for this path.

      show code
      SchemaType.prototype.select = function select (val) {
      +  this.selected = !! val;
      +}

      Parameters:

      Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

      + +

      Example:

      + +
      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      +T.find(..); // field x will always be selected ..
      +// .. unless overridden;
      +T.find().select('-x').exec(callback);

      SchemaType#doValidate(value, callback, scope)

      Performs a validation of value using the validators declared for this SchemaType.

      show code
      SchemaType.prototype.doValidate = function (value, fn, scope) {
      +  var err = false
      +    , path = this.path
      +    , count = this.validators.length;
      +
      +  if (!count) return fn(null);
      +
      +  function validate (val, msg) {
      +    if (err) return;
      +    if (val === undefined || val) {
      +      --count || fn(null);
      +    } else {
      +      fn(err = new ValidatorError(path, msg));
      +    }
      +  }
      +
      +  this.validators.forEach(function (v) {
      +    var validator = v[0]
      +      , message   = v[1];
      +
      +    if (validator instanceof RegExp) {
      +      validate(validator.test(value), message);
      +    } else if ('function' === typeof validator) {
      +      if (2 === validator.length) {
      +        validator.call(scope, value, function (val) {
      +          validate(val, message);
      +        });
      +      } else {
      +        validate(validator.call(scope, value), message);
      +      }
      +    }
      +  });
      +};

      Parameters:


      SchemaType._isRef(self, value, init)

      Determines if value is a valid Reference.

      show code
      SchemaType._isRef = function (self, value, init) {
      +  if (init && self.options && self.options.ref) {
      +    if (null == value) return true;
      +    if (value._id && value._id.constructor.name === self.instance) return true;
      +  }
      +
      +  return false;
      +}

      Parameters:

      Returns:


    • types/array.js

      MongooseArray(values, path, doc)

      Mongoose Array constructor.

      show code
      function MongooseArray (values, path, doc) {
      +  var arr = [];
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:

      NOTE:

      + +

      Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


      MongooseArray#_cast(value)

      Casts a member based on this arrays schema.

      show code
      MongooseArray.prototype._cast = function (value) {
      +  var cast = this._schema.caster.cast
      +    , doc = this._parent;
      +
      +  return cast.call(null, value, doc);
      +};

      Parameters:

      Returns:

      • <value> the casted value

      MongooseArray#_markModified(embeddedDoc, embeddedPath)

      Marks this array as modified.

      show code
      MongooseArray.prototype._markModified = function (elem, embeddedPath) {
      +  var parent = this._parent
      +    , dirtyPath;
      +
      +  if (parent) {
      +    dirtyPath = this._path;
      +
      +    if (arguments.length) {
      +      if (null != embeddedPath) {
      +        // an embedded doc bubbled up the change
      +        dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
      +      } else {
      +        // directly set an index
      +        dirtyPath = dirtyPath + '.' + elem;
      +      }
      +
      +    }
      +    parent.markModified(dirtyPath);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
      • embeddedPath <String> the path which changed in the embeddedDoc

      If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


      MongooseArray#_registerAtomic(op, val)

      Register an atomic operation with the parent.

      show code
      MongooseArray.prototype._registerAtomic = function (op, val) {
      +  if ('$set' == op) {
      +    // $set takes precedence over all other ops.
      +    // mark entire array modified.
      +    this._atomics = { $set: val };
      +    this._markModified();
      +    return this;
      +  }
      +
      +  var atomics = this._atomics;
      +
      +  // reset pop/shift after save
      +  if ('$pop' == op && !('$pop' in atomics)) {
      +    var self = this;
      +    this._parent.once('save', function () {
      +      self._popped = self._shifted = null;
      +    });
      +  }
      +
      +  if (this._atomics.$set) {
      +    return this;
      +  }
      +
      +  // check for impossible $atomic combos (Mongo denies more than one
      +  // $atomic op on a single path
      +  if (Object.keys(atomics).length && !(op in atomics)) {
      +    // a different op was previously registered.
      +    // save the entire thing.
      +    this._atomics = { $set: this };
      +    this._markModified();
      +    return this;
      +  }
      +
      +  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
      +    atomics[op] || (atomics[op] = []);
      +    atomics[op] = atomics[op].concat(val);
      +  } else if (op === '$pullDocs') {
      +    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
      +      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
      +    selector['$in'] = selector['$in'].concat(val);
      +  } else {
      +    atomics[op] = val;
      +  }
      +
      +  this._markModified();
      +  return this;
      +};

      Parameters:


      MongooseArray#hasAtomics()

      Returns the number of pending atomic operations to send to the db for this array.

      show code
      MongooseArray.prototype.hasAtomics = function hasAtomics () {
      +  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
      +    return 0;
      +  }
      +
      +  return Object.keys(this._atomics).length;
      +}

      Returns:


      MongooseArray#push([args...])

      Wraps Array#push with proper change tracking.

      show code
      MongooseArray.prototype.push = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +
      +  // $pushAll might be fibbed (could be $push). But it makes it easier to
      +  // handle what could have been $push, $pushAll combos
      +  this._registerAtomic('$pushAll', values);
      +  return ret;
      +};

      Parameters:


      MongooseArray#nonAtomicPush([args...])

      Pushes items to the array non-atomically.

      show code
      MongooseArray.prototype.nonAtomicPush = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +};

      Parameters:

      • [args...] <any>

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$pop()

      Pops the array atomically at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var popped = doc.array.$pop();
      + console.log(popped); // 3
      + console.log(doc.array); // [1,2]
      +
      + // no affect
      + popped = doc.array.$pop();
      + console.log(doc.array); // [1,2]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $pop works again
      +   popped = doc.array.$pop();
      +   console.log(popped); // 2
      +   console.log(doc.array); // [1]
      + })

      MongooseArray#pop()

      Wraps Array#pop with proper change tracking.

      show code
      MongooseArray.prototype.pop = function () {
      +  var ret = [].pop.call(this);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +};

      Note:

      + +

      marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$shift()

      Atomically shifts the array at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var shifted = doc.array.$shift();
      + console.log(shifted); // 1
      + console.log(doc.array); // [2,3]
      +
      + // no affect
      + shifted = doc.array.$shift();
      + console.log(doc.array); // [2,3]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $shift works again
      +   shifted = doc.array.$shift();
      +   console.log(shifted ); // 2
      +   console.log(doc.array); // [3]
      + })

      MongooseArray#shift()

      Wraps Array#shift with proper change tracking.

      show code
      MongooseArray.prototype.shift = function () {
      +  var ret = [].shift.call(this);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +};

      Example:

      + +
      doc.array = [2,3];
      +var res = doc.array.shift();
      +console.log(res) // 2
      +console.log(doc.array) // [3]
      + +

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#remove([args...])

      Removes items from an array atomically

      show code
      MongooseArray.prototype.remove = function () {
      +  var args = [].map.call(arguments, this._cast, this);
      +  if (args.length == 1)
      +    this.pull(args[0]);
      +  else
      +    this.pull.apply(this, args);
      +  return args;
      +};

      Parameters:

      • [args...] <Object> values to remove

      Examples:

      + +
      doc.array.remove(ObjectId)
      +doc.array.remove('tag 1', 'tag 2')

      MongooseArray#pull([args...])

      Pulls items from the array atomically.

      show code
      MongooseArray.prototype.pull = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , cur = this._parent.get(this._path)
      +    , i = cur.length
      +    , mem;
      +
      +  while (i--) {
      +    mem = cur[i];
      +    if (mem instanceof EmbeddedDocument) {
      +      if (values.some(function (v) { return v.equals(mem); } )) {
      +        [].splice.call(cur, i, 1);
      +      }
      +    } else if (~cur.indexOf.call(values, mem)) {
      +      [].splice.call(cur, i, 1);
      +    }
      +  }
      +
      +  if (values[0] instanceof EmbeddedDocument) {
      +    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
      +  } else {
      +    this._registerAtomic('$pullAll', values);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • [args...] <any>

      MongooseArray#splice()

      Wraps Array#splice with proper change tracking and casting.

      show code
      MongooseArray.prototype.splice = function splice () {
      +  var ret, vals, i;
      +
      +  if (arguments.length) {
      +    vals = [];
      +    for (i = 0; i < arguments.length; ++i) {
      +      vals[i] = i < 2
      +        ? arguments[i]
      +        : this._cast(arguments[i]);
      +    }
      +    ret = [].splice.apply(this, vals);
      +    this._registerAtomic('$set', this);
      +  }
      +
      +  return ret;
      +}

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#unshift()

      Wraps Array#unshift with proper change tracking.

      show code
      MongooseArray.prototype.unshift = function () {
      +  var values = [].map.call(arguments, this._cast, this);
      +  [].unshift.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  return this.length;
      +};

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#sort()

      Wraps Array#sort with proper change tracking.

      show code
      MongooseArray.prototype.sort = function () {
      +  var ret = [].sort.apply(this, arguments);
      +  this._registerAtomic('$set', this);
      +  return ret;
      +}

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#addToSet([args...])

      Adds values to the array if not already present.

      show code
      MongooseArray.prototype.addToSet = function addToSet () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , added = []
      +    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
      +             values[0] instanceof Date ? 'date' :
      +             '';
      +
      +  values.forEach(function (v) {
      +    var found;
      +    switch (type) {
      +      case 'doc':
      +        found = this.some(function(doc){ return doc.equals(v) });
      +        break;
      +      case 'date':
      +        var val = +v;
      +        found = this.some(function(d){ return +d === val });
      +        break;
      +      default:
      +        found = ~this.indexOf(v);
      +    }
      +
      +    if (!found) {
      +      [].push.call(this, v);
      +      this._registerAtomic('$addToSet', v);
      +      [].push.call(added, v);
      +    }
      +  }, this);
      +
      +  return added;
      +};

      Parameters:

      • [args...] <any>

      Returns:

      • <Array> the values that were added

      Example:

      + +
      console.log(doc.array) // [2,3,4]
      +var added = doc.array.addToSet(4,5);
      +console.log(doc.array) // [2,3,4,5]
      +console.log(added)     // [5]

      MongooseArray#set()

      Sets the casted val at index i and marks the array modified.

      show code
      MongooseArray.prototype.set = function set (i, val) {
      +  this[i] = this._cast(val);
      +  this._markModified(i);
      +  return this;
      +}

      Returns:

      Example:

      + +
      // given documents based on the following
      +var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
      +
      +var doc = new Doc({ array: [2,3,4] })
      +
      +console.log(doc.array) // [2,3,4]
      +
      +doc.array.set(1,"5");
      +console.log(doc.array); // [2,5,4] // properly cast to number
      +doc.save() // the change is saved
      +
      +// VS not using array#set
      +doc.array[1] = "5";
      +console.log(doc.array); // [2,"5",4] // no casting
      +doc.save() // change is not saved

      MongooseArray#toObject(options)

      Returns a native js Array.

      show code
      MongooseArray.prototype.toObject = function (options) {
      +  if (options && options.depopulate && this[0] instanceof Document) {
      +    return this.map(function (doc) {
      +      return doc._id;
      +    });
      +  }
      +
      +  // return this.slice()?
      +  return this.map(function (doc) {
      +    return doc;
      +  });
      +};

      Parameters:

      Returns:


      MongooseArray#inspect()

      Helper for console.log

      show code
      MongooseArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    return ' ' + doc;
      +  }) + ' ]';
      +};

      MongooseArray#indexOf(obj)

      Return the index of obj or -1 if not found.

      show code
      MongooseArray.prototype.indexOf = function indexOf (obj) {
      +  if (obj instanceof ObjectId) obj = obj.toString();
      +  for (var i = 0, len = this.length; i < len; ++i) {
      +    if (obj == this[i])
      +      return i;
      +  }
      +  return -1;
      +};

      Parameters:

      • obj <Object> the item to look for

      Returns:


      MongooseArray#_parent

      Parent owner document


      MongooseArray#_atomics

      Stores a queue of atomic operations to perform


    • types/buffer.js

      MongooseBuffer(value, encode, offset)

      Mongoose Buffer constructor.

      show code
      function MongooseBuffer (value, encode, offset) {
      +  var length = arguments.length;
      +  var val;
      +
      +  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
      +    val = 0;
      +  } else {
      +    val = value;
      +  }
      +
      +  var encoding;
      +  var path;
      +  var doc;
      +
      +  if (Array.isArray(encode)) {
      +    // internal casting
      +    path = encode[0];
      +    doc = encode[1];
      +  } else {
      +    encoding = encode;
      +  }
      +
      +  var buf = new Buffer(val, encoding, offset);
      +  buf.__proto__ = MongooseBuffer.prototype;
      +
      +  // make sure these internal props don't show up in Object.keys()
      +  Object.defineProperties(buf, {
      +      validators: { value: [] }
      +    , _path: { value: path }
      +    , _parent: { value: doc }
      +  });
      +
      +  if (doc && "string" === typeof path) {
      +    Object.defineProperty(buf, '_schema', {
      +        value: doc.schema.path(path)
      +    });
      +  }
      +
      +  return buf;
      +};

      Parameters:

      Inherits:

      Values always have to be passed to the constructor to initialize.


      MongooseBuffer#_markModified()

      Marks this buffer as modified.

      show code
      MongooseBuffer.prototype._markModified = function () {
      +  var parent = this._parent;
      +
      +  if (parent) {
      +    parent.markModified(this._path);
      +  }
      +  return this;
      +};

      MongooseBuffer#write()

      Writes the buffer.

      show code
      MongooseBuffer.prototype.write = function () {
      +  var written = Buffer.prototype.write.apply(this, arguments);
      +
      +  if (written > 0) {
      +    this._markModified();
      +  }
      +
      +  return written;
      +};

      MongooseBuffer#copy(target)

      Copies the buffer.

      show code
      MongooseBuffer.prototype.copy = function (target) {
      +  var ret = Buffer.prototype.copy.apply(this, arguments);
      +
      +  if (target instanceof MongooseBuffer) {
      +    target._markModified();
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Note:

      + +

      Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


      MongooseBuffer#toObject([subtype])

      Converts this buffer to its Binary type representation.

      show code
      MongooseBuffer.prototype.toObject = function (subtype) {
      +  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
      +  return new Binary(this, subtype);
      +};

      Parameters:

      • [subtype] <Hex>

      Returns:

      SubTypes:

      + +
        +
      • 0x00: Binary/Generic
      • +
      • 0x01: Function
      • +
      • 0x02: Binary (Deprecated, 0x00 is new default)
      • +
      • 0x03: UUID
      • +
      • 0x04: MD5
      • +
      • 0x80: User Defined
      • +

      MongooseBuffer#_parent

      Parent owner document


    • types/documentarray.js

      MongooseDocumentArray(values, path, doc)

      DocumentArray constructor

      show code
      function MongooseDocumentArray (values, path, doc) {
      +  var arr = [];
      +
      +  // Values always have to be passed to the constructor to initialize, since
      +  // otherwise MongooseArray#push will mark the array as modified to the parent.
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseDocumentArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +    doc.on('save', arr.notify('save'));
      +    doc.on('isNew', arr.notify('isNew'));
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:


      MongooseDocumentArray#_cast()

      Overrides MongooseArray#cast

      show code
      MongooseDocumentArray.prototype._cast = function (value) {
      +  if (value instanceof this._schema.casterConstructor)
      +    return value;
      +
      +  return new this._schema.casterConstructor(value, this);
      +};

      MongooseDocumentArray#id(id)

      Searches array items for the first document with a matching id.

      show code
      MongooseDocumentArray.prototype.id = function (id) {
      +  var casted
      +    , _id;
      +
      +  try {
      +    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
      +  } catch (e) {
      +    casted = null;
      +  }
      +
      +  for (var i = 0, l = this.length; i < l; i++) {
      +    _id = this[i].get('_id');
      +    if (!(_id instanceof ObjectId)) {
      +      if (String(id) == _id)
      +        return this[i];
      +    } else {
      +      if (casted == _id)
      +        return this[i];
      +    }
      +  }
      +
      +  return null;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var embeddedDoc = m.array.id(some_id);

      MongooseDocumentArray#toObject()

      Returns a native js Array of plain js objects

      show code
      MongooseDocumentArray.prototype.toObject = function () {
      +  return this.map(function (doc) {
      +    return doc && doc.toObject() || null;
      +  });
      +};

      Returns:

      NOTE:

      + +

      Each sub-document is converted to a plain object by calling its #toObject method.


      MongooseDocumentArray#inspect()

      Helper for console.log

      show code
      MongooseDocumentArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    if (doc) {
      +      return doc.inspect
      +        ? doc.inspect()
      +        : util.inspect(doc)
      +    }
      +    return 'null'
      +  }).join('
      +') + ']';
      +};

      MongooseDocumentArray#create(obj)

      Creates a subdocument casted to this schema.

      show code
      MongooseDocumentArray.prototype.create = function (obj) {
      +  return new this._schema.casterConstructor(obj);
      +}

      Parameters:

      • obj <Object> the value to cast to this arrays SubDocument schema

      This is the same subdocument constructor used for casting.


      MongooseDocumentArray#notify(event)

      Creates a fn that notifies all child docs of event.

      show code
      MongooseDocumentArray.prototype.notify = function notify (event) {
      +  var self = this;
      +  return function notify (val) {
      +    var i = self.length;
      +    while (i--) {
      +      if (!self[i]) continue;
      +      self[i].emit(event, val);
      +    }
      +  }
      +}

      Parameters:

      Returns:


    • types/embedded.js

      EmbeddedDocument(obj, parentArr, skipId)

      EmbeddedDocument constructor.

      show code
      function EmbeddedDocument (obj, parentArr, skipId, fields) {
      +  if (parentArr) {
      +    this.__parentArray = parentArr;
      +    this.__parent = parentArr._parent;
      +  } else {
      +    this.__parentArray = undefined;
      +    this.__parent = undefined;
      +  }
      +
      +  Document.call(this, obj, fields, skipId);
      +
      +  var self = this;
      +  this.on('isNew', function (val) {
      +    self.isNew = val;
      +  });
      +};

      Parameters:

      Inherits:


      EmbeddedDocument#markModified(path)

      Marks the embedded doc modified.

      show code
      EmbeddedDocument.prototype.markModified = function (path) {
      +  if (!this.__parentArray) return;
      +
      +  this._activePaths.modify(path);
      +
      +  if (this.isNew) {
      +    // Mark the WHOLE parent array as modified
      +    // if this is a new document (i.e., we are initializing
      +    // a document),
      +    this.__parentArray._markModified();
      +  } else
      +    this.__parentArray._markModified(this, path);
      +};

      Parameters:

      • path <String> the path which changed

      Example:

      + +
      var doc = blogpost.comments.id(hexstring);
      +doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');

      EmbeddedDocument#save([fn])

      Used as a stub for hooks.js

      show code
      EmbeddedDocument.prototype.save = function(fn) {
      +  if (fn)
      +    fn(null);
      +  return this;
      +};

      Parameters:

      Returns:

      NOTE:

      + +

      This is a no-op. Does not actually save the doc to the db.


      EmbeddedDocument#remove([fn])

      Removes the subdocument from its parent array.

      show code
      EmbeddedDocument.prototype.remove = function (fn) {
      +  if (!this.__parentArray) return this;
      +
      +  var _id;
      +  if (!this.willRemove) {
      +    _id = this._doc._id;
      +    if (!_id) {
      +      throw new Error('For your own good, Mongoose does not know ' + 
      +                      'how to remove an EmbeddedDocument that has no _id');
      +    }
      +    this.__parentArray.pull({ _id: _id });
      +    this.willRemove = true;
      +  }
      +
      +  if (fn)
      +    fn(null);
      +
      +  return this;
      +};

      Parameters:


      EmbeddedDocument#update()

      Override #update method of parent documents.

      show code
      EmbeddedDocument.prototype.update = function () {
      +  throw new Error('The #update method is not available on EmbeddedDocuments');
      +}

      EmbeddedDocument#inspect()

      Helper for console.log

      show code
      EmbeddedDocument.prototype.inspect = function () {
      +  return inspect(this.toObject());
      +};

      EmbeddedDocument#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
      +  if (!this.__parent) return false;
      +  var index = this.__parentArray.indexOf(this);
      +  var parentPath = this.__parentArray._path;
      +  var fullPath = [parentPath, index, path].join('.');
      +  this.__parent.invalidate(fullPath, err);
      +  if (first)
      +    this._validationError = ownerDocument(this)._validationError;
      +  return true;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> error which states the reason `path` was invalid

      Returns:


      EmbeddedDocument#ownerDocument()

      Returns the top level document of this sub-document.

      show code
      EmbeddedDocument.prototype.ownerDocument = function () {
      +  return ownerDocument(this);
      +}

      Returns:


      EmbeddedDocument#parent()

      Returns this sub-documents parent document.

      show code
      EmbeddedDocument.prototype.parent = function () {
      +  return this.__parent;
      +}

      EmbeddedDocument#parentArray()

      Returns this sub-documents parent array.

      show code
      EmbeddedDocument.prototype.parentArray = function () {
      +  return this.__parentArray;
      +}

    • types/objectid.js

      ObjectId()

      ObjectId type constructor

      Example

      + +
      var id = new mongoose.Types.ObjectId;

      ObjectId.fromString(str)

      Creates an ObjectId from str

      show code
      ObjectId.fromString;

      Parameters:

      Returns:


      ObjectId.toString(oid)

      Converts oid to a string.

      show code
      ObjectId.toString;

      Parameters:

      Returns:


    • utils.js

      exports.toCollectionName(name)

      Produces a collection name from model name.

      show code
      exports.toCollectionName = function (name) {
      +  if ('system.profile' === name) return name;
      +  if ('system.indexes' === name) return name;
      +  return pluralize(name.toLowerCase());
      +};

      Parameters:

      Returns:


      exports.pluralization

      Pluralization rules.

      show code
      exports.pluralization = [
      +  [/(m)an$/gi, '$1en'],
      +  [/(pe)rson$/gi, '$1ople'],
      +  [/(child)$/gi, '$1ren'],
      +  [/^(ox)$/gi, '$1en'],
      +  [/(ax|test)is$/gi, '$1es'],
      +  [/(octop|vir)us$/gi, '$1i'],
      +  [/(alias|status)$/gi, '$1es'],
      +  [/(bu)s$/gi, '$1ses'],
      +  [/(buffal|tomat|potat)o$/gi, '$1oes'],
      +  [/([ti])um$/gi, '$1a'],
      +  [/sis$/gi, 'ses'],
      +  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
      +  [/(hive)$/gi, '$1s'],
      +  [/([^aeiouy]|qu)y$/gi, '$1ies'],
      +  [/(x|ch|ss|sh)$/gi, '$1es'],
      +  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
      +  [/([m|l])ouse$/gi, '$1ice'],
      +  [/(quiz)$/gi, '$1zes'],
      +  [/s$/gi, 's'],
      +  [/$/gi, 's']
      +];
      +var rules = exports.pluralization;

      These rules are applied while processing the argument to toCollectionName.


      exports.uncountables

      Uncountable words.

      show code
      exports.uncountables = [
      +  'advice',
      +  'energy',
      +  'excretion',
      +  'digestion',
      +  'cooperation',
      +  'health',
      +  'justice',
      +  'labour',
      +  'machinery',
      +  'equipment',
      +  'information',
      +  'pollution',
      +  'sewage',
      +  'paper',
      +  'money',
      +  'species',
      +  'series',
      +  'rain',
      +  'rice',
      +  'fish',
      +  'sheep',
      +  'moose',
      +  'deer',
      +  'news'
      +];
      +var uncountables = exports.uncountables;

      These words are applied while processing the argument to toCollectionName.


      exports.deepEqual(a, b)

      Determines if a and b are deep equal.

      show code
      exports.deepEqual = function deepEqual (a, b) {
      +  if (a === b) return true;
      +
      +  if (a instanceof Date && b instanceof Date)
      +    return a.getTime() === b.getTime();
      +
      +  if (a instanceof ObjectId && b instanceof ObjectId) {
      +    return a.toString() === b.toString();
      +  }
      +
      +  if (typeof a !== 'object' && typeof b !== 'object')
      +    return a == b;
      +
      +  if (a === null || b === null || a === undefined || b === undefined)
      +    return false
      +
      +  if (a.prototype !== b.prototype) return false;
      +
      +  // Handle MongooseNumbers
      +  if (a instanceof Number && b instanceof Number) {
      +    return a.valueOf() === b.valueOf();
      +  }
      +
      +  if (Buffer.isBuffer(a)) {
      +    if (!Buffer.isBuffer(b)) return false;
      +    if (a.length !== b.length) return false;
      +    for (var i = 0, len = a.length; i < len; ++i) {
      +      if (a[i] !== b[i]) return false;
      +    }
      +    return true;
      +  }
      +
      +  if (isMongooseObject(a)) a = a.toObject();
      +  if (isMongooseObject(b)) b = b.toObject();
      +
      +  try {
      +    var ka = Object.keys(a),
      +        kb = Object.keys(b),
      +        key, i;
      +  } catch (e) {//happens when one is a string literal and the other isn't
      +    return false;
      +  }
      +
      +  // having the same number of owned properties (keys incorporates
      +  // hasOwnProperty)
      +  if (ka.length != kb.length)
      +    return false;
      +
      +  //the same set of keys (although not necessarily the same order),
      +  ka.sort();
      +  kb.sort();
      +
      +  //~~~cheap key test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    if (ka[i] != kb[i])
      +      return false;
      +  }
      +
      +  //equivalent values for every corresponding key, and
      +  //~~~possibly expensive deep test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    key = ka[i];
      +    if (!deepEqual(a[key], b[key])) return false;
      +  }
      +
      +  return true;
      +};

      Parameters:

      • a <any> a value to compare to `b`
      • b <any> a value to compare to `a`

      Returns:

      Modified from node/lib/assert.js


      exports.clone(obj, options)

      Object clone with Mongoose natives support.

      show code
      exports.clone = function clone (obj, options) {
      +  if (obj === undefined || obj === null)
      +    return obj;
      +
      +  if (Array.isArray(obj))
      +    return cloneArray(obj, options);
      +
      +  if (isMongooseObject(obj)) {
      +    if (options && options.json && 'function' === typeof obj.toJSON) {
      +      return obj.toJSON(options);
      +    } else {
      +      return obj.toObject(options);
      +    }
      +  }
      +
      +  if ('Object' === obj.constructor.name)
      +    return cloneObject(obj, options);
      +
      +  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
      +    return new obj.constructor(+obj);
      +
      +  if ('RegExp' === obj.constructor.name)
      +    return new RegExp(obj.source);
      +
      +  if (obj instanceof ObjectId) {
      +    return new ObjectId(obj.id);
      +  }
      +
      +  if (obj.valueOf)
      +    return obj.valueOf();
      +};
      +var clone = exports.clone;

      Parameters:

      Returns:

      Creates a minimal data Object.
      It does not clone empty Arrays, empty Objects, and undefined values.
      This makes the data payload sent to MongoDB as minimal as possible.


      exports.options(defaults, options)

      Copies and merges options with defaults.

      show code
      exports.options = function (defaults, options) {
      +  var keys = Object.keys(defaults)
      +    , i = keys.length
      +    , k ;
      +
      +  options = options || {};
      +
      +  while (i--) {
      +    k = keys[i];
      +    if (!(k in options)) {
      +      options[k] = defaults[k];
      +    }
      +  }
      +
      +  return options;
      +};

      Parameters:

      Returns:


      exports.random()

      Generates a random string

      show code
      exports.random = function () {
      +  return Math.random().toString().substr(3);
      +};

      exports.merge(to, from)

      Merges from into to without overwriting existing properties.

      show code
      exports.merge = function merge (to, from) {
      +  var keys = Object.keys(from)
      +    , i = keys.length
      +    , key
      +
      +  while (i--) {
      +    key = keys[i];
      +    if ('undefined' === typeof to[key]) {
      +      to[key] = from[key];
      +    } else {
      +      merge(to[key], from[key]);
      +    }
      +  }
      +};

      Parameters:


      exports.args

      A faster Array.prototype.slice.call(arguments) alternative

      show code
      exports.args = sliced;

      exports.tick(callback)

      process.nextTick helper.

      show code
      exports.tick = function tick (callback) {
      +  if ('function' !== typeof callback) return;
      +  return function () {
      +    try {
      +      callback.apply(this, arguments);
      +    } catch (err) {
      +      // only nextTick on err to get out of
      +      // the event loop and avoid state corruption.
      +      process.nextTick(function () {
      +        throw err;
      +      });
      +    }
      +  }
      +}

      Parameters:

      Wraps callback in a try/catch + nextTick.

      + +

      node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


      exports.isMongooseObject(v)

      Returns if v is a mongoose object that has a toObject() method we can use.

      show code
      exports.isMongooseObject = function (v) {
      +  Document || (Document = require('./document'));
      +  MongooseArray || (MongooseArray = require('./types').Array);
      +  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
      +
      +  return v instanceof Document ||
      +         v instanceof MongooseArray ||
      +         v instanceof MongooseBuffer
      +}
      +var isMongooseObject = exports.isMongooseObject;

      Parameters:

      This is for compatibility with libs like Date.js which do foolish things to Natives.


      exports.expires(object)

      Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

      show code
      exports.expires = function expires (object) {
      +  if (!(object && 'Object' == object.constructor.name)) return;
      +  if (!('expires' in object)) return;
      +
      +  var when;
      +  if ('string' != typeof object.expires) {
      +    when = object.expires;
      +  } else {
      +    when = Math.round(ms(object.expires) / 1000);
      +  }
      +  object.expireAfterSeconds = when;
      +  delete object.expires;
      +}
      +
      +exports.readPref = function readPref (pref, tags) {
      +  if (Array.isArray(pref)) {
      +    tags = pref[1];
      +    pref = pref[0];
      +  }
      +
      +  switch (pref) {
      +    case 'p':
      +      pref = 'primary';
      +      break;
      +    case 'pp':
      +      pref = 'primaryPrefered';
      +      break;
      +    case 's':
      +      pref = 'secondary';
      +      break;
      +    case 'sp':
      +      pref = 'secondaryPrefered';
      +      break;
      +    case 'n':
      +      pref = 'nearest';
      +      break;
      +  }
      +
      +  return new ReadPref(pref, tags);
      +}

      Parameters:


    • virtualtype.js

      VirtualType()

      VirtualType constructor

      show code
      function VirtualType (options, name) {
      +  this.path = name;
      +  this.getters = [];
      +  this.setters = [];
      +  this.options = options || {};
      +}

      This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

      + +

      Example:

      + +
      var fullname = schema.virtual('fullname');
      +fullname instanceof mongoose.VirtualType // true

      VirtualType#get(fn)

      Defines a getter.

      show code
      VirtualType.prototype.get = function (fn) {
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.get(function () {
      +  return this.name.first + ' ' + this.name.last;
      +});

      VirtualType#set(fn)

      Defines a setter.

      show code
      VirtualType.prototype.set = function (fn) {
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.set(function (v) {
      +  var parts = v.split(' ');
      +  this.name.first = parts[0];
      +  this.name.last = parts[1];
      +});

      VirtualType#applyGetters(value, scope)

      Applies getters to value using optional scope.

      show code
      VirtualType.prototype.applyGetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.getters.length - 1; l >= 0; l--) {
      +    v = this.getters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all getters

      VirtualType#applySetters(value, scope)

      Applies setters to value using optional scope.

      show code
      VirtualType.prototype.applySetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.setters.length - 1; l >= 0; l--) {
      +    v = this.setters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all setters

    diff --git a/docs/3.2.x/docs/api.jade b/docs/3.2.x/docs/api.jade new file mode 100644 index 00000000000..1c264a12e82 --- /dev/null +++ b/docs/3.2.x/docs/api.jade @@ -0,0 +1,507 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose API v#{package.version} + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + style. + body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; + } + a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; + } + a:hover { + opacity: 0.8; + } + #wrap { + } + h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; + } + pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; + } + code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Monaco; + } + pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; + } + h3 { + padding: 20px 15px; + margin-left: -15px; + } + h3 code { + font-weight: normal; + } + hr { + height: 1px; + border: 0 none; + padding: 0; + margin: 60px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) + } + .doclinks hr { + margin: 10px 0; + } + li { + list-style: square; + } + #header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; + } + #header h1 { + margin-top: 0; + margin-bottom: 0; + } + #header h1 a { + text-decoration: none; + } + #header .mongoose { + font-size: 48px; + font-weight: 100; + color: #fff; + letter-spacing: -5px; + } + #links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + } + #links hr { + margin: 32px 0; + } + #content { + padding: 0; + margin: 0 0 30px 230px; + overflow-x: hidden; + } + #content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; + } + #content .controls:hover { + opacity: .9; + } + #content p { + word-wrap: break-word; + } + #content > ul { + margin: 0; + padding: 0; + } + .private { + display: none; + } + .section { + font-size: 15px; + } + .doclinks li.private a:before, + .doclinks .module.private a:before, + .doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; + } + #content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; + } + .module { + list-style: none; + padding: 30px 0 30px 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; + } + .module > * { + max-width: 700px; + } + .item:last-child { + margin-bottom: 90px; + } + .item:last-child > hr { + display: none; + } + .item h3 a { + color: #333; + text-decoration: none; + } + .property h3 span { + color: #444; + } + .description { + margin-top: 25px; + } + .sourcecode { + display: none; + } + .showcode { + font-size: 12px; + cursor: pointer; + display: none; + } + .load .showcode { + display: block; + } + .types a { + text-decoration: none; + } + @media only screen and (device-width: 768px) { + + } + @media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links hr { + display: none; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + .controls { display: none; } + } + body.api + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + hr + .doclinks + each item in docs + .file(class=item.hasPublic ? '' : 'private') + a.section(href='#' + item.title.replace(/[\.\/#]/g, '-'))= item.title + ul + each method in item.methods + if method.ctx && !method.ignore + li(class= method.isPrivate ? 'private' : '') + case method.ctx.type + when 'method' + id = method.ctx.constructor + '-' + method.ctx.name + when 'function' + id = method.ctx.name + default + id = '' + url = href(klass(item.title) + '_' + id) + a(href='#' + url)= method.ctx.name + each stat in item.statics + if stat.ctx && !stat.ignore + li(class= stat.isPrivate ? 'private' : '') + case stat.ctx.type + when 'method' + id = stat.ctx.receiver + '-' + stat.ctx.name + when 'property' + id = stat.ctx.receiver + '-' + stat.ctx.name + when 'function' + id = stat.ctx.name + url = href(klass(item.title) + '_' + id) + a(href='#' + url)= stat.ctx.name + each property in item.props + if property.ctx && !property.ignore + li(class= property.isPrivate ? 'private' : '') + construct = property.ctx.receiver || property.ctx.constructor + link = href(construct) + '-' + href(property.ctx.name) + url = href(klass(item.title) + '_' + link) + a(href='#' + url)= property.ctx.name + #content + .controls + label + input(type='checkbox') + | private + ul + each item in docs + li.module(class=item.hasPublic ? '' : 'private') + a(href=github + package.version + '/' + item.title, id=item.title.replace(/[\.\/#]/g, '-'))= item.title + each method in item.methods + div.item.method(class= method.isPrivate ? 'private' : 'public') + if method.ctx + case method.ctx.type + when 'method' + id = method.ctx.constructor + '-' + method.ctx.name + text = method.ctx.constructor + '#' + method.ctx.name + when 'function' + id = method.ctx.name + text = method.ctx.name + default + text = '' + url = href(klass(item.title) + '_' + text) + h3(id= url) + a(href= '#' + url) + = text + | ( + each tag, i in method.params + code= tag.name + if i+1 < method.params.length + | , + | ) + else + - // console.log('\nmissing method name', method); + h3 MISSING method name + != method.description.summary + if method.code + span.showcode show code + .sourcecode + != hl(method.code) + if method.params.length + .params + h4 Parameters: + ul + each tag in method.params + li + code= tag.name + if tag.types && tag.types.length + span.types + | < + each type, i in tag.types + != linktype(type) + if i+1 < tag.types.length + | , + | > + span= tag.description + if method.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in method.return.types + != linktype(type) + if i+1 < method.return.types.length + | , + | > + span= method.return.description + if method.inherits + .inherits + h4 Inherits: + ul + li + != method.inherits + if method.events && method.events.length + .events + h4 Events: + ul + each event in method.events + li + != event.string + if method.see.length + .see + h4 See: + ul.see + each see in method.see + li + url = see.url || see.local + a(href=url, title=see.title || see.local)= see.title || see.url || see.local + div.description + != method.description.body + hr(class= method.isPrivate ? 'private' : '') + each stat in item.statics + div.item.static(class= stat.isPrivate ? 'private' : 'public') + if stat.ctx + case stat.ctx.type + when 'method' + id = stat.ctx.receiver + '-' + stat.ctx.name + text = stat.ctx.receiver + '.' + stat.ctx.name + when 'property' + id = stat.ctx.receiver + '-' + stat.ctx.name + text = stat.ctx.receiver + '.' + stat.ctx.name + when 'function' + id = stat.ctx.name + text = stat.ctx.name + default + text = '' + url = href(klass(item.title) + '_' + id) + h3(id= url) + a(href= '#' + url) + = text + if 'property' != stat.ctx.type + | ( + each tag, i in stat.params + code= tag.name + if i+1 < stat.params.length + | , + | ) + else + - // console.log('\nmissing static name', stat); + h3 MISSING stat name + != stat.description.summary + if stat.code + span.showcode show code + .sourcecode + != hl(stat.code) + if stat.params.length + .params + h4 Parameters: + ul + each tag in stat.params + li + - if (!tag.name) + - // console.log(tag) + code= tag.name + if tag.types && tag.types.length + span.types + | < + each type, i in tag.types + != linktype(type) + if i+1 < tag.types.length + | , + | > + span= tag.description + if stat.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in stat.return.types + != linktype(type) + if i+1 < stat.return.types.length + | , + | > + span= stat.return.description + if stat.inherits + .inherits + h4 Inherits: + ul + li + != stat.inherits + if stat.see.length + .see + h4 See: + ul.see + each see in stat.see + li + url = see.url || see.local + a(href=url, title=see.title || see.local)= see.title || see.url || see.local + != stat.description.body + hr(class= stat.isPrivate ? 'private' : '') + each property in item.props + div.item.property(class= property.ignore || property.isPrivate ? 'private' : 'public') + construct = property.ctx.receiver || property.ctx.constructor + link = href(construct) + '-' + href(property.ctx.name) + url = href(klass(item.title) + '_' + link) + h3(id = url) + a(href= '#' + url) + = construct + '#' + span= property.ctx.name + != property.description.full + if property.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in property.return.types + != linktype(type) + if i+1 < property.return.types.length + | , + | > + span= property.return.description + hr(class= property.isPrivate ? 'private' : '') + script. + document.body.className = 'load'; + include includes/keen + script(src="/docs/js/zepto.min.js") + script. + $(".module").on("click", ".showcode", function (e) { + $(this).closest(".item").find(".sourcecode").first().toggle(); + }); + $("#content .controls input").on("click", function (e) { + $(".private").toggle() + }) diff --git a/docs/3.2.x/docs/connections.html b/docs/3.2.x/docs/connections.html new file mode 100644 index 00000000000..6d47687b51e --- /dev/null +++ b/docs/3.2.x/docs/connections.html @@ -0,0 +1,27 @@ +Mongoose Connecting to MongoDB v3.2.2Fork me on GitHub

    Connections

    We may connect to MongoDB by utilizing the mongoose.connect() method.

    mongoose.connect('mongodb://localhost/myapp');
    +

    This is the minimum needed to connect the myapp database running locally on the default port (27017). We may also specify several more parameters in the uri depending on your environment:

    mongoose.connect('mongodb://username:password@host:port/database');
    +

    Options

    The connect method also accepts an options object which will be passed on to the underlying driver.

    mongoose.connect(uri, options);
    +

    The following option keys are available:

    + +
     db      - passed to the connection db instance
    + server  - passed to the connection server instance(s)
    + replset - passed to the connection ReplSet instance
    + user    - username for authentication (if not specified in uri)
    + pass    - password for authentication (if not specified in uri)
    + +

    See the driver for more information about available options.

    + +

    Note: The server option auto_reconnect is defaulted to true.

    + +

    Note: The db option forceServerObjectId is set to false and cannot be overridden.

    ReplicaSet Connections

    The same method is used to connect to a replica set but instead of passing a single uri we pass a comma delimited list of uris.

    mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]);
    +

    NOTE: The database need only be specified in one of the uris.

    Multiple connections

    So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize mongoose.createConnection() which accepts all the arguments already discussed and returns a fresh connection for you.

    var conn = mongoose.createConnection('uri,uri,uri...', options);
    +

    Connection pools

    Each connection, whether created with mongoose.connect or mongoose.createConnection are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options:

    mongoose.createConnection(uri, { server: { poolSize: 10 }});
    +

    Next Up

    Now that we've covered connections, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

    diff --git a/docs/3.2.x/docs/connections.jade b/docs/3.2.x/docs/connections.jade new file mode 100644 index 00000000000..5e67abc8a4b --- /dev/null +++ b/docs/3.2.x/docs/connections.jade @@ -0,0 +1,65 @@ +extends layout + +block content + h2 Connections + :markdown + We may connect to MongoDB by utilizing the `mongoose.connect()` method. + + :js + mongoose.connect('mongodb://localhost/myapp'); + + :markdown + This is the minimum needed to connect the `myapp` database running locally on the default port (27017). We may also specify several more parameters in the `uri` depending on your environment: + + :js + mongoose.connect('mongodb://username:password@host:port/database'); + + h3 Options + :markdown + The `connect` method also accepts an `options` object which will be passed on to the underlying driver. + + :js + mongoose.connect(uri, options); + + :markdown + The following option keys are available: + + db - passed to the connection db instance + server - passed to the connection server instance(s) + replset - passed to the connection ReplSet instance + user - username for authentication (if not specified in uri) + pass - password for authentication (if not specified in uri) + + See the [driver](https://github.com/mongodb/node-mongodb-native) for more information about available options. + + _Note: The server option `auto_reconnect` is defaulted to true._ + + _Note: The db option `forceServerObjectId` is set to false and cannot be overridden._ + + h3 ReplicaSet Connections + :markdown + The same method is used to connect to a replica set but instead of passing a single `uri` we pass a comma delimited list of `uri`s. + + :js + mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]); + + :markdown + _NOTE: The `database` need only be specified in one of the `uri`s._ + + h3 Multiple connections + :markdown + So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize `mongoose.createConnection()` which accepts all the arguments already discussed and returns a fresh connection for you. + + :js + var conn = mongoose.createConnection('uri,uri,uri...', options); + + h3 Connection pools + :markdown + Each `connection`, whether created with `mongoose.connect` or `mongoose.createConnection` are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options: + + :js + mongoose.createConnection(uri, { server: { poolSize: 10 }}); + + h3#next Next Up + :markdown + Now that we've covered `connections`, let's take a look at how we can break pieces of our functionality out into reusable and shareable [plugins](/docs/plugins.html). diff --git a/docs/3.2.x/docs/contributing.html b/docs/3.2.x/docs/contributing.html new file mode 100644 index 00000000000..70f372138b1 --- /dev/null +++ b/docs/3.2.x/docs/contributing.html @@ -0,0 +1,9 @@ +Mongoose Contributing v3.2.2Fork me on GitHub

    Contributing

    Please read all about contributing here.

    diff --git a/docs/3.2.x/docs/contributing.jade b/docs/3.2.x/docs/contributing.jade new file mode 100644 index 00000000000..48d9a658aaf --- /dev/null +++ b/docs/3.2.x/docs/contributing.jade @@ -0,0 +1,8 @@ +extends layout + +block content + h2 Contributing + + :markdown + Please read all about contributing [here](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md). + diff --git a/docs/3.2.x/docs/css/default.css b/docs/3.2.x/docs/css/default.css new file mode 100644 index 00000000000..ccb22728ed3 --- /dev/null +++ b/docs/3.2.x/docs/css/default.css @@ -0,0 +1,135 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +pre code { + display: block; padding: 0.5em; + background: #F0F0F0; +} + +pre code, +pre .ruby .subst, +pre .tag .title, +pre .lisp .title, +pre .clojure .built_in, +pre .nginx .title { + color: black; +} + +pre .string, +pre .title, +pre .constant, +pre .parent, +pre .tag .value, +pre .rules .value, +pre .rules .value .number, +pre .preprocessor, +pre .ruby .symbol, +pre .ruby .symbol .string, +pre .ruby .symbol .keyword, +pre .ruby .symbol .keymethods, +pre .instancevar, +pre .aggregate, +pre .template_tag, +pre .django .variable, +pre .smalltalk .class, +pre .addition, +pre .flow, +pre .stream, +pre .bash .variable, +pre .apache .tag, +pre .apache .cbracket, +pre .tex .command, +pre .tex .special, +pre .erlang_repl .function_or_atom, +pre .markdown .header { + color: #800; +} + +pre .comment, +pre .annotation, +pre .template_comment, +pre .diff .header, +pre .chunk, +pre .markdown .blockquote { + color: #888; +} + +pre .number, +pre .date, +pre .regexp, +pre .literal, +pre .smalltalk .symbol, +pre .smalltalk .char, +pre .go .constant, +pre .change, +pre .markdown .bullet, +pre .markdown .link_url { + color: #080; +} + +pre .label, +pre .javadoc, +pre .ruby .string, +pre .decorator, +pre .filter .argument, +pre .localvars, +pre .array, +pre .attr_selector, +pre .important, +pre .pseudo, +pre .pi, +pre .doctype, +pre .deletion, +pre .envvar, +pre .shebang, +pre .apache .sqbracket, +pre .nginx .built_in, +pre .tex .formula, +pre .erlang_repl .reserved, +pre .input_number, +pre .markdown .link_label, +pre .vhdl .attribute, +pre .clojure .attribute { + color: #88F +} + +pre .keyword, +pre .id, +pre .phpdoc, +pre .title, +pre .built_in, +pre .aggregate, +pre .css .tag, +pre .javadoctag, +pre .phpdoc, +pre .yardoctag, +pre .smalltalk .class, +pre .winutils, +pre .bash .variable, +pre .apache .tag, +pre .go .typename, +pre .tex .command, +pre .markdown .strong, +pre .request, +pre .status { + font-weight: bold; +} + +pre .markdown .emphasis { + font-style: italic; +} + +pre .nginx .built_in { + font-weight: normal; +} + +pre .coffeescript .javascript, +pre .xml .css, +pre .xml .javascript, +pre .xml .vbscript, +pre .tex .formula { + opacity: 0.5; +} diff --git a/docs/3.2.x/docs/css/guide.css b/docs/3.2.x/docs/css/guide.css new file mode 100644 index 00000000000..69fe3f84a8e --- /dev/null +++ b/docs/3.2.x/docs/css/guide.css @@ -0,0 +1,281 @@ +html, body, #content { + height: 100%; +} +.module { + min-height: 100%; + box-sizing: border-box; +} +body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; +} +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; +} +code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Monaco; + /*text-shadow: 1px 2px 2px #555;*/ +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +h2 { + margin-top: 0; +} +h3 { padding-top: 35px; } +h3 code { + font-weight: normal; +} +hr { + display: none; + height: 1px; + border: 0 none; + padding: 0; + margin: 90px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) +} +.doclinks hr { + margin: 10px 0; +} +li { + list-style: square; +} +#header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +#header .mongoose { + font-size: 48px; + font-weight: 100; + color: #fff; + letter-spacing: -5px; +} +#links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; +} +#links .schematypes span { + display: none; +} +#content { + padding: 0; + margin: 0 0 0 230px; +} +#content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +#content .controls:hover { + opacity: .9; +} +#content p { + word-wrap: break-word; +} +#content > ul { + margin: 0; + padding: 0; +} +.private { + display: none; +} +.doclinks li.private a:before, +.doclinks .module.private a:before, +.doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; +} +#content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; +} +.module { + list-style: none; + padding: 30px 0 0 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; +} +.module > * { + max-width: 700px; +} +.item { + margin-bottom: 175px; +} +.item h3 a { + color: #333; + text-decoration: none; +} +.property h3 span { + color: #444; +} +.description { + margin-top: 25px; +} +.sourcecode { + display: none; +} +.showcode { + font-size: 12px; + cursor: pointer; + display: none; +} +.load .showcode { + display: block; +} +.types a { + text-decoration: none; +} +li.guide ul { + padding-left: 16px; +} + +@media only screen and (device-width: 768px) { + +} +@media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + html, body, #content { + height: auto; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + #links li.guide { + display: block; + width: 390px; + margin-bottom: 15px; + } + #links li.guide > a { + display: none; + } + #links li ul li { + width: 44%; + text-align: left; + } + #links li ul li ul li { + width: 95%; + } + #links .plugins, + #links .changelog { + display: none; + } + #links .schematypes span { + display: inline; + } + #links .double { + width: 332px; + } + #links .double > ul { + display: inline; + float: right; + } + #links .double > ul li { + width: 155px; + } +} diff --git a/docs/3.2.x/docs/css/style.css b/docs/3.2.x/docs/css/style.css new file mode 100644 index 00000000000..7f7362cf306 --- /dev/null +++ b/docs/3.2.x/docs/css/style.css @@ -0,0 +1,207 @@ +body { + font-family: 'Open Sans', Helvetica, Arial, FreeSans; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; +} +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { + width: 600px; + margin: 0 auto; + position:relative; +} +li { + list-style: square; +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: #eee; + padding: 5px; + border-radius: 3px; +} +code { + color: #333; + font-size: 11px; + font-family: Monaco; +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +#header { + text-align: center; + padding-top: 40px; +} +#header, h2, h3, .tagline, .blurb { + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +h2 { + margin: 30px 0; +} +h2 a { + font-size: 11px; + position: relative; + bottom: 4px; +} +#header .mongoose { + font-size: 146px; + font-weight: 100; + text-indent: -23px; +} +.load #header .mongoose { + letter-spacing: -14px; +} +.tagline { + color: #333; + font-size: 25px; + text-shadow: 1px 1px #f8f8f8; + text-align: center; +} +.blurb { + text-align: center; + font-style: oblique; + font-size: 12px; + margin-bottom: 20px; +} +.tagline a, .blurb a { + text-decoration: none; + color: #800; +} +#links { + margin: 30px 10px 46px; + text-align: center; + position: relative; +} +#links ul { + margin: 0; + padding: 0; +} +#links li { + display: inline-block; + margin: 0 15px; + background-color: #FEFEFE; +} +#links a { + background: #444; + padding: 9px 0px; + border-radius: 3px; + color: white; + width: 180px; + display: inline-block; + text-decoration: none; + text-transform: lowercase; + text-shadow: 1px 1px 7px #222; +} +#production ul { + padding: 0; +} +#production li { + list-style: none; + overflow: hidden; + display: inline-block; + height: 133px; +} +#production img { + width: 180px; + margin: 10px; +} +#production a { + -webkit-transition-property: opacity; + -moz-transition-property: opacity; + -o-transition-property: opacity; + transition-property: opacity; + -webkit-transition-duration: 0.25s; + -moz-transition-duration: 0.25s; + -o-transition-duration: 0.25s; + transition-duration: 0.25s; + opacity: 0.7; +} +#production a:hover { + opacity: 1.0; +} +#footer { + text-align: center; + font-size: 12px; + margin-bottom: 20px; +} +@media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header { + padding-top: 12px; + } + #header .mongoose { + text-align: center; + font-size: 65px; + font-weight: 100; + letter-spacing: -7px; + } + .load #header .mongoose { + letter-spacing: -7px; + } + .tagline { + text-align: center; + font-size: 14px; + } + .tagline a { + text-decoration: none; + } + .blurb { + font-size: 16px; + text-align: justify; + margin-top: 25px; + } + #links { + margin-bottom: 40px; + } + #links li { + padding: 8px 2px; + margin: 0 12px; + } + #links a { + background: #444; + padding: 7px 34px; + font-size: 15px; + } + #docs { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + #wrap { + width: auto; + padding: 0 5px; + } + #production li { + margin-bottom: 8px; + } + #production a { + opacity: 1; + } + #production img { + width: 100%; + } + .addyourown, .addyourown a { + width: 100%; + } +} diff --git a/docs/3.2.x/docs/documents.html b/docs/3.2.x/docs/documents.html new file mode 100644 index 00000000000..92a9a1fccaa --- /dev/null +++ b/docs/3.2.x/docs/documents.html @@ -0,0 +1,20 @@ +Mongoose Documents v3.2.2Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    +  if (err) return handleError(err);
    +  
    +  tank.size = 'large';
    +  tank.save(function (err) {
    +    if (err) return handleError(err);
    +    res.send(tank);
    +  });
    +});

    This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    +  if (err) return handleError(err);
    +  res.send(tank);
    +});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    diff --git a/docs/3.2.x/docs/documents.jade b/docs/3.2.x/docs/documents.jade new file mode 100644 index 00000000000..67134e821b3 --- /dev/null +++ b/docs/3.2.x/docs/documents.jade @@ -0,0 +1,42 @@ +extends layout + +block content + h2 Documents + :markdown + Mongoose [documents](./api.html#document-js) represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its [Model](./models.html). + h3 Retrieving + :markdown + There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on [querying](./queries.html) for detail. + h3 Updating + :markdown + There are a number of ways to update documents. We'll first look at a traditional approach using [findById](./api.html#model_Model-findById): + :js + Tank.findById(id, function (err, tank) { + if (err) return handleError(err); + + tank.size = 'large'; + tank.save(function (err) { + if (err) return handleError(err); + res.send(tank); + }); + }); + :markdown + This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model-update) is right for us: + :js + Tank.update({ _id: id }, { $set: { size: 'large' }}, callback); + :markdown + If we do need the document returned in our application there is another, often [better](./api.html#model_Model-findByIdAndUpdate), option: + :js + Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) { + if (err) return handleError(err); + res.send(tank); + }); + :markdown + The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model-findByIdAndRemove) [several](./api.html#model_Model-findOneAndUpdate) [variations](./api.html#model_Model-findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. + h3 Validating + :markdown + Documents are validated before they are saved. Read the [api](./api.html#document_Document-validate) docs or the [validation](./validation.html) chapter for detail. + + h3#next Next Up + :markdown + Now that we've covered `Documents`, let's take a look at [Sub-documents](/docs/subdocs.html). diff --git a/docs/3.2.x/docs/faq.html b/docs/3.2.x/docs/faq.html new file mode 100644 index 00000000000..c4a4511086b --- /dev/null +++ b/docs/3.2.x/docs/faq.html @@ -0,0 +1,31 @@ +Mongoose FAQ v3.2.2Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    +doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    +doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    +new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    +doc.user.remove();// ?
    +doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    + +

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    + +

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    +mongoose.connect(..);
    +mongoose.connection.on('error', handleError);
    +
    +// if connecting on a separate connection
    +var conn = mongoose.createConnection(..);
    +conn.on('error', handleError);
    +

    Something to add?

    + +

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    diff --git a/docs/3.2.x/docs/faq.jade b/docs/3.2.x/docs/faq.jade new file mode 100644 index 00000000000..07abc7ea928 --- /dev/null +++ b/docs/3.2.x/docs/faq.jade @@ -0,0 +1,63 @@ +extends layout + +block append style + style. + hr { + display: block; + margin: 30px 0; + } + +block content + h2 FAQ + :markdown + **Q**. Why don't my changes to arrays get saved when I update an element directly? + :js + doc.array[3] = 'changed'; + doc.save(); + :markdown + **A**. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving. + :js + doc.markModified('array'); + doc.save(); + hr + :markdown + **Q**. Why doesn't mongoose allow me to directly assign schemas to paths? + :js + var userSchema = new Schema({ name: String }); + new Schema({ user: userSchema }) + :markdown + **A**. Schemas have a one-to-one mapping with documents. Documents have `save` and `remove` methods along with their own `pre` and `post` hooks which would lead to code like the following: + :js + doc.user.save(); // ? + doc.user.remove();// ? + doc.save() + :markdown + We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling `save` on a sub-document is a no-op and exists only to support `pre` save hooks). In the future this is likely to be revisited. + hr + :markdown + **Q**. How can I enable debugging? + + **A**. Set the `debug` option to `true`: + :js + mongoose.set('debug', true) + hr + :markdown + **Q**. My `save()` callback never executes. What am I doing wrong? + + **A**. All `collection` actions (insert, remove, queries, etc) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. + :js + // if connecting on the default mongoose connection + mongoose.connect(..); + mongoose.connection.on('error', handleError); + + // if connecting on a separate connection + var conn = mongoose.createConnection(..); + conn.on('error', handleError); + + hr + :markdown + **Something to add?** + + If you'd like to contribute to this page, please [visit it](https://github.com/learnboost/mongoose/tree/master/docs/faq.jade) on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request. + br + diff --git a/docs/3.2.x/docs/guide.html b/docs/3.2.x/docs/guide.html new file mode 100644 index 00000000000..c76f95bb639 --- /dev/null +++ b/docs/3.2.x/docs/guide.html @@ -0,0 +1,187 @@ +Mongoose Schemas v3.2.2Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

    If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    +  title:  String,
    +  author: String,
    +  body:   String,
    +  comments: [{ body: String, date: Date }],
    +  date: { type: Date, default: Date.now },
    +  hidden: Boolean,
    +  meta: {
    +    votes: Number,
    +    favs:  Number
    +  }
    +});

    If you want to add additional keys later, use the Schema#add method.

    +Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. +Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    +
    +animalSchema.methods.findSimilarTypes = function (cb) {
    +  return this.model('Animal').find({ type: this.type }, cb);
    +}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    +var dog = new Animal({ type: 'dog' });
    +
    +dog.findSimilarTypes(function (err, dogs) {
    +  console.log(dogs); // woof
    +});

    Statics

    +Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    +  this.find({ name: new RegExp(name, 'i') }, cb);
    +}
    +
    +var Animal = mongoose.model('Animal', animalSchema);
    +Animal.findByName('fido', function (err, animals) {
    +  console.log(animals);
    +});

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });
    +

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index. It is recommended this behavior be disabled in production by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false);
    +// or
    +new Schema({..}, { autoIndex: false });
    +

    See also the Model#ensureIndexes method for more details.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    +  name: {
    +    first: String,
    +    last: String
    +  }
    +});
    +
    +var Person = mongoose.model('Person', personSchema);
    +
    +var bad = new Person({
    +    name: { first: 'Walter', last: 'White' }
    +});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    +  return this.name.first + ' ' + this.name.last;
    +});

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full); // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    +  var split = name.split(' ');
    +  this.name.first = split[0];
    +  this.name.last = split[1];
    +});
    +
    +...
    +
    +mad.name.full = 'Breaking Bad';
    +console.log(mad.name.first); // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    +
    +// or
    +
    +var schema = new Schema({..});
    +schema.set(option, value);
    +

    Valid options:

    + +

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false });
    +var Clock = db.model('Clock', schema);
    +Clock.ensureIndexes(callback);
    +

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 });

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });
    +

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // '50341373e894ad16347efe01'
    +
    +// disabled id
    +var schema = new Schema({ name: String }, { id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // undefined
    +

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    + +

    Pass this option during schema construction to prevent documents from getting an auto _id created.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
    +
    +// disabled _id
    +var schema = new Schema({ name: String }, { _id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { name: 'mongodb.org' }
    +

    option: read

    Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

    var schema = new Schema({..}, { read: 'primary' });            // also aliased as 'p'
    +var schema = new Schema({..}, { read: 'primaryPreferred' });   // aliased as 'pp'
    +var schema = new Schema({..}, { read: 'secondary' });          // aliased as 's'
    +var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp'
    +var schema = new Schema({..}, { read: 'nearest' });            // aliased as 'n'
    +

    The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'.

    + +

    The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

    + +

    NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

    // pings the replset members periodically to track network latency
    +// now `nearest` works as intended
    +var options = { replset: { strategy: 'ping' }};
    +mongoose.connect(uri, options);
    +
    +var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
    +mongoose.model('JellyBean', schema);
    +

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    +new Schema({ .. }, { safe: safe });
    +

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. +By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    + +

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
    +new Schema({ .. }, { safe: safe });
    +

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    +

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: strict

    The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save(); // iAmNotInTheSchema is not saved to the db
    +
    +// set to false..
    +var thingSchema = new Schema({..}, { strict: false });
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save(); // iAmNotInTheSchema is now saved to the db!!
    +

    This also affects the use of doc.set() to set a property value.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing;
    +thing.set('iAmNotInTheSchema', true);
    +thing.save(); // iAmNotInTheSchema is not saved to the db
    +

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = db.model('Thing');
    +var thing = new Thing(doc, true);  // enables strict mode
    +var thing = new Thing(doc, false); // disables strict mode
    +

    The strict option may also be set to "throw" which will cause errors to be produced instead of dropping the bad data.

    NOTE: do not set to false unless you have good reason.

    + +

    NOTE: in mongoose v2 the default was false.

    + +

    NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing;
    +thing.iAmNotInTheSchema = true;
    +thing.save(); // iAmNotInTheSchema is never saved to the db
    +

    option: toJSON

    Exactly the same as the toObject option but only applies when the documents toJSON method is called.

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toJSON', { getters: true, virtuals: false });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
    +console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +// since we know toJSON is called whenever a js object is stringified:
    +console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
    +

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    + +

    To have all virtuals show up in your console.log output, set the toObject option to { getters: true }:

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toObject', { getters: true });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { __v: 0, name: 'mongoose v3' }
    +
    +// customized versionKey
    +new Schema({..}, { versionKey: '_somethingElse' })
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    +

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false });
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'no versioning please' });
    +thing.save(); // { name: 'no versioning please' }
    +
    +

    Next Up

    Now that we've covered Schemas, let's take a look at SchemaTypes.

    diff --git a/docs/3.2.x/docs/guide.jade b/docs/3.2.x/docs/guide.jade new file mode 100644 index 00000000000..f28189e3079 --- /dev/null +++ b/docs/3.2.x/docs/guide.jade @@ -0,0 +1,450 @@ +extends layout + +block content + h2 Schemas + :markdown + If you haven't yet done so, please take a minute to read the [quickstart](./index.html) to get an idea of how Mongoose works. + :markdown + If you are migrating from 2.x to 3.x please take a moment to read the [migration guide](./migration.html). + :markdown + This page covers `Schema` [definition](#definition), [plugins](#plugins), instance [methods](#methods), [statics](#statics), [indexes](#indexes), [virtuals](#virtuals) and [options](#options). Let's start with `Schema` definition. + h3#definition Defining your schema + p + | Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection. + :js + var blogSchema = new Schema({ + title: String, + author: String, + body: String, + comments: [{ body: String, date: Date }], + date: { type: Date, default: Date.now }, + hidden: Boolean, + meta: { + votes: Number, + favs: Number + } + }); + p + em + | If you want to add additional keys later, use the + a(href="./api.html#schema_Schema-add") Schema#add + | method. + p + | Each key in our + code blogSchema + | defines a property in our documents which will be cast to its associated + a(href="./api.html#schematype_SchemaType") SchemaType + |. For example, we've defined a + code title + | which will be cast to the + a(href="./api.html#schema-string-js") String + | SchemaType and + code date + | which will be cast to a + code Date + | SchemaType. + | Keys may also be assigned nested objects containing further key/type definitions + em (e.g. the `meta` property above). + p + | The permitted SchemaTypes are + ul + li String + li Number + li Date + li Buffer + li Boolean + li Mixed + li ObjectId + li Array + | Read more about them + a(href="./schematypes.html") here + | . + p + | Schemas not only define the structure of your document and casting of properties, they also define document + a(href="#methods") instance methods + |, static + a(href="#statics") Model methods + |, + a(href="#indexes") compound indexes + | and document lifecycle hooks called + a(href="./middleware.html") middleware + |. + h3#plugins Pluggable + p + | Schemas are + a(href="./plugins.html") pluggable + | which allows us to package up reusable features into + a(href="http://plugins.mongoosejs.com") plugins + | that can be shared with the community or just between your projects. + h3#methods Instance methods + p + a(href="./models.html") Models + | are just fancy + code constructor + | functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are + a(href="./documents.html") documents + |. + p + | Defining an instance method is easy. + :js + var animalSchema = new Schema({ name: String, type: String }); + + animalSchema.methods.findSimilarTypes = function (cb) { + return this.model('Animal').find({ type: this.type }, cb); + } + p + | Now all of our + code animal + | instances have a + code findSimilarTypes + | method available to it. + :js + var Animal = mongoose.model('Animal', animalSchema); + var dog = new Animal({ type: 'dog' }); + + dog.findSimilarTypes(function (err, dogs) { + console.log(dogs); // woof + }); + h3#statics Statics + p + | Adding static constructor methods to Models is simple as well. Continuing with our + code animalSchema + |: + :js + animalSchema.statics.findByName = function (name, cb) { + this.find({ name: new RegExp(name, 'i') }, cb); + } + + var Animal = mongoose.model('Animal', animalSchema); + Animal.findByName('fido', function (err, animals) { + console.log(animals); + }); + h3#indexes Indexes + p + a(href="http://www.mongodb.org/display/DOCS/Indexes") Indexes + | can be defined + a(href="./api.html#schematype_SchemaType-index") at + | + a(href="./api.html#schematype_SchemaType-unique") the + | + a(href="./api.html#schematype_SchemaType-sparse") path + | + a(href="./api.html#schematype_SchemaType-expires") level + | or the + code schema + | level. Defining indexes at the schema level is necessary when defining + a(href="http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys", target="_blank") compound indexes + |. + :js + animalSchema.index({ name: 1, type: -1 }); + + :markdown + When your application starts up, Mongoose automatically calls `ensureIndex` for each defined index. It is recommended this behavior be disabled in production by setting the `autoIndex` option of your schema to `false`. + + :js + animalSchema.set('autoIndex', false); + // or + new Schema({..}, { autoIndex: false }); + + p + | See also the + a(href="./api.html#model_Model-ensureIndexes") + code Model#ensureIndexes + | method for more details. + + h3#virtuals Virtuals + :markdown + [Virtual](./api.html#schema_Schema-virtual) attributes are attributes that are convenient to have around but that do not get persisted to MongoDB. + :js + var personSchema = new Schema({ + name: { + first: String, + last: String + } + }); + + var Person = mongoose.model('Person', personSchema); + + var bad = new Person({ + name: { first: 'Walter', last: 'White' } + }); + :markdown + Suppose we want to log the full name of `bad`. We could do this manually like so: + :js + console.log(bad.name.first + ' ' + bad.name.last); // Walter White + :markdown + Or we could add a `virtual` attribute [getter](./api.html#virtualtype_VirtualType-get) to our `personSchema` so we don't need to write out this string concatenation mess each time: + :js + personSchema.virtual('name.full').get(function () { + return this.name.first + ' ' + this.name.last; + }); + :markdown + Now, when we access our virtual full name property, our getter function will be invoked and the value returned: + :js + console.log('%s is insane', bad.name.full); // Walter White is insane + :markdown + It would also be nice to be able to set `this.name.first` and `this.name.last` by setting `this.name.full`. For example, if we wanted to change `bad`'s `name.first` and `name.last` to 'Breaking' and 'Bad' respectively, it'd be nice to just: + :js + bad.name.full = 'Breaking Bad'; + :markdown + Mongoose lets you do this as well through its virtual attribute [setters](./api.html#virtualtype_VirtualType-set): + :js + personSchema.virtual('name.full').set(function (name) { + var split = name.split(' '); + this.name.first = split[0]; + this.name.last = split[1]; + }); + + ... + + mad.name.full = 'Breaking Bad'; + console.log(mad.name.first); // Breaking + :markdown + If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you. + + h3#options Options + :markdown + `Schema`s have a few configurable options which can be passed to the constructor or `set` directly: + :js + new Schema({..}, options); + + // or + + var schema = new Schema({..}); + schema.set(option, value); + + :markdown + Valid options: + + - [autoIndex](#autoIndex) + - [capped](#capped) + - [id](#id) + - [_id](#_id) + - [read](#read) + - [safe](#safe) + - [shardKey](#shardKey) + - [strict](#strict) + - [toJSON](#toJSON) + - [toObject](#toObject) + - [versionKey](#versionKey) + + h4#autoIndex option: autoIndex + :markdown + At application startup, Mongoose sends an `ensureIndex` command for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model-ensureIndexes) method on your model. + :js + var schema = new Schema({..}, { autoIndex: false }); + var Clock = db.model('Clock', schema); + Clock.ensureIndexes(callback); + + h4#capped option: capped + :markdown + Mongoose supports MongoDBs [capped](http://www.mongodb.org/display/DOCS/Capped+Collections) collections. To specify the underlying MongoDB collection be `capped`, set the `capped` option to the maximum size of the collection in [bytes](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-size.). + :js + new Schema({..}, { capped: 1024 }); + :markdown + The `capped` option may also be set to an object if you want to pass additional options like [max](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-max) or [autoIndexId](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-autoIndexId). In this case you must explicitly pass the `size` option which is required. + :js + new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } }); + + h4#id option: id + :markdown + Mongoose assigns each of your schemas an `id` virtual getter by default which returns the documents `_id` field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an `id` getter added to your schema, you may disable it passing this option at schema construction time. + :js + // default behavior + var schema = new Schema({ name: String }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p.id); // '50341373e894ad16347efe01' + + // disabled id + var schema = new Schema({ name: String }, { id: false }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p.id); // undefined + + h4#_id option: _id + :markdown + Mongoose assigns each of your schemas an `_id` field by default if one is not passed into the [Schema](/docs/api.html#schema-js) constructor. The type assiged is an [ObjectId](/docs/api.html#schema_Schema-Types) to coincide with MongoDBs default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option. + + Pass this option during schema construction to prevent documents from getting an auto `_id` created. + :js + // default behavior + var schema = new Schema({ name: String }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' } + + // disabled _id + var schema = new Schema({ name: String }, { _id: false }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p); // { name: 'mongodb.org' } + + h4#read option: read + :markdown + Allows setting [query#read](/docs/api.html#query_Query-read) options at the schema level, providing us a way to apply default [ReadPreferences](http://docs.mongodb.org/manual/applications/replication/#replica-set-read-preference) to all queries derived from a model. + + :js + var schema = new Schema({..}, { read: 'primary' }); // also aliased as 'p' + var schema = new Schema({..}, { read: 'primaryPreferred' }); // aliased as 'pp' + var schema = new Schema({..}, { read: 'secondary' }); // aliased as 's' + var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp' + var schema = new Schema({..}, { read: 'nearest' }); // aliased as 'n' + + :markdown + The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'. + + The read option also allows us to specify _tag sets_. These tell the [driver](https://github.com/mongodb/node-mongodb-native/) from which members of the replica-set it should attempt to read. Read more about tag sets [here](http://docs.mongodb.org/manual/applications/replication/#tag-sets) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences). + + _NOTE: if you specify the read pref 'nearest', you must also pass the [strategy](http://mongodb.github.com/node-mongodb-native/api-generated/replset.html?highlight=strategy) option when connecting or your reads will not behave predictably:_ + + :js + // pings the replset members periodically to track network latency + // now `nearest` works as intended + var options = { replset: { strategy: 'ping' }}; + mongoose.connect(uri, options); + + var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] }); + mongoose.model('JellyBean', schema); + + h4#safe option: safe + :markdown + This option is passed to MongoDB with all operations and specifies if errors should be returned to our callbacks as well as tune write behavior. + + :js + var safe = true; + new Schema({ .. }, { safe: safe }); + + :markdown + By default this is set to `true` for all schemas which guarentees that any occurring error gets passed back to our callback. + By setting `safe` to something else like `{ j: 1, w: 2, wtimeout: 10000 }` we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback. + + There are other write concerns like `{ w: "majority" }` too. See the MongoDB [docs](http://www.mongodb.org/display/DOCS/getLastError+Command) for more details. + + :js + var safe = { w: "majority", wtimeout: 10000 }; + new Schema({ .. }, { safe: safe }); + + h4#shardKey option: shardKey + :markdown + The `shardKey` option is used when we have a [sharded MongoDB architecture](http://www.mongodb.org/display/DOCS/Sharding+Introduction). Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set. + + :js + new Schema({ .. }, { shardkey: { tag: 1, name: 1 }}) + + :markdown + _Note that Mongoose does not send the `shardcollection` command for you. You must configure your shards yourself._ + + h4#strict option: strict + :markdown + The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db. + + :js + var thingSchema = new Schema({..}) + var Thing = db.model('Thing', schemaSchema); + var thing = new Thing({ iAmNotInTheSchema: true }); + thing.save(); // iAmNotInTheSchema is not saved to the db + + // set to false.. + var thingSchema = new Schema({..}, { strict: false }); + var thing = new Thing({ iAmNotInTheSchema: true }); + thing.save(); // iAmNotInTheSchema is now saved to the db!! + + :markdown + This also affects the use of `doc.set()` to set a property value. + + :js + var thingSchema = new Schema({..}) + var Thing = db.model('Thing', schemaSchema); + var thing = new Thing; + thing.set('iAmNotInTheSchema', true); + thing.save(); // iAmNotInTheSchema is not saved to the db + + :markdown + This value can be overridden at the model instance level by passing a second boolean argument: + + :js + var Thing = db.model('Thing'); + var thing = new Thing(doc, true); // enables strict mode + var thing = new Thing(doc, false); // disables strict mode + + :markdown + The `strict` option may also be set to `"throw"` which will cause errors to be produced instead of dropping the bad data. + + :markdown + _NOTE: do not set to false unless you have good reason._ + + _NOTE: in mongoose v2 the default was false._ + + _NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option._ + + :js + var thingSchema = new Schema({..}) + var Thing = db.model('Thing', schemaSchema); + var thing = new Thing; + thing.iAmNotInTheSchema = true; + thing.save(); // iAmNotInTheSchema is never saved to the db + + h4#toJSON option: toJSON + :markdown + Exactly the same as the [toObject](#toObject) option but only applies when the documents `toJSON` method is called. + :js + var schema = new Schema({ name: String }); + schema.path('name').get(function (v) { + return v + ' is my name'; + }); + schema.set('toJSON', { getters: true, virtuals: false }); + var M = mongoose.model('Person', schema); + var m = new M({ name: 'Max Headroom' }); + console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' } + console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } + // since we know toJSON is called whenever a js object is stringified: + console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" } + + h4#toObject option: toObject + :markdown + Documents have a [toObject](/docs/api.html#document_Document-toObject) method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default. + + To have all virtuals show up in your `console.log` output, set the `toObject` option to `{ getters: true }`: + + :js + var schema = new Schema({ name: String }); + schema.path('name').get(function (v) { + return v + ' is my name'; + }); + schema.set('toObject', { getters: true }); + var M = mongoose.model('Person', schema); + var m = new M({ name: 'Max Headroom' }); + console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } + + h4#versionKey option: versionKey + :markdown + The `versionKey` is a property set on each document when first created by Mongoose. This keys value contains the internal [revision](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning) of the document. The name of this document property is configurable. The default is `__v`. If this conflicts with your application you can configure as such: + :js + var schema = new Schema({ name: 'string' }); + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'mongoose v3' }); + thing.save(); // { __v: 0, name: 'mongoose v3' } + + // customized versionKey + new Schema({..}, { versionKey: '_somethingElse' }) + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'mongoose v3' }); + thing.save(); // { _somethingElse: 0, name: 'mongoose v3' } + + :markdown + Document versioning can also be disabled by setting the `versionKey` to false. _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning)._ + :js + new Schema({..}, { versionKey: false }); + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'no versioning please' }); + thing.save(); // { name: 'no versioning please' } + + + h3#next Next Up + :markdown + Now that we've covered `Schemas`, let's take a look at [SchemaTypes](/docs/schematypes.html). + +script. +document.body.className = 'load'; +include includes/keen diff --git a/docs/3.2.x/docs/helpers/filters.js b/docs/3.2.x/docs/helpers/filters.js new file mode 100644 index 00000000000..33546a7e805 --- /dev/null +++ b/docs/3.2.x/docs/helpers/filters.js @@ -0,0 +1,20 @@ + +var hl = require('highlight.js') + +module.exports = exports = function (jade) { + // add highlighting filter to jade + + jade.filters.js = function (str) { + str = str.replace(/\\n/g, '\n'); + var ret = hl.highlight('javascript', str).value; + var code = '
    ' + ret.replace(/\n/g, '\\n') + '
    '; + return code; + } + + jade.filters.bash = function (str) { + var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; + var code = '
    ' + ret + '
    '; + return code + } + +} diff --git a/docs/3.2.x/docs/helpers/highlight.js b/docs/3.2.x/docs/helpers/highlight.js new file mode 100644 index 00000000000..8aca9b9e222 --- /dev/null +++ b/docs/3.2.x/docs/helpers/highlight.js @@ -0,0 +1,11 @@ + +var h = require('highlight.js') + +function hl (str) { + str = str.replace(/\\n/g, '\n'); + var ret = h.highlight('javascript', str).value; + var code = '
    ' + ret+ '
    '; + return code; +} + +module.exports = hl; diff --git a/docs/3.2.x/docs/helpers/href.js b/docs/3.2.x/docs/helpers/href.js new file mode 100644 index 00000000000..e7299b1cf0d --- /dev/null +++ b/docs/3.2.x/docs/helpers/href.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str, char) { + if ('string' != typeof str) return str; + return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); +} diff --git a/docs/3.2.x/docs/helpers/klass.js b/docs/3.2.x/docs/helpers/klass.js new file mode 100644 index 00000000000..0c4a865b43b --- /dev/null +++ b/docs/3.2.x/docs/helpers/klass.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str) { + var parts = str.replace(/\.js$/, '').split('/'); + return parts.join('_'); +} diff --git a/docs/3.2.x/docs/helpers/linktype.js b/docs/3.2.x/docs/helpers/linktype.js new file mode 100644 index 00000000000..997e740f671 --- /dev/null +++ b/docs/3.2.x/docs/helpers/linktype.js @@ -0,0 +1,50 @@ + +var types = {}; +types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; +types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' +types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' +types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' +types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' +types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' +types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' +types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' +types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' +types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' + +// mongoose +types.ObjectId = '#types_objectid_ObjectId'; +types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; +types.MongooseArray = '#types_array_MongooseArray'; +types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; +types.Query = '#query-js'; +types.QueryStream = '#querystream_QueryStream'; +types.Document = '#document_Document'; +types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; +types.Document = '#document_Document'; +types.Model = '#model_Model'; +types.Connection = '#connection_Connection'; +types.Collection = '#collection_Collection'; +types.Schema = '#schema_Schema'; +types.Promise = '#promise_Promise'; +types.Mongoose = '#index_Mongoose'; +types.MongooseError = '#error_MongooseError'; +types.Type = '#schematype_SchemaType'; // ? +types.SchemaType = '#schematype_SchemaType'; +types.SchemaArray = '#schema_array_SchemaArray'; +types.Mixed = '#schema_mixed_Mixed'; +types.VirtualType = '#virtualtype_VirtualType'; +types.MongooseBuffer = '#types_buffer_MongooseBuffer'; +types.Buffer = 'http://nodejs.org/api/buffer.html'; + +module.exports= function (type) { + if (types[type]) { + return '' + type + ''; + } + return '' + type + ''; +} + +module.exports.types = types; +module.exports.type = function (str) { + if (types[str]) return types[str]; + return str; +} diff --git a/docs/3.2.x/docs/images/apps/attictv.png b/docs/3.2.x/docs/images/apps/attictv.png new file mode 100644 index 0000000000000000000000000000000000000000..1327f0bd858cf6f002a077a9aafba1217ce38e9c GIT binary patch literal 42666 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 Cl*SPN literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/calllist.png b/docs/3.2.x/docs/images/apps/calllist.png new file mode 100644 index 0000000000000000000000000000000000000000..824fa428eb2de2a237b37ada591cc7056d68f399 GIT binary patch literal 33502 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 $5C9j=SSd5$;KOc+eQQ2^5$rlF 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 literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/cldfy.png b/docs/3.2.x/docs/images/apps/cldfy.png new file mode 100644 index 0000000000000000000000000000000000000000..c44ca3525daa7b847ab2869d44a00ebae852646d GIT binary patch literal 9773 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 AJOBUy literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/clickdummy.png b/docs/3.2.x/docs/images/apps/clickdummy.png new file mode 100644 index 0000000000000000000000000000000000000000..773ce3ec638a72dd3eb7ab6d103dade3874fa53e GIT binary patch literal 34210 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 O0000=x}o)VD=23xZGidKsJj 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

    &}XJ7y^uLKL|l(=^=~M7SI1ZoeQx zU4~gEai7K82`kG>M728gdW}}AMYGYQ-EK2CH&>WCl`3G-QXy3VSNHuQw?jOLdF9nt z(fJF+amd$SflgFyVt28T@8Qsw68{V@wV+(~gN&uV5xIDOPvMbil@@D~PBmBJ*nP zI{hSO;?Xl$RR^OnM<&Qyb&?2luS@Op1IPzXQ*VHBHBNlvF*5H2bT+{`x&rbvz;8^U z-t+*b-Jsu`VsarMURfuYogz9m&!D@`WUEFaiD{lW#O7&WACyguakj?bP?7TPD7Jt zSZ(l{O&ZNf2E9$v)DQ*^n-?sC)-xDvLI3YG&Sa$BE}097+J^`Z9c2*rpze`mJ@VVP zQ8ET4==C+y^J&frl*({IVyH2QQ@WWM()8Ct57qDpA2`FY_r4u<>nd*U2-XQi8gue( z=P=KFir~~K963oxU?2K!Lbr%I{t#kqo%Hf~!fPqv+r9?cllVuElJ`^cqemf5nFs^I zT8+5h<@*2k3k3hwpCJfCx;Jle>vuoO$+P#7^wx-)6WDBk%ZmUmYs+1F`OS{0)3jf_sr-O?ui zL8mjWglTIp*x#juAdM4pV=%7J$*nDun%ImyOYVx<-V&4|+mSI2Ed*K#w6jGlM#U|g zr$t0%p5siBm%^ej&R|WB=jZsMi*y~V>mk@6GIwaz`b6^q{_#1Oo}e#$7JH7hj=?y{ za)Yrkh!kT4X$n~;8Dv}c-k6z2)@sPOOPIy@tx5cP1J5M*on;zthMMkM#nv_z3?KdH*ZlTy>b*5*~)PXf{DpVTCMg0L4@`VPG@`%aNmB@ z8IMlPKT04%0N*dTw0vy{qL3)^Y0b>jn4Q8T1DrP7L~S(lgm92&2?mK@n*`_Z!jwi( zBklEx*Vc&B7z1Qhlk|Ip#>3_sPk5jTMi5Up1RjADOsXknQV3tThzl*wm(*fITPpHe z#HNWE6kMNJQ9~QZvtGgCk_zH{tH0|j8?3%?k(*a8B0LYjHHoqgI=4|u5gdMrFoIAz zRI83#SwWtE4iRr6lMPh7hEyJEu!?=^H;~q&zw||1rWh_3R5P7(r5hnHR8Zf4V?l&FO{P5|+;)39 zr~aTU@`7i(`c6A*Bz# zBFzPv@CjWVFYY4axM*XdiD7{995qj15^y4CkQC2GTgA#oNyWP)6vomhb}qOdIW*YQmUySYKOzJWvFPd1Q&LdRPShn|## zkw+eHA_f+6A8Asg&hcsiwOR{nGm?#rt7#8Kj=~TjsB1$bT|#lZRMq(7D5lBI4MflpM0)CM(NGA3E6vC?A_8 z*i;vSA-0^rw)9sSW7ybO$E$Ssdjaxf$;@#Vh|q4G3&sI_qlfIB$|`VQWi_hWxo0}# zUFv#6K!o?WpWVi06hye+BZi=emqusUTw`^L$#Rs<5H>>(3@WIR$1zzy!Q=*KWg$>r zgdb{rFG1NJMhj|lhlr+T*}QNCQ##ow1w%Ai^pGQ^iMx*xt^5#%9z% zvfs-XOFBpx^fCtB3}*^%sIZk`(iH@PXm%3e2Z*4K-;j7p5{7~x2(kGJdJto!Le*N- zCniZ&Z;`F6(U?DpCm50o1WFLq1z8r-UF&0wM&cmz2$V-giZ5$K%?RZ|C^K|ssfU*N zlOgqKA4Ejf=^{ddbCQ17V60U*nIv=1T%-2{kr#I^PCz9UU(a;?~u*E4Q0-wd_`ERlWUFdQcPxw z=hgP{8x6D;Na+)`8-(pS@+2pmo-49U>5Pggr^wI2wjE<=eA&r^TS?7cAi^qloh|KN zwdy_hV^QAnioNe2>avEphh%H-5qg@Z1tfgfc! zr*KZAtsys%^essjG6T6N@K~y}^hhBQK}36Q0k73Ws3ucyJB}CBXtnFqj~ya^>M88P zQEa14cWsmS`~`Fxqr#WTJFDc~P5i?PM2DtPN8WtmZZCO3%@47 z*3j7i;S6DD32FhhUMpDJrNf$p-t9|tmeW;i5M3{DcsA^?H39{>fT1%vPjz zjxk#+W#vCm%0qc_D;=>EA=xha`ZajDS_uX=1(_JE0)Ej7^fNp%{np&2<>A(6i`Hc$<&Y#CyTO)cUMtDE(f-$;`&T4sHk{B{%|}1_G2ZsXyZD`7{Y8H5cRqm-aPsUU{P+idh~N27ALh|_ zy^qt!=82Pn?j(w8TzvJ*{M0}GS-$hT|7*VG8{SJi7+}lE9|R$nUU{BRKK(L(`FsC7 zN))*vlu~4A%)kEGpW(%;Yy8Ad{5@vc4dNszb_pS<*CPJoFa8_;uV4F}p|AvDlOOrf zA1Bi5{LerAPw6Ka6Vr$I@xS|bxpn@_#A<@KKCr<5^7FsIU-|yO&cfUTgE%gOtt4UK z@qhi|FYv&l?`0;;_^E&P^Zd=f{r}?ZiNhpGTB=9TsMqEOU4MpO`49h= zU;oI*FxK)7ANbRJ_ji0V|DXT&Px8v8>%$#L9OUd>Wt%KLuhmaIVVOEQ$@IxKzVDN+ z+=eW}`JlWBWH^D6O;pgv!~@dx>)3n);T1lBhv^XPMx5 z1M%V~@sbsi>yCW0fjn~(-IHuCcL{Tkuvtfj5-AOhK!XR7=QBMuhY*Kw#?W8iWcBtk z-H`yUN+>GG&FDhzo&WM@`Hhc#4&_Ju@CSd4w?Fa#H*YNRj(5I`7e4oULl{JBVwQJ( z&DU`0;zi!`p7-*~7k{6h|F{1qPWb%LkNi0A{+f3Yg#Q~)yyLx`T$tl0e&Qdpvf0D; zYy6%6<{$9BuYC{eS;*sWdz63kbN`YT&tKx9M;_z<@qK@ZkNw6kaibUTwO{)_KKHx- zk^l79}9aO~vo^Ywq?{e0>pzrw%$KYtbH9H$?AD}VRL{toBPJ;0-nJ;sFS z(4L&(-S2rHtCzmSzx>&Mg#l*gj`83B&w0N66w36V?>1sWxW0M{ZIy24nhY1X-_8i#*RE z67U6h9%yYb5{%Z&&B5^#(CKN`VoSKv=g{#Q#~)~sxuoE!>cqJ93^_eXXceL!VA~V) z+Eb{B8k4ir_?->R%q+pi22+!hh-MS++#&VP;ZID^uraL@E%a1?eDPxhjW+69w@k4N zXpd}FldRr=AYpo@P99m(bWj>HG+B~kU5a%QrHV+FN;9t%^wGSD!*s@1E?(pdpZ@}0 z5b)pqw|}4csbWQX|2KYss8*xdY@n2)*=&?~tP7p&&eAQOdg>{ZUuR`~ljGA9$nreW z?{;|R>1SBp>=J}cR@XO}i|VCHmGSf!KF23M|3&(_;(PP&MoGUgQyR*|JiThYv1!uzWCB5zVRDBKxg?TpZx3>cn zJX8U#HQc^&ou|I=6n+r!>iJ9DxO$%TwKd-Qo(~lM6kVk0UAldXXP$lH~AZX>qm#UF*%x?as;?|0Bs8EMogSaBD^{->!Xtto#gn!VGWo* zh(<(IYk}^fvlT>1UMYo#@C4cx$s?TwfA%P$+rVzzAZYstVZr4n5fU{bnu(>inUj_r zw>bsvjdW$Md&)CPR?=hoaAE-t9RV+ZWL4t_K8be3n|*4NZD!^@UVCW?ooD!d6RAAH zqepS=7RDO7H*aCmS=8hdbu01002KzPL63GbpmXjt#zMTbNYJcP%hnK6Z$Te>3;9Zh zSh|AAa?(tqLWN5*&^?6iVp{>XudXxbcIn@`i8C3_w|FuqtVc*+V$vL0recz+2O);2cy=5PNl-uHp;EL96h-0#rq^|8+K zp7(!%fA-H#;E=ra%?~h9b3AnB)Q}n74}1`U>G?yPJbo0HuNK@uLBx;$xBor=&u))q ztBsO^KmDEmcNXJc$6Cw%4?fJ)M2ny?#i6-rR#%qkC)sx7tJb{s((}A{{t93JC;lYA z{psg;*E=8Msn7j3m#*F{c$6lmIdS+9gE-;qKJabK-}mqk9jvY4qrdwRthLM?I>LQN zj}&3MUXiyB>o{}nK_=VHA#}i6!^=e_7W@*n%5;;R=OC<2s zTl8Lj71nQY_|zt?#V?b&8p~f?#`Y3y>mjl{z>5^7;p4kGT;^eg!U=(2pCC(bV3L%e zCJ}ytKz2@{!Wf$l*PtREzEowa%UX-~_`BZAWb1#UAE(UBFYxVu=39C3OHc7v|H}7r z{J#77$^Y?xWMMkuAO3^C%jduJB3^BpKl@#OiKEAk@@v2Lt6aQ%gJ+)oGC%Y;|0dt^ zjbD!}mFyxnwd3>y4{_qy5f(456f2{YB!f-<-M{^JWVzwNx4et*`wQRB(IcNj8_R=_ zyp@IdIo|#a-_Cb@^EYt(_)-4D&;L{Y`M>@@wjd!vz{biVAN|WV-J0V;}t6%+E|0<~%>-FMQAU^Vpm3XKm>kMr&pcEpYDi@xn(@ zIryaHp-0|AvlbKr=^UOPuypM_uU)y#U;Hb7jptrDk1c&I)sAscCc@E6D#6@?Cpi4b zX?nM>)46SEd6M=*6Vbhc)8&K2Aaoy00#YIT7RnZM`&qJy&NM=Lc=bBX=}DrgqfGagPCn_J84P-~Dc~xLfWL0x8A8nFy=h zLcr|(hdBE1DTEZ5eixm>U@fINm*Xq29*9g5Dh=r!umgn4Q6k0Qqf>`Y2RP~QYHduK zvv&P9p3c~O=Ce%BDTMEXEiggO2^=*{KENhf5xnFXe3_y=izgrmAgqJ$3rb@0;#>qI z(NQ{jhRMT%J1@LIvUr`t=jzOzK2El}iPMI3J>xzD?}L3JboXYXTAt#z{ayr z(>(J4{`3@iEn@leUt;>bPmuOHct>Wb1(NLMbI3-3$@}EY;DU&Fu*Px>o=6b0v$&}? zrqw39e37v3W6~}%Dsq<#;p2qGh%#5npP7ke8L&0cG&-3Gd|0n3j z3GJyF6ow=z*gB#xL~A|74;8uTBx#l*y*5Amw||uH+2|708%#E9h3PU)n4UYwKl~ql zk|fKSo;wWA6u6l@FET9U1^gojgA%x9Nb|JFl+YJeCo{>@BW%U!4r=@!Z&=&cOr!1;YS`o zYfYAB<-KW=WI!Cpy!o+r@-zSRpJ9QMr|-uYLlVaY^^7q{saU#snSb;@{m=Z&PybI$ zh7=6v6odVGb`0wrt+@sZ51qjG!I%uG`-GDU5e4*C)~L@2R2%e$#bvi~Dg>uW!H&^c z2c1Gt^XP8~>T`$i>n)7$6Eq@3YRNWwsEH=RNyu|BIoPZS?@Ll7DL#hKxA+2r5d5Hs zsgPxM(_(dlT-31j!?>P6c|I~9KtI7GfJWz}ftx(e{;W&HlVNM=9!fP+T$n85T7;Aa+TOVb1YLexp+q5QUsMl)*Lo{pw z_Pc!PB2#mRnQS$ znc(R!e1UG9f^%e9#$Wwwf1OW!;uHMNZ~xXkh2l^U@>2o4{~afon4iMR1}2Z$eC@=&fw9+-dUaYn#YMjrz&sWVtO=7o!mqbLb?d-l~(W zECZHkqE6?+RkDpPN5T#dz4H)JBv{R+xp>)O`h8kw9wY)>bB?&%htLtVL!5JTu3p2f zTp?QhUU_x*M^>APkAif zzRL2_4Xm|XxpHM_PaXyLIY3qLc0B_8^F1!U_A=*Rc@fX^v9>7t@)w^O`W0+xIT|IF ztFTR%E?*tuz0~y^cg0pzF(RI)xPJ9g5f9?~i9YXmy;Q)(t0-*%HU#zUshi%A~auIb7v;jSHmgv|csFeGmI8E1Ae^;vW{1; z5kxhFSKK#VK<)Smq$jXFFg=ZOIZ76}t%WoQsgXV?RS1QHA#Tf9Fb2{TlHe%8+4mrV z2rrBX!U$_M$!3bhBTEJS&VW2CcF_7{18e)tJhZ@}M;@ek_7VK{EK`rao2la`$X

  • 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 literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/geeklist.png b/docs/3.2.x/docs/images/apps/geeklist.png new file mode 100644 index 0000000000000000000000000000000000000000..c6579c12f6f37e10ab1a3f667e33f70fbdc87173 GIT binary patch literal 27911 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 /dev/null + then + echo waiting for manual firefox shutdown... + fi + + while true; do + if ps ax | grep -v grep | grep firefox > /dev/null + then + sleep 1 + else + break + fi + done + echo firefox shutdown detected +} + +if test -z "$1" +then + while read line + do + func $line + done < urls +else + func $1 "$2" +fi + diff --git a/docs/3.2.x/docs/images/apps/growthegamegolf.png b/docs/3.2.x/docs/images/apps/growthegamegolf.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d6e9fb7493ce38c487cb2f31416838fe063bb6 GIT binary patch literal 43441 zcmZ^qRa6{Jw}wfO5Fkj<;O_43uEE{iEx0APyL-?OoWX7I!3TGj;O@)-hwr~XEmf=g zqSxxKUG+Zu-K(R%E6aRA!bgIEf%zgQE2;M0551qUhzRd3jn0BL3=Hmxt%SsPTXRPk z7@ht!U3d*mm6if`r>`03((N6k9RgDOGhdAG;W5zZ;3*|PsEWd=veIFoOJXG@f5(#i z@Ih)2reu$Z^>q`{{ji|#ypYWY>;UHr`Q2||LJVM*oG>LMU`_F1f`j|zxWoAcl_!}6 zTeV?ec|TC}z4(m)A^k8S$ zpLVy1RAI0`myn7MUv%oZKYWvV3k$S0US za`A(x+e@*%@2VevmLlKZB1`M|pjT~gE8N2UocOYhfrf;%+?$1nAK#-R3cM)tr6?@3n}|&w#+iFGA?^k3#T_)D$g~A$Qv*?% zCfV~K_z(uy7aspSw&PQ;wnTsRX<))UE}_kpAM<4_&q&Wd9-{}O)x3*yo$YQOW>CFp)puI)4fvBIy78l=;E1@S$U0?66n%*5~8=f%Xudf&hN{4^hKCwW(Nezp}v5carAU$Xv`O-|waD{|eq_pMkOBZx0h zy+X1A>*oY>5X|-D#RVd2haTi5A{DWuogx{U0kKsyT@DC;)T{n?~4_7H!tQ7TSUPjeO*QUULOs4C^^IT4t5D9i{nny zjdlcwdWn;F1RG}98%(S(UYZ(#%ctiR=<07Goa7C-^kW}IYi`h(;G!m0{4Mx$Um~a@ zt2nf=r*^MJfyZW}>Wvo*tZL>bQi}9P-dFd`ZTOqa3c%8|L!OAG;>vqF-eT!yD-p zhNT!L`r}~ej+9(ss%kr}LMrkoft2`Q@r)|`A9f9WSYG+rO>jYR2o4OBEl93@Y84+^N}F zagk`%T|*Ou&nIAs;pyqv3b~4U{0PPNX9z?TiP$79Cc`9ErvgykP{xprkyn!1Q=ib} zP_2@dQ{j?p)3i`L(1=JI$r>qaNWDfw3E<%eiIK38?2$yG;iAQ(Pp}ebH@;V?&ZtJK z9jmpgNq^5T>Qr1-ehR)O_$7)?X@g;axE-n7gJk>FAC(dZHXQQ48|t^aNNE%B|~E%vS9EdWIafegVMAt)Rr+#V$WMIrV_ z>~$<^>~ySD>;qnT=6A(l#UaICin@wCS<+bxS$tVdSzVd4nf6%`ncBKbx{W%WIy1V* zI?_4|x;{F0y0AL#Is`g2OH&R-4hs&d4hPHaOE}Blmgbj)mS&fo8xq`m2#W~02_yJM z`F#1(`Pz8D@JaB2-8|ix-Pl}hU7y_dU7OsPTxQ+vT_COpt}U*>1Jk|ff1mg0_I!E( z17p4R0|dQ(Ni7Lp<_S~85TPi)<9o%+q#L>$pPT(Fk4vU2_nVv>lI_}U5?oTu?>Lv( zycAPRb@a59hqT_}bz&|?ky67tv|4|p57Su1bkrXcU9v9g5Va(ADMd>pEkvmr5C++H=y!T|EO*SmrhZ-dn)H?Ht21R5Um6OW@iS}=jj0H7U>@n z4HiFEGgcawTy#@3vOHAYNq$h?d=zC=Ycy*#L4%c^pI$~&Ph&v?TeDx&`EQ_B%6H`N z9Yx$gZJXM~jp(k~W52nmW8C?2PH)aNPG%cL+iSb8Tw|P@c2~AOcA9n*wlOvkd*k`n z5{hbxnYLoU-^#xP<*PLjGaPdYizl z>O0}_$h0sx=abJGCOg;r%@m#aq8GormX(g;9I>gh#4MlT9wnHjIMnw!n@5BB|#EwUgll_(7 zL-y|b>u;)Lx(ap_q*amyyvd&iZhjP@6!9{hQFD=u(NK(ibPtAXZhqc&9%)W$CM)Iz z()$_HThoMoA{p-lLV;^)Wr1@uL97enP1n>5o9pRixc<<;=6j%z@j^zSMG1CsF|15)GfzTr^CfvgH~ zK;IAmY7GE8<=+VLsFkQ|XpgJrYIW-E=(7JXI`Ma;v$mB!dWHuggIVy6s#q`?8E8T2 zGU>odmp_NyCH@ud$<^$|ZYOS+`xW##e?QI3&(CY~)>zEqr!E7~ zyUFWF_F`$dY{ptQ@64E&-^gBTU&mQ(UL#)V_TD^r{Q>HY&&X5G>qo01x%J5M6!NvX ztOMwGbettU7pH^%Cgk|0`r+r(3Rhfc9(LVmY#-$b4|YEXmc9;sNc;7#w=1MtB3t62 z;7G`i*Fg|!F<@rlG8cIJlzFl==MFx&Vfkq6|1E)V(>v=D>4rWa*s91R*}UPjY51g_ zZm`17`F7*ByD0$TwqpL=uedb+&*562uOpc6yzSU$`6(SfB<$A%WCI+C_)=G&d7X4` zenqpb(jsCXaBk?Pm;ECC-0;G6LvYeEwz&`VV$^3+se!9@s49Cic~NaD>s;tMZxwFA zXo^~8T>H9g_iFomGw(Td?@5~^xz>eLn26-(2YY$Pp4`F36PuD~7JiT%CXce&N7AF3Hy2M5M+GZ}LHJ%>HO=VD;9X<~VNVw}V{ zQ7_ZS_>Rn5)yehAe4Qo%+*okIsLRv^aoc0KS&Z0h=>Eilsoj~xo2`4XlDxLDaVJ9Z zgXmsnr0Cx?59?8j>hVb z4n@e12n!G%jj^==ZdX8d4FbdvRg!4jt3&zJ<>Kn_x^q|aG++rdt-X>k<2)TiTF6(& z|A&^Bfs!rt$8cH+_7G7shVWNcCU&Y(Aw3ak{`5E21B?aUA@A(srDBH9&Ixyv8?vJ+ z@%-H)gL|Pye|7QMUUY^^$0KNHR02lzCXFU^gTCCpYckEe?@oMzfWTiZ7n*@^Y^1n#MNlavR zTr+*TAabsDu(x&Y3M!@O;5Zl4(C+K6I!~6_PXIsU`hK0ZhiDX`t@CUIxs#et1r0xE zz1F=(-u;2-4BYJD(hThy`2uJ1OmcK`9ee}KMvvkK^r5R>vw0j;fQSv-3DwCj;0zYR zfQyG-_vr`osq!iCZ-w8+vc?p^LH`83dwn*8QlqXri8oLRS4LC932aWP{%*%BE-V_U z`XS$GSYJ`Yl-XgRBBK^k$Ip(?2dWfueTs|Uw574+OW#M-)KzPzItv}kE6c!^k>lQiIBs(_yRr~Y@%sX^j6RRnM8GR&lqF8gdI~dPoYYb}i_|#UElMEje z7-i$-gp!@o+sO54Ge|GW3X38&Pqjz2J=IJ#eSYf|{cF?KBB~UwP_4}>-LI@Jr}(2# z{OPv)2>dM;e}jvj^`0GrHH)2z6Tk_|^3tQ!#n-Rb>1uIm8fm&~QU}m1sqh=P3+`C# zj2}W*O6`mh-Ck?YfL^5Ag*5~lj)^*_#9Q@?DKqYCCk+o|B$fqAo7_OSplTTODPnI% zSspy1HEcIQ4S`$GZ~SBqH!JN3{qUd!+SoM$zHe#h6W;<@hM3anJfSWVNhQ4H-rJ99 z#d)9GK>lCvk|k4gNZ z)IY7j^INNdcfh5%6RCCi8BCgOg>I_975^Hv20whYr#iE|rf;ybqfDNwZ8sE9^{YN# zzMIJDYcX&t=;m1JnL1q4SQA_bZljs8Tl%*Vc>DSkzc9Io)=YBkc_Mu6le_G`J7RO8 zRUrG;{fi?c1#A(a67P=>2-x79gs=yRA9Ky;{K<-a%1pp9)?TRcg1(&)EGzfYe@u+o z%R;3|YKIY3hE2BKfd83A2*dCZ#*-dKSQXi%Uk?VJ@Xaq!RCXsy#!Z>J=ZoY|!DQR) z54e<@@d&oE(mvRY!DN&I8=;4!7_!JCX#IsLvcgO7O8w~L$R|Ddm!B!e2!aoIkqZgp657i1Ae-;@leaHp&!*Qep3 z0m^pEn~JGQMV0+1Kcz%OpFu46bNWXwQIRGBVT!OQ>$gYQSvf~xhfJ-aF}QGaYQ(0W zcLJ+7){@x-!@}00$t2HO!7{_N;2-V&kAttf&%G~+GzE+934$c)7gTRdzZiQ($<$5R zFoK7Z4DlNV8GFtrmRCz(MT_+T zD)t6`M%GejhvrEEsLr80)EvJ#Em?QDGFs~DP?|>pPW4$$6iZ_QyaGdfhAx3y><9Ao z#?L?ddnuf-2ZSF;@}Wk}8=wF^|HT&%*hz#Mc)w5-B6iZI&@q`gDLKi_$aOz&QszBc znLZmcqlV?HG)y1cog>36qjEfe(ShJZ-tZ>#9$&edgXim3SY`t<_HG8%UlxP3n!I+` ztNULF(Pb;?FOFtJYla93qrP;Iuut0I?n9x*DBb*T&*Q7Vy_}HkNsfe#Uy!;LYX4L@ z)t1)sIH5Ritkb`JYp-tX2omksBs_!>K!a<;KT*qDhxn#MhyQ*BS z?Fco25>z4z!rnr9gnAvwoK1-^KB)4ub@EDoWRatiqETW9$gynr8=y{$*-XiP+7C?SL$-~($ZAyFJMbVZG;)G?9HxWsf<{V|b)349-G z*d37H4-eulXJJNyd^IQ_-r~nQU$~e&*gng;@Bnpyt%tn&3+P0drFtjgn5h_66-r3`Ktu9-s<>65LfogoM9NzxO?E9MlflPp}|_12}Dp2its7BY@D1 zKOWY6Zlb~$1%k;sumNvcHdEFO zIS-d{^_GI^T^sD+9#w`y8uJ>%ETc29M0;7?Qd7vl+{>eIp|IvC{BnY$<;rX4n1^6C z8~y@yO~FCk!T69i(BuhyJ>bE03A279tNR94Spo$dF5NJsnD3lm9AL@E_Qr2!cjCB% zV#n=@ny=!U@app8YL+Gh%%(tPtQ;8kSoYv}2T8Mx+0S6;W?-mHszeqs2)eC3s+q6C zT##6d;Kt%c;^}t4cTRV7a#(gWghV|b-QFB?H#!0XEJ1Ik8*U99pihz&urO9`evlke znATYshkXZU=Tt{$=QN6uAqJQg*r1n-2ETEPj`{=lu*bU$s2s=C~)N4*@W-A z`;TCzAR`I$_TOIERi5&G=d-i4wEKJi--ZTb*zorQ49rg$IY}`M@0HURuU5-NpN-G2 z3oB21?oP^@9t_%KpUBbSGAR*MQHm%(jU=x(RNJ(af$sn46R)}@fIK7WSDV{G=b(II zb+s`qayqt{BH52{V&uh0X_Zdvxhfkz7fsIz0je;vqHt6=V#9aBD)W2~xq0B{h36ee zR6@Y%F1{#?ZFaKdw{Tk%UGBn%ZXdeajY{v4%^l5d$k0poe7%w5>Y`h`vxk$>e&*)m z^I7h0Y0ycA!$bA?fxb|R$VnGaH84e60L0LBjSs%Eeo``8TZA57iv&D*nO*$MCTRV2 z!D!@K1@ynPE*OD`%t8U;#fU&RAP8f3F(R~(-B~FM@NF#gb2XSw| z5aX1}#AMx4Gp=bHIP?RIE^h(}`Ow5dGWBJTf)*v8JeAA!pVsq9eT5eD)BI#3<|wwN zh+;Hrl#6^YYMHHN5tiOIdBxK@;W45Vtcl`@6)1F+;yNX5DrM}UtS%^@=#;{*n8o-z zJ)IW+s(DF&8xpY4Gglyp>tP$SXj5U?=xVMu*ZQ-hnJh@A9i2T(uKi7H#VQlECXPy- z-&+fQ%w<|{8;`iZB*vE4yG%x8McRBzPxCw7na%DX$=sz)ySe01q9TKxatftNBCTit zo&BnuDVx@Egc_ZiY@fqVEbjdMuO$*Qf<+Dqrt)%S;+`QMsah~P;WD#%l#}7DR&k2( zl5Hy4)~QwaZPA|_KD3R(Ov$4Qy;&U+S_N+MdaeCP6zROauvv4<)W3gWte-g@h(4dJ zy@I`a5#+rS{?QgY?4BNh44oVdn&`q52_8o|jziG?1iq>VyagN3EIKM?)jkxy0>mlW zyf#%_N_>(jPfYcxvd{6_l$XBc9*7jYW?1;d!w}ks@_++Hsz(V;1ue<~b4hJ?^_Wn| zSWCom;bS$?8kT`QtVB~kK!||I_F1#UTU{rS(F5E-0+`b6%R|^szgHG_&s{*tKUzp7 zq%MwM&z{*KC>_iKWfsR;B_`}j5O@!H4{5{{Zp4_R85A_**9XC-r^BYR_*h^{%efy* z4TpI4k0a>-IKDiaoNU7#h8U9Ffq~V`N}@8M&S4NUR3KH0_KSI1&ZB+H8+(Qqu{F(# zX|r!=^#0YrD9Kb5_jkQw&T($1{mCdEb9`)i&$#JpN`fwilD!f=*5id`V&<86$edzt zIm?UmRVNpx{3q|t>4N^Gse5gd zx^sI%lvNm5=uMv%V&#pw-8;Z@MXRrww;{qhf|O}n2>{JfJA@?MNH|4gO~;C_>~ zFLZY(mKIs-E;BzS>){js%do;@2g9fe{ODFN^v7q01((+T;tTPI&Kf z-cLpXc0~%tezRGke$fWD&c697m71F!BRIGbX5_Q-k!#^_MvU@J z+b4{j9jSD%({CBT3IE>#f!B3{&GCg!N$?`e;-K-wMGw#EjT)8F&4jNY%adZ~=vDXC zT5ao@LUTPzIvkqS*?iYh1JCr%)ic;Th=UDocKDFK~u>flSO?`IncDoNE*Lkzn z>1%6tre}9*+qpD04!~VdY9UL?^?5CZf*(YbZ7NTi%_3V~oSpr9-X!*8DdwddauE~3&Jm>OUoP6Ef!Bp#JX`bx{*~hUgu~3pC@G2%71C_bzyy5Qo03^)PIOo2>PG>HPTrT>6Q#dU|pr-0$%&TV$}HKqxx-EIU@UZpW_HNCFF3e_ zl)8+}t*voqIg`|qt#wu501q3iN*ehTB^DMIaCAT#oN-EiZ4ME(4%LwJ-P=fnYx!L*3tcl~>3?5NAvf2FX*xTas_Ja@X`0 z1DeQq&UshFSO)XW9;V7APtZT>$J=sYsV2SsbbY7oHtT|Yq6>c-;EO(R5VG+Wxbc$z zV1QZo-=`fo5w;Y*+e`7z2SugO7~ek)AJT&2Ne*6lfZzIAy+IEFBqH~iBE2L5uQ!Y= zOjiYgHzM`*-Mz-IS0o3pBv8_ezze^prng6o^Uf3IWZt10!Hv5bulmMT*>p?j6xtgr z2LQ0@_BlH)gco6v$6sidUT-;X z?;&n~wzLT_2SUAa7rA_= zI|t)`B7v_wk8NmgEu5V*P3t#|+adw~Hd#}#Uvto2b_!gG2T4Sprlt*N=tx2soLvfRD!!xKvcGNkzUqb zz(WAciANp0v39RbiNzIh~%y(D`n1&^?(MEs$tUuQX= zE)$@L@6#!w07Ce%9wY()0CIiL`GhZf(LSPwlXYLXn*`>E+}ylJOEr|_ZCiwuOK4(c z1s@0z0QTo>UZ>kL%vOroE49s8SV3Wc5YSsv!Sj?zk(mwunL=*cGiAZcGbjsRAXN4_ zmaA-eO>Zmfp1#>~7CBtdWlX>(Rgk%g2~ZChADm}cb3HYpuYok&I9wR*Zw5jOT;GI( z(v1Dzz=fJa%VFiZCl1qpRR92w@J*jnb?D~X&RYy7;M0eR{Ze&$Lf}F~)NTx3S)wwz@~gb=Iwg{s&eq`;T?AM*p4$0kmXoH-|5C z3YI0TBRkB-z)MPzmzsjDAn4f}kD4rgDN7}72U6E+|3j1S6#?yZj= zAh{wz`2~+71^&zQH}dG>>;i!>U@ZUpE0wGCRgvK?n)AJx`P!Sg9VtRJ;i~}>H*d4} zgupwm)|V|JDERH^EvoLX|JBuIUnP+!We4M_gX!N$9Rk8Eq39>I9BKP*-{+XQQKoLU z=LDZIN0FYL9qlLWpiAerg8_Y=4Fd%1%g23d@69ffGS!-3EkU1qj3Ul$5&vsrSBp(Y z=$ptDSeFPc7YJn?6DqLIf1^BT@wDMhPTOF<=y-^zLxKJEuU@_2U%dkOa;o}biz5O0 z#tWRcGImd`K4%8r9|c9}=WU-piR{cBvyY7>+(1mp-&=vGxyxuxFqHtc@b+_{@ou~LZbn|hoc4whXb((oqOcuwJH5XqSr@N0t@XqquC8gFta6;e7 z7lv$WX5M;<`2Hz`<&A_=Ixpve2$pPVjUSwXe6YmBKPc}P6ELCrdRG3*RrbSs=Lvi> zFn@FE9Crx}I({2lr`c4VxT_g^gx1umvhemIgnUT1RISi>Od@$v4Sco^N~a+X%H4c> z1U=2*0*4_YmttjQWv$-ZA1_{hk(l_|$Gm((y?l7<6*2L!3`%m`3e?>FajZ~ zK&7CmgNxT0mT3nZj+u#;wZ2X0QNh1GC7!EaXn~2qOWZf|{D(6k$=(>LUHpmqmzJv< zflaAo$vJu^%52|isV;-v^@qSj*kZu#3t5?|o9VVav^S+-_Z$;#OOIOj)$A&;7C1SZ zQDEM{r9#~F1f4B7xE|GQ)ZOmR+2}(Px$Tdg&z>9gpw8ZfDbekd_R8Boqe3txVRAg) zr$^g(Wj^P1K^8dk$Tt=o6XF5JbR?{Wk;U3eT2fR8KzD(!m4pQL*PB6m7uRj&z=7U2 zeQ(IR$gmOzAlI;K+z>>(w|6UekglwHO;4Bu3;|ws7g+l23ic0JZ{E5}S5Dv-#Gyxa ziMx$?R`^n-YT?c7WdV%0kgdBXbK*Ba`|}4!aE8+Q?xzGf>-vM7j=+h&XR6?(a*osP z)2vUbxVAixkf8kn_nX(^M!Q{T+`}8W?u>Z}9~hQLNYw8E$^LBOgj*SS@^@|!8Q1%? z9yFylYulo$Yh=ZW=dx(%bp;T4yBTnewas4al-{(#>^#c%V?_zMyYo<-wea*z|3vJc zcy)D^;iz4$^`szjZw|BO2|3%m_waKl6qeLG1|%^I-Y?+TX3tza9R1+G^%Y80YpodriQKbI<_V2G zbe$LyW)>XG492{J+2a75Deo?x?p&Mzz-3 zy5!S)?r*lr9Lw2Oo!sKN2jj8l#e4I7obHJY+WSl0IdscZs1tdG|K>A^H^GwTu~r_j z=I;t1N5So1#=J{SH$P`Mg|R|Xn+ zTCMQIMwxw|gTEZx#+%EM!uwxnhM8eu)-@xouIq5M@>_ zcA0sGVvot0AxkLbewXvB>PFC81nZAcPv?x0dI>@A8;MiT#jI@JNxzFgv@%;ZA%4*5 z(g!C2H?-#A<>T|Is(6kKJgWErH(PcNcDYpP)ZDK(93Z^f1h$3Tojs^wC*+(&@-VeS zxjRL|e75SmM$PSHJXV<^)WXR@M9=MQ2-VrY%I>L!Z`I*H362vFibn#pt>fZwEFHeVqi~BSzBP`BJc)j_S64a+n?DM`< zHyQ7eypGl;?(@B!7C$&}l@5yU$rZ~Z~TEHBqAfS|X) z!pK}}UFlM_?b(87tT6=z=q>n_@tqE#H$l%TPdyRB0|FaQ%FKqH!@wu)x99>$*n7%b zUhoc9`CCkALZPGX!nfOK#_Gs5pZL4J_^OV+Mzt;e3cEvi<$SF9qb5(+z$jrqd=o1M z1g~y9YYE>RsT8N}^gsnCv{KyK6tO_5qn4=SV2aWK4?`#5E-GAIQ(M$Rc6~itA?sEt zdTWhBHf0qfi~I8&-SdlZin_X@veMO)2vmaD|5A)N2r~!9cyrLU8!uo~ z#$e3Cd6L3;vKdDc0J}+Nz|-q3=Aql!KD=;`<4U;O&WtEFa+8^r-)$ACK)1ZMwC5EF zX_?mBMT=PML_dk6IOn3;|f=!jDN~R>+h;b0P8Rzgn^$N;B3wZ30jgKb}B?Y_Z zi+DtLT(m{((kNeEW^@l^bU#WpFcwccBp>k2uq(yn?ai^Cd^h+ubWyWjt5%$OPx zDS8;P0ksO;T@1>5dh(f}6r+pACN>A4wG5T8l zN?omO-^{(BYoJFx=H9q)>fr2tcdUt1!_0mQ+qlr!(xRi&DxX{8=MagXX6@kQRMbcv zZ~ojxtgA&R0Srx2wI5tLW?$_fT7oDUwZ?NseM5P%4+7pkBfJo+5^@|qsLBJc?}GX> zeYUy49Lbzr#1c1LyX{qY;)p18M|bV9DvC39P0?VCSa0G_2WZy=yT%|A6kfl7j5#?u zC=vbk2v;tL?&qhvIJh`A7pK>05hUBkeIJ9KKtZtuPi+MUUV$eqiQ+R3+;xsQH`d^* zQx27z#kYSd>b3LlbO_;k-7+V!cDGG?3f{8d_kAacd zXde^^t@YQhSrb&?_4?=I*#G}~x*btidXc~Py)o0AX z*JV1Kj72;mN7thr_&!?d+kp20{Dexp_oQCV>wn5?KNeHva6WbBDGP{|u9gOF%GkOX zWB|(ZrB;ZW$v*EQf|yj9{C+?r;zffCg_*|j9)mkxm>qHHl{jP+Z z*_?6}izgO7lP%H%Ic6D|n8{16tXm|yrbX?Q2&GY;1Ki-8eGVNXEqXk?MEB4}G>1ly5sER@358if zJJ@ z9K|d|4xz)LxnsaIl9f@B4i7cFaY&la#U%f%2|Jil!tz_Z_T`Y1qvLKmedm#q*X)MD z{?2}-Mh=ArQOfp4K%=zG<);ApCY*jF-2R3h^flj`>MAB<`2OFUjU0VuX#r7_anvV4oB@!;n4&2xD@Qy1l!YihOa-0fp(1+NiZvv;%v z@6QU%t*j7cIismb2U-2L)u!|=gd)i~OQ&w%q1#r~Q*egS9Q{j0ds@+k_`WO|x;V~+ zWa?1j*V(!nE@7YT`++f?c%W;Ez1?QG3Cs@x$57VcYkw713B|FYdM3fz0hg)b*)vsU zZCW2xfeuGK3W`13=#P36IJ)?lp%@<%!zmFzHYjp%arNFWP^%`J$;;JnrMY3x(mMQM zMZ)N_aC6JeJ7WrF?eie&qb*abfys6&6|e15sL%tU7dBEON$gNc$;-~hx|Q|~4`SFKKZ|*M@_u^twdI(uhgJXLhbIrkaJGX9nQVHL#xp~kl zoP@1X%Pd(mIm)agV$|-EcMXK;CJiP$2`oeMMmZrL5_gV+M%WQyU6Vi5MA!@wSQGRL zRuR18dwpIF%B>iJ13tICiB43qsu696cy-~fHX8M726|07UZ7KE*K2(diLFzFEfqzY z*dNQt%FOTgV5F>T^-i-h4~?qF=wp4irFM9GIVrQ$9Gt7nGwc-Oc|Hf@&8F_P4K*v_ zFdJL>`^HzNRnpGxZ$Ur6Me{1xF~;!5W7q`qmTEG%|68My*4Knea&Yj)Tk3|I%2sHQ z$72dEnz9nA(Pzl*;Egpz79rAok*7*vMX4p?i4uPn8(1610vGTPLX&p!#7#4~`BhY9 z@$XhnUer6S40vi&v4XWK!xr#MvE(c4Yo^UCA5+TT-}i-2YsDV=s2>Sl%C))sOrZ1rM1-5& zPmjg3#(hl&jKzm1R`@tzCSkCoBg)O{_o!}ycge{ctdzx?(8A0c;H`Ie`QK`ls?~Fm{V+^1*#2*?x-$mv1w4V$0O$2Z}G4s||=ym{~Vk zZF&uQO@ofZf2(JntV|htO^QugmP;4r*$5IMTmM#_io3exHqmUj2;lNi)8y~=qf$3_ zz1J1=jlZB3Kg89lSdwJw%%c_IyGAZh~ljd;Fg4Ow7I(uWmz6WH7vK8=E)!kVZb{#yCcwi zId(17q4++v(;bVO=sb|Vs4DBJm5kdHr0L>JWlK^Y`-KJ0gj04Y-f4%8k1NhR z=;BYyCekJ#_;=&KD+U$7`l>Xnv+y-Fvm&rT@E%Ijk}_L&~ImvyECJELRsl z`Ze1co?N@b@?09$tA(NS`uPTloC4fDqV%ej@enf0M(*#qBhW~!?CoRTJ>VZ<kyJ zr{C$*qIM%`qw&6d`>j{~yXjricZ6_@Rw~bAXH&29**f0Ye77}LMHwC8!-Q3ga(SE< zzO8I}Mn)S%$+<|^zH8hKdkG7H=Nj4Ss!ryqgF^&HqVA*qcbS_i+?W z=4wjc_5f&-I=!{uJFOLtfcs2JPM$AXgW{Ph@aifd$LUy2-p& zE$d}^6@`sfQy1!$i?kV|k76+Gk%u)kHDgGmPA+CWBWCwpBopI4!laxmHXmjTU4HPLj86TtTk2nTR>M^czXr8B8dF z>&Mbbk4hyi5iK6(kV?k^;i#G5n_c9F`5EAUTx6?b#H=P$a!;nDn7D1SP@YZoTg81# zRV%TLUvak;h}X1uiQef($FIiHLvG|opAonJg$}Q+kf{~(}JseWp5NC`AW+|sB-Y$eKU*Fu!AEyR(aKMAD`-XA9 zUWSB9(cP)-j$83_y5(0X_~lwl0mSO>h*LFJ`^KF-KpxYdT?Yr_6Si{+SKqG<7u8fQ+Kmuby0d0=^V7x|7JA~(Wj2#)X=DsQ+(#| z75KKz3c915z(}}qO|YBquUC@Cj%mwcFQ)h+I&~CU<&1iGD-MMT7YjaUFLaa7|26Zu zODsW|hBS&p9y_P44I_R$L7gcpRj|%M>?_Sf(W`vLRJ zk!Mye9=zk!2|V2I1oFYF_cD}J;w;JSkryog>gT5L!7EJjaj*(2o3K);!5}+jS>!LQ z#U>X6Idph~?#3Z^Fth8;mDi;baA?bv$MPvKdrwz5+VZ5w&zEu%? zqC^OO&r8qRb;3#2w=xq=DKr$(hvtsIB=h#ACOg%F4hP`Y@0r2EUeTY3y*W00RcA|l zhfSuaQDeTTWPcr-$;4S|9$?m1{TTWK50!jJmVz?WbiA%s7E`RkK^5b3M~84u4w-Ec zx@;(%DWb#Tz~3~3{^GJEK6HeYzUP|I(rc7u{zE8G-!>^G3(Ieg}3_z8>%tI8-# zKAmQ%QpP0dV9RArnXy*vnCad`Wfrplp|aVdl!541Qkqyu==4uoWz{xvc@z|mp=1d? zE?jVmHx;s&a%~2ni%HdCN0ZPl?p;bEi(>C4zJyQX7w=+AgA9sfr;nrP73lJhOEg z;P!r(SO3eCRYQAiFm1zKp)GHt>C!*s8fm$#6W{+UfTOC$ak?rV&^$lnPE@j7sKt~* z{Y}r3(ns0d0%fe>zvZqpEiTv!ZWSqai>azknbt~MGrCZsf}U*quNx_k9v&I~e@ zscus2S~qoP{KXU#LS!%!?R!}g>1C9v<5STt3dCi$+i3;{wNk}NtTXh0CTvzbJI|GX zIa1159Hh7@6MdX~>m)j{Oq;~S3c|5uNn2%_Lky5(=Mv?(-MhzwC;7Pj)2dPtu+rl} zsfT@Rh(`H zW9m?)Tzu4BcJ(Mkfj7h2cF+wmPL8iiRI6+64AuOr=E~&h*)cvoxxGX^JL``40fI*D zS23e`-c}ySG)NaEv9QpB`0`=?AD&mNiYXq#$C}db@3z?22=5xu@DlHx9sDe(u_C`l zG$Xk7Xi)}r68A6Ez9cgtJUUQ6DV#J+5-(U#9r1H7DcP5ZRCLd3F6XB{flGx#=s+wk9{i9@R z{MBaG5`?7UY2N%_2TPnemV)5E#INA`IwgYdKc0ygWs(j)ho{nV+WwttBSm5_BK1=O zu0O<@6k;pHAftptGRh5eX^c_TFdLX{PUlo)YU1E#WM*e?wOOm+j)cjp(`CdgQ=yEc zNn6s*OUJwb)D7Ca91Q_+30Ijqo+WK z{yzXDLEF9@(+~_y3#|-P$wHbEtp#zM(&_Zr?et006a$SZ!1Fv>HJe)9MQM}aAg4c6 zC=E%jF-!x?E{>7J27VuE6%ViC?A4GYwA($_*0$(&6Qm(%j5wH9j%5m5$D}@1rqy!s z$|h;9QK_J8+th0wmZ?#BPJa+!n+_Gv!!RxCRTGg*x;sTl?;A=m(lq7r#Y=RDLu}i_ z)HxUYfL5c1+RIPUN^$k_1(sIVky@j*!Vdz*C#L9icBnN+734 zd3}qy1M}Fm%D0va4SBASrod2w^^J8@t~q-2DBD|`{Kyag2GxsYpfuB&^bvOvH!pG&;bxhk~I84}B8!#N^c%=%O43#GY zamKKp(eGw>Zka4s2$9k64cXr56GS<2oFFi8U4wGP!w?F`vzVD0rPV4UM8f87mo(LQ zwKA2mOSS5d<_Snp+9Jo^=cQpPJ)D3=`4G{?3bqM%O@rQ}nSH1`VV$0w(#j%cbShmFl0Zo26vdfg6M$U=X1 z9ilv8-+_Z1J$_R`$5NT1G3ayT$YB(cYRRQH@F|yEMkglmoY!9IXP5%plW0p4#eKGS zHFwwU;MlPvL~(#=NJd6R8Tx(vV93@+58HBB-`K=+4NMCr#%D;A1R(^iW{s(-ak||B zXU;s&_+*PTOUYGA7=_rjMSl=buZ>WvHi;9Tm6gksN@Xn5B}qd}L(}WG>2xxhjd3cK z2HU&4R4Wd)T_)8z&DIE>Qzec}27^AG&JJOiV3$h7iDGSiK(`%}sT|L7D0?2&Y6&4d zv~V!(GNrNuLegla#IaA33p6fqr0DGW40y3iIZF+k8W!qG0bt<)&lf+I=PQL8#v2p%X zkU}5@C@C-uNs@&;{OA`DhUUuRnSy=s`DaM84AV5Pu^SpvVwf3~ibJ_{mTs?yV^@iy z5aU^g&Tc@j=Tj;>)LUiZxR2}EeDTYl2ANW;mN|X)aSTHM38o2-?U3a;X_Ann1=Y-G zYlivx6Fh(R6uo|%Oog;sCHmc*VQ)a1rgVD)I^7|{%&Am;awTYY6OtrD0G{jMIxZ-i z;ZU))6#;!Fr<)iilqw3-PVoDZAjlaGBm7~4CL>iby}m+7iQ`&G)538ba#g5yRjdheAd0$Y%d}B>Mi@pEfx05lhL%(+Ws<~4>y$>l zMw+FRq(PDdG#VzhQ=>oZ6DOK-*}--Ugv`iQLT`{^_&)Oojy3!FQDkvNUXvW!yML}HLfZ7i#Z6AglZB+ap1Fzt*WOc)Le_pE6cq;W>%r`V=L zmc^u5n@ndoC4-TXDz4{IZ>1!8NPifBNEjJ&Fbo?%u<7?w(k!Oxl&IBe*p7wF9p3u3 zALRJWZ{oH85AlM^_O%kKInPNhtxTB6Ig7vLy2d<_p(uxk4EEbb7n2Z7$Or>=1>;y{B=G6cQyM zj8h!fCQUPhq|on)2&0%dsUVFq)w)5F32dj(`D^7ereP7q8C%<3`on-~%|w&qW-bpM zzlUblV(a1>nLUH5jgeXNbT`-djeq|nSFbKGyMLbB?ygZ8GpRNW%2k_MtwG7FVp)PD z_DRx&I7x6^2Yb&Wc0H-Xu8UwKal*ot1qOo-nPHIx5o6=i95^`1_VNmsPCd``frA*C z&(?OEepuKZo10y3x%C+Boi@Q!r%B=-v-8L4Zm*%OI=%G`!YsiqyX>DEXYuMXN{OPJ z)zB<2tsteQIWb4WQ0(-4_8mCDrHc!A4qUl%iK+c3so1b^Qj@1#F0Yl+BCa!DH>9+BQDYH{YnVOtq zx4jL*VE@b!b~{^)jm|UD)cAhD?(Qy0tT;4(f}uZTW@?^N*<*5IlI`s^q_m0R4!4}V zhsz7+3)YfElPQg9Nu($`SV?T+Sdlsk+mc8LN)@r5Za+i{8-&G3YaC-VCC?LVvxH}t zNzxFaa@ly%c+)23Ncs}zpovAB4VgY!3$Bn9=1mWp!8qTAahOW@qui%d-&#C2Vyp(s}@;@GEJ zsk5@O#znRR$|1{b%H=YXlXYCDSZP8(LkbJ6A~v@-SzF&k zcPE)hPmub8{=nz(v7?;b+`=!9Qym+l-Pz&H)2Er)e}upDvwsEKyuueB{Wm~}G-KSd zMWxb0C>!#WBm6R%Puk3&{FU67KUtu2x)r&K8sZ}r)2moW_3+}Wa08zmTYvFsAv ziigq)trh)V#KhznT1XI*?X@lRc$4KTm)IE$IdSY5YwOE&yBVV+RZJe?cKpRl~LM3yQv0;FWSy+&sUhBQD3wzf73BNZr>9h5px9L1QfKnqE^ZsK`1uIu1f z7IB=Br5U^akfAAPRz|Rehb0Oc&fQ)grE*4F4%&1Glbo&1K7)RUkTKn1hvg+779%e1 zK0}(PH0up!4;>&f>eMHWQ)-T5Rud-oy$RR07-lvz)p6?eDpE)c!^Pf9!c=5LNl2Qe zD4pS!T-=h0YXP-uxHffwhQThg z^GC>n0fT{0n55XI#IQUq488olk1&GoAY4WpCeq(MlMqzs~nn&*%Tm+_eyTGjH) z?ng+$>`aR!X|cPVQ7?~jV4sKQwg^MP<4-)vNNbcRia4C|X=ACtdFy!dbW8}GJI2^LDaFOZBX*{pO`Sa&_+gl%E=y$19 zT>PMqVMst@+g@R0m#VC9tWvMF7z}$%P81C!H#RqrI1KwC<#H9!OioVm^s`UkhaC(I zN{)kRNK~fCNXe3nz>f(07}v2F3^Rg3ico?<5U{(`B~43k^cD*6R_*85O;QAsi}R31O5_D(CStm&xYq)Jq5H4xh%c4Lrxg zcB;flLY79vLXl@VX&RGd7D;AdNfV{>Z+~#Uo`PXHF7JHL5A3C56b<`FviZz*G2#J&i!j$ZGcjzT6 z$c+$#W7wr}Qe9!~{3!_9Y<$h;oo_vXO3u@Xw=hi?!!U_sMUq$uX@Q~Wb^<~_A{);r zS3K&K=o}v09t3nQ9za@^m;pVx?6O6n}opv zmR+J;EwQlpJeFB_X|7&fAPgfG7A|w};6b9KOO*Dwy1a^4ifDH(BE*1d#iHL|q0<@A z=|y|x9*WJaHA*Fy^^GNJwHlsRVtHkW$%z?!f51+AgE$RY-&&?sAH%X7wl=re+TJ7# z6S53y)drjETS!A<+JaiO%J|qAQfgYQeVn}IEgYD?8Plo~rx1i4+B;X-+<2Ppt)~dW zfGf*g#*-@bmP6ex;xhfN!I@_?n@ft`c1|2-G$(T!b2)i#A(8|gDLl7~Q!1gdi0z$4 zF0P+qbYzYrM<1fMx{J}>q*7_3^D5od4u_82%frwA7DDuBH5}4Z;twN)NI?qH9CkMQ z42BUClTDh{=#3>9Xhow@r@h^!-S?TCtg^YiL$}+bR;e&DGEJ>)vAVs@NUer#dsvo9 z*(;+|P8bE)}jE@)`Ii!gX`8<7kjh#+P9!tWYNUSt1k4m+HSFMvKLw0rs4ALQ? ze~DhV%UE7vvRWgH1X-pybKweebN4bgdI!s!Phudk9G5)vQ98wPEs`v!KS;?lMY$Xj zg>SGG!*oj=J8?7lks|n|wMMJk=yW<%Y7J~lqBYF>A-3yc8iiIhF&W^xW%kX@(I51w zlxv_e4jnm4sa!#8RnT$Df}(SF-#+|7pJTV&LaSM482ETjX|JNL$fym&gmT#}C_SYt zdete-zS(IMptQm?%)JcV{KcxXmq18Kr7=pm*1)n;CaaT-j~&3aZO&eJ3?U$`=G5v9 zwl)S>W<(e$W@hH;_O~!?McFH1TLM8&wOj+8V_7bFo>Fpah?YZ^t&&6z>uWtU0@DJ| zv*|}ZmTBO6Ri-BPAw?lD<#L5AiNGl8LuO~^SXo&mj(psbQDma(qWPy~6)EoZ#y;-7 z@BQ3y$1MnHar)e4ws+fPS&B}5X2&apafEH%Mt&e=`Rebpc+tWiButE!x$UMh)B7a# zQ4LbCwqnp|xGXLDL=nVEPO~+IX}XxULzYIYZ(n8*4-itIGO$dak?9)Ut8F|t#PkHc zp37Gsd4dPtaW~tY%MAT4b+ZaWGaRI3y_jw4i8zTE8=peQ8Nv`uPfv2` z$`YpK;&}$Gk#RPcmr24tp)#4>zmLIio4`*HLZb2njf3Y@Xn2CnewRZBj*EEG(Bxl)N&M9m?evGgF7yX)j|)gQG|91|dP9pU@G?|pPTT}p0+eY1zqIz^KgMOdc6+}u2${Paf& z;vuD~S+sD=6oxG7I?#f{Cm&)M+dT5vb2LXMKtiikXLe?aBnnwr+F-m@#~3xJmG9-! z*~|F;S9su^)7)~~DAk&cZCY4%j#fEYnlLiDi)jjm{TRz|sF`(y%1}Bdj#5^mbxc>F zQh{M;S|c`xZmG~I3l^T*z|Az4;c?9-f|W4F_%R;w{RKEh77i)EVVJj1YT zJgEaGs;&gv4+UcHFn zmf3&g1aCcYkiT*7tvuE}OJh7i%M{CQ>|JL}k_>P>n{vgY(X`oGkEnYM%nUF!nSw;5 zWLAPOBq{@8LauULM{?I&C+KfQ>@0S$>>UiJ#;LRCIClIHcOH8W&t3Txna=6;0=Bm! z3~4hyTBlK~BV~H6eEAI{7*ZPSKe(SPiHS4C=tzqsPMDmWL?G~kA&ys~Ns$@rwA)~q zjEsAviDqhMmNoWTocDFAx)ENt$MBJT+r_^)*9WbE;Nc>64xYMQ+9JKGa^kR zR+rCn@#00oC?rV|9{>6i?6lVqNb)?pMpo@sGPZZm)9r@*@t0TeJb~+(Tv~XVGzqDc zD;Rqu2U3Dz2yEM7=nqiJV!Pep{H3Sq_PY3fpQ~4|lB<-l(FVdusMl-wp^s%+q-jo; z$Aw$lG4@Cq3`&N9M)}bn`Vl_-*M5lQ zwG9?7Ug5d_`~{BtKDVEozE{08N`jg@C?_u4qFgJXK+QN-lF z;|#Xe2(yH4zsJnX5j;0xb$t_+B~0y`Cki`s1}SD9;+Ct3Ji*Te70V+^`;g`AKXihX ztCvAI48lIPl!o~Hl>OK5~PvQ8mSQYVWI9MA>~S` z$T-yj!hj$eU~3bEWPEgr(UA$laLCl;A+~llD3@x?&X_#@)UyPB%Ixek8pUpBjdIzc zQmHdOK1&#dEG%Bcb4m;oAEgA{-557EupE>1D-pY!KA@?2Ce4aVz2xG$W#SBM(`I(O zNz;bA@4btMS|fCp7J2;FKSK8PXQ|bXu(kX=gYGsuTV-}`obibggF&CQjUCq42efx0 z%1)J%QKZEq1bLd$&-x5|32B&vmIzxC_=*dcw@^t&yMtc(`Cb<<7>4^y{wJIt*ipC&G6Dp-| zRHp=aCQ!hOpS$4Ty5UaA|VNzcT7+(ncVw>@8e>k2**d+eMS?kbU>|P*%pX|F!EVl z>$0&vq_dlIczgy&d$^?%nHCr*b~_!yK?Zpd&2}A|a>XH2nx)MyZqLUq)sQ8ZJW0UI z=>;*DE?;6|e2n{!znf>Dd!AnJ94J8)_;fo8Y2-9&>Gc@C*H19gIA(ca0k={i%ToL> zq~tl+ZW)ynNosyPq~a9$QG?DdZll3St;XWQWu#%@m5c4oJjW0Q{;&sHlcou_?V|IH zB*}2S8kTLcytF~B=236fnVp?`)k)-qYK>N_sOey&^)2s5qp=->k)gw#yGuh7fE54 z7}B88m|!p*u-j>~xwVaDH5qNqkY)ncwQ)U{TW`J{$F7oPDVF81xxLQv$|7;7FoZ{? zRHs%RV`*_6g~T)jFC}$XTH|qL94C5YIuJNo=k?Os36@Lg>G^8~#$@jnO9p94qbgw0h`-bSz10vtue~h(kVQ*$hM`uZr0jsMWHa1t;-VQL0Dm(2CQ5axIiSLK3Z#;+VmFRTa zn1;b_dxs>-dGyi8D3@xiZ*G9HA#pJsi&|aNPBT=lNOK62oGWVsj!w)m*&M?#z#t(U z4mox148vZVcPPdD?YD9G!MB3WIC=gt{`jd!*;olc?Xa~zBu#RzUgr3!C($J_9SeYSUd?B6#_zQ;O;5Ll+k&9@X4 zenLQ=tG!eZ!7Y2#Ee8%Byw)nrwr$iNA)Dhkqmtm#$!# z21jnXiPiNLKK|)H%b8qJYE)iJ(_n$t3QVGS@}dfB#xS1OYJ%Ga^i zMG(YnY;@@C`qZiujExa+NfCese60TwB@ z-gXlYf9YX9^NCL}Gd;txBZqkN9ryFjx8BERAO0f!o+2FNBtg!^*aS0;F|sJctyDoP zw9=TiMGz0ERGXNFMYq!>&V9l#qT4MzafZ|gsVS9Alu9vb3Nf@GPZ5U6FbG(k6P zQlr<~VPj*Nsp-Sa%^qiSdxI#9@!T>>7lEmjwI$LlWq$t&OiR*iGjZ<=POD=|MqqT+KgFMb~$~mQx94$fT5;BQO zARnKcD9+R*oaJ#DM{uJ!F4(H@tAgaU2|#%qJt_(4PzM<}J)+TKJOC3?L!xq^~cC5~hIengz4Z0)SzxfOPI zw@A|j&nvOMxx~=#bN<3}xL%cV*<)>EfvxQ=q!1`AxV&(Ik=7JTD~mLnE#fp{YHEZi zj4@3Eu-VteBQV^T@X~OC49Zt4J ziNk`s$#o3k43;-`a6K1W3ii!SvbwfT=MVpw_x#k4^N;@Pf5|7ma0-=MEMI<#_LWN{ zae(Jk5JDleK%i($ALjUje*v9l*mWDLe3)Afy_LJnoVv^zvr`^F{VdNu_cSA}O||5c zMIGYhE?;}}akR?O8p0%GZF7ywS1vL;e~7zI+|A;~DkcKUzJ9~^hG4t~XdulLPRXU- zGT7Q|^YpXp3(j3DysaQ58qp0c5H8e)X*jid6 z*lu&{?GNC$O`blx$?V;4;df3yjcwbQrh!1CbWwS^GR8c`SYIwGK6%I(m-lWu2QU0nccu+VeKkH zXdFuugfSP-o+nFEs*Mp0OOQuC_l~af+4H;Pafk{BEM8rp*BjEbtJoz2Bt&t@)y1nk z@#K@d^9Mh~+|&`yEj~?}rA0~48zsQ^T9Kv+&p!JsYinyo2CioBwdl7X5ZC%Eh?i=U zFMSZ#tgjb%hQ!M^`G)U`7r_ewFUN5>dGe-j;;7;qPJvdqw#DRli)N$B$f(6&P{y(( z(sURMazZ~M2|;IIU?4HDO_O1e(A$kMj0`Ci<+6#?X~E8sXC!e(uamQ}*(HpNJJ%|} zl0HB8i?=aT-n0@LDQ_X!m_RJ#${u?aq{I%kdM;_tt{GGqU z&d%;Ne{>-SvJi$n7QzJKBM8{ZpJB8}qx0}njF-}`(2k5}#B zs%$z~W>tgmgezA`}X@u^Nu%u}x>wCX;+{(w9;u*@pU zOUsbi7?h}0${0q8&wuu52E&kC3ry3&_9`GUEDI*5T17dllGuicVF+@SVcOtTBxo=s zG)G)aN7C!X#6eQHj#G^xB|@2yo2WP?O%;Y&G@H?)$hysRPRHorH6=+9v$-^&ZcDN_ zVbgSQOvV1u8rz#2{MKhq@yN5Qly*-S#b;OrJ(7^5X~D?YPi!_jJJ{6;vLrzYMHmL8 zNrWKrGYXGti9V`SXf{% z=)byPC|Fw_(%xNR(8+MCF3Je;%AkeAaA+32%j1knsYMhH7#rJ%<9L+IHC9#@S>IR( zRpQ`*Tj}+>7)H*>NS*d>M!)w}lBD>Nm9)s>4l0YWM@pPOTj=Fkp3wIPtZ(*+V~xrM z>eY(W^MIMM(Gc?Nl=Npwyi5)89gnS?3!D*B4&V>uy5dGU+4+>t`P!3OXE`9OcB!43@ZsmeHo`w=vLI!o;;~ETPF!lxj_$y0AdcEOB!F zAk|8V)6ZQX3d21fT7`;-NW(=sCSk5f(y%Bk)_~9mQ(%}96>AIxo?(%T94!KN#X4!8 zGdEkKRQhvjVO%*zN^cdA@m7zc6rHnq`P%`uqeX^)-qK4ZLTo_ zzT~}SSyZc4+U+(;67Lm2{mCv zZT$*C*dtdteh|{_M0DE;rmQja2TV+iaqfc8=2`$K%H^V0d6p}bPS8qW+6LR(A)aTF zBmskAL^x0+dm4o2**K0vx#VF;h0sGHQ)8Pkt}P4iR1U!~LC8XNGL(TdHKwBr#tqk? zRB>^u$LVHwu+gbt*ZTOWVh|09+=EoA5zV<#`ntzt{}j7xrx1CHZ8?;^GNzEAa}3+U z8#_X{ky2{TGC5V_zyLJX_LN?%i#Jt|%a4d^^ayS`3uOhoH&j#Ed$H65K{1>RZ&A@?3m49POQFz!G9;B& zo!00mu4kZBLVu9bZVyPp9F!!^;gZ-X!#5(E)R3{ey_91fV9-OtSQ z44az^96L76U=Xvsvckf`0+VBhNg_qJw~OoAfWhS}3j|RgN(J4I;T^)4_j7*xE-)u} z*L(MI$FT}mu58oW-ei5}Z5(gKw4zgd?Xj=0aQ>^9q_`+-5=ti6(j-GOd*lS~{i$ET zd$h+Ne|4Slu?icTZ8Q>L7{%&sm}CN?K?k?&;fqn$ySwbO63_*UWfVmiPD*7|GBMp? zc7K_2!(w&4&+d*w?j@U>#-Gy_sO1SH%bxXpnNRiDFR(3+$0{>Aj|mCcSPKKaBUz|E;gpDOt3}Ta1j4Q7xPF!#0DR zkbWm)d$V9CPXkTAmvZ9xBvDjEfCs~vUN53it&t=dwgba(o4L73nzbhFc8}+ucj)zc z?BBnik&#hM)8O3sGelX+;_@Q<=4Lr~;3o1sBMd^qC}DBwJciUvjn9&%5lIr^xgMTZ zr_mT=YkM8X&6%E_U~Kdlo>yggWtB@;E|6!6Jhw0!??SfTO+pEBu;>z|E}L14+a5T< zfzp1|rRTW#^wa#|qmQz^y^4|h7&-%;qqPM|gk{$;y%I_FHU>19+b^k{8PIB#ICJ(A zP}Jxk3N9$aa>%ljI1KUXRo0R@2HOL&&?8Q(WcdpBKG>n!ikO%)8J#rIxu#YXq)AGe zB;;xQii|GbDZH+Nq4(x+tuq;1VZZ~ zo7FVAdUb)TiwkI7@WTdviXktdb%q~pP^p=WjkH)>1Je{7K3?Xzr%sWbG4}e0Xv#G~ zsUrC5*V-(vj4(3Vpi(Xqg+5Un5(Iq=)8xXHuVdQ|Vbtf;nTLtu6hFur`aSx+4(sa| zs8=gwxn^s-Pm+WPp{Y(jggg0zWT`@^0SHBJ{W72W?Tpc*0do^J_gYV*b}z8Fe39MV zO{5O7jT{3_9_NS@(qupq0Ij>|t7#%>V0jkJhDR93Y_9L_b(@t4X`ukqE&&Evk|U)? zR3{mTqgV}xF}q8%yiTb!#4#L_FrmFIa9x9H#ROpyg^(mR_1YUOiSXNj)`fWV`~YL% zgV-~ag(}FBrNl4{46TtAm2Re#47Z;_be`bk+&G=y8e0pWWc=W}kxqSYwa^7cPp(k9 z2s|mJ(b_=if-N!2)yq_~SA&p(YSm$7W595jlB=9F4Tw^KG;L}Pfmbqc44cr;>9!-{ zI3-CHAd!Y9%MwgeAY`H28@8bAl`u_BbJU#Hy$vNXpJB66j%%T1~?ZzW4Z zPyvFXh$!{faqIi>2Rn4y7g;i%B}=;m!#1c8p%awK$x&bmVy)=L0cvy}G5HYtkIgeR zRpH7)n^wan+iPpBb%r!dgfvlEg5{L4+!}^$VtP$n*J7m7#=Q(NECho7%tk-bE zC96TA+G`P@u@O z44uaqjty!+MeJb6j5JRWdarl5ge+4ed4@18N@M#d&)!S* zR-sfnL>Pw*1D~GXb(eD4W@=)d$1j|wqC@gLM+$)- z1yoB_pa>>vt+;Y_l@t5#raX2BQoLx)|B14pi$QMM7R@n}YPpQ-xm1KnrB7$yi6;u;~gsmTn1X&AU(5o^Ez)19O?{{XkX?Zcc~R$N+3 zn4T8wpR3?Vfka{17FQS7F-#AoQiKN6j!5GOjX||Ffv3KR6PzNB!FTHPJr~QeF)WjE zy+q9`QE$|+?SkDr%@iaVwkwMk$NG)dobo03>en9Q-~6xtE1hmw50*%%- zLDZ+;j~NbQvMi@scW^xerzFu*k>ti+o8FWpRbpw}BR zIZ~lWU%{%*?opabbROYUTSXLI6gBGF2nv>VN1zQ!jLlHYar0aMBFnuRpMAW~ zaNu+J@Eix{>s(pdVQa^tRCagowTWs1^>jXS(ZmKW_827?gK zfl}GRtCT5MY&_eh=SHgGQ1>?+_GYCVnZ{NP6MAWtm zp~w}|QVilYGW7_e0Jr4exGq5ukYyQhl8`0|mo8mmePg{~1WZ!Wos{*}Z9e;zk8|Pj zGqn4CE^jPjSteoZBM@YH;q3Rr!L?Y3hN910$)jW!Y_(b`^q#@{YEVjZb)m!J)gB5# zoMgC;i|5uzGmT*=!YHLyX))F^DV0*HHHBdaf~Zg%)66DMGW>zQ*0NX%O{?W`@KA%1 zMx{`lR7x1`Y5AvL|>fFR6CQv*ZVB(cOaDyYb$?zz-T4%M=S<7gaL z5Jn2ev5U!}?qFGpAPm^rSYUno2}bKPTS$0;O^c%SIYDxk}O6 z0mDToh3y#Fj)~)#cy96gAWVcX07;z2^!fq)j!&Lvw3=0F4HrWmeq#!T)|!R&D})n$ zZoBz7{h&{^TxD%zmAW@V-|y3jH8Ybf&R*SwbOh5hY45gi90$WJXl!(6ibZvzOtaxIGvkr#K53ehBmv|Wj;Se^4FoxXuTV-* zt{9BZR5^5TlCjYdN@asMj>uI?Z+1W&rU(hU?GUXqcDsGL!vrbIOpceS)|)uCP02N= zRxL~;DJmkh0u+YvLJ+kW_@-^*xE6NFB)D_|e{+=T^ljw1M0yTs2FQZew3AqzTkc_4 zlHJH+;2tN+ZB*iO?&1~R{NRK9?Z0+2X{ExK{^)V8E^d+~K3Xdb!^N-w5nz}e7#4Xl zL`oZBSmb#^mOGf`d5mZc(-Bx!k#X#~CXQ(mrx2wHxl$xi$i`ZamE|@lI5=MfD3Nba zRVqzVHinyYT5Zxsf>}05WrA=esh^>hraE3FFaqp~jqN)i1nYw}?8wH%B8xN5T|7sr z;$b=|iC<7@PPE3k{n+iOEPGL0_6+XyRa7HQ;dTT&^TO%Bvn&CjpWoL7XjkRUk`7S-(BQq1+s)1K3 zH7?aIb&lL4AZ98Xi+P_%8`_>zDiwMZ)0)&atv|8B;>D)!K_T zzlP{{F0RE!1VzpfQXr+lpdYfdxJeuZIO-55Pri@QnR_{W=me9^3UL^+yRpu~`7=E8 z_#>RX@+^!bcqPqXkYL*(ajY>d1JAK>9gk93U>Gq$lo9MIGOZa7V+1|w6_Bu1NuD3vB?RAWZ!Wk#DNN{&s*anZ`8(@W_0LWIgNq@Y@NF)f26&uO;< z0{;z0pYsCxgFdd|@WB7o-kZfpmZkT7zjMxAW8ZSGtbOb1eea&;>>P49!_mm*7$B?{ zO9l*xfDOTx9}F0_Uu{3|MSigj2{uUB5=9#pCDI;C6r0n-nV#mTr}yfvy>ictj6H7L z?VRI>8znbW6#=4Y`vbN*K_MuRD|s-sCdhpbrABqMa&M2)k& z_nxJ)e;F+#%g;Sat5K!ZsB-S&d0za&m-x}k|B5#+f1iQ6$zafBI+>uY!Sh2Z zOSMv>{Q9IsfUj)RpBx3>@H z$){cmsD=uYSjNMI zes@f77@=g2BL$s>3X^HfXcW;s7_q+Ee=r@R-yd-4;Y)n`TYrOUrHV7>oh_PrmNZRq z=hB;h{K_l5`lBDBgyckclF)`s?1V}V?!31d2(7{uX1BB8R*2|_z;9Xx35jP z^5*X|>hDwX98RA+$(8SXhhP5Yw>f|D0#XX9%?6Kr{;P~<4!uc**EfEj@pJ%IfD|a@ z(rg5*Ec?_dCA5Ze=+mfINjtC|P3aws>38~6D;~MB#Cbw*IA%1Qp|w+p=D1#=rn)m> zdwaqM?@j3UvUwh65gMc;$&vy6TR&v^($^85MCFz&k7%!j*DsLCPKXr6{D;+slZSQWII4eHerr9iN&GbZC1gJCpBWItez(d!+uy1L4VlP3yT_&od&#pDr5 zoS+o_35^L#wd;|pK_?2J#JN)9ee;Kz0*EV|`&ekz{mwqoH&eDSSDbpCB*AwjT zIxH_$>9lKvzE8Vap?Wf)(=3B1wCIe;5uU^aN_CgvG-5DHn9dB!QS|#MJ3CXZU74`A zm0~owN+6X$ieg>^DH(OI<8Hi3bNy)$8PonPdV70>wME>Zj5Qi56-qf69g)XFr0ZcR zqm+;9m5cnuYJ~8S%0mc;qOKtU1C}Dkz#x;DgM$gGbcTh-kI^O}&p`_ZBNa<4ib}(! zHw-b>(yCWzHp+Nji}m4{n>P+9{bh28{d^sxk01Dq$77V^Fr7>&mC86uB9eq*98&^< zYL&f%gMvTG7+lw((P)rm8LsD{q{MYyR#uj2Hk-Wr?z?>O`cDY0#dBTk9EYu4m(1F^ z*2O1fW&+2v9J`Qn`z^&ZE;{2sbKphZ0c{mKMgiC|NFnA8KuZ#*pe@x>iAJSPxm3Yb z4zncY=8Y@-=70BJ^9O(Uea=7oH2FkQa*m-KNi;10cG?*7%wh~=i6)72uofi*qA6(A z%gBbLRB@O_nmEshk|{y81P;aAx6lZs@cj_abBU$`ZKg%{*%dfSU^Q3)yeC804O)WG zdY+?MdK*7LIAw(2U^JNEm6xctj*}##B3x1qpvluwA#!ZG~?Qq$LUKAX44IX)P$uF*Ohoa80)i^wV6y}q)^oBF7WY%JZz!L(;b?^4Q(^*UyI5-~YSxRp>CQ5x0T}COxWRjz`#Bqv2 zq_7mwXbOVe5v?VkpyGfQ>@a*xn5oo*A`>GmSWWQ&I80~Q*0O(get->sT}fLb7dpth0`6ThZ}Sc za*UN!>kf`AlKfK1L0E^$bVi=1g_PMGv5;jCm_7y+H$EJWII(_=w(CNcp_F1Uo1vwm z|w9 zh0t@zvW(5abxiGx-PzR0HZad;fVeH z1ANazDTV76TGX>>M!8fbNfKgPNcH0cj}RDuOO*QYhD62%kBe!!QWeU=v;(~cFNr|Qj@hrphJ*0HVGJ(!C@hk&j3nZ&m z^mZnHDJh!6tL_m~dH z80#QaWey>iC|sl}cxtUK2;HyWeX4VT`^lb1;3g#JhG=p|qX@^9WGzKl>aeh+s8`$EA0EQ{=oqtE(N%8MYIu&z zAWiU;!q=K~zIz1LlFq3&qsau%b>^@Ums+h_%w|}NF`77znME@kmKr5e?8fV2UQnqq7~e`K)+qH#i4R;;hrkgJko z$4aDWO1?}VB8X}=U{Y>Qa*Sd*363U(e<%5L+24f`XCe*gHk@q zEg^(MoYY*DS&kg81JHSd>S+&{;dP9^{ZZb8OXa!Lpx3VIb|utJbJP7y0Q4pBVAaU67- z5|&B?et~s6xrXH~UC$>vh7_DST_@FR7%d0`2iH}MrzxY!l*5CFK{sbM)r^uE z8pAZ1GMz=(R3n688c#@RFx4r${T`)CiIw$py!eH$^MuOy#^pEpUw-R<t7fF>r&lM7cEMbi*$k_5xk$kHn z7qm#EEU-~`aA+VAQV|3m>#Ge8yUCpNAVaE@JkObCWuANC^X$I%0M!dk#Eju=mJ zs!5x{>=wg#gp@wfG$jagd{0seod=Jib1)oIsgx`*k4N06x#?y>WT~qc-NDHoTXqKyFUO+qv zSX^A;p>r>A?(`$Lt|gjoF^;Y=j;}MAY|*bq)N6(`in-n2M}+&x);h{{(di7QR7FS! ziw2W|Z~yyXQ2#gG*!&%-1cdxsg%JogLqFTX=) zX^B&(kF&kI!7xr3jwU32iX$OSQ@Y)Kq)N~_LbjLh*Ydr8j?wS;s8(w@zK_}1CB@xpD)UN+5Lheca1MzT^Z5%sZ#eSl^B77hK36}BboUw56lhJJ z&(L{5rbDvzI;W3M=?`XfcN4^D#Hc$Xnobc|k|-uMnwT6d4RIdRnT`po<$JEPy1L5W z{g3{0-hSszy2D*;=Af)kB~V2ykB3E&n;dO5xz5Ql4Or4tQIQH?xl9goj2lrdhosY- zbQmz&R%ByKd7@Z&;sR@HPZSrmj}b>*cD7$-HvB_c%`TyDc;iRcxpC_jRi{I%y@uy| zWJ!!$mI&ctZGsfG00v5lwWionis>+{&9TzO>KG|3ahy^K6t3r!=N6$Yju&FIpxd2N z{pv+B&v1M524{{haAtXt>)Si@W-0A3x`w1A7OtgP_-^Dp4}9DaAc}QghEBjXs8r zP>8$4gGcX|ck>S+IC0`6wd$wT#Em7Kws=%8@tWB~dj?-AtPj$ac&^9#u_b0v%B!z! z^ZrJcJab9XLLVa0IntFlZV4$3S)P(kNAwR4ke){nct@Y(vB#g}*S_;jUjF{?QZ5Hn zLcbuDo@5wdn9Op(5T_AYs!3*=EX{F!muM^*>IA4+6M%o6~H~#=t>Qi?sl)Qj!+DE5T{J%EA zbc`ecD+@VRVX!8jXLJUPDZ(q|5Jfqj5;UtG-7&?)qcK>|G8snPV0DIY3LOk%a&$7r>KueXx@Dv+gA8!o5S`}*WJD^GOfyY$mOCE%qZH3| z5w_3@Pi8T<4>FEF{51W`S9$uW&(Uafz#4Y@1Nz$=L<>2w$?$y_JIAZ#`T^`?Y;0}v z`cK}VTCI_!8P-^8)oRg|);XPahn3|eELIvHkzC|b&7Z2d56(>%whKsOEC&7 zMNuALHkuPBPw?fhe1$lU8IQ-s6W12#*?PT(kRQ)EWUV1iW0X{Qj*nE5N~Mf7 z<`a*}1^mD&o|?GSa*qRI90fs1AY@UA8AoL{cAw^8FGA#3KpRSqj|v=wvKW!gIdBCP z-{Gu{Ru(O%tY$Pd`aHJc#(y|M{Qs+Ixq5 z+1|W?lu#Ni) zbe{8r58h*^Y&niapbG~}9Hz0$wOercx@0tlN!G*(0y16nAXHWq0UQT%Yp{97Lc7V@ z+8Ul$CJd{rU3`pgcboBaf*lJ=s>=D*UnFp=?2Z2z>E?F0t7QNv<{8PHP((ba2-pz7I5}LlN;~HlpM?9{yzKNZT1g$Xt!FFYZaQE4*UHP zIZ*Z;l#~ny5yOF@@t`&M(llj%Z=Wnnh^8=$W2)5(gJB;>DjY{Ki(^V*iOsDIT-W8L z7hj}Q3Q3ZLt?g|#x3-R)%ux=_W|PC-;n6mF_Uu_2%?4ZB8@&4c*Ld`?$H;6%cfX5r z6wP`A*Y$Y!y?3bB>R18G?L*$V`Z~Y-YhNG;LUcMN2;G9S_S0f9Yq@dtJ;p7c#*-D& ziDhHA%*L+b`bNt3PKstq=xv}%Eo`+xg2l||HiR}PQPBTriVD*(&ZuV&CBSi9R+di| zNp+S&nj@9VLirM-=mS!B$WpsW$@N)VuCTX1qI(#ljmPrJ0_ZANu2^Q18q3QkdEtqd zc=XZ<;%vYuzRJppw>WcYi>#}8q`iQHBy)W_ZJ#I4pXAAhPZ2blOsAIZohiQW&|Fxe zzO({YuTYBnRQxGP*km?~u~`r0A1e?BCMhHULfJDuh@a)8F5qz0hKD zZJph%1NOFJo`1N(FP?NbS=01BsBo**qPxG3)`s3>#O}uT*h)WO{aBr9#mDy*QfRbJ z@Z1MXIL2`tPMto*_rCuMNt$A@OeRxut+CRO>m03hF>9bTzUQ;PevD3MfiMW}VKT>p z?|C#D4ThrvyrwnO>va|u7HG9PxFV$F*GN+jrKgzOQd#O0sNK}Vq0DG7W)`F@R!_1T zJc1W0e*FFqIrWsHR4U!Q-p7~}g3}9aLf>U;v&}mP5u1C4{%}S#jlpXC06cfVv6Ih} z%q}q8ze-7Kq;>Idkhuk6sg@Q9Ol7=?Hd{0* zHPTLswJFhb%HiRN!$HPj&*R5`(r4p(3DJBGedebOsuvQ${#73UE}8H7PniB%AGHvKTpTak9F~=@S_pHjr;@F&GZHr4-Fd zh2tmI+1lGMXHK7CXJ?1W zbjoBpVLTc$nNFCD$BZWvrcp#3$DBWZfyWrA5|gI+}QD=mV#Gk&6DD8=dLU*zr01Ag#UpMz0Co~Ia{&v~wjvT%}(sWmHH zeEe5<{ZIcf+d5;WJQh8dDi%+`lTSR!7rylkY9~)oD%F^obPm`R%xs2_Lnw;SvC&!N zxbr2h-#EmYJ!*{*B{f-Aqup+>y*=i&@89IzHxJ3PMVyr~^5jFj7Awr_S2=OKL4NiU z{e>3p!GzVN5j%%n&Oi4&-}z7eV;ZeGt|JQ;MGGrdQjcTuG-LDjCO5BNCAA=YiR*yy z7Vwl?^d|B?>C8t-g>}^Yfi*)%J#;cAPop`Zo5l-kl&cLE8y@SR z$Q`YWVje(o_RJZ+_{A?Fgy8h))BN4v_>CjTy0w<+bV?G(NTqoAk%zI?lIJ-K3k!7G zZNC2}-zO{ueEr}5Ce3E^r^>z`H7g|B+Tka+x0y_)Xrr;FU^%q&4zJOMIGV7r@di&m z`m1bhy~m9kKV+E3RL-B~!l{$Avz)UpJx{vahOmSIy736dk@${>w&sYDT_W&=Vx{>o zjw`u#?SDne80AVF&%yOPx(6Bi+Yyd*sWvmJ&Z{){8&rj4ck(vf{biC}s8&}wrk=ry zKO!hi80>7YcjJ8;3(q3MaDKgFF_h*cW}6!~*}8p;EQ=}m&24HgDe|jc3MT6=DDY5l%@& zK~(rbNPA(4OHVz{SO4~Zz{8I}%(2~V{>lIO&*|@Xajc*fta0eI399Gtt2?;fYalhg z?@}(+9z4g;c}_S-!QN%}C>Ecbci;4aM(2fgcY$px=s2H!?zxXF)DQn21i?|cRVqcL zT)wAyedm04j=Q6~0r2EgPw~iOk77)Y(H3KDG3@jyDTc9z-ENO4nxf{-axII+D}=Xj3;>W^|Gd!5l_hqvCpLQo0#g{Pn5w$NO8^BtbPP-S_kM&JjOm4}Zi zK#*8wHYc|^B^lr%DV0v(hUXX$UPCBT$RJC}#>N5N?J+BzbsC*z()c#f%l|zylhF4A zyz(NYjWI7>wuHzttQ&d`%!f1=Y zEADhoTXXgHtDIQ=3XeVUH`zV>A+=V>>e&n28jhLn>~iMhC0wV3l@=uwvKZZ=*nbQX z!Du#REE39oK&n&R>cecj`vWGEeKHf_DR}oMdju&gdn1zFA-!P_Wix7?Bp(_^>HB0( z8A@&1O96|ugd~j#jiP%i;!l6)ACum`MsVT+ufKBz6V_SXiSgSGvpD4BBaa}+8C|=E zhz%Y0fbKNH)e}zFU}V z{~NvicPaa0IR1b+M&JijDwSf#xU=~01mkxW+lL619mgpUw?T;OdiR{`PN?%?2)UB# zuJioV?(k`LN7GLV$-T7dpJLV)^93dc6t3$+UW}k>Auv`_I93tLB|2h~e86w~t-nQB zdXaZGE|a7QXV0AC#ECUJ;R03HLsK}L7KKyX$yX$T-Tgy)qX{d^OQdN+wX(`2YV)HX zy-GZesP0*&J8-&ErQ|{{il};$&~%g3lz z8qDH|h2ip91nx;HH8gz?hF8a2IoIhqa&_^;55Z^yg1r=oAzEA366Yzg=fp0e3Ji(xn)5 zl9Jp&ZUhzuwg`tR<$xDnT;s$UpA(A@W1Wm!dmF5+ui#3DcIX3|vCR;o(7;Pk6bLeb zCmfU&?Ck6j#R=2tl#3THg1gG?n?r1plWz&U*khqlM#^HUP-YJ39H9kCX2_8=Yb9E) z2kwYi7#3C={K7N8%0n-Fjh>&ZsC6i!6pTD;P<1k7NeJsl$m?MRmzV+Zr7&q!mN? zph7$yGKSc^BCMg5gAypFP2uh`p6Q_=G_WU}h&Yov+ZJla!4L7V(DK}}?YwYdc zz?z)nYbWr%0Id_I(U3e7oW1lI?|m@f<-rQcn|+qnYc!h0e=X?Lh_m~WNJoBY5@ZuLQ(YX{dEFxLT z@_vEN@1tV~A&#hVKJ?;8iH?R0;OUrGZdEy}g&m+?r2g!&|P-nHi!ppC}%F;rWJlY3!o8^@{^?J4F z?mG@zS~6*oNE`&wxFAhdLNOi;s8$!~v`^6Q?LgV5QmfDitN4z<)j3WQqbvmvtpmO* zsFf>(HfQ7s%4<*Y{BwVkD04XI5Al>mxf$AZ$+bIYOtD~ntjUnFgyWr|Q4c7y#lUY+ z@@v#u6%;83gRv5AgJQ=dMc53j!S!kgVG5pFcT# zj5)q~ntE#uDaIIU*}Aof8`SyQx4zD^FC6F8x{v3;D1$h+q*Blb?$4}}us>ge;h zQjz6`;dqP?1&9)n;d?I1af+&#yjwD!?`MoBQ_?g=DpllQQZnivl4n`*;1LpcF5PVG zhX=0i2yxE8C!;Y6R1i=K>xFR6Jnyq}5T?CHrSRx92pJTVA|@%`Qw)j}l5Tg7uy>BV zLv$yQLLU9hoQI@fBrJ{<(#3Nf(kww|vjPX_IJjO3V+>gi2mKh&_o>zb=7Gdq3w~ad z0q$3i@4h;Q{g~b1lbqqhfB)%YKC{p4=WX}ZF+Q`;>_N5r2R8W>%kzvhO^*ay3Y|8K z*7>IprF~|f+0W1JTk;)86E1&njf)pAqIHf^#jLadHa9ou^#-i1pQP2Qa_#bE%FPbG zGW3QC=guBSIR(T#nihhUSVOKgKM~ z-yCCacbj+Lc^lXB*t~s<&cYHpkLe!v@%<19+`4{^x8E8gjV9aPF0fG2W$X4emex;k z{^Sa;{rD$fElHZ9bHn3LKg)8b%Jpkkz~5)F5wfwfN4?%8noL+Zw$8;17f{}3j`5lO z`R%@}o;=Tp63rtIU!*@6(rGsdN@bELBF$2gG$G4V4*Ol=I6+E>a=DD-sA3vSIn*lU zqB=9L{z#?pJ%=QT=^h+#^6W*FPU!WAh3r?kO6WV(>P>v_uUw`1Gkd`8z9iqq820z} zKq_jrDuM6MS@aTet&bYvS)So27e`43{X;S>SXgKm)hek7{6g)>7Tk{HxyJK+qREI! zG$YS*>WwA}!|wh8uH)hPE{#@)a_ASR*SS*cXZD%>|FQcs+M1`l^~US8mRC9Kx@1`) zHqxlqm`)=cC5UD*dwct=uC9{j89Gnd+CJc+habWbmLx5>r;;>hq0?qC9I$%qI2F%j zYAjdYf1g@wkvz}QI_JvOtE{Z9GaL7)4@W3rnTTI2XWXHK6k zP`;npXZA66UmQb9hvlV3uHU?cv2%2+l2{AzY=Y~Dtgap-&oT}V_L#;o!@+aoZgc~50hvy!n+38RY1M0OZTeq&Tci6`dOYClK5GOGQhkcam zQ}PtGPK7j%xP18v*5veuBc6Kh#rwu!_nH0MVfV!`ES7S$!I`tcy!%}YF+|fTj=O@8 zl9iP;7CQ|#Zr(sBk4GMPlzh%s=(!HsSk|=08iVKi(>Yo6zY zlL^83iw^;CY;EPwbVp~;U-)@_r}tQQu*dKG;D6%Q?)5+W%KM9&1)&5N)*j_=f8p=b zX)PYT{>ppb<)8ofw@H)xC+zrfRxX!`qm(Z{{*Ad@+h1?HKcSR>QST6I4DY}57TX7X zlrZGlFdhwQb{27!Aj@;oq|mf@=J^+B)j$1das)7ZfGmoq3`Tv@X~vyr^S#{bcjr>X z5&r5Ee_d% zZ>%{Q8vF2$bkDuae<_}eQ+D^a$#aeS08|a{Px5Uo##(OQyvog6H_5faQ5G)S*IJqn$UCN>N5V03PdX7V2dyFWXIa(MEYXR*d` z?AURv)?9w?J=RX0Wx3NN%jfhtdCEKQUgp9>kI-q{zrpsuYAXmJKHf2m(VSd7&!yu} z@WXfih=tk;^-`NwwL@=oK&QUQERFcyo8M)L51mTjJAbFNq4xGlCMSrYbT;V8}Z@$H9>p0I}{36=qSYw&Y#+*O) z2x%5mFSl`JfYF9(SU(E6Lbt*+n%-sRwRe+U^D&MAb7|(>9Nmu=cSLU@)|XBrkepvD zm{rEp5rG@BP+z7TR5%2UtFJJpTvNS&$ zIMccL`Q=!D33mU3J!=cO;5m@q94Q@%xv3b!I2?3|(;3=mdcy;x(DJ@{~%c#vi`+`>ZdW!dlDio$GU=2!LXjvi4)Yg1?sL0Ea;PFZ;w-u3TYh zX$jAfT)TFQL>HoqdmGyz0vZc-&R@KUNMm;PcJciZf$uXI4DdY{D;4!xo$lTij$fi$ zF4G?jX*L?nvV_TDmxJDj)nhAITgddLX+&?5&=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81fB;EEK~#9!?EU$(W!aVAhkf>V&bjk_ z^UKW2Dr6PV0J;G*dLWw=hY%@=lY^4NqOE_x5f15Jvi+Mv5oXwywMQQYfkjR z|L}WH-dOjFxVgm$2=Un$6uaLF@!T)_vTpjze$T5+_7`zoU&niY`t`5+-aij>qQCv| z?8Wa;5?N$~#rlZ_za25ApT~$86o4QuZ@l)VvBamoKx}^g3qH{oz4z%Eg;$&5&wB0a zy!Umk`E|bM7kxIL_d0&jYkJw7{36fl3%d9241fsQJOBK5#)upaQGfM^xPS7mKr5&l zPzt1mwgIECzxiGKY)N=@21*f{282Wu8KRd15H9A(K@L)alGwlg8`S^r-zBcAU*L{@ zk*D!Re8(4kEx)Ym`aBNI>s?m_f;EWX5iTT;BZTCD2oO(gvQY@45{QsI6cNJqyJGiR zvDt*5{w^sAMj`7qy`yt`gb(SvHj7@%^p_A{`gxn7L)%_Ir_Ei7?gP9>eB&7N5B~=K zryn7E1!B|(7YUb_$lVFzXb*KcL$obIYg|ha%JcZF-#u*~uY2#$ zy9Oe0GQ$7bTTocy#U)gpP}LA3Vmw6Oe~dhxr@0q`@WWrh_chFxMCXZBi(Zuw1>w#< zYQ2I7SE$y55Z4=Oh=h0EzDaW-zv&Q(&Y=#b&@|Nl&woY#fA?SDKKPXOcYj3jzyC+n|Ls44vcX?n zA&o*9h5qh6$Sm%s9}s^09vFk%9U^w8w150_{K*yW!w0yF894WvGw~PWYd>O4o`G|S zVuZYN06RN)Ef7*5<`q0VAvSGi7!on)BL^Dxr%*Sz<6Yunfp8L`Br&!yIwAi4dmts- zH5(!jQFTlF&F>HdsKyZ+j~nO6WsM*9kymp>>k&s&LIBYQ80Ex&@rN%w0Ci~HlQ*?F zUP44HO3MG{{{?k}GzOMS+@HLMznCHBE82HI!c8v7e)t{yPd~ytNAvDSAO-4hhxYwP z=@j|oA>v>EA+dD0j~}7me}H-WP3qtOlP8a}7wul#Smq@Y@}k}K<~=^7i`Hd+tHuCr_a3pr>^5w@BOo`>zVgGeZQYIC(k)H9-JUt3xD)8A_DI0 zV;)_m*ZM$Qu8Gd2_X!aH;`b1_A!-eKBlQ3Dr{Dv)fRNn zpobPAEqbjnN~=t zzWD~_Kl#@bf9*H$>x%k!f7IRFQxEdyd$*qz(oPaPq)W+X1M(M*U)06HVa{xh1A>EDGb?at7 zm9>5Gb9ph&u_62XVo&Jhi9hjm+9-}=**Hrb8Xz8&lpK}Q4=M7dgs0f8ESUAVtxZ=F*;{xnX2P{g* zqV-(X5tCVN4;0RMq5y3(Y^DgoQ@I)!HE-ICTsnlzDSgS=>Jct3iFnX=F`{5H>LuW@ zV^653V9gEE?%I~NZON>`7{g*!asQ%4E5W2M$?XJd4VkvYkn<lPY?rwn+BeXJ{FC1knD60Xr3xo(C zpVeeW(#sU<#`AFIa8a<+Hw=u!#)hU*SQ8odBCAHwwjPr!v@}%p8FP0Z@C@w^Z%lKt ztUyXZ>jOlwh5Da%O;68GDXS#}$#k+qUi2CC6>qAVhnE%aKCEdy*%+QGm2)5l=8krtxG=m z-~--#>uq9iU$X=K*`bv{Nia%KHjzQD`1wi2?l6$$mn@eD_!wziU|>8ux#VaFA$s~n zPKbiCteNx=2`cjKJCV#9Hc^9>8JX(Sgf%|4RBemV*DkM+X@k4CxZq^@G17Xf*&eMb z3B480H#p&GWW~di!0n^kRBa$cL2fk>_{M(DZ0)#QIa(j7n()lRj}fLl&0G69@1Inh zFWT36OkeICe9<2mW2ER0`TqC5iy&}(`wfiAkWvtWC&Wbg^)X_NrfC{t6l9sjdr$Cz z2!?tL2ebYm4u)W60A-qfb(frE=-TN#=l18R+A%y4pV6QSFf}*%~TW-b< zn~*rqizk2I{UXNj+GvvZ{t2I0O38c~`9J>;{{~AtzvFr>C zxslW^Qn!ISI~l7wpj3_0SJd?mlOnJ?%9->vLTZGN2q_s42Q)5FB#;-?(T-w_1fJlB zB1Oh1%R5?AAov=AAplkFc=-4sE}P>*OAL~AGf&14B|^lGZQ&7vC710-%pRYy(?4Q& zGC>HqT2{E=$h2fl_OiqRCQ1Orwq<&-S%@pUqa4R5ZON%n_^aZfWZ z9jP+dW!wN|U^ZJ&^m0apqH;Bl z9-q=zcbSX_>`i)YNtHXp4Xst2Apv9LGQoY&;EyyRK<4j9>nIuHGHMNX;8U&P0Kt+#?o)9&efqAnc zS33k#&^8s`7YL!Q{q}Cr6BGKTwWg|TVuTRm4fq_!h1wFGMR%%br6D+^PKco}ff!>~ zvnFYSV{CV*!x|qw5s4t3>O-@~PX0}@zTx!rG1KW3gg|M9jtkby8CFLkk){pQE^vFA zky}aK2Ci0)2bT>-33dmX$Fr99D|V+|x>CINIOkp|Cn1DL5Avx$Z~pFiuiyNAGhXF8 zZvK1op3U#H)~FX`Gr!7_2%jNEwm@#=))=goe0ovS_=;h!803oCQsP{Tk&3EmaN;qc zwGaZszNM*FyvI@hTCA_;Bfs9cLR3Hpw7#?d{q!phEtx;7Z8G{L8n%Ey)Xs9onX%Z5@;G2(85y zzBO9%t>c2(+Ve*rExCVD<9yr_aK9>`;0egJvR+w zbIo735rslTM-&#TCDVcCV4MPNDFl~YAnHP7ccAexClK%H#Rv#nUK5IXt5Mv%)Jf;Z}n`I38MFL)kUAyAKl!y{3%$mWCR=O0UGOnp zCs{ska&PlFU&pcKG-MS`e*{OOv)O70!xoXlHJX6-NKB>7CkNH_AV zEA>3L=B5z|0q?#4E{jT zNGDWRdIrF1y`mJSEXozp8%EhKBYl^ZJ4H#&Zgz{2oswxw(<)A8bLReIG>VDc$NRuy zzT#ki4`VDLJ|EG1Iujm&PEdqiCR6UC4Sf4{k4d5E=ZeCncx+vJ$|jI$i3>5Ecwexw zywosajL$%zuR5d@)+OgYXgC;VAa7&x z0mho-dn-c-j`PdM_-u}`4!_cbN>Sx&9)IY-G38G-Bg9DP zxV=$$=IvvYRNNVT2N^wDXB~kMK0bfQ*&<^!9H3&u&fYGMPp`Op`v_wUjZ14sb^yS& zF+^@Mr>b@X%_s6>;{yUHY(nZL{p7+GR&p@5EGy5WtA@f#G9x*iwVcdbmbL%FjN>y; zjGMvt>y9_ye22H*l3ZO};Jim^#dtF1jiUq3P9IbGhoqa)g;rmAXo#zWfn^FhQh z#$U)4`yz)BaPJ^zXV~)I{Z*QHDd}0sw6E!_JG}q6;jvnCG_i~dg;Ijp)Py$eg4$Rz z+arYWc2^I?eAlZkiqTZ&F$-M?(&-edh_>}xl@~eZ(h4WrM}9cWC|pW61=sS z^Wai)J}*()U`_I)FISGsm7uVO+f&Q5uTfH@=j{W^WMo-Fj=Ycf5V2bF@Zm$GR5<5Y z%xBmv!wfZb6a+lFCottMcW%8wZi=MY6cSleZCqR_p3o@}Lf~V|vbiAF1GHA;zE2ac zh(t1@=;>RmORzn`vhw`-DJ11rdp|Ev_n2Q74!-MjDqE zsFXJfhD7=<(Iq-Bs|TE{KVV{Sp{gmv(GFF8i4vNg-XRl*7(C~z$cLvDtJ*Wj6@$Fs z&FK!S*@~U%n7hXrnKgtMsG5k;BJJK?z9Td82~iIpA|XVS?iPO(C=t-^lzu+Kt2|vd zom`dZ+_4+P#JWv9tVv%JNio{E(ERDAYaY*<&pnr)nfWe?;%kfcJUxUEUuleyb&Gw{ z(>%Pau}1QZJ@d-gH#_ZZWoPOB0t|)Su!*l2fhS0@{qTi#fZa zf=u>N!eUiUF7ME@n&=y-8iqxR0S-o%5G~79Aha<-#AeVHI0=kSi+7l-j$jzcVCy=G z?quD>Kb!cY4c9piA<~Jdm7w)8xn)nwK#>qNAFgAVQBU#1xBC3-k>tbEIvL$-j?Z+Z zy!T((Li;>J2=SG~83$v_q^B4aD&;1mz(_&WMD|CTca91kUNtxu`Q~u}0<04B^W;Yp zT%v9Wg_dA*Nx&zrQZ$^_AF_65xO&X0KA@jx+`e;%`=5S7-kVa&3nCGfc^1n{ns%>C z@TEl)fW>^yr)M7!Xi&q3sG77$eSu$T%%o+d?=xGrAOd~8Pi`bWmRM`p9a)5E$xX(j zr|D%9qa?01oSt7WnF1lQtOJFW+d`+z$ZOCI~W0Xj4RadU+L;B8d-|jIiG(Y)tP5B&l@5{z#CitGMqyGAiO?+al{iS}d zR;hG!($lQ!v^(w$G+F_{F&X42Dd=a4UZ%E-Br}psOM-WZ=ny7DcQI6q;6lyG`h7yk zS-BHLfSxS?NhD&e;r6XNeEjK$WWxbbImX!$m*pkzfBG(iY{alXrdRZ6nufE>Q|LFS z=xF8&Wqaseo7@!RiL$2kkr)LMMXvj--D6JHAJWq!rup0StYFyFXstlB%$mp43m6Zl zC@E-Mq-P~cUB?l1cVeuYz$jN3ExJm%I!NPlXE6Ry0?MpQU?U29k|62Sb3XrQ_jcL#742EQu@ck4zUx->frNq-fg{g-)l7 z6sQ|>8-Z2jJA~?bvvEF>N%6#Y-mcKYa1W<*~5~z4-2l= zj>~1so&6PcE3q;sv^9%HQr8WmzNM`ih>>;c$gKjMF`qA}s+!DN2E!f-fs}^2-eE7# zh;7X()EJvRVf-;h`u!faj^E()^qeJYj4Y5wQ~4P|H5A!|z2Pp8R+l8LVucg|-HT{? z_~;O(zCrVk2;sP>KJK0=#OP^!iI#nY?DUwUW+0Dn#S$SUA*MXUX8+r`_JvI}`ZxA6 ze)g#3WbSzTP_r{g8nc__b-l{OmO_ItAUXgdCMx|#U~p9El-2J}2y0S&;(W@(+&r}= zJ8w~zJ-FNtrSmj(Z-K!O;d@sYDdgTyn+!G{H|RTOzf z4JRGK!ua1JKiBhIWtE*9a-eWC3GXw-v3w-buC0 z(9%-5B}!_%7epzTHxDWDH}O%TyJThER9KS&>CJFHc7Q>bPY@}{mNLQE#}mWR#9kXv zNWnNAhbk>hO$;r_;)x)8JOAB(T5YhkPBS{jEeu^X0n-r{YZurb8NPX3@Z(QQ+-C&j zUs{51Jel&tU;hDRRg+uG)ndtT*vGYw-eANaf19hzb1vp9w1ny2J|cL^vScux&^9fv zTQ~8G@VZ`iY!;;y38R1eC}*#qhZq;`=}-7xAYl+9Vq)+kYNXRn~h zEz%flo|74YF_!yR3l_^hx26+Dv{dDs2M--`Z4Qr zNv=o47@0R$WX*(q_OCU-JA`OsEM0DsstF8p&9t9f!3_oE=A0?n)th?-z5@q3x`*qC zhc~5WGxMZ}(E60~ks@XEMR&p&l^)hN4sx7Nf)eZI#T)OJW*ACaj&I%WKF4zyuM>Hj zi7om)4nxAYwSJPt>)h+t|NgQlAp+PLY9@JVFlDsn_Ku~gYvzsO^sHuHd3siIGHd8% zii07HGmj}?uiqyMg_NqJfD5ElNM)#E$-z!!pffI)4VR5%)El!m@br86v-KuVJ^;L{ z$ci4tU_@PyI6XaMe}9+EW&{>olpk|z@Lg)R;AH&)ZK&w!F%jQEqu^tU4=qASTxi+p z-6j%o&hn^!pGAAlqPYMOkwQVRiP_M_jL$4q7bu%ZW(2o)5-{Ssn6o=jXkEv)mFe_d zu3C0_>Iqf3Co=c3BOu9Bg;gW&`VkAO)*i75u*xr`vbI6^zw{VS#vtCs2YPbk-mB{SuXe{ zmAcBbBU@`342R5SR~#N35pk^BIqPuqx6irjn8!_hf$JMbO^4SoZi%|+T6d4Dd=}DQr0b@ zunCRolANoKJh(qJC?&A!Nu{c$ORA>0MG$;UTrri3zqCqhW@{unS~BTr9-Tjb-Tg&^ z?=?qZ1h>ZtF#YHPK0Nbe3d$ySx=iU=?Tt*r`c;cklG9bn$}5>zq-|ZNW8UP%7-^d} zotjd0neeph^@^O^M&rCE-he7Me)-m|2x)>vmmrkgPTMbXPEQ__7ej&;WV(-!6`7i{ zSG>i*PEitqi&!Oy(X*4^#>z3DUU;O43~VF>kE20~94j*FaJ4lgvYPvs@3C0#vpe0V z$nz~PN{~o`^R-XVG|w8g5MZ@rS$U*PC(dp^;-f%vO$E_1X=gnVzuXu`3HF9&n-Glg z8UU!aX8_6)&C`l&}_k0uhOu@CUntSwh88O17uXt+;l@t8QBhRw(v_8_f4Z$zX zLeEOx*v*gv`Wlu^?2>+|Vr^YEJbZkH5R&mQM{A9>=7}1WEom@Dj8ON+-_E znF&5+&^J))W@w|iefu`&XBQkC9Z>5f^Xi|{U%_zBtSy;6I^*{A8%!n>lGA5#>t~cF%eEGs^G@M-zz=KKbjy^63Tq{IMgt19q}^xI6kDJv}0XNR&W- z$=U2tC#Idoh8})1aK73Lj@SvMUT)xE@p#Qg$TRG#yN+j6cJmES_T zp{vo@0IIG#UGD5yZcj5ZBR^Atrd^sV&jf5F>S~sGXpnbybn^ z`H9$@Bg-?Iwqca*Qr3#n&FGl{xtb)H(+8pysLpRUGDixH5RSvKL2FBJk@H2%y7AoE zvE)V)qCrc`$nG)94k+CmqsA=e3ntTXf|Yr3Ty)cj1u)42C+h(hiXEnk|;_+Nx!q{;dGQul)NKtDKj zRPMzObdV`_2AW~6IGrb|g*6KA1HDXBtxNJe!&=M3%bGzh$xI*<1|j4VSGWmCLrg(r z1dOtn=m@^1_J&{+EP0K+ym&NCL%&y`q`+uL?Nai$roYWN7zzxcVvk z*;^QLtcD-F*=JsQ@=j181lTR!L<@ryhQ8iM~*MszUuCJ?{* zXWhc03hWNeR=zX+Ja9T|ne;RvMpkvodT(5)oxZ+yv$~%>Pss9S(El<_>7|CzHVsYd z$nqTBeM{3cNGYF)J%abo^cnEZcLgiYiYh$uI`5wenCrSmYtz*RZ+69wqWqe&oieuU z_9eM6s1R5=zjZlYb!>K}+P^$w8e$Sjo2?z*Lv8~yc=9|WBB<&WI*TZoPJ)NCHOhWO z-&)4`VV8(Yi(D(gP^nF+c(N`Z2XR=j1fw@Zf-=Gl~eD zE?Rn-BGZZNCj>NY#2SIs60Jl68g4AjNQxI$wdZ{4*d1sxbFD$OdCm2`K7V{h&-*9F zOAX`S{(t`|KlvTQZ)%qF1wZ`l-{SoA6z?26 z`$v>lXH-Ezbex}_qjO81W#n1DW$ZfVAVj1#*eogP)m6#m#W_XRN860ysE;Xz+`D_s z&wuta%BID&9%VF2q#gC!-}w&KJbNo4LLpmzcyEWRt1J4$G5`7}=LkFCb%v5DbNgBJ zWgpN^3rS&=Pfz$)MoDCm%5@8&=CT#%ju{MhL^*x88oPVMrmkT$KFt z|LGHSsA**%U+j~;BKdYxK;(RUB|TLsU^-Cvknr@Lc4!GzQ*&`SqZLcq#_`eYXXGX$ z?_Xe?plJ*0+H%5uWN*YMAHhZj^TsZ>=}(dR#w$=35!1#3*QK9v`#-iNt!>ki7a2sb zvS7EkORmPLx~nREnl-RgKI&OENUcZNWiadC7e#O7| zbx$9C@XM!hhEn1l;N zO^ga9O((`JXzGf^V$Q+A{!16{y!3o}QPWmuG_l9q$J4~oizyd$6Y&cjJtWnS^IX7U z1O2|L+q7J*nND|~DOGrRtFgrbljnTn-Zub2+cwM>D~5v}<+{XJ!)mq0dB^_VK3c17 zaZ?CBxjb4?mlYudY_?H74+yzI6jJg0-u^CUXBX`3?oh4QG%nB|^iWb^dTH0m@*HFB zYc(NJO3~{N7)VK=_sT|*9`wt9znP#xrpT>i+^<+POD28E&}fwRxX@sAMjacKdgqh1Rse zBb3HUN!vQkuP!L^f^WS2E9A!W)Av5WWCg$atKa6`fBz@US4*m@A~ywDKZlU|E@Zi7 zKAZC!zx`Kv``(?`JTBvQqQA(IG?OBY6WrRd2!;rsVU=N^Kv_)`BYL}geDL61cE@K3 zS#K-Nwj3ZLjc?J6IUMfeJyfmV!jBu7o15B6q5I*+(4~AzX)wfX<(`ycD}rEDDzR1a z`g2A1-f?!kRs7rJNu)AJLfX(=O%yh9j=IuRfnb^+)AzdwlGwxS>XN~rkG1Bdtcehz zY&`uu)r2fUQd@r-8rgsmtExk{u2G} zZI7y|uvx~cTrwODxO?|5NXcS$0XpYse~+RlaKRIODqB1`Jz+fFVLIKxwIy%7;n~^S zXFMA5yY?{95UvafOoQV?2nMK>WxjLN9n z$jPkXaB31aM_VSnJ)D_QiW(o1>YtBo_c;)8iM;1Km=ejOtA@Ry*=o&hgvMjHGlm$D zQg1)wX+j;FfI7muEYVugD>A$f$=$tC+aO5H;B_6yOhn#TWKsgsbn=`nLfMqii|Ka} zFw&-~x^;zfp7FH*T-wIXVU$42uI?gKj0V%~iud8#ZQ7hrHj3BU+(L|$b)d*pr`;>Q z7*y)u)@}BWj`1A>c2kY_qH+7yak?p=x_3VBBHp_9c85v{l#<-Kb9ei@$z;s&ty}3c zoI`X<7f;CRbZ*#JJ%mX8@{Y!-r^VjLpgSIvRf5?fAvJ9%i71T88QLBP#cfJAM+k-U zHRshQw4ug_RNqafCu@~pXP`Nmw^%JW7}>-;ZCZ$3DXfqX?Q<7Pk`lU(VvOnNCPEUU zr)rZ>f|ecJ+eJJ+T<_UFq?5J@D?(T?FgvuNqHa97)kvKT^r|`|*F$ohvzX5rk4H(| z;T0BP)dpgH!J~yh8pr-f(zlXz6F6VA+}TM~mD&aRnR>0@T8fkeOqx`$XH+jWjE~=c zpR7NiELW^nYZj}DK`-Os!xKi+DdSDf8M@q}`Dh15NAD_N8k z{XAnan{oQ!gnTe!FfJ&on&F_&XguZMV1FA#s~2#zz79q~H#t^I`dLyZ_aSLFMM@eU z85NqfpL4SQh@KvCxoA1sxyw-ZuyU~NjM}#o7R@<|oEUOW<_*V_wAlNZqOgjKWlL3; ztla~g7wq)!qGX1^<6VW+*)t6{V@xN^W|OrxLn_5;T~Xv&m$kkw>e-B8uC9-s&_WCt zRWPehurf!Wu_{r+1+mLA3u@QWRwX@(^Sw9v+xqdc zE0ukC)udRYqkHr-^#p45B7@nwgs-`5UTPTiddZL9{TZ|QoMO;py!^BWCBPeB;~SV}F1DRj>QCMhKB00zrN;EMcPr2V=|a9m^EG!CV%v&Lye#-kzU=NI$}d!26PhMsLq0lX4j{eARkor4gJ>>*N0WEYbp z-CH0E#@QYr!pZEE$#?|BCt+sN*EKFJ>Z%P}5$A{?I?2Hx@UTcHhkdk$+_~VaP{NT+2{Y-Az#N(c#?Rp4?2(!`= zB1{MRnfU5;Y~)4Yz)KCo*o>Xd$NRj)X4mhx);`e+?8_}F>T027%Wr?@8+h-j8pl8V zgHK=EFt%JCk;rG$zNVikoZnEx141-h)bFusmdU*cC-lt(72)>L0d|v9ASJ7u-^k&2 zja*`)I=hf|#i~t8BSj|BQlO+Ele-i~FfbX7PZVlMi7zQKf@@IXT5@oMMBQ98&N(7- zo1D8@H@>NG^AQqNHXy<#08X)E>p{nj>}=;s(S44#ES6=e;psBmAtqEvh{UoLB8eEZ zKJdXw#j;MU*l!uMp|vXHshb=v*lQp`(@Q?)s!u zG;NLdWs>kgqonFY(ISI>kIRd5%CaILJ1PrADexgs)t+S)&^VM7ys>MTm6{JuO3GG} z7dyPQvm%Is(|OAueY_&X$g=YEbH(1!Y~^-xBYAT#d%`F-b5+-&W0h*45iHpxy(gO45|1t#;Hj&nQZcPo+dk)7LE~LhknNFzK;V7NxC-atNnYy?F%vO%VN-md<-C7@aWjQ*&jrR>wC->qvfBP?Syub6xhS7+efBx@2A%sMo80{RqvQcbGD1C^D z|KFid5g2EC>VhF^j30%{*t&)_%)4E6%lBQCoB}!>R^vO87&PtnSF`v&cMx%8q9O`H3 z&y72!CA3YQVo3}}NW_+gkz#~Vu9);SjSDCd2(AXH@f%Gq?UE*L6!d%f){Rm?FNY?0 zZtrG9BHp*mR;ftpY+hrBp2BE^Pwr)IBxUDn0bHyczx&>Tb?uoBG{5#npK1Ta&8atK zwIQ&j*WBEoUb=STD-?8BRmFO}W@kF({wE)@T2)j{LvC}by5i0ocUdpzJb3hoUaug= z)E!7#%V;>F-ybl$IA^(DC2dh3kV0atWi%S|@Z%2lvB0C{Zvk9pheFV6H2kaUJA48R#dj*tj)}ZACz%wAnUgdHm=h`v(U|si>OJ`TViVheYbSB8t>wBLun<+Sv6B@7Tp% z(A{)gD-i>AxkPA7<66$wAERAPKigq6-GO*5%KUiNa5%P>F`Fpdh=o*BV`ll=Ze-vE|x9B zLNVwzxX;Cv+KfEUw{4A&Z@>9mS7vv2%B?$hwh6hXYcGa_7l+!ryVEaOLGbgzw3`K? zl|YHK7^F-S*6((p#j0Xx9a@eM%7RiIJtGpDHCE?1FNvM*?7TW9(*;J4(+*rHDwlS( zzL8xGd1{)n$yy7c2)<4JytrPZMhR9Ona{_F@f$5Cfzlc4Rf%wd%&5))1X4(Z5M7~B zU{Rf-M21y4J_>qyS|FQEb;G)CTxy2~DWGoL^-dgwLdS^FmYu;JVk}wBN`@h9*NT!! zs+0&9%a*;N;e6p(m7cvp!{H=H8AJ4IS{G=2LhVL9P3;2fCOlC_EP!2FW3O=4`rqTRY5A|(!u60BUng*9cEvtIU*LUJ_i z6GTRBm#kK6Mx%s6N&$;9@X=|_y~CWIRV*vd=|UlOMwT0h0pU^{Azd=2Zyx3JGRcFB zl>ECnMEA@Vm1j|U?w{95D7(vc?+y*OCYDL(Zf%Y86~^lshJdCi`S~XgDVv7F<0EpV z_~7Rsa(w#@b`I*VdL4h^BQug)6HDzvC%vNRS;cJKQe>KbzsGFtIX%51Qyw8CMV@hZ zcz{x(qsG)MYsb0~^iUMW(s<9bpPIe95ZE7CgoK@eq3!BFlAD$4LA(bo9opC}nQ)`< zmrjBNv$h@5l$#A;ppt791k>r1)3YTdNUoZa z$vqUpu&xFy>c}?^vaTCz!DM8(yu3tb#kQ&B!>fj?mE(A7>1B%jk?H!JZ?e~dfW)ZC zs)kh^*c)ozIm|g68-DU>`P^nOn++raWg94)ggjm>9Uq_7ys>M!caSGod;5k2o4=^| z>^0$9!LR@J@9?WXbX_oOAVz-UH-8Ib4O;#ALVu+c^sFSe5~C%DW5cM>#NZj{0UuNF zoN0k;8;1QMxs{BD$w%I>PzU`SAu7tIp{&5D3@Os-W0c@><*~{!DAbk;zN(WDcI}e% zj&qS!)iTs3wGHdgs7?G*Hi5P)6iN$i)8cEh=pse0U@#c6ST5O_PE%EjcjQ@yl#1G| zP*NjAwq^515^t++1!oJ#!N_z8Us%?jMHy*Z!R@K(0{PV3GLYh-%Xvw*+ox^=jSET9 zqx9?#4P~3M;6|k^cnE^B(e%ZNQEyDuhAl8L$`wC&v(HZ+2tGc0@do@fMBTW+`;RLg zU3IZVeof)ITscBh@;r9@E3M>BjfF9WPd@q(r8As&jHi<{kuG43rm8DMjLha&Os2cU z5GYqG^8NrRpsq^l)-xOqutu|9uW4FGp66uNa(;4x(1y`yh}Md>b!_Mb-Z>(IqR6Q0 znzF3e-P?Pu+KksW43YRyF{Ui^#{b7RXk(JkkHBcbbXc%E8Kz<^??LLVHc=!cI(x-6 z^lfa$PTz1cZkdk0w;)P`+S_@ofx(KHAxXo6BSB zTZd4JN3)hfX+~LkhDyL2yBY62D!E!ae2nxmxkZc8g+^vgM)Wg!{R}BGj83uLy!4EF zsR7T)yiJW@USlqobE?und*Avl(_HcMkM6Tv%)uyj#ygyzo|37IJ8#_LaX&qLsl|D9aLMGJ00A zKQvt@pmajCE~b`VE}-$as0l)nTY>kHW$AGN_J*m4U+n1Rc~=*`E^7!aJ_H6tq)Ll6 zEocR?#n%gb6lmLHSzqD8nsI&%U6GIXEtQ+oGdtV5>|8~f*3-BZ&RdikkXemUkXb{F zfu;>qwZkew+bVP?%POVd&Q8X(uals1ofhQ0^jmR*)cQd3a4z}gAP{_{b!>xZL_(tO z>?8wwo$>TZvN4bst)5phj5~MkFdPn%Lh_yO|A2$r=UiOQfJo8H**`d9d49st@h#l$ zF8%SCBFi{FIzmfBz+>_pZ44p=s@5?ak9p^vcj%8s^oyMH^9$bk)~{eR)K0K-u*2I` zg*KY=(-X$KhwM&A)OEw4*JHf9&lgOsdd4V1NPPY#j|kDCWMohXOvn7aTBk-R_YMnc zpJX&GhSoU(8ahp*bn*xqmxKeHm!LCT+ak5)c#?Wo`w;0_1vaR!f9X+>wf=ZMazZR0XMEep%tfoSj}stpbF?BMBkp47~GP ztu7FHP0#G4&avLpwk_5gR&IrKiq>6HH4$e9^a}7HB|uG3WLD9(g2imMg@7W7G5qFU z#<~go_|r9u%5(1^=Ud0c7HJx00U;Fg%0oL zytBK<-cu}C?;L)22V=|=ises3w%)lX=;Zr1>VfaR`Q|gG1laH{)F*v#fD?RIYFj1W!<2J zVqFW)mo0DYTXds;g%gS$ErQFJnbCvua*>RafY-yt6)61Gcmhu&46IfKf z>zN%{UpnrWnz#2H_sk4q2gqn~ts@Fa8ztHp)=foK*IVh)EX%0Z!DRKiSR?9gjkI&JW;oHCREiTT_&_y4&oY6+b zU{DZZY1zuXBYw+F?F|dV2U^m&HFdkDsSGCTqoibh zHKVEkN(eo`WQdUL6oz}3oq zX+{B`1FpTgJmA(L&L~n=NlO7MxE)(+=XG_S89sSZ|TMzTNBoXlEOw!#NT|S>Zpm##B8gFM+iF#9=-Ot5#7WXNxlL6~P!_2yAjwn`ITj*aV<6JE zlENlUrF9*)f(_BP_yCvdoU1bNpmb+MH|{jG8t9D?LejWM-FW8fhzpVL6%M5hnGwWT zU}R41Vyf*R_0A9!TQ)9Tsb~la*BY$R1h?XHF{5b%d7hEwmbMLCu3XoAQf?{kMMng* zowCWjWcaZXt~Vu(z4lJ==F znz~%`m;ZymNq;b)$aB8AT5@?gLn_JM{yxzMw9))}`Rm)Rn$~7tYOL^?BLdNPNdd)8 z6CLD=y@ADrLlBzF_C4n914ed)6&W$sxM-8WfPit&5Tc;01A{^%(MS;x!P7R5C={7B zTbx}=fpZF@Gm1iCZO*D{P{C1TdB>!UI2VY)6A&y*nDkR$aMM$iO`xo5)>X^0)qHYM zr9R<4;-AvOx|ZMR@UrN;jJW1v4NdDQbduIdb?1Vv#9}*N8-v);$&;}uLeRwMLHe$< zYGg3z6GI}Ej*3pH{06ZplJZ1v?dPm2&!X})E-=U?F`JOZ3y3w4rF!z(^U+yK^nKZl zvtG$CHXTBxl$<<%L|J?8+_{BTnzpHuuiH8XqcNkT21dDBQkD%z$H$cAn#E$yXguvm zY?`{RKuEI8P}en!#T;WZijI1+p_arL@!qkRFBpu*6!|Y!AM(r)A}Nf;03kIuiBfNo zm`(kFQG2Lb62cM@4a@eN^Yzau%#^V?+&-U;06?mt5P$@wk%Km8GQFzgzJNLI@g%{nOzR;?q_@M}N#Ekd>A{PL1VCui*M z?~xnB>B$K}2#mJmnW1qGZ4FuoW{Wja1c-v)`73{&JGT$MoF}m<@Cgn0fK&!81t;@1 z)nKF9DGsTfA$XY8k7z=PYfDzEIs4f?gcMYjPx?pVnoa>p-%6Q`PcPQ&_C4c44=E!~ zK&C{3X;sHZk{T@)O;h8%LIh8**Gst*<(Mxkv{qzBk!PAgu8DL1>YcAPn*leZd0^Xp zNQ!I5tsoUNIbWx~dQzo+dfro(Z6^{f(MIE%iVy{^@vPQsisgcxooU+SI*HRwm!;GP z@FqZ$ejib2qJV(l z=lb<}@-648M)6@*d6EdSYJ3UFVpjl3@DCiYm@M-bviUFC?HvuI)!z_~LDWA~G zk{%N-V_BWBZqJhdM3ls}WqdG3#H1Xu5joo|h}K6|rK7Nl+j|49=1cTyp5#ok45bu# zNQ&OI3yI$(B`VKYmr1-}+rQ9Sj8@cj65Nh4#VND3qkiSKh1V-(vtScJ&_5aLZ5CI6 z)_bb<3dNL&?vj)iYf|5DVxV!6whasl#qq%&=NFgk>`b>YRow>87A>nL(6^G~sojbi zXeG8P=o^ZNQXoPP+zf1v5~;c5qgkp87o@z#oBKHzOGnkAZ$3muh2q{}!PUy~;Ic_T z#TRWD^?y_vpiLIk=C&U=2>IS5u_L1CnNhwke zqjf1rw??uv%n~iUi*KS#Xp_~VldKWjj8v8v+bwT{5%e-eW>R1*qUUthP}V7r@XB`_ zlaB10dl~PaR9vk+7qb)fmu9Bq)S+rY4p z%oi)B)19pn$;HYsUpsD1ZQ_1KI9s>`-QGyjKB0{T$&EsSUlG-SUM4vh89qGq9c?AC zXP1@dY~i;(4SQX_TPZlmdJbzNeuB{Mo{!*=2az_uu9BRC*zj#P%= zYP@TRGWET70jkE)%ha|&NN##r-vH2*6l5y0SXF#*DX2dOP*b%D&UHRA=^3>4i0B9; z1wl_liw<>*kegAe7F4N+-NxN&eWWTKjZeftV$w4nkB2laak!*_agh>p8wT%uU30N? zsn|$tbgbB_yl+M{Q)teKC<0m1!|G&NR<-BH57yfrCRz!4h2n5*w$FZlWN<#RtQ>V4 zpHOss(Rlql#!r62{YNKUUR^TT+vDSpKH>cAoXKF!gHIo@UX>ib@dmS=bo-L@>4^>;XbVqHj=A zv1$|hH4g(uxdEvWQXrM4Y6ByiGTupoG9-ki>mS!Rk0zjW1_-pt@oh!$Ey7r;)^~FL zY4JNBi6L%fZJv4 z>qc~1DT#ItupI~ysHz67HG___FC|;P(jZs7xt}p#C*gvgmH4hWYGV{JCXQ2X6jt{j zIseL)x`lxheD7|Lz2UXsMT~Gbw*2P3As?UB%-4=Zmn?nJcHDSgS>1!o3}Vy zI8Ns+!$K!X93?oOSOz!BKD~D+0S?2}s!6+3vmzf%w&KQFW{71?)22o_s#5@2l%C6# zV~{B{EmD~-21%J~r8AnULdu3gW{8=jY$ClZDd{<%cI=HdYg(rrG9(p3xR*}ybDu(l z!`ME9Y#j-QO>FkI4Kwm2ArLp zp|$4d=m4SEHka9oy^;FvH7<~A*=;7*pPLxBU42Q6TLcZ*Ht5_;<7PISHpLk?4Wsq3 z>-efUU$peIj9Vg!P9$-xXUA(M_yk!mXH{10@9mT4mc?Sua56;+@UCTDRg~o#AvIZM z2{F>^5Ae=Y^m^A4_T`$@s$w)Aq4n!G0r~uPk>EvCDtX!x6_=;lI7N#DG3#C`n;fS!fpArKrc3WPN1%-~&1kQ)IuLESjK zYf=VY>BPeAzCS(AfNL9yB1Z^GFH1(8nLc@*ae8{TMUY}lNxe;vaG^+DqvExktE8)x z6iJ{hHy!Nlk`-(SnVa>ziBC5DOCs>@gOc1xZcQz|12v>gO3-`5>l%;{A{X;tKtAV# z4?f_>KmIX)@9+H`-v8Opxc~4m!=g_y>~V7XnD2h?hs;kNGFvXWT+9(M;GD!5sOrdH z{!72bdw=rp**Q9%9x(J6Z+iAm{Cr<#RP5gGS1C#MT47ie8Tc9e`5q4JVJe?SPXYonG*N%w|^vT^A& z(bpPIg-x{xK18Ch80l%7iYP512$bqt@!r^^H<<=yGIj@n+f%`(m(8o68WARiU^>i^ zS|egwgi>`KVY_wWH{=xnlFg0qpWJQG8Ekc>g^6`t2NVUkKtg*;qfu^)e1u41nSKSz$Kmpxs@^@$n(+)v9Y0W5_bQJsQ87A&|H@aY6XBn?<`9RzDFnDmp9ML?rfBo`hb)z(Ljo1!fr(Pkq|kQUBo^{w6vt0KR4 z%Q7AHfa}hwTO~qmsOyF-&yh;gG%e0wt0OM!z@u5qAeZbG5owYyzd6y83zRDFw6#Qc z!D>}9?GHL;amsZhI=)2o#4~a>tJ>4J$hfCS6}J+cOy@?7OnQoM9VcDei)Bk;(@Cop40`nPoKHS^z#Dh( zP?u}gRh=3h#-vWyI!ADh#caiRcf#)e{;Owczr-=>Y2G~S(Nms9c|kuPGb*yJYtuRh z-jnAAhl4jcEdy80r&NBD{08(u`+pgCYm9iM&Q98qS6Q?&l zsp#mt_>dUBLMpuT?Dit-M)UKNifK=?Gmz-$5YlejrKQs^U{qoeFRPlJe!-i!54gNM zr(7p-h{E0wLyOSb>y~G&kEre$Se;H5x(!6eK(!?_!cJfF{k#37=Ga$!d{(n4%dPY% zA<^9b=%Xcc&sPeV_WMZ0_Vjwucx_bbDLL5PWj8Ax!>V}!t(jCI@aH~;qE;qAM}U!_f8l;ExXoZW$;X(CpQFsc(8h>>z#GAjd< zL4gYnPe~hBNRfz!tq)A|w~^UNmscQ(Evv|~j$OTWpll(xn)PZ$o@E%>p)*2kjX^1a z2&olvj0p)_R)KM0!8gRHnU}EBH#c^>$i=+kPagOelj?$JyRwAja3r~RkRzl*bSH%0 z2vvG++YcT>ryvkXDa(IhRE+fzkPHJmR4kLQ8uAZ%lSRIBc~OH2Xvpr6yYB=*+p z^`5xANbK~vB2mQ77)6)6k=J~~7;sUrY6Fx0wfs$CCAW7{Ey$hSj8*M;@I2PjDKoza4};ko0r*|op=!{6Y}e1Xk!T9*(J*E+1taBYLla*86uxt8^6-7!{^ zbF8GKsvGuqzuFvzR)X6*8OIZwD(jk-S$V;ZK87F=A=Pvr76uDd`*RF@S`^&-1mmRD4*-}V(riNShq2}hOP`rIua58IYx;mAomM)KH4R0Uj^t)3}zC)rVB=iZIKW4EH!b9#OZB z;A+;Z1>@0>#(}-DnQyYfNu zby^qD!sC6QXDt$*|Dd#NUSAvRak&dOf5RoX=Z!1{$L! zMqUTQH+8Hw&!qLS)A$WEJ{31@#;W#IZDhC8XiC7umO-vT+0-o3d;0xe3J`;%EL~UZlqNjW5PX{?dOGn0r6N)p zOsJ7WqL;+rc)W-#%FYibJ~7czCK~-H3m9YB8whp=ihi%x(fB=0(~#K&fNV~#1gA=Z zb4m6;IuMdxFC}Cpfx24LlnpMnOa?jDNa|{hG8v645olD`byX@u+c?Uy;_&c*^JSvC zBqQkh13tBH#~7)7WLYN0z;uwBW3FqDv~f%O*dSClhtYx`yxHgRh2W}6gb`4en zx$ZNOcX0;xcE-$0hw~BBN$Mcd#;3E?nQ7fT>q8uID0rI1M`sI8b? zT`?RDX?)^lU9KGW4)Wx}$>+_PAo|GpvP}YS653YMxA6XDgH}m~CzT2(S8}5+C`ffM zdqczRJwuFw2bT>e^M+qJ?jPYae-nH|`^f`@ zG@W5U_G{lJEN6tW#h;uaRE|0v;~!swl;}5)@sCc4ZHw&Xh@wybKmMIBuaceX7G1j& zOXGav`jEczV(A$76jr7tnr90~SvwAgful(uV^yckqzJX9HyBg533Kmfl1W#@A36?` z?p%VT076F_j|>V+>l}6My8@=f)NOr4E4f8j;9AN*vj(LUSBo;W6407u73kX}PJFhE z{OqKBf+Di%@qJ_JC~WF*G|UZ3XZR8<8r;-h#%hSRx#=sIX6hAU{1 z`n;#&Ey2#HpsFhB){z;D79O4T(sS!BqN>)Uz8U=_Ffp~f|G30;B6UxDGn-_cmV!5S zvs4Ej!DvlYw?s1D>-zM4|89Tl3i_}?uu|L>Zj{~L-m%*NJsH0M`PsJd62lP4K|#1$ zK#1r!j!=7JgigH?!n#2Y(@7u(1uU;n(=kE{)c!8QYGl8Uu$I`?=;M7b23!lme5nc# z+ndvZL9Y1j?LHr!RV*sMZ4I2MB#rZUk#wQHu`B841=?8F?F=b$+I53eDzRW=WWII` zGTY(t$<^@zwCxa_uEdp?x*cgFSg%Wj(rBf~GP})3G%jwH$v16wLriMtN=iokoK;z) zML>qY!}FG(op{PNm8~i%s5@T7(>aX7O70zG?DsuV6-cF7E?4Q)j)Kq?2pMa+ny<-o zOY{z{lbiF&MZ;tu7-i}DoJ)%~dWX*QuC^jlbIFAzr&pPpr3J#FaAdy!rf}zwtEG8i{Y;Mm!~@{#6d6QZ2Dmu&N`&Tyb|dV>&RL z&Rae{Z+LXEW?p%A`VvWol!m%)k-|VsR1GO5{XCVd-r2DzDYriA&0r9&Cm{G1ghVPy zzsQL(2?JcCKdHmerc+T;5*M8=Y??r$6`2;C%}S!m`1xsIR$ikmH#JvpZZZ=YgA&fS{!b?UiC^3aR^guFhd zpJmi7T&~(}L6X&yy73H(jm!A#oNN%TSKW)hAV*((t&9S|g~0vOCDv%NEF-syVWAPi z(a!>B^T4m%DX5x?5Io?CA<~8=0#B|ai@IVo8bR>*wx!Ui7^rTOuyY{sa(qbbbrBF; zjgYeA4@I)fP?l9kvyj_GwMleEkvcU&xAVtM&$`H>Z20+EppA7(`aLzPg4BVj?bx>) zNztB-SQTi4#J3eOM#@&=+cnzQ6lZk#f`hT4sUultxmvYk(y}|!lx2k!g2o4Qca4ii z(liNf*0SR}kzzULJVr?#UY1;~18?qU^fN{40+Z>K#+`He_%V~6U2=P!E#KZtw`g7W zES-z(|$MWtdC z6nVzcG)E9=gTg2v24t)`9(#rc_D549lGVD#1vp6BtZcrLZ(e(!$h^#rcS9v{^E>(x9c}eP2&?9^k5dbDpQxG=e!1zx5;IE zc-gQ!FboPs*+SE_6nRR7uIkkNsR+|=FE82I z*&!;kz31-s2_f~g2r(w9&o=OQ=4f2tcw)Pzlorz%3M09-W3iq48W1QgQ>kyfPU3yu z@#oesv=S6n;My7^BPK#!MvA;(&>PT;0@s#Xog<^+56{hKZTU^zHw_ET-91Gn0}@A(7dRKNHg!i5r1<60+_OJ01lQ1Z?vYlKHbmC7 zXQ!{|=L%$Mk|{(?DuCT?o*9MgkUXn3t2(f%14ecVAX2e6%4l50$F!=C_Og<79gs4)rW^Hl=OagB3sK;F;zZr*JER$5y`XA66Kk$rNRa~T zvT7Lgi|1}YbsM&lJ-=`T-z#(?`&x{rAA}&1>qurZVhE`oTEs3BuaF|5JELfQq-Rr$ z-$`*qKO3USd31ikv}qaj^6O9SP^k2sBn1&6x&_p1U8WEM-US4T5J9U%cdp8kqUdc^ zEE4r1Vzt7z6%S{D_fH&U>z`_1e`8L%KYf4?PAhf?nuA_VKg-d&0HJWM!uhbJxW@=p z8xc}swPm?lV{Jxm2UK3LsvNnIT&^RTsu}l_TFccsvO6?g$tf6VXquWfruvn$g=24! zIzD;t>E${14kd?U&nH)1rK1(Bn+1z<#s26HS|vr1yy$gI407Jw&r^+f z2r0*c!stkhDel{ddZ+74^)N3wl_PLEZ#kaY?Hs;nywot-wxwwr{wxeBB}Gv@@el$! zp(G&^LxXb_trKLKN(~>oJ$FO1kP-^hrzZxKO~6Y{S+42#itPsR^fQ-Ia5Og5O@j}C z(9|Ft|M(yOU+~`Z_x|4BO-xlOXq%R@EXneU-}}A)nRnj)2K~VZZ8PfijG{keURhcn zJ~J~br9g?KN;2&mavKP~B}k16NlK^4Y-%{uEuOaz@~)4b?24+=ZjMZ)x3vo#jx$bX zCF>?)gkzXnR&~mm6uh<*BL7u%q@NF_0A#kCh_DhHp zgiu|pt_F)ko8pO6^XUgJNYLfUtmbgqCxl2xTn&|BNZ{U#E_I) zh)IHG^LnkWDc({he|+7f<~W6wWM+dv2|hVlaPN4?AXh9(hx3~r8Ik#_p+AxoCb>RU zn_MxotrLgyRpe+4E+%qeL^3L}RLG!>V{Ee9xvhR^JSN0|HR+_ebNd$V)*U{*Y}pw)RM$`MWn%+B-r31G znpn!!f~o~;G~QKcZMuN`CX5`nl$E4Y712`SLh|)n7tpfP`5N_jd|8uak+MyTeN-rp zMv^n1v#26gr(PbH%Ld;z9E^1`q9C|`(bBgt>|4B#6h`vKuI+;CBr7@|4Y4Lkfo|?s zbbSNU-xKUEaL~??*$!u?p7$TuytSV(EK=9ofx4Dz$}&scv}9siHg#PWe!~hju~Ykk z=1hNX4I?R8w1l_-uNY=KWW5oS{E!%0LXga=$DFz~rC;Jg%hdR7M^YaonkQ?~l@#=> z+Gb}rngEK(sFw(P0thV9}M{$fAg=WmRUkk7>Tupx~aE}n!;i|uNHtm%3L zhDhB;)~hu}tFDFcwcKZFq0AFib}>R*UE#>djb+?xdH3O(^JU9BM+J9xvl}xGLQ0I* ztjfBR;Ys4)f+y)@ADX z5L^;A)=DzU$2ePe`nhb6_zeWOWq^i=j9p;`p0cWuQlV|eNGptyj+&d;>3`Z1lOQC_&9Xgbsqv!ON>rchOr|LChECl zEWkB2!@^>fAZX3Hu9*x4R<<|?Q50yS803;wC0Um>LmRnT2UbPrm%Ak(YbKjXSb=df5EfA>KfC_@i>}TQP&N5o+pZjd^UBem4KjW+ZrEb za#1>&mm<$o7Cbss1f_J>?=DT&#e9j7mJiPbm#bG-$=eLy_1kFL7GvzSP=ZhhWs|yx z%5WZxiYO7OsuHO*ZBt{k-l9P%{!j#|h$5A-Y9-hoX{0Z4&QrPst@d+CS-0$u3}x9; zIm2XB5JQ6xlE%ZQR~{oB$JV4)5k8$nZPOA$U^MJ)(Y4LSbF;)XM38`G%_1mTp%k9K|9K-OrN0^4D3CWIKoJSl!^ARE=yMRf|b8ywiu8X z#a8(|J@?q{wp}J$O0-tEsv!uCQi8Vi$mlS}B30^77rn!^olL%Ks9X5((s8+L`8<1s z3z5fH4WoUwJ-)kJ2dN0&Awr<8Tk7CaW1A2NO-q&+WL9srqc()Wgd!)}eByma(3yG2LtUnK3XZyl$`Md~@d z8aMO##TbSVg!ezi{kQ)Nlq4#d7>gkwLI58TcMsA3;IHuefA}FEoYnl=+q+bCLx_T= zZdg~Idw2J6b;bR&644dOjK+O_@XbAD%LYV}wfy+eoc&23(Xl6I^Aelet^ghu>zdK9 z$IS@kl5i@aX)6yfsM|uq+xt6RL zAcWcq!WTtBRWE2-N9&+44Y`hJUC_&OW@W|g-99}liJ|V?yU5x31zKw+<6*}{PNYHL z`b4H{#?$Tk)@JNmD1)NzT9wVq)H0!Vk#V6Ztm;ImuSePVEveJF7HjMlQG68w>*sQ% zgcOAFfabez60{^5gREQZhmTOFS1BO?^m-Xaw>&D%6LkJj{0YWQ~ z3Kv=?*^rr+^oj}AYH~HXv1^EK=SrtW?IitvPKcI%meew|4j5yws)tcIPive=ZOLMd z$t+D>Qy7EM2IrDepmQxvlj@q45Ez+wL5)j2>ORkCL!=FY;C*td;+&>w5NNE;0H2f( zWeR{>4@gT{CH_^G<ZWBh8X;+En8*V2xF3PnF1E8in^|mI&rJ6R*t?2 zjE5GfJhg}Ux@CV7sM}Oh>jPX~Tw#o1IvJ(hMAtJzkfOUIqvY^zBtMVHTrePVM3 zCTCfv4F2O;LvCc(2RxE%Nxy50>^gnm{h_^9E|HSDX(^PX?aBhwXIRGPGK}a0{H@<4 z|F8ZtbmLHYO3c*r1>wK>r=1uV{QCFr^8H_noL?+4nV~Ej4)=zM@87|OQVP5eTPYo_ z1joloYf1{i;ogvU?k4FTxv4h0aZ{V(`KJRG?*j8>$#i$b*z6F4=c2h!C0j(JnD+0X zmE5vag}6S>oe#{)ii6=1P1a(KL2E@_*Xi|Albh?#tx81t#&a_O*)&ZFk*;YcSZlU| z12Q^RP2^(fUWkl*<~)$fbbD5&I7SMVr2%~+g54)ZOOY9Zk7QaA3A9dPRHSMv8fWQc zIVQGL>m~ok|HJ=@yLa!hx3@=B7U@?kW*6)nyg`;(#^VW(9-r{$-8c9*|K@+>=;)BY z^|$^*loeRxxqneH8RrNjqe6B%QG&KJ|HGf+{;&TZ+RG(!z9cF|c;^koyB{OI`9@k40h||1CPM)FMV@MIrP}g@ zf``oL4!uajaMQC8^g30*?w?Pzs@g7+rxw@ja>2j+r@zOod%GM>?$WM3=j%u0eT!8y z9_Vw*vgG*a7$GFL@7$)}%e!VHk-n`lVhCCiNEGWl ^!Ew8_;FrDA-Jwjzfp_2R2 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 literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/learnboost.png b/docs/3.2.x/docs/images/apps/learnboost.png new file mode 100644 index 0000000000000000000000000000000000000000..a6c33c8bd41f9806ab255e4afe5e0187c65810fe GIT binary patch literal 31434 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 literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/linkr.png b/docs/3.2.x/docs/images/apps/linkr.png new file mode 100644 index 0000000000000000000000000000000000000000..62dc5f6c51174c77fdc4356a7f442e95cf8fb6ad GIT binary patch literal 6428 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 literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/lists.png b/docs/3.2.x/docs/images/apps/lists.png new file mode 100644 index 0000000000000000000000000000000000000000..a0f48c63b1eb40fa7cab3c8384ed97834c621e21 GIT binary patch literal 697 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
  • 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 T655ph=X$5122!n4wvPBe3)j3P literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/nextdays.png b/docs/3.2.x/docs/images/apps/nextdays.png new file mode 100644 index 0000000000000000000000000000000000000000..9ca96fe961a84f3df23513aa4ceeef52bddbf91c GIT binary patch literal 35067 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

    w5Dis*m_y7@7D1e4 z9KyYI4f%OwlzTAnb!V%w9KSzGo_o-qx+T}|jD5Ifli>QkW^4Dl0qy#E)^i;gdP#au zr9x#A#Io9I&z!xvS$TH47mkmAF#UBdPbm|v{2;slZ$DJmPmS?1yxcuDGRQ(}O$K=1 zFn#VfHDa?`9liRT@+C{IRnxxx?5s8Rh~lDICyci{z1SY120Tc4v~$^^!r%f8jxW19 z-!W`RQzz>^r}e(!0X7(Pb?K+iq5AfybxkX}f4^kWitELX$1DEcEnRK_ph}nDH>*zm zy3V{RsVR+=)o!jcG2+*20u33eu<^y~xtRhKSCPtAvS`<=_T}huGX{g3*M2{`*=99p ziLoS6f4d24rO6V*^XZ~5A;7S1u*90%{i(w@k(ax90!}Ao?BL|`vVe5C|Fs)o<1=Hq z*7Vq=V1_&ljo$rq-0i93i}&NK89GXC(^RniXeiBYq{#U9Smxv!xmqg?NPZZDZFt9y`?L~^|PZTaeRVGu4$>! z*~xLh8OqGkTu?%Ax&5K@^>KM7$B~oKE=0ZapNoslb^sxS4bxDC-UpY9UPH33=VPt2 z5r0ae{#CbkC7>lHTD!U4=#7o5gX{F)zoHsnFm6{J<$b^s0bLQW)vWQ(qAB9ooxZI8 zHE%f*;8ul9KplfaG~DLj@NarC&|=6w${-C|QJeA1WQiC7JB0BHFR$)Ziqf=cNr(U= zX~>2fSWgU4gLxZqWnCT4kPOmpRcD}FM2g}#|Y z2!kk!^pH_ZOiZGfS!G;QDIGV)`bUORxeQbKV1=4JswDh82)g6ZIc0#v?Dlr7b$XIi zv6$P`D->mFWKe!dG3olV0;r;P6^2>XBJL!I045|waUG527M&6RuVRrY#GJU12%1Pn z8Hrk=IN^?^1))EM)m#lzi~=FXdJ;}t%U4cHvRFk(B2lE@=A7h?jE3OPSY?+swf2O$ z>0-s+ikvXb-`O&X;XAN|a^uNniST-~HUwYP&lgwN&27EIQNNMA`P+oxa0#67&ueB}*bx zi*h9ssAUNGpp1{!+D_AniHlRBmr^EsTP^3ev|yA&bhA&!Cz?u-&sUyZ5MN;8^16Ty zG_Ew76Mu(WdHWf^+O!@e$nXLrW|p^wEiG}5r?LuE$}ckF=SUJMoer3@>G#Oy^NhZk zsF>y0UbwLQvhhdB_dE5ioT6ygT~JlXI6Q5FM3_YT>nK&J(n7*nEFuF@Q07^ny>c0% zG?qL3ovkT<^WW2?SfZ+d8KRXNCve0tA_UIBL90wGU2xC%r0;{3)>&mPJ-RG8H`<@f zpsKw4O{M%aWHG=cVj=hjhc_%<&k&*F{*`Cr$({M6!Mc7Vlp+yW**cv+S50r}*u21z zXO=3w?8XvY$mtlAGmv#zC5i)NKl98WL5Z&rTC3I0x?ksSR6rE1WsCOqWkyc6;TuQd z#;5za#T;QGO#Dm%P~yUUH+uo?vXj$^{JpgJSs1bsDG4kl9!|-AhSj?2-2MfU!hwNj zt@(c?_DXcg4)G19kP1?XW5x=>u<=`?Co@=(;$$c5Gr*m;hUXk{szo7RTk7~L!a4Jj zl9F&#$o@EZ#9ZNuH0A+Q$#z<&7E?^j-zCLe*+oWo_YLCiL-ZRm-3nsR5U{uNs4_9p zKS0p~Swv_}1TD$e65+FP`kUv^*BXNT{ROoeRx>UX;M-Jwn#0Qd%o=|BTe;nttb*%s zJAss=ZZeP}8-U#LF3uA%6d0OJI%zUJOc#uT!3$l}3Uxvo$L_mu#%f zgc;J;);FJ2Qd0KHxGEF!zJO-KCT?Jnq0|<&Pd0iSDT6Vtks>Jm#MOT)88Jur2&?k< z$44f+{o?@)D8h?SyjOk{tdJaHmSI05B;1f?oFwxv!QYe&Rg0uDx39`+K z&(@|Oo{$n9IwOhE=VuZdCPv33lyBV$WhldnEmED5kT&(Q`e(>gwuvE=e05VW1+<+` zs8q3#rzZvsP~XfAe4u`$Xf8=g6lL@te!l!q4E7Ii?=D=QBg%Sf-Les&J*tWnsY4Z> z@jTuBKB`-{yr(Hf3?&wadw@mRNQp8>btEBp@?UvRZJZqSauW|&gY6u=DERC`9fT7z z+ft1zBDJP0LLp2Nl%F~3#Z_IX`9$Br<~QW5t!Yu9!=jC&FFjO3p(6uf3H2Qu5*U;k zo0|+J`<@3$6mjj}pBXodQ)n|^M~t;4Nol4K5R6voPMu%}kW{2ZA*bMHJGxVgER`t^ z%&$&{8Nd~Fn3>DbB9o|8=hA7khLWTqN+QvhYR>xN6slkEAFE3lSmnx5W|p=h6e7w` zDdFe)oM~W(h{8nzEEY|@uRO+r%^~G-h_WXQw8)yxl^%GD(4fr?rNZMNwL~#XM87S# zTxIVsVHCPiH!DjKpJNReLO5)6Lx6j>(4Q6WWAgAnj3OaZ`Z?jp3?|a8KStRB>&N zD$^2)zJ7*-n1r4AaOV^Y&hR-m9H}qdb~^X32UAttz&Hf+g_kre&8p+*zC}NDB6zy_ z)uR_-%gIRAvCBx=IY(B5)nX;kw93J(tlLx*P}gGFS4TGbpXop^mTMi@`(TDYb8x(m>HJWH7W`T<-rQ|PyI}s#2S?sC%W}F)Sc5W zDrj@>3RcUQ4^G>yCz_i{PEY}prJNzi<2SNv&x0n?bu?ZguxRfm%g{ikp)^1OL9fLf zZK{$4KhRe(V0DnWL!&CshF`@KY)+S#YH4Y zC<+op2{e?<=k>?ahL#tAxHd--L!}NW-e&xZ1eNiYTQ-*wmlQx1LkUeJOFFZmdV@Sh zzO<9JGqe*NAs*}2lr(}3uU~-TXu*(iD9H0IOAkgEoWc~UWUi{>DU;^-0(#wikh!sc zEW$}v=MC48yD3IkWNKt;F!jeNT{owagbU|NOviI9)~yTzWLU-nwy|e2J~B}oO*0DC z$kZUEt6yRaha9rp;VI28v1Dmj)dul}&tAd5b@U3HNzIM_LlLKw!leHNd?d?gMWSN? z(o-eZTfhCCvY!z_O${*7j6?y7K77mQH+K?yC1OyqewluV>9QEhej; zM=_s^)GZ!v2Ky0=?sxaC=SM*405Z?@&Hyex$E5c5?XQSLqef>JVO)j3ZWULtpyjb9S6-e2KxxW9r?{*h+@Q!Wzl0y$dA#XROv5 zgJ<&_FkKS7-yWIRoI+x~4v0Hn@UHfjaDFlj`; z%@f%Al6;cdh1OsDc#L^+qj;d+6Y%@@u&TvsRu$I9`pC$CU%D4V_1Z3n29u2)s~Xjvw^bIspAW?|LNT{3df4Yp4(^xr{k;w_N#TyTY&96dKwKJmW5^6qC5|KP!y}sKNalZ;zLI z6##ea%#1HoEvByi6tFN=z>#MH;TQGuRL8jzkdus>1k&sWmIXvt0^%jf^lG$P& z>nct$Alb?3+3~^%xGH}h@3I`gmcH5K2ebe0q(6Dz$bkkUJhwrU0(ErB8@ByS>x7F; z51&mhV7n4gXN1w;oLYrIZK2D}$0tUWDEv2UHk@)JNZQo%jY!@?EF>gt3`2qhrK!=- zz|TMnt)x`KM4KUqEP0fPi$?^FI$@L~TqUFQ_uCJ7gslDV0qbgnkX-ZL1`~w`jkh@p zJGnTc0+B~W0{&hFMliyIp;Jc;fnxsp=<1T7Ov}mWbx0^mfDw}>jQ>lj65d2+E`_U{ zP@fslb=X@>cIZ$eNzc`AC)E~Zpvf`bn!$3j2aG@+c2IBWbnna5kk*hxoJT)oRO`p7 zl|az<`sH z!#FuTO_v<2p4C#MQ)i%sTekm0h7C;!lYFF;FNI01Gp_H==3fU1sYoe`1kNm2IV4j( zd6&4pu1>*3_v=>UJL$i~mzV{UrYp}<^C!Rzs%}pwKSBw6neAkhB!zbS6;2Q{L_~4H zj6W>o0^r>#Ge5`>wP<4jMlFRI`*on0<8=hB%ZpPhB2%X$A|=^JogjN;XB8=tiS%~9 z>gtF8O1JHCNmFw+dNZStv)yfu(_($8b-_p+WAy!7I9&F?<>myXz}8vf=Zd-tQEQY+ zYHF?m7$fN_VkizQ0WVB-$wa9V$QFpA6ExdK1oEH%HLoI1MKl;7%IkO1;#`1gTOF_DunM44AwwmE*)M98l@RRi#Q0p zN|Fo}Tu^}NrN7FdkYO)F*OStnFg-}RTt@&lELp6;UYS+`T^}2T{^xfxqr3okDkab; zHf(MKKsjYeX6TnCu?R`UPMRx9urZQZMpoLGY3E3s;D77&jalkc|y}-20VEA4y zO|`G%wy3g|f|V2ogZ5Ec{s>et`_%Nt$@xusk3QeY>gAPHpDKOP^sCu?!iZv6Eg@XU zMpu`;7s8UtaI#<)iQ962$#&_Terd!YGE{6)nB?#v314CrO%UMxs|NffSOKB1^a2 zKR9?G6QUiAmOv3B@m>6gp8OX|%7An}NDrdeDCn1jupu|hH`Oaa1J99fCk1{hk98AG zj!OXA@39y+aF)QjliiZ)5G0N&P^peK6+sK-azM^EEBa5bIQ<4PAxppyeA}zl@^Fn> znFl%w3`P}1vO{_j@l98phB*y;xQQlaiU71MQc&8`VkwXXK2S$G237cY#$JXkS;zvS zB=8q(jg}}B-?xcNwMh^q7HE|hC_>YY962OKn)GvsSp@$C8%u_*wnlmW0SyL})K7;j zF;SpR{qxT{r`jMm{fZ;z1`Ho5twdA%;13JXF+WMjQa4e_Om`jOK1xZ#vJpg3cD*vm zLW23oA|E5A4P}!B-e{DBTI(!>g*?LIP>NIDz4dx^=$_QEW_c)IX-QA5@B0MpWip}Nu69(SKkaUp^u24(&i?I-v58z86Gvt1wqo6W{ZH2anWTc+;gtGWu+!+h>%QXmu}iYT&>6gcatw7fi` z>xMnl_xmQ9O)$;?xIm7nIT5m`{Z_&@cSfQNWMTRx{$eyJ#NP*{{2%7~TD)WA+fuBis{|q!`;wG3VKc1Q{P$rhjpz1S>WHB0 zb_~&LES0h9rl#aoRaH^Z(Yvj5g#&>H(k37%;ox0e)AZA$aD5TTAtsvNbAccuC&$Fd z*tg1Dij#4@+2K0Byey6xl6t@xx+Nk5L^42AC%C*%_$)cx4G z&#~dQAMNB!+q3-@5yA6a%;L6>vpupq5X$Lz1pnRtd+EG-cv7OlLQ^7zg~a+1fq3o=;hn`Lk`i+<}=#TLHUR^uXIO3-7;D9smB zB1m68#20-i*d!v!#uzGf>apX3!p$(E+wEv#m#mLB|dcO&cC6VPB`2S zjDSH|GCR~%atqxS8@#ins>~M5s{aY&5FGCmR$NG~wZgP)uGz5ztua)z}?O%R->(@83+-tKzx|3@M1?TDmVOsO4z`Dpik6I>owm>yXmGG!5c7#xMSplu00&y@hQMICga(>g+^yE`4l?bn zKyAVaDI2l3&sFYUNu8okQajdgl8^e^(`1aQH1&#q*P zMHXDBRB{|=*%VDeNYZ8&Q&|W@K)sp^@)vdH14!1d=+$G~7dgdcvMuu)uLYJ|n|VxD zN3ALZT0^z!VcQPrOd7vji=<~rgKRoYSSnGeR6&JkrKnatT3TDE231OB4=HPA15%ne zi3ElvQQVLkz@CFP7&HS#L2+VG?wH0&WM4x+fS_y<<$iTn=Jv}{F zBt5A+cC961U24?7p>5k3hOsI~rVC+3cMQw2o|lQkT$6#T$^O=|tSkP=b=xZ;#Eh#i zn5I#iOwd>y)-o20=R5cJayWM_6;_lmu2kuDH9%`ke}DgyMIjVIFgh~G@aQC|bc!IT z`GLEpNw%Yd^_^W@I+f$HT?Sy969eZR2^)^QoSs^^8(Q0mP^ z-NJS$eM}tNM(c=@ACOHXh>HcnFsPYJh_%UvgkeY!1oMcXQmHhez_0n;ZZ&uetu^_4 zfn+j4xm>}vEet~vhVjfmYP3={zGB8aeO{CcYW6hs6{t>VQp%d4qGe(lCWe$VHa1|} z7Eu%dH3C&ylW<*xl(^4BvNSjH#=4brbHEuFXE}N!U$W!qHOv}Xg zeIhR)k6o3Bw4jmrevJrKD6W;Q1k`RI+jW@WTKp3{)Ir+ZJII zBBg<|hNM2{84Vr0wYFX7`S3R(Qm)8jQ8pn(66jlF1~AL}FFjb~#v4!YKGt z4EtvgGnBDV(|sPn=-Gc}pPNx{Es*nStr1epGZ~t5v-bYn`+9ywmpzXbzB}i)Mw6k1 zjQzs>Fcv~s|9{Wher>O=vx-J!10uEVmdhWqkb zXye7OvZ4-Ao7^gj8908H*7h8uLlZczjqO-OK?qXT7-(w#29{-FS{7p?6C{%^Q3R=! zjpzA98e%`ha%~*f!YfsXB8}x(NI7GPY8a$aNybLTNv2#fxeQ*pN*rrqt#KTKSQzy5 zbkxq1q+XJLWoA# zo4IXWYy4&%D<5!;+61#LlhChu?D>@{pg}82#R^g>4A()p7L`hsOiPYr(#7{GfI}38 zcoh#NCBzDX5X(03${wa=QA-lWzwL&kaDXG)=!#+dQl&}h;+$A-+dE0#)WtqFo)%`&G; z1*KHeh!AS7sDbBk>i8L|QG_iG5Q?x`GcT`HV}t?8Yyv|=wOk>U%VHUV>5`8nG_ISZ zP|V}H4nZ{_)|!s4b|%IrkV0TPXjmC0p)^A*oG$blk#BuH1u9YH= z;u-HRhd7KtgD?z)R&+^;nDOI=p4z)nj0O@3m+syUqAmT4i0Fdab<)N)Iw(n(6i3Q-WDMa{)B4r5S?FpRNXi*zPM zxl{oGaimEkY|7;dLP}7AWZESP0#u~YQec>pa@8Z5OwiHMx~wU>TsMi1#uynMBAH52 z4Sc3zMeq8ahJ?E@AkV z?}9_5b>kRVt7GYz@2g=FT`m?ocFxsz{M<9&q3?0#*cqx`NQ^+}kT{0+&UW$>)8x9_ zm>QiV3TsE9Tze~9ui0>ZS&OWg=UtomE#}-8LR^$*URcHjS7sqFm+52vJjAYD%S68_ z%(r1#boF%;D~(~9=r|^h6^`qWYs(-EiQ`z9Gj=tWV=t=EUVB)&4?Wk25SGueYBf>c zz1L#mpcN$y*GiC7DTF0RCuYnh>fd^fwFer+oIEnM`LOmUg+`Om$%YyAm7pFbUrI@( zTqcZS+=N>bHP56szS^*u^HLngYwj2Y%gAGBtvPt`AcKR0vr#{^B2rg>;O2|=TY({r zMt+MIT+R%SA%vhfHO<7tB$3caG?`orogE!(eg~N=u7#RwYu#6+j=F;Hg~kJL9EVrF z@|9N;#=SP77so2(7XioYyD$hDQ08qURi{~dCD&hO2w!-X54G>__474 z^TQj}oVXS)81-jf$arb3$>nnF+qduPAq=45qg)?|wdka@oc+F1!k7!WjCzul!eWtA z>iv8ncX_!)u!+l^GY`x#i3k z6VJqPukQ?66U{6t%Q+cV1NCSk$z*a(Et;!F7+Py$rHH~1r8TBu)IPqH5UECRF)0nS zR)k?l9M6ba4TCU@kU|i}GufJ?L~Df~M3|<95Sk!}5JJv`!xzMH*of*;oA@$7H@lPwxg?5pewU z5WZI>kxCPXK3W){B4RDrxqBB=BZEv#m#9`f(&;24!^4D8yc(Zw+2+Dp!>SO5kODW6 zKv0XBR7ZW1oj2J;%`KKWlQQ96TJw9pqnLYl#Go{(%sd{ z-+t^PJbUcai)!asYgnBfLn(@-GFr`eqRk|8QCgEoI0SwGLSS39l^jtEbyHj2Ydc9Y zm8vC{S#r#u`19^8qWHTU!Vp3*F+R*>Ip$@z+=SMWVzJ2SQzvkf8A7G;y(;V0_YwwG zCMTy5I_C7rbBs=vxc-hBnh{+dJ8FM%|E2XFeH{~H3qeDq;iaT%)7h_26wiCy+)0oXMES%ex`q{nC%+I}kxx3tzVqtpf z*=($9A1fZzc`d@U9QN$piwdipJ~KGuN$3;Dnnc3I^J=*}q+#GVHi7S>wZNK*l$cB= z@jVYUlVwQ**=&wXI>GqFBw-LX@|g#|4^raTHc|+JD59&Yo5J)oUEN)jig_lc@?u}6^Pdtd+%!4DH?NPr7K)(5(upoxwa1a*RP|sql1^+ zbPLsL6~mN_jZV|m(aMPvN2o>yyLN1?1y~S@QY9oTO>uU-!2WA@Q<$0p(_-u9&1kKN zg8(n6P%KqRCKCi+K(@7&Cx83{l-`FD*0v0jlhd3y zdKhgb>1=PMzrPPdN`!`3De|QvrXh*L7=fUzy$!7uDhj#t>;KBY;K;JC@N0DkF@Xu7 zeI+Vei*AfsLt%Q7vgebilsS54kX%bEwq=mbq_IttVxa(Tj^gwrL0rrD>R1*}A3025 zBoR`QNTeuNE1WwwSQGVDYjJIbX;CQ^7#td9%hs(#kwVLme7?YuqescMwPO)8Ha^1f z6UUj(m)LgAHbfk7>dYx7r}9)P6{@8PhDN5?ym=#q=>m>xQ?B^5w`Dnge1QJ`KElxF z?BH1{RgZPuo!E{`sZ>N+n$}!~LZL`8KV8c*l}ORv*}>T85QV7%gF{1X*tiMXGG=%c lwP*&ar62#bwNTda{{zOpNBnz{3a0=7002ovPDHLkV1l1B;i~`u literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/nuorder.png b/docs/3.2.x/docs/images/apps/nuorder.png new file mode 100644 index 0000000000000000000000000000000000000000..da4cf597aae0b92aff5c13b2638ec7edc997705d GIT binary patch literal 38163 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 Ef(FYGSO5S3 literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/scottyapp.png b/docs/3.2.x/docs/images/apps/scottyapp.png new file mode 100644 index 0000000000000000000000000000000000000000..d5142f34601224e550deb71b93313497f5720cf8 GIT binary patch literal 118416 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 Dx(}}{ literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/seelio.png b/docs/3.2.x/docs/images/apps/seelio.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e7a8e65abae0ad30c3db0a00782d8b1d54ce9c GIT binary patch literal 24005 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 literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/selectvids.png b/docs/3.2.x/docs/images/apps/selectvids.png new file mode 100644 index 0000000000000000000000000000000000000000..9ba693a6a156164f547eb4b615afaa43a2475a81 GIT binary patch literal 42214 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 KMNUMnLSTZ(DAHH} literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/sharelatex.png b/docs/3.2.x/docs/images/apps/sharelatex.png new file mode 100644 index 0000000000000000000000000000000000000000..e3ef6dd25e1f81de2a170ede0e3a3665fe98b80d GIT binary patch literal 19707 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 w+RWv0lh6Ai#~9=x}o)VD=23xZGidKsJj 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

    UgJe6f|Y=Yr! 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 M07*qoM6N<$f<=x}o)VD=23xZGidKsJj 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 DnZfGr literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/todaylaunch.png b/docs/3.2.x/docs/images/apps/todaylaunch.png new file mode 100644 index 0000000000000000000000000000000000000000..f75fba3bda92d1387dc24b7cb6d5eaa648fff69e GIT binary patch literal 33233 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 KMNUMnLSTZ9^9~09 literal 0 HcmV?d00001 diff --git a/docs/3.2.x/docs/images/apps/upcload.png b/docs/3.2.x/docs/images/apps/upcload.png new file mode 100644 index 0000000000000000000000000000000000000000..4199712ee7ca626e6f2b45800fce43336a6da398 GIT binary patch literal 37792 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 C;!Mongoose Quick Start v3.2.2Fork me on GitHub

    Getting Started

    First be sure you have MongoDB and Nodejs installed.

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. +The first thing we need to do is include mongoose in our project and open a connection.

    var mongoose = require('mongoose')
    +  , db = mongoose.createConnection('localhost', 'test');

    We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    db.on('error', console.error.bind(console, 'connection error:'));
    +db.once('open', function () {
    +  // yay!
    +});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = new mongoose.Schema({
    +    name: String
    +})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a model.

    var Kitten = db.model('Kitten', kittySchema)

    A model is a class with which we construct documents. +In this case, each document will be a kitten with properties and behaviors as declared in our schema. +Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    +console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    kittySchema.methods.speak = function () {
    +  var greeting = this.name
    +    ? "Meow name is " + this.name
    +    : "I don't have a name"
    +  console.log(greeting);
    +}
    +
    +var Kitten = db.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    +fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. +Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err) {
    +  if (err) // TODO handle the error
    +  console.log('meow')
    +});

    Say time goes by and we want to display all the kittens we've seen. +We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    +  if (err) // TODO handle err
    +  console.log(kittens)
    +})

    We just logged all of the kittens in our db to the console. +If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax.

    Kitten.find({ name: /fluff/i }, callback)

    This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or api docs for more.

    \ No newline at end of file diff --git a/docs/3.2.x/docs/index.jade b/docs/3.2.x/docs/index.jade new file mode 100644 index 00000000000..62462a8e7f9 --- /dev/null +++ b/docs/3.2.x/docs/index.jade @@ -0,0 +1,119 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose Quick Start v#{package.version} + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + link(href='css/guide.css', rel='stylesheet', type='text/css') + style. + body.api + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + #content + .module + h2 Getting Started + p + em + | First be sure you have + a(href="http://www.mongodb.org/downloads") MongoDB + | and + a(href="http://nodejs.org/") Nodejs + | installed. + p + | Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. + | The first thing we need to do is include mongoose in our project and open a connection. + :js + var mongoose = require('mongoose') + , db = mongoose.createConnection('localhost', 'test'); + p We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs: + :js + db.on('error', console.error.bind(console, 'connection error:')); + db.once('open', function () { + // yay! + }); + p Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback. + p + | With Mongoose, everything is derived from a + a(href="./api.html#schema_Schema") Schema + | . Let's get a reference to it and define our kittens. + :js + var kittySchema = new mongoose.Schema({ + name: String + }) + p + | So far so good. We've got a schema with one property, + code name + | , which will be a + code String + | . The next step is compiling our schema into a + a(href="./api.html#model_Model") model + | . + :js + var Kitten = db.model('Kitten', kittySchema) + p + | A model is a class with which we construct documents. + | In this case, each document will be a kitten with properties and behaviors as declared in our schema. + | Let's create a kitten document representing the little guy we just met on the sidewalk outside: + :js + var silence = new Kitten({ name: 'Silence' }) + console.log(silence.name) // 'Silence' + p Kittens can meow, so let's take a look at how to add "speak" functionality to our documents: + :js + kittySchema.methods.speak = function () { + var greeting = this.name + ? "Meow name is " + this.name + : "I don't have a name" + console.log(greeting); + } + + var Kitten = db.model('Kitten', kittySchema) + p + | Functions added to the + code methods + | property of a schema get compiled into the Model prototype and exposed on each document instance: + :js + var fluffy = new Kitten({ name: 'fluffy' }); + fluffy.speak() // "Meow name is fluffy" + p + | We have talking kittens! But we still haven't saved anything to MongoDB. + | Each document can be saved to the database by calling its + code save + | method. The first argument to the callback will be an error if any occured. + :js + fluffy.save(function (err) { + if (err) // TODO handle the error + console.log('meow') + }); + p + | Say time goes by and we want to display all the kittens we've seen. + | We can access all of the kitten documents through our Kitten model. + :js + Kitten.find(function (err, kittens) { + if (err) // TODO handle err + console.log(kittens) + }) + p + | We just logged all of the kittens in our db to the console. + | If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax. + :js + Kitten.find({ name: /fluff/i }, callback) + p + | This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback. + h3 Congratulations + p + | That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the + a(href="guide.html") guide + | , or + a(href="api.html") api docs + | for more. + script. + document.body.className = 'load'; + include includes/keen diff --git a/docs/3.2.x/docs/js/zepto.min.js b/docs/3.2.x/docs/js/zepto.min.js new file mode 100644 index 00000000000..428f84a28c5 --- /dev/null +++ b/docs/3.2.x/docs/js/zepto.min.js @@ -0,0 +1,2 @@ +/* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */ +(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.2.x/docs/layout.jade b/docs/3.2.x/docs/layout.jade new file mode 100644 index 00000000000..ab1e9553cbe --- /dev/null +++ b/docs/3.2.x/docs/layout.jade @@ -0,0 +1,25 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose #{title} v#{package.version} + block style + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + link(href='css/guide.css', rel='stylesheet', type='text/css') + body + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + #content + .module + block content + script. + document.body.className = 'load'; + include includes/keen diff --git a/docs/3.2.x/docs/middleware.html b/docs/3.2.x/docs/middleware.html new file mode 100644 index 00000000000..1b5636ea640 --- /dev/null +++ b/docs/3.2.x/docs/middleware.html @@ -0,0 +1,29 @@ +Mongoose Middleware v3.2.2Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

    +There are two types of middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next

    var schema = new Schema(..);
    +schema.pre('save', function (next) {
    +  // do stuff
    +  next();
    +});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    +schema.pre('save', true, function (next, done) {
    +  // calling next kicks off the next middleware in parallel
    +  next();
    +  doAsync(done);
    +});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    +  var err = new Error('something went wrong');
    +  next(err);
    +});
    +
    +// later...
    +
    +myModel.save(function (err) {
    +  console.log(err.message) // something went wrong
    +});
    +

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    diff --git a/docs/3.2.x/docs/middleware.jade b/docs/3.2.x/docs/middleware.jade new file mode 100644 index 00000000000..b9e9e9eca94 --- /dev/null +++ b/docs/3.2.x/docs/middleware.jade @@ -0,0 +1,74 @@ +extends layout + +block content + h2 Middleware + p + | Middleware are functions which are passed control of flow during execution of + a(href="./api.html#document_Document-init") init + |, + a(href="./api.html#document_Document-validate") validate + |, + a(href="./api.html#model_Model-save") save + | and + a(href="./api.html#model_Model-remove") remove + | methods. + p + | There are two types of middleware, serial and parallel. + h4 Serial + p + | Serial middleware are executed one after another, when each middleware calls + code next + :js + var schema = new Schema(..); + schema.pre('save', function (next) { + // do stuff + next(); + }); + h4 Parallel + p + | Parallel middleware offer more fine-grained flow control. + :js + var schema = new Schema(..); + schema.pre('save', true, function (next, done) { + // calling next kicks off the next middleware in parallel + next(); + doAsync(done); + }); + p + | The hooked method, in this case + code save + |, will not be executed until + code done + | is called by each middleware. + h4 Use Cases + p + | Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas: + ul + li complex validation + li + | removing dependent documents + ul + li (removing a user removes all his blogposts) + li asynchronous defaults + li asynchronous tasks that a certain action triggers + ul + li triggering custom events + li notifications + h4 Error handling + :markdown + If any middleware calls `next` or `done` with an `Error` instance, the flow is interrupted, and the error is passed to the callback. + :js + schema.pre('save', function (next) { + var err = new Error('something went wrong'); + next(err); + }); + + // later... + + myModel.save(function (err) { + console.log(err.message) // something went wrong + }); + + h3#next Next Up + :markdown + Now that we've covered `middleware`, let's take a look at Mongoose's approach to faking JOINs with its query [population](/docs/populate.html) helper. diff --git a/docs/3.2.x/docs/migration.html b/docs/3.2.x/docs/migration.html new file mode 100644 index 00000000000..6a18a146953 --- /dev/null +++ b/docs/3.2.x/docs/migration.html @@ -0,0 +1,40 @@ +Mongoose Migration Guide v3.2.2Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    + +

    Here are the removed methods are their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    + +

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    • are now strict by default.
    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    + +

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    + +
    • $inc
    • $increment
    • $decrement
    + +

    If you really want this behavior back, include the mongoose-number module in your project.

    + +

    A good alternative is to start using the new findAndModify helpers. +Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    +...
    +Inventory.findById(id, function (err, inventory) {
    +  if (err) return handleError(err);
    +  inventory.productCount.$decrement(7);
    +  inventory.save(function (err) {
    +    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    +    if (err) return handleError(err);
    +    res.send(inventory.productCount); // 3
    +  });
    +});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    +  if (err) return handleError(err);
    +  res.send(inventory.productCount); // 3
    +});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This change allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    More Info

    Related blog posts:

    + +
    diff --git a/docs/3.2.x/docs/migration.jade b/docs/3.2.x/docs/migration.jade new file mode 100644 index 00000000000..988c6964f85 --- /dev/null +++ b/docs/3.2.x/docs/migration.jade @@ -0,0 +1,280 @@ +extends layout + +block append style + style. + table td { + padding-right: 15px; + } + +block content + h2 Migrating from 2.x to 3.x + :markdown + Migrating from Mongoose 2.x to 3.x brings with it [several changes](https://github.com/LearnBoost/mongoose/blob/master/History.md) to be aware of: + + h3 Query clean-up + :markdown + Many methods of the [Query](./api.html#query-js) API were nothing but aliases and have been [removed](https://github.com/LearnBoost/mongoose/commit/1149804c) in an effort to keep Mongoose clean and focused on there being as close to [one way](http://www.python.org/dev/peps/pep-0020/) of doing things as possible. If you really love all that extra noise, you can bring most of it back with [this module](https://github.com/aheckmann/mongoose-v2-compat). + + Here are the removed methods are their still existing aliases: + table + thead + tr(style='text-align:left') + th Removed + th Alternative + tbody + tr + td + code query.run + td + code query.exec + tr + td + code query.$or + td + code query.or + tr + td + code query.$nor + td + code query.nor + tr + td + code query.$gt + td + code query.gt + tr + td + code query.$gte + td + code query.gte + tr + td + code query.$lt + td + code query.lt + tr + td + code query.$lte + td + code query.lte + tr + td + code query.$ne + td + code query.ne + tr + td + code query.$in + td + code query.in + tr + td + code query.$nin + td + code query.nin + tr + td + code query.$all + td + code query.all + tr + td + code query.$regex + td + code query.regex + tr + td + code query.$size + td + code query.size + tr + td + code query.$maxDistance + td + code query.maxDistance + tr + td + code query.$mod + td + code query.mod + tr + td + code query.$near + td + code query.near + tr + td + code query.$exists + td + code query.exists + tr + td + code query.$elemMatch + td + code query.elemMatch + tr + td + code query.$within + td + code query.within + tr + td + code query.$box + td + code query.box + tr + td + code query.$center + td + code query.center + tr + td + code query.$centerSphere + td + code query.centerSphere + tr + td + code query.$slice + td + code query.slice + tr + td + code query.notEqualTo + td + code query.ne + tr + td + code query.wherein + td + code query.within + tr + td + code query.asc + td + code + | query.sort + a(href="#asc") * + tr + td + code query.desc + td + code + | query.sort + a(href="#desc") * + tr + td + code query.fields + td + code + | query.select + a(href="#fields") * + + h4#asc query#asc + :markdown + The `asc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#desc query#desc + :markdown + The `desc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#sort query#sort + :markdown + The [sort](./api.html#query_Query-sort) method of [Queries](./api.html#query-js) now accepts slightly different arguments. Read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#fields query#fields + :markdown + The `fields` method of [Query](./api.html#query-js) has been removed, it being mostly an alias for the [select](./api.html#query_Query-select) method anyway. The `select` method has slightly different arguments so read the [docs](./api.html#query_Query-select) to make sure your application is all set. + + Because of the change to the `fields` method, the field selection argument for [query.populate](./api.html#query_Query-populate) and model methods like [findById](./api.html#model_Model-findById), [find](./api.html#model_Model-find), etc, is slightly different as well (no longer accepts arrays for example), so read the [docs](./api.html#query_Query-select) to make sure your application is all set. + + h3 Connecting to ReplicaSets + :markdown + To connect to a [ReplicaSet](http://www.mongodb.org/display/DOCS/Replica+Sets) you no longer use the separate `connectSet` or `createSetConnection` methods. Both [mongoose.connect](./api.html#index_Mongoose-connect) and [mongoose.createConnection](./api.html#index_Mongoose-createConnection) are now smart enough to just do the right thing with your connection string. If you really want to bring `connectSet` and `createSetConnection` back use [this module](https://github.com/aheckmann/mongoose-v2-compat). + + h3 Schemas + :markdown + - are now [strict](./guide.html#strict) by default. + - Arrays of [object literal](./subdocs.html#altsyntax) now creates document arrays instead of arrays of [Mixed](./schematypes.html#mixed). + - Indexes are now created in [background](./guide.html#autoIndex) by default. + - Index errors are now emitted on their model instead of the connection. See issue [#984](https://github.com/LearnBoost/mongoose/issues/984). + + h3#arrays Arrays + :markdown + - [pop](./api.html#types_array_MongooseArray-pop) is now fixed causing a $set of the entire array. + - [$pop](./api.html#types_array_MongooseArray-%24pop) is now fixed and behaves just as MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the last element of the array. + - [shift](./api.html#types_array_MongooseArray-shift) is now fixed causing a $set of the entire array. + - [$shift](./api.html#types_array_MongooseArray-%24shift) is now fixed and behaves just as a [MongoDB $pop -1](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the first element of array. + - `$unshift` was removed, use [unshift](./api.html#types_array_MongooseArray-unshift) instead. + - `$addToSet` was removed, use [addToSet](./api.html#types_array_MongooseArray-addToSet) instead. + - `$pushAll` was removed, use [push](./api.html#types_array_MongooseArray-push) instead. + - `$pull` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. + - `$pullAll` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. + - `doAtomics` was changed to the [hasAtomics](./api.html#types_array_MongooseArray-hasAtomics) private method + + h3#mongoosenumber Number type + :markdown + The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused [too many problems](https://groups.google.com/d/msg/mongoose-orm/syKlN2xL1EE/FfRFhEFj4KcJ) when doing comparisons and had other bad side-effects. + + With it out of the picture, the following helper methods of MongooseNumbers are now also gone: + + - $inc + - $increment + - $decrement + + If you really want this behavior back, include the [mongoose-number](https://github.com/aheckmann/mongoose-number) module in your project. + + A good alternative is to start using the new [findAndModify](./api.html#model_Model-findOneAndUpdate) [helpers](./api.html#model_Model-findOneAndRemove). + Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber: + :js + var inventorySchema = new Schema({ productCount: Number }); + ... + Inventory.findById(id, function (err, inventory) { + if (err) return handleError(err); + inventory.productCount.$decrement(7); + inventory.save(function (err) { + // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback); + if (err) return handleError(err); + res.send(inventory.productCount); // 3 + }); + }); + :markdown + With MongooseNumber out of the picture, we'll instead use the [Account.findByIdAndUpdate](./api.html#model_Model-findByIdAndUpdate) helper: + :js + Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) { + if (err) return handleError(err); + res.send(inventory.productCount); // 3 + }); + :markdown + The `findByIdAndUpdate` helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases. + + h3#documents Documents + :markdown + - `doc#commit` is now removed, use [doc.markModified](./api.html#document_Document-markModified) instead + - [doc#modifiedPaths](./api.html#document_Document-modifiedPaths) is now a method not a getter + - `doc.modified` is now removed, use [doc.isModified](./api.html#document_Document-isModified) instead + + h4#gettercasting getter casting + :markdown + Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue [#820](https://github.com/LearnBoost/mongoose/issues/820) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). + + h4#setterorder setter order + :markdown + Values being set no longer cast until _after_ all setters have been applied. Previously the value returned from each setter was cast _before_ passing it on to the next setter. This change allows more flexible processing of values in setters. See issue [#665](https://github.com/learnboost/mongoose/issues/665) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). + + h3#subdocs Subdocuments + :markdown + - `subdoc.parent` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parent). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). + - `subdoc.parentArray` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parentArray). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). + + h3#stringmatch String match validator + :markdown + The String SchemaType [match](./api.html#schema_string_SchemaString-match) validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the [required](./api.html#schematype_SchemaType-required) validator as well. See issue [#934](https://github.com/LearnBoost/mongoose/issues/934) and pull request [#935](https://github.com/LearnBoost/mongoose/pull/935). + + h3#version Versioning + :markdown + Documents are now transparently versioned. Read the in depth details [here](http://aaronheckmann.posterous.com/tag/versioning). + + h3#moreinfo More Info + :markdown + Related blog posts: + + - [Mongoose v3 released](http://aaronheckmann.posterous.com/mongoose-v3-released) + - [API changes](http://aaronheckmann.posterous.com/mongoose-v3-part-3-api-changes) + - [FindAndModify](http://aaronheckmann.posterous.com/mongoose-v3-part-2-findandmodify) diff --git a/docs/3.2.x/docs/models.html b/docs/3.2.x/docs/models.html new file mode 100644 index 00000000000..645951f6d96 --- /dev/null +++ b/docs/3.2.x/docs/models.html @@ -0,0 +1,32 @@ +Mongoose Models v3.2.2Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var schema = new Schema({ name: 'string', size: 'string' });
    +var Tank = mongoose.model('Tank', schema);
    +
    +// or, if you are using separate connections
    +var db = mongoose.createConnection(..);
    +var Tank = db.model('Tank', schema);
    +

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = db.model('Tank', yourSchema);
    +
    +var small = new Tank({ size: 'small' });
    +small.save(function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +
    +// or
    +
    +Tank.create({ size: 'small' }, function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    +  if (err) return handleError(err);
    +  // removed!
    +});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at Documents.

    diff --git a/docs/3.2.x/docs/models.jade b/docs/3.2.x/docs/models.jade new file mode 100644 index 00000000000..105ef327803 --- /dev/null +++ b/docs/3.2.x/docs/models.jade @@ -0,0 +1,61 @@ +extends layout + +block content + h2 Models + :markdown + [Models](./api.html#model-js) are fancy constructors compiled from our `Schema` definitions. Instances of these models represent [documents](./documents.html) which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models. + + h3 Compiling your first model + :js + var schema = new Schema({ name: 'string', size: 'string' }); + var Tank = mongoose.model('Tank', schema); + + // or, if you are using separate connections + var db = mongoose.createConnection(..); + var Tank = db.model('Tank', schema); + + h3 Constructing documents + :markdown + [Documents](./documents.html) are instances of our model. Creating them and saving to the database is easy: + :js + var Tank = db.model('Tank', yourSchema); + + var small = new Tank({ size: 'small' }); + small.save(function (err) { + if (err) return handleError(err); + // saved! + }) + + // or + + Tank.create({ size: 'small' }, function (err) { + if (err) return handleError(err); + // saved! + }) + + h3 Querying + :markdown + Finding documents is easy with Mongoose, which supports the [rich](http://www.mongodb.org/display/DOCS/Advanced+Queries) query syntax of MongoDB. Documents can be retreived using each `models` [find](./api.html#model_Model-find), [findById](./api.html#model_Model-findById), [findOne](./api.html#model_Model-findOne), or [where](./api.html#model_Model-where) static methods. + + :js + Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback); + :markdown + See the chapter on [querying](./queries.html) for more details on how to use the [Query](./api.html#query-js) api. + h3 Removing + :markdown + Models have a static `remove` method available for removing all documents matching `conditions`. + :js + Tank.remove({ size: 'large' }, function (err) { + if (err) return handleError(err); + // removed! + }); + h3 Updating + :markdown + Each `model` has its own `update` method for modifying documents in the database without returning them to your application. See the [API](./api.html#model_Model-update) docs for more detail. + h3 Yet more + :markdown + The [API docs](./api.html#model_Model) cover many additional methods available like [count](./api.html#model_Model-count), [mapReduce](./api.html#model_Model-mapReduce), [aggregate](./api.html#model_Model-aggregate), and more. + + h3#next Next Up + :markdown + Now that we've covered `Models`, let's take a look at [Documents](/docs/documents.html). diff --git a/docs/3.2.x/docs/plugins.html b/docs/3.2.x/docs/plugins.html new file mode 100644 index 00000000000..05010cb615d --- /dev/null +++ b/docs/3.2.x/docs/plugins.html @@ -0,0 +1,33 @@ +Mongoose Plugins v3.2.2Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    + +

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    +module.exports = exports = function lastModifiedPlugin (schema, options) {
    +  schema.add({ lastMod: Date })
    +  
    +  schema.pre('save', function (next) {
    +    this.lastMod = new Date
    +    next()
    +  })
    +  
    +  if (options && options.index) {
    +    schema.path('lastMod').index(options.index)
    +  }
    +}
    +
    +// game-schema.js
    +var lastMod = require('./lastMod');
    +var Game = new Schema({ ... });
    +Game.plugin(lastMod, { index: true });
    +
    +// player-schema.js
    +var lastMod = require('./lastMod');
    +var Player = new Schema({ ... });
    +Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    diff --git a/docs/3.2.x/docs/plugins.jade b/docs/3.2.x/docs/plugins.jade new file mode 100644 index 00000000000..4930fd8a46e --- /dev/null +++ b/docs/3.2.x/docs/plugins.jade @@ -0,0 +1,42 @@ +extends layout + +block content + h2 Plugins + :markdown + Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature. + + Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each `Schema`: + + :js + // lastMod.js + module.exports = exports = function lastModifiedPlugin (schema, options) { + schema.add({ lastMod: Date }) + + schema.pre('save', function (next) { + this.lastMod = new Date + next() + }) + + if (options && options.index) { + schema.path('lastMod').index(options.index) + } + } + + // game-schema.js + var lastMod = require('./lastMod'); + var Game = new Schema({ ... }); + Game.plugin(lastMod, { index: true }); + + // player-schema.js + var lastMod = require('./lastMod'); + var Player = new Schema({ ... }); + Player.plugin(lastMod); + :markdown + We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code. + h3 Community! + :markdown + Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. + + h3#next Next Up + :markdown + Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help [contribute](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md) to the continuing development of Mongoose itself. diff --git a/docs/3.2.x/docs/populate.html b/docs/3.2.x/docs/populate.html new file mode 100644 index 00000000000..c02800225c4 --- /dev/null +++ b/docs/3.2.x/docs/populate.html @@ -0,0 +1,104 @@ +Mongoose Query Population v3.2.2Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    + +

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    +  , Schema = mongoose.Schema
    +  
    +var PersonSchema = new Schema({
    +  name    : String,
    +  age     : Number,
    +  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    +});
    +
    +var StorySchema = new Schema({
    +  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    +  title    : String,
    +  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    +});
    +
    +var Story  = mongoose.model('Story', StorySchema);
    +var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    +
    +aaron.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  var story1 = new Story({
    +    title: "Once upon a timex.",
    +    _creator: aaron._id    // assign an ObjectId
    +  });
    +  
    +  story1.save(function (err) {
    +    if (err) return handleError(err);
    +    // thats it!
    +  });
    +})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    +.findOne({ title: /timex/ })
    +.populate('_creator')
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    +})
    +

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    + +

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    +.findOne({ title: /timex/i })
    +.populate('_creator', 'name') // only return the Persons name
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  
    +  console.log('The creator is %s', story._creator.name);
    +  // prints "The creator is Aaron"
    +  
    +  console.log('The creators age is %s', story._creator.age);
    +  // prints "The creators age is null'
    +})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    +.find(...)
    +.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    + +

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    +aaron.save();

    This allows us to perform a find and populate combo:

    Person
    +.findOne({ name: 'Aaron' })
    +.populate('stories') // only works if we pushed refs to children
    +.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log(person);
    +})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    +.find({ _creator: aaron._id })
    +.populate('_creator') // not really necessary
    +.exec(function (err, stories) {
    +  if (err) return handleError(err);
    +  console.log('The stories are an array: ', stories);
    +})
    +

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    +guille.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  story._creator = guille; // or guille._id
    +  
    +  story.save(function (err) {
    +    if (err) return handleError(err);
    +    
    +    Story
    +    .findOne({ title: /timex/i })
    +    .populate('_creator', 'name')
    +    .exec(function (err, story) {
    +      if (err) return handleError(err);
    +      
    +      console.log('The creator is %s', story._creator.name)
    +      // prints "The creator is Guillermo"
    +    })
    +  })
    +})
    +

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    +Story.findOne(..).populate('_creator', 'name age').exec(..);
    +
    +// this doesn't
    +Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
    +

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at connections.

    diff --git a/docs/3.2.x/docs/populate.jade b/docs/3.2.x/docs/populate.jade new file mode 100644 index 00000000000..5443bbbcc28 --- /dev/null +++ b/docs/3.2.x/docs/populate.jade @@ -0,0 +1,164 @@ +extends layout + +block content + h2 Query Population + :markdown + There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. + + `ObjectIds` can refer to another document in a collection within our database and be `populate()`d when querying: + :js + var mongoose = require('mongoose') + , Schema = mongoose.Schema + + var PersonSchema = new Schema({ + name : String, + age : Number, + stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] + }); + + var StorySchema = new Schema({ + _creator : { type: Schema.Types.ObjectId, ref: 'Person' }, + title : String, + fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }] + }); + + var Story = mongoose.model('Story', StorySchema); + var Person = mongoose.model('Person', PersonSchema); + :markdown + So far we've created two `models`. Our `Person` model has it's `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose in which model to look, in our case the `Story` model. All `_id`s we store here must be document _ids from the `Story` model. We also added a `_creator` `ObjectId` to our `Story` schema which refers to a single `Person`. + h3 Saving refs + :markdown + Saving refs to other documents works the same way you normally save objectids, just assign an `ObjectId`: + :js + var aaron = new Person({ name: 'Aaron', age: 100 }); + + aaron.save(function (err) { + if (err) return handleError(err); + + var story1 = new Story({ + title: "Once upon a timex.", + _creator: aaron._id // assign an ObjectId + }); + + story1.save(function (err) { + if (err) return handleError(err); + // thats it! + }); + }) + h3 Population + :markdown + So far we haven't done anything special. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator`: + :js + Story + .findOne({ title: /timex/ }) + .populate('_creator') + .exec(function (err, story) { + if (err) return handleError(err); + console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron" + }) + + :markdown + Populated paths are no longer set to their original `ObjectId`s, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. + + Arrays of `ObjectId` refs work the same way. Just call the [populate](./api.html#query_Query-populate) method on the query and an array of documents will be returned _in place_ of the `ObjectIds`. + + h3 Field selection + :markdown + What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: + :js + Story + .findOne({ title: /timex/i }) + .populate('_creator', 'name') // only return the Persons name + .exec(function (err, story) { + if (err) return handleError(err); + + console.log('The creator is %s', story._creator.name); + // prints "The creator is Aaron" + + console.log('The creators age is %s', story._creator.age); + // prints "The creators age is null' + }) + h3 Query conditions for populate + :markdown + What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them? + :js + Story + .find(...) + .populate('fans', null, { age: { $gte: 21 }}, { limit: 5 }) + :markdown + Done. `Conditions` and `options` for populate queries are passed as the third and fourth arguments respectively. + h3 Refs to children + :markdown + We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' on to `aaron.stories`. + + There are two perspectives to this story. First, it's nice to have `aaron` know which are his stories. + :js + aaron.stories.push(story1); + aaron.save(); + :markdown + This allows us to perform a `find` and `populate` combo: + :js + Person + .findOne({ name: 'Aaron' }) + .populate('stories') // only works if we pushed refs to children + .exec(function (err, person) { + if (err) return handleError(err); + console.log(person); + }) + :markdown + However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely `find()` the documents we are interested in. + :js + Story + .find({ _creator: aaron._id }) + .populate('_creator') // not really necessary + .exec(function (err, stories) { + if (err) return handleError(err); + console.log('The stories are an array: ', stories); + }) + + h3 Updating refs + :markdown + Now that we have a `story` we realized that the `_creator` was incorrect. We can update `ObjectId` refs the same as any other property through the magic of Mongoose's internal casting: + :js + var guille = new Person({ name: 'Guillermo' }); + guille.save(function (err) { + if (err) return handleError(err); + + story._creator = guille; // or guille._id + + story.save(function (err) { + if (err) return handleError(err); + + Story + .findOne({ title: /timex/i }) + .populate('_creator', 'name') + .exec(function (err, story) { + if (err) return handleError(err); + + console.log('The creator is %s', story._creator.name) + // prints "The creator is Guillermo" + }) + }) + }) + + h4 NOTE: + :markdown + The documents returned from calling [populate](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. + + h4 NOTE: + :markdown + _Field selection_ in v3 is slightly different than v2. Arrays of fields are no longer accepted. + + :js + // this works + Story.findOne(..).populate('_creator', 'name age').exec(..); + + // this doesn't + Story.findOne(..).populate('_creator', ['name', 'age']).exec(..); + + :markdown + See the [migration guide](./migration.html#fields) for more detail. + + h3#next Next Up + :markdown + Now that we've covered query population, let's take a look at [connections](/docs/connections.html). diff --git a/docs/3.2.x/docs/prior.html b/docs/3.2.x/docs/prior.html new file mode 100644 index 00000000000..c585504f8bf --- /dev/null +++ b/docs/3.2.x/docs/prior.html @@ -0,0 +1,9 @@ +Mongoose v3.2.2Fork me on GitHub

    Prior Release Documentation

    diff --git a/docs/3.2.x/docs/prior.jade b/docs/3.2.x/docs/prior.jade new file mode 100644 index 00000000000..1ef7d088a72 --- /dev/null +++ b/docs/3.2.x/docs/prior.jade @@ -0,0 +1,8 @@ +extends layout + +block content + h2 Prior Release Documentation + ul + each release in releases + li + a(href=release.url)= release.version diff --git a/docs/3.2.x/docs/queries.html b/docs/3.2.x/docs/queries.html new file mode 100644 index 00000000000..6f115e9f1bf --- /dev/null +++ b/docs/3.2.x/docs/queries.html @@ -0,0 +1,41 @@ +Mongoose Queries v3.2.2Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    + +

    When a callback function:

    + +
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    + +

    Let's take a look at what happens when passing a callback:

    var Person = db.model('Person', yourSchema);
    +
    +// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    +Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    Here we see that the query was executed immediately and the results passed to our callback. +Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    +var query = Person.findOne({ 'name.last': 'Ghost' });
    +
    +// selecting the `name` and `occupation` fields
    +query.select('name occupation');
    +
    +// execute the query at a later time
    +query.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    +.find({ occupation: /host/ })
    +.where('name.last').equals('Ghost')
    +.where('age').gt(17).lt(66)
    +.where('likes').in(['vaporizing', 'talking'])
    +.limit(10)
    +.sort('-occupation')
    +.select('name occupation')
    +.exec(callback);
    +

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    diff --git a/docs/3.2.x/docs/queries.jade b/docs/3.2.x/docs/queries.jade new file mode 100644 index 00000000000..68c529efe25 --- /dev/null +++ b/docs/3.2.x/docs/queries.jade @@ -0,0 +1,62 @@ +extends layout + +block content + h2 Queries + :markdown + Documents can be retrieved through several static helper methods of [models](./models.html). + :markdown + Any [model](./api.html#model_Model) method which [involves](./api.html#model_Model-find) [specifying](./api.html#model_Model-findById) [query](./api.html#model_Model-count) [conditions](./api.html#model_Model-update) can be executed two ways: + + When a `callback` function: + + - is passed, the operation will be executed immediately with the results passed to the callback. + - is not passed, an instance of [Query](./api.html#query-js) is returned, which provides a special `QueryBuilder` interface for you. + + Let's take a look at what happens when passing a `callback`: + :js + var Person = db.model('Person', yourSchema); + + // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields + Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { + if (err) return handleError(err); + console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. + }) + :markdown + Here we see that the query was executed immediately and the results passed to our callback. + Now let's look at what happens when no `callback` is passed: + :js + // find each person with a last name matching 'Ghost' + var query = Person.findOne({ 'name.last': 'Ghost' }); + + // selecting the `name` and `occupation` fields + query.select('name occupation'); + + // execute the query at a later time + query.exec(function (err, person) { + if (err) return handleError(err); + console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. + }) + :markdown + An instance of [Query](./api.html#query-js) was returned which allows us to build up our query. Taking this example further: + :js + Person + .find({ occupation: /host/ }) + .where('name.last').equals('Ghost') + .where('age').gt(17).lt(66) + .where('likes').in(['vaporizing', 'talking']) + .limit(10) + .sort('-occupation') + .select('name occupation') + .exec(callback); + + h3#refs References to other documents + :markdown + There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. Read more [here](./populate.html). + + h3 Streaming + :markdown + Queries can be [streamed](http://nodejs.org/api/stream.html) from MongoDB to your application as well. Simply call the query's [stream](./api.html#query_Query-stream) method instead of [exec](./api.html#query_Query-exec) to return an instance of [QueryStream](./api.html#querystream_QueryStream). + + h3#next Next Up + :markdown + Now that we've covered `Queries`, let's take a look at [validation](/docs/validation.html). diff --git a/docs/3.2.x/docs/releases b/docs/3.2.x/docs/releases new file mode 100644 index 00000000000..cd9fcd27bd1 --- /dev/null +++ b/docs/3.2.x/docs/releases @@ -0,0 +1,2 @@ +2.8.x +2.7.x diff --git a/docs/3.2.x/docs/schematypes.html b/docs/3.2.x/docs/schematypes.html new file mode 100644 index 00000000000..068dad8eea1 --- /dev/null +++ b/docs/3.2.x/docs/schematypes.html @@ -0,0 +1,67 @@ +Mongoose SchemaTypes v3.2.2Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    +  name:    String,
    +  binary:  Buffer,
    +  living:  Boolean,
    +  updated: { type: Date, default: Date.now },
    +  age:     { type: Number, min: 18, max: 65 },
    +  mixed:   Schema.Types.Mixed,
    +  _someId: Schema.Types.ObjectId,
    +  array:      [],
    +  ofString:   [String],
    +  ofNumber:   [Number],
    +  ofDates:    [Date],
    +  ofBuffer:   [Buffer],
    +  ofBoolean:  [Boolean],
    +  ofMixed:    [Schema.Types.Mixed],
    +  ofObjectId: [Schema.Types.ObjectId],
    +  nested: {
    +    stuff: { type: String, lowercase: true, trim: true }
    +  }
    +})
    +
    +// example use
    +
    +var Thing = mongoose.model('Thing', schema);
    +
    +var m = new Thing;
    +m.name = 'Statue of Liberty';
    +m.age = 125;
    +m.updated = new Date;
    +m.binary = new Buffer(0);
    +m.living = false;
    +m.mixed = {[ any: { thing: 'i want' } ]};
    +m.markModified('mixed');
    +m._someId = new mongoose.Types.ObjectId;
    +m.array.push(1);
    +m.ofString.push("strings!");
    +m.ofNumber.unshift(1,2,3,4);
    +m.ofDates.addToSet(new Date);
    +m.ofBuffer.pop();
    +m.ofMixed = [1, [], 'three', { four: 5 }];
    +m.nested.stuff = 'good';
    +m.save(callback);
    +

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    +var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    +person.markModified('anything');
    +person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    +var ObjectId = mongoose.Schema.Types.ObjectId;
    +var Car = new Schema({ driver: ObjectId });
    +// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    +var ToyBox = new Schema({
    +  toys: [ToySchema],
    +  buffers: [Buffer],
    +  string:  [String],
    +  numbers: [Number]
    +  // ... etc
    +});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    +var Empty2 = new Schema({ any: Array });
    +var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    +var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Models.

    diff --git a/docs/3.2.x/docs/schematypes.jade b/docs/3.2.x/docs/schematypes.jade new file mode 100644 index 00000000000..afa3c3276fe --- /dev/null +++ b/docs/3.2.x/docs/schematypes.jade @@ -0,0 +1,146 @@ +extends layout + +block content + h2 SchemaTypes + p + | SchemaTypes handle definition of path + a(href="./api.html#schematype_SchemaType-default") defaults + |, + a(href="./api.html#schematype_SchemaType-validate") validation + |, + a(href="./api.html#schematype_SchemaType-get") getters + |, + a(href="./api.html#schematype_SchemaType-set") setters + |, + a(href="./api.html#schematype_SchemaType-select") field selection defaults + | for + a(href="./api.html#query-js") queries + | and other general characteristics for + a(href="./api.html#schema-string-js") Strings + | and + a(href="./api.html#schema-number-js") Numbers + |. Check out their respective API documentation for more detail. + p + | Following are all valid + a(href="./api.html#schema_Schema-Types") Schema Types + |. + ul + li String + li Number + li Date + li Buffer + li Boolean + li Mixed + li ObjectId + li Array + h4 Example + :js + var schema = new Schema({ + name: String, + binary: Buffer, + living: Boolean, + updated: { type: Date, default: Date.now }, + age: { type: Number, min: 18, max: 65 }, + mixed: Schema.Types.Mixed, + _someId: Schema.Types.ObjectId, + array: [], + ofString: [String], + ofNumber: [Number], + ofDates: [Date], + ofBuffer: [Buffer], + ofBoolean: [Boolean], + ofMixed: [Schema.Types.Mixed], + ofObjectId: [Schema.Types.ObjectId], + nested: { + stuff: { type: String, lowercase: true, trim: true } + } + }) + + // example use + + var Thing = mongoose.model('Thing', schema); + + var m = new Thing; + m.name = 'Statue of Liberty'; + m.age = 125; + m.updated = new Date; + m.binary = new Buffer(0); + m.living = false; + m.mixed = {[ any: { thing: 'i want' } ]}; + m.markModified('mixed'); + m._someId = new mongoose.Types.ObjectId; + m.array.push(1); + m.ofString.push("strings!"); + m.ofNumber.unshift(1,2,3,4); + m.ofDates.addToSet(new Date); + m.ofBuffer.pop(); + m.ofMixed = [1, [], 'three', { four: 5 }]; + m.nested.stuff = 'good'; + m.save(callback); + + h3 Usage notes: + h4#mixed Mixed + p An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent: + :js + var Any = new Schema({ any: {} }); + var Any = new Schema({ any: Schema.Types.Mixed }); + p + | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the + code .markModified(path) + | method of the document passing the path to the Mixed type you just changed. + :js + person.anything = { x: [3, 4, { y: "changed" }] }; + person.markModified('anything'); + person.save(); // anything will now get saved + h4#objectids ObjectIds + p + | To specify a type of ObjectId, use + code Schema.Types.ObjectId + | in your declaration. + :js + var mongoose = require('mongoose'); + var ObjectId = mongoose.Schema.Types.ObjectId; + var Car = new Schema({ driver: ObjectId }); + // or just Schema.ObjectId for backwards compatibility with v2 + h4#arrays Arrays + p + | Provide creation of arrays of + a(href="./api.html#schema_Schema-Types") SchemaTypes + | or + a(href="./subdocs.html") Sub-Documents + |. + :js + var ToySchema = new Schema({ name: String }); + var ToyBox = new Schema({ + toys: [ToySchema], + buffers: [Buffer], + string: [String], + numbers: [Number] + // ... etc + }); + p + | Note: specifying an empty array is equivalent to + code Mixed + |. The following all create arrays of + code Mixed + |: + :js + var Empty1 = new Schema({ any: [] }); + var Empty2 = new Schema({ any: Array }); + var Empty3 = new Schema({ any: [Schema.Types.Mixed] }); + var Empty4 = new Schema({ any: [{}] }); + h3#customtypes Creating Custom Types + p + | Mongoose can also be extended with custom SchemaTypes. Search the + a(href="http://plugins.mongoosejs.com") plugins + | site for compatible types like + a(href="https://github.com/aheckmann/mongoose-long") mongoose-long + | and + a(href="https://github.com/aheckmann/mongoose-number") other + | + a(href="https://github.com/bnoguchi/mongoose-types") types + |. + + h3#next Next Up + :markdown + Now that we've covered `SchemaTypes`, let's take a look at [Models](/docs/models.html). diff --git a/docs/3.2.x/docs/source/_docs b/docs/3.2.x/docs/source/_docs new file mode 100644 index 00000000000..2b19e8db161 --- /dev/null +++ b/docs/3.2.x/docs/source/_docs @@ -0,0 +1,16201 @@ + +### lib/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = require('./connectionstate')", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "require('./connectionstate')", + "string": "STATES" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the collection" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "conn", + "description": "A MongooseConnection instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "optional collection options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", + "summary": "

    Abstract Collection constructor

    ", + "body": "

    This is the base class that drivers inherit from and implement.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", + "ctx": { + "type": "function", + "name": "Collection", + "string": "Collection()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "name" + } + ], + "description": { + "full": "

    The collection name

    ", + "summary": "

    The collection name

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.name;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "conn" + } + ], + "description": { + "full": "

    The Connection instance

    ", + "summary": "

    The Connection instance

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.conn;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database connects

    ", + "summary": "

    Called when the database connects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onOpen", + "string": "Collection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database disconnects

    ", + "summary": "

    Called when the database disconnects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onClose", + "string": "Collection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the method to queue" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method when executed" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Queues a method for later execution when its
    database connection opens.

    ", + "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "addQueue", + "string": "Collection.prototype.addQueue()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes all queued methods and clears the queue.

    ", + "summary": "

    Executes all queued methods and clears the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "doQueue", + "string": "Collection.prototype.doQueue()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "ensureIndex", + "string": "Collection.prototype.ensureIndex()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findAndModify", + "string": "Collection.prototype.findAndModify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findOne", + "string": "Collection.prototype.findOne()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "find", + "string": "Collection.prototype.find()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "insert", + "string": "Collection.prototype.insert()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "save", + "string": "Collection.prototype.save()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "update", + "string": "Collection.prototype.update()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "getIndexes", + "string": "Collection.prototype.getIndexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "mapReduce", + "string": "Collection.prototype.mapReduce()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Collection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Collection", + "string": "module.exports" + } + } +] +### lib/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , assert =require('assert')", + "ctx": { + "type": "declaration", + "name": "url", + "value": "require('url')", + "string": "url" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Protocol prefix regexp.

    ", + "summary": "

    Protocol prefix regexp.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", + "ctx": { + "type": "declaration", + "name": "rgxProtocol", + "value": "/^(?:.)+:\\/\\//", + "string": "rgxProtocol" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "a mongoose instance" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." + }, + { + "type": "event", + "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." + }, + { + "type": "event", + "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." + }, + { + "type": "event", + "string": "`disconnecting`: Emitted when `connection.close()` was executed." + }, + { + "type": "event", + "string": "`disconnected`: Emitted after getting disconnected from the db." + }, + { + "type": "event", + "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." + }, + { + "type": "event", + "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." + }, + { + "type": "event", + "string": "`error`: Emitted when an error occurs on this connection." + }, + { + "type": "event", + "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", + "summary": "

    Connection constructor

    ", + "body": "

    For practical reasons, a Connection equals a Db.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", + "ctx": { + "type": "function", + "name": "Connection", + "string": "Connection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter

    ", + "summary": "

    Inherit from EventEmitter

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Connection", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Connection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readyState" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", + "summary": "

    Connection ready state

    ", + "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" + }, + { + "tags": [ + { + "type": "property", + "string": "collections" + } + ], + "description": { + "full": "

    A hash of the collections associated with this connection

    ", + "summary": "

    A hash of the collections associated with this connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collections;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    The mongodb.Db instance, set when the connection is opened

    ", + "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.db;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "connection_string", + "description": "mongodb://uri or the host to which you are connecting" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[port]", + "description": "database port" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n uri = url.parse(host);\n host = uri.hostname;\n port = uri.port || 27017;\n database = uri.pathname && uri.pathname.replace(/\\//g, '');\n }\n\n this.options = this.defaultOptions(options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing connection hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing connection database.'), callback);\n return this;\n }\n\n // handle authentication\n if (uri && uri.auth) {\n var auth = uri.auth.split(':');\n this.user = auth[0];\n this.pass = auth[1];\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n // user/pass options\n } else if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "open", + "string": "Connection.prototype.open()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "uris", + "description": "comma-separated mongodb:// `URI`s" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name if not included in `uris`" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "passed to the internal driver" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connects to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    ", + "summary": "

    Connects to a replica set.

    ", + "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n var uris = uris.split(',')\n , self = this;\n\n switch (arguments.length) {\n case 3:\n this.name = database;\n if ('function' === typeof options) callback = options, options = {};\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n this.options = options = this.defaultOptions(options);\n\n if (uris.length < 2) {\n this.error(new Error('Please provide comma-separated URIs'), callback);\n return this;\n }\n\n this.replica = true;\n this.host = [];\n this.port = [];\n\n uris.forEach(function (uri) {\n // handle missing protocols\n if (!rgxProtocol.test(uri))\n uri = 'mongodb://' + uri;\n\n var uri = url.parse(uri);\n\n self.host.push(uri.hostname);\n self.port.push(uri.port || 27017);\n\n if (!self.name && uri.pathname && uri.pathname.replace(/\\//g, ''))\n self.name = uri.pathname.replace(/\\//g, '');\n\n if (!self.user && uri.auth) {\n var auth = uri.auth.split(':');\n self.user = auth[0];\n self.pass = auth[1];\n }\n });\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "openSet", + "string": "Connection.prototype.openSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "optional" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", + "summary": "

    error

    ", + "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "error", + "string": "Connection.prototype.error()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "_open", + "string": "Connection.prototype._open()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection is opened

    ", + "summary": "

    Called when the connection is opened

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onOpen", + "string": "Connection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "self" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "close", + "string": "Connection.prototype.close()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onClose", + "string": "Connection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "of the collection" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional collection options" + }, + { + "type": "return", + "types": [ + "Collection" + ], + "description": "collection instance" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retrieves a collection, creating it if not cached.

    ", + "summary": "

    Retrieves a collection, creating it if not cached.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "collection", + "string": "Connection.prototype.collection()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "the model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "a schema. necessary when defining a model" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name of mongodb collection (optional) if not given it will be induced from model name" + }, + { + "type": "see", + "local": "Mongoose#model #index_Mongoose-model", + "visibility": "Mongoose#model" + }, + { + "type": "return", + "types": [ + "Model" + ], + "description": "The compiled model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    ", + "summary": "

    Defines or retrieves a model.

    ", + "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.model = function (name, schema, collection) {\n if (!this.models[name]) {\n var model = this.base.model(name, schema, collection, true)\n , Model\n\n if (this != model.prototype.db) {\n // subclass model using this connection and collection name\n Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model))\n return new Model(doc, fields, skipId);\n model.call(this, doc, fields, skipId);\n };\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = this;\n\n // collection name discovery\n if ('string' === typeof schema) {\n collection = schema;\n }\n\n if (!collection) {\n collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);\n }\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n Model.prototype.collection = this.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n }\n\n this.models[name] = Model || model;\n }\n\n return this.models[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "model", + "string": "Connection.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "level", + "description": "either off (0), slow (1), or all (2)" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[ms]", + "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Set profiling level.

    ", + "summary": "

    Set profiling level.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "setProfiling", + "string": "Connection.prototype.setProfiling()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Prepares default connection options.

    ", + "summary": "

    Prepares default connection options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.defaultOptions = function (options) {\n var o = options || {};\n\n o.server = o.server || {};\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n o.db || (o.db = {});\n o.db.forceServerObjectId = false;\n\n // TODO default to true once the driver is fixed\n if (!('safe' in o.db)) o.db.safe = false;\n\n return o;\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "defaultOptions", + "string": "Connection.prototype.defaultOptions()" + } + }, + { + "tags": [], + "description": { + "full": "

    Noop.

    ", + "summary": "

    Noop.

    ", + "body": "" + }, + "ignore": true, + "code": "function noop () {}", + "ctx": { + "type": "function", + "name": "noop", + "string": "noop()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", + "ctx": { + "type": "property", + "receiver": "Connection", + "name": "STATES", + "value": "STATES", + "string": "Connection.STATES" + } + } +] +### lib/connectionstate.js +[ + { + "tags": [], + "description": { + "full": "

    Connection states

    ", + "summary": "

    Connection states

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "module.exports = exports = Object.create(null)", + "string": "STATES" + } + } +] +### lib/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the values to set" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "the fields which were selected in the query returning this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "bool, should we auto create an ObjectId _id" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." + }, + { + "type": "event", + "string": "`save`: Emitted when the document is successfully saved" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document constructor.

    ", + "summary": "

    Document constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", + "ctx": { + "type": "function", + "name": "Document", + "string": "Document()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Document.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "schema" + } + ], + "description": { + "full": "

    The documents schema.

    ", + "summary": "

    The documents schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.schema;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "isNew" + } + ], + "description": { + "full": "

    Boolean flag specifying if the document is new.

    ", + "summary": "

    Boolean flag specifying if the document is new.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isNew;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "local": "Schema options /docs/guide.html#options", + "visibility": "Schema" + }, + { + "type": "property", + "string": "id" + } + ], + "description": { + "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", + "summary": "

    The string version of this documents _id.

    ", + "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.id;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "errors" + } + ], + "description": { + "full": "

    Hash containing current validation errors.

    ", + "summary": "

    Hash containing current validation errors.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.errors;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Builds the default doc structure

    ", + "summary": "

    Builds the default doc structure

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_buildDoc", + "string": "Document.prototype._buildDoc()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", + "summary": "

    Initializes the document without setters or marking anything modified.

    ", + "body": "

    Called internally after a document is returned from mongodb.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init');\n if (fn) fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "init", + "string": "Document.prototype.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "self", + "description": "document instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "raw mongodb doc" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "object we are initializing" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Init helper.

    ", + "summary": "

    Init helper.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", + "ctx": { + "type": "function", + "name": "init", + "string": "init()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", + "summary": "

    Stores the current values of the shard keys.

    ", + "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_storeShard", + "string": "Document.prototype._storeShard()" + } + }, + { + "tags": [], + "description": { + "full": "

    Set up middleware support

    ", + "summary": "

    Set up middleware support

    ", + "body": "" + }, + "ignore": true, + "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    ", + "summary": "

    Sends an update command with this document _id as the query selector.

    ", + "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "update", + "string": "Document.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "path", + "description": "path or object of key/vals to set" + }, + { + "type": "param", + "types": [ + "Any" + ], + "name": "val", + "description": "the value to set" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for \"on-the-fly\" attributes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    ", + "summary": "

    Sets the value of a path, or many paths.

    ", + "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.set = function (path, val, type) {\n var constructing = true === type\n , adhoc = type && true !== type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n if (null != path[key] && 'Object' === path[key].constructor.name\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n pathtype = this.schema.pathType(prefix + key);\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "set", + "string": "Document.prototype.set()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {\n if (this.isNew) {\n this.markModified(pathToMark);\n } else {\n\n priorVal || (priorVal = this.get(path));\n\n if (!this.isDirectModified(pathToMark)) {\n if (undefined === val && !this.isSelected(path)) {\n // special case:\n // when a path is not selected in a query its initial\n // value will be undefined.\n this.markModified(pathToMark, priorVal);\n } else if (undefined === val && path in this._activePaths.states.default) {\n // do nothing\n // unsetting the default value which was never saved\n } else if (!deepEqual(val, priorVal)) {\n this.markModified(pathToMark, priorVal);\n } else if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // special case:\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n this.markModified(pathToMark, priorVal);\n }\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_set", + "string": "Document.prototype._set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets a raw value from a path (no getters)

    ", + "summary": "

    Gets a raw value from a path (no getters)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "getValue", + "string": "Document.prototype.getValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "setValue", + "string": "Document.prototype.setValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for on-the-fly attributes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", + "summary": "

    Returns the value of a path.

    ", + "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "get", + "string": "Document.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns the schematype for the given path.

    ", + "summary": "

    Returns the schematype for the given path.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_path", + "string": "Document.prototype._path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to mark modified" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", + "summary": "

    Marks the path as having pending changes to write to the db.

    ", + "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "markModified", + "string": "Document.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "function to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope with which to call fn" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "try", + "string": "Document.prototype.try()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the list of paths that have been modified.

    ", + "summary": "

    Returns the list of paths that have been modified.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "modifiedPaths", + "string": "Document.prototype.modifiedPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", + "summary": "

    Returns true if this document was modified, else false.

    ", + "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isModified", + "string": "Document.prototype.isModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", + "summary": "

    Returns true if path was directly set and modified, else false.

    ", + "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isDirectModified", + "string": "Document.prototype.isDirectModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was initialized.

    ", + "summary": "

    Checks if path was initialized.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isInit", + "string": "Document.prototype.isInit()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", + "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", + "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isSelected", + "string": "Document.prototype.isSelected()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "cb", + "description": "called after validation completes, passing an error if one occurred" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", + "summary": "

    Executes registered validation rules for this document.

    ", + "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n paths = paths.concat(Object.keys(this._activePaths.states.default));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n cb(err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "validate", + "string": "Document.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "the error which states the reason `path` was invalid" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "invalidate", + "string": "Document.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Resets the internal modified state of this document.

    ", + "summary": "

    Resets the internal modified state of this document.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n })\n .forEach(function (array) {\n var i = array.length;\n while (i--) {\n var doc = array[i];\n if (!doc) continue;\n doc._reset();\n }\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_reset", + "string": "Document.prototype._reset()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns this documents dirty paths / vals.

    ", + "summary": "

    Returns this documents dirty paths / vals.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_dirty", + "string": "Document.prototype._dirty()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compiles schemas.

    ", + "summary": "

    Compiles schemas.

    ", + "body": "" + }, + "ignore": true, + "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", + "ctx": { + "type": "function", + "name": "compile", + "string": "compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Defines the accessor named prop on the incoming prototype.

    ", + "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", + "body": "" + }, + "ignore": true, + "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", + "ctx": { + "type": "function", + "name": "define", + "string": "define()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Assigns/compiles schema into this documents prototype.

    ", + "summary": "

    Assigns/compiles schema into this documents prototype.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_setSchema", + "string": "Document.prototype._setSchema()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register default hooks

    ", + "summary": "

    Register default hooks

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n if (error) return;\n\n // handle sparse arrays by using for loop vs array.forEach\n // which skips the sparse elements\n\n var len = array.length\n subdocs += len;\n\n for (var i = 0; i < len; ++i) {\n if (error) break;\n\n var doc = array[i];\n if (!doc) {\n --subdocs || next();\n continue;\n }\n\n doc.save(handleSave);\n }\n });\n\n function handleSave (err) {\n if (error) return;\n\n if (err) {\n self._validationError = undefined;\n return next(error = err);\n }\n\n --subdocs || next();\n }\n\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_registerHooks", + "string": "Document.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Registers an error

    ", + "summary": "

    Registers an error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_error", + "string": "Document.prototype._error()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes methods queued from the Schema definition

    ", + "summary": "

    Executes methods queued from the Schema definition

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_doQueue", + "string": "Document.prototype._doQueue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "js object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this document into a plain javascript object

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", + "summary": "

    Converts this document into a plain javascript object

    ", + "body": "

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    See schema options for details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toObject", + "string": "Document.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "json", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "either `virtuals` or `paths`" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "`json`" + } + ], + "description": { + "full": "

    Applies virtuals properties to json.

    ", + "summary": "

    Applies virtuals properties to json.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", + "ctx": { + "type": "function", + "name": "applyGetters", + "string": "applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "same options as `Document#toObject`" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "see", + "local": "Document#toObject #document_Document-toObject", + "visibility": "Document#toObject" + }, + { + "type": "", + "string": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    \n\n

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", + "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", + "body": "

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toJSON", + "string": "Document.prototype.toJSON()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "inspect", + "string": "Document.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "toString" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toString = Document.prototype.inspect;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "toString", + "value": "Document.prototype.inspect", + "string": "Document.prototypetoString" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "a document to compare" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", + "summary": "

    Returns true if the Document stores the same data as doc.

    ", + "body": "

    Documents are considered equal when they have matching _ids.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "equals", + "string": "Document.prototype.equals()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", + "ctx": { + "type": "property", + "receiver": "Document", + "name": "ValidationError", + "value": "ValidationError", + "string": "Document.ValidationError" + } + } +] +### lib/drivers/node-mongodb-native/binary.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require('mongodb').BSONPure.Binary", + "string": "Binary" + } + } +] +### lib/drivers/node-mongodb-native/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", + "ctx": { + "type": "declaration", + "name": "MongooseCollection", + "value": "require('../../collection')", + "string": "MongooseCollection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Collection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", + "summary": "

    A node-mongodb-native collection implementation.

    ", + "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", + "ctx": { + "type": "function", + "name": "NativeCollection", + "string": "NativeCollection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from abstract Collection.

    ", + "summary": "

    Inherit from abstract Collection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "__proto__", + "value": "MongooseCollection.prototype", + "string": "NativeCollection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection opens.

    ", + "summary": "

    Called when the connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onOpen", + "string": "NativeCollection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onClose", + "string": "NativeCollection.prototype.onClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Copy the collection methods and make them subject to queues

    ", + "summary": "

    Copy the collection methods and make them subject to queues

    ", + "body": "" + }, + "ignore": true, + "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", + "ctx": { + "type": "function", + "name": "print", + "string": "print()" + } + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if ('Date' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", + "ctx": { + "type": "function", + "name": "format", + "string": "format()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "method", + "string": "getIndexes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retreives information about this collections indexes.

    ", + "summary": "

    Retreives information about this collections indexes.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "getIndexes", + "value": "NativeCollection.prototype.indexInformation", + "string": "NativeCollection.prototypegetIndexes" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeCollection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeCollection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", + "ctx": { + "type": "declaration", + "name": "MongooseConnection", + "value": "require('../../connection')", + "string": "MongooseConnection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Connection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native connection implementation.

    ", + "summary": "

    A node-mongodb-native connection implementation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", + "ctx": { + "type": "function", + "name": "NativeConnection", + "string": "NativeConnection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Connection.

    ", + "summary": "

    Inherits from Connection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeConnection", + "name": "__proto__", + "value": "MongooseConnection.prototype", + "string": "NativeConnection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, Number(this.port), this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpen", + "string": "NativeConnection.prototype.doOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", + "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", + "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , ports = this.port\n , self = this\n\n this.host.forEach(function (host, i) {\n servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));\n });\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpenSet", + "string": "NativeConnection.prototype.doOpenSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doClose", + "string": "NativeConnection.prototype.doClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeConnection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeConnection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/objectid.js +[ + { + "tags": [ + { + "type": "constructor", + "string": "NodeMongoDbObjectId" + }, + { + "type": "see", + "local": "ObjectId", + "visibility": "ObjectId" + } + ], + "description": { + "full": "

    node-mongodb-native ObjectId

    ", + "summary": "

    node-mongodb-native ObjectId

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require('mongodb').BSONPure.ObjectID", + "string": "ObjectId" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", + "ctx": { + "type": "declaration", + "name": "ObjectIdToString", + "value": "ObjectId.toString.bind(ObjectId)", + "string": "ObjectIdToString" + } + } +] +### lib/error.js +[ + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" + } + ], + "description": { + "full": "

    Mongoose error

    ", + "summary": "

    Mongoose error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", + "ctx": { + "type": "function", + "name": "MongooseError", + "string": "MongooseError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Error.

    ", + "summary": "

    Inherits from Error.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseError.prototype.__proto__ = Error.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseError", + "name": "__proto__", + "value": "Error.prototype", + "string": "MongooseError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseError", + "string": "module.exports" + } + } +] +### lib/errors/cast.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casting Error constructor.

    ", + "summary": "

    Casting Error constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", + "ctx": { + "type": "function", + "name": "CastError", + "string": "CastError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "CastError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "CastError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "CastError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = CastError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "CastError", + "string": "module.exports" + } + } +] +### lib/errors/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document Error

    ", + "summary": "

    Document Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", + "ctx": { + "type": "function", + "name": "DocumentError", + "string": "DocumentError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "DocumentError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = DocumentError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = DocumentError", + "string": "module.exports" + } + } +] +### lib/errors/validation.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "instance", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    Document Validation Error

    ", + "summary": "

    Document Validation Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", + "ctx": { + "type": "function", + "name": "ValidationError", + "string": "ValidationError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Console.log helper

    ", + "summary": "

    Console.log helper

    ", + "body": "" + }, + "ignore": false, + "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", + "ctx": { + "type": "method", + "constructor": "ValidationError", + "name": "toString", + "string": "ValidationError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidationError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidationError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = ValidationError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = ValidationError", + "string": "module.exports" + } + } +] +### lib/errors/validator.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Schema validator error

    ", + "summary": "

    Schema validator error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", + "ctx": { + "type": "function", + "name": "ValidatorError", + "string": "ValidatorError()" + } + }, + { + "tags": [], + "description": { + "full": "

    toString helper

    ", + "summary": "

    toString helper

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", + "ctx": { + "type": "method", + "constructor": "ValidatorError", + "name": "toString", + "string": "ValidatorError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError

    ", + "summary": "

    Inherits from MongooseError

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidatorError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidatorError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ValidatorError", + "string": "module.exports" + } + } +] +### lib/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", + "summary": "

    Mongoose constructor.

    ", + "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", + "ctx": { + "type": "function", + "name": "Mongoose", + "string": "Mongoose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", + "summary": "

    Sets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "set", + "string": "Mongoose.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "method", + "string": "get" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", + "summary": "

    Gets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.get = Mongoose.prototype.set;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "get", + "value": "Mongoose.prototype.set", + "string": "Mongoose.prototypeget" + } + }, + { + "tags": [], + "description": { + "full": "

    ReplSet connection string check.

    ", + "summary": "

    ReplSet connection string check.

    ", + "body": "" + }, + "ignore": true, + "code": "var rgxReplSet = /^.+,.+$/;", + "ctx": { + "type": "declaration", + "name": "rgxReplSet", + "value": "/^.+,.+$/", + "string": "rgxReplSet" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[uri]", + "description": "a mongodb:// URI" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options to pass to the driver" + }, + { + "type": "see", + "local": "Connection#open #connection_Connection-open", + "visibility": "Connection#open" + }, + { + "type": "see", + "local": "Connection#openSet #connection_Connection-openSet", + "visibility": "Connection#openSet" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "the created Connection object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Connection instance.

    \n\n

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    ", + "summary": "

    Creates a Connection instance.

    ", + "body": "

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "createConnection", + "string": "Mongoose.prototype.createConnection()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Mongoose#createConnection #index_Mongoose-createConnection", + "visibility": "Mongoose#createConnection" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    ", + "summary": "

    Opens the default mongoose connection.

    ", + "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "connect", + "string": "Mongoose.prototype.connect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "called after all connection close." + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Disconnects all connections.

    ", + "summary": "

    Disconnects all connections.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "disconnect", + "string": "Mongoose.prototype.disconnect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name (optional, induced from model name)" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipInit]", + "description": "whether to skip initialization (defaults to false)" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    ", + "summary": "

    Defines a model or retrieves it.

    ", + "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n // normalize collection\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // look up models for the collection\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n this.modelSchemas[name] = schema;\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n } else {\n throw new Error('Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)');\n }\n }\n\n if (!this.models[name]) {\n schema || (schema = this.modelSchemas[name]);\n collection || (collection = schema.set('collection') || format(name));\n\n var model = Model.compile(name\n , this.modelSchemas[name]\n , collection\n , this.connection\n , this);\n\n if (!skipInit) model.init();\n\n this.models[name] = model;\n }\n\n return this.models[name];\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "model", + "string": "Mongoose.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "plugin callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "optional options" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", + "summary": "

    Declares a global plugin executed on all Schemas.

    ", + "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "plugin", + "string": "Mongoose.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "connection" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", + "summary": "

    The default connection of the mongoose module.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" + }, + { + "tags": [], + "description": { + "full": "

    Driver depentend APIs

    ", + "summary": "

    Driver depentend APIs

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Connection

    ", + "summary": "

    Connection

    ", + "body": "" + }, + "ignore": true, + "code": "var Connection = require(driver + '/connection');", + "ctx": { + "type": "declaration", + "name": "Connection", + "value": "require(driver + '/connection')", + "string": "Connection" + } + }, + { + "tags": [], + "description": { + "full": "

    Collection

    ", + "summary": "

    Collection

    ", + "body": "" + }, + "ignore": true, + "code": "var Collection = require(driver + '/collection');", + "ctx": { + "type": "declaration", + "name": "Collection", + "value": "require(driver + '/collection')", + "string": "Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The exports object is an instance of Mongoose.

    ", + "summary": "

    The exports object is an instance of Mongoose.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = new Mongoose", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Collection constructor

    ", + "summary": "

    The Mongoose Collection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Collection = Collection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Collection", + "value": "Collection", + "string": "mongoose.Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Connection constructor

    ", + "summary": "

    The Mongoose Connection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Connection = Connection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Connection", + "value": "Connection", + "string": "mongoose.Connection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose version

    ", + "summary": "

    Mongoose version

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "version", + "value": "JSON.parse(", + "string": "mongoose.version" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", + "summary": "

    The Mongoose constructor

    ", + "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Mongoose = Mongoose;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Mongoose", + "value": "Mongoose", + "string": "mongoose.Mongoose" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", + "summary": "

    The Mongoose Schema constructor

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Schema = Schema;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Schema", + "value": "Schema", + "string": "mongoose.Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose SchemaType constructor.

    ", + "summary": "

    The Mongoose SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaType = SchemaType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaType", + "value": "SchemaType", + "string": "mongoose.SchemaType" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Schema.SchemaTypes #schema_Schema-Types", + "visibility": "Schema.SchemaTypes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", + "summary": "

    The various Mongoose SchemaTypes.

    ", + "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaTypes = Schema.Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaTypes", + "value": "Schema.Types", + "string": "mongoose.SchemaTypes" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose VirtualType constructor.

    ", + "summary": "

    The Mongoose VirtualType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.VirtualType = VirtualType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "VirtualType", + "value": "VirtualType", + "string": "mongoose.VirtualType" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", + "summary": "

    The various Mongoose Types.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Types = Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Types", + "value": "Types", + "string": "mongoose.Types" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Query constructor.

    ", + "summary": "

    The Mongoose Query constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Query = Query;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Query", + "value": "Query", + "string": "mongoose.Query" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Promise constructor.

    ", + "summary": "

    The Mongoose Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Promise = Promise;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Promise", + "value": "Promise", + "string": "mongoose.Promise" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Model constructor.

    ", + "summary": "

    The Mongoose Model constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Model = Model;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Model", + "value": "Model", + "string": "mongoose.Model" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Document constructor.

    ", + "summary": "

    The Mongoose Document constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Document = Document;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Document", + "value": "Document", + "string": "mongoose.Document" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The MongooseError constructor.

    ", + "summary": "

    The MongooseError constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Error = require('./error');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Error", + "value": "require('./error')", + "string": "mongoose.Error" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The node-mongodb-native driver Mongoose uses.

    ", + "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.mongo = require('mongodb');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "mongo", + "value": "require('mongodb')", + "string": "mongoose.mongo" + } + } +] +### lib/model.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('./document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "values to with which to create the document" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "event", + "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." + }, + { + "type": "event", + "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Model constructor

    ", + "summary": "

    Model constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", + "ctx": { + "type": "function", + "name": "Model", + "string": "Model()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Document.

    ", + "summary": "

    Inherits from Document.

    ", + "body": "" + }, + "ignore": true, + "code": "Model.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "Model", + "name": "__proto__", + "value": "Document.prototype", + "string": "Model.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    Connection the model uses.

    ", + "summary": "

    Connection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.db;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "collection" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.collection;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "modelName" + } + ], + "description": { + "full": "

    The name of the model

    ", + "summary": "

    The name of the model

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.modelName;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "object" + }, + { + "type": "return", + "types": [ + "Object", + "undefined" + ], + "description": "population paths" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns what paths can be populated

    ", + "summary": "

    Returns what paths can be populated

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_getPopulationKeys", + "string": "Model.prototype._getPopulationKeys()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "schema", + "description": "type for the oid" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "oid", + "description": "object id or array of object ids" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "query", + "description": "object specifying query conditions, fields, and options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Populates an object

    ", + "summary": "

    Populates an object

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_populate", + "string": "Model.prototype._populate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "query that originated the initialization" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs auto-population of relations.

    ", + "summary": "

    Performs auto-population of relations.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "init", + "string": "Model.prototype.init()" + } + }, + { + "tags": [], + "description": { + "full": "

    Handles doc.save() callbacks

    ", + "summary": "

    Handles doc.save() callbacks

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new Error('No matching document found.'));\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", + "ctx": { + "type": "function", + "name": "handleSave", + "string": "handleSave()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "title": "middleware", + "url": "http://mongoosejs.com/docs/middleware.html", + "visibility": "http://mongoosejs.com/docs/middleware.html" + } + ], + "description": { + "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", + "summary": "

    Saves this document.

    ", + "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n complete(null);\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "save", + "string": "Model.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Mixed" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[operation]", + "description": "" + } + ], + "description": { + "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", + "ctx": { + "type": "function", + "name": "operand", + "string": "operand()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "val", + "description": "" + } + ], + "description": { + "full": "

    Compiles an update and where clause for a val with _atomics.

    ", + "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", + "ctx": { + "type": "function", + "name": "handleAtomics", + "string": "handleAtomics()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a special query document of the modified properties used in updates.

    ", + "summary": "

    Produces a special query document of the modified properties used in updates.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_delta", + "string": "Model.prototype._delta()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Appends versioning to the where and update clauses.

    ", + "summary": "

    Appends versioning to the where and update clauses.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_version", + "string": "Model.prototype._version()" + } + }, + { + "tags": [ + { + "type": "see", + "title": "versionKeys", + "url": "http://mongoosejs.com/docs/guide.html#versionKey", + "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Signal that we desire an increment of this documents version.

    ", + "summary": "

    Signal that we desire an increment of this documents version.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "increment", + "string": "Model.prototype.increment()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns a query object which applies shardkeys if they exist.

    ", + "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_where", + "string": "Model.prototype._where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", + "summary": "

    Removes this document from the db.

    ", + "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) return this;\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "remove", + "string": "Model.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register hooks override

    ", + "summary": "

    Register hooks override

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_registerHooks", + "string": "Model.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", + "summary": "

    Returns another Model instance.

    ", + "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "model", + "string": "Model.prototype.model()" + } + }, + { + "tags": [ + { + "type": "TODO", + "string": "determine if this is still necessary" + } + ], + "description": { + "full": "

    Give the constructor the ability to emit events.

    ", + "summary": "

    Give the constructor the ability to emit events.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the model compiles.

    ", + "summary": "

    Called when the model compiles.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.init = function init () {\n if (this.schema.options.autoIndex)\n this.ensureIndexes();\n\n this.schema.emit('init', this);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "init", + "string": "Model.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[cb]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    ", + "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", + "body": "

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "ensureIndexes", + "string": "Model.ensureIndexes()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "schema" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema the model uses.

    ", + "summary": "

    Schema the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.schema;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Database instance the model uses.

    ", + "summary": "

    Database instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.db;" + }, + { + "tags": [ + { + "type": "property", + "string": "collection" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.collection;" + }, + { + "tags": [ + { + "type": "property", + "string": "base" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Base Mongoose instance the model uses.

    ", + "summary": "

    Base Mongoose instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.base;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes documents from the collection.

    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    ", + "summary": "

    Removes documents from the collection.

    ", + "body": "

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "remove", + "string": "Model.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents

    \n\n

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    ", + "summary": "

    Finds documents

    ", + "body": "

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "find", + "string": "Model.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges the current named scope query into query.

    ", + "summary": "

    Merges the current named scope query into query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "_applyNamedScope", + "string": "Model._applyNamedScope()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "objectid, or a value that can be casted to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds a single document by id.

    \n\n

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    ", + "summary": "

    Finds a single document by id.

    ", + "body": "

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findById", + "string": "Model.findById()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    ", + "summary": "

    Finds one document.

    ", + "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n // TODO Handle all 3 of the following scenarios\n // Hint: Only some of these scenarios are possible if cQuery is present\n // Scenario: findOne(conditions, fields, callback);\n // Scenario: findOne(fields, options, callback);\n // Scenario: findOne(conditions, options, callback);\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n // TODO Handle all 2 of the following scenarios\n // Scenario: findOne(conditions, callback)\n // Scenario: findOne(fields, callback)\n // Scenario: findOne(options, callback);\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOne", + "string": "Model.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", + "summary": "

    Counts number of matching documents in a database collection.

    ", + "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "count", + "string": "Model.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a DISTINCT command

    ", + "summary": "

    Executes a DISTINCT command

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "distinct", + "string": "Model.distinct()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "optional value" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", + "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", + "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "where", + "string": "Model.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "argument", + "description": "is a javascript string or anonymous function" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "memberOf", + "parent": "Model" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Query.$where #query_Query-%24where", + "visibility": "Query.$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    ", + "summary": "

    Creates a Query and specifies a $where condition.

    ", + "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndUpdate", + "string": "Model.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "an ObjectId or string that can be cast to one." + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", + "visibility": "Model.findOneAndUpdate" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndUpdate", + "string": "Model.findByIdAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndRemove", + "string": "Model.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "id", + "description": "ObjectId or string that can be cast to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", + "visibility": "Model.findOneAndRemove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndRemove", + "string": "Model.findByIdAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array", + "Object..." + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", + "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", + "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "create", + "string": "Model.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "update", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Updates documents in the database without returning them.

    ", + "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "update", + "string": "Model.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "o", + "description": "an object specifying map-reduce options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/MapReduce", + "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", + "summary": "

    Executes a mapReduce command.

    ", + "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "mapReduce", + "string": "Model.mapReduce()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "an array of pipeline commands" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "aggregation", + "url": "http://docs.mongodb.org/manual/applications/aggregation/", + "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", + "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes an aggregate command on this models collection.

    \n\n

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    ", + "summary": "

    Executes an aggregate command on this models collection.

    ", + "body": "

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "aggregate", + "string": "Model.aggregate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "collectionName", + "description": "" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "connection", + "description": "" + }, + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "mongoose instance" + } + ], + "description": { + "full": "

    Compiler utility.

    ", + "summary": "

    Compiler utility.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "compile", + "string": "Model.compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Model;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Model", + "string": "module.exports" + } + } +] +### lib/namedscope.js +[ + { + "tags": [ + { + "type": "param", + "types": [ + "NamedScope" + ], + "name": "target", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "getters", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Decorate

    ", + "summary": "

    Decorate

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", + "ctx": { + "type": "method", + "constructor": "NamedScope", + "name": "decorate", + "string": "NamedScope.prototype.decorate()" + } + } +] +### lib/promise.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", + "ctx": { + "type": "declaration", + "name": "util", + "value": "require('./utils')", + "string": "util" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "back", + "description": "a callback+errback that accepts `fn(err, ...){}` as signature" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`err`: Emits when the promise resolves to an error." + }, + { + "type": "event", + "string": "`complete`: Emits when the promise resolves sucessfully." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Promise constructor.

    ", + "summary": "

    Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", + "ctx": { + "type": "function", + "name": "Promise", + "string": "Promise()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from EventEmitter.

    ", + "summary": "

    Inherits from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Promise", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Promise.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Event" + ], + "name": "event", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds listener to the event.

    \n\n

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", + "summary": "

    Adds listener to the event.

    ", + "body": "

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "on", + "string": "Promise.prototype.on()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Keeps track of emitted events to run them on on.

    ", + "summary": "

    Keeps track of emitted events to run them on on.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "emit", + "string": "Promise.prototype.emit()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for emitting the complete event.

    ", + "summary": "

    Shortcut for emitting the complete event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "complete", + "string": "Promise.prototype.complete()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Shortcut for emitting the err event.

    ", + "summary": "

    Shortcut for emitting the err event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "error", + "string": "Promise.prototype.error()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('complete', fn).

    ", + "summary": "

    Shortcut for .on('complete', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addCallback", + "string": "Promise.prototype.addCallback()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('err', fn).

    ", + "summary": "

    Shortcut for .on('err', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addErrback", + "string": "Promise.prototype.addErrback()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Adds a single function that's both a callback and errback.

    ", + "summary": "

    Adds a single function that's both a callback and errback.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addBack", + "string": "Promise.prototype.addBack()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "optional error or null" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "value to complete the promise with" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "summary": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "resolve", + "string": "Promise.prototype.resolve()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Promise;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Promise", + "string": "module.exports" + } + } +] +### lib/query.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "criteria", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", + "summary": "

    Query constructor used for building queries.

    ", + "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n if (criteria) this.find(criteria);\n}", + "ctx": { + "type": "function", + "name": "Query", + "string": "Query()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", + "summary": "

    Sets query options.

    ", + "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "setOptions", + "string": "Query.prototype.setOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "the model to which the query is bound" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "the operation to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "updateArg", + "description": "used in update methods" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Binds this query to a model.

    ", + "summary": "

    Binds this query to a model.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "bind", + "string": "Query.prototype.bind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "[operation]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", + "summary": "

    Executes the query

    ", + "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exec", + "string": "Query.prototype.exec()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[criteria]", + "description": "mongodb selector" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", + "summary": "

    Finds documents.

    ", + "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "find", + "string": "Query.prototype.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[obj]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", + "summary": "

    Casts this query to the schema of model

    ", + "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "cast", + "string": "Query.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options.

    ", + "summary": "

    Returns default options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_optionsForExec", + "string": "Query.prototype._optionsForExec()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies schematype selected options to this query.

    ", + "summary": "

    Applies schematype selected options to this query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_applyPaths", + "string": "Query.prototype._applyPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "js", + "description": "javascript string or function" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", + "summary": "

    Specifies a $where condition

    ", + "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", + "summary": "

    Specifies a path for use with chaining.

    ", + "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "where", + "string": "Query.prototype.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", + "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", + "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "equals", + "string": "Query.prototype.equals()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", + "summary": "

    Specifies arguments for an $or condition.

    ", + "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "or", + "string": "Query.prototype.or()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", + "summary": "

    Specifies arguments for a $nor condition.

    ", + "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nor", + "string": "Query.prototype.nor()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "gt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", + "summary": "

    Specifies a $gt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "gte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $gte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "ne" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $ne query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "in" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $in query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "nin" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $nin query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "all" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $all query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "size" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $size query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "regex" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $regex query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxDistance" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $maxDistance query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", + "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", + "body": "
    Thing.where('type').nin(array)\n
    " + }, + "ignore": true, + "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $near condition

    ", + "summary": "

    Specifies a $near condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "near", + "string": "Query.prototype.near()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $nearSphere condition.

    ", + "summary": "

    Specifies a $nearSphere condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nearSphere", + "string": "Query.prototype.nearSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $mod condition

    ", + "summary": "

    Specifies a $mod condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "mod", + "string": "Query.prototype.mod()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $exists condition

    ", + "summary": "

    Specifies an $exists condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exists", + "string": "Query.prototype.exists()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object", + "Function" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "Function" + ], + "name": "criteria", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", + "summary": "

    Specifies an $elemMatch condition

    ", + "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "elemMatch", + "string": "Query.prototype.elemMatch()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "within" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Syntax sugar for expressive queries.

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    ", + "summary": "

    Syntax sugar for expressive queries.

    ", + "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "see", + "local": "Query#within #query_Query-within", + "visibility": "Query#within" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", + "summary": "

    Specifies a $box condition

    ", + "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "box", + "string": "Query.prototype.box()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "options e.g. { $uniqueDocs: true }" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", + "summary": "

    Specifies a $center condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "center", + "string": "Query.prototype.center()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", + "summary": "

    Specifies a $centerSphere condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "centerSphere", + "string": "Query.prototype.centerSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Array", + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", + "summary": "

    Specifies a $polygon condition

    ", + "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "polygon", + "string": "Query.prototype.polygon()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "local": "SchemaType", + "visibility": "SchemaType" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    ", + "summary": "

    Specifies which document fields to include or exclude

    ", + "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "select", + "string": "Query.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "number of elements to slice" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", + "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", + "summary": "

    Specifies a $slice condition

    ", + "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slice", + "string": "Query.prototype.slice()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", + "summary": "

    Sets the sort order

    ", + "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "sort", + "string": "Query.prototype.sort()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", + "ctx": { + "type": "function", + "name": "push", + "string": "push()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "limit" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", + "summary": "

    Specifies the limit option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "skip" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", + "summary": "

    Specifies the skip option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxscan" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", + "summary": "

    Specifies the maxscan option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "batchSize" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", + "summary": "

    Specifies the batchSize option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "comment" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", + "summary": "

    Specifies the comment option.

    ", + "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", + "summary": "

    limit, skip, maxscan, batchSize, comment

    ", + "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " + }, + "ignore": true, + "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", + "summary": "

    Specifies this query as a snapshot query.

    ", + "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "snapshot", + "string": "Query.prototype.snapshot()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "a hint object" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", + "summary": "

    Sets query hints.

    ", + "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "hint", + "string": "Query.prototype.hint()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", + "summary": "

    Sets the slaveOk option.

    ", + "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slaveOk", + "string": "Query.prototype.slaveOk()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "one of the listed preference options or their aliases" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "[tags]", + "description": "optional tags for this query" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", + "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the readPreference option for the query.

    \n\n

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    ", + "summary": "

    Sets the readPreference option for the query.

    ", + "body": "

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "read", + "string": "Query.prototype.read()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", + "summary": "

    Sets the lean option.

    ", + "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "lean", + "string": "Query.prototype.lean()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", + "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", + "summary": "

    Sets tailable option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "tailable", + "string": "Query.prototype.tailable()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes the query as a find() operation.

    ", + "summary": "

    Executes the query as a find() operation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "execFind", + "string": "Query.prototype.execFind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", + "summary": "

    Executes the query as a findOne() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOne", + "string": "Query.prototype.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", + "summary": "

    Exectues the query as a count() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "count", + "string": "Query.prototype.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a distict() operation.

    ", + "summary": "

    Executes this query as a distict() operation.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "distinct", + "string": "Query.prototype.distinct()" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "body": "" + }, + "ignore": true, + "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", + "ctx": { + "type": "declaration", + "name": "castOps", + "value": "{", + "string": "castOps" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "body": "" + }, + "ignore": true, + "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", + "ctx": { + "type": "declaration", + "name": "numberOps", + "value": "{", + "string": "numberOps" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "the update conditions" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", + "summary": "

    Executes this query as an update() operation.

    ", + "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n delete options.safe;\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "update", + "string": "Query.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "obj after casting its values" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts obj for an update command.

    ", + "summary": "

    Casts obj for an update command.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdate", + "string": "Query.prototype._castUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "- part of a query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "- path prefix (internal only)" + }, + { + "type": "return", + "types": [ + "Bool" + ], + "description": "true if this path has keys to update" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_walkUpdatePath", + "string": "Query.prototype._walkUpdatePath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[$conditional]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val according to schema and atomic op.

    ", + "summary": "

    Casts val according to schema and atomic op.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdateVal", + "string": "Query.prototype._castUpdateVal()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_getSchema", + "string": "Query.prototype._getSchema()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "https://github.com/LearnBoost/mongoose/issues/1091", + "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" + }, + { + "type": "see", + "title": "", + "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", + "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts selected field arguments for field selection with mongo 2.2

    \n\n
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    ", + "summary": "

    Casts selected field arguments for field selection with mongo 2.2

    ", + "body": "
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castFields", + "string": "Query.prototype._castFields()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", + "summary": "

    Executes this query as a remove() operation.

    ", + "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n delete options.safe;\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "remove", + "string": "Query.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[query]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[doc]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndUpdate", + "string": "Query.prototype.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndRemove", + "string": "Query.prototype.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "- either \"remove\" or \"update\"" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    _findAndModify

    ", + "summary": "

    _findAndModify

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_findAndModify", + "string": "Query.prototype._findAndModify()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Model" + ], + "name": "[model]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "see", + "local": "population ./populate.html", + "visibility": "population" + }, + { + "type": "see", + "local": "Query#select #query_Query-select", + "visibility": "Query#select" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    ", + "summary": "

    Specifies paths which should be populated with other documents.

    ", + "body": "

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "populate", + "string": "Query.prototype.populate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Populate options constructor

    ", + "summary": "

    Populate options constructor

    ", + "body": "" + }, + "ignore": true, + "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", + "ctx": { + "type": "function", + "name": "PopulateOptions", + "string": "PopulateOptions()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "QueryStream" + ], + "description": "" + }, + { + "type": "see", + "local": "QueryStream", + "visibility": "QueryStream" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a stream interface

    \n\n

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    ", + "summary": "

    Returns a stream interface

    ", + "body": "

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "stream", + "string": "Query.prototype.stream()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castDoc

    ", + "summary": "

    castDoc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castDoc", + "string": "castDoc()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castQuery

    ", + "summary": "

    castQuery

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castQuery", + "string": "castQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Exports.

    ", + "summary": "

    Exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Query", + "string": "module.exports" + } + } +] +### lib/querystream.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", + "ctx": { + "type": "declaration", + "name": "Stream", + "value": "require('stream').Stream", + "string": "Stream" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS Stream http://nodejs.org/api/stream.html" + }, + { + "type": "event", + "string": "`data`: emits a single Mongoose document" + }, + { + "type": "event", + "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." + }, + { + "type": "event", + "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Provides a ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    ", + "summary": "

    Provides a ReadStream interface for Queries.

    ", + "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n this._running = false;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", + "ctx": { + "type": "function", + "name": "QueryStream", + "string": "QueryStream()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Stream

    ", + "summary": "

    Inherit from Stream

    ", + "body": "" + }, + "ignore": true, + "code": "QueryStream.prototype.__proto__ = Stream.prototype;", + "ctx": { + "type": "property", + "constructor": "QueryStream", + "name": "__proto__", + "value": "Stream.prototype", + "string": "QueryStream.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readable" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is readable.

    ", + "summary": "

    Flag stating whether or not this stream is readable.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.readable;" + }, + { + "tags": [ + { + "type": "property", + "string": "paused" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is paused.

    ", + "summary": "

    Flag stating whether or not this stream is paused.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the query.

    ", + "summary": "

    Initializes the query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_init", + "string": "QueryStream.prototype._init()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#__next #querystream_QueryStream-__next", + "visibility": "QueryStream#__next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Trampoline for pulling the next doc from cursor.

    ", + "summary": "

    Trampoline for pulling the next doc from cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) {\n return this._running = false;\n }\n\n this._running = true;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n while (this.__next()) {}\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_next", + "string": "QueryStream.prototype._next()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#_next #querystream_QueryStream-_next", + "visibility": "QueryStream#_next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pulls the next doc from the cursor.

    ", + "summary": "

    Pulls the next doc from the cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed)\n return this._running = false;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "__next", + "string": "QueryStream.prototype.__next()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error", + "null" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return this._running = false;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && true === this.query.options.lean) {\n this.emit('data', doc);\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_onNextObject", + "string": "QueryStream.prototype._onNextObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pauses this stream.

    ", + "summary": "

    Pauses this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "pause", + "string": "QueryStream.prototype.pause()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Resumes this stream.

    ", + "summary": "

    Resumes this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n\n if (!this._cursor) {\n // cannot start if not initialized\n return;\n }\n\n // are we within the trampoline?\n if (T_INIT === this._inline) {\n return;\n }\n\n if (!this._running) {\n // outside QueryStream control, need manual restart\n return this._next();\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "resume", + "string": "QueryStream.prototype.resume()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "[err]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this._running = false;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "destroy", + "string": "QueryStream.prototype.destroy()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "pipe" + }, + { + "type": "memberOf", + "parent": "QueryStream" + }, + { + "type": "see", + "title": "NodeJS", + "url": "http://nodejs.org/api/stream.html", + "visibility": "http://nodejs.org/api/stream.html" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", + "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", + "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = QueryStream", + "string": "module.exports" + } + } +] +### lib/schema/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Array SchemaType constructor

    ", + "summary": "

    Array SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "SchemaArray", + "string": "SchemaArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaArray", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "checkRequired", + "string": "SchemaArray.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides the getters application for the population special-case

    ", + "summary": "

    Overrides the getters application for the population special-case

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "applyGetters", + "string": "SchemaArray.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "cast", + "string": "SchemaArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "castForQuery", + "string": "SchemaArray.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': SchemaArray.prototype.castForQuery\n , '$gte': SchemaArray.prototype.castForQuery\n , '$lt': SchemaArray.prototype.castForQuery\n , '$lte': SchemaArray.prototype.castForQuery\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", + "ctx": { + "type": "function", + "name": "castToNumber", + "string": "castToNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaArray", + "string": "module.exports" + } + } +] +### lib/schema/boolean.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Boolean SchemaType constructor.

    ", + "summary": "

    Boolean SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaBoolean", + "string": "SchemaBoolean()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBoolean", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBoolean.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "checkRequired", + "string": "SchemaBoolean.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to boolean

    ", + "summary": "

    Casts to boolean

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "cast", + "string": "SchemaBoolean.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", + "ctx": { + "type": "function", + "name": "handleArray", + "string": "handleArray()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "castForQuery", + "string": "SchemaBoolean.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBoolean;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBoolean", + "string": "module.exports" + } + } +] +### lib/schema/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Buffer SchemaType constructor

    ", + "summary": "

    Buffer SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", + "ctx": { + "type": "function", + "name": "SchemaBuffer", + "string": "SchemaBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBuffer", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBuffer.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "checkRequired", + "string": "SchemaBuffer.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "cast", + "string": "SchemaBuffer.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "castForQuery", + "string": "SchemaBuffer.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBuffer;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBuffer", + "string": "module.exports" + } + } +] +### lib/schema/date.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date SchemaType constructor.

    ", + "summary": "

    Date SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaDate", + "string": "SchemaDate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaDate", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaDate.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for date

    ", + "summary": "

    Required validator for date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "checkRequired", + "string": "SchemaDate.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to date

    ", + "summary": "

    Casts to date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "cast", + "string": "SchemaDate.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date Query casting.

    ", + "summary": "

    Date Query casting.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "castForQuery", + "string": "SchemaDate.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaDate;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaDate", + "string": "module.exports" + } + } +] +### lib/schema/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaArray" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    SubdocsArray SchemaType constructor

    ", + "summary": "

    SubdocsArray SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "DocumentArray", + "string": "DocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from ArrayType.

    ", + "summary": "

    Inherits from ArrayType.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentArray", + "name": "__proto__", + "value": "ArrayType.prototype", + "string": "DocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs local validations first, then validations on each embedded doc

    ", + "summary": "

    Performs local validations first, then validations on each embedded doc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n\n SchemaType.prototype.doValidate.call(this, array, function (err) {\n if (err) return fn(err);\n\n var count = array && array.length\n , error;\n\n if (!count) return fn();\n\n // handle sparse arrays, do not use array.forEach which does not\n // iterate over sparse elements yet reports array.length including\n // them :(\n\n for (var i = 0, len = count; i < len; ++i) {\n // sidestep sparse entries\n var doc = array[i];\n if (!doc) {\n --count || fn();\n continue;\n }\n\n ;(function (i) {\n doc.validate(function (err) {\n if (err && !error) {\n // rewrite the key\n err.key = self.key + '.' + i + '.' + err.key;\n return fn(error = err);\n }\n --count || fn();\n });\n })(i);\n }\n }, scope);\n};", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "doValidate", + "string": "DocumentArray.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "document", + "description": "that triggers the casting" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument) && value[i]) {\n if (init) {\n selected || (selected = scopePaths(this, doc._selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "cast", + "string": "DocumentArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "DocumentArray" + ], + "name": "array", + "description": "- the array to scope `fields` paths" + }, + { + "type": "param", + "types": [ + "Object", + "undefined" + ], + "name": "fields", + "description": "- the root fields selected in the query" + }, + { + "type": "param", + "types": [ + "Boolean", + "undefined" + ], + "name": "init", + "description": "- if we are being created part of a query result" + } + ], + "description": { + "full": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "summary": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , hasKeys\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n hasKeys || (hasKeys = true);\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return hasKeys && selected || undefined;\n}", + "ctx": { + "type": "function", + "name": "scopePaths", + "string": "scopePaths()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = DocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "DocumentArray", + "string": "module.exports" + } + } +] +### lib/schema/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "String", + "value": "require('./string')", + "string": "exports.String" + } + } +] +### lib/schema/mixed.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Mixed SchemaType constructor.

    ", + "summary": "

    Mixed SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "Mixed", + "string": "Mixed()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "Mixed", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "Mixed.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "checkRequired", + "string": "Mixed.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", + "summary": "

    Casts val for Mixed.

    ", + "body": "

    this is a no-op

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "cast", + "string": "Mixed.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$cond", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "castForQuery", + "string": "Mixed.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Mixed;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Mixed", + "string": "module.exports" + } + } +] +### lib/schema/number.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Number SchemaType constructor.

    ", + "summary": "

    Number SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", + "ctx": { + "type": "function", + "name": "SchemaNumber", + "string": "SchemaNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaNumber", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaNumber.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for number

    ", + "summary": "

    Required validator for number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "checkRequired", + "string": "SchemaNumber.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "value", + "description": "minimum number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "min", + "string": "SchemaNumber.prototype.min()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "maximum", + "description": "number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "max", + "string": "SchemaNumber.prototype.max()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "value to cast" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to number

    ", + "summary": "

    Casts to number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "cast", + "string": "SchemaNumber.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "castForQuery", + "string": "SchemaNumber.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaNumber;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaNumber", + "string": "module.exports" + } + } +] +### lib/schema/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    ObjectId SchemaType constructor.

    ", + "summary": "

    ObjectId SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", + "ctx": { + "type": "function", + "name": "ObjectId", + "string": "ObjectId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "ObjectId", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "ObjectId.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "checkRequired", + "string": "ObjectId.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to ObjectId

    ", + "summary": "

    Casts to ObjectId

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "cast", + "string": "ObjectId.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "castForQuery", + "string": "ObjectId.prototype.castForQuery()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "turnOn", + "description": "auto generated ObjectId defaults" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "auto", + "string": "ObjectId.prototype.auto()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", + "ctx": { + "type": "function", + "name": "defaultId", + "string": "defaultId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ObjectId;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ObjectId", + "string": "module.exports" + } + } +] +### lib/schema/string.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    String SchemaType constructor.

    ", + "summary": "

    String SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", + "ctx": { + "type": "function", + "name": "SchemaString", + "string": "SchemaString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaString", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaString.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[args...]", + "description": "enumeration values" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", + "summary": "

    Adds enumeration values and a coinciding validator.

    ", + "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "enum", + "string": "SchemaString.prototype.enum()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", + "summary": "

    Adds a lowercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toLowerCase();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "lowercase", + "string": "SchemaString.prototype.lowercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", + "summary": "

    Adds an uppercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toUpperCase();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "uppercase", + "string": "SchemaString.prototype.uppercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", + "summary": "

    Adds a trim setter.

    ", + "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.trim();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "trim", + "string": "SchemaString.prototype.trim()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp" + ], + "name": "regExp", + "description": "regular expression to test against" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", + "summary": "

    Sets a regexp validator.

    ", + "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "match", + "string": "SchemaString.prototype.match()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "null", + "undefined" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "checkRequired", + "string": "SchemaString.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to String

    ", + "summary": "

    Casts to String

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "cast", + "string": "SchemaString.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "castForQuery", + "string": "SchemaString.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaString;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaString", + "string": "module.exports" + } + } +] +### lib/schema.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "definition", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted after the schema is compiled into a `Model`." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", + "summary": "

    Schema constructor.

    ", + "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", + "ctx": { + "type": "function", + "name": "Schema", + "string": "Schema()" + } + }, + { + "tags": [], + "description": { + "full": "

    Returns this documents _id cast to a string.

    ", + "summary": "

    Returns this documents _id cast to a string.

    ", + "body": "" + }, + "ignore": true, + "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", + "ctx": { + "type": "function", + "name": "idGetter", + "string": "idGetter()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Schema", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Schema.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "paths" + } + ], + "description": { + "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", + "summary": "

    Schema as flat paths

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.paths;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "tree" + } + ], + "description": { + "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", + "summary": "

    Schema as a tree

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.tree;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options for this schema, merged with options.

    ", + "summary": "

    Returns default options for this schema, merged with options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.defaultOptions = function (options) {\n options = utils.options({\n safe: true\n , strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "defaultOptions", + "string": "Schema.prototype.defaultOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "prefix", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", + "summary": "

    Adds key path / schema type pairs to this schema.

    ", + "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n }\n else\n this.path(prefix + i, obj[i]); // mixed type\n } else\n this.path(prefix + i, obj[i]);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "add", + "string": "Schema.prototype.add()" + } + }, + { + "tags": [], + "description": { + "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    ", + "summary": "

    Reserved document keys.

    ", + "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    " + }, + "ignore": false, + "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "reserved", + "value": "Object.create(null)", + "string": "Schema.reserved" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "constructor", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", + "summary": "

    Gets/sets schema paths.

    ", + "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(path) {\n if (!branch[path]) branch[path] = {};\n branch = branch[path];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "path", + "string": "Schema.prototype.path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "constructor" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts type arguments into Mongoose Types.

    ", + "summary": "

    Converts type arguments into Mongoose Types.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", + "ctx": { + "type": "method", + "receiver": "Schema", + "name": "interpretAsType", + "string": "Schema.interpretAsType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback function" + }, + { + "type": "return", + "types": [ + "Schema" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", + "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", + "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "eachPath", + "string": "Schema.prototype.eachPath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns an Array of path strings that are required by this schema.

    ", + "summary": "

    Returns an Array of path strings that are required by this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "requiredPaths", + "string": "Schema.prototype.requiredPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", + "summary": "

    Returns the pathType of path for this schema.

    ", + "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pathType", + "string": "Schema.prototype.pathType()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", + "ctx": { + "type": "function", + "name": "getPositionalPath", + "string": "getPositionalPath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the document method to call later" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds a method call to the queue.

    ", + "summary": "

    Adds a method call to the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "queue", + "string": "Schema.prototype.queue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", + "summary": "

    Defines a pre hook for the document.

    ", + "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pre", + "string": "Schema.prototype.pre()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "name of the method to hook" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", + "summary": "

    Defines a post hook for the document.

    ", + "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "post", + "string": "Schema.prototype.post()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "plugin", + "description": "callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "" + }, + { + "type": "see", + "local": "plugins", + "visibility": "plugins" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Registers a plugin for this schema.

    ", + "summary": "

    Registers a plugin for this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "plugin", + "string": "Schema.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "method", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", + "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "method", + "string": "Schema.prototype.method()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", + "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "static", + "string": "Schema.prototype.static()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", + "summary": "

    Defines an index (most likely compound) for this schema.

    ", + "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "index", + "string": "Schema.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "option name" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[value]", + "description": "if not passed, the current option value is returned" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets/gets a schema option.

    ", + "summary": "

    Sets/gets a schema option.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.set = function (key, value, tags) {\n if (arguments.length == 1)\n return this.options[key];\n\n this.options[key] = 'read' == key\n ? utils.readPref(value, tags)\n : value;\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "set", + "string": "Schema.prototype.set()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Compiles indexes from fields and schema-level indexes

    ", + "summary": "

    Compiles indexes from fields and schema-level indexes

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "indexes", + "string": "Schema.prototype.indexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", + "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", + "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " + }, + "ignore": true, + "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", + "ctx": { + "type": "function", + "name": "fixSubIndexPaths", + "string": "fixSubIndexPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Creates a virtual type with the given name.

    ", + "summary": "

    Creates a virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtual", + "string": "Schema.prototype.virtual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the virtual type with the given name.

    ", + "summary": "

    Returns the virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtualpath", + "string": "Schema.prototype.virtualpath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "namedScope", + "string": "Schema.prototype.namedScope()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Schema", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Schema Types.

    \n\n

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", + "summary": "

    The various Mongoose Schema Types.

    ", + "body": "

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.Types = require('./schema/index');", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "Types", + "value": "require('./schema/index')", + "string": "Schema.Types" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" + } +] +### lib/schemadefault.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "property", + "string": "system.profile" + }, + { + "type": "receiver", + "string": "exports" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Default model for querying the system.profiles collection.

    ", + "summary": "

    Default model for querying the system.profiles collection.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" + } +] +### lib/schematype.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');\nvar CastError = require('./errors/cast')\nvar ValidatorError = require('./errors/validator')", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[instance]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    SchemaType constructor

    ", + "summary": "

    SchemaType constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", + "ctx": { + "type": "function", + "name": "SchemaType", + "string": "SchemaType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function", + "any" + ], + "name": "val", + "description": "the default value" + }, + { + "type": "return", + "types": [ + "defaultValue" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", + "summary": "

    Sets a default value for this SchemaType.

    ", + "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "default", + "string": "SchemaType.prototype.default()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "Boolean" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", + "summary": "

    Declares the index options for this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "index", + "string": "SchemaType.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares an unique index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    ", + "summary": "

    Declares an unique index.

    ", + "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "unique", + "string": "SchemaType.prototype.unique()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a sparse index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", + "summary": "

    Declares a sparse index.

    ", + "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "sparse", + "string": "SchemaType.prototype.sparse()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "when", + "description": "" + }, + { + "type": "added", + "string": "3.0.0" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    ", + "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", + "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "expires", + "string": "SchemaType.prototype.expires()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    ", + "summary": "

    Adds a setter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "set", + "string": "SchemaType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    ", + "summary": "

    Adds a getter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "get", + "string": "SchemaType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp", + "Function", + "Object" + ], + "name": "obj", + "description": "validator" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[error]", + "description": "optional error message" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", + "summary": "

    Adds validator(s) for this document path.

    ", + "body": "

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "validate", + "string": "SchemaType.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "required", + "description": "enable/disable the validator" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", + "summary": "

    Adds a required validator to this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "required", + "string": "SchemaType.prototype.required()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope which callback are executed" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets the default value

    ", + "summary": "

    Gets the default value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "getDefault", + "string": "SchemaType.prototype.getDefault()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies setters

    ", + "summary": "

    Applies setters

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applySetters", + "string": "SchemaType.prototype.applySetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies getters to a value

    ", + "summary": "

    Applies getters to a value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applyGetters", + "string": "SchemaType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", + "summary": "

    Sets default select() behavior for this path.

    ", + "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "select", + "string": "SchemaType.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "doValidate", + "string": "SchemaType.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if value is a valid Reference.

    ", + "summary": "

    Determines if value is a valid Reference.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", + "ctx": { + "type": "method", + "receiver": "SchemaType", + "name": "_isRef", + "string": "SchemaType._isRef()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = SchemaType", + "string": "module.exports" + } + } +] +### lib/statemachine.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", + "ctx": { + "type": "declaration", + "name": "StateMachine", + "value": "module.exports = exports = function StateMachine () {", + "string": "StateMachine" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "subclass constructor" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", + "ctx": { + "type": "method", + "receiver": "StateMachine", + "name": "ctor", + "string": "StateMachine.ctor()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", + "summary": "

    This function is wrapped by the state change functions

    ", + "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_changeState", + "string": "StateMachine.prototype._changeState()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "clear", + "string": "StateMachine.prototype.clear()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "that we want to check for." + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "some", + "string": "StateMachine.prototype.some()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "iterMethod", + "description": "is either 'forEach' or 'map'" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_iter", + "string": "StateMachine.prototype._iter()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "forEach", + "string": "StateMachine.prototype.forEach()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "map", + "string": "StateMachine.prototype.map()" + } + } +] +### lib/types/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", + "ctx": { + "type": "declaration", + "name": "EmbeddedDocument", + "value": "require('./embedded')", + "string": "EmbeddedDocument" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Array" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", + "summary": "

    Mongoose Array constructor.

    ", + "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseArray", + "string": "MongooseArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Array

    ", + "summary": "

    Inherit from Array

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseArray.prototype = new Array;", + "ctx": { + "type": "property", + "receiver": "MongooseArray", + "name": "prototype", + "value": "new Array", + "string": "MongooseArray.prototype" + } + }, + { + "tags": [ + { + "type": "property", + "string": "_atomics" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores a queue of atomic operations to perform

    ", + "summary": "

    Stores a queue of atomic operations to perform

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._atomics;" + }, + { + "tags": [ + { + "type": "property", + "string": "_parent" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._parent;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "return", + "types": [ + "value" + ], + "description": "the casted value" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts a member based on this arrays schema.

    ", + "summary": "

    Casts a member based on this arrays schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_cast", + "string": "MongooseArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "EmbeddedDocument" + ], + "name": "embeddedDoc", + "description": "the embedded doc that invoked this method on the Array" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "embeddedPath", + "description": "the path which changed in the embeddedDoc" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", + "summary": "

    Marks this array as modified.

    ", + "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._markModified = function (elem, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n dirtyPath = this._path;\n\n if (arguments.length) {\n if (null != embeddedPath) {\n // an embedded doc bubbled up the change\n dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;\n } else {\n // directly set an index\n dirtyPath = dirtyPath + '.' + elem;\n }\n\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_markModified", + "string": "MongooseArray.prototype._markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "op", + "description": "operation" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register an atomic operation with the parent.

    ", + "summary": "

    Register an atomic operation with the parent.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n this._markModified();\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n if (this._atomics.$set) {\n return this;\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n this._markModified();\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n this._markModified();\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_registerAtomic", + "string": "MongooseArray.prototype._registerAtomic()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "hasAtomics", + "string": "MongooseArray.prototype.hasAtomics()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#push with proper change tracking.

    ", + "summary": "

    Wraps Array#push with proper change tracking.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "push", + "string": "MongooseArray.prototype.push()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Pushes items to the array non-atomically.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "nonAtomicPush", + "string": "MongooseArray.prototype.nonAtomicPush()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "$pop" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", + "summary": "

    Pops the array atomically at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" + }, + { + "tags": [ + { + "type": "see", + "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", + "visibility": "MongooseArray#$pop" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#pop with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pop", + "string": "MongooseArray.prototype.pop()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "method", + "string": "$shift" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", + "summary": "

    Atomically shifts the array at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#shift with proper change tracking.

    ", + "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "shift", + "string": "MongooseArray.prototype.shift()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "values to remove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes items from an array atomically

    \n\n

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    ", + "summary": "

    Removes items from an array atomically

    ", + "body": "

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "remove", + "string": "MongooseArray.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pulls items from the array atomically.

    ", + "summary": "

    Pulls items from the array atomically.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pull", + "string": "MongooseArray.prototype.pull()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#splice with proper change tracking and casting.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#splice with proper change tracking and casting.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.splice = function splice () {\n var ret, vals, i;\n\n if (arguments.length) {\n vals = [];\n for (i = 0; i < arguments.length; ++i) {\n vals[i] = i < 2\n ? arguments[i]\n : this._cast(arguments[i]);\n }\n ret = [].splice.apply(this, vals);\n this._registerAtomic('$set', this);\n }\n\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "splice", + "string": "MongooseArray.prototype.splice()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#unshift with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n return this.length;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "unshift", + "string": "MongooseArray.prototype.unshift()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#sort with proper change tracking.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "sort", + "string": "MongooseArray.prototype.sort()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "the values that were added" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", + "summary": "

    Adds values to the array if not already present.

    ", + "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "addToSet", + "string": "MongooseArray.prototype.addToSet()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the casted val at index i and marks the array modified.

    \n\n

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    ", + "summary": "

    Sets the casted val at index i and marks the array modified.

    ", + "body": "

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.set = function set (i, val) {\n this[i] = this._cast(val);\n this._markModified(i);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "set", + "string": "MongooseArray.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array.

    ", + "summary": "

    Returns a native js Array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "toObject", + "string": "MongooseArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "inspect", + "string": "MongooseArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the item to look for" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Return the index of obj or -1 if not found.

    ", + "summary": "

    Return the index of obj or -1 if not found.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "indexOf", + "string": "MongooseArray.prototype.indexOf()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = MongooseArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = MongooseArray", + "string": "module.exports" + } + } +] +### lib/types/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require(driver + '/binary');", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require(driver + '/binary')", + "string": "Binary" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "encode", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "offset", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Buffer" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", + "summary": "

    Mongoose Buffer constructor.

    ", + "body": "

    Values always have to be passed to the constructor to initialize.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", + "ctx": { + "type": "function", + "name": "MongooseBuffer", + "string": "MongooseBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Buffer.

    ", + "summary": "

    Inherit from Buffer.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.prototype = new Buffer(0);", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "prototype", + "value": "new Buffer(0)", + "string": "MongooseBuffer.prototype" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "_parent" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._parent;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this buffer as modified.

    ", + "summary": "

    Marks this buffer as modified.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "_markModified", + "string": "MongooseBuffer.prototype._markModified()" + } + }, + { + "tags": [], + "description": { + "full": "

    Writes the buffer.

    ", + "summary": "

    Writes the buffer.

    ", + "body": "" + }, + "ignore": false, + "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "write", + "string": "MongooseBuffer.prototype.write()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "MongooseBuffer" + ], + "description": "" + }, + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "target", + "description": "" + } + ], + "description": { + "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", + "summary": "

    Copies the buffer.

    ", + "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "copy", + "string": "MongooseBuffer.prototype.copy()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "body": "" + }, + "ignore": true, + "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://bsonspec.org/#/specification", + "visibility": "http://bsonspec.org/#/specification" + }, + { + "type": "param", + "types": [ + "Hex" + ], + "name": "[subtype]", + "description": "" + }, + { + "type": "return", + "types": [ + "Binary" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", + "summary": "

    Converts this buffer to its Binary type representation.

    ", + "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "toObject", + "string": "MongooseBuffer.prototype.toObject()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "Binary", + "value": "Binary", + "string": "MongooseBuffer.Binary" + } + } +] +### lib/types/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", + "ctx": { + "type": "declaration", + "name": "MongooseArray", + "value": "require('./array')", + "string": "MongooseArray" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to this array" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "MongooseDocumentArray" + ], + "description": "" + }, + { + "type": "inherits", + "string": "MongooseArray" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    DocumentArray constructor

    ", + "summary": "

    DocumentArray constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseDocumentArray", + "string": "MongooseDocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseArray

    ", + "summary": "

    Inherits from MongooseArray

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseDocumentArray", + "name": "__proto__", + "value": "MongooseArray.prototype", + "string": "MongooseDocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides MongooseArray#cast

    ", + "summary": "

    Overrides MongooseArray#cast

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype._cast = function (value) {\n if (value instanceof this._schema.casterConstructor)\n return value;\n\n return new this._schema.casterConstructor(value, this);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "_cast", + "string": "MongooseDocumentArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "EmbeddedDocument", + "null" + ], + "description": "the subdocuent or null if not found." + }, + { + "type": "param", + "types": [ + "ObjectId", + "String", + "Number", + "Buffer" + ], + "name": "id", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Searches array items for the first document with a matching id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", + "summary": "

    Searches array items for the first document with a matching id.

    ", + "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "id", + "string": "MongooseDocumentArray.prototype.id()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", + "summary": "

    Returns a native js Array of plain js objects

    ", + "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "toObject", + "string": "MongooseDocumentArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "inspect", + "string": "MongooseDocumentArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the value to cast to this arrays SubDocument schema" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", + "summary": "

    Creates a subdocument casted to this schema.

    ", + "body": "

    This is the same subdocument constructor used for casting.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "create", + "string": "MongooseDocumentArray.prototype.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates a fn that notifies all child docs of event.

    ", + "summary": "

    Creates a fn that notifies all child docs of event.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n if (!self[i]) continue;\n self[i].emit(event, val);\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "notify", + "string": "MongooseDocumentArray.prototype.notify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseDocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseDocumentArray", + "string": "module.exports" + } + } +] +### lib/types/embedded.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('../document')\n , inspect = require('util').inspect;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('../document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "js object returned from the db" + }, + { + "type": "param", + "types": [ + "MongooseDocumentArray" + ], + "name": "parentArr", + "description": "the parent array of this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "skipId", + "description": "" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    EmbeddedDocument constructor.

    ", + "summary": "

    EmbeddedDocument constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", + "ctx": { + "type": "function", + "name": "EmbeddedDocument", + "string": "EmbeddedDocument()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Document

    ", + "summary": "

    Inherit from Document

    ", + "body": "" + }, + "ignore": true, + "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "EmbeddedDocument", + "name": "__proto__", + "value": "Document.prototype", + "string": "EmbeddedDocument.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path which changed" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", + "summary": "

    Marks the embedded doc modified.

    ", + "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "markModified", + "string": "EmbeddedDocument.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "return", + "types": [ + "EmbeddedDocument" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", + "summary": "

    Used as a stub for hooks.js

    ", + "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "save", + "string": "EmbeddedDocument.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes the subdocument from its parent array.

    ", + "summary": "

    Removes the subdocument from its parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "remove", + "string": "EmbeddedDocument.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Override #update method of parent documents.

    ", + "summary": "

    Override #update method of parent documents.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "update", + "string": "EmbeddedDocument.prototype.update()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "inspect", + "string": "EmbeddedDocument.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "error which states the reason `path` was invalid" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "invalidate", + "string": "EmbeddedDocument.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "ownerDocument", + "string": "EmbeddedDocument.prototype.ownerDocument()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", + "ctx": { + "type": "function", + "name": "ownerDocument", + "string": "ownerDocument()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent document.

    ", + "summary": "

    Returns this sub-documents parent document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parent", + "string": "EmbeddedDocument.prototype.parent()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent array.

    ", + "summary": "

    Returns this sub-documents parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parentArray", + "string": "EmbeddedDocument.prototype.parentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = EmbeddedDocument;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "EmbeddedDocument", + "string": "module.exports" + } + } +] +### lib/types/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "Array", + "value": "require('./array')", + "string": "exports.Array" + } + } +] +### lib/types/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [ + { + "type": "constructor", + "string": "ObjectId" + } + ], + "description": { + "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", + "summary": "

    ObjectId type constructor

    ", + "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require(driver + '/objectid')", + "string": "ObjectId" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "str", + "description": "" + }, + { + "type": "static", + "string": "fromString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "ObjectId" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates an ObjectId from str

    ", + "summary": "

    Creates an ObjectId from str

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.fromString;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId" + ], + "name": "oid", + "description": "ObjectId instance" + }, + { + "type": "static", + "string": "toString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts oid to a string.

    ", + "summary": "

    Converts oid to a string.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.toString;" + } +] +### lib/utils.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , sliced = require('sliced')\n , MongooseBuffer\n , MongooseArray\n , Document", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "a model name" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "a collection name" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a collection name from model name.

    ", + "summary": "

    Produces a collection name from model name.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "toCollectionName", + "string": "exports.toCollectionName()" + } + }, + { + "tags": [], + "description": { + "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Pluralization rules.

    ", + "body": "

    These rules are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "pluralization", + "value": "[", + "string": "exports.pluralization" + } + }, + { + "tags": [], + "description": { + "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Uncountable words.

    ", + "body": "

    These words are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news'\n];\nvar uncountables = exports.uncountables;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "uncountables", + "value": "[", + "string": "exports.uncountables" + } + }, + { + "tags": [ + { + "type": "author", + "string": "TJ Holowaychuk (extracted from _ext.js_)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "string", + "description": "to pluralize" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pluralize function.

    ", + "summary": "

    Pluralize function.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", + "ctx": { + "type": "function", + "name": "pluralize", + "string": "pluralize()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "listener", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Add once to EventEmitter if absent

    ", + "summary": "

    Add once to EventEmitter if absent

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", + "ctx": { + "type": "declaration", + "name": "Events", + "value": "EventEmitter", + "string": "Events" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Events", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Events.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Add once.

    ", + "summary": "

    Add once.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", + "ctx": { + "type": "method", + "constructor": "Events", + "name": "once", + "string": "Events.prototype.once()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "a", + "description": "a value to compare to `b`" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "b", + "description": "a value to compare to `a`" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", + "summary": "

    Determines if a and b are deep equal.

    ", + "body": "

    Modified from node/lib/assert.js

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "deepEqual", + "string": "exports.deepEqual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the object to clone" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the cloned object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Object clone with Mongoose natives support.

    \n\n

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.

    ", + "summary": "

    Object clone with Mongoose natives support.

    ", + "body": "

    Creates a minimal data Object.
    It does not clone empty Arrays, empty Objects, and undefined values.
    This makes the data payload sent to MongoDB as minimal as possible.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId) {\n return new ObjectId(obj.id);\n }\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "clone", + "string": "exports.clone()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", + "ctx": { + "type": "function", + "name": "cloneObject", + "string": "cloneObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "defaults", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the merged object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Copies and merges options with defaults.

    ", + "summary": "

    Copies and merges options with defaults.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "options", + "string": "exports.options()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Generates a random string

    ", + "summary": "

    Generates a random string

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "random", + "string": "exports.random()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "to", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "from", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges from into to without overwriting existing properties.

    ", + "summary": "

    Merges from into to without overwriting existing properties.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n merge(to[key], from[key]);\n }\n }\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "merge", + "string": "exports.merge()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.args = sliced;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "args", + "value": "sliced", + "string": "exports.args" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", + "summary": "

    process.nextTick helper.

    ", + "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "tick", + "string": "exports.tick()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "v", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", + "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", + "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isMongooseObject", + "string": "exports.isMongooseObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "object", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expireAfterSeconds = when;\n delete object.expires;\n}\n\nexports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "expires", + "string": "exports.expires()" + } + } +] +### lib/virtualtype.js +[ + { + "tags": [ + { + "type": "parma", + "string": "{Object} options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", + "summary": "

    VirtualType constructor

    ", + "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", + "ctx": { + "type": "function", + "name": "VirtualType", + "string": "VirtualType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", + "summary": "

    Defines a getter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "get", + "string": "VirtualType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", + "summary": "

    Defines a setter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "set", + "string": "VirtualType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all getters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies getters to value using optional scope.

    ", + "summary": "

    Applies getters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applyGetters", + "string": "VirtualType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all setters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies setters to value using optional scope.

    ", + "summary": "

    Applies setters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applySetters", + "string": "VirtualType.prototype.applySetters()" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = VirtualType;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "VirtualType", + "string": "module.exports" + } + } +] diff --git a/docs/3.2.x/docs/source/api.js b/docs/3.2.x/docs/source/api.js new file mode 100644 index 00000000000..8fd87f0035b --- /dev/null +++ b/docs/3.2.x/docs/source/api.js @@ -0,0 +1,220 @@ +/*! + * Module dependencies + */ + +var fs = require('fs'); +var link = require('../helpers/linktype'); +var hl = require('highlight.js') +var md = require('markdown') + +module.exports = { + docs: [] + , github: 'https://github.com/LearnBoost/mongoose/tree/' + , title: 'API docs' +} + +var out = module.exports.docs; + +var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); +parse(docs); +order(out); + +function parse (docs) { + docs.split(/^### /gm).forEach(function (chunk) { + if (!(chunk = chunk.trim())) return; + + chunk = chunk.split(/^([^\n]+)\n/); + + var title = chunk[1]; + + if (!title || !(title = title.trim())) + throw new Error('missing title'); + + title = title.replace(/^lib\//, ''); + + var json = JSON.parse(chunk[2]); + + var props = []; + var methods = []; + var statics = []; + var constructor = null; + + json.forEach(function (comment) { + if (comment.description) + highlight(comment.description); + + var prop = false; + comment.params = []; + comment.see = []; + + var i = comment.tags.length; + while (i--) { + var tag = comment.tags[i]; + switch (tag.type) { + case 'property': + prop = true; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + props.unshift(comment); + break; + case 'method': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'method'; + comment.code = ''; + break; + case 'memberOf': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.constructor = tag.parent; + break; + case 'static': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + comment.ctx.type = 'method'; + break; + case 'receiver': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.receiver = tag.string; + break; + case 'constructor': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'function'; + comment.code = ''; + break; + case 'inherits': + if (/http/.test(tag.string)) { + var result = tag.string.split(' '); + var href = result.pop(); + var title = result.join(' '); + comment.inherits = '' + title + ''; + } else { + comment.inherits = link(tag.string); + } + comment.tags.splice(i, 1); + break; + case 'param': + comment.params.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'return': + comment.return = tag; + comment.tags.splice(i, 1); + break; + case 'see': + if (tag.local) { + var parts = tag.local.split(' '); + if (1 === parts.length) { + tag.url = link.type(parts[0]); + tag.title = parts[0]; + } else { + tag.url = parts.pop(); + tag.title = parts.join(' '); + } + } + comment.see.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'event': + var str = tag.string.replace(/\\n/g, '\n'); + tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); + comment.events || (comment.events = []); + comment.events.unshift(tag); + comment.tags.splice(i, 1); + } + } + + if (!prop) { + methods.push(comment); + } + }); + + methods = methods.filter(ignored); + props = props.filter(ignored); + + function ignored (method) { + if (method.ignore) return false; + return true; + } + + if (0 === methods.length + props.length) return; + + // add constructor to properties too + methods.some(function (method) { + if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { + props.forEach(function (prop) { + prop.ctx.constructor = method.ctx.constructor; + }); + return true; + } + return false; + }); + + var len = methods.length; + while (len--) { + method = methods[len]; + if (method.ctx && method.ctx.receiver) { + var stat = methods.splice(len, 1)[0]; + statics.unshift(stat); + } + } + + out.push({ + title: title + , methods: methods + , props: props + , statics: statics + , hasPublic: hasPublic(methods, props, statics) + }); + }); +} + +function hasPublic () { + for (var i = 0; i < arguments.length; ++i) { + var arr = arguments[i]; + for (var j = 0; j < arr.length; ++j) { + var item = arr[j]; + if (!item.ignore && !item.isPrivate) return true; + } + } + return false; +} + +// add "class='language'" to our
     elements
    +function highlight (o) {
    +  o.full = fix(o.full);
    +  o.summary = fix(o.summary);
    +  o.body = fix(o.body);
    +}
    +
    +function fix (str) {
    +  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    +
    +    // parse out the ```language
    +    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    +
    +    if ('js' == code[1] || !code[1]) {
    +      code[1] = 'javascript';
    +    }
    +
    +    return $1
    +          + hl.highlight(code[1], code[2]).value.trim()
    +          + $3;
    +  });
    +}
    +
    +function order (docs) {
    +  // want index first
    +  for (var i = 0; i < docs.length; ++i) {
    +    if ('index.js' == docs[i].title) {
    +      docs.unshift(docs.splice(i, 1)[0]);
    +    }
    +  }
    +}
    diff --git a/docs/3.2.x/docs/source/home.js b/docs/3.2.x/docs/source/home.js
    new file mode 100644
    index 00000000000..557f27b966b
    --- /dev/null
    +++ b/docs/3.2.x/docs/source/home.js
    @@ -0,0 +1,19 @@
    +
    +var fs = require('fs')
    +var package = require('./../../package.json')
    +var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    +
    +var imgs = [];
    +
    +images.forEach(function (line) {
    +  line = line.trim();
    +  if (!line) return;
    +  line = line.split('|');
    +  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    +});
    +
    +module.exports = {
    +    package: package
    +  , images: imgs
    +  , title: 'ODM'
    +}
    diff --git a/docs/3.2.x/docs/source/index.js b/docs/3.2.x/docs/source/index.js
    new file mode 100644
    index 00000000000..7eaf8a85b18
    --- /dev/null
    +++ b/docs/3.2.x/docs/source/index.js
    @@ -0,0 +1,19 @@
    +
    +exports['index.jade'] = require('./home')
    +exports['docs/api.jade'] = require('./api')
    +exports['docs/index.jade'] = { title: 'Getting Started' }
    +exports['docs/prior.jade'] = require('./prior')
    +exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    +exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    +exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    +exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    +exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    +exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    +exports['docs/models.jade'] = { guide: true, title: 'Models' }
    +exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    +exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    +exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    +exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    +exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    +exports['docs/connections.jade'] = { guide: true, title: 'Connecting to MongoDB' }
    +exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.2.x/docs/source/prior.js b/docs/3.2.x/docs/source/prior.js
    new file mode 100644
    index 00000000000..2e03811d215
    --- /dev/null
    +++ b/docs/3.2.x/docs/source/prior.js
    @@ -0,0 +1,13 @@
    +var fs = require('fs')
    +var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    +releases = releases.split('\n').filter(Boolean);
    +
    +module.exports = exports = {
    +    title: ''
    +  , releases: releases.map(function (version) {
    +      return {
    +          url: version + '/'
    +        , version: version
    +      }
    +    })
    +}
    diff --git a/docs/3.2.x/docs/subdocs.html b/docs/3.2.x/docs/subdocs.html
    new file mode 100644
    index 00000000000..7535ca7272f
    --- /dev/null
    +++ b/docs/3.2.x/docs/subdocs.html
    @@ -0,0 +1,49 @@
    +Mongoose SubDocuments v3.2.2Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    +
    +var parentSchema = new Schema({
    +  children: [childSchema]
    +})
    +

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = db.model('Parent', parentSchema);
    +var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    +parent.children[0].name = 'Matthew';
    +parent.save(callback);
    +

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    +  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    +  next();
    +});
    +
    +var parent = new Parent({ children: [{ name: 'invalid' }] });
    +parent.save(function (err) {
    +  console.log(err.message) // #sadpanda
    +})
    +

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    +

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = db.model('Parent');
    +var parent = new Parent;
    +
    +// create a comment
    +post.children.push({ name: 'Liesl' });
    +var doc = post.children[0];
    +console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    +doc.isNew; // true
    +
    +post.save(function (err) {
    +  if (err) return handleError(err)
    +  console.log('Success!');
    +});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    +

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    +parent.save(function (err) {
    +  if (err) return handleError(err);
    +  console.log('the sub-doc was removed')
    +});
    +

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    +  children: [{ name: 'string' }]
    +})
    +

    Next Up

    Now that we've covered Sub-documents, let's take a look at querying.

    diff --git a/docs/3.2.x/docs/subdocs.jade b/docs/3.2.x/docs/subdocs.jade new file mode 100644 index 00000000000..9e568e3ab74 --- /dev/null +++ b/docs/3.2.x/docs/subdocs.jade @@ -0,0 +1,84 @@ +extends layout + +block content + h2 Sub Docs + :markdown + [Sub-documents](./api.html#types-embedded-js) are docs with schemas of their own which are elements of a parents document array: + :js + var childSchema = new Schema({ name: 'string' }); + + var parentSchema = new Schema({ + children: [childSchema] + }) + + :markdown + Sub-documents enjoy all the same features as normal [documents](./api.html#document-js). The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved. + :js + var Parent = db.model('Parent', parentSchema); + var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) + parent.children[0].name = 'Matthew'; + parent.save(callback); + + :markdown + If an error occurs in a sub-documents' middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap! + + :js + childSchema.pre('save', function (next) { + if ('invalid' == this.name) return next(new Error('#sadpanda')); + next(); + }); + + var parent = new Parent({ children: [{ name: 'invalid' }] }); + parent.save(function (err) { + console.log(err.message) // #sadpanda + }) + + h3 Finding a sub-document + :markdown + Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. + :js + var doc = parent.children.id(id); + + h3 Adding sub-docs + :markdown + MongooseArray methods such as [push](./api.html#types_array_MongooseArray-push), [unshift](./api.html#types_array_MongooseArray-unshift), [addToSet](./api.html#types_array_MongooseArray-addToSet), and others cast arguments to their proper types transparently: + :js + var Parent = db.model('Parent'); + var parent = new Parent; + + // create a comment + post.children.push({ name: 'Liesl' }); + var doc = post.children[0]; + console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' } + doc.isNew; // true + + post.save(function (err) { + if (err) return handleError(err) + console.log('Success!'); + }); + :markdown + Sub-docs may also be created without adding them to the array by using the [create](./api.html#types_documentarray_MongooseDocumentArray-create) method of MongooseArrays. + :js + var newdoc = post.children.create({ name: 'Aaron' }); + + h3 Removing docs + :markdown + Each sub-document has it's own [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. + :js + var doc = parent.children.id(id).remove(); + parent.save(function (err) { + if (err) return handleError(err); + console.log('the sub-doc was removed') + }); + + h4#altsyntax Alternate declaration syntax + :markdown + _New in v3_ If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal: + :js + var parentSchema = new Schema({ + children: [{ name: 'string' }] + }) + + h3#next Next Up + :markdown + Now that we've covered `Sub-documents`, let's take a look at [querying](/docs/queries.html). diff --git a/docs/3.2.x/docs/validation.html b/docs/3.2.x/docs/validation.html new file mode 100644 index 00000000000..5ca01b7fb7e --- /dev/null +++ b/docs/3.2.x/docs/validation.html @@ -0,0 +1,37 @@ +Mongoose Validation v3.2.2Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    + +
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    + +

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    +  color: String,
    +  name: String
    +});
    +
    +var Toy = db.model('Toy', toySchema);
    +
    +Toy.schema.path('color').validate(function (value) {
    +  return /blue|green|white|red|orange|periwinkel/i.test(value);
    +}, 'Invalid color');
    +
    +var toy = new Toy({ color: 'grease'});
    +
    +toy.save(function (err) {
    +  // err.errors.color is a ValidatorError object
    +  
    +  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(err.errors.color.type) // prints "Invalid color"
    +  console.log(err.errors.color.path) // prints "color"
    +  console.log(err.name) // prints "ValidationError"
    +  console.log(err.message) // prints "Validation failed"
    +});
    +

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    +

    Next Up

    Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

    diff --git a/docs/3.2.x/docs/validation.jade b/docs/3.2.x/docs/validation.jade new file mode 100644 index 00000000000..5b267bf95a5 --- /dev/null +++ b/docs/3.2.x/docs/validation.jade @@ -0,0 +1,58 @@ +extends layout + +block content + h2 Validation + :markdown + Before we get into the specifics of validation syntax, please keep the following rules in mind: + + - Validation is defined in the [SchemaType](./schematypes.html) + - Validation is an internal piece of [middleware](./middleware.html) + - Validation occurs when a document attempts to be [saved](./api.html#model_Model-save), after defaults have been applied + - Validation is asynchronously recursive: when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed. If an error happens, your Model#save callback receives it + - Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, `"min"` is the identifier for the error triggered when a number doesn't meet the [minimum value](./api.html#schema_number_SchemaNumber-min). The path and value that triggered the error can be accessed in the `ValidationError` object + h3 Built in validators + :markdown + Mongoose has several built in validators. + + - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. + - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. + - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum) and [match](./api.html#schema_string_SchemaString-match) validators. + h3 Custom validators + :markdown + Custom validation is declared by passing a validation `function` and an error type to your `SchemaType`s validate method. Read the [API](./api.html#schematype_SchemaType-validate) docs for details on custom validators, async validators, and more. + h3 Validation errors + :markdown + Errors returned after failed validation contain an `errors` object holding the actual `ValidatorErrors`. Each [ValidatorError](./api.html#errors-validation-js) has a `type` and `path` property providing us with a little more error handling flexibility. + :js + var toySchema = new Schema({ + color: String, + name: String + }); + + var Toy = db.model('Toy', toySchema); + + Toy.schema.path('color').validate(function (value) { + return /blue|green|white|red|orange|periwinkel/i.test(value); + }, 'Invalid color'); + + var toy = new Toy({ color: 'grease'}); + + toy.save(function (err) { + // err.errors.color is a ValidatorError object + + console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color' + console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color' + console.log(err.errors.color.type) // prints "Invalid color" + console.log(err.errors.color.path) // prints "color" + console.log(err.name) // prints "ValidationError" + console.log(err.message) // prints "Validation failed" + }); + + :markdown + After a validation error, the document will also have the same `errors` property available: + :js + toy.errors.color.message === err.errors.color.message + + h3#next Next Up + :markdown + Now that we've covered `validation`, let's take a look at how you might handle advanced validation with Mongoose's [middleware](/docs/middleware.html). diff --git a/docs/3.2.x/index.html b/docs/3.2.x/index.html new file mode 100644 index 00000000000..3568a23d128 --- /dev/null +++ b/docs/3.2.x/index.html @@ -0,0 +1,20 @@ +Mongoose ODM v3.2.2Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

    var mongoose = require('mongoose');
    +var db = mongoose.createConnection('localhost', 'test');
    +
    +var schema = mongoose.Schema({ name: 'string' });
    +var Cat = db.model('Cat', schema);
    +
    +var kitty = new Cat({ name: 'Zildjian' });
    +kitty.save(function (err) {
    +  if (err) // ...
    +  res.end('meow');
    +});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    Production + (add your project)

    • LearnBoost is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students.
    • Storify lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative.
    • ClickDummy is a rapid mockup prototyping application for designers and dummies.
    • Scotty App allows you to create data driven backends for your apps in minutes instead of weeks.
    • Geeklist is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found.
    • Bozuko is an exciting customer rewards program.
    • Call List helps you maintain a todo list for people you need to call.
    • Grow The Game Golf lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more.
    • nextdays lets you share plans with friends and discover what is happening around you.
    • AtticTV is Music Television (MTV) for the web.
    • LocalResponse helps marketers respond to real-time consumer intent.
    • Select Vids is a collection of amazing, funny, and creative videos for you to discover.
    • cldfy delivers mail to your app.
    • ShareLatex is a real-time LaTeX collaboration tool.
    • Cyborg Vision uses real-time facial recognition to identify your friends and show their information.
    • Wavo lets you express yourself through the songs you love.
    • seelio is a stage for college students to distinguish themselves and connect with companies.
    • TodayLaunch is a free dashboard for your social media accounts.
    • Stachify
    • Skim is a playful way to meet new people.
    • NuORDER online fashion wholesale for brands and buyers.
    • UPcload helps you find clothes that fit you when shopping online.
    • TreinoSmart is a system for gym and physical trainers.
    • ShoeJitsu let's you shop, compare, and share fashion.
    • Kyyti is a meeting place for rides.
    • Nimble Quiz allows you to quickly create and manage simple multiple choice quizzes.
    • Fur Baby Rescue provides a temporary, safe home for cats, dogs, puppies and kittens.
    diff --git a/docs/3.2.x/static.js b/docs/3.2.x/static.js new file mode 100644 index 00000000000..fc0e722dd4e --- /dev/null +++ b/docs/3.2.x/static.js @@ -0,0 +1,17 @@ + +var static = require('node-static'); +var server = new static.Server('.', { cache: 0 }); + +require('http').createServer(function (req, res) { + req.on('end', function () { + server.serve(req, res, function (err) { + if (err) { + console.error(err, req.url); + res.writeHead(err.status, err.headers); + res.end(); + } + }); + }); +}).listen(8088); + +console.error('now listening on localhost:8088'); diff --git a/docs/3.3.x/docs/api.html b/docs/3.3.x/docs/api.html new file mode 100644 index 00000000000..0f55a1ecbd8 --- /dev/null +++ b/docs/3.3.x/docs/api.html @@ -0,0 +1,6883 @@ +Mongoose API v3.3.1Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      +  this.connections = [];
      +  this.plugins = [];
      +  this.models = {};
      +  this.modelSchemas = {};
      +  this.options = {};
      +  this.createConnection(); // default connection
      +};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +  this.options[key] = value;
      +  return this;
      +};

      Parameters:

      Example:

      + +
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      + +
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri], [options])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      +  var conn = new Connection(this);
      +  this.connections.push(conn);
      +
      +  if (arguments.length) {
      +    if (rgxReplSet.test(arguments[0])) {
      +      conn.openSet.apply(conn, arguments);
      +    } else {
      +      conn.open.apply(conn, arguments);
      +    }
      +  }
      +
      +  return conn;
      +};

      Parameters:

      • [uri] <String> a mongodb:// URI
      • [options] <Object> options to pass to the driver

      Returns:

      Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

      + +

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

      + +

      Example:

      + +
      // with mongodb:// URI
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
      +
      +// and options
      +var opts = { db: { native_parser: true }}
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
      +
      +// replica sets
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
      +
      +// and options
      +var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
      +
      +// with [host, database_name[, port] signature
      +db = mongoose.createConnection('localhost', 'database', port)
      +
      +// and options
      +var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
      +db = mongoose.createConnection('localhost', 'database', port, opts)
      +
      +// initialize now, connect later
      +db = mongoose.createConnection();
      +db.open('localhost', 'database', port, [opts]);

      Mongoose#connect()

      Opens the default mongoose connection.

      show code
      Mongoose.prototype.connect = function () {
      +  var conn = this.connection;
      +
      +  if (rgxReplSet.test(arguments[0])) {
      +    conn.openSet.apply(conn, arguments);
      +  } else {
      +    conn.open.apply(conn, arguments);
      +  }
      +
      +  return this;
      +};

      Returns:

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


      Mongoose#disconnect([fn])

      Disconnects all connections.

      show code
      Mongoose.prototype.disconnect = function (fn) {
      +  var count = this.connections.length
      +    , error
      +
      +  this.connections.forEach(function(conn){
      +    conn.close(function(err){
      +      if (error) return;
      +
      +      if (err) {
      +        error = err;
      +        if (fn) return fn(err);
      +        throw err;
      +      }
      +
      +      if (fn)
      +        --count || fn();
      +    });
      +  });
      +  return this;
      +};

      Parameters:

      • [fn] <Function> called after all connection close.

      Returns:


      Mongoose#model(name, [schema], [collection], [skipInit])

      Defines a model or retrieves it.

      show code
      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
      +  // normalize collection
      +  if (!(schema instanceof Schema)) {
      +    collection = schema;
      +    schema = false;
      +  }
      +
      +  if ('boolean' === typeof collection) {
      +    skipInit = collection;
      +    collection = null;
      +  }
      +
      +  // look up models for the collection
      +  if (!this.modelSchemas[name]) {
      +    if (!schema && name in SchemaDefaults) {
      +      schema = SchemaDefaults[name];
      +    }
      +
      +    if (schema) {
      +      this.modelSchemas[name] = schema;
      +      for (var i = 0, l = this.plugins.length; i < l; i++) {
      +        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
      +      }
      +    } else {
      +      throw new Error('Schema hasn\'t been registered for model "' + name + '".
      +'
      +                    + 'Use mongoose.model(name, schema)');
      +    }
      +  }
      +
      +  if (!this.models[name]) {
      +    schema || (schema = this.modelSchemas[name]);
      +    collection || (collection = schema.set('collection') || format(name));
      +
      +    var model = Model.compile(name
      +                        , this.modelSchemas[name]
      +                        , collection
      +                        , this.connection
      +                        , this);
      +
      +    if (!skipInit) model.init();
      +
      +    this.models[name] = model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> model name
      • [schema] <Schema>
      • [collection] <String> name (optional, induced from model name)
      • [skipInit] <Boolean> whether to skip initialization (defaults to false)

      Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +
      +// define an Actor model with this mongoose instance
      +mongoose.model('Actor', new Schema({ name: String }));
      +
      +// create a new connection
      +var conn = mongoose.createConnection(..);
      +
      +// retrieve the Actor model
      +var Actor = conn.model('Actor');
      + +

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

      + +

      Example:

      + +
      var schema = new Schema({ name: String });
      +schema.set('collection', 'actor');

      Mongoose#plugin(fn, [opts])

      Declares a global plugin executed on all Schemas.

      show code
      Mongoose.prototype.plugin = function (fn, opts) {
      +  this.plugins.push([fn, opts]);
      +  return this;
      +};

      Parameters:

      Returns:

      Equivalent to calling .plugin(fn) on each Schema you create.


      module.exports

      The exports object is an instance of Mongoose.

      show code
      module.exports = exports = new Mongoose;
      +var mongoose = module.exports;

      mongoose.Collection

      The Mongoose Collection constructor

      show code
      mongoose.Collection = Collection;

      mongoose.Connection

      The Mongoose Connection constructor

      show code
      mongoose.Connection = Connection;

      mongoose.version

      Mongoose version

      show code
      mongoose.version = JSON.parse(
      +  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      +).version;

      mongoose.Mongoose

      The Mongoose constructor

      show code
      mongoose.Mongoose = Mongoose;

      The exports of the mongoose module is an instance of this class.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var mongoose2 = new mongoose.Mongoose();

      mongoose.Schema

      The Mongoose Schema constructor

      show code
      mongoose.Schema = Schema;

      Example:

      + +
      var mongoose = require('mongoose');
      +var Schema = mongoose.Schema;
      +var CatSchema = new Schema(..);

      mongoose.SchemaType

      The Mongoose SchemaType constructor.

      show code
      mongoose.SchemaType = SchemaType;

      mongoose.SchemaTypes

      The various Mongoose SchemaTypes.

      show code
      mongoose.SchemaTypes = Schema.Types;

      Note:

      + +

      Alias of mongoose.Schema.Types for backwards compatibility.


      mongoose.VirtualType

      The Mongoose VirtualType constructor.

      show code
      mongoose.VirtualType = VirtualType;

      mongoose.Types

      The various Mongoose Types.

      show code
      mongoose.Types = Types;

      Example:

      + +
      var mongoose = require('mongoose');
      +var array = mongoose.Types.Array;
      + +

      Types:

      + +
        +
      • Array
      • +
      • Buffer
      • +
      • Document
      • +
      • Embedded
      • +
      • DocumentArray
      • +
      • ObjectId
      • +
      + +

      Using this exposed access to the ObjectId type, we can construct ids on demand.

      + +
      var ObjectId = mongoose.Types.ObjectId;
      +var id1 = new ObjectId;

      mongoose.Query

      The Mongoose Query constructor.

      show code
      mongoose.Query = Query;

      mongoose.Promise

      The Mongoose Promise constructor.

      show code
      mongoose.Promise = Promise;

      mongoose.Model

      The Mongoose Model constructor.

      show code
      mongoose.Model = Model;

      mongoose.Document

      The Mongoose Document constructor.

      show code
      mongoose.Document = Document;

      mongoose.Error

      The MongooseError constructor.

      show code
      mongoose.Error = require('./error');

      mongoose.mongo

      The node-mongodb-native driver Mongoose uses.

      show code
      mongoose.mongo = require('mongodb');

      Mongoose#connection

      The default connection of the mongoose module.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +mongoose.connect(...);
      +mongoose.connection.on('error', cb);
      + +

      This is the connection used by default for every model created using mongoose.model.

      Returns:


    • collection.js

      Collection(name, conn, opts)

      Abstract Collection constructor

      show code
      function Collection (name, conn, opts) {
      +  this.name = name;
      +  this.conn = conn;
      +  this.buffer = true;
      +  this.queue = [];
      +
      +  if ('number' == typeof opts) opts = { size: opts };
      +  this.opts = opts || {};
      +
      +  if (STATES.connected == this.conn.readyState) {
      +    this.onOpen();
      +  }
      +};

      Parameters:

      • name <String> name of the collection
      • conn <Connection> A MongooseConnection instance
      • opts <Object> optional collection options

      This is the base class that drivers inherit from and implement.


      Collection#onOpen()

      Called when the database connects

      show code
      Collection.prototype.onOpen = function () {
      +  var self = this;
      +  this.buffer = false;
      +  self.doQueue();
      +};

      Collection#onClose()

      Called when the database disconnects

      show code
      Collection.prototype.onClose = function () {
      +  this.buffer = true;
      +};

      Collection#addQueue(name, args)

      Queues a method for later execution when its
      database connection opens.

      show code
      Collection.prototype.addQueue = function (name, args) {
      +  this.queue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the method to queue
      • args <Array> arguments to pass to the method when executed

      Collection#doQueue()

      Executes all queued methods and clears the queue.

      show code
      Collection.prototype.doQueue = function () {
      +  for (var i = 0, l = this.queue.length; i < l; i++){
      +    this[this.queue[i][0]].apply(this, this.queue[i][1]);
      +  }
      +  this.queue = [];
      +  return this;
      +};

      Collection#ensureIndex()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.ensureIndex = function(){
      +  throw new Error('Collection#ensureIndex unimplemented by driver');
      +};

      Collection#findAndModify()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findAndModify = function(){
      +  throw new Error('Collection#findAndModify unimplemented by driver');
      +};

      Collection#findOne()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findOne = function(){
      +  throw new Error('Collection#findOne unimplemented by driver');
      +};

      Collection#find()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.find = function(){
      +  throw new Error('Collection#find unimplemented by driver');
      +};

      Collection#insert()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.insert = function(){
      +  throw new Error('Collection#insert unimplemented by driver');
      +};

      Collection#save()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.save = function(){
      +  throw new Error('Collection#save unimplemented by driver');
      +};

      Collection#update()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.update = function(){
      +  throw new Error('Collection#update unimplemented by driver');
      +};

      Collection#getIndexes()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.getIndexes = function(){
      +  throw new Error('Collection#getIndexes unimplemented by driver');
      +};

      Collection#mapReduce()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.mapReduce = function(){
      +  throw new Error('Collection#mapReduce unimplemented by driver');
      +};

      Collection#conn

      The Connection instance


      Collection#name

      The collection name


    • connection.js

      Connection(base)

      Connection constructor

      show code
      function Connection (base) {
      +  this.base = base;
      +  this.collections = {};
      +  this.models = {};
      +  this.replica = false;
      +  this.host = null;
      +  this.port = null;
      +  this.user = null;
      +  this.pass = null;
      +  this.name = null;
      +  this.options = null;
      +  this._readyState = STATES.disconnected;
      +  this._closeCalled = false;
      +  this._hasOpened = false;
      +};

      Parameters:

      Events:

      • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

      • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

      • open: Emitted after we connected and onOpen is executed on all of this connections models.

      • disconnecting: Emitted when connection.close() was executed.

      • disconnected: Emitted after getting disconnected from the db.

      • close: Emitted after we disconnected and onClose executed on all of this connections models.

      • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

      • error: Emitted when an error occurs on this connection.

      • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

      For practical reasons, a Connection equals a Db.


      Connection#open(connection_string, [database], [port], [options], [callback])

      Opens the connection to MongoDB.

      show code
      Connection.prototype.open = function (host, database, port, options, callback) {
      +  var self = this
      +    , uri;
      +
      +  if ('string' === typeof database) {
      +    switch (arguments.length) {
      +      case 2:
      +        port = 27017;
      +      case 3:
      +        switch (typeof port) {
      +          case 'function':
      +            callback = port, port = 27017;
      +            break;
      +          case 'object':
      +            options = port, port = 27017;
      +            break;
      +        }
      +        break;
      +      case 4:
      +        if ('function' === typeof options)
      +          callback = options, options = {};
      +    }
      +  } else {
      +    switch (typeof database) {
      +      case 'function':
      +        callback = database, database = undefined;
      +        break;
      +      case 'object':
      +        options = database;
      +        database = undefined;
      +        callback = port;
      +        break;
      +    }
      +
      +    if (!rgxProtocol.test(host)) {
      +      host = 'mongodb://' + host;
      +    }
      +
      +    uri = url.parse(host);
      +    host = uri.hostname;
      +    port = uri.port || 27017;
      +    database = uri.pathname && uri.pathname.replace(/\//g, '');
      +  }
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // make sure we can open
      +  if (STATES.disconnected !== this.readyState) {
      +    var err = new Error('Trying to open unclosed connection.');
      +    err.state = this.readyState;
      +    this.error(err, callback);
      +    return this;
      +  }
      +
      +  if (!host) {
      +    this.error(new Error('Missing hostname.'), callback);
      +    return this;
      +  }
      +
      +  if (!database) {
      +    this.error(new Error('Missing database name.'), callback);
      +    return this;
      +  }
      +
      +  // handle authentication
      +  if (uri && uri.auth) {
      +    var auth = uri.auth.split(':');
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // Check hostname for user/pass
      +  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
      +    host = host.split('@');
      +    var auth = host.shift().split(':');
      +    host = host.pop();
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // user/pass options
      +  } else if (options && options.user && options.pass) {
      +    this.user = options.user;
      +    this.pass = options.pass;
      +
      +  } else {
      +    this.user = this.pass = undefined;
      +  }
      +
      +  this.name = database;
      +  this.host = host;
      +  this.port = port;
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • connection_string <String> mongodb://uri or the host to which you are connecting
      • [database] <String> database name
      • [port] <Number> database port
      • [options] <Object> options
      • [callback] <Function>

      options is a hash with the following possible properties:

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSet instance
      +user    - username for authentication
      +pass    - password for authentication
      + +

      Notes:

      + +

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.


      Connection#openSet(uris, [database], [options], [callback])

      Connects to a replica set.

      show code
      Connection.prototype.openSet = function (uris, database, options, callback) {
      +  var uris = uris.split(',')
      +    , self = this;
      +
      +  switch (arguments.length) {
      +    case 3:
      +      switch (typeof database) {
      +        case 'string':
      +          this.name = database;
      +          break;
      +        case 'object':
      +          callback = options;
      +          options = database;
      +          database = null;
      +          break;
      +      }
      +
      +      if ('function' === typeof options) {
      +        callback = options;
      +        options = {};
      +      }
      +      break;
      +    case 2:
      +      switch (typeof database) {
      +        case 'string':
      +          this.name = database;
      +          break;
      +        case 'function':
      +          callback = database, database = null;
      +          break;
      +        case 'object':
      +          options = database, database = null;
      +          break;
      +      }
      +  }
      +
      +  this.options = options = this.defaultOptions(options);
      +
      +  if (uris.length < 2) {
      +    this.error(new Error('Please provide comma-separated URIs'), callback);
      +    return this;
      +  }
      +
      +  this.replica = true;
      +  this.host = [];
      +  this.port = [];
      +
      +  uris.forEach(function (uri) {
      +    // handle missing protocols
      +    if (!rgxProtocol.test(uri))
      +      uri = 'mongodb://' + uri;
      +
      +    var uri = url.parse(uri);
      +
      +    self.host.push(uri.hostname);
      +    self.port.push(uri.port || 27017);
      +
      +    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
      +      self.name = uri.pathname.replace(/\//g, '');
      +
      +    if (!self.user && uri.auth) {
      +      var auth = uri.auth.split(':');
      +      self.user = auth[0];
      +      self.pass = auth[1];
      +    }
      +  });
      +
      +  if (!this.name) {
      +    this.error(new Error('No database name provided for replica set'), callback);
      +    return this;
      +  }
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • uris <String> comma-separated mongodb:// `URI`s
      • [database] <String> database name if not included in `uris`
      • [options] <Object> passed to the internal driver
      • [callback] <Function>

      Example:

      + +
      var db = mongoose.createConnection();
      +db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
      + +

      The database name and/or auth need only be included in one URI.
      The options is a hash which is passed to the internal driver connection object.

      + +

      Valid options

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSetServer instance
      +user    - username for authentication
      +pass    - password for authentication

      Connection#error(err, callback)

      error

      show code
      Connection.prototype.error = function (err, callback) {
      +  if (callback) return callback(err);
      +  this.emit('error', err);
      +}

      Parameters:

      Graceful error handling, passes error to callback
      if available, else emits error on the connection.


      Connection#_open(callback)

      Handles opening the connection with the appropriate method based on connection type.

      show code
      Connection.prototype._open = function (callback) {
      +  this.readyState = STATES.connecting;
      +  this._closeCalled = false;
      +
      +  var self = this;
      +
      +  var method = this.replica
      +    ? 'doOpenSet'
      +    : 'doOpen';
      +
      +  // open connection
      +  this[method](function (err) {
      +    if (err) {
      +      self.readyState = STATES.disconnected;
      +      if (self._hasOpened) {
      +        if (callback) callback(err);
      +      } else {
      +        self.error(err, callback);
      +      }
      +      return;
      +    }
      +
      +    self.onOpen();
      +    callback && callback();
      +  });
      +}

      Parameters:


      Connection#onOpen()

      Called when the connection is opened

      show code
      Connection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  function open () {
      +    self.readyState = STATES.connected;
      +
      +    // avoid having the collection subscribe to our event emitter
      +    // to prevent 0.3 warning
      +    for (var i in self.collections)
      +      self.collections[i].onOpen();
      +
      +    self.emit('open');
      +  };
      +
      +  // re-authenticate
      +  if (self.user && self.pass)
      +    self.db.authenticate(self.user, self.pass, open);
      +  else
      +    open();
      +};

      Connection#close([callback])

      Closes the connection

      show code
      Connection.prototype.close = function (callback) {
      +  var self = this;
      +  this._closeCalled = true;
      +
      +  switch (this.readyState){
      +    case 0: // disconnected
      +      callback && callback();
      +      break;
      +
      +    case 1: // connected
      +      this.readyState = STATES.disconnecting;
      +      this.doClose(function(err){
      +        if (err){
      +          self.error(err, callback);
      +        } else {
      +          self.onClose();
      +          callback && callback();
      +        }
      +      });
      +      break;
      +
      +    case 2: // connecting
      +      this.once('open', function(){
      +        self.close(callback);
      +      });
      +      break;
      +
      +    case 3: // disconnecting
      +      if (!callback) break;
      +      this.once('close', function () {
      +        callback();
      +      });
      +      break;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Connection#onClose()

      Called when the connection closes

      show code
      Connection.prototype.onClose = function () {
      +  this.readyState = STATES.disconnected;
      +
      +  // avoid having the collection subscribe to our event emitter
      +  // to prevent 0.3 warning
      +  for (var i in this.collections)
      +    this.collections[i].onClose();
      +
      +  this.emit('close');
      +};

      Connection#collection(name, [options])

      Retrieves a collection, creating it if not cached.

      show code
      Connection.prototype.collection = function (name, options) {
      +  if (!(name in this.collections))
      +    this.collections[name] = new Collection(name, this, options);
      +  return this.collections[name];
      +};

      Parameters:

      • name <String> of the collection
      • [options] <Object> optional collection options

      Returns:


      Connection#model(name, [schema], [collection])

      Defines or retrieves a model.

      show code
      Connection.prototype.model = function (name, schema, collection) {
      +  if (!this.models[name]) {
      +    var model = this.base.model(name, schema, collection, true)
      +      , Model
      +
      +    if (this != model.prototype.db) {
      +      // subclass model using this connection and collection name
      +      Model = function Model (doc, fields, skipId) {
      +        if (!(this instanceof Model))
      +          return new Model(doc, fields, skipId);
      +        model.call(this, doc, fields, skipId);
      +      };
      +
      +      Model.__proto__ = model;
      +      Model.prototype.__proto__ = model.prototype;
      +      Model.db = Model.prototype.db = this;
      +
      +      // collection name discovery
      +      if ('string' === typeof schema) {
      +        collection = schema;
      +      }
      +
      +      if (!collection) {
      +        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
      +      }
      +
      +      var s = 'string' != typeof schema
      +        ? schema
      +        : model.prototype.schema;
      +
      +      Model.prototype.collection = this.collection(collection, s && s.options.capped);
      +      Model.collection = Model.prototype.collection;
      +      Model.init();
      +    }
      +
      +    this.models[name] = Model || model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> the model name
      • [schema] <Schema> a schema. necessary when defining a model
      • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

      Returns:

      • <Model> The compiled model
      var mongoose = require('mongoose');
      +var db = mongoose.createConnection(..);
      +db.model('Venue', new Schema(..));
      +var Ticket = db.model('Ticket', new Schema(..));
      +var Venue = db.model('Venue');

      Connection#setProfiling(level, [ms], callback)

      Set profiling level.

      show code
      Connection.prototype.setProfiling = function (level, ms, callback) {
      +  if (STATES.connected !== this.readyState) {
      +    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
      +  }
      +
      +  if (!callback) callback = ms, ms = 100;
      +
      +  var cmd = {};
      +
      +  switch (level) {
      +    case 0:
      +    case 'off':
      +      cmd.profile = 0;
      +      break;
      +    case 1:
      +    case 'slow':
      +      cmd.profile = 1;
      +      if ('number' !== typeof ms) {
      +        ms = parseInt(ms, 10);
      +        if (isNaN(ms)) ms = 100;
      +      }
      +      cmd.slowms = ms;
      +      break;
      +    case 2:
      +    case 'all':
      +      cmd.profile = 2;
      +      break;
      +    default:
      +      return callback(new Error('Invalid profiling level: '+ level));
      +  }
      +
      +  this.db.executeDbCommand(cmd, function (err, resp) {
      +    if (err) return callback(err);
      +
      +    var doc = resp.documents[0];
      +
      +    err = 1 === doc.ok
      +      ? null
      +      : new Error('Could not set profiling level to: '+ level)
      +
      +    callback(err, doc);
      +  });
      +};

      Parameters:

      • level <Number, String> either off (0), slow (1), or all (2)
      • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
      • callback <Function>

      Connection#defaultOptions(options)

      Prepares default connection options.

      show code
      Connection.prototype.defaultOptions = function (options) {
      +  var o = options || {};
      +
      +  o.server = o.server || {};
      +
      +  if (!('auto_reconnect' in o.server)) {
      +    o.server.auto_reconnect = true;
      +  }
      +
      +  o.db || (o.db = {});
      +  o.db.forceServerObjectId = false;
      +
      +  // TODO default to true once the driver is fixed
      +  if (!('safe' in o.db)) o.db.safe = false;
      +
      +  return o;
      +}

      Parameters:


      Connection#db

      The mongodb.Db instance, set when the connection is opened


      Connection#collections

      A hash of the collections associated with this connection


      Connection#readyState

      Connection ready state

      + +
        +
      • 0 = disconnected
      • +
      • 1 = connected
      • +
      • 2 = connecting
      • +
      • 3 = disconnecting
      • +
      + +

      Each state change emits its associated event name.

      + +

      Example

      + +
      conn.on('connected', callback);
      +conn.on('disconnected', callback);

    • document.js

      Document(obj, [fields], [skipId])

      Document constructor.

      show code
      function Document (obj, fields, skipId) {
      +  // node <0.4.3 bug
      +  if (!this._events) this._events = {};
      +  this.setMaxListeners(0);
      +
      +  if ('boolean' === typeof fields) {
      +    this._strictMode = fields;
      +    this._selected = fields = undefined;
      +  } else {
      +    this._strictMode = this.schema.options && this.schema.options.strict;
      +    this._selected = fields;
      +  }
      +
      +  this.isNew = true;
      +  this.errors = undefined;
      +  this._shardval = undefined;
      +  this._saveError = undefined;
      +  this._validationError = undefined;
      +  this._adhocPaths = undefined;
      +  this._removing = undefined;
      +  this._inserting = undefined;
      +  this.__version = undefined;
      +  this.__getters = {};
      +  this.__id = undefined;
      +
      +  this._activePaths = new ActiveRoster;
      +
      +  var required = this.schema.requiredPaths();
      +  for (var i = 0; i < required.length; ++i) {
      +    this._activePaths.require(required[i]);
      +  }
      +
      +  this._doc = this._buildDoc(obj, fields, skipId);
      +  if (obj) this.set(obj, undefined, true);
      +  this._registerHooks();
      +};

      Parameters:

      • obj <Object> the values to set
      • [fields] <Object> the fields which were selected in the query returning this document
      • [skipId] <Boolean> bool, should we auto create an ObjectId _id

      Events:

      • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

      • save: Emitted when the document is successfully saved


      Document#_buildDoc(obj, [fields], [skipId])

      Builds the default doc structure

      show code
      Document.prototype._buildDoc = function (obj, fields, skipId) {
      +  var doc = {}
      +    , self = this
      +    , exclude
      +    , keys
      +    , key
      +    , ki
      +
      +  // determine if this doc is a result of a query with
      +  // excluded fields
      +  if (fields && 'Object' === fields.constructor.name) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('_id' !== keys[ki]) {
      +        exclude = 0 === fields[keys[ki]];
      +        break;
      +      }
      +    }
      +  }
      +
      +  var paths = Object.keys(this.schema.paths)
      +    , plen = paths.length
      +    , ii = 0
      +
      +  for (; ii < plen; ++ii) {
      +    var p = paths[ii];
      +
      +    if ('_id' == p) {
      +      if (skipId) continue;
      +      if (obj && '_id' in obj) continue;
      +    }
      +
      +    var type = this.schema.paths[p]
      +      , path = p.split('.')
      +      , len = path.length
      +      , last = len-1
      +      , doc_ = doc
      +      , i = 0
      +
      +    for (; i < len; ++i) {
      +      var piece = path[i]
      +        , def
      +
      +      if (i === last) {
      +        if (fields) {
      +          if (exclude) {
      +            // apply defaults to all non-excluded fields
      +            if (p in fields) continue;
      +
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +
      +          } else if (p in fields) {
      +            // selected field
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +          }
      +        } else {
      +          def = type.getDefault(self, true);
      +          if ('undefined' !== typeof def) {
      +            doc_[piece] = def;
      +            self._activePaths.default(p);
      +          }
      +        }
      +      } else {
      +        doc_ = doc_[piece] || (doc_[piece] = {});
      +      }
      +    }
      +  };
      +
      +  return doc;
      +};

      Parameters:

      Returns:


      Document#init(doc, fn)

      Initializes the document without setters or marking anything modified.

      show code
      Document.prototype.init = function (doc, fn) {
      +  this.isNew = false;
      +
      +  init(this, doc, this._doc);
      +  this._storeShard();
      +
      +  this.emit('init');
      +  if (fn) fn(null);
      +  return this;
      +};

      Parameters:

      Called internally after a document is returned from mongodb.


      Document#_storeShard()

      Stores the current values of the shard keys.

      show code
      Document.prototype._storeShard = function _storeShard () {
      +  // backwards compat
      +  var key = this.schema.options.shardKey || this.schema.options.shardkey;
      +  if (!(key && 'Object' == key.constructor.name)) return;
      +
      +  var orig = this._shardval = {}
      +    , paths = Object.keys(key)
      +    , len = paths.length
      +    , val
      +
      +  for (var i = 0; i < len; ++i) {
      +    val = this.getValue(paths[i]);
      +    if (isMongooseObject(val)) {
      +      orig[paths[i]] = val.toObject({ depopulate: true })
      +    } else if (null != val && val.valueOf) {
      +      orig[paths[i]] = val.valueOf();
      +    } else {
      +      orig[paths[i]] = val;
      +    }
      +  }
      +}

      Note:

      + +

      Shard key values do not / are not allowed to change.


      Document#update(doc, options, callback)

      Sends an update command with this document _id as the query selector.

      show code
      Document.prototype.update = function update () {
      +  var args = utils.args(arguments);
      +  args.unshift({_id: this._id});
      +  this.constructor.update.apply(this.constructor, args);
      +}

      Parameters:

      Returns:

      Example:

      + +
      weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
      + +

      Valid options:

      + +
        +
      • safe safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +

      Document#set(path, val, [type], [options])

      Sets the value of a path, or many paths.

      show code
      Document.prototype.set = function (path, val, type, options) {
      +  if (type && 'Object' == type.constructor.name) {
      +    options = type;
      +    type = undefined;
      +  }
      +
      +  var merge = options && options.merge
      +    , adhoc = type && true !== type
      +    , constructing = true === type
      +    , adhocs
      +
      +  if (adhoc) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  if ('string' !== typeof path) {
      +    // new Document({ key: val })
      +
      +    if (null === path || undefined === path) {
      +      var _ = path;
      +      path = val;
      +      val = _;
      +
      +    } else {
      +      var prefix = val
      +        ? val + '.'
      +        : '';
      +
      +      if (path instanceof Document) path = path._doc;
      +
      +      var keys = Object.keys(path)
      +        , i = keys.length
      +        , pathtype
      +        , key
      +
      +      while (i--) {
      +        key = keys[i];
      +        if (null != path[key] && 'Object' === path[key].constructor.name
      +          && !(this._path(prefix + key) instanceof MixedSchema)) {
      +          this.set(path[key], prefix + key, constructing);
      +        } else if (this._strictMode) {
      +          pathtype = this.schema.pathType(prefix + key);
      +          if ('real' === pathtype || 'virtual' === pathtype) {
      +            this.set(prefix + key, path[key], constructing);
      +          } else if ('throw' == this._strictMode) {
      +            throw new Error("Field `" + key + "` is not in schema.");
      +          }
      +        } else if (undefined !== path[key]) {
      +          this.set(prefix + key, path[key], constructing);
      +        }
      +      }
      +
      +      return this;
      +    }
      +  }
      +
      +  // ensure _strict is honored for obj props
      +  // docschema = new Schema({ path: { nest: 'string' }})
      +  // doc.set('path', obj);
      +  var pathType = this.schema.pathType(path);
      +  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
      +    if (!merge) this.setValue(path, null);
      +    this.set(val, path, constructing);
      +    return this;
      +  }
      +
      +  var schema;
      +  if ('adhocOrUndefined' == pathType && this._strictMode) {
      +    return this;
      +  } else if ('virtual' == pathType) {
      +    schema = this.schema.virtualpath(path);
      +    schema.applySetters(val, this);
      +    return this;
      +  } else {
      +    schema = this._path(path);
      +  }
      +
      +  var parts = path.split('.')
      +    , pathToMark
      +
      +  // When using the $set operator the path to the field must already exist.
      +  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
      +
      +  if (parts.length <= 1) {
      +    pathToMark = path;
      +  } else {
      +    for (var i = 0; i < parts.length; ++i) {
      +      var part = parts[i];
      +      var subpath = parts.slice(0, i).concat(part).join('.');
      +      if (this.isDirectModified(subpath) // earlier prefixes that are already
      +                                         // marked as dirty have precedence
      +          || this.get(subpath) === null) {
      +        pathToMark = subpath;
      +        break;
      +      }
      +    }
      +
      +    if (!pathToMark) pathToMark = path;
      +  }
      +
      +  if (!schema || null === val || undefined === val) {
      +    this._set(pathToMark, path, constructing, parts, schema, val);
      +    return this;
      +  }
      +
      +  var self = this;
      +
      +  // if this doc is being constructed we should not
      +  // trigger getters.
      +  var priorVal = constructing
      +    ? undefined
      +    : this.get(path);
      +
      +  var shouldSet = this.try(function(){
      +    val = schema.applySetters(val, self, false, priorVal);
      +  });
      +
      +  if (shouldSet) {
      +    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
      +  }
      +
      +  return this;
      +}

      Parameters:

      • path <String, Object> path or object of key/vals to set
      • val <Any> the value to set
      • [type] <Schema, String, Number, Buffer, etc..> optionally specify a type for "on-the-fly" attributes
      • [options] <Object> optionally specify options that modify the behavior of the set

      Example:

      + +
      // path, value
      +doc.set(path, value)
      +
      +// object
      +doc.set({
      +    path  : value
      +  , path2 : {
      +       path  : value
      +    }
      +})
      +
      +// only-the-fly cast to number
      +doc.set(path, value, Number)
      +
      +// only-the-fly cast to string
      +doc.set(path, value, String)

      Document#_shouldModify()

      Determine if we should mark this change as modified.

      show code
      Document.prototype._shouldModify = function (
      +    pathToMark, path, constructing, parts, schema, val, priorVal) {
      +
      +  if (this.isNew) return true;
      +  if (this.isDirectModified(pathToMark)) return false;
      +
      +  if (undefined === val && !this.isSelected(path)) {
      +    // when a path is not selected in a query, its initial
      +    // value will be undefined.
      +    return true;
      +  }
      +
      +  if (undefined === val && path in this._activePaths.states.default) {
      +    // we're just unsetting the default value which was never saved
      +    return false;
      +  }
      +
      +  if (!deepEqual(val, priorVal || this.get(path))) {
      +    return true;
      +  }
      +
      +  if (!constructing &&
      +      null != val &&
      +      path in this._activePaths.states.default &&
      +      deepEqual(val, schema.getDefault(this, constructing))) {
      +    // a path with a default was $unset on the server
      +    // and the user is setting it to the same value again
      +    return true;
      +  }
      +
      +  return false;
      +}

      Returns:


      Document#_set()

      Handles the actual setting of the value and marking the path modified if appropriate.

      show code
      Document.prototype._set = function (
      +    pathToMark, path, constructing, parts, schema, val, priorVal) {
      +
      +  var shouldModify = this._shouldModify.apply(this, arguments);
      +
      +  if (shouldModify) {
      +    this.markModified(pathToMark, val);
      +
      +    // handle directly setting arrays (gh-1126)
      +    MongooseArray || (MongooseArray = require('./types/array'));
      +    if (val instanceof MongooseArray) {
      +      val._registerAtomic('$set', val);
      +    }
      +  }
      +
      +  var obj = this._doc
      +    , i = 0
      +    , l = parts.length
      +
      +  for (; i < l; i++) {
      +    var next = i + 1
      +      , last = next === l;
      +
      +    if (last) {
      +      obj[parts[i]] = val;
      +    } else {
      +      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
      +        obj = obj[parts[i]];
      +      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
      +        obj = obj[parts[i]];
      +      } else {
      +        obj = obj[parts[i]] = {};
      +      }
      +    }
      +  }
      +}

      Document#getValue(path)

      Gets a raw value from a path (no getters)

      show code
      Document.prototype.getValue = function (path) {
      +  var parts = path.split('.')
      +    , obj = this._doc
      +    , part;
      +
      +  for (var i = 0, l = parts.length; i < l; i++) {
      +    part = parts[i];
      +    obj = obj.getValue
      +        ? obj.getValue(part) // If we have an embedded array document member
      +        : obj[part];
      +    if (!obj) return obj;
      +  }
      +
      +  return obj;
      +}

      Parameters:


      Document#setValue(path, value)

      Sets a raw value for a path (no casting, setters, transformations)

      show code
      Document.prototype.setValue = function (path, val) {
      +  var parts = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, len = parts.length-1; i < len; i++) {
      +    obj = obj[parts[i]];
      +  }
      +
      +  obj[parts[len]] = val;
      +  return this;
      +};

      Parameters:


      Document#get(path, [type])

      Returns the value of a path.

      show code
      Document.prototype.get = function (path, type) {
      +  var adhocs;
      +  if (type) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  var schema = this._path(path) || this.schema.virtualpath(path)
      +    , pieces = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, l = pieces.length; i < l; i++) {
      +    obj = null == obj ? null : obj[pieces[i]];
      +  }
      +
      +  if (schema) {
      +    obj = schema.applyGetters(obj, this);
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Example

      + +
      // path
      +doc.get('age') // 47
      +
      +// dynamic casting to a string
      +doc.get('age', String) // "47"

      Document#_path(path)

      Returns the schematype for the given path.

      show code
      Document.prototype._path = function (path) {
      +  var adhocs = this._adhocPaths
      +    , adhocType = adhocs && adhocs[path];
      +
      +  if (adhocType) {
      +    return adhocType;
      +  } else {
      +    return this.schema.path(path);
      +  }
      +};

      Parameters:


      Document#markModified(path)

      Marks the path as having pending changes to write to the db.

      show code
      Document.prototype.markModified = function (path) {
      +  this._activePaths.modify(path);
      +}

      Parameters:

      • path <String> the path to mark modified

      Very helpful when using Mixed types.

      + +

      Example:

      + +
      doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');
      +doc.save() // changes to mixed.type are now persisted

      Document#try(fn, scope)

      Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

      show code
      Document.prototype.try = function (fn, scope) {
      +  var res;
      +  try {
      +    fn.call(scope);
      +    res = true;
      +  } catch (e) {
      +    this._error(e);
      +    res = false;
      +  }
      +  return res;
      +};

      Parameters:

      • fn <Function> function to execute
      • scope <Object> the scope with which to call fn

      Document#modifiedPaths()

      Returns the list of paths that have been modified.

      show code
      Document.prototype.modifiedPaths = function () {
      +  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
      +
      +  return directModifiedPaths.reduce(function (list, path) {
      +    var parts = path.split('.');
      +    return list.concat(parts.reduce(function (chains, part, i) {
      +      return chains.concat(parts.slice(0, i).concat(part).join('.'));
      +    }, []));
      +  }, []);
      +};

      Returns:


      Document#isModified([path])

      Returns true if this document was modified, else false.

      show code
      Document.prototype.isModified = function (path) {
      +  return path
      +    ? !!~this.modifiedPaths().indexOf(path)
      +    : this._activePaths.some('modify');
      +};

      Parameters:

      Returns:

      If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

      + +

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isModified()                    // true
      +doc.isModified('documents')         // true
      +doc.isModified('documents.0.title') // true
      +doc.isDirectModified('documents')   // false

      Document#isDirectModified(path)

      Returns true if path was directly set and modified, else false.

      show code
      Document.prototype.isDirectModified = function (path) {
      +  return (path in this._activePaths.states.modify);
      +};

      Parameters:

      Returns:

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isDirectModified('documents.0.title') // true
      +doc.isDirectModified('documents') // false

      Document#isInit(path)

      Checks if path was initialized.

      show code
      Document.prototype.isInit = function (path) {
      +  return (path in this._activePaths.states.init);
      +};

      Parameters:

      Returns:


      Document#isSelected(path)

      Checks if path was selected in the source query which initialized this document.

      show code
      Document.prototype.isSelected = function isSelected (path) {
      +  if (this._selected) {
      +
      +    if ('_id' === path) {
      +      return 0 !== this._selected._id;
      +    }
      +
      +    var paths = Object.keys(this._selected)
      +      , i = paths.length
      +      , inclusive = false
      +      , cur
      +
      +    if (1 === i && '_id' === paths[0]) {
      +      // only _id was selected.
      +      return 0 === this._selected._id;
      +    }
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +      inclusive = !! this._selected[cur];
      +      break;
      +    }
      +
      +    if (path in this._selected) {
      +      return inclusive;
      +    }
      +
      +    i = paths.length;
      +    var pathDot = path + '.';
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +
      +      if (0 === cur.indexOf(pathDot)) {
      +        return inclusive;
      +      }
      +
      +      if (0 === pathDot.indexOf(cur)) {
      +        return inclusive;
      +      }
      +    }
      +
      +    return ! inclusive;
      +  }
      +
      +  return true;
      +}

      Parameters:

      Returns:

      Example

      + +
      Thing.findOne().select('name').exec(function (err, doc) {
      +   doc.isSelected('name') // true
      +   doc.isSelected('age')  // false
      +})

      Document#validate(cb)

      Executes registered validation rules for this document.

      show code
      Document.prototype.validate = function (cb) {
      +  var self = this
      +
      +  // only validate required fields when necessary
      +  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
      +    if (!self.isSelected(path) && !self.isModified(path)) return false;
      +    return true;
      +  });
      +
      +  paths = paths.concat(Object.keys(this._activePaths.states.init));
      +  paths = paths.concat(Object.keys(this._activePaths.states.modify));
      +  paths = paths.concat(Object.keys(this._activePaths.states.default));
      +
      +  if (0 === paths.length) {
      +    complete();
      +    return this;
      +  }
      +
      +  var validating = {}
      +    , total = 0;
      +
      +  paths.forEach(validatePath);
      +  return this;
      +
      +  function validatePath (path) {
      +    if (validating[path]) return;
      +
      +    validating[path] = true;
      +    total++;
      +
      +    process.nextTick(function(){
      +      var p = self.schema.path(path);
      +      if (!p) return --total || complete();
      +
      +      p.doValidate(self.getValue(path), function (err) {
      +        if (err) self.invalidate(path, err, true);
      +        --total || complete();
      +      }, self);
      +    });
      +  }
      +
      +  function complete () {
      +    var err = self._validationError;
      +    self._validationError = undefined;
      +    cb(err);
      +  }
      +};

      Parameters:

      • cb <Function> called after validation completes, passing an error if one occurred

      Note:

      + +

      This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

      + +

      Example:

      + +
      doc.validate(function (err) {
      +  if (err) handleError(err);
      +  else // validation passed
      +});

      Document#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      Document.prototype.invalidate = function (path, err) {
      +  if (!this._validationError) {
      +    this._validationError = new ValidationError(this);
      +  }
      +
      +  if (!err || 'string' === typeof err) {
      +    err = new ValidatorError(path, err);
      +  }
      +
      +  this._validationError.errors[path] = err;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> the error which states the reason `path` was invalid

      Document#_reset()

      Resets the internal modified state of this document.

      show code
      Document.prototype._reset = function reset () {
      +  var self = this;
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this._activePaths
      +  .map('init', 'modify', function (i) {
      +    return self.getValue(i);
      +  })
      +  .filter(function (val) {
      +    return val && val instanceof DocumentArray && val.length;
      +  })
      +  .forEach(function (array) {
      +    var i = array.length;
      +    while (i--) {
      +      var doc = array[i];
      +      if (!doc) continue;
      +      doc._reset();
      +    }
      +  });
      +
      +  // clear atomics
      +  this._dirty().forEach(function (dirt) {
      +    var type = dirt.value;
      +    if (type && type._atomics) {
      +      type._atomics = {};
      +    }
      +  });
      +
      +  // Clear 'modify'('dirty') cache
      +  this._activePaths.clear('modify');
      +  this._validationError = undefined;
      +  this.errors = undefined;
      +  var self = this;
      +  this.schema.requiredPaths().forEach(function (path) {
      +    self._activePaths.require(path);
      +  });
      +
      +  return this;
      +}

      Returns:


      Document#_dirty()

      Returns this documents dirty paths / vals.

      show code
      Document.prototype._dirty = function _dirty () {
      +  var self = this;
      +
      +  var all = this._activePaths.map('modify', function (path) {
      +    return { path: path
      +           , value: self.getValue(path)
      +           , schema: self._path(path) };
      +  });
      +
      +  // Sort dirty paths in a flat hierarchy.
      +  all.sort(function (a, b) {
      +    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
      +  });
      +
      +  // Ignore "foo.a" if "foo" is dirty already.
      +  var minimal = []
      +    , lastPath
      +    , top;
      +
      +  all.forEach(function (item, i) {
      +    if (item.path.indexOf(lastPath) !== 0) {
      +      lastPath = item.path + '.';
      +      minimal.push(item);
      +      top = item;
      +    } else {
      +      if (!(item.value && top.value)) return;
      +
      +      // special case for top level MongooseArrays
      +      if (top.value._atomics && top.value.hasAtomics()) {
      +        // the `top` array itself and a sub path of `top` are being modified.
      +        // the only way to honor all of both modifications is through a $set
      +        // of entire array.
      +        top.value._atomics = {};
      +        top.value._atomics.$set = top.value;
      +      }
      +    }
      +  });
      +
      +  top = lastPath = null;
      +  return minimal;
      +}

      Document#_setSchema(schema)

      Assigns/compiles schema into this documents prototype.

      show code
      Document.prototype._setSchema = function (schema) {
      +  compile(schema.tree, this);
      +  this.schema = schema;
      +}

      Parameters:


      Document#_registerHooks()

      Register default hooks

      show code
      Document.prototype._registerHooks = function _registerHooks () {
      +  if (!this.save) return;
      +
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this.pre('save', function (next) {
      +    // we keep the error semaphore to make sure we don't
      +    // call `save` unnecessarily (we only need 1 error)
      +    var subdocs = 0
      +      , error = false
      +      , self = this;
      +
      +    // check for DocumentArrays
      +    var arrays = this._activePaths
      +    .map('init', 'modify', function (i) {
      +      return self.getValue(i);
      +    })
      +    .filter(function (val) {
      +      return val && val instanceof DocumentArray && val.length;
      +    });
      +
      +    if (!arrays.length)
      +      return next();
      +
      +    arrays.forEach(function (array) {
      +      if (error) return;
      +
      +      // handle sparse arrays by using for loop vs array.forEach
      +      // which skips the sparse elements
      +
      +      var len = array.length
      +      subdocs += len;
      +
      +      for (var i = 0; i < len; ++i) {
      +        if (error) break;
      +
      +        var doc = array[i];
      +        if (!doc) {
      +          --subdocs || next();
      +          continue;
      +        }
      +
      +        doc.save(handleSave);
      +      }
      +    });
      +
      +    function handleSave (err) {
      +      if (error) return;
      +
      +      if (err) {
      +        self._validationError = undefined;
      +        return next(error = err);
      +      }
      +
      +      --subdocs || next();
      +    }
      +
      +  }, function (err) {
      +    // emit on the Model if listening
      +    if (this.constructor.listeners('error').length) {
      +      this.constructor.emit('error', err);
      +    } else {
      +      // emit on the connection
      +      if (!this.db.listeners('error').length) {
      +        err.stack = 'No listeners detected, throwing. '
      +                  + 'Consider adding an error listener to your connection.
      +'
      +                  + err.stack
      +      }
      +      this.db.emit('error', err);
      +    }
      +  }).pre('save', function checkForExistingErrors (next) {
      +    // if any doc.set() calls failed
      +    if (this._saveError) {
      +      next(this._saveError);
      +      this._saveError = null;
      +    } else {
      +      next();
      +    }
      +  }).pre('save', function validation (next) {
      +    return this.validate(next);
      +  });
      +
      +  // add user defined queues
      +  this._doQueue();
      +};

      Document#_error(err)

      Registers an error

      show code
      Document.prototype._error = function (err) {
      +  this._saveError = err;
      +  return this;
      +};

      Parameters:


      Document#_doQueue()

      Executes methods queued from the Schema definition

      show code
      Document.prototype._doQueue = function () {
      +  var q = this.schema && this.schema.callQueue;
      +  if (q) {
      +    for (var i = 0, l = q.length; i < l; i++) {
      +      this[q[i][0]].apply(this, q[i][1]);
      +    }
      +  }
      +  return this;
      +};

      Document#toObject([options])

      Converts this document into a plain javascript object

      show code
      Document.prototype.toObject = function (options) {
      +  // When internally saving this document we always pass options,
      +  // bypassing the custom schema options.
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toObject
      +      ? clone(this.schema.options.toObject)
      +      : {};
      +  }
      +
      +  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
      +
      +  var ret = clone(this._doc, options);
      +
      +  if (options.virtuals || options.getters && false !== options.virtuals) {
      +    applyGetters(this, ret, 'virtuals', options);
      +  }
      +
      +  if (options.getters) {
      +    applyGetters(this, ret, 'paths', options);
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Options:

      + +
        +
      • getters apply all getters (path and virtual getters)
      • +
      • virtuals apply virtual getters (can override getters option)
      • +
      • minimize remove empty objects (defaults to true)
      • +
      + +

      Example of only applying path getters

      + +
      doc.toObject({ getters: true, virtuals: false })
      + +

      Example of only applying virtual getters

      + +
      doc.toObject({ virtuals: true })
      + +

      Example of applying both path and virtual getters

      + +
      doc.toObject({ getters: true })
      + +

      To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

      + +
      schema.set('toObject', { virtuals: true })
      + +

      See schema options for details.


      Document#toJSON(options)

      The return value of this method is used in calls to JSON.stringify(doc).

      show code
      Document.prototype.toJSON = function (options) {
      +  // check for object type since an array of documents
      +  // being stringified passes array indexes instead
      +  // of options objects. JSON.stringify([doc, doc])
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toJSON
      +      ? clone(this.schema.options.toJSON)
      +      : {};
      +  }
      +  options.json = true;
      +  return this.toObject(options);
      +};

      Parameters:

      • options <Object> same options as `Document#toObject`

      Returns:

      This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

      + +
      schema.set('toJSON', { virtuals: true })
      + +

      See schema options for details.


      Document#inspect()

      Helper for console.log

      show code
      Document.prototype.inspect = function (options) {
      +  var opts = options && 'Object' == options.constructor.name
      +    ? options
      +    : undefined
      +  return inspect(this.toObject(opts));
      +};

      Document#toString()

      Helper for console.log


      Document#equals(doc)

      Returns true if the Document stores the same data as doc.

      show code
      Document.prototype.equals = function (doc) {
      +  var tid = this.get('_id');
      +  var docid = doc.get('_id');
      +  return tid.equals
      +    ? tid.equals(docid)
      +    : tid === docid;
      +};

      Parameters:

      Returns:

      Documents are considered equal when they have matching _ids.


      Document#errors

      Hash containing current validation errors.


      Document#id

      The string version of this documents _id.

      + +

      Note:

      + +

      This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

      + +
      new Schema({ name: String }, { id: false });

      Document#isNew

      Boolean flag specifying if the document is new.


      Document#schema

      The documents schema.


    • drivers/node-mongodb-native/collection.js

      NativeCollection()

      A node-mongodb-native collection implementation.

      show code
      function NativeCollection () {
      +  this.collection = null;
      +  MongooseCollection.apply(this, arguments);
      +}

      Inherits:

      All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


      NativeCollection#onOpen()

      Called when the connection opens.

      show code
      NativeCollection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  if (this.collection) {
      +    return MongooseCollection.prototype.onOpen.call(self);
      +  }
      +
      +  if (!self.opts.size) {
      +    // non-capped
      +    return self.conn.db.collection(self.name, callback);
      +  }
      +
      +  // capped
      +  return self.conn.db.collection(self.name, function (err, c) {
      +    if (err) return callback(err);
      +
      +    // discover if this collection exists and if it is capped
      +    c.options(function (err, exists) {
      +      if (err) return callback(err);
      +
      +      if (exists) {
      +        if (exists.capped) {
      +          callback(null, c);
      +        } else {
      +          var msg = 'A non-capped collection exists with this name.
      +
      +'
      +                  + ' To use this collection as a capped collection, please '
      +                  + 'first convert it.
      +'
      +                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
      +          err = new Error(msg);
      +          callback(err);
      +        }
      +      } else {
      +        // create
      +        var opts = utils.clone(self.opts);
      +        opts.capped = true;
      +        self.conn.db.createCollection(self.name, opts, callback);
      +      }
      +    });
      +  });
      +
      +  function callback (err, collection) {
      +    if (err) {
      +      // likely a strict mode error
      +      self.conn.emit('error', err);
      +    } else {
      +      self.collection = collection;
      +      MongooseCollection.prototype.onOpen.call(self);
      +    }
      +  };
      +};

      NativeCollection#onClose()

      Called when the connection closes

      show code
      NativeCollection.prototype.onClose = function () {
      +  MongooseCollection.prototype.onClose.call(this);
      +};

      NativeCollection#getIndexes(callback)

      Retreives information about this collections indexes.

      Parameters:


    • drivers/node-mongodb-native/connection.js

      NativeConnection()

      A node-mongodb-native connection implementation.

      show code
      function NativeConnection() {
      +  MongooseConnection.apply(this, arguments);
      +};

      Inherits:


      NativeConnection#doOpen(fn)

      Opens the connection to MongoDB.

      show code
      NativeConnection.prototype.doOpen = function (fn) {
      +  var server
      +    , self = this;
      +
      +  if (!this.db) {
      +    server = new mongo.Server(this.host, Number(this.port), this.options.server);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};
      +
      +function listen (conn) {
      +  if (conn._listening) return;
      +  conn._listening = true;
      +
      +  conn.db.on('close', function(){
      +    if (conn._closeCalled) return;
      +
      +    // the driver never emits an `open` event. auto_reconnect still
      +    // emits a `close` event but since we never get another
      +    // `open` we can't emit close
      +    if (conn.db.serverConfig.autoReconnect) {
      +      conn.readyState = STATES.disconnected;
      +      conn.emit('close');
      +      return;
      +    }
      +    conn.onClose();
      +  });
      +  conn.db.on('error', function(err){
      +    conn.emit('error', err);
      +  });
      +  conn.db.on('timeout', function(err){
      +    var error = new Error(err && err.err || 'connection timeout');
      +    conn.emit('error', error);
      +  });
      +  conn.db.on('open', function (err, db) {
      +    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
      +      conn.readyState = STATES.connected;
      +      conn.emit('reconnected')
      +    }
      +  })
      +}

      Parameters:

      Returns:


      NativeConnection#doOpenSet(fn)

      Opens a connection to a MongoDB ReplicaSet.

      show code
      NativeConnection.prototype.doOpenSet = function (fn) {
      +  if (!this.db) {
      +    var servers = []
      +      , ports = this.port
      +      , self = this
      +
      +    this.host.forEach(function (host, i) {
      +      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
      +    });
      +
      +    var server = new ReplSetServers(servers, this.options.replset);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +
      +    this.db.on('fullsetup', function () {
      +      self.emit('fullsetup')
      +    });
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:

      See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


      NativeConnection#doClose(fn)

      Closes the connection

      show code
      NativeConnection.prototype.doClose = function (fn) {
      +  this.db.close();
      +  if (fn) fn();
      +  return this;
      +}

      Parameters:

      Returns:


    • error.js

      MongooseError()

      Mongoose error

      show code
      function MongooseError (msg) {
      +  Error.call(this);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.message = msg;
      +  this.name = 'MongooseError';
      +};

      Inherits:


    • errors/cast.js

      CastError(type, value)

      Casting Error constructor.

      show code
      function CastError (type, value) {
      +  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'CastError';
      +  this.type = type;
      +  this.value = value;
      +};

      Parameters:

      Inherits:


    • errors/document.js

      DocumentError(msg)

      Document Error

      show code
      function DocumentError (msg) {
      +  MongooseError.call(this, msg);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'DocumentError';
      +};

      Parameters:

      Inherits:


    • errors/validation.js

      ValidationError(instance)

      Document Validation Error

      show code
      function ValidationError (instance) {
      +  MongooseError.call(this, "Validation failed");
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidationError';
      +  this.errors = instance.errors = {};
      +};

      Parameters:

      Inherits:


      ValidationError#toString()

      Console.log helper

      show code
      ValidationError.prototype.toString = function () {
      +  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
      +    return String(this.errors[key]);
      +  }, this).join(', ');
      +};

    • errors/validator.js

      ValidatorError(path, msg)

      Schema validator error

      show code
      function ValidatorError (path, type) {
      +  var msg = type
      +    ? '"' + type + '" '
      +    : '';
      +  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidatorError';
      +  this.path = path;
      +  this.type = type;
      +};

      Parameters:

      Inherits:


    • model.js

      Model(doc)

      Model constructor

      show code
      function Model (doc, fields, skipId) {
      +  Document.call(this, doc, fields, skipId);
      +};

      Parameters:

      • doc <Object> values to with which to create the document

      Inherits:

      Events:

      • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

      • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


      Model#_getPopulationKeys(query)

      Returns what paths can be populated

      show code
      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
      +  if (!(query && query.options.populate)) return;
      +
      +  var names = Object.keys(query.options.populate)
      +    , n = names.length
      +    , name
      +    , paths = {}
      +    , hasKeys
      +    , schema
      +
      +  while (n--) {
      +    name = names[n];
      +    schema = this.schema.path(name);
      +    hasKeys = true;
      +
      +    if (!schema) {
      +      // if the path is not recognized, it's potentially embedded docs
      +      // walk path atoms from right to left to find a matching path
      +      var pieces = name.split('.')
      +        , i = pieces.length;
      +
      +      while (i--) {
      +        var path = pieces.slice(0, i).join('.')
      +          , pathSchema = this.schema.path(path);
      +
      +        // loop until we find an array schema
      +        if (pathSchema && pathSchema.caster) {
      +          if (!paths[path]) {
      +            paths[path] = { sub: {} };
      +          }
      +
      +          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
      +          hasKeys || (hasKeys = true);
      +          break;
      +        }
      +      }
      +    } else {
      +      paths[name] = query.options.populate[name];
      +      hasKeys || (hasKeys = true);
      +    }
      +  }
      +
      +  return hasKeys && paths;
      +};

      Parameters:

      Returns:


      Model#_populate(schema, oid, query, fn)

      Populates an object

      show code
      Model.prototype._populate = function populate (schema, oid, query, fn) {
      +  if (!Array.isArray(oid)) {
      +    var conditions = query.conditions || {};
      +    conditions._id = oid;
      +
      +    return this
      +    .db.model(query.model || schema.options.ref)
      +    .findOne(conditions, query.fields, query.options, fn);
      +  }
      +
      +  if (!oid.length) {
      +    return fn(null, oid);
      +  }
      +
      +  var model = this.db.model(query.model || schema.caster.options.ref)
      +    , conditions = query && query.conditions || {};
      +
      +  conditions._id || (conditions._id = { $in: oid });
      +
      +  model.find(conditions, query.fields, query.options, function (err, docs) {
      +    if (err) return fn(err);
      +
      +    // user specified sort order?
      +    if (query.options && query.options.sort) {
      +      return fn(null, docs);
      +    }
      +
      +    // put back in original id order (using a hash reduces complexity from n*n to 2n)
      +    var docHash = {};
      +    docs.forEach(function (doc) {
      +      docHash[doc._id] = doc;
      +    });
      +
      +    var arr = [];
      +    oid.forEach(function (id) {
      +      if (id in docHash) arr.push(docHash[id]);
      +    });
      +
      +    fn(null, arr);
      +  });
      +};

      Parameters:

      • schema <SchemaType> type for the oid
      • oid <Object> object id or array of object ids
      • query <Object> object specifying query conditions, fields, and options
      • fn <Function>

      Model#init(doc, query, fn)

      Performs auto-population of relations.

      show code
      Model.prototype.init = function init (doc, query, fn) {
      +  if ('function' == typeof query) {
      +    fn = query;
      +    query = null;
      +  }
      +
      +  var populate = this._getPopulationKeys(query);
      +
      +  if (!populate) {
      +    return Document.prototype.init.call(this, doc, fn);
      +  }
      +
      +  // population from other models is necessary
      +  var self = this;
      +
      +  init(doc, '', function (err) {
      +    if (err) return fn(err);
      +    Document.prototype.init.call(self, doc, fn);
      +  });
      +
      +  return this;
      +
      +  function init (obj, prefix, fn) {
      +    prefix = prefix || '';
      +
      +    var keys = Object.keys(obj)
      +      , len = keys.length;
      +
      +    return next();
      +
      +    function next () {
      +      if (--len < 0) return fn();
      +
      +      var i = keys[len]
      +        , path = prefix + i
      +        , schema = self.schema.path(path)
      +        , total = 0
      +        , inline = false
      +        , poppath
      +
      +      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
      +        // assume nested object
      +        return init(obj[i], path + '.', next);
      +      }
      +
      +      if (!(obj[i] && schema && populate[path])) return next();
      +
      +      // this query object is re-used and passed around. we clone
      +      // it to prevent query condition contamination between
      +      // one populate call to the next.
      +      poppath = utils.clone(populate[path]);
      +
      +      if (poppath.sub) {
      +        obj[i].forEach(function (subobj) {
      +          inline = true;
      +
      +          var pkeys = Object.keys(poppath.sub)
      +            , pi = pkeys.length
      +            , key
      +
      +          while (pi--) {
      +            key = pkeys[pi];
      +
      +            if (subobj[key]) (function (key) {
      +              total++;
      +              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
      +              function done (err, doc) {
      +                if (err) return error(err);
      +                subobj[key] = doc;
      +                if (--total < 1 && !inline) {
      +                  next();
      +                }
      +              }
      +            })(key);
      +          }
      +        });
      +
      +        inline = false;
      +
      +        if (0 === total) return next();
      +
      +      } else {
      +        self._populate(schema, obj[i], poppath, function (err, doc) {
      +          if (err) return error(err);
      +          obj[i] = doc;
      +          next();
      +        });
      +      }
      +    };
      +  };
      +
      +  function error (err) {
      +    if (error.err) return;
      +    fn(error.err = err);
      +  }
      +};

      Parameters:

      • doc <Object> document returned by mongo
      • query <Query> query that originated the initialization
      • fn <Function>

      Model#save([fn])

      Saves this document.

      show code
      Model.prototype.save = function save (fn) {
      +  var promise = new Promise(fn)
      +    , complete = handleSave(promise, this)
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  if (this.isNew) {
      +    // send entire doc
      +    var obj = this.toObject({ depopulate: 1 });
      +    this._version(true, obj);
      +    this.collection.insert(obj, options, complete);
      +    this._reset();
      +    this.isNew = false;
      +    this.emit('isNew', false);
      +    // Make it possible to retry the insert
      +    this._inserting = true;
      +
      +  } else {
      +    // Make sure we don't treat it as a new object on error,
      +    // since it already exists
      +    this._inserting = false;
      +
      +    var delta = this._delta();
      +    if (delta) {
      +      var where = this._where(delta[0]);
      +      this.collection.update(where, delta[1], options, complete);
      +    } else {
      +      process.nextTick(function () {
      +        complete(null);
      +      })
      +    }
      +
      +    this._reset();
      +    this.emit('isNew', false);
      +  }
      +};

      Parameters:

      Example:

      + +
      product.sold = Date.now();
      +product.save(function (err, product) {
      +  if (err) ..
      +})
      + +

      The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      + +
      var db = mongoose.createConnection(..);
      +var schema = new Schema(..);
      +var Product = db.model('Product', schema);
      +
      +db.on('error', handleError);
      + +

      However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

      + +
      Product.on('error', handleError);

      Model#_delta()

      Produces a special query document of the modified properties used in updates.

      show code
      Model.prototype._delta = function _delta () {
      +  var dirty = this._dirty();
      +  if (!dirty.length) return;
      +
      +  var self = this
      +    , where = {}
      +    , delta = {}
      +    , len = dirty.length
      +    , d = 0
      +    , val
      +    , obj
      +
      +  for (; d < len; ++d) {
      +    var data = dirty[d]
      +    var value = data.value
      +    var schema = data.schema
      +
      +    if (undefined === value) {
      +      operand(self, where, delta, data, 1, '$unset');
      +
      +    } else if (null === value) {
      +      operand(self, where, delta, data, null);
      +
      +    } else if (value._path && value._atomics) {
      +      handleAtomics(self, where, delta, data, value);
      +
      +    } else if (value._path && Buffer.isBuffer(value)) {
      +      // MongooseBuffer
      +      value = value.toObject();
      +      operand(self, where, delta, data, value);
      +
      +    } else {
      +      value = utils.clone(value);
      +      operand(self, where, delta, data, value);
      +    }
      +  }
      +
      +  if (this.__version) {
      +    this._version(where, delta);
      +  }
      +
      +  return [where, delta];
      +}

      Model#_version()

      Appends versioning to the where and update clauses.

      show code
      Model.prototype._version = function _version (where, delta) {
      +  var key = this.schema.options.versionKey;
      +
      +  if (true === where) {
      +    // this is an insert
      +    if (key) this.setValue(key, delta[key] = 0);
      +    return;
      +  }
      +
      +  // updates
      +
      +  // only apply versioning if our versionKey was selected. else
      +  // there is no way to select the correct version. we could fail
      +  // fast here and force them to include the versionKey but
      +  // thats a bit intrusive. can we do this automatically?
      +  // TODO fail fast option?
      +  if (!this.isSelected(key)) {
      +    return;
      +  }
      +
      +  // $push $addToSet don't need the where clause set
      +  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
      +    where[key] = this.getValue(key);
      +  }
      +
      +  if (VERSION_INC === (VERSION_INC & this.__version)) {
      +    delta.$inc || (delta.$inc = {});
      +    delta.$inc[key] = 1;
      +  }
      +}

      Model#increment()

      Signal that we desire an increment of this documents version.

      show code
      Model.prototype.increment = function increment () {
      +  this.__version = VERSION_ALL;
      +  return this;
      +}

      Model#_where()

      Returns a query object which applies shardkeys if they exist.

      show code
      Model.prototype._where = function _where (where) {
      +  where || (where = {});
      +
      +  var paths
      +    , len
      +
      +  if (this._shardval) {
      +    paths = Object.keys(this._shardval)
      +    len = paths.length
      +
      +    for (var i = 0; i < len; ++i) {
      +      where[paths[i]] = this._shardval[paths[i]];
      +    }
      +  }
      +
      +  where._id = this._doc._id;
      +  return where;
      +}

      Model#remove([fn])

      Removes this document from the db.

      show code
      Model.prototype.remove = function remove (fn) {
      +  if (this._removing) return this;
      +
      +  var promise = this._removing = new Promise(fn)
      +    , where = this._where()
      +    , self = this
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  this.collection.remove(where, options, tick(function (err) {
      +    if (err) {
      +      promise.error(err);
      +      promise = self = self._removing = where = options = null;
      +      return;
      +    }
      +    self.emit('remove', self);
      +    promise.complete();
      +    promise = self = where = options = null;
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Example:

      + +
      product.remove(function (err, product) {
      +  if (err) return handleError(err);
      +  Product.findById(product._id, function (err, product) {
      +    console.log(product) // null
      +  })
      +})

      Model#_registerHooks()

      Register hooks override

      show code
      Model.prototype._registerHooks = function registerHooks () {
      +  Document.prototype._registerHooks.call(this);
      +};

      Model#model(name)

      Returns another Model instance.

      show code
      Model.prototype.model = function model (name) {
      +  return this.db.model(name);
      +};

      Parameters:

      Example:

      + +
      var doc = new Tank;
      +doc.model('User').findById(id, callback);

      Model#$where(argument)

      Creates a Query and specifies a $where condition.

      Parameters:

      • argument <String, Function> is a javascript string or anonymous function

      Returns:

      Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      + +
      Blog.$where('this.comments.length &gt; 5');

      Model.init()

      Called when the model compiles.

      show code
      Model.init = function init () {
      +  if (this.schema.options.autoIndex)
      +    this.ensureIndexes();
      +
      +  this.schema.emit('init', this);
      +};

      Model.ensureIndexes([cb])

      Sends ensureIndex commands to mongo for each index declared in the schema.

      show code
      Model.ensureIndexes = function ensureIndexes (cb) {
      +  var indexes = this.schema.indexes();
      +  if (!indexes.length) {
      +    return cb && cb();
      +  }
      +
      +  var self = this
      +    , safe = self.schema.options.safe
      +    , count = indexes.length
      +    , error
      +
      +  indexes.forEach(function (index) {
      +    var options = index[1];
      +    options.safe = safe;
      +    self.collection.ensureIndex(index[0], options, tick(function (err) {
      +      if (err) error = err;
      +      if (--count) return;
      +
      +      self.emit('index', error);
      +      cb && cb(error);
      +    }));
      +  });
      +}

      Parameters:

      After completion, an index event is emitted on this Model passing an error if one occurred.

      + +

      NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

      + +

      Example:

      + +
      Event.ensureIndexes(function (err) {
      +  if (err) return handleError(err);
      +});

      Model.remove(conditions, [callback])

      Removes documents from the collection.

      show code
      Model.remove = function remove (conditions, callback) {
      +  if ('function' === typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +  }
      +
      +  var query = new Query(conditions).bind(this, 'remove');
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.remove(callback);
      +};

      Parameters:

      Returns:

      Note:

      + +

      To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.remove({ _id: id }).exec();

      Model.find(conditions, [fields], [options], [callback])

      Finds documents

      show code
      Model.find = function find (conditions, fields, options, callback) {
      +  if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options);
      +  query.bind(this, 'find');
      +  query.select(fields);
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.find(callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      // retrieve only certain keys
      +MyModel.find({ name: /john/i }, 'name friends', function () { })
      +
      +// pass options
      +MyModel.find({ name: /john/i }, null, { skip: 10 } )

      Model._applyNamedScope(query)

      Merges the current named scope query into query.

      show code
      Model._applyNamedScope = function _applyNamedScope (query) {
      +  var cQuery = this._cumulativeQuery;
      +
      +  if (cQuery) {
      +    merge(query._conditions, cQuery._conditions);
      +    if (query._fields && cQuery._fields)
      +      merge(query._fields, cQuery._fields);
      +    if (query.options && cQuery.options)
      +      merge(query.options, cQuery.options);
      +    delete this._cumulativeQuery;
      +  }
      +
      +  return query;
      +}

      Parameters:

      Returns:


      Model.findById(id, [fields], [options], [callback])

      Finds a single document by id.

      show code
      Model.findById = function findById (id, fields, options, callback) {
      +  return this.findOne({ _id: id }, fields, options, callback);
      +};

      Parameters:

      Returns:

      The id is cast to an ObjectId before sending the command.

      + +

      Example:

      + +
      Adventure.findById(id, callback);

      Model.findOne(conditions, [fields], [options], [callback])

      Finds one document.

      show code
      Model.findOne = function findOne (conditions, fields, options, callback) {
      +  if ('function' == typeof options) {
      +    // TODO Handle all 3 of the following scenarios
      +    // Hint: Only some of these scenarios are possible if cQuery is present
      +    // Scenario: findOne(conditions, fields, callback);
      +    // Scenario: findOne(fields, options, callback);
      +    // Scenario: findOne(conditions, options, callback);
      +    callback = options;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    // TODO Handle all 2 of the following scenarios
      +    // Scenario: findOne(conditions, callback)
      +    // Scenario: findOne(fields, callback)
      +    // Scenario: findOne(options, callback);
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOne(callback);
      +};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      + +

      Example:

      + +
      Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

      Model.count(conditions, [callback])

      Counts number of matching documents in a database collection.

      show code
      Model.count = function count (conditions, callback) {
      +  if ('function' === typeof conditions)
      +    callback = conditions, conditions = {};
      +
      +  var query = new Query(conditions).bind(this, 'count');
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.count(callback);
      +};

      Parameters:

      Returns:

      Example:

      + +
      Adventure.count({ type: 'jungle' }, function (err, count) {
      +  if (err) ..
      +  console.log('there are %d jungle adventures', count);
      +});

      Model.distinct(field, [conditions], [callback])

      Executes a DISTINCT command

      show code
      Model.distinct = function distinct (field, conditions, callback) {
      +  var query = new Query(conditions).bind(this, 'distinct');
      +  if ('undefined' == typeof callback) {
      +    query._distinctArg = field;
      +    return query;
      +  }
      +
      +  this._applyNamedScope(query);
      +  return query.distinct(field, callback);
      +};

      Parameters:

      Returns:


      Model.where(path, [val])

      Creates a Query, applies the passed conditions, and returns the Query.

      show code
      Model.where = function where (path, val) {
      +  var q = new Query().bind(this, 'find');
      +  return q.where.apply(q, arguments);
      +};

      Parameters:

      Returns:

      For example, instead of writing:

      + +
      User.find({age: {$gte: 21, $lte: 65}}, callback);
      + +

      we can instead write:

      + +
      User.where('age').gte(21).lte(65).exec(callback);
      + +

      Since the Query class also supports where you can continue chaining

      + +
      User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +... etc

      Model.findOneAndUpdate([conditions], [update], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Model.findOneAndUpdate = function (conditions, update, options, callback) {
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +  else if (1 === arguments.length) {
      +    if ('function' == typeof conditions) {
      +      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    update = conditions;
      +    conditions = undefined;
      +  }
      +
      +  var fields;
      +  if (options && options.fields) {
      +    fields = options.fields;
      +    options.fields = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndUpdate', update);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndUpdate(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndUpdate(conditions, update, options, callback) // executes
      +A.findOneAndUpdate(conditions, update, options)  // returns Query
      +A.findOneAndUpdate(conditions, update, callback) // executes
      +A.findOneAndUpdate(conditions, update)           // returns Query
      +A.findOneAndUpdate()                             // returns Query
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findByIdAndUpdate(id, [update], [options], [callback])

      Issues a mongodb findAndModify update command by a documents id.

      show code
      Model.findByIdAndUpdate = function (id, update, options, callback) {
      +  var args;
      +
      +  if (1 === arguments.length) {
      +    if ('function' == typeof id) {
      +      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
      +
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    return this.findOneAndUpdate({_id: id }, undefined);
      +  }
      +
      +  args = utils.args(arguments, 1);
      +  args.unshift({ _id: id });
      +  return this.findOneAndUpdate.apply(this, args);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndUpdate(id, update, options, callback) // executes
      +A.findByIdAndUpdate(id, update, options)  // returns Query
      +A.findByIdAndUpdate(id, update, callback) // executes
      +A.findByIdAndUpdate(id, update)           // returns Query
      +A.findByIdAndUpdate()                     // returns Query
      + +

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findById(id, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findOneAndRemove(conditions, [options], [callback])

      Issue a mongodb findAndModify remove command.

      show code
      Model.findOneAndRemove = function (conditions, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof conditions) {
      +    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  }
      +
      +  var fields;
      +  if (options) {
      +    fields = options.select;
      +    options.select = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndRemove');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndRemove(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndRemove(conditions, options, callback) // executes
      +A.findOneAndRemove(conditions, options)  // return Query
      +A.findOneAndRemove(conditions, callback) // executes
      +A.findOneAndRemove(conditions) // returns Query
      +A.findOneAndRemove()           // returns Query

      Model.findByIdAndRemove(id, [options], [callback])

      Issue a mongodb findAndModify remove command by a documents id.

      show code
      Model.findByIdAndRemove = function (id, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof id) {
      +    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  return this.findOneAndRemove({ _id: id }, options, callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed, else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndRemove(id, options, callback) // executes
      +A.findByIdAndRemove(id, options)  // return Query
      +A.findByIdAndRemove(id, callback) // executes
      +A.findByIdAndRemove(id) // returns Query
      +A.findByIdAndRemove()           // returns Query

      Model.create(doc, fn)

      Shortcut for creating a new Document that is automatically saved to the db if valid.

      show code
      Model.create = function create (doc, fn) {
      +  if (1 === arguments.length) {
      +    return 'function' === typeof doc && doc(null);
      +  }
      +
      +  var self = this
      +    , docs = [null]
      +    , promise
      +    , count
      +    , args
      +
      +  if (Array.isArray(doc)) {
      +    args = doc;
      +  } else {
      +    args = utils.args(arguments, 0, arguments.length - 1);
      +    fn = arguments[arguments.length - 1];
      +  }
      +
      +  if (0 === args.length) return fn(null);
      +
      +  promise = new Promise(fn);
      +  count = args.length;
      +
      +  args.forEach(function (arg, i) {
      +    var doc = new self(arg);
      +    docs[i+1] = doc;
      +    doc.save(function (err) {
      +      if (err) return promise.error(err);
      +      --count || fn.apply(null, docs);
      +    });
      +  });
      +
      +  // TODO
      +  // utilize collection.insertAll for batch processing?
      +};

      Parameters:

      Example:

      + +
      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});
      +
      +var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      +Candy.create(array, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});

      Model.update(conditions, update, [options], [callback])

      Updates documents in the database without returning them.

      show code
      Model.update = function update (conditions, doc, options, callback) {
      +  if (arguments.length < 4) {
      +    if ('function' === typeof options) {
      +      // Scenario: update(conditions, doc, callback)
      +      callback = options;
      +      options = null;
      +    } else if ('function' === typeof doc) {
      +      // Scenario: update(doc, callback);
      +      callback = doc;
      +      doc = conditions;
      +      conditions = {};
      +      options = null;
      +    }
      +  }
      +
      +  var query = new Query(conditions, options).bind(this, 'update', doc);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.update(doc, callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
      +MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
      +  if (err) return handleError(err);
      +  console.log('The number of updated documents was %d', numberAffected);
      +  console.log('The raw response from Mongo was ', raw);
      +});
      + +

      Valid options:

      + +
        +
      • safe (boolean) safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +
      • multi (boolean) whether multiple documents should be updated (false)
      • +
      + +

      All update values are cast to their appropriate SchemaTypes before being sent.

      + +

      The callback function receives (err, numberAffected, rawResponse).

      + +
        +
      • err is the error if any occurred
      • +
      • numberAffected is the count of updated documents Mongo reported
      • +
      • rawResponse is the full response from Mongo
      • +
      + +

      Note:

      + +

      All top level keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.update(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

      + +

      Note:

      + +

      To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
      + +

      Note:

      + +

      Although values are casted to their appropriate types when using update, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.mapReduce(o, callback)

      Executes a mapReduce command.

      show code
      Model.mapReduce = function mapReduce (o, callback) {
      +  if ('function' != typeof callback) throw new Error('missing callback');
      +
      +  var self = this;
      +
      +  if (!Model.mapReduce.schema) {
      +    var opts = { noId: true, noVirtualId: true, strict: false }
      +    Model.mapReduce.schema = new Schema({}, opts);
      +  }
      +
      +  if (!o.out) o.out = { inline: 1 };
      +
      +  o.map = String(o.map);
      +  o.reduce = String(o.reduce);
      +
      +  if (o.query) {
      +    var q = new Query(o.query);
      +    q.cast(this);
      +    o.query = q._conditions;
      +    q = undefined;
      +  }
      +
      +  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
      +    if (err) return callback(err);
      +
      +    if (ret.findOne && ret.mapReduce) {
      +      // returned a collection, convert to Model
      +      var model = Model.compile(
      +          '_mapreduce_' + ret.collectionName
      +        , Model.mapReduce.schema
      +        , ret.collectionName
      +        , self.db
      +        , self.base);
      +
      +      model._mapreduce = true;
      +
      +      return callback(err, model, stats);
      +    }
      +
      +    callback(err, ret, stats);
      +  });
      +}

      Parameters:

      • o <Object> an object specifying map-reduce options
      • callback <Function>

      o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +User.mapReduce(o, function (err, results) {
      +  console.log(results)
      +})
      + +

      Other options:

      + +
        +
      • query {Object} query filter object.
      • +
      • limit {Number} max number of documents
      • +
      • keeptemp {Boolean, default:false} keep temporary data
      • +
      • finalize {Function} finalize function
      • +
      • scope {Object} scope variables exposed to map/reduce/finalize during execution
      • +
      • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
      • +
      • verbose {Boolean, default:false} provide statistics on job execution time.
      • +
      • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
      • +
      + +

      * out options:

      + +
        +
      • {inline:1} the results are returned in an array
      • +
      • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
      • +
      • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
      • +
      • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
      • +
      + +

      If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +o.out = { replace: 'createdCollectionNameForResults' }
      +o.verbose = true;
      +User.mapReduce(o, function (err, model, stats) {
      +  console.log('map reduce took %d ms', stats.processtime)
      +  model.find().where('value').gt(10).exec(function (err, docs) {
      +    console.log(docs);
      +  });
      +})

      Model.aggregate(array, [options], callback)

      Executes an aggregate command on this models collection.

      show code
      Model.aggregate = function aggregate () {
      +  return this.collection.aggregate.apply(this.collection, arguments);
      +}

      Parameters:

      Example:

      + +
      // find the max age of all users
      +Users.aggregate(
      +    { $group: { _id: null, maxAge: { $max: '$age' }}}
      +  , { $project: { _id: 0, maxAge: 1 }}
      +  , function (err, res) {
      +  if (err) return handleError(err);
      +  console.log(res); // [ { maxAge: 98 } ]
      +});
      + +

      NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

      + +

      NOTE: this requires running MongoDB >= 2.1


      Model#base

      Base Mongoose instance the model uses.


      Model#collection

      Collection the model uses.


      Model#db

      Database instance the model uses.


      Model#schema

      Schema the model uses.


      Model#modelName

      The name of the model


      Model#collection

      Collection the model uses.


      Model#db

      Connection the model uses.


    • namedscope.js

      NamedScope#decorate(target, getters)

      Decorate

      show code
      NamedScope.prototype.decorate = function (target, getters) {
      +  var name = this.name
      +    , block = this.block
      +    , query = this.query;
      +  if (block) {
      +    if (block.length === 0) {
      +      Object.defineProperty(target, name, {
      +        get: getters.block0(block)
      +      });
      +    } else {
      +      target[name] = getters.blockN(block);
      +    }
      +  } else {
      +    Object.defineProperty(target, name, {
      +      get: getters.basic(query)
      +    });
      +  }
      +};
      +
      +NamedScope.prototype.compile = function (model) {
      +  var allScopes = this.scopesByName
      +    , scope;
      +  for (var k in allScopes) {
      +    scope = allScopes[k];
      +    scope.decorate(model, {
      +      block0: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.call(cquery);
      +          return this;
      +        };
      +      },
      +      blockN: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.apply(cquery, arguments);
      +          return this;
      +        };
      +      },
      +      basic: function (query) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          cquery.find(query);
      +          return this;
      +        };
      +      }
      +    });
      +  }
      +};
      +
      +module.exports = NamedScope;

      Parameters:


    • promise.js

      Promise(back)

      Promise constructor.

      show code
      function Promise (back) {
      +  this.emitted = {};
      +  if ('function' == typeof back)
      +    this.addBack(back);
      +};

      Parameters:

      • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

      Events:

      • err: Emits when the promise resolves to an error.

      • complete: Emits when the promise resolves sucessfully.


      Promise#on(event, callback)

      Adds listener to the event.

      show code
      Promise.prototype.on = function (event, callback) {
      +  if (this.emitted[event])
      +    callback.apply(this, this.emitted[event]);
      +  else
      +    EventEmitter.prototype.on.call(this, event, callback);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


      Promise#emit()

      Keeps track of emitted events to run them on on.

      show code
      Promise.prototype.emit = function (event) {
      +  // ensures a promise can't be complete() or error() twice
      +  if (event == 'err' || event == 'complete'){
      +    if (this.emitted.err || this.emitted.complete) {
      +      return this;
      +    }
      +    this.emitted[event] = util.args(arguments, 1);
      +  }
      +
      +  return EventEmitter.prototype.emit.apply(this, arguments);
      +};

      Promise#complete()

      Shortcut for emitting the complete event.

      show code
      Promise.prototype.complete = function () {
      +  var args = util.args(arguments);
      +  return this.emit.apply(this, ['complete'].concat(args));
      +};

      Promise#error()

      Shortcut for emitting the err event.

      show code
      Promise.prototype.error = function (err) {
      +  if (!(err instanceof Error)) err = new Error(err);
      +  return this.emit('err', err);
      +};

      Returns:


      Promise#addCallback()

      Shortcut for .on('complete', fn).

      show code
      Promise.prototype.addCallback = function (fn) {
      +  return this.on('complete', fn);
      +};

      Returns:


      Promise#addErrback()

      Shortcut for .on('err', fn).

      show code
      Promise.prototype.addErrback = function (fn) {
      +  return this.on('err', fn);
      +};

      Returns:


      Promise#addBack(fn)

      Adds a single function that's both a callback and errback.

      show code
      Promise.prototype.addBack = function (fn) {
      +  this.on('err', function(err){
      +    fn.call(this, err);
      +  });
      +
      +  this.on('complete', function(){
      +    var args = util.args(arguments);
      +    fn.apply(this, [null].concat(args));
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Promise#resolve(err, val)

      Sugar for handling cases where you may be resolving to either an error condition or a success condition.

      show code
      Promise.prototype.resolve = function (err, val) {
      +  if (err) return this.error(err);
      +  return this.complete(val);
      +};

      Parameters:

      • err <Error> optional error or null
      • val <Object> value to complete the promise with

    • query.js

      Query(criteria, options)

      Query constructor used for building queries.

      show code
      function Query (criteria, options) {
      +  this.setOptions(options, true);
      +  this._conditions = {};
      +  this._updateArg = {};
      +  this._fields = undefined;
      +  if (criteria) this.find(criteria);
      +}

      Parameters:

      Example:

      + +
      var query = Model.find();
      +query.where('age').gte(21).exec(callback);

      Query#setOptions(options)

      Sets query options.

      show code
      Query.prototype.setOptions = function (options, overwrite) {
      +  // overwrite is internal use only
      +  if (overwrite) {
      +    options = this.options = options || {};
      +    this.safe = options.safe
      +
      +    // normalize population options
      +    var pop = this.options.populate;
      +    this.options.populate = {};
      +
      +    if (pop && Array.isArray(pop)) {
      +      for (var i = 0, l = pop.length; i < l; i++) {
      +        this.options.populate[pop[i]] = {};
      +      }
      +    }
      +
      +    return this;
      +  }
      +
      +  if (!(options && 'Object' == options.constructor.name))
      +    return this;
      +
      +  if ('safe' in options)
      +    this.safe = options.safe;
      +
      +  // set arbitrary options
      +  var methods = Object.keys(options)
      +    , i = methods.length
      +    , method
      +
      +  while (i--) {
      +    method = methods[i];
      +
      +    // use methods if exist (safer option manipulation)
      +    if ('function' == typeof this[method]) {
      +      var args = Array.isArray(options[method])
      +        ? options[method]
      +        : [options[method]];
      +      this[method].apply(this, args)
      +    } else {
      +      this.options[method] = options[method];
      +    }
      +  }
      +  return this;
      +}

      Parameters:

      Options:

      + + + +

      * denotes a query helper method is also available


      Query#bind(model, op, updateArg)

      Binds this query to a model.

      show code
      Query.prototype.bind = function bind (model, op, updateArg) {
      +  this.model = model;
      +  this.op = op;
      +
      +  if (model._mapreduce) this.options.lean = true;
      +
      +  if (op == 'update' || op == 'findOneAndUpdate') {
      +    merge(this._updateArg, updateArg || {});
      +  }
      +
      +  return this;
      +};

      Parameters:

      • model <Model> the model to which the query is bound
      • op <String> the operation to execute
      • updateArg <Object> used in update methods

      Returns:


      Query#exec([operation], [callback])

      Executes the query

      show code
      Query.prototype.exec = function exec (op, callback) {
      +  var promise = new Promise();
      +
      +  switch (typeof op) {
      +    case 'function':
      +      callback = op;
      +      op = null;
      +      break;
      +    case 'string':
      +      this.op = op;
      +      break;
      +  }
      +
      +  if (callback) promise.addBack(callback);
      +
      +  if (!this.op) {
      +    promise.complete();
      +    return promise;
      +  }
      +
      +  if ('update' == this.op) {
      +    this[this.op](this._updateArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  if ('distinct' == this.op) {
      +    this.distinct(this._distinctArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  this[this.op](promise.resolve.bind(promise));
      +  return promise;
      +};

      Parameters:

      Returns:

      Examples

      + +
      query.exec();
      +query.exec(callback);
      +query.exec('update');
      +query.exec('find', callback);

      Query#find([criteria], [callback])

      Finds documents.

      show code
      Query.prototype.find = function (criteria, callback) {
      +  this.op = 'find';
      +  if ('function' === typeof criteria) {
      +    callback = criteria;
      +    criteria = {};
      +  } else if (criteria instanceof Query) {
      +    // TODO Merge options, too
      +    merge(this._conditions, criteria._conditions);
      +  } else if (criteria instanceof Document) {
      +    merge(this._conditions, criteria.toObject());
      +  } else if (criteria && 'Object' === criteria.constructor.name) {
      +    merge(this._conditions, criteria);
      +  }
      +  if (!callback) return this;
      +  return this.execFind(callback);
      +};

      Parameters:

      Returns:

      When no callback is passed, the query is not executed.

      + +

      Example

      + +
      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

      Query#cast(model, [obj])

      Casts this query to the schema of model

      show code
      Query.prototype.cast = function (model, obj) {
      +  obj || (obj= this._conditions);
      +
      +  var schema = model.schema
      +    , paths = Object.keys(obj)
      +    , i = paths.length
      +    , any$conditionals
      +    , schematype
      +    , nested
      +    , path
      +    , type
      +    , val;
      +
      +  while (i--) {
      +    path = paths[i];
      +    val = obj[path];
      +
      +    if ('$or' === path || '$nor' === path) {
      +      var k = val.length
      +        , orComponentQuery;
      +
      +      while (k--) {
      +        orComponentQuery = new Query(val[k]);
      +        orComponentQuery.cast(model);
      +        val[k] = orComponentQuery._conditions;
      +      }
      +
      +    } else if (path === '$where') {
      +      type = typeof val;
      +
      +      if ('string' !== type && 'function' !== type) {
      +        throw new Error("Must have a string or function for $where");
      +      }
      +
      +      if ('function' === type) {
      +        obj[path] = val.toString();
      +      }
      +
      +      continue;
      +
      +    } else {
      +
      +      if (!schema) {
      +        // no casting for Mixed types
      +        continue;
      +      }
      +
      +      schematype = schema.path(path);
      +
      +      if (!schematype) {
      +        // Handle potential embedded array queries
      +        var split = path.split('.')
      +          , j = split.length
      +          , pathFirstHalf
      +          , pathLastHalf
      +          , remainingConds
      +          , castingQuery;
      +
      +        // Find the part of the var path that is a path of the Schema
      +        while (j--) {
      +          pathFirstHalf = split.slice(0, j).join('.');
      +          schematype = schema.path(pathFirstHalf);
      +          if (schematype) break;
      +        }
      +
      +        // If a substring of the input path resolves to an actual real path...
      +        if (schematype) {
      +          // Apply the casting; similar code for $elemMatch in schema/array.js
      +          if (schematype.caster && schematype.caster.schema) {
      +            remainingConds = {};
      +            pathLastHalf = split.slice(j).join('.');
      +            remainingConds[pathLastHalf] = val;
      +            castingQuery = new Query(remainingConds);
      +            castingQuery.cast(schematype.caster);
      +            obj[path] = castingQuery._conditions[pathLastHalf];
      +          } else {
      +            obj[path] = val;
      +          }
      +        }
      +
      +      } else if (val === null || val === undefined) {
      +        continue;
      +      } else if ('Object' === val.constructor.name) {
      +
      +        any$conditionals = Object.keys(val).some(function (k) {
      +          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
      +        });
      +
      +        if (!any$conditionals) {
      +          obj[path] = schematype.castForQuery(val);
      +        } else {
      +
      +          var ks = Object.keys(val)
      +            , k = ks.length
      +            , $cond;
      +
      +          while (k--) {
      +            $cond = ks[k];
      +            nested = val[$cond];
      +
      +            if ('$exists' === $cond) {
      +              if ('boolean' !== typeof nested) {
      +                throw new Error("$exists parameter must be Boolean");
      +              }
      +              continue;
      +            }
      +
      +            if ('$type' === $cond) {
      +              if ('number' !== typeof nested) {
      +                throw new Error("$type parameter must be Number");
      +              }
      +              continue;
      +            }
      +
      +            if ('$not' === $cond) {
      +              this.cast(model, nested);
      +            } else {
      +              val[$cond] = schematype.castForQuery($cond, nested);
      +            }
      +          }
      +        }
      +      } else {
      +        obj[path] = schematype.castForQuery(val);
      +      }
      +    }
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Returns:

      Note

      + +

      If obj is present, it is cast instead of this query.


      Query#_optionsForExec(model)

      Returns default options.

      show code
      Query.prototype._optionsForExec = function (model) {
      +  var options = utils.clone(this.options, { retainKeyOrder: true });
      +  delete options.populate;
      +
      +  if (!('safe' in options))
      +    options.safe = model.schema.options.safe;
      +
      +  if (!('readPreference' in options) && model.schema.options.read)
      +    options.readPreference = model.schema.options.read;
      +
      +  return options;
      +};

      Parameters:


      Query#_applyPaths()

      Applies schematype selected options to this query.

      show code
      Query.prototype._applyPaths = function applyPaths () {
      +  // determine if query is selecting or excluding fields
      +
      +  var fields = this._fields
      +    , exclude
      +    , keys
      +    , ki
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('+' == keys[ki][0]) continue;
      +      exclude = 0 === fields[keys[ki]];
      +      break;
      +    }
      +  }
      +
      +  // if selecting, apply default schematype select:true fields
      +  // if excluding, apply schematype select:false fields
      +
      +  var selected = []
      +    , excluded = []
      +    , seen = [];
      +
      +  analyzeSchema(this.model.schema);
      +
      +  switch (exclude) {
      +    case true:
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +    case false:
      +      selected.length && this.select(selected.join(' '));
      +      break;
      +    case undefined:
      +      // user didn't specify fields, implies returning all fields.
      +      // only need to apply excluded fields
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +  }
      +
      +  return seen = excluded = selected = keys = fields = null;
      +
      +  function analyzeSchema (schema, prefix) {
      +    prefix || (prefix = '');
      +
      +    // avoid recursion
      +    if (~seen.indexOf(schema)) return;
      +    seen.push(schema);
      +
      +    schema.eachPath(function (path, type) {
      +      if (prefix) path = prefix + '.' + path;
      +
      +      // array of subdocs?
      +      if (type.schema) {
      +        analyzeSchema(type.schema, path);
      +      }
      +
      +      analyzePath(path, type);
      +    });
      +  }
      +
      +  function analyzePath (path, type) {
      +    if ('boolean' != typeof type.selected) return;
      +
      +    if (fields && ('+' + path) in fields) {
      +      // forced inclusion
      +      delete fields['+' + path];
      +
      +      // if there are other fields being included, add this one
      +      // if no other included fields, leave this out (implied inclusion)
      +      if (false === exclude && keys.length > 1) {
      +        fields[path] = 1;
      +      }
      +
      +      return
      +    };
      +
      +    ;(type.selected ? selected : excluded).push(path);
      +  }
      +}

      Query#$where(js)

      Specifies a $where condition

      Parameters:

      Returns:

      Use $where when you need to select documents using a JavaScript expression.

      + +

      Example

      + +
      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
      +
      +query.$where(function () {
      +  return this.comments.length &gt; 10 || this.name.length &gt; 5;
      +})

      Query#where([path], [val])

      Specifies a path for use with chaining.

      show code
      Query.prototype.where = function (path, val) {
      +  if (!arguments.length) return this;
      +
      +  if ('string' != typeof path) {
      +    throw new TypeError('path must be a string');
      +  }
      +
      +  this._currPath = path;
      +
      +  if (2 === arguments.length) {
      +    this._conditions[path] = val;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      // instead of writing:
      +User.find({age: {$gte: 21, $lte: 65}}, callback);
      +
      +// we can instead write:
      +User.where('age').gte(21).lte(65);
      +
      +// Moreover, you can also chain a bunch of these together:
      +
      +User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +.where('friends').slice(10)
      +.exec(callback)

      Query#equals(val)

      Specifies the complementary comparison value for paths specified with where()

      show code
      Query.prototype.equals = function equals (val) {
      +  var path = this._currPath;
      +  if (!path) throw new Error('equals() must be used after where()');
      +  this._conditions[path] = val;
      +  return this;
      +}

      Parameters:

      Returns:

      Example

      + +
      User.where('age').equals(49);
      +
      +// is the same as
      +
      +User.where('age', 49);

      Query#or(array)

      Specifies arguments for an $or condition.

      show code
      Query.prototype.or = function or (array) {
      +  var or = this._conditions.$or || (this._conditions.$or = []);
      +  if (!Array.isArray(array)) array = [array];
      +  or.push.apply(or, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.or([{ color: 'red' }, { status: 'emergency' }])

      Query#nor(array)

      Specifies arguments for a $nor condition.

      show code
      Query.prototype.nor = function nor (array) {
      +  var nor = this._conditions.$nor || (this._conditions.$nor = []);
      +  if (!Array.isArray(array)) array = [array];
      +  nor.push.apply(nor, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.nor([{ color: 'green' }, { status: 'ok' }])

      Query#gt(path, val)

      Specifies a $gt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.

      + +

      Example

      + +
      Thing.find().where('age').gt(21)
      +
      +// or
      +Thing.find().gt('age', 21)

      Query#gte(path, val)

      Specifies a $gte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lt(path, val)

      Specifies a $lt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lte(path, val)

      Specifies a $lte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#ne(path, val)

      Specifies a $ne query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#in(path, val)

      Specifies an $in query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#nin(path, val)

      Specifies an $nin query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#all(path, val)

      Specifies an $all query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#size(path, val)

      Specifies an $size query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#regex(path, val)

      Specifies a $regex query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#maxDistance(path, val)

      Specifies a $maxDistance query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#near(path, val)

      Specifies a $near condition

      show code
      Query.prototype.near = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$near = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#nearSphere(path, val)

      Specifies a $nearSphere condition.

      show code
      Query.prototype.nearSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$nearSphere = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#mod(path, val)

      Specifies a $mod condition

      show code
      Query.prototype.mod = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$mod = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#exists(path, val)

      Specifies an $exists condition

      show code
      Query.prototype.exists = function (path, val) {
      +  if (arguments.length === 0) {
      +    path = this._currPath
      +    val = true;
      +  } else if (arguments.length === 1) {
      +    if ('boolean' === typeof path) {
      +      val = path;
      +      path = this._currPath;
      +    } else {
      +      val = true;
      +    }
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$exists'] = val;
      +  return this;
      +};

      Parameters:

      Returns:


      Query#elemMatch(path, criteria)

      Specifies an $elemMatch condition

      show code
      Query.prototype.elemMatch = function (path, criteria) {
      +  var block;
      +  if ('Object' === path.constructor.name) {
      +    criteria = path;
      +    path = this._currPath;
      +  } else if ('function' === typeof path) {
      +    block = path;
      +    path = this._currPath;
      +  } else if ('Object' === criteria.constructor.name) {
      +  } else if ('function' === typeof criteria) {
      +    block = criteria;
      +  } else {
      +    throw new Error("Argument error");
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  if (block) {
      +    criteria = new Query();
      +    block(criteria);
      +    conds['$elemMatch'] = criteria._conditions;
      +  } else {
      +    conds['$elemMatch'] = criteria;
      +  }
      +  return this;
      +};
      +
      +// Spatial queries

      Parameters:

      Returns:

      Example

      + +
      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
      +
      +query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
      +
      +query.elemMatch('comment', function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})
      +
      +query.where('comment').elemMatch(function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})

      Query#box(path, val)

      Specifies a $box condition

      show code
      Query.prototype.box = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$box': [val.ll, val.ur]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var lowerLeft = [40.73083, -73.99756]
      +var upperRight= [40.741404,  -73.988135]
      +query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

      Query#center(path, val, [opts])

      Specifies a $center condition

      show code
      Query.prototype.center = function (path, val, opts) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$center': [val.center, val.radius]  };
      +
      +  // copy any options
      +  if (opts && 'Object' == opts.constructor.name) {
      +    utils.options(opts, conds.$within);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.center(area)

      Query#centerSphere(path, val)

      Specifies a $centerSphere condition

      show code
      Query.prototype.centerSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.centerSphere(area)

      Query#polygon(path, val)

      Specifies a $polygon condition

      show code
      Query.prototype.polygon = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$polygon': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      +query.where('loc').within.polygon(polyA)
      +
      +// or
      +var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      +query.where('loc').within.polygon(polyB)

      Query#select(arg)

      Specifies which document fields to include or exclude

      show code
      Query.prototype.select = function select (arg) {
      +  if (!arg) return this;
      +
      +  var fields = this._fields || (this._fields = {});
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      fields[field] = arg[field];
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var include = '-' == field[0] ? 0 : 1;
      +      if (include === 0) field = field.substring(1);
      +      fields[field] = include;
      +    });
      +  } else {
      +    throw new TypeError('Invalid select() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

      + +

      Example

      + +
      // include a and b, exclude c
      +query.select('a b -c');
      +
      +// or you may use object notation, useful when
      +// you have keys already prefixed with a "-"
      +query.select({a: 1, b: 1, c: 0});
      +
      +// force inclusion of field excluded at schema level
      +query.select('+path')
      + +

      NOTE:

      + +

      v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


      Query#slice(path, val)

      Specifies a $slice condition

      show code
      Query.prototype.slice = function (path, val) {
      +  if (arguments.length === 1) {
      +      val = path;
      +      path = this._currPath
      +  } else if (arguments.length === 2) {
      +    if ('number' === typeof path) {
      +      val = [path, val];
      +      path = this._currPath;
      +    }
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var myFields = this._fields || (this._fields = {});
      +  myFields[path] = { '$slice': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      query.slice('comments', 5)
      +query.slice('comments', -5)
      +query.slice('comments', [10, 5])
      +query.where('comments').slice(5)
      +query.where('comments').slice([-10, 5])

      Query#sort(arg)

      Sets the sort order

      show code
      Query.prototype.sort = function (arg) {
      +  if (!arg) return this;
      +
      +  var sort = this.options.sort || (this.options.sort = []);
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      push(sort, field, arg[field]);
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var ascend = '-' == field[0] ? -1 : 1;
      +      if (ascend === -1) field = field.substring(1);
      +      push(sort, field, ascend);
      +    });
      +  } else {
      +    throw new TypeError('Invalid sort() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

      + +

      If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

      + +

      Example

      + +
      // these are equivalent
      +query.sort({ field: 'asc', test: -1 });
      +query.sort('field -test');

      Query#limit(val)

      Specifies the limit option.

      Parameters:

      Example

      + +
      Kitten.find().limit(20)

      Query#skip(val)

      Specifies the skip option.

      Parameters:

      Example

      + +
      Kitten.find().skip(100).limit(20)

      Query#maxscan(val)

      Specifies the maxscan option.

      Parameters:

      Example

      + +
      Kitten.find().maxscan(100)

      Query#batchSize(val)

      Specifies the batchSize option.

      Parameters:

      Example

      + +
      Kitten.find().batchSize(100)

      Query#comment(val)

      Specifies the comment option.

      Parameters:

      Example

      + +
      Kitten.findOne(condition).comment('login query')

      Query#snapshot()

      Specifies this query as a snapshot query.

      show code
      Query.prototype.snapshot = function () {
      +  this.options.snapshot = true;
      +  return this;
      +};

      Returns:

      Example

      + +
      Kitten.find().snapshot()

      Query#hint(val)

      Sets query hints.

      show code
      Query.prototype.hint = function (val) {
      +  if (!val) return this;
      +
      +  var hint = this.options.hint || (this.options.hint = {});
      +
      +  if ('Object' === val.constructor.name) {
      +    // must keep object keys in order so don't use Object.keys()
      +    for (var k in val) {
      +      hint[k] = val[k];
      +    }
      +  } else {
      +    throw new TypeError('Invalid hint. ' + val);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Model.find().hint({ indexA: 1, indexB: -1})

      Query#slaveOk(v)

      Sets the slaveOk option.

      show code
      Query.prototype.slaveOk = function (v) {
      +  this.options.slaveOk = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Example:

      + +
      new Query().slaveOk() // true
      +new Query().slaveOk(true)
      +new Query().slaveOk(false)

      Query#read(pref, [tags])

      Sets the readPreference option for the query.

      show code
      Query.prototype.read = function (pref, tags) {
      +  this.options.readPreference = utils.readPref(pref, tags);
      +  return this;
      +}

      Parameters:

      • pref <String> one of the listed preference options or their aliases
      • [tags] <Array> optional tags for this query

      Returns:

      Example:

      + +
      new Query().read('primary')
      +new Query().read('p')  // same as primary
      +
      +new Query().read('primaryPreferred')
      +new Query().read('pp') // same as primaryPreferred
      +
      +new Query().read('secondary')
      +new Query().read('s')  // same as secondary
      +
      +new Query().read('secondaryPreferred')
      +new Query().read('sp') // same as secondaryPreferred
      +
      +new Query().read('nearest')
      +new Query().read('n')  // same as nearest
      +
      +// with tags
      +new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
      + +

      Preferences:

      + +
      primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
      +secondary            Read from secondary if available, otherwise error.
      +primaryPreferred     Read from primary if available, otherwise a secondary.
      +secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
      +nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
      + +

      Aliases

      + +
      p   primary
      +pp  primaryPreferred
      +s   secondary
      +sp  secondaryPreferred
      +n   nearest
      + +

      Read more about how to use read preferrences here and here.


      Query#lean(v)

      Sets the lean option.

      show code
      Query.prototype.lean = function (v) {
      +  this.options.lean = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

      + +

      This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

      + +

      Example:

      + +
      new Query().lean() // true
      +new Query().lean(true)
      +new Query().lean(false)
      +
      +Model.find().lean().exec();
      +
      +var leanStream = Model.find().lean().stream();

      Query#tailable(v)

      Sets tailable option.

      show code
      Query.prototype.tailable = function (v) {
      +  this.options.tailable = arguments.length ? !!v : true;
      +  return this;
      +};

      Parameters:

      Example

      + +
      Kitten.find().tailable() &lt;== true
      +Kitten.find().tailable(true)
      +Kitten.find().tailable(false)

      Query#execFind(callback)

      Executes the query as a find() operation.

      show code
      Query.prototype.execFind = function (callback) {
      +  var model = this.model
      +    , promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.find(castQuery, options, function (err, cursor) {
      +    if (err) return promise.error(err);
      +    cursor.toArray(tick(cb));
      +  });
      +
      +  function cb (err, docs) {
      +    if (err) return promise.error(err);
      +
      +    if (true === options.lean)
      +      return promise.complete(docs);
      +
      +    var arr = []
      +      , count = docs.length;
      +
      +    if (!count) return promise.complete([]);
      +
      +    for (var i = 0, l = docs.length; i < l; i++) {
      +      arr[i] = new model(undefined, fields, true);
      +      arr[i].init(docs[i], self, function (err) {
      +        if (err) return promise.error(err);
      +        --count || promise.complete(arr);
      +      });
      +    }
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#findOne(callback)

      Executes the query as a findOne() operation.

      show code
      Query.prototype.findOne = function (callback) {
      +  this.op = 'findOne';
      +
      +  if (!callback) return this;
      +
      +  var model = this.model;
      +  var promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.findOne(castQuery, options, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === options.lean) return promise.complete(doc);
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'white').findOne(function (err, kitten) {
      +  if (err) return handleError(err);
      +
      +  // kitten may be null if no document matched
      +  if (kitten) {
      +    ...
      +  }
      +})

      Query#count(callback)

      Exectues the query as a count() operation.

      show code
      Query.prototype.count = function (callback) {
      +  this.op = 'count';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.count(castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'black').count(function (err, count) {
      +  if (err) return handleError(err);
      +  console.log('there are %d black kittens', count);
      +})

      Query#distinct(field, callback)

      Executes this query as a distict() operation.

      show code
      Query.prototype.distinct = function (field, callback) {
      +  this.op = 'distinct';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.distinct(field, castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#update(doc, callback)

      Executes this query as an update() operation.

      show code
      Query.prototype.update = function update (doc, callback) {
      +  this.op = 'update';
      +  this._updateArg = doc;
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , fn = 'function' == typeof callback
      +    , castedQuery
      +    , castedDoc
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedQuery));
      +      return this;
      +    }
      +    throw castedQuery;
      +  }
      +
      +  castedDoc = castDoc(this);
      +  if (!castedDoc) {
      +    fn && process.nextTick(callback.bind(null, null, 0));
      +    return this;
      +  }
      +
      +  if (castedDoc instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedDoc));
      +      return this;
      +    }
      +    throw castedDoc;
      +  }
      +
      +  if (!fn) {
      +    delete options.safe;
      +  }
      +
      +  model.collection.update(castedQuery, castedDoc, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Returns:

      All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

      + +

      Example

      + +
      Model.update({..}, { title: 'remove words' }, ...)
      + +

      becomes

      + +
      Model.update({..}, { $set: { title: 'remove words' }}, ...)
      + +

      Note

      + +

      Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


      Query#_castUpdate(obj)

      Casts obj for an update command.

      show code
      Query.prototype._castUpdate = function _castUpdate (obj) {
      +  var ops = Object.keys(obj)
      +    , i = ops.length
      +    , ret = {}
      +    , hasKeys
      +    , val
      +
      +  while (i--) {
      +    var op = ops[i];
      +    if ('$' !== op[0]) {
      +      // fix up $set sugar
      +      if (!ret.$set) {
      +        if (obj.$set) {
      +          ret.$set = obj.$set;
      +        } else {
      +          ret.$set = {};
      +        }
      +      }
      +      ret.$set[op] = obj[op];
      +      ops.splice(i, 1);
      +      if (!~ops.indexOf('$set')) ops.push('$set');
      +    } else if ('$set' === op) {
      +      if (!ret.$set) {
      +        ret[op] = obj[op];
      +      }
      +    } else {
      +      ret[op] = obj[op];
      +    }
      +  }
      +
      +  // cast each value
      +  i = ops.length;
      +
      +  while (i--) {
      +    op = ops[i];
      +    val = ret[op];
      +    if ('Object' === val.constructor.name) {
      +      hasKeys |= this._walkUpdatePath(val, op);
      +    } else {
      +      var msg = 'Invalid atomic update value for ' + op + '. '
      +              + 'Expected an object, received ' + typeof val;
      +      throw new Error(msg);
      +    }
      +  }
      +
      +  return hasKeys && ret;
      +}

      Parameters:

      Returns:

      • <Object> obj after casting its values

      Query#_walkUpdatePath(obj, op, pref)

      Walk each path of obj and cast its values
      according to its schema.

      show code
      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
      +  var strict = this.model.schema.options.strict
      +    , prefix = pref ? pref + '.' : ''
      +    , keys = Object.keys(obj)
      +    , i = keys.length
      +    , hasKeys = false
      +    , schema
      +    , key
      +    , val
      +
      +  while (i--) {
      +    key = keys[i];
      +    val = obj[key];
      +
      +    if (val && 'Object' === val.constructor.name) {
      +      // watch for embedded doc schemas
      +      schema = this._getSchema(prefix + key);
      +      if (schema && schema.caster && op in castOps) {
      +        // embedded doc schema
      +
      +        if (strict && !schema) {
      +          // path is not in our strict schema
      +          if ('throw' == strict) {
      +            throw new Error('Field `' + key + '` is not in schema.');
      +          } else {
      +            // ignore paths not specified in schema
      +            delete obj[key];
      +          }
      +        } else {
      +          hasKeys = true;
      +          if ('$each' in val) {
      +            obj[key] = {
      +                $each: this._castUpdateVal(schema, val.$each, op)
      +            }
      +          } else {
      +            obj[key] = this._castUpdateVal(schema, val, op);
      +          }
      +        }
      +      } else {
      +        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
      +      }
      +    } else {
      +      schema = '$each' === key
      +        ? this._getSchema(pref)
      +        : this._getSchema(prefix + key);
      +
      +      var skip = strict &&
      +                 !schema &&
      +                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
      +
      +      if (skip) {
      +        if ('throw' == strict) {
      +          throw new Error('Field `' + prefix + key + '` is not in schema.');
      +        } else {
      +          delete obj[key];
      +        }
      +      } else {
      +        hasKeys = true;
      +        obj[key] = this._castUpdateVal(schema, val, op, key);
      +      }
      +    }
      +  }
      +  return hasKeys;
      +}

      Parameters:

      • obj <Object> - part of a query
      • op <String> - the atomic operator ($pull, $set, etc)
      • pref <String> - path prefix (internal only)

      Returns:

      • <Bool> true if this path has keys to update

      Query#_castUpdateVal(schema, val, op, [$conditional])

      Casts val according to schema and atomic op.

      show code
      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
      +  if (!schema) {
      +    // non-existing schema path
      +    return op in numberOps
      +      ? Number(val)
      +      : val
      +  }
      +
      +  if (schema.caster && op in castOps &&
      +    ('Object' === val.constructor.name || Array.isArray(val))) {
      +    // Cast values for ops that add data to MongoDB.
      +    // Ensures embedded documents get ObjectIds etc.
      +    var tmp = schema.cast(val);
      +
      +    if (Array.isArray(val)) {
      +      val = tmp;
      +    } else {
      +      val = tmp[0];
      +    }
      +  }
      +
      +  if (op in numberOps) return Number(val);
      +  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
      +  return schema.castForQuery(val)
      +}

      Parameters:


      Query#_getSchema(path)

      Finds the schema for path. This is different than
      calling schema.path as it also resolves paths with
      positional selectors (something.$.another.$.path).

      show code
      Query.prototype._getSchema = function _getSchema (path) {
      +  var schema = this.model.schema
      +    , pathschema = schema.path(path);
      +
      +  if (pathschema)
      +    return pathschema;
      +
      +  // look for arrays
      +  return (function search (parts, schema) {
      +    var p = parts.length + 1
      +      , foundschema
      +      , trypath
      +
      +    while (p--) {
      +      trypath = parts.slice(0, p).join('.');
      +      foundschema = schema.path(trypath);
      +      if (foundschema) {
      +        if (foundschema.caster) {
      +
      +          // array of Mixed?
      +          if (foundschema.caster instanceof Types.Mixed) {
      +            return foundschema.caster;
      +          }
      +
      +          // Now that we found the array, we need to check if there
      +          // are remaining document paths to look up for casting.
      +          // Also we need to handle array.$.path since schema.path
      +          // doesn't work for that.
      +          if (p !== parts.length) {
      +            if ('$' === parts[p]) {
      +              // comments.$.comments.$.title
      +              return search(parts.slice(p+1), foundschema.schema);
      +            } else {
      +              // this is the last path of the selector
      +              return search(parts.slice(p), foundschema.schema);
      +            }
      +          }
      +        }
      +        return foundschema;
      +      }
      +    }
      +  })(path.split('.'), schema)
      +}

      Parameters:


      Query#_castFields(fields)

      Casts selected field arguments for field selection with mongo 2.2

      show code
      Query.prototype._castFields = function _castFields (fields) {
      +  var selected
      +    , elemMatchKeys
      +    , keys
      +    , key
      +    , out
      +    , i
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    elemMatchKeys = [];
      +    i = keys.length;
      +
      +    // collect $elemMatch args
      +    while (i--) {
      +      key = keys[i];
      +      if (fields[key].$elemMatch) {
      +        selected || (selected = {});
      +        selected[key] = fields[key];
      +        elemMatchKeys.push(key);
      +      }
      +    }
      +  }
      +
      +  if (selected) {
      +    // they passed $elemMatch, cast em
      +    try {
      +      out = this.cast(this.model, selected);
      +    } catch (err) {
      +      return err;
      +    }
      +
      +    // apply the casted field args
      +    i = elemMatchKeys.length;
      +    while (i--) {
      +      key = elemMatchKeys[i];
      +      fields[key] = out[key];
      +    }
      +  }
      +
      +  return fields;
      +}

      Parameters:

      query.select({ ids: { $elemMatch: { $in: [hexString] }})

      Query#remove(callback)

      Executes this query as a remove() operation.

      show code
      Query.prototype.remove = function (callback) {
      +  this.op = 'remove';
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , cb = 'function' == typeof callback
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    if (cb) return callback(err);
      +    throw err;
      +  }
      +
      +  if (!cb) {
      +    delete options.safe;
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.remove(castQuery, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Example

      + +
      Cassette.where('artist').equals('Anne Murray').remove(callback)

      Query#findOneAndUpdate([query], [doc], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
      +  this.op = 'findOneAndUpdate';
      +
      +  switch (arguments.length) {
      +    case 3:
      +      if ('function' == typeof options)
      +        callback = options, options = {};
      +      break;
      +    case 2:
      +      if ('function' == typeof doc) {
      +        callback = doc;
      +        doc = query;
      +        query = undefined;
      +      }
      +      options = undefined;
      +      break;
      +    case 1:
      +      if ('function' == typeof query) {
      +        callback = query;
      +        query = options = doc = undefined;
      +      } else {
      +        doc = query;
      +        query = options = undefined;
      +      }
      +  }
      +
      +  // apply query
      +  if (query) {
      +    if ('Object' === query.constructor.name) {
      +      merge(this._conditions, query);
      +    } else if (query instanceof Query) {
      +      merge(this._conditions, query._conditions);
      +    } else if (query instanceof Document) {
      +      merge(this._conditions, query.toObject());
      +    }
      +  }
      +
      +  // apply doc
      +  if (doc) {
      +    merge(this._updateArg, doc);
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('update', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      query.findOneAndUpdate(conditions, update, options, callback) // executes
      +query.findOneAndUpdate(conditions, update, options)  // returns Query
      +query.findOneAndUpdate(conditions, update, callback) // executes
      +query.findOneAndUpdate(conditions, update)           // returns Query
      +query.findOneAndUpdate(callback)                     // executes
      +query.findOneAndUpdate()                             // returns Query

      Query#findOneAndRemove([conditions], [options], [callback])

      Issues a mongodb findAndModify remove command.

      show code
      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
      +  this.op = 'findOneAndRemove';
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = undefined;
      +  }
      +
      +  // apply conditions
      +  if (conditions) {
      +    if ('Object' === conditions.constructor.name) {
      +      merge(this._conditions, conditions);
      +    } else if (conditions instanceof Query) {
      +      merge(this._conditions, conditions._conditions);
      +    } else if (conditions instanceof Document) {
      +      merge(this._conditions, conditions.toObject());
      +    }
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('remove', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      A.where().findOneAndRemove(conditions, options, callback) // executes
      +A.where().findOneAndRemove(conditions, options)  // return Query
      +A.where().findOneAndRemove(conditions, callback) // executes
      +A.where().findOneAndRemove(conditions) // returns Query
      +A.where().findOneAndRemove(callback)   // executes
      +A.where().findOneAndRemove()           // returns Query

      Query#_findAndModify(type, callback)

      _findAndModify

      show code
      Query.prototype._findAndModify = function (type, callback) {
      +  var model = this.model
      +    , promise = new Promise(callback)
      +    , self = this
      +    , castedQuery
      +    , castedDoc
      +    , fields
      +    , sort
      +    , opts
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    process.nextTick(promise.error.bind(promise, castedQuery));
      +    return promise;
      +  }
      +
      +  opts = this._optionsForExec(model);
      +
      +  if ('remove' == type) {
      +    opts.remove = true;
      +  } else {
      +    if (!('new' in opts)) opts.new = true;
      +    if (!('upsert' in opts)) opts.upsert = false;
      +
      +    castedDoc = castDoc(this);
      +    if (!castedDoc) {
      +      if (opts.upsert) {
      +        // still need to do the upsert to empty doc
      +        castedDoc = { $set: {} };
      +      } else {
      +        return this.findOne(callback);
      +      }
      +    } else if (castedDoc instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, castedDoc));
      +      return promise;
      +    }
      +  }
      +
      +  this._applyPaths();
      +
      +  if (this._fields) {
      +    fields = utils.clone(this._fields)
      +    opts.fields = this._castFields(fields);
      +    if (opts.fields instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, opts.fields));
      +      return promise;
      +    }
      +  }
      +
      +  // the driver needs a default
      +  sort = opts.sort || [];
      +
      +  model
      +  .collection
      +  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === opts.lean) {
      +      return promise.complete(doc);
      +    }
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return promise;
      +}

      Parameters:


      Query#populate(path, [fields], [model], [conditions], [options])

      Specifies paths which should be populated with other documents.

      show code
      Query.prototype.populate = function (path, fields, model, conditions, options) {
      +  if ('string' !== typeof model) {
      +    options = conditions;
      +    conditions = model;
      +    model = undefined;
      +  }
      +  // The order of fields/conditions args is opposite Model.find but
      +  // necessary to keep backward compatibility (fields could be
      +  // an array, string, or object literal).
      +  this.options.populate[path] =
      +    new PopulateOptions(fields, conditions, options, model);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

      + +

      Example:

      + +
      Kitten.findOne().populate('owner').exec(function (err, kitten) {
      +  console.log(kitten.owner.name) // Max
      +})

      Query#stream()

      Returns a stream interface

      show code
      Query.prototype.stream = function stream () {
      +  return new QueryStream(this);
      +}
      +
      +// helpers

      Returns:

      Example

      + +
      // follows the nodejs stream api
      +Thing.find({ name: /^hello/ }).stream().pipe(res)
      +
      +// manual streaming
      +var stream = Thing.find({ name: /^hello/ }).stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});

      Query#within

      Syntax sugar for expressive queries.

      + +

      Example

      + +
      query.within.box()
      +query.within.center()

      Returns:


    • querystream.js

      QueryStream(query)

      Provides a ReadStream interface for Queries.

      show code
      function QueryStream (query) {
      +  Stream.call(this);
      +
      +  this.query = query;
      +  this.readable = true;
      +  this.paused = false;
      +  this._cursor = null;
      +  this._destroyed = null;
      +  this._fields = null;
      +  this._buffer = null;
      +  this._inline = T_INIT;
      +  this._running = false;
      +
      +  // give time to hook up events
      +  var self = this;
      +  process.nextTick(function () {
      +    self._init();
      +  });
      +}

      Parameters:

      Inherits:

      Events:

      • data: emits a single Mongoose document

      • error: emits when an error occurs during streaming. This will emit before the close event.

      • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

      var stream = Model.find().stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});
      + +

      The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

      + +
      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

      QueryStream#_init()

      Initializes the query.

      show code
      QueryStream.prototype._init = function () {
      +  if (this._destroyed) return;
      +
      +  var query = this.query
      +    , model = query.model
      +    , options = query._optionsForExec(model)
      +    , self = this
      +
      +  try {
      +    query.cast(model);
      +  } catch (err) {
      +    return self.destroy(err);
      +  }
      +
      +  self._fields = utils.clone(query._fields);
      +  options.fields = query._castFields(self._fields);
      +
      +  model.collection.find(query._conditions, options, function (err, cursor) {
      +    if (err) return self.destroy(err);
      +    self._cursor = cursor;
      +    self._next();
      +  });
      +}

      QueryStream#_next()

      Trampoline for pulling the next doc from cursor.

      show code
      QueryStream.prototype._next = function _next () {
      +  if (this.paused || this._destroyed) {
      +    return this._running = false;
      +  }
      +
      +  this._running = true;
      +
      +  if (this._buffer && this._buffer.length) {
      +    var arg;
      +    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
      +      this._onNextObject.apply(this, arg);
      +    }
      +  }
      +
      +  // avoid stack overflows with large result sets.
      +  // trampoline instead of recursion.
      +  while (this.__next()) {}
      +}

      QueryStream#__next()

      Pulls the next doc from the cursor.

      show code
      QueryStream.prototype.__next = function () {
      +  if (this.paused || this._destroyed)
      +    return this._running = false;
      +
      +  var self = this;
      +  self._inline = T_INIT;
      +
      +  self._cursor.nextObject(function cursorcb (err, doc) {
      +    self._onNextObject(err, doc);
      +  });
      +
      +  // if onNextObject() was already called in this tick
      +  // return ourselves to the trampoline.
      +  if (T_CONT === this._inline) {
      +    return true;
      +  } else {
      +    // onNextObject() hasn't fired yet. tell onNextObject
      +    // that its ok to call _next b/c we are not within
      +    // the trampoline anymore.
      +    this._inline = T_IDLE;
      +  }
      +}

      QueryStream#_onNextObject(err, doc)

      Transforms raw docs returned from the cursor into a model instance.

      show code
      QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
      +  if (this._destroyed) return;
      +
      +  if (this.paused) {
      +    this._buffer || (this._buffer = []);
      +    this._buffer.push([err, doc]);
      +    return this._running = false;
      +  }
      +
      +  if (err) return this.destroy(err);
      +
      +  // when doc is null we hit the end of the cursor
      +  if (!doc) {
      +    this.emit('end');
      +    return this.destroy();
      +  }
      +
      +  if (this.query.options && true === this.query.options.lean)  {
      +    this.emit('data', doc);
      +
      +    // trampoline management
      +    if (T_IDLE === this._inline) {
      +      // no longer in trampoline. restart it.
      +      this._next();
      +    } else {
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      this._inline = T_CONT;
      +    }
      +    return;
      +  }
      +
      +  var instance = new this.query.model(undefined, this._fields, true);
      +
      +  var self = this;
      +  instance.init(doc, this.query, function (err) {
      +    if (err) return self.destroy(err);
      +    self.emit('data', instance);
      +
      +    // trampoline management
      +    if (T_IDLE === self._inline) {
      +      // no longer in trampoline. restart it.
      +      self._next();
      +    } else
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      self._inline = T_CONT;
      +  });
      +}

      Parameters:


      QueryStream#pause()

      Pauses this stream.

      show code
      QueryStream.prototype.pause = function () {
      +  this.paused = true;
      +}

      QueryStream#resume()

      Resumes this stream.

      show code
      QueryStream.prototype.resume = function () {
      +  this.paused = false;
      +
      +  if (!this._cursor) {
      +    // cannot start if not initialized
      +    return;
      +  }
      +
      +  // are we within the trampoline?
      +  if (T_INIT === this._inline) {
      +    return;
      +  }
      +
      +  if (!this._running) {
      +    // outside QueryStream control, need manual restart
      +    return this._next();
      +  }
      +}

      QueryStream#destroy([err])

      Destroys the stream, closing the underlying cursor. No more events will be emitted.

      show code
      QueryStream.prototype.destroy = function (err) {
      +  if (this._destroyed) return;
      +  this._destroyed = true;
      +  this._running = false;
      +  this.readable = false;
      +
      +  if (this._cursor) {
      +    this._cursor.close();
      +  }
      +
      +  if (err) {
      +    this.emit('error', err);
      +  }
      +
      +  this.emit('close');
      +}

      Parameters:


      QueryStream#pipe()

      Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

      See:

      Example:

      + +
      query.stream().pipe(writeStream [, options])
      + +

      This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      + +
      var format = new ArrayFormatter;
      +Events.find().stream().pipe(format).pipe(res);
      + +

      As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


      QueryStream#paused

      Flag stating whether or not this stream is paused.


      QueryStream#readable

      Flag stating whether or not this stream is readable.


    • schema/array.js

      SchemaArray(key, cast, options)

      Array SchemaType constructor

      show code
      function SchemaArray (key, cast, options) {
      +  if (cast) {
      +    var castOptions = {};
      +
      +    if ('Object' === cast.constructor.name) {
      +      if (cast.type) {
      +        // support { type: Woot }
      +        castOptions = cast;
      +        cast = cast.type;
      +        delete castOptions.type;
      +      } else {
      +        cast = Mixed;
      +      }
      +    }
      +
      +    var caster = cast.name in Types ? Types[cast.name] : cast;
      +    this.casterConstructor = caster;
      +    this.caster = new caster(null, castOptions);
      +  }
      +
      +  SchemaType.call(this, key, options);
      +
      +  var self = this
      +    , defaultArr
      +    , fn;
      +
      +  if (this.defaultValue) {
      +    defaultArr = this.defaultValue;
      +    fn = 'function' == typeof defaultArr;
      +  }
      +
      +  this.default(function(){
      +    var arr = fn ? defaultArr() : defaultArr || [];
      +    return new MongooseArray(arr, self.path, this);
      +  });
      +};

      Parameters:

      Inherits:


      SchemaArray#checkRequired(value)

      Check required

      show code
      SchemaArray.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      Parameters:


      SchemaArray#applyGetters(value, scope)

      Overrides the getters application for the population special-case

      show code
      SchemaArray.prototype.applyGetters = function (value, scope) {
      +  if (this.caster.options && this.caster.options.ref) {
      +    // means the object id was populated
      +    return value;
      +  }
      +
      +  return SchemaType.prototype.applyGetters.call(this, value, scope);
      +};

      Parameters:


      SchemaArray#cast(value, doc, init)

      Casts contents

      show code
      SchemaArray.prototype.cast = function (value, doc, init) {
      +  if (Array.isArray(value)) {
      +    if (!(value instanceof MongooseArray)) {
      +      value = new MongooseArray(value, this.path, doc);
      +    }
      +
      +    if (this.caster) {
      +      try {
      +        for (var i = 0, l = value.length; i < l; i++) {
      +          value[i] = this.caster.cast(value[i], doc, init);
      +        }
      +      } catch (e) {
      +        // rethrow
      +        throw new CastError(e.type, value);
      +      }
      +    }
      +
      +    return value;
      +  } else {
      +    return this.cast([value], doc, init);
      +  }
      +};

      Parameters:

      • value <Object>
      • doc <Document> document that triggers the casting
      • init <Boolean> whether this is an initialization cast

      SchemaArray#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaArray.prototype.castForQuery = function ($conditional, value) {
      +  var handler
      +    , val;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Array.");
      +    val = handler.call(this, value);
      +  } else {
      +    val = $conditional;
      +    var proto = this.casterConstructor.prototype;
      +    var method = proto.castForQuery || proto.cast;
      +    if (Array.isArray(val)) {
      +      val = val.map(function (v) {
      +        if (method) v = method.call(proto, v);
      +        return isMongooseObject(v)
      +          ? v.toObject()
      +          : v;
      +      });
      +    } else if (method) {
      +      val = method.call(proto, val);
      +    }
      +  }
      +  return val && isMongooseObject(val)
      +    ? val.toObject()
      +    : val;
      +};

      Parameters:


    • schema/boolean.js

      SchemaBoolean(path, options)

      Boolean SchemaType constructor.

      show code
      function SchemaBoolean (path, options) {
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      SchemaBoolean#checkRequired()

      Required validator

      show code
      SchemaBoolean.prototype.checkRequired = function (value) {
      +  return value === true || value === false;
      +};

      SchemaBoolean#cast(value)

      Casts to boolean

      show code
      SchemaBoolean.prototype.cast = function (value) {
      +  if (value === null) return value;
      +  if (value === '0') return false;
      +  return !!value;
      +};

      Parameters:


      SchemaBoolean#castForQuery($conditional, val)

      Casts contents for queries.

      show code
      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (2 === arguments.length) {
      +    handler = SchemaBoolean.$conditionalHandlers[$conditional];
      +
      +    if (handler) {
      +      return handler.call(this, val);
      +    }
      +
      +    return this.cast(val);
      +  }
      +
      +  return this.cast($conditional);
      +};

      Parameters:


    • schema/buffer.js

      SchemaBuffer(key, cast)

      Buffer SchemaType constructor

      show code
      function SchemaBuffer (key, options) {
      +  SchemaType.call(this, key, options, 'Buffer');
      +};

      Parameters:

      Inherits:


      SchemaBuffer#checkRequired()

      Check required

      show code
      SchemaBuffer.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      SchemaBuffer#cast(value, doc, init)

      Casts contents

      show code
      SchemaBuffer.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (Buffer.isBuffer(value)) {
      +    if (!(value instanceof MongooseBuffer)) {
      +      value = new MongooseBuffer(value, [this.path, doc]);
      +    }
      +
      +    return value;
      +  } else if (value instanceof Binary) {
      +    return new MongooseBuffer(value.value(true), [this.path, doc]);
      +  }
      +
      +  if ('string' === typeof value || Array.isArray(value)) {
      +    return new MongooseBuffer(value, [this.path, doc]);
      +  }
      +
      +  throw new CastError('buffer', value);
      +};

      Parameters:


      SchemaBuffer#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Buffer.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    return this.cast(val).toObject();
      +  }
      +};

      Parameters:


    • schema/date.js

      SchemaDate(key, options)

      Date SchemaType constructor.

      show code
      function SchemaDate (key, options) {
      +  SchemaType.call(this, key, options);
      +};

      Parameters:

      Inherits:


      SchemaDate#checkRequired()

      Required validator for date

      show code
      SchemaDate.prototype.checkRequired = function (value) {
      +  return value instanceof Date;
      +};

      SchemaDate#cast(value)

      Casts to date

      show code
      SchemaDate.prototype.cast = function (value) {
      +  if (value === null || value === '')
      +    return null;
      +
      +  if (value instanceof Date)
      +    return value;
      +
      +  var date;
      +
      +  // support for timestamps
      +  if (value instanceof Number || 'number' == typeof value 
      +      || String(value) == Number(value))
      +    date = new Date(Number(value));
      +
      +  // support for date strings
      +  else if (value.toString)
      +    date = new Date(value.toString());
      +
      +  if (date.toString() != 'Invalid Date')
      +    return date;
      +
      +  throw new CastError('date', value);
      +};

      Parameters:


      SchemaDate#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaDate.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +
      +  if (2 !== arguments.length) {
      +    return this.cast($conditional);
      +  }
      +
      +  handler = this.$conditionalHandlers[$conditional];
      +
      +  if (!handler) {
      +    throw new Error("Can't use " + $conditional + " with Date.");
      +  }
      +
      +  return handler.call(this, val);
      +};

      Parameters:


    • schema/documentarray.js

      DocumentArray(key, schema, options)

      SubdocsArray SchemaType constructor

      show code
      function DocumentArray (key, schema, options) {
      +
      +  // compile an embedded document for this schema
      +  function EmbeddedDocument () {
      +    Subdocument.apply(this, arguments);
      +  }
      +
      +  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
      +  EmbeddedDocument.prototype._setSchema(schema);
      +  EmbeddedDocument.schema = schema;
      +
      +  // apply methods
      +  for (var i in schema.methods) {
      +    EmbeddedDocument.prototype[i] = schema.methods[i];
      +  }
      +
      +  // apply statics
      +  for (var i in schema.statics)
      +    EmbeddedDocument[i] = schema.statics[i];
      +
      +  EmbeddedDocument.options = options;
      +  this.schema = schema;
      +
      +  ArrayType.call(this, key, EmbeddedDocument, options);
      +
      +  this.schema = schema;
      +  var path = this.path;
      +  var fn = this.defaultValue;
      +
      +  this.default(function(){
      +    var arr = fn.call(this);
      +    if (!Array.isArray(arr)) arr = [arr];
      +    return new MongooseDocumentArray(arr, path, this);
      +  });
      +};

      Parameters:

      Inherits:


      DocumentArray#doValidate()

      Performs local validations first, then validations on each embedded doc

      show code
      DocumentArray.prototype.doValidate = function (array, fn, scope) {
      +  var self = this;
      +
      +  SchemaType.prototype.doValidate.call(this, array, function (err) {
      +    if (err) return fn(err);
      +
      +    var count = array && array.length
      +      , error;
      +
      +    if (!count) return fn();
      +
      +    // handle sparse arrays, do not use array.forEach which does not
      +    // iterate over sparse elements yet reports array.length including
      +    // them :(
      +
      +    for (var i = 0, len = count; i < len; ++i) {
      +      // sidestep sparse entries
      +      var doc = array[i];
      +      if (!doc) {
      +        --count || fn();
      +        continue;
      +      }
      +
      +      ;(function (i) {
      +        doc.validate(function (err) {
      +          if (err && !error) {
      +            // rewrite the key
      +            err.key = self.key + '.' + i + '.' + err.key;
      +            return fn(error = err);
      +          }
      +          --count || fn();
      +        });
      +      })(i);
      +    }
      +  }, scope);
      +};

      DocumentArray#cast(value, document)

      Casts contents

      show code
      DocumentArray.prototype.cast = function (value, doc, init, prev) {
      +  var selected
      +    , subdoc
      +    , i
      +
      +  if (!Array.isArray(value)) {
      +    return this.cast([value], doc, init, prev);
      +  }
      +
      +  if (!(value instanceof MongooseDocumentArray)) {
      +    value = new MongooseDocumentArray(value, this.path, doc);
      +  }
      +
      +  i = value.length;
      +
      +  while (i--) {
      +    if (!(value[i] instanceof Subdocument) && value[i]) {
      +      if (init) {
      +        selected || (selected = scopePaths(this, doc._selected, init));
      +        subdoc = new this.casterConstructor(null, value, true, selected);
      +        value[i] = subdoc.init(value[i]);
      +      } else {
      +        if (prev && (subdoc = prev.id(value[i]._id))) {
      +          // handle resetting doc with existing id but differing data
      +          // doc.array = [{ doc: 'val' }]
      +          subdoc.set(value[i]);
      +        } else {
      +          subdoc = new this.casterConstructor(value[i], value);
      +        }
      +
      +        // if set() is hooked it will have no return value
      +        // see gh-746
      +        value[i] = subdoc;
      +      }
      +    }
      +  }
      +
      +  return value;
      +}

      Parameters:


    • schema/mixed.js

      Mixed(path, options)

      Mixed SchemaType constructor.

      show code
      function Mixed (path, options) {
      +  // make sure empty array defaults are handled
      +  if (options &&
      +      options.default &&
      +      Array.isArray(options.default) &&
      +      0 === options.default.length) {
      +    options.default = Array;
      +  }
      +
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      Mixed#checkRequired()

      Required validator

      show code
      Mixed.prototype.checkRequired = function (val) {
      +  return true;
      +};

      Mixed#cast(value)

      Casts val for Mixed.

      show code
      Mixed.prototype.cast = function (val) {
      +  return val;
      +};

      Parameters:

      this is a no-op


      Mixed#castForQuery($cond, [val])

      Casts contents for queries.

      show code
      Mixed.prototype.castForQuery = function ($cond, val) {
      +  if (arguments.length === 2) return val;
      +  return $cond;
      +};

      Parameters:


    • schema/number.js

      SchemaNumber(key, options)

      Number SchemaType constructor.

      show code
      function SchemaNumber (key, options) {
      +  SchemaType.call(this, key, options, 'Number');
      +};

      Parameters:

      Inherits:


      SchemaNumber#checkRequired()

      Required validator for number

      show code
      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return typeof value == 'number' || value instanceof Number;
      +  }
      +};

      SchemaNumber#min(value, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.min = function (value, message) {
      +  if (this.minValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'min';
      +    });
      +  if (value != null)
      +    this.validators.push([function(v){
      +      return v === null || v >= value;
      +    }, 'min']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, min: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 9 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#max(maximum, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.max = function (value, message) {
      +  if (this.maxValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'max';
      +    });
      +  if (value != null)
      +    this.validators.push([this.maxValidator = function(v){
      +      return v === null || v <= value;
      +    }, 'max']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, max: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 11 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#cast(value, doc, init)

      Casts to number

      show code
      SchemaNumber.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (!isNaN(value)){
      +    if (null === value) return value;
      +    if ('' === value) return null;
      +    if ('string' == typeof value) value = Number(value);
      +    if (value instanceof Number) return value
      +    if ('number' == typeof value) return value;
      +    if (value.toString && !Array.isArray(value) &&
      +        value.toString() == Number(value)) {
      +      return new Number(value)
      +    }
      +  }
      +
      +  throw new CastError('number', value);
      +};

      Parameters:


      SchemaNumber#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Number.");
      +    return handler.call(this, val);
      +  } else {
      +    val = this.cast($conditional);
      +    return val == null ? val : val
      +  }
      +};

      Parameters:


    • schema/objectid.js

      ObjectId(key, options)

      ObjectId SchemaType constructor.

      show code
      function ObjectId (key, options) {
      +  SchemaType.call(this, key, options, 'ObjectID');
      +};

      Parameters:

      Inherits:


      ObjectId#checkRequired()

      Check required

      show code
      ObjectId.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return value instanceof oid;
      +  }
      +};

      ObjectId#cast(value, scope, init)

      Casts to ObjectId

      show code
      ObjectId.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (value === null) return value;
      +
      +  if (value instanceof oid)
      +    return value;
      +
      +  if (value._id && value._id instanceof oid)
      +    return value._id;
      +
      +  if (value.toString)
      +    return oid.fromString(value.toString());
      +
      +  throw new CastError('object id', value);
      +};

      Parameters:


      ObjectId#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      ObjectId.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with ObjectId.");
      +    return handler.call(this, val);
      +  } else {
      +    return this.cast($conditional);
      +  }
      +};

      Parameters:


      ObjectId#auto(turnOn)

      Adds an auto-generated ObjectId default if turnOn is true.

      show code
      ObjectId.prototype.auto = function (turnOn) {
      +  if (turnOn) {
      +    this.default(defaultId);
      +    this.set(resetId)
      +  }
      +};

      Parameters:

      • turnOn <Boolean> auto generated ObjectId defaults

    • schema/string.js

      SchemaString(key, options)

      String SchemaType constructor.

      show code
      function SchemaString (key, options) {
      +  this.enumValues = [];
      +  this.regExp = null;
      +  SchemaType.call(this, key, options, 'String');
      +};

      Parameters:

      Inherits:


      SchemaString#enum([args...])

      Adds enumeration values and a coinciding validator.

      show code
      SchemaString.prototype.enum = function () {
      +  var len = arguments.length;
      +  if (!len || undefined === arguments[0] || false === arguments[0]) {
      +    if (this.enumValidator){
      +      this.enumValidator = false;
      +      this.validators = this.validators.filter(function(v){
      +        return v[1] != 'enum';
      +      });
      +    }
      +    return;
      +  }
      +
      +  for (var i = 0; i < len; i++) {
      +    if (undefined !== arguments[i]) {
      +      this.enumValues.push(this.cast(arguments[i]));
      +    }
      +  }
      +
      +  if (!this.enumValidator) {
      +    var values = this.enumValues;
      +    this.enumValidator = function(v){
      +      return undefined === v || ~values.indexOf(v);
      +    };
      +    this.validators.push([this.enumValidator, 'enum']);
      +  }
      +};

      Parameters:

      • [args...] <String> enumeration values

      Example:

      + +
      var states = 'opening open closing closed'.split(' ')
      +var s = new Schema({ state: { type: String, enum: states })
      +var M = db.model('M', s)
      +var m = new M({ state: 'invalid' })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.state = 'open'
      +  m.save() // success
      +})

      SchemaString#lowercase()

      Adds a lowercase setter.

      show code
      SchemaString.prototype.lowercase = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.toLowerCase();
      +    return v;
      +  });
      +};

      Example:

      + +
      var s = new Schema({ email: { type: String, lowercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ email: 'SomeEmail@example.COM' });
      +console.log(m.email) // someemail@example.com
      +

      SchemaString#uppercase()

      Adds an uppercase setter.

      show code
      SchemaString.prototype.uppercase = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.toUpperCase();
      +    return v;
      +  });
      +};

      Example:

      + +
      var s = new Schema({ caps: { type: String, uppercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ caps: 'an example' });
      +console.log(m.caps) // AN EXAMPLE

      SchemaString#trim()

      Adds a trim setter.

      show code
      SchemaString.prototype.trim = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.trim();
      +    return v;
      +  });
      +};

      The string value will be trimmed when set.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, trim: true }})
      +var M = db.model('M', s)
      +var string = ' some name '
      +console.log(string.length) // 11
      +var m = new M({ name: string })
      +console.log(m.name.length) // 9

      SchemaString#match(regExp)

      Sets a regexp validator.

      show code
      SchemaString.prototype.match = function match (regExp) {
      +  this.validators.push([function(v){
      +    return null != v && '' !== v
      +      ? regExp.test(v)
      +      : true
      +  }, 'regexp']);
      +};

      Parameters:

      • regExp <RegExp> regular expression to test against

      Any value that does not pass regExp.test(val) will fail validation.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, match: /^a/ }})
      +var M = db.model('M', s)
      +var m = new M({ name: 'invalid' })
      +m.validate(function (err) {
      +  console.error(err) // validation error
      +  m.name = 'apples'
      +  m.validate(function (err) {
      +    assert.ok(err) // success
      +  })
      +})

      SchemaString#checkRequired(value)

      Check required

      show code
      SchemaString.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return (value instanceof String || typeof value == 'string') && value.length;
      +  }
      +};

      Parameters:


      SchemaString#cast()

      Casts to String

      show code
      SchemaString.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +  if (value === null) return value;
      +  if ('undefined' !== typeof value && value.toString) return value.toString();
      +  throw new CastError('string', value);
      +};

      SchemaString#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      SchemaString.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with String.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    if (val instanceof RegExp) return val;
      +    return this.cast(val);
      +  }
      +};

      Parameters:


    • schema.js

      Schema(definition)

      Schema constructor.

      show code
      function Schema (obj, options) {
      +  if (!(this instanceof Schema))
      +    return new Schema(obj, options);
      +
      +  this.paths = {};
      +  this.subpaths = {};
      +  this.virtuals = {};
      +  this.nested = {};
      +  this.inherits = {};
      +  this.callQueue = [];
      +  this._indexes = [];
      +  this.methods = {};
      +  this.statics = {};
      +  this.tree = {};
      +  this._requiredpaths = undefined;
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // build paths
      +  if (obj) {
      +    this.add(obj);
      +  }
      +
      +  // ensure the documents get an auto _id unless disabled
      +  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
      +  if (auto_id) {
      +    this.add({ _id: {type: Schema.ObjectId, auto: true} });
      +  }
      +
      +  // ensure the documents receive an id getter unless disabled
      +  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
      +  if (autoid) {
      +    this.virtual('id').get(idGetter);
      +  }
      +
      +  // versioning not directly added to schema b/c we only want
      +  // it in the top level document, not embedded ones.
      +};

      Parameters:

      Events:

      • init: Emitted after the schema is compiled into a Model.

      Example:

      + +
      var child = new Schema({ name: String });
      +var schema = new Schema({ name: String, age: Number, children: [child] });
      +var Tree = mongoose.model('Tree', schema);
      +
      +// setting schema options
      +new Schema({ name: String }, { _id: false, autoIndex: false })
      + +

      Options:

      + +
        +
      • safe: bool - defaults to true.
      • +
      • read: string
      • +
      • strict: bool - defaults to true
      • +
      • capped: bool - defaults to false
      • +
      • versionKey: bool - defaults to "__v"
      • +
      • shardKey: bool - defaults to null
      • +
      • autoIndex: bool - defaults to true
      • +
      • _id: bool - defaults to true
      • +
      • id: bool - defaults to true
      • +
      • toObject - object - no default
      • +
      • toJSON - object - no default
      • +
      • minimize: bool - controls document#toObject behavior when called manually - defaults to true
      • +
      + +

      Note:

      + +

      When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


      Schema#defaultOptions(options)

      Returns default options for this schema, merged with options.

      show code
      Schema.prototype.defaultOptions = function (options) {
      +  options = utils.options({
      +      safe: true
      +    , strict: true
      +    , capped: false // { size, max, autoIndexId }
      +    , versionKey: '__v'
      +    , minimize: true
      +    , autoIndex: true
      +    , shardKey: null
      +    , read: null
      +    // the following are only applied at construction time
      +    , noId: false // deprecated, use { _id: false }
      +    , _id: true
      +    , noVirtualId: false // deprecated, use { id: false }
      +    , id: true
      +  }, options);
      +
      +  if (options.read)
      +    options.read = utils.readPref(options.read);
      +
      +  return options;
      +}

      Parameters:

      Returns:


      Schema#add(obj, prefix)

      Adds key path / schema type pairs to this schema.

      show code
      Schema.prototype.add = function add (obj, prefix) {
      +  prefix = prefix || '';
      +  for (var i in obj) {
      +    if (null == obj[i]) {
      +      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
      +    }
      +
      +    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
      +      if (Object.keys(obj[i]).length) {
      +        // nested object { last: { name: String }}
      +        this.nested[prefix + i] = true;
      +        this.add(obj[i], prefix + i + '.');
      +      }
      +      else
      +        this.path(prefix + i, obj[i]); // mixed type
      +    } else
      +      this.path(prefix + i, obj[i]);
      +  }
      +};

      Parameters:

      Example:

      + +
      var ToySchema = new Schema;
      +ToySchema.add({ name: 'string', color: 'string', price: 'number' });

      Schema#path(path, constructor)

      Gets/sets schema paths.

      show code
      Schema.prototype.path = function (path, obj) {
      +  if (obj == undefined) {
      +    if (this.paths[path]) return this.paths[path];
      +    if (this.subpaths[path]) return this.subpaths[path];
      +
      +    // subpaths?
      +    return /\.\d+\.?$/.test(path)
      +      ? getPositionalPath(this, path)
      +      : undefined;
      +  }
      +
      +  // some path names conflict with document methods
      +  if (reserved[path]) {
      +    throw new Error("`" + path + "` may not be used as a schema pathname");
      +  }
      +
      +  // update the tree
      +  var subpaths = path.split(/\./)
      +    , last = subpaths.pop()
      +    , branch = this.tree;
      +
      +  subpaths.forEach(function(path) {
      +    if (!branch[path]) branch[path] = {};
      +    branch = branch[path];
      +  });
      +
      +  branch[last] = utils.clone(obj);
      +
      +  this.paths[path] = Schema.interpretAsType(path, obj);
      +  return this;
      +};

      Parameters:

      Sets a path (if arity 2)
      Gets a path (if arity 1)

      + +

      Example

      + +
      schema.path('name') // returns a SchemaType
      +schema.path('name', Number) // changes the schemaType of `name` to Number

      Schema#eachPath(fn)

      Iterates the schemas paths similar to Array#forEach.

      show code
      Schema.prototype.eachPath = function (fn) {
      +  var keys = Object.keys(this.paths)
      +    , len = keys.length;
      +
      +  for (var i = 0; i < len; ++i) {
      +    fn(keys[i], this.paths[keys[i]]);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      The callback is passed the pathname and schemaType as arguments on each iteration.


      Schema#requiredPaths()

      Returns an Array of path strings that are required by this schema.

      show code
      Schema.prototype.requiredPaths = function requiredPaths () {
      +  if (this._requiredpaths) return this._requiredpaths;
      +
      +  var paths = Object.keys(this.paths)
      +    , i = paths.length
      +    , ret = [];
      +
      +  while (i--) {
      +    var path = paths[i];
      +    if (this.paths[path].isRequired) ret.push(path);
      +  }
      +
      +  return this._requiredpaths = ret;
      +}

      Returns:


      Schema#pathType(path)

      Returns the pathType of path for this schema.

      show code
      Schema.prototype.pathType = function (path) {
      +  if (path in this.paths) return 'real';
      +  if (path in this.virtuals) return 'virtual';
      +  if (path in this.nested) return 'nested';
      +  if (path in this.subpaths) return 'real';
      +
      +  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
      +    return 'real';
      +  } else {
      +    return 'adhocOrUndefined'
      +  }
      +};

      Parameters:

      Returns:

      Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


      Schema#queue(name, args)

      Adds a method call to the queue.

      show code
      Schema.prototype.queue = function(name, args){
      +  this.callQueue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the document method to call later
      • args <Array> arguments to pass to the method

      Schema#pre(method, callback)

      Defines a pre hook for the document.

      show code
      Schema.prototype.pre = function(){
      +  return this.queue('pre', arguments);
      +};

      Parameters:

      Example

      + +
      var toySchema = new Schema(..);
      +
      +toySchema.pre('save', function (next) {
      +  if (!this.created) this.created = new Date;
      +  next();
      +})
      +
      +toySchema.pre('validate', function (next) {
      +  if (this.name != 'Woody') this.name = 'Woody';
      +  next();
      +})

      Schema#post(method, fn)

      Defines a post hook for the document.

      show code
      Schema.prototype.post = function(method, fn){
      +  return this.queue('on', arguments);
      +};

      Parameters:

      Post hooks fire on the event emitted from document instances of Models compiled from this schema.

      + +
      var schema = new Schema(..);
      +schema.post('save', function () {
      +  console.log('this fired after a document was saved');
      +});
      +
      +var Model = mongoose.model('Model', schema);
      +
      +var m = new Model(..);
      +m.save(function (err) {
      +  console.log('this fires after the `post` hook');
      +});

      Schema#plugin(plugin, opts)

      Registers a plugin for this schema.

      show code
      Schema.prototype.plugin = function (fn, opts) {
      +  fn(this, opts);
      +  return this;
      +};

      Parameters:


      Schema#method(method, [fn])

      Adds an instance method to documents constructed from Models compiled from this schema.

      show code
      Schema.prototype.method = function (name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.methods[i] = name[i];
      +  else
      +    this.methods[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = kittySchema = new Schema(..);
      +
      +schema.methods.meow = function () {
      +  console.log('meeeeeoooooooooooow');
      +})
      +
      +var Kitty = mongoose.model('Kitty', schema);
      +
      +var fizz = new Kitty;
      +fizz.meow(); // meeeeeooooooooooooow
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      + +
      schema.method({
      +    purr: function () {}
      +  , scratch: function () {}
      +});
      +
      +// later
      +fizz.purr();
      +fizz.scratch();

      Schema#static(name, fn)

      Adds static "class" methods to Models compiled from this schema.

      show code
      Schema.prototype.static = function(name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.statics[i] = name[i];
      +  else
      +    this.statics[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = new Schema(..);
      +schema.static('findByName', function (name, callback) {
      +  return this.find({ name: name }, callback);
      +});
      +
      +var Drink = mongoose.model('Drink', schema);
      +Drink.findByName('sanpellegrino', function (err, drinks) {
      +  //
      +});
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


      Schema#index(fields, [options])

      Defines an index (most likely compound) for this schema.

      show code
      Schema.prototype.index = function (fields, options) {
      +  options || (options = {});
      +
      +  if (options.expires)
      +    utils.expires(options);
      +
      +  this._indexes.push([fields, options]);
      +  return this;
      +};

      Parameters:

      Example

      + +
      schema.index({ first: 1, last: -1 })

      Schema#set(key, [value])

      Sets/gets a schema option.

      show code
      Schema.prototype.set = function (key, value, tags) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +
      +  this.options[key] = 'read' == key
      +    ? utils.readPref(value, tags)
      +    : value;
      +
      +  return this;
      +};

      Parameters:

      • key <String> option name
      • [value] <Object> if not passed, the current option value is returned

      Schema#indexes()

      Compiles indexes from fields and schema-level indexes

      show code
      Schema.prototype.indexes = function () {
      +  var indexes = []
      +    , seenSchemas = [];
      +
      +  collectIndexes(this);
      +
      +  return indexes;
      +
      +  function collectIndexes (schema, prefix) {
      +    if (~seenSchemas.indexOf(schema)) return;
      +    seenSchemas.push(schema);
      +
      +    var index;
      +    var paths = schema.paths;
      +    prefix = prefix || '';
      +
      +    for (var i in paths) {
      +      if (paths[i]) {
      +        if (paths[i] instanceof Types.DocumentArray) {
      +          collectIndexes(paths[i].schema, i + '.');
      +        } else {
      +          index = paths[i]._index;
      +
      +          if (index !== false && index !== null){
      +            var field = {};
      +            field[prefix + i] = '2d' === index ? index : 1;
      +            var options = 'Object' === index.constructor.name ? index : {};
      +            if (!('background' in options)) options.background = true;
      +            indexes.push([field, options]);
      +          }
      +        }
      +      }
      +    }
      +
      +    if (prefix) {
      +      fixSubIndexPaths(schema, prefix);
      +    } else {
      +      schema._indexes.forEach(function (index) {
      +        if (!('background' in index[1])) index[1].background = true;
      +      });
      +      indexes = indexes.concat(schema._indexes);
      +    }
      +  }

      Schema#virtual(name, [options])

      Creates a virtual type with the given name.

      show code
      Schema.prototype.virtual = function (name, options) {
      +  var virtuals = this.virtuals;
      +  var parts = name.split('.');
      +  return virtuals[name] = parts.reduce(function (mem, part, i) {
      +    mem[part] || (mem[part] = (i === parts.length-1)
      +                            ? new VirtualType(options, name)
      +                            : {});
      +    return mem[part];
      +  }, this.tree);
      +};

      Parameters:

      Returns:


      Schema#virtualpath(name)

      Returns the virtual type with the given name.

      show code
      Schema.prototype.virtualpath = function (name) {
      +  return this.virtuals[name];
      +};

      Parameters:

      Returns:


      Schema#namedScope()

      These still haven't been fixed. Once they're working we'll make them public again.

      show code
      Schema.prototype.namedScope = function (name, fn) {
      +  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
      +    , newScope = Object.create(namedScopes)
      +    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
      +  allScopes[name] = newScope;
      +  newScope.name = name;
      +  newScope.block = fn;
      +  newScope.query = new Query();
      +  newScope.decorate(namedScopes, {
      +    block0: function (block) {
      +      return function () {
      +        block.call(this.query);
      +        return this;
      +      };
      +    },
      +    blockN: function (block) {
      +      return function () {
      +        block.apply(this.query, arguments);
      +        return this;
      +      };
      +    },
      +    basic: function (query) {
      +      return function () {
      +        this.query.find(query);
      +        return this;
      +      };
      +    }
      +  });
      +  return newScope;
      +};

      Schema.reserved

      Reserved document keys.

      show code
      Schema.reserved = Object.create(null);
      +var reserved = Schema.reserved;
      +reserved.on =
      +reserved.db =
      +reserved.init =
      +reserved.isNew =
      +reserved.errors =
      +reserved.schema =
      +reserved.options =
      +reserved.modelName =
      +reserved.collection = 1;

      Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      + +
      on, db, init, isNew, errors, schema, options, modelName, collection
      + +

      NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

      + +
      var schema = new Schema(..);
      + schema.methods.init = function () {} // potentially breaking

      Schema.interpretAsType(path, obj)

      Converts type arguments into Mongoose Types.

      show code
      Schema.interpretAsType = function (path, obj) {
      +  if (obj.constructor.name != 'Object')
      +    obj = { type: obj };
      +
      +  // Get the type making sure to allow keys named "type"
      +  // and default to mixed if not specified.
      +  // { type: { type: String, default: 'freshcut' } }
      +  var type = obj.type && !obj.type.type
      +    ? obj.type
      +    : {};
      +
      +  if ('Object' == type.constructor.name || 'mixed' == type) {
      +    return new Types.Mixed(path, obj);
      +  }
      +
      +  if (Array.isArray(type) || Array == type || 'array' == type) {
      +    // if it was specified through { type } look for `cast`
      +    var cast = (Array == type || 'array' == type)
      +      ? obj.cast
      +      : type[0];
      +
      +    if (cast instanceof Schema) {
      +      return new Types.DocumentArray(path, cast, obj);
      +    }
      +
      +    if ('string' == typeof cast) {
      +      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
      +    } else if (cast && (!cast.type || cast.type.type)
      +                    && 'Object' == cast.constructor.name
      +                    && Object.keys(cast).length) {
      +      return new Types.DocumentArray(path, new Schema(cast), obj);
      +    }
      +
      +    return new Types.Array(path, cast || Types.Mixed, obj);
      +  }
      +
      +  var name = 'string' == typeof type
      +    ? type
      +    : type.name;
      +
      +  if (name) {
      +    name = name.charAt(0).toUpperCase() + name.substring(1);
      +  }
      +
      +  if (undefined == Types[name]) {
      +    throw new TypeError('Undefined type at `' + path +
      +        '`
      +  Did you try nesting Schemas? ' +
      +        'You can only nest using refs or arrays.');
      +  }
      +
      +  return new Types[name](path, obj);
      +};

      Parameters:


      Schema.Types

      The various Mongoose Schema Types.

      show code
      Schema.Types = require('./schema/index');

      Example:

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var ObjectId = mongoose.Schema.Types.ObjectId;
      + +

      Types:

      + +
        +
      • String
      • +
      • Number
      • +
      • Boolean | Bool
      • +
      • Array
      • +
      • Buffer
      • +
      • Date
      • +
      • ObjectId | Oid
      • +
      • Mixed
      • +
      + +

      Using this exposed access to the Mixed SchemaType, we can use them in our schema.

      + +
      var Mixed = mongoose.Schema.Types.Mixed;
      +new mongoose.Schema({ _user: Mixed })

      Schema#tree

      Schema as a tree

      + +

      Example:

      + +
      {
      +    '_id'     : ObjectId
      +  , 'nested'  : {
      +        'key' : String
      +    }
      +}

      Schema#paths

      Schema as flat paths

      + +

      Example:

      + +
      {
      +    '_id'        : SchemaType,
      +  , 'nested.key' : SchemaType,
      +}

    • schemadefault.js

      exports#system.profile

      Default model for querying the system.profiles collection.


    • schematype.js

      SchemaType(path, [options], [instance])

      SchemaType constructor

      show code
      function SchemaType (path, options, instance) {
      +  this.path = path;
      +  this.instance = instance;
      +  this.validators = [];
      +  this.setters = [];
      +  this.getters = [];
      +  this.options = options;
      +  this._index = null;
      +  this.selected;
      +
      +  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
      +    // { unique: true, index: true }
      +    if ('index' == i && this._index) continue;
      +
      +    var opts = Array.isArray(options[i])
      +      ? options[i]
      +      : [options[i]];
      +
      +    this[i].apply(this, opts);
      +  }
      +};

      Parameters:


      SchemaType#default(val)

      Sets a default value for this SchemaType.

      show code
      SchemaType.prototype.default = function (val) {
      +  if (1 === arguments.length) {
      +    this.defaultValue = typeof val === 'function'
      +      ? val
      +      : this.cast(val);
      +    return this;
      +  } else if (arguments.length > 1) {
      +    this.defaultValue = utils.args(arguments);
      +  }
      +  return this.defaultValue;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var schema = new Schema({ n: { type: Number, default: 10 })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.n) // 10
      + +

      Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

      + +

      Example:

      + +
      // values are cast:
      +var schema = new Schema({ aNumber: Number, default: "4.815162342" })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.aNumber) // 4.815162342
      +
      +// default unique objects for Mixed types:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default(function () {
      +  return {};
      +});
      +
      +// if we don't use a function to return object literals for Mixed defaults,
      +// each document will receive a reference to the same object literal creating
      +// a "shared" object instance:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default({});
      +var M = db.model('M', schema);
      +var m1 = new M;
      +m1.mixed.added = 1;
      +console.log(m1.mixed); // { added: 1 }
      +var m2 = new M;
      +console.log(m2.mixed); // { added: 1 }

      SchemaType#index(options)

      Declares the index options for this schematype.

      show code
      SchemaType.prototype.index = function (options) {
      +  this._index = options;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var s = new Schema({ name: { type: String, index: true })
      +var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
      +Schema.path('my.path').index(true);
      +Schema.path('my.path').index({ expires: 60 });
      +Schema.path('my.path').index({ unique: true, sparse: true });
      + +

      NOTE:

      + +

      Indexes are created in the background by default. Specify background: false to override.

      + +

      Direction doesn't matter for single key indexes


      SchemaType#unique(bool)

      Declares an unique index.

      show code
      SchemaType.prototype.unique = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.unique = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, unique: true })
      +Schema.path('name').index({ unique: true });

      SchemaType#sparse(bool)

      Declares a sparse index.

      show code
      SchemaType.prototype.sparse = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.sparse = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, sparse: true })
      +Schema.path('name').index({ sparse: true });

      SchemaType#expires(when)

      Declares a TTL index (rounded to the nearest second) for Date types only.

      show code
      SchemaType.prototype.expires = function (when) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.expires = when;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
      This index type is only compatible with Date types.

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({..}, { expires: 60*60*24 });
      + +

      expires utilizes the ms module from guille allowing us to use a friendlier syntax:

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({..}, { expires: '24h' });
      +
      +// expire in 1.5 hours
      +new Schema({..}, { expires: '1.5h' });
      +
      +// expire in 7 days
      +var schema = new Schema({..});
      +schema.expires('7d');

      SchemaType#set(fn)

      Adds a setter to this schematype.

      show code
      SchemaType.prototype.set = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A setter must be a function.');
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function capitalize (val) {
      +  if ('string' != typeof val) val = '';
      +  return val.charAt(0).toUpperCase() + val.substring(1);
      +}
      +
      +// defining within the schema
      +var s = new Schema({ name: { type: String, set: capitalize }})
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ name: String })
      +s.path('name').set(capitalize)
      + +

      Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

      + +

      You can set up email lower case normalization easily via a Mongoose setter.

      + +
      function toLower (v) {
      +  return v.toLowerCase();
      +}
      +
      +var UserSchema = new Schema({
      +  email: { type: String, set: toLower }
      +})
      +
      +var User = db.model('User', UserSchema)
      +
      +var user = new User({email: 'AVENUE@Q.COM'})
      +console.log(user.email); // 'avenue@q.com'
      +
      +// or
      +var user = new User
      +user.email = 'Avenue@Q.com'
      +console.log(user.email) // 'avenue@q.com'
      +
      + +

      As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

      + +
      new Schema({ email: { type: String, lowercase: true }})

      SchemaType#get(fn)

      Adds a getter to this schematype.

      show code
      SchemaType.prototype.get = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A getter must be a function.');
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function dob (val) {
      +  if (!val) return val;
      +  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      +}
      +
      +// defining within the schema
      +var s = new Schema({ born: { type: Date, get: dob })
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ born: Date })
      +s.path('born').get(dob)
      + +

      Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

      + +

      Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

      + +
      function obfuscate (cc) {
      +  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
      +}
      +
      +var AccountSchema = new Schema({
      +  creditCardNumber: { type: String, get: obfuscate }
      +});
      +
      +var Account = db.model('Account', AccountSchema);
      +
      +Account.findById(id, function (err, found) {
      +  console.log(found.creditCardNumber); // '****-****-****-1234'
      +});

      SchemaType#validate(obj, [error])

      Adds validator(s) for this document path.

      show code
      SchemaType.prototype.validate = function (obj, error) {
      +  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
      +    this.validators.push([obj, error]);
      +    return this;
      +  }
      +
      +  var i = arguments.length
      +    , arg
      +
      +  while (i--) {
      +    arg = arguments[i];
      +    if (!(arg && 'Object' == arg.constructor.name)) {
      +      var msg = 'Invalid validator. Received (' + typeof arg + ') '
      +        + arg
      +        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
      +
      +      throw new Error(msg);
      +    }
      +    this.validate(arg.validator, arg.msg);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Validators must return Boolean. Returning false is interpreted as validation failure.

      + +

      Examples:

      + +
      function validator () { ... }
      +
      +var single = [validator, 'failed']
      +new Schema({ name: { type: String, validate: single }});
      +
      +var many = [
      +    { validator: validator, msg: 'uh oh' }
      +  , { validator: fn, msg: 'failed' }
      +]
      +new Schema({ name: { type: String, validate: many }});
      +
      +// or utilizing SchemaType methods directly:
      +
      +var schema = new Schema({ name: 'string' });
      +schema.path('name').validate(validator, 'validation failed');
      + +

      Asynchronous validation:

      + +

      Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

      + +
      schema.path('name').validate(function (value, respond) {
      +  doStuff(value, function () {
      +    ...
      +    respond(false); // validation failed
      +  })
      + }, 'my error type');
      + +

      Validation occurs pre('save') or whenever you manually execute document#validate.

      + +

      If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

      + +
      var conn = mongoose.createConnection(..);
      +conn.on('error', handleError);
      +
      +var Product = conn.model('Product', yourSchema);
      +var dvd = new Product(..);
      +dvd.save(); // emits error on the `conn` above
      + +

      If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

      + +
      // registering an error listener on the Model lets us handle errors more locally
      +Product.on('error', handleError);

      SchemaType#required(required)

      Adds a required validator to this schematype.

      show code
      SchemaType.prototype.required = function (required) {
      +  var self = this;
      +
      +  function __checkRequired (v) {
      +    // in here, `this` refers to the validating document.
      +    // no validation when this path wasn't selected in the query.
      +    if ('isSelected' in this &&
      +        !this.isSelected(self.path) &&
      +        !this.isModified(self.path)) return true;
      +    return self.checkRequired(v);
      +  }
      +
      +  if (false === required) {
      +    this.isRequired = false;
      +    this.validators = this.validators.filter(function (v) {
      +      return v[0].name !== '__checkRequired';
      +    });
      +  } else {
      +    this.isRequired = true;
      +    this.validators.push([__checkRequired, 'required']);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • required <Boolean> enable/disable the validator

      Returns:

      Example:

      + +
      var s = new Schema({ born: { type: Date, required: true })
      +// or
      +Schema.path('name').required(true);

      SchemaType#getDefault(scope, init)

      Gets the default value

      show code
      SchemaType.prototype.getDefault = function (scope, init) {
      +  var ret = 'function' === typeof this.defaultValue
      +    ? this.defaultValue.call(scope)
      +    : this.defaultValue;
      +
      +  if (null !== ret && undefined !== ret) {
      +    return this.cast(ret, scope, init);
      +  } else {
      +    return ret;
      +  }
      +};

      Parameters:

      • scope <Object> the scope which callback are executed
      • init <Boolean>

      SchemaType#applySetters(value, scope, init)

      Applies setters

      show code
      SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  var v = value
      +    , setters = this.setters
      +    , len = setters.length
      +
      +  if (!len) {
      +    if (null === v || undefined === v) return v;
      +    return init
      +      ? v // if we just initialized we dont recast
      +      : this.cast(v, scope, init, priorVal)
      +  }
      +
      +  while (len--) {
      +    v = setters[len].call(scope, v, this);
      +  }
      +
      +  if (null === v || undefined === v) return v;
      +
      +  // do not cast until all setters are applied #665
      +  v = this.cast(v, scope, init, priorVal);
      +
      +  return v;
      +};

      Parameters:


      SchemaType#applyGetters(value, scope)

      Applies getters to a value

      show code
      SchemaType.prototype.applyGetters = function (value, scope) {
      +  if (SchemaType._isRef(this, value, true)) return value;
      +
      +  var v = value
      +    , getters = this.getters
      +    , len = getters.length;
      +
      +  if (!len) {
      +    return v;
      +  }
      +
      +  while (len--) {
      +    v = getters[len].call(scope, v, this);
      +  }
      +
      +  return v;
      +};

      Parameters:


      SchemaType#select(val)

      Sets default select() behavior for this path.

      show code
      SchemaType.prototype.select = function select (val) {
      +  this.selected = !! val;
      +}

      Parameters:

      Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

      + +

      Example:

      + +
      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      +T.find(..); // field x will always be selected ..
      +// .. unless overridden;
      +T.find().select('-x').exec(callback);

      SchemaType#doValidate(value, callback, scope)

      Performs a validation of value using the validators declared for this SchemaType.

      show code
      SchemaType.prototype.doValidate = function (value, fn, scope) {
      +  var err = false
      +    , path = this.path
      +    , count = this.validators.length;
      +
      +  if (!count) return fn(null);
      +
      +  function validate (val, msg) {
      +    if (err) return;
      +    if (val === undefined || val) {
      +      --count || fn(null);
      +    } else {
      +      fn(err = new ValidatorError(path, msg));
      +    }
      +  }
      +
      +  this.validators.forEach(function (v) {
      +    var validator = v[0]
      +      , message   = v[1];
      +
      +    if (validator instanceof RegExp) {
      +      validate(validator.test(value), message);
      +    } else if ('function' === typeof validator) {
      +      if (2 === validator.length) {
      +        validator.call(scope, value, function (val) {
      +          validate(val, message);
      +        });
      +      } else {
      +        validate(validator.call(scope, value), message);
      +      }
      +    }
      +  });
      +};

      Parameters:


      SchemaType._isRef(self, value, init)

      Determines if value is a valid Reference.

      show code
      SchemaType._isRef = function (self, value, init) {
      +  if (init && self.options && self.options.ref) {
      +    if (null == value) return true;
      +    if (value._id && value._id.constructor.name === self.instance) return true;
      +  }
      +
      +  return false;
      +}

      Parameters:

      Returns:


    • types/array.js

      MongooseArray(values, path, doc)

      Mongoose Array constructor.

      show code
      function MongooseArray (values, path, doc) {
      +  var arr = [];
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:

      NOTE:

      + +

      Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


      MongooseArray#_cast(value)

      Casts a member based on this arrays schema.

      show code
      MongooseArray.prototype._cast = function (value) {
      +  var cast = this._schema.caster.cast
      +    , doc = this._parent;
      +
      +  return cast.call(null, value, doc);
      +};

      Parameters:

      Returns:

      • <value> the casted value

      MongooseArray#_markModified(embeddedDoc, embeddedPath)

      Marks this array as modified.

      show code
      MongooseArray.prototype._markModified = function (elem, embeddedPath) {
      +  var parent = this._parent
      +    , dirtyPath;
      +
      +  if (parent) {
      +    dirtyPath = this._path;
      +
      +    if (arguments.length) {
      +      if (null != embeddedPath) {
      +        // an embedded doc bubbled up the change
      +        dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
      +      } else {
      +        // directly set an index
      +        dirtyPath = dirtyPath + '.' + elem;
      +      }
      +
      +    }
      +    parent.markModified(dirtyPath);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
      • embeddedPath <String> the path which changed in the embeddedDoc

      If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


      MongooseArray#_registerAtomic(op, val)

      Register an atomic operation with the parent.

      show code
      MongooseArray.prototype._registerAtomic = function (op, val) {
      +  if ('$set' == op) {
      +    // $set takes precedence over all other ops.
      +    // mark entire array modified.
      +    this._atomics = { $set: val };
      +    return this;
      +  }
      +
      +  var atomics = this._atomics;
      +
      +  // reset pop/shift after save
      +  if ('$pop' == op && !('$pop' in atomics)) {
      +    var self = this;
      +    this._parent.once('save', function () {
      +      self._popped = self._shifted = null;
      +    });
      +  }
      +
      +  // check for impossible $atomic combos (Mongo denies more than one
      +  // $atomic op on a single path
      +  if (this._atomics.$set ||
      +      Object.keys(atomics).length && !(op in atomics)) {
      +    // a different op was previously registered.
      +    // save the entire thing.
      +    this._atomics = { $set: this };
      +    return this;
      +  }
      +
      +  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
      +    atomics[op] || (atomics[op] = []);
      +    atomics[op] = atomics[op].concat(val);
      +  } else if (op === '$pullDocs') {
      +    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
      +      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
      +    selector['$in'] = selector['$in'].concat(val);
      +  } else {
      +    atomics[op] = val;
      +  }
      +
      +  return this;
      +};

      Parameters:


      MongooseArray#hasAtomics()

      Returns the number of pending atomic operations to send to the db for this array.

      show code
      MongooseArray.prototype.hasAtomics = function hasAtomics () {
      +  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
      +    return 0;
      +  }
      +
      +  return Object.keys(this._atomics).length;
      +}

      Returns:


      MongooseArray#push([args...])

      Wraps Array#push with proper change tracking.

      show code
      MongooseArray.prototype.push = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +
      +  // $pushAll might be fibbed (could be $push). But it makes it easier to
      +  // handle what could have been $push, $pushAll combos
      +  this._registerAtomic('$pushAll', values);
      +  this._markModified();
      +  return ret;
      +};

      Parameters:


      MongooseArray#nonAtomicPush([args...])

      Pushes items to the array non-atomically.

      show code
      MongooseArray.prototype.nonAtomicPush = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +};

      Parameters:

      • [args...] <any>

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$pop()

      Pops the array atomically at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var popped = doc.array.$pop();
      + console.log(popped); // 3
      + console.log(doc.array); // [1,2]
      +
      + // no affect
      + popped = doc.array.$pop();
      + console.log(doc.array); // [1,2]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $pop works again
      +   popped = doc.array.$pop();
      +   console.log(popped); // 2
      +   console.log(doc.array); // [1]
      + })

      MongooseArray#pop()

      Wraps Array#pop with proper change tracking.

      show code
      MongooseArray.prototype.pop = function () {
      +  var ret = [].pop.call(this);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +};

      Note:

      + +

      marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$shift()

      Atomically shifts the array at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var shifted = doc.array.$shift();
      + console.log(shifted); // 1
      + console.log(doc.array); // [2,3]
      +
      + // no affect
      + shifted = doc.array.$shift();
      + console.log(doc.array); // [2,3]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $shift works again
      +   shifted = doc.array.$shift();
      +   console.log(shifted ); // 2
      +   console.log(doc.array); // [3]
      + })

      MongooseArray#shift()

      Wraps Array#shift with proper change tracking.

      show code
      MongooseArray.prototype.shift = function () {
      +  var ret = [].shift.call(this);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +};

      Example:

      + +
      doc.array = [2,3];
      +var res = doc.array.shift();
      +console.log(res) // 2
      +console.log(doc.array) // [3]
      + +

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#remove([args...])

      Removes items from an array atomically

      show code
      MongooseArray.prototype.remove = function () {
      +  var args = [].map.call(arguments, this._cast, this);
      +  if (args.length == 1)
      +    this.pull(args[0]);
      +  else
      +    this.pull.apply(this, args);
      +  return args;
      +};

      Parameters:

      • [args...] <Object> values to remove

      Examples:

      + +
      doc.array.remove(ObjectId)
      +doc.array.remove('tag 1', 'tag 2')

      MongooseArray#pull([args...])

      Pulls items from the array atomically.

      show code
      MongooseArray.prototype.pull = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , cur = this._parent.get(this._path)
      +    , i = cur.length
      +    , mem;
      +
      +  while (i--) {
      +    mem = cur[i];
      +    if (mem instanceof EmbeddedDocument) {
      +      if (values.some(function (v) { return v.equals(mem); } )) {
      +        [].splice.call(cur, i, 1);
      +      }
      +    } else if (~cur.indexOf.call(values, mem)) {
      +      [].splice.call(cur, i, 1);
      +    }
      +  }
      +
      +  if (values[0] instanceof EmbeddedDocument) {
      +    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
      +  } else {
      +    this._registerAtomic('$pullAll', values);
      +  }
      +
      +  this._markModified();
      +  return this;
      +};

      Parameters:

      • [args...] <any>

      MongooseArray#splice()

      Wraps Array#splice with proper change tracking and casting.

      show code
      MongooseArray.prototype.splice = function splice () {
      +  var ret, vals, i;
      +
      +  if (arguments.length) {
      +    vals = [];
      +    for (i = 0; i < arguments.length; ++i) {
      +      vals[i] = i < 2
      +        ? arguments[i]
      +        : this._cast(arguments[i]);
      +    }
      +    ret = [].splice.apply(this, vals);
      +    this._registerAtomic('$set', this);
      +    this._markModified();
      +  }
      +
      +  return ret;
      +}

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#unshift()

      Wraps Array#unshift with proper change tracking.

      show code
      MongooseArray.prototype.unshift = function () {
      +  var values = [].map.call(arguments, this._cast, this);
      +  [].unshift.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return this.length;
      +};

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#sort()

      Wraps Array#sort with proper change tracking.

      show code
      MongooseArray.prototype.sort = function () {
      +  var ret = [].sort.apply(this, arguments);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +}

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#addToSet([args...])

      Adds values to the array if not already present.

      show code
      MongooseArray.prototype.addToSet = function addToSet () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , added = []
      +    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
      +             values[0] instanceof Date ? 'date' :
      +             '';
      +
      +  values.forEach(function (v) {
      +    var found;
      +    switch (type) {
      +      case 'doc':
      +        found = this.some(function(doc){ return doc.equals(v) });
      +        break;
      +      case 'date':
      +        var val = +v;
      +        found = this.some(function(d){ return +d === val });
      +        break;
      +      default:
      +        found = ~this.indexOf(v);
      +    }
      +
      +    if (!found) {
      +      [].push.call(this, v);
      +      this._registerAtomic('$addToSet', v);
      +      this._markModified();
      +      [].push.call(added, v);
      +    }
      +  }, this);
      +
      +  return added;
      +};

      Parameters:

      • [args...] <any>

      Returns:

      • <Array> the values that were added

      Example:

      + +
      console.log(doc.array) // [2,3,4]
      +var added = doc.array.addToSet(4,5);
      +console.log(doc.array) // [2,3,4,5]
      +console.log(added)     // [5]

      MongooseArray#set()

      Sets the casted val at index i and marks the array modified.

      show code
      MongooseArray.prototype.set = function set (i, val) {
      +  this[i] = this._cast(val);
      +  this._markModified(i);
      +  return this;
      +}

      Returns:

      Example:

      + +
      // given documents based on the following
      +var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
      +
      +var doc = new Doc({ array: [2,3,4] })
      +
      +console.log(doc.array) // [2,3,4]
      +
      +doc.array.set(1,"5");
      +console.log(doc.array); // [2,5,4] // properly cast to number
      +doc.save() // the change is saved
      +
      +// VS not using array#set
      +doc.array[1] = "5";
      +console.log(doc.array); // [2,"5",4] // no casting
      +doc.save() // change is not saved

      MongooseArray#toObject(options)

      Returns a native js Array.

      show code
      MongooseArray.prototype.toObject = function (options) {
      +  if (options && options.depopulate && this[0] instanceof Document) {
      +    return this.map(function (doc) {
      +      return doc._id;
      +    });
      +  }
      +
      +  // return this.slice()?
      +  return this.map(function (doc) {
      +    return doc;
      +  });
      +};

      Parameters:

      Returns:


      MongooseArray#inspect()

      Helper for console.log

      show code
      MongooseArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    return ' ' + doc;
      +  }) + ' ]';
      +};

      MongooseArray#indexOf(obj)

      Return the index of obj or -1 if not found.

      show code
      MongooseArray.prototype.indexOf = function indexOf (obj) {
      +  if (obj instanceof ObjectId) obj = obj.toString();
      +  for (var i = 0, len = this.length; i < len; ++i) {
      +    if (obj == this[i])
      +      return i;
      +  }
      +  return -1;
      +};

      Parameters:

      • obj <Object> the item to look for

      Returns:


      MongooseArray#_parent

      Parent owner document


      MongooseArray#_atomics

      Stores a queue of atomic operations to perform


    • types/buffer.js

      MongooseBuffer(value, encode, offset)

      Mongoose Buffer constructor.

      show code
      function MongooseBuffer (value, encode, offset) {
      +  var length = arguments.length;
      +  var val;
      +
      +  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
      +    val = 0;
      +  } else {
      +    val = value;
      +  }
      +
      +  var encoding;
      +  var path;
      +  var doc;
      +
      +  if (Array.isArray(encode)) {
      +    // internal casting
      +    path = encode[0];
      +    doc = encode[1];
      +  } else {
      +    encoding = encode;
      +  }
      +
      +  var buf = new Buffer(val, encoding, offset);
      +  buf.__proto__ = MongooseBuffer.prototype;
      +
      +  // make sure these internal props don't show up in Object.keys()
      +  Object.defineProperties(buf, {
      +      validators: { value: [] }
      +    , _path: { value: path }
      +    , _parent: { value: doc }
      +  });
      +
      +  if (doc && "string" === typeof path) {
      +    Object.defineProperty(buf, '_schema', {
      +        value: doc.schema.path(path)
      +    });
      +  }
      +
      +  return buf;
      +};

      Parameters:

      Inherits:

      Values always have to be passed to the constructor to initialize.


      MongooseBuffer#_markModified()

      Marks this buffer as modified.

      show code
      MongooseBuffer.prototype._markModified = function () {
      +  var parent = this._parent;
      +
      +  if (parent) {
      +    parent.markModified(this._path);
      +  }
      +  return this;
      +};

      MongooseBuffer#write()

      Writes the buffer.

      show code
      MongooseBuffer.prototype.write = function () {
      +  var written = Buffer.prototype.write.apply(this, arguments);
      +
      +  if (written > 0) {
      +    this._markModified();
      +  }
      +
      +  return written;
      +};

      MongooseBuffer#copy(target)

      Copies the buffer.

      show code
      MongooseBuffer.prototype.copy = function (target) {
      +  var ret = Buffer.prototype.copy.apply(this, arguments);
      +
      +  if (target instanceof MongooseBuffer) {
      +    target._markModified();
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Note:

      + +

      Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


      MongooseBuffer#toObject([subtype])

      Converts this buffer to its Binary type representation.

      show code
      MongooseBuffer.prototype.toObject = function (subtype) {
      +  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
      +  return new Binary(this, subtype);
      +};

      Parameters:

      • [subtype] <Hex>

      Returns:

      SubTypes:

      + +
        +
      • 0x00: Binary/Generic
      • +
      • 0x01: Function
      • +
      • 0x02: Binary (Deprecated, 0x00 is new default)
      • +
      • 0x03: UUID
      • +
      • 0x04: MD5
      • +
      • 0x80: User Defined
      • +

      MongooseBuffer#_parent

      Parent owner document


    • types/documentarray.js

      MongooseDocumentArray(values, path, doc)

      DocumentArray constructor

      show code
      function MongooseDocumentArray (values, path, doc) {
      +  var arr = [];
      +
      +  // Values always have to be passed to the constructor to initialize, since
      +  // otherwise MongooseArray#push will mark the array as modified to the parent.
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseDocumentArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +    doc.on('save', arr.notify('save'));
      +    doc.on('isNew', arr.notify('isNew'));
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:


      MongooseDocumentArray#_cast()

      Overrides MongooseArray#cast

      show code
      MongooseDocumentArray.prototype._cast = function (value) {
      +  if (value instanceof this._schema.casterConstructor)
      +    return value;
      +
      +  return new this._schema.casterConstructor(value, this);
      +};

      MongooseDocumentArray#id(id)

      Searches array items for the first document with a matching id.

      show code
      MongooseDocumentArray.prototype.id = function (id) {
      +  var casted
      +    , _id;
      +
      +  try {
      +    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
      +  } catch (e) {
      +    casted = null;
      +  }
      +
      +  for (var i = 0, l = this.length; i < l; i++) {
      +    _id = this[i].get('_id');
      +    if (!(_id instanceof ObjectId)) {
      +      if (String(id) == _id)
      +        return this[i];
      +    } else {
      +      if (casted == _id)
      +        return this[i];
      +    }
      +  }
      +
      +  return null;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var embeddedDoc = m.array.id(some_id);

      MongooseDocumentArray#toObject()

      Returns a native js Array of plain js objects

      show code
      MongooseDocumentArray.prototype.toObject = function () {
      +  return this.map(function (doc) {
      +    return doc && doc.toObject() || null;
      +  });
      +};

      Returns:

      NOTE:

      + +

      Each sub-document is converted to a plain object by calling its #toObject method.


      MongooseDocumentArray#inspect()

      Helper for console.log

      show code
      MongooseDocumentArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    if (doc) {
      +      return doc.inspect
      +        ? doc.inspect()
      +        : util.inspect(doc)
      +    }
      +    return 'null'
      +  }).join('
      +') + ']';
      +};

      MongooseDocumentArray#create(obj)

      Creates a subdocument casted to this schema.

      show code
      MongooseDocumentArray.prototype.create = function (obj) {
      +  return new this._schema.casterConstructor(obj);
      +}

      Parameters:

      • obj <Object> the value to cast to this arrays SubDocument schema

      This is the same subdocument constructor used for casting.


      MongooseDocumentArray#notify(event)

      Creates a fn that notifies all child docs of event.

      show code
      MongooseDocumentArray.prototype.notify = function notify (event) {
      +  var self = this;
      +  return function notify (val) {
      +    var i = self.length;
      +    while (i--) {
      +      if (!self[i]) continue;
      +      self[i].emit(event, val);
      +    }
      +  }
      +}

      Parameters:

      Returns:


    • types/embedded.js

      EmbeddedDocument(obj, parentArr, skipId)

      EmbeddedDocument constructor.

      show code
      function EmbeddedDocument (obj, parentArr, skipId, fields) {
      +  if (parentArr) {
      +    this.__parentArray = parentArr;
      +    this.__parent = parentArr._parent;
      +  } else {
      +    this.__parentArray = undefined;
      +    this.__parent = undefined;
      +  }
      +
      +  Document.call(this, obj, fields, skipId);
      +
      +  var self = this;
      +  this.on('isNew', function (val) {
      +    self.isNew = val;
      +  });
      +};

      Parameters:

      Inherits:


      EmbeddedDocument#markModified(path)

      Marks the embedded doc modified.

      show code
      EmbeddedDocument.prototype.markModified = function (path) {
      +  if (!this.__parentArray) return;
      +
      +  this._activePaths.modify(path);
      +
      +  if (this.isNew) {
      +    // Mark the WHOLE parent array as modified
      +    // if this is a new document (i.e., we are initializing
      +    // a document),
      +    this.__parentArray._markModified();
      +  } else
      +    this.__parentArray._markModified(this, path);
      +};

      Parameters:

      • path <String> the path which changed

      Example:

      + +
      var doc = blogpost.comments.id(hexstring);
      +doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');

      EmbeddedDocument#save([fn])

      Used as a stub for hooks.js

      show code
      EmbeddedDocument.prototype.save = function(fn) {
      +  if (fn)
      +    fn(null);
      +  return this;
      +};

      Parameters:

      Returns:

      NOTE:

      + +

      This is a no-op. Does not actually save the doc to the db.


      EmbeddedDocument#remove([fn])

      Removes the subdocument from its parent array.

      show code
      EmbeddedDocument.prototype.remove = function (fn) {
      +  if (!this.__parentArray) return this;
      +
      +  var _id;
      +  if (!this.willRemove) {
      +    _id = this._doc._id;
      +    if (!_id) {
      +      throw new Error('For your own good, Mongoose does not know ' + 
      +                      'how to remove an EmbeddedDocument that has no _id');
      +    }
      +    this.__parentArray.pull({ _id: _id });
      +    this.willRemove = true;
      +  }
      +
      +  if (fn)
      +    fn(null);
      +
      +  return this;
      +};

      Parameters:


      EmbeddedDocument#update()

      Override #update method of parent documents.

      show code
      EmbeddedDocument.prototype.update = function () {
      +  throw new Error('The #update method is not available on EmbeddedDocuments');
      +}

      EmbeddedDocument#inspect()

      Helper for console.log

      show code
      EmbeddedDocument.prototype.inspect = function () {
      +  return inspect(this.toObject());
      +};

      EmbeddedDocument#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
      +  if (!this.__parent) return false;
      +  var index = this.__parentArray.indexOf(this);
      +  var parentPath = this.__parentArray._path;
      +  var fullPath = [parentPath, index, path].join('.');
      +  this.__parent.invalidate(fullPath, err);
      +  if (first)
      +    this._validationError = ownerDocument(this)._validationError;
      +  return true;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> error which states the reason `path` was invalid

      Returns:


      EmbeddedDocument#ownerDocument()

      Returns the top level document of this sub-document.

      show code
      EmbeddedDocument.prototype.ownerDocument = function () {
      +  return ownerDocument(this);
      +}

      Returns:


      EmbeddedDocument#parent()

      Returns this sub-documents parent document.

      show code
      EmbeddedDocument.prototype.parent = function () {
      +  return this.__parent;
      +}

      EmbeddedDocument#parentArray()

      Returns this sub-documents parent array.

      show code
      EmbeddedDocument.prototype.parentArray = function () {
      +  return this.__parentArray;
      +}

    • types/objectid.js

      ObjectId()

      ObjectId type constructor

      Example

      + +
      var id = new mongoose.Types.ObjectId;

      ObjectId.fromString(str)

      Creates an ObjectId from str

      show code
      ObjectId.fromString;

      Parameters:

      Returns:


      ObjectId.toString(oid)

      Converts oid to a string.

      show code
      ObjectId.toString;

      Parameters:

      Returns:


    • utils.js

      exports.toCollectionName(name)

      Produces a collection name from model name.

      show code
      exports.toCollectionName = function (name) {
      +  if ('system.profile' === name) return name;
      +  if ('system.indexes' === name) return name;
      +  return pluralize(name.toLowerCase());
      +};

      Parameters:

      Returns:


      exports.pluralization

      Pluralization rules.

      show code
      exports.pluralization = [
      +  [/(m)an$/gi, '$1en'],
      +  [/(pe)rson$/gi, '$1ople'],
      +  [/(child)$/gi, '$1ren'],
      +  [/^(ox)$/gi, '$1en'],
      +  [/(ax|test)is$/gi, '$1es'],
      +  [/(octop|vir)us$/gi, '$1i'],
      +  [/(alias|status)$/gi, '$1es'],
      +  [/(bu)s$/gi, '$1ses'],
      +  [/(buffal|tomat|potat)o$/gi, '$1oes'],
      +  [/([ti])um$/gi, '$1a'],
      +  [/sis$/gi, 'ses'],
      +  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
      +  [/(hive)$/gi, '$1s'],
      +  [/([^aeiouy]|qu)y$/gi, '$1ies'],
      +  [/(x|ch|ss|sh)$/gi, '$1es'],
      +  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
      +  [/([m|l])ouse$/gi, '$1ice'],
      +  [/(quiz)$/gi, '$1zes'],
      +  [/s$/gi, 's'],
      +  [/$/gi, 's']
      +];
      +var rules = exports.pluralization;

      These rules are applied while processing the argument to toCollectionName.


      exports.uncountables

      Uncountable words.

      show code
      exports.uncountables = [
      +  'advice',
      +  'energy',
      +  'excretion',
      +  'digestion',
      +  'cooperation',
      +  'health',
      +  'justice',
      +  'labour',
      +  'machinery',
      +  'equipment',
      +  'information',
      +  'pollution',
      +  'sewage',
      +  'paper',
      +  'money',
      +  'species',
      +  'series',
      +  'rain',
      +  'rice',
      +  'fish',
      +  'sheep',
      +  'moose',
      +  'deer',
      +  'news',
      +  'expertise',
      +  'status',
      +  'media'
      +];
      +var uncountables = exports.uncountables;

      These words are applied while processing the argument to toCollectionName.


      exports.deepEqual(a, b)

      Determines if a and b are deep equal.

      show code
      exports.deepEqual = function deepEqual (a, b) {
      +  if (a === b) return true;
      +
      +  if (a instanceof Date && b instanceof Date)
      +    return a.getTime() === b.getTime();
      +
      +  if (a instanceof ObjectId && b instanceof ObjectId) {
      +    return a.toString() === b.toString();
      +  }
      +
      +  if (typeof a !== 'object' && typeof b !== 'object')
      +    return a == b;
      +
      +  if (a === null || b === null || a === undefined || b === undefined)
      +    return false
      +
      +  if (a.prototype !== b.prototype) return false;
      +
      +  // Handle MongooseNumbers
      +  if (a instanceof Number && b instanceof Number) {
      +    return a.valueOf() === b.valueOf();
      +  }
      +
      +  if (Buffer.isBuffer(a)) {
      +    if (!Buffer.isBuffer(b)) return false;
      +    if (a.length !== b.length) return false;
      +    for (var i = 0, len = a.length; i < len; ++i) {
      +      if (a[i] !== b[i]) return false;
      +    }
      +    return true;
      +  }
      +
      +  if (isMongooseObject(a)) a = a.toObject();
      +  if (isMongooseObject(b)) b = b.toObject();
      +
      +  try {
      +    var ka = Object.keys(a),
      +        kb = Object.keys(b),
      +        key, i;
      +  } catch (e) {//happens when one is a string literal and the other isn't
      +    return false;
      +  }
      +
      +  // having the same number of owned properties (keys incorporates
      +  // hasOwnProperty)
      +  if (ka.length != kb.length)
      +    return false;
      +
      +  //the same set of keys (although not necessarily the same order),
      +  ka.sort();
      +  kb.sort();
      +
      +  //~~~cheap key test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    if (ka[i] != kb[i])
      +      return false;
      +  }
      +
      +  //equivalent values for every corresponding key, and
      +  //~~~possibly expensive deep test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    key = ka[i];
      +    if (!deepEqual(a[key], b[key])) return false;
      +  }
      +
      +  return true;
      +};

      Parameters:

      • a <any> a value to compare to `b`
      • b <any> a value to compare to `a`

      Returns:

      Modified from node/lib/assert.js


      exports.clone(obj, options)

      Object clone with Mongoose natives support.

      show code
      exports.clone = function clone (obj, options) {
      +  if (obj === undefined || obj === null)
      +    return obj;
      +
      +  if (Array.isArray(obj))
      +    return cloneArray(obj, options);
      +
      +  if (isMongooseObject(obj)) {
      +    if (options && options.json && 'function' === typeof obj.toJSON) {
      +      return obj.toJSON(options);
      +    } else {
      +      return obj.toObject(options);
      +    }
      +  }
      +
      +  if ('Object' === obj.constructor.name)
      +    return cloneObject(obj, options);
      +
      +  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
      +    return new obj.constructor(+obj);
      +
      +  if ('RegExp' === obj.constructor.name)
      +    return new RegExp(obj.source);
      +
      +  if (obj instanceof ObjectId) {
      +    return new ObjectId(obj.id);
      +  }
      +
      +  if (obj.valueOf)
      +    return obj.valueOf();
      +};
      +var clone = exports.clone;

      Parameters:

      Returns:

      Creates a minimal data Object.
      It does not clone empty Arrays, empty Objects, and undefined values.
      This makes the data payload sent to MongoDB as minimal as possible.


      exports.options(defaults, options)

      Copies and merges options with defaults.

      show code
      exports.options = function (defaults, options) {
      +  var keys = Object.keys(defaults)
      +    , i = keys.length
      +    , k ;
      +
      +  options = options || {};
      +
      +  while (i--) {
      +    k = keys[i];
      +    if (!(k in options)) {
      +      options[k] = defaults[k];
      +    }
      +  }
      +
      +  return options;
      +};

      Parameters:

      Returns:


      exports.random()

      Generates a random string

      show code
      exports.random = function () {
      +  return Math.random().toString().substr(3);
      +};

      exports.merge(to, from)

      Merges from into to without overwriting existing properties.

      show code
      exports.merge = function merge (to, from) {
      +  var keys = Object.keys(from)
      +    , i = keys.length
      +    , key
      +
      +  while (i--) {
      +    key = keys[i];
      +    if ('undefined' === typeof to[key]) {
      +      to[key] = from[key];
      +    } else {
      +      merge(to[key], from[key]);
      +    }
      +  }
      +};

      Parameters:


      exports.args

      A faster Array.prototype.slice.call(arguments) alternative

      show code
      exports.args = sliced;

      exports.tick(callback)

      process.nextTick helper.

      show code
      exports.tick = function tick (callback) {
      +  if ('function' !== typeof callback) return;
      +  return function () {
      +    try {
      +      callback.apply(this, arguments);
      +    } catch (err) {
      +      // only nextTick on err to get out of
      +      // the event loop and avoid state corruption.
      +      process.nextTick(function () {
      +        throw err;
      +      });
      +    }
      +  }
      +}

      Parameters:

      Wraps callback in a try/catch + nextTick.

      + +

      node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


      exports.isMongooseObject(v)

      Returns if v is a mongoose object that has a toObject() method we can use.

      show code
      exports.isMongooseObject = function (v) {
      +  Document || (Document = require('./document'));
      +  MongooseArray || (MongooseArray = require('./types').Array);
      +  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
      +
      +  return v instanceof Document ||
      +         v instanceof MongooseArray ||
      +         v instanceof MongooseBuffer
      +}
      +var isMongooseObject = exports.isMongooseObject;

      Parameters:

      This is for compatibility with libs like Date.js which do foolish things to Natives.


      exports.expires(object)

      Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

      show code
      exports.expires = function expires (object) {
      +  if (!(object && 'Object' == object.constructor.name)) return;
      +  if (!('expires' in object)) return;
      +
      +  var when;
      +  if ('string' != typeof object.expires) {
      +    when = object.expires;
      +  } else {
      +    when = Math.round(ms(object.expires) / 1000);
      +  }
      +  object.expireAfterSeconds = when;
      +  delete object.expires;
      +}
      +
      +exports.readPref = function readPref (pref, tags) {
      +  if (Array.isArray(pref)) {
      +    tags = pref[1];
      +    pref = pref[0];
      +  }
      +
      +  switch (pref) {
      +    case 'p':
      +      pref = 'primary';
      +      break;
      +    case 'pp':
      +      pref = 'primaryPrefered';
      +      break;
      +    case 's':
      +      pref = 'secondary';
      +      break;
      +    case 'sp':
      +      pref = 'secondaryPrefered';
      +      break;
      +    case 'n':
      +      pref = 'nearest';
      +      break;
      +  }
      +
      +  return new ReadPref(pref, tags);
      +}

      Parameters:


    • virtualtype.js

      VirtualType()

      VirtualType constructor

      show code
      function VirtualType (options, name) {
      +  this.path = name;
      +  this.getters = [];
      +  this.setters = [];
      +  this.options = options || {};
      +}

      This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

      + +

      Example:

      + +
      var fullname = schema.virtual('fullname');
      +fullname instanceof mongoose.VirtualType // true

      VirtualType#get(fn)

      Defines a getter.

      show code
      VirtualType.prototype.get = function (fn) {
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.get(function () {
      +  return this.name.first + ' ' + this.name.last;
      +});

      VirtualType#set(fn)

      Defines a setter.

      show code
      VirtualType.prototype.set = function (fn) {
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.set(function (v) {
      +  var parts = v.split(' ');
      +  this.name.first = parts[0];
      +  this.name.last = parts[1];
      +});

      VirtualType#applyGetters(value, scope)

      Applies getters to value using optional scope.

      show code
      VirtualType.prototype.applyGetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.getters.length - 1; l >= 0; l--) {
      +    v = this.getters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all getters

      VirtualType#applySetters(value, scope)

      Applies setters to value using optional scope.

      show code
      VirtualType.prototype.applySetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.setters.length - 1; l >= 0; l--) {
      +    v = this.setters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all setters

    diff --git a/docs/3.3.x/docs/api.jade b/docs/3.3.x/docs/api.jade new file mode 100644 index 00000000000..58b6eb1891f --- /dev/null +++ b/docs/3.3.x/docs/api.jade @@ -0,0 +1,517 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose API v#{package.version} + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='/docs/css/default.css', rel='stylesheet', type='text/css') + style. + body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; + } + a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; + } + a:hover { + opacity: 0.8; + } + #wrap { + } + h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; + } + pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; + } + code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Monaco; + } + pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; + } + h3 { + padding: 20px 15px; + margin-left: -15px; + } + h3 code { + font-weight: normal; + } + hr { + height: 1px; + border: 0 none; + padding: 0; + margin: 60px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) + } + .doclinks hr { + margin: 10px 0; + } + li { + list-style: square; + } + #header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; + } + #header h1 { + margin-top: 0; + margin-bottom: 0; + } + #header h1 a { + text-decoration: none; + } + #header .mongoose { + font-size: 48px; + font-weight: 100; + color: #fff; + letter-spacing: -5px; + } + #links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + } + #links hr { + margin: 32px 0; + } + #content { + padding: 0; + margin: 0 0 30px 230px; + overflow-x: hidden; + } + #content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; + } + #content .controls:hover { + opacity: .9; + } + #content p { + word-wrap: break-word; + } + #content > ul { + margin: 0; + padding: 0; + } + .private { + display: none; + } + .section { + font-size: 15px; + } + .doclinks li.private a:before, + .doclinks .module.private a:before, + .doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; + } + #content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; + } + .module { + list-style: none; + padding: 30px 0 30px 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; + } + .module > * { + max-width: 700px; + } + .item:last-child { + margin-bottom: 90px; + } + .item:last-child > hr { + display: none; + } + .item h3 a { + color: #333; + text-decoration: none; + } + .property h3 span { + color: #444; + } + .description { + margin-top: 25px; + } + .sourcecode { + display: none; + } + .showcode { + font-size: 12px; + cursor: pointer; + display: none; + } + .load .showcode { + display: block; + } + .types a { + text-decoration: none; + } + @media only screen and (device-width: 768px) { + + } + @media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links hr { + display: none; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + .controls { display: none; } + } + body.api + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + hr + .doclinks + each item in docs + .file(class=item.hasPublic ? '' : 'private') + a.section(href='#' + item.title.replace(/[\.\/#]/g, '-'))= item.title + ul + each method in item.methods + if method.ctx && !method.ignore + li(class= method.isPrivate ? 'private' : '') + case method.ctx.type + when 'method' + id = method.ctx.constructor + '-' + method.ctx.name + when 'function' + id = method.ctx.name + default + id = '' + url = href(klass(item.title) + '_' + id) + a(href='#' + url)= method.ctx.name + each stat in item.statics + if stat.ctx && !stat.ignore + li(class= stat.isPrivate ? 'private' : '') + case stat.ctx.type + when 'method' + id = stat.ctx.receiver + '-' + stat.ctx.name + when 'property' + id = stat.ctx.receiver + '-' + stat.ctx.name + when 'function' + id = stat.ctx.name + url = href(klass(item.title) + '_' + id) + a(href='#' + url)= stat.ctx.name + each property in item.props + if property.ctx && !property.ignore + li(class= property.isPrivate ? 'private' : '') + construct = property.ctx.receiver || property.ctx.constructor + link = href(construct) + '-' + href(property.ctx.name) + url = href(klass(item.title) + '_' + link) + a(href='#' + url)= property.ctx.name + #content + .controls + label + input(type='checkbox') + | private + ul + each item in docs + li.module(class=item.hasPublic ? '' : 'private') + a(href=github + package.version + '/' + item.title, id=item.title.replace(/[\.\/#]/g, '-'))= item.title + each method in item.methods + div.item.method(class= method.isPrivate ? 'private' : 'public') + if method.ctx + case method.ctx.type + when 'method' + id = method.ctx.constructor + '-' + method.ctx.name + text = method.ctx.constructor + '#' + method.ctx.name + when 'function' + id = method.ctx.name + text = method.ctx.name + default + text = '' + url = href(klass(item.title) + '_' + text) + h3(id= url) + a(href= '#' + url) + = text + | ( + each tag, i in method.params + code= tag.name + if i+1 < method.params.length + | , + | ) + else + - // console.log('\nmissing method name', method); + h3 MISSING method name + != method.description.summary + if method.code + span.showcode show code + .sourcecode + != hl(method.code) + if method.params.length + .params + h4 Parameters: + ul + each tag in method.params + li + code= tag.name + if tag.types && tag.types.length + span.types + | < + each type, i in tag.types + != linktype(type) + if i+1 < tag.types.length + | , + | > + span= tag.description + if method.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in method.return.types + != linktype(type) + if i+1 < method.return.types.length + | , + | > + span= method.return.description + if method.inherits + .inherits + h4 Inherits: + ul + li + != method.inherits + if method.events && method.events.length + .events + h4 Events: + ul + each event in method.events + li + != event.string + if method.see.length + .see + h4 See: + ul.see + each see in method.see + li + url = see.url || see.local + a(href=url, title=see.title || see.local)= see.title || see.url || see.local + div.description + != method.description.body + hr(class= method.isPrivate ? 'private' : '') + each stat in item.statics + div.item.static(class= stat.isPrivate ? 'private' : 'public') + if stat.ctx + case stat.ctx.type + when 'method' + id = stat.ctx.receiver + '-' + stat.ctx.name + text = stat.ctx.receiver + '.' + stat.ctx.name + when 'property' + id = stat.ctx.receiver + '-' + stat.ctx.name + text = stat.ctx.receiver + '.' + stat.ctx.name + when 'function' + id = stat.ctx.name + text = stat.ctx.name + default + text = '' + url = href(klass(item.title) + '_' + id) + h3(id= url) + a(href= '#' + url) + = text + if 'property' != stat.ctx.type + | ( + each tag, i in stat.params + code= tag.name + if i+1 < stat.params.length + | , + | ) + else + - // console.log('\nmissing static name', stat); + h3 MISSING stat name + != stat.description.summary + if stat.code + span.showcode show code + .sourcecode + != hl(stat.code) + if stat.params.length + .params + h4 Parameters: + ul + each tag in stat.params + li + - if (!tag.name) + - // console.log(tag) + code= tag.name + if tag.types && tag.types.length + span.types + | < + each type, i in tag.types + != linktype(type) + if i+1 < tag.types.length + | , + | > + span= tag.description + if stat.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in stat.return.types + != linktype(type) + if i+1 < stat.return.types.length + | , + | > + span= stat.return.description + if stat.inherits + .inherits + h4 Inherits: + ul + li + != stat.inherits + if stat.see.length + .see + h4 See: + ul.see + each see in stat.see + li + url = see.url || see.local + a(href=url, title=see.title || see.local)= see.title || see.url || see.local + != stat.description.body + hr(class= stat.isPrivate ? 'private' : '') + each property in item.props + div.item.property(class= property.ignore || property.isPrivate ? 'private' : 'public') + construct = property.ctx.receiver || property.ctx.constructor + link = href(construct) + '-' + href(property.ctx.name) + url = href(klass(item.title) + '_' + link) + h3(id = url) + a(href= '#' + url) + = construct + '#' + span= property.ctx.name + != property.description.full + if property.return + .returns + h4 Returns: + ul + li + span.types + | < + each type, i in property.return.types + != linktype(type) + if i+1 < property.return.types.length + | , + | > + span= property.return.description + hr(class= property.isPrivate ? 'private' : '') + script. + document.body.className = 'load'; + include includes/keen + script(src="/docs/js/zepto.min.js") + script(src="/docs/js/cookies.min.js") + script. + $(".module").on("click", ".showcode", function (e) { + $(this).closest(".item").find(".sourcecode").first().toggle(); + }); + $("#content .controls input").on("click", function (e) { + $(".private").toggle() + var checked = $(this).prop('checked'); + Cookies.set('prv', checked); + }); + ;(function(){ + var checked = 'true' === Cookies.get('prv'); + if (checked) { + $("#content .controls input").prop('checked', 'checked'); + $(".private").show() + } + })() diff --git a/docs/3.3.x/docs/connections.html b/docs/3.3.x/docs/connections.html new file mode 100644 index 00000000000..056b76affcf --- /dev/null +++ b/docs/3.3.x/docs/connections.html @@ -0,0 +1,27 @@ +Mongoose Connecting to MongoDB v3.3.1Fork me on GitHub

    Connections

    We may connect to MongoDB by utilizing the mongoose.connect() method.

    mongoose.connect('mongodb://localhost/myapp');
    +

    This is the minimum needed to connect the myapp database running locally on the default port (27017). We may also specify several more parameters in the uri depending on your environment:

    mongoose.connect('mongodb://username:password@host:port/database');
    +

    Options

    The connect method also accepts an options object which will be passed on to the underlying driver.

    mongoose.connect(uri, options);
    +

    The following option keys are available:

    + +
     db      - passed to the connection db instance
    + server  - passed to the connection server instance(s)
    + replset - passed to the connection ReplSet instance
    + user    - username for authentication (if not specified in uri)
    + pass    - password for authentication (if not specified in uri)
    + +

    See the driver for more information about available options.

    + +

    Note: The server option auto_reconnect is defaulted to true.

    + +

    Note: The db option forceServerObjectId is set to false and cannot be overridden.

    ReplicaSet Connections

    The same method is used to connect to a replica set but instead of passing a single uri we pass a comma delimited list of uris.

    mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]);
    +

    NOTE: The database need only be specified in one of the uris.

    Multiple connections

    So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize mongoose.createConnection() which accepts all the arguments already discussed and returns a fresh connection for you.

    var conn = mongoose.createConnection('uri,uri,uri...', options);
    +

    Connection pools

    Each connection, whether created with mongoose.connect or mongoose.createConnection are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options:

    mongoose.createConnection(uri, { server: { poolSize: 10 }});
    +

    Next Up

    Now that we've covered connections, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

    diff --git a/docs/3.3.x/docs/connections.jade b/docs/3.3.x/docs/connections.jade new file mode 100644 index 00000000000..5e67abc8a4b --- /dev/null +++ b/docs/3.3.x/docs/connections.jade @@ -0,0 +1,65 @@ +extends layout + +block content + h2 Connections + :markdown + We may connect to MongoDB by utilizing the `mongoose.connect()` method. + + :js + mongoose.connect('mongodb://localhost/myapp'); + + :markdown + This is the minimum needed to connect the `myapp` database running locally on the default port (27017). We may also specify several more parameters in the `uri` depending on your environment: + + :js + mongoose.connect('mongodb://username:password@host:port/database'); + + h3 Options + :markdown + The `connect` method also accepts an `options` object which will be passed on to the underlying driver. + + :js + mongoose.connect(uri, options); + + :markdown + The following option keys are available: + + db - passed to the connection db instance + server - passed to the connection server instance(s) + replset - passed to the connection ReplSet instance + user - username for authentication (if not specified in uri) + pass - password for authentication (if not specified in uri) + + See the [driver](https://github.com/mongodb/node-mongodb-native) for more information about available options. + + _Note: The server option `auto_reconnect` is defaulted to true._ + + _Note: The db option `forceServerObjectId` is set to false and cannot be overridden._ + + h3 ReplicaSet Connections + :markdown + The same method is used to connect to a replica set but instead of passing a single `uri` we pass a comma delimited list of `uri`s. + + :js + mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]); + + :markdown + _NOTE: The `database` need only be specified in one of the `uri`s._ + + h3 Multiple connections + :markdown + So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize `mongoose.createConnection()` which accepts all the arguments already discussed and returns a fresh connection for you. + + :js + var conn = mongoose.createConnection('uri,uri,uri...', options); + + h3 Connection pools + :markdown + Each `connection`, whether created with `mongoose.connect` or `mongoose.createConnection` are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options: + + :js + mongoose.createConnection(uri, { server: { poolSize: 10 }}); + + h3#next Next Up + :markdown + Now that we've covered `connections`, let's take a look at how we can break pieces of our functionality out into reusable and shareable [plugins](/docs/plugins.html). diff --git a/docs/3.3.x/docs/contributing.html b/docs/3.3.x/docs/contributing.html new file mode 100644 index 00000000000..b7c60dc4438 --- /dev/null +++ b/docs/3.3.x/docs/contributing.html @@ -0,0 +1,9 @@ +Mongoose Contributing v3.3.1Fork me on GitHub

    Contributing

    Please read all about contributing here.

    diff --git a/docs/3.3.x/docs/contributing.jade b/docs/3.3.x/docs/contributing.jade new file mode 100644 index 00000000000..48d9a658aaf --- /dev/null +++ b/docs/3.3.x/docs/contributing.jade @@ -0,0 +1,8 @@ +extends layout + +block content + h2 Contributing + + :markdown + Please read all about contributing [here](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md). + diff --git a/docs/3.3.x/docs/css/default.css b/docs/3.3.x/docs/css/default.css new file mode 100644 index 00000000000..ccb22728ed3 --- /dev/null +++ b/docs/3.3.x/docs/css/default.css @@ -0,0 +1,135 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +pre code { + display: block; padding: 0.5em; + background: #F0F0F0; +} + +pre code, +pre .ruby .subst, +pre .tag .title, +pre .lisp .title, +pre .clojure .built_in, +pre .nginx .title { + color: black; +} + +pre .string, +pre .title, +pre .constant, +pre .parent, +pre .tag .value, +pre .rules .value, +pre .rules .value .number, +pre .preprocessor, +pre .ruby .symbol, +pre .ruby .symbol .string, +pre .ruby .symbol .keyword, +pre .ruby .symbol .keymethods, +pre .instancevar, +pre .aggregate, +pre .template_tag, +pre .django .variable, +pre .smalltalk .class, +pre .addition, +pre .flow, +pre .stream, +pre .bash .variable, +pre .apache .tag, +pre .apache .cbracket, +pre .tex .command, +pre .tex .special, +pre .erlang_repl .function_or_atom, +pre .markdown .header { + color: #800; +} + +pre .comment, +pre .annotation, +pre .template_comment, +pre .diff .header, +pre .chunk, +pre .markdown .blockquote { + color: #888; +} + +pre .number, +pre .date, +pre .regexp, +pre .literal, +pre .smalltalk .symbol, +pre .smalltalk .char, +pre .go .constant, +pre .change, +pre .markdown .bullet, +pre .markdown .link_url { + color: #080; +} + +pre .label, +pre .javadoc, +pre .ruby .string, +pre .decorator, +pre .filter .argument, +pre .localvars, +pre .array, +pre .attr_selector, +pre .important, +pre .pseudo, +pre .pi, +pre .doctype, +pre .deletion, +pre .envvar, +pre .shebang, +pre .apache .sqbracket, +pre .nginx .built_in, +pre .tex .formula, +pre .erlang_repl .reserved, +pre .input_number, +pre .markdown .link_label, +pre .vhdl .attribute, +pre .clojure .attribute { + color: #88F +} + +pre .keyword, +pre .id, +pre .phpdoc, +pre .title, +pre .built_in, +pre .aggregate, +pre .css .tag, +pre .javadoctag, +pre .phpdoc, +pre .yardoctag, +pre .smalltalk .class, +pre .winutils, +pre .bash .variable, +pre .apache .tag, +pre .go .typename, +pre .tex .command, +pre .markdown .strong, +pre .request, +pre .status { + font-weight: bold; +} + +pre .markdown .emphasis { + font-style: italic; +} + +pre .nginx .built_in { + font-weight: normal; +} + +pre .coffeescript .javascript, +pre .xml .css, +pre .xml .javascript, +pre .xml .vbscript, +pre .tex .formula { + opacity: 0.5; +} diff --git a/docs/3.3.x/docs/css/guide.css b/docs/3.3.x/docs/css/guide.css new file mode 100644 index 00000000000..b77ffe83b0c --- /dev/null +++ b/docs/3.3.x/docs/css/guide.css @@ -0,0 +1,326 @@ +html, body, #content { + height: 100%; +} +:target::before { + content: ">>> "; + color: #1371C9; + font-weight: bold; + font-size: 20px; +} +.module { + min-height: 100%; + box-sizing: border-box; + overflow-x: hidden; +} +body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; +} +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; +} +code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Monaco; + /*text-shadow: 1px 2px 2px #555;*/ +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +h2 { + margin-top: 0; +} +h2 a { + font-size: 12px; + position: relative; + bottom: 3px; + font-weight: normal; +} +h3 { padding-top: 35px; } +h3 code { + font-weight: normal; +} +hr { + display: none; + height: 1px; + border: 0 none; + padding: 0; + margin: 90px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) +} +.doclinks hr { + margin: 10px 0; +} +li { + list-style: square; +} +#header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +#header .mongoose { + font-size: 48px; + font-weight: 100; + color: #fff; + letter-spacing: -5px; +} +#links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; +} +#links .schematypes span { + display: none; +} +#content { + padding: 0; + margin: 0 0 0 230px; +} +#content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +#content .controls:hover { + opacity: .9; +} +#content p { + word-wrap: break-word; +} +#content > ul { + margin: 0; + padding: 0; +} +.private { + display: none; +} +.doclinks li.private a:before, +.doclinks .module.private a:before, +.doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; +} +#content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; +} +.module { + list-style: none; + padding: 30px 0 0 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; +} +.module > * { + max-width: 700px; +} +.item { + margin-bottom: 175px; +} +.item h3 a { + color: #333; + text-decoration: none; +} +.property h3 span { + color: #444; +} +.description { + margin-top: 25px; +} +.sourcecode { + display: none; +} +.showcode { + font-size: 12px; + cursor: pointer; + display: none; +} +.load .showcode { + display: block; +} +.types a { + text-decoration: none; +} +li.guide ul { + padding-left: 16px; +} + +ul.inthewild { + margin: 30px 0 0 -30px; + padding: 0; + width: 125%; + max-width: 125%; +} +ul.inthewild li { + display: inline-block; + list-style: none; +} +ul.inthewild img { + width: 200px; +} + +@media only screen and (device-width: 768px) { + ul.inthewild { + margin-left: 0px; + } +} + +@media only screen and (max-width: 480px) { + ul.inthewild { + margin-left: 0px; + } + ul.inthewild li { + margin: 5px; + border-width: 2px 2px 0 2px; + border-style: solid; + border-color: #eee; + } + ul.inthewild li img { + width: 140px; + } + h2 a { + white-space: nowrap; + } + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + html, body, #content { + height: auto; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + #links li.guide { + display: block; + width: 390px; + margin-bottom: 15px; + } + #links li.guide > a { + display: none; + } + #links li ul li { + width: 44%; + text-align: left; + } + #links li ul li ul li { + width: 95%; + } + #links .plugins, + #links .changelog { + display: none; + } + #links .schematypes span { + display: inline; + } + #links .double { + width: 332px; + } + #links .double > ul { + display: inline; + float: right; + } + #links .double > ul li { + width: 155px; + } +} diff --git a/docs/3.3.x/docs/css/style.css b/docs/3.3.x/docs/css/style.css new file mode 100644 index 00000000000..34fee99b3f7 --- /dev/null +++ b/docs/3.3.x/docs/css/style.css @@ -0,0 +1,225 @@ +body { + font-family: 'Open Sans', Helvetica, Arial, FreeSans; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; +} + +/* location.hash */ +:target::before { + content: ">>> "; + color: #1371C9; + font-weight: bold; + font-size: 20px; +} +/* ignore home page hash */ +#production:target::before { + content: ""; + font-size: inherit; +} + +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { + width: 600px; + margin: 0 auto; + position:relative; +} +li { + list-style: square; +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: #eee; + padding: 5px; + border-radius: 3px; +} +code { + color: #333; + font-size: 11px; + font-family: Monaco; +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +#header { + text-align: center; + padding-top: 40px; +} +#header, h2, h3, .tagline, .blurb { + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +h2 { + margin: 30px 0; +} +h2 a { + font-size: 11px; + position: relative; + bottom: 4px; +} +#header .mongoose { + font-size: 146px; + font-weight: 100; + text-indent: -23px; +} +.load #header .mongoose { + letter-spacing: -14px; +} +.tagline { + color: #333; + font-size: 25px; + text-shadow: 1px 1px #f8f8f8; + text-align: center; +} +.blurb { + text-align: center; + font-style: oblique; + font-size: 12px; + margin-bottom: 20px; +} +.tagline a, .blurb a { + text-decoration: none; + color: #800; +} +#links { + margin: 30px 10px 46px; + text-align: center; + position: relative; +} +#links ul { + margin: 0; + padding: 0; +} +#links li { + display: inline-block; + margin: 0 15px; + background-color: #FEFEFE; +} +#links a { + background: #444; + padding: 9px 0px; + border-radius: 3px; + color: white; + width: 180px; + display: inline-block; + text-decoration: none; + text-transform: lowercase; + text-shadow: 1px 1px 7px #222; +} +#production ul { + padding: 0; +} +#production li { + list-style: none; + overflow: hidden; + display: inline-block; + height: 114px; +} +#production img { + width: 180px; + margin: 10px; +} +#production img#mcds { + width: 134px; + margin: 10px 25px; +} +#production a { + -webkit-transition-property: opacity; + -moz-transition-property: opacity; + -o-transition-property: opacity; + transition-property: opacity; + -webkit-transition-duration: 0.25s; + -moz-transition-duration: 0.25s; + -o-transition-duration: 0.25s; + transition-duration: 0.25s; + opacity: 0.7; +} +#production a:hover { + opacity: 1.0; +} +#footer { + text-align: center; + font-size: 12px; + margin-bottom: 20px; +} +@media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header { + padding-top: 12px; + } + #header .mongoose { + text-align: center; + font-size: 65px; + font-weight: 100; + letter-spacing: -7px; + } + .load #header .mongoose { + letter-spacing: -7px; + } + .tagline { + text-align: center; + font-size: 14px; + } + .tagline a { + text-decoration: none; + } + .blurb { + font-size: 16px; + text-align: justify; + margin-top: 25px; + } + #links { + margin-bottom: 40px; + } + #links li { + padding: 8px 2px; + margin: 0 12px; + } + #links a { + background: #444; + padding: 7px 34px; + font-size: 15px; + } + #docs { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + #wrap { + width: auto; + padding: 0 5px; + } + #production li { + margin-bottom: 8px; + } + #production a { + opacity: 1; + } + #production img { + width: 175px; + } + .addyourown, .addyourown a { + width: 100%; + } +} diff --git a/docs/3.3.x/docs/documents.html b/docs/3.3.x/docs/documents.html new file mode 100644 index 00000000000..415588076cd --- /dev/null +++ b/docs/3.3.x/docs/documents.html @@ -0,0 +1,20 @@ +Mongoose Documents v3.3.1Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    +  if (err) return handleError(err);
    +  
    +  tank.size = 'large';
    +  tank.save(function (err) {
    +    if (err) return handleError(err);
    +    res.send(tank);
    +  });
    +});

    This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    +  if (err) return handleError(err);
    +  res.send(tank);
    +});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    diff --git a/docs/3.3.x/docs/documents.jade b/docs/3.3.x/docs/documents.jade new file mode 100644 index 00000000000..67134e821b3 --- /dev/null +++ b/docs/3.3.x/docs/documents.jade @@ -0,0 +1,42 @@ +extends layout + +block content + h2 Documents + :markdown + Mongoose [documents](./api.html#document-js) represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its [Model](./models.html). + h3 Retrieving + :markdown + There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on [querying](./queries.html) for detail. + h3 Updating + :markdown + There are a number of ways to update documents. We'll first look at a traditional approach using [findById](./api.html#model_Model-findById): + :js + Tank.findById(id, function (err, tank) { + if (err) return handleError(err); + + tank.size = 'large'; + tank.save(function (err) { + if (err) return handleError(err); + res.send(tank); + }); + }); + :markdown + This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling `save`). However, if we don't need the document returned in our application and merely want to update a property in the database directly, [Model#update](./api.html#model_Model-update) is right for us: + :js + Tank.update({ _id: id }, { $set: { size: 'large' }}, callback); + :markdown + If we do need the document returned in our application there is another, often [better](./api.html#model_Model-findByIdAndUpdate), option: + :js + Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) { + if (err) return handleError(err); + res.send(tank); + }); + :markdown + The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model-findByIdAndRemove) [several](./api.html#model_Model-findOneAndUpdate) [variations](./api.html#model_Model-findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. + h3 Validating + :markdown + Documents are validated before they are saved. Read the [api](./api.html#document_Document-validate) docs or the [validation](./validation.html) chapter for detail. + + h3#next Next Up + :markdown + Now that we've covered `Documents`, let's take a look at [Sub-documents](/docs/subdocs.html). diff --git a/docs/3.3.x/docs/faq.html b/docs/3.3.x/docs/faq.html new file mode 100644 index 00000000000..d00c66400f7 --- /dev/null +++ b/docs/3.3.x/docs/faq.html @@ -0,0 +1,31 @@ +Mongoose FAQ v3.3.1Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    +doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    +doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    +new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    +doc.user.remove();// ?
    +doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    + +

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    + +

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    +mongoose.connect(..);
    +mongoose.connection.on('error', handleError);
    +
    +// if connecting on a separate connection
    +var conn = mongoose.createConnection(..);
    +conn.on('error', handleError);
    +

    Something to add?

    + +

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    diff --git a/docs/3.3.x/docs/faq.jade b/docs/3.3.x/docs/faq.jade new file mode 100644 index 00000000000..07abc7ea928 --- /dev/null +++ b/docs/3.3.x/docs/faq.jade @@ -0,0 +1,63 @@ +extends layout + +block append style + style. + hr { + display: block; + margin: 30px 0; + } + +block content + h2 FAQ + :markdown + **Q**. Why don't my changes to arrays get saved when I update an element directly? + :js + doc.array[3] = 'changed'; + doc.save(); + :markdown + **A**. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving. + :js + doc.markModified('array'); + doc.save(); + hr + :markdown + **Q**. Why doesn't mongoose allow me to directly assign schemas to paths? + :js + var userSchema = new Schema({ name: String }); + new Schema({ user: userSchema }) + :markdown + **A**. Schemas have a one-to-one mapping with documents. Documents have `save` and `remove` methods along with their own `pre` and `post` hooks which would lead to code like the following: + :js + doc.user.save(); // ? + doc.user.remove();// ? + doc.save() + :markdown + We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling `save` on a sub-document is a no-op and exists only to support `pre` save hooks). In the future this is likely to be revisited. + hr + :markdown + **Q**. How can I enable debugging? + + **A**. Set the `debug` option to `true`: + :js + mongoose.set('debug', true) + hr + :markdown + **Q**. My `save()` callback never executes. What am I doing wrong? + + **A**. All `collection` actions (insert, remove, queries, etc) are queued until the `connection` opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection. + :js + // if connecting on the default mongoose connection + mongoose.connect(..); + mongoose.connection.on('error', handleError); + + // if connecting on a separate connection + var conn = mongoose.createConnection(..); + conn.on('error', handleError); + + hr + :markdown + **Something to add?** + + If you'd like to contribute to this page, please [visit it](https://github.com/learnboost/mongoose/tree/master/docs/faq.jade) on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request. + br + diff --git a/docs/3.3.x/docs/guide.html b/docs/3.3.x/docs/guide.html new file mode 100644 index 00000000000..1c526d64d10 --- /dev/null +++ b/docs/3.3.x/docs/guide.html @@ -0,0 +1,188 @@ +Mongoose Schemas v3.3.1Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

    If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    +  title:  String,
    +  author: String,
    +  body:   String,
    +  comments: [{ body: String, date: Date }],
    +  date: { type: Date, default: Date.now },
    +  hidden: Boolean,
    +  meta: {
    +    votes: Number,
    +    favs:  Number
    +  }
    +});

    If you want to add additional keys later, use the Schema#add method.

    +Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. +Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    +
    +animalSchema.methods.findSimilarTypes = function (cb) {
    +  return this.model('Animal').find({ type: this.type }, cb);
    +}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    +var dog = new Animal({ type: 'dog' });
    +
    +dog.findSimilarTypes(function (err, dogs) {
    +  console.log(dogs); // woof
    +});

    Statics

    +Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    +  this.find({ name: new RegExp(name, 'i') }, cb);
    +}
    +
    +var Animal = mongoose.model('Animal', animalSchema);
    +Animal.findByName('fido', function (err, animals) {
    +  console.log(animals);
    +});

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });
    +

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index. It is recommended this behavior be disabled in production by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false);
    +// or
    +new Schema({..}, { autoIndex: false });
    +

    See also the Model#ensureIndexes method for more details.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    +  name: {
    +    first: String,
    +    last: String
    +  }
    +});
    +
    +var Person = mongoose.model('Person', personSchema);
    +
    +var bad = new Person({
    +    name: { first: 'Walter', last: 'White' }
    +});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    +  return this.name.first + ' ' + this.name.last;
    +});

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full); // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    +  var split = name.split(' ');
    +  this.name.first = split[0];
    +  this.name.last = split[1];
    +});
    +
    +...
    +
    +mad.name.full = 'Breaking Bad';
    +console.log(mad.name.first); // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    +
    +// or
    +
    +var schema = new Schema({..});
    +schema.set(option, value);
    +

    Valid options:

    + +

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false });
    +var Clock = db.model('Clock', schema);
    +Clock.ensureIndexes(callback);
    +

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 });

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });
    +

    option: collection

    Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Set this option if you need a different name for your collection.

    var dataSchema = new Schema({..}, { collection: 'data' });
    +

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // '50341373e894ad16347efe01'
    +
    +// disabled id
    +var schema = new Schema({ name: String }, { id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // undefined
    +

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    + +

    Pass this option during schema construction to prevent documents from getting an auto _id created.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
    +
    +// disabled _id
    +var schema = new Schema({ name: String }, { _id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { name: 'mongodb.org' }
    +

    option: read

    Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

    var schema = new Schema({..}, { read: 'primary' });            // also aliased as 'p'
    +var schema = new Schema({..}, { read: 'primaryPreferred' });   // aliased as 'pp'
    +var schema = new Schema({..}, { read: 'secondary' });          // aliased as 's'
    +var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp'
    +var schema = new Schema({..}, { read: 'nearest' });            // aliased as 'n'
    +

    The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'.

    + +

    The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

    + +

    NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

    // pings the replset members periodically to track network latency
    +// now `nearest` works as intended
    +var options = { replset: { strategy: 'ping' }};
    +mongoose.connect(uri, options);
    +
    +var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
    +mongoose.model('JellyBean', schema);
    +

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    +new Schema({ .. }, { safe: safe });
    +

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. +By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    + +

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
    +new Schema({ .. }, { safe: safe });
    +

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    +

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: strict

    The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save(); // iAmNotInTheSchema is not saved to the db
    +
    +// set to false..
    +var thingSchema = new Schema({..}, { strict: false });
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save(); // iAmNotInTheSchema is now saved to the db!!
    +

    This also affects the use of doc.set() to set a property value.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing;
    +thing.set('iAmNotInTheSchema', true);
    +thing.save(); // iAmNotInTheSchema is not saved to the db
    +

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = db.model('Thing');
    +var thing = new Thing(doc, true);  // enables strict mode
    +var thing = new Thing(doc, false); // disables strict mode
    +

    The strict option may also be set to "throw" which will cause errors to be produced instead of dropping the bad data.

    NOTE: do not set to false unless you have good reason.

    + +

    NOTE: in mongoose v2 the default was false.

    + +

    NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing;
    +thing.iAmNotInTheSchema = true;
    +thing.save(); // iAmNotInTheSchema is never saved to the db
    +

    option: toJSON

    Exactly the same as the toObject option but only applies when the documents toJSON method is called.

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toJSON', { getters: true, virtuals: false });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
    +console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +// since we know toJSON is called whenever a js object is stringified:
    +console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
    +

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    + +

    To have all virtuals show up in your console.log output, set the toObject option to { getters: true }:

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toObject', { getters: true });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { __v: 0, name: 'mongoose v3' }
    +
    +// customized versionKey
    +new Schema({..}, { versionKey: '_somethingElse' })
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    +

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false });
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'no versioning please' });
    +thing.save(); // { name: 'no versioning please' }
    +
    +

    Next Up

    Now that we've covered Schemas, let's take a look at SchemaTypes.

    diff --git a/docs/3.3.x/docs/guide.jade b/docs/3.3.x/docs/guide.jade new file mode 100644 index 00000000000..2f407579b5f --- /dev/null +++ b/docs/3.3.x/docs/guide.jade @@ -0,0 +1,457 @@ +extends layout + +block content + h2 Schemas + :markdown + If you haven't yet done so, please take a minute to read the [quickstart](./index.html) to get an idea of how Mongoose works. + :markdown + If you are migrating from 2.x to 3.x please take a moment to read the [migration guide](./migration.html). + :markdown + This page covers `Schema` [definition](#definition), [plugins](#plugins), instance [methods](#methods), [statics](#statics), [indexes](#indexes), [virtuals](#virtuals) and [options](#options). Let's start with `Schema` definition. + h3#definition Defining your schema + p + | Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection. + :js + var blogSchema = new Schema({ + title: String, + author: String, + body: String, + comments: [{ body: String, date: Date }], + date: { type: Date, default: Date.now }, + hidden: Boolean, + meta: { + votes: Number, + favs: Number + } + }); + p + em + | If you want to add additional keys later, use the + a(href="./api.html#schema_Schema-add") Schema#add + | method. + p + | Each key in our + code blogSchema + | defines a property in our documents which will be cast to its associated + a(href="./api.html#schematype_SchemaType") SchemaType + |. For example, we've defined a + code title + | which will be cast to the + a(href="./api.html#schema-string-js") String + | SchemaType and + code date + | which will be cast to a + code Date + | SchemaType. + | Keys may also be assigned nested objects containing further key/type definitions + em (e.g. the `meta` property above). + p + | The permitted SchemaTypes are + ul + li String + li Number + li Date + li Buffer + li Boolean + li Mixed + li ObjectId + li Array + | Read more about them + a(href="./schematypes.html") here + | . + p + | Schemas not only define the structure of your document and casting of properties, they also define document + a(href="#methods") instance methods + |, static + a(href="#statics") Model methods + |, + a(href="#indexes") compound indexes + | and document lifecycle hooks called + a(href="./middleware.html") middleware + |. + h3#plugins Pluggable + p + | Schemas are + a(href="./plugins.html") pluggable + | which allows us to package up reusable features into + a(href="http://plugins.mongoosejs.com") plugins + | that can be shared with the community or just between your projects. + h3#methods Instance methods + p + a(href="./models.html") Models + | are just fancy + code constructor + | functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are + a(href="./documents.html") documents + |. + p + | Defining an instance method is easy. + :js + var animalSchema = new Schema({ name: String, type: String }); + + animalSchema.methods.findSimilarTypes = function (cb) { + return this.model('Animal').find({ type: this.type }, cb); + } + p + | Now all of our + code animal + | instances have a + code findSimilarTypes + | method available to it. + :js + var Animal = mongoose.model('Animal', animalSchema); + var dog = new Animal({ type: 'dog' }); + + dog.findSimilarTypes(function (err, dogs) { + console.log(dogs); // woof + }); + h3#statics Statics + p + | Adding static constructor methods to Models is simple as well. Continuing with our + code animalSchema + |: + :js + animalSchema.statics.findByName = function (name, cb) { + this.find({ name: new RegExp(name, 'i') }, cb); + } + + var Animal = mongoose.model('Animal', animalSchema); + Animal.findByName('fido', function (err, animals) { + console.log(animals); + }); + h3#indexes Indexes + p + a(href="http://www.mongodb.org/display/DOCS/Indexes") Indexes + | can be defined + a(href="./api.html#schematype_SchemaType-index") at + | + a(href="./api.html#schematype_SchemaType-unique") the + | + a(href="./api.html#schematype_SchemaType-sparse") path + | + a(href="./api.html#schematype_SchemaType-expires") level + | or the + code schema + | level. Defining indexes at the schema level is necessary when defining + a(href="http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys", target="_blank") compound indexes + |. + :js + animalSchema.index({ name: 1, type: -1 }); + + :markdown + When your application starts up, Mongoose automatically calls `ensureIndex` for each defined index. It is recommended this behavior be disabled in production by setting the `autoIndex` option of your schema to `false`. + + :js + animalSchema.set('autoIndex', false); + // or + new Schema({..}, { autoIndex: false }); + + p + | See also the + a(href="./api.html#model_Model-ensureIndexes") + code Model#ensureIndexes + | method for more details. + + h3#virtuals Virtuals + :markdown + [Virtual](./api.html#schema_Schema-virtual) attributes are attributes that are convenient to have around but that do not get persisted to MongoDB. + :js + var personSchema = new Schema({ + name: { + first: String, + last: String + } + }); + + var Person = mongoose.model('Person', personSchema); + + var bad = new Person({ + name: { first: 'Walter', last: 'White' } + }); + :markdown + Suppose we want to log the full name of `bad`. We could do this manually like so: + :js + console.log(bad.name.first + ' ' + bad.name.last); // Walter White + :markdown + Or we could add a `virtual` attribute [getter](./api.html#virtualtype_VirtualType-get) to our `personSchema` so we don't need to write out this string concatenation mess each time: + :js + personSchema.virtual('name.full').get(function () { + return this.name.first + ' ' + this.name.last; + }); + :markdown + Now, when we access our virtual full name property, our getter function will be invoked and the value returned: + :js + console.log('%s is insane', bad.name.full); // Walter White is insane + :markdown + It would also be nice to be able to set `this.name.first` and `this.name.last` by setting `this.name.full`. For example, if we wanted to change `bad`'s `name.first` and `name.last` to 'Breaking' and 'Bad' respectively, it'd be nice to just: + :js + bad.name.full = 'Breaking Bad'; + :markdown + Mongoose lets you do this as well through its virtual attribute [setters](./api.html#virtualtype_VirtualType-set): + :js + personSchema.virtual('name.full').set(function (name) { + var split = name.split(' '); + this.name.first = split[0]; + this.name.last = split[1]; + }); + + ... + + mad.name.full = 'Breaking Bad'; + console.log(mad.name.first); // Breaking + :markdown + If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you. + + h3#options Options + :markdown + `Schema`s have a few configurable options which can be passed to the constructor or `set` directly: + :js + new Schema({..}, options); + + // or + + var schema = new Schema({..}); + schema.set(option, value); + + :markdown + Valid options: + + - [autoIndex](#autoIndex) + - [capped](#capped) + - [collection](#collection) + - [id](#id) + - [_id](#_id) + - [read](#read) + - [safe](#safe) + - [shardKey](#shardKey) + - [strict](#strict) + - [toJSON](#toJSON) + - [toObject](#toObject) + - [versionKey](#versionKey) + + h4#autoIndex option: autoIndex + :markdown + At application startup, Mongoose sends an `ensureIndex` command for each index declared in your `Schema`. As of Mongoose v3, indexes are created in the `background` by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your `Schema`s `autoIndex` option to `false` and use the [ensureIndexes](./api.html#model_Model-ensureIndexes) method on your model. + :js + var schema = new Schema({..}, { autoIndex: false }); + var Clock = db.model('Clock', schema); + Clock.ensureIndexes(callback); + + h4#capped option: capped + :markdown + Mongoose supports MongoDBs [capped](http://www.mongodb.org/display/DOCS/Capped+Collections) collections. To specify the underlying MongoDB collection be `capped`, set the `capped` option to the maximum size of the collection in [bytes](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-size.). + :js + new Schema({..}, { capped: 1024 }); + :markdown + The `capped` option may also be set to an object if you want to pass additional options like [max](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-max) or [autoIndexId](http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-autoIndexId). In this case you must explicitly pass the `size` option which is required. + :js + new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } }); + + h4#collection option: collection + :markdown + Mongoose by default produces a collection name by passing the model name to the [utils.toCollectionName](./api.html#utils.toCollectionName) method. This method pluralizes the name. Set this option if you need a different name for your collection. + :js + var dataSchema = new Schema({..}, { collection: 'data' }); + + h4#id option: id + :markdown + Mongoose assigns each of your schemas an `id` virtual getter by default which returns the documents `_id` field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an `id` getter added to your schema, you may disable it passing this option at schema construction time. + :js + // default behavior + var schema = new Schema({ name: String }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p.id); // '50341373e894ad16347efe01' + + // disabled id + var schema = new Schema({ name: String }, { id: false }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p.id); // undefined + + h4#_id option: _id + :markdown + Mongoose assigns each of your schemas an `_id` field by default if one is not passed into the [Schema](/docs/api.html#schema-js) constructor. The type assiged is an [ObjectId](/docs/api.html#schema_Schema-Types) to coincide with MongoDBs default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option. + + Pass this option during schema construction to prevent documents from getting an auto `_id` created. + :js + // default behavior + var schema = new Schema({ name: String }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' } + + // disabled _id + var schema = new Schema({ name: String }, { _id: false }); + var Page = db.model('Page', schema); + var p = new Page({ name: 'mongodb.org' }); + console.log(p); // { name: 'mongodb.org' } + + h4#read option: read + :markdown + Allows setting [query#read](/docs/api.html#query_Query-read) options at the schema level, providing us a way to apply default [ReadPreferences](http://docs.mongodb.org/manual/applications/replication/#replica-set-read-preference) to all queries derived from a model. + + :js + var schema = new Schema({..}, { read: 'primary' }); // also aliased as 'p' + var schema = new Schema({..}, { read: 'primaryPreferred' }); // aliased as 'pp' + var schema = new Schema({..}, { read: 'secondary' }); // aliased as 's' + var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp' + var schema = new Schema({..}, { read: 'nearest' }); // aliased as 'n' + + :markdown + The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'. + + The read option also allows us to specify _tag sets_. These tell the [driver](https://github.com/mongodb/node-mongodb-native/) from which members of the replica-set it should attempt to read. Read more about tag sets [here](http://docs.mongodb.org/manual/applications/replication/#tag-sets) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences). + + _NOTE: if you specify the read pref 'nearest', you must also pass the [strategy](http://mongodb.github.com/node-mongodb-native/api-generated/replset.html?highlight=strategy) option when connecting or your reads will not behave predictably:_ + + :js + // pings the replset members periodically to track network latency + // now `nearest` works as intended + var options = { replset: { strategy: 'ping' }}; + mongoose.connect(uri, options); + + var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] }); + mongoose.model('JellyBean', schema); + + h4#safe option: safe + :markdown + This option is passed to MongoDB with all operations and specifies if errors should be returned to our callbacks as well as tune write behavior. + + :js + var safe = true; + new Schema({ .. }, { safe: safe }); + + :markdown + By default this is set to `true` for all schemas which guarentees that any occurring error gets passed back to our callback. + By setting `safe` to something else like `{ j: 1, w: 2, wtimeout: 10000 }` we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback. + + There are other write concerns like `{ w: "majority" }` too. See the MongoDB [docs](http://www.mongodb.org/display/DOCS/getLastError+Command) for more details. + + :js + var safe = { w: "majority", wtimeout: 10000 }; + new Schema({ .. }, { safe: safe }); + + h4#shardKey option: shardKey + :markdown + The `shardKey` option is used when we have a [sharded MongoDB architecture](http://www.mongodb.org/display/DOCS/Sharding+Introduction). Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set. + + :js + new Schema({ .. }, { shardkey: { tag: 1, name: 1 }}) + + :markdown + _Note that Mongoose does not send the `shardcollection` command for you. You must configure your shards yourself._ + + h4#strict option: strict + :markdown + The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db. + + :js + var thingSchema = new Schema({..}) + var Thing = db.model('Thing', schemaSchema); + var thing = new Thing({ iAmNotInTheSchema: true }); + thing.save(); // iAmNotInTheSchema is not saved to the db + + // set to false.. + var thingSchema = new Schema({..}, { strict: false }); + var thing = new Thing({ iAmNotInTheSchema: true }); + thing.save(); // iAmNotInTheSchema is now saved to the db!! + + :markdown + This also affects the use of `doc.set()` to set a property value. + + :js + var thingSchema = new Schema({..}) + var Thing = db.model('Thing', schemaSchema); + var thing = new Thing; + thing.set('iAmNotInTheSchema', true); + thing.save(); // iAmNotInTheSchema is not saved to the db + + :markdown + This value can be overridden at the model instance level by passing a second boolean argument: + + :js + var Thing = db.model('Thing'); + var thing = new Thing(doc, true); // enables strict mode + var thing = new Thing(doc, false); // disables strict mode + + :markdown + The `strict` option may also be set to `"throw"` which will cause errors to be produced instead of dropping the bad data. + + :markdown + _NOTE: do not set to false unless you have good reason._ + + _NOTE: in mongoose v2 the default was false._ + + _NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option._ + + :js + var thingSchema = new Schema({..}) + var Thing = db.model('Thing', schemaSchema); + var thing = new Thing; + thing.iAmNotInTheSchema = true; + thing.save(); // iAmNotInTheSchema is never saved to the db + + h4#toJSON option: toJSON + :markdown + Exactly the same as the [toObject](#toObject) option but only applies when the documents `toJSON` method is called. + :js + var schema = new Schema({ name: String }); + schema.path('name').get(function (v) { + return v + ' is my name'; + }); + schema.set('toJSON', { getters: true, virtuals: false }); + var M = mongoose.model('Person', schema); + var m = new M({ name: 'Max Headroom' }); + console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' } + console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } + // since we know toJSON is called whenever a js object is stringified: + console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" } + + h4#toObject option: toObject + :markdown + Documents have a [toObject](/docs/api.html#document_Document-toObject) method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default. + + To have all virtuals show up in your `console.log` output, set the `toObject` option to `{ getters: true }`: + + :js + var schema = new Schema({ name: String }); + schema.path('name').get(function (v) { + return v + ' is my name'; + }); + schema.set('toObject', { getters: true }); + var M = mongoose.model('Person', schema); + var m = new M({ name: 'Max Headroom' }); + console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' } + + h4#versionKey option: versionKey + :markdown + The `versionKey` is a property set on each document when first created by Mongoose. This keys value contains the internal [revision](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning) of the document. The name of this document property is configurable. The default is `__v`. If this conflicts with your application you can configure as such: + :js + var schema = new Schema({ name: 'string' }); + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'mongoose v3' }); + thing.save(); // { __v: 0, name: 'mongoose v3' } + + // customized versionKey + new Schema({..}, { versionKey: '_somethingElse' }) + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'mongoose v3' }); + thing.save(); // { _somethingElse: 0, name: 'mongoose v3' } + + :markdown + Document versioning can also be disabled by setting the `versionKey` to false. _DO NOT disable versioning unless you [know what you are doing](http://aaronheckmann.posterous.com/mongoose-v3-part-1-versioning)._ + :js + new Schema({..}, { versionKey: false }); + var Thing = db.model('Thing', schema); + var thing = new Thing({ name: 'no versioning please' }); + thing.save(); // { name: 'no versioning please' } + + + h3#next Next Up + :markdown + Now that we've covered `Schemas`, let's take a look at [SchemaTypes](/docs/schematypes.html). + +script. +document.body.className = 'load'; +include includes/keen diff --git a/docs/3.3.x/docs/helpers/filters.js b/docs/3.3.x/docs/helpers/filters.js new file mode 100644 index 00000000000..33546a7e805 --- /dev/null +++ b/docs/3.3.x/docs/helpers/filters.js @@ -0,0 +1,20 @@ + +var hl = require('highlight.js') + +module.exports = exports = function (jade) { + // add highlighting filter to jade + + jade.filters.js = function (str) { + str = str.replace(/\\n/g, '\n'); + var ret = hl.highlight('javascript', str).value; + var code = '
    ' + ret.replace(/\n/g, '\\n') + '
    '; + return code; + } + + jade.filters.bash = function (str) { + var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; + var code = '
    ' + ret + '
    '; + return code + } + +} diff --git a/docs/3.3.x/docs/helpers/highlight.js b/docs/3.3.x/docs/helpers/highlight.js new file mode 100644 index 00000000000..8aca9b9e222 --- /dev/null +++ b/docs/3.3.x/docs/helpers/highlight.js @@ -0,0 +1,11 @@ + +var h = require('highlight.js') + +function hl (str) { + str = str.replace(/\\n/g, '\n'); + var ret = h.highlight('javascript', str).value; + var code = '
    ' + ret+ '
    '; + return code; +} + +module.exports = hl; diff --git a/docs/3.3.x/docs/helpers/href.js b/docs/3.3.x/docs/helpers/href.js new file mode 100644 index 00000000000..e7299b1cf0d --- /dev/null +++ b/docs/3.3.x/docs/helpers/href.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str, char) { + if ('string' != typeof str) return str; + return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); +} diff --git a/docs/3.3.x/docs/helpers/klass.js b/docs/3.3.x/docs/helpers/klass.js new file mode 100644 index 00000000000..0c4a865b43b --- /dev/null +++ b/docs/3.3.x/docs/helpers/klass.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str) { + var parts = str.replace(/\.js$/, '').split('/'); + return parts.join('_'); +} diff --git a/docs/3.3.x/docs/helpers/linktype.js b/docs/3.3.x/docs/helpers/linktype.js new file mode 100644 index 00000000000..997e740f671 --- /dev/null +++ b/docs/3.3.x/docs/helpers/linktype.js @@ -0,0 +1,50 @@ + +var types = {}; +types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; +types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' +types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' +types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' +types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' +types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' +types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' +types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' +types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' +types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' + +// mongoose +types.ObjectId = '#types_objectid_ObjectId'; +types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; +types.MongooseArray = '#types_array_MongooseArray'; +types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; +types.Query = '#query-js'; +types.QueryStream = '#querystream_QueryStream'; +types.Document = '#document_Document'; +types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; +types.Document = '#document_Document'; +types.Model = '#model_Model'; +types.Connection = '#connection_Connection'; +types.Collection = '#collection_Collection'; +types.Schema = '#schema_Schema'; +types.Promise = '#promise_Promise'; +types.Mongoose = '#index_Mongoose'; +types.MongooseError = '#error_MongooseError'; +types.Type = '#schematype_SchemaType'; // ? +types.SchemaType = '#schematype_SchemaType'; +types.SchemaArray = '#schema_array_SchemaArray'; +types.Mixed = '#schema_mixed_Mixed'; +types.VirtualType = '#virtualtype_VirtualType'; +types.MongooseBuffer = '#types_buffer_MongooseBuffer'; +types.Buffer = 'http://nodejs.org/api/buffer.html'; + +module.exports= function (type) { + if (types[type]) { + return '' + type + ''; + } + return '' + type + ''; +} + +module.exports.types = types; +module.exports.type = function (str) { + if (types[str]) return types[str]; + return str; +} diff --git a/docs/3.3.x/docs/images/apps/attictv.png b/docs/3.3.x/docs/images/apps/attictv.png new file mode 100644 index 0000000000000000000000000000000000000000..1327f0bd858cf6f002a077a9aafba1217ce38e9c GIT binary patch literal 42666 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 Cl*SPN literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/calllist.png b/docs/3.3.x/docs/images/apps/calllist.png new file mode 100644 index 0000000000000000000000000000000000000000..824fa428eb2de2a237b37ada591cc7056d68f399 GIT binary patch literal 33502 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 $5C9j=SSd5$;KOc+eQQ2^5$rlF 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/cldfy.png b/docs/3.3.x/docs/images/apps/cldfy.png new file mode 100644 index 0000000000000000000000000000000000000000..c44ca3525daa7b847ab2869d44a00ebae852646d GIT binary patch literal 9773 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 AJOBUy literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/clickdummy.png b/docs/3.3.x/docs/images/apps/clickdummy.png new file mode 100644 index 0000000000000000000000000000000000000000..773ce3ec638a72dd3eb7ab6d103dade3874fa53e GIT binary patch literal 34210 zcmV)(K#RYLP)=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81ZA(c+K~#9!?frR>W!ZVyiT%#G%iA+w zE>*eJUe#5-0=)wbl7O0o1|R`0BZ`D1k8F{U0wTq0EY*t&iCFu z_pIM{zWqDm5B}f}G=LC-AP5M<5X-V~9EZOse^LIYTI}EZz27@@Wvw+rhy#Cn(08=f z0Q(6~nHjeg#%&Ar;rzLTwc6k~goHG3TUd6@A(?ARV<&Ft&f zuOE6~084)*2}#T7yywAq3+PZZ9l62sH!S>b;H?ChtDNQji3Hv3` zK7@+r&s2Ese1UKLs7axa<8S?~zr}?M7qBdgKmOxCCW<125L~)+iCV43r#|&5zVxLp zp_Jmvl`C|+T`bGuOJDjDQ&ZFYkN@ib$=~{S`t&`)6DKtP_D#Xx`J&?O8-m;G@b72kd524$+OHIn__2kot;LDFpS9MTynV_p65|2m+5ud z1Yw9q(C>B#!f4+y*iMcoo_GRFM69f=5vd3vB)NP6#}c&K9l|i8SSpcoEbgzY9yrda znPZ$geUi#(u0NvG4n4}yKirL|_^#3`2MkFmYIO{39>S$>Jv z?_s+Is+AJWc8gZ4H9(B)Nt1UapL)$De7+h#gFpLmgUh$u2&J*zBCXDGwAP$EcaGOy zdyRkekNy$WYL!Z*lFAkH^YhHi%<$T4ukpR_eUGny{p&pQ%rh)3Eb!usFLLqXMgI5y zhriE@r`u>P_`m#jlK6l5U||}HIhdW){Fi?y`Jeq|*r>tR-x7T3bxo(Q z2_yJ_{juO5{+8mu`HJKdPisychfWV(e_nHH4!-fWAP5Zw8Mgs@ZOo$r;iCfdeq(zO z*<|Qlpj@7yR4j4)>1WYe)9ZBzLyhCOI624gwt$ott@;i>dh@M)$ELL=Uo2ru&E|HK zCoW#XbzKA+X<0}qu^oqQr;Q&dbkJjEW!12|d##DqhvRV)@Mm&=T5x`YrYrLZiE zYPE{vIBaZe&}=sOxu5$v`gcA+h%l}@kPRkFnqyUg9gorrV5lyjP|{aElH|5e3K6Mk@2#^m_H0sKJ#?;yZGsI8+wnghp(ptili_U3)& z7Z%C64wh{*Q7*HwzKN4}@jVaAvXK%t*VpiZfPus|e%}3V2S3uxPFHESTR67OPOXOH z=BQRDacvvV@6+%5^t;`7v-hEfLeT5Bxpws$PNBrx^&Kh`6C9gg#L^*~o7)6Y#DPUX zzt^SH=@0}VlhrB(*Wt#^8}xd8yuQcE{rhx#UBW2ZjTi!G_aeUbredjTqoXc8PZNb^ z@KOk7W@eF=1O+#5-sC&q`3`^g@BUpZ%i_yl{xT~oD|EYEHa0fc+1cUCU;Z+`@f*Lv zCqD5B-h1yoHa9o<-uJ%8x4->u{^sBOpY!GS&hWgt%75}DgA6~cOEw$u@4T$Icmh_p z4Kl253!(_N8qn;5=L^<$H1#%Y)*(`w)olnuLA|XB0(kG1APnK^J;7!jgn0aH(Lwt3 zL~FNKorl$IJxCD(HZ}|!v$eH_l#+?bDar+x)wOjrS@pb#HHqTDaYdoewGXb496v&U zQUj_xI={WNP+3adY}DfKwe(#ntyEszZ#~ob0_&?QY;CL&MG?o2&tr**_4Up4nEasG z7}S6D)mL}TQfru+u=)4DP~e#pb$Y!n|C|5pE>$B!SU*XvQM z)tH!=px5h>&*$+x56|-BMEk8(lN=^J(@hy=$b zH9a391$_?+IcW6^TNNn?Ln!1mVJNUH==5QtXxJym2G@aK`h?;OpVa*4zc2a0RWX*0 zdN6?c@MVs}YMLH(Y=^a2KTP>3*6mT|Iu`z)$;cmX-w;IVqu!4F%TZXa zKkUAbx{VLB-F^Ff<&{_TURa}JTIkvWr431Z)D!7o|CxtVsqWU|n9o^*;fJcK-Gg^N zsZbS3i!}&6KHnis><4rk( z>}HLusYZ`~9zRRo*O_q*NYmU1@aTB4b)?W*Wnh2Mw-L4^LdtktqjSm3PMa~R zND)PmVX>sZvMemij1>e*YkbeA*=)1Dxy|O<7PYM!-FBD24`X3dXMjn>n-z~M0SI9> zb`r~>2f7eF6JcJm7XA*%-&n`_AQ!$l{T7!sXp`2w9V!kLj zUXT=R2qS3w3P04imSn1EbFAW0ohVYMPQcVL)bug*_L1mNz1^9u{tNnXbvtN8PHDP zC^?w5Rz{l@!=^}JQzY6G9c#OE%C%$NK(x3$>E9pE+fdG*VAnr(wB8D7NMJ5zwfQhC}F@UQfnqk^Bm~Gx0@uHL&iXn&D zhHMcjVkp8ej2GVceT7bl9a%_efq+OUe9t5Be8M0g3d3|Wm5PYeFk+A(Ml9S9b9Z8J z3Nvt=6fuh!VT?sTE0tr3P&#R3$P8oz@x| zNi18TR5XB-$WWBTp;QQgWhsOeBZeAKr=-YHiZbHPG1!-QC3J?$X^o0M3#}1EgZW8` zv~4UWGzcREwo-=dB@DUNP^&lD+}a@wBS<%v46CHjDnoLu%&C%)*ZKW{%#1k2V69bBYIkBR2V@OXnE2cUKfmRCN4`{bK)OPA@Z|u;hH|TYG z1VL!#7`HgUftVU3r>Yp}=2PU)u%a?kKgKDe#7NjZtA<5&`@qB$ z0JMtCT0{{<#$`oE5hxpJ+XyMJi42VJh4W!TBx) z>d0Asn6iH$$zFoeu2!-_<&aQ3ES%_=^;62GRGpzvnHuj%$F8O_GaC_jgxGV4p6A6f z1}Tsx15RYAP(Uryq!eJ=g2|~Fnya_z`#$JWa-zhiw*gk9GKX76dnn}Y(TGHCo~*$b zem>#RlT$ib7Zs`WBu{P;k*Y^WH5~G=xUpy1Piu9w zWyt3yUfAS>*vlVh?C+U(lu~SMZ4rjX^+g>pm87|XE3j?J&wTRJyl{MiDDnnxKZE#~0jp(*wMr2rk&m<%h6-dUM$FzsQ3Ps0Arclc5yp}+B{E}b0v90E zfaOjF<7B0G9a?ILVk8P2A@l&)lk+b*{IZ(Bw5?=MGDbaV#Y2mcGYSlnL{^L#k%|`* zkf0(`o?od5OLv$rZSe1Yc8dSoe_!PI;w2Ur7icz{^!t4l78hB*{!Px#+~ek|izQ&9 zqzD3mWt(=}J<07go9(6?W|4kEN}*5~`tEsN%G)}Q@gYi1Dc|?gXRhnwI8N+<*Gqvh zm&+lgOgBFW0+cdxPY{H-4m@+p#`BGAt5vLl@-=zaP@Ls0Mc>ziQlPbr6$wBpr)2j@ z$B3apsDYLV5IVz?o3{;Lov2jR00>i7D@Go4!gghVH8THF>#H!XB2o|7HZ!hRI8Fdk zC0a5Awo1iqr4&QPZDkQ-K*@w0W~GE496$**5V1TwYHG;V69U6x8Vo@Ti4sOMP?2HX zM5M4)G|=B`Ez*THSPftNIl*Fin}6`TJ4`LS$o#^*aR!{4A__xFr7~wvPEZIHmrnSE zk)Y=ZW-FRrXiks|O9A&btOEh`qYAQd9EW1Dm;y)w$Vse8p-@OSq|s=Y6BEN1=ks}l z5O}^%6jKAoaVVF|^!t5+ARx%NL=UDXs1)NvRzau)wx!AE1S-8 zm{PHfk!3SdDaQ!?0z}L=i%NGWtQkY9=P0C-cxh=0@O5HUKv0b-1!+5;HM+N$(O9kVtXgB&`hLXiTYBO`p1 z5!Q?yt`#_5DWG!D>UezT+ut@qqt;lKZPM*X5X@ri1L^*N2Frq(iHMGG zQOFOO=rWtVx5UQ-Ivghnd7g*wdx;_g%d)U7gUCuLI-O2hH$jGE!Q1UN z0&=rpb|y{I|4LX#fp=}E+Y-QWt0`>J)^D#6&ZjPQW$^|10_eYW+^4pI_+1d?Ivo} z0acNSj1jLy%1S9sV)=<-*T7bWT^t;!gTL9$HfQk@r^RNG<6rBFLC1b_a1MvB&)=WIISL-+lW31FMB5dmi81LRv%zlc6@qH)X zl~zb0SY2D^cmDBz%FfP?5hTS()8oJH-(70N8fXd;dYF~UQjB;|B2_zQ5F_Cn;!`~} zU}_yh>p&wp&}0fE#-J!Hoz~Y%6GekI4Xa}i$Oz&CpjT01q%;3hi6ow~iUZj|W)UMR zV?k2u%DfOoW>QOwi!3cJAb{1iHQs*nPqC!W zb|W8Kvd5p`0~Y}Ulvxt}lTro(+CX?S2Fk%graWu%J$WzLluTQR6*gN(E6wC&mDm5$ z&r>WEDVHm$S8)O?wr!{KiW;Lb9bXcvk==BivNt+4pvB`;q%2N4e>pgPP2U4iAZgQR zfgsX46_}HDRkCaYVh{sumI|47Q#mEAtJAh3odw!>&Exin=ak65LK;?3#P+jf4fFut zN9<&o`HbwL$eb0Xk72k)Ti8)Fj2K}|-c)Rvlv1+1a-W;u_p-|=~+h&br{+Yd$LR`Y>(nStqfJ3_B4qaBNHJWRKdUjvj7ju=+zl zRLB=7l}ZRHQ%bS9xd}kO-%o7>iA^BN$RT@9CjR$7UcSS3mv>OMi?VFAw2k_7h-=Co zqhsbzre5}M_PH27oU+u>JQf4nP3DYB6*|e!v2iWCKIp{JGahHQ&#cBNUH%c9QHJ7= zE>mX1hU<+OnYC7w%O$?>i+`D8$7WNx$PN=-b6g^2^x5%IgVvgv*<+l)^wg07^#4>! z7zS)_ZIUY#DODyY7K>cEbcyBVWmZ>LDHe+;rSN^9cDuc2JBi6EQA9>cadWf5Mze#k zJhY6R2gL(PfN2?Q|2V452vOc$CuKpzNTWl*D0ZJvdQ5*~n1o@^*bzkCHJR}<8Na5c zUcJ#`W2;7Gaw;`C+Q!i<)^JM^KhQ({=wuQLj)iRx_VvCG4RC_sM5(3h7<#kVPS`WWSBEgD8Z0scfUDhKBPvq3>zdy zAyTI>oN;~~j5n>8h15Yc5*9A0Di0B!Jj@-Au!zIjT#y>i3+VQ|0mVQ?>4=R?6rn~Y z_7{lp@FlCQlTvd2{CQSaR|&(Aa=C2k#4KwN1k`G^A%kGH3`C5qQ8qTZ35awiaA-(# zHW)|33=9V`#hMv3iE>V<@wODDNL-FkI`&&kJf35gDLLO&>S!8wmA?+uZ_VlbbT+N)AM4Dtj6|3VPUz=wP%l zCb3s?0wx-pD2lK$R_ML5T_<*cBsFBBYEJm~te5C$qK0G)iGR~Bk5Z*l74!p_%yFia zqSb1p;~Ga9#<5kSEYH9O7Q0qx&C5?m{IyRhRvUs(KMgy52srB!-grl{(J^z{ZVDz!CID-y0r$&?8kBjb!u13IeM zS6buwKE1w|Dxd6LU@RP3gBBVujM4;F9|n5dym_7Pe)kQQ7Ec)aKp4_&H7Vo^IF3WJ z)ud9HNcH`vPoH6Rb%p!)mpOChEVbGWpZ)CT`8R*^$MpJr%H=Yi*T->Oip3&pYpYC5 zOcDeEi;Ii6ZjKjTc!@XP{2@1QUQgXSI-M@A^{GtVnr7b<1=rB5oJUeGi<;AuE_ z5zfpj-d%y8f6h>rckaWfIrwX@!?oK6C_neA;>krrRetwh2;N^atlIRX=9LQ&2Jo>9 zn$OK@`XM}jMldm{DY;N<2r32m((8(MZU|;(G(Y&U-DHkRr%^y|CH)vm4$^x zKKNjh#l;hJ+HF3#`aU;qT;uH7^StoFi)^f~@y&03jZ&%1)YLSe`OMGrr+@k_0b`Neh1Rq<_ zSQea}2hRgfK_&Kc3qxpn@Z2fQ{Vl<%wv8fB$QOViErGaX5KQ^UZez zQ?pPlL8Yka2ZGxxf*W=C)LBit3#BT|RbvS%o};t{fA4QD@Z2c}-`D&H|Hs?>$N%Rh z}Rb%k6m$H|kYxq9^jE?s<*e4&6+ij|f7R4Nr-dhrz+%{ogM~ zODC9{o2S!h1HxFQZHG>$vyb)ufD(Igf?=f+mJJMhmu)vihM0Fw_Itejf0$-`^-aNV z{etFy{YA}tHw1S#1$nLML~wUo@bk}VHfpe36a4;H1@kkSQ!~)_p}P$`O}MlOGgF$c zy(Kuaq}gf-UOcO5b>Qxfpts;Mg(vwV%^`a2syi zhaY|*IB`s~wk>%6k|Ok>?ZKxmDQ4<|H?F|hCCEEa>kd=Qo~QZ7+YXD9E-L8IYDe_? znuYn}NGms}s}BHt_LngLB4u&}s2GjxAkv^!>NKX*Fkkk#HBwX4(|q9zzZ$z+SZM&1 zZQDpG@jQ=QE|p#Baso%nT)E&{Q15_ySrA0<)wfJ$$Y#&H z_s_m+sF@XOuYw4^@)qQ5!FCgD8>Y&FMmzDn1IGcS1qD~o^Wn9RX&fc_{cj2CT}?4> zDAsm!ka#aCUwtc}?@#jd2^*(0$E8arnVX*^TU_SVHBw-^`x=0&SOdYSwE=9 zO*3rUPSuuRT)y2H5R&J6J)B~r+4iz^N~O|JKS?=?+iSCEFz$w_gNoks z3qyixt7rZJLs=KKHo1KVK|BIX0uMTUQzwb4NNf##76MzWL?*KNh?xp&lboyKDZX(Nmep`aXR9ZTPbfN`$$yES?wyT|M|B?#&6M zzFDzD(2%MnaiU7{a13mzk5&@RPNFeV@tp}$O2RNe#_3l^HAcya5Je%DWv4+kX+mEe z@1Af$hvuKmfsQ~2ARG`@ybKcKS(o{%y_lKJ4(px7%+4Ig_kHS(9p>g1@w`5b#tw^%rvYd-YAi0DW@~GWg@sexyLS_QvQbNci}CJRki`+tB{f{CAp-em|jpl}I-bqF?L^7Ej3;N6CqzXlus6-@p-G`|Mr zSE2r|!J2{DzXA3nx_$$_@isJWq5U@E*mDRghr0g;V&N6U{LAR~e-HWGZ=tUK0lK@1 zy!dN~*{2U&1FbcV<8bQKDZsE*$<0HXo166e{eu@WF-`COaajA3IOJs@+gP;s;sEp> zJoqrQXARRS#Tb|TK`=0NkNlhrFa2eVF?l!3s1ZXnYQM2RAiO5a7puON*(_`gppxJe zg%B#OZNmP5_3>pRTM9H&q$L2wtW38;P!w*EhcT38d%eHX%QuxG(tfX)9JdOwEpC!qON z===bp23S)NY(f4K$e3O7YUrISh|otq{WnnW{~kK*f!9Dxo-BD-<@8jW&yihbH{_(aW(wTNFPHP3rBt* zcPULa*+7y<3L$V^7vB#up2=~gjE~(Q8H0$EX!x1m5@VxEy)Z^8TH=%SSW1RmX-Gm_ zwFyx~5Df|6M{tX9FQ5Cr+GW z<^FAM-@b~J64!B!dKo}<4RsJXKtWiC(z6hCz@7&GE_gRg-Nsj-_;Dy)1b^MIT-DFP z_CLdyCy|v`uo4DR1&Hn%=n!GK=-ebk9{T>b5rt#uweKU(eGYZ~UlLsZSEy(Ib{x;K z&$`EI*olb=wAS?deWEBLm&;M9RG65o((86Rhd~PK?uRpsncA#_ymoe zE#AL!h0UD?j%^MU&`8TB3_QBs9&Rod8%}M6loWCSi25Bm){k%E7?tceezm7QdI&%JH^vd_p^_$4jaeC7qr?I`x(&DN8 z_k&?st57JUR{dV5$z&-aR}9I?f%?|O&s)2cBSW9GM(K#FSFSKSJIkG$H<({s!g7n8 zSej#MYMM^FN3od0^ZLB;#&=jcb(WF?L&tlm&zUR@X*Ku=sq!9G`eTu~*K^Rb(m|(I}VW-)o*KCq2O)xuC#g-C3@Ufgc zt}S@ytvA_f^qHET;q;lapcFw6GBH_ZVsZ*8CEZq?AHMZ21BZ{tr~pdkoIxf@5ZIy8 zamqp?poWnm(xa(zAB}!3ES$u3bM(3$jvqI&MY%Fbqfw(+EYWE;D`ve;#B3y)KcLPNUau zqI>Tk&%c1W{B6Xh@*CnP;&+{#m-WKEU?-tVf`n3vB5!<(UbjvS>EzOfCI7 z?N)=Z7je8Da{R&r-3YzjraC)E&av6v-sWRJ_cL_bO`<5^`i+~s z_`=7LN`VtmDil~*zDupy=0tUYwY628T#;IBi>EF=#p?1c>OIXXFFwZ)zxQ1NVe{hR z30$FB->Fe57b#XI$T<$zu3qKLg^NfOmhDn5m)LIk6pBSczsIdx_c?X?1dV2!eBR}~ zA7A0Ai|4T{VKRse1gG6#nDI%3g9ylQFqIwwZy{s1Av9V@>{KArafT0VJSd0J;n6Tw zYt7xeH)u8M6pAHo-Mm7l(@Jw!EiRs7b>$v~(gZWLHKMzh5$m_ny%xgBA)GwX)V-)3g!7@M1G1c8rj&C%(!ICbhgw{Ksg zQkg&l*RNmZ#EG+9y7aOA_G9odo1H?b)HZT_;T)@L>$r}Ci;D;aN-G2sJ0Fn`wvb}L z3XE4)YIb(E>2`bc{D>2a^X%+w(QGv71sWap(b72H^;=E+FyhXw8{{Wvxb(z%Zrr%e z)XXtviw;{`ThtpZgpl<6UFvm(<@D)xI^4WR6uBuUPNYS9?fl8qc{Jv}uwSKhyj)=+=zO)N_ijC$&BY@w8*I&++z z%{A`cUnRJ^g6mj#eGl8djS!kJG-I(Wi~7zc^;$d+tyo=M!?tXs(0G2pty_1}D~pq) z&6Z`MBE`82=V@$jvb9r3NDIfY@H`*evH9T2`>7ZA&dxScnuFPK9D*>wcAPW;+F;&; z7(QuRCco{j*bhBcQ?{30Lu+H4uq+GPu}Cu7+tPAC4l-R!tq&Io@&F|W0-ku{8S?oe z_4*dGv-4Cc6Krp-6GjpD@86+1HN$ju7Q7~+JdG$$AfI{-_5Qcfx8BBj`4>^Q-a+I` zh;tt|>PHnJ&wU&wW|7rnM4dYN-j&$S0Ak?+dgU5o@;Kt`$Iv$fdgVH*U5C~V^6bYE zj!SiFmg%Wk@`Vz)Tn^tiYUEO>LaWuF+il~zIqu!N$dme6lIC!29fRoE%34!nXNZX;1xA23IVx_|QGpD%n z{`&-x!m@3ojJSR4Ca&Y)xGtwop5*@WT?(ZNFTe0H-hKNmydc8!JY<}ctM7Se4NqKr zlF3q$)s=g!Zfv16mw{1+p<_#TB6^qvsr5xEoZ`YiGfTq&V_1hiSJKwY}>4@ z7TD6Z5lIda4CN5=;H-fUQYI&-s8*)|n4Ug{=k>UA=Q?2+GC4U-7zPL-Xt(RE)Z4fp z|3wPLGP83hXiv-&_&xez#O$lTLbI_0woAEGX661JtX7wkKl2;hU%kituY8Jnt3kOu zNg`9(SUUX#JM&LcES5k>R!a*MCZ@4gmub|u34;LJvY4EhGMXH%+1}Y? zYHBu4b>ndS_#(%TF9LAl8>GOTdBM{s)Rz@>M#z-iS;JJ^#$kb$+cB@IgJb?}Z zh}~O?#R|UHCWuU2g=OWKn8-6ZF+n$gQ%j3PQ9!rd#*Z}9QP7tgmk~KYtwG?^CO{ICgB7yle5nl`AZsIL*cLXAmfMY7J&*XXy2M9Gg8x zyS{_Um6@5E;?h&kP^pyJ-rOKptWYlIS>M>8IyKEywMr0#96L6{salO@r_aLNakjTM zaPlScu8puQh?baMU**cx8|X}G&g9hJEwqoZtq4HK)GI>AJeZWyB(W9JiZ2VX2Dx{R zsEo!?IF5@YErP&9YsKc~DpFe9zIByczQF9<607U?xqIgtx9(hLtG2`Ym*3>}y<2ST zY_qnu%=H^r5SGpC>^z-rn=2o@!)9%pt=cv{-vcK{uh*g3?a=77SX*1>#;vO?uP)PQ zHRuEZYis7x^iHQmp-|-B@-41>@D6LM%WQ40Q?G5|x;b{XH}JhaD=T+~b4-ny-x1^x^rE)awvcW&LHRGsC?i|0^EF*`epZCMmcB?`G5xqN|gsX(bb!R+iT>+37@0?oP8 zC%Jz88tqOGDJ|yb=ed9H4w05zIDZzjrc^9YtMAbBJiLC7TD{KP+#FgdPM$u)iN)h6 z1Q#z}q`9-n{k3(_ifh-dV&%##F3e%s4yVtar{D;#T)l>n4rk7s!Rr|x7#ZK#wC_J5 zOe&wDf5xb7+cu8lV%sJ~l1y*RNpcMh@xPD9nqpZt<;oB?Fwy~igux#5nC2B>zu|ug?c_3AGY5;!3;@Se+ zGOSpXWcky>nt9uGxp?Ukoo0iLt!>uV*Ezm;f>O?6eQTS*_o!57IX*qf%G#Qt(A_@$ zPMfY5a`ECt`mGu_Z!cpM5?l29CZf$;)h1IFtyUrJcAI9i!TRPl=gyrsId0K3nhj2! zImgswh5IXOXkcq|6VDGR6$@w;(P%bVU0VkM%lGcGzPW>rLT=u?$@H-~rYFj@+g;9_ zIfoAWc%Dxb1$5d?w6uBh(i8MLP2PO#ZKh|B;W+jXuqTKhGgW}zG>UCEG8;dW@hJDc5hKCmFf06)ayG`t23NA^91$! z4jUUQ96!D|58IT}wh==qv{pwUj8-e|-F8X;)ZYuwt}U~_8+4MdTmUaz6T051q} zY}@euXnK8*Lb1d%Pd~-g>o=L4nPc<*4y)^1Xat2qo^H2GE|*72=yc7g{N3+=9{?4F zCgGge;I=UC`9a_lC}X%3La@EH!8`B1OU`xa_4-IlruSWZaP=A>C=_yZI~^?B!F6o9 zy&m~|5v`32cp~p<1Ubhc3`67KXGuKYH<#{M=AMrq5mGXL{5V2dxXB`?_bSBd#KE>^yga4I^eKk= zGHo2KQsS^BRD)z|X~MptHL+M+Tq5*Zyfk$TNyJXQ&HUUfonDXmW5-xsT}PmBU6&{U zv?v&xfFYYIf5?U~1a+q9OntPuqp#I!rK_uxSnLF!5_^mu)X4Zj#*fCC`b9?bq=%Z? z2tf&h&_&G~)T10Q7LsNo-_G)TRSx!{NZ} z(TFS4kjNs)F2#}<#;u_bdwk!s48yk+!nmObu=T#M|Ir{ta*@f1=ky_zZ$s;MXpec3 zIkrCR{g7 z&w9|PMuOS0rsgqj|(CX}7aT8b6ZxJ-u`_gUox#77d9(y>A;2(%F(XWfkINMl+A6ZQDmGl z+iiqpr8lV#=U&RXgpXO=y@ow<>YHrp!x0m^4y~9XB<$6m?T$o64TrA|kmj%^(p~#8 zGHF=#pD?QxAu0vR7 zk2p8YBgT zk-`h(bf-h_nJb_pWdv`77$f@dv~@ky(_fTFDv!R1Sq<0V@}T%amJAdQCq~}=5zHlw z`Ft+D%Ojg$Iw{64Ob=a6kWE6DXzCKdeOypeGN2)#*3kF*_`x6{-i1ZUU-|Sjb5k~+ zukk`f!Ie1n;LR|$-3Vc9I#Hx)_Z6-qDYzz%L<3f=F9}1Ps&JDv*=~mXi*MGsa!;j- zmNc7Va=&1F$)-J6xh$WRAy<#6u1!+LBpRgQivz`;?*u`RW+#;K1t!UcWH)j5g@la# zo;A#6?~2RDnrBnnB=tstA)5^`oAGcj74Cx&{)5VJFr^+K2g!+@S<^k@a*_zjD75G) z&B>Fea4e|R8+cwHX*sAUV0w0zV$NaZ{tEeW8Cyym*QVR)((Crfm&zQUouOXaq3`*z zW=9YPAqa~~sYI{eHQv2(P*ygvL>TxuZjOQz@@uc;cxIu8*6{AV9&3$|xhV(77RI+L zCvhwYB2B9s;W!p2W-PAV?P9qWvy(QBPK0d>TuV?XO6tv!3#am2z2{NNOD-(A94o+I zc~$Vc8vz~PWw21mZL>zc)k4Ift=Ux4L#sOe>w}a|yUpEucZmH@;=~44nkdV%B)08P zC=}uh;3g_;XJWMebbAq~NJkDs(!X*x*>haa=B4 zdg|fRcperp7)|`2-PXgE}rA4pb=h*xL#c~0m zAm`fn)rj?#`zUGQ_4|}3s#K*wS{9{B1zQU0wK}%zGUv{7_vSTf^*TWiq-l_})&zcl z<+$Xmkev3}+~|RZRwH10D`IU8gk`M$$EuR4f@Hm+sI?=cC2%gd*ip#Jn&QSCg|sDp zpa?_AIf4_j7SqK(8yf+|oS^DBXuwesc?;Uw9cC|e!sZdjd}rNylNjAGDzb+y`9gt( zg~b%G`~5Din~P6sqiVEmJH5iISS(U1mCO~w!dy=!rNsA*lb;{>X>M8Db_^m2L9tN8 zaU8-hz_wj{-%Ekm0Ck>1T&LacAf=#MtrCV|n$ya*Z91I}<#IW7qpnnj-9QrefuyZ! zwVM9E7dRhX(YyW*``I3Rh6y1Ed_N5j-rQWH*K6atHd0#no=3e=r`BxK@Aa5HcHCq% zhuCx1BJ@4_o*$q3c?yLBlamvO^)))3uCZq*h2y$38#R32PwxjYaA2Gwr4V#H$p^RU zJh^D(i;~ownKJjy-`;|g(@=2*mVyaO;}(tcci8Dsvf<=}9>fp{lPR(7!;C9v?ZC;3 zQC9418Zf@Tu4whA_5kVFGgpWhF_KJ#5a;g9Xr*|F96p)iI1ba(Gnrpz4)tESeE6ui zq!f$A1KKqCt0pI_N7m zS;~yfq+ZL6Ch=a%Xo+uihF3-a4bS37t5rOe8-o~z6-^Eo+guK4;xV*l*CmC2Q68}z z)lv>^GjiVj}Llh?}-i99abjp4v&^`ynB-DP9SImRlatw zgwRo{RXS>|k1>YYDB;9NF>c-iA2eI(I7>*JW+ln?Jg6^@lo>co@fG}k?+4ftet9|~ z>=}OE+-_=QlpqKw7K;=L#Y43jY52qSfO-hOb`0pX)AasYoBQ%Am5Dtw9X`^I9A(*! z6T2&90c%7aPli({6ymkp9RaudI2~oiVF)pHX~M=B@3J1-+2cL6ZMbMTDm@+Pvayc^ zB~`E_mVR3)23JGrM8p`@;eOckBhZ@f)I%&G_)M-xea$3tmQvE`bZ{J#XnAgK{?Le_ zG<>%fanIAdUW(|iuj2WB?Dj6`^?IB-Wgk6a997YWd7RbUXP=0nib;B=;Y%OM@FMz= z5Z#U2%j)8gTL zt7hUNlW{kAoNnj)6#>lWj=tAf_ro{iKdRfgz-aCUzUId6o3|}#K>|&wD)r(z1hV7B*T}b2J-XF<1I=qom?ozd<-nAmLM38l; z{0K1P&rK1J%#tV#CucP$W@7^sMmzJ_^T)Yxyh>lXwCw^dS)^yV1jd_&Na-S!aP|rR@yt zYZ*$HSgVu6`#~{dghfpH$mI)6&mN1lu|t;c;mu5^m#AxFd&9mSr+d-j2T^kDcB)KO zccaFb4+UAXqSiyqAqlTlV_YsCq~x5;krj{W#6*Ep$EN7m1$LYXw(LooR*}ARiDDp5 zHhRcAL?`)(#URa$QAftW8dsD8VXkCN>!M9^K2$Wgg)6Bit+YK6x2GdR=?r2BlrWi2 zRHQ&fNEKmWRLIh{%;g%E#gNDDXbf-GtvDl}3>!Ij+mv*IV3{@)#Mx%lu2_CMA+j1B zt852e^ht@rfM&DtklT9n8it2&`*DtCcS-zke9xoX?L4#^+&IBy03`MAQL$I3iCR=5 zLJ^^o``XE#v|<2gGC7r#L(m{amh}-yt}&^NJ5D+$Q&*=KaAdTWalHh2h^dCDDPyhY zfPqpe0w|OcCR+`L0*UzdfmcRyP$&N~h%>s&Vk9mk=oan z>foYr@-s+h0>UvskZfAY4JCqk2FP{nO_c?JSeLJ}Z7?v*=?t0HBjXvC9g;&eTXVOK zMMIjA!%!?`h>_AU&c?aGvTB8RScCCd88(73vJS)Z936MEfn(*TWF<603vA+hmJ>25 z;xR-~l%}b-ESr4Z{fP?R`DrLo6w&wkShh2i#qdFkau$iK8DI+-gTOIR4gl&P%9M2z z9lkX~WaNZQ;|Dc2)>bkoBF#WE_zb84BBWrN&LwkFr)*Ag8=J>s^|hFku+})LG0Adnd)C zl*Aji*XyCRW@2IjAiV}4xi=#zqc=)fQqb*n==J+dX4)NSyN+u71N1NvredFZd;gT) znX$)6MRNB=RvUT%+-MQY0%P}UFE%IhTUJWX>X`OfIy<%a=|n4G8d+Ic6SKWux&*E}9v`MdzEaP*|rjw z^5kBMY^+5>^^zN$5D1J%d2(!ZM%=y?z&|C1qE|7JTzgyWLKM zek{wP)oR7JEd*#S3~@#BEk>IRsoIh6*#k?2jgs`WR7*ta^Sg5iJ9e>1RC( zi)o2dzYdLAkX%J(*rU;r46|3m^BFzr^&#M1g4icf-snN1HMUj*=|ADF3&#u>?5fp|GXEiHSJc5`<_Bhz$ZV^#gCCH%SxR% zae}3#CBPu{i!Z%Ixm=-8J&)DfF?VNpUwOd%eCLDcaH|Ij?j*flZ#>?|84v_eXOmNr{$kJ%IF&|0(J?1O;()EsDy zMB`+&6GGrl%nV28#e#f#LZl}3G1Ex3B`ReP%(jh)fQbNi5WALWGGYhG6bPh1C#gt@ z)tzC8@_i!TLj?gk3K42pFFvYHmjY}la3wgFFxO>Ci%?ob!er%0fJ&q%nr3>U8sA)H zuFh3TnT+j9VF5V_MH>pXNG-1_wjM^#vt32PO(J~$V6;}8@J{Iq}Z)A z)FU`E&X6=fnyjaU*`utGyPFau!B(c(%x;ee%_+qn2Pz_&e{6ry83VOYF<&>v?Iknb zT~_||5Yb5{!eJYR5Q5UgB%U9jBqU@~0Ac(s0XmtuDF_2_M*oJ%V;Zw&sl`)RyK}x| ziilm`jV^nDaD&AWXqogg9yzj;7Fr>q2%#baBtoDq3*zL}8f{WdMt%ICPtfiXw%g!) zSW$?jb$a)8h|!crF?_g|V8Vt{PEv6#+?-436zDnyy3)auj?t{f`g{?ulSUe2pHf7j zBJ_Ne*N4EvRS|hxQ_f3f^MXQr3v&=@LTxUyFBe>ss$P#c38t7k@DLrk^m6o4$E1G7 zHZlyu@s2Bvu#%gv6F5jtcJr>05i;$J;MAxJcGwW7)4sFYsS+ZUIgCuk#rP7-&r=_4(RLeVw)<_uz_r<5K=42hO<0LU@*NyxBD zk!G(bw?tK}O`9V|h2-qeVsPSX3B!S&aXWGDA)%E)G8M*`Zwhqmb|9n$!sJ$pEE`8h z_+dz-6w;EoI>OZ&OK2huzJ?(FCk2#j!AwqYydas%J2?3~{al%*TcK$c=}DImVUR*a z>0)akiG(0hioo{?dtHKV7v1aNggzx1QOOG?@{*!$HrbCfkuq!VTD#=}J^Ej*$=uUA z@S@Giu(1U?kvp-elp^j^n0wxbsBK2R7COmYt4Foj3{IXArXnSwvE?<@Mkq1{p#*W_ zK7}%rEwgxH^jJyU2u8GHneB{$dxQjMo)3CAWY!>tN)ZDgjny{oGD!e2I2a^G#&spw zNFt$AzFrHHg(7bW%C=zAkxb+y(zU^L=sFIT?P5vSv=&n>D~@&1QX++g)EZ%%fEgV{ zM4^vRVJskyT1AIJfXu8D9y@U&L}_$#_GDc`#zAO?l^L@9W_mCjgp8A%WvIlcbKqcy zOp40^jHOjHDn0enSG0!Y)KA&pfnYL_r7|pHtc^<%2IHDC$meU2Y&SQRVG(0$sWEFN zQaKxA+1H63V=(%`2Qi!>I!4%3bCvL~sX->|vViGK#V5Z;nhxdY37Ga`6a1Q<>H zSO%appcW<#k?pCx0|gQH!d0LcxZjBPlq7oFxgYfi*YL>=}h<=716zAi<;q5|)LqY@}u6o-_?! zDmU!fjNvs;0VzI6ltxQE&^II-D)epwB$Itlp*91Erh-n?N(0DERr{n03Yj@eHHv7U z_KyK?ybDK$D~Y2-4Y3%>F)%8UBtsf`p5Rq-m*kLuG9-s3lqsG^6hRcB!w{t+bQGb& z5IYP*NQGq;gOW61hGI8Qn+mpReFLy6S%75g(>QV+%NU79DS0kZ0}tumX{1ufcyZLo zifARwiJXyDM2sE@SCIJZ3}g&*5-32+*n>22q6;GeU&zAz4QLK}^f&?=UTEOew$aR!noGIEWIfhba%Kq>qX{CIvr zqzMy$A`O0|@j`HHffYvhI>eI!feP@YPk<&Q&Xtvtd3Gx+WPAh&fj|udO$-A9jKTw% z9y}uP!d2!3*Fqv>gs>7BGgeu|YcCS2C554u2^{Fe{agJc+ zMBDNWy4nuSp#<{kP-6@PB?5jWgR*F#ru05-`9;4q%51_#b zxJx^h(J!ZM9-w6v>^@a?;bkUvScq)>F+BMYdzKwTtlLjw-J=L1WmL7=s7@t1rNoJz zOk*gCD~)E#jqiqzge1hm7ZxEBB}UY>*%^w#FIp>97{w}LBa1i^Trp7KWe-|`k#TG( zu%tOyA|VNdg^xujr17jBS;p}xh!c%YmQBl0`jMB0-p|?&_EN(SX^E2OW3*#g-hafn zI1mXkP?;)(GOW`mbr{3<4E2>^&k|%B;vTfdUcPm0WEguvWQIg#*s1-%c%ZLl-!ila zL#rkZd}ptEhZ@_sI(yhivh8V|9qr)B?z3UMFP7MAO~wS#j34Q^F=kGDF=jt^X?qy> zHH`!6(TtJf>J8Or7{EuyHvIbD`#P|_9MsNUV>$qi$FJP3H|#Ou-S{GQ*E;~-2g2}S z>g}p34)xAn_4evEbpsjmn|V?1`Oa{Ude5H5xwH(8ZLh)UakCm%dAGtq?*ht^zDN9s z2HQDijJxU{kn1oj-;J+upiTCmH5=Q`SQn)I-IB6>?Oy9adFTthM=x<7efCk72krkL z->V1p8s5)W?66~dkU1QMSM!66?QxWY0QsoeI?Qu;1jN{{gQME0$59@2Y>yjw4(llS zIL7uD`#C5FM$hc!0h=AvF48ozx#Ko_bU@?U(uZJc_ImapV>@g=iNoJGFX6rV+G}3p zWsm*Wd9>c>-@Vpszp?yz+t0nqeqP+;ioI7ON-281-jK)aUa<^^EqejPgZ};?Z9nMP z#<|5mYG3=cW5p>ev+nH4vwpvyy0wqCb5v^vAKrc*McWVh{y}RdrA*g9TkO3W?e%&n zrP9oNX`K3yDQvW}jK)eNHlAdFq`!}9WsDj$YX}=CWcJb+Cz=TrYcU2Y>&J(Dk5b0< zliaV-?RF`ZN<;B1+4WD>Z&V4BUB`6YGRq~zz`i!TZlmuF>tzP*W_};q1M_=YFR`a( zs>_F1($N!qKg2z%{S3o!X#JBi7BP}LpA)3W=LBE)WDXT*zH>RC(bWhEt_`P;TijZU z@WVJQP`t1`Pjh_6;>48TgB8W+UvcsKif_CV(DvbD=WVvOBZMn?VqS9fZpd~=)9%5g zGd8b2VR7wl$h)^AlQLeysdU~yKkRa0yA?sF2Llw7WpWdF#nzt(W>gw3S|$@Mkku5f?H_^Abf$vP88P{<2De#YXh>mj{B zW7&ci&)d9vBg9u=Tc)1U;8+G}x}K(7Fi8fC9ahlpX$m<~wZA2dON=FqO-Bj{!Z`R# zns%!dNwp++^0dv}`yt=?AUx7_dR+UN+@q4c+z9rOF%r_EH577!UwF~s?rOxV&p7nD z3TX>m2XeOH_G(C@2TR8!TEX$EWPMvvsYq(|h_!aWXFl!_c$)JI7Hdt#$Id%Mfu`Bh zOcVsqpSRFj@a1oMJaO9MwWn;JJ8kpXmlPc@cFC}ym=_c*!A8wkjOS-8{_vZ9)*IoF zF$f-x@649bXAjc$eq|i5JNi6J+O>dRc*W)QOBR3hgMhOO7D{QRCL}uzMX4LP20lXm=IOJ}l0ftG*luR@WmUTTpSV6fur655S|g zwby=Tqb`%OODmPV(;)T#0j}N&`O1$192+J}lH*m0C19<7`C^~_r zm={cz1XC43!G)O#bKmpwrlD5j6zzLmLpHiFkE*IXsGrei2VILc`hB7-nJvQgHN~mp zk|5OFxF2ELFf%EbtqA6(CB>ZJ-g-p2A}L5gyRW%&C#2)Snd26&El^TWj1#!!9YG-n z$0jASRY|X>skJo|MZxT(WO`CEQxW7Gm@ElgS5Php@;Sl$ti`jZEo@=-yw=v-S&z8A z7V)*W1JnU9{GjWd-J^rveVF|meMh|d>Z`k^kR%33PAyBqL{U;}E9Pe;5`krz3jlTe zTngxVhBP0qN}3(TWJS{IXc}Ej$%T3cW~+j7PS6W9rJSJFR#;M?G)z|n%bUuu2B9WY zP|67`8>Y*W7cbddxfxRLYC1kl7NFS$6=`-liL7yWEz^TMf7G&H`$_hdgp@~7gzx)l zT)Jh!OhphxkaxlJq1{tVRU}blSluwxu0g&q(%69i`8<00dir^c=3~TqpZ*>UE8y$bB3`=W@Y*vD)v~1C zR&+g0E+=q-%l9Id@0mWvX^=*L6JtJ)U4C)61L31UhzFrE_I{Nfq?1QsMIOZPa?}g( zAme(Nu^mQ}HBSB*@VuHRg4G>`j0Ecq#qlZ06N?tt?nJzGJEYUmw0oLcYl`*lh$ztX zJOHt$ddBxi-|fh$+L7A z1lns*N3m#+yS<|Vtad=?d@$EjRx&@n_jPn@B0KnKoA6kVTk8>^!t5! zy&m0emoN-bN~I?GN~J=zTIK51tE{iDr>Ev#6R1p1;abq@^f+;12}=kzHZ~|vR4Enn zC>61~vO>4#v3TMXla&(p@86@*Y!7Y1;IBDeM}3c^ltWn-53{)syP*f$T?T)%8o0xt zy2v*06Iwnhxno?hM=Oo98Yh4;Gc&{FG=y!!G>+_`t3r=EU_Tet7>@#kOQ-p#A5udXsVbDY;+`vjXCn@mlXxORJ)+36}f zJ9SFs60KH;sp=%_YpXc<64i+kn_FAV&K?I9vb9}fZhns1)+Sp!wGU;Z9>&+{aRb#) zBa3>Na-b98UX2$D1!iYwSy)&|Py8?pDVIu27V@dh!?G;O{JEUg1KYU z)OR-d&Kqy=xnKGMn``%3T|dDGSFX@#b(pa8^m-oUa*=xA^Xe2z1>Z|Q_j}aqHQs&a zEo!wLYPA}TMxC9V9onrH^?HqNr$eV>SS-);@O=;0b$H>0=O{>@&033&XY<$p#=nQ- z*fg6B!Z7587hd4K_uix5?+-QzICbVMUZ+V*NzR=;gCOMWxpNd;i(cO|iJ7HD2q+dy zwCme6x;`I&?pa#RZ8kQyn3$Yl`QB~LJ@E{kP8&B@Am=)4Z|@*2!TP=1codmCK1s9H zVR~v7DFo3&$PI_tj7I^Ihwb}O`hA>sh(~qhdDyWXO2$Yk`MyuNT;^YX`CoAR?eEj< z^;vIr@Vq|0=hNx5+1lD72>dv2lX*XkGldV-k49rMGc(I4U;7lc?O<7!(FpXm@S5v% zyItny76<~LC!V;-@BGg1@Y}!r+g!bRbs&%nLA$ZTSHJo`zOuOZ#5qdEB8v<2y#1pe z(rkCQaqSANZWkd0joLQ-=may>3U7S->p1x`^K-|zdE*1Nw>N3DJ7tGC9eU-blyy=8t|f zBuEP(xN+@j`q}q-eE+-OK?;%Hl|8g5TRYsleIx#Uch`cgt-#eQS5i6aQOe`w)At+O zVNT$~);+4R?iTpM;JzUo=+Gmd_Ndcoer0sU46FNZ5s7D6O&b%%_gN{iF&_h)Uv(3%~!ti6`IZF zq1ItfmyqP;ZnsOX-)Cxin&o>N+_;^&=m&*5G*_+gqEQJA0mm zg#{)jC%Jp~ZW=%`s)g818V62@nHiAycx3@+FF4rCx$(m)W7XwAE??xi=bmMIbCZw1 zSS1QWq?F|HIr{A;U;WxQ2>0WcZ5!X~v$efrsJH^xbxiiXNU*rH5UbDs{FcM0!4Kst zl~nY7pH{2M#KZ*oeD1OF$-eK?ZnY>Bi<~`s9@our_wLsq~J&L6qDp2%#ecW7*YIXJ}YOar~90oD= z)k=-N?E5~=W|OI@DGG(cff@cDwuE8C*7i28>vG|Vi-cjw%F48*uPrul~5)gQjMql7s(DemDAefm9 z@q9@+Z?tM}yj|kPx*gvW|8NJvVVx{T?H8kUg%EiCF5h|M4S+N`#gA+UP=sNWDi!uC z)#+nA|NI1&ZGk3EvLJCB8|%+GwSdC~lV!_+>e?uZsMqV9SXwkUm&!N*_=rmogf!|k zT-W8ynX|N7EjBkdhbCmkq-nJptgk!dixUX7P8h*XQ=&sdF-|Y|grT62)7)8giL~JE zx=ppDi9&&8Yu2_MDwPn&(G>Fv$AX?Om@Fv@xd#hjJ&cdfVb!sFwKeJRK~M(d825O zBFB+tK_sxG#*#V{Xl43}qA}MC>{A{Tu=dJ^F>d|$YvV9QDaAkir~i~c_=7(fOT|X} zJV=fDC=qpgt<_%RdepIH+v#?@>Fv1LvX|rQo~%@sx3AahnI#Fb<^j%(Frq}E3q8KK7Mvh`3M-&EV4UXe7IXOYI*(6^m zu+{1j>4?edB!1sxYGwu%h9ESJMjO|bG+J$h6a-O(W!VTR2&2#l@KTbq1xo2S6G!mC zbKb8U6c;eA&co(_5<+m{!Udju^2uGBe^{hHOm>b3ZTDg8KkU1;T8%f}cw^7I=tq%m z-w3{BVQaM-j_WX4ts>*}^HNIV{1=C0=5je4+on(~;yMmF*QHo0k|$>YxrJ2jYGI|=T3U>b#`1@YmUz^F+Ex0%-M5;Mafs*ZI|7{nbMuM$+D&Hx+KZUgx)e`?tA#`SPJy%0s!G*Xwnpw3wWnN&dI zF0Py7)~#FPPgVqB7%(|Gi2!^*05t7Rn^K`bqh2SMH%7?X_6Ax?x~)2Q{0{e5R_U}o zZr@p^TCL#wA=T<6Tbr9qR;LIm%Mg&a=KK`G7kt1I|k zAKP|VUS1wQ9w}H|zQfk~3gt?LcC!&*%9D+)7}zbe)~v6t40)~IyL&s0juS!qo zY@s5JANZ(H?b1~ByB%)axQ_1!1a74|wmr8%&n+Y}VVHKE1&C^CyU+#D8k|;z`T0ux;q~x`g{g z?`6xVf74+F)T3|*|1gWzI(2t%Hk)I|83aCw-QM#CZZu&SvT}cgPPdC~TZS!+*mW?N zHjI+N588A)AN8z{wk$6%Q>)b;&5kkp^7QmHQd-Q+%wSo@tMlONG2r}rj=2bMp1-qNt%rsr{hFp+3_5e8}#FjM0;4lb)2E^ zFng1EGPaIVihuG?{t18dM}PG2b4t@K4043+KbK@JhCdIi!-G5YKCJVn)oQV|wY6_P zfg!EbVK(x_i4zC`m5B)i(C_pYiQfsg*TqmF%nF)XTXP)QTr_N$K7J0{J zvQp&MomDE8l5qi#?`Br9lam>TrrU1dIPOq}jGv}Rw1-ir9_83Z_frT#y6>`B(|+7IGPB}6H7kJ>n__(NgO_p5D>-}+&h*gQefMf<5k6E zDdNtG!*lE%d~lK-b#&gA!`pH%RV|1+Fy<^e-nhX$fGb8~Yzj!mmsXLe?WQn7@JLWIl% z+57p-zg*5H3Il|S(9&ohf-uDMeWFN_sA;v(@81#3#3tHBEI}CyIL9jS<(U$ zMb8WI0(Gchv;z%%XU?3VTAiZX?U9c&2KKxNUYK4u%s`$5Bc#S*;#=F%RQ__pr`y59>QL?w!4WE~}y)r-|FI z|HnPHqgdMq85iu{Psf7Kzc$A&{p=j&f=uCVIOcLcWHm@~?OvCE@<;c$dB1z$nC!ke$sP`kfB2140l6zPV3M zMMROtc5+lIRdR(gm5C{e#R|pp1f|jhxqN|Qsew;DXSyW#)N@tVb|RvT zGeolH*;sJ#+H0@r?BtTuE4eT+xz%Uz+_Y$H4Y5Zj4EyHn5j-t~G~TrcgcPyCZ~SSg zwH`_oJ>1TNW%wI)DL#sXU5^9#4l77MOy3W)W)J%QLE5v2)vj662<=*rM}w?y+}Lr& z|4HgZksi~=@EGi9j5~Fbe>QocS~Yp2dc7XaW)rP7p68R#=XW)(V(DwobTF~2M-~Z_ z&kyR)@}MQ@>v3k$d(`riW|_~{A14rh7_v|lWi9CA;zNd{@c7xIS=ILxz7tmJ7k}{= z`P}C|N2}FBO3Cm3?(ed)VjS7>`8>}*|2&@O(dl#uf`DSNn5tTrmzOzn<_wvvapMMm_=kVU=Rf~>a=9FD zzx_5^Yv$+YdF{2=Xti3LJ9myJpL{ZH!*Lv5dg&$B*Vn05t33DIb6mJ^ft{TljvYIO zl#)+>`qP{^ae}F-DbAif%jL_L8Arj60th}VZO>sg;8Dl0*Za0@$E@$LM{z=l^MwMg z>!zxBX~p+@3t`yeF)5GBuknBosR}>o)3)t2h-#E#gUKyy+Y*ozi^bTd z&fN83Nr~gSrOA>Bf>NoNdJ_*=Yl$Ug%I&}&zEWCi zY}@9SfBBc0nVI4H-~T?BFJI>R_3OO;`s;lE``_oSx87oVdz-i4ew(MCewsp|K(E)s zbzS=Xe!3XRW$sF;G)GjqTuxobgCJmfdisGpA0MV1rQg+I0*nq*j*@z5;Plz^Gqu1}?N1Af6Xacnm*p`LY@6qk{sMTu5Hl{VjQibEk zW^i*kynY{HSx7YN8{3>adxkI!X*U~$N+Zx%wnIMWP^;I`2uh{WcwZ^4H7~vN60g1X z8rQF1r&g;mGc&_`@4d&xix>H|U;8y~+_;fyPOe|SPOH_T*=#aBJx!@pLMg>pzVa2$ zpFdBnR^#T)n|Pkb#KZ*sexH0k&o{pDjTEz!>jm}$>W3|lA~^0<_eg;G2t9&Lu#rO{ zUqEX`rBWdXqS)b2P-lze;>diyfMYoUmjh`0D51$!tN6Z;lu)iz2||xZS(NfFonD80 zvBXSulG^rmW;_xBnI@uh%9bj}R6p#bkAgc72=eooy2T?QXYA zv2>b#zsIrTbAY10Q!|uQYl@{Z#bVyb$vGE42r1 z<9#rc+!$JwHh1{>zK_<1EefNEVyTR43pO^l2UoXgD3wYGVQ!)d0-q?-xH&hD;a6y7 zI07LpT-QcvhytI!=MT-ZSSq8VkT6o@^CqfLNDIr7gkgYfJ84Q%OG-07AyQepIyH^g zZJFd2nRUzMawx6HVJjV3&G%vmM64$O> zBM1U!XJ>I;m#3b33MnPu`qsCYn3!OGex8Me1w)?VJhobEW@ct+Hk*9wTi+s|&+`kv z@Czn%^v)ez*X8)}Go$_V^o=9z%IhA^$<&`LM^PltL**5CrsliHdTV zvUNMH^kh!iL9OZa($-?t=RmF9sMpfZ*>QC`!#RtE5cs~gYg`b}@9&)&r`>8o4CrZq zmDU;H@9*kA+s5X`+E_L@fuq3lht{FdXzXjWOrDKJ4A1j;=bd*DLNGBg!86Z1!}aUe zdGg68dGpOT0l0npHnwfk?RL3(^=c|;)oLbb+O1o+n4X@dTCK9Vxyj|rm(9&ey&k!o zNx$hhPI^yYrBeCGwMBcCqjVnJtG%Q0;o6_g8-$7t!d}HLlhbG$``I53)AxR38mj>l z!{dA;cl<+)aqMs7SgFLoH#IfI;^HE{@6+venVOoS+wF4i-o0JMzj19OGDsqT?=^^| z&S5s=aBFdN_ewvEJM%$+w4b5zFj|+#G4D~^z+uLJ*fsko=XKE7_MGd>FTcE{wVoMm z2uuv{@KwRFDl1kC9>qy|)UgI1rF-~6ZNbsGu|KSJ`lDL2pX9NPEB}8ee7F9qg5?MR O0000=x}o)VD=23xZGidKsJj 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

    &}XJ7y^uLKL|l(=^=~M7SI1ZoeQx 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

  • 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 Q6aWAK07*qoM6N<$g5iQW;Q#;t literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/furbabyrescue.png b/docs/3.3.x/docs/images/apps/furbabyrescue.png new file mode 100644 index 0000000000000000000000000000000000000000..79dafc640738444c01883ac66e8f0f2584a45a57 GIT binary patch literal 49891 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/geeklist.png b/docs/3.3.x/docs/images/apps/geeklist.png new file mode 100644 index 0000000000000000000000000000000000000000..c6579c12f6f37e10ab1a3f667e33f70fbdc87173 GIT binary patch literal 27911 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 /dev/null + then + echo waiting for manual firefox shutdown... + fi + + while true; do + if ps ax | grep -v grep | grep firefox > /dev/null + then + sleep 1 + else + break + fi + done + echo firefox shutdown detected +} + +if test -z "$1" +then + while read line + do + func $line + done < urls +else + func $1 "$2" +fi + diff --git a/docs/3.3.x/docs/images/apps/growthegamegolf.png b/docs/3.3.x/docs/images/apps/growthegamegolf.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d6e9fb7493ce38c487cb2f31416838fe063bb6 GIT binary patch literal 43441 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/h_learnboost.png b/docs/3.3.x/docs/images/apps/h_learnboost.png new file mode 100644 index 0000000000000000000000000000000000000000..2940dc31489e2f0db0857ecf2c32a2dabb907b69 GIT binary patch literal 12727 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/h_mcds.png b/docs/3.3.x/docs/images/apps/h_mcds.png new file mode 100644 index 0000000000000000000000000000000000000000..1ac655377ad9e784895c1d0ac1e74d46d4949752 GIT binary patch literal 3904 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 O0000D_X* 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/kyyti.png b/docs/3.3.x/docs/images/apps/kyyti.png new file mode 100644 index 0000000000000000000000000000000000000000..f74d98da1346a95376b33f6bc6118e8864261b4b GIT binary patch literal 41966 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 ^!Ew8_;FrDA-Jwjzfp_2R2 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/learnboost.png b/docs/3.3.x/docs/images/apps/learnboost.png new file mode 100644 index 0000000000000000000000000000000000000000..a6c33c8bd41f9806ab255e4afe5e0187c65810fe GIT binary patch literal 31434 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/linkr.png b/docs/3.3.x/docs/images/apps/linkr.png new file mode 100644 index 0000000000000000000000000000000000000000..62dc5f6c51174c77fdc4356a7f442e95cf8fb6ad GIT binary patch literal 6428 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/lists.png b/docs/3.3.x/docs/images/apps/lists.png new file mode 100644 index 0000000000000000000000000000000000000000..a0f48c63b1eb40fa7cab3c8384ed97834c621e21 GIT binary patch literal 697 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
  • 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 T655ph=X$5122!n4wvPBe3)j3P literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/mcdonalds.png b/docs/3.3.x/docs/images/apps/mcdonalds.png new file mode 100644 index 0000000000000000000000000000000000000000..28a1bbf0bc13f1d3728ad42e53a04eb669f14517 GIT binary patch literal 57481 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

    kEHs_LGe?wKJuGaPCdM8l?nCCj!TI01$Q7!ES* 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/nextdays.png b/docs/3.3.x/docs/images/apps/nextdays.png new file mode 100644 index 0000000000000000000000000000000000000000..9ca96fe961a84f3df23513aa4ceeef52bddbf91c GIT binary patch literal 35067 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

    w5Dis*m_y7@7D1e4 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/nuorder.png b/docs/3.3.x/docs/images/apps/nuorder.png new file mode 100644 index 0000000000000000000000000000000000000000..da4cf597aae0b92aff5c13b2638ec7edc997705d GIT binary patch literal 38163 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 Ef(FYGSO5S3 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/scottyapp.png b/docs/3.3.x/docs/images/apps/scottyapp.png new file mode 100644 index 0000000000000000000000000000000000000000..d5142f34601224e550deb71b93313497f5720cf8 GIT binary patch literal 118416 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 Dx(}}{ literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/seelio.png b/docs/3.3.x/docs/images/apps/seelio.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e7a8e65abae0ad30c3db0a00782d8b1d54ce9c GIT binary patch literal 24005 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 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/selectvids.png b/docs/3.3.x/docs/images/apps/selectvids.png new file mode 100644 index 0000000000000000000000000000000000000000..9ba693a6a156164f547eb4b615afaa43a2475a81 GIT binary patch literal 42214 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 KMNUMnLSTZ(DAHH} literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/sharelatex.png b/docs/3.3.x/docs/images/apps/sharelatex.png new file mode 100644 index 0000000000000000000000000000000000000000..e3ef6dd25e1f81de2a170ede0e3a3665fe98b80d GIT binary patch literal 19707 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 w+RWv0lh6Ai#~9=x}o)VD=23xZGidKsJj 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

    UgJe6f|Y=Yr! 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 M07*qoM6N<$f<=x}o)VD=23xZGidKsJj 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 P00000NkvXXu0mjfkLXIi literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/stachify.png b/docs/3.3.x/docs/images/apps/stachify.png new file mode 100644 index 0000000000000000000000000000000000000000..14a64c23af6ffe25419224c9e6313b366b925014 GIT binary patch literal 27783 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 DnZfGr literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/todaylaunch.png b/docs/3.3.x/docs/images/apps/todaylaunch.png new file mode 100644 index 0000000000000000000000000000000000000000..f75fba3bda92d1387dc24b7cb6d5eaa648fff69e GIT binary patch literal 33233 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 KMNUMnLSTZ9^9~09 literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/upcload.png b/docs/3.3.x/docs/images/apps/upcload.png new file mode 100644 index 0000000000000000000000000000000000000000..4199712ee7ca626e6f2b45800fce43336a6da398 GIT binary patch literal 37792 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 C>_hDU literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/apps/wavo.png b/docs/3.3.x/docs/images/apps/wavo.png new file mode 100644 index 0000000000000000000000000000000000000000..3ab6bb877c1b05a6f2f20a8cd697bc21ee84a7aa GIT binary patch literal 54906 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

    Getting Started

    First be sure you have MongoDB and Nodejs installed.

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. +The first thing we need to do is include mongoose in our project and open a connection.

    var mongoose = require('mongoose')
    +  , db = mongoose.createConnection('localhost', 'test');

    We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    db.on('error', console.error.bind(console, 'connection error:'));
    +db.once('open', function () {
    +  // yay!
    +});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = new mongoose.Schema({
    +    name: String
    +})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a model.

    var Kitten = db.model('Kitten', kittySchema)

    A model is a class with which we construct documents. +In this case, each document will be a kitten with properties and behaviors as declared in our schema. +Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    +console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    kittySchema.methods.speak = function () {
    +  var greeting = this.name
    +    ? "Meow name is " + this.name
    +    : "I don't have a name"
    +  console.log(greeting);
    +}
    +
    +var Kitten = db.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    +fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. +Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err) {
    +  if (err) // TODO handle the error
    +  console.log('meow')
    +});

    Say time goes by and we want to display all the kittens we've seen. +We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    +  if (err) // TODO handle err
    +  console.log(kittens)
    +})

    We just logged all of the kittens in our db to the console. +If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax.

    Kitten.find({ name: /fluff/i }, callback)

    This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or api docs for more.

    diff --git a/docs/3.3.x/docs/index.jade b/docs/3.3.x/docs/index.jade new file mode 100644 index 00000000000..62462a8e7f9 --- /dev/null +++ b/docs/3.3.x/docs/index.jade @@ -0,0 +1,119 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose Quick Start v#{package.version} + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + link(href='css/guide.css', rel='stylesheet', type='text/css') + style. + body.api + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + #content + .module + h2 Getting Started + p + em + | First be sure you have + a(href="http://www.mongodb.org/downloads") MongoDB + | and + a(href="http://nodejs.org/") Nodejs + | installed. + p + | Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. + | The first thing we need to do is include mongoose in our project and open a connection. + :js + var mongoose = require('mongoose') + , db = mongoose.createConnection('localhost', 'test'); + p We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs: + :js + db.on('error', console.error.bind(console, 'connection error:')); + db.once('open', function () { + // yay! + }); + p Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback. + p + | With Mongoose, everything is derived from a + a(href="./api.html#schema_Schema") Schema + | . Let's get a reference to it and define our kittens. + :js + var kittySchema = new mongoose.Schema({ + name: String + }) + p + | So far so good. We've got a schema with one property, + code name + | , which will be a + code String + | . The next step is compiling our schema into a + a(href="./api.html#model_Model") model + | . + :js + var Kitten = db.model('Kitten', kittySchema) + p + | A model is a class with which we construct documents. + | In this case, each document will be a kitten with properties and behaviors as declared in our schema. + | Let's create a kitten document representing the little guy we just met on the sidewalk outside: + :js + var silence = new Kitten({ name: 'Silence' }) + console.log(silence.name) // 'Silence' + p Kittens can meow, so let's take a look at how to add "speak" functionality to our documents: + :js + kittySchema.methods.speak = function () { + var greeting = this.name + ? "Meow name is " + this.name + : "I don't have a name" + console.log(greeting); + } + + var Kitten = db.model('Kitten', kittySchema) + p + | Functions added to the + code methods + | property of a schema get compiled into the Model prototype and exposed on each document instance: + :js + var fluffy = new Kitten({ name: 'fluffy' }); + fluffy.speak() // "Meow name is fluffy" + p + | We have talking kittens! But we still haven't saved anything to MongoDB. + | Each document can be saved to the database by calling its + code save + | method. The first argument to the callback will be an error if any occured. + :js + fluffy.save(function (err) { + if (err) // TODO handle the error + console.log('meow') + }); + p + | Say time goes by and we want to display all the kittens we've seen. + | We can access all of the kitten documents through our Kitten model. + :js + Kitten.find(function (err, kittens) { + if (err) // TODO handle err + console.log(kittens) + }) + p + | We just logged all of the kittens in our db to the console. + | If we want to filter our kittens by name, Mongoose supports MongoDbs rich querying syntax. + :js + Kitten.find({ name: /fluff/i }, callback) + p + | This performs a case-insensitive search for all documents with a name property containing "fluff" and returns the results to the callback. + h3 Congratulations + p + | That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the + a(href="guide.html") guide + | , or + a(href="api.html") api docs + | for more. + script. + document.body.className = 'load'; + include includes/keen diff --git a/docs/3.3.x/docs/js/cookies.min.js b/docs/3.3.x/docs/js/cookies.min.js new file mode 100644 index 00000000000..dc94dbc5bbc --- /dev/null +++ b/docs/3.3.x/docs/js/cookies.min.js @@ -0,0 +1,4 @@ +/*! Cookies.js - 0.2.0; Copyright (c) 2012, Scott Hamper; http://www.opensource.org/licenses/MIT */ +(function(f,e){var b=function(c,d,a){return 1===arguments.length?b.get(c):b.set(c,d,a)};b.get=function(c){f.cookie!==b._cacheString&&b._populateCache();return b._cache[c]};b.defaults={path:"/"};b.set=function(c,d,a){a={path:a&&a.path||b.defaults.path,domain:a&&a.domain||b.defaults.domain,expires:a&&a.expires||b.defaults.expires,secure:a&&a.secure!==e?a.secure:b.defaults.secure};d===e&&(a.expires=-1);switch(typeof a.expires){case "number":a.expires=new Date((new Date).getTime()+1E3*a.expires);break; +case "string":a.expires=new Date(a.expires)}c=encodeURIComponent(c)+"="+(d+"").replace(/[^!#-+\--:<-[\]-~]/g,encodeURIComponent);c+=a.path?";path="+a.path:"";c+=a.domain?";domain="+a.domain:"";c+=a.expires?";expires="+a.expires.toGMTString():"";c+=a.secure?";secure":"";f.cookie=c;return b};b.expire=function(c,d){return b.set(c,e,d)};b._populateCache=function(){b._cache={};b._cacheString=f.cookie;for(var c=b._cacheString.split("; "),d=0;d>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.3.x/docs/layout.jade b/docs/3.3.x/docs/layout.jade new file mode 100644 index 00000000000..ab1e9553cbe --- /dev/null +++ b/docs/3.3.x/docs/layout.jade @@ -0,0 +1,25 @@ +doctype html +html(lang='en') + head + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") + title Mongoose #{title} v#{package.version} + block style + link(href='http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700', rel='stylesheet', type='text/css') + link(href='css/default.css', rel='stylesheet', type='text/css') + link(href='css/guide.css', rel='stylesheet', type='text/css') + body + a#forkbanner(href="http://github.com/learnboost/mongoose") + img(style="position: absolute; top: 0; right: 0; border: 0;", src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png", alt="Fork me on GitHub") + #links + #header + h1 + a(href="../index.html") + .mongoose Mongoose + include includes/nav + #content + .module + block content + script. + document.body.className = 'load'; + include includes/keen diff --git a/docs/3.3.x/docs/middleware.html b/docs/3.3.x/docs/middleware.html new file mode 100644 index 00000000000..b9b3e244ca4 --- /dev/null +++ b/docs/3.3.x/docs/middleware.html @@ -0,0 +1,29 @@ +Mongoose Middleware v3.3.1Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

    +There are two types of middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next

    var schema = new Schema(..);
    +schema.pre('save', function (next) {
    +  // do stuff
    +  next();
    +});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    +schema.pre('save', true, function (next, done) {
    +  // calling next kicks off the next middleware in parallel
    +  next();
    +  doAsync(done);
    +});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    +  var err = new Error('something went wrong');
    +  next(err);
    +});
    +
    +// later...
    +
    +myModel.save(function (err) {
    +  console.log(err.message) // something went wrong
    +});
    +

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    diff --git a/docs/3.3.x/docs/middleware.jade b/docs/3.3.x/docs/middleware.jade new file mode 100644 index 00000000000..b9e9e9eca94 --- /dev/null +++ b/docs/3.3.x/docs/middleware.jade @@ -0,0 +1,74 @@ +extends layout + +block content + h2 Middleware + p + | Middleware are functions which are passed control of flow during execution of + a(href="./api.html#document_Document-init") init + |, + a(href="./api.html#document_Document-validate") validate + |, + a(href="./api.html#model_Model-save") save + | and + a(href="./api.html#model_Model-remove") remove + | methods. + p + | There are two types of middleware, serial and parallel. + h4 Serial + p + | Serial middleware are executed one after another, when each middleware calls + code next + :js + var schema = new Schema(..); + schema.pre('save', function (next) { + // do stuff + next(); + }); + h4 Parallel + p + | Parallel middleware offer more fine-grained flow control. + :js + var schema = new Schema(..); + schema.pre('save', true, function (next, done) { + // calling next kicks off the next middleware in parallel + next(); + doAsync(done); + }); + p + | The hooked method, in this case + code save + |, will not be executed until + code done + | is called by each middleware. + h4 Use Cases + p + | Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas: + ul + li complex validation + li + | removing dependent documents + ul + li (removing a user removes all his blogposts) + li asynchronous defaults + li asynchronous tasks that a certain action triggers + ul + li triggering custom events + li notifications + h4 Error handling + :markdown + If any middleware calls `next` or `done` with an `Error` instance, the flow is interrupted, and the error is passed to the callback. + :js + schema.pre('save', function (next) { + var err = new Error('something went wrong'); + next(err); + }); + + // later... + + myModel.save(function (err) { + console.log(err.message) // something went wrong + }); + + h3#next Next Up + :markdown + Now that we've covered `middleware`, let's take a look at Mongoose's approach to faking JOINs with its query [population](/docs/populate.html) helper. diff --git a/docs/3.3.x/docs/migration.html b/docs/3.3.x/docs/migration.html new file mode 100644 index 00000000000..dec9b499446 --- /dev/null +++ b/docs/3.3.x/docs/migration.html @@ -0,0 +1,40 @@ +Mongoose Migration Guide v3.3.1Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    + +

    Here are the removed methods are their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    + +

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    • are now strict by default.
    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    + +

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    + +
    • $inc
    • $increment
    • $decrement
    + +

    If you really want this behavior back, include the mongoose-number module in your project.

    + +

    A good alternative is to start using the new findAndModify helpers. +Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    +...
    +Inventory.findById(id, function (err, inventory) {
    +  if (err) return handleError(err);
    +  inventory.productCount.$decrement(7);
    +  inventory.save(function (err) {
    +    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    +    if (err) return handleError(err);
    +    res.send(inventory.productCount); // 3
    +  });
    +});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    +  if (err) return handleError(err);
    +  res.send(inventory.productCount); // 3
    +});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This change allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    More Info

    Related blog posts:

    + +
    diff --git a/docs/3.3.x/docs/migration.jade b/docs/3.3.x/docs/migration.jade new file mode 100644 index 00000000000..988c6964f85 --- /dev/null +++ b/docs/3.3.x/docs/migration.jade @@ -0,0 +1,280 @@ +extends layout + +block append style + style. + table td { + padding-right: 15px; + } + +block content + h2 Migrating from 2.x to 3.x + :markdown + Migrating from Mongoose 2.x to 3.x brings with it [several changes](https://github.com/LearnBoost/mongoose/blob/master/History.md) to be aware of: + + h3 Query clean-up + :markdown + Many methods of the [Query](./api.html#query-js) API were nothing but aliases and have been [removed](https://github.com/LearnBoost/mongoose/commit/1149804c) in an effort to keep Mongoose clean and focused on there being as close to [one way](http://www.python.org/dev/peps/pep-0020/) of doing things as possible. If you really love all that extra noise, you can bring most of it back with [this module](https://github.com/aheckmann/mongoose-v2-compat). + + Here are the removed methods are their still existing aliases: + table + thead + tr(style='text-align:left') + th Removed + th Alternative + tbody + tr + td + code query.run + td + code query.exec + tr + td + code query.$or + td + code query.or + tr + td + code query.$nor + td + code query.nor + tr + td + code query.$gt + td + code query.gt + tr + td + code query.$gte + td + code query.gte + tr + td + code query.$lt + td + code query.lt + tr + td + code query.$lte + td + code query.lte + tr + td + code query.$ne + td + code query.ne + tr + td + code query.$in + td + code query.in + tr + td + code query.$nin + td + code query.nin + tr + td + code query.$all + td + code query.all + tr + td + code query.$regex + td + code query.regex + tr + td + code query.$size + td + code query.size + tr + td + code query.$maxDistance + td + code query.maxDistance + tr + td + code query.$mod + td + code query.mod + tr + td + code query.$near + td + code query.near + tr + td + code query.$exists + td + code query.exists + tr + td + code query.$elemMatch + td + code query.elemMatch + tr + td + code query.$within + td + code query.within + tr + td + code query.$box + td + code query.box + tr + td + code query.$center + td + code query.center + tr + td + code query.$centerSphere + td + code query.centerSphere + tr + td + code query.$slice + td + code query.slice + tr + td + code query.notEqualTo + td + code query.ne + tr + td + code query.wherein + td + code query.within + tr + td + code query.asc + td + code + | query.sort + a(href="#asc") * + tr + td + code query.desc + td + code + | query.sort + a(href="#desc") * + tr + td + code query.fields + td + code + | query.select + a(href="#fields") * + + h4#asc query#asc + :markdown + The `asc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#desc query#desc + :markdown + The `desc` method of [Query](./api.html#query-js) has been removed in favor of [sort](./api.html#query_Query-sort). The `sort` method accepts slightly different arguments so read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#sort query#sort + :markdown + The [sort](./api.html#query_Query-sort) method of [Queries](./api.html#query-js) now accepts slightly different arguments. Read the [docs](./api.html#query_Query-sort) to make sure your application is all set. + h4#fields query#fields + :markdown + The `fields` method of [Query](./api.html#query-js) has been removed, it being mostly an alias for the [select](./api.html#query_Query-select) method anyway. The `select` method has slightly different arguments so read the [docs](./api.html#query_Query-select) to make sure your application is all set. + + Because of the change to the `fields` method, the field selection argument for [query.populate](./api.html#query_Query-populate) and model methods like [findById](./api.html#model_Model-findById), [find](./api.html#model_Model-find), etc, is slightly different as well (no longer accepts arrays for example), so read the [docs](./api.html#query_Query-select) to make sure your application is all set. + + h3 Connecting to ReplicaSets + :markdown + To connect to a [ReplicaSet](http://www.mongodb.org/display/DOCS/Replica+Sets) you no longer use the separate `connectSet` or `createSetConnection` methods. Both [mongoose.connect](./api.html#index_Mongoose-connect) and [mongoose.createConnection](./api.html#index_Mongoose-createConnection) are now smart enough to just do the right thing with your connection string. If you really want to bring `connectSet` and `createSetConnection` back use [this module](https://github.com/aheckmann/mongoose-v2-compat). + + h3 Schemas + :markdown + - are now [strict](./guide.html#strict) by default. + - Arrays of [object literal](./subdocs.html#altsyntax) now creates document arrays instead of arrays of [Mixed](./schematypes.html#mixed). + - Indexes are now created in [background](./guide.html#autoIndex) by default. + - Index errors are now emitted on their model instead of the connection. See issue [#984](https://github.com/LearnBoost/mongoose/issues/984). + + h3#arrays Arrays + :markdown + - [pop](./api.html#types_array_MongooseArray-pop) is now fixed causing a $set of the entire array. + - [$pop](./api.html#types_array_MongooseArray-%24pop) is now fixed and behaves just as MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the last element of the array. + - [shift](./api.html#types_array_MongooseArray-shift) is now fixed causing a $set of the entire array. + - [$shift](./api.html#types_array_MongooseArray-%24shift) is now fixed and behaves just as a [MongoDB $pop -1](http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop) does, removing at most the first element of array. + - `$unshift` was removed, use [unshift](./api.html#types_array_MongooseArray-unshift) instead. + - `$addToSet` was removed, use [addToSet](./api.html#types_array_MongooseArray-addToSet) instead. + - `$pushAll` was removed, use [push](./api.html#types_array_MongooseArray-push) instead. + - `$pull` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. + - `$pullAll` was removed, use [pull](./api.html#types_array_MongooseArray-pull) instead. + - `doAtomics` was changed to the [hasAtomics](./api.html#types_array_MongooseArray-hasAtomics) private method + + h3#mongoosenumber Number type + :markdown + The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused [too many problems](https://groups.google.com/d/msg/mongoose-orm/syKlN2xL1EE/FfRFhEFj4KcJ) when doing comparisons and had other bad side-effects. + + With it out of the picture, the following helper methods of MongooseNumbers are now also gone: + + - $inc + - $increment + - $decrement + + If you really want this behavior back, include the [mongoose-number](https://github.com/aheckmann/mongoose-number) module in your project. + + A good alternative is to start using the new [findAndModify](./api.html#model_Model-findOneAndUpdate) [helpers](./api.html#model_Model-findOneAndRemove). + Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber: + :js + var inventorySchema = new Schema({ productCount: Number }); + ... + Inventory.findById(id, function (err, inventory) { + if (err) return handleError(err); + inventory.productCount.$decrement(7); + inventory.save(function (err) { + // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback); + if (err) return handleError(err); + res.send(inventory.productCount); // 3 + }); + }); + :markdown + With MongooseNumber out of the picture, we'll instead use the [Account.findByIdAndUpdate](./api.html#model_Model-findByIdAndUpdate) helper: + :js + Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) { + if (err) return handleError(err); + res.send(inventory.productCount); // 3 + }); + :markdown + The `findByIdAndUpdate` helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases. + + h3#documents Documents + :markdown + - `doc#commit` is now removed, use [doc.markModified](./api.html#document_Document-markModified) instead + - [doc#modifiedPaths](./api.html#document_Document-modifiedPaths) is now a method not a getter + - `doc.modified` is now removed, use [doc.isModified](./api.html#document_Document-isModified) instead + + h4#gettercasting getter casting + :markdown + Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue [#820](https://github.com/LearnBoost/mongoose/issues/820) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). + + h4#setterorder setter order + :markdown + Values being set no longer cast until _after_ all setters have been applied. Previously the value returned from each setter was cast _before_ passing it on to the next setter. This change allows more flexible processing of values in setters. See issue [#665](https://github.com/learnboost/mongoose/issues/665) and pull [#924](https://github.com/LearnBoost/mongoose/pull/924). + + h3#subdocs Subdocuments + :markdown + - `subdoc.parent` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parent). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). + - `subdoc.parentArray` was changed from a property to a [method](./api.html#types_embedded_EmbeddedDocument-parentArray). See issue [#928](https://github.com/LearnBoost/mongoose/issues/928). + + h3#stringmatch String match validator + :markdown + The String SchemaType [match](./api.html#schema_string_SchemaString-match) validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the [required](./api.html#schematype_SchemaType-required) validator as well. See issue [#934](https://github.com/LearnBoost/mongoose/issues/934) and pull request [#935](https://github.com/LearnBoost/mongoose/pull/935). + + h3#version Versioning + :markdown + Documents are now transparently versioned. Read the in depth details [here](http://aaronheckmann.posterous.com/tag/versioning). + + h3#moreinfo More Info + :markdown + Related blog posts: + + - [Mongoose v3 released](http://aaronheckmann.posterous.com/mongoose-v3-released) + - [API changes](http://aaronheckmann.posterous.com/mongoose-v3-part-3-api-changes) + - [FindAndModify](http://aaronheckmann.posterous.com/mongoose-v3-part-2-findandmodify) diff --git a/docs/3.3.x/docs/models.html b/docs/3.3.x/docs/models.html new file mode 100644 index 00000000000..e507b8ab97b --- /dev/null +++ b/docs/3.3.x/docs/models.html @@ -0,0 +1,32 @@ +Mongoose Models v3.3.1Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var schema = new Schema({ name: 'string', size: 'string' });
    +var Tank = mongoose.model('Tank', schema);
    +
    +// or, if you are using separate connections
    +var db = mongoose.createConnection(..);
    +var Tank = db.model('Tank', schema);
    +

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = db.model('Tank', yourSchema);
    +
    +var small = new Tank({ size: 'small' });
    +small.save(function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +
    +// or
    +
    +Tank.create({ size: 'small' }, function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    +  if (err) return handleError(err);
    +  // removed!
    +});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at Documents.

    diff --git a/docs/3.3.x/docs/models.jade b/docs/3.3.x/docs/models.jade new file mode 100644 index 00000000000..105ef327803 --- /dev/null +++ b/docs/3.3.x/docs/models.jade @@ -0,0 +1,61 @@ +extends layout + +block content + h2 Models + :markdown + [Models](./api.html#model-js) are fancy constructors compiled from our `Schema` definitions. Instances of these models represent [documents](./documents.html) which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models. + + h3 Compiling your first model + :js + var schema = new Schema({ name: 'string', size: 'string' }); + var Tank = mongoose.model('Tank', schema); + + // or, if you are using separate connections + var db = mongoose.createConnection(..); + var Tank = db.model('Tank', schema); + + h3 Constructing documents + :markdown + [Documents](./documents.html) are instances of our model. Creating them and saving to the database is easy: + :js + var Tank = db.model('Tank', yourSchema); + + var small = new Tank({ size: 'small' }); + small.save(function (err) { + if (err) return handleError(err); + // saved! + }) + + // or + + Tank.create({ size: 'small' }, function (err) { + if (err) return handleError(err); + // saved! + }) + + h3 Querying + :markdown + Finding documents is easy with Mongoose, which supports the [rich](http://www.mongodb.org/display/DOCS/Advanced+Queries) query syntax of MongoDB. Documents can be retreived using each `models` [find](./api.html#model_Model-find), [findById](./api.html#model_Model-findById), [findOne](./api.html#model_Model-findOne), or [where](./api.html#model_Model-where) static methods. + + :js + Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback); + :markdown + See the chapter on [querying](./queries.html) for more details on how to use the [Query](./api.html#query-js) api. + h3 Removing + :markdown + Models have a static `remove` method available for removing all documents matching `conditions`. + :js + Tank.remove({ size: 'large' }, function (err) { + if (err) return handleError(err); + // removed! + }); + h3 Updating + :markdown + Each `model` has its own `update` method for modifying documents in the database without returning them to your application. See the [API](./api.html#model_Model-update) docs for more detail. + h3 Yet more + :markdown + The [API docs](./api.html#model_Model) cover many additional methods available like [count](./api.html#model_Model-count), [mapReduce](./api.html#model_Model-mapReduce), [aggregate](./api.html#model_Model-aggregate), and more. + + h3#next Next Up + :markdown + Now that we've covered `Models`, let's take a look at [Documents](/docs/documents.html). diff --git a/docs/3.3.x/docs/plugins.html b/docs/3.3.x/docs/plugins.html new file mode 100644 index 00000000000..74429a0022d --- /dev/null +++ b/docs/3.3.x/docs/plugins.html @@ -0,0 +1,33 @@ +Mongoose Plugins v3.3.1Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    + +

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    +module.exports = exports = function lastModifiedPlugin (schema, options) {
    +  schema.add({ lastMod: Date })
    +  
    +  schema.pre('save', function (next) {
    +    this.lastMod = new Date
    +    next()
    +  })
    +  
    +  if (options && options.index) {
    +    schema.path('lastMod').index(options.index)
    +  }
    +}
    +
    +// game-schema.js
    +var lastMod = require('./lastMod');
    +var Game = new Schema({ ... });
    +Game.plugin(lastMod, { index: true });
    +
    +// player-schema.js
    +var lastMod = require('./lastMod');
    +var Player = new Schema({ ... });
    +Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    diff --git a/docs/3.3.x/docs/plugins.jade b/docs/3.3.x/docs/plugins.jade new file mode 100644 index 00000000000..4930fd8a46e --- /dev/null +++ b/docs/3.3.x/docs/plugins.jade @@ -0,0 +1,42 @@ +extends layout + +block content + h2 Plugins + :markdown + Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature. + + Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each `Schema`: + + :js + // lastMod.js + module.exports = exports = function lastModifiedPlugin (schema, options) { + schema.add({ lastMod: Date }) + + schema.pre('save', function (next) { + this.lastMod = new Date + next() + }) + + if (options && options.index) { + schema.path('lastMod').index(options.index) + } + } + + // game-schema.js + var lastMod = require('./lastMod'); + var Game = new Schema({ ... }); + Game.plugin(lastMod, { index: true }); + + // player-schema.js + var lastMod = require('./lastMod'); + var Player = new Schema({ ... }); + Player.plugin(lastMod); + :markdown + We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code. + h3 Community! + :markdown + Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to [npm](https://npmjs.org/) and [tagged](https://npmjs.org/doc/tag.html) with `mongoose` will show up on our [search results](http://plugins.mongoosejs.com) page. + + h3#next Next Up + :markdown + Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help [contribute](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md) to the continuing development of Mongoose itself. diff --git a/docs/3.3.x/docs/populate.html b/docs/3.3.x/docs/populate.html new file mode 100644 index 00000000000..3d0a4de8e8a --- /dev/null +++ b/docs/3.3.x/docs/populate.html @@ -0,0 +1,104 @@ +Mongoose Query Population v3.3.1Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    + +

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    +  , Schema = mongoose.Schema
    +  
    +var PersonSchema = new Schema({
    +  name    : String,
    +  age     : Number,
    +  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    +});
    +
    +var StorySchema = new Schema({
    +  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    +  title    : String,
    +  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    +});
    +
    +var Story  = mongoose.model('Story', StorySchema);
    +var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    +
    +aaron.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  var story1 = new Story({
    +    title: "Once upon a timex.",
    +    _creator: aaron._id    // assign an ObjectId
    +  });
    +  
    +  story1.save(function (err) {
    +    if (err) return handleError(err);
    +    // thats it!
    +  });
    +})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    +.findOne({ title: /timex/ })
    +.populate('_creator')
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    +})
    +

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    + +

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    +.findOne({ title: /timex/i })
    +.populate('_creator', 'name') // only return the Persons name
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  
    +  console.log('The creator is %s', story._creator.name);
    +  // prints "The creator is Aaron"
    +  
    +  console.log('The creators age is %s', story._creator.age);
    +  // prints "The creators age is null'
    +})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    +.find(...)
    +.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    + +

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    +aaron.save();

    This allows us to perform a find and populate combo:

    Person
    +.findOne({ name: 'Aaron' })
    +.populate('stories') // only works if we pushed refs to children
    +.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log(person);
    +})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    +.find({ _creator: aaron._id })
    +.populate('_creator') // not really necessary
    +.exec(function (err, stories) {
    +  if (err) return handleError(err);
    +  console.log('The stories are an array: ', stories);
    +})
    +

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    +guille.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  story._creator = guille; // or guille._id
    +  
    +  story.save(function (err) {
    +    if (err) return handleError(err);
    +    
    +    Story
    +    .findOne({ title: /timex/i })
    +    .populate('_creator', 'name')
    +    .exec(function (err, story) {
    +      if (err) return handleError(err);
    +      
    +      console.log('The creator is %s', story._creator.name)
    +      // prints "The creator is Guillermo"
    +    })
    +  })
    +})
    +

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    +Story.findOne(..).populate('_creator', 'name age').exec(..);
    +
    +// this doesn't
    +Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
    +

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at connections.

    diff --git a/docs/3.3.x/docs/populate.jade b/docs/3.3.x/docs/populate.jade new file mode 100644 index 00000000000..5443bbbcc28 --- /dev/null +++ b/docs/3.3.x/docs/populate.jade @@ -0,0 +1,164 @@ +extends layout + +block content + h2 Query Population + :markdown + There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. + + `ObjectIds` can refer to another document in a collection within our database and be `populate()`d when querying: + :js + var mongoose = require('mongoose') + , Schema = mongoose.Schema + + var PersonSchema = new Schema({ + name : String, + age : Number, + stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] + }); + + var StorySchema = new Schema({ + _creator : { type: Schema.Types.ObjectId, ref: 'Person' }, + title : String, + fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }] + }); + + var Story = mongoose.model('Story', StorySchema); + var Person = mongoose.model('Person', PersonSchema); + :markdown + So far we've created two `models`. Our `Person` model has it's `stories` field set to an array of `ObjectId`s. The `ref` option is what tells Mongoose in which model to look, in our case the `Story` model. All `_id`s we store here must be document _ids from the `Story` model. We also added a `_creator` `ObjectId` to our `Story` schema which refers to a single `Person`. + h3 Saving refs + :markdown + Saving refs to other documents works the same way you normally save objectids, just assign an `ObjectId`: + :js + var aaron = new Person({ name: 'Aaron', age: 100 }); + + aaron.save(function (err) { + if (err) return handleError(err); + + var story1 = new Story({ + title: "Once upon a timex.", + _creator: aaron._id // assign an ObjectId + }); + + story1.save(function (err) { + if (err) return handleError(err); + // thats it! + }); + }) + h3 Population + :markdown + So far we haven't done anything special. We've merely created a `Person` and a `Story`. Now let's take a look at populating our story's `_creator`: + :js + Story + .findOne({ title: /timex/ }) + .populate('_creator') + .exec(function (err, story) { + if (err) return handleError(err); + console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron" + }) + + :markdown + Populated paths are no longer set to their original `ObjectId`s, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results. + + Arrays of `ObjectId` refs work the same way. Just call the [populate](./api.html#query_Query-populate) method on the query and an array of documents will be returned _in place_ of the `ObjectIds`. + + h3 Field selection + :markdown + What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual [field name syntax](./api.html#query_Query-select) as the second argument to the populate method: + :js + Story + .findOne({ title: /timex/i }) + .populate('_creator', 'name') // only return the Persons name + .exec(function (err, story) { + if (err) return handleError(err); + + console.log('The creator is %s', story._creator.name); + // prints "The creator is Aaron" + + console.log('The creators age is %s', story._creator.age); + // prints "The creators age is null' + }) + h3 Query conditions for populate + :markdown + What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them? + :js + Story + .find(...) + .populate('fans', null, { age: { $gte: 21 }}, { limit: 5 }) + :markdown + Done. `Conditions` and `options` for populate queries are passed as the third and fourth arguments respectively. + h3 Refs to children + :markdown + We may find however, if we use the `aaron` object, we are unable to get a list of the stories. This is because no `story` objects were ever 'pushed' on to `aaron.stories`. + + There are two perspectives to this story. First, it's nice to have `aaron` know which are his stories. + :js + aaron.stories.push(story1); + aaron.save(); + :markdown + This allows us to perform a `find` and `populate` combo: + :js + Person + .findOne({ name: 'Aaron' }) + .populate('stories') // only works if we pushed refs to children + .exec(function (err, person) { + if (err) return handleError(err); + console.log(person); + }) + :markdown + However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely `find()` the documents we are interested in. + :js + Story + .find({ _creator: aaron._id }) + .populate('_creator') // not really necessary + .exec(function (err, stories) { + if (err) return handleError(err); + console.log('The stories are an array: ', stories); + }) + + h3 Updating refs + :markdown + Now that we have a `story` we realized that the `_creator` was incorrect. We can update `ObjectId` refs the same as any other property through the magic of Mongoose's internal casting: + :js + var guille = new Person({ name: 'Guillermo' }); + guille.save(function (err) { + if (err) return handleError(err); + + story._creator = guille; // or guille._id + + story.save(function (err) { + if (err) return handleError(err); + + Story + .findOne({ title: /timex/i }) + .populate('_creator', 'name') + .exec(function (err, story) { + if (err) return handleError(err); + + console.log('The creator is %s', story._creator.name) + // prints "The creator is Guillermo" + }) + }) + }) + + h4 NOTE: + :markdown + The documents returned from calling [populate](./api.html#query_Query-populate) become fully functional, `remove`able, `save`able documents. Do not confuse them with [sub docs](./subdocs.html). Take caution when calling its remove method because you'll be removing it from the database, not just the array. + + h4 NOTE: + :markdown + _Field selection_ in v3 is slightly different than v2. Arrays of fields are no longer accepted. + + :js + // this works + Story.findOne(..).populate('_creator', 'name age').exec(..); + + // this doesn't + Story.findOne(..).populate('_creator', ['name', 'age']).exec(..); + + :markdown + See the [migration guide](./migration.html#fields) for more detail. + + h3#next Next Up + :markdown + Now that we've covered query population, let's take a look at [connections](/docs/connections.html). diff --git a/docs/3.3.x/docs/prior.html b/docs/3.3.x/docs/prior.html new file mode 100644 index 00000000000..7968715028f --- /dev/null +++ b/docs/3.3.x/docs/prior.html @@ -0,0 +1,9 @@ +Mongoose v3.3.1Fork me on GitHub

    Prior Release Documentation

    diff --git a/docs/3.3.x/docs/prior.jade b/docs/3.3.x/docs/prior.jade new file mode 100644 index 00000000000..1ef7d088a72 --- /dev/null +++ b/docs/3.3.x/docs/prior.jade @@ -0,0 +1,8 @@ +extends layout + +block content + h2 Prior Release Documentation + ul + each release in releases + li + a(href=release.url)= release.version diff --git a/docs/3.3.x/docs/production.html b/docs/3.3.x/docs/production.html new file mode 100644 index 00000000000..f7da97ec7e1 --- /dev/null +++ b/docs/3.3.x/docs/production.html @@ -0,0 +1,9 @@ +Mongoose Production v3.3.1Fork me on GitHub

    Mongoose In The Wild (add your project)

    • LearnBoost is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students.
    • Storify lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative.
    • Geeklist is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found.
    • ClickDummy is a rapid mockup prototyping application for designers and dummies.
    • Scotty App allows you to create data driven backends for your apps in minutes instead of weeks.
    • Bozuko is an exciting customer rewards program.
    • Call List helps you maintain a todo list for people you need to call.
    • Grow The Game Golf lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more.
    • nextdays lets you share plans with friends and discover what is happening around you.
    • AtticTV is Music Television (MTV) for the web.
    • LocalResponse helps marketers respond to real-time consumer intent.
    • Select Vids is a collection of amazing, funny, and creative videos for you to discover.
    • cldfy delivers mail to your app.
    • ShareLatex is a real-time LaTeX collaboration tool.
    • Cyborg Vision uses real-time facial recognition to identify your friends and show their information.
    • Wavo lets you express yourself through the songs you love.
    • seelio is a stage for college students to distinguish themselves and connect with companies.
    • TodayLaunch is a free dashboard for your social media accounts.
    • Stachify
    • Skim is a playful way to meet new people.
    • NuORDER online fashion wholesale for brands and buyers.
    • UPcload helps you find clothes that fit you when shopping online.
    • TreinoSmart is a system for gym and physical trainers.
    • ShoeJitsu lets you shop, compare, and share fashion.
    • Kyyti is a meeting place for rides.
    • Nimble Quiz allows you to quickly create and manage simple multiple choice quizzes.
    • Fur Baby Rescue provides a temporary, safe home for cats, dogs, puppies and kittens.
    • McDonalds food, your questions answered.
    • SquadSheet is a sports app packed with fun and powerful social features.
    • VeriWalk is live GPS dog walking software.
    • DashKu lets you build real-time dashboards and widgets using HTML, CSS, and JavaScript.
    • First Impression helps singles find fun, safe and exciting dates.
    • Muffle is a suite of Twitter reputation management tools.
    • Zootify is a live, real-time YouTube party app.
    diff --git a/docs/3.3.x/docs/production.jade b/docs/3.3.x/docs/production.jade new file mode 100644 index 00000000000..da5c5f9d13e --- /dev/null +++ b/docs/3.3.x/docs/production.jade @@ -0,0 +1,11 @@ +extends layout + +block content + h2 + | Mongoose In The Wild + a(href='mailto:aaronheckmann+github@gmail.com?subject=Please add my project to mongoosejs.com', title='add/remove your project') (add your project) + ul.inthewild + each img in images + li + a(href=img.url, title=img.title + ' ' + img.desc) + img(src="images/apps/" + img.src + ".png", alt=img.title + ' ' + img.desc) diff --git a/docs/3.3.x/docs/queries.html b/docs/3.3.x/docs/queries.html new file mode 100644 index 00000000000..d2165946657 --- /dev/null +++ b/docs/3.3.x/docs/queries.html @@ -0,0 +1,41 @@ +Mongoose Queries v3.3.1Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    + +

    When a callback function:

    + +
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    + +

    Let's take a look at what happens when passing a callback:

    var Person = db.model('Person', yourSchema);
    +
    +// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    +Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    Here we see that the query was executed immediately and the results passed to our callback. +Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    +var query = Person.findOne({ 'name.last': 'Ghost' });
    +
    +// selecting the `name` and `occupation` fields
    +query.select('name occupation');
    +
    +// execute the query at a later time
    +query.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    +.find({ occupation: /host/ })
    +.where('name.last').equals('Ghost')
    +.where('age').gt(17).lt(66)
    +.where('likes').in(['vaporizing', 'talking'])
    +.limit(10)
    +.sort('-occupation')
    +.select('name occupation')
    +.exec(callback);
    +

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    diff --git a/docs/3.3.x/docs/queries.jade b/docs/3.3.x/docs/queries.jade new file mode 100644 index 00000000000..68c529efe25 --- /dev/null +++ b/docs/3.3.x/docs/queries.jade @@ -0,0 +1,62 @@ +extends layout + +block content + h2 Queries + :markdown + Documents can be retrieved through several static helper methods of [models](./models.html). + :markdown + Any [model](./api.html#model_Model) method which [involves](./api.html#model_Model-find) [specifying](./api.html#model_Model-findById) [query](./api.html#model_Model-count) [conditions](./api.html#model_Model-update) can be executed two ways: + + When a `callback` function: + + - is passed, the operation will be executed immediately with the results passed to the callback. + - is not passed, an instance of [Query](./api.html#query-js) is returned, which provides a special `QueryBuilder` interface for you. + + Let's take a look at what happens when passing a `callback`: + :js + var Person = db.model('Person', yourSchema); + + // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields + Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { + if (err) return handleError(err); + console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. + }) + :markdown + Here we see that the query was executed immediately and the results passed to our callback. + Now let's look at what happens when no `callback` is passed: + :js + // find each person with a last name matching 'Ghost' + var query = Person.findOne({ 'name.last': 'Ghost' }); + + // selecting the `name` and `occupation` fields + query.select('name occupation'); + + // execute the query at a later time + query.exec(function (err, person) { + if (err) return handleError(err); + console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host. + }) + :markdown + An instance of [Query](./api.html#query-js) was returned which allows us to build up our query. Taking this example further: + :js + Person + .find({ occupation: /host/ }) + .where('name.last').equals('Ghost') + .where('age').gt(17).lt(66) + .where('likes').in(['vaporizing', 'talking']) + .limit(10) + .sort('-occupation') + .select('name occupation') + .exec(callback); + + h3#refs References to other documents + :markdown + There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where [query#populate](./api.html#query_Query-populate) comes in. Read more [here](./populate.html). + + h3 Streaming + :markdown + Queries can be [streamed](http://nodejs.org/api/stream.html) from MongoDB to your application as well. Simply call the query's [stream](./api.html#query_Query-stream) method instead of [exec](./api.html#query_Query-exec) to return an instance of [QueryStream](./api.html#querystream_QueryStream). + + h3#next Next Up + :markdown + Now that we've covered `Queries`, let's take a look at [validation](/docs/validation.html). diff --git a/docs/3.3.x/docs/releases b/docs/3.3.x/docs/releases new file mode 100644 index 00000000000..f48a582a3ee --- /dev/null +++ b/docs/3.3.x/docs/releases @@ -0,0 +1,5 @@ +3.2.x +3.1.x +3.0.x +2.8.x +2.7.x diff --git a/docs/3.3.x/docs/schematypes.html b/docs/3.3.x/docs/schematypes.html new file mode 100644 index 00000000000..f314761f410 --- /dev/null +++ b/docs/3.3.x/docs/schematypes.html @@ -0,0 +1,67 @@ +Mongoose SchemaTypes v3.3.1Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    +  name:    String,
    +  binary:  Buffer,
    +  living:  Boolean,
    +  updated: { type: Date, default: Date.now },
    +  age:     { type: Number, min: 18, max: 65 },
    +  mixed:   Schema.Types.Mixed,
    +  _someId: Schema.Types.ObjectId,
    +  array:      [],
    +  ofString:   [String],
    +  ofNumber:   [Number],
    +  ofDates:    [Date],
    +  ofBuffer:   [Buffer],
    +  ofBoolean:  [Boolean],
    +  ofMixed:    [Schema.Types.Mixed],
    +  ofObjectId: [Schema.Types.ObjectId],
    +  nested: {
    +    stuff: { type: String, lowercase: true, trim: true }
    +  }
    +})
    +
    +// example use
    +
    +var Thing = mongoose.model('Thing', schema);
    +
    +var m = new Thing;
    +m.name = 'Statue of Liberty';
    +m.age = 125;
    +m.updated = new Date;
    +m.binary = new Buffer(0);
    +m.living = false;
    +m.mixed = {[ any: { thing: 'i want' } ]};
    +m.markModified('mixed');
    +m._someId = new mongoose.Types.ObjectId;
    +m.array.push(1);
    +m.ofString.push("strings!");
    +m.ofNumber.unshift(1,2,3,4);
    +m.ofDates.addToSet(new Date);
    +m.ofBuffer.pop();
    +m.ofMixed = [1, [], 'three', { four: 5 }];
    +m.nested.stuff = 'good';
    +m.save(callback);
    +

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    +var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    +person.markModified('anything');
    +person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    +var ObjectId = mongoose.Schema.Types.ObjectId;
    +var Car = new Schema({ driver: ObjectId });
    +// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    +var ToyBox = new Schema({
    +  toys: [ToySchema],
    +  buffers: [Buffer],
    +  string:  [String],
    +  numbers: [Number]
    +  // ... etc
    +});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    +var Empty2 = new Schema({ any: Array });
    +var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    +var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Models.

    diff --git a/docs/3.3.x/docs/schematypes.jade b/docs/3.3.x/docs/schematypes.jade new file mode 100644 index 00000000000..afa3c3276fe --- /dev/null +++ b/docs/3.3.x/docs/schematypes.jade @@ -0,0 +1,146 @@ +extends layout + +block content + h2 SchemaTypes + p + | SchemaTypes handle definition of path + a(href="./api.html#schematype_SchemaType-default") defaults + |, + a(href="./api.html#schematype_SchemaType-validate") validation + |, + a(href="./api.html#schematype_SchemaType-get") getters + |, + a(href="./api.html#schematype_SchemaType-set") setters + |, + a(href="./api.html#schematype_SchemaType-select") field selection defaults + | for + a(href="./api.html#query-js") queries + | and other general characteristics for + a(href="./api.html#schema-string-js") Strings + | and + a(href="./api.html#schema-number-js") Numbers + |. Check out their respective API documentation for more detail. + p + | Following are all valid + a(href="./api.html#schema_Schema-Types") Schema Types + |. + ul + li String + li Number + li Date + li Buffer + li Boolean + li Mixed + li ObjectId + li Array + h4 Example + :js + var schema = new Schema({ + name: String, + binary: Buffer, + living: Boolean, + updated: { type: Date, default: Date.now }, + age: { type: Number, min: 18, max: 65 }, + mixed: Schema.Types.Mixed, + _someId: Schema.Types.ObjectId, + array: [], + ofString: [String], + ofNumber: [Number], + ofDates: [Date], + ofBuffer: [Buffer], + ofBoolean: [Boolean], + ofMixed: [Schema.Types.Mixed], + ofObjectId: [Schema.Types.ObjectId], + nested: { + stuff: { type: String, lowercase: true, trim: true } + } + }) + + // example use + + var Thing = mongoose.model('Thing', schema); + + var m = new Thing; + m.name = 'Statue of Liberty'; + m.age = 125; + m.updated = new Date; + m.binary = new Buffer(0); + m.living = false; + m.mixed = {[ any: { thing: 'i want' } ]}; + m.markModified('mixed'); + m._someId = new mongoose.Types.ObjectId; + m.array.push(1); + m.ofString.push("strings!"); + m.ofNumber.unshift(1,2,3,4); + m.ofDates.addToSet(new Date); + m.ofBuffer.pop(); + m.ofMixed = [1, [], 'three', { four: 5 }]; + m.nested.stuff = 'good'; + m.save(callback); + + h3 Usage notes: + h4#mixed Mixed + p An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent: + :js + var Any = new Schema({ any: {} }); + var Any = new Schema({ any: Schema.Types.Mixed }); + p + | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the + code .markModified(path) + | method of the document passing the path to the Mixed type you just changed. + :js + person.anything = { x: [3, 4, { y: "changed" }] }; + person.markModified('anything'); + person.save(); // anything will now get saved + h4#objectids ObjectIds + p + | To specify a type of ObjectId, use + code Schema.Types.ObjectId + | in your declaration. + :js + var mongoose = require('mongoose'); + var ObjectId = mongoose.Schema.Types.ObjectId; + var Car = new Schema({ driver: ObjectId }); + // or just Schema.ObjectId for backwards compatibility with v2 + h4#arrays Arrays + p + | Provide creation of arrays of + a(href="./api.html#schema_Schema-Types") SchemaTypes + | or + a(href="./subdocs.html") Sub-Documents + |. + :js + var ToySchema = new Schema({ name: String }); + var ToyBox = new Schema({ + toys: [ToySchema], + buffers: [Buffer], + string: [String], + numbers: [Number] + // ... etc + }); + p + | Note: specifying an empty array is equivalent to + code Mixed + |. The following all create arrays of + code Mixed + |: + :js + var Empty1 = new Schema({ any: [] }); + var Empty2 = new Schema({ any: Array }); + var Empty3 = new Schema({ any: [Schema.Types.Mixed] }); + var Empty4 = new Schema({ any: [{}] }); + h3#customtypes Creating Custom Types + p + | Mongoose can also be extended with custom SchemaTypes. Search the + a(href="http://plugins.mongoosejs.com") plugins + | site for compatible types like + a(href="https://github.com/aheckmann/mongoose-long") mongoose-long + | and + a(href="https://github.com/aheckmann/mongoose-number") other + | + a(href="https://github.com/bnoguchi/mongoose-types") types + |. + + h3#next Next Up + :markdown + Now that we've covered `SchemaTypes`, let's take a look at [Models](/docs/models.html). diff --git a/docs/3.3.x/docs/source/_docs b/docs/3.3.x/docs/source/_docs new file mode 100644 index 00000000000..628139bb801 --- /dev/null +++ b/docs/3.3.x/docs/source/_docs @@ -0,0 +1,16292 @@ + +### lib/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = require('./connectionstate')", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "require('./connectionstate')", + "string": "STATES" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the collection" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "conn", + "description": "A MongooseConnection instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "optional collection options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", + "summary": "

    Abstract Collection constructor

    ", + "body": "

    This is the base class that drivers inherit from and implement.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", + "ctx": { + "type": "function", + "name": "Collection", + "string": "Collection()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "name" + } + ], + "description": { + "full": "

    The collection name

    ", + "summary": "

    The collection name

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.name;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "conn" + } + ], + "description": { + "full": "

    The Connection instance

    ", + "summary": "

    The Connection instance

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.conn;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database connects

    ", + "summary": "

    Called when the database connects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onOpen", + "string": "Collection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database disconnects

    ", + "summary": "

    Called when the database disconnects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onClose", + "string": "Collection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the method to queue" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method when executed" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Queues a method for later execution when its
    database connection opens.

    ", + "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "addQueue", + "string": "Collection.prototype.addQueue()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes all queued methods and clears the queue.

    ", + "summary": "

    Executes all queued methods and clears the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "doQueue", + "string": "Collection.prototype.doQueue()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "ensureIndex", + "string": "Collection.prototype.ensureIndex()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findAndModify", + "string": "Collection.prototype.findAndModify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findOne", + "string": "Collection.prototype.findOne()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "find", + "string": "Collection.prototype.find()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "insert", + "string": "Collection.prototype.insert()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "save", + "string": "Collection.prototype.save()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "update", + "string": "Collection.prototype.update()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "getIndexes", + "string": "Collection.prototype.getIndexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "mapReduce", + "string": "Collection.prototype.mapReduce()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Collection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Collection", + "string": "module.exports" + } + } +] +### lib/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , assert =require('assert')", + "ctx": { + "type": "declaration", + "name": "url", + "value": "require('url')", + "string": "url" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Protocol prefix regexp.

    ", + "summary": "

    Protocol prefix regexp.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", + "ctx": { + "type": "declaration", + "name": "rgxProtocol", + "value": "/^(?:.)+:\\/\\//", + "string": "rgxProtocol" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "a mongoose instance" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." + }, + { + "type": "event", + "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." + }, + { + "type": "event", + "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." + }, + { + "type": "event", + "string": "`disconnecting`: Emitted when `connection.close()` was executed." + }, + { + "type": "event", + "string": "`disconnected`: Emitted after getting disconnected from the db." + }, + { + "type": "event", + "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." + }, + { + "type": "event", + "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." + }, + { + "type": "event", + "string": "`error`: Emitted when an error occurs on this connection." + }, + { + "type": "event", + "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", + "summary": "

    Connection constructor

    ", + "body": "

    For practical reasons, a Connection equals a Db.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", + "ctx": { + "type": "function", + "name": "Connection", + "string": "Connection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter

    ", + "summary": "

    Inherit from EventEmitter

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Connection", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Connection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readyState" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", + "summary": "

    Connection ready state

    ", + "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" + }, + { + "tags": [ + { + "type": "property", + "string": "collections" + } + ], + "description": { + "full": "

    A hash of the collections associated with this connection

    ", + "summary": "

    A hash of the collections associated with this connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collections;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    The mongodb.Db instance, set when the connection is opened

    ", + "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.db;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "connection_string", + "description": "mongodb://uri or the host to which you are connecting" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[port]", + "description": "database port" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n uri = url.parse(host);\n host = uri.hostname;\n port = uri.port || 27017;\n database = uri.pathname && uri.pathname.replace(/\\//g, '');\n }\n\n this.options = this.defaultOptions(options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing database name.'), callback);\n return this;\n }\n\n // handle authentication\n if (uri && uri.auth) {\n var auth = uri.auth.split(':');\n this.user = auth[0];\n this.pass = auth[1];\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n // user/pass options\n } else if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "open", + "string": "Connection.prototype.open()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "uris", + "description": "comma-separated mongodb:// `URI`s" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name if not included in `uris`" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "passed to the internal driver" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connects to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    ", + "summary": "

    Connects to a replica set.

    ", + "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n var uris = uris.split(',')\n , self = this;\n\n switch (arguments.length) {\n case 3:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'object':\n callback = options;\n options = database;\n database = null;\n break;\n }\n\n if ('function' === typeof options) {\n callback = options;\n options = {};\n }\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n this.options = options = this.defaultOptions(options);\n\n if (uris.length < 2) {\n this.error(new Error('Please provide comma-separated URIs'), callback);\n return this;\n }\n\n this.replica = true;\n this.host = [];\n this.port = [];\n\n uris.forEach(function (uri) {\n // handle missing protocols\n if (!rgxProtocol.test(uri))\n uri = 'mongodb://' + uri;\n\n var uri = url.parse(uri);\n\n self.host.push(uri.hostname);\n self.port.push(uri.port || 27017);\n\n if (!self.name && uri.pathname && uri.pathname.replace(/\\//g, ''))\n self.name = uri.pathname.replace(/\\//g, '');\n\n if (!self.user && uri.auth) {\n var auth = uri.auth.split(':');\n self.user = auth[0];\n self.pass = auth[1];\n }\n });\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "openSet", + "string": "Connection.prototype.openSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "optional" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", + "summary": "

    error

    ", + "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "error", + "string": "Connection.prototype.error()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "_open", + "string": "Connection.prototype._open()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection is opened

    ", + "summary": "

    Called when the connection is opened

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onOpen", + "string": "Connection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "self" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "close", + "string": "Connection.prototype.close()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onClose", + "string": "Connection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "of the collection" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional collection options" + }, + { + "type": "return", + "types": [ + "Collection" + ], + "description": "collection instance" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retrieves a collection, creating it if not cached.

    ", + "summary": "

    Retrieves a collection, creating it if not cached.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "collection", + "string": "Connection.prototype.collection()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "the model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "a schema. necessary when defining a model" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name of mongodb collection (optional) if not given it will be induced from model name" + }, + { + "type": "see", + "local": "Mongoose#model #index_Mongoose-model", + "visibility": "Mongoose#model" + }, + { + "type": "return", + "types": [ + "Model" + ], + "description": "The compiled model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    ", + "summary": "

    Defines or retrieves a model.

    ", + "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.model = function (name, schema, collection) {\n if (!this.models[name]) {\n var model = this.base.model(name, schema, collection, true)\n , Model\n\n if (this != model.prototype.db) {\n // subclass model using this connection and collection name\n Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model))\n return new Model(doc, fields, skipId);\n model.call(this, doc, fields, skipId);\n };\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = this;\n\n // collection name discovery\n if ('string' === typeof schema) {\n collection = schema;\n }\n\n if (!collection) {\n collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);\n }\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n Model.prototype.collection = this.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n }\n\n this.models[name] = Model || model;\n }\n\n return this.models[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "model", + "string": "Connection.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "level", + "description": "either off (0), slow (1), or all (2)" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[ms]", + "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Set profiling level.

    ", + "summary": "

    Set profiling level.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "setProfiling", + "string": "Connection.prototype.setProfiling()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Prepares default connection options.

    ", + "summary": "

    Prepares default connection options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.defaultOptions = function (options) {\n var o = options || {};\n\n o.server = o.server || {};\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n o.db || (o.db = {});\n o.db.forceServerObjectId = false;\n\n // TODO default to true once the driver is fixed\n if (!('safe' in o.db)) o.db.safe = false;\n\n return o;\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "defaultOptions", + "string": "Connection.prototype.defaultOptions()" + } + }, + { + "tags": [], + "description": { + "full": "

    Noop.

    ", + "summary": "

    Noop.

    ", + "body": "" + }, + "ignore": true, + "code": "function noop () {}", + "ctx": { + "type": "function", + "name": "noop", + "string": "noop()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", + "ctx": { + "type": "property", + "receiver": "Connection", + "name": "STATES", + "value": "STATES", + "string": "Connection.STATES" + } + } +] +### lib/connectionstate.js +[ + { + "tags": [], + "description": { + "full": "

    Connection states

    ", + "summary": "

    Connection states

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "module.exports = exports = Object.create(null)", + "string": "STATES" + } + } +] +### lib/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray\n , MongooseArray", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the values to set" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "the fields which were selected in the query returning this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "bool, should we auto create an ObjectId _id" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." + }, + { + "type": "event", + "string": "`save`: Emitted when the document is successfully saved" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document constructor.

    ", + "summary": "

    Document constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", + "ctx": { + "type": "function", + "name": "Document", + "string": "Document()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Document.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "schema" + } + ], + "description": { + "full": "

    The documents schema.

    ", + "summary": "

    The documents schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.schema;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "isNew" + } + ], + "description": { + "full": "

    Boolean flag specifying if the document is new.

    ", + "summary": "

    Boolean flag specifying if the document is new.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isNew;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "local": "Schema options /docs/guide.html#options", + "visibility": "Schema" + }, + { + "type": "property", + "string": "id" + } + ], + "description": { + "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", + "summary": "

    The string version of this documents _id.

    ", + "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.id;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "errors" + } + ], + "description": { + "full": "

    Hash containing current validation errors.

    ", + "summary": "

    Hash containing current validation errors.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.errors;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Builds the default doc structure

    ", + "summary": "

    Builds the default doc structure

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_buildDoc", + "string": "Document.prototype._buildDoc()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", + "summary": "

    Initializes the document without setters or marking anything modified.

    ", + "body": "

    Called internally after a document is returned from mongodb.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init');\n if (fn) fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "init", + "string": "Document.prototype.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "self", + "description": "document instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "raw mongodb doc" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "object we are initializing" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Init helper.

    ", + "summary": "

    Init helper.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", + "ctx": { + "type": "function", + "name": "init", + "string": "init()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", + "summary": "

    Stores the current values of the shard keys.

    ", + "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_storeShard", + "string": "Document.prototype._storeShard()" + } + }, + { + "tags": [], + "description": { + "full": "

    Set up middleware support

    ", + "summary": "

    Set up middleware support

    ", + "body": "" + }, + "ignore": true, + "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    ", + "summary": "

    Sends an update command with this document _id as the query selector.

    ", + "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "update", + "string": "Document.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "path", + "description": "path or object of key/vals to set" + }, + { + "type": "param", + "types": [ + "Any" + ], + "name": "val", + "description": "the value to set" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for \"on-the-fly\" attributes" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optionally specify options that modify the behavior of the set" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    ", + "summary": "

    Sets the value of a path, or many paths.

    ", + "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.set = function (path, val, type, options) {\n if (type && 'Object' == type.constructor.name) {\n options = type;\n type = undefined;\n }\n\n var merge = options && options.merge\n , adhoc = type && true !== type\n , constructing = true === type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n if (null != path[key] && 'Object' === path[key].constructor.name\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n pathtype = this.schema.pathType(prefix + key);\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n if (!merge) this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "set", + "string": "Document.prototype.set()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determine if we should mark this change as modified.

    ", + "summary": "

    Determine if we should mark this change as modified.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._shouldModify = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n if (this.isNew) return true;\n if (this.isDirectModified(pathToMark)) return false;\n\n if (undefined === val && !this.isSelected(path)) {\n // when a path is not selected in a query, its initial\n // value will be undefined.\n return true;\n }\n\n if (undefined === val && path in this._activePaths.states.default) {\n // we're just unsetting the default value which was never saved\n return false;\n }\n\n if (!deepEqual(val, priorVal || this.get(path))) {\n return true;\n }\n\n if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n return true;\n }\n\n return false;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_shouldModify", + "string": "Document.prototype._shouldModify()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._set = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n var shouldModify = this._shouldModify.apply(this, arguments);\n\n if (shouldModify) {\n this.markModified(pathToMark, val);\n\n // handle directly setting arrays (gh-1126)\n MongooseArray || (MongooseArray = require('./types/array'));\n if (val instanceof MongooseArray) {\n val._registerAtomic('$set', val);\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_set", + "string": "Document.prototype._set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets a raw value from a path (no getters)

    ", + "summary": "

    Gets a raw value from a path (no getters)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "getValue", + "string": "Document.prototype.getValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "setValue", + "string": "Document.prototype.setValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for on-the-fly attributes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", + "summary": "

    Returns the value of a path.

    ", + "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "get", + "string": "Document.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns the schematype for the given path.

    ", + "summary": "

    Returns the schematype for the given path.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_path", + "string": "Document.prototype._path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to mark modified" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", + "summary": "

    Marks the path as having pending changes to write to the db.

    ", + "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "markModified", + "string": "Document.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "function to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope with which to call fn" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "try", + "string": "Document.prototype.try()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the list of paths that have been modified.

    ", + "summary": "

    Returns the list of paths that have been modified.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "modifiedPaths", + "string": "Document.prototype.modifiedPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", + "summary": "

    Returns true if this document was modified, else false.

    ", + "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isModified", + "string": "Document.prototype.isModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", + "summary": "

    Returns true if path was directly set and modified, else false.

    ", + "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isDirectModified", + "string": "Document.prototype.isDirectModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was initialized.

    ", + "summary": "

    Checks if path was initialized.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isInit", + "string": "Document.prototype.isInit()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", + "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", + "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isSelected", + "string": "Document.prototype.isSelected()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "cb", + "description": "called after validation completes, passing an error if one occurred" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", + "summary": "

    Executes registered validation rules for this document.

    ", + "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n paths = paths.concat(Object.keys(this._activePaths.states.default));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n cb(err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "validate", + "string": "Document.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "the error which states the reason `path` was invalid" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "invalidate", + "string": "Document.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Resets the internal modified state of this document.

    ", + "summary": "

    Resets the internal modified state of this document.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n })\n .forEach(function (array) {\n var i = array.length;\n while (i--) {\n var doc = array[i];\n if (!doc) continue;\n doc._reset();\n }\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_reset", + "string": "Document.prototype._reset()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns this documents dirty paths / vals.

    ", + "summary": "

    Returns this documents dirty paths / vals.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_dirty", + "string": "Document.prototype._dirty()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compiles schemas.

    ", + "summary": "

    Compiles schemas.

    ", + "body": "" + }, + "ignore": true, + "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", + "ctx": { + "type": "function", + "name": "compile", + "string": "compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Defines the accessor named prop on the incoming prototype.

    ", + "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", + "body": "" + }, + "ignore": true, + "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", + "ctx": { + "type": "function", + "name": "define", + "string": "define()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Assigns/compiles schema into this documents prototype.

    ", + "summary": "

    Assigns/compiles schema into this documents prototype.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_setSchema", + "string": "Document.prototype._setSchema()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register default hooks

    ", + "summary": "

    Register default hooks

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n if (error) return;\n\n // handle sparse arrays by using for loop vs array.forEach\n // which skips the sparse elements\n\n var len = array.length\n subdocs += len;\n\n for (var i = 0; i < len; ++i) {\n if (error) break;\n\n var doc = array[i];\n if (!doc) {\n --subdocs || next();\n continue;\n }\n\n doc.save(handleSave);\n }\n });\n\n function handleSave (err) {\n if (error) return;\n\n if (err) {\n self._validationError = undefined;\n return next(error = err);\n }\n\n --subdocs || next();\n }\n\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_registerHooks", + "string": "Document.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Registers an error

    ", + "summary": "

    Registers an error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_error", + "string": "Document.prototype._error()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes methods queued from the Schema definition

    ", + "summary": "

    Executes methods queued from the Schema definition

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_doQueue", + "string": "Document.prototype._doQueue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "js object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this document into a plain javascript object

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    ", + "summary": "

    Converts this document into a plain javascript object

    ", + "body": "

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n if (true === options.transform) {\n var opts = options.json\n ? this.schema.options.toJSON\n : this.schema.options.toObject;\n if (opts) {\n options.transform = opts.transform;\n }\n }\n\n if ('function' == typeof options.transform) {\n var xformed = options.transform(this, ret, options);\n if ('undefined' != typeof xformed) ret = xformed;\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toObject", + "string": "Document.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "json", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "either `virtuals` or `paths`" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "`json`" + } + ], + "description": { + "full": "

    Applies virtuals properties to json.

    ", + "summary": "

    Applies virtuals properties to json.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", + "ctx": { + "type": "function", + "name": "applyGetters", + "string": "applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "same options as [Document#toObject](#document_Document-toObject)" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "see", + "local": "Document#toObject #document_Document-toObject", + "visibility": "Document#toObject" + }, + { + "type": "", + "string": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    \n\n

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", + "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", + "body": "

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toJSON", + "string": "Document.prototype.toJSON()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "inspect", + "string": "Document.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "toString" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toString = Document.prototype.inspect;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "toString", + "value": "Document.prototype.inspect", + "string": "Document.prototypetoString" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "a document to compare" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", + "summary": "

    Returns true if the Document stores the same data as doc.

    ", + "body": "

    Documents are considered equal when they have matching _ids.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "equals", + "string": "Document.prototype.equals()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", + "ctx": { + "type": "property", + "receiver": "Document", + "name": "ValidationError", + "value": "ValidationError", + "string": "Document.ValidationError" + } + } +] +### lib/drivers/node-mongodb-native/binary.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require('mongodb').BSONPure.Binary", + "string": "Binary" + } + } +] +### lib/drivers/node-mongodb-native/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", + "ctx": { + "type": "declaration", + "name": "MongooseCollection", + "value": "require('../../collection')", + "string": "MongooseCollection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Collection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", + "summary": "

    A node-mongodb-native collection implementation.

    ", + "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", + "ctx": { + "type": "function", + "name": "NativeCollection", + "string": "NativeCollection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from abstract Collection.

    ", + "summary": "

    Inherit from abstract Collection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "__proto__", + "value": "MongooseCollection.prototype", + "string": "NativeCollection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection opens.

    ", + "summary": "

    Called when the connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onOpen", + "string": "NativeCollection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onClose", + "string": "NativeCollection.prototype.onClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Copy the collection methods and make them subject to queues

    ", + "summary": "

    Copy the collection methods and make them subject to queues

    ", + "body": "" + }, + "ignore": true, + "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", + "ctx": { + "type": "function", + "name": "print", + "string": "print()" + } + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if ('Date' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", + "ctx": { + "type": "function", + "name": "format", + "string": "format()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "method", + "string": "getIndexes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retreives information about this collections indexes.

    ", + "summary": "

    Retreives information about this collections indexes.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "getIndexes", + "value": "NativeCollection.prototype.indexInformation", + "string": "NativeCollection.prototypegetIndexes" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeCollection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeCollection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", + "ctx": { + "type": "declaration", + "name": "MongooseConnection", + "value": "require('../../connection')", + "string": "MongooseConnection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Connection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native connection implementation.

    ", + "summary": "

    A node-mongodb-native connection implementation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", + "ctx": { + "type": "function", + "name": "NativeConnection", + "string": "NativeConnection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Connection.

    ", + "summary": "

    Inherits from Connection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeConnection", + "name": "__proto__", + "value": "MongooseConnection.prototype", + "string": "NativeConnection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, Number(this.port), this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpen", + "string": "NativeConnection.prototype.doOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", + "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", + "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , ports = this.port\n , self = this\n\n this.host.forEach(function (host, i) {\n servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));\n });\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpenSet", + "string": "NativeConnection.prototype.doOpenSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doClose", + "string": "NativeConnection.prototype.doClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeConnection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeConnection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/objectid.js +[ + { + "tags": [ + { + "type": "constructor", + "string": "NodeMongoDbObjectId" + }, + { + "type": "see", + "local": "ObjectId", + "visibility": "ObjectId" + } + ], + "description": { + "full": "

    node-mongodb-native ObjectId

    ", + "summary": "

    node-mongodb-native ObjectId

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require('mongodb').BSONPure.ObjectID", + "string": "ObjectId" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", + "ctx": { + "type": "declaration", + "name": "ObjectIdToString", + "value": "ObjectId.toString.bind(ObjectId)", + "string": "ObjectIdToString" + } + } +] +### lib/error.js +[ + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" + } + ], + "description": { + "full": "

    Mongoose error

    ", + "summary": "

    Mongoose error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", + "ctx": { + "type": "function", + "name": "MongooseError", + "string": "MongooseError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Error.

    ", + "summary": "

    Inherits from Error.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseError.prototype.__proto__ = Error.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseError", + "name": "__proto__", + "value": "Error.prototype", + "string": "MongooseError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseError", + "string": "module.exports" + } + } +] +### lib/errors/cast.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casting Error constructor.

    ", + "summary": "

    Casting Error constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", + "ctx": { + "type": "function", + "name": "CastError", + "string": "CastError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "CastError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "CastError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "CastError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = CastError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "CastError", + "string": "module.exports" + } + } +] +### lib/errors/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document Error

    ", + "summary": "

    Document Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", + "ctx": { + "type": "function", + "name": "DocumentError", + "string": "DocumentError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "DocumentError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = DocumentError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = DocumentError", + "string": "module.exports" + } + } +] +### lib/errors/validation.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "instance", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    Document Validation Error

    ", + "summary": "

    Document Validation Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", + "ctx": { + "type": "function", + "name": "ValidationError", + "string": "ValidationError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Console.log helper

    ", + "summary": "

    Console.log helper

    ", + "body": "" + }, + "ignore": false, + "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", + "ctx": { + "type": "method", + "constructor": "ValidationError", + "name": "toString", + "string": "ValidationError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidationError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidationError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = ValidationError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = ValidationError", + "string": "module.exports" + } + } +] +### lib/errors/validator.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Schema validator error

    ", + "summary": "

    Schema validator error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", + "ctx": { + "type": "function", + "name": "ValidatorError", + "string": "ValidatorError()" + } + }, + { + "tags": [], + "description": { + "full": "

    toString helper

    ", + "summary": "

    toString helper

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", + "ctx": { + "type": "method", + "constructor": "ValidatorError", + "name": "toString", + "string": "ValidatorError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError

    ", + "summary": "

    Inherits from MongooseError

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidatorError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidatorError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ValidatorError", + "string": "module.exports" + } + } +] +### lib/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", + "summary": "

    Mongoose constructor.

    ", + "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", + "ctx": { + "type": "function", + "name": "Mongoose", + "string": "Mongoose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", + "summary": "

    Sets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "set", + "string": "Mongoose.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "method", + "string": "get" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", + "summary": "

    Gets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.get = Mongoose.prototype.set;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "get", + "value": "Mongoose.prototype.set", + "string": "Mongoose.prototypeget" + } + }, + { + "tags": [], + "description": { + "full": "

    ReplSet connection string check.

    ", + "summary": "

    ReplSet connection string check.

    ", + "body": "" + }, + "ignore": true, + "code": "var rgxReplSet = /^.+,.+$/;", + "ctx": { + "type": "declaration", + "name": "rgxReplSet", + "value": "/^.+,.+$/", + "string": "rgxReplSet" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[uri]", + "description": "a mongodb:// URI" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options to pass to the driver" + }, + { + "type": "see", + "local": "Connection#open #connection_Connection-open", + "visibility": "Connection#open" + }, + { + "type": "see", + "local": "Connection#openSet #connection_Connection-openSet", + "visibility": "Connection#openSet" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "the created Connection object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Connection instance.

    \n\n

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    ", + "summary": "

    Creates a Connection instance.

    ", + "body": "

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "createConnection", + "string": "Mongoose.prototype.createConnection()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Mongoose#createConnection #index_Mongoose-createConnection", + "visibility": "Mongoose#createConnection" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    ", + "summary": "

    Opens the default mongoose connection.

    ", + "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "connect", + "string": "Mongoose.prototype.connect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "called after all connection close." + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Disconnects all connections.

    ", + "summary": "

    Disconnects all connections.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "disconnect", + "string": "Mongoose.prototype.disconnect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name (optional, induced from model name)" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipInit]", + "description": "whether to skip initialization (defaults to false)" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    ", + "summary": "

    Defines a model or retrieves it.

    ", + "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n // normalize collection\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // look up models for the collection\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n this.modelSchemas[name] = schema;\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n } else {\n throw new Error('Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)');\n }\n }\n\n if (!this.models[name]) {\n schema || (schema = this.modelSchemas[name]);\n collection || (collection = schema.set('collection') || format(name));\n\n var model = Model.compile(name\n , this.modelSchemas[name]\n , collection\n , this.connection\n , this);\n\n if (!skipInit) model.init();\n\n this.models[name] = model;\n }\n\n return this.models[name];\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "model", + "string": "Mongoose.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "plugin callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "optional options" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", + "summary": "

    Declares a global plugin executed on all Schemas.

    ", + "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "plugin", + "string": "Mongoose.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "connection" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", + "summary": "

    The default connection of the mongoose module.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" + }, + { + "tags": [], + "description": { + "full": "

    Driver depentend APIs

    ", + "summary": "

    Driver depentend APIs

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Connection

    ", + "summary": "

    Connection

    ", + "body": "" + }, + "ignore": true, + "code": "var Connection = require(driver + '/connection');", + "ctx": { + "type": "declaration", + "name": "Connection", + "value": "require(driver + '/connection')", + "string": "Connection" + } + }, + { + "tags": [], + "description": { + "full": "

    Collection

    ", + "summary": "

    Collection

    ", + "body": "" + }, + "ignore": true, + "code": "var Collection = require(driver + '/collection');", + "ctx": { + "type": "declaration", + "name": "Collection", + "value": "require(driver + '/collection')", + "string": "Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The exports object is an instance of Mongoose.

    ", + "summary": "

    The exports object is an instance of Mongoose.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = new Mongoose", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Collection constructor

    ", + "summary": "

    The Mongoose Collection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Collection = Collection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Collection", + "value": "Collection", + "string": "mongoose.Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Connection constructor

    ", + "summary": "

    The Mongoose Connection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Connection = Connection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Connection", + "value": "Connection", + "string": "mongoose.Connection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose version

    ", + "summary": "

    Mongoose version

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "version", + "value": "JSON.parse(", + "string": "mongoose.version" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", + "summary": "

    The Mongoose constructor

    ", + "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Mongoose = Mongoose;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Mongoose", + "value": "Mongoose", + "string": "mongoose.Mongoose" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", + "summary": "

    The Mongoose Schema constructor

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Schema = Schema;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Schema", + "value": "Schema", + "string": "mongoose.Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose SchemaType constructor.

    ", + "summary": "

    The Mongoose SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaType = SchemaType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaType", + "value": "SchemaType", + "string": "mongoose.SchemaType" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Schema.SchemaTypes #schema_Schema-Types", + "visibility": "Schema.SchemaTypes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", + "summary": "

    The various Mongoose SchemaTypes.

    ", + "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaTypes = Schema.Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaTypes", + "value": "Schema.Types", + "string": "mongoose.SchemaTypes" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose VirtualType constructor.

    ", + "summary": "

    The Mongoose VirtualType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.VirtualType = VirtualType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "VirtualType", + "value": "VirtualType", + "string": "mongoose.VirtualType" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", + "summary": "

    The various Mongoose Types.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Types = Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Types", + "value": "Types", + "string": "mongoose.Types" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Query constructor.

    ", + "summary": "

    The Mongoose Query constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Query = Query;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Query", + "value": "Query", + "string": "mongoose.Query" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Promise constructor.

    ", + "summary": "

    The Mongoose Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Promise = Promise;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Promise", + "value": "Promise", + "string": "mongoose.Promise" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Model constructor.

    ", + "summary": "

    The Mongoose Model constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Model = Model;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Model", + "value": "Model", + "string": "mongoose.Model" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Document constructor.

    ", + "summary": "

    The Mongoose Document constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Document = Document;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Document", + "value": "Document", + "string": "mongoose.Document" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The MongooseError constructor.

    ", + "summary": "

    The MongooseError constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Error = require('./error');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Error", + "value": "require('./error')", + "string": "mongoose.Error" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The node-mongodb-native driver Mongoose uses.

    ", + "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.mongo = require('mongodb');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "mongo", + "value": "require('mongodb')", + "string": "mongoose.mongo" + } + } +] +### lib/model.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('./document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "values to with which to create the document" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "event", + "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." + }, + { + "type": "event", + "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Model constructor

    ", + "summary": "

    Model constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", + "ctx": { + "type": "function", + "name": "Model", + "string": "Model()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Document.

    ", + "summary": "

    Inherits from Document.

    ", + "body": "" + }, + "ignore": true, + "code": "Model.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "Model", + "name": "__proto__", + "value": "Document.prototype", + "string": "Model.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    Connection the model uses.

    ", + "summary": "

    Connection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.db;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "collection" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.collection;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "modelName" + } + ], + "description": { + "full": "

    The name of the model

    ", + "summary": "

    The name of the model

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.modelName;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "object" + }, + { + "type": "return", + "types": [ + "Object", + "undefined" + ], + "description": "population paths" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns what paths can be populated

    ", + "summary": "

    Returns what paths can be populated

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_getPopulationKeys", + "string": "Model.prototype._getPopulationKeys()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "schema", + "description": "type for the oid" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "oid", + "description": "object id or array of object ids" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "query", + "description": "object specifying query conditions, fields, and options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Populates an object

    ", + "summary": "

    Populates an object

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_populate", + "string": "Model.prototype._populate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "query that originated the initialization" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs auto-population of relations.

    ", + "summary": "

    Performs auto-population of relations.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "init", + "string": "Model.prototype.init()" + } + }, + { + "tags": [], + "description": { + "full": "

    Handles doc.save() callbacks

    ", + "summary": "

    Handles doc.save() callbacks

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new Error('No matching document found.'));\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", + "ctx": { + "type": "function", + "name": "handleSave", + "string": "handleSave()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "title": "middleware", + "url": "http://mongoosejs.com/docs/middleware.html", + "visibility": "http://mongoosejs.com/docs/middleware.html" + } + ], + "description": { + "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", + "summary": "

    Saves this document.

    ", + "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n process.nextTick(function () {\n complete(null);\n })\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "save", + "string": "Model.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Mixed" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[operation]", + "description": "" + } + ], + "description": { + "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", + "ctx": { + "type": "function", + "name": "operand", + "string": "operand()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "val", + "description": "" + } + ], + "description": { + "full": "

    Compiles an update and where clause for a val with _atomics.

    ", + "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", + "ctx": { + "type": "function", + "name": "handleAtomics", + "string": "handleAtomics()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a special query document of the modified properties used in updates.

    ", + "summary": "

    Produces a special query document of the modified properties used in updates.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_delta", + "string": "Model.prototype._delta()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Appends versioning to the where and update clauses.

    ", + "summary": "

    Appends versioning to the where and update clauses.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_version", + "string": "Model.prototype._version()" + } + }, + { + "tags": [ + { + "type": "see", + "title": "versionKeys", + "url": "http://mongoosejs.com/docs/guide.html#versionKey", + "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Signal that we desire an increment of this documents version.

    ", + "summary": "

    Signal that we desire an increment of this documents version.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "increment", + "string": "Model.prototype.increment()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns a query object which applies shardkeys if they exist.

    ", + "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_where", + "string": "Model.prototype._where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", + "summary": "

    Removes this document from the db.

    ", + "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) return this;\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "remove", + "string": "Model.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register hooks override

    ", + "summary": "

    Register hooks override

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_registerHooks", + "string": "Model.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", + "summary": "

    Returns another Model instance.

    ", + "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "model", + "string": "Model.prototype.model()" + } + }, + { + "tags": [ + { + "type": "TODO", + "string": "determine if this is still necessary" + } + ], + "description": { + "full": "

    Give the constructor the ability to emit events.

    ", + "summary": "

    Give the constructor the ability to emit events.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the model compiles.

    ", + "summary": "

    Called when the model compiles.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.init = function init () {\n if (this.schema.options.autoIndex)\n this.ensureIndexes();\n\n this.schema.emit('init', this);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "init", + "string": "Model.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[cb]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    ", + "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", + "body": "

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "ensureIndexes", + "string": "Model.ensureIndexes()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "schema" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema the model uses.

    ", + "summary": "

    Schema the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.schema;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Database instance the model uses.

    ", + "summary": "

    Database instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.db;" + }, + { + "tags": [ + { + "type": "property", + "string": "collection" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.collection;" + }, + { + "tags": [ + { + "type": "property", + "string": "base" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Base Mongoose instance the model uses.

    ", + "summary": "

    Base Mongoose instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.base;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes documents from the collection.

    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    ", + "summary": "

    Removes documents from the collection.

    ", + "body": "

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "remove", + "string": "Model.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents

    \n\n

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    ", + "summary": "

    Finds documents

    ", + "body": "

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "find", + "string": "Model.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges the current named scope query into query.

    ", + "summary": "

    Merges the current named scope query into query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "_applyNamedScope", + "string": "Model._applyNamedScope()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "objectid, or a value that can be casted to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds a single document by id.

    \n\n

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    ", + "summary": "

    Finds a single document by id.

    ", + "body": "

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findById", + "string": "Model.findById()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    ", + "summary": "

    Finds one document.

    ", + "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n // TODO Handle all 3 of the following scenarios\n // Hint: Only some of these scenarios are possible if cQuery is present\n // Scenario: findOne(conditions, fields, callback);\n // Scenario: findOne(fields, options, callback);\n // Scenario: findOne(conditions, options, callback);\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n // TODO Handle all 2 of the following scenarios\n // Scenario: findOne(conditions, callback)\n // Scenario: findOne(fields, callback)\n // Scenario: findOne(options, callback);\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOne", + "string": "Model.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", + "summary": "

    Counts number of matching documents in a database collection.

    ", + "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "count", + "string": "Model.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a DISTINCT command

    ", + "summary": "

    Executes a DISTINCT command

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "distinct", + "string": "Model.distinct()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "optional value" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", + "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", + "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "where", + "string": "Model.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "argument", + "description": "is a javascript string or anonymous function" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "memberOf", + "parent": "Model" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Query.$where #query_Query-%24where", + "visibility": "Query.$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    ", + "summary": "

    Creates a Query and specifies a $where condition.

    ", + "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndUpdate", + "string": "Model.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "an ObjectId or string that can be cast to one." + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", + "visibility": "Model.findOneAndUpdate" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndUpdate", + "string": "Model.findByIdAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndRemove", + "string": "Model.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "id", + "description": "ObjectId or string that can be cast to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", + "visibility": "Model.findOneAndRemove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndRemove", + "string": "Model.findByIdAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array", + "Object..." + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", + "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", + "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "create", + "string": "Model.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "update", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Updates documents in the database without returning them.

    ", + "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "update", + "string": "Model.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "o", + "description": "an object specifying map-reduce options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/MapReduce", + "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", + "summary": "

    Executes a mapReduce command.

    ", + "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "mapReduce", + "string": "Model.mapReduce()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "an array of pipeline commands" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "aggregation", + "url": "http://docs.mongodb.org/manual/applications/aggregation/", + "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", + "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes an aggregate command on this models collection.

    \n\n

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    ", + "summary": "

    Executes an aggregate command on this models collection.

    ", + "body": "

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "aggregate", + "string": "Model.aggregate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "collectionName", + "description": "" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "connection", + "description": "" + }, + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "mongoose instance" + } + ], + "description": { + "full": "

    Compiler utility.

    ", + "summary": "

    Compiler utility.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "compile", + "string": "Model.compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Model;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Model", + "string": "module.exports" + } + } +] +### lib/namedscope.js +[ + { + "tags": [ + { + "type": "param", + "types": [ + "NamedScope" + ], + "name": "target", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "getters", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Decorate

    ", + "summary": "

    Decorate

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", + "ctx": { + "type": "method", + "constructor": "NamedScope", + "name": "decorate", + "string": "NamedScope.prototype.decorate()" + } + } +] +### lib/promise.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", + "ctx": { + "type": "declaration", + "name": "util", + "value": "require('./utils')", + "string": "util" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "back", + "description": "a callback+errback that accepts `fn(err, ...){}` as signature" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`err`: Emits when the promise resolves to an error." + }, + { + "type": "event", + "string": "`complete`: Emits when the promise resolves sucessfully." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Promise constructor.

    ", + "summary": "

    Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", + "ctx": { + "type": "function", + "name": "Promise", + "string": "Promise()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from EventEmitter.

    ", + "summary": "

    Inherits from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Promise", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Promise.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Event" + ], + "name": "event", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds listener to the event.

    \n\n

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", + "summary": "

    Adds listener to the event.

    ", + "body": "

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "on", + "string": "Promise.prototype.on()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Keeps track of emitted events to run them on on.

    ", + "summary": "

    Keeps track of emitted events to run them on on.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "emit", + "string": "Promise.prototype.emit()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for emitting the complete event.

    ", + "summary": "

    Shortcut for emitting the complete event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "complete", + "string": "Promise.prototype.complete()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Shortcut for emitting the err event.

    ", + "summary": "

    Shortcut for emitting the err event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "error", + "string": "Promise.prototype.error()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('complete', fn).

    ", + "summary": "

    Shortcut for .on('complete', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addCallback", + "string": "Promise.prototype.addCallback()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('err', fn).

    ", + "summary": "

    Shortcut for .on('err', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addErrback", + "string": "Promise.prototype.addErrback()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Adds a single function that's both a callback and errback.

    ", + "summary": "

    Adds a single function that's both a callback and errback.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addBack", + "string": "Promise.prototype.addBack()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "optional error or null" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "value to complete the promise with" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "summary": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "resolve", + "string": "Promise.prototype.resolve()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Promise;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Promise", + "string": "module.exports" + } + } +] +### lib/query.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "criteria", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", + "summary": "

    Query constructor used for building queries.

    ", + "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n if (criteria) this.find(criteria);\n}", + "ctx": { + "type": "function", + "name": "Query", + "string": "Query()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", + "summary": "

    Sets query options.

    ", + "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "setOptions", + "string": "Query.prototype.setOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "the model to which the query is bound" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "the operation to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "updateArg", + "description": "used in update methods" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Binds this query to a model.

    ", + "summary": "

    Binds this query to a model.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "bind", + "string": "Query.prototype.bind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "[operation]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", + "summary": "

    Executes the query

    ", + "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exec", + "string": "Query.prototype.exec()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[criteria]", + "description": "mongodb selector" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", + "summary": "

    Finds documents.

    ", + "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "find", + "string": "Query.prototype.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[obj]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", + "summary": "

    Casts this query to the schema of model

    ", + "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path || '$and' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "cast", + "string": "Query.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options.

    ", + "summary": "

    Returns default options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_optionsForExec", + "string": "Query.prototype._optionsForExec()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies schematype selected options to this query.

    ", + "summary": "

    Applies schematype selected options to this query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_applyPaths", + "string": "Query.prototype._applyPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "js", + "description": "javascript string or function" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", + "summary": "

    Specifies a $where condition

    ", + "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", + "summary": "

    Specifies a path for use with chaining.

    ", + "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "where", + "string": "Query.prototype.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", + "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", + "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "equals", + "string": "Query.prototype.equals()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", + "summary": "

    Specifies arguments for an $or condition.

    ", + "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "or", + "string": "Query.prototype.or()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", + "summary": "

    Specifies arguments for a $nor condition.

    ", + "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nor", + "string": "Query.prototype.nor()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "gt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", + "summary": "

    Specifies a $gt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "gte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $gte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "ne" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $ne query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "in" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $in query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "nin" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $nin query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "all" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $all query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "size" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $size query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "regex" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $regex query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxDistance" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $maxDistance query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", + "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", + "body": "
    Thing.where('type').nin(array)\n
    " + }, + "ignore": true, + "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $near condition

    ", + "summary": "

    Specifies a $near condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "near", + "string": "Query.prototype.near()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $nearSphere condition.

    ", + "summary": "

    Specifies a $nearSphere condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nearSphere", + "string": "Query.prototype.nearSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $mod condition

    ", + "summary": "

    Specifies a $mod condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "mod", + "string": "Query.prototype.mod()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $exists condition

    ", + "summary": "

    Specifies an $exists condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exists", + "string": "Query.prototype.exists()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object", + "Function" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "Function" + ], + "name": "criteria", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", + "summary": "

    Specifies an $elemMatch condition

    ", + "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "elemMatch", + "string": "Query.prototype.elemMatch()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "within" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Syntax sugar for expressive queries.

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    ", + "summary": "

    Syntax sugar for expressive queries.

    ", + "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "see", + "local": "Query#within #query_Query-within", + "visibility": "Query#within" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", + "summary": "

    Specifies a $box condition

    ", + "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "box", + "string": "Query.prototype.box()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "options e.g. { $uniqueDocs: true }" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", + "summary": "

    Specifies a $center condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "center", + "string": "Query.prototype.center()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", + "summary": "

    Specifies a $centerSphere condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "centerSphere", + "string": "Query.prototype.centerSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Array", + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", + "summary": "

    Specifies a $polygon condition

    ", + "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "polygon", + "string": "Query.prototype.polygon()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "local": "SchemaType", + "visibility": "SchemaType" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    ", + "summary": "

    Specifies which document fields to include or exclude

    ", + "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "select", + "string": "Query.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "number of elements to slice" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", + "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", + "summary": "

    Specifies a $slice condition

    ", + "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slice", + "string": "Query.prototype.slice()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", + "summary": "

    Sets the sort order

    ", + "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "sort", + "string": "Query.prototype.sort()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", + "ctx": { + "type": "function", + "name": "push", + "string": "push()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "limit" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", + "summary": "

    Specifies the limit option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "skip" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", + "summary": "

    Specifies the skip option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxscan" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", + "summary": "

    Specifies the maxscan option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "batchSize" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", + "summary": "

    Specifies the batchSize option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "comment" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", + "summary": "

    Specifies the comment option.

    ", + "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", + "summary": "

    limit, skip, maxscan, batchSize, comment

    ", + "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " + }, + "ignore": true, + "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", + "summary": "

    Specifies this query as a snapshot query.

    ", + "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "snapshot", + "string": "Query.prototype.snapshot()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "a hint object" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", + "summary": "

    Sets query hints.

    ", + "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "hint", + "string": "Query.prototype.hint()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", + "summary": "

    Sets the slaveOk option.

    ", + "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slaveOk", + "string": "Query.prototype.slaveOk()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "one of the listed preference options or their aliases" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "[tags]", + "description": "optional tags for this query" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", + "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the readPreference option for the query.

    \n\n

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    ", + "summary": "

    Sets the readPreference option for the query.

    ", + "body": "

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "read", + "string": "Query.prototype.read()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", + "summary": "

    Sets the lean option.

    ", + "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "lean", + "string": "Query.prototype.lean()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", + "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", + "summary": "

    Sets tailable option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "tailable", + "string": "Query.prototype.tailable()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes the query as a find() operation.

    ", + "summary": "

    Executes the query as a find() operation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "execFind", + "string": "Query.prototype.execFind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", + "summary": "

    Executes the query as a findOne() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOne", + "string": "Query.prototype.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", + "summary": "

    Exectues the query as a count() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "count", + "string": "Query.prototype.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a distict() operation.

    ", + "summary": "

    Executes this query as a distict() operation.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "distinct", + "string": "Query.prototype.distinct()" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "body": "" + }, + "ignore": true, + "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", + "ctx": { + "type": "declaration", + "name": "castOps", + "value": "{", + "string": "castOps" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "body": "" + }, + "ignore": true, + "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", + "ctx": { + "type": "declaration", + "name": "numberOps", + "value": "{", + "string": "numberOps" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "the update conditions" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", + "summary": "

    Executes this query as an update() operation.

    ", + "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n delete options.safe;\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "update", + "string": "Query.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "obj after casting its values" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts obj for an update command.

    ", + "summary": "

    Casts obj for an update command.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdate", + "string": "Query.prototype._castUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "- part of a query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "- path prefix (internal only)" + }, + { + "type": "return", + "types": [ + "Bool" + ], + "description": "true if this path has keys to update" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_walkUpdatePath", + "string": "Query.prototype._walkUpdatePath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[$conditional]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val according to schema and atomic op.

    ", + "summary": "

    Casts val according to schema and atomic op.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdateVal", + "string": "Query.prototype._castUpdateVal()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_getSchema", + "string": "Query.prototype._getSchema()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "https://github.com/LearnBoost/mongoose/issues/1091", + "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" + }, + { + "type": "see", + "title": "", + "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", + "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts selected field arguments for field selection with mongo 2.2

    \n\n
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    ", + "summary": "

    Casts selected field arguments for field selection with mongo 2.2

    ", + "body": "
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castFields", + "string": "Query.prototype._castFields()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", + "summary": "

    Executes this query as a remove() operation.

    ", + "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n delete options.safe;\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "remove", + "string": "Query.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[query]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[doc]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndUpdate", + "string": "Query.prototype.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndRemove", + "string": "Query.prototype.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "- either \"remove\" or \"update\"" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    _findAndModify

    ", + "summary": "

    _findAndModify

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n this._applyPaths();\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_findAndModify", + "string": "Query.prototype._findAndModify()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Model" + ], + "name": "[model]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "see", + "local": "population ./populate.html", + "visibility": "population" + }, + { + "type": "see", + "local": "Query#select #query_Query-select", + "visibility": "Query#select" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    ", + "summary": "

    Specifies paths which should be populated with other documents.

    ", + "body": "

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "populate", + "string": "Query.prototype.populate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Populate options constructor

    ", + "summary": "

    Populate options constructor

    ", + "body": "" + }, + "ignore": true, + "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", + "ctx": { + "type": "function", + "name": "PopulateOptions", + "string": "PopulateOptions()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "QueryStream" + ], + "description": "" + }, + { + "type": "see", + "local": "QueryStream", + "visibility": "QueryStream" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a stream interface

    \n\n

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    ", + "summary": "

    Returns a stream interface

    ", + "body": "

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "stream", + "string": "Query.prototype.stream()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castDoc

    ", + "summary": "

    castDoc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castDoc", + "string": "castDoc()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castQuery

    ", + "summary": "

    castQuery

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castQuery", + "string": "castQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Exports.

    ", + "summary": "

    Exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Query", + "string": "module.exports" + } + } +] +### lib/querystream.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", + "ctx": { + "type": "declaration", + "name": "Stream", + "value": "require('stream').Stream", + "string": "Stream" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS Stream http://nodejs.org/api/stream.html" + }, + { + "type": "event", + "string": "`data`: emits a single Mongoose document" + }, + { + "type": "event", + "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." + }, + { + "type": "event", + "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Provides a ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    ", + "summary": "

    Provides a ReadStream interface for Queries.

    ", + "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n this._running = false;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", + "ctx": { + "type": "function", + "name": "QueryStream", + "string": "QueryStream()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Stream

    ", + "summary": "

    Inherit from Stream

    ", + "body": "" + }, + "ignore": true, + "code": "QueryStream.prototype.__proto__ = Stream.prototype;", + "ctx": { + "type": "property", + "constructor": "QueryStream", + "name": "__proto__", + "value": "Stream.prototype", + "string": "QueryStream.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readable" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is readable.

    ", + "summary": "

    Flag stating whether or not this stream is readable.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.readable;" + }, + { + "tags": [ + { + "type": "property", + "string": "paused" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is paused.

    ", + "summary": "

    Flag stating whether or not this stream is paused.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the query.

    ", + "summary": "

    Initializes the query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_init", + "string": "QueryStream.prototype._init()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#__next #querystream_QueryStream-__next", + "visibility": "QueryStream#__next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Trampoline for pulling the next doc from cursor.

    ", + "summary": "

    Trampoline for pulling the next doc from cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) {\n return this._running = false;\n }\n\n this._running = true;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n while (this.__next()) {}\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_next", + "string": "QueryStream.prototype._next()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#_next #querystream_QueryStream-_next", + "visibility": "QueryStream#_next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pulls the next doc from the cursor.

    ", + "summary": "

    Pulls the next doc from the cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed)\n return this._running = false;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "__next", + "string": "QueryStream.prototype.__next()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error", + "null" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return this._running = false;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && true === this.query.options.lean) {\n this.emit('data', doc);\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_onNextObject", + "string": "QueryStream.prototype._onNextObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pauses this stream.

    ", + "summary": "

    Pauses this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "pause", + "string": "QueryStream.prototype.pause()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Resumes this stream.

    ", + "summary": "

    Resumes this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n\n if (!this._cursor) {\n // cannot start if not initialized\n return;\n }\n\n // are we within the trampoline?\n if (T_INIT === this._inline) {\n return;\n }\n\n if (!this._running) {\n // outside QueryStream control, need manual restart\n return this._next();\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "resume", + "string": "QueryStream.prototype.resume()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "[err]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this._running = false;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "destroy", + "string": "QueryStream.prototype.destroy()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "pipe" + }, + { + "type": "memberOf", + "parent": "QueryStream" + }, + { + "type": "see", + "title": "NodeJS", + "url": "http://nodejs.org/api/stream.html", + "visibility": "http://nodejs.org/api/stream.html" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", + "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", + "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = QueryStream", + "string": "module.exports" + } + } +] +### lib/schema/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Array SchemaType constructor

    ", + "summary": "

    Array SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "SchemaArray", + "string": "SchemaArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaArray", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "checkRequired", + "string": "SchemaArray.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides the getters application for the population special-case

    ", + "summary": "

    Overrides the getters application for the population special-case

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "applyGetters", + "string": "SchemaArray.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "cast", + "string": "SchemaArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "castForQuery", + "string": "SchemaArray.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': SchemaArray.prototype.castForQuery\n , '$gte': SchemaArray.prototype.castForQuery\n , '$lt': SchemaArray.prototype.castForQuery\n , '$lte': SchemaArray.prototype.castForQuery\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", + "ctx": { + "type": "function", + "name": "castToNumber", + "string": "castToNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaArray", + "string": "module.exports" + } + } +] +### lib/schema/boolean.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Boolean SchemaType constructor.

    ", + "summary": "

    Boolean SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaBoolean", + "string": "SchemaBoolean()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBoolean", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBoolean.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "checkRequired", + "string": "SchemaBoolean.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to boolean

    ", + "summary": "

    Casts to boolean

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "cast", + "string": "SchemaBoolean.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", + "ctx": { + "type": "function", + "name": "handleArray", + "string": "handleArray()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "castForQuery", + "string": "SchemaBoolean.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBoolean;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBoolean", + "string": "module.exports" + } + } +] +### lib/schema/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Buffer SchemaType constructor

    ", + "summary": "

    Buffer SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", + "ctx": { + "type": "function", + "name": "SchemaBuffer", + "string": "SchemaBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBuffer", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBuffer.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "checkRequired", + "string": "SchemaBuffer.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "cast", + "string": "SchemaBuffer.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "castForQuery", + "string": "SchemaBuffer.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBuffer;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBuffer", + "string": "module.exports" + } + } +] +### lib/schema/date.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date SchemaType constructor.

    ", + "summary": "

    Date SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaDate", + "string": "SchemaDate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaDate", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaDate.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for date

    ", + "summary": "

    Required validator for date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "checkRequired", + "string": "SchemaDate.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to date

    ", + "summary": "

    Casts to date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "cast", + "string": "SchemaDate.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date Query casting.

    ", + "summary": "

    Date Query casting.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "castForQuery", + "string": "SchemaDate.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaDate;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaDate", + "string": "module.exports" + } + } +] +### lib/schema/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaArray" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    SubdocsArray SchemaType constructor

    ", + "summary": "

    SubdocsArray SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "DocumentArray", + "string": "DocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from ArrayType.

    ", + "summary": "

    Inherits from ArrayType.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentArray", + "name": "__proto__", + "value": "ArrayType.prototype", + "string": "DocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs local validations first, then validations on each embedded doc

    ", + "summary": "

    Performs local validations first, then validations on each embedded doc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n\n SchemaType.prototype.doValidate.call(this, array, function (err) {\n if (err) return fn(err);\n\n var count = array && array.length\n , error;\n\n if (!count) return fn();\n\n // handle sparse arrays, do not use array.forEach which does not\n // iterate over sparse elements yet reports array.length including\n // them :(\n\n for (var i = 0, len = count; i < len; ++i) {\n // sidestep sparse entries\n var doc = array[i];\n if (!doc) {\n --count || fn();\n continue;\n }\n\n ;(function (i) {\n doc.validate(function (err) {\n if (err && !error) {\n // rewrite the key\n err.key = self.key + '.' + i + '.' + err.key;\n return fn(error = err);\n }\n --count || fn();\n });\n })(i);\n }\n }, scope);\n};", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "doValidate", + "string": "DocumentArray.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "document", + "description": "that triggers the casting" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument) && value[i]) {\n if (init) {\n selected || (selected = scopePaths(this, doc._selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "cast", + "string": "DocumentArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "DocumentArray" + ], + "name": "array", + "description": "- the array to scope `fields` paths" + }, + { + "type": "param", + "types": [ + "Object", + "undefined" + ], + "name": "fields", + "description": "- the root fields selected in the query" + }, + { + "type": "param", + "types": [ + "Boolean", + "undefined" + ], + "name": "init", + "description": "- if we are being created part of a query result" + } + ], + "description": { + "full": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "summary": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , hasKeys\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n hasKeys || (hasKeys = true);\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return hasKeys && selected || undefined;\n}", + "ctx": { + "type": "function", + "name": "scopePaths", + "string": "scopePaths()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = DocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "DocumentArray", + "string": "module.exports" + } + } +] +### lib/schema/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "String", + "value": "require('./string')", + "string": "exports.String" + } + } +] +### lib/schema/mixed.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Mixed SchemaType constructor.

    ", + "summary": "

    Mixed SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "Mixed", + "string": "Mixed()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "Mixed", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "Mixed.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "checkRequired", + "string": "Mixed.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", + "summary": "

    Casts val for Mixed.

    ", + "body": "

    this is a no-op

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "cast", + "string": "Mixed.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$cond", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "castForQuery", + "string": "Mixed.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Mixed;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Mixed", + "string": "module.exports" + } + } +] +### lib/schema/number.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Number SchemaType constructor.

    ", + "summary": "

    Number SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", + "ctx": { + "type": "function", + "name": "SchemaNumber", + "string": "SchemaNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaNumber", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaNumber.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for number

    ", + "summary": "

    Required validator for number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "checkRequired", + "string": "SchemaNumber.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "value", + "description": "minimum number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "min", + "string": "SchemaNumber.prototype.min()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "maximum", + "description": "number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "max", + "string": "SchemaNumber.prototype.max()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "value to cast" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to number

    ", + "summary": "

    Casts to number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "cast", + "string": "SchemaNumber.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "castForQuery", + "string": "SchemaNumber.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaNumber;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaNumber", + "string": "module.exports" + } + } +] +### lib/schema/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    ObjectId SchemaType constructor.

    ", + "summary": "

    ObjectId SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", + "ctx": { + "type": "function", + "name": "ObjectId", + "string": "ObjectId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "ObjectId", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "ObjectId.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "checkRequired", + "string": "ObjectId.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to ObjectId

    ", + "summary": "

    Casts to ObjectId

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "cast", + "string": "ObjectId.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "castForQuery", + "string": "ObjectId.prototype.castForQuery()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "turnOn", + "description": "auto generated ObjectId defaults" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "auto", + "string": "ObjectId.prototype.auto()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", + "ctx": { + "type": "function", + "name": "defaultId", + "string": "defaultId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ObjectId;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ObjectId", + "string": "module.exports" + } + } +] +### lib/schema/string.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    String SchemaType constructor.

    ", + "summary": "

    String SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", + "ctx": { + "type": "function", + "name": "SchemaString", + "string": "SchemaString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaString", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaString.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[args...]", + "description": "enumeration values" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", + "summary": "

    Adds enumeration values and a coinciding validator.

    ", + "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "enum", + "string": "SchemaString.prototype.enum()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", + "summary": "

    Adds a lowercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toLowerCase();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "lowercase", + "string": "SchemaString.prototype.lowercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", + "summary": "

    Adds an uppercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toUpperCase();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "uppercase", + "string": "SchemaString.prototype.uppercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", + "summary": "

    Adds a trim setter.

    ", + "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.trim();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "trim", + "string": "SchemaString.prototype.trim()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp" + ], + "name": "regExp", + "description": "regular expression to test against" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", + "summary": "

    Sets a regexp validator.

    ", + "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "match", + "string": "SchemaString.prototype.match()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "null", + "undefined" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "checkRequired", + "string": "SchemaString.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to String

    ", + "summary": "

    Casts to String

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "cast", + "string": "SchemaString.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "castForQuery", + "string": "SchemaString.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaString;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaString", + "string": "module.exports" + } + } +] +### lib/schema.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "definition", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted after the schema is compiled into a `Model`." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", + "summary": "

    Schema constructor.

    ", + "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • safe: bool - defaults to true.
    • \n
    • read: string
    • \n
    • strict: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • shardKey: bool - defaults to null
    • \n
    • autoIndex: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • id: bool - defaults to true
    • \n
    • toObject - object - no default
    • \n
    • toJSON - object - no default
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", + "ctx": { + "type": "function", + "name": "Schema", + "string": "Schema()" + } + }, + { + "tags": [], + "description": { + "full": "

    Returns this documents _id cast to a string.

    ", + "summary": "

    Returns this documents _id cast to a string.

    ", + "body": "" + }, + "ignore": true, + "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", + "ctx": { + "type": "function", + "name": "idGetter", + "string": "idGetter()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Schema", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Schema.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "paths" + } + ], + "description": { + "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", + "summary": "

    Schema as flat paths

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.paths;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "tree" + } + ], + "description": { + "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", + "summary": "

    Schema as a tree

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.tree;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options for this schema, merged with options.

    ", + "summary": "

    Returns default options for this schema, merged with options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.defaultOptions = function (options) {\n options = utils.options({\n safe: true\n , strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "defaultOptions", + "string": "Schema.prototype.defaultOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "prefix", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", + "summary": "

    Adds key path / schema type pairs to this schema.

    ", + "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n } else {\n this.path(prefix + i, obj[i]); // mixed type\n }\n } else {\n this.path(prefix + i, obj[i]);\n }\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "add", + "string": "Schema.prototype.add()" + } + }, + { + "tags": [], + "description": { + "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    ", + "summary": "

    Reserved document keys.

    ", + "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    " + }, + "ignore": false, + "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "reserved", + "value": "Object.create(null)", + "string": "Schema.reserved" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "constructor", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", + "summary": "

    Gets/sets schema paths.

    ", + "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(sub, i) {\n if (!branch[sub]) branch[sub] = {};\n if ('function' == typeof branch[sub]) {\n var msg = 'Cannot set nested path `' + path + '`. '\n + 'Parent path `'\n + subpaths.slice(0, i).concat([sub]).join('.')\n + '` already set to type ' + branch[sub].name\n + '.';\n throw new Error(msg);\n }\n branch = branch[sub];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "path", + "string": "Schema.prototype.path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "constructor" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts type arguments into Mongoose Types.

    ", + "summary": "

    Converts type arguments into Mongoose Types.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", + "ctx": { + "type": "method", + "receiver": "Schema", + "name": "interpretAsType", + "string": "Schema.interpretAsType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback function" + }, + { + "type": "return", + "types": [ + "Schema" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", + "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", + "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "eachPath", + "string": "Schema.prototype.eachPath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns an Array of path strings that are required by this schema.

    ", + "summary": "

    Returns an Array of path strings that are required by this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "requiredPaths", + "string": "Schema.prototype.requiredPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", + "summary": "

    Returns the pathType of path for this schema.

    ", + "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pathType", + "string": "Schema.prototype.pathType()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", + "ctx": { + "type": "function", + "name": "getPositionalPath", + "string": "getPositionalPath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the document method to call later" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds a method call to the queue.

    ", + "summary": "

    Adds a method call to the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "queue", + "string": "Schema.prototype.queue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", + "summary": "

    Defines a pre hook for the document.

    ", + "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pre", + "string": "Schema.prototype.pre()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "name of the method to hook" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", + "summary": "

    Defines a post hook for the document.

    ", + "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function () {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "post", + "string": "Schema.prototype.post()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "plugin", + "description": "callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "" + }, + { + "type": "see", + "local": "plugins", + "visibility": "plugins" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Registers a plugin for this schema.

    ", + "summary": "

    Registers a plugin for this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "plugin", + "string": "Schema.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "method", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", + "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "method", + "string": "Schema.prototype.method()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", + "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "static", + "string": "Schema.prototype.static()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", + "summary": "

    Defines an index (most likely compound) for this schema.

    ", + "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "index", + "string": "Schema.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "option name" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[value]", + "description": "if not passed, the current option value is returned" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets/gets a schema option.

    ", + "summary": "

    Sets/gets a schema option.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.set = function (key, value, tags) {\n if (arguments.length == 1)\n return this.options[key];\n\n this.options[key] = 'read' == key\n ? utils.readPref(value, tags)\n : value;\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "set", + "string": "Schema.prototype.set()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Compiles indexes from fields and schema-level indexes

    ", + "summary": "

    Compiles indexes from fields and schema-level indexes

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "indexes", + "string": "Schema.prototype.indexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", + "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", + "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " + }, + "ignore": true, + "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", + "ctx": { + "type": "function", + "name": "fixSubIndexPaths", + "string": "fixSubIndexPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Creates a virtual type with the given name.

    ", + "summary": "

    Creates a virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtual", + "string": "Schema.prototype.virtual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the virtual type with the given name.

    ", + "summary": "

    Returns the virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtualpath", + "string": "Schema.prototype.virtualpath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "namedScope", + "string": "Schema.prototype.namedScope()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Schema", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Schema Types.

    \n\n

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", + "summary": "

    The various Mongoose Schema Types.

    ", + "body": "

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.Types = require('./schema/index');", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "Types", + "value": "require('./schema/index')", + "string": "Schema.Types" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" + } +] +### lib/schemadefault.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "property", + "string": "system.profile" + }, + { + "type": "receiver", + "string": "exports" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Default model for querying the system.profiles collection.

    ", + "summary": "

    Default model for querying the system.profiles collection.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" + } +] +### lib/schematype.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');\nvar CastError = require('./errors/cast')\nvar ValidatorError = require('./errors/validator')", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[instance]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    SchemaType constructor

    ", + "summary": "

    SchemaType constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", + "ctx": { + "type": "function", + "name": "SchemaType", + "string": "SchemaType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function", + "any" + ], + "name": "val", + "description": "the default value" + }, + { + "type": "return", + "types": [ + "defaultValue" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", + "summary": "

    Sets a default value for this SchemaType.

    ", + "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "default", + "string": "SchemaType.prototype.default()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "Boolean" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", + "summary": "

    Declares the index options for this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.path').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "index", + "string": "SchemaType.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares an unique index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    ", + "summary": "

    Declares an unique index.

    ", + "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "unique", + "string": "SchemaType.prototype.unique()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a sparse index.

    \n\n

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", + "summary": "

    Declares a sparse index.

    ", + "body": "

    Examples:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "sparse", + "string": "SchemaType.prototype.sparse()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "when", + "description": "" + }, + { + "type": "added", + "string": "3.0.0" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    ", + "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", + "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: 60*60*24 });\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({..}, { expires: '24h' });\n\n// expire in 1.5 hours\nnew Schema({..}, { expires: '1.5h' });\n\n// expire in 7 days\nvar schema = new Schema({..});\nschema.expires('7d');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "expires", + "string": "SchemaType.prototype.expires()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    ", + "summary": "

    Adds a setter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "set", + "string": "SchemaType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    ", + "summary": "

    Adds a getter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "get", + "string": "SchemaType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp", + "Function", + "Object" + ], + "name": "obj", + "description": "validator" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[error]", + "description": "optional error message" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", + "summary": "

    Adds validator(s) for this document path.

    ", + "body": "

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "validate", + "string": "SchemaType.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "required", + "description": "enable/disable the validator" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", + "summary": "

    Adds a required validator to this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "required", + "string": "SchemaType.prototype.required()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope which callback are executed" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets the default value

    ", + "summary": "

    Gets the default value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "getDefault", + "string": "SchemaType.prototype.getDefault()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies setters

    ", + "summary": "

    Applies setters

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applySetters", + "string": "SchemaType.prototype.applySetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies getters to a value

    ", + "summary": "

    Applies getters to a value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applyGetters", + "string": "SchemaType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", + "summary": "

    Sets default select() behavior for this path.

    ", + "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "select", + "string": "SchemaType.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "doValidate", + "string": "SchemaType.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if value is a valid Reference.

    ", + "summary": "

    Determines if value is a valid Reference.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", + "ctx": { + "type": "method", + "receiver": "SchemaType", + "name": "_isRef", + "string": "SchemaType._isRef()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = SchemaType", + "string": "module.exports" + } + } +] +### lib/statemachine.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", + "ctx": { + "type": "declaration", + "name": "StateMachine", + "value": "module.exports = exports = function StateMachine () {", + "string": "StateMachine" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "subclass constructor" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", + "ctx": { + "type": "method", + "receiver": "StateMachine", + "name": "ctor", + "string": "StateMachine.ctor()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", + "summary": "

    This function is wrapped by the state change functions

    ", + "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_changeState", + "string": "StateMachine.prototype._changeState()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "clear", + "string": "StateMachine.prototype.clear()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "that we want to check for." + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "some", + "string": "StateMachine.prototype.some()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "iterMethod", + "description": "is either 'forEach' or 'map'" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_iter", + "string": "StateMachine.prototype._iter()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "forEach", + "string": "StateMachine.prototype.forEach()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "map", + "string": "StateMachine.prototype.map()" + } + } +] +### lib/types/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", + "ctx": { + "type": "declaration", + "name": "EmbeddedDocument", + "value": "require('./embedded')", + "string": "EmbeddedDocument" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Array" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", + "summary": "

    Mongoose Array constructor.

    ", + "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseArray", + "string": "MongooseArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Array

    ", + "summary": "

    Inherit from Array

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseArray.prototype = new Array;", + "ctx": { + "type": "property", + "receiver": "MongooseArray", + "name": "prototype", + "value": "new Array", + "string": "MongooseArray.prototype" + } + }, + { + "tags": [ + { + "type": "property", + "string": "_atomics" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores a queue of atomic operations to perform

    ", + "summary": "

    Stores a queue of atomic operations to perform

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._atomics;" + }, + { + "tags": [ + { + "type": "property", + "string": "_parent" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._parent;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "return", + "types": [ + "value" + ], + "description": "the casted value" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts a member based on this arrays schema.

    ", + "summary": "

    Casts a member based on this arrays schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_cast", + "string": "MongooseArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "EmbeddedDocument" + ], + "name": "embeddedDoc", + "description": "the embedded doc that invoked this method on the Array" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "embeddedPath", + "description": "the path which changed in the embeddedDoc" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", + "summary": "

    Marks this array as modified.

    ", + "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._markModified = function (elem, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n dirtyPath = this._path;\n\n if (arguments.length) {\n if (null != embeddedPath) {\n // an embedded doc bubbled up the change\n dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;\n } else {\n // directly set an index\n dirtyPath = dirtyPath + '.' + elem;\n }\n\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_markModified", + "string": "MongooseArray.prototype._markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "op", + "description": "operation" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register an atomic operation with the parent.

    ", + "summary": "

    Register an atomic operation with the parent.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (this._atomics.$set ||\n Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_registerAtomic", + "string": "MongooseArray.prototype._registerAtomic()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "hasAtomics", + "string": "MongooseArray.prototype.hasAtomics()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#push with proper change tracking.

    ", + "summary": "

    Wraps Array#push with proper change tracking.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "push", + "string": "MongooseArray.prototype.push()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Pushes items to the array non-atomically.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "nonAtomicPush", + "string": "MongooseArray.prototype.nonAtomicPush()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "$pop" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", + "summary": "

    Pops the array atomically at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n this._markModified();\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" + }, + { + "tags": [ + { + "type": "see", + "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", + "visibility": "MongooseArray#$pop" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#pop with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pop", + "string": "MongooseArray.prototype.pop()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "method", + "string": "$shift" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", + "summary": "

    Atomically shifts the array at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n this._markModified();\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#shift with proper change tracking.

    ", + "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "shift", + "string": "MongooseArray.prototype.shift()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "values to remove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes items from an array atomically

    \n\n

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    ", + "summary": "

    Removes items from an array atomically

    ", + "body": "

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "remove", + "string": "MongooseArray.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pulls items from the array atomically.

    ", + "summary": "

    Pulls items from the array atomically.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n this._markModified();\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pull", + "string": "MongooseArray.prototype.pull()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#splice with proper change tracking and casting.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#splice with proper change tracking and casting.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.splice = function splice () {\n var ret, vals, i;\n\n if (arguments.length) {\n vals = [];\n for (i = 0; i < arguments.length; ++i) {\n vals[i] = i < 2\n ? arguments[i]\n : this._cast(arguments[i]);\n }\n ret = [].splice.apply(this, vals);\n this._registerAtomic('$set', this);\n this._markModified();\n }\n\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "splice", + "string": "MongooseArray.prototype.splice()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#unshift with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return this.length;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "unshift", + "string": "MongooseArray.prototype.unshift()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#sort with proper change tracking.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "sort", + "string": "MongooseArray.prototype.sort()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "the values that were added" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", + "summary": "

    Adds values to the array if not already present.

    ", + "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n this._markModified();\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "addToSet", + "string": "MongooseArray.prototype.addToSet()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the casted val at index i and marks the array modified.

    \n\n

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    ", + "summary": "

    Sets the casted val at index i and marks the array modified.

    ", + "body": "

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.set = function set (i, val) {\n this[i] = this._cast(val);\n this._markModified(i);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "set", + "string": "MongooseArray.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array.

    ", + "summary": "

    Returns a native js Array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "toObject", + "string": "MongooseArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "inspect", + "string": "MongooseArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the item to look for" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Return the index of obj or -1 if not found.

    ", + "summary": "

    Return the index of obj or -1 if not found.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "indexOf", + "string": "MongooseArray.prototype.indexOf()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = MongooseArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = MongooseArray", + "string": "module.exports" + } + } +] +### lib/types/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require(driver + '/binary');", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require(driver + '/binary')", + "string": "Binary" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "encode", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "offset", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Buffer" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", + "summary": "

    Mongoose Buffer constructor.

    ", + "body": "

    Values always have to be passed to the constructor to initialize.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", + "ctx": { + "type": "function", + "name": "MongooseBuffer", + "string": "MongooseBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Buffer.

    ", + "summary": "

    Inherit from Buffer.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.prototype = new Buffer(0);", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "prototype", + "value": "new Buffer(0)", + "string": "MongooseBuffer.prototype" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "_parent" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._parent;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this buffer as modified.

    ", + "summary": "

    Marks this buffer as modified.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "_markModified", + "string": "MongooseBuffer.prototype._markModified()" + } + }, + { + "tags": [], + "description": { + "full": "

    Writes the buffer.

    ", + "summary": "

    Writes the buffer.

    ", + "body": "" + }, + "ignore": false, + "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "write", + "string": "MongooseBuffer.prototype.write()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "MongooseBuffer" + ], + "description": "" + }, + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "target", + "description": "" + } + ], + "description": { + "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", + "summary": "

    Copies the buffer.

    ", + "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "copy", + "string": "MongooseBuffer.prototype.copy()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "body": "" + }, + "ignore": true, + "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://bsonspec.org/#/specification", + "visibility": "http://bsonspec.org/#/specification" + }, + { + "type": "param", + "types": [ + "Hex" + ], + "name": "[subtype]", + "description": "" + }, + { + "type": "return", + "types": [ + "Binary" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", + "summary": "

    Converts this buffer to its Binary type representation.

    ", + "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "toObject", + "string": "MongooseBuffer.prototype.toObject()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "Binary", + "value": "Binary", + "string": "MongooseBuffer.Binary" + } + } +] +### lib/types/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", + "ctx": { + "type": "declaration", + "name": "MongooseArray", + "value": "require('./array')", + "string": "MongooseArray" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to this array" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "MongooseDocumentArray" + ], + "description": "" + }, + { + "type": "inherits", + "string": "MongooseArray" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    DocumentArray constructor

    ", + "summary": "

    DocumentArray constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseDocumentArray", + "string": "MongooseDocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseArray

    ", + "summary": "

    Inherits from MongooseArray

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseDocumentArray", + "name": "__proto__", + "value": "MongooseArray.prototype", + "string": "MongooseDocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides MongooseArray#cast

    ", + "summary": "

    Overrides MongooseArray#cast

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype._cast = function (value) {\n if (value instanceof this._schema.casterConstructor)\n return value;\n\n return new this._schema.casterConstructor(value, this);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "_cast", + "string": "MongooseDocumentArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "EmbeddedDocument", + "null" + ], + "description": "the subdocuent or null if not found." + }, + { + "type": "param", + "types": [ + "ObjectId", + "String", + "Number", + "Buffer" + ], + "name": "id", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Searches array items for the first document with a matching id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", + "summary": "

    Searches array items for the first document with a matching id.

    ", + "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "id", + "string": "MongooseDocumentArray.prototype.id()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", + "summary": "

    Returns a native js Array of plain js objects

    ", + "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "toObject", + "string": "MongooseDocumentArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "inspect", + "string": "MongooseDocumentArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the value to cast to this arrays SubDocument schema" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", + "summary": "

    Creates a subdocument casted to this schema.

    ", + "body": "

    This is the same subdocument constructor used for casting.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "create", + "string": "MongooseDocumentArray.prototype.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates a fn that notifies all child docs of event.

    ", + "summary": "

    Creates a fn that notifies all child docs of event.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n if (!self[i]) continue;\n self[i].emit(event, val);\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "notify", + "string": "MongooseDocumentArray.prototype.notify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseDocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseDocumentArray", + "string": "module.exports" + } + } +] +### lib/types/embedded.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('../document')\n , inspect = require('util').inspect;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('../document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "js object returned from the db" + }, + { + "type": "param", + "types": [ + "MongooseDocumentArray" + ], + "name": "parentArr", + "description": "the parent array of this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "skipId", + "description": "" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    EmbeddedDocument constructor.

    ", + "summary": "

    EmbeddedDocument constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", + "ctx": { + "type": "function", + "name": "EmbeddedDocument", + "string": "EmbeddedDocument()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Document

    ", + "summary": "

    Inherit from Document

    ", + "body": "" + }, + "ignore": true, + "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "EmbeddedDocument", + "name": "__proto__", + "value": "Document.prototype", + "string": "EmbeddedDocument.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path which changed" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", + "summary": "

    Marks the embedded doc modified.

    ", + "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "markModified", + "string": "EmbeddedDocument.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "return", + "types": [ + "EmbeddedDocument" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", + "summary": "

    Used as a stub for hooks.js

    ", + "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "save", + "string": "EmbeddedDocument.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes the subdocument from its parent array.

    ", + "summary": "

    Removes the subdocument from its parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "remove", + "string": "EmbeddedDocument.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Override #update method of parent documents.

    ", + "summary": "

    Override #update method of parent documents.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "update", + "string": "EmbeddedDocument.prototype.update()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "inspect", + "string": "EmbeddedDocument.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "error which states the reason `path` was invalid" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "invalidate", + "string": "EmbeddedDocument.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "ownerDocument", + "string": "EmbeddedDocument.prototype.ownerDocument()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", + "ctx": { + "type": "function", + "name": "ownerDocument", + "string": "ownerDocument()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent document.

    ", + "summary": "

    Returns this sub-documents parent document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parent", + "string": "EmbeddedDocument.prototype.parent()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent array.

    ", + "summary": "

    Returns this sub-documents parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parentArray", + "string": "EmbeddedDocument.prototype.parentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = EmbeddedDocument;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "EmbeddedDocument", + "string": "module.exports" + } + } +] +### lib/types/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "Array", + "value": "require('./array')", + "string": "exports.Array" + } + } +] +### lib/types/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [ + { + "type": "constructor", + "string": "ObjectId" + } + ], + "description": { + "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", + "summary": "

    ObjectId type constructor

    ", + "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require(driver + '/objectid')", + "string": "ObjectId" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "str", + "description": "" + }, + { + "type": "static", + "string": "fromString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "ObjectId" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates an ObjectId from str

    ", + "summary": "

    Creates an ObjectId from str

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.fromString;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId" + ], + "name": "oid", + "description": "ObjectId instance" + }, + { + "type": "static", + "string": "toString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts oid to a string.

    ", + "summary": "

    Converts oid to a string.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.toString;" + } +] +### lib/utils.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , sliced = require('sliced')\n , MongooseBuffer\n , MongooseArray\n , Document", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "a model name" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "a collection name" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a collection name from model name.

    ", + "summary": "

    Produces a collection name from model name.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "toCollectionName", + "string": "exports.toCollectionName()" + } + }, + { + "tags": [], + "description": { + "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Pluralization rules.

    ", + "body": "

    These rules are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "pluralization", + "value": "[", + "string": "exports.pluralization" + } + }, + { + "tags": [], + "description": { + "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Uncountable words.

    ", + "body": "

    These words are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news',\n 'expertise',\n 'status',\n 'media'\n];\nvar uncountables = exports.uncountables;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "uncountables", + "value": "[", + "string": "exports.uncountables" + } + }, + { + "tags": [ + { + "type": "author", + "string": "TJ Holowaychuk (extracted from _ext.js_)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "string", + "description": "to pluralize" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pluralize function.

    ", + "summary": "

    Pluralize function.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", + "ctx": { + "type": "function", + "name": "pluralize", + "string": "pluralize()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "listener", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Add once to EventEmitter if absent

    ", + "summary": "

    Add once to EventEmitter if absent

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", + "ctx": { + "type": "declaration", + "name": "Events", + "value": "EventEmitter", + "string": "Events" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Events", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Events.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Add once.

    ", + "summary": "

    Add once.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", + "ctx": { + "type": "method", + "constructor": "Events", + "name": "once", + "string": "Events.prototype.once()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "a", + "description": "a value to compare to `b`" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "b", + "description": "a value to compare to `a`" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", + "summary": "

    Determines if a and b are deep equal.

    ", + "body": "

    Modified from node/lib/assert.js

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "deepEqual", + "string": "exports.deepEqual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the object to clone" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the cloned object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Object clone with Mongoose natives support.

    \n\n

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    ", + "summary": "

    Object clone with Mongoose natives support.

    ", + "body": "

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId)\n return new ObjectId(obj.id);\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "clone", + "string": "exports.clone()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", + "ctx": { + "type": "function", + "name": "cloneObject", + "string": "cloneObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "defaults", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the merged object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Copies and merges options with defaults.

    ", + "summary": "

    Copies and merges options with defaults.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "options", + "string": "exports.options()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Generates a random string

    ", + "summary": "

    Generates a random string

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "random", + "string": "exports.random()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "to", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "from", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges from into to without overwriting existing properties.

    ", + "summary": "

    Merges from into to without overwriting existing properties.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n if (exports.isObject(from[key])) {\n merge(to[key], from[key]);\n } else {\n to[key] = from[key];\n }\n }\n }\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "merge", + "string": "exports.merge()" + } + }, + { + "tags": [], + "description": { + "full": "

    toString helper

    ", + "summary": "

    toString helper

    ", + "body": "" + }, + "ignore": true, + "code": "var toString = Object.prototype.toString;", + "ctx": { + "type": "declaration", + "name": "toString", + "value": "Object.prototype.toString", + "string": "toString" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "Array", + "String", + "Function", + "RegExp", + "any" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + } + ], + "description": { + "full": "

    Determines if arg is an object.

    ", + "summary": "

    Determines if arg is an object.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "exports.isObject = function (arg) {\n return '[object Object]' == toString(arg);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isObject", + "string": "exports.isObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.args = sliced;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "args", + "value": "sliced", + "string": "exports.args" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", + "summary": "

    process.nextTick helper.

    ", + "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "tick", + "string": "exports.tick()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "v", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", + "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", + "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isMongooseObject", + "string": "exports.isMongooseObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "object", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expireAfterSeconds = when;\n delete object.expires;\n}\n\nexports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "expires", + "string": "exports.expires()" + } + } +] +### lib/virtualtype.js +[ + { + "tags": [ + { + "type": "parma", + "string": "{Object} options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", + "summary": "

    VirtualType constructor

    ", + "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", + "ctx": { + "type": "function", + "name": "VirtualType", + "string": "VirtualType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", + "summary": "

    Defines a getter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "get", + "string": "VirtualType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", + "summary": "

    Defines a setter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "set", + "string": "VirtualType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all getters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies getters to value using optional scope.

    ", + "summary": "

    Applies getters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applyGetters", + "string": "VirtualType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all setters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies setters to value using optional scope.

    ", + "summary": "

    Applies setters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applySetters", + "string": "VirtualType.prototype.applySetters()" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = VirtualType;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "VirtualType", + "string": "module.exports" + } + } +] diff --git a/docs/3.3.x/docs/source/api.js b/docs/3.3.x/docs/source/api.js new file mode 100644 index 00000000000..8fd87f0035b --- /dev/null +++ b/docs/3.3.x/docs/source/api.js @@ -0,0 +1,220 @@ +/*! + * Module dependencies + */ + +var fs = require('fs'); +var link = require('../helpers/linktype'); +var hl = require('highlight.js') +var md = require('markdown') + +module.exports = { + docs: [] + , github: 'https://github.com/LearnBoost/mongoose/tree/' + , title: 'API docs' +} + +var out = module.exports.docs; + +var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); +parse(docs); +order(out); + +function parse (docs) { + docs.split(/^### /gm).forEach(function (chunk) { + if (!(chunk = chunk.trim())) return; + + chunk = chunk.split(/^([^\n]+)\n/); + + var title = chunk[1]; + + if (!title || !(title = title.trim())) + throw new Error('missing title'); + + title = title.replace(/^lib\//, ''); + + var json = JSON.parse(chunk[2]); + + var props = []; + var methods = []; + var statics = []; + var constructor = null; + + json.forEach(function (comment) { + if (comment.description) + highlight(comment.description); + + var prop = false; + comment.params = []; + comment.see = []; + + var i = comment.tags.length; + while (i--) { + var tag = comment.tags[i]; + switch (tag.type) { + case 'property': + prop = true; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + props.unshift(comment); + break; + case 'method': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'method'; + comment.code = ''; + break; + case 'memberOf': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.constructor = tag.parent; + break; + case 'static': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + comment.ctx.type = 'method'; + break; + case 'receiver': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.receiver = tag.string; + break; + case 'constructor': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'function'; + comment.code = ''; + break; + case 'inherits': + if (/http/.test(tag.string)) { + var result = tag.string.split(' '); + var href = result.pop(); + var title = result.join(' '); + comment.inherits = '' + title + ''; + } else { + comment.inherits = link(tag.string); + } + comment.tags.splice(i, 1); + break; + case 'param': + comment.params.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'return': + comment.return = tag; + comment.tags.splice(i, 1); + break; + case 'see': + if (tag.local) { + var parts = tag.local.split(' '); + if (1 === parts.length) { + tag.url = link.type(parts[0]); + tag.title = parts[0]; + } else { + tag.url = parts.pop(); + tag.title = parts.join(' '); + } + } + comment.see.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'event': + var str = tag.string.replace(/\\n/g, '\n'); + tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); + comment.events || (comment.events = []); + comment.events.unshift(tag); + comment.tags.splice(i, 1); + } + } + + if (!prop) { + methods.push(comment); + } + }); + + methods = methods.filter(ignored); + props = props.filter(ignored); + + function ignored (method) { + if (method.ignore) return false; + return true; + } + + if (0 === methods.length + props.length) return; + + // add constructor to properties too + methods.some(function (method) { + if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { + props.forEach(function (prop) { + prop.ctx.constructor = method.ctx.constructor; + }); + return true; + } + return false; + }); + + var len = methods.length; + while (len--) { + method = methods[len]; + if (method.ctx && method.ctx.receiver) { + var stat = methods.splice(len, 1)[0]; + statics.unshift(stat); + } + } + + out.push({ + title: title + , methods: methods + , props: props + , statics: statics + , hasPublic: hasPublic(methods, props, statics) + }); + }); +} + +function hasPublic () { + for (var i = 0; i < arguments.length; ++i) { + var arr = arguments[i]; + for (var j = 0; j < arr.length; ++j) { + var item = arr[j]; + if (!item.ignore && !item.isPrivate) return true; + } + } + return false; +} + +// add "class='language'" to our
     elements
    +function highlight (o) {
    +  o.full = fix(o.full);
    +  o.summary = fix(o.summary);
    +  o.body = fix(o.body);
    +}
    +
    +function fix (str) {
    +  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    +
    +    // parse out the ```language
    +    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    +
    +    if ('js' == code[1] || !code[1]) {
    +      code[1] = 'javascript';
    +    }
    +
    +    return $1
    +          + hl.highlight(code[1], code[2]).value.trim()
    +          + $3;
    +  });
    +}
    +
    +function order (docs) {
    +  // want index first
    +  for (var i = 0; i < docs.length; ++i) {
    +    if ('index.js' == docs[i].title) {
    +      docs.unshift(docs.splice(i, 1)[0]);
    +    }
    +  }
    +}
    diff --git a/docs/3.3.x/docs/source/home.js b/docs/3.3.x/docs/source/home.js
    new file mode 100644
    index 00000000000..e349d8ddcad
    --- /dev/null
    +++ b/docs/3.3.x/docs/source/home.js
    @@ -0,0 +1,7 @@
    +
    +var package = require('./../../package.json')
    +
    +module.exports = {
    +    package: package
    +  , title: 'ODM'
    +}
    diff --git a/docs/3.3.x/docs/source/index.js b/docs/3.3.x/docs/source/index.js
    new file mode 100644
    index 00000000000..18b3eeb5718
    --- /dev/null
    +++ b/docs/3.3.x/docs/source/index.js
    @@ -0,0 +1,20 @@
    +
    +exports['index.jade'] = require('./home')
    +exports['docs/api.jade'] = require('./api')
    +exports['docs/index.jade'] = { title: 'Getting Started' }
    +exports['docs/production.jade'] = require('./production')
    +exports['docs/prior.jade'] = require('./prior')
    +exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    +exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    +exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    +exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    +exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    +exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    +exports['docs/models.jade'] = { guide: true, title: 'Models' }
    +exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    +exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    +exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    +exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    +exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    +exports['docs/connections.jade'] = { guide: true, title: 'Connecting to MongoDB' }
    +exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.3.x/docs/source/prior.js b/docs/3.3.x/docs/source/prior.js
    new file mode 100644
    index 00000000000..2e03811d215
    --- /dev/null
    +++ b/docs/3.3.x/docs/source/prior.js
    @@ -0,0 +1,13 @@
    +var fs = require('fs')
    +var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    +releases = releases.split('\n').filter(Boolean);
    +
    +module.exports = exports = {
    +    title: ''
    +  , releases: releases.map(function (version) {
    +      return {
    +          url: version + '/'
    +        , version: version
    +      }
    +    })
    +}
    diff --git a/docs/3.3.x/docs/source/production.js b/docs/3.3.x/docs/source/production.js
    new file mode 100644
    index 00000000000..9fdbcfffbc7
    --- /dev/null
    +++ b/docs/3.3.x/docs/source/production.js
    @@ -0,0 +1,17 @@
    +
    +var fs = require('fs')
    +var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    +
    +var imgs = [];
    +
    +images.forEach(function (line) {
    +  line = line.trim();
    +  if (!line) return;
    +  line = line.split('|');
    +  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    +});
    +
    +module.exports = {
    +    images: imgs
    +  , title: 'Production'
    +}
    diff --git a/docs/3.3.x/docs/subdocs.html b/docs/3.3.x/docs/subdocs.html
    new file mode 100644
    index 00000000000..42f1c21c61d
    --- /dev/null
    +++ b/docs/3.3.x/docs/subdocs.html
    @@ -0,0 +1,49 @@
    +Mongoose SubDocuments v3.3.1Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    +
    +var parentSchema = new Schema({
    +  children: [childSchema]
    +})
    +

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = db.model('Parent', parentSchema);
    +var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    +parent.children[0].name = 'Matthew';
    +parent.save(callback);
    +

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    +  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    +  next();
    +});
    +
    +var parent = new Parent({ children: [{ name: 'invalid' }] });
    +parent.save(function (err) {
    +  console.log(err.message) // #sadpanda
    +})
    +

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    +

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = db.model('Parent');
    +var parent = new Parent;
    +
    +// create a comment
    +post.children.push({ name: 'Liesl' });
    +var doc = post.children[0];
    +console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    +doc.isNew; // true
    +
    +post.save(function (err) {
    +  if (err) return handleError(err)
    +  console.log('Success!');
    +});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    +

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    +parent.save(function (err) {
    +  if (err) return handleError(err);
    +  console.log('the sub-doc was removed')
    +});
    +

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    +  children: [{ name: 'string' }]
    +})
    +

    Next Up

    Now that we've covered Sub-documents, let's take a look at querying.

    diff --git a/docs/3.3.x/docs/subdocs.jade b/docs/3.3.x/docs/subdocs.jade new file mode 100644 index 00000000000..9e568e3ab74 --- /dev/null +++ b/docs/3.3.x/docs/subdocs.jade @@ -0,0 +1,84 @@ +extends layout + +block content + h2 Sub Docs + :markdown + [Sub-documents](./api.html#types-embedded-js) are docs with schemas of their own which are elements of a parents document array: + :js + var childSchema = new Schema({ name: 'string' }); + + var parentSchema = new Schema({ + children: [childSchema] + }) + + :markdown + Sub-documents enjoy all the same features as normal [documents](./api.html#document-js). The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved. + :js + var Parent = db.model('Parent', parentSchema); + var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) + parent.children[0].name = 'Matthew'; + parent.save(callback); + + :markdown + If an error occurs in a sub-documents' middleware, it is bubbled up to the `save()` callback of the parent, so error handling is a snap! + + :js + childSchema.pre('save', function (next) { + if ('invalid' == this.name) return next(new Error('#sadpanda')); + next(); + }); + + var parent = new Parent({ children: [{ name: 'invalid' }] }); + parent.save(function (err) { + console.log(err.message) // #sadpanda + }) + + h3 Finding a sub-document + :markdown + Each document has an `_id`. DocumentArrays have a special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method for looking up a document by its `_id`. + :js + var doc = parent.children.id(id); + + h3 Adding sub-docs + :markdown + MongooseArray methods such as [push](./api.html#types_array_MongooseArray-push), [unshift](./api.html#types_array_MongooseArray-unshift), [addToSet](./api.html#types_array_MongooseArray-addToSet), and others cast arguments to their proper types transparently: + :js + var Parent = db.model('Parent'); + var parent = new Parent; + + // create a comment + post.children.push({ name: 'Liesl' }); + var doc = post.children[0]; + console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' } + doc.isNew; // true + + post.save(function (err) { + if (err) return handleError(err) + console.log('Success!'); + }); + :markdown + Sub-docs may also be created without adding them to the array by using the [create](./api.html#types_documentarray_MongooseDocumentArray-create) method of MongooseArrays. + :js + var newdoc = post.children.create({ name: 'Aaron' }); + + h3 Removing docs + :markdown + Each sub-document has it's own [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. + :js + var doc = parent.children.id(id).remove(); + parent.save(function (err) { + if (err) return handleError(err); + console.log('the sub-doc was removed') + }); + + h4#altsyntax Alternate declaration syntax + :markdown + _New in v3_ If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal: + :js + var parentSchema = new Schema({ + children: [{ name: 'string' }] + }) + + h3#next Next Up + :markdown + Now that we've covered `Sub-documents`, let's take a look at [querying](/docs/queries.html). diff --git a/docs/3.3.x/docs/validation.html b/docs/3.3.x/docs/validation.html new file mode 100644 index 00000000000..7a7d182e83e --- /dev/null +++ b/docs/3.3.x/docs/validation.html @@ -0,0 +1,37 @@ +Mongoose Validation v3.3.1Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    + +
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    + +

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    +  color: String,
    +  name: String
    +});
    +
    +var Toy = db.model('Toy', toySchema);
    +
    +Toy.schema.path('color').validate(function (value) {
    +  return /blue|green|white|red|orange|periwinkel/i.test(value);
    +}, 'Invalid color');
    +
    +var toy = new Toy({ color: 'grease'});
    +
    +toy.save(function (err) {
    +  // err.errors.color is a ValidatorError object
    +  
    +  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(err.errors.color.type) // prints "Invalid color"
    +  console.log(err.errors.color.path) // prints "color"
    +  console.log(err.name) // prints "ValidationError"
    +  console.log(err.message) // prints "Validation failed"
    +});
    +

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    +

    Next Up

    Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

    diff --git a/docs/3.3.x/docs/validation.jade b/docs/3.3.x/docs/validation.jade new file mode 100644 index 00000000000..5b267bf95a5 --- /dev/null +++ b/docs/3.3.x/docs/validation.jade @@ -0,0 +1,58 @@ +extends layout + +block content + h2 Validation + :markdown + Before we get into the specifics of validation syntax, please keep the following rules in mind: + + - Validation is defined in the [SchemaType](./schematypes.html) + - Validation is an internal piece of [middleware](./middleware.html) + - Validation occurs when a document attempts to be [saved](./api.html#model_Model-save), after defaults have been applied + - Validation is asynchronously recursive: when you call [Model#save](./api.html#model_Model-save), sub-document validation is executed. If an error happens, your Model#save callback receives it + - Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, `"min"` is the identifier for the error triggered when a number doesn't meet the [minimum value](./api.html#schema_number_SchemaNumber-min). The path and value that triggered the error can be accessed in the `ValidationError` object + h3 Built in validators + :markdown + Mongoose has several built in validators. + + - All [SchemaTypes](./schematypes.html) have the built in [required](./api.html#schematype_SchemaType-required) validator. + - [Numbers](./api.html#schema-number-js) have [min](./api.html#schema_number_SchemaNumber-min) and [max](./api.html#schema_number_SchemaNumber-max) validators. + - [Strings](./api.html#schema-string-js) have [enum](./api.html#schema_string_SchemaString-enum) and [match](./api.html#schema_string_SchemaString-match) validators. + h3 Custom validators + :markdown + Custom validation is declared by passing a validation `function` and an error type to your `SchemaType`s validate method. Read the [API](./api.html#schematype_SchemaType-validate) docs for details on custom validators, async validators, and more. + h3 Validation errors + :markdown + Errors returned after failed validation contain an `errors` object holding the actual `ValidatorErrors`. Each [ValidatorError](./api.html#errors-validation-js) has a `type` and `path` property providing us with a little more error handling flexibility. + :js + var toySchema = new Schema({ + color: String, + name: String + }); + + var Toy = db.model('Toy', toySchema); + + Toy.schema.path('color').validate(function (value) { + return /blue|green|white|red|orange|periwinkel/i.test(value); + }, 'Invalid color'); + + var toy = new Toy({ color: 'grease'}); + + toy.save(function (err) { + // err.errors.color is a ValidatorError object + + console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color' + console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color' + console.log(err.errors.color.type) // prints "Invalid color" + console.log(err.errors.color.path) // prints "color" + console.log(err.name) // prints "ValidationError" + console.log(err.message) // prints "Validation failed" + }); + + :markdown + After a validation error, the document will also have the same `errors` property available: + :js + toy.errors.color.message === err.errors.color.message + + h3#next Next Up + :markdown + Now that we've covered `validation`, let's take a look at how you might handle advanced validation with Mongoose's [middleware](/docs/middleware.html). diff --git a/docs/3.3.x/docs/website.js b/docs/3.3.x/docs/website.js new file mode 100644 index 00000000000..d1adea38b5c --- /dev/null +++ b/docs/3.3.x/docs/website.js @@ -0,0 +1,48 @@ + +var fs= require('fs') +var jade = require('jade') +var package = require('./package') +var hl = require('./docs/helpers/highlight') +var linktype = require('./docs/helpers/linktype') +var href = require('./docs/helpers/href') +var klass = require('./docs/helpers/klass') + +// add custom jade filters +require('./docs/helpers/filters')(jade); + +// clean up version for ui +package.version = package.version.replace(/-pre$/, ''); + +var filemap = require('./docs/source'); +var files = Object.keys(filemap); + +files.forEach(function (file) { + var filename = __dirname + '/' + file; + jadeify(filename, filemap[file]); + + if ('--watch' == process.argv[2]) { + fs.watchFile(filename, { interval: 1000 }, function (cur, prev) { + if (cur.mtime > prev.mtime) { + jadeify(filename, filemap[file]); + } + }); + } +}); + +function jadeify (filename, options) { + options || (options = {}); + options.package = package; + options.hl = hl; + options.linktype = linktype; + options.href = href; + options.klass = klass; + jade.renderFile(filename, options, function (err, str) { + if (err) return console.error(err.stack); + + var newfile = filename.replace('.jade', '.html') + fs.writeFile(newfile, str, function (err) { + if (err) return console.error('could not write', err.stack); + console.log('%s : rendered ', new Date, newfile); + }); + }); +} diff --git a/docs/3.3.x/index.html b/docs/3.3.x/index.html new file mode 100644 index 00000000000..ceb880d8c89 --- /dev/null +++ b/docs/3.3.x/index.html @@ -0,0 +1,20 @@ +Mongoose ODM v3.3.1Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

    var mongoose = require('mongoose');
    +var db = mongoose.createConnection('localhost', 'test');
    +
    +var schema = mongoose.Schema({ name: 'string' });
    +var Cat = db.model('Cat', schema);
    +
    +var kitty = new Cat({ name: 'Zildjian' });
    +kitty.save(function (err) {
    +  if (err) // ...
    +  res.end('meow');
    +});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    Production + View More

    • Storify
    • LearnBoost
    • GeekList
    • McDonalds
    • ShoeJitsu
    • Bozuko
    \ No newline at end of file diff --git a/docs/3.3.x/static.js b/docs/3.3.x/static.js new file mode 100644 index 00000000000..fc0e722dd4e --- /dev/null +++ b/docs/3.3.x/static.js @@ -0,0 +1,17 @@ + +var static = require('node-static'); +var server = new static.Server('.', { cache: 0 }); + +require('http').createServer(function (req, res) { + req.on('end', function () { + server.serve(req, res, function (err) { + if (err) { + console.error(err, req.url); + res.writeHead(err.status, err.headers); + res.end(); + } + }); + }); +}).listen(8088); + +console.error('now listening on localhost:8088'); diff --git a/docs/3.4.x/docs/api.html b/docs/3.4.x/docs/api.html new file mode 100644 index 00000000000..53740ed405f --- /dev/null +++ b/docs/3.4.x/docs/api.html @@ -0,0 +1,6999 @@ +Mongoose API v3.4.0Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      +  this.connections = [];
      +  this.plugins = [];
      +  this.models = {};
      +  this.modelSchemas = {};
      +  this.options = {};
      +  this.createConnection(); // default connection
      +};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +  this.options[key] = value;
      +  return this;
      +};

      Parameters:

      Example:

      + +
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      + +
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri], [options])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      +  var conn = new Connection(this);
      +  this.connections.push(conn);
      +
      +  if (arguments.length) {
      +    if (rgxReplSet.test(arguments[0])) {
      +      conn.openSet.apply(conn, arguments);
      +    } else {
      +      conn.open.apply(conn, arguments);
      +    }
      +  }
      +
      +  return conn;
      +};

      Parameters:

      • [uri] <String> a mongodb:// URI
      • [options] <Object> options to pass to the driver

      Returns:

      Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

      + +

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver. Note that the safe option specified in your schema will overwrite the safe db option specified here unless you set your schemas safe option to undefined. See this for more information.

      + +

      Example:

      + +
      // with mongodb:// URI
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
      +
      +// and options
      +var opts = { db: { native_parser: true }}
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
      +
      +// replica sets
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
      +
      +// and options
      +var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
      +
      +// with [host, database_name[, port] signature
      +db = mongoose.createConnection('localhost', 'database', port)
      +
      +// and options
      +var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
      +db = mongoose.createConnection('localhost', 'database', port, opts)
      +
      +// initialize now, connect later
      +db = mongoose.createConnection();
      +db.open('localhost', 'database', port, [opts]);

      Mongoose#connect()

      Opens the default mongoose connection.

      show code
      Mongoose.prototype.connect = function () {
      +  var conn = this.connection;
      +
      +  if (rgxReplSet.test(arguments[0])) {
      +    conn.openSet.apply(conn, arguments);
      +  } else {
      +    conn.open.apply(conn, arguments);
      +  }
      +
      +  return this;
      +};

      Returns:

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.


      Mongoose#disconnect([fn])

      Disconnects all connections.

      show code
      Mongoose.prototype.disconnect = function (fn) {
      +  var count = this.connections.length
      +    , error
      +
      +  this.connections.forEach(function(conn){
      +    conn.close(function(err){
      +      if (error) return;
      +
      +      if (err) {
      +        error = err;
      +        if (fn) return fn(err);
      +        throw err;
      +      }
      +
      +      if (fn)
      +        --count || fn();
      +    });
      +  });
      +  return this;
      +};

      Parameters:

      • [fn] <Function> called after all connection close.

      Returns:


      Mongoose#model(name, [schema], [collection], [skipInit])

      Defines a model or retrieves it.

      show code
      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
      +  if (!(schema instanceof Schema)) {
      +    collection = schema;
      +    schema = false;
      +  }
      +
      +  if ('boolean' === typeof collection) {
      +    skipInit = collection;
      +    collection = null;
      +  }
      +
      +  // look up models for the collection
      +  if (!this.modelSchemas[name]) {
      +    if (!schema && name in SchemaDefaults) {
      +      schema = SchemaDefaults[name];
      +    }
      +
      +    if (schema) {
      +      this.modelSchemas[name] = schema;
      +      for (var i = 0, l = this.plugins.length; i < l; i++) {
      +        schema.plugin(this.plugins[i][0], this.plugins[i][1]);
      +      }
      +    } else {
      +      throw new Error('Schema hasn\'t been registered for model "' + name + '".
      +'
      +                    + 'Use mongoose.model(name, schema)');
      +    }
      +  }
      +
      +  if (!this.models[name]) {
      +    schema || (schema = this.modelSchemas[name]);
      +    collection || (collection = schema.set('collection') || format(name));
      +
      +    var model = Model.compile(name
      +                        , this.modelSchemas[name]
      +                        , collection
      +                        , this.connection
      +                        , this);
      +
      +    if (!skipInit) model.init();
      +
      +    this.models[name] = model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> model name
      • [schema] <Schema>
      • [collection] <String> name (optional, induced from model name)
      • [skipInit] <Boolean> whether to skip initialization (defaults to false)

      Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +
      +// define an Actor model with this mongoose instance
      +mongoose.model('Actor', new Schema({ name: String }));
      +
      +// create a new connection
      +var conn = mongoose.createConnection(..);
      +
      +// retrieve the Actor model
      +var Actor = conn.model('Actor');
      + +

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

      + +

      Example:

      + +
      var schema = new Schema({ name: String });
      +schema.set('collection', 'actor');

      Mongoose#plugin(fn, [opts])

      Declares a global plugin executed on all Schemas.

      show code
      Mongoose.prototype.plugin = function (fn, opts) {
      +  this.plugins.push([fn, opts]);
      +  return this;
      +};

      Parameters:

      Returns:

      Equivalent to calling .plugin(fn) on each Schema you create.


      module.exports

      The exports object is an instance of Mongoose.

      show code
      module.exports = exports = new Mongoose;
      +var mongoose = module.exports;

      mongoose.Collection

      The Mongoose Collection constructor

      show code
      mongoose.Collection = Collection;

      mongoose.Connection

      The Mongoose Connection constructor

      show code
      mongoose.Connection = Connection;

      mongoose.version

      Mongoose version

      show code
      mongoose.version = JSON.parse(
      +  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      +).version;

      mongoose.Mongoose

      The Mongoose constructor

      show code
      mongoose.Mongoose = Mongoose;

      The exports of the mongoose module is an instance of this class.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var mongoose2 = new mongoose.Mongoose();

      mongoose.Schema

      The Mongoose Schema constructor

      show code
      mongoose.Schema = Schema;

      Example:

      + +
      var mongoose = require('mongoose');
      +var Schema = mongoose.Schema;
      +var CatSchema = new Schema(..);

      mongoose.SchemaType

      The Mongoose SchemaType constructor.

      show code
      mongoose.SchemaType = SchemaType;

      mongoose.SchemaTypes

      The various Mongoose SchemaTypes.

      show code
      mongoose.SchemaTypes = Schema.Types;

      Note:

      + +

      Alias of mongoose.Schema.Types for backwards compatibility.


      mongoose.VirtualType

      The Mongoose VirtualType constructor.

      show code
      mongoose.VirtualType = VirtualType;

      mongoose.Types

      The various Mongoose Types.

      show code
      mongoose.Types = Types;

      Example:

      + +
      var mongoose = require('mongoose');
      +var array = mongoose.Types.Array;
      + +

      Types:

      + +
        +
      • Array
      • +
      • Buffer
      • +
      • Document
      • +
      • Embedded
      • +
      • DocumentArray
      • +
      • ObjectId
      • +
      + +

      Using this exposed access to the ObjectId type, we can construct ids on demand.

      + +
      var ObjectId = mongoose.Types.ObjectId;
      +var id1 = new ObjectId;

      mongoose.Query

      The Mongoose Query constructor.

      show code
      mongoose.Query = Query;

      mongoose.Promise

      The Mongoose Promise constructor.

      show code
      mongoose.Promise = Promise;

      mongoose.Model

      The Mongoose Model constructor.

      show code
      mongoose.Model = Model;

      mongoose.Document

      The Mongoose Document constructor.

      show code
      mongoose.Document = Document;

      mongoose.Error

      The MongooseError constructor.

      show code
      mongoose.Error = require('./error');

      mongoose.mongo

      The node-mongodb-native driver Mongoose uses.

      show code
      mongoose.mongo = require('mongodb');

      Mongoose#connection

      The default connection of the mongoose module.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +mongoose.connect(...);
      +mongoose.connection.on('error', cb);
      + +

      This is the connection used by default for every model created using mongoose.model.

      Returns:


    • collection.js

      Collection(name, conn, opts)

      Abstract Collection constructor

      show code
      function Collection (name, conn, opts) {
      +  this.name = name;
      +  this.conn = conn;
      +  this.buffer = true;
      +  this.queue = [];
      +
      +  if ('number' == typeof opts) opts = { size: opts };
      +  this.opts = opts || {};
      +
      +  if (STATES.connected == this.conn.readyState) {
      +    this.onOpen();
      +  }
      +};

      Parameters:

      • name <String> name of the collection
      • conn <Connection> A MongooseConnection instance
      • opts <Object> optional collection options

      This is the base class that drivers inherit from and implement.


      Collection#onOpen()

      Called when the database connects

      show code
      Collection.prototype.onOpen = function () {
      +  var self = this;
      +  this.buffer = false;
      +  self.doQueue();
      +};

      Collection#onClose()

      Called when the database disconnects

      show code
      Collection.prototype.onClose = function () {
      +  this.buffer = true;
      +};

      Collection#addQueue(name, args)

      Queues a method for later execution when its
      database connection opens.

      show code
      Collection.prototype.addQueue = function (name, args) {
      +  this.queue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the method to queue
      • args <Array> arguments to pass to the method when executed

      Collection#doQueue()

      Executes all queued methods and clears the queue.

      show code
      Collection.prototype.doQueue = function () {
      +  for (var i = 0, l = this.queue.length; i < l; i++){
      +    this[this.queue[i][0]].apply(this, this.queue[i][1]);
      +  }
      +  this.queue = [];
      +  return this;
      +};

      Collection#ensureIndex()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.ensureIndex = function(){
      +  throw new Error('Collection#ensureIndex unimplemented by driver');
      +};

      Collection#findAndModify()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findAndModify = function(){
      +  throw new Error('Collection#findAndModify unimplemented by driver');
      +};

      Collection#findOne()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findOne = function(){
      +  throw new Error('Collection#findOne unimplemented by driver');
      +};

      Collection#find()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.find = function(){
      +  throw new Error('Collection#find unimplemented by driver');
      +};

      Collection#insert()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.insert = function(){
      +  throw new Error('Collection#insert unimplemented by driver');
      +};

      Collection#save()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.save = function(){
      +  throw new Error('Collection#save unimplemented by driver');
      +};

      Collection#update()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.update = function(){
      +  throw new Error('Collection#update unimplemented by driver');
      +};

      Collection#getIndexes()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.getIndexes = function(){
      +  throw new Error('Collection#getIndexes unimplemented by driver');
      +};

      Collection#mapReduce()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.mapReduce = function(){
      +  throw new Error('Collection#mapReduce unimplemented by driver');
      +};

      Collection#conn

      The Connection instance


      Collection#name

      The collection name


    • connection.js

      Connection(base)

      Connection constructor

      show code
      function Connection (base) {
      +  this.base = base;
      +  this.collections = {};
      +  this.models = {};
      +  this.replica = false;
      +  this.host = null;
      +  this.port = null;
      +  this.user = null;
      +  this.pass = null;
      +  this.name = null;
      +  this.options = null;
      +  this._readyState = STATES.disconnected;
      +  this._closeCalled = false;
      +  this._hasOpened = false;
      +};

      Parameters:

      Events:

      • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

      • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

      • open: Emitted after we connected and onOpen is executed on all of this connections models.

      • disconnecting: Emitted when connection.close() was executed.

      • disconnected: Emitted after getting disconnected from the db.

      • close: Emitted after we disconnected and onClose executed on all of this connections models.

      • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

      • error: Emitted when an error occurs on this connection.

      • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

      For practical reasons, a Connection equals a Db.


      Connection#open(connection_string, [database], [port], [options], [callback])

      Opens the connection to MongoDB.

      show code
      Connection.prototype.open = function (host, database, port, options, callback) {
      +  var self = this
      +    , uri;
      +
      +  if ('string' === typeof database) {
      +    switch (arguments.length) {
      +      case 2:
      +        port = 27017;
      +      case 3:
      +        switch (typeof port) {
      +          case 'function':
      +            callback = port, port = 27017;
      +            break;
      +          case 'object':
      +            options = port, port = 27017;
      +            break;
      +        }
      +        break;
      +      case 4:
      +        if ('function' === typeof options)
      +          callback = options, options = {};
      +    }
      +  } else {
      +    switch (typeof database) {
      +      case 'function':
      +        callback = database, database = undefined;
      +        break;
      +      case 'object':
      +        options = database;
      +        database = undefined;
      +        callback = port;
      +        break;
      +    }
      +
      +    if (!rgxProtocol.test(host)) {
      +      host = 'mongodb://' + host;
      +    }
      +
      +    uri = url.parse(host);
      +    host = uri.hostname;
      +    port = uri.port || 27017;
      +    database = uri.pathname && uri.pathname.replace(/\//g, '');
      +  }
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // make sure we can open
      +  if (STATES.disconnected !== this.readyState) {
      +    var err = new Error('Trying to open unclosed connection.');
      +    err.state = this.readyState;
      +    this.error(err, callback);
      +    return this;
      +  }
      +
      +  if (!host) {
      +    this.error(new Error('Missing hostname.'), callback);
      +    return this;
      +  }
      +
      +  if (!database) {
      +    this.error(new Error('Missing database name.'), callback);
      +    return this;
      +  }
      +
      +  // handle authentication
      +  if (uri && uri.auth) {
      +    var auth = uri.auth.split(':');
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // Check hostname for user/pass
      +  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
      +    host = host.split('@');
      +    var auth = host.shift().split(':');
      +    host = host.pop();
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  // user/pass options
      +  } else if (options && options.user && options.pass) {
      +    this.user = options.user;
      +    this.pass = options.pass;
      +
      +  } else {
      +    this.user = this.pass = undefined;
      +  }
      +
      +  this.name = database;
      +  this.host = host;
      +  this.port = port;
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • connection_string <String> mongodb://uri or the host to which you are connecting
      • [database] <String> database name
      • [port] <Number> database port
      • [options] <Object> options
      • [callback] <Function>

      options is a hash with the following possible properties:

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSet instance
      +user    - username for authentication
      +pass    - password for authentication
      + +

      Notes:

      + +

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.


      Connection#openSet(uris, [database], [options], [callback])

      Connects to a replica set.

      show code
      Connection.prototype.openSet = function (uris, database, options, callback) {
      +  var uris = uris.split(',')
      +    , self = this;
      +
      +  switch (arguments.length) {
      +    case 3:
      +      switch (typeof database) {
      +        case 'string':
      +          this.name = database;
      +          break;
      +        case 'object':
      +          callback = options;
      +          options = database;
      +          database = null;
      +          break;
      +      }
      +
      +      if ('function' === typeof options) {
      +        callback = options;
      +        options = {};
      +      }
      +      break;
      +    case 2:
      +      switch (typeof database) {
      +        case 'string':
      +          this.name = database;
      +          break;
      +        case 'function':
      +          callback = database, database = null;
      +          break;
      +        case 'object':
      +          options = database, database = null;
      +          break;
      +      }
      +  }
      +
      +  this.options = options = this.defaultOptions(options);
      +
      +  if (uris.length < 2) {
      +    this.error(new Error('Please provide comma-separated URIs'), callback);
      +    return this;
      +  }
      +
      +  this.replica = true;
      +  this.host = [];
      +  this.port = [];
      +
      +  uris.forEach(function (uri) {
      +    // handle missing protocols
      +    if (!rgxProtocol.test(uri))
      +      uri = 'mongodb://' + uri;
      +
      +    var uri = url.parse(uri);
      +
      +    self.host.push(uri.hostname);
      +    self.port.push(uri.port || 27017);
      +
      +    if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
      +      self.name = uri.pathname.replace(/\//g, '');
      +
      +    if (!self.user && uri.auth) {
      +      var auth = uri.auth.split(':');
      +      self.user = auth[0];
      +      self.pass = auth[1];
      +    }
      +  });
      +
      +  if (!this.name) {
      +    this.error(new Error('No database name provided for replica set'), callback);
      +    return this;
      +  }
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • uris <String> comma-separated mongodb:// `URI`s
      • [database] <String> database name if not included in `uris`
      • [options] <Object> passed to the internal driver
      • [callback] <Function>

      Example:

      + +
      var db = mongoose.createConnection();
      +db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
      + +

      The database name and/or auth need only be included in one URI.
      The options is a hash which is passed to the internal driver connection object.

      + +

      Valid options

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSetServer instance
      +user    - username for authentication
      +pass    - password for authentication

      Connection#error(err, callback)

      error

      show code
      Connection.prototype.error = function (err, callback) {
      +  if (callback) return callback(err);
      +  this.emit('error', err);
      +}

      Parameters:

      Graceful error handling, passes error to callback
      if available, else emits error on the connection.


      Connection#_open(callback)

      Handles opening the connection with the appropriate method based on connection type.

      show code
      Connection.prototype._open = function (callback) {
      +  this.readyState = STATES.connecting;
      +  this._closeCalled = false;
      +
      +  var self = this;
      +
      +  var method = this.replica
      +    ? 'doOpenSet'
      +    : 'doOpen';
      +
      +  // open connection
      +  this[method](function (err) {
      +    if (err) {
      +      self.readyState = STATES.disconnected;
      +      if (self._hasOpened) {
      +        if (callback) callback(err);
      +      } else {
      +        self.error(err, callback);
      +      }
      +      return;
      +    }
      +
      +    self.onOpen();
      +    callback && callback();
      +  });
      +}

      Parameters:


      Connection#onOpen()

      Called when the connection is opened

      show code
      Connection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  function open () {
      +    self.readyState = STATES.connected;
      +
      +    // avoid having the collection subscribe to our event emitter
      +    // to prevent 0.3 warning
      +    for (var i in self.collections)
      +      self.collections[i].onOpen();
      +
      +    self.emit('open');
      +  };
      +
      +  // re-authenticate
      +  if (self.user && self.pass)
      +    self.db.authenticate(self.user, self.pass, open);
      +  else
      +    open();
      +};

      Connection#close([callback])

      Closes the connection

      show code
      Connection.prototype.close = function (callback) {
      +  var self = this;
      +  this._closeCalled = true;
      +
      +  switch (this.readyState){
      +    case 0: // disconnected
      +      callback && callback();
      +      break;
      +
      +    case 1: // connected
      +      this.readyState = STATES.disconnecting;
      +      this.doClose(function(err){
      +        if (err){
      +          self.error(err, callback);
      +        } else {
      +          self.onClose();
      +          callback && callback();
      +        }
      +      });
      +      break;
      +
      +    case 2: // connecting
      +      this.once('open', function(){
      +        self.close(callback);
      +      });
      +      break;
      +
      +    case 3: // disconnecting
      +      if (!callback) break;
      +      this.once('close', function () {
      +        callback();
      +      });
      +      break;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Connection#onClose()

      Called when the connection closes

      show code
      Connection.prototype.onClose = function () {
      +  this.readyState = STATES.disconnected;
      +
      +  // avoid having the collection subscribe to our event emitter
      +  // to prevent 0.3 warning
      +  for (var i in this.collections)
      +    this.collections[i].onClose();
      +
      +  this.emit('close');
      +};

      Connection#collection(name, [options])

      Retrieves a collection, creating it if not cached.

      show code
      Connection.prototype.collection = function (name, options) {
      +  if (!(name in this.collections))
      +    this.collections[name] = new Collection(name, this, options);
      +  return this.collections[name];
      +};

      Parameters:

      • name <String> of the collection
      • [options] <Object> optional collection options

      Returns:


      Connection#model(name, [schema], [collection])

      Defines or retrieves a model.

      show code
      Connection.prototype.model = function (name, schema, collection) {
      +  if (!this.models[name]) {
      +    var model = this.base.model(name, schema, collection, true)
      +      , Model
      +
      +    if (this != model.prototype.db) {
      +      // subclass model using this connection and collection name
      +      Model = function Model (doc, fields, skipId) {
      +        if (!(this instanceof Model))
      +          return new Model(doc, fields, skipId);
      +        model.call(this, doc, fields, skipId);
      +      };
      +
      +      Model.__proto__ = model;
      +      Model.prototype.__proto__ = model.prototype;
      +      Model.db = Model.prototype.db = this;
      +
      +      // collection name discovery
      +      if ('string' === typeof schema) {
      +        collection = schema;
      +      }
      +
      +      if (!collection) {
      +        collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
      +      }
      +
      +      var s = 'string' != typeof schema
      +        ? schema
      +        : model.prototype.schema;
      +
      +      Model.prototype.collection = this.collection(collection, s && s.options.capped);
      +      Model.collection = Model.prototype.collection;
      +      Model.init();
      +    }
      +
      +    this.models[name] = Model || model;
      +  }
      +
      +  return this.models[name];
      +};

      Parameters:

      • name <String> the model name
      • [schema] <Schema> a schema. necessary when defining a model
      • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

      Returns:

      • <Model> The compiled model
      var mongoose = require('mongoose');
      +var db = mongoose.createConnection(..);
      +db.model('Venue', new Schema(..));
      +var Ticket = db.model('Ticket', new Schema(..));
      +var Venue = db.model('Venue');

      Connection#setProfiling(level, [ms], callback)

      Set profiling level.

      show code
      Connection.prototype.setProfiling = function (level, ms, callback) {
      +  if (STATES.connected !== this.readyState) {
      +    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
      +  }
      +
      +  if (!callback) callback = ms, ms = 100;
      +
      +  var cmd = {};
      +
      +  switch (level) {
      +    case 0:
      +    case 'off':
      +      cmd.profile = 0;
      +      break;
      +    case 1:
      +    case 'slow':
      +      cmd.profile = 1;
      +      if ('number' !== typeof ms) {
      +        ms = parseInt(ms, 10);
      +        if (isNaN(ms)) ms = 100;
      +      }
      +      cmd.slowms = ms;
      +      break;
      +    case 2:
      +    case 'all':
      +      cmd.profile = 2;
      +      break;
      +    default:
      +      return callback(new Error('Invalid profiling level: '+ level));
      +  }
      +
      +  this.db.executeDbCommand(cmd, function (err, resp) {
      +    if (err) return callback(err);
      +
      +    var doc = resp.documents[0];
      +
      +    err = 1 === doc.ok
      +      ? null
      +      : new Error('Could not set profiling level to: '+ level)
      +
      +    callback(err, doc);
      +  });
      +};

      Parameters:

      • level <Number, String> either off (0), slow (1), or all (2)
      • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
      • callback <Function>

      Connection#defaultOptions(options)

      Prepares default connection options.

      show code
      Connection.prototype.defaultOptions = function (options) {
      +  var o = options || {};
      +
      +  o.server = o.server || {};
      +
      +  if (!('auto_reconnect' in o.server)) {
      +    o.server.auto_reconnect = true;
      +  }
      +
      +  o.db || (o.db = {});
      +  o.db.forceServerObjectId = false;
      +
      +  // TODO default to true once the driver is fixed
      +  if (!('safe' in o.db)) o.db.safe = false;
      +
      +  return o;
      +}

      Parameters:


      Connection#db

      The mongodb.Db instance, set when the connection is opened


      Connection#collections

      A hash of the collections associated with this connection


      Connection#readyState

      Connection ready state

      + +
        +
      • 0 = disconnected
      • +
      • 1 = connected
      • +
      • 2 = connecting
      • +
      • 3 = disconnecting
      • +
      + +

      Each state change emits its associated event name.

      + +

      Example

      + +
      conn.on('connected', callback);
      +conn.on('disconnected', callback);

    • document.js

      Document(obj, [fields], [skipId])

      Document constructor.

      show code
      function Document (obj, fields, skipId) {
      +  // node <0.4.3 bug
      +  if (!this._events) this._events = {};
      +  this.setMaxListeners(0);
      +
      +  if ('boolean' === typeof fields) {
      +    this._strictMode = fields;
      +    this._selected = fields = undefined;
      +  } else {
      +    this._strictMode = this.schema.options && this.schema.options.strict;
      +    this._selected = fields;
      +  }
      +
      +  this.isNew = true;
      +  this.errors = undefined;
      +  this._shardval = undefined;
      +  this._saveError = undefined;
      +  this._validationError = undefined;
      +  this._adhocPaths = undefined;
      +  this._removing = undefined;
      +  this._inserting = undefined;
      +  this.__version = undefined;
      +  this.__getters = {};
      +  this.__id = undefined;
      +
      +  this._activePaths = new ActiveRoster;
      +
      +  var required = this.schema.requiredPaths();
      +  for (var i = 0; i < required.length; ++i) {
      +    this._activePaths.require(required[i]);
      +  }
      +
      +  this._doc = this._buildDoc(obj, fields, skipId);
      +  if (obj) this.set(obj, undefined, true);
      +  this._registerHooks();
      +};

      Parameters:

      • obj <Object> the values to set
      • [fields] <Object> the fields which were selected in the query returning this document
      • [skipId] <Boolean> bool, should we auto create an ObjectId _id

      Events:

      • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

      • save: Emitted when the document is successfully saved


      Document#_buildDoc(obj, [fields], [skipId])

      Builds the default doc structure

      show code
      Document.prototype._buildDoc = function (obj, fields, skipId) {
      +  var doc = {}
      +    , self = this
      +    , exclude
      +    , keys
      +    , key
      +    , ki
      +
      +  // determine if this doc is a result of a query with
      +  // excluded fields
      +  if (fields && 'Object' === fields.constructor.name) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('_id' !== keys[ki]) {
      +        exclude = 0 === fields[keys[ki]];
      +        break;
      +      }
      +    }
      +  }
      +
      +  var paths = Object.keys(this.schema.paths)
      +    , plen = paths.length
      +    , ii = 0
      +
      +  for (; ii < plen; ++ii) {
      +    var p = paths[ii];
      +
      +    if ('_id' == p) {
      +      if (skipId) continue;
      +      if (obj && '_id' in obj) continue;
      +    }
      +
      +    var type = this.schema.paths[p]
      +      , path = p.split('.')
      +      , len = path.length
      +      , last = len-1
      +      , doc_ = doc
      +      , i = 0
      +
      +    for (; i < len; ++i) {
      +      var piece = path[i]
      +        , def
      +
      +      if (i === last) {
      +        if (fields) {
      +          if (exclude) {
      +            // apply defaults to all non-excluded fields
      +            if (p in fields) continue;
      +
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +
      +          } else if (p in fields) {
      +            // selected field
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +          }
      +        } else {
      +          def = type.getDefault(self, true);
      +          if ('undefined' !== typeof def) {
      +            doc_[piece] = def;
      +            self._activePaths.default(p);
      +          }
      +        }
      +      } else {
      +        doc_ = doc_[piece] || (doc_[piece] = {});
      +      }
      +    }
      +  };
      +
      +  return doc;
      +};

      Parameters:

      Returns:


      Document#init(doc, fn)

      Initializes the document without setters or marking anything modified.

      show code
      Document.prototype.init = function (doc, fn) {
      +  this.isNew = false;
      +
      +  init(this, doc, this._doc);
      +  this._storeShard();
      +
      +  this.emit('init');
      +  if (fn) fn(null);
      +  return this;
      +};

      Parameters:

      Called internally after a document is returned from mongodb.


      Document#_storeShard()

      Stores the current values of the shard keys.

      show code
      Document.prototype._storeShard = function _storeShard () {
      +  // backwards compat
      +  var key = this.schema.options.shardKey || this.schema.options.shardkey;
      +  if (!(key && 'Object' == key.constructor.name)) return;
      +
      +  var orig = this._shardval = {}
      +    , paths = Object.keys(key)
      +    , len = paths.length
      +    , val
      +
      +  for (var i = 0; i < len; ++i) {
      +    val = this.getValue(paths[i]);
      +    if (isMongooseObject(val)) {
      +      orig[paths[i]] = val.toObject({ depopulate: true })
      +    } else if (null != val && val.valueOf) {
      +      orig[paths[i]] = val.valueOf();
      +    } else {
      +      orig[paths[i]] = val;
      +    }
      +  }
      +}

      Note:

      + +

      Shard key values do not / are not allowed to change.


      Document#update(doc, options, callback)

      Sends an update command with this document _id as the query selector.

      show code
      Document.prototype.update = function update () {
      +  var args = utils.args(arguments);
      +  args.unshift({_id: this._id});
      +  this.constructor.update.apply(this.constructor, args);
      +}

      Parameters:

      Returns:

      Example:

      + +
      weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
      + +

      Valid options:

      + +
        +
      • safe safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +

      Document#set(path, val, [type], [options])

      Sets the value of a path, or many paths.

      show code
      Document.prototype.set = function (path, val, type, options) {
      +  if (type && 'Object' == type.constructor.name) {
      +    options = type;
      +    type = undefined;
      +  }
      +
      +  var merge = options && options.merge
      +    , adhoc = type && true !== type
      +    , constructing = true === type
      +    , adhocs
      +
      +  if (adhoc) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  if ('string' !== typeof path) {
      +    // new Document({ key: val })
      +
      +    if (null === path || undefined === path) {
      +      var _ = path;
      +      path = val;
      +      val = _;
      +
      +    } else {
      +      var prefix = val
      +        ? val + '.'
      +        : '';
      +
      +      if (path instanceof Document) path = path._doc;
      +
      +      var keys = Object.keys(path)
      +        , i = keys.length
      +        , pathtype
      +        , key
      +
      +      while (i--) {
      +        key = keys[i];
      +        if (null != path[key] && 'Object' === path[key].constructor.name
      +          && !(this._path(prefix + key) instanceof MixedSchema)) {
      +          this.set(path[key], prefix + key, constructing);
      +        } else if (this._strictMode) {
      +          pathtype = this.schema.pathType(prefix + key);
      +          if ('real' === pathtype || 'virtual' === pathtype) {
      +            this.set(prefix + key, path[key], constructing);
      +          } else if ('throw' == this._strictMode) {
      +            throw new Error("Field `" + key + "` is not in schema.");
      +          }
      +        } else if (undefined !== path[key]) {
      +          this.set(prefix + key, path[key], constructing);
      +        }
      +      }
      +
      +      return this;
      +    }
      +  }
      +
      +  // ensure _strict is honored for obj props
      +  // docschema = new Schema({ path: { nest: 'string' }})
      +  // doc.set('path', obj);
      +  var pathType = this.schema.pathType(path);
      +  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
      +    if (!merge) this.setValue(path, null);
      +    this.set(val, path, constructing);
      +    return this;
      +  }
      +
      +  var schema;
      +  if ('adhocOrUndefined' == pathType && this._strictMode) {
      +    return this;
      +  } else if ('virtual' == pathType) {
      +    schema = this.schema.virtualpath(path);
      +    schema.applySetters(val, this);
      +    return this;
      +  } else {
      +    schema = this._path(path);
      +  }
      +
      +  var parts = path.split('.')
      +    , pathToMark
      +
      +  // When using the $set operator the path to the field must already exist.
      +  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
      +
      +  if (parts.length <= 1) {
      +    pathToMark = path;
      +  } else {
      +    for (var i = 0; i < parts.length; ++i) {
      +      var part = parts[i];
      +      var subpath = parts.slice(0, i).concat(part).join('.');
      +      if (this.isDirectModified(subpath) // earlier prefixes that are already
      +                                         // marked as dirty have precedence
      +          || this.get(subpath) === null) {
      +        pathToMark = subpath;
      +        break;
      +      }
      +    }
      +
      +    if (!pathToMark) pathToMark = path;
      +  }
      +
      +  if (!schema || null === val || undefined === val) {
      +    this._set(pathToMark, path, constructing, parts, schema, val);
      +    return this;
      +  }
      +
      +  var self = this;
      +
      +  // if this doc is being constructed we should not
      +  // trigger getters.
      +  var priorVal = constructing
      +    ? undefined
      +    : this.get(path);
      +
      +  var shouldSet = this.try(function(){
      +    val = schema.applySetters(val, self, false, priorVal);
      +  });
      +
      +  if (shouldSet) {
      +    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
      +  }
      +
      +  return this;
      +}

      Parameters:

      • path <String, Object> path or object of key/vals to set
      • val <Any> the value to set
      • [type] <Schema, String, Number, Buffer, etc..> optionally specify a type for "on-the-fly" attributes
      • [options] <Object> optionally specify options that modify the behavior of the set

      Example:

      + +
      // path, value
      +doc.set(path, value)
      +
      +// object
      +doc.set({
      +    path  : value
      +  , path2 : {
      +       path  : value
      +    }
      +})
      +
      +// only-the-fly cast to number
      +doc.set(path, value, Number)
      +
      +// only-the-fly cast to string
      +doc.set(path, value, String)

      Document#_shouldModify()

      Determine if we should mark this change as modified.

      show code
      Document.prototype._shouldModify = function (
      +    pathToMark, path, constructing, parts, schema, val, priorVal) {
      +
      +  if (this.isNew) return true;
      +  if (this.isDirectModified(pathToMark)) return false;
      +
      +  if (undefined === val && !this.isSelected(path)) {
      +    // when a path is not selected in a query, its initial
      +    // value will be undefined.
      +    return true;
      +  }
      +
      +  if (undefined === val && path in this._activePaths.states.default) {
      +    // we're just unsetting the default value which was never saved
      +    return false;
      +  }
      +
      +  if (!deepEqual(val, priorVal || this.get(path))) {
      +    return true;
      +  }
      +
      +  if (!constructing &&
      +      null != val &&
      +      path in this._activePaths.states.default &&
      +      deepEqual(val, schema.getDefault(this, constructing))) {
      +    // a path with a default was $unset on the server
      +    // and the user is setting it to the same value again
      +    return true;
      +  }
      +
      +  return false;
      +}

      Returns:


      Document#_set()

      Handles the actual setting of the value and marking the path modified if appropriate.

      show code
      Document.prototype._set = function (
      +    pathToMark, path, constructing, parts, schema, val, priorVal) {
      +
      +  var shouldModify = this._shouldModify.apply(this, arguments);
      +
      +  if (shouldModify) {
      +    this.markModified(pathToMark, val);
      +
      +    // handle directly setting arrays (gh-1126)
      +    MongooseArray || (MongooseArray = require('./types/array'));
      +    if (val instanceof MongooseArray) {
      +      val._registerAtomic('$set', val);
      +    }
      +  }
      +
      +  var obj = this._doc
      +    , i = 0
      +    , l = parts.length
      +
      +  for (; i < l; i++) {
      +    var next = i + 1
      +      , last = next === l;
      +
      +    if (last) {
      +      obj[parts[i]] = val;
      +    } else {
      +      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
      +        obj = obj[parts[i]];
      +      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
      +        obj = obj[parts[i]];
      +      } else {
      +        obj = obj[parts[i]] = {};
      +      }
      +    }
      +  }
      +}

      Document#getValue(path)

      Gets a raw value from a path (no getters)

      show code
      Document.prototype.getValue = function (path) {
      +  var parts = path.split('.')
      +    , obj = this._doc
      +    , part;
      +
      +  for (var i = 0, l = parts.length; i < l; i++) {
      +    part = parts[i];
      +    obj = obj.getValue
      +        ? obj.getValue(part) // If we have an embedded array document member
      +        : obj[part];
      +    if (!obj) return obj;
      +  }
      +
      +  return obj;
      +}

      Parameters:


      Document#setValue(path, value)

      Sets a raw value for a path (no casting, setters, transformations)

      show code
      Document.prototype.setValue = function (path, val) {
      +  var parts = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, len = parts.length-1; i < len; i++) {
      +    obj = obj[parts[i]];
      +  }
      +
      +  obj[parts[len]] = val;
      +  return this;
      +};

      Parameters:


      Document#get(path, [type])

      Returns the value of a path.

      show code
      Document.prototype.get = function (path, type) {
      +  var adhocs;
      +  if (type) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  var schema = this._path(path) || this.schema.virtualpath(path)
      +    , pieces = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, l = pieces.length; i < l; i++) {
      +    obj = null == obj ? null : obj[pieces[i]];
      +  }
      +
      +  if (schema) {
      +    obj = schema.applyGetters(obj, this);
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Example

      + +
      // path
      +doc.get('age') // 47
      +
      +// dynamic casting to a string
      +doc.get('age', String) // "47"

      Document#_path(path)

      Returns the schematype for the given path.

      show code
      Document.prototype._path = function (path) {
      +  var adhocs = this._adhocPaths
      +    , adhocType = adhocs && adhocs[path];
      +
      +  if (adhocType) {
      +    return adhocType;
      +  } else {
      +    return this.schema.path(path);
      +  }
      +};

      Parameters:


      Document#markModified(path)

      Marks the path as having pending changes to write to the db.

      show code
      Document.prototype.markModified = function (path) {
      +  this._activePaths.modify(path);
      +}

      Parameters:

      • path <String> the path to mark modified

      Very helpful when using Mixed types.

      + +

      Example:

      + +
      doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');
      +doc.save() // changes to mixed.type are now persisted

      Document#try(fn, scope)

      Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

      show code
      Document.prototype.try = function (fn, scope) {
      +  var res;
      +  try {
      +    fn.call(scope);
      +    res = true;
      +  } catch (e) {
      +    this._error(e);
      +    res = false;
      +  }
      +  return res;
      +};

      Parameters:

      • fn <Function> function to execute
      • scope <Object> the scope with which to call fn

      Document#modifiedPaths()

      Returns the list of paths that have been modified.

      show code
      Document.prototype.modifiedPaths = function () {
      +  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
      +
      +  return directModifiedPaths.reduce(function (list, path) {
      +    var parts = path.split('.');
      +    return list.concat(parts.reduce(function (chains, part, i) {
      +      return chains.concat(parts.slice(0, i).concat(part).join('.'));
      +    }, []));
      +  }, []);
      +};

      Returns:


      Document#isModified([path])

      Returns true if this document was modified, else false.

      show code
      Document.prototype.isModified = function (path) {
      +  return path
      +    ? !!~this.modifiedPaths().indexOf(path)
      +    : this._activePaths.some('modify');
      +};

      Parameters:

      Returns:

      If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

      + +

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isModified()                    // true
      +doc.isModified('documents')         // true
      +doc.isModified('documents.0.title') // true
      +doc.isDirectModified('documents')   // false

      Document#isDirectModified(path)

      Returns true if path was directly set and modified, else false.

      show code
      Document.prototype.isDirectModified = function (path) {
      +  return (path in this._activePaths.states.modify);
      +};

      Parameters:

      Returns:

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isDirectModified('documents.0.title') // true
      +doc.isDirectModified('documents') // false

      Document#isInit(path)

      Checks if path was initialized.

      show code
      Document.prototype.isInit = function (path) {
      +  return (path in this._activePaths.states.init);
      +};

      Parameters:

      Returns:


      Document#isSelected(path)

      Checks if path was selected in the source query which initialized this document.

      show code
      Document.prototype.isSelected = function isSelected (path) {
      +  if (this._selected) {
      +
      +    if ('_id' === path) {
      +      return 0 !== this._selected._id;
      +    }
      +
      +    var paths = Object.keys(this._selected)
      +      , i = paths.length
      +      , inclusive = false
      +      , cur
      +
      +    if (1 === i && '_id' === paths[0]) {
      +      // only _id was selected.
      +      return 0 === this._selected._id;
      +    }
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +      inclusive = !! this._selected[cur];
      +      break;
      +    }
      +
      +    if (path in this._selected) {
      +      return inclusive;
      +    }
      +
      +    i = paths.length;
      +    var pathDot = path + '.';
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +
      +      if (0 === cur.indexOf(pathDot)) {
      +        return inclusive;
      +      }
      +
      +      if (0 === pathDot.indexOf(cur)) {
      +        return inclusive;
      +      }
      +    }
      +
      +    return ! inclusive;
      +  }
      +
      +  return true;
      +}

      Parameters:

      Returns:

      Example

      + +
      Thing.findOne().select('name').exec(function (err, doc) {
      +   doc.isSelected('name') // true
      +   doc.isSelected('age')  // false
      +})

      Document#validate(cb)

      Executes registered validation rules for this document.

      show code
      Document.prototype.validate = function (cb) {
      +  var self = this
      +
      +  // only validate required fields when necessary
      +  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
      +    if (!self.isSelected(path) && !self.isModified(path)) return false;
      +    return true;
      +  });
      +
      +  paths = paths.concat(Object.keys(this._activePaths.states.init));
      +  paths = paths.concat(Object.keys(this._activePaths.states.modify));
      +  paths = paths.concat(Object.keys(this._activePaths.states.default));
      +
      +  if (0 === paths.length) {
      +    complete();
      +    return this;
      +  }
      +
      +  var validating = {}
      +    , total = 0;
      +
      +  paths.forEach(validatePath);
      +  return this;
      +
      +  function validatePath (path) {
      +    if (validating[path]) return;
      +
      +    validating[path] = true;
      +    total++;
      +
      +    process.nextTick(function(){
      +      var p = self.schema.path(path);
      +      if (!p) return --total || complete();
      +
      +      p.doValidate(self.getValue(path), function (err) {
      +        if (err) self.invalidate(path, err, true);
      +        --total || complete();
      +      }, self);
      +    });
      +  }
      +
      +  function complete () {
      +    var err = self._validationError;
      +    self._validationError = undefined;
      +    cb(err);
      +  }
      +};

      Parameters:

      • cb <Function> called after validation completes, passing an error if one occurred

      Note:

      + +

      This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

      + +

      Example:

      + +
      doc.validate(function (err) {
      +  if (err) handleError(err);
      +  else // validation passed
      +});

      Document#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      Document.prototype.invalidate = function (path, err) {
      +  if (!this._validationError) {
      +    this._validationError = new ValidationError(this);
      +  }
      +
      +  if (!err || 'string' === typeof err) {
      +    err = new ValidatorError(path, err);
      +  }
      +
      +  this._validationError.errors[path] = err;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> the error which states the reason `path` was invalid

      Document#_reset()

      Resets the internal modified state of this document.

      show code
      Document.prototype._reset = function reset () {
      +  var self = this;
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this._activePaths
      +  .map('init', 'modify', function (i) {
      +    return self.getValue(i);
      +  })
      +  .filter(function (val) {
      +    return val && val instanceof DocumentArray && val.length;
      +  })
      +  .forEach(function (array) {
      +    var i = array.length;
      +    while (i--) {
      +      var doc = array[i];
      +      if (!doc) continue;
      +      doc._reset();
      +    }
      +  });
      +
      +  // clear atomics
      +  this._dirty().forEach(function (dirt) {
      +    var type = dirt.value;
      +    if (type && type._atomics) {
      +      type._atomics = {};
      +    }
      +  });
      +
      +  // Clear 'modify'('dirty') cache
      +  this._activePaths.clear('modify');
      +  this._validationError = undefined;
      +  this.errors = undefined;
      +  var self = this;
      +  this.schema.requiredPaths().forEach(function (path) {
      +    self._activePaths.require(path);
      +  });
      +
      +  return this;
      +}

      Returns:


      Document#_dirty()

      Returns this documents dirty paths / vals.

      show code
      Document.prototype._dirty = function _dirty () {
      +  var self = this;
      +
      +  var all = this._activePaths.map('modify', function (path) {
      +    return { path: path
      +           , value: self.getValue(path)
      +           , schema: self._path(path) };
      +  });
      +
      +  // Sort dirty paths in a flat hierarchy.
      +  all.sort(function (a, b) {
      +    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
      +  });
      +
      +  // Ignore "foo.a" if "foo" is dirty already.
      +  var minimal = []
      +    , lastPath
      +    , top;
      +
      +  all.forEach(function (item, i) {
      +    if (item.path.indexOf(lastPath) !== 0) {
      +      lastPath = item.path + '.';
      +      minimal.push(item);
      +      top = item;
      +    } else {
      +      if (!(item.value && top.value)) return;
      +
      +      // special case for top level MongooseArrays
      +      if (top.value._atomics && top.value.hasAtomics()) {
      +        // the `top` array itself and a sub path of `top` are being modified.
      +        // the only way to honor all of both modifications is through a $set
      +        // of entire array.
      +        top.value._atomics = {};
      +        top.value._atomics.$set = top.value;
      +      }
      +    }
      +  });
      +
      +  top = lastPath = null;
      +  return minimal;
      +}

      Document#_setSchema(schema)

      Assigns/compiles schema into this documents prototype.

      show code
      Document.prototype._setSchema = function (schema) {
      +  compile(schema.tree, this);
      +  this.schema = schema;
      +}

      Parameters:


      Document#_registerHooks()

      Register default hooks

      show code
      Document.prototype._registerHooks = function _registerHooks () {
      +  if (!this.save) return;
      +
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this.pre('save', function (next) {
      +    // we keep the error semaphore to make sure we don't
      +    // call `save` unnecessarily (we only need 1 error)
      +    var subdocs = 0
      +      , error = false
      +      , self = this;
      +
      +    // check for DocumentArrays
      +    var arrays = this._activePaths
      +    .map('init', 'modify', function (i) {
      +      return self.getValue(i);
      +    })
      +    .filter(function (val) {
      +      return val && val instanceof DocumentArray && val.length;
      +    });
      +
      +    if (!arrays.length)
      +      return next();
      +
      +    arrays.forEach(function (array) {
      +      if (error) return;
      +
      +      // handle sparse arrays by using for loop vs array.forEach
      +      // which skips the sparse elements
      +
      +      var len = array.length
      +      subdocs += len;
      +
      +      for (var i = 0; i < len; ++i) {
      +        if (error) break;
      +
      +        var doc = array[i];
      +        if (!doc) {
      +          --subdocs || next();
      +          continue;
      +        }
      +
      +        doc.save(handleSave);
      +      }
      +    });
      +
      +    function handleSave (err) {
      +      if (error) return;
      +
      +      if (err) {
      +        self._validationError = undefined;
      +        return next(error = err);
      +      }
      +
      +      --subdocs || next();
      +    }
      +
      +  }, function (err) {
      +    // emit on the Model if listening
      +    if (this.constructor.listeners('error').length) {
      +      this.constructor.emit('error', err);
      +    } else {
      +      // emit on the connection
      +      if (!this.db.listeners('error').length) {
      +        err.stack = 'No listeners detected, throwing. '
      +                  + 'Consider adding an error listener to your connection.
      +'
      +                  + err.stack
      +      }
      +      this.db.emit('error', err);
      +    }
      +  }).pre('save', function checkForExistingErrors (next) {
      +    // if any doc.set() calls failed
      +    if (this._saveError) {
      +      next(this._saveError);
      +      this._saveError = null;
      +    } else {
      +      next();
      +    }
      +  }).pre('save', function validation (next) {
      +    return this.validate(next);
      +  });
      +
      +  // add user defined queues
      +  this._doQueue();
      +};

      Document#_error(err)

      Registers an error

      show code
      Document.prototype._error = function (err) {
      +  this._saveError = err;
      +  return this;
      +};

      Parameters:


      Document#_doQueue()

      Executes methods queued from the Schema definition

      show code
      Document.prototype._doQueue = function () {
      +  var q = this.schema && this.schema.callQueue;
      +  if (q) {
      +    for (var i = 0, l = q.length; i < l; i++) {
      +      this[q[i][0]].apply(this, q[i][1]);
      +    }
      +  }
      +  return this;
      +};

      Document#toObject([options])

      Converts this document into a plain javascript object

      show code
      Document.prototype.toObject = function (options) {
      +  // When internally saving this document we always pass options,
      +  // bypassing the custom schema options.
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toObject
      +      ? clone(this.schema.options.toObject)
      +      : {};
      +  }
      +
      +  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
      +
      +  var ret = clone(this._doc, options);
      +
      +  if (options.virtuals || options.getters && false !== options.virtuals) {
      +    applyGetters(this, ret, 'virtuals', options);
      +  }
      +
      +  if (options.getters) {
      +    applyGetters(this, ret, 'paths', options);
      +  }
      +
      +  if (true === options.transform) {
      +    var opts = options.json
      +      ? this.schema.options.toJSON
      +      : this.schema.options.toObject;
      +    if (opts) {
      +      options.transform = opts.transform;
      +    }
      +  }
      +
      +  if ('function' == typeof options.transform) {
      +    var xformed = options.transform(this, ret, options);
      +    if ('undefined' != typeof xformed) ret = xformed;
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Options:

      + +
        +
      • getters apply all getters (path and virtual getters)
      • +
      • virtuals apply virtual getters (can override getters option)
      • +
      • minimize remove empty objects (defaults to true)
      • +
      • transform a transform function to apply to the resulting document before returning
      • +
      + +

      Getters/Virtuals

      + +

      Example of only applying path getters

      + +
      doc.toObject({ getters: true, virtuals: false })
      + +

      Example of only applying virtual getters

      + +
      doc.toObject({ virtuals: true })
      + +

      Example of applying both path and virtual getters

      + +
      doc.toObject({ getters: true })
      + +

      To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

      + +
      schema.set('toObject', { virtuals: true })
      + +

      Transform

      + +

      We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

      + +

      Transform functions receive three arguments

      + +
      function (doc, ret, options) {}
      + +
        +
      • doc The mongoose document which is being converted
      • +
      • ret The plain object representation which has been converted
      • +
      • options The options in use (either schema options or the options passed inline)
      • +
      + +

      Example

      + +
      // specify the transform schema option
      +schema.options.toObject.transform = function (doc, ret, options) {
      +  // remove the _id of every document before returning the result
      +  delete ret._id;
      +}
      +
      +// without the transformation in the schema
      +doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
      +
      +// with the transformation
      +doc.toObject(); // { name: 'Wreck-it Ralph' }
      + +

      With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

      + +
      schema.options.toObject.transform = function (doc, ret, options) {
      +  return { movie: ret.name }
      +}
      +
      +// without the transformation in the schema
      +doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
      +
      +// with the transformation
      +doc.toObject(); // { movie: 'Wreck-it Ralph' }
      + +

      Note: if a transform function returns undefined, the return value will be ignored.

      + +

      Transformations may also be applied inline, overridding any transform set in the options:

      + +
      function xform (doc, ret, options) {
      +  return { inline: ret.name, custom: true }
      +}
      +
      +// pass the transform as an inline option
      +doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }
      + +

      Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

      + +
      schema.options.toObject.hide = '_id';
      +schema.options.toObject.transform = function (doc, ret, options) {
      +  if (options.hide) {
      +    options.hide.split(' ').forEach(function (prop) {
      +      delete ret[prop];
      +    });
      +  }
      +}
      +
      +var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });
      +doc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }
      +doc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }
      +doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }
      + +

      Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

      + +
      if ('function' == typeof doc.ownerDocument) {
      +  // working with a sub doc
      +}
      + +

      Transforms, like all of these options, are also available for toJSON.

      + +

      See schema options for some more details.


      Document#toJSON(options)

      The return value of this method is used in calls to JSON.stringify(doc).

      show code
      Document.prototype.toJSON = function (options) {
      +  // check for object type since an array of documents
      +  // being stringified passes array indexes instead
      +  // of options objects. JSON.stringify([doc, doc])
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toJSON
      +      ? clone(this.schema.options.toJSON)
      +      : {};
      +  }
      +  options.json = true;
      +  return this.toObject(options);
      +};

      Parameters:

      • options <Object> same options as [Document#toObject](#document_Document-toObject)

      Returns:

      This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

      + +
      schema.set('toJSON', { virtuals: true })
      + +

      See schema options for details.


      Document#inspect()

      Helper for console.log

      show code
      Document.prototype.inspect = function (options) {
      +  var opts = options && 'Object' == options.constructor.name
      +    ? options
      +    : undefined
      +  return inspect(this.toObject(opts));
      +};

      Document#toString()

      Helper for console.log


      Document#equals(doc)

      Returns true if the Document stores the same data as doc.

      show code
      Document.prototype.equals = function (doc) {
      +  var tid = this.get('_id');
      +  var docid = doc.get('_id');
      +  return tid.equals
      +    ? tid.equals(docid)
      +    : tid === docid;
      +};

      Parameters:

      Returns:

      Documents are considered equal when they have matching _ids.


      Document#errors

      Hash containing current validation errors.


      Document#id

      The string version of this documents _id.

      + +

      Note:

      + +

      This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

      + +
      new Schema({ name: String }, { id: false });

      Document#isNew

      Boolean flag specifying if the document is new.


      Document#schema

      The documents schema.


    • drivers/node-mongodb-native/collection.js

      NativeCollection()

      A node-mongodb-native collection implementation.

      show code
      function NativeCollection () {
      +  this.collection = null;
      +  MongooseCollection.apply(this, arguments);
      +}

      Inherits:

      All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


      NativeCollection#onOpen()

      Called when the connection opens.

      show code
      NativeCollection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  if (this.collection) {
      +    return MongooseCollection.prototype.onOpen.call(self);
      +  }
      +
      +  if (!self.opts.size) {
      +    // non-capped
      +    return self.conn.db.collection(self.name, callback);
      +  }
      +
      +  // capped
      +  return self.conn.db.collection(self.name, function (err, c) {
      +    if (err) return callback(err);
      +
      +    // discover if this collection exists and if it is capped
      +    c.options(function (err, exists) {
      +      if (err) return callback(err);
      +
      +      if (exists) {
      +        if (exists.capped) {
      +          callback(null, c);
      +        } else {
      +          var msg = 'A non-capped collection exists with this name.
      +
      +'
      +                  + ' To use this collection as a capped collection, please '
      +                  + 'first convert it.
      +'
      +                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
      +          err = new Error(msg);
      +          callback(err);
      +        }
      +      } else {
      +        // create
      +        var opts = utils.clone(self.opts);
      +        opts.capped = true;
      +        self.conn.db.createCollection(self.name, opts, callback);
      +      }
      +    });
      +  });
      +
      +  function callback (err, collection) {
      +    if (err) {
      +      // likely a strict mode error
      +      self.conn.emit('error', err);
      +    } else {
      +      self.collection = collection;
      +      MongooseCollection.prototype.onOpen.call(self);
      +    }
      +  };
      +};

      NativeCollection#onClose()

      Called when the connection closes

      show code
      NativeCollection.prototype.onClose = function () {
      +  MongooseCollection.prototype.onClose.call(this);
      +};

      NativeCollection#getIndexes(callback)

      Retreives information about this collections indexes.

      Parameters:


    • drivers/node-mongodb-native/connection.js

      NativeConnection()

      A node-mongodb-native connection implementation.

      show code
      function NativeConnection() {
      +  MongooseConnection.apply(this, arguments);
      +};

      Inherits:


      NativeConnection#doOpen(fn)

      Opens the connection to MongoDB.

      show code
      NativeConnection.prototype.doOpen = function (fn) {
      +  var server
      +    , self = this;
      +
      +  if (!this.db) {
      +    server = new mongo.Server(this.host, Number(this.port), this.options.server);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};
      +
      +function listen (conn) {
      +  if (conn._listening) return;
      +  conn._listening = true;
      +
      +  conn.db.on('close', function(){
      +    if (conn._closeCalled) return;
      +
      +    // the driver never emits an `open` event. auto_reconnect still
      +    // emits a `close` event but since we never get another
      +    // `open` we can't emit close
      +    if (conn.db.serverConfig.autoReconnect) {
      +      conn.readyState = STATES.disconnected;
      +      conn.emit('close');
      +      return;
      +    }
      +    conn.onClose();
      +  });
      +  conn.db.on('error', function(err){
      +    conn.emit('error', err);
      +  });
      +  conn.db.on('timeout', function(err){
      +    var error = new Error(err && err.err || 'connection timeout');
      +    conn.emit('error', error);
      +  });
      +  conn.db.on('open', function (err, db) {
      +    if (STATES.disconnected === conn.readyState && db && db.databaseName) {
      +      conn.readyState = STATES.connected;
      +      conn.emit('reconnected')
      +    }
      +  })
      +}

      Parameters:

      Returns:


      NativeConnection#doOpenSet(fn)

      Opens a connection to a MongoDB ReplicaSet.

      show code
      NativeConnection.prototype.doOpenSet = function (fn) {
      +  if (!this.db) {
      +    var servers = []
      +      , ports = this.port
      +      , self = this
      +
      +    this.host.forEach(function (host, i) {
      +      servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
      +    });
      +
      +    var server = new ReplSetServers(servers, this.options.replset);
      +    this.db = new mongo.Db(this.name, server, this.options.db);
      +
      +    this.db.on('fullsetup', function () {
      +      self.emit('fullsetup')
      +    });
      +  }
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:

      See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


      NativeConnection#doClose(fn)

      Closes the connection

      show code
      NativeConnection.prototype.doClose = function (fn) {
      +  this.db.close();
      +  if (fn) fn();
      +  return this;
      +}

      Parameters:

      Returns:


    • error.js

      MongooseError()

      Mongoose error

      show code
      function MongooseError (msg) {
      +  Error.call(this);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.message = msg;
      +  this.name = 'MongooseError';
      +};

      Inherits:


    • errors/cast.js

      CastError(type, value)

      Casting Error constructor.

      show code
      function CastError (type, value) {
      +  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'CastError';
      +  this.type = type;
      +  this.value = value;
      +};

      Parameters:

      Inherits:


    • errors/document.js

      DocumentError(msg)

      Document Error

      show code
      function DocumentError (msg) {
      +  MongooseError.call(this, msg);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'DocumentError';
      +};

      Parameters:

      Inherits:


    • errors/validation.js

      ValidationError(instance)

      Document Validation Error

      show code
      function ValidationError (instance) {
      +  MongooseError.call(this, "Validation failed");
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidationError';
      +  this.errors = instance.errors = {};
      +};

      Parameters:

      Inherits:


      ValidationError#toString()

      Console.log helper

      show code
      ValidationError.prototype.toString = function () {
      +  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
      +    return String(this.errors[key]);
      +  }, this).join(', ');
      +};

    • errors/validator.js

      ValidatorError(path, msg)

      Schema validator error

      show code
      function ValidatorError (path, type) {
      +  var msg = type
      +    ? '"' + type + '" '
      +    : '';
      +  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidatorError';
      +  this.path = path;
      +  this.type = type;
      +};

      Parameters:

      Inherits:


    • errors/version.js

      VersionError()

      Version Error constructor.

      show code
      function VersionError () {
      +  MongooseError.call(this, 'No matching document found.');
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'VersionError';
      +};

      Inherits:


    • model.js

      Model(doc)

      Model constructor

      show code
      function Model (doc, fields, skipId) {
      +  Document.call(this, doc, fields, skipId);
      +};

      Parameters:

      • doc <Object> values to with which to create the document

      Inherits:

      Events:

      • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

      • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


      Model#_getPopulationKeys(query)

      Returns what paths can be populated

      show code
      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
      +  if (!(query && query.options.populate)) return;
      +
      +  var names = Object.keys(query.options.populate)
      +    , n = names.length
      +    , name
      +    , paths = {}
      +    , hasKeys
      +    , schema
      +
      +  while (n--) {
      +    name = names[n];
      +    schema = this.schema.path(name);
      +    hasKeys = true;
      +
      +    if (!schema) {
      +      // if the path is not recognized, it's potentially embedded docs
      +      // walk path atoms from right to left to find a matching path
      +      var pieces = name.split('.')
      +        , i = pieces.length;
      +
      +      while (i--) {
      +        var path = pieces.slice(0, i).join('.')
      +          , pathSchema = this.schema.path(path);
      +
      +        // loop until we find an array schema
      +        if (pathSchema && pathSchema.caster) {
      +          if (!paths[path]) {
      +            paths[path] = { sub: {} };
      +          }
      +
      +          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
      +          hasKeys || (hasKeys = true);
      +          break;
      +        }
      +      }
      +    } else {
      +      paths[name] = query.options.populate[name];
      +      hasKeys || (hasKeys = true);
      +    }
      +  }
      +
      +  return hasKeys && paths;
      +};

      Parameters:

      Returns:


      Model#_populate(schema, oid, query, fn)

      Populates an object

      show code
      Model.prototype._populate = function populate (schema, oid, query, fn) {
      +  if (!Array.isArray(oid)) {
      +    var conditions = query.conditions || {};
      +    conditions._id = oid;
      +
      +    return this
      +    .db.model(query.model || schema.options.ref)
      +    .findOne(conditions, query.fields, query.options, fn);
      +  }
      +
      +  if (!oid.length) {
      +    return fn(null, oid);
      +  }
      +
      +  var model = this.db.model(query.model || schema.caster.options.ref)
      +    , conditions = query && query.conditions || {};
      +
      +  conditions._id || (conditions._id = { $in: oid });
      +
      +  model.find(conditions, query.fields, query.options, function (err, docs) {
      +    if (err) return fn(err);
      +
      +    // user specified sort order?
      +    if (query.options && query.options.sort) {
      +      return fn(null, docs);
      +    }
      +
      +    // put back in original id order (using a hash reduces complexity from n*n to 2n)
      +    var docHash = {};
      +    docs.forEach(function (doc) {
      +      docHash[doc._id] = doc;
      +    });
      +
      +    var arr = [];
      +    oid.forEach(function (id) {
      +      if (id in docHash) arr.push(docHash[id]);
      +    });
      +
      +    fn(null, arr);
      +  });
      +};

      Parameters:

      • schema <SchemaType> type for the oid
      • oid <Object> object id or array of object ids
      • query <Object> object specifying query conditions, fields, and options
      • fn <Function>

      Model#init(doc, query, fn)

      Performs auto-population of relations.

      show code
      Model.prototype.init = function init (doc, query, fn) {
      +  if ('function' == typeof query) {
      +    fn = query;
      +    query = null;
      +  }
      +
      +  var populate = this._getPopulationKeys(query);
      +
      +  if (!populate) {
      +    return Document.prototype.init.call(this, doc, fn);
      +  }
      +
      +  // population from other models is necessary
      +  var self = this;
      +
      +  init(doc, '', function (err) {
      +    if (err) return fn(err);
      +    Document.prototype.init.call(self, doc, fn);
      +  });
      +
      +  return this;
      +
      +  function init (obj, prefix, fn) {
      +    prefix = prefix || '';
      +
      +    var keys = Object.keys(obj)
      +      , len = keys.length;
      +
      +    return next();
      +
      +    function next () {
      +      if (--len < 0) return fn();
      +
      +      var i = keys[len]
      +        , path = prefix + i
      +        , schema = self.schema.path(path)
      +        , total = 0
      +        , inline = false
      +        , poppath
      +
      +      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
      +        // assume nested object
      +        return init(obj[i], path + '.', next);
      +      }
      +
      +      if (!(obj[i] && schema && populate[path])) return next();
      +
      +      // this query object is re-used and passed around. we clone
      +      // it to prevent query condition contamination between
      +      // one populate call to the next.
      +      poppath = utils.clone(populate[path]);
      +
      +      if (poppath.sub) {
      +        obj[i].forEach(function (subobj) {
      +          inline = true;
      +
      +          var pkeys = Object.keys(poppath.sub)
      +            , pi = pkeys.length
      +            , key
      +
      +          while (pi--) {
      +            key = pkeys[pi];
      +
      +            if (subobj[key]) (function (key) {
      +              total++;
      +              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
      +              function done (err, doc) {
      +                if (err) return error(err);
      +                subobj[key] = doc;
      +                if (--total < 1 && !inline) {
      +                  next();
      +                }
      +              }
      +            })(key);
      +          }
      +        });
      +
      +        inline = false;
      +
      +        if (0 === total) return next();
      +
      +      } else {
      +        self._populate(schema, obj[i], poppath, function (err, doc) {
      +          if (err) return error(err);
      +          obj[i] = doc;
      +          next();
      +        });
      +      }
      +    };
      +  };
      +
      +  function error (err) {
      +    if (error.err) return;
      +    fn(error.err = err);
      +  }
      +};

      Parameters:

      • doc <Object> document returned by mongo
      • query <Query> query that originated the initialization
      • fn <Function>

      Model#save([fn])

      Saves this document.

      show code
      Model.prototype.save = function save (fn) {
      +  var promise = new Promise(fn)
      +    , complete = handleSave(promise, this)
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  if (this.isNew) {
      +    // send entire doc
      +    var obj = this.toObject({ depopulate: 1 });
      +    this._version(true, obj);
      +    this.collection.insert(obj, options, complete);
      +    this._reset();
      +    this.isNew = false;
      +    this.emit('isNew', false);
      +    // Make it possible to retry the insert
      +    this._inserting = true;
      +
      +  } else {
      +    // Make sure we don't treat it as a new object on error,
      +    // since it already exists
      +    this._inserting = false;
      +
      +    var delta = this._delta();
      +    if (delta) {
      +      var where = this._where(delta[0]);
      +      this.collection.update(where, delta[1], options, complete);
      +    } else {
      +      process.nextTick(function () {
      +        complete(null);
      +      })
      +    }
      +
      +    this._reset();
      +    this.emit('isNew', false);
      +  }
      +};

      Parameters:

      Example:

      + +
      product.sold = Date.now();
      +product.save(function (err, product) {
      +  if (err) ..
      +})
      + +

      The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      + +
      var db = mongoose.createConnection(..);
      +var schema = new Schema(..);
      +var Product = db.model('Product', schema);
      +
      +db.on('error', handleError);
      + +

      However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

      + +
      Product.on('error', handleError);

      Model#_delta()

      Produces a special query document of the modified properties used in updates.

      show code
      Model.prototype._delta = function _delta () {
      +  var dirty = this._dirty();
      +  if (!dirty.length) return;
      +
      +  var self = this
      +    , where = {}
      +    , delta = {}
      +    , len = dirty.length
      +    , d = 0
      +    , val
      +    , obj
      +
      +  for (; d < len; ++d) {
      +    var data = dirty[d]
      +    var value = data.value
      +    var schema = data.schema
      +
      +    if (undefined === value) {
      +      operand(self, where, delta, data, 1, '$unset');
      +
      +    } else if (null === value) {
      +      operand(self, where, delta, data, null);
      +
      +    } else if (value._path && value._atomics) {
      +      // arrays and other custom types (support plugins etc)
      +      handleAtomics(self, where, delta, data, value);
      +
      +    } else if (value._path && Buffer.isBuffer(value)) {
      +      // MongooseBuffer
      +      value = value.toObject();
      +      operand(self, where, delta, data, value);
      +
      +    } else {
      +      value = utils.clone(value);
      +      operand(self, where, delta, data, value);
      +    }
      +  }
      +
      +  if (this.__version) {
      +    this._version(where, delta);
      +  }
      +
      +  return [where, delta];
      +}

      Model#_version()

      Appends versioning to the where and update clauses.

      show code
      Model.prototype._version = function _version (where, delta) {
      +  var key = this.schema.options.versionKey;
      +
      +  if (true === where) {
      +    // this is an insert
      +    if (key) this.setValue(key, delta[key] = 0);
      +    return;
      +  }
      +
      +  // updates
      +
      +  // only apply versioning if our versionKey was selected. else
      +  // there is no way to select the correct version. we could fail
      +  // fast here and force them to include the versionKey but
      +  // thats a bit intrusive. can we do this automatically?
      +  // TODO fail fast option?
      +  if (!this.isSelected(key)) {
      +    return;
      +  }
      +
      +  // $push $addToSet don't need the where clause set
      +  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
      +    where[key] = this.getValue(key);
      +  }
      +
      +  if (VERSION_INC === (VERSION_INC & this.__version)) {
      +    delta.$inc || (delta.$inc = {});
      +    delta.$inc[key] = 1;
      +  }
      +}

      Model#increment()

      Signal that we desire an increment of this documents version.

      show code
      Model.prototype.increment = function increment () {
      +  this.__version = VERSION_ALL;
      +  return this;
      +}

      Model#_where()

      Returns a query object which applies shardkeys if they exist.

      show code
      Model.prototype._where = function _where (where) {
      +  where || (where = {});
      +
      +  var paths
      +    , len
      +
      +  if (this._shardval) {
      +    paths = Object.keys(this._shardval)
      +    len = paths.length
      +
      +    for (var i = 0; i < len; ++i) {
      +      where[paths[i]] = this._shardval[paths[i]];
      +    }
      +  }
      +
      +  where._id = this._doc._id;
      +  return where;
      +}

      Model#remove([fn])

      Removes this document from the db.

      show code
      Model.prototype.remove = function remove (fn) {
      +  if (this._removing) {
      +    this._removing.addBack(fn);
      +    return this;
      +  }
      +
      +  var promise = this._removing = new Promise(fn)
      +    , where = this._where()
      +    , self = this
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  this.collection.remove(where, options, tick(function (err) {
      +    if (err) {
      +      promise.error(err);
      +      promise = self = self._removing = where = options = null;
      +      return;
      +    }
      +    self.emit('remove', self);
      +    promise.complete();
      +    promise = self = where = options = null;
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Example:

      + +
      product.remove(function (err, product) {
      +  if (err) return handleError(err);
      +  Product.findById(product._id, function (err, product) {
      +    console.log(product) // null
      +  })
      +})

      Model#_registerHooks()

      Register hooks override

      show code
      Model.prototype._registerHooks = function registerHooks () {
      +  Document.prototype._registerHooks.call(this);
      +};

      Model#model(name)

      Returns another Model instance.

      show code
      Model.prototype.model = function model (name) {
      +  return this.db.model(name);
      +};
      +
      +// Model (class) features

      Parameters:

      Example:

      + +
      var doc = new Tank;
      +doc.model('User').findById(id, callback);

      Model#$where(argument)

      Creates a Query and specifies a $where condition.

      Parameters:

      • argument <String, Function> is a javascript string or anonymous function

      Returns:

      Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      + +
      Blog.$where('this.comments.length &gt; 5');

      Model.init()

      Called when the model compiles.

      show code
      Model.init = function init () {
      +  if (this.schema.options.autoIndex)
      +    this.ensureIndexes();
      +
      +  this.schema.emit('init', this);
      +};

      Model.ensureIndexes([cb])

      Sends ensureIndex commands to mongo for each index declared in the schema.

      show code
      Model.ensureIndexes = function ensureIndexes (cb) {
      +  var indexes = this.schema.indexes();
      +  if (!indexes.length) {
      +    return cb && cb();
      +  }
      +
      +  var self = this
      +    , safe = self.schema.options.safe
      +    , count = indexes.length
      +    , error
      +
      +  indexes.forEach(function (index) {
      +    var options = index[1];
      +    options.safe = safe;
      +    self.collection.ensureIndex(index[0], options, tick(function (err) {
      +      if (err) error = err;
      +      if (--count) return;
      +
      +      self.emit('index', error);
      +      cb && cb(error);
      +    }));
      +  });
      +}

      Parameters:

      After completion, an index event is emitted on this Model passing an error if one occurred.

      + +

      NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

      + +

      Example:

      + +
      Event.ensureIndexes(function (err) {
      +  if (err) return handleError(err);
      +});

      Model.remove(conditions, [callback])

      Removes documents from the collection.

      show code
      Model.remove = function remove (conditions, callback) {
      +  if ('function' === typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +  }
      +
      +  var query = new Query(conditions).bind(this, 'remove');
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.remove(callback);
      +};

      Parameters:

      Returns:

      Note:

      + +

      To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.remove({ _id: id }).exec();

      Model.find(conditions, [fields], [options], [callback])

      Finds documents

      show code
      Model.find = function find (conditions, fields, options, callback) {
      +  if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options);
      +  query.bind(this, 'find');
      +  query.select(fields);
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.find(callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      // retrieve only certain keys
      +MyModel.find({ name: /john/i }, 'name friends', function () { })
      +
      +// pass options
      +MyModel.find({ name: /john/i }, null, { skip: 10 } )

      Model._applyNamedScope(query)

      Merges the current named scope query into query.

      show code
      Model._applyNamedScope = function _applyNamedScope (query) {
      +  var cQuery = this._cumulativeQuery;
      +
      +  if (cQuery) {
      +    merge(query._conditions, cQuery._conditions);
      +    if (query._fields && cQuery._fields)
      +      merge(query._fields, cQuery._fields);
      +    if (query.options && cQuery.options)
      +      merge(query.options, cQuery.options);
      +    delete this._cumulativeQuery;
      +  }
      +
      +  return query;
      +}

      Parameters:

      Returns:


      Model.findById(id, [fields], [options], [callback])

      Finds a single document by id.

      show code
      Model.findById = function findById (id, fields, options, callback) {
      +  return this.findOne({ _id: id }, fields, options, callback);
      +};

      Parameters:

      Returns:

      The id is cast to an ObjectId before sending the command.

      + +

      Example:

      + +
      Adventure.findById(id, callback);

      Model.findOne(conditions, [fields], [options], [callback])

      Finds one document.

      show code
      Model.findOne = function findOne (conditions, fields, options, callback) {
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOne(callback);
      +};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      + +

      Example:

      + +
      Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

      Model.count(conditions, [callback])

      Counts number of matching documents in a database collection.

      show code
      Model.count = function count (conditions, callback) {
      +  if ('function' === typeof conditions)
      +    callback = conditions, conditions = {};
      +
      +  var query = new Query(conditions).bind(this, 'count');
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.count(callback);
      +};

      Parameters:

      Returns:

      Example:

      + +
      Adventure.count({ type: 'jungle' }, function (err, count) {
      +  if (err) ..
      +  console.log('there are %d jungle adventures', count);
      +});

      Model.distinct(field, [conditions], [callback])

      Executes a DISTINCT command

      show code
      Model.distinct = function distinct (field, conditions, callback) {
      +  var query = new Query(conditions).bind(this, 'distinct');
      +  if ('undefined' == typeof callback) {
      +    query._distinctArg = field;
      +    return query;
      +  }
      +
      +  this._applyNamedScope(query);
      +  return query.distinct(field, callback);
      +};

      Parameters:

      Returns:


      Model.where(path, [val])

      Creates a Query, applies the passed conditions, and returns the Query.

      show code
      Model.where = function where (path, val) {
      +  var q = new Query().bind(this, 'find');
      +  return q.where.apply(q, arguments);
      +};

      Parameters:

      Returns:

      For example, instead of writing:

      + +
      User.find({age: {$gte: 21, $lte: 65}}, callback);
      + +

      we can instead write:

      + +
      User.where('age').gte(21).lte(65).exec(callback);
      + +

      Since the Query class also supports where you can continue chaining

      + +
      User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +... etc

      Model.findOneAndUpdate([conditions], [update], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Model.findOneAndUpdate = function (conditions, update, options, callback) {
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +  else if (1 === arguments.length) {
      +    if ('function' == typeof conditions) {
      +      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    update = conditions;
      +    conditions = undefined;
      +  }
      +
      +  var fields;
      +  if (options && options.fields) {
      +    fields = options.fields;
      +    options.fields = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndUpdate', update);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndUpdate(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndUpdate(conditions, update, options, callback) // executes
      +A.findOneAndUpdate(conditions, update, options)  // returns Query
      +A.findOneAndUpdate(conditions, update, callback) // executes
      +A.findOneAndUpdate(conditions, update)           // returns Query
      +A.findOneAndUpdate()                             // returns Query
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findByIdAndUpdate(id, [update], [options], [callback])

      Issues a mongodb findAndModify update command by a documents id.

      show code
      Model.findByIdAndUpdate = function (id, update, options, callback) {
      +  var args;
      +
      +  if (1 === arguments.length) {
      +    if ('function' == typeof id) {
      +      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
      +
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    return this.findOneAndUpdate({_id: id }, undefined);
      +  }
      +
      +  args = utils.args(arguments, 1);
      +  args.unshift({ _id: id });
      +  return this.findOneAndUpdate.apply(this, args);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndUpdate(id, update, options, callback) // executes
      +A.findByIdAndUpdate(id, update, options)  // returns Query
      +A.findByIdAndUpdate(id, update, callback) // executes
      +A.findByIdAndUpdate(id, update)           // returns Query
      +A.findByIdAndUpdate()                     // returns Query
      + +

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findById(id, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findOneAndRemove(conditions, [options], [callback])

      Issue a mongodb findAndModify remove command.

      show code
      Model.findOneAndRemove = function (conditions, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof conditions) {
      +    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  }
      +
      +  var fields;
      +  if (options) {
      +    fields = options.select;
      +    options.select = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndRemove');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndRemove(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndRemove(conditions, options, callback) // executes
      +A.findOneAndRemove(conditions, options)  // return Query
      +A.findOneAndRemove(conditions, callback) // executes
      +A.findOneAndRemove(conditions) // returns Query
      +A.findOneAndRemove()           // returns Query

      Model.findByIdAndRemove(id, [options], [callback])

      Issue a mongodb findAndModify remove command by a documents id.

      show code
      Model.findByIdAndRemove = function (id, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof id) {
      +    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  return this.findOneAndRemove({ _id: id }, options, callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed, else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndRemove(id, options, callback) // executes
      +A.findByIdAndRemove(id, options)  // return Query
      +A.findByIdAndRemove(id, callback) // executes
      +A.findByIdAndRemove(id) // returns Query
      +A.findByIdAndRemove()           // returns Query

      Model.create(doc, fn)

      Shortcut for creating a new Document that is automatically saved to the db if valid.

      show code
      Model.create = function create (doc, fn) {
      +  if (1 === arguments.length) {
      +    return 'function' === typeof doc && doc(null);
      +  }
      +
      +  var self = this
      +    , docs = [null]
      +    , promise
      +    , count
      +    , args
      +
      +  if (Array.isArray(doc)) {
      +    args = doc;
      +  } else {
      +    args = utils.args(arguments, 0, arguments.length - 1);
      +    fn = arguments[arguments.length - 1];
      +  }
      +
      +  if (0 === args.length) return fn(null);
      +
      +  promise = new Promise(fn);
      +  count = args.length;
      +
      +  args.forEach(function (arg, i) {
      +    var doc = new self(arg);
      +    docs[i+1] = doc;
      +    doc.save(function (err) {
      +      if (err) return promise.error(err);
      +      --count || fn.apply(null, docs);
      +    });
      +  });
      +
      +  // TODO
      +  // utilize collection.insertAll for batch processing?
      +};

      Parameters:

      Example:

      + +
      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});
      +
      +var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      +Candy.create(array, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});

      Model.update(conditions, update, [options], [callback])

      Updates documents in the database without returning them.

      show code
      Model.update = function update (conditions, doc, options, callback) {
      +  if (arguments.length < 4) {
      +    if ('function' === typeof options) {
      +      // Scenario: update(conditions, doc, callback)
      +      callback = options;
      +      options = null;
      +    } else if ('function' === typeof doc) {
      +      // Scenario: update(doc, callback);
      +      callback = doc;
      +      doc = conditions;
      +      conditions = {};
      +      options = null;
      +    }
      +  }
      +
      +  var query = new Query(conditions, options).bind(this, 'update', doc);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.update(doc, callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
      +MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
      +  if (err) return handleError(err);
      +  console.log('The number of updated documents was %d', numberAffected);
      +  console.log('The raw response from Mongo was ', raw);
      +});
      + +

      Valid options:

      + +
        +
      • safe (boolean) safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +
      • multi (boolean) whether multiple documents should be updated (false)
      • +
      + +

      All update values are cast to their appropriate SchemaTypes before being sent.

      + +

      The callback function receives (err, numberAffected, rawResponse).

      + +
        +
      • err is the error if any occurred
      • +
      • numberAffected is the count of updated documents Mongo reported
      • +
      • rawResponse is the full response from Mongo
      • +
      + +

      Note:

      + +

      All top level keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.update(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

      + +

      Note:

      + +

      To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
      + +

      Note:

      + +

      Although values are casted to their appropriate types when using update, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.mapReduce(o, callback)

      Executes a mapReduce command.

      show code
      Model.mapReduce = function mapReduce (o, callback) {
      +  if ('function' != typeof callback) throw new Error('missing callback');
      +
      +  var self = this;
      +
      +  if (!Model.mapReduce.schema) {
      +    var opts = { noId: true, noVirtualId: true, strict: false }
      +    Model.mapReduce.schema = new Schema({}, opts);
      +  }
      +
      +  if (!o.out) o.out = { inline: 1 };
      +
      +  o.map = String(o.map);
      +  o.reduce = String(o.reduce);
      +
      +  if (o.query) {
      +    var q = new Query(o.query);
      +    q.cast(this);
      +    o.query = q._conditions;
      +    q = undefined;
      +  }
      +
      +  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
      +    if (err) return callback(err);
      +
      +    if (ret.findOne && ret.mapReduce) {
      +      // returned a collection, convert to Model
      +      var model = Model.compile(
      +          '_mapreduce_' + ret.collectionName
      +        , Model.mapReduce.schema
      +        , ret.collectionName
      +        , self.db
      +        , self.base);
      +
      +      model._mapreduce = true;
      +
      +      return callback(err, model, stats);
      +    }
      +
      +    callback(err, ret, stats);
      +  });
      +}

      Parameters:

      • o <Object> an object specifying map-reduce options
      • callback <Function>

      o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +User.mapReduce(o, function (err, results) {
      +  console.log(results)
      +})
      + +

      Other options:

      + +
        +
      • query {Object} query filter object.
      • +
      • limit {Number} max number of documents
      • +
      • keeptemp {Boolean, default:false} keep temporary data
      • +
      • finalize {Function} finalize function
      • +
      • scope {Object} scope variables exposed to map/reduce/finalize during execution
      • +
      • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
      • +
      • verbose {Boolean, default:false} provide statistics on job execution time.
      • +
      • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
      • +
      + +

      * out options:

      + +
        +
      • {inline:1} the results are returned in an array
      • +
      • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
      • +
      • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
      • +
      • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
      • +
      + +

      If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +o.out = { replace: 'createdCollectionNameForResults' }
      +o.verbose = true;
      +User.mapReduce(o, function (err, model, stats) {
      +  console.log('map reduce took %d ms', stats.processtime)
      +  model.find().where('value').gt(10).exec(function (err, docs) {
      +    console.log(docs);
      +  });
      +})

      Model.aggregate(array, [options], callback)

      Executes an aggregate command on this models collection.

      show code
      Model.aggregate = function aggregate () {
      +  return this.collection.aggregate.apply(this.collection, arguments);
      +}

      Parameters:

      Example:

      + +
      // find the max age of all users
      +Users.aggregate(
      +    { $group: { _id: null, maxAge: { $max: '$age' }}}
      +  , { $project: { _id: 0, maxAge: 1 }}
      +  , function (err, res) {
      +  if (err) return handleError(err);
      +  console.log(res); // [ { maxAge: 98 } ]
      +});
      + +

      NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

      + +

      NOTE: this requires running MongoDB >= 2.1


      Model#base

      Base Mongoose instance the model uses.


      Model#collection

      Collection the model uses.


      Model#db

      Database instance the model uses.


      Model#schema

      Schema the model uses.


      Model#modelName

      The name of the model


      Model#collection

      Collection the model uses.


      Model#db

      Connection the model uses.


    • namedscope.js

      NamedScope#decorate(target, getters)

      Decorate

      show code
      NamedScope.prototype.decorate = function (target, getters) {
      +  var name = this.name
      +    , block = this.block
      +    , query = this.query;
      +  if (block) {
      +    if (block.length === 0) {
      +      Object.defineProperty(target, name, {
      +        get: getters.block0(block)
      +      });
      +    } else {
      +      target[name] = getters.blockN(block);
      +    }
      +  } else {
      +    Object.defineProperty(target, name, {
      +      get: getters.basic(query)
      +    });
      +  }
      +};
      +
      +NamedScope.prototype.compile = function (model) {
      +  var allScopes = this.scopesByName
      +    , scope;
      +  for (var k in allScopes) {
      +    scope = allScopes[k];
      +    scope.decorate(model, {
      +      block0: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.call(cquery);
      +          return this;
      +        };
      +      },
      +      blockN: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.apply(cquery, arguments);
      +          return this;
      +        };
      +      },
      +      basic: function (query) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          cquery.find(query);
      +          return this;
      +        };
      +      }
      +    });
      +  }
      +};
      +
      +module.exports = NamedScope;

      Parameters:


    • promise.js

      Promise(back)

      Promise constructor.

      show code
      function Promise (back) {
      +  this.emitted = {};
      +  if ('function' == typeof back)
      +    this.addBack(back);
      +};

      Parameters:

      • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

      Events:

      • err: Emits when the promise resolves to an error.

      • complete: Emits when the promise resolves sucessfully.


      Promise#on(event, callback)

      Adds listener to the event.

      show code
      Promise.prototype.on = function (event, callback) {
      +  if (this.emitted[event])
      +    callback.apply(this, this.emitted[event]);
      +  else
      +    EventEmitter.prototype.on.call(this, event, callback);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


      Promise#emit()

      Keeps track of emitted events to run them on on.

      show code
      Promise.prototype.emit = function (event) {
      +  // ensures a promise can't be complete() or error() twice
      +  if (event == 'err' || event == 'complete'){
      +    if (this.emitted.err || this.emitted.complete) {
      +      return this;
      +    }
      +    this.emitted[event] = util.args(arguments, 1);
      +  }
      +
      +  return EventEmitter.prototype.emit.apply(this, arguments);
      +};

      Promise#complete()

      Shortcut for emitting the complete event.

      show code
      Promise.prototype.complete = function () {
      +  var args = util.args(arguments);
      +  return this.emit.apply(this, ['complete'].concat(args));
      +};

      Promise#error()

      Shortcut for emitting the err event.

      show code
      Promise.prototype.error = function (err) {
      +  if (!(err instanceof Error)) err = new Error(err);
      +  return this.emit('err', err);
      +};

      Returns:


      Promise#addCallback()

      Shortcut for .on('complete', fn).

      show code
      Promise.prototype.addCallback = function (fn) {
      +  return this.on('complete', fn);
      +};

      Returns:


      Promise#addErrback()

      Shortcut for .on('err', fn).

      show code
      Promise.prototype.addErrback = function (fn) {
      +  return this.on('err', fn);
      +};

      Returns:


      Promise#addBack(fn)

      Adds a single function that's both a callback and errback.

      show code
      Promise.prototype.addBack = function (fn) {
      +  this.on('err', function(err){
      +    fn.call(this, err);
      +  });
      +
      +  this.on('complete', function(){
      +    var args = util.args(arguments);
      +    fn.apply(this, [null].concat(args));
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Promise#resolve(err, val)

      Sugar for handling cases where you may be resolving to either an error condition or a success condition.

      show code
      Promise.prototype.resolve = function (err, val) {
      +  if (err) return this.error(err);
      +  return this.complete(val);
      +};

      Parameters:

      • err <Error> optional error or null
      • val <Object> value to complete the promise with

    • query.js

      Query(criteria, options)

      Query constructor used for building queries.

      show code
      function Query (criteria, options) {
      +  this.setOptions(options, true);
      +  this._conditions = {};
      +  this._updateArg = {};
      +  this._fields = undefined;
      +  if (criteria) this.find(criteria);
      +}

      Parameters:

      Example:

      + +
      var query = Model.find();
      +query.where('age').gte(21).exec(callback);

      Query#setOptions(options)

      Sets query options.

      show code
      Query.prototype.setOptions = function (options, overwrite) {
      +  // overwrite is internal use only
      +  if (overwrite) {
      +    options = this.options = options || {};
      +    this.safe = options.safe
      +
      +    // normalize population options
      +    var pop = this.options.populate;
      +    this.options.populate = {};
      +
      +    if (pop && Array.isArray(pop)) {
      +      for (var i = 0, l = pop.length; i < l; i++) {
      +        this.options.populate[pop[i]] = {};
      +      }
      +    }
      +
      +    return this;
      +  }
      +
      +  if (!(options && 'Object' == options.constructor.name))
      +    return this;
      +
      +  if ('safe' in options)
      +    this.safe = options.safe;
      +
      +  // set arbitrary options
      +  var methods = Object.keys(options)
      +    , i = methods.length
      +    , method
      +
      +  while (i--) {
      +    method = methods[i];
      +
      +    // use methods if exist (safer option manipulation)
      +    if ('function' == typeof this[method]) {
      +      var args = Array.isArray(options[method])
      +        ? options[method]
      +        : [options[method]];
      +      this[method].apply(this, args)
      +    } else {
      +      this.options[method] = options[method];
      +    }
      +  }
      +  return this;
      +}

      Parameters:

      Options:

      + + + +

      * denotes a query helper method is also available


      Query#bind(model, op, updateArg)

      Binds this query to a model.

      show code
      Query.prototype.bind = function bind (model, op, updateArg) {
      +  this.model = model;
      +  this.op = op;
      +
      +  if (model._mapreduce) this.options.lean = true;
      +
      +  if (op == 'update' || op == 'findOneAndUpdate') {
      +    merge(this._updateArg, updateArg || {});
      +  }
      +
      +  return this;
      +};

      Parameters:

      • model <Model> the model to which the query is bound
      • op <String> the operation to execute
      • updateArg <Object> used in update methods

      Returns:


      Query#exec([operation], [callback])

      Executes the query

      show code
      Query.prototype.exec = function exec (op, callback) {
      +  var promise = new Promise();
      +
      +  switch (typeof op) {
      +    case 'function':
      +      callback = op;
      +      op = null;
      +      break;
      +    case 'string':
      +      this.op = op;
      +      break;
      +  }
      +
      +  if (callback) promise.addBack(callback);
      +
      +  if (!this.op) {
      +    promise.complete();
      +    return promise;
      +  }
      +
      +  if ('update' == this.op) {
      +    this[this.op](this._updateArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  if ('distinct' == this.op) {
      +    this.distinct(this._distinctArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  this[this.op](promise.resolve.bind(promise));
      +  return promise;
      +};

      Parameters:

      Returns:

      Examples

      + +
      query.exec();
      +query.exec(callback);
      +query.exec('update');
      +query.exec('find', callback);

      Query#find([criteria], [callback])

      Finds documents.

      show code
      Query.prototype.find = function (criteria, callback) {
      +  this.op = 'find';
      +  if ('function' === typeof criteria) {
      +    callback = criteria;
      +    criteria = {};
      +  } else if (criteria instanceof Query) {
      +    // TODO Merge options, too
      +    merge(this._conditions, criteria._conditions);
      +  } else if (criteria instanceof Document) {
      +    merge(this._conditions, criteria.toObject());
      +  } else if (criteria && 'Object' === criteria.constructor.name) {
      +    merge(this._conditions, criteria);
      +  }
      +  if (!callback) return this;
      +  return this.execFind(callback);
      +};

      Parameters:

      Returns:

      When no callback is passed, the query is not executed.

      + +

      Example

      + +
      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

      Query#cast(model, [obj])

      Casts this query to the schema of model

      show code
      Query.prototype.cast = function (model, obj) {
      +  obj || (obj= this._conditions);
      +
      +  var schema = model.schema
      +    , paths = Object.keys(obj)
      +    , i = paths.length
      +    , any$conditionals
      +    , schematype
      +    , nested
      +    , path
      +    , type
      +    , val;
      +
      +  while (i--) {
      +    path = paths[i];
      +    val = obj[path];
      +
      +    if ('$or' === path || '$nor' === path || '$and' === path) {
      +      var k = val.length
      +        , orComponentQuery;
      +
      +      while (k--) {
      +        orComponentQuery = new Query(val[k]);
      +        orComponentQuery.cast(model);
      +        val[k] = orComponentQuery._conditions;
      +      }
      +
      +    } else if (path === '$where') {
      +      type = typeof val;
      +
      +      if ('string' !== type && 'function' !== type) {
      +        throw new Error("Must have a string or function for $where");
      +      }
      +
      +      if ('function' === type) {
      +        obj[path] = val.toString();
      +      }
      +
      +      continue;
      +
      +    } else {
      +
      +      if (!schema) {
      +        // no casting for Mixed types
      +        continue;
      +      }
      +
      +      schematype = schema.path(path);
      +
      +      if (!schematype) {
      +        // Handle potential embedded array queries
      +        var split = path.split('.')
      +          , j = split.length
      +          , pathFirstHalf
      +          , pathLastHalf
      +          , remainingConds
      +          , castingQuery;
      +
      +        // Find the part of the var path that is a path of the Schema
      +        while (j--) {
      +          pathFirstHalf = split.slice(0, j).join('.');
      +          schematype = schema.path(pathFirstHalf);
      +          if (schematype) break;
      +        }
      +
      +        // If a substring of the input path resolves to an actual real path...
      +        if (schematype) {
      +          // Apply the casting; similar code for $elemMatch in schema/array.js
      +          if (schematype.caster && schematype.caster.schema) {
      +            remainingConds = {};
      +            pathLastHalf = split.slice(j).join('.');
      +            remainingConds[pathLastHalf] = val;
      +            castingQuery = new Query(remainingConds);
      +            castingQuery.cast(schematype.caster);
      +            obj[path] = castingQuery._conditions[pathLastHalf];
      +          } else {
      +            obj[path] = val;
      +          }
      +        }
      +
      +      } else if (val === null || val === undefined) {
      +        continue;
      +      } else if ('Object' === val.constructor.name) {
      +
      +        any$conditionals = Object.keys(val).some(function (k) {
      +          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
      +        });
      +
      +        if (!any$conditionals) {
      +          obj[path] = schematype.castForQuery(val);
      +        } else {
      +
      +          var ks = Object.keys(val)
      +            , k = ks.length
      +            , $cond;
      +
      +          while (k--) {
      +            $cond = ks[k];
      +            nested = val[$cond];
      +
      +            if ('$exists' === $cond) {
      +              if ('boolean' !== typeof nested) {
      +                throw new Error("$exists parameter must be Boolean");
      +              }
      +              continue;
      +            }
      +
      +            if ('$type' === $cond) {
      +              if ('number' !== typeof nested) {
      +                throw new Error("$type parameter must be Number");
      +              }
      +              continue;
      +            }
      +
      +            if ('$not' === $cond) {
      +              this.cast(model, nested);
      +            } else {
      +              val[$cond] = schematype.castForQuery($cond, nested);
      +            }
      +          }
      +        }
      +      } else {
      +        obj[path] = schematype.castForQuery(val);
      +      }
      +    }
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Returns:

      Note

      + +

      If obj is present, it is cast instead of this query.


      Query#_optionsForExec(model)

      Returns default options.

      show code
      Query.prototype._optionsForExec = function (model) {
      +  var options = utils.clone(this.options, { retainKeyOrder: true });
      +  delete options.populate;
      +
      +  if (!('safe' in options))
      +    options.safe = model.schema.options.safe;
      +
      +  if (!('readPreference' in options) && model.schema.options.read)
      +    options.readPreference = model.schema.options.read;
      +
      +  return options;
      +};

      Parameters:


      Query#_applyPaths()

      Applies schematype selected options to this query.

      show code
      Query.prototype._applyPaths = function applyPaths () {
      +  // determine if query is selecting or excluding fields
      +
      +  var fields = this._fields
      +    , exclude
      +    , keys
      +    , ki
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('+' == keys[ki][0]) continue;
      +      exclude = 0 === fields[keys[ki]];
      +      break;
      +    }
      +  }
      +
      +  // if selecting, apply default schematype select:true fields
      +  // if excluding, apply schematype select:false fields
      +
      +  var selected = []
      +    , excluded = []
      +    , seen = [];
      +
      +  analyzeSchema(this.model.schema);
      +
      +  switch (exclude) {
      +    case true:
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +    case false:
      +      selected.length && this.select(selected.join(' '));
      +      break;
      +    case undefined:
      +      // user didn't specify fields, implies returning all fields.
      +      // only need to apply excluded fields
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +  }
      +
      +  return seen = excluded = selected = keys = fields = null;
      +
      +  function analyzeSchema (schema, prefix) {
      +    prefix || (prefix = '');
      +
      +    // avoid recursion
      +    if (~seen.indexOf(schema)) return;
      +    seen.push(schema);
      +
      +    schema.eachPath(function (path, type) {
      +      if (prefix) path = prefix + '.' + path;
      +
      +      // array of subdocs?
      +      if (type.schema) {
      +        analyzeSchema(type.schema, path);
      +      }
      +
      +      analyzePath(path, type);
      +    });
      +  }
      +
      +  function analyzePath (path, type) {
      +    if ('boolean' != typeof type.selected) return;
      +
      +    if (fields && ('+' + path) in fields) {
      +      // forced inclusion
      +      delete fields['+' + path];
      +
      +      // if there are other fields being included, add this one
      +      // if no other included fields, leave this out (implied inclusion)
      +      if (false === exclude && keys.length > 1) {
      +        fields[path] = 1;
      +      }
      +
      +      return
      +    };
      +
      +    ;(type.selected ? selected : excluded).push(path);
      +  }
      +}

      Query#$where(js)

      Specifies a $where condition

      Parameters:

      Returns:

      Use $where when you need to select documents using a JavaScript expression.

      + +

      Example

      + +
      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
      +
      +query.$where(function () {
      +  return this.comments.length &gt; 10 || this.name.length &gt; 5;
      +})

      Query#where([path], [val])

      Specifies a path for use with chaining.

      show code
      Query.prototype.where = function (path, val) {
      +  if (!arguments.length) return this;
      +
      +  if ('string' != typeof path) {
      +    throw new TypeError('path must be a string');
      +  }
      +
      +  this._currPath = path;
      +
      +  if (2 === arguments.length) {
      +    this._conditions[path] = val;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      // instead of writing:
      +User.find({age: {$gte: 21, $lte: 65}}, callback);
      +
      +// we can instead write:
      +User.where('age').gte(21).lte(65);
      +
      +// Moreover, you can also chain a bunch of these together:
      +
      +User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +.where('friends').slice(10)
      +.exec(callback)

      Query#equals(val)

      Specifies the complementary comparison value for paths specified with where()

      show code
      Query.prototype.equals = function equals (val) {
      +  var path = this._currPath;
      +  if (!path) throw new Error('equals() must be used after where()');
      +  this._conditions[path] = val;
      +  return this;
      +}

      Parameters:

      Returns:

      Example

      + +
      User.where('age').equals(49);
      +
      +// is the same as
      +
      +User.where('age', 49);

      Query#or(array)

      Specifies arguments for an $or condition.

      show code
      Query.prototype.or = function or (array) {
      +  var or = this._conditions.$or || (this._conditions.$or = []);
      +  if (!Array.isArray(array)) array = [array];
      +  or.push.apply(or, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.or([{ color: 'red' }, { status: 'emergency' }])

      Query#nor(array)

      Specifies arguments for a $nor condition.

      show code
      Query.prototype.nor = function nor (array) {
      +  var nor = this._conditions.$nor || (this._conditions.$nor = []);
      +  if (!Array.isArray(array)) array = [array];
      +  nor.push.apply(nor, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.nor([{ color: 'green' }, { status: 'ok' }])

      Query#and(array)

      Specifies arguments for a $and condition.

      show code
      Query.prototype.and = function and (array) {
      +  var and = this._conditions.$and || (this._conditions.$and = []);
      +  if (!Array.isArray(array)) array = [array];
      +  and.push.apply(and, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.and([{ color: 'green' }, { status: 'ok' }])

      Query#gt(path, val)

      Specifies a $gt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.

      + +

      Example

      + +
      Thing.find().where('age').gt(21)
      +
      +// or
      +Thing.find().gt('age', 21)

      Query#gte(path, val)

      Specifies a $gte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lt(path, val)

      Specifies a $lt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lte(path, val)

      Specifies a $lte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#ne(path, val)

      Specifies a $ne query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#in(path, val)

      Specifies an $in query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#nin(path, val)

      Specifies an $nin query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#all(path, val)

      Specifies an $all query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#size(path, val)

      Specifies an $size query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#regex(path, val)

      Specifies a $regex query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#maxDistance(path, val)

      Specifies a $maxDistance query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#near(path, val)

      Specifies a $near condition

      show code
      Query.prototype.near = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$near = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#nearSphere(path, val)

      Specifies a $nearSphere condition.

      show code
      Query.prototype.nearSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$nearSphere = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#mod(path, val)

      Specifies a $mod condition

      show code
      Query.prototype.mod = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$mod = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#exists(path, val)

      Specifies an $exists condition

      show code
      Query.prototype.exists = function (path, val) {
      +  if (arguments.length === 0) {
      +    path = this._currPath
      +    val = true;
      +  } else if (arguments.length === 1) {
      +    if ('boolean' === typeof path) {
      +      val = path;
      +      path = this._currPath;
      +    } else {
      +      val = true;
      +    }
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$exists'] = val;
      +  return this;
      +};

      Parameters:

      Returns:


      Query#elemMatch(path, criteria)

      Specifies an $elemMatch condition

      show code
      Query.prototype.elemMatch = function (path, criteria) {
      +  var block;
      +  if ('Object' === path.constructor.name) {
      +    criteria = path;
      +    path = this._currPath;
      +  } else if ('function' === typeof path) {
      +    block = path;
      +    path = this._currPath;
      +  } else if ('Object' === criteria.constructor.name) {
      +  } else if ('function' === typeof criteria) {
      +    block = criteria;
      +  } else {
      +    throw new Error("Argument error");
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  if (block) {
      +    criteria = new Query();
      +    block(criteria);
      +    conds['$elemMatch'] = criteria._conditions;
      +  } else {
      +    conds['$elemMatch'] = criteria;
      +  }
      +  return this;
      +};
      +
      +// Spatial queries

      Parameters:

      Returns:

      Example

      + +
      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
      +
      +query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
      +
      +query.elemMatch('comment', function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})
      +
      +query.where('comment').elemMatch(function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})

      Query#box(path, val)

      Specifies a $box condition

      show code
      Query.prototype.box = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$box': [val.ll, val.ur]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var lowerLeft = [40.73083, -73.99756]
      +var upperRight= [40.741404,  -73.988135]
      +query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

      Query#center(path, val, [opts])

      Specifies a $center condition

      show code
      Query.prototype.center = function (path, val, opts) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$center': [val.center, val.radius]  };
      +
      +  // copy any options
      +  if (opts && 'Object' == opts.constructor.name) {
      +    utils.options(opts, conds.$within);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.center(area)

      Query#centerSphere(path, val)

      Specifies a $centerSphere condition

      show code
      Query.prototype.centerSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.centerSphere(area)

      Query#polygon(path, val)

      Specifies a $polygon condition

      show code
      Query.prototype.polygon = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$polygon': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      +query.where('loc').within.polygon(polyA)
      +
      +// or
      +var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      +query.where('loc').within.polygon(polyB)

      Query#select(arg)

      Specifies which document fields to include or exclude

      show code
      Query.prototype.select = function select (arg) {
      +  if (!arg) return this;
      +
      +  var fields = this._fields || (this._fields = {});
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      fields[field] = arg[field];
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var include = '-' == field[0] ? 0 : 1;
      +      if (include === 0) field = field.substring(1);
      +      fields[field] = include;
      +    });
      +  } else {
      +    throw new TypeError('Invalid select() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

      + +

      Example

      + +
      // include a and b, exclude c
      +query.select('a b -c');
      +
      +// or you may use object notation, useful when
      +// you have keys already prefixed with a "-"
      +query.select({a: 1, b: 1, c: 0});
      +
      +// force inclusion of field excluded at schema level
      +query.select('+path')
      + +

      NOTE:

      + +

      v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


      Query#slice(path, val)

      Specifies a $slice condition

      show code
      Query.prototype.slice = function (path, val) {
      +  if (arguments.length === 1) {
      +      val = path;
      +      path = this._currPath
      +  } else if (arguments.length === 2) {
      +    if ('number' === typeof path) {
      +      val = [path, val];
      +      path = this._currPath;
      +    }
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var myFields = this._fields || (this._fields = {});
      +  myFields[path] = { '$slice': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      query.slice('comments', 5)
      +query.slice('comments', -5)
      +query.slice('comments', [10, 5])
      +query.where('comments').slice(5)
      +query.where('comments').slice([-10, 5])

      Query#sort(arg)

      Sets the sort order

      show code
      Query.prototype.sort = function (arg) {
      +  if (!arg) return this;
      +
      +  var sort = this.options.sort || (this.options.sort = []);
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      push(sort, field, arg[field]);
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var ascend = '-' == field[0] ? -1 : 1;
      +      if (ascend === -1) field = field.substring(1);
      +      push(sort, field, ascend);
      +    });
      +  } else {
      +    throw new TypeError('Invalid sort() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

      + +

      If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

      + +

      Example

      + +
      // these are equivalent
      +query.sort({ field: 'asc', test: -1 });
      +query.sort('field -test');

      Query#limit(val)

      Specifies the limit option.

      Parameters:

      Example

      + +
      Kitten.find().limit(20)

      Query#skip(val)

      Specifies the skip option.

      Parameters:

      Example

      + +
      Kitten.find().skip(100).limit(20)

      Query#maxscan(val)

      Specifies the maxscan option.

      Parameters:

      Example

      + +
      Kitten.find().maxscan(100)

      Query#batchSize(val)

      Specifies the batchSize option.

      Parameters:

      Example

      + +
      Kitten.find().batchSize(100)

      Query#comment(val)

      Specifies the comment option.

      Parameters:

      Example

      + +
      Kitten.findOne(condition).comment('login query')

      Query#snapshot()

      Specifies this query as a snapshot query.

      show code
      Query.prototype.snapshot = function () {
      +  this.options.snapshot = true;
      +  return this;
      +};

      Returns:

      Example

      + +
      Kitten.find().snapshot()

      Query#hint(val)

      Sets query hints.

      show code
      Query.prototype.hint = function (val) {
      +  if (!val) return this;
      +
      +  var hint = this.options.hint || (this.options.hint = {});
      +
      +  if ('Object' === val.constructor.name) {
      +    // must keep object keys in order so don't use Object.keys()
      +    for (var k in val) {
      +      hint[k] = val[k];
      +    }
      +  } else {
      +    throw new TypeError('Invalid hint. ' + val);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Model.find().hint({ indexA: 1, indexB: -1})

      Query#slaveOk(v)

      Sets the slaveOk option.

      show code
      Query.prototype.slaveOk = function (v) {
      +  this.options.slaveOk = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Example:

      + +
      new Query().slaveOk() // true
      +new Query().slaveOk(true)
      +new Query().slaveOk(false)

      Query#read(pref, [tags])

      Sets the readPreference option for the query.

      show code
      Query.prototype.read = function (pref, tags) {
      +  this.options.readPreference = utils.readPref(pref, tags);
      +  return this;
      +}

      Parameters:

      • pref <String> one of the listed preference options or their aliases
      • [tags] <Array> optional tags for this query

      Returns:

      Example:

      + +
      new Query().read('primary')
      +new Query().read('p')  // same as primary
      +
      +new Query().read('primaryPreferred')
      +new Query().read('pp') // same as primaryPreferred
      +
      +new Query().read('secondary')
      +new Query().read('s')  // same as secondary
      +
      +new Query().read('secondaryPreferred')
      +new Query().read('sp') // same as secondaryPreferred
      +
      +new Query().read('nearest')
      +new Query().read('n')  // same as nearest
      +
      +// with tags
      +new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
      + +

      Preferences:

      + +
      primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
      +secondary            Read from secondary if available, otherwise error.
      +primaryPreferred     Read from primary if available, otherwise a secondary.
      +secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
      +nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
      + +

      Aliases

      + +
      p   primary
      +pp  primaryPreferred
      +s   secondary
      +sp  secondaryPreferred
      +n   nearest
      + +

      Read more about how to use read preferrences here and here.


      Query#lean(v)

      Sets the lean option.

      show code
      Query.prototype.lean = function (v) {
      +  this.options.lean = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

      + +

      This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

      + +

      Example:

      + +
      new Query().lean() // true
      +new Query().lean(true)
      +new Query().lean(false)
      +
      +Model.find().lean().exec();
      +
      +var leanStream = Model.find().lean().stream();

      Query#tailable(v)

      Sets tailable option.

      show code
      Query.prototype.tailable = function (v) {
      +  this.options.tailable = arguments.length ? !!v : true;
      +  return this;
      +};

      Parameters:

      Example

      + +
      Kitten.find().tailable() &lt;== true
      +Kitten.find().tailable(true)
      +Kitten.find().tailable(false)

      Query#execFind(callback)

      Executes the query as a find() operation.

      show code
      Query.prototype.execFind = function (callback) {
      +  var model = this.model
      +    , promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.find(castQuery, options, function (err, cursor) {
      +    if (err) return promise.error(err);
      +    cursor.toArray(tick(cb));
      +  });
      +
      +  function cb (err, docs) {
      +    if (err) return promise.error(err);
      +
      +    if (true === options.lean)
      +      return promise.complete(docs);
      +
      +    var arr = []
      +      , count = docs.length;
      +
      +    if (!count) return promise.complete([]);
      +
      +    for (var i = 0, l = docs.length; i < l; i++) {
      +      arr[i] = new model(undefined, fields, true);
      +      arr[i].init(docs[i], self, function (err) {
      +        if (err) return promise.error(err);
      +        --count || promise.complete(arr);
      +      });
      +    }
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#findOne(callback)

      Executes the query as a findOne() operation.

      show code
      Query.prototype.findOne = function (callback) {
      +  this.op = 'findOne';
      +
      +  if (!callback) return this;
      +
      +  var model = this.model;
      +  var promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.findOne(castQuery, options, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === options.lean) return promise.complete(doc);
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'white').findOne(function (err, kitten) {
      +  if (err) return handleError(err);
      +
      +  // kitten may be null if no document matched
      +  if (kitten) {
      +    ...
      +  }
      +})

      Query#count(callback)

      Exectues the query as a count() operation.

      show code
      Query.prototype.count = function (callback) {
      +  this.op = 'count';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.count(castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'black').count(function (err, count) {
      +  if (err) return handleError(err);
      +  console.log('there are %d black kittens', count);
      +})

      Query#distinct(field, callback)

      Executes this query as a distict() operation.

      show code
      Query.prototype.distinct = function (field, callback) {
      +  this.op = 'distinct';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.distinct(field, castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#update(doc, callback)

      Executes this query as an update() operation.

      show code
      Query.prototype.update = function update (doc, callback) {
      +  this.op = 'update';
      +  this._updateArg = doc;
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , fn = 'function' == typeof callback
      +    , castedQuery
      +    , castedDoc
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedQuery));
      +      return this;
      +    }
      +    throw castedQuery;
      +  }
      +
      +  castedDoc = castDoc(this);
      +  if (!castedDoc) {
      +    fn && process.nextTick(callback.bind(null, null, 0));
      +    return this;
      +  }
      +
      +  if (castedDoc instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedDoc));
      +      return this;
      +    }
      +    throw castedDoc;
      +  }
      +
      +  if (!fn) {
      +    delete options.safe;
      +  }
      +
      +  model.collection.update(castedQuery, castedDoc, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Returns:

      All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

      + +

      Example

      + +
      Model.update({..}, { title: 'remove words' }, ...)
      + +

      becomes

      + +
      Model.update({..}, { $set: { title: 'remove words' }}, ...)
      + +

      Note

      + +

      Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


      Query#_castUpdate(obj)

      Casts obj for an update command.

      show code
      Query.prototype._castUpdate = function _castUpdate (obj) {
      +  var ops = Object.keys(obj)
      +    , i = ops.length
      +    , ret = {}
      +    , hasKeys
      +    , val
      +
      +  while (i--) {
      +    var op = ops[i];
      +    if ('$' !== op[0]) {
      +      // fix up $set sugar
      +      if (!ret.$set) {
      +        if (obj.$set) {
      +          ret.$set = obj.$set;
      +        } else {
      +          ret.$set = {};
      +        }
      +      }
      +      ret.$set[op] = obj[op];
      +      ops.splice(i, 1);
      +      if (!~ops.indexOf('$set')) ops.push('$set');
      +    } else if ('$set' === op) {
      +      if (!ret.$set) {
      +        ret[op] = obj[op];
      +      }
      +    } else {
      +      ret[op] = obj[op];
      +    }
      +  }
      +
      +  // cast each value
      +  i = ops.length;
      +
      +  while (i--) {
      +    op = ops[i];
      +    val = ret[op];
      +    if ('Object' === val.constructor.name) {
      +      hasKeys |= this._walkUpdatePath(val, op);
      +    } else {
      +      var msg = 'Invalid atomic update value for ' + op + '. '
      +              + 'Expected an object, received ' + typeof val;
      +      throw new Error(msg);
      +    }
      +  }
      +
      +  return hasKeys && ret;
      +}

      Parameters:

      Returns:

      • <Object> obj after casting its values

      Query#_walkUpdatePath(obj, op, pref)

      Walk each path of obj and cast its values
      according to its schema.

      show code
      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
      +  var strict = this.model.schema.options.strict
      +    , prefix = pref ? pref + '.' : ''
      +    , keys = Object.keys(obj)
      +    , i = keys.length
      +    , hasKeys = false
      +    , schema
      +    , key
      +    , val
      +
      +  while (i--) {
      +    key = keys[i];
      +    val = obj[key];
      +
      +    if (val && 'Object' === val.constructor.name) {
      +      // watch for embedded doc schemas
      +      schema = this._getSchema(prefix + key);
      +      if (schema && schema.caster && op in castOps) {
      +        // embedded doc schema
      +
      +        if (strict && !schema) {
      +          // path is not in our strict schema
      +          if ('throw' == strict) {
      +            throw new Error('Field `' + key + '` is not in schema.');
      +          } else {
      +            // ignore paths not specified in schema
      +            delete obj[key];
      +          }
      +        } else {
      +          hasKeys = true;
      +          if ('$each' in val) {
      +            obj[key] = {
      +                $each: this._castUpdateVal(schema, val.$each, op)
      +            }
      +          } else {
      +            obj[key] = this._castUpdateVal(schema, val, op);
      +          }
      +        }
      +      } else {
      +        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
      +      }
      +    } else {
      +      schema = '$each' === key
      +        ? this._getSchema(pref)
      +        : this._getSchema(prefix + key);
      +
      +      var skip = strict &&
      +                 !schema &&
      +                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
      +
      +      if (skip) {
      +        if ('throw' == strict) {
      +          throw new Error('Field `' + prefix + key + '` is not in schema.');
      +        } else {
      +          delete obj[key];
      +        }
      +      } else {
      +        hasKeys = true;
      +        obj[key] = this._castUpdateVal(schema, val, op, key);
      +      }
      +    }
      +  }
      +  return hasKeys;
      +}

      Parameters:

      • obj <Object> - part of a query
      • op <String> - the atomic operator ($pull, $set, etc)
      • pref <String> - path prefix (internal only)

      Returns:

      • <Bool> true if this path has keys to update

      Query#_castUpdateVal(schema, val, op, [$conditional])

      Casts val according to schema and atomic op.

      show code
      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
      +  if (!schema) {
      +    // non-existing schema path
      +    return op in numberOps
      +      ? Number(val)
      +      : val
      +  }
      +
      +  if (schema.caster && op in castOps &&
      +    ('Object' === val.constructor.name || Array.isArray(val))) {
      +    // Cast values for ops that add data to MongoDB.
      +    // Ensures embedded documents get ObjectIds etc.
      +    var tmp = schema.cast(val);
      +
      +    if (Array.isArray(val)) {
      +      val = tmp;
      +    } else {
      +      val = tmp[0];
      +    }
      +  }
      +
      +  if (op in numberOps) return Number(val);
      +  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
      +  return schema.castForQuery(val)
      +}

      Parameters:


      Query#_getSchema(path)

      Finds the schema for path. This is different than
      calling schema.path as it also resolves paths with
      positional selectors (something.$.another.$.path).

      show code
      Query.prototype._getSchema = function _getSchema (path) {
      +  var schema = this.model.schema
      +    , pathschema = schema.path(path);
      +
      +  if (pathschema)
      +    return pathschema;
      +
      +  // look for arrays
      +  return (function search (parts, schema) {
      +    var p = parts.length + 1
      +      , foundschema
      +      , trypath
      +
      +    while (p--) {
      +      trypath = parts.slice(0, p).join('.');
      +      foundschema = schema.path(trypath);
      +      if (foundschema) {
      +        if (foundschema.caster) {
      +
      +          // array of Mixed?
      +          if (foundschema.caster instanceof Types.Mixed) {
      +            return foundschema.caster;
      +          }
      +
      +          // Now that we found the array, we need to check if there
      +          // are remaining document paths to look up for casting.
      +          // Also we need to handle array.$.path since schema.path
      +          // doesn't work for that.
      +          if (p !== parts.length) {
      +            if ('$' === parts[p]) {
      +              // comments.$.comments.$.title
      +              return search(parts.slice(p+1), foundschema.schema);
      +            } else {
      +              // this is the last path of the selector
      +              return search(parts.slice(p), foundschema.schema);
      +            }
      +          }
      +        }
      +        return foundschema;
      +      }
      +    }
      +  })(path.split('.'), schema)
      +}

      Parameters:


      Query#_castFields(fields)

      Casts selected field arguments for field selection with mongo 2.2

      show code
      Query.prototype._castFields = function _castFields (fields) {
      +  var selected
      +    , elemMatchKeys
      +    , keys
      +    , key
      +    , out
      +    , i
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    elemMatchKeys = [];
      +    i = keys.length;
      +
      +    // collect $elemMatch args
      +    while (i--) {
      +      key = keys[i];
      +      if (fields[key].$elemMatch) {
      +        selected || (selected = {});
      +        selected[key] = fields[key];
      +        elemMatchKeys.push(key);
      +      }
      +    }
      +  }
      +
      +  if (selected) {
      +    // they passed $elemMatch, cast em
      +    try {
      +      out = this.cast(this.model, selected);
      +    } catch (err) {
      +      return err;
      +    }
      +
      +    // apply the casted field args
      +    i = elemMatchKeys.length;
      +    while (i--) {
      +      key = elemMatchKeys[i];
      +      fields[key] = out[key];
      +    }
      +  }
      +
      +  return fields;
      +}

      Parameters:

      query.select({ ids: { $elemMatch: { $in: [hexString] }})

      Query#remove(callback)

      Executes this query as a remove() operation.

      show code
      Query.prototype.remove = function (callback) {
      +  this.op = 'remove';
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , cb = 'function' == typeof callback
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    if (cb) return callback(err);
      +    throw err;
      +  }
      +
      +  if (!cb) {
      +    delete options.safe;
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.remove(castQuery, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Example

      + +
      Cassette.where('artist').equals('Anne Murray').remove(callback)

      Query#findOneAndUpdate([query], [doc], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
      +  this.op = 'findOneAndUpdate';
      +
      +  switch (arguments.length) {
      +    case 3:
      +      if ('function' == typeof options)
      +        callback = options, options = {};
      +      break;
      +    case 2:
      +      if ('function' == typeof doc) {
      +        callback = doc;
      +        doc = query;
      +        query = undefined;
      +      }
      +      options = undefined;
      +      break;
      +    case 1:
      +      if ('function' == typeof query) {
      +        callback = query;
      +        query = options = doc = undefined;
      +      } else {
      +        doc = query;
      +        query = options = undefined;
      +      }
      +  }
      +
      +  // apply query
      +  if (query) {
      +    if ('Object' === query.constructor.name) {
      +      merge(this._conditions, query);
      +    } else if (query instanceof Query) {
      +      merge(this._conditions, query._conditions);
      +    } else if (query instanceof Document) {
      +      merge(this._conditions, query.toObject());
      +    }
      +  }
      +
      +  // apply doc
      +  if (doc) {
      +    merge(this._updateArg, doc);
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('update', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      query.findOneAndUpdate(conditions, update, options, callback) // executes
      +query.findOneAndUpdate(conditions, update, options)  // returns Query
      +query.findOneAndUpdate(conditions, update, callback) // executes
      +query.findOneAndUpdate(conditions, update)           // returns Query
      +query.findOneAndUpdate(callback)                     // executes
      +query.findOneAndUpdate()                             // returns Query

      Query#findOneAndRemove([conditions], [options], [callback])

      Issues a mongodb findAndModify remove command.

      show code
      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
      +  this.op = 'findOneAndRemove';
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = undefined;
      +  }
      +
      +  // apply conditions
      +  if (conditions) {
      +    if ('Object' === conditions.constructor.name) {
      +      merge(this._conditions, conditions);
      +    } else if (conditions instanceof Query) {
      +      merge(this._conditions, conditions._conditions);
      +    } else if (conditions instanceof Document) {
      +      merge(this._conditions, conditions.toObject());
      +    }
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('remove', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      A.where().findOneAndRemove(conditions, options, callback) // executes
      +A.where().findOneAndRemove(conditions, options)  // return Query
      +A.where().findOneAndRemove(conditions, callback) // executes
      +A.where().findOneAndRemove(conditions) // returns Query
      +A.where().findOneAndRemove(callback)   // executes
      +A.where().findOneAndRemove()           // returns Query

      Query#_findAndModify(type, callback)

      _findAndModify

      show code
      Query.prototype._findAndModify = function (type, callback) {
      +  var model = this.model
      +    , promise = new Promise(callback)
      +    , self = this
      +    , castedQuery
      +    , castedDoc
      +    , fields
      +    , sort
      +    , opts
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    process.nextTick(promise.error.bind(promise, castedQuery));
      +    return promise;
      +  }
      +
      +  opts = this._optionsForExec(model);
      +
      +  if ('remove' == type) {
      +    opts.remove = true;
      +  } else {
      +    if (!('new' in opts)) opts.new = true;
      +    if (!('upsert' in opts)) opts.upsert = false;
      +
      +    castedDoc = castDoc(this);
      +    if (!castedDoc) {
      +      if (opts.upsert) {
      +        // still need to do the upsert to empty doc
      +        castedDoc = { $set: {} };
      +      } else {
      +        return this.findOne(callback);
      +      }
      +    } else if (castedDoc instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, castedDoc));
      +      return promise;
      +    }
      +  }
      +
      +  this._applyPaths();
      +
      +  if (this._fields) {
      +    fields = utils.clone(this._fields)
      +    opts.fields = this._castFields(fields);
      +    if (opts.fields instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, opts.fields));
      +      return promise;
      +    }
      +  }
      +
      +  // the driver needs a default
      +  sort = opts.sort || [];
      +
      +  model
      +  .collection
      +  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === opts.lean) {
      +      return promise.complete(doc);
      +    }
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return promise;
      +}

      Parameters:


      Query#populate(path, [fields], [model], [conditions], [options])

      Specifies paths which should be populated with other documents.

      show code
      Query.prototype.populate = function (path, fields, model, conditions, options) {
      +  if ('string' !== typeof model) {
      +    options = conditions;
      +    conditions = model;
      +    model = undefined;
      +  }
      +  // The order of fields/conditions args is opposite Model.find but
      +  // necessary to keep backward compatibility (fields could be
      +  // an array, string, or object literal).
      +  this.options.populate[path] =
      +    new PopulateOptions(fields, conditions, options, model);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

      + +

      Example:

      + +
      Kitten.findOne().populate('owner').exec(function (err, kitten) {
      +  console.log(kitten.owner.name) // Max
      +})

      Query#stream()

      Returns a stream interface

      show code
      Query.prototype.stream = function stream () {
      +  return new QueryStream(this);
      +}
      +
      +// helpers

      Returns:

      Example

      + +
      // follows the nodejs stream api
      +Thing.find({ name: /^hello/ }).stream().pipe(res)
      +
      +// manual streaming
      +var stream = Thing.find({ name: /^hello/ }).stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});

      Query#within

      Syntax sugar for expressive queries.

      + +

      Example

      + +
      query.within.box()
      +query.within.center()

      Returns:


    • querystream.js

      QueryStream(query)

      Provides a ReadStream interface for Queries.

      show code
      function QueryStream (query) {
      +  Stream.call(this);
      +
      +  this.query = query;
      +  this.readable = true;
      +  this.paused = false;
      +  this._cursor = null;
      +  this._destroyed = null;
      +  this._fields = null;
      +  this._buffer = null;
      +  this._inline = T_INIT;
      +  this._running = false;
      +
      +  // give time to hook up events
      +  var self = this;
      +  process.nextTick(function () {
      +    self._init();
      +  });
      +}

      Parameters:

      Inherits:

      Events:

      • data: emits a single Mongoose document

      • error: emits when an error occurs during streaming. This will emit before the close event.

      • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

      var stream = Model.find().stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});
      + +

      The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

      + +
      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

      QueryStream#_init()

      Initializes the query.

      show code
      QueryStream.prototype._init = function () {
      +  if (this._destroyed) return;
      +
      +  var query = this.query
      +    , model = query.model
      +    , options = query._optionsForExec(model)
      +    , self = this
      +
      +  try {
      +    query.cast(model);
      +  } catch (err) {
      +    return self.destroy(err);
      +  }
      +
      +  self._fields = utils.clone(query._fields);
      +  options.fields = query._castFields(self._fields);
      +
      +  model.collection.find(query._conditions, options, function (err, cursor) {
      +    if (err) return self.destroy(err);
      +    self._cursor = cursor;
      +    self._next();
      +  });
      +}

      QueryStream#_next()

      Trampoline for pulling the next doc from cursor.

      show code
      QueryStream.prototype._next = function _next () {
      +  if (this.paused || this._destroyed) {
      +    return this._running = false;
      +  }
      +
      +  this._running = true;
      +
      +  if (this._buffer && this._buffer.length) {
      +    var arg;
      +    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
      +      this._onNextObject.apply(this, arg);
      +    }
      +  }
      +
      +  // avoid stack overflows with large result sets.
      +  // trampoline instead of recursion.
      +  while (this.__next()) {}
      +}

      QueryStream#__next()

      Pulls the next doc from the cursor.

      show code
      QueryStream.prototype.__next = function () {
      +  if (this.paused || this._destroyed)
      +    return this._running = false;
      +
      +  var self = this;
      +  self._inline = T_INIT;
      +
      +  self._cursor.nextObject(function cursorcb (err, doc) {
      +    self._onNextObject(err, doc);
      +  });
      +
      +  // if onNextObject() was already called in this tick
      +  // return ourselves to the trampoline.
      +  if (T_CONT === this._inline) {
      +    return true;
      +  } else {
      +    // onNextObject() hasn't fired yet. tell onNextObject
      +    // that its ok to call _next b/c we are not within
      +    // the trampoline anymore.
      +    this._inline = T_IDLE;
      +  }
      +}

      QueryStream#_onNextObject(err, doc)

      Transforms raw docs returned from the cursor into a model instance.

      show code
      QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
      +  if (this._destroyed) return;
      +
      +  if (this.paused) {
      +    this._buffer || (this._buffer = []);
      +    this._buffer.push([err, doc]);
      +    return this._running = false;
      +  }
      +
      +  if (err) return this.destroy(err);
      +
      +  // when doc is null we hit the end of the cursor
      +  if (!doc) {
      +    this.emit('end');
      +    return this.destroy();
      +  }
      +
      +  if (this.query.options && true === this.query.options.lean)  {
      +    this.emit('data', doc);
      +
      +    // trampoline management
      +    if (T_IDLE === this._inline) {
      +      // no longer in trampoline. restart it.
      +      this._next();
      +    } else {
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      this._inline = T_CONT;
      +    }
      +    return;
      +  }
      +
      +  var instance = new this.query.model(undefined, this._fields, true);
      +
      +  var self = this;
      +  instance.init(doc, this.query, function (err) {
      +    if (err) return self.destroy(err);
      +    self.emit('data', instance);
      +
      +    // trampoline management
      +    if (T_IDLE === self._inline) {
      +      // no longer in trampoline. restart it.
      +      self._next();
      +    } else
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      self._inline = T_CONT;
      +  });
      +}

      Parameters:


      QueryStream#pause()

      Pauses this stream.

      show code
      QueryStream.prototype.pause = function () {
      +  this.paused = true;
      +}

      QueryStream#resume()

      Resumes this stream.

      show code
      QueryStream.prototype.resume = function () {
      +  this.paused = false;
      +
      +  if (!this._cursor) {
      +    // cannot start if not initialized
      +    return;
      +  }
      +
      +  // are we within the trampoline?
      +  if (T_INIT === this._inline) {
      +    return;
      +  }
      +
      +  if (!this._running) {
      +    // outside QueryStream control, need manual restart
      +    return this._next();
      +  }
      +}

      QueryStream#destroy([err])

      Destroys the stream, closing the underlying cursor. No more events will be emitted.

      show code
      QueryStream.prototype.destroy = function (err) {
      +  if (this._destroyed) return;
      +  this._destroyed = true;
      +  this._running = false;
      +  this.readable = false;
      +
      +  if (this._cursor) {
      +    this._cursor.close();
      +  }
      +
      +  if (err) {
      +    this.emit('error', err);
      +  }
      +
      +  this.emit('close');
      +}

      Parameters:


      QueryStream#pipe()

      Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

      See:

      Example:

      + +
      query.stream().pipe(writeStream [, options])
      + +

      This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      + +
      var format = new ArrayFormatter;
      +Events.find().stream().pipe(format).pipe(res);
      + +

      As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


      QueryStream#paused

      Flag stating whether or not this stream is paused.


      QueryStream#readable

      Flag stating whether or not this stream is readable.


    • schema/array.js

      SchemaArray(key, cast, options)

      Array SchemaType constructor

      show code
      function SchemaArray (key, cast, options) {
      +  if (cast) {
      +    var castOptions = {};
      +
      +    if ('Object' === cast.constructor.name) {
      +      if (cast.type) {
      +        // support { type: Woot }
      +        castOptions = cast;
      +        cast = cast.type;
      +        delete castOptions.type;
      +      } else {
      +        cast = Mixed;
      +      }
      +    }
      +
      +    var caster = cast.name in Types ? Types[cast.name] : cast;
      +    this.casterConstructor = caster;
      +    this.caster = new caster(null, castOptions);
      +  }
      +
      +  SchemaType.call(this, key, options);
      +
      +  var self = this
      +    , defaultArr
      +    , fn;
      +
      +  if (this.defaultValue) {
      +    defaultArr = this.defaultValue;
      +    fn = 'function' == typeof defaultArr;
      +  }
      +
      +  this.default(function(){
      +    var arr = fn ? defaultArr() : defaultArr || [];
      +    return new MongooseArray(arr, self.path, this);
      +  });
      +};

      Parameters:

      Inherits:


      SchemaArray#checkRequired(value)

      Check required

      show code
      SchemaArray.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      Parameters:


      SchemaArray#applyGetters(value, scope)

      Overrides the getters application for the population special-case

      show code
      SchemaArray.prototype.applyGetters = function (value, scope) {
      +  if (this.caster.options && this.caster.options.ref) {
      +    // means the object id was populated
      +    return value;
      +  }
      +
      +  return SchemaType.prototype.applyGetters.call(this, value, scope);
      +};

      Parameters:


      SchemaArray#cast(value, doc, init)

      Casts contents

      show code
      SchemaArray.prototype.cast = function (value, doc, init) {
      +  if (Array.isArray(value)) {
      +    if (!(value instanceof MongooseArray)) {
      +      value = new MongooseArray(value, this.path, doc);
      +    }
      +
      +    if (this.caster) {
      +      try {
      +        for (var i = 0, l = value.length; i < l; i++) {
      +          value[i] = this.caster.cast(value[i], doc, init);
      +        }
      +      } catch (e) {
      +        // rethrow
      +        throw new CastError(e.type, value);
      +      }
      +    }
      +
      +    return value;
      +  } else {
      +    return this.cast([value], doc, init);
      +  }
      +};

      Parameters:

      • value <Object>
      • doc <Document> document that triggers the casting
      • init <Boolean> whether this is an initialization cast

      SchemaArray#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaArray.prototype.castForQuery = function ($conditional, value) {
      +  var handler
      +    , val;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Array.");
      +    val = handler.call(this, value);
      +  } else {
      +    val = $conditional;
      +    var proto = this.casterConstructor.prototype;
      +    var method = proto.castForQuery || proto.cast;
      +    if (Array.isArray(val)) {
      +      val = val.map(function (v) {
      +        if (method) v = method.call(proto, v);
      +        return isMongooseObject(v)
      +          ? v.toObject()
      +          : v;
      +      });
      +    } else if (method) {
      +      val = method.call(proto, val);
      +    }
      +  }
      +  return val && isMongooseObject(val)
      +    ? val.toObject()
      +    : val;
      +};

      Parameters:


    • schema/boolean.js

      SchemaBoolean(path, options)

      Boolean SchemaType constructor.

      show code
      function SchemaBoolean (path, options) {
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      SchemaBoolean#checkRequired()

      Required validator

      show code
      SchemaBoolean.prototype.checkRequired = function (value) {
      +  return value === true || value === false;
      +};

      SchemaBoolean#cast(value)

      Casts to boolean

      show code
      SchemaBoolean.prototype.cast = function (value) {
      +  if (value === null) return value;
      +  if (value === '0') return false;
      +  return !!value;
      +};

      Parameters:


      SchemaBoolean#castForQuery($conditional, val)

      Casts contents for queries.

      show code
      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (2 === arguments.length) {
      +    handler = SchemaBoolean.$conditionalHandlers[$conditional];
      +
      +    if (handler) {
      +      return handler.call(this, val);
      +    }
      +
      +    return this.cast(val);
      +  }
      +
      +  return this.cast($conditional);
      +};

      Parameters:


    • schema/buffer.js

      SchemaBuffer(key, cast)

      Buffer SchemaType constructor

      show code
      function SchemaBuffer (key, options) {
      +  SchemaType.call(this, key, options, 'Buffer');
      +};

      Parameters:

      Inherits:


      SchemaBuffer#checkRequired()

      Check required

      show code
      SchemaBuffer.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      SchemaBuffer#cast(value, doc, init)

      Casts contents

      show code
      SchemaBuffer.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (Buffer.isBuffer(value)) {
      +    if (!(value instanceof MongooseBuffer)) {
      +      value = new MongooseBuffer(value, [this.path, doc]);
      +    }
      +
      +    return value;
      +  } else if (value instanceof Binary) {
      +    return new MongooseBuffer(value.value(true), [this.path, doc]);
      +  }
      +
      +  if ('string' === typeof value || Array.isArray(value)) {
      +    return new MongooseBuffer(value, [this.path, doc]);
      +  }
      +
      +  throw new CastError('buffer', value);
      +};

      Parameters:


      SchemaBuffer#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Buffer.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    return this.cast(val).toObject();
      +  }
      +};

      Parameters:


    • schema/date.js

      SchemaDate(key, options)

      Date SchemaType constructor.

      show code
      function SchemaDate (key, options) {
      +  SchemaType.call(this, key, options);
      +};

      Parameters:

      Inherits:


      SchemaDate#checkRequired()

      Required validator for date

      show code
      SchemaDate.prototype.checkRequired = function (value) {
      +  return value instanceof Date;
      +};

      SchemaDate#cast(value)

      Casts to date

      show code
      SchemaDate.prototype.cast = function (value) {
      +  if (value === null || value === '')
      +    return null;
      +
      +  if (value instanceof Date)
      +    return value;
      +
      +  var date;
      +
      +  // support for timestamps
      +  if (value instanceof Number || 'number' == typeof value 
      +      || String(value) == Number(value))
      +    date = new Date(Number(value));
      +
      +  // support for date strings
      +  else if (value.toString)
      +    date = new Date(value.toString());
      +
      +  if (date.toString() != 'Invalid Date')
      +    return date;
      +
      +  throw new CastError('date', value);
      +};

      Parameters:


      SchemaDate#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaDate.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +
      +  if (2 !== arguments.length) {
      +    return this.cast($conditional);
      +  }
      +
      +  handler = this.$conditionalHandlers[$conditional];
      +
      +  if (!handler) {
      +    throw new Error("Can't use " + $conditional + " with Date.");
      +  }
      +
      +  return handler.call(this, val);
      +};

      Parameters:


    • schema/documentarray.js

      DocumentArray(key, schema, options)

      SubdocsArray SchemaType constructor

      show code
      function DocumentArray (key, schema, options) {
      +
      +  // compile an embedded document for this schema
      +  function EmbeddedDocument () {
      +    Subdocument.apply(this, arguments);
      +  }
      +
      +  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
      +  EmbeddedDocument.prototype._setSchema(schema);
      +  EmbeddedDocument.schema = schema;
      +
      +  // apply methods
      +  for (var i in schema.methods) {
      +    EmbeddedDocument.prototype[i] = schema.methods[i];
      +  }
      +
      +  // apply statics
      +  for (var i in schema.statics)
      +    EmbeddedDocument[i] = schema.statics[i];
      +
      +  EmbeddedDocument.options = options;
      +  this.schema = schema;
      +
      +  ArrayType.call(this, key, EmbeddedDocument, options);
      +
      +  this.schema = schema;
      +  var path = this.path;
      +  var fn = this.defaultValue;
      +
      +  this.default(function(){
      +    var arr = fn.call(this);
      +    if (!Array.isArray(arr)) arr = [arr];
      +    return new MongooseDocumentArray(arr, path, this);
      +  });
      +};

      Parameters:

      Inherits:


      DocumentArray#doValidate()

      Performs local validations first, then validations on each embedded doc

      show code
      DocumentArray.prototype.doValidate = function (array, fn, scope) {
      +  var self = this;
      +
      +  SchemaType.prototype.doValidate.call(this, array, function (err) {
      +    if (err) return fn(err);
      +
      +    var count = array && array.length
      +      , error;
      +
      +    if (!count) return fn();
      +
      +    // handle sparse arrays, do not use array.forEach which does not
      +    // iterate over sparse elements yet reports array.length including
      +    // them :(
      +
      +    for (var i = 0, len = count; i < len; ++i) {
      +      // sidestep sparse entries
      +      var doc = array[i];
      +      if (!doc) {
      +        --count || fn();
      +        continue;
      +      }
      +
      +      ;(function (i) {
      +        doc.validate(function (err) {
      +          if (err && !error) {
      +            // rewrite the key
      +            err.key = self.key + '.' + i + '.' + err.key;
      +            return fn(error = err);
      +          }
      +          --count || fn();
      +        });
      +      })(i);
      +    }
      +  }, scope);
      +};

      DocumentArray#cast(value, document)

      Casts contents

      show code
      DocumentArray.prototype.cast = function (value, doc, init, prev) {
      +  var selected
      +    , subdoc
      +    , i
      +
      +  if (!Array.isArray(value)) {
      +    return this.cast([value], doc, init, prev);
      +  }
      +
      +  if (!(value instanceof MongooseDocumentArray)) {
      +    value = new MongooseDocumentArray(value, this.path, doc);
      +  }
      +
      +  i = value.length;
      +
      +  while (i--) {
      +    if (!(value[i] instanceof Subdocument) && value[i]) {
      +      if (init) {
      +        selected || (selected = scopePaths(this, doc._selected, init));
      +        subdoc = new this.casterConstructor(null, value, true, selected);
      +        value[i] = subdoc.init(value[i]);
      +      } else {
      +        if (prev && (subdoc = prev.id(value[i]._id))) {
      +          // handle resetting doc with existing id but differing data
      +          // doc.array = [{ doc: 'val' }]
      +          subdoc.set(value[i]);
      +        } else {
      +          subdoc = new this.casterConstructor(value[i], value);
      +        }
      +
      +        // if set() is hooked it will have no return value
      +        // see gh-746
      +        value[i] = subdoc;
      +      }
      +    }
      +  }
      +
      +  return value;
      +}

      Parameters:


    • schema/mixed.js

      Mixed(path, options)

      Mixed SchemaType constructor.

      show code
      function Mixed (path, options) {
      +  // make sure empty array defaults are handled
      +  if (options &&
      +      options.default &&
      +      Array.isArray(options.default) &&
      +      0 === options.default.length) {
      +    options.default = Array;
      +  }
      +
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      Mixed#checkRequired()

      Required validator

      show code
      Mixed.prototype.checkRequired = function (val) {
      +  return true;
      +};

      Mixed#cast(value)

      Casts val for Mixed.

      show code
      Mixed.prototype.cast = function (val) {
      +  return val;
      +};

      Parameters:

      this is a no-op


      Mixed#castForQuery($cond, [val])

      Casts contents for queries.

      show code
      Mixed.prototype.castForQuery = function ($cond, val) {
      +  if (arguments.length === 2) return val;
      +  return $cond;
      +};

      Parameters:


    • schema/number.js

      SchemaNumber(key, options)

      Number SchemaType constructor.

      show code
      function SchemaNumber (key, options) {
      +  SchemaType.call(this, key, options, 'Number');
      +};

      Parameters:

      Inherits:


      SchemaNumber#checkRequired()

      Required validator for number

      show code
      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return typeof value == 'number' || value instanceof Number;
      +  }
      +};

      SchemaNumber#min(value, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.min = function (value, message) {
      +  if (this.minValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'min';
      +    });
      +  if (value != null)
      +    this.validators.push([function(v){
      +      return v === null || v >= value;
      +    }, 'min']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, min: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 9 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#max(maximum, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.max = function (value, message) {
      +  if (this.maxValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'max';
      +    });
      +  if (value != null)
      +    this.validators.push([this.maxValidator = function(v){
      +      return v === null || v <= value;
      +    }, 'max']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, max: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 11 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#cast(value, doc, init)

      Casts to number

      show code
      SchemaNumber.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (!isNaN(value)){
      +    if (null === value) return value;
      +    if ('' === value) return null;
      +    if ('string' == typeof value) value = Number(value);
      +    if (value instanceof Number) return value
      +    if ('number' == typeof value) return value;
      +    if (value.toString && !Array.isArray(value) &&
      +        value.toString() == Number(value)) {
      +      return new Number(value)
      +    }
      +  }
      +
      +  throw new CastError('number', value);
      +};

      Parameters:


      SchemaNumber#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Number.");
      +    return handler.call(this, val);
      +  } else {
      +    val = this.cast($conditional);
      +    return val == null ? val : val
      +  }
      +};

      Parameters:


    • schema/objectid.js

      ObjectId(key, options)

      ObjectId SchemaType constructor.

      show code
      function ObjectId (key, options) {
      +  SchemaType.call(this, key, options, 'ObjectID');
      +};

      Parameters:

      Inherits:


      ObjectId#checkRequired()

      Check required

      show code
      ObjectId.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return value instanceof oid;
      +  }
      +};

      ObjectId#cast(value, scope, init)

      Casts to ObjectId

      show code
      ObjectId.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (value === null) return value;
      +
      +  if (value instanceof oid)
      +    return value;
      +
      +  if (value._id && value._id instanceof oid)
      +    return value._id;
      +
      +  if (value.toString)
      +    return oid.fromString(value.toString());
      +
      +  throw new CastError('object id', value);
      +};

      Parameters:


      ObjectId#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      ObjectId.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with ObjectId.");
      +    return handler.call(this, val);
      +  } else {
      +    return this.cast($conditional);
      +  }
      +};

      Parameters:


      ObjectId#auto(turnOn)

      Adds an auto-generated ObjectId default if turnOn is true.

      show code
      ObjectId.prototype.auto = function (turnOn) {
      +  if (turnOn) {
      +    this.default(defaultId);
      +    this.set(resetId)
      +  }
      +};

      Parameters:

      • turnOn <Boolean> auto generated ObjectId defaults

    • schema/string.js

      SchemaString(key, options)

      String SchemaType constructor.

      show code
      function SchemaString (key, options) {
      +  this.enumValues = [];
      +  this.regExp = null;
      +  SchemaType.call(this, key, options, 'String');
      +};

      Parameters:

      Inherits:


      SchemaString#enum([args...])

      Adds enumeration values and a coinciding validator.

      show code
      SchemaString.prototype.enum = function () {
      +  var len = arguments.length;
      +  if (!len || undefined === arguments[0] || false === arguments[0]) {
      +    if (this.enumValidator){
      +      this.enumValidator = false;
      +      this.validators = this.validators.filter(function(v){
      +        return v[1] != 'enum';
      +      });
      +    }
      +    return;
      +  }
      +
      +  for (var i = 0; i < len; i++) {
      +    if (undefined !== arguments[i]) {
      +      this.enumValues.push(this.cast(arguments[i]));
      +    }
      +  }
      +
      +  if (!this.enumValidator) {
      +    var values = this.enumValues;
      +    this.enumValidator = function(v){
      +      return undefined === v || ~values.indexOf(v);
      +    };
      +    this.validators.push([this.enumValidator, 'enum']);
      +  }
      +};

      Parameters:

      • [args...] <String> enumeration values

      Example:

      + +
      var states = 'opening open closing closed'.split(' ')
      +var s = new Schema({ state: { type: String, enum: states })
      +var M = db.model('M', s)
      +var m = new M({ state: 'invalid' })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.state = 'open'
      +  m.save() // success
      +})

      SchemaString#lowercase()

      Adds a lowercase setter.

      show code
      SchemaString.prototype.lowercase = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.toLowerCase();
      +    return v;
      +  });
      +};

      Example:

      + +
      var s = new Schema({ email: { type: String, lowercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ email: 'SomeEmail@example.COM' });
      +console.log(m.email) // someemail@example.com
      +

      SchemaString#uppercase()

      Adds an uppercase setter.

      show code
      SchemaString.prototype.uppercase = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.toUpperCase();
      +    return v;
      +  });
      +};

      Example:

      + +
      var s = new Schema({ caps: { type: String, uppercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ caps: 'an example' });
      +console.log(m.caps) // AN EXAMPLE

      SchemaString#trim()

      Adds a trim setter.

      show code
      SchemaString.prototype.trim = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.trim();
      +    return v;
      +  });
      +};

      The string value will be trimmed when set.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, trim: true }})
      +var M = db.model('M', s)
      +var string = ' some name '
      +console.log(string.length) // 11
      +var m = new M({ name: string })
      +console.log(m.name.length) // 9

      SchemaString#match(regExp)

      Sets a regexp validator.

      show code
      SchemaString.prototype.match = function match (regExp) {
      +  this.validators.push([function(v){
      +    return null != v && '' !== v
      +      ? regExp.test(v)
      +      : true
      +  }, 'regexp']);
      +};

      Parameters:

      • regExp <RegExp> regular expression to test against

      Any value that does not pass regExp.test(val) will fail validation.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, match: /^a/ }})
      +var M = db.model('M', s)
      +var m = new M({ name: 'invalid' })
      +m.validate(function (err) {
      +  console.error(err) // validation error
      +  m.name = 'apples'
      +  m.validate(function (err) {
      +    assert.ok(err) // success
      +  })
      +})

      SchemaString#checkRequired(value)

      Check required

      show code
      SchemaString.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return (value instanceof String || typeof value == 'string') && value.length;
      +  }
      +};

      Parameters:


      SchemaString#cast()

      Casts to String

      show code
      SchemaString.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +  if (value === null) return value;
      +  if ('undefined' !== typeof value && value.toString) return value.toString();
      +  throw new CastError('string', value);
      +};

      SchemaString#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      SchemaString.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with String.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    if (val instanceof RegExp) return val;
      +    return this.cast(val);
      +  }
      +};

      Parameters:


    • schema.js

      Schema(definition)

      Schema constructor.

      show code
      function Schema (obj, options) {
      +  if (!(this instanceof Schema))
      +    return new Schema(obj, options);
      +
      +  this.paths = {};
      +  this.subpaths = {};
      +  this.virtuals = {};
      +  this.nested = {};
      +  this.inherits = {};
      +  this.callQueue = [];
      +  this._indexes = [];
      +  this.methods = {};
      +  this.statics = {};
      +  this.tree = {};
      +  this._requiredpaths = undefined;
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // build paths
      +  if (obj) {
      +    this.add(obj);
      +  }
      +
      +  // ensure the documents get an auto _id unless disabled
      +  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
      +  if (auto_id) {
      +    this.add({ _id: {type: Schema.ObjectId, auto: true} });
      +  }
      +
      +  // ensure the documents receive an id getter unless disabled
      +  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
      +  if (autoid) {
      +    this.virtual('id').get(idGetter);
      +  }
      +
      +  // versioning not directly added to schema b/c we only want
      +  // it in the top level document, not embedded ones.
      +};

      Parameters:

      Events:

      • init: Emitted after the schema is compiled into a Model.

      Example:

      + +
      var child = new Schema({ name: String });
      +var schema = new Schema({ name: String, age: Number, children: [child] });
      +var Tree = mongoose.model('Tree', schema);
      +
      +// setting schema options
      +new Schema({ name: String }, { _id: false, autoIndex: false })
      + +

      Options:

      + +
        +
      • autoIndex: bool - defaults to true
      • +
      • capped: bool - defaults to false
      • +
      • collection: string - no default
      • +
      • id: bool - defaults to true
      • +
      • _id: bool - defaults to true
      • +
      • read: string
      • +
      • safe: bool - defaults to true.
      • +
      • shardKey: bool - defaults to null
      • +
      • strict: bool - defaults to true
      • +
      • toJSON - object - no default
      • +
      • toObject - object - no default
      • +
      • versionKey: bool - defaults to "__v"
      • +
      • minimize: bool - controls document#toObject behavior when called manually - defaults to true
      • +
      + +

      Note:

      + +

      When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


      Schema#defaultOptions(options)

      Returns default options for this schema, merged with options.

      show code
      Schema.prototype.defaultOptions = function (options) {
      +  options = utils.options({
      +      safe: true
      +    , strict: true
      +    , capped: false // { size, max, autoIndexId }
      +    , versionKey: '__v'
      +    , minimize: true
      +    , autoIndex: true
      +    , shardKey: null
      +    , read: null
      +    // the following are only applied at construction time
      +    , noId: false // deprecated, use { _id: false }
      +    , _id: true
      +    , noVirtualId: false // deprecated, use { id: false }
      +    , id: true
      +  }, options);
      +
      +  if (options.read)
      +    options.read = utils.readPref(options.read);
      +
      +  return options;
      +}

      Parameters:

      Returns:


      Schema#add(obj, prefix)

      Adds key path / schema type pairs to this schema.

      show code
      Schema.prototype.add = function add (obj, prefix) {
      +  prefix = prefix || '';
      +  for (var i in obj) {
      +    if (null == obj[i]) {
      +      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
      +    }
      +
      +    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
      +      if (Object.keys(obj[i]).length) {
      +        // nested object { last: { name: String }}
      +        this.nested[prefix + i] = true;
      +        this.add(obj[i], prefix + i + '.');
      +      } else {
      +        this.path(prefix + i, obj[i]); // mixed type
      +      }
      +    } else {
      +      this.path(prefix + i, obj[i]);
      +    }
      +  }
      +};

      Parameters:

      Example:

      + +
      var ToySchema = new Schema;
      +ToySchema.add({ name: 'string', color: 'string', price: 'number' });

      Schema#path(path, constructor)

      Gets/sets schema paths.

      show code
      Schema.prototype.path = function (path, obj) {
      +  if (obj == undefined) {
      +    if (this.paths[path]) return this.paths[path];
      +    if (this.subpaths[path]) return this.subpaths[path];
      +
      +    // subpaths?
      +    return /\.\d+\.?$/.test(path)
      +      ? getPositionalPath(this, path)
      +      : undefined;
      +  }
      +
      +  // some path names conflict with document methods
      +  if (reserved[path]) {
      +    throw new Error("`" + path + "` may not be used as a schema pathname");
      +  }
      +
      +  // update the tree
      +  var subpaths = path.split(/\./)
      +    , last = subpaths.pop()
      +    , branch = this.tree;
      +
      +  subpaths.forEach(function(sub, i) {
      +    if (!branch[sub]) branch[sub] = {};
      +    if ('object' != typeof branch[sub]) {
      +      var msg = 'Cannot set nested path `' + path + '`. '
      +              + 'Parent path `'
      +              + subpaths.slice(0, i).concat([sub]).join('.')
      +              + '` already set to type ' + branch[sub].name
      +              + '.';
      +      throw new Error(msg);
      +    }
      +    branch = branch[sub];
      +  });
      +
      +  branch[last] = utils.clone(obj);
      +
      +  this.paths[path] = Schema.interpretAsType(path, obj);
      +  return this;
      +};

      Parameters:

      Sets a path (if arity 2)
      Gets a path (if arity 1)

      + +

      Example

      + +
      schema.path('name') // returns a SchemaType
      +schema.path('name', Number) // changes the schemaType of `name` to Number

      Schema#eachPath(fn)

      Iterates the schemas paths similar to Array#forEach.

      show code
      Schema.prototype.eachPath = function (fn) {
      +  var keys = Object.keys(this.paths)
      +    , len = keys.length;
      +
      +  for (var i = 0; i < len; ++i) {
      +    fn(keys[i], this.paths[keys[i]]);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      The callback is passed the pathname and schemaType as arguments on each iteration.


      Schema#requiredPaths()

      Returns an Array of path strings that are required by this schema.

      show code
      Schema.prototype.requiredPaths = function requiredPaths () {
      +  if (this._requiredpaths) return this._requiredpaths;
      +
      +  var paths = Object.keys(this.paths)
      +    , i = paths.length
      +    , ret = [];
      +
      +  while (i--) {
      +    var path = paths[i];
      +    if (this.paths[path].isRequired) ret.push(path);
      +  }
      +
      +  return this._requiredpaths = ret;
      +}

      Returns:


      Schema#pathType(path)

      Returns the pathType of path for this schema.

      show code
      Schema.prototype.pathType = function (path) {
      +  if (path in this.paths) return 'real';
      +  if (path in this.virtuals) return 'virtual';
      +  if (path in this.nested) return 'nested';
      +  if (path in this.subpaths) return 'real';
      +
      +  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
      +    return 'real';
      +  } else {
      +    return 'adhocOrUndefined'
      +  }
      +};

      Parameters:

      Returns:

      Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


      Schema#queue(name, args)

      Adds a method call to the queue.

      show code
      Schema.prototype.queue = function(name, args){
      +  this.callQueue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the document method to call later
      • args <Array> arguments to pass to the method

      Schema#pre(method, callback)

      Defines a pre hook for the document.

      show code
      Schema.prototype.pre = function(){
      +  return this.queue('pre', arguments);
      +};

      Parameters:

      Example

      + +
      var toySchema = new Schema(..);
      +
      +toySchema.pre('save', function (next) {
      +  if (!this.created) this.created = new Date;
      +  next();
      +})
      +
      +toySchema.pre('validate', function (next) {
      +  if (this.name != 'Woody') this.name = 'Woody';
      +  next();
      +})

      Schema#post(method, fn)

      Defines a post hook for the document.

      show code
      Schema.prototype.post = function(method, fn){
      +  return this.queue('on', arguments);
      +};

      Parameters:

      Post hooks fire on the event emitted from document instances of Models compiled from this schema.

      + +
      var schema = new Schema(..);
      +schema.post('save', function () {
      +  console.log('this fired after a document was saved');
      +});
      +
      +var Model = mongoose.model('Model', schema);
      +
      +var m = new Model(..);
      +m.save(function (err) {
      +  console.log('this fires after the `post` hook');
      +});

      Schema#plugin(plugin, opts)

      Registers a plugin for this schema.

      show code
      Schema.prototype.plugin = function (fn, opts) {
      +  fn(this, opts);
      +  return this;
      +};

      Parameters:


      Schema#method(method, [fn])

      Adds an instance method to documents constructed from Models compiled from this schema.

      show code
      Schema.prototype.method = function (name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.methods[i] = name[i];
      +  else
      +    this.methods[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = kittySchema = new Schema(..);
      +
      +schema.methods.meow = function () {
      +  console.log('meeeeeoooooooooooow');
      +})
      +
      +var Kitty = mongoose.model('Kitty', schema);
      +
      +var fizz = new Kitty;
      +fizz.meow(); // meeeeeooooooooooooow
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      + +
      schema.method({
      +    purr: function () {}
      +  , scratch: function () {}
      +});
      +
      +// later
      +fizz.purr();
      +fizz.scratch();

      Schema#static(name, fn)

      Adds static "class" methods to Models compiled from this schema.

      show code
      Schema.prototype.static = function(name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.statics[i] = name[i];
      +  else
      +    this.statics[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = new Schema(..);
      +schema.static('findByName', function (name, callback) {
      +  return this.find({ name: name }, callback);
      +});
      +
      +var Drink = mongoose.model('Drink', schema);
      +Drink.findByName('sanpellegrino', function (err, drinks) {
      +  //
      +});
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


      Schema#index(fields, [options])

      Defines an index (most likely compound) for this schema.

      show code
      Schema.prototype.index = function (fields, options) {
      +  options || (options = {});
      +
      +  if (options.expires)
      +    utils.expires(options);
      +
      +  this._indexes.push([fields, options]);
      +  return this;
      +};

      Parameters:

      Example

      + +
      schema.index({ first: 1, last: -1 })

      Schema#set(key, [value])

      Sets/gets a schema option.

      show code
      Schema.prototype.set = function (key, value, tags) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +
      +  this.options[key] = 'read' == key
      +    ? utils.readPref(value, tags)
      +    : value;
      +
      +  return this;
      +};

      Parameters:

      • key <String> option name
      • [value] <Object> if not passed, the current option value is returned

      Schema#indexes()

      Compiles indexes from fields and schema-level indexes

      show code
      Schema.prototype.indexes = function () {
      +  var indexes = []
      +    , seenSchemas = [];
      +
      +  collectIndexes(this);
      +
      +  return indexes;
      +
      +  function collectIndexes (schema, prefix) {
      +    if (~seenSchemas.indexOf(schema)) return;
      +    seenSchemas.push(schema);
      +
      +    var index;
      +    var paths = schema.paths;
      +    prefix = prefix || '';
      +
      +    for (var i in paths) {
      +      if (paths[i]) {
      +        if (paths[i] instanceof Types.DocumentArray) {
      +          collectIndexes(paths[i].schema, i + '.');
      +        } else {
      +          index = paths[i]._index;
      +
      +          if (index !== false && index !== null){
      +            var field = {};
      +            field[prefix + i] = '2d' === index ? index : 1;
      +            var options = 'Object' === index.constructor.name ? index : {};
      +            if (!('background' in options)) options.background = true;
      +            indexes.push([field, options]);
      +          }
      +        }
      +      }
      +    }
      +
      +    if (prefix) {
      +      fixSubIndexPaths(schema, prefix);
      +    } else {
      +      schema._indexes.forEach(function (index) {
      +        if (!('background' in index[1])) index[1].background = true;
      +      });
      +      indexes = indexes.concat(schema._indexes);
      +    }
      +  }

      Schema#virtual(name, [options])

      Creates a virtual type with the given name.

      show code
      Schema.prototype.virtual = function (name, options) {
      +  var virtuals = this.virtuals;
      +  var parts = name.split('.');
      +  return virtuals[name] = parts.reduce(function (mem, part, i) {
      +    mem[part] || (mem[part] = (i === parts.length-1)
      +                            ? new VirtualType(options, name)
      +                            : {});
      +    return mem[part];
      +  }, this.tree);
      +};

      Parameters:

      Returns:


      Schema#virtualpath(name)

      Returns the virtual type with the given name.

      show code
      Schema.prototype.virtualpath = function (name) {
      +  return this.virtuals[name];
      +};

      Parameters:

      Returns:


      Schema#namedScope()

      These still haven't been fixed. Once they're working we'll make them public again.

      show code
      Schema.prototype.namedScope = function (name, fn) {
      +  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
      +    , newScope = Object.create(namedScopes)
      +    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
      +  allScopes[name] = newScope;
      +  newScope.name = name;
      +  newScope.block = fn;
      +  newScope.query = new Query();
      +  newScope.decorate(namedScopes, {
      +    block0: function (block) {
      +      return function () {
      +        block.call(this.query);
      +        return this;
      +      };
      +    },
      +    blockN: function (block) {
      +      return function () {
      +        block.apply(this.query, arguments);
      +        return this;
      +      };
      +    },
      +    basic: function (query) {
      +      return function () {
      +        this.query.find(query);
      +        return this;
      +      };
      +    }
      +  });
      +  return newScope;
      +};

      Schema.reserved

      Reserved document keys.

      show code
      Schema.reserved = Object.create(null);
      +var reserved = Schema.reserved;
      +reserved.on =
      +reserved.db =
      +reserved.init =
      +reserved.isNew =
      +reserved.errors =
      +reserved.schema =
      +reserved.options =
      +reserved.modelName =
      +reserved.collection = 1;

      Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      + +
      on, db, init, isNew, errors, schema, options, modelName, collection
      + +

      NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

      + +
      var schema = new Schema(..);
      + schema.methods.init = function () {} // potentially breaking

      Schema.interpretAsType(path, obj)

      Converts type arguments into Mongoose Types.

      show code
      Schema.interpretAsType = function (path, obj) {
      +  if (obj.constructor.name != 'Object')
      +    obj = { type: obj };
      +
      +  // Get the type making sure to allow keys named "type"
      +  // and default to mixed if not specified.
      +  // { type: { type: String, default: 'freshcut' } }
      +  var type = obj.type && !obj.type.type
      +    ? obj.type
      +    : {};
      +
      +  if ('Object' == type.constructor.name || 'mixed' == type) {
      +    return new Types.Mixed(path, obj);
      +  }
      +
      +  if (Array.isArray(type) || Array == type || 'array' == type) {
      +    // if it was specified through { type } look for `cast`
      +    var cast = (Array == type || 'array' == type)
      +      ? obj.cast
      +      : type[0];
      +
      +    if (cast instanceof Schema) {
      +      return new Types.DocumentArray(path, cast, obj);
      +    }
      +
      +    if ('string' == typeof cast) {
      +      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
      +    } else if (cast && (!cast.type || cast.type.type)
      +                    && 'Object' == cast.constructor.name
      +                    && Object.keys(cast).length) {
      +      return new Types.DocumentArray(path, new Schema(cast), obj);
      +    }
      +
      +    return new Types.Array(path, cast || Types.Mixed, obj);
      +  }
      +
      +  var name = 'string' == typeof type
      +    ? type
      +    : type.name;
      +
      +  if (name) {
      +    name = name.charAt(0).toUpperCase() + name.substring(1);
      +  }
      +
      +  if (undefined == Types[name]) {
      +    throw new TypeError('Undefined type at `' + path +
      +        '`
      +  Did you try nesting Schemas? ' +
      +        'You can only nest using refs or arrays.');
      +  }
      +
      +  return new Types[name](path, obj);
      +};

      Parameters:


      Schema.Types

      The various Mongoose Schema Types.

      show code
      Schema.Types = require('./schema/index');

      Example:

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var ObjectId = mongoose.Schema.Types.ObjectId;
      + +

      Types:

      + +
        +
      • String
      • +
      • Number
      • +
      • Boolean | Bool
      • +
      • Array
      • +
      • Buffer
      • +
      • Date
      • +
      • ObjectId | Oid
      • +
      • Mixed
      • +
      + +

      Using this exposed access to the Mixed SchemaType, we can use them in our schema.

      + +
      var Mixed = mongoose.Schema.Types.Mixed;
      +new mongoose.Schema({ _user: Mixed })

      Schema#tree

      Schema as a tree

      + +

      Example:

      + +
      {
      +    '_id'     : ObjectId
      +  , 'nested'  : {
      +        'key' : String
      +    }
      +}

      Schema#paths

      Schema as flat paths

      + +

      Example:

      + +
      {
      +    '_id'        : SchemaType,
      +  , 'nested.key' : SchemaType,
      +}

    • schemadefault.js

      exports#system.profile

      Default model for querying the system.profiles collection.


    • schematype.js

      SchemaType(path, [options], [instance])

      SchemaType constructor

      show code
      function SchemaType (path, options, instance) {
      +  this.path = path;
      +  this.instance = instance;
      +  this.validators = [];
      +  this.setters = [];
      +  this.getters = [];
      +  this.options = options;
      +  this._index = null;
      +  this.selected;
      +
      +  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
      +    // { unique: true, index: true }
      +    if ('index' == i && this._index) continue;
      +
      +    var opts = Array.isArray(options[i])
      +      ? options[i]
      +      : [options[i]];
      +
      +    this[i].apply(this, opts);
      +  }
      +};

      Parameters:


      SchemaType#default(val)

      Sets a default value for this SchemaType.

      show code
      SchemaType.prototype.default = function (val) {
      +  if (1 === arguments.length) {
      +    this.defaultValue = typeof val === 'function'
      +      ? val
      +      : this.cast(val);
      +    return this;
      +  } else if (arguments.length > 1) {
      +    this.defaultValue = utils.args(arguments);
      +  }
      +  return this.defaultValue;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var schema = new Schema({ n: { type: Number, default: 10 })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.n) // 10
      + +

      Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

      + +

      Example:

      + +
      // values are cast:
      +var schema = new Schema({ aNumber: Number, default: "4.815162342" })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.aNumber) // 4.815162342
      +
      +// default unique objects for Mixed types:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default(function () {
      +  return {};
      +});
      +
      +// if we don't use a function to return object literals for Mixed defaults,
      +// each document will receive a reference to the same object literal creating
      +// a "shared" object instance:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default({});
      +var M = db.model('M', schema);
      +var m1 = new M;
      +m1.mixed.added = 1;
      +console.log(m1.mixed); // { added: 1 }
      +var m2 = new M;
      +console.log(m2.mixed); // { added: 1 }

      SchemaType#index(options)

      Declares the index options for this schematype.

      show code
      SchemaType.prototype.index = function (options) {
      +  this._index = options;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var s = new Schema({ name: { type: String, index: true })
      +var s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
      +Schema.path('my.path').index(true);
      +Schema.path('my.date').index({ expires: 60 });
      +Schema.path('my.path').index({ unique: true, sparse: true });
      + +

      NOTE:

      + +

      Indexes are created in the background by default. Specify background: false to override.

      + +

      Direction doesn't matter for single key indexes


      SchemaType#unique(bool)

      Declares an unique index.

      show code
      SchemaType.prototype.unique = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.unique = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, unique: true })
      +Schema.path('name').index({ unique: true });

      SchemaType#sparse(bool)

      Declares a sparse index.

      show code
      SchemaType.prototype.sparse = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.sparse = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Examples:

      + +
      var s = new Schema({ name: { type: String, sparse: true })
      +Schema.path('name').index({ sparse: true });

      SchemaType#expires(when)

      Declares a TTL index (rounded to the nearest second) for Date types only.

      show code
      SchemaType.prototype.expires = function (when) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.expires = when;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
      This index type is only compatible with Date types.

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
      + +

      expires utilizes the ms module from guille allowing us to use a friendlier syntax:

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({ createdAt: { type: Date, expires: '24h' }});
      +
      +// expire in 1.5 hours
      +new Schema({ createdAt: { type: Date, expires: '1.5h' }});
      +
      +// expire in 7 days
      +var schema = new Schema({ createdAt: Date });
      +schema.path('createdAt').expires('7d');

      SchemaType#set(fn)

      Adds a setter to this schematype.

      show code
      SchemaType.prototype.set = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A setter must be a function.');
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function capitalize (val) {
      +  if ('string' != typeof val) val = '';
      +  return val.charAt(0).toUpperCase() + val.substring(1);
      +}
      +
      +// defining within the schema
      +var s = new Schema({ name: { type: String, set: capitalize }})
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ name: String })
      +s.path('name').set(capitalize)
      + +

      Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

      + +

      You can set up email lower case normalization easily via a Mongoose setter.

      + +
      function toLower (v) {
      +  return v.toLowerCase();
      +}
      +
      +var UserSchema = new Schema({
      +  email: { type: String, set: toLower }
      +})
      +
      +var User = db.model('User', UserSchema)
      +
      +var user = new User({email: 'AVENUE@Q.COM'})
      +console.log(user.email); // 'avenue@q.com'
      +
      +// or
      +var user = new User
      +user.email = 'Avenue@Q.com'
      +console.log(user.email) // 'avenue@q.com'
      +
      + +

      As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

      + +
      new Schema({ email: { type: String, lowercase: true }})

      SchemaType#get(fn)

      Adds a getter to this schematype.

      show code
      SchemaType.prototype.get = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A getter must be a function.');
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function dob (val) {
      +  if (!val) return val;
      +  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      +}
      +
      +// defining within the schema
      +var s = new Schema({ born: { type: Date, get: dob })
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ born: Date })
      +s.path('born').get(dob)
      + +

      Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

      + +

      Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

      + +
      function obfuscate (cc) {
      +  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
      +}
      +
      +var AccountSchema = new Schema({
      +  creditCardNumber: { type: String, get: obfuscate }
      +});
      +
      +var Account = db.model('Account', AccountSchema);
      +
      +Account.findById(id, function (err, found) {
      +  console.log(found.creditCardNumber); // '****-****-****-1234'
      +});

      SchemaType#validate(obj, [error])

      Adds validator(s) for this document path.

      show code
      SchemaType.prototype.validate = function (obj, error) {
      +  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
      +    this.validators.push([obj, error]);
      +    return this;
      +  }
      +
      +  var i = arguments.length
      +    , arg
      +
      +  while (i--) {
      +    arg = arguments[i];
      +    if (!(arg && 'Object' == arg.constructor.name)) {
      +      var msg = 'Invalid validator. Received (' + typeof arg + ') '
      +        + arg
      +        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
      +
      +      throw new Error(msg);
      +    }
      +    this.validate(arg.validator, arg.msg);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Validators must return Boolean. Returning false is interpreted as validation failure.

      + +

      Examples:

      + +
      function validator () { ... }
      +
      +var single = [validator, 'failed']
      +new Schema({ name: { type: String, validate: single }});
      +
      +var many = [
      +    { validator: validator, msg: 'uh oh' }
      +  , { validator: fn, msg: 'failed' }
      +]
      +new Schema({ name: { type: String, validate: many }});
      +
      +// or utilizing SchemaType methods directly:
      +
      +var schema = new Schema({ name: 'string' });
      +schema.path('name').validate(validator, 'validation failed');
      + +

      Asynchronous validation:

      + +

      Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

      + +
      schema.path('name').validate(function (value, respond) {
      +  doStuff(value, function () {
      +    ...
      +    respond(false); // validation failed
      +  })
      + }, 'my error type');
      + +

      Validation occurs pre('save') or whenever you manually execute document#validate.

      + +

      If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

      + +
      var conn = mongoose.createConnection(..);
      +conn.on('error', handleError);
      +
      +var Product = conn.model('Product', yourSchema);
      +var dvd = new Product(..);
      +dvd.save(); // emits error on the `conn` above
      + +

      If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

      + +
      // registering an error listener on the Model lets us handle errors more locally
      +Product.on('error', handleError);

      SchemaType#required(required)

      Adds a required validator to this schematype.

      show code
      SchemaType.prototype.required = function (required) {
      +  var self = this;
      +
      +  function __checkRequired (v) {
      +    // in here, `this` refers to the validating document.
      +    // no validation when this path wasn't selected in the query.
      +    if ('isSelected' in this &&
      +        !this.isSelected(self.path) &&
      +        !this.isModified(self.path)) return true;
      +    return self.checkRequired(v);
      +  }
      +
      +  if (false === required) {
      +    this.isRequired = false;
      +    this.validators = this.validators.filter(function (v) {
      +      return v[0].name !== '__checkRequired';
      +    });
      +  } else {
      +    this.isRequired = true;
      +    this.validators.push([__checkRequired, 'required']);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • required <Boolean> enable/disable the validator

      Returns:

      Example:

      + +
      var s = new Schema({ born: { type: Date, required: true })
      +// or
      +Schema.path('name').required(true);

      SchemaType#getDefault(scope, init)

      Gets the default value

      show code
      SchemaType.prototype.getDefault = function (scope, init) {
      +  var ret = 'function' === typeof this.defaultValue
      +    ? this.defaultValue.call(scope)
      +    : this.defaultValue;
      +
      +  if (null !== ret && undefined !== ret) {
      +    return this.cast(ret, scope, init);
      +  } else {
      +    return ret;
      +  }
      +};

      Parameters:

      • scope <Object> the scope which callback are executed
      • init <Boolean>

      SchemaType#applySetters(value, scope, init)

      Applies setters

      show code
      SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  var v = value
      +    , setters = this.setters
      +    , len = setters.length
      +
      +  if (!len) {
      +    if (null === v || undefined === v) return v;
      +    return init
      +      ? v // if we just initialized we dont recast
      +      : this.cast(v, scope, init, priorVal)
      +  }
      +
      +  while (len--) {
      +    v = setters[len].call(scope, v, this);
      +  }
      +
      +  if (null === v || undefined === v) return v;
      +
      +  // do not cast until all setters are applied #665
      +  v = this.cast(v, scope, init, priorVal);
      +
      +  return v;
      +};

      Parameters:


      SchemaType#applyGetters(value, scope)

      Applies getters to a value

      show code
      SchemaType.prototype.applyGetters = function (value, scope) {
      +  if (SchemaType._isRef(this, value, true)) return value;
      +
      +  var v = value
      +    , getters = this.getters
      +    , len = getters.length;
      +
      +  if (!len) {
      +    return v;
      +  }
      +
      +  while (len--) {
      +    v = getters[len].call(scope, v, this);
      +  }
      +
      +  return v;
      +};

      Parameters:


      SchemaType#select(val)

      Sets default select() behavior for this path.

      show code
      SchemaType.prototype.select = function select (val) {
      +  this.selected = !! val;
      +}

      Parameters:

      Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

      + +

      Example:

      + +
      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      +T.find(..); // field x will always be selected ..
      +// .. unless overridden;
      +T.find().select('-x').exec(callback);

      SchemaType#doValidate(value, callback, scope)

      Performs a validation of value using the validators declared for this SchemaType.

      show code
      SchemaType.prototype.doValidate = function (value, fn, scope) {
      +  var err = false
      +    , path = this.path
      +    , count = this.validators.length;
      +
      +  if (!count) return fn(null);
      +
      +  function validate (val, msg) {
      +    if (err) return;
      +    if (val === undefined || val) {
      +      --count || fn(null);
      +    } else {
      +      fn(err = new ValidatorError(path, msg));
      +    }
      +  }
      +
      +  this.validators.forEach(function (v) {
      +    var validator = v[0]
      +      , message   = v[1];
      +
      +    if (validator instanceof RegExp) {
      +      validate(validator.test(value), message);
      +    } else if ('function' === typeof validator) {
      +      if (2 === validator.length) {
      +        validator.call(scope, value, function (val) {
      +          validate(val, message);
      +        });
      +      } else {
      +        validate(validator.call(scope, value), message);
      +      }
      +    }
      +  });
      +};

      Parameters:


      SchemaType._isRef(self, value, init)

      Determines if value is a valid Reference.

      show code
      SchemaType._isRef = function (self, value, init) {
      +  if (init && self.options && self.options.ref) {
      +    if (null == value) return true;
      +    if (value._id && value._id.constructor.name === self.instance) return true;
      +  }
      +
      +  return false;
      +}

      Parameters:

      Returns:


    • types/array.js

      MongooseArray(values, path, doc)

      Mongoose Array constructor.

      show code
      function MongooseArray (values, path, doc) {
      +  var arr = [];
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:

      NOTE:

      + +

      Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


      MongooseArray#_cast(value)

      Casts a member based on this arrays schema.

      show code
      MongooseArray.prototype._cast = function (value) {
      +  var cast = this._schema.caster.cast
      +    , doc = this._parent;
      +
      +  return cast.call(null, value, doc);
      +};

      Parameters:

      Returns:

      • <value> the casted value

      MongooseArray#_markModified(embeddedDoc, embeddedPath)

      Marks this array as modified.

      show code
      MongooseArray.prototype._markModified = function (elem, embeddedPath) {
      +  var parent = this._parent
      +    , dirtyPath;
      +
      +  if (parent) {
      +    dirtyPath = this._path;
      +
      +    if (arguments.length) {
      +      if (null != embeddedPath) {
      +        // an embedded doc bubbled up the change
      +        dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
      +      } else {
      +        // directly set an index
      +        dirtyPath = dirtyPath + '.' + elem;
      +      }
      +
      +    }
      +    parent.markModified(dirtyPath);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
      • embeddedPath <String> the path which changed in the embeddedDoc

      If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


      MongooseArray#_registerAtomic(op, val)

      Register an atomic operation with the parent.

      show code
      MongooseArray.prototype._registerAtomic = function (op, val) {
      +  if ('$set' == op) {
      +    // $set takes precedence over all other ops.
      +    // mark entire array modified.
      +    this._atomics = { $set: val };
      +    return this;
      +  }
      +
      +  var atomics = this._atomics;
      +
      +  // reset pop/shift after save
      +  if ('$pop' == op && !('$pop' in atomics)) {
      +    var self = this;
      +    this._parent.once('save', function () {
      +      self._popped = self._shifted = null;
      +    });
      +  }
      +
      +  // check for impossible $atomic combos (Mongo denies more than one
      +  // $atomic op on a single path
      +  if (this._atomics.$set ||
      +      Object.keys(atomics).length && !(op in atomics)) {
      +    // a different op was previously registered.
      +    // save the entire thing.
      +    this._atomics = { $set: this };
      +    return this;
      +  }
      +
      +  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
      +    atomics[op] || (atomics[op] = []);
      +    atomics[op] = atomics[op].concat(val);
      +  } else if (op === '$pullDocs') {
      +    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
      +      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
      +    selector['$in'] = selector['$in'].concat(val);
      +  } else {
      +    atomics[op] = val;
      +  }
      +
      +  return this;
      +};

      Parameters:


      MongooseArray#hasAtomics()

      Returns the number of pending atomic operations to send to the db for this array.

      show code
      MongooseArray.prototype.hasAtomics = function hasAtomics () {
      +  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
      +    return 0;
      +  }
      +
      +  return Object.keys(this._atomics).length;
      +}

      Returns:


      MongooseArray#push([args...])

      Wraps Array#push with proper change tracking.

      show code
      MongooseArray.prototype.push = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +
      +  // $pushAll might be fibbed (could be $push). But it makes it easier to
      +  // handle what could have been $push, $pushAll combos
      +  this._registerAtomic('$pushAll', values);
      +  this._markModified();
      +  return ret;
      +};

      Parameters:


      MongooseArray#nonAtomicPush([args...])

      Pushes items to the array non-atomically.

      show code
      MongooseArray.prototype.nonAtomicPush = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +};

      Parameters:

      • [args...] <any>

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$pop()

      Pops the array atomically at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var popped = doc.array.$pop();
      + console.log(popped); // 3
      + console.log(doc.array); // [1,2]
      +
      + // no affect
      + popped = doc.array.$pop();
      + console.log(doc.array); // [1,2]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $pop works again
      +   popped = doc.array.$pop();
      +   console.log(popped); // 2
      +   console.log(doc.array); // [1]
      + })

      MongooseArray#pop()

      Wraps Array#pop with proper change tracking.

      show code
      MongooseArray.prototype.pop = function () {
      +  var ret = [].pop.call(this);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +};

      Note:

      + +

      marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$shift()

      Atomically shifts the array at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var shifted = doc.array.$shift();
      + console.log(shifted); // 1
      + console.log(doc.array); // [2,3]
      +
      + // no affect
      + shifted = doc.array.$shift();
      + console.log(doc.array); // [2,3]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $shift works again
      +   shifted = doc.array.$shift();
      +   console.log(shifted ); // 2
      +   console.log(doc.array); // [3]
      + })

      MongooseArray#shift()

      Wraps Array#shift with proper change tracking.

      show code
      MongooseArray.prototype.shift = function () {
      +  var ret = [].shift.call(this);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +};

      Example:

      + +
      doc.array = [2,3];
      +var res = doc.array.shift();
      +console.log(res) // 2
      +console.log(doc.array) // [3]
      + +

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#remove([args...])

      Removes items from an array atomically

      show code
      MongooseArray.prototype.remove = function () {
      +  var args = [].map.call(arguments, this._cast, this);
      +  if (args.length == 1)
      +    this.pull(args[0]);
      +  else
      +    this.pull.apply(this, args);
      +  return args;
      +};

      Parameters:

      • [args...] <Object> values to remove

      Examples:

      + +
      doc.array.remove(ObjectId)
      +doc.array.remove('tag 1', 'tag 2')

      MongooseArray#pull([args...])

      Pulls items from the array atomically.

      show code
      MongooseArray.prototype.pull = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , cur = this._parent.get(this._path)
      +    , i = cur.length
      +    , mem;
      +
      +  while (i--) {
      +    mem = cur[i];
      +    if (mem instanceof EmbeddedDocument) {
      +      if (values.some(function (v) { return v.equals(mem); } )) {
      +        [].splice.call(cur, i, 1);
      +      }
      +    } else if (~cur.indexOf.call(values, mem)) {
      +      [].splice.call(cur, i, 1);
      +    }
      +  }
      +
      +  if (values[0] instanceof EmbeddedDocument) {
      +    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
      +  } else {
      +    this._registerAtomic('$pullAll', values);
      +  }
      +
      +  this._markModified();
      +  return this;
      +};

      Parameters:

      • [args...] <any>

      MongooseArray#splice()

      Wraps Array#splice with proper change tracking and casting.

      show code
      MongooseArray.prototype.splice = function splice () {
      +  var ret, vals, i;
      +
      +  if (arguments.length) {
      +    vals = [];
      +    for (i = 0; i < arguments.length; ++i) {
      +      vals[i] = i < 2
      +        ? arguments[i]
      +        : this._cast(arguments[i]);
      +    }
      +    ret = [].splice.apply(this, vals);
      +    this._registerAtomic('$set', this);
      +    this._markModified();
      +  }
      +
      +  return ret;
      +}

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#unshift()

      Wraps Array#unshift with proper change tracking.

      show code
      MongooseArray.prototype.unshift = function () {
      +  var values = [].map.call(arguments, this._cast, this);
      +  [].unshift.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return this.length;
      +};

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#sort()

      Wraps Array#sort with proper change tracking.

      show code
      MongooseArray.prototype.sort = function () {
      +  var ret = [].sort.apply(this, arguments);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +}

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#addToSet([args...])

      Adds values to the array if not already present.

      show code
      MongooseArray.prototype.addToSet = function addToSet () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , added = []
      +    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
      +             values[0] instanceof Date ? 'date' :
      +             '';
      +
      +  values.forEach(function (v) {
      +    var found;
      +    switch (type) {
      +      case 'doc':
      +        found = this.some(function(doc){ return doc.equals(v) });
      +        break;
      +      case 'date':
      +        var val = +v;
      +        found = this.some(function(d){ return +d === val });
      +        break;
      +      default:
      +        found = ~this.indexOf(v);
      +    }
      +
      +    if (!found) {
      +      [].push.call(this, v);
      +      this._registerAtomic('$addToSet', v);
      +      this._markModified();
      +      [].push.call(added, v);
      +    }
      +  }, this);
      +
      +  return added;
      +};

      Parameters:

      • [args...] <any>

      Returns:

      • <Array> the values that were added

      Example:

      + +
      console.log(doc.array) // [2,3,4]
      +var added = doc.array.addToSet(4,5);
      +console.log(doc.array) // [2,3,4,5]
      +console.log(added)     // [5]

      MongooseArray#set()

      Sets the casted val at index i and marks the array modified.

      show code
      MongooseArray.prototype.set = function set (i, val) {
      +  this[i] = this._cast(val);
      +  this._markModified(i);
      +  return this;
      +}

      Returns:

      Example:

      + +
      // given documents based on the following
      +var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
      +
      +var doc = new Doc({ array: [2,3,4] })
      +
      +console.log(doc.array) // [2,3,4]
      +
      +doc.array.set(1,"5");
      +console.log(doc.array); // [2,5,4] // properly cast to number
      +doc.save() // the change is saved
      +
      +// VS not using array#set
      +doc.array[1] = "5";
      +console.log(doc.array); // [2,"5",4] // no casting
      +doc.save() // change is not saved

      MongooseArray#toObject(options)

      Returns a native js Array.

      show code
      MongooseArray.prototype.toObject = function (options) {
      +  if (options && options.depopulate && this[0] instanceof Document) {
      +    return this.map(function (doc) {
      +      return doc._id;
      +    });
      +  }
      +
      +  // return this.slice()?
      +  return this.map(function (doc) {
      +    return doc;
      +  });
      +};

      Parameters:

      Returns:


      MongooseArray#inspect()

      Helper for console.log

      show code
      MongooseArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    return ' ' + doc;
      +  }) + ' ]';
      +};

      MongooseArray#indexOf(obj)

      Return the index of obj or -1 if not found.

      show code
      MongooseArray.prototype.indexOf = function indexOf (obj) {
      +  if (obj instanceof ObjectId) obj = obj.toString();
      +  for (var i = 0, len = this.length; i < len; ++i) {
      +    if (obj == this[i])
      +      return i;
      +  }
      +  return -1;
      +};

      Parameters:

      • obj <Object> the item to look for

      Returns:


      MongooseArray#_parent

      Parent owner document


      MongooseArray#_atomics

      Stores a queue of atomic operations to perform


    • types/buffer.js

      MongooseBuffer(value, encode, offset)

      Mongoose Buffer constructor.

      show code
      function MongooseBuffer (value, encode, offset) {
      +  var length = arguments.length;
      +  var val;
      +
      +  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
      +    val = 0;
      +  } else {
      +    val = value;
      +  }
      +
      +  var encoding;
      +  var path;
      +  var doc;
      +
      +  if (Array.isArray(encode)) {
      +    // internal casting
      +    path = encode[0];
      +    doc = encode[1];
      +  } else {
      +    encoding = encode;
      +  }
      +
      +  var buf = new Buffer(val, encoding, offset);
      +  buf.__proto__ = MongooseBuffer.prototype;
      +
      +  // make sure these internal props don't show up in Object.keys()
      +  Object.defineProperties(buf, {
      +      validators: { value: [] }
      +    , _path: { value: path }
      +    , _parent: { value: doc }
      +  });
      +
      +  if (doc && "string" === typeof path) {
      +    Object.defineProperty(buf, '_schema', {
      +        value: doc.schema.path(path)
      +    });
      +  }
      +
      +  return buf;
      +};

      Parameters:

      Inherits:

      Values always have to be passed to the constructor to initialize.


      MongooseBuffer#_markModified()

      Marks this buffer as modified.

      show code
      MongooseBuffer.prototype._markModified = function () {
      +  var parent = this._parent;
      +
      +  if (parent) {
      +    parent.markModified(this._path);
      +  }
      +  return this;
      +};

      MongooseBuffer#write()

      Writes the buffer.

      show code
      MongooseBuffer.prototype.write = function () {
      +  var written = Buffer.prototype.write.apply(this, arguments);
      +
      +  if (written > 0) {
      +    this._markModified();
      +  }
      +
      +  return written;
      +};

      MongooseBuffer#copy(target)

      Copies the buffer.

      show code
      MongooseBuffer.prototype.copy = function (target) {
      +  var ret = Buffer.prototype.copy.apply(this, arguments);
      +
      +  if (target instanceof MongooseBuffer) {
      +    target._markModified();
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Note:

      + +

      Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


      MongooseBuffer#toObject([subtype])

      Converts this buffer to its Binary type representation.

      show code
      MongooseBuffer.prototype.toObject = function (subtype) {
      +  subtype = typeof subtype !== 'undefined' ? subtype : 0x00
      +  return new Binary(this, subtype);
      +};

      Parameters:

      • [subtype] <Hex>

      Returns:

      SubTypes:

      + +
        +
      • 0x00: Binary/Generic
      • +
      • 0x01: Function
      • +
      • 0x02: Binary (Deprecated, 0x00 is new default)
      • +
      • 0x03: UUID
      • +
      • 0x04: MD5
      • +
      • 0x80: User Defined
      • +

      MongooseBuffer#_parent

      Parent owner document


    • types/documentarray.js

      MongooseDocumentArray(values, path, doc)

      DocumentArray constructor

      show code
      function MongooseDocumentArray (values, path, doc) {
      +  var arr = [];
      +
      +  // Values always have to be passed to the constructor to initialize, since
      +  // otherwise MongooseArray#push will mark the array as modified to the parent.
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseDocumentArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +    doc.on('save', arr.notify('save'));
      +    doc.on('isNew', arr.notify('isNew'));
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:


      MongooseDocumentArray#_cast()

      Overrides MongooseArray#cast

      show code
      MongooseDocumentArray.prototype._cast = function (value) {
      +  if (value instanceof this._schema.casterConstructor)
      +    return value;
      +
      +  return new this._schema.casterConstructor(value, this);
      +};

      MongooseDocumentArray#id(id)

      Searches array items for the first document with a matching id.

      show code
      MongooseDocumentArray.prototype.id = function (id) {
      +  var casted
      +    , _id;
      +
      +  try {
      +    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
      +  } catch (e) {
      +    casted = null;
      +  }
      +
      +  for (var i = 0, l = this.length; i < l; i++) {
      +    _id = this[i].get('_id');
      +    if (!(_id instanceof ObjectId)) {
      +      if (String(id) == _id)
      +        return this[i];
      +    } else {
      +      if (casted == _id)
      +        return this[i];
      +    }
      +  }
      +
      +  return null;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var embeddedDoc = m.array.id(some_id);

      MongooseDocumentArray#toObject()

      Returns a native js Array of plain js objects

      show code
      MongooseDocumentArray.prototype.toObject = function () {
      +  return this.map(function (doc) {
      +    return doc && doc.toObject() || null;
      +  });
      +};

      Returns:

      NOTE:

      + +

      Each sub-document is converted to a plain object by calling its #toObject method.


      MongooseDocumentArray#inspect()

      Helper for console.log

      show code
      MongooseDocumentArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    if (doc) {
      +      return doc.inspect
      +        ? doc.inspect()
      +        : util.inspect(doc)
      +    }
      +    return 'null'
      +  }).join('
      +') + ']';
      +};

      MongooseDocumentArray#create(obj)

      Creates a subdocument casted to this schema.

      show code
      MongooseDocumentArray.prototype.create = function (obj) {
      +  return new this._schema.casterConstructor(obj);
      +}

      Parameters:

      • obj <Object> the value to cast to this arrays SubDocument schema

      This is the same subdocument constructor used for casting.


      MongooseDocumentArray#notify(event)

      Creates a fn that notifies all child docs of event.

      show code
      MongooseDocumentArray.prototype.notify = function notify (event) {
      +  var self = this;
      +  return function notify (val) {
      +    var i = self.length;
      +    while (i--) {
      +      if (!self[i]) continue;
      +      self[i].emit(event, val);
      +    }
      +  }
      +}

      Parameters:

      Returns:


    • types/embedded.js

      EmbeddedDocument(obj, parentArr, skipId)

      EmbeddedDocument constructor.

      show code
      function EmbeddedDocument (obj, parentArr, skipId, fields) {
      +  if (parentArr) {
      +    this.__parentArray = parentArr;
      +    this.__parent = parentArr._parent;
      +  } else {
      +    this.__parentArray = undefined;
      +    this.__parent = undefined;
      +  }
      +
      +  Document.call(this, obj, fields, skipId);
      +
      +  var self = this;
      +  this.on('isNew', function (val) {
      +    self.isNew = val;
      +  });
      +};

      Parameters:

      Inherits:


      EmbeddedDocument#markModified(path)

      Marks the embedded doc modified.

      show code
      EmbeddedDocument.prototype.markModified = function (path) {
      +  if (!this.__parentArray) return;
      +
      +  this._activePaths.modify(path);
      +
      +  if (this.isNew) {
      +    // Mark the WHOLE parent array as modified
      +    // if this is a new document (i.e., we are initializing
      +    // a document),
      +    this.__parentArray._markModified();
      +  } else
      +    this.__parentArray._markModified(this, path);
      +};

      Parameters:

      • path <String> the path which changed

      Example:

      + +
      var doc = blogpost.comments.id(hexstring);
      +doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');

      EmbeddedDocument#save([fn])

      Used as a stub for hooks.js

      show code
      EmbeddedDocument.prototype.save = function(fn) {
      +  if (fn)
      +    fn(null);
      +  return this;
      +};

      Parameters:

      Returns:

      NOTE:

      + +

      This is a no-op. Does not actually save the doc to the db.


      EmbeddedDocument#remove([fn])

      Removes the subdocument from its parent array.

      show code
      EmbeddedDocument.prototype.remove = function (fn) {
      +  if (!this.__parentArray) return this;
      +
      +  var _id;
      +  if (!this.willRemove) {
      +    _id = this._doc._id;
      +    if (!_id) {
      +      throw new Error('For your own good, Mongoose does not know ' + 
      +                      'how to remove an EmbeddedDocument that has no _id');
      +    }
      +    this.__parentArray.pull({ _id: _id });
      +    this.willRemove = true;
      +  }
      +
      +  if (fn)
      +    fn(null);
      +
      +  return this;
      +};

      Parameters:


      EmbeddedDocument#update()

      Override #update method of parent documents.

      show code
      EmbeddedDocument.prototype.update = function () {
      +  throw new Error('The #update method is not available on EmbeddedDocuments');
      +}

      EmbeddedDocument#inspect()

      Helper for console.log

      show code
      EmbeddedDocument.prototype.inspect = function () {
      +  return inspect(this.toObject());
      +};

      EmbeddedDocument#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
      +  if (!this.__parent) return false;
      +  var index = this.__parentArray.indexOf(this);
      +  var parentPath = this.__parentArray._path;
      +  var fullPath = [parentPath, index, path].join('.');
      +  this.__parent.invalidate(fullPath, err);
      +  if (first)
      +    this._validationError = ownerDocument(this)._validationError;
      +  return true;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> error which states the reason `path` was invalid

      Returns:


      EmbeddedDocument#ownerDocument()

      Returns the top level document of this sub-document.

      show code
      EmbeddedDocument.prototype.ownerDocument = function () {
      +  return ownerDocument(this);
      +}

      Returns:


      EmbeddedDocument#parent()

      Returns this sub-documents parent document.

      show code
      EmbeddedDocument.prototype.parent = function () {
      +  return this.__parent;
      +}

      EmbeddedDocument#parentArray()

      Returns this sub-documents parent array.

      show code
      EmbeddedDocument.prototype.parentArray = function () {
      +  return this.__parentArray;
      +}

    • types/objectid.js

      ObjectId()

      ObjectId type constructor

      Example

      + +
      var id = new mongoose.Types.ObjectId;

      ObjectId.fromString(str)

      Creates an ObjectId from str

      show code
      ObjectId.fromString;

      Parameters:

      Returns:


      ObjectId.toString(oid)

      Converts oid to a string.

      show code
      ObjectId.toString;

      Parameters:

      Returns:


    • utils.js

      exports.toCollectionName(name)

      Produces a collection name from model name.

      show code
      exports.toCollectionName = function (name) {
      +  if ('system.profile' === name) return name;
      +  if ('system.indexes' === name) return name;
      +  return pluralize(name.toLowerCase());
      +};

      Parameters:

      Returns:


      exports.pluralization

      Pluralization rules.

      show code
      exports.pluralization = [
      +  [/(m)an$/gi, '$1en'],
      +  [/(pe)rson$/gi, '$1ople'],
      +  [/(child)$/gi, '$1ren'],
      +  [/^(ox)$/gi, '$1en'],
      +  [/(ax|test)is$/gi, '$1es'],
      +  [/(octop|vir)us$/gi, '$1i'],
      +  [/(alias|status)$/gi, '$1es'],
      +  [/(bu)s$/gi, '$1ses'],
      +  [/(buffal|tomat|potat)o$/gi, '$1oes'],
      +  [/([ti])um$/gi, '$1a'],
      +  [/sis$/gi, 'ses'],
      +  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
      +  [/(hive)$/gi, '$1s'],
      +  [/([^aeiouy]|qu)y$/gi, '$1ies'],
      +  [/(x|ch|ss|sh)$/gi, '$1es'],
      +  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
      +  [/([m|l])ouse$/gi, '$1ice'],
      +  [/(quiz)$/gi, '$1zes'],
      +  [/s$/gi, 's'],
      +  [/$/gi, 's']
      +];
      +var rules = exports.pluralization;

      These rules are applied while processing the argument to toCollectionName.


      exports.uncountables

      Uncountable words.

      show code
      exports.uncountables = [
      +  'advice',
      +  'energy',
      +  'excretion',
      +  'digestion',
      +  'cooperation',
      +  'health',
      +  'justice',
      +  'labour',
      +  'machinery',
      +  'equipment',
      +  'information',
      +  'pollution',
      +  'sewage',
      +  'paper',
      +  'money',
      +  'species',
      +  'series',
      +  'rain',
      +  'rice',
      +  'fish',
      +  'sheep',
      +  'moose',
      +  'deer',
      +  'news',
      +  'expertise',
      +  'status',
      +  'media'
      +];
      +var uncountables = exports.uncountables;

      These words are applied while processing the argument to toCollectionName.


      exports.deepEqual(a, b)

      Determines if a and b are deep equal.

      show code
      exports.deepEqual = function deepEqual (a, b) {
      +  if (a === b) return true;
      +
      +  if (a instanceof Date && b instanceof Date)
      +    return a.getTime() === b.getTime();
      +
      +  if (a instanceof ObjectId && b instanceof ObjectId) {
      +    return a.toString() === b.toString();
      +  }
      +
      +  if (typeof a !== 'object' && typeof b !== 'object')
      +    return a == b;
      +
      +  if (a === null || b === null || a === undefined || b === undefined)
      +    return false
      +
      +  if (a.prototype !== b.prototype) return false;
      +
      +  // Handle MongooseNumbers
      +  if (a instanceof Number && b instanceof Number) {
      +    return a.valueOf() === b.valueOf();
      +  }
      +
      +  if (Buffer.isBuffer(a)) {
      +    if (!Buffer.isBuffer(b)) return false;
      +    if (a.length !== b.length) return false;
      +    for (var i = 0, len = a.length; i < len; ++i) {
      +      if (a[i] !== b[i]) return false;
      +    }
      +    return true;
      +  }
      +
      +  if (isMongooseObject(a)) a = a.toObject();
      +  if (isMongooseObject(b)) b = b.toObject();
      +
      +  try {
      +    var ka = Object.keys(a),
      +        kb = Object.keys(b),
      +        key, i;
      +  } catch (e) {//happens when one is a string literal and the other isn't
      +    return false;
      +  }
      +
      +  // having the same number of owned properties (keys incorporates
      +  // hasOwnProperty)
      +  if (ka.length != kb.length)
      +    return false;
      +
      +  //the same set of keys (although not necessarily the same order),
      +  ka.sort();
      +  kb.sort();
      +
      +  //~~~cheap key test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    if (ka[i] != kb[i])
      +      return false;
      +  }
      +
      +  //equivalent values for every corresponding key, and
      +  //~~~possibly expensive deep test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    key = ka[i];
      +    if (!deepEqual(a[key], b[key])) return false;
      +  }
      +
      +  return true;
      +};

      Parameters:

      • a <any> a value to compare to `b`
      • b <any> a value to compare to `a`

      Returns:

      Modified from node/lib/assert.js


      exports.clone(obj, options)

      Object clone with Mongoose natives support.

      show code
      exports.clone = function clone (obj, options) {
      +  if (obj === undefined || obj === null)
      +    return obj;
      +
      +  if (Array.isArray(obj))
      +    return cloneArray(obj, options);
      +
      +  if (isMongooseObject(obj)) {
      +    if (options && options.json && 'function' === typeof obj.toJSON) {
      +      return obj.toJSON(options);
      +    } else {
      +      return obj.toObject(options);
      +    }
      +  }
      +
      +  if ('Object' === obj.constructor.name)
      +    return cloneObject(obj, options);
      +
      +  if ('Date' === obj.constructor.name)
      +    return new obj.constructor(+obj);
      +
      +  if ('RegExp' === obj.constructor.name)
      +    return new RegExp(obj.source);
      +
      +  if (obj instanceof ObjectId)
      +    return new ObjectId(obj.id);
      +
      +  if (obj.valueOf)
      +    return obj.valueOf();
      +};
      +var clone = exports.clone;

      Parameters:

      Returns:

      If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

      + +

      Functions are never cloned.


      exports.options(defaults, options)

      Copies and merges options with defaults.

      show code
      exports.options = function (defaults, options) {
      +  var keys = Object.keys(defaults)
      +    , i = keys.length
      +    , k ;
      +
      +  options = options || {};
      +
      +  while (i--) {
      +    k = keys[i];
      +    if (!(k in options)) {
      +      options[k] = defaults[k];
      +    }
      +  }
      +
      +  return options;
      +};

      Parameters:

      Returns:


      exports.random()

      Generates a random string

      show code
      exports.random = function () {
      +  return Math.random().toString().substr(3);
      +};

      exports.merge(to, from)

      Merges from into to without overwriting existing properties.

      show code
      exports.merge = function merge (to, from) {
      +  var keys = Object.keys(from)
      +    , i = keys.length
      +    , key
      +
      +  while (i--) {
      +    key = keys[i];
      +    if ('undefined' === typeof to[key]) {
      +      to[key] = from[key];
      +    } else {
      +      if (exports.isObject(from[key])) {
      +        merge(to[key], from[key]);
      +      } else {
      +        to[key] = from[key];
      +      }
      +    }
      +  }
      +};

      Parameters:


      exports.isObject(arg)

      Determines if arg is an object.

      show code
      exports.isObject = function (arg) {
      +  return '[object Object]' == toString(arg);
      +}

      Parameters:

      Returns:


      exports.args

      A faster Array.prototype.slice.call(arguments) alternative

      show code
      exports.args = sliced;

      exports.tick(callback)

      process.nextTick helper.

      show code
      exports.tick = function tick (callback) {
      +  if ('function' !== typeof callback) return;
      +  return function () {
      +    try {
      +      callback.apply(this, arguments);
      +    } catch (err) {
      +      // only nextTick on err to get out of
      +      // the event loop and avoid state corruption.
      +      process.nextTick(function () {
      +        throw err;
      +      });
      +    }
      +  }
      +}

      Parameters:

      Wraps callback in a try/catch + nextTick.

      + +

      node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


      exports.isMongooseObject(v)

      Returns if v is a mongoose object that has a toObject() method we can use.

      show code
      exports.isMongooseObject = function (v) {
      +  Document || (Document = require('./document'));
      +  MongooseArray || (MongooseArray = require('./types').Array);
      +  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
      +
      +  return v instanceof Document ||
      +         v instanceof MongooseArray ||
      +         v instanceof MongooseBuffer
      +}
      +var isMongooseObject = exports.isMongooseObject;

      Parameters:

      This is for compatibility with libs like Date.js which do foolish things to Natives.


      exports.expires(object)

      Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

      show code
      exports.expires = function expires (object) {
      +  if (!(object && 'Object' == object.constructor.name)) return;
      +  if (!('expires' in object)) return;
      +
      +  var when;
      +  if ('string' != typeof object.expires) {
      +    when = object.expires;
      +  } else {
      +    when = Math.round(ms(object.expires) / 1000);
      +  }
      +  object.expireAfterSeconds = when;
      +  delete object.expires;
      +}
      +
      +exports.readPref = function readPref (pref, tags) {
      +  if (Array.isArray(pref)) {
      +    tags = pref[1];
      +    pref = pref[0];
      +  }
      +
      +  switch (pref) {
      +    case 'p':
      +      pref = 'primary';
      +      break;
      +    case 'pp':
      +      pref = 'primaryPrefered';
      +      break;
      +    case 's':
      +      pref = 'secondary';
      +      break;
      +    case 'sp':
      +      pref = 'secondaryPrefered';
      +      break;
      +    case 'n':
      +      pref = 'nearest';
      +      break;
      +  }
      +
      +  return new ReadPref(pref, tags);
      +}

      Parameters:


    • virtualtype.js

      VirtualType()

      VirtualType constructor

      show code
      function VirtualType (options, name) {
      +  this.path = name;
      +  this.getters = [];
      +  this.setters = [];
      +  this.options = options || {};
      +}

      This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

      + +

      Example:

      + +
      var fullname = schema.virtual('fullname');
      +fullname instanceof mongoose.VirtualType // true

      VirtualType#get(fn)

      Defines a getter.

      show code
      VirtualType.prototype.get = function (fn) {
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.get(function () {
      +  return this.name.first + ' ' + this.name.last;
      +});

      VirtualType#set(fn)

      Defines a setter.

      show code
      VirtualType.prototype.set = function (fn) {
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.set(function (v) {
      +  var parts = v.split(' ');
      +  this.name.first = parts[0];
      +  this.name.last = parts[1];
      +});

      VirtualType#applyGetters(value, scope)

      Applies getters to value using optional scope.

      show code
      VirtualType.prototype.applyGetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.getters.length - 1; l >= 0; l--) {
      +    v = this.getters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all getters

      VirtualType#applySetters(value, scope)

      Applies setters to value using optional scope.

      show code
      VirtualType.prototype.applySetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.setters.length - 1; l >= 0; l--) {
      +    v = this.setters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all setters

    diff --git a/docs/3.4.x/docs/connections.html b/docs/3.4.x/docs/connections.html new file mode 100644 index 00000000000..7761fd4d84c --- /dev/null +++ b/docs/3.4.x/docs/connections.html @@ -0,0 +1,27 @@ +Mongoose Connecting to MongoDB v3.4.0Fork me on GitHub

    Connections

    We may connect to MongoDB by utilizing the mongoose.connect() method.

    mongoose.connect('mongodb://localhost/myapp');
    +

    This is the minimum needed to connect the myapp database running locally on the default port (27017). We may also specify several more parameters in the uri depending on your environment:

    mongoose.connect('mongodb://username:password@host:port/database');
    +

    Options

    The connect method also accepts an options object which will be passed on to the underlying driver.

    mongoose.connect(uri, options);
    +

    The following option keys are available:

    + +
     db      - passed to the connection db instance
    + server  - passed to the connection server instance(s)
    + replset - passed to the connection ReplSet instance
    + user    - username for authentication (if not specified in uri)
    + pass    - password for authentication (if not specified in uri)
    + +

    See the driver for more information about available options.

    + +

    Note: The server option auto_reconnect is defaulted to true.

    + +

    Note: The db option forceServerObjectId is set to false and cannot be overridden.

    ReplicaSet Connections

    The same method is used to connect to a replica set but instead of passing a single uri we pass a comma delimited list of uris.

    mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port' [, options]);
    +

    NOTE: The database need only be specified in one of the uris.

    Multiple connections

    So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize mongoose.createConnection() which accepts all the arguments already discussed and returns a fresh connection for you.

    var conn = mongoose.createConnection('uri,uri,uri...', options);
    +

    Connection pools

    Each connection, whether created with mongoose.connect or mongoose.createConnection are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options:

    mongoose.createConnection(uri, { server: { poolSize: 10 }});
    +

    Next Up

    Now that we've covered connections, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

    diff --git a/docs/3.4.x/docs/contributing.html b/docs/3.4.x/docs/contributing.html new file mode 100644 index 00000000000..b75cc3d3d3c --- /dev/null +++ b/docs/3.4.x/docs/contributing.html @@ -0,0 +1,9 @@ +Mongoose Contributing v3.4.0Fork me on GitHub

    Contributing

    Please read all about contributing here.

    diff --git a/docs/3.4.x/docs/css/default.css b/docs/3.4.x/docs/css/default.css new file mode 100644 index 00000000000..ccb22728ed3 --- /dev/null +++ b/docs/3.4.x/docs/css/default.css @@ -0,0 +1,135 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +pre code { + display: block; padding: 0.5em; + background: #F0F0F0; +} + +pre code, +pre .ruby .subst, +pre .tag .title, +pre .lisp .title, +pre .clojure .built_in, +pre .nginx .title { + color: black; +} + +pre .string, +pre .title, +pre .constant, +pre .parent, +pre .tag .value, +pre .rules .value, +pre .rules .value .number, +pre .preprocessor, +pre .ruby .symbol, +pre .ruby .symbol .string, +pre .ruby .symbol .keyword, +pre .ruby .symbol .keymethods, +pre .instancevar, +pre .aggregate, +pre .template_tag, +pre .django .variable, +pre .smalltalk .class, +pre .addition, +pre .flow, +pre .stream, +pre .bash .variable, +pre .apache .tag, +pre .apache .cbracket, +pre .tex .command, +pre .tex .special, +pre .erlang_repl .function_or_atom, +pre .markdown .header { + color: #800; +} + +pre .comment, +pre .annotation, +pre .template_comment, +pre .diff .header, +pre .chunk, +pre .markdown .blockquote { + color: #888; +} + +pre .number, +pre .date, +pre .regexp, +pre .literal, +pre .smalltalk .symbol, +pre .smalltalk .char, +pre .go .constant, +pre .change, +pre .markdown .bullet, +pre .markdown .link_url { + color: #080; +} + +pre .label, +pre .javadoc, +pre .ruby .string, +pre .decorator, +pre .filter .argument, +pre .localvars, +pre .array, +pre .attr_selector, +pre .important, +pre .pseudo, +pre .pi, +pre .doctype, +pre .deletion, +pre .envvar, +pre .shebang, +pre .apache .sqbracket, +pre .nginx .built_in, +pre .tex .formula, +pre .erlang_repl .reserved, +pre .input_number, +pre .markdown .link_label, +pre .vhdl .attribute, +pre .clojure .attribute { + color: #88F +} + +pre .keyword, +pre .id, +pre .phpdoc, +pre .title, +pre .built_in, +pre .aggregate, +pre .css .tag, +pre .javadoctag, +pre .phpdoc, +pre .yardoctag, +pre .smalltalk .class, +pre .winutils, +pre .bash .variable, +pre .apache .tag, +pre .go .typename, +pre .tex .command, +pre .markdown .strong, +pre .request, +pre .status { + font-weight: bold; +} + +pre .markdown .emphasis { + font-style: italic; +} + +pre .nginx .built_in { + font-weight: normal; +} + +pre .coffeescript .javascript, +pre .xml .css, +pre .xml .javascript, +pre .xml .vbscript, +pre .tex .formula { + opacity: 0.5; +} diff --git a/docs/3.4.x/docs/css/guide.css b/docs/3.4.x/docs/css/guide.css new file mode 100644 index 00000000000..b77ffe83b0c --- /dev/null +++ b/docs/3.4.x/docs/css/guide.css @@ -0,0 +1,326 @@ +html, body, #content { + height: 100%; +} +:target::before { + content: ">>> "; + color: #1371C9; + font-weight: bold; + font-size: 20px; +} +.module { + min-height: 100%; + box-sizing: border-box; + overflow-x: hidden; +} +body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; +} +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; +} +code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Monaco; + /*text-shadow: 1px 2px 2px #555;*/ +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +h2 { + margin-top: 0; +} +h2 a { + font-size: 12px; + position: relative; + bottom: 3px; + font-weight: normal; +} +h3 { padding-top: 35px; } +h3 code { + font-weight: normal; +} +hr { + display: none; + height: 1px; + border: 0 none; + padding: 0; + margin: 90px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) +} +.doclinks hr { + margin: 10px 0; +} +li { + list-style: square; +} +#header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +#header .mongoose { + font-size: 48px; + font-weight: 100; + color: #fff; + letter-spacing: -5px; +} +#links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; +} +#links .schematypes span { + display: none; +} +#content { + padding: 0; + margin: 0 0 0 230px; +} +#content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +#content .controls:hover { + opacity: .9; +} +#content p { + word-wrap: break-word; +} +#content > ul { + margin: 0; + padding: 0; +} +.private { + display: none; +} +.doclinks li.private a:before, +.doclinks .module.private a:before, +.doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; +} +#content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; +} +.module { + list-style: none; + padding: 30px 0 0 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; +} +.module > * { + max-width: 700px; +} +.item { + margin-bottom: 175px; +} +.item h3 a { + color: #333; + text-decoration: none; +} +.property h3 span { + color: #444; +} +.description { + margin-top: 25px; +} +.sourcecode { + display: none; +} +.showcode { + font-size: 12px; + cursor: pointer; + display: none; +} +.load .showcode { + display: block; +} +.types a { + text-decoration: none; +} +li.guide ul { + padding-left: 16px; +} + +ul.inthewild { + margin: 30px 0 0 -30px; + padding: 0; + width: 125%; + max-width: 125%; +} +ul.inthewild li { + display: inline-block; + list-style: none; +} +ul.inthewild img { + width: 200px; +} + +@media only screen and (device-width: 768px) { + ul.inthewild { + margin-left: 0px; + } +} + +@media only screen and (max-width: 480px) { + ul.inthewild { + margin-left: 0px; + } + ul.inthewild li { + margin: 5px; + border-width: 2px 2px 0 2px; + border-style: solid; + border-color: #eee; + } + ul.inthewild li img { + width: 140px; + } + h2 a { + white-space: nowrap; + } + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + html, body, #content { + height: auto; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + #links li.guide { + display: block; + width: 390px; + margin-bottom: 15px; + } + #links li.guide > a { + display: none; + } + #links li ul li { + width: 44%; + text-align: left; + } + #links li ul li ul li { + width: 95%; + } + #links .plugins, + #links .changelog { + display: none; + } + #links .schematypes span { + display: inline; + } + #links .double { + width: 332px; + } + #links .double > ul { + display: inline; + float: right; + } + #links .double > ul li { + width: 155px; + } +} diff --git a/docs/3.4.x/docs/css/style.css b/docs/3.4.x/docs/css/style.css new file mode 100644 index 00000000000..34fee99b3f7 --- /dev/null +++ b/docs/3.4.x/docs/css/style.css @@ -0,0 +1,225 @@ +body { + font-family: 'Open Sans', Helvetica, Arial, FreeSans; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; +} + +/* location.hash */ +:target::before { + content: ">>> "; + color: #1371C9; + font-weight: bold; + font-size: 20px; +} +/* ignore home page hash */ +#production:target::before { + content: ""; + font-size: inherit; +} + +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { + width: 600px; + margin: 0 auto; + position:relative; +} +li { + list-style: square; +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: #eee; + padding: 5px; + border-radius: 3px; +} +code { + color: #333; + font-size: 11px; + font-family: Monaco; +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +#header { + text-align: center; + padding-top: 40px; +} +#header, h2, h3, .tagline, .blurb { + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +h2 { + margin: 30px 0; +} +h2 a { + font-size: 11px; + position: relative; + bottom: 4px; +} +#header .mongoose { + font-size: 146px; + font-weight: 100; + text-indent: -23px; +} +.load #header .mongoose { + letter-spacing: -14px; +} +.tagline { + color: #333; + font-size: 25px; + text-shadow: 1px 1px #f8f8f8; + text-align: center; +} +.blurb { + text-align: center; + font-style: oblique; + font-size: 12px; + margin-bottom: 20px; +} +.tagline a, .blurb a { + text-decoration: none; + color: #800; +} +#links { + margin: 30px 10px 46px; + text-align: center; + position: relative; +} +#links ul { + margin: 0; + padding: 0; +} +#links li { + display: inline-block; + margin: 0 15px; + background-color: #FEFEFE; +} +#links a { + background: #444; + padding: 9px 0px; + border-radius: 3px; + color: white; + width: 180px; + display: inline-block; + text-decoration: none; + text-transform: lowercase; + text-shadow: 1px 1px 7px #222; +} +#production ul { + padding: 0; +} +#production li { + list-style: none; + overflow: hidden; + display: inline-block; + height: 114px; +} +#production img { + width: 180px; + margin: 10px; +} +#production img#mcds { + width: 134px; + margin: 10px 25px; +} +#production a { + -webkit-transition-property: opacity; + -moz-transition-property: opacity; + -o-transition-property: opacity; + transition-property: opacity; + -webkit-transition-duration: 0.25s; + -moz-transition-duration: 0.25s; + -o-transition-duration: 0.25s; + transition-duration: 0.25s; + opacity: 0.7; +} +#production a:hover { + opacity: 1.0; +} +#footer { + text-align: center; + font-size: 12px; + margin-bottom: 20px; +} +@media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header { + padding-top: 12px; + } + #header .mongoose { + text-align: center; + font-size: 65px; + font-weight: 100; + letter-spacing: -7px; + } + .load #header .mongoose { + letter-spacing: -7px; + } + .tagline { + text-align: center; + font-size: 14px; + } + .tagline a { + text-decoration: none; + } + .blurb { + font-size: 16px; + text-align: justify; + margin-top: 25px; + } + #links { + margin-bottom: 40px; + } + #links li { + padding: 8px 2px; + margin: 0 12px; + } + #links a { + background: #444; + padding: 7px 34px; + font-size: 15px; + } + #docs { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + #wrap { + width: auto; + padding: 0 5px; + } + #production li { + margin-bottom: 8px; + } + #production a { + opacity: 1; + } + #production img { + width: 175px; + } + .addyourown, .addyourown a { + width: 100%; + } +} diff --git a/docs/3.4.x/docs/documents.html b/docs/3.4.x/docs/documents.html new file mode 100644 index 00000000000..c10a191f2b0 --- /dev/null +++ b/docs/3.4.x/docs/documents.html @@ -0,0 +1,20 @@ +Mongoose Documents v3.4.0Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    +  if (err) return handleError(err);
    +  
    +  tank.size = 'large';
    +  tank.save(function (err) {
    +    if (err) return handleError(err);
    +    res.send(tank);
    +  });
    +});

    This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    +  if (err) return handleError(err);
    +  res.send(tank);
    +});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    diff --git a/docs/3.4.x/docs/faq.html b/docs/3.4.x/docs/faq.html new file mode 100644 index 00000000000..35cc94d6d1e --- /dev/null +++ b/docs/3.4.x/docs/faq.html @@ -0,0 +1,31 @@ +Mongoose FAQ v3.4.0Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    +doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    +doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    +new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    +doc.user.remove();// ?
    +doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    + +

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    + +

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    +mongoose.connect(..);
    +mongoose.connection.on('error', handleError);
    +
    +// if connecting on a separate connection
    +var conn = mongoose.createConnection(..);
    +conn.on('error', handleError);
    +

    Something to add?

    + +

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    diff --git a/docs/3.4.x/docs/guide.html b/docs/3.4.x/docs/guide.html new file mode 100644 index 00000000000..c9e352dd274 --- /dev/null +++ b/docs/3.4.x/docs/guide.html @@ -0,0 +1,190 @@ +Mongoose Schemas v3.4.0Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works.

    If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    +  title:  String,
    +  author: String,
    +  body:   String,
    +  comments: [{ body: String, date: Date }],
    +  date: { type: Date, default: Date.now },
    +  hidden: Boolean,
    +  meta: {
    +    votes: Number,
    +    favs:  Number
    +  }
    +});

    If you want to add additional keys later, use the Schema#add method.

    +Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. +Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    +
    +animalSchema.methods.findSimilarTypes = function (cb) {
    +  return this.model('Animal').find({ type: this.type }, cb);
    +}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    +var dog = new Animal({ type: 'dog' });
    +
    +dog.findSimilarTypes(function (err, dogs) {
    +  console.log(dogs); // woof
    +});

    Statics

    +Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    +  this.find({ name: new RegExp(name, 'i') }, cb);
    +}
    +
    +var Animal = mongoose.model('Animal', animalSchema);
    +Animal.findByName('fido', function (err, animals) {
    +  console.log(animals);
    +});

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });
    +

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index. It is recommended this behavior be disabled in production by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false);
    +// or
    +new Schema({..}, { autoIndex: false });
    +

    See also the Model#ensureIndexes method for more details.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    +  name: {
    +    first: String,
    +    last: String
    +  }
    +});
    +
    +var Person = mongoose.model('Person', personSchema);
    +
    +var bad = new Person({
    +    name: { first: 'Walter', last: 'White' }
    +});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    +  return this.name.first + ' ' + this.name.last;
    +});

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full); // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    +  var split = name.split(' ');
    +  this.name.first = split[0];
    +  this.name.last = split[1];
    +});
    +
    +...
    +
    +mad.name.full = 'Breaking Bad';
    +console.log(mad.name.first); // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    +
    +// or
    +
    +var schema = new Schema({..});
    +schema.set(option, value);
    +

    Valid options:

    + +

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false });
    +var Clock = db.model('Clock', schema);
    +Clock.ensureIndexes(callback);
    +

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 });

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });
    +

    option: collection

    Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Set this option if you need a different name for your collection.

    var dataSchema = new Schema({..}, { collection: 'data' });
    +

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // '50341373e894ad16347efe01'
    +
    +// disabled id
    +var schema = new Schema({ name: String }, { id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // undefined
    +

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    + +

    Pass this option during schema construction to prevent documents from getting an auto _id created.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
    +
    +// disabled _id
    +var schema = new Schema({ name: String }, { _id: false });
    +var Page = db.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { name: 'mongodb.org' }
    +

    option: read

    Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

    var schema = new Schema({..}, { read: 'primary' });            // also aliased as 'p'
    +var schema = new Schema({..}, { read: 'primaryPreferred' });   // aliased as 'pp'
    +var schema = new Schema({..}, { read: 'secondary' });          // aliased as 's'
    +var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp'
    +var schema = new Schema({..}, { read: 'nearest' });            // aliased as 'n'
    +

    The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'.

    + +

    The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

    + +

    NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

    // pings the replset members periodically to track network latency
    +// now `nearest` works as intended
    +var options = { replset: { strategy: 'ping' }};
    +mongoose.connect(uri, options);
    +
    +var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
    +mongoose.model('JellyBean', schema);
    +

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    +new Schema({ .. }, { safe: safe });
    +

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. +By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    + +

    NOTE: this setting overrides any setting specified by passing db options while creating a connection. To prevent this behavior and allow your db safe option to be honored, you must set this option to undefined on your schemas.

    + +

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
    +new Schema({ .. }, { safe: safe });
    +

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    +

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: strict

    The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save(); // iAmNotInTheSchema is not saved to the db
    +
    +// set to false..
    +var thingSchema = new Schema({..}, { strict: false });
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save(); // iAmNotInTheSchema is now saved to the db!!
    +

    This also affects the use of doc.set() to set a property value.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing;
    +thing.set('iAmNotInTheSchema', true);
    +thing.save(); // iAmNotInTheSchema is not saved to the db
    +

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = db.model('Thing');
    +var thing = new Thing(doc, true);  // enables strict mode
    +var thing = new Thing(doc, false); // disables strict mode
    +

    The strict option may also be set to "throw" which will cause errors to be produced instead of dropping the bad data.

    NOTE: do not set to false unless you have good reason.

    + +

    NOTE: in mongoose v2 the default was false.

    + +

    NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.

    var thingSchema = new Schema({..})
    +var Thing = db.model('Thing', schemaSchema);
    +var thing = new Thing;
    +thing.iAmNotInTheSchema = true;
    +thing.save(); // iAmNotInTheSchema is never saved to the db
    +

    option: toJSON

    Exactly the same as the toObject option but only applies when the documents toJSON method is called.

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toJSON', { getters: true, virtuals: false });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
    +console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +// since we know toJSON is called whenever a js object is stringified:
    +console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
    +

    To see all available toJSON/toObject options, read this.

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    + +

    To have all virtuals show up in your console.log output, set the toObject option to { getters: true }:

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toObject', { getters: true });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +

    To see all available toObject options, read this.

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { __v: 0, name: 'mongoose v3' }
    +
    +// customized versionKey
    +new Schema({..}, { versionKey: '_somethingElse' })
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    +

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false });
    +var Thing = db.model('Thing', schema);
    +var thing = new Thing({ name: 'no versioning please' });
    +thing.save(); // { name: 'no versioning please' }
    +
    +

    Next Up

    Now that we've covered Schemas, let's take a look at SchemaTypes.

    diff --git a/docs/3.4.x/docs/helpers/filters.js b/docs/3.4.x/docs/helpers/filters.js new file mode 100644 index 00000000000..33546a7e805 --- /dev/null +++ b/docs/3.4.x/docs/helpers/filters.js @@ -0,0 +1,20 @@ + +var hl = require('highlight.js') + +module.exports = exports = function (jade) { + // add highlighting filter to jade + + jade.filters.js = function (str) { + str = str.replace(/\\n/g, '\n'); + var ret = hl.highlight('javascript', str).value; + var code = '
    ' + ret.replace(/\n/g, '\\n') + '
    '; + return code; + } + + jade.filters.bash = function (str) { + var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; + var code = '
    ' + ret + '
    '; + return code + } + +} diff --git a/docs/3.4.x/docs/helpers/highlight.js b/docs/3.4.x/docs/helpers/highlight.js new file mode 100644 index 00000000000..8aca9b9e222 --- /dev/null +++ b/docs/3.4.x/docs/helpers/highlight.js @@ -0,0 +1,11 @@ + +var h = require('highlight.js') + +function hl (str) { + str = str.replace(/\\n/g, '\n'); + var ret = h.highlight('javascript', str).value; + var code = '
    ' + ret+ '
    '; + return code; +} + +module.exports = hl; diff --git a/docs/3.4.x/docs/helpers/href.js b/docs/3.4.x/docs/helpers/href.js new file mode 100644 index 00000000000..e7299b1cf0d --- /dev/null +++ b/docs/3.4.x/docs/helpers/href.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str, char) { + if ('string' != typeof str) return str; + return encodeURIComponent(str.replace(/\.js$/, '').replace(/\.|#/g, char || '-')); +} diff --git a/docs/3.4.x/docs/helpers/klass.js b/docs/3.4.x/docs/helpers/klass.js new file mode 100644 index 00000000000..0c4a865b43b --- /dev/null +++ b/docs/3.4.x/docs/helpers/klass.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str) { + var parts = str.replace(/\.js$/, '').split('/'); + return parts.join('_'); +} diff --git a/docs/3.4.x/docs/helpers/linktype.js b/docs/3.4.x/docs/helpers/linktype.js new file mode 100644 index 00000000000..997e740f671 --- /dev/null +++ b/docs/3.4.x/docs/helpers/linktype.js @@ -0,0 +1,50 @@ + +var types = {}; +types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; +types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' +types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' +types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' +types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' +types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' +types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' +types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' +types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' +types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' + +// mongoose +types.ObjectId = '#types_objectid_ObjectId'; +types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; +types.MongooseArray = '#types_array_MongooseArray'; +types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; +types.Query = '#query-js'; +types.QueryStream = '#querystream_QueryStream'; +types.Document = '#document_Document'; +types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; +types.Document = '#document_Document'; +types.Model = '#model_Model'; +types.Connection = '#connection_Connection'; +types.Collection = '#collection_Collection'; +types.Schema = '#schema_Schema'; +types.Promise = '#promise_Promise'; +types.Mongoose = '#index_Mongoose'; +types.MongooseError = '#error_MongooseError'; +types.Type = '#schematype_SchemaType'; // ? +types.SchemaType = '#schematype_SchemaType'; +types.SchemaArray = '#schema_array_SchemaArray'; +types.Mixed = '#schema_mixed_Mixed'; +types.VirtualType = '#virtualtype_VirtualType'; +types.MongooseBuffer = '#types_buffer_MongooseBuffer'; +types.Buffer = 'http://nodejs.org/api/buffer.html'; + +module.exports= function (type) { + if (types[type]) { + return '' + type + ''; + } + return '' + type + ''; +} + +module.exports.types = types; +module.exports.type = function (str) { + if (types[str]) return types[str]; + return str; +} diff --git a/docs/3.4.x/docs/images/apps/attictv.png b/docs/3.4.x/docs/images/apps/attictv.png new file mode 100644 index 0000000000000000000000000000000000000000..1327f0bd858cf6f002a077a9aafba1217ce38e9c GIT binary patch literal 42666 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 Cl*SPN literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/calllist.png b/docs/3.4.x/docs/images/apps/calllist.png new file mode 100644 index 0000000000000000000000000000000000000000..824fa428eb2de2a237b37ada591cc7056d68f399 GIT binary patch literal 33502 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 $5C9j=SSd5$;KOc+eQQ2^5$rlF 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/cldfy.png b/docs/3.4.x/docs/images/apps/cldfy.png new file mode 100644 index 0000000000000000000000000000000000000000..c44ca3525daa7b847ab2869d44a00ebae852646d GIT binary patch literal 9773 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 AJOBUy literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/clickdummy.png b/docs/3.4.x/docs/images/apps/clickdummy.png new file mode 100644 index 0000000000000000000000000000000000000000..773ce3ec638a72dd3eb7ab6d103dade3874fa53e GIT binary patch literal 34210 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 O0000=x}o)VD=23xZGidKsJj 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

    &}XJ7y^uLKL|l(=^=~M7SI1ZoeQx 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

  • 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 Q6aWAK07*qoM6N<$g5iQW;Q#;t literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/furbabyrescue.png b/docs/3.4.x/docs/images/apps/furbabyrescue.png new file mode 100644 index 0000000000000000000000000000000000000000..79dafc640738444c01883ac66e8f0f2584a45a57 GIT binary patch literal 49891 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/geeklist.png b/docs/3.4.x/docs/images/apps/geeklist.png new file mode 100644 index 0000000000000000000000000000000000000000..c6579c12f6f37e10ab1a3f667e33f70fbdc87173 GIT binary patch literal 27911 zcmV*>KrX+DP)=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81RIo`zK~#9!?Y(!LWyy8l_pQ45<=1(7 zdgAWP&g^UkumBcm1%dzxP$WcA6qBWoEK4SxK9nt)hDqyV$sb#mNSVPPBubV|fI%V% zkc7>EkC2EQHej)7cEaxD&fPDEo2vZBeed;quV43cPuN*3`nR9ie(&9T>z+DQr|Q(H zQ|E|3{^LK^073}DFeHj148y>-ZM4>OuXR6Ce^v%$4!&SK6 zgMHU`P>)-O>(JFl%T4oc%U4{dFI~3=H%iy;8q+**;J~KG*;NsH*u(1&BJh2!*^nnO z;-=x>yF#=1-a%;=*S&uvNzf@}D^3YjCX>~weEatx7vE(;sDjUbN`5{ zh|X_au^K2>50jes$GA3?Ur|2^|g^wHT2GHdDlnFP4jMuha>2egWT0aZ7BK* zAClMJPo0u_@9MixYqk}F{(r;hJuCX|A7)^;Mk8L*y)OFb6+<^%Zy6x^J`XT%_}RW2 z26)${Z42J@8hIPuZIXL2NS7EadJ_%3kHfqhdSCxf!|&OacYPN}(KSrpDBkJ5qPFCn z-kNvAb-5nz#1Oqbnm1^ZJ*ElKM^Jy|Iv+$|FYYy>9(=RzFKZY>lHOnME))7IDMmDE z|110H6GN@g-^uzJtcS`QMPEN7weFj-hDLlb{8@~qZA;z_HEOTnhNjekPCE2lm&W1h z3^aJ(EUh=l806h>=hhpYcz{0o>N28T2m11Ec*hQS*ME%>We@SL_i+U8v>v>#$LkGx zhM!a~S1F(DE4G8(Ln#D%jjC|+t_2Ch5NFx{}%)^??fSRL6 z%Hn3m5B2U*?Y%J(cGCzsYQ)|J?}kYmg^|msZG>ke|E|Zo z5!D_!kc}ACw;b@c5V-5{u3OG_ycvZibv z1-2SpMostKvU^i)KQl&r-n1qeUQBHna z_|Q8C2UfYs{I!Yr?oY$_ZK1Ob6FN}A5h}{?h&Ze_c6Vd@b>Xe(>ldo6Xd523hudp- zJu6O*js3T=&xDLZNZZVJy@J@_)_g1{?uK7mrj-h9Vg=(00{RWtUrWS(&(BEdm z>!nSL>TOiOQ9SFXZPX~+6MQ}59ew?7cricByG?va1_pDm;rd_NW!BIFdaH)*sYLyq zxQ|K0qvDR#Cq~~tyapXL0*+o73^77)Zoq-QJEY+E*fF%Q-=roCJ-bP#9yKNO4Uo(s|RirgJsHr zhet|M-)GVHZ}@tD!JEuxqolq6vmRn}cO>W|YE4RA{_msc3&RMlRIhR4k1?RrjC5>VS6Ndg`(H-w?elKdV+DYXL0v%;|QZD zX*elgbxY3o3N#R_#L%>raP;^7fi=d>3Wi|wqFr}3n{LO!`qu+gXQr?$>rRvMx`z-D zg%P%GkG|gbxi@1drEYN6NYt-L`BZ}?O6|+k!xfZ{af}Q_XO4n1hiB#ifkxeF{=BBJ zH(b1W5C~$mv;Jplt#5d3A&`Ws$)(zpoGpKWmF8JmafMh%fJR_oOOKqhkHgtFbG-0Z zC^-A~W{*9*=5fPTDIp}K_GO+}`duzmzd@+l2q6)j|GImSfoibQJjY7wJm(3*Cvr?0(q|1d^r3OMG$u z|74|kKIu@x*z)dfColO|_|p7GsE4aOJo#ftVbL!fQcA)wWOa3wdaZ`zx=c<^u(Y(y zXFu~9-uu4yap1s#8x{_&HRsNr<=VAtyy?+LNu^Q)g4b*|dFGjC$mjE%I(2H-?~zjO z3DkEp`m`oek4dGS)SzVG`iEG)2Z z-wcl9zIu(BRBnW8`^L|k*N&S#czgG385wco8L?6Dj-yrXbp6`BZ&+iv&Qsiy)mq=O z!t8(XPKbzfz|+frz*6%Jmh`x9>ivYur_x>^?@klMEtcwMXhjvK(#I*d`v~GT&9KDb z!lS&j`dQYRukiHpA28(|V5#fZu?l4O&muUriqFZhq~pJRVF8= zkjX{>j%~BJxPX_=Vj2?H^$-Hutrl?{v9!F(?Ed}8&Pq}W(c7c39S5OxZvotH)>&Dv zFgLd!-MMFdeT}h+DVnu1jb;m_leSlJ2nY}{MR z&>M^IZi8Se&U8d$QGncy`OS)(@LEOTU z4t`W;y>*d#xXSZuf6AnHH&U2<{No?zxo4jxo6YjGKl^ih-}k?V%aE{ns1yI==6dFBE!$D5a!Yt+KMR0$MXMISIg%Pd&xr!UFU2^NbaXWU^UI^A(Xl2Z z)!MADE(4%q#ff`QQC?Z(>cRr9m!@8;U^^b6-^Q|Cs?`d!`{$^Z)=1^YdGORdoIP_I zX}O>jNAA7{*Nl1U+s{!f7Ack1Sy^2{M**RdxVAyF)u!$HoV@n|QnupsnU_IIY*SLH z)>vIzC2BVb;$)C}L$1IpFQ2F7hqQg4`Gsq=n++`6#q(S&%f@vqUU>dlR1{IG*U03@ zdE+AwCjxv6uq$7wSVx>Me+fUXBZWc5pJ%1{G83soT&g_Hb4!25Oy(pH&-@6JsUs}Z z&+zSqKce97=Z&*JMyT3ct38L(3Lzv{>Q7VhFOy+EFTL~F*(Wm-~WDo>ZgC2TrNkYQsLkK z{_pc=fBL7at*zm@E)PHQ2!HSI{XHh9rUrzf)oSstKJpPh_qosU!4H0rv9Ym@y2ddd z{_ux+@`)$;C;!Vo?X5Y!^{sF5uRih-&YwF6z}(y%|J8r}-(Xu7jYfli{7b(?CY$BI z`-lIKcfb4Hw{GSTg1Li-Y1XT}a<)W1pQG)!3F{5~Fv7MB!YIaXw?P`z>kTF*CRkcr z!*SDCmWgS*WYdBm2#Lag@tOS;^I2X#^8#TMBU(+OSRtbTKa6nPNTD$QmK*GrMf7D%}^(lGE+He+K&mY0_Cqlk&AJo8sBbMJ$1V!D{(%U}H(<6{#9 zK}af{?hI--u2K!`W9(S>L(mAzEH+OkqcR%XNHgvoB32>ay!v}wD1VI$^VyPuiN zah{t0Lta?k25wt&R>4v3;dtI@f);SEq?arevXg)=5O+Qzx%t~d+)vc$Ok{j z>C>nAi$DK!u3f##hko%FksUQCjv_wx(U0Z*hCwuU06z$@Y#ZCM(JG?lhl~~TL{W;jzvCT9DLb>U=HP*Y1VMo9*q{Yc z8r*&C9uN}CG&p?t2<^5{6tqzaW~V2RXdZp^Ex4}3+<^mRb9uxq+y*dr+;~Dz4_9c0 z>xd2sS}U|pHU=%j0|b_IF{KR%95anTVhFqQ8>qfTy3#SLtyefTW^wZ5Nxt!oZ}8Gf zFY%{;`lr16`@WCG#YH~%+0UZ2W^8PXuYc`pJpbHt{O!N+ZYx=fC{R9654?m6a7f^b5bhSHJpIzVP|aBcvpbV?O!G zPx2rB{lDkLi4*+dFZ~j;`}c2NOUOYN{4fluRw_7-!@C}TocF!&eQ2$z)oR4CBAds+or&2;7%Z$I##GL=5Ybov-$-a)ihJUaUmWbG-k z&LnfW`zW^;SgfDv9T^osEm%Pj@nb*!<2?QJ(>(wD^ZfJw{eS0UAN?q`T8-u9Wo+B# z``+^&zVn^$AcWw>7hd3h`o&*FYmM*wL{UVkw9a3C;S1F3b#l!nANlZyJ4cTN3kwUx zQN)D{7eH%PS6BJiM?Xrt-R9m?r#O80@O3+J(pY&u@IybuZ+`g0{L}yWf95M+{xU!E z!4Gom?z@xv2!S**x69wcn-OzKjrZpbVuIhYua*U5`J`>C>kHD3wY8+;h)8{Lo+htGxdM zAK-~6o}_w`w&sRmpta_wf97YHo|)kjAOAR?`jbE53!ncy|HXg#Um|YR zs&5EF2*SXp)@V}5=QkM-wzA08YgG^?nM?|;6m_ z{8j@k4NNI$G~0M756^W6=&ROh9ThGlm&;=qa;Qk%IS3R{DOboBib&ZnOkGQ{-gfqD zHtLwRi)9+U_c!V_{2;Wq?4KTEetr?8M8y%M^)-|*i2OFiiD~Y??_QSYuW)T?l|n8{rB4A@Af!?*apJy*2pVN7 zwK}G0(r7d&mCLw}L#x&1=&=(VJv6ubnWNKJdOP1cG1qFX$XFA2W`Q7R0D_D)!F!JW zcN{7_f)pmP3Q$^g)*G7H?7d8-@4}Q0Qb_8-8eh8fZ+L0#vz-k;$(VZ>Lt0$9a+y-8 zglU@m$shd@TI=4PLpq(|?eBOy_Z&aYSHApZ{_x`;r%)_%@ZiCoiS%#R?XH@=aB zhYs=dQ%~_bANv^ZeCIofqKIdnd4_kr>s^eGCkx_iF3X9NCwb$W-o!V)@eRKI^{?}X zAOASx6B7U|EH2V+w}E7h@zt+>mH+ospWX`xii#Y+|5{FcX9 zn!iT1(M&u68a0~D28L;pPI+8eyo`_rW8-7A8g?R={l zL!(KVV@!F+DEn6d&0Ovw?jC!L<;Kf=d+|>Ijc4YGbx5ot95Y22w`oOHX0xYwXy%8x zfBFNwT>1*3YU3JNW>P0nO7XV0zn$-Y?|XUf*=MQMYNS#rX7b=AIW{)NfBv&S%gZmn%W+keY%|MqY5 z{qKD*k390o4GTr5m6+K#OSRtONH#;QR%32%4%@PbFkHI#}emCEefKZj$R?3wfTV(q?CO&;o)|Yyj=b=pS|+SgsRQGlkejL z$9{>+m1p?eg5rBW&Lq5t7SJoV(0yz`y!ZE zS|XFl@bJSAbLzhPh~t=Ve&ZXw@WKn2rpa60@)l0rci(jzBUXwyjt4A4!z0+Xjj0r2 z6k%D`jx1A~@6nV>CA?Gy*Rj|t=*_5w`*!cU-df>$*LPo!&G(G@t?m20_0cd|%_dQl zEE9Gm7$68$i_cy8WnQj)g{-}gA3XLU4(1=G9oA?^Ra`TRXXSxpL$L0zfDmNuN&Kk6 z7cPF77gj!vYi4=x!4GjT`vyQ$sZ{uvzw#?I8x8*2kNzmfjvq%U#pxGcd4p=wZUkeOJ_{OKrg-DjPqE&xP{{&^xW--!}j^@HkRWcN2uJrJNwGx5kVMXng&r6 z;kfR=Jl1M8k7YQyKwcI-e3wy!yuJPZ97#71ea=0@}+CPNhP?JY~o1=Q(DA2 zCQ@y*Rv6O8lnz=eBIToWh#_oFjsGBTnfW_dGSzFWb7#-;2Y>JfeEn-*V|jTQ-}ezx zlFMef_uhN?>Hp+E;T`XI$LlUw!;Q`uLI|4m8jH&-c%DZTg~_gStVnq-jYgAZqlT9$ za$t6fYuB#frqTqhCem^cI;Pe3F-((`=TfUT$mjFat5w`ons%#!W!cnfRnqAUAh0ci zb`UW;J4>@xX02Q!lk$?iqkNufWu3KBjr$*XfXdo3L9DS&gJwG*lX9un>If;xrZY5} zHR4#~dMO+`Q3Hd(r`2j>TPE}K^BA^+=Xzw*DWqv3bW9ku}?$l;-(opJBaRC5&P`&!bi? zqY${3MZMV~olbM_eGd{fOI%x8L#qgoG@A{iVGu_V(lC;pb2LF1(QMT5QdwNbB8noU zlr$Q3q-jAMBP@@1yzMQVe(u{`o?oU|C?F;Het_dR*j|Q{#}4!S3#V~xo2KuhNZ0wh2L&dt2db0H_P1qS*~2Vfa$oj8x7LAJg#k# zPN%5(RfLoj^JA1NRVJsVux%#^4iE$^E-sPH=kZ*PV>_fX84860wOSR^FtIF)OfFBe zUd2gek!X|>OifRd&*ku3n@XihtJP*^W(K3<2bIa?i7O>+JA-A}SZ1&(pT!;qkqMo7`~hZAfJT1qA79=hw7;aCB2 z9AlU!g2eIAFbtH65z^Q;EKt9pql=#9OA1u1I=ki@<=+T)GGoM}RH-gQ)0xb!b$Nk+ z&H_(sg+?Qh2$8H`_M(G~#?4x#ZiPkZyUr?ggV>E=45(5aF5TEm(a?Xq6|w2a>mF`B zZbgUwUJ#0%qB}_RY-+u!>rPX)hdtaW^!e4v!Qb~rjy-%2qu;xB$u?Dd|7+A zaSTMKxf#FsJ?!E2ie6CXk&zenu!rv<45(5&IgPc4J$x^qo2Re0^Svh&d)Nb=AcCFb zlzT$4hdm_d&KS_=5;E+jyoWt}FQd2fy=R@;!}mJ+RVfJ@Q8o5X$?f5L8U3o1*&n&# zd*#5&uAwzS7-HLYlDatx(FiQl>;*X9DsbISt$s;nrU1*b2k#wG{?14q)BvI=L}@S$ zqZfWZ2m%blys2o3uUDA;0nn>l^n>5RpRI5rPE|mDJta>K^Wn> zZgLDXRs?}hDw9PJQ>i4$HsdHnN`oK>a6PY=(;Wx2i$!pq0(;AJG z$(e5{B!-#9(rq=H2r1D@VVGv`*yg267s=%dShjmd1HHYLvFAj%4Z4AiS60_46bdw( zO&r%l3XsykvP>K|-SM$exL%q#O7g~eo=Ya1$2Lu(Fr?jXlgk&#W^*)ZWx^Q7$MRGv z6%c|ENd#kQj0XNdYZ|lIcCln*mKYN>_rr}o;uce9UwPvY)E%7E< zzr4QDF9&zrSE}BM3BqpdsXI5v+m=DvHBefkR804vrXoR5<+CVE%on(cBf~z|raYZNg?M4Ps z0li+lu_3k*&c2s%bi{8;X&yN-!;k%y!vsN_uoKJ}APmB!VLD`N%6hsDlIVl&16KDAcT2wG_z$3hBdwZo*bHDuBbuANwS)+;S? zIggBEvb^3PigiyN$)+6|O&_I`Xc3lW;93T?MnD)Vj_%J7G*lEteEZ2KS(u+^YI>SC zJo+d>yUCSn3ls`PvbijVlxUp<9_G~cQ>Xh}F?c?hjok0TnfN-SeS zQ!q^0ag5&;2MuGUg((D))~rM!v$lzfVpgIUEx^!l+_sZvgkT{E@s%R(ME!0{LB&lC zv|BgFMY~aFd3B9kE>9}u0f_;pRR(zWv-4ykeHwoDGJFp%v9uNFnRt*(SA?j~~V;rLioN z$-K)Sf982!S*#6YO^TIb{_0i!<6ry*fBCu3@#eR_m6_RDbkyQ2U;ZkoYynGxX;~Pi z%>(zH;`Fmm6B;fLoI1&q-+F>r3v}cYMghg?eH=e}i0^#oIbx*Vu~1{BMu%rPG!ABd3~LGAH1I{7td2JRZ)?q zrD6`>eGjRy&gGQ~wqX*e7*m2D`D7>N_+Q&>UPHw0oVE~`)Wd|7~c=5RDBk$ zI`w*si&vJBVG|6K2kx5UxieR}vRtFwjCsL`DOFpn)&eeGbEwqY2q{4+)=PE5^*S#G z5hw4O#xbDQ3aHhaM3F|wM6C!Tg&`%^7B$VbPY?vjx}r0UM`1`DML3RwR*K@-7*Q0F z&lWj;{5YoVa{1+R*r_ac-*p(rv6(w`5NW6IQYq#R>_-?Do@EflF>X3TE?;1Fb{`6f z<9cWfj-e=5>dfvxh~=h}1UpeDg#r)-5wt>@wH9g5;raC{-&w8FZu&g8R$|^U$T==2 z^J%`kw8~Pw#cC_00X8hj)8w>RY_S+;EDAzm4=VXk8m*6nrxxSJtt3s5?sFU3P+9{VR~wUTsp(d)Fj11 zfoNtwx%>p#REj_=vV}3spoOxMfk6>bDX(KXHe(a}Ue*3LT%Y8RzVlY8D2iydT3lN$ z)Aj?ZwL0HQ1NG9(Y zfA>A`z$RX5t$E3^zc{X29wz5Dvhywi@X1Bqkq6bc!K12Y9y*BX?|E#{^R zeaps#QIliYZG%ns7T-gk`>*#ZJ>tGtX^L65#}r8PBH_VU%>v8Ox$-Ify{h4BF%o6fCE6`-TBQ`-+36LpNE^ zK)Je)1~FuF?KzLqXPoHNqx%l2i8YK{X6KP4YnG5hYL%3v)9FnL&}I!pY`bh22;roM zzTakaY1dkB?0k1;j_tFy-g>nBsLxyrf>(d7qtV!wf#;a7iR?|XW3FxZA(7gc1vYrp zrF-yu_qXBe{m+dmhoR^D@9q9|OarfDss7_abh%HgZ#PGcuj@q)V=@hVHkV7xpUYHpR2? zdym-U>$2T%+m*A`_ZvM=y;Yf`%G=31ZZ(ZNt;4p#xJU4Lr}XdY{w?m?jwd_$KB}I# z75!(vHxY4*-qC8*snqHOK|sDZMkeKv1Qctdl_H8`a=9E)6cWdZFbD>Gw4`C6Rg4gl za;b!u&S04aaTF583deELTG47Yk*1kM0PKsuo0y*=@krMgMiO!+juov|6Cn-KspRlY z6b959P4c-Mjn081%S`;HqA0`8zkX8_qO{aSa8oTvS zDyG$H<9QxZN~DwofsY?VWYVc#c~VN^IL464!7R^9Aq4n-8;w9BupK*bNJLYvRLSLY z$WBP0TCGmLP{5E96-Tt%0qJzA=YJJO5uWQN1_-Tt{Y6SayB$y{7C?h(-hP*qUaGNM zDUsdTXKi%_rD6WsHKbu8&;)^xY1w4+MQYUwOUo-vPEAuQuM=sAf)K+rIe6$0^H(o1 zF}07C#RZyvfS2-!{Qy4-v26#T6+sYSJ1$c*`ygynt~EO6l0&2rNJA1w5w`1L8j>Ig zX}4MkDVd(xhbcA7D=VZj1?rU&mo8t$aXd2V6hY+EZYA`ZGBIUGafCEX3@LHE48@$w zrOVgQT4UKZj^i;oF~-%)m$2LvwkfGrYfR4U10UdlyEi+$4*T)uj(b2L{XB;>~?aHZnv;xeA&pwXl=IU>JFsZz(bExc5Q zdrzJ~%G)yw4+zGso~E?cq_a8Z_Rq3bs^Gd_GP0@|%d${fV>>P?j+huv4zpx4DQcA} z?JzlGZJ7q1m&Wrvrl+SUS8L>Qd9;qH*Bb~akwRjcCR!;n=@foblgk+>rIOJaIGB7_~}?*?s#kZ5!LRh{KRDR!AYK*DF|#hh<7k z%S{ADns~0o#P|g1Y=$TbiDFGUm11UgKLTj^KIx1mo$elmy*Xu7YmMW$OioRc&E<(T zq*5M}6O(wJLl~w>wSCf=3~}hw@&jzk#&sQ9trkHT5(WWI%4T9>0%=H0+a=?3_uQ0Hgh9A#b8WNP>_s9pcd`K5IW*-`2|o-w9WtT4SS(PjR;X4gc!m(P>Sr27t- zblz1d6U7>>73oZtdU=i2QjM9JX$-@}5Q=J}McQ+TIs%u@WQjwca=DCYyEvBFI|D6A zqLzfAPZTK%#UfHDD%Co!>m>>7+YOq{L~YS3d3UTdk zk84*hgJC0d65b~a17fX_Lg2byM;G@QpPa%JG1XcFAq446hNby=ln}VCOR+dc6#BGU zZMp}TTsMVj2v4%piNF4e}uJi6lADgA*w(Fc5Fcw6S5G##on9LoRquFd=_&$pZ^O&Z|_~aCZ&@8R2A_SC6WgOR~=%i3eCo`I1QYn{N zn7@W)CAzO=I~|rtJ~O0sH0-;n(X#QONnTFOe%wGG0h??aF1OVIYN|9fTY{ ze1v+rL^}+bnwsL`rAxGZAA!WN3|hXA=Q^}}pCDG)LQ$^Ph@y~OVFK6ET)K1(A(NRg zpUWW)6Vni!KX(o{l>rr_ksKeJ-2ITFVye|Djh2sT2pWwRmTlv?4vl8B6X{%FIWC!8 zo=Sb4i&y4Jr!(x^w+~?$_>DTXS|ZE~*Dh13RIzLq&$F?d46dn}Ut9rVY{$ivl18h= z+UhE%Wiv53MG)30SL;Z_puD!i>Us&oG*C)#^ym@7pv}cgB}~(zUac@Wv!9eBxqSI5 zUOI)+0s~E>(ZI{(v2Bz2D_3c>Tcpxy3}FDtre_#M1YwAZB7z{|=-qd*va~?E-KNqE`i#S%;mPxbK8nEJMt&q~hwk^Ui#4rqkFvO4& z%d*irCI})d)4&e`Ow&S$ByU6+tq8lDV;wcav27a7CbsRMRE+I7#8C)H;wZ$h zEKo74Yb8uml1gVVq{MYy+N~CbX%Pl(+CfCha{)mZv}v_{@`VB_jvTs8T{equxMB1Fb@?UR_{nW*;ffNfOy~ zqvdD~NGwYdh7m#tJkKSLRVN0Qz%&h_FiZ>yQc|zh@G@C!(;x_=j=B|NNTUpubv=T>M`?wW23l!c*Gbfvu%mVYrj?{02%~7gv>eAVrfFf>CUKZVg3(%GnpSfD zzIVjfq}8ahvRdZQk;9bD~ zwfE0LVHhS!RkX(Lx{`F5u1UihG%k z`t|o#vxVz2Grh5Y4$8lY%l`^GDl|o^Rd@hryPhDL%?wB&useyHil(M%r z>i?~4di4E(RLUD@v_`##VcJRjs6IYkPcWh|WMy@QY`#dw^U!E~-$!>$oSAGEtzzO> zVc8a14JHF>G@7K+DYS}d`vG1jxlOkdb?XoWK2a3+)G~m;4=^mVmk*@ZSG4X7SSDc* zU|1HWVGzd=vC@RTk7+vts!lgpT)WjGh+?vt%%*jd)|ytc0n#Mh;hzwRN15)>>bKiT zS_7>K+HF$l47R=DMsu@k47d#;I^!r}d3goLv6!DAxRG#H8n zchk5nQ9`uVWV1Phj`3U%DIt^wg#Io)J=@XPwn-GniQQf#qg`Qaq8IpVH?VCR*L6{*iR#RFxoi?3&2c@# zFd~)CBqq*E8AD1;%cfWu!?7)<_svkLRM8r0)f%3cLdOa}2yt8wG$;l6ViCu(FfEfx zIZ>s?#wT!Hmwdi}rh?~r_-&tbI)#c_w8IE1l>)7kC?PscKA*$0O`<5I)ozncXR$03 zQwn0G$>#D*PK?oN)X8Qto$x*y$4isRq?wqS!7@!M)e5Op8ov>fN_m*3fnnNY(ixg< zAJ=i1ni#)z0>OrbY+#MiHAU_;KgK9kYFP5F*9ivi*@$D2OxJ^vSG%f#@3)bLnIwnY ziLffw$#UfF=zhQ5?x_a5XYKA6f;(Ab44ZiS`L^Q?TCF>?pM6sv4!1hq@$UNxqvIrX zaHFbJtJ&$d-{LtzDtPY zIobDn|9zU|`EL4vQUBx+O>w6T)f-qk{#j!CP?Wa=L6q=OjNoCHmbe>>HtvKB-J*U` zr0_#UJBSIQEJMQtqg))(bjAvq-65B|8E~8i>4MC$Fb7VFHQN&X(SD7xl z*ketW|t6USgUKB1k!sLe62f=)5Wo8OMqz zPp=aon9NxiGNCkwFot2JrmC|@Pp*+T;Rvl{Fq|KBITHvQuE@K1_vfREGcM( zF;YMrYf6ofjAxN`4JwTQEd(jYi!@#5%d2Nm+QNpb^KclzrA45pOzPL@Q0KHCL9JXer6N2Bk(wtdbGW zwGFbKiEEpvND{@0%S%n7Skq|7XsrojO%N)M2*Lg_=T*t=r!}NKgQyj8aj8i@WnmhE z^{S8Km{=10NR!JsScX8Fl4>JhsoVw)u}N|OEOLAuK|pPH|j8~3m+NgO9?PnZ56R9I%RLmhXT%QQMU z&O1M-&U=Lr1MjsuW%!Z8lnGy=Sohi>p<5^32_!KRU_H05{#R{aQ#N{=w|DCD|xmZZq`={UIXcj zcZ%JRrThQx;JKaLH~jwBCYNp;*W>T4sPAi?X9MQi+kI$%4}17-#7(6$*4+Q*Pm-jRjk>lx+^H0T~~4Mw_z>|qak*nsRmVF!B)@ICAShEk2)4%hQN?BTl& z0~wXNKU{YgTPxx_obLC#7Xm}dP0$;Qet;{UF#R1aTD7YPB&f3)gjf&kV!57`dByIsCcn?WwgU@ckq{@Q8T3uSN7*XwCjgE2XydCX-!ey_$q7)e8tF zh5~+tVMr84IIfE{B!08O)yr29G70s6@aR!2BXNIrU6&{fh$4k$8C<=5ndyD|v23%K z1J7|i4C8xmTPKb}u3WlA6vg;Kz@eje_1yPe*X`vm=?2{HrWc6g7|Tf_GWu;liOwjJ z;BW|uAz^i8g~{m|qOcP{TMF8(b`nkgwU}qH&pO*vrEWM!#%+`q*$KaxB#}`AJ}_&m ztE{iAFgZKN)Z{qJiwn5v9Am{Sm2!o4qsG;h6{0YvFg`}3RwW2RisR$7TP+snuaV7V zDX*^)E6vot{fv(nU$djx?SK%1(%K5K65MtCIE`ABR;|KfrAiov6vrp1me*0S0wGZ< zW@2iJ_0?5`5I9~M+k|pC3D#|(Xa@mtteKjcAP7Phu3o0uXyT;Om=YR|CYfA;xr1}B z0R?i1A0!h1LTsG*?&H>u3kupTn)T*DAcZjSiK2~ovi;Lj6o#~#tsR%YL7MIfNVnX{ zsVUNFk2sFe-Hbpfk7~KZ%IX@WwKZY|wrx>bT_K7Tj$SQRa)mKm*JWjK5zDqoryYc06ZuU%*CA|Ms5qw4s1pS?xm<=?wT59BIIfL~ zO$?8&xOz;EZ6C{Vke%p-mX$;x7ee%eEC>Qj%fhy-SEZq})>uLgBufe6 z7;&4k1Z_u;-)#Bp8XI3)0cPEfnVJg+;6T2vfy_0lDBW0T~vX$;dK@Pl67zOE@> zt0YXfGz`MP2L!fl6}n@v=loZH_~Mx{}L0m%riI~j<&i6ITc z=w-tZQeqeeaTIkD8%9XOy6NPCU8~eEhAkdjT28ik=GADN*OFj#m@qI#LF{wYZX>y-+L+=^JR{H61xx*W2 zJ9*}N65H@?5CYE|Ol`2cGsmxSUibB@f!MXXMXT8)Xty?v02;7e7sqvb3-M7*GA#?$ zXKm{G5Oo(pQp&ya39m7{t_PC7y4`R(V<{z{`w#ztPyb*43Kb6y21>*C|E<5p5B>eW zPta~-**2h)geEcxrWOPNW}IZlNqH_|tXQblX@?PGX_tcM(rUFxXENK;HY!2-KIrBqr;PS6FBxKMI3&&lm`7HLwDlb_^xlsQOhmsf1T?+%A`#GZHIWH zA$Ox8-7xJ#@3_O7)<7S+@pQ&QP+DB%(zD+|2x$8omtx?NYuC_9W7`f=8=U+4Ro1T5 zDDKa4{B8R?n@16rX|mW1_}I6;!}*nUgcMj(@}m!&;LZES2?HO?v`|_RMR6~UF&bK} zCiPm07f+w#mGkFF*%HUGu%tvFh@yalcOB=UN8d)fSz-C&c?@ZylxA_^Dqc2ArdUJ> zFs&4YiD^=)46SApAq1ySpXT)G(`0iw4jw$niF@wpC2G&-^PD|*j?aJgGng`2xS|x( z#Ue|kb%Z6!q+IsT9pO!nzGdelZ6~{|+|CPBYoaJ3P@45Xu$|bYq^95+#9#Re;_0V1 ztsOO>L{f(Fecy+5@+9qcNDyh#o`LL(MHIzJ+^Dz{6RI=D4R{aq?~r!~EY*!$+JRw6 z{2-?3D^iYuZ6yo#dOKNbrEP;CQb`Ofu@S=4G{k`5NGUOlPJa**;t=gO5w-`G4V|@a zf10zM;)XZ)w1!;4pJ1iYJ*a`6MX9% z-yjMCPMkOaDhc{_{>&ME_5b*n94_WKP)M;}t#bJAQRdfboLgRCYP!Jt-}}Qn`sTOp zN(FHpr<3na4_EmYkg;mou0;FvddVFozGe7%!EHtOK-aRnWPGZnycy z*S|?)P!?Tsg|mE zUV&?it1QhgvG2&ej88+O+2omLp5bSH=4W{9vBxMDi(I{Wm6u+6DM=z91mp?@ruI#9 zVE+{FIew78_0ChQG!$QX?iEUvDk~=%wI&5y0&suA2sgYXo?d2xxA(&{6 z6&z-AE?EFYn)hf?C{cT=+@kJhf;ksy@~-^_>Osi2US6VEaJg%CobirJQlJ#-(MNHA;0M5U z3353yZ+HVL45@zQE0~WzPN+48l*~=I_|Zm~Ppy;BQLL#pBMO;~6vC}`%u*%Tm@TB_ z#TQ=S)1Uq{?|tuk$!4?EYE_NXRP*F5e zIJ)R9zIU4+LkPHbHQ-C1Tc9|$f@MjrUhClCnLL(5 z2u&2nJTy1MPrTt2fA+$8e&w@YXDs7kYRS*N{Y@M$rje$^07R5js^8I1qR2VmX7Vgv zDKj}Xja^zNmG*Fmc<|U^=KY8)FflgHwX@H0;lc&x*UB6}e3-LqFHl=6Gc}Rp@WT(1 z&t=hCVc9lQQ&XHhdzQ zV2VqAn^mm{ghuaTn^z-<ztXnhq=i*Z!CO^l99s7-_LaBzGUMK_{y0D zF0R&jFaAjJMIJGM*fGU%J~-J87^TXE1}TloD-7v^0|x%BF>iZFCs)oKO38 zAVIQ;twxwF`X>pqe*D3(Wwa>dUEJn4 zso2ELWwGNJZAwI_5i+?u>v;i;qc+Z zRI62_l#Gv$Gcz-T=XsnyeVR-r!&oP{v1NN4oSxyxSQ@PY-t(3Rahwbvd*XR$l+e57 ztI$XxvBt)jQVxw`fr1m_r4LXFN=Z&~Cqup2K*ceo`9Jw~IlMzz*p-s&Bi7c}@mvoV0YQKc0#x94 zaySY^6cI%shGkzjmhC|B>tR3p;iw_~zv;fkU>rp}{x^P{2j2dU#8MCis4zmIKpKoq zP9b!X=spMne7{ZT`-%IyOwK;1(kbFt(XLfF;F%oGP9cRPY&9vjTNqZNpGPVt3ZtIu zvyS5=$x9ToUiEQPDdy{SzH?!oBZu;2bPLBBqj{}?lZg=s!d44YN=zZJgu$8To@f5b zC1#HwX1!b|%BFj#yP_y!dU~3CK2NLFBAd-75xk>_iHQk}&dBPR7H%d>RSUvKfOI`n zqrs)sDy!=iBB_w<&H-5@8#v@2d6=Bm977;DfDjLJD6C@|PPY#t4TB@oc`m$o1|2-aO@3l*qsoMfCkcO zkE|*%DOV90g>r0^JB~1JT}*!=1kFaB=bwF!d~uw7%Ar;*qhf_3$G-Ur^mvrl}Hg_O&M z%S#+Pk|VZEDhp*=*O~1LgJFb7V?&Eju?g{ zlSvat0juQ}?RGoy*^4!p3KfP}j>pvW)VAjD4ca&M#Z155;Nqn#q|zC3*(|MQ6T`N! zEE_|D>!nz_dIiHxlg*|{rBe9KCXrIak;3yFs`Umb&!gF_)Aj>g*Tb=`#H@@Vysx`${eFKS?M_2`|otF6^j!bzxP3&d-@xs^C>Pit6VOXX=gEayLTP^ zV?c%JH;jnkYssPgv@`n9PgjV*z}K3x?^F8Hm(U$vDoFkbffj=B7Ia#TCWt|04q)2T ziG!hGprynQqk#iwH}xK^@zPmN-giHc49x9za(Xk0Vm!}9DV3}bJEmanCR$k-4kz?38;M)0DFl?7oC-33er=OzXN91w^W~L{&dhH7J zMw47NOB6+fVTftk9KGuZ^=g@R+o#cNVVWlCT%Hrh??wuV<2YL$|JZTvXJPQ>$A6Fq z-cV(Eah=+@hv_SrZZKJ^anF7C0vctxSd;siOBM0`Hicsku-0hd*e1swc^toMd)x4#TntA; zR=Yi}R7@B~*tXr-Wi(irzk-`7Fj*{g&IDUHj!m^vpAj~X4mdBU6o6S#ML+q zgO2VlaBLgZ$zdmiNH($hn7Y+|%Jn){I-5-#75f^wn*dRFvh{S=527>d3Pdj_U)RQ> zJ9f}6{r#T8UG#g!4$vt?5^t-U>8Ve(>0ey##JhGUE+pM^)H@Nnu1olJT|zoXn{UVa zcT#3gu(r5YYmMu=yG{r*@D92M>cUO&y}B8d0RDe>QW$DW?`84;0000 /dev/null + then + echo waiting for manual firefox shutdown... + fi + + while true; do + if ps ax | grep -v grep | grep firefox > /dev/null + then + sleep 1 + else + break + fi + done + echo firefox shutdown detected +} + +if test -z "$1" +then + while read line + do + func $line + done < urls +else + func $1 "$2" +fi + diff --git a/docs/3.4.x/docs/images/apps/growthegamegolf.png b/docs/3.4.x/docs/images/apps/growthegamegolf.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d6e9fb7493ce38c487cb2f31416838fe063bb6 GIT binary patch literal 43441 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/h_learnboost.png b/docs/3.4.x/docs/images/apps/h_learnboost.png new file mode 100644 index 0000000000000000000000000000000000000000..2940dc31489e2f0db0857ecf2c32a2dabb907b69 GIT binary patch literal 12727 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/h_mcds.png b/docs/3.4.x/docs/images/apps/h_mcds.png new file mode 100644 index 0000000000000000000000000000000000000000..1ac655377ad9e784895c1d0ac1e74d46d4949752 GIT binary patch literal 3904 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 O0000D_X* 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/kyyti.png b/docs/3.4.x/docs/images/apps/kyyti.png new file mode 100644 index 0000000000000000000000000000000000000000..f74d98da1346a95376b33f6bc6118e8864261b4b GIT binary patch literal 41966 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 ^!Ew8_;FrDA-Jwjzfp_2R2 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/learnboost.png b/docs/3.4.x/docs/images/apps/learnboost.png new file mode 100644 index 0000000000000000000000000000000000000000..a6c33c8bd41f9806ab255e4afe5e0187c65810fe GIT binary patch literal 31434 zcmV)FK)=6=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81VslAEK~#9!?frMOW!HJw3I6sz`R12X zy-KJmBHVoxS(Bzx-|S z=}&)J(}OS!iJ}O@FtBYKtu;aj@}PB6Jbj)oGyHD2-j&+gsqEGCaizY8-=%F1|9dTc z1)@ZFMS8L4gKS*_A60H@hmo9Sg)JX!rd)pz%?Yudp z5U88j$Mv>3U4t4oAQDT|WPNpJHw4 z(rtwtSMyyrvfj1!aWi|l-u7?yxZX-&?)Fk^jbWO+`{O^(qo4Rm#%K4i5%_#>^%D12 zCYjuGkUJm!0NqxL&;Q=1Xf+$RWMjPzw?8PQ&{|`f<{NKp2hds*$1ze$;yA{#tZQx~ zj^pG&7}~eyZft{6ihJJiDDV4)zlkFaI_HjY6gaoC#6%b{*KT1|#<~B)pXA($V?6bx zzd%a4O#r%9!Dpv3S88Kand_bKn+f_R_i?@L-^g)AQM3&)u0;tk3`!;cCUR~1Oc4YD zwrvvxL53LD(od>vl0)3iF1(M%Efl%;iJwBc1)N|LYxQNe*3YuwdQ{F`#(Vj7DsB#UCGeJefrP6{#5rq&uM<<+%sS~!k_*;^l_6mcBi^aCJ@B7z_w z2m-<|!m=#X$ess5 zkbQp~$JsN>w$Uoi+Us_^_!$EE18t`Wylu{Q`Y5e5-sB8syn_41{|0&fIf^QxrrwF= z%<RfI@BYVY2?T)cRZ ziHQl8mX>fF2O$JUjvUF5rPJv!K0c1``!t(P#>dBrq6noF>+9>>bI&~-J9Z4;_jg?! ztu>b8@`)e+NgNgM%B!!j)o5bcF0Lhc{n+b-aXhlFG)zADk&iP`c6jCJQQ}x343oh3 zDV54hPES)`U**)P6BNegc=yA1^W2LsW0?kqX`*5UI_B7G#|Y!m8(3-0`#$_p_D)uL z{`)Tz#TviU#H&v7-bWwi+uwQ$>6DnCo#NQ5uO^EdMHEX_=BLLwcm6ELUOPrNj7Q1` zN@?En{txrOU58k@bcxevPg8HSD0nXC&YWaz^X9R?aU2sx5uou(D@Yp(<{EaiNzh)PvC*dftq$Skh*%o<_Z(trYmIKFlbsUjq*#`f zQIS%q#Knsjaa|Xs6wPLnnVA_((`0FBiH(g7W@l%KF%*=55^l7@?F3Zcygkd;(Q|C_8PPfb1^XGZw-h27T6MKl1!gR}=dg&Qnc;N+< z9$n9J3?|0Mn46hqVebJfQ=;M!q=RD!lwmMFHpXB4=^r91^W1yi1MJy%7%5^5Ltr{Z zMA+gt|M_old83_ezTc=SCi&dl@GFa0r_vBBi@6iT_&0u;bs>1_U;d9A|N56e2&Si}SzKJ?+_`fsEG)3Gu|c=n z#c>>5*TwgJOw&XN!G#MK*t2I3&1RG7>1mdimow7ZXf(1qtyYU52pAt9=luEe96WfC zG2AUb_dH4fTUa<PX9`QY;XKQL_1z!gFj+o_L*(AC5#ktzmXzWA9x;`Osj*`~PBh>@-{z{J!vrqD>kBn$!+n!pbd3SnDVriJU+ zG@4Bu$D!41(CH?Jw&O}Z@(bhaxx?l7_uG8!(;LK*&c^CE4xLUX>#I^5qg*Ty$BI(9 z!XuBogRlLEFVg777!m?Mpw(^z2~~4l_v#S?t?|YtdF=21Qzqy4aPg@xGFIEfRliAj zYLb=Zze>APr!n`<2Z{J+Egh5v*DPy7_Ft`i*p97g#=>_74!(Qdan{_In{ z`0xK$I`z#=U6AiM{k_{J9)6dvGhF{_+S{p*>*1y44z`&%Rs-)wee*CvT3vUO@?8Nth2iv1Gx0;lepz7`r|*(*z_#2 z@?)st2iaWT;L`I?@zS4siu%%pz7FkecpFF%qf)8d689Q_QmJ&^o(?0QKmPdRS8PoP zL3wVGi9`3{lw4vzV)M*#HqIU=^8M{-d>g>^vIRGiop`hQxShZKtpeiXKk{Q*Yeix@ z8HFRsbFFnE$%%wlgJB24eEr?q%6^N%HzNnQ6GjjG5Zj(hDN)&Xjc#9v?Qar!L2c_v z40n+InSRsgj~UhP_6?XXrAPcd8Z;xSX^>K&l+H@%9V!jK6=F1Eqe>;hc z;0Ol&brQLtxA{_yj_B7(%ceDC(m=1B!M0^j#z>JtpbKjYg+?yeEiiP3Ab5TE6wr z-zwLCzP`%ZNFJ(ueUVzL`}H8{OY7XY2Kps8*50$BZ%l-9woTZM`!w78+mT^ZTiF_Z zdm|n?4w3;6o|A*vFzEZ<*TM|KFgE4~)PI#BLXH|`$bimmHl1y%{>JNVNS$u}!QS%E zG6WL3-*$>%x$=EP7;LAH2)SniZ4dR``$myNko>W}Z7HvC(CKY|r<$yOT|HF3zo~|v zr^rKpqw8$*BCkU9!4rMPu~6{D%I1R(MJTO`}2Hd38H_f zDV2B&BxC5$)lOW0o=$7P95v-hsl19Xsid;Kn>@%=Yr8CEI+z3*a;H~1$h7esi#9OS z6zMXAPsf$ccps6|?baK058)WtsUm-Rh}_uqAi@q%xc*QEPyZoKVsKnT)4A>BO2?4j zu?#*Nu99E>;oUy8e1pZ)&CbX=`RVPmO}X+qH=iO~*<4%s0qcI7dc=X=qz8}7Yy;_R zF>(jO;3|m0(>!f!keVbjHcUMvdZ1qaG}lR+IhLe<;`b>|(pHX&{R}T?vFWpA(BlZdYH6r83(9}$UPdO=nNx=?(d1A9hN?l^w&IYMf!Z;{L>j_$tXkiUMFR9hcg3p$ykMK|Ija!SCWdft%QLdptb{h z9?|=)x2tQjMb+D}%s}I}J4A6}c*+$Xp1%=@Ik+lf+qrSa`}ueTn=aSOlkFEGWc z1B-oC)aNY;nkb&aF8>1zV-}?~GVe~*lc&jP9RbWdpL@k^Eje`%@kA8LMcBe#2{(ObiVW(dOM8u_68v& z!-`}n4f-0B8@GN!Kos?~I;jHYw%H$|XR|VTepLoS3Urq7W>Dj(bx&QJs>`ILPg8YY z7P5+lwY1iMju}rc(3_1F6|F{jF}$ zmtVnRylor+@ejVEoDfhQdw{K$N5}>U3)^roC5Rj62@WJ|)8auF9h5kKYK3CGOS9z> zg%$2R;&JwD7a735yKF9=i_j{G1BoL=96=nKY;-;Dy4&N_b20b4BTQ^qH)<{b#|7K% z?_eoGNWINYnlhMX`dp>KA!$qb3i|5z-|*^)P8;jHFJirT91%psi*p3;eu#K+`i*~a z93z4V?bw6h*Vb^q{B4jn{zudMaQq9fc~-IS zZjbMOcasxG6^ln|NV#$omPUi_%M@tU^T5!9c8ngFeV2{Am1Us0tkN|NRtQ9^LGibK z7w@T8Fz!AG6%YOCFA{v^8S4M|*NLa9eG{pm=XEA>yj|~^$URGaQ>4Ux?KQmL{W8tJ z`zyqA)j>*-uOkJfR+L^oihAxG;luY6Pn79fc<58HZG8=mDeoJTH=CvuQ0C@Q<$N9F zfGIW^s}Oy`ZkxYGs!q)L&*aB&6;w|e7M055EU$eX%L+-{CT={n)Jk*UT`lGhO(TpD zySPQv_4xi*Yxs=<^M~6!_--F$#Nr_nv}WpXlOLOzO{QIJv3zlw$385n&Ro7ZF&vrS zNlyc-bwZWIXeq%QRvhRd2RD&x_nJTm?5{qB_v8!2zy3Gb`skx5%f$QEcPRYv*DyOB z%rCr%Z2E+EAHY0zitv$#&?3Tl@@eFHlj#1t2p+o+(QaXV>v_ym7tpmD{)gX<_9V_1 zzKQj{m+}7iOLTwY{X~1FvrQydSFxXb8sqW?@!|r(haRQziN`5?|9|fxZ43L`&ttxR z7F{S3eBe={eY42*b?mP_jd5{}c;6zy2i}DiG4|J=#yoWiH9LdA9xq>{3K|N`T7a$Z$6Lcgvob3dLLqI6X(fiP-A1L z@gmmKFQfMFBRsNz{q<)M!ovUP+k{M18$7>mH9N|2B6t#CB^$)z0$S@#` zXy1Py@sT6Mu1)3SX^cO9l6ZOyt5BpdJ&F16Ka1N1u{cirKmRt3zx%6*S(oZxeg|eJ z(ckzo=J88(|JIM7V>7yvq&5;RV!}pQ63lB|KP8KNM?i zmFkzig`6Bmedh&&7fw?DNB=4AAAOGEpFfLy>>l)|{+MQ=gla5N`u~0w)-qts#e8xELy)-#s2i?D175(j0X;(pZPw)SDvBq-~OkF^-Glh$!}xT#t>r# z;xBxI*3bVq(T5+P{HJBukb(Wk$Pnw`Wh*r?-Yky`<+|HDsE_}71k_tFLA z1N%|`%kR^e7^nNt9lKHvfgtFvqTA(>;gRpsSyQJLMgf! z-i6!-yBT9s+gYg|t&mdYdQ6^~AbQk)5NrCzkNi-t9y5eiNIyi`HnEf-1wUDWV_!Akm&NoM&Ff`_^+b|K4Ar{c|5h zUtY&PdoDSVOJg)Y@i>K7mT3IVpTpljnQRh6Vmlcw*Z7e%Eh1>fVu^+q>?%9j^%w?p2&g=~4gGbPJ9i}=x7 zvf@|HI5|AVUbTKJxp<6`R}UyfEDVJ1=a3RTmU5uoj6$T^>>R(O=(z*uT(WiM-F5Yt ztW67jXbimWjIXN_IesDkKf{H{=JnExBesha{!J!N& z+YzJBT4f;)Ls@4sPAAO*GqB?Ye%RvW)&DnLeIAio`?bnGLG>~{>fSsE(s&F_#yW}o z0EY#PYou`g$KHqY_2()6KmRrIXP!V!Rq3p6QBVS585n0Tf*-==HAKrt-?0x-^XP80 z@gI8tj9lP)80T)fe!7 z=g$yNybJTS6X-pA(YA%?b}(N%f&KE!2xZcE{9)|>{WF;DHsK8wW_s{<=-gjR{EmooJqgOW&TP@VyJ&36i&hLE&6}B;-dl7TB zN%x)iB9;o+zx@TgfB!|Ixhl?|eie=!KzkO(`O9cOK%QSFo-cz^hzrYzRyUc%%{u0Z z(^$Xrr?lSrPK=-V5Y9jQ-*8?#OL*`89p_#M$=1g6gu!u4Gw!AG(HJtqF>4f@Ni>=u zR&)b3;O;H7&e-YUj4gfky1%LWQF}RMM9yVa00qaulrkeGDvpS|9ds`psn#GJ2Vo4! zO=-%TZ2Jv(_mQ$f84~HlZK)pzBaqk-K^zB2VIqV?N2+J}&bh7UwtX%hBTs_zF5gL< z0Qwqb45jHVE@J*S{|Uw4|8tx_{)=R)O9kRz{z;;J)095-B-YF%#?ja5t~^d~$3cSs z{1++w;g|7#^EjeZq_bxa>Z9++{hiNK`Rz|54(vsQXDPmLl*W(07ySz#ru6L>;T?C; zoEihA@bA70@9+Lqihul<6n^V9M5RpUzyUgk?!b8LPKw`ujo^KcV4hs2@~{604$dR? zbtoP^fxhn!?9Y7*^^`*1eT44E9z|R}NAdT+gnId9#Pkfok3UZFxtFkO74+Hj_~(}C z-nEGT_x}ck-~Al!zx+Lf>k|F#U!?Qs-H6}-PNPHROHZOB1qb)j`qiI7wCfa)ok7l2 zDLnlWjh}uW@{R?(V<+gY)RBv`*ymosJ-LK=?*ZJu_z%fmd;FcmkKNtRbUXsIj)_8r z>pYRfa>s473Qt_R9%5-2sYX=o}mV`-+4Eoow%f7%}!<$=9|+oVGBOlyq}x~#Q*gfuXu zOfd6GASG55VmF$ISP>NpgawyaX`F5s87s691g?vc0wD!XtA*L=5*G^io`=>NuhB?Y zmvRxK(?yvkf#YCkh28EDSvH}S`_QzVc9*DFAn-gCV21%Rj0ijrr`1G8ilAJ=@O`v2 z2t5a<)xziogvA1Zo460StrkYdCn_dmvbtT2D4G1gb%_lLQsQ(wSdAviap{&zN%*D^ z7+T@f>q&o=3W04RqZqr}MQBilL1-cEDykKx@t4`S4zT;vI7dVhG9l zcfLaV9*VWzE8bgr%`WUmh(I+YL!Z*f@zwxJ00RE&e%UcjCiRY(UvwRp8hv{>ns0^!}t9tAOD&E3Ab3w zFh4(?WVf=lp>S{L9LdZC88%Z`d-d2KILtdrdueY3q?}04$!Jp zvT{MOm^{~-SV-EXV%BCh?tymt?FXg>mJM3dE>{wEKx=|R0fELidx2bkCBSsX&#&w;j5Z?%;EsI32XAwf=LZQBu+=4vw!|Ec85~HOg@a zT(>_5)oQ=&Rj6Gv0aO4@)s)@d$ZMs>Oby*nV!o;k}Gzw|{4UV&D-g<%*x`skxvym*mTvqcys<+RdC zwnHO9k{|t%A7ydxB2gG^6X=CB66ZmonV!Fg_kH{y;uXhswCkAJ#AR{@nK^zKLEZ?A z)SvGZFFxYANO@QzS>T?Q0Q;F2FppoR^D`eoTRm^ml#(euP%kme0n)%cc?#z%&(rzo zkD|s331UeoJo_TvzxfQo``^vhKm666K&JYLm$n7Tv()=CXZXuDu9Q8#TlL3srFj|p z_Wb)BZiCPeG`85dbb%LNJIBkfo}#n5f){w0mc@6UZ}aLg8$XP(OoOf;(e^`Lc~vu0 zE8^M)-7v=L%}3muUjan1qTLM%wpwTsAFVuRB7v>7RVw=r6C-KY8-#v9;0H`hOz^=E zd=STRh~fxC8dR%QO2tx^-ChVmr_dlfuCGCVB02rFYx}{7D|)6 z@8kcFiJ8NwIL?OQsA7ZPHdHNzqgXr*n)OZ=WvWC30hMt~4$00_ui}k{bcz^O`;)QvF$L>Z|iiuqG zi4S0Z<5@)4$2@)tv9w0Ke=#xC34v%fF<(242%@C@i3-NavxrWBnx96ltfD3-Q6(4i z_0!1pI%;vAXz%QsJAWfUYt8;imwTp7UVZHZRoUU*S%=D46|;A1uhyD^o!qNY_Dss2 znF+pr5G6F_YmU6XV^ORI_923n3hXm*lgA7 zpcK>7)7y4jZES2?-r0pcd$I)KQ5;imG|*aOS!U+`-p>-EIC$5`C{-tWc8si{f$&;% z??$C<3I%d*BIJ}(Zx(I{f!tiD^gsP8+~o!k<1g$b{IPf8KJzMiqfPCPzChFa5!~PX zQ>@Jny3xSjyPw8?{U75VJx1|2|A2665)pJTXQyF(9o=eE{nIbdoE@X}z#-6@$h3$p z6Z6HRR8O5kuGI-=W~u+9{~YZ=@t^%R-uX2!An+03k41E$ox$iQfGf>aio(OB-|_ybu3_ z@4)=dDLQ}uR|v)mn1Agjh$4mY-Dj}=>}kxiD+G_f3+Ksau)g+v^nd(wbe?zw@!ShI z|DVs&`t@JIKQuqIVKqVtqQCRYM4QW4|MMSUU08*sQ@GE(M)_;g*`7F-TCeh#f6)7B_u5`zlu3val^H zmxw@T|K{x&X}zos@`k-ZyD{7T5}8bs&t`6T1=8&6Ni(BQ-YY%NUvD?+ZtqbB%zOr! z{Ju|Bz*#bc4D)3l`*uprc*{X4;+a|0ul*F(=e|jF^cdX_KThB{n3jbh4LYR~;?gDf z-#(8MDujrVR4%b1vTY*Mz&N;%t)KibLB+#;*~S)|d- zO2siDj*%h+JL8{f>{k>kinr zr)M8{^ARI|UD>dZI_m0yD`l9^Z^ltq78r&k^t+rndxmDK!`#ANW~V2zG3<1!Q97Qq z@7)k&z`!?TFwCbN&E#l?j1pon>!Fzs&dB}Ds@@KGft1MOrwPw)5d0s173Ygz!TEzf z$AAAj!Lbl)Ygi}FVSWF5I4_^2`;UJeUico)i)Rp>E~4ur{19c?s3=YZVar6cn^;Fr z5>J=Wc5<}W?L&eXF(5|gsvX*3urpE&Z`k3@o8CcEuW$0|tFM9S zaPZKP+&I+0rrxRDQINk!WB6IVu2Q)JNu=h%+&3g0lIAeeSzf7}F|)sLI!_62hQs4E zfngdHzV`y*b4L+D7x~~_=gV?M^p>6-*aE0wfO2cu}&|8xrO`mD@1c1(v%cG z`6WbBe4f(xd3hk;R{DFVHb=FU-~6K}SNhHmBVKMQ+L(;FCYD?1tDgpTnC`oh ze0MWSz0xxhGcdTcz5wOFd5F=QjecNHJ_u+aXh>u>1)X|bYMlwaVyK?Z+a1zpLuIv0 z?H0M9C6NUEh+fcC=784o*8y^N41HT@qaZluZkwh?g3gHU{Ia zh2grr1QEUZsjEqjLo!nbs($dE9`K17#;G?Iw1!cFT7F~iU=S1W4hF_i2DYKHVn}0^ zTEnyXP-^tt+$PAd8+2NAzVVHxFieL^twt0?OiWD@w3@_1qEtv21URnC%=|nvlatA} z@4`xD^ES*50q4)0qUFaZ72|gUoI(LxD7v9S>4>1y!EzjG6BF!TTpWoAyRmxd`$6iF zU%kGDweRnkY;>7ZJee6mNLj9-eUh=+uloi0-|v&ogdLeOe7n4Ozp zz1d`=zJXILVPUYovCj0|{5Bb5CsrnXH~6V1;h8!P4bRNY}-+ z9M(6MD3mJ$D&BlwDK*>alG5#nI&{z_FM6W$c7#KNczQF+X|4NJ^DgMAAHE8@tiGA7 z)Z6feA(1gcDy{>7@B7BJ=giaK@0Tu3?6<8}D=C{<|+mSrJ?pxfJS)9GYaC!3~;=Xp2v>+1FTz*W`T^BN3>8ug8sx`zuQ=R`;! zIdra4c3A8nP+c$N4L6ymr;0(yYm#LK?%94bAa$wf3FHHTUbiV^C$Ul(hC#9C;d`?{ zDV0$Q*L5ir3OBXCR;xAe_np0@r(@!yf*Mqc| zPT_ZbD)alPPEN9Zd6~G=K${*D3-cI;K@2OHm|*MtDctdS_T7I!r=R@> z8Vl2L(A_phvBKK9lX#{@{n8nnQW;@8Nep!uP%4$!+}NZ#J<0Ofb5zI2=+w8UEZ)iV zOpVhozKG@8iC>jaXkid*!NmL?I_v8!Jn%4UufN2lvuE(CQ*gAh2qc{dp7ZrvS zCZ_S%m+5pnEZqArD<@v2>kC}hM1=vBeMhL(O1$#*uV6bCaSUE{jLC%smR^0C^4vbw z&%Tc7dQ|rugw{IsdWX{F1nre2f+)r-mhkJFOy2bnQws|>gc_xeb;CmKP2Zlkh>~vq zmOLu-gmIC(mM*;pAm;!n`{4^ZE0~TyldW}1g5Jn*70ahiFflbng(8!%jCX;teihfYjcav+66W*U7$2QkB9@dmM>B)l`wVu zMkasT#*srBpPLQ0vaemo(fe0IriRUIUGz<2Wq=8p1v3~kE(|h*PTwlg1 zln`1`oS0yrurY+ftxeHbIzw%892 z@ws_6&Y#6`9aI!zm?n;6;ubwh#S%fYPHA$6(%2@k5-c2=W8=a(EYm?n5w(eFbSFUT zh{oj=W)9zjjv`8)hgYf~WEaEG`0*xYZ34qI(S-uGSD;$-5OF|da+cEAI4dWQqOAh^ z@4lDT#wKp5azmM))VLSNF~0BL)J+?PVbZ5gLQ&ITqniavDJ;v%X{rX_XNSKSmOsek zMe)p5a-DG^jE%5(=YGdQm(|wwt7}tR{Ii1r;w=9YwwXz|4c|pcXNe}(w)qD6IByJ}52qnT!PK;@t;WEQEi}d|YPLOio;+J%6d9%d!jc%rU zCrxXWcgY>hMmXrlaxKu_+5jO@afCDsf^HYDSSD6+VmA?zu-n0MJltY|#`-Ecj@dkW zoUsFUqvHs-QX^*jU5zN~o|)94qP<&Z4XW6AKGCu0wNU z4YypwkkH)P!Vrp;b4wg}$2%~j5@De0G8E#yV4njt~Yxl5Z)FsZ7q$ZEO%LL3MKK4V#nlmf<)Ixwy1Mp&mR5$m9x{BNZv} zFjJS0zW>M&UzYh$aa|-s2*K9b*J(65M4cvv<5DgaS#EYPZHw~cIGt|9@`aN zbz!h|=^~b6Vb~saX^aE!dW81M1une&619DIuyXPk<%vmFy)wdY5p~)qrRZ!fbNaha zQJkDjHfD8~| zNW2-986$hdnP-);i^zvyi`>qiV{(U(Z3Mfyo0$*t~p!+Wg+c z4WLj)2uU3JtSv3kX|=J-6O<;WQ9%c7xwuo)pkgkcK0z2ow6?Y=6f3kgHt>p7x{U@g zCe@jFw2;VR8P(iEOB><1=qRK#InCJ23}Xw67_m>}`>b8OKpY2jT1|@MlT;S=&|FsMO{xp~>1?hLG@Dq35>XgZT|9^(HCty-AWR3lSRiQB z6T_PALL4G(4^-4k+yz#thKRegH#Vru@1?u3OcW^!wHlqRI&P_mMxp{AZ)%S2>Lt33 zI)>w-mBt&NAZRsFL5HyGQ<~q8WgFDbpTVh&5qDd}D#>kX6e~!b+%wVHSi>8i#W109 zd5O~WJdxi;nikI3B;nRFE2mCSon0jEHtDun6sH!@VH>kJhT|A4AAgO~>|QE!^RzCX zqq(+@ien7RL|QIV$4J{w^L2H3C zF_qavl-Akrw41y&y4Pvn5HsZGpCNOeA5AAQoxr?WieCIg>ieI4Yubm%CWstKCJnC1 zorpUvO#Y+OYo7;VmeWgcQr@=bZ<8#b9Q4^q7q~x-03$DWo<1y**H=j~KS=4fs)Ivz=Q)(=?3%;X7?Oj#Y+Kf?=9+ z4WPjppY9JhC&Ul_PBwqvqgQ6ZKw2x7j=x4}YL;T9LV62nYL!nhIh&`x1I&PSN%XW{ zO6P)85U41`Z+Eam~` zY9@DeZXX26vnULarkSXMcbVcFYQxCf&XZR2o~Umo)J2s|QrZzD~eQgcPaREhVV*^9N%H?Ior)F4Ry3F{VJxm=qgrOB1 zm(DUazZbt%XZ73}yxJt%ZxLZ&TL!Iq1Isk<{Vra09GdI2S611)a0YSjL$p?w@W!Sv zBsA7msLU+T-C9E_&E+$v+5gaER3^r5Va&^RZPD#OF<^Iv_sSr4B5(m7n{~-V1pZs%d$013rF19yzqbDSe**JNWW6!_Hp?80fvoAbD zZDO4DOXrFG4wYIhu^I@?>1V!37{e*Bbj+qyEVFXr7^Y?6cSD5KTzJ`_xwJ%W zVJ}g)MYrp7$0HwPYHFO-*I%L0*upK8nV6m>h`Pxf6beZ;&&De4tw}25HLU6whGlZ< zxn~IKbsCp1|zyftVY;r5eHpbmoIYqx$h8ky4b}srE-Dh))rcY1YIAuI*u?+ z3KP>vL(p7XMM(>{P^RFyY_6|j+Af8H&HCCJj^|M*RSCL2Ua?4hb(v1Re#_!rM#XF2 zF0fO8(r$K)eBDvccgFpcm&%)-6Kz%Qehk$UhzEl>`VHL7>Cl*Nkw<^x7m35f2&k08 zbY1q||4wuq5l0b*SHiGe-u>f0i($KHl{nTJwnNa^#41$KD(qptMp`yutAQ4RW8eKc zcR%_#PO*Seii3~5AB2I9BZQO`N)-&pCGK`Wnix)^4U(40kq6(I*d9s`5_K9Fw#UrD zpzj7^+MwnTrp3hE94ZJNu4#!gd2;*cg^c9EM2Sxn-8t*wFgyDJv@Wzx281Y&8e@qK^5m1DU5osz2Urm;%**Wlm>zacG>MJ}d@ zVVX8`volzRU}!9BX_PR?eJ9ItTYGosiR?zPr9le5`8x|2y- zN~<=R^<%o+Lir-^b`GxV?wSd3Cl+Ox_s^HzDI?%;nc++%wrvkQ%Ui^U`?-?e)L_5E z&S`oZbQlHpDa?mG^xe%x?wwAvohO)@xIK(oxMAz-%>)6|!+;Z=27$i$3Cqfc z$sL6XwoHs%1{%+}HE8K8O`yar$B_I+_DWSAeeB(YK^LWaES6G9B5f%#r9lvMFm0D0 z2zF$NuH-&4EXRyOl$2fDNtPKl;0+_>sJf6Kh#^QKSTmc37&z$D$D&s*%M#LPZzaL^ zBb2@(FPYrzMFXB~Zt(e_g}Mb4%2SHJDI`ZqHDaZhb|w4E&Mo=Y^=`zmMwrs%TLyWT zi7<+A90$jB2O~Fg@}BFtSv|P=Afn;2qo_mvneY49wvAyJ*~Z_=?R+P#)F}TcDd1q$ zCX^PPNYRBs?d!nYBsM)0G}5r}3Pm1#@BzN_+>2QNM;^JfzA+JGR|5^DXaT9C!T^$A z?c#HFWg|45oV$iOB1q|GfJpn|){AlZ4Q!ewV`F2tcm$(iYio-z3^8(v*xsnydFuP- zn1YIHvEB{o#(+qpKL?$q`quymK^*y9ymXP%ufIaa4>O0ltj;Z$TQ#Z|TdDy^2uva9 zYDJLQT6*eG1~EU4)iQ)2(u2Axkt>s_qlfa)YTZj*oU60*C|PZ$Kb@}7M3XqBTcnna%8^5 zcTa3EUb6ZAxjLd%@$_`gi7JZicKj|fD23;k{4o4lSHXtDa}xl|AfU+ zusGqNkBs412CZ(Coi?Tv%#XXcmc)>Pg>knR5TlqMcNr_$+_$$v#WPu{`$TaVjH}lL+H{h@n-kUj|6m~NR4v&AQ=Xqq3LSW=V6Z&yV8B?9>8%z*%J8jlC z>nyLX4Y+=!Lim7ua%-jtrTY;g4dAIL*}f$-=eO##rNNVNoEum_1^m7+vNI0BEMFPS#cGwsPlu2@TARxkGiyf|K4Xijm3~ zsh)phVz3|YL>m<*-C6hhK&ZSi}* z_q)BwseX8y6apxp-Y;~wtkdL#JIeM?bZ#zN3q2=?m}yUse3%OR3Zyf8t5R+RmrVc zLk&#W4xe;pZ+>Szh;x$|XbAM1FNoe;7_?*Lo%ix?6lq$V@$vC2E`0k*KFp_I8x>4l zMcVClcDvI~2EO5RJ1JZ-f^S5>>9~hSn;QJgU;97(mkFtnGKu-tP^?t4RFnBEA-9V1 zCw%_xsbl{^fOKOirHG@D&8-HNN*S#ZrAIzk$S_O{DS7dG&k|s9_|Sfgo*z}W-Q?os zRrc@OmxMqIL7`C0G@Dlfr4-F(lTN3@>gp;By=xAx77vq^;Jj)Qlww7krN z4?j$~;3A~Nb!^sGHu%Fo_yfwt0_|qN;=x7MSC@GDTi-@W$>RPy_`v($bJd6;gy7Pp zOB_3PjD7p|4U8}U`;ABN<-Wc5pOM`Z28iu$CuS7Ixn#j&0EO}ir*5??_}g&vARobJ zm^OR%?4i}zVr+5_$CMNbE{GW0GD#1^`Nh4AP0cVlUL^>+Xk}8U6uJAZJ83ss_))~n z+&rFr^@$zQ`~U8_=bmlhwdpu-Oa$M+Q!-zpVc(q`buiPygN+WyC%jE5-YRgVl}a7w z65&%*s#GbKD=;@pmb4C-nVU!T60${6M5$V%T!rbGncdsJ1{OGuFMb#+1hYh zZ#aT4&u-<8cQNpzf29NnOqrRfM!DNDpz3;?mAd^PT@eXbQs5W@TPFV*xp37OO%Q9s zP$7Emi=(trX`3mFVwxtKo15DN-m4zp4nasM)M~YXa>L=X*Au~)KF@v+)lcYU-@!2d zoZdULr_9alUj3S)Cz0f9zRgPAE|7Q-L&22PY=ep=aSeeXM;v24$x;AOD4-K<6PvvF;`99U zNA728qKIiGS2o9SjM9oQh_FnPSSiZo5@8S!D}|H>S}VdZ%+l~kDe${Nrt*zdOcX{~ zww?WZk8$q8c^3EWr@gt(^4bQ4Vu^OA zjcHq0QW7fIzqp6jUq6<3S!jdWcoo0ZC5U~5Au*+i-|bSVPB1Z1=EC_U{IH8wNpk7g zJ$t$9(7_!k%C$!DZC|^DN@NrRJ%k(?#pvJd-G7nIWa3PSc*BXE->RTV1Y6e-6ii9c zOn7-m%FI(!0in`#V?{esw4&s9Jj$Q(I$**v*jKVJr6AUc2bs~688V|(_TR9JLvQo+ zLOHd7G%bPBFjcep`S%?`N=dD3VVbj`G_!LHL{XF&_za0*7);JgVLL8jZkD}4khIae zAvO7}@jRDWtxBvE2uZ~q zs+PntdYYbHKxqh+rV+-hc4Jokh;FQR9MdSs_b}&~>?vAk(f9F55h4xIO(}&KQNQ1p z=plwc_TAYSRqKV9j5PwH?foJN9PR6 z>4wfM)WgEQOy!>*6PY4`0IkKq4NtpmiV=7N^jN9g7A+$=Z!!5I{RUeK%9f;N8I*dP z+w4tptTn#UG(*K!7*h`vzS5XNFzp#E7A(q^!L{7lEJZ?HT*GA2HEBl{7uz8h+Y!F% z^RFrO@p{OnNz&=GBSkY*1WGgOnJkv9EdE2LaRoi&T#6uKK>i!z#fR2Yi=JFUPGBBV z(+`(G#0*K?}Ytr{< zO{G|1yy%R~0+KyQHQ9Rm90^2U_!b%I%6(XGW;25E7C{aTc!prcGnsKsN|xO9q@Q+^ zlfD%xR{e;AA(?W`YeI-oAb_GNIb3m=bWKh-0t_jbat*v*oTcvZ{%P=#AYseek)mQH z!MzDm^btbRLx>!;fSr{idE;&xN1sBYzC{peYSnUf2eh(>@=4n3$Ic`#b%De2t*{v zPJ`S+E0tV)B#hn#NJ`2~V>Bl@EzC9-b? zypRHBJ(Imfo3eHF7dc7+WlK`F?5nPGEih&qcr}-d@&b#wRMAJ9i$_u&9lXQE-ZY@%b`ur>PpUMPxlx-FY)*C+UZ!~mcMLSMHW(7GOR^&Eq@BdR?-{>KM z%&5emJTcO}VaK`a8NE{WL?i~ishL?U$3r7AO@p!Vaa`BIG7J>ZuGiUYw1^Z;j89++ zNxRd<@d}LBDuiK(S1e=8Dvef$TCIxb772VG({ZR(Y#z`MD5w?WR^9-7rX-HAG^( z%G?=93|E0l{@Y2*ld?{CRvo6@tH04S<*C!))`Zo_ZNM7@omkO{6A?c}h~XZ#X_tiP z3D*qdLlRe{7*~eW;H8yfd}5NZ@reNo^nh((W;#jVDh-5ya=F6%!XA(kW5|7DVk)UK zHa2*XO`DxMYLmu1ooFKrmg}hLZ#`%Nj5`0G*HpgE@(8N)&x-^fI3o8FeLU> z@Mg&zBv~dB7Y$9QQ*YKmSs~xr;K`q7eERR?kaFaWQncMp>Ore=|Jktb(@x>B`SiE`LQJdYv^np7uO%rLP?&oqOwUAQcc*(^;J89Z-6P{bW{$@7&4~I&o zLbn(UR7yAWq-QejniR~0?NK`6qqjoEnjh2YrMuZ_NHxpgaMfnazP77$T|=_JWHaHI z9IN{nLa?V`?YdDkeI7rRmr{ftME2xuNd{a(r?n-+`ugshYR49 zt0ebDYN9a8cif++p08B9vBhNB${j8{Q=)+loj$lm=QUWRJfy zOe;BPWa0%Zq-3#JU~$atZ~Rg7Jp5hcm?Ev&#((TI@mg!Dj=`Ryn{C9MpkPW4RT7@x zmIBw1g8}n5Xn`FgIZst?gT}emB?+sAAd5{%1=?+Po00$NOx>pt_)25M3eS)Pv7+0P zQBo~a%Kzu(iD8>VU&h#3b{VynHyR;!Vu6zWw;S+a(0g^K6gj)Kd!@0|DrFwMrZ6Y@qUKxs`Uj?ubr2-~LC%x_luh?4)NfpO^My%xIf zLnFup^2}hAYe(iH9sAlQF|z%ujb|C2pHa5gH#+yXLlWnKLurJz?nXnbG~Gxc#FZ63 zSB)4_2-;e3e7%lwm80LTcpLrfdfH0anW3#XQpYbww6%*gwaZ`q26k$DxQ}bu%r|nr zb{+rFJ8=zVuQaaR#yhf~)I2Z(QLm+~E6tN2iCzq(iD_T?V842b0hpFWBqhO{dE?0q z262VIN4^tRQRXW8)$C3M^oVj-f?dlFy2Fin1=slQtpsTd`_(`%9^>lc19l3Ie=CEy z%4gf&-#`Sp-uHRfsoX#^y=$p=mHobzV5b9V_*=~@u>_2$U|nffyhY)vsKqWX^OHR4 z_pO3$tctionJcyN0|FXNkYjcRZw1gjAGU(hY$yeCcLDsG zC`R6GKni))>c_X?c7q?jg;QE1mFkh4E7P27LW}{UnYcZ4;cvsWf!3NRXafFDCHTQZ z9F3-cG@YxLrLVn{AGAsP;R2;Joz_WQ`y3x7qAXngxsYM*!y@){!W-iGT1g_LRR!w|?Aq`v8h zaW(GfHx{m~uN%G#8{hmMOaJD}So;=efA?wpI_&xNpC?{hWAm%e;T+me<qzJZ@!FsWRdoZ$FTOyV|tR#sf(yiMD@du5MI1M`{i>KAG?oeX^C*PMfGEk zVbzLne9%8+(2Gc67%`HB92$g7e8qON)8umB_A|@$efS2``RMF@3Tx|aN<|ynzEua| zwITWq9hD9P8s9yNQM74%=M_v#VpNI?{rt-`o!1D_!G%kd-}ex$XI^0QOV1*U4sv3g@sB)o zizfC58^SPRYpYAaG4Vr1vFy-k2S~%fkPt=+A)wOqP{ioG_$vNtn~9(M z5Sw5A9+h|Bg<7qn!Ke$^0IVm5XhpCs-UWadElH zzQr=f+MCQymT5PAX6LHROt=_^fg)z#o^k&8&(1UV#55b1JGjLvmzOpvmp%3_*0^wf zi_>Q}xckUBtyY)kzkiX*$r86tnR9LZh@*A?s_2;3nj(t1f{hd+GxA+8Xy2#t>`^c* zN)H`DI#+*p+uLyc5XXvU{S}JtdGb+mmoGKgXlg1B96#G&@7@}hF4dWxud=?}Kv*V@ z38rO&fGCLYN-le6Eq?d+o@U?S1I$mCXf}Kt&&H4t#Tv&@Y&Byn%cN4XIk2}#9L1bI zv(C&+g;L4B>Ha55K_@suvAmCN9C5xA!xjAf-ZT}Ea2zU+KlEmG|3eOgtdvGGJy&H$ z08z}sVht_f!2SwaYYy()Ik2f!Z)4al_uf0h?6`%}J2`C#Ac=l7Oq0Whr~5ZJ-2ztX zT5<1f-RKW3`fn-5Ac zc*o>bz%50LQ0XlB^0h)7g{-Zw<9bCZ<t;Vpq2SDUXW2RD6Z#5%c%B zPQbo>dwK2XQI5X)D&Kmv zNEQk$qTORfuRNsdtCxW!xd&-`1GlA&5h{&DP_nOI`yiyGT5>sc`V5VFow@x7D7zMy zM3T`u3In8RQmIr>BQc;y6SI1KTp``aX{1(CKt26pI9Y7t40gaYPtv z3a*>nas309(BWD@3b4#k{E|Q^6DbXp>R;I@R2O&Uv&fC3gtI?}xZ|&584jQcXwzsP zBlycY;$Z{*LJY1zSR|V~0vwSbgwW9Lbz2}IHsb;zA^wI!xFGgQ@SvA~I6)c}+;@Znava(`w-rikOCx2==|3b{xkc3<4yAt<6m)CZ{mtkSLCE9Ggz7 zg<;#7oZb-+PeN;2?KXu%0VySc-=W^@FgYGd4e&s&>OSNGTaGU zAliT}lS{JCC5Ah(0BnK2s1Y+FdAF4yh?o=TWf1pEgwsQU^Psyu1TugwFe4BpV55gP z=XCOWTx8d@^(G&7RYPAr+;qe!nSy(37GV_9ZnrUe+M;f^i)orzmes$tQzdb^wlNq@ zu2sybGiRvP#`yk=FR*X_elA};&+MLkY+N`;BZx7j?y*rCEiD#i=Q#QL>llW~T78wf z?s<@))ucQ=f$BCmdHO82?PQz2;1xg!!Z=2$m}0Ta;X4lS()V8^j5WeAC>1NWW!g63+#`hIF)F2X zv~Kk4YY?tLzRyS~MJkU!+WR+Ur-I&ZNDu%Z)aWjVX@T)cvqu>~FDvv$Qcvs?h*EEy z3b0A~5P-vw@#NZUFuTDGMT}4-SMoY2R2&V&hCKE zM3@2&SFE9IhsiCU-A;!%3^;Z2IDQy&xKw7#G>F@6E-kO%dIeM*5MvN@y0rX|v5Ld^ z_yjALF4AsysZLB%ueUG^$?Dn~reUGAqS@?V+ZM5k@QO7gf@Z79<;$1pL@{^Yc^7Ld zE0~srWtv=CUE$REC2G}iN<|wXU8D|a`2kTJ(pX=kR4%h`-(KqVO-`LWLEy&-t+{aS z49lylL{W@di?J=2;-0;@w@8hwfKcT(kmiNcpXIsBzs<_t6TEN!f1zaVMTmY<SH=ZF6)(od^S^d0{=Iq`J(QQ9=!*1g!~zAfXUF_C+a$@B73^ z+R~3&Sw5 zEEB)eK?zBvQYQ4fwAvjU$03Sh&b71Eru? zEMnU?-;pwo70u>J3We4FCJ=&+<~hFb!ars?exAGb{xt8I{SAuNY?9J+ZC zMT!`K*x+3EPYD0Aj@|$P%PgnrjZ8Kcu#q*R)FbDRimDR^+)B8p9dZVM@8mbFkyNf3q^>(cIY zaBLgfFtFkn*Rlv=O*hsQ%zKp;VF?-SrAMu1BZcrB*9L?~a9H;V=gd--*#nS{=tRlarJEG1xYxayhxU#I~_) zI~jxH(C&077K^y9JCF|F?{tV2OifKE%cnK9v5DS-rQ?igwG)b!+!_Qbj%cNupYeZR~+ZugNL6opedKJVhNf{ILNd+E=aljSGyCu2>`lLqObze_Ak?mW1kS6+UFNJFJmq|s`iB0;HK zq}y(SkVw(Y1Fr9wL@BQh!RjLRcLH9 z31h`Xv4mv^wzldNiY4av%yRzRStci@*xXphbjt)`M5$84G$l*t&e8BYxNebnE2Puz zU|TjZT{ME_OBV=Yf#*7`t*p@6Y;gBIceB2_%Gzd&v9WPX6;LdW6LcEHN)tyR4L?K} zHEOkSRxX_6+`02i&&;!Deum4J&(muA>|I>od(S?N?G`Z&$;C_OaoqxU9XZJJ&p)4> z%3%^q?Yb`Y%?;X}E{4%YYmMW1REi#c7+yDGC=KC=Y<#iS+_~qI+_Ufrf*?j|u!IDI z>^9d}4c3iB&r4)OCz_*z=nLHdPLKMxfsRh>8&_i91>j!$cf|@qy}kK2UB(zyr`>J? z3?PT^`)I&*oWwuBcjJu)T4BOU4ZG@e+ikjGi0e44t}KD!FgZ3xH}LU14=JG2>0p=^ zj%^bLK7J5lStd$D(esGn7zBiV^3L-LNC92n$1n`ySWzk!Idl3n(=)R~QHX8Z_(0&SFKQd1^q$$lgVg zZg(Cjoo(z#b`Q958P{!*vQnYg;9UKW2tLWzp$&3BwS}vaoHNmMzNu`j0GYEvwg@Ct(s*}ciIEjv?eL}7qsI}|*ZPP>H=k^=`1 z_EpG1fMHt66}e8ouXeM+=2o4_iE*5s?PPFfEj+Wo1LpSZ$=W=0=#Iq3RT#9qyKd5c z`m{DSHrQt22CWODeFUYY5bAsq#Iys_NvV>{aNLZ)o p9@50zB*Y-Q;%(bWe;qQ${~zbWB7!lcBnAKg002ovPDHLkV1l?yf1>~Z literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/linkr.png b/docs/3.4.x/docs/images/apps/linkr.png new file mode 100644 index 0000000000000000000000000000000000000000..62dc5f6c51174c77fdc4356a7f442e95cf8fb6ad GIT binary patch literal 6428 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/lists.png b/docs/3.4.x/docs/images/apps/lists.png new file mode 100644 index 0000000000000000000000000000000000000000..a0f48c63b1eb40fa7cab3c8384ed97834c621e21 GIT binary patch literal 697 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
  • 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 T655ph=X$5122!n4wvPBe3)j3P literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/mcdonalds.png b/docs/3.4.x/docs/images/apps/mcdonalds.png new file mode 100644 index 0000000000000000000000000000000000000000..28a1bbf0bc13f1d3728ad42e53a04eb669f14517 GIT binary patch literal 57481 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

    kEHs_LGe?wKJuGaPCdM8l?nCCj!TI01$Q7!ES* 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/nextdays.png b/docs/3.4.x/docs/images/apps/nextdays.png new file mode 100644 index 0000000000000000000000000000000000000000..9ca96fe961a84f3df23513aa4ceeef52bddbf91c GIT binary patch literal 35067 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

    w5Dis*m_y7@7D1e4 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/nuorder.png b/docs/3.4.x/docs/images/apps/nuorder.png new file mode 100644 index 0000000000000000000000000000000000000000..da4cf597aae0b92aff5c13b2638ec7edc997705d GIT binary patch literal 38163 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 Ef(FYGSO5S3 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/scottyapp.png b/docs/3.4.x/docs/images/apps/scottyapp.png new file mode 100644 index 0000000000000000000000000000000000000000..d5142f34601224e550deb71b93313497f5720cf8 GIT binary patch literal 118416 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 Dx(}}{ literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/seelio.png b/docs/3.4.x/docs/images/apps/seelio.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e7a8e65abae0ad30c3db0a00782d8b1d54ce9c GIT binary patch literal 24005 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 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/selectvids.png b/docs/3.4.x/docs/images/apps/selectvids.png new file mode 100644 index 0000000000000000000000000000000000000000..9ba693a6a156164f547eb4b615afaa43a2475a81 GIT binary patch literal 42214 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 KMNUMnLSTZ(DAHH} literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/sharelatex.png b/docs/3.4.x/docs/images/apps/sharelatex.png new file mode 100644 index 0000000000000000000000000000000000000000..e3ef6dd25e1f81de2a170ede0e3a3665fe98b80d GIT binary patch literal 19707 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 w+RWv0lh6Ai#~9=x}o)VD=23xZGidKsJj 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

    UgJe6f|Y=Yr! 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 M07*qoM6N<$f<=x}o)VD=23xZGidKsJj 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 P00000NkvXXu0mjfkLXIi literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/stachify.png b/docs/3.4.x/docs/images/apps/stachify.png new file mode 100644 index 0000000000000000000000000000000000000000..14a64c23af6ffe25419224c9e6313b366b925014 GIT binary patch literal 27783 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 DnZfGr literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/todaylaunch.png b/docs/3.4.x/docs/images/apps/todaylaunch.png new file mode 100644 index 0000000000000000000000000000000000000000..f75fba3bda92d1387dc24b7cb6d5eaa648fff69e GIT binary patch literal 33233 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 KMNUMnLSTZ9^9~09 literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/upcload.png b/docs/3.4.x/docs/images/apps/upcload.png new file mode 100644 index 0000000000000000000000000000000000000000..4199712ee7ca626e6f2b45800fce43336a6da398 GIT binary patch literal 37792 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 C>_hDU literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/apps/wavo.png b/docs/3.4.x/docs/images/apps/wavo.png new file mode 100644 index 0000000000000000000000000000000000000000..3ab6bb877c1b05a6f2f20a8cd697bc21ee84a7aa GIT binary patch literal 54906 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

    Getting Started

    First be sure you have MongoDB and Node.js installed.

    + +

    Next install Mongoose from the command line using npm:

    + +
    $ npm install mongoose

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. +The first thing we need to do is include mongoose in our project and open a connection to the test database on our locally running instance of MongoDB.

    // getting-started.js
    +var mongoose = require('mongoose');
    +var db = mongoose.createConnection('mongodb://localhost/test');

    We have a pending connection object to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    db.on('error', console.error.bind(console, 'connection error:'));
    +db.once('open', function callback () {
    +  // yay!
    +});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = new mongoose.Schema({
    +    name: String
    +})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a Model.

    var Kitten = db.model('Kitten', kittySchema)

    A model is a class with which we construct documents. +In this case, each document will be a kitten with properties and behaviors as declared in our schema. +Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    +console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    kittySchema.methods.speak = function () {
    +  var greeting = this.name
    +    ? "Meow name is " + this.name
    +    : "I don't have a name"
    +  console.log(greeting);
    +}
    +
    +var Kitten = db.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    +fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. +Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err, fluffy) {
    +  if (err) // TODO handle the error
    +  fluffy.speak();
    +});

    Say time goes by and we want to display all the kittens we've seen. +We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    +  if (err) // TODO handle err
    +  console.log(kittens)
    +})

    We just logged all of the kittens in our db to the console. +If we want to filter our kittens by name, Mongoose supports MongoDBs rich querying syntax.

    Kitten.find({ name: /^Fluff/ }, callback)

    This performs a search for all documents with a name property that begins with "Fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or API docs for more.

    diff --git a/docs/3.4.x/docs/js/cookies.min.js b/docs/3.4.x/docs/js/cookies.min.js new file mode 100644 index 00000000000..dc94dbc5bbc --- /dev/null +++ b/docs/3.4.x/docs/js/cookies.min.js @@ -0,0 +1,4 @@ +/*! Cookies.js - 0.2.0; Copyright (c) 2012, Scott Hamper; http://www.opensource.org/licenses/MIT */ +(function(f,e){var b=function(c,d,a){return 1===arguments.length?b.get(c):b.set(c,d,a)};b.get=function(c){f.cookie!==b._cacheString&&b._populateCache();return b._cache[c]};b.defaults={path:"/"};b.set=function(c,d,a){a={path:a&&a.path||b.defaults.path,domain:a&&a.domain||b.defaults.domain,expires:a&&a.expires||b.defaults.expires,secure:a&&a.secure!==e?a.secure:b.defaults.secure};d===e&&(a.expires=-1);switch(typeof a.expires){case "number":a.expires=new Date((new Date).getTime()+1E3*a.expires);break; +case "string":a.expires=new Date(a.expires)}c=encodeURIComponent(c)+"="+(d+"").replace(/[^!#-+\--:<-[\]-~]/g,encodeURIComponent);c+=a.path?";path="+a.path:"";c+=a.domain?";domain="+a.domain:"";c+=a.expires?";expires="+a.expires.toGMTString():"";c+=a.secure?";secure":"";f.cookie=c;return b};b.expire=function(c,d){return b.set(c,e,d)};b._populateCache=function(){b._cache={};b._cacheString=f.cookie;for(var c=b._cacheString.split("; "),d=0;d>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.4.x/docs/middleware.html b/docs/3.4.x/docs/middleware.html new file mode 100644 index 00000000000..c90a4257eeb --- /dev/null +++ b/docs/3.4.x/docs/middleware.html @@ -0,0 +1,29 @@ +Mongoose Middleware v3.4.0Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods.

    +There are two types of middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next

    var schema = new Schema(..);
    +schema.pre('save', function (next) {
    +  // do stuff
    +  next();
    +});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    +schema.pre('save', true, function (next, done) {
    +  // calling next kicks off the next middleware in parallel
    +  next();
    +  doAsync(done);
    +});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    +  var err = new Error('something went wrong');
    +  next(err);
    +});
    +
    +// later...
    +
    +myModel.save(function (err) {
    +  console.log(err.message) // something went wrong
    +});
    +

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    diff --git a/docs/3.4.x/docs/migration.html b/docs/3.4.x/docs/migration.html new file mode 100644 index 00000000000..af30ffe1c77 --- /dev/null +++ b/docs/3.4.x/docs/migration.html @@ -0,0 +1,40 @@ +Mongoose Migration Guide v3.4.0Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    + +

    Here are the removed methods are their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    + +

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    • are now strict by default.
    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    + +

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    + +
    • $inc
    • $increment
    • $decrement
    + +

    If you really want this behavior back, include the mongoose-number module in your project.

    + +

    A good alternative is to start using the new findAndModify helpers. +Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    +...
    +Inventory.findById(id, function (err, inventory) {
    +  if (err) return handleError(err);
    +  inventory.productCount.$decrement(7);
    +  inventory.save(function (err) {
    +    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    +    if (err) return handleError(err);
    +    res.send(inventory.productCount); // 3
    +  });
    +});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    +  if (err) return handleError(err);
    +  res.send(inventory.productCount); // 3
    +});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This change allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    More Info

    Related blog posts:

    + +
    diff --git a/docs/3.4.x/docs/models.html b/docs/3.4.x/docs/models.html new file mode 100644 index 00000000000..cfecd30c71a --- /dev/null +++ b/docs/3.4.x/docs/models.html @@ -0,0 +1,31 @@ +Mongoose Models v3.4.0Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var db = mongoose.createConnection(..);
    +var schema = new mongoose.Schema({ name: 'string', size: 'string' });
    +var Tank = db.model('Tank', schema);
    +

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = db.model('Tank', yourSchema);
    +
    +var small = new Tank({ size: 'small' });
    +small.save(function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +
    +// or
    +
    +Tank.create({ size: 'small' }, function (err, small) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    +  if (err) return handleError(err);
    +  // removed!
    +});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    + +

    If you want to update a single document in the db and return it to your application, use findOneAndUpdate instead.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at Documents.

    diff --git a/docs/3.4.x/docs/plugins.html b/docs/3.4.x/docs/plugins.html new file mode 100644 index 00000000000..b21f4c90703 --- /dev/null +++ b/docs/3.4.x/docs/plugins.html @@ -0,0 +1,33 @@ +Mongoose Plugins v3.4.0Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    + +

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    +module.exports = exports = function lastModifiedPlugin (schema, options) {
    +  schema.add({ lastMod: Date })
    +  
    +  schema.pre('save', function (next) {
    +    this.lastMod = new Date
    +    next()
    +  })
    +  
    +  if (options && options.index) {
    +    schema.path('lastMod').index(options.index)
    +  }
    +}
    +
    +// game-schema.js
    +var lastMod = require('./lastMod');
    +var Game = new Schema({ ... });
    +Game.plugin(lastMod, { index: true });
    +
    +// player-schema.js
    +var lastMod = require('./lastMod');
    +var Player = new Schema({ ... });
    +Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    diff --git a/docs/3.4.x/docs/populate.html b/docs/3.4.x/docs/populate.html new file mode 100644 index 00000000000..2e51f09da4c --- /dev/null +++ b/docs/3.4.x/docs/populate.html @@ -0,0 +1,104 @@ +Mongoose Query Population v3.4.0Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    + +

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    +  , Schema = mongoose.Schema
    +  
    +var PersonSchema = new Schema({
    +  name    : String,
    +  age     : Number,
    +  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    +});
    +
    +var StorySchema = new Schema({
    +  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    +  title    : String,
    +  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    +});
    +
    +var Story  = mongoose.model('Story', StorySchema);
    +var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    +
    +aaron.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  var story1 = new Story({
    +    title: "Once upon a timex.",
    +    _creator: aaron._id    // assign an ObjectId
    +  });
    +  
    +  story1.save(function (err) {
    +    if (err) return handleError(err);
    +    // thats it!
    +  });
    +})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    +.findOne({ title: /timex/ })
    +.populate('_creator')
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    +})
    +

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    + +

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    +.findOne({ title: /timex/i })
    +.populate('_creator', 'name') // only return the Persons name
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  
    +  console.log('The creator is %s', story._creator.name);
    +  // prints "The creator is Aaron"
    +  
    +  console.log('The creators age is %s', story._creator.age);
    +  // prints "The creators age is null'
    +})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    +.find(...)
    +.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    + +

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    +aaron.save();

    This allows us to perform a find and populate combo:

    Person
    +.findOne({ name: 'Aaron' })
    +.populate('stories') // only works if we pushed refs to children
    +.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log(person);
    +})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    +.find({ _creator: aaron._id })
    +.populate('_creator') // not really necessary
    +.exec(function (err, stories) {
    +  if (err) return handleError(err);
    +  console.log('The stories are an array: ', stories);
    +})
    +

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    +guille.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  story._creator = guille; // or guille._id
    +  
    +  story.save(function (err) {
    +    if (err) return handleError(err);
    +    
    +    Story
    +    .findOne({ title: /timex/i })
    +    .populate('_creator', 'name')
    +    .exec(function (err, story) {
    +      if (err) return handleError(err);
    +      
    +      console.log('The creator is %s', story._creator.name)
    +      // prints "The creator is Guillermo"
    +    })
    +  })
    +})
    +

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    +Story.findOne(..).populate('_creator', 'name age').exec(..);
    +
    +// this doesn't
    +Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
    +

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at connections.

    diff --git a/docs/3.4.x/docs/prior.html b/docs/3.4.x/docs/prior.html new file mode 100644 index 00000000000..fe8db728380 --- /dev/null +++ b/docs/3.4.x/docs/prior.html @@ -0,0 +1,9 @@ +Mongoose v3.4.0Fork me on GitHub

    Prior Release Documentation

    diff --git a/docs/3.4.x/docs/production.html b/docs/3.4.x/docs/production.html new file mode 100644 index 00000000000..caf6e8b1e11 --- /dev/null +++ b/docs/3.4.x/docs/production.html @@ -0,0 +1,9 @@ +Mongoose Production v3.4.0Fork me on GitHub

    Mongoose In The Wild (add your project)

    • LearnBoost is a free online gradebook, lesson planner, attendance, and reporting application for Teachers, Parents, and Students.
    • Storify lets you curate social networks to build social stories, bringing together media scattered across the Web into a coherent narrative.
    • Geeklist is an achievement-based social portfolio builder where all bad-ass code monkeys around the globe can communicate, brag, build their street cred and get found.
    • ClickDummy is a rapid mockup prototyping application for designers and dummies.
    • Scotty App allows you to create data driven backends for your apps in minutes instead of weeks.
    • Bozuko is an exciting customer rewards program.
    • Call List helps you maintain a todo list for people you need to call.
    • Grow The Game Golf lets you think, act, and score your golf game like a pro with real-time scoring, live leaderboards and more.
    • nextdays lets you share plans with friends and discover what is happening around you.
    • AtticTV is Music Television (MTV) for the web.
    • LocalResponse helps marketers respond to real-time consumer intent.
    • Select Vids is a collection of amazing, funny, and creative videos for you to discover.
    • cldfy delivers mail to your app.
    • ShareLatex is a real-time LaTeX collaboration tool.
    • Cyborg Vision uses real-time facial recognition to identify your friends and show their information.
    • Wavo lets you express yourself through the songs you love.
    • seelio is a stage for college students to distinguish themselves and connect with companies.
    • TodayLaunch is a free dashboard for your social media accounts.
    • Stachify
    • Skim is a playful way to meet new people.
    • NuORDER online fashion wholesale for brands and buyers.
    • UPcload helps you find clothes that fit you when shopping online.
    • TreinoSmart is a system for gym and physical trainers.
    • ShoeJitsu let's you shop, compare, and share fashion.
    • Kyyti is a meeting place for rides.
    • Nimble Quiz allows you to quickly create and manage simple multiple choice quizzes.
    • Fur Baby Rescue provides a temporary, safe home for cats, dogs, puppies and kittens.
    • McDonalds food, your questions answered.
    • SquadSheet is a sports app packed with fun and powerful social features.
    • VeriWalk is live GPS dog walking software.
    • DashKu lets you build real-time dashboards and widgets using HTML, CSS, and JavaScript.
    • First Impression helps singles find fun, safe and exciting dates.
    • Muffle is a suite of Twitter reputation management tools.
    • Zootify is a live, real-time YouTube party app.
    diff --git a/docs/3.4.x/docs/queries.html b/docs/3.4.x/docs/queries.html new file mode 100644 index 00000000000..c939cc5c648 --- /dev/null +++ b/docs/3.4.x/docs/queries.html @@ -0,0 +1,41 @@ +Mongoose Queries v3.4.0Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    + +

    When a callback function:

    + +
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    + +

    Let's take a look at what happens when passing a callback:

    var Person = db.model('Person', yourSchema);
    +
    +// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    +Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    Here we see that the query was executed immediately and the results passed to our callback. +Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    +var query = Person.findOne({ 'name.last': 'Ghost' });
    +
    +// selecting the `name` and `occupation` fields
    +query.select('name occupation');
    +
    +// execute the query at a later time
    +query.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    +.find({ occupation: /host/ })
    +.where('name.last').equals('Ghost')
    +.where('age').gt(17).lt(66)
    +.where('likes').in(['vaporizing', 'talking'])
    +.limit(10)
    +.sort('-occupation')
    +.select('name occupation')
    +.exec(callback);
    +

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    diff --git a/docs/3.4.x/docs/releases b/docs/3.4.x/docs/releases new file mode 100644 index 00000000000..6131da8e54a --- /dev/null +++ b/docs/3.4.x/docs/releases @@ -0,0 +1,6 @@ +3.3.x +3.2.x +3.1.x +3.0.x +2.8.x +2.7.x diff --git a/docs/3.4.x/docs/schematypes.html b/docs/3.4.x/docs/schematypes.html new file mode 100644 index 00000000000..b3a96950f30 --- /dev/null +++ b/docs/3.4.x/docs/schematypes.html @@ -0,0 +1,67 @@ +Mongoose SchemaTypes v3.4.0Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    +  name:    String,
    +  binary:  Buffer,
    +  living:  Boolean,
    +  updated: { type: Date, default: Date.now },
    +  age:     { type: Number, min: 18, max: 65 },
    +  mixed:   Schema.Types.Mixed,
    +  _someId: Schema.Types.ObjectId,
    +  array:      [],
    +  ofString:   [String],
    +  ofNumber:   [Number],
    +  ofDates:    [Date],
    +  ofBuffer:   [Buffer],
    +  ofBoolean:  [Boolean],
    +  ofMixed:    [Schema.Types.Mixed],
    +  ofObjectId: [Schema.Types.ObjectId],
    +  nested: {
    +    stuff: { type: String, lowercase: true, trim: true }
    +  }
    +})
    +
    +// example use
    +
    +var Thing = mongoose.model('Thing', schema);
    +
    +var m = new Thing;
    +m.name = 'Statue of Liberty';
    +m.age = 125;
    +m.updated = new Date;
    +m.binary = new Buffer(0);
    +m.living = false;
    +m.mixed = {[ any: { thing: 'i want' } ]};
    +m.markModified('mixed');
    +m._someId = new mongoose.Types.ObjectId;
    +m.array.push(1);
    +m.ofString.push("strings!");
    +m.ofNumber.unshift(1,2,3,4);
    +m.ofDates.addToSet(new Date);
    +m.ofBuffer.pop();
    +m.ofMixed = [1, [], 'three', { four: 5 }];
    +m.nested.stuff = 'good';
    +m.save(callback);
    +

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    +var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    +person.markModified('anything');
    +person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    +var ObjectId = mongoose.Schema.Types.ObjectId;
    +var Car = new Schema({ driver: ObjectId });
    +// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    +var ToyBox = new Schema({
    +  toys: [ToySchema],
    +  buffers: [Buffer],
    +  string:  [String],
    +  numbers: [Number]
    +  // ... etc
    +});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    +var Empty2 = new Schema({ any: Array });
    +var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    +var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Models.

    diff --git a/docs/3.4.x/docs/source/_docs b/docs/3.4.x/docs/source/_docs new file mode 100644 index 00000000000..f30bb740efb --- /dev/null +++ b/docs/3.4.x/docs/source/_docs @@ -0,0 +1,16713 @@ + +### lib/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = require('./connectionstate')", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "require('./connectionstate')", + "string": "STATES" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the collection" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "conn", + "description": "A MongooseConnection instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "optional collection options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", + "summary": "

    Abstract Collection constructor

    ", + "body": "

    This is the base class that drivers inherit from and implement.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Collection (name, conn, opts) {\n this.name = name;\n this.conn = conn;\n this.buffer = true;\n this.queue = [];\n\n if ('number' == typeof opts) opts = { size: opts };\n this.opts = opts || {};\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", + "ctx": { + "type": "function", + "name": "Collection", + "string": "Collection()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "name" + } + ], + "description": { + "full": "

    The collection name

    ", + "summary": "

    The collection name

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.name;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "conn" + } + ], + "description": { + "full": "

    The Connection instance

    ", + "summary": "

    The Connection instance

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.conn;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database connects

    ", + "summary": "

    Called when the database connects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onOpen", + "string": "Collection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database disconnects

    ", + "summary": "

    Called when the database disconnects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onClose = function () {\n this.buffer = true;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onClose", + "string": "Collection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the method to queue" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method when executed" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Queues a method for later execution when its
    database connection opens.

    ", + "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "addQueue", + "string": "Collection.prototype.addQueue()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes all queued methods and clears the queue.

    ", + "summary": "

    Executes all queued methods and clears the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "doQueue", + "string": "Collection.prototype.doQueue()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "ensureIndex", + "string": "Collection.prototype.ensureIndex()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findAndModify", + "string": "Collection.prototype.findAndModify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findOne", + "string": "Collection.prototype.findOne()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "find", + "string": "Collection.prototype.find()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "insert", + "string": "Collection.prototype.insert()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "save", + "string": "Collection.prototype.save()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "update", + "string": "Collection.prototype.update()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "getIndexes", + "string": "Collection.prototype.getIndexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "mapReduce", + "string": "Collection.prototype.mapReduce()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Collection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Collection", + "string": "module.exports" + } + } +] +### lib/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = utils.EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , MongooseError = require('./error')\n , assert =require('assert')\n , muri = require('muri')", + "ctx": { + "type": "declaration", + "name": "url", + "value": "require('url')", + "string": "url" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Protocol prefix regexp.

    ", + "summary": "

    Protocol prefix regexp.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", + "ctx": { + "type": "declaration", + "name": "rgxProtocol", + "value": "/^(?:.)+:\\/\\//", + "string": "rgxProtocol" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "a mongoose instance" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." + }, + { + "type": "event", + "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." + }, + { + "type": "event", + "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." + }, + { + "type": "event", + "string": "`disconnecting`: Emitted when `connection.close()` was executed." + }, + { + "type": "event", + "string": "`disconnected`: Emitted after getting disconnected from the db." + }, + { + "type": "event", + "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." + }, + { + "type": "event", + "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." + }, + { + "type": "event", + "string": "`error`: Emitted when an error occurs on this connection." + }, + { + "type": "event", + "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", + "summary": "

    Connection constructor

    ", + "body": "

    For practical reasons, a Connection equals a Db.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.hosts = null;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", + "ctx": { + "type": "function", + "name": "Connection", + "string": "Connection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter

    ", + "summary": "

    Inherit from EventEmitter

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Connection", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Connection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readyState" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", + "summary": "

    Connection ready state

    ", + "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" + }, + { + "tags": [ + { + "type": "property", + "string": "collections" + } + ], + "description": { + "full": "

    A hash of the collections associated with this connection

    ", + "summary": "

    A hash of the collections associated with this connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collections;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    The mongodb.Db instance, set when the connection is opened

    ", + "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.db;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "connection_string", + "description": "mongodb://uri or the host to which you are connecting" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[port]", + "description": "database port" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    \n\n

    Options passed take precedence over options included in connection strings.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    \n\n

    Options passed take precedence over options included in connection strings.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , parsed\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n try {\n parsed = muri(host);\n } catch (err) {\n this.error(err, callback);\n return this;\n }\n\n database = parsed.db;\n host = parsed.hosts.length && parsed.hosts[0].host;\n port = parsed.hosts[0].port;\n }\n\n this.options = this.parseOptions(options, parsed && parsed.options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing database name.'), callback);\n return this;\n }\n\n // authentication\n if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else if (parsed && parsed.auth) {\n this.user = parsed.auth.user;\n this.pass = parsed.auth.pass;\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "open", + "string": "Connection.prototype.open()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "uris", + "description": "comma-separated mongodb:// `URI`s" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name if not included in `uris`" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "passed to the internal driver" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connects to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Options passed take precedence over options included in connection strings.

    ", + "summary": "

    Connects to a replica set.

    ", + "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\n
    \n\n

    Options passed take precedence over options included in connection strings.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n if (!rgxProtocol.test(uris)) {\n uris = 'mongodb://' + uris;\n }\n\n var self = this;\n\n switch (arguments.length) {\n case 3:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'object':\n callback = options;\n options = database;\n database = null;\n break;\n }\n\n if ('function' === typeof options) {\n callback = options;\n options = {};\n }\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n var parsed;\n try {\n parsed = muri(uris);\n } catch (err) {\n this.error(err, callback);\n return this;\n }\n\n if (!this.name) {\n this.name = parsed.db;\n }\n\n this.hosts = parsed.hosts;\n this.options = this.parseOptions(options, parsed && parsed.options);\n this.replica = true;\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "openSet", + "string": "Connection.prototype.openSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "optional" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", + "summary": "

    error

    ", + "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "error", + "string": "Connection.prototype.error()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen();\n callback && callback();\n });\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "_open", + "string": "Connection.prototype._open()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection is opened

    ", + "summary": "

    Called when the connection is opened

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onOpen = function () {\n var self = this;\n\n function open () {\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass)\n self.db.authenticate(self.user, self.pass, open);\n else\n open();\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onOpen", + "string": "Connection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "self" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "close", + "string": "Connection.prototype.close()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onClose", + "string": "Connection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "of the collection" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional collection options" + }, + { + "type": "return", + "types": [ + "Collection" + ], + "description": "collection instance" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retrieves a collection, creating it if not cached.

    ", + "summary": "

    Retrieves a collection, creating it if not cached.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "collection", + "string": "Connection.prototype.collection()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "the model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "a schema. necessary when defining a model" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name of mongodb collection (optional) if not given it will be induced from model name" + }, + { + "type": "see", + "local": "Mongoose#model #index_Mongoose-model", + "visibility": "Mongoose#model" + }, + { + "type": "return", + "types": [ + "Model" + ], + "description": "The compiled model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    ", + "summary": "

    Defines or retrieves a model.

    ", + "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.model = function (name, schema, collection) {\n // collection name discovery\n if ('string' == typeof schema) {\n collection = schema;\n schema = false;\n }\n\n if (this.models[name] && !collection) {\n // model exists but we are not subclassing with custom collection\n if (schema instanceof Schema && schema != this.models[name].schema) {\n throw new MongooseError.OverwriteModelError(name);\n }\n return this.models[name];\n }\n\n var opts = { cache: false, connection: this }\n var model;\n\n if (schema instanceof Schema) {\n // compile a model\n model = this.base.model(name, schema, collection, opts)\n\n // only the first model with this name is cached to allow\n // for one-offs with custom collection names etc.\n if (!this.models[name]) {\n this.models[name] = model;\n }\n\n model.init();\n return model;\n }\n\n if (this.models[name] && collection) {\n // subclassing current model with alternate collection\n model = this.models[name];\n schema = model.prototype.schema;\n var sub = model.__subclass(this, schema, collection);\n // do not cache the sub model\n return sub;\n }\n\n // lookup model in mongoose module\n model = this.base.models[name];\n\n if (!model) {\n throw new MongooseError.MissingSchemaError(name);\n }\n\n if (this == model.prototype.db\n && (!collection || collection == model.collection.name)) {\n // model already uses this connection.\n\n // only the first model with this name is cached to allow\n // for one-offs with custom collection names etc.\n if (!this.models[name]) {\n this.models[name] = model;\n }\n\n return model;\n }\n\n return this.models[name] = model.__subclass(this, schema, collection);\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "model", + "string": "Connection.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "level", + "description": "either off (0), slow (1), or all (2)" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[ms]", + "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Set profiling level.

    ", + "summary": "

    Set profiling level.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "setProfiling", + "string": "Connection.prototype.setProfiling()" + } + }, + { + "tags": [], + "description": { + "full": "

    Noop.

    ", + "summary": "

    Noop.

    ", + "body": "" + }, + "ignore": true, + "code": "function noop () {}", + "ctx": { + "type": "function", + "name": "noop", + "string": "noop()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", + "ctx": { + "type": "property", + "receiver": "Connection", + "name": "STATES", + "value": "STATES", + "string": "Connection.STATES" + } + } +] +### lib/connectionstate.js +[ + { + "tags": [], + "description": { + "full": "

    Connection states

    ", + "summary": "

    Connection states

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "module.exports = exports = Object.create(null)", + "string": "STATES" + } + } +] +### lib/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , StateMachine = require('./statemachine')\n , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n , ValidationError = require('./errors/validation')\n , DocumentError = require('./errors/document')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray\n , MongooseArray", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the values to set" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "the fields which were selected in the query returning this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "bool, should we auto create an ObjectId _id" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." + }, + { + "type": "event", + "string": "`save`: Emitted when the document is successfully saved" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document constructor.

    ", + "summary": "

    Document constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Document (obj, fields, skipId) {\n // node <0.4.3 bug\n if (!this._events) this._events = {};\n this.setMaxListeners(0);\n\n if ('boolean' === typeof fields) {\n this._strictMode = fields;\n this._selected = fields = undefined;\n } else {\n this._strictMode = this.schema.options && this.schema.options.strict;\n this._selected = fields;\n }\n\n this.isNew = true;\n this.errors = undefined;\n this._shardval = undefined;\n this._saveError = undefined;\n this._validationError = undefined;\n this._adhocPaths = undefined;\n this._removing = undefined;\n this._inserting = undefined;\n this.__version = undefined;\n this.__getters = {};\n this.__id = undefined;\n\n this._activePaths = new ActiveRoster;\n\n var required = this.schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this._activePaths.require(required[i]);\n }\n\n this._doc = this._buildDoc(obj, fields, skipId);\n if (obj) this.set(obj, undefined, true);\n this._registerHooks();\n};", + "ctx": { + "type": "function", + "name": "Document", + "string": "Document()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Document.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "schema" + } + ], + "description": { + "full": "

    The documents schema.

    ", + "summary": "

    The documents schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.schema;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "isNew" + } + ], + "description": { + "full": "

    Boolean flag specifying if the document is new.

    ", + "summary": "

    Boolean flag specifying if the document is new.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isNew;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "local": "Schema options /docs/guide.html#options", + "visibility": "Schema" + }, + { + "type": "property", + "string": "id" + } + ], + "description": { + "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", + "summary": "

    The string version of this documents _id.

    ", + "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.id;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "errors" + } + ], + "description": { + "full": "

    Hash containing current validation errors.

    ", + "summary": "

    Hash containing current validation errors.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.errors;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Builds the default doc structure

    ", + "summary": "

    Builds the default doc structure

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self._activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_buildDoc", + "string": "Document.prototype._buildDoc()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", + "summary": "

    Initializes the document without setters or marking anything modified.

    ", + "body": "

    Called internally after a document is returned from mongodb.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.init = function (doc, fn) {\n this.isNew = false;\n\n init(this, doc, this._doc);\n this._storeShard();\n\n this.emit('init', this);\n if (fn) fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "init", + "string": "Document.prototype.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "self", + "description": "document instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "raw mongodb doc" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "object we are initializing" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Init helper.

    ", + "summary": "

    Init helper.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) {\n doc[i] = {};\n }\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self._activePaths.init(path);\n }\n }\n};", + "ctx": { + "type": "function", + "name": "init", + "string": "init()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", + "summary": "

    Stores the current values of the shard keys.

    ", + "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._storeShard = function _storeShard () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this._shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_storeShard", + "string": "Document.prototype._storeShard()" + } + }, + { + "tags": [], + "description": { + "full": "

    Set up middleware support

    ", + "summary": "

    Set up middleware support

    ", + "body": "" + }, + "ignore": true, + "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    ", + "summary": "

    Sends an update command with this document _id as the query selector.

    ", + "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "update", + "string": "Document.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "path", + "description": "path or object of key/vals to set" + }, + { + "type": "param", + "types": [ + "Any" + ], + "name": "val", + "description": "the value to set" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for \"on-the-fly\" attributes" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optionally specify options that modify the behavior of the set" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    ", + "summary": "

    Sets the value of a path, or many paths.

    ", + "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.set = function (path, val, type, options) {\n if (type && 'Object' == type.constructor.name) {\n options = type;\n type = undefined;\n }\n\n var merge = options && options.merge\n , adhoc = type && true !== type\n , constructing = true === type\n , adhocs\n\n if (adhoc) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n pathtype = this.schema.pathType(prefix + key);\n if (null != path[key]\n && 'Object' == path[key].constructor.name\n && 'virtual' != pathtype\n && !(this._path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (this._strictMode) {\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == this._strictMode) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n if (!merge) this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && this._strictMode) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this._path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this._set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this._set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "set", + "string": "Document.prototype.set()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determine if we should mark this change as modified.

    ", + "summary": "

    Determine if we should mark this change as modified.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._shouldModify = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n if (this.isNew) return true;\n if (this.isDirectModified(pathToMark)) return false;\n\n if (undefined === val && !this.isSelected(path)) {\n // when a path is not selected in a query, its initial\n // value will be undefined.\n return true;\n }\n\n if (undefined === val && path in this._activePaths.states.default) {\n // we're just unsetting the default value which was never saved\n return false;\n }\n\n if (!deepEqual(val, priorVal || this.get(path))) {\n return true;\n }\n\n if (!constructing &&\n null != val &&\n path in this._activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n return true;\n }\n\n return false;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_shouldModify", + "string": "Document.prototype._shouldModify()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._set = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n var shouldModify = this._shouldModify.apply(this, arguments);\n\n if (shouldModify) {\n this.markModified(pathToMark, val);\n\n // handle directly setting arrays (gh-1126)\n MongooseArray || (MongooseArray = require('./types/array'));\n if (val instanceof MongooseArray) {\n val._registerAtomic('$set', val);\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_set", + "string": "Document.prototype._set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets a raw value from a path (no getters)

    ", + "summary": "

    Gets a raw value from a path (no getters)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.getValue = function (path) {\n var parts = path.split('.')\n , obj = this._doc\n , part;\n\n for (var i = 0, l = parts.length; i < l; i++) {\n part = parts[i];\n obj = obj.getValue\n ? obj.getValue(part) // If we have an embedded array document member\n : obj[part];\n if (!obj) return obj;\n }\n\n return obj;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "getValue", + "string": "Document.prototype.getValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.setValue = function (path, val) {\n var parts = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, len = parts.length-1; i < len; i++) {\n obj = obj[parts[i]];\n }\n\n obj[parts[len]] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "setValue", + "string": "Document.prototype.setValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for on-the-fly attributes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", + "summary": "

    Returns the value of a path.

    ", + "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this._adhocPaths || (this._adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this._path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "get", + "string": "Document.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns the schematype for the given path.

    ", + "summary": "

    Returns the schematype for the given path.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._path = function (path) {\n var adhocs = this._adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_path", + "string": "Document.prototype._path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to mark modified" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", + "summary": "

    Marks the path as having pending changes to write to the db.

    ", + "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.markModified = function (path) {\n this._activePaths.modify(path);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "markModified", + "string": "Document.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "function to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope with which to call fn" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this._error(e);\n res = false;\n }\n return res;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "try", + "string": "Document.prototype.try()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the list of paths that have been modified.

    ", + "summary": "

    Returns the list of paths that have been modified.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this._activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "modifiedPaths", + "string": "Document.prototype.modifiedPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", + "summary": "

    Returns true if this document was modified, else false.

    ", + "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this._activePaths.some('modify');\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isModified", + "string": "Document.prototype.isModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", + "summary": "

    Returns true if path was directly set and modified, else false.

    ", + "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this._activePaths.states.modify);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isDirectModified", + "string": "Document.prototype.isDirectModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was initialized.

    ", + "summary": "

    Checks if path was initialized.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isInit = function (path) {\n return (path in this._activePaths.states.init);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isInit", + "string": "Document.prototype.isInit()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", + "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", + "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this._selected) {\n\n if ('_id' === path) {\n return 0 !== this._selected._id;\n }\n\n var paths = Object.keys(this._selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this._selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this._selected[cur];\n break;\n }\n\n if (path in this._selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isSelected", + "string": "Document.prototype.isSelected()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "cb", + "description": "called after validation completes, passing an error if one occurred" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", + "summary": "

    Executes registered validation rules for this document.

    ", + "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this._activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this._activePaths.states.init));\n paths = paths.concat(Object.keys(this._activePaths.states.modify));\n paths = paths.concat(Object.keys(this._activePaths.states.default));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n p.doValidate(self.getValue(path), function (err) {\n if (err) self.invalidate(path, err, true);\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self._validationError;\n self._validationError = undefined;\n self.emit('validate', self);\n cb(err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "validate", + "string": "Document.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "the error which states the reason `path` was invalid" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.invalidate = function (path, err) {\n if (!this._validationError) {\n this._validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n err = new ValidatorError(path, err);\n }\n\n this._validationError.errors[path] = err;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "invalidate", + "string": "Document.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Resets the internal modified state of this document.

    ", + "summary": "

    Resets the internal modified state of this document.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n })\n .forEach(function (array) {\n var i = array.length;\n while (i--) {\n var doc = array[i];\n if (!doc) continue;\n doc._reset();\n }\n });\n\n // clear atomics\n this._dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this._activePaths.clear('modify');\n this._validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self._activePaths.require(path);\n });\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_reset", + "string": "Document.prototype._reset()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns this documents dirty paths / vals.

    ", + "summary": "

    Returns this documents dirty paths / vals.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._dirty = function _dirty () {\n var self = this;\n\n var all = this._activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self._path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n if (!(item.value && top.value)) return;\n\n // special case for top level MongooseArrays\n if (top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_dirty", + "string": "Document.prototype._dirty()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compiles schemas.

    ", + "summary": "

    Compiles schemas.

    ", + "body": "" + }, + "ignore": true, + "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", + "ctx": { + "type": "function", + "name": "compile", + "string": "compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Defines the accessor named prop on the incoming prototype.

    ", + "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", + "body": "" + }, + "ignore": true, + "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.__getters)\n this.__getters = {};\n\n if (!this.__getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested._scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.__getters[path] = nested;\n }\n\n return this.__getters[path];\n }\n , set: function (v) {\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this._scope || this, path); }\n , set: function (v) { return this.set.call(this._scope || this, path, v); }\n });\n }\n};", + "ctx": { + "type": "function", + "name": "define", + "string": "define()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Assigns/compiles schema into this documents prototype.

    ", + "summary": "

    Assigns/compiles schema into this documents prototype.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_setSchema", + "string": "Document.prototype._setSchema()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register default hooks

    ", + "summary": "

    Register default hooks

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._registerHooks = function _registerHooks () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this._activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n if (error) return;\n\n // handle sparse arrays by using for loop vs array.forEach\n // which skips the sparse elements\n\n var len = array.length\n subdocs += len;\n\n for (var i = 0; i < len; ++i) {\n if (error) break;\n\n var doc = array[i];\n if (!doc) {\n --subdocs || next();\n continue;\n }\n\n doc.save(handleSave);\n }\n });\n\n function handleSave (err) {\n if (error) return;\n\n if (err) {\n self._validationError = undefined;\n return next(error = err);\n }\n\n --subdocs || next();\n }\n\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n if (this._saveError) {\n next(this._saveError);\n this._saveError = null;\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this._doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_registerHooks", + "string": "Document.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Registers an error

    ", + "summary": "

    Registers an error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._error = function (err) {\n this._saveError = err;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_error", + "string": "Document.prototype._error()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes methods queued from the Schema definition

    ", + "summary": "

    Executes methods queued from the Schema definition

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype._doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "_doQueue", + "string": "Document.prototype._doQueue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "js object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this document into a plain javascript object

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    ", + "summary": "

    Converts this document into a plain javascript object

    ", + "body": "

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toObject = function (options) {\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n if (true === options.transform) {\n var opts = options.json\n ? this.schema.options.toJSON\n : this.schema.options.toObject;\n if (opts) {\n options.transform = opts.transform;\n }\n }\n\n if ('function' == typeof options.transform) {\n var xformed = options.transform(this, ret, options);\n if ('undefined' != typeof xformed) ret = xformed;\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toObject", + "string": "Document.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "json", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "either `virtuals` or `paths`" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "`json`" + } + ], + "description": { + "full": "

    Applies virtuals properties to json.

    ", + "summary": "

    Applies virtuals properties to json.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", + "ctx": { + "type": "function", + "name": "applyGetters", + "string": "applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "same options as [Document#toObject](#document_Document-toObject)" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "see", + "local": "Document#toObject #document_Document-toObject", + "visibility": "Document#toObject" + }, + { + "type": "", + "string": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    \n\n

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", + "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", + "body": "

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toJSON", + "string": "Document.prototype.toJSON()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name\n ? options\n : undefined\n return inspect(this.toObject(opts));\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "inspect", + "string": "Document.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "toString" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toString = Document.prototype.inspect;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "toString", + "value": "Document.prototype.inspect", + "string": "Document.prototypetoString" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "a document to compare" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", + "summary": "

    Returns true if the Document stores the same data as doc.

    ", + "body": "

    Documents are considered equal when they have matching _ids.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "equals", + "string": "Document.prototype.equals()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", + "ctx": { + "type": "property", + "receiver": "Document", + "name": "ValidationError", + "value": "ValidationError", + "string": "Document.ValidationError" + } + } +] +### lib/drivers/node-mongodb-native/binary.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require('mongodb').BSONPure.Binary", + "string": "Binary" + } + } +] +### lib/drivers/node-mongodb-native/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", + "ctx": { + "type": "declaration", + "name": "MongooseCollection", + "value": "require('../../collection')", + "string": "MongooseCollection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Collection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", + "summary": "

    A node-mongodb-native collection implementation.

    ", + "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", + "ctx": { + "type": "function", + "name": "NativeCollection", + "string": "NativeCollection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from abstract Collection.

    ", + "summary": "

    Inherit from abstract Collection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "__proto__", + "value": "MongooseCollection.prototype", + "string": "NativeCollection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection opens.

    ", + "summary": "

    Called when the connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n if (this.collection) {\n return MongooseCollection.prototype.onOpen.call(self);\n }\n\n if (!self.opts.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onOpen", + "string": "NativeCollection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onClose", + "string": "NativeCollection.prototype.onClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Copy the collection methods and make them subject to queues

    ", + "summary": "

    Copy the collection methods and make them subject to queues

    ", + "body": "" + }, + "ignore": true, + "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", + "ctx": { + "type": "function", + "name": "print", + "string": "print()" + } + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if ('Date' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", + "ctx": { + "type": "function", + "name": "format", + "string": "format()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "method", + "string": "getIndexes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retreives information about this collections indexes.

    ", + "summary": "

    Retreives information about this collections indexes.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "getIndexes", + "value": "NativeCollection.prototype.indexInformation", + "string": "NativeCollection.prototypegetIndexes" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeCollection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeCollection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", + "ctx": { + "type": "declaration", + "name": "MongooseConnection", + "value": "require('../../connection')", + "string": "MongooseConnection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Connection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native connection implementation.

    ", + "summary": "

    A node-mongodb-native connection implementation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n};", + "ctx": { + "type": "function", + "name": "NativeConnection", + "string": "NativeConnection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Connection.

    ", + "summary": "

    Inherits from Connection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeConnection", + "name": "__proto__", + "value": "MongooseConnection.prototype", + "string": "NativeConnection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpen = function (fn) {\n var server\n , self = this;\n\n if (!this.db) {\n server = new mongo.Server(this.host, this.port, this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};\n\nfunction listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpen", + "string": "NativeConnection.prototype.doOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", + "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", + "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (!this.db) {\n var servers = []\n , self = this\n\n this.hosts.forEach(function (server) {\n servers.push(new mongo.Server(server.host, server.port, self.options.server));\n })\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n }\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpenSet", + "string": "NativeConnection.prototype.doOpenSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doClose", + "string": "NativeConnection.prototype.doClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "passed", + "description": "options that were passed directly during connection" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[connStrOptions]", + "description": "options that were passed in the connection string" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Prepares default connection options for the node-mongodb-native driver.

    \n\n

    NOTE: passed options take precedence over connection string options.

    ", + "summary": "

    Prepares default connection options for the node-mongodb-native driver.

    ", + "body": "

    NOTE: passed options take precedence over connection string options.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {\n var o = passed || {};\n o.db || (o.db = {});\n o.server || (o.server = {});\n o.replset || (o.replset = {});\n o.server.socketOptions || (o.server.socketOptions = {});\n o.replset.socketOptions || (o.replset.socketOptions = {});\n\n var opts = connStrOpts || {};\n Object.keys(opts).forEach(function (name) {\n switch (name) {\n case 'poolSize':\n if ('undefined' == typeof o.server.poolSize) {\n o.server.poolSize = o.replset.poolSize = opts[name];\n }\n break;\n case 'slaveOk':\n if ('undefined' == typeof o.server.slave_ok) {\n o.server.slave_ok = opts[name];\n }\n break;\n case 'autoReconnect':\n if ('undefined' == typeof o.server.auto_reconnect) {\n o.server.auto_reconnect = opts[name];\n }\n break;\n case 'ssl':\n case 'socketTimeoutMS':\n case 'connectTimeoutMS':\n if ('undefined' == typeof o.server.socketOptions[name]) {\n o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];\n }\n break;\n case 'retries':\n case 'reconnectWait':\n case 'rs_name':\n if ('undefined' == typeof o.replset[name]) {\n o.replset[name] = opts[name];\n }\n break;\n case 'replicaSet':\n if ('undefined' == typeof o.replset.rs_name) {\n o.replset.rs_name = opts[name];\n }\n break;\n case 'readSecondary':\n if ('undefined' == typeof o.replset.read_secondary) {\n o.replset.read_secondary = opts[name];\n }\n break;\n case 'nativeParser':\n if ('undefined' == typeof o.db.native_parser) {\n o.db.native_parser = opts[name];\n }\n break;\n case 'w':\n case 'safe':\n case 'fsync':\n case 'journal':\n case 'wtimeoutMS':\n if ('undefined' == typeof o.db[name]) {\n o.db[name] = opts[name];\n }\n break;\n case 'readPreference':\n if ('undefined' == typeof o.db.read_preference) {\n o.db.read_preference = opts[name];\n }\n break;\n case 'readPreferenceTags':\n if ('undefined' == typeof o.db.read_preference_tags) {\n o.db.read_preference_tags = opts[name];\n }\n break;\n }\n })\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n if (!o.db.read_preference) {\n o.db.read_preference = 'primary';\n }\n\n o.db.forceServerObjectId = false;\n\n // default safe using new nomenclature\n if (!(o.db.journal || o.db.fsync || o.db.safe || 'w' in o.db)) {\n o.db.w = 1;\n }\n\n validate(o);\n return o;\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "parseOptions", + "string": "NativeConnection.prototype.parseOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "o", + "description": "" + } + ], + "description": { + "full": "

    Validates the driver db options.

    ", + "summary": "

    Validates the driver db options.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function validate (o) {\n if (-1 === o.db.w || 0 === o.db.w) {\n if (o.db.journal || o.db.fsync || o.db.safe) {\n throw new Error(\n 'Invalid writeConcern: '\n + 'w set to -1 or 0 cannot be combined with safe|fsync|journal');\n }\n }\n}", + "ctx": { + "type": "function", + "name": "validate", + "string": "validate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeConnection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeConnection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/objectid.js +[ + { + "tags": [ + { + "type": "constructor", + "string": "NodeMongoDbObjectId" + }, + { + "type": "see", + "local": "ObjectId", + "visibility": "ObjectId" + } + ], + "description": { + "full": "

    node-mongodb-native ObjectId

    ", + "summary": "

    node-mongodb-native ObjectId

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require('mongodb').BSONPure.ObjectID", + "string": "ObjectId" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", + "ctx": { + "type": "declaration", + "name": "ObjectIdToString", + "value": "ObjectId.toString.bind(ObjectId)", + "string": "ObjectIdToString" + } + } +] +### lib/error.js +[ + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" + } + ], + "description": { + "full": "

    Mongoose error

    ", + "summary": "

    Mongoose error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", + "ctx": { + "type": "function", + "name": "MongooseError", + "string": "MongooseError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Error.

    ", + "summary": "

    Inherits from Error.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseError.prototype.__proto__ = Error.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseError", + "name": "__proto__", + "value": "Error.prototype", + "string": "MongooseError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = MongooseError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = MongooseError", + "string": "module.exports" + } + }, + { + "tags": [], + "description": { + "full": "

    Expose subclasses

    ", + "summary": "

    Expose subclasses

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseError.CastError = require('./errors/cast');\nMongooseError.DocumentError = require('./errors/document');\nMongooseError.ValidationError = require('./errors/validation')\nMongooseError.ValidatorError = require('./errors/validator')\nMongooseError.VersionError =require('./errors/version')\nMongooseError.OverwriteModelError = require('./errors/overwriteModel')\nMongooseError.MissingSchemaError = require('./errors/missingSchema')", + "ctx": { + "type": "property", + "receiver": "MongooseError", + "name": "CastError", + "value": "require('./errors/cast')", + "string": "MongooseError.CastError" + } + } +] +### lib/errors/cast.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casting Error constructor.

    ", + "summary": "

    Casting Error constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function CastError (type, value) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n};", + "ctx": { + "type": "function", + "name": "CastError", + "string": "CastError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "CastError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "CastError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "CastError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = CastError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "CastError", + "string": "module.exports" + } + } +] +### lib/errors/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document Error

    ", + "summary": "

    Document Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", + "ctx": { + "type": "function", + "name": "DocumentError", + "string": "DocumentError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "DocumentError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = DocumentError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = DocumentError", + "string": "module.exports" + } + } +] +### lib/errors/missingSchema.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    MissingSchema Error constructor.

    ", + "summary": "

    MissingSchema Error constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function MissingSchemaError (name) {\n var msg = 'Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)';\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'MissingSchemaError';\n};", + "ctx": { + "type": "function", + "name": "MissingSchemaError", + "string": "MissingSchemaError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "MissingSchemaError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "MissingSchemaError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "MissingSchemaError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MissingSchemaError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MissingSchemaError", + "string": "module.exports" + } + } +] +### lib/errors/overwriteModel.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    OverwriteModel Error constructor.

    ", + "summary": "

    OverwriteModel Error constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function OverwriteModelError (name) {\n MongooseError.call(this, 'Cannot overwrite `' + name + '` model once compiled.');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'OverwriteModelError';\n};", + "ctx": { + "type": "function", + "name": "OverwriteModelError", + "string": "OverwriteModelError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "OverwriteModelError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "OverwriteModelError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "OverwriteModelError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = OverwriteModelError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "OverwriteModelError", + "string": "module.exports" + } + } +] +### lib/errors/validation.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "instance", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    Document Validation Error

    ", + "summary": "

    Document Validation Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", + "ctx": { + "type": "function", + "name": "ValidationError", + "string": "ValidationError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Console.log helper

    ", + "summary": "

    Console.log helper

    ", + "body": "" + }, + "ignore": false, + "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", + "ctx": { + "type": "method", + "constructor": "ValidationError", + "name": "toString", + "string": "ValidationError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidationError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidationError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = ValidationError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = ValidationError", + "string": "module.exports" + } + } +] +### lib/errors/validator.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Schema validator error

    ", + "summary": "

    Schema validator error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidatorError (path, type) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n};", + "ctx": { + "type": "function", + "name": "ValidatorError", + "string": "ValidatorError()" + } + }, + { + "tags": [], + "description": { + "full": "

    toString helper

    ", + "summary": "

    toString helper

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", + "ctx": { + "type": "method", + "constructor": "ValidatorError", + "name": "toString", + "string": "ValidatorError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError

    ", + "summary": "

    Inherits from MongooseError

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidatorError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidatorError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ValidatorError", + "string": "module.exports" + } + } +] +### lib/errors/version.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Version Error constructor.

    ", + "summary": "

    Version Error constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function VersionError () {\n MongooseError.call(this, 'No matching document found.');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'VersionError';\n};", + "ctx": { + "type": "function", + "name": "VersionError", + "string": "VersionError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "VersionError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "VersionError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "VersionError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = VersionError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "VersionError", + "string": "module.exports" + } + } +] +### lib/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", + "summary": "

    Mongoose constructor.

    ", + "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", + "ctx": { + "type": "function", + "name": "Mongoose", + "string": "Mongoose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", + "summary": "

    Sets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "set", + "string": "Mongoose.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "method", + "string": "get" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", + "summary": "

    Gets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.get = Mongoose.prototype.set;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "get", + "value": "Mongoose.prototype.set", + "string": "Mongoose.prototypeget" + } + }, + { + "tags": [], + "description": { + "full": "

    ReplSet connection string check.

    ", + "summary": "

    ReplSet connection string check.

    ", + "body": "" + }, + "ignore": true, + "code": "var rgxReplSet = /^.+,.+$/;", + "ctx": { + "type": "declaration", + "name": "rgxReplSet", + "value": "/^.+,.+$/", + "string": "rgxReplSet" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[uri]", + "description": "a mongodb:// URI" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options to pass to the driver" + }, + { + "type": "see", + "local": "Connection#open #connection_Connection-open", + "visibility": "Connection#open" + }, + { + "type": "see", + "local": "Connection#openSet #connection_Connection-openSet", + "visibility": "Connection#openSet" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "the created Connection object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Connection instance.

    \n\n

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    ", + "summary": "

    Creates a Connection instance.

    ", + "body": "

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "createConnection", + "string": "Mongoose.prototype.createConnection()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Mongoose#createConnection #index_Mongoose-createConnection", + "visibility": "Mongoose#createConnection" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    \n\n

    Options passed take precedence over options included in connection strings.

    ", + "summary": "

    Opens the default mongoose connection.

    ", + "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    \n\n

    Options passed take precedence over options included in connection strings.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "connect", + "string": "Mongoose.prototype.connect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "called after all connection close." + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Disconnects all connections.

    ", + "summary": "

    Disconnects all connections.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "disconnect", + "string": "Mongoose.prototype.disconnect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name (optional, induced from model name)" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipInit]", + "description": "whether to skip initialization (defaults to false)" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    ", + "summary": "

    Defines a model or retrieves it.

    ", + "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String });\nschema.set('collection', 'actor');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n if (!(schema instanceof Schema)) {\n collection = schema;\n schema = false;\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // handle internal options from connection.model()\n var options;\n if (skipInit && utils.isObject(skipInit)) {\n options = skipInit;\n skipInit = true;\n } else {\n options = {};\n }\n\n // look up schema for the collection. this might be a\n // default schema like system.indexes stored in SchemaDefaults.\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n // cache it so we only apply plugins once\n this.modelSchemas[name] = schema;\n this._applyPlugins(schema);\n } else {\n throw new mongoose.Error.MissingSchemaError(name);\n }\n }\n\n var model;\n var sub;\n\n // connection.model() may be passing a different schema for\n // an existing model name. in this case don't read from cache.\n if (this.models[name] && false !== options.cache) {\n if (schema instanceof Schema && schema != this.models[name].schema) {\n throw new mongoose.Error.OverwriteModelError(name);\n }\n\n if (collection) {\n // subclass current model with alternate collection\n model = this.models[name];\n schema = model.prototype.schema;\n sub = model.__subclass(this.connection, schema, collection);\n // do not cache the sub model\n return sub;\n }\n\n return this.models[name];\n }\n\n // ensure a schema exists\n if (!schema) {\n schema = this.modelSchemas[name];\n if (!schema) {\n throw new mongoose.Error.MissingSchemaError(name);\n }\n }\n\n if (!collection) {\n collection = schema.get('collection') || format(name);\n }\n\n var connection = options.connection || this.connection;\n model = Model.compile(name, schema, collection, connection, this);\n\n if (!skipInit) {\n model.init();\n }\n\n if (false === options.cache) {\n return model;\n }\n\n return this.models[name] = model;\n}", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "model", + "string": "Mongoose.prototype.model()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies global plugins to schema.

    ", + "summary": "

    Applies global plugins to schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mongoose.prototype._applyPlugins = function (schema) {\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n}", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "_applyPlugins", + "string": "Mongoose.prototype._applyPlugins()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "plugin callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "optional options" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "see", + "local": "plugins ./plugins.html", + "visibility": "plugins" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", + "summary": "

    Declares a global plugin executed on all Schemas.

    ", + "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "plugin", + "string": "Mongoose.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "connection" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", + "summary": "

    The default connection of the mongoose module.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" + }, + { + "tags": [], + "description": { + "full": "

    Driver depentend APIs

    ", + "summary": "

    Driver depentend APIs

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Connection

    ", + "summary": "

    Connection

    ", + "body": "" + }, + "ignore": true, + "code": "var Connection = require(driver + '/connection');", + "ctx": { + "type": "declaration", + "name": "Connection", + "value": "require(driver + '/connection')", + "string": "Connection" + } + }, + { + "tags": [], + "description": { + "full": "

    Collection

    ", + "summary": "

    Collection

    ", + "body": "" + }, + "ignore": true, + "code": "var Collection = require(driver + '/collection');", + "ctx": { + "type": "declaration", + "name": "Collection", + "value": "require(driver + '/collection')", + "string": "Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The exports object is an instance of Mongoose.

    ", + "summary": "

    The exports object is an instance of Mongoose.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "module.exports = exports = new Mongoose;\nvar mongoose = module.exports;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = new Mongoose", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Collection constructor

    ", + "summary": "

    The Mongoose Collection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Collection = Collection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Collection", + "value": "Collection", + "string": "mongoose.Collection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Connection constructor

    ", + "summary": "

    The Mongoose Connection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Connection = Connection;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Connection", + "value": "Connection", + "string": "mongoose.Connection" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose version

    ", + "summary": "

    Mongoose version

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.version = JSON.parse(\n require('fs').readFileSync(__dirname + '/../package.json', 'utf8')\n).version;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "version", + "value": "JSON.parse(", + "string": "mongoose.version" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", + "summary": "

    The Mongoose constructor

    ", + "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Mongoose = Mongoose;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Mongoose", + "value": "Mongoose", + "string": "mongoose.Mongoose" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", + "summary": "

    The Mongoose Schema constructor

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Schema = Schema;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Schema", + "value": "Schema", + "string": "mongoose.Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose SchemaType constructor.

    ", + "summary": "

    The Mongoose SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaType = SchemaType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaType", + "value": "SchemaType", + "string": "mongoose.SchemaType" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Schema.SchemaTypes #schema_Schema-Types", + "visibility": "Schema.SchemaTypes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", + "summary": "

    The various Mongoose SchemaTypes.

    ", + "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.SchemaTypes = Schema.Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "SchemaTypes", + "value": "Schema.Types", + "string": "mongoose.SchemaTypes" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose VirtualType constructor.

    ", + "summary": "

    The Mongoose VirtualType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.VirtualType = VirtualType;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "VirtualType", + "value": "VirtualType", + "string": "mongoose.VirtualType" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", + "summary": "

    The various Mongoose Types.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Types = Types;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Types", + "value": "Types", + "string": "mongoose.Types" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Query constructor.

    ", + "summary": "

    The Mongoose Query constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Query = Query;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Query", + "value": "Query", + "string": "mongoose.Query" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Promise constructor.

    ", + "summary": "

    The Mongoose Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Promise = Promise;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Promise", + "value": "Promise", + "string": "mongoose.Promise" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Model constructor.

    ", + "summary": "

    The Mongoose Model constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Model = Model;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Model", + "value": "Model", + "string": "mongoose.Model" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Document constructor.

    ", + "summary": "

    The Mongoose Document constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Document = Document;", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Document", + "value": "Document", + "string": "mongoose.Document" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The MongooseError constructor.

    ", + "summary": "

    The MongooseError constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.Error = require('./error');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "Error", + "value": "require('./error')", + "string": "mongoose.Error" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The node-mongodb-native driver Mongoose uses.

    ", + "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "mongoose.mongo = require('mongodb');", + "ctx": { + "type": "property", + "receiver": "mongoose", + "name": "mongo", + "value": "require('mongodb')", + "string": "mongoose.mongo" + } + } +] +### lib/model.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , VersionError = require('./errors/version')\n , Query = require('./query')\n , Schema = require('./schema')\n , utils = require('./utils')\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = utils.EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('./document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "values to with which to create the document" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "event", + "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." + }, + { + "type": "event", + "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Model constructor

    ", + "summary": "

    Model constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", + "ctx": { + "type": "function", + "name": "Model", + "string": "Model()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Document.

    \n\n

    All Model.prototype features are available on
    top level (non-sub) documents.

    ", + "summary": "

    Inherits from Document.

    ", + "body": "

    All Model.prototype features are available on
    top level (non-sub) documents.

    " + }, + "ignore": true, + "code": "Model.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "Model", + "name": "__proto__", + "value": "Document.prototype", + "string": "Model.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    Connection the model uses.

    ", + "summary": "

    Connection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.db;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "collection" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.collection;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "modelName" + } + ], + "description": { + "full": "

    The name of the model

    ", + "summary": "

    The name of the model

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.modelName;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "object" + }, + { + "type": "return", + "types": [ + "Object", + "undefined" + ], + "description": "population paths" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns what paths can be populated

    ", + "summary": "

    Returns what paths can be populated

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._getPopulationKeys = function getPopulationKeys (query) {\n if (!(query && query.options.populate)) return;\n\n var names = Object.keys(query.options.populate)\n , n = names.length\n , name\n , paths = {}\n , hasKeys\n , schema\n\n while (n--) {\n name = names[n];\n schema = this.schema.path(name);\n hasKeys = true;\n\n if (!schema) {\n // if the path is not recognized, it's potentially embedded docs\n // walk path atoms from right to left to find a matching path\n var pieces = name.split('.')\n , i = pieces.length;\n\n while (i--) {\n var path = pieces.slice(0, i).join('.')\n , pathSchema = this.schema.path(path);\n\n // loop until we find an array schema\n if (pathSchema && pathSchema.caster) {\n if (!paths[path]) {\n paths[path] = { sub: {} };\n }\n\n paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n break;\n }\n }\n } else {\n paths[name] = query.options.populate[name];\n hasKeys || (hasKeys = true);\n }\n }\n\n return hasKeys && paths;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_getPopulationKeys", + "string": "Model.prototype._getPopulationKeys()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "schema", + "description": "type for the oid" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "oid", + "description": "object id or array of object ids" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "query", + "description": "object specifying query conditions, fields, and options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Populates an object

    ", + "summary": "

    Populates an object

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._populate = function populate (schema, oid, query, fn) {\n if (!Array.isArray(oid)) {\n var conditions = query.conditions || {};\n conditions._id = oid;\n\n return this\n .db.model(query.model || schema.options.ref)\n .findOne(conditions, query.fields, query.options, fn);\n }\n\n if (!oid.length) {\n return fn(null, oid);\n }\n\n var model = this.db.model(query.model || schema.caster.options.ref)\n , conditions = query && query.conditions || {};\n\n conditions._id || (conditions._id = { $in: oid });\n\n model.find(conditions, query.fields, query.options, function (err, docs) {\n if (err) return fn(err);\n\n // user specified sort order?\n if (query.options && query.options.sort) {\n return fn(null, docs);\n }\n\n // put back in original id order (using a hash reduces complexity from n*n to 2n)\n var docHash = {};\n docs.forEach(function (doc) {\n docHash[doc._id] = doc;\n });\n\n var arr = [];\n oid.forEach(function (id) {\n if (id in docHash) arr.push(docHash[id]);\n });\n\n fn(null, arr);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_populate", + "string": "Model.prototype._populate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "query that originated the initialization" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs auto-population of relations.

    ", + "summary": "

    Performs auto-population of relations.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype.init = function init (doc, query, fn) {\n if ('function' == typeof query) {\n fn = query;\n query = null;\n }\n\n var populate = this._getPopulationKeys(query);\n\n if (!populate) {\n return Document.prototype.init.call(this, doc, fn);\n }\n\n // population from other models is necessary\n var self = this;\n\n init(doc, '', function (err) {\n if (err) return fn(err);\n Document.prototype.init.call(self, doc, fn);\n });\n\n return this;\n\n function init (obj, prefix, fn) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length;\n\n return next();\n\n function next () {\n if (--len < 0) return fn();\n\n var i = keys[len]\n , path = prefix + i\n , schema = self.schema.path(path)\n , total = 0\n , inline = false\n , poppath\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n return init(obj[i], path + '.', next);\n }\n\n if (!(obj[i] && schema && populate[path])) return next();\n\n // this query object is re-used and passed around. we clone\n // it to prevent query condition contamination between\n // one populate call to the next.\n poppath = utils.clone(populate[path]);\n\n if (poppath.sub) {\n obj[i].forEach(function (subobj) {\n inline = true;\n\n var pkeys = Object.keys(poppath.sub)\n , pi = pkeys.length\n , key\n\n while (pi--) {\n key = pkeys[pi];\n\n if (subobj[key]) (function (key) {\n total++;\n self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);\n function done (err, doc) {\n if (err) return error(err);\n subobj[key] = doc;\n if (--total < 1 && !inline) {\n next();\n }\n }\n })(key);\n }\n });\n\n inline = false;\n\n if (0 === total) return next();\n\n } else {\n self._populate(schema, obj[i], poppath, function (err, doc) {\n if (err) return error(err);\n obj[i] = doc;\n next();\n });\n }\n };\n };\n\n function error (err) {\n if (error.err) return;\n fn(error.err = err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "init", + "string": "Model.prototype.init()" + } + }, + { + "tags": [], + "description": { + "full": "

    Handles doc.save() callbacks

    ", + "summary": "

    Handles doc.save() callbacks

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self._inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self._storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.__version && !self._inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.__version);\n self.__version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new VersionError);\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", + "ctx": { + "type": "function", + "name": "handleSave", + "string": "handleSave()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "title": "middleware", + "url": "http://mongoosejs.com/docs/middleware.html", + "visibility": "http://mongoosejs.com/docs/middleware.html" + } + ], + "description": { + "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", + "summary": "

    Saves this document.

    ", + "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this._version(true, obj);\n this.collection.insert(obj, options, complete);\n this._reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this._inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this._inserting = false;\n\n var delta = this._delta();\n if (delta) {\n var where = this._where(delta[0]);\n this.collection.update(where, delta[1], options, complete);\n } else {\n process.nextTick(function () {\n complete(null);\n })\n }\n\n this._reset();\n this.emit('isNew', false);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "save", + "string": "Model.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Mixed" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[operation]", + "description": "" + } + ], + "description": { + "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.__version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.__version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.__version = VERSION_WHERE;\n }\n}", + "ctx": { + "type": "function", + "name": "operand", + "string": "operand()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "val", + "description": "" + } + ], + "description": { + "full": "

    Compiles an update and where clause for a val with _atomics.

    ", + "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function handleAtomics (self, where, delta, data, val) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n var atomics = val._atomics\n , ops = Object.keys(atomics)\n , schema = data.schema\n , path = data.path\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n return operand(self, where, delta, data, val);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", + "ctx": { + "type": "function", + "name": "handleAtomics", + "string": "handleAtomics()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a special query document of the modified properties used in updates.

    ", + "summary": "

    Produces a special query document of the modified properties used in updates.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._delta = function _delta () {\n var dirty = this._dirty();\n if (!dirty.length) return;\n\n var self = this\n , where = {}\n , delta = {}\n , len = dirty.length\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n if (undefined === value) {\n operand(self, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(self, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n // arrays and other custom types (support plugins etc)\n handleAtomics(self, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(self, where, delta, data, value);\n\n } else {\n value = utils.clone(value);\n operand(self, where, delta, data, value);\n }\n }\n\n if (this.__version) {\n this._version(where, delta);\n }\n\n return [where, delta];\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_delta", + "string": "Model.prototype._delta()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Appends versioning to the where and update clauses.

    ", + "summary": "

    Appends versioning to the where and update clauses.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._version = function _version (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n // TODO fail fast option?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.__version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_version", + "string": "Model.prototype._version()" + } + }, + { + "tags": [ + { + "type": "see", + "title": "versionKeys", + "url": "http://mongoosejs.com/docs/guide.html#versionKey", + "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Signal that we desire an increment of this documents version.

    ", + "summary": "

    Signal that we desire an increment of this documents version.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.increment = function increment () {\n this.__version = VERSION_ALL;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "increment", + "string": "Model.prototype.increment()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns a query object which applies shardkeys if they exist.

    ", + "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this._shardval) {\n paths = Object.keys(this._shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this._shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_where", + "string": "Model.prototype._where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", + "summary": "

    Removes this document from the db.

    ", + "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.remove = function remove (fn) {\n if (this._removing) {\n this._removing.addBack(fn);\n return this;\n }\n\n var promise = this._removing = new Promise(fn)\n , where = this._where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self._removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "remove", + "string": "Model.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register hooks override

    ", + "summary": "

    Register hooks override

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype._registerHooks = function registerHooks () {\n Document.prototype._registerHooks.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "_registerHooks", + "string": "Model.prototype._registerHooks()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", + "summary": "

    Returns another Model instance.

    ", + "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};\n\n// Model (class) features", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "model", + "string": "Model.prototype.model()" + } + }, + { + "tags": [], + "description": { + "full": "

    Give the constructor the ability to emit events.

    ", + "summary": "

    Give the constructor the ability to emit events.

    ", + "body": "" + }, + "ignore": true, + "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the model compiles.

    ", + "summary": "

    Called when the model compiles.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.init = function init () {\n if (this.schema.options.autoIndex) {\n this.ensureIndexes();\n }\n\n this.schema.emit('init', this);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "init", + "string": "Model.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[cb]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    ", + "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", + "body": "

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && cb();\n }\n\n var self = this\n , safe = self.schema.options.safe\n , count = indexes.length\n , error\n\n indexes.forEach(function (index) {\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) error = err;\n if (--count) return;\n\n self.emit('index', error);\n cb && cb(error);\n }));\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "ensureIndexes", + "string": "Model.ensureIndexes()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "schema" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema the model uses.

    ", + "summary": "

    Schema the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.schema;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Database instance the model uses.

    ", + "summary": "

    Database instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.db;" + }, + { + "tags": [ + { + "type": "property", + "string": "collection" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.collection;" + }, + { + "tags": [ + { + "type": "property", + "string": "base" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Base Mongoose instance the model uses.

    ", + "summary": "

    Base Mongoose instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.base;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes documents from the collection.

    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    ", + "summary": "

    Removes documents from the collection.

    ", + "body": "

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.remove({ _id: id }).exec();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "remove", + "string": "Model.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents

    \n\n

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    ", + "summary": "

    Finds documents

    ", + "body": "

    Examples:

    \n\n
    // retrieve only certain keys\nMyModel.find({ name: /john/i }, 'name friends', function () { })\n\n// pass options\nMyModel.find({ name: /john/i }, null, { skip: 10 } )\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "find", + "string": "Model.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges the current named scope query into query.

    ", + "summary": "

    Merges the current named scope query into query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "_applyNamedScope", + "string": "Model._applyNamedScope()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "objectid, or a value that can be casted to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds a single document by id.

    \n\n

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    ", + "summary": "

    Finds a single document by id.

    ", + "body": "

    The id is cast to an ObjectId before sending the command.

    \n\n

    Example:

    \n\n
    Adventure.findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findById", + "string": "Model.findById()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    ", + "summary": "

    Finds one document.

    ", + "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOne", + "string": "Model.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", + "summary": "

    Counts number of matching documents in a database collection.

    ", + "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "count", + "string": "Model.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a DISTINCT command

    ", + "summary": "

    Executes a DISTINCT command

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "distinct", + "string": "Model.distinct()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "optional value" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", + "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", + "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "where", + "string": "Model.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "argument", + "description": "is a javascript string or anonymous function" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "memberOf", + "parent": "Model" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Query.$where #query_Query-%24where", + "visibility": "Query.$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    ", + "summary": "

    Creates a Query and specifies a $where condition.

    ", + "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndUpdate", + "string": "Model.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "an ObjectId or string that can be cast to one." + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndUpdate #model_Model-findOneAndUpdate", + "visibility": "Model.findOneAndUpdate" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndUpdate", + "string": "Model.findByIdAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndRemove", + "string": "Model.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "id", + "description": "ObjectId or string that can be cast to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndRemove #model_Model-findOneAndRemove", + "visibility": "Model.findOneAndRemove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndRemove", + "string": "Model.findByIdAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array", + "Object..." + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", + "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", + "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n\n // TODO\n // utilize collection.insertAll for batch processing?\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "create", + "string": "Model.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "update", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Updates documents in the database without returning them.

    ", + "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "update", + "string": "Model.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "o", + "description": "an object specifying map-reduce options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/MapReduce", + "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", + "summary": "

    Executes a mapReduce command.

    ", + "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "mapReduce", + "string": "Model.mapReduce()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "an array of pipeline commands" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "aggregation", + "url": "http://docs.mongodb.org/manual/applications/aggregation/", + "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", + "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes an aggregate command on this models collection.

    \n\n

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    ", + "summary": "

    Executes an aggregate command on this models collection.

    ", + "body": "

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "aggregate", + "string": "Model.aggregate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "collectionName", + "description": "" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "connection", + "description": "" + }, + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "mongoose instance" + } + ], + "description": { + "full": "

    Compiler utility.

    ", + "summary": "

    Compiler utility.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.prototype.db = connection;\n model.prototype._setSchema(schema);\n model.prototype.collection = connection.collection(\n collectionName\n , schema.options.capped\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.model = model.prototype.model;\n model.options = model.prototype.options;\n model.db = model.prototype.db;\n model.schema = model.prototype.schema;\n model.collection = model.prototype.collection;\n model.base = base;\n\n return model;\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "compile", + "string": "Model.compile()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Connection" + ], + "name": "conn", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "" + }, + { + "type": "return", + "types": [ + "Model" + ], + "description": "" + } + ], + "description": { + "full": "

    Subclass this model with conn, schema, and collection settings.

    ", + "summary": "

    Subclass this model with conn, schema, and collection settings.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.__subclass = function subclass (conn, schema, collection) {\n // subclass model using this connection and collection name\n var model = this;\n\n var Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model)) {\n return new Model(doc, fields, skipId);\n }\n model.call(this, doc, fields, skipId);\n }\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = conn;\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n if (!collection) {\n collection = model.prototype.schema.get('collection')\n || utils.toCollectionName(model.modelName);\n }\n\n Model.prototype.collection = conn.collection(collection, s && s.options.capped);\n Model.collection = Model.prototype.collection;\n Model.init();\n return Model;\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "__subclass", + "string": "Model.__subclass()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Model;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Model", + "string": "module.exports" + } + } +] +### lib/namedscope.js +[ + { + "tags": [ + { + "type": "param", + "types": [ + "NamedScope" + ], + "name": "target", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "getters", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Decorate

    ", + "summary": "

    Decorate

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", + "ctx": { + "type": "method", + "constructor": "NamedScope", + "name": "decorate", + "string": "NamedScope.prototype.decorate()" + } + } +] +### lib/promise.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var util = require('./utils');\nvar EventEmitter = util.EventEmitter;", + "ctx": { + "type": "declaration", + "name": "util", + "value": "require('./utils')", + "string": "util" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "back", + "description": "a callback+errback that accepts `fn(err, ...){}` as signature" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`err`: Emits when the promise resolves to an error." + }, + { + "type": "event", + "string": "`complete`: Emits when the promise resolves sucessfully." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Promise constructor.

    ", + "summary": "

    Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Promise (back) {\n this.emitted = {};\n if ('function' == typeof back)\n this.addBack(back);\n};", + "ctx": { + "type": "function", + "name": "Promise", + "string": "Promise()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from EventEmitter.

    ", + "summary": "

    Inherits from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Promise.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Promise", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Promise.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Event" + ], + "name": "event", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds listener to the event.

    \n\n

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", + "summary": "

    Adds listener to the event.

    ", + "body": "

    If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.on = function (event, callback) {\n if (this.emitted[event])\n callback.apply(this, this.emitted[event]);\n else\n EventEmitter.prototype.on.call(this, event, callback);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "on", + "string": "Promise.prototype.on()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Keeps track of emitted events to run them on on.

    ", + "summary": "

    Keeps track of emitted events to run them on on.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Promise.prototype.emit = function (event) {\n // ensures a promise can't be complete() or error() twice\n if (event == 'err' || event == 'complete'){\n if (this.emitted.err || this.emitted.complete) {\n return this;\n }\n this.emitted[event] = util.args(arguments, 1);\n }\n\n return EventEmitter.prototype.emit.apply(this, arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "emit", + "string": "Promise.prototype.emit()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for emitting the complete event.

    ", + "summary": "

    Shortcut for emitting the complete event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.complete = function () {\n var args = util.args(arguments);\n return this.emit.apply(this, ['complete'].concat(args));\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "complete", + "string": "Promise.prototype.complete()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Shortcut for emitting the err event.

    ", + "summary": "

    Shortcut for emitting the err event.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.emit('err', err);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "error", + "string": "Promise.prototype.error()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('complete', fn).

    ", + "summary": "

    Shortcut for .on('complete', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addCallback = function (fn) {\n return this.on('complete', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addCallback", + "string": "Promise.prototype.addCallback()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for .on('err', fn).

    ", + "summary": "

    Shortcut for .on('err', fn).

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addErrback = function (fn) {\n return this.on('err', fn);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addErrback", + "string": "Promise.prototype.addErrback()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + } + ], + "description": { + "full": "

    Adds a single function that's both a callback and errback.

    ", + "summary": "

    Adds a single function that's both a callback and errback.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addBack = function (fn) {\n this.on('err', function(err){\n fn.call(this, err);\n });\n\n this.on('complete', function(){\n var args = util.args(arguments);\n fn.apply(this, [null].concat(args));\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "addBack", + "string": "Promise.prototype.addBack()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "optional error or null" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "value to complete the promise with" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "summary": "

    Sugar for handling cases where you may be resolving to either an error condition or a success condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.complete(val);\n};", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "resolve", + "string": "Promise.prototype.resolve()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Promise;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Promise", + "string": "module.exports" + } + } +] +### lib/query.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "criteria", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", + "summary": "

    Query constructor used for building queries.

    ", + "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n if (criteria) this.find(criteria);\n}", + "ctx": { + "type": "function", + "name": "Query", + "string": "Query()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", + "summary": "

    Sets query options.

    ", + "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe\n\n // normalize population options\n var pop = this.options.populate;\n this.options.populate = {};\n\n if (pop && Array.isArray(pop)) {\n for (var i = 0, l = pop.length; i < l; i++) {\n this.options.populate[pop[i]] = {};\n }\n }\n\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "setOptions", + "string": "Query.prototype.setOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "the model to which the query is bound" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "the operation to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "updateArg", + "description": "used in update methods" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Binds this query to a model.

    ", + "summary": "

    Binds this query to a model.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "bind", + "string": "Query.prototype.bind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "[operation]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", + "summary": "

    Executes the query

    ", + "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exec", + "string": "Query.prototype.exec()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[criteria]", + "description": "mongodb selector" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", + "summary": "

    Finds documents.

    ", + "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "find", + "string": "Query.prototype.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[obj]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", + "summary": "

    Casts this query to the schema of model

    ", + "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path || '$and' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "cast", + "string": "Query.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options.

    ", + "summary": "

    Returns default options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_optionsForExec", + "string": "Query.prototype._optionsForExec()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies schematype selected options to this query.

    ", + "summary": "

    Applies schematype selected options to this query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_applyPaths", + "string": "Query.prototype._applyPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "js", + "description": "javascript string or function" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", + "summary": "

    Specifies a $where condition

    ", + "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", + "summary": "

    Specifies a path for use with chaining.

    ", + "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "where", + "string": "Query.prototype.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", + "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", + "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "equals", + "string": "Query.prototype.equals()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", + "summary": "

    Specifies arguments for an $or condition.

    ", + "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "or", + "string": "Query.prototype.or()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", + "summary": "

    Specifies arguments for a $nor condition.

    ", + "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nor", + "string": "Query.prototype.nor()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for a $and condition.

    \n\n

    Example

    \n\n
    query.and([{ color: 'green' }, { status: 'ok' }])\n
    ", + "summary": "

    Specifies arguments for a $and condition.

    ", + "body": "

    Example

    \n\n
    query.and([{ color: 'green' }, { status: 'ok' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.and = function and (array) {\n var and = this._conditions.$and || (this._conditions.$and = []);\n if (!Array.isArray(array)) array = [array];\n and.push.apply(and, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "and", + "string": "Query.prototype.and()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "gt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", + "summary": "

    Specifies a $gt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "gte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $gte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "ne" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $ne query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "in" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $in query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "nin" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $nin query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "all" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $all query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "size" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $size query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "regex" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $regex query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxDistance" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $maxDistance query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", + "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", + "body": "
    Thing.where('type').nin(array)\n
    " + }, + "ignore": true, + "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $near condition

    ", + "summary": "

    Specifies a $near condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "near", + "string": "Query.prototype.near()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $nearSphere condition.

    ", + "summary": "

    Specifies a $nearSphere condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nearSphere", + "string": "Query.prototype.nearSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $mod condition

    ", + "summary": "

    Specifies a $mod condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "mod", + "string": "Query.prototype.mod()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $exists condition

    ", + "summary": "

    Specifies an $exists condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exists", + "string": "Query.prototype.exists()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object", + "Function" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "Function" + ], + "name": "criteria", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", + "summary": "

    Specifies an $elemMatch condition

    ", + "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "elemMatch", + "string": "Query.prototype.elemMatch()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "within" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Syntax sugar for expressive queries.

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    ", + "summary": "

    Syntax sugar for expressive queries.

    ", + "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () { return this }\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "see", + "local": "Query#within #query_Query-within", + "visibility": "Query#within" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", + "summary": "

    Specifies a $box condition

    ", + "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "box", + "string": "Query.prototype.box()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "options e.g. { $uniqueDocs: true }" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", + "summary": "

    Specifies a $center condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "center", + "string": "Query.prototype.center()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", + "summary": "

    Specifies a $centerSphere condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "centerSphere", + "string": "Query.prototype.centerSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Array", + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", + "summary": "

    Specifies a $polygon condition

    ", + "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "polygon", + "string": "Query.prototype.polygon()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "local": "SchemaType", + "visibility": "SchemaType" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    ", + "summary": "

    Specifies which document fields to include or exclude

    ", + "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "select", + "string": "Query.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "number of elements to slice" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", + "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", + "summary": "

    Specifies a $slice condition

    ", + "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slice", + "string": "Query.prototype.slice()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", + "summary": "

    Sets the sort order

    ", + "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "sort", + "string": "Query.prototype.sort()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", + "ctx": { + "type": "function", + "name": "push", + "string": "push()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "limit" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", + "summary": "

    Specifies the limit option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "skip" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", + "summary": "

    Specifies the skip option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxscan" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", + "summary": "

    Specifies the maxscan option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "batchSize" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", + "summary": "

    Specifies the batchSize option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "comment" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", + "summary": "

    Specifies the comment option.

    ", + "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", + "summary": "

    limit, skip, maxscan, batchSize, comment

    ", + "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " + }, + "ignore": true, + "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", + "summary": "

    Specifies this query as a snapshot query.

    ", + "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "snapshot", + "string": "Query.prototype.snapshot()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "a hint object" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", + "summary": "

    Sets query hints.

    ", + "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "hint", + "string": "Query.prototype.hint()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", + "summary": "

    Sets the slaveOk option.

    ", + "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slaveOk", + "string": "Query.prototype.slaveOk()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "one of the listed preference options or their aliases" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "[tags]", + "description": "optional tags for this query" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", + "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the readPreference option for the query.

    \n\n

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    ", + "summary": "

    Sets the readPreference option for the query.

    ", + "body": "

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "read", + "string": "Query.prototype.read()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", + "summary": "

    Sets the lean option.

    ", + "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "lean", + "string": "Query.prototype.lean()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", + "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", + "summary": "

    Sets tailable option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "tailable", + "string": "Query.prototype.tailable()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes the query as a find() operation.

    ", + "summary": "

    Executes the query as a find() operation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (true === options.lean)\n return promise.complete(docs);\n\n var arr = []\n , count = docs.length;\n\n if (!count) return promise.complete([]);\n\n for (var i = 0, l = docs.length; i < l; i++) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], self, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "execFind", + "string": "Query.prototype.execFind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", + "summary": "

    Executes the query as a findOne() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === options.lean) return promise.complete(doc);\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOne", + "string": "Query.prototype.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", + "summary": "

    Exectues the query as a count() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "count", + "string": "Query.prototype.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a distict() operation.

    ", + "summary": "

    Executes this query as a distict() operation.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "distinct", + "string": "Query.prototype.distinct()" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "body": "" + }, + "ignore": true, + "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", + "ctx": { + "type": "declaration", + "name": "castOps", + "value": "{", + "string": "castOps" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "body": "" + }, + "ignore": true, + "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", + "ctx": { + "type": "declaration", + "name": "numberOps", + "value": "{", + "string": "numberOps" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "the update conditions" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", + "summary": "

    Executes this query as an update() operation.

    ", + "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n options.safe = { w: 0 };\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "update", + "string": "Query.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "obj after casting its values" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts obj for an update command.

    ", + "summary": "

    Casts obj for an update command.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdate", + "string": "Query.prototype._castUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "- part of a query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "- path prefix (internal only)" + }, + { + "type": "return", + "types": [ + "Bool" + ], + "description": "true if this path has keys to update" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var strict = this.model.schema.options.strict\n , prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_walkUpdatePath", + "string": "Query.prototype._walkUpdatePath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[$conditional]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val according to schema and atomic op.

    ", + "summary": "

    Casts val according to schema and atomic op.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdateVal", + "string": "Query.prototype._castUpdateVal()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._getSchema = function _getSchema (path) {\n var schema = this.model.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_getSchema", + "string": "Query.prototype._getSchema()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "https://github.com/LearnBoost/mongoose/issues/1091", + "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" + }, + { + "type": "see", + "title": "", + "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", + "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts selected field arguments for field selection with mongo 2.2

    \n\n
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    ", + "summary": "

    Casts selected field arguments for field selection with mongo 2.2

    ", + "body": "
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castFields", + "string": "Query.prototype._castFields()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", + "summary": "

    Executes this query as a remove() operation.

    ", + "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n options.safe = { w: 0 };\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "remove", + "string": "Query.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[query]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[doc]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndUpdate", + "string": "Query.prototype.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndRemove", + "string": "Query.prototype.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "- either \"remove\" or \"update\"" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    _findAndModify

    ", + "summary": "

    _findAndModify

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n this._applyPaths();\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, self, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_findAndModify", + "string": "Query.prototype._findAndModify()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Model" + ], + "name": "[model]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "see", + "local": "population ./populate.html", + "visibility": "population" + }, + { + "type": "see", + "local": "Query#select #query_Query-select", + "visibility": "Query#select" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    ", + "summary": "

    Specifies paths which should be populated with other documents.

    ", + "body": "

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.populate = function (path, fields, model, conditions, options) {\n if ('string' !== typeof model) {\n options = conditions;\n conditions = model;\n model = undefined;\n }\n // The order of fields/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (fields could be\n // an array, string, or object literal).\n this.options.populate[path] =\n new PopulateOptions(fields, conditions, options, model);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "populate", + "string": "Query.prototype.populate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Populate options constructor

    ", + "summary": "

    Populate options constructor

    ", + "body": "" + }, + "ignore": true, + "code": "function PopulateOptions (fields, conditions, options, model) {\n this.conditions = conditions;\n this.fields = fields;\n this.options = options;\n this.model = model;\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;", + "ctx": { + "type": "function", + "name": "PopulateOptions", + "string": "PopulateOptions()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "QueryStream" + ], + "description": "" + }, + { + "type": "see", + "local": "QueryStream", + "visibility": "QueryStream" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a stream interface

    \n\n

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    ", + "summary": "

    Returns a stream interface

    ", + "body": "

    Example

    \n\n
    // follows the nodejs stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.stream = function stream () {\n return new QueryStream(this);\n}\n\n// helpers", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "stream", + "string": "Query.prototype.stream()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castDoc

    ", + "summary": "

    castDoc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castDoc", + "string": "castDoc()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castQuery

    ", + "summary": "

    castQuery

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castQuery", + "string": "castQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Exports.

    ", + "summary": "

    Exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Query", + "string": "module.exports" + } + } +] +### lib/querystream.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')", + "ctx": { + "type": "declaration", + "name": "Stream", + "value": "require('stream').Stream", + "string": "Stream" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS Stream http://nodejs.org/api/stream.html" + }, + { + "type": "event", + "string": "`data`: emits a single Mongoose document" + }, + { + "type": "event", + "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." + }, + { + "type": "event", + "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Provides a ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    ", + "summary": "

    Provides a ReadStream interface for Queries.

    ", + "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node streams such as http responses and write streams so everything \"just works\" out of the box.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function QueryStream (query) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n this._running = false;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", + "ctx": { + "type": "function", + "name": "QueryStream", + "string": "QueryStream()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Stream

    ", + "summary": "

    Inherit from Stream

    ", + "body": "" + }, + "ignore": true, + "code": "QueryStream.prototype.__proto__ = Stream.prototype;", + "ctx": { + "type": "property", + "constructor": "QueryStream", + "name": "__proto__", + "value": "Stream.prototype", + "string": "QueryStream.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readable" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is readable.

    ", + "summary": "

    Flag stating whether or not this stream is readable.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.readable;" + }, + { + "tags": [ + { + "type": "property", + "string": "paused" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is paused.

    ", + "summary": "

    Flag stating whether or not this stream is paused.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the query.

    ", + "summary": "

    Initializes the query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_init", + "string": "QueryStream.prototype._init()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#__next #querystream_QueryStream-__next", + "visibility": "QueryStream#__next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Trampoline for pulling the next doc from cursor.

    ", + "summary": "

    Trampoline for pulling the next doc from cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) {\n return this._running = false;\n }\n\n this._running = true;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n while (this.__next()) {}\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_next", + "string": "QueryStream.prototype._next()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#_next #querystream_QueryStream-_next", + "visibility": "QueryStream#_next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pulls the next doc from the cursor.

    ", + "summary": "

    Pulls the next doc from the cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed)\n return this._running = false;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "__next", + "string": "QueryStream.prototype.__next()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error", + "null" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return this._running = false;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && true === this.query.options.lean) {\n this.emit('data', doc);\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, this.query, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', instance);\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_onNextObject", + "string": "QueryStream.prototype._onNextObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pauses this stream.

    ", + "summary": "

    Pauses this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "pause", + "string": "QueryStream.prototype.pause()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Resumes this stream.

    ", + "summary": "

    Resumes this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n\n if (!this._cursor) {\n // cannot start if not initialized\n return;\n }\n\n // are we within the trampoline?\n if (T_INIT === this._inline) {\n return;\n }\n\n if (!this._running) {\n // outside QueryStream control, need manual restart\n return this._next();\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "resume", + "string": "QueryStream.prototype.resume()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "[err]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this._running = false;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "destroy", + "string": "QueryStream.prototype.destroy()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "pipe" + }, + { + "type": "memberOf", + "parent": "QueryStream" + }, + { + "type": "see", + "title": "NodeJS", + "url": "http://nodejs.org/api/stream.html", + "visibility": "http://nodejs.org/api/stream.html" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", + "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", + "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = QueryStream", + "string": "module.exports" + } + } +] +### lib/schema/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Array SchemaType constructor

    ", + "summary": "

    Array SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n var caster = cast.name in Types ? Types[cast.name] : cast;\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "SchemaArray", + "string": "SchemaArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaArray", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "checkRequired", + "string": "SchemaArray.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides the getters application for the population special-case

    ", + "summary": "

    Overrides the getters application for the population special-case

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "applyGetters", + "string": "SchemaArray.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "cast", + "string": "SchemaArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(proto, v);\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(proto, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "castForQuery", + "string": "SchemaArray.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': SchemaArray.prototype.castForQuery\n , '$gte': SchemaArray.prototype.castForQuery\n , '$lt': SchemaArray.prototype.castForQuery\n , '$lte': SchemaArray.prototype.castForQuery\n , '$within': function(val) {\n var query = new Query(val);\n query.cast(this.casterConstructor)\n return query._conditions;\n }\n , '$maxDistance': castToNumber\n};", + "ctx": { + "type": "function", + "name": "castToNumber", + "string": "castToNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaArray", + "string": "module.exports" + } + } +] +### lib/schema/boolean.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Boolean SchemaType constructor.

    ", + "summary": "

    Boolean SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaBoolean", + "string": "SchemaBoolean()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBoolean", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBoolean.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "checkRequired", + "string": "SchemaBoolean.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to boolean

    ", + "summary": "

    Casts to boolean

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.cast = function (value) {\n if (value === null) return value;\n if (value === '0') return false;\n return !!value;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "cast", + "string": "SchemaBoolean.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", + "ctx": { + "type": "function", + "name": "handleArray", + "string": "handleArray()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "castForQuery", + "string": "SchemaBoolean.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBoolean;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBoolean", + "string": "module.exports" + } + } +] +### lib/schema/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Buffer SchemaType constructor

    ", + "summary": "

    Buffer SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", + "ctx": { + "type": "function", + "name": "SchemaBuffer", + "string": "SchemaBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBuffer", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBuffer.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "checkRequired", + "string": "SchemaBuffer.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if ('string' === typeof value || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "cast", + "string": "SchemaBuffer.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "castForQuery", + "string": "SchemaBuffer.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBuffer;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBuffer", + "string": "module.exports" + } + } +] +### lib/schema/date.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date SchemaType constructor.

    ", + "summary": "

    Date SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaDate", + "string": "SchemaDate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaDate", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaDate.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for date

    ", + "summary": "

    Required validator for date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "checkRequired", + "string": "SchemaDate.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to date

    ", + "summary": "

    Casts to date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "cast", + "string": "SchemaDate.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date Query casting.

    ", + "summary": "

    Date Query casting.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "castForQuery", + "string": "SchemaDate.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaDate;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaDate", + "string": "module.exports" + } + } +] +### lib/schema/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , CastError = SchemaType.CastError\n , Document = require('../document');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaArray" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    SubdocsArray SchemaType constructor

    ", + "summary": "

    SubdocsArray SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype._setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "DocumentArray", + "string": "DocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from ArrayType.

    ", + "summary": "

    Inherits from ArrayType.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentArray", + "name": "__proto__", + "value": "ArrayType.prototype", + "string": "DocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs local validations first, then validations on each embedded doc

    ", + "summary": "

    Performs local validations first, then validations on each embedded doc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n\n SchemaType.prototype.doValidate.call(this, array, function (err) {\n if (err) return fn(err);\n\n var count = array && array.length\n , error;\n\n if (!count) return fn();\n\n // handle sparse arrays, do not use array.forEach which does not\n // iterate over sparse elements yet reports array.length including\n // them :(\n\n for (var i = 0, len = count; i < len; ++i) {\n // sidestep sparse entries\n var doc = array[i];\n if (!doc) {\n --count || fn();\n continue;\n }\n\n ;(function (i) {\n doc.validate(function (err) {\n if (err && !error) {\n // rewrite the key\n err.key = self.key + '.' + i + '.' + err.key;\n return fn(error = err);\n }\n --count || fn();\n });\n })(i);\n }\n }, scope);\n};", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "doValidate", + "string": "DocumentArray.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "document", + "description": "that triggers the casting" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument) && value[i]) {\n if (init) {\n selected || (selected = scopePaths(this, doc._selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "cast", + "string": "DocumentArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "DocumentArray" + ], + "name": "array", + "description": "- the array to scope `fields` paths" + }, + { + "type": "param", + "types": [ + "Object", + "undefined" + ], + "name": "fields", + "description": "- the root fields selected in the query" + }, + { + "type": "param", + "types": [ + "Boolean", + "undefined" + ], + "name": "init", + "description": "- if we are being created part of a query result" + } + ], + "description": { + "full": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "summary": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , hasKeys\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n hasKeys || (hasKeys = true);\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return hasKeys && selected || undefined;\n}", + "ctx": { + "type": "function", + "name": "scopePaths", + "string": "scopePaths()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = DocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "DocumentArray", + "string": "module.exports" + } + } +] +### lib/schema/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "String", + "value": "require('./string')", + "string": "exports.String" + } + } +] +### lib/schema/mixed.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Mixed SchemaType constructor.

    ", + "summary": "

    Mixed SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Mixed (path, options) {\n // make sure empty array defaults are handled\n if (options &&\n options.default &&\n Array.isArray(options.default) &&\n 0 === options.default.length) {\n options.default = Array;\n }\n\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "Mixed", + "string": "Mixed()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "Mixed", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "Mixed.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "checkRequired", + "string": "Mixed.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", + "summary": "

    Casts val for Mixed.

    ", + "body": "

    this is a no-op

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "cast", + "string": "Mixed.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$cond", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "castForQuery", + "string": "Mixed.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Mixed;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Mixed", + "string": "module.exports" + } + } +] +### lib/schema/number.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Number SchemaType constructor.

    ", + "summary": "

    Number SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", + "ctx": { + "type": "function", + "name": "SchemaNumber", + "string": "SchemaNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaNumber", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaNumber.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for number

    ", + "summary": "

    Required validator for number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "checkRequired", + "string": "SchemaNumber.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "value", + "description": "minimum number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "min", + "string": "SchemaNumber.prototype.min()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "maximum", + "description": "number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "max", + "string": "SchemaNumber.prototype.max()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "value to cast" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to number

    ", + "summary": "

    Casts to number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (!isNaN(value)){\n if (null === value) return value;\n if ('' === value) return null;\n if ('string' == typeof value) value = Number(value);\n if (value instanceof Number) return value\n if ('number' == typeof value) return value;\n if (value.toString && !Array.isArray(value) &&\n value.toString() == Number(value)) {\n return new Number(value)\n }\n }\n\n throw new CastError('number', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "cast", + "string": "SchemaNumber.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "castForQuery", + "string": "SchemaNumber.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaNumber;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaNumber", + "string": "module.exports" + } + } +] +### lib/schema/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    ObjectId SchemaType constructor.

    ", + "summary": "

    ObjectId SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", + "ctx": { + "type": "function", + "name": "ObjectId", + "string": "ObjectId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "ObjectId", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "ObjectId.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "checkRequired", + "string": "ObjectId.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to ObjectId

    ", + "summary": "

    Casts to ObjectId

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString)\n return oid.fromString(value.toString());\n\n throw new CastError('object id', value);\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "cast", + "string": "ObjectId.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "castForQuery", + "string": "ObjectId.prototype.castForQuery()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "turnOn", + "description": "auto generated ObjectId defaults" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "auto", + "string": "ObjectId.prototype.auto()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.__id = null;\n return v;\n}", + "ctx": { + "type": "function", + "name": "defaultId", + "string": "defaultId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ObjectId;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ObjectId", + "string": "module.exports" + } + } +] +### lib/schema/string.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError;", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    String SchemaType constructor.

    ", + "summary": "

    String SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", + "ctx": { + "type": "function", + "name": "SchemaString", + "string": "SchemaString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaString", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaString.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[args...]", + "description": "enumeration values" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", + "summary": "

    Adds enumeration values and a coinciding validator.

    ", + "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "enum", + "string": "SchemaString.prototype.enum()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", + "summary": "

    Adds a lowercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toLowerCase();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "lowercase", + "string": "SchemaString.prototype.lowercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", + "summary": "

    Adds an uppercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toUpperCase();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "uppercase", + "string": "SchemaString.prototype.uppercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", + "summary": "

    Adds a trim setter.

    ", + "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.trim();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "trim", + "string": "SchemaString.prototype.trim()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp" + ], + "name": "regExp", + "description": "regular expression to test against" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", + "summary": "

    Sets a regexp validator.

    ", + "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "match", + "string": "SchemaString.prototype.match()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "null", + "undefined" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.checkRequired = function checkRequired (value) {\n if (SchemaType._isRef(this, value, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "checkRequired", + "string": "SchemaString.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to String

    ", + "summary": "

    Casts to String

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.cast = function (value, scope, init) {\n if (SchemaType._isRef(this, value, init)) return value;\n if (value === null) return value;\n if ('undefined' !== typeof value && value.toString) return value.toString();\n throw new CastError('string', value);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "cast", + "string": "SchemaString.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "castForQuery", + "string": "SchemaString.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaString;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaString", + "string": "module.exports" + } + } +] +### lib/schema.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "definition", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted after the schema is compiled into a `Model`." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • autoIndex: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • collection: string - no default
    • \n
    • id: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • read: string
    • \n
    • safe: bool - defaults to true.
    • \n
    • shardKey: bool - defaults to null
    • \n
    • strict: bool - defaults to true
    • \n
    • toJSON - object - no default
    • \n
    • toObject - object - no default
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", + "summary": "

    Schema constructor.

    ", + "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n
      \n
    • autoIndex: bool - defaults to true
    • \n
    • capped: bool - defaults to false
    • \n
    • collection: string - no default
    • \n
    • id: bool - defaults to true
    • \n
    • _id: bool - defaults to true
    • \n
    • read: string
    • \n
    • safe: bool - defaults to true.
    • \n
    • shardKey: bool - defaults to null
    • \n
    • strict: bool - defaults to true
    • \n
    • toJSON - object - no default
    • \n
    • toObject - object - no default
    • \n
    • versionKey: bool - defaults to \"__v\"
    • \n
    • minimize: bool - controls document#toObject behavior when called manually - defaults to true
    • \n
    \n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n\n // versioning not directly added to schema b/c we only want\n // it in the top level document, not embedded ones.\n};", + "ctx": { + "type": "function", + "name": "Schema", + "string": "Schema()" + } + }, + { + "tags": [], + "description": { + "full": "

    Returns this documents _id cast to a string.

    ", + "summary": "

    Returns this documents _id cast to a string.

    ", + "body": "" + }, + "ignore": true, + "code": "function idGetter () {\n if (this.__id) {\n return this.__id;\n }\n\n return this.__id = null == this._id\n ? null\n : String(this._id);\n}", + "ctx": { + "type": "function", + "name": "idGetter", + "string": "idGetter()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Schema", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Schema.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "paths" + } + ], + "description": { + "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", + "summary": "

    Schema as flat paths

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.paths;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "tree" + } + ], + "description": { + "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", + "summary": "

    Schema as a tree

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.tree;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options for this schema, merged with options.

    ", + "summary": "

    Returns default options for this schema, merged with options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.defaultOptions = function (options) {\n if (options && false === options.safe) {\n options.safe = { w: 0 };\n }\n\n options = utils.options({\n strict: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "defaultOptions", + "string": "Schema.prototype.defaultOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "prefix", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", + "summary": "

    Adds key path / schema type pairs to this schema.

    ", + "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n } else {\n this.path(prefix + i, obj[i]); // mixed type\n }\n } else {\n this.path(prefix + i, obj[i]);\n }\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "add", + "string": "Schema.prototype.add()" + } + }, + { + "tags": [], + "description": { + "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    ", + "summary": "

    Reserved document keys.

    ", + "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, db, init, isNew, errors, schema, options, modelName, collection\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    " + }, + "ignore": false, + "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection = 1;", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "reserved", + "value": "Object.create(null)", + "string": "Schema.reserved" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "constructor", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", + "summary": "

    Gets/sets schema paths.

    ", + "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(sub, i) {\n if (!branch[sub]) branch[sub] = {};\n if ('object' != typeof branch[sub]) {\n var msg = 'Cannot set nested path `' + path + '`. '\n + 'Parent path `'\n + subpaths.slice(0, i).concat([sub]).join('.')\n + '` already set to type ' + branch[sub].name\n + '.';\n throw new Error(msg);\n }\n branch = branch[sub];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "path", + "string": "Schema.prototype.path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "constructor" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts type arguments into Mongoose Types.

    ", + "summary": "

    Converts type arguments into Mongoose Types.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", + "ctx": { + "type": "method", + "receiver": "Schema", + "name": "interpretAsType", + "string": "Schema.interpretAsType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback function" + }, + { + "type": "return", + "types": [ + "Schema" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", + "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", + "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "eachPath", + "string": "Schema.prototype.eachPath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns an Array of path strings that are required by this schema.

    ", + "summary": "

    Returns an Array of path strings that are required by this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "requiredPaths", + "string": "Schema.prototype.requiredPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", + "summary": "

    Returns the pathType of path for this schema.

    ", + "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pathType", + "string": "Schema.prototype.pathType()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", + "ctx": { + "type": "function", + "name": "getPositionalPath", + "string": "getPositionalPath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the document method to call later" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds a method call to the queue.

    ", + "summary": "

    Adds a method call to the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "queue", + "string": "Schema.prototype.queue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", + "summary": "

    Defines a pre hook for the document.

    ", + "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pre", + "string": "Schema.prototype.pre()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "name of the method to hook" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function (doc) {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", + "summary": "

    Defines a post hook for the document.

    ", + "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function (doc) {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "post", + "string": "Schema.prototype.post()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "plugin", + "description": "callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "" + }, + { + "type": "see", + "local": "plugins", + "visibility": "plugins" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Registers a plugin for this schema.

    ", + "summary": "

    Registers a plugin for this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "plugin", + "string": "Schema.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "method", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", + "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "method", + "string": "Schema.prototype.method()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", + "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "static", + "string": "Schema.prototype.static()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", + "summary": "

    Defines an index (most likely compound) for this schema.

    ", + "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "index", + "string": "Schema.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "option name" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[value]", + "description": "if not passed, the current option value is returned" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets/gets a schema option.

    ", + "summary": "

    Sets/gets a schema option.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.set = function (key, value, _tags) {\n if (1 === arguments.length) {\n return this.options[key];\n }\n\n switch (key) {\n case 'read':\n this.options[key] = utils.readPref(value, _tags)\n break;\n case 'safe':\n this.options[key] = false === value\n ? { w: 0 }\n : value\n break;\n default:\n this.options[key] = value;\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "set", + "string": "Schema.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "option name" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets a schema option.

    ", + "summary": "

    Gets a schema option.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.get = function (key) {\n return this.options[key];\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "get", + "string": "Schema.prototype.get()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Compiles indexes from fields and schema-level indexes

    ", + "summary": "

    Compiles indexes from fields and schema-level indexes

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.indexes = function () {\n var indexes = []\n , seenSchemas = [];\n\n collectIndexes(this);\n\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n var index;\n var paths = schema.paths;\n prefix = prefix || '';\n\n for (var i in paths) {\n if (paths[i]) {\n if (paths[i] instanceof Types.DocumentArray) {\n collectIndexes(paths[i].schema, i + '.');\n } else {\n index = paths[i]._index;\n\n if (index !== false && index !== null){\n var field = {};\n field[prefix + i] = '2d' === index ? index : 1;\n var options = 'Object' === index.constructor.name ? index : {};\n if (!('background' in options)) options.background = true;\n indexes.push([field, options]);\n }\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "indexes", + "string": "Schema.prototype.indexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", + "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", + "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " + }, + "ignore": true, + "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", + "ctx": { + "type": "function", + "name": "fixSubIndexPaths", + "string": "fixSubIndexPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Creates a virtual type with the given name.

    ", + "summary": "

    Creates a virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtual", + "string": "Schema.prototype.virtual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the virtual type with the given name.

    ", + "summary": "

    Returns the virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtualpath", + "string": "Schema.prototype.virtualpath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "namedScope", + "string": "Schema.prototype.namedScope()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Schema", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Schema Types.

    \n\n

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", + "summary": "

    The various Mongoose Schema Types.

    ", + "body": "

    Example:

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n
      \n
    • String
    • \n
    • Number
    • \n
    • Boolean | Bool
    • \n
    • Array
    • \n
    • Buffer
    • \n
    • Date
    • \n
    • ObjectId | Oid
    • \n
    • Mixed
    • \n
    \n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.Types = require('./schema/index');", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "Types", + "value": "require('./schema/index')", + "string": "Schema.Types" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" + } +] +### lib/schemadefault.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "property", + "string": "system.profile" + }, + { + "type": "receiver", + "string": "exports" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Default model for querying the system.profiles collection.

    ", + "summary": "

    Default model for querying the system.profiles collection.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" + } +] +### lib/schematype.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');\nvar CastError = require('./error').CastError;\nvar ValidatorError = require('./error').ValidatorError;", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[instance]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    SchemaType constructor

    ", + "summary": "

    SchemaType constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", + "ctx": { + "type": "function", + "name": "SchemaType", + "string": "SchemaType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function", + "any" + ], + "name": "val", + "description": "the default value" + }, + { + "type": "return", + "types": [ + "defaultValue" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", + "summary": "

    Sets a default value for this SchemaType.

    ", + "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "default", + "string": "SchemaType.prototype.default()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "Boolean" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.date').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", + "summary": "

    Declares the index options for this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.date').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "index", + "string": "SchemaType.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares an unique index.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    \n\n

    NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.

    ", + "summary": "

    Declares an unique index.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    \n\n

    NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.unique = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.unique = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "unique", + "string": "SchemaType.prototype.unique()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a sparse index.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", + "summary": "

    Declares a sparse index.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.sparse = function (bool) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.sparse = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "sparse", + "string": "SchemaType.prototype.sparse()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "when", + "description": "" + }, + { + "type": "added", + "string": "3.0.0" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: 60*60*24 }});\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: '24h' }});\n\n// expire in 1.5 hours\nnew Schema({ createdAt: { type: Date, expires: '1.5h' }});\n\n// expire in 7 days\nvar schema = new Schema({ createdAt: Date });\nschema.path('createdAt').expires('7d');\n
    ", + "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", + "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: 60*60*24 }});\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: '24h' }});\n\n// expire in 1.5 hours\nnew Schema({ createdAt: { type: Date, expires: '1.5h' }});\n\n// expire in 7 days\nvar schema = new Schema({ createdAt: Date });\nschema.path('createdAt').expires('7d');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "expires", + "string": "SchemaType.prototype.expires()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    ", + "summary": "

    Adds a setter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "set", + "string": "SchemaType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    ", + "summary": "

    Adds a getter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new Error('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "get", + "string": "SchemaType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp", + "Function", + "Object" + ], + "name": "obj", + "description": "validator" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[error]", + "description": "optional error message" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", + "summary": "

    Adds validator(s) for this document path.

    ", + "body": "

    Validators must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator () { ... }\n\nvar single = [validator, 'failed']\nnew Schema({ name: { type: String, validate: single }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either true or false when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "validate", + "string": "SchemaType.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "required", + "description": "enable/disable the validator" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", + "summary": "

    Adds a required validator to this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "required", + "string": "SchemaType.prototype.required()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope which callback are executed" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets the default value

    ", + "summary": "

    Gets the default value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "getDefault", + "string": "SchemaType.prototype.getDefault()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies setters

    ", + "summary": "

    Applies setters

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, init)) return value;\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return init\n ? v // if we just initialized we dont recast\n : this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applySetters", + "string": "SchemaType.prototype.applySetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies getters to a value

    ", + "summary": "

    Applies getters to a value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applyGetters", + "string": "SchemaType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", + "summary": "

    Sets default select() behavior for this path.

    ", + "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "select", + "string": "SchemaType.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (val, msg) {\n if (err) return;\n if (val === undefined || val) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (val) {\n validate(val, message);\n });\n } else {\n validate(validator.call(scope, value), message);\n }\n }\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "doValidate", + "string": "SchemaType.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if value is a valid Reference.

    ", + "summary": "

    Determines if value is a valid Reference.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType._isRef = function (self, value, init) {\n if (init && self.options && self.options.ref) {\n if (null == value) return true;\n if (value._id && value._id.constructor.name === self.instance) return true;\n }\n\n return false;\n}", + "ctx": { + "type": "method", + "receiver": "SchemaType", + "name": "_isRef", + "string": "SchemaType._isRef()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = SchemaType", + "string": "module.exports" + } + } +] +### lib/statemachine.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", + "ctx": { + "type": "declaration", + "name": "StateMachine", + "value": "module.exports = exports = function StateMachine () {", + "string": "StateMachine" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "subclass constructor" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", + "ctx": { + "type": "method", + "receiver": "StateMachine", + "name": "ctor", + "string": "StateMachine.ctor()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", + "summary": "

    This function is wrapped by the state change functions

    ", + "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_changeState", + "string": "StateMachine.prototype._changeState()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "clear", + "string": "StateMachine.prototype.clear()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "that we want to check for." + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "some", + "string": "StateMachine.prototype.some()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "iterMethod", + "description": "is either 'forEach' or 'map'" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_iter", + "string": "StateMachine.prototype._iter()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "forEach", + "string": "StateMachine.prototype.forEach()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "map", + "string": "StateMachine.prototype.map()" + } + } +] +### lib/types/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');", + "ctx": { + "type": "declaration", + "name": "EmbeddedDocument", + "value": "require('./embedded')", + "string": "EmbeddedDocument" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Array" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", + "summary": "

    Mongoose Array constructor.

    ", + "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseArray", + "string": "MongooseArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Array

    ", + "summary": "

    Inherit from Array

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseArray.prototype = new Array;", + "ctx": { + "type": "property", + "receiver": "MongooseArray", + "name": "prototype", + "value": "new Array", + "string": "MongooseArray.prototype" + } + }, + { + "tags": [ + { + "type": "property", + "string": "_atomics" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores a queue of atomic operations to perform

    ", + "summary": "

    Stores a queue of atomic operations to perform

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._atomics;" + }, + { + "tags": [ + { + "type": "property", + "string": "_parent" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._parent;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "return", + "types": [ + "value" + ], + "description": "the casted value" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts a member based on this arrays schema.

    ", + "summary": "

    Casts a member based on this arrays schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._cast = function (value) {\n var cast = this._schema.caster.cast\n , doc = this._parent;\n\n return cast.call(null, value, doc);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_cast", + "string": "MongooseArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "EmbeddedDocument" + ], + "name": "embeddedDoc", + "description": "the embedded doc that invoked this method on the Array" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "embeddedPath", + "description": "the path which changed in the embeddedDoc" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", + "summary": "

    Marks this array as modified.

    ", + "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._markModified = function (elem, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n dirtyPath = this._path;\n\n if (arguments.length) {\n if (null != embeddedPath) {\n // an embedded doc bubbled up the change\n dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;\n } else {\n // directly set an index\n dirtyPath = dirtyPath + '.' + elem;\n }\n\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_markModified", + "string": "MongooseArray.prototype._markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "op", + "description": "operation" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register an atomic operation with the parent.

    ", + "summary": "

    Register an atomic operation with the parent.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (this._atomics.$set ||\n Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_registerAtomic", + "string": "MongooseArray.prototype._registerAtomic()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "hasAtomics", + "string": "MongooseArray.prototype.hasAtomics()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#push with proper change tracking.

    ", + "summary": "

    Wraps Array#push with proper change tracking.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "push", + "string": "MongooseArray.prototype.push()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Pushes items to the array non-atomically.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "nonAtomicPush", + "string": "MongooseArray.prototype.nonAtomicPush()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "$pop" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", + "summary": "

    Pops the array atomically at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n this._markModified();\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" + }, + { + "tags": [ + { + "type": "see", + "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", + "visibility": "MongooseArray#$pop" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#pop with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pop", + "string": "MongooseArray.prototype.pop()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "method", + "string": "$shift" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", + "summary": "

    Atomically shifts the array at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n this._markModified();\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#shift with proper change tracking.

    ", + "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "shift", + "string": "MongooseArray.prototype.shift()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "values to remove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes items from an array atomically

    \n\n

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    ", + "summary": "

    Removes items from an array atomically

    ", + "body": "

    Examples:

    \n\n
    doc.array.remove(ObjectId)\ndoc.array.remove('tag 1', 'tag 2')\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.remove = function () {\n var args = [].map.call(arguments, this._cast, this);\n if (args.length == 1)\n this.pull(args[0]);\n else\n this.pull.apply(this, args);\n return args;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "remove", + "string": "MongooseArray.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pulls items from the array atomically.

    ", + "summary": "

    Pulls items from the array atomically.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n this._markModified();\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pull", + "string": "MongooseArray.prototype.pull()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#splice with proper change tracking and casting.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#splice with proper change tracking and casting.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.splice = function splice () {\n var ret, vals, i;\n\n if (arguments.length) {\n vals = [];\n for (i = 0; i < arguments.length; ++i) {\n vals[i] = i < 2\n ? arguments[i]\n : this._cast(arguments[i]);\n }\n ret = [].splice.apply(this, vals);\n this._registerAtomic('$set', this);\n this._markModified();\n }\n\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "splice", + "string": "MongooseArray.prototype.splice()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#unshift with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return this.length;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "unshift", + "string": "MongooseArray.prototype.unshift()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#sort with proper change tracking.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "sort", + "string": "MongooseArray.prototype.sort()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "the values that were added" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", + "summary": "

    Adds values to the array if not already present.

    ", + "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n this._markModified();\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "addToSet", + "string": "MongooseArray.prototype.addToSet()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the casted val at index i and marks the array modified.

    \n\n

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    ", + "summary": "

    Sets the casted val at index i and marks the array modified.

    ", + "body": "

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.set = function set (i, val) {\n this[i] = this._cast(val);\n this._markModified(i);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "set", + "string": "MongooseArray.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array.

    ", + "summary": "

    Returns a native js Array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate && this[0] instanceof Document) {\n return this.map(function (doc) {\n return doc._id;\n });\n }\n\n // return this.slice()?\n return this.map(function (doc) {\n return doc;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "toObject", + "string": "MongooseArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "inspect", + "string": "MongooseArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the item to look for" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Return the index of obj or -1 if not found.

    ", + "summary": "

    Return the index of obj or -1 if not found.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "indexOf", + "string": "MongooseArray.prototype.indexOf()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = MongooseArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = MongooseArray", + "string": "module.exports" + } + } +] +### lib/types/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require(driver + '/binary');", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require(driver + '/binary')", + "string": "Binary" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "encode", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "offset", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Buffer" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", + "summary": "

    Mongoose Buffer constructor.

    ", + "body": "

    Values always have to be passed to the constructor to initialize.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", + "ctx": { + "type": "function", + "name": "MongooseBuffer", + "string": "MongooseBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Buffer.

    ", + "summary": "

    Inherit from Buffer.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.prototype = new Buffer(0);", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "prototype", + "value": "new Buffer(0)", + "string": "MongooseBuffer.prototype" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "_parent" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._parent;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this buffer as modified.

    ", + "summary": "

    Marks this buffer as modified.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "_markModified", + "string": "MongooseBuffer.prototype._markModified()" + } + }, + { + "tags": [], + "description": { + "full": "

    Writes the buffer.

    ", + "summary": "

    Writes the buffer.

    ", + "body": "" + }, + "ignore": false, + "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "write", + "string": "MongooseBuffer.prototype.write()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "MongooseBuffer" + ], + "description": "" + }, + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "target", + "description": "" + } + ], + "description": { + "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", + "summary": "

    Copies the buffer.

    ", + "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "copy", + "string": "MongooseBuffer.prototype.copy()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "body": "" + }, + "ignore": true, + "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://bsonspec.org/#/specification", + "visibility": "http://bsonspec.org/#/specification" + }, + { + "type": "param", + "types": [ + "Hex" + ], + "name": "[subtype]", + "description": "" + }, + { + "type": "return", + "types": [ + "Binary" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", + "summary": "

    Converts this buffer to its Binary type representation.

    ", + "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.toObject = function (subtype) {\n subtype = typeof subtype !== 'undefined' ? subtype : 0x00\n return new Binary(this, subtype);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "toObject", + "string": "MongooseBuffer.prototype.toObject()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "Binary", + "value": "Binary", + "string": "MongooseBuffer.Binary" + } + } +] +### lib/types/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , util = require('util')", + "ctx": { + "type": "declaration", + "name": "MongooseArray", + "value": "require('./array')", + "string": "MongooseArray" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to this array" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "MongooseDocumentArray" + ], + "description": "" + }, + { + "type": "inherits", + "string": "MongooseArray" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    DocumentArray constructor

    ", + "summary": "

    DocumentArray constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseDocumentArray", + "string": "MongooseDocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseArray

    ", + "summary": "

    Inherits from MongooseArray

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseDocumentArray", + "name": "__proto__", + "value": "MongooseArray.prototype", + "string": "MongooseDocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides MongooseArray#cast

    ", + "summary": "

    Overrides MongooseArray#cast

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype._cast = function (value) {\n if (value instanceof this._schema.casterConstructor)\n return value;\n\n return new this._schema.casterConstructor(value, this);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "_cast", + "string": "MongooseDocumentArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "EmbeddedDocument", + "null" + ], + "description": "the subdocuent or null if not found." + }, + { + "type": "param", + "types": [ + "ObjectId", + "String", + "Number", + "Buffer" + ], + "name": "id", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Searches array items for the first document with a matching id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", + "summary": "

    Searches array items for the first document with a matching id.

    ", + "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "id", + "string": "MongooseDocumentArray.prototype.id()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", + "summary": "

    Returns a native js Array of plain js objects

    ", + "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "toObject", + "string": "MongooseDocumentArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "inspect", + "string": "MongooseDocumentArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the value to cast to this arrays SubDocument schema" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", + "summary": "

    Creates a subdocument casted to this schema.

    ", + "body": "

    This is the same subdocument constructor used for casting.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "create", + "string": "MongooseDocumentArray.prototype.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates a fn that notifies all child docs of event.

    ", + "summary": "

    Creates a fn that notifies all child docs of event.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n if (!self[i]) continue;\n self[i].emit(event, val);\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "notify", + "string": "MongooseDocumentArray.prototype.notify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseDocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseDocumentArray", + "string": "module.exports" + } + } +] +### lib/types/embedded.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('../document')\n , inspect = require('util').inspect;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('../document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "js object returned from the db" + }, + { + "type": "param", + "types": [ + "MongooseDocumentArray" + ], + "name": "parentArr", + "description": "the parent array of this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "skipId", + "description": "" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    EmbeddedDocument constructor.

    ", + "summary": "

    EmbeddedDocument constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", + "ctx": { + "type": "function", + "name": "EmbeddedDocument", + "string": "EmbeddedDocument()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Document

    ", + "summary": "

    Inherit from Document

    ", + "body": "" + }, + "ignore": true, + "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "EmbeddedDocument", + "name": "__proto__", + "value": "Document.prototype", + "string": "EmbeddedDocument.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path which changed" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", + "summary": "

    Marks the embedded doc modified.

    ", + "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this._activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "markModified", + "string": "EmbeddedDocument.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "return", + "types": [ + "EmbeddedDocument" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", + "summary": "

    Used as a stub for hooks.js

    ", + "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "save", + "string": "EmbeddedDocument.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes the subdocument from its parent array.

    ", + "summary": "

    Removes the subdocument from its parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' + \n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "remove", + "string": "EmbeddedDocument.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Override #update method of parent documents.

    ", + "summary": "

    Override #update method of parent documents.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "update", + "string": "EmbeddedDocument.prototype.update()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "inspect", + "string": "EmbeddedDocument.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "error which states the reason `path` was invalid" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.invalidate = function (path, err, first) {\n if (!this.__parent) return false;\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n this.__parent.invalidate(fullPath, err);\n if (first)\n this._validationError = ownerDocument(this)._validationError;\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "invalidate", + "string": "EmbeddedDocument.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n return ownerDocument(this);\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "ownerDocument", + "string": "EmbeddedDocument.prototype.ownerDocument()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function ownerDocument (self) {\n var parent = self.__parent;\n while (parent.__parent)\n parent = parent.__parent;\n return parent;\n}", + "ctx": { + "type": "function", + "name": "ownerDocument", + "string": "ownerDocument()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent document.

    ", + "summary": "

    Returns this sub-documents parent document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parent", + "string": "EmbeddedDocument.prototype.parent()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent array.

    ", + "summary": "

    Returns this sub-documents parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parentArray", + "string": "EmbeddedDocument.prototype.parentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = EmbeddedDocument;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "EmbeddedDocument", + "string": "module.exports" + } + } +] +### lib/types/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "Array", + "value": "require('./array')", + "string": "exports.Array" + } + } +] +### lib/types/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [ + { + "type": "constructor", + "string": "ObjectId" + } + ], + "description": { + "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", + "summary": "

    ObjectId type constructor

    ", + "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require(driver + '/objectid')", + "string": "ObjectId" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "str", + "description": "" + }, + { + "type": "static", + "string": "fromString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "ObjectId" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates an ObjectId from str

    ", + "summary": "

    Creates an ObjectId from str

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.fromString;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId" + ], + "name": "oid", + "description": "ObjectId instance" + }, + { + "type": "static", + "string": "toString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts oid to a string.

    ", + "summary": "

    Converts oid to a string.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.toString;" + } +] +### lib/utils.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , sliced = require('sliced')\n , MongooseBuffer\n , MongooseArray\n , Document", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "a model name" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "a collection name" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a collection name from model name.

    ", + "summary": "

    Produces a collection name from model name.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "toCollectionName", + "string": "exports.toCollectionName()" + } + }, + { + "tags": [], + "description": { + "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Pluralization rules.

    ", + "body": "

    These rules are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "pluralization", + "value": "[", + "string": "exports.pluralization" + } + }, + { + "tags": [], + "description": { + "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Uncountable words.

    ", + "body": "

    These words are applied while processing the argument to toCollectionName.

    " + }, + "ignore": false, + "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news',\n 'expertise',\n 'status',\n 'media'\n];\nvar uncountables = exports.uncountables;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "uncountables", + "value": "[", + "string": "exports.uncountables" + } + }, + { + "tags": [ + { + "type": "author", + "string": "TJ Holowaychuk (extracted from _ext.js_)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "string", + "description": "to pluralize" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pluralize function.

    ", + "summary": "

    Pluralize function.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", + "ctx": { + "type": "function", + "name": "pluralize", + "string": "pluralize()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "listener", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Add once to EventEmitter if absent

    ", + "summary": "

    Add once to EventEmitter if absent

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var Events = EventEmitter;\n\nif (!('once' in EventEmitter.prototype)){\n\n Events = function () {\n EventEmitter.apply(this, arguments);\n };", + "ctx": { + "type": "declaration", + "name": "Events", + "value": "EventEmitter", + "string": "Events" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Events", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Events.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Add once.

    ", + "summary": "

    Add once.

    ", + "body": "" + }, + "ignore": true, + "code": "Events.prototype.once = function (type, listener) {\n var self = this;\n self.on(type, function g(){\n self.removeListener(type, g);\n listener.apply(this, arguments);\n });\n };\n}\nexports.EventEmitter = Events;", + "ctx": { + "type": "method", + "constructor": "Events", + "name": "once", + "string": "Events.prototype.once()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "a", + "description": "a value to compare to `b`" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "b", + "description": "a value to compare to `a`" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", + "summary": "

    Determines if a and b are deep equal.

    ", + "body": "

    Modified from node/lib/assert.js

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "deepEqual", + "string": "exports.deepEqual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the object to clone" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the cloned object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Object clone with Mongoose natives support.

    \n\n

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    ", + "summary": "

    Object clone with Mongoose natives support.

    ", + "body": "

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name)\n return new RegExp(obj.source);\n\n if (obj instanceof ObjectId)\n return new ObjectId(obj.id);\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "clone", + "string": "exports.clone()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", + "ctx": { + "type": "function", + "name": "cloneObject", + "string": "cloneObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "defaults", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the merged object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Copies and merges options with defaults.

    ", + "summary": "

    Copies and merges options with defaults.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "options", + "string": "exports.options()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Generates a random string

    ", + "summary": "

    Generates a random string

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "random", + "string": "exports.random()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "to", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "from", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges from into to without overwriting existing properties.

    ", + "summary": "

    Merges from into to without overwriting existing properties.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n if (exports.isObject(from[key])) {\n merge(to[key], from[key]);\n } else {\n to[key] = from[key];\n }\n }\n }\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "merge", + "string": "exports.merge()" + } + }, + { + "tags": [], + "description": { + "full": "

    toString helper

    ", + "summary": "

    toString helper

    ", + "body": "" + }, + "ignore": true, + "code": "var toString = Object.prototype.toString;", + "ctx": { + "type": "declaration", + "name": "toString", + "value": "Object.prototype.toString", + "string": "toString" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "Array", + "String", + "Function", + "RegExp", + "any" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + } + ], + "description": { + "full": "

    Determines if arg is an object.

    ", + "summary": "

    Determines if arg is an object.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "exports.isObject = function (arg) {\n return '[object Object]' == toString.call(arg);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isObject", + "string": "exports.isObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.args = sliced;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "args", + "value": "sliced", + "string": "exports.args" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", + "summary": "

    process.nextTick helper.

    ", + "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "tick", + "string": "exports.tick()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "v", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", + "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", + "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isMongooseObject", + "string": "exports.isMongooseObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "object", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expireAfterSeconds = when;\n delete object.expires;\n}\n\nexports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "expires", + "string": "exports.expires()" + } + } +] +### lib/virtualtype.js +[ + { + "tags": [ + { + "type": "parma", + "string": "{Object} options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", + "summary": "

    VirtualType constructor

    ", + "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", + "ctx": { + "type": "function", + "name": "VirtualType", + "string": "VirtualType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", + "summary": "

    Defines a getter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "get", + "string": "VirtualType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", + "summary": "

    Defines a setter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "set", + "string": "VirtualType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all getters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies getters to value using optional scope.

    ", + "summary": "

    Applies getters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applyGetters", + "string": "VirtualType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all setters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies setters to value using optional scope.

    ", + "summary": "

    Applies setters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applySetters", + "string": "VirtualType.prototype.applySetters()" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = VirtualType;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "VirtualType", + "string": "module.exports" + } + } +] diff --git a/docs/3.4.x/docs/source/api.js b/docs/3.4.x/docs/source/api.js new file mode 100644 index 00000000000..8fd87f0035b --- /dev/null +++ b/docs/3.4.x/docs/source/api.js @@ -0,0 +1,220 @@ +/*! + * Module dependencies + */ + +var fs = require('fs'); +var link = require('../helpers/linktype'); +var hl = require('highlight.js') +var md = require('markdown') + +module.exports = { + docs: [] + , github: 'https://github.com/LearnBoost/mongoose/tree/' + , title: 'API docs' +} + +var out = module.exports.docs; + +var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); +parse(docs); +order(out); + +function parse (docs) { + docs.split(/^### /gm).forEach(function (chunk) { + if (!(chunk = chunk.trim())) return; + + chunk = chunk.split(/^([^\n]+)\n/); + + var title = chunk[1]; + + if (!title || !(title = title.trim())) + throw new Error('missing title'); + + title = title.replace(/^lib\//, ''); + + var json = JSON.parse(chunk[2]); + + var props = []; + var methods = []; + var statics = []; + var constructor = null; + + json.forEach(function (comment) { + if (comment.description) + highlight(comment.description); + + var prop = false; + comment.params = []; + comment.see = []; + + var i = comment.tags.length; + while (i--) { + var tag = comment.tags[i]; + switch (tag.type) { + case 'property': + prop = true; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + props.unshift(comment); + break; + case 'method': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'method'; + comment.code = ''; + break; + case 'memberOf': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.constructor = tag.parent; + break; + case 'static': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + comment.ctx.type = 'method'; + break; + case 'receiver': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.receiver = tag.string; + break; + case 'constructor': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'function'; + comment.code = ''; + break; + case 'inherits': + if (/http/.test(tag.string)) { + var result = tag.string.split(' '); + var href = result.pop(); + var title = result.join(' '); + comment.inherits = '' + title + ''; + } else { + comment.inherits = link(tag.string); + } + comment.tags.splice(i, 1); + break; + case 'param': + comment.params.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'return': + comment.return = tag; + comment.tags.splice(i, 1); + break; + case 'see': + if (tag.local) { + var parts = tag.local.split(' '); + if (1 === parts.length) { + tag.url = link.type(parts[0]); + tag.title = parts[0]; + } else { + tag.url = parts.pop(); + tag.title = parts.join(' '); + } + } + comment.see.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'event': + var str = tag.string.replace(/\\n/g, '\n'); + tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); + comment.events || (comment.events = []); + comment.events.unshift(tag); + comment.tags.splice(i, 1); + } + } + + if (!prop) { + methods.push(comment); + } + }); + + methods = methods.filter(ignored); + props = props.filter(ignored); + + function ignored (method) { + if (method.ignore) return false; + return true; + } + + if (0 === methods.length + props.length) return; + + // add constructor to properties too + methods.some(function (method) { + if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { + props.forEach(function (prop) { + prop.ctx.constructor = method.ctx.constructor; + }); + return true; + } + return false; + }); + + var len = methods.length; + while (len--) { + method = methods[len]; + if (method.ctx && method.ctx.receiver) { + var stat = methods.splice(len, 1)[0]; + statics.unshift(stat); + } + } + + out.push({ + title: title + , methods: methods + , props: props + , statics: statics + , hasPublic: hasPublic(methods, props, statics) + }); + }); +} + +function hasPublic () { + for (var i = 0; i < arguments.length; ++i) { + var arr = arguments[i]; + for (var j = 0; j < arr.length; ++j) { + var item = arr[j]; + if (!item.ignore && !item.isPrivate) return true; + } + } + return false; +} + +// add "class='language'" to our
     elements
    +function highlight (o) {
    +  o.full = fix(o.full);
    +  o.summary = fix(o.summary);
    +  o.body = fix(o.body);
    +}
    +
    +function fix (str) {
    +  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    +
    +    // parse out the ```language
    +    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    +
    +    if ('js' == code[1] || !code[1]) {
    +      code[1] = 'javascript';
    +    }
    +
    +    return $1
    +          + hl.highlight(code[1], code[2]).value.trim()
    +          + $3;
    +  });
    +}
    +
    +function order (docs) {
    +  // want index first
    +  for (var i = 0; i < docs.length; ++i) {
    +    if ('index.js' == docs[i].title) {
    +      docs.unshift(docs.splice(i, 1)[0]);
    +    }
    +  }
    +}
    diff --git a/docs/3.4.x/docs/source/home.js b/docs/3.4.x/docs/source/home.js
    new file mode 100644
    index 00000000000..e349d8ddcad
    --- /dev/null
    +++ b/docs/3.4.x/docs/source/home.js
    @@ -0,0 +1,7 @@
    +
    +var package = require('./../../package.json')
    +
    +module.exports = {
    +    package: package
    +  , title: 'ODM'
    +}
    diff --git a/docs/3.4.x/docs/source/index.js b/docs/3.4.x/docs/source/index.js
    new file mode 100644
    index 00000000000..18b3eeb5718
    --- /dev/null
    +++ b/docs/3.4.x/docs/source/index.js
    @@ -0,0 +1,20 @@
    +
    +exports['index.jade'] = require('./home')
    +exports['docs/api.jade'] = require('./api')
    +exports['docs/index.jade'] = { title: 'Getting Started' }
    +exports['docs/production.jade'] = require('./production')
    +exports['docs/prior.jade'] = require('./prior')
    +exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    +exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    +exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    +exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    +exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    +exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    +exports['docs/models.jade'] = { guide: true, title: 'Models' }
    +exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    +exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    +exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    +exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    +exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    +exports['docs/connections.jade'] = { guide: true, title: 'Connecting to MongoDB' }
    +exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.4.x/docs/source/prior.js b/docs/3.4.x/docs/source/prior.js
    new file mode 100644
    index 00000000000..2e03811d215
    --- /dev/null
    +++ b/docs/3.4.x/docs/source/prior.js
    @@ -0,0 +1,13 @@
    +var fs = require('fs')
    +var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    +releases = releases.split('\n').filter(Boolean);
    +
    +module.exports = exports = {
    +    title: ''
    +  , releases: releases.map(function (version) {
    +      return {
    +          url: version + '/'
    +        , version: version
    +      }
    +    })
    +}
    diff --git a/docs/3.4.x/docs/source/production.js b/docs/3.4.x/docs/source/production.js
    new file mode 100644
    index 00000000000..9fdbcfffbc7
    --- /dev/null
    +++ b/docs/3.4.x/docs/source/production.js
    @@ -0,0 +1,17 @@
    +
    +var fs = require('fs')
    +var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    +
    +var imgs = [];
    +
    +images.forEach(function (line) {
    +  line = line.trim();
    +  if (!line) return;
    +  line = line.split('|');
    +  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    +});
    +
    +module.exports = {
    +    images: imgs
    +  , title: 'Production'
    +}
    diff --git a/docs/3.4.x/docs/subdocs.html b/docs/3.4.x/docs/subdocs.html
    new file mode 100644
    index 00000000000..a97d0e026c7
    --- /dev/null
    +++ b/docs/3.4.x/docs/subdocs.html
    @@ -0,0 +1,49 @@
    +Mongoose SubDocuments v3.4.0Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    +
    +var parentSchema = new Schema({
    +  children: [childSchema]
    +})
    +

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = db.model('Parent', parentSchema);
    +var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    +parent.children[0].name = 'Matthew';
    +parent.save(callback);
    +

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    +  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    +  next();
    +});
    +
    +var parent = new Parent({ children: [{ name: 'invalid' }] });
    +parent.save(function (err) {
    +  console.log(err.message) // #sadpanda
    +})
    +

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    +

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = db.model('Parent');
    +var parent = new Parent;
    +
    +// create a comment
    +post.children.push({ name: 'Liesl' });
    +var doc = post.children[0];
    +console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    +doc.isNew; // true
    +
    +post.save(function (err) {
    +  if (err) return handleError(err)
    +  console.log('Success!');
    +});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    +

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    +parent.save(function (err) {
    +  if (err) return handleError(err);
    +  console.log('the sub-doc was removed')
    +});
    +

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    +  children: [{ name: 'string' }]
    +})
    +

    Next Up

    Now that we've covered Sub-documents, let's take a look at querying.

    diff --git a/docs/3.4.x/docs/validation.html b/docs/3.4.x/docs/validation.html new file mode 100644 index 00000000000..832b43aa4ae --- /dev/null +++ b/docs/3.4.x/docs/validation.html @@ -0,0 +1,37 @@ +Mongoose Validation v3.4.0Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    + +
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    + +

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    +  color: String,
    +  name: String
    +});
    +
    +var Toy = db.model('Toy', toySchema);
    +
    +Toy.schema.path('color').validate(function (value) {
    +  return /blue|green|white|red|orange|periwinkel/i.test(value);
    +}, 'Invalid color');
    +
    +var toy = new Toy({ color: 'grease'});
    +
    +toy.save(function (err) {
    +  // err.errors.color is a ValidatorError object
    +  
    +  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(err.errors.color.type) // prints "Invalid color"
    +  console.log(err.errors.color.path) // prints "color"
    +  console.log(err.name) // prints "ValidationError"
    +  console.log(err.message) // prints "Validation failed"
    +});
    +

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    +

    Next Up

    Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

    diff --git a/docs/3.4.x/docs/website.js b/docs/3.4.x/docs/website.js new file mode 100644 index 00000000000..d1adea38b5c --- /dev/null +++ b/docs/3.4.x/docs/website.js @@ -0,0 +1,48 @@ + +var fs= require('fs') +var jade = require('jade') +var package = require('./package') +var hl = require('./docs/helpers/highlight') +var linktype = require('./docs/helpers/linktype') +var href = require('./docs/helpers/href') +var klass = require('./docs/helpers/klass') + +// add custom jade filters +require('./docs/helpers/filters')(jade); + +// clean up version for ui +package.version = package.version.replace(/-pre$/, ''); + +var filemap = require('./docs/source'); +var files = Object.keys(filemap); + +files.forEach(function (file) { + var filename = __dirname + '/' + file; + jadeify(filename, filemap[file]); + + if ('--watch' == process.argv[2]) { + fs.watchFile(filename, { interval: 1000 }, function (cur, prev) { + if (cur.mtime > prev.mtime) { + jadeify(filename, filemap[file]); + } + }); + } +}); + +function jadeify (filename, options) { + options || (options = {}); + options.package = package; + options.hl = hl; + options.linktype = linktype; + options.href = href; + options.klass = klass; + jade.renderFile(filename, options, function (err, str) { + if (err) return console.error(err.stack); + + var newfile = filename.replace('.jade', '.html') + fs.writeFile(newfile, str, function (err) { + if (err) return console.error('could not write', err.stack); + console.log('%s : rendered ', new Date, newfile); + }); + }); +} diff --git a/docs/3.4.x/index.html b/docs/3.4.x/index.html new file mode 100644 index 00000000000..5bf9aaee774 --- /dev/null +++ b/docs/3.4.x/index.html @@ -0,0 +1,20 @@ +Mongoose ODM v3.4.0Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    Flexible, schema based and feature-rich, mongoose solves common problems for real-world applications.

    var mongoose = require('mongoose');
    +var db = mongoose.createConnection('localhost', 'test');
    +
    +var schema = mongoose.Schema({ name: 'string' });
    +var Cat = db.model('Cat', schema);
    +
    +var kitty = new Cat({ name: 'Zildjian' });
    +kitty.save(function (err) {
    +  if (err) // ...
    +  console.log('meow');
    +});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    Production + View More

    • Storify
    • LearnBoost
    • GeekList
    • McDonalds
    • ShoeJitsu
    • Bozuko
    \ No newline at end of file diff --git a/docs/3.4.x/static.js b/docs/3.4.x/static.js new file mode 100644 index 00000000000..fc0e722dd4e --- /dev/null +++ b/docs/3.4.x/static.js @@ -0,0 +1,17 @@ + +var static = require('node-static'); +var server = new static.Server('.', { cache: 0 }); + +require('http').createServer(function (req, res) { + req.on('end', function () { + server.serve(req, res, function (err) { + if (err) { + console.error(err, req.url); + res.writeHead(err.status, err.headers); + res.end(); + } + }); + }); +}).listen(8088); + +console.error('now listening on localhost:8088'); diff --git a/docs/3.5.x/docs/api.html b/docs/3.5.x/docs/api.html new file mode 100644 index 00000000000..9bb76bb0a0f --- /dev/null +++ b/docs/3.5.x/docs/api.html @@ -0,0 +1,7225 @@ +Mongoose API v3.5.9Fork me on GitHub
    • index.js

      Mongoose()

      Mongoose constructor.

      show code
      function Mongoose () {
      +  this.connections = [];
      +  this.plugins = [];
      +  this.models = {};
      +  this.modelSchemas = {};
      +  this.options = {};
      +  this.createConnection(); // default connection
      +};

      The exports object of the mongoose module is an instance of this class.
      Most apps will only use this one instance.


      Mongoose#set(key, value)

      Sets mongoose options

      show code
      Mongoose.prototype.set = function (key, value) {
      +  if (arguments.length == 1)
      +    return this.options[key];
      +  this.options[key] = value;
      +  return this;
      +};

      Parameters:

      Example:

      + +
      mongoose.set('test', value) // sets the 'test' option to `value`

      Mongoose#get(key)

      Gets mongoose options

      Parameters:

      Example:

      + +
      mongoose.get('test') // returns the 'test' value

      Mongoose#createConnection([uri], [options])

      Creates a Connection instance.

      show code
      Mongoose.prototype.createConnection = function () {
      +  var conn = new Connection(this);
      +  this.connections.push(conn);
      +
      +  if (arguments.length) {
      +    if (rgxReplSet.test(arguments[0])) {
      +      conn.openSet.apply(conn, arguments);
      +    } else {
      +      conn.open.apply(conn, arguments);
      +    }
      +  }
      +
      +  return conn;
      +};

      Parameters:

      • [uri] <String> a mongodb:// URI
      • [options] <Object> options to pass to the driver

      Returns:

      Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

      + +

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver. Note that the safe option specified in your schema will overwrite the safe db option specified here unless you set your schemas safe option to undefined. See this for more information.

      + +

      Options passed take precedence over options included in connection strings.

      + +

      Example:

      + +
      // with mongodb:// URI
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
      +
      +// and options
      +var opts = { db: { native_parser: true }}
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
      +
      +// replica sets
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
      +
      +// and options
      +var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
      +db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
      +
      +// with [host, database_name[, port] signature
      +db = mongoose.createConnection('localhost', 'database', port)
      +
      +// and options
      +var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
      +db = mongoose.createConnection('localhost', 'database', port, opts)
      +
      +// initialize now, connect later
      +db = mongoose.createConnection();
      +db.open('localhost', 'database', port, [opts]);

      Mongoose#connect()

      Opens the default mongoose connection.

      show code
      Mongoose.prototype.connect = function () {
      +  var conn = this.connection;
      +
      +  if (rgxReplSet.test(arguments[0])) {
      +    conn.openSet.apply(conn, arguments);
      +  } else {
      +    conn.open.apply(conn, arguments);
      +  }
      +
      +  return this;
      +};

      Returns:

      If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

      + +

      Options passed take precedence over options included in connection strings.


      Mongoose#disconnect([fn])

      Disconnects all connections.

      show code
      Mongoose.prototype.disconnect = function (fn) {
      +  var count = this.connections.length
      +    , error
      +
      +  this.connections.forEach(function(conn){
      +    conn.close(function(err){
      +      if (error) return;
      +
      +      if (err) {
      +        error = err;
      +        if (fn) return fn(err);
      +        throw err;
      +      }
      +
      +      if (fn)
      +        --count || fn();
      +    });
      +  });
      +  return this;
      +};

      Parameters:

      • [fn] <Function> called after all connection close.

      Returns:


      Mongoose#model(name, [schema], [collection], [skipInit])

      Defines a model or retrieves it.

      show code
      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
      +  if (!(schema instanceof Schema)) {
      +    collection = schema;
      +    schema = false;
      +  }
      +
      +  if ('boolean' === typeof collection) {
      +    skipInit = collection;
      +    collection = null;
      +  }
      +
      +  // handle internal options from connection.model()
      +  var options;
      +  if (skipInit && utils.isObject(skipInit)) {
      +    options = skipInit;
      +    skipInit = true;
      +  } else {
      +    options = {};
      +  }
      +
      +  // look up schema for the collection. this might be a
      +  // default schema like system.indexes stored in SchemaDefaults.
      +  if (!this.modelSchemas[name]) {
      +    if (!schema && name in SchemaDefaults) {
      +      schema = SchemaDefaults[name];
      +    }
      +
      +    if (schema) {
      +      // cache it so we only apply plugins once
      +      this.modelSchemas[name] = schema;
      +      this._applyPlugins(schema);
      +    } else {
      +      throw new mongoose.Error.MissingSchemaError(name);
      +    }
      +  }
      +
      +  var model;
      +  var sub;
      +
      +  // connection.model() may be passing a different schema for
      +  // an existing model name. in this case don't read from cache.
      +  if (this.models[name] && false !== options.cache) {
      +    if (schema instanceof Schema && schema != this.models[name].schema) {
      +      throw new mongoose.Error.OverwriteModelError(name);
      +    }
      +
      +    if (collection) {
      +      // subclass current model with alternate collection
      +      model = this.models[name];
      +      schema = model.prototype.schema;
      +      sub = model.__subclass(this.connection, schema, collection);
      +      // do not cache the sub model
      +      return sub;
      +    }
      +
      +    return this.models[name];
      +  }
      +
      +  // ensure a schema exists
      +  if (!schema) {
      +    schema = this.modelSchemas[name];
      +    if (!schema) {
      +      throw new mongoose.Error.MissingSchemaError(name);
      +    }
      +  }
      +
      +  if (!collection) {
      +    collection = schema.get('collection') || format(name);
      +  }
      +
      +  var connection = options.connection || this.connection;
      +  model = Model.compile(name, schema, collection, connection, this);
      +
      +  if (!skipInit) {
      +    model.init();
      +  }
      +
      +  if (false === options.cache) {
      +    return model;
      +  }
      +
      +  return this.models[name] = model;
      +}

      Parameters:

      • name <String> model name
      • [schema] <Schema>
      • [collection] <String> name (optional, induced from model name)
      • [skipInit] <Boolean> whether to skip initialization (defaults to false)

      Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +
      +// define an Actor model with this mongoose instance
      +mongoose.model('Actor', new Schema({ name: String }));
      +
      +// create a new connection
      +var conn = mongoose.createConnection(..);
      +
      +// retrieve the Actor model
      +var Actor = conn.model('Actor');
      + +

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

      + +

      Example:

      + +
      var schema = new Schema({ name: String }, { collection: 'actor' });
      +
      +// or
      +
      +schema.set('collection', 'actor');
      +
      +// or
      +
      +var collectionName = 'actor'
      +var M = mongoose.model('Actor', schema, collectionName)

      Mongoose#_applyPlugins(schema)

      Applies global plugins to schema.

      show code
      Mongoose.prototype._applyPlugins = function (schema) {
      +  for (var i = 0, l = this.plugins.length; i < l; i++) {
      +    schema.plugin(this.plugins[i][0], this.plugins[i][1]);
      +  }
      +}

      Parameters:


      Mongoose#plugin(fn, [opts])

      Declares a global plugin executed on all Schemas.

      show code
      Mongoose.prototype.plugin = function (fn, opts) {
      +  this.plugins.push([fn, opts]);
      +  return this;
      +};

      Parameters:

      Returns:

      Equivalent to calling .plugin(fn) on each Schema you create.


      module.exports

      The exports object is an instance of Mongoose.

      show code
      module.exports = exports = new Mongoose;
      +var mongoose = module.exports;

      mongoose.Collection

      The Mongoose Collection constructor

      show code
      mongoose.Collection = Collection;

      mongoose.Connection

      The Mongoose Connection constructor

      show code
      mongoose.Connection = Connection;

      mongoose.version

      Mongoose version

      show code
      mongoose.version = JSON.parse(
      +  require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      +).version;

      mongoose.Mongoose

      The Mongoose constructor

      show code
      mongoose.Mongoose = Mongoose;

      The exports of the mongoose module is an instance of this class.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var mongoose2 = new mongoose.Mongoose();

      mongoose.Schema

      The Mongoose Schema constructor

      show code
      mongoose.Schema = Schema;

      Example:

      + +
      var mongoose = require('mongoose');
      +var Schema = mongoose.Schema;
      +var CatSchema = new Schema(..);

      mongoose.SchemaType

      The Mongoose SchemaType constructor.

      show code
      mongoose.SchemaType = SchemaType;

      mongoose.SchemaTypes

      The various Mongoose SchemaTypes.

      show code
      mongoose.SchemaTypes = Schema.Types;

      Note:

      + +

      Alias of mongoose.Schema.Types for backwards compatibility.


      mongoose.VirtualType

      The Mongoose VirtualType constructor.

      show code
      mongoose.VirtualType = VirtualType;

      mongoose.Types

      The various Mongoose Types.

      show code
      mongoose.Types = Types;

      Example:

      + +
      var mongoose = require('mongoose');
      +var array = mongoose.Types.Array;
      + +

      Types:

      + +
        +
      • Array
      • +
      • Buffer
      • +
      • Document
      • +
      • Embedded
      • +
      • DocumentArray
      • +
      • ObjectId
      • +
      + +

      Using this exposed access to the ObjectId type, we can construct ids on demand.

      + +
      var ObjectId = mongoose.Types.ObjectId;
      +var id1 = new ObjectId;

      mongoose.Query

      The Mongoose Query constructor.

      show code
      mongoose.Query = Query;

      mongoose.Promise

      The Mongoose Promise constructor.

      show code
      mongoose.Promise = Promise;

      mongoose.Model

      The Mongoose Model constructor.

      show code
      mongoose.Model = Model;

      mongoose.Document

      The Mongoose Document constructor.

      show code
      mongoose.Document = Document;

      mongoose.Error

      The MongooseError constructor.

      show code
      mongoose.Error = require('./error');

      mongoose.mongo

      The node-mongodb-native driver Mongoose uses.

      show code
      mongoose.mongo = require('mongodb');

      Mongoose#connection

      The default connection of the mongoose module.

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +mongoose.connect(...);
      +mongoose.connection.on('error', cb);
      + +

      This is the connection used by default for every model created using mongoose.model.

      Returns:


    • connection.js

      Connection(base)

      Connection constructor

      show code
      function Connection (base) {
      +  this.base = base;
      +  this.collections = {};
      +  this.models = {};
      +  this.replica = false;
      +  this.hosts = null;
      +  this.host = null;
      +  this.port = null;
      +  this.user = null;
      +  this.pass = null;
      +  this.name = null;
      +  this.options = null;
      +  this._readyState = STATES.disconnected;
      +  this._closeCalled = false;
      +  this._hasOpened = false;
      +};

      Parameters:

      Events:

      • connecting: Emitted when connection.{open,openSet}() is executed on this connection.

      • connected: Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios.

      • open: Emitted after we connected and onOpen is executed on all of this connections models.

      • disconnecting: Emitted when connection.close() was executed.

      • disconnected: Emitted after getting disconnected from the db.

      • close: Emitted after we disconnected and onClose executed on all of this connections models.

      • reconnected: Emitted after we connected and subsequently disconnected, followed by successfully another successfull connection.

      • error: Emitted when an error occurs on this connection.

      • fullsetup: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

      For practical reasons, a Connection equals a Db.


      Connection#open(connection_string, [database], [port], [options], [callback])

      Opens the connection to MongoDB.

      show code
      Connection.prototype.open = function (host, database, port, options, callback) {
      +  var self = this
      +    , parsed
      +    , uri;
      +
      +  if ('string' === typeof database) {
      +    switch (arguments.length) {
      +      case 2:
      +        port = 27017;
      +      case 3:
      +        switch (typeof port) {
      +          case 'function':
      +            callback = port, port = 27017;
      +            break;
      +          case 'object':
      +            options = port, port = 27017;
      +            break;
      +        }
      +        break;
      +      case 4:
      +        if ('function' === typeof options)
      +          callback = options, options = {};
      +    }
      +  } else {
      +    switch (typeof database) {
      +      case 'function':
      +        callback = database, database = undefined;
      +        break;
      +      case 'object':
      +        options = database;
      +        database = undefined;
      +        callback = port;
      +        break;
      +    }
      +
      +    if (!rgxProtocol.test(host)) {
      +      host = 'mongodb://' + host;
      +    }
      +
      +    try {
      +      parsed = muri(host);
      +    } catch (err) {
      +      this.error(err, callback);
      +      return this;
      +    }
      +
      +    database = parsed.db;
      +    host = parsed.hosts[0].host || parsed.hosts[0].ipc;
      +    port = parsed.hosts[0].port || 27017;
      +  }
      +
      +  this.options = this.parseOptions(options, parsed && parsed.options);
      +
      +  // make sure we can open
      +  if (STATES.disconnected !== this.readyState) {
      +    var err = new Error('Trying to open unclosed connection.');
      +    err.state = this.readyState;
      +    this.error(err, callback);
      +    return this;
      +  }
      +
      +  if (!host) {
      +    this.error(new Error('Missing hostname.'), callback);
      +    return this;
      +  }
      +
      +  if (!database) {
      +    this.error(new Error('Missing database name.'), callback);
      +    return this;
      +  }
      +
      +  // authentication
      +  if (options && options.user && options.pass) {
      +    this.user = options.user;
      +    this.pass = options.pass;
      +
      +  } else if (parsed && parsed.auth) {
      +    this.user = parsed.auth.user;
      +    this.pass = parsed.auth.pass;
      +
      +  // Check hostname for user/pass
      +  } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
      +    host = host.split('@');
      +    var auth = host.shift().split(':');
      +    host = host.pop();
      +    this.user = auth[0];
      +    this.pass = auth[1];
      +
      +  } else {
      +    this.user = this.pass = undefined;
      +  }
      +
      +  this.name = database;
      +  this.host = host;
      +  this.port = port;
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • connection_string <String> mongodb://uri or the host to which you are connecting
      • [database] <String> database name
      • [port] <Number> database port
      • [options] <Object> options
      • [callback] <Function>

      options is a hash with the following possible properties:

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSet instance
      +user    - username for authentication
      +pass    - password for authentication
      +auth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
      +
      + +

      Notes:

      + +

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.

      + +

      Options passed take precedence over options included in connection strings.


      Connection#openSet(uris, [database], [options], [callback])

      Opens the connection to a replica set.

      show code
      Connection.prototype.openSet = function (uris, database, options, callback) {
      +  if (!rgxProtocol.test(uris)) {
      +    uris = 'mongodb://' + uris;
      +  }
      +
      +  var self = this;
      +
      +  switch (arguments.length) {
      +    case 3:
      +      switch (typeof database) {
      +        case 'string':
      +          this.name = database;
      +          break;
      +        case 'object':
      +          callback = options;
      +          options = database;
      +          database = null;
      +          break;
      +      }
      +
      +      if ('function' === typeof options) {
      +        callback = options;
      +        options = {};
      +      }
      +      break;
      +    case 2:
      +      switch (typeof database) {
      +        case 'string':
      +          this.name = database;
      +          break;
      +        case 'function':
      +          callback = database, database = null;
      +          break;
      +        case 'object':
      +          options = database, database = null;
      +          break;
      +      }
      +  }
      +
      +  var parsed;
      +  try {
      +    parsed = muri(uris);
      +  } catch (err) {
      +    this.error(err, callback);
      +    return this;
      +  }
      +
      +  if (!this.name) {
      +    this.name = parsed.db;
      +  }
      +
      +  this.hosts = parsed.hosts;
      +  this.options = this.parseOptions(options, parsed && parsed.options);
      +  this.replica = true;
      +
      +  if (!this.name) {
      +    this.error(new Error('No database name provided for replica set'), callback);
      +    return this;
      +  }
      +
      +  // authentication
      +  if (options && options.user && options.pass) {
      +    this.user = options.user;
      +    this.pass = options.pass;
      +
      +  } else if (parsed && parsed.auth) {
      +    this.user = parsed.auth.user;
      +    this.pass = parsed.auth.pass;
      +
      +  } else {
      +    this.user = this.pass = undefined;
      +  }
      +
      +  this._open(callback);
      +  return this;
      +};

      Parameters:

      • uris <String> comma-separated mongodb:// `URI`s
      • [database] <String> database name if not included in `uris`
      • [options] <Object> passed to the internal driver
      • [callback] <Function>

      Example:

      + +
      var db = mongoose.createConnection();
      +db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
      + +

      The database name and/or auth need only be included in one URI.
      The options is a hash which is passed to the internal driver connection object.

      + +

      Valid options

      + +
      db      - passed to the connection db instance
      +server  - passed to the connection server instance(s)
      +replset - passed to the connection ReplSetServer instance
      +user    - username for authentication
      +pass    - password for authentication
      +auth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
      +
      + +

      Options passed take precedence over options included in connection strings.

      + +

      Notes:

      + +

      Mongoose forces the db option forceServerObjectId false and cannot be overridden.
      Mongoose defaults the server auto_reconnect options to true which can be overridden.
      See the node-mongodb-native driver instance for options that it understands.


      Connection#error(err, callback)

      error

      show code
      Connection.prototype.error = function (err, callback) {
      +  if (callback) return callback(err);
      +  this.emit('error', err);
      +}

      Parameters:

      Graceful error handling, passes error to callback
      if available, else emits error on the connection.


      Connection#_open(callback)

      Handles opening the connection with the appropriate method based on connection type.

      show code
      Connection.prototype._open = function (callback) {
      +  this.readyState = STATES.connecting;
      +  this._closeCalled = false;
      +
      +  var self = this;
      +
      +  var method = this.replica
      +    ? 'doOpenSet'
      +    : 'doOpen';
      +
      +  // open connection
      +  this[method](function (err) {
      +    if (err) {
      +      self.readyState = STATES.disconnected;
      +      if (self._hasOpened) {
      +        if (callback) callback(err);
      +      } else {
      +        self.error(err, callback);
      +      }
      +      return;
      +    }
      +
      +    self.onOpen(callback);
      +  });
      +}

      Parameters:


      Connection#onOpen()

      Called when the connection is opened

      show code
      Connection.prototype.onOpen = function (callback) {
      +  var self = this;
      +
      +  function open (err) {
      +    if (err) {
      +      self.readyState = STATES.disconnected;
      +      if (self._hasOpened) {
      +        if (callback) callback(err);
      +      } else {
      +        self.error(err, callback);
      +      }
      +      return;
      +    }
      +
      +    self.readyState = STATES.connected;
      +
      +    // avoid having the collection subscribe to our event emitter
      +    // to prevent 0.3 warning
      +    for (var i in self.collections)
      +      self.collections[i].onOpen();
      +
      +    callback && callback();
      +    self.emit('open');
      +  };
      +
      +  // re-authenticate
      +  if (self.user && self.pass) {
      +    self.db.authenticate(self.user, self.pass, self.options.auth, open);
      +  }
      +  else
      +    open();
      +};

      Connection#close([callback])

      Closes the connection

      show code
      Connection.prototype.close = function (callback) {
      +  var self = this;
      +  this._closeCalled = true;
      +
      +  switch (this.readyState){
      +    case 0: // disconnected
      +      callback && callback();
      +      break;
      +
      +    case 1: // connected
      +      this.readyState = STATES.disconnecting;
      +      this.doClose(function(err){
      +        if (err){
      +          self.error(err, callback);
      +        } else {
      +          self.onClose();
      +          callback && callback();
      +        }
      +      });
      +      break;
      +
      +    case 2: // connecting
      +      this.once('open', function(){
      +        self.close(callback);
      +      });
      +      break;
      +
      +    case 3: // disconnecting
      +      if (!callback) break;
      +      this.once('close', function () {
      +        callback();
      +      });
      +      break;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Connection#onClose()

      Called when the connection closes

      show code
      Connection.prototype.onClose = function () {
      +  this.readyState = STATES.disconnected;
      +
      +  // avoid having the collection subscribe to our event emitter
      +  // to prevent 0.3 warning
      +  for (var i in this.collections)
      +    this.collections[i].onClose();
      +
      +  this.emit('close');
      +};

      Connection#collection(name, [options])

      Retrieves a collection, creating it if not cached.

      show code
      Connection.prototype.collection = function (name, options) {
      +  if (!(name in this.collections))
      +    this.collections[name] = new Collection(name, this, options);
      +  return this.collections[name];
      +};

      Parameters:

      • name <String> of the collection
      • [options] <Object> optional collection options

      Returns:


      Connection#model(name, [schema], [collection])

      Defines or retrieves a model.

      show code
      Connection.prototype.model = function (name, schema, collection) {
      +  // collection name discovery
      +  if ('string' == typeof schema) {
      +    collection = schema;
      +    schema = false;
      +  }
      +
      +  if (this.models[name] && !collection) {
      +    // model exists but we are not subclassing with custom collection
      +    if (schema instanceof Schema && schema != this.models[name].schema) {
      +      throw new MongooseError.OverwriteModelError(name);
      +    }
      +    return this.models[name];
      +  }
      +
      +  var opts = { cache: false, connection: this }
      +  var model;
      +
      +  if (schema instanceof Schema) {
      +    // compile a model
      +    model = this.base.model(name, schema, collection, opts)
      +
      +    // only the first model with this name is cached to allow
      +    // for one-offs with custom collection names etc.
      +    if (!this.models[name]) {
      +      this.models[name] = model;
      +    }
      +
      +    model.init();
      +    return model;
      +  }
      +
      +  if (this.models[name] && collection) {
      +    // subclassing current model with alternate collection
      +    model = this.models[name];
      +    schema = model.prototype.schema;
      +    var sub = model.__subclass(this, schema, collection);
      +    // do not cache the sub model
      +    return sub;
      +  }
      +
      +  // lookup model in mongoose module
      +  model = this.base.models[name];
      +
      +  if (!model) {
      +    throw new MongooseError.MissingSchemaError(name);
      +  }
      +
      +  if (this == model.prototype.db
      +      && (!collection || collection == model.collection.name)) {
      +    // model already uses this connection.
      +
      +    // only the first model with this name is cached to allow
      +    // for one-offs with custom collection names etc.
      +    if (!this.models[name]) {
      +      this.models[name] = model;
      +    }
      +
      +    return model;
      +  }
      +
      +  return this.models[name] = model.__subclass(this, schema, collection);
      +}

      Parameters:

      • name <String> the model name
      • [schema] <Schema> a schema. necessary when defining a model
      • [collection] <String> name of mongodb collection (optional) if not given it will be induced from model name

      Returns:

      • <Model> The compiled model
      var mongoose = require('mongoose');
      +var db = mongoose.createConnection(..);
      +db.model('Venue', new Schema(..));
      +var Ticket = db.model('Ticket', new Schema(..));
      +var Venue = db.model('Venue');
      + +

      When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

      + +

      Example:

      + +
      var schema = new Schema({ name: String }, { collection: 'actor' });
      +
      +// or
      +
      +schema.set('collection', 'actor');
      +
      +// or
      +
      +var collectionName = 'actor'
      +var M = conn.model('Actor', schema, collectionName)

      Connection#setProfiling(level, [ms], callback)

      Set profiling level.

      show code
      Connection.prototype.setProfiling = function (level, ms, callback) {
      +  if (STATES.connected !== this.readyState) {
      +    return this.on('open', this.setProfiling.bind(this, level, ms, callback));
      +  }
      +
      +  if (!callback) callback = ms, ms = 100;
      +
      +  var cmd = {};
      +
      +  switch (level) {
      +    case 0:
      +    case 'off':
      +      cmd.profile = 0;
      +      break;
      +    case 1:
      +    case 'slow':
      +      cmd.profile = 1;
      +      if ('number' !== typeof ms) {
      +        ms = parseInt(ms, 10);
      +        if (isNaN(ms)) ms = 100;
      +      }
      +      cmd.slowms = ms;
      +      break;
      +    case 2:
      +    case 'all':
      +      cmd.profile = 2;
      +      break;
      +    default:
      +      return callback(new Error('Invalid profiling level: '+ level));
      +  }
      +
      +  this.db.executeDbCommand(cmd, function (err, resp) {
      +    if (err) return callback(err);
      +
      +    var doc = resp.documents[0];
      +
      +    err = 1 === doc.ok
      +      ? null
      +      : new Error('Could not set profiling level to: '+ level)
      +
      +    callback(err, doc);
      +  });
      +};

      Parameters:

      • level <Number, String> either off (0), slow (1), or all (2)
      • [ms] <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
      • callback <Function>

      Connection#db

      The mongodb.Db instance, set when the connection is opened


      Connection#collections

      A hash of the collections associated with this connection


      Connection#readyState

      Connection ready state

      + +
        +
      • 0 = disconnected
      • +
      • 1 = connected
      • +
      • 2 = connecting
      • +
      • 3 = disconnecting
      • +
      + +

      Each state change emits its associated event name.

      + +

      Example

      + +
      conn.on('connected', callback);
      +conn.on('disconnected', callback);

    • document.js

      Document(obj, [fields], [skipId])

      Document constructor.

      show code
      function Document (obj, fields, skipId) {
      +  this.setMaxListeners(0);
      +
      +  if ('boolean' === typeof fields) {
      +    this._strictMode = fields;
      +    this._selected = fields = undefined;
      +  } else {
      +    this._strictMode = this.schema.options && this.schema.options.strict;
      +    this._selected = fields;
      +  }
      +
      +  this.isNew = true;
      +  this.errors = undefined;
      +  this._shardval = undefined;
      +  this._saveError = undefined;
      +  this._validationError = undefined;
      +  this._adhocPaths = undefined;
      +  this._removing = undefined;
      +  this._inserting = undefined;
      +  this.__version = undefined;
      +  this.__getters = {};
      +  this.__id = undefined;
      +
      +  this._activePaths = new ActiveRoster;
      +
      +  var required = this.schema.requiredPaths();
      +  for (var i = 0; i < required.length; ++i) {
      +    this._activePaths.require(required[i]);
      +  }
      +
      +  this._doc = this._buildDoc(obj, fields, skipId);
      +  if (obj) this.set(obj, undefined, true);
      +  this._registerHooks();
      +};

      Parameters:

      • obj <Object> the values to set
      • [fields] <Object> the fields which were selected in the query returning this document
      • [skipId] <Boolean> bool, should we auto create an ObjectId _id

      Events:

      • init: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

      • save: Emitted when the document is successfully saved


      Document#_buildDoc(obj, [fields], [skipId])

      Builds the default doc structure

      show code
      Document.prototype._buildDoc = function (obj, fields, skipId) {
      +  var doc = {}
      +    , self = this
      +    , exclude
      +    , keys
      +    , key
      +    , ki
      +
      +  // determine if this doc is a result of a query with
      +  // excluded fields
      +  if (fields && 'Object' === fields.constructor.name) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('_id' !== keys[ki]) {
      +        exclude = 0 === fields[keys[ki]];
      +        break;
      +      }
      +    }
      +  }
      +
      +  var paths = Object.keys(this.schema.paths)
      +    , plen = paths.length
      +    , ii = 0
      +
      +  for (; ii < plen; ++ii) {
      +    var p = paths[ii];
      +
      +    if ('_id' == p) {
      +      if (skipId) continue;
      +      if (obj && '_id' in obj) continue;
      +    }
      +
      +    var type = this.schema.paths[p]
      +      , path = p.split('.')
      +      , len = path.length
      +      , last = len-1
      +      , doc_ = doc
      +      , i = 0
      +
      +    for (; i < len; ++i) {
      +      var piece = path[i]
      +        , def
      +
      +      if (i === last) {
      +        if (fields) {
      +          if (exclude) {
      +            // apply defaults to all non-excluded fields
      +            if (p in fields) continue;
      +
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +
      +          } else if (p in fields) {
      +            // selected field
      +            def = type.getDefault(self, true);
      +            if ('undefined' !== typeof def) {
      +              doc_[piece] = def;
      +              self._activePaths.default(p);
      +            }
      +          }
      +        } else {
      +          def = type.getDefault(self, true);
      +          if ('undefined' !== typeof def) {
      +            doc_[piece] = def;
      +            self._activePaths.default(p);
      +          }
      +        }
      +      } else {
      +        doc_ = doc_[piece] || (doc_[piece] = {});
      +      }
      +    }
      +  };
      +
      +  return doc;
      +};

      Parameters:

      Returns:


      Document#init(doc, fn)

      Initializes the document without setters or marking anything modified.

      show code
      Document.prototype.init = function (doc, fn) {
      +  this.isNew = false;
      +
      +  init(this, doc, this._doc);
      +  this._storeShard();
      +
      +  this.emit('init', this);
      +  if (fn) fn(null);
      +  return this;
      +};

      Parameters:

      Called internally after a document is returned from mongodb.


      Document#_storeShard()

      Stores the current values of the shard keys.

      show code
      Document.prototype._storeShard = function _storeShard () {
      +  // backwards compat
      +  var key = this.schema.options.shardKey || this.schema.options.shardkey;
      +  if (!(key && 'Object' == key.constructor.name)) return;
      +
      +  var orig = this._shardval = {}
      +    , paths = Object.keys(key)
      +    , len = paths.length
      +    , val
      +
      +  for (var i = 0; i < len; ++i) {
      +    val = this.getValue(paths[i]);
      +    if (isMongooseObject(val)) {
      +      orig[paths[i]] = val.toObject({ depopulate: true })
      +    } else if (null != val && val.valueOf) {
      +      orig[paths[i]] = val.valueOf();
      +    } else {
      +      orig[paths[i]] = val;
      +    }
      +  }
      +}

      Note:

      + +

      Shard key values do not / are not allowed to change.


      Document#update(doc, options, callback)

      Sends an update command with this document _id as the query selector.

      show code
      Document.prototype.update = function update () {
      +  var args = utils.args(arguments);
      +  args.unshift({_id: this._id});
      +  this.constructor.update.apply(this.constructor, args);
      +}

      Parameters:

      Returns:

      Example:

      + +
      weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);
      + +

      Valid options:

      + +

      Document#set(path, val, [type], [options])

      Sets the value of a path, or many paths.

      show code
      Document.prototype.set = function (path, val, type, options) {
      +  if (type && 'Object' == type.constructor.name) {
      +    options = type;
      +    type = undefined;
      +  }
      +
      +  var merge = options && options.merge
      +    , adhoc = type && true !== type
      +    , constructing = true === type
      +    , adhocs
      +
      +  if (adhoc) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  if ('string' !== typeof path) {
      +    // new Document({ key: val })
      +
      +    if (null === path || undefined === path) {
      +      var _ = path;
      +      path = val;
      +      val = _;
      +
      +    } else {
      +      var prefix = val
      +        ? val + '.'
      +        : '';
      +
      +      if (path instanceof Document) path = path._doc;
      +
      +      var keys = Object.keys(path)
      +        , i = keys.length
      +        , pathtype
      +        , key
      +
      +      while (i--) {
      +        key = keys[i];
      +        pathtype = this.schema.pathType(prefix + key);
      +        if (null != path[key]
      +            && 'Object' == path[key].constructor.name
      +            && 'virtual' != pathtype
      +            && !(this._path(prefix + key) instanceof MixedSchema)) {
      +          this.set(path[key], prefix + key, constructing);
      +        } else if (this._strictMode) {
      +          if ('real' === pathtype || 'virtual' === pathtype) {
      +            this.set(prefix + key, path[key], constructing);
      +          } else if ('throw' == this._strictMode) {
      +            throw new Error("Field `" + key + "` is not in schema.");
      +          }
      +        } else if (undefined !== path[key]) {
      +          this.set(prefix + key, path[key], constructing);
      +        }
      +      }
      +
      +      return this;
      +    }
      +  }
      +
      +  // ensure _strict is honored for obj props
      +  // docschema = new Schema({ path: { nest: 'string' }})
      +  // doc.set('path', obj);
      +  var pathType = this.schema.pathType(path);
      +  if ('nested' == pathType && val && 'Object' == val.constructor.name) {
      +    if (!merge) this.setValue(path, null);
      +    this.set(val, path, constructing);
      +    return this;
      +  }
      +
      +  var schema;
      +  if ('adhocOrUndefined' == pathType && this._strictMode) {
      +    return this;
      +  } else if ('virtual' == pathType) {
      +    schema = this.schema.virtualpath(path);
      +    schema.applySetters(val, this);
      +    return this;
      +  } else {
      +    schema = this._path(path);
      +  }
      +
      +  var parts = path.split('.')
      +    , pathToMark
      +
      +  // When using the $set operator the path to the field must already exist.
      +  // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
      +
      +  if (parts.length <= 1) {
      +    pathToMark = path;
      +  } else {
      +    for (var i = 0; i < parts.length; ++i) {
      +      var part = parts[i];
      +      var subpath = parts.slice(0, i).concat(part).join('.');
      +      if (this.isDirectModified(subpath) // earlier prefixes that are already
      +                                         // marked as dirty have precedence
      +          || this.get(subpath) === null) {
      +        pathToMark = subpath;
      +        break;
      +      }
      +    }
      +
      +    if (!pathToMark) pathToMark = path;
      +  }
      +
      +  if (!schema || null === val || undefined === val) {
      +    this._set(pathToMark, path, constructing, parts, schema, val);
      +    return this;
      +  }
      +
      +  var self = this;
      +
      +  // if this doc is being constructed we should not
      +  // trigger getters.
      +  var priorVal = constructing
      +    ? undefined
      +    : this.get(path);
      +
      +  var shouldSet = this.try(function(){
      +    val = schema.applySetters(val, self, false, priorVal);
      +  });
      +
      +  if (shouldSet) {
      +    this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
      +  }
      +
      +  return this;
      +}

      Parameters:

      • path <String, Object> path or object of key/vals to set
      • val <Any> the value to set
      • [type] <Schema, String, Number, Buffer, etc..> optionally specify a type for "on-the-fly" attributes
      • [options] <Object> optionally specify options that modify the behavior of the set

      Example:

      + +
      // path, value
      +doc.set(path, value)
      +
      +// object
      +doc.set({
      +    path  : value
      +  , path2 : {
      +       path  : value
      +    }
      +})
      +
      +// only-the-fly cast to number
      +doc.set(path, value, Number)
      +
      +// only-the-fly cast to string
      +doc.set(path, value, String)

      Document#_shouldModify()

      Determine if we should mark this change as modified.

      show code
      Document.prototype._shouldModify = function (
      +    pathToMark, path, constructing, parts, schema, val, priorVal) {
      +
      +  if (this.isNew) return true;
      +  if (this.isDirectModified(pathToMark)) return false;
      +
      +  if (undefined === val && !this.isSelected(path)) {
      +    // when a path is not selected in a query, its initial
      +    // value will be undefined.
      +    return true;
      +  }
      +
      +  if (undefined === val && path in this._activePaths.states.default) {
      +    // we're just unsetting the default value which was never saved
      +    return false;
      +  }
      +
      +  if (!deepEqual(val, priorVal || this.get(path))) {
      +    return true;
      +  }
      +
      +  if (!constructing &&
      +      null != val &&
      +      path in this._activePaths.states.default &&
      +      deepEqual(val, schema.getDefault(this, constructing))) {
      +    // a path with a default was $unset on the server
      +    // and the user is setting it to the same value again
      +    return true;
      +  }
      +
      +  return false;
      +}

      Returns:


      Document#_set()

      Handles the actual setting of the value and marking the path modified if appropriate.

      show code
      Document.prototype._set = function (
      +    pathToMark, path, constructing, parts, schema, val, priorVal) {
      +
      +  var shouldModify = this._shouldModify.apply(this, arguments);
      +
      +  if (shouldModify) {
      +    this.markModified(pathToMark, val);
      +
      +    // handle directly setting arrays (gh-1126)
      +    MongooseArray || (MongooseArray = require('./types/array'));
      +    if (val instanceof MongooseArray) {
      +      val._registerAtomic('$set', val);
      +    }
      +  }
      +
      +  var obj = this._doc
      +    , i = 0
      +    , l = parts.length
      +
      +  for (; i < l; i++) {
      +    var next = i + 1
      +      , last = next === l;
      +
      +    if (last) {
      +      obj[parts[i]] = val;
      +    } else {
      +      if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
      +        obj = obj[parts[i]];
      +      } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
      +        obj = obj[parts[i]];
      +      } else {
      +        obj = obj[parts[i]] = {};
      +      }
      +    }
      +  }
      +}

      Document#getValue(path)

      Gets a raw value from a path (no getters)

      show code
      Document.prototype.getValue = function (path) {
      +  var parts = path.split('.')
      +    , obj = this._doc
      +    , part;
      +
      +  for (var i = 0, l = parts.length; i < l; i++) {
      +    part = parts[i];
      +    obj = obj.getValue
      +        ? obj.getValue(part) // If we have an embedded array document member
      +        : obj[part];
      +    if (!obj) return obj;
      +  }
      +
      +  return obj;
      +}

      Parameters:


      Document#setValue(path, value)

      Sets a raw value for a path (no casting, setters, transformations)

      show code
      Document.prototype.setValue = function (path, val) {
      +  var parts = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, len = parts.length-1; i < len; i++) {
      +    obj = obj[parts[i]];
      +  }
      +
      +  obj[parts[len]] = val;
      +  return this;
      +};

      Parameters:


      Document#get(path, [type])

      Returns the value of a path.

      show code
      Document.prototype.get = function (path, type) {
      +  var adhocs;
      +  if (type) {
      +    adhocs = this._adhocPaths || (this._adhocPaths = {});
      +    adhocs[path] = Schema.interpretAsType(path, type);
      +  }
      +
      +  var schema = this._path(path) || this.schema.virtualpath(path)
      +    , pieces = path.split('.')
      +    , obj = this._doc;
      +
      +  for (var i = 0, l = pieces.length; i < l; i++) {
      +    obj = null == obj ? null : obj[pieces[i]];
      +  }
      +
      +  if (schema) {
      +    obj = schema.applyGetters(obj, this);
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Example

      + +
      // path
      +doc.get('age') // 47
      +
      +// dynamic casting to a string
      +doc.get('age', String) // "47"

      Document#_path(path)

      Returns the schematype for the given path.

      show code
      Document.prototype._path = function (path) {
      +  var adhocs = this._adhocPaths
      +    , adhocType = adhocs && adhocs[path];
      +
      +  if (adhocType) {
      +    return adhocType;
      +  } else {
      +    return this.schema.path(path);
      +  }
      +};

      Parameters:


      Document#markModified(path)

      Marks the path as having pending changes to write to the db.

      show code
      Document.prototype.markModified = function (path) {
      +  this._activePaths.modify(path);
      +}

      Parameters:

      • path <String> the path to mark modified

      Very helpful when using Mixed types.

      + +

      Example:

      + +
      doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');
      +doc.save() // changes to mixed.type are now persisted

      Document#try(fn, scope)

      Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

      show code
      Document.prototype.try = function (fn, scope) {
      +  var res;
      +  try {
      +    fn.call(scope);
      +    res = true;
      +  } catch (e) {
      +    this._error(e);
      +    res = false;
      +  }
      +  return res;
      +};

      Parameters:

      • fn <Function> function to execute
      • scope <Object> the scope with which to call fn

      Document#modifiedPaths()

      Returns the list of paths that have been modified.

      show code
      Document.prototype.modifiedPaths = function () {
      +  var directModifiedPaths = Object.keys(this._activePaths.states.modify);
      +
      +  return directModifiedPaths.reduce(function (list, path) {
      +    var parts = path.split('.');
      +    return list.concat(parts.reduce(function (chains, part, i) {
      +      return chains.concat(parts.slice(0, i).concat(part).join('.'));
      +    }, []));
      +  }, []);
      +};

      Returns:


      Document#isModified([path])

      Returns true if this document was modified, else false.

      show code
      Document.prototype.isModified = function (path) {
      +  return path
      +    ? !!~this.modifiedPaths().indexOf(path)
      +    : this._activePaths.some('modify');
      +};

      Parameters:

      Returns:

      If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

      + +

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isModified()                    // true
      +doc.isModified('documents')         // true
      +doc.isModified('documents.0.title') // true
      +doc.isDirectModified('documents')   // false

      Document#isDirectModified(path)

      Returns true if path was directly set and modified, else false.

      show code
      Document.prototype.isDirectModified = function (path) {
      +  return (path in this._activePaths.states.modify);
      +};

      Parameters:

      Returns:

      Example

      + +
      doc.set('documents.0.title', 'changed');
      +doc.isDirectModified('documents.0.title') // true
      +doc.isDirectModified('documents') // false

      Document#isInit(path)

      Checks if path was initialized.

      show code
      Document.prototype.isInit = function (path) {
      +  return (path in this._activePaths.states.init);
      +};

      Parameters:

      Returns:


      Document#isSelected(path)

      Checks if path was selected in the source query which initialized this document.

      show code
      Document.prototype.isSelected = function isSelected (path) {
      +  if (this._selected) {
      +
      +    if ('_id' === path) {
      +      return 0 !== this._selected._id;
      +    }
      +
      +    var paths = Object.keys(this._selected)
      +      , i = paths.length
      +      , inclusive = false
      +      , cur
      +
      +    if (1 === i && '_id' === paths[0]) {
      +      // only _id was selected.
      +      return 0 === this._selected._id;
      +    }
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +      inclusive = !! this._selected[cur];
      +      break;
      +    }
      +
      +    if (path in this._selected) {
      +      return inclusive;
      +    }
      +
      +    i = paths.length;
      +    var pathDot = path + '.';
      +
      +    while (i--) {
      +      cur = paths[i];
      +      if ('_id' == cur) continue;
      +
      +      if (0 === cur.indexOf(pathDot)) {
      +        return inclusive;
      +      }
      +
      +      if (0 === pathDot.indexOf(cur)) {
      +        return inclusive;
      +      }
      +    }
      +
      +    return ! inclusive;
      +  }
      +
      +  return true;
      +}

      Parameters:

      Returns:

      Example

      + +
      Thing.findOne().select('name').exec(function (err, doc) {
      +   doc.isSelected('name') // true
      +   doc.isSelected('age')  // false
      +})

      Document#validate(cb)

      Executes registered validation rules for this document.

      show code
      Document.prototype.validate = function (cb) {
      +  var self = this
      +
      +  // only validate required fields when necessary
      +  var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
      +    if (!self.isSelected(path) && !self.isModified(path)) return false;
      +    return true;
      +  });
      +
      +  paths = paths.concat(Object.keys(this._activePaths.states.init));
      +  paths = paths.concat(Object.keys(this._activePaths.states.modify));
      +  paths = paths.concat(Object.keys(this._activePaths.states.default));
      +
      +  if (0 === paths.length) {
      +    complete();
      +    return this;
      +  }
      +
      +  var validating = {}
      +    , total = 0;
      +
      +  paths.forEach(validatePath);
      +  return this;
      +
      +  function validatePath (path) {
      +    if (validating[path]) return;
      +
      +    validating[path] = true;
      +    total++;
      +
      +    process.nextTick(function(){
      +      var p = self.schema.path(path);
      +      if (!p) return --total || complete();
      +
      +      p.doValidate(self.getValue(path), function (err) {
      +        if (err) self.invalidate(path, err, true);
      +        --total || complete();
      +      }, self);
      +    });
      +  }
      +
      +  function complete () {
      +    var err = self._validationError;
      +    self._validationError = undefined;
      +    self.emit('validate', self);
      +    cb(err);
      +  }
      +};

      Parameters:

      • cb <Function> called after validation completes, passing an error if one occurred

      Note:

      + +

      This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

      + +

      Example:

      + +
      doc.validate(function (err) {
      +  if (err) handleError(err);
      +  else // validation passed
      +});

      Document#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      Document.prototype.invalidate = function (path, err) {
      +  if (!this._validationError) {
      +    this._validationError = new ValidationError(this);
      +  }
      +
      +  if (!err || 'string' === typeof err) {
      +    err = new ValidatorError(path, err);
      +  }
      +
      +  this._validationError.errors[path] = err;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> the error which states the reason `path` was invalid

      Document#_reset()

      Resets the internal modified state of this document.

      show code
      Document.prototype._reset = function reset () {
      +  var self = this;
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this._activePaths
      +  .map('init', 'modify', function (i) {
      +    return self.getValue(i);
      +  })
      +  .filter(function (val) {
      +    return val && val instanceof DocumentArray && val.length;
      +  })
      +  .forEach(function (array) {
      +    var i = array.length;
      +    while (i--) {
      +      var doc = array[i];
      +      if (!doc) continue;
      +      doc._reset();
      +    }
      +  });
      +
      +  // clear atomics
      +  this._dirty().forEach(function (dirt) {
      +    var type = dirt.value;
      +    if (type && type._atomics) {
      +      type._atomics = {};
      +    }
      +  });
      +
      +  // Clear 'modify'('dirty') cache
      +  this._activePaths.clear('modify');
      +  this._validationError = undefined;
      +  this.errors = undefined;
      +  var self = this;
      +  this.schema.requiredPaths().forEach(function (path) {
      +    self._activePaths.require(path);
      +  });
      +
      +  return this;
      +}

      Returns:


      Document#_dirty()

      Returns this documents dirty paths / vals.

      show code
      Document.prototype._dirty = function _dirty () {
      +  var self = this;
      +
      +  var all = this._activePaths.map('modify', function (path) {
      +    return { path: path
      +           , value: self.getValue(path)
      +           , schema: self._path(path) };
      +  });
      +
      +  // Sort dirty paths in a flat hierarchy.
      +  all.sort(function (a, b) {
      +    return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
      +  });
      +
      +  // Ignore "foo.a" if "foo" is dirty already.
      +  var minimal = []
      +    , lastPath
      +    , top;
      +
      +  all.forEach(function (item, i) {
      +    if (item.path.indexOf(lastPath) !== 0) {
      +      lastPath = item.path + '.';
      +      minimal.push(item);
      +      top = item;
      +    } else {
      +      // special case for top level MongooseArrays
      +      if (top.value && top.value._atomics && top.value.hasAtomics()) {
      +        // the `top` array itself and a sub path of `top` are being modified.
      +        // the only way to honor all of both modifications is through a $set
      +        // of entire array.
      +        top.value._atomics = {};
      +        top.value._atomics.$set = top.value;
      +      }
      +    }
      +  });
      +
      +  top = lastPath = null;
      +  return minimal;
      +}

      Document#_setSchema(schema)

      Assigns/compiles schema into this documents prototype.

      show code
      Document.prototype._setSchema = function (schema) {
      +  compile(schema.tree, this);
      +  this.schema = schema;
      +}

      Parameters:


      Document#_registerHooks()

      Register default hooks

      show code
      Document.prototype._registerHooks = function _registerHooks () {
      +  if (!this.save) return;
      +
      +  DocumentArray || (DocumentArray = require('./types/documentarray'));
      +
      +  this.pre('save', function (next) {
      +    // we keep the error semaphore to make sure we don't
      +    // call `save` unnecessarily (we only need 1 error)
      +    var subdocs = 0
      +      , error = false
      +      , self = this;
      +
      +    // check for DocumentArrays
      +    var arrays = this._activePaths
      +    .map('init', 'modify', function (i) {
      +      return self.getValue(i);
      +    })
      +    .filter(function (val) {
      +      return val && val instanceof DocumentArray && val.length;
      +    });
      +
      +    if (!arrays.length)
      +      return next();
      +
      +    arrays.forEach(function (array) {
      +      if (error) return;
      +
      +      // handle sparse arrays by using for loop vs array.forEach
      +      // which skips the sparse elements
      +
      +      var len = array.length
      +      subdocs += len;
      +
      +      for (var i = 0; i < len; ++i) {
      +        if (error) break;
      +
      +        var doc = array[i];
      +        if (!doc) {
      +          --subdocs || next();
      +          continue;
      +        }
      +
      +        doc.save(handleSave);
      +      }
      +    });
      +
      +    function handleSave (err) {
      +      if (error) return;
      +
      +      if (err) {
      +        self._validationError = undefined;
      +        return next(error = err);
      +      }
      +
      +      --subdocs || next();
      +    }
      +
      +  }, function (err) {
      +    // emit on the Model if listening
      +    if (this.constructor.listeners('error').length) {
      +      this.constructor.emit('error', err);
      +    } else {
      +      // emit on the connection
      +      if (!this.db.listeners('error').length) {
      +        err.stack = 'No listeners detected, throwing. '
      +                  + 'Consider adding an error listener to your connection.
      +'
      +                  + err.stack
      +      }
      +      this.db.emit('error', err);
      +    }
      +  }).pre('save', function checkForExistingErrors (next) {
      +    // if any doc.set() calls failed
      +    var err = this._saveError;
      +    if (err) {
      +      this._saveError = null;
      +      next(err);
      +    } else {
      +      next();
      +    }
      +  }).pre('save', function validation (next) {
      +    return this.validate(next);
      +  });
      +
      +  // add user defined queues
      +  this._doQueue();
      +};

      Document#_error(err)

      Registers an error

      show code
      Document.prototype._error = function (err) {
      +  this._saveError = err;
      +  return this;
      +};

      Parameters:


      Document#_doQueue()

      Executes methods queued from the Schema definition

      show code
      Document.prototype._doQueue = function () {
      +  var q = this.schema && this.schema.callQueue;
      +  if (q) {
      +    for (var i = 0, l = q.length; i < l; i++) {
      +      this[q[i][0]].apply(this, q[i][1]);
      +    }
      +  }
      +  return this;
      +};

      Document#toObject([options])

      Converts this document into a plain javascript object

      show code
      Document.prototype.toObject = function (options) {
      +  // When internally saving this document we always pass options,
      +  // bypassing the custom schema options.
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toObject
      +      ? clone(this.schema.options.toObject)
      +      : {};
      +  }
      +
      +  ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
      +
      +  var ret = clone(this._doc, options);
      +
      +  if (options.virtuals || options.getters && false !== options.virtuals) {
      +    applyGetters(this, ret, 'virtuals', options);
      +  }
      +
      +  if (options.getters) {
      +    applyGetters(this, ret, 'paths', options);
      +  }
      +
      +  if (true === options.transform) {
      +    var opts = options.json
      +      ? this.schema.options.toJSON
      +      : this.schema.options.toObject;
      +    if (opts) {
      +      options.transform = opts.transform;
      +    }
      +  }
      +
      +  if ('function' == typeof options.transform) {
      +    var xformed = options.transform(this, ret, options);
      +    if ('undefined' != typeof xformed) ret = xformed;
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Options:

      + +
        +
      • getters apply all getters (path and virtual getters)
      • +
      • virtuals apply virtual getters (can override getters option)
      • +
      • minimize remove empty objects (defaults to true)
      • +
      • transform a transform function to apply to the resulting document before returning
      • +
      + +

      Getters/Virtuals

      + +

      Example of only applying path getters

      + +
      doc.toObject({ getters: true, virtuals: false })
      + +

      Example of only applying virtual getters

      + +
      doc.toObject({ virtuals: true })
      + +

      Example of applying both path and virtual getters

      + +
      doc.toObject({ getters: true })
      + +

      To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

      + +
      schema.set('toObject', { virtuals: true })
      + +

      Transform

      + +

      We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

      + +

      Transform functions receive three arguments

      + +
      function (doc, ret, options) {}
      + +
        +
      • doc The mongoose document which is being converted
      • +
      • ret The plain object representation which has been converted
      • +
      • options The options in use (either schema options or the options passed inline)
      • +
      + +

      Example

      + +
      // specify the transform schema option
      +schema.options.toObject.transform = function (doc, ret, options) {
      +  // remove the _id of every document before returning the result
      +  delete ret._id;
      +}
      +
      +// without the transformation in the schema
      +doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
      +
      +// with the transformation
      +doc.toObject(); // { name: 'Wreck-it Ralph' }
      + +

      With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

      + +
      schema.options.toObject.transform = function (doc, ret, options) {
      +  return { movie: ret.name }
      +}
      +
      +// without the transformation in the schema
      +doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
      +
      +// with the transformation
      +doc.toObject(); // { movie: 'Wreck-it Ralph' }
      + +

      Note: if a transform function returns undefined, the return value will be ignored.

      + +

      Transformations may also be applied inline, overridding any transform set in the options:

      + +
      function xform (doc, ret, options) {
      +  return { inline: ret.name, custom: true }
      +}
      +
      +// pass the transform as an inline option
      +doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }
      + +

      Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

      + +
      schema.options.toObject.hide = '_id';
      +schema.options.toObject.transform = function (doc, ret, options) {
      +  if (options.hide) {
      +    options.hide.split(' ').forEach(function (prop) {
      +      delete ret[prop];
      +    });
      +  }
      +}
      +
      +var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });
      +doc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }
      +doc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }
      +doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }
      + +

      Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

      + +
      if ('function' == typeof doc.ownerDocument) {
      +  // working with a sub doc
      +}
      + +

      Transforms, like all of these options, are also available for toJSON.

      + +

      See schema options for some more details.


      Document#toJSON(options)

      The return value of this method is used in calls to JSON.stringify(doc).

      show code
      Document.prototype.toJSON = function (options) {
      +  // check for object type since an array of documents
      +  // being stringified passes array indexes instead
      +  // of options objects. JSON.stringify([doc, doc])
      +  if (!(options && 'Object' == options.constructor.name)) {
      +    options = this.schema.options.toJSON
      +      ? clone(this.schema.options.toJSON)
      +      : {};
      +  }
      +  options.json = true;
      +  return this.toObject(options);
      +};

      Parameters:

      • options <Object> same options as [Document#toObject](#document_Document-toObject)

      Returns:

      This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

      + +
      schema.set('toJSON', { virtuals: true })
      + +

      See schema options for details.


      Document#inspect()

      Helper for console.log

      show code
      Document.prototype.inspect = function (options) {
      +  var opts = options && 'Object' == options.constructor.name ? options :
      +      this.schema.options.toObject ? clone(this.schema.options.toObject) :
      +      {};
      +  opts.minimize = false;
      +  return inspect(this.toObject(opts));
      +};

      Document#toString()

      Helper for console.log


      Document#equals(doc)

      Returns true if the Document stores the same data as doc.

      show code
      Document.prototype.equals = function (doc) {
      +  var tid = this.get('_id');
      +  var docid = doc.get('_id');
      +  return tid.equals
      +    ? tid.equals(docid)
      +    : tid === docid;
      +};

      Parameters:

      Returns:

      Documents are considered equal when they have matching _ids.


      Document#errors

      Hash containing current validation errors.


      Document#id

      The string version of this documents _id.

      + +

      Note:

      + +

      This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

      + +
      new Schema({ name: String }, { id: false });

      Document#isNew

      Boolean flag specifying if the document is new.


      Document#schema

      The documents schema.


    • drivers/node-mongodb-native/collection.js

      NativeCollection()

      A node-mongodb-native collection implementation.

      show code
      function NativeCollection () {
      +  this.collection = null;
      +  MongooseCollection.apply(this, arguments);
      +}

      Inherits:

      All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.


      NativeCollection#onOpen()

      Called when the connection opens.

      show code
      NativeCollection.prototype.onOpen = function () {
      +  var self = this;
      +
      +  if (this.collection) {
      +    return MongooseCollection.prototype.onOpen.call(self);
      +  }
      +
      +  if (!self.opts.size) {
      +    // non-capped
      +    return self.conn.db.collection(self.name, callback);
      +  }
      +
      +  // capped
      +  return self.conn.db.collection(self.name, function (err, c) {
      +    if (err) return callback(err);
      +
      +    // discover if this collection exists and if it is capped
      +    c.options(function (err, exists) {
      +      if (err) return callback(err);
      +
      +      if (exists) {
      +        if (exists.capped) {
      +          callback(null, c);
      +        } else {
      +          var msg = 'A non-capped collection exists with this name.
      +
      +'
      +                  + ' To use this collection as a capped collection, please '
      +                  + 'first convert it.
      +'
      +                  + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
      +          err = new Error(msg);
      +          callback(err);
      +        }
      +      } else {
      +        // create
      +        var opts = utils.clone(self.opts);
      +        opts.capped = true;
      +        self.conn.db.createCollection(self.name, opts, callback);
      +      }
      +    });
      +  });
      +
      +  function callback (err, collection) {
      +    if (err) {
      +      // likely a strict mode error
      +      self.conn.emit('error', err);
      +    } else {
      +      self.collection = collection;
      +      MongooseCollection.prototype.onOpen.call(self);
      +    }
      +  };
      +};

      NativeCollection#onClose()

      Called when the connection closes

      show code
      NativeCollection.prototype.onClose = function () {
      +  MongooseCollection.prototype.onClose.call(this);
      +};

      NativeCollection#getIndexes(callback)

      Retreives information about this collections indexes.

      Parameters:


    • drivers/node-mongodb-native/connection.js

      NativeConnection()

      A node-mongodb-native connection implementation.

      show code
      function NativeConnection() {
      +  MongooseConnection.apply(this, arguments);
      +  this._listening = false;
      +};

      Inherits:


      NativeConnection#doOpen(fn)

      Opens the connection to MongoDB.

      show code
      NativeConnection.prototype.doOpen = function (fn) {
      +  if (this.db) {
      +    mute(this);
      +  }
      +
      +  var server = new mongo.Server(this.host, this.port, this.options.server);
      +  this.db = new mongo.Db(this.name, server, this.options.db);
      +
      +  var self = this;
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:


      NativeConnection#doOpenSet(fn)

      Opens a connection to a MongoDB ReplicaSet.

      show code
      NativeConnection.prototype.doOpenSet = function (fn) {
      +  if (this.db) {
      +    mute(this);
      +  }
      +
      +  var servers = []
      +    , self = this;
      +
      +  this.hosts.forEach(function (server) {
      +    var host = server.host || server.ipc;
      +    var port = server.port || 27017;
      +    servers.push(new mongo.Server(host, port, self.options.server));
      +  })
      +
      +  var server = new ReplSetServers(servers, this.options.replset);
      +  this.db = new mongo.Db(this.name, server, this.options.db);
      +
      +  this.db.on('fullsetup', function () {
      +    self.emit('fullsetup')
      +  });
      +
      +  this.db.open(function (err) {
      +    if (err) return fn(err);
      +    fn();
      +    listen(self);
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:

      See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.


      NativeConnection#doClose(fn)

      Closes the connection

      show code
      NativeConnection.prototype.doClose = function (fn) {
      +  this.db.close();
      +  if (fn) fn();
      +  return this;
      +}

      Parameters:

      Returns:


      NativeConnection#parseOptions(passed, [connStrOptions])

      Prepares default connection options for the node-mongodb-native driver.

      show code
      NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {
      +  var o = passed || {};
      +  o.db || (o.db = {});
      +  o.auth || (o.auth = {});
      +  o.server || (o.server = {});
      +  o.replset || (o.replset = {});
      +  o.server.socketOptions || (o.server.socketOptions = {});
      +  o.replset.socketOptions || (o.replset.socketOptions = {});
      +
      +  var opts = connStrOpts || {};
      +  Object.keys(opts).forEach(function (name) {
      +    switch (name) {
      +      case 'poolSize':
      +        if ('undefined' == typeof o.server.poolSize) {
      +          o.server.poolSize = o.replset.poolSize = opts[name];
      +        }
      +        break;
      +      case 'slaveOk':
      +        if ('undefined' == typeof o.server.slave_ok) {
      +          o.server.slave_ok = opts[name];
      +        }
      +        break;
      +      case 'autoReconnect':
      +        if ('undefined' == typeof o.server.auto_reconnect) {
      +          o.server.auto_reconnect = opts[name];
      +        }
      +        break;
      +      case 'ssl':
      +      case 'socketTimeoutMS':
      +      case 'connectTimeoutMS':
      +        if ('undefined' == typeof o.server.socketOptions[name]) {
      +          o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];
      +        }
      +        break;
      +      case 'authdb':
      +        if ('undefined' == typeof o.auth.authdb) {
      +          o.auth.authdb = opts[name];
      +        }
      +        break;
      +      case 'authSource':
      +        if ('undefined' == typeof o.auth.authSource) {
      +          o.auth.authSource = opts[name];
      +        }
      +        break;
      +      case 'retries':
      +      case 'reconnectWait':
      +      case 'rs_name':
      +        if ('undefined' == typeof o.replset[name]) {
      +          o.replset[name] = opts[name];
      +        }
      +        break;
      +      case 'replicaSet':
      +        if ('undefined' == typeof o.replset.rs_name) {
      +          o.replset.rs_name = opts[name];
      +        }
      +        break;
      +      case 'readSecondary':
      +        if ('undefined' == typeof o.replset.read_secondary) {
      +          o.replset.read_secondary = opts[name];
      +        }
      +        break;
      +      case 'nativeParser':
      +        if ('undefined' == typeof o.db.native_parser) {
      +          o.db.native_parser = opts[name];
      +        }
      +        break;
      +      case 'w':
      +      case 'safe':
      +      case 'fsync':
      +      case 'journal':
      +      case 'wtimeoutMS':
      +        if ('undefined' == typeof o.db[name]) {
      +          o.db[name] = opts[name];
      +        }
      +        break;
      +      case 'readPreference':
      +        if ('undefined' == typeof o.db.read_preference) {
      +          o.db.read_preference = opts[name];
      +        }
      +        break;
      +      case 'readPreferenceTags':
      +        if ('undefined' == typeof o.db.read_preference_tags) {
      +          o.db.read_preference_tags = opts[name];
      +        }
      +        break;
      +    }
      +  })
      +
      +  if (!('auto_reconnect' in o.server)) {
      +    o.server.auto_reconnect = true;
      +  }
      +
      +  if (!o.db.read_preference) {
      +    // read from primaries by default
      +    o.db.read_preference = 'primary';
      +  }
      +
      +  // mongoose creates its own ObjectIds
      +  o.db.forceServerObjectId = false;
      +
      +  // default safe using new nomenclature
      +  if (!('journal' in o.db || 'j' in o.db ||
      +        'fsync' in o.db || 'safe' in o.db || 'w' in o.db)) {
      +    o.db.w = 1;
      +  }
      +
      +  validate(o);
      +  return o;
      +}

      Parameters:

      • passed <Object> options that were passed directly during connection
      • [connStrOptions] <Object> options that were passed in the connection string

      NOTE: passed options take precedence over connection string options.


    • error.js

      MongooseError()

      Mongoose error

      show code
      function MongooseError (msg) {
      +  Error.call(this);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.message = msg;
      +  this.name = 'MongooseError';
      +};

      Inherits:


    • errors/cast.js

      CastError(type, value)

      Casting Error constructor.

      show code
      function CastError (type, value, path) {
      +  MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '" at path "' + path + '"');
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'CastError';
      +  this.type = type;
      +  this.value = value;
      +  this.path = path;
      +};

      Parameters:

      Inherits:


    • errors/document.js

      DocumentError(msg)

      Document Error

      show code
      function DocumentError (msg) {
      +  MongooseError.call(this, msg);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'DocumentError';
      +};

      Parameters:

      Inherits:


    • errors/validation.js

      ValidationError(instance)

      Document Validation Error

      show code
      function ValidationError (instance) {
      +  MongooseError.call(this, "Validation failed");
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidationError';
      +  this.errors = instance.errors = {};
      +};

      Parameters:

      Inherits:


      ValidationError#toString()

      Console.log helper

      show code
      ValidationError.prototype.toString = function () {
      +  return this.name + ': ' + Object.keys(this.errors).map(function (key) {
      +    return String(this.errors[key]);
      +  }, this).join(', ');
      +};

    • errors/validator.js

      ValidatorError(path, msg)

      Schema validator error

      show code
      function ValidatorError (path, type) {
      +  var msg = type
      +    ? '"' + type + '" '
      +    : '';
      +  MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'ValidatorError';
      +  this.path = path;
      +  this.type = type;
      +};

      Parameters:

      Inherits:


    • errors/version.js

      VersionError()

      Version Error constructor.

      show code
      function VersionError () {
      +  MongooseError.call(this, 'No matching document found.');
      +  Error.captureStackTrace(this, arguments.callee);
      +  this.name = 'VersionError';
      +};

      Inherits:


    • model.js

      Model(doc)

      Model constructor

      show code
      function Model (doc, fields, skipId) {
      +  Document.call(this, doc, fields, skipId);
      +};

      Parameters:

      • doc <Object> values to with which to create the document

      Inherits:

      Events:

      • error: If listening to this Model event, it is emitted when a document was saved without passing a callback and an error occurred. If not listening, the event bubbles to the connection used to create this Model.

      • index: Emitted after Model#ensureIndexes completes. If an error occurred it is passed with the event.


      Model#_getPopulationKeys(query)

      Returns what paths can be populated

      show code
      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
      +  if (!(query && query.options.populate)) return;
      +
      +  var names = Object.keys(query.options.populate)
      +    , n = names.length
      +    , name
      +    , paths = {}
      +    , hasKeys
      +    , schema
      +
      +  while (n--) {
      +    name = names[n];
      +    schema = this.schema.path(name);
      +    hasKeys = true;
      +
      +    if (!schema) {
      +      // if the path is not recognized, it's potentially embedded docs
      +      // walk path atoms from right to left to find a matching path
      +      var pieces = name.split('.')
      +        , i = pieces.length;
      +
      +      while (i--) {
      +        var path = pieces.slice(0, i).join('.')
      +          , pathSchema = this.schema.path(path);
      +
      +        // loop until we find an array schema
      +        if (pathSchema && pathSchema.caster) {
      +          if (!paths[path]) {
      +            paths[path] = { sub: {} };
      +          }
      +
      +          paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
      +          hasKeys || (hasKeys = true);
      +          break;
      +        }
      +      }
      +    } else {
      +      paths[name] = query.options.populate[name];
      +      hasKeys || (hasKeys = true);
      +    }
      +  }
      +
      +  return hasKeys && paths;
      +};

      Parameters:

      Returns:


      Model#_populate(schema, oid, query, fn)

      Populates an object

      show code
      Model.prototype._populate = function populate (schema, oid, query, fn) {
      +  if (!Array.isArray(oid)) {
      +    var conditions = query.conditions || {};
      +    conditions._id = oid;
      +
      +    return this
      +    .db.model(query.model || schema.options.ref)
      +    .findOne(conditions, query.fields, query.options, fn);
      +  }
      +
      +  if (!oid.length) {
      +    return fn(null, oid);
      +  }
      +
      +  var model = this.db.model(query.model || schema.caster.options.ref)
      +    , conditions = query && query.conditions || {};
      +
      +  conditions._id || (conditions._id = { $in: oid });
      +
      +  model.find(conditions, query.fields, query.options, function (err, docs) {
      +    if (err) return fn(err);
      +
      +    // user specified sort order?
      +    if (query.options && query.options.sort) {
      +      return fn(null, docs);
      +    }
      +
      +    // put back in original id order (using a hash reduces complexity from n*n to 2n)
      +    var docHash = {};
      +    docs.forEach(function (doc) {
      +      docHash[doc._id] = doc;
      +    });
      +
      +    var arr = [];
      +    oid.forEach(function (id) {
      +      if (id in docHash) arr.push(docHash[id]);
      +    });
      +
      +    fn(null, arr);
      +  });
      +};

      Parameters:

      • schema <SchemaType> type for the oid
      • oid <Object> object id or array of object ids
      • query <Object> object specifying query conditions, fields, and options
      • fn <Function>

      Model#init(doc, query, fn)

      Performs auto-population of relations.

      show code
      Model.prototype.init = function init (doc, query, fn) {
      +  if ('function' == typeof query) {
      +    fn = query;
      +    query = null;
      +  }
      +
      +  var populate = this._getPopulationKeys(query);
      +
      +  if (!populate) {
      +    return Document.prototype.init.call(this, doc, fn);
      +  }
      +
      +  // population from other models is necessary
      +  var self = this;
      +
      +  init(doc, '', function (err) {
      +    if (err) return fn(err);
      +    Document.prototype.init.call(self, doc, fn);
      +  });
      +
      +  return this;
      +
      +  function init (obj, prefix, fn) {
      +    prefix = prefix || '';
      +
      +    var keys = Object.keys(obj)
      +      , len = keys.length;
      +
      +    return next();
      +
      +    function next () {
      +      if (--len < 0) return fn();
      +
      +      var i = keys[len]
      +        , path = prefix + i
      +        , schema = self.schema.path(path)
      +        , total = 0
      +        , inline = false
      +        , poppath
      +
      +      if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
      +        // assume nested object
      +        return init(obj[i], path + '.', next);
      +      }
      +
      +      if (!(obj[i] && schema && populate[path])) return next();
      +
      +      // this query object is re-used and passed around. we clone
      +      // it to prevent query condition contamination between
      +      // one populate call to the next.
      +      poppath = utils.clone(populate[path]);
      +
      +      if (poppath.sub) {
      +        obj[i].forEach(function (subobj) {
      +          inline = true;
      +
      +          var pkeys = Object.keys(poppath.sub)
      +            , pi = pkeys.length
      +            , key
      +
      +          while (pi--) {
      +            key = pkeys[pi];
      +
      +            if (subobj[key]) (function (key) {
      +              total++;
      +              self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
      +              function done (err, doc) {
      +                if (err) return error(err);
      +                subobj[key] = doc;
      +                if (--total < 1 && !inline) {
      +                  next();
      +                }
      +              }
      +            })(key);
      +          }
      +        });
      +
      +        inline = false;
      +
      +        if (0 === total) return next();
      +
      +      } else {
      +        self._populate(schema, obj[i], poppath, function (err, doc) {
      +          if (err) return error(err);
      +          obj[i] = doc;
      +          next();
      +        });
      +      }
      +    };
      +  };
      +
      +  function error (err) {
      +    if (error.err) return;
      +    fn(error.err = err);
      +  }
      +};

      Parameters:

      • doc <Object> document returned by mongo
      • query <Query> query that originated the initialization
      • fn <Function>

      Model#save([fn])

      Saves this document.

      show code
      Model.prototype.save = function save (fn) {
      +  var promise = new Promise(fn)
      +    , complete = handleSave(promise, this)
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  if (this.isNew) {
      +    // send entire doc
      +    var obj = this.toObject({ depopulate: 1 });
      +    this._version(true, obj);
      +    this.collection.insert(obj, options, complete);
      +    this._reset();
      +    this.isNew = false;
      +    this.emit('isNew', false);
      +    // Make it possible to retry the insert
      +    this._inserting = true;
      +
      +  } else {
      +    // Make sure we don't treat it as a new object on error,
      +    // since it already exists
      +    this._inserting = false;
      +
      +    var delta = this._delta();
      +    if (delta) {
      +      var where = this._where(delta[0]);
      +      this.collection.update(where, delta[1], options, complete);
      +    } else {
      +      process.nextTick(function () {
      +        complete(null);
      +      })
      +    }
      +
      +    this._reset();
      +    this.emit('isNew', false);
      +  }
      +};

      Parameters:

      Example:

      + +
      product.sold = Date.now();
      +product.save(function (err, product) {
      +  if (err) ..
      +})
      + +

      The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      + +
      var db = mongoose.createConnection(..);
      +var schema = new Schema(..);
      +var Product = db.model('Product', schema);
      +
      +db.on('error', handleError);
      + +

      However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

      + +
      Product.on('error', handleError);

      Model#_delta()

      Produces a special query document of the modified properties used in updates.

      show code
      Model.prototype._delta = function _delta () {
      +  var dirty = this._dirty();
      +  if (!dirty.length) return;
      +
      +  var self = this
      +    , where = {}
      +    , delta = {}
      +    , len = dirty.length
      +    , d = 0
      +    , val
      +    , obj
      +
      +  for (; d < len; ++d) {
      +    var data = dirty[d]
      +    var value = data.value
      +    var schema = data.schema
      +
      +    if (undefined === value) {
      +      operand(self, where, delta, data, 1, '$unset');
      +
      +    } else if (null === value) {
      +      operand(self, where, delta, data, null);
      +
      +    } else if (value._path && value._atomics) {
      +      // arrays and other custom types (support plugins etc)
      +      handleAtomics(self, where, delta, data, value);
      +
      +    } else if (value._path && Buffer.isBuffer(value)) {
      +      // MongooseBuffer
      +      value = value.toObject();
      +      operand(self, where, delta, data, value);
      +
      +    } else {
      +      value = utils.clone(value);
      +      operand(self, where, delta, data, value);
      +    }
      +  }
      +
      +  if (this.__version) {
      +    this._version(where, delta);
      +  }
      +
      +  return [where, delta];
      +}

      Model#_version()

      Appends versioning to the where and update clauses.

      show code
      Model.prototype._version = function _version (where, delta) {
      +  var key = this.schema.options.versionKey;
      +
      +  if (true === where) {
      +    // this is an insert
      +    if (key) this.setValue(key, delta[key] = 0);
      +    return;
      +  }
      +
      +  // updates
      +
      +  // only apply versioning if our versionKey was selected. else
      +  // there is no way to select the correct version. we could fail
      +  // fast here and force them to include the versionKey but
      +  // thats a bit intrusive. can we do this automatically?
      +  // TODO fail fast option?
      +  if (!this.isSelected(key)) {
      +    return;
      +  }
      +
      +  // $push $addToSet don't need the where clause set
      +  if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
      +    where[key] = this.getValue(key);
      +  }
      +
      +  if (VERSION_INC === (VERSION_INC & this.__version)) {
      +    delta.$inc || (delta.$inc = {});
      +    delta.$inc[key] = 1;
      +  }
      +}

      Model#increment()

      Signal that we desire an increment of this documents version.

      show code
      Model.prototype.increment = function increment () {
      +  this.__version = VERSION_ALL;
      +  return this;
      +}

      Model#_where()

      Returns a query object which applies shardkeys if they exist.

      show code
      Model.prototype._where = function _where (where) {
      +  where || (where = {});
      +
      +  var paths
      +    , len
      +
      +  if (this._shardval) {
      +    paths = Object.keys(this._shardval)
      +    len = paths.length
      +
      +    for (var i = 0; i < len; ++i) {
      +      where[paths[i]] = this._shardval[paths[i]];
      +    }
      +  }
      +
      +  where._id = this._doc._id;
      +  return where;
      +}

      Model#remove([fn])

      Removes this document from the db.

      show code
      Model.prototype.remove = function remove (fn) {
      +  if (this._removing) {
      +    this._removing.addBack(fn);
      +    return this;
      +  }
      +
      +  var promise = this._removing = new Promise(fn)
      +    , where = this._where()
      +    , self = this
      +    , options = {}
      +
      +  if (this.schema.options.safe) {
      +    options.safe = this.schema.options.safe;
      +  }
      +
      +  this.collection.remove(where, options, tick(function (err) {
      +    if (err) {
      +      promise.error(err);
      +      promise = self = self._removing = where = options = null;
      +      return;
      +    }
      +    self.emit('remove', self);
      +    promise.complete();
      +    promise = self = where = options = null;
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Example:

      + +
      product.remove(function (err, product) {
      +  if (err) return handleError(err);
      +  Product.findById(product._id, function (err, product) {
      +    console.log(product) // null
      +  })
      +})

      Model#_registerHooks()

      Register hooks override

      show code
      Model.prototype._registerHooks = function registerHooks () {
      +  Document.prototype._registerHooks.call(this);
      +};

      Model#model(name)

      Returns another Model instance.

      show code
      Model.prototype.model = function model (name) {
      +  return this.db.model(name);
      +};
      +
      +// Model (class) features

      Parameters:

      Example:

      + +
      var doc = new Tank;
      +doc.model('User').findById(id, callback);

      Model#$where(argument)

      Creates a Query and specifies a $where condition.

      Parameters:

      • argument <String, Function> is a javascript string or anonymous function

      Returns:

      Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      + +
      Blog.$where('this.comments.length &gt; 5').exec(function (err, docs) {});

      Model.init()

      Called when the model compiles.

      show code
      Model.init = function init () {
      +  if (this.schema.options.autoIndex) {
      +    this.ensureIndexes();
      +  }
      +
      +  this.schema.emit('init', this);
      +};

      Model.ensureIndexes([cb])

      Sends ensureIndex commands to mongo for each index declared in the schema.

      show code
      Model.ensureIndexes = function ensureIndexes (cb) {
      +  var indexes = this.schema.indexes();
      +  if (!indexes.length) {
      +    return cb && process.nextTick(cb);
      +  }
      +
      +  // Indexes are created one-by-one to support how MongoDB < 2.4 deals
      +  // with background indexes.
      +
      +  var self = this
      +    , safe = self.schema.options.safe
      +
      +  function done (err) {
      +    self.emit('index', err);
      +    cb && cb(err);
      +  }
      +
      +  function create () {
      +    var index = indexes.shift();
      +    if (!index) return done();
      +
      +    var options = index[1];
      +    options.safe = safe;
      +    self.collection.ensureIndex(index[0], options, tick(function (err) {
      +      if (err) return done(err);
      +      create();
      +    }));
      +  }
      +
      +  create();
      +}

      Parameters:

      Example:

      + +
      Event.ensureIndexes(function (err) {
      +  if (err) return handleError(err);
      +});
      + +

      After completion, an index event is emitted on this Model passing an error if one occurred.

      + +

      Example:

      + +
      var eventSchema = new Schema({ thing: { type: 'string', unique: true }})
      +var Event = mongoose.model('Event', eventSchema);
      +
      +Event.on('index', function (err) {
      +  if (err) console.error(err); // error occurred during index creation
      +})
      + +

      NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

      + +

      The ensureIndex commands are not sent in parallel. This is to avoid the MongoError: cannot add index with a background operation in progress error. See this ticket for more information.


      Model.remove(conditions, [callback])

      Removes documents from the collection.

      show code
      Model.remove = function remove (conditions, callback) {
      +  if ('function' === typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +  }
      +
      +  var query = new Query(conditions).bind(this, 'remove');
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.remove(callback);
      +};

      Parameters:

      Returns:

      Example:

      + +
      Comment.remove({ title: 'baby born from alien father' }, function (err) {
      +
      +});
      + +

      Note:

      + +

      To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      var query = Comment.remove({ _id: id });
      +query.exec();
      + +

      Note:

      + +

      This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, no middleware (hooks) are executed.


      Model.find(conditions, [fields], [options], [callback])

      Finds documents

      show code
      Model.find = function find (conditions, fields, options, callback) {
      +  if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options);
      +  query.bind(this, 'find');
      +  query.select(fields);
      +
      +  if ('undefined' === typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.find(callback);
      +};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      + +

      Examples:

      + +
      // named john and at least 18
      +MyModel.find({ name: 'john', age: { $gte: 18 }});
      +
      +// executes immediately, passing results to callback
      +MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});
      +
      +// name LIKE john and only selecting the "name" and "friends" fields, executing immediately
      +MyModel.find({ name: /john/i }, 'name friends', function (err, docs) { })
      +
      +// passing options
      +MyModel.find({ name: /john/i }, null, { skip: 10 })
      +
      +// passing options and executing immediately
      +MyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {});
      +
      +// executing a query explicitly
      +var query = MyModel.find({ name: /john/i }, null, { skip: 10 })
      +query.exec(function (err, docs) {});
      +
      +// using the promise returned from executing a query
      +var query = MyModel.find({ name: /john/i }, null, { skip: 10 });
      +var promise = query.exec();
      +promise.addBack(function (err, docs) {});

      Model._applyNamedScope(query)

      Merges the current named scope query into query.

      show code
      Model._applyNamedScope = function _applyNamedScope (query) {
      +  var cQuery = this._cumulativeQuery;
      +
      +  if (cQuery) {
      +    merge(query._conditions, cQuery._conditions);
      +    if (query._fields && cQuery._fields)
      +      merge(query._fields, cQuery._fields);
      +    if (query.options && cQuery.options)
      +      merge(query.options, cQuery.options);
      +    delete this._cumulativeQuery;
      +  }
      +
      +  return query;
      +}

      Parameters:

      Returns:


      Model.findById(id, [fields], [options], [callback])

      Finds a single document by id.

      show code
      Model.findById = function findById (id, fields, options, callback) {
      +  return this.findOne({ _id: id }, fields, options, callback);
      +};

      Parameters:

      Returns:

      The id is cast based on the Schema before sending the command.

      + +

      Example:

      + +
      // find adventure by id and execute immediately
      +Adventure.findById(id, function (err, adventure) {});
      +
      +// same as above
      +Adventure.findById(id).exec(callback);
      +
      +// select only the adventures name and length
      +Adventure.findById(id, 'name length', function (err, adventure) {});
      +
      +// same as above
      +Adventure.findById(id, 'name length').exec(callback);
      +
      +// include all properties except for `length`
      +Adventure.findById(id, '-length').exec(function (err, adventure) {});
      +
      +// passing options (in this case return the raw js objects, not mongoose documents by passing `lean`
      +Adventure.findById(id, 'name', { lean: true }, function (err, doc) {});
      +
      +// same as above
      +Adventure.findById(id, 'name').lean().exec(function (err, doc) {});

      Model.findOne(conditions, [fields], [options], [callback])

      Finds one document.

      show code
      Model.findOne = function findOne (conditions, fields, options, callback) {
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  } else if ('function' == typeof fields) {
      +    callback = fields;
      +    fields = null;
      +    options = null;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = {};
      +    fields = null;
      +    options = null;
      +  }
      +
      +  var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOne(callback);
      +};

      Parameters:

      Returns:

      The conditions are cast to their respective SchemaTypes before the command is sent.

      + +

      Example:

      + +
      // find one iphone adventures - iphone adventures??
      +Adventure.findOne({ type: 'iphone' }, function (err, adventure) {});
      +
      +// same as above
      +Adventure.findOne({ type: 'iphone' }).exec(function (err, adventure) {});
      +
      +// select only the adventures name
      +Adventure.findOne({ type: 'iphone' }, 'name', function (err, adventure) {});
      +
      +// same as above
      +Adventure.findOne({ type: 'iphone' }, 'name').exec(function (err, adventure) {});
      +
      +// specify options, in this case lean
      +Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }, callback);
      +
      +// same as above
      +Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }).exec(callback);
      +
      +// chaining findOne queries (same as above)
      +Adventure.findOne({ type: 'iphone' }).select('name').lean().exec(callback);

      Model.count(conditions, [callback])

      Counts number of matching documents in a database collection.

      show code
      Model.count = function count (conditions, callback) {
      +  if ('function' === typeof conditions)
      +    callback = conditions, conditions = {};
      +
      +  var query = new Query(conditions).bind(this, 'count');
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.count(callback);
      +};

      Parameters:

      Returns:

      Example:

      + +
      Adventure.count({ type: 'jungle' }, function (err, count) {
      +  if (err) ..
      +  console.log('there are %d jungle adventures', count);
      +});

      Model.distinct(field, [conditions], [callback])

      Executes a DISTINCT command

      show code
      Model.distinct = function distinct (field, conditions, callback) {
      +  var query = new Query(conditions).bind(this, 'distinct');
      +  if ('undefined' == typeof callback) {
      +    query._distinctArg = field;
      +    return query;
      +  }
      +
      +  this._applyNamedScope(query);
      +  return query.distinct(field, callback);
      +};

      Parameters:

      Returns:


      Model.where(path, [val])

      Creates a Query, applies the passed conditions, and returns the Query.

      show code
      Model.where = function where (path, val) {
      +  var q = new Query().bind(this, 'find');
      +  return q.where.apply(q, arguments);
      +};

      Parameters:

      Returns:

      For example, instead of writing:

      + +
      User.find({age: {$gte: 21, $lte: 65}}, callback);
      + +

      we can instead write:

      + +
      User.where('age').gte(21).lte(65).exec(callback);
      + +

      Since the Query class also supports where you can continue chaining

      + +
      User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +... etc

      Model.findOneAndUpdate([conditions], [update], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Model.findOneAndUpdate = function (conditions, update, options, callback) {
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = null;
      +  }
      +  else if (1 === arguments.length) {
      +    if ('function' == typeof conditions) {
      +      var msg = 'Model.findOneAndUpdate(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate(update)
      +'
      +              + '  ' + this.modelName + '.findOneAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    update = conditions;
      +    conditions = undefined;
      +  }
      +
      +  var fields;
      +  if (options && options.fields) {
      +    fields = options.fields;
      +    options.fields = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndUpdate', update);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndUpdate(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndUpdate(conditions, update, options, callback) // executes
      +A.findOneAndUpdate(conditions, update, options)  // returns Query
      +A.findOneAndUpdate(conditions, update, callback) // executes
      +A.findOneAndUpdate(conditions, update)           // returns Query
      +A.findOneAndUpdate()                             // returns Query
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findByIdAndUpdate(id, [update], [options], [callback])

      Issues a mongodb findAndModify update command by a documents id.

      show code
      Model.findByIdAndUpdate = function (id, update, options, callback) {
      +  var args;
      +
      +  if (1 === arguments.length) {
      +    if ('function' == typeof id) {
      +      var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.
      +
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate(id)
      +'
      +                + '  ' + this.modelName + '.findByIdAndUpdate()
      +';
      +      throw new TypeError(msg)
      +    }
      +    return this.findOneAndUpdate({_id: id }, undefined);
      +  }
      +
      +  args = utils.args(arguments, 1);
      +  args.unshift({ _id: id });
      +  return this.findOneAndUpdate.apply(this, args);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndUpdate(id, update, options, callback) // executes
      +A.findByIdAndUpdate(id, update, options)  // returns Query
      +A.findByIdAndUpdate(id, update, callback) // executes
      +A.findByIdAndUpdate(id, update)           // returns Query
      +A.findByIdAndUpdate()                     // returns Query
      + +

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Note:

      + +

      All top level update keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

      + +

      Note:

      + +

      Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findById(id, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.findOneAndRemove(conditions, [options], [callback])

      Issue a mongodb findAndModify remove command.

      show code
      Model.findOneAndRemove = function (conditions, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof conditions) {
      +    var msg = 'Model.findOneAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove(conditions)
      +'
      +              + '  ' + this.modelName + '.findOneAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  }
      +
      +  var fields;
      +  if (options) {
      +    fields = options.select;
      +    options.select = undefined;
      +  }
      +
      +  var query = new Query(conditions);
      +  query.setOptions(options);
      +  query.select(fields);
      +  query.bind(this, 'findOneAndRemove');
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.findOneAndRemove(callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findOneAndRemove(conditions, options, callback) // executes
      +A.findOneAndRemove(conditions, options)  // return Query
      +A.findOneAndRemove(conditions, callback) // executes
      +A.findOneAndRemove(conditions) // returns Query
      +A.findOneAndRemove()           // returns Query

      Model.findByIdAndRemove(id, [options], [callback])

      Issue a mongodb findAndModify remove command by a documents id.

      show code
      Model.findByIdAndRemove = function (id, options, callback) {
      +  if (1 === arguments.length && 'function' == typeof id) {
      +    var msg = 'Model.findByIdAndRemove(): First argument must not be a function.
      +
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove(id)
      +'
      +              + '  ' + this.modelName + '.findByIdAndRemove()
      +';
      +    throw new TypeError(msg)
      +  }
      +
      +  return this.findOneAndRemove({ _id: id }, options, callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback.

      + +

      Executes immediately if callback is passed, else a Query object is returned.

      + +

      Options:

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      • select: sets the document fields to return
      • +
      + +

      Examples:

      + +
      A.findByIdAndRemove(id, options, callback) // executes
      +A.findByIdAndRemove(id, options)  // return Query
      +A.findByIdAndRemove(id, callback) // executes
      +A.findByIdAndRemove(id) // returns Query
      +A.findByIdAndRemove()           // returns Query

      Model.create(doc, fn)

      Shortcut for creating a new Document that is automatically saved to the db if valid.

      show code
      Model.create = function create (doc, fn) {
      +  if (1 === arguments.length) {
      +    return 'function' === typeof doc && doc(null);
      +  }
      +
      +  var self = this
      +    , docs = [null]
      +    , promise
      +    , count
      +    , args
      +
      +  if (Array.isArray(doc)) {
      +    args = doc;
      +  } else {
      +    args = utils.args(arguments, 0, arguments.length - 1);
      +    fn = arguments[arguments.length - 1];
      +  }
      +
      +  if (0 === args.length) return fn(null);
      +
      +  promise = new Promise(fn);
      +  count = args.length;
      +
      +  args.forEach(function (arg, i) {
      +    var doc = new self(arg);
      +    docs[i+1] = doc;
      +    doc.save(function (err) {
      +      if (err) return promise.error(err);
      +      --count || fn.apply(null, docs);
      +    });
      +  });
      +
      +  // TODO
      +  // utilize collection.insertAll for batch processing?
      +};

      Parameters:

      Example:

      + +
      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});
      +
      +var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      +Candy.create(array, function (err, jellybean, snickers) {
      +  if (err) // ...
      +});

      Model.update(conditions, update, [options], [callback])

      Updates documents in the database without returning them.

      show code
      Model.update = function update (conditions, doc, options, callback) {
      +  if (arguments.length < 4) {
      +    if ('function' === typeof options) {
      +      // Scenario: update(conditions, doc, callback)
      +      callback = options;
      +      options = null;
      +    } else if ('function' === typeof doc) {
      +      // Scenario: update(doc, callback);
      +      callback = doc;
      +      doc = conditions;
      +      conditions = {};
      +      options = null;
      +    }
      +  }
      +
      +  var query = new Query(conditions, options).bind(this, 'update', doc);
      +
      +  if ('undefined' == typeof callback)
      +    return query;
      +
      +  this._applyNamedScope(query);
      +  return query.update(doc, callback);
      +};

      Parameters:

      Returns:

      Examples:

      + +
      MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
      +MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
      +  if (err) return handleError(err);
      +  console.log('The number of updated documents was %d', numberAffected);
      +  console.log('The raw response from Mongo was ', raw);
      +});
      + +

      Valid options:

      + +
        +
      • safe (boolean) safe mode (defaults to value set in schema (true))
      • +
      • upsert (boolean) whether to create the doc if it doesn't match (false)
      • +
      • multi (boolean) whether multiple documents should be updated (false)
      • +
      + +

      All update values are cast to their appropriate SchemaTypes before being sent.

      + +

      The callback function receives (err, numberAffected, rawResponse).

      + +
        +
      • err is the error if any occurred
      • +
      • numberAffected is the count of updated documents Mongo reported
      • +
      • rawResponse is the full response from Mongo
      • +
      + +

      Note:

      + +

      All top level keys which are not atomic operation names are treated as set operations:

      + +

      Example:

      + +
      var query = { name: 'borne' };
      +Model.update(query, { name: 'jason borne' }, options, callback)
      +
      +// is sent as
      +Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
      + +

      This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

      + +

      Note:

      + +

      To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

      + +
      Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
      + +

      Note:

      + +

      Although values are casted to their appropriate types when using update, the following are not applied:

      + +
        +
      • defaults
      • +
      • setters
      • +
      • validators
      • +
      • middleware
      • +
      + +

      If you need those features, use the traditional approach of first retrieving the document.

      + +
      Model.findOne({ name: 'borne' }, function (err, doc) {
      +  if (err) ..
      +  doc.name = 'jason borne';
      +  doc.save(callback);
      +})

      Model.mapReduce(o, callback)

      Executes a mapReduce command.

      show code
      Model.mapReduce = function mapReduce (o, callback) {
      +  if ('function' != typeof callback) throw new Error('missing callback');
      +
      +  var self = this;
      +
      +  if (!Model.mapReduce.schema) {
      +    var opts = { noId: true, noVirtualId: true, strict: false }
      +    Model.mapReduce.schema = new Schema({}, opts);
      +  }
      +
      +  if (!o.out) o.out = { inline: 1 };
      +
      +  o.map = String(o.map);
      +  o.reduce = String(o.reduce);
      +
      +  if (o.query) {
      +    var q = new Query(o.query);
      +    q.cast(this);
      +    o.query = q._conditions;
      +    q = undefined;
      +  }
      +
      +  this.collection.mapReduce(null, null, o, function (err, ret, stats) {
      +    if (err) return callback(err);
      +
      +    if (ret.findOne && ret.mapReduce) {
      +      // returned a collection, convert to Model
      +      var model = Model.compile(
      +          '_mapreduce_' + ret.collectionName
      +        , Model.mapReduce.schema
      +        , ret.collectionName
      +        , self.db
      +        , self.base);
      +
      +      model._mapreduce = true;
      +
      +      return callback(err, model, stats);
      +    }
      +
      +    callback(err, ret, stats);
      +  });
      +}

      Parameters:

      • o <Object> an object specifying map-reduce options
      • callback <Function>

      o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +User.mapReduce(o, function (err, results) {
      +  console.log(results)
      +})
      + +

      Other options:

      + +
        +
      • query {Object} query filter object.
      • +
      • limit {Number} max number of documents
      • +
      • keeptemp {Boolean, default:false} keep temporary data
      • +
      • finalize {Function} finalize function
      • +
      • scope {Object} scope variables exposed to map/reduce/finalize during execution
      • +
      • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
      • +
      • verbose {Boolean, default:false} provide statistics on job execution time.
      • +
      • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
      • +
      + +

      * out options:

      + +
        +
      • {inline:1} the results are returned in an array
      • +
      • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
      • +
      • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
      • +
      • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
      • +
      + +

      If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

      + +

      Example:

      + +
      var o = {};
      +o.map = function () { emit(this.name, 1) }
      +o.reduce = function (k, vals) { return vals.length }
      +o.out = { replace: 'createdCollectionNameForResults' }
      +o.verbose = true;
      +User.mapReduce(o, function (err, model, stats) {
      +  console.log('map reduce took %d ms', stats.processtime)
      +  model.find().where('value').gt(10).exec(function (err, docs) {
      +    console.log(docs);
      +  });
      +})

      Model.aggregate(array, [options], callback)

      Executes an aggregate command on this models collection.

      show code
      Model.aggregate = function aggregate () {
      +  return this.collection.aggregate.apply(this.collection, arguments);
      +}

      Parameters:

      Example:

      + +
      // find the max age of all users
      +Users.aggregate(
      +    { $group: { _id: null, maxAge: { $max: '$age' }}}
      +  , { $project: { _id: 0, maxAge: 1 }}
      +  , function (err, res) {
      +  if (err) return handleError(err);
      +  console.log(res); // [ { maxAge: 98 } ]
      +});
      + +

      NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

      + +

      NOTE: this requires running MongoDB >= 2.1


      Model#base

      Base Mongoose instance the model uses.


      Model#schema

      Schema the model uses.


      Model#modelName

      The name of the model


      Model#collection

      Collection the model uses.


      Model#db

      Connection the model uses.


    • namedscope.js

      NamedScope#decorate(target, getters)

      Decorate

      show code
      NamedScope.prototype.decorate = function (target, getters) {
      +  var name = this.name
      +    , block = this.block
      +    , query = this.query;
      +  if (block) {
      +    if (block.length === 0) {
      +      Object.defineProperty(target, name, {
      +        get: getters.block0(block)
      +      });
      +    } else {
      +      target[name] = getters.blockN(block);
      +    }
      +  } else {
      +    Object.defineProperty(target, name, {
      +      get: getters.basic(query)
      +    });
      +  }
      +};
      +
      +NamedScope.prototype.compile = function (model) {
      +  var allScopes = this.scopesByName
      +    , scope;
      +  for (var k in allScopes) {
      +    scope = allScopes[k];
      +    scope.decorate(model, {
      +      block0: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.call(cquery);
      +          return this;
      +        };
      +      },
      +      blockN: function (block) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          block.apply(cquery, arguments);
      +          return this;
      +        };
      +      },
      +      basic: function (query) {
      +        return function () {
      +          var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
      +          cquery.find(query);
      +          return this;
      +        };
      +      }
      +    });
      +  }
      +};
      +
      +module.exports = NamedScope;

      Parameters:


    • promise.js

      Promise(back)

      Promise constructor.

      show code
      function Promise (back) {
      +  this.emitted = {};
      +  if ('function' == typeof back)
      +    this.addBack(back);
      +};

      Parameters:

      • back <Function> a callback+errback that accepts `fn(err, ...){}` as signature

      Events:

      • err: Emits when the promise resolves to an error.

      • complete: Emits when the promise resolves sucessfully.


      Promise#on(event, callback)

      Adds listener to the event.

      show code
      Promise.prototype.on = function (event, callback) {
      +  if (this.emitted[event])
      +    callback.apply(this, this.emitted[event]);
      +  else
      +    EventEmitter.prototype.on.call(this, event, callback);
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If event is either error or complete and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.


      Promise#emit()

      Keeps track of emitted events to run them on on.

      show code
      Promise.prototype.emit = function (event) {
      +  // ensures a promise can't be complete() or error() twice
      +  if (event == 'err' || event == 'complete'){
      +    if (this.emitted.err || this.emitted.complete) {
      +      return this;
      +    }
      +    this.emitted[event] = util.args(arguments, 1);
      +  }
      +
      +  return EventEmitter.prototype.emit.apply(this, arguments);
      +};

      Promise#complete()

      Shortcut for emitting the complete event.

      show code
      Promise.prototype.complete = function () {
      +  var args = util.args(arguments);
      +  return this.emit.apply(this, ['complete'].concat(args));
      +};

      Promise#error()

      Shortcut for emitting the err event.

      show code
      Promise.prototype.error = function (err) {
      +  if (!(err instanceof Error)) err = new Error(err);
      +  return this.emit('err', err);
      +};

      Returns:

      If err is not instanceof Error, it is cast to Error before rejecting.


      Promise#addCallback()

      Adds a listener to the complete (success) event.

      show code
      Promise.prototype.addCallback = function (fn) {
      +  return this.on('complete', fn);
      +};

      Returns:


      Promise#addErrback()

      Adds a listener to the err (rejected) event.

      show code
      Promise.prototype.addErrback = function (fn) {
      +  return this.on('err', fn);
      +};

      Returns:


      Promise#addBack(fn)

      Adds a single function as both a callback and errback.

      show code
      Promise.prototype.addBack = function (fn) {
      +  this.on('err', function(err){
      +    fn.call(this, err);
      +  });
      +
      +  this.on('complete', function(){
      +    var args = util.args(arguments);
      +    fn.apply(this, [null].concat(args));
      +  });
      +
      +  return this;
      +};

      Parameters:

      Returns:

      It will be executed with traditional node.js argument position:
      function (err, args...) {}


      Promise#resolve([err], [val])

      Resolves this promise to an error state if err is passed or success state when no err is passed.

      show code
      Promise.prototype.resolve = function (err, val) {
      +  if (err) return this.error(err);
      +  return this.complete(val);
      +};

      Parameters:

      • [err] <Error> error or null
      • [val] <Object> value to complete the promise with

      err will be cast to an Error if not already instanceof Error.


    • query.js

      Query(criteria, options)

      Query constructor used for building queries.

      show code
      function Query (criteria, options) {
      +  this.setOptions(options, true);
      +  this._conditions = {};
      +  this._updateArg = {};
      +  this._fields = undefined;
      +  if (criteria) this.find(criteria);
      +}

      Parameters:

      Example:

      + +
      var query = Model.find();
      +query.where('age').gte(21).exec(callback);

      Query#setOptions(options)

      Sets query options.

      show code
      Query.prototype.setOptions = function (options, overwrite) {
      +  // overwrite is internal use only
      +  if (overwrite) {
      +    options = this.options = options || {};
      +    this.safe = options.safe
      +
      +    // normalize population options
      +    var pop = this.options.populate;
      +    this.options.populate = {};
      +
      +    if (pop && Array.isArray(pop)) {
      +      for (var i = 0, l = pop.length; i < l; i++) {
      +        this.options.populate[pop[i]] = {};
      +      }
      +    }
      +
      +    return this;
      +  }
      +
      +  if (!(options && 'Object' == options.constructor.name))
      +    return this;
      +
      +  if ('safe' in options)
      +    this.safe = options.safe;
      +
      +  // set arbitrary options
      +  var methods = Object.keys(options)
      +    , i = methods.length
      +    , method
      +
      +  while (i--) {
      +    method = methods[i];
      +
      +    // use methods if exist (safer option manipulation)
      +    if ('function' == typeof this[method]) {
      +      var args = Array.isArray(options[method])
      +        ? options[method]
      +        : [options[method]];
      +      this[method].apply(this, args)
      +    } else {
      +      this.options[method] = options[method];
      +    }
      +  }
      +  return this;
      +}

      Parameters:

      Options:

      + + + +

      * denotes a query helper method is also available


      Query#bind(model, op, updateArg)

      Binds this query to a model.

      show code
      Query.prototype.bind = function bind (model, op, updateArg) {
      +  this.model = model;
      +  this.op = op;
      +
      +  if (model._mapreduce) this.options.lean = true;
      +
      +  if (op == 'update' || op == 'findOneAndUpdate') {
      +    merge(this._updateArg, updateArg || {});
      +  }
      +
      +  return this;
      +};

      Parameters:

      • model <Model> the model to which the query is bound
      • op <String> the operation to execute
      • updateArg <Object> used in update methods

      Returns:


      Query#exec([operation], [callback])

      Executes the query

      show code
      Query.prototype.exec = function exec (op, callback) {
      +  var promise = new Promise();
      +
      +  switch (typeof op) {
      +    case 'function':
      +      callback = op;
      +      op = null;
      +      break;
      +    case 'string':
      +      this.op = op;
      +      break;
      +  }
      +
      +  if (callback) promise.addBack(callback);
      +
      +  if (!this.op) {
      +    promise.complete();
      +    return promise;
      +  }
      +
      +  if ('update' == this.op) {
      +    this[this.op](this._updateArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  if ('distinct' == this.op) {
      +    this.distinct(this._distinctArg, promise.resolve.bind(promise));
      +    return promise;
      +  }
      +
      +  this[this.op](promise.resolve.bind(promise));
      +  return promise;
      +};

      Parameters:

      Returns:

      Examples

      + +
      query.exec();
      +query.exec(callback);
      +query.exec('update');
      +query.exec('find', callback);

      Query#find([criteria], [callback])

      Finds documents.

      show code
      Query.prototype.find = function (criteria, callback) {
      +  this.op = 'find';
      +  if ('function' === typeof criteria) {
      +    callback = criteria;
      +    criteria = {};
      +  } else if (criteria instanceof Query) {
      +    // TODO Merge options, too
      +    merge(this._conditions, criteria._conditions);
      +  } else if (criteria instanceof Document) {
      +    merge(this._conditions, criteria.toObject());
      +  } else if (criteria && 'Object' === criteria.constructor.name) {
      +    merge(this._conditions, criteria);
      +  }
      +  if (!callback) return this;
      +  return this.execFind(callback);
      +};

      Parameters:

      Returns:

      When no callback is passed, the query is not executed.

      + +

      Example

      + +
      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

      Query#cast(model, [obj])

      Casts this query to the schema of model

      show code
      Query.prototype.cast = function (model, obj) {
      +  obj || (obj= this._conditions);
      +
      +  var schema = model.schema
      +    , paths = Object.keys(obj)
      +    , i = paths.length
      +    , any$conditionals
      +    , schematype
      +    , nested
      +    , path
      +    , type
      +    , val;
      +
      +  while (i--) {
      +    path = paths[i];
      +    val = obj[path];
      +
      +    if ('$or' === path || '$nor' === path || '$and' === path) {
      +      var k = val.length
      +        , orComponentQuery;
      +
      +      while (k--) {
      +        orComponentQuery = new Query(val[k]);
      +        orComponentQuery.cast(model);
      +        val[k] = orComponentQuery._conditions;
      +      }
      +
      +    } else if (path === '$where') {
      +      type = typeof val;
      +
      +      if ('string' !== type && 'function' !== type) {
      +        throw new Error("Must have a string or function for $where");
      +      }
      +
      +      if ('function' === type) {
      +        obj[path] = val.toString();
      +      }
      +
      +      continue;
      +
      +    } else {
      +
      +      if (!schema) {
      +        // no casting for Mixed types
      +        continue;
      +      }
      +
      +      schematype = schema.path(path);
      +
      +      if (!schematype) {
      +        // Handle potential embedded array queries
      +        var split = path.split('.')
      +          , j = split.length
      +          , pathFirstHalf
      +          , pathLastHalf
      +          , remainingConds
      +          , castingQuery;
      +
      +        // Find the part of the var path that is a path of the Schema
      +        while (j--) {
      +          pathFirstHalf = split.slice(0, j).join('.');
      +          schematype = schema.path(pathFirstHalf);
      +          if (schematype) break;
      +        }
      +
      +        // If a substring of the input path resolves to an actual real path...
      +        if (schematype) {
      +          // Apply the casting; similar code for $elemMatch in schema/array.js
      +          if (schematype.caster && schematype.caster.schema) {
      +            remainingConds = {};
      +            pathLastHalf = split.slice(j).join('.');
      +            remainingConds[pathLastHalf] = val;
      +            castingQuery = new Query(remainingConds);
      +            castingQuery.cast(schematype.caster);
      +            obj[path] = castingQuery._conditions[pathLastHalf];
      +          } else {
      +            obj[path] = val;
      +          }
      +          continue;
      +        }
      +
      +        if (utils.isObject(val)) {
      +          // handle geo schemas that use object notation
      +          // { loc: { long: Number, lat: Number }
      +
      +          var geo = val.$near ? '$near' :
      +                    val.$nearSphere ? '$nearSphere' :
      +                    val.$within ? '$within' : '';
      +
      +          if (!geo) {
      +            continue;
      +          }
      +
      +          var numbertype = new Types.Number('__QueryCasting__')
      +          var value = val[geo];
      +
      +          if (val.$maxDistance) {
      +            val.$maxDistance = numbertype.castForQuery(val.$maxDistance);
      +          }
      +
      +          if ('$within' == geo) {
      +            // find $center, $centerSphere, $box, $polygon
      +            var withinType = value.$center || value.$centerSphere || value.$box || value.$polygon;
      +            if (!withinType) {
      +              throw new Error('Bad $within paramater: ' + JSON.stringify(val));
      +            }
      +
      +            value = withinType;
      +          }
      +
      +          ;(function _cast (val) {
      +            if (Array.isArray(val)) {
      +              val.forEach(function (item, i) {
      +                if (Array.isArray(item) || utils.isObject(item)) {
      +                  return _cast(item);
      +                }
      +                val[i] = numbertype.castForQuery(item);
      +              });
      +            } else {
      +              var nearKeys= Object.keys(val);
      +              var nearLen = nearKeys.length;
      +              while (nearLen--) {
      +                var nkey = nearKeys[nearLen];
      +                var item = val[nkey];
      +                if (Array.isArray(item) || utils.isObject(item)) {
      +                  _cast(item);
      +                  val[nkey] = item;
      +                } else {
      +                  val[nkey] = numbertype.castForQuery(item);
      +                }
      +              }
      +            }
      +          })(value);
      +        }
      +
      +      } else if (val === null || val === undefined) {
      +        continue;
      +      } else if ('Object' === val.constructor.name) {
      +
      +        any$conditionals = Object.keys(val).some(function (k) {
      +          return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
      +        });
      +
      +        if (!any$conditionals) {
      +          obj[path] = schematype.castForQuery(val);
      +        } else {
      +
      +          var ks = Object.keys(val)
      +            , k = ks.length
      +            , $cond;
      +
      +          while (k--) {
      +            $cond = ks[k];
      +            nested = val[$cond];
      +
      +            if ('$exists' === $cond) {
      +              if ('boolean' !== typeof nested) {
      +                throw new Error("$exists parameter must be Boolean");
      +              }
      +              continue;
      +            }
      +
      +            if ('$type' === $cond) {
      +              if ('number' !== typeof nested) {
      +                throw new Error("$type parameter must be Number");
      +              }
      +              continue;
      +            }
      +
      +            if ('$not' === $cond) {
      +              this.cast(model, nested);
      +            } else {
      +              val[$cond] = schematype.castForQuery($cond, nested);
      +            }
      +          }
      +        }
      +      } else {
      +        obj[path] = schematype.castForQuery(val);
      +      }
      +    }
      +  }
      +
      +  return obj;
      +};

      Parameters:

      Returns:

      Note

      + +

      If obj is present, it is cast instead of this query.


      Query#_optionsForExec(model)

      Returns default options.

      show code
      Query.prototype._optionsForExec = function (model) {
      +  var options = utils.clone(this.options, { retainKeyOrder: true });
      +  delete options.populate;
      +
      +  if (!('safe' in options))
      +    options.safe = model.schema.options.safe;
      +
      +  if (!('readPreference' in options) && model.schema.options.read)
      +    options.readPreference = model.schema.options.read;
      +
      +  return options;
      +};

      Parameters:


      Query#_applyPaths()

      Applies schematype selected options to this query.

      show code
      Query.prototype._applyPaths = function applyPaths () {
      +  // determine if query is selecting or excluding fields
      +
      +  var fields = this._fields
      +    , exclude
      +    , keys
      +    , ki
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    ki = keys.length;
      +
      +    while (ki--) {
      +      if ('+' == keys[ki][0]) continue;
      +      exclude = 0 === fields[keys[ki]];
      +      break;
      +    }
      +  }
      +
      +  // if selecting, apply default schematype select:true fields
      +  // if excluding, apply schematype select:false fields
      +
      +  var selected = []
      +    , excluded = []
      +    , seen = [];
      +
      +  analyzeSchema(this.model.schema);
      +
      +  switch (exclude) {
      +    case true:
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +    case false:
      +      selected.length && this.select(selected.join(' '));
      +      break;
      +    case undefined:
      +      // user didn't specify fields, implies returning all fields.
      +      // only need to apply excluded fields
      +      excluded.length && this.select('-' + excluded.join(' -'));
      +      break;
      +  }
      +
      +  return seen = excluded = selected = keys = fields = null;
      +
      +  function analyzeSchema (schema, prefix) {
      +    prefix || (prefix = '');
      +
      +    // avoid recursion
      +    if (~seen.indexOf(schema)) return;
      +    seen.push(schema);
      +
      +    schema.eachPath(function (path, type) {
      +      if (prefix) path = prefix + '.' + path;
      +
      +      // array of subdocs?
      +      if (type.schema) {
      +        analyzeSchema(type.schema, path);
      +      }
      +
      +      analyzePath(path, type);
      +    });
      +  }
      +
      +  function analyzePath (path, type) {
      +    if ('boolean' != typeof type.selected) return;
      +
      +    if (fields && ('+' + path) in fields) {
      +      // forced inclusion
      +      delete fields['+' + path];
      +
      +      // if there are other fields being included, add this one
      +      // if no other included fields, leave this out (implied inclusion)
      +      if (false === exclude && keys.length > 1) {
      +        fields[path] = 1;
      +      }
      +
      +      return
      +    };
      +
      +    ;(type.selected ? selected : excluded).push(path);
      +  }
      +}

      Query#$where(js)

      Specifies a $where condition

      Parameters:

      Returns:

      Use $where when you need to select documents using a JavaScript expression.

      + +

      Example

      + +
      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')
      +
      +query.$where(function () {
      +  return this.comments.length &gt; 10 || this.name.length &gt; 5;
      +})

      Query#where([path], [val])

      Specifies a path for use with chaining.

      show code
      Query.prototype.where = function (path, val) {
      +  if (!arguments.length) return this;
      +
      +  if ('string' != typeof path) {
      +    throw new TypeError('path must be a string');
      +  }
      +
      +  this._currPath = path;
      +
      +  if (2 === arguments.length) {
      +    this._conditions[path] = val;
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      // instead of writing:
      +User.find({age: {$gte: 21, $lte: 65}}, callback);
      +
      +// we can instead write:
      +User.where('age').gte(21).lte(65);
      +
      +// Moreover, you can also chain a bunch of these together:
      +
      +User
      +.where('age').gte(21).lte(65)
      +.where('name', /^b/i)
      +.where('friends').slice(10)
      +.exec(callback)

      Query#equals(val)

      Specifies the complementary comparison value for paths specified with where()

      show code
      Query.prototype.equals = function equals (val) {
      +  var path = this._currPath;
      +  if (!path) throw new Error('equals() must be used after where()');
      +  this._conditions[path] = val;
      +  return this;
      +}

      Parameters:

      Returns:

      Example

      + +
      User.where('age').equals(49);
      +
      +// is the same as
      +
      +User.where('age', 49);

      Query#or(array)

      Specifies arguments for an $or condition.

      show code
      Query.prototype.or = function or (array) {
      +  var or = this._conditions.$or || (this._conditions.$or = []);
      +  if (!Array.isArray(array)) array = [array];
      +  or.push.apply(or, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.or([{ color: 'red' }, { status: 'emergency' }])

      Query#nor(array)

      Specifies arguments for a $nor condition.

      show code
      Query.prototype.nor = function nor (array) {
      +  var nor = this._conditions.$nor || (this._conditions.$nor = []);
      +  if (!Array.isArray(array)) array = [array];
      +  nor.push.apply(nor, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.nor([{ color: 'green' }, { status: 'ok' }])

      Query#and(array)

      Specifies arguments for a $and condition.

      show code
      Query.prototype.and = function and (array) {
      +  var and = this._conditions.$and || (this._conditions.$and = []);
      +  if (!Array.isArray(array)) array = [array];
      +  and.push.apply(and, array);
      +  return this;
      +}

      Parameters:

      • array <Array> array of conditions

      Returns:

      Example

      + +
      query.and([{ color: 'green' }, { status: 'ok' }])

      Query#gt(path, val)

      Specifies a $gt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.

      + +

      Example

      + +
      Thing.find().where('age').gt(21)
      +
      +// or
      +Thing.find().gt('age', 21)

      Query#gte(path, val)

      Specifies a $gte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lt(path, val)

      Specifies a $lt query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#lte(path, val)

      Specifies a $lte query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#ne(path, val)

      Specifies a $ne query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#in(path, val)

      Specifies an $in query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#nin(path, val)

      Specifies an $nin query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#all(path, val)

      Specifies an $all query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#size(path, val)

      Specifies an $size query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#regex(path, val)

      Specifies a $regex query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#maxDistance(path, val)

      Specifies a $maxDistance query condition.

      Parameters:

      When called with one argument, the most recent path passed to where() is used.


      Query#near(path, val)

      Specifies a $near condition

      show code
      Query.prototype.near = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$near = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#nearSphere(path, val)

      Specifies a $nearSphere condition.

      show code
      Query.prototype.nearSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$nearSphere = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#mod(path, val)

      Specifies a $mod condition

      show code
      Query.prototype.mod = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath
      +  } else if (arguments.length === 2 && !Array.isArray(val)) {
      +    val = utils.args(arguments);
      +    path = this._currPath;
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds.$mod = val;
      +  return this;
      +}

      Parameters:

      Returns:


      Query#exists(path, val)

      Specifies an $exists condition

      show code
      Query.prototype.exists = function (path, val) {
      +  if (arguments.length === 0) {
      +    path = this._currPath
      +    val = true;
      +  } else if (arguments.length === 1) {
      +    if ('boolean' === typeof path) {
      +      val = path;
      +      path = this._currPath;
      +    } else {
      +      val = true;
      +    }
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$exists'] = val;
      +  return this;
      +};

      Parameters:

      Returns:


      Query#elemMatch(path, criteria)

      Specifies an $elemMatch condition

      show code
      Query.prototype.elemMatch = function (path, criteria) {
      +  var block;
      +  if ('Object' === path.constructor.name) {
      +    criteria = path;
      +    path = this._currPath;
      +  } else if ('function' === typeof path) {
      +    block = path;
      +    path = this._currPath;
      +  } else if ('Object' === criteria.constructor.name) {
      +  } else if ('function' === typeof criteria) {
      +    block = criteria;
      +  } else {
      +    throw new Error("Argument error");
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  if (block) {
      +    criteria = new Query();
      +    block(criteria);
      +    conds['$elemMatch'] = criteria._conditions;
      +  } else {
      +    conds['$elemMatch'] = criteria;
      +  }
      +  return this;
      +};
      +
      +// Spatial queries

      Parameters:

      Returns:

      Example

      + +
      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
      +
      +query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
      +
      +query.elemMatch('comment', function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})
      +
      +query.where('comment').elemMatch(function (elem) {
      +  elem.where('author').equals('autobot');
      +  elem.where('votes').gte(5);
      +})

      Query#box(path, val)

      Specifies a $box condition

      show code
      Query.prototype.box = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$box': [val.ll, val.ur]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var lowerLeft = [40.73083, -73.99756]
      +var upperRight= [40.741404,  -73.988135]
      +query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

      Query#center(path, val, [opts])

      Specifies a $center condition

      show code
      Query.prototype.center = function (path, val, opts) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$center': [val.center, val.radius]  };
      +
      +  // copy any options
      +  if (opts && 'Object' == opts.constructor.name) {
      +    utils.options(opts, conds.$within);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.center(area)

      Query#centerSphere(path, val)

      Specifies a $centerSphere condition

      show code
      Query.prototype.centerSphere = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var area = { center: [50, 50], radius: 10 }
      +query.where('loc').within.centerSphere(area)

      Query#polygon(path, val)

      Specifies a $polygon condition

      show code
      Query.prototype.polygon = function (path, val) {
      +  if (arguments.length === 1) {
      +    val = path;
      +    path = this._currPath;
      +  }
      +  var conds = this._conditions[path] || (this._conditions[path] = {});
      +  conds['$within'] = { '$polygon': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      +query.where('loc').within.polygon(polyA)
      +
      +// or
      +var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      +query.where('loc').within.polygon(polyB)

      Query#select(arg)

      Specifies which document fields to include or exclude

      show code
      Query.prototype.select = function select (arg) {
      +  if (!arg) return this;
      +
      +  var fields = this._fields || (this._fields = {});
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      fields[field] = arg[field];
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var include = '-' == field[0] ? 0 : 1;
      +      if (include === 0) field = field.substring(1);
      +      fields[field] = include;
      +    });
      +  } else {
      +    throw new TypeError('Invalid select() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

      + +

      Example

      + +
      // include a and b, exclude c
      +query.select('a b -c');
      +
      +// or you may use object notation, useful when
      +// you have keys already prefixed with a "-"
      +query.select({a: 1, b: 1, c: 0});
      +
      +// force inclusion of field excluded at schema level
      +query.select('+path')
      + +

      NOTE:

      + +

      v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.


      Query#slice(path, val)

      Specifies a $slice condition

      show code
      Query.prototype.slice = function (path, val) {
      +  if (arguments.length === 1) {
      +      val = path;
      +      path = this._currPath
      +  } else if (arguments.length === 2) {
      +    if ('number' === typeof path) {
      +      val = [path, val];
      +      path = this._currPath;
      +    }
      +  } else if (arguments.length === 3) {
      +    val = utils.args(arguments, 1);
      +  }
      +  var myFields = this._fields || (this._fields = {});
      +  myFields[path] = { '$slice': val };
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      query.slice('comments', 5)
      +query.slice('comments', -5)
      +query.slice('comments', [10, 5])
      +query.where('comments').slice(5)
      +query.where('comments').slice([-10, 5])

      Query#sort(arg)

      Sets the sort order

      show code
      Query.prototype.sort = function (arg) {
      +  if (!arg) return this;
      +
      +  var sort = this.options.sort || (this.options.sort = []);
      +
      +  if ('Object' === arg.constructor.name) {
      +    Object.keys(arg).forEach(function (field) {
      +      push(sort, field, arg[field]);
      +    });
      +  } else if (1 === arguments.length && 'string' == typeof arg) {
      +    arg.split(/\s+/).forEach(function (field) {
      +      if (!field) return;
      +      var ascend = '-' == field[0] ? -1 : 1;
      +      if (ascend === -1) field = field.substring(1);
      +      push(sort, field, ascend);
      +    });
      +  } else {
      +    throw new TypeError('Invalid sort() argument. Must be a string or object.');
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

      + +

      If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

      + +

      Example

      + +
      // these are equivalent
      +query.sort({ field: 'asc', test: -1 });
      +query.sort('field -test');

      Query#limit(val)

      Specifies the limit option.

      Parameters:

      Example

      + +
      Kitten.find().limit(20)

      Query#skip(val)

      Specifies the skip option.

      Parameters:

      Example

      + +
      Kitten.find().skip(100).limit(20)

      Query#maxscan(val)

      Specifies the maxscan option.

      Parameters:

      Example

      + +
      Kitten.find().maxscan(100)

      Query#batchSize(val)

      Specifies the batchSize option.

      Parameters:

      Example

      + +
      Kitten.find().batchSize(100)

      Query#comment(val)

      Specifies the comment option.

      Parameters:

      Example

      + +
      Kitten.findOne(condition).comment('login query')

      Query#snapshot()

      Specifies this query as a snapshot query.

      show code
      Query.prototype.snapshot = function () {
      +  this.options.snapshot = true;
      +  return this;
      +};

      Returns:

      Example

      + +
      Kitten.find().snapshot()

      Query#hint(val)

      Sets query hints.

      show code
      Query.prototype.hint = function (val) {
      +  if (!val) return this;
      +
      +  var hint = this.options.hint || (this.options.hint = {});
      +
      +  if ('Object' === val.constructor.name) {
      +    // must keep object keys in order so don't use Object.keys()
      +    for (var k in val) {
      +      hint[k] = val[k];
      +    }
      +  } else {
      +    throw new TypeError('Invalid hint. ' + val);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Model.find().hint({ indexA: 1, indexB: -1})

      Query#slaveOk(v)

      Sets the slaveOk option.

      show code
      Query.prototype.slaveOk = function (v) {
      +  this.options.slaveOk = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Example:

      + +
      new Query().slaveOk() // true
      +new Query().slaveOk(true)
      +new Query().slaveOk(false)

      Query#read(pref, [tags])

      Sets the readPreference option for the query.

      show code
      Query.prototype.read = function (pref, tags) {
      +  this.options.readPreference = utils.readPref(pref, tags);
      +  return this;
      +}

      Parameters:

      • pref <String> one of the listed preference options or their aliases
      • [tags] <Array> optional tags for this query

      Returns:

      Example:

      + +
      new Query().read('primary')
      +new Query().read('p')  // same as primary
      +
      +new Query().read('primaryPreferred')
      +new Query().read('pp') // same as primaryPreferred
      +
      +new Query().read('secondary')
      +new Query().read('s')  // same as secondary
      +
      +new Query().read('secondaryPreferred')
      +new Query().read('sp') // same as secondaryPreferred
      +
      +new Query().read('nearest')
      +new Query().read('n')  // same as nearest
      +
      +// with tags
      +new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
      + +

      Preferences:

      + +
      primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
      +secondary            Read from secondary if available, otherwise error.
      +primaryPreferred     Read from primary if available, otherwise a secondary.
      +secondaryPreferred   Read from a secondary if available, otherwise read from the primary.
      +nearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
      + +

      Aliases

      + +
      p   primary
      +pp  primaryPreferred
      +s   secondary
      +sp  secondaryPreferred
      +n   nearest
      + +

      Read more about how to use read preferrences here and here.


      Query#lean(v)

      Sets the lean option.

      show code
      Query.prototype.lean = function (v) {
      +  this.options.lean = arguments.length ? !!v : true;
      +  return this;
      +}

      Parameters:

      Returns:

      Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

      + +

      This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

      + +

      Example:

      + +
      new Query().lean() // true
      +new Query().lean(true)
      +new Query().lean(false)
      +
      +Model.find().lean().exec();
      +
      +var leanStream = Model.find().lean().stream();

      Query#tailable(v)

      Sets tailable option.

      show code
      Query.prototype.tailable = function (v) {
      +  this.options.tailable = arguments.length ? !!v : true;
      +  return this;
      +};

      Parameters:

      Example

      + +
      Kitten.find().tailable() &lt;== true
      +Kitten.find().tailable(true)
      +Kitten.find().tailable(false)

      Query#execFind(callback)

      Executes the query as a find() operation.

      show code
      Query.prototype.execFind = function (callback) {
      +  var model = this.model
      +    , promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.find(castQuery, options, function (err, cursor) {
      +    if (err) return promise.error(err);
      +    cursor.toArray(tick(cb));
      +  });
      +
      +  function cb (err, docs) {
      +    if (err) return promise.error(err);
      +
      +    if (true === options.lean)
      +      return promise.complete(docs);
      +
      +    var arr = []
      +      , count = docs.length;
      +
      +    if (!count) return promise.complete([]);
      +
      +    for (var i = 0, l = docs.length; i < l; i++) {
      +      arr[i] = new model(undefined, fields, true);
      +      arr[i].init(docs[i], self, function (err) {
      +        if (err) return promise.error(err);
      +        --count || promise.complete(arr);
      +      });
      +    }
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#findOne(callback)

      Executes the query as a findOne() operation.

      show code
      Query.prototype.findOne = function (callback) {
      +  this.op = 'findOne';
      +
      +  if (!callback) return this;
      +
      +  var model = this.model;
      +  var promise = new Promise(callback);
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    promise.error(err);
      +    return this;
      +  }
      +
      +  // apply default schematype path selections
      +  this._applyPaths();
      +
      +  var self = this
      +    , castQuery = this._conditions
      +    , options = this._optionsForExec(model)
      +    , fields = utils.clone(this._fields)
      +
      +  options.fields = this._castFields(fields);
      +  if (options.fields instanceof Error) {
      +    promise.error(options.fields);
      +    return this;
      +  }
      +
      +  model.collection.findOne(castQuery, options, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === options.lean) return promise.complete(doc);
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'white').findOne(function (err, kitten) {
      +  if (err) return handleError(err);
      +
      +  // kitten may be null if no document matched
      +  if (kitten) {
      +    ...
      +  }
      +})

      Query#count(callback)

      Exectues the query as a count() operation.

      show code
      Query.prototype.count = function (callback) {
      +  this.op = 'count';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.count(castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:

      Example

      + +
      Kitten.where('color', 'black').count(function (err, count) {
      +  if (err) return handleError(err);
      +  console.log('there are %d black kittens', count);
      +})

      Query#distinct(field, callback)

      Executes this query as a distict() operation.

      show code
      Query.prototype.distinct = function (field, callback) {
      +  this.op = 'distinct';
      +  var model = this.model;
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    return callback(err);
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.distinct(field, castQuery, tick(callback));
      +
      +  return this;
      +};

      Parameters:

      Returns:


      Query#update(doc, callback)

      Executes this query as an update() operation.

      show code
      Query.prototype.update = function update (doc, callback) {
      +  this.op = 'update';
      +  this._updateArg = doc;
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , fn = 'function' == typeof callback
      +    , castedQuery
      +    , castedDoc
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedQuery));
      +      return this;
      +    }
      +    throw castedQuery;
      +  }
      +
      +  castedDoc = castDoc(this);
      +  if (!castedDoc) {
      +    fn && process.nextTick(callback.bind(null, null, 0));
      +    return this;
      +  }
      +
      +  if (castedDoc instanceof Error) {
      +    if (fn) {
      +      process.nextTick(callback.bind(null, castedDoc));
      +      return this;
      +    }
      +    throw castedDoc;
      +  }
      +
      +  if (!fn) {
      +    options.safe = { w: 0 };
      +  }
      +
      +  model.collection.update(castedQuery, castedDoc, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Returns:

      All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

      + +

      Example

      + +
      Model.update({..}, { title: 'remove words' }, ...)
      + +

      becomes

      + +
      Model.update({..}, { $set: { title: 'remove words' }}, ...)
      + +

      Note

      + +

      Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.


      Query#_castUpdate(obj)

      Casts obj for an update command.

      show code
      Query.prototype._castUpdate = function _castUpdate (obj) {
      +  var ops = Object.keys(obj)
      +    , i = ops.length
      +    , ret = {}
      +    , hasKeys
      +    , val
      +
      +  while (i--) {
      +    var op = ops[i];
      +    if ('$' !== op[0]) {
      +      // fix up $set sugar
      +      if (!ret.$set) {
      +        if (obj.$set) {
      +          ret.$set = obj.$set;
      +        } else {
      +          ret.$set = {};
      +        }
      +      }
      +      ret.$set[op] = obj[op];
      +      ops.splice(i, 1);
      +      if (!~ops.indexOf('$set')) ops.push('$set');
      +    } else if ('$set' === op) {
      +      if (!ret.$set) {
      +        ret[op] = obj[op];
      +      }
      +    } else {
      +      ret[op] = obj[op];
      +    }
      +  }
      +
      +  // cast each value
      +  i = ops.length;
      +
      +  while (i--) {
      +    op = ops[i];
      +    val = ret[op];
      +    if ('Object' === val.constructor.name) {
      +      hasKeys |= this._walkUpdatePath(val, op);
      +    } else {
      +      var msg = 'Invalid atomic update value for ' + op + '. '
      +              + 'Expected an object, received ' + typeof val;
      +      throw new Error(msg);
      +    }
      +  }
      +
      +  return hasKeys && ret;
      +}

      Parameters:

      Returns:

      • <Object> obj after casting its values

      Query#_walkUpdatePath(obj, op, pref)

      Walk each path of obj and cast its values
      according to its schema.

      show code
      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
      +  var strict = this.model.schema.options.strict
      +    , prefix = pref ? pref + '.' : ''
      +    , keys = Object.keys(obj)
      +    , i = keys.length
      +    , hasKeys = false
      +    , schema
      +    , key
      +    , val
      +
      +  while (i--) {
      +    key = keys[i];
      +    val = obj[key];
      +
      +    if (val && 'Object' === val.constructor.name) {
      +      // watch for embedded doc schemas
      +      schema = this._getSchema(prefix + key);
      +      if (schema && schema.caster && op in castOps) {
      +        // embedded doc schema
      +
      +        if (strict && !schema) {
      +          // path is not in our strict schema
      +          if ('throw' == strict) {
      +            throw new Error('Field `' + key + '` is not in schema.');
      +          } else {
      +            // ignore paths not specified in schema
      +            delete obj[key];
      +          }
      +        } else {
      +          hasKeys = true;
      +          if ('$each' in val) {
      +            obj[key] = {
      +                $each: this._castUpdateVal(schema, val.$each, op)
      +            }
      +          } else {
      +            obj[key] = this._castUpdateVal(schema, val, op);
      +          }
      +        }
      +      } else {
      +        hasKeys |= this._walkUpdatePath(val, op, prefix + key);
      +      }
      +    } else {
      +      schema = '$each' === key
      +        ? this._getSchema(pref)
      +        : this._getSchema(prefix + key);
      +
      +      var skip = strict &&
      +                 !schema &&
      +                 !/real|nested/.test(this.model.schema.pathType(prefix + key));
      +
      +      if (skip) {
      +        if ('throw' == strict) {
      +          throw new Error('Field `' + prefix + key + '` is not in schema.');
      +        } else {
      +          delete obj[key];
      +        }
      +      } else {
      +        hasKeys = true;
      +        obj[key] = this._castUpdateVal(schema, val, op, key);
      +      }
      +    }
      +  }
      +  return hasKeys;
      +}

      Parameters:

      • obj <Object> - part of a query
      • op <String> - the atomic operator ($pull, $set, etc)
      • pref <String> - path prefix (internal only)

      Returns:

      • <Bool> true if this path has keys to update

      Query#_castUpdateVal(schema, val, op, [$conditional])

      Casts val according to schema and atomic op.

      show code
      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
      +  if (!schema) {
      +    // non-existing schema path
      +    return op in numberOps
      +      ? Number(val)
      +      : val
      +  }
      +
      +  if (schema.caster && op in castOps &&
      +    ('Object' === val.constructor.name || Array.isArray(val))) {
      +    // Cast values for ops that add data to MongoDB.
      +    // Ensures embedded documents get ObjectIds etc.
      +    var tmp = schema.cast(val);
      +
      +    if (Array.isArray(val)) {
      +      val = tmp;
      +    } else {
      +      val = tmp[0];
      +    }
      +  }
      +
      +  if (op in numberOps) return Number(val);
      +  if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
      +  return schema.castForQuery(val)
      +}

      Parameters:


      Query#_getSchema(path)

      Finds the schema for path. This is different than
      calling schema.path as it also resolves paths with
      positional selectors (something.$.another.$.path).

      show code
      Query.prototype._getSchema = function _getSchema (path) {
      +  var schema = this.model.schema
      +    , pathschema = schema.path(path);
      +
      +  if (pathschema)
      +    return pathschema;
      +
      +  // look for arrays
      +  return (function search (parts, schema) {
      +    var p = parts.length + 1
      +      , foundschema
      +      , trypath
      +
      +    while (p--) {
      +      trypath = parts.slice(0, p).join('.');
      +      foundschema = schema.path(trypath);
      +      if (foundschema) {
      +        if (foundschema.caster) {
      +
      +          // array of Mixed?
      +          if (foundschema.caster instanceof Types.Mixed) {
      +            return foundschema.caster;
      +          }
      +
      +          // Now that we found the array, we need to check if there
      +          // are remaining document paths to look up for casting.
      +          // Also we need to handle array.$.path since schema.path
      +          // doesn't work for that.
      +          if (p !== parts.length) {
      +            if ('$' === parts[p]) {
      +              // comments.$.comments.$.title
      +              return search(parts.slice(p+1), foundschema.schema);
      +            } else {
      +              // this is the last path of the selector
      +              return search(parts.slice(p), foundschema.schema);
      +            }
      +          }
      +        }
      +        return foundschema;
      +      }
      +    }
      +  })(path.split('.'), schema)
      +}

      Parameters:


      Query#_castFields(fields)

      Casts selected field arguments for field selection with mongo 2.2

      show code
      Query.prototype._castFields = function _castFields (fields) {
      +  var selected
      +    , elemMatchKeys
      +    , keys
      +    , key
      +    , out
      +    , i
      +
      +  if (fields) {
      +    keys = Object.keys(fields);
      +    elemMatchKeys = [];
      +    i = keys.length;
      +
      +    // collect $elemMatch args
      +    while (i--) {
      +      key = keys[i];
      +      if (fields[key].$elemMatch) {
      +        selected || (selected = {});
      +        selected[key] = fields[key];
      +        elemMatchKeys.push(key);
      +      }
      +    }
      +  }
      +
      +  if (selected) {
      +    // they passed $elemMatch, cast em
      +    try {
      +      out = this.cast(this.model, selected);
      +    } catch (err) {
      +      return err;
      +    }
      +
      +    // apply the casted field args
      +    i = elemMatchKeys.length;
      +    while (i--) {
      +      key = elemMatchKeys[i];
      +      fields[key] = out[key];
      +    }
      +  }
      +
      +  return fields;
      +}

      Parameters:

      query.select({ ids: { $elemMatch: { $in: [hexString] }})

      Query#remove(callback)

      Executes this query as a remove() operation.

      show code
      Query.prototype.remove = function (callback) {
      +  this.op = 'remove';
      +
      +  var model = this.model
      +    , options = this._optionsForExec(model)
      +    , cb = 'function' == typeof callback
      +
      +  try {
      +    this.cast(model);
      +  } catch (err) {
      +    if (cb) return callback(err);
      +    throw err;
      +  }
      +
      +  if (!cb) {
      +    options.safe = { w: 0 };
      +  }
      +
      +  var castQuery = this._conditions;
      +  model.collection.remove(castQuery, options, tick(callback));
      +  return this;
      +};

      Parameters:

      Example

      + +
      Cassette.where('artist').equals('Anne Murray').remove(callback)

      Query#findOneAndUpdate([query], [doc], [options], [callback])

      Issues a mongodb findAndModify update command.

      show code
      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
      +  this.op = 'findOneAndUpdate';
      +
      +  switch (arguments.length) {
      +    case 3:
      +      if ('function' == typeof options)
      +        callback = options, options = {};
      +      break;
      +    case 2:
      +      if ('function' == typeof doc) {
      +        callback = doc;
      +        doc = query;
      +        query = undefined;
      +      }
      +      options = undefined;
      +      break;
      +    case 1:
      +      if ('function' == typeof query) {
      +        callback = query;
      +        query = options = doc = undefined;
      +      } else {
      +        doc = query;
      +        query = options = undefined;
      +      }
      +  }
      +
      +  // apply query
      +  if (query) {
      +    if ('Object' === query.constructor.name) {
      +      merge(this._conditions, query);
      +    } else if (query instanceof Query) {
      +      merge(this._conditions, query._conditions);
      +    } else if (query instanceof Document) {
      +      merge(this._conditions, query.toObject());
      +    }
      +  }
      +
      +  // apply doc
      +  if (doc) {
      +    merge(this._updateArg, doc);
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('update', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • new: bool - true to return the modified document rather than the original. defaults to true
      • +
      • upsert: bool - creates the object if it doesn't exist. defaults to false.
      • +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      query.findOneAndUpdate(conditions, update, options, callback) // executes
      +query.findOneAndUpdate(conditions, update, options)  // returns Query
      +query.findOneAndUpdate(conditions, update, callback) // executes
      +query.findOneAndUpdate(conditions, update)           // returns Query
      +query.findOneAndUpdate(callback)                     // executes
      +query.findOneAndUpdate()                             // returns Query

      Query#findOneAndRemove([conditions], [options], [callback])

      Issues a mongodb findAndModify remove command.

      show code
      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
      +  this.op = 'findOneAndRemove';
      +
      +  if ('function' == typeof options) {
      +    callback = options;
      +    options = undefined;
      +  } else if ('function' == typeof conditions) {
      +    callback = conditions;
      +    conditions = undefined;
      +  }
      +
      +  // apply conditions
      +  if (conditions) {
      +    if ('Object' === conditions.constructor.name) {
      +      merge(this._conditions, conditions);
      +    } else if (conditions instanceof Query) {
      +      merge(this._conditions, conditions._conditions);
      +    } else if (conditions instanceof Document) {
      +      merge(this._conditions, conditions.toObject());
      +    }
      +  }
      +
      +  // apply options
      +  options && this.setOptions(options);
      +
      +  if (!callback) return this;
      +
      +  return this._findAndModify('remove', callback);
      +}

      Parameters:

      Returns:

      Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

      + +

      Available options

      + +
        +
      • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
      • +
      + +

      Examples

      + +
      A.where().findOneAndRemove(conditions, options, callback) // executes
      +A.where().findOneAndRemove(conditions, options)  // return Query
      +A.where().findOneAndRemove(conditions, callback) // executes
      +A.where().findOneAndRemove(conditions) // returns Query
      +A.where().findOneAndRemove(callback)   // executes
      +A.where().findOneAndRemove()           // returns Query

      Query#_findAndModify(type, callback)

      _findAndModify

      show code
      Query.prototype._findAndModify = function (type, callback) {
      +  var model = this.model
      +    , promise = new Promise(callback)
      +    , self = this
      +    , castedQuery
      +    , castedDoc
      +    , fields
      +    , sort
      +    , opts
      +
      +  castedQuery = castQuery(this);
      +  if (castedQuery instanceof Error) {
      +    process.nextTick(promise.error.bind(promise, castedQuery));
      +    return promise;
      +  }
      +
      +  opts = this._optionsForExec(model);
      +
      +  if ('remove' == type) {
      +    opts.remove = true;
      +  } else {
      +    if (!('new' in opts)) opts.new = true;
      +    if (!('upsert' in opts)) opts.upsert = false;
      +
      +    castedDoc = castDoc(this);
      +    if (!castedDoc) {
      +      if (opts.upsert) {
      +        // still need to do the upsert to empty doc
      +        castedDoc = { $set: {} };
      +      } else {
      +        return this.findOne(callback);
      +      }
      +    } else if (castedDoc instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, castedDoc));
      +      return promise;
      +    }
      +  }
      +
      +  this._applyPaths();
      +
      +  if (this._fields) {
      +    fields = utils.clone(this._fields)
      +    opts.fields = this._castFields(fields);
      +    if (opts.fields instanceof Error) {
      +      process.nextTick(promise.error.bind(promise, opts.fields));
      +      return promise;
      +    }
      +  }
      +
      +  // the driver needs a default
      +  sort = opts.sort || [];
      +
      +  model
      +  .collection
      +  .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
      +    if (err) return promise.error(err);
      +    if (!doc) return promise.complete(null);
      +
      +    if (true === opts.lean) {
      +      return promise.complete(doc);
      +    }
      +
      +    var casted = new model(undefined, fields, true);
      +    casted.init(doc, self, function (err) {
      +      if (err) return promise.error(err);
      +      promise.complete(casted);
      +    });
      +  }));
      +
      +  return promise;
      +}

      Parameters:


      Query#populate(path, [fields], [model], [conditions], [options])

      Specifies paths which should be populated with other documents.

      show code
      Query.prototype.populate = function (path, fields, model, conditions, options) {
      +  if ('string' !== typeof model) {
      +    options = conditions;
      +    conditions = model;
      +    model = undefined;
      +  }
      +  // The order of fields/conditions args is opposite Model.find but
      +  // necessary to keep backward compatibility (fields could be
      +  // an array, string, or object literal).
      +  this.options.populate[path] =
      +    new PopulateOptions(fields, conditions, options, model);
      +
      +  return this;
      +};

      Parameters:

      • path <String>
      • [fields] <Object, String> Field selection for the population query
      • [model] <Model> The name of the model you wish to use for population. If not specified, the name is looked up from the Schema ref.
      • [conditions] <Object> Conditions for the population query
      • [options] <Object> Options for the population query (sort, etc)

      Returns:

      Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

      + +

      Example:

      + +
      Kitten.findOne().populate('owner').exec(function (err, kitten) {
      +  console.log(kitten.owner.name) // Max
      +})

      Query#stream([options])

      Returns a Node.js 0.8 style read stream interface.

      show code
      Query.prototype.stream = function stream (opts) {
      +  return new QueryStream(this, opts);
      +}
      +
      +// helpers

      Parameters:

      Returns:

      Example

      + +
      // follows the nodejs 0.8 stream api
      +Thing.find({ name: /^hello/ }).stream().pipe(res)
      +
      +// manual streaming
      +var stream = Thing.find({ name: /^hello/ }).stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});
      + +

      Valid options

      + +
        +
      • transform: optional function which accepts a mongoose document. The return value of the function will be emitted.
      • +
      + +

      Example

      + +
      // JSON.stringify all documents before emitting
      +var stream = Thing.find().stream({ transform: JSON.stringify });
      +stream.pipe(writeStream);

      Query#within

      Syntax sugar for expressive queries.

      + +

      Example

      + +
      query.within.box()
      +query.within.center()

      Returns:


    • querystream.js

      QueryStream(query)

      Provides a Node.js 0.8 style ReadStream interface for Queries.

      show code
      function QueryStream (query, options) {
      +  Stream.call(this);
      +
      +  this.query = query;
      +  this.readable = true;
      +  this.paused = false;
      +  this._cursor = null;
      +  this._destroyed = null;
      +  this._fields = null;
      +  this._buffer = null;
      +  this._inline = T_INIT;
      +  this._running = false;
      +  this._transform = options && 'function' == typeof options.transform
      +    ? options.transform
      +    : K;
      +
      +  // give time to hook up events
      +  var self = this;
      +  process.nextTick(function () {
      +    self._init();
      +  });
      +}

      Parameters:

      Inherits:

      Events:

      • data: emits a single Mongoose document

      • error: emits when an error occurs during streaming. This will emit before the close event.

      • close: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually destroyed. After this event, no more events are emitted.

      var stream = Model.find().stream();
      +
      +stream.on('data', function (doc) {
      +  // do something with the mongoose document
      +}).on('error', function (err) {
      +  // handle the error
      +}).on('close', function () {
      +  // the stream is closed
      +});
      + +

      The stream interface allows us to simply "plug-in" to other Node.js 0.8 style write streams.

      + +
      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);
      + +

      NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary.

      + +

      NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work.


      QueryStream#_init()

      Initializes the query.

      show code
      QueryStream.prototype._init = function () {
      +  if (this._destroyed) return;
      +
      +  var query = this.query
      +    , model = query.model
      +    , options = query._optionsForExec(model)
      +    , self = this
      +
      +  try {
      +    query.cast(model);
      +  } catch (err) {
      +    return self.destroy(err);
      +  }
      +
      +  self._fields = utils.clone(query._fields);
      +  options.fields = query._castFields(self._fields);
      +
      +  model.collection.find(query._conditions, options, function (err, cursor) {
      +    if (err) return self.destroy(err);
      +    self._cursor = cursor;
      +    self._next();
      +  });
      +}

      QueryStream#_next()

      Trampoline for pulling the next doc from cursor.

      show code
      QueryStream.prototype._next = function _next () {
      +  if (this.paused || this._destroyed) {
      +    return this._running = false;
      +  }
      +
      +  this._running = true;
      +
      +  if (this._buffer && this._buffer.length) {
      +    var arg;
      +    while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
      +      this._onNextObject.apply(this, arg);
      +    }
      +  }
      +
      +  // avoid stack overflows with large result sets.
      +  // trampoline instead of recursion.
      +  while (this.__next()) {}
      +}

      QueryStream#__next()

      Pulls the next doc from the cursor.

      show code
      QueryStream.prototype.__next = function () {
      +  if (this.paused || this._destroyed)
      +    return this._running = false;
      +
      +  var self = this;
      +  self._inline = T_INIT;
      +
      +  self._cursor.nextObject(function cursorcb (err, doc) {
      +    self._onNextObject(err, doc);
      +  });
      +
      +  // if onNextObject() was already called in this tick
      +  // return ourselves to the trampoline.
      +  if (T_CONT === this._inline) {
      +    return true;
      +  } else {
      +    // onNextObject() hasn't fired yet. tell onNextObject
      +    // that its ok to call _next b/c we are not within
      +    // the trampoline anymore.
      +    this._inline = T_IDLE;
      +  }
      +}

      QueryStream#_onNextObject(err, doc)

      Transforms raw docs returned from the cursor into a model instance.

      show code
      QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
      +  if (this._destroyed) return;
      +
      +  if (this.paused) {
      +    this._buffer || (this._buffer = []);
      +    this._buffer.push([err, doc]);
      +    return this._running = false;
      +  }
      +
      +  if (err) return this.destroy(err);
      +
      +  // when doc is null we hit the end of the cursor
      +  if (!doc) {
      +    this.emit('end');
      +    return this.destroy();
      +  }
      +
      +  if (this.query.options && true === this.query.options.lean)  {
      +    this.emit('data', this._transform(doc));
      +
      +    // trampoline management
      +    if (T_IDLE === this._inline) {
      +      // no longer in trampoline. restart it.
      +      this._next();
      +    } else {
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      this._inline = T_CONT;
      +    }
      +    return;
      +  }
      +
      +  var instance = new this.query.model(undefined, this._fields, true);
      +
      +  var self = this;
      +  instance.init(doc, this.query, function (err) {
      +    if (err) return self.destroy(err);
      +    self.emit('data', self._transform(instance));
      +
      +    // trampoline management
      +    if (T_IDLE === self._inline) {
      +      // no longer in trampoline. restart it.
      +      self._next();
      +    } else
      +      // in a trampoline. tell __next that its
      +      // ok to continue jumping.
      +      self._inline = T_CONT;
      +  });
      +}

      Parameters:


      QueryStream#pause()

      Pauses this stream.

      show code
      QueryStream.prototype.pause = function () {
      +  this.paused = true;
      +}

      QueryStream#resume()

      Resumes this stream.

      show code
      QueryStream.prototype.resume = function () {
      +  this.paused = false;
      +
      +  if (!this._cursor) {
      +    // cannot start if not initialized
      +    return;
      +  }
      +
      +  // are we within the trampoline?
      +  if (T_INIT === this._inline) {
      +    return;
      +  }
      +
      +  if (!this._running) {
      +    // outside QueryStream control, need manual restart
      +    return this._next();
      +  }
      +}

      QueryStream#destroy([err])

      Destroys the stream, closing the underlying cursor. No more events will be emitted.

      show code
      QueryStream.prototype.destroy = function (err) {
      +  if (this._destroyed) return;
      +  this._destroyed = true;
      +  this._running = false;
      +  this.readable = false;
      +
      +  if (this._cursor) {
      +    this._cursor.close();
      +  }
      +
      +  if (err) {
      +    this.emit('error', err);
      +  }
      +
      +  this.emit('close');
      +}

      Parameters:


      QueryStream#pipe()

      Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

      See:

      Example:

      + +
      query.stream().pipe(writeStream [, options])
      + +

      This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      + +
      var format = new ArrayFormatter;
      +Events.find().stream().pipe(format).pipe(res);
      + +

      As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.


      QueryStream#paused

      Flag stating whether or not this stream is paused.


      QueryStream#readable

      Flag stating whether or not this stream is readable.


    • schema/array.js

      SchemaArray(key, cast, options)

      Array SchemaType constructor

      show code
      function SchemaArray (key, cast, options) {
      +  if (cast) {
      +    var castOptions = {};
      +
      +    if ('Object' === cast.constructor.name) {
      +      if (cast.type) {
      +        // support { type: Woot }
      +        castOptions = cast;
      +        cast = cast.type;
      +        delete castOptions.type;
      +      } else {
      +        cast = Mixed;
      +      }
      +    }
      +
      +    var caster = cast.name in Types ? Types[cast.name] : cast;
      +    this.casterConstructor = caster;
      +    this.caster = new caster(null, castOptions);
      +    if (!(this.caster instanceof EmbeddedDoc)) {
      +      this.caster.path = key;
      +    }
      +  }
      +
      +  SchemaType.call(this, key, options);
      +
      +  var self = this
      +    , defaultArr
      +    , fn;
      +
      +  if (this.defaultValue) {
      +    defaultArr = this.defaultValue;
      +    fn = 'function' == typeof defaultArr;
      +  }
      +
      +  this.default(function(){
      +    var arr = fn ? defaultArr() : defaultArr || [];
      +    return new MongooseArray(arr, self.path, this);
      +  });
      +};

      Parameters:

      Inherits:


      SchemaArray#checkRequired(value)

      Check required

      show code
      SchemaArray.prototype.checkRequired = function (value) {
      +  return !!(value && value.length);
      +};

      Parameters:


      SchemaArray#applyGetters(value, scope)

      Overrides the getters application for the population special-case

      show code
      SchemaArray.prototype.applyGetters = function (value, scope) {
      +  if (this.caster.options && this.caster.options.ref) {
      +    // means the object id was populated
      +    return value;
      +  }
      +
      +  return SchemaType.prototype.applyGetters.call(this, value, scope);
      +};

      Parameters:


      SchemaArray#cast(value, doc, init)

      Casts contents

      show code
      SchemaArray.prototype.cast = function (value, doc, init) {
      +  if (Array.isArray(value)) {
      +    if (!(value instanceof MongooseArray)) {
      +      value = new MongooseArray(value, this.path, doc);
      +    }
      +
      +    if (this.caster) {
      +      try {
      +        for (var i = 0, l = value.length; i < l; i++) {
      +          value[i] = this.caster.cast(value[i], doc, init);
      +        }
      +      } catch (e) {
      +        // rethrow
      +        throw new CastError(e.type, value, this.path);
      +      }
      +    }
      +
      +    return value;
      +  } else {
      +    return this.cast([value], doc, init);
      +  }
      +};

      Parameters:

      • value <Object>
      • doc <Document> document that triggers the casting
      • init <Boolean> whether this is an initialization cast

      SchemaArray#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaArray.prototype.castForQuery = function ($conditional, value) {
      +  var handler
      +    , val;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Array.");
      +    val = handler.call(this, value);
      +  } else {
      +    val = $conditional;
      +    var proto = this.casterConstructor.prototype;
      +    var method = proto.castForQuery || proto.cast;
      +
      +    var caster = this.caster;
      +    if (Array.isArray(val)) {
      +      val = val.map(function (v) {
      +        if (method) v = method.call(caster, v);
      +
      +        return isMongooseObject(v)
      +          ? v.toObject()
      +          : v;
      +      });
      +    } else if (method) {
      +      val = method.call(caster, val);
      +    }
      +  }
      +  return val && isMongooseObject(val)
      +    ? val.toObject()
      +    : val;
      +};

      Parameters:


    • schema/boolean.js

      SchemaBoolean(path, options)

      Boolean SchemaType constructor.

      show code
      function SchemaBoolean (path, options) {
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      SchemaBoolean#checkRequired()

      Required validator

      show code
      SchemaBoolean.prototype.checkRequired = function (value) {
      +  return value === true || value === false;
      +};

      SchemaBoolean#cast(value)

      Casts to boolean

      show code
      SchemaBoolean.prototype.cast = function (value) {
      +  if (value === null) return value;
      +  if (value === '0') return false;
      +  return !!value;
      +};

      Parameters:


      SchemaBoolean#castForQuery($conditional, val)

      Casts contents for queries.

      show code
      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (2 === arguments.length) {
      +    handler = SchemaBoolean.$conditionalHandlers[$conditional];
      +
      +    if (handler) {
      +      return handler.call(this, val);
      +    }
      +
      +    return this.cast(val);
      +  }
      +
      +  return this.cast($conditional);
      +};

      Parameters:


    • schema/buffer.js

      SchemaBuffer(key, cast)

      Buffer SchemaType constructor

      show code
      function SchemaBuffer (key, options) {
      +  SchemaType.call(this, key, options, 'Buffer');
      +};

      Parameters:

      Inherits:


      SchemaBuffer#checkRequired()

      Check required

      show code
      SchemaBuffer.prototype.checkRequired = function (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return !!(value && value.length);
      +  }
      +};

      SchemaBuffer#cast(value, doc, init)

      Casts contents

      show code
      SchemaBuffer.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (Buffer.isBuffer(value)) {
      +    if (!(value instanceof MongooseBuffer)) {
      +      value = new MongooseBuffer(value, [this.path, doc]);
      +    }
      +
      +    return value;
      +  } else if (value instanceof Binary) {
      +    return new MongooseBuffer(value.value(true), [this.path, doc]);
      +  }
      +
      +  var type = typeof value;
      +  if ('string' == type || 'number' == type || Array.isArray(value)) {
      +    return new MongooseBuffer(value, [this.path, doc]);
      +  }
      +
      +  throw new CastError('buffer', value, this.path);
      +};

      Parameters:


      SchemaBuffer#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Buffer.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    return this.cast(val).toObject();
      +  }
      +};

      Parameters:


    • schema/date.js

      SchemaDate(key, options)

      Date SchemaType constructor.

      show code
      function SchemaDate (key, options) {
      +  SchemaType.call(this, key, options);
      +};

      Parameters:

      Inherits:


      SchemaDate#checkRequired()

      Required validator for date

      show code
      SchemaDate.prototype.checkRequired = function (value) {
      +  return value instanceof Date;
      +};

      SchemaDate#cast(value)

      Casts to date

      show code
      SchemaDate.prototype.cast = function (value) {
      +  if (value === null || value === '')
      +    return null;
      +
      +  if (value instanceof Date)
      +    return value;
      +
      +  var date;
      +
      +  // support for timestamps
      +  if (value instanceof Number || 'number' == typeof value 
      +      || String(value) == Number(value))
      +    date = new Date(Number(value));
      +
      +  // support for date strings
      +  else if (value.toString)
      +    date = new Date(value.toString());
      +
      +  if (date.toString() != 'Invalid Date')
      +    return date;
      +
      +  throw new CastError('date', value, this.path);
      +};

      Parameters:


      SchemaDate#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaDate.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +
      +  if (2 !== arguments.length) {
      +    return this.cast($conditional);
      +  }
      +
      +  handler = this.$conditionalHandlers[$conditional];
      +
      +  if (!handler) {
      +    throw new Error("Can't use " + $conditional + " with Date.");
      +  }
      +
      +  return handler.call(this, val);
      +};

      Parameters:


    • schema/documentarray.js

      DocumentArray(key, schema, options)

      SubdocsArray SchemaType constructor

      show code
      function DocumentArray (key, schema, options) {
      +
      +  // compile an embedded document for this schema
      +  function EmbeddedDocument () {
      +    Subdocument.apply(this, arguments);
      +  }
      +
      +  EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
      +  EmbeddedDocument.prototype._setSchema(schema);
      +  EmbeddedDocument.schema = schema;
      +
      +  // apply methods
      +  for (var i in schema.methods) {
      +    EmbeddedDocument.prototype[i] = schema.methods[i];
      +  }
      +
      +  // apply statics
      +  for (var i in schema.statics)
      +    EmbeddedDocument[i] = schema.statics[i];
      +
      +  EmbeddedDocument.options = options;
      +  this.schema = schema;
      +
      +  ArrayType.call(this, key, EmbeddedDocument, options);
      +
      +  this.schema = schema;
      +  var path = this.path;
      +  var fn = this.defaultValue;
      +
      +  this.default(function(){
      +    var arr = fn.call(this);
      +    if (!Array.isArray(arr)) arr = [arr];
      +    return new MongooseDocumentArray(arr, path, this);
      +  });
      +};

      Parameters:

      Inherits:


      DocumentArray#doValidate()

      Performs local validations first, then validations on each embedded doc

      show code
      DocumentArray.prototype.doValidate = function (array, fn, scope) {
      +  var self = this;
      +
      +  SchemaType.prototype.doValidate.call(this, array, function (err) {
      +    if (err) return fn(err);
      +
      +    var count = array && array.length
      +      , error;
      +
      +    if (!count) return fn();
      +
      +    // handle sparse arrays, do not use array.forEach which does not
      +    // iterate over sparse elements yet reports array.length including
      +    // them :(
      +
      +    for (var i = 0, len = count; i < len; ++i) {
      +      // sidestep sparse entries
      +      var doc = array[i];
      +      if (!doc) {
      +        --count || fn();
      +        continue;
      +      }
      +
      +      ;(function (i) {
      +        doc.validate(function (err) {
      +          if (err && !error) {
      +            // rewrite the key
      +            err.key = self.key + '.' + i + '.' + err.key;
      +            return fn(error = err);
      +          }
      +          --count || fn();
      +        });
      +      })(i);
      +    }
      +  }, scope);
      +};

      DocumentArray#cast(value, document)

      Casts contents

      show code
      DocumentArray.prototype.cast = function (value, doc, init, prev) {
      +  var selected
      +    , subdoc
      +    , i
      +
      +  if (!Array.isArray(value)) {
      +    return this.cast([value], doc, init, prev);
      +  }
      +
      +  if (!(value instanceof MongooseDocumentArray)) {
      +    value = new MongooseDocumentArray(value, this.path, doc);
      +  }
      +
      +  i = value.length;
      +
      +  while (i--) {
      +    if (!(value[i] instanceof Subdocument) && value[i]) {
      +      if (init) {
      +        selected || (selected = scopePaths(this, doc._selected, init));
      +        subdoc = new this.casterConstructor(null, value, true, selected);
      +        value[i] = subdoc.init(value[i]);
      +      } else {
      +        if (prev && (subdoc = prev.id(value[i]._id))) {
      +          // handle resetting doc with existing id but differing data
      +          // doc.array = [{ doc: 'val' }]
      +          subdoc.set(value[i]);
      +        } else {
      +          subdoc = new this.casterConstructor(value[i], value);
      +        }
      +
      +        // if set() is hooked it will have no return value
      +        // see gh-746
      +        value[i] = subdoc;
      +      }
      +    }
      +  }
      +
      +  return value;
      +}

      Parameters:


    • schema/mixed.js

      Mixed(path, options)

      Mixed SchemaType constructor.

      show code
      function Mixed (path, options) {
      +  // make sure empty array defaults are handled
      +  if (options &&
      +      options.default &&
      +      Array.isArray(options.default) &&
      +      0 === options.default.length) {
      +    options.default = Array;
      +  }
      +
      +  SchemaType.call(this, path, options);
      +};

      Parameters:

      Inherits:


      Mixed#checkRequired()

      Required validator

      show code
      Mixed.prototype.checkRequired = function (val) {
      +  return true;
      +};

      Mixed#cast(value)

      Casts val for Mixed.

      show code
      Mixed.prototype.cast = function (val) {
      +  return val;
      +};

      Parameters:

      this is a no-op


      Mixed#castForQuery($cond, [val])

      Casts contents for queries.

      show code
      Mixed.prototype.castForQuery = function ($cond, val) {
      +  if (arguments.length === 2) return val;
      +  return $cond;
      +};

      Parameters:


    • schema/number.js

      SchemaNumber(key, options)

      Number SchemaType constructor.

      show code
      function SchemaNumber (key, options) {
      +  SchemaType.call(this, key, options, 'Number');
      +};

      Parameters:

      Inherits:


      SchemaNumber#checkRequired()

      Required validator for number

      show code
      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return typeof value == 'number' || value instanceof Number;
      +  }
      +};

      SchemaNumber#min(value, message)

      Sets a minimum number validator.

      show code
      SchemaNumber.prototype.min = function (value, message) {
      +  if (this.minValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'min';
      +    });
      +  if (value != null)
      +    this.validators.push([function(v){
      +      return v === null || v >= value;
      +    }, 'min']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, min: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 9 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#max(maximum, message)

      Sets a maximum number validator.

      show code
      SchemaNumber.prototype.max = function (value, message) {
      +  if (this.maxValidator)
      +    this.validators = this.validators.filter(function(v){
      +      return v[1] != 'max';
      +    });
      +  if (value != null)
      +    this.validators.push([this.maxValidator = function(v){
      +      return v === null || v <= value;
      +    }, 'max']);
      +  return this;
      +};

      Parameters:

      Example:

      + +
      var s = new Schema({ n: { type: Number, max: 10 })
      +var M = db.model('M', s)
      +var m = new M({ n: 11 })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.n = 10;
      +  m.save() // success
      +})

      SchemaNumber#cast(value, doc, init)

      Casts to number

      show code
      SchemaNumber.prototype.cast = function (value, doc, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (!isNaN(value)){
      +    if (null === value) return value;
      +    if ('' === value) return null;
      +    if ('string' == typeof value) value = Number(value);
      +    if (value instanceof Number) return value
      +    if ('number' == typeof value) return value;
      +    if (value.toString && !Array.isArray(value) &&
      +        value.toString() == Number(value)) {
      +      return new Number(value)
      +    }
      +  }
      +
      +  throw new CastError('number', value, this.path);
      +};

      Parameters:


      SchemaNumber#castForQuery($conditional, [value])

      Casts contents for queries.

      show code
      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with Number.");
      +    return handler.call(this, val);
      +  } else {
      +    val = this.cast($conditional);
      +    return val == null ? val : val
      +  }
      +};

      Parameters:


    • schema/objectid.js

      ObjectId(key, options)

      ObjectId SchemaType constructor.

      show code
      function ObjectId (key, options) {
      +  SchemaType.call(this, key, options, 'ObjectID');
      +};

      Parameters:

      Inherits:


      ObjectId#checkRequired()

      Check required

      show code
      ObjectId.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return value instanceof oid;
      +  }
      +};

      ObjectId#cast(value, scope, init)

      Casts to ObjectId

      show code
      ObjectId.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  if (value === null) return value;
      +
      +  if (value instanceof oid)
      +    return value;
      +
      +  if (value._id && value._id instanceof oid)
      +    return value._id;
      +
      +  if (value.toString) {
      +    try {
      +      return oid.fromString(value.toString());
      +    } catch (err) {
      +      throw new CastError('ObjectId', value, this.path);
      +    }
      +  }
      +
      +  throw new CastError('ObjectId', value, this.path);
      +};

      Parameters:


      ObjectId#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      ObjectId.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with ObjectId.");
      +    return handler.call(this, val);
      +  } else {
      +    return this.cast($conditional);
      +  }
      +};

      Parameters:


      ObjectId#auto(turnOn)

      Adds an auto-generated ObjectId default if turnOn is true.

      show code
      ObjectId.prototype.auto = function (turnOn) {
      +  if (turnOn) {
      +    this.default(defaultId);
      +    this.set(resetId)
      +  }
      +};

      Parameters:

      • turnOn <Boolean> auto generated ObjectId defaults

    • schema/string.js

      SchemaString(key, options)

      String SchemaType constructor.

      show code
      function SchemaString (key, options) {
      +  this.enumValues = [];
      +  this.regExp = null;
      +  SchemaType.call(this, key, options, 'String');
      +};

      Parameters:

      Inherits:


      SchemaString#enum([args...])

      Adds enumeration values and a coinciding validator.

      show code
      SchemaString.prototype.enum = function () {
      +  var len = arguments.length;
      +  if (!len || undefined === arguments[0] || false === arguments[0]) {
      +    if (this.enumValidator){
      +      this.enumValidator = false;
      +      this.validators = this.validators.filter(function(v){
      +        return v[1] != 'enum';
      +      });
      +    }
      +    return;
      +  }
      +
      +  for (var i = 0; i < len; i++) {
      +    if (undefined !== arguments[i]) {
      +      this.enumValues.push(this.cast(arguments[i]));
      +    }
      +  }
      +
      +  if (!this.enumValidator) {
      +    var values = this.enumValues;
      +    this.enumValidator = function(v){
      +      return undefined === v || ~values.indexOf(v);
      +    };
      +    this.validators.push([this.enumValidator, 'enum']);
      +  }
      +};

      Parameters:

      • [args...] <String> enumeration values

      Example:

      + +
      var states = 'opening open closing closed'.split(' ')
      +var s = new Schema({ state: { type: String, enum: states })
      +var M = db.model('M', s)
      +var m = new M({ state: 'invalid' })
      +m.save(function (err) {
      +  console.error(err) // validator error
      +  m.state = 'open'
      +  m.save() // success
      +})

      SchemaString#lowercase()

      Adds a lowercase setter.

      show code
      SchemaString.prototype.lowercase = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.toLowerCase();
      +    return v;
      +  });
      +};

      Example:

      + +
      var s = new Schema({ email: { type: String, lowercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ email: 'SomeEmail@example.COM' });
      +console.log(m.email) // someemail@example.com
      +

      SchemaString#uppercase()

      Adds an uppercase setter.

      show code
      SchemaString.prototype.uppercase = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.toUpperCase();
      +    return v;
      +  });
      +};

      Example:

      + +
      var s = new Schema({ caps: { type: String, uppercase: true }})
      +var M = db.model('M', s);
      +var m = new M({ caps: 'an example' });
      +console.log(m.caps) // AN EXAMPLE

      SchemaString#trim()

      Adds a trim setter.

      show code
      SchemaString.prototype.trim = function () {
      +  return this.set(function (v, self) {
      +    if ('string' != typeof v) v = self.cast(v)
      +    if (v) return v.trim();
      +    return v;
      +  });
      +};

      The string value will be trimmed when set.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, trim: true }})
      +var M = db.model('M', s)
      +var string = ' some name '
      +console.log(string.length) // 11
      +var m = new M({ name: string })
      +console.log(m.name.length) // 9

      SchemaString#match(regExp)

      Sets a regexp validator.

      show code
      SchemaString.prototype.match = function match (regExp) {
      +  this.validators.push([function(v){
      +    return null != v && '' !== v
      +      ? regExp.test(v)
      +      : true
      +  }, 'regexp']);
      +};

      Parameters:

      • regExp <RegExp> regular expression to test against

      Any value that does not pass regExp.test(val) will fail validation.

      + +

      Example:

      + +
      var s = new Schema({ name: { type: String, match: /^a/ }})
      +var M = db.model('M', s)
      +var m = new M({ name: 'invalid' })
      +m.validate(function (err) {
      +  console.error(err) // validation error
      +  m.name = 'apples'
      +  m.validate(function (err) {
      +    assert.ok(err) // success
      +  })
      +})

      SchemaString#checkRequired(value)

      Check required

      show code
      SchemaString.prototype.checkRequired = function checkRequired (value) {
      +  if (SchemaType._isRef(this, value, true)) {
      +    return null != value;
      +  } else {
      +    return (value instanceof String || typeof value == 'string') && value.length;
      +  }
      +};

      Parameters:


      SchemaString#cast()

      Casts to String

      show code
      SchemaString.prototype.cast = function (value, scope, init) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +  if (value === null) return value;
      +  if ('undefined' !== typeof value && value.toString) return value.toString();
      +  throw new CastError('string', value, this.path);
      +};

      SchemaString#castForQuery($conditional, [val])

      Casts contents for queries.

      show code
      SchemaString.prototype.castForQuery = function ($conditional, val) {
      +  var handler;
      +  if (arguments.length === 2) {
      +    handler = this.$conditionalHandlers[$conditional];
      +    if (!handler)
      +      throw new Error("Can't use " + $conditional + " with String.");
      +    return handler.call(this, val);
      +  } else {
      +    val = $conditional;
      +    if (val instanceof RegExp) return val;
      +    return this.cast(val);
      +  }
      +};

      Parameters:


    • schema.js

      Schema(definition)

      Schema constructor.

      show code
      function Schema (obj, options) {
      +  if (!(this instanceof Schema))
      +    return new Schema(obj, options);
      +
      +  this.paths = {};
      +  this.subpaths = {};
      +  this.virtuals = {};
      +  this.nested = {};
      +  this.inherits = {};
      +  this.callQueue = [];
      +  this._indexes = [];
      +  this.methods = {};
      +  this.statics = {};
      +  this.tree = {};
      +  this._requiredpaths = undefined;
      +
      +  this.options = this.defaultOptions(options);
      +
      +  // build paths
      +  if (obj) {
      +    this.add(obj);
      +  }
      +
      +  // ensure the documents get an auto _id unless disabled
      +  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
      +  if (auto_id) {
      +    this.add({ _id: {type: Schema.ObjectId, auto: true} });
      +  }
      +
      +  // ensure the documents receive an id getter unless disabled
      +  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
      +  if (autoid) {
      +    this.virtual('id').get(idGetter);
      +  }
      +
      +  // versioning not directly added to schema b/c we only want
      +  // it in the top level document, not embedded ones.
      +};

      Parameters:

      Events:

      • init: Emitted after the schema is compiled into a Model.

      Example:

      + +
      var child = new Schema({ name: String });
      +var schema = new Schema({ name: String, age: Number, children: [child] });
      +var Tree = mongoose.model('Tree', schema);
      +
      +// setting schema options
      +new Schema({ name: String }, { _id: false, autoIndex: false })
      + +

      Options:

      + +
        +
      • autoIndex: bool - defaults to true
      • +
      • capped: bool - defaults to false
      • +
      • collection: string - no default
      • +
      • id: bool - defaults to true
      • +
      • _id: bool - defaults to true
      • +
      • read: string
      • +
      • safe: bool - defaults to true.
      • +
      • shardKey: bool - defaults to null
      • +
      • strict: bool - defaults to true
      • +
      • toJSON - object - no default
      • +
      • toObject - object - no default
      • +
      • versionKey: bool - defaults to "__v"
      • +
      • minimize: bool - controls document#toObject behavior when called manually - defaults to true
      • +
      + +

      Note:

      + +

      When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.


      Schema#defaultOptions(options)

      Returns default options for this schema, merged with options.

      show code
      Schema.prototype.defaultOptions = function (options) {
      +  if (options && false === options.safe) {
      +    options.safe = { w: 0 };
      +  }
      +
      +  options = utils.options({
      +      strict: true
      +    , capped: false // { size, max, autoIndexId }
      +    , versionKey: '__v'
      +    , minimize: true
      +    , autoIndex: true
      +    , shardKey: null
      +    , read: null
      +    // the following are only applied at construction time
      +    , noId: false // deprecated, use { _id: false }
      +    , _id: true
      +    , noVirtualId: false // deprecated, use { id: false }
      +    , id: true
      +  }, options);
      +
      +  if (options.read)
      +    options.read = utils.readPref(options.read);
      +
      +  return options;
      +}

      Parameters:

      Returns:


      Schema#add(obj, prefix)

      Adds key path / schema type pairs to this schema.

      show code
      Schema.prototype.add = function add (obj, prefix) {
      +  prefix = prefix || '';
      +  for (var i in obj) {
      +    if (null == obj[i]) {
      +      throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
      +    }
      +
      +    if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
      +      if (Object.keys(obj[i]).length) {
      +        // nested object { last: { name: String }}
      +        this.nested[prefix + i] = true;
      +        this.add(obj[i], prefix + i + '.');
      +      } else {
      +        this.path(prefix + i, obj[i]); // mixed type
      +      }
      +    } else {
      +      this.path(prefix + i, obj[i]);
      +    }
      +  }
      +};

      Parameters:

      Example:

      + +
      var ToySchema = new Schema;
      +ToySchema.add({ name: 'string', color: 'string', price: 'number' });

      Schema#path(path, constructor)

      Gets/sets schema paths.

      show code
      Schema.prototype.path = function (path, obj) {
      +  if (obj == undefined) {
      +    if (this.paths[path]) return this.paths[path];
      +    if (this.subpaths[path]) return this.subpaths[path];
      +
      +    // subpaths?
      +    return /\.\d+\.?$/.test(path)
      +      ? getPositionalPath(this, path)
      +      : undefined;
      +  }
      +
      +  // some path names conflict with document methods
      +  if (reserved[path]) {
      +    throw new Error("`" + path + "` may not be used as a schema pathname");
      +  }
      +
      +  // update the tree
      +  var subpaths = path.split(/\./)
      +    , last = subpaths.pop()
      +    , branch = this.tree;
      +
      +  subpaths.forEach(function(sub, i) {
      +    if (!branch[sub]) branch[sub] = {};
      +    if ('object' != typeof branch[sub]) {
      +      var msg = 'Cannot set nested path `' + path + '`. '
      +              + 'Parent path `'
      +              + subpaths.slice(0, i).concat([sub]).join('.')
      +              + '` already set to type ' + branch[sub].name
      +              + '.';
      +      throw new Error(msg);
      +    }
      +    branch = branch[sub];
      +  });
      +
      +  branch[last] = utils.clone(obj);
      +
      +  this.paths[path] = Schema.interpretAsType(path, obj);
      +  return this;
      +};

      Parameters:

      Sets a path (if arity 2)
      Gets a path (if arity 1)

      + +

      Example

      + +
      schema.path('name') // returns a SchemaType
      +schema.path('name', Number) // changes the schemaType of `name` to Number

      Schema#eachPath(fn)

      Iterates the schemas paths similar to Array#forEach.

      show code
      Schema.prototype.eachPath = function (fn) {
      +  var keys = Object.keys(this.paths)
      +    , len = keys.length;
      +
      +  for (var i = 0; i < len; ++i) {
      +    fn(keys[i], this.paths[keys[i]]);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Returns:

      The callback is passed the pathname and schemaType as arguments on each iteration.


      Schema#requiredPaths()

      Returns an Array of path strings that are required by this schema.

      show code
      Schema.prototype.requiredPaths = function requiredPaths () {
      +  if (this._requiredpaths) return this._requiredpaths;
      +
      +  var paths = Object.keys(this.paths)
      +    , i = paths.length
      +    , ret = [];
      +
      +  while (i--) {
      +    var path = paths[i];
      +    if (this.paths[path].isRequired) ret.push(path);
      +  }
      +
      +  return this._requiredpaths = ret;
      +}

      Returns:


      Schema#pathType(path)

      Returns the pathType of path for this schema.

      show code
      Schema.prototype.pathType = function (path) {
      +  if (path in this.paths) return 'real';
      +  if (path in this.virtuals) return 'virtual';
      +  if (path in this.nested) return 'nested';
      +  if (path in this.subpaths) return 'real';
      +
      +  if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
      +    return 'real';
      +  } else {
      +    return 'adhocOrUndefined'
      +  }
      +};

      Parameters:

      Returns:

      Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.


      Schema#queue(name, args)

      Adds a method call to the queue.

      show code
      Schema.prototype.queue = function(name, args){
      +  this.callQueue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the document method to call later
      • args <Array> arguments to pass to the method

      Schema#pre(method, callback)

      Defines a pre hook for the document.

      show code
      Schema.prototype.pre = function(){
      +  return this.queue('pre', arguments);
      +};

      Parameters:

      Example

      + +
      var toySchema = new Schema(..);
      +
      +toySchema.pre('save', function (next) {
      +  if (!this.created) this.created = new Date;
      +  next();
      +})
      +
      +toySchema.pre('validate', function (next) {
      +  if (this.name != 'Woody') this.name = 'Woody';
      +  next();
      +})

      Schema#post(method, fn)

      Defines a post hook for the document.

      show code
      Schema.prototype.post = function(method, fn){
      +  return this.queue('on', arguments);
      +};

      Parameters:

      Post hooks fire on the event emitted from document instances of Models compiled from this schema.

      + +
      var schema = new Schema(..);
      +schema.post('save', function (doc) {
      +  console.log('this fired after a document was saved');
      +});
      +
      +var Model = mongoose.model('Model', schema);
      +
      +var m = new Model(..);
      +m.save(function (err) {
      +  console.log('this fires after the `post` hook');
      +});

      Schema#plugin(plugin, opts)

      Registers a plugin for this schema.

      show code
      Schema.prototype.plugin = function (fn, opts) {
      +  fn(this, opts);
      +  return this;
      +};

      Parameters:


      Schema#method(method, [fn])

      Adds an instance method to documents constructed from Models compiled from this schema.

      show code
      Schema.prototype.method = function (name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.methods[i] = name[i];
      +  else
      +    this.methods[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = kittySchema = new Schema(..);
      +
      +schema.methods.meow = function () {
      +  console.log('meeeeeoooooooooooow');
      +})
      +
      +var Kitty = mongoose.model('Kitty', schema);
      +
      +var fizz = new Kitty;
      +fizz.meow(); // meeeeeooooooooooooow
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      + +
      schema.method({
      +    purr: function () {}
      +  , scratch: function () {}
      +});
      +
      +// later
      +fizz.purr();
      +fizz.scratch();

      Schema#static(name, fn)

      Adds static "class" methods to Models compiled from this schema.

      show code
      Schema.prototype.static = function(name, fn) {
      +  if ('string' != typeof name)
      +    for (var i in name)
      +      this.statics[i] = name[i];
      +  else
      +    this.statics[name] = fn;
      +  return this;
      +};

      Parameters:

      Example

      + +
      var schema = new Schema(..);
      +schema.static('findByName', function (name, callback) {
      +  return this.find({ name: name }, callback);
      +});
      +
      +var Drink = mongoose.model('Drink', schema);
      +Drink.findByName('sanpellegrino', function (err, drinks) {
      +  //
      +});
      + +

      If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.


      Schema#index(fields, [options])

      Defines an index (most likely compound) for this schema.

      show code
      Schema.prototype.index = function (fields, options) {
      +  options || (options = {});
      +
      +  if (options.expires)
      +    utils.expires(options);
      +
      +  this._indexes.push([fields, options]);
      +  return this;
      +};

      Parameters:

      Example

      + +
      schema.index({ first: 1, last: -1 })

      Schema#set(key, [value])

      Sets/gets a schema option.

      show code
      Schema.prototype.set = function (key, value, _tags) {
      +  if (1 === arguments.length) {
      +    return this.options[key];
      +  }
      +
      +  switch (key) {
      +    case 'read':
      +      this.options[key] = utils.readPref(value, _tags)
      +      break;
      +    case 'safe':
      +      this.options[key] = false === value
      +        ? { w: 0 }
      +        : value
      +      break;
      +    default:
      +      this.options[key] = value;
      +  }
      +
      +  return this;
      +}

      Parameters:

      • key <String> option name
      • [value] <Object> if not passed, the current option value is returned

      Schema#get(key)

      Gets a schema option.

      show code
      Schema.prototype.get = function (key) {
      +  return this.options[key];
      +}

      Parameters:


      Schema#indexes()

      Compiles indexes from fields and schema-level indexes

      show code
      Schema.prototype.indexes = function () {
      +  var indexes = []
      +    , seenSchemas = [];
      +
      +  collectIndexes(this);
      +
      +  return indexes;
      +
      +  function collectIndexes (schema, prefix) {
      +    if (~seenSchemas.indexOf(schema)) return;
      +    seenSchemas.push(schema);
      +
      +    var index;
      +    var paths = schema.paths;
      +    prefix = prefix || '';
      +
      +    for (var i in paths) {
      +      if (paths[i]) {
      +        if (paths[i] instanceof Types.DocumentArray) {
      +          collectIndexes(paths[i].schema, i + '.');
      +        } else {
      +          index = paths[i]._index;
      +
      +          if (index !== false && index !== null){
      +            var field = {};
      +            field[prefix + i] = '2d' === index ? index : 1;
      +            var options = 'Object' === index.constructor.name ? index : {};
      +            if (!('background' in options)) options.background = true;
      +            indexes.push([field, options]);
      +          }
      +        }
      +      }
      +    }
      +
      +    if (prefix) {
      +      fixSubIndexPaths(schema, prefix);
      +    } else {
      +      schema._indexes.forEach(function (index) {
      +        if (!('background' in index[1])) index[1].background = true;
      +      });
      +      indexes = indexes.concat(schema._indexes);
      +    }
      +  }

      Schema#virtual(name, [options])

      Creates a virtual type with the given name.

      show code
      Schema.prototype.virtual = function (name, options) {
      +  var virtuals = this.virtuals;
      +  var parts = name.split('.');
      +  return virtuals[name] = parts.reduce(function (mem, part, i) {
      +    mem[part] || (mem[part] = (i === parts.length-1)
      +                            ? new VirtualType(options, name)
      +                            : {});
      +    return mem[part];
      +  }, this.tree);
      +};

      Parameters:

      Returns:


      Schema#virtualpath(name)

      Returns the virtual type with the given name.

      show code
      Schema.prototype.virtualpath = function (name) {
      +  return this.virtuals[name];
      +};

      Parameters:

      Returns:


      Schema#namedScope()

      These still haven't been fixed. Once they're working we'll make them public again.

      show code
      Schema.prototype.namedScope = function (name, fn) {
      +  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
      +    , newScope = Object.create(namedScopes)
      +    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
      +  allScopes[name] = newScope;
      +  newScope.name = name;
      +  newScope.block = fn;
      +  newScope.query = new Query();
      +  newScope.decorate(namedScopes, {
      +    block0: function (block) {
      +      return function () {
      +        block.call(this.query);
      +        return this;
      +      };
      +    },
      +    blockN: function (block) {
      +      return function () {
      +        block.apply(this.query, arguments);
      +        return this;
      +      };
      +    },
      +    basic: function (query) {
      +      return function () {
      +        this.query.find(query);
      +        return this;
      +      };
      +    }
      +  });
      +  return newScope;
      +};

      Schema.reserved

      Reserved document keys.

      show code
      Schema.reserved = Object.create(null);
      +var reserved = Schema.reserved;
      +reserved.on =
      +reserved.db =
      +reserved.init =
      +reserved.isNew =
      +reserved.errors =
      +reserved.schema =
      +reserved.options =
      +reserved.modelName =
      +reserved.collection =
      +reserved.emit =    // EventEmitter
      +reserved._events = // EventEmitter
      +reserved._pres = reserved._posts = 1 // hooks.js

      Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      + +
      on, emit, _events, db, init, isNew, errors, schema, options, modelName, collection, _pres, _posts
      + +

      NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

      + +
      var schema = new Schema(..);
      + schema.methods.init = function () {} // potentially breaking

      Schema.interpretAsType(path, obj)

      Converts type arguments into Mongoose Types.

      show code
      Schema.interpretAsType = function (path, obj) {
      +  if (obj.constructor.name != 'Object')
      +    obj = { type: obj };
      +
      +  // Get the type making sure to allow keys named "type"
      +  // and default to mixed if not specified.
      +  // { type: { type: String, default: 'freshcut' } }
      +  var type = obj.type && !obj.type.type
      +    ? obj.type
      +    : {};
      +
      +  if ('Object' == type.constructor.name || 'mixed' == type) {
      +    return new Types.Mixed(path, obj);
      +  }
      +
      +  if (Array.isArray(type) || Array == type || 'array' == type) {
      +    // if it was specified through { type } look for `cast`
      +    var cast = (Array == type || 'array' == type)
      +      ? obj.cast
      +      : type[0];
      +
      +    if (cast instanceof Schema) {
      +      return new Types.DocumentArray(path, cast, obj);
      +    }
      +
      +    if ('string' == typeof cast) {
      +      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
      +    } else if (cast && (!cast.type || cast.type.type)
      +                    && 'Object' == cast.constructor.name
      +                    && Object.keys(cast).length) {
      +      return new Types.DocumentArray(path, new Schema(cast), obj);
      +    }
      +
      +    return new Types.Array(path, cast || Types.Mixed, obj);
      +  }
      +
      +  var name = 'string' == typeof type
      +    ? type
      +    : type.name;
      +
      +  if (name) {
      +    name = name.charAt(0).toUpperCase() + name.substring(1);
      +  }
      +
      +  if (undefined == Types[name]) {
      +    throw new TypeError('Undefined type at `' + path +
      +        '`
      +  Did you try nesting Schemas? ' +
      +        'You can only nest using refs or arrays.');
      +  }
      +
      +  return new Types[name](path, obj);
      +};

      Parameters:


      Schema.Types

      The various Mongoose Schema Types.

      show code
      Schema.Types = require('./schema/index');

      Example:

      + +

      Example:

      + +
      var mongoose = require('mongoose');
      +var ObjectId = mongoose.Schema.Types.ObjectId;
      + +

      Types:

      + +
        +
      • String
      • +
      • Number
      • +
      • Boolean | Bool
      • +
      • Array
      • +
      • Buffer
      • +
      • Date
      • +
      • ObjectId | Oid
      • +
      • Mixed
      • +
      + +

      Using this exposed access to the Mixed SchemaType, we can use them in our schema.

      + +
      var Mixed = mongoose.Schema.Types.Mixed;
      +new mongoose.Schema({ _user: Mixed })

      Schema#tree

      Schema as a tree

      + +

      Example:

      + +
      {
      +    '_id'     : ObjectId
      +  , 'nested'  : {
      +        'key' : String
      +    }
      +}

      Schema#paths

      Schema as flat paths

      + +

      Example:

      + +
      {
      +    '_id'        : SchemaType,
      +  , 'nested.key' : SchemaType,
      +}

    • schemadefault.js

      exports#system.profile

      Default model for querying the system.profiles collection.


    • schematype.js

      SchemaType(path, [options], [instance])

      SchemaType constructor

      show code
      function SchemaType (path, options, instance) {
      +  this.path = path;
      +  this.instance = instance;
      +  this.validators = [];
      +  this.setters = [];
      +  this.getters = [];
      +  this.options = options;
      +  this._index = null;
      +  this.selected;
      +
      +  for (var i in options) if (this[i] && 'function' == typeof this[i]) {
      +    // { unique: true, index: true }
      +    if ('index' == i && this._index) continue;
      +
      +    var opts = Array.isArray(options[i])
      +      ? options[i]
      +      : [options[i]];
      +
      +    this[i].apply(this, opts);
      +  }
      +};

      Parameters:


      SchemaType#default(val)

      Sets a default value for this SchemaType.

      show code
      SchemaType.prototype.default = function (val) {
      +  if (1 === arguments.length) {
      +    this.defaultValue = typeof val === 'function'
      +      ? val
      +      : this.cast(val);
      +    return this;
      +  } else if (arguments.length > 1) {
      +    this.defaultValue = utils.args(arguments);
      +  }
      +  return this.defaultValue;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var schema = new Schema({ n: { type: Number, default: 10 })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.n) // 10
      + +

      Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

      + +

      Example:

      + +
      // values are cast:
      +var schema = new Schema({ aNumber: Number, default: "4.815162342" })
      +var M = db.model('M', schema)
      +var m = new M;
      +console.log(m.aNumber) // 4.815162342
      +
      +// default unique objects for Mixed types:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default(function () {
      +  return {};
      +});
      +
      +// if we don't use a function to return object literals for Mixed defaults,
      +// each document will receive a reference to the same object literal creating
      +// a "shared" object instance:
      +var schema = new Schema({ mixed: Schema.Types.Mixed });
      +schema.path('mixed').default({});
      +var M = db.model('M', schema);
      +var m1 = new M;
      +m1.mixed.added = 1;
      +console.log(m1.mixed); // { added: 1 }
      +var m2 = new M;
      +console.log(m2.mixed); // { added: 1 }

      SchemaType#index(options)

      Declares the index options for this schematype.

      show code
      SchemaType.prototype.index = function (options) {
      +  this._index = options;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var s = new Schema({ name: { type: String, index: true })
      +var s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
      +Schema.path('my.path').index(true);
      +Schema.path('my.date').index({ expires: 60 });
      +Schema.path('my.path').index({ unique: true, sparse: true });
      + +

      NOTE:

      + +

      Indexes are created in the background by default. Specify background: false to override.

      + +

      Direction doesn't matter for single key indexes


      SchemaType#unique(bool)

      Declares an unique index.

      show code
      SchemaType.prototype.unique = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.unique = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var s = new Schema({ name: { type: String, unique: true })
      +Schema.path('name').index({ unique: true });
      + +

      NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.


      SchemaType#sparse(bool)

      Declares a sparse index.

      show code
      SchemaType.prototype.sparse = function (bool) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.sparse = bool;
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var s = new Schema({ name: { type: String, sparse: true })
      +Schema.path('name').index({ sparse: true });

      SchemaType#expires(when)

      Declares a TTL index (rounded to the nearest second) for Date types only.

      show code
      SchemaType.prototype.expires = function (when) {
      +  if (!this._index || 'Object' !== this._index.constructor.name) {
      +    this._index = {};
      +  }
      +
      +  this._index.expires = when;
      +  utils.expires(this._index);
      +  return this;
      +};

      Parameters:

      Returns:

      This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
      This index type is only compatible with Date types.

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
      + +

      expires utilizes the ms module from guille allowing us to use a friendlier syntax:

      + +

      Example:

      + +
      // expire in 24 hours
      +new Schema({ createdAt: { type: Date, expires: '24h' }});
      +
      +// expire in 1.5 hours
      +new Schema({ createdAt: { type: Date, expires: '1.5h' }});
      +
      +// expire in 7 days
      +var schema = new Schema({ createdAt: Date });
      +schema.path('createdAt').expires('7d');

      SchemaType#set(fn)

      Adds a setter to this schematype.

      show code
      SchemaType.prototype.set = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A setter must be a function.');
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function capitalize (val) {
      +  if ('string' != typeof val) val = '';
      +  return val.charAt(0).toUpperCase() + val.substring(1);
      +}
      +
      +// defining within the schema
      +var s = new Schema({ name: { type: String, set: capitalize }})
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ name: String })
      +s.path('name').set(capitalize)
      + +

      Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

      + +

      You can set up email lower case normalization easily via a Mongoose setter.

      + +
      function toLower (v) {
      +  return v.toLowerCase();
      +}
      +
      +var UserSchema = new Schema({
      +  email: { type: String, set: toLower }
      +})
      +
      +var User = db.model('User', UserSchema)
      +
      +var user = new User({email: 'AVENUE@Q.COM'})
      +console.log(user.email); // 'avenue@q.com'
      +
      +// or
      +var user = new User
      +user.email = 'Avenue@Q.com'
      +console.log(user.email) // 'avenue@q.com'
      +
      + +

      As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

      + +

      NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

      + +
      new Schema({ email: { type: String, lowercase: true }})
      + +

      Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.

      + +
      function inspector (val, schematype) {
      +  if (schematype.options.required) {
      +    return schematype.path + ' is required';
      +  } else {
      +    return val;
      +  }
      +}
      +
      +var VirusSchema = new Schema({
      +  name: { type: String, required: true, set: inspector },
      +  taxonomy: { type: String, set: inspector }
      +})
      +
      +var Virus = db.model('Virus', VirusSchema);
      +var v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });
      +
      +console.log(v.name);     // name is required
      +console.log(v.taxonomy); // Parvovirinae

      SchemaType#get(fn)

      Adds a getter to this schematype.

      show code
      SchemaType.prototype.get = function (fn) {
      +  if ('function' != typeof fn)
      +    throw new Error('A getter must be a function.');
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      function dob (val) {
      +  if (!val) return val;
      +  return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      +}
      +
      +// defining within the schema
      +var s = new Schema({ born: { type: Date, get: dob })
      +
      +// or by retreiving its SchemaType
      +var s = new Schema({ born: Date })
      +s.path('born').get(dob)
      + +

      Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

      + +

      Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

      + +
      function obfuscate (cc) {
      +  return '****-****-****-' + cc.slice(cc.length-4, cc.length);
      +}
      +
      +var AccountSchema = new Schema({
      +  creditCardNumber: { type: String, get: obfuscate }
      +});
      +
      +var Account = db.model('Account', AccountSchema);
      +
      +Account.findById(id, function (err, found) {
      +  console.log(found.creditCardNumber); // '****-****-****-1234'
      +});
      + +

      Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.

      + +
      function inspector (val, schematype) {
      +  if (schematype.options.required) {
      +    return schematype.path + ' is required';
      +  } else {
      +    return schematype.path + ' is not';
      +  }
      +}
      +
      +var VirusSchema = new Schema({
      +  name: { type: String, required: true, get: inspector },
      +  taxonomy: { type: String, get: inspector }
      +})
      +
      +var Virus = db.model('Virus', VirusSchema);
      +
      +Virus.findById(id, function (err, virus) {
      +  console.log(virus.name);     // name is required
      +  console.log(virus.taxonomy); // taxonomy is not
      +})

      SchemaType#validate(obj, [error])

      Adds validator(s) for this document path.

      show code
      SchemaType.prototype.validate = function (obj, error) {
      +  if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
      +    this.validators.push([obj, error]);
      +    return this;
      +  }
      +
      +  var i = arguments.length
      +    , arg
      +
      +  while (i--) {
      +    arg = arguments[i];
      +    if (!(arg && 'Object' == arg.constructor.name)) {
      +      var msg = 'Invalid validator. Received (' + typeof arg + ') '
      +        + arg
      +        + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
      +
      +      throw new Error(msg);
      +    }
      +    this.validate(arg.validator, arg.msg);
      +  }
      +
      +  return this;
      +};

      Parameters:

      Validators always receive the value to validate as their first argument and must return Boolean. Returning false is interpreted as validation failure.

      + +

      Examples:

      + +
      function validator (val) {
      +  return val == 'something';
      +}
      +
      +new Schema({ name: { type: String, validate: validator }});
      +
      +// with a custom error message
      +
      +var custom = [validator, 'validation failed']
      +new Schema({ name: { type: String, validate: custom }});
      +
      +var many = [
      +    { validator: validator, msg: 'uh oh' }
      +  , { validator: fn, msg: 'failed' }
      +]
      +new Schema({ name: { type: String, validate: many }});
      +
      +// or utilizing SchemaType methods directly:
      +
      +var schema = new Schema({ name: 'string' });
      +schema.path('name').validate(validator, 'validation failed');
      + +

      Asynchronous validation:

      + +

      Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The second argument is an callback function that must be passed either true or false when validation is complete.

      + +
      schema.path('name').validate(function (value, respond) {
      +  doStuff(value, function () {
      +    ...
      +    respond(false); // validation failed
      +  })
      + }, 'my error type');
      + +

      You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.

      + +

      Validation occurs pre('save') or whenever you manually execute document#validate.

      + +

      If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

      + +
      var conn = mongoose.createConnection(..);
      +conn.on('error', handleError);
      +
      +var Product = conn.model('Product', yourSchema);
      +var dvd = new Product(..);
      +dvd.save(); // emits error on the `conn` above
      + +

      If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

      + +
      // registering an error listener on the Model lets us handle errors more locally
      +Product.on('error', handleError);

      SchemaType#required(required)

      Adds a required validator to this schematype.

      show code
      SchemaType.prototype.required = function (required) {
      +  var self = this;
      +
      +  function __checkRequired (v) {
      +    // in here, `this` refers to the validating document.
      +    // no validation when this path wasn't selected in the query.
      +    if ('isSelected' in this &&
      +        !this.isSelected(self.path) &&
      +        !this.isModified(self.path)) return true;
      +    return self.checkRequired(v);
      +  }
      +
      +  if (false === required) {
      +    this.isRequired = false;
      +    this.validators = this.validators.filter(function (v) {
      +      return v[0].name !== '__checkRequired';
      +    });
      +  } else {
      +    this.isRequired = true;
      +    this.validators.push([__checkRequired, 'required']);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • required <Boolean> enable/disable the validator

      Returns:

      Example:

      + +
      var s = new Schema({ born: { type: Date, required: true })
      +// or
      +Schema.path('name').required(true);

      SchemaType#getDefault(scope, init)

      Gets the default value

      show code
      SchemaType.prototype.getDefault = function (scope, init) {
      +  var ret = 'function' === typeof this.defaultValue
      +    ? this.defaultValue.call(scope)
      +    : this.defaultValue;
      +
      +  if (null !== ret && undefined !== ret) {
      +    return this.cast(ret, scope, init);
      +  } else {
      +    return ret;
      +  }
      +};

      Parameters:

      • scope <Object> the scope which callback are executed
      • init <Boolean>

      SchemaType#applySetters(value, scope, init)

      Applies setters

      show code
      SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
      +  if (SchemaType._isRef(this, value, init)) return value;
      +
      +  var v = value
      +    , setters = this.setters
      +    , len = setters.length
      +
      +  if (!len) {
      +    if (null === v || undefined === v) return v;
      +    return init
      +      ? v // if we just initialized we dont recast
      +      : this.cast(v, scope, init, priorVal)
      +  }
      +
      +  while (len--) {
      +    v = setters[len].call(scope, v, this);
      +  }
      +
      +  if (null === v || undefined === v) return v;
      +
      +  // do not cast until all setters are applied #665
      +  v = this.cast(v, scope, init, priorVal);
      +
      +  return v;
      +};

      Parameters:


      SchemaType#applyGetters(value, scope)

      Applies getters to a value

      show code
      SchemaType.prototype.applyGetters = function (value, scope) {
      +  if (SchemaType._isRef(this, value, true)) return value;
      +
      +  var v = value
      +    , getters = this.getters
      +    , len = getters.length;
      +
      +  if (!len) {
      +    return v;
      +  }
      +
      +  while (len--) {
      +    v = getters[len].call(scope, v, this);
      +  }
      +
      +  return v;
      +};

      Parameters:


      SchemaType#select(val)

      Sets default select() behavior for this path.

      show code
      SchemaType.prototype.select = function select (val) {
      +  this.selected = !! val;
      +}

      Parameters:

      Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

      + +

      Example:

      + +
      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      +T.find(..); // field x will always be selected ..
      +// .. unless overridden;
      +T.find().select('-x').exec(callback);

      SchemaType#doValidate(value, callback, scope)

      Performs a validation of value using the validators declared for this SchemaType.

      show code
      SchemaType.prototype.doValidate = function (value, fn, scope) {
      +  var err = false
      +    , path = this.path
      +    , count = this.validators.length;
      +
      +  if (!count) return fn(null);
      +
      +  function validate (val, msg) {
      +    if (err) return;
      +    if (val === undefined || val) {
      +      --count || fn(null);
      +    } else {
      +      fn(err = new ValidatorError(path, msg));
      +    }
      +  }
      +
      +  this.validators.forEach(function (v) {
      +    var validator = v[0]
      +      , message   = v[1];
      +
      +    if (validator instanceof RegExp) {
      +      validate(validator.test(value), message);
      +    } else if ('function' === typeof validator) {
      +      if (2 === validator.length) {
      +        validator.call(scope, value, function (val) {
      +          validate(val, message);
      +        });
      +      } else {
      +        validate(validator.call(scope, value), message);
      +      }
      +    }
      +  });
      +};

      Parameters:


      SchemaType._isRef(self, value, init)

      Determines if value is a valid Reference.

      show code
      SchemaType._isRef = function (self, value, init) {
      +  if (init && self.options && self.options.ref) {
      +    if (null == value) return true;
      +    if (value._id && value._id.constructor.name === self.instance) return true;
      +  }
      +
      +  return false;
      +}

      Parameters:

      Returns:


    • types/array.js

      MongooseArray(values, path, doc)

      Mongoose Array constructor.

      show code
      function MongooseArray (values, path, doc) {
      +  var arr = [];
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:

      NOTE:

      + +

      Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.


      MongooseArray#_cast(value)

      Casts a member based on this arrays schema.

      show code
      MongooseArray.prototype._cast = function (value) {
      +  var cast = this._schema.caster.cast
      +    , doc = this._parent;
      +
      +  return cast.call(null, value, doc);
      +};

      Parameters:

      Returns:

      • <value> the casted value

      MongooseArray#_markModified(embeddedDoc, embeddedPath)

      Marks this array as modified.

      show code
      MongooseArray.prototype._markModified = function (elem, embeddedPath) {
      +  var parent = this._parent
      +    , dirtyPath;
      +
      +  if (parent) {
      +    dirtyPath = this._path;
      +
      +    if (arguments.length) {
      +      if (null != embeddedPath) {
      +        // an embedded doc bubbled up the change
      +        dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
      +      } else {
      +        // directly set an index
      +        dirtyPath = dirtyPath + '.' + elem;
      +      }
      +
      +    }
      +    parent.markModified(dirtyPath);
      +  }
      +
      +  return this;
      +};

      Parameters:

      • embeddedDoc <EmbeddedDocument> the embedded doc that invoked this method on the Array
      • embeddedPath <String> the path which changed in the embeddedDoc

      If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)


      MongooseArray#_registerAtomic(op, val)

      Register an atomic operation with the parent.

      show code
      MongooseArray.prototype._registerAtomic = function (op, val) {
      +  if ('$set' == op) {
      +    // $set takes precedence over all other ops.
      +    // mark entire array modified.
      +    this._atomics = { $set: val };
      +    return this;
      +  }
      +
      +  var atomics = this._atomics;
      +
      +  // reset pop/shift after save
      +  if ('$pop' == op && !('$pop' in atomics)) {
      +    var self = this;
      +    this._parent.once('save', function () {
      +      self._popped = self._shifted = null;
      +    });
      +  }
      +
      +  // check for impossible $atomic combos (Mongo denies more than one
      +  // $atomic op on a single path
      +  if (this._atomics.$set ||
      +      Object.keys(atomics).length && !(op in atomics)) {
      +    // a different op was previously registered.
      +    // save the entire thing.
      +    this._atomics = { $set: this };
      +    return this;
      +  }
      +
      +  if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
      +    atomics[op] || (atomics[op] = []);
      +    atomics[op] = atomics[op].concat(val);
      +  } else if (op === '$pullDocs') {
      +    var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
      +      , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
      +    selector['$in'] = selector['$in'].concat(val);
      +  } else {
      +    atomics[op] = val;
      +  }
      +
      +  return this;
      +};

      Parameters:


      MongooseArray#hasAtomics()

      Returns the number of pending atomic operations to send to the db for this array.

      show code
      MongooseArray.prototype.hasAtomics = function hasAtomics () {
      +  if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
      +    return 0;
      +  }
      +
      +  return Object.keys(this._atomics).length;
      +}

      Returns:


      MongooseArray#push([args...])

      Wraps Array#push with proper change tracking.

      show code
      MongooseArray.prototype.push = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +
      +  // $pushAll might be fibbed (could be $push). But it makes it easier to
      +  // handle what could have been $push, $pushAll combos
      +  this._registerAtomic('$pushAll', values);
      +  this._markModified();
      +  return ret;
      +};

      Parameters:


      MongooseArray#nonAtomicPush([args...])

      Pushes items to the array non-atomically.

      show code
      MongooseArray.prototype.nonAtomicPush = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , ret = [].push.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +};

      Parameters:

      • [args...] <any>

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$pop()

      Pops the array atomically at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var popped = doc.array.$pop();
      + console.log(popped); // 3
      + console.log(doc.array); // [1,2]
      +
      + // no affect
      + popped = doc.array.$pop();
      + console.log(doc.array); // [1,2]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $pop works again
      +   popped = doc.array.$pop();
      +   console.log(popped); // 2
      +   console.log(doc.array); // [1]
      + })

      MongooseArray#pop()

      Wraps Array#pop with proper change tracking.

      show code
      MongooseArray.prototype.pop = function () {
      +  var ret = [].pop.call(this);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +};

      Note:

      + +

      marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#$shift()

      Atomically shifts the array at most one time per document save().

      NOTE:

      + +

      Calling this mulitple times on an array before saving sends the same command as calling it once.
      This update is implemented using the MongoDB $pop method which enforces this restriction.

      + +
      doc.array = [1,2,3];
      +
      + var shifted = doc.array.$shift();
      + console.log(shifted); // 1
      + console.log(doc.array); // [2,3]
      +
      + // no affect
      + shifted = doc.array.$shift();
      + console.log(doc.array); // [2,3]
      +
      + doc.save(function (err) {
      +   if (err) return handleError(err);
      +
      +   // we saved, now $shift works again
      +   shifted = doc.array.$shift();
      +   console.log(shifted ); // 2
      +   console.log(doc.array); // [3]
      + })

      MongooseArray#shift()

      Wraps Array#shift with proper change tracking.

      show code
      MongooseArray.prototype.shift = function () {
      +  var ret = [].shift.call(this);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +};

      Example:

      + +
      doc.array = [2,3];
      +var res = doc.array.shift();
      +console.log(res) // 2
      +console.log(doc.array) // [3]
      + +

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#remove([args...])

      Removes items from an array atomically

      show code
      MongooseArray.prototype.remove = function () {
      +  var args = [].map.call(arguments, this._cast, this);
      +  if (args.length == 1)
      +    this.pull(args[0]);
      +  else
      +    this.pull.apply(this, args);
      +  return args;
      +};

      Parameters:

      • [args...] <Object> values to remove

      Examples:

      + +
      doc.array.remove(ObjectId)
      +doc.array.remove('tag 1', 'tag 2')

      MongooseArray#pull([args...])

      Pulls items from the array atomically.

      show code
      MongooseArray.prototype.pull = function () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , cur = this._parent.get(this._path)
      +    , i = cur.length
      +    , mem;
      +
      +  while (i--) {
      +    mem = cur[i];
      +    if (mem instanceof EmbeddedDocument) {
      +      if (values.some(function (v) { return v.equals(mem); } )) {
      +        [].splice.call(cur, i, 1);
      +      }
      +    } else if (~cur.indexOf.call(values, mem)) {
      +      [].splice.call(cur, i, 1);
      +    }
      +  }
      +
      +  if (values[0] instanceof EmbeddedDocument) {
      +    this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
      +  } else {
      +    this._registerAtomic('$pullAll', values);
      +  }
      +
      +  this._markModified();
      +  return this;
      +};

      Parameters:

      • [args...] <any>

      MongooseArray#splice()

      Wraps Array#splice with proper change tracking and casting.

      show code
      MongooseArray.prototype.splice = function splice () {
      +  var ret, vals, i;
      +
      +  if (arguments.length) {
      +    vals = [];
      +    for (i = 0; i < arguments.length; ++i) {
      +      vals[i] = i < 2
      +        ? arguments[i]
      +        : this._cast(arguments[i]);
      +    }
      +    ret = [].splice.apply(this, vals);
      +    this._registerAtomic('$set', this);
      +    this._markModified();
      +  }
      +
      +  return ret;
      +}

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#unshift()

      Wraps Array#unshift with proper change tracking.

      show code
      MongooseArray.prototype.unshift = function () {
      +  var values = [].map.call(arguments, this._cast, this);
      +  [].unshift.apply(this, values);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return this.length;
      +};

      Note:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#sort()

      Wraps Array#sort with proper change tracking.

      show code
      MongooseArray.prototype.sort = function () {
      +  var ret = [].sort.apply(this, arguments);
      +  this._registerAtomic('$set', this);
      +  this._markModified();
      +  return ret;
      +}

      NOTE:

      + +

      marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.


      MongooseArray#addToSet([args...])

      Adds values to the array if not already present.

      show code
      MongooseArray.prototype.addToSet = function addToSet () {
      +  var values = [].map.call(arguments, this._cast, this)
      +    , added = []
      +    , type = values[0] instanceof EmbeddedDocument ? 'doc' :
      +             values[0] instanceof Date ? 'date' :
      +             '';
      +
      +  values.forEach(function (v) {
      +    var found;
      +    switch (type) {
      +      case 'doc':
      +        found = this.some(function(doc){ return doc.equals(v) });
      +        break;
      +      case 'date':
      +        var val = +v;
      +        found = this.some(function(d){ return +d === val });
      +        break;
      +      default:
      +        found = ~this.indexOf(v);
      +    }
      +
      +    if (!found) {
      +      [].push.call(this, v);
      +      this._registerAtomic('$addToSet', v);
      +      this._markModified();
      +      [].push.call(added, v);
      +    }
      +  }, this);
      +
      +  return added;
      +};

      Parameters:

      • [args...] <any>

      Returns:

      • <Array> the values that were added

      Example:

      + +
      console.log(doc.array) // [2,3,4]
      +var added = doc.array.addToSet(4,5);
      +console.log(doc.array) // [2,3,4,5]
      +console.log(added)     // [5]

      MongooseArray#set()

      Sets the casted val at index i and marks the array modified.

      show code
      MongooseArray.prototype.set = function set (i, val) {
      +  this[i] = this._cast(val);
      +  this._markModified(i);
      +  return this;
      +}

      Returns:

      Example:

      + +
      // given documents based on the following
      +var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
      +
      +var doc = new Doc({ array: [2,3,4] })
      +
      +console.log(doc.array) // [2,3,4]
      +
      +doc.array.set(1,"5");
      +console.log(doc.array); // [2,5,4] // properly cast to number
      +doc.save() // the change is saved
      +
      +// VS not using array#set
      +doc.array[1] = "5";
      +console.log(doc.array); // [2,"5",4] // no casting
      +doc.save() // change is not saved

      MongooseArray#toObject(options)

      Returns a native js Array.

      show code
      MongooseArray.prototype.toObject = function (options) {
      +  if (options && options.depopulate && this[0] instanceof Document) {
      +    return this.map(function (doc) {
      +      return doc._id;
      +    });
      +  }
      +
      +  // return this.slice()?
      +  return this.map(function (doc) {
      +    return doc;
      +  });
      +};

      Parameters:

      Returns:


      MongooseArray#inspect()

      Helper for console.log

      show code
      MongooseArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    return ' ' + doc;
      +  }) + ' ]';
      +};

      MongooseArray#indexOf(obj)

      Return the index of obj or -1 if not found.

      show code
      MongooseArray.prototype.indexOf = function indexOf (obj) {
      +  if (obj instanceof ObjectId) obj = obj.toString();
      +  for (var i = 0, len = this.length; i < len; ++i) {
      +    if (obj == this[i])
      +      return i;
      +  }
      +  return -1;
      +};

      Parameters:

      • obj <Object> the item to look for

      Returns:


      MongooseArray#_parent

      Parent owner document


      MongooseArray#_atomics

      Stores a queue of atomic operations to perform


    • types/buffer.js

      MongooseBuffer(value, encode, offset)

      Mongoose Buffer constructor.

      show code
      function MongooseBuffer (value, encode, offset) {
      +  var length = arguments.length;
      +  var val;
      +
      +  if (0 === length || null === arguments[0] || undefined === arguments[0]) {
      +    val = 0;
      +  } else {
      +    val = value;
      +  }
      +
      +  var encoding;
      +  var path;
      +  var doc;
      +
      +  if (Array.isArray(encode)) {
      +    // internal casting
      +    path = encode[0];
      +    doc = encode[1];
      +  } else {
      +    encoding = encode;
      +  }
      +
      +  var buf = new Buffer(val, encoding, offset);
      +  buf.__proto__ = MongooseBuffer.prototype;
      +
      +  // make sure these internal props don't show up in Object.keys()
      +  Object.defineProperties(buf, {
      +      validators: { value: [] }
      +    , _path: { value: path }
      +    , _parent: { value: doc }
      +  });
      +
      +  if (doc && "string" === typeof path) {
      +    Object.defineProperty(buf, '_schema', {
      +        value: doc.schema.path(path)
      +    });
      +  }
      +
      +  return buf;
      +};

      Parameters:

      Inherits:

      Values always have to be passed to the constructor to initialize.


      MongooseBuffer#_markModified()

      Marks this buffer as modified.

      show code
      MongooseBuffer.prototype._markModified = function () {
      +  var parent = this._parent;
      +
      +  if (parent) {
      +    parent.markModified(this._path);
      +  }
      +  return this;
      +};

      MongooseBuffer#write()

      Writes the buffer.

      show code
      MongooseBuffer.prototype.write = function () {
      +  var written = Buffer.prototype.write.apply(this, arguments);
      +
      +  if (written > 0) {
      +    this._markModified();
      +  }
      +
      +  return written;
      +};

      MongooseBuffer#copy(target)

      Copies the buffer.

      show code
      MongooseBuffer.prototype.copy = function (target) {
      +  var ret = Buffer.prototype.copy.apply(this, arguments);
      +
      +  if (target instanceof MongooseBuffer) {
      +    target._markModified();
      +  }
      +
      +  return ret;
      +};

      Parameters:

      Returns:

      Note:

      + +

      Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.


      MongooseBuffer#toObject([subtype])

      Converts this buffer to its Binary type representation.

      show code
      MongooseBuffer.prototype.toObject = function (options) {
      +  var subtype = 'number' == typeof options
      +    ? options
      +    : 0x00;
      +  return new Binary(this, subtype);
      +};

      Parameters:

      • [subtype] <Hex>

      Returns:

      SubTypes:

      + +
        +
      • 0x00: Binary/Generic
      • +
      • 0x01: Function
      • +
      • 0x02: Binary (Deprecated, 0x00 is new default)
      • +
      • 0x03: UUID
      • +
      • 0x04: MD5
      • +
      • 0x80: User Defined
      • +

      MongooseBuffer#equals(other)

      Determines if this buffer is equals to other buffer

      show code
      MongooseBuffer.prototype.equals = function (other) {
      +  if (!Buffer.isBuffer(other)) {
      +    return false;
      +  }
      +
      +  if (this.length !== other.length) {
      +    return false;
      +  }
      +
      +  for (var i = 0; i < this.length; ++i) {
      +    if (this[i] !== other[i]) return false;
      +  }
      +
      +  return true;
      +}

      Parameters:

      Returns:


      MongooseBuffer#_parent

      Parent owner document


    • types/documentarray.js

      MongooseDocumentArray(values, path, doc)

      DocumentArray constructor

      show code
      function MongooseDocumentArray (values, path, doc) {
      +  var arr = [];
      +
      +  // Values always have to be passed to the constructor to initialize, since
      +  // otherwise MongooseArray#push will mark the array as modified to the parent.
      +  arr.push.apply(arr, values);
      +  arr.__proto__ = MongooseDocumentArray.prototype;
      +
      +  arr._atomics = {};
      +  arr.validators = [];
      +  arr._path = path;
      +
      +  if (doc) {
      +    arr._parent = doc;
      +    arr._schema = doc.schema.path(path);
      +    doc.on('save', arr.notify('save'));
      +    doc.on('isNew', arr.notify('isNew'));
      +  }
      +
      +  return arr;
      +};

      Parameters:

      Inherits:


      MongooseDocumentArray#_cast()

      Overrides MongooseArray#cast

      show code
      MongooseDocumentArray.prototype._cast = function (value) {
      +  if (value instanceof this._schema.casterConstructor)
      +    return value;
      +
      +  return new this._schema.casterConstructor(value, this);
      +};

      MongooseDocumentArray#id(id)

      Searches array items for the first document with a matching _id.

      show code
      MongooseDocumentArray.prototype.id = function (id) {
      +  var casted
      +    , _id;
      +
      +  try {
      +    casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
      +  } catch (e) {
      +    casted = null;
      +  }
      +
      +  for (var i = 0, l = this.length; i < l; i++) {
      +    _id = this[i].get('_id');
      +    if (!(_id instanceof ObjectId)) {
      +      if (String(id) == _id)
      +        return this[i];
      +    } else {
      +      if (casted == _id)
      +        return this[i];
      +    }
      +  }
      +
      +  return null;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var embeddedDoc = m.array.id(some_id);

      MongooseDocumentArray#toObject()

      Returns a native js Array of plain js objects

      show code
      MongooseDocumentArray.prototype.toObject = function () {
      +  return this.map(function (doc) {
      +    return doc && doc.toObject() || null;
      +  });
      +};

      Returns:

      NOTE:

      + +

      Each sub-document is converted to a plain object by calling its #toObject method.


      MongooseDocumentArray#inspect()

      Helper for console.log

      show code
      MongooseDocumentArray.prototype.inspect = function () {
      +  return '[' + this.map(function (doc) {
      +    if (doc) {
      +      return doc.inspect
      +        ? doc.inspect()
      +        : util.inspect(doc)
      +    }
      +    return 'null'
      +  }).join('
      +') + ']';
      +};

      MongooseDocumentArray#create(obj)

      Creates a subdocument casted to this schema.

      show code
      MongooseDocumentArray.prototype.create = function (obj) {
      +  return new this._schema.casterConstructor(obj);
      +}

      Parameters:

      • obj <Object> the value to cast to this arrays SubDocument schema

      This is the same subdocument constructor used for casting.


      MongooseDocumentArray#notify(event)

      Creates a fn that notifies all child docs of event.

      show code
      MongooseDocumentArray.prototype.notify = function notify (event) {
      +  var self = this;
      +  return function notify (val) {
      +    var i = self.length;
      +    while (i--) {
      +      if (!self[i]) continue;
      +      self[i].emit(event, val);
      +    }
      +  }
      +}

      Parameters:

      Returns:


    • types/embedded.js

      EmbeddedDocument(obj, parentArr, skipId)

      EmbeddedDocument constructor.

      show code
      function EmbeddedDocument (obj, parentArr, skipId, fields) {
      +  if (parentArr) {
      +    this.__parentArray = parentArr;
      +    this.__parent = parentArr._parent;
      +  } else {
      +    this.__parentArray = undefined;
      +    this.__parent = undefined;
      +  }
      +
      +  Document.call(this, obj, fields, skipId);
      +
      +  var self = this;
      +  this.on('isNew', function (val) {
      +    self.isNew = val;
      +  });
      +};

      Parameters:

      Inherits:


      EmbeddedDocument#markModified(path)

      Marks the embedded doc modified.

      show code
      EmbeddedDocument.prototype.markModified = function (path) {
      +  if (!this.__parentArray) return;
      +
      +  this._activePaths.modify(path);
      +
      +  if (this.isNew) {
      +    // Mark the WHOLE parent array as modified
      +    // if this is a new document (i.e., we are initializing
      +    // a document),
      +    this.__parentArray._markModified();
      +  } else
      +    this.__parentArray._markModified(this, path);
      +};

      Parameters:

      • path <String> the path which changed

      Example:

      + +
      var doc = blogpost.comments.id(hexstring);
      +doc.mixed.type = 'changed';
      +doc.markModified('mixed.type');

      EmbeddedDocument#save([fn])

      Used as a stub for hooks.js

      show code
      EmbeddedDocument.prototype.save = function(fn) {
      +  if (fn)
      +    fn(null);
      +  return this;
      +};

      Parameters:

      Returns:

      NOTE:

      + +

      This is a no-op. Does not actually save the doc to the db.


      EmbeddedDocument#remove([fn])

      Removes the subdocument from its parent array.

      show code
      EmbeddedDocument.prototype.remove = function (fn) {
      +  if (!this.__parentArray) return this;
      +
      +  var _id;
      +  if (!this.willRemove) {
      +    _id = this._doc._id;
      +    if (!_id) {
      +      throw new Error('For your own good, Mongoose does not know ' + 
      +                      'how to remove an EmbeddedDocument that has no _id');
      +    }
      +    this.__parentArray.pull({ _id: _id });
      +    this.willRemove = true;
      +  }
      +
      +  if (fn)
      +    fn(null);
      +
      +  return this;
      +};

      Parameters:


      EmbeddedDocument#update()

      Override #update method of parent documents.

      show code
      EmbeddedDocument.prototype.update = function () {
      +  throw new Error('The #update method is not available on EmbeddedDocuments');
      +}

      EmbeddedDocument#inspect()

      Helper for console.log

      show code
      EmbeddedDocument.prototype.inspect = function () {
      +  return inspect(this.toObject());
      +};

      EmbeddedDocument#invalidate(path, err)

      Marks a path as invalid, causing validation to fail.

      show code
      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
      +  if (!this.__parent) return false;
      +  var index = this.__parentArray.indexOf(this);
      +  var parentPath = this.__parentArray._path;
      +  var fullPath = [parentPath, index, path].join('.');
      +  this.__parent.invalidate(fullPath, err);
      +  if (first)
      +    this._validationError = ownerDocument(this)._validationError;
      +  return true;
      +}

      Parameters:

      • path <String> the field to invalidate
      • err <String, Error> error which states the reason `path` was invalid

      Returns:


      EmbeddedDocument#ownerDocument()

      Returns the top level document of this sub-document.

      show code
      EmbeddedDocument.prototype.ownerDocument = function () {
      +  return ownerDocument(this);
      +}

      Returns:


      EmbeddedDocument#parent()

      Returns this sub-documents parent document.

      show code
      EmbeddedDocument.prototype.parent = function () {
      +  return this.__parent;
      +}

      EmbeddedDocument#parentArray()

      Returns this sub-documents parent array.

      show code
      EmbeddedDocument.prototype.parentArray = function () {
      +  return this.__parentArray;
      +}

    • types/objectid.js

      ObjectId()

      ObjectId type constructor

      Example

      + +
      var id = new mongoose.Types.ObjectId;

      ObjectId.fromString(str)

      Creates an ObjectId from str

      show code
      ObjectId.fromString;

      Parameters:

      Returns:


      ObjectId.toString(oid)

      Converts oid to a string.

      show code
      ObjectId.toString;

      Parameters:

      Returns:


    • utils.js

      exports.toCollectionName(name)

      Produces a collection name from model name.

      show code
      exports.toCollectionName = function (name) {
      +  if ('system.profile' === name) return name;
      +  if ('system.indexes' === name) return name;
      +  return pluralize(name.toLowerCase());
      +};

      Parameters:

      Returns:


      exports.pluralization

      Pluralization rules.

      show code
      exports.pluralization = [
      +  [/(m)an$/gi, '$1en'],
      +  [/(pe)rson$/gi, '$1ople'],
      +  [/(child)$/gi, '$1ren'],
      +  [/^(ox)$/gi, '$1en'],
      +  [/(ax|test)is$/gi, '$1es'],
      +  [/(octop|vir)us$/gi, '$1i'],
      +  [/(alias|status)$/gi, '$1es'],
      +  [/(bu)s$/gi, '$1ses'],
      +  [/(buffal|tomat|potat)o$/gi, '$1oes'],
      +  [/([ti])um$/gi, '$1a'],
      +  [/sis$/gi, 'ses'],
      +  [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
      +  [/(hive)$/gi, '$1s'],
      +  [/([^aeiouy]|qu)y$/gi, '$1ies'],
      +  [/(x|ch|ss|sh)$/gi, '$1es'],
      +  [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
      +  [/([m|l])ouse$/gi, '$1ice'],
      +  [/(quiz)$/gi, '$1zes'],
      +  [/s$/gi, 's'],
      +  [/$/gi, 's']
      +];
      +var rules = exports.pluralization;

      These rules are applied while processing the argument to toCollectionName.


      exports.uncountables

      Uncountable words.

      show code
      exports.uncountables = [
      +  'advice',
      +  'energy',
      +  'excretion',
      +  'digestion',
      +  'cooperation',
      +  'health',
      +  'justice',
      +  'labour',
      +  'machinery',
      +  'equipment',
      +  'information',
      +  'pollution',
      +  'sewage',
      +  'paper',
      +  'money',
      +  'species',
      +  'series',
      +  'rain',
      +  'rice',
      +  'fish',
      +  'sheep',
      +  'moose',
      +  'deer',
      +  'news',
      +  'expertise',
      +  'status',
      +  'media'
      +];
      +var uncountables = exports.uncountables;

      These words are applied while processing the argument to toCollectionName.


      exports.deepEqual(a, b)

      Determines if a and b are deep equal.

      show code
      exports.deepEqual = function deepEqual (a, b) {
      +  if (a === b) return true;
      +
      +  if (a instanceof Date && b instanceof Date)
      +    return a.getTime() === b.getTime();
      +
      +  if (a instanceof ObjectId && b instanceof ObjectId) {
      +    return a.toString() === b.toString();
      +  }
      +
      +  if (a instanceof RegExp && b instanceof RegExp) {
      +    return a.source == b.source &&
      +           a.ignoreCase == b.ignoreCase &&
      +           a.multiline == b.multiline &&
      +           a.global == b.global;
      +  }
      +
      +  if (typeof a !== 'object' && typeof b !== 'object')
      +    return a == b;
      +
      +  if (a === null || b === null || a === undefined || b === undefined)
      +    return false
      +
      +  if (a.prototype !== b.prototype) return false;
      +
      +  // Handle MongooseNumbers
      +  if (a instanceof Number && b instanceof Number) {
      +    return a.valueOf() === b.valueOf();
      +  }
      +
      +  if (Buffer.isBuffer(a)) {
      +    if (!Buffer.isBuffer(b)) return false;
      +    if (a.length !== b.length) return false;
      +    for (var i = 0, len = a.length; i < len; ++i) {
      +      if (a[i] !== b[i]) return false;
      +    }
      +    return true;
      +  }
      +
      +  if (isMongooseObject(a)) a = a.toObject();
      +  if (isMongooseObject(b)) b = b.toObject();
      +
      +  try {
      +    var ka = Object.keys(a),
      +        kb = Object.keys(b),
      +        key, i;
      +  } catch (e) {//happens when one is a string literal and the other isn't
      +    return false;
      +  }
      +
      +  // having the same number of owned properties (keys incorporates
      +  // hasOwnProperty)
      +  if (ka.length != kb.length)
      +    return false;
      +
      +  //the same set of keys (although not necessarily the same order),
      +  ka.sort();
      +  kb.sort();
      +
      +  //~~~cheap key test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    if (ka[i] != kb[i])
      +      return false;
      +  }
      +
      +  //equivalent values for every corresponding key, and
      +  //~~~possibly expensive deep test
      +  for (i = ka.length - 1; i >= 0; i--) {
      +    key = ka[i];
      +    if (!deepEqual(a[key], b[key])) return false;
      +  }
      +
      +  return true;
      +};

      Parameters:

      • a <any> a value to compare to `b`
      • b <any> a value to compare to `a`

      Returns:

      Modified from node/lib/assert.js


      exports.clone(obj, options)

      Object clone with Mongoose natives support.

      show code
      exports.clone = function clone (obj, options) {
      +  if (obj === undefined || obj === null)
      +    return obj;
      +
      +  if (Array.isArray(obj))
      +    return cloneArray(obj, options);
      +
      +  if (isMongooseObject(obj)) {
      +    if (options && options.json && 'function' === typeof obj.toJSON) {
      +      return obj.toJSON(options);
      +    } else {
      +      return obj.toObject(options);
      +    }
      +  }
      +
      +  if ('Object' === obj.constructor.name)
      +    return cloneObject(obj, options);
      +
      +  if ('Date' === obj.constructor.name)
      +    return new obj.constructor(+obj);
      +
      +  if ('RegExp' === obj.constructor.name) {
      +    var flags = [];
      +    if (obj.global) flags.push('g');
      +    if (obj.multiline) flags.push('m');
      +    if (obj.ignoreCase) flags.push('i');
      +    return new RegExp(obj.source, flags.join(''));
      +  }
      +
      +  if (obj instanceof ObjectId)
      +    return new ObjectId(obj.id);
      +
      +  if (obj.valueOf)
      +    return obj.valueOf();
      +};
      +var clone = exports.clone;

      Parameters:

      Returns:

      If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

      + +

      Functions are never cloned.


      exports.options(defaults, options)

      Copies and merges options with defaults.

      show code
      exports.options = function (defaults, options) {
      +  var keys = Object.keys(defaults)
      +    , i = keys.length
      +    , k ;
      +
      +  options = options || {};
      +
      +  while (i--) {
      +    k = keys[i];
      +    if (!(k in options)) {
      +      options[k] = defaults[k];
      +    }
      +  }
      +
      +  return options;
      +};

      Parameters:

      Returns:


      exports.random()

      Generates a random string

      show code
      exports.random = function () {
      +  return Math.random().toString().substr(3);
      +};

      exports.merge(to, from)

      Merges from into to without overwriting existing properties.

      show code
      exports.merge = function merge (to, from) {
      +  var keys = Object.keys(from)
      +    , i = keys.length
      +    , key
      +
      +  while (i--) {
      +    key = keys[i];
      +    if ('undefined' === typeof to[key]) {
      +      to[key] = from[key];
      +    } else {
      +      if (exports.isObject(from[key])) {
      +        merge(to[key], from[key]);
      +      } else {
      +        to[key] = from[key];
      +      }
      +    }
      +  }
      +};

      Parameters:


      exports.isObject(arg)

      Determines if arg is an object.

      show code
      exports.isObject = function (arg) {
      +  return '[object Object]' == toString.call(arg);
      +}

      Parameters:

      Returns:


      exports.args

      A faster Array.prototype.slice.call(arguments) alternative

      show code
      exports.args = sliced;

      exports.tick(callback)

      process.nextTick helper.

      show code
      exports.tick = function tick (callback) {
      +  if ('function' !== typeof callback) return;
      +  return function () {
      +    try {
      +      callback.apply(this, arguments);
      +    } catch (err) {
      +      // only nextTick on err to get out of
      +      // the event loop and avoid state corruption.
      +      process.nextTick(function () {
      +        throw err;
      +      });
      +    }
      +  }
      +}

      Parameters:

      Wraps callback in a try/catch + nextTick.

      + +

      node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.


      exports.isMongooseObject(v)

      Returns if v is a mongoose object that has a toObject() method we can use.

      show code
      exports.isMongooseObject = function (v) {
      +  Document || (Document = require('./document'));
      +  MongooseArray || (MongooseArray = require('./types').Array);
      +  MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
      +
      +  return v instanceof Document ||
      +         v instanceof MongooseArray ||
      +         v instanceof MongooseBuffer
      +}
      +var isMongooseObject = exports.isMongooseObject;

      Parameters:

      This is for compatibility with libs like Date.js which do foolish things to Natives.


      exports.expires(object)

      Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

      show code
      exports.expires = function expires (object) {
      +  if (!(object && 'Object' == object.constructor.name)) return;
      +  if (!('expires' in object)) return;
      +
      +  var when;
      +  if ('string' != typeof object.expires) {
      +    when = object.expires;
      +  } else {
      +    when = Math.round(ms(object.expires) / 1000);
      +  }
      +  object.expireAfterSeconds = when;
      +  delete object.expires;
      +}
      +
      +exports.readPref = function readPref (pref, tags) {
      +  if (Array.isArray(pref)) {
      +    tags = pref[1];
      +    pref = pref[0];
      +  }
      +
      +  switch (pref) {
      +    case 'p':
      +      pref = 'primary';
      +      break;
      +    case 'pp':
      +      pref = 'primaryPrefered';
      +      break;
      +    case 's':
      +      pref = 'secondary';
      +      break;
      +    case 'sp':
      +      pref = 'secondaryPrefered';
      +      break;
      +    case 'n':
      +      pref = 'nearest';
      +      break;
      +  }
      +
      +  return new ReadPref(pref, tags);
      +}

      Parameters:


    • virtualtype.js

      VirtualType()

      VirtualType constructor

      show code
      function VirtualType (options, name) {
      +  this.path = name;
      +  this.getters = [];
      +  this.setters = [];
      +  this.options = options || {};
      +}

      This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

      + +

      Example:

      + +
      var fullname = schema.virtual('fullname');
      +fullname instanceof mongoose.VirtualType // true

      VirtualType#get(fn)

      Defines a getter.

      show code
      VirtualType.prototype.get = function (fn) {
      +  this.getters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.get(function () {
      +  return this.name.first + ' ' + this.name.last;
      +});

      VirtualType#set(fn)

      Defines a setter.

      show code
      VirtualType.prototype.set = function (fn) {
      +  this.setters.push(fn);
      +  return this;
      +};

      Parameters:

      Returns:

      Example:

      + +
      var virtual = schema.virtual('fullname');
      +virtual.set(function (v) {
      +  var parts = v.split(' ');
      +  this.name.first = parts[0];
      +  this.name.last = parts[1];
      +});

      VirtualType#applyGetters(value, scope)

      Applies getters to value using optional scope.

      show code
      VirtualType.prototype.applyGetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.getters.length - 1; l >= 0; l--) {
      +    v = this.getters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all getters

      VirtualType#applySetters(value, scope)

      Applies setters to value using optional scope.

      show code
      VirtualType.prototype.applySetters = function (value, scope) {
      +  var v = value;
      +  for (var l = this.setters.length - 1; l >= 0; l--) {
      +    v = this.setters[l].call(scope, v, this);
      +  }
      +  return v;
      +};

      Parameters:

      Returns:

      • <any> the value after applying all setters

    • collection.js

      Collection(name, conn, opts)

      Abstract Collection constructor

      show code
      function Collection (name, conn, opts) {
      +  this.name = name;
      +  this.conn = conn;
      +  this.buffer = true;
      +  this.queue = [];
      +
      +  if ('number' == typeof opts) opts = { size: opts };
      +  this.opts = opts || {};
      +
      +  if (STATES.connected == this.conn.readyState) {
      +    this.onOpen();
      +  }
      +};

      Parameters:

      • name <String> name of the collection
      • conn <Connection> A MongooseConnection instance
      • opts <Object> optional collection options

      This is the base class that drivers inherit from and implement.


      Collection#onOpen()

      Called when the database connects

      show code
      Collection.prototype.onOpen = function () {
      +  var self = this;
      +  this.buffer = false;
      +  self.doQueue();
      +};

      Collection#onClose()

      Called when the database disconnects

      show code
      Collection.prototype.onClose = function () {
      +  this.buffer = true;
      +};

      Collection#addQueue(name, args)

      Queues a method for later execution when its
      database connection opens.

      show code
      Collection.prototype.addQueue = function (name, args) {
      +  this.queue.push([name, args]);
      +  return this;
      +};

      Parameters:

      • name <String> name of the method to queue
      • args <Array> arguments to pass to the method when executed

      Collection#doQueue()

      Executes all queued methods and clears the queue.

      show code
      Collection.prototype.doQueue = function () {
      +  for (var i = 0, l = this.queue.length; i < l; i++){
      +    this[this.queue[i][0]].apply(this, this.queue[i][1]);
      +  }
      +  this.queue = [];
      +  return this;
      +};

      Collection#ensureIndex()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.ensureIndex = function(){
      +  throw new Error('Collection#ensureIndex unimplemented by driver');
      +};

      Collection#findAndModify()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findAndModify = function(){
      +  throw new Error('Collection#findAndModify unimplemented by driver');
      +};

      Collection#findOne()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.findOne = function(){
      +  throw new Error('Collection#findOne unimplemented by driver');
      +};

      Collection#find()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.find = function(){
      +  throw new Error('Collection#find unimplemented by driver');
      +};

      Collection#insert()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.insert = function(){
      +  throw new Error('Collection#insert unimplemented by driver');
      +};

      Collection#save()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.save = function(){
      +  throw new Error('Collection#save unimplemented by driver');
      +};

      Collection#update()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.update = function(){
      +  throw new Error('Collection#update unimplemented by driver');
      +};

      Collection#getIndexes()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.getIndexes = function(){
      +  throw new Error('Collection#getIndexes unimplemented by driver');
      +};

      Collection#mapReduce()

      Abstract method that drivers must implement.

      show code
      Collection.prototype.mapReduce = function(){
      +  throw new Error('Collection#mapReduce unimplemented by driver');
      +};

      Collection#conn

      The Connection instance


      Collection#name

      The collection name


    diff --git a/docs/3.5.x/docs/connections.html b/docs/3.5.x/docs/connections.html new file mode 100644 index 00000000000..35a0bd237b9 --- /dev/null +++ b/docs/3.5.x/docs/connections.html @@ -0,0 +1,32 @@ +Mongoose Connecting to MongoDB v3.5.9Fork me on GitHub

    Connections

    We may connect to MongoDB by utilizing the mongoose.connect() method.

    mongoose.connect('mongodb://localhost/myapp');
    +

    This is the minimum needed to connect the myapp database running locally on the default port (27017). We may also specify several more parameters in the uri depending on your environment:

    mongoose.connect('mongodb://username:password@host:port/database?options...');
    +

    See the mongodb connection string spec for more detail.

    Options

    The connect method also accepts an options object which will be passed on to the underlying driver. All options included here take precedence over options passed in the connection string.

    mongoose.connect(uri, options);
    +

    The following option keys are available:

    + +
     db      - passed to the connection db instance
    + server  - passed to the connection server instance(s)
    + replset - passed to the connection ReplSet instance
    + user    - username for authentication (if not specified in uri)
    + pass    - password for authentication (if not specified in uri)
    + +

    See the driver for more information about available options.

    + +

    Note: The server option auto_reconnect is defaulted to true.

    + +

    Note: The db option forceServerObjectId is set to false and cannot be overridden.

    ReplicaSet Connections

    The same method is used to connect to a replica set but instead of passing a single uri we pass a comma delimited list of uris.

    mongoose.connect('mongodb://username:password@host:port/database,mongodb://username:password@host:port,mongodb://username:password@host:port?options...' [, options]);
    +

    NOTE: The database need only be specified in one of the uris.

    Multiple connections

    So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize mongoose.createConnection() which accepts all the arguments already discussed and returns a fresh connection for you.

    var conn = mongoose.createConnection('uri,uri,uri...', options);
    +

    Connection pools

    Each connection, whether created with mongoose.connect or mongoose.createConnection are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options:

    var uri = 'mongodb://localhost/test';
    +mongoose.createConnection(uri, { server: { poolSize: 10 }});
    +
    +// or
    +var uri = 'mongodb://localhost/test?poolSize=10';
    +mongoose.createConnection(uri);
    +

    Next Up

    Now that we've covered connections, let's take a look at how we can break pieces of our functionality out into reusable and shareable plugins.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/contributing.html b/docs/3.5.x/docs/contributing.html new file mode 100644 index 00000000000..1cb806450bb --- /dev/null +++ b/docs/3.5.x/docs/contributing.html @@ -0,0 +1,9 @@ +Mongoose Contributing v3.5.9Fork me on GitHub

    Contributing

    Please read all about contributing here.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/css/api.css b/docs/3.5.x/docs/css/api.css new file mode 100644 index 00000000000..6aaae04b23e --- /dev/null +++ b/docs/3.5.x/docs/css/api.css @@ -0,0 +1,244 @@ +body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; +} +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; +} +code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +h3 { + padding: 20px 15px; + margin-left: -15px; +} +h3 code { + font-weight: normal; +} +hr { + height: 1px; + border: 0 none; + padding: 0; + margin: 60px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) +} +.doclinks hr { + margin: 10px 0; +} +li { + list-style: square; +} +#header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +#header .mongoose { + font-size: 48px; + font-weight: 100; + color: #fff; + letter-spacing: -5px; +} +#links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; +} +#links hr { + margin: 32px 0; +} +#content { + padding: 0; + margin: 0 0 30px 230px; + overflow-x: hidden; +} +#content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +#content .controls:hover { + opacity: .9; +} +#content p { + word-wrap: break-word; +} +#content > ul { + margin: 0; + padding: 0; +} +.private { + display: none; +} +.section { + font-size: 15px; +} +.doclinks li.private a:before, +.doclinks .module.private a:before, +.doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; +} +#content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; +} +.module { + list-style: none; + padding: 30px 0 30px 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; +} +.module > * { + max-width: 700px; +} +.item:last-child { + margin-bottom: 90px; +} +.item:last-child > hr { + display: none; +} +.item h3 a { + color: #333; + text-decoration: none; +} +.property h3 span { + color: #444; +} +.description { + margin-top: 25px; +} +.sourcecode { + display: none; +} +.showcode { + font-size: 12px; + cursor: pointer; + display: none; +} +.load .showcode { + display: block; +} +.types a { + text-decoration: none; +} +@media only screen and (device-width: 768px) { + +} +@media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links hr { + display: none; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + .controls { display: none; } +} diff --git a/docs/3.5.x/docs/css/default.css b/docs/3.5.x/docs/css/default.css new file mode 100644 index 00000000000..ccb22728ed3 --- /dev/null +++ b/docs/3.5.x/docs/css/default.css @@ -0,0 +1,135 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +pre code { + display: block; padding: 0.5em; + background: #F0F0F0; +} + +pre code, +pre .ruby .subst, +pre .tag .title, +pre .lisp .title, +pre .clojure .built_in, +pre .nginx .title { + color: black; +} + +pre .string, +pre .title, +pre .constant, +pre .parent, +pre .tag .value, +pre .rules .value, +pre .rules .value .number, +pre .preprocessor, +pre .ruby .symbol, +pre .ruby .symbol .string, +pre .ruby .symbol .keyword, +pre .ruby .symbol .keymethods, +pre .instancevar, +pre .aggregate, +pre .template_tag, +pre .django .variable, +pre .smalltalk .class, +pre .addition, +pre .flow, +pre .stream, +pre .bash .variable, +pre .apache .tag, +pre .apache .cbracket, +pre .tex .command, +pre .tex .special, +pre .erlang_repl .function_or_atom, +pre .markdown .header { + color: #800; +} + +pre .comment, +pre .annotation, +pre .template_comment, +pre .diff .header, +pre .chunk, +pre .markdown .blockquote { + color: #888; +} + +pre .number, +pre .date, +pre .regexp, +pre .literal, +pre .smalltalk .symbol, +pre .smalltalk .char, +pre .go .constant, +pre .change, +pre .markdown .bullet, +pre .markdown .link_url { + color: #080; +} + +pre .label, +pre .javadoc, +pre .ruby .string, +pre .decorator, +pre .filter .argument, +pre .localvars, +pre .array, +pre .attr_selector, +pre .important, +pre .pseudo, +pre .pi, +pre .doctype, +pre .deletion, +pre .envvar, +pre .shebang, +pre .apache .sqbracket, +pre .nginx .built_in, +pre .tex .formula, +pre .erlang_repl .reserved, +pre .input_number, +pre .markdown .link_label, +pre .vhdl .attribute, +pre .clojure .attribute { + color: #88F +} + +pre .keyword, +pre .id, +pre .phpdoc, +pre .title, +pre .built_in, +pre .aggregate, +pre .css .tag, +pre .javadoctag, +pre .phpdoc, +pre .yardoctag, +pre .smalltalk .class, +pre .winutils, +pre .bash .variable, +pre .apache .tag, +pre .go .typename, +pre .tex .command, +pre .markdown .strong, +pre .request, +pre .status { + font-weight: bold; +} + +pre .markdown .emphasis { + font-style: italic; +} + +pre .nginx .built_in { + font-weight: normal; +} + +pre .coffeescript .javascript, +pre .xml .css, +pre .xml .javascript, +pre .xml .vbscript, +pre .tex .formula { + opacity: 0.5; +} diff --git a/docs/3.5.x/docs/css/guide.css b/docs/3.5.x/docs/css/guide.css new file mode 100644 index 00000000000..d18ea6af618 --- /dev/null +++ b/docs/3.5.x/docs/css/guide.css @@ -0,0 +1,332 @@ +html, body, #content { + height: 100%; +} +:target::before { + content: ">>> "; + color: #1371C9; + font-weight: bold; + font-size: 20px; +} +.module { + min-height: 100%; + box-sizing: border-box; + overflow-x: hidden; +} +body { + background: #d8e2d8 url(/docs/images/square_bg.png) fixed; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; + font-size: 14px; + line-height: 22px; +} +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: rgba(255,255,255,.8); + border: 1px solid #bbb; + padding:5px; + border-radius: 3px; + box-shadow: 1px 3px 6px #ddd; +} +code { + background: rgba(255,255,255,.8); + color: #333; + border-radius: 3px; + font-size: 13px; + font-family: Consolas, "Liberation Mono", Courier, monospace; + /*text-shadow: 1px 2px 2px #555;*/ +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +h2 { + margin-top: 0; +} +h2 a { + font-size: 12px; + position: relative; + bottom: 3px; + font-weight: normal; +} +h3 { padding-top: 35px; } +h3 code { + font-weight: normal; +} +hr { + display: none; + height: 1px; + border: 0 none; + padding: 0; + margin: 90px 0; + background: -webkit-gradient(linear, left top, right top, from(rgba(57, 172, 57, 0.0)), color-stop(0.5, rgba(57, 172, 57, 0.33)), to(rgba(57, 172, 57, 0.0))) +} +.doclinks hr { + margin: 10px 0; +} +li { + list-style: square; +} +#header { + padding-top: 22px; + padding-bottom: 25px; + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +#header .mongoose { + font-size: 48px; + font-weight: 100; + color: #fff; + letter-spacing: -5px; +} +#links { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 210px; + overflow-x: hidden; + overflow-y: auto; + padding: 15px 0 30px 20px; + border-right: 1px solid #ddd; + background: -webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; +} +#links .schematypes span { + display: none; +} +#content { + padding: 0; + margin: 0 0 0 230px; +} +#content .controls { + padding: 5px 15px 5px 10px; + position: fixed; + background: #fff; + border: 3px solid #eee; + border-radius: 0 0 12px 0; + border-width: 0 3px 3px 10px; + width: 100%; + bottom: 0; + opacity: 0.75; + -webkit-transition-property: opacity; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +#content .controls:hover { + opacity: .9; +} +#content p { + word-wrap: break-word; +} +#content > ul { + margin: 0; + padding: 0; +} +.private { + display: none; +} +.doclinks li.private a:before, +.doclinks .module.private a:before, +.doclinks item.private a:before { + content: "p"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-right: 5px; +} +#content .private h3:after { + content: "private"; + background: #333; + color: #fff; + font-size: 11px; + line-height: 15px; + font-weight: normal; + padding: 0 2px; + border-radius: 3px; + border: 1px solid #333; + display: inline-block; + margin-left: 5px; +} +.module { + list-style: none; + padding: 30px 0 0 30px; + border-color: #eee; + border-width: 9px 10px; + border-style: solid; + background-color: #fff; +} +.module > * { + max-width: 700px; +} +.item { + margin-bottom: 175px; +} +.item h3 a { + color: #333; + text-decoration: none; +} +.property h3 span { + color: #444; +} +.description { + margin-top: 25px; +} +.sourcecode { + display: none; +} +.showcode { + font-size: 12px; + cursor: pointer; + display: none; +} +.load .showcode { + display: block; +} +.types a { + text-decoration: none; +} +li.guide ul { + padding-left: 16px; +} + +.important { + background-color: #FBFF94; + margin-left: 5px; +} +.important p { + padding: 22px; +} + +ul.inthewild { + margin: 30px 0 0 -30px; + padding: 0; + width: 125%; + max-width: 125%; +} +ul.inthewild li { + display: inline-block; + list-style: none; +} +ul.inthewild img { + width: 200px; +} + +@media only screen and (device-width: 768px) { + ul.inthewild { + margin-left: 0px; + } +} + +@media only screen and (max-width: 480px) { + ul.inthewild { + margin-left: 0px; + } + ul.inthewild li { + margin: 5px; + border-width: 2px 2px 0 2px; + border-style: solid; + border-color: #eee; + } + ul.inthewild li img { + width: 140px; + } + h2 a { + white-space: nowrap; + } + #forkbanner { display: none } + #header .mongoose { + font-size: 65px; + text-align: center; + } + html, body, #content { + height: auto; + } + #links { + position: static; + width: auto; + border: 0 none; + border-right: 0 none; + border-bottom: 1px solid #ddd; + background: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.92, transparent), color-stop(0.9201, rgba(172,172,172, 0.0)), to(rgba(172,172,172, 0.4))), transparent; + padding: 15px 0; + } + #links, #links ul, #links li { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + #links ul { padding: 0 10px 0 0; } + #links li { + list-style: none; + display: inline-block; + width: 25%; + text-align: center; + } + #links .home, #links .support, #links .fork { + display: none; + } + .doclinks { + display: none; + } + #content { margin-left: 0; } + .module { + padding-left: 5px; + border-width: 3px; + } + #links li.guide { + display: block; + width: 390px; + margin-bottom: 15px; + } + #links li.guide > a { + display: none; + } + #links li ul li { + width: 44%; + text-align: left; + } + #links li ul li ul li { + width: 95%; + } + #links .plugins, + #links .changelog { + display: none; + } + #links .schematypes span { + display: inline; + } + #links .double { + width: 332px; + } + #links .double > ul { + display: inline; + float: right; + } + #links .double > ul li { + width: 155px; + } +} diff --git a/docs/3.5.x/docs/css/style.css b/docs/3.5.x/docs/css/style.css new file mode 100644 index 00000000000..5e40d383d58 --- /dev/null +++ b/docs/3.5.x/docs/css/style.css @@ -0,0 +1,255 @@ +body { + font-family: 'Open Sans', Helvetica, Arial, FreeSans; + color: #333; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + padding: 0; + margin: 0; +} + +/* location.hash */ +:target::before { + content: ">>> "; + color: #1371C9; + font-weight: bold; + font-size: 20px; +} +/* ignore home page hash */ +#production:target::before { + content: ""; + font-size: inherit; +} + +a { + color: #800; + -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; + -webkit-transition-duration: 0.15s; + -webkit-transition-timing-function: ease-out; +} +a:hover { + opacity: 0.8; +} +#wrap { + width: 600px; + margin: 0 auto; + position:relative; +} +li { + list-style: square; +} +h1 { + font-family: 'Helvetica Nueue', Helvetica, Arial, FreeSans, sans-serif; + text-rendering: geometricPrecision; +} +pre { + background: #eee; + padding: 5px; + border-radius: 3px; +} +code { + color: #333; + font-size: 11px; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} +pre code { + border: 0 none; + padding: 1.2em; + overflow-x: auto; +} +#header { + text-align: center; + padding-top: 40px; +} +#header, h2, h3, .tagline, .blurb { + text-transform: lowercase; +} +#header h1 { + margin-top: 0; + margin-bottom: 0; +} +#header h1 a { + text-decoration: none; +} +h2 { + margin: 30px 0; +} +h2 a { + font-size: 11px; + position: relative; + bottom: 4px; +} +#header .mongoose { + font-size: 146px; + font-weight: 100; + text-indent: -23px; +} +.load #header .mongoose { + letter-spacing: -14px; +} +.tagline { + color: #333; + font-size: 25px; + text-shadow: 1px 1px #f8f8f8; + text-align: center; + margin: 7px 0; +} +.blurb { + text-align: center; + font-style: oblique; + font-size: 12px; + margin-bottom: 20px; +} +.tagline a, .blurb a { + text-decoration: none; + color: #800; +} +#links { + margin: 50px 10px 20px; + text-align: center; + position: relative; +} +#links ul { + margin: 0; + padding: 0; +} +#links li { + display: inline-block; + margin: 0 15px; + background-color: #FEFEFE; +} +#links a { + background: #444; + padding: 9px 0px; + border-radius: 3px; + color: white; + width: 180px; + display: inline-block; + text-decoration: none; + text-transform: lowercase; + text-shadow: 1px 1px 7px #222; +} +#follow { + margin-bottom: 38px; + margin-left: 109px; +} +#follow ul { + height: 26px; +} +#follow li { + display: inline-block; + font-size: 12px; + margin-right: 12px; +} +#follow #version { + margin: 0 29px 0 10px; +} +#follow #version span { + position: relative; + top: -4px; +} +#production ul { + padding: 0; +} +#production li { + list-style: none; + overflow: hidden; + display: inline-block; + height: 114px; +} +#production img { + width: 180px; + margin: 10px; +} +#production img#mcds { + width: 134px; + margin: 10px 25px; +} +#production a { + -webkit-transition-property: opacity; + -moz-transition-property: opacity; + -o-transition-property: opacity; + transition-property: opacity; + -webkit-transition-duration: 0.25s; + -moz-transition-duration: 0.25s; + -o-transition-duration: 0.25s; + transition-duration: 0.25s; + opacity: 0.7; +} +#production a:hover { + opacity: 1.0; +} +#footer { + text-align: center; + font-size: 12px; + margin-bottom: 20px; +} +@media only screen and (max-width: 480px) { + #forkbanner { display: none } + #header { + padding-top: 12px; + } + #header .mongoose { + text-align: center; + font-size: 65px; + font-weight: 100; + letter-spacing: -7px; + } + .load #header .mongoose { + letter-spacing: -7px; + } + .tagline { + text-align: center; + font-size: 14px; + } + .tagline a { + text-decoration: none; + } + .blurb { + font-size: 16px; + text-align: justify; + margin-top: 25px; + } + #links { + margin-bottom: 40px; + } + #links li { + padding: 8px 2px; + margin: 0 12px; + } + #links a { + background: #444; + padding: 7px 34px; + font-size: 15px; + } + #follow, #docs { margin-left: 0; } + #follow ul { padding-left: 15px } + #follow li { margin-right: 0px } + #follow #version { + margin-left: 5px; + margin-right: 15px; + } + .module { + padding-left: 5px; + border-width: 3px; + } + #wrap { + width: auto; + padding: 0 5px; + } + #production li { + margin-bottom: 8px; + } + #production a { + opacity: 1; + } + #production img { + width: 175px; + } + .addyourown, .addyourown a { + width: 100%; + } +} + +#wrap.homepage #install code, #wrap.homepage #example code { + font-size: 13px; +} diff --git a/docs/3.5.x/docs/documents.html b/docs/3.5.x/docs/documents.html new file mode 100644 index 00000000000..cfb86afdc35 --- /dev/null +++ b/docs/3.5.x/docs/documents.html @@ -0,0 +1,20 @@ +Mongoose Documents v3.5.9Fork me on GitHub

    Documents

    Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.

    Retrieving

    There are many ways to retrieve documents from MongoDB. We won't cover that in this section. See the chapter on querying for detail.

    Updating

    There are a number of ways to update documents. We'll first look at a traditional approach using findById:

    Tank.findById(id, function (err, tank) {
    +  if (err) return handleError(err);
    +  
    +  tank.size = 'large';
    +  tank.save(function (err) {
    +    if (err) return handleError(err);
    +    res.send(tank);
    +  });
    +});

    This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save). However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

    If we do need the document returned in our application there is another, often better, option:

    Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
    +  if (err) return handleError(err);
    +  res.send(tank);
    +});

    The findAndUpdate/Remove static methods all make a change to at most one document, and return it with just one call to the database. There are several variations on the findAndModify theme. Read the API docs for more detail.

    Validating

    Documents are validated before they are saved. Read the api docs or the validation chapter for detail.

    Next Up

    Now that we've covered Documents, let's take a look at Sub-documents.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/faq.html b/docs/3.5.x/docs/faq.html new file mode 100644 index 00000000000..f8e0616ab2b --- /dev/null +++ b/docs/3.5.x/docs/faq.html @@ -0,0 +1,31 @@ +Mongoose FAQ v3.5.9Fork me on GitHub

    FAQ

    Q. Why don't my changes to arrays get saved when I update an element directly?

    doc.array[3] = 'changed';
    +doc.save();

    A. Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to first mark the path of the array modified before saving.

    doc.markModified('array');
    +doc.save();

    Q. Why doesn't mongoose allow me to directly assign schemas to paths?

    var userSchema = new Schema({ name: String });
    +new Schema({ user: userSchema })

    A. Schemas have a one-to-one mapping with documents. Documents have save and remove methods along with their own pre and post hooks which would lead to code like the following:

    doc.user.save();  // ?
    +doc.user.remove();// ?
    +doc.save()

    We've felt that this api would be more confusing than helpful. The counter argument is that arrays of sub-documents already have this functionality, but at best this too leads to confusion (calling save on a sub-document is a no-op and exists only to support pre save hooks). In the future this is likely to be revisited.


    Q. How can I enable debugging?

    + +

    A. Set the debug option to true:

    mongoose.set('debug', true)

    Q. My save() callback never executes. What am I doing wrong?

    + +

    A. All collection actions (insert, remove, queries, etc) are queued until the connection opens. It is likely that an error occurred while attempting to connect. Try adding an error handler to your connection.

    // if connecting on the default mongoose connection
    +mongoose.connect(..);
    +mongoose.connection.on('error', handleError);
    +
    +// if connecting on a separate connection
    +var conn = mongoose.createConnection(..);
    +conn.on('error', handleError);
    +

    Something to add?

    + +

    If you'd like to contribute to this page, please visit it on github and use the Edit button to send a pull request.


    \ No newline at end of file diff --git a/docs/3.5.x/docs/guide.html b/docs/3.5.x/docs/guide.html new file mode 100644 index 00000000000..47fdc94d50f --- /dev/null +++ b/docs/3.5.x/docs/guide.html @@ -0,0 +1,200 @@ +Mongoose Schemas v3.5.9Fork me on GitHub

    Schemas

    If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works. +If you are migrating from 2.x to 3.x please take a moment to read the migration guide.

    This page covers Schema definition, plugins, instance methods, statics, indexes, virtuals and options. Let's start with Schema definition.

    Defining your schema

    Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

    var blogSchema = new Schema({
    +  title:  String,
    +  author: String,
    +  body:   String,
    +  comments: [{ body: String, date: Date }],
    +  date: { type: Date, default: Date.now },
    +  hidden: Boolean,
    +  meta: {
    +    votes: Number,
    +    favs:  Number
    +  }
    +});

    If you want to add additional keys later, use the Schema#add method.

    +Each key in our blogSchema defines a property in our documents which will be cast to its associated SchemaType. For example, we've defined a title which will be cast to the String SchemaType and date which will be cast to a Date SchemaType. +Keys may also be assigned nested objects containing further key/type definitions (e.g. the `meta` property above).

    The permitted SchemaTypes are

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array
    Read more about them here.

    Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.

    Pluggable

    Schemas are pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.

    Instance methods

    Models are just fancy constructor functions. As such they can have prototype methods inherited by their instances. In the case of Mongoose, instances are documents.

    Defining an instance method is easy.

    var animalSchema = new Schema({ name: String, type: String });
    +
    +animalSchema.methods.findSimilarTypes = function (cb) {
    +  return this.model('Animal').find({ type: this.type }, cb);
    +}

    Now all of our animal instances have a findSimilarTypes method available to it.

    var Animal = mongoose.model('Animal', animalSchema);
    +var dog = new Animal({ type: 'dog' });
    +
    +dog.findSimilarTypes(function (err, dogs) {
    +  console.log(dogs); // woof
    +});

    Statics

    +Adding static constructor methods to Models is simple as well. Continuing with our animalSchema:

    animalSchema.statics.findByName = function (name, cb) {
    +  this.find({ name: new RegExp(name, 'i') }, cb);
    +}
    +
    +var Animal = mongoose.model('Animal', animalSchema);
    +Animal.findByName('fido', function (err, animals) {
    +  console.log(animals);
    +});

    Indexes

    Indexes can be defined at the path level or the schema level. Defining indexes at the schema level is necessary when defining compound indexes.

    animalSchema.index({ name: 1, type: -1 });
    +

    When your application starts up, Mongoose automatically calls ensureIndex for each defined index in your schema. +While nice for development, it is recommended this behavior be disabled in production since index creation can cause a significant performance impact. Disable the behavior by setting the autoIndex option of your schema to false.

    animalSchema.set('autoIndex', false);
    +// or
    +new Schema({..}, { autoIndex: false });
    +

    See also the Model#ensureIndexes method.

    Virtuals

    Virtual attributes are attributes that are convenient to have around but that do not get persisted to MongoDB.

    var personSchema = new Schema({
    +  name: {
    +    first: String,
    +    last: String
    +  }
    +});
    +
    +var Person = mongoose.model('Person', personSchema);
    +
    +var bad = new Person({
    +    name: { first: 'Walter', last: 'White' }
    +});

    Suppose we want to log the full name of bad. We could do this manually like so:

    console.log(bad.name.first + ' ' + bad.name.last); // Walter White

    Or we could add a virtual attribute getter to our personSchema so we don't need to write out this string concatenation mess each time:

    personSchema.virtual('name.full').get(function () {
    +  return this.name.first + ' ' + this.name.last;
    +});

    Now, when we access our virtual full name property, our getter function will be invoked and the value returned:

    console.log('%s is insane', bad.name.full); // Walter White is insane

    It would also be nice to be able to set this.name.first and this.name.last by setting this.name.full. For example, if we wanted to change bad's name.first and name.last to 'Breaking' and 'Bad' respectively, it'd be nice to just:

    bad.name.full = 'Breaking Bad';

    Mongoose let's you do this as well through its virtual attribute setters:

    personSchema.virtual('name.full').set(function (name) {
    +  var split = name.split(' ');
    +  this.name.first = split[0];
    +  this.name.last = split[1];
    +});
    +
    +...
    +
    +mad.name.full = 'Breaking Bad';
    +console.log(mad.name.first); // Breaking

    If you need attributes that you can get and set but that are not themselves persisted to MongoDB, virtual attributes is the Mongoose feature for you.

    Options

    Schemas have a few configurable options which can be passed to the constructor or set directly:

    new Schema({..}, options);
    +
    +// or
    +
    +var schema = new Schema({..});
    +schema.set(option, value);
    +

    Valid options:

    + +

    option: autoIndex

    At application startup, Mongoose sends an ensureIndex command for each index declared in your Schema. As of Mongoose v3, indexes are created in the background by default. If you wish to disable the auto-creation feature and manually handle when indexes are created, set your Schemas autoIndex option to false and use the ensureIndexes method on your model.

    var schema = new Schema({..}, { autoIndex: false });
    +var Clock = mongoose.model('Clock', schema);
    +Clock.ensureIndexes(callback);
    +

    option: capped

    Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be capped, set the capped option to the maximum size of the collection in bytes.

    new Schema({..}, { capped: 1024 });

    The capped option may also be set to an object if you want to pass additional options like max or autoIndexId. In this case you must explicitly pass the size option which is required.

    new Schema({..}, { capped: { size: 1024, max: 1000, autoIndexId: true } });
    +

    option: collection

    Mongoose by default produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. Set this option if you need a different name for your collection.

    var dataSchema = new Schema({..}, { collection: 'data' });
    +

    option: id

    Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = mongoose.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // '50341373e894ad16347efe01'
    +
    +// disabled id
    +var schema = new Schema({ name: String }, { id: false });
    +var Page = mongoose.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p.id); // undefined
    +

    option: _id

    Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assiged is an ObjectId to coincide with MongoDBs default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.

    + +

    Pass this option during schema construction to prevent documents from getting an _id auto created by Mongoose (parent documents will still have an _id created by MongoDB when inserted).

    // default behavior
    +var schema = new Schema({ name: String });
    +var Page = mongoose.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
    +
    +// disabled _id
    +var schema = new Schema({ name: String }, { _id: false });
    +var Page = mongoose.model('Page', schema);
    +var p = new Page({ name: 'mongodb.org' });
    +console.log(p); // { name: 'mongodb.org' }
    +// MongoDB will create the _id when inserted
    +p.save(function (err) {
    +  if (err) return handleError(err);
    +  Page.findById(p, function (err, doc) {
    +    if (err) return handleError(err);
    +    console.log(doc); // { name: 'mongodb.org', _id: '50341373e894ad16347efe12' }
    +  })
    +})
    +

    option: read

    Allows setting query#read options at the schema level, providing us a way to apply default ReadPreferences to all queries derived from a model.

    var schema = new Schema({..}, { read: 'primary' });            // also aliased as 'p'
    +var schema = new Schema({..}, { read: 'primaryPreferred' });   // aliased as 'pp'
    +var schema = new Schema({..}, { read: 'secondary' });          // aliased as 's'
    +var schema = new Schema({..}, { read: 'secondaryPreferred' }); // aliased as 'sp'
    +var schema = new Schema({..}, { read: 'nearest' });            // aliased as 'n'
    +

    The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'.

    + +

    The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets here and here.

    + +

    NOTE: if you specify the read pref 'nearest', you must also pass the strategy option when connecting or your reads will not behave predictably:

    // pings the replset members periodically to track network latency
    +// now `nearest` works as intended
    +var options = { replset: { strategy: 'ping' }};
    +mongoose.connect(uri, options);
    +
    +var schema = new Schema({..}, { read: ['n', { disk: 'ssd' }] });
    +mongoose.model('JellyBean', schema);
    +

    option: safe

    This option is passed to MongoDB with all operations and let's us specify if errors should be returned to our callbacks as well as tune write behavior.

    var safe = true;
    +new Schema({ .. }, { safe: safe });
    +

    By default this is set to true for all schemas which guarentees that any occurring error gets passed back to our callback. +By setting safe to something else like { j: 1, w: 2, wtimeout: 10000 } we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback.

    + +

    **NOTE: this setting overrides any setting specified by passing db options while creating a connection.

    + +

    There are other write concerns like { w: "majority" } too. See the MongoDB docs for more details.

    var safe = { w: "majority", wtimeout: 10000 };
    +new Schema({ .. }, { safe: safe });
    +

    option: shardKey

    The shardKey option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.

    new Schema({ .. }, { shardkey: { tag: 1, name: 1 }})
    +

    Note that Mongoose does not send the shardcollection command for you. You must configure your shards yourself.

    option: strict

    The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.

    var thingSchema = new Schema({..})
    +var Thing = mongoose.model('Thing', schemaSchema);
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save(); // iAmNotInTheSchema is not saved to the db
    +
    +// set to false..
    +var thingSchema = new Schema({..}, { strict: false });
    +var thing = new Thing({ iAmNotInTheSchema: true });
    +thing.save(); // iAmNotInTheSchema is now saved to the db!!
    +

    This also affects the use of doc.set() to set a property value.

    var thingSchema = new Schema({..})
    +var Thing = mongoose.model('Thing', schemaSchema);
    +var thing = new Thing;
    +thing.set('iAmNotInTheSchema', true);
    +thing.save(); // iAmNotInTheSchema is not saved to the db
    +

    This value can be overridden at the model instance level by passing a second boolean argument:

    var Thing = mongoose.model('Thing');
    +var thing = new Thing(doc, true);  // enables strict mode
    +var thing = new Thing(doc, false); // disables strict mode
    +

    The strict option may also be set to "throw" which will cause errors to be produced instead of dropping the bad data.

    NOTE: do not set to false unless you have good reason.

    + +

    NOTE: in mongoose v2 the default was false.

    + +

    NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.

    var thingSchema = new Schema({..})
    +var Thing = mongoose.model('Thing', schemaSchema);
    +var thing = new Thing;
    +thing.iAmNotInTheSchema = true;
    +thing.save(); // iAmNotInTheSchema is never saved to the db
    +

    option: toJSON

    Exactly the same as the toObject option but only applies when the documents toJSON method is called.

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toJSON', { getters: true, virtuals: false });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
    +console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +// since we know toJSON is called whenever a js object is stringified:
    +console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
    +

    To see all available toJSON/toObject options, read this.

    option: toObject

    Documents have a toObject method which converts the mongoose document into a plain javascript object. This method accepts a few options. Instead of applying these options on a per-document basis we may declare the options here and have it applied to all of this schemas documents by default.

    + +

    To have all virtuals show up in your console.log output, set the toObject option to { getters: true }:

    var schema = new Schema({ name: String });
    +schema.path('name').get(function (v) {
    +  return v + ' is my name';
    +});
    +schema.set('toObject', { getters: true });
    +var M = mongoose.model('Person', schema);
    +var m = new M({ name: 'Max Headroom' });
    +console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
    +

    To see all available toObject options, read this.

    option: versionKey

    The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable. The default is __v. If this conflicts with your application you can configure as such:

    var schema = new Schema({ name: 'string' });
    +var Thing = mongoose.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { __v: 0, name: 'mongoose v3' }
    +
    +// customized versionKey
    +new Schema({..}, { versionKey: '_somethingElse' })
    +var Thing = mongoose.model('Thing', schema);
    +var thing = new Thing({ name: 'mongoose v3' });
    +thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
    +

    Document versioning can also be disabled by setting the versionKey to false. DO NOT disable versioning unless you know what you are doing.

    new Schema({..}, { versionKey: false });
    +var Thing = mongoose.model('Thing', schema);
    +var thing = new Thing({ name: 'no versioning please' });
    +thing.save(); // { name: 'no versioning please' }
    +
    +

    Next Up

    Now that we've covered Schemas, let's take a look at SchemaTypes.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/helpers/filters.js b/docs/3.5.x/docs/helpers/filters.js new file mode 100644 index 00000000000..33546a7e805 --- /dev/null +++ b/docs/3.5.x/docs/helpers/filters.js @@ -0,0 +1,20 @@ + +var hl = require('highlight.js') + +module.exports = exports = function (jade) { + // add highlighting filter to jade + + jade.filters.js = function (str) { + str = str.replace(/\\n/g, '\n'); + var ret = hl.highlight('javascript', str).value; + var code = '
    ' + ret.replace(/\n/g, '\\n') + '
    '; + return code; + } + + jade.filters.bash = function (str) { + var ret = hl.highlight('bash', str.replace(/\\n/g, '\n')).value; + var code = '
    ' + ret + '
    '; + return code + } + +} diff --git a/docs/3.5.x/docs/helpers/highlight.js b/docs/3.5.x/docs/helpers/highlight.js new file mode 100644 index 00000000000..8aca9b9e222 --- /dev/null +++ b/docs/3.5.x/docs/helpers/highlight.js @@ -0,0 +1,11 @@ + +var h = require('highlight.js') + +function hl (str) { + str = str.replace(/\\n/g, '\n'); + var ret = h.highlight('javascript', str).value; + var code = '
    ' + ret+ '
    '; + return code; +} + +module.exports = hl; diff --git a/docs/3.5.x/docs/helpers/href.js b/docs/3.5.x/docs/helpers/href.js new file mode 100644 index 00000000000..e6d6568b123 --- /dev/null +++ b/docs/3.5.x/docs/helpers/href.js @@ -0,0 +1,8 @@ + +module.exports = exports = function (str, char) { + if ('string' != typeof str) return str; + return encodeURIComponent( + str.replace(/\.js$/, '') + .replace(/#/g, char || '-') + ); +} diff --git a/docs/3.5.x/docs/helpers/klass.js b/docs/3.5.x/docs/helpers/klass.js new file mode 100644 index 00000000000..0c4a865b43b --- /dev/null +++ b/docs/3.5.x/docs/helpers/klass.js @@ -0,0 +1,5 @@ + +module.exports = exports = function (str) { + var parts = str.replace(/\.js$/, '').split('/'); + return parts.join('_'); +} diff --git a/docs/3.5.x/docs/helpers/linktype.js b/docs/3.5.x/docs/helpers/linktype.js new file mode 100644 index 00000000000..997e740f671 --- /dev/null +++ b/docs/3.5.x/docs/helpers/linktype.js @@ -0,0 +1,50 @@ + +var types = {}; +types.Object = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object'; +types.Boolean = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Boolean' +types.String = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' +types.Array = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array' +types.Number = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number' +types.Date = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date' +types.Function = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' +types.RegExp = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp' +types.Error = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error' +types['undefined'] = 'https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined' + +// mongoose +types.ObjectId = '#types_objectid_ObjectId'; +types.MongooseDocumentArray = '#types_documentarray_MongooseDocumentArray'; +types.MongooseArray = '#types_array_MongooseArray'; +types.Binary = 'https://github.com/mongodb/js-bson/blob/master/lib/bson/binary.js'; +types.Query = '#query-js'; +types.QueryStream = '#querystream_QueryStream'; +types.Document = '#document_Document'; +types.EmbeddedDocument = '#types_embedded_EmbeddedDocument'; +types.Document = '#document_Document'; +types.Model = '#model_Model'; +types.Connection = '#connection_Connection'; +types.Collection = '#collection_Collection'; +types.Schema = '#schema_Schema'; +types.Promise = '#promise_Promise'; +types.Mongoose = '#index_Mongoose'; +types.MongooseError = '#error_MongooseError'; +types.Type = '#schematype_SchemaType'; // ? +types.SchemaType = '#schematype_SchemaType'; +types.SchemaArray = '#schema_array_SchemaArray'; +types.Mixed = '#schema_mixed_Mixed'; +types.VirtualType = '#virtualtype_VirtualType'; +types.MongooseBuffer = '#types_buffer_MongooseBuffer'; +types.Buffer = 'http://nodejs.org/api/buffer.html'; + +module.exports= function (type) { + if (types[type]) { + return '' + type + ''; + } + return '' + type + ''; +} + +module.exports.types = types; +module.exports.type = function (str) { + if (types[str]) return types[str]; + return str; +} diff --git a/docs/3.5.x/docs/images/apps/attictv.png b/docs/3.5.x/docs/images/apps/attictv.png new file mode 100644 index 0000000000000000000000000000000000000000..1327f0bd858cf6f002a077a9aafba1217ce38e9c GIT binary patch literal 42666 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 Cl*SPN literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/calllist.png b/docs/3.5.x/docs/images/apps/calllist.png new file mode 100644 index 0000000000000000000000000000000000000000..824fa428eb2de2a237b37ada591cc7056d68f399 GIT binary patch literal 33502 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 $5C9j=SSd5$;KOc+eQQ2^5$rlF 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/cldfy.png b/docs/3.5.x/docs/images/apps/cldfy.png new file mode 100644 index 0000000000000000000000000000000000000000..c44ca3525daa7b847ab2869d44a00ebae852646d GIT binary patch literal 9773 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 AJOBUy literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/clickdummy.png b/docs/3.5.x/docs/images/apps/clickdummy.png new file mode 100644 index 0000000000000000000000000000000000000000..773ce3ec638a72dd3eb7ab6d103dade3874fa53e GIT binary patch literal 34210 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 O0000=x}o)VD=23xZGidKsJj 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

    &}XJ7y^uLKL|l(=^=~M7SI1ZoeQx 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

  • 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 Q6aWAK07*qoM6N<$g5iQW;Q#;t literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/furbabyrescue.png b/docs/3.5.x/docs/images/apps/furbabyrescue.png new file mode 100644 index 0000000000000000000000000000000000000000..79dafc640738444c01883ac66e8f0f2584a45a57 GIT binary patch literal 49891 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/geeklist.png b/docs/3.5.x/docs/images/apps/geeklist.png new file mode 100644 index 0000000000000000000000000000000000000000..c6579c12f6f37e10ab1a3f667e33f70fbdc87173 GIT binary patch literal 27911 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 /dev/null + then + echo waiting for manual firefox shutdown... + fi + + while true; do + if ps ax | grep -v grep | grep firefox > /dev/null + then + sleep 1 + else + break + fi + done + echo firefox shutdown detected +} + +if test -z "$1" +then + while read line + do + func $line + done < urls +else + func $1 "$2" +fi + diff --git a/docs/3.5.x/docs/images/apps/growthegamegolf.png b/docs/3.5.x/docs/images/apps/growthegamegolf.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d6e9fb7493ce38c487cb2f31416838fe063bb6 GIT binary patch literal 43441 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/h_learnboost.png b/docs/3.5.x/docs/images/apps/h_learnboost.png new file mode 100644 index 0000000000000000000000000000000000000000..2940dc31489e2f0db0857ecf2c32a2dabb907b69 GIT binary patch literal 12727 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/h_mcds.png b/docs/3.5.x/docs/images/apps/h_mcds.png new file mode 100644 index 0000000000000000000000000000000000000000..1ac655377ad9e784895c1d0ac1e74d46d4949752 GIT binary patch literal 3904 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 O0000D_X* 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/knack.png b/docs/3.5.x/docs/images/apps/knack.png new file mode 100644 index 0000000000000000000000000000000000000000..f08fcdbaf24289861c424c5816c2c3959fd9f0dd GIT binary patch literal 29572 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 Z_6Wh^+jflZ#s50AmE_c9tHEX={|Dh$?!W*5 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/kyyti.png b/docs/3.5.x/docs/images/apps/kyyti.png new file mode 100644 index 0000000000000000000000000000000000000000..f74d98da1346a95376b33f6bc6118e8864261b4b GIT binary patch literal 41966 zcmV)UK(N1wP)=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81fB;EEK~#9!?EU$(W!aVAhkf>V&bjk_ z^UKW2Dr6PV0J;G*dLWw=hY%@=lY^4NqOE_x5f15Jvi+Mv5oXwywMQQYfkjR z|L}WH-dOjFxVgm$2=Un$6uaLF@!T)_vTpjze$T5+_7`zoU&niY`t`5+-aij>qQCv| z?8Wa;5?N$~#rlZ_za25ApT~$86o4QuZ@l)VvBamoKx}^g3qH{oz4z%Eg;$&5&wB0a zy!Umk`E|bM7kxIL_d0&jYkJw7{36fl3%d9241fsQJOBK5#)upaQGfM^xPS7mKr5&l zPzt1mwgIECzxiGKY)N=@21*f{282Wu8KRd15H9A(K@L)alGwlg8`S^r-zBcAU*L{@ zk*D!Re8(4kEx)Ym`aBNI>s?m_f;EWX5iTT;BZTCD2oO(gvQY@45{QsI6cNJqyJGiR zvDt*5{w^sAMj`7qy`yt`gb(SvHj7@%^p_A{`gxn7L)%_Ir_Ei7?gP9>eB&7N5B~=K zryn7E1!B|(7YUb_$lVFzXb*KcL$obIYg|ha%JcZF-#u*~uY2#$ zy9Oe0GQ$7bTTocy#U)gpP}LA3Vmw6Oe~dhxr@0q`@WWrh_chFxMCXZBi(Zuw1>w#< zYQ2I7SE$y55Z4=Oh=h0EzDaW-zv&Q(&Y=#b&@|Nl&woY#fA?SDKKPXOcYj3jzyC+n|Ls44vcX?n zA&o*9h5qh6$Sm%s9}s^09vFk%9U^w8w150_{K*yW!w0yF894WvGw~PWYd>O4o`G|S zVuZYN06RN)Ef7*5<`q0VAvSGi7!on)BL^Dxr%*Sz<6Yunfp8L`Br&!yIwAi4dmts- zH5(!jQFTlF&F>HdsKyZ+j~nO6WsM*9kymp>>k&s&LIBYQ80Ex&@rN%w0Ci~HlQ*?F zUP44HO3MG{{{?k}GzOMS+@HLMznCHBE82HI!c8v7e)t{yPd~ytNAvDSAO-4hhxYwP z=@j|oA>v>EA+dD0j~}7me}H-WP3qtOlP8a}7wul#Smq@Y@}k}K<~=^7i`Hd+tHuCr_a3pr>^5w@BOo`>zVgGeZQYIC(k)H9-JUt3xD)8A_DI0 zV;)_m*ZM$Qu8Gd2_X!aH;`b1_A!-eKBlQ3Dr{Dv)fRNn zpobPAEqbjnN~=t zzWD~_Kl#@bf9*H$>x%k!f7IRFQxEdyd$*qz(oPaPq)W+X1M(M*U)06HVa{xh1A>EDGb?at7 zm9>5Gb9ph&u_62XVo&Jhi9hjm+9-}=**Hrb8Xz8&lpK}Q4=M7dgs0f8ESUAVtxZ=F*;{xnX2P{g* zqV-(X5tCVN4;0RMq5y3(Y^DgoQ@I)!HE-ICTsnlzDSgS=>Jct3iFnX=F`{5H>LuW@ zV^653V9gEE?%I~NZON>`7{g*!asQ%4E5W2M$?XJd4VkvYkn<lPY?rwn+BeXJ{FC1knD60Xr3xo(C zpVeeW(#sU<#`AFIa8a<+Hw=u!#)hU*SQ8odBCAHwwjPr!v@}%p8FP0Z@C@w^Z%lKt ztUyXZ>jOlwh5Da%O;68GDXS#}$#k+qUi2CC6>qAVhnE%aKCEdy*%+QGm2)5l=8krtxG=m z-~--#>uq9iU$X=K*`bv{Nia%KHjzQD`1wi2?l6$$mn@eD_!wziU|>8ux#VaFA$s~n zPKbiCteNx=2`cjKJCV#9Hc^9>8JX(Sgf%|4RBemV*DkM+X@k4CxZq^@G17Xf*&eMb z3B480H#p&GWW~di!0n^kRBa$cL2fk>_{M(DZ0)#QIa(j7n()lRj}fLl&0G69@1Inh zFWT36OkeICe9<2mW2ER0`TqC5iy&}(`wfiAkWvtWC&Wbg^)X_NrfC{t6l9sjdr$Cz z2!?tL2ebYm4u)W60A-qfb(frE=-TN#=l18R+A%y4pV6QSFf}*%~TW-b< zn~*rqizk2I{UXNj+GvvZ{t2I0O38c~`9J>;{{~AtzvFr>C zxslW^Qn!ISI~l7wpj3_0SJd?mlOnJ?%9->vLTZGN2q_s42Q)5FB#;-?(T-w_1fJlB zB1Oh1%R5?AAov=AAplkFc=-4sE}P>*OAL~AGf&14B|^lGZQ&7vC710-%pRYy(?4Q& zGC>HqT2{E=$h2fl_OiqRCQ1Orwq<&-S%@pUqa4R5ZON%n_^aZfWZ z9jP+dW!wN|U^ZJ&^m0apqH;Bl z9-q=zcbSX_>`i)YNtHXp4Xst2Apv9LGQoY&;EyyRK<4j9>nIuHGHMNX;8U&P0Kt+#?o)9&efqAnc zS33k#&^8s`7YL!Q{q}Cr6BGKTwWg|TVuTRm4fq_!h1wFGMR%%br6D+^PKco}ff!>~ zvnFYSV{CV*!x|qw5s4t3>O-@~PX0}@zTx!rG1KW3gg|M9jtkby8CFLkk){pQE^vFA zky}aK2Ci0)2bT>-33dmX$Fr99D|V+|x>CINIOkp|Cn1DL5Avx$Z~pFiuiyNAGhXF8 zZvK1op3U#H)~FX`Gr!7_2%jNEwm@#=))=goe0ovS_=;h!803oCQsP{Tk&3EmaN;qc zwGaZszNM*FyvI@hTCA_;Bfs9cLR3Hpw7#?d{q!phEtx;7Z8G{L8n%Ey)Xs9onX%Z5@;G2(85y zzBO9%t>c2(+Ve*rExCVD<9yr_aK9>`;0egJvR+w zbIo735rslTM-&#TCDVcCV4MPNDFl~YAnHP7ccAexClK%H#Rv#nUK5IXt5Mv%)Jf;Z}n`I38MFL)kUAyAKl!y{3%$mWCR=O0UGOnp zCs{ska&PlFU&pcKG-MS`e*{OOv)O70!xoXlHJX6-NKB>7CkNH_AV zEA>3L=B5z|0q?#4E{jT zNGDWRdIrF1y`mJSEXozp8%EhKBYl^ZJ4H#&Zgz{2oswxw(<)A8bLReIG>VDc$NRuy zzT#ki4`VDLJ|EG1Iujm&PEdqiCR6UC4Sf4{k4d5E=ZeCncx+vJ$|jI$i3>5Ecwexw zywosajL$%zuR5d@)+OgYXgC;VAa7&x z0mho-dn-c-j`PdM_-u}`4!_cbN>Sx&9)IY-G38G-Bg9DP zxV=$$=IvvYRNNVT2N^wDXB~kMK0bfQ*&<^!9H3&u&fYGMPp`Op`v_wUjZ14sb^yS& zF+^@Mr>b@X%_s6>;{yUHY(nZL{p7+GR&p@5EGy5WtA@f#G9x*iwVcdbmbL%FjN>y; zjGMvt>y9_ye22H*l3ZO};Jim^#dtF1jiUq3P9IbGhoqa)g;rmAXo#zWfn^FhQh z#$U)4`yz)BaPJ^zXV~)I{Z*QHDd}0sw6E!_JG}q6;jvnCG_i~dg;Ijp)Py$eg4$Rz z+arYWc2^I?eAlZkiqTZ&F$-M?(&-edh_>}xl@~eZ(h4WrM}9cWC|pW61=sS z^Wai)J}*()U`_I)FISGsm7uVO+f&Q5uTfH@=j{W^WMo-Fj=Ycf5V2bF@Zm$GR5<5Y z%xBmv!wfZb6a+lFCottMcW%8wZi=MY6cSleZCqR_p3o@}Lf~V|vbiAF1GHA;zE2ac zh(t1@=;>RmORzn`vhw`-DJ11rdp|Ev_n2Q74!-MjDqE zsFXJfhD7=<(Iq-Bs|TE{KVV{Sp{gmv(GFF8i4vNg-XRl*7(C~z$cLvDtJ*Wj6@$Fs z&FK!S*@~U%n7hXrnKgtMsG5k;BJJK?z9Td82~iIpA|XVS?iPO(C=t-^lzu+Kt2|vd zom`dZ+_4+P#JWv9tVv%JNio{E(ERDAYaY*<&pnr)nfWe?;%kfcJUxUEUuleyb&Gw{ z(>%Pau}1QZJ@d-gH#_ZZWoPOB0t|)Su!*l2fhS0@{qTi#fZa zf=u>N!eUiUF7ME@n&=y-8iqxR0S-o%5G~79Aha<-#AeVHI0=kSi+7l-j$jzcVCy=G z?quD>Kb!cY4c9piA<~Jdm7w)8xn)nwK#>qNAFgAVQBU#1xBC3-k>tbEIvL$-j?Z+Z zy!T((Li;>J2=SG~83$v_q^B4aD&;1mz(_&WMD|CTca91kUNtxu`Q~u}0<04B^W;Yp zT%v9Wg_dA*Nx&zrQZ$^_AF_65xO&X0KA@jx+`e;%`=5S7-kVa&3nCGfc^1n{ns%>C z@TEl)fW>^yr)M7!Xi&q3sG77$eSu$T%%o+d?=xGrAOd~8Pi`bWmRM`p9a)5E$xX(j zr|D%9qa?01oSt7WnF1lQtOJFW+d`+z$ZOCI~W0Xj4RadU+L;B8d-|jIiG(Y)tP5B&l@5{z#CitGMqyGAiO?+al{iS}d zR;hG!($lQ!v^(w$G+F_{F&X42Dd=a4UZ%E-Br}psOM-WZ=ny7DcQI6q;6lyG`h7yk zS-BHLfSxS?NhD&e;r6XNeEjK$WWxbbImX!$m*pkzfBG(iY{alXrdRZ6nufE>Q|LFS z=xF8&Wqaseo7@!RiL$2kkr)LMMXvj--D6JHAJWq!rup0StYFyFXstlB%$mp43m6Zl zC@E-Mq-P~cUB?l1cVeuYz$jN3ExJm%I!NPlXE6Ry0?MpQU?U29k|62Sb3XrQ_jcL#742EQu@ck4zUx->frNq-fg{g-)l7 z6sQ|>8-Z2jJA~?bvvEF>N%6#Y-mcKYa1W<*~5~z4-2l= zj>~1so&6PcE3q;sv^9%HQr8WmzNM`ih>>;c$gKjMF`qA}s+!DN2E!f-fs}^2-eE7# zh;7X()EJvRVf-;h`u!faj^E()^qeJYj4Y5wQ~4P|H5A!|z2Pp8R+l8LVucg|-HT{? z_~;O(zCrVk2;sP>KJK0=#OP^!iI#nY?DUwUW+0Dn#S$SUA*MXUX8+r`_JvI}`ZxA6 ze)g#3WbSzTP_r{g8nc__b-l{OmO_ItAUXgdCMx|#U~p9El-2J}2y0S&;(W@(+&r}= zJ8w~zJ-FNtrSmj(Z-K!O;d@sYDdgTyn+!G{H|RTOzf z4JRGK!ua1JKiBhIWtE*9a-eWC3GXw-v3w-buC0 z(9%-5B}!_%7epzTHxDWDH}O%TyJThER9KS&>CJFHc7Q>bPY@}{mNLQE#}mWR#9kXv zNWnNAhbk>hO$;r_;)x)8JOAB(T5YhkPBS{jEeu^X0n-r{YZurb8NPX3@Z(QQ+-C&j zUs{51Jel&tU;hDRRg+uG)ndtT*vGYw-eANaf19hzb1vp9w1ny2J|cL^vScux&^9fv zTQ~8G@VZ`iY!;;y38R1eC}*#qhZq;`=}-7xAYl+9Vq)+kYNXRn~h zEz%flo|74YF_!yR3l_^hx26+Dv{dDs2M--`Z4Qr zNv=o47@0R$WX*(q_OCU-JA`OsEM0DsstF8p&9t9f!3_oE=A0?n)th?-z5@q3x`*qC zhc~5WGxMZ}(E60~ks@XEMR&p&l^)hN4sx7Nf)eZI#T)OJW*ACaj&I%WKF4zyuM>Hj zi7om)4nxAYwSJPt>)h+t|NgQlAp+PLY9@JVFlDsn_Ku~gYvzsO^sHuHd3siIGHd8% zii07HGmj}?uiqyMg_NqJfD5ElNM)#E$-z!!pffI)4VR5%)El!m@br86v-KuVJ^;L{ z$ci4tU_@PyI6XaMe}9+EW&{>olpk|z@Lg)R;AH&)ZK&w!F%jQEqu^tU4=qASTxi+p z-6j%o&hn^!pGAAlqPYMOkwQVRiP_M_jL$4q7bu%ZW(2o)5-{Ssn6o=jXkEv)mFe_d zu3C0_>Iqf3Co=c3BOu9Bg;gW&`VkAO)*i75u*xr`vbI6^zw{VS#vtCs2YPbk-mB{SuXe{ zmAcBbBU@`342R5SR~#N35pk^BIqPuqx6irjn8!_hf$JMbO^4SoZi%|+T6d4Dd=}DQr0b@ zunCRolANoKJh(qJC?&A!Nu{c$ORA>0MG$;UTrri3zqCqhW@{unS~BTr9-Tjb-Tg&^ z?=?qZ1h>ZtF#YHPK0Nbe3d$ySx=iU=?Tt*r`c;cklG9bn$}5>zq-|ZNW8UP%7-^d} zotjd0neeph^@^O^M&rCE-he7Me)-m|2x)>vmmrkgPTMbXPEQ__7ej&;WV(-!6`7i{ zSG>i*PEitqi&!Oy(X*4^#>z3DUU;O43~VF>kE20~94j*FaJ4lgvYPvs@3C0#vpe0V z$nz~PN{~o`^R-XVG|w8g5MZ@rS$U*PC(dp^;-f%vO$E_1X=gnVzuXu`3HF9&n-Glg z8UU!aX8_6)&C`l&}_k0uhOu@CUntSwh88O17uXt+;l@t8QBhRw(v_8_f4Z$zX zLeEOx*v*gv`Wlu^?2>+|Vr^YEJbZkH5R&mQM{A9>=7}1WEom@Dj8ON+-_E znF&5+&^J))W@w|iefu`&XBQkC9Z>5f^Xi|{U%_zBtSy;6I^*{A8%!n>lGA5#>t~cF%eEGs^G@M-zz=KKbjy^63Tq{IMgt19q}^xI6kDJv}0XNR&W- z$=U2tC#Idoh8})1aK73Lj@SvMUT)xE@p#Qg$TRG#yN+j6cJmES_T zp{vo@0IIG#UGD5yZcj5ZBR^Atrd^sV&jf5F>S~sGXpnbybn^ z`H9$@Bg-?Iwqca*Qr3#n&FGl{xtb)H(+8pysLpRUGDixH5RSvKL2FBJk@H2%y7AoE zvE)V)qCrc`$nG)94k+CmqsA=e3ntTXf|Yr3Ty)cj1u)42C+h(hiXEnk|;_+Nx!q{;dGQul)NKtDKj zRPMzObdV`_2AW~6IGrb|g*6KA1HDXBtxNJe!&=M3%bGzh$xI*<1|j4VSGWmCLrg(r z1dOtn=m@^1_J&{+EP0K+ym&NCL%&y`q`+uL?Nai$roYWN7zzxcVvk z*;^QLtcD-F*=JsQ@=j181lTR!L<@ryhQ8iM~*MszUuCJ?{* zXWhc03hWNeR=zX+Ja9T|ne;RvMpkvodT(5)oxZ+yv$~%>Pss9S(El<_>7|CzHVsYd z$nqTBeM{3cNGYF)J%abo^cnEZcLgiYiYh$uI`5wenCrSmYtz*RZ+69wqWqe&oieuU z_9eM6s1R5=zjZlYb!>K}+P^$w8e$Sjo2?z*Lv8~yc=9|WBB<&WI*TZoPJ)NCHOhWO z-&)4`VV8(Yi(D(gP^nF+c(N`Z2XR=j1fw@Zf-=Gl~eD zE?Rn-BGZZNCj>NY#2SIs60Jl68g4AjNQxI$wdZ{4*d1sxbFD$OdCm2`K7V{h&-*9F zOAX`S{(t`|KlvTQZ)%qF1wZ`l-{SoA6z?26 z`$v>lXH-Ezbex}_qjO81W#n1DW$ZfVAVj1#*eogP)m6#m#W_XRN860ysE;Xz+`D_s z&wuta%BID&9%VF2q#gC!-}w&KJbNo4LLpmzcyEWRt1J4$G5`7}=LkFCb%v5DbNgBJ zWgpN^3rS&=Pfz$)MoDCm%5@8&=CT#%ju{MhL^*x88oPVMrmkT$KFt z|LGHSsA**%U+j~;BKdYxK;(RUB|TLsU^-Cvknr@Lc4!GzQ*&`SqZLcq#_`eYXXGX$ z?_Xe?plJ*0+H%5uWN*YMAHhZj^TsZ>=}(dR#w$=35!1#3*QK9v`#-iNt!>ki7a2sb zvS7EkORmPLx~nREnl-RgKI&OENUcZNWiadC7e#O7| zbx$9C@XM!hhEn1l;N zO^ga9O((`JXzGf^V$Q+A{!16{y!3o}QPWmuG_l9q$J4~oizyd$6Y&cjJtWnS^IX7U z1O2|L+q7J*nND|~DOGrRtFgrbljnTn-Zub2+cwM>D~5v}<+{XJ!)mq0dB^_VK3c17 zaZ?CBxjb4?mlYudY_?H74+yzI6jJg0-u^CUXBX`3?oh4QG%nB|^iWb^dTH0m@*HFB zYc(NJO3~{N7)VK=_sT|*9`wt9znP#xrpT>i+^<+POD28E&}fwRxX@sAMjacKdgqh1Rse zBb3HUN!vQkuP!L^f^WS2E9A!W)Av5WWCg$atKa6`fBz@US4*m@A~ywDKZlU|E@Zi7 zKAZC!zx`Kv``(?`JTBvQqQA(IG?OBY6WrRd2!;rsVU=N^Kv_)`BYL}geDL61cE@K3 zS#K-Nwj3ZLjc?J6IUMfeJyfmV!jBu7o15B6q5I*+(4~AzX)wfX<(`ycD}rEDDzR1a z`g2A1-f?!kRs7rJNu)AJLfX(=O%yh9j=IuRfnb^+)AzdwlGwxS>XN~rkG1Bdtcehz zY&`uu)r2fUQd@r-8rgsmtExk{u2G} zZI7y|uvx~cTrwODxO?|5NXcS$0XpYse~+RlaKRIODqB1`Jz+fFVLIKxwIy%7;n~^S zXFMA5yY?{95UvafOoQV?2nMK>WxjLN9n z$jPkXaB31aM_VSnJ)D_QiW(o1>YtBo_c;)8iM;1Km=ejOtA@Ry*=o&hgvMjHGlm$D zQg1)wX+j;FfI7muEYVugD>A$f$=$tC+aO5H;B_6yOhn#TWKsgsbn=`nLfMqii|Ka} zFw&-~x^;zfp7FH*T-wIXVU$42uI?gKj0V%~iud8#ZQ7hrHj3BU+(L|$b)d*pr`;>Q z7*y)u)@}BWj`1A>c2kY_qH+7yak?p=x_3VBBHp_9c85v{l#<-Kb9ei@$z;s&ty}3c zoI`X<7f;CRbZ*#JJ%mX8@{Y!-r^VjLpgSIvRf5?fAvJ9%i71T88QLBP#cfJAM+k-U zHRshQw4ug_RNqafCu@~pXP`Nmw^%JW7}>-;ZCZ$3DXfqX?Q<7Pk`lU(VvOnNCPEUU zr)rZ>f|ecJ+eJJ+T<_UFq?5J@D?(T?FgvuNqHa97)kvKT^r|`|*F$ohvzX5rk4H(| z;T0BP)dpgH!J~yh8pr-f(zlXz6F6VA+}TM~mD&aRnR>0@T8fkeOqx`$XH+jWjE~=c zpR7NiELW^nYZj}DK`-Os!xKi+DdSDf8M@q}`Dh15NAD_N8k z{XAnan{oQ!gnTe!FfJ&on&F_&XguZMV1FA#s~2#zz79q~H#t^I`dLyZ_aSLFMM@eU z85NqfpL4SQh@KvCxoA1sxyw-ZuyU~NjM}#o7R@<|oEUOW<_*V_wAlNZqOgjKWlL3; ztla~g7wq)!qGX1^<6VW+*)t6{V@xN^W|OrxLn_5;T~Xv&m$kkw>e-B8uC9-s&_WCt zRWPehurf!Wu_{r+1+mLA3u@QWRwX@(^Sw9v+xqdc zE0ukC)udRYqkHr-^#p45B7@nwgs-`5UTPTiddZL9{TZ|QoMO;py!^BWCBPeB;~SV}F1DRj>QCMhKB00zrN;EMcPr2V=|a9m^EG!CV%v&Lye#-kzU=NI$}d!26PhMsLq0lX4j{eARkor4gJ>>*N0WEYbp z-CH0E#@QYr!pZEE$#?|BCt+sN*EKFJ>Z%P}5$A{?I?2Hx@UTcHhkdk$+_~VaP{NT+2{Y-Az#N(c#?Rp4?2(!`= zB1{MRnfU5;Y~)4Yz)KCo*o>Xd$NRj)X4mhx);`e+?8_}F>T027%Wr?@8+h-j8pl8V zgHK=EFt%JCk;rG$zNVikoZnEx141-h)bFusmdU*cC-lt(72)>L0d|v9ASJ7u-^k&2 zja*`)I=hf|#i~t8BSj|BQlO+Ele-i~FfbX7PZVlMi7zQKf@@IXT5@oMMBQ98&N(7- zo1D8@H@>NG^AQqNHXy<#08X)E>p{nj>}=;s(S44#ES6=e;psBmAtqEvh{UoLB8eEZ zKJdXw#j;MU*l!uMp|vXHshb=v*lQp`(@Q?)s!u zG;NLdWs>kgqonFY(ISI>kIRd5%CaILJ1PrADexgs)t+S)&^VM7ys>MTm6{JuO3GG} z7dyPQvm%Is(|OAueY_&X$g=YEbH(1!Y~^-xBYAT#d%`F-b5+-&W0h*45iHpxy(gO45|1t#;Hj&nQZcPo+dk)7LE~LhknNFzK;V7NxC-atNnYy?F%vO%VN-md<-C7@aWjQ*&jrR>wC->qvfBP?Syub6xhS7+efBx@2A%sMo80{RqvQcbGD1C^D z|KFid5g2EC>VhF^j30%{*t&)_%)4E6%lBQCoB}!>R^vO87&PtnSF`v&cMx%8q9O`H3 z&y72!CA3YQVo3}}NW_+gkz#~Vu9);SjSDCd2(AXH@f%Gq?UE*L6!d%f){Rm?FNY?0 zZtrG9BHp*mR;ftpY+hrBp2BE^Pwr)IBxUDn0bHyczx&>Tb?uoBG{5#npK1Ta&8atK zwIQ&j*WBEoUb=STD-?8BRmFO}W@kF({wE)@T2)j{LvC}by5i0ocUdpzJb3hoUaug= z)E!7#%V;>F-ybl$IA^(DC2dh3kV0atWi%S|@Z%2lvB0C{Zvk9pheFV6H2kaUJA48R#dj*tj)}ZACz%wAnUgdHm=h`v(U|si>OJ`TViVheYbSB8t>wBLun<+Sv6B@7Tp% z(A{)gD-i>AxkPA7<66$wAERAPKigq6-GO*5%KUiNa5%P>F`Fpdh=o*BV`ll=Ze-vE|x9B zLNVwzxX;Cv+KfEUw{4A&Z@>9mS7vv2%B?$hwh6hXYcGa_7l+!ryVEaOLGbgzw3`K? zl|YHK7^F-S*6((p#j0Xx9a@eM%7RiIJtGpDHCE?1FNvM*?7TW9(*;J4(+*rHDwlS( zzL8xGd1{)n$yy7c2)<4JytrPZMhR9Ona{_F@f$5Cfzlc4Rf%wd%&5))1X4(Z5M7~B zU{Rf-M21y4J_>qyS|FQEb;G)CTxy2~DWGoL^-dgwLdS^FmYu;JVk}wBN`@h9*NT!! zs+0&9%a*;N;e6p(m7cvp!{H=H8AJ4IS{G=2LhVL9P3;2fCOlC_EP!2FW3O=4`rqTRY5A|(!u60BUng*9cEvtIU*LUJ_i z6GTRBm#kK6Mx%s6N&$;9@X=|_y~CWIRV*vd=|UlOMwT0h0pU^{Azd=2Zyx3JGRcFB zl>ECnMEA@Vm1j|U?w{95D7(vc?+y*OCYDL(Zf%Y86~^lshJdCi`S~XgDVv7F<0EpV z_~7Rsa(w#@b`I*VdL4h^BQug)6HDzvC%vNRS;cJKQe>KbzsGFtIX%51Qyw8CMV@hZ zcz{x(qsG)MYsb0~^iUMW(s<9bpPIe95ZE7CgoK@eq3!BFlAD$4LA(bo9opC}nQ)`< zmrjBNv$h@5l$#A;ppt791k>r1)3YTdNUoZa z$vqUpu&xFy>c}?^vaTCz!DM8(yu3tb#kQ&B!>fj?mE(A7>1B%jk?H!JZ?e~dfW)ZC zs)kh^*c)ozIm|g68-DU>`P^nOn++raWg94)ggjm>9Uq_7ys>M!caSGod;5k2o4=^| z>^0$9!LR@J@9?WXbX_oOAVz-UH-8Ib4O;#ALVu+c^sFSe5~C%DW5cM>#NZj{0UuNF zoN0k;8;1QMxs{BD$w%I>PzU`SAu7tIp{&5D3@Os-W0c@><*~{!DAbk;zN(WDcI}e% zj&qS!)iTs3wGHdgs7?G*Hi5P)6iN$i)8cEh=pse0U@#c6ST5O_PE%EjcjQ@yl#1G| zP*NjAwq^515^t++1!oJ#!N_z8Us%?jMHy*Z!R@K(0{PV3GLYh-%Xvw*+ox^=jSET9 zqx9?#4P~3M;6|k^cnE^B(e%ZNQEyDuhAl8L$`wC&v(HZ+2tGc0@do@fMBTW+`;RLg zU3IZVeof)ITscBh@;r9@E3M>BjfF9WPd@q(r8As&jHi<{kuG43rm8DMjLha&Os2cU z5GYqG^8NrRpsq^l)-xOqutu|9uW4FGp66uNa(;4x(1y`yh}Md>b!_Mb-Z>(IqR6Q0 znzF3e-P?Pu+KksW43YRyF{Ui^#{b7RXk(JkkHBcbbXc%E8Kz<^??LLVHc=!cI(x-6 z^lfa$PTz1cZkdk0w;)P`+S_@ofx(KHAxXo6BSB zTZd4JN3)hfX+~LkhDyL2yBY62D!E!ae2nxmxkZc8g+^vgM)Wg!{R}BGj83uLy!4EF zsR7T)yiJW@USlqobE?und*Avl(_HcMkM6Tv%)uyj#ygyzo|37IJ8#_LaX&qLsl|D9aLMGJ00A zKQvt@pmajCE~b`VE}-$as0l)nTY>kHW$AGN_J*m4U+n1Rc~=*`E^7!aJ_H6tq)Ll6 zEocR?#n%gb6lmLHSzqD8nsI&%U6GIXEtQ+oGdtV5>|8~f*3-BZ&RdikkXemUkXb{F zfu;>qwZkew+bVP?%POVd&Q8X(uals1ofhQ0^jmR*)cQd3a4z}gAP{_{b!>xZL_(tO z>?8wwo$>TZvN4bst)5phj5~MkFdPn%Lh_yO|A2$r=UiOQfJo8H**`d9d49st@h#l$ zF8%SCBFi{FIzmfBz+>_pZ44p=s@5?ak9p^vcj%8s^oyMH^9$bk)~{eR)K0K-u*2I` zg*KY=(-X$KhwM&A)OEw4*JHf9&lgOsdd4V1NPPY#j|kDCWMohXOvn7aTBk-R_YMnc zpJX&GhSoU(8ahp*bn*xqmxKeHm!LCT+ak5)c#?Wo`w;0_1vaR!f9X+>wf=ZMazZR0XMEep%tfoSj}stpbF?BMBkp47~GP ztu7FHP0#G4&avLpwk_5gR&IrKiq>6HH4$e9^a}7HB|uG3WLD9(g2imMg@7W7G5qFU z#<~go_|r9u%5(1^=Ud0c7HJx00U;Fg%0oL zytBK<-cu}C?;L)22V=|=ises3w%)lX=;Zr1>VfaR`Q|gG1laH{)F*v#fD?RIYFj1W!<2J zVqFW)mo0DYTXds;g%gS$ErQFJnbCvua*>RafY-yt6)61Gcmhu&46IfKf z>zN%{UpnrWnz#2H_sk4q2gqn~ts@Fa8ztHp)=foK*IVh)EX%0Z!DRKiSR?9gjkI&JW;oHCREiTT_&_y4&oY6+b zU{DZZY1zuXBYw+F?F|dV2U^m&HFdkDsSGCTqoibh zHKVEkN(eo`WQdUL6oz}3oq zX+{B`1FpTgJmA(L&L~n=NlO7MxE)(+=XG_S89sSZ|TMzTNBoXlEOw!#NT|S>Zpm##B8gFM+iF#9=-Ot5#7WXNxlL6~P!_2yAjwn`ITj*aV<6JE zlENlUrF9*)f(_BP_yCvdoU1bNpmb+MH|{jG8t9D?LejWM-FW8fhzpVL6%M5hnGwWT zU}R41Vyf*R_0A9!TQ)9Tsb~la*BY$R1h?XHF{5b%d7hEwmbMLCu3XoAQf?{kMMng* zowCWjWcaZXt~Vu(z4lJ==F znz~%`m;ZymNq;b)$aB8AT5@?gLn_JM{yxzMw9))}`Rm)Rn$~7tYOL^?BLdNPNdd)8 z6CLD=y@ADrLlBzF_C4n914ed)6&W$sxM-8WfPit&5Tc;01A{^%(MS;x!P7R5C={7B zTbx}=fpZF@Gm1iCZO*D{P{C1TdB>!UI2VY)6A&y*nDkR$aMM$iO`xo5)>X^0)qHYM zr9R<4;-AvOx|ZMR@UrN;jJW1v4NdDQbduIdb?1Vv#9}*N8-v);$&;}uLeRwMLHe$< zYGg3z6GI}Ej*3pH{06ZplJZ1v?dPm2&!X})E-=U?F`JOZ3y3w4rF!z(^U+yK^nKZl zvtG$CHXTBxl$<<%L|J?8+_{BTnzpHuuiH8XqcNkT21dDBQkD%z$H$cAn#E$yXguvm zY?`{RKuEI8P}en!#T;WZijI1+p_arL@!qkRFBpu*6!|Y!AM(r)A}Nf;03kIuiBfNo zm`(kFQG2Lb62cM@4a@eN^Yzau%#^V?+&-U;06?mt5P$@wk%Km8GQFzgzJNLI@g%{nOzR;?q_@M}N#Ekd>A{PL1VCui*M z?~xnB>B$K}2#mJmnW1qGZ4FuoW{Wja1c-v)`73{&JGT$MoF}m<@Cgn0fK&!81t;@1 z)nKF9DGsTfA$XY8k7z=PYfDzEIs4f?gcMYjPx?pVnoa>p-%6Q`PcPQ&_C4c44=E!~ zK&C{3X;sHZk{T@)O;h8%LIh8**Gst*<(Mxkv{qzBk!PAgu8DL1>YcAPn*leZd0^Xp zNQ!I5tsoUNIbWx~dQzo+dfro(Z6^{f(MIE%iVy{^@vPQsisgcxooU+SI*HRwm!;GP z@FqZ$ejib2qJV(l z=lb<}@-648M)6@*d6EdSYJ3UFVpjl3@DCiYm@M-bviUFC?HvuI)!z_~LDWA~G zk{%N-V_BWBZqJhdM3ls}WqdG3#H1Xu5joo|h}K6|rK7Nl+j|49=1cTyp5#ok45bu# zNQ&OI3yI$(B`VKYmr1-}+rQ9Sj8@cj65Nh4#VND3qkiSKh1V-(vtScJ&_5aLZ5CI6 z)_bb<3dNL&?vj)iYf|5DVxV!6whasl#qq%&=NFgk>`b>YRow>87A>nL(6^G~sojbi zXeG8P=o^ZNQXoPP+zf1v5~;c5qgkp87o@z#oBKHzOGnkAZ$3muh2q{}!PUy~;Ic_T z#TRWD^?y_vpiLIk=C&U=2>IS5u_L1CnNhwke zqjf1rw??uv%n~iUi*KS#Xp_~VldKWjj8v8v+bwT{5%e-eW>R1*qUUthP}V7r@XB`_ zlaB10dl~PaR9vk+7qb)fmu9Bq)S+rY4p z%oi)B)19pn$;HYsUpsD1ZQ_1KI9s>`-QGyjKB0{T$&EsSUlG-SUM4vh89qGq9c?AC zXP1@dY~i;(4SQX_TPZlmdJbzNeuB{Mo{!*=2az_uu9BRC*zj#P%= zYP@TRGWET70jkE)%ha|&NN##r-vH2*6l5y0SXF#*DX2dOP*b%D&UHRA=^3>4i0B9; z1wl_liw<>*kegAe7F4N+-NxN&eWWTKjZeftV$w4nkB2laak!*_agh>p8wT%uU30N? zsn|$tbgbB_yl+M{Q)teKC<0m1!|G&NR<-BH57yfrCRz!4h2n5*w$FZlWN<#RtQ>V4 zpHOss(Rlql#!r62{YNKUUR^TT+vDSpKH>cAoXKF!gHIo@UX>ib@dmS=bo-L@>4^>;XbVqHj=A zv1$|hH4g(uxdEvWQXrM4Y6ByiGTupoG9-ki>mS!Rk0zjW1_-pt@oh!$Ey7r;)^~FL zY4JNBi6L%fZJv4 z>qc~1DT#ItupI~ysHz67HG___FC|;P(jZs7xt}p#C*gvgmH4hWYGV{JCXQ2X6jt{j zIseL)x`lxheD7|Lz2UXsMT~Gbw*2P3As?UB%-4=Zmn?nJcHDSgS>1!o3}Vy zI8Ns+!$K!X93?oOSOz!BKD~D+0S?2}s!6+3vmzf%w&KQFW{71?)22o_s#5@2l%C6# zV~{B{EmD~-21%J~r8AnULdu3gW{8=jY$ClZDd{<%cI=HdYg(rrG9(p3xR*}ybDu(l z!`ME9Y#j-QO>FkI4Kwm2ArLp zp|$4d=m4SEHka9oy^;FvH7<~A*=;7*pPLxBU42Q6TLcZ*Ht5_;<7PISHpLk?4Wsq3 z>-efUU$peIj9Vg!P9$-xXUA(M_yk!mXH{10@9mT4mc?Sua56;+@UCTDRg~o#AvIZM z2{F>^5Ae=Y^m^A4_T`$@s$w)Aq4n!G0r~uPk>EvCDtX!x6_=;lI7N#DG3#C`n;fS!fpArKrc3WPN1%-~&1kQ)IuLESjK zYf=VY>BPeAzCS(AfNL9yB1Z^GFH1(8nLc@*ae8{TMUY}lNxe;vaG^+DqvExktE8)x z6iJ{hHy!Nlk`-(SnVa>ziBC5DOCs>@gOc1xZcQz|12v>gO3-`5>l%;{A{X;tKtAV# z4?f_>KmIX)@9+H`-v8Opxc~4m!=g_y>~V7XnD2h?hs;kNGFvXWT+9(M;GD!5sOrdH z{!72bdw=rp**Q9%9x(J6Z+iAm{Cr<#RP5gGS1C#MT47ie8Tc9e`5q4JVJe?SPXYonG*N%w|^vT^A& z(bpPIg-x{xK18Ch80l%7iYP512$bqt@!r^^H<<=yGIj@n+f%`(m(8o68WARiU^>i^ zS|egwgi>`KVY_wWH{=xnlFg0qpWJQG8Ekc>g^6`t2NVUkKtg*;qfu^)e1u41nSKSz$Kmpxs@^@$n(+)v9Y0W5_bQJsQ87A&|H@aY6XBn?<`9RzDFnDmp9ML?rfBo`hb)z(Ljo1!fr(Pkq|kQUBo^{w6vt0KR4 z%Q7AHfa}hwTO~qmsOyF-&yh;gG%e0wt0OM!z@u5qAeZbG5owYyzd6y83zRDFw6#Qc z!D>}9?GHL;amsZhI=)2o#4~a>tJ>4J$hfCS6}J+cOy@?7OnQoM9VcDei)Bk;(@Cop40`nPoKHS^z#Dh( zP?u}gRh=3h#-vWyI!ADh#caiRcf#)e{;Owczr-=>Y2G~S(Nms9c|kuPGb*yJYtuRh z-jnAAhl4jcEdy80r&NBD{08(u`+pgCYm9iM&Q98qS6Q?&l zsp#mt_>dUBLMpuT?Dit-M)UKNifK=?Gmz-$5YlejrKQs^U{qoeFRPlJe!-i!54gNM zr(7p-h{E0wLyOSb>y~G&kEre$Se;H5x(!6eK(!?_!cJfF{k#37=Ga$!d{(n4%dPY% zA<^9b=%Xcc&sPeV_WMZ0_Vjwucx_bbDLL5PWj8Ax!>V}!t(jCI@aH~;qE;qAM}U!_f8l;ExXoZW$;X(CpQFsc(8h>>z#GAjd< zL4gYnPe~hBNRfz!tq)A|w~^UNmscQ(Evv|~j$OTWpll(xn)PZ$o@E%>p)*2kjX^1a z2&olvj0p)_R)KM0!8gRHnU}EBH#c^>$i=+kPagOelj?$JyRwAja3r~RkRzl*bSH%0 z2vvG++YcT>ryvkXDa(IhRE+fzkPHJmR4kLQ8uAZ%lSRIBc~OH2Xvpr6yYB=*+p z^`5xANbK~vB2mQ77)6)6k=J~~7;sUrY6Fx0wfs$CCAW7{Ey$hSj8*M;@I2PjDKoza4};ko0r*|op=!{6Y}e1Xk!T9*(J*E+1taBYLla*86uxt8^6-7!{^ zbF8GKsvGuqzuFvzR)X6*8OIZwD(jk-S$V;ZK87F=A=Pvr76uDd`*RF@S`^&-1mmRD4*-}V(riNShq2}hOP`rIua58IYx;mAomM)KH4R0Uj^t)3}zC)rVB=iZIKW4EH!b9#OZB z;A+;Z1>@0>#(}-DnQyYfNu zby^qD!sC6QXDt$*|Dd#NUSAvRak&dOf5RoX=Z!1{$L! zMqUTQH+8Hw&!qLS)A$WEJ{31@#;W#IZDhC8XiC7umO-vT+0-o3d;0xe3J`;%EL~UZlqNjW5PX{?dOGn0r6N)p zOsJ7WqL;+rc)W-#%FYibJ~7czCK~-H3m9YB8whp=ihi%x(fB=0(~#K&fNV~#1gA=Z zb4m6;IuMdxFC}Cpfx24LlnpMnOa?jDNa|{hG8v645olD`byX@u+c?Uy;_&c*^JSvC zBqQkh13tBH#~7)7WLYN0z;uwBW3FqDv~f%O*dSClhtYx`yxHgRh2W}6gb`4en zx$ZNOcX0;xcE-$0hw~BBN$Mcd#;3E?nQ7fT>q8uID0rI1M`sI8b? zT`?RDX?)^lU9KGW4)Wx}$>+_PAo|GpvP}YS653YMxA6XDgH}m~CzT2(S8}5+C`ffM zdqczRJwuFw2bT>e^M+qJ?jPYae-nH|`^f`@ zG@W5U_G{lJEN6tW#h;uaRE|0v;~!swl;}5)@sCc4ZHw&Xh@wybKmMIBuaceX7G1j& zOXGav`jEczV(A$76jr7tnr90~SvwAgful(uV^yckqzJX9HyBg533Kmfl1W#@A36?` z?p%VT076F_j|>V+>l}6My8@=f)NOr4E4f8j;9AN*vj(LUSBo;W6407u73kX}PJFhE z{OqKBf+Di%@qJ_JC~WF*G|UZ3XZR8<8r;-h#%hSRx#=sIX6hAU{1 z`n;#&Ey2#HpsFhB){z;D79O4T(sS!BqN>)Uz8U=_Ffp~f|G30;B6UxDGn-_cmV!5S zvs4Ej!DvlYw?s1D>-zM4|89Tl3i_}?uu|L>Zj{~L-m%*NJsH0M`PsJd62lP4K|#1$ zK#1r!j!=7JgigH?!n#2Y(@7u(1uU;n(=kE{)c!8QYGl8Uu$I`?=;M7b23!lme5nc# z+ndvZL9Y1j?LHr!RV*sMZ4I2MB#rZUk#wQHu`B841=?8F?F=b$+I53eDzRW=WWII` zGTY(t$<^@zwCxa_uEdp?x*cgFSg%Wj(rBf~GP})3G%jwH$v16wLriMtN=iokoK;z) zML>qY!}FG(op{PNm8~i%s5@T7(>aX7O70zG?DsuV6-cF7E?4Q)j)Kq?2pMa+ny<-o zOY{z{lbiF&MZ;tu7-i}DoJ)%~dWX*QuC^jlbIFAzr&pPpr3J#FaAdy!rf}zwtEG8i{Y;Mm!~@{#6d6QZ2Dmu&N`&Tyb|dV>&RL z&Rae{Z+LXEW?p%A`VvWol!m%)k-|VsR1GO5{XCVd-r2DzDYriA&0r9&Cm{G1ghVPy zzsQL(2?JcCKdHmerc+T;5*M8=Y??r$6`2;C%}S!m`1xsIR$ikmH#JvpZZZ=YgA&fS{!b?UiC^3aR^guFhd zpJmi7T&~(}L6X&yy73H(jm!A#oNN%TSKW)hAV*((t&9S|g~0vOCDv%NEF-syVWAPi z(a!>B^T4m%DX5x?5Io?CA<~8=0#B|ai@IVo8bR>*wx!Ui7^rTOuyY{sa(qbbbrBF; zjgYeA4@I)fP?l9kvyj_GwMleEkvcU&xAVtM&$`H>Z20+EppA7(`aLzPg4BVj?bx>) zNztB-SQTi4#J3eOM#@&=+cnzQ6lZk#f`hT4sUultxmvYk(y}|!lx2k!g2o4Qca4ii z(liNf*0SR}kzzULJVr?#UY1;~18?qU^fN{40+Z>K#+`He_%V~6U2=P!E#KZtw`g7W zES-z(|$MWtdC z6nVzcG)E9=gTg2v24t)`9(#rc_D549lGVD#1vp6BtZcrLZ(e(!$h^#rcS9v{^E>(x9c}eP2&?9^k5dbDpQxG=e!1zx5;IE zc-gQ!FboPs*+SE_6nRR7uIkkNsR+|=FE82I z*&!;kz31-s2_f~g2r(w9&o=OQ=4f2tcw)Pzlorz%3M09-W3iq48W1QgQ>kyfPU3yu z@#oesv=S6n;My7^BPK#!MvA;(&>PT;0@s#Xog<^+56{hKZTU^zHw_ET-91Gn0}@A(7dRKNHg!i5r1<60+_OJ01lQ1Z?vYlKHbmC7 zXQ!{|=L%$Mk|{(?DuCT?o*9MgkUXn3t2(f%14ecVAX2e6%4l50$F!=C_Og<79gs4)rW^Hl=OagB3sK;F;zZr*JER$5y`XA66Kk$rNRa~T zvT7Lgi|1}YbsM&lJ-=`T-z#(?`&x{rAA}&1>qurZVhE`oTEs3BuaF|5JELfQq-Rr$ z-$`*qKO3USd31ikv}qaj^6O9SP^k2sBn1&6x&_p1U8WEM-US4T5J9U%cdp8kqUdc^ zEE4r1Vzt7z6%S{D_fH&U>z`_1e`8L%KYf4?PAhf?nuA_VKg-d&0HJWM!uhbJxW@=p z8xc}swPm?lV{Jxm2UK3LsvNnIT&^RTsu}l_TFccsvO6?g$tf6VXquWfruvn$g=24! zIzD;t>E${14kd?U&nH)1rK1(Bn+1z<#s26HS|vr1yy$gI407Jw&r^+f z2r0*c!stkhDel{ddZ+74^)N3wl_PLEZ#kaY?Hs;nywot-wxwwr{wxeBB}Gv@@el$! zp(G&^LxXb_trKLKN(~>oJ$FO1kP-^hrzZxKO~6Y{S+42#itPsR^fQ-Ia5Og5O@j}C z(9|Ft|M(yOU+~`Z_x|4BO-xlOXq%R@EXneU-}}A)nRnj)2K~VZZ8PfijG{keURhcn zJ~J~br9g?KN;2&mavKP~B}k16NlK^4Y-%{uEuOaz@~)4b?24+=ZjMZ)x3vo#jx$bX zCF>?)gkzXnR&~mm6uh<*BL7u%q@NF_0A#kCh_DhHp zgiu|pt_F)ko8pO6^XUgJNYLfUtmbgqCxl2xTn&|BNZ{U#E_I) zh)IHG^LnkWDc({he|+7f<~W6wWM+dv2|hVlaPN4?AXh9(hx3~r8Ik#_p+AxoCb>RU zn_MxotrLgyRpe+4E+%qeL^3L}RLG!>V{Ee9xvhR^JSN0|HR+_ebNd$V)*U{*Y}pw)RM$`MWn%+B-r31G znpn!!f~o~;G~QKcZMuN`CX5`nl$E4Y712`SLh|)n7tpfP`5N_jd|8uak+MyTeN-rp zMv^n1v#26gr(PbH%Ld;z9E^1`q9C|`(bBgt>|4B#6h`vKuI+;CBr7@|4Y4Lkfo|?s zbbSNU-xKUEaL~??*$!u?p7$TuytSV(EK=9ofx4Dz$}&scv}9siHg#PWe!~hju~Ykk z=1hNX4I?R8w1l_-uNY=KWW5oS{E!%0LXga=$DFz~rC;Jg%hdR7M^YaonkQ?~l@#=> z+Gb}rngEK(sFw(P0thV9}M{$fAg=WmRUkk7>Tupx~aE}n!;i|uNHtm%3L zhDhB;)~hu}tFDFcwcKZFq0AFib}>R*UE#>djb+?xdH3O(^JU9BM+J9xvl}xGLQ0I* ztjfBR;Ys4)f+y)@ADX z5L^;A)=DzU$2ePe`nhb6_zeWOWq^i=j9p;`p0cWuQlV|eNGptyj+&d;>3`Z1lOQC_&9Xgbsqv!ON>rchOr|LChECl zEWkB2!@^>fAZX3Hu9*x4R<<|?Q50yS803;wC0Um>LmRnT2UbPrm%Ak(YbKjXSb=df5EfA>KfC_@i>}TQP&N5o+pZjd^UBem4KjW+ZrEb za#1>&mm<$o7Cbss1f_J>?=DT&#e9j7mJiPbm#bG-$=eLy_1kFL7GvzSP=ZhhWs|yx z%5WZxiYO7OsuHO*ZBt{k-l9P%{!j#|h$5A-Y9-hoX{0Z4&QrPst@d+CS-0$u3}x9; zIm2XB5JQ6xlE%ZQR~{oB$JV4)5k8$nZPOA$U^MJ)(Y4LSbF;)XM38`G%_1mTp%k9K|9K-OrN0^4D3CWIKoJSl!^ARE=yMRf|b8ywiu8X z#a8(|J@?q{wp}J$O0-tEsv!uCQi8Vi$mlS}B30^77rn!^olL%Ks9X5((s8+L`8<1s z3z5fH4WoUwJ-)kJ2dN0&Awr<8Tk7CaW1A2NO-q&+WL9srqc()Wgd!)}eByma(3yG2LtUnK3XZyl$`Md~@d z8aMO##TbSVg!ezi{kQ)Nlq4#d7>gkwLI58TcMsA3;IHuefA}FEoYnl=+q+bCLx_T= zZdg~Idw2J6b;bR&644dOjK+O_@XbAD%LYV}wfy+eoc&23(Xl6I^Aelet^ghu>zdK9 z$IS@kl5i@aX)6yfsM|uq+xt6RL zAcWcq!WTtBRWE2-N9&+44Y`hJUC_&OW@W|g-99}liJ|V?yU5x31zKw+<6*}{PNYHL z`b4H{#?$Tk)@JNmD1)NzT9wVq)H0!Vk#V6Ztm;ImuSePVEveJF7HjMlQG68w>*sQ% zgcOAFfabez60{^5gREQZhmTOFS1BO?^m-Xaw>&D%6LkJj{0YWQ~ z3Kv=?*^rr+^oj}AYH~HXv1^EK=SrtW?IitvPKcI%meew|4j5yws)tcIPive=ZOLMd z$t+D>Qy7EM2IrDepmQxvlj@q45Ez+wL5)j2>ORkCL!=FY;C*td;+&>w5NNE;0H2f( zWeR{>4@gT{CH_^G<ZWBh8X;+En8*V2xF3PnF1E8in^|mI&rJ6R*t?2 zjE5GfJhg}Ux@CV7sM}Oh>jPX~Tw#o1IvJ(hMAtJzkfOUIqvY^zBtMVHTrePVM3 zCTCfv4F2O;LvCc(2RxE%Nxy50>^gnm{h_^9E|HSDX(^PX?aBhwXIRGPGK}a0{H@<4 z|F8ZtbmLHYO3c*r1>wK>r=1uV{QCFr^8H_noL?+4nV~Ej4)=zM@87|OQVP5eTPYo_ z1joloYf1{i;ogvU?k4FTxv4h0aZ{V(`KJRG?*j8>$#i$b*z6F4=c2h!C0j(JnD+0X zmE5vag}6S>oe#{)ii6=1P1a(KL2E@_*Xi|Albh?#tx81t#&a_O*)&ZFk*;YcSZlU| z12Q^RP2^(fUWkl*<~)$fbbD5&I7SMVr2%~+g54)ZOOY9Zk7QaA3A9dPRHSMv8fWQc zIVQGL>m~ok|HJ=@yLa!hx3@=B7U@?kW*6)nyg`;(#^VW(9-r{$-8c9*|K@+>=;)BY z^|$^*loeRxxqneH8RrNjqe6B%QG&KJ|HGf+{;&TZ+RG(!z9cF|c;^koyB{OI`9@k40h||1CPM)FMV@MIrP}g@ zf``oL4!uajaMQC8^g30*?w?Pzs@g7+rxw@ja>2j+r@zOod%GM>?$WM3=j%u0eT!8y z9_Vw*vgG*a7$GFL@7$)}%e!VHk-n`lVhCCiNEGWl ^!Ew8_;FrDA-Jwjzfp_2R2 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/learnboost.png b/docs/3.5.x/docs/images/apps/learnboost.png new file mode 100644 index 0000000000000000000000000000000000000000..a6c33c8bd41f9806ab255e4afe5e0187c65810fe GIT binary patch literal 31434 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/linkr.png b/docs/3.5.x/docs/images/apps/linkr.png new file mode 100644 index 0000000000000000000000000000000000000000..62dc5f6c51174c77fdc4356a7f442e95cf8fb6ad GIT binary patch literal 6428 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/lists.png b/docs/3.5.x/docs/images/apps/lists.png new file mode 100644 index 0000000000000000000000000000000000000000..a0f48c63b1eb40fa7cab3c8384ed97834c621e21 GIT binary patch literal 697 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
  • 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 T655ph=X$5122!n4wvPBe3)j3P literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/mcdonalds.png b/docs/3.5.x/docs/images/apps/mcdonalds.png new file mode 100644 index 0000000000000000000000000000000000000000..28a1bbf0bc13f1d3728ad42e53a04eb669f14517 GIT binary patch literal 57481 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

    w5Dis*m_y7@7D1e4 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/nuorder.png b/docs/3.5.x/docs/images/apps/nuorder.png new file mode 100644 index 0000000000000000000000000000000000000000..da4cf597aae0b92aff5c13b2638ec7edc997705d GIT binary patch literal 38163 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 Ef(FYGSO5S3 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/panemerkille.png b/docs/3.5.x/docs/images/apps/panemerkille.png new file mode 100644 index 0000000000000000000000000000000000000000..1c23893588b5750f2f523e5b44568ea271caf2d0 GIT binary patch literal 26344 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/pictorious.png b/docs/3.5.x/docs/images/apps/pictorious.png new file mode 100644 index 0000000000000000000000000000000000000000..e0d30fd24aedac9843c81570908393ba45261951 GIT binary patch literal 45953 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�Ji(&ADpg6G8MuR@X{q2Ka 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 FV1hD~I!yoo literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/scottyapp.png b/docs/3.5.x/docs/images/apps/scottyapp.png new file mode 100644 index 0000000000000000000000000000000000000000..d5142f34601224e550deb71b93313497f5720cf8 GIT binary patch literal 118416 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 Dx(}}{ literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/seelio.png b/docs/3.5.x/docs/images/apps/seelio.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e7a8e65abae0ad30c3db0a00782d8b1d54ce9c GIT binary patch literal 24005 zcmV*3Kz6^0P)=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81MQ%w%K~#9!?Y(!DWXE~l{j0k7cFvR2 z<_PQpSO|e&0E3u=DN>?DS+Wu(QIdU*W!bV7EGOBrK3leB(^jxerOzUzj}{40rbv?_ z!Av3%VHd#WG&yxnH&uOq-0q&9+1Z_*T>zWrIcLsv-@dnQs;AyqZ;3}9c|-#UA#hz6 z&+{-01Ix15!WM2}2tcEII9MxIE*Ga~0nyoi3tPBZVM-}4`=gMOR4PTYUPlW_BxF)5SBNE& zpnZl$cktGS4)NJ9e;rdf%q%RENvEll%ecPJwa`Orjn*0|W#_Yy@``P09mqK$#419s zg;EM3E+z1lj@iQP1=DSMSP}D*ACyuYzUKiRyzemQ&z@&!WR&gO#(Dg)Z!xxG4l+{%Hkq5BBNR@M%cfXfTBP2v zJDqneQ4*;%rcjhCHBzY*rD74*5WuuT4D|O?tCT2~%Fu30NV2&;%Edgs+9Jp+39VG; zJwWhLcj@xo8p~!Ox*H7|S^fPoFsp?Iv2=uR>{4S}E7-MjH|cagF;nra#~x?@;Uh$p z&C}03hiO{)o=2nUbLXBtWU?7P`iFnahky3(GT8SwT$sxvH`&3o)?^1pdEG+~P;1uM zvv&`XXq@rU5hf?6@O*_~8Z_&5PM5)(O8Q2zV~}@>?-HaU!YcNU`1nuO_N-%pJHK|7hgEaV#Vbed+PLC6ZzXjJihg%A?7!i>Z?ux~HT zN|C3Ri|9rbvs48EDwRf~Fe=q6UX`hQO}*GeN^yzg5WvY3rx+U>BNVY19_V9!YMQ$a z9VDHZr`FKKVlmRGB))4?s=IvGy+@dtJWsJ)>lo!%1H&+gr*iDtv5kmSEEUQey8CWi z+hgkDdB(;jxN!C)x^3(r4~@2J*I3ChJhOT`-Z z-g_UFQi*srhh48?no)M|+QIznBp0Vkco$B!Lc^^QiKb~*N<@<> z?1oK$Uxw$8JA z;`EubjPKZmR1V99GO1)7&sS*QrQY-y8y#k5>LSa95?8Wct_(r{z#x&Zg|9TBkcsDd zXdOsEX@;2?9ps6}AIJ4o=a_-PLA3G-g+hUZP#PgLiwldWmI$>%VbZAtwOW&0E{*Ri zw(Z_WM7X?o;tY{Ug#7X%wR+=v_nTWDT5D37K1PQJ$)vNCt9c^P6v=pua5zMxUMHIy zq*|EcnHNvf-`~%U?c2HY&I6oy@p(!$2j8}XeH(QO#R|hi11P2NeTQ>r&Tt`-!A~a8 zi6o7^dl8K?)=~j$ewO(06I{;y+93u&BoQK>j&u~Wj?vpPW&xy>C>3?X`(joOxVH}R$)~aGK@>Ny~HpJKmDVt zHV7#QMJ&W-%>xaS=#CxGX%Dd_Ft%{h!TgYaaMcE(;I4;uFtR6y-Wuw+aGS!sI}d)x zvlHla_ml+p^k-YdXd5YOhkYIVT}9Ak3tPC+Va5le6lQB3^+#zaE;ev|00mwdoJDZ+ z;5PsbG7M%0LIYrBK!#cb*&@jnZVi};T$I9Wl@*B~XjW>d(ldzKGf+PRZUK}7ti%iu z7MLlBOdwMCK;jUX>8^dYu!Wl!reUqIvXzZjdz+ zW@Wh%7}#C~2qKKhbQ2*IT1yD^Lu?O3wj-!`k`OJ`OGv0Z zgI*d&483<{`xdrvlfcwoiMB1EwIG>lkQ>jz==%`y1JIfS9;i;;5McEq`ri)medyUg zhsGIJNT8wcRY=?ciG%AL|H_~($2Q8VY29V;r+b_8zJ*&CCb}y_RV&8#MTqTv7sPg7 zYDZjx)^D-hh_N3FP+LT~?a=A1T0<-)*!9|n5b@nX24k<# z3L;~Oq3;RE;n(PRtZK)hF$wYAFRRp$1X7`?6f+Hn7ix8mR;rw=H<@YLlv-r)wMOZc zIw);vA^=MY;?khcGMR{mxicQ)a5B!mc$A!FVFv8i`jy*Iq!xcfTw*AX{@nW^9MYN)^7EFLA6|W6||+yYl?IlUjl*KbNXj zuF@2gN8WWgS#R*AgjXq*eazl7?P6hZpR$y%MyE*AJ=zR1O96IW?uiwMS5Og36;k2I9x zM6J&8TAfE0mN=Y<^X|bMug_-4TILo(Zc&(83lhl&_dQ%9F*tH<8MRtNWE`wMu%`hT z^fYG){CX>8W&U(_k+Y3vXZtIGwiNQT=80m3Z_do|x?F~z+p~l3%BDM>tu5UAFkk=nQw$81 z(P9`O46gar3M0tA?QTc=pgp*Tt|NuuWUbEcP0sRYzSL5guHS(?M6u&n)%SSHEQ1<*yS2cXO zptZ*LFD*YRh2T5I5`X`hV|;mG>4v%9Eo>euNlePQ)XlnCXdhjEsx{NE3$dLb!aXB%msqrr?L;s-ZncY9j%htu=?$;<-oHISlB1R(@5DM_0q zS<4`0nnaDDAhfMC70;*OxfETWn(yPcj=5awW81#C91J12P;c*$3~BSM1^8SR}MLV~@Bo_{1rVQ<&o(Hdg=A-b*Swgm90g=PL|dj6_O z(I&%yWpQUB#*tKlgYg)nkq~LqAS@+ji@d%DM=PqH&%EPuvew|~N|om-HKv<3UdzDl z#zw?|fE?#*b$;#G3I5xW!|YEbw#ac4LD*0KxW=!rVl8Wk?L~}y5F*=I$vIv3@RnUM zgP!|ys6M~C9T`JR{4^vF^+XIQ1m7x_`IVFBSaiKjC#x$BhJbzXC~xh{@^CKAj%b8P zD;ZF?>RzqAo3$CZu2Rg}4&N?S`0QeVXDd~jN_7ZQt<|t?yQgdNwdO5D1N` zf*AT&~xk?SCHI+&Q&+|6b-rw7^gJ0agd&}myNg$m1g4Xko!15Q?{Gf1VaeEoGM=u)0vfBpm~%GFJc{=U|{sxQm`xbH6dL!m8|>IR2w z2jIl;_rbusf?(V#dqA$JQOa4VFC`@FlEO?Q;(J>uARE7a0Tf)1Kbcve?0K6Yg=Rbw z;-Bx{&IgAF2uu008n^A1-#pOAM~)ogflUVR3?XQ=B_DJw1rm&D^WNZMGU?R zG4`QgDylGgn8CLW+Q&36g5EeLB81?J%LTquuJ&wKD6JWbg!$*YxADfl%uA{|Z3JIy z?nJX zw&#QS7tP5lx@p_)*%zwyo~4B)1Rok7;!W2%7s=O}L+K>{^p3p@ghM@-mQz~u$n-oj zO?#_$$_uva+dXpG3 z((3RLuyTm_{+6UjLh^n{-V5nhL-vi3eFLN(fY<>DjRwa%tBr60)P0}FOVyrUr~?2LBM(GY?cD^-5%JI8pUSi)Rq0#|!q z(e-`3&#d_@*R-{^osG7wcg>eO*OjiZ`}^9z&ULOiSGz4K1fQ6h??Eo5FFc(%GY zDg?~h4rl5;x-GTlO}Pvck?;*!KV1V!)8zeQ!<`~+8^P0>$Cryed*eFKjv(%HvRb3$ zdhAQYi5QZLji7$kg?h6?P5~@AE~l!sPK>DFdNh>kr1rPB`&zT?xTsb-{<&J6i(PFk zJ1!@yHHxm+>6q=dYptNH0OoCnGqpNS>l|&AJde7+vaRTPG+W>2ZHH6UI(1(mMetj} z^;R9*@D+L2rQ-S2eV?N1;c3m;TAit;jnYA9ww2;^wa%jBAbyiH^{pi2lO(SR^a-jrXtk(F=Q|F0DfgvTo zeqc9A)8LWW1wOy9#8lJfN5)6_p@|V5nO)$|rss%BiK{g~w{wEeFDw(5l3(7plRurB z<>_LD|8my>zOii2n3Nq4m_jfV4)Ke7caSg)gb@6%$ypX`hktQkH}kg5KRkAl zpWQjZxmttIE-Vp|5<>|7(ViWAZMnb~m-771T?ffnCjasD1s=$zIa;ppe5FRtvN)1X zvh2FNP_EKYiXWL6;oeM&e}C#c4d18gD}HkO7&~K8B8H^sc>K-cGEutC? z4!?7Ll2_-_d|+&dujPw8UMO|$?M(wY9xIeMUvKc$r6Q&b)SZt{&+$+8?%*SL9pGRx z&PUE&4}igbDwsmBBOaqaygHxho67}$<>+yK`l)C6wPPnZS}I@i za7`h2AeSZ7gE}REit901Z}e<8`C9YF{w#lMWRTxHd5$NFWds6C3f?x@$4Dg1XgE+e zCmT&7hUCF)nxtv+rv4lS*JDRCO58B`KXZ%341@3P&+*suOPsGacvF9lQ?)t|<p0Dm9iIhh@j*T)n}!@q z%XB26(wc*bIQOKJd~$YyFD>PH-^d_Kj>||S#NFv6Y0KhG{W+!@&0sdPT(NN+rI0|x zknD-ac^*jc{AsnUn{K7H|w#_4R3k-xUcE+RJmr3!v=O;OsOz@7O zem*`mOGHWzB;p)OCHVZpGAAlEj#q1Zc`45$vkMG{Eq-GA7-4Bpay_OSP2M`t$1m*J z&Yw-s(NK!*(I`jKDSmdx1m8O{$j(@_Goecg!TU#s_~c9w+GfkVXEftw< z+Wh6*0(;^ya+XQcSDdLe_{wsDCyQk&o`JA*NJ>z9qPWK=y@9kxHJT{W22j|FmgGx zJCUmtqUG6nO@EI2b7_v1DpWj=-#vYS$MOaK;QqVWmrU@{bCbMvXn#XWy)~-ujz`&>i1Wt&ED=NU z{i8$7G;MzAg_DG&GS*`P#`6U#ZH}&VZFP-A&cW>hl zE==?3xdjHpVSZuvc2Z{hU25*lBpHf?xi_6+AQU2NS^V_&asK;-DJ0MrviSMk+Zl~S zc*{T^zjgXNd*U(PG1$-1a+QP0I0q8(j#~Rfp~Rn5X7JE_aBP@YWi!k*9e(+RQ-q}C zy(0rW+?QipG{WPB62sw8Q0ustXYDlduc!xH3OHZ4`HAOGvglknhM|D5aEOl{+Q;}N z(k@oc73i^T+d&YFrjJa|@mRh{SV}%HG0Lm^vi!+~DL!^_nm>K;2sO{=r=EI_zq4(e zHxKpm{oi_uUpladca03&1eSHw+&nitHG?+aO2LLdZGJfDi^k+m!$ zQg%AwWTVM!)8@BMU*MnZ-^E?&BuWQG^Ga^uvFZz1goHp5sEq~JC1IK^J4z9j5>IKu zhC~8BuxvY6Qj)dIPM=w_9ZV_6TER4lhOZC;3XtDkE0aFN@c#iTwvL811X_3|LNp8J~y|>n}-JI3y1i%W5+pOsd8s3Ny+t? zY1mA}qU=w^d9G9@W*Fo`7Ec#T_yl%D!&jWDRM{4bt|A4k-?N*T!dmkJw_~r+K-@4G z35T&{K!ixw9CiUD3dyTr z4PRPV;-B5IkI`tDvg@*BJ3P9u%m*e$h#QjQl`3~-QyfaC`0Lqu3@P~G?c@CW6K61` zKlUWXeMd0vJA#NtFG~&$t<;5$)v&fo zi8Psra{)Sh?@ql>d*1v zUE7G8CS}*;%1> z$NR#g=$To}x4jvWNv}^1t%(|vP%p#~f?6vDpnn|~Xwh}?l)@5{Hx2eN6bZLFn&5?U zg~RD2KQJ-Mu6T@0%Rqep*a&|yHA`4Z`a%|;pIanlnf%7#1H5x&5MOI{#A9SEi+_9g zK*xahT1L0kilH{f3us?qz4u*+ zc!RvAD9>=Bqh7zG5*26U7e1< zUWdKXpxyR*E!uX^8N<1dby?}NdS}6MzCf*BXWRG~T5CMtLu-v~+r(orl=3kQ17G>j z>WJ-aS}RVSJx3;;rZ1amZPO^NFr*AVE5CCLLNGZ!16ngOG>BUVnQD!{`}9$U zBN0lj%U$Ud*^oudH2ATd6a3(|(ZHkA>LA^DQdbKp1oKUs#pcE_3<$g`!;vtOjccj+ zzR$(!X|&dC8y{nSafy7fh-I3TD-|;7G}T&-L@b8wxOl!tG7%?VD6xOfZhYToaXF7^ zn9MIOGSJsYzF1@+m!mJ2<=n+d3`3%IP*AQvm!np%BM{8YFHkI%$z?N?%4NdgU^zOa zGza(XVQOZUrfuVT9=`9BO{a;+V$>TAD%BdrQi;KVelAQ+)1S*ysa9J=FsRk*gu@~F zvROuk203-^9F}P!g~V4rdv@-?SBi5NCMi|Q4E6U@saBcxJYvx(i%ZK4^!Fi!pja*w zi$pOklR~jXDw!aYPGQ>)p6>;An%0CuA!g_1X*O;4?A)>LyIM^QA<(5V-Zvi$Bmf}N zX{`6X3%O@^hbY}6w}?eC?zU7 zr8QGCv-Ib()M|m3&-Z+m@_Dw8j|FOt6!^Z6Atl*#nsTK=)3&KptK>2nY$wub&vD(B zv;x<2nHU{mDW6|?CZ-uk3&3wG9M`2#ED?!>aoh;D;}8yqY1%eQDFz4nX*3#mzE3)t zqEf5k)~ZAz5gf;%-e^)RmM{!SJQkzYXrOGH(cvNLSI9cJgc$17Y4pNkM}0CLesw^K z%XOd@QRL3;m~VU-_b)#axOK}F)Ug)>Vyr!>6zqsbdJ3Wl;Ao{r$@58@tMjFVfT$_? z+}t8)c<<;C-#b3i@!!9;KiAPTdvy_C3tX*vEMLTF*&|ni2GXX*ws>^I>rzV5Y}(v= z_aPRSm+^cb*L6`kuo=)AtrYb}1H&+AG@C>t5pvlKsYHTMC`5H}iBvL4rCOy}DwEA- zh)1JHDG7xvT-T#qt%87By+JmU0j;rG@qkDqLZw>8^E?Ln`tUrDR5I|&`Cgz#S*D5S z`#6q^#-T5prBEsn35Q9<<0z$wMI%_2MZM9)bq#9u1|U{dcC<{BLa9VF5+N3iQmfZl zDinx>LPVp{F4Zqk$D)x42thItr(rj#HyT8Ma5&6zzCa=#!!k{T2+os;$4Mp=SeDgM z?Jntet0Lb@;eO%~{G&k)TDff;>+k#kA{Oh-1?xCCAN${^(`NvX6XS$_^amlbI;F!9 zf=Ba3{^9Yn>w28lcA&T+`OgP-^Quhh5>=<2-T{FW(60ai)`Jv+=|+POe(O7&u5LVC z*VmdOnKU1J)e$n*#sNX4R`hux1g`6X2vW}jBRS|OXU<o>N{0@U_J}7kZq0rGY!sNm4zK z0tk#^t#KWfO07o7GD)XWEpN|?w`I@H9eAEcBoe42p^$~=`|R94LB3FAWO#^>Wvv<| zwboeO9hQ~$AV{=~$6~}{QAUS{h=ju((rB#-heFUQnB9Gx5CY4xI@>JE3{;^|kh3JD zY;|@hl`9yA#57Homh+4b4|O_iyPY-+W99nWlA!&4baVx zoC2HiN;%F-@J>oZF1O;M?X`pSVyUBMEiUIV&A>4i^98E4I(v3*$Mrlew(Op2 z%f?A1lPu-)K|-iB=*wkTTFw&=g-9k7EG{h*i^cGLAKSL+%jIxgmqMwGZQEFug<(i0 zMn^kdueDgcb?uy@t4Z}1a^<+74EegdMGVP<>10oxNCMNg!>1RQZ#YswphkUhVUfr4 z#h&g*X&8xwxi_2MRAQv#y7c9;ND&yhGjj`En3_f@#Ztb2WtyERd9&HX_kGS!PEv0K zdbed+Ois_RxV+4T$tirLa6J#t^RP^lg~cTd!=T=1u(-TTBoZcHD3UK00X!YU;)%y% z#A7iU%_hZCnZf=63dLf_$hTYB#Pf@b7>1%NR(D&(rFsaCLznhG!3fNI;Lq*ESHId!-PVijsZM1 zGt0KIF+9&BlS+XI+_Sz4;u)1n70Wb;Mx!JXafA?5t2HWijlqF_ga|xPa8V03ug+x5oxfer9QmG{MdV_2_jpI1f8V!8kqc4}G zTCHMPR&Z>kLMoAYvw6icO!QSCT^WQfP2Bom2_T@en2a9xjd zDn+ecr(UmL@ma4BLu*7dg2-jj^9#WXJbwXf8$zMp-kjs0&Yq{GY(g>_{H^oum4@xn zF!!Yr{GY}Ah8?OsY5sps&GE1IZYObr)Ryu!{NcHaJY6jHTum`%7`%OCkdTx;6I^S} z@X#Qx>k?||+d@hP`}>hXGSC;evxN}!WwSW0%gE3mvZbbkLxFMI-%%k*h6V>nr&B@ut>|*QEdhi=A%qa@+p`M+^kp;nN(I|lvGJr3WYej@CUV`tz1nON z3We~!z;K=zAL|^`_A=^yJt z${@+`{Kde=PzpIQzHaopjj)uwy+6m7@+F#Us!FVT3L*GvzR1UCV|-|Q<9WL;Hw+>8 z%-lSGd|_&XP~{4ItvQ@d@=%YZcDi92MkghujaW2#iMvrsiPdFbTUM;|xt;kN4hNl? zF2hx}jO?}TMZ)3Be(yHe*D59kbPWAOJRStsTD7;@Ua{^9j)t-Ft=*QCvUBWu*Cs8C z9or^a4uIDEU1q8JSZhXMr0bq9hcz~a#@M$9k;?|1*>&;0{590n^h$ozx~)j`>^$z5 zz7iPkT0=C7arodBk5gK6Upm2&RJ`X-;sJj&JW^N^2>LAVis-qT61?g$vcM!Z>VaDTeuXL=1TcK z#_$NLzaO<2M8Ng@BJL;u5`V{bw<7!$~3Vl;W>u=K0Ozr#V;a zedz*dRcap`;GH8|(&A>oN=k?jP_Cj+ox^?Xan$tmN<89n9iaV!+cw3agP0G$re{*D zY6|$hi?jUx)a<5@Glk%dximjHKFq;Zg}IlilxMrD$Yj02N6%g4V;83>yWZxi6l%?A zG{XP5?{2;;o8FQZHvv{8hU22=7EueqOg%X|3WkA@61BLvB0*Zog-D68Oh_h?6XO_% zTQ)@x>eG6Vzz>cL@LaXV*9*P7KHGIyKfhGqXr;#chWdHWK#uW9xHHe;YPw;2g3_Yx z@VU7K{`mYP&zGy6-+D!R-uln&*};)@a=o^2V;-5Z^ckEc8 zDvgX_+;I>wJ`9NjBAEzWvMm?wwLl8N^VJ&v_{2FbY@&2!8}0RGw@1Rfxi7;Ta~bx; zqQp&!KwRR5>2|S-uBna<-{*X-!Iu}8`1H&?$4V7krLL;zn*#p!#3;XhXn)TRhAmuw z1jO(ax>!bZFJ#inwAA?$6iT>HJb_wRz`Fl_`5OoR)*|4vpyc^{yIAJ2VwsSXBu#^~X_7PyBCYyF zwo+7mpOWiS_B|F$Wo*aks8ZKLiX)jc|LV|wMx&A2QiT#iaI{?I8~M@=BPo^E?1)8p z%Rugmb7oehgsh8X9Qw0J+kw08LS)krkG?FVXhQ(+AMV4^ijQ2Fq1Gzudo}HJs+4O@ z-t|~^Jl0wr?fO(&DRht7u~$NS$>aa$t^*uMCT>eoK=522T`KU0le3pR(<_xkxSIVo zYNLI;(whB=IIqd3uUKQar-EyuKZmZ?gKWf1>Z%Rw&D@BA;Df^hm_qPhFV0Zhq$gfwl81+HozDAVZ|ViVEdvy`k5#w@QSTi5MP0dw!rsy#g=0{XoBecz}#) z^4k}tnQYqEJepq#eyhC9)n2av9_;JqUmx1X;q>h*DXs{mcsL$sS2T*P6yGYBIp=xA zMNotHj!1;EQe5;r2BqZPnP9ze}|8sbsJwo!O0)-k)VS9OAbxO!HLB zW%_c^!|$4RyxHrFNQ1WwkMh3pZDc}`tsvey&_KUwvOgB%1p;wBE$`YXX|y|(BIFQa+!y+Sr*G>2Et(m zOp|Yy%M3@O>&Vv#w=;ekws zqT_HRnPf*K!XM4duK|M)8H<@j`*J);w7( zaB6vVwILx_5gGHri_&%ed5a(+(Y~YDP z0S|chzyL#*MRF5`wqY|1$J_u=1a`;kb7>AIV|-z$$R`(;I9{#ewklIxZD;hAx+;1U@n|!+}^VSSi+ZsdyfH<8c-p zhb7l#tl2~f!GiDe)k+1UTIG1X&J*=IQYq4n2EI}>T56FiC4VwIOH4{0tyY z9GjnK#IpE&sYG>?PL-RA7;X4klQB)ce`J6+_GS1=zQ|{n3Orw}QStna`*kzj()azV zGQ0&)bzPn+EORiG?rbl)8aD#BIX7@y25+|tZUfJ*nOgdEt=9Q`rfV6x7dxp)lG&CG zINhD#+CpAy@~zIl&~8g9=GWSdt@1t_;ie=8tW2`$w@f}TJiy!fvpip|^VNKbC(BhX zG@I1@6))39M7dhSyNzcGdEPTRLAt$)kJ3~C*o{gNqw21HFu|y z!CER;z$?Dg*vo}>7Oc{mqU-UkVuL5kH71)4795);$D!h{-}!Z`pqP6NQyCc`aVzQm-((-e`o))r*Sn{x3M}Ema?_D=#BFb zdZ|`<%MfGLjRS^gt$_eUrNKZbNJC%G&8u3eAf4}8(-#ht3x%0&)Ty=$Twj4C5;#^W zvS>FM3I`=gn=N%JcbltI?WE3|3AZFMAXp!~ofe=8O4gW{A%^Gso!6$cW;hz{l7H%lqy2KDc zmaX5ah8UHSkdQRFG+VcAcq^@$h{gHoJ^MJ6&Z4#Ej&z1Q(iz_Ec}z9xJYOnsv{>X^ ztwPy#@w?o_u2MXeU*dHGgP0=7-Yt6?M?vWJHZ^WK+>*oyRH@+4*DEO-At_nw9?@EN zVi>y;Nj|)LANx}2j!UoY)ruMh`;sa4B~!d(WSrSXofpa_o+}nOQ!P_;g2f|WESH$B z*V&l}O5`_vsCtUN(B_t8-oo|8ElCUr=7AeRpb6}Zkd#CWiFP&JN|3J zfm@asQmh2mG!PPkm^4^hGSKrp?o4I)soi^-i1l9ht+O(dkW9qmY>UTv!7>KHEWvP3%d>9bM!;=B3y`uY{K>f9{qw2?c>?strR3;&OE{f_sx`etcrb zx}*pSqzQJ#Bok3d))Isyt2|xnL9LT=pa^oOUaFElH#=OdsrW(aPRaAoK*@118ag{P3`uk zSEaLj@6ZTo!(5jXNkgzBCP|v@q6y$AP0iPoJ*aw`rqUhbUTknJ6;EUPnuu|Gt5fYI zpFcIf#6%=a-f{WB=nzfc<8K!8+?P&La9toE$3#5NK-lEPVj06Q*^`KIv0A0>`8-pq zvOON7-!ciA28Bk0ujR|U6{vYWmJrl^g`+&`TJpBRT+b5wmL&$z8Q~!qLE?si6oS`f z`gq^aFmY+DJBnv5!H%dTYOJU}Qb5!YL=8b-2s{lm=xDDmC>S!8Ql%rLn>m*L|Vr*Y9(NQ$oF;ej-dFBd5I@Uy$O@r}i03cf~a zO~Z51Qn1i;*po;gwc;^yz8?mAZZGcra%!$le$lbC=EYIKkq)K;A#59H&SxME01;7 zDVevM*sZuyE*wT_9V}su#_n>6^nzO^iSUveBM7d&SoJ&goa(-hDFoqlNFfCbhb3bX zi7BowfnjCoqD>kzus?``~9WHE$gm@KoXcjT=qf74A>oe z=}EC3wg|Brou$OqJo=aN8C_F6vFhd zRVlbMmeEGe3Stxyxuxr057Ft^M6i;bQslxGO{Ex&M$oOi=$L5)g)l9XaLB+`KKqW`TR!`yD< zxaE!S+Xn))gI@eASpJ)q4ber4wlt8jpwmkWlmmV(P_eqTZy`Z7VDU3(Z6gN%7KjkH z6FIhsamzrX^IwMLFSfi+UEwTYLToRj?m)HbruzEyDr@#y72XYSbl|7#4?hI zi4Q~KK+AZ)^>IrF_--5cjliyOOROSAcnmTAX5ltX|n>rV#`0M2!A0 zSXov%NWC(8>GR+>uJ@h3V%Q?a%?=@F=+js`Yy!K z_Xh6U_BJ7*b{uLadh>4G0=PZy@>YiS(B-GVx4Sk9=zAl?uSWGzkh%}j53bp42j|h( zwp_x^f-Pd)3}~;zd`T*U0JjYFvt3?S4dD?)`c+qdK4~JduM48$tVE!xpIxJ_-MZK! z#*GRgKuS;w-Dsk#HFT{8PEbJuDT95S1@MY=UZvI$KL}Qit9Gwy1(8vR?&>nsMQ|Qx z;kqnP`buNVU3;TJ2+$h6oX0{4e$^mzo+d*P%5#vUJ5a@ax|B3J5KlLoSP=NNj9j#GXYYk`5 z<3I5&6$5ey5xW^RY40xJQjG3{Mxl$4*(kNS6PXK z0|L34Vwus2CcrCaIv}c0y1Fw}*K``!`qSP%9RQ=3qH?Wa_ z(BSRBi!EYYcX%HDvqzy3bYziAV!rLW5rYFkCttVrj|S7ke9Z&Mz4xH2(Vzp{4%+pC zc*C_ssf9q7p8*q^t5#xG72z0rEx;WJ-IVtZvh@2Q(@kU(^T0z<`}5J&5P}TY6Q7WZjnvf140HWRQ^#`5kN>t-VH|NdOx*S1Y5+oo)7|ECy@_;FMJa{`!R6l2wwG-Rw)-y zKaZaIW2hcmy|1t!_r`0Brr%`P@=9HAbSL=XkC zVT?NuLTjmIJvWc{=vSf9ymETC5cn^iz<>P7P5@904j^}J12cmd{(*oX$-}MkH;R>+ zd_DYWH<)|j7F)*q?FG~IjZR5JahVsP+htDI`%EWOdZj#S*OyhL*V|8^oy}kxMzGk1Zmp$kNE-DzN=w3)i8Ljq6~c3x_zL3jI9mDGjtd9` z8X+a|c#LYL68J{iwMBhJwNWDyiIdA^aO@_wZMW`0QK{8Q#^aPLHIj)qLI@IxB(7uQ zI1UJbW81_MDKhCK0F6e2X0w63nTY{GNvLWan$6WCNiu;5ht?&AE>{9KuV@V|LLyR0 zFpW$17qTT)8bKY~p6vw@NE>N_jB>-PQvxF42$p4Cds8Q#KdPr@7jf-6m1=`f!~!L$ zRZ4^tF-&QKHjqM7tCfl6`pG52OwTMZGB!r7u*CdwP$by0EF9No-+{fHJADc%Eetbw zDa}TMNFs*kz@2vZq#voMJQy_Xf!bliS4+=qA@_@`#wfX?^eE#kOrZU*;2Cv wLdc+^wepd@MvAv^%OjJ?kVqu1d9eKd0XM+pbQF5AivR!s07*qoM6N<$g87z;T>t<8 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/selectvids.png b/docs/3.5.x/docs/images/apps/selectvids.png new file mode 100644 index 0000000000000000000000000000000000000000..9ba693a6a156164f547eb4b615afaa43a2475a81 GIT binary patch literal 42214 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 KMNUMnLSTZ(DAHH} literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/sharelatex.png b/docs/3.5.x/docs/images/apps/sharelatex.png new file mode 100644 index 0000000000000000000000000000000000000000..e3ef6dd25e1f81de2a170ede0e3a3665fe98b80d GIT binary patch literal 19707 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 w+RWv0lh6Ai#~9=x}o)VD=23xZGidKsJj zrdNiB>)8CJxA=t{+wIs0!Na~0M)tq)d_;h~Hi9`2ycrN;y2Fpy31$g)x3EMo9fJ8i z!gO7J$%GYSeeE27^O$*h>FFaFi6YpE6k_v--#0AM_76Qa)>qf!55GUrWXIoB2u>%G zcISfV02g`%8t#m{2f#OokJT3(Xz_b4@QgRfz~(nz_X^vc@9tRPzIH~xQI7rjfoVJ5q$rjve?B?Clk7|63+1-IJ(i`pYJ$ zVqgG>fCRjNI|v3_fCrcXU7+{7QVBTQ{F>f&=m?_MQzudZi z_<$eqM4o@>9{)nO1+m~GBGn6o{TU6-hSorEC=ePEe|Em2#zeLi%^>P2(<3DvW05iK%e{)FJNH0il{^|eEjIsJyJ**Md04st@ zMcqPmqwb>~qgqf6fCtrvYDD#-?(N`z8-@7WDx}@{nj#~5fr#B-!T+O15q~*;Q>jF$ z6oAbxe*p5%@9zi>yITAGhm;7Ux+9YOk$0wl=lI9cf{1k$&^l;!#LkF~(M)JIAc2-g zEUt~#M0}utP<8*k*Y8#Wc<uuJaEq1c}Ysd}KMC{f8!qtTR>> z0B+iNM35qX(a<{$29N`4B>GvAor4buBYMgLMW6<>fIct*mcR};g9C_leL)bSaTGWL zj)4@A0kT0pI0s5WIj92Hz)jEqTEKnq5Ig|`UOm18RcqLyw_B=mqo!T7bSn z>o5wYgc)E?SP+(im0@kz6t;u+!#?mKI2KNZPr-$78GIG4hwsBr;1PHV{s1qd0Ez;| zgyKa>pp;R%C`*(J${R&O#iPA~)FNsPjYZR=dC(GwCymhdXb82pA5G7)BLijB&#FV4^T7m;y{C<_@L{S1(+Hga-S=L^taRXx=Z)hB8)Y5{6( z>I2lV)CJVHsQalGX~<{@6bH1RY=G)**PG|RN~v@*1ov_Z6)v{z^!)6Uc3=mhEX z={)I@>B{Lk>89yX^nCQX^d9s{^cD17^s@|D1|bGx27iVOhHDIc3`>l3jPi^QjM0om zjQ1F)m{3fDOvX%sOj%4fnMRq`nK_xYnZ20Pm}{Abm{(cYS+rQZSkhVQSVmaZS$SCX zSp!&eSQ}U;*wAdEY}Ra1Z0Fg!*cRCt*wxrQ*wfi>vX67X9HJaH9EUl|IeIykIk`9u zIYT+ma&~eqaxrmfartxQakX+SaMN>ZaQkuRakp{5=V9d0<_Y8}h?_Vk@G3@dGqD*b?`0mbMu??AK|az9~U4KP!{kNI3v(4uqr4d z=qPwXut9KMh(*X)C|0OO=#?-*SX20raGCJ12v$T{BtWD@WIz-aRS@+REfVb)gT)lZ z{KQJc2E{SrD&oQ7W#VHJloHw!krFi$ZzP!{%_I{g8zetT@k_Z#(i&xx7R^mH&9b6r%9abIn98Wt=IY~LiIX!V^ zbM|v?biuhexKz3<@6+Fxzi-x6!8OHobidI4=>3lmupJ0IaPJ`XLE^z%ZWuR5w<~U& zL`z~BaoOG2z1V%pL)YVs#|KX>&pgisFLkfeUUS~+-lx6iebjw&eHMH*eG7aS{dE1# z`F-&>@-OvY4X_Nj9Izee7+4pC4{{4?3Z@GV2!0U46%rjX7%CQ;5;}EA^-%tyC6Xzr zG7JjaAJ!PofLwBWBZMQ4N4$yDh%Acy5#^LX;o^S66{7l4|sY0{D#)D94sZmcOfTsOY|= ze5tyUtumu>>vHhrsVbYQ2h~c|)mJ#KWYxem5j6`}U9S#Y)4SGKD^Yu~j;Su=I=CKj z{rwHM8>2T(Z+6^LzEyi$;CAsH`a9|MP<>4OQiE^9RHJj_V3SExN3&Ybb(wZOdT8*lvs=5n?UDMU zmdC1(n|hRc8lEUVsqa772szWRQp{>A~7f#$)zgRMiFL-(KQJ$pE8Jp5$D zVq|dCe)Rd6>)6zD&*$?m0$+R?j~w54neYnpDt&@xqF|C^vh20U>$)k$se5nq-t@k; zefx6SWBS8P*v#f^@;k!2f;sNF>Ur7umIZ@_f%p5~&wdE~u(6o(k@jQpC*e=GKWlyN zU2$l6_<-d0SepKY-jRsD9-}zY7Yve89-l0g{A1zzMeFgyhmbHN?6)jCPB7FZbSiAlu_ERoUT%@`erXdU0K6TGfnG; z_A6byo}#{oLAGI|(WD7v%5P?9?r)K0dE4r_^$%MnJ2`txhakt3PPNWYT;A+ka$ViO zaS*tX6ItCQJhVM+ybgMM`4D|={r39v1V8~(fo(w-f|EjgL#+-elX$}LVV}cCBU&S? zqH?3-V*+EH4;vp*k5h_QJgSnQeatk`G07`A{P^*dyb~3vx6<0vdoxBeU!R;i^)c&f z_Hxe3>E+zzy!8U~8OB2Kvxet9ijEc+meihaD}8cd_~LlkRQW>1_e#`d#wyWjohz<2 zQCIV>-K-s~`*MT!rra&t+hKRI>#G}@8}B!DHn-os+j8e#U2An)d3(wI{Eqa_BML6ypy+Jh#Zwv?`weu0sONtv0*lFE9UZIXk6Q;usNcLL8v z-nKn2`IZGJ1i6J2gpEbqL}SEq#cxRTO3q88Wq4)x%DKpgD`Y5EC^acRRe7uWeJ@s> zT|-9GTq{sJOXs@ofZj&~ydkHNtg*g{y{U&;uz9payk(NraqASDRNHjBO#5_)WXBjM zUuQcPy?vUl2K!wOL>rP{VjJX?_>UA!KX7n&eEJyDGDyGEa^KxUAk~#_TuZZ z7v+N$k1n-Vwp{M1`gn!6X8+aVYcJ{;u3OwlMRu>XJCgOD4MmMZ&6vCLEeG!%Z>?-= zX>YxMr6apD?m<*n!o#fYl1Jr_&-a{q647h>RH6^vH{O49AY;&f$oiT7u>OeksQXyN z^W+yN#^YXkztWvxn^>G|dVONb>5ar&{M&caoiin~hu&$;QO*s|moFTB@AtuT(f4D} zr_j%#OQBy#Un9T8e2-f8TQOXvUcL20|HqRxm$i@U1Dljv6x0{u5&9wAD^e;NCT1kgD*;O^NRCN8l5Uo{ zB3mezAn&H2qKH-OSISp*Qejnjp<1HmxmQ*lt3IhwubHLgtF5Oas7s><^uFoO8H^g< zH7YRnG7&JDGA%T-G{>2DS|nK-Td`QZw{Eq`we_`AvnSY3I$U!+;$-5?==|EHYF`L) z{;%!7cOc=Qt{dKMkXY;<;IY?}(sSJFviBh$WuHyoHopXatpE_v9(XKBHy9n<6>>aO zJM_n)8j>?|W><$>hJTMJjNBVJ8I=&t8GSFtEtV;E{BX^Yq&TN|;rNxKoe81{D?Hj-R@om7X1tV|beG^uyeJxr=$R`Pv0KXHw7N z&!rd5l(3$cEmgUoa#5j7s$95&_Y!L*?Pc;RvTAB1lGLxdT{}^Gt?t?N&6~ovTyCGf zGuXh;=-gD?Jl2A_C(>%z=H7nv{`rp9&espNAM$qVKJs~-*>mH`Xzx~^NdLZpGlP@Q zWQR|Vd>XTT-ZakpGJitqHPxG_nT+|Ej}~87)~t8@|LYssPQfYykc;G*4kwYi06+5VV~wG<#gu~)G3-{y?K!vrlVWdtPTn59ni& zeGYGgHzqToG-WX3HJ7)rune}!vu?4OwIkTeJ2*SWIbCpm;4`8cwS>z@)I~`|--z9Ncpxt1C`ZC*VqUV@@s$&K zY2xW!nO>(DvtH*s&7H{KF623{syMI8t-yG-wI}il2Kogh)R}ci^K@O+@O`splf-Q&%l7dViZzu^WgYH9bVKgiR zo53Xb9NYFJc>`rbL!*Pn@g^5dyUms?*e&&~0+2H;&-RR6zI~p<1;;k0FD?rE z5?r4i;5r!Y*6+^e;q964b;rBUXU2EKpD92t&@L!4_*_VP=z9`#m_c}C#O28GXqp)F z*sR0P;{@a5j!qx*Nuo*aNeNHIrk%(@XQrNF&+5!c%yr7wJ)?G3tw^mzrBvi1y6j;^ zWF`CMd)4kWj8`XWyRP@&T)rdIaHQ!;3w5hrJE^1c!9usrP4L*IwLjLtou z9-n{p{WbK4e41gFf6i#3U{UFF`nSr}z_q@Oid91@9p;NDMNENKhfv4!wt&U_Ce-u7t-?v?ya#GO8W5g;qnyqMOm17;Q{CW(+HW zJ%*jYY2eE6czg(cm`sJNgd8UKCm*5Eqqs|{LV2HHMR-S*NX<*#PUA|mLYqw|LHCqC zn1R4h#i+yhiYbPfi@A^G6stR%4!bA^1IGsE1Xm;XX`Ucnvpv#$Ec{shHGwaJpM|~& zZ;4Wg@r!FoxJf2Rl}Iuur;YBq5Wo=emTAO8h}%D>4O?ag`s000JJOGiWi{{a60 z|De66lK=n!32#P5a{vGU000004**@VssR81aJ@-HK~#9!?frL@WXXNsiGCukO`nzJ zU03^_Hsc*;1|9=TfDlO$BtcQ6L`l?A6iJaXPw$8;h#L{Vh@bub#OFTu zIZcPcFeHj1Ow+`&EVR}LApp?2ciUwogt+W__j_I1?0WaJt^VHX+1K*?EA{JY@3I+f z>{I_|oAr6)cf0rWU)%WqjnCY8&&F$4`_5~5_pRRPTIhP$O8=N#Yg@0SU$5nRW-gao z_kolW(=;&*K@gynS~q#NZLfQtQVQSq(OP5MHl}F;5JeGT7-AR(wrwMX zAPhsoFhpyO<2aW+CkO(x*6Rkl|NEOw)RiVgYfT)-L{W521G&}0-E7fs_MIzT-;9yA znum?g6G9+_KuU>}viJAKd$0D6*Sestci~-ajJEg^Y%w5ZKX!;p5njZ&)jOv5lpr_-3G*?Ug2*(3}@EXyL3$smNl^E}$^Hjd+v zPN&gY({8u%eILUx$Ye6T$?ab2GEKMNwrykEc5gB0s|;lKSy2=b$1!0TqLk|O|4M`V zT2HqAzP#2Quz!(v7r$W`y>Zz1vsqi$()N|^c|AM*R*QPG=SeBiT6Z>FiIkhXPao6t zKfCw0*3h}8H{2(LKr4mP8fh3vAuzkUdp~n%t?_-IAP9OVNcX2ZA)8G$fMFP?GTaVfugi7k&RJ(0~7C{n~6C`rF+2`Bq}u)x^Gy z?|CIrxBq)rJH3RE%wIgq@e}8$t*x==&~5DAxs5Og5FLg|rBbXc&T;g_X^O=mcI}+O zFa&X|l5ql*2Fo&tV};hbGky}+bvbk52xrePP$`$W`@x5p7#+mitTX+C&=pt0Fzhjj zWm&z6+Ds(rGKXbZc%DbOT*k62gb=u{+ha1@w(&fVD2jT|>mSr8icm^n+jeik$8k)% z-6o16AlXf9+s1L6YdV&@r@}^N*tnoKzSC9{yKzBmwHP*IivES)FYaty_!}3{#^-I; zw=4B&tCQn;PT2ly-OcrC`qP!hXsdgLfYqf%o_Y2u&~RaKo+qBn;+iJqa)oRz&wD@c zFsEO6j?f-JFVFJlFF#MYyoTerNU6~zOrWBGK*g9OVt;mEn2&tqL(E;gz>`lu2TC!w zx{T|lFgG4MTfI^R9bgx zbajG$S-8uL-9_JjQV1ciEDOhRdOFHx3$J@JL{ZfH*|Wvm| zDn%G9V3-4(Jb99d=^4&loF_6Rj_Z=i<;Z8VpkvOSJx_jM5W}=Fqkv*@kWw*2D^Q#` zahzO!ko|l2uvV>;%A}Z^U&7q@!dKfV`X{W*B!*%1^bvqpUU`Ls2M@Bky2_CwM>u`@ zH0REpy zli_MI?#7d#E8AY_zRebT_xo`iZ@QQ^im%s7*R8C+#_zlpw3Q_fU~qJd`-ew+^O3BN zi0w1mC=HKM$Yl^xGCDqilqOnt#utqME}lP!oh~poGT0M&yKAaDZ`0eiubUIoaU7IV zy~Wg9K!!-pu}EFF~(aSX$_Ox)=olPHSF=kwUM{hE~Px9RFMIXQI=x($quj)B&w>)0er*LBw|46QXP ziV@E&qSrj4`$mY;60P*Qoo=IM-~B8I0`9%{UcUV0FY~8=`lrqL|&if~=GCq5~qNTpKi%&bD*y-cv+{abnU^3Pop! zjywO?3OYv@aq>8&6feH`0>_V>XZ7R&rBRy)KeC;>?zxrEfBy6Q$)EfQKlgJ#$8Y}T zZ}LmO^h*p44Plxlqobn$Jxf%p)k4a|deA*eyA0UR3|-o4x8JDfZl>UFX6L_F>OXCw zC?W^~#>U1H#t36nxrLAd921duuYabx&&avZ^by0^q}_50UH3o<LLFj| z6M3-YH8-bQKDz87hO-D0)Ug$CEaa}zrJKAERc_j;`NWm8%)V| zCImuhI9G>803&JC{p0XIjv^Wn@^}SVu+hV5M6BRq1H1@5nMLJHbP%J@Rnb9AJe47~ zK*fst@4ug&+iv6E|G!RPMh2s!qpYo!X|-BC1{fI`Aq+!)<2QbTv9U4!&fobv6pKX` z78WR%%Z!YSkj-XUUS6hDD&ct^%gf8;^La9vOz%ZDTl|}eJFmrhve`WwP23wTYU{}J ziT?0qNZE*73c0HYVFVFiNJv`{DvaC4z}{lH2UC3^1XHlDGQWF9vDSrtj))>)*}4f=fN@1wGi_|yA#pf zl+X+y1~HyP?i%2&qOLgy_1}-cqqB&DgDST%|IY1%et`UsFF+$eMGEtOehBroGw8?X z5Qan#x|qLuAMu}^fMaC|uzLu?Q@Eb+JE15($`@Bn6^{5Jg_F@Dv@v&LdnN`%uRm4~h z6zJJH^7e7$?m>j@Y%x^=QFKwK*AUVm`pQX+_iTrpjecPXT$AvByoe~K&}S=9Od+Oo z5Nh;V6WwZ{jxM4F2+PL$;X@erk8j>otk5fM|L^BeC(ERM{e6hBEZ#r< zOTvHsIO^mY?$6&1wu%3*AIEv`H0FD@v3Rb=OOMsqf9E*64rEECQf%9{jgNlxqx{bA z{0<-c*vI(%=ReP_x8BO#ci+v-%nU#Kvp>tv|NPIB$z=G^AN^6zpFhui_ua==zVa26 zQrvUTJ?z-AgJ!cyI-Tw**&7$@mWy-~+Ui8O5?#$?x_*>RtRJ`~SvWzbznb2p>qsFo zHX>(l{R}BFKd=WZiM~)lEw?dl8$(X!;QpE9aouNH5+a2T6(VgVfBO*_5@AVnD@0Bg zwrghqA|kfbNN5n^-?{8}0x0GVR~^4isFn1GnO5B<`IfsNodBfJJ;{ z5jm13eP9q$CgDsD|Es5xCp|R_wt>EX9FehDo@?+2|L!=)UJ!sHjwANn>0nxk<*IAJ zG7JO5Fo>cE+qTJMGW_h%{w%-$`@hd`{KjvP$z<5EV@K~~=qj_DdEl>P3*RcftN-t- zG00{L`&NF0etihXMC>2ldZF|^pRFudj)~Zv$oFC@j|gILO+>+6_l(V+yZPVx%GR>+ z9AZ4b>G!Ycvnx10u?@uDA+AjNEw$!#qW5Cz#};uveUQ{(nuTBa5@X?Qc6r~iO`OIf{`st_HwQCnA zPoCt$g$s<0jjanw*ywlIEZkzV7^538XU8uXfn zYK6#x18IwY@h|>Agl)+W{lMSgH~-DQ=f{5X6a36S_&A>L@vFc3tGKSqKl^9@tY_~R zLQt(%F${xTF30lna_{f1_j_$^t>?>Vx7$7ES-ASfw>`B#qXfl}f@E0R~*m!4y&?u}$~hcNgFM<~MlPNB8mKsh#|fFZ^E|ddC=l z{KtRHxpU|Em;dr#lF#RRfrbE6Q&Y5BEgZ*TWMri03GarU4-5?S!a%xV>D>_VZeZX> zCfVqK?EbxR7vC(h^;!e_`mJI8j?&8*N-5&!=MaM#^l}5acLb5QiC>;a*cO-qz1o0$ z7UPz|UMMyF&*{Ee_oFaQ{&O`Sg%=P%H;>p>K+n}N?wkZupiY<3D=p;SVXy_!S5F{@ z^Oz59OWN=w)O;OX3os6K%)Q+{^%)Qd;^dlnm3~Bu`0xUl2FAYO%kEcaSJ6uzWDN*G z?kXX&c6X94jYYR@t(7_e}!UUfZzJ9-{J!we3-xevwxfE zsp)k=gz0p;7fR7RA=>RWnM{UMDn+~9rrmD$LPxsMy4?la4O{Pe!n=7DS2}LDI*$9j z*IOy=o1Hk_kos=O{3Z>e4$l*xszVeYcP}A#55aPc=*6YP!n3ys%?0A8&R>#?Q#QI8 zKolp(ylrBBaz7$#5`F6oNE7qjGgoE~0ns;4fi%z!4|S@H+*TlZd=~TJ9YkL|3YJ8@ zIES|E#GGshv>%{ORFIPy)bZtxGm*qHB_-x3_9F~U^vGFAIhgO-&o;RKgM;g%Yx@_=Rw38@&a?g;jb0>c z9OHQ&#nJ#Heu~PmS?uWnKK_YM&{(TcIMQU>4@_ZL$wKx#ulKzEm@Uh)@O>ZO_i5yt zF`P}j*|{|8Y!xw4M5GPWnF{J$1^gJ@iXm#D{1{?|oX&$GQK!}rWgorTf`SWmA5u2P z2lhZlCjE%wWK+M=s*E*qB1`<@3hMYOa%KQ+OK1g&6w;2685i9o8G|!xiEk!~5r#zh zA=Cq;wBVs>2vl;CgfZ7cUM*twbenb~X4jz{tu>$HFSm&!MYA3w&YU@;y9;77vu1a3 zY&;SA<#44GwOWnJS|wS$e!$!l$Ef}3VYdC$1Nht1un-F)qtVkNTCEmg7?R0kdM85n)aWvT<2aYaPxUYS{z%vUxT=jwM^_6l-1zs# z>-~(?jpm)1nOU!6#0qtyoa}z>5Vh1qP7grZNJJ4Kde_#8DjgpI&^s06ov&R4a zPmZEujWh*X!?wL?>MH@|<*+lSTw;vP7D4~1uvN}QSJ^y!_AG1VwM2~YL)3TYhzl0c z&K#HmqY{!{ieX<7oid1(LK>1CJ9aQMG=va>D2gtNx^1;un5Ic8mFmgxp6B8Fe(z@$Y#0STP6Qo>Dm1oOE-RNY-|kI-4J#mH|Ptm)jHW_6d|tt5$oFSYy9CF-EHU+4?!tTLw115wtNzY_s6W zjrYG9{o1Op{o`__+@EWWKG^KpoBh8_zNd&nm6&TUv)CpdnB63!jUv+Zbf`;)VNfU( z=pv73tuYOgR65o3SPLO~Vdvc}y#B!e*5yxImPHgrJ>N(7R7j;#2qAhFEu~a1P4;Tx z-u;8#6%XOcA?%yIfByp9D2DYX@Nd@c^`w$+wNS2`F;hR|=545?yWMxKbp- z#{8G9j3ZmU|7O>=dXN6!LI_+JF7ZVFcy-58B=9+#MVxLnK$~@}3x(5#&FQ~x+x9vD zgs%ME-RZk0(^i84iI~)Vw(t9-)9Kzl-B5JT^LqX4CN)`>)w{m&y*8UnxWpvg+sR{h zYWHt;-Mm^P>Q-ELSyoRk=>L8-Sc> zcb7KKNB{Ny6yS{v(VwrrSp-4<{a4GUzZz|Pm#uW$D?NX+Q|n4|wDJGul^WdYS~n4= z3y-t00o%5F-t2zrI^ntl-H$VMr4Dz+DXn!+r0SpGE?7dV)mj%G(mg%;O}kfHz?%(n zzqr-)QS_fC*E;!InZmC&{+p%TZr0{z*EhcFwTdwPn^ku#`)OkoLHDz*!f&qiq}-|> zR~y&OKI?C9D-~g@z)^Fv8@A&3E|g9eMQ}569H(cA>3>dFPv|z>^5j? z3=FJW8|ieq2a?g9Z{PQOjL~Q`Xt&##rb!S4>*l5(h_Aa?fpzoUk8Rfd|3-%Bzqavo z?rxy{_jTvl>?+9JMblltT?cPX zy%?!3AVRnOIF3oD(>+L??*F^HQg;#Bw%t?2fu66U%e39Rj;@Yk7zWvFmLLddG#Wj) z(004sTc}-l9@lj@?OQi!u{$i6bc2DQaymXF36ql`xFX=9#eK9PdCn6|JbC{ zY3lWQZ*KY*f46VhY_^9r9LF*Fd>*9~rfHH+r+ecc1VOKT!!Ua0cgJyPx7(Yp8{4*N zHk)L#*3c)C%bdwd0r2cudDNR8MfVSV_6oqZTD~jx{U65UQdtg z>aSfDKOhbAU{uT?2)%4b<5c)T)ne28fJ_uC!4X zYoIOcU%o%dt++{P%a!YgA-{3N=S!=S-`ua^$PvEz%|}UP98?sc1*Fm$-v9827%mmj zVZ_d(*`o`nI!t^IpkCpwa`Y+6wqf@5`@Y57V^MQ0*7<1O#GyS zI=ldAqOY7p?k)lb>eWSbD}r{MWEyIL7|LM&;9laV=aOV9Un7Q`1V_t}u-qnodKQtB zkjo?Y4j@NLNlNrhOj|OB4g(%6!oIxZ-du!t*WFB4s~|wdF}plq0iA^rF@p+p@4bw)?krjPGNLVszC<45lx?=7mXW>R9fkU+~vTZ<}l1rnhMm zy150tx9M$qi|B2}c$?m)O{g28g}P8d)|w=(#Fl z`yl$v8afCu?wbJ>5I-}AUTS0h;6dbwP4tZm$h$^}A3cj0&7sfN5L3Bi;m=pmjUXwM z5@?LOM~R;}kJb{oyGZ=)i^x02u>Sg?o7ygZvrrsIC>3K_&g*~JYoKPm#knI#5Z)r0 z(gfZiR5)hO5UkFjj;$dk-NbA8@(QeZXl0^fjh=5J2D0dCj5st3S|E21 zpiWlMbssUX2f3|;+@6O>B2p&8wUb@mk zNC~D$?A?};)G{d8&62{OZi!xT1W0GF>4K88$=0dtleve2w@hkxLs%-L&D0TcKA-Ari4`lg0#H~ zre=0y7;h{h`|47KN51qlje0A|r#2jFevwuyAc|v*#TCpazlK{JWyihmza|K$H=0ZU zr4_4=uUXYb=gqTJ08@ zbOr=Su^xL#NJ*=ieBUsWU0oo0S!w`L95LXONV_+m!q!iXMx7_W`#6*z?Q)!ySfl0enL+J$VCG(v>Co?e0*xp;;wDH-BdMF_(jyZSs42J2F&7^3xT4eJ@ zq=0Ir%v!mEVcBFeDYP(fT?ZY9oIP`z7=v6UMK+tqFeFjE#>Ke>hK7cdf#`&k*p7oh zv$C{6t?7}=CV9Y(W*w;o*}?#}WfFL6tduL5riJ6!wAyX*o&4!szL1n3xQR(A#q-ZT z%ek{>vF#MCR-0<2%(uV!EiBt*|G`6VN+i&C zBojI?B1mSo?*v3gpVbH>o_UJ-*;(9Fij?b8tu^q20EFb+xmmvah0pWDKlWqf-XJSX6owo<{2a?G7cp!T z(@gMu8`UP|)wMpL28hC#xr^uC5XM-%xXRqAW#Tvix-bku6h|0Qr|`WsjF1^TZ;dq# zh9R*mgVf89;$-q1eE3JO?6;;Ol?lm$92pmqLj8jV&8)9hplqI>OYom6s4x+1WxE0q0xi|PE?)68GIfRLJ4X;PUC z!Z2AYm#H@zq|#|#dF3#Lfv@rLPks{9ys;A>MIpzJzRbnhQy7+s?YNkhg;Fu?RzMsp z9NR+5Bw9L^&af~y%ijIBA&ncCSf;h+^sBQpYpouplhO*&fj)}j7-?oP+)@1cGGW{X z4UT1zu`~lOe4Yybi@ULuM^+*At7PH=e9lE4cIf{?c7GawU8t1yc2J&!Q(a8fr; zbn*R=*|Up@G$26f#Plc)6OBe7kkTZTouImUlqim9dLGN=Dz2dzO-IZ<`6m>oc2gRA z^Yx8H`3_^e&%Z=;WMQ3?Oh|+FEf$ad+kZmq;#^V~B$)x6p%Fgt>wleMMBO{~i+Ozj{x2?72?CBGnKlK8EU&qN5u$>fP7?HBfj>WKr<0P2Eq9ew(nk}*^ z6Q!=NBGJ{TRc}*YYl0A%mVpRlr(|7%j~l5N9fLIT*iIS|G?Q{)K|rU4MIrU3N3-r-UK~V2tPHF!bDYNf?$rAGPHuQPY*=$k*6SG}W8zu5HJ<`=lK>wJrA8vM}5 z3w^xM>-@9{;@~ZjGp~oV)(8|S*Cmt9GBPsE&|rz}+qY3F6-cFB1_}jq9Fb1DjE#>W zgl4V0$`g-0is!XobK5IR3!FIeG=^@I%jOs;l&IGl45S@~OGTnkvAkTtb!<}U6n>Dv zUuH5XcJ12E;Ls4p4b(3H5F$Ahbb=t6%Vlv=DTM3*a(5#v3;>HkbiN16E%l&KAz_|| z=d)aH&?wJy;mI%Id;aU~(RIvfp4H<`w4Gj^;F_l`AFpP0isYLm9EONOlQfRW7ESBpcZ?F-dG?b?_QsCmr zIfO_Ywyv8djul~)KxLvehBS!G5~k^5NR3u8hR}qOqFis2buFxu-{t%(?_|$C558%$ zd1)53USHR&Z?d&giBqk+ZFfFHD?nY+G$Hw{`}wA%P&)bPKLnIk#Id3kctlayJ5-bc zFR+s^5vA9iaawIs8TG9q4H|*cnp`eRabN&QEPl;ai@kexZ!n7>>&_ij3Mj;IY zVGhuWOXQ3yDH}4Dz>t!55L0e=WUH%OeD14E9k`QJ`pt=WNc^R?&Fkejl@h#QZe-I{Zs5XILTr)Lg~KeX(;U&x+xTIgdhk*TFn;e zw43m?6iCCMkS|ay3OwJ#bsW;EG?r=6Y_@RIY1*DgWv#;LQzyyg3vA!H`>M?azR#(n zFH&1MPd1&VP%Po5GMqYdmV7!zCY_;LtHZ%vuRT4G{Um6 zZ=f}*Z#dX@>kQ96dYERV30h#75>RNZ5K<6_3MmXs)5S^;(ewlZsTu=02^u^vpxz3o zHa$}3USRI%3+%e=zXKy7ESQnBL_(sBMFz4(&C*TyOkf@{{X8)?^tjCP34%{c^A{aFhQ#m zhm~A}(cvNXjh!ak^mQKIX4t=P4?A|uFf=$w zDxF4ag=<^AK+0@3MJDYMYr**FFcV|LRO?Mn9)Fc=F2~UD*0~Z&DbAicN_p-S*|bZc zSR$Rx(e?xCwF=v3wqu$mxm*r!wT3hdrluw+7V{i9cnc%LBS=GH+76j~>4u*cT^bo1 zVAr8-9Dd>ikQ5FQ8Vq5eb>i#NLStDDcieRk7cU+qsIE}Vd02*`-fYusdQ=)dx#|iR zp7}D9x7?1KPQT8cU7dQdQh|<%(!IPT&`D6={M;O0d+ae9wOU_rA>?K+^30LL{MPS$ z_OgdQe{7ad-ao^UC%>_7&|{@Q4D*h6zMH5~fj)C>t5##l86s$U$PJFhdS#U;^*?a+ ze_!8_CaEty@JV|4u5TetZ`;nu*aUy{hkwK${_*D+9U0-!!Tr4B{(CrdU_XUo0V$K{ zVZ$^~aRf*P2L}lJfLuP$((($k=T9R93=Un+97-uJoI6E%;S?#yq&QF_oy}ufHs>$S zlFR1FW)r`Tl#*(_&5j+@%*@Pm!r${)rUgQf&K9w(H!jRuO38sccJlI*Cm_<8(!@3$ zLNh`~K_W(VA|FhVQP4rF-&9qk0Cn&fSsI-u7Rqjx@;b9 zo`_Ui=`1&ijsc|H6z_c3yVQ|gszawBt>Ej%f_^9Y%570 z5JED0afM=Th>!fp5Ax#4i=3KmGBH?U+r$use3p94r&U|y+>?JnvtED0`@N1ax`jmg ze{Kr-{d%fq+eS<5m>MCSO;K%mG|s=kx#u5$!?(k$GDhdDd&39t`-SrP zJa^u87pZirvp|!ukff}apxJ1Ul^&-LKg+XEKf}`MDxU8XMlnGU;&~on5Fm7n->Oqt zUF-lDD9)cgPTVS!&1A^t^4Lxa({_=D#oYW7xm*q@4NS`J@pvRKmP*FR-0z4jpupzor<`=*P^-hnZg3`bMLdrxGwp`Nb3{nV8Gb!iXZ2NrnGoNM0&h41j5s0bch=uui78Vv* zT3X`#`3v|#c+KA*9xc+8DV{mH24Ra^cL*MQ=PnA_ES6>W>LFgZu*Blr8sn4Gy!S&N z<;>hgzI~)d%5j()8DMgJ2!&+j+{>JJ;x8}H1igXO3p?M;cCNK%Y;25=e)OX(E-kII zA`K4@vwg=7f*_#TTp!}`&Ue0(+josIIzCB%61S8F4}J7g3=I#`tgNiFJeju3z~l~O zs*+eQ`r687^Vr3o06V_SDn;&xxEU1hewvt=V)yRdy!_J3m@<*+wbl#{miSvg_YauZ zInKhVml!E#Ddk*VJ$Zpgzx6HdfAAq(+aw5l;@H6Vd@Rc(jAB}qMe-S&bf$o1I|#!} zex#&UZ!tJn!nW<6LphtzV_KI=I2)$Lx4!ZSCr=z@&)#3XuJ?(ffIs=e&tRppEYHtT z^A!K^mwu7S(b6@2Kbv(K9v$YD!$)}FV3mAn8xMTs9W;Hx^7t zTDriQGv~1_$@3={xO49qyN4wsrF>HTx9zcd`0Fg+^)5!Ix4j{A*mLl0<#EmBa{Sm& z{KS?Ic;JDp?aB{)@ULBWhYABjTU?oh+{16kAlzuOZJS&6A3&);29bn@K!rW4>5KpHlt6t;+xS%x4)KEHX4aa$WCZ7$yUS0_mYK98

    UgJe6f|Y=Yr! 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 M07*qoM6N<$f<=x}o)VD=23xZGidKsJj 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 P00000NkvXXu0mjfkLXIi literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/stachify.png b/docs/3.5.x/docs/images/apps/stachify.png new file mode 100644 index 0000000000000000000000000000000000000000..14a64c23af6ffe25419224c9e6313b366b925014 GIT binary patch literal 27783 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 DnZfGr literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/todaylaunch.png b/docs/3.5.x/docs/images/apps/todaylaunch.png new file mode 100644 index 0000000000000000000000000000000000000000..f75fba3bda92d1387dc24b7cb6d5eaa648fff69e GIT binary patch literal 33233 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 KMNUMnLSTZ9^9~09 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/upcload.png b/docs/3.5.x/docs/images/apps/upcload.png new file mode 100644 index 0000000000000000000000000000000000000000..4199712ee7ca626e6f2b45800fce43336a6da398 GIT binary patch literal 37792 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 C>_hDU literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/wavo.png b/docs/3.5.x/docs/images/apps/wavo.png new file mode 100644 index 0000000000000000000000000000000000000000..3ab6bb877c1b05a6f2f20a8cd697bc21ee84a7aa GIT binary patch literal 54906 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

    Getting Started

    First be sure you have MongoDB and Node.js installed.

    + +

    Next install Mongoose from the command line using npm:

    + +
    $ npm install mongoose

    Now say we like fuzzy kittens and want to record every kitten we ever meet in MongoDB. +The first thing we need to do is include mongoose in our project and open a connection to the test database on our locally running instance of MongoDB.

    // getting-started.js
    +var mongoose = require('mongoose');
    +mongoose.connect('mongodb://localhost/test');

    We have a pending connection to the test database running on localhost. We now need to get notified if we connect successfully or if a connection error occurs:

    var db = mongoose.connection;
    +db.on('error', console.error.bind(console, 'connection error:'));
    +db.once('open', function callback () {
    +  // yay!
    +});

    Once our connection opens, our callback will be called. For brevity, let's assume that all following code is within this callback.

    With Mongoose, everything is derived from a Schema. Let's get a reference to it and define our kittens.

    var kittySchema = mongoose.Schema({
    +    name: String
    +})

    So far so good. We've got a schema with one property, name, which will be a String. The next step is compiling our schema into a Model.

    var Kitten = mongoose.model('Kitten', kittySchema)

    A model is a class with which we construct documents. +In this case, each document will be a kitten with properties and behaviors as declared in our schema. +Let's create a kitten document representing the little guy we just met on the sidewalk outside:

    var silence = new Kitten({ name: 'Silence' })
    +console.log(silence.name) // 'Silence'

    Kittens can meow, so let's take a look at how to add "speak" functionality to our documents:

    // NOTE: methods must be added to the schema before compiling it with mongoose.model()
    +kittySchema.methods.speak = function () {
    +  var greeting = this.name
    +    ? "Meow name is " + this.name
    +    : "I don't have a name"
    +  console.log(greeting);
    +}
    +
    +var Kitten = mongoose.model('Kitten', kittySchema)

    Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance:

    var fluffy = new Kitten({ name: 'fluffy' });
    +fluffy.speak() // "Meow name is fluffy"

    We have talking kittens! But we still haven't saved anything to MongoDB. +Each document can be saved to the database by calling its save method. The first argument to the callback will be an error if any occured.

    fluffy.save(function (err, fluffy) {
    +  if (err) // TODO handle the error
    +  fluffy.speak();
    +});

    Say time goes by and we want to display all the kittens we've seen. +We can access all of the kitten documents through our Kitten model.

    Kitten.find(function (err, kittens) {
    +  if (err) // TODO handle err
    +  console.log(kittens)
    +})

    We just logged all of the kittens in our db to the console. +If we want to filter our kittens by name, Mongoose supports MongoDBs rich querying syntax.

    Kitten.find({ name: /^Fluff/ }, callback)

    This performs a search for all documents with a name property that begins with "Fluff" and returns the results to the callback.

    Congratulations

    That's the end of our quick start. We created a schema, added a custom document method, saved and queried kittens in MongoDB using Mongoose. Head over to the guide, or API docs for more.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/js/cookies.min.js b/docs/3.5.x/docs/js/cookies.min.js new file mode 100644 index 00000000000..dc94dbc5bbc --- /dev/null +++ b/docs/3.5.x/docs/js/cookies.min.js @@ -0,0 +1,4 @@ +/*! Cookies.js - 0.2.0; Copyright (c) 2012, Scott Hamper; http://www.opensource.org/licenses/MIT */ +(function(f,e){var b=function(c,d,a){return 1===arguments.length?b.get(c):b.set(c,d,a)};b.get=function(c){f.cookie!==b._cacheString&&b._populateCache();return b._cache[c]};b.defaults={path:"/"};b.set=function(c,d,a){a={path:a&&a.path||b.defaults.path,domain:a&&a.domain||b.defaults.domain,expires:a&&a.expires||b.defaults.expires,secure:a&&a.secure!==e?a.secure:b.defaults.secure};d===e&&(a.expires=-1);switch(typeof a.expires){case "number":a.expires=new Date((new Date).getTime()+1E3*a.expires);break; +case "string":a.expires=new Date(a.expires)}c=encodeURIComponent(c)+"="+(d+"").replace(/[^!#-+\--:<-[\]-~]/g,encodeURIComponent);c+=a.path?";path="+a.path:"";c+=a.domain?";domain="+a.domain:"";c+=a.expires?";expires="+a.expires.toGMTString():"";c+=a.secure?";secure":"";f.cookie=c;return b};b.expire=function(c,d){return b.set(c,e,d)};b._populateCache=function(){b._cache={};b._cacheString=f.cookie;for(var c=b._cacheString.split("; "),d=0;d>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?[].concat.apply([],a):a}function H(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function I(a){return a in i?i[a]:i[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function J(a,b){return typeof b=="number"&&!k[H(a)]?b+"px":b}function K(a){var b,c;return h[a]||(b=g.createElement(a),g.body.appendChild(b),c=j(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),h[a]=c),h[a]}function L(b,d){return d===a?c(b):c(b).filter(d)}function M(a,b,c,d){return A(b)?b.call(a,c,d):b}function N(a,b,d){var e=a%2?b:b.parentNode;e?e.insertBefore(d,a?a==1?e.firstChild:a==2?b:null:b.nextSibling):c(d).remove()}function O(a,b){b(a);for(var c in a.childNodes)O(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=window.document,h={},i={},j=g.defaultView.getComputedStyle,k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=[1,3,8,9,11],n=["after","prepend","before","append"],o=g.createElement("table"),p=g.createElement("tr"),q={tr:g.createElement("tbody"),tbody:o,thead:o,tfoot:o,td:p,th:p,"*":g.createElement("div")},r=/complete|loaded|interactive/,s=/^\.([\w-]+)$/,t=/^#([\w-]+)$/,u=/^[\w-]+$/,v={}.toString,w={},x,y,z=g.createElement("div");return w.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=z).appendChild(a),d=~w.qsa(e,b).indexOf(a),f&&z.removeChild(a),d},x=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},y=function(a){return a.filter(function(b,c){return a.indexOf(b)==c})},w.fragment=function(b,d){d===a&&(d=l.test(b)&&RegExp.$1),d in q||(d="*");var e=q[d];return e.innerHTML=""+b,c.each(f.call(e.childNodes),function(){e.removeChild(this)})},w.Z=function(a,b){return a=a||[],a.__proto__=arguments.callee.prototype,a.selector=b||"",a},w.isZ=function(a){return a instanceof w.Z},w.init=function(b,d){if(!b)return w.Z();if(A(b))return c(g).ready(b);if(w.isZ(b))return b;var e;if(D(b))e=F(b);else if(C(b))e=[c.extend({},b)],b=null;else if(m.indexOf(b.nodeType)>=0||b===window)e=[b],b=null;else if(l.test(b))e=w.fragment(b.trim(),RegExp.$1),b=null;else{if(d!==a)return c(d).find(b);e=w.qsa(g,b)}return w.Z(e,b)},c=function(a,b){return w.init(a,b)},c.extend=function(c){return f.call(arguments,1).forEach(function(d){for(b in d)d[b]!==a&&(c[b]=d[b])}),c},w.qsa=function(a,b){var c;return a===g&&t.test(b)?(c=a.getElementById(RegExp.$1))?[c]:e:a.nodeType!==1&&a.nodeType!==9?e:f.call(s.test(b)?a.getElementsByClassName(RegExp.$1):u.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.isFunction=A,c.isObject=B,c.isArray=D,c.isPlainObject=C,c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.trim=function(a){return a.trim()},c.uuid=0,c.map=function(a,b){var c,d=[],e,f;if(E(a))for(e=0;e0&&w.matches(this[0],a)},not:function(b){var d=[];if(A(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):E(b)&&A(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!B(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!B(a)?a:c(a)},find:function(a){var b;return this.length==1?b=w.qsa(this[0],a):b=this.map(function(){return w.qsa(this,a)}),c(b)},closest:function(a,b){var d=this[0];while(d&&!w.matches(d,a))d=d!==b&&d!==g&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&a!==g&&b.indexOf(a)<0)return b.push(a),a});return L(b,a)},parent:function(a){return L(y(this.pluck("parentNode")),a)},children:function(a){return L(this.map(function(){return f.call(this.children)}),a)},siblings:function(a){return L(this.map(function(a,b){return f.call(b.parentNode.children).filter(function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return this.map(function(){return this[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),j(this,"").getPropertyValue("display")=="none"&&(this.style.display=K(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return this.each(function(){c(this).wrapAll(c(a)[0].cloneNode(!1))})},wrapAll:function(a){return this[0]&&(c(this[0]).before(a=c(a)),a.append(this)),this},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return c(this.map(function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(b){return(b===a?this.css("display")=="none":b)?this.show():this.hide()},prev:function(){return c(this.pluck("previousElementSibling"))},next:function(){return c(this.pluck("nextElementSibling"))},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(M(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(B(c))for(b in c)this.setAttribute(b,c[b]);else this.setAttribute(c,M(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&this.removeAttribute(a)})},prop:function(b,c){return c===a?this[0]?this[0][b]:a:this.each(function(a){this[b]=M(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+H(b),c);return d!==null?d:a},val:function(b){return b===a?this.length>0?this[0].value:a:this.each(function(a){this.value=M(this,b,a,this.value)})},offset:function(){if(this.length==0)return null;var a=this[0].getBoundingClientRect();return{left:a.left+window.pageXOffset,top:a.top+window.pageYOffset,width:a.width,height:a.height}},css:function(c,d){if(d===a&&typeof c=="string")return this.length==0?a:this[0].style[x(c)]||j(this[0],"").getPropertyValue(c);var e="";for(b in c)typeof c[b]=="string"&&c[b]==""?this.each(function(){this.style.removeProperty(H(b))}):e+=H(b)+":"+J(b,c[b])+";";return typeof c=="string"&&(d==""?this.each(function(){this.style.removeProperty(H(c))}):e=H(c)+":"+J(c,d)),this.each(function(){this.style.cssText+=";"+e})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return this.length<1?!1:I(a).test(this[0].className)},addClass:function(a){return this.each(function(b){d=[];var e=this.className,f=M(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&(this.className+=(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return this.className="";d=this.className,M(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(I(a)," ")}),this.className=d.trim()})},toggleClass:function(b,d){return this.each(function(e){var f=M(this,b,e,this.className);(d===a?!c(this).hasClass(f):d)?c(this).addClass(f):c(this).removeClass(f)})}},["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?this[0]==window?window["inner"+f]:this[0]==g?g.documentElement["offset"+f]:(e=this.offset())&&e[b]:this.each(function(a){var e=c(this);e.css(b,M(this,d,a,e[b]()))})}}),n.forEach(function(a,b){c.fn[a]=function(){var a=c.map(arguments,function(a){return B(a)?a:w.fragment(a)});if(a.length<1)return this;var d=this.length,e=d>1,f=b<2;return this.each(function(c,g){for(var h=0;h0&&this.bind(o,n),setTimeout(function(){m.css(i),e<=0&&setTimeout(function(){m.each(function(){n.call(this)})},0)},0),this},i=null}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){isObject(a.data)&&(a.data=$.param(a.data)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function serialize(a,b,c,d){var e=$.isArray(b);$.each(b,function(b,f){d&&(b=c?d:d+"["+(e?"":b)+"]"),!d&&e?a.add(f.name,f.value):(c?$.isArray(f):isObject(f))?serialize(a,f,c,b):a.add(b,f)})}var jsonpID=0,isObject=$.isObject,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){$(c).remove(),b in window&&(window[b]=empty),ajaxComplete("abort",e,a)},e={abort:d},f;return a.error&&(c.onerror=function(){e.abort(),a.error()}),window[b]=function(d){clearTimeout(f),$(c).remove(),delete window[b],ajaxSuccess(d,e,a)},serializeData(a),c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(f=setTimeout(function(){e.abort(),ajaxComplete("timeout",e,a)},a.timeout)),e},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=$.ajaxSettings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:JSON.parse(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,"error",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b){return $.ajax({url:a,success:b})},$.post=function(a,b,c,d){return $.isFunction(b)&&(d=d||c,c=b,b=null),$.ajax({type:"POST",url:a,data:b,success:c,dataType:d})},$.getJSON=function(a,b){return $.ajax({url:a,success:b,dataType:"json"})},$.fn.load=function(a,b){if(!this.length)return this;var c=this,d=a.split(/\s/),e;return d.length>1&&(a=d[0],e=d[1]),$.get(a,function(a){c.html(e?$(document.createElement("div")).html(a.replace(rscript,"")).find(e).html():a),b&&b.call(c)}),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace("%20","+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a){function d(a){return"tagName"in a?a:a.parentNode}function e(a,b,c,d){var e=Math.abs(a-b),f=Math.abs(c-d);return e>=f?a-b>0?"Left":"Right":c-d>0?"Up":"Down"}function h(){g=null,b.last&&(b.el.trigger("longTap"),b={})}function i(){g&&clearTimeout(g),g=null}var b={},c,f=750,g;a(document).ready(function(){var j,k;a(document.body).bind("touchstart",function(e){j=Date.now(),k=j-(b.last||j),b.el=a(d(e.touches[0].target)),c&&clearTimeout(c),b.x1=e.touches[0].pageX,b.y1=e.touches[0].pageY,k>0&&k<=250&&(b.isDoubleTap=!0),b.last=j,g=setTimeout(h,f)}).bind("touchmove",function(a){i(),b.x2=a.touches[0].pageX,b.y2=a.touches[0].pageY}).bind("touchend",function(a){i(),b.isDoubleTap?(b.el.trigger("doubleTap"),b={}):b.x2&&Math.abs(b.x1-b.x2)>30||b.y2&&Math.abs(b.y1-b.y2)>30?(b.el.trigger("swipe")&&b.el.trigger("swipe"+e(b.x1,b.x2,b.y1,b.y2)),b={}):"last"in b&&(b.el.trigger("tap"),c=setTimeout(function(){c=null,b.el.trigger("singleTap"),b={}},250))}).bind("touchcancel",function(){c&&clearTimeout(c),g&&clearTimeout(g),g=c=null,b={}})}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(b){a.fn[b]=function(a){return this.bind(b,a)}})}(Zepto); \ No newline at end of file diff --git a/docs/3.5.x/docs/middleware.html b/docs/3.5.x/docs/middleware.html new file mode 100644 index 00000000000..6aa1061e6ba --- /dev/null +++ b/docs/3.5.x/docs/middleware.html @@ -0,0 +1,40 @@ +Mongoose Middleware v3.5.9Fork me on GitHub

    Middleware

    Middleware are functions which are passed control of flow during execution of init, validate, save and remove methods. There are two types of middleware, pre and post. Let's start with pre.

    Pre

    There are two types of pre middleware, serial and parallel.

    Serial

    Serial middleware are executed one after another, when each middleware calls next.

    var schema = new Schema(..);
    +schema.pre('save', function (next) {
    +  // do stuff
    +  next();
    +});

    Parallel

    Parallel middleware offer more fine-grained flow control.

    var schema = new Schema(..);
    +schema.pre('save', true, function (next, done) {
    +  // calling next kicks off the next middleware in parallel
    +  next();
    +  doAsync(done);
    +});

    The hooked method, in this case save, will not be executed until done is called by each middleware.

    Use Cases

    Middleware are useful for atomizing model logic and avoiding nested blocks of async code. Here are some other ideas:

    • complex validation
    • removing dependent documents
      • (removing a user removes all his blogposts)
    • asynchronous defaults
    • asynchronous tasks that a certain action triggers
      • triggering custom events
      • notifications

    Error handling

    If any middleware calls next or done with an Error instance, the flow is interrupted, and the error is passed to the callback.

    schema.pre('save', function (next) {
    +  var err = new Error('something went wrong');
    +  next(err);
    +});
    +
    +// later...
    +
    +myModel.save(function (err) {
    +  console.log(err.message) // something went wrong
    +});
    +

    Post middleware

    post middleware are executed after the hooked method and all of its pre middleware have completed. post middleware do not directly receive flow control, e.g. no next or done callbacks are passed to it. post hooks are a way to register traditional event listeners for these methods.

    schema.post('init', function (doc) {
    +  console.log('%s has been initialized from the db', doc._id);
    +})
    +schema.post('validate', function (doc) {
    +  console.log('%s has been validated (but not saved yet)', doc._id);
    +})
    +schema.post('save', function (doc) {
    +  console.log('%s has been saved', doc._id);
    +})
    +schema.post('remove', function (doc) {
    +  console.log('%s has been removed', doc._id);
    +})
    +

    Next Up

    Now that we've covered middleware, let's take a look at Mongooses approach to faking JOINs with its query population helper.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/migration.html b/docs/3.5.x/docs/migration.html new file mode 100644 index 00000000000..190fd95143c --- /dev/null +++ b/docs/3.5.x/docs/migration.html @@ -0,0 +1,40 @@ +Mongoose Migration Guide v3.5.9Fork me on GitHub

    Migrating from 2.x to 3.x

    Migrating from Mongoose 2.x to 3.x brings with it several changes to be aware of:

    Query clean-up

    Many methods of the Query API were nothing but aliases and have been removed in an effort to keep Mongoose clean and focused on there being as close to one way of doing things as possible. If you really love all that extra noise, you can bring most of it back with this module.

    + +

    Here are the removed methods and their still existing aliases:

    RemovedAlternative
    query.runquery.exec
    query.$orquery.or
    query.$norquery.nor
    query.$gtquery.gt
    query.$gtequery.gte
    query.$ltquery.lt
    query.$ltequery.lte
    query.$nequery.ne
    query.$inquery.in
    query.$ninquery.nin
    query.$allquery.all
    query.$regexquery.regex
    query.$sizequery.size
    query.$maxDistancequery.maxDistance
    query.$modquery.mod
    query.$nearquery.near
    query.$existsquery.exists
    query.$elemMatchquery.elemMatch
    query.$withinquery.within
    query.$boxquery.box
    query.$centerquery.center
    query.$centerSpherequery.centerSphere
    query.$slicequery.slice
    query.notEqualToquery.ne
    query.whereinquery.within
    query.ascquery.sort *
    query.descquery.sort *
    query.fieldsquery.select *

    query#asc

    The asc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#desc

    The desc method of Query has been removed in favor of sort. The sort method accepts slightly different arguments so read the docs to make sure your application is all set.

    query#sort

    The sort method of Queries now accepts slightly different arguments. Read the docs to make sure your application is all set.

    query#fields

    The fields method of Query has been removed, it being mostly an alias for the select method anyway. The select method has slightly different arguments so read the docs to make sure your application is all set.

    + +

    Because of the change to the fields method, the field selection argument for query.populate and model methods like findById, find, etc, is slightly different as well (no longer accepts arrays for example), so read the docs to make sure your application is all set.

    Connecting to ReplicaSets

    To connect to a ReplicaSet you no longer use the separate connectSet or createSetConnection methods. Both mongoose.connect and mongoose.createConnection are now smart enough to just do the right thing with your connection string. If you really want to bring connectSet and createSetConnection back use this module.

    Schemas

    Schemas are now strict by default. This means that if you depended on saving fields not defined in the schema, you may lose data unless you set this back to false.

    • Arrays of object literal now creates document arrays instead of arrays of Mixed.
    • Indexes are now created in background by default.
    • Index errors are now emitted on their model instead of the connection. See issue #984.

    Arrays

    • pop is now fixed causing a $set of the entire array.
    • $pop is now fixed and behaves just as MongoDB $pop does, removing at most the last element of the array.
    • shift is now fixed causing a $set of the entire array.
    • $shift is now fixed and behaves just as a MongoDB $pop -1 does, removing at most the first element of array.
    • $unshift was removed, use unshift instead.
    • $addToSet was removed, use addToSet instead.
    • $pushAll was removed, use push instead.
    • $pull was removed, use pull instead.
    • $pullAll was removed, use pull instead.
    • doAtomics was changed to the hasAtomics private method

    Number type

    The custom subclassed Number type Mongoose used to use for all numbers is now gone. It caused too many problems when doing comparisons and had other bad side-effects.

    + +

    With it out of the picture, the following helper methods of MongooseNumbers are now also gone:

    + +
    • $inc
    • $increment
    • $decrement
    + +

    If you really want this behavior back, include the mongoose-number module in your project.

    + +

    A good alternative is to start using the new findAndModify helpers. +Say we have an inventory of 10 products and a customer purchases 7 of them. In Mongoose v2 you could have depended on MongooseNumber:

    var inventorySchema = new Schema({ productCount: Number });
    +...
    +Inventory.findById(id, function (err, inventory) {
    +  if (err) return handleError(err);
    +  inventory.productCount.$decrement(7);
    +  inventory.save(function (err) {
    +    // sends Inventory.update({ _id: id }, { $inc: { balance: -7 }}, callback);
    +    if (err) return handleError(err);
    +    res.send(inventory.productCount); // 3
    +  });
    +});

    With MongooseNumber out of the picture, we'll instead use the Account.findByIdAndUpdate helper:

    Inventory.findByIdAndUpdate(id, { $inc: { productCount: -7 }}, function (err, inventory) {
    +  if (err) return handleError(err);
    +  res.send(inventory.productCount); // 3
    +});

    The findByIdAndUpdate helper not only finds the document but updates it as well before responding with the altered document. The findAndModify helpers are a great addition for many use cases.

    Documents

    getter casting

    Getters no longer apply casting. Casting happens at set time. Useful in situations where you desire formatted responses like currency. See issue #820 and pull #924.

    setter order

    Values being set no longer cast until after all setters have been applied. Previously the value returned from each setter was cast before passing it on to the next setter. This change allows more flexible processing of values in setters. See issue #665 and pull #924.

    Subdocuments

    • subdoc.parent was changed from a property to a method. See issue #928.
    • subdoc.parentArray was changed from a property to a method. See issue #928.

    String match validator

    The String SchemaType match validator no longer checks against null, undefined, or ''. If you need to validate against these values, enable the required validator as well. See issue #934 and pull request #935.

    Versioning

    Documents are now transparently versioned. Read the in depth details here.

    More Info

    Related blog posts:

    + +
    \ No newline at end of file diff --git a/docs/3.5.x/docs/models.html b/docs/3.5.x/docs/models.html new file mode 100644 index 00000000000..f6a827e10c7 --- /dev/null +++ b/docs/3.5.x/docs/models.html @@ -0,0 +1,30 @@ +Mongoose Models v3.5.9Fork me on GitHub

    Models

    Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retreived from our database. All document creation and retreival from the database is handled by these models.

    Compiling your first model

    var schema = new mongoose.Schema({ name: 'string', size: 'string' });
    +var Tank = mongoose.model('Tank', schema);
    +

    Constructing documents

    Documents are instances of our model. Creating them and saving to the database is easy:

    var Tank = mongoose.model('Tank', yourSchema);
    +
    +var small = new Tank({ size: 'small' });
    +small.save(function (err) {
    +  if (err) return handleError(err);
    +  // saved!
    +})
    +
    +// or
    +
    +Tank.create({ size: 'small' }, function (err, small) {
    +  if (err) return handleError(err);
    +  // saved!
    +})

    Note that no tanks will be created/removed until the connection your model uses is open. In this case we are using mongoose.model() so let's open the default mongoose connection:

    mongoose.connect('localhost', 'gettingstarted');
    +

    Querying

    Finding documents is easy with Mongoose, which supports the rich query syntax of MongoDB. Documents can be retreived using each models find, findById, findOne, or where static methods.

    Tank.find({ type: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);

    See the chapter on querying for more details on how to use the Query api.

    Removing

    Models have a static remove method available for removing all documents matching conditions.

    Tank.remove({ size: 'large' }, function (err) {
    +  if (err) return handleError(err);
    +  // removed!
    +});

    Updating

    Each model has its own update method for modifying documents in the database without returning them to your application. See the API docs for more detail.

    + +

    If you want to update a single document in the db and return it to your application, use findOneAndUpdate instead.

    Yet more

    The API docs cover many additional methods available like count, mapReduce, aggregate, and more.

    Next Up

    Now that we've covered Models, let's take a look at Documents.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/plugins.html b/docs/3.5.x/docs/plugins.html new file mode 100644 index 00000000000..d031056e738 --- /dev/null +++ b/docs/3.5.x/docs/plugins.html @@ -0,0 +1,33 @@ +Mongoose Plugins v3.5.9Fork me on GitHub

    Plugins

    Schemas are pluggable, that is, they allow for applying pre-packaged capabilities to extend their functionality. This is a very powerful feature.

    + +

    Suppose that we have several collections in our database and want to add last-modified functionality to each one. With plugins this is easy. Just create a plugin once and apply it to each Schema:

    // lastMod.js
    +module.exports = exports = function lastModifiedPlugin (schema, options) {
    +  schema.add({ lastMod: Date })
    +  
    +  schema.pre('save', function (next) {
    +    this.lastMod = new Date
    +    next()
    +  })
    +  
    +  if (options && options.index) {
    +    schema.path('lastMod').index(options.index)
    +  }
    +}
    +
    +// game-schema.js
    +var lastMod = require('./lastMod');
    +var Game = new Schema({ ... });
    +Game.plugin(lastMod, { index: true });
    +
    +// player-schema.js
    +var lastMod = require('./lastMod');
    +var Player = new Schema({ ... });
    +Player.plugin(lastMod);

    We just added last-modified behavior to both our Game and Player schemas and declared an index on the lastMod path of our Games to boot. Not bad for a few lines of code.

    Community!

    Not only can you re-use schema functionality in your own projects but you also reap the benefits of the Mongoose community as well. Any plugin published to npm and tagged with mongoose will show up on our search results page.

    Next Up

    Now that we've covered plugins and how to get involved in the great community growing around them, let's take a look how you can help contribute to the continuing development of Mongoose itself.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/populate.html b/docs/3.5.x/docs/populate.html new file mode 100644 index 00000000000..1a7b88a68a8 --- /dev/null +++ b/docs/3.5.x/docs/populate.html @@ -0,0 +1,104 @@ +Mongoose Query Population v3.5.9Fork me on GitHub

    Query Population

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in.

    + +

    ObjectIds can refer to another document in a collection within our database and be populate()d when querying:

    var mongoose = require('mongoose')
    +  , Schema = mongoose.Schema
    +  
    +var PersonSchema = new Schema({
    +  name    : String,
    +  age     : Number,
    +  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
    +});
    +
    +var StorySchema = new Schema({
    +  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },
    +  title    : String,
    +  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
    +});
    +
    +var Story  = mongoose.model('Story', StorySchema);
    +var Person = mongoose.model('Person', PersonSchema);

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving refs

    Saving refs to other documents works the same way you normally save objectids, just assign an ObjectId:

    var aaron = new Person({ name: 'Aaron', age: 100 });
    +
    +aaron.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  var story1 = new Story({
    +    title: "Once upon a timex.",
    +    _creator: aaron._id    // assign an ObjectId
    +  });
    +  
    +  story1.save(function (err) {
    +    if (err) return handleError(err);
    +    // thats it!
    +  });
    +})

    Population

    So far we haven't done anything special. We've merely created a Person and a Story. Now let's take a look at populating our story's _creator:

    Story
    +.findOne({ title: /timex/ })
    +.populate('_creator')
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  console.log('The creator is %s', story._creator.name); // prints "The creator is Aaron"
    +})
    +

    Populated paths are no longer set to their original ObjectIds, their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.

    + +

    Arrays of ObjectId refs work the same way. Just call the populate method on the query and an array of documents will be returned in place of the ObjectIds.

    Field selection

    What if we only want a few specific fields returned for the query? This can be accomplished by passing the usual field name syntax as the second argument to the populate method:

    Story
    +.findOne({ title: /timex/i })
    +.populate('_creator', 'name') // only return the Persons name
    +.exec(function (err, story) {
    +  if (err) return handleError(err);
    +  
    +  console.log('The creator is %s', story._creator.name);
    +  // prints "The creator is Aaron"
    +  
    +  console.log('The creators age is %s', story._creator.age);
    +  // prints "The creators age is null'
    +})

    Query conditions for populate

    What if we wanted to populate our fans array based on their age, and return, at most, any 5 of them?

    Story
    +.find(...)
    +.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

    Done. Conditions and options for populate queries are passed as the third and fourth arguments respectively.

    Refs to children

    We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' on to aaron.stories.

    + +

    There are two perspectives to this story. First, it's nice to have aaron know which are his stories.

    aaron.stories.push(story1);
    +aaron.save();

    This allows us to perform a find and populate combo:

    Person
    +.findOne({ name: 'Aaron' })
    +.populate('stories') // only works if we pushed refs to children
    +.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log(person);
    +})

    However, it is debatable that we really want two sets of pointers as they may get out of sync. So we could instead merely find() the documents we are interested in.

    Story
    +.find({ _creator: aaron._id })
    +.populate('_creator') // not really necessary
    +.exec(function (err, stories) {
    +  if (err) return handleError(err);
    +  console.log('The stories are an array: ', stories);
    +})
    +

    Updating refs

    Now that we have a story we realized that the _creator was incorrect. We can update ObjectId refs the same as any other property through the magic of Mongooses internal casting:

    var guille = new Person({ name: 'Guillermo' });
    +guille.save(function (err) {
    +  if (err) return handleError(err);
    +  
    +  story._creator = guille; // or guille._id
    +  
    +  story.save(function (err) {
    +    if (err) return handleError(err);
    +    
    +    Story
    +    .findOne({ title: /timex/i })
    +    .populate('_creator', 'name')
    +    .exec(function (err, story) {
    +      if (err) return handleError(err);
    +      
    +      console.log('The creator is %s', story._creator.name)
    +      // prints "The creator is Guillermo"
    +    })
    +  })
    +})
    +

    NOTE:

    The documents returned from calling populate become fully functional, removeable, saveable documents. Do not confuse them with sub docs. Take caution when calling its remove method because you'll be removing it from the database, not just the array.

    NOTE:

    Field selection in v3 is slightly different than v2. Arrays of fields are no longer accepted.

    // this works
    +Story.findOne(..).populate('_creator', 'name age').exec(..);
    +
    +// this doesn't
    +Story.findOne(..).populate('_creator', ['name', 'age']).exec(..);
    +

    See the migration guide for more detail.

    Next Up

    Now that we've covered query population, let's take a look at connections.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/prior.html b/docs/3.5.x/docs/prior.html new file mode 100644 index 00000000000..d26f9269381 --- /dev/null +++ b/docs/3.5.x/docs/prior.html @@ -0,0 +1,9 @@ +Mongoose v3.5.9Fork me on GitHub

    Prior Release Documentation

    \ No newline at end of file diff --git a/docs/3.5.x/docs/production.html b/docs/3.5.x/docs/production.html new file mode 100644 index 00000000000..29f93a58b97 --- /dev/null +++ b/docs/3.5.x/docs/production.html @@ -0,0 +1,9 @@ +MongooseFork me on GitHub

    You are being redirected to http://mongoosejs.tumblr.com.
    Please click here if you are not redirected in 5 seconds.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/queries.html b/docs/3.5.x/docs/queries.html new file mode 100644 index 00000000000..f5ef969088c --- /dev/null +++ b/docs/3.5.x/docs/queries.html @@ -0,0 +1,41 @@ +Mongoose Queries v3.5.9Fork me on GitHub

    Queries

    Documents can be retrieved through several static helper methods of models.

    Any model method which involves specifying query conditions can be executed two ways:

    + +

    When a callback function:

    + +
    • is passed, the operation will be executed immediately with the results passed to the callback.
    • is not passed, an instance of Query is returned, which provides a special QueryBuilder interface for you.
    + +

    Let's take a look at what happens when passing a callback:

    var Person = mongoose.model('Person', yourSchema);
    +
    +// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
    +Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    Here we see that the query was executed immediately and the results passed to our callback. +Now let's look at what happens when no callback is passed:

    // find each person with a last name matching 'Ghost'
    +var query = Person.findOne({ 'name.last': 'Ghost' });
    +
    +// selecting the `name` and `occupation` fields
    +query.select('name occupation');
    +
    +// execute the query at a later time
    +query.exec(function (err, person) {
    +  if (err) return handleError(err);
    +  console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
    +})

    An instance of Query was returned which allows us to build up our query. Taking this example further:

    Person
    +.find({ occupation: /host/ })
    +.where('name.last').equals('Ghost')
    +.where('age').gt(17).lt(66)
    +.where('likes').in(['vaporizing', 'talking'])
    +.limit(10)
    +.sort('-occupation')
    +.select('name occupation')
    +.exec(callback);
    +

    References to other documents

    There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where query#populate comes in. Read more here.

    Streaming

    Queries can be streamed from MongoDB to your application as well. Simply call the query's stream method instead of exec to return an instance of QueryStream. Note: QueryStreams are Node.js 0.8 style read streams not Node.js 0.10 style.

    Next Up

    Now that we've covered Queries, let's take a look at validation.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/schematypes.html b/docs/3.5.x/docs/schematypes.html new file mode 100644 index 00000000000..d42c5e0a073 --- /dev/null +++ b/docs/3.5.x/docs/schematypes.html @@ -0,0 +1,67 @@ +Mongoose SchemaTypes v3.5.9Fork me on GitHub

    SchemaTypes

    SchemaTypes handle definition of path defaults, validation, getters, setters, field selection defaults for queries and other general characteristics for Strings and Numbers. Check out their respective API documentation for more detail.

    Following are all valid Schema Types.

    • String
    • Number
    • Date
    • Buffer
    • Boolean
    • Mixed
    • ObjectId
    • Array

    Example

    var schema = new Schema({
    +  name:    String,
    +  binary:  Buffer,
    +  living:  Boolean,
    +  updated: { type: Date, default: Date.now },
    +  age:     { type: Number, min: 18, max: 65 },
    +  mixed:   Schema.Types.Mixed,
    +  _someId: Schema.Types.ObjectId,
    +  array:      [],
    +  ofString:   [String],
    +  ofNumber:   [Number],
    +  ofDates:    [Date],
    +  ofBuffer:   [Buffer],
    +  ofBoolean:  [Boolean],
    +  ofMixed:    [Schema.Types.Mixed],
    +  ofObjectId: [Schema.Types.ObjectId],
    +  nested: {
    +    stuff: { type: String, lowercase: true, trim: true }
    +  }
    +})
    +
    +// example use
    +
    +var Thing = mongoose.model('Thing', schema);
    +
    +var m = new Thing;
    +m.name = 'Statue of Liberty';
    +m.age = 125;
    +m.updated = new Date;
    +m.binary = new Buffer(0);
    +m.living = false;
    +m.mixed = {[ any: { thing: 'i want' } ]};
    +m.markModified('mixed');
    +m._someId = new mongoose.Types.ObjectId;
    +m.array.push(1);
    +m.ofString.push("strings!");
    +m.ofNumber.unshift(1,2,3,4);
    +m.ofDates.addToSet(new Date);
    +m.ofBuffer.pop();
    +m.ofMixed = [1, [], 'three', { four: 5 }];
    +m.nested.stuff = 'good';
    +m.save(callback);
    +

    Usage notes:

    Mixed

    An "anything goes" SchemaType, its flexibility comes at a trade-off of it being harder to maintain. Mixed is available either through Schema.Types.Mixed or by passing an empty object literal. The following are equivalent:

    var Any = new Schema({ any: {} });
    +var Any = new Schema({ any: Schema.Types.Mixed });

    Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

    person.anything = { x: [3, 4, { y: "changed" }] };
    +person.markModified('anything');
    +person.save(); // anything will now get saved

    ObjectIds

    To specify a type of ObjectId, use Schema.Types.ObjectId in your declaration.

    var mongoose = require('mongoose');
    +var ObjectId = mongoose.Schema.Types.ObjectId;
    +var Car = new Schema({ driver: ObjectId });
    +// or just Schema.ObjectId for backwards compatibility with v2

    Arrays

    Provide creation of arrays of SchemaTypes or Sub-Documents.

    var ToySchema = new Schema({ name: String });
    +var ToyBox = new Schema({
    +  toys: [ToySchema],
    +  buffers: [Buffer],
    +  string:  [String],
    +  numbers: [Number]
    +  // ... etc
    +});

    Note: specifying an empty array is equivalent to Mixed. The following all create arrays of Mixed:

    var Empty1 = new Schema({ any: [] });
    +var Empty2 = new Schema({ any: Array });
    +var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
    +var Empty4 = new Schema({ any: [{}] });

    Creating Custom Types

    Mongoose can also be extended with custom SchemaTypes. Search the plugins site for compatible types like mongoose-long and other types.

    Next Up

    Now that we've covered SchemaTypes, let's take a look at Models.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/source/_docs b/docs/3.5.x/docs/source/_docs new file mode 100644 index 00000000000..6f04de5db44 --- /dev/null +++ b/docs/3.5.x/docs/source/_docs @@ -0,0 +1,18108 @@ + +### lib/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = require('./connectionstate')", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "require('./connectionstate')", + "string": "STATES" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the collection" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "conn", + "description": "A MongooseConnection instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "optional collection options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Abstract Collection constructor

    \n\n

    This is the base class that drivers inherit from and implement.

    ", + "summary": "

    Abstract Collection constructor

    ", + "body": "

    This is the base class that drivers inherit from and implement.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Collection (name, conn, opts) {\n if (undefined === opts) opts = {};\n if (undefined === opts.capped) opts.capped = {};\n\n opts.bufferCommands = undefined === opts.bufferCommands\n ? true\n : opts.bufferCommands;\n\n if ('number' == typeof opts.capped) {\n opts.capped = { size: opts.capped };\n }\n\n this.opts = opts;\n this.name = name;\n this.conn = conn;\n this.queue = [];\n this.buffer = this.opts.bufferCommands;\n\n if (STATES.connected == this.conn.readyState) {\n this.onOpen();\n }\n};", + "ctx": { + "type": "function", + "name": "Collection", + "string": "Collection()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "name" + } + ], + "description": { + "full": "

    The collection name

    ", + "summary": "

    The collection name

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.name;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "conn" + } + ], + "description": { + "full": "

    The Connection instance

    ", + "summary": "

    The Connection instance

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Collection.prototype.conn;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database connects

    ", + "summary": "

    Called when the database connects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onOpen = function () {\n var self = this;\n this.buffer = false;\n self.doQueue();\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onOpen", + "string": "Collection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the database disconnects

    ", + "summary": "

    Called when the database disconnects

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.onClose = function () {\n if (this.opts.bufferCommands) {\n this.buffer = true;\n }\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "onClose", + "string": "Collection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the method to queue" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method when executed" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Queues a method for later execution when its
    database connection opens.

    ", + "summary": "

    Queues a method for later execution when its
    database connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.addQueue = function (name, args) {\n this.queue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "addQueue", + "string": "Collection.prototype.addQueue()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes all queued methods and clears the queue.

    ", + "summary": "

    Executes all queued methods and clears the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Collection.prototype.doQueue = function () {\n for (var i = 0, l = this.queue.length; i < l; i++){\n this[this.queue[i][0]].apply(this, this.queue[i][1]);\n }\n this.queue = [];\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "doQueue", + "string": "Collection.prototype.doQueue()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.ensureIndex = function(){\n throw new Error('Collection#ensureIndex unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "ensureIndex", + "string": "Collection.prototype.ensureIndex()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findAndModify = function(){\n throw new Error('Collection#findAndModify unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findAndModify", + "string": "Collection.prototype.findAndModify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.findOne = function(){\n throw new Error('Collection#findOne unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "findOne", + "string": "Collection.prototype.findOne()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.find = function(){\n throw new Error('Collection#find unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "find", + "string": "Collection.prototype.find()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.insert = function(){\n throw new Error('Collection#insert unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "insert", + "string": "Collection.prototype.insert()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.save = function(){\n throw new Error('Collection#save unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "save", + "string": "Collection.prototype.save()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.update = function(){\n throw new Error('Collection#update unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "update", + "string": "Collection.prototype.update()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.getIndexes = function(){\n throw new Error('Collection#getIndexes unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "getIndexes", + "string": "Collection.prototype.getIndexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Abstract method that drivers must implement.

    ", + "summary": "

    Abstract method that drivers must implement.

    ", + "body": "" + }, + "ignore": false, + "code": "Collection.prototype.mapReduce = function(){\n throw new Error('Collection#mapReduce unimplemented by driver');\n};", + "ctx": { + "type": "method", + "constructor": "Collection", + "name": "mapReduce", + "string": "Collection.prototype.mapReduce()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Collection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Collection", + "string": "module.exports" + } + } +] +### lib/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var url = require('url')\n , utils = require('./utils')\n , EventEmitter = require('events').EventEmitter\n , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'\n , Model = require('./model')\n , Schema = require('./schema')\n , Collection = require(driver + '/collection')\n , STATES = require('./connectionstate')\n , MongooseError = require('./error')\n , assert =require('assert')\n , muri = require('muri')", + "ctx": { + "type": "declaration", + "name": "url", + "value": "require('url')", + "string": "url" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Protocol prefix regexp.

    ", + "summary": "

    Protocol prefix regexp.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var rgxProtocol = /^(?:.)+:\\/\\//;", + "ctx": { + "type": "declaration", + "name": "rgxProtocol", + "value": "/^(?:.)+:\\/\\//", + "string": "rgxProtocol" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "a mongoose instance" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection." + }, + { + "type": "event", + "string": "`connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios." + }, + { + "type": "event", + "string": "`open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models." + }, + { + "type": "event", + "string": "`disconnecting`: Emitted when `connection.close()` was executed." + }, + { + "type": "event", + "string": "`disconnected`: Emitted after getting disconnected from the db." + }, + { + "type": "event", + "string": "`close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models." + }, + { + "type": "event", + "string": "`reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection." + }, + { + "type": "event", + "string": "`error`: Emitted when an error occurs on this connection." + }, + { + "type": "event", + "string": "`fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection constructor

    \n\n

    For practical reasons, a Connection equals a Db.

    ", + "summary": "

    Connection constructor

    ", + "body": "

    For practical reasons, a Connection equals a Db.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Connection (base) {\n this.base = base;\n this.collections = {};\n this.models = {};\n this.replica = false;\n this.hosts = null;\n this.host = null;\n this.port = null;\n this.user = null;\n this.pass = null;\n this.name = null;\n this.options = null;\n this._readyState = STATES.disconnected;\n this._closeCalled = false;\n this._hasOpened = false;\n};", + "ctx": { + "type": "function", + "name": "Connection", + "string": "Connection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter

    ", + "summary": "

    Inherit from EventEmitter

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Connection", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Connection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readyState" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection ready state

    \n\n
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    ", + "summary": "

    Connection ready state

    ", + "body": "
      \n
    • 0 = disconnected
    • \n
    • 1 = connected
    • \n
    • 2 = connecting
    • \n
    • 3 = disconnecting
    • \n
    \n\n

    Each state change emits its associated event name.

    \n\n

    Example

    \n\n
    conn.on('connected', callback);\nconn.on('disconnected', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Connection.prototype, 'readyState', {\n get: function(){ return this._readyState; }\n , set: function (val) {\n if (!(val in STATES)) {\n throw new Error('Invalid connection state: ' + val);\n }\n\n if (this._readyState !== val) {\n this._readyState = val;\n\n if (STATES.connected === val)\n this._hasOpened = true;\n\n this.emit(STATES[val]);\n }\n }\n});" + }, + { + "tags": [ + { + "type": "property", + "string": "collections" + } + ], + "description": { + "full": "

    A hash of the collections associated with this connection

    ", + "summary": "

    A hash of the collections associated with this connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collections;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    The mongodb.Db instance, set when the connection is opened

    ", + "summary": "

    The mongodb.Db instance, set when the connection is opened

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.db;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "connection_string", + "description": "mongodb://uri or the host to which you are connecting" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[port]", + "description": "database port" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "see", + "title": "", + "url": "http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate", + "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    \n\n

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\nauth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    \n\n

    Options passed take precedence over options included in connection strings.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "

    options is a hash with the following possible properties:

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSet instance\nuser    - username for authentication\npass    - password for authentication\nauth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)\n
    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    \n\n

    Options passed take precedence over options included in connection strings.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.open = function (host, database, port, options, callback) {\n var self = this\n , parsed\n , uri;\n\n if ('string' === typeof database) {\n switch (arguments.length) {\n case 2:\n port = 27017;\n case 3:\n switch (typeof port) {\n case 'function':\n callback = port, port = 27017;\n break;\n case 'object':\n options = port, port = 27017;\n break;\n }\n break;\n case 4:\n if ('function' === typeof options)\n callback = options, options = {};\n }\n } else {\n switch (typeof database) {\n case 'function':\n callback = database, database = undefined;\n break;\n case 'object':\n options = database;\n database = undefined;\n callback = port;\n break;\n }\n\n if (!rgxProtocol.test(host)) {\n host = 'mongodb://' + host;\n }\n\n try {\n parsed = muri(host);\n } catch (err) {\n this.error(err, callback);\n return this;\n }\n\n database = parsed.db;\n host = parsed.hosts[0].host || parsed.hosts[0].ipc;\n port = parsed.hosts[0].port || 27017;\n }\n\n this.options = this.parseOptions(options, parsed && parsed.options);\n\n // make sure we can open\n if (STATES.disconnected !== this.readyState) {\n var err = new Error('Trying to open unclosed connection.');\n err.state = this.readyState;\n this.error(err, callback);\n return this;\n }\n\n if (!host) {\n this.error(new Error('Missing hostname.'), callback);\n return this;\n }\n\n if (!database) {\n this.error(new Error('Missing database name.'), callback);\n return this;\n }\n\n // authentication\n if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else if (parsed && parsed.auth) {\n this.user = parsed.auth.user;\n this.pass = parsed.auth.pass;\n\n // Check hostname for user/pass\n } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {\n host = host.split('@');\n var auth = host.shift().split(':');\n host = host.pop();\n this.user = auth[0];\n this.pass = auth[1];\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this.name = database;\n this.host = host;\n this.port = port;\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "open", + "string": "Connection.prototype.open()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "uris", + "description": "comma-separated mongodb:// `URI`s" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[database]", + "description": "database name if not included in `uris`" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "passed to the internal driver" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "node-mongodb-native", + "url": "https://github.com/mongodb/node-mongodb-native", + "visibility": "https://github.com/mongodb/node-mongodb-native" + }, + { + "type": "see", + "title": "", + "url": "http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate", + "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Opens the connection to a replica set.

    \n\n

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\nauth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)\n
    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    ", + "summary": "

    Opens the connection to a replica set.

    ", + "body": "

    Example:

    \n\n
    var db = mongoose.createConnection();\ndb.openSet(\"mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019\");\n
    \n\n

    The database name and/or auth need only be included in one URI.
    The options is a hash which is passed to the internal driver connection object.

    \n\n

    Valid options

    \n\n
    db      - passed to the connection db instance\nserver  - passed to the connection server instance(s)\nreplset - passed to the connection ReplSetServer instance\nuser    - username for authentication\npass    - password for authentication\nauth    - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)\n
    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Notes:

    \n\n

    Mongoose forces the db option forceServerObjectId false and cannot be overridden.
    Mongoose defaults the server auto_reconnect options to true which can be overridden.
    See the node-mongodb-native driver instance for options that it understands.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.openSet = function (uris, database, options, callback) {\n if (!rgxProtocol.test(uris)) {\n uris = 'mongodb://' + uris;\n }\n\n var self = this;\n\n switch (arguments.length) {\n case 3:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'object':\n callback = options;\n options = database;\n database = null;\n break;\n }\n\n if ('function' === typeof options) {\n callback = options;\n options = {};\n }\n break;\n case 2:\n switch (typeof database) {\n case 'string':\n this.name = database;\n break;\n case 'function':\n callback = database, database = null;\n break;\n case 'object':\n options = database, database = null;\n break;\n }\n }\n\n var parsed;\n try {\n parsed = muri(uris);\n } catch (err) {\n this.error(err, callback);\n return this;\n }\n\n if (!this.name) {\n this.name = parsed.db;\n }\n\n this.hosts = parsed.hosts;\n this.options = this.parseOptions(options, parsed && parsed.options);\n this.replica = true;\n\n if (!this.name) {\n this.error(new Error('No database name provided for replica set'), callback);\n return this;\n }\n\n // authentication\n if (options && options.user && options.pass) {\n this.user = options.user;\n this.pass = options.pass;\n\n } else if (parsed && parsed.auth) {\n this.user = parsed.auth.user;\n this.pass = parsed.auth.pass;\n\n } else {\n this.user = this.pass = undefined;\n }\n\n this._open(callback);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "openSet", + "string": "Connection.prototype.openSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "optional" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    error

    \n\n

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    ", + "summary": "

    error

    ", + "body": "

    Graceful error handling, passes error to callback
    if available, else emits error on the connection.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.error = function (err, callback) {\n if (callback) return callback(err);\n this.emit('error', err);\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "error", + "string": "Connection.prototype.error()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "summary": "

    Handles opening the connection with the appropriate method based on connection type.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype._open = function (callback) {\n this.readyState = STATES.connecting;\n this._closeCalled = false;\n\n var self = this;\n\n var method = this.replica\n ? 'doOpenSet'\n : 'doOpen';\n\n // open connection\n this[method](function (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.onOpen(callback);\n });\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "_open", + "string": "Connection.prototype._open()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection is opened

    ", + "summary": "

    Called when the connection is opened

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onOpen = function (callback) {\n var self = this;\n\n function open (err) {\n if (err) {\n self.readyState = STATES.disconnected;\n if (self._hasOpened) {\n if (callback) callback(err);\n } else {\n self.error(err, callback);\n }\n return;\n }\n\n self.readyState = STATES.connected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in self.collections)\n self.collections[i].onOpen();\n\n callback && callback();\n self.emit('open');\n };\n\n // re-authenticate\n if (self.user && self.pass) {\n self.db.authenticate(self.user, self.pass, self.options.auth, open);\n }\n else\n open();\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onOpen", + "string": "Connection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "self" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.close = function (callback) {\n var self = this;\n this._closeCalled = true;\n\n switch (this.readyState){\n case 0: // disconnected\n callback && callback();\n break;\n\n case 1: // connected\n this.readyState = STATES.disconnecting;\n this.doClose(function(err){\n if (err){\n self.error(err, callback);\n } else {\n self.onClose();\n callback && callback();\n }\n });\n break;\n\n case 2: // connecting\n this.once('open', function(){\n self.close(callback);\n });\n break;\n\n case 3: // disconnecting\n if (!callback) break;\n this.once('close', function () {\n callback();\n });\n break;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "close", + "string": "Connection.prototype.close()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Connection.prototype.onClose = function () {\n this.readyState = STATES.disconnected;\n\n // avoid having the collection subscribe to our event emitter\n // to prevent 0.3 warning\n for (var i in this.collections)\n this.collections[i].onClose();\n\n this.emit('close');\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "onClose", + "string": "Connection.prototype.onClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "of the collection" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional collection options" + }, + { + "type": "return", + "types": [ + "Collection" + ], + "description": "collection instance" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retrieves a collection, creating it if not cached.

    ", + "summary": "

    Retrieves a collection, creating it if not cached.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.collection = function (name, options) {\n if (!(name in this.collections))\n this.collections[name] = new Collection(name, this, options);\n return this.collections[name];\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "collection", + "string": "Connection.prototype.collection()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "the model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "a schema. necessary when defining a model" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name of mongodb collection (optional) if not given it will be induced from model name" + }, + { + "type": "see", + "local": "Mongoose#model #index_Mongoose-model", + "visibility": "Mongoose#model" + }, + { + "type": "return", + "types": [ + "Model" + ], + "description": "The compiled model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines or retrieves a model.

    \n\n
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String }, { collection: 'actor' });\n\n// or\n\nschema.set('collection', 'actor');\n\n// or\n\nvar collectionName = 'actor'\nvar M = conn.model('Actor', schema, collectionName)\n
    ", + "summary": "

    Defines or retrieves a model.

    ", + "body": "
    var mongoose = require('mongoose');\nvar db = mongoose.createConnection(..);\ndb.model('Venue', new Schema(..));\nvar Ticket = db.model('Ticket', new Schema(..));\nvar Venue = db.model('Venue');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String }, { collection: 'actor' });\n\n// or\n\nschema.set('collection', 'actor');\n\n// or\n\nvar collectionName = 'actor'\nvar M = conn.model('Actor', schema, collectionName)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.model = function (name, schema, collection) {\n // collection name discovery\n if ('string' == typeof schema) {\n collection = schema;\n schema = false;\n }\n\n if (utils.isObject(schema) && !(schema instanceof Schema)) {\n schema = new Schema(schema);\n }\n\n if (this.models[name] && !collection) {\n // model exists but we are not subclassing with custom collection\n if (schema instanceof Schema && schema != this.models[name].schema) {\n throw new MongooseError.OverwriteModelError(name);\n }\n return this.models[name];\n }\n\n var opts = { cache: false, connection: this }\n var model;\n\n if (schema instanceof Schema) {\n // compile a model\n model = this.base.model(name, schema, collection, opts)\n\n // only the first model with this name is cached to allow\n // for one-offs with custom collection names etc.\n if (!this.models[name]) {\n this.models[name] = model;\n }\n\n model.init();\n return model;\n }\n\n if (this.models[name] && collection) {\n // subclassing current model with alternate collection\n model = this.models[name];\n schema = model.prototype.schema;\n var sub = model.__subclass(this, schema, collection);\n // do not cache the sub model\n return sub;\n }\n\n // lookup model in mongoose module\n model = this.base.models[name];\n\n if (!model) {\n throw new MongooseError.MissingSchemaError(name);\n }\n\n if (this == model.prototype.db\n && (!collection || collection == model.collection.name)) {\n // model already uses this connection.\n\n // only the first model with this name is cached to allow\n // for one-offs with custom collection names etc.\n if (!this.models[name]) {\n this.models[name] = model;\n }\n\n return model;\n }\n\n return this.models[name] = model.__subclass(this, schema, collection);\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "model", + "string": "Connection.prototype.model()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns an array of model names created on this connection.

    ", + "summary": "

    Returns an array of model names created on this connection.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.modelNames = function () {\n return Object.keys(this.models);\n}", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "modelNames", + "string": "Connection.prototype.modelNames()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "level", + "description": "either off (0), slow (1), or all (2)" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "[ms]", + "description": "the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100." + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Set profiling level.

    ", + "summary": "

    Set profiling level.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Connection.prototype.setProfiling = function (level, ms, callback) {\n if (STATES.connected !== this.readyState) {\n return this.on('open', this.setProfiling.bind(this, level, ms, callback));\n }\n\n if (!callback) callback = ms, ms = 100;\n\n var cmd = {};\n\n switch (level) {\n case 0:\n case 'off':\n cmd.profile = 0;\n break;\n case 1:\n case 'slow':\n cmd.profile = 1;\n if ('number' !== typeof ms) {\n ms = parseInt(ms, 10);\n if (isNaN(ms)) ms = 100;\n }\n cmd.slowms = ms;\n break;\n case 2:\n case 'all':\n cmd.profile = 2;\n break;\n default:\n return callback(new Error('Invalid profiling level: '+ level));\n }\n\n this.db.executeDbCommand(cmd, function (err, resp) {\n if (err) return callback(err);\n\n var doc = resp.documents[0];\n\n err = 1 === doc.ok\n ? null\n : new Error('Could not set profiling level to: '+ level)\n\n callback(err, doc);\n });\n};", + "ctx": { + "type": "method", + "constructor": "Connection", + "name": "setProfiling", + "string": "Connection.prototype.setProfiling()" + } + }, + { + "tags": [], + "description": { + "full": "

    Noop.

    ", + "summary": "

    Noop.

    ", + "body": "" + }, + "ignore": true, + "code": "function noop () {}", + "ctx": { + "type": "function", + "name": "noop", + "string": "noop()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Connection.STATES = STATES;\nmodule.exports = Connection;", + "ctx": { + "type": "property", + "receiver": "Connection", + "name": "STATES", + "value": "STATES", + "string": "Connection.STATES" + } + } +] +### lib/connectionstate.js +[ + { + "tags": [], + "description": { + "full": "

    Connection states

    ", + "summary": "

    Connection states

    ", + "body": "" + }, + "ignore": true, + "code": "var STATES = module.exports = exports = Object.create(null);\n\nvar disconnected = 'disconnected';\nvar connected = 'connected';\nvar connecting = 'connecting';\nvar disconnecting = 'disconnecting';\nvar uninitialized = 'uninitialized';\n\nSTATES[0] = disconnected;\nSTATES[1] = connected;\nSTATES[2] = connecting;\nSTATES[3] = disconnecting;\nSTATES[99] = uninitialized;\n\nSTATES[disconnected] = 0;\nSTATES[connected] = 1;\nSTATES[connecting] = 2;\nSTATES[disconnecting] = 3;\nSTATES[uninitialized] = 99;", + "ctx": { + "type": "declaration", + "name": "STATES", + "value": "module.exports = exports = Object.create(null)", + "string": "STATES" + } + } +] +### lib/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , MongooseError = require('./error')\n , MixedSchema = require('./schema/mixed')\n , Schema = require('./schema')\n , ValidatorError = require('./schematype').ValidatorError\n , utils = require('./utils')\n , clone = utils.clone\n , isMongooseObject = utils.isMongooseObject\n , inspect = require('util').inspect\n , ElemMatchError = MongooseError.ElemMatchError\n , ValidationError = MongooseError.ValidationError\n , DocumentError = MongooseError.DocumentError\n , InternalCache = require('./internal')\n , deepEqual = utils.deepEqual\n , hooks = require('hooks')\n , DocumentArray\n , MongooseArray", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the values to set" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "optional object containing the fields which were selected in the query returning this document and any populated paths data" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "bool, should we auto create an ObjectId _id" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose." + }, + { + "type": "event", + "string": "`save`: Emitted when the document is successfully saved" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document constructor.

    ", + "summary": "

    Document constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Document (obj, fields, skipId) {\n this.$__ = new InternalCache;\n this.isNew = true;\n this.errors = undefined;\n\n var schema = this.schema;\n\n if ('boolean' === typeof fields) {\n this.$__.strictMode = fields;\n fields = undefined;\n } else {\n this.$__.strictMode = schema.options && schema.options.strict;\n this.$__.selected = fields;\n }\n\n var required = schema.requiredPaths();\n for (var i = 0; i < required.length; ++i) {\n this.$__.activePaths.require(required[i]);\n }\n\n this._doc = this.$__buildDoc(obj, fields, skipId);\n this.setMaxListeners(0);\n\n if (obj) {\n this.set(obj, undefined, true);\n }\n\n this.$__registerHooks();\n}", + "ctx": { + "type": "function", + "name": "Document", + "string": "Document()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Document.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "schema" + } + ], + "description": { + "full": "

    The documents schema.

    ", + "summary": "

    The documents schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.schema;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "isNew" + } + ], + "description": { + "full": "

    Boolean flag specifying if the document is new.

    ", + "summary": "

    Boolean flag specifying if the document is new.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isNew;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "local": "Schema options /docs/guide.html#options", + "visibility": "Schema" + }, + { + "type": "property", + "string": "id" + } + ], + "description": { + "full": "

    The string version of this documents _id.

    \n\n

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    ", + "summary": "

    The string version of this documents _id.

    ", + "body": "

    Note:

    \n\n

    This getter exists on all documents by default. The getter can be disabled by setting the id option of its Schema to false at construction time.

    \n\n
    new Schema({ name: String }, { id: false });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.id;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "errors" + } + ], + "description": { + "full": "

    Hash containing current validation errors.

    ", + "summary": "

    Hash containing current validation errors.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.errors;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipId]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__buildDoc" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Builds the default doc structure

    ", + "summary": "

    Builds the default doc structure

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__buildDoc = function (obj, fields, skipId) {\n var doc = {}\n , self = this\n , exclude\n , keys\n , key\n , ki\n\n // determine if this doc is a result of a query with\n // excluded fields\n if (fields && 'Object' === fields.constructor.name) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('_id' !== keys[ki]) {\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n }\n\n var paths = Object.keys(this.schema.paths)\n , plen = paths.length\n , ii = 0\n\n for (; ii < plen; ++ii) {\n var p = paths[ii];\n\n if ('_id' == p) {\n if (skipId) continue;\n if (obj && '_id' in obj) continue;\n }\n\n var type = this.schema.paths[p]\n , path = p.split('.')\n , len = path.length\n , last = len-1\n , doc_ = doc\n , i = 0\n\n for (; i < len; ++i) {\n var piece = path[i]\n , def\n\n if (i === last) {\n if (fields) {\n if (exclude) {\n // apply defaults to all non-excluded fields\n if (p in fields) continue;\n\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self.$__.activePaths.default(p);\n }\n\n } else if (p in fields) {\n // selected field\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self.$__.activePaths.default(p);\n }\n }\n } else {\n def = type.getDefault(self, true);\n if ('undefined' !== typeof def) {\n doc_[piece] = def;\n self.$__.activePaths.default(p);\n }\n }\n } else {\n doc_ = doc_[piece] || (doc_[piece] = {});\n }\n }\n };\n\n return doc;\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "document returned by mongo" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the document without setters or marking anything modified.

    \n\n

    Called internally after a document is returned from mongodb.

    ", + "summary": "

    Initializes the document without setters or marking anything modified.

    ", + "body": "

    Called internally after a document is returned from mongodb.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.init = function (doc, opts, fn) {\n // do not prefix this method with $__ since its\n // used by public hooks\n\n if ('function' == typeof opts) {\n fn = opts;\n opts = null;\n }\n\n this.isNew = false;\n\n // handle docs with populated paths\n if (doc._id && opts && opts.populated && opts.populated.length) {\n var id = String(doc._id);\n for (var i = 0; i < opts.populated.length; ++i) {\n var item = opts.populated[i];\n this.populated(item.path, item._docs[id], item);\n }\n }\n\n init(this, doc, this._doc);\n this.$__storeShard();\n\n this.emit('init', this);\n if (fn) fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "init", + "string": "Document.prototype.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "self", + "description": "document instance" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "raw mongodb doc" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "object we are initializing" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Init helper.

    ", + "summary": "

    Init helper.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function init (self, obj, doc, prefix) {\n prefix = prefix || '';\n\n var keys = Object.keys(obj)\n , len = keys.length\n , schema\n , path\n , i;\n\n while (len--) {\n i = keys[len];\n path = prefix + i;\n schema = self.schema.path(path);\n\n if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {\n // assume nested object\n if (!doc[i]) doc[i] = {};\n init(self, obj[i], doc[i], path + '.');\n } else {\n if (obj[i] === null) {\n doc[i] = null;\n } else if (obj[i] !== undefined) {\n if (schema) {\n self.$__try(function(){\n doc[i] = schema.cast(obj[i], self, true);\n });\n } else {\n doc[i] = obj[i];\n }\n }\n // mark as hydrated\n self.$__.activePaths.init(path);\n }\n }\n};", + "ctx": { + "type": "function", + "name": "init", + "string": "init()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__storeShard" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Stores the current values of the shard keys.

    \n\n

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    ", + "summary": "

    Stores the current values of the shard keys.

    ", + "body": "

    Note:

    \n\n

    Shard key values do not / are not allowed to change.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__storeShard = function () {\n // backwards compat\n var key = this.schema.options.shardKey || this.schema.options.shardkey;\n if (!(key && 'Object' == key.constructor.name)) return;\n\n var orig = this.$__.shardval = {}\n , paths = Object.keys(key)\n , len = paths.length\n , val\n\n for (var i = 0; i < len; ++i) {\n val = this.getValue(paths[i]);\n if (isMongooseObject(val)) {\n orig[paths[i]] = val.toObject({ depopulate: true })\n } else if (null != val && val.valueOf) {\n orig[paths[i]] = val.valueOf();\n } else {\n orig[paths[i]] = val;\n }\n }\n}" + }, + { + "tags": [], + "description": { + "full": "

    Set up middleware support

    ", + "summary": "

    Set up middleware support

    ", + "body": "" + }, + "ignore": true, + "code": "for (var k in hooks) {\n Document.prototype[k] = Document[k] = hooks[k];\n}" + }, + { + "tags": [ + { + "type": "see", + "local": "Model.update #model_Model.update", + "visibility": "Model.update" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends an update command with this document _id as the query selector.

    \n\n

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);\n
    \n\n

    Valid options:

    \n\n", + "summary": "

    Sends an update command with this document _id as the query selector.

    ", + "body": "

    Example:

    \n\n
    weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);\n
    \n\n

    Valid options:

    \n\n" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.update = function update () {\n var args = utils.args(arguments);\n args.unshift({_id: this._id});\n this.constructor.update.apply(this.constructor, args);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "update", + "string": "Document.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "path", + "description": "path or object of key/vals to set" + }, + { + "type": "param", + "types": [ + "Any" + ], + "name": "val", + "description": "the value to set" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for \"on-the-fly\" attributes" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optionally specify options that modify the behavior of the set" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the value of a path, or many paths.

    \n\n

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n\n// changing strict mode behavior\ndoc.set(path, value, { strict: false });\n
    ", + "summary": "

    Sets the value of a path, or many paths.

    ", + "body": "

    Example:

    \n\n
    // path, value\ndoc.set(path, value)\n\n// object\ndoc.set({\n    path  : value\n  , path2 : {\n       path  : value\n    }\n})\n\n// only-the-fly cast to number\ndoc.set(path, value, Number)\n\n// only-the-fly cast to string\ndoc.set(path, value, String)\n\n// changing strict mode behavior\ndoc.set(path, value, { strict: false });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.set = function (path, val, type, options) {\n if (type && 'Object' == type.constructor.name) {\n options = type;\n type = undefined;\n }\n\n var merge = options && options.merge\n , adhoc = type && true !== type\n , constructing = true === type\n , adhocs\n\n var strict = options && 'strict' in options\n ? options.strict\n : this.$__.strictMode;\n\n if (adhoc) {\n adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n if ('string' !== typeof path) {\n // new Document({ key: val })\n\n if (null === path || undefined === path) {\n var _ = path;\n path = val;\n val = _;\n\n } else {\n var prefix = val\n ? val + '.'\n : '';\n\n if (path instanceof Document) path = path._doc;\n\n var keys = Object.keys(path)\n , i = keys.length\n , pathtype\n , key\n\n while (i--) {\n key = keys[i];\n pathtype = this.schema.pathType(prefix + key);\n if (null != path[key]\n && 'Object' == path[key].constructor.name\n && 'virtual' != pathtype\n && !(this.$__path(prefix + key) instanceof MixedSchema)) {\n this.set(path[key], prefix + key, constructing);\n } else if (strict) {\n if ('real' === pathtype || 'virtual' === pathtype) {\n this.set(prefix + key, path[key], constructing);\n } else if ('throw' == strict) {\n throw new Error(\"Field `\" + key + \"` is not in schema.\");\n }\n } else if (undefined !== path[key]) {\n this.set(prefix + key, path[key], constructing);\n }\n }\n\n return this;\n }\n }\n\n // ensure _strict is honored for obj props\n // docschema = new Schema({ path: { nest: 'string' }})\n // doc.set('path', obj);\n var pathType = this.schema.pathType(path);\n if ('nested' == pathType && val && 'Object' == val.constructor.name) {\n if (!merge) this.setValue(path, null);\n this.set(val, path, constructing);\n return this;\n }\n\n var schema;\n if ('adhocOrUndefined' == pathType && strict) {\n return this;\n } else if ('virtual' == pathType) {\n schema = this.schema.virtualpath(path);\n schema.applySetters(val, this);\n return this;\n } else {\n schema = this.$__path(path);\n }\n\n var parts = path.split('.')\n , pathToMark\n\n // When using the $set operator the path to the field must already exist.\n // Else mongodb throws: \"LEFT_SUBFIELD only supports Object\"\n\n if (parts.length <= 1) {\n pathToMark = path;\n } else {\n for (var i = 0; i < parts.length; ++i) {\n var part = parts[i];\n var subpath = parts.slice(0, i).concat(part).join('.');\n if (this.isDirectModified(subpath) // earlier prefixes that are already\n // marked as dirty have precedence\n || this.get(subpath) === null) {\n pathToMark = subpath;\n break;\n }\n }\n\n if (!pathToMark) pathToMark = path;\n }\n\n if (!schema || null === val || undefined === val) {\n this.$__set(pathToMark, path, constructing, parts, schema, val);\n return this;\n }\n\n var self = this;\n\n // if this doc is being constructed we should not\n // trigger getters.\n var priorVal = constructing\n ? undefined\n : this.get(path);\n\n var shouldSet = this.$__try(function(){\n val = schema.applySetters(val, self, false, priorVal);\n });\n\n if (shouldSet) {\n this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal);\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "set", + "string": "Document.prototype.set()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__shouldModify" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Determine if we should mark this change as modified.

    ", + "summary": "

    Determine if we should mark this change as modified.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__shouldModify = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n if (this.isNew) return true;\n if (this.isDirectModified(pathToMark)) return false;\n\n if (undefined === val && !this.isSelected(path)) {\n // when a path is not selected in a query, its initial\n // value will be undefined.\n return true;\n }\n\n if (undefined === val && path in this.$__.activePaths.states.default) {\n // we're just unsetting the default value which was never saved\n return false;\n }\n\n if (!deepEqual(val, priorVal || this.get(path))) {\n return true;\n }\n\n if (!constructing &&\n null != val &&\n path in this.$__.activePaths.states.default &&\n deepEqual(val, schema.getDefault(this, constructing))) {\n // a path with a default was $unset on the server\n // and the user is setting it to the same value again\n return true;\n }\n\n return false;\n}" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__set" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "summary": "

    Handles the actual setting of the value and marking the path modified if appropriate.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__set = function (\n pathToMark, path, constructing, parts, schema, val, priorVal) {\n\n var shouldModify = this.$__shouldModify.apply(this, arguments);\n\n if (shouldModify) {\n this.markModified(pathToMark, val);\n\n // handle directly setting arrays (gh-1126)\n MongooseArray || (MongooseArray = require('./types/array'));\n if (val instanceof MongooseArray) {\n val._registerAtomic('$set', val);\n }\n }\n\n var obj = this._doc\n , i = 0\n , l = parts.length\n\n for (; i < l; i++) {\n var next = i + 1\n , last = next === l;\n\n if (last) {\n obj[parts[i]] = val;\n } else {\n if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {\n obj = obj[parts[i]];\n } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {\n obj = obj[parts[i]];\n } else {\n obj = obj[parts[i]] = {};\n }\n }\n }\n}" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets a raw value from a path (no getters)

    ", + "summary": "

    Gets a raw value from a path (no getters)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.getValue = function (path) {\n return utils.getValue(path, this._doc);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "getValue", + "string": "Document.prototype.getValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "summary": "

    Sets a raw value for a path (no casting, setters, transformations)

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.setValue = function (path, val) {\n utils.setValue(path, val, this._doc);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "setValue", + "string": "Document.prototype.setValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema", + "String", + "Number", + "Buffer", + "etc.." + ], + "name": "[type]", + "description": "optionally specify a type for on-the-fly attributes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the value of a path.

    \n\n

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    ", + "summary": "

    Returns the value of a path.

    ", + "body": "

    Example

    \n\n
    // path\ndoc.get('age') // 47\n\n// dynamic casting to a string\ndoc.get('age', String) // \"47\"\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.get = function (path, type) {\n var adhocs;\n if (type) {\n adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {});\n adhocs[path] = Schema.interpretAsType(path, type);\n }\n\n var schema = this.$__path(path) || this.schema.virtualpath(path)\n , pieces = path.split('.')\n , obj = this._doc;\n\n for (var i = 0, l = pieces.length; i < l; i++) {\n obj = null == obj ? null : obj[pieces[i]];\n }\n\n if (schema) {\n obj = schema.applyGetters(obj, this);\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "get", + "string": "Document.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__path" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Returns the schematype for the given path.

    ", + "summary": "

    Returns the schematype for the given path.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__path = function (path) {\n var adhocs = this.$__.adhocPaths\n , adhocType = adhocs && adhocs[path];\n\n if (adhocType) {\n return adhocType;\n } else {\n return this.schema.path(path);\n }\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to mark modified" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the path as having pending changes to write to the db.

    \n\n

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    ", + "summary": "

    Marks the path as having pending changes to write to the db.

    ", + "body": "

    Very helpful when using Mixed types.

    \n\n

    Example:

    \n\n
    doc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\ndoc.save() // changes to mixed.type are now persisted\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.markModified = function (path) {\n this.$__.activePaths.modify(path);\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "markModified", + "string": "Document.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "function to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope with which to call fn" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__try" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "summary": "

    Catches errors that occur during execution of fn and stores them to later be passed when save() is executed.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__try = function (fn, scope) {\n var res;\n try {\n fn.call(scope);\n res = true;\n } catch (e) {\n this.$__error(e);\n res = false;\n }\n return res;\n};" + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the list of paths that have been modified.

    ", + "summary": "

    Returns the list of paths that have been modified.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.modifiedPaths = function () {\n var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);\n\n return directModifiedPaths.reduce(function (list, path) {\n var parts = path.split('.');\n return list.concat(parts.reduce(function (chains, part, i) {\n return chains.concat(parts.slice(0, i).concat(part).join('.'));\n }, []));\n }, []);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "modifiedPaths", + "string": "Document.prototype.modifiedPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "optional" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if this document was modified, else false.

    \n\n

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    ", + "summary": "

    Returns true if this document was modified, else false.

    ", + "body": "

    If path is given, checks if a path or any full path containing path as part of its path chain has been modified.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isModified()                    // true\ndoc.isModified('documents')         // true\ndoc.isModified('documents.0.title') // true\ndoc.isDirectModified('documents')   // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isModified = function (path) {\n return path\n ? !!~this.modifiedPaths().indexOf(path)\n : this.$__.activePaths.some('modify');\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isModified", + "string": "Document.prototype.isModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if path was directly set and modified, else false.

    \n\n

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    ", + "summary": "

    Returns true if path was directly set and modified, else false.

    ", + "body": "

    Example

    \n\n
    doc.set('documents.0.title', 'changed');\ndoc.isDirectModified('documents.0.title') // true\ndoc.isDirectModified('documents') // false\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isDirectModified = function (path) {\n return (path in this.$__.activePaths.states.modify);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isDirectModified", + "string": "Document.prototype.isDirectModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was initialized.

    ", + "summary": "

    Checks if path was initialized.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isInit = function (path) {\n return (path in this.$__.activePaths.states.init);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isInit", + "string": "Document.prototype.isInit()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Checks if path was selected in the source query which initialized this document.

    \n\n

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    ", + "summary": "

    Checks if path was selected in the source query which initialized this document.

    ", + "body": "

    Example

    \n\n
    Thing.findOne().select('name').exec(function (err, doc) {\n   doc.isSelected('name') // true\n   doc.isSelected('age')  // false\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.isSelected = function isSelected (path) {\n if (this.$__.selected) {\n\n if ('_id' === path) {\n return 0 !== this.$__.selected._id;\n }\n\n var paths = Object.keys(this.$__.selected)\n , i = paths.length\n , inclusive = false\n , cur\n\n if (1 === i && '_id' === paths[0]) {\n // only _id was selected.\n return 0 === this.$__.selected._id;\n }\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n inclusive = !! this.$__.selected[cur];\n break;\n }\n\n if (path in this.$__.selected) {\n return inclusive;\n }\n\n i = paths.length;\n var pathDot = path + '.';\n\n while (i--) {\n cur = paths[i];\n if ('_id' == cur) continue;\n\n if (0 === cur.indexOf(pathDot)) {\n return inclusive;\n }\n\n if (0 === pathDot.indexOf(cur)) {\n return inclusive;\n }\n }\n\n return ! inclusive;\n }\n\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "isSelected", + "string": "Document.prototype.isSelected()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "cb", + "description": "called after validation completes, passing an error if one occurred" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes registered validation rules for this document.

    \n\n

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    ", + "summary": "

    Executes registered validation rules for this document.

    ", + "body": "

    Note:

    \n\n

    This method is called pre save and if a validation rule is violated, save is aborted and the error is returned to your callback.

    \n\n

    Example:

    \n\n
    doc.validate(function (err) {\n  if (err) handleError(err);\n  else // validation passed\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.validate = function (cb) {\n var self = this\n\n // only validate required fields when necessary\n var paths = Object.keys(this.$__.activePaths.states.require).filter(function (path) {\n if (!self.isSelected(path) && !self.isModified(path)) return false;\n return true;\n });\n\n paths = paths.concat(Object.keys(this.$__.activePaths.states.init));\n paths = paths.concat(Object.keys(this.$__.activePaths.states.modify));\n paths = paths.concat(Object.keys(this.$__.activePaths.states.default));\n\n if (0 === paths.length) {\n complete();\n return this;\n }\n\n var validating = {}\n , total = 0;\n\n paths.forEach(validatePath);\n return this;\n\n function validatePath (path) {\n if (validating[path]) return;\n\n validating[path] = true;\n total++;\n\n process.nextTick(function(){\n var p = self.schema.path(path);\n if (!p) return --total || complete();\n\n var val = self.getValue(path);\n p.doValidate(val, function (err) {\n if (err) {\n self.invalidate(\n path\n , err\n , undefined\n , true // embedded docs\n );\n }\n --total || complete();\n }, self);\n });\n }\n\n function complete () {\n var err = self.$__.validationError;\n self.$__.validationError = undefined;\n self.emit('validate', self);\n cb(err);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "validate", + "string": "Document.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "the error which states the reason `path` was invalid" + }, + { + "type": "param", + "types": [ + "Object", + "String", + "Number", + "any" + ], + "name": "value", + "description": "optional invalid value" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.invalidate = function (path, err, val) {\n if (!this.$__.validationError) {\n this.$__.validationError = new ValidationError(this);\n }\n\n if (!err || 'string' === typeof err) {\n // sniffing arguments:\n // need to handle case where user does not pass value\n // so our error message is cleaner\n err = 2 < arguments.length\n ? new ValidatorError(path, err, val)\n : new ValidatorError(path, err)\n }\n\n this.$__.validationError.errors[path] = err;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "invalidate", + "string": "Document.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + }, + { + "type": "method", + "string": "$__reset" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Resets the internal modified state of this document.

    ", + "summary": "

    Resets the internal modified state of this document.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__reset = function reset () {\n var self = this;\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.$__.activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n })\n .forEach(function (array) {\n var i = array.length;\n while (i--) {\n var doc = array[i];\n if (!doc) continue;\n doc.$__reset();\n }\n });\n\n // clear atomics\n this.$__dirty().forEach(function (dirt) {\n var type = dirt.value;\n if (type && type._atomics) {\n type._atomics = {};\n }\n });\n\n // Clear 'modify'('dirty') cache\n this.$__.activePaths.clear('modify');\n this.$__.validationError = undefined;\n this.errors = undefined;\n var self = this;\n this.schema.requiredPaths().forEach(function (path) {\n self.$__.activePaths.require(path);\n });\n\n return this;\n}" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__dirty" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Returns this documents dirty paths / vals.

    ", + "summary": "

    Returns this documents dirty paths / vals.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__dirty = function () {\n var self = this;\n\n var all = this.$__.activePaths.map('modify', function (path) {\n return { path: path\n , value: self.getValue(path)\n , schema: self.$__path(path) };\n });\n\n // Sort dirty paths in a flat hierarchy.\n all.sort(function (a, b) {\n return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));\n });\n\n // Ignore \"foo.a\" if \"foo\" is dirty already.\n var minimal = []\n , lastPath\n , top;\n\n all.forEach(function (item, i) {\n if (item.path.indexOf(lastPath) !== 0) {\n lastPath = item.path + '.';\n minimal.push(item);\n top = item;\n } else {\n // special case for top level MongooseArrays\n if (top.value && top.value._atomics && top.value.hasAtomics()) {\n // the `top` array itself and a sub path of `top` are being modified.\n // the only way to honor all of both modifications is through a $set\n // of entire array.\n top.value._atomics = {};\n top.value._atomics.$set = top.value;\n }\n }\n });\n\n top = lastPath = null;\n return minimal;\n}" + }, + { + "tags": [], + "description": { + "full": "

    Compiles schemas.

    ", + "summary": "

    Compiles schemas.

    ", + "body": "" + }, + "ignore": true, + "code": "function compile (tree, proto, prefix) {\n var keys = Object.keys(tree)\n , i = keys.length\n , limb\n , key;\n\n while (i--) {\n key = keys[i];\n limb = tree[key];\n\n define(key\n , (('Object' === limb.constructor.name\n && Object.keys(limb).length)\n && (!limb.type || limb.type.type)\n ? limb\n : null)\n , proto\n , prefix\n , keys);\n }\n};", + "ctx": { + "type": "function", + "name": "compile", + "string": "compile()" + } + }, + { + "tags": [], + "description": { + "full": "

    Defines the accessor named prop on the incoming prototype.

    ", + "summary": "

    Defines the accessor named prop on the incoming prototype.

    ", + "body": "" + }, + "ignore": true, + "code": "function define (prop, subprops, prototype, prefix, keys) {\n var prefix = prefix || ''\n , path = (prefix ? prefix + '.' : '') + prop;\n\n if (subprops) {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function () {\n if (!this.$__.getters)\n this.$__.getters = {};\n\n if (!this.$__.getters[path]) {\n var nested = Object.create(this);\n\n // save scope for nested getters/setters\n if (!prefix) nested.$__.scope = this;\n\n // shadow inherited getters from sub-objects so\n // thing.nested.nested.nested... doesn't occur (gh-366)\n var i = 0\n , len = keys.length;\n\n for (; i < len; ++i) {\n // over-write the parents getter without triggering it\n Object.defineProperty(nested, keys[i], {\n enumerable: false // It doesn't show up.\n , writable: true // We can set it later.\n , configurable: true // We can Object.defineProperty again.\n , value: undefined // It shadows its parent.\n });\n }\n\n nested.toObject = function () {\n return this.get(path);\n };\n\n compile(subprops, nested, path);\n this.$__.getters[path] = nested;\n }\n\n return this.$__.getters[path];\n }\n , set: function (v) {\n if (v instanceof Document) v = v.toObject();\n return this.set(path, v);\n }\n });\n\n } else {\n\n Object.defineProperty(prototype, prop, {\n enumerable: true\n , get: function ( ) { return this.get.call(this.$__.scope || this, path); }\n , set: function (v) { return this.set.call(this.$__.scope || this, path, v); }\n });\n }\n};", + "ctx": { + "type": "function", + "name": "define", + "string": "define()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__setSchema" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Assigns/compiles schema into this documents prototype.

    ", + "summary": "

    Assigns/compiles schema into this documents prototype.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__setSchema = function (schema) {\n compile(schema.tree, this);\n this.schema = schema;\n}" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__registerHooks" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Register default hooks

    ", + "summary": "

    Register default hooks

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__registerHooks = function () {\n if (!this.save) return;\n\n DocumentArray || (DocumentArray = require('./types/documentarray'));\n\n this.pre('save', function (next) {\n // validate all document arrays.\n // we keep the error semaphore to make sure we don't\n // call `save` unnecessarily (we only need 1 error)\n var subdocs = 0\n , error = false\n , self = this;\n\n // check for DocumentArrays\n var arrays = this.$__.activePaths\n .map('init', 'modify', function (i) {\n return self.getValue(i);\n })\n .filter(function (val) {\n return val && val instanceof DocumentArray && val.length;\n });\n\n if (!arrays.length)\n return next();\n\n arrays.forEach(function (array) {\n if (error) return;\n\n // handle sparse arrays by using for loop vs array.forEach\n // which skips the sparse elements\n\n var len = array.length\n subdocs += len;\n\n for (var i = 0; i < len; ++i) {\n if (error) break;\n\n var doc = array[i];\n if (!doc) {\n --subdocs || next();\n continue;\n }\n\n doc.save(handleSave);\n }\n });\n\n function handleSave (err) {\n if (error) return;\n\n if (err) {\n self.$__.validationError = undefined;\n return next(error = err);\n }\n\n --subdocs || next();\n }\n\n }, function (err) {\n // emit on the Model if listening\n if (this.constructor.listeners('error').length) {\n this.constructor.emit('error', err);\n } else {\n // emit on the connection\n if (!this.db.listeners('error').length) {\n err.stack = 'No listeners detected, throwing. '\n + 'Consider adding an error listener to your connection.\\n'\n + err.stack\n }\n this.db.emit('error', err);\n }\n }).pre('save', function checkForExistingErrors (next) {\n // if any doc.set() calls failed\n var err = this.$__.saveError;\n if (err) {\n this.$__.saveError = null;\n next(err);\n } else {\n next();\n }\n }).pre('save', function validation (next) {\n return this.validate(next);\n });\n\n // add user defined queues\n this.$__doQueue();\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "err", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__error" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Registers an error

    ", + "summary": "

    Registers an error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__error = function (err) {\n this.$__.saveError = err;\n return this;\n};" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__doQueue" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Executes methods queued from the Schema definition

    ", + "summary": "

    Executes methods queued from the Schema definition

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__doQueue = function () {\n var q = this.schema && this.schema.callQueue;\n if (q) {\n for (var i = 0, l = q.length; i < l; i++) {\n this[q[i][0]].apply(this, q[i][1]);\n }\n }\n return this;\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "js object" + }, + { + "type": "see", + "title": "mongodb.Binary", + "url": "http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html", + "visibility": "http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this document into a plain javascript object, ready for storage in MongoDB.

    \n\n

    Buffers are converted to instances of mongodb.Binary for proper storage.

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    ", + "summary": "

    Converts this document into a plain javascript object, ready for storage in MongoDB.

    ", + "body": "

    Buffers are converted to instances of mongodb.Binary for proper storage.

    \n\n

    Options:

    \n\n
      \n
    • getters apply all getters (path and virtual getters)
    • \n
    • virtuals apply virtual getters (can override getters option)
    • \n
    • minimize remove empty objects (defaults to true)
    • \n
    • transform a transform function to apply to the resulting document before returning
    • \n
    \n\n

    Getters/Virtuals

    \n\n

    Example of only applying path getters

    \n\n
    doc.toObject({ getters: true, virtuals: false })\n
    \n\n

    Example of only applying virtual getters

    \n\n
    doc.toObject({ virtuals: true })\n
    \n\n

    Example of applying both path and virtual getters

    \n\n
    doc.toObject({ getters: true })\n
    \n\n

    To apply these options to every document of your schema by default, set your schemas toObject option to the same argument.

    \n\n
    schema.set('toObject', { virtuals: true })\n
    \n\n

    Transform

    \n\n

    We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional transform function.

    \n\n

    Transform functions receive three arguments

    \n\n
    function (doc, ret, options) {}\n
    \n\n
      \n
    • doc The mongoose document which is being converted
    • \n
    • ret The plain object representation which has been converted
    • \n
    • options The options in use (either schema options or the options passed inline)
    • \n
    \n\n

    Example

    \n\n
    // specify the transform schema option\nschema.options.toObject.transform = function (doc, ret, options) {\n  // remove the _id of every document before returning the result\n  delete ret._id;\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { name: 'Wreck-it Ralph' }\n
    \n\n

    With transformations we can do a lot more than remove properties. We can even return completely new customized objects:

    \n\n
    schema.options.toObject.transform = function (doc, ret, options) {\n  return { movie: ret.name }\n}\n\n// without the transformation in the schema\ndoc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }\n\n// with the transformation\ndoc.toObject(); // { movie: 'Wreck-it Ralph' }\n
    \n\n

    Note: if a transform function returns undefined, the return value will be ignored.

    \n\n

    Transformations may also be applied inline, overridding any transform set in the options:

    \n\n
    function xform (doc, ret, options) {\n  return { inline: ret.name, custom: true }\n}\n\n// pass the transform as an inline option\ndoc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }\n
    \n\n

    Note: if you call toObject and pass any options, the transform declared in your schema options will not be applied. To force its application pass transform: true

    \n\n
    schema.options.toObject.hide = '_id';\nschema.options.toObject.transform = function (doc, ret, options) {\n  if (options.hide) {\n    options.hide.split(' ').forEach(function (prop) {\n      delete ret[prop];\n    });\n  }\n}\n\nvar doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });\ndoc.toObject();                                        // { secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id' });                  // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }\ndoc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }\n
    \n\n

    Transforms are applied to the document and each of its sub-documents. To determine whether or not you are currently operating on a sub-document you might use the following guard:

    \n\n
    if ('function' == typeof doc.ownerDocument) {\n  // working with a sub doc\n}\n
    \n\n

    Transforms, like all of these options, are also available for toJSON.

    \n\n

    See schema options for some more details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toObject = function (options) {\n // check for populated paths that we set to a document\n if (options && options.convertToId) {\n return clone(this._id, options);\n }\n\n // When internally saving this document we always pass options,\n // bypassing the custom schema options.\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toObject\n ? clone(this.schema.options.toObject)\n : {};\n }\n\n ;('minimize' in options) || (options.minimize = this.schema.options.minimize);\n\n var ret = clone(this._doc, options);\n\n if (options.virtuals || options.getters && false !== options.virtuals) {\n applyGetters(this, ret, 'virtuals', options);\n }\n\n if (options.getters) {\n applyGetters(this, ret, 'paths', options);\n }\n\n if (true === options.transform) {\n var opts = options.json\n ? this.schema.options.toJSON\n : this.schema.options.toObject;\n if (opts) {\n options.transform = opts.transform;\n }\n }\n\n if ('function' == typeof options.transform) {\n var xformed = options.transform(this, ret, options);\n if ('undefined' != typeof xformed) ret = xformed;\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toObject", + "string": "Document.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "json", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "either `virtuals` or `paths`" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "`json`" + } + ], + "description": { + "full": "

    Applies virtuals properties to json.

    ", + "summary": "

    Applies virtuals properties to json.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function applyGetters (self, json, type, options) {\n var schema = self.schema\n , paths = Object.keys(schema[type])\n , i = paths.length\n , path\n\n while (i--) {\n path = paths[i];\n\n var parts = path.split('.')\n , plen = parts.length\n , last = plen - 1\n , branch = json\n , part\n\n for (var ii = 0; ii < plen; ++ii) {\n part = parts[ii];\n if (ii === last) {\n branch[part] = clone(self.get(path), options);\n } else {\n branch = branch[part] || (branch[part] = {});\n }\n }\n }\n\n return json;\n}", + "ctx": { + "type": "function", + "name": "applyGetters", + "string": "applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "same options as [Document#toObject](#document_Document-toObject)" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "see", + "local": "Document#toObject #document_Document-toObject", + "visibility": "Document#toObject" + }, + { + "type": "", + "string": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The return value of this method is used in calls to JSON.stringify(doc).

    \n\n

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    ", + "summary": "

    The return value of this method is used in calls to JSON.stringify(doc).

    ", + "body": "

    This method accepts the same options as Document#toObject. To apply the options to every document of your schema by default, set your schemas toJSON option to the same argument.

    \n\n
    schema.set('toJSON', { virtuals: true })\n
    \n\n

    See schema options for details.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toJSON = function (options) {\n // check for object type since an array of documents\n // being stringified passes array indexes instead\n // of options objects. JSON.stringify([doc, doc])\n if (!(options && 'Object' == options.constructor.name)) {\n options = this.schema.options.toJSON\n ? clone(this.schema.options.toJSON)\n : {};\n }\n options.json = true;\n return this.toObject(options);\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "toJSON", + "string": "Document.prototype.toJSON()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.inspect = function (options) {\n var opts = options && 'Object' == options.constructor.name ? options :\n this.schema.options.toObject ? clone(this.schema.options.toObject) :\n {};\n opts.minimize = false;\n return inspect(this.toObject(opts));\n};", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "inspect", + "string": "Document.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "toString" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.toString = Document.prototype.inspect;", + "ctx": { + "type": "property", + "constructor": "Document", + "name": "toString", + "value": "Document.prototype.inspect", + "string": "Document.prototypetoString" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "a document to compare" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns true if the Document stores the same data as doc.

    \n\n

    Documents are considered equal when they have matching _ids.

    ", + "summary": "

    Returns true if the Document stores the same data as doc.

    ", + "body": "

    Documents are considered equal when they have matching _ids.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.equals = function (doc) {\n var tid = this.get('_id');\n var docid = doc.get('_id');\n return tid.equals\n ? tid.equals(docid)\n : tid === docid;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "equals", + "string": "Document.prototype.equals()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Model.populate #model_Model.populate", + "visibility": "Model.populate" + }, + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "[path]", + "description": "The path to populate or an options object" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "When passed, population is invoked" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Document" + ], + "description": "this" + } + ], + "description": { + "full": "

    Populates document references, executing the callback when complete.

    \n\n

    Example:

    \n\n
    doc\n.populate('company')\n.populate({\n  path: 'notes',\n  match: /airline/,\n  select: 'text',\n  match: 'modelName'\n  options: opts\n}, function (err, user) {\n  assert(doc._id == user._id) // the document itself is passed\n})\n\n// summary\ndoc.populate(path)               // not executed\ndoc.populate(options);           // not executed\ndoc.populate(path, callback)     // executed\ndoc.populate(options, callback); // executed\ndoc.populate(callback);          // executed\n
    \n\n

    NOTE:

    \n\n

    Population does not occur unless a callback is passed.
    Passing the same path a second time will overwrite the previous path options.
    See Model.populate() for explaination of options.

    ", + "summary": "

    Populates document references, executing the callback when complete.

    ", + "body": "

    Example:

    \n\n
    doc\n.populate('company')\n.populate({\n  path: 'notes',\n  match: /airline/,\n  select: 'text',\n  match: 'modelName'\n  options: opts\n}, function (err, user) {\n  assert(doc._id == user._id) // the document itself is passed\n})\n\n// summary\ndoc.populate(path)               // not executed\ndoc.populate(options);           // not executed\ndoc.populate(path, callback)     // executed\ndoc.populate(options, callback); // executed\ndoc.populate(callback);          // executed\n
    \n\n

    NOTE:

    \n\n

    Population does not occur unless a callback is passed.
    Passing the same path a second time will overwrite the previous path options.
    See Model.populate() for explaination of options.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.populate = function populate () {\n if (0 === arguments.length) return this;\n\n var pop = this.$__.populate || (this.$__.populate = {});\n var args = utils.args(arguments);\n var fn;\n\n if ('function' == typeof args[args.length-1]) {\n fn = args.pop();\n }\n\n // allow `doc.populate(callback)`\n if (args.length) {\n // use hash to remove duplicate paths\n var res = utils.populate.apply(null, args);\n for (var i = 0; i < res.length; ++i) {\n pop[res[i].path] = res[i];\n }\n }\n\n if (fn) {\n var paths = utils.object.vals(pop);\n this.$__.populate = undefined;\n this.constructor.populate(this, paths, fn);\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "populate", + "string": "Document.prototype.populate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Array", + "ObjectId", + "Number", + "Buffer", + "String", + "undefined" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets _id(s) used during population of the given path.

    \n\n

    Example:

    \n\n
    Model.findOne().populate('author').exec(function (err, doc) {\n  console.log(doc.author.name)         // Dr.Seuss\n  console.log(doc.populated('author')) // '5144cf8050f071d979c118a7'\n})\n
    \n\n

    If the path was not populated, undefined is returned.

    ", + "summary": "

    Gets _id(s) used during population of the given path.

    ", + "body": "

    Example:

    \n\n
    Model.findOne().populate('author').exec(function (err, doc) {\n  console.log(doc.author.name)         // Dr.Seuss\n  console.log(doc.populated('author')) // '5144cf8050f071d979c118a7'\n})\n
    \n\n

    If the path was not populated, undefined is returned.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Document.prototype.populated = function (path, val, options) {\n // val and options are internal\n\n if (null == val) {\n if (!this.$__.populated) return undefined;\n var v = this.$__.populated[path];\n if (v) return v.value;\n return undefined;\n }\n\n // internal\n\n if (true === val) {\n if (!this.$__.populated) return undefined;\n return this.$__.populated[path];\n }\n\n this.$__.populated || (this.$__.populated = {});\n this.$__.populated[path] = { value: val, options: options };\n return val;\n}", + "ctx": { + "type": "method", + "constructor": "Document", + "name": "populated", + "string": "Document.prototype.populated()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__fullPath" + }, + { + "type": "memberOf", + "parent": "Document" + } + ], + "description": { + "full": "

    Returns the full path to this document.

    ", + "summary": "

    Returns the full path to this document.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Document.prototype.$__fullPath = function (path) {\n // overridden in SubDocuments\n return path || '';\n}" + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "Document.ValidationError = ValidationError;\nmodule.exports = exports = Document;\nexports.Error = DocumentError;", + "ctx": { + "type": "property", + "receiver": "Document", + "name": "ValidationError", + "value": "ValidationError", + "string": "Document.ValidationError" + } + } +] +### lib/drivers/node-mongodb-native/binary.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require('mongodb').BSONPure.Binary;\n\nmodule.exports = exports = Binary;", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require('mongodb').BSONPure.Binary", + "string": "Binary" + } + } +] +### lib/drivers/node-mongodb-native/collection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseCollection = require('../../collection')\n , Collection = require('mongodb').Collection\n , STATES = require('../../connectionstate')\n , utils = require('../../utils')", + "ctx": { + "type": "declaration", + "name": "MongooseCollection", + "value": "require('../../collection')", + "string": "MongooseCollection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Collection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native collection implementation.

    \n\n

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    ", + "summary": "

    A node-mongodb-native collection implementation.

    ", + "body": "

    All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeCollection () {\n this.collection = null;\n MongooseCollection.apply(this, arguments);\n}", + "ctx": { + "type": "function", + "name": "NativeCollection", + "string": "NativeCollection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from abstract Collection.

    ", + "summary": "

    Inherit from abstract Collection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeCollection.prototype.__proto__ = MongooseCollection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "__proto__", + "value": "MongooseCollection.prototype", + "string": "NativeCollection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection opens.

    ", + "summary": "

    Called when the connection opens.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onOpen = function () {\n var self = this;\n\n // always get a new collection in case the user changed host:port\n // of parent db instance when re-opening the connection.\n\n if (!self.opts.capped.size) {\n // non-capped\n return self.conn.db.collection(self.name, callback);\n }\n\n // capped\n return self.conn.db.collection(self.name, function (err, c) {\n if (err) return callback(err);\n\n // discover if this collection exists and if it is capped\n c.options(function (err, exists) {\n if (err) return callback(err);\n\n if (exists) {\n if (exists.capped) {\n callback(null, c);\n } else {\n var msg = 'A non-capped collection exists with this name.\\n\\n'\n + ' To use this collection as a capped collection, please '\n + 'first convert it.\\n'\n + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'\n err = new Error(msg);\n callback(err);\n }\n } else {\n // create\n var opts = utils.clone(self.opts.capped);\n opts.capped = true;\n self.conn.db.createCollection(self.name, opts, callback);\n }\n });\n });\n\n function callback (err, collection) {\n if (err) {\n // likely a strict mode error\n self.conn.emit('error', err);\n } else {\n self.collection = collection;\n MongooseCollection.prototype.onOpen.call(self);\n }\n };\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onOpen", + "string": "NativeCollection.prototype.onOpen()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the connection closes

    ", + "summary": "

    Called when the connection closes

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeCollection.prototype.onClose = function () {\n MongooseCollection.prototype.onClose.call(this);\n};", + "ctx": { + "type": "method", + "constructor": "NativeCollection", + "name": "onClose", + "string": "NativeCollection.prototype.onClose()" + } + }, + { + "tags": [], + "description": { + "full": "

    Copy the collection methods and make them subject to queues

    ", + "summary": "

    Copy the collection methods and make them subject to queues

    ", + "body": "" + }, + "ignore": true, + "code": "for (var i in Collection.prototype) {\n (function(i){\n NativeCollection.prototype[i] = function () {\n if (this.buffer) {\n this.addQueue(i, arguments);\n return;\n }\n\n var collection = this.collection\n , args = arguments\n , self = this\n , debug = self.conn.base.options.debug;\n\n if (debug) {\n if ('function' === typeof debug) {\n debug.apply(debug\n , [self.name, i].concat(utils.args(args, 0, args.length-1)));\n } else {\n console.error('\\x1B[0;36mMongoose:\\x1B[0m %s.%s(%s) %s %s %s'\n , self.name\n , i\n , print(args[0])\n , print(args[1])\n , print(args[2])\n , print(args[3]))\n }\n }\n\n collection[i].apply(collection, args);\n };\n })(i);\n}" + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function print (arg) {\n var type = typeof arg;\n if ('function' === type || 'undefined' === type) return '';\n return format(arg);\n}", + "ctx": { + "type": "function", + "name": "print", + "string": "print()" + } + }, + { + "tags": [], + "description": { + "full": "

    Debug print helper

    ", + "summary": "

    Debug print helper

    ", + "body": "" + }, + "ignore": true, + "code": "function format (obj, sub) {\n var x = utils.clone(obj);\n if (x) {\n if ('Binary' === x.constructor.name) {\n x = '[object Buffer]';\n } else if ('ObjectID' === x.constructor.name) {\n var representation = 'ObjectId(\"' + x.toHexString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Date' === x.constructor.name) {\n var representation = 'new Date(\"' + x.toUTCString() + '\")';\n x = { inspect: function() { return representation; } };\n } else if ('Object' === x.constructor.name) {\n var keys = Object.keys(x)\n , i = keys.length\n , key\n while (i--) {\n key = keys[i];\n if (x[key]) {\n if ('Binary' === x[key].constructor.name) {\n x[key] = '[object Buffer]';\n } else if ('Object' === x[key].constructor.name) {\n x[key] = format(x[key], true);\n } else if ('ObjectID' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'ObjectId(\"' + x[key].toHexString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if ('Date' === x[key].constructor.name) {\n ;(function(x){\n var representation = 'new Date(\"' + x[key].toUTCString() + '\")';\n x[key] = { inspect: function() { return representation; } };\n })(x)\n } else if (Array.isArray(x[key])) {\n x[key] = x[key].map(function (o) {\n return format(o, true)\n });\n }\n }\n }\n }\n if (sub) return x;\n }\n\n return require('util')\n .inspect(x, false, 10, true)\n .replace(/\\n/g, '')\n .replace(/\\s{2,}/g, ' ')\n}", + "ctx": { + "type": "function", + "name": "format", + "string": "format()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "method", + "string": "getIndexes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Retreives information about this collections indexes.

    ", + "summary": "

    Retreives information about this collections indexes.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;", + "ctx": { + "type": "property", + "constructor": "NativeCollection", + "name": "getIndexes", + "value": "NativeCollection.prototype.indexInformation", + "string": "NativeCollection.prototypegetIndexes" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeCollection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeCollection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/connection.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseConnection = require('../../connection')\n , mongo = require('mongodb')\n , Server = mongo.Server\n , STATES = require('../../connectionstate')\n , ReplSetServers = mongo.ReplSetServers;", + "ctx": { + "type": "declaration", + "name": "MongooseConnection", + "value": "require('../../connection')", + "string": "MongooseConnection" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "Connection" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A node-mongodb-native connection implementation.

    ", + "summary": "

    A node-mongodb-native connection implementation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function NativeConnection() {\n MongooseConnection.apply(this, arguments);\n this._listening = false;\n};", + "ctx": { + "type": "function", + "name": "NativeConnection", + "string": "NativeConnection()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Connection.

    ", + "summary": "

    Inherits from Connection.

    ", + "body": "" + }, + "ignore": true, + "code": "NativeConnection.prototype.__proto__ = MongooseConnection.prototype;", + "ctx": { + "type": "property", + "constructor": "NativeConnection", + "name": "__proto__", + "value": "MongooseConnection.prototype", + "string": "NativeConnection.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Opens the connection to MongoDB.

    ", + "summary": "

    Opens the connection to MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpen = function (fn) {\n if (this.db) {\n mute(this);\n }\n\n var server = new mongo.Server(this.host, this.port, this.options.server);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n var self = this;\n this.db.open(function (err) {\n if (err) return fn(err);\n listen(self);\n fn();\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpen", + "string": "NativeConnection.prototype.doOpen()" + } + }, + { + "tags": [], + "description": { + "full": "

    Register listeners for important events and bubble appropriately.

    ", + "summary": "

    Register listeners for important events and bubble appropriately.

    ", + "body": "" + }, + "ignore": true, + "code": "function listen (conn) {\n if (conn._listening) return;\n conn._listening = true;\n\n conn.db.on('close', function(){\n if (conn._closeCalled) return;\n\n // the driver never emits an `open` event. auto_reconnect still\n // emits a `close` event but since we never get another\n // `open` we can't emit close\n if (conn.db.serverConfig.autoReconnect) {\n conn.readyState = STATES.disconnected;\n conn.emit('close');\n return;\n }\n conn.onClose();\n });\n conn.db.on('error', function(err){\n conn.emit('error', err);\n });\n conn.db.on('timeout', function(err){\n var error = new Error(err && err.err || 'connection timeout');\n conn.emit('error', error);\n });\n conn.db.on('open', function (err, db) {\n if (STATES.disconnected === conn.readyState && db && db.databaseName) {\n conn.readyState = STATES.connected;\n conn.emit('reconnected')\n }\n })\n}", + "ctx": { + "type": "function", + "name": "listen", + "string": "listen()" + } + }, + { + "tags": [], + "description": { + "full": "

    Remove listeners registered in listen

    ", + "summary": "

    Remove listeners registered in listen

    ", + "body": "" + }, + "ignore": true, + "code": "function mute (conn) {\n if (!conn.db) throw new Error('missing db');\n conn.db.removeAllListeners(\"close\");\n conn.db.removeAllListeners(\"error\");\n conn.db.removeAllListeners(\"timeout\");\n conn.db.removeAllListeners(\"open\");\n conn.db.removeAllListeners(\"fullsetup\");\n conn._listening = false;\n}", + "ctx": { + "type": "function", + "name": "mute", + "string": "mute()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens a connection to a MongoDB ReplicaSet.

    \n\n

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    ", + "summary": "

    Opens a connection to a MongoDB ReplicaSet.

    ", + "body": "

    See description of doOpen for server options. In this case options.replset is also passed to ReplSetServers.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doOpenSet = function (fn) {\n if (this.db) {\n mute(this);\n }\n\n var servers = []\n , self = this;\n\n this.hosts.forEach(function (server) {\n var host = server.host || server.ipc;\n var port = server.port || 27017;\n servers.push(new mongo.Server(host, port, self.options.server));\n })\n\n var server = new ReplSetServers(servers, this.options.replset);\n this.db = new mongo.Db(this.name, server, this.options.db);\n\n this.db.on('fullsetup', function () {\n self.emit('fullsetup')\n });\n\n this.db.open(function (err) {\n if (err) return fn(err);\n fn();\n listen(self);\n });\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doOpenSet", + "string": "NativeConnection.prototype.doOpenSet()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Closes the connection

    ", + "summary": "

    Closes the connection

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.doClose = function (fn) {\n this.db.close();\n if (fn) fn();\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "doClose", + "string": "NativeConnection.prototype.doClose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "passed", + "description": "options that were passed directly during connection" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[connStrOptions]", + "description": "options that were passed in the connection string" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Prepares default connection options for the node-mongodb-native driver.

    \n\n

    NOTE: passed options take precedence over connection string options.

    ", + "summary": "

    Prepares default connection options for the node-mongodb-native driver.

    ", + "body": "

    NOTE: passed options take precedence over connection string options.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {\n var o = passed || {};\n o.db || (o.db = {});\n o.auth || (o.auth = {});\n o.server || (o.server = {});\n o.replset || (o.replset = {});\n o.server.socketOptions || (o.server.socketOptions = {});\n o.replset.socketOptions || (o.replset.socketOptions = {});\n\n var opts = connStrOpts || {};\n Object.keys(opts).forEach(function (name) {\n switch (name) {\n case 'poolSize':\n if ('undefined' == typeof o.server.poolSize) {\n o.server.poolSize = o.replset.poolSize = opts[name];\n }\n break;\n case 'slaveOk':\n if ('undefined' == typeof o.server.slave_ok) {\n o.server.slave_ok = opts[name];\n }\n break;\n case 'autoReconnect':\n if ('undefined' == typeof o.server.auto_reconnect) {\n o.server.auto_reconnect = opts[name];\n }\n break;\n case 'ssl':\n case 'socketTimeoutMS':\n case 'connectTimeoutMS':\n if ('undefined' == typeof o.server.socketOptions[name]) {\n o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];\n }\n break;\n case 'authdb':\n if ('undefined' == typeof o.auth.authdb) {\n o.auth.authdb = opts[name];\n }\n break;\n case 'authSource':\n if ('undefined' == typeof o.auth.authSource) {\n o.auth.authSource = opts[name];\n }\n break;\n case 'retries':\n case 'reconnectWait':\n case 'rs_name':\n if ('undefined' == typeof o.replset[name]) {\n o.replset[name] = opts[name];\n }\n break;\n case 'replicaSet':\n if ('undefined' == typeof o.replset.rs_name) {\n o.replset.rs_name = opts[name];\n }\n break;\n case 'readSecondary':\n if ('undefined' == typeof o.replset.read_secondary) {\n o.replset.read_secondary = opts[name];\n }\n break;\n case 'nativeParser':\n if ('undefined' == typeof o.db.native_parser) {\n o.db.native_parser = opts[name];\n }\n break;\n case 'w':\n case 'safe':\n case 'fsync':\n case 'journal':\n case 'wtimeoutMS':\n if ('undefined' == typeof o.db[name]) {\n o.db[name] = opts[name];\n }\n break;\n case 'readPreference':\n if ('undefined' == typeof o.db.read_preference) {\n o.db.read_preference = opts[name];\n }\n break;\n case 'readPreferenceTags':\n if ('undefined' == typeof o.db.read_preference_tags) {\n o.db.read_preference_tags = opts[name];\n }\n break;\n }\n })\n\n if (!('auto_reconnect' in o.server)) {\n o.server.auto_reconnect = true;\n }\n\n if (!o.db.read_preference) {\n // read from primaries by default\n o.db.read_preference = 'primary';\n }\n\n // mongoose creates its own ObjectIds\n o.db.forceServerObjectId = false;\n\n // default safe using new nomenclature\n if (!('journal' in o.db || 'j' in o.db ||\n 'fsync' in o.db || 'safe' in o.db || 'w' in o.db)) {\n o.db.w = 1;\n }\n\n validate(o);\n return o;\n}", + "ctx": { + "type": "method", + "constructor": "NativeConnection", + "name": "parseOptions", + "string": "NativeConnection.prototype.parseOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "o", + "description": "" + } + ], + "description": { + "full": "

    Validates the driver db options.

    ", + "summary": "

    Validates the driver db options.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function validate (o) {\n if (-1 === o.db.w || 0 === o.db.w) {\n if (o.db.journal || o.db.fsync || o.db.safe) {\n throw new Error(\n 'Invalid writeConcern: '\n + 'w set to -1 or 0 cannot be combined with safe|fsync|journal');\n }\n }\n}", + "ctx": { + "type": "function", + "name": "validate", + "string": "validate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = NativeConnection;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "NativeConnection", + "string": "module.exports" + } + } +] +### lib/drivers/node-mongodb-native/objectid.js +[ + { + "tags": [ + { + "type": "constructor", + "string": "NodeMongoDbObjectId" + }, + { + "type": "see", + "local": "ObjectId", + "visibility": "ObjectId" + } + ], + "description": { + "full": "

    node-mongodb-native ObjectId

    ", + "summary": "

    node-mongodb-native ObjectId

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "var ObjectId = require('mongodb').BSONPure.ObjectID;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require('mongodb').BSONPure.ObjectID", + "string": "ObjectId" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "var ObjectIdToString = ObjectId.toString.bind(ObjectId);\nmodule.exports = exports = ObjectId;\n\nObjectId.fromString = function(str){\n // patch native driver bug in V0.9.6.4\n if (!('string' === typeof str && 24 === str.length)) {\n throw new Error(\"Invalid ObjectId\");\n }\n\n return ObjectId.createFromHexString(str);\n};\n\nObjectId.toString = function(oid){\n if (!arguments.length) return ObjectIdToString();\n return oid.toHexString();\n};", + "ctx": { + "type": "declaration", + "name": "ObjectIdToString", + "value": "ObjectId.toString.bind(ObjectId)", + "string": "ObjectIdToString" + } + } +] +### lib/error.js +[ + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error" + } + ], + "description": { + "full": "

    Mongoose error

    ", + "summary": "

    Mongoose error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseError (msg) {\n Error.call(this);\n Error.captureStackTrace(this, arguments.callee);\n this.message = msg;\n this.name = 'MongooseError';\n};", + "ctx": { + "type": "function", + "name": "MongooseError", + "string": "MongooseError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Error.

    ", + "summary": "

    Inherits from Error.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseError.prototype.__proto__ = Error.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseError", + "name": "__proto__", + "value": "Error.prototype", + "string": "MongooseError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = MongooseError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = MongooseError", + "string": "module.exports" + } + }, + { + "tags": [], + "description": { + "full": "

    Expose subclasses

    ", + "summary": "

    Expose subclasses

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseError.CastError = require('./errors/cast');\nMongooseError.DocumentError = require('./errors/document');\nMongooseError.ValidationError = require('./errors/validation')\nMongooseError.ValidatorError = require('./errors/validator')\nMongooseError.VersionError =require('./errors/version')\nMongooseError.OverwriteModelError = require('./errors/overwriteModel')\nMongooseError.MissingSchemaError = require('./errors/missingSchema')\nMongooseError.DivergentArrayError = require('./errors/divergentArray')", + "ctx": { + "type": "property", + "receiver": "MongooseError", + "name": "CastError", + "value": "require('./errors/cast')", + "string": "MongooseError.CastError" + } + } +] +### lib/errors/cast.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casting Error constructor.

    ", + "summary": "

    Casting Error constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function CastError (type, value, path) {\n MongooseError.call(this, 'Cast to ' + type + ' failed for value \"' + value + '\" at path \"' + path + '\"');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'CastError';\n this.type = type;\n this.value = value;\n this.path = path;\n};", + "ctx": { + "type": "function", + "name": "CastError", + "string": "CastError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "CastError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "CastError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "CastError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = CastError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "CastError", + "string": "module.exports" + } + } +] +### lib/errors/divergentArray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    DivergentArrayError constructor.

    ", + "summary": "

    DivergentArrayError constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function DivergentArrayError (paths) {\n var msg = 'For your own good, using `document.save()` to update an array '\n + 'which was selected using an $elemMatch projection OR '\n + 'populated using skip, limit, query conditions, or exclusion of '\n + 'the _id field when the operation results in a $pop or $set of '\n + 'the entire array is not supported. The following '\n + 'path(s) would have been modified unsafely:\\n'\n + ' ' + paths.join('\\n ') + '\\n'\n + 'Use Model.update() to update these arrays instead.'\n // TODO write up a docs page (FAQ) and link to it\n\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DivergentArrayError';\n};", + "ctx": { + "type": "function", + "name": "DivergentArrayError", + "string": "DivergentArrayError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "DivergentArrayError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "DivergentArrayError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "DivergentArrayError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = DivergentArrayError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "DivergentArrayError", + "string": "module.exports" + } + } +] +### lib/errors/document.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Document Error

    ", + "summary": "

    Document Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentError (msg) {\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'DocumentError';\n};", + "ctx": { + "type": "function", + "name": "DocumentError", + "string": "DocumentError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "DocumentError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = DocumentError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = DocumentError", + "string": "module.exports" + } + } +] +### lib/errors/missingSchema.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    MissingSchema Error constructor.

    ", + "summary": "

    MissingSchema Error constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function MissingSchemaError (name) {\n var msg = 'Schema hasn\\'t been registered for model \"' + name + '\".\\n'\n + 'Use mongoose.model(name, schema)';\n MongooseError.call(this, msg);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'MissingSchemaError';\n};", + "ctx": { + "type": "function", + "name": "MissingSchemaError", + "string": "MissingSchemaError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "MissingSchemaError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "MissingSchemaError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "MissingSchemaError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MissingSchemaError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MissingSchemaError", + "string": "module.exports" + } + } +] +### lib/errors/overwriteModel.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    OverwriteModel Error constructor.

    ", + "summary": "

    OverwriteModel Error constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function OverwriteModelError (name) {\n MongooseError.call(this, 'Cannot overwrite `' + name + '` model once compiled.');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'OverwriteModelError';\n};", + "ctx": { + "type": "function", + "name": "OverwriteModelError", + "string": "OverwriteModelError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "OverwriteModelError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "OverwriteModelError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "OverwriteModelError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = OverwriteModelError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "OverwriteModelError", + "string": "module.exports" + } + } +] +### lib/errors/validation.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements

    ", + "summary": "

    Module requirements

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error')", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "instance", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + } + ], + "description": { + "full": "

    Document Validation Error

    ", + "summary": "

    Document Validation Error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidationError (instance) {\n MongooseError.call(this, \"Validation failed\");\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidationError';\n this.errors = instance.errors = {};\n};", + "ctx": { + "type": "function", + "name": "ValidationError", + "string": "ValidationError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Console.log helper

    ", + "summary": "

    Console.log helper

    ", + "body": "" + }, + "ignore": false, + "code": "ValidationError.prototype.toString = function () {\n return this.name + ': ' + Object.keys(this.errors).map(function (key) {\n return String(this.errors[key]);\n }, this).join(', ');\n};", + "ctx": { + "type": "method", + "constructor": "ValidationError", + "name": "toString", + "string": "ValidationError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "ValidationError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidationError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidationError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = ValidationError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = ValidationError", + "string": "module.exports" + } + } +] +### lib/errors/validator.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "msg", + "description": "" + }, + { + "type": "param", + "types": [ + "String", + "Number", + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Schema validator error

    ", + "summary": "

    Schema validator error

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ValidatorError (path, type, val) {\n var msg = type\n ? '\"' + type + '\" '\n : '';\n\n var message = 'Validator ' + msg + 'failed for path ' + path\n if (2 < arguments.length) message += ' with value `' + String(val) + '`';\n\n MongooseError.call(this, message);\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'ValidatorError';\n this.path = path;\n this.type = type;\n this.value = val;\n};", + "ctx": { + "type": "function", + "name": "ValidatorError", + "string": "ValidatorError()" + } + }, + { + "tags": [], + "description": { + "full": "

    toString helper

    ", + "summary": "

    toString helper

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.toString = function () {\n return this.message;\n}", + "ctx": { + "type": "method", + "constructor": "ValidatorError", + "name": "toString", + "string": "ValidatorError.prototype.toString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError

    ", + "summary": "

    Inherits from MongooseError

    ", + "body": "" + }, + "ignore": true, + "code": "ValidatorError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "ValidatorError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "ValidatorError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ValidatorError", + "string": "module.exports" + } + } +] +### lib/errors/version.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseError = require('../error');", + "ctx": { + "type": "declaration", + "name": "MongooseError", + "value": "require('../error')", + "string": "MongooseError" + } + }, + { + "tags": [ + { + "type": "inherits", + "string": "MongooseError" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Version Error constructor.

    ", + "summary": "

    Version Error constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function VersionError () {\n MongooseError.call(this, 'No matching document found.');\n Error.captureStackTrace(this, arguments.callee);\n this.name = 'VersionError';\n};", + "ctx": { + "type": "function", + "name": "VersionError", + "string": "VersionError()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseError.

    ", + "summary": "

    Inherits from MongooseError.

    ", + "body": "" + }, + "ignore": true, + "code": "VersionError.prototype.__proto__ = MongooseError.prototype;", + "ctx": { + "type": "property", + "constructor": "VersionError", + "name": "__proto__", + "value": "MongooseError.prototype", + "string": "VersionError.prototype__proto__" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = VersionError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "VersionError", + "string": "module.exports" + } + } +] +### lib/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')\n , SchemaType = require('./schematype')\n , VirtualType = require('./virtualtype')\n , SchemaTypes = Schema.Types\n , SchemaDefaults = require('./schemadefault')\n , Types = require('./types')\n , Query = require('./query')\n , Promise = require('./promise')\n , Model = require('./model')\n , Document = require('./document')\n , utils = require('./utils')\n , format = utils.toCollectionName\n , mongodb = require('mongodb')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Mongoose constructor.

    \n\n

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    ", + "summary": "

    Mongoose constructor.

    ", + "body": "

    The exports object of the mongoose module is an instance of this class.
    Most apps will only use this one instance.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Mongoose () {\n this.connections = [];\n this.plugins = [];\n this.models = {};\n this.modelSchemas = {};\n this.options = {};\n this.createConnection(); // default connection\n};", + "ctx": { + "type": "function", + "name": "Mongoose", + "string": "Mongoose()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    ", + "summary": "

    Sets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.set('test', value) // sets the 'test' option to `value`\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.set = function (key, value) {\n if (arguments.length == 1)\n return this.options[key];\n this.options[key] = value;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "set", + "string": "Mongoose.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "method", + "string": "get" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets mongoose options

    \n\n

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    ", + "summary": "

    Gets mongoose options

    ", + "body": "

    Example:

    \n\n
    mongoose.get('test') // returns the 'test' value\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.get = Mongoose.prototype.set;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "get", + "value": "Mongoose.prototype.set", + "string": "Mongoose.prototypeget" + } + }, + { + "tags": [], + "description": { + "full": "

    ReplSet connection string check.

    ", + "summary": "

    ReplSet connection string check.

    ", + "body": "" + }, + "ignore": true, + "code": "var rgxReplSet = /^.+,.+$/;", + "ctx": { + "type": "declaration", + "name": "rgxReplSet", + "value": "/^.+,.+$/", + "string": "rgxReplSet" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[uri]", + "description": "a mongodb:// URI" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "options to pass to the driver" + }, + { + "type": "see", + "local": "Connection#open #connection_Connection-open", + "visibility": "Connection#open" + }, + { + "type": "see", + "local": "Connection#openSet #connection_Connection-openSet", + "visibility": "Connection#openSet" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "the created Connection object" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Connection instance.

    \n\n

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    ", + "summary": "

    Creates a Connection instance.

    ", + "body": "

    Each connection instance maps to a single database. This method is helpful when mangaging multiple db connections.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately. This means we can pass db, server, and replset options to the driver.

    \n\n

    Options passed take precedence over options included in connection strings.

    \n\n

    Example:

    \n\n
    // with mongodb:// URI\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database');\n\n// and options\nvar opts = { db: { native_parser: true }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);\n\n// replica sets\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');\n\n// and options\nvar opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}\ndb = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);\n\n// with [host, database_name[, port] signature\ndb = mongoose.createConnection('localhost', 'database', port)\n\n// and options\nvar opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }\ndb = mongoose.createConnection('localhost', 'database', port, opts)\n\n// initialize now, connect later\ndb = mongoose.createConnection();\ndb.open('localhost', 'database', port, [opts]);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.createConnection = function () {\n var conn = new Connection(this);\n this.connections.push(conn);\n\n if (arguments.length) {\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n }\n\n return conn;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "createConnection", + "string": "Mongoose.prototype.createConnection()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "Mongoose#createConnection #index_Mongoose-createConnection", + "visibility": "Mongoose#createConnection" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + } + ], + "description": { + "full": "

    Opens the default mongoose connection.

    \n\n

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    \n\n

    Options passed take precedence over options included in connection strings.

    ", + "summary": "

    Opens the default mongoose connection.

    ", + "body": "

    If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

    \n\n

    Options passed take precedence over options included in connection strings.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.connect = function () {\n var conn = this.connection;\n\n if (rgxReplSet.test(arguments[0])) {\n conn.openSet.apply(conn, arguments);\n } else {\n conn.open.apply(conn, arguments);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "connect", + "string": "Mongoose.prototype.connect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "called after all connection close." + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Disconnects all connections.

    ", + "summary": "

    Disconnects all connections.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.disconnect = function (fn) {\n var count = this.connections.length\n , error\n\n this.connections.forEach(function(conn){\n conn.close(function(err){\n if (error) return;\n\n if (err) {\n error = err;\n if (fn) return fn(err);\n throw err;\n }\n\n if (fn)\n --count || fn();\n });\n });\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "disconnect", + "string": "Mongoose.prototype.disconnect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "name (optional, induced from model name)" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "[skipInit]", + "description": "whether to skip initialization (defaults to false)" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a model or retrieves it.

    \n\n

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String }, { collection: 'actor' });\n\n// or\n\nschema.set('collection', 'actor');\n\n// or\n\nvar collectionName = 'actor'\nvar M = mongoose.model('Actor', schema, collectionName)\n
    ", + "summary": "

    Defines a model or retrieves it.

    ", + "body": "

    Models defined on the mongoose instance are available to all connection created by the same mongoose instance.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\n\n// define an Actor model with this mongoose instance\nmongoose.model('Actor', new Schema({ name: String }));\n\n// create a new connection\nvar conn = mongoose.createConnection(..);\n\n// retrieve the Actor model\nvar Actor = conn.model('Actor');\n
    \n\n

    When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ name: String }, { collection: 'actor' });\n\n// or\n\nschema.set('collection', 'actor');\n\n// or\n\nvar collectionName = 'actor'\nvar M = mongoose.model('Actor', schema, collectionName)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.model = function (name, schema, collection, skipInit) {\n if ('string' == typeof schema) {\n collection = schema;\n schema = false;\n }\n\n if (utils.isObject(schema) && !(schema instanceof Schema)) {\n schema = new Schema(schema);\n }\n\n if ('boolean' === typeof collection) {\n skipInit = collection;\n collection = null;\n }\n\n // handle internal options from connection.model()\n var options;\n if (skipInit && utils.isObject(skipInit)) {\n options = skipInit;\n skipInit = true;\n } else {\n options = {};\n }\n\n // look up schema for the collection. this might be a\n // default schema like system.indexes stored in SchemaDefaults.\n if (!this.modelSchemas[name]) {\n if (!schema && name in SchemaDefaults) {\n schema = SchemaDefaults[name];\n }\n\n if (schema) {\n // cache it so we only apply plugins once\n this.modelSchemas[name] = schema;\n this._applyPlugins(schema);\n } else {\n throw new mongoose.Error.MissingSchemaError(name);\n }\n }\n\n var model;\n var sub;\n\n // connection.model() may be passing a different schema for\n // an existing model name. in this case don't read from cache.\n if (this.models[name] && false !== options.cache) {\n if (schema instanceof Schema && schema != this.models[name].schema) {\n throw new mongoose.Error.OverwriteModelError(name);\n }\n\n if (collection) {\n // subclass current model with alternate collection\n model = this.models[name];\n schema = model.prototype.schema;\n sub = model.__subclass(this.connection, schema, collection);\n // do not cache the sub model\n return sub;\n }\n\n return this.models[name];\n }\n\n // ensure a schema exists\n if (!schema) {\n schema = this.modelSchemas[name];\n if (!schema) {\n throw new mongoose.Error.MissingSchemaError(name);\n }\n }\n\n if (!collection) {\n collection = schema.get('collection') || format(name);\n }\n\n var connection = options.connection || this.connection;\n model = Model.compile(name, schema, collection, connection, this);\n\n if (!skipInit) {\n model.init();\n }\n\n if (false === options.cache) {\n return model;\n }\n\n return this.models[name] = model;\n}", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "model", + "string": "Mongoose.prototype.model()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns an array of model names created on this instance of Mongoose.

    \n\n

    Note:

    \n\n

    Does not include names of models created using connection.model().

    ", + "summary": "

    Returns an array of model names created on this instance of Mongoose.

    ", + "body": "

    Note:

    \n\n

    Does not include names of models created using connection.model().

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.modelNames = function () {\n var names = Object.keys(this.models);\n return names;\n}", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "modelNames", + "string": "Mongoose.prototype.modelNames()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies global plugins to schema.

    ", + "summary": "

    Applies global plugins to schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mongoose.prototype._applyPlugins = function (schema) {\n for (var i = 0, l = this.plugins.length; i < l; i++) {\n schema.plugin(this.plugins[i][0], this.plugins[i][1]);\n }\n}", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "_applyPlugins", + "string": "Mongoose.prototype._applyPlugins()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "plugin callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "optional options" + }, + { + "type": "return", + "types": [ + "Mongoose" + ], + "description": "this" + }, + { + "type": "see", + "local": "plugins ./plugins.html", + "visibility": "plugins" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a global plugin executed on all Schemas.

    \n\n

    Equivalent to calling .plugin(fn) on each Schema you create.

    ", + "summary": "

    Declares a global plugin executed on all Schemas.

    ", + "body": "

    Equivalent to calling .plugin(fn) on each Schema you create.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.plugin = function (fn, opts) {\n this.plugins.push([fn, opts]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Mongoose", + "name": "plugin", + "string": "Mongoose.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "connection" + }, + { + "type": "return", + "types": [ + "Connection" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The default connection of the mongoose module.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    ", + "summary": "

    The default connection of the mongoose module.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nmongoose.connect(...);\nmongoose.connection.on('error', cb);\n
    \n\n

    This is the connection used by default for every model created using mongoose.model.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.__defineGetter__('connection', function(){\n return this.connections[0];\n});" + }, + { + "tags": [], + "description": { + "full": "

    Driver depentend APIs

    ", + "summary": "

    Driver depentend APIs

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Connection

    ", + "summary": "

    Connection

    ", + "body": "" + }, + "ignore": true, + "code": "var Connection = require(driver + '/connection');", + "ctx": { + "type": "declaration", + "name": "Connection", + "value": "require(driver + '/connection')", + "string": "Connection" + } + }, + { + "tags": [], + "description": { + "full": "

    Collection

    ", + "summary": "

    Collection

    ", + "body": "" + }, + "ignore": true, + "code": "var Collection = require(driver + '/collection');", + "ctx": { + "type": "declaration", + "name": "Collection", + "value": "require(driver + '/collection')", + "string": "Collection" + } + }, + { + "tags": [ + { + "type": "method", + "string": "Collection" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Collection constructor

    ", + "summary": "

    The Mongoose Collection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Collection = Collection;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Collection", + "value": "Collection", + "string": "Mongoose.prototypeCollection" + } + }, + { + "tags": [ + { + "type": "method", + "string": "Connection" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Connection constructor

    ", + "summary": "

    The Mongoose Connection constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Connection = Connection;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Connection", + "value": "Connection", + "string": "Mongoose.prototypeConnection" + } + }, + { + "tags": [ + { + "type": "property", + "string": "version" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose version

    ", + "summary": "

    The Mongoose version

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.version = require(__dirname + '/../package.json').version;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "version", + "value": "require(__dirname + '/../package.json').version", + "string": "Mongoose.prototypeversion" + } + }, + { + "tags": [ + { + "type": "method", + "string": "Mongoose" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose constructor

    \n\n

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    ", + "summary": "

    The Mongoose constructor

    ", + "body": "

    The exports of the mongoose module is an instance of this class.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar mongoose2 = new mongoose.Mongoose();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Mongoose = Mongoose;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Mongoose", + "value": "Mongoose", + "string": "Mongoose.prototypeMongoose" + } + }, + { + "tags": [ + { + "type": "method", + "string": "Schema" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Schema constructor

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    ", + "summary": "

    The Mongoose Schema constructor

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar CatSchema = new Schema(..);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Schema = Schema;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Schema", + "value": "Schema", + "string": "Mongoose.prototypeSchema" + } + }, + { + "tags": [ + { + "type": "method", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose SchemaType constructor.

    ", + "summary": "

    The Mongoose SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.SchemaType = SchemaType;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "SchemaType", + "value": "SchemaType", + "string": "Mongoose.prototypeSchemaType" + } + }, + { + "tags": [ + { + "type": "property", + "string": "SchemaTypes" + }, + { + "type": "see", + "local": "Schema.SchemaTypes #schema_Schema.Types", + "visibility": "Schema.SchemaTypes" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose SchemaTypes.

    \n\n

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    ", + "summary": "

    The various Mongoose SchemaTypes.

    ", + "body": "

    Note:

    \n\n

    Alias of mongoose.Schema.Types for backwards compatibility.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.SchemaTypes = Schema.Types;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "SchemaTypes", + "value": "Schema.Types", + "string": "Mongoose.prototypeSchemaTypes" + } + }, + { + "tags": [ + { + "type": "method", + "string": "VirtualType" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose VirtualType constructor.

    ", + "summary": "

    The Mongoose VirtualType constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.VirtualType = VirtualType;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "VirtualType", + "value": "VirtualType", + "string": "Mongoose.prototypeVirtualType" + } + }, + { + "tags": [ + { + "type": "property", + "string": "Types" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various Mongoose Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    ", + "summary": "

    The various Mongoose Types.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar array = mongoose.Types.Array;\n
    \n\n

    Types:

    \n\n
      \n
    • Array
    • \n
    • Buffer
    • \n
    • Document
    • \n
    • Embedded
    • \n
    • DocumentArray
    • \n
    • ObjectId
    • \n
    \n\n

    Using this exposed access to the ObjectId type, we can construct ids on demand.

    \n\n
    var ObjectId = mongoose.Types.ObjectId;\nvar id1 = new ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Types = Types;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Types", + "value": "Types", + "string": "Mongoose.prototypeTypes" + } + }, + { + "tags": [ + { + "type": "method", + "string": "Query" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Query constructor.

    ", + "summary": "

    The Mongoose Query constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Query = Query;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Query", + "value": "Query", + "string": "Mongoose.prototypeQuery" + } + }, + { + "tags": [ + { + "type": "method", + "string": "Promise" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Promise constructor.

    ", + "summary": "

    The Mongoose Promise constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Promise = Promise;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Promise", + "value": "Promise", + "string": "Mongoose.prototypePromise" + } + }, + { + "tags": [ + { + "type": "method", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Model constructor.

    ", + "summary": "

    The Mongoose Model constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Model = Model;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Model", + "value": "Model", + "string": "Mongoose.prototypeModel" + } + }, + { + "tags": [ + { + "type": "method", + "string": "Document" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The Mongoose Document constructor.

    ", + "summary": "

    The Mongoose Document constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Document = Document;", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Document", + "value": "Document", + "string": "Mongoose.prototypeDocument" + } + }, + { + "tags": [ + { + "type": "method", + "string": "Error" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The MongooseError constructor.

    ", + "summary": "

    The MongooseError constructor.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.Error = require('./error');", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "Error", + "value": "require('./error')", + "string": "Mongoose.prototypeError" + } + }, + { + "tags": [ + { + "type": "property", + "string": "mongo" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The node-mongodb-native driver Mongoose uses.

    ", + "summary": "

    The node-mongodb-native driver Mongoose uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Mongoose.prototype.mongo = require('mongodb');", + "ctx": { + "type": "property", + "constructor": "Mongoose", + "name": "mongo", + "value": "require('mongodb')", + "string": "Mongoose.prototypemongo" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The exports object is an instance of Mongoose.

    ", + "summary": "

    The exports object is an instance of Mongoose.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "var mongoose = module.exports = exports = new Mongoose;", + "ctx": { + "type": "declaration", + "name": "mongoose", + "value": "module.exports = exports = new Mongoose", + "string": "mongoose" + } + } +] +### lib/internal.js +[ + { + "tags": [], + "description": { + "full": "

    Dependencies

    ", + "summary": "

    Dependencies

    ", + "body": "" + }, + "ignore": false, + "code": "var StateMachine = require('./statemachine')\nvar ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')\n\nmodule.exports = exports = InternalCache;\n\nfunction InternalCache () {\n this.strictMode = undefined;\n this.selected = undefined;\n this.shardval = undefined;\n this.saveError = undefined;\n this.validationError = undefined;\n this.adhocPaths = undefined;\n this.removing = undefined;\n this.inserting = undefined;\n this.version = undefined;\n this.getters = {};\n this._id = undefined;\n this.populate = undefined;\n this.populated = undefined;\n this.scope = undefined;\n this.activePaths = new ActiveRoster;\n\n // embedded docs\n this.ownerDocument = undefined;\n this.fullPath = undefined;\n}", + "ctx": { + "type": "declaration", + "name": "StateMachine", + "value": "require('./statemachine')", + "string": "StateMachine" + } + } +] +### lib/model.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('./document')\n , MongooseArray = require('./types/array')\n , MongooseBuffer = require('./types/buffer')\n , MongooseError = require('./error')\n , VersionError = MongooseError.VersionError\n , DivergentArrayError = MongooseError.DivergentArrayError\n , Query = require('./query')\n , Schema = require('./schema')\n , Types = require('./schema/index')\n , utils = require('./utils')\n , hasOwnProperty = utils.object.hasOwnProperty\n , isMongooseObject = utils.isMongooseObject\n , EventEmitter = require('events').EventEmitter\n , merge = utils.merge\n , Promise = require('./promise')\n , assert = require('assert')\n , tick = utils.tick\n\nvar VERSION_WHERE = 1\n , VERSION_INC = 2\n , VERSION_ALL = VERSION_WHERE | VERSION_INC;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('./document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "values to with which to create the document" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "event", + "string": "`error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model." + }, + { + "type": "event", + "string": "`index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Model constructor

    ", + "summary": "

    Model constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function Model (doc, fields, skipId) {\n Document.call(this, doc, fields, skipId);\n};", + "ctx": { + "type": "function", + "name": "Model", + "string": "Model()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from Document.

    \n\n

    All Model.prototype features are available on
    top level (non-sub) documents.

    ", + "summary": "

    Inherits from Document.

    ", + "body": "

    All Model.prototype features are available on
    top level (non-sub) documents.

    " + }, + "ignore": true, + "code": "Model.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "Model", + "name": "__proto__", + "value": "Document.prototype", + "string": "Model.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "db" + } + ], + "description": { + "full": "

    Connection the model uses.

    ", + "summary": "

    Connection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.db;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "collection" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.collection;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "property", + "string": "modelName" + } + ], + "description": { + "full": "

    The name of the model

    ", + "summary": "

    The name of the model

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.modelName;" + }, + { + "tags": [], + "description": { + "full": "

    Handles doc.save() callbacks

    ", + "summary": "

    Handles doc.save() callbacks

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSave (promise, self) {\n return tick(function handleSave (err, result) {\n if (err) {\n // If the initial insert fails provide a second chance.\n // (If we did this all the time we would break updates)\n if (self.$__.inserting) {\n self.isNew = true;\n self.emit('isNew', true);\n }\n promise.error(err);\n promise = self = null;\n return;\n }\n\n self.$__storeShard();\n\n var numAffected;\n if (result) {\n // when inserting, the array of created docs is returned\n numAffected = result.length\n ? result.length\n : result;\n } else {\n numAffected = 0;\n }\n\n // was this an update that required a version bump?\n if (self.$__.version && !self.$__.inserting) {\n var doIncrement = VERSION_INC === (VERSION_INC & self.$__.version);\n self.$__.version = undefined;\n\n // increment version if was successful\n if (numAffected > 0) {\n if (doIncrement) {\n var key = self.schema.options.versionKey;\n var version = self.getValue(key) | 0;\n self.setValue(key, version + 1);\n }\n } else {\n // the update failed. pass an error back\n promise.error(new VersionError);\n promise = self = null;\n return;\n }\n }\n\n self.emit('save', self, numAffected);\n promise.complete(self, numAffected);\n promise = self = null;\n });\n}", + "ctx": { + "type": "function", + "name": "handleSave", + "string": "handleSave()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "title": "middleware", + "url": "http://mongoosejs.com/docs/middleware.html", + "visibility": "http://mongoosejs.com/docs/middleware.html" + } + ], + "description": { + "full": "

    Saves this document.

    \n\n

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    ", + "summary": "

    Saves this document.

    ", + "body": "

    Example:

    \n\n
    product.sold = Date.now();\nproduct.save(function (err, product) {\n  if (err) ..\n})\n
    \n\n

    The fn callback is optional. If no fn is passed and validation fails, the validation error will be emitted on the connection used to create this model.

    \n\n
    var db = mongoose.createConnection(..);\nvar schema = new Schema(..);\nvar Product = db.model('Product', schema);\n\ndb.on('error', handleError);\n
    \n\n

    However, if you desire more local error handling you can add an error listener to the model and handle errors there instead.

    \n\n
    Product.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.save = function save (fn) {\n var promise = new Promise(fn)\n , complete = handleSave(promise, this)\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n if (this.isNew) {\n // send entire doc\n var obj = this.toObject({ depopulate: 1 });\n this.$__version(true, obj);\n this.collection.insert(obj, options, complete);\n this.$__reset();\n this.isNew = false;\n this.emit('isNew', false);\n // Make it possible to retry the insert\n this.$__.inserting = true;\n\n } else {\n // Make sure we don't treat it as a new object on error,\n // since it already exists\n this.$__.inserting = false;\n\n var delta = this.$__delta();\n if (delta) {\n if (delta instanceof Error) return complete(delta);\n var where = this.$__where(delta[0]);\n this.$__reset();\n this.collection.update(where, delta[1], options, complete);\n } else {\n this.$__reset();\n complete(null);\n }\n\n this.emit('isNew', false);\n }\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "save", + "string": "Model.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Mixed" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[operation]", + "description": "" + } + ], + "description": { + "full": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "summary": "

    Apply the operation to the delta (update) clause as
    well as track versioning for our where clause.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function operand (self, where, delta, data, val, op) {\n // delta\n op || (op = '$set');\n if (!delta[op]) delta[op] = {};\n delta[op][data.path] = val;\n\n // disabled versioning?\n if (false === self.schema.options.versionKey) return;\n\n // already marked for versioning?\n if (VERSION_ALL === (VERSION_ALL & self.$__.version)) return;\n\n switch (op) {\n case '$set':\n case '$unset':\n case '$pop':\n case '$pull':\n case '$pullAll':\n case '$push':\n case '$pushAll':\n case '$addToSet':\n break;\n default:\n // nothing to do\n return;\n }\n\n // ensure updates sent with positional notation are\n // editing the correct array element.\n // only increment the version if an array position changes.\n // modifying elements of an array is ok if position does not change.\n\n if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {\n self.$__.version = VERSION_INC;\n }\n else if (/^\\$p/.test(op)) {\n // potentially changing array positions\n self.increment();\n }\n else if (Array.isArray(val)) {\n // $set an array\n self.increment();\n }\n // now handling $set, $unset\n else if (/\\.\\d+/.test(data.path)) {\n // subpath of array\n self.$__.version = VERSION_WHERE;\n }\n}", + "ctx": { + "type": "function", + "name": "operand", + "string": "operand()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "where", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "delta", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "data", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "value", + "description": "" + } + ], + "description": { + "full": "

    Compiles an update and where clause for a val with _atomics.

    ", + "summary": "

    Compiles an update and where clause for a val with _atomics.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function handleAtomics (self, where, delta, data, value) {\n if (delta.$set && delta.$set[data.path]) {\n // $set has precedence over other atomics\n return;\n }\n\n if ('function' == typeof value.$__getAtomics) {\n value.$__getAtomics().forEach(function (atomic) {\n var op = atomic[0];\n var val = atomic[1];\n operand(self, where, delta, data, val, op);\n })\n return;\n }\n\n // legacy support for plugins\n\n var atomics = value._atomics\n , ops = Object.keys(atomics)\n , i = ops.length\n , val\n , op;\n\n if (0 === i) {\n // $set\n\n if (isMongooseObject(value)) {\n value = value.toObject({ depopulate: 1 });\n } else if (value.valueOf) {\n value = value.valueOf();\n }\n\n return operand(self, where, delta, data, value);\n }\n\n while (i--) {\n op = ops[i];\n val = atomics[op];\n\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 })\n } else if (Array.isArray(val)) {\n val = val.map(function (mem) {\n return isMongooseObject(mem)\n ? mem.toObject({ depopulate: 1 })\n : mem;\n })\n } else if (val.valueOf) {\n val = val.valueOf()\n }\n\n if ('$addToSet' === op)\n val = { $each: val };\n\n operand(self, where, delta, data, val, op);\n }\n}", + "ctx": { + "type": "function", + "name": "handleAtomics", + "string": "handleAtomics()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__delta" + }, + { + "type": "memberOf", + "parent": "Model" + } + ], + "description": { + "full": "

    Produces a special query document of the modified properties used in updates.

    ", + "summary": "

    Produces a special query document of the modified properties used in updates.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype.$__delta = function () {\n var dirty = this.$__dirty();\n if (!dirty.length) return;\n\n var where = {}\n , delta = {}\n , len = dirty.length\n , divergent = []\n , d = 0\n , val\n , obj\n\n for (; d < len; ++d) {\n var data = dirty[d]\n var value = data.value\n var schema = data.schema\n\n var match = checkDivergentArray(this, data.path, value);\n if (match) {\n divergent.push(match);\n continue;\n }\n\n if (divergent.length) continue;\n\n if (undefined === value) {\n operand(this, where, delta, data, 1, '$unset');\n\n } else if (null === value) {\n operand(this, where, delta, data, null);\n\n } else if (value._path && value._atomics) {\n // arrays and other custom types (support plugins etc)\n handleAtomics(this, where, delta, data, value);\n\n } else if (value._path && Buffer.isBuffer(value)) {\n // MongooseBuffer\n value = value.toObject();\n operand(this, where, delta, data, value);\n\n } else {\n value = utils.clone(value, { convertToId: 1 });\n operand(this, where, delta, data, value);\n }\n }\n\n if (divergent.length) {\n return new DivergentArrayError(divergent);\n }\n\n if (this.$__.version) {\n this.$__version(where, delta);\n }\n\n return [where, delta];\n}" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "https://github.com/LearnBoost/mongoose/issues/1334", + "visibility": "https://github.com/LearnBoost/mongoose/issues/1334" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "String", + "undefined" + ], + "description": "" + } + ], + "description": { + "full": "

    Determine if array was populated with some form of filter and is now
    being updated in a manner which could overwrite data unintentionally.

    ", + "summary": "

    Determine if array was populated with some form of filter and is now
    being updated in a manner which could overwrite data unintentionally.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function checkDivergentArray (doc, path, array) {\n // see if we populated this path\n var pop = doc.populated(path, true);\n\n if (!pop && doc.$__.selected) {\n // If any array was selected using an $elemMatch projection, we deny the update.\n // NOTE: MongoDB only supports projected $elemMatch on top level array.\n var top = path.split('.')[0];\n if (doc.$__.selected[top] && doc.$__.selected[top].$elemMatch) {\n return top;\n }\n }\n\n if (!(pop && array instanceof MongooseArray)) return;\n\n // If the array was populated using options that prevented all\n // documents from being returned (match, skip, limit) or they\n // deselected the _id field, $pop and $set of the array are\n // not safe operations. If _id was deselected, we do not know\n // how to remove elements. $pop will pop off the _id from the end\n // of the array in the db which is not guaranteed to be the\n // same as the last element we have here. $set of the entire array\n // would be similarily destructive as we never received all\n // elements of the array and potentially would overwrite data.\n var check = pop.options.match ||\n pop.options.options && hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted\n pop.options.options && pop.options.options.skip || // 0 is permitted\n pop.options.select && // deselected _id?\n (0 === pop.options.select._id ||\n /\\s?-_id\\s?/.test(pop.options.select))\n\n if (check) {\n var atomics = array._atomics;\n if (0 === Object.keys(atomics).length || atomics.$set || atomics.$pop) {\n return path;\n }\n }\n}", + "ctx": { + "type": "function", + "name": "checkDivergentArray", + "string": "checkDivergentArray()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__version" + }, + { + "type": "memberOf", + "parent": "Model" + } + ], + "description": { + "full": "

    Appends versioning to the where and update clauses.

    ", + "summary": "

    Appends versioning to the where and update clauses.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype.$__version = function (where, delta) {\n var key = this.schema.options.versionKey;\n\n if (true === where) {\n // this is an insert\n if (key) this.setValue(key, delta[key] = 0);\n return;\n }\n\n // updates\n\n // only apply versioning if our versionKey was selected. else\n // there is no way to select the correct version. we could fail\n // fast here and force them to include the versionKey but\n // thats a bit intrusive. can we do this automatically?\n if (!this.isSelected(key)) {\n return;\n }\n\n // $push $addToSet don't need the where clause set\n if (VERSION_WHERE === (VERSION_WHERE & this.$__.version)) {\n where[key] = this.getValue(key);\n }\n\n if (VERSION_INC === (VERSION_INC & this.$__.version)) {\n delta.$inc || (delta.$inc = {});\n delta.$inc[key] = 1;\n }\n}" + }, + { + "tags": [ + { + "type": "see", + "title": "versionKeys", + "url": "http://mongoosejs.com/docs/guide.html#versionKey", + "visibility": "http://mongoosejs.com/docs/guide.html#versionKey" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Signal that we desire an increment of this documents version.

    ", + "summary": "

    Signal that we desire an increment of this documents version.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.increment = function increment () {\n this.$__.version = VERSION_ALL;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "increment", + "string": "Model.prototype.increment()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__where" + }, + { + "type": "memberOf", + "parent": "Model" + } + ], + "description": { + "full": "

    Returns a query object which applies shardkeys if they exist.

    ", + "summary": "

    Returns a query object which applies shardkeys if they exist.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.prototype.$__where = function _where (where) {\n where || (where = {});\n\n var paths\n , len\n\n if (this.$__.shardval) {\n paths = Object.keys(this.$__.shardval)\n len = paths.length\n\n for (var i = 0; i < len; ++i) {\n where[paths[i]] = this.$__.shardval[paths[i]];\n }\n }\n\n where._id = this._doc._id;\n return where;\n}" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes this document from the db.

    \n\n

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    ", + "summary": "

    Removes this document from the db.

    ", + "body": "

    Example:

    \n\n
    product.remove(function (err, product) {\n  if (err) return handleError(err);\n  Product.findById(product._id, function (err, product) {\n    console.log(product) // null\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.remove = function remove (fn) {\n if (this.$__.removing) {\n this.$__.removing.addBack(fn);\n return this;\n }\n\n var promise = this.$__.removing = new Promise(fn)\n , where = this.$__where()\n , self = this\n , options = {}\n\n if (this.schema.options.safe) {\n options.safe = this.schema.options.safe;\n }\n\n this.collection.remove(where, options, tick(function (err) {\n if (err) {\n promise.error(err);\n promise = self = self.$__.removing = where = options = null;\n return;\n }\n self.emit('remove', self);\n promise.complete();\n promise = self = where = options = null;\n }));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "remove", + "string": "Model.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns another Model instance.

    \n\n

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    ", + "summary": "

    Returns another Model instance.

    ", + "body": "

    Example:

    \n\n
    var doc = new Tank;\ndoc.model('User').findById(id, callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.prototype.model = function model (name) {\n return this.db.model(name);\n};\n\n// Model (class) features", + "ctx": { + "type": "method", + "constructor": "Model", + "name": "model", + "string": "Model.prototype.model()" + } + }, + { + "tags": [], + "description": { + "full": "

    Give the constructor the ability to emit events.

    ", + "summary": "

    Give the constructor the ability to emit events.

    ", + "body": "" + }, + "ignore": true, + "code": "for (var i in EventEmitter.prototype)\n Model[i] = EventEmitter.prototype[i];" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Called when the model compiles.

    ", + "summary": "

    Called when the model compiles.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model.init = function init () {\n if (this.schema.options.autoIndex) {\n this.ensureIndexes();\n }\n\n this.schema.emit('init', this);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "init", + "string": "Model.init()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[cb]", + "description": "optional callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    \n\n

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    Example:

    \n\n
    var eventSchema = new Schema({ thing: { type: 'string', unique: true }})\nvar Event = mongoose.model('Event', eventSchema);\n\nEvent.on('index', function (err) {\n  if (err) console.error(err); // error occurred during index creation\n})\n
    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    The ensureIndex commands are not sent in parallel. This is to avoid the MongoError: cannot add index with a background operation in progress error. See this ticket for more information.

    ", + "summary": "

    Sends ensureIndex commands to mongo for each index declared in the schema.

    ", + "body": "

    Example:

    \n\n
    Event.ensureIndexes(function (err) {\n  if (err) return handleError(err);\n});\n
    \n\n

    After completion, an index event is emitted on this Model passing an error if one occurred.

    \n\n

    Example:

    \n\n
    var eventSchema = new Schema({ thing: { type: 'string', unique: true }})\nvar Event = mongoose.model('Event', eventSchema);\n\nEvent.on('index', function (err) {\n  if (err) console.error(err); // error occurred during index creation\n})\n
    \n\n

    NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution.

    \n\n

    The ensureIndex commands are not sent in parallel. This is to avoid the MongoError: cannot add index with a background operation in progress error. See this ticket for more information.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.ensureIndexes = function ensureIndexes (cb) {\n var indexes = this.schema.indexes();\n if (!indexes.length) {\n return cb && process.nextTick(cb);\n }\n\n // Indexes are created one-by-one to support how MongoDB < 2.4 deals\n // with background indexes.\n\n var self = this\n , safe = self.schema.options.safe\n\n function done (err) {\n self.emit('index', err);\n cb && cb(err);\n }\n\n function create () {\n var index = indexes.shift();\n if (!index) return done();\n\n var options = index[1];\n options.safe = safe;\n self.collection.ensureIndex(index[0], options, tick(function (err) {\n if (err) return done(err);\n create();\n }));\n }\n\n create();\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "ensureIndexes", + "string": "Model.ensureIndexes()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "schema" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema the model uses.

    ", + "summary": "

    Schema the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.schema;" + }, + { + "tags": [ + { + "type": "property", + "string": "db" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Connection instance the model uses.

    ", + "summary": "

    Connection instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.db;" + }, + { + "tags": [ + { + "type": "property", + "string": "collection" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Collection the model uses.

    ", + "summary": "

    Collection the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.collection;" + }, + { + "tags": [ + { + "type": "property", + "string": "base" + }, + { + "type": "receiver", + "string": "Model" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Base Mongoose instance the model uses.

    ", + "summary": "

    Base Mongoose instance the model uses.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.base;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes documents from the collection.

    \n\n

    Example:

    \n\n
    Comment.remove({ title: 'baby born from alien father' }, function (err) {\n\n});\n
    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    var query = Comment.remove({ _id: id });\nquery.exec();\n
    \n\n

    Note:

    \n\n

    This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, no middleware (hooks) are executed.

    ", + "summary": "

    Removes documents from the collection.

    ", + "body": "

    Example:

    \n\n
    Comment.remove({ title: 'baby born from alien father' }, function (err) {\n\n});\n
    \n\n

    Note:

    \n\n

    To remove documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    var query = Comment.remove({ _id: id });\nquery.exec();\n
    \n\n

    Note:

    \n\n

    This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, no middleware (hooks) are executed.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.remove = function remove (conditions, callback) {\n if ('function' === typeof conditions) {\n callback = conditions;\n conditions = {};\n }\n\n var query = new Query(conditions).bind(this, 'remove');\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.remove(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "remove", + "string": "Model.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "see", + "local": "promise #promise-js", + "visibility": "promise" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Examples:

    \n\n
    // named john and at least 18\nMyModel.find({ name: 'john', age: { $gte: 18 }});\n\n// executes immediately, passing results to callback\nMyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});\n\n// name LIKE john and only selecting the \"name\" and \"friends\" fields, executing immediately\nMyModel.find({ name: /john/i }, 'name friends', function (err, docs) { })\n\n// passing options\nMyModel.find({ name: /john/i }, null, { skip: 10 })\n\n// passing options and executing immediately\nMyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {});\n\n// executing a query explicitly\nvar query = MyModel.find({ name: /john/i }, null, { skip: 10 })\nquery.exec(function (err, docs) {});\n\n// using the promise returned from executing a query\nvar query = MyModel.find({ name: /john/i }, null, { skip: 10 });\nvar promise = query.exec();\npromise.addBack(function (err, docs) {});\n
    ", + "summary": "

    Finds documents

    ", + "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Examples:

    \n\n
    // named john and at least 18\nMyModel.find({ name: 'john', age: { $gte: 18 }});\n\n// executes immediately, passing results to callback\nMyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});\n\n// name LIKE john and only selecting the \"name\" and \"friends\" fields, executing immediately\nMyModel.find({ name: /john/i }, 'name friends', function (err, docs) { })\n\n// passing options\nMyModel.find({ name: /john/i }, null, { skip: 10 })\n\n// passing options and executing immediately\nMyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {});\n\n// executing a query explicitly\nvar query = MyModel.find({ name: /john/i }, null, { skip: 10 })\nquery.exec(function (err, docs) {});\n\n// using the promise returned from executing a query\nvar query = MyModel.find({ name: /john/i }, null, { skip: 10 });\nvar promise = query.exec();\npromise.addBack(function (err, docs) {});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.find = function find (conditions, fields, options, callback) {\n if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n\n var query = new Query(conditions, options);\n query.bind(this, 'find');\n query.select(fields);\n\n if ('undefined' === typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.find(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "find", + "string": "Model.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges the current named scope query into query.

    ", + "summary": "

    Merges the current named scope query into query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model._applyNamedScope = function _applyNamedScope (query) {\n var cQuery = this._cumulativeQuery;\n\n if (cQuery) {\n merge(query._conditions, cQuery._conditions);\n if (query._fields && cQuery._fields)\n merge(query._fields, cQuery._fields);\n if (query.options && cQuery.options)\n merge(query.options, cQuery.options);\n delete this._cumulativeQuery;\n }\n\n return query;\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "_applyNamedScope", + "string": "Model._applyNamedScope()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "objectid, or a value that can be casted to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "see", + "local": "lean queries #query_Query-lean", + "visibility": "lean" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds a single document by id.

    \n\n

    The id is cast based on the Schema before sending the command.

    \n\n

    Example:

    \n\n
    // find adventure by id and execute immediately\nAdventure.findById(id, function (err, adventure) {});\n\n// same as above\nAdventure.findById(id).exec(callback);\n\n// select only the adventures name and length\nAdventure.findById(id, 'name length', function (err, adventure) {});\n\n// same as above\nAdventure.findById(id, 'name length').exec(callback);\n\n// include all properties except for `length`\nAdventure.findById(id, '-length').exec(function (err, adventure) {});\n\n// passing options (in this case return the raw js objects, not mongoose documents by passing `lean`\nAdventure.findById(id, 'name', { lean: true }, function (err, doc) {});\n\n// same as above\nAdventure.findById(id, 'name').lean().exec(function (err, doc) {});\n
    ", + "summary": "

    Finds a single document by id.

    ", + "body": "

    The id is cast based on the Schema before sending the command.

    \n\n

    Example:

    \n\n
    // find adventure by id and execute immediately\nAdventure.findById(id, function (err, adventure) {});\n\n// same as above\nAdventure.findById(id).exec(callback);\n\n// select only the adventures name and length\nAdventure.findById(id, 'name length', function (err, adventure) {});\n\n// same as above\nAdventure.findById(id, 'name length').exec(callback);\n\n// include all properties except for `length`\nAdventure.findById(id, '-length').exec(function (err, adventure) {});\n\n// passing options (in this case return the raw js objects, not mongoose documents by passing `lean`\nAdventure.findById(id, 'name', { lean: true }, function (err, doc) {});\n\n// same as above\nAdventure.findById(id, 'name').lean().exec(function (err, doc) {});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findById = function findById (id, fields, options, callback) {\n return this.findOne({ _id: id }, fields, options, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findById", + "string": "Model.findById()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[fields]", + "description": "optional fields to select" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "field selection #query_Query-select", + "visibility": "field" + }, + { + "type": "see", + "local": "lean queries #query_Query-lean", + "visibility": "lean" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds one document.

    \n\n

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    // find one iphone adventures - iphone adventures??\nAdventure.findOne({ type: 'iphone' }, function (err, adventure) {});\n\n// same as above\nAdventure.findOne({ type: 'iphone' }).exec(function (err, adventure) {});\n\n// select only the adventures name\nAdventure.findOne({ type: 'iphone' }, 'name', function (err, adventure) {});\n\n// same as above\nAdventure.findOne({ type: 'iphone' }, 'name').exec(function (err, adventure) {});\n\n// specify options, in this case lean\nAdventure.findOne({ type: 'iphone' }, 'name', { lean: true }, callback);\n\n// same as above\nAdventure.findOne({ type: 'iphone' }, 'name', { lean: true }).exec(callback);\n\n// chaining findOne queries (same as above)\nAdventure.findOne({ type: 'iphone' }).select('name').lean().exec(callback);\n
    ", + "summary": "

    Finds one document.

    ", + "body": "

    The conditions are cast to their respective SchemaTypes before the command is sent.

    \n\n

    Example:

    \n\n
    // find one iphone adventures - iphone adventures??\nAdventure.findOne({ type: 'iphone' }, function (err, adventure) {});\n\n// same as above\nAdventure.findOne({ type: 'iphone' }).exec(function (err, adventure) {});\n\n// select only the adventures name\nAdventure.findOne({ type: 'iphone' }, 'name', function (err, adventure) {});\n\n// same as above\nAdventure.findOne({ type: 'iphone' }, 'name').exec(function (err, adventure) {});\n\n// specify options, in this case lean\nAdventure.findOne({ type: 'iphone' }, 'name', { lean: true }, callback);\n\n// same as above\nAdventure.findOne({ type: 'iphone' }, 'name', { lean: true }).exec(callback);\n\n// chaining findOne queries (same as above)\nAdventure.findOne({ type: 'iphone' }).select('name').lean().exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOne = function findOne (conditions, fields, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n } else if ('function' == typeof fields) {\n callback = fields;\n fields = null;\n options = null;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = {};\n fields = null;\n options = null;\n }\n\n var query = new Query(conditions, options).select(fields).bind(this, 'findOne');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOne(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOne", + "string": "Model.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Counts number of matching documents in a database collection.

    \n\n

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    ", + "summary": "

    Counts number of matching documents in a database collection.

    ", + "body": "

    Example:

    \n\n
    Adventure.count({ type: 'jungle' }, function (err, count) {\n  if (err) ..\n  console.log('there are %d jungle adventures', count);\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.count = function count (conditions, callback) {\n if ('function' === typeof conditions)\n callback = conditions, conditions = {};\n\n var query = new Query(conditions).bind(this, 'count');\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.count(callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "count", + "string": "Model.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "optional" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a DISTINCT command

    ", + "summary": "

    Executes a DISTINCT command

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Model.distinct = function distinct (field, conditions, callback) {\n var query = new Query(conditions).bind(this, 'distinct');\n if ('undefined' == typeof callback) {\n query._distinctArg = field;\n return query;\n }\n\n this._applyNamedScope(query);\n return query.distinct(field, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "distinct", + "string": "Model.distinct()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "optional value" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query, applies the passed conditions, and returns the Query.

    \n\n

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    ", + "summary": "

    Creates a Query, applies the passed conditions, and returns the Query.

    ", + "body": "

    For example, instead of writing:

    \n\n
    User.find({age: {$gte: 21, $lte: 65}}, callback);\n
    \n\n

    we can instead write:

    \n\n
    User.where('age').gte(21).lte(65).exec(callback);\n
    \n\n

    Since the Query class also supports where you can continue chaining

    \n\n
    User\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n... etc\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.where = function where (path, val) {\n var q = new Query().bind(this, 'find');\n return q.where.apply(q, arguments);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "where", + "string": "Model.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "argument", + "description": "is a javascript string or anonymous function" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "memberOf", + "parent": "Model" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Query.$where #query_Query-%24where", + "visibility": "Query.$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a Query and specifies a $where condition.

    \n\n

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5').exec(function (err, docs) {});\n
    ", + "summary": "

    Creates a Query and specifies a $where condition.

    ", + "body": "

    Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({ $where: javascript }), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

    \n\n
    Blog.$where('this.comments.length > 5').exec(function (err, docs) {});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.$where = function $where () {\n var q = new Query().bind(this, 'find');\n return q.$where.apply(q, arguments);\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndUpdate(conditions, update, options, callback) // executes\nA.findOneAndUpdate(conditions, update, options)  // returns Query\nA.findOneAndUpdate(conditions, update, callback) // executes\nA.findOneAndUpdate(conditions, update)           // returns Query\nA.findOneAndUpdate()                             // returns Query\n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndUpdate = function (conditions, update, options, callback) {\n if ('function' == typeof options) {\n callback = options;\n options = null;\n }\n else if (1 === arguments.length) {\n if ('function' == typeof conditions) {\n var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate(update)\\n'\n + ' ' + this.modelName + '.findOneAndUpdate()\\n';\n throw new TypeError(msg)\n }\n update = conditions;\n conditions = undefined;\n }\n\n var fields;\n if (options && options.fields) {\n fields = options.fields;\n options.fields = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndUpdate', update);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndUpdate(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndUpdate", + "string": "Model.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexId" + ], + "name": "id", + "description": "an ObjectId or string that can be cast to one." + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[update]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndUpdate #model_Model.findOneAndUpdate", + "visibility": "Model.findOneAndUpdate" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command by a documents id.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Issues a mongodb findAndModify update command by a documents id.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndUpdate(id, update, options, callback) // executes\nA.findByIdAndUpdate(id, update, options)  // returns Query\nA.findByIdAndUpdate(id, update, callback) // executes\nA.findByIdAndUpdate(id, update)           // returns Query\nA.findByIdAndUpdate()                     // returns Query\n
    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Note:

    \n\n

    All top level update keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting your document with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    Although values are cast to their appropriate types when using the findAndModify helpers, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findById(id, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndUpdate = function (id, update, options, callback) {\n var args;\n\n if (1 === arguments.length) {\n if ('function' == typeof id) {\n var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate(id)\\n'\n + ' ' + this.modelName + '.findByIdAndUpdate()\\n';\n throw new TypeError(msg)\n }\n return this.findOneAndUpdate({_id: id }, undefined);\n }\n\n args = utils.args(arguments, 1);\n args.unshift({ _id: id });\n return this.findOneAndUpdate.apply(this, args);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndUpdate", + "string": "Model.findByIdAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findOneAndRemove(conditions, options, callback) // executes\nA.findOneAndRemove(conditions, options)  // return Query\nA.findOneAndRemove(conditions, callback) // executes\nA.findOneAndRemove(conditions) // returns Query\nA.findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findOneAndRemove = function (conditions, options, callback) {\n if (1 === arguments.length && 'function' == typeof conditions) {\n var msg = 'Model.findOneAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\\n'\n + ' ' + this.modelName + '.findOneAndRemove(conditions)\\n'\n + ' ' + this.modelName + '.findOneAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n }\n\n var fields;\n if (options) {\n fields = options.select;\n options.select = undefined;\n }\n\n var query = new Query(conditions);\n query.setOptions(options);\n query.select(fields);\n query.bind(this, 'findOneAndRemove');\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.findOneAndRemove(callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findOneAndRemove", + "string": "Model.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "id", + "description": "ObjectId or string that can be cast to one" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "see", + "local": "Model.findOneAndRemove #model_Model.findOneAndRemove", + "visibility": "Model.findOneAndRemove" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + } + ], + "description": { + "full": "

    Issue a mongodb findAndModify remove command by a documents id.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    ", + "summary": "

    Issue a mongodb findAndModify remove command by a documents id.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback.

    \n\n

    Executes immediately if callback is passed, else a Query object is returned.

    \n\n

    Options:

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    • select: sets the document fields to return
    • \n
    \n\n

    Examples:

    \n\n
    A.findByIdAndRemove(id, options, callback) // executes\nA.findByIdAndRemove(id, options)  // return Query\nA.findByIdAndRemove(id, callback) // executes\nA.findByIdAndRemove(id) // returns Query\nA.findByIdAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.findByIdAndRemove = function (id, options, callback) {\n if (1 === arguments.length && 'function' == typeof id) {\n var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\\n\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove(id)\\n'\n + ' ' + this.modelName + '.findByIdAndRemove()\\n';\n throw new TypeError(msg)\n }\n\n return this.findOneAndRemove({ _id: id }, options, callback);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "findByIdAndRemove", + "string": "Model.findByIdAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array", + "Object..." + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    \n\n

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    ", + "summary": "

    Shortcut for creating a new Document that is automatically saved to the db if valid.

    ", + "body": "

    Example:

    \n\n
    Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n\nvar array = [{ type: 'jelly bean' }, { type: 'snickers' }];\nCandy.create(array, function (err, jellybean, snickers) {\n  if (err) // ...\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.create = function create (doc, fn) {\n if (1 === arguments.length) {\n return 'function' === typeof doc && doc(null);\n }\n\n var self = this\n , docs = [null]\n , promise\n , count\n , args\n\n if (Array.isArray(doc)) {\n args = doc;\n } else {\n args = utils.args(arguments, 0, arguments.length - 1);\n fn = arguments[arguments.length - 1];\n }\n\n if (0 === args.length) return fn(null);\n\n promise = new Promise(fn);\n count = args.length;\n\n args.forEach(function (arg, i) {\n var doc = new self(arg);\n docs[i+1] = doc;\n doc.save(function (err) {\n if (err) return promise.error(err);\n --count || fn.apply(null, docs);\n });\n });\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "create", + "string": "Model.create()" + } + }, + { + "tags": [ + { + "type": "see", + "title": "strict", + "url": "schemas http://mongoosejs.com/docs/guide.html#strict", + "visibility": "schemas" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "conditions", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "update", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Updates documents in the database without returning them.

    \n\n

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    • strict (boolean) overrides the strict option for this update
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    ", + "summary": "

    Updates documents in the database without returning them.

    ", + "body": "

    Examples:

    \n\n
    MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);\nMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {\n  if (err) return handleError(err);\n  console.log('The number of updated documents was %d', numberAffected);\n  console.log('The raw response from Mongo was ', raw);\n});\n
    \n\n

    Valid options:

    \n\n
      \n
    • safe (boolean) safe mode (defaults to value set in schema (true))
    • \n
    • upsert (boolean) whether to create the doc if it doesn't match (false)
    • \n
    • multi (boolean) whether multiple documents should be updated (false)
    • \n
    • strict (boolean) overrides the strict option for this update
    • \n
    \n\n

    All update values are cast to their appropriate SchemaTypes before being sent.

    \n\n

    The callback function receives (err, numberAffected, rawResponse).

    \n\n
      \n
    • err is the error if any occurred
    • \n
    • numberAffected is the count of updated documents Mongo reported
    • \n
    • rawResponse is the full response from Mongo
    • \n
    \n\n

    Note:

    \n\n

    All top level keys which are not atomic operation names are treated as set operations:

    \n\n

    Example:

    \n\n
    var query = { name: 'borne' };\nModel.update(query, { name: 'jason borne' }, options, callback)\n\n// is sent as\nModel.update(query, { $set: { name: 'jason borne' }}, options, callback)\n
    \n\n

    This helps prevent accidentally overwriting all documents in your collection with { name: 'jason borne' }.

    \n\n

    Note:

    \n\n

    To update documents without waiting for a response from MongoDB, do not pass a callback, then call exec on the returned Query:

    \n\n
    Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();\n
    \n\n

    Note:

    \n\n

    Although values are casted to their appropriate types when using update, the following are not applied:

    \n\n
      \n
    • defaults
    • \n
    • setters
    • \n
    • validators
    • \n
    • middleware
    • \n
    \n\n

    If you need those features, use the traditional approach of first retrieving the document.

    \n\n
    Model.findOne({ name: 'borne' }, function (err, doc) {\n  if (err) ..\n  doc.name = 'jason borne';\n  doc.save(callback);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.update = function update (conditions, doc, options, callback) {\n if (arguments.length < 4) {\n if ('function' === typeof options) {\n // Scenario: update(conditions, doc, callback)\n callback = options;\n options = null;\n } else if ('function' === typeof doc) {\n // Scenario: update(doc, callback);\n callback = doc;\n doc = conditions;\n conditions = {};\n options = null;\n }\n }\n\n var query = new Query(conditions, options).bind(this, 'update', doc);\n\n if ('undefined' == typeof callback)\n return query;\n\n this._applyNamedScope(query);\n return query.update(doc, callback);\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "update", + "string": "Model.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "o", + "description": "an object specifying map-reduce options" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/MapReduce", + "visibility": "http://www.mongodb.org/display/DOCS/MapReduce" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes a mapReduce command.

    \n\n

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    ", + "summary": "

    Executes a mapReduce command.

    ", + "body": "

    o is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\nUser.mapReduce(o, function (err, results) {\n  console.log(results)\n})\n
    \n\n

    Other options:

    \n\n
      \n
    • query {Object} query filter object.
    • \n
    • limit {Number} max number of documents
    • \n
    • keeptemp {Boolean, default:false} keep temporary data
    • \n
    • finalize {Function} finalize function
    • \n
    • scope {Object} scope variables exposed to map/reduce/finalize during execution
    • \n
    • jsMode {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
    • \n
    • verbose {Boolean, default:false} provide statistics on job execution time.
    • \n
    • out* {Object, default: {inline:1}} sets the output target for the map reduce job.
    • \n
    \n\n

    * out options:

    \n\n
      \n
    • {inline:1} the results are returned in an array
    • \n
    • {replace: 'collectionName'} add the results to collectionName: the results replace the collection
    • \n
    • {reduce: 'collectionName'} add the results to collectionName: if dups are detected, uses the reducer / finalize functions
    • \n
    • {merge: 'collectionName'} add the results to collectionName: if dups exist the new docs overwrite the old
    • \n
    \n\n

    If options.out is set to replace, merge, or reduce, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the lean option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

    \n\n

    Example:

    \n\n
    var o = {};\no.map = function () { emit(this.name, 1) }\no.reduce = function (k, vals) { return vals.length }\no.out = { replace: 'createdCollectionNameForResults' }\no.verbose = true;\nUser.mapReduce(o, function (err, model, stats) {\n  console.log('map reduce took %d ms', stats.processtime)\n  model.find().where('value').gt(10).exec(function (err, docs) {\n    console.log(docs);\n  });\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.mapReduce = function mapReduce (o, callback) {\n if ('function' != typeof callback) throw new Error('missing callback');\n\n var self = this;\n\n if (!Model.mapReduce.schema) {\n var opts = { noId: true, noVirtualId: true, strict: false }\n Model.mapReduce.schema = new Schema({}, opts);\n }\n\n if (!o.out) o.out = { inline: 1 };\n\n o.map = String(o.map);\n o.reduce = String(o.reduce);\n\n if (o.query) {\n var q = new Query(o.query);\n q.cast(this);\n o.query = q._conditions;\n q = undefined;\n }\n\n this.collection.mapReduce(null, null, o, function (err, ret, stats) {\n if (err) return callback(err);\n\n if (ret.findOne && ret.mapReduce) {\n // returned a collection, convert to Model\n var model = Model.compile(\n '_mapreduce_' + ret.collectionName\n , Model.mapReduce.schema\n , ret.collectionName\n , self.db\n , self.base);\n\n model._mapreduce = true;\n\n return callback(err, model, stats);\n }\n\n callback(err, ret, stats);\n });\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "mapReduce", + "string": "Model.mapReduce()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "an array of pipeline commands" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "aggregation", + "url": "http://docs.mongodb.org/manual/applications/aggregation/", + "visibility": "http://docs.mongodb.org/manual/applications/aggregation/" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate", + "visibility": "http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes an aggregate command on this models collection.

    \n\n

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    ", + "summary": "

    Executes an aggregate command on this models collection.

    ", + "body": "

    Example:

    \n\n
    // find the max age of all users\nUsers.aggregate(\n    { $group: { _id: null, maxAge: { $max: '$age' }}}\n  , { $project: { _id: 0, maxAge: 1 }}\n  , function (err, res) {\n  if (err) return handleError(err);\n  console.log(res); // [ { maxAge: 98 } ]\n});\n
    \n\n

    NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned).

    \n\n

    NOTE: this requires running MongoDB >= 2.1

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.aggregate = function aggregate () {\n return this.collection.aggregate.apply(this.collection, arguments);\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "aggregate", + "string": "Model.aggregate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Document", + "Array" + ], + "name": "docs", + "description": "Either a single document or array of documents to populate." + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "A hash of key/val (path, options) used for population." + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "cb(err,doc)", + "description": "A callback, executed upon completion. Receives `err` and the `doc(s)`." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Populates document references.

    \n\n

    Available options:

    \n\n
      \n
    • path: space delimited path(s) to populate
    • \n
    • select: optional fields to select
    • \n
    • match: optional query conditions to match
    • \n
    • model: optional name of the model to use for population
    • \n
    • options: optional query options like sort, limit, etc
    • \n
    \n\n

    Examples:

    \n\n
    // populates a single object\nUser.findById(id, function (err, user) {\n  var opts = [\n      { path: 'company', match: { x: 1 }, select: 'name' }\n    , { path: 'notes', options: {}, model: 'override' }\n  ]\n\n  User.populate(user, opts, function (err, user) {\n    console.log(user);\n  })\n})\n\n// populates an array of objects\nUser.find(match, function (err, users) {\n  var opts = [{ path: 'company', match: { x: 1 }, select: 'name' }]\n\n  User.populate(users, opts, function (err, user) {\n    console.log(user);\n  })\n})\n\n// imagine a Weapon model exists with two saved documents:\n//   { _id: 389, name: 'whip' }\n//   { _id: 8921, name: 'boomerang' }\n\nvar user = { name: 'Indiana Jones', weapon: 389 }\nWeapon.populate(user, { path: 'weapon', model: 'Weapon' }, function (err, user) {\n  console.log(user.weapon.name) // whip\n})\n\n// populate many plain objects\nvar users = [{ name: 'Indiana Jones', weapon: 389 }]\nusers.push({ name: 'Batman', weapon: 8921 })\nWeapon.populate(users, { path: 'weapon' }, function (err, users) {\n  users.forEach(function (user) {\n    console.log('%s uses a %s', users.name, user.weapon.name)\n    // Indiana Jones uses a whip\n    // Batman uses a boomerang\n  })\n})\n// Note that we didn't need to specify the Weapon model because\n// we were already using it's populate() method.\n
    ", + "summary": "

    Populates document references.

    ", + "body": "

    Available options:

    \n\n
      \n
    • path: space delimited path(s) to populate
    • \n
    • select: optional fields to select
    • \n
    • match: optional query conditions to match
    • \n
    • model: optional name of the model to use for population
    • \n
    • options: optional query options like sort, limit, etc
    • \n
    \n\n

    Examples:

    \n\n
    // populates a single object\nUser.findById(id, function (err, user) {\n  var opts = [\n      { path: 'company', match: { x: 1 }, select: 'name' }\n    , { path: 'notes', options: {}, model: 'override' }\n  ]\n\n  User.populate(user, opts, function (err, user) {\n    console.log(user);\n  })\n})\n\n// populates an array of objects\nUser.find(match, function (err, users) {\n  var opts = [{ path: 'company', match: { x: 1 }, select: 'name' }]\n\n  User.populate(users, opts, function (err, user) {\n    console.log(user);\n  })\n})\n\n// imagine a Weapon model exists with two saved documents:\n//   { _id: 389, name: 'whip' }\n//   { _id: 8921, name: 'boomerang' }\n\nvar user = { name: 'Indiana Jones', weapon: 389 }\nWeapon.populate(user, { path: 'weapon', model: 'Weapon' }, function (err, user) {\n  console.log(user.weapon.name) // whip\n})\n\n// populate many plain objects\nvar users = [{ name: 'Indiana Jones', weapon: 389 }]\nusers.push({ name: 'Batman', weapon: 8921 })\nWeapon.populate(users, { path: 'weapon' }, function (err, users) {\n  users.forEach(function (user) {\n    console.log('%s uses a %s', users.name, user.weapon.name)\n    // Indiana Jones uses a whip\n    // Batman uses a boomerang\n  })\n})\n// Note that we didn't need to specify the Weapon model because\n// we were already using it's populate() method.\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Model.populate = function (docs, paths, cb) {\n assert.equal('function', typeof cb);\n\n // always callback on nextTick for consistent async behavior\n function callback () {\n var args = utils.args(arguments);\n process.nextTick(function () {\n cb.apply(null, args);\n });\n }\n\n // normalized paths\n var paths = utils.populate(paths);\n var pending = paths.length;\n\n if (0 === pending) {\n return callback(null, docs);\n }\n\n // each path has its own query options and must be executed separately\n var i = pending;\n var path;\n while (i--) {\n path = paths[i];\n populate(this, docs, path, next);\n }\n\n function next (err) {\n if (next.err) return;\n if (err) return callback(next.err = err);\n if (--pending) return;\n callback(null, docs);\n }\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "populate", + "string": "Model.populate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Populates docs

    ", + "summary": "

    Populates docs

    ", + "body": "" + }, + "ignore": true, + "code": "function populate (model, docs, options, cb) {\n var select = options.select\n , match = options.match\n , path = options.path\n\n var schema = model._getSchema(path);\n var subpath;\n\n // handle document arrays\n if (schema && schema.caster) {\n schema = schema.caster;\n }\n\n // model name for the populate query\n var modelName = options.model // overridden in query options\n || schema && schema.options.ref // declared in schema\n || model.modelName // an ad-hoc structure\n\n var Model = model.db.model(modelName);\n\n // expose the model used\n options.model = Model;\n\n // normalize single / multiple docs passed\n if (!Array.isArray(docs)) {\n docs = [docs];\n }\n\n if (0 === docs.length || docs.every(utils.isNullOrUndefined)) {\n return cb();\n }\n\n // get all ids for all docs for a given path\n var rawIds = docs.map(function (doc) {\n if (!doc) return doc;\n\n var isDocument = !! doc.$__;\n var ret;\n\n if (isDocument && !doc.isModified(path)) {\n // it is possible a previously populated path is being\n // populated again. because users can specify matcher\n // clauses in their populate arguments we use the cached\n // _ids from the original populate call to ensure all _ids\n // are looked up, but only if the path wasn't modified which\n // signifies the users intent of the state of the path.\n ret = doc.populated(path);\n }\n\n if (!ret || Array.isArray(ret) && 0 === ret.length) {\n ret = utils.getValue(path, doc);\n }\n\n options._docs[doc._id] = Array.isArray(ret)\n ? ret.slice()\n : ret;\n\n if (isDocument) {\n // cache original populated _ids and model used\n doc.populated(path, options._docs[doc._id], options);\n }\n\n return ret;\n });\n\n var ids = utils.array.flatten(rawIds, function (item) {\n // no need to include undefined values in our query\n return undefined !== item;\n });\n\n if (0 === ids.length || ids.every(utils.isNullOrUndefined)) {\n return cb();\n }\n\n // preserve original match conditions by copying\n if (match) {\n match = utils.object.shallowCopy(match);\n } else {\n match = {};\n }\n\n match._id || (match._id = { $in: ids });\n\n var assignmentOpts = {};\n assignmentOpts.sort = options.options && options.options.sort || undefined;\n assignmentOpts.excludeId = /\\s?-_id\\s?/.test(select) || (select && 0 === select._id);\n\n if (assignmentOpts.excludeId) {\n // override the exclusion from the query so we can use the _id\n // for document matching during assignment. we'll delete the\n // _id back off before returning the result.\n if ('string' == typeof select) {\n select = null;\n } else {\n // preserve original select conditions by copying\n select = utils.object.shallowCopy(select);\n delete select._id;\n }\n }\n\n Model.find(match, select, options.options, function (err, vals) {\n if (err) return cb(err);\n\n assignVals({\n rawIds: rawIds\n , rawDocs: vals\n , docs: docs\n , path: path\n , options: assignmentOpts\n })\n\n cb();\n });\n}", + "ctx": { + "type": "function", + "name": "populate", + "string": "populate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Assigns documents returned from a population query back
    to the original document path.

    ", + "summary": "

    Assigns documents returned from a population query back
    to the original document path.

    ", + "body": "" + }, + "ignore": true, + "code": "function assignVals (opts) {\n var rawIds = opts.rawIds;\n var rawDocs = opts.rawDocs;\n var docs = opts.docs;\n var path = opts.path;\n var options = opts.options;\n\n assignRawDocsToIdStructure(rawIds, rawDocs, options);\n\n for (var i = 0; i < docs.length; ++i) {\n utils.setValue(path, rawIds[i], docs[i], function (val) {\n return valueFilter(val, options);\n });\n }\n}", + "ctx": { + "type": "function", + "name": "assignVals", + "string": "assignVals()" + } + }, + { + "tags": [], + "description": { + "full": "

    1) Apply backwards compatible find/findOne behavior to sub documents

    \n\n

    find logic:
    a) filter out non-documents
    b) remove _id from sub docs when user specified

    \n\n

    findOne
    a) if no doc found, set to null
    b) remove _id from sub docs when user specified

    \n\n

    2) Remove _ids when specified by users query.

    \n\n

    background:
    _ids are left in the query even when user excludes them so
    that population mapping can occur.

    ", + "summary": "

    1) Apply backwards compatible find/findOne behavior to sub documents

    ", + "body": "

    find logic:
    a) filter out non-documents
    b) remove _id from sub docs when user specified

    \n\n

    findOne
    a) if no doc found, set to null
    b) remove _id from sub docs when user specified

    \n\n

    2) Remove _ids when specified by users query.

    \n\n

    background:
    _ids are left in the query even when user excludes them so
    that population mapping can occur.

    " + }, + "ignore": true, + "code": "function valueFilter (val, assignmentOpts) {\n if (Array.isArray(val)) {\n // find logic\n var ret = [];\n for (var i = 0; i < val.length; ++i) {\n var subdoc = val[i];\n if (!isDoc(subdoc)) continue;\n maybeRemoveId(subdoc, assignmentOpts);\n ret.push(subdoc);\n }\n return ret;\n }\n\n // findOne\n if (isDoc(val)) {\n maybeRemoveId(val, assignmentOpts);\n return val;\n }\n return null;\n}", + "ctx": { + "type": "function", + "name": "valueFilter", + "string": "valueFilter()" + } + }, + { + "tags": [], + "description": { + "full": "

    Remove _id from subdoc if user specified \"lean\" query option

    ", + "summary": "

    Remove _id from subdoc if user specified \"lean\" query option

    ", + "body": "" + }, + "ignore": true, + "code": "function maybeRemoveId (subdoc, assignmentOpts) {\n if (assignmentOpts.excludeId) {\n if ('function' == typeof subdoc.setValue) {\n subdoc.setValue('_id', undefined);\n } else {\n delete subdoc._id;\n }\n }\n}", + "ctx": { + "type": "function", + "name": "maybeRemoveId", + "string": "maybeRemoveId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Determine if doc is a document returned
    by a populate query.

    ", + "summary": "

    Determine if doc is a document returned
    by a populate query.

    ", + "body": "" + }, + "ignore": true, + "code": "function isDoc (doc) {\n if (null == doc)\n return false;\n\n var type = typeof doc;\n if ('string' == type)\n return false;\n\n if ('number' == type)\n return false;\n\n if (Buffer.isBuffer(doc))\n return false;\n\n if ('ObjectID' == doc.constructor.name)\n return false;\n\n // only docs\n return true;\n}", + "ctx": { + "type": "function", + "name": "isDoc", + "string": "isDoc()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "rawIds", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "vals", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "sort", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Assign vals returned by mongo query to the rawIds
    structure returned from utils.getVals() honoring
    query sort order if specified by user.

    \n\n

    This can be optimized.

    \n\n

    Rules

    \n\n

    if the value of the path is not an array, use findOne rules, else find.
    for findOne the results are assigned directly to doc path (including null results).
    for find, if user specified sort order, results are assigned directly
    else documents are put back in original order of array if found in results

    ", + "summary": "

    Assign vals returned by mongo query to the rawIds
    structure returned from utils.getVals() honoring
    query sort order if specified by user.

    ", + "body": "

    This can be optimized.

    \n\n

    Rules

    \n\n

    if the value of the path is not an array, use findOne rules, else find.
    for findOne the results are assigned directly to doc path (including null results).
    for find, if user specified sort order, results are assigned directly
    else documents are put back in original order of array if found in results

    " + }, + "isPrivate": true, + "ignore": true, + "code": "function assignRawDocsToIdStructure (rawIds, vals, options, recursed) {\n // honor user specified sort order\n var newOrder = [];\n var sorting = options.sort && rawIds.length > 1;\n var found;\n var doc;\n var sid;\n var id;\n\n for (var i = 0; i < rawIds.length; ++i) {\n id = rawIds[i];\n\n if (Array.isArray(id)) {\n // handle [ [id0, id2], [id3] ]\n assignRawDocsToIdStructure(id, vals, options, true);\n newOrder.push(id);\n continue;\n }\n\n if (null === id && !sorting) {\n // keep nulls for findOne unless sorting, which always\n // removes them (backward compat)\n newOrder.push(id);\n continue;\n }\n\n sid = String(id);\n found = false;\n\n if (recursed) {\n // apply find behavior\n\n // assign matching documents in original order unless sorting\n for (var f = 0; f < vals.length; ++f) {\n if (sid == String(vals[f]._id)) {\n found = true;\n if (sorting) {\n newOrder[f] = vals[f];\n } else {\n newOrder.push(vals[f]);\n }\n break;\n }\n }\n\n if (!found) {\n newOrder.push(id);\n }\n\n } else {\n // apply findOne behavior - if document in results, assign, else assign null\n\n doc = null;\n for (var f = 0; f < vals.length; ++f) {\n if (sid == String(vals[f]._id)) {\n doc = vals[f];\n break;\n }\n }\n\n newOrder[i] = doc;\n }\n }\n\n rawIds.length = 0;\n if (newOrder.length) {\n // reassign the documents based on corrected order\n\n // forEach skips over sparse entries in arrays so we\n // can safely use this to our advantage dealing with sorted\n // result sets too.\n newOrder.forEach(function (doc, i) {\n rawIds[i] = doc;\n });\n }\n}", + "ctx": { + "type": "function", + "name": "assignRawDocsToIdStructure", + "string": "assignRawDocsToIdStructure()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "Schema" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Model._getSchema = function _getSchema (path) {\n var schema = this.schema\n , pathschema = schema.path(path);\n\n if (pathschema)\n return pathschema;\n\n // look for arrays\n return (function search (parts, schema) {\n var p = parts.length + 1\n , foundschema\n , trypath\n\n while (p--) {\n trypath = parts.slice(0, p).join('.');\n foundschema = schema.path(trypath);\n if (foundschema) {\n if (foundschema.caster) {\n\n // array of Mixed?\n if (foundschema.caster instanceof Types.Mixed) {\n return foundschema.caster;\n }\n\n // Now that we found the array, we need to check if there\n // are remaining document paths to look up for casting.\n // Also we need to handle array.$.path since schema.path\n // doesn't work for that.\n if (p !== parts.length) {\n if ('$' === parts[p]) {\n // comments.$.comments.$.title\n return search(parts.slice(p+1), foundschema.schema);\n } else {\n // this is the last path of the selector\n return search(parts.slice(p), foundschema.schema);\n }\n }\n }\n return foundschema;\n }\n }\n })(path.split('.'), schema)\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "_getSchema", + "string": "Model._getSchema()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "model name" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "collectionName", + "description": "" + }, + { + "type": "param", + "types": [ + "Connection" + ], + "name": "connection", + "description": "" + }, + { + "type": "param", + "types": [ + "Mongoose" + ], + "name": "base", + "description": "mongoose instance" + } + ], + "description": { + "full": "

    Compiler utility.

    ", + "summary": "

    Compiler utility.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.compile = function compile (name, schema, collectionName, connection, base) {\n var versioningEnabled = false !== schema.options.versionKey;\n\n if (versioningEnabled && !schema.paths[schema.options.versionKey]) {\n // add versioning to top level documents only\n var o = {};\n o[schema.options.versionKey] = Number;\n schema.add(o);\n }\n\n // generate new class\n function model (doc, fields, skipId) {\n if (!(this instanceof model))\n return new model(doc, fields, skipId);\n Model.call(this, doc, fields, skipId);\n };\n\n model.base = base;\n model.modelName = name;\n model.__proto__ = Model;\n model.prototype.__proto__ = Model.prototype;\n model.model = Model.prototype.model;\n model.db = model.prototype.db = connection;\n\n model.prototype.$__setSchema(schema);\n\n var collectionOptions = {\n bufferCommands: schema.options.bufferCommands\n , capped: schema.options.capped\n };\n\n model.prototype.collection = connection.collection(\n collectionName\n , collectionOptions\n );\n\n // apply methods\n for (var i in schema.methods)\n model.prototype[i] = schema.methods[i];\n\n // apply statics\n for (var i in schema.statics)\n model[i] = schema.statics[i];\n\n // apply named scopes\n if (schema.namedScopes) schema.namedScopes.compile(model);\n\n model.schema = model.prototype.schema;\n model.options = model.prototype.options;\n model.collection = model.prototype.collection;\n\n return model;\n};", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "compile", + "string": "Model.compile()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Connection" + ], + "name": "conn", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "[schema]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[collection]", + "description": "" + }, + { + "type": "return", + "types": [ + "Model" + ], + "description": "" + } + ], + "description": { + "full": "

    Subclass this model with conn, schema, and collection settings.

    ", + "summary": "

    Subclass this model with conn, schema, and collection settings.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "Model.__subclass = function subclass (conn, schema, collection) {\n // subclass model using this connection and collection name\n var model = this;\n\n var Model = function Model (doc, fields, skipId) {\n if (!(this instanceof Model)) {\n return new Model(doc, fields, skipId);\n }\n model.call(this, doc, fields, skipId);\n }\n\n Model.__proto__ = model;\n Model.prototype.__proto__ = model.prototype;\n Model.db = Model.prototype.db = conn;\n\n var s = 'string' != typeof schema\n ? schema\n : model.prototype.schema;\n\n if (!collection) {\n collection = model.prototype.schema.get('collection')\n || utils.toCollectionName(model.modelName);\n }\n\n var collectionOptions = {\n bufferCommands: s ? s.options.bufferCommands : true\n , capped: s && s.options.capped\n };\n\n Model.prototype.collection = conn.collection(collection, collectionOptions);\n Model.collection = Model.prototype.collection;\n Model.init();\n return Model;\n}", + "ctx": { + "type": "method", + "receiver": "Model", + "name": "__subclass", + "string": "Model.__subclass()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Model;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Model", + "string": "module.exports" + } + } +] +### lib/namedscope.js +[ + { + "tags": [ + { + "type": "param", + "types": [ + "NamedScope" + ], + "name": "target", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "getters", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Decorate

    ", + "summary": "

    Decorate

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "NamedScope.prototype.decorate = function (target, getters) {\n var name = this.name\n , block = this.block\n , query = this.query;\n if (block) {\n if (block.length === 0) {\n Object.defineProperty(target, name, {\n get: getters.block0(block)\n });\n } else {\n target[name] = getters.blockN(block);\n }\n } else {\n Object.defineProperty(target, name, {\n get: getters.basic(query)\n });\n }\n};\n\nNamedScope.prototype.compile = function (model) {\n var allScopes = this.scopesByName\n , scope;\n for (var k in allScopes) {\n scope = allScopes[k];\n scope.decorate(model, {\n block0: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.call(cquery);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n block.apply(cquery, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));\n cquery.find(query);\n return this;\n };\n }\n });\n }\n};\n\nmodule.exports = NamedScope;", + "ctx": { + "type": "method", + "constructor": "NamedScope", + "name": "decorate", + "string": "NamedScope.prototype.decorate()" + } + } +] +### lib/promise.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies

    ", + "summary": "

    Module dependencies

    ", + "body": "" + }, + "ignore": true, + "code": "var MPromise = require('mpromise');", + "ctx": { + "type": "declaration", + "name": "MPromise", + "value": "require('mpromise')", + "string": "MPromise" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "a function which will be called when the promise is resolved that accepts `fn(err, ...){}` as signature" + }, + { + "type": "inherits", + "string": "mpromise https://github.com/aheckmann/mpromise" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`err`: Emits when the promise is rejected" + }, + { + "type": "event", + "string": "`complete`: Emits when the promise is fulfilled" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Promise constructor.

    \n\n

    Promises are returned from executed queries. Example:

    \n\n
    var query = Candy.find({ bar: true });\nvar promise = query.exec();\n
    ", + "summary": "

    Promise constructor.

    ", + "body": "

    Promises are returned from executed queries. Example:

    \n\n
    var query = Candy.find({ bar: true });\nvar promise = query.exec();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Promise (fn) {\n MPromise.call(this, fn);\n}", + "ctx": { + "type": "function", + "name": "Promise", + "string": "Promise()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from mpromise

    ", + "summary": "

    Inherit from mpromise

    ", + "body": "" + }, + "ignore": true, + "code": "Promise.prototype = Object.create(MPromise.prototype, {\n constructor: {\n value: Promise\n , enumerable: false\n , writable: true\n , configurable: true\n }\n});", + "ctx": { + "type": "property", + "receiver": "Promise", + "name": "prototype", + "value": "Object.create(MPromise.prototype, {", + "string": "Promise.prototype" + } + }, + { + "tags": [], + "description": { + "full": "

    Override event names for backward compatibility.

    ", + "summary": "

    Override event names for backward compatibility.

    ", + "body": "" + }, + "ignore": true, + "code": "Promise.SUCCESS = 'complete';\nPromise.FAILURE = 'err';", + "ctx": { + "type": "property", + "receiver": "Promise", + "name": "SUCCESS", + "value": "'complete'", + "string": "Promise.SUCCESS" + } + }, + { + "tags": [ + { + "type": "see", + "title": "mpromise#on", + "url": "https://github.com/aheckmann/mpromise#on", + "visibility": "https://github.com/aheckmann/mpromise#on" + }, + { + "type": "method", + "string": "on" + }, + { + "type": "memberOf", + "parent": "Promise" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "listener", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds listener to the event.

    \n\n

    If event is either the success or failure event and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    ", + "summary": "

    Adds listener to the event.

    ", + "body": "

    If event is either the success or failure event and the event has already been emitted, thelistener is called immediately and passed the results of the original emitted event.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "see", + "title": "mpromise#reject", + "url": "https://github.com/aheckmann/mpromise#reject", + "visibility": "https://github.com/aheckmann/mpromise#reject" + }, + { + "type": "method", + "string": "reject" + }, + { + "type": "memberOf", + "parent": "Promise" + }, + { + "type": "param", + "types": [ + "Object", + "String", + "Error" + ], + "name": "reason", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Rejects this promise with reason.

    \n\n

    If the promise has already been fulfilled or rejected, not action is taken.

    ", + "summary": "

    Rejects this promise with reason.

    ", + "body": "

    If the promise has already been fulfilled or rejected, not action is taken.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "param", + "types": [ + "Error", + "String" + ], + "name": "err", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + } + ], + "description": { + "full": "

    Rejects this promise with err.

    \n\n

    If the promise has already been fulfilled or rejected, not action is taken.

    \n\n

    Differs from #reject by first casting err to an Error if it is not instanceof Error.

    ", + "summary": "

    Rejects this promise with err.

    ", + "body": "

    If the promise has already been fulfilled or rejected, not action is taken.

    \n\n

    Differs from #reject by first casting err to an Error if it is not instanceof Error.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.error = function (err) {\n if (!(err instanceof Error)) err = new Error(err);\n return this.reject(err);\n}", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "error", + "string": "Promise.prototype.error()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "[err]", + "description": "error or null" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "value to fulfill the promise with" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Resolves this promise to a rejected state if err is passed or a fulfilled state if no err is passed.

    \n\n

    If the promise has already been fulfilled or rejected, not action is taken.

    \n\n

    err will be cast to an Error if not already instanceof Error.

    \n\n

    NOTE: overrides mpromise#resolve to provide error casting.

    ", + "summary": "

    Resolves this promise to a rejected state if err is passed or a fulfilled state if no err is passed.

    ", + "body": "

    If the promise has already been fulfilled or rejected, not action is taken.

    \n\n

    err will be cast to an Error if not already instanceof Error.

    \n\n

    NOTE: overrides mpromise#resolve to provide error casting.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.resolve = function (err, val) {\n if (err) return this.error(err);\n return this.fulfill(val);\n}", + "ctx": { + "type": "method", + "constructor": "Promise", + "name": "resolve", + "string": "Promise.prototype.resolve()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "addBack" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "listener", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + } + ], + "description": { + "full": "

    Adds a single function as a listener to both err and complete.

    \n\n

    It will be executed with traditional node.js argument position when the promise is resolved.

    \n\n
    promise.addBack(function (err, args...) {\n  if (err) return handleError(err);\n  console.log('success');\n})\n
    \n\n

    Alias of mpromise#onResolve.

    ", + "summary": "

    Adds a single function as a listener to both err and complete.

    ", + "body": "

    It will be executed with traditional node.js argument position when the promise is resolved.

    \n\n
    promise.addBack(function (err, args...) {\n  if (err) return handleError(err);\n  console.log('success');\n})\n
    \n\n

    Alias of mpromise#onResolve.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addBack = Promise.prototype.onResolve;", + "ctx": { + "type": "property", + "constructor": "Promise", + "name": "addBack", + "value": "Promise.prototype.onResolve", + "string": "Promise.prototypeaddBack" + } + }, + { + "tags": [ + { + "type": "method", + "string": "complete" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "args", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Fulfills this promise with passed arguments.

    \n\n

    Alias of mpromise#fulfill.

    ", + "summary": "

    Fulfills this promise with passed arguments.

    ", + "body": "

    Alias of mpromise#fulfill.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.complete = MPromise.prototype.fulfill;", + "ctx": { + "type": "property", + "constructor": "Promise", + "name": "complete", + "value": "MPromise.prototype.fulfill", + "string": "Promise.prototypecomplete" + } + }, + { + "tags": [ + { + "type": "method", + "string": "addCallback" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "listener", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a listener to the complete (success) event.

    \n\n

    Alias of mpromise#onFulfill.

    ", + "summary": "

    Adds a listener to the complete (success) event.

    ", + "body": "

    Alias of mpromise#onFulfill.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addCallback = Promise.prototype.onFulfill;", + "ctx": { + "type": "property", + "constructor": "Promise", + "name": "addCallback", + "value": "Promise.prototype.onFulfill", + "string": "Promise.prototypeaddCallback" + } + }, + { + "tags": [ + { + "type": "method", + "string": "addErrback" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "listener", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a listener to the err (rejected) event.

    \n\n

    Alias of mpromise#onReject.

    ", + "summary": "

    Adds a listener to the err (rejected) event.

    ", + "body": "

    Alias of mpromise#onReject.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Promise.prototype.addErrback = Promise.prototype.onReject;", + "ctx": { + "type": "property", + "constructor": "Promise", + "name": "addErrback", + "value": "Promise.prototype.onReject", + "string": "Promise.prototypeaddErrback" + } + }, + { + "tags": [ + { + "type": "see", + "title": "promises-A+", + "url": "https://github.com/promises-aplus/promises-spec", + "visibility": "https://github.com/promises-aplus/promises-spec" + }, + { + "type": "see", + "title": "mpromise#then", + "url": "https://github.com/aheckmann/mpromise#then", + "visibility": "https://github.com/aheckmann/mpromise#then" + }, + { + "type": "method", + "string": "then" + }, + { + "type": "memberOf", + "parent": "Promise" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "onFulFill", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "onReject", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "newPromise" + } + ], + "description": { + "full": "

    Creates a new promise and returns it. If onFulfill or onReject are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.

    \n\n

    Conforms to promises/A+ specification.

    \n\n

    Example:

    \n\n
    var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec();\npromise.then(function (meetups) {\n  var ids = meetups.map(function (m) {\n    return m._id;\n  });\n  return People.find({ meetups: { $in: ids }).exec();\n}).then(function (people) {\n  if (people.length < 10000) {\n    throw new Error('Too few people!!!');\n  } else {\n    throw new Error('Still need more people!!!');\n  }\n}).then(null, function (err) {\n  assert.ok(err instanceof Error);\n});\n
    ", + "summary": "

    Creates a new promise and returns it. If onFulfill or onReject are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.

    ", + "body": "

    Conforms to promises/A+ specification.

    \n\n

    Example:

    \n\n
    var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec();\npromise.then(function (meetups) {\n  var ids = meetups.map(function (m) {\n    return m._id;\n  });\n  return People.find({ meetups: { $in: ids }).exec();\n}).then(function (people) {\n  if (people.length < 10000) {\n    throw new Error('Too few people!!!');\n  } else {\n    throw new Error('Still need more people!!!');\n  }\n}).then(null, function (err) {\n  assert.ok(err instanceof Error);\n});\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "see", + "title": "mpromise#end", + "url": "https://github.com/aheckmann/mpromise#end", + "visibility": "https://github.com/aheckmann/mpromise#end" + }, + { + "type": "method", + "string": "end" + }, + { + "type": "memberOf", + "parent": "Promise" + } + ], + "description": { + "full": "

    Signifies that this promise was the last in a chain of then()s: if a handler passed to the call to then which produced this promise throws, the exception will go uncaught.

    \n\n

    Example:

    \n\n
    var p = new Promise;\np.then(function(){ throw new Error('shucks') });\nsetTimeout(function () {\n  p.fulfill();\n  // error was caught and swallowed by the promise returned from\n  // p.then(). we either have to always register handlers on\n  // the returned promises or we can do the following...\n}, 10);\n\n// this time we use .end() which prevents catching thrown errors\nvar p = new Promise;\nvar p2 = p.then(function(){ throw new Error('shucks') }).end(); // <--\nsetTimeout(function () {\n  p.fulfill(); // throws \"shucks\"\n}, 10);\n
    ", + "summary": "

    Signifies that this promise was the last in a chain of then()s: if a handler passed to the call to then which produced this promise throws, the exception will go uncaught.

    ", + "body": "

    Example:

    \n\n
    var p = new Promise;\np.then(function(){ throw new Error('shucks') });\nsetTimeout(function () {\n  p.fulfill();\n  // error was caught and swallowed by the promise returned from\n  // p.then(). we either have to always register handlers on\n  // the returned promises or we can do the following...\n}, 10);\n\n// this time we use .end() which prevents catching thrown errors\nvar p = new Promise;\nvar p2 = p.then(function(){ throw new Error('shucks') }).end(); // <--\nsetTimeout(function () {\n  p.fulfill(); // throws \"shucks\"\n}, 10);\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    expose

    ", + "summary": "

    expose

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Promise;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Promise", + "string": "module.exports" + } + } +] +### lib/query.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils')\n , merge = utils.merge\n , Promise = require('./promise')\n , Document = require('./document')\n , Types = require('./schema/index')\n , inGroupsOf = utils.inGroupsOf\n , tick = utils.tick\n , QueryStream = require('./querystream')\n , ReadPref = require('mongodb').ReadPreference", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "criteria", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Query constructor used for building queries.

    \n\n

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    ", + "summary": "

    Query constructor used for building queries.

    ", + "body": "

    Example:

    \n\n
    var query = Model.find();\nquery.where('age').gte(21).exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Query (criteria, options) {\n this.setOptions(options, true);\n this._conditions = {};\n this._updateArg = {};\n this._fields = undefined;\n this._geoComparison = undefined;\n if (criteria) this.find(criteria);\n}", + "ctx": { + "type": "function", + "name": "Query", + "string": "Query()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query options.

    \n\n

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    ", + "summary": "

    Sets query options.

    ", + "body": "

    Options:

    \n\n\n\n

    * denotes a query helper method is also available

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.setOptions = function (options, overwrite) {\n // overwrite is internal use only\n if (overwrite) {\n options = this.options = options || {};\n this.safe = options.safe;\n if ('populate' in options) {\n this.populate(this.options.populate);\n }\n return this;\n }\n\n if (!(options && 'Object' == options.constructor.name))\n return this;\n\n if ('safe' in options)\n this.safe = options.safe;\n\n // set arbitrary options\n var methods = Object.keys(options)\n , i = methods.length\n , method\n\n while (i--) {\n method = methods[i];\n\n // use methods if exist (safer option manipulation)\n if ('function' == typeof this[method]) {\n var args = Array.isArray(options[method])\n ? options[method]\n : [options[method]];\n this[method].apply(this, args)\n } else {\n this.options[method] = options[method];\n }\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "setOptions", + "string": "Query.prototype.setOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "the model to which the query is bound" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "the operation to execute" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "updateArg", + "description": "used in update methods" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Binds this query to a model.

    ", + "summary": "

    Binds this query to a model.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.bind = function bind (model, op, updateArg) {\n this.model = model;\n this.op = op;\n\n if (model._mapreduce) this.options.lean = true;\n\n if (op == 'update' || op == 'findOneAndUpdate') {\n merge(this._updateArg, updateArg || {});\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "bind", + "string": "Query.prototype.bind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "[operation]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Promise" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query

    \n\n

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    ", + "summary": "

    Executes the query

    ", + "body": "

    Examples

    \n\n
    query.exec();\nquery.exec(callback);\nquery.exec('update');\nquery.exec('find', callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exec = function exec (op, callback) {\n var promise = new Promise();\n\n switch (typeof op) {\n case 'function':\n callback = op;\n op = null;\n break;\n case 'string':\n this.op = op;\n break;\n }\n\n if (callback) promise.addBack(callback);\n\n if (!this.op) {\n promise.complete();\n return promise;\n }\n\n if ('update' == this.op) {\n this[this.op](this._updateArg, promise.resolve.bind(promise));\n return promise;\n }\n\n if ('distinct' == this.op) {\n this.distinct(this._distinctArg, promise.resolve.bind(promise));\n return promise;\n }\n\n this[this.op](promise.resolve.bind(promise));\n return promise;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exec", + "string": "Query.prototype.exec()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[criteria]", + "description": "mongodb selector" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Finds documents.

    \n\n

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    ", + "summary": "

    Finds documents.

    ", + "body": "

    When no callback is passed, the query is not executed.

    \n\n

    Example

    \n\n
    query.find({ name: 'Los Pollos Hermanos' }).find(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.find = function (criteria, callback) {\n this.op = 'find';\n if ('function' === typeof criteria) {\n callback = criteria;\n criteria = {};\n } else if (criteria instanceof Query) {\n // TODO Merge options, too\n merge(this._conditions, criteria._conditions);\n } else if (criteria instanceof Document) {\n merge(this._conditions, criteria.toObject());\n } else if (criteria && 'Object' === criteria.constructor.name) {\n merge(this._conditions, criteria);\n }\n if (!callback) return this;\n return this.execFind(callback);\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "find", + "string": "Query.prototype.find()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[obj]", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Casts this query to the schema of model

    \n\n

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    ", + "summary": "

    Casts this query to the schema of model

    ", + "body": "

    Note

    \n\n

    If obj is present, it is cast instead of this query.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.cast = function (model, obj) {\n obj || (obj= this._conditions);\n\n var schema = model.schema\n , paths = Object.keys(obj)\n , i = paths.length\n , any$conditionals\n , schematype\n , nested\n , path\n , type\n , val;\n\n while (i--) {\n path = paths[i];\n val = obj[path];\n\n if ('$or' === path || '$nor' === path || '$and' === path) {\n var k = val.length\n , orComponentQuery;\n\n while (k--) {\n orComponentQuery = new Query(val[k]);\n orComponentQuery.cast(model);\n val[k] = orComponentQuery._conditions;\n }\n\n } else if (path === '$where') {\n type = typeof val;\n\n if ('string' !== type && 'function' !== type) {\n throw new Error(\"Must have a string or function for $where\");\n }\n\n if ('function' === type) {\n obj[path] = val.toString();\n }\n\n continue;\n\n } else {\n\n if (!schema) {\n // no casting for Mixed types\n continue;\n }\n\n schematype = schema.path(path);\n\n if (!schematype) {\n // Handle potential embedded array queries\n var split = path.split('.')\n , j = split.length\n , pathFirstHalf\n , pathLastHalf\n , remainingConds\n , castingQuery;\n\n // Find the part of the var path that is a path of the Schema\n while (j--) {\n pathFirstHalf = split.slice(0, j).join('.');\n schematype = schema.path(pathFirstHalf);\n if (schematype) break;\n }\n\n // If a substring of the input path resolves to an actual real path...\n if (schematype) {\n // Apply the casting; similar code for $elemMatch in schema/array.js\n if (schematype.caster && schematype.caster.schema) {\n remainingConds = {};\n pathLastHalf = split.slice(j).join('.');\n remainingConds[pathLastHalf] = val;\n castingQuery = new Query(remainingConds);\n castingQuery.cast(schematype.caster);\n obj[path] = castingQuery._conditions[pathLastHalf];\n } else {\n obj[path] = val;\n }\n continue;\n }\n\n if (utils.isObject(val)) {\n // handle geo schemas that use object notation\n // { loc: { long: Number, lat: Number }\n\n var geo = val.$near ? '$near' :\n val.$nearSphere ? '$nearSphere' :\n val.$within ? '$within' :\n val.$geoIntersects ? '$geoIntersects' : '';\n\n if (!geo) {\n continue;\n }\n\n var numbertype = new Types.Number('__QueryCasting__')\n var value = val[geo];\n\n if (val.$maxDistance) {\n val.$maxDistance = numbertype.castForQuery(val.$maxDistance);\n }\n\n if ('$within' == geo) {\n var withinType = value.$center\n || value.$centerSphere\n || value.$box\n || value.$polygon;\n\n if (!withinType) {\n throw new Error('Bad $within paramater: ' + JSON.stringify(val));\n }\n\n value = withinType;\n\n } else if ('$near' == geo &&\n 'string' == typeof value.type && Array.isArray(value.coordinates)) {\n // geojson; cast the coordinates\n value = value.coordinates;\n\n } else if (('$near' == geo || '$geoIntersects' == geo) &&\n value.$geometry && 'string' == typeof value.$geometry.type &&\n Array.isArray(value.$geometry.coordinates)) {\n // geojson; cast the coordinates\n value = value.$geometry.coordinates;\n }\n\n ;(function _cast (val) {\n if (Array.isArray(val)) {\n val.forEach(function (item, i) {\n if (Array.isArray(item) || utils.isObject(item)) {\n return _cast(item);\n }\n val[i] = numbertype.castForQuery(item);\n });\n } else {\n var nearKeys= Object.keys(val);\n var nearLen = nearKeys.length;\n while (nearLen--) {\n var nkey = nearKeys[nearLen];\n var item = val[nkey];\n if (Array.isArray(item) || utils.isObject(item)) {\n _cast(item);\n val[nkey] = item;\n } else {\n val[nkey] = numbertype.castForQuery(item);\n }\n }\n }\n })(value);\n }\n\n } else if (val === null || val === undefined) {\n continue;\n } else if ('Object' === val.constructor.name) {\n\n any$conditionals = Object.keys(val).some(function (k) {\n return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';\n });\n\n if (!any$conditionals) {\n obj[path] = schematype.castForQuery(val);\n } else {\n\n var ks = Object.keys(val)\n , k = ks.length\n , $cond;\n\n while (k--) {\n $cond = ks[k];\n nested = val[$cond];\n\n if ('$exists' === $cond) {\n if ('boolean' !== typeof nested) {\n throw new Error(\"$exists parameter must be Boolean\");\n }\n continue;\n }\n\n if ('$type' === $cond) {\n if ('number' !== typeof nested) {\n throw new Error(\"$type parameter must be Number\");\n }\n continue;\n }\n\n if ('$not' === $cond) {\n this.cast(model, nested);\n } else {\n val[$cond] = schematype.castForQuery($cond, nested);\n }\n }\n }\n } else {\n obj[path] = schematype.castForQuery(val);\n }\n }\n }\n\n return obj;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "cast", + "string": "Query.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options.

    ", + "summary": "

    Returns default options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._optionsForExec = function (model) {\n var options = utils.clone(this.options, { retainKeyOrder: true });\n delete options.populate;\n\n if (!('safe' in options))\n options.safe = model.schema.options.safe;\n\n if (!('readPreference' in options) && model.schema.options.read)\n options.readPreference = model.schema.options.read;\n\n return options;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_optionsForExec", + "string": "Query.prototype._optionsForExec()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies schematype selected options to this query.

    ", + "summary": "

    Applies schematype selected options to this query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._applyPaths = function applyPaths () {\n // determine if query is selecting or excluding fields\n\n var fields = this._fields\n , exclude\n , keys\n , ki\n\n if (fields) {\n keys = Object.keys(fields);\n ki = keys.length;\n\n while (ki--) {\n if ('+' == keys[ki][0]) continue;\n exclude = 0 === fields[keys[ki]];\n break;\n }\n }\n\n // if selecting, apply default schematype select:true fields\n // if excluding, apply schematype select:false fields\n\n var selected = []\n , excluded = []\n , seen = [];\n\n analyzeSchema(this.model.schema);\n\n switch (exclude) {\n case true:\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n case false:\n selected.length && this.select(selected.join(' '));\n break;\n case undefined:\n // user didn't specify fields, implies returning all fields.\n // only need to apply excluded fields\n excluded.length && this.select('-' + excluded.join(' -'));\n break;\n }\n\n return seen = excluded = selected = keys = fields = null;\n\n function analyzeSchema (schema, prefix) {\n prefix || (prefix = '');\n\n // avoid recursion\n if (~seen.indexOf(schema)) return;\n seen.push(schema);\n\n schema.eachPath(function (path, type) {\n if (prefix) path = prefix + '.' + path;\n\n // array of subdocs?\n if (type.schema) {\n analyzeSchema(type.schema, path);\n }\n\n analyzePath(path, type);\n });\n }\n\n function analyzePath (path, type) {\n if ('boolean' != typeof type.selected) return;\n\n if (fields && ('+' + path) in fields) {\n // forced inclusion\n delete fields['+' + path];\n\n // if there are other fields being included, add this one\n // if no other included fields, leave this out (implied inclusion)\n if (false === exclude && keys.length > 1) {\n fields[path] = 1;\n }\n\n return\n };\n\n ;(type.selected ? selected : excluded).push(path);\n }\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_applyPaths", + "string": "Query.prototype._applyPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Function" + ], + "name": "js", + "description": "javascript string or function" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "method", + "string": "$where" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $where condition

    \n\n

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    ", + "summary": "

    Specifies a $where condition

    ", + "body": "

    Use $where when you need to select documents using a JavaScript expression.

    \n\n

    Example

    \n\n
    query.$where('this.comments.length > 10 || this.name.length > 5')\n\nquery.$where(function () {\n  return this.comments.length > 10 || this.name.length > 5;\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.$where = function (js) {\n this._conditions['$where'] = js;\n return this;\n};" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[val]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a path for use with chaining.

    \n\n

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    ", + "summary": "

    Specifies a path for use with chaining.

    ", + "body": "

    Example

    \n\n
    // instead of writing:\nUser.find({age: {$gte: 21, $lte: 65}}, callback);\n\n// we can instead write:\nUser.where('age').gte(21).lte(65);\n\n// Moreover, you can also chain a bunch of these together:\n\nUser\n.where('age').gte(21).lte(65)\n.where('name', /^b/i)\n.where('friends').slice(10)\n.exec(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.where = function (path, val) {\n if (!arguments.length) return this;\n\n if ('string' != typeof path) {\n throw new TypeError('path must be a string');\n }\n\n this._currPath = path;\n\n if (2 === arguments.length) {\n this._conditions[path] = val;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "where", + "string": "Query.prototype.where()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the complementary comparison value for paths specified with where()

    \n\n

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    ", + "summary": "

    Specifies the complementary comparison value for paths specified with where()

    ", + "body": "

    Example

    \n\n
    User.where('age').equals(49);\n\n// is the same as\n\nUser.where('age', 49);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.equals = function equals (val) {\n var path = this._currPath;\n if (!path) throw new Error('equals() must be used after where()');\n this._conditions[path] = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "equals", + "string": "Query.prototype.equals()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for an $or condition.

    \n\n

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    ", + "summary": "

    Specifies arguments for an $or condition.

    ", + "body": "

    Example

    \n\n
    query.or([{ color: 'red' }, { status: 'emergency' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.or = function or (array) {\n var or = this._conditions.$or || (this._conditions.$or = []);\n if (!Array.isArray(array)) array = [array];\n or.push.apply(or, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "or", + "string": "Query.prototype.or()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for a $nor condition.

    \n\n

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    ", + "summary": "

    Specifies arguments for a $nor condition.

    ", + "body": "

    Example

    \n\n
    query.nor([{ color: 'green' }, { status: 'ok' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nor = function nor (array) {\n var nor = this._conditions.$nor || (this._conditions.$nor = []);\n if (!Array.isArray(array)) array = [array];\n nor.push.apply(nor, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nor", + "string": "Query.prototype.nor()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "array", + "description": "array of conditions" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies arguments for a $and condition.

    \n\n

    Example

    \n\n
    query.and([{ color: 'green' }, { status: 'ok' }])\n
    ", + "summary": "

    Specifies arguments for a $and condition.

    ", + "body": "

    Example

    \n\n
    query.and([{ color: 'green' }, { status: 'ok' }])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.and = function and (array) {\n var and = this._conditions.$and || (this._conditions.$and = []);\n if (!Array.isArray(array)) array = [array];\n and.push.apply(and, array);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "and", + "string": "Query.prototype.and()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "gt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    ", + "summary": "

    Specifies a $gt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    \n\n

    Example

    \n\n
    Thing.find().where('age').gt(21)\n\n// or\nThing.find().gt('age', 21)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "gte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $gte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $gte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lt" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lt query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lt query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "lte" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $lte query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $lte query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "ne" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $ne query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $ne query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "in" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $in query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $in query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "nin" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $nin query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $nin query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "all" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $all query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $all query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "size" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $size query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies an $size query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "regex" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $regex query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $regex query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxDistance" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $maxDistance query condition.

    \n\n

    When called with one argument, the most recent path passed to where() is used.

    ", + "summary": "

    Specifies a $maxDistance query condition.

    ", + "body": "

    When called with one argument, the most recent path passed to where() is used.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    \n\n
    Thing.where('type').nin(array)\n
    ", + "summary": "

    gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance

    ", + "body": "
    Thing.where('type').nin(array)\n
    " + }, + "ignore": true, + "code": "'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {\n Query.prototype[$conditional] = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$' + $conditional] = val;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $near condition

    ", + "summary": "

    Specifies a $near condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.near = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$near = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "near", + "string": "Query.prototype.near()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $nearSphere condition.

    ", + "summary": "

    Specifies a $nearSphere condition.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.nearSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$nearSphere = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "nearSphere", + "string": "Query.prototype.nearSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $mod condition

    ", + "summary": "

    Specifies a $mod condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.mod = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2 && !Array.isArray(val)) {\n val = utils.args(arguments);\n path = this._currPath;\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds.$mod = val;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "mod", + "string": "Query.prototype.mod()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $exists condition

    ", + "summary": "

    Specifies an $exists condition

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.exists = function (path, val) {\n if (arguments.length === 0) {\n path = this._currPath\n val = true;\n } else if (arguments.length === 1) {\n if ('boolean' === typeof path) {\n val = path;\n path = this._currPath;\n } else {\n val = true;\n }\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$exists'] = val;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "exists", + "string": "Query.prototype.exists()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object", + "Function" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object", + "Function" + ], + "name": "criteria", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies an $elemMatch condition

    \n\n

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    ", + "summary": "

    Specifies an $elemMatch condition

    ", + "body": "

    Example

    \n\n
    query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})\n\nquery.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})\n\nquery.elemMatch('comment', function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n\nquery.where('comment').elemMatch(function (elem) {\n  elem.where('author').equals('autobot');\n  elem.where('votes').gte(5);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.elemMatch = function (path, criteria) {\n var block;\n if ('Object' === path.constructor.name) {\n criteria = path;\n path = this._currPath;\n } else if ('function' === typeof path) {\n block = path;\n path = this._currPath;\n } else if ('Object' === criteria.constructor.name) {\n } else if ('function' === typeof criteria) {\n block = criteria;\n } else {\n throw new Error(\"Argument error\");\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n if (block) {\n criteria = new Query();\n block(criteria);\n conds['$elemMatch'] = criteria._conditions;\n } else {\n conds['$elemMatch'] = criteria;\n }\n return this;\n};\n\n// Spatial queries", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "elemMatch", + "string": "Query.prototype.elemMatch()" + } + }, + { + "tags": [ + { + "type": "property", + "string": "within" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "see", + "local": "Query#box #query_Query-box", + "visibility": "Query#box" + }, + { + "type": "see", + "local": "Query#center #query_Query-center", + "visibility": "Query#center" + }, + { + "type": "see", + "local": "Query#centeSphere #query_Query-centerSphere", + "visibility": "Query#centeSphere" + }, + { + "type": "see", + "local": "Query#polygon #query_Query-polygon", + "visibility": "Query#polygon" + }, + { + "type": "see", + "local": "Query#geometry #query_Query-geometry", + "visibility": "Query#geometry" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a $within query for box(), center(), etc

    \n\n

    Example

    \n\n
    query.within.box()\nquery.within.center()\nquery.within.geometry()\n
    ", + "summary": "

    Defines a $within query for box(), center(), etc

    ", + "body": "

    Example

    \n\n
    query.within.box()\nquery.within.center()\nquery.within.geometry()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Query.prototype, 'within', {\n get: function () {\n this._geoComparison = '$within';\n return this\n }\n});" + }, + { + "tags": [ + { + "type": "property", + "string": "intersects" + }, + { + "type": "see", + "local": "Query#geometry #query_Query-geometry", + "visibility": "Query#geometry" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares an intersects query for geometry().

    \n\n

    Example

    \n\n
    query.intersects.geometry({\n    type: 'LineString'\n  , coordinates: [[180.0, 11.0], [180, 9.0]]\n})\n
    ", + "summary": "

    Declares an intersects query for geometry().

    ", + "body": "

    Example

    \n\n
    query.intersects.geometry({\n    type: 'LineString'\n  , coordinates: [[180.0, 11.0], [180, 9.0]]\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Object.defineProperty(Query.prototype, 'intersects', {\n get: function () {\n this._geoComparison = '$geoIntersects';\n return this\n }\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "see", + "local": "Query#within #query_Query-within", + "visibility": "Query#within" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $box condition

    \n\n

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    ", + "summary": "

    Specifies a $box condition

    ", + "body": "

    Example

    \n\n
    var lowerLeft = [40.73083, -73.99756]\nvar upperRight= [40.741404,  -73.988135]\nquery.where('loc').within.box({ ll: lowerLeft , ur: upperRight })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.box = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$box': [val.ll, val.ur] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "box", + "string": "Query.prototype.box()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[opts]", + "description": "options e.g. { $uniqueDocs: true }" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $center condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    ", + "summary": "

    Specifies a $center condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.center(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.center = function (path, val, opts) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$center': [val.center, val.radius] };\n\n // copy any options\n if (opts && 'Object' == opts.constructor.name) {\n utils.options(opts, conds.$within);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "center", + "string": "Query.prototype.center()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $centerSphere condition

    \n\n

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    ", + "summary": "

    Specifies a $centerSphere condition

    ", + "body": "

    Example

    \n\n
    var area = { center: [50, 50], radius: 10 }\nquery.where('loc').within.centerSphere(area)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.centerSphere = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$centerSphere': [val.center, val.radius] };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "centerSphere", + "string": "Query.prototype.centerSphere()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Array", + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $polygon condition

    \n\n

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    ", + "summary": "

    Specifies a $polygon condition

    ", + "body": "

    Example

    \n\n
    var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]\nquery.where('loc').within.polygon(polyA)\n\n// or\nvar polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }\nquery.where('loc').within.polygon(polyB)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.polygon = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n var conds = this._conditions[path] || (this._conditions[path] = {});\n conds['$within'] = { '$polygon': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "polygon", + "string": "Query.prototype.polygon()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "", + "url": "http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry", + "visibility": "http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry" + }, + { + "type": "see", + "title": "", + "url": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing", + "visibility": "http://www.mongodb.org/display/DOCS/Geospatial+Indexing" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $geometry condition

    \n\n

    Accepts an object that must contain the following two properties

    \n\n
      \n
    • type: String
    • \n
    • coordinates: Array
    • \n
    \n\n

    Example

    \n\n
    var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]]\nquery.where('loc').within.geometry({ type: 'Polygon', coordinates: polyA })\n\n// or\nvar polyB = [[ 0, 0 ], [ 1, 1 ]]\nquery.where('loc').within.geometry({ type: 'LineString', coordinates: polyB })\n\n// or\nvar polyC = [ 0, 0 ]\nquery.where('loc').within.geometry({ type: 'Point', coordinates: polyC })\n\n// or\nvar polyC = [ 0, 0 ]\nquery.where('loc').intersects.geometry({ type: 'Point', coordinates: polyC })\n
    \n\n

    NOTE: Must come after intersects or within.

    ", + "summary": "

    Specifies a $geometry condition

    ", + "body": "

    Accepts an object that must contain the following two properties

    \n\n
      \n
    • type: String
    • \n
    • coordinates: Array
    • \n
    \n\n

    Example

    \n\n
    var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]]\nquery.where('loc').within.geometry({ type: 'Polygon', coordinates: polyA })\n\n// or\nvar polyB = [[ 0, 0 ], [ 1, 1 ]]\nquery.where('loc').within.geometry({ type: 'LineString', coordinates: polyB })\n\n// or\nvar polyC = [ 0, 0 ]\nquery.where('loc').within.geometry({ type: 'Point', coordinates: polyC })\n\n// or\nvar polyC = [ 0, 0 ]\nquery.where('loc').intersects.geometry({ type: 'Point', coordinates: polyC })\n
    \n\n

    NOTE: Must come after intersects or within.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.geometry = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath;\n }\n\n var conds = this._conditions[path] || (this._conditions[path] = {});\n\n if (!this._geoComparison) {\n throw new Error('query.geometry() must come after either `within` or `intersects`');\n }\n\n conds[this._geoComparison] = { $geometry: val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "geometry", + "string": "Query.prototype.geometry()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "local": "SchemaType", + "visibility": "SchemaType" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies which document fields to include or exclude

    \n\n

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    ", + "summary": "

    Specifies which document fields to include or exclude

    ", + "body": "

    When using string syntax, prefixing a path with - will flag that path as excluded. When a path does not have the - prefix, it is included. Lastly, if a path is prefixed with +, it forces inclusion of the path, which is useful for paths excluded at the schema level.

    \n\n

    Example

    \n\n
    // include a and b, exclude c\nquery.select('a b -c');\n\n// or you may use object notation, useful when\n// you have keys already prefixed with a \"-\"\nquery.select({a: 1, b: 1, c: 0});\n\n// force inclusion of field excluded at schema level\nquery.select('+path')\n
    \n\n

    NOTE:

    \n\n

    v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.select = function select (arg) {\n if (!arg) return this;\n\n var fields = this._fields || (this._fields = {});\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n fields[field] = arg[field];\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var include = '-' == field[0] ? 0 : 1;\n if (include === 0) field = field.substring(1);\n fields[field] = include;\n });\n } else {\n throw new TypeError('Invalid select() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "select", + "string": "Query.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "number of elements to slice" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements", + "visibility": "http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies a $slice condition

    \n\n

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    ", + "summary": "

    Specifies a $slice condition

    ", + "body": "

    Example

    \n\n
    query.slice('comments', 5)\nquery.slice('comments', -5)\nquery.slice('comments', [10, 5])\nquery.where('comments').slice(5)\nquery.where('comments').slice([-10, 5])\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slice = function (path, val) {\n if (arguments.length === 1) {\n val = path;\n path = this._currPath\n } else if (arguments.length === 2) {\n if ('number' === typeof path) {\n val = [path, val];\n path = this._currPath;\n }\n } else if (arguments.length === 3) {\n val = utils.args(arguments, 1);\n }\n var myFields = this._fields || (this._fields = {});\n myFields[path] = { '$slice': val };\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slice", + "string": "Query.prototype.slice()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "arg", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the sort order

    \n\n

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    ", + "summary": "

    Sets the sort order

    ", + "body": "

    If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

    \n\n

    If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with - which will be treated as descending.

    \n\n

    Example

    \n\n
    // these are equivalent\nquery.sort({ field: 'asc', test: -1 });\nquery.sort('field -test');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.sort = function (arg) {\n if (!arg) return this;\n\n var sort = this.options.sort || (this.options.sort = []);\n\n if ('Object' === arg.constructor.name) {\n Object.keys(arg).forEach(function (field) {\n push(sort, field, arg[field]);\n });\n } else if (1 === arguments.length && 'string' == typeof arg) {\n arg.split(/\\s+/).forEach(function (field) {\n if (!field) return;\n var ascend = '-' == field[0] ? -1 : 1;\n if (ascend === -1) field = field.substring(1);\n push(sort, field, ascend);\n });\n } else {\n throw new TypeError('Invalid sort() argument. Must be a string or object.');\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "sort", + "string": "Query.prototype.sort()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function push (arr, field, value) {\n var val = String(value || 1).toLowerCase();\n if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {\n if (Array.isArray(value)) value = '['+value+']';\n throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');\n }\n arr.push([field, value]);\n}", + "ctx": { + "type": "function", + "name": "push", + "string": "push()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "limit" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the limit option.

    \n\n

    Example

    \n\n
    Kitten.find().limit(20)\n
    ", + "summary": "

    Specifies the limit option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "skip" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the skip option.

    \n\n

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    ", + "summary": "

    Specifies the skip option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().skip(100).limit(20)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "maxscan" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the maxscan option.

    \n\n

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    ", + "summary": "

    Specifies the maxscan option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().maxscan(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "batchSize" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the batchSize option.

    \n\n

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    ", + "summary": "

    Specifies the batchSize option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().batchSize(100)\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [ + { + "type": "method", + "string": "comment" + }, + { + "type": "memberOf", + "parent": "Query" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "val", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies the comment option.

    \n\n

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    ", + "summary": "

    Specifies the comment option.

    ", + "body": "

    Example

    \n\n
    Kitten.findOne(condition).comment('login query')\n
    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    limit, skip, maxscan, batchSize, comment

    \n\n

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    ", + "summary": "

    limit, skip, maxscan, batchSize, comment

    ", + "body": "

    Sets these associated options.

    \n\n
    query.comment('feed query');\n
    " + }, + "ignore": true, + "code": ";['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {\n Query.prototype[method] = function (v) {\n this.options[method] = v;\n return this;\n };\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies this query as a snapshot query.

    \n\n

    Example

    \n\n
    Kitten.find().snapshot()\n
    ", + "summary": "

    Specifies this query as a snapshot query.

    ", + "body": "

    Example

    \n\n
    Kitten.find().snapshot()\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.snapshot = function () {\n this.options.snapshot = true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "snapshot", + "string": "Query.prototype.snapshot()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "a hint object" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint", + "visibility": "http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets query hints.

    \n\n

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    ", + "summary": "

    Sets query hints.

    ", + "body": "

    Example

    \n\n
    Model.find().hint({ indexA: 1, indexB: -1})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.hint = function (val) {\n if (!val) return this;\n\n var hint = this.options.hint || (this.options.hint = {});\n\n if ('Object' === val.constructor.name) {\n // must keep object keys in order so don't use Object.keys()\n for (var k in val) {\n hint[k] = val[k];\n }\n } else {\n throw new TypeError('Invalid hint. ' + val);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "hint", + "string": "Query.prototype.hint()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the slaveOk option.

    \n\n

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    ", + "summary": "

    Sets the slaveOk option.

    ", + "body": "

    Example:

    \n\n
    new Query().slaveOk() // true\nnew Query().slaveOk(true)\nnew Query().slaveOk(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.slaveOk = function (v) {\n this.options.slaveOk = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "slaveOk", + "string": "Query.prototype.slaveOk()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "one of the listed preference options or their aliases" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "[tags]", + "description": "optional tags for this query" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://docs.mongodb.org/manual/applications/replication/#read-preference", + "visibility": "http://docs.mongodb.org/manual/applications/replication/#read-preference" + }, + { + "type": "see", + "title": "driver", + "url": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences", + "visibility": "http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the readPreference option for the query.

    \n\n

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    ", + "summary": "

    Sets the readPreference option for the query.

    ", + "body": "

    Example:

    \n\n
    new Query().read('primary')\nnew Query().read('p')  // same as primary\n\nnew Query().read('primaryPreferred')\nnew Query().read('pp') // same as primaryPreferred\n\nnew Query().read('secondary')\nnew Query().read('s')  // same as secondary\n\nnew Query().read('secondaryPreferred')\nnew Query().read('sp') // same as secondaryPreferred\n\nnew Query().read('nearest')\nnew Query().read('n')  // same as nearest\n\n// with tags\nnew Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])\n
    \n\n

    Preferences:

    \n\n
    primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.\nsecondary            Read from secondary if available, otherwise error.\nprimaryPreferred     Read from primary if available, otherwise a secondary.\nsecondaryPreferred   Read from a secondary if available, otherwise read from the primary.\nnearest              All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.\n
    \n\n

    Aliases

    \n\n
    p   primary\npp  primaryPreferred\ns   secondary\nsp  secondaryPreferred\nn   nearest\n
    \n\n

    Read more about how to use read preferrences here and here.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.read = function (pref, tags) {\n this.options.readPreference = utils.readPref(pref, tags);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "read", + "string": "Query.prototype.read()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the lean option.

    \n\n

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    ", + "summary": "

    Sets the lean option.

    ", + "body": "

    Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or any other Mongoose magic applied.

    \n\n

    This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

    \n\n

    Example:

    \n\n
    new Query().lean() // true\nnew Query().lean(true)\nnew Query().lean(false)\n\nModel.find().lean().exec();\n\nvar leanStream = Model.find().lean().stream();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.lean = function (v) {\n this.options.lean = arguments.length ? !!v : true;\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "lean", + "string": "Query.prototype.lean()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "v", + "description": "defaults to true" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Tailable+Cursors", + "visibility": "http://www.mongodb.org/display/DOCS/Tailable+Cursors" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets tailable option.

    \n\n

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    ", + "summary": "

    Sets tailable option.

    ", + "body": "

    Example

    \n\n
    Kitten.find().tailable() <== true\nKitten.find().tailable(true)\nKitten.find().tailable(false)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.tailable = function (v) {\n this.options.tailable = arguments.length ? !!v : true;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "tailable", + "string": "Query.prototype.tailable()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Executes the query as a find() operation.

    ", + "summary": "

    Executes the query as a find() operation.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype.execFind = function (callback) {\n var model = this.model\n , promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.find(castQuery, options, function (err, cursor) {\n if (err) return promise.error(err);\n cursor.toArray(tick(cb));\n });\n\n function cb (err, docs) {\n if (err) return promise.error(err);\n\n if (0 === docs.length) {\n return promise.complete(docs);\n }\n\n if (!self.options.populate) {\n return true === options.lean\n ? promise.complete(docs)\n : completeMany(model, docs, fields, self, null, promise);\n }\n\n var pop = preparePopulationOptions(self, options);\n model.populate(docs, pop, function (err, docs) {\n if (err) return promise.error(err);\n return true === options.lean\n ? promise.complete(docs)\n : completeMany(model, docs, fields, self, pop, promise);\n });\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "execFind", + "string": "Query.prototype.execFind()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "docs", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "param", + "types": [ + "Query" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "[pop]", + "description": "array of paths used in population" + }, + { + "type": "param", + "types": [ + "Promise" + ], + "name": "promise", + "description": "" + } + ], + "description": { + "full": "

    hydrates many documents

    ", + "summary": "

    hydrates many documents

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function completeMany (model, docs, fields, self, pop, promise) {\n var arr = [];\n var count = docs.length;\n var len = count;\n var i = 0;\n var opts = pop ?\n { populated: pop }\n : undefined;\n\n for (; i < len; ++i) {\n arr[i] = new model(undefined, fields, true);\n arr[i].init(docs[i], opts, function (err) {\n if (err) return promise.error(err);\n --count || promise.complete(arr);\n });\n }\n}", + "ctx": { + "type": "function", + "name": "completeMany", + "string": "completeMany()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes the query as a findOne() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    ", + "summary": "

    Executes the query as a findOne() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'white').findOne(function (err, kitten) {\n  if (err) return handleError(err);\n\n  // kitten may be null if no document matched\n  if (kitten) {\n    ...\n  }\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOne = function (callback) {\n this.op = 'findOne';\n\n if (!callback) return this;\n\n var model = this.model;\n var promise = new Promise(callback);\n\n try {\n this.cast(model);\n } catch (err) {\n promise.error(err);\n return this;\n }\n\n // apply default schematype path selections\n this._applyPaths();\n\n var self = this\n , castQuery = this._conditions\n , options = this._optionsForExec(model)\n , fields = utils.clone(this._fields)\n\n options.fields = this._castFields(fields);\n if (options.fields instanceof Error) {\n promise.error(options.fields);\n return this;\n }\n\n model.collection.findOne(castQuery, options, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (!self.options.populate) {\n return true === options.lean\n ? promise.complete(doc)\n : completeOne(model, doc, fields, self, null, promise);\n }\n\n var pop = preparePopulationOptions(self, options);\n model.populate(doc, pop, function (err, doc) {\n if (err) return promise.error(err);\n return true === options.lean\n ? promise.complete(doc)\n : completeOne(model, doc, fields, self, pop, promise);\n })\n }));\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOne", + "string": "Query.prototype.findOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + } + ], + "description": { + "full": "

    Prepare a set of path options for query population.

    ", + "summary": "

    Prepare a set of path options for query population.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function preparePopulationOptions (query, options) {\n var pop = utils.object.vals(query.options.populate);\n\n // lean options should trickle through all queries\n if (options.lean) pop.forEach(makeLean);\n\n return pop;\n}", + "ctx": { + "type": "function", + "name": "preparePopulationOptions", + "string": "preparePopulationOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "option", + "description": "" + } + ], + "description": { + "full": "

    Set each path query option to lean

    ", + "summary": "

    Set each path query option to lean

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function makeLean (option) {\n option.options || (option.options = {});\n option.options.lean = true;\n}", + "ctx": { + "type": "function", + "name": "makeLean", + "string": "makeLean()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Model" + ], + "name": "model", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "param", + "types": [ + "Query" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "[pop]", + "description": "array of paths used in population" + }, + { + "type": "param", + "types": [ + "Promise" + ], + "name": "promise", + "description": "" + } + ], + "description": { + "full": "

    hydrates a document

    ", + "summary": "

    hydrates a document

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function completeOne (model, doc, fields, self, pop, promise) {\n var opts = pop ?\n { populated: pop }\n : undefined;\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, opts, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n}", + "ctx": { + "type": "function", + "name": "completeOne", + "string": "completeOne()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Exectues the query as a count() operation.

    \n\n

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    ", + "summary": "

    Exectues the query as a count() operation.

    ", + "body": "

    Example

    \n\n
    Kitten.where('color', 'black').count(function (err, count) {\n  if (err) return handleError(err);\n  console.log('there are %d black kittens', count);\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.count = function (callback) {\n this.op = 'count';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.count(castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "count", + "string": "Query.prototype.count()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "field", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct", + "visibility": "http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a distict() operation.

    ", + "summary": "

    Executes this query as a distict() operation.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.distinct = function (field, callback) {\n this.op = 'distinct';\n var model = this.model;\n\n try {\n this.cast(model);\n } catch (err) {\n return callback(err);\n }\n\n var castQuery = this._conditions;\n model.collection.distinct(field, castQuery, tick(callback));\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "distinct", + "string": "Query.prototype.distinct()" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "summary": "

    These operators require casting docs
    to real Documents for Update operations.

    ", + "body": "" + }, + "ignore": true, + "code": "var castOps = {\n $push: 1\n , $pushAll: 1\n , $addToSet: 1\n , $set: 1\n};", + "ctx": { + "type": "declaration", + "name": "castOps", + "value": "{", + "string": "castOps" + } + }, + { + "tags": [], + "description": { + "full": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "summary": "

    These operators should be cast to numbers instead
    of their path schema type.

    ", + "body": "" + }, + "ignore": true, + "code": "var numberOps = {\n $pop: 1\n , $unset: 1\n , $inc: 1\n}", + "ctx": { + "type": "declaration", + "name": "numberOps", + "value": "{", + "string": "numberOps" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "the update conditions" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as an update() operation.

    \n\n

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    ", + "summary": "

    Executes this query as an update() operation.

    ", + "body": "

    All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    \n\n

    Example

    \n\n
    Model.update({..}, { title: 'remove words' }, ...)\n
    \n\n

    becomes

    \n\n
    Model.update({..}, { $set: { title: 'remove words' }}, ...)\n
    \n\n

    Note

    \n\n

    Passing an empty object {} as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.update = function update (doc, callback) {\n this.op = 'update';\n this._updateArg = doc;\n\n var model = this.model\n , options = this._optionsForExec(model)\n , fn = 'function' == typeof callback\n , castedQuery\n , castedDoc\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedQuery));\n return this;\n }\n throw castedQuery;\n }\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n fn && process.nextTick(callback.bind(null, null, 0));\n return this;\n }\n\n if (castedDoc instanceof Error) {\n if (fn) {\n process.nextTick(callback.bind(null, castedDoc));\n return this;\n }\n throw castedDoc;\n }\n\n if (!fn) {\n options.safe = { w: 0 };\n }\n\n model.collection.update(castedQuery, castedDoc, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "update", + "string": "Query.prototype.update()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "obj after casting its values" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts obj for an update command.

    ", + "summary": "

    Casts obj for an update command.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdate = function _castUpdate (obj) {\n var ops = Object.keys(obj)\n , i = ops.length\n , ret = {}\n , hasKeys\n , val\n\n while (i--) {\n var op = ops[i];\n if ('$' !== op[0]) {\n // fix up $set sugar\n if (!ret.$set) {\n if (obj.$set) {\n ret.$set = obj.$set;\n } else {\n ret.$set = {};\n }\n }\n ret.$set[op] = obj[op];\n ops.splice(i, 1);\n if (!~ops.indexOf('$set')) ops.push('$set');\n } else if ('$set' === op) {\n if (!ret.$set) {\n ret[op] = obj[op];\n }\n } else {\n ret[op] = obj[op];\n }\n }\n\n // cast each value\n i = ops.length;\n\n while (i--) {\n op = ops[i];\n val = ret[op];\n if ('Object' === val.constructor.name) {\n hasKeys |= this._walkUpdatePath(val, op);\n } else {\n var msg = 'Invalid atomic update value for ' + op + '. '\n + 'Expected an object, received ' + typeof val;\n throw new Error(msg);\n }\n }\n\n return hasKeys && ret;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdate", + "string": "Query.prototype._castUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "- part of a query" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "pref", + "description": "- path prefix (internal only)" + }, + { + "type": "return", + "types": [ + "Bool" + ], + "description": "true if this path has keys to update" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "summary": "

    Walk each path of obj and cast its values
    according to its schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {\n var prefix = pref ? pref + '.' : ''\n , keys = Object.keys(obj)\n , i = keys.length\n , hasKeys = false\n , schema\n , key\n , val\n\n var strict = 'strict' in this.options\n ? this.options.strict\n : this.model.schema.options.strict;\n\n while (i--) {\n key = keys[i];\n val = obj[key];\n\n if (val && 'Object' === val.constructor.name) {\n // watch for embedded doc schemas\n schema = this._getSchema(prefix + key);\n if (schema && schema.caster && op in castOps) {\n // embedded doc schema\n\n if (strict && !schema) {\n // path is not in our strict schema\n if ('throw' == strict) {\n throw new Error('Field `' + key + '` is not in schema.');\n } else {\n // ignore paths not specified in schema\n delete obj[key];\n }\n } else {\n hasKeys = true;\n\n if ('$each' in val) {\n obj[key] = {\n $each: this._castUpdateVal(schema, val.$each, op)\n }\n\n if (val.$slice) {\n obj[key].$slice = val.$slice | 0;\n }\n\n if (val.$sort) {\n obj[key].$sort = val.$sort;\n }\n\n } else {\n obj[key] = this._castUpdateVal(schema, val, op);\n }\n }\n } else {\n hasKeys |= this._walkUpdatePath(val, op, prefix + key);\n }\n } else {\n schema = '$each' === key\n ? this._getSchema(pref)\n : this._getSchema(prefix + key);\n\n var skip = strict &&\n !schema &&\n !/real|nested/.test(this.model.schema.pathType(prefix + key));\n\n if (skip) {\n if ('throw' == strict) {\n throw new Error('Field `' + prefix + key + '` is not in schema.');\n } else {\n delete obj[key];\n }\n } else {\n hasKeys = true;\n obj[key] = this._castUpdateVal(schema, val, op, key);\n }\n }\n }\n return hasKeys;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_walkUpdatePath", + "string": "Query.prototype._walkUpdatePath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "op", + "description": "- the atomic operator ($pull, $set, etc)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[$conditional]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val according to schema and atomic op.

    ", + "summary": "

    Casts val according to schema and atomic op.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {\n if (!schema) {\n // non-existing schema path\n return op in numberOps\n ? Number(val)\n : val\n }\n\n if (schema.caster && op in castOps &&\n ('Object' === val.constructor.name || Array.isArray(val))) {\n // Cast values for ops that add data to MongoDB.\n // Ensures embedded documents get ObjectIds etc.\n var tmp = schema.cast(val);\n\n if (Array.isArray(val)) {\n val = tmp;\n } else {\n val = tmp[0];\n }\n }\n\n if (op in numberOps) return Number(val);\n if (/^\\$/.test($conditional)) return schema.castForQuery($conditional, val);\n return schema.castForQuery(val)\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castUpdateVal", + "string": "Query.prototype._castUpdateVal()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "summary": "

    Finds the schema for path. This is different than
    calling schema.path as it also resolves paths with
    positional selectors (something.$.another.$.path).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._getSchema = function _getSchema (path) {\n return this.model._getSchema(path);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_getSchema", + "string": "Query.prototype._getSchema()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "see", + "title": "", + "url": "https://github.com/LearnBoost/mongoose/issues/1091", + "visibility": "https://github.com/LearnBoost/mongoose/issues/1091" + }, + { + "type": "see", + "title": "", + "url": "http://docs.mongodb.org/manual/reference/projection/elemMatch/", + "visibility": "http://docs.mongodb.org/manual/reference/projection/elemMatch/" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts selected field arguments for field selection with mongo 2.2

    \n\n
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    ", + "summary": "

    Casts selected field arguments for field selection with mongo 2.2

    ", + "body": "
    query.select({ ids: { $elemMatch: { $in: [hexString] }})\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._castFields = function _castFields (fields) {\n var selected\n , elemMatchKeys\n , keys\n , key\n , out\n , i\n\n if (fields) {\n keys = Object.keys(fields);\n elemMatchKeys = [];\n i = keys.length;\n\n // collect $elemMatch args\n while (i--) {\n key = keys[i];\n if (fields[key].$elemMatch) {\n selected || (selected = {});\n selected[key] = fields[key];\n elemMatchKeys.push(key);\n }\n }\n }\n\n if (selected) {\n // they passed $elemMatch, cast em\n try {\n out = this.cast(this.model, selected);\n } catch (err) {\n return err;\n }\n\n // apply the casted field args\n i = elemMatchKeys.length;\n while (i--) {\n key = elemMatchKeys[i];\n fields[key] = out[key];\n }\n }\n\n return fields;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_castFields", + "string": "Query.prototype._castFields()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Executes this query as a remove() operation.

    \n\n

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    ", + "summary": "

    Executes this query as a remove() operation.

    ", + "body": "

    Example

    \n\n
    Cassette.where('artist').equals('Anne Murray').remove(callback)\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.remove = function (callback) {\n this.op = 'remove';\n\n var model = this.model\n , options = this._optionsForExec(model)\n , cb = 'function' == typeof callback\n\n try {\n this.cast(model);\n } catch (err) {\n if (cb) return callback(err);\n throw err;\n }\n\n if (!cb) {\n options.safe = { w: 0 };\n }\n\n var castQuery = this._conditions;\n model.collection.remove(castQuery, options, tick(callback));\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "remove", + "string": "Query.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[query]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[doc]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify update command.

    \n\n

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify update command.

    ", + "body": "

    Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • new: bool - true to return the modified document rather than the original. defaults to true
    • \n
    • upsert: bool - creates the object if it doesn't exist. defaults to false.
    • \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    query.findOneAndUpdate(conditions, update, options, callback) // executes\nquery.findOneAndUpdate(conditions, update, options)  // returns Query\nquery.findOneAndUpdate(conditions, update, callback) // executes\nquery.findOneAndUpdate(conditions, update)           // returns Query\nquery.findOneAndUpdate(callback)                     // executes\nquery.findOneAndUpdate()                             // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {\n this.op = 'findOneAndUpdate';\n\n switch (arguments.length) {\n case 3:\n if ('function' == typeof options)\n callback = options, options = {};\n break;\n case 2:\n if ('function' == typeof doc) {\n callback = doc;\n doc = query;\n query = undefined;\n }\n options = undefined;\n break;\n case 1:\n if ('function' == typeof query) {\n callback = query;\n query = options = doc = undefined;\n } else {\n doc = query;\n query = options = undefined;\n }\n }\n\n // apply query\n if (query) {\n if ('Object' === query.constructor.name) {\n merge(this._conditions, query);\n } else if (query instanceof Query) {\n merge(this._conditions, query._conditions);\n } else if (query instanceof Document) {\n merge(this._conditions, query.toObject());\n }\n }\n\n // apply doc\n if (doc) {\n merge(this._updateArg, doc);\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('update', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndUpdate", + "string": "Query.prototype.findOneAndUpdate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[conditions]", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[callback]", + "description": "" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/findAndModify+Command", + "visibility": "http://www.mongodb.org/display/DOCS/findAndModify+Command" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Issues a mongodb findAndModify remove command.

    \n\n

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    ", + "summary": "

    Issues a mongodb findAndModify remove command.

    ", + "body": "

    Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed else a Query object is returned.

    \n\n

    Available options

    \n\n
      \n
    • sort: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
    • \n
    \n\n

    Examples

    \n\n
    A.where().findOneAndRemove(conditions, options, callback) // executes\nA.where().findOneAndRemove(conditions, options)  // return Query\nA.where().findOneAndRemove(conditions, callback) // executes\nA.where().findOneAndRemove(conditions) // returns Query\nA.where().findOneAndRemove(callback)   // executes\nA.where().findOneAndRemove()           // returns Query\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.findOneAndRemove = function (conditions, options, callback) {\n this.op = 'findOneAndRemove';\n\n if ('function' == typeof options) {\n callback = options;\n options = undefined;\n } else if ('function' == typeof conditions) {\n callback = conditions;\n conditions = undefined;\n }\n\n // apply conditions\n if (conditions) {\n if ('Object' === conditions.constructor.name) {\n merge(this._conditions, conditions);\n } else if (conditions instanceof Query) {\n merge(this._conditions, conditions._conditions);\n } else if (conditions instanceof Document) {\n merge(this._conditions, conditions.toObject());\n }\n }\n\n // apply options\n options && this.setOptions(options);\n\n if (!callback) return this;\n\n return this._findAndModify('remove', callback);\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "findOneAndRemove", + "string": "Query.prototype.findOneAndRemove()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "type", + "description": "- either \"remove\" or \"update\"" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    _findAndModify

    ", + "summary": "

    _findAndModify

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Query.prototype._findAndModify = function (type, callback) {\n var model = this.model\n , promise = new Promise(callback)\n , self = this\n , castedQuery\n , castedDoc\n , fields\n , sort\n , opts\n\n castedQuery = castQuery(this);\n if (castedQuery instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedQuery));\n return promise;\n }\n\n opts = this._optionsForExec(model);\n\n if ('remove' == type) {\n opts.remove = true;\n } else {\n if (!('new' in opts)) opts.new = true;\n if (!('upsert' in opts)) opts.upsert = false;\n\n castedDoc = castDoc(this);\n if (!castedDoc) {\n if (opts.upsert) {\n // still need to do the upsert to empty doc\n castedDoc = { $set: {} };\n } else {\n return this.findOne(callback);\n }\n } else if (castedDoc instanceof Error) {\n process.nextTick(promise.error.bind(promise, castedDoc));\n return promise;\n }\n }\n\n this._applyPaths();\n\n if (this._fields) {\n fields = utils.clone(this._fields)\n opts.fields = this._castFields(fields);\n if (opts.fields instanceof Error) {\n process.nextTick(promise.error.bind(promise, opts.fields));\n return promise;\n }\n }\n\n // the driver needs a default\n sort = opts.sort || [];\n\n model\n .collection\n .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {\n if (err) return promise.error(err);\n if (!doc) return promise.complete(null);\n\n if (true === opts.lean) {\n return promise.complete(doc);\n }\n\n var casted = new model(undefined, fields, true);\n casted.init(doc, function (err) {\n if (err) return promise.error(err);\n promise.complete(casted);\n });\n }));\n\n return promise;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "_findAndModify", + "string": "Query.prototype._findAndModify()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "path", + "description": "either the path to populate or an object specifying all parameters" + }, + { + "type": "param", + "types": [ + "Object", + "String" + ], + "name": "[select]", + "description": "Field selection for the population query" + }, + { + "type": "param", + "types": [ + "Model" + ], + "name": "[model]", + "description": "The name of the model you wish to use for population. If not specified, the name is looked up from the Schema [ref](./populate.html)." + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[match]", + "description": "Conditions for the population query" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "Options for the population query (sort, etc)" + }, + { + "type": "see", + "local": "population ./populate.html", + "visibility": "population" + }, + { + "type": "see", + "local": "Query#select #query_Query-select", + "visibility": "Query#select" + }, + { + "type": "return", + "types": [ + "Query" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Specifies paths which should be populated with other documents.

    \n\n

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n\nKitten.find().populate({\n    path: 'owner'\n  , select: 'name'\n  , match: { color: 'black' }\n  , options: { sort: { name: -1 }}\n}).exec(function (err, kittens) {\n  console.log(kittens[0].owner.name) // Zoopa\n})\n\n// alternatively\nKitten.find().populate('owner', 'name', null, {sort: { name: -1 }}).exec(function (err, kittens) {\n  console.log(kittens[0].owner.name) // Zoopa\n})\n
    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    ", + "summary": "

    Specifies paths which should be populated with other documents.

    ", + "body": "

    Example:

    \n\n
    Kitten.findOne().populate('owner').exec(function (err, kitten) {\n  console.log(kitten.owner.name) // Max\n})\n\nKitten.find().populate({\n    path: 'owner'\n  , select: 'name'\n  , match: { color: 'black' }\n  , options: { sort: { name: -1 }}\n}).exec(function (err, kittens) {\n  console.log(kittens[0].owner.name) // Zoopa\n})\n\n// alternatively\nKitten.find().populate('owner', 'name', null, {sort: { name: -1 }}).exec(function (err, kittens) {\n  console.log(kittens[0].owner.name) // Zoopa\n})\n
    \n\n

    Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.populate = function populate () {\n var res = utils.populate.apply(null, arguments);\n var opts = this.options;\n\n if (!utils.isObject(opts.populate)) {\n opts.populate = {};\n }\n\n for (var i = 0; i < res.length; ++i) {\n opts.populate[res[i].path] = res[i];\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "populate", + "string": "Query.prototype.populate()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "QueryStream" + ], + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "see", + "local": "QueryStream", + "visibility": "QueryStream" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a Node.js 0.8 style read stream interface.

    \n\n

    Example

    \n\n
    // follows the nodejs 0.8 stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    Valid options

    \n\n
      \n
    • transform: optional function which accepts a mongoose document. The return value of the function will be emitted.
    • \n
    \n\n

    Example

    \n\n
    // JSON.stringify all documents before emitting\nvar stream = Thing.find().stream({ transform: JSON.stringify });\nstream.pipe(writeStream);\n
    ", + "summary": "

    Returns a Node.js 0.8 style read stream interface.

    ", + "body": "

    Example

    \n\n
    // follows the nodejs 0.8 stream api\nThing.find({ name: /^hello/ }).stream().pipe(res)\n\n// manual streaming\nvar stream = Thing.find({ name: /^hello/ }).stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    Valid options

    \n\n
      \n
    • transform: optional function which accepts a mongoose document. The return value of the function will be emitted.
    • \n
    \n\n

    Example

    \n\n
    // JSON.stringify all documents before emitting\nvar stream = Thing.find().stream({ transform: JSON.stringify });\nstream.pipe(writeStream);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Query.prototype.stream = function stream (opts) {\n return new QueryStream(this, opts);\n}\n\n// helpers", + "ctx": { + "type": "method", + "constructor": "Query", + "name": "stream", + "string": "Query.prototype.stream()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castDoc

    ", + "summary": "

    castDoc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castDoc (query) {\n try {\n return query._castUpdate(query._updateArg);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castDoc", + "string": "castDoc()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    castQuery

    ", + "summary": "

    castQuery

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function castQuery (query) {\n try {\n return query.cast(query.model);\n } catch (err) {\n return err;\n }\n}", + "ctx": { + "type": "function", + "name": "castQuery", + "string": "castQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Exports.

    ", + "summary": "

    Exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Query;\nmodule.exports.QueryStream = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Query", + "string": "module.exports" + } + } +] +### lib/querystream.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Stream = require('stream').Stream\nvar utils = require('./utils')\nvar K = function(k){ return k }", + "ctx": { + "type": "declaration", + "name": "Stream", + "value": "require('stream').Stream", + "string": "Stream" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Query" + ], + "name": "query", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS Stream http://nodejs.org/docs/v0.8.21/api/stream.html#stream_readable_stream" + }, + { + "type": "event", + "string": "`data`: emits a single Mongoose document" + }, + { + "type": "event", + "string": "`error`: emits when an error occurs during streaming. This will emit _before_ the `close` event." + }, + { + "type": "event", + "string": "`close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Provides a Node.js 0.8 style ReadStream interface for Queries.

    \n\n
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node.js 0.8 style write streams.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    \n\n

    NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary.

    \n\n

    NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work.

    ", + "summary": "

    Provides a Node.js 0.8 style ReadStream interface for Queries.

    ", + "body": "
    var stream = Model.find().stream();\n\nstream.on('data', function (doc) {\n  // do something with the mongoose document\n}).on('error', function (err) {\n  // handle the error\n}).on('close', function () {\n  // the stream is closed\n});\n
    \n\n

    The stream interface allows us to simply \"plug-in\" to other Node.js 0.8 style write streams.

    \n\n
    Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);\n
    \n\n

    NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary.

    \n\n

    NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function QueryStream (query, options) {\n Stream.call(this);\n\n this.query = query;\n this.readable = true;\n this.paused = false;\n this._cursor = null;\n this._destroyed = null;\n this._fields = null;\n this._buffer = null;\n this._inline = T_INIT;\n this._running = false;\n this._transform = options && 'function' == typeof options.transform\n ? options.transform\n : K;\n\n // give time to hook up events\n var self = this;\n process.nextTick(function () {\n self._init();\n });\n}", + "ctx": { + "type": "function", + "name": "QueryStream", + "string": "QueryStream()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Stream

    ", + "summary": "

    Inherit from Stream

    ", + "body": "" + }, + "ignore": true, + "code": "QueryStream.prototype.__proto__ = Stream.prototype;", + "ctx": { + "type": "property", + "constructor": "QueryStream", + "name": "__proto__", + "value": "Stream.prototype", + "string": "QueryStream.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "property", + "string": "readable" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is readable.

    ", + "summary": "

    Flag stating whether or not this stream is readable.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.readable;" + }, + { + "tags": [ + { + "type": "property", + "string": "paused" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Flag stating whether or not this stream is paused.

    ", + "summary": "

    Flag stating whether or not this stream is paused.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.paused;\n\n// trampoline flags\nvar T_INIT = 0;\nvar T_IDLE = 1;\nvar T_CONT = 2;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Initializes the query.

    ", + "summary": "

    Initializes the query.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._init = function () {\n if (this._destroyed) return;\n\n var query = this.query\n , model = query.model\n , options = query._optionsForExec(model)\n , self = this\n\n try {\n query.cast(model);\n } catch (err) {\n return self.destroy(err);\n }\n\n self._fields = utils.clone(query._fields);\n options.fields = query._castFields(self._fields);\n\n model.collection.find(query._conditions, options, function (err, cursor) {\n if (err) return self.destroy(err);\n self._cursor = cursor;\n self._next();\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_init", + "string": "QueryStream.prototype._init()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#__next #querystream_QueryStream-__next", + "visibility": "QueryStream#__next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Trampoline for pulling the next doc from cursor.

    ", + "summary": "

    Trampoline for pulling the next doc from cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._next = function _next () {\n if (this.paused || this._destroyed) {\n return this._running = false;\n }\n\n this._running = true;\n\n if (this._buffer && this._buffer.length) {\n var arg;\n while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {\n this._onNextObject.apply(this, arg);\n }\n }\n\n // avoid stack overflows with large result sets.\n // trampoline instead of recursion.\n while (this.__next()) {}\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_next", + "string": "QueryStream.prototype._next()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "QueryStream#_next #querystream_QueryStream-_next", + "visibility": "QueryStream#_next" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pulls the next doc from the cursor.

    ", + "summary": "

    Pulls the next doc from the cursor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype.__next = function () {\n if (this.paused || this._destroyed)\n return this._running = false;\n\n var self = this;\n self._inline = T_INIT;\n\n self._cursor.nextObject(function cursorcb (err, doc) {\n self._onNextObject(err, doc);\n });\n\n // if onNextObject() was already called in this tick\n // return ourselves to the trampoline.\n if (T_CONT === this._inline) {\n return true;\n } else {\n // onNextObject() hasn't fired yet. tell onNextObject\n // that its ok to call _next b/c we are not within\n // the trampoline anymore.\n this._inline = T_IDLE;\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "__next", + "string": "QueryStream.prototype.__next()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error", + "null" + ], + "name": "err", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "summary": "

    Transforms raw docs returned from the cursor into a model instance.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {\n if (this._destroyed) return;\n\n if (this.paused) {\n this._buffer || (this._buffer = []);\n this._buffer.push([err, doc]);\n return this._running = false;\n }\n\n if (err) return this.destroy(err);\n\n // when doc is null we hit the end of the cursor\n if (!doc) {\n this.emit('end');\n return this.destroy();\n }\n\n if (this.query.options && true === this.query.options.lean) {\n this.emit('data', this._transform(doc));\n\n // trampoline management\n if (T_IDLE === this._inline) {\n // no longer in trampoline. restart it.\n this._next();\n } else {\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n this._inline = T_CONT;\n }\n return;\n }\n\n var instance = new this.query.model(undefined, this._fields, true);\n\n var self = this;\n instance.init(doc, function (err) {\n if (err) return self.destroy(err);\n self.emit('data', self._transform(instance));\n\n // trampoline management\n if (T_IDLE === self._inline) {\n // no longer in trampoline. restart it.\n self._next();\n } else\n // in a trampoline. tell __next that its\n // ok to continue jumping.\n self._inline = T_CONT;\n });\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "_onNextObject", + "string": "QueryStream.prototype._onNextObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pauses this stream.

    ", + "summary": "

    Pauses this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.pause = function () {\n this.paused = true;\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "pause", + "string": "QueryStream.prototype.pause()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Resumes this stream.

    ", + "summary": "

    Resumes this stream.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.resume = function () {\n this.paused = false;\n\n if (!this._cursor) {\n // cannot start if not initialized\n return;\n }\n\n // are we within the trampoline?\n if (T_INIT === this._inline) {\n return;\n }\n\n if (!this._running) {\n // outside QueryStream control, need manual restart\n return this._next();\n }\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "resume", + "string": "QueryStream.prototype.resume()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Error" + ], + "name": "[err]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "summary": "

    Destroys the stream, closing the underlying cursor. No more events will be emitted.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "QueryStream.prototype.destroy = function (err) {\n if (this._destroyed) return;\n this._destroyed = true;\n this._running = false;\n this.readable = false;\n\n if (this._cursor) {\n this._cursor.close();\n }\n\n if (err) {\n this.emit('error', err);\n }\n\n this.emit('close');\n}", + "ctx": { + "type": "method", + "constructor": "QueryStream", + "name": "destroy", + "string": "QueryStream.prototype.destroy()" + } + }, + { + "tags": [ + { + "type": "method", + "string": "pipe" + }, + { + "type": "memberOf", + "parent": "QueryStream" + }, + { + "type": "see", + "title": "NodeJS", + "url": "http://nodejs.org/api/stream.html", + "visibility": "http://nodejs.org/api/stream.html" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    \n\n

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    ", + "summary": "

    Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

    ", + "body": "

    Example:

    \n\n
    query.stream().pipe(writeStream [, options])\n
    \n\n

    This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

    \n\n
    var format = new ArrayFormatter;\nEvents.find().stream().pipe(format).pipe(res);\n
    \n\n

    As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

    " + }, + "isPrivate": false, + "ignore": false + }, + { + "tags": [], + "description": { + "full": "

    Module exports

    ", + "summary": "

    Module exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = QueryStream;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = QueryStream", + "string": "module.exports" + } + } +] +### lib/schema/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , NumberSchema = require('./number')\n , Types = {\n Boolean: require('./boolean')\n , Date: require('./date')\n , Number: require('./number')\n , String: require('./string')\n , ObjectId: require('./objectid')\n , Buffer: require('./buffer')\n }\n , MongooseArray = require('../types').Array\n , EmbeddedDoc = require('../types').Embedded\n , Mixed = require('./mixed')\n , Query = require('../query')\n , isMongooseObject = require('../utils').isMongooseObject", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Array SchemaType constructor

    ", + "summary": "

    Array SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaArray (key, cast, options) {\n if (cast) {\n var castOptions = {};\n\n if ('Object' === cast.constructor.name) {\n if (cast.type) {\n // support { type: Woot }\n castOptions = cast;\n cast = cast.type;\n delete castOptions.type;\n } else {\n cast = Mixed;\n }\n }\n\n // support { type: 'String' }\n var name = 'string' == typeof cast\n ? cast\n : cast.name;\n\n var caster = name in Types\n ? Types[name]\n : cast;\n\n this.casterConstructor = caster;\n this.caster = new caster(null, castOptions);\n if (!(this.caster instanceof EmbeddedDoc)) {\n this.caster.path = key;\n }\n }\n\n SchemaType.call(this, key, options);\n\n var self = this\n , defaultArr\n , fn;\n\n if (this.defaultValue) {\n defaultArr = this.defaultValue;\n fn = 'function' == typeof defaultArr;\n }\n\n this.default(function(){\n var arr = fn ? defaultArr() : defaultArr || [];\n return new MongooseArray(arr, self.path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "SchemaArray", + "string": "SchemaArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaArray.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaArray", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.checkRequired = function (value) {\n return !!(value && value.length);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "checkRequired", + "string": "SchemaArray.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides the getters application for the population special-case

    ", + "summary": "

    Overrides the getters application for the population special-case

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.applyGetters = function (value, scope) {\n if (this.caster.options && this.caster.options.ref) {\n // means the object id was populated\n return value;\n }\n\n return SchemaType.prototype.applyGetters.call(this, value, scope);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "applyGetters", + "string": "SchemaArray.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.cast = function (value, doc, init) {\n if (Array.isArray(value)) {\n if (!(value instanceof MongooseArray)) {\n value = new MongooseArray(value, this.path, doc);\n }\n\n if (this.caster) {\n try {\n for (var i = 0, l = value.length; i < l; i++) {\n value[i] = this.caster.cast(value[i], doc, init);\n }\n } catch (e) {\n // rethrow\n throw new CastError(e.type, value, this.path);\n }\n }\n\n return value;\n } else {\n return this.cast([value], doc, init);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "cast", + "string": "SchemaArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaArray.prototype.castForQuery = function ($conditional, value) {\n var handler\n , val;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Array.\");\n val = handler.call(this, value);\n } else {\n val = $conditional;\n var proto = this.casterConstructor.prototype;\n var method = proto.castForQuery || proto.cast;\n\n var caster = this.caster;\n if (Array.isArray(val)) {\n val = val.map(function (v) {\n if (method) v = method.call(caster, v);\n\n return isMongooseObject(v)\n ? v.toObject()\n : v;\n });\n } else if (method) {\n val = method.call(caster, val);\n }\n }\n return val && isMongooseObject(val)\n ? val.toObject()\n : val;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaArray", + "name": "castForQuery", + "string": "SchemaArray.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    @ignore

    ", + "summary": "

    @ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function castToNumber (val) {\n return Types.Number.prototype.cast.call(this, val);\n}\n\nfunction castArray (arr, self) {\n self || (self = this);\n\n arr.forEach(function (v, i) {\n if (Array.isArray(v)) {\n castArray(v, self);\n } else {\n arr[i] = castToNumber.call(self, v);\n }\n });\n}\n\nSchemaArray.prototype.$conditionalHandlers = {\n '$all': function handle$all (val) {\n if (!Array.isArray(val)) {\n val = [val];\n }\n\n val = val.map(function (v) {\n if (v && 'Object' === v.constructor.name) {\n var o = {};\n o[this.path] = v;\n var query = new Query(o);\n query.cast(this.casterConstructor);\n return query._conditions[this.path];\n }\n return v;\n }, this);\n\n return this.castForQuery(val);\n }\n , '$elemMatch': function (val) {\n if (val.$in) {\n val.$in = this.castForQuery('$in', val.$in);\n return val;\n }\n\n var query = new Query(val);\n query.cast(this.casterConstructor);\n return query._conditions;\n }\n , '$size': castToNumber\n , '$ne': SchemaArray.prototype.castForQuery\n , '$in': SchemaArray.prototype.castForQuery\n , '$nin': SchemaArray.prototype.castForQuery\n , '$regex': SchemaArray.prototype.castForQuery\n , '$near': SchemaArray.prototype.castForQuery\n , '$nearSphere': SchemaArray.prototype.castForQuery\n , '$gt': SchemaArray.prototype.castForQuery\n , '$gte': SchemaArray.prototype.castForQuery\n , '$lt': SchemaArray.prototype.castForQuery\n , '$lte': SchemaArray.prototype.castForQuery\n , '$within': function (val) {\n var self = this;\n\n if (val.$maxDistance) {\n val.$maxDistance = castToNumber.call(this, val.$maxDistance);\n }\n\n if (val.$box || val.$polygon) {\n var type = val.$box ? '$box' : '$polygon';\n val[type].forEach(function (arr) {\n if (!Array.isArray(arr)) {\n var msg = 'Invalid $within $box argument. '\n + 'Expected an array, received ' + arr;\n throw new TypeError(msg);\n }\n arr.forEach(function (v, i) {\n arr[i] = castToNumber.call(this, v);\n });\n })\n } else if (val.$center || val.$centerSphere) {\n var type = val.$center ? '$center' : '$centerSphere';\n val[type].forEach(function (item, i) {\n if (Array.isArray(item)) {\n item.forEach(function (v, j) {\n item[j] = castToNumber.call(this, v);\n });\n } else {\n val[type][i] = castToNumber.call(this, item);\n }\n })\n } else if (val.$geometry) {\n switch (val.$geometry.type) {\n case 'Polygon':\n case 'LineString':\n case 'Point':\n val.$geometry.coordinates.forEach(castArray);\n break;\n default:\n // ignore unknowns\n break;\n }\n }\n\n return val;\n }\n , '$geoIntersects': function (val) {\n var geo = val.$geometry;\n if (!geo) return;\n\n switch (val.$geometry.type) {\n case 'Polygon':\n case 'LineString':\n case 'Point':\n val.$geometry.coordinates.forEach(castArray);\n break;\n default:\n // ignore unknowns\n break;\n }\n }\n , '$maxDistance': castToNumber\n};", + "ctx": { + "type": "function", + "name": "castToNumber", + "string": "castToNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaArray", + "string": "module.exports" + } + } +] +### lib/schema/boolean.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Boolean SchemaType constructor.

    ", + "summary": "

    Boolean SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBoolean (path, options) {\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaBoolean", + "string": "SchemaBoolean()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBoolean.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBoolean", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBoolean.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.checkRequired = function (value) {\n return value === true || value === false;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "checkRequired", + "string": "SchemaBoolean.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to boolean

    ", + "summary": "

    Casts to boolean

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.cast = function (value) {\n if (null === value) return value;\n if ('0' === value) return false;\n if ('true' === value) return true;\n if ('false' === value) return false;\n return !! value;\n}", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "cast", + "string": "SchemaBoolean.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nSchemaBoolean.$conditionalHandlers = {\n '$in': handleArray\n}", + "ctx": { + "type": "function", + "name": "handleArray", + "string": "handleArray()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBoolean.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (2 === arguments.length) {\n handler = SchemaBoolean.$conditionalHandlers[$conditional];\n\n if (handler) {\n return handler.call(this, val);\n }\n\n return this.cast(val);\n }\n\n return this.cast($conditional);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBoolean", + "name": "castForQuery", + "string": "SchemaBoolean.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBoolean;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBoolean", + "string": "module.exports" + } + } +] +### lib/schema/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , MongooseBuffer = require('../types').Buffer\n , Binary = MongooseBuffer.Binary\n , Query = require('../query')\n , utils = require('../utils')\n , Document", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "cast", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Buffer SchemaType constructor

    ", + "summary": "

    Buffer SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaBuffer (key, options) {\n SchemaType.call(this, key, options, 'Buffer');\n};", + "ctx": { + "type": "function", + "name": "SchemaBuffer", + "string": "SchemaBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaBuffer.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaBuffer", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaBuffer.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.checkRequired = function (value, doc) {\n if (SchemaType._isRef(this, value, doc, true)) {\n return null != value;\n } else {\n return !!(value && value.length);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "checkRequired", + "string": "SchemaBuffer.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, doc, init)) {\n // wait! we may need to cast this to a document\n\n // lazy load\n Document || (Document = require('./../document'));\n\n if (value instanceof Document || null == value) {\n return value;\n }\n\n // setting a populated path\n if (Buffer.isBuffer(value)) {\n return value;\n } else if (!utils.isObject(value)) {\n throw new CastError('buffer', value, this.path);\n }\n\n // Handle the case where user directly sets a populated\n // path to a plain object; cast to the Model used in\n // the population query.\n var path = doc.$__fullPath(this.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n var pop = owner.populated(path, true);\n var ret = new pop.options.model(value);\n return ret;\n }\n\n // documents\n if (value && value._id) {\n value = value._id;\n }\n\n if (Buffer.isBuffer(value)) {\n if (!(value instanceof MongooseBuffer)) {\n value = new MongooseBuffer(value, [this.path, doc]);\n }\n\n return value;\n } else if (value instanceof Binary) {\n return new MongooseBuffer(value.value(true), [this.path, doc]);\n }\n\n if (null === value) return value;\n\n var type = typeof value;\n if ('string' == type || 'number' == type || Array.isArray(value)) {\n return new MongooseBuffer(value, [this.path, doc]);\n }\n\n throw new CastError('buffer', value, this.path);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "cast", + "string": "SchemaBuffer.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaBuffer.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaBuffer.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Buffer.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n return this.cast(val).toObject();\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaBuffer", + "name": "castForQuery", + "string": "SchemaBuffer.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaBuffer;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaBuffer", + "string": "module.exports" + } + } +] +### lib/schema/date.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');\nvar CastError = SchemaType.CastError;\nvar utils = require('../utils');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date SchemaType constructor.

    ", + "summary": "

    Date SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaDate (key, options) {\n SchemaType.call(this, key, options);\n};", + "ctx": { + "type": "function", + "name": "SchemaDate", + "string": "SchemaDate()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaDate.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaDate", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaDate.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number", + "String" + ], + "name": "when", + "description": "" + }, + { + "type": "added", + "string": "3.0.0" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    \n\n

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: 60*60*24 }});\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: '24h' }});\n\n// expire in 1.5 hours\nnew Schema({ createdAt: { type: Date, expires: '1.5h' }});\n\n// expire in 7 days\nvar schema = new Schema({ createdAt: Date });\nschema.path('createdAt').expires('7d');\n
    ", + "summary": "

    Declares a TTL index (rounded to the nearest second) for Date types only.

    ", + "body": "

    This sets the expiresAfterSeconds index option available in MongoDB >= 2.1.2.
    This index type is only compatible with Date types.

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: 60*60*24 }});\n
    \n\n

    expires utilizes the ms module from guille allowing us to use a friendlier syntax:

    \n\n

    Example:

    \n\n
    // expire in 24 hours\nnew Schema({ createdAt: { type: Date, expires: '24h' }});\n\n// expire in 1.5 hours\nnew Schema({ createdAt: { type: Date, expires: '1.5h' }});\n\n// expire in 7 days\nvar schema = new Schema({ createdAt: Date });\nschema.path('createdAt').expires('7d');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaDate.prototype.expires = function (when) {\n if (!this._index || 'Object' !== this._index.constructor.name) {\n this._index = {};\n }\n\n this._index.expires = when;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "expires", + "string": "SchemaDate.prototype.expires()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for date

    ", + "summary": "

    Required validator for date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.checkRequired = function (value) {\n return value instanceof Date;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "checkRequired", + "string": "SchemaDate.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to date

    ", + "summary": "

    Casts to date

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.cast = function (value) {\n if (value === null || value === '')\n return null;\n\n if (value instanceof Date)\n return value;\n\n var date;\n\n // support for timestamps\n if (value instanceof Number || 'number' == typeof value \n || String(value) == Number(value))\n date = new Date(Number(value));\n\n // support for date strings\n else if (value.toString)\n date = new Date(value.toString());\n\n if (date.toString() != 'Invalid Date')\n return date;\n\n throw new CastError('date', value, this.path);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "cast", + "string": "SchemaDate.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Date Query casting.

    ", + "summary": "

    Date Query casting.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map( function (m) {\n return self.cast(m);\n });\n}\n\nSchemaDate.prototype.$conditionalHandlers = {\n '$lt': handleSingle\n , '$lte': handleSingle\n , '$gt': handleSingle\n , '$gte': handleSingle\n , '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaDate.prototype.castForQuery = function ($conditional, val) {\n var handler;\n\n if (2 !== arguments.length) {\n return this.cast($conditional);\n }\n\n handler = this.$conditionalHandlers[$conditional];\n\n if (!handler) {\n throw new Error(\"Can't use \" + $conditional + \" with Date.\");\n }\n\n return handler.call(this, val);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaDate", + "name": "castForQuery", + "string": "SchemaDate.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaDate;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaDate", + "string": "module.exports" + } + } +] +### lib/schema/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , ArrayType = require('./array')\n , MongooseDocumentArray = require('../types/documentarray')\n , Subdocument = require('../types/embedded')\n , Document = require('../document');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Schema" + ], + "name": "schema", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaArray" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    SubdocsArray SchemaType constructor

    ", + "summary": "

    SubdocsArray SchemaType constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function DocumentArray (key, schema, options) {\n\n // compile an embedded document for this schema\n function EmbeddedDocument () {\n Subdocument.apply(this, arguments);\n }\n\n EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;\n EmbeddedDocument.prototype.$__setSchema(schema);\n EmbeddedDocument.schema = schema;\n\n // apply methods\n for (var i in schema.methods) {\n EmbeddedDocument.prototype[i] = schema.methods[i];\n }\n\n // apply statics\n for (var i in schema.statics)\n EmbeddedDocument[i] = schema.statics[i];\n\n EmbeddedDocument.options = options;\n this.schema = schema;\n\n ArrayType.call(this, key, EmbeddedDocument, options);\n\n this.schema = schema;\n var path = this.path;\n var fn = this.defaultValue;\n\n this.default(function(){\n var arr = fn.call(this);\n if (!Array.isArray(arr)) arr = [arr];\n return new MongooseDocumentArray(arr, path, this);\n });\n};", + "ctx": { + "type": "function", + "name": "DocumentArray", + "string": "DocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from ArrayType.

    ", + "summary": "

    Inherits from ArrayType.

    ", + "body": "" + }, + "ignore": true, + "code": "DocumentArray.prototype.__proto__ = ArrayType.prototype;", + "ctx": { + "type": "property", + "constructor": "DocumentArray", + "name": "__proto__", + "value": "ArrayType.prototype", + "string": "DocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs local validations first, then validations on each embedded doc

    ", + "summary": "

    Performs local validations first, then validations on each embedded doc

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.doValidate = function (array, fn, scope) {\n var self = this;\n\n SchemaType.prototype.doValidate.call(this, array, function (err) {\n if (err) return fn(err);\n\n var count = array && array.length\n , error;\n\n if (!count) return fn();\n\n // handle sparse arrays, do not use array.forEach which does not\n // iterate over sparse elements yet reports array.length including\n // them :(\n\n for (var i = 0, len = count; i < len; ++i) {\n // sidestep sparse entries\n var doc = array[i];\n if (!doc) {\n --count || fn();\n continue;\n }\n\n ;(function (i) {\n doc.validate(function (err) {\n if (err && !error) {\n // rewrite the key\n err.key = self.key + '.' + i + '.' + err.key;\n return fn(error = err);\n }\n --count || fn();\n });\n })(i);\n }\n }, scope);\n};", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "doValidate", + "string": "DocumentArray.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "document", + "description": "that triggers the casting" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents

    ", + "summary": "

    Casts contents

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "DocumentArray.prototype.cast = function (value, doc, init, prev) {\n var selected\n , subdoc\n , i\n\n if (!Array.isArray(value)) {\n return this.cast([value], doc, init, prev);\n }\n\n if (!(value instanceof MongooseDocumentArray)) {\n value = new MongooseDocumentArray(value, this.path, doc);\n }\n\n i = value.length;\n\n while (i--) {\n if (!(value[i] instanceof Subdocument) && value[i]) {\n if (init) {\n selected || (selected = scopePaths(this, doc.$__.selected, init));\n subdoc = new this.casterConstructor(null, value, true, selected);\n value[i] = subdoc.init(value[i]);\n } else {\n if (prev && (subdoc = prev.id(value[i]._id))) {\n // handle resetting doc with existing id but differing data\n // doc.array = [{ doc: 'val' }]\n subdoc.set(value[i]);\n } else {\n subdoc = new this.casterConstructor(value[i], value);\n }\n\n // if set() is hooked it will have no return value\n // see gh-746\n value[i] = subdoc;\n }\n }\n }\n\n return value;\n}", + "ctx": { + "type": "method", + "constructor": "DocumentArray", + "name": "cast", + "string": "DocumentArray.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "DocumentArray" + ], + "name": "array", + "description": "- the array to scope `fields` paths" + }, + { + "type": "param", + "types": [ + "Object", + "undefined" + ], + "name": "fields", + "description": "- the root fields selected in the query" + }, + { + "type": "param", + "types": [ + "Boolean", + "undefined" + ], + "name": "init", + "description": "- if we are being created part of a query result" + } + ], + "description": { + "full": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "summary": "

    Scopes paths selected in a query to this array.
    Necessary for proper default application of subdocument values.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "function scopePaths (array, fields, init) {\n if (!(init && fields)) return undefined;\n\n var path = array.path + '.'\n , keys = Object.keys(fields)\n , i = keys.length\n , selected = {}\n , hasKeys\n , key\n\n while (i--) {\n key = keys[i];\n if (0 === key.indexOf(path)) {\n hasKeys || (hasKeys = true);\n selected[key.substring(path.length)] = fields[key];\n }\n }\n\n return hasKeys && selected || undefined;\n}", + "ctx": { + "type": "function", + "name": "scopePaths", + "string": "scopePaths()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = DocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "DocumentArray", + "string": "module.exports" + } + } +] +### lib/schema/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.String = require('./string');\n\nexports.Number = require('./number');\n\nexports.Boolean = require('./boolean');\n\nexports.DocumentArray = require('./documentarray');\n\nexports.Array = require('./array');\n\nexports.Buffer = require('./buffer');\n\nexports.Date = require('./date');\n\nexports.ObjectId = require('./objectid');\n\nexports.Mixed = require('./mixed');\n\n// alias\n\nexports.Oid = exports.ObjectId;\nexports.Object = exports.Mixed;\nexports.Bool = exports.Boolean;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "String", + "value": "require('./string')", + "string": "exports.String" + } + } +] +### lib/schema/mixed.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype');\nvar utils = require('../utils');", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Mixed SchemaType constructor.

    ", + "summary": "

    Mixed SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function Mixed (path, options) {\n if (options && options.default) {\n var def = options.default;\n if (Array.isArray(def) && 0 === def.length) {\n // make sure empty array defaults are handled\n options.default = Array;\n } else if (!options.shared &&\n utils.isObject(def) &&\n 0 === Object.keys(def).length) {\n // prevent odd \"shared\" objects between documents\n options.default = function () {\n return {}\n }\n }\n }\n\n SchemaType.call(this, path, options);\n};", + "ctx": { + "type": "function", + "name": "Mixed", + "string": "Mixed()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "Mixed.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "Mixed", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "Mixed.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator

    ", + "summary": "

    Required validator

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.checkRequired = function (val) {\n return true;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "checkRequired", + "string": "Mixed.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "to cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts val for Mixed.

    \n\n

    this is a no-op

    ", + "summary": "

    Casts val for Mixed.

    ", + "body": "

    this is a no-op

    " + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.cast = function (val) {\n return val;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "cast", + "string": "Mixed.prototype.cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$cond", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Mixed.prototype.castForQuery = function ($cond, val) {\n if (arguments.length === 2) return val;\n return $cond;\n};", + "ctx": { + "type": "method", + "constructor": "Mixed", + "name": "castForQuery", + "string": "Mixed.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = Mixed;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "Mixed", + "string": "module.exports" + } + } +] +### lib/schema/number.js +[ + { + "tags": [], + "description": { + "full": "

    Module requirements.

    ", + "summary": "

    Module requirements.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , utils = require('../utils')\n , Document", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Number SchemaType constructor.

    ", + "summary": "

    Number SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaNumber (key, options) {\n SchemaType.call(this, key, options, 'Number');\n};", + "ctx": { + "type": "function", + "name": "SchemaNumber", + "string": "SchemaNumber()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaNumber.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaNumber", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaNumber.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Required validator for number

    ", + "summary": "

    Required validator for number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.checkRequired = function checkRequired (value, doc) {\n if (SchemaType._isRef(this, value, doc, true)) {\n return null != value;\n } else {\n return typeof value == 'number' || value instanceof Number;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "checkRequired", + "string": "SchemaNumber.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "value", + "description": "minimum number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a minimum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a minimum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, min: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 9 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.min = function (value, message) {\n if (this.minValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'min';\n });\n if (value != null)\n this.validators.push([function(v){\n return v === null || v >= value;\n }, 'min']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "min", + "string": "SchemaNumber.prototype.min()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Number" + ], + "name": "maximum", + "description": "number" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "message", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a maximum number validator.

    \n\n

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    ", + "summary": "

    Sets a maximum number validator.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ n: { type: Number, max: 10 })\nvar M = db.model('M', s)\nvar m = new M({ n: 11 })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.n = 10;\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaNumber.prototype.max = function (value, message) {\n if (this.maxValidator)\n this.validators = this.validators.filter(function(v){\n return v[1] != 'max';\n });\n if (value != null)\n this.validators.push([this.maxValidator = function(v){\n return v === null || v <= value;\n }, 'max']);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "max", + "string": "SchemaNumber.prototype.max()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "value to cast" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "document that triggers the casting" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to number

    ", + "summary": "

    Casts to number

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, doc, init)) {\n // wait! we may need to cast this to a document\n\n // lazy load\n Document || (Document = require('./../document'));\n\n if (value instanceof Document || null == value) {\n return value;\n }\n\n // setting a populated path\n if ('number' == typeof value) {\n return value;\n } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {\n throw new CastError('number', value, this.path);\n }\n\n // Handle the case where user directly sets a populated\n // path to a plain object; cast to the Model used in\n // the population query.\n var path = doc.$__fullPath(this.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n var pop = owner.populated(path, true);\n return new pop.options.model(value);\n }\n\n var val = value && value._id\n ? value._id // documents\n : value;\n\n if (!isNaN(val)){\n if (null === val) return val;\n if ('' === val) return null;\n if ('string' == typeof val) val = Number(val);\n if (val instanceof Number) return val\n if ('number' == typeof val) return val;\n if (val.toString && !Array.isArray(val) &&\n val.toString() == Number(val)) {\n return new Number(val)\n }\n }\n\n throw new CastError('number', value, this.path);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "cast", + "string": "SchemaNumber.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val)\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m)\n });\n}\n\nSchemaNumber.prototype.$conditionalHandlers = {\n '$lt' : handleSingle\n , '$lte': handleSingle\n , '$gt' : handleSingle\n , '$gte': handleSingle\n , '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$mod': handleArray\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[value]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaNumber.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with Number.\");\n return handler.call(this, val);\n } else {\n val = this.cast($conditional);\n return val == null ? val : val\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaNumber", + "name": "castForQuery", + "string": "SchemaNumber.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaNumber;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaNumber", + "string": "module.exports" + } + } +] +### lib/schema/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'\n , oid = require('../types/objectid')\n , utils = require('../utils')\n , Document", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    ObjectId SchemaType constructor.

    ", + "summary": "

    ObjectId SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function ObjectId (key, options) {\n SchemaType.call(this, key, options, 'ObjectID');\n};", + "ctx": { + "type": "function", + "name": "ObjectId", + "string": "ObjectId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "ObjectId.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "ObjectId", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "ObjectId.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.checkRequired = function checkRequired (value, doc) {\n if (SchemaType._isRef(this, value, doc, true)) {\n return null != value;\n } else {\n return value instanceof oid;\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "checkRequired", + "string": "ObjectId.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "whether this is an initialization cast" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to ObjectId

    ", + "summary": "

    Casts to ObjectId

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, doc, init)) {\n // wait! we may need to cast this to a document\n\n // lazy load\n Document || (Document = require('./../document'));\n\n if (value instanceof Document || null == value) {\n return value;\n }\n\n // setting a populated path\n if (value instanceof oid) {\n return value;\n } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {\n throw new CastError('ObjectId', value, this.path);\n }\n\n // Handle the case where user directly sets a populated\n // path to a plain object; cast to the Model used in\n // the population query.\n var path = doc.$__fullPath(this.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n var pop = owner.populated(path, true);\n return new pop.options.model(value);\n }\n\n if (value === null) return value;\n\n if (value instanceof oid)\n return value;\n\n if (value._id && value._id instanceof oid)\n return value._id;\n\n if (value.toString) {\n try {\n return oid.fromString(value.toString());\n } catch (err) {\n throw new CastError('ObjectId', value, this.path);\n }\n }\n\n throw new CastError('ObjectId', value, this.path);\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "cast", + "string": "ObjectId.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.cast(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.cast(m);\n });\n}\n\nObjectId.prototype.$conditionalHandlers = {\n '$ne': handleSingle\n , '$in': handleArray\n , '$nin': handleArray\n , '$gt': handleSingle\n , '$lt': handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with ObjectId.\");\n return handler.call(this, val);\n } else {\n return this.cast($conditional);\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "castForQuery", + "string": "ObjectId.prototype.castForQuery()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "turnOn", + "description": "auto generated ObjectId defaults" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "summary": "

    Adds an auto-generated ObjectId default if turnOn is true.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "ObjectId.prototype.auto = function (turnOn) {\n if (turnOn) {\n this.default(defaultId);\n this.set(resetId)\n }\n};", + "ctx": { + "type": "method", + "constructor": "ObjectId", + "name": "auto", + "string": "ObjectId.prototype.auto()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function defaultId () {\n return new oid();\n};\n\nfunction resetId (v) {\n this.$__._id = null;\n return v;\n}", + "ctx": { + "type": "function", + "name": "defaultId", + "string": "defaultId()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = ObjectId;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "ObjectId", + "string": "module.exports" + } + } +] +### lib/schema/string.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var SchemaType = require('../schematype')\n , CastError = SchemaType.CastError\n , utils = require('../utils')\n , Document", + "ctx": { + "type": "declaration", + "name": "SchemaType", + "value": "require('../schematype')", + "string": "SchemaType" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "inherits", + "string": "SchemaType" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    String SchemaType constructor.

    ", + "summary": "

    String SchemaType constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function SchemaString (key, options) {\n this.enumValues = [];\n this.regExp = null;\n SchemaType.call(this, key, options, 'String');\n};", + "ctx": { + "type": "function", + "name": "SchemaString", + "string": "SchemaString()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from SchemaType.

    ", + "summary": "

    Inherits from SchemaType.

    ", + "body": "" + }, + "ignore": true, + "code": "SchemaString.prototype.__proto__ = SchemaType.prototype;", + "ctx": { + "type": "property", + "constructor": "SchemaString", + "name": "__proto__", + "value": "SchemaType.prototype", + "string": "SchemaString.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[args...]", + "description": "enumeration values" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds enumeration values and a coinciding validator.

    \n\n

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    ", + "summary": "

    Adds enumeration values and a coinciding validator.

    ", + "body": "

    Example:

    \n\n
    var states = 'opening open closing closed'.split(' ')\nvar s = new Schema({ state: { type: String, enum: states })\nvar M = db.model('M', s)\nvar m = new M({ state: 'invalid' })\nm.save(function (err) {\n  console.error(err) // validator error\n  m.state = 'open'\n  m.save() // success\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.enum = function () {\n var len = arguments.length;\n if (!len || undefined === arguments[0] || false === arguments[0]) {\n if (this.enumValidator){\n this.enumValidator = false;\n this.validators = this.validators.filter(function(v){\n return v[1] != 'enum';\n });\n }\n return;\n }\n\n for (var i = 0; i < len; i++) {\n if (undefined !== arguments[i]) {\n this.enumValues.push(this.cast(arguments[i]));\n }\n }\n\n if (!this.enumValidator) {\n var values = this.enumValues;\n this.enumValidator = function(v){\n return undefined === v || ~values.indexOf(v);\n };\n this.validators.push([this.enumValidator, 'enum']);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "enum", + "string": "SchemaString.prototype.enum()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a lowercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    ", + "summary": "

    Adds a lowercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ email: { type: String, lowercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ email: 'SomeEmail@example.COM' });\nconsole.log(m.email) // someemail@example.com\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.lowercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toLowerCase();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "lowercase", + "string": "SchemaString.prototype.lowercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an uppercase setter.

    \n\n

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    ", + "summary": "

    Adds an uppercase setter.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ caps: { type: String, uppercase: true }})\nvar M = db.model('M', s);\nvar m = new M({ caps: 'an example' });\nconsole.log(m.caps) // AN EXAMPLE\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.uppercase = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.toUpperCase();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "uppercase", + "string": "SchemaString.prototype.uppercase()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a trim setter.

    \n\n

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    ", + "summary": "

    Adds a trim setter.

    ", + "body": "

    The string value will be trimmed when set.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, trim: true }})\nvar M = db.model('M', s)\nvar string = ' some name '\nconsole.log(string.length) // 11\nvar m = new M({ name: string })\nconsole.log(m.name.length) // 9\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.trim = function () {\n return this.set(function (v, self) {\n if ('string' != typeof v) v = self.cast(v)\n if (v) return v.trim();\n return v;\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "trim", + "string": "SchemaString.prototype.trim()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp" + ], + "name": "regExp", + "description": "regular expression to test against" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a regexp validator.

    \n\n

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    ", + "summary": "

    Sets a regexp validator.

    ", + "body": "

    Any value that does not pass regExp.test(val) will fail validation.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, match: /^a/ }})\nvar M = db.model('M', s)\nvar m = new M({ name: 'invalid' })\nm.validate(function (err) {\n  console.error(err) // validation error\n  m.name = 'apples'\n  m.validate(function (err) {\n    assert.ok(err) // success\n  })\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaString.prototype.match = function match (regExp) {\n this.validators.push([function(v){\n return null != v && '' !== v\n ? regExp.test(v)\n : true\n }, 'regexp']);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "match", + "string": "SchemaString.prototype.match()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "null", + "undefined" + ], + "name": "value", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Check required

    ", + "summary": "

    Check required

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.checkRequired = function checkRequired (value, doc) {\n if (SchemaType._isRef(this, value, doc, true)) {\n return null != value;\n } else {\n return (value instanceof String || typeof value == 'string') && value.length;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "checkRequired", + "string": "SchemaString.prototype.checkRequired()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts to String

    ", + "summary": "

    Casts to String

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.cast = function (value, doc, init) {\n if (SchemaType._isRef(this, value, doc, init)) {\n // wait! we may need to cast this to a document\n\n // lazy load\n Document || (Document = require('./../document'));\n\n if (value instanceof Document || null == value) {\n return value;\n }\n\n // setting a populated path\n if ('string' == typeof value) {\n return value;\n } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {\n throw new CastError('string', value, this.path);\n }\n\n // Handle the case where user directly sets a populated\n // path to a plain object; cast to the Model used in\n // the population query.\n var path = doc.$__fullPath(this.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n var pop = owner.populated(path, true);\n return new pop.options.model(value);\n }\n\n if (value === null) {\n return value;\n }\n\n if ('undefined' !== typeof value) {\n // handle documents being passed\n if (value._id && 'string' == typeof value._id) {\n return value._id;\n }\n if (value.toString) {\n return value.toString();\n }\n }\n\n\n throw new CastError('string', value, this.path);\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "cast", + "string": "SchemaString.prototype.cast()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function handleSingle (val) {\n return this.castForQuery(val);\n}\n\nfunction handleArray (val) {\n var self = this;\n return val.map(function (m) {\n return self.castForQuery(m);\n });\n}\n\nSchemaString.prototype.$conditionalHandlers = {\n '$ne' : handleSingle\n , '$in' : handleArray\n , '$nin': handleArray\n , '$gt' : handleSingle\n , '$lt' : handleSingle\n , '$gte': handleSingle\n , '$lte': handleSingle\n , '$all': handleArray\n , '$regex': handleSingle\n , '$options': handleSingle\n};", + "ctx": { + "type": "function", + "name": "handleSingle", + "string": "handleSingle()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "$conditional", + "description": "" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "[val]", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts contents for queries.

    ", + "summary": "

    Casts contents for queries.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaString.prototype.castForQuery = function ($conditional, val) {\n var handler;\n if (arguments.length === 2) {\n handler = this.$conditionalHandlers[$conditional];\n if (!handler)\n throw new Error(\"Can't use \" + $conditional + \" with String.\");\n return handler.call(this, val);\n } else {\n val = $conditional;\n if (val instanceof RegExp) return val;\n return this.cast(val);\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaString", + "name": "castForQuery", + "string": "SchemaString.prototype.castForQuery()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = SchemaString;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "SchemaString", + "string": "module.exports" + } + } +] +### lib/schema.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EventEmitter = require('events').EventEmitter\n , VirtualType = require('./virtualtype')\n , utils = require('./utils')\n , NamedScope\n , Query\n , Types", + "ctx": { + "type": "declaration", + "name": "EventEmitter", + "value": "require('events').EventEmitter", + "string": "EventEmitter" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "definition", + "description": "" + }, + { + "type": "inherits", + "string": "NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter" + }, + { + "type": "event", + "string": "`init`: Emitted after the schema is compiled into a `Model`." + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Schema constructor.

    \n\n

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n\n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    ", + "summary": "

    Schema constructor.

    ", + "body": "

    Example:

    \n\n
    var child = new Schema({ name: String });\nvar schema = new Schema({ name: String, age: Number, children: [child] });\nvar Tree = mongoose.model('Tree', schema);\n\n// setting schema options\nnew Schema({ name: String }, { _id: false, autoIndex: false })\n
    \n\n

    Options:

    \n\n\n\n

    Note:

    \n\n

    When nesting schemas, (children in the example above), always declare the child schema first before passing it into is parent.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "function Schema (obj, options) {\n if (!(this instanceof Schema))\n return new Schema(obj, options);\n\n this.paths = {};\n this.subpaths = {};\n this.virtuals = {};\n this.nested = {};\n this.inherits = {};\n this.callQueue = [];\n this._indexes = [];\n this.methods = {};\n this.statics = {};\n this.tree = {};\n this._requiredpaths = undefined;\n\n this.options = this.defaultOptions(options);\n\n // build paths\n if (obj) {\n this.add(obj);\n }\n\n // ensure the documents get an auto _id unless disabled\n var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);\n if (auto_id) {\n this.add({ _id: {type: Schema.ObjectId, auto: true} });\n }\n\n // ensure the documents receive an id getter unless disabled\n var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);\n if (autoid) {\n this.virtual('id').get(idGetter);\n }\n}", + "ctx": { + "type": "function", + "name": "Schema", + "string": "Schema()" + } + }, + { + "tags": [], + "description": { + "full": "

    Returns this documents _id cast to a string.

    ", + "summary": "

    Returns this documents _id cast to a string.

    ", + "body": "" + }, + "ignore": true, + "code": "function idGetter () {\n if (this.$__._id) {\n return this.$__._id;\n }\n\n return this.$__._id = null == this._id\n ? null\n : String(this._id);\n}", + "ctx": { + "type": "function", + "name": "idGetter", + "string": "idGetter()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from EventEmitter.

    ", + "summary": "

    Inherit from EventEmitter.

    ", + "body": "" + }, + "ignore": true, + "code": "Schema.prototype.__proto__ = EventEmitter.prototype;", + "ctx": { + "type": "property", + "constructor": "Schema", + "name": "__proto__", + "value": "EventEmitter.prototype", + "string": "Schema.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "paths" + } + ], + "description": { + "full": "

    Schema as flat paths

    \n\n

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    ", + "summary": "

    Schema as flat paths

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'        : SchemaType,\n  , 'nested.key' : SchemaType,\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.paths;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "tree" + } + ], + "description": { + "full": "

    Schema as a tree

    \n\n

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    ", + "summary": "

    Schema as a tree

    ", + "body": "

    Example:

    \n\n
    {\n    '_id'     : ObjectId\n  , 'nested'  : {\n        'key' : String\n    }\n}\n
    " + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.tree;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns default options for this schema, merged with options.

    ", + "summary": "

    Returns default options for this schema, merged with options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.defaultOptions = function (options) {\n if (options && false === options.safe) {\n options.safe = { w: 0 };\n }\n\n options = utils.options({\n strict: true\n , bufferCommands: true\n , capped: false // { size, max, autoIndexId }\n , versionKey: '__v'\n , minimize: true\n , autoIndex: true\n , shardKey: null\n , read: null\n // the following are only applied at construction time\n , noId: false // deprecated, use { _id: false }\n , _id: true\n , noVirtualId: false // deprecated, use { id: false }\n , id: true\n }, options);\n\n if (options.read)\n options.read = utils.readPref(options.read);\n\n return options;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "defaultOptions", + "string": "Schema.prototype.defaultOptions()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "prefix", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds key path / schema type pairs to this schema.

    \n\n

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    ", + "summary": "

    Adds key path / schema type pairs to this schema.

    ", + "body": "

    Example:

    \n\n
    var ToySchema = new Schema;\nToySchema.add({ name: 'string', color: 'string', price: 'number' });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.add = function add (obj, prefix) {\n prefix = prefix || '';\n for (var i in obj) {\n if (null == obj[i]) {\n throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');\n }\n\n if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {\n if (Object.keys(obj[i]).length) {\n // nested object { last: { name: String }}\n this.nested[prefix + i] = true;\n this.add(obj[i], prefix + i + '.');\n } else {\n this.path(prefix + i, obj[i]); // mixed type\n }\n } else {\n this.path(prefix + i, obj[i]);\n }\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "add", + "string": "Schema.prototype.add()" + } + }, + { + "tags": [], + "description": { + "full": "

    Reserved document keys.

    \n\n

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, emit, _events, db, init, isNew, errors, schema, options, modelName, collection, _pres, _posts, toObject\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    ", + "summary": "

    Reserved document keys.

    ", + "body": "

    Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

    \n\n
     on, emit, _events, db, init, isNew, errors, schema, options, modelName, collection, _pres, _posts, toObject\n
    \n\n

    NOTE: Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.

    \n\n
     var schema = new Schema(..);\n schema.methods.init = function () {} // potentially breaking\n
    " + }, + "ignore": false, + "code": "Schema.reserved = Object.create(null);\nvar reserved = Schema.reserved;\nreserved.on =\nreserved.db =\nreserved.init =\nreserved.isNew =\nreserved.errors =\nreserved.schema =\nreserved.options =\nreserved.modelName =\nreserved.collection =\nreserved.toObject =\nreserved.emit = // EventEmitter\nreserved._events = // EventEmitter\nreserved._pres = reserved._posts = 1 // hooks.js", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "reserved", + "value": "Object.create(null)", + "string": "Schema.reserved" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "constructor", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets/sets schema paths.

    \n\n

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    ", + "summary": "

    Gets/sets schema paths.

    ", + "body": "

    Sets a path (if arity 2)
    Gets a path (if arity 1)

    \n\n

    Example

    \n\n
    schema.path('name') // returns a SchemaType\nschema.path('name', Number) // changes the schemaType of `name` to Number\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.path = function (path, obj) {\n if (obj == undefined) {\n if (this.paths[path]) return this.paths[path];\n if (this.subpaths[path]) return this.subpaths[path];\n\n // subpaths?\n return /\\.\\d+\\.?$/.test(path)\n ? getPositionalPath(this, path)\n : undefined;\n }\n\n // some path names conflict with document methods\n if (reserved[path]) {\n throw new Error(\"`\" + path + \"` may not be used as a schema pathname\");\n }\n\n // update the tree\n var subpaths = path.split(/\\./)\n , last = subpaths.pop()\n , branch = this.tree;\n\n subpaths.forEach(function(sub, i) {\n if (!branch[sub]) branch[sub] = {};\n if ('object' != typeof branch[sub]) {\n var msg = 'Cannot set nested path `' + path + '`. '\n + 'Parent path `'\n + subpaths.slice(0, i).concat([sub]).join('.')\n + '` already set to type ' + branch[sub].name\n + '.';\n throw new Error(msg);\n }\n branch = branch[sub];\n });\n\n branch[last] = utils.clone(obj);\n\n this.paths[path] = Schema.interpretAsType(path, obj);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "path", + "string": "Schema.prototype.path()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "constructor" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts type arguments into Mongoose Types.

    ", + "summary": "

    Converts type arguments into Mongoose Types.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.interpretAsType = function (path, obj) {\n if (obj.constructor.name != 'Object')\n obj = { type: obj };\n\n // Get the type making sure to allow keys named \"type\"\n // and default to mixed if not specified.\n // { type: { type: String, default: 'freshcut' } }\n var type = obj.type && !obj.type.type\n ? obj.type\n : {};\n\n if ('Object' == type.constructor.name || 'mixed' == type) {\n return new Types.Mixed(path, obj);\n }\n\n if (Array.isArray(type) || Array == type || 'array' == type) {\n // if it was specified through { type } look for `cast`\n var cast = (Array == type || 'array' == type)\n ? obj.cast\n : type[0];\n\n if (cast instanceof Schema) {\n return new Types.DocumentArray(path, cast, obj);\n }\n\n if ('string' == typeof cast) {\n cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];\n } else if (cast && (!cast.type || cast.type.type)\n && 'Object' == cast.constructor.name\n && Object.keys(cast).length) {\n return new Types.DocumentArray(path, new Schema(cast), obj);\n }\n\n return new Types.Array(path, cast || Types.Mixed, obj);\n }\n\n var name = 'string' == typeof type\n ? type\n : type.name;\n\n if (name) {\n name = name.charAt(0).toUpperCase() + name.substring(1);\n }\n\n if (undefined == Types[name]) {\n throw new TypeError('Undefined type at `' + path +\n '`\\n Did you try nesting Schemas? ' +\n 'You can only nest using refs or arrays.');\n }\n\n return new Types[name](path, obj);\n};", + "ctx": { + "type": "method", + "receiver": "Schema", + "name": "interpretAsType", + "string": "Schema.interpretAsType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback function" + }, + { + "type": "return", + "types": [ + "Schema" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Iterates the schemas paths similar to Array#forEach.

    \n\n

    The callback is passed the pathname and schemaType as arguments on each iteration.

    ", + "summary": "

    Iterates the schemas paths similar to Array#forEach.

    ", + "body": "

    The callback is passed the pathname and schemaType as arguments on each iteration.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.eachPath = function (fn) {\n var keys = Object.keys(this.paths)\n , len = keys.length;\n\n for (var i = 0; i < len; ++i) {\n fn(keys[i], this.paths[keys[i]]);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "eachPath", + "string": "Schema.prototype.eachPath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns an Array of path strings that are required by this schema.

    ", + "summary": "

    Returns an Array of path strings that are required by this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.requiredPaths = function requiredPaths () {\n if (this._requiredpaths) return this._requiredpaths;\n\n var paths = Object.keys(this.paths)\n , i = paths.length\n , ret = [];\n\n while (i--) {\n var path = paths[i];\n if (this.paths[path].isRequired) ret.push(path);\n }\n\n return this._requiredpaths = ret;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "requiredPaths", + "string": "Schema.prototype.requiredPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns the pathType of path for this schema.

    \n\n

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    ", + "summary": "

    Returns the pathType of path for this schema.

    ", + "body": "

    Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pathType = function (path) {\n if (path in this.paths) return 'real';\n if (path in this.virtuals) return 'virtual';\n if (path in this.nested) return 'nested';\n if (path in this.subpaths) return 'real';\n\n if (/\\.\\d+\\.?/.test(path) && getPositionalPath(this, path)) {\n return 'real';\n } else {\n return 'adhocOrUndefined'\n }\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pathType", + "string": "Schema.prototype.pathType()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function getPositionalPath (self, path) {\n var subpaths = path.split(/\\.(\\d+)\\.?/).filter(Boolean);\n if (subpaths.length < 2) {\n return self.paths[subpaths[0]];\n }\n\n var val = self.path(subpaths[0]);\n if (!val) return val;\n\n var last = subpaths.length - 1\n , subpath\n , i = 1;\n\n for (; i < subpaths.length; ++i) {\n subpath = subpaths[i];\n\n if (i === last &&\n val &&\n !val.schema &&\n !/\\D/.test(subpath) &&\n val instanceof Types.Array) {\n // StringSchema, NumberSchema, etc\n val = val.caster;\n continue;\n }\n\n // 'path.0.subpath'\n if (!/\\D/.test(subpath)) continue;\n val = val.schema.path(subpath);\n }\n\n return self.subpaths[path] = val;\n}", + "ctx": { + "type": "function", + "name": "getPositionalPath", + "string": "getPositionalPath()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "name of the document method to call later" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "args", + "description": "arguments to pass to the method" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Adds a method call to the queue.

    ", + "summary": "

    Adds a method call to the queue.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.queue = function(name, args){\n this.callQueue.push([name, args]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "queue", + "string": "Schema.prototype.queue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a pre hook for the document.

    \n\n

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    ", + "summary": "

    Defines a pre hook for the document.

    ", + "body": "

    Example

    \n\n
    var toySchema = new Schema(..);\n\ntoySchema.pre('save', function (next) {\n  if (!this.created) this.created = new Date;\n  next();\n})\n\ntoySchema.pre('validate', function (next) {\n  if (this.name != 'Woody') this.name = 'Woody';\n  next();\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.pre = function(){\n return this.queue('pre', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "pre", + "string": "Schema.prototype.pre()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "method", + "description": "name of the method to hook" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "callback" + }, + { + "type": "see", + "title": "hooks.js", + "url": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3", + "visibility": "https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a post hook for the document.

    \n\n

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function (doc) {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    ", + "summary": "

    Defines a post hook for the document.

    ", + "body": "

    Post hooks fire on the event emitted from document instances of Models compiled from this schema.

    \n\n
    var schema = new Schema(..);\nschema.post('save', function (doc) {\n  console.log('this fired after a document was saved');\n});\n\nvar Model = mongoose.model('Model', schema);\n\nvar m = new Model(..);\nm.save(function (err) {\n  console.log('this fires after the `post` hook');\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.post = function(method, fn){\n return this.queue('on', arguments);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "post", + "string": "Schema.prototype.post()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "plugin", + "description": "callback" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "opts", + "description": "" + }, + { + "type": "see", + "local": "plugins", + "visibility": "plugins" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Registers a plugin for this schema.

    ", + "summary": "

    Registers a plugin for this schema.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.plugin = function (fn, opts) {\n fn(this, opts);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "plugin", + "string": "Schema.prototype.plugin()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String", + "Object" + ], + "name": "method", + "description": "name" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    ", + "summary": "

    Adds an instance method to documents constructed from Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = kittySchema = new Schema(..);\n\nschema.methods.meow = function () {\n  console.log('meeeeeoooooooooooow');\n})\n\nvar Kitty = mongoose.model('Kitty', schema);\n\nvar fizz = new Kitty;\nfizz.meow(); // meeeeeooooooooooooow\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

    \n\n
    schema.method({\n    purr: function () {}\n  , scratch: function () {}\n});\n\n// later\nfizz.purr();\nfizz.scratch();\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.method = function (name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.methods[i] = name[i];\n else\n this.methods[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "method", + "string": "Schema.prototype.method()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds static \"class\" methods to Models compiled from this schema.

    \n\n

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    ", + "summary": "

    Adds static \"class\" methods to Models compiled from this schema.

    ", + "body": "

    Example

    \n\n
    var schema = new Schema(..);\nschema.static('findByName', function (name, callback) {\n  return this.find({ name: name }, callback);\n});\n\nvar Drink = mongoose.model('Drink', schema);\nDrink.findByName('sanpellegrino', function (err, drinks) {\n  //\n});\n
    \n\n

    If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.static = function(name, fn) {\n if ('string' != typeof name)\n for (var i in name)\n this.statics[i] = name[i];\n else\n this.statics[name] = fn;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "static", + "string": "Schema.prototype.static()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "fields", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines an index (most likely compound) for this schema.

    \n\n

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    ", + "summary": "

    Defines an index (most likely compound) for this schema.

    ", + "body": "

    Example

    \n\n
    schema.index({ first: 1, last: -1 })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.index = function (fields, options) {\n options || (options = {});\n\n if (options.expires)\n utils.expires(options);\n\n this._indexes.push([fields, options]);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "index", + "string": "Schema.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "option name" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[value]", + "description": "if not passed, the current option value is returned" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets/gets a schema option.

    ", + "summary": "

    Sets/gets a schema option.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.set = function (key, value, _tags) {\n if (1 === arguments.length) {\n return this.options[key];\n }\n\n switch (key) {\n case 'read':\n this.options[key] = utils.readPref(value, _tags)\n break;\n case 'safe':\n this.options[key] = false === value\n ? { w: 0 }\n : value\n break;\n default:\n this.options[key] = value;\n }\n\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "set", + "string": "Schema.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "key", + "description": "option name" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Gets a schema option.

    ", + "summary": "

    Gets a schema option.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.get = function (key) {\n return this.options[key];\n}", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "get", + "string": "Schema.prototype.get()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Compiles indexes from fields and schema-level indexes

    ", + "summary": "

    Compiles indexes from fields and schema-level indexes

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.indexes = function () {\n 'use strict';\n\n var indexes = []\n , seenSchemas = []\n , indexTypes = '2d 2dsphere hashed'.split(' ');\n\n collectIndexes(this);\n return indexes;\n\n function collectIndexes (schema, prefix) {\n if (~seenSchemas.indexOf(schema)) return;\n seenSchemas.push(schema);\n\n prefix = prefix || '';\n\n var key, path, index, field, isObject, options, type;\n var keys = Object.keys(schema.paths);\n\n for (var i = 0; i < keys.length; ++i) {\n key = keys[i];\n path = schema.paths[key];\n\n if (path instanceof Types.DocumentArray) {\n collectIndexes(path.schema, key + '.');\n } else {\n index = path._index;\n\n if (false !== index && null != index) {\n field = {};\n isObject = utils.isObject(index);\n options = isObject ? index : {};\n type = 'string' == typeof index ? index :\n isObject ? index.type :\n false;\n\n if (type && ~indexTypes.indexOf(type)) {\n field[prefix + key] = type;\n } else {\n field[prefix + key] = 1;\n }\n\n delete options.type;\n if (!('background' in options)) {\n options.background = true;\n }\n\n indexes.push([field, options]);\n }\n }\n }\n\n if (prefix) {\n fixSubIndexPaths(schema, prefix);\n } else {\n schema._indexes.forEach(function (index) {\n if (!('background' in index[1])) index[1].background = true;\n });\n indexes = indexes.concat(schema._indexes);\n }\n }", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "indexes", + "string": "Schema.prototype.indexes()" + } + }, + { + "tags": [], + "description": { + "full": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    \n\n

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    ", + "summary": "

    Checks for indexes added to subdocs using Schema.index().
    These indexes need their paths prefixed properly.

    ", + "body": "

    schema._indexes = [ [indexObj, options], [indexObj, options] ..]

    " + }, + "ignore": true, + "code": "function fixSubIndexPaths (schema, prefix) {\n var subindexes = schema._indexes\n , len = subindexes.length\n , indexObj\n , newindex\n , klen\n , keys\n , key\n , i = 0\n , j\n\n for (i = 0; i < len; ++i) {\n indexObj = subindexes[i][0];\n keys = Object.keys(indexObj);\n klen = keys.length;\n newindex = {};\n\n // use forward iteration, order matters\n for (j = 0; j < klen; ++j) {\n key = keys[j];\n newindex[prefix + key] = indexObj[key];\n }\n\n indexes.push([newindex, subindexes[i][1]]);\n }\n }\n}", + "ctx": { + "type": "function", + "name": "fixSubIndexPaths", + "string": "fixSubIndexPaths()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Creates a virtual type with the given name.

    ", + "summary": "

    Creates a virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtual = function (name, options) {\n var virtuals = this.virtuals;\n var parts = name.split('.');\n return virtuals[name] = parts.reduce(function (mem, part, i) {\n mem[part] || (mem[part] = (i === parts.length-1)\n ? new VirtualType(options, name)\n : {});\n return mem[part];\n }, this.tree);\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtual", + "string": "Schema.prototype.virtual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the virtual type with the given name.

    ", + "summary": "

    Returns the virtual type with the given name.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.prototype.virtualpath = function (name) {\n return this.virtuals[name];\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "virtualpath", + "string": "Schema.prototype.virtualpath()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "summary": "

    These still haven't been fixed. Once they're working we'll make them public again.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "Schema.prototype.namedScope = function (name, fn) {\n var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)\n , newScope = Object.create(namedScopes)\n , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});\n allScopes[name] = newScope;\n newScope.name = name;\n newScope.block = fn;\n newScope.query = new Query();\n newScope.decorate(namedScopes, {\n block0: function (block) {\n return function () {\n block.call(this.query);\n return this;\n };\n },\n blockN: function (block) {\n return function () {\n block.apply(this.query, arguments);\n return this;\n };\n },\n basic: function (query) {\n return function () {\n this.query.find(query);\n return this;\n };\n }\n });\n return newScope;\n};", + "ctx": { + "type": "method", + "constructor": "Schema", + "name": "namedScope", + "string": "Schema.prototype.namedScope()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = Schema;\n\n// require down here because of reference issues", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = Schema", + "string": "module.exports" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    The various built-in Mongoose Schema Types.

    \n\n

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n\n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    ", + "summary": "

    The various built-in Mongoose Schema Types.

    ", + "body": "

    Example:

    \n\n
    var mongoose = require('mongoose');\nvar ObjectId = mongoose.Schema.Types.ObjectId;\n
    \n\n

    Types:

    \n\n\n\n

    Using this exposed access to the Mixed SchemaType, we can use them in our schema.

    \n\n
    var Mixed = mongoose.Schema.Types.Mixed;\nnew mongoose.Schema({ _user: Mixed })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "Schema.Types = require('./schema/index');", + "ctx": { + "type": "property", + "receiver": "Schema", + "name": "Types", + "value": "require('./schema/index')", + "string": "Schema.Types" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "Types = Schema.Types;\nNamedScope = require('./namedscope')\nQuery = require('./query');\nvar ObjectId = exports.ObjectId = Types.ObjectId;" + } +] +### lib/schemadefault.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Schema = require('./schema')", + "ctx": { + "type": "declaration", + "name": "Schema", + "value": "require('./schema')", + "string": "Schema" + } + }, + { + "tags": [ + { + "type": "property", + "string": "system.profile" + }, + { + "type": "receiver", + "string": "exports" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Default model for querying the system.profiles collection.

    ", + "summary": "

    Default model for querying the system.profiles collection.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "exports['system.profile'] = new Schema({\n ts: Date\n , info: String // deprecated\n , millis: Number\n , op: String\n , ns: String\n , query: Schema.Types.Mixed\n , updateobj: Schema.Types.Mixed\n , ntoreturn: Number\n , nreturned: Number\n , nscanned: Number\n , responseLength: Number\n , client: String\n , user: String\n , idhack: Boolean\n , scanAndOrder: Boolean\n , keyUpdates: Number\n , cursorid: Number\n}, { noVirtualId: true, noId: true });" + } +] +### lib/schematype.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');\nvar CastError = require('./error').CastError;\nvar ValidatorError = require('./error').ValidatorError;", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "[options]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[instance]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    SchemaType constructor

    ", + "summary": "

    SchemaType constructor

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "function SchemaType (path, options, instance) {\n this.path = path;\n this.instance = instance;\n this.validators = [];\n this.setters = [];\n this.getters = [];\n this.options = options;\n this._index = null;\n this.selected;\n\n for (var i in options) if (this[i] && 'function' == typeof this[i]) {\n // { unique: true, index: true }\n if ('index' == i && this._index) continue;\n\n var opts = Array.isArray(options[i])\n ? options[i]\n : [options[i]];\n\n this[i].apply(this, opts);\n }\n};", + "ctx": { + "type": "function", + "name": "SchemaType", + "string": "SchemaType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function", + "any" + ], + "name": "val", + "description": "the default value" + }, + { + "type": "return", + "types": [ + "defaultValue" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets a default value for this SchemaType.

    \n\n

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    ", + "summary": "

    Sets a default value for this SchemaType.

    ", + "body": "

    Example:

    \n\n
    var schema = new Schema({ n: { type: Number, default: 10 })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.n) // 10\n
    \n\n

    Defaults can be either functions which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.

    \n\n

    Example:

    \n\n
    // values are cast:\nvar schema = new Schema({ aNumber: Number, default: \"4.815162342\" })\nvar M = db.model('M', schema)\nvar m = new M;\nconsole.log(m.aNumber) // 4.815162342\n\n// default unique objects for Mixed types:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default(function () {\n  return {};\n});\n\n// if we don't use a function to return object literals for Mixed defaults,\n// each document will receive a reference to the same object literal creating\n// a \"shared\" object instance:\nvar schema = new Schema({ mixed: Schema.Types.Mixed });\nschema.path('mixed').default({});\nvar M = db.model('M', schema);\nvar m1 = new M;\nm1.mixed.added = 1;\nconsole.log(m1.mixed); // { added: 1 }\nvar m2 = new M;\nconsole.log(m2.mixed); // { added: 1 }\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.default = function (val) {\n if (1 === arguments.length) {\n this.defaultValue = typeof val === 'function'\n ? val\n : this.cast(val);\n return this;\n } else if (arguments.length > 1) {\n this.defaultValue = utils.args(arguments);\n }\n return this.defaultValue;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "default", + "string": "SchemaType.prototype.default()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "Boolean", + "String" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares the index options for this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ loc: { type: [Number], index: '2d' })\nvar s = new Schema({ loc: { type: [Number], index: '2d', sparse: true })\nvar s = new Schema({ loc: { type: [Number], index: { type: '2d', sparse: true }})\nvar s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.date').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    ", + "summary": "

    Declares the index options for this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, index: true })\nvar s = new Schema({ loc: { type: [Number], index: '2d' })\nvar s = new Schema({ loc: { type: [Number], index: '2d', sparse: true })\nvar s = new Schema({ loc: { type: [Number], index: { type: '2d', sparse: true }})\nvar s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})\nSchema.path('my.path').index(true);\nSchema.path('my.date').index({ expires: 60 });\nSchema.path('my.path').index({ unique: true, sparse: true });\n
    \n\n

    NOTE:

    \n\n

    Indexes are created in the background by default. Specify background: false to override.

    \n\n

    Direction doesn't matter for single key indexes

    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.index = function (options) {\n this._index = options;\n utils.expires(this._index);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "index", + "string": "SchemaType.prototype.index()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares an unique index.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    \n\n

    NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.

    ", + "summary": "

    Declares an unique index.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, unique: true })\nSchema.path('name').index({ unique: true });\n
    \n\n

    NOTE: violating the constraint returns an E11000 error from MongoDB when saving, not a Mongoose validation error.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.unique = function (bool) {\n if (null == this._index || 'boolean' == typeof this._index) {\n this._index = {};\n } else if ('string' == typeof this._index) {\n this._index = { type: this._index };\n }\n\n this._index.unique = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "unique", + "string": "SchemaType.prototype.unique()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "bool", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Declares a sparse index.

    \n\n

    Example:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    ", + "summary": "

    Declares a sparse index.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ name: { type: String, sparse: true })\nSchema.path('name').index({ sparse: true });\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.sparse = function (bool) {\n if (null == this._index || 'boolean' == typeof this._index) {\n this._index = {};\n } else if ('string' == typeof this._index) {\n this._index = { type: this._index };\n }\n\n this._index.sparse = bool;\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "sparse", + "string": "SchemaType.prototype.sparse()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a setter to this schematype.

    \n\n

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    \n\n

    Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.

    \n\n
    function inspector (val, schematype) {\n  if (schematype.options.required) {\n    return schematype.path + ' is required';\n  } else {\n    return val;\n  }\n}\n\nvar VirusSchema = new Schema({\n  name: { type: String, required: true, set: inspector },\n  taxonomy: { type: String, set: inspector }\n})\n\nvar Virus = db.model('Virus', VirusSchema);\nvar v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });\n\nconsole.log(v.name);     // name is required\nconsole.log(v.taxonomy); // Parvovirinae\n
    ", + "summary": "

    Adds a setter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function capitalize (val) {\n  if ('string' != typeof val) val = '';\n  return val.charAt(0).toUpperCase() + val.substring(1);\n}\n\n// defining within the schema\nvar s = new Schema({ name: { type: String, set: capitalize }})\n\n// or by retreiving its SchemaType\nvar s = new Schema({ name: String })\ns.path('name').set(capitalize)\n
    \n\n

    Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.

    \n\n

    You can set up email lower case normalization easily via a Mongoose setter.

    \n\n
    function toLower (v) {\n  return v.toLowerCase();\n}\n\nvar UserSchema = new Schema({\n  email: { type: String, set: toLower }\n})\n\nvar User = db.model('User', UserSchema)\n\nvar user = new User({email: 'AVENUE@Q.COM'})\nconsole.log(user.email); // 'avenue@q.com'\n\n// or\nvar user = new User\nuser.email = 'Avenue@Q.com'\nconsole.log(user.email) // 'avenue@q.com'\n
    \n\n

    As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.

    \n\n

    NOTE: we could have also just used the built-in lowercase: true SchemaType option instead of defining our own function.

    \n\n
    new Schema({ email: { type: String, lowercase: true }})\n
    \n\n

    Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.

    \n\n
    function inspector (val, schematype) {\n  if (schematype.options.required) {\n    return schematype.path + ' is required';\n  } else {\n    return val;\n  }\n}\n\nvar VirusSchema = new Schema({\n  name: { type: String, required: true, set: inspector },\n  taxonomy: { type: String, set: inspector }\n})\n\nvar Virus = db.model('Virus', VirusSchema);\nvar v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });\n\nconsole.log(v.name);     // name is required\nconsole.log(v.taxonomy); // Parvovirinae\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.set = function (fn) {\n if ('function' != typeof fn)\n throw new TypeError('A setter must be a function.');\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "set", + "string": "SchemaType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a getter to this schematype.

    \n\n

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    \n\n

    Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.

    \n\n
    function inspector (val, schematype) {\n  if (schematype.options.required) {\n    return schematype.path + ' is required';\n  } else {\n    return schematype.path + ' is not';\n  }\n}\n\nvar VirusSchema = new Schema({\n  name: { type: String, required: true, get: inspector },\n  taxonomy: { type: String, get: inspector }\n})\n\nvar Virus = db.model('Virus', VirusSchema);\n\nVirus.findById(id, function (err, virus) {\n  console.log(virus.name);     // name is required\n  console.log(virus.taxonomy); // taxonomy is not\n})\n
    ", + "summary": "

    Adds a getter to this schematype.

    ", + "body": "

    Example:

    \n\n
    function dob (val) {\n  if (!val) return val;\n  return (val.getMonth() + 1) + \"/\" + val.getDate() + \"/\" + val.getFullYear();\n}\n\n// defining within the schema\nvar s = new Schema({ born: { type: Date, get: dob })\n\n// or by retreiving its SchemaType\nvar s = new Schema({ born: Date })\ns.path('born').get(dob)\n
    \n\n

    Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.

    \n\n

    Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:

    \n\n
    function obfuscate (cc) {\n  return '****-****-****-' + cc.slice(cc.length-4, cc.length);\n}\n\nvar AccountSchema = new Schema({\n  creditCardNumber: { type: String, get: obfuscate }\n});\n\nvar Account = db.model('Account', AccountSchema);\n\nAccount.findById(id, function (err, found) {\n  console.log(found.creditCardNumber); // '****-****-****-1234'\n});\n
    \n\n

    Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.

    \n\n
    function inspector (val, schematype) {\n  if (schematype.options.required) {\n    return schematype.path + ' is required';\n  } else {\n    return schematype.path + ' is not';\n  }\n}\n\nvar VirusSchema = new Schema({\n  name: { type: String, required: true, get: inspector },\n  taxonomy: { type: String, get: inspector }\n})\n\nvar Virus = db.model('Virus', VirusSchema);\n\nVirus.findById(id, function (err, virus) {\n  console.log(virus.name);     // name is required\n  console.log(virus.taxonomy); // taxonomy is not\n})\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.get = function (fn) {\n if ('function' != typeof fn)\n throw new TypeError('A getter must be a function.');\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "get", + "string": "SchemaType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "RegExp", + "Function", + "Object" + ], + "name": "obj", + "description": "validator" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[error]", + "description": "optional error message" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds validator(s) for this document path.

    \n\n

    Validators always receive the value to validate as their first argument and must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator (val) {\n  return val == 'something';\n}\n\nnew Schema({ name: { type: String, validate: validator }});\n\n// with a custom error message\n\nvar custom = [validator, 'validation failed']\nnew Schema({ name: { type: String, validate: custom }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The second argument is an callback function that must be passed either true or false when validation is complete.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.

    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    ", + "summary": "

    Adds validator(s) for this document path.

    ", + "body": "

    Validators always receive the value to validate as their first argument and must return Boolean. Returning false is interpreted as validation failure.

    \n\n

    Examples:

    \n\n
    function validator (val) {\n  return val == 'something';\n}\n\nnew Schema({ name: { type: String, validate: validator }});\n\n// with a custom error message\n\nvar custom = [validator, 'validation failed']\nnew Schema({ name: { type: String, validate: custom }});\n\nvar many = [\n    { validator: validator, msg: 'uh oh' }\n  , { validator: fn, msg: 'failed' }\n]\nnew Schema({ name: { type: String, validate: many }});\n\n// or utilizing SchemaType methods directly:\n\nvar schema = new Schema({ name: 'string' });\nschema.path('name').validate(validator, 'validation failed');\n
    \n\n

    Asynchronous validation:

    \n\n

    Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The second argument is an callback function that must be passed either true or false when validation is complete.

    \n\n
    schema.path('name').validate(function (value, respond) {\n  doStuff(value, function () {\n    ...\n    respond(false); // validation failed\n  })\n }, 'my error type');\n
    \n\n

    You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.

    \n\n

    Validation occurs pre('save') or whenever you manually execute document#validate.

    \n\n

    If validation fails during pre('save') and no callback was passed to receive the error, an error event will be emitted on your Models associated db connection, passing the validation error object along.

    \n\n
    var conn = mongoose.createConnection(..);\nconn.on('error', handleError);\n\nvar Product = conn.model('Product', yourSchema);\nvar dvd = new Product(..);\ndvd.save(); // emits error on the `conn` above\n
    \n\n

    If you desire handling these errors at the Model level, attach an error listener to your Model and the event will instead be emitted there.

    \n\n
    // registering an error listener on the Model lets us handle errors more locally\nProduct.on('error', handleError);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.validate = function (obj, error) {\n if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {\n this.validators.push([obj, error]);\n return this;\n }\n\n var i = arguments.length\n , arg\n\n while (i--) {\n arg = arguments[i];\n if (!(arg && 'Object' == arg.constructor.name)) {\n var msg = 'Invalid validator. Received (' + typeof arg + ') '\n + arg\n + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';\n\n throw new Error(msg);\n }\n this.validate(arg.validator, arg.msg);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "validate", + "string": "SchemaType.prototype.validate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "required", + "description": "enable/disable the validator" + }, + { + "type": "return", + "types": [ + "SchemaType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds a required validator to this schematype.

    \n\n

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    ", + "summary": "

    Adds a required validator to this schematype.

    ", + "body": "

    Example:

    \n\n
    var s = new Schema({ born: { type: Date, required: true })\n// or\nSchema.path('name').required(true);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.required = function (required) {\n var self = this;\n\n function __checkRequired (v) {\n // in here, `this` refers to the validating document.\n // no validation when this path wasn't selected in the query.\n if ('isSelected' in this &&\n !this.isSelected(self.path) &&\n !this.isModified(self.path)) return true;\n return self.checkRequired(v, this);\n }\n\n if (false === required) {\n this.isRequired = false;\n this.validators = this.validators.filter(function (v) {\n return v[0].name !== '__checkRequired';\n });\n } else {\n this.isRequired = true;\n this.validators.push([__checkRequired, 'required']);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "required", + "string": "SchemaType.prototype.required()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "the scope which callback are executed" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Gets the default value

    ", + "summary": "

    Gets the default value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.getDefault = function (scope, init) {\n var ret = 'function' === typeof this.defaultValue\n ? this.defaultValue.call(scope)\n : this.defaultValue;\n\n if (null !== ret && undefined !== ret) {\n return this.cast(ret, scope, init);\n } else {\n return ret;\n }\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "getDefault", + "string": "SchemaType.prototype.getDefault()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies setters

    ", + "summary": "

    Applies setters

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {\n if (SchemaType._isRef(this, value, scope, init)) {\n return init\n ? value\n : this.cast(value, scope, init, priorVal);\n }\n\n var v = value\n , setters = this.setters\n , len = setters.length\n\n if (!len) {\n if (null === v || undefined === v) return v;\n return this.cast(v, scope, init, priorVal)\n }\n\n while (len--) {\n v = setters[len].call(scope, v, this);\n }\n\n if (null === v || undefined === v) return v;\n\n // do not cast until all setters are applied #665\n v = this.cast(v, scope, init, priorVal);\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applySetters", + "string": "SchemaType.prototype.applySetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Applies getters to a value

    ", + "summary": "

    Applies getters to a value

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.applyGetters = function (value, scope) {\n if (SchemaType._isRef(this, value, scope, true)) return value;\n\n var v = value\n , getters = this.getters\n , len = getters.length;\n\n if (!len) {\n return v;\n }\n\n while (len--) {\n v = getters[len].call(scope, v, this);\n }\n\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "applyGetters", + "string": "SchemaType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets default select() behavior for this path.

    \n\n

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    ", + "summary": "

    Sets default select() behavior for this path.

    ", + "body": "

    Set to true if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

    \n\n

    Example:

    \n\n
    T = db.model('T', new Schema({ x: { type: String, select: true }}));\nT.find(..); // field x will always be selected ..\n// .. unless overridden;\nT.find().select('-x').exec(callback);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "SchemaType.prototype.select = function select (val) {\n this.selected = !! val;\n}", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "select", + "string": "SchemaType.prototype.select()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "summary": "

    Performs a validation of value using the validators declared for this SchemaType.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType.prototype.doValidate = function (value, fn, scope) {\n var err = false\n , path = this.path\n , count = this.validators.length;\n\n if (!count) return fn(null);\n\n function validate (ok, msg, val) {\n if (err) return;\n if (ok === undefined || ok) {\n --count || fn(null);\n } else {\n fn(err = new ValidatorError(path, msg, val));\n }\n }\n\n this.validators.forEach(function (v) {\n var validator = v[0]\n , message = v[1];\n\n if (validator instanceof RegExp) {\n validate(validator.test(value), message, value);\n } else if ('function' === typeof validator) {\n if (2 === validator.length) {\n validator.call(scope, value, function (ok) {\n validate(ok, message, value);\n });\n } else {\n validate(validator.call(scope, value), message, value);\n }\n }\n });\n};", + "ctx": { + "type": "method", + "constructor": "SchemaType", + "name": "doValidate", + "string": "SchemaType.prototype.doValidate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "SchemaType" + ], + "name": "self", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "init", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if value is a valid Reference.

    ", + "summary": "

    Determines if value is a valid Reference.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "SchemaType._isRef = function (self, value, doc, init) {\n // fast path\n var ref = init && self.options && self.options.ref;\n\n if (!ref && doc && doc.$__fullPath) {\n // checks for\n // - this populated with adhoc model and no ref was set in schema OR\n // - setting / pushing values after population\n var path = doc.$__fullPath(self.path);\n var owner = doc.ownerDocument ? doc.ownerDocument() : doc;\n ref = owner.populated(path);\n }\n\n if (ref) {\n if (null == value) return true;\n if (!Buffer.isBuffer(value) && // buffers are objects too\n 'Binary' != value._bsontype // raw binary value from the db\n && utils.isObject(value) // might have deselected _id in population query\n ) {\n return true;\n }\n }\n\n return false;\n}", + "ctx": { + "type": "method", + "receiver": "SchemaType", + "name": "_isRef", + "string": "SchemaType._isRef()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = SchemaType;\n\nexports.CastError = CastError;\n\nexports.ValidatorError = ValidatorError;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = SchemaType", + "string": "module.exports" + } + } +] +### lib/statemachine.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var utils = require('./utils');", + "ctx": { + "type": "declaration", + "name": "utils", + "value": "require('./utils')", + "string": "utils" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "summary": "

    StateMachine represents a minimal interface for the
    constructors it builds via StateMachine.ctor(...).

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "var StateMachine = module.exports = exports = function StateMachine () {\n this.paths = {};\n this.states = {};\n}", + "ctx": { + "type": "declaration", + "name": "StateMachine", + "value": "module.exports = exports = function StateMachine () {", + "string": "StateMachine" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "subclass constructor" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "summary": "

    StateMachine.ctor('state1', 'state2', ...)
    A factory method for subclassing StateMachine.
    The arguments are a list of states. For each state,
    the constructor's prototype gets state transition
    methods named after each state. These transition methods
    place their path argument into the given state.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.ctor = function () {\n var states = utils.args(arguments);\n\n var ctor = function () {\n StateMachine.apply(this, arguments);\n this.stateNames = states;\n\n var i = states.length\n , state;\n\n while (i--) {\n state = states[i];\n this.states[state] = {};\n }\n };\n\n ctor.prototype.__proto__ = StateMachine.prototype;\n\n states.forEach(function (state) {\n // Changes the `path`'s state to `state`.\n ctor.prototype[state] = function (path) {\n this._changeState(path, state);\n }\n });\n\n return ctor;\n};", + "ctx": { + "type": "method", + "receiver": "StateMachine", + "name": "ctor", + "string": "StateMachine.ctor()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function is wrapped by the state change functions

    \n\n
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    ", + "summary": "

    This function is wrapped by the state change functions

    ", + "body": "
      \n
    • require(path)
    • \n
    • modify(path)
    • \n
    • init(path)
    • \n
    " + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._changeState = function _changeState (path, nextState) {\n var prevBucket = this.states[this.paths[path]];\n if (prevBucket) delete prevBucket[path];\n\n this.paths[path] = nextState;\n this.states[nextState][path] = true;\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_changeState", + "string": "StateMachine.prototype._changeState()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "StateMachine.prototype.clear = function clear (state) {\n var keys = Object.keys(this.states[state])\n , i = keys.length\n , path\n\n while (i--) {\n path = keys[i];\n delete this.states[state][path];\n delete this.paths[path];\n }\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "clear", + "string": "StateMachine.prototype.clear()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "state", + "description": "that we want to check for." + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "summary": "

    Checks to see if at least one path is in the states passed in via arguments
    e.g., this.some('required', 'inited')

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.some = function some () {\n var self = this;\n var what = arguments.length ? arguments : this.stateNames;\n return Array.prototype.some.call(what, function (state) {\n return Object.keys(self.states[state]).length;\n });\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "some", + "string": "StateMachine.prototype.some()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "iterMethod", + "description": "is either 'forEach' or 'map'" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "summary": "

    This function builds the functions that get assigned to forEach and map,
    since both of those methods share a lot of the same logic.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "StateMachine.prototype._iter = function _iter (iterMethod) {\n return function () {\n var numArgs = arguments.length\n , states = utils.args(arguments, 0, numArgs-1)\n , callback = arguments[numArgs-1];\n\n if (!states.length) states = this.stateNames;\n\n var self = this;\n\n var paths = states.reduce(function (paths, state) {\n return paths.concat(Object.keys(self.states[state]));\n }, []);\n\n return paths[iterMethod](function (path, i, paths) {\n return callback(path, i, paths);\n });\n };\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "_iter", + "string": "StateMachine.prototype._iter()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Iterates over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Iterates over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.forEach = function forEach () {\n this.forEach = this._iter('forEach');\n return this.forEach.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "forEach", + "string": "StateMachine.prototype.forEach()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "[state]", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Maps over the paths that belong to one of the parameter states.

    \n\n

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    ", + "summary": "

    Maps over the paths that belong to one of the parameter states.

    ", + "body": "

    The function profile can look like

    \n\n

    this.forEach(state1, fn); // iterates over all paths in state1
    this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
    this.forEach(fn); // iterates over all paths in all states

    " + }, + "isPrivate": false, + "ignore": true, + "code": "StateMachine.prototype.map = function map () {\n this.map = this._iter('map');\n return this.map.apply(this, arguments);\n}", + "ctx": { + "type": "method", + "constructor": "StateMachine", + "name": "map", + "string": "StateMachine.prototype.map()" + } + } +] +### lib/types/array.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var EmbeddedDocument = require('./embedded');\nvar Document = require('../document');\nvar ObjectId = require('./objectid');\nvar utils = require('../utils');\nvar isMongooseObject = utils.isMongooseObject;", + "ctx": { + "type": "declaration", + "name": "EmbeddedDocument", + "value": "require('./embedded')", + "string": "EmbeddedDocument" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Array" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Array constructor.

    \n\n

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    ", + "summary": "

    Mongoose Array constructor.

    ", + "body": "

    NOTE:

    \n\n

    Values always have to be passed to the constructor to initialize, otherwise MongooseArray#push will mark the array as modified.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseArray (values, path, doc) {\n var arr = [];\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseArray", + "string": "MongooseArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Array

    ", + "summary": "

    Inherit from Array

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseArray.prototype = new Array;", + "ctx": { + "type": "property", + "receiver": "MongooseArray", + "name": "prototype", + "value": "new Array", + "string": "MongooseArray.prototype" + } + }, + { + "tags": [ + { + "type": "property", + "string": "_atomics" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Stores a queue of atomic operations to perform

    ", + "summary": "

    Stores a queue of atomic operations to perform

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._atomics;" + }, + { + "tags": [ + { + "type": "property", + "string": "_parent" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._parent;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "value", + "description": "" + }, + { + "type": "return", + "types": [ + "value" + ], + "description": "the casted value" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Casts a member based on this arrays schema.

    ", + "summary": "

    Casts a member based on this arrays schema.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._cast = function (value) {\n var owner = this._owner;\n var populated = false;\n var Model;\n\n if (this._parent) {\n // if a populated array, we must cast to the same model\n // instance as specified in the original query.\n if (!owner) {\n owner = this._owner = this._parent.ownerDocument\n ? this._parent.ownerDocument()\n : this._parent;\n }\n\n populated = owner.populated(this._path, true);\n }\n\n if (populated && null != value) {\n // cast to the populated Models schema\n var Model = populated.options.model;\n\n // only objects are permitted so we can safely assume that\n // non-objects are to be interpreted as _id\n if (Buffer.isBuffer(value) ||\n value instanceof ObjectId || !utils.isObject(value)) {\n value = { _id: value };\n }\n\n value = new Model(value);\n return this._schema.caster.cast(value, this._parent, true)\n }\n\n return this._schema.caster.cast(value, this._parent, false)\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_cast", + "string": "MongooseArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "EmbeddedDocument" + ], + "name": "embeddedDoc", + "description": "the embedded doc that invoked this method on the Array" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "embeddedPath", + "description": "the path which changed in the embeddedDoc" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this array as modified.

    \n\n

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    ", + "summary": "

    Marks this array as modified.

    ", + "body": "

    If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

    " + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._markModified = function (elem, embeddedPath) {\n var parent = this._parent\n , dirtyPath;\n\n if (parent) {\n dirtyPath = this._path;\n\n if (arguments.length) {\n if (null != embeddedPath) {\n // an embedded doc bubbled up the change\n dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;\n } else {\n // directly set an index\n dirtyPath = dirtyPath + '.' + elem;\n }\n }\n parent.markModified(dirtyPath);\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_markModified", + "string": "MongooseArray.prototype._markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "op", + "description": "operation" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "val", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Register an atomic operation with the parent.

    ", + "summary": "

    Register an atomic operation with the parent.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype._registerAtomic = function (op, val) {\n if ('$set' == op) {\n // $set takes precedence over all other ops.\n // mark entire array modified.\n this._atomics = { $set: val };\n return this;\n }\n\n var atomics = this._atomics;\n\n // reset pop/shift after save\n if ('$pop' == op && !('$pop' in atomics)) {\n var self = this;\n this._parent.once('save', function () {\n self._popped = self._shifted = null;\n });\n }\n\n // check for impossible $atomic combos (Mongo denies more than one\n // $atomic op on a single path\n if (this._atomics.$set ||\n Object.keys(atomics).length && !(op in atomics)) {\n // a different op was previously registered.\n // save the entire thing.\n this._atomics = { $set: this };\n return this;\n }\n\n if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {\n atomics[op] || (atomics[op] = []);\n atomics[op] = atomics[op].concat(val);\n } else if (op === '$pullDocs') {\n var pullOp = atomics['$pull'] || (atomics['$pull'] = {})\n , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });\n selector['$in'] = selector['$in'].concat(val);\n } else {\n atomics[op] = val;\n }\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "_registerAtomic", + "string": "MongooseArray.prototype._registerAtomic()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "method", + "string": "$__getAtomics" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.

    \n\n

    If no atomics exist, we return all array values after conversion.

    ", + "summary": "

    Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.

    ", + "body": "

    If no atomics exist, we return all array values after conversion.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype.$__getAtomics = function () {\n var ret = [];\n var keys = Object.keys(this._atomics);\n var i = keys.length;\n\n if (0 === i) {\n ret[0] = ['$set', this.toObject({ depopulate: 1 })];\n return ret;\n }\n\n while (i--) {\n var op = keys[i];\n var val = this._atomics[op];\n\n // the atomic values which are arrays are not MongooseArrays. we\n // need to convert their elements as if they were MongooseArrays\n // to handle populated arrays versus DocumentArrays properly.\n if (isMongooseObject(val)) {\n val = val.toObject({ depopulate: 1 });\n } else if (Array.isArray(val)) {\n val = this.toObject.call(val, { depopulate: 1 });\n } else if (val.valueOf) {\n val = val.valueOf();\n }\n\n if ('$addToSet' == op) {\n val = { $each: val }\n }\n\n ret.push([op, val]);\n }\n\n return ret;\n}" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "summary": "

    Returns the number of pending atomic operations to send to the db for this array.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseArray.prototype.hasAtomics = function hasAtomics () {\n if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {\n return 0;\n }\n\n return Object.keys(this._atomics).length;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "hasAtomics", + "string": "MongooseArray.prototype.hasAtomics()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#push with proper change tracking.

    ", + "summary": "

    Wraps Array#push with proper change tracking.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.push = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n\n // $pushAll might be fibbed (could be $push). But it makes it easier to\n // handle what could have been $push, $pushAll combos\n this._registerAtomic('$pushAll', values);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "push", + "string": "MongooseArray.prototype.push()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pushes items to the array non-atomically.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Pushes items to the array non-atomically.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.nonAtomicPush = function () {\n var values = [].map.call(arguments, this._cast, this)\n , ret = [].push.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "nonAtomicPush", + "string": "MongooseArray.prototype.nonAtomicPush()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "method", + "string": "$pop" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Pops the array atomically at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    ", + "summary": "

    Pops the array atomically at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var popped = doc.array.$pop();\n console.log(popped); // 3\n console.log(doc.array); // [1,2]\n\n // no affect\n popped = doc.array.$pop();\n console.log(doc.array); // [1,2]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $pop works again\n   popped = doc.array.$pop();\n   console.log(popped); // 2\n   console.log(doc.array); // [1]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$pop = function () {\n this._registerAtomic('$pop', 1);\n this._markModified();\n\n // only allow popping once\n if (this._popped) return;\n this._popped = true;\n\n return [].pop.call(this);\n};" + }, + { + "tags": [ + { + "type": "see", + "local": "MongooseArray#$pop #types_array_MongooseArray-%24pop", + "visibility": "MongooseArray#$pop" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#pop with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#pop with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pop = function () {\n var ret = [].pop.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pop", + "string": "MongooseArray.prototype.pop()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "method", + "string": "$shift" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop" + } + ], + "description": { + "full": "

    Atomically shifts the array at most one time per document save().

    \n\n

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    ", + "summary": "

    Atomically shifts the array at most one time per document save().

    ", + "body": "

    NOTE:

    \n\n

    Calling this mulitple times on an array before saving sends the same command as calling it once.
    This update is implemented using the MongoDB $pop method which enforces this restriction.

    \n\n
     doc.array = [1,2,3];\n\n var shifted = doc.array.$shift();\n console.log(shifted); // 1\n console.log(doc.array); // [2,3]\n\n // no affect\n shifted = doc.array.$shift();\n console.log(doc.array); // [2,3]\n\n doc.save(function (err) {\n   if (err) return handleError(err);\n\n   // we saved, now $shift works again\n   shifted = doc.array.$shift();\n   console.log(shifted ); // 2\n   console.log(doc.array); // [3]\n })\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.$shift = function $shift () {\n this._registerAtomic('$pop', -1);\n this._markModified();\n\n // only allow shifting once\n if (this._shifted) return;\n this._shifted = true;\n\n return [].shift.call(this);\n};" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#shift with proper change tracking.

    \n\n

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#shift with proper change tracking.

    ", + "body": "

    Example:

    \n\n
    doc.array = [2,3];\nvar res = doc.array.shift();\nconsole.log(res) // 2\nconsole.log(doc.array) // [3]\n
    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.shift = function () {\n var ret = [].shift.call(this);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "shift", + "string": "MongooseArray.prototype.shift()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Pulls items from the array atomically.

    \n\n

    Examples:

    \n\n
    doc.array.pull(ObjectId)\ndoc.array.pull({ _id: 'someId' })\ndoc.array.pull(36)\ndoc.array.pull('tag 1', 'tag 2')\n
    \n\n

    To remove a document from a subdocument array we may pass an object with a matching _id.

    \n\n
    doc.subdocs.push({ _id: 4815162342 })\ndoc.subdocs.pull({ _id: 4815162342 }) // removed\n
    \n\n

    Or we may passing the _id directly and let mongoose take care of it.

    \n\n
    doc.subdocs.push({ _id: 4815162342 })\ndoc.subdocs.pull(4815162342); // works\n
    ", + "summary": "

    Pulls items from the array atomically.

    ", + "body": "

    Examples:

    \n\n
    doc.array.pull(ObjectId)\ndoc.array.pull({ _id: 'someId' })\ndoc.array.pull(36)\ndoc.array.pull('tag 1', 'tag 2')\n
    \n\n

    To remove a document from a subdocument array we may pass an object with a matching _id.

    \n\n
    doc.subdocs.push({ _id: 4815162342 })\ndoc.subdocs.pull({ _id: 4815162342 }) // removed\n
    \n\n

    Or we may passing the _id directly and let mongoose take care of it.

    \n\n
    doc.subdocs.push({ _id: 4815162342 })\ndoc.subdocs.pull(4815162342); // works\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.pull = function () {\n var values = [].map.call(arguments, this._cast, this)\n , cur = this._parent.get(this._path)\n , i = cur.length\n , mem;\n\n while (i--) {\n mem = cur[i];\n if (mem instanceof EmbeddedDocument) {\n if (values.some(function (v) { return v.equals(mem); } )) {\n [].splice.call(cur, i, 1);\n }\n } else if (~cur.indexOf.call(values, mem)) {\n [].splice.call(cur, i, 1);\n }\n }\n\n if (values[0] instanceof EmbeddedDocument) {\n this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));\n } else {\n this._registerAtomic('$pullAll', values);\n }\n\n this._markModified();\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "pull", + "string": "MongooseArray.prototype.pull()" + } + }, + { + "tags": [ + { + "type": "see", + "local": "MongooseArray#pull #types_array_MongooseArray-pull", + "visibility": "MongooseArray#pull" + }, + { + "type": "see", + "title": "mongodb", + "url": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull", + "visibility": "http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull" + }, + { + "type": "api", + "visibility": "public" + }, + { + "type": "memberOf", + "parent": "MongooseArray" + }, + { + "type": "method", + "string": "remove" + } + ], + "description": { + "full": "

    Alias of pull

    ", + "summary": "

    Alias of pull

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.remove = MongooseArray.prototype.pull;", + "ctx": { + "type": "property", + "constructor": "MongooseArray", + "name": "remove", + "value": "MongooseArray.prototype.pull", + "string": "MongooseArray.prototyperemove" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#splice with proper change tracking and casting.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#splice with proper change tracking and casting.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.splice = function splice () {\n var ret, vals, i;\n\n if (arguments.length) {\n vals = [];\n for (i = 0; i < arguments.length; ++i) {\n vals[i] = i < 2\n ? arguments[i]\n : this._cast(arguments[i]);\n }\n ret = [].splice.apply(this, vals);\n this._registerAtomic('$set', this);\n this._markModified();\n }\n\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "splice", + "string": "MongooseArray.prototype.splice()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#unshift with proper change tracking.

    \n\n

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#unshift with proper change tracking.

    ", + "body": "

    Note:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.unshift = function () {\n var values = [].map.call(arguments, this._cast, this);\n [].unshift.apply(this, values);\n this._registerAtomic('$set', this);\n this._markModified();\n return this.length;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "unshift", + "string": "MongooseArray.prototype.unshift()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Wraps Array#sort with proper change tracking.

    \n\n

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    ", + "summary": "

    Wraps Array#sort with proper change tracking.

    ", + "body": "

    NOTE:

    \n\n

    marks the entire array as modified, which if saved, will store it as a $set operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.sort = function () {\n var ret = [].sort.apply(this, arguments);\n this._registerAtomic('$set', this);\n this._markModified();\n return ret;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "sort", + "string": "MongooseArray.prototype.sort()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "[args...]", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "the values that were added" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Adds values to the array if not already present.

    \n\n

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    ", + "summary": "

    Adds values to the array if not already present.

    ", + "body": "

    Example:

    \n\n
    console.log(doc.array) // [2,3,4]\nvar added = doc.array.addToSet(4,5);\nconsole.log(doc.array) // [2,3,4,5]\nconsole.log(added)     // [5]\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.addToSet = function addToSet () {\n var values = [].map.call(arguments, this._cast, this)\n , added = []\n , type = values[0] instanceof EmbeddedDocument ? 'doc' :\n values[0] instanceof Date ? 'date' :\n '';\n\n values.forEach(function (v) {\n var found;\n switch (type) {\n case 'doc':\n found = this.some(function(doc){ return doc.equals(v) });\n break;\n case 'date':\n var val = +v;\n found = this.some(function(d){ return +d === val });\n break;\n default:\n found = ~this.indexOf(v);\n }\n\n if (!found) {\n [].push.call(this, v);\n this._registerAtomic('$addToSet', v);\n this._markModified();\n [].push.call(added, v);\n }\n }, this);\n\n return added;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "addToSet", + "string": "MongooseArray.prototype.addToSet()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Sets the casted val at index i and marks the array modified.

    \n\n

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    ", + "summary": "

    Sets the casted val at index i and marks the array modified.

    ", + "body": "

    Example:

    \n\n
    // given documents based on the following\nvar Doc = mongoose.model('Doc', new Schema({ array: [Number] }));\n\nvar doc = new Doc({ array: [2,3,4] })\n\nconsole.log(doc.array) // [2,3,4]\n\ndoc.array.set(1,\"5\");\nconsole.log(doc.array); // [2,5,4] // properly cast to number\ndoc.save() // the change is saved\n\n// VS not using array#set\ndoc.array[1] = \"5\";\nconsole.log(doc.array); // [2,\"5\",4] // no casting\ndoc.save() // change is not saved\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.set = function set (i, val) {\n this[i] = this._cast(val);\n this._markModified(i);\n return this;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "set", + "string": "MongooseArray.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array.

    ", + "summary": "

    Returns a native js Array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.toObject = function (options) {\n if (options && options.depopulate) {\n return this.map(function (doc) {\n // this is called on populated arrays too\n return doc instanceof Document\n ? doc._id\n : doc\n });\n }\n\n return this.slice()\n}", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "toObject", + "string": "MongooseArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n return ' ' + doc;\n }) + ' ]';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "inspect", + "string": "MongooseArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the item to look for" + }, + { + "type": "return", + "types": [ + "Number" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Return the index of obj or -1 if not found.

    ", + "summary": "

    Return the index of obj or -1 if not found.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseArray.prototype.indexOf = function indexOf (obj) {\n if (obj instanceof ObjectId) obj = obj.toString();\n for (var i = 0, len = this.length; i < len; ++i) {\n if (obj == this[i])\n return i;\n }\n return -1;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseArray", + "name": "indexOf", + "string": "MongooseArray.prototype.indexOf()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = exports = MongooseArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "exports = MongooseArray", + "string": "module.exports" + } + } +] +### lib/types/buffer.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Binary = require(driver + '/binary');", + "ctx": { + "type": "declaration", + "name": "Binary", + "value": "require(driver + '/binary')", + "string": "Binary" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "encode", + "description": "" + }, + { + "type": "param", + "types": [ + "Number" + ], + "name": "offset", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "inherits", + "string": "Buffer" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    Mongoose Buffer constructor.

    \n\n

    Values always have to be passed to the constructor to initialize.

    ", + "summary": "

    Mongoose Buffer constructor.

    ", + "body": "

    Values always have to be passed to the constructor to initialize.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseBuffer (value, encode, offset) {\n var length = arguments.length;\n var val;\n\n if (0 === length || null === arguments[0] || undefined === arguments[0]) {\n val = 0;\n } else {\n val = value;\n }\n\n var encoding;\n var path;\n var doc;\n\n if (Array.isArray(encode)) {\n // internal casting\n path = encode[0];\n doc = encode[1];\n } else {\n encoding = encode;\n }\n\n var buf = new Buffer(val, encoding, offset);\n buf.__proto__ = MongooseBuffer.prototype;\n\n // make sure these internal props don't show up in Object.keys()\n Object.defineProperties(buf, {\n validators: { value: [] }\n , _path: { value: path }\n , _parent: { value: doc }\n });\n\n if (doc && \"string\" === typeof path) {\n Object.defineProperty(buf, '_schema', {\n value: doc.schema.path(path)\n });\n }\n\n return buf;\n};", + "ctx": { + "type": "function", + "name": "MongooseBuffer", + "string": "MongooseBuffer()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Buffer.

    ", + "summary": "

    Inherit from Buffer.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.prototype = new Buffer(0);", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "prototype", + "value": "new Buffer(0)", + "string": "MongooseBuffer.prototype" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + }, + { + "type": "property", + "string": "_parent" + } + ], + "description": { + "full": "

    Parent owner document

    ", + "summary": "

    Parent owner document

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._parent;" + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Marks this buffer as modified.

    ", + "summary": "

    Marks this buffer as modified.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseBuffer.prototype._markModified = function () {\n var parent = this._parent;\n\n if (parent) {\n parent.markModified(this._path);\n }\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "_markModified", + "string": "MongooseBuffer.prototype._markModified()" + } + }, + { + "tags": [], + "description": { + "full": "

    Writes the buffer.

    ", + "summary": "

    Writes the buffer.

    ", + "body": "" + }, + "ignore": false, + "code": "MongooseBuffer.prototype.write = function () {\n var written = Buffer.prototype.write.apply(this, arguments);\n\n if (written > 0) {\n this._markModified();\n }\n\n return written;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "write", + "string": "MongooseBuffer.prototype.write()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "MongooseBuffer" + ], + "description": "" + }, + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "target", + "description": "" + } + ], + "description": { + "full": "

    Copies the buffer.

    \n\n

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    ", + "summary": "

    Copies the buffer.

    ", + "body": "

    Note:

    \n\n

    Buffer#copy does not mark target as modified so you must copy from a MongooseBuffer for it to work as expected. This is a work around since copy modifies the target, not this.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.copy = function (target) {\n var ret = Buffer.prototype.copy.apply(this, arguments);\n\n if (target instanceof MongooseBuffer) {\n target._markModified();\n }\n\n return ret;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "copy", + "string": "MongooseBuffer.prototype.copy()" + } + }, + { + "tags": [], + "description": { + "full": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "summary": "

    Compile other Buffer methods marking this buffer as modified.

    ", + "body": "" + }, + "ignore": true, + "code": ";(\n// node < 0.5\n'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +\n'writeFloat writeDouble fill ' +\n'utf8Write binaryWrite asciiWrite set ' +\n\n// node >= 0.5\n'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +\n'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +\n'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'\n).split(' ').forEach(function (method) {\n if (!Buffer.prototype[method]) return;\n MongooseBuffer.prototype[method] = new Function(\n 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +\n 'this._markModified();' +\n 'return ret;'\n )\n});" + }, + { + "tags": [ + { + "type": "see", + "title": "", + "url": "http://bsonspec.org/#/specification", + "visibility": "http://bsonspec.org/#/specification" + }, + { + "type": "param", + "types": [ + "Hex" + ], + "name": "[subtype]", + "description": "" + }, + { + "type": "return", + "types": [ + "Binary" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Converts this buffer to its Binary type representation.

    \n\n

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    ", + "summary": "

    Converts this buffer to its Binary type representation.

    ", + "body": "

    SubTypes:

    \n\n
      \n
    • 0x00: Binary/Generic
    • \n
    • 0x01: Function
    • \n
    • 0x02: Binary (Deprecated, 0x00 is new default)
    • \n
    • 0x03: UUID
    • \n
    • 0x04: MD5
    • \n
    • 0x80: User Defined
    • \n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.toObject = function (options) {\n var subtype = 'number' == typeof options\n ? options\n : 0x00;\n return new Binary(this, subtype);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "toObject", + "string": "MongooseBuffer.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Buffer" + ], + "name": "other", + "description": "" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + } + ], + "description": { + "full": "

    Determines if this buffer is equals to other buffer

    ", + "summary": "

    Determines if this buffer is equals to other buffer

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseBuffer.prototype.equals = function (other) {\n if (!Buffer.isBuffer(other)) {\n return false;\n }\n\n if (this.length !== other.length) {\n return false;\n }\n\n for (var i = 0; i < this.length; ++i) {\n if (this[i] !== other[i]) return false;\n }\n\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "MongooseBuffer", + "name": "equals", + "string": "MongooseBuffer.prototype.equals()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseBuffer.Binary = Binary;\n\nmodule.exports = MongooseBuffer;", + "ctx": { + "type": "property", + "receiver": "MongooseBuffer", + "name": "Binary", + "value": "Binary", + "string": "MongooseBuffer.Binary" + } + } +] +### lib/types/documentarray.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var MongooseArray = require('./array')\n , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'\n , ObjectId = require(driver + '/objectid')\n , ObjectIdSchema = require('../schema/objectid')\n , utils = require('../utils')\n , util = require('util')", + "ctx": { + "type": "declaration", + "name": "MongooseArray", + "value": "require('./array')", + "string": "MongooseArray" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "values", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path to this array" + }, + { + "type": "param", + "types": [ + "Document" + ], + "name": "doc", + "description": "parent document" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "MongooseDocumentArray" + ], + "description": "" + }, + { + "type": "inherits", + "string": "MongooseArray" + }, + { + "type": "see", + "title": "", + "url": "http://bit.ly/f6CnZU", + "visibility": "http://bit.ly/f6CnZU" + } + ], + "description": { + "full": "

    DocumentArray constructor

    ", + "summary": "

    DocumentArray constructor

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function MongooseDocumentArray (values, path, doc) {\n var arr = [];\n\n // Values always have to be passed to the constructor to initialize, since\n // otherwise MongooseArray#push will mark the array as modified to the parent.\n arr.push.apply(arr, values);\n arr.__proto__ = MongooseDocumentArray.prototype;\n\n arr._atomics = {};\n arr.validators = [];\n arr._path = path;\n\n if (doc) {\n arr._parent = doc;\n arr._schema = doc.schema.path(path);\n doc.on('save', arr.notify('save'));\n doc.on('isNew', arr.notify('isNew'));\n }\n\n return arr;\n};", + "ctx": { + "type": "function", + "name": "MongooseDocumentArray", + "string": "MongooseDocumentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherits from MongooseArray

    ", + "summary": "

    Inherits from MongooseArray

    ", + "body": "" + }, + "ignore": true, + "code": "MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;", + "ctx": { + "type": "property", + "constructor": "MongooseDocumentArray", + "name": "__proto__", + "value": "MongooseArray.prototype", + "string": "MongooseDocumentArray.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Overrides MongooseArray#cast

    ", + "summary": "

    Overrides MongooseArray#cast

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype._cast = function (value) {\n if (value instanceof this._schema.casterConstructor) {\n return value;\n }\n\n // handle cast('string') or cast(ObjectId) etc.\n // only objects are permitted so we can safely assume that\n // non-objects are to be interpreted as _id\n if (Buffer.isBuffer(value) ||\n value instanceof ObjectId || !utils.isObject(value)) {\n value = { _id: value };\n }\n\n return new this._schema.casterConstructor(value, this);\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "_cast", + "string": "MongooseDocumentArray.prototype._cast()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "EmbeddedDocument", + "null" + ], + "description": "the subdocuent or null if not found." + }, + { + "type": "param", + "types": [ + "ObjectId", + "String", + "Number", + "Buffer" + ], + "name": "id", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Searches array items for the first document with a matching _id.

    \n\n

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    ", + "summary": "

    Searches array items for the first document with a matching _id.

    ", + "body": "

    Example:

    \n\n
    var embeddedDoc = m.array.id(some_id);\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.id = function (id) {\n var casted\n , _id;\n\n try {\n casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));\n } catch (e) {\n casted = null;\n }\n\n for (var i = 0, l = this.length; i < l; i++) {\n _id = this[i].get('_id');\n if (!(_id instanceof ObjectId)) {\n if (String(id) == _id)\n return this[i];\n } else {\n if (casted == _id)\n return this[i];\n }\n }\n\n return null;\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "id", + "string": "MongooseDocumentArray.prototype.id()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns a native js Array of plain js objects

    \n\n

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    ", + "summary": "

    Returns a native js Array of plain js objects

    ", + "body": "

    NOTE:

    \n\n

    Each sub-document is converted to a plain object by calling its #toObject method.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.toObject = function () {\n return this.map(function (doc) {\n return doc && doc.toObject() || null;\n });\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "toObject", + "string": "MongooseDocumentArray.prototype.toObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.inspect = function () {\n return '[' + this.map(function (doc) {\n if (doc) {\n return doc.inspect\n ? doc.inspect()\n : util.inspect(doc)\n }\n return 'null'\n }).join('\\n') + ']';\n};", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "inspect", + "string": "MongooseDocumentArray.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the value to cast to this arrays SubDocument schema" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Creates a subdocument casted to this schema.

    \n\n

    This is the same subdocument constructor used for casting.

    ", + "summary": "

    Creates a subdocument casted to this schema.

    ", + "body": "

    This is the same subdocument constructor used for casting.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "MongooseDocumentArray.prototype.create = function (obj) {\n return new this._schema.casterConstructor(obj);\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "create", + "string": "MongooseDocumentArray.prototype.create()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "event", + "description": "" + }, + { + "type": "return", + "types": [ + "Function" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates a fn that notifies all child docs of event.

    ", + "summary": "

    Creates a fn that notifies all child docs of event.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "MongooseDocumentArray.prototype.notify = function notify (event) {\n var self = this;\n return function notify (val) {\n var i = self.length;\n while (i--) {\n if (!self[i]) continue;\n self[i].emit(event, val);\n }\n }\n}", + "ctx": { + "type": "method", + "constructor": "MongooseDocumentArray", + "name": "notify", + "string": "MongooseDocumentArray.prototype.notify()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = MongooseDocumentArray;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "MongooseDocumentArray", + "string": "module.exports" + } + } +] +### lib/types/embedded.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var Document = require('../document')\n , inspect = require('util').inspect;", + "ctx": { + "type": "declaration", + "name": "Document", + "value": "require('../document')", + "string": "Document" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "js object returned from the db" + }, + { + "type": "param", + "types": [ + "MongooseDocumentArray" + ], + "name": "parentArr", + "description": "the parent array of this document" + }, + { + "type": "param", + "types": [ + "Boolean" + ], + "name": "skipId", + "description": "" + }, + { + "type": "inherits", + "string": "Document" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    EmbeddedDocument constructor.

    ", + "summary": "

    EmbeddedDocument constructor.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "function EmbeddedDocument (obj, parentArr, skipId, fields) {\n if (parentArr) {\n this.__parentArray = parentArr;\n this.__parent = parentArr._parent;\n } else {\n this.__parentArray = undefined;\n this.__parent = undefined;\n }\n\n Document.call(this, obj, fields, skipId);\n\n var self = this;\n this.on('isNew', function (val) {\n self.isNew = val;\n });\n};", + "ctx": { + "type": "function", + "name": "EmbeddedDocument", + "string": "EmbeddedDocument()" + } + }, + { + "tags": [], + "description": { + "full": "

    Inherit from Document

    ", + "summary": "

    Inherit from Document

    ", + "body": "" + }, + "ignore": true, + "code": "EmbeddedDocument.prototype.__proto__ = Document.prototype;", + "ctx": { + "type": "property", + "constructor": "EmbeddedDocument", + "name": "__proto__", + "value": "Document.prototype", + "string": "EmbeddedDocument.prototype__proto__" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the path which changed" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks the embedded doc modified.

    \n\n

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    ", + "summary": "

    Marks the embedded doc modified.

    ", + "body": "

    Example:

    \n\n
    var doc = blogpost.comments.id(hexstring);\ndoc.mixed.type = 'changed';\ndoc.markModified('mixed.type');\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.markModified = function (path) {\n if (!this.__parentArray) return;\n\n this.$__.activePaths.modify(path);\n\n if (this.isNew) {\n // Mark the WHOLE parent array as modified\n // if this is a new document (i.e., we are initializing\n // a document),\n this.__parentArray._markModified();\n } else\n this.__parentArray._markModified(this, path);\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "markModified", + "string": "EmbeddedDocument.prototype.markModified()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "return", + "types": [ + "EmbeddedDocument" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Used as a stub for hooks.js

    \n\n

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    ", + "summary": "

    Used as a stub for hooks.js

    ", + "body": "

    NOTE:

    \n\n

    This is a no-op. Does not actually save the doc to the db.

    " + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.save = function(fn) {\n if (fn)\n fn(null);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "save", + "string": "EmbeddedDocument.prototype.save()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "[fn]", + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Removes the subdocument from its parent array.

    ", + "summary": "

    Removes the subdocument from its parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.remove = function (fn) {\n if (!this.__parentArray) return this;\n\n var _id;\n if (!this.willRemove) {\n _id = this._doc._id;\n if (!_id) {\n throw new Error('For your own good, Mongoose does not know ' +\n 'how to remove an EmbeddedDocument that has no _id');\n }\n this.__parentArray.pull({ _id: _id });\n this.willRemove = true;\n }\n\n if (fn)\n fn(null);\n\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "remove", + "string": "EmbeddedDocument.prototype.remove()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Override #update method of parent documents.

    ", + "summary": "

    Override #update method of parent documents.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.update = function () {\n throw new Error('The #update method is not available on EmbeddedDocuments');\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "update", + "string": "EmbeddedDocument.prototype.update()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Helper for console.log

    ", + "summary": "

    Helper for console.log

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.inspect = function () {\n return inspect(this.toObject());\n};", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "inspect", + "string": "EmbeddedDocument.prototype.inspect()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "the field to invalidate" + }, + { + "type": "param", + "types": [ + "String", + "Error" + ], + "name": "err", + "description": "error which states the reason `path` was invalid" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Marks a path as invalid, causing validation to fail.

    ", + "summary": "

    Marks a path as invalid, causing validation to fail.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.invalidate = function (path, err, val, first) {\n if (!this.__parent) {\n var msg = 'Unable to invalidate a subdocument that has not been added to an array.'\n throw new Error(msg);\n }\n\n var index = this.__parentArray.indexOf(this);\n var parentPath = this.__parentArray._path;\n var fullPath = [parentPath, index, path].join('.');\n\n // sniffing arguments:\n // need to check if user passed a value to keep\n // our error message clean.\n if (2 < arguments.length) {\n this.__parent.invalidate(fullPath, err, val);\n } else {\n this.__parent.invalidate(fullPath, err);\n }\n\n if (first)\n this.$__.validationError = this.ownerDocument().$__.validationError;\n return true;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "invalidate", + "string": "EmbeddedDocument.prototype.invalidate()" + } + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Document" + ], + "description": "" + } + ], + "description": { + "full": "

    Returns the top level document of this sub-document.

    ", + "summary": "

    Returns the top level document of this sub-document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.ownerDocument = function () {\n if (this.$__.ownerDocument) {\n return this.$__.ownerDocument;\n }\n\n var parent = this.__parent;\n if (!parent) return this;\n\n while (parent.__parent) {\n parent = parent.__parent;\n }\n\n return this.$__.ownerDocument = parent;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "ownerDocument", + "string": "EmbeddedDocument.prototype.ownerDocument()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "[path]", + "description": "" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "method", + "string": "$__fullPath" + }, + { + "type": "memberOf", + "parent": "EmbeddedDocument" + } + ], + "description": { + "full": "

    Returns the full path to this document. If optional path is passed, it is appended to the full path.

    ", + "summary": "

    Returns the full path to this document. If optional path is passed, it is appended to the full path.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "EmbeddedDocument.prototype.$__fullPath = function (path) {\n if (!this.$__.fullPath) {\n var parent = this;\n if (!parent.__parent) return path;\n\n var paths = [];\n while (parent.__parent) {\n paths.unshift(parent.__parentArray._path);\n parent = parent.__parent;\n }\n\n this.$__.fullPath = paths.join('.');\n\n if (!this.$__.ownerDocument) {\n // optimization\n this.$__.ownerDocument = parent;\n }\n }\n\n return path\n ? this.$__.fullPath + '.' + path\n : this.$__.fullPath;\n}" + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent document.

    ", + "summary": "

    Returns this sub-documents parent document.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parent = function () {\n return this.__parent;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parent", + "string": "EmbeddedDocument.prototype.parent()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Returns this sub-documents parent array.

    ", + "summary": "

    Returns this sub-documents parent array.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "EmbeddedDocument.prototype.parentArray = function () {\n return this.__parentArray;\n}", + "ctx": { + "type": "method", + "constructor": "EmbeddedDocument", + "name": "parentArray", + "string": "EmbeddedDocument.prototype.parentArray()" + } + }, + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = EmbeddedDocument;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "EmbeddedDocument", + "string": "module.exports" + } + } +] +### lib/types/index.js +[ + { + "tags": [], + "description": { + "full": "

    Module exports.

    ", + "summary": "

    Module exports.

    ", + "body": "" + }, + "ignore": true, + "code": "exports.Array = require('./array');\nexports.Buffer = require('./buffer');\n\nexports.Document = // @deprecate\nexports.Embedded = require('./embedded');\n\nexports.DocumentArray = require('./documentarray');\nexports.ObjectId = require('./objectid');", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "Array", + "value": "require('./array')", + "string": "exports.Array" + } + } +] +### lib/types/objectid.js +[ + { + "tags": [], + "description": { + "full": "

    Access driver.

    ", + "summary": "

    Access driver.

    ", + "body": "" + }, + "ignore": true, + "code": "var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';", + "ctx": { + "type": "declaration", + "name": "driver", + "value": "global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'", + "string": "driver" + } + }, + { + "tags": [ + { + "type": "constructor", + "string": "ObjectId" + } + ], + "description": { + "full": "

    ObjectId type constructor

    \n\n

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    ", + "summary": "

    ObjectId type constructor

    ", + "body": "

    Example

    \n\n
    var id = new mongoose.Types.ObjectId;\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "var ObjectId = require(driver + '/objectid');\nmodule.exports = ObjectId;", + "ctx": { + "type": "declaration", + "name": "ObjectId", + "value": "require(driver + '/objectid')", + "string": "ObjectId" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId", + "HexString" + ], + "name": "str", + "description": "" + }, + { + "type": "static", + "string": "fromString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "ObjectId" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Creates an ObjectId from str

    ", + "summary": "

    Creates an ObjectId from str

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.fromString;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "ObjectId" + ], + "name": "oid", + "description": "ObjectId instance" + }, + { + "type": "static", + "string": "toString" + }, + { + "type": "receiver", + "string": "ObjectId" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts oid to a string.

    ", + "summary": "

    Converts oid to a string.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": false, + "code": "ObjectId.toString;" + } +] +### lib/utils.js +[ + { + "tags": [], + "description": { + "full": "

    Module dependencies.

    ", + "summary": "

    Module dependencies.

    ", + "body": "" + }, + "ignore": true, + "code": "var ReadPref = require('mongodb').ReadPreference\n , ObjectId = require('./types/objectid')\n , ms = require('ms')\n , sliced = require('sliced')\n , mpath = require('mpath')\n , MongooseBuffer\n , MongooseArray\n , Document", + "ctx": { + "type": "declaration", + "name": "ReadPref", + "value": "require('mongodb').ReadPreference", + "string": "ReadPref" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "name", + "description": "a model name" + }, + { + "type": "return", + "types": [ + "String" + ], + "description": "a collection name" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Produces a collection name from model name.

    ", + "summary": "

    Produces a collection name from model name.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "exports.toCollectionName = function (name) {\n if ('system.profile' === name) return name;\n if ('system.indexes' === name) return name;\n return pluralize(name.toLowerCase());\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "toCollectionName", + "string": "exports.toCollectionName()" + } + }, + { + "tags": [ + { + "type": "deprecated", + "string": "remove in 4.x gh-1350" + } + ], + "description": { + "full": "

    Pluralization rules.

    \n\n

    These rules are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Pluralization rules.

    ", + "body": "

    These rules are applied while processing the argument to toCollectionName.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "exports.pluralization = [\n [/(m)an$/gi, '$1en'],\n [/(pe)rson$/gi, '$1ople'],\n [/(child)$/gi, '$1ren'],\n [/^(ox)$/gi, '$1en'],\n [/(ax|test)is$/gi, '$1es'],\n [/(octop|vir)us$/gi, '$1i'],\n [/(alias|status)$/gi, '$1es'],\n [/(bu)s$/gi, '$1ses'],\n [/(buffal|tomat|potat)o$/gi, '$1oes'],\n [/([ti])um$/gi, '$1a'],\n [/sis$/gi, 'ses'],\n [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],\n [/(hive)$/gi, '$1s'],\n [/([^aeiouy]|qu)y$/gi, '$1ies'],\n [/(x|ch|ss|sh)$/gi, '$1es'],\n [/(matr|vert|ind)ix|ex$/gi, '$1ices'],\n [/([m|l])ouse$/gi, '$1ice'],\n [/(quiz)$/gi, '$1zes'],\n [/s$/gi, 's'],\n [/$/gi, 's']\n];\nvar rules = exports.pluralization;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "pluralization", + "value": "[", + "string": "exports.pluralization" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Uncountable words.

    \n\n

    These words are applied while processing the argument to toCollectionName.

    ", + "summary": "

    Uncountable words.

    ", + "body": "

    These words are applied while processing the argument to toCollectionName.

    " + }, + "isPrivate": false, + "ignore": false, + "code": "exports.uncountables = [\n 'advice',\n 'energy',\n 'excretion',\n 'digestion',\n 'cooperation',\n 'health',\n 'justice',\n 'labour',\n 'machinery',\n 'equipment',\n 'information',\n 'pollution',\n 'sewage',\n 'paper',\n 'money',\n 'species',\n 'series',\n 'rain',\n 'rice',\n 'fish',\n 'sheep',\n 'moose',\n 'deer',\n 'news',\n 'expertise',\n 'status',\n 'media'\n];\nvar uncountables = exports.uncountables;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "uncountables", + "value": "[", + "string": "exports.uncountables" + } + }, + { + "tags": [ + { + "type": "author", + "string": "TJ Holowaychuk (extracted from _ext.js_)" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "string", + "description": "to pluralize" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Pluralize function.

    ", + "summary": "

    Pluralize function.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "function pluralize (str) {\n var rule, found;\n if (!~uncountables.indexOf(str.toLowerCase())){\n found = rules.filter(function(rule){\n return str.match(rule[0]);\n });\n if (found[0]) return str.replace(found[0][0], found[0][1]);\n }\n return str;\n};", + "ctx": { + "type": "function", + "name": "pluralize", + "string": "pluralize()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "a", + "description": "a value to compare to `b`" + }, + { + "type": "param", + "types": [ + "any" + ], + "name": "b", + "description": "a value to compare to `a`" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Determines if a and b are deep equal.

    \n\n

    Modified from node/lib/assert.js

    ", + "summary": "

    Determines if a and b are deep equal.

    ", + "body": "

    Modified from node/lib/assert.js

    " + }, + "isPrivate": true, + "ignore": true, + "code": "exports.deepEqual = function deepEqual (a, b) {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n\n if (a instanceof ObjectId && b instanceof ObjectId) {\n return a.toString() === b.toString();\n }\n\n if (a instanceof RegExp && b instanceof RegExp) {\n return a.source == b.source &&\n a.ignoreCase == b.ignoreCase &&\n a.multiline == b.multiline &&\n a.global == b.global;\n }\n\n if (typeof a !== 'object' && typeof b !== 'object')\n return a == b;\n\n if (a === null || b === null || a === undefined || b === undefined)\n return false\n\n if (a.prototype !== b.prototype) return false;\n\n // Handle MongooseNumbers\n if (a instanceof Number && b instanceof Number) {\n return a.valueOf() === b.valueOf();\n }\n\n if (Buffer.isBuffer(a)) {\n if (!Buffer.isBuffer(b)) return false;\n if (a.length !== b.length) return false;\n for (var i = 0, len = a.length; i < len; ++i) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (isMongooseObject(a)) a = a.toObject();\n if (isMongooseObject(b)) b = b.toObject();\n\n try {\n var ka = Object.keys(a),\n kb = Object.keys(b),\n key, i;\n } catch (e) {//happens when one is a string literal and the other isn't\n return false;\n }\n\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length != kb.length)\n return false;\n\n //the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n\n //~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] != kb[i])\n return false;\n }\n\n //equivalent values for every corresponding key, and\n //~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n if (!deepEqual(a[key], b[key])) return false;\n }\n\n return true;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "deepEqual", + "string": "exports.deepEqual()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "the object to clone" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the cloned object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Object clone with Mongoose natives support.

    \n\n

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    ", + "summary": "

    Object clone with Mongoose natives support.

    ", + "body": "

    If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.

    \n\n

    Functions are never cloned.

    " + }, + "isPrivate": true, + "ignore": true, + "code": "exports.clone = function clone (obj, options) {\n if (obj === undefined || obj === null)\n return obj;\n\n if (Array.isArray(obj))\n return cloneArray(obj, options);\n\n if (isMongooseObject(obj)) {\n if (options && options.json && 'function' === typeof obj.toJSON) {\n return obj.toJSON(options);\n } else {\n return obj.toObject(options);\n }\n }\n\n if ('Object' === obj.constructor.name)\n return cloneObject(obj, options);\n\n if ('Date' === obj.constructor.name)\n return new obj.constructor(+obj);\n\n if ('RegExp' === obj.constructor.name) {\n var flags = [];\n if (obj.global) flags.push('g');\n if (obj.multiline) flags.push('m');\n if (obj.ignoreCase) flags.push('i');\n return new RegExp(obj.source, flags.join(''));\n }\n\n if (obj instanceof ObjectId)\n return new ObjectId(obj.id);\n\n if (obj.valueOf)\n return obj.valueOf();\n};\nvar clone = exports.clone;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "clone", + "string": "exports.clone()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "function cloneObject (obj, options) {\n var retainKeyOrder = options && options.retainKeyOrder\n , minimize = options && options.minimize\n , ret = {}\n , hasKeys\n , keys\n , val\n , k\n , i\n\n if (retainKeyOrder) {\n for (k in obj) {\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n hasKeys || (hasKeys = true);\n ret[k] = val;\n }\n }\n } else {\n // faster\n\n keys = Object.keys(obj);\n i = keys.length;\n\n while (i--) {\n k = keys[i];\n val = clone(obj[k], options);\n\n if (!minimize || ('undefined' !== typeof val)) {\n if (!hasKeys) hasKeys = true;\n ret[k] = val;\n }\n }\n }\n\n return minimize\n ? hasKeys && ret\n : ret;\n};\n\nfunction cloneArray (arr, options) {\n var ret = [];\n for (var i = 0, l = arr.length; i < l; i++)\n ret.push(clone(arr[i], options));\n return ret;\n};", + "ctx": { + "type": "function", + "name": "cloneObject", + "string": "cloneObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "defaults", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "options", + "description": "" + }, + { + "type": "return", + "types": [ + "Object" + ], + "description": "the merged object" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Shallow copies defaults into options.

    ", + "summary": "

    Shallow copies defaults into options.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "exports.options = function (defaults, options) {\n var keys = Object.keys(defaults)\n , i = keys.length\n , k ;\n\n options = options || {};\n\n while (i--) {\n k = keys[i];\n if (!(k in options)) {\n options[k] = defaults[k];\n }\n }\n\n return options;\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "options", + "string": "exports.options()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Generates a random string

    ", + "summary": "

    Generates a random string

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "exports.random = function () {\n return Math.random().toString().substr(3);\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "random", + "string": "exports.random()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "to", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "from", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Merges from into to without overwriting existing properties.

    ", + "summary": "

    Merges from into to without overwriting existing properties.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "exports.merge = function merge (to, from) {\n var keys = Object.keys(from)\n , i = keys.length\n , key\n\n while (i--) {\n key = keys[i];\n if ('undefined' === typeof to[key]) {\n to[key] = from[key];\n } else {\n if (exports.isObject(from[key])) {\n merge(to[key], from[key]);\n } else {\n to[key] = from[key];\n }\n }\n }\n};", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "merge", + "string": "exports.merge()" + } + }, + { + "tags": [], + "description": { + "full": "

    toString helper

    ", + "summary": "

    toString helper

    ", + "body": "" + }, + "ignore": true, + "code": "var toString = Object.prototype.toString;", + "ctx": { + "type": "declaration", + "name": "toString", + "value": "Object.prototype.toString", + "string": "toString" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object", + "Array", + "String", + "Function", + "RegExp", + "any" + ], + "name": "arg", + "description": "" + }, + { + "type": "api", + "visibility": "private" + }, + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + } + ], + "description": { + "full": "

    Determines if arg is an object.

    ", + "summary": "

    Determines if arg is an object.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "exports.isObject = function (arg) {\n return '[object Object]' == toString.call(arg);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isObject", + "string": "exports.isObject()" + } + }, + { + "tags": [ + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "summary": "

    A faster Array.prototype.slice.call(arguments) alternative

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "exports.args = sliced;", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "args", + "value": "sliced", + "string": "exports.args" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "callback", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    process.nextTick helper.

    \n\n

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    ", + "summary": "

    process.nextTick helper.

    ", + "body": "

    Wraps callback in a try/catch + nextTick.

    \n\n

    node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

    " + }, + "isPrivate": true, + "ignore": true, + "code": "exports.tick = function tick (callback) {\n if ('function' !== typeof callback) return;\n return function () {\n try {\n callback.apply(this, arguments);\n } catch (err) {\n // only nextTick on err to get out of\n // the event loop and avoid state corruption.\n process.nextTick(function () {\n throw err;\n });\n }\n }\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "tick", + "string": "exports.tick()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "any" + ], + "name": "v", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    \n\n

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    ", + "summary": "

    Returns if v is a mongoose object that has a toObject() method we can use.

    ", + "body": "

    This is for compatibility with libs like Date.js which do foolish things to Natives.

    " + }, + "isPrivate": true, + "ignore": true, + "code": "exports.isMongooseObject = function (v) {\n Document || (Document = require('./document'));\n MongooseArray || (MongooseArray = require('./types').Array);\n MongooseBuffer || (MongooseBuffer = require('./types').Buffer);\n\n return v instanceof Document ||\n v instanceof MongooseArray ||\n v instanceof MongooseBuffer\n}\nvar isMongooseObject = exports.isMongooseObject;", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isMongooseObject", + "string": "exports.isMongooseObject()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "object", + "description": "" + }, + { + "type": "api", + "visibility": "private" + } + ], + "description": { + "full": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "summary": "

    Converts expires options of index objects to expiresAfterSeconds options for MongoDB.

    ", + "body": "" + }, + "isPrivate": true, + "ignore": true, + "code": "exports.expires = function expires (object) {\n if (!(object && 'Object' == object.constructor.name)) return;\n if (!('expires' in object)) return;\n\n var when;\n if ('string' != typeof object.expires) {\n when = object.expires;\n } else {\n when = Math.round(ms(object.expires) / 1000);\n }\n object.expireAfterSeconds = when;\n delete object.expires;\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "expires", + "string": "exports.expires()" + } + }, + { + "tags": [ + { + "type": "TODO", + "string": "move this into the driver layer" + }, + { + "type": "param", + "types": [ + "String", + "Array" + ], + "name": "pref", + "description": "" + }, + { + "type": "param", + "types": [ + "Array" + ], + "name": "[tags]", + "description": "" + } + ], + "description": { + "full": "

    Converts arguments to ReadPrefs the driver
    can understand.

    ", + "summary": "

    Converts arguments to ReadPrefs the driver
    can understand.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "exports.readPref = function readPref (pref, tags) {\n if (Array.isArray(pref)) {\n tags = pref[1];\n pref = pref[0];\n }\n\n switch (pref) {\n case 'p':\n pref = 'primary';\n break;\n case 'pp':\n pref = 'primaryPrefered';\n break;\n case 's':\n pref = 'secondary';\n break;\n case 'sp':\n pref = 'secondaryPrefered';\n break;\n case 'n':\n pref = 'nearest';\n break;\n }\n\n return new ReadPref(pref, tags);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "readPref", + "string": "exports.readPref()" + } + }, + { + "tags": [], + "description": { + "full": "

    Populate options constructor

    ", + "summary": "

    Populate options constructor

    ", + "body": "" + }, + "ignore": true, + "code": "function PopulateOptions (path, select, match, options, model) {\n this.path = path;\n this.match = match;\n this.select = select;\n this.options = options;\n this.model = model;\n this._docs = {};\n}\n\n// make it compatible with utils.clone\nPopulateOptions.prototype.constructor = Object;\n\n// expose\nexports.PopulateOptions = PopulateOptions;", + "ctx": { + "type": "function", + "name": "PopulateOptions", + "string": "PopulateOptions()" + } + }, + { + "tags": [], + "description": { + "full": "

    populate helper

    ", + "summary": "

    populate helper

    ", + "body": "" + }, + "ignore": true, + "code": "exports.populate = function populate (path, select, model, match, options) {\n // The order of select/conditions args is opposite Model.find but\n // necessary to keep backward compatibility (select could be\n // an array, string, or object literal).\n\n // might have passed an object specifying all arguments\n if (1 === arguments.length) {\n if (path instanceof PopulateOptions) {\n return [path];\n }\n\n if (Array.isArray(path)) {\n return path.map(function(o){\n return exports.populate(o)[0];\n });\n }\n\n if (exports.isObject(path)) {\n match = path.match;\n options = path.options;\n select = path.select;\n model = path.model;\n path = path.path;\n }\n } else if ('string' !== typeof model) {\n options = match;\n match = model;\n model = undefined;\n }\n\n if ('string' != typeof path) {\n throw new TypeError('utils.populate: invalid path. Expected string. Got typeof `' + typeof path + '`');\n }\n\n var ret = [];\n var paths = path.split(' ');\n for (var i = 0; i < paths.length; ++i) {\n ret.push(new PopulateOptions(paths[i], select, match, options, model));\n }\n\n return ret;\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "populate", + "string": "exports.populate()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + } + ], + "description": { + "full": "

    Return the value of obj at the given path.

    ", + "summary": "

    Return the value of obj at the given path.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "exports.getValue = function (path, obj, map) {\n return mpath.get(path, obj, '_doc', map);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "getValue", + "string": "exports.getValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "String" + ], + "name": "path", + "description": "" + }, + { + "type": "param", + "types": [ + "Anything" + ], + "name": "val", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + } + ], + "description": { + "full": "

    Sets the value of obj at the given path.

    ", + "summary": "

    Sets the value of obj at the given path.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "exports.setValue = function (path, val, obj, map) {\n mpath.set(path, val, obj, '_doc', map);\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "setValue", + "string": "exports.setValue()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "o", + "description": "" + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Returns an array of values from object o.

    ", + "summary": "

    Returns an array of values from object o.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "exports.object = {};\nexports.object.vals = function vals (o) {\n var keys = Object.keys(o)\n , i = keys.length\n , ret = [];\n\n while (i--) {\n ret.push(o[keys[i]]);\n }\n\n return ret;\n}", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "object", + "value": "{}", + "string": "exports.object" + } + }, + { + "tags": [], + "description": { + "full": "

    @see exports.options

    ", + "summary": "

    @see exports.options

    ", + "body": "" + }, + "ignore": true, + "code": "exports.object.shallowCopy = exports.options;" + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "obj", + "description": "" + }, + { + "type": "param", + "types": [ + "String" + ], + "name": "prop", + "description": "" + } + ], + "description": { + "full": "

    Safer helper for hasOwnProperty checks

    ", + "summary": "

    Safer helper for hasOwnProperty checks

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "exports.object.hasOwnProperty = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}" + }, + { + "tags": [ + { + "type": "return", + "types": [ + "Boolean" + ], + "description": "" + } + ], + "description": { + "full": "

    Determine if val is null or undefined

    ", + "summary": "

    Determine if val is null or undefined

    ", + "body": "" + }, + "isPrivate": false, + "ignore": true, + "code": "exports.isNullOrUndefined = function (val) {\n return null == val\n}", + "ctx": { + "type": "method", + "receiver": "exports", + "name": "isNullOrUndefined", + "string": "exports.isNullOrUndefined()" + } + }, + { + "tags": [], + "description": { + "full": "

    ignore

    ", + "summary": "

    ignore

    ", + "body": "" + }, + "ignore": true, + "code": "exports.array = {};", + "ctx": { + "type": "property", + "receiver": "exports", + "name": "array", + "value": "{}", + "string": "exports.array" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Array" + ], + "name": "arr", + "description": "" + }, + { + "type": "param", + "types": [ + "Function" + ], + "name": "[filter]", + "description": "If passed, will be invoked with each item in the array. If `filter` returns a falsey value, the item will not be included in the results." + }, + { + "type": "return", + "types": [ + "Array" + ], + "description": "" + }, + { + "type": "private", + "string": "" + } + ], + "description": { + "full": "

    Flattens an array.

    \n\n

    [ 1, [ 2, 3, [4] ]] -> [1,2,3,4]

    ", + "summary": "

    Flattens an array.

    ", + "body": "

    [ 1, [ 2, 3, [4] ]] -> [1,2,3,4]

    " + }, + "isPrivate": false, + "ignore": true, + "code": "exports.array.flatten = function flatten (arr, filter, ret) {\n ret || (ret = []);\n\n arr.forEach(function (item) {\n if (Array.isArray(item)) {\n flatten(item, filter, ret);\n } else {\n if (!filter || filter(item)) {\n ret.push(item);\n }\n }\n });\n\n return ret;\n}" + } +] +### lib/virtualtype.js +[ + { + "tags": [ + { + "type": "parma", + "string": "{Object} options" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    VirtualType constructor

    \n\n

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    ", + "summary": "

    VirtualType constructor

    ", + "body": "

    This is what mongoose uses to define virtual attributes via Schema.prototype.virtual.

    \n\n

    Example:

    \n\n
    var fullname = schema.virtual('fullname');\nfullname instanceof mongoose.VirtualType // true\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "function VirtualType (options, name) {\n this.path = name;\n this.getters = [];\n this.setters = [];\n this.options = options || {};\n}", + "ctx": { + "type": "function", + "name": "VirtualType", + "string": "VirtualType()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a getter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    ", + "summary": "

    Defines a getter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.get(function () {\n  return this.name.first + ' ' + this.name.last;\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.get = function (fn) {\n this.getters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "get", + "string": "VirtualType.prototype.get()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Function" + ], + "name": "fn", + "description": "" + }, + { + "type": "return", + "types": [ + "VirtualType" + ], + "description": "this" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Defines a setter.

    \n\n

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    ", + "summary": "

    Defines a setter.

    ", + "body": "

    Example:

    \n\n
    var virtual = schema.virtual('fullname');\nvirtual.set(function (v) {\n  var parts = v.split(' ');\n  this.name.first = parts[0];\n  this.name.last = parts[1];\n});\n
    " + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.set = function (fn) {\n this.setters.push(fn);\n return this;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "set", + "string": "VirtualType.prototype.set()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all getters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies getters to value using optional scope.

    ", + "summary": "

    Applies getters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applyGetters = function (value, scope) {\n var v = value;\n for (var l = this.getters.length - 1; l >= 0; l--) {\n v = this.getters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applyGetters", + "string": "VirtualType.prototype.applyGetters()" + } + }, + { + "tags": [ + { + "type": "param", + "types": [ + "Object" + ], + "name": "value", + "description": "" + }, + { + "type": "param", + "types": [ + "Object" + ], + "name": "scope", + "description": "" + }, + { + "type": "return", + "types": [ + "any" + ], + "description": "the value after applying all setters" + }, + { + "type": "api", + "visibility": "public" + } + ], + "description": { + "full": "

    Applies setters to value using optional scope.

    ", + "summary": "

    Applies setters to value using optional scope.

    ", + "body": "" + }, + "isPrivate": false, + "ignore": false, + "code": "VirtualType.prototype.applySetters = function (value, scope) {\n var v = value;\n for (var l = this.setters.length - 1; l >= 0; l--) {\n v = this.setters[l].call(scope, v, this);\n }\n return v;\n};", + "ctx": { + "type": "method", + "constructor": "VirtualType", + "name": "applySetters", + "string": "VirtualType.prototype.applySetters()" + } + }, + { + "tags": [], + "description": { + "full": "

    exports

    ", + "summary": "

    exports

    ", + "body": "" + }, + "ignore": true, + "code": "module.exports = VirtualType;", + "ctx": { + "type": "property", + "receiver": "module", + "name": "exports", + "value": "VirtualType", + "string": "module.exports" + } + } +] diff --git a/docs/3.5.x/docs/source/api.js b/docs/3.5.x/docs/source/api.js new file mode 100644 index 00000000000..2acf17aeeb5 --- /dev/null +++ b/docs/3.5.x/docs/source/api.js @@ -0,0 +1,223 @@ +/*! + * Module dependencies + */ + +var fs = require('fs'); +var link = require('../helpers/linktype'); +var hl = require('highlight.js') +var md = require('markdown') + +module.exports = { + docs: [] + , github: 'https://github.com/LearnBoost/mongoose/blob/' + , title: 'API docs' +} + +var out = module.exports.docs; + +var docs = fs.readFileSync(__dirname + '/_docs', 'utf8'); +parse(docs); +order(out); + +function parse (docs) { + docs.split(/^### /gm).forEach(function (chunk) { + if (!(chunk = chunk.trim())) return; + + chunk = chunk.split(/^([^\n]+)\n/); + + var fulltitle = chunk[1]; + + if (!fulltitle || !(fulltitle = fulltitle.trim())) + throw new Error('missing title'); + + var title = fulltitle.replace(/^lib\//, ''); + var json = JSON.parse(chunk[2]); + + var props = []; + var methods = []; + var statics = []; + var constructor = null; + + json.forEach(function (comment) { + if (comment.description) + highlight(comment.description); + + var prop = false; + comment.params = []; + comment.see = []; + + var i = comment.tags.length; + while (i--) { + var tag = comment.tags[i]; + switch (tag.type) { + case 'property': + prop = true; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + props.unshift(comment); + break; + case 'method': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'method'; + comment.code = ''; + break; + case 'memberOf': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.constructor = tag.parent; + break; + case 'static': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name = tag.string; + comment.ctx.type = 'static'; + break; + case 'receiver': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.receiver = tag.string; + break; + case 'constructor': + prop = false; + comment.ctx || (comment.ctx = {}); + comment.ctx.name || (comment.ctx.name = tag.string); + comment.ctx.type = 'function'; + comment.code = ''; + break; + case 'inherits': + if (/http/.test(tag.string)) { + var result = tag.string.split(' '); + var href = result.pop(); + var title = result.join(' '); + comment.inherits = '' + title + ''; + } else { + comment.inherits = link(tag.string); + } + comment.tags.splice(i, 1); + break; + case 'param': + comment.params.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'return': + comment.return = tag; + comment.tags.splice(i, 1); + break; + case 'see': + if (tag.local) { + var parts = tag.local.split(' '); + if (1 === parts.length) { + tag.url = link.type(parts[0]); + tag.title = parts[0]; + } else { + tag.url = parts.pop(); + tag.title = parts.join(' '); + } + } + comment.see.unshift(tag); + comment.tags.splice(i, 1); + break; + case 'event': + var str = tag.string.replace(/\\n/g, '\n'); + tag.string = md.parse(str).replace(/\n/g, '\\n').replace(/'/g, '''); + comment.events || (comment.events = []); + comment.events.unshift(tag); + comment.tags.splice(i, 1); + } + } + + if (!prop) { + methods.push(comment); + } + }); + + methods = methods.filter(ignored); + props = props.filter(ignored); + + function ignored (method) { + if (method.ignore) return false; + return true; + } + + if (0 === methods.length + props.length) return; + + // add constructor to properties too + methods.some(function (method) { + if (method.ctx && 'method' == method.ctx.type && method.ctx.hasOwnProperty('constructor')) { + props.forEach(function (prop) { + prop.ctx.constructor = method.ctx.constructor; + }); + return true; + } + return false; + }); + + var len = methods.length; + while (len--) { + method = methods[len]; + if (method.ctx && method.ctx.receiver) { + var stat = methods.splice(len, 1)[0]; + statics.unshift(stat); + } + } + + out.push({ + title: title + , fulltitle: fulltitle + , cleantitle: title.replace(/[\.\/#]/g, '-') + , methods: methods + , props: props + , statics: statics + , hasPublic: hasPublic(methods, props, statics) + }); + }); +} + +function hasPublic () { + for (var i = 0; i < arguments.length; ++i) { + var arr = arguments[i]; + for (var j = 0; j < arr.length; ++j) { + var item = arr[j]; + if (!item.ignore && !item.isPrivate) return true; + } + } + return false; +} + +// add "class='language'" to our
     elements
    +function highlight (o) {
    +  o.full = fix(o.full);
    +  o.summary = fix(o.summary);
    +  o.body = fix(o.body);
    +}
    +
    +function fix (str) {
    +  return str.replace(/(
    )([^<]+)(<\/code)/gm, function (_, $1, $2, $3) {
    +
    +    // parse out the ```language
    +    var code = /^(?:`{3}([^\n]+)\n)?([\s\S]*)/gm.exec($2);
    +
    +    if ('js' == code[1] || !code[1]) {
    +      code[1] = 'javascript';
    +    }
    +
    +    return $1
    +          + hl.highlight(code[1], code[2]).value.trim()
    +          + $3;
    +  });
    +}
    +
    +function order (docs) {
    +  // want index first
    +  for (var i = 0; i < docs.length; ++i) {
    +    if ('index.js' == docs[i].title) {
    +      docs.unshift(docs.splice(i, 1)[0]);
    +    } else if ('collection.js' == docs[i].title) {
    +      docs.push(docs.splice(i, 1)[0]);
    +    }
    +  }
    +}
    diff --git a/docs/3.5.x/docs/source/home.js b/docs/3.5.x/docs/source/home.js
    new file mode 100644
    index 00000000000..e349d8ddcad
    --- /dev/null
    +++ b/docs/3.5.x/docs/source/home.js
    @@ -0,0 +1,7 @@
    +
    +var package = require('./../../package.json')
    +
    +module.exports = {
    +    package: package
    +  , title: 'ODM'
    +}
    diff --git a/docs/3.5.x/docs/source/index.js b/docs/3.5.x/docs/source/index.js
    new file mode 100644
    index 00000000000..18b3eeb5718
    --- /dev/null
    +++ b/docs/3.5.x/docs/source/index.js
    @@ -0,0 +1,20 @@
    +
    +exports['index.jade'] = require('./home')
    +exports['docs/api.jade'] = require('./api')
    +exports['docs/index.jade'] = { title: 'Getting Started' }
    +exports['docs/production.jade'] = require('./production')
    +exports['docs/prior.jade'] = require('./prior')
    +exports['docs/guide.jade'] = { guide: true, schema: true, title: 'Schemas' }
    +exports['docs/schematypes.jade'] = { guide: true, schema: true, title: 'SchemaTypes' }
    +exports['docs/middleware.jade'] = { guide: true, title: 'Middleware' }
    +exports['docs/plugins.jade'] = { guide: true, title: 'Plugins' }
    +exports['docs/subdocs.jade'] = { guide: true, docs: true, title: 'SubDocuments' }
    +exports['docs/documents.jade'] = { guide: true, docs: true, title: 'Documents' }
    +exports['docs/models.jade'] = { guide: true, title: 'Models' }
    +exports['docs/queries.jade'] = { guide: true, title: 'Queries' }
    +exports['docs/populate.jade'] = { guide: true, title: 'Query Population' }
    +exports['docs/validation.jade'] = { guide: true, title: 'Validation' }
    +exports['docs/migration.jade'] = { guide: true, title: 'Migration Guide' }
    +exports['docs/contributing.jade'] = { guide: true, title: 'Contributing' }
    +exports['docs/connections.jade'] = { guide: true, title: 'Connecting to MongoDB' }
    +exports['docs/faq.jade'] = { guide: true, title: 'FAQ' }
    diff --git a/docs/3.5.x/docs/source/prior.js b/docs/3.5.x/docs/source/prior.js
    new file mode 100644
    index 00000000000..350ec4994bd
    --- /dev/null
    +++ b/docs/3.5.x/docs/source/prior.js
    @@ -0,0 +1,13 @@
    +var fs = require('fs')
    +var releases = fs.readFileSync(__dirname + '/../releases', 'utf8');
    +releases = releases.split('\n').filter(Boolean);
    +
    +module.exports = exports = {
    +    title: ''
    +  , releases: releases.map(function (version) {
    +      return {
    +          url: '/docs/' + version + '/'
    +        , version: version
    +      }
    +    })
    +}
    diff --git a/docs/3.5.x/docs/source/production.js b/docs/3.5.x/docs/source/production.js
    new file mode 100644
    index 00000000000..9fdbcfffbc7
    --- /dev/null
    +++ b/docs/3.5.x/docs/source/production.js
    @@ -0,0 +1,17 @@
    +
    +var fs = require('fs')
    +var images = fs.readFileSync(__dirname + '/../images/apps/urls', 'utf-8').split('\n');
    +
    +var imgs = [];
    +
    +images.forEach(function (line) {
    +  line = line.trim();
    +  if (!line) return;
    +  line = line.split('|');
    +  imgs.push({ url: line[0], title: line[1], desc: line[2], src: line[1].toLowerCase().replace(/\s/g,'') });
    +});
    +
    +module.exports = {
    +    images: imgs
    +  , title: 'Production'
    +}
    diff --git a/docs/3.5.x/docs/subdocs.html b/docs/3.5.x/docs/subdocs.html
    new file mode 100644
    index 00000000000..424477f06c4
    --- /dev/null
    +++ b/docs/3.5.x/docs/subdocs.html
    @@ -0,0 +1,49 @@
    +Mongoose SubDocuments v3.5.9Fork me on GitHub

    Sub Docs

    Sub-documents are docs with schemas of their own which are elements of a parents document array:

    var childSchema = new Schema({ name: 'string' });
    +
    +var parentSchema = new Schema({
    +  children: [childSchema]
    +})
    +

    Sub-documents enjoy all the same features as normal documents. The only difference is that they are not saved individually, they are saved whenever their top-level parent document is saved.

    var Parent = mongoose.model('Parent', parentSchema);
    +var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    +parent.children[0].name = 'Matthew';
    +parent.save(callback);
    +

    If an error occurs in a sub-documents' middleware, it is bubbled up to the save() callback of the parent, so error handling is a snap!

    childSchema.pre('save', function (next) {
    +  if ('invalid' == this.name) return next(new Error('#sadpanda'));
    +  next();
    +});
    +
    +var parent = new Parent({ children: [{ name: 'invalid' }] });
    +parent.save(function (err) {
    +  console.log(err.message) // #sadpanda
    +})
    +

    Finding a sub-document

    Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

    var doc = parent.children.id(id);
    +

    Adding sub-docs

    MongooseArray methods such as push, unshift, addToSet, and others cast arguments to their proper types transparently:

    var Parent = mongoose.model('Parent');
    +var parent = new Parent;
    +
    +// create a comment
    +post.children.push({ name: 'Liesl' });
    +var doc = post.children[0];
    +console.log(doc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    +doc.isNew; // true
    +
    +post.save(function (err) {
    +  if (err) return handleError(err)
    +  console.log('Success!');
    +});

    Sub-docs may also be created without adding them to the array by using the create method of MongooseArrays.

    var newdoc = post.children.create({ name: 'Aaron' });
    +

    Removing docs

    Each sub-document has it's own remove method.

    var doc = parent.children.id(id).remove();
    +parent.save(function (err) {
    +  if (err) return handleError(err);
    +  console.log('the sub-doc was removed')
    +});
    +

    Alternate declaration syntax

    New in v3 If you don't need access to the sub-document schema instance, you may also declare sub-docs by simply passing an object literal:

    var parentSchema = new Schema({
    +  children: [{ name: 'string' }]
    +})
    +

    Next Up

    Now that we've covered Sub-documents, let's take a look at querying.

    \ No newline at end of file diff --git a/docs/3.5.x/docs/validation.html b/docs/3.5.x/docs/validation.html new file mode 100644 index 00000000000..adf73caa2df --- /dev/null +++ b/docs/3.5.x/docs/validation.html @@ -0,0 +1,37 @@ +Mongoose Validation v3.5.9Fork me on GitHub

    Validation

    Before we get into the specifics of validation syntax, please keep the following rules in mind:

    + +
    • Validation is defined in the SchemaType
    • Validation is an internal piece of middleware
    • Validation occurs when a document attempts to be saved, after defaults have been applied
    • Validation is asynchronously recursive: when you call Model#save, sub-document validation is executed. If an error happens, your Model#save callback receives it
    • Mongoose doesn't care about complex error message construction. Errors have type identifiers. For example, "min" is the identifier for the error triggered when a number doesn't meet the minimum value. The path and value that triggered the error can be accessed in the ValidationError object

    Built in validators

    Mongoose has several built in validators.

    + +

    Custom validators

    Custom validation is declared by passing a validation function and an error type to your SchemaTypes validate method. Read the API docs for details on custom validators, async validators, and more.

    Validation errors

    Errors returned after failed validation contain an errors object holding the actual ValidatorErrors. Each ValidatorError has a type and path property providing us with a little more error handling flexibility.

    var toySchema = new Schema({
    +  color: String,
    +  name: String
    +});
    +
    +var Toy = mongoose.model('Toy', toySchema);
    +
    +Toy.schema.path('color').validate(function (value) {
    +  return /blue|green|white|red|orange|periwinkel/i.test(value);
    +}, 'Invalid color');
    +
    +var toy = new Toy({ color: 'grease'});
    +
    +toy.save(function (err) {
    +  // err.errors.color is a ValidatorError object
    +  
    +  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color'
    +  console.log(err.errors.color.type) // prints "Invalid color"
    +  console.log(err.errors.color.path) // prints "color"
    +  console.log(err.name) // prints "ValidationError"
    +  console.log(err.message) // prints "Validation failed"
    +});
    +

    After a validation error, the document will also have the same errors property available:

    toy.errors.color.message === err.errors.color.message
    +

    Next Up

    Now that we've covered validation, let's take a look at how you might handle advanced validation with Mongooses middleware.

    \ No newline at end of file diff --git a/docs/3.5.x/index.html b/docs/3.5.x/index.html new file mode 100644 index 00000000000..68d28f54ca5 --- /dev/null +++ b/docs/3.5.x/index.html @@ -0,0 +1,20 @@ +Mongoose ODM v3.5.9Fork me on GitHub

    Elegant MongoDB object modeling for Node.js

    • Version 3.5.9
    var mongoose = require('mongoose');
    +mongoose.connect('localhost', 'test');
    +
    +var schema = mongoose.Schema({ name: 'string' });
    +var Cat = mongoose.model('Cat', schema);
    +
    +var kitty = new Cat({ name: 'Zildjian' });
    +kitty.save(function (err) {
    +  if (err) // ...
    +  console.log('meow');
    +});

    Installation

    $ npm install mongoose

    Getting Started

    Support

    Changelog

    Production + View More

    • Storify
    • LearnBoost
    • GeekList
    • McDonalds
    • ShoeJitsu
    • Bozuko
    \ No newline at end of file diff --git a/docs/3.5.x/static.js b/docs/3.5.x/static.js new file mode 100644 index 00000000000..fc0e722dd4e --- /dev/null +++ b/docs/3.5.x/static.js @@ -0,0 +1,17 @@ + +var static = require('node-static'); +var server = new static.Server('.', { cache: 0 }); + +require('http').createServer(function (req, res) { + req.on('end', function () { + server.serve(req, res, function (err) { + if (err) { + console.error(err, req.url); + res.writeHead(err.status, err.headers); + res.end(); + } + }); + }); +}).listen(8088); + +console.error('now listening on localhost:8088'); diff --git a/docs/api.html b/docs/api.html index 20f56480b6f..49cdbfb2aa8 100644 --- a/docs/api.html +++ b/docs/api.html @@ -10982,4 +10982,4 @@

    Note:

    _gaq.push(['_trackEvent', 'anchor', 'click', this.hash]) } }) -})() +})() \ No newline at end of file From 8f2f5b67bae272b1ba6c3eb0ece15378a515dd1f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Sep 2017 20:10:28 -0700 Subject: [PATCH 1843/2240] test: make connection tests more robust --- test/connection.test.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/connection.test.js b/test/connection.test.js index 32c02cb193d..654bb009ced 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -94,7 +94,7 @@ describe('connections:', function() { var numConnected = 0; var numDisconnected = 0; var numReconnected = 0; - conn = mongoose.connect('mongodb://localhost:27000/mongoosetest', { + conn = mongoose.createConnection('mongodb://localhost:27000/mongoosetest', { useMongoClient: true }); @@ -133,6 +133,8 @@ describe('connections:', function() { then(function() { assert.equal(numDisconnected, 1); assert.equal(numReconnected, 1); + + conn.close(); done(); }). catch(done); @@ -144,7 +146,7 @@ describe('connections:', function() { var conn; var numTimeout = 0; var numDisconnected = 0; - conn = mongoose.connect('mongodb://localhost:27000/mongoosetest', { + conn = mongoose.createConnection('mongodb://localhost:27000/mongoosetest', { useMongoClient: true, socketTimeoutMS: 100, poolSize: 1 @@ -175,6 +177,8 @@ describe('connections:', function() { assert.ok(error.message.indexOf('timed out'), error.message); assert.equal(numTimeout, 1); assert.equal(numDisconnected, 0); + + conn.close(); done(); }); }); From de065e7870d18f172242d040b9e1096086a23fdf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Sep 2017 20:19:13 -0700 Subject: [PATCH 1844/2240] chore: pass all options to populated() re: #5564 --- lib/model.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index b7fce587ab8..04622b9ecce 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3214,7 +3214,8 @@ function populate(model, docs, options, callback) { path: options.path, options: assignmentOpts, justOne: mod.justOne, - isVirtual: mod.isVirtual + isVirtual: mod.isVirtual, + allOptions: mod }); } } @@ -3269,7 +3270,7 @@ function assignVals(o) { cur = cur[parts[j]]; } if (docs[i].$__) { - docs[i].populated(o.path, o.allIds[i]); + docs[i].populated(o.path, o.allIds[i], o.allOptions); } utils.setValue(o.path, rawIds[i], docs[i], setValue); } From 00d10d77450d91cb70c591db378723af3cf64f0a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Sep 2017 20:32:22 -0700 Subject: [PATCH 1845/2240] chore: release 4.11.10 --- History.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 6ac66f4a9c3..60854eee74d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,17 @@ +4.11.10 / 2017-09-03 +==================== + * docs: add KeenIO tracking #5612 + * fix(schema): ensure validators declared with `.validate()` get copied with clone() #5607 + * fix: remove unnecessary jest warning #5480 + * fix(discriminator): prevent implicit discriminator schema id from clobbering base schema custom id #5591 + * fix(schema): hide schema objectid warning for non-hex strings of length 24 #5587 + * docs(populate): use story schema defined key author instead of creator #5578 [dmric](https://github.com/dmric) + * docs(document): describe usage of `.set()` #5576 + * fix(document): ensure correct scope in single nested validators #5569 + * fix(populate): don't mark path as populated until populate() is done #5564 + * fix(document): make push()-ing a doc onto an empty array act as manual population #5504 + * fix(connection): emit timeout event on socket timeout #4513 + 4.11.9 / 2017-08-27 =================== * fix(error): avoid using arguments.callee because that breaks strict mode #5572 diff --git a/package.json b/package.json index 8ea1e157f1c..f2859264a76 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.10-pre", + "version": "4.11.10", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 8d677f7a035ccf7a9ed60b67801de3ee0751a7f7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 3 Sep 2017 20:35:03 -0700 Subject: [PATCH 1846/2240] chore: now working on 4.11.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f2859264a76..8d707fbbf45 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.10", + "version": "4.11.11-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a227d6f70d66fc2003461a857bb2cc16caa809b4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 4 Sep 2017 11:56:38 -0700 Subject: [PATCH 1847/2240] fix(populate): fix intermittent test failure Re: #5595 --- lib/types/array.js | 2 +- test/document.populate.test.js | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/types/array.js b/lib/types/array.js index b6efac4f77a..bc0c384ffc6 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -103,7 +103,7 @@ MongooseArray.mixin = { if (populated && value !== null && value !== undefined) { // cast to the populated Models schema - Model = populated.options.model; + Model = populated.options.model || populated.options.Model; // only objects are permitted so we can safely assume that // non-objects are to be interpreted as _id diff --git a/test/document.populate.test.js b/test/document.populate.test.js index 1035fd83974..ab7601bb878 100644 --- a/test/document.populate.test.js +++ b/test/document.populate.test.js @@ -526,7 +526,7 @@ describe('document.populate', function() { }); describe('gh-2214', function() { - it('should return a real document array when populating', function() { + it('should return a real document array when populating', function(done) { var db = start(); var Car = db.model('gh-2214-1', { @@ -554,16 +554,21 @@ describe('document.populate', function() { }); joe.cars.push(car); - return joe.save(function() { - return car.save(function() { - return Person.findById(joe.id, function(err, joe) { - return joe.populate('cars', function() { + joe.save(function(error) { + assert.ifError(error); + car.save(function(error) { + assert.ifError(error); + Person.findById(joe.id, function(error, joe) { + assert.ifError(error); + joe.populate('cars', function(error) { + assert.ifError(error); car = new Car({ model: 'BMW', color: 'black' }); joe.cars.push(car); assert.ok(joe.isModified('cars')); + done(); db.close(); }); }); From 908a5dc3443b0f6870ecd8e4c64290b52045f64e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 4 Sep 2017 21:54:53 -0700 Subject: [PATCH 1848/2240] style: use multiple var declarations --- test/document.populate.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/document.populate.test.js b/test/document.populate.test.js index ab7601bb878..9833e5115eb 100644 --- a/test/document.populate.test.js +++ b/test/document.populate.test.js @@ -544,7 +544,8 @@ describe('document.populate', function() { ] }); - var car, joe; + var car; + var joe; joe = new Person({ name: 'Joe' }); From a55c991fb6784f439b6d77f60c4c73299a494371 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 4 Sep 2017 22:09:14 -0700 Subject: [PATCH 1849/2240] feat(connection): bubble up reconnectFailed event when driver gives up reconnecting Fix #4027 --- lib/connection.js | 3 ++ test/connection.test.js | 76 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index ea1d74b5bb2..9e5543bab41 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -766,6 +766,9 @@ Connection.prototype.openUri = function(uri, options, callback) { db.on('reconnect', function() { _this.emit('reconnected'); }); + db.s.topology.on('reconnectFailed', function() { + _this.emit('reconnectFailed'); + }); db.s.topology.on('close', function() { _this.emit('disconnected'); }); diff --git a/test/connection.test.js b/test/connection.test.js index 654bb009ced..7834ddad332 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -94,6 +94,7 @@ describe('connections:', function() { var numConnected = 0; var numDisconnected = 0; var numReconnected = 0; + var numClose = 0; conn = mongoose.createConnection('mongodb://localhost:27000/mongoosetest', { useMongoClient: true }); @@ -107,6 +108,9 @@ describe('connections:', function() { conn.on('reconnected', function() { ++numReconnected; }); + conn.on('close', function() { + ++numClose; + }); conn. then(function() { @@ -133,6 +137,78 @@ describe('connections:', function() { then(function() { assert.equal(numDisconnected, 1); assert.equal(numReconnected, 1); + assert.equal(numClose, 0); + + conn.close(); + done(); + }). + catch(done); + }); + + it('reconnectFailed (gh-4027)', function(done) { + this.timeout(25000); + + var conn; + var numReconnectFailed = 0; + var numConnected = 0; + var numDisconnected = 0; + var numReconnected = 0; + conn = mongoose.createConnection('mongodb://localhost:27000/mongoosetest', { + useMongoClient: true, + reconnectTries: 3, + reconnectInterval: 100 + }); + + conn.on('connected', function() { + ++numConnected; + }); + conn.on('disconnected', function() { + ++numDisconnected; + }); + conn.on('reconnected', function() { + ++numReconnected; + }); + conn.on('reconnectFailed', function() { + ++numReconnectFailed; + }); + + conn. + then(function() { + assert.equal(numConnected, 1); + return server.stop(); + }). + then(function() { + return new Promise(function(resolve) { + setTimeout(function() { resolve(); }, 100); + }); + }). + then(function() { + assert.equal(numDisconnected, 1); + assert.equal(numReconnected, 0); + assert.equal(numReconnectFailed, 0); + }). + then(function() { + return new Promise(function(resolve) { + setTimeout(function() { resolve(); }, 400); + }); + }). + then(function() { + assert.equal(numDisconnected, 1); + assert.equal(numReconnected, 0); + assert.equal(numReconnectFailed, 1); + }). + then(function() { + return server.start(); + }). + then(function() { + return new Promise(function(resolve) { + setTimeout(function() { resolve(); }, 2000); + }); + }). + then(function() { + assert.equal(numDisconnected, 1); + assert.equal(numReconnected, 0); + assert.equal(numReconnectFailed, 1); conn.close(); done(); From 10194bdd2d27d42cd14dc1dcdc163374efc033f7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 5 Sep 2017 21:25:22 -0700 Subject: [PATCH 1850/2240] test(timestamps): repro #5598 --- test/timestamps.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/timestamps.test.js b/test/timestamps.test.js index 84347e5733c..0b2a0911f9f 100644 --- a/test/timestamps.test.js +++ b/test/timestamps.test.js @@ -43,6 +43,25 @@ describe('timestamps', function() { }); }); + it('updatedAt without createdAt (gh-5598)', function(done) { + var startTime = Date.now(); + var schema = new mongoose.Schema({ + name: String + }, { timestamps: { createdAt: null, updatedAt: true } }); + var M = db.model('gh4868', schema); + + M.create({ name: 'Test' }, function(error) { + assert.ifError(error); + M.findOne({}, function(error, doc) { + assert.ifError(error); + assert.ok(!doc.createdAt); + assert.ok(doc.updatedAt); + assert.ok(doc.updatedAt.valueOf() >= startTime); + done(); + }); + }); + }); + it('nested paths (gh-4503)', function(done) { var startTime = Date.now(); var schema = new mongoose.Schema({ From 84d19034f53c213ff38693d331ff19f7d0ad51e7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 5 Sep 2017 21:44:52 -0700 Subject: [PATCH 1851/2240] fix(timestamps): allow enabling updatedAt without createdAt Fix #5598 --- lib/schema.js | 139 +++++++++++++++++++++++++++------------- test/timestamps.test.js | 24 ++++++- 2 files changed, 118 insertions(+), 45 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 27a138028f6..0d993e4a1f3 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -779,28 +779,35 @@ Schema.prototype.hasMixedParent = function(path) { */ Schema.prototype.setupTimestamp = function(timestamps) { if (timestamps) { - var createdAt = timestamps.createdAt || 'createdAt'; - var updatedAt = timestamps.updatedAt || 'updatedAt'; + var createdAt = handleTimestampOption(timestamps, 'createdAt'); + var updatedAt = handleTimestampOption(timestamps, 'updatedAt'); var schemaAdditions = {}; - var parts = createdAt.split('.'); + var parts; var i; - var cur = schemaAdditions; - if (this.pathType(createdAt) === 'adhocOrUndefined') { - for (i = 0; i < parts.length; ++i) { - cur[parts[i]] = (i < parts.length - 1 ? - cur[parts[i]] || {} : - Date); + var cur; + + if (createdAt != null) { + cur = schemaAdditions; + parts = createdAt.split('.'); + if (this.pathType(createdAt) === 'adhocOrUndefined') { + for (i = 0; i < parts.length; ++i) { + cur[parts[i]] = (i < parts.length - 1 ? + cur[parts[i]] || {} : + Date); + } } } - parts = updatedAt.split('.'); - cur = schemaAdditions; - if (this.pathType(createdAt) === 'adhocOrUndefined') { - for (i = 0; i < parts.length; ++i) { - cur[parts[i]] = (i < parts.length - 1 ? - cur[parts[i]] || {} : - Date); + if (updatedAt != null) { + parts = updatedAt.split('.'); + cur = schemaAdditions; + if (this.pathType(createdAt) === 'adhocOrUndefined') { + for (i = 0; i < parts.length; ++i) { + cur[parts[i]] = (i < parts.length - 1 ? + cur[parts[i]] || {} : + Date); + } } } @@ -810,12 +817,20 @@ Schema.prototype.setupTimestamp = function(timestamps) { var defaultTimestamp = new Date(); var auto_id = this._id && this._id.auto; - if (!this.get(createdAt) && this.isSelected(createdAt)) { + if (createdAt != null && !this.get(createdAt) && this.isSelected(createdAt)) { this.set(createdAt, auto_id ? this._id.getTimestamp() : defaultTimestamp); } - if (this.isNew || this.isModified()) { - this.set(updatedAt, this.isNew ? this.get(createdAt) : defaultTimestamp); + if (updatedAt != null && (this.isNew || this.isModified())) { + var ts = defaultTimestamp; + if (this.isNew) { + if (createdAt != null) { + ts = this.get(createdAt); + } else if (auto_id) { + ts = this._id.getTimestamp(); + } + } + this.set(updatedAt, ts); } next(); @@ -831,10 +846,10 @@ Schema.prototype.setupTimestamp = function(timestamps) { updates.$set = {}; _updates = updates.$set; } - if (!currentUpdate[updatedAt]) { + if (updatedAt != null && !currentUpdate[updatedAt]) { _updates[updatedAt] = now; } - if (!currentUpdate[createdAt]) { + if (createdAt != null && !currentUpdate[createdAt]) { _updates[createdAt] = now; } return updates; @@ -842,19 +857,22 @@ Schema.prototype.setupTimestamp = function(timestamps) { updates = { $set: {} }; currentUpdate = currentUpdate || {}; - if (!currentUpdate.$currentDate || !currentUpdate.$currentDate[updatedAt]) { + if (updatedAt != null && + (!currentUpdate.$currentDate || !currentUpdate.$currentDate[updatedAt])) { updates.$set[updatedAt] = now; } - if (currentUpdate[createdAt]) { - delete currentUpdate[createdAt]; - } - if (currentUpdate.$set && currentUpdate.$set[createdAt]) { - delete currentUpdate.$set[createdAt]; - } + if (createdAt != null) { + if (currentUpdate[createdAt]) { + delete currentUpdate[createdAt]; + } + if (currentUpdate.$set && currentUpdate.$set[createdAt]) { + delete currentUpdate.$set[createdAt]; + } - updates.$setOnInsert = {}; - updates.$setOnInsert[createdAt] = now; + updates.$setOnInsert = {}; + updates.$setOnInsert[createdAt] = now; + } return updates; }; @@ -889,6 +907,23 @@ Schema.prototype.setupTimestamp = function(timestamps) { } }; +/*! + * ignore + */ + +function handleTimestampOption(arg, prop) { + if (typeof arg === 'boolean') { + return prop; + } + if (typeof arg[prop] === 'boolean') { + return arg[prop] ? prop : null; + } + if (!(prop in arg)) { + return prop; + } + return arg[prop]; +} + /*! * ignore */ @@ -916,16 +951,24 @@ function applyTimestampsToChildren(query) { $path.$isMongooseDocumentArray && $path.schema.options.timestamps) { timestamps = $path.schema.options.timestamps; - createdAt = timestamps.createdAt || 'createdAt'; - updatedAt = timestamps.updatedAt || 'updatedAt'; + createdAt = handleTimestampOption(timestamps, 'createdAt'); + updatedAt = handleTimestampOption(timestamps, 'updatedAt'); if (update.$push[key].$each) { update.$push[key].$each.forEach(function(subdoc) { - subdoc[updatedAt] = now; - subdoc[createdAt] = now; + if (updatedAt != null) { + subdoc[updatedAt] = now; + } + if (createdAt != null) { + subdoc[createdAt] = now; + } }); } else { - update.$push[key][updatedAt] = now; - update.$push[key][createdAt] = now; + if (updatedAt != null) { + update.$push[key][updatedAt] = now; + } + if (createdAt != null) { + update.$push[key][createdAt] = now; + } } } } @@ -940,20 +983,28 @@ function applyTimestampsToChildren(query) { len = update.$set[key].length; timestamps = schema.path(key).schema.options.timestamps; if (timestamps) { - createdAt = timestamps.createdAt || 'createdAt'; - updatedAt = timestamps.updatedAt || 'updatedAt'; + createdAt = handleTimestampOption(timestamps, 'createdAt'); + updatedAt = handleTimestampOption(timestamps, 'updatedAt'); for (var i = 0; i < len; ++i) { - update.$set[key][i][updatedAt] = now; - update.$set[key][i][createdAt] = now; + if (updatedAt != null) { + update.$set[key][i][updatedAt] = now; + } + if (createdAt != null) { + update.$set[key][i][createdAt] = now; + } } } } else if (update.$set[key] && path.$isSingleNested) { timestamps = schema.path(key).schema.options.timestamps; if (timestamps) { - createdAt = timestamps.createdAt || 'createdAt'; - updatedAt = timestamps.updatedAt || 'updatedAt'; - update.$set[key][updatedAt] = now; - update.$set[key][createdAt] = now; + createdAt = handleTimestampOption(timestamps, 'createdAt'); + updatedAt = handleTimestampOption(timestamps, 'updatedAt'); + if (updatedAt != null) { + update.$set[key][updatedAt] = now; + } + if (createdAt != null) { + update.$set[key][createdAt] = now; + } } } } diff --git a/test/timestamps.test.js b/test/timestamps.test.js index 0b2a0911f9f..536f9595dd5 100644 --- a/test/timestamps.test.js +++ b/test/timestamps.test.js @@ -48,7 +48,7 @@ describe('timestamps', function() { var schema = new mongoose.Schema({ name: String }, { timestamps: { createdAt: null, updatedAt: true } }); - var M = db.model('gh4868', schema); + var M = db.model('gh5598', schema); M.create({ name: 'Test' }, function(error) { assert.ifError(error); @@ -62,6 +62,28 @@ describe('timestamps', function() { }); }); + it('updatedAt without createdAt for nested (gh-5598)', function(done) { + var startTime = Date.now(); + var schema = new mongoose.Schema({ + name: String + }, { timestamps: { createdAt: null, updatedAt: true } }); + var parentSchema = new mongoose.Schema({ + child: schema + }); + var M = db.model('gh5598_0', parentSchema); + + M.create({ child: { name: 'test' } }, function(error) { + assert.ifError(error); + M.findOne({}, function(error, doc) { + assert.ifError(error); + assert.ok(!doc.child.createdAt); + assert.ok(doc.child.updatedAt); + assert.ok(doc.child.updatedAt.valueOf() >= startTime); + done(); + }); + }); + }); + it('nested paths (gh-4503)', function(done) { var startTime = Date.now(); var schema = new mongoose.Schema({ From 92f5eccc0a4201ccfb64f600571968772b28a404 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 6 Sep 2017 08:35:48 -0700 Subject: [PATCH 1852/2240] test: improve unique validator test by making create run before ensureIndex Fix #5562 Fix #5595 --- lib/model.js | 5 ++++- test/docs/validation.test.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index 04622b9ecce..2e9ff698703 100644 --- a/lib/model.js +++ b/lib/model.js @@ -865,7 +865,10 @@ for (var i in EventEmitter.prototype) { Model.init = function init() { if ((this.schema.options.autoIndex) || (this.schema.options.autoIndex == null && this.db.config.autoIndex)) { - this.ensureIndexes({ __noPromise: true, _automatic: true }); + var _this = this; + setImmediate(function() { + _this.ensureIndexes({ __noPromise: true, _automatic: true }); + }); } this.schema.emit('init', this); diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 5312c2a489e..362b6a2503f 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -140,7 +140,7 @@ describe('validation docs', function() { U2.on('index', function(error) { assert.ifError(error); U2.create(dup, function(error) { - // Will error, but will *not* be a mongoose validation error, but + // Will error, but will *not* be a mongoose validation error, it will be // a duplicate key error. assert.ok(error); assert.ok(!error.errors); From 691fd635b771e1df5436b254d823dcc297683921 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 6 Sep 2017 08:44:45 -0700 Subject: [PATCH 1853/2240] chore: enable debug mode for test --- test/docs/validation.test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 362b6a2503f..a36527c9d2a 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -15,6 +15,10 @@ describe('validation docs', function() { db.close(done); }); + afterEach(function() { + mongoose.set('debug', false); + }); + /** * Before we get into the specifics of validation syntax, please keep the following rules in mind: * @@ -114,6 +118,8 @@ describe('validation docs', function() { */ it('The `unique` Option is Not a Validator', function(done) { + mongoose.set('debug', true); + var uniqueUsernameSchema = new Schema({ username: { type: String, From 2121efb3f4781ca8b8bd6697725752913bd098dd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 6 Sep 2017 08:56:45 -0700 Subject: [PATCH 1854/2240] chore: use small pool size for test re: #5595 --- test/docs/validation.test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index a36527c9d2a..789be7390e0 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -8,7 +8,10 @@ describe('validation docs', function() { var Schema = mongoose.Schema; before(function() { - db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test'); + db = mongoose.createConnection('mongodb://localhost:27017/mongoose_test', { + useMongoClient: true, + poolSize: 1 + }); }); after(function(done) { From de6c4064b8ba7b56829311cf692472542b1684cb Mon Sep 17 00:00:00 2001 From: Gabriel Nicolas Avellaneda Date: Wed, 6 Sep 2017 19:48:36 -0300 Subject: [PATCH 1855/2240] Fixed example to work with current stable version --- index.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.jade b/index.jade index 245287d4bb6..80ec15d0e96 100644 --- a/index.jade +++ b/index.jade @@ -44,7 +44,7 @@ html(lang='en') #example :js var mongoose = require('mongoose'); - mongoose.connect('mongodb://localhost/test'); + mongoose.connect('mongodb://localhost/test', { useMongoClient: true, promiseLibrary: global.Promise }); var Cat = mongoose.model('Cat', { name: String }); From f9f4986321ade39e9cbd84c53bc89b47178904d8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Sep 2017 09:03:27 -0700 Subject: [PATCH 1856/2240] chore: remove debug print --- test/docs/validation.test.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 789be7390e0..8228a9cc8fc 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -18,10 +18,6 @@ describe('validation docs', function() { db.close(done); }); - afterEach(function() { - mongoose.set('debug', false); - }); - /** * Before we get into the specifics of validation syntax, please keep the following rules in mind: * @@ -121,8 +117,6 @@ describe('validation docs', function() { */ it('The `unique` Option is Not a Validator', function(done) { - mongoose.set('debug', true); - var uniqueUsernameSchema = new Schema({ username: { type: String, From 2e942e52c0d6976dfccbeb660ce00538c0474485 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Sep 2017 09:28:54 -0700 Subject: [PATCH 1857/2240] style: remove comma-separated vars --- lib/document.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/document.js b/lib/document.js index cc95ef5358c..c1f2a23fad2 100644 --- a/lib/document.js +++ b/lib/document.js @@ -498,12 +498,13 @@ Document.prototype.set = function(path, val, type, options) { type = undefined; } - var merge = options && options.merge, - adhoc = type && type !== true, - constructing = type === true, - adhocs; + options = options || {}; + var merge = options.merge; + var adhoc = type && type !== true; + var constructing = type === true; + var adhocs; - var strict = options && 'strict' in options + var strict = 'strict' in options ? options.strict : this.$__.strictMode; From f09793108281c6a4067c418111f2286a2b66d99f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Sep 2017 09:29:08 -0700 Subject: [PATCH 1858/2240] test(document): repro #5601 --- test/document.test.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 51db052ac97..053a4a87426 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4658,6 +4658,35 @@ describe('document', function() { }); }); + it('single nested setters only get called once (gh-5601)', function(done) { + var vals = []; + var ChildSchema = new mongoose.Schema({ + number: { + type: String, + set: function(v) { + vals.push(v); + return v; + } + }, + _id: false + }); + ChildSchema.set('toObject', { getters: true, minimize: false }); + + var ParentSchema = new mongoose.Schema({ + child: { + type: ChildSchema, + default: {}, + } + }); + + var Parent = db.model('gh5601', ParentSchema); + var p = new Parent(); + p.child = { number: '555.555.0123' }; + assert.equal(vals.length, 1); + assert.equal(vals[0], '555.555.0123'); + done(); + }); + it('consistent context for nested docs (gh-5347)', function(done) { var contexts = []; var childSchema = new mongoose.Schema({ From 0947633dc316c57a604a47792c346df948c67dd4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Sep 2017 09:29:12 -0700 Subject: [PATCH 1859/2240] fix(document): ensure single embedded doc setters only get called once, with correct value Fix #5601 --- lib/schema/embedded.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 4ada6d38edc..f41a2d64f85 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -133,7 +133,13 @@ Embedded.prototype.cast = function(val, doc, init, priorVal) { } if (priorVal && priorVal.$isSingleNested) { - subdoc = new this.caster(priorVal.toObject(), doc ? doc.$__.selected : void 0, doc); + var _priorVal = priorVal.toObject({ + minimize: true, + transform: false, + virtuals: false, + getters: false + }); + subdoc = new this.caster(_priorVal, doc ? doc.$__.selected : void 0, doc); } else { subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); } From afa0a4d898547fa99f9f4e6ec7098ebf848c2511 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Sep 2017 10:45:13 -0700 Subject: [PATCH 1860/2240] style: fix lint --- test/document.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/document.test.js b/test/document.test.js index 053a4a87426..3fd6c7c9cf6 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4675,7 +4675,7 @@ describe('document', function() { var ParentSchema = new mongoose.Schema({ child: { type: ChildSchema, - default: {}, + default: {} } }); From a6eb59a4552f6d05926eccabd633ecf9d4164586 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Sep 2017 14:49:14 -0700 Subject: [PATCH 1861/2240] test(query): repro #5592 --- test/query.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index 67956ecfe65..82a105b5f3d 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2096,6 +2096,32 @@ describe('Query', function() { }); }); + it('errors in post init (gh-5592)', function(done) { + var TestSchema = new Schema(); + + var count = 0; + TestSchema.post('init', function(model, next) { + return next(new Error('Failed! ' + (count++))); + }); + + var TestModel = db.model('gh5592', TestSchema); + + var docs = []; + for (var i = 0; i < 10; ++i) { + docs.push({}); + } + + TestModel.create(docs, function(error) { + assert.ifError(error); + TestModel.find({}, function(error, docs) { + assert.ok(error); + assert.equal(error.message, 'Failed! 0'); + assert.equal(count, 10); + done(); + }); + }); + }); + it('handles geoWithin with mongoose docs (gh-4392)', function(done) { var areaSchema = new Schema({ name: {type: String}, From 3f5908cddba84cfcbc51973e886aaf9205765a8d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Sep 2017 14:49:34 -0700 Subject: [PATCH 1862/2240] fix(query): ensure find callback only gets called once when post init hook throws error Fix #5592 --- lib/query.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/query.js b/lib/query.js index 7b12c4dc634..a1e1891e0fd 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1305,11 +1305,16 @@ function completeMany(model, docs, fields, userProvidedFields, pop, callback) { var arr = []; var count = docs.length; var len = count; - var opts = pop ? - {populated: pop} - : undefined; - function init(err) { - if (err) return callback(err); + var opts = pop ? { populated: pop } : undefined; + var error = null; + function init(_error) { + if (error != null) { + return; + } + if (_error != null) { + error = _error; + return callback(error); + } --count || callback(null, arr); } for (var i = 0; i < len; ++i) { From 2aa4d842be56cba514179f90734deedc3c3b0899 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Sep 2017 15:48:22 -0700 Subject: [PATCH 1863/2240] chore: bump lock file --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 2817225881f..8739c25c38c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.11.9-pre", + "version": "4.11.11-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From 1cd36a822cc07416752af7bfdb03e27722cecfe5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Sep 2017 16:03:32 -0700 Subject: [PATCH 1864/2240] test(connection): repro #5604 --- test/connection.test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/connection.test.js b/test/connection.test.js index 654bb009ced..5ee33e5f355 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -110,6 +110,7 @@ describe('connections:', function() { conn. then(function() { + assert.equal(conn.readyState, conn.states.connected); assert.equal(numConnected, 1); return server.stop(); }). @@ -119,6 +120,7 @@ describe('connections:', function() { }); }). then(function() { + assert.equal(conn.readyState, conn.states.disconnected); assert.equal(numDisconnected, 1); assert.equal(numReconnected, 0); }). @@ -131,6 +133,7 @@ describe('connections:', function() { }); }). then(function() { + assert.equal(conn.readyState, conn.states.connected); assert.equal(numDisconnected, 1); assert.equal(numReconnected, 1); @@ -164,6 +167,7 @@ describe('connections:', function() { conn. then(function() { + assert.equal(conn.readyState, conn.states.connected); return Model.create({}); }). then(function() { @@ -175,6 +179,9 @@ describe('connections:', function() { catch(function(error) { assert.ok(error); assert.ok(error.message.indexOf('timed out'), error.message); + // TODO: if autoReconnect is false, we might not actually be + // connected. See gh-5634 + assert.equal(conn.readyState, conn.states.connected); assert.equal(numTimeout, 1); assert.equal(numDisconnected, 0); From 55716cc699c2587b513e52ff50d5f9ed44b8ffb7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Sep 2017 16:03:36 -0700 Subject: [PATCH 1865/2240] fix(connection): properly set ready state in response to driver 'close' and 'reconnect' events Fix #5604 --- lib/connection.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index ea1d74b5bb2..63d64e9756c 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -66,6 +66,7 @@ function Connection(base) { this.name = null; this.options = null; this.otherDbs = []; + this.states = STATES; this._readyState = STATES.disconnected; this._closeCalled = false; this._hasOpened = false; @@ -764,10 +765,12 @@ Connection.prototype.openUri = function(uri, options, callback) { } // Backwards compat for mongoose 4.x db.on('reconnect', function() { + _this.readyState = STATES.connected; _this.emit('reconnected'); }); db.s.topology.on('close', function() { - _this.emit('disconnected'); + // Implicitly emits 'disconnected' + _this.readyState = STATES.disconnected; }); db.on('timeout', function() { _this.emit('timeout'); From 66c41e4c42f42e65c06c013a62467b2e8850d7f6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Sep 2017 16:07:36 -0700 Subject: [PATCH 1866/2240] style: fix lint --- test/query.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/query.test.js b/test/query.test.js index 82a105b5f3d..ec07fa3380d 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2113,7 +2113,7 @@ describe('Query', function() { TestModel.create(docs, function(error) { assert.ifError(error); - TestModel.find({}, function(error, docs) { + TestModel.find({}, function(error) { assert.ok(error); assert.equal(error.message, 'Failed! 0'); assert.equal(count, 10); From 6e5e5679d7ea3782c2530fe48c142417ac2ad412 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Sep 2017 21:42:01 -0700 Subject: [PATCH 1867/2240] feat(query): add .error() helper to query to error out in pre hooks Fix #5520 --- lib/query.js | 112 +++++++++++++++++++++++++++++++-------------- lib/schema.js | 1 + test/query.test.js | 37 +++++++++++++++ 3 files changed, 115 insertions(+), 35 deletions(-) diff --git a/lib/query.js b/lib/query.js index a1e1891e0fd..95a78711276 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2,6 +2,7 @@ * Module dependencies. */ +var CastError = require('./error/cast'); var PromiseProvider = require('./promise_provider'); var QueryCursor = require('./cursor/QueryCursor'); var QueryStream = require('./querystream'); @@ -1120,6 +1121,46 @@ Query.prototype.lean = function(v) { return this; }; +/** + * Gets/sets the error flag on this query. If this flag is not null or + * undefined, the `exec()` promise will reject. + * + * ####Example: + * + * Query().error(); // Get current error value + * Query().error(null); // Unset the current error + * Query().error(new Error('test')); // `exec()` will resolve with test + * Schema.pre('find', function() { + * if (!this.getQuery().userId) { + * this.error(new Error('Not allowed to query without setting userId')); + * } + * }); + * + * @param {Error|null} err if set, `exec()` will fail fast before sending the query to MongoDB + * @returns {Query} this + * @api public + */ + +Query.prototype.error = function error(err) { + if (arguments.length === 0) { + return this._error; + } + + this._error = err; + return this; +}; + +/*! + * ignore + */ + +Query.prototype._setCastError = function _setCastError(err) { + if (err == null && this._error != null && !(this._error instanceof CastError)) { + return; + } + return this.error(err); +}; + /** * Getter/setter around the current mongoose-specific options for this query * (populate, lean, etc.) @@ -1143,9 +1184,9 @@ Query.prototype.mongooseOptions = function(v) { Query.prototype._castConditions = function() { try { this.cast(this.model); - this._castError = null; + this._setCastError(null); } catch (err) { - this._castError = err; + this.error(err); } }; @@ -1159,8 +1200,8 @@ Query.prototype._castConditions = function() { Query.prototype._find = function(callback) { this._castConditions(); - if (this._castError) { - callback(this._castError); + if (this.error() != null) { + callback(this.error()); return this; } @@ -1351,8 +1392,8 @@ Query.prototype.collation = function(value) { Query.prototype._findOne = function(callback) { this._castConditions(); - if (this._castError) { - return callback(this._castError); + if (this.error()) { + return callback(this.error()); } this._applyPaths(); @@ -1459,9 +1500,9 @@ Query.prototype.findOne = function(conditions, projection, options, callback) { try { this.cast(this.model); - this._castError = null; + this.error(null); } catch (err) { - this._castError = err; + this.error(err); } if (!callback) { @@ -1486,10 +1527,11 @@ Query.prototype._count = function(callback) { try { this.cast(this.model); } catch (err) { - process.nextTick(function() { - callback(err); - }); - return this; + this.error(err); + } + + if (this.error()) { + return callback(this.error()); } var conds = this._conditions; @@ -1678,7 +1720,7 @@ Query.prototype.remove = function(filter, callback) { this.cast(this.model, filter); this.merge(filter); } catch (err) { - this._castError = err; + this.error(err); } prepareDiscriminatorCriteria(this); @@ -1695,8 +1737,8 @@ Query.prototype.remove = function(filter, callback) { */ Query.prototype._remove = function(callback) { - if (this._castError) { - callback(this._castError); + if (this.error() != null) { + callback(this.error()); return this; } @@ -1733,7 +1775,7 @@ Query.prototype.deleteOne = function(filter, callback) { this.cast(this.model, filter); this.merge(filter); } catch (err) { - this._castError = err; + this.error(err); } prepareDiscriminatorCriteria(this); @@ -1750,8 +1792,8 @@ Query.prototype.deleteOne = function(filter, callback) { */ Query.prototype._deleteOne = function(callback) { - if (this._castError) { - callback(this._castError); + if (this.error() != null) { + callback(this.error()); return this; } @@ -1788,7 +1830,7 @@ Query.prototype.deleteMany = function(filter, callback) { this.cast(this.model, filter); this.merge(filter); } catch (err) { - this._castError = err; + this.error(err); } prepareDiscriminatorCriteria(this); @@ -1805,8 +1847,8 @@ Query.prototype.deleteMany = function(filter, callback) { */ Query.prototype._deleteMany = function(callback) { - if (this._castError) { - callback(this._castError); + if (this.error() != null) { + callback(this.error()); return this; } @@ -1981,8 +2023,8 @@ Query.prototype.findOneAndUpdate = function(criteria, doc, options, callback) { Query.prototype._findOneAndUpdate = function(callback) { this._castConditions(); - if (this._castError) { - return callback(this._castError); + if (this.error() != null) { + return callback(this.error()); } this._findAndModify('update', callback); @@ -2073,8 +2115,8 @@ Query.prototype.findOneAndRemove = function(conditions, options, callback) { Query.prototype._findOneAndRemove = function(callback) { this._castConditions(); - if (this._castError) { - return callback(this._castError); + if (this.error() != null) { + return callback(this.error()); } Query.base.findOneAndRemove.call(this, callback); @@ -2330,8 +2372,8 @@ Query.prototype._execUpdate = function(callback) { var castedDoc = this._update; var options = this.options; - if (this._castError) { - callback(this._castError); + if (this.error() != null) { + callback(this.error()); return this; } @@ -2394,8 +2436,8 @@ Query.prototype._updateMany = function(callback) { var castedDoc = this._update; var options = this.options; - if (this._castError) { - callback(this._castError); + if (this.error() != null) { + callback(this.error()); return this; } @@ -2441,8 +2483,8 @@ Query.prototype._updateOne = function(callback) { var castedDoc = this._update; var options = this.options; - if (this._castError) { - callback(this._castError); + if (this.error() != null) { + callback(this.error()); return this; } @@ -2486,8 +2528,8 @@ Query.prototype._replaceOne = function(callback) { var castedDoc = this._update; var options = this.options; - if (this._castError) { - callback(this._castError); + if (this.error() != null) { + callback(this.error()); return this; } @@ -2816,7 +2858,7 @@ function _update(query, op, conditions, doc, options, callback) { // validate the selector part of the query var castedQuery = castQuery(query); if (castedQuery instanceof Error) { - query._castError = castedQuery; + query.error(castedQuery); if (callback) { callback(castedQuery); return query; @@ -2835,7 +2877,7 @@ function _update(query, op, conditions, doc, options, callback) { castedDoc = query._castUpdate(utils.clone(doc, $options), (options && options.overwrite) || op === 'replaceOne'); } catch (err) { - query._castError = castedQuery; + query.error(castedQuery); if (callback) { callback(err); return query; diff --git a/lib/schema.js b/lib/schema.js index 0d993e4a1f3..2bbf80aebff 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -19,6 +19,7 @@ var IS_KAREEM_HOOK = { findOneAndUpdate: true, findOneAndRemove: true, insertMany: true, + replaceOne: true, update: true, updateMany: true, updateOne: true diff --git a/test/query.test.js b/test/query.test.js index 82a105b5f3d..accf68deb33 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2096,6 +2096,43 @@ describe('Query', function() { }); }); + it('report error in pre hook (gh-5520)', function(done) { + var TestSchema = new Schema({ name: String }); + var i; + + var ops = [ + 'count', + 'find', + 'findOne', + 'findOneAndRemove', + 'findOneAndUpdate', + 'replaceOne', + 'update', + 'updateOne', + 'updateMany' + ]; + + ops.forEach(function(op) { + TestSchema.pre(op, function(next) { + this.error(new Error(op + ' error')); + next(); + }); + }); + + var TestModel = db.model('gh5520', TestSchema); + + var numOps = ops.length; + + ops.forEach(function(op) { + TestModel.find({}).update({ name: 'test' })[op](function(error) { + assert.ok(error); + assert.equal(error.message, op + ' error'); + --numOps || done(); + }); + }) + }); + + it('errors in post init (gh-5592)', function(done) { var TestSchema = new Schema(); From 1f29656bba69511e91eef3b30f435527ad4aa1f4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Sep 2017 21:44:13 -0700 Subject: [PATCH 1868/2240] style: fix lint --- test/query.test.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index accf68deb33..4128a52dd6d 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2098,7 +2098,6 @@ describe('Query', function() { it('report error in pre hook (gh-5520)', function(done) { var TestSchema = new Schema({ name: String }); - var i; var ops = [ 'count', @@ -2129,7 +2128,7 @@ describe('Query', function() { assert.equal(error.message, op + ' error'); --numOps || done(); }); - }) + }); }); @@ -2150,7 +2149,7 @@ describe('Query', function() { TestModel.create(docs, function(error) { assert.ifError(error); - TestModel.find({}, function(error, docs) { + TestModel.find({}, function(error) { assert.ok(error); assert.equal(error.message, 'Failed! 0'); assert.equal(count, 10); From 9b388b8eb5ae10dcca63a1728545b409e49828ac Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 10 Sep 2017 11:54:02 -0700 Subject: [PATCH 1869/2240] chore: release 4.11.11 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 60854eee74d..1afb9f12569 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.11.11 / 2017-09-10 +==================== + * fix(connection): properly set readyState in response to driver 'close' and 'reconnect' events #5604 + * fix(document): ensure single embedded doc setters only get called once, with correct value #5601 + * fix(timestamps): allow enabling updatedAt without createdAt #5598 + * test: improve unique validator test by making create run before ensureIndex #5595 #5562 + * fix(query): ensure find callback only gets called once when post init hook throws error #5592 + 4.11.10 / 2017-09-03 ==================== * docs: add KeenIO tracking #5612 diff --git a/package.json b/package.json index 8d707fbbf45..63e3f0b50b4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.11-pre", + "version": "4.11.11", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From d8639d5b892668ee8c753763a8367a81ddb4032e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 10 Sep 2017 11:56:04 -0700 Subject: [PATCH 1870/2240] chore: now working on 4.11.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 63e3f0b50b4..6ca7ad2ac40 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.11", + "version": "4.11.12-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 324b4cba58f86e30beb88884884354ae31ae6149 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 10 Sep 2017 12:39:01 -0700 Subject: [PATCH 1871/2240] feat(connection): add dropCollection() helper Fix #5393 --- lib/connection.js | 78 ++++++++++++++++++++++++++++------------- package-lock.json | 2 +- test/connection.test.js | 31 ++++++++++++++++ 3 files changed, 85 insertions(+), 26 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 8d0fd618782..3fe85c11b01 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -369,42 +369,70 @@ Connection.prototype._openWithoutPromise = function() { }; /** - * Helper for `dropDatabase()`. + * Helper for `dropCollection()`. Will delete the given collection, including + * all documents and indexes. * - * @param {Function} callback + * @param {string} collection The collection to delete + * @param {Function} [callback] * @return {Promise} * @api public */ -Connection.prototype.dropDatabase = function(callback) { - var Promise = PromiseProvider.get(); - var _this = this; - var promise = new Promise.ES6(function(resolve, reject) { - if (_this.readyState !== STATES.connected) { - _this.on('open', function() { - _this.db.dropDatabase(function(error) { +Connection.prototype.dropCollection = _wrapConnHelper(function dropCollection(collection, cb) { + this.db.dropCollection(collection, cb); +}); + +/** + * Helper for `dropDatabase()`. Deletes the given database, including all + * collections, documents, and indexes. + * + * @param {Function} [callback] + * @return {Promise} + * @api public + */ + +Connection.prototype.dropDatabase = _wrapConnHelper(function dropDatabase(cb) { + this.db.dropDatabase(cb); +}); + +/*! + * ignore + */ + +function _wrapConnHelper(fn) { + return function() { + var _this = this; + var Promise = PromiseProvider.get(); + var argsWithoutCb = Array.prototype.slice.call(arguments, 0, fn.length - 1); + var cb = arguments[arguments.length - 1]; + var promise = new Promise.ES6(function(resolve, reject) { + if (_this.readyState !== STATES.connected) { + _this.on('open', function() { + fn.apply(_this, argsWithoutCb.concat([function(error) { + if (error) { + reject(error); + } else { + resolve(); + } + }])); + }); + } else { + fn.apply(_this, argsWithoutCb.concat([function(error) { if (error) { reject(error); } else { resolve(); } - }); - }); - } else { - _this.db.dropDatabase(function(error) { - if (error) { - reject(error); - } else { - resolve(); - } - }); + }])); + } + }); + if (cb) { + promise. + then(function() { cb(); }, function(error) { cb(error); }); } - }); - if (callback) { - promise.then(function() { callback(); }, callback); - } - return promise; -}; + return promise; + }; +} /*! * ignore diff --git a/package-lock.json b/package-lock.json index 8739c25c38c..1e434c722cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.11.11-pre", + "version": "4.12.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/connection.test.js b/test/connection.test.js index a1017659d4c..62ddcedb517 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -268,6 +268,37 @@ describe('connections:', function() { }); }); + describe('helpers', function() { + var conn; + + before(function() { + conn = mongoose.connect('mongodb://localhost:27017/mongoosetest', { + useMongoClient: true + }); + return conn; + }); + + it('dropDatabase()', function(done) { + conn.dropDatabase(function(error) { + assert.ifError(error); + done(); + }); + }); + + it('dropCollection()', function() { + return conn.db.collection('test').insertOne({ x: 1 }). + then(function() { + return conn.dropCollection('test'); + }). + then(function() { + return conn.db.collection('test').findOne(); + }). + then(function(doc) { + assert.ok(!doc); + }); + }); + }); + it('should allow closing a closed connection', function(done) { var db = mongoose.createConnection(); From 7b0da85a4e0e0be99ea0e0c7b6694d16885bbbb7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 10 Sep 2017 12:45:44 -0700 Subject: [PATCH 1872/2240] test: fix tests --- test/connection.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/connection.test.js b/test/connection.test.js index 62ddcedb517..4137714631e 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -272,7 +272,7 @@ describe('connections:', function() { var conn; before(function() { - conn = mongoose.connect('mongodb://localhost:27017/mongoosetest', { + conn = mongoose.connect('mongodb://localhost:27017/mongoosetest_2', { useMongoClient: true }); return conn; From e0e0aa68abcbfdadbfc428a0856d7924e161104e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 11 Sep 2017 11:00:53 -0700 Subject: [PATCH 1873/2240] fix(connection): call callback when initial connection failed Fix #5626 --- lib/connection.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/connection.js b/lib/connection.js index 63d64e9756c..06f1d879836 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -761,6 +761,7 @@ Connection.prototype.openUri = function(uri, options, callback) { if (_this.listeners('error').length) { _this.emit('error', error); } + callback && callback(error); return reject(error); } // Backwards compat for mongoose 4.x From 52c8b258dd38040f2838346185e9f0843df4f0b3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 11 Sep 2017 18:20:10 -0700 Subject: [PATCH 1874/2240] refactor: use before hook for collation tests --- test/query.test.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index 4128a52dd6d..7f5971d6b8e 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1590,22 +1590,23 @@ describe('Query', function() { db.close(done); }); - it('collation support (gh-4839)', function(done) { - start.mongodVersion(function(err, version) { - if (err) { - done(err); - return; - } - var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); - if (!mongo34) { - done(); - return; - } + describe('collations', function() { + before(function(done) { + var _this = this; + start.mongodVersion(function(err, version) { + if (err) { + return done(err); + } + var mongo34 = version[0] > 3 || (version[0] === 3 && version[1] >= 4); + if (!mongo34) { + return _this.skip(); + } - test(); + done(); + }); }); - function test() { + it('collation support (gh-4839)', function(done) { var schema = new Schema({ name: String }); @@ -1637,7 +1638,7 @@ describe('Query', function() { done(); }). catch(done); - } + }); }); describe('gh-1950', function() { From e5fd79dbb073f8a586baff4e16debf825ecbb22e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 11 Sep 2017 18:26:44 -0700 Subject: [PATCH 1875/2240] feat(schema): add schema-level collation option Fix #5295 --- docs/guide.jade | 20 ++++++++++++++++++++ lib/aggregate.js | 13 +++++++++---- lib/query.js | 5 +++++ lib/schema.js | 1 + test/query.test.js | 18 ++++++++++++++++++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/docs/guide.jade b/docs/guide.jade index 2a8fb63cdcf..05e00760a35 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -311,6 +311,7 @@ block content - [typeKey](#typeKey) - [validateBeforeSave](#validateBeforeSave) - [versionKey](#versionKey) + - [collation](#collation) - [skipVersioning](#skipVersioning) - [timestamps](#timestamps) - [retainKeyOrder](#retainKeyOrder) @@ -663,6 +664,25 @@ block content var thing = new Thing({ name: 'no versioning please' }); thing.save(); // { name: 'no versioning please' } + h4#collation option: collation + :markdown + Sets a default [collation](https://docs.mongodb.com/manual/reference/collation/) for every query and aggregation. [Here's a beginner-friendly overview of collations](http://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations). + :js + var schema = new Schema({ + name: String + }, { collation: { locale: 'en_US', strength: 1 } }); + + var MyModel = db.model('MyModel', schema); + + MyModel.create([{ name: 'val' }, { name: 'Val' }]). + then(function() { + return MyModel.find({ name: 'val' }); + }). + then(function(docs) { + // `docs` will contain both docs, because `strength: 1` means + // MongoDB will ignore case when matching. + }); + h4#skipVersioning option: skipVersioning :markdown `skipVersioning` allows excluding paths from versioning (i.e., the internal revision will not be incremented even if these paths are updated). DO NOT do this unless you know what you're doing. For sub-documents, include this on the parent document using the fully qualified path. diff --git a/lib/aggregate.js b/lib/aggregate.js index eaa20587c51..9d0d00f66e5 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -63,10 +63,15 @@ function Aggregate() { Aggregate.prototype.model = function(model) { this._model = model; - if (this.options.readPreference == null && - model.schema && - model.schema.options.read != null) { - this.options.readPreference = model.schema.options.read; + if (model.schema != null) { + if (this.options.readPreference == null && + model.schema.options.read != null) { + this.options.readPreference = model.schema.options.read; + } + if (this.options.collation == null && + model.schema.options.collation != null) { + this.options.collation = model.schema.options.collation; + } } return this; }; diff --git a/lib/query.js b/lib/query.js index 95a78711276..cbc91c66253 100644 --- a/lib/query.js +++ b/lib/query.js @@ -72,6 +72,11 @@ function Query(conditions, options, model, collection) { this.find(conditions); } + this.options = this.options || {}; + if (this.schema != null && this.schema.options.collation != null) { + this.options.collation = this.schema.options.collation; + } + if (this.schema) { var kareemOptions = { useErrorHandlers: true, diff --git a/lib/schema.js b/lib/schema.js index 2bbf80aebff..cec68db1dc4 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -57,6 +57,7 @@ var IS_KAREEM_HOOK = { * - [useNestedStrict](/docs/guide.html#useNestedStrict) - boolean - defaults to false * - [validateBeforeSave](/docs/guide.html#validateBeforeSave) - bool - defaults to `true` * - [versionKey](/docs/guide.html#versionKey): string - defaults to "__v" + * - [collation](/docs/guide.html#collation): object - defaults to null (which means use no collation) * * ####Note: * diff --git a/test/query.test.js b/test/query.test.js index 7f5971d6b8e..d691fc9affa 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1639,6 +1639,24 @@ describe('Query', function() { }). catch(done); }); + + it('set on schema (gh-5295)', function(done) { + var schema = new Schema({ + name: String + }, { collation: { locale: 'en_US', strength: 1 } }); + + var MyModel = db.model('gh5295', schema); + + MyModel.create([{ name: 'a' }, { name: 'A' }]). + then(function() { + return MyModel.find({ name: 'a' }); + }). + then(function(docs) { + assert.equal(docs.length, 2); + done(); + }). + catch(done); + }); }); describe('gh-1950', function() { From 57e7bea3bda638f500658535e23bb133258a6857 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 14 Sep 2017 19:45:56 -0700 Subject: [PATCH 1876/2240] test(query): repro #5603 --- test/query.test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index ec07fa3380d..17116ce5b8b 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2096,6 +2096,34 @@ describe('Query', function() { }); }); + it('child schema with select: false in multiple paths (gh-5603)', function(done) { + var ChildSchema = new mongoose.Schema({ + field: { + type: String, + select: false + }, + _id: false + }, { id: false }); + + var ParentSchema = new mongoose.Schema({ + child: ChildSchema, + child2: ChildSchema, + }); + var Parent = db.model('gh5603', ParentSchema); + var ogParent = new Parent(); + ogParent.child = { field: 'test' }; + ogParent.child2 = { field: 'test' }; + ogParent.save(function(error) { + assert.ifError(error); + Parent.findById(ogParent._id).exec(function(error, doc) { + assert.ifError(error); + assert.ok(!doc.child.field); + assert.ok(!doc.child2.field); + done(); + }); + }); + }); + it('errors in post init (gh-5592)', function(done) { var TestSchema = new Schema(); From c232c2e0a36136cc54c8c8bf19c510550e0b70fd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 14 Sep 2017 19:46:44 -0700 Subject: [PATCH 1877/2240] fix(query): apply select correctly if a given nested schema is used for 2 different paths Fix #5603 --- lib/queryhelpers.js | 14 +++++++++----- package-lock.json | 2 +- test/query.test.js | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/queryhelpers.js b/lib/queryhelpers.js index 868a0a20777..8ce3500ea70 100644 --- a/lib/queryhelpers.js +++ b/lib/queryhelpers.js @@ -101,9 +101,9 @@ exports.applyPaths = function applyPaths(fields, schema) { // if selecting, apply default schematype select:true fields // if excluding, apply schematype select:false fields - var selected = [], - excluded = [], - seen = []; + var selected = []; + var excluded = []; + var stack = []; var analyzePath = function(path, type) { if (typeof type.selected !== 'boolean') return; @@ -133,8 +133,10 @@ exports.applyPaths = function applyPaths(fields, schema) { prefix || (prefix = ''); // avoid recursion - if (~seen.indexOf(schema)) return; - seen.push(schema); + if (stack.indexOf(schema) !== -1) { + return; + } + stack.push(schema); schema.eachPath(function(path, type) { if (prefix) path = prefix + '.' + path; @@ -146,6 +148,8 @@ exports.applyPaths = function applyPaths(fields, schema) { analyzeSchema(type.schema, path); } }); + + stack.pop(); }; analyzeSchema(schema); diff --git a/package-lock.json b/package-lock.json index 8739c25c38c..34339dfe4ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.11.11-pre", + "version": "4.11.12-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/query.test.js b/test/query.test.js index 17116ce5b8b..16cde51ee71 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2107,7 +2107,7 @@ describe('Query', function() { var ParentSchema = new mongoose.Schema({ child: ChildSchema, - child2: ChildSchema, + child2: ChildSchema }); var Parent = db.model('gh5603', ParentSchema); var ogParent = new Parent(); From 7c006f675e92882800d3f338f7a6933f82dd3748 Mon Sep 17 00:00:00 2001 From: Tim Kinnane Date: Fri, 15 Sep 2017 17:24:29 +1000 Subject: [PATCH 1878/2240] Asterisk should not render as markdown bullet Minor issue with readability in the docs, there's a follow up clarificaiton to the "almost*" clause on `findOne`, but the leading asterisk was being converted to a dot point. Took my a while to find what that "almost" refered to. --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 2e9ff698703..864fd13deb0 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1286,7 +1286,7 @@ Model.find = function find(conditions, projection, options, callback) { * * Note: `findById()` triggers `findOne` hooks. * - * * Except for how it treats `undefined`. If you use `findOne()`, you'll see + * \* Except for how it treats `undefined`. If you use `findOne()`, you'll see * that `findOne(undefined)` and `findOne({ _id: undefined })` are equivalent * to `findOne({})` and return arbitrary documents. However, mongoose * translates `findById(undefined)` into `findOne({ _id: null })`. From 32303d85a47bf55741a2b381cc7edd692467d0ae Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 16 Sep 2017 11:20:08 -0700 Subject: [PATCH 1879/2240] docs(model): use catch() instead of anachronistic onRejected() --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 926548fed8a..392e7390f4c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -709,7 +709,7 @@ Model.prototype.$__where = function _where(where) { * ####Example: * product.remove().then(function (product) { * ... - * }).onRejected(function (err) { + * }).catch(function (err) { * assert.ok(err) * }) * From 5d8b19fce332f074d1dc6996efc9d41565a949dc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 16 Sep 2017 11:39:10 -0700 Subject: [PATCH 1880/2240] feat(document): add $isDeleted() getter/setter for better support for soft deletes Fix #4428 --- lib/document.js | 27 +++++++++++++++++++++++++++ lib/model.js | 11 ++++++++++- test/query.test.js | 31 +++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index c1f2a23fad2..63ad0f17af1 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1134,6 +1134,33 @@ Document.prototype.$isDefault = function(path) { return (path in this.$__.activePaths.states.default); }; +/** + * Getter/setter, determines whether the document was removed or not. + * + * ####Example: + * product.remove(function (err, product) { + * product.isDeleted(); // true + * product.remove(); // no-op, doesn't send anything to the db + * + * product.isDeleted(false); + * product.isDeleted(); // false + * product.remove(); // will execute a remove against the db + * }) + * + * @param {Boolean} [val] optional, overrides whether mongoose thinks the doc is deleted + * @return {Boolean} whether mongoose thinks this doc is deleted. + * @api public + */ + +Document.prototype.$isDeleted = function(val) { + if (arguments.length === 0) { + return !!this.$__.isDeleted; + } + + this.$__.isDeleted = !!val; + return this; +}; + /** * Returns true if `path` was directly set and modified, else false. * diff --git a/lib/model.js b/lib/model.js index 392e7390f4c..6282eb8f269 100644 --- a/lib/model.js +++ b/lib/model.js @@ -724,6 +724,8 @@ Model.prototype.remove = function remove(options, fn) { options = undefined; } + var _this = this; + if (!options) { options = {}; } @@ -736,8 +738,13 @@ Model.prototype.remove = function remove(options, fn) { } return this; } + if (this.$__.isDeleted) { + setImmediate(function() { + fn(null, _this); + }); + return this; + } - var _this = this; var Promise = PromiseProvider.get(); if (fn) { @@ -758,12 +765,14 @@ Model.prototype.remove = function remove(options, fn) { _this.collection.remove(where, options, function(err) { if (!err) { + _this.$__.isDeleted = true; _this.emit('remove', _this); _this.constructor.emit('remove', _this); resolve(_this); fn && fn(null, _this); return; } + _this.$__.isDeleted = false; reject(err); fn && fn(err); }); diff --git a/test/query.test.js b/test/query.test.js index f39ecc5b834..92c0a0cfe0d 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2150,6 +2150,37 @@ describe('Query', function() { }); }); + it('change deleteOne to updateOne for soft deletes using $isDeleted (gh-4428)', function(done) { + var schema = new mongoose.Schema({ + name: String, + isDeleted: Boolean + }); + + schema.pre('remove', function(next) { + var _this = this; + this.update({ isDeleted: true }, function(error) { + // Force mongoose to consider this doc as deleted. + _this.$isDeleted(true); + next(error); + }); + }); + + var M = db.model('gh4428', schema); + + M.create({ name: 'test' }, function(error, doc) { + assert.ifError(error); + doc.remove(function(error) { + assert.ifError(error); + M.findById(doc._id, function(error, doc) { + assert.ifError(error); + assert.ok(doc); + assert.equal(doc.isDeleted, true); + done(); + }); + }); + }); + }); + it('child schema with select: false in multiple paths (gh-5603)', function(done) { var ChildSchema = new mongoose.Schema({ field: { From 84695a12bdbc1489ecea97521e1705425b903fc2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 16 Sep 2017 16:01:05 -0700 Subject: [PATCH 1881/2240] refactor(document): move compile and defineKey into separate file Re: #5613 --- lib/document.js | 154 +---------------------------- lib/services/document/compile.js | 165 +++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 152 deletions(-) create mode 100644 lib/services/document/compile.js diff --git a/lib/document.js b/lib/document.js index c1f2a23fad2..6415b0286f8 100644 --- a/lib/document.js +++ b/lib/document.js @@ -16,7 +16,9 @@ var isMongooseObject = utils.isMongooseObject; var inspect = require('util').inspect; var ValidationError = MongooseError.ValidationError; var InternalCache = require('./internal'); +var compile = require('./services/document/compile').compile; var deepEqual = utils.deepEqual; +var defineKey = require('./services/document/compile').defineKey; var hooks = require('hooks-fixed'); var PromiseProvider = require('./promise_provider'); var DocumentArray; @@ -1834,158 +1836,6 @@ Document.prototype.$__dirty = function() { return minimal; }; -/*! - * Compiles schemas. - */ - -function compile(tree, proto, prefix, options) { - var keys = Object.keys(tree); - var i = keys.length; - var len = keys.length; - var limb; - var key; - - if (options.retainKeyOrder) { - for (i = 0; i < len; ++i) { - key = keys[i]; - limb = tree[key]; - - defineKey(key, - ((utils.getFunctionName(limb.constructor) === 'Object' - && Object.keys(limb).length) - && (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type)) - ? limb - : null) - , proto - , prefix - , keys - , options); - } - } else { - while (i--) { - key = keys[i]; - limb = tree[key]; - - defineKey(key, - ((utils.getFunctionName(limb.constructor) === 'Object' - && Object.keys(limb).length) - && (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type)) - ? limb - : null) - , proto - , prefix - , keys - , options); - } - } -} - -// gets descriptors for all properties of `object` -// makes all properties non-enumerable to match previous behavior to #2211 -function getOwnPropertyDescriptors(object) { - var result = {}; - - Object.getOwnPropertyNames(object).forEach(function(key) { - result[key] = Object.getOwnPropertyDescriptor(object, key); - result[key].enumerable = ['isNew', '$__', 'errors', '_doc'].indexOf(key) === -1; - }); - - return result; -} - -/*! - * Defines the accessor named prop on the incoming prototype. - */ - -function defineKey(prop, subprops, prototype, prefix, keys, options) { - var path = (prefix ? prefix + '.' : '') + prop; - prefix = prefix || ''; - - if (subprops) { - Object.defineProperty(prototype, prop, { - enumerable: true, - configurable: true, - get: function() { - var _this = this; - if (!this.$__.getters) { - this.$__.getters = {}; - } - - if (!this.$__.getters[path]) { - var nested = Object.create(Object.getPrototypeOf(this), getOwnPropertyDescriptors(this)); - - // save scope for nested getters/setters - if (!prefix) { - nested.$__.scope = this; - } - - // shadow inherited getters from sub-objects so - // thing.nested.nested.nested... doesn't occur (gh-366) - var i = 0, - len = keys.length; - - for (; i < len; ++i) { - // over-write the parents getter without triggering it - Object.defineProperty(nested, keys[i], { - enumerable: false, // It doesn't show up. - writable: true, // We can set it later. - configurable: true, // We can Object.defineProperty again. - value: undefined // It shadows its parent. - }); - } - - Object.defineProperty(nested, 'toObject', { - enumerable: false, - configurable: true, - writable: false, - value: function() { - return clone(_this.get(path), { retainKeyOrder: true }); - } - }); - - Object.defineProperty(nested, 'toJSON', { - enumerable: false, - configurable: true, - writable: false, - value: function() { - return _this.get(path); - } - }); - - Object.defineProperty(nested, '$__isNested', { - enumerable: false, - configurable: true, - writable: false, - value: true - }); - - compile(subprops, nested, path, options); - this.$__.getters[path] = nested; - } - - return this.$__.getters[path]; - }, - set: function(v) { - if (v instanceof Document) { - v = v.toObject({ transform: false }); - } - return (this.$__.scope || this).set(path, v); - } - }); - } else { - Object.defineProperty(prototype, prop, { - enumerable: true, - configurable: true, - get: function() { - return this.get.call(this.$__.scope || this, path); - }, - set: function(v) { - return this.set.call(this.$__.scope || this, path, v); - } - }); - } -} - /** * Assigns/compiles `schema` into this documents prototype. * diff --git a/lib/services/document/compile.js b/lib/services/document/compile.js new file mode 100644 index 00000000000..c2a5d4c7067 --- /dev/null +++ b/lib/services/document/compile.js @@ -0,0 +1,165 @@ +'use strict'; + +var Document; +var utils = require('../../utils'); + +/*! + * exports + */ + +exports.compile = compile; +exports.defineKey = defineKey; + +/*! + * Compiles schemas. + */ + +function compile(tree, proto, prefix, options) { + Document = Document || require('../../document'); + var keys = Object.keys(tree); + var i = keys.length; + var len = keys.length; + var limb; + var key; + + if (options.retainKeyOrder) { + for (i = 0; i < len; ++i) { + key = keys[i]; + limb = tree[key]; + + defineKey(key, + ((utils.getFunctionName(limb.constructor) === 'Object' + && Object.keys(limb).length) + && (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type)) + ? limb + : null) + , proto + , prefix + , keys + , options); + } + } else { + while (i--) { + key = keys[i]; + limb = tree[key]; + + defineKey(key, + ((utils.getFunctionName(limb.constructor) === 'Object' + && Object.keys(limb).length) + && (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type)) + ? limb + : null) + , proto + , prefix + , keys + , options); + } + } +} + +/*! + * Defines the accessor named prop on the incoming prototype. + */ + +function defineKey(prop, subprops, prototype, prefix, keys, options) { + Document = Document || require('../../document'); + var path = (prefix ? prefix + '.' : '') + prop; + prefix = prefix || ''; + + if (subprops) { + Object.defineProperty(prototype, prop, { + enumerable: true, + configurable: true, + get: function() { + var _this = this; + if (!this.$__.getters) { + this.$__.getters = {}; + } + + if (!this.$__.getters[path]) { + var nested = Object.create(Object.getPrototypeOf(this), getOwnPropertyDescriptors(this)); + + // save scope for nested getters/setters + if (!prefix) { + nested.$__.scope = this; + } + + // shadow inherited getters from sub-objects so + // thing.nested.nested.nested... doesn't occur (gh-366) + var i = 0, + len = keys.length; + + for (; i < len; ++i) { + // over-write the parents getter without triggering it + Object.defineProperty(nested, keys[i], { + enumerable: false, // It doesn't show up. + writable: true, // We can set it later. + configurable: true, // We can Object.defineProperty again. + value: undefined // It shadows its parent. + }); + } + + Object.defineProperty(nested, 'toObject', { + enumerable: false, + configurable: true, + writable: false, + value: function() { + return utils.clone(_this.get(path), { retainKeyOrder: true }); + } + }); + + Object.defineProperty(nested, 'toJSON', { + enumerable: false, + configurable: true, + writable: false, + value: function() { + return _this.get(path); + } + }); + + Object.defineProperty(nested, '$__isNested', { + enumerable: false, + configurable: true, + writable: false, + value: true + }); + + compile(subprops, nested, path, options); + this.$__.getters[path] = nested; + } + + return this.$__.getters[path]; + }, + set: function(v) { + if (v instanceof Document) { + v = v.toObject({ transform: false }); + } + return (this.$__.scope || this).set(path, v); + } + }); + } else { + Object.defineProperty(prototype, prop, { + enumerable: true, + configurable: true, + get: function() { + return this.get.call(this.$__.scope || this, path); + }, + set: function(v) { + return this.set.call(this.$__.scope || this, path, v); + } + }); + } +} + +// gets descriptors for all properties of `object` +// makes all properties non-enumerable to match previous behavior to #2211 +function getOwnPropertyDescriptors(object) { + var result = {}; + + Object.getOwnPropertyNames(object).forEach(function(key) { + result[key] = Object.getOwnPropertyDescriptor(object, key); + result[key].enumerable = ['isNew', '$__', 'errors', '_doc'].indexOf(key) === -1; + }); + + return result; +} From d5e0f233dc6355a24257e8288d0619b450258d52 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 16 Sep 2017 16:39:18 -0700 Subject: [PATCH 1882/2240] test(query): repro #5613 --- test/model.discriminator.querying.test.js | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js index 5811a2c1b69..7ae863797ca 100644 --- a/test/model.discriminator.querying.test.js +++ b/test/model.discriminator.querying.test.js @@ -829,6 +829,34 @@ describe('model', function() { }); }); + it('updating type key (gh-5613)', function(done) { + function BaseSchema() { + Schema.apply(this, arguments); + + this.add({ + name: {type: String, required: true} + }); + } + + util.inherits(BaseSchema, Schema); + + var orgSchema = new BaseSchema({}); + var schoolSchema = new BaseSchema({ principal: String }); + + var Org = db.model('gh5613', orgSchema); + var School = Org.discriminator('gh5613_0', schoolSchema); + + Org.create({ name: 'test' }, function(error, doc) { + assert.ifError(error); + assert.ok(!doc.__t); + Org.findByIdAndUpdate(doc._id, { __t: 'gh5613_0' }, { new: true }, function(error, doc) { + assert.ifError(error); + assert.equal(doc.__t, 'gh5613_0'); + done(); + }); + }); + }); + it('reference in child schemas (gh-2719-2)', function(done) { var EventSchema, Event, TalkSchema, Talk, Survey; From d4d9ca84624ca2116690643781f40c2439003cb3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 16 Sep 2017 16:39:20 -0700 Subject: [PATCH 1883/2240] feat(discriminator): always add discriminatorKey to base schema to allow updating Fix #5613 --- lib/services/model/discriminator.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 63e5a3cdea0..9b66d0cc81e 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -1,5 +1,6 @@ 'use strict'; +var defineKey = require('../document/compile').defineKey; var utils = require('../../utils'); var CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = { @@ -29,7 +30,24 @@ module.exports = function discriminator(model, name, schema) { } var key = model.schema.options.discriminatorKey; - if (schema.path(key)) { + + var baseSchemaAddition = {}; + baseSchemaAddition[key] = { + default: void 0, + select: true, + set: function(newName) { + if (newName === name) { + return name; + } + throw new Error('Can\'t set discriminator key "' + key + '"'); + }, + $skipDiscriminatorCheck: false + }; + baseSchemaAddition[key][model.schema.options.typeKey] = String; + model.schema.add(baseSchemaAddition); + defineKey(key, null, model.prototype, null, [key], model.schema.options); + + if (schema.path(key) && !schema.path(key).$skipDiscriminatorCheck) { throw new Error('Discriminator "' + name + '" cannot have field with name "' + key + '"'); } From 7b0861861c728dd8f96014faa86f3ab001886580 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 17 Sep 2017 12:50:32 -0700 Subject: [PATCH 1884/2240] test(document): repro #3511 --- test/document.test.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 3fd6c7c9cf6..73f694d0606 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4687,6 +4687,47 @@ describe('document', function() { done(); }); + it('doc array: set then remove (gh-3511)', function(done) { + var ItemChildSchema = new mongoose.Schema({ + name: { + type: String, + required: true + } + }); + + var ItemParentSchema = new mongoose.Schema({ + children: [ItemChildSchema] + }); + + var ItemParent = db.model('gh3511', ItemParentSchema); + + var p = new ItemParent({ + children: [{ name: 'test1' }, { name: 'test2' }] + }); + + p.save(function(error) { + assert.ifError(error); + ItemParent.findById(p._id, function(error, doc) { + assert.ifError(error); + assert.ok(doc); + assert.equal(doc.children.length, 2); + + doc.children[1].name = 'test3'; + doc.children.remove(doc.children[0]); + + doc.save(function(error) { + assert.ifError(error); + ItemParent.findById(doc._id, function(error, doc) { + assert.ifError(error); + assert.equal(doc.children.length, 1); + assert.equal(doc.children[0].name, 'test3'); + done(); + }); + }); + }); + }); + }); + it('consistent context for nested docs (gh-5347)', function(done) { var contexts = []; var childSchema = new mongoose.Schema({ From 1fe4fbc072676e7953e6706acff32d981357a1a5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 17 Sep 2017 12:50:40 -0700 Subject: [PATCH 1885/2240] fix(document): add graceful fallback for setting a doc array value and `pull()`-ing a doc Fix #3511 --- lib/document.js | 15 +-------------- lib/services/document/cleanModifiedSubpaths.js | 18 ++++++++++++++++++ lib/types/array.js | 13 ++++++++++++- 3 files changed, 31 insertions(+), 15 deletions(-) create mode 100644 lib/services/document/cleanModifiedSubpaths.js diff --git a/lib/document.js b/lib/document.js index 6415b0286f8..537e551713e 100644 --- a/lib/document.js +++ b/lib/document.js @@ -16,6 +16,7 @@ var isMongooseObject = utils.isMongooseObject; var inspect = require('util').inspect; var ValidationError = MongooseError.ValidationError; var InternalCache = require('./internal'); +var cleanModifiedSubpaths = require('./services/document/cleanModifiedSubpaths'); var compile = require('./services/document/compile').compile; var deepEqual = utils.deepEqual; var defineKey = require('./services/document/compile').defineKey; @@ -777,20 +778,6 @@ Document.prototype.set = function(path, val, type, options) { return this; }; -/*! - * ignore - */ - -function cleanModifiedSubpaths(doc, path) { - var _modifiedPaths = Object.keys(doc.$__.activePaths.states.modify); - var _numModifiedPaths = _modifiedPaths.length; - for (var j = 0; j < _numModifiedPaths; ++j) { - if (_modifiedPaths[j].indexOf(path + '.') === 0) { - delete doc.$__.activePaths.states.modify[_modifiedPaths[j]]; - } - } -} - /** * Determine if we should mark this change as modified. * diff --git a/lib/services/document/cleanModifiedSubpaths.js b/lib/services/document/cleanModifiedSubpaths.js new file mode 100644 index 00000000000..ec34eb97ddc --- /dev/null +++ b/lib/services/document/cleanModifiedSubpaths.js @@ -0,0 +1,18 @@ +'use strict'; + +/*! + * ignore + */ + +module.exports = function cleanModifiedSubpaths(doc, path) { + var _modifiedPaths = Object.keys(doc.$__.activePaths.states.modify); + var _numModifiedPaths = _modifiedPaths.length; + var deleted = 0; + for (var j = 0; j < _numModifiedPaths; ++j) { + if (_modifiedPaths[j].indexOf(path + '.') === 0) { + delete doc.$__.activePaths.states.modify[_modifiedPaths[j]]; + ++deleted; + } + } + return deleted; +}; diff --git a/lib/types/array.js b/lib/types/array.js index bc0c384ffc6..4505bcb26db 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -5,7 +5,9 @@ var EmbeddedDocument = require('./embedded'); var Document = require('../document'); var ObjectId = require('./objectid'); +var cleanModifiedSubpaths = require('../services/document/cleanModifiedSubpaths'); var utils = require('../utils'); + var isMongooseObject = utils.isMongooseObject; /** @@ -154,7 +156,7 @@ MongooseArray.mixin = { } } - parent.markModified(dirtyPath, elem); + parent.markModified(dirtyPath, arguments.length > 0 ? elem : parent); } return this; @@ -558,6 +560,15 @@ MongooseArray.mixin = { } this._markModified(); + + // Might have modified child paths and then pulled, like + // `doc.children[1].name = 'test';` followed by + // `doc.children.remove(doc.children[0]);`. In this case we fall back + // to a `$set` on the whole array. See #3511 + if (cleanModifiedSubpaths(this._parent, this._path) > 0) { + this._registerAtomic('$set', this); + } + return this; }, From b69abe514b65c438e69ce635b73171e258abbb18 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 18 Sep 2017 10:22:50 -0700 Subject: [PATCH 1886/2240] chore: release 4.11.12 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 1afb9f12569..850aa59765a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.11.12 / 2017-09-18 +==================== + * docs(model): asterisk should not render as markdown bullet #5644 [timkinnane](https://github.com/timkinnane) + * docs: use useMongoClient in connection example #5627 [GabrielNicolasAvellaneda](https://github.com/GabrielNicolasAvellaneda) + * fix(connection): call callback when initial connection failed #5626 + * fix(query): apply select correctly if a given nested schema is used for 2 different paths #5603 + * fix(document): add graceful fallback for setting a doc array value and `pull()`-ing a doc #3511 + 4.11.11 / 2017-09-10 ==================== * fix(connection): properly set readyState in response to driver 'close' and 'reconnect' events #5604 diff --git a/package.json b/package.json index 6ca7ad2ac40..a34dab020df 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.12-pre", + "version": "4.11.12", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From b2297a30b623bc29be1017a78d538f2df4070183 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 18 Sep 2017 10:24:58 -0700 Subject: [PATCH 1887/2240] chore: now working on 4.11.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a34dab020df..2532bd92618 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.12", + "version": "4.11.13-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e12a1a3f029c2c8cc8d3ae3559f8df93699c5973 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 19 Sep 2017 11:18:09 -0700 Subject: [PATCH 1888/2240] fix(model): bind statics to model so statics can serve as express middleware Fix #4571 --- lib/services/model/applyStatics.js | 2 +- test/model.discriminator.test.js | 15 +++++++++++++-- test/model.test.js | 17 +++++++++++++---- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/lib/services/model/applyStatics.js b/lib/services/model/applyStatics.js index 1c24dbc18c7..12aa3832b10 100644 --- a/lib/services/model/applyStatics.js +++ b/lib/services/model/applyStatics.js @@ -7,6 +7,6 @@ */ module.exports = function applyStatics(model, schema) { for (var i in schema.statics) { - model[i] = schema.statics[i]; + model[i] = schema.statics[i].bind(model); } }; diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 932255230e3..f68cf4f3720 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -25,8 +25,12 @@ PersonSchema.methods.toJSonConfig = { include: ['prop1', 'prop2'], exclude: ['prop3', 'prop4'] }; + +var findByGenderResult = Math.random(); PersonSchema.statics.findByGender = function() { + return findByGenderResult; }; + PersonSchema.virtual('name.full').get(function() { return this.name.first + ' ' + this.name.last; }); @@ -46,8 +50,12 @@ EmployeeSchema.index({department: 1}); EmployeeSchema.methods.getDepartment = function() { return this.department; }; + +var findByDepartmentResult = Math.random(); EmployeeSchema.statics.findByDepartment = function() { + return findByDepartmentResult; }; + EmployeeSchema.path('department').validate(function(value) { return /[a-zA-Z]/.test(value); }, 'Invalid name'); @@ -301,8 +309,11 @@ describe('model', function() { }); it('inherits statics', function(done) { - assert.strictEqual(Employee.findByGender, EmployeeSchema.statics.findByGender); - assert.strictEqual(Employee.findByDepartment, EmployeeSchema.statics.findByDepartment); + // Equal modulo `bind()` + assert.equal(Employee.findByGender(), + EmployeeSchema.statics.findByGender()); + assert.equal(Employee.findByDepartment(), + EmployeeSchema.statics.findByDepartment()); assert.equal(Person.findByDepartment, undefined); done(); }); diff --git a/test/model.test.js b/test/model.test.js index cf94c96ea92..6bd31a1bcd9 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -766,14 +766,23 @@ describe('Model', function() { }); describe('statics', function() { - it('can be defined', function(done) { - var db = start(), - BlogPost = db.model('BlogPost', collection); + var BlogPost; - db.close(); + before(function() { + BlogPost = mongoose.model('BlogPost'); + }); + + it('can be defined', function(done) { assert.equal(BlogPost.woot(), BlogPost); done(); }); + + it('are bound to the model', function(done) { + var fn = BlogPost.woot; + assert.equal(fn(), BlogPost); + + done(); + }); }); describe('casting as validation errors', function() { From c790f0749e9b799bdc7603d9183cd7c18de340a0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 19 Sep 2017 20:32:55 -0700 Subject: [PATCH 1889/2240] chore: bump lockfile --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 34339dfe4ae..bb919d1410f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.11.12-pre", + "version": "4.11.13-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From b428b36354beb9035d0fd88d57e22182ec83c52e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 19 Sep 2017 20:50:03 -0700 Subject: [PATCH 1890/2240] test(update): repro #5628 --- test/model.findOneAndUpdate.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 9b6fa02a6bb..ffd9695a6dd 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1863,6 +1863,27 @@ describe('model: findOneAndUpdate:', function() { }); }); + it('update using $ (gh-5628)', function(done) { + var schema = new mongoose.Schema({ + elems: [String] + }); + + var Model = db.model('gh5628', schema); + Model.create({ elems: ['a', 'b'] }, function(error, doc) { + assert.ifError(error); + var query = { _id: doc._id, elems: 'a' }; + var update = { $set: { 'elems.$': 'c' } }; + Model.findOneAndUpdate(query, update, { new: true }, function(error) { + assert.ifError(error); + Model.collection.findOne({ _id: doc._id }, function(error, doc) { + assert.ifError(error); + assert.deepEqual(doc.elems, ['c', 'b']); + done(); + }); + }); + }); + }); + it('setting subtype when saving (gh-5551)', function(done) { if (parseInt(process.version.substr(1).split('.')[0], 10) < 4) { // Don't run on node 0.x because of `const` issues From 4b41fa0f66b07f83f11d839651289288f2d44d7d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 19 Sep 2017 20:51:45 -0700 Subject: [PATCH 1891/2240] fix(update): correctly handle $ in updates Fix #5628 --- lib/schema.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 0d993e4a1f3..f84d6510d16 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1744,9 +1744,9 @@ Schema.prototype._getSchema = function(path) { } function search(parts, schema) { - var p = parts.length + 1, - foundschema, - trypath; + var p = parts.length + 1; + var foundschema; + var trypath; while (p--) { trypath = parts.slice(0, p).join('.'); @@ -1800,7 +1800,14 @@ Schema.prototype._getSchema = function(path) { } // look for arrays - return search(path.split('.'), _this); + var parts = path.split('.'); + for (var i = 0; i < parts.length; ++i) { + if (parts[i] === '$') { + // Re: gh-5628, because `schema.path()` doesn't take $ into account. + parts[i] = '0'; + } + } + return search(parts, _this); }; /*! From 5437b590d7baf22635d774dcc53e40066dd90a4a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 20 Sep 2017 16:47:02 -0700 Subject: [PATCH 1892/2240] test(model): repro #5631 --- test/model.update.test.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 81a4b886ba3..bd02a848738 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2382,21 +2382,30 @@ describe('model: update:', function() { }); }); - it('with overwrite and upsert (gh-4749)', function(done) { + it('with overwrite and upsert (gh-4749) (gh-5631)', function(done) { var schema = new Schema({ name: String, meta: { age: { type: Number } } }); var User = db.model('gh4749', schema); + var filter = { name: 'Bar' }; var update = { name: 'Bar', meta: { age: 33 } }; var options = { overwrite: true, upsert: true }; - var q2 = User.update({ name: 'Bar' }, update, options); + var q2 = User.update(filter, update, options); assert.deepEqual(q2.getUpdate(), { __v: 0, meta: { age: 33 }, name: 'Bar' }); + + var q3 = User.findOneAndUpdate(filter, update, options); + assert.deepEqual(q3.getUpdate(), { + __v: 0, + meta: { age: 33 }, + name: 'Bar' + }); + done(); }); From f1d3330932e411ad78e5c290ee942fdce7ac40fe Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 20 Sep 2017 16:47:13 -0700 Subject: [PATCH 1893/2240] fix(model): handle casting findOneAndUpdate() with overwrite and upsert Fix #5631 --- lib/model.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index 864fd13deb0..6cea7177a99 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1630,10 +1630,14 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { update = utils.clone(update, {depopulate: 1, _isNested: true}); if (this.schema.options.versionKey && options && options.upsert) { - if (!update.$setOnInsert) { - update.$setOnInsert = {}; + if (options.overwrite) { + update[this.schema.options.versionKey] = 0; + } else { + if (!update.$setOnInsert) { + update.$setOnInsert = {}; + } + update.$setOnInsert[this.schema.options.versionKey] = 0; } - update.$setOnInsert[this.schema.options.versionKey] = 0; } var mq = new this.Query({}, {}, this, this.collection); From c18da4754aa8bd3325e73c0d86e01784704f0a8e Mon Sep 17 00:00:00 2001 From: Rebrov Boris Date: Thu, 21 Sep 2017 11:23:55 +0300 Subject: [PATCH 1894/2240] fix(schema): replace mistape in setupTimestamp method --- lib/schema.js | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index f84d6510d16..5515f0d7dd9 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -779,37 +779,20 @@ Schema.prototype.hasMixedParent = function(path) { */ Schema.prototype.setupTimestamp = function(timestamps) { if (timestamps) { - var createdAt = handleTimestampOption(timestamps, 'createdAt'); - var updatedAt = handleTimestampOption(timestamps, 'updatedAt'); - var schemaAdditions = {}; - - var parts; - var i; - var cur; - - if (createdAt != null) { - cur = schemaAdditions; - parts = createdAt.split('.'); - if (this.pathType(createdAt) === 'adhocOrUndefined') { - for (i = 0; i < parts.length; ++i) { + var paths = ['createdAt', 'updatedAt'].map(handleTimestampOption.bind(null, timestamps)); + var createdAt = paths[0]; + var updatedAt = paths[1]; + var schemaAdditions = paths.reduce(function (cur, path) { + var parts = path.split('.'); + if (this.pathType(path) === 'adhocOrUndefined') { + for (var i = 0; i < parts.length; ++i) { cur[parts[i]] = (i < parts.length - 1 ? - cur[parts[i]] || {} : + cur[parts[i]] || {} : Date); } } - } - - if (updatedAt != null) { - parts = updatedAt.split('.'); - cur = schemaAdditions; - if (this.pathType(createdAt) === 'adhocOrUndefined') { - for (i = 0; i < parts.length; ++i) { - cur[parts[i]] = (i < parts.length - 1 ? - cur[parts[i]] || {} : - Date); - } - } - } + return cur; + }, {}); this.add(schemaAdditions); From d1c3ba1b5c27279c8a7b070b6f17493663ea62d7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 21 Sep 2017 22:20:38 -0700 Subject: [PATCH 1895/2240] test(model): repro #5635 --- test/es6/all.test.es6.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/es6/all.test.es6.js b/test/es6/all.test.es6.js index ac03f17a69d..9ca1b22f6e9 100644 --- a/test/es6/all.test.es6.js +++ b/test/es6/all.test.es6.js @@ -47,4 +47,23 @@ describe('bug fixes', function() { done(); }); + + it('supports adding properties (gh-5104) (gh-5635)', function(done) { + class Shape extends mongoose.Model { }; + class Circle extends Shape { }; + + const ShapeModel = mongoose.model(Shape, new mongoose.Schema({ + color: String + })); + + const CircleModel = ShapeModel.discriminator(Circle, new mongoose.Schema({ + radius: Number + })); + + const circle = new Circle({ color: 'blue', radius: 3 }); + assert.equal(circle.color, 'blue'); + assert.equal(circle.radius, 3); + + done(); + }); }); From bf28a112371a7d8b5aa6578f67c7bdec146196cd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 21 Sep 2017 22:20:49 -0700 Subject: [PATCH 1896/2240] fix(model): ensure class gets combined schema when using class syntax with discriminators Fix #5635 --- lib/model.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index 6cea7177a99..d883de4b0d3 100644 --- a/lib/model.js +++ b/lib/model.js @@ -818,6 +818,9 @@ Model.discriminator = function(name, schema) { if (typeof name === 'function') { model = name; name = utils.getFunctionName(model); + if (!(model.prototype instanceof Model)) { + throw new mongoose.Error('The provided class ' + name + ' must extend Model'); + } } schema = discriminator(this, name, schema); @@ -827,9 +830,7 @@ Model.discriminator = function(name, schema) { schema.$isRootDiscriminator = true; - if (!model) { - model = this.db.model(name, schema, this.collection.name); - } + model = this.db.model(model || name, schema, this.collection.name); this.discriminators[name] = model; var d = this.discriminators[name]; d.prototype.__proto__ = this.prototype; From e9deb607cc429e528ce6f1a6b1e3e12e9b9c3ae2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 21 Sep 2017 22:27:42 -0700 Subject: [PATCH 1897/2240] style: fix lint --- lib/model.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index d883de4b0d3..8a1ee684496 100644 --- a/lib/model.js +++ b/lib/model.js @@ -6,6 +6,7 @@ var Aggregate = require('./aggregate'); var Document = require('./document'); var DocumentNotFoundError = require('./error').DocumentNotFoundError; var DivergentArrayError = require('./error').DivergentArrayError; +var Error = require('./error'); var EventEmitter = require('events').EventEmitter; var OverwriteModelError = require('./error').OverwriteModelError; var PromiseProvider = require('./promise_provider'); @@ -819,7 +820,7 @@ Model.discriminator = function(name, schema) { model = name; name = utils.getFunctionName(model); if (!(model.prototype instanceof Model)) { - throw new mongoose.Error('The provided class ' + name + ' must extend Model'); + throw new Error('The provided class ' + name + ' must extend Model'); } } From 9b48cd6142b94b21213889890ffb59d941fc2515 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 21 Sep 2017 22:33:56 -0700 Subject: [PATCH 1898/2240] test: fix tests --- test/model.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.test.js b/test/model.test.js index cf94c96ea92..6a07644a0ea 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -1911,7 +1911,7 @@ describe('Model', function() { assert.ifError(error); doc.remove(function(err) { assert.ok(err); - assert.equal(err.toString(), 'Error: No _id found on document!'); + assert.equal(err.message, 'No _id found on document!'); db.close(done); }); }); From 3c824174911c510e017815ab9b51376f5db05839 Mon Sep 17 00:00:00 2001 From: Rebrov Boris Date: Fri, 22 Sep 2017 11:24:43 +0300 Subject: [PATCH 1899/2240] fix(schema): add mised context to forAech callback in setupTimestamp method --- lib/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 5515f0d7dd9..3451c6c46be 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -792,7 +792,7 @@ Schema.prototype.setupTimestamp = function(timestamps) { } } return cur; - }, {}); + }.bind(this), {}); this.add(schemaAdditions); From 7b13e3b30aa4701ca9c50f9ddceb7c27010451c9 Mon Sep 17 00:00:00 2001 From: Rebrov Boris Date: Fri, 22 Sep 2017 13:29:46 +0300 Subject: [PATCH 1900/2240] fix(schema): turn back checks for `null` value for timestamp paths in Schema.prototype.setupTimestamp --- lib/schema.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 3451c6c46be..be9b778a4ae 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -783,12 +783,14 @@ Schema.prototype.setupTimestamp = function(timestamps) { var createdAt = paths[0]; var updatedAt = paths[1]; var schemaAdditions = paths.reduce(function (cur, path) { - var parts = path.split('.'); - if (this.pathType(path) === 'adhocOrUndefined') { - for (var i = 0; i < parts.length; ++i) { - cur[parts[i]] = (i < parts.length - 1 ? - cur[parts[i]] || {} : - Date); + if (path != null) { + var parts = path.split('.'); + if (this.pathType(path) === 'adhocOrUndefined') { + for (var i = 0; i < parts.length; ++i) { + cur[parts[i]] = (i < parts.length - 1 ? + cur[parts[i]] || {} : + Date); + } } } return cur; From 9f6e79b5a5687ecda4a4ca053761d01fae514cd6 Mon Sep 17 00:00:00 2001 From: Rebrov Boris Date: Fri, 22 Sep 2017 13:33:36 +0300 Subject: [PATCH 1901/2240] fix(schema) code ftyle --- lib/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index be9b778a4ae..53b886c4f13 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -782,7 +782,7 @@ Schema.prototype.setupTimestamp = function(timestamps) { var paths = ['createdAt', 'updatedAt'].map(handleTimestampOption.bind(null, timestamps)); var createdAt = paths[0]; var updatedAt = paths[1]; - var schemaAdditions = paths.reduce(function (cur, path) { + var schemaAdditions = paths.reduce(function(cur, path) { if (path != null) { var parts = path.split('.'); if (this.pathType(path) === 'adhocOrUndefined') { From bc40e453305d562a7bfce4835778d40764cf353f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 22 Sep 2017 18:14:07 -0700 Subject: [PATCH 1902/2240] test(document): repro #5632 --- test/document.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 73f694d0606..abae0ca17c8 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4687,6 +4687,32 @@ describe('document', function() { done(); }); + it('setting doc array to array of top-level docs works (gh-5632)', function(done) { + var MainSchema = new Schema({ + name: { type: String }, + children: [{ + name: { type: String } + }] + }); + var RelatedSchema = new Schema({ name: { type: String } }); + var Model = db.model('gh5632', MainSchema); + var RelatedModel = db.model('gh5632_0', RelatedSchema); + + RelatedModel.create({ name: 'test' }, function(error, doc) { + assert.ifError(error); + Model.create({ name: 'test1', children: [doc] }, function(error, m) { + assert.ifError(error); + m.children = [doc]; + m.save(function(error) { + assert.ifError(error); + assert.equal(m.children.length, 1); + assert.equal(m.children[0].name, 'test'); + done(); + }); + }); + }); + }); + it('doc array: set then remove (gh-3511)', function(done) { var ItemChildSchema = new mongoose.Schema({ name: { From 545bd39aa18e164cf2a8f7ad5fd356167299daf1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 22 Sep 2017 18:17:01 -0700 Subject: [PATCH 1903/2240] fix(document): handle setting doc array to array of top-level docs Fix #5632 --- lib/document.js | 1 - lib/schema/documentarray.js | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 537e551713e..980c08640c8 100644 --- a/lib/document.js +++ b/lib/document.js @@ -495,7 +495,6 @@ Document.prototype.update = function update() { */ Document.prototype.set = function(path, val, type, options) { - //console.log('set', path, val, this, new Error().stack) if (type && utils.getFunctionName(type.constructor) === 'Object') { options = type; type = undefined; diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 5138f2d5f00..97ee114262c 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -6,6 +6,7 @@ var ArrayType = require('./array'); var CastError = require('../error/cast'); +var Document = require('../document'); var EventEmitter = require('events').EventEmitter; var MongooseDocumentArray = require('../types/documentarray'); var SchemaType = require('../schematype'); @@ -292,7 +293,7 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { } // Check if the document has a different schema (re gh-3701) - if ((value[i] instanceof Subdocument) && + if ((value[i] instanceof Document) && value[i].schema !== Constructor.schema) { value[i] = value[i].toObject({ transform: false, virtuals: false }); } From 12a08af89d0c2576ea1c29c40aae23d0d8008c80 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Sep 2017 12:39:54 -0700 Subject: [PATCH 1904/2240] refactor(types): create helper function for logic from #5504 --- lib/types/array.js | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/types/array.js b/lib/types/array.js index 4505bcb26db..2dbe9d88b2a 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -311,19 +311,7 @@ MongooseArray.mixin = { var ref = this._schema.caster.options && this._schema.caster.options.ref; if (this.length === 0 && arguments.length) { - var allSubdocs = true; - for (var i = 0; i < arguments.length; ++i) { - var arg = arguments[i]; - var model = arg.constructor; - allSubdocs = arg instanceof Document && - ref && - (model.modelName === ref || model.baseModelName === ref); - if (!allSubdocs) { - break; - } - } - - if (allSubdocs) { + if (_isAllSubdocs(arguments, ref)) { this._parent.populated(this._path, [], { model: arguments[0].constructor }); } } @@ -585,7 +573,9 @@ MongooseArray.mixin = { */ splice: function splice() { - var ret, vals, i; + var ret; + var vals; + var i; if (arguments.length) { vals = []; @@ -803,6 +793,26 @@ MongooseArray.mixin = { MongooseArray.mixin.remove = MongooseArray.mixin.pull; +/*! + * ignore + */ + +function _isAllSubdocs(docs, ref) { + if (!ref) { + return false; + } + for (var i = 0; i < docs.length; ++i) { + var arg = docs[i]; + var model = arg.constructor; + if (!(arg instanceof Document) || + (model.modelName !== ref && model.baseModelName !== ref)) { + return false; + } + } + + return true; +} + /*! * Module exports. */ From e666f118e45735b6bb1b963085f2e801ae738a1e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Sep 2017 12:48:05 -0700 Subject: [PATCH 1905/2240] test(document): repro #5504 --- test/document.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index abae0ca17c8..2974559c69d 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4609,6 +4609,8 @@ describe('document', function() { var referrerA = new Referrer({reference: [referenceA]}); var referrerB = new Referrer(); + var referrerC = new Referrer(); + var referrerD = new Referrer(); referrerA.reference.push(referenceB); assert.ok(referrerA.reference[0] instanceof Referrer); @@ -4617,6 +4619,12 @@ describe('document', function() { referrerB.reference.push(referenceB); assert.ok(referrerB.reference[0] instanceof Referrer); + referrerC.reference.unshift(referenceB); + assert.ok(referrerC.reference[0] instanceof Referrer); + + referrerD.reference.splice(0, 0, referenceB); + assert.ok(referrerD.reference[0] instanceof Referrer); + done(); }); From 6fa60555a80681fe62b40de39e24143f91fb74f3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 23 Sep 2017 12:48:07 -0700 Subject: [PATCH 1906/2240] fix(types): handle manual population consistently for unshift() and splice() Fix #5504 --- lib/types/array.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/types/array.js b/lib/types/array.js index 2dbe9d88b2a..20a493ef078 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -577,6 +577,15 @@ MongooseArray.mixin = { var vals; var i; + var ref = this._schema.caster.options && this._schema.caster.options.ref; + if (this.length === 0 && + arguments.length > 2) { + var docs = Array.prototype.slice.call(arguments, 2); + if (_isAllSubdocs(docs, ref)) { + this._parent.populated(this._path, [], { model: docs[0].constructor }); + } + } + if (arguments.length) { vals = []; for (i = 0; i < arguments.length; ++i) { @@ -605,6 +614,14 @@ MongooseArray.mixin = { */ unshift: function() { + var ref = this._schema.caster.options && this._schema.caster.options.ref; + if (this.length === 0 && + arguments.length) { + if (_isAllSubdocs(arguments, ref)) { + this._parent.populated(this._path, [], { model: arguments[0].constructor }); + } + } + var values = [].map.call(arguments, this._cast, this); values = this._schema.applySetters(values, this._parent); [].unshift.apply(this, values); @@ -803,6 +820,9 @@ function _isAllSubdocs(docs, ref) { } for (var i = 0; i < docs.length; ++i) { var arg = docs[i]; + if (arg == null) { + return false; + } var model = arg.constructor; if (!(arg instanceof Document) || (model.modelName !== ref && model.baseModelName !== ref)) { From 6cf6c617fdb41404b0feac05c194c000f4e740f6 Mon Sep 17 00:00:00 2001 From: Simeone Date: Sun, 24 Sep 2017 10:20:47 +0200 Subject: [PATCH 1907/2240] fix replaceOne with validators --- lib/query.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index a1e1891e0fd..97f211af616 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2499,7 +2499,7 @@ Query.prototype._replaceOne = function(callback) { return callback(err); } - Query.base.updateMany.call(_this, castedQuery, castedDoc, options, callback); + Query.base.replaceOne.call(_this, castedQuery, castedDoc, options, callback); }; try { doValidate(_callback); From 283100635979aadfb4f8dc895c57eda02ce6c737 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 24 Sep 2017 19:13:13 -0700 Subject: [PATCH 1908/2240] test(query): repro #5640 --- test/model.update.test.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index bd02a848738..ed09c71138c 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2748,6 +2748,41 @@ describe('model: update:', function() { }).catch(done); }); + it('update with nested id (gh-5640)', function(done) { + var testSchema = new mongoose.Schema({ + _id: { + a: String, + b: String + }, + foo: String + }, { + strict: true + }); + + var Test = db.model('gh5640', testSchema); + + var doc = { + _id: { + a: 'a', + b: 'b' + }, + foo: 'bar' + }; + + Test.create(doc, function(error, doc) { + assert.ifError(error); + doc.foo = 'baz'; + Test.update({_id: doc._id}, doc, {upsert: true}, function(error) { + assert.ifError(error); + Test.findOne({ _id: doc._id }, function(error, doc) { + assert.ifError(error); + assert.equal(doc.foo, 'baz'); + done(); + }); + }); + }); + }); + it('cast error in update conditions (gh-5477)', function(done) { var schema = new mongoose.Schema({ name: String From a872591ccc64ed6d164a936cd2e7ad6f97b3ca70 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 24 Sep 2017 19:13:50 -0700 Subject: [PATCH 1909/2240] fix(query): avoid throwing cast error for strict: throw with nested id in query Fix #5640 --- lib/cast.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cast.js b/lib/cast.js index b7a02120190..be6861ef906 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -192,7 +192,7 @@ module.exports = function cast(schema, obj, options, context) { } } - if (options && options.upsert && options.strict) { + if (options && options.upsert && options.strict && !schema.nested[path]) { if (options.strict === 'throw') { throw new StrictModeError(path); } From ab9ba7c4ff1678c62f052d6ab241c867fbb51ba9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 24 Sep 2017 21:08:10 -0700 Subject: [PATCH 1910/2240] test: add coverage for #5656 --- test/schema.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 72888bcea35..286dcb3636e 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1684,5 +1684,21 @@ describe('schema', function() { assert.ok(!clone.path('num').validators[0].validator(41)); done(); }); + + it('TTL index with timestamps (gh-5656)', function(done) { + var testSchema = new mongoose.Schema({ + foo: String, + updatedAt: { + type: Date, + expires: '2h' + } + }, { timestamps: true }); + + var indexes = testSchema.indexes(); + assert.deepEqual(indexes, [ + [{ updatedAt: 1 }, { background: true, expireAfterSeconds: 7200 }] + ]); + done(); + }); }); }); From 96e06b70fb35d3f847dc4a82d04459204655a3ff Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 24 Sep 2017 21:21:32 -0700 Subject: [PATCH 1911/2240] chore: release 4.11.13 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 850aa59765a..d81983d8907 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,14 @@ +4.11.13 / 2017-09-24 +==================== + * fix(query): correctly run replaceOne with update validators #5665 [sime1](https://github.com/sime1) + * fix(schema): replace mistype in setupTimestamp method #5656 [zipp3r](https://github.com/zipp3r) + * fix(query): avoid throwing cast error for strict: throw with nested id in query #5640 + * fix(model): ensure class gets combined schema when using class syntax with discriminators #5635 + * fix(document): handle setting doc array to array of top-level docs #5632 + * fix(model): handle casting findOneAndUpdate() with overwrite and upsert #5631 + * fix(update): correctly handle $ in updates #5628 + * fix(types): handle manual population consistently for unshift() and splice() #5504 + 4.11.12 / 2017-09-18 ==================== * docs(model): asterisk should not render as markdown bullet #5644 [timkinnane](https://github.com/timkinnane) diff --git a/package.json b/package.json index 2532bd92618..4d2eb6732db 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.13-pre", + "version": "4.11.13", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 635f07fc2ff56cb767350d0d167fcc1076386d3d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 24 Sep 2017 21:24:49 -0700 Subject: [PATCH 1912/2240] chore: now working on 4.11.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4d2eb6732db..257887e9523 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.13", + "version": "4.11.14-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4e589da8f44bd44d5f156aca7c2d21697418964f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 25 Sep 2017 08:41:08 -0700 Subject: [PATCH 1913/2240] Revert "fix(model): bind statics to model so statics can serve as express middleware" This reverts commit e12a1a3f029c2c8cc8d3ae3559f8df93699c5973. --- lib/services/model/applyStatics.js | 2 +- test/model.discriminator.test.js | 15 ++------------- test/model.test.js | 17 ++++------------- 3 files changed, 7 insertions(+), 27 deletions(-) diff --git a/lib/services/model/applyStatics.js b/lib/services/model/applyStatics.js index 12aa3832b10..1c24dbc18c7 100644 --- a/lib/services/model/applyStatics.js +++ b/lib/services/model/applyStatics.js @@ -7,6 +7,6 @@ */ module.exports = function applyStatics(model, schema) { for (var i in schema.statics) { - model[i] = schema.statics[i].bind(model); + model[i] = schema.statics[i]; } }; diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index f68cf4f3720..932255230e3 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -25,12 +25,8 @@ PersonSchema.methods.toJSonConfig = { include: ['prop1', 'prop2'], exclude: ['prop3', 'prop4'] }; - -var findByGenderResult = Math.random(); PersonSchema.statics.findByGender = function() { - return findByGenderResult; }; - PersonSchema.virtual('name.full').get(function() { return this.name.first + ' ' + this.name.last; }); @@ -50,12 +46,8 @@ EmployeeSchema.index({department: 1}); EmployeeSchema.methods.getDepartment = function() { return this.department; }; - -var findByDepartmentResult = Math.random(); EmployeeSchema.statics.findByDepartment = function() { - return findByDepartmentResult; }; - EmployeeSchema.path('department').validate(function(value) { return /[a-zA-Z]/.test(value); }, 'Invalid name'); @@ -309,11 +301,8 @@ describe('model', function() { }); it('inherits statics', function(done) { - // Equal modulo `bind()` - assert.equal(Employee.findByGender(), - EmployeeSchema.statics.findByGender()); - assert.equal(Employee.findByDepartment(), - EmployeeSchema.statics.findByDepartment()); + assert.strictEqual(Employee.findByGender, EmployeeSchema.statics.findByGender); + assert.strictEqual(Employee.findByDepartment, EmployeeSchema.statics.findByDepartment); assert.equal(Person.findByDepartment, undefined); done(); }); diff --git a/test/model.test.js b/test/model.test.js index db080495f44..6a07644a0ea 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -766,21 +766,12 @@ describe('Model', function() { }); describe('statics', function() { - var BlogPost; - - before(function() { - BlogPost = mongoose.model('BlogPost'); - }); - it('can be defined', function(done) { - assert.equal(BlogPost.woot(), BlogPost); - done(); - }); - - it('are bound to the model', function(done) { - var fn = BlogPost.woot; - assert.equal(fn(), BlogPost); + var db = start(), + BlogPost = db.model('BlogPost', collection); + db.close(); + assert.equal(BlogPost.woot(), BlogPost); done(); }); }); From bef56465077f98de235858d49553ed7448c6d43f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 25 Sep 2017 09:01:18 -0700 Subject: [PATCH 1914/2240] fix(query): report error if passing array or other non-object as filter to update query Re: #3677 --- lib/error/objectParameter.js | 36 ++++++++++++++++++++++++++++++++++++ lib/query.js | 7 ++++++- test/model.update.test.js | 15 +++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 lib/error/objectParameter.js diff --git a/lib/error/objectParameter.js b/lib/error/objectParameter.js new file mode 100644 index 00000000000..bf3f74a06c7 --- /dev/null +++ b/lib/error/objectParameter.js @@ -0,0 +1,36 @@ +/*! + * Module dependencies. + */ + +var MongooseError = require('../error.js'); + +/** + * Constructor for errors that happen when a parameter that's expected to be + * an object isn't an object + * + * @param {Any} value + * @param {String} paramName + * @param {String} fnName + * @inherits MongooseError + * @api private + */ + +function ObjectParameterError(value, paramName, fnName) { + MongooseError.call(this, 'Parameter "' + paramName + '" to ' + fnName + + '() must be an object, got ' + value.toString()); + this.name = 'ObjectParameterError'; + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } else { + this.stack = new Error().stack; + } +} + +/*! + * Inherits from MongooseError. + */ + +ObjectParameterError.prototype = Object.create(MongooseError.prototype); +ObjectParameterError.prototype.constructor = MongooseError; + +module.exports = ObjectParameterError; diff --git a/lib/query.js b/lib/query.js index 1d270f4d88d..9d80c117d3f 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3,6 +3,7 @@ */ var CastError = require('./error/cast'); +var ObjectParameterError = require('./error/objectParameter'); var PromiseProvider = require('./promise_provider'); var QueryCursor = require('./cursor/QueryCursor'); var QueryStream = require('./querystream'); @@ -2856,7 +2857,11 @@ function _update(query, op, conditions, doc, options, callback) { doc = query._updateForExec(); } - if (mquery.canMerge(conditions)) { + if (!(conditions instanceof Query) && + conditions != null && + conditions.toString() !== '[object Object]') { + query.error(new ObjectParameterError(conditions, 'filter', op)); + } else { query.merge(conditions); } diff --git a/test/model.update.test.js b/test/model.update.test.js index ed09c71138c..6d7ca5a108f 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2748,6 +2748,21 @@ describe('model: update:', function() { }).catch(done); }); + it('returns error if passing array as conditions (gh-3677)', function(done) { + var schema = new mongoose.Schema({ + name: String + }); + + var Model = db.model('gh3677', schema); + Model.updateMany(['foo'], { name: 'bar' }, function(error) { + assert.ok(error); + assert.equal(error.name, 'ObjectParameterError'); + var expected = 'Parameter "filter" to updateMany() must be an object'; + assert.ok(error.message.indexOf(expected) !== -1, error.message); + done(); + }); + }); + it('update with nested id (gh-5640)', function(done) { var testSchema = new mongoose.Schema({ _id: { From c79d48eaa6ade50f5684d79b8e4811e6812b9895 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 25 Sep 2017 21:06:36 -0700 Subject: [PATCH 1915/2240] docs(model/query): clarify which functions fire which middleware Fix #5654 --- lib/model.js | 41 +++++++++++++++++++++++++++++++++++++---- lib/query.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/lib/model.js b/lib/model.js index 8a1ee684496..154c518e7ea 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1286,7 +1286,8 @@ Model.find = function find(conditions, projection, options, callback) { * * The `id` is cast based on the Schema before sending the command. * - * Note: `findById()` triggers `findOne` hooks. + * This function triggers the following middleware: + * - `findOne()` * * \* Except for how it treats `undefined`. If you use `findOne()`, you'll see * that `findOne(undefined)` and `findOne({ _id: undefined })` are equivalent @@ -1657,7 +1658,8 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { * callback. The query executes immediately if `callback` is passed else a * Query object is returned. * - * This function triggers `findOneAndUpdate` middleware. + * This function triggers the following middleware: + * - `findOneAndUpdate()` * * ####Options: * @@ -1753,6 +1755,9 @@ Model.findByIdAndUpdate = function(id, update, options, callback) { * * Executes immediately if `callback` is passed else a Query object is returned. * + * This function triggers the following middleware: + * - `findOneAndRemove()` + * * ####Options: * * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update @@ -1832,6 +1837,9 @@ Model.findOneAndRemove = function(conditions, options, callback) { * * Executes immediately if `callback` is passed, else a `Query` object is returned. * + * This function triggers the following middleware: + * - `findOneAndRemove()` + * * ####Options: * * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update @@ -1875,7 +1883,7 @@ Model.findByIdAndRemove = function(id, options, callback) { * `MyModel.create(docs)` does `new MyModel(doc).save()` for every doc in * docs. * - * Hooks Triggered: + * This function triggers the following middleware: * - `save()` * * ####Example: @@ -2021,6 +2029,9 @@ var INSERT_MANY_CONVERT_OPTIONS = { * * This function does **not** trigger save middleware. * + * This function triggers the following middleware: + * - `insertMany()` + * * ####Example: * * var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }]; @@ -2118,7 +2129,8 @@ Model.insertMany = function(arr, options, callback) { * * Mongoose will perform casting on all operations you provide. * - * This function does **not** trigger any middleware. If you need to trigger + * This function does **not** trigger any middleware, not `save()` nor `update()`. + * If you need to trigger * `save()` middleware for every document use [`create()`](http://mongoosejs.com/docs/api.html#model_Model.create) instead. * * ####Example: @@ -2302,6 +2314,9 @@ Model.hydrate = function(obj) { /** * Updates one document in the database without returning it. * + * This function triggers the following middleware: + * - `update()` + * * ####Examples: * * MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn); @@ -2391,6 +2406,9 @@ Model.update = function update(conditions, doc, options, callback) { * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')` * and `post('updateMany')` instead. * + * This function triggers the following middleware: + * - `updateMany()` + * * @param {Object} conditions * @param {Object} doc * @param {Object} [options] @@ -2407,6 +2425,9 @@ Model.updateMany = function updateMany(conditions, doc, options, callback) { * Same as `update()`, except MongoDB will update _only_ the first document that * matches `criteria` regardless of the value of the `multi` option. * + * This function triggers the following middleware: + * - `updateOne()` + * * @param {Object} conditions * @param {Object} doc * @param {Object} [options] @@ -2423,6 +2444,9 @@ Model.updateOne = function updateOne(conditions, doc, options, callback) { * Same as `update()`, except MongoDB replace the existing document with the * given document (no atomic operators like `$set`). * + * This function triggers the following middleware: + * - `replaceOne()` + * * @param {Object} conditions * @param {Object} doc * @param {Object} [options] @@ -2472,6 +2496,8 @@ function _update(model, op, conditions, doc, options, callback) { * * `o` is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation. See [node-mongodb-native mapReduce() documentation](http://mongodb.github.io/node-mongodb-native/api-generated/collection.html#mapreduce) for more detail about options. * + * This function does not trigger any middleware. + * * ####Example: * * var o = {}; @@ -2601,6 +2627,9 @@ Model.mapReduce = function mapReduce(o, callback) { /** * geoNear support for Mongoose * + * This function does not trigger any middleware. In particular, this + * bypasses `find()` middleware. + * * ####Options: * - `lean` {Boolean} return the raw object * - All options supported by the driver are also supported @@ -2722,6 +2751,8 @@ Model.geoNear = function(near, options, callback) { * * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned. * + * This function does not trigger any middleware. + * * ####Example: * * // Find the max balance of all accounts @@ -2787,6 +2818,8 @@ Model.aggregate = function aggregate() { /** * Implements `$geoSearch` functionality for Mongoose * + * This function does not trigger any middleware + * * ####Example: * * var options = { near: [10, 10], maxDistance: 5 }; diff --git a/lib/query.js b/lib/query.js index 97f211af616..e4252be7f43 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1401,6 +1401,9 @@ Query.prototype._findOne = function(callback) { * an arbitrary document. If you're querying by `_id`, use `Model.findById()` * instead. * + * This function triggers the following middleware: + * - `findOne()` + * * ####Example * * var query = Kitten.where({ color: 'white' }); @@ -1503,6 +1506,9 @@ Query.prototype._count = function(callback) { * * Passing a `callback` executes the query. * + * This function triggers the following middleware: + * - `count()` + * * ####Example: * * var countQuery = model.where({ 'color': 'black' }).count(); @@ -1548,6 +1554,8 @@ Query.prototype.count = function(conditions, callback) { * * Passing a `callback` executes the query. * + * This function does not trigger any middleware. + * * ####Example * * distinct(field, conditions, callback) @@ -1634,6 +1642,8 @@ Query.prototype.sort = function(arg) { /** * Declare and/or execute this query as a remove() operation. * + * This function does not trigger any middleware + * * ####Example * * Model.remove({ artist: 'Anne Murray' }, callback) @@ -1708,6 +1718,8 @@ Query.prototype._remove = function(callback) { * remove, except it deletes at most one document regardless of the `single` * option. * + * This function does not trigger any middleware. + * * ####Example * * Character.deleteOne({ name: 'Eddard Stark' }, callback) @@ -1763,6 +1775,8 @@ Query.prototype._deleteOne = function(callback) { * remove, except it deletes _every_ document that matches `criteria` in the * collection, regardless of the value of `single`. * + * This function does not trigger any middleware + * * ####Example * * Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, callback) @@ -1868,6 +1882,9 @@ function prepareDiscriminatorCriteria(query) { * * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed. * + * This function triggers the following middleware: + * - `findOneAndUpdate()` + * * ####Available options * * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0) @@ -1994,6 +2011,9 @@ Query.prototype._findOneAndUpdate = function(callback) { * * Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if `callback` is passed. * + * This function triggers the following middleware: + * - `findOneAndRemove()` + * * ####Available options * * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update @@ -2520,6 +2540,9 @@ Query.prototype._replaceOne = function(callback) { * * _All paths passed that are not $atomic operations will become $set ops._ * + * This function triggers the following middleware: + * - `update()` + * * ####Example * * Model.where({ _id: id }).update({ title: 'words' }) @@ -2639,6 +2662,9 @@ Query.prototype.update = function(conditions, doc, options, callback) { * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')` * and `post('updateMany')` instead. * + * This function triggers the following middleware: + * - `updateMany()` + * * @param {Object} [criteria] * @param {Object} [doc] the update command * @param {Object} [options] @@ -2686,6 +2712,9 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) { * **Note** updateOne will _not_ fire update middleware. Use `pre('updateOne')` * and `post('updateOne')` instead. * + * This function triggers the following middleware: + * - `updateOne()` + * * @param {Object} [criteria] * @param {Object} [doc] the update command * @param {Object} [options] @@ -2733,6 +2762,9 @@ Query.prototype.updateOne = function(conditions, doc, options, callback) { * **Note** replaceOne will _not_ fire update middleware. Use `pre('replaceOne')` * and `post('replaceOne')` instead. * + * This function triggers the following middleware: + * - `replaceOne()` + * * @param {Object} [criteria] * @param {Object} [doc] the update command * @param {Object} [options] From a7a56217b4340cf3f1c0aaa088620aebf6be007d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 26 Sep 2017 18:12:42 -0700 Subject: [PATCH 1916/2240] test(document): repro #5661 --- test/model.findOneAndUpdate.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index ffd9695a6dd..f542f7f92fc 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1884,6 +1884,32 @@ describe('model: findOneAndUpdate:', function() { }); }); + it('projection with $elemMatch (gh-5661)', function(done) { + var schema = new mongoose.Schema({ + name: { type: String, default: 'test' }, + arr: [{ tag: String }] + }); + + var Model = db.model('gh5661', schema); + var doc = { arr: [{ tag: 't1' }, { tag: 't2' }] }; + Model.create(doc, function(error, doc) { + assert.ifError(error); + var query = {}; + var update = { $set: { name: 'test2' } }; + var opts = { + new: true, + fields: { arr: { $elemMatch: { tag: 't1' } } } + }; + Model.findOneAndUpdate(query, update, opts, function(error, doc) { + assert.ifError(error); + assert.ok(!doc.name); + assert.equal(doc.arr.length, 1); + assert.equal(doc.arr[0].tag, 't1'); + done(); + }); + }); + }); + it('setting subtype when saving (gh-5551)', function(done) { if (parseInt(process.version.substr(1).split('.')[0], 10) < 4) { // Don't run on node 0.x because of `const` issues From 3f173939f03f0d290d3d2018cc7cbd15a2c73a48 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 26 Sep 2017 18:13:41 -0700 Subject: [PATCH 1917/2240] fix(document): treat $elemMatch as inclusive projection Fix #5661 --- lib/document.js | 8 ++++++-- test/model.findOneAndUpdate.test.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/document.js b/lib/document.js index 980c08640c8..e438a91042a 100644 --- a/lib/document.js +++ b/lib/document.js @@ -181,8 +181,12 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) { exclude = !!fields[keys[ki]]; } else { while (ki--) { - if (keys[ki] !== '_id' && - (!fields[keys[ki]] || typeof fields[keys[ki]] !== 'object')) { + // Does this projection explicitly define inclusion/exclusion? + // Explicitly avoid `$meta` and `$slice` + var isDefiningProjection = !fields[keys[ki]] || + typeof fields[keys[ki]] !== 'object' || + fields[keys[ki]].$elemMatch != null; + if (keys[ki] !== '_id' && isDefiningProjection) { exclude = !fields[keys[ki]]; break; } diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index f542f7f92fc..c2ff235878e 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1892,7 +1892,7 @@ describe('model: findOneAndUpdate:', function() { var Model = db.model('gh5661', schema); var doc = { arr: [{ tag: 't1' }, { tag: 't2' }] }; - Model.create(doc, function(error, doc) { + Model.create(doc, function(error) { assert.ifError(error); var query = {}; var update = { $set: { name: 'test2' } }; From 4875dbec2d2f59280580605665def9e20c8bef8a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Sep 2017 16:54:37 -0700 Subject: [PATCH 1918/2240] fix(model): make `init()` public and return a promise that resolves when indexes are done building Fix #5563 --- docs/faq.jade | 10 ++++++ lib/model.js | 59 +++++++++++++++++++++++++++++------- test/docs/validation.test.js | 18 ++++++++++- test/model.indexes.test.js | 7 +++-- 4 files changed, 79 insertions(+), 15 deletions(-) diff --git a/docs/faq.jade b/docs/faq.jade index 6e45f2cc6b3..fc45f5a5ca3 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -61,6 +61,16 @@ block content console.log(err); }); }); + + // Promise based alternative. `init()` returns a promise that resolves + // when the indexes have finished building successfully. The `init()` + // function is idempotent, so don't worry about triggering an index rebuild. + Model.init().then(function() { + assert.ifError(err); + Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) { + console.log(err); + }); + }); :markdown MongoDB persists indexes, so you only need to rebuild indexes if you're starting with a fresh database or you ran `db.dropDatabase()`. In a production environment, diff --git a/lib/model.js b/lib/model.js index 154c518e7ea..d0b473638e8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -859,21 +859,59 @@ for (var i in EventEmitter.prototype) { } /** - * Called when the model compiles. + * Performs any async initialization of this model against MongoDB. Currently, + * this function is only responsible for building [indexes](https://docs.mongodb.com/manual/indexes/), + * unless [`autoIndex`](http://mongoosejs.com/docs/guide.html#autoIndex) is turned off. * - * @api private + * This function is called automatically, so you don't need to call it. + * This function is also idempotent, so you may call it to get back a promise + * that will resolve when your indexes are finished building as an alternative + * to `MyModel.on('index')` + * + * ####Example: + * + * var eventSchema = new Schema({ thing: { type: 'string', unique: true }}) + * // This calls `Event.init()` implicitly, so you don't need to call + * // `Event.init()` on your own. + * var Event = mongoose.model('Event', eventSchema); + * + * Event.init().then(function(Event) { + * // You can also use `Event.on('index')` if you prefer event emitters + * // over promises. + * console.log('Indexes are done building!'); + * }); + * + * @api public + * @param {Function} [callback] + * @returns {Promise} */ -Model.init = function init() { - if ((this.schema.options.autoIndex) || - (this.schema.options.autoIndex == null && this.db.config.autoIndex)) { - var _this = this; - setImmediate(function() { - _this.ensureIndexes({ __noPromise: true, _automatic: true }); - }); +Model.init = function init(callback) { + this.schema.emit('init', this); + + if (this.$init) { + return this.$init; } - this.schema.emit('init', this); + var _this = this; + var Promise = PromiseProvider.get(); + this.$init = new Promise.ES6(function(resolve, reject) { + if ((_this.schema.options.autoIndex) || + (_this.schema.options.autoIndex == null && _this.db.config.autoIndex)) { + _this.ensureIndexes({ _automatic: true, __noPromise: true }, function(error) { + if (error) { + callback && callback(error); + return reject(error); + } + callback && callback(null, _this); + resolve(_this); + }); + } + + return _this; + }); + + return this.$init; }; /** @@ -978,7 +1016,6 @@ function _ensureIndexes(model, options, callback) { _handleSafe(options); indexSingleStart(indexFields, options); - model.collection.ensureIndex(indexFields, indexOptions, utils.tick(function(err, name) { indexSingleDone(err, indexFields, indexOptions, name); if (err) { diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 8228a9cc8fc..1fe2ef655c1 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -126,7 +126,7 @@ describe('validation docs', function() { var U1 = db.model('U1', uniqueUsernameSchema); var U2 = db.model('U2', uniqueUsernameSchema); // acquit:ignore:start - var remaining = 2; + var remaining = 3; // acquit:ignore:end var dup = [{ username: 'Val' }, { username: 'Val' }]; @@ -153,6 +153,22 @@ describe('validation docs', function() { // acquit:ignore:end }); }); + + // There's also a promise-based equivalent to the event emitter API. + // The `init()` function is idempotent and returns a promise that + // will resolve once indexes are done building; + U2.init().then(function() { + U2.create(dup, function(error) { + // Will error, but will *not* be a mongoose validation error, it will be + // a duplicate key error. + assert.ok(error); + assert.ok(!error.errors); + assert.ok(error.message.indexOf('duplicate key error') !== -1); + // acquit:ignore:start + --remaining || done(); + // acquit:ignore:end + }); + }); }); /** diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index 7c0e7a89467..6606d36f6b0 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -222,9 +222,9 @@ describe('model', function() { }); it('error should emit on the model', function(done) { - var db = start(), - schema = new Schema({name: {type: String}}), - Test = db.model('IndexError', schema, 'x' + random()); + var db = start(); + var schema = new Schema({name: {type: String}}); + var Test = db.model('IndexError', schema, 'x' + random()); Test.create({name: 'hi'}, {name: 'hi'}, function(err) { assert.strictEqual(err, null); @@ -237,6 +237,7 @@ describe('model', function() { done(); }); + delete Test.$init; Test.init(); }); }); From e8f0055b1cf2ad472dfce77674c224fb009900c6 Mon Sep 17 00:00:00 2001 From: Jonathan Lambert Date: Thu, 28 Sep 2017 10:23:03 +0100 Subject: [PATCH 1919/2240] Update mquery dependency See https://nodesecurity.io/advisories/534, debug is a dependency of mquery. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 257887e9523..2ff5a1a33aa 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mongodb": "2.2.31", "mpath": "0.3.0", "mpromise": "0.5.5", - "mquery": "2.3.1", + "mquery": "2.3.2", "ms": "2.0.0", "muri": "1.2.2", "regexp-clone": "0.0.1", From 0e5fc395c94612a0ae089f02cd400a8922671b34 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Sep 2017 17:16:57 -0700 Subject: [PATCH 1920/2240] test(connection): repro #5664 --- test/connection.test.js | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/connection.test.js b/test/connection.test.js index 5ee33e5f355..a8eb2a68a73 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -1190,6 +1190,54 @@ describe('connections:', function() { }); }); + it('force close (gh-5664)', function(done) { + var opts = { useMongoClient: true }; + var db = mongoose.createConnection('mongodb://localhost:27017/test', opts); + var coll = db.collection('Test'); + db.then(function() { + setTimeout(function() { + coll.insertOne({x:1}, function(error) { + assert.ok(error); + assert.ok(error.message.indexOf('pool was destroyed') !== -1, error.message); + done(); + }); + }, 100); + + // Force close + db.close(true); + }); + }); + + it('force close with connection created after close (gh-5664)', function(done) { + var opts = { useMongoClient: true }; + var db = mongoose.createConnection('mongodb://localhost:27017/test', opts); + db.then(function() { + setTimeout(function() { + // TODO: enforce error.message, right now get a confusing error + /*db.collection('Test').insertOne({x:1}, function(error) { + assert.ok(error); + + //assert.ok(error.message.indexOf('pool was destroyed') !== -1, error.message); + done(); + });*/ + + var threw = false; + try { + db.collection('Test').insertOne({x:1}, function() {}); + } catch (error) { + threw = true; + assert.ok(error); + } + + assert.ok(threw); + done(); + }, 100); + + // Force close + db.close(true); + }); + }); + describe('connecting to multiple mongos nodes (gh-1037)', function() { var mongos = process.env.MONGOOSE_MULTI_MONGOS_TEST_URI; if (!mongos) { From f9e0525fa2f7c8e254f3f949cab6273469b3df30 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Sep 2017 17:16:59 -0700 Subject: [PATCH 1921/2240] fix(connection): make force close work as expected Fix #5664 --- lib/collection.js | 4 +-- lib/connection.js | 28 +++++++++++++------ lib/drivers/node-mongodb-native/collection.js | 8 ++++-- lib/drivers/node-mongodb-native/connection.js | 11 ++++---- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/lib/collection.js b/lib/collection.js index e550ec2da58..2f7841b39cd 100644 --- a/lib/collection.js +++ b/lib/collection.js @@ -89,8 +89,8 @@ Collection.prototype.onOpen = function() { * @api private */ -Collection.prototype.onClose = function() { - if (this.opts.bufferCommands) { +Collection.prototype.onClose = function(force) { + if (this.opts.bufferCommands && !force) { this.buffer = true; } }; diff --git a/lib/connection.js b/lib/connection.js index 06f1d879836..fc60a1a4447 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -807,16 +807,25 @@ Connection.prototype.openUri = function(uri, options, callback) { /** * Closes the connection * + * @param {Boolean} [force] optional * @param {Function} [callback] optional * @return {Connection} self * @api public */ -Connection.prototype.close = function(callback) { +Connection.prototype.close = function(force, callback) { var _this = this; var Promise = PromiseProvider.get(); + + if (typeof force === 'function') { + callback = force; + force = false; + } + + this.$wasForceClosed = !!force; + return new Promise.ES6(function(resolve, reject) { - _this._close(function(error) { + _this._close(force, function(error) { callback && callback(error); if (error) { reject(error); @@ -830,10 +839,11 @@ Connection.prototype.close = function(callback) { /** * Handles closing the connection * + * @param {Boolean} force * @param {Function} callback * @api private */ -Connection.prototype._close = function(callback) { +Connection.prototype._close = function(force, callback) { var _this = this; this._closeCalled = true; @@ -845,11 +855,11 @@ Connection.prototype._close = function(callback) { case 1: // connected case 4: // unauthorized this.readyState = STATES.disconnecting; - this.doClose(function(err) { + this.doClose(force, function(err) { if (err) { _this.error(err, callback); } else { - _this.onClose(); + _this.onClose(force); callback && callback(); } }); @@ -880,18 +890,18 @@ Connection.prototype._close = function(callback) { * @api private */ -Connection.prototype.onClose = function() { +Connection.prototype.onClose = function(force) { this.readyState = STATES.disconnected; // avoid having the collection subscribe to our event emitter // to prevent 0.3 warning for (var i in this.collections) { if (utils.object.hasOwnProperty(this.collections, i)) { - this.collections[i].onClose(); + this.collections[i].onClose(force); } } - this.emit('close'); + this.emit('close', force); }; /** @@ -906,6 +916,8 @@ Connection.prototype.onClose = function() { */ Connection.prototype.collection = function(name, options) { + options = options ? utils.clone(options, { retainKeyOrder: true }) : {}; + options.$wasForceClosed = this.$wasForceClosed; if (!(name in this.collections)) { this.collections[name] = new Collection(name, this, options); } diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js index 49cd41acfe9..f913f21de63 100644 --- a/lib/drivers/node-mongodb-native/collection.js +++ b/lib/drivers/node-mongodb-native/collection.js @@ -93,8 +93,8 @@ NativeCollection.prototype.onOpen = function() { * @api private */ -NativeCollection.prototype.onClose = function() { - MongooseCollection.prototype.onClose.call(this); +NativeCollection.prototype.onClose = function(force) { + MongooseCollection.prototype.onClose.call(this, force); }; /*! @@ -103,6 +103,10 @@ NativeCollection.prototype.onClose = function() { function iter(i) { NativeCollection.prototype[i] = function() { + // If user force closed, queueing will hang forever. See #5664 + if (this.opts.$wasForceClosed) { + return this.conn.db.collection(this.name)[i].apply(collection, args); + } if (this.buffer) { this.addQueue(i, arguments); return; diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 98228ae4da9..609889564b9 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -144,7 +144,7 @@ function listen(conn) { } conn.db._listening = true; - conn.db.on('close', function() { + conn.db.on('close', function(force) { if (conn._closeCalled) return; // the driver never emits an `open` event. auto_reconnect still @@ -155,7 +155,7 @@ function listen(conn) { conn.emit('close'); return; } - conn.onClose(); + conn.onClose(force); }); conn.db.on('error', function(err) { conn.emit('error', err); @@ -224,13 +224,14 @@ NativeConnection.prototype.doOpenSet = function(fn) { /** * Closes the connection * - * @param {Function} fn + * @param {Boolean} [force] + * @param {Function} [fn] * @return {Connection} this * @api private */ -NativeConnection.prototype.doClose = function(fn) { - this.db.close(fn); +NativeConnection.prototype.doClose = function(force, fn) { + this.db.close(force, fn); return this; }; From 48ca0466a131d725557ff77777fa9a062f84bc72 Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Fri, 29 Sep 2017 13:14:30 -0400 Subject: [PATCH 1922/2240] Adding nsp check to the CI build Signed-off-by: Dave Henderson --- .travis.yml | 1 + package.json | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index a95635ca18e..1b60ba9628d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,5 +15,6 @@ before_script: - mkdir -p ./data/db/27000 - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --nopreallocj --dbpath ./data/db/27017 --syslog --port 27017 script: + - npm run nsp - npm test - npm run lint diff --git a/package.json b/package.json index 257887e9523..401ddfbfe51 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "mongoose-long": "0.1.1", "mongodb-topology-manager": "1.0.11", "node-static": "0.7.7", + "nsp": "^2.8.1", "power-assert": "1.4.1", "q": "1.4.1", "tbd": "0.6.4", @@ -74,6 +75,7 @@ "fix-lint": "eslint . --fix", "install-browser": "npm install `node format_deps.js`", "lint": "eslint . --quiet", + "nsp": "nsp check", "test": "mocha test/*.test.js test/**/*.test.js", "test-cov": "istanbul cover --report text --report html _mocha test/*.test.js" }, From 5332ab609f8cd6e809ea38cfba604f06d3db795a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Sep 2017 10:55:30 -0700 Subject: [PATCH 1923/2240] chore: use ~ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 401ddfbfe51..43de7acbf16 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "mongoose-long": "0.1.1", "mongodb-topology-manager": "1.0.11", "node-static": "0.7.7", - "nsp": "^2.8.1", + "nsp": "~2.8.1", "power-assert": "1.4.1", "q": "1.4.1", "tbd": "0.6.4", From 5ab67260450adaed5c1d07680f6718c591194e28 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Sep 2017 12:13:24 -0700 Subject: [PATCH 1924/2240] chore: run nsp after test --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1b60ba9628d..8623517fbe0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,6 @@ before_script: - mkdir -p ./data/db/27000 - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --nopreallocj --dbpath ./data/db/27017 --syslog --port 27017 script: - - npm run nsp - npm test - npm run lint + - npm run nsp From 4be7d796b0468e1a81dbcb736b5dd94220cee09a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Sep 2017 12:18:35 -0700 Subject: [PATCH 1925/2240] chore: remove nsp for now --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8623517fbe0..a95635ca18e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,4 +17,3 @@ before_script: script: - npm test - npm run lint - - npm run nsp From cc6e489766d3910150278b74b318f213c91f9c3d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Sep 2017 16:01:50 -0700 Subject: [PATCH 1926/2240] test(populate): repro #5669 --- lib/services/query/selectPopulatedFields.js | 24 +++++++++++++ test/model.populate.test.js | 40 +++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 lib/services/query/selectPopulatedFields.js diff --git a/lib/services/query/selectPopulatedFields.js b/lib/services/query/selectPopulatedFields.js new file mode 100644 index 00000000000..bfcd8ccb5ec --- /dev/null +++ b/lib/services/query/selectPopulatedFields.js @@ -0,0 +1,24 @@ +'use strict'; + +module.exports = function selectPopulatedFields(query) { + var opts = query._mongooseOptions; + + if (opts.populate != null) { + var paths = Object.keys(opts.populate); + var i; + var userProvidedFields = query._userProvidedFields || {}; + if (query.selectedInclusively()) { + for (i = 0; i < paths.length; ++i) { + if (userProvidedFields[paths[i]] == null) { + query.select(paths[i]); + } + } + } else if (query.selectedExclusively()) { + for (i = 0; i < paths.length; ++i) { + if (userProvidedFields[paths[i]] == null) { + delete query._fields[paths[i]]; + } + } + } + } +}; diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 0d373c1b9e6..4b87cf0c102 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4840,6 +4840,46 @@ describe('model: populate:', function() { }); }); + it('auto select populated fields (gh-5669)', function(done) { + var ProductSchema = new mongoose.Schema({ + name: { + type: String + }, + categories: { + type: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'gh5669' + }], + select: false + } + }); + + var CategorySchema = new Schema({ name: String }); + var Product = db.model('gh5669_0', ProductSchema); + var Category = db.model('gh5669', CategorySchema); + + Category.create({ name: 'Books' }, function(error, doc) { + assert.ifError(error); + var product = { + name: 'Professional AngularJS', + categories: [doc._id] + }; + Product.create(product, function(error, product) { + assert.ifError(error); + Product.findById(product._id).populate('categories').exec(function(error, product) { + assert.ifError(error); + assert.equal(product.categories.length, 1); + assert.equal(product.categories[0].name, 'Books'); + Product.findById(product._id).populate('categories').select({ categories: 0 }).exec(function(error, product) { + assert.ifError(error); + assert.ok(!product.categories); + done(); + }); + }); + }); + }); + }); + it('handles populating with discriminators that may not have a ref (gh-4817)', function(done) { var imagesSchema = new mongoose.Schema({ name: { From 07e62be8f3cc10d6a388334ded15790292be8f02 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Sep 2017 16:01:53 -0700 Subject: [PATCH 1927/2240] fix(populate): automatically select() populated()-ed fields Fix #5669 --- lib/query.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/query.js b/lib/query.js index e4252be7f43..05f58bd9a5d 100644 --- a/lib/query.js +++ b/lib/query.js @@ -11,6 +11,7 @@ var hasDollarKeys = require('./services/query/hasDollarKeys'); var helpers = require('./queryhelpers'); var mquery = require('mquery'); var readPref = require('./drivers').ReadPreference; +var selectPopulatedFields = require('./services/query/selectPopulatedFields'); var setDefaultsOnInsert = require('./services/setDefaultsOnInsert'); var updateValidators = require('./services/updateValidators'); var util = require('util'); @@ -3217,6 +3218,7 @@ Query.prototype._castFields = function _castFields(fields) { Query.prototype._applyPaths = function applyPaths() { this._fields = this._fields || {}; helpers.applyPaths(this._fields, this.model.schema); + selectPopulatedFields(this); }; /** @@ -3729,6 +3731,29 @@ Query.prototype.centerSphere = function() { * @api public */ +Query.prototype.selectedExclusively = function selectedExclusively() { + if (!this._fields) { + return false; + } + + var keys = Object.keys(this._fields); + if (keys.length === 0) { + return false; + } + + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (key === '_id') { + continue; + } + if (this._fields[key] === 0) { + return true; + } + } + + return false; +}; + /*! * Export */ From 0165e5f3b259290e99f14d767db7a904a350594e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 29 Sep 2017 17:54:28 -0700 Subject: [PATCH 1928/2240] chore: bump lockfile and add back nsp re: #5658 --- .travis.yml | 1 + package-lock.json | 310 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 299 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index a95635ca18e..8623517fbe0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,3 +17,4 @@ before_script: script: - npm test - npm run lint + - npm run nsp diff --git a/package-lock.json b/package-lock.json index bb919d1410f..c6aa4c9c925 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.11.13-pre", + "version": "4.11.14-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -383,8 +383,7 @@ "bluebird": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", - "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", - "dev": true + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" }, "brace-expansion": { "version": "1.1.8", @@ -603,6 +602,7 @@ "version": "2.6.8", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, "requires": { "ms": "2.0.0" } @@ -2066,20 +2066,23 @@ "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" }, "mquery": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.1.tgz", - "integrity": "sha1-mrNnSXFIAP8LtTpoHOS8TV8HyHs=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.2.tgz", + "integrity": "sha512-KXWMypZSvhCuqRtza+HMQZdYw7PfFBjBTFvP31NNAq0OX0/NTIgpcDpkWQ2uTxk6vGQtwQ2elhwhs+ZvCA8OaA==", "requires": { - "bluebird": "2.10.2", - "debug": "2.6.8", + "bluebird": "3.5.0", + "debug": "2.6.9", "regexp-clone": "0.0.1", "sliced": "0.0.5" }, "dependencies": { - "bluebird": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz", - "integrity": "sha1-AkpVFylTCIV/FPkfEQb8O1VfRGs=" + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } }, "sliced": { "version": "0.0.5", @@ -2136,6 +2139,289 @@ "abbrev": "1.0.9" } }, + "nsp": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/nsp/-/nsp-2.8.1.tgz", + "integrity": "sha512-jvjDg2Gsw4coD/iZ5eQddsDlkvnwMCNnpG05BproSnuG+Gr1bSQMwWMcQeYje+qdDl3XznmhblMPLpZLecTORQ==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-table": "0.3.1", + "cvss": "1.0.2", + "https-proxy-agent": "1.0.0", + "joi": "6.10.1", + "nodesecurity-npm-utils": "5.0.0", + "path-is-absolute": "1.0.1", + "rc": "1.2.1", + "semver": "5.4.1", + "subcommand": "2.1.0", + "wreck": "6.3.0" + }, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "dev": true, + "requires": { + "colors": "1.0.3" + } + }, + "cliclopts": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cliclopts/-/cliclopts-1.1.1.tgz", + "integrity": "sha1-aUMcfLWvcjd0sNORG0w3USQxkQ8=", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, + "cvss": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cvss/-/cvss-1.0.2.tgz", + "integrity": "sha1-32fpK/EqeW9J6Sh5nI2zunS5/NY=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "isemail": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", + "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=", + "dev": true + }, + "joi": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", + "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", + "dev": true, + "requires": { + "hoek": "2.16.3", + "isemail": "1.2.0", + "moment": "2.18.1", + "topo": "1.1.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "moment": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", + "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nodesecurity-npm-utils": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-5.0.0.tgz", + "integrity": "sha1-Baow3jDKjIRcQEjpT9eOXgi1Xtk=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "subcommand": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/subcommand/-/subcommand-2.1.0.tgz", + "integrity": "sha1-XkzspaN3njNlsVEeBfhmh3MC92A=", + "dev": true, + "requires": { + "cliclopts": "1.1.1", + "debug": "2.6.9", + "minimist": "1.2.0", + "xtend": "4.0.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "topo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", + "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "wreck": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-6.3.0.tgz", + "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", + "dev": true, + "requires": { + "boom": "2.10.1", + "hoek": "2.16.3" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", From c86ef79c5d351510010fd3a23b6c204897c20704 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Sep 2017 14:22:24 -0700 Subject: [PATCH 1929/2240] chore: release 4.11.14 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index d81983d8907..e751e3e7936 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.11.14 / 2017-09-30 +==================== + * chore: add nsp check to the CI build #5679 [hairyhenderson](https://github.com/hairyhenderson) + * fix: bump mquery because of security issue with debug package #5677 #5675 [jonathanprl](https://github.com/jonathanprl) + * fix(populate): automatically select() populated()-ed fields #5669 + * fix(connection): make force close work as expected #5664 + * fix(document): treat $elemMatch as inclusive projection #5661 + * docs(model/query): clarify which functions fire which middleware #5654 + * fix(model): make `init()` public and return a promise that resolves when indexes are done building #5563 + 4.11.13 / 2017-09-24 ==================== * fix(query): correctly run replaceOne with update validators #5665 [sime1](https://github.com/sime1) diff --git a/package.json b/package.json index d615e873deb..fbeaa8d50bd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.14-pre", + "version": "4.11.14", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 33342bfed760b28ee988c17c269dd68f28692434 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Sep 2017 14:25:23 -0700 Subject: [PATCH 1930/2240] chore: add missing comment --- lib/services/query/selectPopulatedFields.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/services/query/selectPopulatedFields.js b/lib/services/query/selectPopulatedFields.js index bfcd8ccb5ec..f706f4552c0 100644 --- a/lib/services/query/selectPopulatedFields.js +++ b/lib/services/query/selectPopulatedFields.js @@ -1,5 +1,9 @@ 'use strict'; +/*! + * ignore + */ + module.exports = function selectPopulatedFields(query) { var opts = query._mongooseOptions; From abe39a6d744be80e5b003cf6242a4b1a8de2fdcb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Sep 2017 14:27:07 -0700 Subject: [PATCH 1931/2240] chore: now working on 4.11.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fbeaa8d50bd..911d71c461d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.11.14", + "version": "4.11.15-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 1ee73cea347d80a36921dba63599b90aefebf6b5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Sep 2017 14:38:49 -0700 Subject: [PATCH 1932/2240] chore: fix merge conflict --- lib/model.js | 5 ----- lib/query.js | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index ad7465acc61..2c58e588bea 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1024,12 +1024,7 @@ function _createIndexes(model, options, callback) { _handleSafe(options); indexSingleStart(indexFields, options); -<<<<<<< HEAD - model.collection.createIndex(indexFields, indexOptions, utils.tick(function(err, name) { -======= - model.collection.ensureIndex(indexFields, indexOptions, utils.tick(function(err, name) { ->>>>>>> master indexSingleDone(err, indexFields, indexOptions, name); if (err) { return done(err); diff --git a/lib/query.js b/lib/query.js index fef21692a98..07f2943cfb1 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1130,7 +1130,7 @@ Query.prototype.lean = function(v) { /** * Gets/sets the error flag on this query. If this flag is not null or - * undefined, the `exec()` promise will reject. + * undefined, the `exec()` promise will reject without executing. * * ####Example: * From 25a15668ef82d648c10d43c29bc9d2a2a9334065 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Sep 2017 14:56:52 -0700 Subject: [PATCH 1933/2240] docs(query): clarify relationship between custom query errors and cast errors Re: #5520 --- lib/query.js | 18 ++++++++++++++---- test/query.test.js | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/query.js b/lib/query.js index 07f2943cfb1..f28307f2074 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1143,6 +1143,16 @@ Query.prototype.lean = function(v) { * } * }); * + * Note that query casting runs **after** hooks, so cast errors will override + * custom errors. + * + * ####Example: + * var TestSchema = new Schema({ num: Number }); + * var TestModel = db.model('Test', TestSchema); + * TestModel.find({ num: 'not a number' }).error(new Error('woops')).exec(function(error) { + * // `error` will be a cast error because `num` failed to cast + * }); + * * @param {Error|null} err if set, `exec()` will fail fast before sending the query to MongoDB * @returns {Query} this * @api public @@ -1161,11 +1171,11 @@ Query.prototype.error = function error(err) { * ignore */ -Query.prototype._setCastError = function _setCastError(err) { - if (err == null && this._error != null && !(this._error instanceof CastError)) { +Query.prototype._unsetCastError = function _unsetCastError() { + if (this._error != null && !(this._error instanceof CastError)) { return; } - return this.error(err); + return this.error(null); }; /** @@ -1191,7 +1201,7 @@ Query.prototype.mongooseOptions = function(v) { Query.prototype._castConditions = function() { try { this.cast(this.model); - this._setCastError(null); + this._unsetCastError(); } catch (err) { this.error(err); } diff --git a/test/query.test.js b/test/query.test.js index 92c0a0cfe0d..b410108963f 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2150,6 +2150,22 @@ describe('Query', function() { }); }); + it('cast error with custom error (gh-5520)', function(done) { + var TestSchema = new Schema({ name: Number }); + + var TestModel = db.model('gh5520_0', TestSchema); + + TestModel. + find({ name: 'not a number' }). + error(new Error('woops')). + exec(function(error) { + assert.ok(error); + // CastError check happens **after** `.error()` + assert.equal(error.name, 'CastError'); + done(); + }); + }); + it('change deleteOne to updateOne for soft deletes using $isDeleted (gh-4428)', function(done) { var schema = new mongoose.Schema({ name: String, From 7880a7734e1d9afdbc4cad47235460280487b2d7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Sep 2017 15:04:28 -0700 Subject: [PATCH 1934/2240] style: fix lint --- test/model.discriminator.querying.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js index 7ae863797ca..abb87ea0484 100644 --- a/test/model.discriminator.querying.test.js +++ b/test/model.discriminator.querying.test.js @@ -844,7 +844,7 @@ describe('model', function() { var schoolSchema = new BaseSchema({ principal: String }); var Org = db.model('gh5613', orgSchema); - var School = Org.discriminator('gh5613_0', schoolSchema); + Org.discriminator('gh5613_0', schoolSchema); Org.create({ name: 'test' }, function(error, doc) { assert.ifError(error); From 97397ccdbf2b0d6cf4332385b7cd8a2862adf0e7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Sep 2017 17:32:04 -0700 Subject: [PATCH 1935/2240] refactor: create _createConstructor helper for embedded schemas re: #5244 --- lib/schema/embedded.js | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index f41a2d64f85..2e577b01685 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -9,6 +9,7 @@ var EventEmitter = require('events').EventEmitter; var SchemaType = require('../schematype'); var Subdocument = require('../types/subdocument'); var castToNumber = require('./operators/helpers').castToNumber; +var discriminator = require('../services/model/discriminator'); var geospatial = require('./operators/geospatial'); module.exports = Embedded; @@ -24,6 +25,24 @@ module.exports = Embedded; */ function Embedded(schema, path, options) { + this.caster = _createConstructor(schema); + this.caster.prototype.$basePath = path; + this.schema = schema; + this.$isSingleNested = true; + SchemaType.call(this, path, options, 'Embedded'); +} + +/*! + * ignore + */ + +Embedded.prototype = Object.create(SchemaType.prototype); + +/*! + * ignore + */ + +function _createConstructor(schema) { var _embedded = function SingleNested(value, path, parent) { var _this = this; Subdocument.apply(this, arguments); @@ -46,7 +65,6 @@ function Embedded(schema, path, options) { _embedded.prototype.constructor = _embedded; _embedded.schema = schema; _embedded.$isSingleNested = true; - _embedded.prototype.$basePath = path; _embedded.prototype.toBSON = function() { return this.toObject({ transform: false, @@ -72,14 +90,9 @@ function Embedded(schema, path, options) { _embedded[i] = EventEmitter.prototype[i]; } - this.caster = _embedded; - this.schema = schema; - this.$isSingleNested = true; - SchemaType.call(this, path, options, 'Embedded'); + return _embedded; } -Embedded.prototype = Object.create(SchemaType.prototype); - /*! * Special case for when users use a common location schema to represent * locations for use with $geoWithin. From a072f8381941a0a8f040e7d94a1e44b5cea31aed Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 30 Sep 2017 18:12:27 -0700 Subject: [PATCH 1936/2240] feat(types): add `discriminator()` function for single nested subdocs Fix #5244 --- lib/schema/embedded.js | 41 +++++++++++++++++++++++++--- lib/services/model/discriminator.js | 3 ++- test/model.discriminator.test.js | 42 +++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 2e577b01685..861e88b5b34 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -136,13 +136,22 @@ Embedded.prototype.cast = function(val, doc, init, priorVal) { return val; } + var Constructor = this.caster; + var discriminatorKey = Constructor.schema.options.discriminatorKey; + if (val != null && + Constructor.discriminators && + typeof val[discriminatorKey] === 'string' && + Constructor.discriminators[val[discriminatorKey]]) { + Constructor = Constructor.discriminators[val[discriminatorKey]]; + } + var subdoc; if (init) { - subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); + subdoc = new Constructor(void 0, doc ? doc.$__.selected : void 0, doc); subdoc.init(val); } else { if (Object.keys(val).length === 0) { - return new this.caster({}, doc ? doc.$__.selected : void 0, doc); + return new Constructor({}, doc ? doc.$__.selected : void 0, doc); } if (priorVal && priorVal.$isSingleNested) { @@ -152,9 +161,9 @@ Embedded.prototype.cast = function(val, doc, init, priorVal) { virtuals: false, getters: false }); - subdoc = new this.caster(_priorVal, doc ? doc.$__.selected : void 0, doc); + subdoc = new Constructor(_priorVal, doc ? doc.$__.selected : void 0, doc); } else { - subdoc = new this.caster(void 0, doc ? doc.$__.selected : void 0, doc); + subdoc = new Constructor(void 0, doc ? doc.$__.selected : void 0, doc); } subdoc.set(val, undefined, false); @@ -200,6 +209,14 @@ Embedded.prototype.castForQuery = function($conditional, val) { Embedded.prototype.doValidate = function(value, fn, scope) { var Constructor = this.caster; + var discriminatorKey = Constructor.schema.options.discriminatorKey; + if (value != null && + Constructor.discriminators && + typeof value[discriminatorKey] === 'string' && + Constructor.discriminators[value[discriminatorKey]]) { + Constructor = Constructor.discriminators[value[discriminatorKey]]; + } + SchemaType.prototype.doValidate.call(this, value, function(error) { if (error) { return fn(error); @@ -207,6 +224,7 @@ Embedded.prototype.doValidate = function(value, fn, scope) { if (!value) { return fn(null); } + if (!(value instanceof Constructor)) { value = new Constructor(value); } @@ -230,3 +248,18 @@ Embedded.prototype.doValidateSync = function(value, scope) { } return value.validateSync(); }; + +/** + * Adds a discriminator to this property + * + * @param {String} name + * @param {Schema} schema fields to add to the schema for instances of this sub-class + * @api public + */ + +Embedded.prototype.discriminator = function(name, schema) { + discriminator(this.caster, name, schema); + + this.caster.discriminators[name] = _createConstructor(schema); + return this.caster.discriminators[name]; +}; diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 9b66d0cc81e..b0bf8e83b67 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -39,7 +39,8 @@ module.exports = function discriminator(model, name, schema) { if (newName === name) { return name; } - throw new Error('Can\'t set discriminator key "' + key + '"'); + throw new Error('Can\'t set discriminator key "' + key + '", "' + + name + '" !== "' + newName + '"'); }, $skipDiscriminatorCheck: false }; diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 932255230e3..c4cf109fd2a 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -748,5 +748,47 @@ describe('model', function() { catch(done); }); }); + + it('embedded with single nested subdocs (gh-5244)', function(done) { + var eventSchema = new Schema({ message: String }, + { discriminatorKey: 'kind', _id: false }); + + var trackSchema = new Schema({ event: eventSchema }); + trackSchema.path('event').discriminator('Clicked', new Schema({ + element: String + }, { _id: false })); + trackSchema.path('event').discriminator('Purchased', new Schema({ + product: String + }, { _id: false })); + + var MyModel = db.model('gh5244', trackSchema); + var doc1 = { + event: { + kind: 'Clicked', + element: 'Amazon Link' + } + }; + var doc2 = { + event: { + kind: 'Purchased', + product: 'Professional AngularJS' + } + }; + MyModel.create([doc1, doc2]). + then(function(docs) { + var doc1 = docs[0]; + var doc2 = docs[1]; + + assert.equal(doc1.event.kind, 'Clicked'); + assert.equal(doc1.event.element, 'Amazon Link'); + assert.ok(!doc1.event.product); + + assert.equal(doc2.event.kind, 'Purchased'); + assert.equal(doc2.event.product, 'Professional AngularJS'); + assert.ok(!doc2.event.element); + done(); + }). + catch(done); + }); }); }); From d6f65e72f6e293d812569ab84e0e56c5d6a83268 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 1 Oct 2017 21:06:21 -0700 Subject: [PATCH 1937/2240] docs(validation): add docs coverage for ValidatorError.reason Fix #5681 --- test/docs/validation.test.js | 37 +++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 1fe2ef655c1..a18c5b1d5f1 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -285,9 +285,12 @@ describe('validation docs', function() { /** * Errors returned after failed validation contain an `errors` object - * holding the actual `ValidatorError` objects. Each + * whose values are `ValidatorError` objects. Each * [ValidatorError](./api.html#error-validation-js) has `kind`, `path`, * `value`, and `message` properties. + * A ValidatorError also may have a `reason` property. If an error was + * thrown in the validator, this property will contain the error that was + * thrown. */ it('Validation Errors', function(done) { @@ -296,23 +299,35 @@ describe('validation docs', function() { name: String }); - var Toy = db.model('Toy', toySchema); - - var validator = function (value) { - return /blue|green|white|red|orange|periwinkle/i.test(value); + var validator = function(value) { + return /red|white|gold/i.test(value); }; - Toy.schema.path('color').validate(validator, + toySchema.path('color').validate(validator, 'Color `{VALUE}` not valid', 'Invalid color'); + toySchema.path('name').validate(function(v) { + if (v !== 'Turbo Man') { + throw new Error('Need to get a Turbo Man for Christmas'); + } + return true; + }, 'Name `{VALUE}` is not valid'); - var toy = new Toy({ color: 'grease'}); + var Toy = db.model('Toy', toySchema); + + var toy = new Toy({ color: 'Green', name: 'Power Ranger' }); toy.save(function (err) { - // err is our ValidationError object - // err.errors.color is a ValidatorError object - assert.equal(err.errors.color.message, 'Color `grease` not valid'); + // `err` is a ValidationError object + // `err.errors.color` is a ValidatorError object + assert.equal(err.errors.color.message, 'Color `Green` not valid'); assert.equal(err.errors.color.kind, 'Invalid color'); assert.equal(err.errors.color.path, 'color'); - assert.equal(err.errors.color.value, 'grease'); + assert.equal(err.errors.color.value, 'Green'); + + assert.equal(err.errors.name.message, 'Name `Power Ranger` is not valid'); + assert.equal(err.errors.name.value, 'Power Ranger'); + assert.equal(err.errors.name.reason.message, + 'Need to get a Turbo Man for Christmas'); + assert.equal(err.name, 'ValidationError'); // acquit:ignore:start done(); From 8f958f42444d507e0c2bfd0c3625b595ca6c86b8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 1 Oct 2017 21:14:24 -0700 Subject: [PATCH 1938/2240] refactor: bring selectedInclusively() back --- lib/query.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/query.js b/lib/query.js index 05f58bd9a5d..7d691421a57 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3717,6 +3717,31 @@ Query.prototype.centerSphere = function() { * @api public */ +Query.prototype.selectedInclusively = function selectedInclusively() { + if (!this._fields) { + return false; + } + + var keys = Object.keys(this._fields); + if (keys.length === 0) { + return false; + } + + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (this._fields[key] === 0) { + return false; + } + if (this._fields[key] && + typeof this._fields[key] === 'object' && + this._fields[key].$meta) { + return false; + } + } + + return true; +}; + /** * Determines if exclusive field selection has been made. * From b9cda3d380a201d1efa184517f4424cb4fbeb0cd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 Oct 2017 09:30:36 -0700 Subject: [PATCH 1939/2240] feat(query): run update validators on $pull and $pullAll Fix #5555 --- lib/services/updateValidators.js | 3 ++- test/docs/validation.test.js | 36 +++++++++++++++++++++------ test/model.update.test.js | 42 ++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 5bba9697727..64d49b69cbc 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -32,7 +32,8 @@ module.exports = function(query, schema, castedDoc, options) { for (var i = 0; i < numKeys; ++i) { if (keys[i].charAt(0) === '$') { - if (keys[i] === '$push' || keys[i] === '$addToSet') { + if (keys[i] === '$push' || keys[i] === '$addToSet' || + keys[i] === '$pull' || keys[i] === '$pullAll') { _keys = Object.keys(castedDoc[keys[i]]); for (var ii = 0; ii < _keys.length; ++ii) { if (castedDoc[keys[i]][_keys[ii]].$each) { diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index 1fe2ef655c1..661e257fb45 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -516,15 +516,32 @@ describe('validation docs', function() { }); /** - * One final detail worth noting: update validators **only** run on `$set` - * and `$unset` operations (and `$push` and `$addToSet` in >= 4.8.0). + * One final detail worth noting: update validators **only** run on the + * following update operators: + * + * \* `$set` + * \* `$unset` + * \* `$push` (>= 4.8.0) + * \* `$addToSet` (>= 4.8.0) + * \* `$pull` (>= 4.12.0) + * \* `$pullAll` (>= 4.12.0) + * * For instance, the below update will succeed, regardless of the value of - * `number`, because update validators ignore `$inc`. + * `number`, because update validators ignore `$inc`. Also, `$push`, + * `$addToSet`, `$pull`, and `$pullAll` validation does **not** run any + * validation on the array itself, only individual elements of the array. */ it('Update Validators Only Run On Specified Paths', function(done) { var testSchema = new Schema({ number: { type: Number, max: 0 }, + arr: [{ message: { type: String, maxLength: 10 } }] + }); + + // Update validators won't check this, so you can still `$push` 2 elements + // onto the array, so long as they don't have a `message` that's too long. + testSchema.path('arr').validate(function(v) { + return v.length < 2; }); var Test = db.model('Test', testSchema); @@ -533,10 +550,15 @@ describe('validation docs', function() { var opts = { runValidators: true }; Test.update({}, update, opts, function(error) { // There will never be a validation error here - // acquit:ignore:start - assert.ifError(error); - done(); - // acquit:ignore:end + update = { $push: [{ message: 'hello' }, { message: 'world' }] }; + Test.update({}, update, opts, function(error) { + // This will never error either even though the array will have at + // least 2 elements. + // acquit:ignore:start + assert.ifError(error); + done(); + // acquit:ignore:end + }); }); }); diff --git a/test/model.update.test.js b/test/model.update.test.js index 6d7ca5a108f..69c3c977ea1 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2684,6 +2684,48 @@ describe('model: update:', function() { }); }); + it('$pull with updateValidators (gh-5555)', function(done) { + var notificationSchema = new mongoose.Schema({ + message: { + type: String, + maxlength: 12 + } + }); + + var userSchema = new mongoose.Schema({ + notifications: [notificationSchema] + }); + + var User = db.model('gh5555', userSchema); + + var opts = { multi: true, runValidators: true }; + var update = { + $pull: { + notifications: { + message: 'This message is wayyyyyyyyyy too long' + } + } + }; + User.create({ notifications: [{ message: 'test' }] }, function(error, doc) { + assert.ifError(error); + + User.update({}, update, opts).exec(function(error) { + assert.ok(error); + assert.ok(error.errors['notifications']); + + update.$pull.notifications.message = 'test'; + User.update({ _id: doc._id }, update, opts).exec(function(error) { + assert.ifError(error); + User.findById(doc._id, function(error, doc) { + assert.ifError(error); + assert.equal(doc.notifications.length, 0); + done(); + }); + }); + }); + }); + }); + it('update with Decimal type (gh-5361)', function(done) { start.mongodVersion(function(err, version) { if (err) { From 1a2432d072a8152095d0076deb7eb389eb314a93 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 Oct 2017 18:19:13 -0700 Subject: [PATCH 1940/2240] chore: fix merge conflicts --- lib/services/document/compile.js | 27 ++++++++++++--------------- test/docs/schematypes.test.js | 2 +- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/lib/services/document/compile.js b/lib/services/document/compile.js index c2a5d4c7067..958c4b672a1 100644 --- a/lib/services/document/compile.js +++ b/lib/services/document/compile.js @@ -77,27 +77,19 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { } if (!this.$__.getters[path]) { - var nested = Object.create(Object.getPrototypeOf(this), getOwnPropertyDescriptors(this)); + var nested = Object.create(Document.prototype, getOwnPropertyDescriptors(this)); // save scope for nested getters/setters if (!prefix) { nested.$__.scope = this; } - // shadow inherited getters from sub-objects so - // thing.nested.nested.nested... doesn't occur (gh-366) - var i = 0, - len = keys.length; - - for (; i < len; ++i) { - // over-write the parents getter without triggering it - Object.defineProperty(nested, keys[i], { - enumerable: false, // It doesn't show up. - writable: true, // We can set it later. - configurable: true, // We can Object.defineProperty again. - value: undefined // It shadows its parent. - }); - } + Object.defineProperty(nested, 'schema', { + enumerable: false, + configurable: true, + writable: false, + value: prototype.schema + }); Object.defineProperty(nested, 'toObject', { enumerable: false, @@ -158,6 +150,11 @@ function getOwnPropertyDescriptors(object) { Object.getOwnPropertyNames(object).forEach(function(key) { result[key] = Object.getOwnPropertyDescriptor(object, key); + // Assume these are schema paths, ignore them re: #5470 + if (result[key].get) { + delete result[key]; + return; + } result[key].enumerable = ['isNew', '$__', 'errors', '_doc'].indexOf(key) === -1; }); diff --git a/test/docs/schematypes.test.js b/test/docs/schematypes.test.js index d1a8e90f5a9..28834d9d315 100644 --- a/test/docs/schematypes.test.js +++ b/test/docs/schematypes.test.js @@ -52,7 +52,7 @@ describe('schemaTypes', function () { mongoose.Schema.Types.Int8 = Int8; var testSchema = new Schema({ test: Int8 }); - var Test = mongoose.model('Test', testSchema); + var Test = mongoose.model('CustomTypeExample', testSchema); var t = new Test(); t.test = 'abc'; From 2a26a92a6ae55337f0d4d1e65f8595e74cab8353 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 Oct 2017 20:31:15 -0700 Subject: [PATCH 1941/2240] chore: release 4.12.0 --- History.md | 15 +++++++++++++++ package.json | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e751e3e7936..2757ee5744f 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,18 @@ +4.12.0 / 2017-10-02 +=================== + * docs(validation): add docs coverage for ValidatorError.reason #5681 + * feat(discriminator): always add discriminatorKey to base schema to allow updating #5613 + * fix(document): make nested docs no longer inherit parent doc's schema props #5586 #5546 #5470 + * feat(query): run update validators on $pull and $pullAll #5555 + * feat(query): add .error() helper to query to error out in pre hooks #5520 + * feat(connection): add dropCollection() helper #5393 + * feat(schema): add schema-level collation option #5295 + * feat(types): add `discriminator()` function for single nested subdocs #5244 + * feat(document): add $isDeleted() getter/setter for better support for soft deletes #4428 + * feat(connection): bubble up reconnectFailed event when driver gives up reconnecting #4027 + * fix(query): report error if passing array or other non-object as filter to update query #3677 + * fix(collection): use createIndex() instead of deprecated ensureIndex() #3280 + 4.11.14 / 2017-09-30 ==================== * chore: add nsp check to the CI build #5679 [hairyhenderson](https://github.com/hairyhenderson) diff --git a/package.json b/package.json index 2b370f258fe..d6e9a66ff4c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.0-pre", + "version": "4.12.0", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From bbe20225b020c7eeb98d346bea7568fc185eebe1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 2 Oct 2017 20:33:57 -0700 Subject: [PATCH 1942/2240] chore: now working on 4.12.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d6e9a66ff4c..d1a3c9c26a1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.0", + "version": "4.12.1-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From aa3c732979e0a6e29cd8408b4c483b45b87d8aeb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Oct 2017 09:17:55 -0700 Subject: [PATCH 1943/2240] test(discriminator): repro #5684 --- test/model.discriminator.test.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index c4cf109fd2a..db68b68b717 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -539,6 +539,36 @@ describe('model', function() { }); }); + it('reusing schema for discriminators (gh-5684)', function(done) { + var ParentSchema = new Schema({}); + var ChildSchema = new Schema({ name: String }); + + var FirstContainerSchema = new Schema({ + stuff: [ParentSchema] + }); + + FirstContainerSchema.path('stuff').discriminator('Child', ChildSchema); + + var SecondContainerSchema = new Schema({ + things: [ParentSchema] + }); + + SecondContainerSchema.path('things').discriminator('Child', ChildSchema); + + var M1 = db.model('gh5684_0', FirstContainerSchema); + var M2 = db.model('gh5684_1', SecondContainerSchema); + + var doc1 = new M1({ stuff: [{ __t: 'Child', name: 'test' }] }); + var doc2 = new M2({ things: [{ __t: 'Child', name: 'test' }] }); + + assert.equal(doc1.stuff.length, 1); + assert.equal(doc1.stuff[0].name, 'test'); + assert.equal(doc2.things.length, 1); + assert.equal(doc2.things[0].name, 'test'); + + done(); + }); + it('embedded discriminators with $push (gh-5009)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From a517f1454ae05393acfe1c073186c6a9db5a6372 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 3 Oct 2017 09:18:12 -0700 Subject: [PATCH 1944/2240] fix(discriminator): allow reusing child schema Fix #5684 --- lib/services/model/discriminator.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index b0bf8e83b67..8d781827bfb 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -42,13 +42,13 @@ module.exports = function discriminator(model, name, schema) { throw new Error('Can\'t set discriminator key "' + key + '", "' + name + '" !== "' + newName + '"'); }, - $skipDiscriminatorCheck: false + $skipDiscriminatorCheck: true }; baseSchemaAddition[key][model.schema.options.typeKey] = String; model.schema.add(baseSchemaAddition); defineKey(key, null, model.prototype, null, [key], model.schema.options); - if (schema.path(key) && !schema.path(key).$skipDiscriminatorCheck) { + if (schema.path(key) && schema.path(key).options.$skipDiscriminatorCheck !== true) { throw new Error('Discriminator "' + name + '" cannot have field with name "' + key + '"'); } @@ -73,7 +73,8 @@ module.exports = function discriminator(model, name, schema) { return name; } throw new Error('Can\'t set discriminator key "' + key + '"'); - } + }, + $skipDiscriminatorCheck: true }; obj[key][schema.options.typeKey] = String; schema.add(obj); From b8ebf88483dd55e339087e82c26b1ad1666a258e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 4 Oct 2017 16:44:12 -0700 Subject: [PATCH 1945/2240] docs: fix bad promise lib example on home page Re: #5686 --- index.jade | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.jade b/index.jade index 80ec15d0e96..bae6f56650d 100644 --- a/index.jade +++ b/index.jade @@ -44,7 +44,8 @@ html(lang='en') #example :js var mongoose = require('mongoose'); - mongoose.connect('mongodb://localhost/test', { useMongoClient: true, promiseLibrary: global.Promise }); + mongoose.connect('mongodb://localhost/test', { useMongoClient: true }); + mongoose.Promise = global.Promise; var Cat = mongoose.model('Cat', { name: String }); From a8a9a2a8ea2003da1d6e3e8ee5039b3ebbc45950 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Oct 2017 21:43:02 -0700 Subject: [PATCH 1946/2240] test: repro #5504 --- test/document.test.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 728cb0ec18f..bed6e68ae0e 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4636,6 +4636,7 @@ describe('document', function() { var referrerB = new Referrer(); var referrerC = new Referrer(); var referrerD = new Referrer(); + var referrerE = new Referrer(); referrerA.reference.push(referenceB); assert.ok(referrerA.reference[0] instanceof Referrer); @@ -4650,6 +4651,9 @@ describe('document', function() { referrerD.reference.splice(0, 0, referenceB); assert.ok(referrerD.reference[0] instanceof Referrer); + referrerE.reference.addToSet(referenceB); + assert.ok(referrerE.reference[0] instanceof Referrer); + done(); }); From 59f237865182effe8bf11d5e8e34d257ea4718bf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 5 Oct 2017 21:44:13 -0700 Subject: [PATCH 1947/2240] fix: make addToSet() on empty array with subdoc trigger manual population Fix #5504 --- lib/types/array.js | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/lib/types/array.js b/lib/types/array.js index 20a493ef078..06682f1bd3b 100644 --- a/lib/types/array.js +++ b/lib/types/array.js @@ -308,13 +308,7 @@ MongooseArray.mixin = { */ push: function() { - var ref = this._schema.caster.options && this._schema.caster.options.ref; - if (this.length === 0 && - arguments.length) { - if (_isAllSubdocs(arguments, ref)) { - this._parent.populated(this._path, [], { model: arguments[0].constructor }); - } - } + _checkManualPopulation(this, arguments); var values = [].map.call(arguments, this._mapCast, this); values = this._schema.applySetters(values, this._parent, undefined, undefined, { skipDocumentArrayCast: true }); @@ -577,14 +571,7 @@ MongooseArray.mixin = { var vals; var i; - var ref = this._schema.caster.options && this._schema.caster.options.ref; - if (this.length === 0 && - arguments.length > 2) { - var docs = Array.prototype.slice.call(arguments, 2); - if (_isAllSubdocs(docs, ref)) { - this._parent.populated(this._path, [], { model: docs[0].constructor }); - } - } + _checkManualPopulation(this, Array.prototype.slice.call(arguments, 2)); if (arguments.length) { vals = []; @@ -614,13 +601,7 @@ MongooseArray.mixin = { */ unshift: function() { - var ref = this._schema.caster.options && this._schema.caster.options.ref; - if (this.length === 0 && - arguments.length) { - if (_isAllSubdocs(arguments, ref)) { - this._parent.populated(this._path, [], { model: arguments[0].constructor }); - } - } + _checkManualPopulation(this, arguments); var values = [].map.call(arguments, this._cast, this); values = this._schema.applySetters(values, this._parent); @@ -667,6 +648,8 @@ MongooseArray.mixin = { */ addToSet: function addToSet() { + _checkManualPopulation(this, arguments); + var values = [].map.call(arguments, this._mapCast, this); values = this._schema.applySetters(values, this._parent); var added = []; @@ -833,6 +816,20 @@ function _isAllSubdocs(docs, ref) { return true; } +/*! + * ignore + */ + +function _checkManualPopulation(arr, docs) { + var ref = arr._schema.caster.options && arr._schema.caster.options.ref; + if (arr.length === 0 && + docs.length > 0) { + if (_isAllSubdocs(docs, ref)) { + arr._parent.populated(arr._path, [], { model: docs[0].constructor }); + } + } +} + /*! * Module exports. */ From 2276254b0723856b4718f4b0ef9610b7d1ff0780 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 6 Oct 2017 09:43:58 -0700 Subject: [PATCH 1948/2240] test(populate): repro #5685 --- test/model.populate.test.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 4b87cf0c102..b04c788258a 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4840,7 +4840,7 @@ describe('model: populate:', function() { }); }); - it('auto select populated fields (gh-5669)', function(done) { + it('auto select populated fields (gh-5669) (gh-5685)', function(done) { var ProductSchema = new mongoose.Schema({ name: { type: String @@ -4873,7 +4873,13 @@ describe('model: populate:', function() { Product.findById(product._id).populate('categories').select({ categories: 0 }).exec(function(error, product) { assert.ifError(error); assert.ok(!product.categories); - done(); + Product.findById(product._id).select({ name: 0 }).populate('categories').exec(function(error, product) { + assert.ifError(error); + assert.equal(product.categories.length, 1); + assert.equal(product.categories[0].name, 'Books'); + assert.ok(!product.name); + done(); + }); }); }); }); From 11503386c2ff4ade402463ed53072b976c6d797f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 6 Oct 2017 09:44:02 -0700 Subject: [PATCH 1949/2240] fix(query): handle false when checking for inclusive/exclusive projection Fix #5685 --- lib/query.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index bfca3d0be86..829e94ffad1 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3791,7 +3791,7 @@ Query.prototype.selectedInclusively = function selectedInclusively() { for (var i = 0; i < keys.length; ++i) { var key = keys[i]; - if (this._fields[key] === 0) { + if (this._fields[key] === 0 || this._fields[key] === false) { return false; } if (this._fields[key] && @@ -3833,7 +3833,7 @@ Query.prototype.selectedExclusively = function selectedExclusively() { if (key === '_id') { continue; } - if (this._fields[key] === 0) { + if (this._fields[key] === 0 || this._fields[key] === false) { return true; } } From 7f1bfd2870e9e55430df900ae631fa0073f14903 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 6 Oct 2017 10:17:21 -0700 Subject: [PATCH 1950/2240] test(model): repro #5690 --- test/index.test.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/index.test.js b/test/index.test.js index 2081348f464..34a7932b6e2 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -61,9 +61,9 @@ describe('mongoose module:', function() { done(); }); - it('declaring global plugins', function(done) { + it('declaring global plugins (gh-5690)', function(done) { var mong = new Mongoose(); - var subSchema = new Schema({}); + var subSchema = new Schema({ name: String }); var schema = new Schema({ test: [subSchema] }); @@ -78,6 +78,8 @@ describe('mongoose module:', function() { ++preSaveCalls; next(); }); + + s.methods.testMethod = function() { return 42; }; }); schema.plugin(function(s) { @@ -94,9 +96,11 @@ describe('mongoose module:', function() { assert.equal(preSaveCalls, 0); mong.connect(start.uri, { useMongoClient: true }); - M.create({ test: {} }, function(error) { + M.create({ test: [{ name: 'Val' }] }, function(error, doc) { assert.ifError(error); assert.equal(preSaveCalls, 2); + assert.equal(doc.testMethod(), 42); + assert.equal(doc.test[0].testMethod(), 42); mong.disconnect(); done(); }); From a318435bce0a69fecbe5d502c6f97afb0077888f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 6 Oct 2017 10:17:27 -0700 Subject: [PATCH 1951/2240] fix(model): recursively call applyMethods on child schemas for global plugins Fix #5690 --- lib/services/model/applyMethods.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/services/model/applyMethods.js b/lib/services/model/applyMethods.js index 14c2e29607a..73e51f1cb3b 100644 --- a/lib/services/model/applyMethods.js +++ b/lib/services/model/applyMethods.js @@ -31,4 +31,13 @@ module.exports = function applyMethods(model, schema) { apply(method, schema); } } + + // Recursively call `applyMethods()` on child schemas + model.$appliedMethods = true; + for (var i = 0; i < schema.childSchemas.length; ++i) { + if (schema.childSchemas[i].model.$appliedMethods) { + continue; + } + applyMethods(schema.childSchemas[i].model, schema.childSchemas[i].schema); + } }; From f472f5efdc4bdfb17732f95ae0428375495c2675 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 Oct 2017 18:05:43 -0700 Subject: [PATCH 1952/2240] test(document): repro #5693 --- test/document.test.js | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index bed6e68ae0e..270c8c551b5 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4750,6 +4750,54 @@ describe('document', function() { }); }); + it('Single nested subdocs using discriminator can be modified (gh-5693)', function(done) { + var eventSchema = new Schema({ message: String }, { + discriminatorKey: 'kind', + _id: false + }); + + var trackSchema = new Schema({ event: eventSchema }); + + trackSchema.path('event').discriminator('Clicked', new Schema({ + element: String + }, { _id: false })); + + trackSchema.path('event').discriminator('Purchased', new Schema({ + product: String + }, { _id: false })); + + var MyModel = db.model('gh5693', trackSchema); + + var doc = new MyModel({ + event: { + message: 'Test', + kind: 'Clicked', + element: 'Amazon Link' + } + }); + + doc.save(function(error) { + assert.ifError(error); + assert.equal(doc.event.message, 'Test'); + assert.equal(doc.event.kind, 'Clicked'); + assert.equal(doc.event.element, 'Amazon Link'); + + doc.set('event', { + kind: 'Purchased', + product: 'Professional AngularJS' + }); + + doc.save(function(error) { + assert.ifError(error); + assert.equal(doc.event.kind, 'Purchased'); + assert.equal(doc.event.product, 'Professional AngularJS'); + assert.ok(!doc.event.element); + assert.ok(!doc.event.message); + done(); + }); + }); + }); + it('doc array: set then remove (gh-3511)', function(done) { var ItemChildSchema = new mongoose.Schema({ name: { From 140402c67a014dfe7086c21efd55f952586d84bf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 Oct 2017 18:05:47 -0700 Subject: [PATCH 1953/2240] fix(document): create new doc when setting single nested, no more set() on copy of priorVal Fix #5693 Re: #5363 --- lib/document.js | 8 ++++++-- lib/schema/embedded.js | 20 ++++++-------------- lib/types/subdocument.js | 12 ++++++------ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/lib/document.js b/lib/document.js index e099d3f202a..24b3336b43f 100644 --- a/lib/document.js +++ b/lib/document.js @@ -41,11 +41,12 @@ var idGetter = require('./plugins/idGetter'); * @api private */ -function Document(obj, fields, skipId) { +function Document(obj, fields, skipId, options) { this.$__ = new InternalCache; this.$__.emitter = new EventEmitter(); this.isNew = true; this.errors = undefined; + this.$__.$options = options || {}; var schema = this.schema; @@ -757,7 +758,10 @@ Document.prototype.set = function(path, val, type, options) { didPopulate = true; } - val = schema.applySetters(val, this, false, priorVal); + var setterContext = constructing && this.$__.$options.priorDoc ? + this.$__.$options.priorDoc : + this; + val = schema.applySetters(val, setterContext, false, priorVal); if (!didPopulate && this.$__.populated) { delete this.$__.populated[path]; diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 861e88b5b34..e9705626d59 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -45,8 +45,10 @@ Embedded.prototype = Object.create(SchemaType.prototype); function _createConstructor(schema) { var _embedded = function SingleNested(value, path, parent) { var _this = this; - Subdocument.apply(this, arguments); + this.$parent = parent; + Subdocument.apply(this, arguments); + if (parent) { parent.on('save', function() { _this.emit('save', _this); @@ -154,19 +156,9 @@ Embedded.prototype.cast = function(val, doc, init, priorVal) { return new Constructor({}, doc ? doc.$__.selected : void 0, doc); } - if (priorVal && priorVal.$isSingleNested) { - var _priorVal = priorVal.toObject({ - minimize: true, - transform: false, - virtuals: false, - getters: false - }); - subdoc = new Constructor(_priorVal, doc ? doc.$__.selected : void 0, doc); - } else { - subdoc = new Constructor(void 0, doc ? doc.$__.selected : void 0, doc); - } - - subdoc.set(val, undefined, false); + return new Constructor(val, doc ? doc.$__.selected : void 0, doc, undefined, { + priorDoc: priorVal + }); } return subdoc; diff --git a/lib/types/subdocument.js b/lib/types/subdocument.js index 72b9419aaf7..3d622ec1635 100644 --- a/lib/types/subdocument.js +++ b/lib/types/subdocument.js @@ -10,9 +10,9 @@ module.exports = Subdocument; * @api private */ -function Subdocument(value, fields) { +function Subdocument(value, fields, parent, skipId, options) { this.$isSingleNested = true; - Document.call(this, value, fields); + Document.call(this, value, fields, skipId, options); } Subdocument.prototype = Object.create(Document.prototype); @@ -48,7 +48,7 @@ Subdocument.prototype.save = function(fn) { }; Subdocument.prototype.$isValid = function(path) { - if (this.$parent) { + if (this.$parent && this.$basePath) { return this.$parent.$isValid([this.$basePath, path].join('.')); } return Document.prototype.$isValid.call(this, path); @@ -56,7 +56,7 @@ Subdocument.prototype.$isValid = function(path) { Subdocument.prototype.markModified = function(path) { Document.prototype.markModified.call(this, path); - if (this.$parent) { + if (this.$parent && this.$basePath) { if (this.$parent.isDirectModified(this.$basePath)) { return; } @@ -66,7 +66,7 @@ Subdocument.prototype.markModified = function(path) { Subdocument.prototype.$markValid = function(path) { Document.prototype.$markValid.call(this, path); - if (this.$parent) { + if (this.$parent && this.$basePath) { this.$parent.$markValid([this.$basePath, path].join('.')); } }; @@ -79,7 +79,7 @@ Subdocument.prototype.invalidate = function(path, err, val) { Document.prototype.invalidate.call(this, path, err, val); } - if (this.$parent) { + if (this.$parent && this.$basePath) { this.$parent.invalidate([this.$basePath, path].join('.'), err, val); } else if (err.kind === 'cast' || err.name === 'CastError') { throw err; From 68f57b8dcf106d8c264b01d9c259a1c1323cdeae Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 Oct 2017 19:37:12 -0700 Subject: [PATCH 1954/2240] chore: now working on 4.13.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d1a3c9c26a1..c6ddfe4fb5b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.1-pre", + "version": "4.13.0-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a7518bdba44eedc476464c0bb8abb9f4e74a46db Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 7 Oct 2017 20:48:54 -0700 Subject: [PATCH 1955/2240] refactor(document): add PoC of using $set internally Re: #1939 --- lib/document.js | 26 ++++++++++++++++---------- lib/schema.js | 3 ++- lib/services/document/compile.js | 5 +++-- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/document.js b/lib/document.js index 24b3336b43f..718485fdc5d 100644 --- a/lib/document.js +++ b/lib/document.js @@ -74,7 +74,7 @@ function Document(obj, fields, skipId, options) { if (this.$__original_set) { this.$__original_set(obj, undefined, true); } else { - this.set(obj, undefined, true); + this.$set(obj, undefined, true); } } @@ -499,7 +499,7 @@ Document.prototype.update = function update() { * @api public */ -Document.prototype.set = function(path, val, type, options) { +Document.prototype.$set = function(path, val, type, options) { if (type && utils.getFunctionName(type.constructor) === 'Object') { options = type; type = undefined; @@ -548,7 +548,7 @@ Document.prototype.set = function(path, val, type, options) { if (len === 0 && !this.schema.options.minimize) { if (val) { - this.set(val, {}); + this.$set(val, {}); } return this; } @@ -583,7 +583,7 @@ Document.prototype.set = function(path, val, type, options) { && !(this.schema.paths[pathName] && this.schema.paths[pathName].options && this.schema.paths[pathName].options.ref)) { - this.set(path[key], prefix + key, constructing); + this.$set(path[key], prefix + key, constructing); } else if (strict) { // Don't overwrite defaults with undefined keys (gh-3981) if (constructing && path[key] === void 0 && @@ -599,9 +599,9 @@ Document.prototype.set = function(path, val, type, options) { path[key] instanceof Document) { p = p.toObject({ virtuals: false, transform: false }); } - this.set(prefix + key, p, constructing); + this.$set(prefix + key, p, constructing); } else if (pathtype === 'nested' && path[key] instanceof Document) { - this.set(prefix + key, + this.$set(prefix + key, path[key].toObject({transform: false}), constructing); } else if (strict === 'throw') { if (pathtype === 'nested') { @@ -611,7 +611,7 @@ Document.prototype.set = function(path, val, type, options) { } } } else if (path[key] !== void 0) { - this.set(prefix + key, path[key], constructing); + this.$set(prefix + key, path[key], constructing); } } @@ -629,7 +629,7 @@ Document.prototype.set = function(path, val, type, options) { this.markModified(path); cleanModifiedSubpaths(this, path); } else { - this.set(val, path, constructing); + this.$set(val, path, constructing); } return this; } @@ -681,7 +681,7 @@ Document.prototype.set = function(path, val, type, options) { cur = cur[parts[i]]; curPath += (curPath.length > 0 ? '.' : '') + parts[i]; if (!cur) { - this.set(curPath, {}); + this.$set(curPath, {}); cur = this.getValue(curPath); } } @@ -785,6 +785,12 @@ Document.prototype.set = function(path, val, type, options) { return this; }; +/*! + * ignore + */ + +Document.prototype.set = Document.prototype.$set; + /** * Determine if we should mark this change as modified. * @@ -2575,7 +2581,7 @@ Document.prototype.depopulate = function(path) { return; } delete this.$__.populated[path]; - this.set(path, populatedIds); + this.$set(path, populatedIds); return this; }; diff --git a/lib/schema.js b/lib/schema.js index e4517730287..a849eee9b03 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -325,7 +325,8 @@ Schema.prototype.defaultOptions = function(options) { noVirtualId: false, // deprecated, use { id: false } id: true, typeKey: 'type', - retainKeyOrder: false + retainKeyOrder: false, + setFunction: 'set' }, options); if (options.read) { diff --git a/lib/services/document/compile.js b/lib/services/document/compile.js index 958c4b672a1..e5b329cf1c1 100644 --- a/lib/services/document/compile.js +++ b/lib/services/document/compile.js @@ -126,7 +126,8 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { if (v instanceof Document) { v = v.toObject({ transform: false }); } - return (this.$__.scope || this).set(path, v); + var doc = this.$__.scope || this; + return doc[doc.schema.options.setFunction](path, v); } }); } else { @@ -137,7 +138,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { return this.get.call(this.$__.scope || this, path); }, set: function(v) { - return this.set.call(this.$__.scope || this, path, v); + return this[this.schema.options.setFunction].call(this.$__.scope || this, path, v); } }); } From fbfe28368722e6ef11a119f4b6166d14af711180 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 Oct 2017 10:23:24 -0700 Subject: [PATCH 1956/2240] chore: release 4.12.1 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2757ee5744f..812b3bdf17a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.12.1 / 2017-10-08 +=================== + * fix(document): create new doc when setting single nested, no more set() on copy of priorVal #5693 + * fix(model): recursively call applyMethods on child schemas for global plugins #5690 + * docs: fix bad promise lib example on home page #5686 + * fix(query): handle false when checking for inclusive/exclusive projection #5685 + * fix(discriminator): allow reusing child schema #5684 + * fix: make addToSet() on empty array with subdoc trigger manual population #5504 + 4.12.0 / 2017-10-02 =================== * docs(validation): add docs coverage for ValidatorError.reason #5681 diff --git a/package.json b/package.json index d1a3c9c26a1..2eeee7856cb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.1-pre", + "version": "4.12.1", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4bb72ddb8ba037e05ec0eeef44abaa8918f30c8d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 Oct 2017 10:27:22 -0700 Subject: [PATCH 1957/2240] chore: now working on 4.12.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2eeee7856cb..07d368d93ce 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.1", + "version": "4.12.2-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c5ec9a9ae3e2fd9f697faca7cb0e21d8c29ca5c2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 8 Oct 2017 17:47:47 -0700 Subject: [PATCH 1958/2240] docs(connection): clarify that poolSize is max --- docs/connections.jade | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index 974edc9b04b..56f55fc4c82 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -13,7 +13,7 @@ block content on the default port (27017). If the local connection fails then try using 127.0.0.1 instead of localhost. Sometimes issues may arise when the local hostname has been changed. - + You can also specify several more parameters in the `uri`: :js @@ -26,28 +26,28 @@ block content :markdown Mongoose lets you start using your models immediately, without waiting for mongoose to establish a connection to MongoDB. - + :js mongoose.connect('mongodb://localhost/myapp'); var MyModel = mongoose.model('Test', new Schema({ name: String })); // Works MyModel.findOne(function(error, result) { /* ... */ }); - + :markdown That's because mongoose buffers model function calls internally. This buffering is convenient, but also a common source of confusion. Mongoose will *not* throw any errors by default if you use a model without connecting. - + :js var MyModel = mongoose.model('Test', new Schema({ name: String })); // Will just hang until mongoose successfully connects MyModel.findOne(function(error, result) { /* ... */ }); - + setTimeout(function() { mongoose.connect('mongodb://localhost/myapp'); }, 60000); - + :markdown To disable buffering, turn off the [`bufferCommands` option on your schema](http://mongoosejs.com/docs/guide.html#bufferCommands). If you have `bufferCommands` on and your connection is hanging, try turning @@ -93,7 +93,7 @@ block content :js // Good way to make sure mongoose never stops trying to reconnect mongoose.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } }); - + h3#callback Callback :markdown The `connect()` function also accepts a callback parameter and returns a [promise](http://mongoosejs.com/docs/promises.html). @@ -101,7 +101,7 @@ block content mongoose.connect(uri, options, function(error) { // Check error in initial connection. There is no 2nd param to the callback. }); - + // Or using promises mongoose.connect(uri, options).then( () => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ }, @@ -111,7 +111,7 @@ block content h4#connection-string-options Connection String Options :markdown Mongoose supports the following options in the connection string. - + * [ssl](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) * [poolSize](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) * [autoReconnect](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) @@ -155,7 +155,7 @@ block content :markdown To connect to a single node replica set, specify the `replicaSet` option. - + :js mongoose.connect('mongodb://host1:port1/?replicaSet=rsName'); @@ -179,7 +179,7 @@ block content h3#connection_pools Connection pools :markdown - Each `connection`, whether created with `mongoose.connect` or `mongoose.createConnection` are all backed by an internal configurable connection pool defaulting to a size of 5. Adjust the pool size using your connection options: + Each `connection`, whether created with `mongoose.connect` or `mongoose.createConnection` are all backed by an internal configurable connection pool defaulting to a maximum size of 5. Adjust the pool size using your connection options: :js // single server @@ -192,7 +192,7 @@ block content // passing the option in the URI works with single or replica sets var uri = 'mongodb://localhost/test?poolSize=4'; mongoose.createConnection(uri); - + h3#use-mongo-client The `useMongoClient` Option :markdown Mongoose's default connection logic is deprecated as of 4.11.0. Please opt @@ -261,7 +261,7 @@ block content keepAlive: true, reconnectTries: 30 }); - + :markdown This deprecation is because the [MongoDB driver](https://www.npmjs.com/package/mongodb) has deprecated an API that is critical to mongoose's connection logic to From 76f14feca511e651635248c5b271cc87b6074f54 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Oct 2017 07:59:21 -0700 Subject: [PATCH 1959/2240] test(model): refactor tests to reuse same db connetion Re: #5575 --- test/model.indexes.test.js | 113 ++++++++++--------------------------- 1 file changed, 29 insertions(+), 84 deletions(-) diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index 6606d36f6b0..43f13e8961d 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -10,6 +10,16 @@ var start = require('./common'), ObjectId = Schema.Types.ObjectId; describe('model', function() { + var db; + + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + describe('indexes', function() { it('are created when model is compiled', function(done) { var Indexed = new Schema({ @@ -22,9 +32,8 @@ describe('model', function() { Indexed.index({last: 1, email: 1}, {unique: true}); Indexed.index({date: 1}, {expires: 10}); - var db = start(), - IndexedModel = db.model('IndexedModel', Indexed, 'indexedmodel' + random()), - assertions = 0; + var IndexedModel = db.model('IndexedModel1', Indexed, 'indexedmodel' + random()); + var assertions = 0; IndexedModel.on('index', function() { IndexedModel.collection.getIndexes({full: true}, function(err, indexes) { @@ -45,7 +54,7 @@ describe('model', function() { }); assert.equal(assertions, 4); - db.close(done); + done(); }); }); }); @@ -62,9 +71,8 @@ describe('model', function() { blogposts: [BlogPosts] }); - var db = start(), - UserModel = db.model('DeepIndexedModel', User, 'deepindexedmodel' + random()), - assertions = 0; + var UserModel = db.model('DeepIndexedModel2', User, 'deepindexedmodel' + random()); + var assertions = 0; UserModel.on('index', function() { UserModel.collection.getIndexes(function(err, indexes) { @@ -87,7 +95,7 @@ describe('model', function() { } assert.equal(assertions, 3); - db.close(done); + done(); }); }); }); @@ -105,8 +113,7 @@ describe('model', function() { featured: [BlogPosts] }); - var db = start(); - var UserModel = db.model('DeepIndexedModel', User, 'gh-2322'); + var UserModel = db.model('DeepIndexedModelMulti3', User, 'gh2322'); var assertions = 0; UserModel.on('index', function() { @@ -136,7 +143,7 @@ describe('model', function() { } assert.equal(assertions, 5); - db.close(done); + done(); }); }); }); @@ -154,9 +161,8 @@ describe('model', function() { blogposts: [BlogPosts] }); - var db = start(), - UserModel = db.model('DeepCompoundIndexModel', User, 'deepcompoundindexmodel' + random()), - found = 0; + var UserModel = db.model('DeepCompoundIndexModel4', User, 'deepcompoundindexmodel' + random()); + var found = 0; UserModel.on('index', function() { UserModel.collection.getIndexes(function(err, indexes) { @@ -171,7 +177,6 @@ describe('model', function() { } } - db.close(); assert.equal(found, 2); done(); }); @@ -222,9 +227,8 @@ describe('model', function() { }); it('error should emit on the model', function(done) { - var db = start(); var schema = new Schema({name: {type: String}}); - var Test = db.model('IndexError', schema, 'x' + random()); + var Test = db.model('IndexError5', schema, 'x' + random()); Test.create({name: 'hi'}, {name: 'hi'}, function(err) { assert.strictEqual(err, null); @@ -232,7 +236,6 @@ describe('model', function() { Test.schema.index({other: 1}); Test.on('index', function(err) { - db.close(); assert.ok(/E11000 duplicate key error/.test(err.message), err); done(); }); @@ -244,11 +247,10 @@ describe('model', function() { describe('auto creation', function() { it('can be disabled', function(done) { - var db = start(); var schema = new Schema({name: {type: String, index: true}}); schema.set('autoIndex', false); - var Test = db.model('AutoIndexing', schema, 'autoindexing-disable'); + var Test = db.model('AutoIndexing6', schema, 'autoindexing-disable'); Test.on('index', function() { assert.ok(false, 'Model.ensureIndexes() was called'); }); @@ -262,7 +264,7 @@ describe('model', function() { assert.ifError(err); // Only default _id index should exist assert.deepEqual(['_id_'], Object.keys(indexes)); - db.close(done); + done(); }); }, 100); }); @@ -270,16 +272,15 @@ describe('model', function() { describe('global autoIndexes (gh-1875)', function() { it('will create indexes as a default', function(done) { - var db = start(); var schema = new Schema({name: {type: String, index: true}}); - var Test = db.model('GlobalAutoIndex', schema, 'gh-1875-1'); + var Test = db.model('GlobalAutoIndex7', schema, 'gh-1875-1'); Test.on('index', function(error) { assert.ifError(error); assert.ok(true, 'Model.ensureIndexes() was called'); Test.collection.getIndexes(function(err, indexes) { assert.ifError(err); assert.equal(Object.keys(indexes).length, 2); - db.close(done); + done(); }); }); }); @@ -287,7 +288,7 @@ describe('model', function() { it('will not create indexes if the global auto index is false and schema option isnt set (gh-1875)', function(done) { var db = start({config: {autoIndex: false}}); var schema = new Schema({name: {type: String, index: true}}); - var Test = db.model('GlobalAutoIndex', schema, 'x' + random()); + var Test = db.model('GlobalAutoIndex8', schema, 'x' + random()); Test.on('index', function() { assert.ok(false, 'Model.ensureIndexes() was called'); }); @@ -306,61 +307,6 @@ describe('model', function() { }); }); - it('do not trigger "MongoError: cannot add index with a background operation in progress" (gh-1365) LONG', function(done) { - this.timeout(90000); - - var db = start({uri: 'mongodb://localhost/mongoose_test_indexing'}); - - var schema = new Schema({ - name: {type: String, index: true}, - furryness: {type: Number, index: true} - }, {autoIndex: false}); - - schema.index({name: 1, furryness: 1}); - - var K = db.model('Kitten', schema); - K.on('index', function(err) { - assert.ifError(err); - db.close(done); - }); - - var neededKittens = 30000; - - db.on('open', function() { - K.count({}, function(err, n) { - assert.ifError(err); - if (n >= neededKittens) { - return index(); - } - var pending = neededKittens - n; - - function callback(err) { - assert.ifError(err); - if (--pending) { - return; - } - index(); - } - - function iter(i) { - K.create({name: 'kitten' + i, furryness: i}, callback); - } - - for (var i = n; i < neededKittens; ++i) { - iter(i); - } - }); - - function index() { - K.collection.dropAllIndexes(function(err) { - assert.ifError(err); - K.ensureIndexes(); - }); - } - }); - }); - - describe('model.ensureIndexes()', function() { it('is a function', function(done) { var schema = mongoose.Schema({x: 'string'}); @@ -378,9 +324,8 @@ describe('model', function() { }); it('creates indexes', function(done) { - var db = start(); - var schema = new Schema({name: {type: String}}), - Test = db.model('ManualIndexing', schema, 'x' + random()); + var schema = new Schema({name: {type: String}}); + var Test = db.model('ManualIndexing' + random(), schema, 'x' + random()); Test.schema.index({name: 1}, {sparse: true}); @@ -392,7 +337,7 @@ describe('model', function() { Test.ensureIndexes(function(err) { assert.ifError(err); assert.ok(called); - db.close(done); + done(); }); }); }); From 78c8a3dcd1d360bb459421e4e4846f947de42293 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Oct 2017 08:47:38 -0700 Subject: [PATCH 1960/2240] feat(schema): add excludeIndexes option to optionally prevent collecting indexes from nested schemas Fix #5575 --- lib/schema.js | 6 ++++-- test/model.indexes.test.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index e4517730287..a3ed2ff6693 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -569,7 +569,7 @@ Schema.interpretAsType = function(path, obj, options) { if (cast && cast[options.typeKey] && cast[options.typeKey].instanceOfSchema) { - return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj); + return new MongooseTypes.DocumentArray(path, cast[options.typeKey], cast); } if (Array.isArray(cast)) { @@ -1408,7 +1408,9 @@ Schema.prototype.indexes = function() { path = schema.paths[key]; if ((path instanceof MongooseTypes.DocumentArray) || path.$isSingleNested) { - collectIndexes(path.schema, prefix + key + '.'); + if (path.options.excludeIndexes !== true) { + collectIndexes(path.schema, prefix + key + '.'); + } } else { index = path._index || (path.caster && path.caster._index); diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index 43f13e8961d..7d1255740fb 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -100,6 +100,40 @@ describe('model', function() { }); }); + it('of embedded documents unless excludeIndexes (gh-5575)', function(done) { + var BlogPost = new Schema({ + _id: {type: ObjectId}, + title: {type: String, index: true}, + desc: String + }); + + var User = new Schema({ + name: {type: String, index: true}, + blogposts: { + type: [BlogPost], + excludeIndexes: true + }, + otherblogposts: [{ type: BlogPost, excludeIndexes: true }], + blogpost: { + type: BlogPost, + excludeIndexes: true + } + }); + + var UserModel = db.model('gh5575', User); + + UserModel.on('index', function() { + UserModel.collection.getIndexes(function(err, indexes) { + assert.ifError(err); + + // Should only have _id and name indexes + var indexNames = Object.keys(indexes); + assert.deepEqual(indexNames.sort(), ['_id_', 'name_1']); + done(); + }); + }); + }); + it('of multiple embedded documents with same schema', function(done) { var BlogPosts = new Schema({ _id: {type: ObjectId, index: true}, From 053a118042f8a8153c3852c5c116a30f5c025e93 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 10 Oct 2017 16:22:46 -0700 Subject: [PATCH 1961/2240] fix: upgrade muri for more detailed error messages Re: https://github.com/Automattic/mongoose/issues/2912#issuecomment-335242685 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 07d368d93ce..2349bccf1ac 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "mpromise": "0.5.5", "mquery": "2.3.2", "ms": "2.0.0", - "muri": "1.2.2", + "muri": "1.3.0", "regexp-clone": "0.0.1", "sliced": "1.0.1" }, From 23967d713b7e90643734e70374ba15d29a0a57ca Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 11 Oct 2017 09:51:20 -0700 Subject: [PATCH 1962/2240] test(schema): add coverage for childSchemas re: #5695 --- test/schema.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 286dcb3636e..8f21b8e40bc 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1700,5 +1700,25 @@ describe('schema', function() { ]); done(); }); + + it('childSchemas prop (gh-5695)', function(done) { + var schema1 = new Schema({ name: String }); + var schema2 = new Schema({ test: String }); + var schema = new Schema({ + arr: [schema1], + single: schema2 + }); + + assert.equal(schema.childSchemas.length, 2); + assert.equal(schema.childSchemas[0].schema, schema1); + assert.equal(schema.childSchemas[1].schema, schema2); + + schema = schema.clone(); + assert.equal(schema.childSchemas.length, 2); + assert.equal(schema.childSchemas[0].schema, schema1); + assert.equal(schema.childSchemas[1].schema, schema2); + + done(); + }); }); }); From 6df478284003019187af9fc0a10d0376f97776d8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 11 Oct 2017 09:51:25 -0700 Subject: [PATCH 1963/2240] docs(schema): document the childSchemas property and add to public API Fix #5695 --- lib/schema.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index e4517730287..52ec2bae076 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -224,6 +224,23 @@ Object.defineProperty(Schema.prototype, '_defaultMiddleware', { ] }); +/** + * Array of child schemas (from document arrays and single nested subdocs) + * and their corresponding compiled models. Each element of the array is + * an object with 2 properties: `schema` and `model`. + * + * This property is typically only useful for plugin authors and advanced users. + * You do not need to interact with this property at all to use mongoose. + * + * @api public + * @property childSchemas + */ + +Object.defineProperty(Schema.prototype, 'childSchemas', { + configurable: false, + enumerable: true, + writable: true +}); /** * The original object passed to the schema constructor From 4594c5dacc722b9aa4980ebd55575835ce377402 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 11 Oct 2017 10:50:19 -0700 Subject: [PATCH 1964/2240] test(query): repro #5669 --- test/services.query.test.js | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/services.query.test.js diff --git a/test/services.query.test.js b/test/services.query.test.js new file mode 100644 index 00000000000..89bc5e2a1d7 --- /dev/null +++ b/test/services.query.test.js @@ -0,0 +1,58 @@ +'use strict'; + +var Query = require('../lib/query'); +var Schema = require('../lib/schema'); +var assert = require('assert'); +var selectPopulatedFields = require('../lib/services/query/selectPopulatedFields'); + +describe('Query helpers', function() { + describe('selectPopulatedFields', function() { + it('handles nested populate if parent key is projected in (gh-5669)', function(done) { + var schema = new Schema({ + nested: { + key1: String, + key2: String + } + }); + + var q = new Query({}); + q.schema = schema; + + assert.strictEqual(q._fields, void 0); + + q.select('nested'); + q.populate('nested.key1'); + assert.deepEqual(q._fields, { nested: 1 }); + + selectPopulatedFields(q); + + assert.deepEqual(q._fields, { nested: 1 }); + + done(); + }); + + it('handles nested populate if parent key is projected out (gh-5669)', function(done) { + var schema = new Schema({ + nested: { + key1: String, + key2: String + } + }); + + var q = new Query({}); + q.schema = schema; + + assert.strictEqual(q._fields, void 0); + + q.select('-nested'); + q.populate('nested.key1'); + assert.deepEqual(q._fields, { nested: 0 }); + + selectPopulatedFields(q); + + assert.deepEqual(q._fields, { nested: 0 }); + + done(); + }); + }); +}); From ccae0a91dd97b47c8daf1c73c865ff91095f0265 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 11 Oct 2017 10:54:34 -0700 Subject: [PATCH 1965/2240] fix(query): don't project in populated field if parent field is already projected in Fix #5669 --- lib/services/query/selectPopulatedFields.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/services/query/selectPopulatedFields.js b/lib/services/query/selectPopulatedFields.js index f706f4552c0..bb69f9d3f05 100644 --- a/lib/services/query/selectPopulatedFields.js +++ b/lib/services/query/selectPopulatedFields.js @@ -13,7 +13,7 @@ module.exports = function selectPopulatedFields(query) { var userProvidedFields = query._userProvidedFields || {}; if (query.selectedInclusively()) { for (i = 0; i < paths.length; ++i) { - if (userProvidedFields[paths[i]] == null) { + if (!isPathInFields(userProvidedFields, paths[i])) { query.select(paths[i]); } } @@ -26,3 +26,20 @@ module.exports = function selectPopulatedFields(query) { } } }; + +/*! + * ignore + */ + +function isPathInFields(userProvidedFields, path) { + var pieces = path.split('.'); + var len = pieces.length; + var cur = pieces[0]; + for (var i = 1; i < len; ++i) { + if (userProvidedFields[cur] != null) { + return true; + } + cur += '.' + pieces[i]; + } + return false; +} From e0632116103f4c076b58fb9ae161737df0472fad Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Oct 2017 12:26:42 -0700 Subject: [PATCH 1966/2240] fix: bump mongodb -> 2.2.33 Fix #4513 --- package-lock.json | 36 +++++++++++++++++++----------------- package.json | 2 +- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 54aa52a74c0..98a55a69610 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.12.0-pre", + "version": "4.12.2-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2055,22 +2055,24 @@ } }, "mongodb": { - "version": "2.2.31", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.31.tgz", - "integrity": "sha1-GUBEXGYeGSF7s7+CRdmFSq71SNs=", + "version": "2.2.33", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.33.tgz", + "integrity": "sha1-tTfEcdNKZlG0jzb9vyl1A0Dgi1A=", "requires": { "es6-promise": "3.2.1", - "mongodb-core": "2.1.15", + "mongodb-core": "2.1.17", "readable-stream": "2.2.7" - } - }, - "mongodb-core": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.15.tgz", - "integrity": "sha1-hB9TuH//9MdFgYnDXIroJ+EWl2Q=", - "requires": { - "bson": "1.0.4", - "require_optional": "1.0.1" + }, + "dependencies": { + "mongodb-core": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.17.tgz", + "integrity": "sha1-pBizN6FKFJkPtRC5I97mqBMXPfg=", + "requires": { + "bson": "1.0.4", + "require_optional": "1.0.1" + } + } } }, "mongodb-topology-manager": { @@ -2148,9 +2150,9 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "muri": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/muri/-/muri-1.2.2.tgz", - "integrity": "sha1-YxmBMmUNsIoEzHnM0A3Tia/SYxw=" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/muri/-/muri-1.3.0.tgz", + "integrity": "sha512-FiaFwKl864onHFFUV/a2szAl7X0fxVlSKNdhTf+BM8i8goEgYut8u5P9MqQqIYwvaMxjzVESsoEm/2kfkFH1rg==" }, "mute-stream": { "version": "0.0.5", diff --git a/package.json b/package.json index 2349bccf1ac..9711fa054ff 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "2.0.0", "kareem": "1.5.0", - "mongodb": "2.2.31", + "mongodb": "2.2.33", "mpath": "0.3.0", "mpromise": "0.5.5", "mquery": "2.3.2", From aca06b1ae2651e3b13f6e82fd6dbf7fb860769dd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Oct 2017 12:49:27 -0700 Subject: [PATCH 1967/2240] docs(faq): add warnings about using arrow functions for getters/setters, virtuals, and methods Fix #5700 --- docs/faq.jade | 60 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/docs/faq.jade b/docs/faq.jade index fc45f5a5ca3..feb006bdf2c 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -30,11 +30,11 @@ block content doc.array[3] = 'changed'; doc.markModified('array'); doc.save(); - + hr#unique-doesnt-work :markdown **Q**. I declared a schema property as `unique` but I can still save duplicates. What gives? - + **A**. Mongoose doesn't handle `unique` on it's own, `{ name: { type: String, unique: true } }` just a shorthand for creating a [MongoDB unique index on `name`](https://docs.mongodb.com/manual/core/index-unique/). For example, if MongoDB doesn't already have a unique index on `name`, the below code will not error despite the fact that `unique` is true. @@ -61,7 +61,7 @@ block content console.log(err); }); }); - + // Promise based alternative. `init()` returns a promise that resolves // when the indexes have finished building successfully. The `init()` // function is idempotent, so don't worry about triggering an index rebuild. @@ -77,7 +77,7 @@ block content you should [create your indexes using the MongoDB shell])(https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/) rather than relying on mongoose to do it for you. The `unique` option for schemas is convenient for development and documentation, but mongoose is *not* an index management solution. - + hr#nested-properties :markdown **Q**. When I have a nested property in a schema, mongoose adds empty objects by default. Why? @@ -88,7 +88,7 @@ block content } }); var Model = db.model('Test', schema); - + // The below prints `{ _id: /* ... */, nested: {} }`, mongoose assigns // `nested` to an empty object `{}` by default. console.log(new Model()); @@ -96,7 +96,7 @@ block content **A**. This is a performance optimization. These empty objects are not saved to the database, nor are they in the result `toObject()`, nor do they show up in `JSON.stringify()` output unless you turn off the [`minimize` option](http://mongoosejs.com/docs/guide.html#minimize). - + The reason for this behavior is that Mongoose's change detection and getters/setters are based on [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). In order to support change detection on nested properties without incurring @@ -105,7 +105,35 @@ block content Because mongoose needs to define getters and setters for `nested.prop`, `nested` must always be defined as an object on a mongoose document, even if `nested` is undefined on the underlying [POJO](http://mongoosejs.com/docs/guide.html#minimize). - + + hr#arrow-functions + :markdown + **Q**. I'm using an arrow function for a [virtual](http://mongoosejs.com/docs/guide.html#virtuals), getter/setter, or [method](http://mongoosejs.com/docs/guide.html#methods) and the value of `this` is wrong. + + **A**. Arrow functions [handle the `this` keyword much differently than conventional functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_this). + Mongoose getters/setters depend on `this` to give you access to the document that you're writing to, but this functionality does not work with arrow functions. Do **not** use arrow functions for mongoose getters/setters unless do not intend to access the document in the getter/setter. + :js + // Do **NOT** use arrow functions as shown below unless you're certain + // that's what you want. If you're reading this FAQ, odds are you should + // just be using a conventional function. + var schema = new mongoose.Schema({ + propWithGetter: { + type: String, + get: v => { + // Will **not** be the doc, do **not** use arrow functions for getters/setters + console.log(this); + return v; + } + } + }); + + // `this` will **not** be the doc, do **not** use arrow functions for methods + schema.method.arrowMethod = () => this; + schema.virtual('virtualWithArrow').get(() => { + // `this` will **not** be the doc, do **not** use arrow functions for virtuals + console.log(this); + }); + hr#date_changes :markdown **Q**. Why don't in-place modifications to date objects @@ -125,11 +153,11 @@ block content :js doc.createdAt = new Date(2011, 5, 1).setHours(4); doc.save(); // Works - + hr#populate_sort_order :markdown **Q**. I'm populating a nested property under an array like the below code: - + ``` new Schema({ arr: [{ @@ -137,21 +165,21 @@ block content }] }); ``` - + `.populate({ path: 'arr.child', options: { sort: 'name' } })` won't sort by `arr.child.name`? - + :markdown **A**. See [this GitHub issue](https://github.com/Automattic/mongoose/issues/2202). It's a known issue but one that's exceptionally difficult to fix. - + hr#model_functions_hanging :markdown **Q**. All function calls on my models hang, what am I doing wrong? - + **A**. By default, mongoose will buffer your function calls until it can connect to MongoDB. Read the [buffering section of the connection docs](http://mongoosejs.com/docs/connections.html#buffering) for more information. - + hr#enable_debugging :markdown **Q**. How can I enable debugging? @@ -183,7 +211,7 @@ block content :markdown **Q**. Why do I get "OverwriteModelError: Cannot overwrite .. model once compiled" when I use nodemon / a testing framework? - + **A**. `mongoose.model('ModelName', schema)` requires 'ModelName' to be unique, so you can access the model by using `mongoose.model('ModelName')`. If you put `mongoose.model('ModelName', schema);` in a @@ -198,7 +226,7 @@ block content // use mongoose.Schema var kittySchema = mongoose.Schema({ name: String }); - + // use connection.model var Kitten = connection.model('Kitten', kittySchema); From f2170ee2a6bab60982f04ee54a153314d7ebe405 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 08:01:35 -0700 Subject: [PATCH 1968/2240] chore: release 4.12.2 --- History.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 812b3bdf17a..550a4754ab3 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.12.2 / 2017-10-13 +=================== + * docs(faq): add FAQ about using arrow functions for getters/setters, virtuals, and methods #5700 + * docs(schema): document the childSchemas property and add to public API #5695 + * fix(query): don't project in populated field if parent field is already projected in #5669 + * fix: bump mongodb -> 2.2.33 for issue with autoReconnect #4513 + 4.12.1 / 2017-10-08 =================== * fix(document): create new doc when setting single nested, no more set() on copy of priorVal #5693 diff --git a/package.json b/package.json index 9711fa054ff..a21e47c2805 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.2-pre", + "version": "4.12.2", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 75a55af19b625435362a25bf26b87943368847c7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 11:46:33 -0700 Subject: [PATCH 1969/2240] test(query): repro #5702 --- test/model.findOneAndUpdate.test.js | 59 +++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index c2ff235878e..6edccb61356 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1910,6 +1910,65 @@ describe('model: findOneAndUpdate:', function() { }); }); + it('avoids edge case with middleware cloning buffers (gh-5702)', function(done) { + var uuidParse = require('uuid-parse'); + + function toUUID(string) { + if (!string) { + return null; + } + if (Buffer.isBuffer(string) || Buffer.isBuffer(string.buffer)) { + return string; + } + var buffer = uuidParse.parse(string); + return new mongoose.Types.Buffer(buffer).toObject(0x04); + } + + function fromUUID(buffer) { + if (!buffer || buffer.length !== 16) { + return null; + } + return uuidParse.unparse(buffer); + } + + var UserSchema = new mongoose.Schema({ + name: String, + lastUpdate: {type: Date}, + friends: [{ + _id: false, + status: {type: String, required: true}, + id: { + type: mongoose.Schema.Types.Buffer, + get: fromUUID, + set: toUUID + } + }] + }, { collection: 'users', runSettersOnQuery: true }); + + UserSchema.pre('findOneAndUpdate', function() { + this.update({},{ $set: {lastUpdate: new Date()} }); + }); + + var User = db.model('gh5702', UserSchema); + + var friendId = uuid.v4(); + var user = { + name: 'Sean', + friends: [{status: 'New', id: friendId}] + }; + + User.create(user, function(error, user) { + assert.ifError(error); + + var q = { _id: user._id, 'friends.id': friendId }; + var upd = {'friends.$.status': 'Active'}; + User.findOneAndUpdate(q, upd, {new: true}).lean().exec(function(error) { + assert.ifError(error); + done(); + }); + }); + }); + it('setting subtype when saving (gh-5551)', function(done) { if (parseInt(process.version.substr(1).split('.')[0], 10) < 4) { // Don't run on node 0.x because of `const` issues From 63692e3353bfbf9aed81e53a443c9ac480968cee Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 11:46:44 -0700 Subject: [PATCH 1970/2240] fix(query): avoid infinite recursion edge case when cloning a buffer Fix #5702 --- lib/types/buffer.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/types/buffer.js b/lib/types/buffer.js index 9d7d4f26bf5..c61459eca7b 100644 --- a/lib/types/buffer.js +++ b/lib/types/buffer.js @@ -46,9 +46,18 @@ function MongooseBuffer(value, encode, offset) { // make sure these internal props don't show up in Object.keys() Object.defineProperties(buf, { - validators: {value: []}, - _path: {value: path}, - _parent: {value: doc} + validators: { + value: [], + enumerable: false + }, + _path: { + value: path, + enumerable: false + }, + _parent: { + value: doc, + enumerable: false + } }); if (doc && typeof path === 'string') { From 10882668528fdc58e9305b55aff041a68e40f0c5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 15:55:17 -0700 Subject: [PATCH 1971/2240] chore: now working on 4.12.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a21e47c2805..2df39dd808a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.2", + "version": "4.12.3-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 191ff1d588590feb92a27a62848d2c99da524927 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 15:57:55 -0700 Subject: [PATCH 1972/2240] style: fix lint --- test/model.findOneAndUpdate.test.js | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 6edccb61356..c35c2215aec 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1914,14 +1914,14 @@ describe('model: findOneAndUpdate:', function() { var uuidParse = require('uuid-parse'); function toUUID(string) { - if (!string) { + if (!string) { return null; } - if (Buffer.isBuffer(string) || Buffer.isBuffer(string.buffer)) { + if (Buffer.isBuffer(string) || Buffer.isBuffer(string.buffer)) { return string; } - var buffer = uuidParse.parse(string); - return new mongoose.Types.Buffer(buffer).toObject(0x04); + var buffer = uuidParse.parse(string); + return new mongoose.Types.Buffer(buffer).toObject(0x04); } function fromUUID(buffer) { @@ -1932,17 +1932,17 @@ describe('model: findOneAndUpdate:', function() { } var UserSchema = new mongoose.Schema({ - name: String, - lastUpdate: {type: Date}, - friends: [{ - _id: false, - status: {type: String, required: true}, - id: { - type: mongoose.Schema.Types.Buffer, - get: fromUUID, - set: toUUID - } - }] + name: String, + lastUpdate: {type: Date}, + friends: [{ + _id: false, + status: {type: String, required: true}, + id: { + type: mongoose.Schema.Types.Buffer, + get: fromUUID, + set: toUUID + } + }] }, { collection: 'users', runSettersOnQuery: true }); UserSchema.pre('findOneAndUpdate', function() { From 16475f3b7959563cca4978011b62098ab44ecb0a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 16:19:01 -0700 Subject: [PATCH 1973/2240] test(query): repro #5710 --- test/model.findOneAndUpdate.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index c35c2215aec..8538eadac38 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1910,6 +1910,21 @@ describe('model: findOneAndUpdate:', function() { }); }); + it('update validators with pushing null (gh-5710)', function(done) { + var schema = new mongoose.Schema({ + arr: [String] + }); + + var Model = db.model('gh5710', schema); + + var update = { $addToSet: { arr: null } }; + var options = { runValidators: true }; + Model.findOneAndUpdate({}, update, options, function(error) { + assert.ifError(error); + done(); + }); + }); + it('avoids edge case with middleware cloning buffers (gh-5702)', function(done) { var uuidParse = require('uuid-parse'); From b7ac49b05e89cea3cee74c31aa753e397a22dd3b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 16:19:16 -0700 Subject: [PATCH 1974/2240] fix(query): handle null with addToSet/push/pull/pullAll update validators Fix #5710 --- lib/services/updateValidators.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 64d49b69cbc..326d0b169a2 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -29,6 +29,7 @@ module.exports = function(query, schema, castedDoc, options) { var numKeys = keys.length; var hasDollarUpdate = false; var modified = {}; + var currentUpdate; for (var i = 0; i < numKeys; ++i) { if (keys[i].charAt(0) === '$') { @@ -36,12 +37,13 @@ module.exports = function(query, schema, castedDoc, options) { keys[i] === '$pull' || keys[i] === '$pullAll') { _keys = Object.keys(castedDoc[keys[i]]); for (var ii = 0; ii < _keys.length; ++ii) { - if (castedDoc[keys[i]][_keys[ii]].$each) { + currentUpdate = castedDoc[keys[i]][_keys[ii]]; + if (currentUpdate && currentUpdate.$each) { arrayAtomicUpdates[_keys[ii]] = (arrayAtomicUpdates[_keys[ii]] || []). - concat(castedDoc[keys[i]][_keys[ii]].$each); + concat(currentUpdate.$each); } else { arrayAtomicUpdates[_keys[ii]] = (arrayAtomicUpdates[_keys[ii]] || []). - concat([castedDoc[keys[i]][_keys[ii]]]); + concat([currentUpdate]); } } continue; From 2410add849a5ac76269527893e3bbf9e17387103 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 16:49:08 -0700 Subject: [PATCH 1975/2240] fix(connection): allow passing in `autoIndex` as top-level option rather than requiring `config.autoIndex` Re: #5711 --- lib/connection.js | 8 ++++++-- test/connection.test.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 07530bb6b70..1f3cc2c5c89 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -763,9 +763,13 @@ Connection.prototype.openUri = function(uri, options, callback) { if (options) { options = utils.clone(options, { retainKeyOrder: true }); delete options.useMongoClient; - if (options.config && options.config.autoIndex != null) { - this.config.autoIndex = options.config.autoIndex !== false; + var autoIndex = options.config && options.config.autoIndex != null ? + options.config.autoIndex : + options.autoIndex; + if (autoIndex != null) { + this.config.autoIndex = autoIndex !== false; delete options.config; + delete options.autoIndex; } // Backwards compat diff --git a/test/connection.test.js b/test/connection.test.js index d682d4fff81..50fea157b60 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -65,7 +65,7 @@ describe('connections:', function() { it('with autoIndex (gh-5423)', function(done) { var promise = mongoose.createConnection('mongodb://localhost:27017/mongoosetest', { useMongoClient: true, - config: { autoIndex: false } + autoIndex: false }); promise.then(function(conn) { From 69e44805873fe1391eeecb76eb1438d4aa40ad3a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 16:50:01 -0700 Subject: [PATCH 1976/2240] docs(connection): improve docs regarding reconnectTries, autoReconnect, and bufferMaxEntries Fix #5711 --- docs/connections.jade | 54 ++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index 56f55fc4c82..305b25aeaab 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -55,44 +55,40 @@ block content h3#options Options :markdown - The `connect` method also accepts an `options` object which will be passed on to the underlying driver. All options included here take precedence over options passed in the connection string. + The `connect` method also accepts an `options` object which will be passed on to the underlying MongoDB driver. :js mongoose.connect(uri, options); :markdown - The following option keys are available: - - db - passed to the [underlying driver's db instance](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) - server - passed to the [underlying driver's server instance(s)](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) - replset - passed to the [underlying driver's ReplSet instance](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) - user - username for authentication (if not specified in uri) - pass - password for authentication (if not specified in uri) - auth - options for authentication - mongos - passed to the [underlying driver's mongos options](http://mongodb.github.io/node-mongodb-native/2.1/api/Mongos.html) - promiseLibrary - sets the [underlying driver's promise library](http://mongodb.github.io/node-mongodb-native/2.1/api/MongoClient.html) + A full list of options can be found on the [MongoDB Node.js driver docs for `connect()`](http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect). + Mongoose passes options to the driver without modification, modulo three exceptions that are explained below. + + * `useMongoClient` - This is a mongoose-specific option (not passed to the MongoDB driver) that opts in to mongoose 4.11's new connection logic. If you are writing a new application, you **should** set this to `true`. + * `user`/`pass` - The username and password for authentication. These options are mongoose-specific, they are equivalent to the MongoDB driver's `auth.user` and `auth.password` options. + * `autoIndex` - By default, mongoose will automatically build indexes defined in your schema when it connects. This is great for development, but not ideal for large production deployments, because index builds can cause performance degradation. If you set `autoIndex` to false, mongoose will not automatically build indexes for **any** model associated with this connection. + + Below are some of the options that are important for tuning mongoose. + + * `autoReconnect` - The underlying MongoDB driver will automatically try to reconnect when it loses connection to MongoDB. Unless you are an extremely advanced user that wants to manage their own connection pool, do **not** set this option to `false`. + * `reconnectTries` - If you're connected to a single server or mongos proxy (as opposed to a replica set), the MongoDB driver will try to reconnect every `reconnectInterval` milliseconds for `reconnectTries` times, and give up afterward. When the driver gives up, the mongoose connection emits a `reconnectFailed` event. This option does nothing for replica set connections. + * `reconnectInterval` - See `reconnectTries` + * `promiseLibrary` - sets the [underlying driver's promise library](http://mongodb.github.io/node-mongodb-native/2.1/api/MongoClient.html) + * `poolSize` - The maximum number of sockets the MongoDB driver will keep open for this connection. By default, `poolSize` is 5. Keep in mind that, as of MongoDB 3.4, MongoDB only allows one operation per socket at a time, so you may want to increase this if you find you have a few slow queries that are blocking faster queries from proceeding. + * `bufferMaxEntries` - The MongoDB driver also has its own buffering mechanism that kicks in when the driver is disconnected. Set this option to 0 and set `bufferCommands` to `false` on your schemas if you want your database operations to fail immediately when the driver is not connected, as opposed to waiting for reconnection. + Example: :js var options = { - db: { native_parser: true }, - server: { poolSize: 5 }, - replset: { rs_name: 'myReplicaSetName' }, - user: 'myUserName', - pass: 'myPassword' - } + useMongoClient: true, + autoIndex: false, // Don't build indexes + reconnectTries: Number.MAX_VALUE, // Never stop trying to reconnect + reconnectInterval: 500, // Reconnect every 500ms + poolSize: 10, // Maintain up to 10 socket connections + // If not connected, return errors immediately rather than waiting for reconnect + bufferMaxEntries: 0 + }; mongoose.connect(uri, options); - :markdown - **Note:** - The server option `auto_reconnect` is defaulted to true which _can_ be overridden. - The db option `forceServerObjectId` is set to false which _cannot_ be overridden. - - See the [driver](https://github.com/mongodb/node-mongodb-native) for more information about available options. - :markdown - **Note:** - If `auto_reconnect` is on, mongoose will give up trying to reconnect after a certain number of failures. Set the [`server.reconnectTries` and `server.reconnectInterval` options](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) to increase the number of times mongoose will try to reconnect. - :js - // Good way to make sure mongoose never stops trying to reconnect - mongoose.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } }); h3#callback Callback :markdown From 480098dcd894b471c7a660296c91184bdc22a4db Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 17:00:02 -0700 Subject: [PATCH 1977/2240] test: fix 0.10+0.12 const issue --- test/model.findOneAndUpdate.test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 8538eadac38..23c2f3cb4d0 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1926,6 +1926,11 @@ describe('model: findOneAndUpdate:', function() { }); it('avoids edge case with middleware cloning buffers (gh-5702)', function(done) { + if (parseInt(process.version.substr(1).split('.')[0], 10) < 4) { + // Don't run on node 0.x because of `const` issues + this.skip(); + } + var uuidParse = require('uuid-parse'); function toUUID(string) { From 7c45e7ea87c8fab537a5b750ad4536a099224353 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 17:05:54 -0700 Subject: [PATCH 1978/2240] chore: correct 4.12.2 release date --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 550a4754ab3..1cf45cfd5db 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -4.12.2 / 2017-10-13 +4.12.2 / 2017-10-14 =================== * docs(faq): add FAQ about using arrow functions for getters/setters, virtuals, and methods #5700 * docs(schema): document the childSchemas property and add to public API #5695 From 76d8ffeb0ccc8bce49b549a4286a35606148b007 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 14 Oct 2017 17:45:55 -0700 Subject: [PATCH 1979/2240] refactor(query): make setDefaultsOnInsert take a filter as opposed to a query Re: #5708 --- lib/query.js | 4 ++-- lib/services/setDefaultsOnInsert.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/query.js b/lib/query.js index 829e94ffad1..28e8a648586 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2227,7 +2227,7 @@ Query.prototype._findAndModify = function(type, callback) { }; } else { castedDoc = castDoc(this, opts.overwrite); - castedDoc = setDefaultsOnInsert(this, schema, castedDoc, opts); + castedDoc = setDefaultsOnInsert(this._conditions, schema, castedDoc, opts); if (!castedDoc) { if (opts.upsert) { // still need to do the upsert to empty doc @@ -2939,7 +2939,7 @@ function _update(query, op, conditions, doc, options, callback) { } } - castedDoc = setDefaultsOnInsert(query, query.schema, castedDoc, options); + castedDoc = setDefaultsOnInsert(query._conditions, query.schema, castedDoc, options); if (!castedDoc) { // Make sure promises know that this is still an update, see gh-2796 query.op = op; diff --git a/lib/services/setDefaultsOnInsert.js b/lib/services/setDefaultsOnInsert.js index 26ead96d73d..265d4c8fd0f 100644 --- a/lib/services/setDefaultsOnInsert.js +++ b/lib/services/setDefaultsOnInsert.js @@ -5,7 +5,7 @@ var modifiedPaths = require('./common').modifiedPaths; /** * Applies defaults to update and findOneAndUpdate operations. * - * @param {Query} query + * @param {Object} filter * @param {Schema} schema * @param {Object} castedDoc * @param {Object} options @@ -13,7 +13,7 @@ var modifiedPaths = require('./common').modifiedPaths; * @api private */ -module.exports = function(query, schema, castedDoc, options) { +module.exports = function(filter, schema, castedDoc, options) { var keys = Object.keys(castedDoc || {}); var updatedKeys = {}; var updatedValues = {}; @@ -33,11 +33,11 @@ module.exports = function(query, schema, castedDoc, options) { modifiedPaths(castedDoc, '', modified); } - var paths = Object.keys(query._conditions); + var paths = Object.keys(filter); var numPaths = paths.length; for (i = 0; i < numPaths; ++i) { var path = paths[i]; - var condition = query._conditions[path]; + var condition = filter[path]; if (condition && typeof condition === 'object') { var conditionKeys = Object.keys(condition); var numConditionKeys = conditionKeys.length; From 23da8c9eaae8388eb98aeb8fdb94b51827c16895 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 15 Oct 2017 09:52:57 -0700 Subject: [PATCH 1980/2240] test(model): repro #5708 --- test/model.test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index 6a07644a0ea..ebe2ffe8d6d 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5611,6 +5611,37 @@ describe('Model', function() { }); }); + it('bulkWrite with setDefaultsOnInsert (gh-5708)', function(done) { + var schema = new Schema({ + str: { type: String, default: 'test' }, + num: Number + }); + + var M = db.model('gh5708', schema); + + var ops = [ + { + updateOne: { + filter: { num: 0 }, + update: { + $inc: { num: 1 } + }, + upsert: true, + setDefaultsOnInsert: true + } + } + ]; + M.bulkWrite(ops, function(error) { + assert.ifError(error); + M.findOne({}).lean().exec(function(error, doc) { + assert.ifError(error); + assert.strictEqual(doc.str, 'test'); + assert.strictEqual(doc.num, 1); + done(); + }); + }); + }); + it('insertMany with Decimal (gh-5190)', function(done) { start.mongodVersion(function(err, version) { if (err) { From 1452950e6f001268d3cd26e72e32b91db60620c8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 15 Oct 2017 09:54:05 -0700 Subject: [PATCH 1981/2240] fix(model): handle setDefaultsOnInsert option for bulkWrite updateOne and updateMany Fix #5708 --- lib/model.js | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/model.js b/lib/model.js index 2c58e588bea..64a078aa917 100644 --- a/lib/model.js +++ b/lib/model.js @@ -23,6 +23,7 @@ var isPathSelectedInclusive = require('./services/projection/isPathSelectedInclu var mpath = require('mpath'); var parallel = require('async/parallel'); var parallelLimit = require('async/parallelLimit'); +var setDefaultsOnInsert = require('./services/setDefaultsOnInsert'); var util = require('util'); var utils = require('./utils'); @@ -2239,12 +2240,18 @@ Model.bulkWrite = function(ops, options, callback) { }); }; } else if (op['updateOne']) { + op = op['updateOne']; return function(callback) { try { - op['updateOne']['filter'] = cast(_this.schema, - op['updateOne']['filter']); - op['updateOne']['update'] = castUpdate(_this.schema, - op['updateOne']['update'], _this.schema.options.strict); + op['filter'] = cast(_this.schema, op['filter']); + op['update'] = castUpdate(_this.schema, op['update'], + _this.schema.options.strict); + if (op.setDefaultsOnInsert) { + setDefaultsOnInsert(op['filter'], _this.schema, op['update'], { + setDefaultsOnInsert: true, + upsert: op.upsert + }); + } } catch (error) { return callback(error); } @@ -2252,14 +2259,20 @@ Model.bulkWrite = function(ops, options, callback) { callback(null); }; } else if (op['updateMany']) { + op = op['updateMany']; return function(callback) { try { - op['updateMany']['filter'] = cast(_this.schema, - op['updateMany']['filter']); - op['updateMany']['update'] = castUpdate(_this.schema, op['updateMany']['update'], { + op['filter'] = cast(_this.schema, op['filter']); + op['update'] = castUpdate(_this.schema, op['update'], { strict: _this.schema.options.strict, overwrite: false }); + if (op.setDefaultsOnInsert) { + setDefaultsOnInsert(op['filter'], _this.schema, op['update'], { + setDefaultsOnInsert: true, + upsert: op.upsert + }); + } } catch (error) { return callback(error); } From 74f2493320e3ee457729624c1cbb63a3060e59dc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 15 Oct 2017 15:18:09 -0700 Subject: [PATCH 1982/2240] feat(connection): add createCollection() helper Fix #5712 --- lib/connection.js | 28 ++++++++++++++++++++++++++-- test/connection.test.js | 26 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 1f3cc2c5c89..ac118ad7fcd 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -368,6 +368,28 @@ Connection.prototype._openWithoutPromise = function() { }); }; +/** + * Helper for `createCollection()`. Will explicitly create the given collection + * with specified options. Used to create [capped collections](https://docs.mongodb.com/manual/core/capped-collections/) + * and [views](https://docs.mongodb.com/manual/core/views/) from mongoose. + * + * Options are passed down without modification to the [MongoDB driver's `createCollection()` function](http://mongodb.github.io/node-mongodb-native/2.2/api/Db.html#createCollection) + * + * @param {string} collection The collection to delete + * @param {Object} [options] see [MongoDB driver docs](http://mongodb.github.io/node-mongodb-native/2.2/api/Db.html#createCollection) + * @param {Function} [callback] + * @return {Promise} + * @api public + */ + +Connection.prototype.createCollection = _wrapConnHelper(function createCollection(collection, options, cb) { + if (typeof options === 'function') { + cb = options; + options = {}; + } + this.db.createCollection(collection, options, cb); +}); + /** * Helper for `dropCollection()`. Will delete the given collection, including * all documents and indexes. @@ -403,8 +425,10 @@ function _wrapConnHelper(fn) { return function() { var _this = this; var Promise = PromiseProvider.get(); - var argsWithoutCb = Array.prototype.slice.call(arguments, 0, fn.length - 1); - var cb = arguments[arguments.length - 1]; + var cb = arguments.length > 0 ? arguments[arguments.length - 1] : []; + var argsWithoutCb = typeof cb === 'function' ? + Array.prototype.slice.call(arguments, 0, arguments.length - 1) : + Array.prototype.slice.call(arguments); var promise = new Promise.ES6(function(resolve, reject) { if (_this.readyState !== STATES.connected) { _this.on('open', function() { diff --git a/test/connection.test.js b/test/connection.test.js index 50fea157b60..fc2c5aa2a4b 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -297,6 +297,32 @@ describe('connections:', function() { assert.ok(!doc); }); }); + + it('createCollection()', function() { + return conn.dropDatabase(). + then(function() { + return conn.createCollection('gh5712', { + capped: true, + size: 1024 + }); + }). + then(function() { + return conn.db.listCollections().toArray(); + }). + then(function(collections) { + var names = collections.map(function(c) { return c.name; }); + assert.ok(names.indexOf('gh5712') !== -1); + assert.ok(collections[names.indexOf('gh5712')].options.capped); + return conn.createCollection('gh5712_0'); + }). + then(function() { + return conn.db.listCollections().toArray(); + }). + then(function(collections) { + var names = collections.map(function(c) { return c.name; }); + assert.ok(names.indexOf('gh5712') !== -1); + }); + }); }); it('should allow closing a closed connection', function(done) { From fa6bce36e5eb30f979c8bc88886447466ebadc8c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 15 Oct 2017 21:10:53 -0700 Subject: [PATCH 1983/2240] refactor(error): move error.js -> error/index.js for sanity --- lib/error/browserMissingSchema.js | 2 +- lib/error/cast.js | 2 +- lib/error/disconnected.js | 2 +- lib/error/divergentArray.js | 2 +- lib/{error.js => error/index.js} | 18 +++++++++--------- lib/error/missingSchema.js | 2 +- lib/error/notFound.js | 2 +- lib/error/objectExpected.js | 2 +- lib/error/objectParameter.js | 2 +- lib/error/overwriteModel.js | 2 +- lib/error/strict.js | 2 +- lib/error/validation.js | 2 +- lib/error/validator.js | 2 +- lib/error/version.js | 2 +- 14 files changed, 22 insertions(+), 22 deletions(-) rename lib/{error.js => error/index.js} (66%) diff --git a/lib/error/browserMissingSchema.js b/lib/error/browserMissingSchema.js index 898915596db..24140f58a59 100644 --- a/lib/error/browserMissingSchema.js +++ b/lib/error/browserMissingSchema.js @@ -2,7 +2,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /*! * MissingSchema Error constructor. diff --git a/lib/error/cast.js b/lib/error/cast.js index 59e6c180736..9bd9bc91160 100644 --- a/lib/error/cast.js +++ b/lib/error/cast.js @@ -2,7 +2,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); var util = require('util'); /** diff --git a/lib/error/disconnected.js b/lib/error/disconnected.js index a8c3e12f5a0..e17f71ce0e6 100644 --- a/lib/error/disconnected.js +++ b/lib/error/disconnected.js @@ -2,7 +2,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /** * Casting Error constructor. diff --git a/lib/error/divergentArray.js b/lib/error/divergentArray.js index 473f7dc446f..de949cb0206 100644 --- a/lib/error/divergentArray.js +++ b/lib/error/divergentArray.js @@ -3,7 +3,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /*! * DivergentArrayError constructor. diff --git a/lib/error.js b/lib/error/index.js similarity index 66% rename from lib/error.js rename to lib/error/index.js index b0e8ff53f82..2dbf4963880 100644 --- a/lib/error.js +++ b/lib/error/index.js @@ -37,7 +37,7 @@ module.exports = exports = MongooseError; * @api public */ -MongooseError.messages = require('./error/messages'); +MongooseError.messages = require('./messages'); // backward compat MongooseError.Messages = MongooseError.messages; @@ -51,16 +51,16 @@ MongooseError.Messages = MongooseError.messages; * @api public */ -MongooseError.DocumentNotFoundError = require('./error/notFound'); +MongooseError.DocumentNotFoundError = require('./notFound'); /*! * Expose subclasses */ -MongooseError.CastError = require('./error/cast'); -MongooseError.ValidationError = require('./error/validation'); -MongooseError.ValidatorError = require('./error/validator'); -MongooseError.VersionError = require('./error/version'); -MongooseError.OverwriteModelError = require('./error/overwriteModel'); -MongooseError.MissingSchemaError = require('./error/missingSchema'); -MongooseError.DivergentArrayError = require('./error/divergentArray'); +MongooseError.CastError = require('./cast'); +MongooseError.ValidationError = require('./validation'); +MongooseError.ValidatorError = require('./validator'); +MongooseError.VersionError = require('./version'); +MongooseError.OverwriteModelError = require('./overwriteModel'); +MongooseError.MissingSchemaError = require('./missingSchema'); +MongooseError.DivergentArrayError = require('./divergentArray'); diff --git a/lib/error/missingSchema.js b/lib/error/missingSchema.js index a2445b40364..dacfb1c7abe 100644 --- a/lib/error/missingSchema.js +++ b/lib/error/missingSchema.js @@ -3,7 +3,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /*! * MissingSchema Error constructor. diff --git a/lib/error/notFound.js b/lib/error/notFound.js index f63f8f1bacb..fecbd8c584a 100644 --- a/lib/error/notFound.js +++ b/lib/error/notFound.js @@ -4,7 +4,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); var util = require('util'); /*! diff --git a/lib/error/objectExpected.js b/lib/error/objectExpected.js index eb764fc2df3..5a64c9debee 100644 --- a/lib/error/objectExpected.js +++ b/lib/error/objectExpected.js @@ -2,7 +2,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /** * Strict mode error constructor diff --git a/lib/error/objectParameter.js b/lib/error/objectParameter.js index bf3f74a06c7..450771b671d 100644 --- a/lib/error/objectParameter.js +++ b/lib/error/objectParameter.js @@ -2,7 +2,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /** * Constructor for errors that happen when a parameter that's expected to be diff --git a/lib/error/overwriteModel.js b/lib/error/overwriteModel.js index 85c29c8c935..27ce7fe7069 100644 --- a/lib/error/overwriteModel.js +++ b/lib/error/overwriteModel.js @@ -3,7 +3,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /*! * OverwriteModel Error constructor. diff --git a/lib/error/strict.js b/lib/error/strict.js index e0e94eded7b..2d0c108fda9 100644 --- a/lib/error/strict.js +++ b/lib/error/strict.js @@ -2,7 +2,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /** * Strict mode error constructor diff --git a/lib/error/validation.js b/lib/error/validation.js index e51af657fdd..2202d82a97b 100644 --- a/lib/error/validation.js +++ b/lib/error/validation.js @@ -2,7 +2,7 @@ * Module requirements */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); var utils = require('../utils'); /** diff --git a/lib/error/validator.js b/lib/error/validator.js index d05ea491471..d934b524a14 100644 --- a/lib/error/validator.js +++ b/lib/error/validator.js @@ -2,7 +2,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /** * Schema validator error diff --git a/lib/error/version.js b/lib/error/version.js index e509b9b5fa5..719c07f1254 100644 --- a/lib/error/version.js +++ b/lib/error/version.js @@ -4,7 +4,7 @@ * Module dependencies. */ -var MongooseError = require('../error.js'); +var MongooseError = require('./'); /** * Version Error constructor. From d9dce1bfeebe188004df58773866f14f73fea8d4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 15 Oct 2017 21:34:51 -0700 Subject: [PATCH 1984/2240] fix: correctly bubble up left/joined events for replica set Fix #5718 --- lib/drivers/node-mongodb-native/connection.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 609889564b9..17e96e7f1ac 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -204,6 +204,14 @@ NativeConnection.prototype.doOpenSet = function(fn) { : new ReplSetServers(servers, this.options.replset || this.options.replSet); this.db = new Db(this.name, server, this.options.db); + this.db.s.topology.on('left', function(data) { + _this.emit('left', data); + }); + + this.db.s.topology.on('joined', function(data) { + _this.emit('joined', data); + }); + this.db.on('fullsetup', function() { _this.emit('fullsetup'); }); From dfab80c26d8086e9f535a67075da3b5e3af7f541 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Oct 2017 08:32:24 -0700 Subject: [PATCH 1985/2240] fix(connection): emit 'reconnect' event as well as 'reconnected' for consistency with driver These two events are interchangeable, 'reconnected' is for backwards compat because that's what mongoose has always supported, but 'reconnect' is the event the driver uses. Fix #5719 --- lib/connection.js | 1 + lib/drivers/node-mongodb-native/connection.js | 2 ++ test/connection.test.js | 7 +++++++ 3 files changed, 10 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 1f3cc2c5c89..8919115629c 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -799,6 +799,7 @@ Connection.prototype.openUri = function(uri, options, callback) { // Backwards compat for mongoose 4.x db.on('reconnect', function() { _this.readyState = STATES.connected; + _this.emit('reconnect'); _this.emit('reconnected'); }); db.s.topology.on('reconnectFailed', function() { diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index 17e96e7f1ac..b92d8254716 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -162,6 +162,7 @@ function listen(conn) { }); conn.db.on('reconnect', function() { conn.readyState = STATES.connected; + conn.emit('reconnect'); conn.emit('reconnected'); conn.onOpen(); }); @@ -171,6 +172,7 @@ function listen(conn) { conn.db.on('open', function(err, db) { if (STATES.disconnected === conn.readyState && db && db.databaseName) { conn.readyState = STATES.connected; + conn.emit('reconnect'); conn.emit('reconnected'); } }); diff --git a/test/connection.test.js b/test/connection.test.js index 50fea157b60..3d97056ba27 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -94,6 +94,7 @@ describe('connections:', function() { var numConnected = 0; var numDisconnected = 0; var numReconnected = 0; + var numReconnect = 0; var numClose = 0; conn = mongoose.createConnection('mongodb://localhost:27000/mongoosetest', { useMongoClient: true @@ -105,6 +106,10 @@ describe('connections:', function() { conn.on('disconnected', function() { ++numDisconnected; }); + conn.on('reconnect', function() { + ++numReconnect; + }); + // Same as `reconnect`, just for backwards compat conn.on('reconnected', function() { ++numReconnected; }); @@ -127,6 +132,7 @@ describe('connections:', function() { assert.equal(conn.readyState, conn.states.disconnected); assert.equal(numDisconnected, 1); assert.equal(numReconnected, 0); + assert.equal(numReconnect, 0); }). then(function() { return server.start(); @@ -140,6 +146,7 @@ describe('connections:', function() { assert.equal(conn.readyState, conn.states.connected); assert.equal(numDisconnected, 1); assert.equal(numReconnected, 1); + assert.equal(numReconnect, 1); assert.equal(numClose, 0); conn.close(); From 12b2087adbedde4e5599bcdd2fbea10f60457f8c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Oct 2017 09:10:38 -0700 Subject: [PATCH 1986/2240] chore: release 4.12.3 --- History.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 1cf45cfd5db..ffff568ac93 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +4.12.3 / 2017-10-16 +=================== + * fix(connection): emit 'reconnect' event as well as 'reconnected' for consistency with driver #5719 + * fix: correctly bubble up left/joined events for replica set #5718 + * fix(connection): allow passing in `autoIndex` as top-level option rather than requiring `config.autoIndex` #5711 + * docs(connection): improve docs regarding reconnectTries, autoReconnect, and bufferMaxEntries #5711 + * fix(query): handle null with addToSet/push/pull/pullAll update validators #5710 + * fix(model): handle setDefaultsOnInsert option for bulkWrite updateOne and updateMany #5708 + * fix(query): avoid infinite recursion edge case when cloning a buffer #5702 + 4.12.2 / 2017-10-14 =================== * docs(faq): add FAQ about using arrow functions for getters/setters, virtuals, and methods #5700 diff --git a/package.json b/package.json index 2df39dd808a..96878cb9b90 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.3-pre", + "version": "4.12.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 1aa4390c52b216ff7f3210b1802d4c68488fd82d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 16 Oct 2017 09:12:04 -0700 Subject: [PATCH 1987/2240] chore: now working on 4.12.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 96878cb9b90..7ee3ffe6b3e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.3", + "version": "4.12.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From db63ef53f8f3eed1ea79c945bc0d1b6988096a23 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 17 Oct 2017 14:12:52 -0700 Subject: [PATCH 1988/2240] test(model): repro #5721 --- test/model.discriminator.test.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index db68b68b717..e473571b659 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -512,6 +512,28 @@ describe('model', function() { done(); }); + it('clone() allows reusing with different models (gh-5721)', function(done) { + var schema = new mongoose.Schema({ + name: String + }); + + var schemaExt = new mongoose.Schema({ + nameExt: String + }); + + var ModelA = db.model('gh5721_a0', schema); + ModelA.discriminator('gh5721_a1', schemaExt); + + ModelA.findOneAndUpdate({}, { $set: { name: 'test' } }, function(error) { + assert.ifError(error); + + var ModelB = db.model('gh5721_b0', schema.clone()); + ModelB.discriminator('gh5721_b1', schemaExt.clone()); + + done(); + }); + }); + it('copies query hooks (gh-5147)', function(done) { var options = { discriminatorKey: 'kind' }; From d2a4904d298c174ba9186a1ec8d18f3123ef66bf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 17 Oct 2017 14:13:10 -0700 Subject: [PATCH 1989/2240] fix(model): avoid copying recursive $$context object when creating discriminator after querying Fix #5721 --- lib/schematype.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/schematype.js b/lib/schematype.js index 779588159d2..4be2d132fa5 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -42,6 +42,13 @@ function SchemaType(path, options, instance) { this[i].apply(this, opts); } } + + Object.defineProperty(this, '$$context', { + enumerable: false, + configurable: false, + writable: true, + value: null + }); } /** From 2e326f0774824ead0a1291cc79cd18f6a4b00417 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 17 Oct 2017 14:49:58 -0700 Subject: [PATCH 1990/2240] fix(collection): ensure queued operations run on the next tick Fix #5562 --- lib/collection.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/collection.js b/lib/collection.js index d894173e440..7bc5145ecc8 100644 --- a/lib/collection.js +++ b/lib/collection.js @@ -80,7 +80,10 @@ Collection.prototype.conn; Collection.prototype.onOpen = function() { this.buffer = false; - this.doQueue(); + var _this = this; + setImmediate(function() { + _this.doQueue(); + }); }; /** From 006cb7163d23699fe4ab0eaf7a3cf67b7536a48a Mon Sep 17 00:00:00 2001 From: Sheyi Folorunsho Adekoya Date: Wed, 18 Oct 2017 13:02:25 +0100 Subject: [PATCH 1991/2240] Fixes typo in schematypes.jade Fixes typo in schematypes.jade about adding indexes --- docs/schematypes.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index 2cceb02ad2b..0411d5394e5 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -143,7 +143,7 @@ block content using schema type options. :markdown - * `index`: boolean, whether to define an on this property. + * `index`: boolean, whether to define an [index](https://docs.mongodb.com/manual/indexes/) on this property. * `unique`: boolean, whether to define a [unique index](https://docs.mongodb.com/manual/core/index-unique/) on this property. * `sparse`: boolean, whether to define a [sparse index](https://docs.mongodb.com/manual/core/index-sparse/) on this property. :js From 53856939f2e56fbf37a0dec98be3a11840acb324 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Oct 2017 09:05:51 -0700 Subject: [PATCH 1992/2240] refactor(aggregate): clean up exec() for fewer LoD violations --- lib/aggregate.js | 49 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 9d0d00f66e5..c56fec66fe7 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -626,25 +626,25 @@ Aggregate.prototype.exec = function(callback) { } var _this = this; var Promise = PromiseProvider.get(); - var options = utils.clone(this.options); + var options = utils.clone(this.options || {}); + var pipeline = this._pipeline; + var collection = this._model.collection; if (options && options.cursor) { if (options.cursor.async) { delete options.cursor.async; return new Promise.ES6(function(resolve) { - if (!_this._model.collection.buffer) { + if (!collection.buffer) { process.nextTick(function() { - var cursor = _this._model.collection. - aggregate(_this._pipeline, options || {}); + var cursor = collection.aggregate(pipeline, options); decorateCursor(cursor); resolve(cursor); callback && callback(null, cursor); }); return; } - _this._model.collection.emitter.once('queue', function() { - var cursor = _this._model.collection. - aggregate(_this._pipeline, options || {}); + collection.emitter.once('queue', function() { + var cursor = collection.aggregate(pipeline, options); decorateCursor(cursor); resolve(cursor); callback && callback(null, cursor); @@ -654,14 +654,13 @@ Aggregate.prototype.exec = function(callback) { delete options.cursor.useMongooseAggCursor; return new AggregationCursor(this); } - var cursor = this._model.collection. - aggregate(this._pipeline, this.options || {}); + var cursor = collection.aggregate(pipeline, options); decorateCursor(cursor); return cursor; } return new Promise.ES6(function(resolve, reject) { - if (!_this._pipeline.length) { + if (!pipeline.length) { var err = new Error('Aggregate has empty pipeline'); if (callback) { callback(err); @@ -672,22 +671,20 @@ Aggregate.prototype.exec = function(callback) { prepareDiscriminatorPipeline(_this); - _this._model - .collection - .aggregate(_this._pipeline, _this.options || {}, function(error, result) { - if (error) { - if (callback) { - callback(error); - } - reject(error); - return; - } + collection.aggregate(pipeline, options, function(error, result) { + if (error) { + if (callback) { + callback(error); + } + reject(error); + return; + } - if (callback) { - callback(null, result); - } - resolve(result); - }); + if (callback) { + callback(null, result); + } + resolve(result); + }); }); }; @@ -781,7 +778,7 @@ function prepareDiscriminatorPipeline(aggregate) { } else { var match = {}; match[discriminatorKey] = discriminatorValue; - aggregate._pipeline = [{$match: match}].concat(originalPipeline); + aggregate._pipeline.unshift({ $match: match }); } } } From ae2b5c9bc063235c9aac831e0796ef036b7a4fa7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Oct 2017 09:06:37 -0700 Subject: [PATCH 1993/2240] feat(AggregationCursor): run pre aggregate hooks with agg cursor --- lib/cursor/AggregationCursor.js | 15 +++++++++++---- lib/schema.js | 1 + package-lock.json | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/cursor/AggregationCursor.js b/lib/cursor/AggregationCursor.js index a56d6a54d0c..2f360731224 100644 --- a/lib/cursor/AggregationCursor.js +++ b/lib/cursor/AggregationCursor.js @@ -14,6 +14,9 @@ var util = require('util'); * in addition to several other mechanisms for loading documents from MongoDB * one at a time. * + * Creating an AggregationCursor executes the model's pre aggregate hooks, + * but **not** the model's post aggregate hooks. + * * Unless you're an advanced user, do **not** instantiate this class directly. * Use [`Aggregate#cursor()`](/docs/api.html#aggregate_Aggregate-cursor) instead. * @@ -47,13 +50,17 @@ util.inherits(AggregationCursor, Readable); function _init(model, c, agg) { if (!model.collection.buffer) { - c.cursor = model.collection.aggregate(agg._pipeline, agg.options || {}); - c.emit('cursor', c.cursor); - } else { - model.collection.emitter.once('queue', function() { + model.hooks.execPre('aggregate', agg, function() { c.cursor = model.collection.aggregate(agg._pipeline, agg.options || {}); c.emit('cursor', c.cursor); }); + } else { + model.collection.emitter.once('queue', function() { + model.hooks.execPre('aggregate', agg, function() { + c.cursor = model.collection.aggregate(agg._pipeline, agg.options || {}); + c.emit('cursor', c.cursor); + }); + }); } } diff --git a/lib/schema.js b/lib/schema.js index 177f4f012ba..49160f41d71 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -13,6 +13,7 @@ var SchemaType = require('./schematype'); var mpath = require('mpath'); var IS_KAREEM_HOOK = { + aggregate: true, count: true, find: true, findOne: true, diff --git a/package-lock.json b/package-lock.json index 98a55a69610..9b614be3b2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.12.2-pre", + "version": "4.13.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From 6478176e0aced0450aee0d395524f5ab9f8ef05c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Oct 2017 09:41:34 -0700 Subject: [PATCH 1994/2240] feat(aggregate): add pre/post aggregate middleware Fix #5251 --- lib/aggregate.js | 39 ++++++++---- test/aggregate.test.js | 137 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 159 insertions(+), 17 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index c56fec66fe7..a7d57d0b462 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -625,6 +625,7 @@ Aggregate.prototype.exec = function(callback) { throw new Error('Aggregate not bound to any Model'); } var _this = this; + var model = this._model; var Promise = PromiseProvider.get(); var options = utils.clone(this.options || {}); var pipeline = this._pipeline; @@ -671,19 +672,34 @@ Aggregate.prototype.exec = function(callback) { prepareDiscriminatorPipeline(_this); - collection.aggregate(pipeline, options, function(error, result) { + model.hooks.execPre('aggregate', _this, function(error) { if (error) { - if (callback) { - callback(error); - } - reject(error); - return; + var _opts = { error: error }; + return model.hooks.execPost('aggregate', _this, [null], _opts, function(error) { + if (callback) { + callback(error); + } + reject(error); + }); } - if (callback) { - callback(null, result); - } - resolve(result); + collection.aggregate(pipeline, options, function(error, result) { + var _opts = { error: error }; + model.hooks.execPost('aggregate', _this, [result], _opts, function(error, result) { + if (error) { + if (callback) { + callback(error); + } + reject(error); + return; + } + + if (callback) { + callback(null, result); + } + resolve(result); + }); + }); }); }); }; @@ -755,6 +771,8 @@ function isOperator(obj) { * @param {Aggregate} aggregate Aggregate to prepare */ +Aggregate._prepareDiscriminatorPipeline = prepareDiscriminatorPipeline; + function prepareDiscriminatorPipeline(aggregate) { var schema = aggregate._model.schema, discriminatorMapping = schema && schema.discriminatorMapping; @@ -783,7 +801,6 @@ function prepareDiscriminatorPipeline(aggregate) { } } - /*! * Exports */ diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 2af32acb83c..38a6f06dc26 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -337,9 +337,7 @@ describe('aggregate: ', function() { assert.equal(aggregate.near({ a: 1 }), aggregate); // Run exec so we apply discriminator pipeline - assert.throws(function() { - aggregate.exec(); - }, /Cannot read property 'aggregate' of undefined|Cannot call method 'aggregate' of undefined/); + Aggregate._prepareDiscriminatorPipeline(aggregate); assert.deepEqual(aggregate._pipeline, [{ $geoNear: { a: 1, query: { __t: 'subschema' } } }]); @@ -347,9 +345,7 @@ describe('aggregate: ', function() { aggregate._model = stub; aggregate.near({ b: 2, query: { x: 1 } }); - assert.throws(function() { - aggregate.exec(); - }, /Cannot read property 'aggregate' of undefined|Cannot call method 'aggregate' of undefined/); + Aggregate._prepareDiscriminatorPipeline(aggregate); assert.deepEqual(aggregate._pipeline, [{ $geoNear: { b: 2, query: { x: 1, __t: 'subschema' } } }]); @@ -863,6 +859,135 @@ describe('aggregate: ', function() { }); }); + describe('middleware (gh-5251)', function() { + var db; + + before(function() { + db = start(); + }); + + after(function(done) { + db.close(done); + }); + + it('pre', function(done) { + var s = new Schema({ name: String }); + + var called = 0; + s.pre('aggregate', function(next) { + ++called; + next(); + }); + + var M = db.model('gh5251', s); + + M.aggregate([{ $match: { name: 'test' } }], function(error, res) { + assert.ifError(error); + assert.deepEqual(res, []); + assert.equal(called, 1); + done(); + }); + }); + + it('post', function(done) { + var s = new Schema({ name: String }); + + var calledWith = []; + s.post('aggregate', function(res, next) { + calledWith.push(res); + next(); + }); + + var M = db.model('gh5251_post', s); + + M.aggregate([{ $match: { name: 'test' } }], function(error, res) { + assert.ifError(error); + assert.deepEqual(res, []); + assert.equal(calledWith.length, 1); + assert.deepEqual(calledWith[0], []); + done(); + }); + }); + + it('error handler with agg error', function(done) { + var s = new Schema({ name: String }); + + var calledWith = []; + s.post('aggregate', function(error, res, next) { + calledWith.push(error); + next(); + }); + + var M = db.model('gh5251_error_agg', s); + + M.aggregate([{ $fakeStage: { name: 'test' } }], function(error, res) { + assert.ok(error); + assert.equal(error.message, + 'Unrecognized pipeline stage name: \'$fakeStage\''); + assert.equal(res, null); + assert.equal(calledWith.length, 1); + assert.equal(calledWith[0], error); + done(); + }); + }); + + it('error handler with pre error', function(done) { + var s = new Schema({ name: String }); + + var calledWith = []; + s.pre('aggregate', function(next) { + next(new Error('woops')); + }); + s.post('aggregate', function(error, res, next) { + calledWith.push(error); + next(); + }); + + var M = db.model('gh5251_error', s); + + M.aggregate([{ $match: { name: 'test' } }], function(error, res) { + assert.ok(error); + assert.equal(error.message, 'woops'); + assert.equal(res, null); + assert.equal(calledWith.length, 1); + assert.equal(calledWith[0], error); + done(); + }); + }); + + it('with agg cursor', function(done) { + var s = new Schema({ name: String }); + + var calledPre = 0; + var calledPost = 0; + s.pre('aggregate', function(next) { + ++calledPre; + next(); + }); + s.post('aggregate', function(res, next) { + ++calledPost; + next(); + }); + + var M = db.model('gh5251_cursor', s); + + var numDocs = 0; + M. + aggregate([{ $match: { name: 'test' } }]). + cursor({ useMongooseAggCursor: true }). + exec(). + eachAsync(function() { + ++numDocs; + }). + then(function() { + assert.equal(numDocs, 0); + assert.equal(calledPre, 1); + assert.equal(calledPost, 0); + done(); + }); + }); + }); + it('readPref from schema (gh-5522)', function(done) { var schema = new Schema({ name: String }, { read: 'secondary' }); var M = db.model('gh5522', schema); From 46188e60e96176cff579d4fa517735cdbf5da35e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 18 Oct 2017 09:46:14 -0700 Subject: [PATCH 1995/2240] test(aggregate): fix brittle test that depends on server-produced error message --- test/aggregate.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 38a6f06dc26..80e01a5a9ce 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -922,8 +922,8 @@ describe('aggregate: ', function() { M.aggregate([{ $fakeStage: { name: 'test' } }], function(error, res) { assert.ok(error); - assert.equal(error.message, - 'Unrecognized pipeline stage name: \'$fakeStage\''); + assert.ok(error.message.indexOf('Unrecognized pipeline stage') !== -1, + error.message); assert.equal(res, null); assert.equal(calledWith.length, 1); assert.equal(calledWith[0], error); From aac3bd2edad017a597e9ff0d109e10a8f7bf5369 Mon Sep 17 00:00:00 2001 From: wlingke Date: Thu, 19 Oct 2017 11:43:46 -0700 Subject: [PATCH 1996/2240] idGetter plugin tests - confirms #5713 has been solved --- package-lock.json | 2 +- test/plugin.idGetter.test.js | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 test/plugin.idGetter.test.js diff --git a/package-lock.json b/package-lock.json index 98a55a69610..26e7972d6b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.12.2-pre", + "version": "4.12.4-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/plugin.idGetter.test.js b/test/plugin.idGetter.test.js new file mode 100644 index 00000000000..875f58d6635 --- /dev/null +++ b/test/plugin.idGetter.test.js @@ -0,0 +1,58 @@ + +/** + * Module dependencies. + */ + +var start = require('./common'), + mongoose = start.mongoose, + assert = require('power-assert'), + Schema = mongoose.Schema; + +describe('id virtual getter', function() { + it('should work as expected with an ObjectId', function(done) { + var db = start(); + + var schema = new Schema({}); + + var S = db.model('Basic', schema); + S.create({}, function(err, s) { + assert.ifError(err); + // Comparing with aliases + assert.equal(s._id.toString(), s.id); + done(); + }); + }); + + it('should be turned off when `id` option is set to false', function(done) { + var db = start(); + + var schema = new Schema({}, {id: false}); + + var S = db.model('NoIdGetter', schema); + S.create({}, function(err, s) { + assert.ifError(err); + + // Comparing with aliases + assert.equal(s.id, undefined); + done(); + }); + }); + + + it('should be turned off when the schema has a set `id` path', function(done) { + var db = start(); + + var schema = new Schema({ + id: String, + }); + + var S = db.model('NoIdGetter', schema); + S.create({ id: 'test'}, function(err, s) { + assert.ifError(err); + + // Comparing with aliases + assert.equal(s.id, 'test'); + done(); + }); + }); +}); From c6fac06295235a6e1cdcac4fb4a7631ce597a2b2 Mon Sep 17 00:00:00 2001 From: wlingke Date: Thu, 19 Oct 2017 11:50:55 -0700 Subject: [PATCH 1997/2240] clean up comments --- test/plugin.idGetter.test.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/plugin.idGetter.test.js b/test/plugin.idGetter.test.js index 875f58d6635..2ed2df03cba 100644 --- a/test/plugin.idGetter.test.js +++ b/test/plugin.idGetter.test.js @@ -17,7 +17,8 @@ describe('id virtual getter', function() { var S = db.model('Basic', schema); S.create({}, function(err, s) { assert.ifError(err); - // Comparing with aliases + + // Comparing with virtual getter assert.equal(s._id.toString(), s.id); done(); }); @@ -32,7 +33,7 @@ describe('id virtual getter', function() { S.create({}, function(err, s) { assert.ifError(err); - // Comparing with aliases + // Comparing with virtual getter assert.equal(s.id, undefined); done(); }); @@ -50,7 +51,7 @@ describe('id virtual getter', function() { S.create({ id: 'test'}, function(err, s) { assert.ifError(err); - // Comparing with aliases + // Comparing with expected value assert.equal(s.id, 'test'); done(); }); From a38203c4504f6237d9ef1c62f613aaf7816d4a66 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 19 Oct 2017 12:41:26 -0700 Subject: [PATCH 1998/2240] style: fix lint --- test/plugin.idGetter.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/plugin.idGetter.test.js b/test/plugin.idGetter.test.js index 2ed2df03cba..f68d930db14 100644 --- a/test/plugin.idGetter.test.js +++ b/test/plugin.idGetter.test.js @@ -44,7 +44,7 @@ describe('id virtual getter', function() { var db = start(); var schema = new Schema({ - id: String, + id: String }); var S = db.model('NoIdGetter', schema); From 90f4782cb332727a551c9111d1c5c57de11dd2e1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 19 Oct 2017 14:11:31 -0700 Subject: [PATCH 1999/2240] docs(schema): add notes about runSettersOnQuery to schema setters Fix #5705 --- lib/schema/string.js | 24 +++++++++++++++++++++--- lib/schematype.js | 28 ++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/schema/string.js b/lib/schema/string.js index b9bf296e88d..8b4a1842728 100644 --- a/lib/schema/string.js +++ b/lib/schema/string.js @@ -116,7 +116,7 @@ SchemaString.prototype.enum = function() { }; /** - * Adds a lowercase setter. + * Adds a lowercase [setter](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set). * * ####Example: * @@ -125,6 +125,12 @@ SchemaString.prototype.enum = function() { * var m = new M({ email: 'SomeEmail@example.COM' }); * console.log(m.email) // someemail@example.com * + * NOTE: Setters do not run on queries by default. Use the `runSettersOnQuery` option: + * + * // Must use `runSettersOnQuery` as shown below, otherwise `email` will + * // **not** be lowercased. + * M.updateOne({}, { $set: { email: 'SomeEmail@example.COM' } }, { runSettersOnQuery: true }); + * * @api public * @return {SchemaType} this */ @@ -145,7 +151,7 @@ SchemaString.prototype.lowercase = function(shouldApply) { }; /** - * Adds an uppercase setter. + * Adds an uppercase [setter](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set). * * ####Example: * @@ -154,6 +160,12 @@ SchemaString.prototype.lowercase = function(shouldApply) { * var m = new M({ caps: 'an example' }); * console.log(m.caps) // AN EXAMPLE * + * NOTE: Setters do not run on queries by default. Use the `runSettersOnQuery` option: + * + * // Must use `runSettersOnQuery` as shown below, otherwise `email` will + * // **not** be lowercased. + * M.updateOne({}, { $set: { email: 'SomeEmail@example.COM' } }, { runSettersOnQuery: true }); + * * @api public * @return {SchemaType} this */ @@ -174,7 +186,7 @@ SchemaString.prototype.uppercase = function(shouldApply) { }; /** - * Adds a trim setter. + * Adds a trim [setter](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set). * * The string value will be trimmed when set. * @@ -187,6 +199,12 @@ SchemaString.prototype.uppercase = function(shouldApply) { * var m = new M({ name: string }) * console.log(m.name.length) // 9 * + * NOTE: Setters do not run on queries by default. Use the `runSettersOnQuery` option: + * + * // Must use `runSettersOnQuery` as shown below, otherwise `email` will + * // **not** be lowercased. + * M.updateOne({}, { $set: { email: 'SomeEmail@example.COM' } }, { runSettersOnQuery: true }); + * * @api public * @return {SchemaType} this */ diff --git a/lib/schematype.js b/lib/schematype.js index 4be2d132fa5..d841a5b5ccd 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -244,25 +244,37 @@ SchemaType.prototype.sparse = function(bool) { * * You can set up email lower case normalization easily via a Mongoose setter. * - * function toLower (v) { + * function toLower(v) { * return v.toLowerCase(); * } * * var UserSchema = new Schema({ * email: { type: String, set: toLower } - * }) + * }); * - * var User = db.model('User', UserSchema) + * var User = db.model('User', UserSchema); * - * var user = new User({email: 'AVENUE@Q.COM'}) + * var user = new User({email: 'AVENUE@Q.COM'}); * console.log(user.email); // 'avenue@q.com' * * // or - * var user = new User - * user.email = 'Avenue@Q.com' - * console.log(user.email) // 'avenue@q.com' + * var user = new User(); + * user.email = 'Avenue@Q.com'; + * console.log(user.email); // 'avenue@q.com' + * + * As you can see above, setters allow you to transform the data before it stored in MongoDB. * - * As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key. + * NOTE: setters by default do **not** run on queries by default. + * + * // Will **not** run the `toLower()` setter by default. + * User.updateOne({ _id: _id }, { $set: { email: 'AVENUE@Q.COM' } }); + * + * Use the `runSettersOnQuery` option to opt-in to running setters on `User.update()`: + * + * // Turn on `runSettersOnQuery` to run the setters from your schema. + * User.updateOne({ _id: _id }, { $set: { email: 'AVENUE@Q.COM' } }, { + * runSettersOnQuery: true + * }); * * _NOTE: we could have also just used the built-in `lowercase: true` SchemaType option instead of defining our own function._ * From d8e023ef39433ede9a35b297f54f9d9290575180 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 19 Oct 2017 14:56:23 -0700 Subject: [PATCH 2000/2240] docs(middleware): add docs coverage for aggregation middleware Re: #5251 --- docs/middleware.jade | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/middleware.jade b/docs/middleware.jade index 6820563484a..a4a4779ae5b 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -6,10 +6,10 @@ block content Middleware (also called pre and post *hooks*) are functions which are passed control during execution of asynchronous functions. Middleware is specified on the schema level and is useful for writing [plugins](./plugins.html). - Mongoose 4.x has 3 types - of middleware: document middleware, model middleware, and query middleware. + Mongoose 4.x has 4 types + of middleware: document middleware, model middleware, aggregate middleware, and query middleware. Document middleware is supported for the following document functions. - In document middleware functions, `this` refers to the document. + In document middleware functions, `this` refers to the document. * [init](./api.html#document_Document-init) * [validate](./api.html#document_Document-validate) @@ -25,10 +25,16 @@ block content * [findOneAndRemove](./api.html#query_Query-findOneAndRemove) * [findOneAndUpdate](./api.html#query_Query-findOneAndUpdate) * [update](./api.html#query_Query-update) - + + Aggregate middleware is for `MyModel.aggregate()`. Aggregate middleware + executes when you call `exec()` on an aggregate object. + In aggregate middleware, `this` refers to the [aggregation object](http://mongoosejs.com/docs/api.html#model_Model.aggregate). + + * [aggregate](http://mongoosejs.com/docs/api.html#model_Model.aggregate) + Model middleware is supported for the following model functions. In model middleware functions, `this` refers to the model. - + * [insertMany](./api.html#model_Model.insertMany) All middleware types support pre and post hooks. From e3473b51d03ef50b5730810cebe3acff684569b0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 19 Oct 2017 15:27:22 -0700 Subject: [PATCH 2001/2240] feat(connection): add connection-level bufferCommands Fix #5720 --- lib/connection.js | 6 ++++++ lib/model.js | 23 +++++++++++++++++++++-- lib/schema.js | 4 ++++ test/connection.test.js | 21 +++++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index b71b2bdbcc5..c19f3e2d0ae 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -806,6 +806,12 @@ Connection.prototype.openUri = function(uri, options, callback) { this.user = options.auth.user; this.pass = options.auth.password; } + + if (options.bufferCommands != null) { + options.bufferMaxEntries = 0; + this.config.bufferCommands = options.bufferCommands; + delete options.bufferCommands; + } } this._connectionOptions = options; diff --git a/lib/model.js b/lib/model.js index 64a078aa917..8f87b4ae33b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3812,8 +3812,17 @@ Model.compile = function compile(name, schema, collectionName, connection, base) model.prototype.$__setSchema(schema); + var _userProvidedOptions = schema._userProvidedOptions || {}; + var bufferCommands = true; + if (connection.config.bufferCommands != null) { + bufferCommands = connection.config.bufferCommands; + } + if (_userProvidedOptions.bufferCommands != null) { + bufferCommands = _userProvidedOptions.bufferCommands; + } + var collectionOptions = { - bufferCommands: schema.options.bufferCommands, + bufferCommands: bufferCommands, capped: schema.options.capped }; @@ -3908,14 +3917,24 @@ Model.__subclass = function subclass(conn, schema, collection) { : _this.prototype.schema; var options = s.options || {}; + var _userProvidedOptions = s._userProvidedOptions || {}; if (!collection) { collection = _this.prototype.schema.get('collection') || utils.toCollectionName(_this.modelName, options); } + var bufferCommands = true; + if (s) { + if (conn.config.bufferCommands != null) { + bufferCommands = conn.config.bufferCommands; + } + if (_userProvidedOptions.bufferCommands != null) { + bufferCommands = _userProvidedOptions.bufferCommands; + } + } var collectionOptions = { - bufferCommands: s ? options.bufferCommands : true, + bufferCommands: bufferCommands, capped: s && options.capped }; diff --git a/lib/schema.js b/lib/schema.js index 49160f41d71..0bf6694b8b1 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -326,6 +326,10 @@ Schema.prototype.defaultOptions = function(options) { options.versionKey = false; } + this._userProvidedOptions = utils.clone(options, { + retainKeyOrder: true + }); + options = utils.options({ strict: true, bufferCommands: true, diff --git a/test/connection.test.js b/test/connection.test.js index be23ba57240..7193d7f9c67 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -1378,6 +1378,27 @@ describe('connections:', function() { }); }); + it('bufferCommands (gh-5720)', function(done) { + var opts = { useMongoClient: true, bufferCommands: false }; + var db = mongoose.createConnection('mongodb://localhost:27017/test', opts); + + var M = db.model('gh5720', new Schema({})); + assert.ok(!M.collection.buffer); + db.close(); + + opts = { useMongoClient: true, bufferCommands: true }; + db = mongoose.createConnection('mongodb://localhost:27017/test', opts); + M = db.model('gh5720', new Schema({}, { bufferCommands: false })); + assert.ok(!M.collection.buffer); + db.close(); + + opts = { useMongoClient: true, bufferCommands: true }; + db = mongoose.createConnection('mongodb://localhost:27017/test', opts); + M = db.model('gh5720', new Schema({})); + assert.ok(M.collection.buffer); + db.close(done); + }); + describe('connecting to multiple mongos nodes (gh-1037)', function() { var mongos = process.env.MONGOOSE_MULTI_MONGOS_TEST_URI; if (!mongos) { From 8e7dfb00787bf406c588c259a6b02896e1e677d9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Oct 2017 12:13:59 -0700 Subject: [PATCH 2002/2240] test(connection): repro #5714 --- test/connection.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/connection.test.js b/test/connection.test.js index 3d97056ba27..c5fa2eebbf3 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -3,6 +3,7 @@ */ var Promise = require('bluebird'); +var Q = require('q'); var assert = require('power-assert'); var muri = require('muri'); var random = require('../lib/utils').random; @@ -75,6 +76,23 @@ describe('connections:', function() { }).catch(done); }); + it('resolving with q (gh-5714)', function(done) { + var bootMongo = Q.defer(); + + var conn = mongoose.createConnection('mongodb://localhost:27017/mongoosetest', { + useMongoClient: true + }); + + conn.on('connected', function() { + bootMongo.resolve(this); + }); + + bootMongo.promise.then(function(_conn) { + assert.equal(_conn, conn); + done(); + }).catch(done); + }); + describe('connection events', function() { beforeEach(function() { this.timeout(10000); From 2445ca4116c41026c1ccc479a9b441baadbe15b3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Oct 2017 12:14:45 -0700 Subject: [PATCH 2003/2240] fix(connection): ensure connection promise helpers are removed before emitting 'connected' Fix #5714 --- lib/connection.js | 5 +++-- package-lock.json | 6 +++--- package.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 8919115629c..fc47b2c8d90 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -813,6 +813,9 @@ Connection.prototype.openUri = function(uri, options, callback) { _this.emit('timeout'); }); + delete _this.then; + delete _this.catch; + _this.db = db; _this.readyState = STATES.connected; @@ -823,8 +826,6 @@ Connection.prototype.openUri = function(uri, options, callback) { } callback && callback(null, _this); - delete _this.then; - delete _this.catch; resolve(_this); _this.emit('open'); }); diff --git a/package-lock.json b/package-lock.json index 26e7972d6b0..2a439c4b0b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2786,9 +2786,9 @@ } }, "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, "qs": { diff --git a/package.json b/package.json index 7ee3ffe6b3e..cfee0371a68 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "node-static": "0.7.7", "nsp": "~2.8.1", "power-assert": "1.4.1", - "q": "1.4.1", + "q": "1.5.1", "tbd": "0.6.4", "uglify-js": "2.7.0", "uuid": "2.0.3", From e071b575d9a791282138c54837e2a8f1d1a44c9a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Oct 2017 18:42:34 -0700 Subject: [PATCH 2004/2240] feat(populate): support setting localField and foreignField to functions Fix #5704 --- lib/model.js | 21 ++++++++++++--- test/model.populate.test.js | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index 8f87b4ae33b..8f71a4cb412 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3547,9 +3547,18 @@ function getModelsMapForPopulate(model, docs, options) { } virtual = model.schema._getVirtual(options.path); - var localField = virtual && virtual.options ? - (virtual.$nestedSchemaPath ? virtual.$nestedSchemaPath + '.' : '') + virtual.options.localField : - options.path; + var localField; + if (virtual && virtual.options) { + var virtualPrefix = virtual.$nestedSchemaPath ? + virtual.$nestedSchemaPath + '.' : ''; + if (typeof virtual.options.localField === 'function') { + localField = virtualPrefix + virtual.options.localField.call(doc); + } else { + localField = virtualPrefix + virtual.options.localField; + } + } else { + localField = options.path; + } var foreignField = virtual && virtual.options ? virtual.options.foreignField : '_id'; @@ -3564,6 +3573,12 @@ function getModelsMapForPopulate(model, docs, options) { } options.isVirtual = isVirtual; + if (typeof localField === 'function') { + localField = localField.call(doc); + } + if (typeof foreignField === 'function') { + foreignField = foreignField.call(doc); + } var ret = convertTo_id(utils.getValue(localField, doc)); var id = String(utils.getValue(foreignField, doc)); options._docs[id] = Array.isArray(ret) ? ret.slice() : ret; diff --git a/test/model.populate.test.js b/test/model.populate.test.js index b04c788258a..8bc1aa99cd0 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4448,6 +4448,59 @@ describe('model: populate:', function() { catch(done); }); + it('with functions for localField and foreignField (gh-5704)', function(done) { + var ASchema = new Schema({ + name: String + }); + + var BSchema = new Schema({ + name: String, + localField: String, + firstId: ObjectId, + secondId: ObjectId + }, { + toObject: { virtuals: true }, + toJSON: { virtuals: true } + }); + + BSchema.virtual('a', { + ref: 'gh5704', + localField: function() { return this.localField; }, + foreignField: function() { return '_id'; }, + justOne: true + }); + + var A = db.model('gh5704', ASchema); + var B = db.model('gh5704_0', BSchema); + + A.create([{ name: 'test1' }, { name: 'test2' }]). + then(function(arr) { + return B.create([ + { + name: 'b1', + localField: 'firstId', + firstId: arr[0]._id, + secondId: arr[1]._id + }, + { + name: 'b2', + localField: 'secondId', + firstId: arr[0]._id, + secondId: arr[1]._id + } + ]); + }). + then(function(b) { + return B.find().populate('a').sort([['name', 1]]).exec(); + }). + then(function(bs) { + assert.equal(bs[0].a.name, 'test1'); + assert.equal(bs[1].a.name, 'test2'); + done(); + }). + catch(done); + }); + it('with no results (gh-4284)', function(done) { var PersonSchema = new Schema({ name: String, From 3416fcc1233ebc70e428a146e6c46209a4886be7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 20 Oct 2017 18:48:59 -0700 Subject: [PATCH 2005/2240] style: fix lint --- test/model.populate.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 8bc1aa99cd0..0f434322b30 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4490,7 +4490,7 @@ describe('model: populate:', function() { } ]); }). - then(function(b) { + then(function() { return B.find().populate('a').sort([['name', 1]]).exec(); }). then(function(bs) { From 30394cde14e6a47d00897febd0cacb3165964e2c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Oct 2017 16:14:29 -0700 Subject: [PATCH 2006/2240] chore: release 4.12.4 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ffff568ac93..5e8424d3c8a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.12.4 / 2017-10-21 +=================== + * test(plugins): add coverage for idGetter with id as a schema property #5713 [wlingke](https://github.com/wlingke) + * fix(model): avoid copying recursive $$context object when creating discriminator after querying #5721 + * fix(connection): ensure connection promise helpers are removed before emitting 'connected' #5714 + * docs(schema): add notes about runSettersOnQuery to schema setters #5705 + * fix(collection): ensure queued operations run on the next tick #5562 + 4.12.3 / 2017-10-16 =================== * fix(connection): emit 'reconnect' event as well as 'reconnected' for consistency with driver #5719 diff --git a/package.json b/package.json index cfee0371a68..63e026c197c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.4-pre", + "version": "4.12.4", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From cf8ef5f3f5856cc3c15e6120b87c815b44927ea6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Oct 2017 16:23:28 -0700 Subject: [PATCH 2007/2240] chore: now working on 4.12.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 63e026c197c..6e84144fbae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.4", + "version": "4.12.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From e527264bfb81991ba04de845ad920d34f393ac57 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 21 Oct 2017 16:53:05 -0700 Subject: [PATCH 2008/2240] feat(populate): allow passing a function to virtual ref Fix #5602 --- lib/model.js | 17 +++++++++----- package-lock.json | 5 +++++ package.json | 1 + test/model.populate.test.js | 45 +++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/lib/model.js b/lib/model.js index 8f71a4cb412..a38b9f10dc6 100644 --- a/lib/model.js +++ b/lib/model.js @@ -20,6 +20,7 @@ var cast = require('./cast'); var castUpdate = require('./services/query/castUpdate'); var discriminator = require('./services/model/discriminator'); var isPathSelectedInclusive = require('./services/projection/isPathSelectedInclusive'); +var get = require('lodash.get'); var mpath = require('mpath'); var parallel = require('async/parallel'); var parallelLimit = require('async/parallelLimit'); @@ -3523,10 +3524,14 @@ function getModelsMapForPopulate(model, docs, options) { } var virtual = modelForCurrentDoc.schema._getVirtual(options.path); - if (schemaForCurrentDoc && schemaForCurrentDoc.options && schemaForCurrentDoc.options.ref) { - modelNames = [schemaForCurrentDoc.options.ref]; - } else if (virtual && virtual.options && virtual.options.ref) { - modelNames = [virtual && virtual.options && virtual.options.ref]; + var ref; + if ((ref = get(schemaForCurrentDoc, 'options.ref')) != null) { + modelNames = [ref]; + } else if ((ref = get(virtual, 'options.ref')) != null) { + if (typeof ref === 'function') { + ref = ref.call(doc, doc); + } + modelNames = [ref]; isVirtual = true; } else { // We may have a discriminator, in which case we don't want to @@ -3552,7 +3557,7 @@ function getModelsMapForPopulate(model, docs, options) { var virtualPrefix = virtual.$nestedSchemaPath ? virtual.$nestedSchemaPath + '.' : ''; if (typeof virtual.options.localField === 'function') { - localField = virtualPrefix + virtual.options.localField.call(doc); + localField = virtualPrefix + virtual.options.localField.call(doc, doc); } else { localField = virtualPrefix + virtual.options.localField; } @@ -3574,7 +3579,7 @@ function getModelsMapForPopulate(model, docs, options) { options.isVirtual = isVirtual; if (typeof localField === 'function') { - localField = localField.call(doc); + localField = localField.call(doc, doc); } if (typeof foreignField === 'function') { foreignField = foreignField.call(doc); diff --git a/package-lock.json b/package-lock.json index 078ad99841c..1947b7c2ab1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1867,6 +1867,11 @@ "lodash._isiterateecall": "3.0.9" } }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, "lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", diff --git a/package.json b/package.json index 51c5f990270..bc669264fbd 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "bson": "~1.0.4", "hooks-fixed": "2.0.0", "kareem": "1.5.0", + "lodash.get": "4.4.2", "mongodb": "2.2.33", "mpath": "0.3.0", "mpromise": "0.5.5", diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 0f434322b30..485c9b50508 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4501,6 +4501,51 @@ describe('model: populate:', function() { catch(done); }); + it('with functions for ref (gh-5602)', function(done) { + var ASchema = new Schema({ + name: String + }); + + var BSchema = new Schema({ + referencedModel: String, + aId: ObjectId + }); + + BSchema.virtual('a', { + ref: function() { return this.referencedModel; }, + localField: 'aId', + foreignField: '_id', + justOne: true + }); + + var A1 = db.model('gh5602_1', ASchema); + var A2 = db.model('gh5602_2', ASchema); + var B = db.model('gh5602_0', BSchema); + + A1.create({ name: 'a1' }). + then(function(a1) { + return A2.create({ name: 'a2' }).then(function(res) { + return [a1].concat(res); + }); + }). + then(function(as) { + return B.create([ + { name: 'test1', referencedModel: 'gh5602_1', aId: as[0]._id }, + { name: 'test2', referencedModel: 'gh5602_2', aId: as[1]._id } + ]); + }). + then(function() { + return B.find().populate('a').sort([['name', 1]]); + }). + then(function(bs) { + assert.equal(bs.length, 2); + assert.equal(bs[0].a.name, 'a1'); + assert.equal(bs[1].a.name, 'a2'); + done(); + }). + catch(done); + }); + it('with no results (gh-4284)', function(done) { var PersonSchema = new Schema({ name: String, From 245cbbc87d78eaa69d097c7f51ee0622dec4e815 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 22 Oct 2017 11:12:18 -0700 Subject: [PATCH 2009/2240] feat(query): add multipleCastError option for aggregating cast errors when casting update Fix #5609 --- lib/query.js | 4 ++ lib/services/query/castUpdate.js | 72 ++++++++++++++++++++++------- test/model.findOneAndUpdate.test.js | 20 ++++++++ 3 files changed, 79 insertions(+), 17 deletions(-) diff --git a/lib/query.js b/lib/query.js index 28e8a648586..f885eee7daf 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1981,6 +1981,7 @@ function prepareDiscriminatorCriteria(query) { * @param {Object} [options] * @param {Boolean} [options.passRawResult] if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) + * @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors. * @param {Function} [callback] optional params are (error, doc), _unless_ `passRawResult` is used, in which case params are (error, doc, writeOpResult) * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult @@ -2676,6 +2677,7 @@ Query.prototype._replaceOne = function(callback) { * @param {Object} [criteria] * @param {Object} [doc] the update command * @param {Object} [options] + * @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors. * @param {Function} [callback] optional, params are (error, writeOpResult) * @return {Query} this * @see Model.update #model_Model.update @@ -2727,6 +2729,7 @@ Query.prototype.update = function(conditions, doc, options, callback) { * @param {Object} [criteria] * @param {Object} [doc] the update command * @param {Object} [options] + @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors. * @param {Function} [callback] optional params are (error, writeOpResult) * @return {Query} this * @see Model.update #model_Model.update @@ -2777,6 +2780,7 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) { * @param {Object} [criteria] * @param {Object} [doc] the update command * @param {Object} [options] + @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors. * @param {Function} [callback] params are (error, writeOpResult) * @return {Query} this * @see Model.update #model_Model.update diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index 9417e71be18..52b11f4f82c 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -1,6 +1,7 @@ 'use strict'; var StrictModeError = require('../../error/strict'); +var ValidationError = require('../../error/validation'); var utils = require('../../utils'); /*! @@ -102,13 +103,16 @@ module.exports = function castUpdate(schema, obj, options, context) { */ function walkUpdatePath(schema, obj, op, strict, context, pref) { - var prefix = pref ? pref + '.' : '', - keys = Object.keys(obj), - i = keys.length, - hasKeys = false, - schematype, - key, - val; + var prefix = pref ? pref + '.' : ''; + var keys = Object.keys(obj); + var i = keys.length; + var hasKeys = false; + var schematype; + var key; + var val; + + var hasError = false; + var aggregatedError = new ValidationError(); var useNestedStrict = schema.options.useNestedStrict; @@ -124,9 +128,14 @@ function walkUpdatePath(schema, obj, op, strict, context, pref) { hasKeys = true; if ('$each' in val) { - obj[key] = { - $each: castUpdateVal(schematype, val.$each, op, context) - }; + try { + obj[key] = { + $each: castUpdateVal(schematype, val.$each, op, context) + }; + } catch (error) { + hasError = true; + _handleCastError(error, context, key, aggregatedError); + } if (val.$slice != null) { obj[key].$slice = val.$slice | 0; @@ -140,14 +149,22 @@ function walkUpdatePath(schema, obj, op, strict, context, pref) { obj[key].$position = val.$position; } } else { - obj[key] = castUpdateVal(schematype, val, op, context); + try { + obj[key] = castUpdateVal(schematype, val, op, context); + } catch (error) { + hasError = true; + _handleCastError(error, context, key, aggregatedError); + } } - } else if (op === '$currentDate') { + } else if ((op === '$currentDate') || (op in castOps && schematype)) { // $currentDate can take an object - obj[key] = castUpdateVal(schematype, val, op, context); - hasKeys = true; - } else if (op in castOps && schematype) { - obj[key] = castUpdateVal(schematype, val, op, context); + try { + obj[key] = castUpdateVal(schematype, val, op, context); + } catch (error) { + hasError = true; + _handleCastError(error, context, key, aggregatedError); + } + hasKeys = true; } else { var pathToCheck = (prefix + key); @@ -208,13 +225,34 @@ function walkUpdatePath(schema, obj, op, strict, context, pref) { } hasKeys = true; - obj[key] = castUpdateVal(schematype, val, op, key, context); + try { + obj[key] = castUpdateVal(schematype, val, op, key, context); + } catch (error) { + hasError = true; + _handleCastError(error, context, key, aggregatedError); + } } } } + + if (hasError) { + throw aggregatedError; + } + return hasKeys; } +/*! + * ignore + */ + +function _handleCastError(error, query, key, aggregatedError) { + if (!query.options.multipleCastError) { + throw error; + } + aggregatedError.addError(key, error); +} + /*! * These operators should be cast to numbers instead * of their path schema type. diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index 23c2f3cb4d0..c1aadd4421e 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1910,6 +1910,26 @@ describe('model: findOneAndUpdate:', function() { }); }); + it('multi cast error (gh-5609)', function(done) { + var schema = new mongoose.Schema({ + num1: Number, + num2: Number + }); + + var Model = db.model('gh5609', schema); + + var opts = { multipleCastError: true }; + Model.findOneAndUpdate({}, { num1: 'fail', num2: 'fail' }, opts, function(error) { + assert.ok(error); + assert.equal(error.name, 'ValidationError'); + assert.ok(error.errors['num1']); + assert.equal(error.errors['num1'].name, 'CastError'); + assert.ok(error.errors['num2']); + assert.equal(error.errors['num2'].name, 'CastError'); + done(); + }); + }); + it('update validators with pushing null (gh-5710)', function(done) { var schema = new mongoose.Schema({ arr: [String] From 5d9c8581e23cc8ec753407078489f3e7c245d734 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 23 Oct 2017 17:57:02 -0700 Subject: [PATCH 2010/2240] fix(model): throw sane error when customer calls `mongoose.Model()` over `mongoose.model()` Fix #2005 --- lib/model.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/model.js b/lib/model.js index 64a078aa917..00d6d2ff7c3 100644 --- a/lib/model.js +++ b/lib/model.js @@ -46,6 +46,11 @@ var VERSION_WHERE = 1, */ function Model(doc, fields, skipId) { + if (fields instanceof Schema) { + throw new TypeError('2nd argument to `Model` must be a POJO or string, ' + + '**not** a schema. Make sure you\'re calling `mongoose.model()`, not ' + + '`mongoose.Model()`.'); + } Document.call(this, doc, fields, skipId, true); } From 174ad6c63174971546cb68161990fddbf977fd74 Mon Sep 17 00:00:00 2001 From: wlingke Date: Mon, 23 Oct 2017 19:52:57 -0700 Subject: [PATCH 2011/2240] Fixes #5706. Separately also adds length check for ObjectId hex string checker. --- lib/schema/documentarray.js | 3 +++ lib/schema/embedded.js | 4 ++++ lib/schema/objectid.js | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 97ee114262c..f27542f22e9 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -11,6 +11,7 @@ var EventEmitter = require('events').EventEmitter; var MongooseDocumentArray = require('../types/documentarray'); var SchemaType = require('../schematype'); var Subdocument = require('../types/embedded'); +var applyHooks = require('../services/model/applyHooks'); var discriminator = require('../services/model/discriminator'); var util = require('util'); var utils = require('../utils'); @@ -119,6 +120,8 @@ DocumentArray.prototype.discriminator = function(name, schema) { this.casterConstructor.discriminators[name] = EmbeddedDocument; + applyHooks(EmbeddedDocument, schema); + return this.casterConstructor.discriminators[name]; }; diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index e9705626d59..7697caf6630 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -8,6 +8,7 @@ var $exists = require('./operators/exists'); var EventEmitter = require('events').EventEmitter; var SchemaType = require('../schematype'); var Subdocument = require('../types/subdocument'); +var applyHooks = require('../services/model/applyHooks'); var castToNumber = require('./operators/helpers').castToNumber; var discriminator = require('../services/model/discriminator'); var geospatial = require('./operators/geospatial'); @@ -253,5 +254,8 @@ Embedded.prototype.discriminator = function(name, schema) { discriminator(this.caster, name, schema); this.caster.discriminators[name] = _createConstructor(schema); + + applyHooks(this.caster.discriminators[name], schema); + return this.caster.discriminators[name]; }; diff --git a/lib/schema/objectid.js b/lib/schema/objectid.js index c75d82dfbb5..83c0d1ab510 100644 --- a/lib/schema/objectid.js +++ b/lib/schema/objectid.js @@ -20,7 +20,7 @@ var SchemaType = require('../schematype'), */ function ObjectId(key, options) { - var isKeyHexStr = typeof key === 'string' && /^a-f0-9$/i.test(key); + var isKeyHexStr = typeof key === 'string' && key.length === 24 && /^a-f0-9$/i.test(key); var suppressWarning = options && options.suppressWarning; if ((isKeyHexStr || typeof key === 'undefined') && !suppressWarning) { console.warn('mongoose: To create a new ObjectId please try ' + From 15ee3b59f8aac979df04799fc8e117af943d9fce Mon Sep 17 00:00:00 2001 From: Ayush Gupta Date: Tue, 24 Oct 2017 08:57:49 +0530 Subject: [PATCH 2012/2240] addFields operator and tests added --- lib/aggregate.js | 35 +++++++++++++++++++++++++++++++++++ package-lock.json | 36 ++++++++++++++++++------------------ test/aggregate.test.js | 14 ++++++++++++++ 3 files changed, 67 insertions(+), 18 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 9d0d00f66e5..c98ff13aacb 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -106,6 +106,41 @@ Aggregate.prototype.append = function() { return this; }; +/** + * Appends a new $addFields operator to this aggregate pipeline. + * Requires MongoDB v3.4+ to work + * + * ####Examples: + * + * // adding new fields based on existing fields + * aggregate.addFields({ + * newField: '$b.nested' + * , plusTen: { $add: ['$val', 10]} + * , sub: { + * name: '$a' + * } + * }) + * + * // etc + * aggregate.addFields({ salary_k: { $divide: [ "$salary", 1000 ] } }); + * + * @param {Object} arg field specification + * @see projection http://docs.mongodb.org/manual/reference/aggregation/project/ + * @return {Aggregate} + * @api public + */ +Aggregate.prototype.addFields = function(arg) { + var fields = {}; + if (typeof arg === 'object' && !util.isArray(arg)) { + Object.keys(arg).forEach(function(field) { + fields[field] = arg[field]; + }); + } else { + throw new Error('Invalid addFields() argument. Must be an object'); + } + return this.append({$addFields: fields}); +}; + /** * Appends a new $project operator to this aggregate pipeline. * diff --git a/package-lock.json b/package-lock.json index 2a439c4b0b0..ace1960d1db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.12.4-pre", + "version": "4.12.5-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2866,15 +2866,6 @@ "is-finite": "1.0.2" } }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "requires": { - "resolve-from": "2.0.0", - "semver": "5.4.1" - } - }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -2893,6 +2884,15 @@ } } }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "2.0.0", + "semver": "5.4.1" + } + }, "requirejs": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", @@ -3097,14 +3097,6 @@ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", "dev": true }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -3116,6 +3108,14 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "stringifier": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz", diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 2af32acb83c..c6aad586408 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -448,6 +448,20 @@ describe('aggregate: ', function() { }); }); + describe('project', function() { + it('(object)', function(done) { + var aggregate = new Aggregate(); + + assert.equal(aggregate.addFields({ a: 1, b: 1, c: 0 }), aggregate); + assert.deepEqual(aggregate._pipeline, [{ $addFields: { a: 1, b: 1, c: 0 } }]); + + aggregate.addFields({ d: {$add: ['$a','$b']} }); + assert.deepEqual(aggregate._pipeline, [{ $addFields: { a: 1, b: 1, c: 0 } }, { $addFields: { d: {$add: ['$a','$b']} } }]); + + done(); + }); + }); + describe('facet', function() { it('works', function(done) { var aggregate = new Aggregate(); From 45b749a526cfaf6309c6196a2dfcba1baf721822 Mon Sep 17 00:00:00 2001 From: Ayush Gupta Date: Tue, 24 Oct 2017 09:02:43 +0530 Subject: [PATCH 2013/2240] fix test name --- test/aggregate.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index c6aad586408..a5b3806762f 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -448,7 +448,7 @@ describe('aggregate: ', function() { }); }); - describe('project', function() { + describe('addFields', function() { it('(object)', function(done) { var aggregate = new Aggregate(); From 273f489bf3c804ad8bea150a1f3da2849d0464c0 Mon Sep 17 00:00:00 2001 From: Ayush Gupta Date: Tue, 24 Oct 2017 09:04:56 +0530 Subject: [PATCH 2014/2240] (docs) fix addFields link --- lib/aggregate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index c98ff13aacb..7927cb21aa4 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -125,7 +125,7 @@ Aggregate.prototype.append = function() { * aggregate.addFields({ salary_k: { $divide: [ "$salary", 1000 ] } }); * * @param {Object} arg field specification - * @see projection http://docs.mongodb.org/manual/reference/aggregation/project/ + * @see $addFields https://docs.mongodb.com/manual/reference/operator/aggregation/addFields/ * @return {Aggregate} * @api public */ From 541fb36a699edb079cc1ff5f091943eb2bef2cc6 Mon Sep 17 00:00:00 2001 From: Ayush Gupta Date: Tue, 24 Oct 2017 09:13:34 +0530 Subject: [PATCH 2015/2240] (lint): fix trailing spaces --- test/aggregate.test.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index a5b3806762f..57bc2fdcda8 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -451,13 +451,12 @@ describe('aggregate: ', function() { describe('addFields', function() { it('(object)', function(done) { var aggregate = new Aggregate(); - + assert.equal(aggregate.addFields({ a: 1, b: 1, c: 0 }), aggregate); assert.deepEqual(aggregate._pipeline, [{ $addFields: { a: 1, b: 1, c: 0 } }]); - + aggregate.addFields({ d: {$add: ['$a','$b']} }); assert.deepEqual(aggregate._pipeline, [{ $addFields: { a: 1, b: 1, c: 0 } }, { $addFields: { d: {$add: ['$a','$b']} } }]); - done(); }); }); From 8632e797bc584d758cd2fb781c633864fc2e537d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 25 Oct 2017 09:30:19 -0700 Subject: [PATCH 2016/2240] feat(model): report validation errors from `insertMany()` if using `ordered: false` and `rawResult: true` Fix #5337 --- lib/model.js | 36 ++++++++++++++++++++++++++++-------- lib/utils.js | 6 ++++++ test/model.test.js | 22 ++++++++++++++++++++++ 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/lib/model.js b/lib/model.js index c86cd0ac7e5..c6d5b28c083 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2079,6 +2079,11 @@ var INSERT_MANY_CONVERT_OPTIONS = { * because it only sends one operation to the server, rather than one for each * document. * + * Mongoose always validates each document **before** sending `insertMany` + * to MongoDB. So if one document has a validation error, no documents will + * be saved, unless you set + * [the `ordered` option to false](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#error-handling). + * * This function does **not** trigger save middleware. * * This function triggers the following middleware: @@ -2091,6 +2096,8 @@ var INSERT_MANY_CONVERT_OPTIONS = { * * @param {Array|Object|*} doc(s) * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#insertMany) + * @param {Boolean} [options.ordered = true] if true, will fail fast on the first error encountered. If false, will insert all the documents it can and report errors later. An `insertMany()` with `ordered = false` is called an "unordered" `insertMany()`. + * @param {Boolean} [options.rawResult = false] if false, the returned promise resolves to the documents that passed mongoose document validation. If `false`, will return the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~insertWriteOpCallback) with a `mongoose` property that contains `validationErrors` if this is an unordered `insertMany`. * @param {Function} [callback] callback * @return {Promise} * @api public @@ -2105,16 +2112,18 @@ Model.insertMany = function(arr, options, callback) { if (callback) { callback = this.$wrapCallback(callback); } - var limit = options && options.limit; - if (typeof limit !== 'number') { - limit = 1000; - } + callback = callback || utils.noop; + options = options || {}; + var limit = get(options, 'limit', 1000); + var rawResult = get(options, 'rawResult', false); + var ordered = get(options, 'ordered', true); if (!Array.isArray(arr)) { arr = [arr]; } var toExecute = []; + var validationErrors = []; arr.forEach(function(doc) { toExecute.push(function(callback) { doc = new _this(doc); @@ -2123,7 +2132,8 @@ Model.insertMany = function(arr, options, callback) { // Option `ordered` signals that insert should be continued after reaching // a failing insert. Therefore we delegate "null", meaning the validation // failed. It's up to the next function to filter out all failed models - if (options != null && typeof options === 'object' && options['ordered'] === false) { + if (ordered === false) { + validationErrors.push(error); return callback(null, null); } return callback(error); @@ -2144,7 +2154,7 @@ Model.insertMany = function(arr, options, callback) { }); // Quickly escape while there aren't any valid docAttributes if (docAttributes.length < 1) { - callback && callback(null, []); + callback(null, []); return; } var docObjects = docAttributes.map(function(doc) { @@ -2157,7 +2167,7 @@ Model.insertMany = function(arr, options, callback) { return doc.toObject(INSERT_MANY_CONVERT_OPTIONS); }); - _this.collection.insertMany(docObjects, options, function(error) { + _this.collection.insertMany(docObjects, options, function(error, res) { if (error) { callback && callback(error); return; @@ -2167,7 +2177,17 @@ Model.insertMany = function(arr, options, callback) { docAttributes[i].emit('isNew', false); docAttributes[i].constructor.emit('isNew', false); } - callback && callback(null, docAttributes); + if (rawResult) { + if (ordered === false) { + // Decorate with mongoose validation errors in case of unordered, + // because then still do `insertMany()` + res.mongoose = { + validationErrors: validationErrors + }; + } + return callback(null, res); + } + callback(null, docAttributes); }); }); }; diff --git a/lib/utils.js b/lib/utils.js index 71b79fde719..8e3b719f297 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -894,3 +894,9 @@ exports.each = function(arr, fn) { fn(arr[i]); } }; + +/*! + * ignore + */ + +exports.noop = function() {}; diff --git a/test/model.test.js b/test/model.test.js index ebe2ffe8d6d..a27155a1761 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5398,6 +5398,28 @@ describe('Model', function() { }); }); + it('insertMany() multi validation error with ordered false (gh-5337)', function(done) { + var schema = new Schema({ + name: { type: String, required: true } + }); + var Movie = db.model('gh5337', schema); + + var arr = [ + { foo: 'The Phantom Menace' }, + { name: 'Star Wars' }, + { name: 'The Empire Strikes Back' }, + { foobar: 'The Force Awakens' } + ]; + var opts = { ordered: false, rawResult: true }; + Movie.insertMany(arr, opts, function(error, res) { + assert.ifError(error); + assert.equal(res.mongoose.validationErrors.length, 2); + assert.equal(res.mongoose.validationErrors[0].name, 'ValidationError'); + assert.equal(res.mongoose.validationErrors[1].name, 'ValidationError'); + done(); + }); + }); + it('insertMany() depopulate (gh-4590)', function(done) { var personSchema = new Schema({ name: String From 8d09a20c79852cb80ca72cca50d01ab4f9225a30 Mon Sep 17 00:00:00 2001 From: wlingke Date: Thu, 26 Oct 2017 10:21:49 -0700 Subject: [PATCH 2017/2240] Added test cases for #5706 --- test/model.discriminator.test.js | 121 +++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index e473571b659..769115dc686 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -842,5 +842,126 @@ describe('model', function() { }). catch(done); }); + describe('embedded discriminators + hooks (gh-5706)', function(){ + var counters = { + eventPreSave: 0, + eventPostSave: 0, + purchasePreSave: 0, + purchasePostSave: 0, + eventPreValidate: 0, + eventPostValidate: 0, + purchasePreValidate: 0, + purchasePostValidate: 0, + }; + var eventSchema = new Schema( + { message: String }, + { discriminatorKey: 'kind', _id: false } + ); + eventSchema.pre('validate', (next) => { + counters.eventPreValidate++; + next(); + }); + + eventSchema.post('validate', (doc) => { + counters.eventPostValidate++; + }); + + eventSchema.pre('save', (next) => { + counters.eventPreSave++; + next(); + }); + + eventSchema.post('save', (doc) => { + counters.eventPostSave++; + }); + + var purchasedSchema = new Schema({ + product: String, + }, { _id: false }); + + purchasedSchema.pre('validate', (next) => { + counters.purchasePreValidate++; + next(); + }); + + purchasedSchema.post('validate', (doc) => { + counters.purchasePostValidate++; + }); + + purchasedSchema.pre('save', (next) => { + counters.purchasePreSave++; + next(); + }); + + purchasedSchema.post('save', (doc) => { + counters.purchasePostSave++; + }); + + beforeEach(function() { + Object.keys(counters).forEach(function(i){ + counters[i]=0; + }) + }); + + it('should call the hooks on the embedded document defined by both the parent and discriminated schemas', function(done){ + var trackSchema = new Schema({ + event: eventSchema, + }); + + var embeddedEventSchema = trackSchema.path('event'); + embeddedEventSchema.discriminator('Purchased', purchasedSchema) + + var TrackModel = db.model('Track', trackSchema); + var doc = new TrackModel({ + event: { + message: 'Test', + kind: 'Purchased' + } + }); + doc.save(function(err){ + assert.ok(!err); + assert.equal(doc.event.message, 'Test') + assert.equal(doc.event.kind, 'Purchased') + Object.keys(counters).forEach(function(i){ + assert.equal(counters[i], 1); + }); + done(); + }) + }) + + it('should call the hooks on the embedded document in an embedded array defined by both the parent and discriminated schemas', function(done){ + var trackSchema = new Schema({ + events: [eventSchema], + }); + + var embeddedEventSchema = trackSchema.path('events'); + embeddedEventSchema.discriminator('Purchased', purchasedSchema) + + var TrackModel = db.model('Track2', trackSchema); + var doc = new TrackModel({ + events: [ + { + message: 'Test', + kind: 'Purchased' + }, + { + message: 'TestAgain', + kind: 'Purchased' + } + ] + }); + doc.save(function(err){ + assert.ok(!err); + assert.equal(doc.events[0].kind, 'Purchased'); + assert.equal(doc.events[0].message, 'Test'); + assert.equal(doc.events[1].kind, 'Purchased'); + assert.equal(doc.events[1].message, 'TestAgain'); + Object.keys(counters).forEach(function(i){ + assert.equal(counters[i], 2); + }); + done(); + }) + }) + }) }); }); From a51e1f520185beb46a0bde5236a4bf18a5fadf13 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 26 Oct 2017 10:56:57 -0700 Subject: [PATCH 2018/2240] fix(connection): handle no cb correctly for connection helpers --- lib/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index ecc4726a4bf..eb8e61133e1 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -425,7 +425,7 @@ function _wrapConnHelper(fn) { return function() { var _this = this; var Promise = PromiseProvider.get(); - var cb = arguments.length > 0 ? arguments[arguments.length - 1] : []; + var cb = arguments.length > 0 ? arguments[arguments.length - 1] : null; var argsWithoutCb = typeof cb === 'function' ? Array.prototype.slice.call(arguments, 0, arguments.length - 1) : Array.prototype.slice.call(arguments); From f0088950c01c7bfdb2f2b5b8bf746c0a0ce2b7dc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 26 Oct 2017 16:22:13 -0700 Subject: [PATCH 2019/2240] chore: bump lockfile --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 2a439c4b0b0..d9d818f0af1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.12.4-pre", + "version": "4.12.5-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From f02641c173a60e5e1e5822118b12791157d1ae1b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 26 Oct 2017 17:27:36 -0700 Subject: [PATCH 2020/2240] test(populate): repro #5737 --- test/model.populate.test.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index b04c788258a..0a19a0eec4a 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3251,6 +3251,42 @@ describe('model: populate:', function() { db.close(done); }); + it('populating an array of refs, slicing, and fetching many (gh-5737)', function(done) { + var BlogPost = db.model('gh5737_0', new Schema({ + title: String, + fans: [{ type: ObjectId, ref: 'gh5737' }] + })); + var User = db.model('gh5737', new Schema({ name: String })); + + User.create([{ name: 'Fan 1' }, { name: 'Fan 2' }], function(error, fans) { + assert.ifError(error); + var posts = [ + { title: 'Test 1', fans: [fans[0]._id, fans[1]._id] }, + { title: 'Test 2', fans: [fans[1]._id, fans[0]._id] } + ]; + BlogPost.create(posts, function(error) { + assert.ifError(error); + BlogPost. + find({}). + slice('fans', [0, 5]). + populate('fans'). + exec(function(err, blogposts) { + assert.ifError(error); + + assert.equal(blogposts[0].title, 'Test 1'); + assert.equal(blogposts[1].title, 'Test 2'); + + assert.equal(blogposts[0].fans[0].name, 'Fan 1'); + assert.equal(blogposts[0].fans[1].name, 'Fan 2'); + + assert.equal(blogposts[1].fans[0].name, 'Fan 2'); + assert.equal(blogposts[1].fans[1].name, 'Fan 1'); + done(); + }); + }); + }); + }); + it('maps results back to correct document (gh-1444)', function(done) { var articleSchema = new Schema({ body: String, From 1d87987bec5934fcdec4ce5361a1ef6087faba83 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 26 Oct 2017 17:27:57 -0700 Subject: [PATCH 2021/2240] fix(populate): handle slice projections correctly when automatically selecting populated fields Fix #5737 --- lib/query.js | 44 +++++++++++++++++++++ lib/services/query/selectPopulatedFields.js | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 28e8a648586..9db55decd67 100644 --- a/lib/query.js +++ b/lib/query.js @@ -15,6 +15,7 @@ var mquery = require('mquery'); var readPref = require('./drivers').ReadPreference; var selectPopulatedFields = require('./services/query/selectPopulatedFields'); var setDefaultsOnInsert = require('./services/setDefaultsOnInsert'); +var slice = require('sliced'); var updateValidators = require('./services/updateValidators'); var util = require('util'); var utils = require('./utils'); @@ -263,6 +264,49 @@ Query.prototype.toConstructor = function toConstructor() { * @api public */ +Query.prototype.slice = function() { + if (arguments.length === 0) { + return this; + } + + this._validate('slice'); + + var path; + var val; + + if (arguments.length === 1) { + var arg = arguments[0]; + if (typeof arg === 'object' && !Array.isArray(arg)) { + var keys = Object.keys(arg); + var numKeys = keys.length; + for (var i = 0; i < numKeys; ++i) { + this.slice(keys[i], arg[keys[i]]); + } + return this; + } + this._ensurePath('slice'); + path = this._path; + val = arguments[0]; + } else if (arguments.length === 2) { + if ('number' === typeof arguments[0]) { + this._ensurePath('slice'); + path = this._path; + val = slice(arguments); + } else { + path = arguments[0]; + val = arguments[1]; + } + } else if (arguments.length === 3) { + path = arguments[0]; + val = slice(arguments, 1); + } + + var p = {}; + p[path] = { $slice: val }; + return this.select(p); +}; + + /** * Specifies the complementary comparison value for paths specified with `where()` * diff --git a/lib/services/query/selectPopulatedFields.js b/lib/services/query/selectPopulatedFields.js index bb69f9d3f05..88b3551cbe7 100644 --- a/lib/services/query/selectPopulatedFields.js +++ b/lib/services/query/selectPopulatedFields.js @@ -41,5 +41,5 @@ function isPathInFields(userProvidedFields, path) { } cur += '.' + pieces[i]; } - return false; + return userProvidedFields[cur] != null; } From 9e3427a1df462eef8f73b98f7ac8aab5a4030fa6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 26 Oct 2017 20:48:01 -0700 Subject: [PATCH 2022/2240] fix(document): catch sync errors in document pre hooks and report as error Fix #5738 --- package-lock.json | 6 +++--- package.json | 2 +- test/document.hooks.test.js | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index d9d818f0af1..8b0b2db2b57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1402,9 +1402,9 @@ } }, "hooks-fixed": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.0.tgz", - "integrity": "sha1-oB2JTVKsf2WZu7H2PfycQR33DLo=" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.2.tgz", + "integrity": "sha512-YurCM4gQSetcrhwEtpQHhQ4M7Zo7poNGqY4kQGeBS6eZtOcT3tnNs01ThFa0jYBByAiYt1MjMjP/YApG0EnAvQ==" }, "http-errors": { "version": "1.6.2", diff --git a/package.json b/package.json index 6e84144fbae..55f7e69bb87 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "async": "2.1.4", "bson": "~1.0.4", - "hooks-fixed": "2.0.0", + "hooks-fixed": "2.0.2", "kareem": "1.5.0", "mongodb": "2.2.33", "mpath": "0.3.0", diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js index c73ff0ccd6c..6c47abdb2a3 100644 --- a/test/document.hooks.test.js +++ b/test/document.hooks.test.js @@ -763,6 +763,26 @@ describe('document: hooks:', function() { done(); }); + it('sync exceptions get passed as errors (gh-5738)', function(done) { + var bookSchema = new Schema({ title: String }); + + /* eslint-disable no-unused-vars */ + bookSchema.pre('save', function(next) { + throw new Error('woops!'); + }); + + var Book = mongoose.model('gh5738', bookSchema); + + var book = new Book({}); + + book.title = 'Professional AngularJS'; + book.save(function(error) { + assert.ok(error); + assert.equal(error.message, 'woops!'); + done(); + }); + }); + it('nested subdocs only fire once (gh-3281)', function(done) { var L3Schema = new Schema({ title: String From b9ab446706d8af0ba6d0181af7ca38e599b5d303 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 Oct 2017 18:59:06 -0700 Subject: [PATCH 2023/2240] refactor(test): remove unnecessary code --- test/document.hooks.test.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/document.hooks.test.js b/test/document.hooks.test.js index 6c47abdb2a3..948831f8f39 100644 --- a/test/document.hooks.test.js +++ b/test/document.hooks.test.js @@ -773,9 +773,7 @@ describe('document: hooks:', function() { var Book = mongoose.model('gh5738', bookSchema); - var book = new Book({}); - - book.title = 'Professional AngularJS'; + var book = new Book({ title: 'Professional AngularJS' }); book.save(function(error) { assert.ok(error); assert.equal(error.message, 'woops!'); From 3b4211ea8b01dd76a6170a0a9504d04109a91daa Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Oct 2017 00:23:44 -0700 Subject: [PATCH 2024/2240] test(query): repro #5744 --- test/model.update.test.js | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/test/model.update.test.js b/test/model.update.test.js index 69c3c977ea1..0659d61f8f3 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2711,7 +2711,7 @@ describe('model: update:', function() { User.update({}, update, opts).exec(function(error) { assert.ok(error); - assert.ok(error.errors['notifications']); + assert.ok(error.errors['notifications.message']); update.$pull.notifications.message = 'test'; User.update({ _id: doc._id }, update, opts).exec(function(error) { @@ -2726,6 +2726,36 @@ describe('model: update:', function() { }); }); + it('$pull with updateValidators and $in (gh-5744)', function(done) { + var exampleSchema = mongoose.Schema({ + subdocuments: [{ + name: String + }] + }); + var ExampleModel = db.model('gh5744', exampleSchema); + var exampleDocument = { + subdocuments: [{ name: 'First' }, { name: 'Second' }] + }; + + ExampleModel.create(exampleDocument, function(error, doc) { + assert.ifError(error); + ExampleModel.updateOne({ _id: doc._id }, { + $pull: { + subdocuments: { + _id: { $in: [doc.subdocuments[0]._id] } + } + } + }, { runValidators: true }, function(error) { + assert.ifError(error); + ExampleModel.findOne({ _id: doc._id }, function(error, doc) { + assert.ifError(error); + assert.equal(doc.subdocuments.length, 1); + done(); + }); + }); + }); + }); + it('update with Decimal type (gh-5361)', function(done) { start.mongodVersion(function(err, version) { if (err) { From 85821d9cd07a78310eaafa5f4357d25f730224b6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Oct 2017 00:23:51 -0700 Subject: [PATCH 2025/2240] fix(query): correctly handle `$in` and required for $pull and update validators Fix #5744 --- lib/services/updateValidators.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 326d0b169a2..f283fd7e3c2 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -33,8 +33,8 @@ module.exports = function(query, schema, castedDoc, options) { for (var i = 0; i < numKeys; ++i) { if (keys[i].charAt(0) === '$') { - if (keys[i] === '$push' || keys[i] === '$addToSet' || - keys[i] === '$pull' || keys[i] === '$pullAll') { + hasDollarUpdate = true; + if (keys[i] === '$push' || keys[i] === '$addToSet') { _keys = Object.keys(castedDoc[keys[i]]); for (var ii = 0; ii < _keys.length; ++ii) { currentUpdate = castedDoc[keys[i]][_keys[ii]]; @@ -55,14 +55,14 @@ module.exports = function(query, schema, castedDoc, options) { for (var j = 0; j < numPaths; ++j) { var updatedPath = paths[j].replace('.$.', '.0.'); updatedPath = updatedPath.replace(/\.\$$/, '.0'); - if (keys[i] === '$set' || keys[i] === '$setOnInsert') { + if (keys[i] === '$set' || keys[i] === '$setOnInsert' || + keys[i] === '$pull' || keys[i] === '$pullAll') { updatedValues[updatedPath] = flat[paths[j]]; } else if (keys[i] === '$unset') { updatedValues[updatedPath] = undefined; } updatedKeys[updatedPath] = true; } - hasDollarUpdate = true; } } From 9c709e1730592d695955a5f67c8459fa0f846537 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Oct 2017 13:03:34 -0700 Subject: [PATCH 2026/2240] refactor: reduce number of array accesses --- lib/services/updateValidators.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index f283fd7e3c2..0453f7eac53 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -30,6 +30,7 @@ module.exports = function(query, schema, castedDoc, options) { var hasDollarUpdate = false; var modified = {}; var currentUpdate; + var key; for (var i = 0; i < numKeys; ++i) { if (keys[i].charAt(0) === '$') { @@ -55,10 +56,11 @@ module.exports = function(query, schema, castedDoc, options) { for (var j = 0; j < numPaths; ++j) { var updatedPath = paths[j].replace('.$.', '.0.'); updatedPath = updatedPath.replace(/\.\$$/, '.0'); - if (keys[i] === '$set' || keys[i] === '$setOnInsert' || - keys[i] === '$pull' || keys[i] === '$pullAll') { + key = keys[i]; + if (keys === '$set' || keys === '$setOnInsert' || + keys === '$pull' || keys === '$pullAll') { updatedValues[updatedPath] = flat[paths[j]]; - } else if (keys[i] === '$unset') { + } else if (key === '$unset') { updatedValues[updatedPath] = undefined; } updatedKeys[updatedPath] = true; From 411db6192d46a711e4bc33c06e3328969ba2b626 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Oct 2017 13:06:57 -0700 Subject: [PATCH 2027/2240] fix: remove typo that was breaking tests --- lib/services/updateValidators.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/updateValidators.js b/lib/services/updateValidators.js index 0453f7eac53..0d0be0857f2 100644 --- a/lib/services/updateValidators.js +++ b/lib/services/updateValidators.js @@ -57,8 +57,8 @@ module.exports = function(query, schema, castedDoc, options) { var updatedPath = paths[j].replace('.$.', '.0.'); updatedPath = updatedPath.replace(/\.\$$/, '.0'); key = keys[i]; - if (keys === '$set' || keys === '$setOnInsert' || - keys === '$pull' || keys === '$pullAll') { + if (key === '$set' || key === '$setOnInsert' || + key === '$pull' || key === '$pullAll') { updatedValues[updatedPath] = flat[paths[j]]; } else if (key === '$unset') { updatedValues[updatedPath] = undefined; From 4d9d71b37fec057c40f2943d74439844db7eeeb3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Oct 2017 19:16:18 -0700 Subject: [PATCH 2028/2240] test(discriminator): fix tests re: #5757 --- test/model.discriminator.test.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 769115dc686..8f3eed47316 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -857,21 +857,21 @@ describe('model', function() { { message: String }, { discriminatorKey: 'kind', _id: false } ); - eventSchema.pre('validate', (next) => { + eventSchema.pre('validate', function(next) { counters.eventPreValidate++; next(); }); - eventSchema.post('validate', (doc) => { + eventSchema.post('validate', function(doc) { counters.eventPostValidate++; }); - eventSchema.pre('save', (next) => { + eventSchema.pre('save', function(next) { counters.eventPreSave++; next(); }); - eventSchema.post('save', (doc) => { + eventSchema.post('save', function(doc) { counters.eventPostSave++; }); @@ -879,28 +879,28 @@ describe('model', function() { product: String, }, { _id: false }); - purchasedSchema.pre('validate', (next) => { + purchasedSchema.pre('validate', function(next) { counters.purchasePreValidate++; next(); }); - purchasedSchema.post('validate', (doc) => { + purchasedSchema.post('validate', function(doc) { counters.purchasePostValidate++; }); - purchasedSchema.pre('save', (next) => { + purchasedSchema.pre('save', function(next) { counters.purchasePreSave++; next(); }); - purchasedSchema.post('save', (doc) => { + purchasedSchema.post('save', function(doc) { counters.purchasePostSave++; }); beforeEach(function() { - Object.keys(counters).forEach(function(i){ - counters[i]=0; - }) + Object.keys(counters).forEach(function(i) { + counters[i] = 0; + }); }); it('should call the hooks on the embedded document defined by both the parent and discriminated schemas', function(done){ @@ -909,7 +909,7 @@ describe('model', function() { }); var embeddedEventSchema = trackSchema.path('event'); - embeddedEventSchema.discriminator('Purchased', purchasedSchema) + embeddedEventSchema.discriminator('Purchased', purchasedSchema.clone()); var TrackModel = db.model('Track', trackSchema); var doc = new TrackModel({ @@ -922,7 +922,7 @@ describe('model', function() { assert.ok(!err); assert.equal(doc.event.message, 'Test') assert.equal(doc.event.kind, 'Purchased') - Object.keys(counters).forEach(function(i){ + Object.keys(counters).forEach(function(i) { assert.equal(counters[i], 1); }); done(); @@ -935,7 +935,7 @@ describe('model', function() { }); var embeddedEventSchema = trackSchema.path('events'); - embeddedEventSchema.discriminator('Purchased', purchasedSchema) + embeddedEventSchema.discriminator('Purchased', purchasedSchema.clone()); var TrackModel = db.model('Track2', trackSchema); var doc = new TrackModel({ @@ -956,7 +956,7 @@ describe('model', function() { assert.equal(doc.events[0].message, 'Test'); assert.equal(doc.events[1].kind, 'Purchased'); assert.equal(doc.events[1].message, 'TestAgain'); - Object.keys(counters).forEach(function(i){ + Object.keys(counters).forEach(function(i) { assert.equal(counters[i], 2); }); done(); From ae78242fb4fecdafabd269c0f3d4e58aead2bbb5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 28 Oct 2017 19:33:48 -0700 Subject: [PATCH 2029/2240] chore: release 4.12.5 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 5e8424d3c8a..cf09366f5f6 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +4.12.5 / 2017-10-28 +=================== + * fix(query): correctly handle `$in` and required for $pull and update validators #5744 + * feat(aggegate): add $addFields pipeline operator #5740 [AyushG3112](https://github.com/AyushG3112) + * fix(document): catch sync errors in document pre hooks and report as error #5738 + * fix(populate): handle slice projections correctly when automatically selecting populated fields #5737 + * fix(discriminator): fix hooks for embedded discriminators #5706 [wlingke](https://github.com/wlingke) + * fix(model): throw sane error when customer calls `mongoose.Model()` over `mongoose.model()` #2005 + 4.12.4 / 2017-10-21 =================== * test(plugins): add coverage for idGetter with id as a schema property #5713 [wlingke](https://github.com/wlingke) diff --git a/package.json b/package.json index 55f7e69bb87..5d6c7fb1b81 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.5-pre", + "version": "4.12.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From c83b4161f5bbf77fc6e2689bfb1e2067dfc01400 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 Oct 2017 22:44:28 -0700 Subject: [PATCH 2030/2240] chore: fix date --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index cf09366f5f6..cfd80ff6aea 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -4.12.5 / 2017-10-28 +4.12.5 / 2017-10-29 =================== * fix(query): correctly handle `$in` and required for $pull and update validators #5744 * feat(aggegate): add $addFields pipeline operator #5740 [AyushG3112](https://github.com/AyushG3112) From 65cc9099f1b046d9403edcee3eb92a27df5f019d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 29 Oct 2017 22:44:44 -0700 Subject: [PATCH 2031/2240] chore: now working on 4.12.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5d6c7fb1b81..a0c5e67a96e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.5", + "version": "4.12.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4138ce5723e9fb58286c5ede57d805dfdbf17e2d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Oct 2017 12:33:03 -0700 Subject: [PATCH 2032/2240] chore: bump lockfile --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 8b0b2db2b57..ac5a35b7c1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.12.5-pre", + "version": "4.12.6-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From 43fb08626fa788b397801a8e9d7824a9960d85fe Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Oct 2017 12:36:07 -0700 Subject: [PATCH 2033/2240] test(schema): repro #5752 --- test/schema.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/schema.test.js b/test/schema.test.js index 8f21b8e40bc..a378e2c6543 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1669,6 +1669,20 @@ describe('schema', function() { done(); }); + it('clone() copies methods, statics, and query helpers (gh-5752)', function(done) { + var schema = new Schema({}); + + schema.methods.fakeMethod = function() { return 'fakeMethod'; }; + schema.statics.fakeStatic = function() { return 'fakeStatic'; }; + schema.query.fakeQueryHelper = function() { return 'fakeQueryHelper'; }; + + var clone = schema.clone(); + assert.equal(clone.methods.fakeMethod, schema.methods.fakeMethod); + assert.equal(clone.statics.fakeStatic, schema.statics.fakeStatic); + assert.equal(clone.query.fakeQueryHelper, schema.query.fakeQueryHelper); + done(); + }); + it('clone() copies validators declared with validate() (gh-5607)', function(done) { var schema = new Schema({ num: Number From f43a984e31049bc2c8b65df617e0779d4c6b3178 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Oct 2017 12:36:19 -0700 Subject: [PATCH 2034/2240] fix(schema): make clone() copy query helpers correctly Fix #5752 --- lib/schema.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 52ec2bae076..48acab99cb2 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -298,11 +298,13 @@ Schema.prototype.tree; Schema.prototype.clone = function() { var s = new Schema(this.paths, this.options); // Clone the call queue + var cloneOpts = { retainKeyOrder: true }; s.callQueue = this.callQueue.map(function(f) { return f; }); - s.methods = utils.clone(this.methods); - s.statics = utils.clone(this.statics); + s.methods = utils.clone(this.methods, cloneOpts); + s.statics = utils.clone(this.statics, cloneOpts); + s.query = utils.clone(this.query, cloneOpts); s.plugins = Array.prototype.slice.call(this.plugins); - s._indexes = utils.clone(this._indexes); + s._indexes = utils.clone(this._indexes, cloneOpts); s.s.hooks = this.s.hooks.clone(); return s; }; From 2068a4bfabdbb7a282d0bacca9750186586c83af Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Oct 2017 13:25:49 -0700 Subject: [PATCH 2035/2240] refactor: get rid of weird setFunction, just use $set internally re: #1939 --- lib/document.js | 68 ++++++++++++++++++++------------ lib/schema.js | 3 +- lib/services/document/compile.js | 4 +- package-lock.json | 38 ++++++++---------- 4 files changed, 62 insertions(+), 51 deletions(-) diff --git a/lib/document.js b/lib/document.js index 718485fdc5d..0a489eb5494 100644 --- a/lib/document.js +++ b/lib/document.js @@ -435,8 +435,18 @@ function init(self, obj, doc, prefix) { */ for (var k in hooks) { - if (k === 'pre' || k === 'post') { + if (k === 'post') { Document.prototype['$' + k] = Document['$' + k] = hooks[k]; + } else if (k === 'pre') { + Document.prototype.$pre = Document.$pre = function mongoosePreWrapper() { + if (arguments[0] === 'set') { + // Make set hooks also work for `$set` + var $setArgs = Array.prototype.slice.call(arguments); + $setArgs[0] = '$set'; + hooks.pre.apply(this, $setArgs); + } + return hooks.pre.apply(this, arguments); + }; } else { Document.prototype[k] = Document[k] = hooks[k]; } @@ -468,29 +478,7 @@ Document.prototype.update = function update() { }; /** - * Sets the value of a path, or many paths. - * - * ####Example: - * - * // path, value - * doc.set(path, value) - * - * // object - * doc.set({ - * path : value - * , path2 : { - * path : value - * } - * }) - * - * // on-the-fly cast to number - * doc.set(path, value, Number) - * - * // on-the-fly cast to string - * doc.set(path, value, String) - * - * // changing strict mode behavior - * doc.set(path, value, { strict: false }); + * Alias for `set()`, used internally to avoid conflicts * * @param {String|Object} path path or object of key/vals to set * @param {Any} val the value to set @@ -785,8 +773,36 @@ Document.prototype.$set = function(path, val, type, options) { return this; }; -/*! - * ignore +/** + * Sets the value of a path, or many paths. + * + * ####Example: + * + * // path, value + * doc.set(path, value) + * + * // object + * doc.set({ + * path : value + * , path2 : { + * path : value + * } + * }) + * + * // on-the-fly cast to number + * doc.set(path, value, Number) + * + * // on-the-fly cast to string + * doc.set(path, value, String) + * + * // changing strict mode behavior + * doc.set(path, value, { strict: false }); + * + * @param {String|Object} path path or object of key/vals to set + * @param {Any} val the value to set + * @param {Schema|String|Number|Buffer|*} [type] optionally specify a type for "on-the-fly" attributes + * @param {Object} [options] optionally specify options that modify the behavior of the set + * @api public */ Document.prototype.set = Document.prototype.$set; diff --git a/lib/schema.js b/lib/schema.js index 714fed8a524..c9f57ab442e 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -349,8 +349,7 @@ Schema.prototype.defaultOptions = function(options) { noVirtualId: false, // deprecated, use { id: false } id: true, typeKey: 'type', - retainKeyOrder: false, - setFunction: 'set' + retainKeyOrder: false }, options); if (options.read) { diff --git a/lib/services/document/compile.js b/lib/services/document/compile.js index e5b329cf1c1..2c282fc9b7a 100644 --- a/lib/services/document/compile.js +++ b/lib/services/document/compile.js @@ -127,7 +127,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { v = v.toObject({ transform: false }); } var doc = this.$__.scope || this; - return doc[doc.schema.options.setFunction](path, v); + return doc.$set(path, v); } }); } else { @@ -138,7 +138,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { return this.get.call(this.$__.scope || this, path); }, set: function(v) { - return this[this.schema.options.setFunction].call(this.$__.scope || this, path, v); + return this.$set.call(this.$__.scope || this, path, v); } }); } diff --git a/package-lock.json b/package-lock.json index d53497c699b..b687e5885cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,10 +1,6 @@ { "name": "mongoose", -<<<<<<< HEAD "version": "4.13.0-pre", -======= - "version": "4.12.6-pre", ->>>>>>> master "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2875,6 +2871,15 @@ "is-finite": "1.0.2" } }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "2.0.0", + "semver": "5.4.1" + } + }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -2893,15 +2898,6 @@ } } }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "requires": { - "resolve-from": "2.0.0", - "semver": "5.4.1" - } - }, "requirejs": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", @@ -3106,6 +3102,14 @@ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", "dev": true }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -3117,14 +3121,6 @@ "strip-ansi": "3.0.1" } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "stringifier": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz", From 01bf20962b2ebe22ac37211a39ab0ae66c96d7fc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Oct 2017 15:31:19 -0700 Subject: [PATCH 2036/2240] feat(schema): allow using set as a schema path Fix #1939 --- lib/schema.js | 1 - test/document.test.js | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index c9f57ab442e..9ddc9f0febf 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -443,7 +443,6 @@ reserved.get = reserved.modelName = reserved.save = reserved.schema = -reserved.set = reserved.toObject = reserved.validate = reserved.remove = diff --git a/test/document.test.js b/test/document.test.js index 270c8c551b5..3eec0b11b06 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4750,6 +4750,24 @@ describe('document', function() { }); }); + it('Using set as a schema path (gh-1939)', function(done) { + var testSchema = new Schema({ set: String }); + + var Test = db.model('gh1939', testSchema); + + var t = new Test({ set: 'test 1' }); + assert.equal(t.set, 'test 1'); + t.save(function(error) { + assert.ifError(error); + t.set = 'test 2'; + t.save(function(error) { + assert.ifError(error); + assert.equal(t.set, 'test 2'); + done(); + }); + }); + }); + it('Single nested subdocs using discriminator can be modified (gh-5693)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', From 5ec995cc611d836bf3b4cfd68be1768842f4d159 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Oct 2017 19:38:20 -0700 Subject: [PATCH 2037/2240] chore: disable travis email spam --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8623517fbe0..d8ab5987c52 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,3 +18,5 @@ script: - npm test - npm run lint - npm run nsp +notifications: + email: false From 64fd96861eaaff27893cd32b0066a2e32825f5ce Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 31 Oct 2017 11:11:44 -0700 Subject: [PATCH 2038/2240] fix: undeprecate `ensureIndex()` and use it by default Fix #3280 --- lib/drivers/node-mongodb-native/collection.js | 7 ---- lib/model.js | 38 +++++++++++++++---- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js index 6b190338c85..c23f75239d7 100644 --- a/lib/drivers/node-mongodb-native/collection.js +++ b/lib/drivers/node-mongodb-native/collection.js @@ -156,13 +156,6 @@ for (var i in Collection.prototype) { iter(i); } -/*! - * ignore - */ - -Collection.prototype.ensureIndex = util.deprecate(Collection.prototype.ensureIndex, - '`ensureIndex()` is deprecated in Mongoose >= 4.12.0, use `createIndex()` instead'); - /** * Debug print helper * diff --git a/lib/model.js b/lib/model.js index 00d6d2ff7c3..85bde0c4517 100644 --- a/lib/model.js +++ b/lib/model.js @@ -935,7 +935,7 @@ Model.init = function init(callback) { * * ####Example: * - * Event.createIndexes(function (err) { + * Event.ensureIndexes(function (err) { * if (err) return handleError(err); * }); * @@ -958,14 +958,14 @@ Model.init = function init(callback) { * @api public */ -Model.createIndexes = Model.ensureIndexes = function createIndexes(options, callback) { +Model.ensureIndexes = function ensureIndexes(options, callback) { if (typeof options === 'function') { callback = options; options = null; } if (options && options.__noPromise) { - _createIndexes(this, options, callback); + _ensureIndexes(this, options, callback); return; } @@ -976,7 +976,7 @@ Model.createIndexes = Model.ensureIndexes = function createIndexes(options, call var _this = this; var Promise = PromiseProvider.get(); return new Promise.ES6(function(resolve, reject) { - _createIndexes(_this, options || {}, function(error) { + _ensureIndexes(_this, options || {}, function(error) { if (error) { callback && callback(error); reject(error); @@ -987,8 +987,31 @@ Model.createIndexes = Model.ensureIndexes = function createIndexes(options, call }); }; -function _createIndexes(model, options, callback) { +/** + * Similar to `ensureIndexes()`, except for it uses the [`createIndex`](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#createIndex) + * function. The `ensureIndex()` function checks to see if an index with that + * name already exists, and, if not, does not attempt to create the index. + * `createIndex()` bypasses this check. + * + * @param {Object} [options] internal options + * @param {Function} [cb] optional callback + * @return {Promise} + * @api public + */ + +Model.createIndexes = function createIndexes(options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + options = options || {}; + options.createIndex = true; + return this.ensureIndexes(options, callback); +}; + +function _ensureIndexes(model, options, callback) { var indexes = model.schema.indexes(); + options = options || {}; var done = function(err) { if (err && model.schema.options.emitIndexErrors) { @@ -1015,7 +1038,7 @@ function _createIndexes(model, options, callback) { }; var create = function() { - if (options && options._automatic) { + if (options._automatic) { if (model.schema.options.autoIndex === false || (model.schema.options.autoIndex == null && model.db.config.autoIndex === false)) { return done(); @@ -1030,7 +1053,8 @@ function _createIndexes(model, options, callback) { _handleSafe(options); indexSingleStart(indexFields, options); - model.collection.createIndex(indexFields, indexOptions, utils.tick(function(err, name) { + var methodName = options.createIndex ? 'createIndex' : 'ensureIndex'; + model.collection[methodName](indexFields, indexOptions, utils.tick(function(err, name) { indexSingleDone(err, indexFields, indexOptions, name); if (err) { return done(err); From 65df02e45faf945d8cd8bfdfc06f3fc5c3479295 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 31 Oct 2017 11:15:39 -0700 Subject: [PATCH 2039/2240] style: fix lint --- lib/drivers/node-mongodb-native/collection.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js index c23f75239d7..a5378a72e09 100644 --- a/lib/drivers/node-mongodb-native/collection.js +++ b/lib/drivers/node-mongodb-native/collection.js @@ -4,7 +4,6 @@ var MongooseCollection = require('../../collection'); var Collection = require('mongodb').Collection; -var util = require('util'); var utils = require('../../utils'); /** From 9153ae43f41342f07800ebc8b8b6361d6441d3ce Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 1 Nov 2017 08:55:14 -0700 Subject: [PATCH 2040/2240] chore: release 4.12.6 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index cfd80ff6aea..7df838a038a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +4.12.6 / 2017-11-01 +=================== + * fix(schema): make clone() copy query helpers correctly #5752 + * fix: undeprecate `ensureIndex()` and use it by default #3280 + 4.12.5 / 2017-10-29 =================== * fix(query): correctly handle `$in` and required for $pull and update validators #5744 diff --git a/package.json b/package.json index a0c5e67a96e..e3113f67125 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.6-pre", + "version": "4.12.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a48219b66930d9408c7925afdd4340a36a552c1a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 1 Nov 2017 08:56:55 -0700 Subject: [PATCH 2041/2240] chore: now working on 4.12.7 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ac5a35b7c1c..0fb3cb7bd16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.12.6-pre", + "version": "4.12.7-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e3113f67125..29a926b8f78 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.12.6", + "version": "4.12.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ca7e915d7d53897569d4a4f86a34ac7137c00c45 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 2 Nov 2017 17:30:02 -0700 Subject: [PATCH 2042/2240] chore: release 4.13.0 --- History.md | 13 +++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 7df838a038a..af445be98e4 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,16 @@ +4.13.0 / 2017-11-02 +=================== + * feat(aggregate): add $addFields helper #5740 [AyushG3112](https://github.com/AyushG3112) + * feat(connection): add connection-level bufferCommands #5720 + * feat(connection): add createCollection() helper #5712 + * feat(populate): support setting localField and foreignField to functions #5704 #5602 + * feat(query): add multipleCastError option for aggregating cast errors when casting update #5609 + * feat(populate): allow passing a function to virtual ref #5602 + * feat(schema): add excludeIndexes option to optionally prevent collecting indexes from nested schemas #5575 + * feat(model): report validation errors from `insertMany()` if using `ordered: false` and `rawResult: true` #5337 + * feat(aggregate): add pre/post aggregate middleware #5251 + * feat(schema): allow using `set` as a schema path #1939 + 4.12.6 / 2017-11-01 =================== * fix(schema): make clone() copy query helpers correctly #5752 diff --git a/package-lock.json b/package-lock.json index b687e5885cc..53e7e7353a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.0-pre", + "version": "4.13.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index fab7f647391..2c22794a77b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.0-pre", + "version": "4.13.0", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From d373c818b9bca9757e816ca99ff8f8831546d372 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 2 Nov 2017 17:37:00 -0700 Subject: [PATCH 2043/2240] chore: now working on 4.13.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 53e7e7353a2..1cc8e02246a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.0", + "version": "4.13.1-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2c22794a77b..2cf41b11e5a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.0", + "version": "4.13.1-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4ff5f5254cf9f39389f39abb340c07888278d4bb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Nov 2017 15:52:20 -0700 Subject: [PATCH 2044/2240] test(document): repro #5780 --- test/document.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 3eec0b11b06..d0deb50bd94 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4768,6 +4768,26 @@ describe('document', function() { }); }); + it('handles array defaults correctly (gh-5780)', function(done) { + var testSchema = new Schema({ + nestedArr: { + type: [[Number]], + default: [[0, 1]] + } + }); + + var Test = db.model('gh5780', testSchema); + + var t = new Test({}); + assert.deepEqual(t.toObject().nestedArr, [[0, 1]]); + + t.nestedArr.push([1, 2]); + var t2 = new Test({}); + assert.deepEqual(t2.toObject().nestedArr, [[0, 1]]); + + done(); + }); + it('Single nested subdocs using discriminator can be modified (gh-5693)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', From e8a29bb5f276aa460465252d4f2273e833164aab Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Nov 2017 15:52:45 -0700 Subject: [PATCH 2045/2240] fix(document): pass default array as actual array rather than taking first element Fix #5780 --- lib/schema/array.js | 2 +- lib/schematype.js | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index e3d27430381..be0406b2547 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -93,7 +93,7 @@ function SchemaArray(key, cast, options, schemaOptions) { if (fn) { arr = defaultArr(); } else if (defaultArr != null) { - arr = defaultArr; + arr = arr.concat(defaultArr); } // Leave it up to `cast()` to convert the array return arr; diff --git a/lib/schematype.js b/lib/schematype.js index d841a5b5ccd..96a38579874 100644 --- a/lib/schematype.js +++ b/lib/schematype.js @@ -28,18 +28,23 @@ function SchemaType(path, options, instance) { this._index = null; this.selected; - for (var i in options) { - if (this[i] && typeof this[i] === 'function') { + for (var prop in options) { + if (this[prop] && typeof this[prop] === 'function') { // { unique: true, index: true } - if (i === 'index' && this._index) { + if (prop === 'index' && this._index) { continue; } - var opts = Array.isArray(options[i]) - ? options[i] - : [options[i]]; + var val = options[prop]; + // Special case so we don't screw up array defaults, see gh-5780 + if (prop === 'default') { + this.default(val); + continue; + } + + var opts = Array.isArray(val) ? val : [val]; - this[i].apply(this, opts); + this[prop].apply(this, opts); } } From 14eb80a1e1a1895d013dc2061a210eb2f4de4ff3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Nov 2017 17:00:59 -0700 Subject: [PATCH 2046/2240] test(model): repro #5765 --- test/model.geonear.test.js | 102 +++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 45 deletions(-) diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js index 45e0f8d2afa..be368413e92 100644 --- a/test/model.geonear.test.js +++ b/test/model.geonear.test.js @@ -1,9 +1,9 @@ +'use strict'; -var start = require('./common'), - assert = require('power-assert'), - mongoose = start.mongoose, - random = require('../lib/utils').random, - Schema = mongoose.Schema; +var start = require('./common'); +var assert = require('power-assert'); +var mongoose = start.mongoose; +var Schema = mongoose.Schema; /** * Setup @@ -23,19 +23,28 @@ function metersToRadians(m) { } describe('model', function() { - var schema; - - function getModel(db) { - return db.model('GeoNear', schema, 'geonear' + random()); - } + var schema = new Schema({ + coordinates: {type: [Number]}, + type: String, + priority: Number + }); + schema.index({ coordinates: '2dsphere' }, { background: false }); + var db; before(function() { - schema = new Schema({ - coordinates: {type: [Number], index: '2dsphere'}, - type: String - }); + db = start(); + }); + + after(function(done) { + db.close(done); }); + var count = 0; + function getModel(db) { + ++count; + return db.model('GeoNear' + count, schema, 'geonear' + count); + } + var mongo24_or_greater = false; before(function(done) { start.mongodVersion(function(err, version) { @@ -45,16 +54,14 @@ describe('model', function() { done(); }); }); + describe('geoNear', function() { it('works with legacy coordinate points', function(done) { if (!mongo24_or_greater) return done(); - var db = start(); var Geo = getModel(db); assert.ok(Geo.geoNear instanceof Function); - Geo.on('index', function(err) { - assert.ifError(err); - + Geo.init().then(function() { var geos = []; geos[0] = new Geo({ coordinates: testLocations.MONGODB_NYC_OFFICE, @@ -93,7 +100,7 @@ describe('model', function() { assert.equal(results[0].obj.coordinates[1], testLocations.MONGODB_NYC_OFFICE[1]); assert.equal(results[0].obj.id, geos[0].id); assert.ok(results[0].obj instanceof Geo); - db.close(done); + done(); }); } }); @@ -101,13 +108,10 @@ describe('model', function() { it('works with GeoJSON coordinate points', function(done) { if (!mongo24_or_greater) return done(); - var db = start(); var Geo = getModel(db); assert.ok(Geo.geoNear instanceof Function); - Geo.on('index', function(err) { - assert.ifError(err); - + Geo.init().then(function() { var geos = []; geos[0] = new Geo({ coordinates: testLocations.MONGODB_NYC_OFFICE, @@ -146,21 +150,18 @@ describe('model', function() { assert.equal(results[0].obj.coordinates[1], testLocations.MONGODB_NYC_OFFICE[1]); assert.equal(results[0].obj.id, geos[0].id); assert.ok(results[0].obj instanceof Geo); - db.close(done); + done(); }); } - }); + }).catch(done); }); it('works with lean', function(done) { if (!mongo24_or_greater) return done(); - var db = start(); var Geo = getModel(db); assert.ok(Geo.geoNear instanceof Function); - Geo.on('index', function(err) { - assert.ifError(err); - + Geo.init().then(function() { var geos = []; geos[0] = new Geo({ coordinates: testLocations.MONGODB_NYC_OFFICE, @@ -199,7 +200,7 @@ describe('model', function() { assert.equal(results[0].obj.coordinates[1], testLocations.MONGODB_NYC_OFFICE[1]); assert.equal(results[0].obj._id, geos[0].id); assert.ok(!(results[0].obj instanceof Geo)); - db.close(done); + done(); }); } }); @@ -208,12 +209,9 @@ describe('model', function() { it('throws the correct error messages', function(done) { if (!mongo24_or_greater) return done(); - var db = start(); var Geo = getModel(db); - Geo.on('index', function(err) { - assert.ifError(err); - + Geo.init().then(function() { var g = new Geo({coordinates: [10, 10], type: 'place'}); g.save(function() { Geo.geoNear('1,2', {}, function(e) { @@ -232,7 +230,7 @@ describe('model', function() { assert.ok(e); assert.equal(e.message, 'Must pass either a legacy coordinate array or GeoJSON Point to geoNear'); - db.close(done); + done(); }); }); }); @@ -240,25 +238,22 @@ describe('model', function() { }); }); }); + it('returns a promise (gh-1614)', function(done) { if (!mongo24_or_greater) return done(); - var db = start(); var Geo = getModel(db); var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION}; // using GeoJSON point var prom = Geo.geoNear(pnt, {spherical: true, maxDistance: 300}, function() {}); assert.ok(prom instanceof mongoose.Promise); - db.close(); done(); }); it('allows not passing a callback (gh-1614)', function(done) { if (!mongo24_or_greater) return done(); - var db = start(); var Geo = getModel(db); - Geo.on('index', function(err) { - assert.ifError(err); + Geo.init().then(function() { var g = new Geo({coordinates: testLocations.MONGODB_NYC_OFFICE, type: 'Point'}); g.save(function(err) { assert.ifError(err); @@ -277,19 +272,18 @@ describe('model', function() { } function finish() { - db.close(done); + done(); } promise.then(validate, assert.ifError).then(finish).end(); }); }); }); + it('promise fulfill even when no results returned', function(done) { if (!mongo24_or_greater) return done(); - var db = start(); var Geo = getModel(db); - Geo.on('index', function(err) { - assert.ifError(err); + Geo.init().then(function() { var g = new Geo({coordinates: [1, 1], type: 'Point'}); g.save(function(err) { assert.ifError(err); @@ -301,12 +295,30 @@ describe('model', function() { }); function finish() { - db.close(done); + done(); } promise.then(finish).end(); }); }); }); + + it('casts (gh-5765)', function() { + if (!mongo24_or_greater) return done(); + var Geo = getModel(db); + Geo.init().then(function() { + var g = new Geo({coordinates: [1, 1], type: 'Point', priority: 1}); + g.save(function(error) { + assert.ifError(error); + var opts = { maxDistance: 1000, query: { priority: '1' } }; + Geo.geoNear([1, 1], opts, function(error, res) { + assert.ifError(error); + assert.equal(res.length, 1); + assert.equal(res[0].priority, 1); + done(); + }); + }); + }); + }); }); }); From f1471762c5eaa879249d4c6a06a8508011a6ee1a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Nov 2017 17:01:03 -0700 Subject: [PATCH 2047/2240] fix(model): cast query option to geoNear() Fix #5765 --- lib/cast.js | 2 +- lib/model.js | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/cast.js b/lib/cast.js index be6861ef906..a2c9777628a 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -10,7 +10,7 @@ var utils = require('./utils'); var ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon']; /** - * Handles internal casting for queries + * Handles internal casting for query filters. * * @param {Schema} schema * @param {Object} obj Object to cast diff --git a/lib/model.js b/lib/model.js index ecf2ff52eee..dc09ca711dd 100644 --- a/lib/model.js +++ b/lib/model.js @@ -922,9 +922,9 @@ Model.init = function init(callback) { callback && callback(null, _this); resolve(_this); }); + } else { + resolve(_this); } - - return _this; }); return this.$init; @@ -2784,7 +2784,9 @@ Model.geoNear = function(near, options, callback) { }); } - var x, y; + var x; + var y; + var schema = this.schema; return new Promise.ES6(function(resolve, reject) { var handler = function(err, res) { @@ -2829,6 +2831,11 @@ Model.geoNear = function(near, options, callback) { } }; + if (options.query != null) { + options.query = utils.clone(options.query, { retainKeyOrder: 1 }); + cast(schema, options.query); + } + if (Array.isArray(near)) { if (near.length !== 2) { var error = new Error('If using legacy coordinates, must be an array ' + From 9665a04cad92aca4458837db2738475b42b58e4c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Nov 2017 17:06:25 -0700 Subject: [PATCH 2048/2240] style: fix lint re: #5765 --- test/model.geonear.test.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js index be368413e92..6f16351006a 100644 --- a/test/model.geonear.test.js +++ b/test/model.geonear.test.js @@ -303,18 +303,22 @@ describe('model', function() { }); }); - it('casts (gh-5765)', function() { + it('casts (gh-5765)', function(done) { if (!mongo24_or_greater) return done(); var Geo = getModel(db); Geo.init().then(function() { var g = new Geo({coordinates: [1, 1], type: 'Point', priority: 1}); g.save(function(error) { assert.ifError(error); - var opts = { maxDistance: 1000, query: { priority: '1' } }; + var opts = { + maxDistance: 1000, + query: { priority: '1' }, + spherical: true + }; Geo.geoNear([1, 1], opts, function(error, res) { assert.ifError(error); assert.equal(res.length, 1); - assert.equal(res[0].priority, 1); + assert.equal(res[0].obj.priority, 1); done(); }); }); From d28410471fe8162e16e4ba2a2a29c63b3af33b14 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 4 Nov 2017 17:24:39 -0700 Subject: [PATCH 2049/2240] refactor(test): remove duplicate 2.4 checks re: #5765 --- test/model.geonear.test.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/test/model.geonear.test.js b/test/model.geonear.test.js index 6f16351006a..ab9497d209c 100644 --- a/test/model.geonear.test.js +++ b/test/model.geonear.test.js @@ -56,8 +56,13 @@ describe('model', function() { }); describe('geoNear', function() { + beforeEach(function() { + if (!mongo24_or_greater) { + this.skip(); + } + }); + it('works with legacy coordinate points', function(done) { - if (!mongo24_or_greater) return done(); var Geo = getModel(db); assert.ok(Geo.geoNear instanceof Function); @@ -107,7 +112,6 @@ describe('model', function() { }); it('works with GeoJSON coordinate points', function(done) { - if (!mongo24_or_greater) return done(); var Geo = getModel(db); assert.ok(Geo.geoNear instanceof Function); @@ -157,7 +161,6 @@ describe('model', function() { }); it('works with lean', function(done) { - if (!mongo24_or_greater) return done(); var Geo = getModel(db); assert.ok(Geo.geoNear instanceof Function); @@ -207,8 +210,6 @@ describe('model', function() { }); it('throws the correct error messages', function(done) { - if (!mongo24_or_greater) return done(); - var Geo = getModel(db); Geo.init().then(function() { @@ -240,7 +241,6 @@ describe('model', function() { }); it('returns a promise (gh-1614)', function(done) { - if (!mongo24_or_greater) return done(); var Geo = getModel(db); var pnt = {type: 'Point', coordinates: testLocations.PORT_AUTHORITY_STATION}; @@ -251,7 +251,6 @@ describe('model', function() { }); it('allows not passing a callback (gh-1614)', function(done) { - if (!mongo24_or_greater) return done(); var Geo = getModel(db); Geo.init().then(function() { var g = new Geo({coordinates: testLocations.MONGODB_NYC_OFFICE, type: 'Point'}); @@ -281,7 +280,6 @@ describe('model', function() { }); it('promise fulfill even when no results returned', function(done) { - if (!mongo24_or_greater) return done(); var Geo = getModel(db); Geo.init().then(function() { var g = new Geo({coordinates: [1, 1], type: 'Point'}); @@ -304,7 +302,6 @@ describe('model', function() { }); it('casts (gh-5765)', function(done) { - if (!mongo24_or_greater) return done(); var Geo = getModel(db); Geo.init().then(function() { var g = new Geo({coordinates: [1, 1], type: 'Point', priority: 1}); From a12d282677e3df7b45eac82e6bbdacae2aee0fe6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 5 Nov 2017 15:48:41 -0800 Subject: [PATCH 2050/2240] test(query): repro #5775 --- test/model.discriminator.test.js | 44 +++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 8f3eed47316..729f38c6704 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -2,13 +2,13 @@ * Test dependencies. */ -var start = require('./common'), - mongoose = start.mongoose, - Schema = mongoose.Schema, - assert = require('power-assert'), - util = require('util'), - clone = require('../lib/utils').clone, - random = require('../lib/utils').random; +var start = require('./common'); +var mongoose = start.mongoose; +var Schema = mongoose.Schema; +var assert = require('power-assert'); +var util = require('util'); +var clone = require('../lib/utils').clone; +var random = require('../lib/utils').random; /** * Setup @@ -591,6 +591,36 @@ describe('model', function() { done(); }); + it('nested discriminator key with projecting in parent (gh-5775)', function(done) { + var itemSchema = new Schema({ + type: { type: String }, + active: { type: Boolean, default: true } + }, { discriminatorKey: 'type' }); + + var collectionSchema = new Schema({ + items: [itemSchema] + }); + + var s = new Schema({ count: Number }); + collectionSchema.path('items').discriminator('type1', s); + + var MyModel = db.model('Collection', collectionSchema); + var doc = { + items: [{ type: 'type1', active: false, count: 3 }] + }; + MyModel.create(doc, function(error) { + assert.ifError(error); + MyModel.findOne({}).select('items').exec(function(error, doc) { + assert.ifError(error); + assert.equal(doc.items.length, 1); + assert.equal(doc.items[0].type, 'type1'); + assert.strictEqual(doc.items[0].active, false); + assert.strictEqual(doc.items[0].count, 3); + done(); + }); + }); + }); + it('embedded discriminators with $push (gh-5009)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From 2adf1f33347955c57914747dfc8792fda1fc3d9a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 5 Nov 2017 15:50:02 -0800 Subject: [PATCH 2051/2240] fix(query): don't explicitly project in discriminator key if user projected in parent path Fix #5775 --- lib/queryhelpers.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/queryhelpers.js b/lib/queryhelpers.js index 8ce3500ea70..9f6db1eba7c 100644 --- a/lib/queryhelpers.js +++ b/lib/queryhelpers.js @@ -3,6 +3,7 @@ * Module dependencies */ +var get = require('lodash.get'); var utils = require('./utils'); /*! @@ -75,7 +76,6 @@ exports.createModel = function createModel(model, doc, fields, userProvidedField exports.applyPaths = function applyPaths(fields, schema) { // determine if query is selecting or excluding fields - var exclude; var keys; var ki; @@ -123,8 +123,25 @@ exports.applyPaths = function applyPaths(fields, schema) { } // check for parent exclusions - var root = path.split('.')[0]; - if (~excluded.indexOf(root)) return; + var pieces = path.split('.'); + var root = pieces[0]; + if (~excluded.indexOf(root)) { + return; + } + + // Special case: if user has included a parent path of a discriminator key, + // don't explicitly project in the discriminator key because that will + // project out everything else under the parent path + if (!exclude && get(type, 'options.$skipDiscriminatorCheck', false)) { + var cur = ''; + for (var i = 0; i < pieces.length; ++i) { + cur += (cur.length === 0 ? '' : '.') + pieces[i]; + var projection = get(fields, cur, false); + if (projection && typeof projection !== 'object') { + return; + } + } + } (type.selected ? selected : excluded).push(path); }; From c40b31333243ad7eecbf5ee10b610e6e3a32ebde Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Nov 2017 08:22:50 -0800 Subject: [PATCH 2052/2240] test(query): repro #5737 --- test/model.populate.test.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 37105dc4a04..2f861b79a2b 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3287,6 +3287,36 @@ describe('model: populate:', function() { }); }); + it('populate + slice (gh-5737a)', function(done) { + var BlogPost = db.model('gh5737b', new Schema({ + title: String, + user: { type: ObjectId, ref: 'gh5737a' }, + fans: [{ type: ObjectId}] + })); + var User = db.model('gh5737a', new Schema({ name: String })); + + User.create([{ name: 'Fan 1' }], function(error, fans) { + assert.ifError(error); + var posts = [ + { title: 'Test 1', user: fans[0]._id, fans: [fans[0]._id] } + ]; + BlogPost.create(posts, function(error) { + assert.ifError(error); + BlogPost. + find({}). + slice('fans', [0, 2]). + populate('user'). + exec(function(err, blogposts) { + assert.ifError(error); + + assert.equal(blogposts[0].user.name, 'Fan 1'); + assert.equal(blogposts[0].title, 'Test 1'); + done(); + }); + }); + }); + }); + it('maps results back to correct document (gh-1444)', function(done) { var articleSchema = new Schema({ body: String, From c93fdae55d0c418edb2d7e72f265f97304866f9a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Nov 2017 08:22:56 -0800 Subject: [PATCH 2053/2240] fix(query): don't treat projection with just $slice as inclusive Fix #5737 --- lib/query.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/query.js b/lib/query.js index 0485682194e..bd781e852d9 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3839,17 +3839,12 @@ Query.prototype.selectedInclusively = function selectedInclusively() { for (var i = 0; i < keys.length; ++i) { var key = keys[i]; - if (this._fields[key] === 0 || this._fields[key] === false) { - return false; - } - if (this._fields[key] && - typeof this._fields[key] === 'object' && - this._fields[key].$meta) { - return false; + if (typeof this._fields[key] !== 'object' && !!this._fields[key]) { + return true; } } - return true; + return false; }; /** From 3771f499935c899a76b4cec767bf75f1544bf0ff Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Nov 2017 08:32:59 -0800 Subject: [PATCH 2054/2240] refactor(query): move selectedInclusively() into separate helper Re: #5737 --- lib/query.js | 19 ++----------------- lib/services/projection/isInclusive.js | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 lib/services/projection/isInclusive.js diff --git a/lib/query.js b/lib/query.js index bd781e852d9..4fd66362eda 100644 --- a/lib/query.js +++ b/lib/query.js @@ -11,6 +11,7 @@ var cast = require('./cast'); var castUpdate = require('./services/query/castUpdate'); var hasDollarKeys = require('./services/query/hasDollarKeys'); var helpers = require('./queryhelpers'); +var isInclusive = require('./services/projection/isInclusive'); var mquery = require('mquery'); var readPref = require('./drivers').ReadPreference; var selectPopulatedFields = require('./services/query/selectPopulatedFields'); @@ -3828,23 +3829,7 @@ Query.prototype.centerSphere = function() { */ Query.prototype.selectedInclusively = function selectedInclusively() { - if (!this._fields) { - return false; - } - - var keys = Object.keys(this._fields); - if (keys.length === 0) { - return false; - } - - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - if (typeof this._fields[key] !== 'object' && !!this._fields[key]) { - return true; - } - } - - return false; + return isInclusive(this._fields); }; /** diff --git a/lib/services/projection/isInclusive.js b/lib/services/projection/isInclusive.js new file mode 100644 index 00000000000..e8dded7dfb3 --- /dev/null +++ b/lib/services/projection/isInclusive.js @@ -0,0 +1,24 @@ +'use strict'; + +module.exports = function isInclusive(projection) { + if (projection == null) { + return false; + } + + var props = Object.keys(projection); + var numProps = props.length; + if (numProps === 0) { + return false; + } + + for (var i = 0; i < numProps; ++i) { + var prop = props[i]; + // If field is truthy (1, true, etc.) and not an object, then this + // projection must be inclusive. If object, assume its $meta, $slice, etc. + if (typeof projection[prop] !== 'object' && !!projection[prop]) { + return true; + } + } + + return false; +}; From 77c543d7c67febb91b30366ffe2ccb26deb5211b Mon Sep 17 00:00:00 2001 From: Adam Reis Date: Tue, 7 Nov 2017 20:31:58 +1300 Subject: [PATCH 2055/2240] Accept multiple paths or array of paths to depopulate - `Document.depopulate()` now accepts an array of paths, e.g. `['some', 'path', 'other.path']` - `Document.depopulate()` now accepts space separated paths, e.g. `'some path other.path'` - Fixes #5797 --- lib/document.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/document.js b/lib/document.js index 0a489eb5494..4d0ba9190c5 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2592,12 +2592,17 @@ Document.prototype.populated = function(path, val, options) { */ Document.prototype.depopulate = function(path) { - var populatedIds = this.populated(path); - if (!populatedIds) { - return; + if (typeof path === 'string') { + path = path.split(' '); + } + for (const p of path) { + var populatedIds = this.populated(p); + if (!populatedIds) { + continue; + } + delete this.$__.populated[p]; + this.$set(p, populatedIds); } - delete this.$__.populated[path]; - this.$set(path, populatedIds); return this; }; From 3b07c00a444b51b1700615cdf64e71b8de0a1c6f Mon Sep 17 00:00:00 2001 From: Adam Reis Date: Tue, 7 Nov 2017 20:35:57 +1300 Subject: [PATCH 2056/2240] Use old school ES5 just in case --- lib/document.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/document.js b/lib/document.js index 4d0ba9190c5..b994048d380 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2595,13 +2595,13 @@ Document.prototype.depopulate = function(path) { if (typeof path === 'string') { path = path.split(' '); } - for (const p of path) { - var populatedIds = this.populated(p); + for (var i = 0; i < path.length; i++) { + var populatedIds = this.populated(path[i]); if (!populatedIds) { continue; } - delete this.$__.populated[p]; - this.$set(p, populatedIds); + delete this.$__.populated[path[i]]; + this.$set(path[i], populatedIds); } return this; }; From ab668dabb7d6f08962ceed11d2dce06e0f21f30c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 6 Nov 2017 19:00:45 -0800 Subject: [PATCH 2057/2240] test(model): repro #5779 --- test/versioning.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/versioning.test.js b/test/versioning.test.js index f60976975b1..db2e9854dc3 100644 --- a/test/versioning.test.js +++ b/test/versioning.test.js @@ -526,4 +526,31 @@ describe('versioning', function() { done(); }); }); + + it('copying doc works (gh-5779)', function(done) { + var schema = new Schema({ subdocs: [{ a: Number }] }); + var M = db.model('gh5779', schema, 'gh5779'); + var m = new M({ subdocs: [] }); + var m2; + + m.save(). + then(function() { + m2 = new M(m); + m2.subdocs.push({ a: 2 }); + return m2.save(); + }). + then(function() { + m2.subdocs[0].a = 3; + return m2.save(); + }). + then(function() { + assert.equal(m2.subdocs[0].a, 3); + return M.findById(m._id); + }). + then(function(doc) { + assert.equal(doc.subdocs[0].a, 3); + done(); + }). + catch(done); + }); }); From 060fcdfb4d8aad1293124ee601a5160efc9b360d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Nov 2017 08:13:21 -0800 Subject: [PATCH 2058/2240] fix(model): increment version when $set-ing it in a save() that requires a version bump Fix #5779 --- lib/model.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index dc09ca711dd..3970f592840 100644 --- a/lib/model.js +++ b/lib/model.js @@ -652,8 +652,13 @@ Model.prototype.$__version = function(where, delta) { } if (VERSION_INC === (VERSION_INC & this.$__.version)) { - if (!delta.$set || typeof delta.$set[key] === 'undefined') { - delta.$inc || (delta.$inc = {}); + if (get(delta.$set, key, null) != null) { + // Version key is getting set, means we'll increment the doc's version + // after a successful save, so we should set the incremented version so + // future saves don't fail (gh-5779) + ++delta.$set[key]; + } else { + delta.$inc = delta.$inc || {}; delta.$inc[key] = 1; } } From b4cf78f99671b9fb23afae2eb3cedd9327dcec76 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Nov 2017 11:23:36 -0800 Subject: [PATCH 2059/2240] fix(hooks): defer applying embedded discriminator hooks until top-level model is compiled Re: #5706 --- lib/schema/documentarray.js | 3 --- lib/schema/embedded.js | 3 --- lib/services/model/applyHooks.js | 12 ++++++++++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index f27542f22e9..97ee114262c 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -11,7 +11,6 @@ var EventEmitter = require('events').EventEmitter; var MongooseDocumentArray = require('../types/documentarray'); var SchemaType = require('../schematype'); var Subdocument = require('../types/embedded'); -var applyHooks = require('../services/model/applyHooks'); var discriminator = require('../services/model/discriminator'); var util = require('util'); var utils = require('../utils'); @@ -120,8 +119,6 @@ DocumentArray.prototype.discriminator = function(name, schema) { this.casterConstructor.discriminators[name] = EmbeddedDocument; - applyHooks(EmbeddedDocument, schema); - return this.casterConstructor.discriminators[name]; }; diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index 7697caf6630..ac64079ee0c 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -8,7 +8,6 @@ var $exists = require('./operators/exists'); var EventEmitter = require('events').EventEmitter; var SchemaType = require('../schematype'); var Subdocument = require('../types/subdocument'); -var applyHooks = require('../services/model/applyHooks'); var castToNumber = require('./operators/helpers').castToNumber; var discriminator = require('../services/model/discriminator'); var geospatial = require('./operators/geospatial'); @@ -255,7 +254,5 @@ Embedded.prototype.discriminator = function(name, schema) { this.caster.discriminators[name] = _createConstructor(schema); - applyHooks(this.caster.discriminators[name], schema); - return this.caster.discriminators[name]; }; diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index f046ac2b20d..de6c0a82597 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -24,10 +24,18 @@ function applyHooks(model, schema) { model.$appliedHooks = true; for (i = 0; i < schema.childSchemas.length; ++i) { - if (schema.childSchemas[i].model.$appliedHooks) { + var childModel = schema.childSchemas[i].model; + if (childModel.$appliedHooks) { continue; } - applyHooks(schema.childSchemas[i].model, schema.childSchemas[i].schema); + if (childModel.discriminators != null) { + keys = Object.keys(childModel.discriminators); + for (j = 0; j < keys.length; ++j) { + applyHooks(childModel.discriminators[keys[j]], + childModel.discriminators[keys[j]].schema); + } + } + applyHooks(childModel, schema.childSchemas[i].schema); } if (!q.length) { From bb6a64e121f9ed4da7cd84f1a61d1ffaf5c51f69 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Nov 2017 17:08:37 -0800 Subject: [PATCH 2060/2240] docs(discriminator): add warning to always attach hooks before calling discriminator() Fix #5706 --- test/docs/discriminators.test.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index 549f17fc6e7..f00d12e8fbf 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -283,6 +283,10 @@ describe('discriminator docs', function () { * types are stored in the same document array (within a document) rather * than the same collection. In other words, embedded discriminators let * you store subdocuments matching different schemas in the same array. + * + * As a general best practice, make sure you declare any hooks on your + * schemas **before** you use them. You should **not** call `pre()` or + * `post()` after calling `discriminator()` */ it('Embedded discriminators in arrays', function(done) { var eventSchema = new Schema({ message: String }, @@ -295,12 +299,15 @@ describe('discriminator docs', function () { // The `events` array can contain 2 different types of events, a // 'clicked' event that requires an element id that was clicked... - var Clicked = docArray.discriminator('Clicked', new Schema({ + var clickedSchema = new Schema({ element: { type: String, required: true } - }, { _id: false })); + }, { _id: false }); + // Make sure to attach any hooks to `eventSchema` and `clickedSchema` + // **before** calling `discriminator()`. + var Clicked = docArray.discriminator('Clicked', clickedSchema); // ... and a 'purchased' event that requires the product that was purchased. var Purchased = docArray.discriminator('Purchased', new Schema({ From a7eeab15bb662b28c929a920725e00cc76762e5c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Nov 2017 17:32:19 -0800 Subject: [PATCH 2061/2240] chore: release 4.13.1 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index af445be98e4..e751c8e1c9a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,14 @@ +4.13.1 / 2017-11-08 +=================== + * fix: accept multiple paths or array of paths to depopulate #5798 #5797 [adamreisnz](https://github.com/adamreisnz) + * fix(document): pass default array as actual array rather than taking first element #5780 + * fix(model): increment version when $set-ing it in a save() that requires a version bump #5779 + * fix(query): don't explicitly project in discriminator key if user projected in parent path #5775 #5754 + * fix(model): cast query option to geoNear() #5765 + * fix(query): don't treat projection with just $slice as inclusive #5737 + * fix(discriminator): defer applying embedded discriminator hooks until top-level model is compiled #5706 + * docs(discriminator): add warning to always attach hooks before calling discriminator() #5706 + 4.13.0 / 2017-11-02 =================== * feat(aggregate): add $addFields helper #5740 [AyushG3112](https://github.com/AyushG3112) diff --git a/package.json b/package.json index 2cf41b11e5a..bde02c6772b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.1-pre", + "version": "4.13.1", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 2b61adf0d3a1e8324f29f2a260935e81ed81a492 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Nov 2017 17:34:16 -0800 Subject: [PATCH 2062/2240] chore: add missing comment for docs build --- lib/services/projection/isInclusive.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/services/projection/isInclusive.js b/lib/services/projection/isInclusive.js index e8dded7dfb3..c7ed9b7a829 100644 --- a/lib/services/projection/isInclusive.js +++ b/lib/services/projection/isInclusive.js @@ -1,5 +1,9 @@ 'use strict'; +/*! + * ignore + */ + module.exports = function isInclusive(projection) { if (projection == null) { return false; From d6e1458526cd224fb3060cc3665a0e65c248308c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 8 Nov 2017 17:49:22 -0800 Subject: [PATCH 2063/2240] chore: now working on 4.13.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bde02c6772b..b807d066605 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.1", + "version": "4.13.2-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 22befbbef00bf355a905b03c21be30e566e2ca0a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 9 Nov 2017 09:32:22 -0800 Subject: [PATCH 2064/2240] docs: fix capitalization issue --- docs/populate.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/populate.jade b/docs/populate.jade index 34174d5f47e..f6c26e061ae 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -349,8 +349,8 @@ block content justOne: false }); - var Person = mongoose.model('Person', personSchema); - var Band = mongoose.model('Band', bandSchema); + var Person = mongoose.model('Person', PersonSchema); + var Band = mongoose.model('Band', BandSchema); /** * Suppose you have 2 bands: "Guns N' Roses" and "Motley Crue" From 83abbad632b594d3bd0e6e3eddde5e47ed5954bc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 10 Nov 2017 18:26:35 -0800 Subject: [PATCH 2065/2240] docs: update release-items.md --- release-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-items.md b/release-items.md index 4d0471afe64..d0589354263 100644 --- a/release-items.md +++ b/release-items.md @@ -18,7 +18,7 @@ For 4.x 0. Change to the master branch 1. execute `make docs` (when this process completes you'll be on the gh-pages branch) -2. `git commit -a -m 'docs: release 4.x.x'` +2. `git commit -a -m 'chore: website 4.x.x'` 3. `git push origin gh-pages` For 3.8.x: From a43d6dc72c7791b721c85cb624d17468f6270fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Par=C3=A9?= Date: Sat, 11 Nov 2017 14:16:34 -0500 Subject: [PATCH 2066/2240] update markdown --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b807d066605..3429412a3d5 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "istanbul": "0.4.4", "jade": "0.26.3", "lodash": "4.16.6", - "markdown": "0.3.1", + "markdown": "0.5.0", "marked": "0.3.6", "mocha": "3.2.0", "mongoose-long": "0.1.1", From e67d1f3a625d143cc5cd0035c6e6be3dad6e62f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Par=C3=A9?= Date: Sat, 11 Nov 2017 14:36:05 -0500 Subject: [PATCH 2067/2240] Add a check for node js 8 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d8ab5987c52..d20f73ff05e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: node_js sudo: false node_js: + - "8" - "7" - "6" - "5" From 68b1d2afd621433005643aa7347403d62371a9e4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Nov 2017 18:07:49 -0800 Subject: [PATCH 2068/2240] test(document): repro #5530 --- test/document.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index d0deb50bd94..146844283b5 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3830,6 +3830,21 @@ describe('document', function() { catch(done); }); + it('buffer subtype prop (gh-5530)', function(done) { + var TestSchema = new mongoose.Schema({ + uuid: { + type: Buffer, + subtype: 4 + } + }); + + var Test = db.model('gh5530', TestSchema); + + var doc = new Test({ uuid: 'test1' }); + assert.equal(doc.uuid._subtype, 4); + done(); + }); + it('runs validate hooks on single nested subdocs if not directly modified (gh-3884)', function(done) { var childSchema = new Schema({ name: { type: String }, From 910e8b2ee2a3ecb4b761cadddab9db82e9131532 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Nov 2017 18:08:05 -0800 Subject: [PATCH 2069/2240] chore: bump lockfile --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 1cc8e02246a..f6b30943cb6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.1-pre", + "version": "4.13.2-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From 89d2f3d1477de3fe852d4e1814aa5c230272e684 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 11 Nov 2017 18:08:12 -0800 Subject: [PATCH 2070/2240] feat(buffer): add support for subtype prop Fix #5530 --- lib/schema/buffer.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js index f7ca7588a36..fae169bf5f8 100644 --- a/lib/schema/buffer.js +++ b/lib/schema/buffer.js @@ -113,6 +113,9 @@ SchemaBuffer.prototype.cast = function(value, doc, init) { if (Buffer.isBuffer(value)) { if (!value || !value.isMongooseBuffer) { value = new MongooseBuffer(value, [this.path, doc]); + if (this.options.subtype != null) { + value._subtype = this.options.subtype; + } } return value; @@ -135,12 +138,36 @@ SchemaBuffer.prototype.cast = function(value, doc, init) { value = [value]; } ret = new MongooseBuffer(value, [this.path, doc]); + if (this.options.subtype != null) { + ret._subtype = this.options.subtype; + } return ret; } throw new CastError('buffer', value, this.path); }; +/** + * Sets the default [subtype](https://studio3t.com/whats-new/best-practices-uuid-mongodb/) + * for this buffer. You can find a [list of allowed subtypes here](http://api.mongodb.com/python/current/api/bson/binary.html). + * + * ####Example: + * + * var s = new Schema({ uuid: { type: Buffer, subtype: 4 }); + * var M = db.model('M', s); + * var m = new M({ uuid: 'test string' }); + * m.uuid._subtype; // 4 + * + * @param {Number} subtype the default subtype + * @return {SchemaType} this + * @api public + */ + +SchemaBuffer.prototype.subtype = function(subtype) { + this.options.subtype = subtype; + return this; +}; + /*! * ignore */ From 3e7497fc7d4a1b5984ef2391357526307c48f2bd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 12 Nov 2017 22:24:09 -0800 Subject: [PATCH 2071/2240] chore: release 4.13.2 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e751c8e1c9a..260d7f2d4a5 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +4.13.2 / 2017-11-11 +=================== + * feat(buffer): add support for subtype prop #5530 + 4.13.1 / 2017-11-08 =================== * fix: accept multiple paths or array of paths to depopulate #5798 #5797 [adamreisnz](https://github.com/adamreisnz) diff --git a/package.json b/package.json index 3429412a3d5..913a74b91f0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.2-pre", + "version": "4.13.2", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 95e548eec84a5ac0001edde3c8ae6f960e249728 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 12 Nov 2017 22:34:20 -0800 Subject: [PATCH 2072/2240] chore: now working on 4.13.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 913a74b91f0..cd50eb231e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.2", + "version": "4.13.3-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 2ed278a2a828c50bc1e5453b9448e78a726bec18 Mon Sep 17 00:00:00 2001 From: Faibk Date: Tue, 14 Nov 2017 15:56:33 +0100 Subject: [PATCH 2073/2240] fixed applyHooks for recursive embedded discriminators --- lib/services/model/applyHooks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/model/applyHooks.js b/lib/services/model/applyHooks.js index de6c0a82597..eb85bce4657 100644 --- a/lib/services/model/applyHooks.js +++ b/lib/services/model/applyHooks.js @@ -28,6 +28,7 @@ function applyHooks(model, schema) { if (childModel.$appliedHooks) { continue; } + applyHooks(childModel, schema.childSchemas[i].schema); if (childModel.discriminators != null) { keys = Object.keys(childModel.discriminators); for (j = 0; j < keys.length; ++j) { @@ -35,7 +36,6 @@ function applyHooks(model, schema) { childModel.discriminators[keys[j]].schema); } } - applyHooks(childModel, schema.childSchemas[i].schema); } if (!q.length) { From 93eb3aaefea805a6306607b6404bc1957d1c7484 Mon Sep 17 00:00:00 2001 From: Faibk Date: Tue, 14 Nov 2017 17:14:06 +0100 Subject: [PATCH 2074/2240] added test for recursive embedded discriminators --- test/docs/discriminators.test.js | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index f00d12e8fbf..6b90ce70750 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -352,4 +352,55 @@ describe('discriminator docs', function () { }). catch(done); }); + + /** + * Recursive embedded discriminators + */ + it('Recursive embedded discriminators in arrays', function(done) { + var eventSchema = new Schema({ message: String }, + { discriminatorKey: 'kind', _id: false }); + + var batchSchema = new Schema({ events: [eventSchema] }); + + var subEventSchema = new Schema({ + sub_events: [eventSchema] + }, { _id: false }); + + var SubEvent = subEventSchema.path('sub_events').discriminator('SubEvent', subEventSchema) + batchSchema.path('events').discriminator('SubEvent', subEventSchema); + + + // Create a new batch of events with different kinds + var batch = { + events: [ + { kind: 'SubEvent', sub_events: [{kind:'SubEvent', sub_events:[], message:'test1'}], message: 'hello' }, + { kind: 'SubEvent', sub_events: [{kind:'SubEvent', sub_events:[{kind:'SubEvent', sub_events:[], message:'test3'}], message:'test2'}], message: 'world' } + ] + }; + + Batch.create(batch). + then(function(doc) { + assert.equal(doc.events.length, 2); + + assert.equal(doc.events[0].sub_events[0].message, 'test1'); + assert.equal(doc.events[0].message, 'hello'); + assert.ok(doc.events[0] instanceof SubEvent); + + assert.equal(doc.events[1].sub_events[0].sub_events[0].message, 'test3'); + assert.equal(doc.events[1].message, 'world'); + assert.ok(doc.events[1] instanceof SubEvent); + + doc.events.push({kind:'SubEvent', sub_events:[{kind:'SubEvent', sub_events:[], message:'test4'}], message:'pushed'}); + return doc.save(); + }). + then(function(doc) { + assert.equal(doc.events.length, 3); + + assert.equal(doc.events[2].message, 'pushed'); + assert.ok(doc.events[2].sub_events[0] instanceof SubEvent); + + done(); + }). + catch(done); + }); }); From d5fd152ef5372eb72f6a9b2bea9f789fa95cbea6 Mon Sep 17 00:00:00 2001 From: Faibk Date: Tue, 14 Nov 2017 17:17:50 +0100 Subject: [PATCH 2075/2240] fixed typo in test --- test/docs/discriminators.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index 6b90ce70750..739fb37cb3d 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -369,6 +369,7 @@ describe('discriminator docs', function () { var SubEvent = subEventSchema.path('sub_events').discriminator('SubEvent', subEventSchema) batchSchema.path('events').discriminator('SubEvent', subEventSchema); + var Batch = db.model('EventBatch', batchSchema); // Create a new batch of events with different kinds var batch = { From dce067b33209de884f58c53616a80521dff6441e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 14 Nov 2017 22:56:41 -0800 Subject: [PATCH 2076/2240] test(document): repro #5807 --- test/document.test.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 146844283b5..152a3902611 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -1908,6 +1908,38 @@ describe('document', function() { }); }); + it('single nested schema transform with save() (gh-5807)', function() { + var embeddedSchema = new Schema({ + test: String + }); + + var called = false; + embeddedSchema.options.toObject = { + transform: function(doc, ret) { + called = true; + delete ret.test; + return ret; + } + }; + var topLevelSchema = new Schema({ + embedded: embeddedSchema + }); + var MyModel = db.model('gh5807', topLevelSchema); + + return MyModel.create({}). + then(function(doc) { + doc.embedded = { test: '123' }; + return doc.save(); + }). + then(function(doc) { + return MyModel.findById(doc._id); + }). + then(function(doc) { + assert.equal(doc.embedded.test, '123'); + assert.ok(!called); + }); + }); + it('setters firing with objects on real paths (gh-2943)', function(done) { var M = mongoose.model('gh2943', { myStr: { From 20fc0abf52383911bc78e4181b61667bc7f2edcf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 14 Nov 2017 22:58:12 -0800 Subject: [PATCH 2077/2240] fix(document): don't apply transforms to nested docs when updating already saved doc Fix #5807 --- lib/model.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 3970f592840..bbbdc124806 100644 --- a/lib/model.js +++ b/lib/model.js @@ -553,7 +553,13 @@ Model.prototype.$__delta = function() { value = value.toObject(); operand(this, where, delta, data, value); } else { - value = utils.clone(value, {depopulate: 1, _isNested: true}); + value = utils.clone(value, { + depopulate: true, + transform: false, + virtuals: false, + retainKeyOrder: true, + _isNested: true + }); operand(this, where, delta, data, value); } } From 3c9a5c1dc92b86cb46783711f0564aeecb88a32c Mon Sep 17 00:00:00 2001 From: Faibk Date: Thu, 16 Nov 2017 00:07:40 +0100 Subject: [PATCH 2078/2240] fixed variables in test --- test/docs/discriminators.test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index 739fb37cb3d..7b2e9a0e927 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -357,29 +357,29 @@ describe('discriminator docs', function () { * Recursive embedded discriminators */ it('Recursive embedded discriminators in arrays', function(done) { - var eventSchema = new Schema({ message: String }, + var singleEventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); - var batchSchema = new Schema({ events: [eventSchema] }); + var eventListSchema = new Schema({ events: [singleEventSchema] }); var subEventSchema = new Schema({ - sub_events: [eventSchema] + sub_events: [singleEventSchema] }, { _id: false }); var SubEvent = subEventSchema.path('sub_events').discriminator('SubEvent', subEventSchema) - batchSchema.path('events').discriminator('SubEvent', subEventSchema); + eventList.path('events').discriminator('SubEvent', subEventSchema); - var Batch = db.model('EventBatch', batchSchema); + var Eventlist = db.model('EventList', eventList); // Create a new batch of events with different kinds - var batch = { + var list = { events: [ { kind: 'SubEvent', sub_events: [{kind:'SubEvent', sub_events:[], message:'test1'}], message: 'hello' }, { kind: 'SubEvent', sub_events: [{kind:'SubEvent', sub_events:[{kind:'SubEvent', sub_events:[], message:'test3'}], message:'test2'}], message: 'world' } ] }; - Batch.create(batch). + Eventlist.create(list). then(function(doc) { assert.equal(doc.events.length, 2); From 484e32b435f6e8973697f79e5035a5a8ac14dd4f Mon Sep 17 00:00:00 2001 From: Faibk Date: Thu, 16 Nov 2017 00:12:26 +0100 Subject: [PATCH 2079/2240] another typo --- test/docs/discriminators.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index 7b2e9a0e927..3d3f18ce0e6 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -367,9 +367,9 @@ describe('discriminator docs', function () { }, { _id: false }); var SubEvent = subEventSchema.path('sub_events').discriminator('SubEvent', subEventSchema) - eventList.path('events').discriminator('SubEvent', subEventSchema); + eventListSchema.path('events').discriminator('SubEvent', subEventSchema); - var Eventlist = db.model('EventList', eventList); + var Eventlist = db.model('EventList', eventListSchema); // Create a new batch of events with different kinds var list = { From 76da92e8a9f9031348b7c5fac70f0c809927894d Mon Sep 17 00:00:00 2001 From: Faibk Date: Thu, 16 Nov 2017 00:25:05 +0100 Subject: [PATCH 2080/2240] added subevent test --- test/docs/discriminators.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index 3d3f18ce0e6..fb4bac84f6a 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -385,11 +385,11 @@ describe('discriminator docs', function () { assert.equal(doc.events[0].sub_events[0].message, 'test1'); assert.equal(doc.events[0].message, 'hello'); - assert.ok(doc.events[0] instanceof SubEvent); + assert.ok(doc.events[0].sub_events[0] instanceof SubEvent); assert.equal(doc.events[1].sub_events[0].sub_events[0].message, 'test3'); assert.equal(doc.events[1].message, 'world'); - assert.ok(doc.events[1] instanceof SubEvent); + assert.ok(doc.events[1].sub_events[0].sub_events[0] instanceof SubEvent); doc.events.push({kind:'SubEvent', sub_events:[{kind:'SubEvent', sub_events:[], message:'test4'}], message:'pushed'}); return doc.save(); From 62d09b0828b41b38293df4671967726cc25f2a22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Par=C3=A9?= Date: Wed, 15 Nov 2017 21:50:35 -0500 Subject: [PATCH 2081/2240] Add node 9 in travis allowing failures --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index d20f73ff05e..4bd1230dd67 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: node_js sudo: false node_js: + - "9" - "8" - "7" - "6" @@ -9,6 +10,9 @@ node_js: - "0.12" - "0.10" - "iojs" +matrix: + allow_failures: + - node_js: "9" before_script: - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.11.tgz - tar -zxvf mongodb-linux-x86_64-2.6.11.tgz From 8e5bd8bb783c150499a89e1bc2f4735e0eface90 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 15 Nov 2017 22:10:31 -0800 Subject: [PATCH 2082/2240] chore: now working on 4.13.3 --- History.md | 5 +++++ package-lock.json | 24 +++++++++++++++++++----- package.json | 2 +- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index 260d7f2d4a5..5c7290b58b1 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +4.13.3 / 2017-11-15 +=================== + * chore: add node 8 to travis #5818 [superheri](https://github.com/superheri) + * fix(document): don't apply transforms to nested docs when updating already saved doc #5807 + 4.13.2 / 2017-11-11 =================== * feat(buffer): add support for subtype prop #5530 diff --git a/package-lock.json b/package-lock.json index f6b30943cb6..d9f69500c0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.2-pre", + "version": "4.13.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1917,10 +1917,24 @@ "dev": true }, "markdown": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/markdown/-/markdown-0.3.1.tgz", - "integrity": "sha1-XZXBqGDRSFNSl4MqFX5L5Z6YgNQ=", - "dev": true + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/markdown/-/markdown-0.5.0.tgz", + "integrity": "sha1-KCBbVlqK51kt4gdGPWY33BgnIrI=", + "dev": true, + "requires": { + "nopt": "2.1.2" + }, + "dependencies": { + "nopt": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz", + "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + } + } }, "marked": { "version": "0.3.6", diff --git a/package.json b/package.json index cd50eb231e8..56bac25ebc0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.3-pre", + "version": "4.13.3", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a0ee8d88cc800e5b1c7055682f751185436e0873 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 15 Nov 2017 22:12:33 -0800 Subject: [PATCH 2083/2240] chore: now working on 4.13.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 56bac25ebc0..21478892ab7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.3", + "version": "4.13.4-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 2f2782e6fa2f38735840d5db169425f3f68abd44 Mon Sep 17 00:00:00 2001 From: mfluehr Date: Thu, 16 Nov 2017 13:28:53 -0500 Subject: [PATCH 2084/2240] Grammar fixes to `unique` FAQ --- docs/faq.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/faq.jade b/docs/faq.jade index feb006bdf2c..cca4c1dda96 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -35,8 +35,8 @@ block content :markdown **Q**. I declared a schema property as `unique` but I can still save duplicates. What gives? - **A**. Mongoose doesn't handle `unique` on it's own, `{ name: { type: String, unique: true } }` - just a shorthand for creating a [MongoDB unique index on `name`](https://docs.mongodb.com/manual/core/index-unique/). + **A**. Mongoose doesn't handle `unique` on its own: `{ name: { type: String, unique: true } }` + is just a shorthand for creating a [MongoDB unique index on `name`](https://docs.mongodb.com/manual/core/index-unique/). For example, if MongoDB doesn't already have a unique index on `name`, the below code will not error despite the fact that `unique` is true. :js var schema = new mongoose.Schema({ From 22d4657a60973935bc10b23452f6bf5c625ca462 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 16 Nov 2017 18:22:48 -0800 Subject: [PATCH 2085/2240] fix(aggregate): add `.pipeline()` helper to get the current pipeline Fix #5825 --- lib/aggregate.js | 16 ++++++++++++++++ package-lock.json | 2 +- test/aggregate.test.js | 12 ++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 56f1aec1466..022fa7a6f3a 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -638,6 +638,22 @@ Aggregate.prototype.facet = function(options) { return this.append({$facet: options}); }; +/** + * Returns the current pipeline + * + * ####Example: + * + * MyModel.aggregate().match({ test: 1 }).pipeline(); // [{ $match: { test: 1 } }] + * + * @return {Array} + * @api public + */ + + +Aggregate.prototype.pipeline = function() { + return this._pipeline; +}; + /** * Executes the aggregate pipeline on the currently bound Model. * diff --git a/package-lock.json b/package-lock.json index d9f69500c0e..5545f2c3b3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.3", + "version": "4.13.4-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 6097b8650d9..bb1b80689ca 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -773,6 +773,18 @@ describe('aggregate: ', function() { }); }); + it('pipeline() (gh-5825)', function(done) { + var aggregate = new Aggregate(); + + var pipeline = aggregate. + model(db.model('Employee')). + match({ sal: { $lt: 16000 } }). + pipeline(); + + assert.deepEqual(pipeline, [{ $match: { sal: { $lt: 16000 } } }]); + done(); + }); + it('explain()', function(done) { var aggregate = new Aggregate(); start.mongodVersion(function(err, version) { From bb840f50a310c1a22074fd4b9497dc560e96cc9d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Nov 2017 10:15:41 -0800 Subject: [PATCH 2086/2240] fix(aggregate): add chainable .option() helper for setting arbitrary options Fix #5829 --- lib/aggregate.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 022fa7a6f3a..40cb9273ceb 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -542,13 +542,31 @@ Aggregate.prototype.explain = function(callback) { */ Aggregate.prototype.allowDiskUse = function(value) { - if (!this.options) { - this.options = {}; - } this.options.allowDiskUse = value; return this; }; +/** + * Lets you set arbitrary options, for middleware or plugins. + * + * ####Example: + * + * var agg = Model.aggregate(..).option({ allowDiskUse: true }); // Set the `allowDiskUse` option + * agg.options; // `{ allowDiskUse: true }` + * + * @param {Object} value keys to merge into current options + * @see mongodb http://docs.mongodb.org/manual/reference/command/aggregate/ + * @return {Aggregate} this + * @api public + */ + +Aggregate.prototype.option = function(value) { + for (var key in Object.keys(value)) { + this.options[key] = value[key]; + } + return this; +}; + /** * Sets the cursor option option for the aggregation query (ignored for < 2.6.0). * Note the different syntax below: .exec() returns a cursor object, and no callback From aa675e7f7ef5a7afccaf1ca0212eb51bc327229a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 17 Nov 2017 10:29:18 -0800 Subject: [PATCH 2087/2240] chore: release 4.13.4 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 5c7290b58b1..70affb187cb 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.13.4 / 2017-11-17 +=================== + * fix(aggregate): add chainable .option() helper for setting arbitrary options #5829 + * fix(aggregate): add `.pipeline()` helper to get the current pipeline #5825 + * docs: grammar fixes for `unique` FAQ #5823 [mfluehr](https://github.com/mfluehr) + * chore: add node 9 to travis #5822 [superheri](https://github.com/superheri) + * fix(model): fix infinite recursion with recursive embedded discriminators #5821 [Faibk](https://github.com/Faibk) + 4.13.3 / 2017-11-15 =================== * chore: add node 8 to travis #5818 [superheri](https://github.com/superheri) diff --git a/package.json b/package.json index 21478892ab7..7fb17ee08aa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.4-pre", + "version": "4.13.4", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 754db14177fb1dcfc88f99d9600232e1b2b4112a Mon Sep 17 00:00:00 2001 From: Bruno Date: Sat, 18 Nov 2017 14:20:46 -0300 Subject: [PATCH 2088/2240] fix(model): allow virtual ref function to return arrays --- lib/model.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index ecf2ff52eee..000c1d2e80c 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3580,7 +3580,15 @@ function getModelsMapForPopulate(model, docs, options) { if (typeof ref === 'function') { ref = ref.call(doc, doc); } - modelNames = [ref]; + + // When referencing nested arrays, the ref should be an Array + // of modelNames. + if (Array.isArray(ref)) { + modelNames = ref; + } else { + modelNames = [ref]; + } + isVirtual = true; } else { // We may have a discriminator, in which case we don't want to From 69f4ced7d9c9631a7637ba445224210af8e6e474 Mon Sep 17 00:00:00 2001 From: Bruno Date: Sat, 18 Nov 2017 14:30:09 -0300 Subject: [PATCH 2089/2240] fix trailing spaces --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 000c1d2e80c..d159f13a3b7 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3580,7 +3580,7 @@ function getModelsMapForPopulate(model, docs, options) { if (typeof ref === 'function') { ref = ref.call(doc, doc); } - + // When referencing nested arrays, the ref should be an Array // of modelNames. if (Array.isArray(ref)) { From 0b13451bb89d4d6a4be81447fcbcd1039da0c2cd Mon Sep 17 00:00:00 2001 From: Bruno Date: Sat, 18 Nov 2017 14:33:27 -0300 Subject: [PATCH 2090/2240] fix trailing spaces --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index d159f13a3b7..3405b990224 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3581,7 +3581,7 @@ function getModelsMapForPopulate(model, docs, options) { ref = ref.call(doc, doc); } - // When referencing nested arrays, the ref should be an Array + // When referencing nested arrays, the ref should be an Array // of modelNames. if (Array.isArray(ref)) { modelNames = ref; From 4fcf4eef5ec43d0fc3c8ae8897a220015f3e04ad Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Nov 2017 18:19:00 -0800 Subject: [PATCH 2091/2240] chore: now working on 4.13.5 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5545f2c3b3a..847f0f7680b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.4-pre", + "version": "4.13.5-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 7fb17ee08aa..bf4afcf62db 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.4", + "version": "4.13.5-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 3597079000e5a7f20e7ce1d11119073746dbfba3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Nov 2017 18:19:24 -0800 Subject: [PATCH 2092/2240] chore: remove allow_failures for node 9 on travis --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4bd1230dd67..a7e9aeac0cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,6 @@ node_js: - "0.12" - "0.10" - "iojs" -matrix: - allow_failures: - - node_js: "9" before_script: - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.11.tgz - tar -zxvf mongodb-linux-x86_64-2.6.11.tgz From 07d8edb3e5484ca7e84056b31bd20e2de89542fe Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Nov 2017 18:50:44 -0800 Subject: [PATCH 2093/2240] test(document): repro #5703 --- test/document.test.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 152a3902611..558a2a03d34 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -913,6 +913,35 @@ describe('document', function() { }); }); }); + + it('populate on nested path (gh-5703)', function() { + var toySchema = new mongoose.Schema({ color: String }); + var Toy = db.model('gh5703', toySchema); + + var childSchema = new mongoose.Schema({ + name: String, + values: { + toy: { type: mongoose.Schema.Types.ObjectId, ref: 'gh5703' } + } + }); + var Child = db.model('gh5703_0', childSchema); + + return Toy.create({ color: 'blue' }). + then(function(toy) { + return Child.create({ values: { toy: toy._id } }); + }). + then(function(child) { + return Child.findById(child._id); + }). + then(function(child) { + return child.values.populate('toy').execPopulate().then(function() { + return child; + }); + }). + then(function(child) { + assert.equal(child.values.toy.color, 'blue'); + }); + }); }); describe('#update', function() { From 6535373788fc16f0613e3d3e40fb01d77f981c24 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 18 Nov 2017 18:50:57 -0800 Subject: [PATCH 2094/2240] fix(document): support calling `populate()` on nested document props Fix #5703 --- lib/document.js | 10 +++++++++- lib/services/document/compile.js | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index b994048d380..c79077be52f 100644 --- a/lib/document.js +++ b/lib/document.js @@ -2481,7 +2481,15 @@ Document.prototype.populate = function populate() { var paths = utils.object.vals(pop); this.$__.populate = undefined; paths.__noPromise = true; - this.constructor.populate(this, paths, fn); + var topLevelModel = this.constructor; + if (this.$__isNested) { + topLevelModel = this.$__.scope.constructor; + var nestedPath = this.$__.nestedPath; + paths.forEach(function(populateOptions) { + populateOptions.path = nestedPath + '.' + populateOptions.path; + }); + } + topLevelModel.populate(this, paths, fn); } return this; diff --git a/lib/services/document/compile.js b/lib/services/document/compile.js index 2c282fc9b7a..be12f5f647f 100644 --- a/lib/services/document/compile.js +++ b/lib/services/document/compile.js @@ -83,6 +83,7 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) { if (!prefix) { nested.$__.scope = this; } + nested.$__.nestedPath = path; Object.defineProperty(nested, 'schema', { enumerable: false, From 743c42c6a58f7967f6b1b1a31fbc59ec2a063527 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Nov 2017 15:29:07 -0800 Subject: [PATCH 2095/2240] test(query): repro #5812 --- test/query.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/query.test.js b/test/query.test.js index b410108963f..b59db2947ae 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2251,6 +2251,31 @@ describe('Query', function() { }); }); + it('queries with BSON overflow (gh-5812)', function(done) { + this.timeout(10000); + + var schema = new mongoose.Schema({ + email: String + }); + + var model = db.model('gh5812', schema); + var bigData = new Array(800000); + + for (var i = 0; i < bigData.length; ++i) { + bigData[i] = 'test1234567890'; + } + + model.find({email: {$in: bigData}}).lean(). + then(function() { + done(new Error('Expected an error')); + }). + catch(function(error) { + assert.ok(error); + assert.ok(error.message !== 'Expected error'); + done(); + }); + }); + it('handles geoWithin with mongoose docs (gh-4392)', function(done) { var areaSchema = new Schema({ name: {type: String}, From 80731fd077ca10042f53fedb890b4ddd9f255203 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Nov 2017 15:29:53 -0800 Subject: [PATCH 2096/2240] fix(query): don't throw uncaught error if query filter too big Fix #5812 --- lib/query.js | 15 +++++++++------ package-lock.json | 6 +++--- package.json | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/query.js b/lib/query.js index 4fd66362eda..14648a7e109 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1271,7 +1271,7 @@ Query.prototype._find = function(callback) { this._fields = this._castFields(this._fields); var fields = this._fieldsForExec(); - var options = this._mongooseOptions; + var mongooseOptions = this._mongooseOptions; var _this = this; var userProvidedFields = _this._userProvidedFields || {}; @@ -1284,23 +1284,26 @@ Query.prototype._find = function(callback) { return callback(null, docs); } - if (!options.populate) { - return !!options.lean === true + if (!mongooseOptions.populate) { + return !!mongooseOptions.lean === true ? callback(null, docs) : completeMany(_this.model, docs, fields, userProvidedFields, null, callback); } - var pop = helpers.preparePopulationOptionsMQ(_this, options); + var pop = helpers.preparePopulationOptionsMQ(_this, mongooseOptions); pop.__noPromise = true; _this.model.populate(docs, pop, function(err, docs) { if (err) return callback(err); - return !!options.lean === true + return !!mongooseOptions.lean === true ? callback(null, docs) : completeMany(_this.model, docs, fields, userProvidedFields, pop, callback); }); }; - return Query.base.find.call(this, {}, cb); + var options = this._optionsForExec(); + options.fields = this._fieldsForExec(); + var filter = this._conditions; + return this._collection.find(filter, options, cb); }; /** diff --git a/package-lock.json b/package-lock.json index 847f0f7680b..da3a51d5b6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2146,9 +2146,9 @@ "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" }, "mquery": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.2.tgz", - "integrity": "sha512-KXWMypZSvhCuqRtza+HMQZdYw7PfFBjBTFvP31NNAq0OX0/NTIgpcDpkWQ2uTxk6vGQtwQ2elhwhs+ZvCA8OaA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.3.tgz", + "integrity": "sha512-NC8L14kn+qxJbbJ1gbcEMDxF0sC3sv+1cbRReXXwVvowcwY1y9KoVZFq0ebwARibsadu8lx8nWGvm3V0Pf0ZWQ==", "requires": { "bluebird": "3.5.0", "debug": "2.6.9", diff --git a/package.json b/package.json index bf4afcf62db..60d36760350 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "mongodb": "2.2.33", "mpath": "0.3.0", "mpromise": "0.5.5", - "mquery": "2.3.2", + "mquery": "2.3.3", "ms": "2.0.0", "muri": "1.3.0", "regexp-clone": "0.0.1", From 93ea193193a1952b6da5664c65fe57745c52f109 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 19 Nov 2017 20:29:34 -0800 Subject: [PATCH 2097/2240] test(document): repro #5800 --- test/document.test.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 558a2a03d34..446058dfb92 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4953,6 +4953,45 @@ describe('document', function() { }); }); + it('modifying unselected nested object (gh-5800)', function() { + var MainSchema = new mongoose.Schema({ + a: { + b: {type: String, default: 'some default'}, + c: {type: Number, default: 0}, + d: {type: String} + }, + e: {type: String} + }); + + MainSchema.pre('save', function(next) { + if (this.isModified()) { + this.set('a.c', 100, Number); + } + next(); + }); + + var Main = db.model('gh5800', MainSchema); + + var doc = { a: { b: 'not the default', d: 'some value' }, e: 'e' }; + return Main.create(doc). + then(function(doc) { + assert.equal(doc.a.b, 'not the default'); + assert.equal(doc.a.d, 'some value'); + return Main.findOne().select('e'); + }). + then(function(doc) { + doc.e = 'e modified'; + return doc.save(); + }). + then(function() { + return Main.findOne(); + }). + then(function(doc) { + assert.equal(doc.a.b, 'not the default'); + assert.equal(doc.a.d, 'some value'); + }); + }); + it('consistent context for nested docs (gh-5347)', function(done) { var contexts = []; var childSchema = new mongoose.Schema({ From 82c615cb13f5719290c0ca3e5b5fe8197e72de3c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 20 Nov 2017 15:25:55 -0500 Subject: [PATCH 2098/2240] fix(document): if setting unselected nested path, don't overwrite nested path Fix #5800 --- lib/document.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/document.js b/lib/document.js index c79077be52f..a73905acae8 100644 --- a/lib/document.js +++ b/lib/document.js @@ -670,6 +670,14 @@ Document.prototype.$set = function(path, val, type, options) { curPath += (curPath.length > 0 ? '.' : '') + parts[i]; if (!cur) { this.$set(curPath, {}); + // Hack re: gh-5800. If nested field is not selected, it probably exists + // so `MongoError: cannot use the part (nested of nested.num) to + // traverse the element ({nested: null})` is not likely. If user gets + // that error, its their fault for now. We should reconsider disallowing + // modifying not selected paths for v5. + if (!this.isSelected(curPath)) { + this.unmarkModified(curPath); + } cur = this.getValue(curPath); } } From d1f6691a0206002f6dc53b288ed1e89e00b26482 Mon Sep 17 00:00:00 2001 From: Yadong Wen Date: Wed, 22 Nov 2017 13:58:37 -0500 Subject: [PATCH 2099/2240] Add link to bufferCommands --- docs/guide.jade | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/guide.jade b/docs/guide.jade index 05e00760a35..8c389700ca1 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -296,6 +296,7 @@ block content Valid options: - [autoIndex](#autoIndex) + - [bufferCommands](#bufferCommands) - [capped](#capped) - [collection](#collection) - [emitIndexErrors](#emitIndexErrors) From 1ffc38d457b8bfefce92d250118f7beb6adfe9c0 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 22 Nov 2017 11:14:47 -0800 Subject: [PATCH 2100/2240] fix "TypeError: Cannot read property 'options' of undefined" error that stops actual error from being thrown --- lib/services/query/castUpdate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index 52b11f4f82c..fa519cc1907 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -247,7 +247,7 @@ function walkUpdatePath(schema, obj, op, strict, context, pref) { */ function _handleCastError(error, query, key, aggregatedError) { - if (!query.options.multipleCastError) { + if (typeof query !== 'object' || !query.options.multipleCastError) { throw error; } aggregatedError.addError(key, error); From e0618816e8ccdd850905ca82aa390b1a04abc69a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 22 Nov 2017 19:36:34 -0500 Subject: [PATCH 2101/2240] docs(faq): add faq re: typeKey Fix #1886 --- docs/faq.jade | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/faq.jade b/docs/faq.jade index cca4c1dda96..489aa84af76 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -134,6 +134,44 @@ block content console.log(this); }); + hr#type-key + :markdown + **Q**. I have an embedded property named `type` like this: + :js + const holdingSchema = new Schema({ + // You might expect `asset` to be an object that has 2 properties, + // but unfortunately `type` is special in mongoose so mongoose + // interprets this schema to mean that `asset` is a string + asset: { + type: String, + ticker: String + } + }); + :markdown + But mongoose gives me a CastError telling me that it can't cast an object + to a string when I try to save a `Holding` with an `asset` object. Why + is this? + :js + Holding.create({ asset: { type: 'stock', ticker: 'MDB' } }).catch(error => { + // Cast to String failed for value "{ type: 'stock', ticker: 'MDB' }" at path "asset" + console.error(error); + }); + :markdown + **A**. The `type` property is special in mongoose, so when you say + `type: String`, mongoose interprets it as a type declaration. In the + above schema, mongoose thinks `asset` is a string, not an object. Do + this instead: + :js + const holdingSchema = new Schema({ + // This is how you tell mongoose you mean `asset` is an object with + // a string property `type`, as opposed to telling mongoose that `asset` + // is a string. + asset: { + type: { type: String }, + ticker: String + } + }); + hr#date_changes :markdown **Q**. Why don't in-place modifications to date objects From fe0d1c5af3da5353fb70628aaa0bec9af508ff4e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 23 Nov 2017 14:46:29 -0500 Subject: [PATCH 2102/2240] docs(query): add more detailed docs re: options Fix #1702 --- lib/model.js | 22 +++++++++++----------- lib/query.js | 39 +++++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/lib/model.js b/lib/model.js index fe40fe373ce..77bb3e67d0b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1326,7 +1326,7 @@ Model.deleteMany = function deleteMany(conditions, callback) { * * @param {Object} conditions * @param {Object} [projection] optional fields to return (http://bit.ly/1HotzBo) - * @param {Object} [options] optional + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @see field selection #query_Query-select @@ -1406,7 +1406,7 @@ Model.find = function find(conditions, projection, options, callback) { * * @param {Object|String|Number} id value of `_id` to query by * @param {Object} [projection] optional fields to return (http://bit.ly/1HotzBo) - * @param {Object} [options] optional + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @see field selection #query_Query-select @@ -1460,7 +1460,7 @@ Model.findById = function findById(id, projection, options, callback) { * * @param {Object} [conditions] * @param {Object} [projection] optional fields to return (http://bit.ly/1HotzBo) - * @param {Object} [options] optional + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @see field selection #query_Query-select @@ -1685,7 +1685,7 @@ Model.$where = function $where() { * * @param {Object} [conditions] * @param {Object} [update] - * @param {Object} [options] + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command @@ -1804,7 +1804,7 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { * * @param {Object|Number|String} id value of `_id` to query by * @param {Object} [update] - * @param {Object} [options] + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @see Model.findOneAndUpdate #model_Model.findOneAndUpdate @@ -1881,7 +1881,7 @@ Model.findByIdAndUpdate = function(id, update, options, callback) { * }); * * @param {Object} conditions - * @param {Object} [options] + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command @@ -1943,7 +1943,7 @@ Model.findOneAndRemove = function(conditions, options, callback) { * A.findByIdAndRemove() // returns Query * * @param {Object|Number|String} id value of `_id` to query by - * @param {Object} [options] + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @see Model.findOneAndRemove #model_Model.findOneAndRemove @@ -2507,7 +2507,7 @@ Model.hydrate = function(obj) { * @see response http://docs.mongodb.org/v2.6/reference/command/update/#output * @param {Object} conditions * @param {Object} doc - * @param {Object} [options] + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @api public @@ -2530,7 +2530,7 @@ Model.update = function update(conditions, doc, options, callback) { * * @param {Object} conditions * @param {Object} doc - * @param {Object} [options] + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @api public @@ -2549,7 +2549,7 @@ Model.updateMany = function updateMany(conditions, doc, options, callback) { * * @param {Object} conditions * @param {Object} doc - * @param {Object} [options] + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @api public @@ -2568,7 +2568,7 @@ Model.updateOne = function updateOne(conditions, doc, options, callback) { * * @param {Object} conditions * @param {Object} doc - * @param {Object} [options] + * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] * @return {Query} * @api public diff --git a/lib/query.js b/lib/query.js index 14648a7e109..b6fa389bde9 100644 --- a/lib/query.js +++ b/lib/query.js @@ -952,25 +952,31 @@ Query.prototype.read = function read(pref, tags) { */ /** - * Sets query options. + * Sets query options. Some options only make sense for certain operations. * * ####Options: * - * - [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors) * - * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D) * - * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D) * - * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D) * - * - [maxscan](https://docs.mongodb.org/v3.2/reference/operator/meta/maxScan/#metaOp._S_maxScan) * - * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D) * - * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment) * - * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D) * - * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint) * - * - [readPreference](http://docs.mongodb.org/manual/applications/replication/#read-preference) ** - * - [lean](./api.html#query_Query-lean) * - * - [safe](http://www.mongodb.org/display/DOCS/getLastError+Command) - * - * _* denotes a query helper method is also available_ - * _** query helper method to set `readPreference` is `read()`_ + * The following options are only for `find()`: + * - [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors) + * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D) + * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D) + * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D) + * - [maxscan](https://docs.mongodb.org/v3.2/reference/operator/meta/maxScan/#metaOp._S_maxScan) + * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D) + * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment) + * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D) + * - [readPreference](http://docs.mongodb.org/manual/applications/replication/#read-preference) + * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint) + * + * The following options are only for `update()`, `updateOne()`, `updateMany()`, `replaceOne()`, and `findOneAndUpdate()`: + * - [upsert](https://docs.mongodb.com/manual/reference/method/db.collection.update/) + * - [writeConcern](https://docs.mongodb.com/manual/reference/method/db.collection.update/) + * + * The following options are only for `find()`, `findOne()`, `findById()`, and `findOneAndUpdate()`: + * - [lean](./api.html#query_Query-lean) + * + * The following options are for all operations: + * - [collation](https://docs.mongodb.com/manual/reference/collation/) * * @param {Object} options * @api public @@ -1522,6 +1528,7 @@ Query.prototype._findOne = function(callback) { * * @param {Object|Query} [criteria] mongodb selector * @param {Object} [projection] optional fields to return + * @param {Object} [options] see [`setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] optional params are (error, document) * @return {Query} this * @see findOne http://docs.mongodb.org/manual/reference/method/db.collection.findOne/ From edca051c66776b9a64053459070aab6b37e9b784 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 24 Nov 2017 12:20:36 -0500 Subject: [PATCH 2103/2240] style: fix lint --- lib/schema/boolean.js | 1 + test/schema.boolean.test.js | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js index c4b437b40fa..099270c2136 100644 --- a/lib/schema/boolean.js +++ b/lib/schema/boolean.js @@ -5,6 +5,7 @@ var utils = require('../utils'); var SchemaType = require('../schematype'); +var CastError = SchemaType.CastError; /** * Boolean SchemaType constructor. diff --git a/test/schema.boolean.test.js b/test/schema.boolean.test.js index acf05f5bb8b..d367bb78ca3 100644 --- a/test/schema.boolean.test.js +++ b/test/schema.boolean.test.js @@ -38,16 +38,16 @@ describe('schematype', function() { var strictValues = [true, false, 'true', 'false', 0, 1, '0', '1']; var testsRemaining = strictValues.length; - strictValues.forEach(function (value) { + strictValues.forEach(function(value) { var doc = new M1; doc.b = value; - doc.validate(function (error) { + doc.validate(function(error) { if (error) { // test fails as soon as one value fails - return done(error) + return done(error); } if (!--testsRemaining) { - return done() + return done(); } }); }); From e31888255bc12315e7dc413fe16495169504e31f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 24 Nov 2017 13:06:09 -0500 Subject: [PATCH 2104/2240] chore: release 4.13.5 --- History.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 70affb187cb..8c6455e49b6 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,15 @@ +4.13.5 / 2017-11-24 +=================== + * fix(model): handle update cast errors correctly with bulkWrite #5845 [Michael77](https://github.com/Michael77) + * docs: add link to bufferCommands option #5844 [ralphite](https://github.com/ralphite) + * fix(model): allow virtual ref function to return arrays #5834 [brunohcastro](https://github.com/brunohcastro) + * fix(query): don't throw uncaught error if query filter too big #5812 + * fix(document): if setting unselected nested path, don't overwrite nested path #5800 + * fix(document): support calling `populate()` on nested document props #5703 + * fix: add `strictBool` option for schema type boolean #5344 #5211 #4245 + * docs(faq): add faq re: typeKey #1886 + * docs(query): add more detailed docs re: options #1702 + 4.13.4 / 2017-11-17 =================== * fix(aggregate): add chainable .option() helper for setting arbitrary options #5829 diff --git a/package.json b/package.json index 60d36760350..a46b5e41647 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.5-pre", + "version": "4.13.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From a122191bb04979e6d6eab58d3ffa468850baa1d8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 24 Nov 2017 13:15:33 -0500 Subject: [PATCH 2105/2240] chore: now working on 4.13.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a46b5e41647..ba66e50d250 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.5", + "version": "4.13.6-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 16a41e5adfc094bbf83514bf41f6576ebb3c8fa9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Nov 2017 14:59:24 -0500 Subject: [PATCH 2106/2240] chore: bump lockfile --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index da3a51d5b6e..0fe4844ebd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.5-pre", + "version": "4.13.6-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From 3a88543c88e6253d7a2d81ba8397c791bfd85002 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 26 Nov 2017 15:12:35 -0500 Subject: [PATCH 2107/2240] docs(query): correct function signature for .mod() helper Fix #1806 --- lib/query.js | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index b6fa389bde9..435cac0ef2b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -531,17 +531,51 @@ Query.prototype.slice = function() { */ /** - * Specifies a `$mod` condition + * Specifies a `$mod` condition, filters documents for documents whose + * `path` property is a number that is equal to `remainder` modulo `divisor`. + * + * ####Example + * + * // All find products whose inventory is odd + * Product.find().mod('inventory', [2, 1]); + * Product.find().where('inventory').mod([2, 1]); + * // This syntax is a little strange, but supported. + * Product.find().where('inventory').mod(2, 1); * * @method mod * @memberOf Query * @param {String} [path] - * @param {Number} val + * @param {Array} val must be of length 2, first element is `divisor`, 2nd element is `remainder`. * @return {Query} this * @see $mod http://docs.mongodb.org/manual/reference/operator/mod/ * @api public */ +Query.prototype.mod = function() { + var val; + var path; + + if (arguments.length === 1) { + this._ensurePath('mod'); + val = arguments[0]; + path = this._path; + } else if (arguments.length === 2 && !Array.isArray(arguments[1])) { + this._ensurePath('mod'); + val = slice(arguments); + path = this._path; + } else if (arguments.length === 3) { + val = slice(arguments, 1); + path = arguments[0]; + } else { + val = arguments[1]; + path = arguments[0]; + } + + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds.$mod = val; + return this; +}; + /** * Specifies an `$exists` condition * From 5e279f4824994f2dec2f29aaf86ddb5810bc4b06 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 27 Nov 2017 20:22:24 -0500 Subject: [PATCH 2108/2240] test(update): repro #5839 --- test/model.update.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/model.update.test.js b/test/model.update.test.js index 0659d61f8f3..cca2d7e4286 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2835,6 +2835,24 @@ describe('model: update:', function() { }); }); + it('upsert: 1 (gh-5839)', function(done) { + var schema = new mongoose.Schema({ + name: String + }); + + var Model = db.model('gh3677', schema); + + var opts = { upsert: 1 }; + Model.update({ name: 'Test' }, { name: 'Test2' }, opts, function(error) { + assert.ifError(error); + Model.findOne({}, function(error, doc) { + assert.ifError(error); + assert.equal(doc.name, 'Test2'); + done(); + }); + }); + }); + it('update with nested id (gh-5640)', function(done) { var testSchema = new mongoose.Schema({ _id: { From 4d4dfa148fad83db4f5de4d6c3c1c1524413a710 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 27 Nov 2017 20:26:15 -0500 Subject: [PATCH 2109/2240] fix(update): make upsert option consistently handle truthy values, not just booleans, for updateOne() Fix #5839 --- lib/query.js | 4 ++++ test/model.update.test.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/query.js b/lib/query.js index 435cac0ef2b..d0b7b2cb57e 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1183,6 +1183,10 @@ Query.prototype._optionsForExec = function(model) { options.readPreference = model.schema.options.read; } + if (options.upsert !== void 0) { + options.upsert = !!options.upsert; + } + return options; }; diff --git a/test/model.update.test.js b/test/model.update.test.js index cca2d7e4286..a6a6fbd98b9 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2840,7 +2840,7 @@ describe('model: update:', function() { name: String }); - var Model = db.model('gh3677', schema); + var Model = db.model('gh5839', schema); var opts = { upsert: 1 }; Model.update({ name: 'Test' }, { name: 'Test2' }, opts, function(error) { From cbab4caa7395679ddca76c7580fe4881ad218bb3 Mon Sep 17 00:00:00 2001 From: Eugene Kulabuhov Date: Wed, 29 Nov 2017 14:39:35 +0200 Subject: [PATCH 2110/2240] Added strictBool option to schema --- lib/schema/boolean.js | 22 +++++++++++----------- test/schema.boolean.test.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js index 099270c2136..e7fb354a65c 100644 --- a/lib/schema/boolean.js +++ b/lib/schema/boolean.js @@ -55,12 +55,21 @@ SchemaBoolean.prototype.checkRequired = function(value) { * @api private */ -SchemaBoolean.prototype.cast = function(value) { +SchemaBoolean.prototype.cast = function(value, model) { if (value === null) { return value; } - if (!this.options.strictBool) { + if (this.options.strictBool || (model.schema.options.strictBool && this.options.strictBool !== false)) { + // strict mode (throws if value is not a boolean, instead of converting) + if (value === true || value === 'true' || value === 1 || value === '1') { + return true; + } + if (value === false || value === 'false' || value === 0 || value === '0') { + return false; + } + throw new CastError('boolean', value, this.path); + } else { // legacy mode if (value === '0') { return false; @@ -72,15 +81,6 @@ SchemaBoolean.prototype.cast = function(value) { return false; } return !!value; - } else { - // strict mode (throws if value is not a boolean, instead of converting) - if (value === true || value === 'true' || value === 1 || value === '1') { - return true; - } - if (value === false || value === 'false' || value === 0 || value === '0') { - return false; - } - throw new CastError('boolean', value, this.path); } }; diff --git a/test/schema.boolean.test.js b/test/schema.boolean.test.js index d367bb78ca3..59b77b916aa 100644 --- a/test/schema.boolean.test.js +++ b/test/schema.boolean.test.js @@ -29,6 +29,7 @@ describe('schematype', function() { assert.strictEqual(true, m3.b); done(); }); + it('strictBool option (gh-5211)', function(done) { var db = start(), s1 = new Schema({b: {type: Boolean, strictBool: true}}), @@ -51,7 +52,37 @@ describe('schematype', function() { } }); }); + }); + + it('strictBool schema option', function(done) { + var db = start(), + s1 = new Schema({b: {type: Boolean}}, {strictBool: true}), + M1 = db.model('StrictBoolTrue', s1); + db.close(); + var strictValues = [true, false, 'true', 'false', 0, 1, '0', '1']; + + strictValues.forEach(function(value) { + var doc = new M1; + doc.b = value; + doc.validate(function(error) { + if (error) { + // test fails as soon as one value fails + return done(error); + } + }); + }); + + var doc = new M1; + doc.b = 'Not a boolean'; + doc.validate(function(error) { + if (error) { + done(); + } else { + done(new Error('ValidationError expected')); + } + }); }); + }); }); From a9be7dc8d1d52316e4dd93b059340a17d6e88f1b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Nov 2017 17:03:14 -0500 Subject: [PATCH 2111/2240] docs: make Document $markValid() public re: #5826 --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index a73905acae8..4d60736d0f3 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1691,7 +1691,7 @@ Document.prototype.invalidate = function(path, err, val, kind) { * Marks a path as valid, removing existing validation errors. * * @param {String} path the field to mark as valid - * @api private + * @api public * @method $markValid * @receiver Document */ From f46e033b7a923d863e7f8213bfdc313e7aa494ae Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 29 Nov 2017 21:14:11 -0800 Subject: [PATCH 2112/2240] refactor: remove unnecessary constructor check Fix #2057 --- lib/query.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/query.js b/lib/query.js index d0b7b2cb57e..80e87994a57 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1029,11 +1029,11 @@ Query.prototype.setOptions = function(options, overwrite) { return this; } - if (!(options && options.constructor.name === 'Object')) { + if (options == null) { return this; } - if (options && Array.isArray(options.populate)) { + if (Array.isArray(options.populate)) { var populate = options.populate; delete options.populate; var _numPopulate = populate.length; From a3fd08ca729f444a0519cc2f71ea7f1d7ddefd60 Mon Sep 17 00:00:00 2001 From: Eugene Kulabuhov Date: Thu, 30 Nov 2017 15:11:41 +0200 Subject: [PATCH 2113/2240] Added check for missing model parameter --- lib/schema/boolean.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/schema/boolean.js b/lib/schema/boolean.js index e7fb354a65c..f90c86a6c2f 100644 --- a/lib/schema/boolean.js +++ b/lib/schema/boolean.js @@ -52,6 +52,7 @@ SchemaBoolean.prototype.checkRequired = function(value) { * Casts to boolean * * @param {Object} value + * @param {Object} model - this value is optional * @api private */ @@ -60,7 +61,7 @@ SchemaBoolean.prototype.cast = function(value, model) { return value; } - if (this.options.strictBool || (model.schema.options.strictBool && this.options.strictBool !== false)) { + if (this.options.strictBool || (model && model.schema.options.strictBool && this.options.strictBool !== false)) { // strict mode (throws if value is not a boolean, instead of converting) if (value === true || value === 'true' || value === 1 || value === '1') { return true; From 0de9867ef21507d261720106ce883833fcf3efae Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Nov 2017 21:31:00 -0800 Subject: [PATCH 2114/2240] test(query): repro #1698 --- test/query.test.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index b59db2947ae..efe5b6beae4 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -547,6 +547,7 @@ describe('Query', function() { assert.ok(!threw); done(); }); + it('works with overwriting previous object args (1176)', function(done) { var q = new Query({}, {}, null, p1.collection); assert.doesNotThrow(function() { @@ -1862,11 +1863,11 @@ describe('Query', function() { var MyModel = db.model('gh4378', schema); - assert.throws(function() { - MyModel.findOne(''); - }, /Invalid argument to findOne()/); - - done(); + MyModel.findOne('', function(error) { + assert.ok(error); + assert.equal(error.name, 'ObjectParameterError'); + done(); + }); }); it('handles geoWithin with $center and mongoose object (gh-4419)', function(done) { @@ -2251,6 +2252,19 @@ describe('Query', function() { }); }); + it('with non-object args (gh-1698)', function(done) { + var schema = new mongoose.Schema({ + email: String + }); + var M = db.model('gh1698', schema); + + M.find(42, function(error) { + assert.ok(error); + assert.equal(error.name, 'ObjectParameterError'); + done(); + }); + }); + it('queries with BSON overflow (gh-5812)', function(done) { this.timeout(10000); From 5c547ad49de1a70d679c526d5ba67d90605194ca Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Nov 2017 21:31:20 -0800 Subject: [PATCH 2115/2240] fix(query): report ObjectParameterError when passing non-object as filter to find() and findOne() Fix #1698 Re: #4378 --- lib/query.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/query.js b/lib/query.js index 80e87994a57..45e6fb77f87 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1359,7 +1359,7 @@ Query.prototype._find = function(callback) { * * query.find({ name: 'Los Pollos Hermanos' }).find(callback) * - * @param {Object} [criteria] mongodb selector + * @param {Object} [filter] mongodb selector * @param {Function} [callback] * @return {Query} this * @api public @@ -1375,9 +1375,11 @@ Query.prototype.find = function(conditions, callback) { if (mquery.canMerge(conditions)) { this.merge(conditions); - } - prepareDiscriminatorCriteria(this); + prepareDiscriminatorCriteria(this); + } else if (conditions != null) { + this.error(new ObjectParameterError(conditions, 'filter', 'find')); + } // if we don't have a callback, then just return the query object if (!callback) { @@ -1564,7 +1566,7 @@ Query.prototype._findOne = function(callback) { * } * }); * - * @param {Object|Query} [criteria] mongodb selector + * @param {Object} [filter] mongodb selector * @param {Object} [projection] optional fields to return * @param {Object} [options] see [`setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) * @param {Function} [callback] optional params are (error, document) @@ -1604,18 +1606,17 @@ Query.prototype.findOne = function(conditions, projection, options, callback) { if (mquery.canMerge(conditions)) { this.merge(conditions); - } else if (conditions != null) { - throw new Error('Invalid argument to findOne(): ' + - util.inspect(conditions)); - } - prepareDiscriminatorCriteria(this); + prepareDiscriminatorCriteria(this); - try { - this.cast(this.model); - this.error(null); - } catch (err) { - this.error(err); + try { + this.cast(this.model); + this.error(null); + } catch (err) { + this.error(err); + } + } else if (conditions != null) { + this.error(new ObjectParameterError(conditions, 'filter', 'findOne')); } if (!callback) { From 5c159d775eb9b807bdc6e6200da34cd0b1249507 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Dec 2017 15:45:34 -0800 Subject: [PATCH 2116/2240] chore: release 4.13.6 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 8c6455e49b6..1a51cca6125 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.13.6 / 2017-12-02 +=================== + * fix(schema): support strictBool option in schema #5856 [ekulabuhov](https://github.com/ekulabuhov) + * fix(update): make upsert option consistently handle truthy values, not just booleans, for updateOne() #5839 + * refactor: remove unnecessary constructor check #2057 + * docs(query): correct function signature for .mod() helper #1806 + * fix(query): report ObjectParameterError when passing non-object as filter to find() and findOne() #1698 + 4.13.5 / 2017-11-24 =================== * fix(model): handle update cast errors correctly with bulkWrite #5845 [Michael77](https://github.com/Michael77) diff --git a/package.json b/package.json index ba66e50d250..75ef05b09ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.6-pre", + "version": "4.13.6", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From d3bb122623d152c221a9eaa1ab9dd3809bcd08e7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 2 Dec 2017 15:54:11 -0800 Subject: [PATCH 2117/2240] chore: now working on 4.13.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 75ef05b09ae..18d67ce3784 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.6", + "version": "4.13.7-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 50aafb6fb6387f4c5750d72dae0ec17dc8da4639 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 4 Dec 2017 10:27:11 -0800 Subject: [PATCH 2118/2240] chore: bump lockfile --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 0fe4844ebd5..50aecde2643 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.6-pre", + "version": "4.13.7-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From d0d2d5f5bd956dece250f0eed06b6964a82e7c77 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 4 Dec 2017 10:27:23 -0800 Subject: [PATCH 2119/2240] test(model): repro #2037 --- test/model.test.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/model.test.js b/test/model.test.js index a27155a1761..82b5dbcef70 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -5718,6 +5718,18 @@ describe('Model', function() { }); }); + it('.create() with non-object (gh-2037)', function(done) { + var schema = new mongoose.Schema({ name: String }); + + var Model = db.model('gh2037', schema); + + Model.create(1, function(error) { + assert.ok(error); + assert.equal(error.name, 'ObjectParameterError'); + done(); + }); + }); + it('bulkWrite casting updateMany, deleteOne, deleteMany (gh-3998)', function(done) { var schema = new Schema({ str: String, From d90100e786728d803faa5bbcad7ba1af486620b5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 4 Dec 2017 10:27:40 -0800 Subject: [PATCH 2120/2240] fix(model): throw error when passing non-object to create() Fix #2037 --- lib/document.js | 5 +++++ lib/model.js | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 4d60736d0f3..dc8df23830f 100644 --- a/lib/document.js +++ b/lib/document.js @@ -7,6 +7,7 @@ var MongooseError = require('./error'); var MixedSchema = require('./schema/mixed'); var Schema = require('./schema'); var ObjectExpectedError = require('./error/objectExpected'); +var ObjectParameterError = require('./error/objectParameter'); var StrictModeError = require('./error/strict'); var ValidatorError = require('./schematype').ValidatorError; var VirtualType = require('./virtualtype'); @@ -48,6 +49,10 @@ function Document(obj, fields, skipId, options) { this.errors = undefined; this.$__.$options = options || {}; + if (obj != null && typeof obj !== 'object') { + throw new ObjectParameterError(obj, 'obj', 'Document'); + } + var schema = this.schema; if (typeof fields === 'boolean') { diff --git a/lib/model.js b/lib/model.js index 77bb3e67d0b..cc961a3c515 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2043,7 +2043,7 @@ Model.create = function create(doc, callback) { var Model = _this.discriminators && doc[discriminatorKey] ? _this.discriminators[doc[discriminatorKey]] : _this; - var toSave = doc instanceof Model ? doc : new Model(doc); + var toSave = doc; var callbackWrapper = function(error, doc) { if (error) { if (!firstError) { @@ -2054,6 +2054,14 @@ Model.create = function create(doc, callback) { callback(null, { doc: doc }); }; + if (!(toSave instanceof Model)) { + try { + toSave = new Model(toSave); + } catch (error) { + return callbackWrapper(error); + } + } + // Hack to avoid getting a promise because of // $__registerHooksFromSchema if (toSave.$__original_save) { From 4a1e47488428548355e912af108ebd210087afe4 Mon Sep 17 00:00:00 2001 From: Lin Qun Date: Tue, 5 Dec 2017 22:36:42 +0800 Subject: [PATCH 2121/2240] fix(Mongoose): fix connection setter --- lib/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index e76a57eb436..ea6ffe1001a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -528,7 +528,10 @@ Mongoose.prototype.__defineGetter__('connection', function() { }); Mongoose.prototype.__defineSetter__('connection', function(v) { - this.connections[0] = v; + if (v instanceof Connection) { + this.connections[0] = v; + this.models = v.models; + } }); /*! From 23c8dd0510d1372fd2691eaa8c28940f58e3c9f4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 5 Dec 2017 21:19:14 -0800 Subject: [PATCH 2122/2240] fix(types): handle Decimal128 when using bson-ext on server side Fix #5850 --- lib/drivers/browser/decimal128.js | 5 +++++ lib/drivers/browser/index.js | 1 + lib/drivers/node-mongodb-native/decimal128.js | 5 +++++ lib/drivers/node-mongodb-native/index.js | 1 + lib/types/decimal128.js | 2 +- 5 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 lib/drivers/browser/decimal128.js create mode 100644 lib/drivers/node-mongodb-native/decimal128.js diff --git a/lib/drivers/browser/decimal128.js b/lib/drivers/browser/decimal128.js new file mode 100644 index 00000000000..ecc1ae3b9be --- /dev/null +++ b/lib/drivers/browser/decimal128.js @@ -0,0 +1,5 @@ +/*! + * ignore + */ + +module.exports = require('bson').Decimal128; diff --git a/lib/drivers/browser/index.js b/lib/drivers/browser/index.js index fa5dbb422d0..cc794a79379 100644 --- a/lib/drivers/browser/index.js +++ b/lib/drivers/browser/index.js @@ -3,5 +3,6 @@ */ exports.Binary = require('./binary'); +exports.Decimal128 = require('./decimal128'); exports.ObjectId = require('./objectid'); exports.ReadPreference = require('./ReadPreference'); diff --git a/lib/drivers/node-mongodb-native/decimal128.js b/lib/drivers/node-mongodb-native/decimal128.js new file mode 100644 index 00000000000..d1f04de9658 --- /dev/null +++ b/lib/drivers/node-mongodb-native/decimal128.js @@ -0,0 +1,5 @@ +/*! + * ignore + */ + +module.exports = require('mongodb').Decimal128; diff --git a/lib/drivers/node-mongodb-native/index.js b/lib/drivers/node-mongodb-native/index.js index fa5dbb422d0..cc794a79379 100644 --- a/lib/drivers/node-mongodb-native/index.js +++ b/lib/drivers/node-mongodb-native/index.js @@ -3,5 +3,6 @@ */ exports.Binary = require('./binary'); +exports.Decimal128 = require('./decimal128'); exports.ObjectId = require('./objectid'); exports.ReadPreference = require('./ReadPreference'); diff --git a/lib/types/decimal128.js b/lib/types/decimal128.js index 87791c63557..ea49a3a96e3 100644 --- a/lib/types/decimal128.js +++ b/lib/types/decimal128.js @@ -8,4 +8,4 @@ * @constructor ObjectId */ -module.exports = require('bson').Decimal128; +module.exports = require('../drivers').Decimal128; From 7e4077d261bbb16fac492372055ef7428597752c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 5 Dec 2017 22:39:08 -0800 Subject: [PATCH 2123/2240] test(document): repro #4991 --- test/model.discriminator.querying.test.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js index abb87ea0484..2cb3fe7cf55 100644 --- a/test/model.discriminator.querying.test.js +++ b/test/model.discriminator.querying.test.js @@ -1010,6 +1010,29 @@ describe('model', function() { catch(done); }); + it('doesnt exclude field if slice (gh-4991)', function(done) { + var baseSchema = new mongoose.Schema({ + propA: { type: String, default: 'default value' }, + array: [{type: String}] + }); + + var Base = db.model('gh4991_A', baseSchema); + var discriminatorSchema = new mongoose.Schema({ + propB: { type: String} + }); + var Discriminator = Base.discriminator('gh4991_A1', discriminatorSchema); + + var obj = { propA: 'Hi', propB: 'test', array: ['a', 'b'] }; + Discriminator.create(obj, function(error, doc) { + assert.ifError(error); + Base.find().slice('array', 1).exec(function(error, docs) { + assert.equal(docs.length, 1); + assert.equal(docs[0].propA, 'Hi'); + done(); + }) + }); + }); + it('merges the first pipeline stages if applicable', function(done) { var aggregate = ImpressionEvent.aggregate([ {$match: {name: 'Test Event'}} From 7b42c15a42f787ec26d0faee074f7674eac41ca3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 5 Dec 2017 22:45:52 -0800 Subject: [PATCH 2124/2240] fix(document): ensure projection with only $slice isn't treated as inclusive for discriminators Fix #4991 --- lib/document.js | 3 ++- test/model.discriminator.querying.test.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/document.js b/lib/document.js index dc8df23830f..188b554f296 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1258,7 +1258,8 @@ Document.prototype.isSelected = function isSelected(path) { if (cur === '_id') { continue; } - if (this.$__.selected[cur] && this.$__.selected[cur].$meta) { + var projection = this.$__.selected[cur]; + if (projection && (projection.$meta || projection.$slice)) { continue; } inclusive = !!this.$__.selected[cur]; diff --git a/test/model.discriminator.querying.test.js b/test/model.discriminator.querying.test.js index 2cb3fe7cf55..69e4732a563 100644 --- a/test/model.discriminator.querying.test.js +++ b/test/model.discriminator.querying.test.js @@ -1023,13 +1023,13 @@ describe('model', function() { var Discriminator = Base.discriminator('gh4991_A1', discriminatorSchema); var obj = { propA: 'Hi', propB: 'test', array: ['a', 'b'] }; - Discriminator.create(obj, function(error, doc) { + Discriminator.create(obj, function(error) { assert.ifError(error); Base.find().slice('array', 1).exec(function(error, docs) { assert.equal(docs.length, 1); assert.equal(docs[0].propA, 'Hi'); done(); - }) + }); }); }); From f4c06e5fc9bc27baa25fd4ceab0c24724767464f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 5 Dec 2017 23:12:41 -0800 Subject: [PATCH 2125/2240] docs(middleware): suggest using `return next()` to stop middleware execution Fix #5866 --- docs/middleware.jade | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/middleware.jade b/docs/middleware.jade index a4a4779ae5b..2d1222e5d0d 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -50,13 +50,29 @@ block content There are two types of `pre` hooks, serial and parallel. h4#serial Serial :markdown - Serial middleware are executed one after another, when each middleware calls `next`. + Serial middleware functions are executed one after another, when each + middleware calls `next`. :js var schema = new Schema(..); schema.pre('save', function(next) { // do stuff next(); }); + :markdown + The `next()` call does **not** stop the rest of the code in your middleware function from executing. Use + [the early `return` pattern](https://www.bennadel.com/blog/2323-use-a-return-statement-when-invoking-callbacks-especially-in-a-guard-statement.htm) + if you want to stop execution when you call `next()`. + :js + var schema = new Schema(..); + schema.pre('save', function(next) { + if (foo()) { + console.log('calling next!'); + // `return next();` will make sure the rest of this function doesn't run + /*return*/ next(); + } + // Unless you comment out the `return` above, 'after next' will print + console.log('after next'); + }); h4#parallel Parallel p | Parallel middleware offer more fine-grained flow control. From 9897aafd321f6979502613fb013add07b78f55d8 Mon Sep 17 00:00:00 2001 From: Zach Smith Date: Wed, 6 Dec 2017 10:23:21 -0500 Subject: [PATCH 2126/2240] fix: eachAsync - Treat reject() as a Promise rejection --- lib/services/cursor/eachAsync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/cursor/eachAsync.js b/lib/services/cursor/eachAsync.js index 1f28db6c812..03675a7fb1f 100644 --- a/lib/services/cursor/eachAsync.js +++ b/lib/services/cursor/eachAsync.js @@ -30,7 +30,7 @@ module.exports = function eachAsync(next, fn, options, callback) { if (promise && typeof promise.then === 'function') { promise.then( function() { callback(null); }, - function(error) { callback(error); }); + function(error) { callback(error || new Error('User\'s @fn called reject() (without an error).')); }); } else { callback(null); } From a11c05e2a151a7eba2852cb0396849e2250927db Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 6 Dec 2017 08:31:28 -0800 Subject: [PATCH 2127/2240] docs(middleware): some cleanup re: #5866 --- docs/middleware.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/middleware.jade b/docs/middleware.jade index 2d1222e5d0d..c85923d31b1 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -61,7 +61,7 @@ block content :markdown The `next()` call does **not** stop the rest of the code in your middleware function from executing. Use [the early `return` pattern](https://www.bennadel.com/blog/2323-use-a-return-statement-when-invoking-callbacks-especially-in-a-guard-statement.htm) - if you want to stop execution when you call `next()`. + to prevent the rest of your middleware function from running when you call `next()`. :js var schema = new Schema(..); schema.pre('save', function(next) { From 83d9a98c5a7fe3def9d3914eecfc3d97535a5470 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 6 Dec 2017 08:44:25 -0800 Subject: [PATCH 2128/2240] docs(connection): improve connection string query param docs Fix #5864 --- docs/connections.jade | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index 305b25aeaab..1d8412a11e0 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -106,26 +106,24 @@ block content h4#connection-string-options Connection String Options :markdown - Mongoose supports the following options in the connection string. - - * [ssl](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) - * [poolSize](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) - * [autoReconnect](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) - * [socketTimeoutMS](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) - * [connectTimeoutMS](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) - * [authSource](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) - * [retries](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) - * [authMechanism](http://mongodb.github.io/node-mongodb-native/2.2/tutorials/connect/authenticating/) - * [reconnectWait](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) - * [rs_name](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) - * [replicaSet](http://mongodb.github.io/node-mongodb-native/2.1/api/ReplSet.html) - * [nativeParser](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) - * [w](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) - * [journal](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) - * [wtimeoutMS](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) - * [readPreference](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) - * [readPreferenceTags](http://mongodb.github.io/node-mongodb-native/2.1/api/Db.html) - * [sslValidate](http://mongodb.github.io/node-mongodb-native/2.1/api/Server.html) + You can also specify options in your connection string as [parameters in the query string](https://en.wikipedia.org/wiki/Query_string) portion of the URI. + :js + mongoose.connect('mongodb://localhost:27017/test?connectTimeoutMS=1000', { useMongoClient: true }); + // The above is equivalent to: + mongoose.connect('mongodb://localhost:27017/test', { + useMongoClient: true, + connectTimeoutMS: 1000 + }); + :markdown + The disadvantage of putting options in the query string is that query + string options are harder to read. The advantage is that you only need a + single configuration option, the URI, rather than separate options for + `socketTimeoutMS`, `connectTimeoutMS`, etc. Best practice is to put options + that likely differ between development and production, like `replicaSet` + or `ssl`, in the connection string, and options that should remain constant, + like `connectTimeoutMS` or `poolSize`, in the options object. + + The MongoDB docs have a full list of [supported connection string options](https://docs.mongodb.com/manual/reference/connection-string/) h4#keepAlive A note about keepAlive .important From cc840265caefd5f4a6b8ba77b013141f1d2fd357 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Dec 2017 19:29:17 -0800 Subject: [PATCH 2129/2240] refactor: add isDefiningProjection helper re: #5881 --- .../projection/isDefiningProjection.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 lib/services/projection/isDefiningProjection.js diff --git a/lib/services/projection/isDefiningProjection.js b/lib/services/projection/isDefiningProjection.js new file mode 100644 index 00000000000..710d4b89929 --- /dev/null +++ b/lib/services/projection/isDefiningProjection.js @@ -0,0 +1,18 @@ +'use strict'; + +/*! + * ignore + */ + +module.exports = function isDefiningProjection(val) { + if (val == null) { + // `undefined` or `null` become exclusive projections + return true; + } + if (typeof val === 'object') { + // Only cases where a value does **not** define whether the whole projection + // is inclusive or exclusive are `$meta` and `$slice`. + return !('$meta' in val) && !('$slice' in val); + } + return true; +} From 7c355b012818541ac5e74c31d980dcd4ac02c737 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Dec 2017 19:29:32 -0800 Subject: [PATCH 2130/2240] test(discriminator): repro #5859 --- test/model.discriminator.test.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/model.discriminator.test.js b/test/model.discriminator.test.js index 729f38c6704..6bf45f7a85b 100644 --- a/test/model.discriminator.test.js +++ b/test/model.discriminator.test.js @@ -621,6 +621,36 @@ describe('model', function() { }); }); + it('with $meta projection (gh-5859)', function() { + var eventSchema = new Schema({ eventField: String }, { id: false }); + var Event = db.model('gh5859', eventSchema); + + var trackSchema = new Schema({ trackField: String }); + var Track = Event.discriminator('gh5859_0', trackSchema); + + var trackedItem = new Track({ + trackField: 'trackField', + eventField: 'eventField', + }); + + return trackedItem.save(). + then(function() { + return Event.find({}).select({ score: { $meta: 'textScore' } }); + }). + then(function(docs) { + assert.equal(docs.length, 1); + assert.equal(docs[0].trackField, 'trackField'); + }). + then(function() { + return Track.find({}).select({ score: { $meta: 'textScore' } }); + }). + then(function(docs) { + assert.equal(docs.length, 1); + assert.equal(docs[0].trackField, 'trackField'); + assert.equal(docs[0].eventField, 'eventField'); + }); + }); + it('embedded discriminators with $push (gh-5009)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', _id: false }); From 107b83824631bc34f2d3ca363933dac15a82dd4b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Dec 2017 19:34:13 -0800 Subject: [PATCH 2131/2240] fix(discriminator): don't treat $meta as defining projection when querying Fix #5859 --- lib/queryhelpers.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/queryhelpers.js b/lib/queryhelpers.js index 9f6db1eba7c..8f52106c441 100644 --- a/lib/queryhelpers.js +++ b/lib/queryhelpers.js @@ -4,6 +4,7 @@ */ var get = require('lodash.get'); +var isDefiningProjection = require('./services/projection/isDefiningProjection'); var utils = require('./utils'); /*! @@ -90,7 +91,8 @@ exports.applyPaths = function applyPaths(fields, schema) { continue; } field = fields[keys[ki]]; - if (typeof field === 'object' && field && field.$slice) { + // Skip `$meta` and `$slice` + if (!isDefiningProjection(field)) { continue; } exclude = field === 0; From 4f1e1a0b18a8a54be8e6363c60f4b1b5fceedaa1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Dec 2017 19:35:01 -0800 Subject: [PATCH 2132/2240] refactor(document): use isDefiningProjection() helper instead of checking for $meta and $slice everywhere Fix #5881 --- lib/document.js | 11 ++++------- lib/services/projection/isDefiningProjection.js | 2 +- lib/services/projection/isInclusive.js | 4 +++- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/document.js b/lib/document.js index 188b554f296..bcf547992f7 100644 --- a/lib/document.js +++ b/lib/document.js @@ -13,6 +13,7 @@ var ValidatorError = require('./schematype').ValidatorError; var VirtualType = require('./virtualtype'); var utils = require('./utils'); var clone = utils.clone; +var isDefiningProjection = require('./services/projection/isDefiningProjection'); var isMongooseObject = utils.isMongooseObject; var inspect = require('util').inspect; var ValidationError = MongooseError.ValidationError; @@ -189,10 +190,7 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) { while (ki--) { // Does this projection explicitly define inclusion/exclusion? // Explicitly avoid `$meta` and `$slice` - var isDefiningProjection = !fields[keys[ki]] || - typeof fields[keys[ki]] !== 'object' || - fields[keys[ki]].$elemMatch != null; - if (keys[ki] !== '_id' && isDefiningProjection) { + if (keys[ki] !== '_id' && isDefiningProjection(keys[ki])) { exclude = !fields[keys[ki]]; break; } @@ -1258,8 +1256,7 @@ Document.prototype.isSelected = function isSelected(path) { if (cur === '_id') { continue; } - var projection = this.$__.selected[cur]; - if (projection && (projection.$meta || projection.$slice)) { + if (!isDefiningProjection(this.$__.selected[cur])) { continue; } inclusive = !!this.$__.selected[cur]; @@ -1336,7 +1333,7 @@ Document.prototype.isDirectSelected = function isDirectSelected(path) { if (cur === '_id') { continue; } - if (this.$__.selected[cur] && this.$__.selected[cur].$meta) { + if (!isDefiningProjection(this.$__.selected[cur])) { continue; } inclusive = !!this.$__.selected[cur]; diff --git a/lib/services/projection/isDefiningProjection.js b/lib/services/projection/isDefiningProjection.js index 710d4b89929..67dfb39fc68 100644 --- a/lib/services/projection/isDefiningProjection.js +++ b/lib/services/projection/isDefiningProjection.js @@ -15,4 +15,4 @@ module.exports = function isDefiningProjection(val) { return !('$meta' in val) && !('$slice' in val); } return true; -} +}; diff --git a/lib/services/projection/isInclusive.js b/lib/services/projection/isInclusive.js index c7ed9b7a829..64c3ded349d 100644 --- a/lib/services/projection/isInclusive.js +++ b/lib/services/projection/isInclusive.js @@ -1,5 +1,7 @@ 'use strict'; +var isDefiningProjection = require('./isDefiningProjection'); + /*! * ignore */ @@ -19,7 +21,7 @@ module.exports = function isInclusive(projection) { var prop = props[i]; // If field is truthy (1, true, etc.) and not an object, then this // projection must be inclusive. If object, assume its $meta, $slice, etc. - if (typeof projection[prop] !== 'object' && !!projection[prop]) { + if (isDefiningProjection(projection[prop]) && !!projection[prop]) { return true; } } From 1c3e21047b2ae256cd68b5d0a1519a3b9e7d19a6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 7 Dec 2017 19:45:18 -0800 Subject: [PATCH 2133/2240] test: fix tests re: #5881 --- lib/document.js | 2 +- test/query.test.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/document.js b/lib/document.js index bcf547992f7..577c1540a68 100644 --- a/lib/document.js +++ b/lib/document.js @@ -190,7 +190,7 @@ Document.prototype.$__buildDoc = function(obj, fields, skipId) { while (ki--) { // Does this projection explicitly define inclusion/exclusion? // Explicitly avoid `$meta` and `$slice` - if (keys[ki] !== '_id' && isDefiningProjection(keys[ki])) { + if (keys[ki] !== '_id' && isDefiningProjection(fields[keys[ki]])) { exclude = !fields[keys[ki]]; break; } diff --git a/test/query.test.js b/test/query.test.js index efe5b6beae4..f5807a6e71e 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2412,8 +2412,7 @@ describe('Query', function() { }); it('slice projection', function(done) { - MyModel.findOne({name: 'John'}, {dependents: {$slice: 1}}). - exec(function(error, person) { + MyModel.findOne({name: 'John'}, {dependents: {$slice: 1}}).exec(function(error, person) { assert.ifError(error); assert.equal(person.salary, 25000); done(); From 5025a4e39b3bd7055f2acadc13d683ce1cfe3f37 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Dec 2017 18:12:27 -0800 Subject: [PATCH 2134/2240] test(document): repro #5861 --- test/document.test.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 446058dfb92..f95a96f7774 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3946,6 +3946,46 @@ describe('document', function() { catch(done); }); + it('runs validate hooks on arrays subdocs if not directly modified (gh-5861)', function(done) { + var childSchema = new Schema({ + name: { type: String }, + friends: [{ type: String }] + }); + var count = 0; + + childSchema.pre('validate', function(next) { + ++count; + next(); + }); + + var parentSchema = new Schema({ + name: { type: String }, + children: [childSchema] + }); + + var Parent = db.model('gh5861', parentSchema); + + var p = new Parent({ + name: 'Mufasa', + children: [{ + name: 'Simba', + friends: ['Pumbaa', 'Timon', 'Nala'] + }] + }); + + p.save(). + then(function(p) { + assert.equal(count, 1); + p.children[0].friends.push('Rafiki'); + return p.save(); + }). + then(function() { + assert.equal(count, 2); + done(); + }). + catch(done); + }); + it('does not overwrite when setting nested (gh-4793)', function(done) { var grandchildSchema = new mongoose.Schema(); grandchildSchema.method({ @@ -5028,6 +5068,7 @@ describe('document', function() { assert.ifError(error); var child = doc.children.id(doc.children[0]._id); child.phoneNumber = '345'; + assert.equal(contexts.length, 1); doc.save(function(error) { assert.ifError(error); assert.equal(contexts.length, 2); From eb2c337871f6d339f74f4f51df3e1948b8a9df95 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 8 Dec 2017 18:13:21 -0800 Subject: [PATCH 2135/2240] fix(document): run validate hooks on array subdocs even if not directly modified Fix #5861 Future Work: #5885 --- lib/document.js | 16 ++++++++++------ lib/schema/documentarray.js | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/document.js b/lib/document.js index 577c1540a68..d61789fe69a 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1413,9 +1413,13 @@ function _getPathsToValidate(doc) { len = subdocs.length; for (i = 0; i < len; ++i) { subdoc = subdocs[i]; - if (subdoc.$isSingleNested && - doc.isModified(subdoc.$basePath) && + if (doc.isModified(subdoc.$basePath) && !doc.isDirectModified(subdoc.$basePath)) { + // Remove child paths for now, because we'll be validating the whole + // subdoc + paths = paths.filter(function(p) { + return p != null && p.indexOf(subdoc.$basePath + '.') !== 0; + }); paths.push(subdoc.$basePath); } } @@ -1499,8 +1503,8 @@ Document.prototype.$__validate = function(callback) { }); } - var validating = {}, - total = 0; + var validated = {}; + var total = 0; var complete = function() { var error = _complete(); @@ -1513,11 +1517,11 @@ Document.prototype.$__validate = function(callback) { }; var validatePath = function(path) { - if (validating[path]) { + if (path == null || validated[path]) { return; } - validating[path] = true; + validated[path] = true; total++; process.nextTick(function() { diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 97ee114262c..9f4c469e066 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -27,6 +27,7 @@ var utils = require('../utils'); function DocumentArray(key, schema, options) { var EmbeddedDocument = _createConstructor(schema, options); + EmbeddedDocument.prototype.$basePath = key; ArrayType.call(this, key, EmbeddedDocument, options); From 580b2d5adb05f172f0310526b908f45608e37529 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 9 Dec 2017 18:37:51 -0800 Subject: [PATCH 2136/2240] chore: more consistent copy --- lib/services/cursor/eachAsync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/cursor/eachAsync.js b/lib/services/cursor/eachAsync.js index 03675a7fb1f..251fe9c8252 100644 --- a/lib/services/cursor/eachAsync.js +++ b/lib/services/cursor/eachAsync.js @@ -30,7 +30,7 @@ module.exports = function eachAsync(next, fn, options, callback) { if (promise && typeof promise.then === 'function') { promise.then( function() { callback(null); }, - function(error) { callback(error || new Error('User\'s @fn called reject() (without an error).')); }); + function(error) { callback(error || new Error('`eachAsync()` promise rejected without error')); }); } else { callback(null); } From e044fdebb2367fb5fce0956311a5d70a8e114a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6kay=20G=C3=BCrcan?= Date: Sun, 10 Dec 2017 18:08:27 +0100 Subject: [PATCH 2137/2240] Update schematypes.jade Fix syntax error --- docs/schematypes.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/schematypes.jade b/docs/schematypes.jade index 0411d5394e5..5379814e222 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -51,8 +51,8 @@ block content ofBoolean: [Boolean], ofMixed: [Schema.Types.Mixed], ofObjectId: [Schema.Types.ObjectId], - ofArrays: [[]] - ofArrayOfNumbers: [[Number]] + ofArrays: [[]], + ofArrayOfNumbers: [[Number]], nested: { stuff: { type: String, lowercase: true, trim: true } } From e5fbd0106a912ad591dbfa751a608c0d6fd5ed16 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 11 Dec 2017 18:01:05 -0800 Subject: [PATCH 2138/2240] chore: release 4.13.7 --- History.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 1a51cca6125..0c1a4f7e1c1 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,16 @@ +4.13.7 / 2017-12-11 +=================== + * docs(schematypes): fix typo #5889 [gokaygurcan](https://github.com/gokaygurcan) + * fix(cursor): handle `reject(null)` with eachAsync callback #5875 #5874 [ZacharyRSmith](https://github.com/ZacharyRSmith) + * fix: disallow setting `mongoose.connection` to invalid values #5871 [jinasonlin](https://github.com/jinasonlin) + * docs(middleware): suggest using `return next()` to stop middleware execution #5866 + * docs(connection): improve connection string query param docs #5864 + * fix(document): run validate hooks on array subdocs even if not directly modified #5861 + * fix(discriminator): don't treat $meta as defining projection when querying #5859 + * fix(types): handle Decimal128 when using bson-ext on server side #5850 + * fix(document): ensure projection with only $slice isn't treated as inclusive for discriminators #4991 + * fix(model): throw error when passing non-object to create() #2037 + 4.13.6 / 2017-12-02 =================== * fix(schema): support strictBool option in schema #5856 [ekulabuhov](https://github.com/ekulabuhov) diff --git a/package.json b/package.json index 18d67ce3784..3ceb6bb1076 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.7-pre", + "version": "4.13.7", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 722d0ab2a53878e45f1964b6e8350ad12151b4a0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 11 Dec 2017 18:10:25 -0800 Subject: [PATCH 2139/2240] chore: now working on 4.13.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ceb6bb1076..4f44134c320 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.7", + "version": "4.13.8-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 1996a0639eafb206eb835ba76c9e38658648b05b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 18 Dec 2017 16:10:57 -0800 Subject: [PATCH 2140/2240] chore: bump lockfile --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 50aecde2643..b550c856be3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.7-pre", + "version": "4.13.8-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From ed8e874246190da43960a17a8034e02823c8c0a2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 18 Dec 2017 16:48:23 -0800 Subject: [PATCH 2141/2240] test(populate): repro #5858 --- test/model.populate.test.js | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 2f861b79a2b..5e0ecce9248 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5859,6 +5859,70 @@ describe('model: populate:', function() { catch(done); }); + it('subPopulate under discriminators race condition (gh-5858)', function() { + var options = { discriminatorKey: 'kind' }; + var activitySchema = new Schema({ title: { type: String } }, options); + + var dateActivitySchema = new Schema({ + postedBy: { + type: Schema.Types.ObjectId, + ref: 'gh5858', + required: true + } + }, options); + + var eventActivitySchema = new Schema({ test: String }, options); + + var logSchema = new Schema({ + seq: Number, + activity: { + type: Schema.Types.ObjectId, + refPath: 'kind', + required: true + }, + kind: String + }, options); + + var User = db.model('gh5858', { name: String }); + var Activity = db.model('gh5858_0', activitySchema); + var DateActivity = Activity.discriminator('gh5858_1', dateActivitySchema); + var EventActivity = Activity.discriminator('gh5858_2', eventActivitySchema); + var Log = db.model('gh5858_3', logSchema); + + var dateActivity; + var eventActivity; + return User.create({ name: 'val' }). + then(function(user) { + return DateActivity.create({ title: 'test', postedBy: user._id }); + }). + then(function(_dateActivity) { + dateActivity = _dateActivity; + return EventActivity.create({ title: 'test' }); + }). + then(function(_eventActivity) { + eventActivity = _eventActivity; + return Log.create([ + { seq: 1, activity: eventActivity._id, kind: 'gh5858_2' }, + { seq: 2, activity: dateActivity._id, kind: 'gh5858_1' } + ]); + }). + then(function() { + return Log.find({}). + populate({ + path: 'activity', + populate: { path: 'postedBy' } + }). + sort({ seq:-1 }); + }). + then(function(results) { + assert.equal(results.length, 2); + assert.equal(results[0].activity.kind, 'gh5858_1' ); + assert.equal(results[0].activity.postedBy.name, 'val'); + assert.equal(results[1].activity.kind, 'gh5858_2' ); + assert.equal(results[1].activity.postedBy, null); + }); + }); + it('specify model in populate (gh-4264)', function(done) { var PersonSchema = new Schema({ name: String, From 4e645964edf8d5d3c881d00955ae43f7ce8fb718 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 18 Dec 2017 16:49:08 -0800 Subject: [PATCH 2142/2240] fix(populate): use correct model with discriminators + nested populate Fix #5858 --- lib/model.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index cc961a3c515..543e05a1307 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3261,7 +3261,9 @@ function populate(model, docs, options, callback) { mod.options.options.limit = mod.options.options.limit * ids.length; } - var subPopulate = mod.options.populate; + var subPopulate = utils.clone(mod.options.populate, { + retainKeyOrder: true + }); var query = mod.Model.find(match, select, mod.options.options); // If we're doing virtual populate and projection is inclusive and foreign From ccec46f1408cde2117c952e05848b97ef10d4a07 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 19 Dec 2017 17:22:55 -0800 Subject: [PATCH 2143/2240] fix: propagate lean options to child schemas Fix #5914 --- lib/queryhelpers.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/queryhelpers.js b/lib/queryhelpers.js index 8f52106c441..c9d99277cd4 100644 --- a/lib/queryhelpers.js +++ b/lib/queryhelpers.js @@ -19,7 +19,9 @@ exports.preparePopulationOptions = function preparePopulationOptions(query, opti var pop = utils.object.vals(query.options.populate); // lean options should trickle through all queries - if (options.lean) pop.forEach(makeLean); + if (options.lean) { + pop.forEach(makeLean(options.lean)); + } return pop; }; @@ -37,7 +39,9 @@ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query, var pop = utils.object.vals(query._mongooseOptions.populate); // lean options should trickle through all queries - if (options.lean) pop.forEach(makeLean); + if (options.lean) { + pop.forEach(makeLean(options.lean)); + } return pop; }; @@ -207,7 +211,9 @@ exports.applyPaths = function applyPaths(fields, schema) { * @param {Object} option */ -function makeLean(option) { - option.options || (option.options = {}); - option.options.lean = true; +function makeLean(val) { + return function(option) { + option.options || (option.options = {}); + option.options.lean = val; + }; } From a159115c0c73b4467959656d605b846f18e14b22 Mon Sep 17 00:00:00 2001 From: Aram Baghdassarian Date: Wed, 20 Dec 2017 20:56:01 -0500 Subject: [PATCH 2144/2240] Grammar change: it's --> its --- docs/2.7.x/docs/populate.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/2.7.x/docs/populate.html b/docs/2.7.x/docs/populate.html index b6749022c7c..0fbdfa919b8 100644 --- a/docs/2.7.x/docs/populate.html +++ b/docs/2.7.x/docs/populate.html @@ -230,7 +230,7 @@

    Populate - DBRef-like behavior

    var Person = mongoose.model('Person', PersonSchema);
    -

    So far we've created two models. Our Person model has it's stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    +

    So far we've created two models. Our Person model has its stories field set to an array of ObjectIds. The ref option is what tells Mongoose in which model to look, in our case the Story model. All _ids we store here must be document _ids from the Story model. We also added a _creator ObjectId to our Story schema which refers to a single Person.

    Saving a ref (to the parent)

    From f59defb10ce8c6f38a330291ecc89bf63a93fc8f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 24 Dec 2017 07:57:07 -0800 Subject: [PATCH 2145/2240] refactor: fix a few tests re: #5891 --- test/schema.validation.test.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/test/schema.validation.test.js b/test/schema.validation.test.js index 7ba04f170ba..a017f47f2e6 100644 --- a/test/schema.validation.test.js +++ b/test/schema.validation.test.js @@ -377,18 +377,22 @@ describe('schema', function() { likes: {type: Array, required: true} }); + var remaining = 3; + Loki.path('likes').doValidate(null, function(err) { assert.ok(err instanceof ValidatorError); + --remaining || done(); }); Loki.path('likes').doValidate(undefined, function(err) { assert.ok(err instanceof ValidatorError); + --remaining || done(); }); Loki.path('likes').doValidate([], function(err) { assert.ok(err instanceof ValidatorError); + --remaining || done(); }); - done(); }); it('boolean required', function(done) { @@ -396,22 +400,27 @@ describe('schema', function() { isFerret: {type: Boolean, required: true} }); + var remaining = 4; + Animal.path('isFerret').doValidate(null, function(err) { assert.ok(err instanceof ValidatorError); + --remaining || done(); }); Animal.path('isFerret').doValidate(undefined, function(err) { assert.ok(err instanceof ValidatorError); + --remaining || done(); }); Animal.path('isFerret').doValidate(true, function(err) { assert.ifError(err); + --remaining || done(); }); Animal.path('isFerret').doValidate(false, function(err) { assert.ifError(err); + --remaining || done(); }); - done(); }); it('mixed required', function(done) { @@ -419,24 +428,29 @@ describe('schema', function() { characteristics: {type: Mixed, required: true} }); + var remaining = 4; + Animal.path('characteristics').doValidate(null, function(err) { assert.ok(err instanceof ValidatorError); + --remaining || done(); }); Animal.path('characteristics').doValidate(undefined, function(err) { assert.ok(err instanceof ValidatorError); + --remaining || done(); }); Animal.path('characteristics').doValidate({ aggresive: true }, function(err) { assert.ifError(err); + --remaining || done(); }); Animal.path('characteristics').doValidate('none available', function(err) { assert.ifError(err); + --remaining || done(); }); - done(); }); }); From 41ff691a08de2946d91e291cc7cfdd857eb6d098 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 26 Dec 2017 18:05:47 -0800 Subject: [PATCH 2146/2240] chore: bump nsp --- package-lock.json | 926 +++++++++++++++++++++++++++++++++++----------- package.json | 2 +- 2 files changed, 720 insertions(+), 208 deletions(-) diff --git a/package-lock.json b/package-lock.json index b550c856be3..a89c143223e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,6 +75,15 @@ "integrity": "sha1-U20adFyqaGf/oILwlJmvzjIn3vo=", "dev": true }, + "agent-base": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.1.2.tgz", + "integrity": "sha512-VE6QoEdaugY86BohRtfGmTDabxdU5sCKOkbcPA6PXKJsRzEi/7A3RCTxJal1ft/4qSfPht5/iQLhMh/wzSkkNw==", + "dev": true, + "requires": { + "es6-promisify": "5.0.0" + } + }, "ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", @@ -453,6 +462,15 @@ "type-is": "1.6.15" } }, + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -479,6 +497,12 @@ "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -535,6 +559,12 @@ "supports-color": "2.0.0" } }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -550,6 +580,25 @@ "restore-cursor": "1.0.1" } }, + "cli-table2": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/cli-table2/-/cli-table2-0.2.0.tgz", + "integrity": "sha1-LR738hig54biFFQFYtS9F3/jLZc=", + "dev": true, + "requires": { + "colors": "1.1.2", + "lodash": "3.10.1", + "string-width": "1.0.2" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -593,6 +642,21 @@ "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", "dev": true }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", @@ -663,6 +727,35 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + } + } + }, + "cvss": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cvss/-/cvss-1.0.2.tgz", + "integrity": "sha1-32fpK/EqeW9J6Sh5nI2zunS5/NY=", + "dev": true + }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -816,6 +909,15 @@ "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", "dev": true }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, "es5-ext": { "version": "0.10.30", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", @@ -856,6 +958,23 @@ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "4.2.2" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.2.tgz", + "integrity": "sha512-LSas5vsuA6Q4nEdf9wokY5/AJYXry98i0IzXsv49rYsgDGDNDPbqAYR1Pe23iFxygfbGZNR/5VrHXBCh2BhvUQ==", + "dev": true + } + } + }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", @@ -1044,6 +1163,21 @@ "es5-ext": "0.10.30" } }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", @@ -1088,6 +1222,17 @@ "vary": "1.1.2" } }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + } + }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -1163,6 +1308,15 @@ "unpipe": "1.0.0" } }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -1268,6 +1422,18 @@ "is-property": "1.0.2" } }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, "github-flavored-markdown": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/github-flavored-markdown/-/github-flavored-markdown-1.0.1.tgz", @@ -1391,6 +1557,12 @@ "integrity": "sha1-QuRhuYoNPE+QzQtmg2TGXAi8bdA=", "dev": true }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", + "dev": true + }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", @@ -1406,6 +1578,12 @@ "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.2.tgz", "integrity": "sha512-YurCM4gQSetcrhwEtpQHhQ4M7Zo7poNGqY4kQGeBS6eZtOcT3tnNs01ThFa0jYBByAiYt1MjMjP/YApG0EnAvQ==" }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", @@ -1426,6 +1604,27 @@ } } }, + "https-proxy-agent": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz", + "integrity": "sha512-LK6tQUR/VOkTI6ygAfWUKKP95I+e6M1h7N3PncGu1CATHCnex+CAv9ttR0lbHu1Uk2PXm/WoAHFo6JCGwMjVMw==", + "dev": true, + "requires": { + "agent-base": "4.1.2", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", @@ -1489,18 +1688,39 @@ "loose-envify": "1.3.1" } }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, "ipaddr.js": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=", "dev": true }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, "is-buffer": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", "dev": true }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, "is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", @@ -1555,6 +1775,12 @@ "path-is-inside": "1.0.2" } }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -1570,6 +1796,12 @@ "tryit": "1.0.3" } }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -1806,6 +2038,15 @@ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -1816,6 +2057,28 @@ "type-check": "0.3.2" } }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, "lodash": { "version": "4.16.6", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.6.tgz", @@ -1948,6 +2211,15 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -1981,6 +2253,12 @@ "mime-db": "1.30.0" } }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2202,6 +2480,12 @@ "optimist": "0.6.1" } }, + "nodesecurity-npm-utils": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-6.0.0.tgz", + "integrity": "sha512-NLRle1woNaT2orR6fue2jNqkhxDTktgJj3sZxvR/8kp21pvOY7Gwlx5wvo0H8ZVPqdgd2nE2ADB9wDu5Cl8zNg==", + "dev": true + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -2211,286 +2495,270 @@ "abbrev": "1.0.9" } }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, "nsp": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/nsp/-/nsp-2.8.1.tgz", - "integrity": "sha512-jvjDg2Gsw4coD/iZ5eQddsDlkvnwMCNnpG05BproSnuG+Gr1bSQMwWMcQeYje+qdDl3XznmhblMPLpZLecTORQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nsp/-/nsp-3.1.0.tgz", + "integrity": "sha512-jtD2WMlmqWA3zSZTFog8MQkwUvXWdJD7ps7A30q8ImOIao0RFgZXbPPZ8O6yWaKxLbRxVUIoCfwvXyg7AVS+IA==", "dev": true, "requires": { - "chalk": "1.1.3", - "cli-table": "0.3.1", + "chalk": "2.3.0", + "cli-table2": "0.2.0", "cvss": "1.0.2", - "https-proxy-agent": "1.0.0", - "joi": "6.10.1", - "nodesecurity-npm-utils": "5.0.0", - "path-is-absolute": "1.0.1", - "rc": "1.2.1", + "https-proxy-agent": "2.1.1", + "inquirer": "3.3.0", + "nodesecurity-npm-utils": "6.0.0", "semver": "5.4.1", - "subcommand": "2.1.0", - "wreck": "6.3.0" + "wreck": "12.5.1", + "yargs": "9.0.1" }, "dependencies": { - "agent-base": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true, - "requires": { - "extend": "3.0.1", - "semver": "5.0.3" - }, - "dependencies": { - "semver": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true - } - } + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { - "hoek": "2.16.3" + "color-convert": "1.9.1" } }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { - "ansi-styles": "2.2.1", + "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "supports-color": "4.5.0" } }, - "cli-table": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", - "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "colors": "1.0.3" + "restore-cursor": "2.0.0" } }, - "cliclopts": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cliclopts/-/cliclopts-1.1.1.tgz", - "integrity": "sha1-aUMcfLWvcjd0sNORG0w3USQxkQ8=", - "dev": true - }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true - }, - "cvss": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cvss/-/cvss-1.0.2.tgz", - "integrity": "sha1-32fpK/EqeW9J6Sh5nI2zunS5/NY=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "ms": "2.0.0" + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } } }, - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "has-ansi": { + "figures": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "escape-string-regexp": "1.0.5" } }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.16.6", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" } }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "isemail": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", - "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=", + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "joi": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", - "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "hoek": "2.16.3", - "isemail": "1.2.0", - "moment": "2.18.1", - "topo": "1.1.0" + "mimic-fn": "1.1.0" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "moment": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", - "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=", - "dev": true - }, - "ms": { + "restore-cursor": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "nodesecurity-npm-utils": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-5.0.0.tgz", - "integrity": "sha1-Baow3jDKjIRcQEjpT9eOXgi1Xtk=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } }, - "rc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", - "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "is-promise": "2.1.0" } }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", "dev": true }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" } }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "subcommand": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/subcommand/-/subcommand-2.1.0.tgz", - "integrity": "sha1-XkzspaN3njNlsVEeBfhmh3MC92A=", + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "cliclopts": "1.1.1", - "debug": "2.6.9", - "minimist": "1.2.0", - "xtend": "4.0.1" + "ansi-regex": "3.0.0" } }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "topo": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", - "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "hoek": "2.16.3" + "has-flag": "2.0.0" } }, - "wreck": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/wreck/-/wreck-6.3.0.tgz", - "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, "requires": { - "boom": "2.10.1", - "hoek": "2.16.3" + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true } } }, @@ -2574,18 +2842,65 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", "dev": true }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2598,6 +2913,12 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", @@ -2610,6 +2931,15 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", "dev": true }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -2804,6 +3134,12 @@ "ipaddr.js": "1.5.2" } }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -2834,6 +3170,27 @@ "unpipe": "1.0.0" } }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, "readable-stream": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", @@ -2894,6 +3251,18 @@ "semver": "5.4.1" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -2991,6 +3360,15 @@ "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", "dev": true }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "3.1.2" + } + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -3042,12 +3420,33 @@ "send": "0.16.1" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "shelljs": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", @@ -3060,6 +3459,12 @@ "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", "dev": true }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -3104,6 +3509,27 @@ } } }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3155,6 +3581,18 @@ "ansi-regex": "2.1.1" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, "strip-json-comments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", @@ -3237,6 +3675,15 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", @@ -3379,6 +3826,16 @@ "integrity": "sha1-9GV3F2JLDkuIrzb5jYlYmlu+5Wk=", "dev": true }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, "validator": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/validator/-/validator-5.4.0.tgz", @@ -3406,6 +3863,12 @@ "isexe": "2.0.0" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -3418,12 +3881,32 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "wreck": { + "version": "12.5.1", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-12.5.1.tgz", + "integrity": "sha512-l5DUGrc+yDyIflpty1x9XuMj1ehVjC/dTbF3/BasOO77xk0EdEa4M/DuOY8W88MQDAD0fEDqyjc8bkIMHd2E9A==", + "dev": true, + "requires": { + "boom": "5.2.0", + "hoek": "4.2.0" + } + }, "write": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", @@ -3439,6 +3922,18 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", @@ -3450,6 +3945,23 @@ "decamelize": "1.2.0", "window-size": "0.1.0" } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } } } } diff --git a/package.json b/package.json index 4f44134c320..8277101d44e 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "mongoose-long": "0.1.1", "mongodb-topology-manager": "1.0.11", "node-static": "0.7.7", - "nsp": "~2.8.1", + "nsp": "3.1.0", "power-assert": "1.4.1", "q": "1.5.1", "tbd": "0.6.4", From fb21c07bc56eb91bf3280f59cc4b2915425f0e9d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 26 Dec 2017 18:17:39 -0800 Subject: [PATCH 2147/2240] Revert "chore: bump nsp" This reverts commit 41ff691a08de2946d91e291cc7cfdd857eb6d098. --- package-lock.json | 926 +++++++++++----------------------------------- package.json | 2 +- 2 files changed, 208 insertions(+), 720 deletions(-) diff --git a/package-lock.json b/package-lock.json index a89c143223e..b550c856be3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,15 +75,6 @@ "integrity": "sha1-U20adFyqaGf/oILwlJmvzjIn3vo=", "dev": true }, - "agent-base": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.1.2.tgz", - "integrity": "sha512-VE6QoEdaugY86BohRtfGmTDabxdU5sCKOkbcPA6PXKJsRzEi/7A3RCTxJal1ft/4qSfPht5/iQLhMh/wzSkkNw==", - "dev": true, - "requires": { - "es6-promisify": "5.0.0" - } - }, "ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", @@ -462,15 +453,6 @@ "type-is": "1.6.15" } }, - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, - "requires": { - "hoek": "4.2.0" - } - }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -497,12 +479,6 @@ "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -559,12 +535,6 @@ "supports-color": "2.0.0" } }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -580,25 +550,6 @@ "restore-cursor": "1.0.1" } }, - "cli-table2": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/cli-table2/-/cli-table2-0.2.0.tgz", - "integrity": "sha1-LR738hig54biFFQFYtS9F3/jLZc=", - "dev": true, - "requires": { - "colors": "1.1.2", - "lodash": "3.10.1", - "string-width": "1.0.2" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - } - } - }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -642,21 +593,6 @@ "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", "dev": true }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", @@ -727,35 +663,6 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - } - } - }, - "cvss": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cvss/-/cvss-1.0.2.tgz", - "integrity": "sha1-32fpK/EqeW9J6Sh5nI2zunS5/NY=", - "dev": true - }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -909,15 +816,6 @@ "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", "dev": true }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, - "requires": { - "is-arrayish": "0.2.1" - } - }, "es5-ext": { "version": "0.10.30", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", @@ -958,23 +856,6 @@ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "4.2.2" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.2.tgz", - "integrity": "sha512-LSas5vsuA6Q4nEdf9wokY5/AJYXry98i0IzXsv49rYsgDGDNDPbqAYR1Pe23iFxygfbGZNR/5VrHXBCh2BhvUQ==", - "dev": true - } - } - }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", @@ -1163,21 +1044,6 @@ "es5-ext": "0.10.30" } }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - }, "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", @@ -1222,17 +1088,6 @@ "vary": "1.1.2" } }, - "external-editor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", - "dev": true, - "requires": { - "chardet": "0.4.2", - "iconv-lite": "0.4.19", - "tmp": "0.0.33" - } - }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -1308,15 +1163,6 @@ "unpipe": "1.0.0" } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "2.0.0" - } - }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -1422,18 +1268,6 @@ "is-property": "1.0.2" } }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, "github-flavored-markdown": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/github-flavored-markdown/-/github-flavored-markdown-1.0.1.tgz", @@ -1557,12 +1391,6 @@ "integrity": "sha1-QuRhuYoNPE+QzQtmg2TGXAi8bdA=", "dev": true }, - "hoek": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", - "dev": true - }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", @@ -1578,12 +1406,6 @@ "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.2.tgz", "integrity": "sha512-YurCM4gQSetcrhwEtpQHhQ4M7Zo7poNGqY4kQGeBS6eZtOcT3tnNs01ThFa0jYBByAiYt1MjMjP/YApG0EnAvQ==" }, - "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", - "dev": true - }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", @@ -1604,27 +1426,6 @@ } } }, - "https-proxy-agent": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz", - "integrity": "sha512-LK6tQUR/VOkTI6ygAfWUKKP95I+e6M1h7N3PncGu1CATHCnex+CAv9ttR0lbHu1Uk2PXm/WoAHFo6JCGwMjVMw==", - "dev": true, - "requires": { - "agent-base": "4.1.2", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", @@ -1688,39 +1489,18 @@ "loose-envify": "1.3.1" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "ipaddr.js": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=", "dev": true }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, "is-buffer": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", "dev": true }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "1.1.1" - } - }, "is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", @@ -1775,12 +1555,6 @@ "path-is-inside": "1.0.2" } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -1796,12 +1570,6 @@ "tryit": "1.0.3" } }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -2038,15 +1806,6 @@ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "1.0.0" - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -2057,28 +1816,6 @@ "type-check": "0.3.2" } }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - } - }, "lodash": { "version": "4.16.6", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.6.tgz", @@ -2211,15 +1948,6 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "1.1.0" - } - }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -2253,12 +1981,6 @@ "mime-db": "1.30.0" } }, - "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", - "dev": true - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2480,12 +2202,6 @@ "optimist": "0.6.1" } }, - "nodesecurity-npm-utils": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-6.0.0.tgz", - "integrity": "sha512-NLRle1woNaT2orR6fue2jNqkhxDTktgJj3sZxvR/8kp21pvOY7Gwlx5wvo0H8ZVPqdgd2nE2ADB9wDu5Cl8zNg==", - "dev": true - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -2495,270 +2211,286 @@ "abbrev": "1.0.9" } }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.1" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "2.0.1" - } - }, "nsp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nsp/-/nsp-3.1.0.tgz", - "integrity": "sha512-jtD2WMlmqWA3zSZTFog8MQkwUvXWdJD7ps7A30q8ImOIao0RFgZXbPPZ8O6yWaKxLbRxVUIoCfwvXyg7AVS+IA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/nsp/-/nsp-2.8.1.tgz", + "integrity": "sha512-jvjDg2Gsw4coD/iZ5eQddsDlkvnwMCNnpG05BproSnuG+Gr1bSQMwWMcQeYje+qdDl3XznmhblMPLpZLecTORQ==", "dev": true, "requires": { - "chalk": "2.3.0", - "cli-table2": "0.2.0", + "chalk": "1.1.3", + "cli-table": "0.3.1", "cvss": "1.0.2", - "https-proxy-agent": "2.1.1", - "inquirer": "3.3.0", - "nodesecurity-npm-utils": "6.0.0", + "https-proxy-agent": "1.0.0", + "joi": "6.10.1", + "nodesecurity-npm-utils": "5.0.0", + "path-is-absolute": "1.0.1", + "rc": "1.2.1", "semver": "5.4.1", - "wreck": "12.5.1", - "yargs": "9.0.1" + "subcommand": "2.1.0", + "wreck": "6.3.0" }, "dependencies": { - "ansi-escapes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", - "dev": true + "agent-base": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "color-convert": "1.9.1" + "hoek": "2.16.3" } }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", "dev": true, "requires": { - "restore-cursor": "2.0.0" + "colors": "1.0.3" } }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "cliclopts": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cliclopts/-/cliclopts-1.1.1.tgz", + "integrity": "sha1-aUMcfLWvcjd0sNORG0w3USQxkQ8=", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, + "cvss": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cvss/-/cvss-1.0.2.tgz", + "integrity": "sha1-32fpK/EqeW9J6Sh5nI2zunS5/NY=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - } + "ms": "2.0.0" } }, - "figures": { + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "has-ansi": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5" + "ansi-regex": "2.1.1" } }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", "dev": true }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", "dev": true, "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.0", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.16.6", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" } }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", "dev": true }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "isemail": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", + "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=", "dev": true }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "joi": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", + "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", "dev": true, "requires": { - "mimic-fn": "1.1.0" + "hoek": "2.16.3", + "isemail": "1.2.0", + "moment": "2.18.1", + "topo": "1.1.0" } }, - "restore-cursor": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "moment": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", + "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=", + "dev": true + }, + "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "nodesecurity-npm-utils": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-5.0.0.tgz", + "integrity": "sha1-Baow3jDKjIRcQEjpT9eOXgi1Xtk=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", "dev": true, "requires": { - "is-promise": "2.1.0" + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" } }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "ansi-regex": "2.1.1" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "subcommand": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/subcommand/-/subcommand-2.1.0.tgz", + "integrity": "sha1-XkzspaN3njNlsVEeBfhmh3MC92A=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "cliclopts": "1.1.1", + "debug": "2.6.9", + "minimist": "1.2.0", + "xtend": "4.0.1" } }, "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "topo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", + "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", "dev": true, "requires": { - "has-flag": "2.0.0" + "hoek": "2.16.3" } }, - "yargs": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", - "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "wreck": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-6.3.0.tgz", + "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", "dev": true, "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "7.0.0" + "boom": "2.10.1", + "hoek": "2.16.3" } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true } } }, @@ -2842,65 +2574,18 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "1.1.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "1.3.1" - } - }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", "dev": true }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2913,12 +2598,6 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", @@ -2931,15 +2610,6 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", "dev": true }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "2.3.0" - } - }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -3134,12 +2804,6 @@ "ipaddr.js": "1.5.2" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -3170,27 +2834,6 @@ "unpipe": "1.0.0" } }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" - } - }, "readable-stream": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", @@ -3251,18 +2894,6 @@ "semver": "5.4.1" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -3360,15 +2991,6 @@ "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", "dev": true }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "3.1.2" - } - }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -3420,33 +3042,12 @@ "send": "0.16.1" } }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, "shelljs": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", @@ -3459,12 +3060,6 @@ "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", "dev": true }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -3509,27 +3104,6 @@ } } }, - "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "dev": true, - "requires": { - "spdx-license-ids": "1.2.2" - } - }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", - "dev": true - }, - "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", - "dev": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3581,18 +3155,6 @@ "ansi-regex": "2.1.1" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, "strip-json-comments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", @@ -3675,15 +3237,6 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "1.0.2" - } - }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", @@ -3826,16 +3379,6 @@ "integrity": "sha1-9GV3F2JLDkuIrzb5jYlYmlu+5Wk=", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true, - "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" - } - }, "validator": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/validator/-/validator-5.4.0.tgz", @@ -3863,12 +3406,6 @@ "isexe": "2.0.0" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -3881,32 +3418,12 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "wreck": { - "version": "12.5.1", - "resolved": "https://registry.npmjs.org/wreck/-/wreck-12.5.1.tgz", - "integrity": "sha512-l5DUGrc+yDyIflpty1x9XuMj1ehVjC/dTbF3/BasOO77xk0EdEa4M/DuOY8W88MQDAD0fEDqyjc8bkIMHd2E9A==", - "dev": true, - "requires": { - "boom": "5.2.0", - "hoek": "4.2.0" - } - }, "write": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", @@ -3922,18 +3439,6 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", @@ -3945,23 +3450,6 @@ "decamelize": "1.2.0", "window-size": "0.1.0" } - }, - "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true, - "requires": { - "camelcase": "4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - } - } } } } diff --git a/package.json b/package.json index 8277101d44e..4f44134c320 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "mongoose-long": "0.1.1", "mongodb-topology-manager": "1.0.11", "node-static": "0.7.7", - "nsp": "3.1.0", + "nsp": "~2.8.1", "power-assert": "1.4.1", "q": "1.5.1", "tbd": "0.6.4", From e179034c2c2df32b1f17535ed6141c5a9ae3efc8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Dec 2017 09:38:14 -0800 Subject: [PATCH 2148/2240] docs(README): add recommended import syntax Fix #5940 --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 8280d049fcb..1197d200c57 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,16 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed - [Help Forum](http://groups.google.com/group/mongoose-orm) - [MongoDB Support](https://docs.mongodb.org/manual/support/) +## Importing + +```javascript +// Using Node.js `require()` +const mongoose = require('mongoose'); + +// Using ES6 imports +import mongoose from 'mongoose'; +``` + ## Plugins Check out the [plugins search site](http://plugins.mongoosejs.io/) to see hundreds of related modules from the community. Next, learn how to write your own plugin from the [docs](http://mongoosejs.com/docs/plugins.html) or [this blog post](http://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins). From 3b6eec3eded2f16a7857b89e646d9acc669d7aa0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Dec 2017 09:40:38 -0800 Subject: [PATCH 2149/2240] docs(guide): use more up-to-date syntax for autoIndex example Fix #5933 --- docs/guide.jade | 102 ++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/docs/guide.jade b/docs/guide.jade index 8c389700ca1..e5ee549ae97 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -27,27 +27,27 @@ block content }); p em - | If you want to add additional keys later, use the + | If you want to add additional keys later, use the a(href="./api.html#schema_Schema-add") Schema#add | method. - p - | Each key in our + p + | Each key in our code blogSchema - | defines a property in our documents which will be cast to its associated + | defines a property in our documents which will be cast to its associated a(href="./api.html#schematype_SchemaType") SchemaType - |. For example, we've defined a + |. For example, we've defined a code title - | which will be cast to the + | which will be cast to the a(href="./api.html#schema-string-js") String - | SchemaType and + | SchemaType and code date - | which will be cast to a + | which will be cast to a code Date | SchemaType. - | Keys may also be assigned nested objects containing further key/type definitions + | Keys may also be assigned nested objects containing further key/type definitions em (e.g. the `meta` property above). p - | The permitted SchemaTypes are + | The permitted SchemaTypes are ul li String li Number @@ -57,17 +57,17 @@ block content li Mixed li ObjectId li Array - | Read more about them + | Read more about them a(href="./schematypes.html") here | . p - | Schemas not only define the structure of your document and casting of properties, they also define document + | Schemas not only define the structure of your document and casting of properties, they also define document a(href="#methods") instance methods - |, static + |, static a(href="#statics") Model methods - |, + |, a(href="#indexes") compound indexes - | and document lifecycle hooks called + | and document lifecycle hooks called a(href="./middleware.html") middleware |. @@ -93,9 +93,9 @@ block content return this.model('Animal').find({ type: this.type }, cb); }; p - | Now all of our + | Now all of our code animal - | instances have a + | instances have a code findSimilarTypes | method available to it. :js @@ -137,12 +137,12 @@ block content You can also add query helper functions, which are like instance methods but for mongoose queries. Query helper methods let you extend mongoose's [chainable query builder API](./queries.html). - + :js animalSchema.query.byName = function(name) { return this.find({ name: new RegExp(name, 'i') }); }; - + var Animal = mongoose.model('Animal', animalSchema); Animal.find().byName('fido').exec(function(err, animals) { console.log(animals); @@ -152,7 +152,7 @@ block content :markdown MongoDB supports [secondary indexes](http://docs.mongodb.org/manual/indexes/). With mongoose, we define these indexes within our `Schema` [at](./api.html#schematype_SchemaType-index) [the](./api.html#schematype_SchemaType-unique) [path](./api.html#schematype_SchemaType-sparse) [level](./api.html#schema_date_SchemaDate-expires) or the `schema` level. - Defining indexes at the schema level is necessary when creating + Defining indexes at the schema level is necessary when creating [compound indexes](http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys). :js @@ -168,12 +168,12 @@ block content :markdown When your application starts up, Mongoose automatically calls [`createIndex`](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex) for each defined index in your schema. Mongoose will call `createIndex` for each index sequentially, and emit an 'index' event on the model when all the `createIndex` calls succeeded or when there was an error. - While nice for development, it is recommended this behavior be disabled in production since index creation can cause a [significant performance impact](http://docs.mongodb.org/manual/core/indexes/#index-creation-operations). Disable the behavior by setting the `autoIndex` option of your schema to `false`, or globally on the connection by setting the option `config.autoIndex` to `false`. + While nice for development, it is recommended this behavior be disabled in production since index creation can cause a [significant performance impact](http://docs.mongodb.org/manual/core/indexes/#index-creation-operations). Disable the behavior by setting the `autoIndex` option of your schema to `false`, or globally on the connection by setting the option `autoIndex` to `false`. :js - mongoose.connect('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } }); - // or - mongoose.createConnection('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } }); + mongoose.connect('mongodb://user:pass@localhost:port/database', { autoIndex: false }); + // or + mongoose.createConnection('mongodb://user:pass@localhost:port/database', { autoIndex: false }); // or animalSchema.set('autoIndex', false); // or @@ -182,13 +182,13 @@ block content :markdown Mongoose will emit an `index` event on the model when indexes are done building or an error occurred. - + :js // Will cause an error because mongodb has an _id index by default that // is not sparse animalSchema.index({ _id: 1 }, { sparse: true }); var Animal = mongoose.model('Animal', animalSchema); - + Animal.on('index', function(error) { // "_id index cannot be sparse" console.log(error.message); @@ -240,7 +240,7 @@ block content :markdown If you use `toJSON()` or `toObject()` (or use `JSON.stringify()` on a mongoose document) mongoose will *not* include virtuals by default. - Pass `{ virtuals: true }` to either [toObject()](./api.html#document_Document-toObject) or `toJSON()`. + Pass `{ virtuals: true }` to either [toObject()](./api.html#document_Document-toObject) or `toJSON()`. You can also add a custom setter to your virtual that will let you set both first name and last name via the `fullName` virtual. @@ -251,18 +251,18 @@ block content this.name.first = v.substr(0, v.indexOf(' ')); this.name.last = v.substr(v.indexOf(' ') + 1); }); - + axl.fullName = 'William Rose'; // Now `axl.name.first` is "William" :markdown Virtual property setters are applied before other validation. So the example above would still work even if the `first` and `last` name fields were required. Only non-virtual properties work as part of queries and for field selection. Since virtuals are not stored in MongoDB, you can't query with them. - + h5#aliases Aliases :markdown Aliases are a particular type of virtual where the getter and setter seamlessly get and set another property. This is handy for saving network bandwidth, so you can convert a short property name stored in the database into a longer name for code readability. - + :js var personSchema = new Schema({ n: { @@ -271,13 +271,13 @@ block content alias: 'name' } }); - + // Setting `name` will propagate to `n` var person = new Person({ name: 'Val' }); console.log(person); // { n: 'Val' } console.log(person.toObject({ virtuals: true })); // { n: 'Val', name: 'Val' } console.log(person.name); // "Val" - + person.name = 'Not Val'; console.log(person); // { n: 'Not Val' } @@ -396,7 +396,7 @@ block content The type assigned is an [ObjectId](/docs/api.html#schema_Schema.Types) to coincide with MongoDB's default behavior. If you don't want an `_id` added to your schema at all, you may disable it using this option. - + You can **only** use this option on sub-documents. Mongoose can't save a document without knowing its id, so you will get an error if you try to save a document without an `_id`. @@ -412,7 +412,7 @@ block content var parentSchema = new Schema({ children: [childSchema] }); var Model = mongoose.model('Model', parentSchema); - + Model.create({ children: [{ name: 'Luke' }] }, function(error, doc) { // doc.children[0]._id will be undefined }); @@ -420,17 +420,17 @@ block content h4#minimize option: minimize :markdown Mongoose will, by default, "minimize" schemas by removing empty objects. - + :js var schema = new Schema({ name: String, inventory: {} }); var Character = mongoose.model('Character', schema); - + // will store `inventory` field if it is not empty var frodo = new Character({ name: 'Frodo', inventory: { ringOfPower: 1 }}); Character.findOne({ name: 'Frodo' }, function(err, character) { console.log(character); // { name: 'Frodo', inventory: { ringOfPower: 1 }} }); - + // will not store `inventory` field if it is empty var sam = new Character({ name: 'Sam', inventory: {}}); Character.findOne({ name: 'Sam' }, function(err, character) { @@ -439,11 +439,11 @@ block content :markdown This behavior can be overridden by setting `minimize` option to `false`. It will then store empty objects. - + :js var schema = new Schema({ name: String, inventory: {} }, { minimize: false }); var Character = mongoose.model('Character', schema); - + // will store `inventory` if empty var sam = new Character({ name: 'Sam', inventory: {}}); Character.findOne({ name: 'Sam' }, function(err, character) { @@ -487,7 +487,7 @@ block content :markdown By default this is set to `true` for all schemas which guarentees that any occurring error gets passed back to our callback. By setting `safe` to something else like `{ j: 1, w: 2, wtimeout: 10000 }` we can guarantee the write was committed to the MongoDB journal (j: 1), at least 2 replicas (w: 2), and that the write will timeout if it takes longer than 10 seconds (wtimeout: 10000). Errors will still be passed to our callback. - + NOTE: In 3.6.x, you also need to turn [versioning](#versionKey) off. In 3.7.x and above, versioning will **automatically be disabled** when `safe` is set to `false` **NOTE: this setting overrides any setting specified by passing db options while [creating a connection](/docs/api.html#index_Mongoose-createConnection). @@ -595,21 +595,21 @@ block content :markdown To see all available `toObject` options, read [this](/docs/api.html#document_Document-toObject). - + h4#typeKey option: typeKey :markdown By default, if you have an object with key 'type' in your schema, mongoose will interpret it as a type declaration. - + :js // Mongoose interprets this as 'loc is a String' var schema = new Schema({ loc: { type: String, coordinates: [Number] } }); - + :markdown However, for applications like [geoJSON](http://docs.mongodb.org/manual/reference/geojson/), the 'type' property is important. If you want to control which key mongoose uses to find type declarations, set the 'typeKey' schema option. - + :js var schema = new Schema({ // Mongoose interpets this as 'loc is an object with 2 keys, type and coordinates' @@ -617,7 +617,7 @@ block content // Mongoose interprets this as 'name is a String' name: { $type: String } }, { typeKey: '$type' }); // A '$type' key means this object is a type declaration - + h4#validateBeforeSave option: validateBeforeSave :markdown By default, documents are automatically validated before they are saved to the database. This is to prevent saving an invalid document. If you want to handle validation manually, and be able to save objects which don't pass validation, you can set validateBeforeSave to false. @@ -672,7 +672,7 @@ block content var schema = new Schema({ name: String }, { collation: { locale: 'en_US', strength: 1 } }); - + var MyModel = db.model('MyModel', schema); MyModel.create([{ name: 'val' }, { name: 'Val' }]). @@ -686,7 +686,7 @@ block content h4#skipVersioning option: skipVersioning :markdown - `skipVersioning` allows excluding paths from versioning (i.e., the internal revision will not be incremented even if these paths are updated). DO NOT do this unless you know what you're doing. For sub-documents, include this on the parent document using the fully qualified path. + `skipVersioning` allows excluding paths from versioning (i.e., the internal revision will not be incremented even if these paths are updated). DO NOT do this unless you know what you're doing. For sub-documents, include this on the parent document using the fully qualified path. :js new Schema({..}, { skipVersioning: { dontVersionMe: true } }); thing.dontVersionMe.push('hey'); @@ -737,9 +737,9 @@ block content h4#retainKeyOrder option: retainKeyOrder :markdown By default, mongoose reverses key order in documents as a performance optimization. For example, `new Model({ first: 1, second: 2 });` would actually be stored in MongoDB as `{ second: 2, first: 1 }`. This behavior is [considered deprecated](https://github.com/Automattic/mongoose/wiki/5.0-Deprecation-Warnings) because it has numerous unintended side effects, including making it difficult to manipulate documents whose `_id` field is an object. - + Mongoose >= 4.6.4 has a `retainKeyOrder` option for schemas that ensures that mongoose will always keep the correct order for your object keys. - + :js var testSchema = new Schema({ first: Number, second: Number }, { retainKeyOrder: true }); var Test = mongoose.model('Test', testSchema); @@ -747,9 +747,9 @@ block content h3#plugins Pluggable p - | Schemas are also + | Schemas are also a(href="./plugins.html") pluggable - | which allows us to package up reusable features into + | which allows us to package up reusable features into a(href="http://plugins.mongoosejs.io") plugins | that can be shared with the community or just between your projects. From 96cfbb8513412316fec2713b18feb9c6989184db Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Dec 2017 09:54:27 -0800 Subject: [PATCH 2150/2240] chore: release 4.13.8 --- History.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0c1a4f7e1c1..bfcabb29b3c 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +4.13.8 / 2017-12-27 +=================== + * docs(guide): use more up-to-date syntax for autoIndex example #5933 + * docs: fix grammar #5927 [abagh0703](https://github.com/abagh0703) + * fix: propagate lean options to child schemas #5914 + * fix(populate): use correct model with discriminators + nested populate #5858 + 4.13.7 / 2017-12-11 =================== * docs(schematypes): fix typo #5889 [gokaygurcan](https://github.com/gokaygurcan) diff --git a/package.json b/package.json index 4f44134c320..e098d222c44 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.8-pre", + "version": "4.13.8", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 941efb4ec3014ff790b85a79c5f22cfecf204b3d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 27 Dec 2017 13:15:43 -0800 Subject: [PATCH 2151/2240] chore: now working on 4.13.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e098d222c44..acef7b4ced5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.8", + "version": "4.13.9-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From d82c6f3bc276ade99f147cecade4f9abbe31a0b9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Dec 2017 08:06:39 -0800 Subject: [PATCH 2152/2240] chore: bump lockfile --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index b550c856be3..659ccc8873b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.8-pre", + "version": "4.13.9-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From efa7339250a8ff9c15d407c552c08aa009ccb77b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Dec 2017 08:10:34 -0800 Subject: [PATCH 2153/2240] chore: update Makefile and release-items for 5.0 release --- Makefile | 2 +- release-items.md | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 89f2bdc0f78..5a3043d7d77 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ DOCS_ = $(shell find lib/ -name '*.js') DOCS = $(DOCS_:.js=.json) DOCFILE = docs/source/_docs STABLE_BRANCH = master -LEGACY_BRANCH = 3.8.x +LEGACY_BRANCH = 4.x test: @MONGOOSE_DISABLE_STABILITY_WARNING=1 ./node_modules/.bin/mocha $(T) --async-only test/*.test.js diff --git a/release-items.md b/release-items.md index d0589354263..3de407d03af 100644 --- a/release-items.md +++ b/release-items.md @@ -1,9 +1,9 @@ ## mongoose release procedure 1. tests must pass -2. update package.json version -3. update History.md using `git changelog` or similar. list the related ticket(s) # as well as a link to the github user who fixed it if applicable. -4. git commit -m 'release x.x.x' +2. update `package.json` and `package-lock.json` version +3. update History.md using `git changelog` or similar. Add # as well as a link to the github user who fixed it if applicable. +4. git commit -a -m 'release x.x.x' 5. git tag x.x.x 6. git push origin BRANCH --tags && npm publish 7. update mongoosejs.com (see "updating the website" below) @@ -14,16 +14,16 @@ ## updating the website -For 4.x +For 5.x 0. Change to the master branch 1. execute `make docs` (when this process completes you'll be on the gh-pages branch) -2. `git commit -a -m 'chore: website 4.x.x'` +2. `git commit -a -m 'chore: website 5.x.x'` 3. `git push origin gh-pages` -For 3.8.x: +For 4.x -0. Change to the 3.8.x branch +0. Change to the 4.x branch 1. execute `make docs_legacy` (when this process completes you'll be on the gh-pages branch) -2. `git commit -a -m 'website; regen '` +2. `git commit -a -m 'chore: website 4.x.x'` 3. `git push origin gh-pages` From a50a05090ff1b54a87b678ead182d71094dd7674 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Dec 2017 08:16:25 -0800 Subject: [PATCH 2154/2240] docs: add missing fn name for docs build --- lib/document.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index d61789fe69a..6fd8d4d3298 100644 --- a/lib/document.js +++ b/lib/document.js @@ -487,10 +487,11 @@ Document.prototype.update = function update() { * @param {Any} val the value to set * @param {Schema|String|Number|Buffer|*} [type] optionally specify a type for "on-the-fly" attributes * @param {Object} [options] optionally specify options that modify the behavior of the set + * @ * @api public */ -Document.prototype.$set = function(path, val, type, options) { +Document.prototype.$set = function $set(path, val, type, options) { if (type && utils.getFunctionName(type.constructor) === 'Object') { options = type; type = undefined; From fb93c16791c69a06078174f3423ce9d61d6279a7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Dec 2017 08:18:24 -0800 Subject: [PATCH 2155/2240] docs: add missing @method --- lib/document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/document.js b/lib/document.js index 6fd8d4d3298..1d6b1eabeca 100644 --- a/lib/document.js +++ b/lib/document.js @@ -487,7 +487,7 @@ Document.prototype.update = function update() { * @param {Any} val the value to set * @param {Schema|String|Number|Buffer|*} [type] optionally specify a type for "on-the-fly" attributes * @param {Object} [options] optionally specify options that modify the behavior of the set - * @ + * @method $set * @api public */ From 9b04e5320208a370ea262611553b5899db365253 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 28 Dec 2017 08:19:57 -0800 Subject: [PATCH 2156/2240] docs: add missing @method --- lib/document.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/document.js b/lib/document.js index 1d6b1eabeca..920aa483809 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1179,6 +1179,7 @@ Document.prototype.$isDefault = function(path) { * * @param {Boolean} [val] optional, overrides whether mongoose thinks the doc is deleted * @return {Boolean} whether mongoose thinks this doc is deleted. + * @method $isDeleted * @api public */ From a1c9d76a2042e1d28705d873e5a82f8580171e6e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 1 Jan 2018 10:58:19 -0800 Subject: [PATCH 2157/2240] chore: backport #5951 to 4.x --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index acef7b4ced5..42dc09eaf0a 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "jade": "0.26.3", "lodash": "4.16.6", "markdown": "0.5.0", - "marked": "0.3.6", + "marked": "0.3.9", "mocha": "3.2.0", "mongoose-long": "0.1.1", "mongodb-topology-manager": "1.0.11", From 4a5464908ca1f1918807ba9434c7f55c0e727ecb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 1 Jan 2018 10:59:41 -0800 Subject: [PATCH 2158/2240] chore: bump lockfile --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 659ccc8873b..06f43899062 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1937,9 +1937,9 @@ } }, "marked": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz", - "integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc=", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.9.tgz", + "integrity": "sha512-nW5u0dxpXxHfkHzzrveY45gCbi+R4PaO4WRZYqZNl+vB0hVGeqlFn0aOg1c8AKL63TrNFn9Bm2UP4AdiZ9TPLw==", "dev": true }, "media-typer": { From f397363941ff86e0f663a818c8ff2452f8b5bfee Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Jan 2018 07:55:38 -0800 Subject: [PATCH 2159/2240] docs: use useMongooseAggCursor for aggregate docs Fix #2955 --- lib/aggregate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 40cb9273ceb..a32a7e68f65 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -574,7 +574,7 @@ Aggregate.prototype.option = function(value) { * * ####Example: * - * var cursor = Model.aggregate(..).cursor({ batchSize: 1000 }).exec(); + * var cursor = Model.aggregate(..).cursor({ batchSize: 1000, useMongooseAggCursor: true }).exec(); * cursor.each(function(error, doc) { * // use doc * }); From 5bf49c17b595f3ddbfccb33c5485cf1b75b24abe Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 Jan 2018 10:28:09 -0800 Subject: [PATCH 2160/2240] fix: upgrade mongodb -> 2.2.34 Fix #5794 Fix #5760 --- package-lock.json | 62 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/package-lock.json b/package-lock.json index 06f43899062..fbe76135703 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2074,24 +2074,22 @@ } }, "mongodb": { - "version": "2.2.33", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.33.tgz", - "integrity": "sha1-tTfEcdNKZlG0jzb9vyl1A0Dgi1A=", + "version": "2.2.34", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.34.tgz", + "integrity": "sha1-o09Zu+thdUrsQy3nLD/iFSakTBo=", "requires": { "es6-promise": "3.2.1", - "mongodb-core": "2.1.17", + "mongodb-core": "2.1.18", "readable-stream": "2.2.7" - }, - "dependencies": { - "mongodb-core": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.17.tgz", - "integrity": "sha1-pBizN6FKFJkPtRC5I97mqBMXPfg=", - "requires": { - "bson": "1.0.4", - "require_optional": "1.0.1" - } - } + } + }, + "mongodb-core": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz", + "integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=", + "requires": { + "bson": "1.0.4", + "require_optional": "1.0.1" } }, "mongodb-topology-manager": { @@ -2885,15 +2883,6 @@ "is-finite": "1.0.2" } }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "requires": { - "resolve-from": "2.0.0", - "semver": "5.4.1" - } - }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -2912,6 +2901,15 @@ } } }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "2.0.0", + "semver": "5.4.1" + } + }, "requirejs": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", @@ -3116,14 +3114,6 @@ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", "dev": true }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -3135,6 +3125,14 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "stringifier": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz", diff --git a/package.json b/package.json index 42dc09eaf0a..169615ead96 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "hooks-fixed": "2.0.2", "kareem": "1.5.0", "lodash.get": "4.4.2", - "mongodb": "2.2.33", + "mongodb": "2.2.34", "mpath": "0.3.0", "mpromise": "0.5.5", "mquery": "2.3.3", From 9fea218392c4fb217ef8dbf2aa68e7e4a197bd60 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 Jan 2018 10:47:14 -0800 Subject: [PATCH 2161/2240] chore: release 4.13.9 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index bfcabb29b3c..98e8dd12b1b 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +4.13.9 / 2017-01-07 +=================== + * chore: update marked (dev dependency) re: security vulnerability #5951 [ChristianMurphy](https://github.com/ChristianMurphy) + * fix: upgrade mongodb -> 2.2.34 for ipv6 and autoReconnect fixes #5794 #5760 + * docs: use useMongooseAggCursor for aggregate docs #2955 + 4.13.8 / 2017-12-27 =================== * docs(guide): use more up-to-date syntax for autoIndex example #5933 diff --git a/package.json b/package.json index 169615ead96..83eb0320b40 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.9-pre", + "version": "4.13.9", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ee6433b917d26dd174b67c3d22137a3d222eb0f5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 7 Jan 2018 10:52:06 -0800 Subject: [PATCH 2162/2240] chore: now working on 4.13.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 83eb0320b40..8fcc5d610da 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.9", + "version": "4.13.10-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From b19aa230287a52a494e201b0e70f857416b83796 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 Jan 2018 10:17:21 -0800 Subject: [PATCH 2163/2240] docs(query+aggregate): add more detail re: maxTimeMS Fix #4066 --- lib/aggregate.js | 6 ++++-- lib/query.js | 3 +++ package-lock.json | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index a32a7e68f65..6d9e1e0e248 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -554,7 +554,10 @@ Aggregate.prototype.allowDiskUse = function(value) { * var agg = Model.aggregate(..).option({ allowDiskUse: true }); // Set the `allowDiskUse` option * agg.options; // `{ allowDiskUse: true }` * - * @param {Object} value keys to merge into current options + * @param {Object} options keys to merge into current options + * @param [options.maxTimeMS] number limits the time this aggregation will run, see [MongoDB docs on `maxTimeMS`](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/) + * @param [options.allowDiskUse] boolean if true, the MongoDB server will use the hard drive to store data during this aggregation + * @param [options.collation] object see [`Aggregate.prototype.collation()`](./docs/api.html#aggregate_Aggregate-collation) * @see mongodb http://docs.mongodb.org/manual/reference/command/aggregate/ * @return {Aggregate} this * @api public @@ -621,7 +624,6 @@ Aggregate.prototype.addCursorFlag = function(flag, value) { * Model.aggregate(..).collation({ locale: 'en_US', strength: 1 }).exec(); * * @param {Object} collation options - * @param {Boolean} value * @see mongodb http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#aggregate */ diff --git a/lib/query.js b/lib/query.js index 45e6fb77f87..c25631d58b1 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1009,6 +1009,9 @@ Query.prototype.read = function read(pref, tags) { * The following options are only for `find()`, `findOne()`, `findById()`, and `findOneAndUpdate()`: * - [lean](./api.html#query_Query-lean) * + * The following options are only for all operations **except** `update()`, `updateOne()`, `updateMany()`, `remove()`, `deleteOne()`, and `deleteMany()`: + * - [maxTimeMS](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/) + * * The following options are for all operations: * - [collation](https://docs.mongodb.com/manual/reference/collation/) * diff --git a/package-lock.json b/package-lock.json index fbe76135703..746a3688a7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.9-pre", + "version": "4.13.10-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From d7232de9e130376d328152d133a73d512365ea65 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 Jan 2018 10:39:43 -0800 Subject: [PATCH 2164/2240] docs(model+query): add lean() option to Model helpers Fix #5996 --- lib/model.js | 5 ++++- lib/query.js | 4 ++-- test/docs/validation.test.js | 12 ++++++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/model.js b/lib/model.js index 543e05a1307..e9a9f1c1b28 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1686,6 +1686,7 @@ Model.$where = function $where() { * @param {Object} [conditions] * @param {Object} [update] * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) + * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](http://mongoosejs.com/docs/api.html#query_Query-lean). * @param {Function} [callback] * @return {Query} * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command @@ -1805,6 +1806,7 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { * @param {Object|Number|String} id value of `_id` to query by * @param {Object} [update] * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions) + * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](http://mongoosejs.com/docs/api.html#query_Query-lean). * @param {Function} [callback] * @return {Query} * @see Model.findOneAndUpdate #model_Model.findOneAndUpdate @@ -2968,7 +2970,8 @@ Model.aggregate = function aggregate() { * - `lean` {Boolean} return the raw object instead of the Mongoose Model * * @param {Object} conditions an object that specifies the match condition (required) - * @param {Object} options for the geoSearch, some (near, maxDistance) are required + * @param {Object} [options] for the geoSearch, some (near, maxDistance) are required + * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](http://mongoosejs.com/docs/api.html#query_Query-lean). * @param {Function} [callback] optional callback * @return {Promise} * @see http://docs.mongodb.org/manual/reference/command/geoSearch/ diff --git a/lib/query.js b/lib/query.js index c25631d58b1..2d0f28011ea 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1002,11 +1002,11 @@ Query.prototype.read = function read(pref, tags) { * - [readPreference](http://docs.mongodb.org/manual/applications/replication/#read-preference) * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint) * - * The following options are only for `update()`, `updateOne()`, `updateMany()`, `replaceOne()`, and `findOneAndUpdate()`: + * The following options are only for `update()`, `updateOne()`, `updateMany()`, `replaceOne()`, `findOneAndUpdate()`, and `findByIdAndUpdate()`: * - [upsert](https://docs.mongodb.com/manual/reference/method/db.collection.update/) * - [writeConcern](https://docs.mongodb.com/manual/reference/method/db.collection.update/) * - * The following options are only for `find()`, `findOne()`, `findById()`, and `findOneAndUpdate()`: + * The following options are only for `find()`, `findOne()`, `findById()`, `findOneAndUpdate()`, and `findByIdAndUpdate()`: * - [lean](./api.html#query_Query-lean) * * The following options are only for all operations **except** `update()`, `updateOne()`, `updateMany()`, `remove()`, `deleteOne()`, and `deleteMany()`: diff --git a/test/docs/validation.test.js b/test/docs/validation.test.js index da21b5e29af..17bfcd3da35 100644 --- a/test/docs/validation.test.js +++ b/test/docs/validation.test.js @@ -534,12 +534,12 @@ describe('validation docs', function() { * One final detail worth noting: update validators **only** run on the * following update operators: * - * \* `$set` - * \* `$unset` - * \* `$push` (>= 4.8.0) - * \* `$addToSet` (>= 4.8.0) - * \* `$pull` (>= 4.12.0) - * \* `$pullAll` (>= 4.12.0) + * - `$set` + * - `$unset` + * - `$push` (>= 4.8.0) + * - `$addToSet` (>= 4.8.0) + * - `$pull` (>= 4.12.0) + * - `$pullAll` (>= 4.12.0) * * For instance, the below update will succeed, regardless of the value of * `number`, because update validators ignore `$inc`. Also, `$push`, From 718e777652c027a4d1aadd30efcab671a0647ad4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 Jan 2018 14:40:02 -0800 Subject: [PATCH 2165/2240] docs(schema): improve description of .indexes() --- lib/schema.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/schema.js b/lib/schema.js index 9ddc9f0febf..cbc1ffb593e 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1403,7 +1403,8 @@ Object.defineProperty(Schema, 'indexTypes', { }); /** - * Compiles indexes from fields and schema-level indexes + * Returns a list of indexes that this schema declares, via `schema.index()` + * or by `index: true` in a path's options. * * @api public */ From 07feb5a16e5a061b7251b18f4aa844e8c8ec3d34 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 20 Jan 2018 14:47:59 -0800 Subject: [PATCH 2166/2240] docs(connections): clarify multi-mongos with useMongoClient for 4.x docs Re: #5984 --- docs/connections.jade | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/connections.jade b/docs/connections.jade index 1d8412a11e0..8cccd9e772e 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -155,9 +155,16 @@ block content h3#mongos_connections Multi-mongos support :markdown - High availability over multiple `mongos` instances is also supported. Pass a connection string for your `mongos` instances and set the `mongos` option to true: + High availability over multiple `mongos` instances is also supported. + Pass a connection string for your `mongos` instances. If you are not using + the `useMongoClient` option, you must also set the `mongos` option: :js mongoose.connect('mongodb://mongosA:27501,mongosB:27501', { mongos: true }, cb); + :markdown + With `useMongoClient`, you do not need to set the `mongos` option. You also + do **not** need to use `mongos` or `useMongoClient` in mongoose 5.x. + :js + mongoose.connect('mongodb://mongosA:27501,mongosB:27501', { useMongoClient: true }, cb); h3#multiple_connections Multiple connections :markdown From ac2c6622a5981eb00f76a4a2d572806debdb72af Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Jan 2018 13:20:56 -0800 Subject: [PATCH 2167/2240] test(populate): repro #5970 --- lib/services/populate/getSchemaTypes.js | 115 ++++++++++++++++++++++++ test/model.populate.test.js | 75 ++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 lib/services/populate/getSchemaTypes.js diff --git a/lib/services/populate/getSchemaTypes.js b/lib/services/populate/getSchemaTypes.js new file mode 100644 index 00000000000..d77bb9a74bb --- /dev/null +++ b/lib/services/populate/getSchemaTypes.js @@ -0,0 +1,115 @@ +'use strict'; + +/*! + * ignore + */ + +var Mixed = require('../../schema/mixed'); +var get = require('lodash.get'); +var mpath = require('mpath'); +var utils = require('../../utils'); + +/*! + * ignore + */ + +module.exports = function getSchemaTypes(schema, doc, path) { + var pathschema = schema.path(path); + + if (pathschema) { + return pathschema; + } + + function search(parts, schema) { + var p = parts.length + 1; + var foundschema; + var trypath; + + while (p--) { + trypath = parts.slice(0, p).join('.'); + foundschema = schema.path(trypath); + if (foundschema) { + if (foundschema.caster) { + // array of Mixed? + if (foundschema.caster instanceof Mixed) { + return foundschema.caster; + } + + var schemas = null; + if (doc != null && foundschema.schema != null && foundschema.schema.discriminators != null) { + var discriminators = foundschema.schema.discriminators; + var keys = mpath.get(trypath + '.' + foundschema.schema.options.discriminatorKey, + doc); + schemas = Object.keys(discriminators). + reduce(function(cur, discriminator) { + if (keys.indexOf(discriminator) !== -1) { + cur.push(discriminators[discriminator]); + } + return cur; + }, []); + } + + // Now that we found the array, we need to check if there + // are remaining document paths to look up for casting. + // Also we need to handle array.$.path since schema.path + // doesn't work for that. + // If there is no foundschema.schema we are dealing with + // a path like array.$ + if (p !== parts.length && foundschema.schema) { + var ret; + if (parts[p] === '$') { + if (p + 1 === parts.length) { + // comments.$ + return foundschema; + } + // comments.$.comments.$.title + ret = search(parts.slice(p + 1), schema); + if (ret) { + ret.$isUnderneathDocArray = ret.$isUnderneathDocArray || + !foundschema.schema.$isSingleNested; + } + return ret; + } + + if (schemas != null && schemas.length > 0) { + ret = []; + for (var i = 0; i < schemas.length; ++i) { + var _ret = search(parts.slice(p), schemas[i]); + if (_ret) { + _ret.$isUnderneathDocArray = _ret.$isUnderneathDocArray || + !foundschema.schema.$isSingleNested; + if (_ret.$isUnderneathDocArray) { + ret.$isUnderneathDocArray = true; + } + } + ret.push(_ret); + } + return ret; + } else { + ret = search(parts.slice(p), foundschema.schema); + + if (ret) { + ret.$isUnderneathDocArray = ret.$isUnderneathDocArray || + !foundschema.schema.$isSingleNested; + } + + return ret; + } + } + } + + return foundschema; + } + } + } + + // look for arrays + var parts = path.split('.'); + for (var i = 0; i < parts.length; ++i) { + if (parts[i] === '$') { + // Re: gh-5628, because `schema.path()` doesn't take $ into account. + parts[i] = '0'; + } + } + return search(parts, schema); +} diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 5e0ecce9248..9fc1814f3a1 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -5923,6 +5923,81 @@ describe('model: populate:', function() { }); }); + it('populating nested discriminator path (gh-5970)', function() { + var Author = db.model('gh5970', new mongoose.Schema({ + firstName: { + type: String, + required: true + }, + lastName: { + type: String, + required: true + } + })); + + var ItemSchema = new mongoose.Schema({ + title: { + type: String, + required: true + } + }, {discriminatorKey: 'type'}); + + var ItemBookSchema = new mongoose.Schema({ + author: { + type: mongoose.Schema.ObjectId, + ref: 'gh5970' + } + }); + + var ItemEBookSchema = new mongoose.Schema({ + author: { + type: mongoose.Schema.ObjectId, + ref: 'gh5970' + }, + url: { + type: String + } + }); + + var BundleSchema = new mongoose.Schema({ + name: { + type: String, + required: true + }, + items: [{ + type: ItemSchema, + required: false + }] + }); + + BundleSchema.path('items').discriminator('Book', ItemBookSchema); + BundleSchema.path('items').discriminator('EBook', ItemEBookSchema); + + var Bundle = db.model('gh5970_0', BundleSchema); + + return Author.create({firstName: 'David', lastName: 'Flanagan'}). + then(function(author) { + return Bundle.create({ + name: 'Javascript Book Collection', items: [ + {type: 'Book', title: 'JavaScript: The Definitive Guide', author: author}, + { + type: 'EBook', + title: 'JavaScript: The Definitive Guide Ebook', + url: 'https://google.com', + author: author + } + ] + }); + }). + then(function(bundle) { + return Bundle.findById(bundle._id).populate('items.author').lean(); + }). + then(function(bundle) { + assert.equal(bundle.items[0].author.firstName, 'David'); + assert.equal(bundle.items[1].author.firstName, 'David'); + }); + }); + it('specify model in populate (gh-4264)', function(done) { var PersonSchema = new Schema({ name: String, From 7677cf3d03346b2bb7f8e8bc8cabce2bdfb98127 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Jan 2018 13:21:02 -0800 Subject: [PATCH 2168/2240] fix(populate): handle populating embedded discriminator paths Fix #5970 --- lib/model.js | 173 +++++++++++++++------------- lib/services/model/discriminator.js | 3 + 2 files changed, 94 insertions(+), 82 deletions(-) diff --git a/lib/model.js b/lib/model.js index e9a9f1c1b28..708b0725948 100644 --- a/lib/model.js +++ b/lib/model.js @@ -21,6 +21,7 @@ var castUpdate = require('./services/query/castUpdate'); var discriminator = require('./services/model/discriminator'); var isPathSelectedInclusive = require('./services/projection/isPathSelectedInclusive'); var get = require('lodash.get'); +var getSchemaTypes = require('./services/populate/getSchemaTypes'); var mpath = require('mpath'); var parallel = require('async/parallel'); var parallelLimit = require('async/parallelLimit'); @@ -3551,92 +3552,114 @@ function getModelsMapForPopulate(model, docs, options) { var originalModel = options.model; var isVirtual = false; var isRefPathArray = false; + var modelSchema = model.schema; - schema = model._getSchema(options.path); - var isUnderneathDocArray = schema && schema.$isUnderneathDocArray; - if (isUnderneathDocArray && - options && - options.options && - options.options.sort) { - return new Error('Cannot populate with `sort` on path ' + options.path + - ' because it is a subproperty of a document array'); - } + for (i = 0; i < len; i++) { + doc = docs[i]; - if (schema && schema.caster) { - schema = schema.caster; - } + schema = getSchemaTypes(modelSchema, doc, options.path); + var isUnderneathDocArray = schema && schema.$isUnderneathDocArray; + if (isUnderneathDocArray && + options && + options.options && + options.options.sort) { + return new Error('Cannot populate with `sort` on path ' + options.path + + ' because it is a subproperty of a document array'); + } - if (!schema && model.discriminators) { - discriminatorKey = model.schema.discriminatorMapping.key; - } + if (Array.isArray(schema)) { + for (var i = 0; i < schema.length; ++i) { + var _modelNames = _getModelNames(schema[i]); + if (!_modelNames) { + continue; + } + modelNames = (modelNames || []).concat(_modelNames); + } + } else { + modelNames = _getModelNames(schema); + if (!modelNames) { + continue; + } + } - refPath = schema && schema.options && schema.options.refPath; + function _getModelNames(schema) { + var modelNames; - for (i = 0; i < len; i++) { - doc = docs[i]; + if (schema && schema.caster) { + schema = schema.caster; + } - if (refPath) { - modelNames = utils.getValue(refPath, doc); - isRefPathArray = Array.isArray(modelNames); - } else { - if (!modelNameFromQuery) { - var modelForCurrentDoc = model; - var schemaForCurrentDoc; - - if (!schema && discriminatorKey) { - modelForFindSchema = utils.getValue(discriminatorKey, doc); - - if (modelForFindSchema) { - try { - modelForCurrentDoc = model.db.model(modelForFindSchema); - } catch (error) { - return error; - } + if (!schema && model.discriminators) { + discriminatorKey = model.schema.discriminatorMapping.key; + } - schemaForCurrentDoc = modelForCurrentDoc._getSchema(options.path); + refPath = schema && schema.options && schema.options.refPath; - if (schemaForCurrentDoc && schemaForCurrentDoc.caster) { - schemaForCurrentDoc = schemaForCurrentDoc.caster; + if (refPath) { + modelNames = utils.getValue(refPath, doc); + isRefPathArray = Array.isArray(modelNames); + } else { + if (!modelNameFromQuery) { + var modelForCurrentDoc = model; + var schemaForCurrentDoc; + + if (!schema && discriminatorKey) { + modelForFindSchema = utils.getValue(discriminatorKey, doc); + + if (modelForFindSchema) { + try { + modelForCurrentDoc = model.db.model(modelForFindSchema); + } catch (error) { + return error; + } + + schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path); + + if (schemaForCurrentDoc && schemaForCurrentDoc.caster) { + schemaForCurrentDoc = schemaForCurrentDoc.caster; + } } + } else { + schemaForCurrentDoc = schema; } - } else { - schemaForCurrentDoc = schema; - } - var virtual = modelForCurrentDoc.schema._getVirtual(options.path); - - var ref; - if ((ref = get(schemaForCurrentDoc, 'options.ref')) != null) { - modelNames = [ref]; - } else if ((ref = get(virtual, 'options.ref')) != null) { - if (typeof ref === 'function') { - ref = ref.call(doc, doc); - } + var virtual = modelForCurrentDoc.schema._getVirtual(options.path); - // When referencing nested arrays, the ref should be an Array - // of modelNames. - if (Array.isArray(ref)) { - modelNames = ref; - } else { + var ref; + if ((ref = get(schemaForCurrentDoc, 'options.ref')) != null) { modelNames = [ref]; - } + } else if ((ref = get(virtual, 'options.ref')) != null) { + if (typeof ref === 'function') { + ref = ref.call(doc, doc); + } - isVirtual = true; + // When referencing nested arrays, the ref should be an Array + // of modelNames. + if (Array.isArray(ref)) { + modelNames = ref; + } else { + modelNames = [ref]; + } + + isVirtual = true; + } else { + // We may have a discriminator, in which case we don't want to + // populate using the base model by default + modelNames = discriminatorKey ? null : [model.modelName]; + } } else { - // We may have a discriminator, in which case we don't want to - // populate using the base model by default - modelNames = discriminatorKey ? null : [model.modelName]; + modelNames = [modelNameFromQuery]; // query options } - } else { - modelNames = [modelNameFromQuery]; // query options } - } - if (!modelNames) { - continue; - } + if (!modelNames) { + return; + } - if (!Array.isArray(modelNames)) { - modelNames = [modelNames]; + if (!Array.isArray(modelNames)) { + modelNames = [modelNames]; + } + + return modelNames; } virtual = model.schema._getVirtual(options.path); @@ -3857,20 +3880,6 @@ function isDoc(doc) { return true; } -/** - * Finds the schema for `path`. This is different than - * calling `schema.path` as it also resolves paths with - * positional selectors (something.$.another.$.path). - * - * @param {String} path - * @return {Schema} - * @api private - */ - -Model._getSchema = function _getSchema(path) { - return this.schema._getSchema(path); -}; - /*! * Compiler utility. * diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 8d781827bfb..6a7087c9d87 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -128,8 +128,11 @@ module.exports = function discriminator(model, name, schema) { if (!model.schema.discriminatorMapping) { model.schema.discriminatorMapping = {key: key, value: null, isRoot: true}; + model.schema.discriminators = {}; } + model.schema.discriminators[name] = schema; + if (model.discriminators[name]) { throw new Error('Discriminator with name "' + name + '" already exists'); } From 7a0b15ffb3999d82aadf550c43f3ed4a36710391 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Jan 2018 13:28:22 -0800 Subject: [PATCH 2169/2240] style: fix lint --- lib/model.js | 168 ++++++++++++------------ lib/services/populate/getSchemaTypes.js | 4 +- 2 files changed, 85 insertions(+), 87 deletions(-) diff --git a/lib/model.js b/lib/model.js index 708b0725948..0d95e769914 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3568,101 +3568,21 @@ function getModelsMapForPopulate(model, docs, options) { } if (Array.isArray(schema)) { - for (var i = 0; i < schema.length; ++i) { - var _modelNames = _getModelNames(schema[i]); + for (var j = 0; j < schema.length; ++j) { + var _modelNames = _getModelNames(doc, schema[j]); if (!_modelNames) { continue; } modelNames = (modelNames || []).concat(_modelNames); } } else { - modelNames = _getModelNames(schema); + modelNames = _getModelNames(doc, schema); if (!modelNames) { continue; } } - function _getModelNames(schema) { - var modelNames; - - if (schema && schema.caster) { - schema = schema.caster; - } - - if (!schema && model.discriminators) { - discriminatorKey = model.schema.discriminatorMapping.key; - } - - refPath = schema && schema.options && schema.options.refPath; - - if (refPath) { - modelNames = utils.getValue(refPath, doc); - isRefPathArray = Array.isArray(modelNames); - } else { - if (!modelNameFromQuery) { - var modelForCurrentDoc = model; - var schemaForCurrentDoc; - - if (!schema && discriminatorKey) { - modelForFindSchema = utils.getValue(discriminatorKey, doc); - - if (modelForFindSchema) { - try { - modelForCurrentDoc = model.db.model(modelForFindSchema); - } catch (error) { - return error; - } - - schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path); - - if (schemaForCurrentDoc && schemaForCurrentDoc.caster) { - schemaForCurrentDoc = schemaForCurrentDoc.caster; - } - } - } else { - schemaForCurrentDoc = schema; - } - var virtual = modelForCurrentDoc.schema._getVirtual(options.path); - - var ref; - if ((ref = get(schemaForCurrentDoc, 'options.ref')) != null) { - modelNames = [ref]; - } else if ((ref = get(virtual, 'options.ref')) != null) { - if (typeof ref === 'function') { - ref = ref.call(doc, doc); - } - - // When referencing nested arrays, the ref should be an Array - // of modelNames. - if (Array.isArray(ref)) { - modelNames = ref; - } else { - modelNames = [ref]; - } - - isVirtual = true; - } else { - // We may have a discriminator, in which case we don't want to - // populate using the base model by default - modelNames = discriminatorKey ? null : [model.modelName]; - } - } else { - modelNames = [modelNameFromQuery]; // query options - } - } - - if (!modelNames) { - return; - } - - if (!Array.isArray(modelNames)) { - modelNames = [modelNames]; - } - - return modelNames; - } - - virtual = model.schema._getVirtual(options.path); + var virtual = model.schema._getVirtual(options.path); var localField; if (virtual && virtual.options) { var virtualPrefix = virtual.$nestedSchemaPath ? @@ -3752,6 +3672,86 @@ function getModelsMapForPopulate(model, docs, options) { } } + function _getModelNames(doc, schema) { + var modelNames; + + if (schema && schema.caster) { + schema = schema.caster; + } + + if (!schema && model.discriminators) { + discriminatorKey = model.schema.discriminatorMapping.key; + } + + refPath = schema && schema.options && schema.options.refPath; + + if (refPath) { + modelNames = utils.getValue(refPath, doc); + isRefPathArray = Array.isArray(modelNames); + } else { + if (!modelNameFromQuery) { + var modelForCurrentDoc = model; + var schemaForCurrentDoc; + + if (!schema && discriminatorKey) { + modelForFindSchema = utils.getValue(discriminatorKey, doc); + + if (modelForFindSchema) { + try { + modelForCurrentDoc = model.db.model(modelForFindSchema); + } catch (error) { + return error; + } + + schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path); + + if (schemaForCurrentDoc && schemaForCurrentDoc.caster) { + schemaForCurrentDoc = schemaForCurrentDoc.caster; + } + } + } else { + schemaForCurrentDoc = schema; + } + var virtual = modelForCurrentDoc.schema._getVirtual(options.path); + + var ref; + if ((ref = get(schemaForCurrentDoc, 'options.ref')) != null) { + modelNames = [ref]; + } else if ((ref = get(virtual, 'options.ref')) != null) { + if (typeof ref === 'function') { + ref = ref.call(doc, doc); + } + + // When referencing nested arrays, the ref should be an Array + // of modelNames. + if (Array.isArray(ref)) { + modelNames = ref; + } else { + modelNames = [ref]; + } + + isVirtual = true; + } else { + // We may have a discriminator, in which case we don't want to + // populate using the base model by default + modelNames = discriminatorKey ? null : [model.modelName]; + } + } else { + modelNames = [modelNameFromQuery]; // query options + } + } + + if (!modelNames) { + return; + } + + if (!Array.isArray(modelNames)) { + modelNames = [modelNames]; + } + + return modelNames; + } + return map; } diff --git a/lib/services/populate/getSchemaTypes.js b/lib/services/populate/getSchemaTypes.js index d77bb9a74bb..820bad6c0b9 100644 --- a/lib/services/populate/getSchemaTypes.js +++ b/lib/services/populate/getSchemaTypes.js @@ -5,9 +5,7 @@ */ var Mixed = require('../../schema/mixed'); -var get = require('lodash.get'); var mpath = require('mpath'); -var utils = require('../../utils'); /*! * ignore @@ -112,4 +110,4 @@ module.exports = function getSchemaTypes(schema, doc, path) { } } return search(parts, schema); -} +}; From bff15e311409c006900e5343be3326e8b7aa2224 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Jan 2018 14:58:32 -0800 Subject: [PATCH 2170/2240] chore: get rid of gemnasium and codementor badges --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 1197d200c57..c882a8cab8b 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed [![Slack Status](http://slack.mongoosejs.io/badge.svg)](http://slack.mongoosejs.io) [![Build Status](https://api.travis-ci.org/Automattic/mongoose.svg?branch=master)](https://travis-ci.org/Automattic/mongoose) [![NPM version](https://badge.fury.io/js/mongoose.svg)](http://badge.fury.io/js/mongoose) -[![Dependency Status](https://gemnasium.com/Automattic/mongoose.svg)](https://gemnasium.com/Automattic/mongoose) -[![Get help on Codementor](https://cdn.codementor.io/badges/get_help_github.svg)](https://www.codementor.io/vkarpov?utm_source=github&utm_medium=button&utm_term=vkarpov&utm_campaign=github) ## Documentation From 0ff2f943fd39cd86137d9440bf3348228b775f52 Mon Sep 17 00:00:00 2001 From: Chas DeVeas Date: Sun, 21 Jan 2018 15:02:12 -0700 Subject: [PATCH 2171/2240] Added unit test for setting default values with timestamps. --- lib/schema.js | 27 +++++++++++---------------- test/document.test.js | 2 +- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index cbc1ffb593e..5ed761ad677 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -804,22 +804,17 @@ Schema.prototype.hasMixedParent = function(path) { */ Schema.prototype.setupTimestamp = function(timestamps) { if (timestamps) { - var paths = ['createdAt', 'updatedAt'].map(handleTimestampOption.bind(null, timestamps)); - var createdAt = paths[0]; - var updatedAt = paths[1]; - var schemaAdditions = paths.reduce(function(cur, path) { - if (path != null) { - var parts = path.split('.'); - if (this.pathType(path) === 'adhocOrUndefined') { - for (var i = 0; i < parts.length; ++i) { - cur[parts[i]] = (i < parts.length - 1 ? - cur[parts[i]] || {} : - Date); - } - } - } - return cur; - }.bind(this), {}); + var createdAt = handleTimestampOption(timestamps, 'createdAt'); + var updatedAt = handleTimestampOption(timestamps, 'updatedAt'); + var schemaAdditions = {}; + + if (updatedAt && !this.paths[updatedAt]) { + schemaAdditions[updatedAt] = Date; + } + + if (createdAt && !this.paths[createdAt]) { + schemaAdditions[createdAt] = Date; + } this.add(schemaAdditions); diff --git a/test/document.test.js b/test/document.test.js index f95a96f7774..905bff70e42 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3801,7 +3801,7 @@ describe('document', function() { }); it('timestamps with nested paths (gh-5051)', function(done) { - var schema = new Schema({ props: Object }, { + var schema = new Schema({ props: {} }, { timestamps: { createdAt: 'props.createdAt', updatedAt: 'props.updatedAt' From c28ce33085c91d91fc2f17f6d6afc58034fd7073 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Jan 2018 15:03:05 -0800 Subject: [PATCH 2172/2240] refactor: move test from #6024 --- test/document.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 905bff70e42..de93442a002 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -3821,6 +3821,23 @@ describe('document', function() { }); }); + it('Declaring defaults in your schema with timestamps defined (gh-6024)', function(done) { + var schemaDefinition = { + name: String, + misc: { + hometown: String, + isAlive: { type: Boolean, default: true } + } + }; + + var schemaWithTimestamps = new Schema(schemaDefinition, {timestamps: {createdAt: 'misc.createdAt'}}); + var PersonWithTimestamps = db.model('Person_timestamps', schemaWithTimestamps); + var dude = new PersonWithTimestamps({ name: 'Keanu', misc: {hometown: 'Beirut'} }); + assert.equal(dude.misc.isAlive, true); + + done(); + }); + it('supports $where in pre save hook (gh-4004)', function(done) { var Promise = global.Promise; From 5b78dba5839f5817300d7cadcc671df707132dec Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Jan 2018 16:27:46 -0800 Subject: [PATCH 2173/2240] fix(populate): make getSchemaTypes() handle embedded discriminators without a ref Re: #5970 --- lib/services/populate/getSchemaTypes.js | 8 ++- test/helpers/populate.getSchemaTypes.test.js | 61 ++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 test/helpers/populate.getSchemaTypes.test.js diff --git a/lib/services/populate/getSchemaTypes.js b/lib/services/populate/getSchemaTypes.js index 820bad6c0b9..e3246f36143 100644 --- a/lib/services/populate/getSchemaTypes.js +++ b/lib/services/populate/getSchemaTypes.js @@ -8,7 +8,9 @@ var Mixed = require('../../schema/mixed'); var mpath = require('mpath'); /*! - * ignore + * @param {Schema} schema + * @param {Object} doc POJO + * @param {string} path */ module.exports = function getSchemaTypes(schema, doc, path) { @@ -73,14 +75,14 @@ module.exports = function getSchemaTypes(schema, doc, path) { ret = []; for (var i = 0; i < schemas.length; ++i) { var _ret = search(parts.slice(p), schemas[i]); - if (_ret) { + if (_ret != null) { _ret.$isUnderneathDocArray = _ret.$isUnderneathDocArray || !foundschema.schema.$isSingleNested; if (_ret.$isUnderneathDocArray) { ret.$isUnderneathDocArray = true; } + ret.push(_ret); } - ret.push(_ret); } return ret; } else { diff --git a/test/helpers/populate.getSchemaTypes.test.js b/test/helpers/populate.getSchemaTypes.test.js new file mode 100644 index 00000000000..56c56f2e716 --- /dev/null +++ b/test/helpers/populate.getSchemaTypes.test.js @@ -0,0 +1,61 @@ +'use strict'; + +var Schema = require('../../lib/schema'); +var assert = require('assert'); +var getSchemaTypes = require('../../lib/services/populate/getSchemaTypes'); + +describe('getSchemaTypes', function() { + it('handles embedded discriminators (gh-5970)', function(done) { + var ItemSchema = new Schema({ + title: { + type: String, + required: true + } + }, {discriminatorKey: 'type'}); + + var ItemBookSchema = new Schema({ + author: { + type: String, + ref: 'Ref1' + } + }); + + var ItemEBookSchema = new Schema({ + author: { + type: String, + ref: 'Ref2' + } + }); + + var OtherItem = new Schema({ name: String }); + + var BundleSchema = new Schema({ + items: [{ + type: ItemSchema, + required: false + }] + }); + + BundleSchema.path('items').discriminator('Book', ItemBookSchema); + BundleSchema.path('items').discriminator('EBook', ItemEBookSchema); + BundleSchema.path('items').discriminator('Other', OtherItem); + + var doc = { + items: [ + { type: 'Book', author: 'test 1' }, + { type: 'EBook', author: 'test 2' }, + { type: 'Other' }, + ] + } + var schemaTypes = getSchemaTypes(BundleSchema, doc, 'items.author'); + + assert.ok(Array.isArray(schemaTypes)); + // Make sure we only got the schema paths for Book and EBook, and none + // for the 'Other' + assert.equal(schemaTypes.length, 2); + assert.equal(schemaTypes[0].options.ref, 'Ref1'); + assert.equal(schemaTypes[1].options.ref, 'Ref2'); + + done(); + }); +}); From cb48835f3ad05a6f9ef5cf90e589fda2b73a44f5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Jan 2018 16:31:14 -0800 Subject: [PATCH 2174/2240] style: fix lint --- test/helpers/populate.getSchemaTypes.test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/helpers/populate.getSchemaTypes.test.js b/test/helpers/populate.getSchemaTypes.test.js index 56c56f2e716..0ae8ea198a7 100644 --- a/test/helpers/populate.getSchemaTypes.test.js +++ b/test/helpers/populate.getSchemaTypes.test.js @@ -44,9 +44,10 @@ describe('getSchemaTypes', function() { items: [ { type: 'Book', author: 'test 1' }, { type: 'EBook', author: 'test 2' }, - { type: 'Other' }, + { type: 'Other' } ] - } + }; + var schemaTypes = getSchemaTypes(BundleSchema, doc, 'items.author'); assert.ok(Array.isArray(schemaTypes)); From b510cb985e9f30333acc93ec6bd5dcb5e51cc10d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 Jan 2018 13:03:00 -0800 Subject: [PATCH 2175/2240] fix(populate): dedupe model names with embedded discriminators Re: #5983 --- lib/model.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 0d95e769914..31f9ca5b753 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3573,7 +3573,12 @@ function getModelsMapForPopulate(model, docs, options) { if (!_modelNames) { continue; } - modelNames = (modelNames || []).concat(_modelNames); + modelNames = (modelNames || []); + for (var k = 0; k < _modelNames.length; ++k) { + if (modelNames.indexOf(_modelNames[k]) === -1) { + modelNames.push(_modelNames[k]); + } + } } } else { modelNames = _getModelNames(doc, schema); @@ -3674,6 +3679,7 @@ function getModelsMapForPopulate(model, docs, options) { function _getModelNames(doc, schema) { var modelNames; + var discriminatorKey; if (schema && schema.caster) { schema = schema.caster; From a5b3899e996bfb1a4878ac9b460574ab69c8c156 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 Jan 2018 15:36:35 -0800 Subject: [PATCH 2176/2240] test: repro #5842 --- test/browser.test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/browser.test.js b/test/browser.test.js index 3d2a8327bad..ad3a3b9559a 100644 --- a/test/browser.test.js +++ b/test/browser.test.js @@ -4,11 +4,17 @@ var Document = require('../lib/browserDocument'); var Schema = require('../lib/schema'); +var execSync = require('child_process').execSync; /** * Test. */ describe('browser', function() { + it('require() works with no other require calls (gh-5842)', function(done) { + execSync('node --eval "require(\'./lib/browserDocument\')"'); + done(); + }); + it('document works (gh-4987)', function(done) { var schema = new Schema({ name: {type: String, required: true}, From 31b84f042d5786cbb674daa9974155f5af9e8b62 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 26 Jan 2018 15:54:35 -0800 Subject: [PATCH 2177/2240] fix: use lazy loading to avoid browserDocument edge case Fix #5842 --- lib/schema/array.js | 11 +++++++++-- lib/schema/buffer.js | 2 +- lib/schema/documentarray.js | 13 +++++++++++-- lib/schema/embedded.js | 6 +++++- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/lib/schema/array.js b/lib/schema/array.js index be0406b2547..2679c7d71a5 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -15,8 +15,6 @@ var Types = { ObjectId: require('./objectid'), Buffer: require('./buffer') }; -var MongooseArray = require('../types').Array; -var EmbeddedDoc = require('../types').Embedded; var Mixed = require('./mixed'); var cast = require('../cast'); var util = require('util'); @@ -24,6 +22,9 @@ var utils = require('../utils'); var castToNumber = require('./operators/helpers').castToNumber; var geospatial = require('./operators/geospatial'); +var MongooseArray; +var EmbeddedDoc; + /** * Array SchemaType constructor * @@ -35,6 +36,9 @@ var geospatial = require('./operators/geospatial'); */ function SchemaArray(key, cast, options, schemaOptions) { + // lazy load + EmbeddedDoc || (EmbeddedDoc = require('../types').Embedded); + var typeKey = 'type'; if (schemaOptions && schemaOptions.typeKey) { typeKey = schemaOptions.typeKey; @@ -155,6 +159,9 @@ SchemaArray.prototype.applyGetters = function(value, scope) { */ SchemaArray.prototype.cast = function(value, doc, init) { + // lazy load + MongooseArray || (MongooseArray = require('../types').Array); + if (Array.isArray(value)) { if (!value.length && doc) { var indexes = doc.schema.indexedPaths(); diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js index fae169bf5f8..f0dcf7e442a 100644 --- a/lib/schema/buffer.js +++ b/lib/schema/buffer.js @@ -5,7 +5,7 @@ var handleBitwiseOperator = require('./operators/bitwise'); var utils = require('../utils'); -var MongooseBuffer = require('../types').Buffer; +var MongooseBuffer = require('../types/buffer'); var SchemaType = require('../schematype'); var Binary = MongooseBuffer.Binary; diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 9f4c469e066..ddfde8aa695 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -8,13 +8,14 @@ var ArrayType = require('./array'); var CastError = require('../error/cast'); var Document = require('../document'); var EventEmitter = require('events').EventEmitter; -var MongooseDocumentArray = require('../types/documentarray'); var SchemaType = require('../schematype'); -var Subdocument = require('../types/embedded'); var discriminator = require('../services/model/discriminator'); var util = require('util'); var utils = require('../utils'); +var MongooseDocumentArray; +var Subdocument; + /** * SubdocsArray SchemaType constructor * @@ -66,6 +67,8 @@ DocumentArray.prototype.constructor = DocumentArray; */ function _createConstructor(schema, options) { + Subdocument || (Subdocument = require('../types/embedded')); + // compile an embedded document for this schema function EmbeddedDocument() { Subdocument.apply(this, arguments); @@ -130,6 +133,9 @@ DocumentArray.prototype.discriminator = function(name, schema) { */ DocumentArray.prototype.doValidate = function(array, fn, scope, options) { + // lazy load + MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentarray')); + var _this = this; SchemaType.prototype.doValidate.call(this, array, function(err) { if (err) { @@ -251,6 +257,9 @@ DocumentArray.prototype.doValidateSync = function(array, scope) { */ DocumentArray.prototype.cast = function(value, doc, init, prev, options) { + // lazy load + MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentarray')); + var selected; var subdoc; var i; diff --git a/lib/schema/embedded.js b/lib/schema/embedded.js index ac64079ee0c..89ba08ddf9f 100644 --- a/lib/schema/embedded.js +++ b/lib/schema/embedded.js @@ -7,11 +7,12 @@ var $exists = require('./operators/exists'); var EventEmitter = require('events').EventEmitter; var SchemaType = require('../schematype'); -var Subdocument = require('../types/subdocument'); var castToNumber = require('./operators/helpers').castToNumber; var discriminator = require('../services/model/discriminator'); var geospatial = require('./operators/geospatial'); +var Subdocument; + module.exports = Embedded; /** @@ -43,6 +44,9 @@ Embedded.prototype = Object.create(SchemaType.prototype); */ function _createConstructor(schema) { + // lazy load + Subdocument || (Subdocument = require('../types/subdocument')); + var _embedded = function SingleNested(value, path, parent) { var _this = this; From 940ccc88d0b0b8c61523e46b88302ea1af1b65e8 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 28 Jan 2018 07:34:09 -0800 Subject: [PATCH 2178/2240] style: fix lint --- lib/model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 31f9ca5b753..9199828201d 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3743,7 +3743,7 @@ function getModelsMapForPopulate(model, docs, options) { modelNames = discriminatorKey ? null : [model.modelName]; } } else { - modelNames = [modelNameFromQuery]; // query options + modelNames = [modelNameFromQuery]; // query options } } From b716e73fb80d8c8fcac09680d0c604efcc94362e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 28 Jan 2018 07:57:35 -0800 Subject: [PATCH 2179/2240] style: fix lint --- lib/model.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index 9199828201d..6da0f02de59 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3574,9 +3574,9 @@ function getModelsMapForPopulate(model, docs, options) { continue; } modelNames = (modelNames || []); - for (var k = 0; k < _modelNames.length; ++k) { - if (modelNames.indexOf(_modelNames[k]) === -1) { - modelNames.push(_modelNames[k]); + for (var x = 0; x < _modelNames.length; ++x) { + if (modelNames.indexOf(_modelNames[x]) === -1) { + modelNames.push(_modelNames[x]); } } } From 82ea3e8965f068efeeba8e18258b9a0c7e3cc18a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 28 Jan 2018 08:18:52 -0800 Subject: [PATCH 2180/2240] chore: release 4.13.10 --- History.md | 8 ++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 98e8dd12b1b..7edceaa7c2e 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +4.13.10 / 2017-01-28 +==================== + * docs(model+query): add lean() option to Model helpers #5996 [aguyinmontreal](https://github.com/aguyinmontreal) + * fix: use lazy loading so we can build mongoose with webpack #5993 #5842 + * docs(connections): clarify multi-mongos with useMongoClient for 4.x docs #5984 + * fix(populate): handle populating embedded discriminator paths #5970 + * docs(query+aggregate): add more detail re: maxTimeMS #4066 + 4.13.9 / 2017-01-07 =================== * chore: update marked (dev dependency) re: security vulnerability #5951 [ChristianMurphy](https://github.com/ChristianMurphy) diff --git a/package-lock.json b/package-lock.json index 746a3688a7f..f9b71fb71a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.10-pre", + "version": "4.13.10", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8fcc5d610da..c24935a84f4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.10-pre", + "version": "4.13.10", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From b447d65f0ad3fd51b817b6e9c9dadd28533e407d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 28 Jan 2018 15:09:20 -0800 Subject: [PATCH 2181/2240] chore: now working on 4.13.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c24935a84f4..f0d0a9e6869 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.10", + "version": "4.13.11-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ca194cc7ae3e3854833f5f5561c3c93daf548aa0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 28 Jan 2018 15:13:11 -0800 Subject: [PATCH 2182/2240] chore: add release script that uses --tag for npm publish for 4.x releases Fix #6063 --- package.json | 2 ++ release-items.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f0d0a9e6869..a282608ca52 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,8 @@ "install-browser": "npm install `node format_deps.js`", "lint": "eslint . --quiet", "nsp": "nsp check", + "release": "git push origin master --tags && npm publish", + "release-legacy": "git push origin 4.x --tags && npm publish --tag 4.x", "test": "mocha test/*.test.js test/**/*.test.js", "test-cov": "istanbul cover --report text --report html _mocha test/*.test.js" }, diff --git a/release-items.md b/release-items.md index 3de407d03af..12ab9a5daca 100644 --- a/release-items.md +++ b/release-items.md @@ -5,7 +5,7 @@ 3. update History.md using `git changelog` or similar. Add # as well as a link to the github user who fixed it if applicable. 4. git commit -a -m 'release x.x.x' 5. git tag x.x.x -6. git push origin BRANCH --tags && npm publish +6. `npm run release`, or `npm run release-legacy` for 4.x 7. update mongoosejs.com (see "updating the website" below) 8. tweet changelog link from [@mongoosejs](https://twitter.com/mongoosejs) 9. Announce on mongoosejsteam slack channel From 6d2963c256bd6040f1a9f16450bc6b92195e85eb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 28 Jan 2018 15:33:33 -0800 Subject: [PATCH 2183/2240] test: use exec instead of execSync() for #5842 test for node 0.10 --- test/browser.test.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/browser.test.js b/test/browser.test.js index ad3a3b9559a..e499e92b25a 100644 --- a/test/browser.test.js +++ b/test/browser.test.js @@ -4,15 +4,14 @@ var Document = require('../lib/browserDocument'); var Schema = require('../lib/schema'); -var execSync = require('child_process').execSync; +var exec = require('child_process').exec; /** * Test. */ describe('browser', function() { it('require() works with no other require calls (gh-5842)', function(done) { - execSync('node --eval "require(\'./lib/browserDocument\')"'); - done(); + exec('node --eval "require(\'./lib/browserDocument\')"', done); }); it('document works (gh-4987)', function(done) { From 3660092cfe643ce4f2983f54eb924cfb07001475 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 6 Feb 2018 19:57:52 -0800 Subject: [PATCH 2184/2240] docs: fix links in 4.x docs Fix #6081 --- docs/connections.jade | 4 ++-- docs/documents.jade | 6 ++--- docs/faq.jade | 8 +++---- docs/guide.jade | 2 +- docs/middleware.jade | 4 ++-- docs/populate.jade | 30 ++++++++++++------------- docs/queries.jade | 10 ++++----- docs/schematypes.jade | 52 +++++++++++++++++++++---------------------- docs/subdocs.jade | 14 ++++++------ package-lock.json | 2 +- 10 files changed, 66 insertions(+), 66 deletions(-) diff --git a/docs/connections.jade b/docs/connections.jade index 8cccd9e772e..54cfe5c26ad 100644 --- a/docs/connections.jade +++ b/docs/connections.jade @@ -49,7 +49,7 @@ block content }, 60000); :markdown - To disable buffering, turn off the [`bufferCommands` option on your schema](http://mongoosejs.com/docs/guide.html#bufferCommands). + To disable buffering, turn off the [`bufferCommands` option on your schema](./guide.html#bufferCommands). If you have `bufferCommands` on and your connection is hanging, try turning `bufferCommands` off to see if you haven't opened a connection properly. @@ -92,7 +92,7 @@ block content h3#callback Callback :markdown - The `connect()` function also accepts a callback parameter and returns a [promise](http://mongoosejs.com/docs/promises.html). + The `connect()` function also accepts a callback parameter and returns a [promise](./promises.html). :js mongoose.connect(uri, options, function(error) { // Check error in initial connection. There is no 2nd param to the callback. diff --git a/docs/documents.jade b/docs/documents.jade index 8600d820395..17cb210e26d 100644 --- a/docs/documents.jade +++ b/docs/documents.jade @@ -22,7 +22,7 @@ block content }); }); :markdown - You can also use [`.set()`](http://mongoosejs.com/docs/api.html#document_Document-set) + You can also use [`.set()`](./api.html#document_Document-set) to modify documents. Under the hood, `tank.size = 'large';` becomes `tank.set({ size: 'large' })`. :js Tank.findById(id, function (err, tank) { @@ -51,7 +51,7 @@ block content }); :markdown The `findAndUpdate/Remove` static methods all make a change to at most one document, and return it with just one call to the database. There [are](./api.html#model_Model.findByIdAndRemove) [several](./api.html#model_Model.findOneAndUpdate) [variations](./api.html#model_Model.findOneAndRemove) on the [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) theme. Read the [API](./api.html) docs for more detail. - + _Note that `findAndUpdate/Remove` do *not* execute any hooks or validation before making the change in the database. You can use the [`runValidators` option](/docs/validation.html#update-validators) to access a limited subset of document validation. However, if you need hooks and full document validation, first query for the document and then `save()` it._ h3 Validating @@ -61,7 +61,7 @@ block content h3 Overwriting :markdown You can overwrite an entire document using `.set()`. This is handy if you - want to change what document is being saved in [middleware](http://mongoosejs.com/docs/middleware.html). + want to change what document is being saved in [middleware](./docs/middleware.html). :js Tank.findById(id, function (err, tank) { if (err) return handleError(err); diff --git a/docs/faq.jade b/docs/faq.jade index 489aa84af76..d3c879c2c87 100644 --- a/docs/faq.jade +++ b/docs/faq.jade @@ -95,7 +95,7 @@ block content :markdown **A**. This is a performance optimization. These empty objects are not saved to the database, nor are they in the result `toObject()`, nor do they show - up in `JSON.stringify()` output unless you turn off the [`minimize` option](http://mongoosejs.com/docs/guide.html#minimize). + up in `JSON.stringify()` output unless you turn off the [`minimize` option](./guide.html#minimize). The reason for this behavior is that Mongoose's change detection and getters/setters are based on [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). @@ -104,11 +104,11 @@ block content mongoose defines properties on the `Model` prototype when the model is compiled. Because mongoose needs to define getters and setters for `nested.prop`, `nested` must always be defined as an object on a mongoose document, even if `nested` - is undefined on the underlying [POJO](http://mongoosejs.com/docs/guide.html#minimize). + is undefined on the underlying [POJO](./guide.html#minimize). hr#arrow-functions :markdown - **Q**. I'm using an arrow function for a [virtual](http://mongoosejs.com/docs/guide.html#virtuals), getter/setter, or [method](http://mongoosejs.com/docs/guide.html#methods) and the value of `this` is wrong. + **Q**. I'm using an arrow function for a [virtual](./guide.html#virtuals), getter/setter, or [method](./guide.html#methods) and the value of `this` is wrong. **A**. Arrow functions [handle the `this` keyword much differently than conventional functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_this). Mongoose getters/setters depend on `this` to give you access to the document that you're writing to, but this functionality does not work with arrow functions. Do **not** use arrow functions for mongoose getters/setters unless do not intend to access the document in the getter/setter. @@ -215,7 +215,7 @@ block content **Q**. All function calls on my models hang, what am I doing wrong? **A**. By default, mongoose will buffer your function calls until it can - connect to MongoDB. Read the [buffering section of the connection docs](http://mongoosejs.com/docs/connections.html#buffering) + connect to MongoDB. Read the [buffering section of the connection docs](./connections.html#buffering) for more information. hr#enable_debugging diff --git a/docs/guide.jade b/docs/guide.jade index e5ee549ae97..07d50efcca8 100644 --- a/docs/guide.jade +++ b/docs/guide.jade @@ -694,7 +694,7 @@ block content h4#timestamps option: timestamps :markdown - If set `timestamps`, mongoose assigns `createdAt` and `updatedAt` fields to your schema, the type assigned is [Date](http://mongoosejs.com/docs/api.html#schema-date-js). + If set `timestamps`, mongoose assigns `createdAt` and `updatedAt` fields to your schema, the type assigned is [Date](./api.html#schema-date-js). By default, the name of two fields are `createdAt` and `updatedAt`, customize the field name by setting `timestamps.createdAt` and `timestamps.updatedAt`. :js diff --git a/docs/middleware.jade b/docs/middleware.jade index c85923d31b1..e6574d5a2bc 100644 --- a/docs/middleware.jade +++ b/docs/middleware.jade @@ -28,9 +28,9 @@ block content Aggregate middleware is for `MyModel.aggregate()`. Aggregate middleware executes when you call `exec()` on an aggregate object. - In aggregate middleware, `this` refers to the [aggregation object](http://mongoosejs.com/docs/api.html#model_Model.aggregate). + In aggregate middleware, `this` refers to the [aggregation object](./api.html#model_Model.aggregate). - * [aggregate](http://mongoosejs.com/docs/api.html#model_Model.aggregate) + * [aggregate](./api.html#model_Model.aggregate) Model middleware is supported for the following model functions. In model middleware functions, `this` refers to the model. diff --git a/docs/populate.jade b/docs/populate.jade index f6c26e061ae..1cf25bf1858 100644 --- a/docs/populate.jade +++ b/docs/populate.jade @@ -214,7 +214,7 @@ block content populate them using the [Model.populate()](./api.html#model_Model.populate) method available in **mongoose >= 3.6**. This is what `document#populate()` and `query#populate()` use to populate documents. - + h3#deep-populate Populating across multiple levels :markdown Say you have a user schema which keeps track of the user's friends. @@ -235,7 +235,7 @@ block content // Get friends of friends - populate the 'friends' array for every friend populate: { path: 'friends' } }); - + h3#cross-db-populate Populating across Databases :markdown Let's say you have a schema representing events, and a schema representing @@ -256,14 +256,14 @@ block content :js var db1 = mongoose.createConnection('localhost:27000/db1'); var db2 = mongoose.createConnection('localhost:27001/db2'); - + var Event = db1.model('Event', eventSchema); var Conversation = db2.model('Conversation', conversationSchema); :markdown In this situation, you will **not** be able to `populate()` normally. The `conversation` field will always be null, because `populate()` doesn't know which model to use. However, - [you can specify the model explicitly](http://mongoosejs.com/docs/api.html#model_Model.populate). + [you can specify the model explicitly](./api.html#model_Model.populate). :js Event. find(). @@ -286,9 +286,9 @@ block content item: { type: ObjectId, refPath: 'connections.kind' } }] }); - + var organizationSchema = new Schema({ name: String, kind: String }); - + var User = mongoose.model('User', userSchema); var Organization = mongoose.model('Organization', organizationSchema); :markdown @@ -320,17 +320,17 @@ block content // doc.connections[0].item is a User doc // doc.connections[1].item is an Organization doc }); - + h3#populate-virtuals Populate Virtuals :markdown _New in 4.5.0_ - + So far you've only populated based on the `_id` field. However, that's sometimes not the right choice. In particular, [arrays that grow without bound are a MongoDB anti-pattern](https://docs.mongodb.com/manual/tutorial/model-referenced-one-to-many-relationships-between-documents/). Using mongoose virtuals, you can define more sophisticated relationships between documents. - + :js var PersonSchema = new Schema({ name: String, @@ -348,10 +348,10 @@ block content // an array. `justOne` is false by default. justOne: false }); - + var Person = mongoose.model('Person', PersonSchema); var Band = mongoose.model('Band', BandSchema); - + /** * Suppose you have 2 bands: "Guns N' Roses" and "Motley Crue" * And 4 people: "Axl Rose" and "Slash" with "Guns N' Roses", and @@ -360,24 +360,24 @@ block content Band.find({}).populate('members').exec(function(error, bands) { /* `bands.members` is now an array of instances of `Person` */ }); - + :markdown Keep in mind that virtuals are _not_ included in `toJSON()` output by default. If you want populate virtuals to show up when using functions that rely on `JSON.stringify()`, like Express' [`res.json()` function](http://expressjs.com/en/4x/api.html#res.json), set the `virtuals: true` option on your schema's `toJSON` options. - + :js // Set `virtuals: true` so `res.json()` works var BandSchema = new Schema({ name: String }, { toJSON: { virtuals: true } }); - + :markdown If you're using populate projections, make sure `foreignField` is included in the projection. - + :js Band. find({}). diff --git a/docs/queries.jade b/docs/queries.jade index f23f251460e..2711fb01c9d 100644 --- a/docs/queries.jade +++ b/docs/queries.jade @@ -28,7 +28,7 @@ block content }) :markdown Here we see that the query was executed immediately and the results passed to our callback. All callbacks in Mongoose use the pattern: - `callback(error, result)`. If an error occurs executing the query, the `error` parameter will contain an error document, and `result` + `callback(error, result)`. If an error occurs executing the query, the `error` parameter will contain an error document, and `result` will be null. If the query is successful, the `error` parameter will be null, and the `result` will be populated with the results of the query. .important :markdown @@ -77,12 +77,12 @@ block content exec(callback); :markdown - A full list of [Query helper functions can be found in the API docs](http://mongoosejs.com/docs/api.html#query-js). + A full list of [Query helper functions can be found in the API docs](./api.html#query-js). h3#setters :markdown Setters are not executed by default in 4.x. For example, if you lowercase emails in your schema: - + :js var personSchema = new Schema({ email: { @@ -90,11 +90,11 @@ block content lowercase: true } }); - + :markdown Mongoose will **not** automatically lowercase the email in your queries, so `Person.find({ email: 'Val@karpov.io' })` would return no results. Use the `runSettersOnQuery` option to turn on this behavior: - + :js var personSchema = new Schema({ email: { diff --git a/docs/schematypes.jade b/docs/schematypes.jade index 5379814e222..7be49cf5628 100644 --- a/docs/schematypes.jade +++ b/docs/schematypes.jade @@ -17,7 +17,7 @@ block content a(href="./api.html#query-js") queries | and other general characteristics for  a(href="./api.html#schema-string-js") Strings - | and + | and a(href="./api.html#schema-number-js") Numbers |. Check out their respective API documentation for more detail. p @@ -88,7 +88,7 @@ block content var schema1 = new Schema({ test: String // `test` is a path of type String }); - + var schema2 = new Schema({ test: { type: String } // `test` is a path of type string }); @@ -108,14 +108,14 @@ block content types. h5 All Schema Types :markdown - * `required`: boolean or function, if true adds a [required validator](http://mongoosejs.com/docs/validation.html#built-in-validators) for this property + * `required`: boolean or function, if true adds a [required validator](./validation.html#built-in-validators) for this property * `default`: Any or function, sets a default value for the path. If the value is a function, the return value of the function is used as the default. * `select`: boolean, specifies default [projections](https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/) for queries - * `validate`: function, adds a [validator function](http://mongoosejs.com/docs/validation.html#built-in-validators) for this property + * `validate`: function, adds a [validator function](./validation.html#built-in-validators) for this property * `get`: function, defines a custom getter for this property using [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). * `set`: function, defines a custom setter for this property using [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). - * `alias`: string, mongoose >= 4.10.0 only. Defines a [virtual](http://mongoosejs.com/docs/guide.html#virtuals) with the given name that gets/sets this path. - + * `alias`: string, mongoose >= 4.10.0 only. Defines a [virtual](./guide.html#virtuals) with the given name that gets/sets this path. + :js var numberSchema = new Schema({ integerOnly: { @@ -125,9 +125,9 @@ block content alias: 'i' } }); - + var Number = mongoose.model('Number', numberSchema); - + var doc = new Number(); doc.integerOnly = 2.001; doc.integerOnly; // 2 @@ -135,13 +135,13 @@ block content doc.i = 3.001; doc.integerOnly; // 3 doc.i; // 3 - + h5 Indexes p :markdown You can also define [MongoDB indexes](https://docs.mongodb.com/manual/indexes/) using schema type options. - + :markdown * `index`: boolean, whether to define an [index](https://docs.mongodb.com/manual/indexes/) on this property. * `unique`: boolean, whether to define a [unique index](https://docs.mongodb.com/manual/core/index-unique/) on this property. @@ -160,14 +160,14 @@ block content * `lowercase`: boolean, whether to always call `.toLowerCase()` on the value * `uppercase`: boolean, whether to always call `.toUpperCase()` on the value * `trim`: boolean, whether to always call `.trim()` on the value - * `match`: RegExp, creates a [validator](http://mongoosejs.com/docs/validation.html) that checks if the value matches the given regular expression - * `enum`: Array, creates a [validator](http://mongoosejs.com/docs/validation.html) that checks if the value is in the given array. + * `match`: RegExp, creates a [validator](./validation.html) that checks if the value matches the given regular expression + * `enum`: Array, creates a [validator](./validation.html) that checks if the value is in the given array. h5 Number :markdown - * `min`: Number, creates a [validator](http://mongoosejs.com/docs/validation.html) that checks if the value is greater than or equal to the given minimum. - * `max`: Number, creates a [validator](http://mongoosejs.com/docs/validation.html) that checks if the value is less than or equal to the given maximum. - + * `min`: Number, creates a [validator](./validation.html) that checks if the value is greater than or equal to the given minimum. + * `max`: Number, creates a [validator](./validation.html) that checks if the value is less than or equal to the given maximum. + h5 Date :markdown * `min`: Date @@ -195,7 +195,7 @@ block content var Any = new Schema({ any: Object }); var Any = new Schema({ any: Schema.Types.Mixed }); p - | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the + | Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the code .markModified(path) | method of the document passing the path to the Mixed type you just changed. :js @@ -204,7 +204,7 @@ block content person.save(); // anything will now get saved h4#objectids ObjectIds p - | To specify a type of ObjectId, use + | To specify a type of ObjectId, use code Schema.Types.ObjectId | in your declaration. :js @@ -214,9 +214,9 @@ block content // or just Schema.ObjectId for backwards compatibility with v2 h4#arrays Arrays p - | Provide creation of arrays of + | Provide creation of arrays of a(href="./api.html#schema_Schema.Types") SchemaTypes - | or + | or a(href="./subdocs.html") Sub-Documents |. :js @@ -229,9 +229,9 @@ block content // ... etc }); p - | Note: specifying an empty array is equivalent to + | Note: specifying an empty array is equivalent to code Mixed - |. The following all create arrays of + |. The following all create arrays of code Mixed |: :js @@ -268,18 +268,18 @@ block content }); h3#customtypes Creating Custom Types p - | Mongoose can also be extended with custom SchemaTypes. Search the + | Mongoose can also be extended with custom SchemaTypes. Search the a(href="http://plugins.mongoosejs.com") plugins - | site for compatible types like + | site for compatible types like a(href="https://github.com/aheckmann/mongoose-long") mongoose-long | ,  a(href="https://github.com/vkarpov15/mongoose-int32") mongoose-int32 - | and + | and a(href="https://github.com/aheckmann/mongoose-function") other - | + | a(href="https://github.com/OpenifyIt/mongoose-types") types |. - + h3#path The `schema.path()` Function :markdown The `schema.path()` function returns the instantiated schema type for a diff --git a/docs/subdocs.jade b/docs/subdocs.jade index dbbc4c79f5e..9d59e37225c 100644 --- a/docs/subdocs.jade +++ b/docs/subdocs.jade @@ -20,7 +20,7 @@ block content :markdown Subdocuments are similar to normal documents. Nested schemas can have - [middleware](http://mongoosejs.com/docs/middleware.html), [custom validation logic](http://mongoosejs.com/docs/middleware.html), + [middleware](./middleware.html), [custom validation logic](./validation.html), virtuals, and any other feature top-level schemas can use. The major difference is that subdocuments are not saved individually, they are saved whenever their top-level parent @@ -29,14 +29,14 @@ block content var Parent = mongoose.model('Parent', parentSchema); var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) parent.children[0].name = 'Matthew'; - + // `parent.children[0].save()` is a no-op, it triggers middleware but // does **not** actually save the subdocument. You need to save the parent // doc. parent.save(callback); :markdown - Subdocuments have `save` and `validate` [middleware](http://mongoosejs.com/docs/middleware.html) + Subdocuments have `save` and `validate` [middleware](./middleware.html) just like top-level documents. Calling `save()` on the parent document triggers the `save()` middleware for all its subdocuments, and the same for `validate()` middleware. @@ -53,13 +53,13 @@ block content parent.save(function (err) { console.log(err.message) // #sadpanda }); - + :markdown Subdocuments' `pre('save')` and `pre('validate')` middleware execute **before** the top-level document's `pre('save')` but **after** the top-level document's `pre('validate')` middleware. This is because validating before `save()` is actually a piece of built-in middleware. - + :js // Below code will print out 1-4 in order var childSchema = new mongoose.Schema({ name: 'string' }); @@ -154,8 +154,8 @@ block content var parentSchema = new Schema({ children: [new Schema({ name: 'string' })] }); - + h3#next Next Up :markdown Now that we've covered `Sub-documents`, let's take a look at - [querying](/docs/queries.html). + [querying](./queries.html). diff --git a/package-lock.json b/package-lock.json index f9b71fb71a1..01a3a1321f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.10", + "version": "4.13.11-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From f86ddcf92cb34426e4b3232fce97ed69d50b1ee7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 7 Feb 2018 19:48:12 -0800 Subject: [PATCH 2185/2240] chore: release 4.13.11 --- History.md | 9 +++++++-- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 7edceaa7c2e..0a0638e8d93 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,9 @@ -4.13.10 / 2017-01-28 +4.13.11 / 2018-02-07 +==================== + * docs: fix links in 4.x docs #6081 + * chore: add release script that uses --tag for npm publish for 4.x releases #6063 + +4.13.10 / 2018-01-28 ==================== * docs(model+query): add lean() option to Model helpers #5996 [aguyinmontreal](https://github.com/aguyinmontreal) * fix: use lazy loading so we can build mongoose with webpack #5993 #5842 @@ -6,7 +11,7 @@ * fix(populate): handle populating embedded discriminator paths #5970 * docs(query+aggregate): add more detail re: maxTimeMS #4066 -4.13.9 / 2017-01-07 +4.13.9 / 2018-01-07 =================== * chore: update marked (dev dependency) re: security vulnerability #5951 [ChristianMurphy](https://github.com/ChristianMurphy) * fix: upgrade mongodb -> 2.2.34 for ipv6 and autoReconnect fixes #5794 #5760 diff --git a/package-lock.json b/package-lock.json index 01a3a1321f3..952a71e10dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.11-pre", + "version": "4.13.11", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a282608ca52..5268f7534e3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.11-pre", + "version": "4.13.11", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 617fb47bf32a8620807c968b418c7bb488158973 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 7 Feb 2018 19:49:21 -0800 Subject: [PATCH 2186/2240] chore: use legacy instead of 4.x --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5268f7534e3..02804350e88 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "lint": "eslint . --quiet", "nsp": "nsp check", "release": "git push origin master --tags && npm publish", - "release-legacy": "git push origin 4.x --tags && npm publish --tag 4.x", + "release-legacy": "git push origin 4.x --tags && npm publish --tag legacy", "test": "mocha test/*.test.js test/**/*.test.js", "test-cov": "istanbul cover --report text --report html _mocha test/*.test.js" }, From 0290187eae03dfd21790052b1d71f6ec865320fa Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 7 Feb 2018 19:55:13 -0800 Subject: [PATCH 2187/2240] chore: now working on 4.13.12 --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 952a71e10dc..4d8d035097b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.11", + "version": "4.13.12-pre", "lockfileVersion": 1, "requires": true, "dependencies": { From 36b2f3f8a915ce5974de0994b2b9b35fa0e0987c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Feb 2018 17:14:27 -0800 Subject: [PATCH 2188/2240] fix(discriminator): don't copy `discriminators` property from base schema Fix #6064 --- lib/services/model/discriminator.js | 5 +- lib/utils.js | 6 ++ test/helpers/populate.getSchemaTypes.test.js | 75 ++++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/lib/services/model/discriminator.js b/lib/services/model/discriminator.js index 6a7087c9d87..a2479aaa1c4 100644 --- a/lib/services/model/discriminator.js +++ b/lib/services/model/discriminator.js @@ -62,7 +62,10 @@ module.exports = function discriminator(model, name, schema) { delete schema.paths._id; delete schema.tree._id; } - utils.merge(schema, baseSchema, { retainKeyOrder: true }); + utils.merge(schema, baseSchema, { + retainKeyOrder: true, + omit: { discriminators: true } + }); var obj = {}; obj[key] = { diff --git a/lib/utils.js b/lib/utils.js index 8e3b719f297..c687ae55cab 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -418,6 +418,9 @@ exports.merge = function merge(to, from, options) { if (options.retainKeyOrder) { while (i < len) { key = keys[i++]; + if (options.omit && options.omit[key]) { + continue; + } if (to[key] == null) { to[key] = from[key]; } else if (exports.isObject(from[key])) { @@ -429,6 +432,9 @@ exports.merge = function merge(to, from, options) { } else { while (len--) { key = keys[len]; + if (options.omit && options.omit[key]) { + continue; + } if (to[key] == null) { to[key] = from[key]; } else if (exports.isObject(from[key])) { diff --git a/test/helpers/populate.getSchemaTypes.test.js b/test/helpers/populate.getSchemaTypes.test.js index 0ae8ea198a7..fc742684ca6 100644 --- a/test/helpers/populate.getSchemaTypes.test.js +++ b/test/helpers/populate.getSchemaTypes.test.js @@ -59,4 +59,79 @@ describe('getSchemaTypes', function() { done(); }); + + it('multiple embedded discriminators (gh-6064)', function(done) { + var ItemSchema = new Schema({ + title: { + type: String, + required: true + } + }, {discriminatorKey: 'type'}); + + var ItemBookSchema = new Schema({ + author: { + type: String, + ref: 'Ref1' + } + }); + + var ItemEBookSchema = new Schema({ + author: { + type: String, + ref: 'Ref2' + } + }); + + var OtherItem = new Schema({ name: String }); + + var BundleSchema = new Schema({ + level1: { + items: [{ + type: ItemSchema, + required: false + }] + }, + level2: { + items: [{ + type: ItemSchema, + required: false + }] + } + }); + + BundleSchema.path('level1.items').discriminator('Book', ItemBookSchema); + BundleSchema.path('level1.items').discriminator('EBook', ItemEBookSchema); + BundleSchema.path('level1.items').discriminator('Other', OtherItem); + + // HERE IS THE ADDED DISCRIMINATOR PATH + BundleSchema.path('level2.items').discriminator('Book', ItemBookSchema); + BundleSchema.path('level2.items').discriminator('EBook', ItemEBookSchema); + BundleSchema.path('level2.items').discriminator('Other', OtherItem); + + var doc = { + level1: { + items: [ + { type: 'Book', author: 'level 1 test 1' }, + { type: 'EBook', author: 'level 1 test 2' } + ] + }, + level2: { + items: [ + { type: 'EBook', author: 'level 2 test 1' }, + { type: 'Book', author: 'level 2 test 2' }, + { type: 'Other' } + ] + } + }; + var schemaTypes = getSchemaTypes(BundleSchema, doc, 'level2.items.author'); + + assert.ok(Array.isArray(schemaTypes)); + // Make sure we only got the schema paths for Book and EBook, and none + // for the 'Other' + assert.equal(schemaTypes.length, 2); + assert.equal(schemaTypes[0].options.ref, 'Ref1'); + assert.equal(schemaTypes[1].options.ref, 'Ref2'); + + done(); + }); }); From 1ed41aba29dc9f35bdf29fc393bc38207b99ad21 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 11 Feb 2018 17:24:31 -0800 Subject: [PATCH 2189/2240] chore: now working on 4.x --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 02804350e88..0cbba6e56a2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.11", + "version": "4.13.12-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 3e547234e0cff1ebbbab1fbb83e933a1da72e455 Mon Sep 17 00:00:00 2001 From: Kev Date: Thu, 8 Mar 2018 05:42:14 -0500 Subject: [PATCH 2190/2240] fix url in useMongoClient error message --- lib/connection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index eb8e61133e1..67c6204a723 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -340,7 +340,7 @@ Connection.prototype.open = util.deprecate(function() { }; return promise; -}, '`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/connections.html#use-mongo-client'); +}, '`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/4.x/docs/connections.html#use-mongo-client'); /*! * ignore @@ -653,7 +653,7 @@ Connection.prototype.openSet = util.deprecate(function(uris, database, options, }; return promise; -}, '`openSet()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/connections.html#use-mongo-client'); +}, '`openSet()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/4.x/docs/connections.html#use-mongo-client'); /** * error From 2be24f4f77b0797471e395c5f3c571ddd7883eed Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 8 Mar 2018 22:03:18 -0800 Subject: [PATCH 2191/2240] fix: support callback with createConnection() and useMongoClient Re: #6217 --- lib/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index ea6ffe1001a..5fbbdc00578 100644 --- a/lib/index.js +++ b/lib/index.js @@ -188,14 +188,14 @@ var checkReplicaSetInUri = function(uri) { * @api public */ -Mongoose.prototype.createConnection = function(uri, options) { +Mongoose.prototype.createConnection = function(uri, options, callback) { var conn = new Connection(this); this.connections.push(conn); var rsOption = options && (options.replset || options.replSet); if (options && options.useMongoClient) { - return conn.openUri(uri, options); + return conn.openUri(uri, options, callback); } if (arguments.length) { From 5f142bdd5bd47c5067fe7687e1274a87b7274e87 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Mar 2018 20:42:24 -0700 Subject: [PATCH 2192/2240] test(document): repro #6223 --- test/document.test.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index de93442a002..bd5ac2c08f1 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4921,6 +4921,39 @@ describe('document', function() { done(); }); + it('virtuals with no getters return undefined (gh-6223)', function(done) { + var personSchema = new mongoose.Schema({ + name: { type: String }, + children: [{ + name: { type: String } + }] + }, { + toObject: { getters: true, virtuals: true }, + toJSON: { getters: true, virtuals: true }, + id: false + }); + + personSchema.virtual('favoriteChild').set(function (v) { + return this.set('children.0', v); + }); + + personSchema.virtual('heir').get(function () { + return this.get('children.0'); + }); + + var Person = db.model('gh6223', personSchema); + + var person = new Person({ + name: 'Anakin' + }); + + assert.strictEqual(person.favoriteChild, void 0); + assert.ok(!('favoriteChild' in person.toJSON())); + assert.ok(!('favoriteChild' in person.toObject())); + + done(); + }); + it('Single nested subdocs using discriminator can be modified (gh-5693)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', From c6295cbfbf1428e061fec8d960f7357257fa9fad Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Mar 2018 20:50:28 -0700 Subject: [PATCH 2193/2240] fix(document): make virtual get() return undefined instead of null if no getters Fix #6223 --- lib/document.js | 3 +++ test/document.test.js | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 920aa483809..65007d9a25e 100644 --- a/lib/document.js +++ b/lib/document.js @@ -988,6 +988,9 @@ Document.prototype.get = function(path, type) { var obj = this._doc; if (schema instanceof VirtualType) { + if (schema.getters.length === 0) { + return void 0; + } return schema.applyGetters(null, this); } diff --git a/test/document.test.js b/test/document.test.js index bd5ac2c08f1..6c9a27d8f70 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4933,11 +4933,11 @@ describe('document', function() { id: false }); - personSchema.virtual('favoriteChild').set(function (v) { + personSchema.virtual('favoriteChild').set(function(v) { return this.set('children.0', v); }); - personSchema.virtual('heir').get(function () { + personSchema.virtual('heir').get(function() { return this.get('children.0'); }); From cd2a15ac27b0119fbf09b39796ca91c947b21b0b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 13 Mar 2018 21:52:37 -0700 Subject: [PATCH 2194/2240] chore: release 4.13.12 --- History.md | 6 ++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 0a0638e8d93..003cec330d4 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +4.13.12 / 2018-03-13 +==================== + * fix(document): make virtual get() return undefined instead of null if no getters #6223 + * docs: fix url in useMongoClient error message #6219 #6217 [lineus](https://github.com/lineus) + * fix(discriminator): don't copy `discriminators` property from base schema #6122 #6064 + 4.13.11 / 2018-02-07 ==================== * docs: fix links in 4.x docs #6081 diff --git a/package-lock.json b/package-lock.json index 4d8d035097b..d272642bc88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.12-pre", + "version": "4.13.12", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0cbba6e56a2..e9d87e16ad9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.12-pre", + "version": "4.13.12", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 06cca17419ddc839a5f086d2b405c94cb0ed2113 Mon Sep 17 00:00:00 2001 From: Kev Date: Sun, 13 May 2018 14:53:56 -0400 Subject: [PATCH 2195/2240] add fix for #6439 to 4.x --- lib/services/query/castUpdate.js | 2 +- test/query.test.js | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/services/query/castUpdate.js b/lib/services/query/castUpdate.js index fa519cc1907..c89de2cc902 100644 --- a/lib/services/query/castUpdate.js +++ b/lib/services/query/castUpdate.js @@ -193,7 +193,7 @@ function walkUpdatePath(schema, obj, op, strict, context, pref) { (utils.isObject(val) && Object.keys(val).length === 0); } } else { - var checkPath = (key === '$each' || key === '$or' || key === '$and') ? + var checkPath = (key === '$each' || key === '$or' || key === '$and' || key === '$in') ? pref : prefix + key; schematype = schema._getSchema(checkPath); diff --git a/test/query.test.js b/test/query.test.js index f5807a6e71e..b53b6d2c3b2 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -9,6 +9,7 @@ var Schema = mongoose.Schema; var assert = require('power-assert'); var random = require('../lib/utils').random; var Query = require('../lib/query'); +var co = require('co'); /** * Test. @@ -918,6 +919,45 @@ describe('Query', function() { done(); }); + it('doesn\'t wipe out $in (gh-6439)', function () { + var embeddedSchema = new Schema({ + name: String + }, { _id: false }); + + var catSchema = new Schema({ + name: String, + props: [embeddedSchema] + }); + + var Cat = db.model('gh6439', catSchema); + var kitty = new Cat({ + name: 'Zildjian', + props: [ + { name: 'invalid' }, + { name: 'abc' }, + { name: 'def' } + ] + }); + + return co(function* () { + yield kitty.save(); + var cond = { _id: kitty._id }; + var update = { + $pull: { + props: { + $in: [ + { name: 'invalid' }, + { name: 'def' } + ] + } + } + }; + yield Cat.update(cond, update); + let found = yield Cat.findOne(cond); + assert.strictEqual(found.props[0].name, 'abc'); + }); + }); + it('subdocument array with $ne: null should not throw', function(done) { var query = new Query({}, {}, null, p1.collection); var Product = db.model('Product'); From 48f1fc30544bd3afbefb986e50f153c3c687effd Mon Sep 17 00:00:00 2001 From: Kev Date: Mon, 14 May 2018 05:54:33 -0400 Subject: [PATCH 2196/2240] remove co for compatibility --- test/query.test.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index b53b6d2c3b2..7e273b24a15 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -9,7 +9,6 @@ var Schema = mongoose.Schema; var assert = require('power-assert'); var random = require('../lib/utils').random; var Query = require('../lib/query'); -var co = require('co'); /** * Test. @@ -919,7 +918,7 @@ describe('Query', function() { done(); }); - it('doesn\'t wipe out $in (gh-6439)', function () { + it('doesn\'t wipe out $in (gh-6439)', function(done) { var embeddedSchema = new Schema({ name: String }, { _id: false }); @@ -939,8 +938,8 @@ describe('Query', function() { ] }); - return co(function* () { - yield kitty.save(); + kitty.save(function(err) { + assert.ifError(err); var cond = { _id: kitty._id }; var update = { $pull: { @@ -952,9 +951,14 @@ describe('Query', function() { } } }; - yield Cat.update(cond, update); - let found = yield Cat.findOne(cond); - assert.strictEqual(found.props[0].name, 'abc'); + Cat.update(cond, update, function(err) { + assert.ifError(err); + Cat.findOne(cond, function(err, found) { + assert.ifError(err); + assert.strictEqual(found.props[0].name, 'abc'); + done(); + }); + }); }); }); From 4219ded18905cfc8762fa3da2c9c1b6024b941c9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 17 May 2018 14:56:18 -0400 Subject: [PATCH 2197/2240] chore: bump lodash devDependency for security --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index d272642bc88..530718f51ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -426,7 +426,7 @@ "integrity": "sha1-BnbYLlYNgtLzF/gs8IWEg5Vae/4=", "dev": true, "requires": { - "lodash": "4.16.6", + "lodash": "4.17.10", "platform": "1.3.4" } }, @@ -966,7 +966,7 @@ "is-resolvable": "1.0.0", "js-yaml": "3.10.0", "json-stable-stringify": "1.0.1", - "lodash": "4.16.6", + "lodash": "4.17.10", "mkdirp": "0.5.1", "optionator": "0.8.2", "path-is-absolute": "1.0.1", @@ -1471,7 +1471,7 @@ "cli-cursor": "1.0.2", "cli-width": "2.2.0", "figures": "1.7.0", - "lodash": "4.16.6", + "lodash": "4.17.10", "readline2": "1.0.1", "run-async": "0.1.0", "rx-lite": "3.1.2", @@ -1817,9 +1817,9 @@ } }, "lodash": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.6.tgz", - "integrity": "sha1-0iyaxmAojzhD4Wun0rXQbMon13c=", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true }, "lodash._baseassign": { @@ -3174,7 +3174,7 @@ "ajv": "4.11.8", "ajv-keywords": "1.5.1", "chalk": "1.1.3", - "lodash": "4.16.6", + "lodash": "4.17.10", "slice-ansi": "0.0.4", "string-width": "2.1.1" }, diff --git a/package.json b/package.json index e9d87e16ad9..d5f6508df4d 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "highlight.js": "7.0.1", "istanbul": "0.4.4", "jade": "0.26.3", - "lodash": "4.16.6", + "lodash": "4.17.10", "markdown": "0.5.0", "marked": "0.3.9", "mocha": "3.2.0", From 67701e2605347ffb41e803eabcfaa5b239c8baa3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 17 May 2018 15:00:07 -0400 Subject: [PATCH 2198/2240] chore: bump async re: security vulnerability with lodash --- package-lock.json | 18 +++++------------- package.json | 2 +- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 530718f51ed..a7bc767cd76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -169,18 +169,11 @@ "dev": true }, "async": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz", - "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", "requires": { - "lodash": "4.17.4" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" - } + "lodash": "4.17.10" } }, "babel-code-frame": { @@ -1819,8 +1812,7 @@ "lodash": { "version": "4.17.10", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, "lodash._baseassign": { "version": "3.2.0", diff --git a/package.json b/package.json index d5f6508df4d..5a46da92dae 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ ], "license": "MIT", "dependencies": { - "async": "2.1.4", + "async": "2.6.0", "bson": "~1.0.4", "hooks-fixed": "2.0.2", "kareem": "1.5.0", From 94b11476e3de7b45fc92f11e6e466128f5c61394 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 17 May 2018 15:09:04 -0400 Subject: [PATCH 2199/2240] chore: release 4.13.13 --- History.md | 5 +++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 003cec330d4..8203c973da3 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +4.13.13 / 2018-05-17 +==================== + * fix(update): stop clobbering $in when casting update #6441 #6339 + * fix: upgrade async -> 2.6.0 re: security warning + 4.13.12 / 2018-03-13 ==================== * fix(document): make virtual get() return undefined instead of null if no getters #6223 diff --git a/package-lock.json b/package-lock.json index a7bc767cd76..cd8beb2b306 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.12", + "version": "4.13.13", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5a46da92dae..660f6dfe9a9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.12", + "version": "4.13.13", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 4d3dea511fb66c7a5ba21fff7c76fe79efe57ce5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 17 May 2018 15:11:02 -0400 Subject: [PATCH 2200/2240] chore: now working on 4.13.14 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index cd8beb2b306..3bb01bdf1d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.13", + "version": "4.13.14-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 660f6dfe9a9..7a2c4cbae9d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.13", + "version": "4.13.14-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 9f866fcd26fd6b0270d38ccd2fec25764dee4534 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 25 May 2018 11:34:57 -0400 Subject: [PATCH 2201/2240] test(model): repro #6484 --- test/model.findOneAndUpdate.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/model.findOneAndUpdate.test.js b/test/model.findOneAndUpdate.test.js index c1aadd4421e..a11dd73361b 100644 --- a/test/model.findOneAndUpdate.test.js +++ b/test/model.findOneAndUpdate.test.js @@ -1811,6 +1811,23 @@ describe('model: findOneAndUpdate:', function() { }); }); + it('honors retainKeyOrder (gh-6484)', function() { + var modelSchema = new Schema({ + nested: { field1: Number, field2: Number } + }, { retainKeyOrder: true }); + + var Model = db.model('gh6484', modelSchema); + var opts = { upsert: true, new: true }; + return Model.findOneAndUpdate({}, { nested: { field1: 1, field2: 2 } }, opts).exec(). + then(function() { + return Model.collection.findOne(); + }). + then(function(doc) { + // Make sure order is correct + assert.deepEqual(Object.keys(doc.nested), ['field1', 'field2']); + }); + }); + it('should not apply schema transforms (gh-4574)', function(done) { var options = { toObject: { From 833cc14ad4ee85a03f750cfd0498d2c2da768560 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 25 May 2018 11:36:23 -0400 Subject: [PATCH 2202/2240] fix(model): handle retainKeyOrder option in findOneAndUpdate() Fix #6484 --- lib/model.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 6da0f02de59..1d1defedd7b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1720,7 +1720,14 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { fields = options.fields; } - update = utils.clone(update, {depopulate: 1, _isNested: true}); + var retainKeyOrder = get(options, 'retainKeyOrder') || + get(this, 'schema.options.retainKeyOrder') || + false; + update = utils.clone(update, { + depopulate: true, + _isNested: true, + retainKeyOrder: retainKeyOrder + }); if (this.schema.options.versionKey && options && options.upsert) { if (options.overwrite) { update[this.schema.options.versionKey] = 0; From 471cadcbaa5daedd5d44f2cafd7908a826809d12 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 25 May 2018 11:44:26 -0400 Subject: [PATCH 2203/2240] chore: release 4.13.14 --- History.md | 4 ++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 8203c973da3..eadb47388ae 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +4.13.14 / 2018-05-25 +==================== + * fix(model): handle retainKeyOrder option in findOneAndUpdate() #6484 + 4.13.13 / 2018-05-17 ==================== * fix(update): stop clobbering $in when casting update #6441 #6339 diff --git a/package-lock.json b/package-lock.json index 3bb01bdf1d9..69bfcdb1615 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.14-pre", + "version": "4.13.14", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 7a2c4cbae9d..de9b7da5ef7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.14-pre", + "version": "4.13.14", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From ce7fb11815fcadc8412bfdcaa2cd31c8647bcdad Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 26 Apr 2018 17:56:20 -0400 Subject: [PATCH 2204/2240] feat(error): add version number to VersionError backport to 4.x of dd2483d1167f0878ca075835858d5708dfc307ac --- lib/error/version.js | 5 +++-- lib/model.js | 7 ++++--- test/versioning.test.js | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/error/version.js b/lib/error/version.js index 719c07f1254..33d1bd88e66 100644 --- a/lib/error/version.js +++ b/lib/error/version.js @@ -13,10 +13,11 @@ var MongooseError = require('./'); * @api private */ -function VersionError(doc) { +function VersionError(doc, currentVersion) { MongooseError.call(this, 'No matching document found for id "' + doc._id + - '"'); + '" version ' + currentVersion); this.name = 'VersionError'; + this.version = currentVersion; } /*! diff --git a/lib/model.js b/lib/model.js index 1d1defedd7b..8b85100599f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -258,16 +258,17 @@ Model.prototype.$__save = function(options, callback) { var doIncrement = VERSION_INC === (VERSION_INC & _this.$__.version); _this.$__.version = undefined; + var key = _this.schema.options.versionKey; + var version = _this.getValue(key) || 0; + if (numAffected <= 0) { // the update failed. pass an error back - var err = new VersionError(_this); + var err = new VersionError(_this, version); return callback(err); } // increment version if was successful if (doIncrement) { - var key = _this.schema.options.versionKey; - var version = _this.getValue(key) | 0; _this.setValue(key, version + 1); } } diff --git a/test/versioning.test.js b/test/versioning.test.js index db2e9854dc3..4e6856c8b08 100644 --- a/test/versioning.test.js +++ b/test/versioning.test.js @@ -265,6 +265,7 @@ describe('versioning', function() { function test4(err, a, b) { assert.ok(/No matching document/.test(err), err); assert.equal(a._doc.__v, 5); + assert.equal(err.version, b._doc.__v - 1); a.set('arr.0.0', 'updated'); var d = a.$__delta(); assert.equal(a._doc.__v, d[0].__v, 'version should be added to where clause'); From 84dffc32e266ad533774ac13145fb04c77f1fe7f Mon Sep 17 00:00:00 2001 From: Fonger Date: Mon, 6 Aug 2018 09:05:10 +0800 Subject: [PATCH 2205/2240] test(model): correct test pending value to prevent ci failure --- test/model.querying.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.querying.test.js b/test/model.querying.test.js index 8d7696a3902..ba4d068cd7d 100644 --- a/test/model.querying.test.js +++ b/test/model.querying.test.js @@ -2087,7 +2087,7 @@ describe('model: querying:', function() { assert.equal(tests.length, 3); }); - var pending = 9; + var pending = 10; function cb() { if (--pending) { From 5484542426c2f34bf90650b693f2ab998ec9f87a Mon Sep 17 00:00:00 2001 From: Fonger <5862369+Fonger@users.noreply.github.com> Date: Tue, 7 Aug 2018 01:39:08 +0800 Subject: [PATCH 2206/2240] test(document): fix near sphere test for #4014 --- test/document.test.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) mode change 100644 => 100755 test/document.test.js diff --git a/test/document.test.js b/test/document.test.js old mode 100644 new mode 100755 index 6c9a27d8f70..952729051f8 --- a/test/document.test.js +++ b/test/document.test.js @@ -2860,12 +2860,16 @@ describe('document', function() { var MyModel = db.model('gh4014', schema); - MyModel. - where('geo').near({ center: [50, 50] }). - exec(function(error) { - assert.ifError(error); - done(); - }); + MyModel.on('index', function(err) { + assert.ifError(err); + + MyModel. + where('geo').near({ center: [50, 50], spherical: true }). + exec(function(err) { + assert.ifError(err); + done(); + }); + }); }); it('skip validation if required returns false (gh-4094)', function(done) { From f2a4a5bb62610a2813a2947d49a48e0e80981748 Mon Sep 17 00:00:00 2001 From: Fonger <5862369+Fonger@users.noreply.github.com> Date: Tue, 7 Aug 2018 19:14:39 +0800 Subject: [PATCH 2207/2240] test(connection): increase delay to make sure driver give up reconnection Re: #4027 --- test/connection.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 test/connection.test.js diff --git a/test/connection.test.js b/test/connection.test.js old mode 100644 new mode 100755 index 1a0fe8fe457..2b94f3f7091 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -217,7 +217,7 @@ describe('connections:', function() { }). then(function() { return new Promise(function(resolve) { - setTimeout(function() { resolve(); }, 400); + setTimeout(function() { resolve(); }, 4000); }); }). then(function() { From c8d02584b263a8d78a99748b474e159b1efa6f87 Mon Sep 17 00:00:00 2001 From: Fonger <5862369+Fonger@users.noreply.github.com> Date: Tue, 7 Aug 2018 23:58:13 +0800 Subject: [PATCH 2208/2240] chore: fix file permission modified by WSL --- test/connection.test.js | 0 test/document.test.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 test/connection.test.js mode change 100755 => 100644 test/document.test.js diff --git a/test/connection.test.js b/test/connection.test.js old mode 100755 new mode 100644 diff --git a/test/document.test.js b/test/document.test.js old mode 100755 new mode 100644 From 127c75061b6d007a3d42e0b05493c3ec06eeb6ca Mon Sep 17 00:00:00 2001 From: Fonger <5862369+Fonger@users.noreply.github.com> Date: Fri, 10 Aug 2018 13:53:24 +0800 Subject: [PATCH 2209/2240] test(connection): adjust delay time to improve ci pass rate --- test/connection.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/connection.test.js b/test/connection.test.js index 2b94f3f7091..29eb8b57710 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -143,7 +143,7 @@ describe('connections:', function() { }). then(function() { return new Promise(function(resolve) { - setTimeout(function() { resolve(); }, 50); + setTimeout(function() { resolve(); }, 100); }); }). then(function() { @@ -157,7 +157,7 @@ describe('connections:', function() { }). then(function() { return new Promise(function(resolve) { - setTimeout(function() { resolve(); }, 2000); + setTimeout(function() { resolve(); }, 4000); }); }). then(function() { From df958a92ea1768083be103b97cc3bb1102b9d770 Mon Sep 17 00:00:00 2001 From: Fonger <5862369+Fonger@users.noreply.github.com> Date: Wed, 8 Aug 2018 01:36:56 +0800 Subject: [PATCH 2210/2240] resolve cherry-pick conflict --- .travis.yml | 4 +++- test/connection.test.js | 3 ++- test/document.test.js | 16 +++++++++++----- test/gh-1408.test.js | 2 ++ test/index.test.js | 2 ++ test/model.aggregate.test.js | 12 ++---------- test/model.create.test.js | 11 +++++++---- test/model.geosearch.test.js | 2 ++ test/model.populate.setting.test.js | 2 ++ test/model.populate.test.js | 2 ++ test/model.querying.test.js | 2 +- 11 files changed, 36 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index a7e9aeac0cc..b8f1b3115da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,9 @@ before_script: - tar -zxvf mongodb-linux-x86_64-2.6.11.tgz - mkdir -p ./data/db/27017 - mkdir -p ./data/db/27000 - - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --nopreallocj --dbpath ./data/db/27017 --syslog --port 27017 + - printf "\n--timeout 8000" >> ./test/mocha.opts + - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --dbpath ./data/db/27017 --syslog --port 27017 + - sleep 3 script: - npm test - npm run lint diff --git a/test/connection.test.js b/test/connection.test.js index 29eb8b57710..0d905b3b48e 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -18,6 +18,7 @@ var Schema = mongoose.Schema; */ describe('connections:', function() { + this.timeout(10000); describe('useMongoClient/openUri (gh-5304)', function() { it('with mongoose.connect()', function(done) { var conn = mongoose.connect('mongodb://localhost:27017/mongoosetest', { @@ -1082,7 +1083,7 @@ describe('connections:', function() { describe('errors', function() { it('event fires with one listener', function(done) { - this.timeout(1000); + this.timeout(1500); var db = start({uri: 'mongodb://whatever23939.localhost/fakeeee?connectTimeoutMS=500', noErrorListener: 1}); db.on('error', function() { // this callback has no params which triggered the bug #759 diff --git a/test/document.test.js b/test/document.test.js index 952729051f8..1c053e72744 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -1376,6 +1376,8 @@ describe('document', function() { }); it('validator should run only once per sub-doc gh-1743', function(done) { + this.timeout(process.env.TRAVIS ? 8000 : 4500); + var count = 0; var db = start(); @@ -1410,18 +1412,21 @@ describe('document', function() { it('validator should run in parallel', function(done) { - // we set the time out to be double that of the validator - 1 (so that running in serial will be greater than that) - this.timeout(1000); var db = start(); var count = 0; + var startTime, endTime; var SchemaWithValidator = new Schema({ preference: { type: String, required: true, - validate: function validator(value, done) { - count++; - setTimeout(done.bind(null, true), 500); + validate: { + validator: function validator(value, done) { + count++; + if (count === 1) startTime = Date.now(); + else if (count === 4) endTime = Date.now(); + setTimeout(done.bind(null, true), 150); + } } } }); @@ -1442,6 +1447,7 @@ describe('document', function() { m.save(function(err) { assert.ifError(err); assert.equal(count, 4); + assert(endTime - startTime < 150 * 4); // serial >= 150 * 4, parallel < 150 * 4 db.close(done); }); }); diff --git a/test/gh-1408.test.js b/test/gh-1408.test.js index 0231388d1f1..a6fda347d16 100644 --- a/test/gh-1408.test.js +++ b/test/gh-1408.test.js @@ -10,6 +10,8 @@ var start = require('./common'), describe('documents should not be converted to _id (gh-1408)', function() { it('if an embedded doc', function(done) { + this.timeout(process.env.TRAVIS ? 8000 : 4500); + var db = start(); var PreferenceSchema = new Schema({ diff --git a/test/index.test.js b/test/index.test.js index 34a7932b6e2..bfc8d7ae6e6 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -107,6 +107,8 @@ describe('mongoose module:', function() { }); describe('disconnection of all connections', function() { + this.timeout(10000); + describe('no callback', function() { it('works', function(done) { var mong = new Mongoose(), diff --git a/test/model.aggregate.test.js b/test/model.aggregate.test.js index c588eddd166..496773f322f 100644 --- a/test/model.aggregate.test.js +++ b/test/model.aggregate.test.js @@ -23,6 +23,8 @@ var collection = 'aggregate_' + random(); mongoose.model('Aggregate', userSchema); describe('model aggregate', function() { + this.timeout(process.env.TRAVIS ? 8000 : 4500); + var group = {$group: {_id: null, maxAge: {$max: '$age'}}}; var project = {$project: {maxAge: 1, _id: 0}}; var db, A, maxAge; @@ -74,8 +76,6 @@ describe('model aggregate', function() { }); it('when return promise', function(done) { - this.timeout(4000); - A.aggregate(group, project).then( function(res) { assert.ok(res); assert.equal(1, res.length); @@ -86,8 +86,6 @@ describe('model aggregate', function() { }); it('with arrays', function(done) { - this.timeout(4000); - A.aggregate([group, project], function(err, res) { assert.ifError(err); assert.ok(res); @@ -99,8 +97,6 @@ describe('model aggregate', function() { }); it('with Aggregate syntax', function(done) { - this.timeout(4000); - var promise = A.aggregate() .group(group.$group) .project(project.$project) @@ -116,8 +112,6 @@ describe('model aggregate', function() { }); it('with Aggregate syntax if callback not provided', function(done) { - this.timeout(4000); - var promise = A.aggregate() .group(group.$group) .project(project.$project) @@ -143,8 +137,6 @@ describe('model aggregate', function() { return done(); } - this.timeout(4000); - var outputCollection = 'aggregate_output_' + random(); A.aggregate() .group(group.$group) diff --git a/test/model.create.test.js b/test/model.create.test.js index 5b25327ab8c..67b6c819b89 100644 --- a/test/model.create.test.js +++ b/test/model.create.test.js @@ -99,8 +99,6 @@ describe('model', function() { }); it('creates in parallel', function(done) { - // we set the time out to be double that of the validator - 1 (so that running in serial will be greater than that) - this.timeout(1000); var db = start(), countPre = 0, countPost = 0; @@ -108,12 +106,16 @@ describe('model', function() { var SchemaWithPreSaveHook = new Schema({ preference: String }); + + var startTime, endTime; SchemaWithPreSaveHook.pre('save', true, function hook(next, done) { setTimeout(function() { countPre++; + if (countPre === 1) startTime = Date.now(); + else if (countPre === 4) endTime = Date.now(); next(); done(); - }, 500); + }, 100); }); SchemaWithPreSaveHook.post('save', function() { countPost++; @@ -139,7 +141,8 @@ describe('model', function() { assert.ok(doc4); assert.equal(countPre, 4); assert.equal(countPost, 4); - done(); + assert.ok(endTime - startTime < 4 * 100); // serial: >= 4 * 100 parallel: < 4 * 100 + db.close(done); }); }); diff --git a/test/model.geosearch.test.js b/test/model.geosearch.test.js index 65b082e1fe1..f144a05c5bc 100644 --- a/test/model.geosearch.test.js +++ b/test/model.geosearch.test.js @@ -22,6 +22,8 @@ describe('model', function() { }); describe('geoSearch', function() { + this.timeout(process.env.TRAVIS ? 8000 : 4500); + it('works', function(done) { var db = start(); var Geo = getModel(db); diff --git a/test/model.populate.setting.test.js b/test/model.populate.setting.test.js index ac279c898e3..a663b18bf1e 100644 --- a/test/model.populate.setting.test.js +++ b/test/model.populate.setting.test.js @@ -24,6 +24,8 @@ var posts = 'blogposts_' + random(), */ describe('model: populate:', function() { + this.timeout(process.env.TRAVIS ? 8000 : 4500); + describe('setting populated paths (gh-570)', function() { var types = { ObjectId: DocObjectId, diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 9fc1814f3a1..228dcea30a4 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -18,6 +18,8 @@ var DocObjectId = mongoose.Types.ObjectId; */ describe('model: populate:', function() { + this.timeout(process.env.TRAVIS ? 8000 : 4500); + var User; var Comment; var BlogPost; diff --git a/test/model.querying.test.js b/test/model.querying.test.js index ba4d068cd7d..1dd9f2e376d 100644 --- a/test/model.querying.test.js +++ b/test/model.querying.test.js @@ -1820,9 +1820,9 @@ describe('model: querying:', function() { }); it('with Dates', function(done) { - this.timeout(3000); var db = start(); + this.timeout(process.env.TRAVIS ? 8000 : 4500); var SSchema = new Schema({d: Date}); var PSchema = new Schema({sub: [SSchema]}); From 6af5f0b49555428fddf0866de8227a7111a774dc Mon Sep 17 00:00:00 2001 From: Fonger <5862369+Fonger@users.noreply.github.com> Date: Tue, 14 Aug 2018 07:07:23 +0800 Subject: [PATCH 2211/2240] test(populate): fix flaky test for #5602 --- test/model.populate.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 228dcea30a4..0f8012bb2f7 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -4607,8 +4607,8 @@ describe('model: populate:', function() { }). then(function(bs) { assert.equal(bs.length, 2); - assert.equal(bs[0].a.name, 'a1'); - assert.equal(bs[1].a.name, 'a2'); + var names = bs.map(function(b) { return b.a.name; }).sort(); + assert.deepEqual(names, ['a1', 'a2']); done(); }). catch(done); From 453f472fed662987e354f53994263780c758eb82 Mon Sep 17 00:00:00 2001 From: Fonger <5862369+Fonger@users.noreply.github.com> Date: Tue, 14 Aug 2018 07:24:27 +0800 Subject: [PATCH 2212/2240] test(populate): fix flaky test for #5737 --- test/model.populate.test.js | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 0f8012bb2f7..1271d2b3364 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -3273,16 +3273,27 @@ describe('model: populate:', function() { slice('fans', [0, 5]). populate('fans'). exec(function(err, blogposts) { - assert.ifError(error); + assert.ifError(err); - assert.equal(blogposts[0].title, 'Test 1'); - assert.equal(blogposts[1].title, 'Test 2'); + assert.ok(blogposts.length === 2); - assert.equal(blogposts[0].fans[0].name, 'Fan 1'); - assert.equal(blogposts[0].fans[1].name, 'Fan 2'); + var test1, test2; + if (blogposts[0].title === 'Test 1') { + test1 = blogposts[0]; + test2 = blogposts[1]; + } else { + test1 = blogposts[1]; + test2 = blogposts[0]; + } - assert.equal(blogposts[1].fans[0].name, 'Fan 2'); - assert.equal(blogposts[1].fans[1].name, 'Fan 1'); + assert.ok(test1.title === 'Test 1'); + assert.ok(test2.title === 'Test 2'); + + assert.equal(test1.fans[0].name, 'Fan 1'); + assert.equal(test1.fans[1].name, 'Fan 2'); + + assert.equal(test2.fans[0].name, 'Fan 2'); + assert.equal(test2.fans[1].name, 'Fan 1'); done(); }); }); From 754a4e9dd5af77c114a9d313039836426b7aebcd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 14 Aug 2018 10:28:23 -0400 Subject: [PATCH 2213/2240] chore: add test/files to npmignore+gitignore for 4.x --- .gitignore | 2 ++ .npmignore | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 6e433ac3b97..d9ae398e527 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ tools/31* *.key docs/*.html + +test/files/main.js diff --git a/.npmignore b/.npmignore index 8f66a38af64..da4b657952c 100644 --- a/.npmignore +++ b/.npmignore @@ -17,3 +17,5 @@ format_deps.js tools/31* *.key data/ + +test/files From 953a846499b74967bd02d7a1265f31d8f9385911 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 14 Aug 2018 10:44:52 -0400 Subject: [PATCH 2214/2240] fix(mongoose): add global `usePushEach` option for easier Mongoose 4.x + MongoDB 3.6 Fix #6858 --- lib/model.js | 9 ++++++++- test/common.js | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/model.js b/lib/model.js index 8b85100599f..e502bc8479f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -432,7 +432,14 @@ function handleAtomics(self, where, delta, data, value) { value.$__getAtomics().forEach(function(atomic) { var op = atomic[0]; var val = atomic[1]; - if (self.schema.options.usePushEach && op === '$pushAll') { + var usePushEach = false; + if ('usePushEach' in get(self, 'constructor.base.options', {})) { + usePushEach = self.constructor.base.get('usePushEach'); + } + if ('usePushEach' in self.schema.options) { + usePushEach = self.schema.options.usePushEach; + } + if (usePushEach && op === '$pushAll') { op = '$push'; val = { $each: val }; } diff --git a/test/common.js b/test/common.js index 041ac8d25ab..a00a381c3ad 100644 --- a/test/common.js +++ b/test/common.js @@ -100,6 +100,23 @@ module.exports = function(options) { return conn; }; +/*! + * ignore + */ + +before(function(done) { + module.exports.mongodVersion(function(err, version) { + if (err) { + return done(err); + } + var mongo36 = version[0] > 3 || (version[0] === 3 && version[1] >= 6); + if (mongo36) { + mongoose.set('usePushEach', true); + } + done(); + }); +}); + /*! * testing uri */ From 631f47633e78af0e1f4dda46ef1bb06197e1bb91 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 14 Aug 2018 11:10:34 -0400 Subject: [PATCH 2215/2240] chore: release 4.13.15 --- History.md | 6 ++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index eadb47388ae..fdfe10b5fce 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +4.13.15 / 2018-08-14 +==================== + * fix(mongoose): add global `usePushEach` option for easier Mongoose 4.x + MongoDB 3.6 #6858 + * chore: fix flakey tests for 4.x #6853 [Fonger](https://github.com/Fonger) + * feat(error): add version number to VersionError #6852 [freewil](https://github.com/freewil) + 4.13.14 / 2018-05-25 ==================== * fix(model): handle retainKeyOrder option in findOneAndUpdate() #6484 diff --git a/package-lock.json b/package-lock.json index 69bfcdb1615..36fb84996c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.14", + "version": "4.13.15", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index de9b7da5ef7..c4992d98b87 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.14", + "version": "4.13.15", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 7ba00683715457fa26575c34bf34168900c055d5 Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Sat, 12 May 2018 19:02:36 +0200 Subject: [PATCH 2216/2240] feat(error): add modified paths to VersionError backport #6464 to 4.x --- lib/error/version.js | 6 ++++-- lib/model.js | 5 ++++- test/versioning.test.js | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/error/version.js b/lib/error/version.js index 33d1bd88e66..8386aefb474 100644 --- a/lib/error/version.js +++ b/lib/error/version.js @@ -13,11 +13,13 @@ var MongooseError = require('./'); * @api private */ -function VersionError(doc, currentVersion) { +function VersionError(doc, currentVersion, modifiedPaths) { + var modifiedPathsStr = modifiedPaths.join(', '); MongooseError.call(this, 'No matching document found for id "' + doc._id + - '" version ' + currentVersion); + '" version ' + currentVersion + 'modifiedPaths "' + modifiedPathsStr + '"'); this.name = 'VersionError'; this.version = currentVersion; + this.modifiedPaths = modifiedPaths; } /*! diff --git a/lib/model.js b/lib/model.js index e502bc8479f..f0ba6eb4324 100644 --- a/lib/model.js +++ b/lib/model.js @@ -229,6 +229,9 @@ Model.prototype.$__save = function(options, callback) { }); } + // store the modified paths before the document is reset + var modifiedPaths = _this.modifiedPaths(); + _this.$__reset(); var numAffected = 0; @@ -263,7 +266,7 @@ Model.prototype.$__save = function(options, callback) { if (numAffected <= 0) { // the update failed. pass an error back - var err = new VersionError(_this, version); + var err = new VersionError(_this, version, modifiedPaths); return callback(err); } diff --git a/test/versioning.test.js b/test/versioning.test.js index 4e6856c8b08..4fa34acd7c9 100644 --- a/test/versioning.test.js +++ b/test/versioning.test.js @@ -266,6 +266,7 @@ describe('versioning', function() { assert.ok(/No matching document/.test(err), err); assert.equal(a._doc.__v, 5); assert.equal(err.version, b._doc.__v - 1); + assert.deepEqual(err.modifiedPaths, ['numbers', 'numbers.2']); a.set('arr.0.0', 'updated'); var d = a.$__delta(); assert.equal(a._doc.__v, d[0].__v, 'version should be added to where clause'); From 5046cef4393b3a705ab36ddfdf08569a232aaddd Mon Sep 17 00:00:00 2001 From: Sean Lavine Date: Mon, 20 Aug 2018 11:57:38 -0700 Subject: [PATCH 2217/2240] fix str spacing --- lib/error/version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/error/version.js b/lib/error/version.js index 8386aefb474..eed37fd5888 100644 --- a/lib/error/version.js +++ b/lib/error/version.js @@ -16,7 +16,7 @@ var MongooseError = require('./'); function VersionError(doc, currentVersion, modifiedPaths) { var modifiedPathsStr = modifiedPaths.join(', '); MongooseError.call(this, 'No matching document found for id "' + doc._id + - '" version ' + currentVersion + 'modifiedPaths "' + modifiedPathsStr + '"'); + '" version ' + currentVersion + ' modifiedPaths "' + modifiedPathsStr + '"'); this.name = 'VersionError'; this.version = currentVersion; this.modifiedPaths = modifiedPaths; From a3b98f62810f9f6fd3b4ef59f1365c2063a081e5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Aug 2018 10:55:44 -0400 Subject: [PATCH 2218/2240] fix(document): disallow setting __proto__ if strict mode false --- lib/document.js | 3 +++ package-lock.json | 6 +++--- package.json | 2 +- test/document.test.js | 16 ++++++++++++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/document.js b/lib/document.js index 65007d9a25e..05ade1ac540 100644 --- a/lib/document.js +++ b/lib/document.js @@ -917,6 +917,9 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche var next = i + 1; var last = next === l; cur += (cur ? '.' + parts[i] : parts[i]); + if (parts[i] === '__proto__') { + return; + } if (last) { obj[parts[i]] = val; diff --git a/package-lock.json b/package-lock.json index 36fb84996c6..6a4f91c9ba9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2126,9 +2126,9 @@ "dev": true }, "mpath": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz", - "integrity": "sha1-elj3iem1/TyUUgY0FXlg8mvV70Q=" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.0.tgz", + "integrity": "sha512-GJvQ1Iokij45SH/uJB03RkJ3HD5zJFhqzYFtUKkz+h9ZNxK18svUTef0/hIJbIPUfNln+tGdTZQ+KMazKvqIEA==" }, "mpromise": { "version": "0.5.5", diff --git a/package.json b/package.json index c4992d98b87..404e668c9ad 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "kareem": "1.5.0", "lodash.get": "4.4.2", "mongodb": "2.2.34", - "mpath": "0.3.0", + "mpath": "0.5.0", "mpromise": "0.5.5", "mquery": "2.3.3", "ms": "2.0.0", diff --git a/test/document.test.js b/test/document.test.js index 1c053e72744..4820e5091f3 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4964,6 +4964,22 @@ describe('document', function() { done(); }); + it('Disallows writing to __proto__', function(done) { + const schema = new mongoose.Schema({ + name: String + }, { strict: false }); + + const Model = db.model('prototest', schema); + const doc = new Model({ '__proto__.x': 'foo' }); + + assert.strictEqual(Model.x, void 0); + doc.set('__proto__.y', 'bar'); + + assert.strictEqual(Model.y, void 0); + + done(); + }); + it('Single nested subdocs using discriminator can be modified (gh-5693)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', From df93f5b2b824f835eec682923ee440b049d9ea6d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Aug 2018 10:57:46 -0400 Subject: [PATCH 2219/2240] chore: release 4.13.16 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index fdfe10b5fce..1f046e3b1da 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +4.13.16 / 2018-08-30 +==================== + * fix(document): disallow setting __proto__ if strict mode false + * feat(error): backport adding modified paths to VersionError #6928 [freewil](https://github.com/freewil) + 4.13.15 / 2018-08-14 ==================== * fix(mongoose): add global `usePushEach` option for easier Mongoose 4.x + MongoDB 3.6 #6858 diff --git a/package.json b/package.json index 404e668c9ad..33fc8b1e254 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.15", + "version": "4.13.16", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From b33d8c2fd0deafcf8da487a18a4fdbbc93db6ad1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Aug 2018 11:04:18 -0400 Subject: [PATCH 2220/2240] style: fix lint --- test/document.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index 4820e5091f3..1d5f132dd06 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4965,12 +4965,12 @@ describe('document', function() { }); it('Disallows writing to __proto__', function(done) { - const schema = new mongoose.Schema({ + var schema = new mongoose.Schema({ name: String }, { strict: false }); - const Model = db.model('prototest', schema); - const doc = new Model({ '__proto__.x': 'foo' }); + var Model = db.model('prototest', schema); + var doc = new Model({ '__proto__.x': 'foo' }); assert.strictEqual(Model.x, void 0); doc.set('__proto__.y', 'bar'); From fb8b644b7ffdd2799f23bb2d8dd1ba875ec8323a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Aug 2018 12:36:01 -0400 Subject: [PATCH 2221/2240] fix(document): disallow setting constructor and prototype if strict mode false --- lib/document.js | 4 +++- test/document.test.js | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/document.js b/lib/document.js index 05ade1ac540..fe514a93bed 100644 --- a/lib/document.js +++ b/lib/document.js @@ -31,6 +31,8 @@ var flatten = require('./services/common').flatten; var mpath = require('mpath'); var idGetter = require('./plugins/idGetter'); +var specialProperties = ['__proto__', 'constructor', 'prototype']; + /** * Document constructor. * @@ -917,7 +919,7 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche var next = i + 1; var last = next === l; cur += (cur ? '.' + parts[i] : parts[i]); - if (parts[i] === '__proto__') { + if (specialProperties.indexOf(parts[i]) !== -1) { return; } diff --git a/test/document.test.js b/test/document.test.js index 1d5f132dd06..a36ae60e55e 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4964,7 +4964,7 @@ describe('document', function() { done(); }); - it('Disallows writing to __proto__', function(done) { + it('Disallows writing to __proto__ and other special properties', function(done) { var schema = new mongoose.Schema({ name: String }, { strict: false }); @@ -4977,6 +4977,10 @@ describe('document', function() { assert.strictEqual(Model.y, void 0); + doc.set('constructor.prototype.z', 'baz'); + + assert.strictEqual(Model.z, void 0); + done(); }); From 4545d44c56a1fe62fa21d783b70bb3a8ff1734cd Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 30 Aug 2018 12:46:32 -0400 Subject: [PATCH 2222/2240] chore: release 4.13.17 --- History.md | 4 ++++ package-lock.json | 8 ++++---- package.json | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index 1f046e3b1da..c4033db4d7d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +4.13.17 / 2018-08-30 +==================== + * fix(document): disallow setting `constructor` and `prototype` if strict mode false + 4.13.16 / 2018-08-30 ==================== * fix(document): disallow setting __proto__ if strict mode false diff --git a/package-lock.json b/package-lock.json index 6a4f91c9ba9..34f276843b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.15", + "version": "4.13.17", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2126,9 +2126,9 @@ "dev": true }, "mpath": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.0.tgz", - "integrity": "sha512-GJvQ1Iokij45SH/uJB03RkJ3HD5zJFhqzYFtUKkz+h9ZNxK18svUTef0/hIJbIPUfNln+tGdTZQ+KMazKvqIEA==" + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.1.tgz", + "integrity": "sha512-H8OVQ+QEz82sch4wbODFOz+3YQ61FYz/z3eJ5pIdbMEaUzDqA268Wd+Vt4Paw9TJfvDgVKaayC0gBzMIw2jhsg==" }, "mpromise": { "version": "0.5.5", diff --git a/package.json b/package.json index 33fc8b1e254..8b08fb6a03e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.16", + "version": "4.13.17", "author": "Guillermo Rauch ", "keywords": [ "mongodb", @@ -25,7 +25,7 @@ "kareem": "1.5.0", "lodash.get": "4.4.2", "mongodb": "2.2.34", - "mpath": "0.5.0", + "mpath": "0.5.1", "mpromise": "0.5.5", "mquery": "2.3.3", "ms": "2.0.0", From 2370f97a4f39362eea0471bd2acff9e60a1e8d20 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Jan 2019 11:08:49 -0500 Subject: [PATCH 2223/2240] chore: now working on 4.13.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b08fb6a03e..be020f237f2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.17", + "version": "4.13.18-pre", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 0e1772f852a1eed23bf10ffaa0ff1151dafc3ba3 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Jan 2019 11:12:25 -0500 Subject: [PATCH 2224/2240] test(document): repro #7302 --- test/document.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index a36ae60e55e..f14c3762eca 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4984,6 +4984,27 @@ describe('document', function() { done(); }); + it('Handles setting populated path set via `Document#populate()` (gh-7302)', function() { + var authorSchema = new Schema({ name: String }); + var bookSchema = new Schema({ + author: { type: mongoose.Schema.Types.ObjectId, ref: 'gh7302_Author' } + }); + + var Author = db.model('gh7302_Author', authorSchema); + var Book = db.model('gh7302_Book', bookSchema); + + return Author.create({ name: 'Victor Hugo' }). + then(author => Book.create({ author: author._id })). + then(() => Book.findOne()). + then(doc => doc.populate('author').execPopulate()). + then(doc => { + doc.author = {}; + assert.ok(!doc.author.name); + assert.ifError(doc.validateSync()); + }); + }); + + it('Single nested subdocs using discriminator can be modified (gh-5693)', function(done) { var eventSchema = new Schema({ message: String }, { discriminatorKey: 'kind', From 29f6709f574bc6da5680963732124a3244bbf4ff Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Jan 2019 11:12:34 -0500 Subject: [PATCH 2225/2240] fix(model): handle setting populated path set via `Document#populate()` Fix #7302 --- lib/model.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/model.js b/lib/model.js index f0ba6eb4324..e5fc3a3d2dc 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3470,6 +3470,7 @@ function assignVals(o) { cur = cur[parts[j]]; } if (docs[i].$__) { + o.allOptions.model = o.allOptions.Model; docs[i].populated(o.path, o.allIds[i], o.allOptions); } utils.setValue(o.path, rawIds[i], docs[i], setValue); From edf70e44323a8e5a30c68cf785ad0e24fe2818ce Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Jan 2019 11:13:41 -0500 Subject: [PATCH 2226/2240] fix(cast): backport fix from #7290 to 4.x --- lib/cast.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cast.js b/lib/cast.js index a2c9777628a..7f475edfeb4 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -255,7 +255,7 @@ module.exports = function cast(schema, obj, options, context) { } } } - } else if (val.constructor.name === 'Array' && ['Buffer', 'Array'].indexOf(schematype.instance) === -1) { + } else if (Array.isArray(val) && ['Buffer', 'Array'].indexOf(schematype.instance) === -1) { var casted = []; for (var valIndex = 0; valIndex < val.length; valIndex++) { casted.push(schematype.castForQueryWrapper({ From c8b87207c0390757b08e8e6d334560d7d6047af6 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Jan 2019 11:18:13 -0500 Subject: [PATCH 2227/2240] style: fix lint --- test/document.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index f14c3762eca..db3edf7fc43 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -4994,10 +4994,10 @@ describe('document', function() { var Book = db.model('gh7302_Book', bookSchema); return Author.create({ name: 'Victor Hugo' }). - then(author => Book.create({ author: author._id })). - then(() => Book.findOne()). - then(doc => doc.populate('author').execPopulate()). - then(doc => { + then(function(author) { return Book.create({ author: author._id }); }). + then(function() { return Book.findOne(); }). + then(function(doc) { return doc.populate('author').execPopulate(); }). + then(function(doc) { doc.author = {}; assert.ok(!doc.author.name); assert.ifError(doc.validateSync()); From 8c75e9be93766c7302a6801ff1fcba6135d2e3cf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 20 Jan 2019 11:28:56 -0500 Subject: [PATCH 2228/2240] chore: dont run nsp --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b8f1b3115da..25ffa13582c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,5 @@ before_script: script: - npm test - npm run lint - - npm run nsp notifications: email: false From 75daf1868904d766ce4fb4b8e2bcb6af7fe64ffb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 21 Jan 2019 23:11:53 -0500 Subject: [PATCH 2229/2240] chore: release 4.13.18 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c4033db4d7d..4b6f56f86f5 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +4.13.18 / 2019-01-21 +==================== + * fix(model): handle setting populated path set via `Document#populate()` #7302 + * fix(cast): backport fix from #7290 to 4.x + 4.13.17 / 2018-08-30 ==================== * fix(document): disallow setting `constructor` and `prototype` if strict mode false diff --git a/package.json b/package.json index be020f237f2..67d86e5ef5b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.18-pre", + "version": "4.13.18", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From d9a202777b699a430c118b01e1b4a939063f2aa2 Mon Sep 17 00:00:00 2001 From: Sebastian Pederiva Date: Thu, 18 Jan 2018 14:11:48 +0200 Subject: [PATCH 2230/2240] fix bug: Using options in aggregates doesn't set anything --- lib/aggregate.js | 2 +- package-lock.json | 1012 ++++++++++++++++++++-------------------- test/aggregate.test.js | 4 +- 3 files changed, 510 insertions(+), 508 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index 6d9e1e0e248..a390176e936 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -564,7 +564,7 @@ Aggregate.prototype.allowDiskUse = function(value) { */ Aggregate.prototype.option = function(value) { - for (var key in Object.keys(value)) { + for (var key in value) { this.options[key] = value[key]; } return this; diff --git a/package-lock.json b/package-lock.json index 34f276843b8..243aae8f7c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.17", + "version": "4.13.18", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -16,7 +16,7 @@ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", "dev": true, "requires": { - "mime-types": "2.1.17", + "mime-types": "~2.1.16", "negotiator": "0.6.1" } }, @@ -38,7 +38,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "3.3.0" + "acorn": "^3.0.4" }, "dependencies": { "acorn": { @@ -81,8 +81,8 @@ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" } }, "ajv-keywords": { @@ -97,9 +97,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" } }, "amdefine": { @@ -132,7 +132,7 @@ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "array-filter": { @@ -153,7 +153,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { @@ -173,7 +173,7 @@ "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", "requires": { - "lodash": "4.17.10" + "lodash": "^4.14.0" } }, "babel-code-frame": { @@ -182,9 +182,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" } }, "babel-core": { @@ -193,25 +193,25 @@ "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.0", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.7", - "slash": "1.0.0", - "source-map": "0.5.7" + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.0", + "debug": "^2.6.8", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.7", + "slash": "^1.0.0", + "source-map": "^0.5.6" }, "dependencies": { "lodash": { @@ -234,14 +234,14 @@ "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", "dev": true, "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.4", - "source-map": "0.5.7", - "trim-right": "1.0.1" + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.6", + "trim-right": "^1.0.1" }, "dependencies": { "lodash": { @@ -264,8 +264,8 @@ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-messages": { @@ -274,7 +274,7 @@ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-polyfill": { @@ -283,9 +283,9 @@ "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "core-js": "2.5.1", - "regenerator-runtime": "0.10.5" + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" }, "dependencies": { "regenerator-runtime": { @@ -302,13 +302,13 @@ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "dev": true, "requires": { - "babel-core": "6.26.0", - "babel-runtime": "6.26.0", - "core-js": "2.5.1", - "home-or-tmp": "2.0.0", - "lodash": "4.17.4", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" }, "dependencies": { "lodash": { @@ -325,8 +325,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.1", - "regenerator-runtime": "0.11.0" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-template": { @@ -335,11 +335,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.4" + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" }, "dependencies": { "lodash": { @@ -356,15 +356,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.4" + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" }, "dependencies": { "globals": { @@ -387,10 +387,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.4", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" }, "dependencies": { "lodash": { @@ -419,8 +419,8 @@ "integrity": "sha1-BnbYLlYNgtLzF/gs8IWEg5Vae/4=", "dev": true, "requires": { - "lodash": "4.17.10", - "platform": "1.3.4" + "lodash": "^4.16.4", + "platform": "^1.3.1" } }, "bluebird": { @@ -435,15 +435,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.1", - "http-errors": "1.6.2", + "depd": "~1.1.1", + "http-errors": "~1.6.2", "iconv-lite": "0.4.19", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "1.6.15" + "type-is": "~1.6.15" } }, "brace-expansion": { @@ -452,7 +452,7 @@ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -490,7 +490,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "0.2.0" + "callsites": "^0.2.0" } }, "callsites": { @@ -511,8 +511,8 @@ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" } }, "chalk": { @@ -521,11 +521,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "circular-json": { @@ -540,7 +540,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "^1.0.1" } }, "cli-width": { @@ -555,8 +555,8 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", + "center-align": "^0.1.1", + "right-align": "^0.1.1", "wordwrap": "0.0.2" }, "dependencies": { @@ -610,9 +610,9 @@ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.2.7", - "typedarray": "0.0.6" + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "content-disposition": { @@ -662,7 +662,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.30" + "es5-ext": "^0.10.9" } }, "debug": { @@ -691,8 +691,8 @@ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", "dev": true, "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" + "foreach": "^2.0.5", + "object-keys": "^1.0.8" } }, "del": { @@ -701,13 +701,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" } }, "depd": { @@ -728,7 +728,7 @@ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "diff": { @@ -749,8 +749,8 @@ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, "dox": { @@ -760,7 +760,7 @@ "dev": true, "requires": { "commander": "0.6.1", - "github-flavored-markdown": "1.0.1" + "github-flavored-markdown": ">= 0.0.1" }, "dependencies": { "commander": { @@ -789,8 +789,8 @@ "integrity": "sha1-bw2nNEf07dg4/sXGAxOoi6XLhSs=", "dev": true, "requires": { - "core-js": "2.5.1", - "empower-core": "0.6.2" + "core-js": "^2.0.0", + "empower-core": "^0.6.2" } }, "empower-core": { @@ -800,7 +800,7 @@ "dev": true, "requires": { "call-signature": "0.0.2", - "core-js": "2.5.1" + "core-js": "^2.0.0" } }, "encodeurl": { @@ -815,8 +815,8 @@ "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=", "dev": true, "requires": { - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" + "es6-iterator": "2", + "es6-symbol": "~3.1" } }, "es6-iterator": { @@ -825,9 +825,9 @@ "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.14", + "es6-symbol": "^3.1" } }, "es6-map": { @@ -836,12 +836,12 @@ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30", - "es6-iterator": "2.0.1", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" } }, "es6-promise": { @@ -855,11 +855,11 @@ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30", - "es6-iterator": "2.0.1", + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "event-emitter": "~0.3.5" } }, "es6-symbol": { @@ -868,8 +868,8 @@ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30" + "d": "1", + "es5-ext": "~0.10.14" } }, "es6-weak-map": { @@ -878,10 +878,10 @@ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30", - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" } }, "escape-html": { @@ -902,11 +902,11 @@ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" }, "dependencies": { "esprima": { @@ -929,10 +929,10 @@ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", "dev": true, "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, "eslint": { @@ -941,38 +941,38 @@ "integrity": "sha1-v7OO/Lf5mBiApyS8LmHSFAku46k=", "dev": true, "requires": { - "chalk": "1.1.3", - "concat-stream": "1.6.0", - "debug": "2.6.9", - "doctrine": "1.5.0", - "es6-map": "0.1.5", - "escope": "3.6.0", - "espree": "3.5.1", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "1.3.1", - "glob": "6.0.4", - "globals": "8.18.0", - "ignore": "2.2.19", - "inquirer": "0.12.0", - "is-my-json-valid": "2.16.1", - "is-resolvable": "1.0.0", - "js-yaml": "3.10.0", - "json-stable-stringify": "1.0.1", - "lodash": "4.17.10", - "mkdirp": "0.5.1", - "optionator": "0.8.2", - "path-is-absolute": "1.0.1", - "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", - "require-uncached": "1.0.3", - "resolve": "1.4.0", - "shelljs": "0.5.3", - "strip-json-comments": "1.0.4", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "chalk": "^1.0.0", + "concat-stream": "^1.4.6", + "debug": "^2.1.1", + "doctrine": "^1.2.0", + "es6-map": "^0.1.3", + "escope": "^3.6.0", + "espree": "^3.1.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^1.1.1", + "glob": "^6.0.4", + "globals": "^8.18.0", + "ignore": "^2.2.19", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "optionator": "^0.8.1", + "path-is-absolute": "^1.0.0", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "resolve": "^1.1.6", + "shelljs": "^0.5.3", + "strip-json-comments": "~1.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" } }, "espree": { @@ -981,8 +981,8 @@ "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", "dev": true, "requires": { - "acorn": "5.1.2", - "acorn-jsx": "3.0.1" + "acorn": "^5.1.1", + "acorn-jsx": "^3.0.0" } }, "esprima": { @@ -996,7 +996,7 @@ "integrity": "sha1-HFz2y8zDLm9jk4C9T5kfq5up0iY=", "dev": true, "requires": { - "core-js": "2.5.1" + "core-js": "^2.0.0" } }, "esrecurse": { @@ -1005,8 +1005,8 @@ "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "^4.1.0", + "object-assign": "^4.0.1" } }, "estraverse": { @@ -1033,8 +1033,8 @@ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30" + "d": "1", + "es5-ext": "~0.10.14" } }, "exit-hook": { @@ -1049,36 +1049,36 @@ "integrity": "sha512-STB7LZ4N0L+81FJHGla2oboUHTk4PaN1RsOkoRh9OSeEKylvF5hwKYVX1xCLFaCT7MD0BNG/gX2WFMLqY6EMBw==", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "~1.3.4", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", - "content-type": "1.0.4", + "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.1", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.1", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "finalhandler": "1.1.0", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", + "proxy-addr": "~2.0.2", "qs": "6.5.1", - "range-parser": "1.2.0", + "range-parser": "~1.2.0", "safe-buffer": "5.1.1", "send": "0.16.1", "serve-static": "1.13.1", "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", + "statuses": "~1.3.1", + "type-is": "~1.6.15", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" } }, "fast-levenshtein": { @@ -1093,8 +1093,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, "file-entry-cache": { @@ -1103,8 +1103,8 @@ "integrity": "sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=", "dev": true, "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" } }, "fileset": { @@ -1113,8 +1113,8 @@ "integrity": "sha1-WI74lzxmI7KnbfRlEFaWuWqsgGc=", "dev": true, "requires": { - "glob": "5.0.15", - "minimatch": "2.0.10" + "glob": "5.x", + "minimatch": "2.x" }, "dependencies": { "glob": { @@ -1123,11 +1123,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "minimatch": { @@ -1136,7 +1136,7 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.0.0" } } } @@ -1148,12 +1148,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" } }, "flat-cache": { @@ -1162,10 +1162,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" } }, "foreach": { @@ -1198,8 +1198,8 @@ "integrity": "sha1-X5S92gr+U7xxCWm81vKCVI1gwnk=", "dev": true, "requires": { - "fileset": "0.1.8", - "minimatch": "0.2.14" + "fileset": "~0.1.5", + "minimatch": "~0.2.9" }, "dependencies": { "fileset": { @@ -1208,8 +1208,8 @@ "integrity": "sha1-UGuRqTluqn4y+0KoQHfHoMc2t0E=", "dev": true, "requires": { - "glob": "3.2.11", - "minimatch": "0.2.14" + "glob": "3.x", + "minimatch": "0.x" } }, "glob": { @@ -1218,8 +1218,8 @@ "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", "dev": true, "requires": { - "inherits": "2.0.3", - "minimatch": "0.3.0" + "inherits": "2", + "minimatch": "0.3" }, "dependencies": { "minimatch": { @@ -1228,8 +1228,8 @@ "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", "dev": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "lru-cache": "2", + "sigmund": "~1.0.0" } } } @@ -1240,8 +1240,8 @@ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", "dev": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "lru-cache": "2", + "sigmund": "~1.0.0" } } } @@ -1258,7 +1258,7 @@ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, "requires": { - "is-property": "1.0.2" + "is-property": "^1.0.0" } }, "github-flavored-markdown": { @@ -1273,11 +1273,11 @@ "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "globals": { @@ -1292,12 +1292,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "dependencies": { "glob": { @@ -1306,12 +1306,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } } } @@ -1340,10 +1340,10 @@ "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", "dev": true, "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.7.0" + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" }, "dependencies": { "async": { @@ -1358,7 +1358,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -1369,7 +1369,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-flag": { @@ -1390,8 +1390,8 @@ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" } }, "hooks-fixed": { @@ -1408,7 +1408,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": "1.3.1" + "statuses": ">= 1.3.1 < 2" }, "dependencies": { "setprototypeof": { @@ -1443,8 +1443,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -1458,19 +1458,19 @@ "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "2.2.0", - "figures": "1.7.0", - "lodash": "4.17.10", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" } }, "invariant": { @@ -1479,7 +1479,7 @@ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", "dev": true, "requires": { - "loose-envify": "1.3.1" + "loose-envify": "^1.0.0" } }, "ipaddr.js": { @@ -1500,7 +1500,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-fullwidth-code-point": { @@ -1509,7 +1509,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-my-json-valid": { @@ -1518,10 +1518,10 @@ "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", "dev": true, "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" } }, "is-path-cwd": { @@ -1536,7 +1536,7 @@ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "^1.0.0" } }, "is-path-inside": { @@ -1545,7 +1545,7 @@ "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.1" } }, "is-property": { @@ -1560,7 +1560,7 @@ "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", "dev": true, "requires": { - "tryit": "1.0.3" + "tryit": "^1.0.1" } }, "isarray": { @@ -1580,20 +1580,20 @@ "integrity": "sha1-6M9xjf7bcTyDNKuf+t418QQtKlY=", "dev": true, "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "fileset": "0.2.1", - "handlebars": "4.0.10", - "js-yaml": "3.10.0", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "once": "1.4.0", - "resolve": "1.1.7", - "supports-color": "3.2.3", - "which": "1.3.0", - "wordwrap": "1.0.0" + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "fileset": "0.2.x", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" }, "dependencies": { "async": { @@ -1620,7 +1620,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -1655,7 +1655,7 @@ "integrity": "sha1-uHrlUeNZ0orVIXdl6u9sB7dj9sg=", "dev": true, "requires": { - "growl": "1.7.0" + "growl": "~1.7.0" }, "dependencies": { "growl": { @@ -1672,14 +1672,14 @@ "integrity": "sha1-GOg5e4VpJO53ADZmw3MbWupQw50=", "dev": true, "requires": { - "coffee-script": "1.12.7", - "gaze": "0.3.4", - "jasmine-growl-reporter": "0.0.3", - "jasmine-reporters": "1.0.2", - "mkdirp": "0.3.5", - "requirejs": "2.3.5", - "underscore": "1.5.2", - "walkdir": "0.0.12" + "coffee-script": ">=1.0.1", + "gaze": "~0.3.2", + "jasmine-growl-reporter": "~0.0.2", + "jasmine-reporters": "~1.0.0", + "mkdirp": "~0.3.5", + "requirejs": ">=0.27.1", + "underscore": ">= 1.3.1", + "walkdir": ">= 0.0.1" }, "dependencies": { "mkdirp": { @@ -1696,7 +1696,7 @@ "integrity": "sha1-q2E+1Zd9x0h+hbPBL2qOqNsq3jE=", "dev": true, "requires": { - "mkdirp": "0.3.5" + "mkdirp": "~0.3.5" }, "dependencies": { "mkdirp": { @@ -1719,8 +1719,8 @@ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "dev": true, "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, "dependencies": { "esprima": { @@ -1743,7 +1743,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json3": { @@ -1781,7 +1781,7 @@ "integrity": "sha1-KaZ8CxJ7+lK907U7e4yGWamghPg=", "dev": true, "requires": { - "nan": "2.0.9" + "nan": "~2.0" } }, "kind-of": { @@ -1790,7 +1790,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" } }, "lazy-cache": { @@ -1805,8 +1805,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "lodash": { @@ -1820,8 +1820,8 @@ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" } }, "lodash._basecopy": { @@ -1854,9 +1854,9 @@ "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", "dev": true, "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" } }, "lodash.get": { @@ -1882,9 +1882,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" } }, "longest": { @@ -1899,7 +1899,7 @@ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "dev": true, "requires": { - "js-tokens": "3.0.2" + "js-tokens": "^3.0.0" } }, "lru-cache": { @@ -1914,7 +1914,7 @@ "integrity": "sha1-KCBbVlqK51kt4gdGPWY33BgnIrI=", "dev": true, "requires": { - "nopt": "2.1.2" + "nopt": "~2.1.1" }, "dependencies": { "nopt": { @@ -1923,7 +1923,7 @@ "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", "dev": true, "requires": { - "abbrev": "1.0.9" + "abbrev": "1" } } } @@ -1970,7 +1970,7 @@ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "mime-db": "1.30.0" + "mime-db": "~1.30.0" } }, "minimatch": { @@ -1979,7 +1979,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -2022,7 +2022,7 @@ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { - "graceful-readlink": "1.0.1" + "graceful-readlink": ">= 1.0.0" } }, "debug": { @@ -2040,12 +2040,12 @@ "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "ms": { @@ -2060,7 +2060,7 @@ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -2080,8 +2080,8 @@ "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz", "integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=", "requires": { - "bson": "1.0.4", - "require_optional": "1.0.1" + "bson": "~1.0.4", + "require_optional": "~1.0.0" } }, "mongodb-topology-manager": { @@ -2090,15 +2090,15 @@ "integrity": "sha1-GXDHRbhe36SAEQRaj+bQP2W1ofA=", "dev": true, "requires": { - "babel-core": "6.26.0", - "babel-polyfill": "6.26.0", - "bluebird": "3.5.0", - "co": "4.6.0", - "es6-promise": "3.2.1", + "babel-core": "^6.10.4", + "babel-polyfill": "^6.9.1", + "bluebird": "^3.4.1", + "co": "^4.6.0", + "es6-promise": "^3.2.1", "kerberos": "0.0.17", - "mkdirp": "0.5.1", - "mongodb-core": "1.3.21", - "rimraf": "2.6.2" + "mkdirp": "^0.5.1", + "mongodb-core": "^1.2.24", + "rimraf": "^2.4.3" }, "dependencies": { "bson": { @@ -2113,8 +2113,8 @@ "integrity": "sha1-/hKee+4rOybBQJ3gKrYNA/YpHMo=", "dev": true, "requires": { - "bson": "0.4.23", - "require_optional": "1.0.1" + "bson": "~0.4.23", + "require_optional": "~1.0.0" } } } @@ -2187,9 +2187,9 @@ "integrity": "sha1-kwgdg02b2dg3N3mN89o81TjokIo=", "dev": true, "requires": { - "colors": "1.1.2", - "mime": "2.0.3", - "optimist": "0.6.1" + "colors": ">=0.6.0", + "mime": ">=1.2.9", + "optimist": ">=0.3.4" } }, "nopt": { @@ -2198,7 +2198,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1.0.9" + "abbrev": "1" } }, "nsp": { @@ -2207,17 +2207,17 @@ "integrity": "sha512-jvjDg2Gsw4coD/iZ5eQddsDlkvnwMCNnpG05BproSnuG+Gr1bSQMwWMcQeYje+qdDl3XznmhblMPLpZLecTORQ==", "dev": true, "requires": { - "chalk": "1.1.3", - "cli-table": "0.3.1", - "cvss": "1.0.2", - "https-proxy-agent": "1.0.0", - "joi": "6.10.1", - "nodesecurity-npm-utils": "5.0.0", - "path-is-absolute": "1.0.1", - "rc": "1.2.1", - "semver": "5.4.1", - "subcommand": "2.1.0", - "wreck": "6.3.0" + "chalk": "^1.1.1", + "cli-table": "^0.3.1", + "cvss": "^1.0.0", + "https-proxy-agent": "^1.0.0", + "joi": "^6.9.1", + "nodesecurity-npm-utils": "^5.0.0", + "path-is-absolute": "^1.0.0", + "rc": "^1.1.2", + "semver": "^5.0.3", + "subcommand": "^2.0.3", + "wreck": "^6.3.0" }, "dependencies": { "agent-base": { @@ -2226,8 +2226,8 @@ "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", "dev": true, "requires": { - "extend": "3.0.1", - "semver": "5.0.3" + "extend": "~3.0.0", + "semver": "~5.0.1" }, "dependencies": { "semver": { @@ -2256,7 +2256,7 @@ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "chalk": { @@ -2265,11 +2265,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "cli-table": { @@ -2332,7 +2332,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "hoek": { @@ -2347,9 +2347,9 @@ "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", "dev": true, "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" + "agent-base": "2", + "debug": "2", + "extend": "3" } }, "ini": { @@ -2370,10 +2370,10 @@ "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", "dev": true, "requires": { - "hoek": "2.16.3", - "isemail": "1.2.0", - "moment": "2.18.1", - "topo": "1.1.0" + "hoek": "2.x.x", + "isemail": "1.x.x", + "moment": "2.x.x", + "topo": "1.x.x" } }, "minimist": { @@ -2412,10 +2412,10 @@ "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", "dev": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" } }, "semver": { @@ -2430,7 +2430,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -2445,10 +2445,10 @@ "integrity": "sha1-XkzspaN3njNlsVEeBfhmh3MC92A=", "dev": true, "requires": { - "cliclopts": "1.1.1", - "debug": "2.6.9", - "minimist": "1.2.0", - "xtend": "4.0.1" + "cliclopts": "^1.1.0", + "debug": "^2.1.3", + "minimist": "^1.2.0", + "xtend": "^4.0.0" } }, "supports-color": { @@ -2463,7 +2463,7 @@ "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "wreck": { @@ -2472,8 +2472,8 @@ "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", "dev": true, "requires": { - "boom": "2.10.1", - "hoek": "2.16.3" + "boom": "2.x.x", + "hoek": "2.x.x" } }, "xtend": { @@ -2517,7 +2517,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -2532,8 +2532,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" }, "dependencies": { "wordwrap": { @@ -2550,12 +2550,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" } }, "os-homedir": { @@ -2618,7 +2618,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "platform": { @@ -2639,11 +2639,11 @@ "integrity": "sha1-SC7gmKmHfoz6ciQshJm5PyBwnE4=", "dev": true, "requires": { - "define-properties": "1.1.2", - "empower": "1.2.3", - "power-assert-formatter": "1.4.1", - "universal-deep-strict-equal": "1.2.2", - "xtend": "4.0.1" + "define-properties": "^1.1.2", + "empower": "^1.1.0", + "power-assert-formatter": "^1.3.1", + "universal-deep-strict-equal": "^1.2.1", + "xtend": "^4.0.0" } }, "power-assert-context-formatter": { @@ -2652,8 +2652,8 @@ "integrity": "sha1-7bo1LT7YpgMRTWZyZazOYNaJzN8=", "dev": true, "requires": { - "core-js": "2.5.1", - "power-assert-context-traversal": "1.1.1" + "core-js": "^2.0.0", + "power-assert-context-traversal": "^1.1.1" } }, "power-assert-context-reducer-ast": { @@ -2662,11 +2662,11 @@ "integrity": "sha1-SEqZ4m9Jc/+IMuXFzHVnAuYJQXQ=", "dev": true, "requires": { - "acorn": "4.0.13", - "acorn-es7-plugin": "1.1.7", - "core-js": "2.5.1", - "espurify": "1.7.0", - "estraverse": "4.2.0" + "acorn": "^4.0.0", + "acorn-es7-plugin": "^1.0.12", + "core-js": "^2.0.0", + "espurify": "^1.6.0", + "estraverse": "^4.2.0" }, "dependencies": { "acorn": { @@ -2683,8 +2683,8 @@ "integrity": "sha1-iMq8oNE7Y1nwfT0+ivppkmRXftk=", "dev": true, "requires": { - "core-js": "2.5.1", - "estraverse": "4.2.0" + "core-js": "^2.0.0", + "estraverse": "^4.1.0" } }, "power-assert-formatter": { @@ -2693,13 +2693,13 @@ "integrity": "sha1-XcEl7VCj37HdomwZNH879Y7CiEo=", "dev": true, "requires": { - "core-js": "2.5.1", - "power-assert-context-formatter": "1.1.1", - "power-assert-context-reducer-ast": "1.1.2", - "power-assert-renderer-assertion": "1.1.1", - "power-assert-renderer-comparison": "1.1.1", - "power-assert-renderer-diagram": "1.1.2", - "power-assert-renderer-file": "1.1.1" + "core-js": "^2.0.0", + "power-assert-context-formatter": "^1.0.7", + "power-assert-context-reducer-ast": "^1.0.7", + "power-assert-renderer-assertion": "^1.0.7", + "power-assert-renderer-comparison": "^1.0.7", + "power-assert-renderer-diagram": "^1.0.7", + "power-assert-renderer-file": "^1.0.7" } }, "power-assert-renderer-assertion": { @@ -2708,8 +2708,8 @@ "integrity": "sha1-y/wOd+AIao+Wrz8djme57n4ozpg=", "dev": true, "requires": { - "power-assert-renderer-base": "1.1.1", - "power-assert-util-string-width": "1.1.1" + "power-assert-renderer-base": "^1.1.1", + "power-assert-util-string-width": "^1.1.1" } }, "power-assert-renderer-base": { @@ -2724,11 +2724,11 @@ "integrity": "sha1-10Odl9hRVr5OMKAPL7WnJRTOPAg=", "dev": true, "requires": { - "core-js": "2.5.1", - "diff-match-patch": "1.0.0", - "power-assert-renderer-base": "1.1.1", - "stringifier": "1.3.0", - "type-name": "2.0.2" + "core-js": "^2.0.0", + "diff-match-patch": "^1.0.0", + "power-assert-renderer-base": "^1.1.1", + "stringifier": "^1.3.0", + "type-name": "^2.0.1" } }, "power-assert-renderer-diagram": { @@ -2737,10 +2737,10 @@ "integrity": "sha1-ZV+PcRk1qbbVQbhjJ2VHF8Y3qYY=", "dev": true, "requires": { - "core-js": "2.5.1", - "power-assert-renderer-base": "1.1.1", - "power-assert-util-string-width": "1.1.1", - "stringifier": "1.3.0" + "core-js": "^2.0.0", + "power-assert-renderer-base": "^1.1.1", + "power-assert-util-string-width": "^1.1.1", + "stringifier": "^1.3.0" } }, "power-assert-renderer-file": { @@ -2749,7 +2749,7 @@ "integrity": "sha1-o34rvReMys0E5427eckv40kzxec=", "dev": true, "requires": { - "power-assert-renderer-base": "1.1.1" + "power-assert-renderer-base": "^1.1.1" } }, "power-assert-util-string-width": { @@ -2758,7 +2758,7 @@ "integrity": "sha1-vmWet5N/3S5smncmjar2S9W3xZI=", "dev": true, "requires": { - "eastasianwidth": "0.1.1" + "eastasianwidth": "^0.1.1" } }, "prelude-ls": { @@ -2790,7 +2790,7 @@ "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", "dev": true, "requires": { - "forwarded": "0.1.2", + "forwarded": "~0.1.2", "ipaddr.js": "1.5.2" } }, @@ -2829,13 +2829,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" } }, "readline2": { @@ -2844,8 +2844,8 @@ "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", "mute-stream": "0.0.5" } }, @@ -2872,7 +2872,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "^1.0.0" } }, "require-uncached": { @@ -2881,8 +2881,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" }, "dependencies": { "resolve-from": { @@ -2898,8 +2898,8 @@ "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", "requires": { - "resolve-from": "2.0.0", - "semver": "5.4.1" + "resolve-from": "^2.0.0", + "semver": "^5.1.0" } }, "requirejs": { @@ -2914,7 +2914,7 @@ "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "resolve-from": { @@ -2928,8 +2928,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" } }, "right-align": { @@ -2938,7 +2938,7 @@ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "0.1.4" + "align-text": "^0.1.1" } }, "rimraf": { @@ -2947,7 +2947,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" }, "dependencies": { "glob": { @@ -2956,12 +2956,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } } } @@ -2972,7 +2972,7 @@ "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.3.0" } }, "rx-lite": { @@ -2998,18 +2998,18 @@ "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.1", - "destroy": "1.0.4", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.1", + "destroy": "~1.0.4", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.2", + "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.3.1" + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.3.1" }, "dependencies": { "mime": { @@ -3026,9 +3026,9 @@ "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", "dev": true, "requires": { - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "parseurl": "1.3.2", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", "send": "0.16.1" } }, @@ -3074,7 +3074,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } }, "source-map-support": { @@ -3083,7 +3083,7 @@ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.5.6" }, "dependencies": { "source-map": { @@ -3112,9 +3112,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -3122,7 +3122,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "stringifier": { @@ -3131,9 +3131,9 @@ "integrity": "sha1-3vGDQvaTPbDy2/yaoCF1tEjBeVk=", "dev": true, "requires": { - "core-js": "2.5.1", - "traverse": "0.6.6", - "type-name": "2.0.2" + "core-js": "^2.0.0", + "traverse": "^0.6.6", + "type-name": "^2.0.1" } }, "strip-ansi": { @@ -3142,7 +3142,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -3163,12 +3163,12 @@ "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.10", + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", "slice-ansi": "0.0.4", - "string-width": "2.1.1" + "string-width": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -3189,8 +3189,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -3199,7 +3199,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -3210,9 +3210,9 @@ "integrity": "sha1-btWic3ZPhu0mjJYeG9TVyk0N5tQ=", "dev": true, "requires": { - "express": "4.16.1", - "jade": "0.26.3", - "jasmine-node": "1.14.5" + "express": ">=2.5.0", + "jade": ">=0.18.0", + "jasmine-node": ">=1.0.0" } }, "text-table": { @@ -3257,7 +3257,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-is": { @@ -3267,7 +3267,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.17" + "mime-types": "~2.1.15" } }, "type-name": { @@ -3288,10 +3288,10 @@ "integrity": "sha1-8CHji6LKdAhg9b1caVwqgXNF8Ow=", "dev": true, "requires": { - "async": "0.2.10", - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" }, "dependencies": { "async": { @@ -3326,9 +3326,9 @@ "integrity": "sha1-DaSsL3PP95JMgfpN4BjKViyisKc=", "dev": true, "requires": { - "array-filter": "1.0.0", + "array-filter": "^1.0.0", "indexof": "0.0.1", - "object-keys": "1.0.11" + "object-keys": "^1.0.0" } }, "unpipe": { @@ -3343,7 +3343,7 @@ "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.0" } }, "util-deprecate": { @@ -3393,7 +3393,7 @@ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "window-size": { @@ -3420,7 +3420,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" } }, "xtend": { @@ -3435,9 +3435,9 @@ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", "window-size": "0.1.0" } } diff --git a/test/aggregate.test.js b/test/aggregate.test.js index bb1b80689ca..6b3c757fba9 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -854,7 +854,7 @@ describe('aggregate: ', function() { }); }); - it('handles aggregation options', function(done) { + it('handles aggregation options allowDiskUse', function(done) { start.mongodVersion(function(err, version) { if (err) { throw err; @@ -867,11 +867,13 @@ describe('aggregate: ', function() { var aggregate = m.aggregate(match).read(pref); if (mongo26_or_greater) { aggregate.allowDiskUse(true); + aggregate.option({maxTimeMS: 1000}); } assert.equal(aggregate.options.readPreference.mode, pref); if (mongo26_or_greater) { assert.equal(aggregate.options.allowDiskUse, true); + assert.equal(aggregate.options.maxTimeMS, 1000); } aggregate. From b10cc982b3967170be8adf35ca58cecef67c008c Mon Sep 17 00:00:00 2001 From: Sebastian Pederiva Date: Thu, 18 Jan 2018 14:22:41 +0200 Subject: [PATCH 2231/2240] rename aggregation option test --- test/aggregate.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/aggregate.test.js b/test/aggregate.test.js index 6b3c757fba9..0e36da861ec 100644 --- a/test/aggregate.test.js +++ b/test/aggregate.test.js @@ -854,7 +854,7 @@ describe('aggregate: ', function() { }); }); - it('handles aggregation options allowDiskUse', function(done) { + it('handles aggregation options', function(done) { start.mongodVersion(function(err, version) { if (err) { throw err; From f51c4aaceaae97a09b402bc395bd5eb60157d168 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 2 Jul 2019 18:09:54 -0400 Subject: [PATCH 2232/2240] chore: release 4.13.19 --- History.md | 4 + package-lock.json | 1012 ++++++++++++++++++++++----------------------- package.json | 2 +- 3 files changed, 511 insertions(+), 507 deletions(-) diff --git a/History.md b/History.md index 4b6f56f86f5..f53d01bcfb5 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +4.13.19 / 2019-07-02 +==================== + * fix(aggregate): make `setOptions()` work as advertised #7950 #6011 [cdimitroulas](https://github.com/cdimitroulas) + 4.13.18 / 2019-01-21 ==================== * fix(model): handle setting populated path set via `Document#populate()` #7302 diff --git a/package-lock.json b/package-lock.json index 243aae8f7c9..e020a0a1130 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.18", + "version": "4.13.19", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -16,7 +16,7 @@ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", "dev": true, "requires": { - "mime-types": "~2.1.16", + "mime-types": "2.1.17", "negotiator": "0.6.1" } }, @@ -38,7 +38,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "^3.0.4" + "acorn": "3.3.0" }, "dependencies": { "acorn": { @@ -81,8 +81,8 @@ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" + "co": "4.6.0", + "json-stable-stringify": "1.0.1" } }, "ajv-keywords": { @@ -97,9 +97,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" } }, "amdefine": { @@ -132,7 +132,7 @@ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "sprintf-js": "1.0.3" } }, "array-filter": { @@ -153,7 +153,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "^1.0.1" + "array-uniq": "1.0.3" } }, "array-uniq": { @@ -173,7 +173,7 @@ "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", "requires": { - "lodash": "^4.14.0" + "lodash": "4.17.10" } }, "babel-code-frame": { @@ -182,9 +182,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" } }, "babel-core": { @@ -193,25 +193,25 @@ "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", "dev": true, "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.0", - "debug": "^2.6.8", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.7", - "slash": "^1.0.0", - "source-map": "^0.5.6" + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.0", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.7", + "slash": "1.0.0", + "source-map": "0.5.7" }, "dependencies": { "lodash": { @@ -234,14 +234,14 @@ "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", "dev": true, "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.6", - "trim-right": "^1.0.1" + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" }, "dependencies": { "lodash": { @@ -264,8 +264,8 @@ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" } }, "babel-messages": { @@ -274,7 +274,7 @@ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.26.0" } }, "babel-polyfill": { @@ -283,9 +283,9 @@ "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" + "babel-runtime": "6.26.0", + "core-js": "2.5.1", + "regenerator-runtime": "0.10.5" }, "dependencies": { "regenerator-runtime": { @@ -302,13 +302,13 @@ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "dev": true, "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.1", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" }, "dependencies": { "lodash": { @@ -325,8 +325,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.1", + "regenerator-runtime": "0.11.0" } }, "babel-template": { @@ -335,11 +335,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" }, "dependencies": { "lodash": { @@ -356,15 +356,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" }, "dependencies": { "globals": { @@ -387,10 +387,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" }, "dependencies": { "lodash": { @@ -419,8 +419,8 @@ "integrity": "sha1-BnbYLlYNgtLzF/gs8IWEg5Vae/4=", "dev": true, "requires": { - "lodash": "^4.16.4", - "platform": "^1.3.1" + "lodash": "4.17.10", + "platform": "1.3.4" } }, "bluebird": { @@ -435,15 +435,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "~1.0.4", + "content-type": "1.0.4", "debug": "2.6.9", - "depd": "~1.1.1", - "http-errors": "~1.6.2", + "depd": "1.1.1", + "http-errors": "1.6.2", "iconv-lite": "0.4.19", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "~1.6.15" + "type-is": "1.6.15" } }, "brace-expansion": { @@ -452,7 +452,7 @@ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "dev": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -490,7 +490,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "^0.2.0" + "callsites": "0.2.0" } }, "callsites": { @@ -511,8 +511,8 @@ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" + "align-text": "0.1.4", + "lazy-cache": "1.0.4" } }, "chalk": { @@ -521,11 +521,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "circular-json": { @@ -540,7 +540,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "^1.0.1" + "restore-cursor": "1.0.1" } }, "cli-width": { @@ -555,8 +555,8 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", + "center-align": "0.1.3", + "right-align": "0.1.3", "wordwrap": "0.0.2" }, "dependencies": { @@ -610,9 +610,9 @@ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", "dev": true, "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "inherits": "2.0.3", + "readable-stream": "2.2.7", + "typedarray": "0.0.6" } }, "content-disposition": { @@ -662,7 +662,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "^0.10.9" + "es5-ext": "0.10.30" } }, "debug": { @@ -691,8 +691,8 @@ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", "dev": true, "requires": { - "foreach": "^2.0.5", - "object-keys": "^1.0.8" + "foreach": "2.0.5", + "object-keys": "1.0.11" } }, "del": { @@ -701,13 +701,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" } }, "depd": { @@ -728,7 +728,7 @@ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { - "repeating": "^2.0.0" + "repeating": "2.0.1" } }, "diff": { @@ -749,8 +749,8 @@ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" + "esutils": "2.0.2", + "isarray": "1.0.0" } }, "dox": { @@ -760,7 +760,7 @@ "dev": true, "requires": { "commander": "0.6.1", - "github-flavored-markdown": ">= 0.0.1" + "github-flavored-markdown": "1.0.1" }, "dependencies": { "commander": { @@ -789,8 +789,8 @@ "integrity": "sha1-bw2nNEf07dg4/sXGAxOoi6XLhSs=", "dev": true, "requires": { - "core-js": "^2.0.0", - "empower-core": "^0.6.2" + "core-js": "2.5.1", + "empower-core": "0.6.2" } }, "empower-core": { @@ -800,7 +800,7 @@ "dev": true, "requires": { "call-signature": "0.0.2", - "core-js": "^2.0.0" + "core-js": "2.5.1" } }, "encodeurl": { @@ -815,8 +815,8 @@ "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=", "dev": true, "requires": { - "es6-iterator": "2", - "es6-symbol": "~3.1" + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" } }, "es6-iterator": { @@ -825,9 +825,9 @@ "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.14", - "es6-symbol": "^3.1" + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-symbol": "3.1.1" } }, "es6-map": { @@ -836,12 +836,12 @@ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" } }, "es6-promise": { @@ -855,11 +855,11 @@ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" + "event-emitter": "0.3.5" } }, "es6-symbol": { @@ -868,8 +868,8 @@ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14" + "d": "1.0.0", + "es5-ext": "0.10.30" } }, "es6-weak-map": { @@ -878,10 +878,10 @@ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" } }, "escape-html": { @@ -902,11 +902,11 @@ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" }, "dependencies": { "esprima": { @@ -929,10 +929,10 @@ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", "dev": true, "requires": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" } }, "eslint": { @@ -941,38 +941,38 @@ "integrity": "sha1-v7OO/Lf5mBiApyS8LmHSFAku46k=", "dev": true, "requires": { - "chalk": "^1.0.0", - "concat-stream": "^1.4.6", - "debug": "^2.1.1", - "doctrine": "^1.2.0", - "es6-map": "^0.1.3", - "escope": "^3.6.0", - "espree": "^3.1.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^1.1.1", - "glob": "^6.0.4", - "globals": "^8.18.0", - "ignore": "^2.2.19", - "inquirer": "^0.12.0", - "is-my-json-valid": "^2.10.0", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.5.1", - "json-stable-stringify": "^1.0.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.0", - "optionator": "^0.8.1", - "path-is-absolute": "^1.0.0", - "path-is-inside": "^1.0.1", - "pluralize": "^1.2.1", - "progress": "^1.1.8", - "require-uncached": "^1.0.2", - "resolve": "^1.1.6", - "shelljs": "^0.5.3", - "strip-json-comments": "~1.0.1", - "table": "^3.7.8", - "text-table": "~0.2.0", - "user-home": "^2.0.0" + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.9", + "doctrine": "1.5.0", + "es6-map": "0.1.5", + "escope": "3.6.0", + "espree": "3.5.1", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "1.3.1", + "glob": "6.0.4", + "globals": "8.18.0", + "ignore": "2.2.19", + "inquirer": "0.12.0", + "is-my-json-valid": "2.16.1", + "is-resolvable": "1.0.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "lodash": "4.17.10", + "mkdirp": "0.5.1", + "optionator": "0.8.2", + "path-is-absolute": "1.0.1", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "resolve": "1.4.0", + "shelljs": "0.5.3", + "strip-json-comments": "1.0.4", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" } }, "espree": { @@ -981,8 +981,8 @@ "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", "dev": true, "requires": { - "acorn": "^5.1.1", - "acorn-jsx": "^3.0.0" + "acorn": "5.1.2", + "acorn-jsx": "3.0.1" } }, "esprima": { @@ -996,7 +996,7 @@ "integrity": "sha1-HFz2y8zDLm9jk4C9T5kfq5up0iY=", "dev": true, "requires": { - "core-js": "^2.0.0" + "core-js": "2.5.1" } }, "esrecurse": { @@ -1005,8 +1005,8 @@ "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", "dev": true, "requires": { - "estraverse": "^4.1.0", - "object-assign": "^4.0.1" + "estraverse": "4.2.0", + "object-assign": "4.1.1" } }, "estraverse": { @@ -1033,8 +1033,8 @@ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14" + "d": "1.0.0", + "es5-ext": "0.10.30" } }, "exit-hook": { @@ -1049,36 +1049,36 @@ "integrity": "sha512-STB7LZ4N0L+81FJHGla2oboUHTk4PaN1RsOkoRh9OSeEKylvF5hwKYVX1xCLFaCT7MD0BNG/gX2WFMLqY6EMBw==", "dev": true, "requires": { - "accepts": "~1.3.4", + "accepts": "1.3.4", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", - "content-type": "~1.0.4", + "content-type": "1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.1", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "etag": "~1.8.1", + "depd": "1.1.1", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.1", "finalhandler": "1.1.0", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.2", + "proxy-addr": "2.0.2", "qs": "6.5.1", - "range-parser": "~1.2.0", + "range-parser": "1.2.0", "safe-buffer": "5.1.1", "send": "0.16.1", "serve-static": "1.13.1", "setprototypeof": "1.1.0", - "statuses": "~1.3.1", - "type-is": "~1.6.15", + "statuses": "1.3.1", + "type-is": "1.6.15", "utils-merge": "1.0.1", - "vary": "~1.1.2" + "vary": "1.1.2" } }, "fast-levenshtein": { @@ -1093,8 +1093,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } }, "file-entry-cache": { @@ -1103,8 +1103,8 @@ "integrity": "sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "1.3.0", + "object-assign": "4.1.1" } }, "fileset": { @@ -1113,8 +1113,8 @@ "integrity": "sha1-WI74lzxmI7KnbfRlEFaWuWqsgGc=", "dev": true, "requires": { - "glob": "5.x", - "minimatch": "2.x" + "glob": "5.0.15", + "minimatch": "2.0.10" }, "dependencies": { "glob": { @@ -1123,11 +1123,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "minimatch": { @@ -1136,7 +1136,7 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "^1.0.0" + "brace-expansion": "1.1.8" } } } @@ -1148,12 +1148,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" } }, "flat-cache": { @@ -1162,10 +1162,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" } }, "foreach": { @@ -1198,8 +1198,8 @@ "integrity": "sha1-X5S92gr+U7xxCWm81vKCVI1gwnk=", "dev": true, "requires": { - "fileset": "~0.1.5", - "minimatch": "~0.2.9" + "fileset": "0.1.8", + "minimatch": "0.2.14" }, "dependencies": { "fileset": { @@ -1208,8 +1208,8 @@ "integrity": "sha1-UGuRqTluqn4y+0KoQHfHoMc2t0E=", "dev": true, "requires": { - "glob": "3.x", - "minimatch": "0.x" + "glob": "3.2.11", + "minimatch": "0.2.14" } }, "glob": { @@ -1218,8 +1218,8 @@ "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", "dev": true, "requires": { - "inherits": "2", - "minimatch": "0.3" + "inherits": "2.0.3", + "minimatch": "0.3.0" }, "dependencies": { "minimatch": { @@ -1228,8 +1228,8 @@ "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", "dev": true, "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "lru-cache": "2.7.3", + "sigmund": "1.0.1" } } } @@ -1240,8 +1240,8 @@ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", "dev": true, "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "lru-cache": "2.7.3", + "sigmund": "1.0.1" } } } @@ -1258,7 +1258,7 @@ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, "requires": { - "is-property": "^1.0.0" + "is-property": "1.0.2" } }, "github-flavored-markdown": { @@ -1273,11 +1273,11 @@ "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "globals": { @@ -1292,12 +1292,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" }, "dependencies": { "glob": { @@ -1306,12 +1306,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } } } @@ -1340,10 +1340,10 @@ "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", "dev": true, "requires": { - "async": "^1.4.0", - "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.7.0" }, "dependencies": { "async": { @@ -1358,7 +1358,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": ">=0.0.4" + "amdefine": "1.0.1" } } } @@ -1369,7 +1369,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "has-flag": { @@ -1390,8 +1390,8 @@ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "hooks-fixed": { @@ -1408,7 +1408,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": ">= 1.3.1 < 2" + "statuses": "1.3.1" }, "dependencies": { "setprototypeof": { @@ -1443,8 +1443,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -1458,19 +1458,19 @@ "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", "dev": true, "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.17.10", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" } }, "invariant": { @@ -1479,7 +1479,7 @@ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", "dev": true, "requires": { - "loose-envify": "^1.0.0" + "loose-envify": "1.3.1" } }, "ipaddr.js": { @@ -1500,7 +1500,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-fullwidth-code-point": { @@ -1509,7 +1509,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-my-json-valid": { @@ -1518,10 +1518,10 @@ "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", "dev": true, "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" } }, "is-path-cwd": { @@ -1536,7 +1536,7 @@ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "is-path-inside": "1.0.0" } }, "is-path-inside": { @@ -1545,7 +1545,7 @@ "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", "dev": true, "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "1.0.2" } }, "is-property": { @@ -1560,7 +1560,7 @@ "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", "dev": true, "requires": { - "tryit": "^1.0.1" + "tryit": "1.0.3" } }, "isarray": { @@ -1580,20 +1580,20 @@ "integrity": "sha1-6M9xjf7bcTyDNKuf+t418QQtKlY=", "dev": true, "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "fileset": "0.2.x", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "fileset": "0.2.1", + "handlebars": "4.0.10", + "js-yaml": "3.10.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" }, "dependencies": { "async": { @@ -1620,7 +1620,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -1655,7 +1655,7 @@ "integrity": "sha1-uHrlUeNZ0orVIXdl6u9sB7dj9sg=", "dev": true, "requires": { - "growl": "~1.7.0" + "growl": "1.7.0" }, "dependencies": { "growl": { @@ -1672,14 +1672,14 @@ "integrity": "sha1-GOg5e4VpJO53ADZmw3MbWupQw50=", "dev": true, "requires": { - "coffee-script": ">=1.0.1", - "gaze": "~0.3.2", - "jasmine-growl-reporter": "~0.0.2", - "jasmine-reporters": "~1.0.0", - "mkdirp": "~0.3.5", - "requirejs": ">=0.27.1", - "underscore": ">= 1.3.1", - "walkdir": ">= 0.0.1" + "coffee-script": "1.12.7", + "gaze": "0.3.4", + "jasmine-growl-reporter": "0.0.3", + "jasmine-reporters": "1.0.2", + "mkdirp": "0.3.5", + "requirejs": "2.3.5", + "underscore": "1.5.2", + "walkdir": "0.0.12" }, "dependencies": { "mkdirp": { @@ -1696,7 +1696,7 @@ "integrity": "sha1-q2E+1Zd9x0h+hbPBL2qOqNsq3jE=", "dev": true, "requires": { - "mkdirp": "~0.3.5" + "mkdirp": "0.3.5" }, "dependencies": { "mkdirp": { @@ -1719,8 +1719,8 @@ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "1.0.9", + "esprima": "4.0.0" }, "dependencies": { "esprima": { @@ -1743,7 +1743,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "~0.0.0" + "jsonify": "0.0.0" } }, "json3": { @@ -1781,7 +1781,7 @@ "integrity": "sha1-KaZ8CxJ7+lK907U7e4yGWamghPg=", "dev": true, "requires": { - "nan": "~2.0" + "nan": "2.0.9" } }, "kind-of": { @@ -1790,7 +1790,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.5" } }, "lazy-cache": { @@ -1805,8 +1805,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "lodash": { @@ -1820,8 +1820,8 @@ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", "dev": true, "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" } }, "lodash._basecopy": { @@ -1854,9 +1854,9 @@ "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", "dev": true, "requires": { - "lodash._baseassign": "^3.0.0", - "lodash._basecreate": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" } }, "lodash.get": { @@ -1882,9 +1882,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" } }, "longest": { @@ -1899,7 +1899,7 @@ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "dev": true, "requires": { - "js-tokens": "^3.0.0" + "js-tokens": "3.0.2" } }, "lru-cache": { @@ -1914,7 +1914,7 @@ "integrity": "sha1-KCBbVlqK51kt4gdGPWY33BgnIrI=", "dev": true, "requires": { - "nopt": "~2.1.1" + "nopt": "2.1.2" }, "dependencies": { "nopt": { @@ -1923,7 +1923,7 @@ "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", "dev": true, "requires": { - "abbrev": "1" + "abbrev": "1.0.9" } } } @@ -1970,7 +1970,7 @@ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "mime-db": "~1.30.0" + "mime-db": "1.30.0" } }, "minimatch": { @@ -1979,7 +1979,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.8" } }, "minimist": { @@ -2022,7 +2022,7 @@ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { - "graceful-readlink": ">= 1.0.0" + "graceful-readlink": "1.0.1" } }, "debug": { @@ -2040,12 +2040,12 @@ "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "ms": { @@ -2060,7 +2060,7 @@ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -2080,8 +2080,8 @@ "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz", "integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=", "requires": { - "bson": "~1.0.4", - "require_optional": "~1.0.0" + "bson": "1.0.4", + "require_optional": "1.0.1" } }, "mongodb-topology-manager": { @@ -2090,15 +2090,15 @@ "integrity": "sha1-GXDHRbhe36SAEQRaj+bQP2W1ofA=", "dev": true, "requires": { - "babel-core": "^6.10.4", - "babel-polyfill": "^6.9.1", - "bluebird": "^3.4.1", - "co": "^4.6.0", - "es6-promise": "^3.2.1", + "babel-core": "6.26.0", + "babel-polyfill": "6.26.0", + "bluebird": "3.5.0", + "co": "4.6.0", + "es6-promise": "3.2.1", "kerberos": "0.0.17", - "mkdirp": "^0.5.1", - "mongodb-core": "^1.2.24", - "rimraf": "^2.4.3" + "mkdirp": "0.5.1", + "mongodb-core": "1.3.21", + "rimraf": "2.6.2" }, "dependencies": { "bson": { @@ -2113,8 +2113,8 @@ "integrity": "sha1-/hKee+4rOybBQJ3gKrYNA/YpHMo=", "dev": true, "requires": { - "bson": "~0.4.23", - "require_optional": "~1.0.0" + "bson": "0.4.23", + "require_optional": "1.0.1" } } } @@ -2187,9 +2187,9 @@ "integrity": "sha1-kwgdg02b2dg3N3mN89o81TjokIo=", "dev": true, "requires": { - "colors": ">=0.6.0", - "mime": ">=1.2.9", - "optimist": ">=0.3.4" + "colors": "1.1.2", + "mime": "2.0.3", + "optimist": "0.6.1" } }, "nopt": { @@ -2198,7 +2198,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1" + "abbrev": "1.0.9" } }, "nsp": { @@ -2207,17 +2207,17 @@ "integrity": "sha512-jvjDg2Gsw4coD/iZ5eQddsDlkvnwMCNnpG05BproSnuG+Gr1bSQMwWMcQeYje+qdDl3XznmhblMPLpZLecTORQ==", "dev": true, "requires": { - "chalk": "^1.1.1", - "cli-table": "^0.3.1", - "cvss": "^1.0.0", - "https-proxy-agent": "^1.0.0", - "joi": "^6.9.1", - "nodesecurity-npm-utils": "^5.0.0", - "path-is-absolute": "^1.0.0", - "rc": "^1.1.2", - "semver": "^5.0.3", - "subcommand": "^2.0.3", - "wreck": "^6.3.0" + "chalk": "1.1.3", + "cli-table": "0.3.1", + "cvss": "1.0.2", + "https-proxy-agent": "1.0.0", + "joi": "6.10.1", + "nodesecurity-npm-utils": "5.0.0", + "path-is-absolute": "1.0.1", + "rc": "1.2.1", + "semver": "5.4.1", + "subcommand": "2.1.0", + "wreck": "6.3.0" }, "dependencies": { "agent-base": { @@ -2226,8 +2226,8 @@ "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", "dev": true, "requires": { - "extend": "~3.0.0", - "semver": "~5.0.1" + "extend": "3.0.1", + "semver": "5.0.3" }, "dependencies": { "semver": { @@ -2256,7 +2256,7 @@ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "2.x.x" + "hoek": "2.16.3" } }, "chalk": { @@ -2265,11 +2265,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "cli-table": { @@ -2332,7 +2332,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "hoek": { @@ -2347,9 +2347,9 @@ "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", "dev": true, "requires": { - "agent-base": "2", - "debug": "2", - "extend": "3" + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" } }, "ini": { @@ -2370,10 +2370,10 @@ "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", "dev": true, "requires": { - "hoek": "2.x.x", - "isemail": "1.x.x", - "moment": "2.x.x", - "topo": "1.x.x" + "hoek": "2.16.3", + "isemail": "1.2.0", + "moment": "2.18.1", + "topo": "1.1.0" } }, "minimist": { @@ -2412,10 +2412,10 @@ "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", "dev": true, "requires": { - "deep-extend": "~0.4.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" } }, "semver": { @@ -2430,7 +2430,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-json-comments": { @@ -2445,10 +2445,10 @@ "integrity": "sha1-XkzspaN3njNlsVEeBfhmh3MC92A=", "dev": true, "requires": { - "cliclopts": "^1.1.0", - "debug": "^2.1.3", - "minimist": "^1.2.0", - "xtend": "^4.0.0" + "cliclopts": "1.1.1", + "debug": "2.6.9", + "minimist": "1.2.0", + "xtend": "4.0.1" } }, "supports-color": { @@ -2463,7 +2463,7 @@ "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", "dev": true, "requires": { - "hoek": "2.x.x" + "hoek": "2.16.3" } }, "wreck": { @@ -2472,8 +2472,8 @@ "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", "dev": true, "requires": { - "boom": "2.x.x", - "hoek": "2.x.x" + "boom": "2.10.1", + "hoek": "2.16.3" } }, "xtend": { @@ -2517,7 +2517,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "onetime": { @@ -2532,8 +2532,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "minimist": "0.0.8", + "wordwrap": "0.0.3" }, "dependencies": { "wordwrap": { @@ -2550,12 +2550,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" } }, "os-homedir": { @@ -2618,7 +2618,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "^2.0.0" + "pinkie": "2.0.4" } }, "platform": { @@ -2639,11 +2639,11 @@ "integrity": "sha1-SC7gmKmHfoz6ciQshJm5PyBwnE4=", "dev": true, "requires": { - "define-properties": "^1.1.2", - "empower": "^1.1.0", - "power-assert-formatter": "^1.3.1", - "universal-deep-strict-equal": "^1.2.1", - "xtend": "^4.0.0" + "define-properties": "1.1.2", + "empower": "1.2.3", + "power-assert-formatter": "1.4.1", + "universal-deep-strict-equal": "1.2.2", + "xtend": "4.0.1" } }, "power-assert-context-formatter": { @@ -2652,8 +2652,8 @@ "integrity": "sha1-7bo1LT7YpgMRTWZyZazOYNaJzN8=", "dev": true, "requires": { - "core-js": "^2.0.0", - "power-assert-context-traversal": "^1.1.1" + "core-js": "2.5.1", + "power-assert-context-traversal": "1.1.1" } }, "power-assert-context-reducer-ast": { @@ -2662,11 +2662,11 @@ "integrity": "sha1-SEqZ4m9Jc/+IMuXFzHVnAuYJQXQ=", "dev": true, "requires": { - "acorn": "^4.0.0", - "acorn-es7-plugin": "^1.0.12", - "core-js": "^2.0.0", - "espurify": "^1.6.0", - "estraverse": "^4.2.0" + "acorn": "4.0.13", + "acorn-es7-plugin": "1.1.7", + "core-js": "2.5.1", + "espurify": "1.7.0", + "estraverse": "4.2.0" }, "dependencies": { "acorn": { @@ -2683,8 +2683,8 @@ "integrity": "sha1-iMq8oNE7Y1nwfT0+ivppkmRXftk=", "dev": true, "requires": { - "core-js": "^2.0.0", - "estraverse": "^4.1.0" + "core-js": "2.5.1", + "estraverse": "4.2.0" } }, "power-assert-formatter": { @@ -2693,13 +2693,13 @@ "integrity": "sha1-XcEl7VCj37HdomwZNH879Y7CiEo=", "dev": true, "requires": { - "core-js": "^2.0.0", - "power-assert-context-formatter": "^1.0.7", - "power-assert-context-reducer-ast": "^1.0.7", - "power-assert-renderer-assertion": "^1.0.7", - "power-assert-renderer-comparison": "^1.0.7", - "power-assert-renderer-diagram": "^1.0.7", - "power-assert-renderer-file": "^1.0.7" + "core-js": "2.5.1", + "power-assert-context-formatter": "1.1.1", + "power-assert-context-reducer-ast": "1.1.2", + "power-assert-renderer-assertion": "1.1.1", + "power-assert-renderer-comparison": "1.1.1", + "power-assert-renderer-diagram": "1.1.2", + "power-assert-renderer-file": "1.1.1" } }, "power-assert-renderer-assertion": { @@ -2708,8 +2708,8 @@ "integrity": "sha1-y/wOd+AIao+Wrz8djme57n4ozpg=", "dev": true, "requires": { - "power-assert-renderer-base": "^1.1.1", - "power-assert-util-string-width": "^1.1.1" + "power-assert-renderer-base": "1.1.1", + "power-assert-util-string-width": "1.1.1" } }, "power-assert-renderer-base": { @@ -2724,11 +2724,11 @@ "integrity": "sha1-10Odl9hRVr5OMKAPL7WnJRTOPAg=", "dev": true, "requires": { - "core-js": "^2.0.0", - "diff-match-patch": "^1.0.0", - "power-assert-renderer-base": "^1.1.1", - "stringifier": "^1.3.0", - "type-name": "^2.0.1" + "core-js": "2.5.1", + "diff-match-patch": "1.0.0", + "power-assert-renderer-base": "1.1.1", + "stringifier": "1.3.0", + "type-name": "2.0.2" } }, "power-assert-renderer-diagram": { @@ -2737,10 +2737,10 @@ "integrity": "sha1-ZV+PcRk1qbbVQbhjJ2VHF8Y3qYY=", "dev": true, "requires": { - "core-js": "^2.0.0", - "power-assert-renderer-base": "^1.1.1", - "power-assert-util-string-width": "^1.1.1", - "stringifier": "^1.3.0" + "core-js": "2.5.1", + "power-assert-renderer-base": "1.1.1", + "power-assert-util-string-width": "1.1.1", + "stringifier": "1.3.0" } }, "power-assert-renderer-file": { @@ -2749,7 +2749,7 @@ "integrity": "sha1-o34rvReMys0E5427eckv40kzxec=", "dev": true, "requires": { - "power-assert-renderer-base": "^1.1.1" + "power-assert-renderer-base": "1.1.1" } }, "power-assert-util-string-width": { @@ -2758,7 +2758,7 @@ "integrity": "sha1-vmWet5N/3S5smncmjar2S9W3xZI=", "dev": true, "requires": { - "eastasianwidth": "^0.1.1" + "eastasianwidth": "0.1.1" } }, "prelude-ls": { @@ -2790,7 +2790,7 @@ "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", "dev": true, "requires": { - "forwarded": "~0.1.2", + "forwarded": "0.1.2", "ipaddr.js": "1.5.2" } }, @@ -2829,13 +2829,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", "requires": { - "buffer-shims": "~1.0.0", - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~1.0.0", - "util-deprecate": "~1.0.1" + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "readline2": { @@ -2844,8 +2844,8 @@ "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", "mute-stream": "0.0.5" } }, @@ -2872,7 +2872,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "^1.0.0" + "is-finite": "1.0.2" } }, "require-uncached": { @@ -2881,8 +2881,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" + "caller-path": "0.1.0", + "resolve-from": "1.0.1" }, "dependencies": { "resolve-from": { @@ -2898,8 +2898,8 @@ "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", "requires": { - "resolve-from": "^2.0.0", - "semver": "^5.1.0" + "resolve-from": "2.0.0", + "semver": "5.4.1" } }, "requirejs": { @@ -2914,7 +2914,7 @@ "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "1.0.5" } }, "resolve-from": { @@ -2928,8 +2928,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "exit-hook": "1.1.1", + "onetime": "1.1.0" } }, "right-align": { @@ -2938,7 +2938,7 @@ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "^0.1.1" + "align-text": "0.1.4" } }, "rimraf": { @@ -2947,7 +2947,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" }, "dependencies": { "glob": { @@ -2956,12 +2956,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } } } @@ -2972,7 +2972,7 @@ "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", "dev": true, "requires": { - "once": "^1.3.0" + "once": "1.4.0" } }, "rx-lite": { @@ -2998,18 +2998,18 @@ "dev": true, "requires": { "debug": "2.6.9", - "depd": "~1.1.1", - "destroy": "~1.0.4", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "etag": "~1.8.1", + "depd": "1.1.1", + "destroy": "1.0.4", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.1", "fresh": "0.5.2", - "http-errors": "~1.6.2", + "http-errors": "1.6.2", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.3.1" + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" }, "dependencies": { "mime": { @@ -3026,9 +3026,9 @@ "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", "dev": true, "requires": { - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "parseurl": "1.3.2", "send": "0.16.1" } }, @@ -3074,7 +3074,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": ">=0.0.4" + "amdefine": "1.0.1" } }, "source-map-support": { @@ -3083,7 +3083,7 @@ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { - "source-map": "^0.5.6" + "source-map": "0.5.7" }, "dependencies": { "source-map": { @@ -3112,9 +3112,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "string_decoder": { @@ -3122,7 +3122,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } }, "stringifier": { @@ -3131,9 +3131,9 @@ "integrity": "sha1-3vGDQvaTPbDy2/yaoCF1tEjBeVk=", "dev": true, "requires": { - "core-js": "^2.0.0", - "traverse": "^0.6.6", - "type-name": "^2.0.1" + "core-js": "2.5.1", + "traverse": "0.6.6", + "type-name": "2.0.2" } }, "strip-ansi": { @@ -3142,7 +3142,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-json-comments": { @@ -3163,12 +3163,12 @@ "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", "dev": true, "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.10", "slice-ansi": "0.0.4", - "string-width": "^2.0.0" + "string-width": "2.1.1" }, "dependencies": { "ansi-regex": { @@ -3189,8 +3189,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" } }, "strip-ansi": { @@ -3199,7 +3199,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -3210,9 +3210,9 @@ "integrity": "sha1-btWic3ZPhu0mjJYeG9TVyk0N5tQ=", "dev": true, "requires": { - "express": ">=2.5.0", - "jade": ">=0.18.0", - "jasmine-node": ">=1.0.0" + "express": "4.16.1", + "jade": "0.26.3", + "jasmine-node": "1.14.5" } }, "text-table": { @@ -3257,7 +3257,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "1.1.2" } }, "type-is": { @@ -3267,7 +3267,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.15" + "mime-types": "2.1.17" } }, "type-name": { @@ -3288,10 +3288,10 @@ "integrity": "sha1-8CHji6LKdAhg9b1caVwqgXNF8Ow=", "dev": true, "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "async": "0.2.10", + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" }, "dependencies": { "async": { @@ -3326,9 +3326,9 @@ "integrity": "sha1-DaSsL3PP95JMgfpN4BjKViyisKc=", "dev": true, "requires": { - "array-filter": "^1.0.0", + "array-filter": "1.0.0", "indexof": "0.0.1", - "object-keys": "^1.0.0" + "object-keys": "1.0.11" } }, "unpipe": { @@ -3343,7 +3343,7 @@ "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", "dev": true, "requires": { - "os-homedir": "^1.0.0" + "os-homedir": "1.0.2" } }, "util-deprecate": { @@ -3393,7 +3393,7 @@ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "window-size": { @@ -3420,7 +3420,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "^0.5.1" + "mkdirp": "0.5.1" } }, "xtend": { @@ -3435,9 +3435,9 @@ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", "window-size": "0.1.0" } } diff --git a/package.json b/package.json index 67d86e5ef5b..8b37d63b100 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.18", + "version": "4.13.19", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 6a8b38144df41955b09a599635128f1c5a0cfdc2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Jan 2020 21:40:01 -0500 Subject: [PATCH 2233/2240] chore: add .config.js to gitignore and npmignore --- .gitignore | 2 ++ .npmignore | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index d9ae398e527..28577b8fb07 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ tools/31* docs/*.html test/files/main.js + +.config.js \ No newline at end of file diff --git a/.npmignore b/.npmignore index da4b657952c..c69c61dc1b7 100644 --- a/.npmignore +++ b/.npmignore @@ -19,3 +19,5 @@ tools/31* data/ test/files + +.config.js \ No newline at end of file From 803090d3e31d780b7b9533dda85791143929e1ba Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Jan 2020 21:40:55 -0500 Subject: [PATCH 2234/2240] fix(schema): make aliases handle mongoose-lean-virtuals Backport fix for #6069 and vkarpov15/mongoose-lean-virtuals#6 --- lib/schema.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index 5ed761ad677..ca4dc3c2d6a 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -143,16 +143,20 @@ function aliasFields(schema) { if (alias) { if ('string' === typeof alias && alias.length > 0) { - if (schema.aliases[alias]) + if (schema.aliases[alias]) { throw new Error('Duplicate alias, alias ' + alias + ' is used more than once'); - else + } else { schema.aliases[alias] = prop; + } schema .virtual(alias) .get((function(p) { return function() { - return this.get(p); + if (typeof this.get === 'function') { + return this.get(p); + } + return this[p]; }; })(prop)) .set((function(p) { From 0e65e6e8b472b927fa0fe16c142c735d65a4c05e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Jan 2020 21:42:21 -0500 Subject: [PATCH 2235/2240] chore: release 4.13.20 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index f53d01bcfb5..294b1e0ce5c 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +4.13.20 / 2020-01-07 +==================== + * fix(schema): make aliases handle mongoose-lean-virtuals #6069 + 4.13.19 / 2019-07-02 ==================== * fix(aggregate): make `setOptions()` work as advertised #7950 #6011 [cdimitroulas](https://github.com/cdimitroulas) diff --git a/package.json b/package.json index 8b37d63b100..82f996b592a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "4.13.19", + "version": "4.13.20", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 91f95dad75fc6d99630b9f492914e0399b85bf68 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Jan 2020 21:50:19 -0500 Subject: [PATCH 2236/2240] chore: run consistent mongod version in tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 25ffa13582c..6dc507e540b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ before_script: - mkdir -p ./data/db/27000 - printf "\n--timeout 8000" >> ./test/mocha.opts - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --dbpath ./data/db/27017 --syslog --port 27017 + - export PATH=`pwd`/mongodb-linux-x86_64-2.6.11/bin/:$PATH - sleep 3 script: - npm test From 4a55040465eeeecdc0e712a78cab975dba4f8c3f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Jan 2020 21:59:16 -0500 Subject: [PATCH 2237/2240] chore: remove problematic mongoose-long dep and use mongodb 3.4 in tests --- .travis.yml | 8 +- package-lock.json | 1954 ++++++++++++++++++------------------- package.json | 1 - test/model.update.test.js | 20 - 4 files changed, 936 insertions(+), 1047 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6dc507e540b..02eda0a1aeb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,13 +11,13 @@ node_js: - "0.10" - "iojs" before_script: - - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.11.tgz - - tar -zxvf mongodb-linux-x86_64-2.6.11.tgz + - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.23.tgz + - tar -zxvf mongodb-linux-x86_64-3.4.23.tgz - mkdir -p ./data/db/27017 - mkdir -p ./data/db/27000 - printf "\n--timeout 8000" >> ./test/mocha.opts - - ./mongodb-linux-x86_64-2.6.11/bin/mongod --fork --dbpath ./data/db/27017 --syslog --port 27017 - - export PATH=`pwd`/mongodb-linux-x86_64-2.6.11/bin/:$PATH + - ./mongodb-linux-x86_64-3.4.23/bin/mongod --fork --dbpath ./data/db/27017 --syslog --port 27017 + - export PATH=`pwd`/mongodb-linux-x86_64-3.4.23/bin/:$PATH - sleep 3 script: - npm test diff --git a/package-lock.json b/package-lock.json index e020a0a1130..26bd7546d2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mongoose", - "version": "4.13.19", + "version": "4.13.20", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -11,19 +11,19 @@ "dev": true }, "accepts": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "dev": true, "requires": { - "mime-types": "2.1.17", - "negotiator": "0.6.1" + "mime-types": "~2.1.24", + "negotiator": "0.6.2" } }, "acorn": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", - "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", "dev": true }, "acorn-es7-plugin": { @@ -38,7 +38,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "3.3.0" + "acorn": "^3.0.4" }, "dependencies": { "acorn": { @@ -81,8 +81,8 @@ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" } }, "ajv-keywords": { @@ -97,16 +97,17 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" } }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "dev": true, + "optional": true }, "ansi-escapes": { "version": "1.4.0", @@ -127,12 +128,12 @@ "dev": true }, "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "array-filter": { @@ -147,33 +148,19 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, "async": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", "requires": { - "lodash": "4.17.10" + "lodash": "^4.14.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + } } }, "babel-code-frame": { @@ -182,44 +169,38 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" } }, "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.0", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.7", - "slash": "1.0.0", - "source-map": "0.5.7" + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" }, "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -229,27 +210,21 @@ } }, "babel-generator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", - "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", - "dev": true, - "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.4", - "source-map": "0.5.7", - "trim-right": "1.0.1" + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" }, "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -264,8 +239,8 @@ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-messages": { @@ -274,7 +249,7 @@ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-polyfill": { @@ -283,9 +258,9 @@ "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "core-js": "2.5.1", - "regenerator-runtime": "0.10.5" + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" }, "dependencies": { "regenerator-runtime": { @@ -302,21 +277,13 @@ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "dev": true, "requires": { - "babel-core": "6.26.0", - "babel-runtime": "6.26.0", - "core-js": "2.5.1", - "home-or-tmp": "2.0.0", - "lodash": "4.17.4", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" } }, "babel-runtime": { @@ -325,8 +292,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.1", - "regenerator-runtime": "0.11.0" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-template": { @@ -335,19 +302,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.4" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" } }, "babel-traverse": { @@ -356,15 +315,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.4" + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" }, "dependencies": { "globals": { @@ -372,12 +331,6 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true } } }, @@ -387,18 +340,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.4", - "to-fast-properties": "1.0.3" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "babylon": { @@ -419,8 +364,8 @@ "integrity": "sha1-BnbYLlYNgtLzF/gs8IWEg5Vae/4=", "dev": true, "requires": { - "lodash": "4.17.10", - "platform": "1.3.4" + "lodash": "^4.16.4", + "platform": "^1.3.1" } }, "bluebird": { @@ -429,30 +374,30 @@ "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" }, "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, "requires": { - "bytes": "3.0.0", - "content-type": "1.0.4", + "bytes": "3.1.0", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.1", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "1.6.15" + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" } }, "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -463,9 +408,15 @@ "dev": true }, "bson": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", - "integrity": "sha1-k8ENOeqltYQVy8QFLz5T5WKwtyw=" + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", + "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true }, "buffer-shims": { "version": "1.0.0", @@ -473,9 +424,9 @@ "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, "call-signature": { @@ -490,7 +441,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "0.2.0" + "callsites": "^0.2.0" } }, "callsites": { @@ -511,8 +462,8 @@ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" } }, "chalk": { @@ -521,11 +472,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "circular-json": { @@ -540,7 +491,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "^1.0.1" } }, "cli-width": { @@ -555,8 +506,8 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", + "center-align": "^0.1.1", + "right-align": "^0.1.1", "wordwrap": "0.0.2" }, "dependencies": { @@ -580,16 +531,16 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, - "coffee-script": { + "coffeescript": { "version": "1.12.7", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", - "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.7.tgz", + "integrity": "sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA==", "dev": true }, "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true }, "commander": { @@ -605,21 +556,25 @@ "dev": true }, "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.2.7", - "typedarray": "0.0.6" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } }, "content-type": { "version": "1.0.4", @@ -628,15 +583,18 @@ "dev": true }, "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", - "dev": true + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } }, "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", "dev": true }, "cookie-signature": { @@ -646,9 +604,9 @@ "dev": true }, "core-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", "dev": true }, "core-util-is": { @@ -657,12 +615,13 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dev": true, "requires": { - "es5-ext": "0.10.30" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, "debug": { @@ -686,34 +645,18 @@ "dev": true }, "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" - } - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "object-keys": "^1.0.12" } }, "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "destroy": { @@ -728,7 +671,7 @@ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "diff": { @@ -738,9 +681,9 @@ "dev": true }, "diff-match-patch": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.0.tgz", - "integrity": "sha1-HMPIOkkNZ/ldkeOfatHy4Ia2MEg=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.4.tgz", + "integrity": "sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==", "dev": true }, "doctrine": { @@ -749,8 +692,8 @@ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, "dox": { @@ -760,7 +703,7 @@ "dev": true, "requires": { "commander": "0.6.1", - "github-flavored-markdown": "1.0.1" + "github-flavored-markdown": ">= 0.0.1" }, "dependencies": { "commander": { @@ -772,9 +715,9 @@ } }, "eastasianwidth": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.1.1.tgz", - "integrity": "sha1-RNZW3p2kFWlEZzNTZfsxR7hXK3w=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, "ee-first": { @@ -784,50 +727,51 @@ "dev": true }, "empower": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/empower/-/empower-1.2.3.tgz", - "integrity": "sha1-bw2nNEf07dg4/sXGAxOoi6XLhSs=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/empower/-/empower-1.3.1.tgz", + "integrity": "sha512-uB6/ViBaawOO/uujFADTK3SqdYlxYNn+N4usK9MRKZ4Hbn/1QSy8k2PezxCA2/+JGbF8vd/eOfghZ90oOSDZCA==", "dev": true, "requires": { - "core-js": "2.5.1", - "empower-core": "0.6.2" + "core-js": "^2.0.0", + "empower-core": "^1.2.0" } }, "empower-core": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-0.6.2.tgz", - "integrity": "sha1-Wt71ZgiOMfuoC6CjbfR9cJQWkUQ=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-1.2.0.tgz", + "integrity": "sha512-g6+K6Geyc1o6FdXs9HwrXleCFan7d66G5xSCfSF7x1mJDCes6t0om9lFQG3zOrzh3Bkb/45N0cZ5Gqsf7YrzGQ==", "dev": true, "requires": { "call-signature": "0.0.2", - "core-js": "2.5.1" + "core-js": "^2.0.0" } }, "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, "es5-ext": { - "version": "0.10.30", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", - "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=", + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "dev": true, "requires": { - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" } }, "es6-iterator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", - "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, "es6-map": { @@ -836,12 +780,12 @@ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30", - "es6-iterator": "2.0.1", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" } }, "es6-promise": { @@ -855,33 +799,45 @@ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30", - "es6-iterator": "2.0.1", + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } } }, "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30" + "d": "^1.0.1", + "ext": "^1.1.2" } }, "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30", - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" } }, "escape-html": { @@ -902,11 +858,11 @@ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" }, "dependencies": { "esprima": { @@ -929,10 +885,10 @@ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", "dev": true, "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, "eslint": { @@ -941,84 +897,83 @@ "integrity": "sha1-v7OO/Lf5mBiApyS8LmHSFAku46k=", "dev": true, "requires": { - "chalk": "1.1.3", - "concat-stream": "1.6.0", - "debug": "2.6.9", - "doctrine": "1.5.0", - "es6-map": "0.1.5", - "escope": "3.6.0", - "espree": "3.5.1", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "1.3.1", - "glob": "6.0.4", - "globals": "8.18.0", - "ignore": "2.2.19", - "inquirer": "0.12.0", - "is-my-json-valid": "2.16.1", - "is-resolvable": "1.0.0", - "js-yaml": "3.10.0", - "json-stable-stringify": "1.0.1", - "lodash": "4.17.10", - "mkdirp": "0.5.1", - "optionator": "0.8.2", - "path-is-absolute": "1.0.1", - "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", - "require-uncached": "1.0.3", - "resolve": "1.4.0", - "shelljs": "0.5.3", - "strip-json-comments": "1.0.4", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "chalk": "^1.0.0", + "concat-stream": "^1.4.6", + "debug": "^2.1.1", + "doctrine": "^1.2.0", + "es6-map": "^0.1.3", + "escope": "^3.6.0", + "espree": "^3.1.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^1.1.1", + "glob": "^6.0.4", + "globals": "^8.18.0", + "ignore": "^2.2.19", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "optionator": "^0.8.1", + "path-is-absolute": "^1.0.0", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "resolve": "^1.1.6", + "shelljs": "^0.5.3", + "strip-json-comments": "~1.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" } }, "espree": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz", - "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "5.1.2", - "acorn-jsx": "3.0.1" + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" } }, "esprima": { "version": "https://github.com/ariya/esprima/archive/85fc2f4b6ad109a86d80d9821f52b5b38d0105c0.tar.gz", - "integrity": "sha1-toewHi8U14sGe4o8gEfmmHLXdow=", + "integrity": "sha512-GyWe6YkK295gEHgCUfRdjb9BWkxWrf3zAB6AvUGhSmW4HLCOw0Zq6cY3eSKCQQk6kaimdNQFssPUY5t8cz2SdQ==", "dev": true }, "espurify": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.7.0.tgz", - "integrity": "sha1-HFz2y8zDLm9jk4C9T5kfq5up0iY=", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.8.1.tgz", + "integrity": "sha512-ZDko6eY/o+D/gHCWyHTU85mKDgYcS4FJj7S+YD6WIInm7GQ6AnOjmcL4+buFV/JOztVLELi/7MmuGU5NHta0Mg==", "dev": true, "requires": { - "core-js": "2.5.1" + "core-js": "^2.0.0" } }, "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "^4.1.0" } }, "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, "etag": { @@ -1033,8 +988,8 @@ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.30" + "d": "1", + "es5-ext": "~0.10.14" } }, "exit-hook": { @@ -1044,41 +999,58 @@ "dev": true }, "express": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.1.tgz", - "integrity": "sha512-STB7LZ4N0L+81FJHGla2oboUHTk4PaN1RsOkoRh9OSeEKylvF5hwKYVX1xCLFaCT7MD0BNG/gX2WFMLqY6EMBw==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "~1.3.7", "array-flatten": "1.1.1", - "body-parser": "1.18.2", - "content-disposition": "0.5.2", - "content-type": "1.0.4", - "cookie": "0.3.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.1", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", - "finalhandler": "1.1.0", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", - "qs": "6.5.1", - "range-parser": "1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.1", - "serve-static": "1.13.1", - "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } } }, "fast-levenshtein": { @@ -1093,8 +1065,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, "file-entry-cache": { @@ -1103,8 +1075,8 @@ "integrity": "sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=", "dev": true, "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" } }, "fileset": { @@ -1113,8 +1085,8 @@ "integrity": "sha1-WI74lzxmI7KnbfRlEFaWuWqsgGc=", "dev": true, "requires": { - "glob": "5.0.15", - "minimatch": "2.0.10" + "glob": "5.x", + "minimatch": "2.x" }, "dependencies": { "glob": { @@ -1123,11 +1095,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "minimatch": { @@ -1136,44 +1108,38 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.0.0" } } } }, "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" } }, "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", "dev": true, "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" } }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -1193,64 +1159,22 @@ "dev": true }, "gaze": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.3.4.tgz", - "integrity": "sha1-X5S92gr+U7xxCWm81vKCVI1gwnk=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", "dev": true, "requires": { - "fileset": "0.1.8", - "minimatch": "0.2.14" - }, - "dependencies": { - "fileset": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/fileset/-/fileset-0.1.8.tgz", - "integrity": "sha1-UGuRqTluqn4y+0KoQHfHoMc2t0E=", - "dev": true, - "requires": { - "glob": "3.2.11", - "minimatch": "0.2.14" - } - }, - "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimatch": "0.3.0" - }, - "dependencies": { - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } + "globule": "^1.0.0" } }, "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } }, "generate-object-property": { "version": "1.2.0", @@ -1258,7 +1182,7 @@ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, "requires": { - "is-property": "1.0.2" + "is-property": "^1.0.0" } }, "github-flavored-markdown": { @@ -1273,11 +1197,11 @@ "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "globals": { @@ -1286,40 +1210,37 @@ "integrity": "sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ=", "dev": true }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "globule": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.0.tgz", + "integrity": "sha512-YlD4kdMqRCQHrhVdonet4TdRtv1/sZKepvoxNT4Nrhrp5HI8XFfc8kFlGlBn2myBo80aGp8Eft259mbcUJhgSg==", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" }, "dependencies": { "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } } } }, "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, "graceful-readlink": { @@ -1335,30 +1256,39 @@ "dev": true }, "handlebars": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", - "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", + "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", "dev": true, "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.7.0" + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" }, "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "optional": true }, "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-js": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.4.tgz", + "integrity": "sha512-tinYWE8X1QfCHxS1lBS8yiDekyhSXOO6R66yNOCdUJeojxxw+PX2BHAz/BWyW7PQ7pkiWVxJfIEbiDxyLWvUGg==", "dev": true, + "optional": true, "requires": { - "amdefine": "1.0.1" + "commander": "~2.20.3", + "source-map": "~0.6.1" } } } @@ -1369,7 +1299,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-flag": { @@ -1390,8 +1320,8 @@ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" } }, "hooks-fixed": { @@ -1400,30 +1330,34 @@ "integrity": "sha512-YurCM4gQSetcrhwEtpQHhQ4M7Zo7poNGqY4kQGeBS6eZtOcT3tnNs01ThFa0jYBByAiYt1MjMjP/YApG0EnAvQ==" }, "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { - "depd": "1.1.1", + "depd": "~1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.3.1" + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" }, "dependencies": { - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true } } }, "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ignore": { "version": "2.2.19", @@ -1443,14 +1377,14 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "inquirer": { "version": "0.12.0", @@ -1458,40 +1392,40 @@ "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "2.2.0", - "figures": "1.7.0", - "lodash": "4.17.10", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" } }, "invariant": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { - "loose-envify": "1.3.1" + "loose-envify": "^1.0.0" } }, "ipaddr.js": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", - "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", "dev": true }, "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-finite": { @@ -1500,7 +1434,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-fullwidth-code-point": { @@ -1509,43 +1443,26 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, - "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, - "is-path-cwd": { + "is-my-ip-valid": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", "dev": true }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, - "requires": { - "is-path-inside": "1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "is-my-json-valid": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", + "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" } }, "is-property": { @@ -1555,13 +1472,10 @@ "dev": true }, "is-resolvable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "dev": true, - "requires": { - "tryit": "1.0.3" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true }, "isarray": { "version": "1.0.0", @@ -1580,20 +1494,20 @@ "integrity": "sha1-6M9xjf7bcTyDNKuf+t418QQtKlY=", "dev": true, "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "fileset": "0.2.1", - "handlebars": "4.0.10", - "js-yaml": "3.10.0", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "once": "1.4.0", - "resolve": "1.1.7", - "supports-color": "3.2.3", - "which": "1.3.0", - "wordwrap": "1.0.0" + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "fileset": "0.2.x", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" }, "dependencies": { "async": { @@ -1620,7 +1534,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -1650,36 +1564,36 @@ } }, "jasmine-growl-reporter": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/jasmine-growl-reporter/-/jasmine-growl-reporter-0.0.3.tgz", - "integrity": "sha1-uHrlUeNZ0orVIXdl6u9sB7dj9sg=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jasmine-growl-reporter/-/jasmine-growl-reporter-2.0.0.tgz", + "integrity": "sha512-RYwVfPaGgxQQSHDOt6jQ99/KAkFQ/Fiwg/AzBS+uO9A4UhGhxb7hwXaUUSU/Zs0MxBoFNqmIRC+7P4/+5O3lXg==", "dev": true, "requires": { - "growl": "1.7.0" + "growl": "^1.10.5" }, "dependencies": { "growl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz", - "integrity": "sha1-3i1mE20ALhErpw8/EMMc98NQsto=", + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true } } }, "jasmine-node": { - "version": "1.14.5", - "resolved": "https://registry.npmjs.org/jasmine-node/-/jasmine-node-1.14.5.tgz", - "integrity": "sha1-GOg5e4VpJO53ADZmw3MbWupQw50=", - "dev": true, - "requires": { - "coffee-script": "1.12.7", - "gaze": "0.3.4", - "jasmine-growl-reporter": "0.0.3", - "jasmine-reporters": "1.0.2", - "mkdirp": "0.3.5", - "requirejs": "2.3.5", - "underscore": "1.5.2", - "walkdir": "0.0.12" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jasmine-node/-/jasmine-node-3.0.0.tgz", + "integrity": "sha512-vUa5Q7bQYwHHqi6FlJYndiKqZp+d+c3MKe0QUMwwrC4JRmoRV3zkg0buxB/uQ6qLh0NO34TNstpAnvaZ6xGlAA==", + "dev": true, + "requires": { + "coffeescript": "~1.12.7", + "gaze": "~1.1.2", + "jasmine-growl-reporter": "~2.0.0", + "jasmine-reporters": "~1.0.0", + "mkdirp": "~0.3.5", + "requirejs": "~2.3.6", + "underscore": "~1.9.1", + "walkdir": "~0.0.12" }, "dependencies": { "mkdirp": { @@ -1687,6 +1601,12 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true + }, + "underscore": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz", + "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==", + "dev": true } } }, @@ -1696,7 +1616,7 @@ "integrity": "sha1-q2E+1Zd9x0h+hbPBL2qOqNsq3jE=", "dev": true, "requires": { - "mkdirp": "0.3.5" + "mkdirp": "~0.3.5" }, "dependencies": { "mkdirp": { @@ -1714,19 +1634,19 @@ "dev": true }, "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, "dependencies": { "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true } } @@ -1743,7 +1663,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json3": { @@ -1781,7 +1701,7 @@ "integrity": "sha1-KaZ8CxJ7+lK907U7e4yGWamghPg=", "dev": true, "requires": { - "nan": "2.0.9" + "nan": "~2.0" } }, "kind-of": { @@ -1790,7 +1710,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" } }, "lazy-cache": { @@ -1805,14 +1725,15 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "lodash": { "version": "4.17.10", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true }, "lodash._baseassign": { "version": "3.2.0", @@ -1820,8 +1741,8 @@ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" } }, "lodash._basecopy": { @@ -1854,9 +1775,9 @@ "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", "dev": true, "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" } }, "lodash.get": { @@ -1882,9 +1803,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" } }, "longest": { @@ -1894,27 +1815,21 @@ "dev": true }, "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "requires": { - "js-tokens": "3.0.2" + "js-tokens": "^3.0.0 || ^4.0.0" } }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, "markdown": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/markdown/-/markdown-0.5.0.tgz", "integrity": "sha1-KCBbVlqK51kt4gdGPWY33BgnIrI=", "dev": true, "requires": { - "nopt": "2.1.2" + "nopt": "~2.1.1" }, "dependencies": { "nopt": { @@ -1923,7 +1838,7 @@ "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", "dev": true, "requires": { - "abbrev": "1.0.9" + "abbrev": "1" } } } @@ -1953,24 +1868,24 @@ "dev": true }, "mime": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-TrpAd/vX3xaLPDgVRm6JkZwLR0KHfukMdU2wTEbqMDdCnY6Yo3mE+mjs9YE6oMNw2QRfXVeBEYpmpO94BIqiug==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", "dev": true }, "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "dev": true, "requires": { - "mime-db": "1.30.0" + "mime-db": "1.43.0" } }, "minimatch": { @@ -1979,7 +1894,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -2022,7 +1937,7 @@ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { - "graceful-readlink": "1.0.1" + "graceful-readlink": ">= 1.0.0" } }, "debug": { @@ -2040,12 +1955,12 @@ "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "ms": { @@ -2060,7 +1975,7 @@ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -2080,8 +1995,8 @@ "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz", "integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=", "requires": { - "bson": "1.0.4", - "require_optional": "1.0.1" + "bson": "~1.0.4", + "require_optional": "~1.0.0" } }, "mongodb-topology-manager": { @@ -2090,15 +2005,15 @@ "integrity": "sha1-GXDHRbhe36SAEQRaj+bQP2W1ofA=", "dev": true, "requires": { - "babel-core": "6.26.0", - "babel-polyfill": "6.26.0", - "bluebird": "3.5.0", - "co": "4.6.0", - "es6-promise": "3.2.1", + "babel-core": "^6.10.4", + "babel-polyfill": "^6.9.1", + "bluebird": "^3.4.1", + "co": "^4.6.0", + "es6-promise": "^3.2.1", "kerberos": "0.0.17", - "mkdirp": "0.5.1", - "mongodb-core": "1.3.21", - "rimraf": "2.6.2" + "mkdirp": "^0.5.1", + "mongodb-core": "^1.2.24", + "rimraf": "^2.4.3" }, "dependencies": { "bson": { @@ -2113,18 +2028,12 @@ "integrity": "sha1-/hKee+4rOybBQJ3gKrYNA/YpHMo=", "dev": true, "requires": { - "bson": "0.4.23", - "require_optional": "1.0.1" + "bson": "~0.4.23", + "require_optional": "~1.0.0" } } } }, - "mongoose-long": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/mongoose-long/-/mongoose-long-0.1.1.tgz", - "integrity": "sha1-zDLgWwz1DIXiWhk1nUOpNv6VBaM=", - "dev": true - }, "mpath": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.1.tgz", @@ -2176,9 +2085,21 @@ "dev": true }, "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, "node-static": { @@ -2187,9 +2108,9 @@ "integrity": "sha1-kwgdg02b2dg3N3mN89o81TjokIo=", "dev": true, "requires": { - "colors": "1.1.2", - "mime": "2.0.3", - "optimist": "0.6.1" + "colors": ">=0.6.0", + "mime": ">=1.2.9", + "optimist": ">=0.3.4" } }, "nopt": { @@ -2198,7 +2119,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1.0.9" + "abbrev": "1" } }, "nsp": { @@ -2207,17 +2128,17 @@ "integrity": "sha512-jvjDg2Gsw4coD/iZ5eQddsDlkvnwMCNnpG05BproSnuG+Gr1bSQMwWMcQeYje+qdDl3XznmhblMPLpZLecTORQ==", "dev": true, "requires": { - "chalk": "1.1.3", - "cli-table": "0.3.1", - "cvss": "1.0.2", - "https-proxy-agent": "1.0.0", - "joi": "6.10.1", - "nodesecurity-npm-utils": "5.0.0", - "path-is-absolute": "1.0.1", - "rc": "1.2.1", - "semver": "5.4.1", - "subcommand": "2.1.0", - "wreck": "6.3.0" + "chalk": "^1.1.1", + "cli-table": "^0.3.1", + "cvss": "^1.0.0", + "https-proxy-agent": "^1.0.0", + "joi": "^6.9.1", + "nodesecurity-npm-utils": "^5.0.0", + "path-is-absolute": "^1.0.0", + "rc": "^1.1.2", + "semver": "^5.0.3", + "subcommand": "^2.0.3", + "wreck": "^6.3.0" }, "dependencies": { "agent-base": { @@ -2226,8 +2147,8 @@ "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", "dev": true, "requires": { - "extend": "3.0.1", - "semver": "5.0.3" + "extend": "~3.0.0", + "semver": "~5.0.1" }, "dependencies": { "semver": { @@ -2256,7 +2177,7 @@ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "chalk": { @@ -2265,11 +2186,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "cli-table": { @@ -2332,7 +2253,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "hoek": { @@ -2347,9 +2268,9 @@ "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", "dev": true, "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" + "agent-base": "2", + "debug": "2", + "extend": "3" } }, "ini": { @@ -2370,10 +2291,10 @@ "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", "dev": true, "requires": { - "hoek": "2.16.3", - "isemail": "1.2.0", - "moment": "2.18.1", - "topo": "1.1.0" + "hoek": "2.x.x", + "isemail": "1.x.x", + "moment": "2.x.x", + "topo": "1.x.x" } }, "minimist": { @@ -2412,10 +2333,10 @@ "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", "dev": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" } }, "semver": { @@ -2430,7 +2351,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -2445,10 +2366,10 @@ "integrity": "sha1-XkzspaN3njNlsVEeBfhmh3MC92A=", "dev": true, "requires": { - "cliclopts": "1.1.1", - "debug": "2.6.9", - "minimist": "1.2.0", - "xtend": "4.0.1" + "cliclopts": "^1.1.0", + "debug": "^2.1.3", + "minimist": "^1.2.0", + "xtend": "^4.0.0" } }, "supports-color": { @@ -2463,7 +2384,7 @@ "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "wreck": { @@ -2472,8 +2393,8 @@ "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", "dev": true, "requires": { - "boom": "2.10.1", - "hoek": "2.16.3" + "boom": "2.x.x", + "hoek": "2.x.x" } }, "xtend": { @@ -2497,9 +2418,9 @@ "dev": true }, "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, "on-finished": { @@ -2517,7 +2438,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -2532,8 +2453,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" }, "dependencies": { "wordwrap": { @@ -2545,17 +2466,17 @@ } }, "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" } }, "os-homedir": { @@ -2571,9 +2492,9 @@ "dev": true }, "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, "path-is-absolute": { @@ -2589,9 +2510,9 @@ "dev": true }, "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-to-regexp": { @@ -2600,31 +2521,10 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", "dev": true }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, "platform": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.4.tgz", - "integrity": "sha1-bw+xftqqSPIUQrOpdcBjEw8cPr0=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", + "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==", "dev": true }, "pluralize": { @@ -2639,52 +2539,44 @@ "integrity": "sha1-SC7gmKmHfoz6ciQshJm5PyBwnE4=", "dev": true, "requires": { - "define-properties": "1.1.2", - "empower": "1.2.3", - "power-assert-formatter": "1.4.1", - "universal-deep-strict-equal": "1.2.2", - "xtend": "4.0.1" + "define-properties": "^1.1.2", + "empower": "^1.1.0", + "power-assert-formatter": "^1.3.1", + "universal-deep-strict-equal": "^1.2.1", + "xtend": "^4.0.0" } }, "power-assert-context-formatter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-context-formatter/-/power-assert-context-formatter-1.1.1.tgz", - "integrity": "sha1-7bo1LT7YpgMRTWZyZazOYNaJzN8=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-context-formatter/-/power-assert-context-formatter-1.2.0.tgz", + "integrity": "sha512-HLNEW8Bin+BFCpk/zbyKwkEu9W8/zThIStxGo7weYcFkKgMuGCHUJhvJeBGXDZf0Qm2xis4pbnnciGZiX0EpSg==", "dev": true, "requires": { - "core-js": "2.5.1", - "power-assert-context-traversal": "1.1.1" + "core-js": "^2.0.0", + "power-assert-context-traversal": "^1.2.0" } }, "power-assert-context-reducer-ast": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.1.2.tgz", - "integrity": "sha1-SEqZ4m9Jc/+IMuXFzHVnAuYJQXQ=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.2.0.tgz", + "integrity": "sha512-EgOxmZ/Lb7tw4EwSKX7ZnfC0P/qRZFEG28dx/690qvhmOJ6hgThYFm5TUWANDLK5NiNKlPBi5WekVGd2+5wPrw==", "dev": true, "requires": { - "acorn": "4.0.13", - "acorn-es7-plugin": "1.1.7", - "core-js": "2.5.1", - "espurify": "1.7.0", - "estraverse": "4.2.0" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - } + "acorn": "^5.0.0", + "acorn-es7-plugin": "^1.0.12", + "core-js": "^2.0.0", + "espurify": "^1.6.0", + "estraverse": "^4.2.0" } }, "power-assert-context-traversal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-context-traversal/-/power-assert-context-traversal-1.1.1.tgz", - "integrity": "sha1-iMq8oNE7Y1nwfT0+ivppkmRXftk=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-context-traversal/-/power-assert-context-traversal-1.2.0.tgz", + "integrity": "sha512-NFoHU6g2umNajiP2l4qb0BRWD773Aw9uWdWYH9EQsVwIZnog5bd2YYLFCVvaxWpwNzWeEfZIon2xtyc63026pQ==", "dev": true, "requires": { - "core-js": "2.5.1", - "estraverse": "4.2.0" + "core-js": "^2.0.0", + "estraverse": "^4.1.0" } }, "power-assert-formatter": { @@ -2693,23 +2585,23 @@ "integrity": "sha1-XcEl7VCj37HdomwZNH879Y7CiEo=", "dev": true, "requires": { - "core-js": "2.5.1", - "power-assert-context-formatter": "1.1.1", - "power-assert-context-reducer-ast": "1.1.2", - "power-assert-renderer-assertion": "1.1.1", - "power-assert-renderer-comparison": "1.1.1", - "power-assert-renderer-diagram": "1.1.2", - "power-assert-renderer-file": "1.1.1" + "core-js": "^2.0.0", + "power-assert-context-formatter": "^1.0.7", + "power-assert-context-reducer-ast": "^1.0.7", + "power-assert-renderer-assertion": "^1.0.7", + "power-assert-renderer-comparison": "^1.0.7", + "power-assert-renderer-diagram": "^1.0.7", + "power-assert-renderer-file": "^1.0.7" } }, "power-assert-renderer-assertion": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.1.1.tgz", - "integrity": "sha1-y/wOd+AIao+Wrz8djme57n4ozpg=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.2.0.tgz", + "integrity": "sha512-3F7Q1ZLmV2ZCQv7aV7NJLNK9G7QsostrhOU7U0RhEQS/0vhEqrRg2jEJl1jtUL4ZyL2dXUlaaqrmPv5r9kRvIg==", "dev": true, "requires": { - "power-assert-renderer-base": "1.1.1", - "power-assert-util-string-width": "1.1.1" + "power-assert-renderer-base": "^1.1.1", + "power-assert-util-string-width": "^1.2.0" } }, "power-assert-renderer-base": { @@ -2719,46 +2611,46 @@ "dev": true }, "power-assert-renderer-comparison": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.1.1.tgz", - "integrity": "sha1-10Odl9hRVr5OMKAPL7WnJRTOPAg=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.2.0.tgz", + "integrity": "sha512-7c3RKPDBKK4E3JqdPtYRE9cM8AyX4LC4yfTvvTYyx8zSqmT5kJnXwzR0yWQLOavACllZfwrAGQzFiXPc5sWa+g==", "dev": true, "requires": { - "core-js": "2.5.1", - "diff-match-patch": "1.0.0", - "power-assert-renderer-base": "1.1.1", - "stringifier": "1.3.0", - "type-name": "2.0.2" + "core-js": "^2.0.0", + "diff-match-patch": "^1.0.0", + "power-assert-renderer-base": "^1.1.1", + "stringifier": "^1.3.0", + "type-name": "^2.0.1" } }, "power-assert-renderer-diagram": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.1.2.tgz", - "integrity": "sha1-ZV+PcRk1qbbVQbhjJ2VHF8Y3qYY=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.2.0.tgz", + "integrity": "sha512-JZ6PC+DJPQqfU6dwSmpcoD7gNnb/5U77bU5KgNwPPa+i1Pxiz6UuDeM3EUBlhZ1HvH9tMjI60anqVyi5l2oNdg==", "dev": true, "requires": { - "core-js": "2.5.1", - "power-assert-renderer-base": "1.1.1", - "power-assert-util-string-width": "1.1.1", - "stringifier": "1.3.0" + "core-js": "^2.0.0", + "power-assert-renderer-base": "^1.1.1", + "power-assert-util-string-width": "^1.2.0", + "stringifier": "^1.3.0" } }, "power-assert-renderer-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-renderer-file/-/power-assert-renderer-file-1.1.1.tgz", - "integrity": "sha1-o34rvReMys0E5427eckv40kzxec=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-renderer-file/-/power-assert-renderer-file-1.2.0.tgz", + "integrity": "sha512-/oaVrRbeOtGoyyd7e4IdLP/jIIUFJdqJtsYzP9/88R39CMnfF/S/rUc8ZQalENfUfQ/wQHu+XZYRMaCEZmEesg==", "dev": true, "requires": { - "power-assert-renderer-base": "1.1.1" + "power-assert-renderer-base": "^1.1.1" } }, "power-assert-util-string-width": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-util-string-width/-/power-assert-util-string-width-1.1.1.tgz", - "integrity": "sha1-vmWet5N/3S5smncmjar2S9W3xZI=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-util-string-width/-/power-assert-util-string-width-1.2.0.tgz", + "integrity": "sha512-lX90G0igAW0iyORTILZ/QjZWsa1MZ6VVY3L0K86e2eKun3S4LKPH4xZIl8fdeMYLfOjkaszbNSzf1uugLeAm2A==", "dev": true, "requires": { - "eastasianwidth": "0.1.1" + "eastasianwidth": "^0.2.0" } }, "prelude-ls": { @@ -2768,9 +2660,9 @@ "dev": true }, "private": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", - "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, "process-nextick-args": { @@ -2785,13 +2677,13 @@ "dev": true }, "proxy-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", - "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", "dev": true, "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.5.2" + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" } }, "q": { @@ -2801,26 +2693,26 @@ "dev": true }, "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", "dev": true }, "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true }, "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, @@ -2829,13 +2721,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" } }, "readline2": { @@ -2844,15 +2736,15 @@ "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", "mute-stream": "0.0.5" } }, "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, "regexp-clone": { @@ -2872,7 +2764,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "^1.0.0" } }, "require-uncached": { @@ -2881,8 +2773,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" }, "dependencies": { "resolve-from": { @@ -2898,23 +2790,23 @@ "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", "requires": { - "resolve-from": "2.0.0", - "semver": "5.4.1" + "resolve-from": "^2.0.0", + "semver": "^5.1.0" } }, "requirejs": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", - "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", + "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", "dev": true }, "resolve": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.2.tgz", + "integrity": "sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ==", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.6" } }, "resolve-from": { @@ -2928,8 +2820,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" } }, "right-align": { @@ -2938,30 +2830,30 @@ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "0.1.4" + "align-text": "^0.1.1" } }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.1.3" }, "dependencies": { "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } } } @@ -2972,7 +2864,7 @@ "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.3.0" } }, "rx-lite": { @@ -2982,60 +2874,72 @@ "dev": true }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, "send": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", - "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.1", - "destroy": "1.0.4", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.3.1" + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" }, "dependencies": { "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } }, "serve-static": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", - "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, "requires": { - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.16.1" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" } }, "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true }, "shelljs": { @@ -3044,12 +2948,6 @@ "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=", "dev": true }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -3074,7 +2972,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } }, "source-map-support": { @@ -3083,7 +2981,7 @@ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.5.6" }, "dependencies": { "source-map": { @@ -3101,9 +2999,9 @@ "dev": true }, "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, "string-width": { @@ -3112,9 +3010,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -3122,18 +3020,18 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "stringifier": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz", - "integrity": "sha1-3vGDQvaTPbDy2/yaoCF1tEjBeVk=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.4.0.tgz", + "integrity": "sha512-cNsMOqqrcbLcHTXEVmkw9y0fwDwkdgtZwlfyolzpQDoAE1xdNGhQhxBUfiDvvZIKl1hnUEgMv66nHwtMz3OjPw==", "dev": true, "requires": { - "core-js": "2.5.1", - "traverse": "0.6.6", - "type-name": "2.0.2" + "core-js": "^2.0.0", + "traverse": "^0.6.6", + "type-name": "^2.0.1" } }, "strip-ansi": { @@ -3142,7 +3040,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -3163,12 +3061,12 @@ "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.10", + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", "slice-ansi": "0.0.4", - "string-width": "2.1.1" + "string-width": "^2.0.0" }, "dependencies": { "ansi-regex": { @@ -3189,8 +3087,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -3199,7 +3097,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -3210,9 +3108,9 @@ "integrity": "sha1-btWic3ZPhu0mjJYeG9TVyk0N5tQ=", "dev": true, "requires": { - "express": "4.16.1", - "jade": "0.26.3", - "jasmine-node": "1.14.5" + "express": ">=2.5.0", + "jade": ">=0.18.0", + "jasmine-node": ">=1.0.0" } }, "text-table": { @@ -3233,6 +3131,12 @@ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, "traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", @@ -3245,10 +3149,10 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", "dev": true }, "type-check": { @@ -3257,17 +3161,17 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-is": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.17" + "mime-types": "~2.1.24" } }, "type-name": { @@ -3288,10 +3192,10 @@ "integrity": "sha1-8CHji6LKdAhg9b1caVwqgXNF8Ow=", "dev": true, "requires": { - "async": "0.2.10", - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" }, "dependencies": { "async": { @@ -3326,9 +3230,9 @@ "integrity": "sha1-DaSsL3PP95JMgfpN4BjKViyisKc=", "dev": true, "requires": { - "array-filter": "1.0.0", + "array-filter": "^1.0.0", "indexof": "0.0.1", - "object-keys": "1.0.11" + "object-keys": "^1.0.0" } }, "unpipe": { @@ -3343,7 +3247,7 @@ "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.0" } }, "util-deprecate": { @@ -3388,12 +3292,12 @@ "dev": true }, "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "window-size": { @@ -3402,6 +3306,12 @@ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -3420,13 +3330,13 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" } }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "yargs": { @@ -3435,9 +3345,9 @@ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", "window-size": "0.1.0" } } diff --git a/package.json b/package.json index 82f996b592a..006b5373612 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ "markdown": "0.5.0", "marked": "0.3.9", "mocha": "3.2.0", - "mongoose-long": "0.1.1", "mongodb-topology-manager": "1.0.11", "node-static": "0.7.7", "nsp": "~2.8.1", diff --git a/test/model.update.test.js b/test/model.update.test.js index a6a6fbd98b9..6da4b84f218 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2230,26 +2230,6 @@ describe('model: update:', function() { }); }); - it('update handles casting with mongoose-long (gh-4283)', function(done) { - require('mongoose-long')(mongoose); - - var Model = db.model('gh4283', { - number: { type: mongoose.Types.Long } - }); - - Model.create({ number: mongoose.mongo.Long.fromString('0') }, function(error) { - assert.ifError(error); - Model.update({}, { $inc: { number: mongoose.mongo.Long.fromString('2147483648') } }, function(error) { - assert.ifError(error); - Model.findOne({ number: { $type: 18 } }, function(error, doc) { - assert.ifError(error); - assert.ok(doc); - done(); - }); - }); - }); - }); - it('single nested with runValidators (gh-4420)', function(done) { var FileSchema = new Schema({ name: String From 8fa801277bc5c8d627c4af0dd4301d43e911a7af Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Jan 2020 22:25:40 -0500 Subject: [PATCH 2238/2240] test: test cleanup re: #8459 --- test/schema.alias.test.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/schema.alias.test.js b/test/schema.alias.test.js index a47bc44a018..75244842287 100644 --- a/test/schema.alias.test.js +++ b/test/schema.alias.test.js @@ -9,7 +9,7 @@ var start = require('./common'), Schema = mongoose.Schema; describe('schema alias option', function() { - it('works with all basic schema types', function() { + it('works with all basic schema types', function(done) { var db = start(); var schema = new Schema({ @@ -45,10 +45,11 @@ describe('schema alias option', function() { assert.equal(s.mixed, s.MixedAlias); assert.equal(s.objectId, s.ObjectIdAlias); assert.equal(s.array, s.ArrayAlias); + done(); }); }); - it('works with nested schema types', function() { + it('works with nested schema types', function(done) { var db = start(); var schema = new Schema({ @@ -92,6 +93,8 @@ describe('schema alias option', function() { assert.equal(s.nested.mixed, s.MixedAlias); assert.equal(s.nested.objectId, s.ObjectIdAlias); assert.equal(s.nested.array, s.ArrayAlias); + + done(); }); }); From 1db031cfa0f64e2eda8f4e428c530ea6dc201cd1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 7 Jan 2020 22:32:57 -0500 Subject: [PATCH 2239/2240] test(schema): clean up messy tests re: #8459 --- test/schema.alias.test.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/test/schema.alias.test.js b/test/schema.alias.test.js index 75244842287..c2d7184d838 100644 --- a/test/schema.alias.test.js +++ b/test/schema.alias.test.js @@ -54,17 +54,14 @@ describe('schema alias option', function() { var schema = new Schema({ nested: { - type: { - string: { type: String, alias: 'StringAlias' }, - number: { type: Number, alias: 'NumberAlias' }, - date: { type: Date, alias: 'DateAlias' }, - buffer: { type: Buffer, alias: 'BufferAlias' }, - boolean: { type: Boolean, alias: 'BooleanAlias' }, - mixed: { type: Schema.Types.Mixed, alias: 'MixedAlias' }, - objectId: { type: Schema.Types.ObjectId, alias: 'ObjectIdAlias'}, - array: { type: [], alias: 'ArrayAlias' } - }, - alias: 'NestedAlias' + string: { type: String, alias: 'StringAlias' }, + number: { type: Number, alias: 'NumberAlias' }, + date: { type: Date, alias: 'DateAlias' }, + buffer: { type: Buffer, alias: 'BufferAlias' }, + boolean: { type: Boolean, alias: 'BooleanAlias' }, + mixed: { type: Schema.Types.Mixed, alias: 'MixedAlias' }, + objectId: { type: Schema.Types.ObjectId, alias: 'ObjectIdAlias'}, + array: { type: [], alias: 'ArrayAlias' } } }); @@ -84,7 +81,6 @@ describe('schema alias option', function() { assert.ifError(err); // Comparing with aliases - assert.equal(s.nested, s.NestedAlias); assert.equal(s.nested.string, s.StringAlias); assert.equal(s.nested.number, s.NumberAlias); assert.equal(s.nested.date, s.DateAlias); From f88eb2524b65a68ff893c90a03c04f0913c1913e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 12 Jul 2020 13:53:04 -0400 Subject: [PATCH 2240/2240] fix(query): delete top-level `_bsontype` property in queries to prevent silent empty queries Backport fix for #8222 Fix #8241 --- lib/cast.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/cast.js b/lib/cast.js index 7f475edfeb4..339c031f14d 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -23,6 +23,12 @@ module.exports = function cast(schema, obj, options, context) { throw new Error('Query filter must be an object, got an array ', util.inspect(obj)); } + // bson 1.x has the unfortunate tendency to remove filters that have a top-level + // `_bsontype` property. Should remove this when we upgrade to bson 4.x. See gh-8222 + if (obj.hasOwnProperty('_bsontype')) { + delete obj._bsontype; + } + var paths = Object.keys(obj); var i = paths.length; var _keys;

    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 Hu0mjfzLskk literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/square_bg.png b/docs/3.5.x/docs/images/square_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca GIT binary patch literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.5.9Fork me on GitHub

    kEHs_LGe?wKJuGaPCdM8l?nCCj!TI01$Q7!ES* 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 literal 0 HcmV?d00001 diff --git a/docs/3.5.x/docs/images/apps/mybrickbuilds.png b/docs/3.5.x/docs/images/apps/mybrickbuilds.png new file mode 100644 index 0000000000000000000000000000000000000000..4d9f560b3ba67f9d13afb5f77b71a2fe0d14e4c4 GIT binary patch literal 42263 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

  • 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 Hu0mjfzLskk literal 0 HcmV?d00001 diff --git a/docs/3.4.x/docs/images/square_bg.png b/docs/3.4.x/docs/images/square_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca GIT binary patch literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.4.0Fork me on GitHub

  • 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 Hu0mjfzLskk literal 0 HcmV?d00001 diff --git a/docs/3.3.x/docs/images/square_bg.png b/docs/3.3.x/docs/images/square_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..f2028ea10b69918713d8fbc5b6c3fe6f0ae70eca GIT binary patch literal 2217 zcma)83rrJt7_XBdLn=hKI0U=1I=93=?pm<)Mn&2}MX6$8iZAr&UCRyHtL;Hs+)!X4 zX(l7{u?ayPi8zeTM^HCJ29>G-pEFL>p**612n=LUl-BJErTAjANqhJI=lA`-@B96} zFR3MNxs2{R%a=x@(PNfK71Yx~ecODzso%b~jw0$2NJb@+@q~&rB6^G#i4w^e5TilV zm;ysk^X57%oJO16f+r-BiSk%jNoY8T3&SyKbW}8r79L^JA<9&Y1d=f|t`#x=s;p)L zI4WYU4wZv)odiq4mt^X(_{`-A%FI-y5M@Rz0>Vu&MWDe*1TbmRv7AqbgV-jdtgvP9kOsN$OxO*Jw0yjC>BES92kuQ0U^|@z@lCZ7^#|#KhJb=8iE) zF@sW%>qwl?0xm`*nMfx^Osdk+7Bo5!t=8a{i4u%!LUde+1G-uo0isF|PM5Av8%d5T zxmX&e!L+1-!a^P_rIK9kfxnSfqw$~(qyii7?Tu(df?0=g6_|lY*DEQLRdZcs>0pT- zLr6lOKoDtTipQl8BwS zDq>Piac~@krGjV)k0*_el0sCOQD7Jt78WgxjFd)(@P&|AFcvE%l<6-0$6`@WY!o(#S$ z)WNg2n3h^rJ++nXck26TG_Rx>X=H-wZdcB{~+|7^Dkmf(-3)s)6{o;u)I zo8LFT*KiuT(AWP(9;3ysgRZ7mC~Q($rn+!S`_Dl9BHnSW>6gx4#j(F%U5K$J#+J_A9V^58qj{D!C^b@a zzEe@&I+)W0FY8%(K5JhIUG7!A+ZG~I&FUFyb;kPjI_g_WlO9NET^IXmf&Gdc;W3|=%Md0?rwfqzNmkm2UsiD=^mofVEWfiVJ4>3{8rANh^a{dKY C;!Mongoose Quick Start v3.3.1Fork me on GitHub